[
  {
    "path": ".gitignore",
    "content": "*.*~\n#*#\n.DS_Store\nThumbs.db\n*.backup\nTools/*.srt\nTools/*.ass\n"
  },
  {
    "path": "Ass/lec10a.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 1691\nVideo Position: 197\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:19.36,0:00:22.65,EN,,0,0,0,,PROFESSOR: Last time, we took a look at\nDialogue: 0,0:00:22.65,0:00:25.67,EN,,0,0,0,,an explicit control evaluator for Lisp\nDialogue: 0,0:00:25.67,0:00:28.97,EN,,0,0,0,,and that bridged the gap between all these high-level languages\nDialogue: 0,0:00:29.05,0:00:32.14,EN,,0,0,0,,like Lisp and query language all that stuff\nDialogue: 0,0:00:32.50,0:00:36.16,EN,,0,0,0,,bridged the gap between that and a conventional register machine.\nDialogue: 0,0:00:36.70,0:00:40.14,EN,,0,0,0,,And in fact, you can think of the explicit control evaluator\nDialogue: 0,0:00:40.16,0:00:44.38,EN,,0,0,0,,either as, say the code for a Lisp interpreter\nDialogue: 0,0:00:44.40,0:00:45.95,EN,,0,0,0,,if you wanted to implement it in the\nDialogue: 0,0:00:46.52,0:00:49.50,EN,,0,0,0,,assembly language of some conventional register transfer machine,\nDialogue: 0,0:00:49.50,0:00:51.50,EN,,0,0,0,,or, if you like, you can think of it as the microcode\nDialogue: 0,0:00:52.08,0:00:54.56,EN,,0,0,0,,of some machine that's going to be specially designed to run Lisp.\nDialogue: 0,0:00:55.20,0:00:55.92,EN,,0,0,0,,In either case,\nDialogue: 0,0:00:55.92,0:00:58.68,EN,,0,0,0,,Nwhat we're doing is we're taking a machine\nDialogue: 0,0:00:58.94,0:01:00.51,EN,,0,0,0,,that speaks some low-level language\nDialogue: 0,0:01:01.42,0:01:03.32,EN,,0,0,0,,and we're raising the machine\nDialogue: 0,0:01:03.37,0:01:04.88,EN,,0,0,0,,to a high-level language like Lisp\nDialogue: 0,0:01:05.36,0:01:06.35,EN,,0,0,0,,by writing an interpreter.\nDialogue: 0,0:01:08.22,0:01:09.58,EN,,0,0,0,,So for instance\nDialogue: 0,0:01:11.82,0:01:13.77,EN,,0,0,0,,here, conceptually,\nDialogue: 0,0:01:18.01,0:01:19.47,EN,,0,0,0,,here conceptually is a\nDialogue: 0,0:01:20.54,0:01:23.44,EN,,0,0,0,,a special purpose machine for computing factorials.\nDialogue: 0,0:01:24.09,0:01:27.39,EN,,0,0,0,,It takes in five and puts out 120.\nDialogue: 0,0:01:28.92,0:01:30.83,EN,,0,0,0,,And what this special purpose machine is\nDialogue: 0,0:01:30.97,0:01:32.72,EN,,0,0,0,,actually a Lisp interpreter\nDialogue: 0,0:01:33.50,0:01:36.17,EN,,0,0,0,,that's configured itself to run factorials\nDialogue: 0,0:01:38.35,0:01:40.99,EN,,0,0,0,,because you feed into it a description of the factorial machine.\nDialogue: 0,0:01:42.12,0:01:43.70,EN,,0,0,0,,So that's what an interpreter is.\nDialogue: 0,0:01:43.70,0:01:45.66,EN,,0,0,0,,It configures itself to\nDialogue: 0,0:01:46.37,0:01:49.24,EN,,0,0,0,,emulate a machine whose description you read in.\nDialogue: 0,0:01:50.07,0:01:51.93,EN,,0,0,0,,Now, inside the Lisp interpreter, what's that?\nDialogue: 0,0:01:52.04,0:01:55.44,EN,,0,0,0,,Well, that might be your general register language interpreter\nDialogue: 0,0:01:56.98,0:02:00.18,EN,,0,0,0,,that configures itself to behave like a Lisp interpreter\nDialogue: 0,0:02:00.18,0:02:02.03,EN,,0,0,0,,because you put in a whole bunch of instructions\nDialogue: 0,0:02:02.12,0:02:03.04,EN,,0,0,0,,in register language.\nDialogue: 0,0:02:03.37,0:02:05.16,EN,,0,0,0,,This is the explicit control evaluator.\nDialogue: 0,0:02:07.05,0:02:08.70,EN,,0,0,0,,And then it also has some sort of library\nDialogue: 0,0:02:08.73,0:02:11.08,EN,,0,0,0,,a library of primitive operators and Lisp operations\nDialogue: 0,0:02:11.12,0:02:12.28,EN,,0,0,0,,all sorts of things like that.\nDialogue: 0,0:02:12.75,0:02:16.89,EN,,0,0,0,,That's the general strategy of interpretation.\nDialogue: 0,0:02:17.32,0:02:18.51,EN,,0,0,0,,And the point is, what we're doing\nDialogue: 0,0:02:18.60,0:02:20.14,EN,,0,0,0,,is we're writing an interpreter\nDialogue: 0,0:02:21.62,0:02:23.40,EN,,0,0,0,,to raise the machine\nDialogue: 0,0:02:23.42,0:02:25.24,EN,,0,0,0,,to the level of the programs that we want to write.\nDialogue: 0,0:02:25.24,0:02:26.72,EN,,0,0,0,,Well, there's another strategy\nDialogue: 0,0:02:27.42,0:02:28.89,EN,,0,0,0,,a different one, which is compilation.\nDialogue: 0,0:02:29.04,0:02:30.43,EN,,0,0,0,,Compilation's a little bit different.\nDialogue: 0,0:02:31.04,0:02:31.50,EN,,0,0,0,,Here--\nDialogue: 0,0:02:33.37,0:02:34.75,EN,,0,0,0,,here we might have produced\nDialogue: 0,0:02:35.67,0:02:38.52,EN,,0,0,0,,a special purpose machine for,\nDialogue: 0,0:02:38.62,0:02:39.98,EN,,0,0,0,,for computing factorials\nDialogue: 0,0:02:43.62,0:02:46.26,EN,,0,0,0,,starting with some sort of machine that speaks register language\nDialogue: 0,0:02:46.26,0:02:47.72,EN,,0,0,0,,except we're going to do a different strategy.\nDialogue: 0,0:02:47.72,0:02:50.38,EN,,0,0,0,,We take our factorial program.\nDialogue: 0,0:02:51.55,0:02:53.92,EN,,0,0,0,,We use that as the source code into a compiler.\nDialogue: 0,0:02:53.92,0:02:55.15,EN,,0,0,0,,What the compiler will do\nDialogue: 0,0:02:55.15,0:02:57.62,EN,,0,0,0,,is translate that factorial program\nDialogue: 0,0:02:57.62,0:02:59.07,EN,,0,0,0,,into some register machine language.\nDialogue: 0,0:03:00.25,0:03:03.40,EN,,0,0,0,,And this will now be not the explicit control evaluator for Lisp\nDialogue: 0,0:03:03.40,0:03:06.17,EN,,0,0,0,,this will be some register language for computing factorials.\nDialogue: 0,0:03:06.49,0:03:08.36,EN,,0,0,0,,So this is the translation of that.\nDialogue: 0,0:03:10.54,0:03:12.41,EN,,0,0,0,,That will go into some sort of loader\nDialogue: 0,0:03:13.35,0:03:15.21,EN,,0,0,0,,which will combine this code\nDialogue: 0,0:03:15.31,0:03:16.84,EN,,0,0,0,,with code selected from the library\nDialogue: 0,0:03:16.86,0:03:18.65,EN,,0,0,0,,to do things like primitive multiplication.\nDialogue: 0,0:03:19.82,0:03:21.69,EN,,0,0,0,,And then we'll produce a load module\nDialogue: 0,0:03:22.22,0:03:25.06,EN,,0,0,0,,which configures the register language machine\nDialogue: 0,0:03:25.06,0:03:27.24,EN,,0,0,0,,to be a special purpose factorial machine.\nDialogue: 0,0:03:28.12,0:03:30.22,EN,,0,0,0,,So that's a, that's a different strategy.\nDialogue: 0,0:03:30.22,0:03:31.22,EN,,0,0,0,,In interpretation,\nDialogue: 0,0:03:31.22,0:03:32.01,EN,,0,0,0,,we're raising\nDialogue: 0,0:03:32.91,0:03:35.23,EN,,0,0,0,,the machine to the level of our language, like Lisp.\nDialogue: 0,0:03:35.32,0:03:36.34,EN,,0,0,0,,In compilation\nDialogue: 0,0:03:36.34,0:03:38.43,EN,,0,0,0,,we're taking our program and lowering\nDialogue: 0,0:03:38.48,0:03:40.56,EN,,0,0,0,,it to the language that's spoken by the machine.\nDialogue: 0,0:03:41.96,0:03:43.84,EN,,0,0,0,,Well, how do these two strategies compare?\nDialogue: 0,0:03:44.30,0:03:49.42,EN,,0,0,0,,The compiler can produce code that will execute more efficiently.\nDialogue: 0,0:03:52.05,0:03:53.90,EN,,0,0,0,,The essential reason for that\nDialogue: 0,0:03:54.17,0:03:58.89,EN,,0,0,0,,is that if you think about the register operations that are running\nDialogue: 0,0:04:01.92,0:04:04.49,EN,,0,0,0,,the interpreter has to produce register operations\nDialogue: 0,0:04:04.97,0:04:06.75,EN,,0,0,0,,which, in principle, are going to be general enough\nDialogue: 0,0:04:07.32,0:04:08.94,EN,,0,0,0,,to execute any Lisp procedure.\nDialogue: 0,0:04:10.22,0:04:12.25,EN,,0,0,0,,Whereas the compiler only has to worry about\nDialogue: 0,0:04:12.27,0:04:14.92,EN,,0,0,0,,producing a special bunch of register operations for\nDialogue: 0,0:04:15.52,0:04:18.22,EN,,0,0,0,,for doing the particular Lisp procedure that you've compiled.\nDialogue: 0,0:04:20.17,0:04:21.20,EN,,0,0,0,,Or another way to say that\nDialogue: 0,0:04:21.20,0:04:25.31,EN,,0,0,0,,is that the interpreter is a general purpose simulator\nDialogue: 0,0:04:25.92,0:04:27.58,EN,,0,0,0,,that when you read in a Lisp procedure\nDialogue: 0,0:04:27.58,0:04:31.32,EN,,0,0,0,,then those can simulate the program described by that, by that procedure.\nDialogue: 0,0:04:31.32,0:04:33.87,EN,,0,0,0,,So the interpreter is worrying about making a general purpose simulator\nDialogue: 0,0:04:34.62,0:04:35.96,EN,,0,0,0,,whereas the compiler, in effect,\nDialogue: 0,0:04:36.00,0:04:37.68,EN,,0,0,0,,is configuring the thing to be the machine\nDialogue: 0,0:04:37.71,0:04:39.34,EN,,0,0,0,,that the interpreter would have been simulating.\nDialogue: 0,0:04:40.02,0:04:41.34,EN,,0,0,0,,So the compiler can be faster.\nDialogue: 0,0:04:52.55,0:04:53.64,EN,,0,0,0,,OK, On the other hand\nDialogue: 0,0:04:55.97,0:04:58.28,EN,,0,0,0,,the interpreter is a nicer environment for debugging.\nDialogue: 0,0:04:59.43,0:05:01.25,EN,,0,0,0,,And the reason for that is that we've got the\nDialogue: 0,0:05:01.57,0:05:03.02,EN,,0,0,0,,the source code actually there.\nDialogue: 0,0:05:03.02,0:05:04.81,EN,,0,0,0,,We're interpreting it That's what we're working with.\nDialogue: 0,0:05:05.87,0:05:07.69,EN,,0,0,0,,And we also have the library around.\nDialogue: 0,0:05:07.90,0:05:10.89,EN,,0,0,0,,See, the interpreter--the library sitting there is part of the interpreter.\nDialogue: 0,0:05:11.30,0:05:13.16,EN,,0,0,0,,The compiler only pulls out from the library\nDialogue: 0,0:05:13.20,0:05:14.56,EN,,0,0,0,,what it needs to run the program.\nDialogue: 0,0:05:14.87,0:05:17.00,EN,,0,0,0,,So if you're in the middle of debugging\nDialogue: 0,0:05:18.00,0:05:20.72,EN,,0,0,0,,and you might like to write a little extra program\nDialogue: 0,0:05:20.80,0:05:22.57,EN,,0,0,0,,to examine some run time data structure\nDialogue: 0,0:05:23.05,0:05:24.25,EN,,0,0,0,,or to produce some computation\nDialogue: 0,0:05:24.30,0:05:25.92,EN,,0,0,0,,that you didn't think of when you wrote the program\nDialogue: 0,0:05:25.95,0:05:27.53,EN,,0,0,0,,the interpreter can do that perfectly well\nDialogue: 0,0:05:28.05,0:05:29.21,EN,,0,0,0,,whereas the compiler can't.\nDialogue: 0,0:05:29.62,0:05:31.90,EN,,0,0,0,,So there are sort of dual, dual advantages.\nDialogue: 0,0:05:31.90,0:05:34.48,EN,,0,0,0,,The compiler will produce code that executes faster.\nDialogue: 0,0:05:34.85,0:05:37.02,EN,,0,0,0,,The interpreter is a better environment for debugging.\nDialogue: 0,0:05:38.95,0:05:41.40,EN,,0,0,0,,And most Lisp systems end up having both\nDialogue: 0,0:05:42.92,0:05:45.23,EN,,0,0,0,,end up being configured so you have an interpreter\nDialogue: 0,0:05:45.24,0:05:47.08,EN,,0,0,0,,that you use when you're developing your code.\nDialogue: 0,0:05:47.08,0:05:48.62,EN,,0,0,0,,Then you can speed it up by compiling.\nDialogue: 0,0:05:49.02,0:05:50.03,EN,,0,0,0,,And very often,\nDialogue: 0,0:05:50.04,0:05:51.68,EN,,0,0,0,,you can arrange that compiled code\nDialogue: 0,0:05:51.69,0:05:53.56,EN,,0,0,0,,and interpreted code can call each other.\nDialogue: 0,0:05:54.60,0:05:56.33,EN,,0,0,0,,We'll see how to do that, That's not hard.\nDialogue: 0,0:05:59.27,0:05:59.85,EN,,0,0,0,,OK\nDialogue: 0,0:06:00.97,0:06:02.09,EN,,0,0,0,,In fact, the way we'll--\nDialogue: 0,0:06:04.30,0:06:05.75,EN,,0,0,0,,in the compiler we're going to make\nDialogue: 0,0:06:05.75,0:06:07.58,EN,,0,0,0,,the way we'll arrange for compiled coding\nDialogue: 0,0:06:07.58,0:06:09.45,EN,,0,0,0,,and interpreted code to call to call each other\nDialogue: 0,0:06:09.90,0:06:12.06,EN,,0,0,0,,is that we'll have the compiler use exactly\nDialogue: 0,0:06:12.11,0:06:14.40,EN,,0,0,0,,the same register conventions as the interpreter.\nDialogue: 0,0:06:18.42,0:06:21.72,EN,,0,0,0,,Well, the idea of a compiler\nDialogue: 0,0:06:21.76,0:06:25.74,EN,,0,0,0,,is very much like the idea of an interpreter or evaluator.\nDialogue: 0,0:06:25.87,0:06:26.46,EN,,0,0,0,,It's the same thing.\nDialogue: 0,0:06:27.05,0:06:29.39,EN,,0,0,0,,See, the evaluator walks over the code\nDialogue: 0,0:06:29.82,0:06:32.35,EN,,0,0,0,,and performs some register operations.\nDialogue: 0,0:06:33.65,0:06:34.97,EN,,0,0,0,,That's what we did yesterday.\nDialogue: 0,0:06:37.10,0:06:40.27,EN,,0,0,0,,Well, the compiler essentially would like to walk over the code\nDialogue: 0,0:06:40.52,0:06:43.00,EN,,0,0,0,,and produce the register operations\nDialogue: 0,0:06:43.04,0:06:44.67,EN,,0,0,0,,that the evaluator would have done\nDialogue: 0,0:06:45.23,0:06:46.64,EN,,0,0,0,,were it evaluating the thing.\nDialogue: 0,0:06:48.60,0:06:49.95,EN,,0,0,0,,And that gives us some model\nDialogue: 0,0:06:50.60,0:06:53.77,EN,,0,0,0,,for how to implement a zeroth-order compiler\nDialogue: 0,0:06:55.30,0:06:58.32,EN,,0,0,0,,a very bad compiler but essentially a compiler.\nDialogue: 0,0:06:58.32,0:06:59.32,EN,,0,0,0,,A model for doing that\nDialogue: 0,0:06:59.36,0:07:00.59,EN,,0,0,0,,is you just take the evaluator,\nDialogue: 0,0:07:00.68,0:07:01.88,EN,,0,0,0,,you run it over the code\nDialogue: 0,0:07:02.80,0:07:06.06,EN,,0,0,0,,but instead of executing the actual operations\nDialogue: 0,0:07:06.06,0:07:07.15,EN,,0,0,0,,you just save them away.\nDialogue: 0,0:07:07.55,0:07:08.82,EN,,0,0,0,,And that's your compiled code.\nDialogue: 0,0:07:08.82,0:07:10.24,EN,,0,0,0,,So let me give you an example of that.\nDialogue: 0,0:07:12.70,0:07:14.14,EN,,0,0,0,,Suppose we're going to compile--\nDialogue: 0,0:07:15.10,0:07:17.90,EN,,0,0,0,,Suppose we want to compile the expression f of x.\nDialogue: 0,0:07:25.07,0:07:25.96,EN,,0,0,0,,So let's assume that\nDialogue: 0,0:07:25.96,0:07:28.06,EN,,0,0,0,,we've got f of x in the exp register\nDialogue: 0,0:07:28.06,0:07:29.55,EN,,0,0,0,,and something in the environment register.\nDialogue: 0,0:07:30.10,0:07:32.20,EN,,0,0,0,,And now imagine starting up the evaluator.\nDialogue: 0,0:07:34.60,0:07:35.71,EN,,0,0,0,,Well, it looks at the expression\nDialogue: 0,0:07:35.71,0:07:37.36,EN,,0,0,0,,and it sees that it's an application.\nDialogue: 0,0:07:37.92,0:07:41.90,EN,,0,0,0,,And it branches to a place in the\nDialogue: 0,0:07:42.52,0:07:45.15,EN,,0,0,0,,in the evaluator code we saw called ev-application.\nDialogue: 0,0:07:47.12,0:07:48.12,EN,,0,0,0,,And then it begins.\nDialogue: 0,0:07:48.16,0:07:50.08,EN,,0,0,0,,It stores away the operands and unev\nDialogue: 0,0:07:50.08,0:07:52.44,EN,,0,0,0,,and then it's going to put the operator in exp,\nDialogue: 0,0:07:52.48,0:07:54.27,EN,,0,0,0,,and it's going to go recursively evaluate it.\nDialogue: 0,0:07:54.47,0:07:56.08,EN,,0,0,0,,That's the process that we walk through.\nDialogue: 0,0:07:56.67,0:07:57.84,EN,,0,0,0,,And if you start looking at the code,\nDialogue: 0,0:07:57.87,0:07:59.74,EN,,0,0,0,,you start seeing some register operations.\nDialogue: 0,0:08:00.20,0:08:02.30,EN,,0,0,0,,You see assign to unev the operands\nDialogue: 0,0:08:02.30,0:08:03.95,EN,,0,0,0,,assign to exp the operator,\nDialogue: 0,0:08:04.09,0:08:06.20,EN,,0,0,0,,save the environment, generate that, and so on.\nDialogue: 0,0:08:10.22,0:08:11.93,EN,,0,0,0,,Well, if we look on the overhead here\nDialogue: 0,0:08:15.75,0:08:19.58,EN,,0,0,0,,we can see those operations starting to be produced.\nDialogue: 0,0:08:20.82,0:08:22.52,EN,,0,0,0,,Here's sort of the first real operation\nDialogue: 0,0:08:22.72,0:08:24.80,EN,,0,0,0,,that the evaluator would have done.\nDialogue: 0,0:08:25.00,0:08:27.20,EN,,0,0,0,,It pulls the operands out of the exp register\nDialogue: 0,0:08:27.47,0:08:28.62,EN,,0,0,0,,and assigns it to unev.\nDialogue: 0,0:08:30.03,0:08:32.27,EN,,0,0,0,,And then it assigns something to the expression register,\nDialogue: 0,0:08:32.30,0:08:33.46,EN,,0,0,0,,and it saves continue\nDialogue: 0,0:08:33.46,0:08:34.62,EN,,0,0,0,,and it saves env.\nDialogue: 0,0:08:34.62,0:08:38.65,EN,,0,0,0,,And all I'm doing here is writing down the register assignments\nDialogue: 0,0:08:39.57,0:08:42.32,EN,,0,0,0,,that the evaluator would have done in executing that code.\nDialogue: 0,0:08:42.77,0:08:43.79,EN,,0,0,0,,And can zoom out a little bit.\nDialogue: 0,0:08:44.30,0:08:47.13,EN,,0,0,0,,Altogether, there are about 19 operations there.\nDialogue: 0,0:08:49.40,0:08:51.64,EN,,0,0,0,,And this is the--this will be the piece of code\nDialogue: 0,0:08:52.05,0:08:53.90,EN,,0,0,0,,up until the point where\nDialogue: 0,0:08:54.75,0:08:57.10,EN,,0,0,0,,the evaluator branches off to apply-dispatch.\nDialogue: 0,0:08:57.86,0:08:59.16,EN,,0,0,0,,And in fact, in this compiler\nDialogue: 0,0:08:59.20,0:09:01.18,EN,,0,0,0,,we're not going to worry about apply-dispatch at all.\nDialogue: 0,0:09:01.30,0:09:02.11,EN,,0,0,0,,We're going to have everything\nDialogue: 0,0:09:02.35,0:09:05.04,EN,,0,0,0,,we're going to have both interpreted code and compiled code.\nDialogue: 0,0:09:06.07,0:09:07.61,EN,,0,0,0,,Always evaluate procedures,\nDialogue: 0,0:09:07.61,0:09:09.85,EN,,0,0,0,,always apply procedures by going to apply-dispatch.\nDialogue: 0,0:09:10.27,0:09:12.32,EN,,0,0,0,,That will easily allow interpreted code and\nDialogue: 0,0:09:12.36,0:09:13.71,EN,,0,0,0,,compiled code to call each other.\nDialogue: 0,0:09:18.27,0:09:19.87,EN,,0,0,0,,Well, in principle, that's all we need to do.\nDialogue: 0,0:09:21.05,0:09:22.66,EN,,0,0,0,,You just run the evaluator.\nDialogue: 0,0:09:22.66,0:09:24.50,EN,,0,0,0,,So the compiler's a lot like the evaluator.\nDialogue: 0,0:09:24.50,0:09:26.47,EN,,0,0,0,,You run it, except it stashes away these operations\nDialogue: 0,0:09:26.47,0:09:28.40,EN,,0,0,0,,instead of actually executing them.\nDialogue: 0,0:09:29.35,0:09:31.39,EN,,0,0,0,,Well, that's not, that's not quite true. there's\nDialogue: 0,0:09:32.91,0:09:34.99,EN,,0,0,0,,There's only one little lie in that.\nDialogue: 0,0:09:36.24,0:09:39.29,EN,,0,0,0,,What you have to worry about is if you have a, a predicate.\nDialogue: 0,0:09:40.12,0:09:42.16,EN,,0,0,0,,If you have some kind of test you want to do\nDialogue: 0,0:09:43.45,0:09:46.03,EN,,0,0,0,,obviously, at the point when you're compiling it\nDialogue: 0,0:09:46.52,0:09:47.98,EN,,0,0,0,,you don't know which branch of these--\nDialogue: 0,0:09:48.32,0:09:50.14,EN,,0,0,0,,of a conditional like this you're going to do.\nDialogue: 0,0:09:51.13,0:09:53.92,EN,,0,0,0,,So you can't say which one the evaluator would have done.\nDialogue: 0,0:09:54.90,0:09:57.12,EN,,0,0,0,,So all you do there is very simple.\nDialogue: 0,0:09:57.12,0:09:58.49,EN,,0,0,0,,You compile both branches.\nDialogue: 0,0:09:59.32,0:10:01.29,EN,,0,0,0,,So you compile a structure that looks like this.\nDialogue: 0,0:10:02.00,0:10:03.98,EN,,0,0,0,,That'll compile into something that says,\nDialogue: 0,0:10:05.31,0:10:09.15,EN,,0,0,0,,the code, the code for P.\nDialogue: 0,0:10:10.71,0:10:16.51,EN,,0,0,0,,And it puts its results in, say, the val register.\nDialogue: 0,0:10:18.17,0:10:20.64,EN,,0,0,0,,So you walk the interpreter over the predicate\nDialogue: 0,0:10:21.35,0:10:24.19,EN,,0,0,0,,and make sure that the result would go into the val register.\nDialogue: 0,0:10:24.70,0:10:27.22,EN,,0,0,0,,And then you compile an instruction that says\nDialogue: 0,0:10:27.22,0:10:33.79,EN,,0,0,0,,branch if, if val is true\nDialogue: 0,0:10:37.17,0:10:38.75,EN,,0,0,0,,to a place we'll call label one.\nDialogue: 0,0:10:44.97,0:10:47.52,EN,,0,0,0,,Then we, we will put the code for B\nDialogue: 0,0:10:49.42,0:10:52.32,EN,,0,0,0,,to walk the interpreter--walk the interpreter over B.\nDialogue: 0,0:10:53.62,0:10:57.21,EN,,0,0,0,,And then go to put in an instruction that says,\nDialogue: 0,0:10:57.23,0:10:58.75,EN,,0,0,0,,go to the next thing, whatever\nDialogue: 0,0:11:02.20,0:11:04.56,EN,,0,0,0,,whatever was supposed to happen after this thing was done.\nDialogue: 0,0:11:04.95,0:11:06.09,EN,,0,0,0,,You put in that instruction.\nDialogue: 0,0:11:06.88,0:11:08.62,EN,,0,0,0,,And here you put label one.\nDialogue: 0,0:11:12.12,0:11:13.80,EN,,0,0,0,,And here you put the code for A.\nDialogue: 0,0:11:19.47,0:11:25.85,EN,,0,0,0,,And you put go to next thing.\nDialogue: 0,0:11:31.42,0:11:32.88,EN,,0,0,0,,So that's how you treat a conditional.\nDialogue: 0,0:11:32.98,0:11:34.65,EN,,0,0,0,,You generate a little block like that.\nDialogue: 0,0:11:35.75,0:11:38.12,EN,,0,0,0,,And other than that\nDialogue: 0,0:11:38.95,0:11:41.55,EN,,0,0,0,,this zeroth-order compiler is the same as the evaluator.\nDialogue: 0,0:11:42.55,0:11:45.12,EN,,0,0,0,,It's just stashing away the instructions instead of executing them.\nDialogue: 0,0:11:46.55,0:11:47.60,EN,,0,0,0,,That seems pretty simple,\nDialogue: 0,0:11:47.64,0:11:49.08,EN,,0,0,0,,but we've gained something by that.\nDialogue: 0,0:11:50.12,0:11:52.62,EN,,0,0,0,,See, already that's going to be more efficient than the evaluator.\nDialogue: 0,0:11:53.52,0:11:56.14,EN,,0,0,0,,Because, if you watch the evaluator run\nDialogue: 0,0:11:56.35,0:12:01.05,EN,,0,0,0,,it's not only generating the register operations we wrote down\nDialogue: 0,0:12:01.27,0:12:03.50,EN,,0,0,0,,it's also doing things to decide which ones to generate.\nDialogue: 0,0:12:04.70,0:12:07.23,EN,,0,0,0,,So the very first thing it does, say here\nDialogue: 0,0:12:07.92,0:12:09.77,EN,,0,0,0,,here for instance, is go do some tests\nDialogue: 0,0:12:09.77,0:12:11.56,EN,,0,0,0,,and decide that this is an application\nDialogue: 0,0:12:13.57,0:12:15.05,EN,,0,0,0,,and then branch off to the place that,\nDialogue: 0,0:12:15.39,0:12:16.62,EN,,0,0,0,,that handles applications.\nDialogue: 0,0:12:16.62,0:12:18.44,EN,,0,0,0,,In other words, what the evaluator's doing\nDialogue: 0,0:12:18.62,0:12:22.76,EN,,0,0,0,,is simultaneously analyzing the code to see what to do\nDialogue: 0,0:12:23.47,0:12:24.99,EN,,0,0,0,,and running these operations.\nDialogue: 0,0:12:25.55,0:12:28.28,EN,,0,0,0,,And when you-- if you run the evaluator a million times\nDialogue: 0,0:12:28.28,0:12:30.30,EN,,0,0,0,,that analysis phase happens a million times\nDialogue: 0,0:12:30.85,0:12:32.58,EN,,0,0,0,,whereas in the compiler, it's happened once\nDialogue: 0,0:12:32.58,0:12:34.81,EN,,0,0,0,,and then you just have the register operations themselves.\nDialogue: 0,0:12:39.20,0:12:41.68,EN,,0,0,0,,Ok, that's a, a zeroth-order compiler\nDialogue: 0,0:12:41.80,0:12:44.04,EN,,0,0,0,,but it is a wretched, wretched compiler.\nDialogue: 0,0:12:44.45,0:12:45.28,EN,,0,0,0,,It's really dumb.\nDialogue: 0,0:12:46.90,0:12:48.41,EN,,0,0,0,,Let's--let's go back and,\nDialogue: 0,0:12:49.88,0:12:50.97,EN,,0,0,0,,and look at this overhead.\nDialogue: 0,0:12:52.02,0:12:55.29,EN,,0,0,0,,So look at look at some of the operations this thing is doing.\nDialogue: 0,0:12:55.85,0:12:56.88,EN,,0,0,0,,We're supposedly\nDialogue: 0,0:12:59.72,0:13:02.28,EN,,0,0,0,,looking at the operations in interpreting f of x.\nDialogue: 0,0:13:03.52,0:13:04.84,EN,,0,0,0,,Now, look here what it's doing.\nDialogue: 0,0:13:05.17,0:13:06.11,EN,,0,0,0,,For example, here\nDialogue: 0,0:13:07.15,0:13:11.98,EN,,0,0,0,,it assigns to exp the operator in fetch of exp.\nDialogue: 0,0:13:13.75,0:13:15.87,EN,,0,0,0,,But see, there's no reason to do that, because this is--\nDialogue: 0,0:13:16.22,0:13:17.47,EN,,0,0,0,,the compiler knows\nDialogue: 0,0:13:17.66,0:13:21.84,EN,,0,0,0,,that the operator, fetch of exp,  is f right here.\nDialogue: 0,0:13:23.35,0:13:25.56,EN,,0,0,0,,So there's no reason why this instruction should say that.\nDialogue: 0,0:13:25.70,0:13:28.88,EN,,0,0,0,,It should say, we'll assign to exp, f.\nDialogue: 0,0:13:29.45,0:13:31.08,EN,,0,0,0,,Or in fact, you don't need exp at all.\nDialogue: 0,0:13:31.87,0:13:33.56,EN,,0,0,0,,There's no reason it should have exp at all.\nDialogue: 0,0:13:33.56,0:13:35.16,EN,,0,0,0,,What, what did exp get used for?\nDialogue: 0,0:13:35.18,0:13:36.33,EN,,0,0,0,,Well, if we come down here\nDialogue: 0,0:13:40.77,0:13:42.20,EN,,0,0,0,,we're going to assign to val\nDialogue: 0,0:13:43.05,0:13:47.34,EN,,0,0,0,,look up the stuff in exp in the environment.\nDialogue: 0,0:13:48.68,0:13:49.53,EN,,0,0,0,,So what we really should do\nDialogue: 0,0:13:49.55,0:13:51.54,EN,,0,0,0,,get rid of the exp register altogether\nDialogue: 0,0:13:51.54,0:13:53.32,EN,,0,0,0,,and just change this instruction to say,\nDialogue: 0,0:13:53.34,0:13:54.16,EN,,0,0,0,,assign to val\nDialogue: 0,0:13:54.45,0:13:56.06,EN,,0,0,0,,look up the variable value\nDialogue: 0,0:13:56.36,0:13:58.40,EN,,0,0,0,,of the symbol f in the environment.\nDialogue: 0,0:14:01.09,0:14:01.77,EN,,0,0,0,,Similarly\nDialogue: 0,0:14:02.57,0:14:04.27,EN,,0,0,0,,back up here, we don't need unev at all\nDialogue: 0,0:14:04.72,0:14:05.79,EN,,0,0,0,,because we know\nDialogue: 0,0:14:06.22,0:14:09.16,EN,,0,0,0,,what the operands of fetch of exp are for this piece of code.\nDialogue: 0,0:14:09.16,0:14:10.62,EN,,0,0,0,,It's the, it's the list x.\nDialogue: 0,0:14:13.25,0:14:14.06,EN,,0,0,0,,So in some sense\nDialogue: 0,0:14:16.17,0:14:19.39,EN,,0,0,0,,you don't want unev and exp at all.\nDialogue: 0,0:14:19.67,0:14:21.05,EN,,0,0,0,,See, what they really are in some sense,\nDialogue: 0,0:14:21.08,0:14:25.30,EN,,0,0,0,,those aren't registers of the actual machine that's supposed to run.\nDialogue: 0,0:14:25.30,0:14:26.40,EN,,0,0,0,,Those are registers\nDialogue: 0,0:14:26.60,0:14:29.50,EN,,0,0,0,,that have to do with arranging the thing that can simulate that machine.\nDialogue: 0,0:14:30.72,0:14:33.77,EN,,0,0,0,,So they're always going to hold expressions\nDialogue: 0,0:14:34.00,0:14:36.04,EN,,0,0,0,,which from the compiler's point of view,\nDialogue: 0,0:14:36.06,0:14:36.81,EN,,0,0,0,,are just constants,\nDialogue: 0,0:14:36.95,0:14:38.48,EN,,0,0,0,,so can be put right into the code.\nDialogue: 0,0:14:39.47,0:14:41.34,EN,,0,0,0,,So you can forget about all the operations\nDialogue: 0,0:14:41.36,0:14:42.54,EN,,0,0,0,,worrying about exp and unev\nDialogue: 0,0:14:42.57,0:14:43.77,EN,,0,0,0,,and just use those constants.\nDialogue: 0,0:14:44.02,0:14:48.00,EN,,0,0,0,,Similarly, again, if we go, go back and look here\nDialogue: 0,0:14:48.00,0:14:51.32,EN,,0,0,0,,there are things like assign to continue eval-args.\nDialogue: 0,0:14:53.75,0:14:55.39,EN,,0,0,0,,Now, that has nothing to do with anything.\nDialogue: 0,0:14:55.62,0:14:57.76,EN,,0,0,0,,That was just the evaluator\nDialogue: 0,0:14:58.08,0:15:00.17,EN,,0,0,0,,keeping track of where it should go next\nDialogue: 0,0:15:02.70,0:15:05.96,EN,,0,0,0,,to evaluate the arguments in some, in some application.\nDialogue: 0,0:15:06.82,0:15:08.65,EN,,0,0,0,,But of course, that's irrelevant to the compiler,\nDialogue: 0,0:15:08.65,0:15:13.88,EN,,0,0,0,,because you-- the analysis phase will have already done that.\nDialogue: 0,0:15:15.05,0:15:16.83,EN,,0,0,0,,So this is completely irrelevant.\nDialogue: 0,0:15:17.70,0:15:19.32,EN,,0,0,0,,So a lot of these, these assignments\nDialogue: 0,0:15:19.32,0:15:21.30,EN,,0,0,0,,to continue have not to do\nDialogue: 0,0:15:21.30,0:15:24.62,EN,,0,0,0,,where the running machine is supposed to continue\nDialogue: 0,0:15:24.64,0:15:25.77,EN,,0,0,0,,in keeping track of its state.\nDialogue: 0,0:15:26.07,0:15:28.72,EN,,0,0,0,,It has to, to do with where the evaluator analysis should continue\nDialogue: 0,0:15:28.72,0:15:30.03,EN,,0,0,0,,and those are completely irrelevant.\nDialogue: 0,0:15:30.06,0:15:31.23,EN,,0,0,0,,So we can get rid of them.\nDialogue: 0,0:15:43.90,0:15:45.98,EN,,0,0,0,,Ok, well, if we, if we simply do that,\nDialogue: 0,0:15:46.16,0:15:47.75,EN,,0,0,0,,make those kinds of optimizations\nDialogue: 0,0:15:47.75,0:15:51.64,EN,,0,0,0,,get rid, get rid of worrying about exp and unev\nDialogue: 0,0:15:51.75,0:15:56.22,EN,,0,0,0,,and get rid of these irrelevant register assignments to continue\nDialogue: 0,0:15:57.25,0:15:59.96,EN,,0,0,0,,then we can take this literal code\nDialogue: 0,0:16:01.48,0:16:06.20,EN,,0,0,0,,these sort of 19 instructions that the evaluator would have done\nDialogue: 0,0:16:06.91,0:16:08.12,EN,,0,0,0,,and then replace them.\nDialogue: 0,0:16:08.36,0:16:10.33,EN,,0,0,0,,Let's look at the, at the slide.\nDialogue: 0,0:16:12.27,0:16:15.34,EN,,0,0,0,,Replace them by--we get rid of about half of them.\nDialogue: 0,0:16:18.28,0:16:20.75,EN,,0,0,0,,And again, this is just sort of filtering\nDialogue: 0,0:16:21.07,0:16:24.46,EN,,0,0,0,,what the evaluator would have done by getting rid of the irrelevant stuff.\nDialogue: 0,0:16:25.17,0:16:26.22,EN,,0,0,0,,And you see, for instance\nDialogue: 0,0:16:27.47,0:16:29.66,EN,,0,0,0,,here the--where the evaluator said,\nDialogue: 0,0:16:29.68,0:16:32.43,EN,,0,0,0,,assign val, look up variable value, fetch of exp\nDialogue: 0,0:16:32.46,0:16:34.22,EN,,0,0,0,,here we have put in the constant f.\nDialogue: 0,0:16:35.44,0:16:37.02,EN,,0,0,0,,Here we've put in the constant x.\nDialogue: 0,0:16:40.02,0:16:42.41,EN,,0,0,0,,So there's a, there's a little better compiler.\nDialogue: 0,0:16:43.79,0:16:46.76,EN,,0,0,0,,It's still pretty dumb.\nDialogue: 0,0:16:47.95,0:16:49.58,EN,,0,0,0,,It's still doing a lot of dumb things.\nDialogue: 0,0:16:50.45,0:16:52.52,EN,,0,0,0,,Again, if we go look at the slide again\nDialogue: 0,0:16:52.88,0:16:53.93,EN,,0,0,0,,look at the very beginning here\nDialogue: 0,0:16:56.34,0:16:58.17,EN,,0,0,0,,we see a save the environment\nDialogue: 0,0:16:59.35,0:17:01.72,EN,,0,0,0,,assign something to the val register\nDialogue: 0,0:17:01.80,0:17:03.35,EN,,0,0,0,,and restore the environment.\nDialogue: 0,0:17:03.35,0:17:04.41,EN,,0,0,0,,Where'd that come from?\nDialogue: 0,0:17:04.91,0:17:07.10,EN,,0,0,0,,That came from the evaluator back here saying\nDialogue: 0,0:17:07.15,0:17:10.28,EN,,0,0,0,,oh, I'm in the middle of evaluating an application.\nDialogue: 0,0:17:11.10,0:17:14.68,EN,,0,0,0,,So I'm going to recursively call eval dispatch.\nDialogue: 0,0:17:15.87,0:17:17.98,EN,,0,0,0,,So I'd better save the thing I'm going to need later,\nDialogue: 0,0:17:17.98,0:17:19.08,EN,,0,0,0,,which is the environment.\nDialogue: 0,0:17:19.77,0:17:22.86,EN,,0,0,0,,This was the result of recursively calling eval dispatch.\nDialogue: 0,0:17:23.47,0:17:25.77,EN,,0,0,0,,It was evaluating the symbol f in that case.\nDialogue: 0,0:17:26.50,0:17:28.27,EN,,0,0,0,,Then it came back from eval dispatch,\nDialogue: 0,0:17:28.28,0:17:29.66,EN,,0,0,0,,restored the environment.\nDialogue: 0,0:17:31.25,0:17:32.28,EN,,0,0,0,,But in fact,\nDialogue: 0,0:17:32.59,0:17:35.88,EN,,0,0,0,,the actual thing it ended up doing in the evaluation\nDialogue: 0,0:17:35.92,0:17:37.71,EN,,0,0,0,,is not going to hurt the environment at all.\nDialogue: 0,0:17:38.67,0:17:40.80,EN,,0,0,0,,So there's no reason to be saving the environment\nDialogue: 0,0:17:40.84,0:17:42.22,EN,,0,0,0,,and restoring the environment here.\nDialogue: 0,0:17:45.67,0:17:46.62,EN,,0,0,0,,Similarly\nDialogue: 0,0:17:49.79,0:17:51.39,EN,,0,0,0,,here I'm saving the argument list.\nDialogue: 0,0:17:53.07,0:17:55.80,EN,,0,0,0,,That's a piece of the argument evaluation loop,\nDialogue: 0,0:17:55.82,0:17:56.86,EN,,0,0,0,,saving the argument list\nDialogue: 0,0:17:57.20,0:17:58.03,EN,,0,0,0,,and here you restore it.\nDialogue: 0,0:17:58.08,0:18:00.51,EN,,0,0,0,,But the actual thing that you ended up doing\nDialogue: 0,0:18:00.80,0:18:02.28,EN,,0,0,0,,didn't trash the argument list.\nDialogue: 0,0:18:02.84,0:18:04.17,EN,,0,0,0,,So there was no reason to save it.\nDialogue: 0,0:18:08.65,0:18:12.88,EN,,0,0,0,,So another way to say, another way to say that\nDialogue: 0,0:18:13.77,0:18:14.80,EN,,0,0,0,,is that the,\nDialogue: 0,0:18:16.43,0:18:19.13,EN,,0,0,0,,the evaluator has to be maximally pessimistic\nDialogue: 0,0:18:19.87,0:18:21.07,EN,,0,0,0,,because as far from its point of view\nDialogue: 0,0:18:21.08,0:18:23.06,EN,,0,0,0,,it's just going off to evaluate something.\nDialogue: 0,0:18:23.24,0:18:24.97,EN,,0,0,0,,So it better save what it's going to need later.\nDialogue: 0,0:18:26.12,0:18:27.79,EN,,0,0,0,,But once you've done the analysis,\nDialogue: 0,0:18:27.82,0:18:29.68,EN,,0,0,0,,the compiler is in a position to say\nDialogue: 0,0:18:29.72,0:18:31.47,EN,,0,0,0,,well, what actually did I need to save?\nDialogue: 0,0:18:32.12,0:18:33.31,EN,,0,0,0,,And doesn't need to do any--\nDialogue: 0,0:18:33.42,0:18:37.30,EN,,0,0,0,,it doesn't need to be as careful as the evaluator\nDialogue: 0,0:18:37.30,0:18:38.80,EN,,0,0,0,,because it knows what it actually needs\nDialogue: 0,0:18:39.69,0:18:41.16,EN,,0,0,0,,Well, in any case, if we do that\nDialogue: 0,0:18:42.50,0:18:45.71,EN,,0,0,0,,and eliminate all those redundant saves and restores\nDialogue: 0,0:18:46.40,0:18:49.05,EN,,0,0,0,,then we can get it down to this.\nDialogue: 0,0:18:49.90,0:18:51.53,EN,,0,0,0,,And you see there are actually only three\nDialogue: 0,0:18:51.64,0:18:53.71,EN,,0,0,0,,only three instructions that we actually need\nDialogue: 0,0:18:54.07,0:18:55.72,EN,,0,0,0,,down from the initial 11 or so\nDialogue: 0,0:18:55.97,0:18:58.81,EN,,0,0,0,,or the initial 20 or so in the original one.\nDialogue: 0,0:18:59.87,0:19:00.92,EN,,0,0,0,,And that's just saying,\nDialogue: 0,0:19:01.12,0:19:03.18,EN,,0,0,0,,of those register operations\nDialogue: 0,0:19:03.27,0:19:04.94,EN,,0,0,0,,which ones did we actually need?\nDialogue: 0,0:19:09.42,0:19:11.74,EN,,0,0,0,,Let me just sort of summarize that in another way,\nDialogue: 0,0:19:11.74,0:19:13.48,EN,,0,0,0,,just to show you in a little better picture.\nDialogue: 0,0:19:16.00,0:19:17.52,EN,,0,0,0,,Here's a picture of starting--\nDialogue: 0,0:19:18.77,0:19:20.81,EN,,0,0,0,,This is looking at all the saves and restores.\nDialogue: 0,0:19:23.50,0:19:25.23,EN,,0,0,0,,So here's the expression, f of x\nDialogue: 0,0:19:25.32,0:19:27.87,EN,,0,0,0,,and then this traces through, on the bottom here\nDialogue: 0,0:19:28.75,0:19:31.80,EN,,0,0,0,,the various places in the evaluator\nDialogue: 0,0:19:34.97,0:19:38.04,EN,,0,0,0,,that were passed when the evaluation happened.\nDialogue: 0,0:19:38.04,0:19:40.01,EN,,0,0,0,,And then here, here you see arrows.\nDialogue: 0,0:19:40.22,0:19:42.08,EN,,0,0,0,,Arrow down means register saved.\nDialogue: 0,0:19:42.40,0:19:44.84,EN,,0,0,0,,So the first thing that happened is the environment got saved.\nDialogue: 0,0:19:46.82,0:19:48.68,EN,,0,0,0,,And over here, the environment got restored.\nDialogue: 0,0:19:52.38,0:19:54.54,EN,,0,0,0,,so there are all the pairs of stack operations.\nDialogue: 0,0:19:56.12,0:19:57.56,EN,,0,0,0,,Now, if you go ahead and say\nDialogue: 0,0:19:58.12,0:20:00.78,EN,,0,0,0,,well, let's remember that we don't--that unev\nDialogue: 0,0:20:00.89,0:20:03.02,EN,,0,0,0,,for instance, is a completely useless register.\nDialogue: 0,0:20:07.80,0:20:09.78,EN,,0,0,0,,And if we use the constant structure of the code\nDialogue: 0,0:20:09.78,0:20:12.52,EN,,0,0,0,,well, we don't need, we don't need to save unev.\nDialogue: 0,0:20:16.20,0:20:19.15,EN,,0,0,0,,And then, depending on how we set up the discipline of the--\nDialogue: 0,0:20:19.16,0:20:21.88,EN,,0,0,0,,of calling other things that apply,\nDialogue: 0,0:20:21.88,0:20:23.85,EN,,0,0,0,,we may or may not need to save continue.\nDialogue: 0,0:20:27.40,0:20:28.74,EN,,0,0,0,,That's the first step I did.\nDialogue: 0,0:20:28.74,0:20:30.51,EN,,0,0,0,,And then we can look and see what's actually,\nDialogue: 0,0:20:31.71,0:20:32.70,EN,,0,0,0,,what's actually needed.\nDialogue: 0,0:20:33.07,0:20:35.56,EN,,0,0,0,,See, we don't-- didn't really need to save env\nDialogue: 0,0:20:36.04,0:20:37.82,EN,,0,0,0,,across-evaluating f\nDialogue: 0,0:20:38.08,0:20:39.92,EN,,0,0,0,,because it wouldn't, it wouldn't trash it.\nDialogue: 0,0:20:39.92,0:20:41.31,EN,,0,0,0,,So if we take advantage of that\nDialogue: 0,0:20:44.12,0:20:47.56,EN,,0,0,0,,and see the evaluation of f here\nDialogue: 0,0:20:48.57,0:20:50.44,EN,,0,0,0,,doesn't really need to worry about,\nDialogue: 0,0:20:51.61,0:20:52.60,EN,,0,0,0,,about hurting env.\nDialogue: 0,0:20:52.60,0:20:54.94,EN,,0,0,0,,And similarly, the evaluation of x here\nDialogue: 0,0:20:57.17,0:20:58.89,EN,,0,0,0,,when the evaluator did that it said\nDialogue: 0,0:20:58.91,0:21:01.64,EN,,0,0,0,,Oh, I'd better preserve the function register around that\nDialogue: 0,0:21:02.07,0:21:03.22,EN,,0,0,0,,because I might need it later.\nDialogue: 0,0:21:03.28,0:21:04.89,EN,,0,0,0,,And I better preserve the argument list.\nDialogue: 0,0:21:06.90,0:21:09.05,EN,,0,0,0,,Whereas the compiler is now in a position to know\nDialogue: 0,0:21:09.05,0:21:10.38,EN,,0,0,0,,well, we didn't really need to save--\nDialogue: 0,0:21:10.52,0:21:11.84,EN,,0,0,0,,to do those saves and restores.\nDialogue: 0,0:21:12.70,0:21:16.09,EN,,0,0,0,,So in fact, all of the stack operations done by the evaluator\nDialogue: 0,0:21:16.32,0:21:19.58,EN,,0,0,0,,turned out to be unnecessary or overly pessimistic.\nDialogue: 0,0:21:19.62,0:21:21.45,EN,,0,0,0,,And the compiler is in a position to know that.\nDialogue: 0,0:21:27.35,0:21:28.48,EN,,0,0,0,,Well that's the basic idea.\nDialogue: 0,0:21:29.80,0:21:31.00,EN,,0,0,0,,We take the evaluator\nDialogue: 0,0:21:31.00,0:21:33.24,EN,,0,0,0,,we eliminate the things that you don't need\nDialogue: 0,0:21:33.24,0:21:35.24,EN,,0,0,0,,that in some sense have nothing to do with the compiler at all\nDialogue: 0,0:21:35.24,0:21:36.19,EN,,0,0,0,,just the evaluator\nDialogue: 0,0:21:37.40,0:21:40.40,EN,,0,0,0,,and then you see which stack operations are unnecessary.\nDialogue: 0,0:21:40.82,0:21:43.76,EN,,0,0,0,,That's the basic structure of the compiler that's\nDialogue: 0,0:21:43.85,0:21:45.04,EN,,0,0,0,,that's described in the book.\nDialogue: 0,0:21:45.04,0:21:47.00,EN,,0,0,0,,Let me just show you how a\nDialogue: 0,0:21:47.76,0:21:49.68,EN,,0,0,0,,that examples a little bit too simple.\nDialogue: 0,0:21:51.20,0:21:53.26,EN,,0,0,0,,To see how you, how you actually save a lot\nDialogue: 0,0:21:53.29,0:21:56.06,EN,,0,0,0,,let's look at a little bit more complicated expression.\nDialogue: 0,0:21:58.15,0:22:01.93,EN,,0,0,0,,(F (G X) 1)\nDialogue: 0,0:22:03.87,0:22:05.52,EN,,0,0,0,,And I'm not going to go through all the code.\nDialogue: 0,0:22:06.40,0:22:08.56,EN,,0,0,0,,There's a, there's a fair pile of it.\nDialogue: 0,0:22:09.72,0:22:12.35,EN,,0,0,0,,I think there are, there are something like 16\nDialogue: 0,0:22:12.35,0:22:14.67,EN,,0,0,0,,16 pairs of register saves and restores\nDialogue: 0,0:22:14.70,0:22:16.25,EN,,0,0,0,,as the evaluator walks through that.\nDialogue: 0,0:22:17.00,0:22:18.57,EN,,0,0,0,,Here's a diagram of them.\nDialogue: 0,0:22:20.57,0:22:21.95,EN,,0,0,0,,Let's see. You see what's going on.\nDialogue: 0,0:22:22.97,0:22:23.90,EN,,0,0,0,,You start out by--\nDialogue: 0,0:22:24.25,0:22:26.62,EN,,0,0,0,,the evaluator says, oh, I'm about to do an application.\nDialogue: 0,0:22:26.90,0:22:29.13,EN,,0,0,0,,I'll preserve the environment. I'll restore it here.\nDialogue: 0,0:22:30.65,0:22:34.44,EN,,0,0,0,,Then I'm about to do the first operand.\nDialogue: 0,0:22:36.81,0:22:39.28,EN,,0,0,0,,Here it recursively goes to the evaluator.\nDialogue: 0,0:22:39.28,0:22:40.89,EN,,0,0,0,,The evaluator says, oh, this is an application,\nDialogue: 0,0:22:40.91,0:22:42.10,EN,,0,0,0,,I'll save the environment\nDialogue: 0,0:22:42.10,0:22:44.97,EN,,0,0,0,,do the operator of that combination, restore it here.\nDialogue: 0,0:22:45.80,0:22:48.92,EN,,0,0,0,,This save--this restore matches that save.\nDialogue: 0,0:22:49.77,0:22:50.78,EN,,0,0,0,,And so on.\nDialogue: 0,0:22:51.65,0:22:52.51,EN,,0,0,0,,There's unev here,\nDialogue: 0,0:22:52.52,0:22:54.62,EN,,0,0,0,,which turns out to be completely unnecessary\nDialogue: 0,0:22:54.97,0:22:56.60,EN,,0,0,0,,continues getting bumped around here.\nDialogue: 0,0:22:57.42,0:23:00.41,EN,,0,0,0,,The function register is getting, getting saved\nDialogue: 0,0:23:00.78,0:23:04.36,EN,,0,0,0,,across the first operands, across the operands.\nDialogue: 0,0:23:05.10,0:23:06.52,EN,,0,0,0,,All sorts of things are going on.\nDialogue: 0,0:23:06.78,0:23:09.39,EN,,0,0,0,,But if you say, well, what of those really were the business of\nDialogue: 0,0:23:09.87,0:23:11.66,EN,,0,0,0,,the compiler as opposed to the evaluator\nDialogue: 0,0:23:12.27,0:23:13.55,EN,,0,0,0,,you get rid of a whole bunch.\nDialogue: 0,0:23:14.30,0:23:16.64,EN,,0,0,0,,And then on top of that, if you say things like\nDialogue: 0,0:23:19.40,0:23:22.54,EN,,0,0,0,,the evaluation of F doesn't hurt the environment register,\nDialogue: 0,0:23:23.82,0:23:26.51,EN,,0,0,0,,or simply looking up the symbol X,\nDialogue: 0,0:23:29.28,0:23:32.09,EN,,0,0,0,,you don't have to protect the function register against that.\nDialogue: 0,0:23:34.30,0:23:37.60,EN,,0,0,0,,So you come down to just a couple of, a couple of pairs here.\nDialogue: 0,0:23:40.25,0:23:42.27,EN,,0,0,0,,And still, you can do a little better.\nDialogue: 0,0:23:42.27,0:23:44.33,EN,,0,0,0,,Look what's going on here with the environment register.\nDialogue: 0,0:23:45.21,0:23:47.39,EN,,0,0,0,,The environment register comes along and says, oh,\nDialogue: 0,0:23:51.00,0:23:52.25,EN,,0,0,0,,here's a combination.\nDialogue: 0,0:23:54.33,0:23:55.69,EN,,0,0,0,,This evaluator, by the way,\nDialogue: 0,0:23:55.78,0:23:57.27,EN,,0,0,0,,doesn't know anything about G.\nDialogue: 0,0:23:58.57,0:24:00.73,EN,,0,0,0,,So here it says, so it says,\nDialogue: 0,0:24:01.29,0:24:03.45,EN,,0,0,0,,I'd better save the environment register,\nDialogue: 0,0:24:03.96,0:24:05.42,EN,,0,0,0,,because evaluating G might be\nDialogue: 0,0:24:05.42,0:24:07.42,EN,,0,0,0,,some arbitrary piece of code that would trash it\nDialogue: 0,0:24:07.55,0:24:09.45,EN,,0,0,0,,and I'm going to need it later,\nDialogue: 0,0:24:10.17,0:24:11.40,EN,,0,0,0,,after this argument,\nDialogue: 0,0:24:12.22,0:24:13.37,EN,,0,0,0,,for doing the second argument.\nDialogue: 0,0:24:15.60,0:24:17.24,EN,,0,0,0,,So that's why this one didn't go away,\nDialogue: 0,0:24:19.07,0:24:22.54,EN,,0,0,0,,because the compiler made no assumptions about what G would do.\nDialogue: 0,0:24:22.54,0:24:23.60,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:24:24.61,0:24:26.52,EN,,0,0,0,,if you look at what the second argument is,\nDialogue: 0,0:24:26.64,0:24:27.70,EN,,0,0,0,,that's just looking up one.\nDialogue: 0,0:24:27.70,0:24:29.60,EN,,0,0,0,,That doesn't need this environment register.\nDialogue: 0,0:24:30.77,0:24:32.04,EN,,0,0,0,,So there's no reason to save it.\nDialogue: 0,0:24:32.06,0:24:33.77,EN,,0,0,0,,So in fact, you can get rid of that one, too.\nDialogue: 0,0:24:34.85,0:24:37.81,EN,,0,0,0,,And from this whole pile of, of register operations,\nDialogue: 0,0:24:37.98,0:24:40.08,EN,,0,0,0,,if you simply do a little bit of reasoning like that,\nDialogue: 0,0:24:40.55,0:24:43.05,EN,,0,0,0,,you get down to, I think, just two pairs of saves and restores.\nDialogue: 0,0:24:45.10,0:24:46.97,EN,,0,0,0,,And those, in fact, could go away further if you,\nDialogue: 0,0:24:47.52,0:24:49.08,EN,,0,0,0,,if you knew something about G.\nDialogue: 0,0:24:56.27,0:24:57.85,EN,,0,0,0,,So again, the general idea\nDialogue: 0,0:24:57.95,0:24:59.98,EN,,0,0,0,,is that the reason the compiler can be better\nDialogue: 0,0:24:59.98,0:25:02.56,EN,,0,0,0,,is that the interpreter doesn't know what it's about to encounter.\nDialogue: 0,0:25:03.25,0:25:05.04,EN,,0,0,0,,It has to be maximally pessimistic\nDialogue: 0,0:25:05.05,0:25:06.70,EN,,0,0,0,,to protect itself.\nDialogue: 0,0:25:07.90,0:25:08.76,EN,,0,0,0,,The compiler\nDialogue: 0,0:25:09.48,0:25:12.38,EN,,0,0,0,,only has to deal with what actually had to be saved.\nDialogue: 0,0:25:13.37,0:25:15.20,EN,,0,0,0,,And there are two reasons that something\nDialogue: 0,0:25:15.24,0:25:17.37,EN,,0,0,0,,might not have to be saved.\nDialogue: 0,0:25:17.82,0:25:18.70,EN,,0,0,0,,One is that\nDialogue: 0,0:25:18.70,0:25:19.82,EN,,0,0,0,,what you're protecting it against,\nDialogue: 0,0:25:19.95,0:25:21.44,EN,,0,0,0,,in fact, didn't trash the register,\nDialogue: 0,0:25:22.08,0:25:23.58,EN,,0,0,0,,like it was just a variable look-up.\nDialogue: 0,0:25:24.12,0:25:25.20,EN,,0,0,0,,And the other one is,\nDialogue: 0,0:25:25.32,0:25:27.10,EN,,0,0,0,,that the thing that you were saving it for\nDialogue: 0,0:25:28.28,0:25:29.92,EN,,0,0,0,,might turn out not to actually need it.\nDialogue: 0,0:25:30.81,0:25:34.27,EN,,0,0,0,,So those are the two basic pieces of knowledge\nDialogue: 0,0:25:34.30,0:25:35.88,EN,,0,0,0,,that the compiler can take advantage of\nDialogue: 0,0:25:36.27,0:25:37.76,EN,,0,0,0,,in making the code more efficient.\nDialogue: 0,0:25:44.27,0:25:45.32,EN,,0,0,0,,Let's break for questions.\nDialogue: 0,0:25:51.20,0:25:53.10,EN,,0,0,0,,AUDIENCE: You kept saying that the uneval register,\nDialogue: 0,0:25:53.13,0:25:56.40,EN,,0,0,0,,unev register didn't need to be used at all.\nDialogue: 0,0:25:56.41,0:25:58.68,EN,,0,0,0,,Does that mean that you could just map a six-register machine?\nDialogue: 0,0:25:58.70,0:26:00.08,EN,,0,0,0,,Or is that, in this particular example,\nDialogue: 0,0:26:00.11,0:26:01.18,EN,,0,0,0,,it didn't need to be used?\nDialogue: 0,0:26:01.72,0:26:02.81,EN,,0,0,0,,PROFESSOR: For the compiler,\nDialogue: 0,0:26:04.31,0:26:07.42,EN,,0,0,0,,you could generate code for the six-register, five, right?\nDialogue: 0,0:26:07.56,0:26:09.02,EN,,0,0,0,,Because that exp goes away also.\nDialogue: 0,0:26:09.40,0:26:14.57,EN,,0,0,0,,Assuming--yeah, you can get rid of both exp and unev\nDialogue: 0,0:26:14.57,0:26:16.87,EN,,0,0,0,,because, see, those are data structures of the evaluator.\nDialogue: 0,0:26:17.36,0:26:19.36,EN,,0,0,0,,Those are all things that would be constants\nDialogue: 0,0:26:19.39,0:26:20.87,EN,,0,0,0,,from the point of view of the compiler.\nDialogue: 0,0:26:21.65,0:26:22.44,EN,,0,0,0,,The only thing is\nDialogue: 0,0:26:22.48,0:26:24.59,EN,,0,0,0,,this particular compiler is set up\nDialogue: 0,0:26:24.79,0:26:27.92,EN,,0,0,0,,so that interpreted code and compiled code can coexist.\nDialogue: 0,0:26:29.32,0:26:30.72,EN,,0,0,0,,So the way to think about it is,\nDialogue: 0,0:26:30.97,0:26:32.29,EN,,0,0,0,,is maybe you build a chip\nDialogue: 0,0:26:34.30,0:26:35.50,EN,,0,0,0,,which is the evaluator,\nDialogue: 0,0:26:35.88,0:26:37.28,EN,,0,0,0,,and what the compiler might do\nDialogue: 0,0:26:37.31,0:26:39.02,EN,,0,0,0,,is generate code for that chip.\nDialogue: 0,0:26:40.40,0:26:41.90,EN,,0,0,0,,It just wouldn't use two of the registers.\nDialogue: 0,0:26:51.52,0:26:52.47,EN,,0,0,0,,All right, let's take a break.\nDialogue: 0,0:26:53.55,0:27:07.18,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:27:29.21,0:27:32.43,EN,,0,0,0,,We just looked at what the compiler is supposed to do.\nDialogue: 0,0:27:32.78,0:27:36.04,EN,,0,0,0,,Now let's very briefly look at how,\nDialogue: 0,0:27:36.15,0:27:37.47,EN,,0,0,0,,how this gets accomplished.\nDialogue: 0,0:27:38.26,0:27:39.58,EN,,0,0,0,,And I'm going to give no details.\nDialogue: 0,0:27:39.60,0:27:42.17,EN,,0,0,0,,There's, there's a giant pile of code in the book\nDialogue: 0,0:27:42.22,0:27:43.42,EN,,0,0,0,,that gives all the details.\nDialogue: 0,0:27:43.45,0:27:45.31,EN,,0,0,0,,But what I want to do is just show you the,\nDialogue: 0,0:27:45.96,0:27:47.26,EN,,0,0,0,,the essential idea here.\nDialogue: 0,0:27:49.49,0:27:51.36,EN,,0,0,0,,Worry about the details some other time.\nDialogue: 0,0:27:51.51,0:27:55.30,EN,,0,0,0,,Let's imagine that we're compiling an expression\nDialogue: 0,0:27:55.30,0:27:57.01,EN,,0,0,0,,that looks like there's some operator\nDialogue: 0,0:27:57.48,0:27:58.56,EN,,0,0,0,,and there are two arguments.\nDialogue: 0,0:28:03.56,0:28:04.24,EN,,0,0,0,,Now, the--\nDialogue: 0,0:28:06.27,0:28:08.14,EN,,0,0,0,,what's the code that the compiler should generate?\nDialogue: 0,0:28:08.85,0:28:09.78,EN,,0,0,0,,Well, first of all,\nDialogue: 0,0:28:09.83,0:28:11.20,EN,,0,0,0,,it should recursively go off\nDialogue: 0,0:28:11.90,0:28:13.28,EN,,0,0,0,,and compile the operator.\nDialogue: 0,0:28:14.37,0:28:19.02,EN,,0,0,0,,So it says, I'll compile the operator.\nDialogue: 0,0:28:21.16,0:28:24.54,EN,,0,0,0,,And where I'm going to need that\nDialogue: 0,0:28:24.84,0:28:27.95,EN,,0,0,0,,is to be in the function register, eventually.\nDialogue: 0,0:28:28.42,0:28:29.60,EN,,0,0,0,,So I'll compile some instructions\nDialogue: 0,0:28:29.64,0:28:31.56,EN,,0,0,0,,that will compile the operator\nDialogue: 0,0:28:31.69,0:28:38.62,EN,,0,0,0,,and end up with the result in the function register.\nDialogue: 0,0:28:45.51,0:28:46.94,EN,,0,0,0,,The next thing it's going to do,\nDialogue: 0,0:28:47.71,0:28:49.68,EN,,0,0,0,,another piece is to say,\nDialogue: 0,0:28:49.68,0:28:55.17,EN,,0,0,0,,I have to compile the first argument.\nDialogue: 0,0:28:55.17,0:28:56.80,EN,,0,0,0,,So it calls itself recursively.\nDialogue: 0,0:28:58.04,0:29:03.36,EN,,0,0,0,,And let's say the result will go into val.\nDialogue: 0,0:29:09.07,0:29:10.75,EN,,0,0,0,,And then what it's going to need to do is\nDialogue: 0,0:29:10.75,0:29:12.26,EN,,0,0,0,,start setting up the argument list.\nDialogue: 0,0:29:12.95,0:29:25.50,EN,,0,0,0,,So it'll say, assign to argl cons of fetch--\nDialogue: 0,0:29:25.55,0:29:27.10,EN,,0,0,0,,so it generates this literal instruction--\nDialogue: 0,0:29:27.50,0:29:32.51,EN,,0,0,0,,fetch of val onto empty list.\nDialogue: 0,0:29:35.00,0:29:36.05,EN,,0,0,0,,However,\nDialogue: 0,0:29:37.99,0:29:40.61,EN,,0,0,0,,it might have to work--  when it gets here,\nDialogue: 0,0:29:41.32,0:29:42.82,EN,,0,0,0,,it's going to need the environment.\nDialogue: 0,0:29:43.95,0:29:45.29,EN,,0,0,0,,It's going to need whatever environment was here\nDialogue: 0,0:29:45.32,0:29:48.21,EN,,0,0,0,,in order to do this evaluation of the first argument.\nDialogue: 0,0:29:49.04,0:29:51.18,EN,,0,0,0,,So it has to ensure that\nDialogue: 0,0:29:51.92,0:29:53.76,EN,,0,0,0,,the compilation of this operand,\nDialogue: 0,0:29:55.32,0:29:57.85,EN,,0,0,0,,or it has to protect the function register\nDialogue: 0,0:29:58.01,0:30:00.98,EN,,0,0,0,,against whatever might happen in the compilation of this operand.\nDialogue: 0,0:30:01.30,0:30:03.08,EN,,0,0,0,,So it puts a note here and says, oh,\nDialogue: 0,0:30:03.37,0:30:12.89,EN,,0,0,0,,this piece should be done preserving the environment register.\nDialogue: 0,0:30:17.39,0:30:18.44,EN,,0,0,0,,Similarly, here,\nDialogue: 0,0:30:21.02,0:30:23.30,EN,,0,0,0,,after it gets done compiling the first operand,\nDialogue: 0,0:30:23.57,0:30:24.67,EN,,0,0,0,,it's going to say, I'd better--\nDialogue: 0,0:30:24.71,0:30:27.92,EN,,0,0,0,,I'm going to need to know the environment for the second operand.\nDialogue: 0,0:30:27.92,0:30:29.46,EN,,0,0,0,,So it puts a little note here, saying,\nDialogue: 0,0:30:29.71,0:30:35.96,EN,,0,0,0,,yeah, this is also done preserving env.\nDialogue: 0,0:30:39.42,0:30:41.02,EN,,0,0,0,,Now it goes on and says, well,\nDialogue: 0,0:30:41.12,0:30:42.83,EN,,0,0,0,,the next chunk of code\nDialogue: 0,0:30:43.31,0:30:49.74,EN,,0,0,0,,is the one that's going to compile the second argument.\nDialogue: 0,0:30:50.82,0:30:52.64,EN,,0,0,0,,And let's say\nDialogue: 0,0:30:52.99,0:30:59.28,EN,,0,0,0,,And let's say it'll compile it with a targeted to val, as they say.\nDialogue: 0,0:31:03.86,0:31:06.70,EN,,0,0,0,,And then it'll generate the literal instruction,\nDialogue: 0,0:31:07.84,0:31:09.25,EN,,0,0,0,,building up the argument list.\nDialogue: 0,0:31:09.55,0:31:15.28,EN,,0,0,0,,So it'll say, assign to argl\nDialogue: 0,0:31:20.22,0:31:28.94,EN,,0,0,0,,cons of the new value it just got onto the old argument list.\nDialogue: 0,0:31:33.97,0:31:34.64,EN,,0,0,0,,However,\nDialogue: 0,0:31:34.81,0:31:36.58,EN,,0,0,0,,in order to have the old argument list,\nDialogue: 0,0:31:37.15,0:31:40.99,EN,,0,0,0,,it better have arranged that the argument list didn't get trashed\nDialogue: 0,0:31:41.30,0:31:42.69,EN,,0,0,0,,by whatever happened in here.\nDialogue: 0,0:31:43.50,0:31:45.17,EN,,0,0,0,,So it puts a little note here and says,\nDialogue: 0,0:31:45.34,0:31:51.64,EN,,0,0,0,,oh, this has to be done preserving argl.\nDialogue: 0,0:31:54.16,0:31:56.03,EN,,0,0,0,,Now it's got the argument list set up.\nDialogue: 0,0:31:58.01,0:32:02.86,EN,,0,0,0,,And it's all ready to go to apply dispatch.\nDialogue: 0,0:32:07.02,0:32:10.80,EN,,0,0,0,,It generates this literal instruction.\nDialogue: 0,0:32:15.19,0:32:17.37,EN,,0,0,0,,Because now it's got the arguments in argl\nDialogue: 0,0:32:18.15,0:32:20.59,EN,,0,0,0,,and the operator in fun,\nDialogue: 0,0:32:20.59,0:32:22.89,EN,,0,0,0,,but wait, it's only got the operator in fun\nDialogue: 0,0:32:23.27,0:32:26.64,EN,,0,0,0,,if it had ensured that this block of code\nDialogue: 0,0:32:27.09,0:32:29.27,EN,,0,0,0,,didn't trash what was in the function register.\nDialogue: 0,0:32:29.67,0:32:31.24,EN,,0,0,0,,So it puts a little note here and says,\nDialogue: 0,0:32:31.55,0:32:32.73,EN,,0,0,0,,oh, yes, all this stuff here\nDialogue: 0,0:32:34.88,0:32:40.73,EN,,0,0,0,,had better be done preserving the function register.\nDialogue: 0,0:32:43.71,0:32:46.15,EN,,0,0,0,,So that's the little--so when it starts ticking--\nDialogue: 0,0:32:46.15,0:32:47.10,EN,,0,0,0,,so basically, what the\nDialogue: 0,0:32:48.20,0:32:50.24,EN,,0,0,0,,what the compiler does is\nDialogue: 0,0:32:50.54,0:32:52.46,EN,,0,0,0,,append a whole bunch of code sequences.\nDialogue: 0,0:32:53.50,0:32:58.83,EN,,0,0,0,,See, what it's got in it is little primitive pieces of things\nDialogue: 0,0:32:58.86,0:33:00.12,EN,,0,0,0,,like how to look up a symbol,\nDialogue: 0,0:33:01.44,0:33:02.60,EN,,0,0,0,,how to do a conditional.\nDialogue: 0,0:33:02.64,0:33:05.44,EN,,0,0,0,,Those are all little pieces of things.\nDialogue: 0,0:33:05.44,0:33:07.99,EN,,0,0,0,,And then it appends them together in this sort of discipline.\nDialogue: 0,0:33:08.78,0:33:10.79,EN,,0,0,0,,So the basic means of combining things\nDialogue: 0,0:33:10.86,0:33:13.18,EN,,0,0,0,,is to append two code sequences.\nDialogue: 0,0:33:21.55,0:33:22.86,EN,,0,0,0,,That's what's going on here.\nDialogue: 0,0:33:25.58,0:33:27.24,EN,,0,0,0,,And it's a little bit tricky.\nDialogue: 0,0:33:27.56,0:33:30.37,EN,,0,0,0,,The idea is that it appends two code sequences,\nDialogue: 0,0:33:31.60,0:33:33.76,EN,,0,0,0,,taking care to preserve a register.\nDialogue: 0,0:33:35.63,0:33:37.93,EN,,0,0,0,,So the actual append operation looks like this.\nDialogue: 0,0:33:39.15,0:33:40.65,EN,,0,0,0,,What it wants to do is say, if--\nDialogue: 0,0:33:41.20,0:33:44.11,EN,,0,0,0,,here's what it means to append two code sequences.\nDialogue: 0,0:33:44.53,0:33:53.63,EN,,0,0,0,,So if sequence one needs register--\nDialogue: 0,0:33:53.66,0:33:54.72,EN,,0,0,0,,I should change this.\nDialogue: 0,0:33:54.72,0:33:56.87,EN,,0,0,0,,Append sequence one to sequence two,\nDialogue: 0,0:33:57.42,0:34:03.96,EN,,0,0,0,,preserving some register.\nDialogue: 0,0:34:08.52,0:34:09.91,EN,,0,0,0,,Let me say, and.\nDialogue: 0,0:34:11.36,0:34:13.03,EN,,0,0,0,,So it's clear that sequence one comes first.\nDialogue: 0,0:34:13.88,0:34:19.87,EN,,0,0,0,,So if sequence two needs the register\nDialogue: 0,0:34:21.12,0:34:27.85,EN,,0,0,0,,and sequence one modifies the register,\nDialogue: 0,0:34:33.68,0:34:36.30,EN,,0,0,0,,then the instructions that the compiler spits out,\nDialogue: 0,0:34:36.97,0:34:41.34,EN,,0,0,0,,are save the register.\nDialogue: 0,0:34:43.02,0:34:44.19,EN,,0,0,0,,Here's the code.\nDialogue: 0,0:34:44.35,0:34:45.35,EN,,0,0,0,,You generate this code.\nDialogue: 0,0:34:45.35,0:34:46.28,EN,,0,0,0,,Save the register,\nDialogue: 0,0:34:46.72,0:34:52.97,EN,,0,0,0,,and then you put out the recursively compiled stuff for sequence one.\nDialogue: 0,0:34:53.30,0:34:54.84,EN,,0,0,0,,And then you restore the register.\nDialogue: 0,0:35:00.52,0:35:03.92,EN,,0,0,0,,And then you put out the recursively compiled stuff\nDialogue: 0,0:35:04.46,0:35:05.47,EN,,0,0,0,,for sequence two.\nDialogue: 0,0:35:07.07,0:35:09.62,EN,,0,0,0,,That's in the case where you need to do it.\nDialogue: 0,0:35:09.62,0:35:11.82,EN,,0,0,0,,Sequence two actually needs the register,\nDialogue: 0,0:35:11.82,0:35:13.74,EN,,0,0,0,,and sequence one actually clobbers it.\nDialogue: 0,0:35:15.12,0:35:17.07,EN,,0,0,0,,So that's sort of if. Otherwise,\nDialogue: 0,0:35:20.50,0:35:26.57,EN,,0,0,0,,all you spit out is sequence one followed by sequence two.\nDialogue: 0,0:35:28.17,0:35:30.30,EN,,0,0,0,,So that's the basic operation\nDialogue: 0,0:35:30.59,0:35:33.52,EN,,0,0,0,,for sticking together these bits of code fragments,\nDialogue: 0,0:35:33.93,0:35:35.93,EN,,0,0,0,,these bits of instructions into a sequence.\nDialogue: 0,0:35:36.89,0:35:38.87,EN,,0,0,0,,And you see, from this point of view,\nDialogue: 0,0:35:40.94,0:35:45.96,EN,,0,0,0,,the difference between the interpreter and the compiler, in some sense,\nDialogue: 0,0:35:46.82,0:35:49.34,EN,,0,0,0,,is that where the compiler has these preserving notes,\nDialogue: 0,0:35:50.14,0:35:52.22,EN,,0,0,0,,and says, maybe I'll actually generate the\nDialogue: 0,0:35:52.49,0:35:54.22,EN,,0,0,0,,saves and restores and maybe I won't,\nDialogue: 0,0:35:55.19,0:35:57.24,EN,,0,0,0,,the interpreter being maximally pessimistic\nDialogue: 0,0:35:57.28,0:35:58.90,EN,,0,0,0,,always has a save and restore here.\nDialogue: 0,0:36:00.76,0:36:01.93,EN,,0,0,0,,That's the essential difference.\nDialogue: 0,0:36:04.16,0:36:06.05,EN,,0,0,0,,Well, in order to do this, of course,\nDialogue: 0,0:36:06.65,0:36:09.40,EN,,0,0,0,,the compiler needs some theory of\nDialogue: 0,0:36:09.56,0:36:11.96,EN,,0,0,0,,what code sequences need and modifier registers.\nDialogue: 0,0:36:14.26,0:36:17.28,EN,,0,0,0,,So the tiny little fragments that you put in, like\nDialogue: 0,0:36:17.48,0:36:21.00,EN,,0,0,0,,the basic primitive code fragments,\nDialogue: 0,0:36:22.74,0:36:24.59,EN,,0,0,0,,say, what are the operations that you do\nDialogue: 0,0:36:24.92,0:36:26.04,EN,,0,0,0,,when you look up a variable?\nDialogue: 0,0:36:26.89,0:36:29.02,EN,,0,0,0,,What are the sequence of things that you do\nDialogue: 0,0:36:29.05,0:36:30.68,EN,,0,0,0,,when you compile a constant\nDialogue: 0,0:36:30.97,0:36:32.10,EN,,0,0,0,,or apply a function?\nDialogue: 0,0:36:32.97,0:36:34.48,EN,,0,0,0,,Those have little notations in there\nDialogue: 0,0:36:34.67,0:36:36.46,EN,,0,0,0,,about what they need and what they modify.\nDialogue: 0,0:36:38.78,0:36:41.50,EN,,0,0,0,,So the bottom-level data structures--\nDialogue: 0,0:36:42.66,0:36:44.33,EN,,0,0,0,,Well, I'll say this.\nDialogue: 0,0:36:44.39,0:36:47.91,EN,,0,0,0,,A code sequence to the compiler looks like this.\nDialogue: 0,0:36:48.07,0:36:51.42,EN,,0,0,0,,It has the actual sequence of instructions.\nDialogue: 0,0:36:55.67,0:36:56.81,EN,,0,0,0,,And then, along with it,\nDialogue: 0,0:36:57.18,0:37:02.60,EN,,0,0,0,,there's the set of registers modified.\nDialogue: 0,0:37:10.54,0:37:12.60,EN,,0,0,0,,And then there's the set of registers needed.\nDialogue: 0,0:37:20.00,0:37:22.46,EN,,0,0,0,,So that's the information the compiler has\nDialogue: 0,0:37:23.00,0:37:26.41,EN,,0,0,0,,that it draws on in order to be able to do this operation.\nDialogue: 0,0:37:29.30,0:37:31.08,EN,,0,0,0,,And where do those come from? Well.\nDialogue: 0,0:37:32.91,0:37:34.49,EN,,0,0,0,,Well, those come from, you might expect,\nDialogue: 0,0:37:34.51,0:37:35.53,EN,,0,0,0,,for the very primitive ones,\nDialogue: 0,0:37:35.55,0:37:36.84,EN,,0,0,0,,we're going to put them in by hand.\nDialogue: 0,0:37:37.24,0:37:38.86,EN,,0,0,0,,And then, when we combine two sequences,\nDialogue: 0,0:37:38.89,0:37:41.02,EN,,0,0,0,,we'll figure out what these things should be.\nDialogue: 0,0:37:42.16,0:37:44.12,EN,,0,0,0,,So for example, a very primitive one, let's see.\nDialogue: 0,0:37:48.43,0:37:51.40,EN,,0,0,0,,How about doing a register assignment.\nDialogue: 0,0:37:51.77,0:37:53.50,EN,,0,0,0,,So a primitive sequence might say,\nDialogue: 0,0:37:53.52,0:37:56.22,EN,,0,0,0,,oh, it's code fragment.\nDialogue: 0,0:37:56.22,0:38:03.17,EN,,0,0,0,,Its code instruction is assigned to R1, fetch of R2.\nDialogue: 0,0:38:03.17,0:38:04.27,EN,,0,0,0,,So this is an example.\nDialogue: 0,0:38:05.42,0:38:08.52,EN,,0,0,0,,That might be an example of a sequence of instructions.\nDialogue: 0,0:38:08.77,0:38:10.53,EN,,0,0,0,,And along with that, it'll say, Oh\nDialogue: 0,0:38:10.64,0:38:15.76,EN,,0,0,0,,oh, what I need to remember is that that modifies R1\nDialogue: 0,0:38:18.60,0:38:21.16,EN,,0,0,0,,and then it needs R2.\nDialogue: 0,0:38:24.69,0:38:26.99,EN,,0,0,0,,So when you're first building this compiler,\nDialogue: 0,0:38:27.10,0:38:29.35,EN,,0,0,0,,you put in little fragments of stuff like that.\nDialogue: 0,0:38:30.95,0:38:33.20,EN,,0,0,0,,And now, when it combines two sequences,\nDialogue: 0,0:38:36.70,0:38:38.04,EN,,0,0,0,,if I'm going to combine,\nDialogue: 0,0:38:38.92,0:38:41.58,EN,,0,0,0,,let's say, sequence one,\nDialogue: 0,0:38:42.88,0:38:47.16,EN,,0,0,0,,that modifies a bunch of registers M1,\nDialogue: 0,0:38:48.45,0:38:51.42,EN,,0,0,0,,and needs a bunch of registers N1.\nDialogue: 0,0:38:54.85,0:38:59.48,EN,,0,0,0,,And I'm going to combine that with sequence two.\nDialogue: 0,0:39:00.81,0:39:05.96,EN,,0,0,0,,That modifies a bunch of registers M2,\nDialogue: 0,0:39:07.11,0:39:10.00,EN,,0,0,0,,and needs a bunch of registers N2.\nDialogue: 0,0:39:12.44,0:39:14.83,EN,,0,0,0,,Then, well, we can reason it out.\nDialogue: 0,0:39:15.11,0:39:16.32,EN,,0,0,0,,The new code fragment,\nDialogue: 0,0:39:17.18,0:39:21.82,EN,,0,0,0,,sequence one, and-- followed by sequence two,\nDialogue: 0,0:39:24.09,0:39:26.45,EN,,0,0,0,,well, what's it going to modify?\nDialogue: 0,0:39:27.80,0:39:29.18,EN,,0,0,0,,The things that it will modify are the things\nDialogue: 0,0:39:29.20,0:39:32.68,EN,,0,0,0,,that are modified either by sequence one or sequence two.\nDialogue: 0,0:39:34.00,0:39:36.35,EN,,0,0,0,,So the union of these two\nDialogue: 0,0:39:37.68,0:39:39.64,EN,,0,0,0,,sets are what the new thing modifies.\nDialogue: 0,0:39:40.46,0:39:41.79,EN,,0,0,0,,And then you say, well, what is this--\nDialogue: 0,0:39:44.66,0:39:46.41,EN,,0,0,0,,what registers is it going to need?\nDialogue: 0,0:39:47.95,0:39:49.77,EN,,0,0,0,,It's going to need the things that are,\nDialogue: 0,0:39:49.93,0:39:51.85,EN,,0,0,0,,first of all, needed by sequence one.\nDialogue: 0,0:39:52.91,0:39:54.49,EN,,0,0,0,,So what it needs is sequence one.\nDialogue: 0,0:39:55.19,0:39:58.28,EN,,0,0,0,,And then, well, not quite all of the ones\nDialogue: 0,0:39:58.32,0:39:59.61,EN,,0,0,0,,that are needed by sequence two.\nDialogue: 0,0:39:59.75,0:40:03.49,EN,,0,0,0,,What it needs are the ones that are needed by sequence two\nDialogue: 0,0:40:03.88,0:40:06.88,EN,,0,0,0,,that have not been set up by sequence one.\nDialogue: 0,0:40:08.14,0:40:09.72,EN,,0,0,0,,So it's sort of the union of\nDialogue: 0,0:40:11.66,0:40:13.40,EN,,0,0,0,,the things that sequence two needs\nDialogue: 0,0:40:14.51,0:40:18.52,EN,,0,0,0,,minus the ones that sequence one modifies.\nDialogue: 0,0:40:19.31,0:40:20.88,EN,,0,0,0,,Because it worries about setting them up.\nDialogue: 0,0:40:23.95,0:40:26.26,EN,,0,0,0,,So there's the basic structure of the compiler.\nDialogue: 0,0:40:26.70,0:40:29.82,EN,,0,0,0,,The way you do register optimizations is you\nDialogue: 0,0:40:30.22,0:40:32.70,EN,,0,0,0,,you have some strategies for what needs to be preserved.\nDialogue: 0,0:40:34.10,0:40:35.63,EN,,0,0,0,,That depends on a data structure.\nDialogue: 0,0:40:35.72,0:40:38.51,EN,,0,0,0,,Well, it depends on the operation of what it means to put things together.\nDialogue: 0,0:40:39.03,0:40:41.63,EN,,0,0,0,,Preserving something, that depends on knowing\nDialogue: 0,0:40:41.93,0:40:47.28,EN,,0,0,0,,what registers are needed and modified by these code fragments.\nDialogue: 0,0:40:48.75,0:40:51.26,EN,,0,0,0,,That depends on having little data structures,\nDialogue: 0,0:40:51.42,0:40:55.43,EN,,0,0,0,,which say, a code sequence is the actual instructions,\nDialogue: 0,0:40:55.60,0:40:57.33,EN,,0,0,0,,what they modify and what they need.\nDialogue: 0,0:40:57.33,0:40:59.77,EN,,0,0,0,,That comes from, at the primitive level, building it in.\nDialogue: 0,0:40:59.79,0:41:01.36,EN,,0,0,0,,At the primitive level,\nDialogue: 0,0:41:01.37,0:41:02.52,EN,,0,0,0,,it's going to be completely obvious\nDialogue: 0,0:41:03.00,0:41:04.44,EN,,0,0,0,,what something needs and modifies.\nDialogue: 0,0:41:04.82,0:41:05.35,EN,,0,0,0,,Plus,\nDialogue: 0,0:41:05.44,0:41:08.60,EN,,0,0,0,,this particular way that says, when I build up bigger ones,\nDialogue: 0,0:41:09.28,0:41:11.89,EN,,0,0,0,,here's how I generate the new set of registers modified\nDialogue: 0,0:41:11.93,0:41:13.37,EN,,0,0,0,,and the new set of registers needed.\nDialogue: 0,0:41:15.27,0:41:17.77,EN,,0,0,0,,And that's the whole-- well, I shouldn't say that's the whole thing.\nDialogue: 0,0:41:17.77,0:41:19.34,EN,,0,0,0,,That's the whole thing except for about\nDialogue: 0,0:41:19.74,0:41:21.87,EN,,0,0,0,,about 30 pages of details in the book.\nDialogue: 0,0:41:22.31,0:41:27.69,EN,,0,0,0,,But it is a perfectly usable rudimentary compiler.\nDialogue: 0,0:41:28.76,0:41:31.37,EN,,0,0,0,,Let me kind of show you what it does.\nDialogue: 0,0:41:31.39,0:41:35.56,EN,,0,0,0,,Suppose we start out with recursive factorial.\nDialogue: 0,0:41:36.20,0:41:38.60,EN,,0,0,0,,And these slides are going to be much too small to read.\nDialogue: 0,0:41:38.60,0:41:39.79,EN,,0,0,0,,I just want to flash through the code\nDialogue: 0,0:41:39.79,0:41:41.28,EN,,0,0,0,,and show you about how much it is.\nDialogue: 0,0:41:42.25,0:41:43.29,EN,,0,0,0,,That starts out with--\nDialogue: 0,0:41:44.32,0:41:45.68,EN,,0,0,0,,here's a first block of it,\nDialogue: 0,0:41:45.95,0:41:47.68,EN,,0,0,0,,where it compiles a procedure entry\nDialogue: 0,0:41:47.69,0:41:48.73,EN,,0,0,0,,and does a bunch of assignments.\nDialogue: 0,0:41:48.75,0:41:51.48,EN,,0,0,0,,And this thing is basically up through the part where\nDialogue: 0,0:41:52.65,0:41:53.90,EN,,0,0,0,,sets up to do the predicate\nDialogue: 0,0:41:54.31,0:41:56.59,EN,,0,0,0,,and test whether the predicate's true.\nDialogue: 0,0:41:56.97,0:41:57.85,EN,,0,0,0,,The second part\nDialogue: 0,0:41:58.46,0:42:03.73,EN,,0,0,0,,is what results from-- in the recursive call to fact of n minus one.\nDialogue: 0,0:42:04.12,0:42:05.05,EN,,0,0,0,,And this last part\nDialogue: 0,0:42:06.07,0:42:07.48,EN,,0,0,0,,is coming back from that\nDialogue: 0,0:42:07.87,0:42:09.90,EN,,0,0,0,,and then taking care of the constant case.\nDialogue: 0,0:42:09.90,0:42:13.16,EN,,0,0,0,,So that's about how much code it would produce for factorial.\nDialogue: 0,0:42:13.72,0:42:17.69,EN,,0,0,0,,We could make this compiler much, much better, of course.\nDialogue: 0,0:42:18.67,0:42:21.24,EN,,0,0,0,,The main way we could make it better is\nDialogue: 0,0:42:21.24,0:42:24.00,EN,,0,0,0,,to allow the compiler to make any assumptions at all\nDialogue: 0,0:42:24.35,0:42:26.27,EN,,0,0,0,,about what happens when you call a procedure.\nDialogue: 0,0:42:26.97,0:42:28.28,EN,,0,0,0,,So this compiler, for instance,\nDialogue: 0,0:42:28.30,0:42:32.32,EN,,0,0,0,,doesn't even know, say, that multiplication\nDialogue: 0,0:42:33.12,0:42:36.14,EN,,0,0,0,,you say, is something that could be coded in line.\nDialogue: 0,0:42:36.14,0:42:37.87,EN,,0,0,0,,Instead, it sets up this whole mechanism.\nDialogue: 0,0:42:38.00,0:42:39.34,EN,,0,0,0,,It goes to apply-dispatch.\nDialogue: 0,0:42:41.37,0:42:42.49,EN,,0,0,0,,That's a tremendous waste,\nDialogue: 0,0:42:42.54,0:42:45.02,EN,,0,0,0,,because what you do every time you go to apply-dispatch\nDialogue: 0,0:42:45.02,0:42:46.80,EN,,0,0,0,,is you have to concern about this argument list,\nDialogue: 0,0:42:47.40,0:42:49.10,EN,,0,0,0,,because it's a very general thing you're going to.\nDialogue: 0,0:42:49.13,0:42:51.07,EN,,0,0,0,,In any real compiler, of course,\nDialogue: 0,0:42:51.08,0:42:53.29,EN,,0,0,0,,you're going to have registers for holding arguments.\nDialogue: 0,0:42:53.77,0:42:55.31,EN,,0,0,0,,And you're going to start preserving\nDialogue: 0,0:42:56.38,0:42:58.05,EN,,0,0,0,,saving the way you use those registers\nDialogue: 0,0:42:58.05,0:43:01.61,EN,,0,0,0,,similar to the same strategy here.\nDialogue: 0,0:43:02.85,0:43:05.93,EN,,0,0,0,,So that's probably the very main way\nDialogue: 0,0:43:05.95,0:43:08.30,EN,,0,0,0,,this particular compiler in the book could be fixed.\nDialogue: 0,0:43:08.69,0:43:09.70,EN,,0,0,0,,There are other things like\nDialogue: 0,0:43:09.70,0:43:11.82,EN,,0,0,0,,looking up variable values and\nDialogue: 0,0:43:11.83,0:43:13.87,EN,,0,0,0,,making more efficient primitive operations,\nDialogue: 0,0:43:13.88,0:43:14.56,EN,,0,0,0,,and all sorts of things.\nDialogue: 0,0:43:14.59,0:43:16.60,EN,,0,0,0,,Essentially, a good Lisp compiler\nDialogue: 0,0:43:16.62,0:43:18.49,EN,,0,0,0,,can absorb an arbitrary amount of effort.\nDialogue: 0,0:43:19.72,0:43:21.63,EN,,0,0,0,,And probably one of the reasons\nDialogue: 0,0:43:21.89,0:43:23.04,EN,,0,0,0,,Lisp is slow\nDialogue: 0,0:43:23.63,0:43:25.44,EN,,0,0,0,,with compared to languages like FORTRAN\nDialogue: 0,0:43:25.90,0:43:28.19,EN,,0,0,0,,is that, if you look over history\nDialogue: 0,0:43:28.22,0:43:31.12,EN,,0,0,0,,the amount of effort that's gone into building Lisp compilers,\nDialogue: 0,0:43:31.16,0:43:32.35,EN,,0,0,0,,it's nowhere near the amount of effort\nDialogue: 0,0:43:32.36,0:43:33.90,EN,,0,0,0,,that's gone into FORTRAN compilers.\nDialogue: 0,0:43:34.43,0:43:35.79,EN,,0,0,0,,And maybe that's something that will\nDialogue: 0,0:43:35.92,0:43:37.68,EN,,0,0,0,,that will change over the next couple of years.\nDialogue: 0,0:43:38.00,0:43:38.83,EN,,0,0,0,,OK, let's break.\nDialogue: 0,0:43:43.80,0:43:44.65,EN,,0,0,0,,Questions?\nDialogue: 0,0:43:48.27,0:43:49.95,EN,,0,0,0,,AUDIENCE: One of the very first classes--\nDialogue: 0,0:43:49.95,0:43:51.40,EN,,0,0,0,,I don't know if it was during class or after class-\nDialogue: 0,0:43:51.47,0:43:53.88,EN,,0,0,0,,you showed me the, the\nDialogue: 0,0:43:54.00,0:43:57.52,EN,,0,0,0,,say, addition has a primitive that we don't see,\nDialogue: 0,0:43:57.69,0:43:59.21,EN,,0,0,0,,and-percent add or something like that.\nDialogue: 0,0:43:59.82,0:44:01.65,EN,,0,0,0,,Is that because,\nDialogue: 0,0:44:01.65,0:44:02.60,EN,,0,0,0,,if you're doing inline code\nDialogue: 0,0:44:02.60,0:44:08.19,EN,,0,0,0,,you'd want to just do it for two operators, operands?\nDialogue: 0,0:44:08.70,0:44:10.25,EN,,0,0,0,,But if you had more operands,\nDialogue: 0,0:44:10.28,0:44:11.47,EN,,0,0,0,,you'd want to do something special?\nDialogue: 0,0:44:12.71,0:44:16.04,EN,,0,0,0,,PROFESSOR: Yeah, you're looking in the actual scheme implementation.\nDialogue: 0,0:44:16.06,0:44:17.84,EN,,0,0,0,,There's a plus, and a plus is some operator.\nDialogue: 0,0:44:17.90,0:44:20.19,EN,,0,0,0,,And then if you go look inside the code for plus,\nDialogue: 0,0:44:20.33,0:44:21.37,EN,,0,0,0,,you see something called--\nDialogue: 0,0:44:21.57,0:44:24.14,EN,,0,0,0,,I forget-- and-percent plus or something like that.\nDialogue: 0,0:44:24.55,0:44:25.79,EN,,0,0,0,,And what's going on there is\nDialogue: 0,0:44:25.79,0:44:27.92,EN,,0,0,0,,is that particular kind of optimization.\nDialogue: 0,0:44:28.47,0:44:31.87,EN,,0,0,0,,Because, see, general plus takes an arbitrary number of arguments.\nDialogue: 0,0:44:35.02,0:44:36.38,EN,,0,0,0,,So the most general plus\nDialogue: 0,0:44:36.76,0:44:38.25,EN,,0,0,0,,says, oh, if I have an argument list,\nDialogue: 0,0:44:38.28,0:44:40.62,EN,,0,0,0,,I'd better cons it up in some list\nDialogue: 0,0:44:41.63,0:44:44.14,EN,,0,0,0,,and then figure out how many there were or something like that.\nDialogue: 0,0:44:44.72,0:44:46.16,EN,,0,0,0,,That's terribly inefficient,\nDialogue: 0,0:44:46.81,0:44:49.25,EN,,0,0,0,,especially since most of the time you're probably adding two numbers.\nDialogue: 0,0:44:49.25,0:44:51.24,EN,,0,0,0,,You don't want to really have to cons this argument list.\nDialogue: 0,0:44:52.04,0:44:53.93,EN,,0,0,0,,So what you'd like to do is build\nDialogue: 0,0:44:55.66,0:44:57.71,EN,,0,0,0,,the code for plus with a bunch of entries.\nDialogue: 0,0:44:58.15,0:45:00.17,EN,,0,0,0,,So most of what it's doing is the same.\nDialogue: 0,0:45:00.49,0:45:01.95,EN,,0,0,0,,However, there might be a special entry\nDialogue: 0,0:45:01.98,0:45:03.92,EN,,0,0,0,,that you'd go to if you knew there were only two arguments.\nDialogue: 0,0:45:04.56,0:45:05.87,EN,,0,0,0,,And those you'll put in registers.\nDialogue: 0,0:45:05.87,0:45:06.97,EN,,0,0,0,,they won't be in an argument list\nDialogue: 0,0:45:06.99,0:45:07.98,EN,,0,0,0,,and you won't have to CONS.\nDialogue: 0,0:45:08.67,0:45:10.42,EN,,0,0,0,,That's how a lot of these things work.\nDialogue: 0,0:45:12.30,0:45:13.72,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:00:00.01,0:00:05.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N杨启钊\\N（windfarer）\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:05.37,0:00:11.84,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:11.84,0:00:13.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}编译\nDialogue: 0,0:00:19.36,0:00:22.65,Default,,0,0,0,,教授: 上节课 我们学习了\nDialogue: 0,0:00:22.65,0:00:25.67,Default,,0,0,0,,一个显式控制的Lisp求值器\nDialogue: 0,0:00:25.67,0:00:28.97,Default,,0,0,0,,它弥合了像Lisp\nDialogue: 0,0:00:29.05,0:00:32.14,Default,,0,0,0,,或者查询语言之类的高级语言\nDialogue: 0,0:00:32.50,0:00:36.16,Default,,0,0,0,,与传统寄存器机器之间的鸿沟\nDialogue: 0,0:00:36.70,0:00:40.14,Default,,0,0,0,,事实上 你可以将显式控制求值器\nDialogue: 0,0:00:40.16,0:00:44.38,Default,,0,0,0,,看作是 在一台常见的\nDialogue: 0,0:00:44.40,0:00:45.95,Default,,0,0,0,,寄存机器上实现的\nDialogue: 0,0:00:46.52,0:00:49.50,Default,,0,0,0,,Lisp求值器的汇编代码\nDialogue: 0,0:00:49.50,0:00:51.50,Default,,0,0,0,,或者 你可以把它看做是\nDialogue: 0,0:00:52.08,0:00:54.56,Default,,0,0,0,,某台专门运行Lisp的机器的微程序\nDialogue: 0,0:00:55.20,0:00:55.92,Default,,0,0,0,,无论是那种情况\nDialogue: 0,0:00:55.92,0:00:58.68,Default,,0,0,0,,我们都是把一台\nDialogue: 0,0:00:58.94,0:01:00.51,Default,,0,0,0,,处理低级语言的机器\nDialogue: 0,0:01:01.42,0:01:03.32,Default,,0,0,0,,抬高到一个层次\nDialogue: 0,0:01:03.37,0:01:04.88,Default,,0,0,0,,以便处理像Lisp这样的高级语言\nDialogue: 0,0:01:05.36,0:01:06.35,Default,,0,0,0,,这是通过编写解释器来实现的\nDialogue: 0,0:01:08.22,0:01:09.58,Default,,0,0,0,,来看个例子\nDialogue: 0,0:01:11.82,0:01:13.77,Default,,0,0,0,,这里 从概念上来说\nDialogue: 0,0:01:18.01,0:01:19.47,Default,,0,0,0,,从概念上来说 这是一台\nDialogue: 0,0:01:20.54,0:01:23.44,Default,,0,0,0,,专用于计算阶乘的机器\nDialogue: 0,0:01:24.09,0:01:27.39,Default,,0,0,0,,输入5 输出120\nDialogue: 0,0:01:28.92,0:01:30.83,Default,,0,0,0,,这个专用机器实际上\nDialogue: 0,0:01:30.97,0:01:32.72,Default,,0,0,0,,是一个Lisp解释器\nDialogue: 0,0:01:33.50,0:01:36.17,Default,,0,0,0,,它将自己配置为计算阶乘\nDialogue: 0,0:01:38.35,0:01:40.99,Default,,0,0,0,,因为你向它送入了一台阶乘机器的描述\nDialogue: 0,0:01:42.12,0:01:43.70,Default,,0,0,0,,这就是解释器\nDialogue: 0,0:01:43.70,0:01:45.66,Default,,0,0,0,,它将自己配置为\nDialogue: 0,0:01:46.37,0:01:49.24,Default,,0,0,0,,模拟你所输入描述的机器\nDialogue: 0,0:01:50.07,0:01:51.93,Default,,0,0,0,,那么 在Lisp解释器里是什么?\nDialogue: 0,0:01:52.04,0:01:55.44,Default,,0,0,0,,里面可能是通用的寄存器语言解释器\nDialogue: 0,0:01:56.98,0:02:00.18,Default,,0,0,0,,它将自己配置成像Lisp解释器那样\nDialogue: 0,0:02:00.18,0:02:02.03,Default,,0,0,0,,因为你输入了一系列用寄存器语言\nDialogue: 0,0:02:02.12,0:02:03.04,Default,,0,0,0,,编写的指令\nDialogue: 0,0:02:03.37,0:02:05.16,Default,,0,0,0,,这就是显式控制求值器\nDialogue: 0,0:02:07.05,0:02:08.70,Default,,0,0,0,,它里面也有一些库\nDialogue: 0,0:02:08.73,0:02:11.08,Default,,0,0,0,,由基本运算符和Lisp运算\nDialogue: 0,0:02:11.12,0:02:12.28,Default,,0,0,0,,等等要素组成\nDialogue: 0,0:02:12.75,0:02:16.89,Default,,0,0,0,,这是解释执行的一般策略\nDialogue: 0,0:02:17.32,0:02:18.51,Default,,0,0,0,,事实上 我们所做的是\nDialogue: 0,0:02:18.60,0:02:20.14,Default,,0,0,0,,通过编写解释器\nDialogue: 0,0:02:21.62,0:02:23.40,Default,,0,0,0,,将机器抬升到\nDialogue: 0,0:02:23.42,0:02:25.24,Default,,0,0,0,,我们程序所在的层次\nDialogue: 0,0:02:25.24,0:02:26.72,Default,,0,0,0,,当然 还有另外一种策略\nDialogue: 0,0:02:27.42,0:02:28.89,Default,,0,0,0,,这种不同的策略就是编译\nDialogue: 0,0:02:29.04,0:02:30.43,Default,,0,0,0,,编译有一些不同\nDialogue: 0,0:02:31.04,0:02:31.50,Default,,0,0,0,,这里\nDialogue: 0,0:02:33.37,0:02:34.75,Default,,0,0,0,,我们可能已经实现了\nDialogue: 0,0:02:35.67,0:02:38.52,Default,,0,0,0,,一个特定用途的机器\nDialogue: 0,0:02:38.62,0:02:39.98,Default,,0,0,0,,用来计算阶乘\nDialogue: 0,0:02:43.62,0:02:46.26,Default,,0,0,0,,从某种使用寄存器语言的机器开始\nDialogue: 0,0:02:46.26,0:02:47.72,Default,,0,0,0,,但是 我们将让它执行不同的策略\nDialogue: 0,0:02:47.72,0:02:50.38,Default,,0,0,0,,把我们的阶乘程序\nDialogue: 0,0:02:51.55,0:02:53.92,Default,,0,0,0,,作为源代码输入编译器\nDialogue: 0,0:02:53.92,0:02:55.15,Default,,0,0,0,,编译器就会\nDialogue: 0,0:02:55.15,0:02:57.62,Default,,0,0,0,,把这个阶乘程序\nDialogue: 0,0:02:57.62,0:02:59.07,Default,,0,0,0,,翻译成某种寄存器机器语言\nDialogue: 0,0:03:00.25,0:03:03.40,Default,,0,0,0,,现在它并不是Lisp的显式控制求值器\nDialogue: 0,0:03:03.40,0:03:06.17,Default,,0,0,0,,而是某种用来计算阶乘的寄存器语言\nDialogue: 0,0:03:06.49,0:03:08.36,Default,,0,0,0,,这就是翻译的过程\nDialogue: 0,0:03:10.54,0:03:12.41,Default,,0,0,0,,它将进入某种加载器\nDialogue: 0,0:03:13.35,0:03:15.21,Default,,0,0,0,,它会把这些代码\nDialogue: 0,0:03:15.31,0:03:16.84,Default,,0,0,0,,和从程序库中选取的代码\nDialogue: 0,0:03:16.86,0:03:18.65,Default,,0,0,0,,比如乘法运算等 结合在一起\nDialogue: 0,0:03:19.82,0:03:21.69,Default,,0,0,0,,随后我们将生成一个加载模块\nDialogue: 0,0:03:22.22,0:03:25.06,Default,,0,0,0,,它把寄存器语言机器配置成\nDialogue: 0,0:03:25.06,0:03:27.24,Default,,0,0,0,,一个专门用来计算阶乘的机器\nDialogue: 0,0:03:28.12,0:03:30.22,Default,,0,0,0,,这就是不同的策略\nDialogue: 0,0:03:30.22,0:03:31.22,Default,,0,0,0,,在解释中\nDialogue: 0,0:03:31.22,0:03:32.01,Default,,0,0,0,,我们把机器\nDialogue: 0,0:03:32.91,0:03:35.23,Default,,0,0,0,,抬升到Lisp语言的层次\nDialogue: 0,0:03:35.32,0:03:36.34,Default,,0,0,0,,而在编译中\nDialogue: 0,0:03:36.34,0:03:38.43,Default,,0,0,0,,我们将我们的程序下降到\nDialogue: 0,0:03:38.48,0:03:40.56,Default,,0,0,0,,机器语言的层次\nDialogue: 0,0:03:41.96,0:03:43.84,Default,,0,0,0,,那么 这两个策略有什么区别呢?\nDialogue: 0,0:03:44.30,0:03:49.42,Default,,0,0,0,,编译器可以生成执行起来更有效率的代码\nDialogue: 0,0:03:52.05,0:03:53.90,Default,,0,0,0,,主要原因是\nDialogue: 0,0:03:54.17,0:03:58.89,Default,,0,0,0,,如果你考虑运行中的寄存器操作\nDialogue: 0,0:04:01.92,0:04:04.49,Default,,0,0,0,,解释器需要生成寄存器的操作\nDialogue: 0,0:04:04.97,0:04:06.75,Default,,0,0,0,,从原则上来讲 它需要足够通用\nDialogue: 0,0:04:07.32,0:04:08.94,Default,,0,0,0,,以支持任何Lisp过程的执行\nDialogue: 0,0:04:10.22,0:04:12.25,Default,,0,0,0,,而编译器只需要\nDialogue: 0,0:04:12.27,0:04:14.92,Default,,0,0,0,,生成一组特定的寄存器操作\nDialogue: 0,0:04:15.52,0:04:18.22,Default,,0,0,0,,用来执行你所编译的那部分特定的Lisp过程\nDialogue: 0,0:04:20.17,0:04:21.20,Default,,0,0,0,,换一种说法\nDialogue: 0,0:04:21.20,0:04:25.31,Default,,0,0,0,,解释器是一种通用的模拟器\nDialogue: 0,0:04:25.92,0:04:27.58,Default,,0,0,0,,当你输入一个Lisp过程时\nDialogue: 0,0:04:27.58,0:04:31.32,Default,,0,0,0,,它们就会模拟那个过程所描述的程序\nDialogue: 0,0:04:31.32,0:04:33.87,Default,,0,0,0,,所以解释器旨在成为一个通用模拟器\nDialogue: 0,0:04:34.62,0:04:35.96,Default,,0,0,0,,而编译器 实际上\nDialogue: 0,0:04:36.00,0:04:37.68,Default,,0,0,0,,只需要将东西配置成\nDialogue: 0,0:04:37.71,0:04:39.34,Default,,0,0,0,,解释器将要去模拟的机器\nDialogue: 0,0:04:40.02,0:04:41.34,Default,,0,0,0,,所以编译器可以运行得更快\nDialogue: 0,0:04:52.55,0:04:53.64,Default,,0,0,0,,另一方面\nDialogue: 0,0:04:55.97,0:04:58.28,Default,,0,0,0,,解释器更适合用来排查错误\nDialogue: 0,0:04:59.43,0:05:01.25,Default,,0,0,0,,这是因为\nDialogue: 0,0:05:01.57,0:05:03.02,Default,,0,0,0,,我们的源代码实际上就在那里\nDialogue: 0,0:05:03.02,0:05:04.81,Default,,0,0,0,,我们正在解释它们\nDialogue: 0,0:05:05.87,0:05:07.69,Default,,0,0,0,,并且库也在其中\nDialogue: 0,0:05:07.90,0:05:10.89,Default,,0,0,0,,看 库是解释器的一部分\nDialogue: 0,0:05:11.30,0:05:13.16,Default,,0,0,0,,而编译器只会拉取\nDialogue: 0,0:05:13.20,0:05:14.56,Default,,0,0,0,,运行程序所需要的代码\nDialogue: 0,0:05:14.87,0:05:17.00,Default,,0,0,0,,所以 如果你在排查错误的途中\nDialogue: 0,0:05:18.00,0:05:20.72,Default,,0,0,0,,你想写一些额外的代码\nDialogue: 0,0:05:20.80,0:05:22.57,Default,,0,0,0,,来考察运行过程中的数据类型\nDialogue: 0,0:05:23.05,0:05:24.25,Default,,0,0,0,,或者做一些\nDialogue: 0,0:05:24.30,0:05:25.92,Default,,0,0,0,,在写程序时没有想到的计算\nDialogue: 0,0:05:25.95,0:05:27.53,Default,,0,0,0,,解释器可以完美搞定这些\nDialogue: 0,0:05:28.05,0:05:29.21,Default,,0,0,0,,而编译器不行\nDialogue: 0,0:05:29.62,0:05:31.90,Default,,0,0,0,,所以它们各有优点\nDialogue: 0,0:05:31.90,0:05:34.48,Default,,0,0,0,,编译器将生成运行更快的代码\nDialogue: 0,0:05:34.85,0:05:37.02,Default,,0,0,0,,而解释器是一种更适合排错的环境\nDialogue: 0,0:05:38.95,0:05:41.40,Default,,0,0,0,,大多数Lisp系统最终将二者都实现了\nDialogue: 0,0:05:42.92,0:05:45.23,Default,,0,0,0,,这样你就可以在开发阶段\nDialogue: 0,0:05:45.24,0:05:47.08,Default,,0,0,0,,可以使用解释器\nDialogue: 0,0:05:47.08,0:05:48.62,Default,,0,0,0,,随后通过编译加速代码的运行\nDialogue: 0,0:05:49.02,0:05:50.03,Default,,0,0,0,,并且通常\nDialogue: 0,0:05:50.04,0:05:51.68,Default,,0,0,0,,你能够让被编译的代码\nDialogue: 0,0:05:51.69,0:05:53.56,Default,,0,0,0,,和被解释的代码互相调用\nDialogue: 0,0:05:54.60,0:05:56.33,Default,,0,0,0,,我们将学习如何做到 其实不难\nDialogue: 0,0:05:59.27,0:05:59.85,Default,,0,0,0,,好\nDialogue: 0,0:06:00.97,0:06:02.09,Default,,0,0,0,,事实上\nDialogue: 0,0:06:04.30,0:06:05.75,Default,,0,0,0,,在我们将要构建的编译器中\nDialogue: 0,0:06:05.75,0:06:07.58,Default,,0,0,0,,我们实现编译的代码和解释的代码\nDialogue: 0,0:06:07.58,0:06:09.45,Default,,0,0,0,,互相调用的方式是\nDialogue: 0,0:06:09.90,0:06:12.06,Default,,0,0,0,,我们让编译器和解释器使用\nDialogue: 0,0:06:12.11,0:06:14.40,Default,,0,0,0,,使用完全一致的寄存器约定\nDialogue: 0,0:06:18.42,0:06:21.72,Default,,0,0,0,,编译器的理念\nDialogue: 0,0:06:21.76,0:06:25.74,Default,,0,0,0,,与解释器或求值器的理念很像\nDialogue: 0,0:06:25.87,0:06:26.46,Default,,0,0,0,,它们是相同的\nDialogue: 0,0:06:27.05,0:06:29.39,Default,,0,0,0,,求值器遍历代码\nDialogue: 0,0:06:29.82,0:06:32.35,Default,,0,0,0,,产生一些寄存器操作\nDialogue: 0,0:06:33.65,0:06:34.97,Default,,0,0,0,,就是我们昨天做的事情\nDialogue: 0,0:06:37.10,0:06:40.27,Default,,0,0,0,,而编译器会读取代码\nDialogue: 0,0:06:40.52,0:06:43.00,Default,,0,0,0,,生成一些进行求值时\nDialogue: 0,0:06:43.04,0:06:44.67,Default,,0,0,0,,求值器会进行的\nDialogue: 0,0:06:45.23,0:06:46.64,Default,,0,0,0,,相关寄存器操作\nDialogue: 0,0:06:48.60,0:06:49.95,Default,,0,0,0,,这就给我们提供了一个模型\nDialogue: 0,0:06:50.60,0:06:53.77,Default,,0,0,0,,来实现一个零阶编译器\nDialogue: 0,0:06:55.30,0:06:58.32,Default,,0,0,0,,一个很差劲但是能用的编译器\nDialogue: 0,0:06:58.32,0:06:59.32,Default,,0,0,0,,这种模型就是\nDialogue: 0,0:06:59.36,0:07:00.59,Default,,0,0,0,,你用求值器\nDialogue: 0,0:07:00.68,0:07:01.88,Default,,0,0,0,,把代码跑一遍\nDialogue: 0,0:07:02.80,0:07:06.06,Default,,0,0,0,,但不去执行实际的操作\nDialogue: 0,0:07:06.06,0:07:07.15,Default,,0,0,0,,只是把它们保存下来\nDialogue: 0,0:07:07.55,0:07:08.82,Default,,0,0,0,,那就是你编译后的代码\nDialogue: 0,0:07:08.82,0:07:10.24,Default,,0,0,0,,让我举个例子\nDialogue: 0,0:07:12.70,0:07:14.14,Default,,0,0,0,,假设我们要编译\nDialogue: 0,0:07:15.10,0:07:17.90,Default,,0,0,0,,编译(F X) 这个表达式\nDialogue: 0,0:07:25.07,0:07:25.96,Default,,0,0,0,,我们假设\nDialogue: 0,0:07:25.96,0:07:28.06,Default,,0,0,0,,EXP寄存器中保存着(F X)\nDialogue: 0,0:07:28.06,0:07:29.55,Default,,0,0,0,,而ENV寄存器又保存着其它东西\nDialogue: 0,0:07:30.10,0:07:32.20,Default,,0,0,0,,想象我们启动了求值器\nDialogue: 0,0:07:34.60,0:07:35.71,Default,,0,0,0,,它读取了表达式\nDialogue: 0,0:07:35.71,0:07:37.36,Default,,0,0,0,,判断它是一个应用\nDialogue: 0,0:07:37.92,0:07:41.90,Default,,0,0,0,,它分支到求值器代码中的一个地方\nDialogue: 0,0:07:42.52,0:07:45.15,Default,,0,0,0,,我们之前见过的叫EV-APPLICATION的地方\nDialogue: 0,0:07:47.12,0:07:48.12,Default,,0,0,0,,然后继续处理\nDialogue: 0,0:07:48.16,0:07:50.08,Default,,0,0,0,,恢复运算对象和UNEV\nDialogue: 0,0:07:50.08,0:07:52.44,Default,,0,0,0,,然后之后它将运算符放在EXP寄存器中\nDialogue: 0,0:07:52.48,0:07:54.27,Default,,0,0,0,,递归地对它求值\nDialogue: 0,0:07:54.47,0:07:56.08,Default,,0,0,0,,这就是我们经历的过程\nDialogue: 0,0:07:56.67,0:07:57.84,Default,,0,0,0,,如果你看代码\nDialogue: 0,0:07:57.87,0:07:59.74,Default,,0,0,0,,会看到一些寄存器操作\nDialogue: 0,0:08:00.20,0:08:02.30,Default,,0,0,0,,你会看到将运算对象赋值给UNEV寄存器\nDialogue: 0,0:08:02.30,0:08:03.95,Default,,0,0,0,,把运算符赋值给EXP\nDialogue: 0,0:08:04.09,0:08:06.20,Default,,0,0,0,,保存环境、生成新环境 等等\nDialogue: 0,0:08:10.22,0:08:11.93,Default,,0,0,0,,如果我们来看下这里的投影\nDialogue: 0,0:08:15.75,0:08:19.58,Default,,0,0,0,,我们会看到产生的这些操作\nDialogue: 0,0:08:20.82,0:08:22.52,Default,,0,0,0,,这是求值器实际要进行的\nDialogue: 0,0:08:22.72,0:08:24.80,Default,,0,0,0,,第一个操作\nDialogue: 0,0:08:25.00,0:08:27.20,Default,,0,0,0,,它将运算对象从EXP寄存器里取出来\nDialogue: 0,0:08:27.47,0:08:28.62,Default,,0,0,0,,并将它赋值给UNEV\nDialogue: 0,0:08:30.03,0:08:32.27,Default,,0,0,0,,然后它给EXP寄存器赋了某个值\nDialogue: 0,0:08:32.30,0:08:33.46,Default,,0,0,0,,然后保存CONTINUE\nDialogue: 0,0:08:33.46,0:08:34.62,Default,,0,0,0,,保存ENV\nDialogue: 0,0:08:34.62,0:08:38.65,Default,,0,0,0,,我在这里就只是寄存器赋值\nDialogue: 0,0:08:39.57,0:08:42.32,Default,,0,0,0,,这就是求值器求值代码时进行的操作\nDialogue: 0,0:08:42.77,0:08:43.79,Default,,0,0,0,,我们缩小画面看看\nDialogue: 0,0:08:44.30,0:08:47.13,Default,,0,0,0,,总计有19个操作\nDialogue: 0,0:08:49.40,0:08:51.64,Default,,0,0,0,,这些代码\nDialogue: 0,0:08:52.05,0:08:53.90,Default,,0,0,0,,对应着\nDialogue: 0,0:08:54.75,0:08:57.10,Default,,0,0,0,,求值器跳转到APPLY-DISPATCH代码之前\nDialogue: 0,0:08:57.86,0:08:59.16,Default,,0,0,0,,事实上 在这个编译器中\nDialogue: 0,0:08:59.20,0:09:01.18,Default,,0,0,0,,我们不需要再关心APPLY-DISPATCH了\nDialogue: 0,0:09:01.30,0:09:02.11,Default,,0,0,0,,我们有所有东西\nDialogue: 0,0:09:02.35,0:09:05.04,Default,,0,0,0,,我们拥有解释后和编译后的所有代码\nDialogue: 0,0:09:06.07,0:09:07.61,Default,,0,0,0,,通常求值过程\nDialogue: 0,0:09:07.61,0:09:09.85,Default,,0,0,0,,是由APPLY-DISPATCH处理的\nDialogue: 0,0:09:10.27,0:09:12.32,Default,,0,0,0,,这将让被解释后代码与编译后代码\nDialogue: 0,0:09:12.36,0:09:13.71,Default,,0,0,0,,很容易互相调用\nDialogue: 0,0:09:18.27,0:09:19.87,Default,,0,0,0,,从原理上来说 这样做足矣\nDialogue: 0,0:09:21.05,0:09:22.66,Default,,0,0,0,,只需运行求值器\nDialogue: 0,0:09:22.66,0:09:24.50,Default,,0,0,0,,因而编译器非常像求值器\nDialogue: 0,0:09:24.50,0:09:26.47,Default,,0,0,0,,你运行它 唯一不同是你把操作存下来\nDialogue: 0,0:09:26.47,0:09:28.40,Default,,0,0,0,,而不是实际执行它们\nDialogue: 0,0:09:29.35,0:09:31.39,Default,,0,0,0,,这其实不完全正确\nDialogue: 0,0:09:32.91,0:09:34.99,Default,,0,0,0,,这里面我们撒了个小谎\nDialogue: 0,0:09:36.24,0:09:39.29,Default,,0,0,0,,你需要关心的是：如果有个谓词\nDialogue: 0,0:09:40.12,0:09:42.16,Default,,0,0,0,,如果你要进行某种测试\nDialogue: 0,0:09:43.45,0:09:46.03,Default,,0,0,0,,显然 在你编译时\nDialogue: 0,0:09:46.52,0:09:47.98,Default,,0,0,0,,你不知道这些分支中\nDialogue: 0,0:09:48.32,0:09:50.14,Default,,0,0,0,,哪条分支会被执行\nDialogue: 0,0:09:51.13,0:09:53.92,Default,,0,0,0,,所以你不能确定求值器将对哪个求值\nDialogue: 0,0:09:54.90,0:09:57.12,Default,,0,0,0,,因此在这里就很简单\nDialogue: 0,0:09:57.12,0:09:58.49,Default,,0,0,0,,你把两个分支全编译了\nDialogue: 0,0:09:59.32,0:10:01.29,Default,,0,0,0,,因此你编译出一个这样的结构\nDialogue: 0,0:10:02.00,0:10:03.98,Default,,0,0,0,,它们都会被编译成\nDialogue: 0,0:10:05.31,0:10:09.15,Default,,0,0,0,,首先是P的代码\nDialogue: 0,0:10:10.71,0:10:16.51,Default,,0,0,0,,它把结果存入VAL寄存器\nDialogue: 0,0:10:18.17,0:10:20.64,Default,,0,0,0,,解释器对谓词求值\nDialogue: 0,0:10:21.35,0:10:24.19,Default,,0,0,0,,并保证结果会放到VAL寄存器中\nDialogue: 0,0:10:24.70,0:10:27.22,Default,,0,0,0,,随后你编译一条指令\nDialogue: 0,0:10:27.22,0:10:33.79,Default,,0,0,0,,如果VAL是TRUE\nDialogue: 0,0:10:37.17,0:10:38.75,Default,,0,0,0,,就转到LABEL1这个地方\nDialogue: 0,0:10:44.97,0:10:47.52,Default,,0,0,0,,然后我们写下B的代码\nDialogue: 0,0:10:49.42,0:10:52.32,Default,,0,0,0,,让解释器对B进行求值\nDialogue: 0,0:10:53.62,0:10:57.21,Default,,0,0,0,,然后写一句指令\nDialogue: 0,0:10:57.23,0:10:58.75,Default,,0,0,0,,用来跳转到下一条指令\nDialogue: 0,0:11:02.20,0:11:04.56,Default,,0,0,0,,就是它结束之后要去的地方\nDialogue: 0,0:11:04.95,0:11:06.09,Default,,0,0,0,,你放入那个指令\nDialogue: 0,0:11:06.88,0:11:08.62,Default,,0,0,0,,这里你写下LABEL1\nDialogue: 0,0:11:12.12,0:11:13.80,Default,,0,0,0,,这里写A的代码\nDialogue: 0,0:11:19.47,0:11:25.85,Default,,0,0,0,,然后又是跳转到下一条指令\nDialogue: 0,0:11:31.42,0:11:32.88,Default,,0,0,0,,这就是处理条件分支的办法\nDialogue: 0,0:11:32.98,0:11:34.65,Default,,0,0,0,,你生成一小段这样的代码\nDialogue: 0,0:11:35.75,0:11:38.12,Default,,0,0,0,,除此之外\nDialogue: 0,0:11:38.95,0:11:41.55,Default,,0,0,0,,这个零阶编译器与求值器一模一样\nDialogue: 0,0:11:42.55,0:11:45.12,Default,,0,0,0,,它只是把指令存起来 而不执行它们\nDialogue: 0,0:11:46.55,0:11:47.60,Default,,0,0,0,,看起来很简单\nDialogue: 0,0:11:47.64,0:11:49.08,Default,,0,0,0,,但我们已经取得了某些收获\nDialogue: 0,0:11:50.12,0:11:52.62,Default,,0,0,0,,它会比求值器更有效率\nDialogue: 0,0:11:53.52,0:11:56.14,Default,,0,0,0,,因为 如果你观察求值器的运行\nDialogue: 0,0:11:56.35,0:12:01.05,Default,,0,0,0,,它并不只是进行寄存器操作\nDialogue: 0,0:12:01.27,0:12:03.50,Default,,0,0,0,,它还会决定执行哪个\nDialogue: 0,0:12:04.70,0:12:07.23,Default,,0,0,0,,它做的第一件事就是\nDialogue: 0,0:12:07.92,0:12:09.77,Default,,0,0,0,,以它为例 就是进行某些测试\nDialogue: 0,0:12:09.77,0:12:11.56,Default,,0,0,0,,确定它是一个应用\nDialogue: 0,0:12:13.57,0:12:15.05,Default,,0,0,0,,然后就跳转到\nDialogue: 0,0:12:15.39,0:12:16.62,Default,,0,0,0,,处理应用的地方去\nDialogue: 0,0:12:16.62,0:12:18.44,Default,,0,0,0,,换句话说 求值器做的事情是\nDialogue: 0,0:12:18.62,0:12:22.76,Default,,0,0,0,,分析代码需要进行的运算\nDialogue: 0,0:12:23.47,0:12:24.99,Default,,0,0,0,,同时并执行它们\nDialogue: 0,0:12:25.55,0:12:28.28,Default,,0,0,0,,当你运行求值器一百万次\nDialogue: 0,0:12:28.28,0:12:30.30,Default,,0,0,0,,这个分析过程就进行一百万次\nDialogue: 0,0:12:30.85,0:12:32.58,Default,,0,0,0,,而在编译器中 它只会进行一次\nDialogue: 0,0:12:32.58,0:12:34.81,Default,,0,0,0,,之后就只有寄存器操作了\nDialogue: 0,0:12:39.20,0:12:41.68,Default,,0,0,0,,这就是零阶编译器了\nDialogue: 0,0:12:41.80,0:12:44.04,Default,,0,0,0,,但它是个拙劣的编译器\nDialogue: 0,0:12:44.45,0:12:45.28,Default,,0,0,0,,它挺蠢的\nDialogue: 0,0:12:46.90,0:12:48.41,Default,,0,0,0,,让我们回过头来\nDialogue: 0,0:12:49.88,0:12:50.97,Default,,0,0,0,,看看这张投影\nDialogue: 0,0:12:52.02,0:12:55.29,Default,,0,0,0,,看看这个东西做的一些操作\nDialogue: 0,0:12:55.85,0:12:56.88,Default,,0,0,0,,我们想看看\nDialogue: 0,0:12:59.72,0:13:02.28,Default,,0,0,0,,在解释(F  X)时的操作\nDialogue: 0,0:13:03.52,0:13:04.84,Default,,0,0,0,,这里就是它做了什么\nDialogue: 0,0:13:05.17,0:13:06.11,Default,,0,0,0,,举个例子 这里\nDialogue: 0,0:13:07.15,0:13:11.98,Default,,0,0,0,,它将(OPERATOR (FETCH EXP))赋值给EXP\nDialogue: 0,0:13:13.75,0:13:15.87,Default,,0,0,0,,其实没必要这样做\nDialogue: 0,0:13:16.22,0:13:17.47,Default,,0,0,0,,因为编译器知道\nDialogue: 0,0:13:17.66,0:13:21.84,Default,,0,0,0,,(OPERATOR (FETCH EXP))的值就是F\nDialogue: 0,0:13:23.35,0:13:25.56,Default,,0,0,0,,因此这个指令没理由存在\nDialogue: 0,0:13:25.70,0:13:28.88,Default,,0,0,0,,应该改为：要把F赋值给EXP\nDialogue: 0,0:13:29.45,0:13:31.08,Default,,0,0,0,,或者实际上 你完全不需要EXP\nDialogue: 0,0:13:31.87,0:13:33.56,Default,,0,0,0,,没有理由需要EXP\nDialogue: 0,0:13:33.56,0:13:35.16,Default,,0,0,0,,EXP是用来做什么的?\nDialogue: 0,0:13:35.18,0:13:36.33,Default,,0,0,0,,我们看这里\nDialogue: 0,0:13:40.77,0:13:42.20,Default,,0,0,0,,我们对VAL赋值\nDialogue: 0,0:13:43.05,0:13:47.34,Default,,0,0,0,,在环境里的EXP里寻找东西\nDialogue: 0,0:13:48.68,0:13:49.53,Default,,0,0,0,,因此 我们实际上是要\nDialogue: 0,0:13:49.55,0:13:51.54,Default,,0,0,0,,替换掉所有的EXP寄存器\nDialogue: 0,0:13:51.54,0:13:53.32,Default,,0,0,0,,把这个指令修改为\nDialogue: 0,0:13:53.34,0:13:54.16,Default,,0,0,0,,给VAL赋值\nDialogue: 0,0:13:54.45,0:13:56.06,Default,,0,0,0,,在环境中查找\nDialogue: 0,0:13:56.36,0:13:58.40,Default,,0,0,0,,符号F的值\nDialogue: 0,0:14:01.09,0:14:01.77,Default,,0,0,0,,类似地\nDialogue: 0,0:14:02.57,0:14:04.27,Default,,0,0,0,,回到这里 我们也完全不需要UNEV\nDialogue: 0,0:14:04.72,0:14:05.79,Default,,0,0,0,,因为我们知道\nDialogue: 0,0:14:06.22,0:14:09.16,Default,,0,0,0,,因为我们知道 (FETCH EXP)取出的运算对象\nDialogue: 0,0:14:09.16,0:14:10.62,Default,,0,0,0,,就是'(X)\nDialogue: 0,0:14:13.25,0:14:14.06,Default,,0,0,0,,从某种意义上来说\nDialogue: 0,0:14:16.17,0:14:19.39,Default,,0,0,0,,你完全不需要UNEV和EXP\nDialogue: 0,0:14:19.67,0:14:21.05,Default,,0,0,0,,看看它们实际上是什么\nDialogue: 0,0:14:21.08,0:14:25.30,Default,,0,0,0,,它们不是实际运行机器的寄存器\nDialogue: 0,0:14:25.30,0:14:26.40,Default,,0,0,0,,它们实际上是\nDialogue: 0,0:14:26.60,0:14:29.50,Default,,0,0,0,,为了模拟该机器的而设置的寄存器\nDialogue: 0,0:14:30.72,0:14:33.77,Default,,0,0,0,,所以它们保存一些表达式\nDialogue: 0,0:14:34.00,0:14:36.04,Default,,0,0,0,,以编译器的视角看来\nDialogue: 0,0:14:36.06,0:14:36.81,Default,,0,0,0,,它们就是常量\nDialogue: 0,0:14:36.95,0:14:38.48,Default,,0,0,0,,因此可以直接把它们放到代码中\nDialogue: 0,0:14:39.47,0:14:41.34,Default,,0,0,0,,你可以忘掉那些关于\nDialogue: 0,0:14:41.36,0:14:42.54,Default,,0,0,0,,EXP和UNEV的操作\nDialogue: 0,0:14:42.57,0:14:43.77,Default,,0,0,0,,只用那些常量\nDialogue: 0,0:14:44.02,0:14:48.00,Default,,0,0,0,,与之相似 如果我们回顾这里\nDialogue: 0,0:14:48.00,0:14:51.32,Default,,0,0,0,,有像(ASSIGN CONTINUE EVAL-ARGS)之类的语句\nDialogue: 0,0:14:53.75,0:14:55.39,Default,,0,0,0,,现在 它和任何东西都没有关系\nDialogue: 0,0:14:55.62,0:14:57.76,Default,,0,0,0,,它只是求值器\nDialogue: 0,0:14:58.08,0:15:00.17,Default,,0,0,0,,维护了下一步需要去哪\nDialogue: 0,0:15:02.70,0:15:05.96,Default,,0,0,0,,在某些应用中对参数进行求值\nDialogue: 0,0:15:06.82,0:15:08.65,Default,,0,0,0,,当然 这与编译器没关系\nDialogue: 0,0:15:08.65,0:15:13.88,Default,,0,0,0,,因为这个分析过程已经被编译器做完了\nDialogue: 0,0:15:15.05,0:15:16.83,Default,,0,0,0,,所以编译后的代码完全不需要它\nDialogue: 0,0:15:17.70,0:15:19.32,Default,,0,0,0,,因此许多向CONTINUE寄存器\nDialogue: 0,0:15:19.32,0:15:21.30,Default,,0,0,0,,赋值的操作都是无用的\nDialogue: 0,0:15:21.30,0:15:24.62,Default,,0,0,0,,运行着的机器留着它们\nDialogue: 0,0:15:24.64,0:15:25.77,Default,,0,0,0,,是为了跟踪它的状态\nDialogue: 0,0:15:26.07,0:15:28.72,Default,,0,0,0,,是为了知道求值器的下一步分析\nDialogue: 0,0:15:28.72,0:15:30.03,Default,,0,0,0,,而它们是完全无关的\nDialogue: 0,0:15:30.06,0:15:31.23,Default,,0,0,0,,因此我们可以去掉它们\nDialogue: 0,0:15:43.90,0:15:45.98,Default,,0,0,0,,那么 如果我们简单地\nDialogue: 0,0:15:46.16,0:15:47.75,Default,,0,0,0,,进行这类优化\nDialogue: 0,0:15:47.75,0:15:51.64,Default,,0,0,0,,不再考虑EXP和UNEV\nDialogue: 0,0:15:51.75,0:15:56.22,Default,,0,0,0,,去掉这些无关的寄存器赋值\nDialogue: 0,0:15:57.25,0:15:59.96,Default,,0,0,0,,我们就可以找到这些代码\nDialogue: 0,0:16:01.48,0:16:06.20,Default,,0,0,0,,也就是求值器会执行的这19条指令\nDialogue: 0,0:16:06.91,0:16:08.12,Default,,0,0,0,,给替换掉\nDialogue: 0,0:16:08.36,0:16:10.33,Default,,0,0,0,,请看幻灯片\nDialogue: 0,0:16:12.27,0:16:15.34,Default,,0,0,0,,我们去掉了大概一半\nDialogue: 0,0:16:18.28,0:16:20.75,Default,,0,0,0,,同样 这就是某种过滤\nDialogue: 0,0:16:21.07,0:16:24.46,Default,,0,0,0,,把无关的东西去掉\nDialogue: 0,0:16:25.17,0:16:26.22,Default,,0,0,0,,你们看 比如说\nDialogue: 0,0:16:27.47,0:16:29.66,Default,,0,0,0,,这里 求值器说\nDialogue: 0,0:16:29.68,0:16:32.43,Default,,0,0,0,,(ASSIGN VAL (LOOKUP 'F (FETCH ENV)))\nDialogue: 0,0:16:32.46,0:16:34.22,Default,,0,0,0,,这里 我们放入了一个常量F\nDialogue: 0,0:16:35.44,0:16:37.02,Default,,0,0,0,,这里又放了一个常量X\nDialogue: 0,0:16:40.02,0:16:42.41,Default,,0,0,0,,因此 这个编译器又稍微好一点\nDialogue: 0,0:16:43.79,0:16:46.76,Default,,0,0,0,,但它还是比较蠢\nDialogue: 0,0:16:47.95,0:16:49.58,Default,,0,0,0,,它仍会做很多蠢事\nDialogue: 0,0:16:50.45,0:16:52.52,Default,,0,0,0,,我们再看幻灯片\nDialogue: 0,0:16:52.88,0:16:53.93,Default,,0,0,0,,看最开头的地方\nDialogue: 0,0:16:56.34,0:16:58.17,Default,,0,0,0,,我们调用(SAVE ENV)保存环境\nDialogue: 0,0:16:59.35,0:17:01.72,Default,,0,0,0,,然后给VAL寄存器赋某个值\nDialogue: 0,0:17:01.80,0:17:03.35,Default,,0,0,0,,然后恢复环境\nDialogue: 0,0:17:03.35,0:17:04.41,Default,,0,0,0,,它是从哪来的\nDialogue: 0,0:17:04.91,0:17:07.10,Default,,0,0,0,,它来自求值器的这个地方\nDialogue: 0,0:17:07.15,0:17:10.28,Default,,0,0,0,,哦 我在正在对一个应用求值\nDialogue: 0,0:17:11.10,0:17:14.68,Default,,0,0,0,,因此我要递归调用EVAL-DISPATCH\nDialogue: 0,0:17:15.87,0:17:17.98,Default,,0,0,0,,我最好把接下来要用到的东西\nDialogue: 0,0:17:17.98,0:17:19.08,Default,,0,0,0,,保存到环境中\nDialogue: 0,0:17:19.77,0:17:22.86,Default,,0,0,0,,这就是递归调用EVAL-DISPATCH的结果\nDialogue: 0,0:17:23.47,0:17:25.77,Default,,0,0,0,,刚才那个例子就是对符号F求值的结果\nDialogue: 0,0:17:26.50,0:17:28.27,Default,,0,0,0,,从EVAL-DISPATCH中返回\nDialogue: 0,0:17:28.28,0:17:29.66,Default,,0,0,0,,将环境恢复\nDialogue: 0,0:17:31.25,0:17:32.28,Default,,0,0,0,,但是实际上\nDialogue: 0,0:17:32.59,0:17:35.88,Default,,0,0,0,,这个求值过程中 所进行的操作\nDialogue: 0,0:17:35.92,0:17:37.71,Default,,0,0,0,,完全不会影响环境\nDialogue: 0,0:17:38.67,0:17:40.80,Default,,0,0,0,,所以这里没必要先保存环境\nDialogue: 0,0:17:40.84,0:17:42.22,Default,,0,0,0,,再恢复环境\nDialogue: 0,0:17:45.67,0:17:46.62,Default,,0,0,0,,与之类似\nDialogue: 0,0:17:49.79,0:17:51.39,Default,,0,0,0,,这里 我们保存了参数表\nDialogue: 0,0:17:53.07,0:17:55.80,Default,,0,0,0,,那是一个求值参数的循环\nDialogue: 0,0:17:55.82,0:17:56.86,Default,,0,0,0,,先保存参数表\nDialogue: 0,0:17:57.20,0:17:58.03,Default,,0,0,0,,然后在这里恢复\nDialogue: 0,0:17:58.08,0:18:00.51,Default,,0,0,0,,但事实上最后\nDialogue: 0,0:18:00.80,0:18:02.28,Default,,0,0,0,,并没有变更参数表\nDialogue: 0,0:18:02.84,0:18:04.17,Default,,0,0,0,,所以不需要保存它\nDialogue: 0,0:18:08.65,0:18:12.88,Default,,0,0,0,,换种方式来说\nDialogue: 0,0:18:13.77,0:18:14.80,Default,,0,0,0,,怎么说呢\nDialogue: 0,0:18:16.43,0:18:19.13,Default,,0,0,0,,求值器需要最大限度地保持悲观\nDialogue: 0,0:18:19.87,0:18:21.07,Default,,0,0,0,,因为 从它的视角来看\nDialogue: 0,0:18:21.08,0:18:23.06,Default,,0,0,0,,只知道接下来是要对某些东西进行求值\nDialogue: 0,0:18:23.24,0:18:24.97,Default,,0,0,0,,所以最好把稍后要用的都存下来\nDialogue: 0,0:18:26.12,0:18:27.79,Default,,0,0,0,,一旦你完成了分析\nDialogue: 0,0:18:27.82,0:18:29.68,Default,,0,0,0,,从编译器的角度就会考虑\nDialogue: 0,0:18:29.72,0:18:31.47,Default,,0,0,0,,哪些是我真正需要存下来的?\nDialogue: 0,0:18:32.12,0:18:33.31,Default,,0,0,0,,我们需要去 --\nDialogue: 0,0:18:33.42,0:18:37.30,Default,,0,0,0,,它不需要像求值器一样小心翼翼\nDialogue: 0,0:18:37.30,0:18:38.80,Default,,0,0,0,,因为它知道 实际需要什么\nDialogue: 0,0:18:39.69,0:18:41.16,Default,,0,0,0,,无论如何 如果我们完成了优化\nDialogue: 0,0:18:42.50,0:18:45.71,Default,,0,0,0,,消除掉所有多余的保存和恢复\nDialogue: 0,0:18:46.40,0:18:49.05,Default,,0,0,0,,那么我们可以得到这样的结果\nDialogue: 0,0:18:49.90,0:18:51.53,Default,,0,0,0,,我们可以发现\nDialogue: 0,0:18:51.64,0:18:53.71,Default,,0,0,0,,只有三条指令是必须的\nDialogue: 0,0:18:54.07,0:18:55.72,Default,,0,0,0,,从刚才的11条指令优化成这样\nDialogue: 0,0:18:55.97,0:18:58.81,Default,,0,0,0,,或是从原始的20条指令优化而来\nDialogue: 0,0:18:59.87,0:19:00.92,Default,,0,0,0,,这告诉我们\nDialogue: 0,0:19:01.12,0:19:03.18,Default,,0,0,0,,对于这些寄存器操作\nDialogue: 0,0:19:03.27,0:19:04.94,Default,,0,0,0,,哪些是必需的?\nDialogue: 0,0:19:09.42,0:19:11.74,Default,,0,0,0,,让我换个方式来总结一下\nDialogue: 0,0:19:11.74,0:19:13.48,Default,,0,0,0,,我先给你们看一张图\nDialogue: 0,0:19:16.00,0:19:17.52,Default,,0,0,0,,这张图片\nDialogue: 0,0:19:18.77,0:19:20.81,Default,,0,0,0,,展示了所有的保存和恢复\nDialogue: 0,0:19:23.50,0:19:25.23,Default,,0,0,0,,这里是表达式(F X)\nDialogue: 0,0:19:25.32,0:19:27.87,Default,,0,0,0,,在下面这里\nDialogue: 0,0:19:28.75,0:19:31.80,Default,,0,0,0,,是对求值器中各种地方的跟踪\nDialogue: 0,0:19:34.97,0:19:38.04,Default,,0,0,0,,在求值发生时会使用这些地方\nDialogue: 0,0:19:38.04,0:19:40.01,Default,,0,0,0,,在这里 你可以看到箭头\nDialogue: 0,0:19:40.22,0:19:42.08,Default,,0,0,0,,下箭头代表寄存器的保存\nDialogue: 0,0:19:42.40,0:19:44.84,Default,,0,0,0,,所以最先保存的是ENV寄存器\nDialogue: 0,0:19:46.82,0:19:48.68,Default,,0,0,0,,然后 在这里恢复ENV\nDialogue: 0,0:19:52.38,0:19:54.54,Default,,0,0,0,,这些都是成对的栈操作\nDialogue: 0,0:19:56.12,0:19:57.56,Default,,0,0,0,,如果你更进一步\nDialogue: 0,0:19:58.12,0:20:00.78,Default,,0,0,0,,我们记得\nDialogue: 0,0:20:00.89,0:20:03.02,Default,,0,0,0,,UNEV是个完全没用的寄存器\nDialogue: 0,0:20:07.80,0:20:09.78,Default,,0,0,0,,如果我们用固定结构的代码\nDialogue: 0,0:20:09.78,0:20:12.52,Default,,0,0,0,,就不需要保存UNEV 因为完全用不上\nDialogue: 0,0:20:16.20,0:20:19.15,Default,,0,0,0,,然后 根据我们约定的\nDialogue: 0,0:20:19.16,0:20:21.88,Default,,0,0,0,,应用过程的准则\nDialogue: 0,0:20:21.88,0:20:23.85,Default,,0,0,0,,我们会选择是否保存CONTINUE\nDialogue: 0,0:20:27.40,0:20:28.74,Default,,0,0,0,,这就是我们做的第一件事\nDialogue: 0,0:20:28.74,0:20:30.51,Default,,0,0,0,,然后我们可以看看\nDialogue: 0,0:20:31.71,0:20:32.70,Default,,0,0,0,,实际需要些什么\nDialogue: 0,0:20:33.07,0:20:35.56,Default,,0,0,0,,其实在求值F的过程中\nDialogue: 0,0:20:36.04,0:20:37.82,Default,,0,0,0,,我们不需要保存ENV\nDialogue: 0,0:20:38.08,0:20:39.92,Default,,0,0,0,,因为它不会被破坏\nDialogue: 0,0:20:39.92,0:20:41.31,Default,,0,0,0,,因此 如果我们利用这点\nDialogue: 0,0:20:44.12,0:20:47.56,Default,,0,0,0,,这里对F的求值\nDialogue: 0,0:20:48.57,0:20:50.44,Default,,0,0,0,,完全不需要担心\nDialogue: 0,0:20:51.61,0:20:52.60,Default,,0,0,0,,会破坏ENV\nDialogue: 0,0:20:52.60,0:20:54.94,Default,,0,0,0,,类似地 这里对X的求值\nDialogue: 0,0:20:57.17,0:20:58.89,Default,,0,0,0,,当求值器进行求值时 它会说\nDialogue: 0,0:20:58.91,0:21:01.64,Default,,0,0,0,,我最好保存好与之有关的FUN寄存器\nDialogue: 0,0:21:02.07,0:21:03.22,Default,,0,0,0,,因为后面也许会用得着\nDialogue: 0,0:21:03.28,0:21:04.89,Default,,0,0,0,,我最好也保存参数表\nDialogue: 0,0:21:06.90,0:21:09.05,Default,,0,0,0,,然而 在这如果是编译器的话\nDialogue: 0,0:21:09.05,0:21:10.38,Default,,0,0,0,,实际需要哪些寄存器\nDialogue: 0,0:21:10.52,0:21:11.84,Default,,0,0,0,,从而进行相关的保存与恢复\nDialogue: 0,0:21:12.70,0:21:16.09,Default,,0,0,0,,事实上 这里求值器做的所有栈操作\nDialogue: 0,0:21:16.32,0:21:19.58,Default,,0,0,0,,都证明是过于悲观而不必要\nDialogue: 0,0:21:19.62,0:21:21.45,Default,,0,0,0,,而编译器在这里是知道这一点的\nDialogue: 0,0:21:27.35,0:21:28.48,Default,,0,0,0,,这是最基础的想法\nDialogue: 0,0:21:29.80,0:21:31.00,Default,,0,0,0,,我们把求值器\nDialogue: 0,0:21:31.00,0:21:33.24,Default,,0,0,0,,剔除那些不需要的东西\nDialogue: 0,0:21:33.24,0:21:35.24,Default,,0,0,0,,去除那些对于编译器完全无用的东西\nDialogue: 0,0:21:35.24,0:21:36.19,Default,,0,0,0,,只保留求值的部分\nDialogue: 0,0:21:37.40,0:21:40.40,Default,,0,0,0,,然后你可以看到哪些栈操作是不必要的\nDialogue: 0,0:21:40.82,0:21:43.76,Default,,0,0,0,,这就是书中所描述的编译器\nDialogue: 0,0:21:43.85,0:21:45.04,Default,,0,0,0,,的基本结构\nDialogue: 0,0:21:45.04,0:21:47.00,Default,,0,0,0,,我给你们展示一下这\nDialogue: 0,0:21:47.76,0:21:49.68,Default,,0,0,0,,这个简单的例子\nDialogue: 0,0:21:51.20,0:21:53.26,Default,,0,0,0,,为了说清楚 多余的东西是怎样保存的\nDialogue: 0,0:21:53.29,0:21:56.06,Default,,0,0,0,,我们来看一个稍复杂的表达式\nDialogue: 0,0:21:58.15,0:22:01.93,Default,,0,0,0,,(F (G X) 1)\nDialogue: 0,0:22:03.87,0:22:05.52,Default,,0,0,0,,我们不会讲解所有的代码\nDialogue: 0,0:22:06.40,0:22:08.56,Default,,0,0,0,,因为代码有点多\nDialogue: 0,0:22:09.72,0:22:12.35,Default,,0,0,0,,我认为在求值器在处理它时\nDialogue: 0,0:22:12.35,0:22:14.67,Default,,0,0,0,,大概会产生\nDialogue: 0,0:22:14.70,0:22:16.25,Default,,0,0,0,,16对保存-恢复操作\nDialogue: 0,0:22:17.00,0:22:18.57,Default,,0,0,0,,这有一张图表\nDialogue: 0,0:22:20.57,0:22:21.95,Default,,0,0,0,,演示了其中的过程\nDialogue: 0,0:22:22.97,0:22:23.90,Default,,0,0,0,,你从这里开始--\nDialogue: 0,0:22:24.25,0:22:26.62,Default,,0,0,0,,求值器说：“我要求值一个应用”\nDialogue: 0,0:22:26.90,0:22:29.13,Default,,0,0,0,,在这里保存ENV 又在这里恢复\nDialogue: 0,0:22:30.65,0:22:34.44,Default,,0,0,0,,然后处理第一个运算对象\nDialogue: 0,0:22:36.81,0:22:39.28,Default,,0,0,0,,这是求值器的递归调用\nDialogue: 0,0:22:39.28,0:22:40.89,Default,,0,0,0,,求值器发现 这是一个应用\nDialogue: 0,0:22:40.91,0:22:42.10,Default,,0,0,0,,又会保存环境\nDialogue: 0,0:22:42.10,0:22:44.97,Default,,0,0,0,,求值组合式的运算符 然后在这里恢复环境\nDialogue: 0,0:22:45.80,0:22:48.92,Default,,0,0,0,,这个恢复匹配的是这个保存操作\nDialogue: 0,0:22:49.77,0:22:50.78,Default,,0,0,0,,以此类推\nDialogue: 0,0:22:51.65,0:22:52.51,Default,,0,0,0,,这里的UNEV\nDialogue: 0,0:22:52.52,0:22:54.62,Default,,0,0,0,,完全没有必要存在\nDialogue: 0,0:22:54.97,0:22:56.60,Default,,0,0,0,,CONTINUE寄存器不断地被保存-恢复\nDialogue: 0,0:22:57.42,0:23:00.41,Default,,0,0,0,,而FUN寄存器则是在\nDialogue: 0,0:23:00.78,0:23:04.36,Default,,0,0,0,,处理运算对象期间被保存\nDialogue: 0,0:23:05.10,0:23:06.52,Default,,0,0,0,,这类的事情一直在发生\nDialogue: 0,0:23:06.78,0:23:09.39,Default,,0,0,0,,但如果你问 跟求值器相比\nDialogue: 0,0:23:09.87,0:23:11.66,Default,,0,0,0,,编译器究竟要做什么？\nDialogue: 0,0:23:12.27,0:23:13.55,Default,,0,0,0,,你会去掉一大堆东西\nDialogue: 0,0:23:14.30,0:23:16.64,Default,,0,0,0,,在这个的基础上 如果你说\nDialogue: 0,0:23:19.40,0:23:22.54,Default,,0,0,0,,对F的求值不会修改ENV寄存器\nDialogue: 0,0:23:23.82,0:23:26.51,Default,,0,0,0,,或者对符号X的查找\nDialogue: 0,0:23:29.28,0:23:32.09,Default,,0,0,0,,不需要特别保护FUN寄存器\nDialogue: 0,0:23:34.30,0:23:37.60,Default,,0,0,0,,就得到了只有几对的保存-恢复操作\nDialogue: 0,0:23:40.25,0:23:42.27,Default,,0,0,0,,然而 你还可以再优化一下\nDialogue: 0,0:23:42.27,0:23:44.33,Default,,0,0,0,,看看这里的ENV寄存器发生了什么\nDialogue: 0,0:23:45.21,0:23:47.39,Default,,0,0,0,,我们观察ENV寄存器的操作 发现\nDialogue: 0,0:23:51.00,0:23:52.25,Default,,0,0,0,,这是一个组合式\nDialogue: 0,0:23:54.33,0:23:55.69,Default,,0,0,0,,而这个求值器\nDialogue: 0,0:23:55.78,0:23:57.27,Default,,0,0,0,,对G一无所知\nDialogue: 0,0:23:58.57,0:24:00.73,Default,,0,0,0,,所以在这 它说\nDialogue: 0,0:24:01.29,0:24:03.45,Default,,0,0,0,,我最好保存ENV寄存器\nDialogue: 0,0:24:03.96,0:24:05.42,Default,,0,0,0,,因为对G的求值\nDialogue: 0,0:24:05.42,0:24:07.42,Default,,0,0,0,,可能会修改ENV寄存器的值\nDialogue: 0,0:24:07.55,0:24:09.45,Default,,0,0,0,,而我稍后可能会需要它\nDialogue: 0,0:24:10.17,0:24:11.40,Default,,0,0,0,,在这个参数之后\nDialogue: 0,0:24:12.22,0:24:13.37,Default,,0,0,0,,在处理第二个参数的时候\nDialogue: 0,0:24:15.60,0:24:17.24,Default,,0,0,0,,这就是为什么它没被优化掉\nDialogue: 0,0:24:19.07,0:24:22.54,Default,,0,0,0,,因为编译器没有对G将要做的事情做任何假设\nDialogue: 0,0:24:22.54,0:24:23.60,Default,,0,0,0,,另一方面\nDialogue: 0,0:24:24.61,0:24:26.52,Default,,0,0,0,,如果你看看这里的第二个参数\nDialogue: 0,0:24:26.64,0:24:27.70,Default,,0,0,0,,它只是查找“1”这个常量\nDialogue: 0,0:24:27.70,0:24:29.60,Default,,0,0,0,,这不需要ENV寄存器\nDialogue: 0,0:24:30.77,0:24:32.04,Default,,0,0,0,,因此没必要保存它\nDialogue: 0,0:24:32.06,0:24:33.77,Default,,0,0,0,,事实上 你也可以把这个也去掉\nDialogue: 0,0:24:34.85,0:24:37.81,Default,,0,0,0,,这一堆寄存器操作\nDialogue: 0,0:24:37.98,0:24:40.08,Default,,0,0,0,,如果你像这样简单地推理的话\nDialogue: 0,0:24:40.55,0:24:43.05,Default,,0,0,0,,只会剩下两对保存-恢复操作\nDialogue: 0,0:24:45.10,0:24:46.97,Default,,0,0,0,,而这些 如果你知道关于G的某些信息的话\nDialogue: 0,0:24:47.52,0:24:49.08,Default,,0,0,0,,可以进一步优化\nDialogue: 0,0:24:56.27,0:24:57.85,Default,,0,0,0,,基本的理念是\nDialogue: 0,0:24:57.95,0:24:59.98,Default,,0,0,0,,编译器之所以更好\nDialogue: 0,0:24:59.98,0:25:02.56,Default,,0,0,0,,是因为解释器对于将要处理的东西一无所知\nDialogue: 0,0:25:03.25,0:25:05.04,Default,,0,0,0,,它不得不以最悲观的方式保存东西\nDialogue: 0,0:25:05.05,0:25:06.70,Default,,0,0,0,,来保护它自己\nDialogue: 0,0:25:07.90,0:25:08.76,Default,,0,0,0,,而编译器\nDialogue: 0,0:25:09.48,0:25:12.38,Default,,0,0,0,,只需要保存实际需要的东西\nDialogue: 0,0:25:13.37,0:25:15.20,Default,,0,0,0,,某个东西是否需要保存\nDialogue: 0,0:25:15.24,0:25:17.37,Default,,0,0,0,,有两种原因\nDialogue: 0,0:25:17.82,0:25:18.70,Default,,0,0,0,,一种是\nDialogue: 0,0:25:18.70,0:25:19.82,Default,,0,0,0,,你保护的东西\nDialogue: 0,0:25:19.95,0:25:21.44,Default,,0,0,0,,不会修改寄存器\nDialogue: 0,0:25:22.08,0:25:23.58,Default,,0,0,0,,例如 变量查找\nDialogue: 0,0:25:24.12,0:25:25.20,Default,,0,0,0,,另一种原因是\nDialogue: 0,0:25:25.32,0:25:27.10,Default,,0,0,0,,你所保存的东西\nDialogue: 0,0:25:28.28,0:25:29.92,Default,,0,0,0,,最后并不会被用到\nDialogue: 0,0:25:30.81,0:25:34.27,Default,,0,0,0,,因此 编译器正是利用了\nDialogue: 0,0:25:34.30,0:25:35.88,Default,,0,0,0,,这两条基本原则\nDialogue: 0,0:25:36.27,0:25:37.76,Default,,0,0,0,,来让代码变得更高效的\nDialogue: 0,0:25:44.27,0:25:45.32,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:25:51.20,0:25:53.10,Default,,0,0,0,,学生: 你一直在说UNEV寄存器\nDialogue: 0,0:25:53.13,0:25:56.40,Default,,0,0,0,,UNEV寄存器完全不会被用到\nDialogue: 0,0:25:56.41,0:25:58.68,Default,,0,0,0,,是否意味着 机器只需要6个寄存器足矣？\nDialogue: 0,0:25:58.70,0:26:00.08,Default,,0,0,0,,或者是说 在这个特定的例子里\nDialogue: 0,0:26:00.11,0:26:01.18,Default,,0,0,0,,它没有被用到？\nDialogue: 0,0:26:01.72,0:26:02.81,Default,,0,0,0,,教授: 对于编译器\nDialogue: 0,0:26:04.31,0:26:07.42,Default,,0,0,0,,你可以生成6个或5个寄存器的代码\nDialogue: 0,0:26:07.56,0:26:09.02,Default,,0,0,0,,因为EXP寄存器也没有用到\nDialogue: 0,0:26:09.40,0:26:14.57,Default,,0,0,0,,是的 你可以把EXP和UNEV都去掉\nDialogue: 0,0:26:14.57,0:26:16.87,Default,,0,0,0,,因为这些是求值器的数据结构\nDialogue: 0,0:26:17.36,0:26:19.36,Default,,0,0,0,,以编译器的视角来看\nDialogue: 0,0:26:19.39,0:26:20.87,Default,,0,0,0,,这些东西都是常量\nDialogue: 0,0:26:21.65,0:26:22.44,Default,,0,0,0,,关键在于\nDialogue: 0,0:26:22.48,0:26:24.59,Default,,0,0,0,,这个特定编译器是被构造出来的\nDialogue: 0,0:26:24.79,0:26:27.92,Default,,0,0,0,,因此被解释的代码和被编译的代码可以共存\nDialogue: 0,0:26:29.32,0:26:30.72,Default,,0,0,0,,可以这样看待它\nDialogue: 0,0:26:30.97,0:26:32.29,Default,,0,0,0,,你构建了一个芯片\nDialogue: 0,0:26:34.30,0:26:35.50,Default,,0,0,0,,它就是求值器\nDialogue: 0,0:26:35.88,0:26:37.28,Default,,0,0,0,,而编译器可以做的就是\nDialogue: 0,0:26:37.31,0:26:39.02,Default,,0,0,0,,为这个芯片生成代码\nDialogue: 0,0:26:40.40,0:26:41.90,Default,,0,0,0,,只是它不会用到两个寄存器而已\nDialogue: 0,0:26:51.52,0:26:52.47,Default,,0,0,0,,好 休息一会\nDialogue: 0,0:26:53.55,0:27:07.18,Default,,0,0,0,,[音乐]\nDialogue: 0,0:27:07.37,0:27:11.42,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:27:14.57,0:27:18.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:27:18.17,0:27:22.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:27:22.22,0:27:26.48,Declare,,0,0,0,,{\\an2\\fad(500,500)}编译\nDialogue: 0,0:27:29.21,0:27:32.43,Default,,0,0,0,,我们刚才研究了编译器应该要做什么\nDialogue: 0,0:27:32.78,0:27:36.04,Default,,0,0,0,,现在我们来简略地看看\nDialogue: 0,0:27:36.15,0:27:37.47,Default,,0,0,0,,这些目标如何达成\nDialogue: 0,0:27:38.26,0:27:39.58,Default,,0,0,0,,而我不会给出细节\nDialogue: 0,0:27:39.60,0:27:42.17,Default,,0,0,0,,在书中有一大堆代码\nDialogue: 0,0:27:42.22,0:27:43.42,Default,,0,0,0,,展示了所有细节\nDialogue: 0,0:27:43.45,0:27:45.31,Default,,0,0,0,,我要做的 是给你们展示\nDialogue: 0,0:27:45.96,0:27:47.26,Default,,0,0,0,,其中的关键思想\nDialogue: 0,0:27:49.49,0:27:51.36,Default,,0,0,0,,换个时间再来关心细节\nDialogue: 0,0:27:51.51,0:27:55.30,Default,,0,0,0,,设想我们正在编译一条表达式\nDialogue: 0,0:27:55.30,0:27:57.01,Default,,0,0,0,,这里有一些运算符\nDialogue: 0,0:27:57.48,0:27:58.56,Default,,0,0,0,,和两个参数\nDialogue: 0,0:28:03.56,0:28:04.24,Default,,0,0,0,,现在\nDialogue: 0,0:28:06.27,0:28:08.14,Default,,0,0,0,,这个编译器会生成什么代码?\nDialogue: 0,0:28:08.85,0:28:09.78,Default,,0,0,0,,首先\nDialogue: 0,0:28:09.83,0:28:11.20,Default,,0,0,0,,它会递归运行\nDialogue: 0,0:28:11.90,0:28:13.28,Default,,0,0,0,,编译运算符\nDialogue: 0,0:28:14.37,0:28:19.02,Default,,0,0,0,,它说 我要编译运算符\nDialogue: 0,0:28:21.16,0:28:24.54,Default,,0,0,0,,最后我需要让它们的结果\nDialogue: 0,0:28:24.84,0:28:27.95,Default,,0,0,0,,存放在FUN寄存器中\nDialogue: 0,0:28:28.42,0:28:29.60,Default,,0,0,0,,所以我编译一些指令\nDialogue: 0,0:28:29.64,0:28:31.56,Default,,0,0,0,,它们会编译运算符\nDialogue: 0,0:28:31.69,0:28:38.62,Default,,0,0,0,,最后把结果放在FUN寄存器中\nDialogue: 0,0:28:45.51,0:28:46.94,Default,,0,0,0,,接下来我要做的是\nDialogue: 0,0:28:47.71,0:28:49.68,Default,,0,0,0,,另一个代码片段则说\nDialogue: 0,0:28:49.68,0:28:55.17,Default,,0,0,0,,我要编译第一个参数\nDialogue: 0,0:28:55.17,0:28:56.80,Default,,0,0,0,,因此它递归调地用自己\nDialogue: 0,0:28:58.04,0:29:03.36,Default,,0,0,0,,而结果会被放在VAL中\nDialogue: 0,0:29:09.07,0:29:10.75,Default,,0,0,0,,接下来需要做的是\nDialogue: 0,0:29:10.75,0:29:12.26,Default,,0,0,0,,建立起参数表\nDialogue: 0,0:29:12.95,0:29:25.50,Default,,0,0,0,,(ASSIGN ARGL (CONS (FETCH --\nDialogue: 0,0:29:25.55,0:29:27.10,Default,,0,0,0,,它会生成这些代码\nDialogue: 0,0:29:27.50,0:29:32.51,Default,,0,0,0,,(FETCH VAL) '()))\nDialogue: 0,0:29:35.00,0:29:36.05,Default,,0,0,0,,然而\nDialogue: 0,0:29:37.99,0:29:40.61,Default,,0,0,0,,当它到这里时\nDialogue: 0,0:29:41.32,0:29:42.82,Default,,0,0,0,,它可能需要环境\nDialogue: 0,0:29:43.95,0:29:45.29,Default,,0,0,0,,它需要环境\nDialogue: 0,0:29:45.32,0:29:48.21,Default,,0,0,0,,这是求值第一个参数所需要的\nDialogue: 0,0:29:49.04,0:29:51.18,Default,,0,0,0,,因此 它需要保证\nDialogue: 0,0:29:51.92,0:29:53.76,Default,,0,0,0,,对运算对象的编译\nDialogue: 0,0:29:55.32,0:29:57.85,Default,,0,0,0,,或者说它需要保护FUN寄存器\nDialogue: 0,0:29:58.01,0:30:00.98,Default,,0,0,0,,来应对编译运算对象时发生的各种情况\nDialogue: 0,0:30:01.30,0:30:03.08,Default,,0,0,0,,因此它在这做了个标注说\nDialogue: 0,0:30:03.37,0:30:12.89,Default,,0,0,0,,这个片段需要保护ENV寄存器\nDialogue: 0,0:30:17.39,0:30:18.44,Default,,0,0,0,,与之类似 这里\nDialogue: 0,0:30:21.02,0:30:23.30,Default,,0,0,0,,在完成第一个运算对象的编译后\nDialogue: 0,0:30:23.57,0:30:24.67,Default,,0,0,0,,它会说 我最好--\nDialogue: 0,0:30:24.71,0:30:27.92,Default,,0,0,0,,我需要知道第二个运算对象的环境\nDialogue: 0,0:30:27.92,0:30:29.46,Default,,0,0,0,,所以它在这做了个标注\nDialogue: 0,0:30:29.71,0:30:35.96,Default,,0,0,0,,这里也需要保护ENV\nDialogue: 0,0:30:39.42,0:30:41.02,Default,,0,0,0,,现在它继续运行\nDialogue: 0,0:30:41.12,0:30:42.83,Default,,0,0,0,,下一段代码\nDialogue: 0,0:30:43.31,0:30:49.74,Default,,0,0,0,,是要编译第二个参数\nDialogue: 0,0:30:50.82,0:30:52.64,Default,,0,0,0,,它将会\nDialogue: 0,0:30:52.99,0:30:59.28,Default,,0,0,0,,把编译的结果按约定放入到VAL中\nDialogue: 0,0:31:03.86,0:31:06.70,Default,,0,0,0,,随后它会生成一条指令\nDialogue: 0,0:31:07.84,0:31:09.25,Default,,0,0,0,,从而建立起参数表\nDialogue: 0,0:31:09.55,0:31:15.28,Default,,0,0,0,,(ASSIGN ARGL\nDialogue: 0,0:31:20.22,0:31:28.94,Default,,0,0,0,,(CONS (FETCH VAL) (FETCH ARGL))\nDialogue: 0,0:31:33.97,0:31:34.64,Default,,0,0,0,,然而\nDialogue: 0,0:31:34.81,0:31:36.58,Default,,0,0,0,,为了取得旧的参数表\nDialogue: 0,0:31:37.15,0:31:40.99,Default,,0,0,0,,它最好保证这期间发生的任何事情\nDialogue: 0,0:31:41.30,0:31:42.69,Default,,0,0,0,,都不影响旧的参数表\nDialogue: 0,0:31:43.50,0:31:45.17,Default,,0,0,0,,因此它在这做了个标注说\nDialogue: 0,0:31:45.34,0:31:51.64,Default,,0,0,0,,哦 这里需要保护ARGL\nDialogue: 0,0:31:54.16,0:31:56.03,Default,,0,0,0,,现在参数表就建立好了\nDialogue: 0,0:31:58.01,0:32:02.86,Default,,0,0,0,,现在可以准备去APPLY-DISPATCH了\nDialogue: 0,0:32:07.02,0:32:10.80,Default,,0,0,0,,它生成了这条指令\nDialogue: 0,0:32:15.19,0:32:17.37,Default,,0,0,0,,因为现在参数都在ARGL中\nDialogue: 0,0:32:18.15,0:32:20.59,Default,,0,0,0,,运算符在FUN中\nDialogue: 0,0:32:20.59,0:32:22.89,Default,,0,0,0,,如果只是单纯地把运算符放到FUN寄存器中\nDialogue: 0,0:32:23.27,0:32:26.64,Default,,0,0,0,,就需要它保证这块代码\nDialogue: 0,0:32:27.09,0:32:29.27,Default,,0,0,0,,不会破坏FUN寄存器里的东西\nDialogue: 0,0:32:29.67,0:32:31.24,Default,,0,0,0,,所以它在这做了个标注说\nDialogue: 0,0:32:31.55,0:32:32.73,Default,,0,0,0,,这里的所有东西\nDialogue: 0,0:32:34.88,0:32:40.73,Default,,0,0,0,,最好能够在保护FUN寄存器的情况下完成\nDialogue: 0,0:32:43.71,0:32:46.15,Default,,0,0,0,,所以这就是--\nDialogue: 0,0:32:46.15,0:32:47.10,Default,,0,0,0,,基本上来说\nDialogue: 0,0:32:48.20,0:32:50.24,Default,,0,0,0,,编译器所做的就是\nDialogue: 0,0:32:50.54,0:32:52.46,Default,,0,0,0,,追加一大堆的代码\nDialogue: 0,0:32:53.50,0:32:58.83,Default,,0,0,0,,而这些代码之中都是一些基本运算\nDialogue: 0,0:32:58.86,0:33:00.12,Default,,0,0,0,,比如符号查找\nDialogue: 0,0:33:01.44,0:33:02.60,Default,,0,0,0,,条件分支的处理\nDialogue: 0,0:33:02.64,0:33:05.44,Default,,0,0,0,,都是一些琐碎的事情\nDialogue: 0,0:33:05.44,0:33:07.99,Default,,0,0,0,,然后按照这种准则将它们追加到一起\nDialogue: 0,0:33:08.78,0:33:10.79,Default,,0,0,0,,因此 组合的基本手段就是\nDialogue: 0,0:33:10.86,0:33:13.18,Default,,0,0,0,,将一段代码追加到另一段的后面\nDialogue: 0,0:33:21.55,0:33:22.86,Default,,0,0,0,,就是这里发生的事情\nDialogue: 0,0:33:25.58,0:33:27.24,Default,,0,0,0,,这有点取巧\nDialogue: 0,0:33:27.56,0:33:30.37,Default,,0,0,0,,向一段代码后面追加代码的思路是\nDialogue: 0,0:33:31.60,0:33:33.76,Default,,0,0,0,,小心保护寄存器\nDialogue: 0,0:33:35.63,0:33:37.93,Default,,0,0,0,,追加操作看起来像这样\nDialogue: 0,0:33:39.15,0:33:40.65,Default,,0,0,0,,它要做的是\nDialogue: 0,0:33:41.20,0:33:44.11,Default,,0,0,0,,代码的追加是这么来做的\nDialogue: 0,0:33:44.53,0:33:53.63,Default,,0,0,0,,如果SEQ1需要寄存器--\nDialogue: 0,0:33:53.66,0:33:54.72,Default,,0,0,0,,我应该改一下这个\nDialogue: 0,0:33:54.72,0:33:56.87,Default,,0,0,0,,在SEQ1后面追加SEQ2\nDialogue: 0,0:33:57.42,0:34:03.96,Default,,0,0,0,,并保护一些寄存器\nDialogue: 0,0:34:08.52,0:34:09.91,Default,,0,0,0,,这里改成AND\nDialogue: 0,0:34:11.36,0:34:13.03,Default,,0,0,0,,这样的话前后顺序就清楚了\nDialogue: 0,0:34:13.88,0:34:19.87,Default,,0,0,0,,如果SEQ2需要寄存器\nDialogue: 0,0:34:21.12,0:34:27.85,Default,,0,0,0,,而SEQ1又修改了寄存器\nDialogue: 0,0:34:33.68,0:34:36.30,Default,,0,0,0,,那么编译器生成的指令是\nDialogue: 0,0:34:36.97,0:34:41.34,Default,,0,0,0,,保存寄存器\nDialogue: 0,0:34:43.02,0:34:44.19,Default,,0,0,0,,这就是代码\nDialogue: 0,0:34:44.35,0:34:45.35,Default,,0,0,0,,生成这段代码\nDialogue: 0,0:34:45.35,0:34:46.28,Default,,0,0,0,,保存寄存器\nDialogue: 0,0:34:46.72,0:34:52.97,Default,,0,0,0,,然后写下递归编译SEQ1的结果\nDialogue: 0,0:34:53.30,0:34:54.84,Default,,0,0,0,,然后恢复寄存器\nDialogue: 0,0:35:00.52,0:35:03.92,Default,,0,0,0,,再写下递归编译\nDialogue: 0,0:35:04.46,0:35:05.47,Default,,0,0,0,,SEQ2的结果\nDialogue: 0,0:35:07.07,0:35:09.62,Default,,0,0,0,,这就是你需要做的\nDialogue: 0,0:35:09.62,0:35:11.82,Default,,0,0,0,,实际上SEQ2需要寄存器\nDialogue: 0,0:35:11.82,0:35:13.74,Default,,0,0,0,,而SEQ1改动了它\nDialogue: 0,0:35:15.12,0:35:17.07,Default,,0,0,0,,否则的话\nDialogue: 0,0:35:20.50,0:35:26.57,Default,,0,0,0,,得到的就是SEQ1后面跟着SEQ2\nDialogue: 0,0:35:28.17,0:35:30.30,Default,,0,0,0,,这就是把两个代码片段\nDialogue: 0,0:35:30.59,0:35:33.52,Default,,0,0,0,,连接到一起的基本操作\nDialogue: 0,0:35:33.93,0:35:35.93,Default,,0,0,0,,把这些指令组合成序列\nDialogue: 0,0:35:36.89,0:35:38.87,Default,,0,0,0,,我们可以发现 从这个角度看\nDialogue: 0,0:35:40.94,0:35:45.96,Default,,0,0,0,,解释器和编译器的区别\nDialogue: 0,0:35:46.82,0:35:49.34,Default,,0,0,0,,是编译器有保护寄存器的标注\nDialogue: 0,0:35:50.14,0:35:52.22,Default,,0,0,0,,上面记录着\nDialogue: 0,0:35:52.49,0:35:54.22,Default,,0,0,0,,是否需要生成保存-恢复代码\nDialogue: 0,0:35:55.19,0:35:57.24,Default,,0,0,0,,而解释器会以最悲观的方式处理\nDialogue: 0,0:35:57.28,0:35:58.90,Default,,0,0,0,,总是会进行保存-恢复\nDialogue: 0,0:36:00.76,0:36:01.93,Default,,0,0,0,,这就是关键的区别\nDialogue: 0,0:36:04.16,0:36:06.05,Default,,0,0,0,,为了实现这个\nDialogue: 0,0:36:06.65,0:36:09.40,Default,,0,0,0,,编译器需要一些理论\nDialogue: 0,0:36:09.56,0:36:11.96,Default,,0,0,0,,来确定代码序列会需要、又会修改哪些寄存器\nDialogue: 0,0:36:14.26,0:36:17.28,Default,,0,0,0,,所以你放入的小片段\nDialogue: 0,0:36:17.48,0:36:21.00,Default,,0,0,0,,例如这段基础代码\nDialogue: 0,0:36:22.74,0:36:24.59,Default,,0,0,0,,当你查找一个变量时\nDialogue: 0,0:36:24.92,0:36:26.04,Default,,0,0,0,,进行了哪些操作？\nDialogue: 0,0:36:26.89,0:36:29.02,Default,,0,0,0,,你又是做了些什么\nDialogue: 0,0:36:29.05,0:36:30.68,Default,,0,0,0,,来编译一个常量\nDialogue: 0,0:36:30.97,0:36:32.10,Default,,0,0,0,,或者应用一个函数\nDialogue: 0,0:36:32.97,0:36:34.48,Default,,0,0,0,,它们都会带有一些标注\nDialogue: 0,0:36:34.67,0:36:36.46,Default,,0,0,0,,说明了它们需要的和修改的寄存器\nDialogue: 0,0:36:38.78,0:36:41.50,Default,,0,0,0,,所以底层的数据结构\nDialogue: 0,0:36:42.66,0:36:44.33,Default,,0,0,0,,我会这样讲\nDialogue: 0,0:36:44.39,0:36:47.91,Default,,0,0,0,,传递给编译器的代码序列大概是这样\nDialogue: 0,0:36:48.07,0:36:51.42,Default,,0,0,0,,它里面有实际的指令序列\nDialogue: 0,0:36:55.67,0:36:56.81,Default,,0,0,0,,跟它一起的还有\nDialogue: 0,0:36:57.18,0:37:02.60,Default,,0,0,0,,一组被修改的寄存器\nDialogue: 0,0:37:10.54,0:37:12.60,Default,,0,0,0,,还有一组需要的寄存器\nDialogue: 0,0:37:20.00,0:37:22.46,Default,,0,0,0,,为了能够执行此操作\nDialogue: 0,0:37:23.00,0:37:26.41,Default,,0,0,0,,编译器必须要掌握这些信息\nDialogue: 0,0:37:29.30,0:37:31.08,Default,,0,0,0,,它们从哪来呢\nDialogue: 0,0:37:32.91,0:37:34.49,Default,,0,0,0,,它们来自于--你们可能也想到了\nDialogue: 0,0:37:34.51,0:37:35.53,Default,,0,0,0,,对于那些最基本的片段\nDialogue: 0,0:37:35.55,0:37:36.84,Default,,0,0,0,,我们会手工添加\nDialogue: 0,0:37:37.24,0:37:38.86,Default,,0,0,0,,然后 当我们组合两个序列时\nDialogue: 0,0:37:38.89,0:37:41.02,Default,,0,0,0,,我们会计算出这两个集合\nDialogue: 0,0:37:42.16,0:37:44.12,Default,,0,0,0,,举一个非常基本的例子\nDialogue: 0,0:37:48.43,0:37:51.40,Default,,0,0,0,,例如做一个寄存器赋值\nDialogue: 0,0:37:51.77,0:37:53.50,Default,,0,0,0,,因此 基本代码片段会说\nDialogue: 0,0:37:53.52,0:37:56.22,Default,,0,0,0,,噢 它是个代码片段\nDialogue: 0,0:37:56.22,0:38:03.17,Default,,0,0,0,,代码的指令部分是(ASSIGN R1 (FETCH R2))\nDialogue: 0,0:38:03.17,0:38:04.27,Default,,0,0,0,,这个例子就是这样的\nDialogue: 0,0:38:05.42,0:38:08.52,Default,,0,0,0,,一段指令序列大概就是这样\nDialogue: 0,0:38:08.77,0:38:10.53,Default,,0,0,0,,和它在一起的是\nDialogue: 0,0:38:10.64,0:38:15.76,Default,,0,0,0,,它需要记得修改了R1\nDialogue: 0,0:38:18.60,0:38:21.16,Default,,0,0,0,,然后它需要R2\nDialogue: 0,0:38:24.69,0:38:26.99,Default,,0,0,0,,因此当你开始构建编译器时\nDialogue: 0,0:38:27.10,0:38:29.35,Default,,0,0,0,,你放入这样的一个片段\nDialogue: 0,0:38:30.95,0:38:33.20,Default,,0,0,0,,当它组合两个序列时\nDialogue: 0,0:38:36.70,0:38:38.04,Default,,0,0,0,,我要组合\nDialogue: 0,0:38:38.92,0:38:41.58,Default,,0,0,0,,代码片段S1\nDialogue: 0,0:38:42.88,0:38:47.16,Default,,0,0,0,,修改了一组寄存器M1\nDialogue: 0,0:38:48.45,0:38:51.42,Default,,0,0,0,,并且需要一组寄存器N1\nDialogue: 0,0:38:54.85,0:38:59.48,Default,,0,0,0,,并且我要把它和序列S2组合到一起\nDialogue: 0,0:39:00.81,0:39:05.96,Default,,0,0,0,,后者修改了一组寄存器M2\nDialogue: 0,0:39:07.11,0:39:10.00,Default,,0,0,0,,并且需要一组寄存器N2\nDialogue: 0,0:39:12.44,0:39:14.83,Default,,0,0,0,,这样我们就能得出结果\nDialogue: 0,0:39:15.11,0:39:16.32,Default,,0,0,0,,新的代码片段是这样的\nDialogue: 0,0:39:17.18,0:39:21.82,Default,,0,0,0,,指令序列S1后面跟着S2\nDialogue: 0,0:39:24.09,0:39:26.45,Default,,0,0,0,,它要修改什么?\nDialogue: 0,0:39:27.80,0:39:29.18,Default,,0,0,0,,它要修改的是\nDialogue: 0,0:39:29.20,0:39:32.68,Default,,0,0,0,,被S1或者被S2修改的寄存器\nDialogue: 0,0:39:34.00,0:39:36.35,Default,,0,0,0,,N1和N2的并集\nDialogue: 0,0:39:37.68,0:39:39.64,Default,,0,0,0,,就是新的修改集\nDialogue: 0,0:39:40.46,0:39:41.79,Default,,0,0,0,,然后你问\nDialogue: 0,0:39:44.66,0:39:46.41,Default,,0,0,0,,又需要哪些寄存器？\nDialogue: 0,0:39:47.95,0:39:49.77,Default,,0,0,0,,需要这些寄存器的是\nDialogue: 0,0:39:49.93,0:39:51.85,Default,,0,0,0,,首先 一定是序列S1需要的\nDialogue: 0,0:39:52.91,0:39:54.49,Default,,0,0,0,,因此必然有N1\nDialogue: 0,0:39:55.19,0:39:58.28,Default,,0,0,0,,然后 并不是N2里面的所有元素\nDialogue: 0,0:39:58.32,0:39:59.61,Default,,0,0,0,,我们都需要\nDialogue: 0,0:39:59.75,0:40:03.49,Default,,0,0,0,,新的修改集需要N2中那些\nDialogue: 0,0:40:03.88,0:40:06.88,Default,,0,0,0,,没有被S1修改过的寄存器\nDialogue: 0,0:40:08.14,0:40:09.72,Default,,0,0,0,,所以 这个并集是N1并上\nDialogue: 0,0:40:11.66,0:40:13.40,Default,,0,0,0,,序列S2的需要集N2\nDialogue: 0,0:40:14.51,0:40:18.52,Default,,0,0,0,,减去序列S1的修改集M1\nDialogue: 0,0:40:19.31,0:40:20.88,Default,,0,0,0,,因为它关心的是如何设置它们\nDialogue: 0,0:40:23.95,0:40:26.26,Default,,0,0,0,,这就是编译器的基本结构\nDialogue: 0,0:40:26.70,0:40:29.82,Default,,0,0,0,,我们进行寄存器优化的方式是\nDialogue: 0,0:40:30.22,0:40:32.70,Default,,0,0,0,,一些策略来应对需要保护的东西\nDialogue: 0,0:40:34.10,0:40:35.63,Default,,0,0,0,,这取决于数据结构\nDialogue: 0,0:40:35.72,0:40:38.51,Default,,0,0,0,,这取决于将东西组合在一起的操作\nDialogue: 0,0:40:39.03,0:40:41.63,Default,,0,0,0,,想知道要保护哪些东西\nDialogue: 0,0:40:41.93,0:40:47.28,Default,,0,0,0,,就需要知道这段代码需要以及修改的寄存器\nDialogue: 0,0:40:48.75,0:40:51.26,Default,,0,0,0,,这就需要我们有一个数据结构\nDialogue: 0,0:40:51.42,0:40:55.43,Default,,0,0,0,,它不但要存放实际的指令序列\nDialogue: 0,0:40:55.60,0:40:57.33,Default,,0,0,0,,它修改了什么 又需要什么\nDialogue: 0,0:40:57.33,0:40:59.77,Default,,0,0,0,,这些信息来自于--最基本的情况是内置的\nDialogue: 0,0:40:59.79,0:41:01.36,Default,,0,0,0,,对于最基本的情况\nDialogue: 0,0:41:01.37,0:41:02.52,Default,,0,0,0,,我们可以容易地知道\nDialogue: 0,0:41:03.00,0:41:04.44,Default,,0,0,0,,需要哪些寄存器 又修改了哪些\nDialogue: 0,0:41:04.82,0:41:05.35,Default,,0,0,0,,另外\nDialogue: 0,0:41:05.44,0:41:08.60,Default,,0,0,0,,利用这个特定的方法构建复杂指令时\nDialogue: 0,0:41:09.28,0:41:11.89,Default,,0,0,0,,我们可以像这样生成新的修改集\nDialogue: 0,0:41:11.93,0:41:13.37,Default,,0,0,0,,以及新的需要集\nDialogue: 0,0:41:15.27,0:41:17.77,Default,,0,0,0,,这就是全部的内容 -- 我不该这么说\nDialogue: 0,0:41:17.77,0:41:19.34,Default,,0,0,0,,这就是书里面大概30页的细节\nDialogue: 0,0:41:19.74,0:41:21.87,Default,,0,0,0,,的核心内容了\nDialogue: 0,0:41:22.31,0:41:27.69,Default,,0,0,0,,但它是一个完全可用的初级编译器\nDialogue: 0,0:41:28.76,0:41:31.37,Default,,0,0,0,,让我给你展示一下它能做什么\nDialogue: 0,0:41:31.39,0:41:35.56,Default,,0,0,0,,假设我们从一个递归阶乘开始\nDialogue: 0,0:41:36.20,0:41:38.60,Default,,0,0,0,,这些幻灯片的字太小不适合阅读\nDialogue: 0,0:41:38.60,0:41:39.79,Default,,0,0,0,,我只想快速翻一下代码\nDialogue: 0,0:41:39.79,0:41:41.28,Default,,0,0,0,,让你们看看它有多少代码\nDialogue: 0,0:41:42.25,0:41:43.29,Default,,0,0,0,,代码从这开始--\nDialogue: 0,0:41:44.32,0:41:45.68,Default,,0,0,0,,这是代码的第一部分\nDialogue: 0,0:41:45.95,0:41:47.68,Default,,0,0,0,,这里编译了一个过程入口\nDialogue: 0,0:41:47.69,0:41:48.73,Default,,0,0,0,,并进行了一些赋值操作\nDialogue: 0,0:41:48.75,0:41:51.48,Default,,0,0,0,,这基本上对应了解释器中\nDialogue: 0,0:41:52.65,0:41:53.90,Default,,0,0,0,,进行判断之前的部分\nDialogue: 0,0:41:54.31,0:41:56.59,Default,,0,0,0,,并判断谓词是否成立\nDialogue: 0,0:41:56.97,0:41:57.85,Default,,0,0,0,,第二部分是\nDialogue: 0,0:41:58.46,0:42:03.73,Default,,0,0,0,,递归调用N-1的阶乘的结果\nDialogue: 0,0:42:04.12,0:42:05.05,Default,,0,0,0,,最后一部分是\nDialogue: 0,0:42:06.07,0:42:07.48,Default,,0,0,0,,从那里返回\nDialogue: 0,0:42:07.87,0:42:09.90,Default,,0,0,0,,并处理递归的基本情况\nDialogue: 0,0:42:09.90,0:42:13.16,Default,,0,0,0,,这就是编译阶乘会生成的代码量\nDialogue: 0,0:42:13.72,0:42:17.69,Default,,0,0,0,,当然 我们可以把这个编译器做得更好\nDialogue: 0,0:42:18.67,0:42:21.24,Default,,0,0,0,,优化它的主要方式是\nDialogue: 0,0:42:21.24,0:42:24.00,Default,,0,0,0,,当你调用一个过程时\nDialogue: 0,0:42:24.35,0:42:26.27,Default,,0,0,0,,允许编译器做任何假设\nDialogue: 0,0:42:26.97,0:42:28.28,Default,,0,0,0,,举例来说\nDialogue: 0,0:42:28.30,0:42:32.32,Default,,0,0,0,,这个编译器甚至不知道\nDialogue: 0,0:42:33.12,0:42:36.14,Default,,0,0,0,,乘法可以被内联执行\nDialogue: 0,0:42:36.14,0:42:37.87,Default,,0,0,0,,它则会自行构建起整个机制\nDialogue: 0,0:42:38.00,0:42:39.34,Default,,0,0,0,,进行APPLY-DISPATCH\nDialogue: 0,0:42:41.37,0:42:42.49,Default,,0,0,0,,这是极大的浪费\nDialogue: 0,0:42:42.54,0:42:45.02,Default,,0,0,0,,因为 每当你进行APPLY-DISPATCH时\nDialogue: 0,0:42:45.02,0:42:46.80,Default,,0,0,0,,你都要关心这个参数表\nDialogue: 0,0:42:47.40,0:42:49.10,Default,,0,0,0,,因为它是个很普遍的操作\nDialogue: 0,0:42:49.13,0:42:51.07,Default,,0,0,0,,在任何真实的编译器中\nDialogue: 0,0:42:51.08,0:42:53.29,Default,,0,0,0,,你会有寄存器来暂存参数\nDialogue: 0,0:42:53.77,0:42:55.31,Default,,0,0,0,,你要开始保护\nDialogue: 0,0:42:56.38,0:42:58.05,Default,,0,0,0,,保存这些寄存器\nDialogue: 0,0:42:58.05,0:43:01.61,Default,,0,0,0,,和这里的策略相近\nDialogue: 0,0:43:02.85,0:43:05.93,Default,,0,0,0,,因此 我们可能主要通过这个方法\nDialogue: 0,0:43:05.95,0:43:08.30,Default,,0,0,0,,来优化书中这个特定的编译器\nDialogue: 0,0:43:08.69,0:43:09.70,Default,,0,0,0,,还有其它的一些方法\nDialogue: 0,0:43:09.70,0:43:11.82,Default,,0,0,0,,比如查找变量的值\nDialogue: 0,0:43:11.83,0:43:13.87,Default,,0,0,0,,使用更高效的基本操作\nDialogue: 0,0:43:13.88,0:43:14.56,Default,,0,0,0,,等等方法\nDialogue: 0,0:43:14.59,0:43:16.60,Default,,0,0,0,,本质上来说 一个好的Lisp编译器\nDialogue: 0,0:43:16.62,0:43:18.49,Default,,0,0,0,,可以吸收任意数量的努力\nDialogue: 0,0:43:19.72,0:43:21.63,Default,,0,0,0,,可能这其中的一个原因是\nDialogue: 0,0:43:21.89,0:43:23.04,Default,,0,0,0,,跟FORTRAN这类语言相比\nDialogue: 0,0:43:23.63,0:43:25.44,Default,,0,0,0,,Lisp就要慢一些\nDialogue: 0,0:43:25.90,0:43:28.19,Default,,0,0,0,,如果你回头审视历史\nDialogue: 0,0:43:28.22,0:43:31.12,Default,,0,0,0,,会发现人们为构建Lisp编译器而呕心沥血\nDialogue: 0,0:43:31.16,0:43:32.35,Default,,0,0,0,,但也远远没有接近\nDialogue: 0,0:43:32.36,0:43:33.90,Default,,0,0,0,,构建FORTRAN编译器的工作量\nDialogue: 0,0:43:34.43,0:43:35.79,Default,,0,0,0,,在接下来的几年\nDialogue: 0,0:43:35.92,0:43:37.68,Default,,0,0,0,,情况可能会发生变化\nDialogue: 0,0:43:38.00,0:43:38.83,Default,,0,0,0,,好吧 就讲到这里\nDialogue: 0,0:43:43.80,0:43:44.65,Default,,0,0,0,,有问题吗\nDialogue: 0,0:43:48.27,0:43:49.95,Default,,0,0,0,,学生: 很早的一个课时里--\nDialogue: 0,0:43:49.95,0:43:51.40,Default,,0,0,0,,我不记得是课上还是课后--\nDialogue: 0,0:43:51.47,0:43:53.88,Default,,0,0,0,,你向我们展示了\nDialogue: 0,0:43:54.00,0:43:57.52,Default,,0,0,0,,ADD操作有一些我们看不到的基本运算\nDialogue: 0,0:43:57.69,0:43:59.21,Default,,0,0,0,,类似于ADD%之类的\nDialogue: 0,0:43:59.82,0:44:01.65,Default,,0,0,0,,这是因为\nDialogue: 0,0:44:01.65,0:44:02.60,Default,,0,0,0,,你想把代码内联为\nDialogue: 0,0:44:02.60,0:44:08.19,Default,,0,0,0,,专门针对二元运算对象的运算么？\nDialogue: 0,0:44:08.70,0:44:10.25,Default,,0,0,0,,但如果你有更多的运算对象\nDialogue: 0,0:44:10.28,0:44:11.47,Default,,0,0,0,,你会做什么特殊的事情吗？\nDialogue: 0,0:44:12.71,0:44:16.04,Default,,0,0,0,,教授: 你看的是Scheme的实际实现\nDialogue: 0,0:44:16.06,0:44:17.84,Default,,0,0,0,,其中有一个‘+’ 这是一个运算符\nDialogue: 0,0:44:17.90,0:44:20.19,Default,,0,0,0,,如果你看‘+’的源代码\nDialogue: 0,0:44:20.33,0:44:21.37,Default,,0,0,0,,你会看到一些叫做--\nDialogue: 0,0:44:21.57,0:44:24.14,Default,,0,0,0,,我记不清了--可能叫ADD%、PLUS之类的东西\nDialogue: 0,0:44:24.55,0:44:25.79,Default,,0,0,0,,这里所进行的\nDialogue: 0,0:44:25.79,0:44:27.92,Default,,0,0,0,,就是你说的那种优化\nDialogue: 0,0:44:28.47,0:44:31.87,Default,,0,0,0,,因为 广义的‘+’接受任意数量的参数\nDialogue: 0,0:44:35.02,0:44:36.38,Default,,0,0,0,,所以 广义加法\nDialogue: 0,0:44:36.76,0:44:38.25,Default,,0,0,0,,会说：如果我有一个参数表\nDialogue: 0,0:44:38.28,0:44:40.62,Default,,0,0,0,,我最好将它们用CONS连接到表里\nDialogue: 0,0:44:41.63,0:44:44.14,Default,,0,0,0,,并指出有多少个参数\nDialogue: 0,0:44:44.72,0:44:46.16,Default,,0,0,0,,这样效率非常低下\nDialogue: 0,0:44:46.81,0:44:49.25,Default,,0,0,0,,因为大部分时间你在把两个数相加\nDialogue: 0,0:44:49.25,0:44:51.24,Default,,0,0,0,,你不必把整个参数表连接到一起\nDialogue: 0,0:44:52.04,0:44:53.93,Default,,0,0,0,,所以你想做的是\nDialogue: 0,0:44:55.66,0:44:57.71,Default,,0,0,0,,构建把一堆东西相加的代码\nDialogue: 0,0:44:58.15,0:45:00.17,Default,,0,0,0,,所以它做的大部分事情是一样的\nDialogue: 0,0:45:00.49,0:45:01.95,Default,,0,0,0,,但这里可能有个特殊的入口\nDialogue: 0,0:45:01.98,0:45:03.92,Default,,0,0,0,,如果你知道只有两个参数\nDialogue: 0,0:45:04.56,0:45:05.87,Default,,0,0,0,,你会把它们放到寄存器中\nDialogue: 0,0:45:05.87,0:45:06.97,Default,,0,0,0,,它们不需要参数表\nDialogue: 0,0:45:06.99,0:45:07.98,Default,,0,0,0,,你也不必用CONS连接它们\nDialogue: 0,0:45:08.67,0:45:10.42,Default,,0,0,0,,这就是这些东西工作的原理\nDialogue: 0,0:45:12.30,0:45:13.72,Default,,0,0,0,,好吧 下课吧\nDialogue: 0,0:45:14.10,0:45:42.97,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:45:14.10,0:45:42.97,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec10a.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 6\nVideo Position: 355\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.01,0:00:05.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N杨启钊\\N（windfarer）\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:05.37,0:00:11.84,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:05.37,0:00:11.84,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:11.84,0:00:13.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}编译\nDialogue: 0,0:00:19.36,0:00:22.65,Default,,0,0,0,,教授: 上节课 我们学习了\nDialogue: 0,0:00:22.65,0:00:25.67,Default,,0,0,0,,一个显式控制的Lisp求值器\nDialogue: 0,0:00:25.67,0:00:28.97,Default,,0,0,0,,它弥合了像Lisp\nDialogue: 0,0:00:29.05,0:00:32.14,Default,,0,0,0,,或者查询语言之类的高级语言\nDialogue: 0,0:00:32.50,0:00:36.16,Default,,0,0,0,,与传统寄存器机器之间的鸿沟\nDialogue: 0,0:00:36.70,0:00:40.14,Default,,0,0,0,,事实上 你可以将显式控制求值器\nDialogue: 0,0:00:40.16,0:00:44.38,Default,,0,0,0,,看作是 在一台常见的\nDialogue: 0,0:00:44.40,0:00:45.95,Default,,0,0,0,,寄存机器上实现的\nDialogue: 0,0:00:46.52,0:00:49.50,Default,,0,0,0,,Lisp求值器的汇编代码\nDialogue: 0,0:00:49.50,0:00:51.50,Default,,0,0,0,,或者 你可以把它看做是\nDialogue: 0,0:00:52.08,0:00:54.56,Default,,0,0,0,,某台专门运行Lisp的机器的微程序\nDialogue: 0,0:00:55.20,0:00:55.92,Default,,0,0,0,,无论是那种情况\nDialogue: 0,0:00:55.92,0:00:58.68,Default,,0,0,0,,我们都是把一台\nDialogue: 0,0:00:58.94,0:01:00.51,Default,,0,0,0,,处理低级语言的机器\nDialogue: 0,0:01:01.42,0:01:03.32,Default,,0,0,0,,抬高到一个层次\nDialogue: 0,0:01:03.37,0:01:04.88,Default,,0,0,0,,以便处理像Lisp这样的高级语言\nDialogue: 0,0:01:05.36,0:01:06.35,Default,,0,0,0,,这是通过编写解释器来实现的\nDialogue: 0,0:01:08.22,0:01:09.58,Default,,0,0,0,,来看个例子\nDialogue: 0,0:01:11.82,0:01:13.77,Default,,0,0,0,,这里 从概念上来说\nDialogue: 0,0:01:18.01,0:01:19.47,Default,,0,0,0,,从概念上来说 这是一台\nDialogue: 0,0:01:20.54,0:01:23.44,Default,,0,0,0,,专用于计算阶乘的机器\nDialogue: 0,0:01:24.09,0:01:27.39,Default,,0,0,0,,输入5 输出120\nDialogue: 0,0:01:28.92,0:01:30.83,Default,,0,0,0,,这个专用机器实际上\nDialogue: 0,0:01:30.97,0:01:32.72,Default,,0,0,0,,是一个Lisp解释器\nDialogue: 0,0:01:33.50,0:01:36.17,Default,,0,0,0,,它将自己配置为计算阶乘\nDialogue: 0,0:01:38.35,0:01:40.99,Default,,0,0,0,,因为你向它送入了一台阶乘机器的描述\nDialogue: 0,0:01:42.12,0:01:43.70,Default,,0,0,0,,这就是解释器\nDialogue: 0,0:01:43.70,0:01:45.66,Default,,0,0,0,,它将自己配置为\nDialogue: 0,0:01:46.37,0:01:49.24,Default,,0,0,0,,模拟你所输入描述的机器\nDialogue: 0,0:01:50.07,0:01:51.93,Default,,0,0,0,,那么 在Lisp解释器里是什么?\nDialogue: 0,0:01:52.04,0:01:55.44,Default,,0,0,0,,里面可能是通用的寄存器语言解释器\nDialogue: 0,0:01:56.98,0:02:00.18,Default,,0,0,0,,它将自己配置成像Lisp解释器那样\nDialogue: 0,0:02:00.18,0:02:02.03,Default,,0,0,0,,因为你输入了一系列用寄存器语言\nDialogue: 0,0:02:02.12,0:02:03.04,Default,,0,0,0,,编写的指令\nDialogue: 0,0:02:03.37,0:02:05.16,Default,,0,0,0,,这就是显式控制求值器\nDialogue: 0,0:02:07.05,0:02:08.70,Default,,0,0,0,,它里面也有一些库\nDialogue: 0,0:02:08.73,0:02:11.08,Default,,0,0,0,,由基本运算符和Lisp运算\nDialogue: 0,0:02:11.12,0:02:12.28,Default,,0,0,0,,等等要素组成\nDialogue: 0,0:02:12.75,0:02:16.89,Default,,0,0,0,,这是解释执行的一般策略\nDialogue: 0,0:02:17.32,0:02:18.51,Default,,0,0,0,,事实上 我们所做的是\nDialogue: 0,0:02:18.60,0:02:20.14,Default,,0,0,0,,通过编写解释器\nDialogue: 0,0:02:21.62,0:02:23.40,Default,,0,0,0,,将机器抬升到\nDialogue: 0,0:02:23.42,0:02:25.24,Default,,0,0,0,,我们程序所在的层次\nDialogue: 0,0:02:25.24,0:02:26.72,Default,,0,0,0,,当然 还有另外一种策略\nDialogue: 0,0:02:27.42,0:02:28.89,Default,,0,0,0,,这种不同的策略就是编译\nDialogue: 0,0:02:29.04,0:02:30.43,Default,,0,0,0,,编译有一些不同\nDialogue: 0,0:02:31.04,0:02:31.50,Default,,0,0,0,,这里\nDialogue: 0,0:02:33.37,0:02:34.75,Default,,0,0,0,,我们可能已经实现了\nDialogue: 0,0:02:35.67,0:02:38.52,Default,,0,0,0,,一个特定用途的机器\nDialogue: 0,0:02:38.62,0:02:39.98,Default,,0,0,0,,用来计算阶乘\nDialogue: 0,0:02:43.62,0:02:46.26,Default,,0,0,0,,从某种使用寄存器语言的机器开始\nDialogue: 0,0:02:46.26,0:02:47.72,Default,,0,0,0,,但是 我们将让它执行不同的策略\nDialogue: 0,0:02:47.72,0:02:50.38,Default,,0,0,0,,把我们的阶乘程序\nDialogue: 0,0:02:51.55,0:02:53.92,Default,,0,0,0,,作为源代码输入编译器\nDialogue: 0,0:02:53.92,0:02:55.15,Default,,0,0,0,,编译器就会\nDialogue: 0,0:02:55.15,0:02:57.62,Default,,0,0,0,,把这个阶乘程序\nDialogue: 0,0:02:57.62,0:02:59.07,Default,,0,0,0,,翻译成某种寄存器机器语言\nDialogue: 0,0:03:00.25,0:03:03.40,Default,,0,0,0,,现在它并不是Lisp的显式控制求值器\nDialogue: 0,0:03:03.40,0:03:06.17,Default,,0,0,0,,而是某种用来计算阶乘的寄存器语言\nDialogue: 0,0:03:06.49,0:03:08.36,Default,,0,0,0,,这就是翻译的过程\nDialogue: 0,0:03:10.54,0:03:12.41,Default,,0,0,0,,它将进入某种加载器\nDialogue: 0,0:03:13.35,0:03:15.21,Default,,0,0,0,,它会把这些代码\nDialogue: 0,0:03:15.31,0:03:16.84,Default,,0,0,0,,和从程序库中选取的代码\nDialogue: 0,0:03:16.86,0:03:18.65,Default,,0,0,0,,比如乘法运算等 结合在一起\nDialogue: 0,0:03:19.82,0:03:21.69,Default,,0,0,0,,随后我们将生成一个加载模块\nDialogue: 0,0:03:22.22,0:03:25.06,Default,,0,0,0,,它把寄存器语言机器配置成\nDialogue: 0,0:03:25.06,0:03:27.24,Default,,0,0,0,,一个专门用来计算阶乘的机器\nDialogue: 0,0:03:28.12,0:03:30.22,Default,,0,0,0,,这就是不同的策略\nDialogue: 0,0:03:30.22,0:03:31.22,Default,,0,0,0,,在解释中\nDialogue: 0,0:03:31.22,0:03:32.01,Default,,0,0,0,,我们把机器\nDialogue: 0,0:03:32.91,0:03:35.23,Default,,0,0,0,,抬升到Lisp语言的层次\nDialogue: 0,0:03:35.32,0:03:36.34,Default,,0,0,0,,而在编译中\nDialogue: 0,0:03:36.34,0:03:38.43,Default,,0,0,0,,我们将我们的程序下降到\nDialogue: 0,0:03:38.48,0:03:40.56,Default,,0,0,0,,机器语言的层次\nDialogue: 0,0:03:41.96,0:03:43.84,Default,,0,0,0,,那么 这两个策略有什么区别呢?\nDialogue: 0,0:03:44.30,0:03:49.42,Default,,0,0,0,,编译器可以生成执行起来更有效率的代码\nDialogue: 0,0:03:52.05,0:03:53.90,Default,,0,0,0,,主要原因是\nDialogue: 0,0:03:54.17,0:03:58.89,Default,,0,0,0,,如果你考虑运行中的寄存器操作\nDialogue: 0,0:04:01.92,0:04:04.49,Default,,0,0,0,,解释器需要生成寄存器的操作\nDialogue: 0,0:04:04.97,0:04:06.75,Default,,0,0,0,,从原则上来讲 它需要足够通用\nDialogue: 0,0:04:07.32,0:04:08.94,Default,,0,0,0,,以支持任何Lisp过程的执行\nDialogue: 0,0:04:10.22,0:04:12.25,Default,,0,0,0,,而编译器只需要\nDialogue: 0,0:04:12.27,0:04:14.92,Default,,0,0,0,,生成一组特定的寄存器操作\nDialogue: 0,0:04:15.52,0:04:18.22,Default,,0,0,0,,用来执行你所编译的那部分特定的Lisp过程\nDialogue: 0,0:04:20.17,0:04:21.20,Default,,0,0,0,,换一种说法\nDialogue: 0,0:04:21.20,0:04:25.31,Default,,0,0,0,,解释器是一种通用的模拟器\nDialogue: 0,0:04:25.92,0:04:27.58,Default,,0,0,0,,当你输入一个Lisp过程时\nDialogue: 0,0:04:27.58,0:04:31.32,Default,,0,0,0,,它们就会模拟那个过程所描述的程序\nDialogue: 0,0:04:31.32,0:04:33.87,Default,,0,0,0,,所以解释器旨在成为一个通用模拟器\nDialogue: 0,0:04:34.62,0:04:35.96,Default,,0,0,0,,而编译器 实际上\nDialogue: 0,0:04:36.00,0:04:37.68,Default,,0,0,0,,只需要将东西配置成\nDialogue: 0,0:04:37.71,0:04:39.34,Default,,0,0,0,,解释器将要去模拟的机器\nDialogue: 0,0:04:40.02,0:04:41.34,Default,,0,0,0,,所以编译器可以运行得更快\nDialogue: 0,0:04:52.55,0:04:53.64,Default,,0,0,0,,另一方面\nDialogue: 0,0:04:55.97,0:04:58.28,Default,,0,0,0,,解释器更适合用来排查错误\nDialogue: 0,0:04:59.43,0:05:01.25,Default,,0,0,0,,这是因为\nDialogue: 0,0:05:01.57,0:05:03.02,Default,,0,0,0,,我们的源代码实际上就在那里\nDialogue: 0,0:05:03.02,0:05:04.81,Default,,0,0,0,,我们正在解释它们\nDialogue: 0,0:05:05.87,0:05:07.69,Default,,0,0,0,,并且库也在其中\nDialogue: 0,0:05:07.90,0:05:10.89,Default,,0,0,0,,看 库是解释器的一部分\nDialogue: 0,0:05:11.30,0:05:13.16,Default,,0,0,0,,而编译器只会拉取\nDialogue: 0,0:05:13.20,0:05:14.56,Default,,0,0,0,,运行程序所需要的代码\nDialogue: 0,0:05:14.87,0:05:17.00,Default,,0,0,0,,所以 如果你在排查错误的途中\nDialogue: 0,0:05:18.00,0:05:20.72,Default,,0,0,0,,你想写一些额外的代码\nDialogue: 0,0:05:20.80,0:05:22.57,Default,,0,0,0,,来考察运行过程中的数据类型\nDialogue: 0,0:05:23.05,0:05:24.25,Default,,0,0,0,,或者做一些\nDialogue: 0,0:05:24.30,0:05:25.92,Default,,0,0,0,,在写程序时没有想到的计算\nDialogue: 0,0:05:25.95,0:05:27.53,Default,,0,0,0,,解释器可以完美搞定这些\nDialogue: 0,0:05:28.05,0:05:29.21,Default,,0,0,0,,而编译器不行\nDialogue: 0,0:05:29.62,0:05:31.90,Default,,0,0,0,,所以它们各有优点\nDialogue: 0,0:05:31.90,0:05:34.48,Default,,0,0,0,,编译器将生成运行更快的代码\nDialogue: 0,0:05:34.85,0:05:37.02,Default,,0,0,0,,而解释器是一种更适合排错的环境\nDialogue: 0,0:05:38.95,0:05:41.40,Default,,0,0,0,,大多数Lisp系统最终将二者都实现了\nDialogue: 0,0:05:42.92,0:05:45.23,Default,,0,0,0,,这样你就可以在开发阶段\nDialogue: 0,0:05:45.24,0:05:47.08,Default,,0,0,0,,可以使用解释器\nDialogue: 0,0:05:47.08,0:05:48.62,Default,,0,0,0,,随后通过编译加速代码的运行\nDialogue: 0,0:05:49.02,0:05:50.03,Default,,0,0,0,,并且通常\nDialogue: 0,0:05:50.04,0:05:51.68,Default,,0,0,0,,你能够让被编译的代码\nDialogue: 0,0:05:51.69,0:05:53.56,Default,,0,0,0,,和被解释的代码互相调用\nDialogue: 0,0:05:54.60,0:05:56.33,Default,,0,0,0,,我们将学习如何做到 其实不难\nDialogue: 0,0:05:59.27,0:05:59.85,Default,,0,0,0,,好\nDialogue: 0,0:06:00.97,0:06:02.09,Default,,0,0,0,,事实上\nDialogue: 0,0:06:04.30,0:06:05.75,Default,,0,0,0,,在我们将要构建的编译器中\nDialogue: 0,0:06:05.75,0:06:07.58,Default,,0,0,0,,我们实现编译的代码和解释的代码\nDialogue: 0,0:06:07.58,0:06:09.45,Default,,0,0,0,,互相调用的方式是\nDialogue: 0,0:06:09.90,0:06:12.06,Default,,0,0,0,,我们让编译器和解释器使用\nDialogue: 0,0:06:12.11,0:06:14.40,Default,,0,0,0,,使用完全一致的寄存器约定\nDialogue: 0,0:06:18.42,0:06:21.72,Default,,0,0,0,,编译器的理念\nDialogue: 0,0:06:21.76,0:06:25.74,Default,,0,0,0,,与解释器或求值器的理念很像\nDialogue: 0,0:06:25.87,0:06:26.46,Default,,0,0,0,,它们是相同的\nDialogue: 0,0:06:27.05,0:06:29.39,Default,,0,0,0,,求值器遍历代码\nDialogue: 0,0:06:29.82,0:06:32.35,Default,,0,0,0,,产生一些寄存器操作\nDialogue: 0,0:06:33.65,0:06:34.97,Default,,0,0,0,,就是我们昨天做的事情\nDialogue: 0,0:06:37.10,0:06:40.27,Default,,0,0,0,,而编译器会读取代码\nDialogue: 0,0:06:40.52,0:06:43.00,Default,,0,0,0,,生成一些进行求值时\nDialogue: 0,0:06:43.04,0:06:44.67,Default,,0,0,0,,求值器会进行的\nDialogue: 0,0:06:45.23,0:06:46.64,Default,,0,0,0,,相关寄存器操作\nDialogue: 0,0:06:48.60,0:06:49.95,Default,,0,0,0,,这就给我们提供了一个模型\nDialogue: 0,0:06:50.60,0:06:53.77,Default,,0,0,0,,来实现一个零阶编译器\nDialogue: 0,0:06:55.30,0:06:58.32,Default,,0,0,0,,一个很差劲但是能用的编译器\nDialogue: 0,0:06:58.32,0:06:59.32,Default,,0,0,0,,这种模型就是\nDialogue: 0,0:06:59.36,0:07:00.59,Default,,0,0,0,,你用求值器\nDialogue: 0,0:07:00.68,0:07:01.88,Default,,0,0,0,,把代码跑一遍\nDialogue: 0,0:07:02.80,0:07:06.06,Default,,0,0,0,,但不去执行实际的操作\nDialogue: 0,0:07:06.06,0:07:07.15,Default,,0,0,0,,只是把它们保存下来\nDialogue: 0,0:07:07.55,0:07:08.82,Default,,0,0,0,,那就是你编译后的代码\nDialogue: 0,0:07:08.82,0:07:10.24,Default,,0,0,0,,让我举个例子\nDialogue: 0,0:07:12.70,0:07:14.14,Default,,0,0,0,,假设我们要编译\nDialogue: 0,0:07:15.10,0:07:17.90,Default,,0,0,0,,编译(F X) 这个表达式\nDialogue: 0,0:07:25.07,0:07:25.96,Default,,0,0,0,,我们假设\nDialogue: 0,0:07:25.96,0:07:28.06,Default,,0,0,0,,EXP寄存器中保存着(F X)\nDialogue: 0,0:07:28.06,0:07:29.55,Default,,0,0,0,,而ENV寄存器又保存着其它东西\nDialogue: 0,0:07:30.10,0:07:32.20,Default,,0,0,0,,想象我们启动了求值器\nDialogue: 0,0:07:34.60,0:07:35.71,Default,,0,0,0,,它读取了表达式\nDialogue: 0,0:07:35.71,0:07:37.36,Default,,0,0,0,,判断它是一个应用\nDialogue: 0,0:07:37.92,0:07:41.90,Default,,0,0,0,,它分支到求值器代码中的一个地方\nDialogue: 0,0:07:42.52,0:07:45.15,Default,,0,0,0,,我们之前见过的叫EV-APPLICATION的地方\nDialogue: 0,0:07:47.12,0:07:48.12,Default,,0,0,0,,然后继续处理\nDialogue: 0,0:07:48.16,0:07:50.08,Default,,0,0,0,,恢复运算对象和UNEV\nDialogue: 0,0:07:50.08,0:07:52.44,Default,,0,0,0,,然后之后它将运算符放在EXP寄存器中\nDialogue: 0,0:07:52.48,0:07:54.27,Default,,0,0,0,,递归地对它求值\nDialogue: 0,0:07:54.47,0:07:56.08,Default,,0,0,0,,这就是我们经历的过程\nDialogue: 0,0:07:56.67,0:07:57.84,Default,,0,0,0,,如果你看代码\nDialogue: 0,0:07:57.87,0:07:59.74,Default,,0,0,0,,会看到一些寄存器操作\nDialogue: 0,0:08:00.20,0:08:02.30,Default,,0,0,0,,你会看到将运算对象赋值给UNEV寄存器\nDialogue: 0,0:08:02.30,0:08:03.95,Default,,0,0,0,,把运算符赋值给EXP\nDialogue: 0,0:08:04.09,0:08:06.20,Default,,0,0,0,,保存环境、生成新环境 等等\nDialogue: 0,0:08:10.22,0:08:11.93,Default,,0,0,0,,如果我们来看下这里的投影\nDialogue: 0,0:08:15.75,0:08:19.58,Default,,0,0,0,,我们会看到产生的这些操作\nDialogue: 0,0:08:20.82,0:08:22.52,Default,,0,0,0,,这是求值器实际要进行的\nDialogue: 0,0:08:22.72,0:08:24.80,Default,,0,0,0,,第一个操作\nDialogue: 0,0:08:25.00,0:08:27.20,Default,,0,0,0,,它将运算对象从EXP寄存器里取出来\nDialogue: 0,0:08:27.47,0:08:28.62,Default,,0,0,0,,并将它赋值给UNEV\nDialogue: 0,0:08:30.03,0:08:32.27,Default,,0,0,0,,然后它给EXP寄存器赋了某个值\nDialogue: 0,0:08:32.30,0:08:33.46,Default,,0,0,0,,然后保存CONTINUE\nDialogue: 0,0:08:33.46,0:08:34.62,Default,,0,0,0,,保存ENV\nDialogue: 0,0:08:34.62,0:08:38.65,Default,,0,0,0,,我在这里就只是寄存器赋值\nDialogue: 0,0:08:39.57,0:08:42.32,Default,,0,0,0,,这就是求值器求值代码时进行的操作\nDialogue: 0,0:08:42.77,0:08:43.79,Default,,0,0,0,,我们缩小画面看看\nDialogue: 0,0:08:44.30,0:08:47.13,Default,,0,0,0,,总计有19个操作\nDialogue: 0,0:08:49.40,0:08:51.64,Default,,0,0,0,,这些代码\nDialogue: 0,0:08:52.05,0:08:53.90,Default,,0,0,0,,对应着\nDialogue: 0,0:08:54.75,0:08:57.10,Default,,0,0,0,,求值器跳转到APPLY-DISPATCH代码之前\nDialogue: 0,0:08:57.86,0:08:59.16,Default,,0,0,0,,事实上 在这个编译器中\nDialogue: 0,0:08:59.20,0:09:01.18,Default,,0,0,0,,我们不需要再关心APPLY-DISPATCH了\nDialogue: 0,0:09:01.30,0:09:02.11,Default,,0,0,0,,我们有所有东西\nDialogue: 0,0:09:02.35,0:09:05.04,Default,,0,0,0,,我们拥有解释后和编译后的所有代码\nDialogue: 0,0:09:06.07,0:09:07.61,Default,,0,0,0,,通常求值过程\nDialogue: 0,0:09:07.61,0:09:09.85,Default,,0,0,0,,是由APPLY-DISPATCH处理的\nDialogue: 0,0:09:10.27,0:09:12.32,Default,,0,0,0,,这将让被解释后代码与编译后代码\nDialogue: 0,0:09:12.36,0:09:13.71,Default,,0,0,0,,很容易互相调用\nDialogue: 0,0:09:18.27,0:09:19.87,Default,,0,0,0,,从原理上来说 这样做足矣\nDialogue: 0,0:09:21.05,0:09:22.66,Default,,0,0,0,,只需运行求值器\nDialogue: 0,0:09:22.66,0:09:24.50,Default,,0,0,0,,因而编译器非常像求值器\nDialogue: 0,0:09:24.50,0:09:26.47,Default,,0,0,0,,你运行它 唯一不同是你把操作存下来\nDialogue: 0,0:09:26.47,0:09:28.40,Default,,0,0,0,,而不是实际执行它们\nDialogue: 0,0:09:29.35,0:09:31.39,Default,,0,0,0,,这其实不完全正确\nDialogue: 0,0:09:32.91,0:09:34.99,Default,,0,0,0,,这里面我们撒了个小谎\nDialogue: 0,0:09:36.24,0:09:39.29,Default,,0,0,0,,你需要关心的是：如果有个谓词\nDialogue: 0,0:09:40.12,0:09:42.16,Default,,0,0,0,,如果你要进行某种测试\nDialogue: 0,0:09:43.45,0:09:46.03,Default,,0,0,0,,显然 在你编译时\nDialogue: 0,0:09:46.52,0:09:47.98,Default,,0,0,0,,你不知道这些分支中\nDialogue: 0,0:09:48.32,0:09:50.14,Default,,0,0,0,,哪条分支会被执行\nDialogue: 0,0:09:51.13,0:09:53.92,Default,,0,0,0,,所以你不能确定求值器将对哪个求值\nDialogue: 0,0:09:54.90,0:09:57.12,Default,,0,0,0,,因此在这里就很简单\nDialogue: 0,0:09:57.12,0:09:58.49,Default,,0,0,0,,你把两个分支全编译了\nDialogue: 0,0:09:59.32,0:10:01.29,Default,,0,0,0,,因此你编译出一个这样的结构\nDialogue: 0,0:10:02.00,0:10:03.98,Default,,0,0,0,,它们都会被编译成\nDialogue: 0,0:10:05.31,0:10:09.15,Default,,0,0,0,,首先是P的代码\nDialogue: 0,0:10:10.71,0:10:16.51,Default,,0,0,0,,它把结果存入VAL寄存器\nDialogue: 0,0:10:18.17,0:10:20.64,Default,,0,0,0,,解释器对谓词求值\nDialogue: 0,0:10:21.35,0:10:24.19,Default,,0,0,0,,并保证结果会放到VAL寄存器中\nDialogue: 0,0:10:24.70,0:10:27.22,Default,,0,0,0,,随后你编译一条指令\nDialogue: 0,0:10:27.22,0:10:33.79,Default,,0,0,0,,如果VAL是TRUE\nDialogue: 0,0:10:37.17,0:10:38.75,Default,,0,0,0,,就转到LABEL1这个地方\nDialogue: 0,0:10:44.97,0:10:47.52,Default,,0,0,0,,然后我们写下B的代码\nDialogue: 0,0:10:49.42,0:10:52.32,Default,,0,0,0,,让解释器对B进行求值\nDialogue: 0,0:10:53.62,0:10:57.21,Default,,0,0,0,,然后写一句指令\nDialogue: 0,0:10:57.23,0:10:58.75,Default,,0,0,0,,用来跳转到下一条指令\nDialogue: 0,0:11:02.20,0:11:04.56,Default,,0,0,0,,就是它结束之后要去的地方\nDialogue: 0,0:11:04.95,0:11:06.09,Default,,0,0,0,,你放入那个指令\nDialogue: 0,0:11:06.88,0:11:08.62,Default,,0,0,0,,这里你写下LABEL1\nDialogue: 0,0:11:12.12,0:11:13.80,Default,,0,0,0,,这里写A的代码\nDialogue: 0,0:11:19.47,0:11:25.85,Default,,0,0,0,,然后又是跳转到下一条指令\nDialogue: 0,0:11:31.42,0:11:32.88,Default,,0,0,0,,这就是处理条件分支的办法\nDialogue: 0,0:11:32.98,0:11:34.65,Default,,0,0,0,,你生成一小段这样的代码\nDialogue: 0,0:11:35.75,0:11:38.12,Default,,0,0,0,,除此之外\nDialogue: 0,0:11:38.95,0:11:41.55,Default,,0,0,0,,这个零阶编译器与求值器一模一样\nDialogue: 0,0:11:42.55,0:11:45.12,Default,,0,0,0,,它只是把指令存起来 而不执行它们\nDialogue: 0,0:11:46.55,0:11:47.60,Default,,0,0,0,,看起来很简单\nDialogue: 0,0:11:47.64,0:11:49.08,Default,,0,0,0,,但我们已经取得了某些收获\nDialogue: 0,0:11:50.12,0:11:52.62,Default,,0,0,0,,它会比求值器更有效率\nDialogue: 0,0:11:53.52,0:11:56.14,Default,,0,0,0,,因为 如果你观察求值器的运行\nDialogue: 0,0:11:56.35,0:12:01.05,Default,,0,0,0,,它并不只是进行寄存器操作\nDialogue: 0,0:12:01.27,0:12:03.50,Default,,0,0,0,,它还会决定执行哪个\nDialogue: 0,0:12:04.70,0:12:07.23,Default,,0,0,0,,它做的第一件事就是\nDialogue: 0,0:12:07.92,0:12:09.77,Default,,0,0,0,,以它为例 就是进行某些测试\nDialogue: 0,0:12:09.77,0:12:11.56,Default,,0,0,0,,确定它是一个应用\nDialogue: 0,0:12:13.57,0:12:15.05,Default,,0,0,0,,然后就跳转到\nDialogue: 0,0:12:15.39,0:12:16.62,Default,,0,0,0,,处理应用的地方去\nDialogue: 0,0:12:16.62,0:12:18.44,Default,,0,0,0,,换句话说 求值器做的事情是\nDialogue: 0,0:12:18.62,0:12:22.76,Default,,0,0,0,,分析代码需要进行的运算\nDialogue: 0,0:12:23.47,0:12:24.99,Default,,0,0,0,,同时并执行它们\nDialogue: 0,0:12:25.55,0:12:28.28,Default,,0,0,0,,当你运行求值器一百万次\nDialogue: 0,0:12:28.28,0:12:30.30,Default,,0,0,0,,这个分析过程就进行一百万次\nDialogue: 0,0:12:30.85,0:12:32.58,Default,,0,0,0,,而在编译器中 它只会进行一次\nDialogue: 0,0:12:32.58,0:12:34.81,Default,,0,0,0,,之后就只有寄存器操作了\nDialogue: 0,0:12:39.20,0:12:41.68,Default,,0,0,0,,这就是零阶编译器了\nDialogue: 0,0:12:41.80,0:12:44.04,Default,,0,0,0,,但它是个拙劣的编译器\nDialogue: 0,0:12:44.45,0:12:45.28,Default,,0,0,0,,它挺蠢的\nDialogue: 0,0:12:46.90,0:12:48.41,Default,,0,0,0,,让我们回过头来\nDialogue: 0,0:12:49.88,0:12:50.97,Default,,0,0,0,,看看这张投影\nDialogue: 0,0:12:52.02,0:12:55.29,Default,,0,0,0,,看看这个东西做的一些操作\nDialogue: 0,0:12:55.85,0:12:56.88,Default,,0,0,0,,我们想看看\nDialogue: 0,0:12:59.72,0:13:02.28,Default,,0,0,0,,在解释(F  X)时的操作\nDialogue: 0,0:13:03.52,0:13:04.84,Default,,0,0,0,,这里就是它做了什么\nDialogue: 0,0:13:05.17,0:13:06.11,Default,,0,0,0,,举个例子 这里\nDialogue: 0,0:13:07.15,0:13:11.98,Default,,0,0,0,,它将(OPERATOR (FETCH EXP))赋值给EXP\nDialogue: 0,0:13:13.75,0:13:15.87,Default,,0,0,0,,其实没必要这样做\nDialogue: 0,0:13:16.22,0:13:17.47,Default,,0,0,0,,因为编译器知道\nDialogue: 0,0:13:17.66,0:13:21.84,Default,,0,0,0,,(OPERATOR (FETCH EXP))的值就是F\nDialogue: 0,0:13:23.35,0:13:25.56,Default,,0,0,0,,因此这个指令没理由存在\nDialogue: 0,0:13:25.70,0:13:28.88,Default,,0,0,0,,应该改为：要把F赋值给EXP\nDialogue: 0,0:13:29.45,0:13:31.08,Default,,0,0,0,,或者实际上 你完全不需要EXP\nDialogue: 0,0:13:31.87,0:13:33.56,Default,,0,0,0,,没有理由需要EXP\nDialogue: 0,0:13:33.56,0:13:35.16,Default,,0,0,0,,EXP是用来做什么的?\nDialogue: 0,0:13:35.18,0:13:36.33,Default,,0,0,0,,我们看这里\nDialogue: 0,0:13:40.77,0:13:42.20,Default,,0,0,0,,我们对VAL赋值\nDialogue: 0,0:13:43.05,0:13:47.34,Default,,0,0,0,,在环境里的EXP里寻找东西\nDialogue: 0,0:13:48.68,0:13:49.53,Default,,0,0,0,,因此 我们实际上是要\nDialogue: 0,0:13:49.55,0:13:51.54,Default,,0,0,0,,替换掉所有的EXP寄存器\nDialogue: 0,0:13:51.54,0:13:53.32,Default,,0,0,0,,把这个指令修改为\nDialogue: 0,0:13:53.34,0:13:54.16,Default,,0,0,0,,给VAL赋值\nDialogue: 0,0:13:54.45,0:13:56.06,Default,,0,0,0,,在环境中查找\nDialogue: 0,0:13:56.36,0:13:58.40,Default,,0,0,0,,符号F的值\nDialogue: 0,0:14:01.09,0:14:01.77,Default,,0,0,0,,类似地\nDialogue: 0,0:14:02.57,0:14:04.27,Default,,0,0,0,,回到这里 我们也完全不需要UNEV\nDialogue: 0,0:14:04.72,0:14:05.79,Default,,0,0,0,,因为我们知道\nDialogue: 0,0:14:06.22,0:14:09.16,Default,,0,0,0,,因为我们知道 (FETCH EXP)取出的运算对象\nDialogue: 0,0:14:09.16,0:14:10.62,Default,,0,0,0,,就是'(X)\nDialogue: 0,0:14:13.25,0:14:14.06,Default,,0,0,0,,从某种意义上来说\nDialogue: 0,0:14:16.17,0:14:19.39,Default,,0,0,0,,你完全不需要UNEV和EXP\nDialogue: 0,0:14:19.67,0:14:21.05,Default,,0,0,0,,看看它们实际上是什么\nDialogue: 0,0:14:21.08,0:14:25.30,Default,,0,0,0,,它们不是实际运行机器的寄存器\nDialogue: 0,0:14:25.30,0:14:26.40,Default,,0,0,0,,它们实际上是\nDialogue: 0,0:14:26.60,0:14:29.50,Default,,0,0,0,,为了模拟该机器的而设置的寄存器\nDialogue: 0,0:14:30.72,0:14:33.77,Default,,0,0,0,,所以它们保存一些表达式\nDialogue: 0,0:14:34.00,0:14:36.04,Default,,0,0,0,,以编译器的视角看来\nDialogue: 0,0:14:36.06,0:14:36.81,Default,,0,0,0,,它们就是常量\nDialogue: 0,0:14:36.95,0:14:38.48,Default,,0,0,0,,因此可以直接把它们放到代码中\nDialogue: 0,0:14:39.47,0:14:41.34,Default,,0,0,0,,你可以忘掉那些关于\nDialogue: 0,0:14:41.36,0:14:42.54,Default,,0,0,0,,EXP和UNEV的操作\nDialogue: 0,0:14:42.57,0:14:43.77,Default,,0,0,0,,只用那些常量\nDialogue: 0,0:14:44.02,0:14:48.00,Default,,0,0,0,,与之相似 如果我们回顾这里\nDialogue: 0,0:14:48.00,0:14:51.32,Default,,0,0,0,,有像(ASSIGN CONTINUE EVAL-ARGS)之类的语句\nDialogue: 0,0:14:53.75,0:14:55.39,Default,,0,0,0,,现在 它和任何东西都没有关系\nDialogue: 0,0:14:55.62,0:14:57.76,Default,,0,0,0,,它只是求值器\nDialogue: 0,0:14:58.08,0:15:00.17,Default,,0,0,0,,维护了下一步需要去哪\nDialogue: 0,0:15:02.70,0:15:05.96,Default,,0,0,0,,在某些应用中对参数进行求值\nDialogue: 0,0:15:06.82,0:15:08.65,Default,,0,0,0,,当然 这与编译器没关系\nDialogue: 0,0:15:08.65,0:15:13.88,Default,,0,0,0,,因为这个分析过程已经被编译器做完了\nDialogue: 0,0:15:15.05,0:15:16.83,Default,,0,0,0,,所以编译后的代码完全不需要它\nDialogue: 0,0:15:17.70,0:15:19.32,Default,,0,0,0,,因此许多向CONTINUE寄存器\nDialogue: 0,0:15:19.32,0:15:21.30,Default,,0,0,0,,赋值的操作都是无用的\nDialogue: 0,0:15:21.30,0:15:24.62,Default,,0,0,0,,运行着的机器留着它们\nDialogue: 0,0:15:24.64,0:15:25.77,Default,,0,0,0,,是为了跟踪它的状态\nDialogue: 0,0:15:26.07,0:15:28.72,Default,,0,0,0,,是为了知道求值器的下一步分析\nDialogue: 0,0:15:28.72,0:15:30.03,Default,,0,0,0,,而它们是完全无关的\nDialogue: 0,0:15:30.06,0:15:31.23,Default,,0,0,0,,因此我们可以去掉它们\nDialogue: 0,0:15:43.90,0:15:45.98,Default,,0,0,0,,那么 如果我们简单地\nDialogue: 0,0:15:46.16,0:15:47.75,Default,,0,0,0,,进行这类优化\nDialogue: 0,0:15:47.75,0:15:51.64,Default,,0,0,0,,不再考虑EXP和UNEV\nDialogue: 0,0:15:51.75,0:15:56.22,Default,,0,0,0,,去掉这些无关的寄存器赋值\nDialogue: 0,0:15:57.25,0:15:59.96,Default,,0,0,0,,我们就可以找到这些代码\nDialogue: 0,0:16:01.48,0:16:06.20,Default,,0,0,0,,也就是求值器会执行的这19条指令\nDialogue: 0,0:16:06.91,0:16:08.12,Default,,0,0,0,,给替换掉\nDialogue: 0,0:16:08.36,0:16:10.33,Default,,0,0,0,,请看幻灯片\nDialogue: 0,0:16:12.27,0:16:15.34,Default,,0,0,0,,我们去掉了大概一半\nDialogue: 0,0:16:18.28,0:16:20.75,Default,,0,0,0,,同样 这就是某种过滤\nDialogue: 0,0:16:21.07,0:16:24.46,Default,,0,0,0,,把无关的东西去掉\nDialogue: 0,0:16:25.17,0:16:26.22,Default,,0,0,0,,你们看 比如说\nDialogue: 0,0:16:27.47,0:16:29.66,Default,,0,0,0,,这里 求值器说\nDialogue: 0,0:16:29.68,0:16:32.43,Default,,0,0,0,,(ASSIGN VAL (LOOKUP 'F (FETCH ENV)))\nDialogue: 0,0:16:32.46,0:16:34.22,Default,,0,0,0,,这里 我们放入了一个常量F\nDialogue: 0,0:16:35.44,0:16:37.02,Default,,0,0,0,,这里又放了一个常量X\nDialogue: 0,0:16:40.02,0:16:42.41,Default,,0,0,0,,因此 这个编译器又稍微好一点\nDialogue: 0,0:16:43.79,0:16:46.76,Default,,0,0,0,,但它还是比较蠢\nDialogue: 0,0:16:47.95,0:16:49.58,Default,,0,0,0,,它仍会做很多蠢事\nDialogue: 0,0:16:50.45,0:16:52.52,Default,,0,0,0,,我们再看幻灯片\nDialogue: 0,0:16:52.88,0:16:53.93,Default,,0,0,0,,看最开头的地方\nDialogue: 0,0:16:56.34,0:16:58.17,Default,,0,0,0,,我们调用(SAVE ENV)保存环境\nDialogue: 0,0:16:59.35,0:17:01.72,Default,,0,0,0,,然后给VAL寄存器赋某个值\nDialogue: 0,0:17:01.80,0:17:03.35,Default,,0,0,0,,然后恢复环境\nDialogue: 0,0:17:03.35,0:17:04.41,Default,,0,0,0,,它是从哪来的\nDialogue: 0,0:17:04.91,0:17:07.10,Default,,0,0,0,,它来自求值器的这个地方\nDialogue: 0,0:17:07.15,0:17:10.28,Default,,0,0,0,,哦 我在正在对一个应用求值\nDialogue: 0,0:17:11.10,0:17:14.68,Default,,0,0,0,,因此我要递归调用EVAL-DISPATCH\nDialogue: 0,0:17:15.87,0:17:17.98,Default,,0,0,0,,我最好把接下来要用到的东西\nDialogue: 0,0:17:17.98,0:17:19.08,Default,,0,0,0,,保存到环境中\nDialogue: 0,0:17:19.77,0:17:22.86,Default,,0,0,0,,这就是递归调用EVAL-DISPATCH的结果\nDialogue: 0,0:17:23.47,0:17:25.77,Default,,0,0,0,,刚才那个例子就是对符号F求值的结果\nDialogue: 0,0:17:26.50,0:17:28.27,Default,,0,0,0,,从EVAL-DISPATCH中返回\nDialogue: 0,0:17:28.28,0:17:29.66,Default,,0,0,0,,将环境恢复\nDialogue: 0,0:17:31.25,0:17:32.28,Default,,0,0,0,,但是实际上\nDialogue: 0,0:17:32.59,0:17:35.88,Default,,0,0,0,,这个求值过程中 所进行的操作\nDialogue: 0,0:17:35.92,0:17:37.71,Default,,0,0,0,,完全不会影响环境\nDialogue: 0,0:17:38.67,0:17:40.80,Default,,0,0,0,,所以这里没必要先保存环境\nDialogue: 0,0:17:40.84,0:17:42.22,Default,,0,0,0,,再恢复环境\nDialogue: 0,0:17:45.67,0:17:46.62,Default,,0,0,0,,与之类似\nDialogue: 0,0:17:49.79,0:17:51.39,Default,,0,0,0,,这里 我们保存了参数表\nDialogue: 0,0:17:53.07,0:17:55.80,Default,,0,0,0,,那是一个求值参数的循环\nDialogue: 0,0:17:55.82,0:17:56.86,Default,,0,0,0,,先保存参数表\nDialogue: 0,0:17:57.20,0:17:58.03,Default,,0,0,0,,然后在这里恢复\nDialogue: 0,0:17:58.08,0:18:00.51,Default,,0,0,0,,但事实上最后\nDialogue: 0,0:18:00.80,0:18:02.28,Default,,0,0,0,,并没有变更参数表\nDialogue: 0,0:18:02.84,0:18:04.17,Default,,0,0,0,,所以不需要保存它\nDialogue: 0,0:18:08.65,0:18:12.88,Default,,0,0,0,,换种方式来说\nDialogue: 0,0:18:13.77,0:18:14.80,Default,,0,0,0,,怎么说呢\nDialogue: 0,0:18:16.43,0:18:19.13,Default,,0,0,0,,求值器需要最大限度地保持悲观\nDialogue: 0,0:18:19.87,0:18:21.07,Default,,0,0,0,,因为 从它的视角来看\nDialogue: 0,0:18:21.08,0:18:23.06,Default,,0,0,0,,只知道接下来是要对某些东西进行求值\nDialogue: 0,0:18:23.24,0:18:24.97,Default,,0,0,0,,所以最好把稍后要用的都存下来\nDialogue: 0,0:18:26.12,0:18:27.79,Default,,0,0,0,,一旦你完成了分析\nDialogue: 0,0:18:27.82,0:18:29.68,Default,,0,0,0,,从编译器的角度就会考虑\nDialogue: 0,0:18:29.72,0:18:31.47,Default,,0,0,0,,哪些是我真正需要存下来的?\nDialogue: 0,0:18:32.12,0:18:33.31,Default,,0,0,0,,我们需要去 --\nDialogue: 0,0:18:33.42,0:18:37.30,Default,,0,0,0,,它不需要像求值器一样小心翼翼\nDialogue: 0,0:18:37.30,0:18:38.80,Default,,0,0,0,,因为它知道 实际需要什么\nDialogue: 0,0:18:39.69,0:18:41.16,Default,,0,0,0,,无论如何 如果我们完成了优化\nDialogue: 0,0:18:42.50,0:18:45.71,Default,,0,0,0,,消除掉所有多余的保存和恢复\nDialogue: 0,0:18:46.40,0:18:49.05,Default,,0,0,0,,那么我们可以得到这样的结果\nDialogue: 0,0:18:49.90,0:18:51.53,Default,,0,0,0,,我们可以发现\nDialogue: 0,0:18:51.64,0:18:53.71,Default,,0,0,0,,只有三条指令是必须的\nDialogue: 0,0:18:54.07,0:18:55.72,Default,,0,0,0,,从刚才的11条指令优化成这样\nDialogue: 0,0:18:55.97,0:18:58.81,Default,,0,0,0,,或是从原始的20条指令优化而来\nDialogue: 0,0:18:59.87,0:19:00.92,Default,,0,0,0,,这告诉我们\nDialogue: 0,0:19:01.12,0:19:03.18,Default,,0,0,0,,对于这些寄存器操作\nDialogue: 0,0:19:03.27,0:19:04.94,Default,,0,0,0,,哪些是必需的?\nDialogue: 0,0:19:09.42,0:19:11.74,Default,,0,0,0,,让我换个方式来总结一下\nDialogue: 0,0:19:11.74,0:19:13.48,Default,,0,0,0,,我先给你们看一张图\nDialogue: 0,0:19:16.00,0:19:17.52,Default,,0,0,0,,这张图片\nDialogue: 0,0:19:18.77,0:19:20.81,Default,,0,0,0,,展示了所有的保存和恢复\nDialogue: 0,0:19:23.50,0:19:25.23,Default,,0,0,0,,这里是表达式(F X)\nDialogue: 0,0:19:25.32,0:19:27.87,Default,,0,0,0,,在下面这里\nDialogue: 0,0:19:28.75,0:19:31.80,Default,,0,0,0,,是对求值器中各种地方的跟踪\nDialogue: 0,0:19:34.97,0:19:38.04,Default,,0,0,0,,在求值发生时会使用这些地方\nDialogue: 0,0:19:38.04,0:19:40.01,Default,,0,0,0,,在这里 你可以看到箭头\nDialogue: 0,0:19:40.22,0:19:42.08,Default,,0,0,0,,下箭头代表寄存器的保存\nDialogue: 0,0:19:42.40,0:19:44.84,Default,,0,0,0,,所以最先保存的是ENV寄存器\nDialogue: 0,0:19:46.82,0:19:48.68,Default,,0,0,0,,然后 在这里恢复ENV\nDialogue: 0,0:19:52.38,0:19:54.54,Default,,0,0,0,,这些都是成对的栈操作\nDialogue: 0,0:19:56.12,0:19:57.56,Default,,0,0,0,,如果你更进一步\nDialogue: 0,0:19:58.12,0:20:00.78,Default,,0,0,0,,我们记得\nDialogue: 0,0:20:00.89,0:20:03.02,Default,,0,0,0,,UNEV是个完全没用的寄存器\nDialogue: 0,0:20:07.80,0:20:09.78,Default,,0,0,0,,如果我们用固定结构的代码\nDialogue: 0,0:20:09.78,0:20:12.52,Default,,0,0,0,,就不需要保存UNEV 因为完全用不上\nDialogue: 0,0:20:16.20,0:20:19.15,Default,,0,0,0,,然后 根据我们约定的\nDialogue: 0,0:20:19.16,0:20:21.88,Default,,0,0,0,,应用过程的准则\nDialogue: 0,0:20:21.88,0:20:23.85,Default,,0,0,0,,我们会选择是否保存CONTINUE\nDialogue: 0,0:20:27.40,0:20:28.74,Default,,0,0,0,,这就是我们做的第一件事\nDialogue: 0,0:20:28.74,0:20:30.51,Default,,0,0,0,,然后我们可以看看\nDialogue: 0,0:20:31.71,0:20:32.70,Default,,0,0,0,,实际需要些什么\nDialogue: 0,0:20:33.07,0:20:35.56,Default,,0,0,0,,其实在求值F的过程中\nDialogue: 0,0:20:36.04,0:20:37.82,Default,,0,0,0,,我们不需要保存ENV\nDialogue: 0,0:20:38.08,0:20:39.92,Default,,0,0,0,,因为它不会被破坏\nDialogue: 0,0:20:39.92,0:20:41.31,Default,,0,0,0,,因此 如果我们利用这点\nDialogue: 0,0:20:44.12,0:20:47.56,Default,,0,0,0,,这里对F的求值\nDialogue: 0,0:20:48.57,0:20:50.44,Default,,0,0,0,,完全不需要担心\nDialogue: 0,0:20:51.61,0:20:52.60,Default,,0,0,0,,会破坏ENV\nDialogue: 0,0:20:52.60,0:20:54.94,Default,,0,0,0,,类似地 这里对X的求值\nDialogue: 0,0:20:57.17,0:20:58.89,Default,,0,0,0,,当求值器进行求值时 它会说\nDialogue: 0,0:20:58.91,0:21:01.64,Default,,0,0,0,,我最好保存好与之有关的FUN寄存器\nDialogue: 0,0:21:02.07,0:21:03.22,Default,,0,0,0,,因为后面也许会用得着\nDialogue: 0,0:21:03.28,0:21:04.89,Default,,0,0,0,,我最好也保存参数表\nDialogue: 0,0:21:06.90,0:21:09.05,Default,,0,0,0,,然而 在这如果是编译器的话\nDialogue: 0,0:21:09.05,0:21:10.38,Default,,0,0,0,,实际需要哪些寄存器\nDialogue: 0,0:21:10.52,0:21:11.84,Default,,0,0,0,,从而进行相关的保存与恢复\nDialogue: 0,0:21:12.70,0:21:16.09,Default,,0,0,0,,事实上 这里求值器做的所有栈操作\nDialogue: 0,0:21:16.32,0:21:19.58,Default,,0,0,0,,都证明是过于悲观而不必要\nDialogue: 0,0:21:19.62,0:21:21.45,Default,,0,0,0,,而编译器在这里是知道这一点的\nDialogue: 0,0:21:27.35,0:21:28.48,Default,,0,0,0,,这是最基础的想法\nDialogue: 0,0:21:29.80,0:21:31.00,Default,,0,0,0,,我们把求值器\nDialogue: 0,0:21:31.00,0:21:33.24,Default,,0,0,0,,剔除那些不需要的东西\nDialogue: 0,0:21:33.24,0:21:35.24,Default,,0,0,0,,去除那些对于编译器完全无用的东西\nDialogue: 0,0:21:35.24,0:21:36.19,Default,,0,0,0,,只保留求值的部分\nDialogue: 0,0:21:37.40,0:21:40.40,Default,,0,0,0,,然后你可以看到哪些栈操作是不必要的\nDialogue: 0,0:21:40.82,0:21:43.76,Default,,0,0,0,,这就是书中所描述的编译器\nDialogue: 0,0:21:43.85,0:21:45.04,Default,,0,0,0,,的基本结构\nDialogue: 0,0:21:45.04,0:21:47.00,Default,,0,0,0,,我给你们展示一下这\nDialogue: 0,0:21:47.76,0:21:49.68,Default,,0,0,0,,这个简单的例子\nDialogue: 0,0:21:51.20,0:21:53.26,Default,,0,0,0,,为了说清楚 多余的东西是怎样保存的\nDialogue: 0,0:21:53.29,0:21:56.06,Default,,0,0,0,,我们来看一个稍复杂的表达式\nDialogue: 0,0:21:58.15,0:22:01.93,Default,,0,0,0,,(F (G X) 1)\nDialogue: 0,0:22:03.87,0:22:05.52,Default,,0,0,0,,我们不会讲解所有的代码\nDialogue: 0,0:22:06.40,0:22:08.56,Default,,0,0,0,,因为代码有点多\nDialogue: 0,0:22:09.72,0:22:12.35,Default,,0,0,0,,我认为在求值器在处理它时\nDialogue: 0,0:22:12.35,0:22:14.67,Default,,0,0,0,,大概会产生\nDialogue: 0,0:22:14.70,0:22:16.25,Default,,0,0,0,,16对保存-恢复操作\nDialogue: 0,0:22:17.00,0:22:18.57,Default,,0,0,0,,这有一张图表\nDialogue: 0,0:22:20.57,0:22:21.95,Default,,0,0,0,,演示了其中的过程\nDialogue: 0,0:22:22.97,0:22:23.90,Default,,0,0,0,,你从这里开始--\nDialogue: 0,0:22:24.25,0:22:26.62,Default,,0,0,0,,求值器说：“我要求值一个应用”\nDialogue: 0,0:22:26.90,0:22:29.13,Default,,0,0,0,,在这里保存ENV 又在这里恢复\nDialogue: 0,0:22:30.65,0:22:34.44,Default,,0,0,0,,然后处理第一个运算对象\nDialogue: 0,0:22:36.81,0:22:39.28,Default,,0,0,0,,这是求值器的递归调用\nDialogue: 0,0:22:39.28,0:22:40.89,Default,,0,0,0,,求值器发现 这是一个应用\nDialogue: 0,0:22:40.91,0:22:42.10,Default,,0,0,0,,又会保存环境\nDialogue: 0,0:22:42.10,0:22:44.97,Default,,0,0,0,,求值组合式的运算符 然后在这里恢复环境\nDialogue: 0,0:22:45.80,0:22:48.92,Default,,0,0,0,,这个恢复匹配的是这个保存操作\nDialogue: 0,0:22:49.77,0:22:50.78,Default,,0,0,0,,以此类推\nDialogue: 0,0:22:51.65,0:22:52.51,Default,,0,0,0,,这里的UNEV\nDialogue: 0,0:22:52.52,0:22:54.62,Default,,0,0,0,,完全没有必要存在\nDialogue: 0,0:22:54.97,0:22:56.60,Default,,0,0,0,,CONTINUE寄存器不断地被保存-恢复\nDialogue: 0,0:22:57.42,0:23:00.41,Default,,0,0,0,,而FUN寄存器则是在\nDialogue: 0,0:23:00.78,0:23:04.36,Default,,0,0,0,,处理运算对象期间被保存\nDialogue: 0,0:23:05.10,0:23:06.52,Default,,0,0,0,,这类的事情一直在发生\nDialogue: 0,0:23:06.78,0:23:09.39,Default,,0,0,0,,但如果你问 跟求值器相比\nDialogue: 0,0:23:09.87,0:23:11.66,Default,,0,0,0,,编译器究竟要做什么？\nDialogue: 0,0:23:12.27,0:23:13.55,Default,,0,0,0,,你会去掉一大堆东西\nDialogue: 0,0:23:14.30,0:23:16.64,Default,,0,0,0,,在这个的基础上 如果你说\nDialogue: 0,0:23:19.40,0:23:22.54,Default,,0,0,0,,对F的求值不会修改ENV寄存器\nDialogue: 0,0:23:23.82,0:23:26.51,Default,,0,0,0,,或者对符号X的查找\nDialogue: 0,0:23:29.28,0:23:32.09,Default,,0,0,0,,不需要特别保护FUN寄存器\nDialogue: 0,0:23:34.30,0:23:37.60,Default,,0,0,0,,就得到了只有几对的保存-恢复操作\nDialogue: 0,0:23:40.25,0:23:42.27,Default,,0,0,0,,然而 你还可以再优化一下\nDialogue: 0,0:23:42.27,0:23:44.33,Default,,0,0,0,,看看这里的ENV寄存器发生了什么\nDialogue: 0,0:23:45.21,0:23:47.39,Default,,0,0,0,,我们观察ENV寄存器的操作 发现\nDialogue: 0,0:23:51.00,0:23:52.25,Default,,0,0,0,,这是一个组合式\nDialogue: 0,0:23:54.33,0:23:55.69,Default,,0,0,0,,而这个求值器\nDialogue: 0,0:23:55.78,0:23:57.27,Default,,0,0,0,,对G一无所知\nDialogue: 0,0:23:58.57,0:24:00.73,Default,,0,0,0,,所以在这 它说\nDialogue: 0,0:24:01.29,0:24:03.45,Default,,0,0,0,,我最好保存ENV寄存器\nDialogue: 0,0:24:03.96,0:24:05.42,Default,,0,0,0,,因为对G的求值\nDialogue: 0,0:24:05.42,0:24:07.42,Default,,0,0,0,,可能会修改ENV寄存器的值\nDialogue: 0,0:24:07.55,0:24:09.45,Default,,0,0,0,,而我稍后可能会需要它\nDialogue: 0,0:24:10.17,0:24:11.40,Default,,0,0,0,,在这个参数之后\nDialogue: 0,0:24:12.22,0:24:13.37,Default,,0,0,0,,在处理第二个参数的时候\nDialogue: 0,0:24:15.60,0:24:17.24,Default,,0,0,0,,这就是为什么它没被优化掉\nDialogue: 0,0:24:19.07,0:24:22.54,Default,,0,0,0,,因为编译器没有对G将要做的事情做任何假设\nDialogue: 0,0:24:22.54,0:24:23.60,Default,,0,0,0,,另一方面\nDialogue: 0,0:24:24.61,0:24:26.52,Default,,0,0,0,,如果你看看这里的第二个参数\nDialogue: 0,0:24:26.64,0:24:27.70,Default,,0,0,0,,它只是查找“1”这个常量\nDialogue: 0,0:24:27.70,0:24:29.60,Default,,0,0,0,,这不需要ENV寄存器\nDialogue: 0,0:24:30.77,0:24:32.04,Default,,0,0,0,,因此没必要保存它\nDialogue: 0,0:24:32.06,0:24:33.77,Default,,0,0,0,,事实上 你也可以把这个也去掉\nDialogue: 0,0:24:34.85,0:24:37.81,Default,,0,0,0,,这一堆寄存器操作\nDialogue: 0,0:24:37.98,0:24:40.08,Default,,0,0,0,,如果你像这样简单地推理的话\nDialogue: 0,0:24:40.55,0:24:43.05,Default,,0,0,0,,只会剩下两对保存-恢复操作\nDialogue: 0,0:24:45.10,0:24:46.97,Default,,0,0,0,,而这些 如果你知道关于G的某些信息的话\nDialogue: 0,0:24:47.52,0:24:49.08,Default,,0,0,0,,可以进一步优化\nDialogue: 0,0:24:56.27,0:24:57.85,Default,,0,0,0,,基本的理念是\nDialogue: 0,0:24:57.95,0:24:59.98,Default,,0,0,0,,编译器之所以更好\nDialogue: 0,0:24:59.98,0:25:02.56,Default,,0,0,0,,是因为解释器对于将要处理的东西一无所知\nDialogue: 0,0:25:03.25,0:25:05.04,Default,,0,0,0,,它不得不以最悲观的方式保存东西\nDialogue: 0,0:25:05.05,0:25:06.70,Default,,0,0,0,,来保护它自己\nDialogue: 0,0:25:07.90,0:25:08.76,Default,,0,0,0,,而编译器\nDialogue: 0,0:25:09.48,0:25:12.38,Default,,0,0,0,,只需要保存实际需要的东西\nDialogue: 0,0:25:13.37,0:25:15.20,Default,,0,0,0,,某个东西是否需要保存\nDialogue: 0,0:25:15.24,0:25:17.37,Default,,0,0,0,,有两种原因\nDialogue: 0,0:25:17.82,0:25:18.70,Default,,0,0,0,,一种是\nDialogue: 0,0:25:18.70,0:25:19.82,Default,,0,0,0,,你保护的东西\nDialogue: 0,0:25:19.95,0:25:21.44,Default,,0,0,0,,不会修改寄存器\nDialogue: 0,0:25:22.08,0:25:23.58,Default,,0,0,0,,例如 变量查找\nDialogue: 0,0:25:24.12,0:25:25.20,Default,,0,0,0,,另一种原因是\nDialogue: 0,0:25:25.32,0:25:27.10,Default,,0,0,0,,你所保存的东西\nDialogue: 0,0:25:28.28,0:25:29.92,Default,,0,0,0,,最后并不会被用到\nDialogue: 0,0:25:30.81,0:25:34.27,Default,,0,0,0,,因此 编译器正是利用了\nDialogue: 0,0:25:34.30,0:25:35.88,Default,,0,0,0,,这两条基本原则\nDialogue: 0,0:25:36.27,0:25:37.76,Default,,0,0,0,,来让代码变得更高效的\nDialogue: 0,0:25:44.27,0:25:45.32,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:25:51.20,0:25:53.10,Default,,0,0,0,,学生: 你一直在说UNEV寄存器\nDialogue: 0,0:25:53.13,0:25:56.40,Default,,0,0,0,,UNEV寄存器完全不会被用到\nDialogue: 0,0:25:56.41,0:25:58.68,Default,,0,0,0,,是否意味着 机器只需要6个寄存器足矣？\nDialogue: 0,0:25:58.70,0:26:00.08,Default,,0,0,0,,或者是说 在这个特定的例子里\nDialogue: 0,0:26:00.11,0:26:01.18,Default,,0,0,0,,它没有被用到？\nDialogue: 0,0:26:01.72,0:26:02.81,Default,,0,0,0,,教授: 对于编译器\nDialogue: 0,0:26:04.31,0:26:07.42,Default,,0,0,0,,你可以生成6个或5个寄存器的代码\nDialogue: 0,0:26:07.56,0:26:09.02,Default,,0,0,0,,因为EXP寄存器也没有用到\nDialogue: 0,0:26:09.40,0:26:14.57,Default,,0,0,0,,是的 你可以把EXP和UNEV都去掉\nDialogue: 0,0:26:14.57,0:26:16.87,Default,,0,0,0,,因为这些是求值器的数据结构\nDialogue: 0,0:26:17.36,0:26:19.36,Default,,0,0,0,,以编译器的视角来看\nDialogue: 0,0:26:19.39,0:26:20.87,Default,,0,0,0,,这些东西都是常量\nDialogue: 0,0:26:21.65,0:26:22.44,Default,,0,0,0,,关键在于\nDialogue: 0,0:26:22.48,0:26:24.59,Default,,0,0,0,,这个特定编译器是被构造出来的\nDialogue: 0,0:26:24.79,0:26:27.92,Default,,0,0,0,,因此被解释的代码和被编译的代码可以共存\nDialogue: 0,0:26:29.32,0:26:30.72,Default,,0,0,0,,可以这样看待它\nDialogue: 0,0:26:30.97,0:26:32.29,Default,,0,0,0,,你构建了一个芯片\nDialogue: 0,0:26:34.30,0:26:35.50,Default,,0,0,0,,它就是求值器\nDialogue: 0,0:26:35.88,0:26:37.28,Default,,0,0,0,,而编译器可以做的就是\nDialogue: 0,0:26:37.31,0:26:39.02,Default,,0,0,0,,为这个芯片生成代码\nDialogue: 0,0:26:40.40,0:26:41.90,Default,,0,0,0,,只是它不会用到两个寄存器而已\nDialogue: 0,0:26:51.52,0:26:52.47,Default,,0,0,0,,好 休息一会\nDialogue: 0,0:26:53.55,0:27:07.18,Default,,0,0,0,,[音乐]\nDialogue: 0,0:27:07.37,0:27:11.42,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:27:14.57,0:27:18.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:27:18.17,0:27:22.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:27:22.22,0:27:26.48,Declare,,0,0,0,,{\\an2\\fad(500,500)}编译\nDialogue: 0,0:27:29.21,0:27:32.43,Default,,0,0,0,,我们刚才研究了编译器应该要做什么\nDialogue: 0,0:27:32.78,0:27:36.04,Default,,0,0,0,,现在我们来简略地看看\nDialogue: 0,0:27:36.15,0:27:37.47,Default,,0,0,0,,这些目标如何达成\nDialogue: 0,0:27:38.26,0:27:39.58,Default,,0,0,0,,而我不会给出细节\nDialogue: 0,0:27:39.60,0:27:42.17,Default,,0,0,0,,在书中有一大堆代码\nDialogue: 0,0:27:42.22,0:27:43.42,Default,,0,0,0,,展示了所有细节\nDialogue: 0,0:27:43.45,0:27:45.31,Default,,0,0,0,,我要做的 是给你们展示\nDialogue: 0,0:27:45.96,0:27:47.26,Default,,0,0,0,,其中的关键思想\nDialogue: 0,0:27:49.49,0:27:51.36,Default,,0,0,0,,换个时间再来关心细节\nDialogue: 0,0:27:51.51,0:27:55.30,Default,,0,0,0,,设想我们正在编译一条表达式\nDialogue: 0,0:27:55.30,0:27:57.01,Default,,0,0,0,,这里有一些运算符\nDialogue: 0,0:27:57.48,0:27:58.56,Default,,0,0,0,,和两个参数\nDialogue: 0,0:28:03.56,0:28:04.24,Default,,0,0,0,,现在\nDialogue: 0,0:28:06.27,0:28:08.14,Default,,0,0,0,,这个编译器会生成什么代码?\nDialogue: 0,0:28:08.85,0:28:09.78,Default,,0,0,0,,首先\nDialogue: 0,0:28:09.83,0:28:11.20,Default,,0,0,0,,它会递归运行\nDialogue: 0,0:28:11.90,0:28:13.28,Default,,0,0,0,,编译运算符\nDialogue: 0,0:28:14.37,0:28:19.02,Default,,0,0,0,,它说 我要编译运算符\nDialogue: 0,0:28:21.16,0:28:24.54,Default,,0,0,0,,最后我需要让它们的结果\nDialogue: 0,0:28:24.84,0:28:27.95,Default,,0,0,0,,存放在FUN寄存器中\nDialogue: 0,0:28:28.42,0:28:29.60,Default,,0,0,0,,所以我编译一些指令\nDialogue: 0,0:28:29.64,0:28:31.56,Default,,0,0,0,,它们会编译运算符\nDialogue: 0,0:28:31.69,0:28:38.62,Default,,0,0,0,,最后把结果放在FUN寄存器中\nDialogue: 0,0:28:45.51,0:28:46.94,Default,,0,0,0,,接下来我要做的是\nDialogue: 0,0:28:47.71,0:28:49.68,Default,,0,0,0,,另一个代码片段则说\nDialogue: 0,0:28:49.68,0:28:55.17,Default,,0,0,0,,我要编译第一个参数\nDialogue: 0,0:28:55.17,0:28:56.80,Default,,0,0,0,,因此它递归调地用自己\nDialogue: 0,0:28:58.04,0:29:03.36,Default,,0,0,0,,而结果会被放在VAL中\nDialogue: 0,0:29:09.07,0:29:10.75,Default,,0,0,0,,接下来需要做的是\nDialogue: 0,0:29:10.75,0:29:12.26,Default,,0,0,0,,建立起参数表\nDialogue: 0,0:29:12.95,0:29:25.50,Default,,0,0,0,,(ASSIGN ARGL (CONS (FETCH --\nDialogue: 0,0:29:25.55,0:29:27.10,Default,,0,0,0,,它会生成这些代码\nDialogue: 0,0:29:27.50,0:29:32.51,Default,,0,0,0,,(FETCH VAL) '()))\nDialogue: 0,0:29:35.00,0:29:36.05,Default,,0,0,0,,然而\nDialogue: 0,0:29:37.99,0:29:40.61,Default,,0,0,0,,当它到这里时\nDialogue: 0,0:29:41.32,0:29:42.82,Default,,0,0,0,,它可能需要环境\nDialogue: 0,0:29:43.95,0:29:45.29,Default,,0,0,0,,它需要环境\nDialogue: 0,0:29:45.32,0:29:48.21,Default,,0,0,0,,这是求值第一个参数所需要的\nDialogue: 0,0:29:49.04,0:29:51.18,Default,,0,0,0,,因此 它需要保证\nDialogue: 0,0:29:51.92,0:29:53.76,Default,,0,0,0,,对运算对象的编译\nDialogue: 0,0:29:55.32,0:29:57.85,Default,,0,0,0,,或者说它需要保护FUN寄存器\nDialogue: 0,0:29:58.01,0:30:00.98,Default,,0,0,0,,来应对编译运算对象时发生的各种情况\nDialogue: 0,0:30:01.30,0:30:03.08,Default,,0,0,0,,因此它在这做了个标注说\nDialogue: 0,0:30:03.37,0:30:12.89,Default,,0,0,0,,这个片段需要保护ENV寄存器\nDialogue: 0,0:30:17.39,0:30:18.44,Default,,0,0,0,,与之类似 这里\nDialogue: 0,0:30:21.02,0:30:23.30,Default,,0,0,0,,在完成第一个运算对象的编译后\nDialogue: 0,0:30:23.57,0:30:24.67,Default,,0,0,0,,它会说 我最好--\nDialogue: 0,0:30:24.71,0:30:27.92,Default,,0,0,0,,我需要知道第二个运算对象的环境\nDialogue: 0,0:30:27.92,0:30:29.46,Default,,0,0,0,,所以它在这做了个标注\nDialogue: 0,0:30:29.71,0:30:35.96,Default,,0,0,0,,这里也需要保护ENV\nDialogue: 0,0:30:39.42,0:30:41.02,Default,,0,0,0,,现在它继续运行\nDialogue: 0,0:30:41.12,0:30:42.83,Default,,0,0,0,,下一段代码\nDialogue: 0,0:30:43.31,0:30:49.74,Default,,0,0,0,,是要编译第二个参数\nDialogue: 0,0:30:50.82,0:30:52.64,Default,,0,0,0,,它将会\nDialogue: 0,0:30:52.99,0:30:59.28,Default,,0,0,0,,把编译的结果按约定放入到VAL中\nDialogue: 0,0:31:03.86,0:31:06.70,Default,,0,0,0,,随后它会生成一条指令\nDialogue: 0,0:31:07.84,0:31:09.25,Default,,0,0,0,,从而建立起参数表\nDialogue: 0,0:31:09.55,0:31:15.28,Default,,0,0,0,,(ASSIGN ARGL\nDialogue: 0,0:31:20.22,0:31:28.94,Default,,0,0,0,,(CONS (FETCH VAL) (FETCH ARGL))\nDialogue: 0,0:31:33.97,0:31:34.64,Default,,0,0,0,,然而\nDialogue: 0,0:31:34.81,0:31:36.58,Default,,0,0,0,,为了取得旧的参数表\nDialogue: 0,0:31:37.15,0:31:40.99,Default,,0,0,0,,它最好保证这期间发生的任何事情\nDialogue: 0,0:31:41.30,0:31:42.69,Default,,0,0,0,,都不影响旧的参数表\nDialogue: 0,0:31:43.50,0:31:45.17,Default,,0,0,0,,因此它在这做了个标注说\nDialogue: 0,0:31:45.34,0:31:51.64,Default,,0,0,0,,哦 这里需要保护ARGL\nDialogue: 0,0:31:54.16,0:31:56.03,Default,,0,0,0,,现在参数表就建立好了\nDialogue: 0,0:31:58.01,0:32:02.86,Default,,0,0,0,,现在可以准备去APPLY-DISPATCH了\nDialogue: 0,0:32:07.02,0:32:10.80,Default,,0,0,0,,它生成了这条指令\nDialogue: 0,0:32:15.19,0:32:17.37,Default,,0,0,0,,因为现在参数都在ARGL中\nDialogue: 0,0:32:18.15,0:32:20.59,Default,,0,0,0,,运算符在FUN中\nDialogue: 0,0:32:20.59,0:32:22.89,Default,,0,0,0,,如果只是单纯地把运算符放到FUN寄存器中\nDialogue: 0,0:32:23.27,0:32:26.64,Default,,0,0,0,,就需要它保证这块代码\nDialogue: 0,0:32:27.09,0:32:29.27,Default,,0,0,0,,不会破坏FUN寄存器里的东西\nDialogue: 0,0:32:29.67,0:32:31.24,Default,,0,0,0,,所以它在这做了个标注说\nDialogue: 0,0:32:31.55,0:32:32.73,Default,,0,0,0,,这里的所有东西\nDialogue: 0,0:32:34.88,0:32:40.73,Default,,0,0,0,,最好能够在保护FUN寄存器的情况下完成\nDialogue: 0,0:32:43.71,0:32:46.15,Default,,0,0,0,,所以这就是--\nDialogue: 0,0:32:46.15,0:32:47.10,Default,,0,0,0,,基本上来说\nDialogue: 0,0:32:48.20,0:32:50.24,Default,,0,0,0,,编译器所做的就是\nDialogue: 0,0:32:50.54,0:32:52.46,Default,,0,0,0,,追加一大堆的代码\nDialogue: 0,0:32:53.50,0:32:58.83,Default,,0,0,0,,而这些代码之中都是一些基本运算\nDialogue: 0,0:32:58.86,0:33:00.12,Default,,0,0,0,,比如符号查找\nDialogue: 0,0:33:01.44,0:33:02.60,Default,,0,0,0,,条件分支的处理\nDialogue: 0,0:33:02.64,0:33:05.44,Default,,0,0,0,,都是一些琐碎的事情\nDialogue: 0,0:33:05.44,0:33:07.99,Default,,0,0,0,,然后按照这种准则将它们追加到一起\nDialogue: 0,0:33:08.78,0:33:10.79,Default,,0,0,0,,因此 组合的基本手段就是\nDialogue: 0,0:33:10.86,0:33:13.18,Default,,0,0,0,,将一段代码追加到另一段的后面\nDialogue: 0,0:33:21.55,0:33:22.86,Default,,0,0,0,,就是这里发生的事情\nDialogue: 0,0:33:25.58,0:33:27.24,Default,,0,0,0,,这有点取巧\nDialogue: 0,0:33:27.56,0:33:30.37,Default,,0,0,0,,向一段代码后面追加代码的思路是\nDialogue: 0,0:33:31.60,0:33:33.76,Default,,0,0,0,,小心保护寄存器\nDialogue: 0,0:33:35.63,0:33:37.93,Default,,0,0,0,,追加操作看起来像这样\nDialogue: 0,0:33:39.15,0:33:40.65,Default,,0,0,0,,它要做的是\nDialogue: 0,0:33:41.20,0:33:44.11,Default,,0,0,0,,代码的追加是这么来做的\nDialogue: 0,0:33:44.53,0:33:53.63,Default,,0,0,0,,如果SEQ1需要寄存器--\nDialogue: 0,0:33:53.66,0:33:54.72,Default,,0,0,0,,我应该改一下这个\nDialogue: 0,0:33:54.72,0:33:56.87,Default,,0,0,0,,在SEQ1后面追加SEQ2\nDialogue: 0,0:33:57.42,0:34:03.96,Default,,0,0,0,,并保护一些寄存器\nDialogue: 0,0:34:08.52,0:34:09.91,Default,,0,0,0,,这里改成AND\nDialogue: 0,0:34:11.36,0:34:13.03,Default,,0,0,0,,这样的话前后顺序就清楚了\nDialogue: 0,0:34:13.88,0:34:19.87,Default,,0,0,0,,如果SEQ2需要寄存器\nDialogue: 0,0:34:21.12,0:34:27.85,Default,,0,0,0,,而SEQ1又修改了寄存器\nDialogue: 0,0:34:33.68,0:34:36.30,Default,,0,0,0,,那么编译器生成的指令是\nDialogue: 0,0:34:36.97,0:34:41.34,Default,,0,0,0,,保存寄存器\nDialogue: 0,0:34:43.02,0:34:44.19,Default,,0,0,0,,这就是代码\nDialogue: 0,0:34:44.35,0:34:45.35,Default,,0,0,0,,生成这段代码\nDialogue: 0,0:34:45.35,0:34:46.28,Default,,0,0,0,,保存寄存器\nDialogue: 0,0:34:46.72,0:34:52.97,Default,,0,0,0,,然后写下递归编译SEQ1的结果\nDialogue: 0,0:34:53.30,0:34:54.84,Default,,0,0,0,,然后恢复寄存器\nDialogue: 0,0:35:00.52,0:35:03.92,Default,,0,0,0,,再写下递归编译\nDialogue: 0,0:35:04.46,0:35:05.47,Default,,0,0,0,,SEQ2的结果\nDialogue: 0,0:35:07.07,0:35:09.62,Default,,0,0,0,,这就是你需要做的\nDialogue: 0,0:35:09.62,0:35:11.82,Default,,0,0,0,,实际上SEQ2需要寄存器\nDialogue: 0,0:35:11.82,0:35:13.74,Default,,0,0,0,,而SEQ1改动了它\nDialogue: 0,0:35:15.12,0:35:17.07,Default,,0,0,0,,否则的话\nDialogue: 0,0:35:20.50,0:35:26.57,Default,,0,0,0,,得到的就是SEQ1后面跟着SEQ2\nDialogue: 0,0:35:28.17,0:35:30.30,Default,,0,0,0,,这就是把两个代码片段\nDialogue: 0,0:35:30.59,0:35:33.52,Default,,0,0,0,,连接到一起的基本操作\nDialogue: 0,0:35:33.93,0:35:35.93,Default,,0,0,0,,把这些指令组合成序列\nDialogue: 0,0:35:36.89,0:35:38.87,Default,,0,0,0,,我们可以发现 从这个角度看\nDialogue: 0,0:35:40.94,0:35:45.96,Default,,0,0,0,,解释器和编译器的区别\nDialogue: 0,0:35:46.82,0:35:49.34,Default,,0,0,0,,是编译器有保护寄存器的标注\nDialogue: 0,0:35:50.14,0:35:52.22,Default,,0,0,0,,上面记录着\nDialogue: 0,0:35:52.49,0:35:54.22,Default,,0,0,0,,是否需要生成保存-恢复代码\nDialogue: 0,0:35:55.19,0:35:57.24,Default,,0,0,0,,而解释器会以最悲观的方式处理\nDialogue: 0,0:35:57.28,0:35:58.90,Default,,0,0,0,,总是会进行保存-恢复\nDialogue: 0,0:36:00.76,0:36:01.93,Default,,0,0,0,,这就是关键的区别\nDialogue: 0,0:36:04.16,0:36:06.05,Default,,0,0,0,,为了实现这个\nDialogue: 0,0:36:06.65,0:36:09.40,Default,,0,0,0,,编译器需要一些理论\nDialogue: 0,0:36:09.56,0:36:11.96,Default,,0,0,0,,来确定代码序列会需要、又会修改哪些寄存器\nDialogue: 0,0:36:14.26,0:36:17.28,Default,,0,0,0,,所以你放入的小片段\nDialogue: 0,0:36:17.48,0:36:21.00,Default,,0,0,0,,例如这段基础代码\nDialogue: 0,0:36:22.74,0:36:24.59,Default,,0,0,0,,当你查找一个变量时\nDialogue: 0,0:36:24.92,0:36:26.04,Default,,0,0,0,,进行了哪些操作？\nDialogue: 0,0:36:26.89,0:36:29.02,Default,,0,0,0,,你又是做了些什么\nDialogue: 0,0:36:29.05,0:36:30.68,Default,,0,0,0,,来编译一个常量\nDialogue: 0,0:36:30.97,0:36:32.10,Default,,0,0,0,,或者应用一个函数\nDialogue: 0,0:36:32.97,0:36:34.48,Default,,0,0,0,,它们都会带有一些标注\nDialogue: 0,0:36:34.67,0:36:36.46,Default,,0,0,0,,说明了它们需要的和修改的寄存器\nDialogue: 0,0:36:38.78,0:36:41.50,Default,,0,0,0,,所以底层的数据结构\nDialogue: 0,0:36:42.66,0:36:44.33,Default,,0,0,0,,我会这样讲\nDialogue: 0,0:36:44.39,0:36:47.91,Default,,0,0,0,,传递给编译器的代码序列大概是这样\nDialogue: 0,0:36:48.07,0:36:51.42,Default,,0,0,0,,它里面有实际的指令序列\nDialogue: 0,0:36:55.67,0:36:56.81,Default,,0,0,0,,跟它一起的还有\nDialogue: 0,0:36:57.18,0:37:02.60,Default,,0,0,0,,一组被修改的寄存器\nDialogue: 0,0:37:10.54,0:37:12.60,Default,,0,0,0,,还有一组需要的寄存器\nDialogue: 0,0:37:20.00,0:37:22.46,Default,,0,0,0,,为了能够执行此操作\nDialogue: 0,0:37:23.00,0:37:26.41,Default,,0,0,0,,编译器必须要掌握这些信息\nDialogue: 0,0:37:29.30,0:37:31.08,Default,,0,0,0,,它们从哪来呢\nDialogue: 0,0:37:32.91,0:37:34.49,Default,,0,0,0,,它们来自于--你们可能也想到了\nDialogue: 0,0:37:34.51,0:37:35.53,Default,,0,0,0,,对于那些最基本的片段\nDialogue: 0,0:37:35.55,0:37:36.84,Default,,0,0,0,,我们会手工添加\nDialogue: 0,0:37:37.24,0:37:38.86,Default,,0,0,0,,然后 当我们组合两个序列时\nDialogue: 0,0:37:38.89,0:37:41.02,Default,,0,0,0,,我们会计算出这两个集合\nDialogue: 0,0:37:42.16,0:37:44.12,Default,,0,0,0,,举一个非常基本的例子\nDialogue: 0,0:37:48.43,0:37:51.40,Default,,0,0,0,,例如做一个寄存器赋值\nDialogue: 0,0:37:51.77,0:37:53.50,Default,,0,0,0,,因此 基本代码片段会说\nDialogue: 0,0:37:53.52,0:37:56.22,Default,,0,0,0,,噢 它是个代码片段\nDialogue: 0,0:37:56.22,0:38:03.17,Default,,0,0,0,,代码的指令部分是(ASSIGN R1 (FETCH R2))\nDialogue: 0,0:38:03.17,0:38:04.27,Default,,0,0,0,,这个例子就是这样的\nDialogue: 0,0:38:05.42,0:38:08.52,Default,,0,0,0,,一段指令序列大概就是这样\nDialogue: 0,0:38:08.77,0:38:10.53,Default,,0,0,0,,和它在一起的是\nDialogue: 0,0:38:10.64,0:38:15.76,Default,,0,0,0,,它需要记得修改了R1\nDialogue: 0,0:38:18.60,0:38:21.16,Default,,0,0,0,,然后它需要R2\nDialogue: 0,0:38:24.69,0:38:26.99,Default,,0,0,0,,因此当你开始构建编译器时\nDialogue: 0,0:38:27.10,0:38:29.35,Default,,0,0,0,,你放入这样的一个片段\nDialogue: 0,0:38:30.95,0:38:33.20,Default,,0,0,0,,当它组合两个序列时\nDialogue: 0,0:38:36.70,0:38:38.04,Default,,0,0,0,,我要组合\nDialogue: 0,0:38:38.92,0:38:41.58,Default,,0,0,0,,代码片段S1\nDialogue: 0,0:38:42.88,0:38:47.16,Default,,0,0,0,,修改了一组寄存器M1\nDialogue: 0,0:38:48.45,0:38:51.42,Default,,0,0,0,,并且需要一组寄存器N1\nDialogue: 0,0:38:54.85,0:38:59.48,Default,,0,0,0,,并且我要把它和序列S2组合到一起\nDialogue: 0,0:39:00.81,0:39:05.96,Default,,0,0,0,,后者修改了一组寄存器M2\nDialogue: 0,0:39:07.11,0:39:10.00,Default,,0,0,0,,并且需要一组寄存器N2\nDialogue: 0,0:39:12.44,0:39:14.83,Default,,0,0,0,,这样我们就能得出结果\nDialogue: 0,0:39:15.11,0:39:16.32,Default,,0,0,0,,新的代码片段是这样的\nDialogue: 0,0:39:17.18,0:39:21.82,Default,,0,0,0,,指令序列S1后面跟着S2\nDialogue: 0,0:39:24.09,0:39:26.45,Default,,0,0,0,,它要修改什么?\nDialogue: 0,0:39:27.80,0:39:29.18,Default,,0,0,0,,它要修改的是\nDialogue: 0,0:39:29.20,0:39:32.68,Default,,0,0,0,,被S1或者被S2修改的寄存器\nDialogue: 0,0:39:34.00,0:39:36.35,Default,,0,0,0,,N1和N2的并集\nDialogue: 0,0:39:37.68,0:39:39.64,Default,,0,0,0,,就是新的修改集\nDialogue: 0,0:39:40.46,0:39:41.79,Default,,0,0,0,,然后你问\nDialogue: 0,0:39:44.66,0:39:46.41,Default,,0,0,0,,又需要哪些寄存器？\nDialogue: 0,0:39:47.95,0:39:49.77,Default,,0,0,0,,需要这些寄存器的是\nDialogue: 0,0:39:49.93,0:39:51.85,Default,,0,0,0,,首先 一定是序列S1需要的\nDialogue: 0,0:39:52.91,0:39:54.49,Default,,0,0,0,,因此必然有N1\nDialogue: 0,0:39:55.19,0:39:58.28,Default,,0,0,0,,然后 并不是N2里面的所有元素\nDialogue: 0,0:39:58.32,0:39:59.61,Default,,0,0,0,,我们都需要\nDialogue: 0,0:39:59.75,0:40:03.49,Default,,0,0,0,,新的修改集需要N2中那些\nDialogue: 0,0:40:03.88,0:40:06.88,Default,,0,0,0,,没有被S1修改过的寄存器\nDialogue: 0,0:40:08.14,0:40:09.72,Default,,0,0,0,,所以 这个并集是N1并上\nDialogue: 0,0:40:11.66,0:40:13.40,Default,,0,0,0,,序列S2的需要集N2\nDialogue: 0,0:40:14.51,0:40:18.52,Default,,0,0,0,,减去序列S1的修改集M1\nDialogue: 0,0:40:19.31,0:40:20.88,Default,,0,0,0,,因为它关心的是如何设置它们\nDialogue: 0,0:40:23.95,0:40:26.26,Default,,0,0,0,,这就是编译器的基本结构\nDialogue: 0,0:40:26.70,0:40:29.82,Default,,0,0,0,,我们进行寄存器优化的方式是\nDialogue: 0,0:40:30.22,0:40:32.70,Default,,0,0,0,,一些策略来应对需要保护的东西\nDialogue: 0,0:40:34.10,0:40:35.63,Default,,0,0,0,,这取决于数据结构\nDialogue: 0,0:40:35.72,0:40:38.51,Default,,0,0,0,,这取决于将东西组合在一起的操作\nDialogue: 0,0:40:39.03,0:40:41.63,Default,,0,0,0,,想知道要保护哪些东西\nDialogue: 0,0:40:41.93,0:40:47.28,Default,,0,0,0,,就需要知道这段代码需要以及修改的寄存器\nDialogue: 0,0:40:48.75,0:40:51.26,Default,,0,0,0,,这就需要我们有一个数据结构\nDialogue: 0,0:40:51.42,0:40:55.43,Default,,0,0,0,,它不但要存放实际的指令序列\nDialogue: 0,0:40:55.60,0:40:57.33,Default,,0,0,0,,它修改了什么 又需要什么\nDialogue: 0,0:40:57.33,0:40:59.77,Default,,0,0,0,,这些信息来自于--最基本的情况是内置的\nDialogue: 0,0:40:59.79,0:41:01.36,Default,,0,0,0,,对于最基本的情况\nDialogue: 0,0:41:01.37,0:41:02.52,Default,,0,0,0,,我们可以容易地知道\nDialogue: 0,0:41:03.00,0:41:04.44,Default,,0,0,0,,需要哪些寄存器 又修改了哪些\nDialogue: 0,0:41:04.82,0:41:05.35,Default,,0,0,0,,另外\nDialogue: 0,0:41:05.44,0:41:08.60,Default,,0,0,0,,利用这个特定的方法构建复杂指令时\nDialogue: 0,0:41:09.28,0:41:11.89,Default,,0,0,0,,我们可以像这样生成新的修改集\nDialogue: 0,0:41:11.93,0:41:13.37,Default,,0,0,0,,以及新的需要集\nDialogue: 0,0:41:15.27,0:41:17.77,Default,,0,0,0,,这就是全部的内容 -- 我不该这么说\nDialogue: 0,0:41:17.77,0:41:19.34,Default,,0,0,0,,这就是书里面大概30页的细节\nDialogue: 0,0:41:19.74,0:41:21.87,Default,,0,0,0,,的核心内容了\nDialogue: 0,0:41:22.31,0:41:27.69,Default,,0,0,0,,但它是一个完全可用的初级编译器\nDialogue: 0,0:41:28.76,0:41:31.37,Default,,0,0,0,,让我给你展示一下它能做什么\nDialogue: 0,0:41:31.39,0:41:35.56,Default,,0,0,0,,假设我们从一个递归阶乘开始\nDialogue: 0,0:41:36.20,0:41:38.60,Default,,0,0,0,,这些幻灯片的字太小不适合阅读\nDialogue: 0,0:41:38.60,0:41:39.79,Default,,0,0,0,,我只想快速翻一下代码\nDialogue: 0,0:41:39.79,0:41:41.28,Default,,0,0,0,,让你们看看它有多少代码\nDialogue: 0,0:41:42.25,0:41:43.29,Default,,0,0,0,,代码从这开始--\nDialogue: 0,0:41:44.32,0:41:45.68,Default,,0,0,0,,这是代码的第一部分\nDialogue: 0,0:41:45.95,0:41:47.68,Default,,0,0,0,,这里编译了一个过程入口\nDialogue: 0,0:41:47.69,0:41:48.73,Default,,0,0,0,,并进行了一些赋值操作\nDialogue: 0,0:41:48.75,0:41:51.48,Default,,0,0,0,,这基本上对应了解释器中\nDialogue: 0,0:41:52.65,0:41:53.90,Default,,0,0,0,,进行判断之前的部分\nDialogue: 0,0:41:54.31,0:41:56.59,Default,,0,0,0,,并判断谓词是否成立\nDialogue: 0,0:41:56.97,0:41:57.85,Default,,0,0,0,,第二部分是\nDialogue: 0,0:41:58.46,0:42:03.73,Default,,0,0,0,,递归调用N-1的阶乘的结果\nDialogue: 0,0:42:04.12,0:42:05.05,Default,,0,0,0,,最后一部分是\nDialogue: 0,0:42:06.07,0:42:07.48,Default,,0,0,0,,从那里返回\nDialogue: 0,0:42:07.87,0:42:09.90,Default,,0,0,0,,并处理递归的基本情况\nDialogue: 0,0:42:09.90,0:42:13.16,Default,,0,0,0,,这就是编译阶乘会生成的代码量\nDialogue: 0,0:42:13.72,0:42:17.69,Default,,0,0,0,,当然 我们可以把这个编译器做得更好\nDialogue: 0,0:42:18.67,0:42:21.24,Default,,0,0,0,,优化它的主要方式是\nDialogue: 0,0:42:21.24,0:42:24.00,Default,,0,0,0,,当你调用一个过程时\nDialogue: 0,0:42:24.35,0:42:26.27,Default,,0,0,0,,允许编译器做任何假设\nDialogue: 0,0:42:26.97,0:42:28.28,Default,,0,0,0,,举例来说\nDialogue: 0,0:42:28.30,0:42:32.32,Default,,0,0,0,,这个编译器甚至不知道\nDialogue: 0,0:42:33.12,0:42:36.14,Default,,0,0,0,,乘法可以被内联执行\nDialogue: 0,0:42:36.14,0:42:37.87,Default,,0,0,0,,它则会自行构建起整个机制\nDialogue: 0,0:42:38.00,0:42:39.34,Default,,0,0,0,,进行APPLY-DISPATCH\nDialogue: 0,0:42:41.37,0:42:42.49,Default,,0,0,0,,这是极大的浪费\nDialogue: 0,0:42:42.54,0:42:45.02,Default,,0,0,0,,因为 每当你进行APPLY-DISPATCH时\nDialogue: 0,0:42:45.02,0:42:46.80,Default,,0,0,0,,你都要关心这个参数表\nDialogue: 0,0:42:47.40,0:42:49.10,Default,,0,0,0,,因为它是个很普遍的操作\nDialogue: 0,0:42:49.13,0:42:51.07,Default,,0,0,0,,在任何真实的编译器中\nDialogue: 0,0:42:51.08,0:42:53.29,Default,,0,0,0,,你会有寄存器来暂存参数\nDialogue: 0,0:42:53.77,0:42:55.31,Default,,0,0,0,,你要开始保护\nDialogue: 0,0:42:56.38,0:42:58.05,Default,,0,0,0,,保存这些寄存器\nDialogue: 0,0:42:58.05,0:43:01.61,Default,,0,0,0,,和这里的策略相近\nDialogue: 0,0:43:02.85,0:43:05.93,Default,,0,0,0,,因此 我们可能主要通过这个方法\nDialogue: 0,0:43:05.95,0:43:08.30,Default,,0,0,0,,来优化书中这个特定的编译器\nDialogue: 0,0:43:08.69,0:43:09.70,Default,,0,0,0,,还有其它的一些方法\nDialogue: 0,0:43:09.70,0:43:11.82,Default,,0,0,0,,比如查找变量的值\nDialogue: 0,0:43:11.83,0:43:13.87,Default,,0,0,0,,使用更高效的基本操作\nDialogue: 0,0:43:13.88,0:43:14.56,Default,,0,0,0,,等等方法\nDialogue: 0,0:43:14.59,0:43:16.60,Default,,0,0,0,,本质上来说 一个好的Lisp编译器\nDialogue: 0,0:43:16.62,0:43:18.49,Default,,0,0,0,,可以吸收任意数量的努力\nDialogue: 0,0:43:19.72,0:43:21.63,Default,,0,0,0,,可能这其中的一个原因是\nDialogue: 0,0:43:21.89,0:43:23.04,Default,,0,0,0,,跟FORTRAN这类语言相比\nDialogue: 0,0:43:23.63,0:43:25.44,Default,,0,0,0,,Lisp就要慢一些\nDialogue: 0,0:43:25.90,0:43:28.19,Default,,0,0,0,,如果你回头审视历史\nDialogue: 0,0:43:28.22,0:43:31.12,Default,,0,0,0,,会发现人们为构建Lisp编译器而呕心沥血\nDialogue: 0,0:43:31.16,0:43:32.35,Default,,0,0,0,,但也远远没有接近\nDialogue: 0,0:43:32.36,0:43:33.90,Default,,0,0,0,,构建FORTRAN编译器的工作量\nDialogue: 0,0:43:34.43,0:43:35.79,Default,,0,0,0,,在接下来的几年\nDialogue: 0,0:43:35.92,0:43:37.68,Default,,0,0,0,,情况可能会发生变化\nDialogue: 0,0:43:38.00,0:43:38.83,Default,,0,0,0,,好吧 就讲到这里\nDialogue: 0,0:43:43.80,0:43:44.65,Default,,0,0,0,,有问题吗\nDialogue: 0,0:43:48.27,0:43:49.95,Default,,0,0,0,,学生: 很早的一个课时里--\nDialogue: 0,0:43:49.95,0:43:51.40,Default,,0,0,0,,我不记得是课上还是课后--\nDialogue: 0,0:43:51.47,0:43:53.88,Default,,0,0,0,,你向我们展示了\nDialogue: 0,0:43:54.00,0:43:57.52,Default,,0,0,0,,ADD操作有一些我们看不到的基本运算\nDialogue: 0,0:43:57.69,0:43:59.21,Default,,0,0,0,,类似于ADD%之类的\nDialogue: 0,0:43:59.82,0:44:01.65,Default,,0,0,0,,这是因为\nDialogue: 0,0:44:01.65,0:44:02.60,Default,,0,0,0,,你想把代码内联为\nDialogue: 0,0:44:02.60,0:44:08.19,Default,,0,0,0,,专门针对二元运算对象的运算么？\nDialogue: 0,0:44:08.70,0:44:10.25,Default,,0,0,0,,但如果你有更多的运算对象\nDialogue: 0,0:44:10.28,0:44:11.47,Default,,0,0,0,,你会做什么特殊的事情吗？\nDialogue: 0,0:44:12.71,0:44:16.04,Default,,0,0,0,,教授: 你看的是Scheme的实际实现\nDialogue: 0,0:44:16.06,0:44:17.84,Default,,0,0,0,,其中有一个‘+’ 这是一个运算符\nDialogue: 0,0:44:17.90,0:44:20.19,Default,,0,0,0,,如果你看‘+’的源代码\nDialogue: 0,0:44:20.33,0:44:21.37,Default,,0,0,0,,你会看到一些叫做--\nDialogue: 0,0:44:21.57,0:44:24.14,Default,,0,0,0,,我记不清了--可能叫ADD%、PLUS之类的东西\nDialogue: 0,0:44:24.55,0:44:25.79,Default,,0,0,0,,这里所进行的\nDialogue: 0,0:44:25.79,0:44:27.92,Default,,0,0,0,,就是你说的那种优化\nDialogue: 0,0:44:28.47,0:44:31.87,Default,,0,0,0,,因为 广义的‘+’接受任意数量的参数\nDialogue: 0,0:44:35.02,0:44:36.38,Default,,0,0,0,,所以 广义加法\nDialogue: 0,0:44:36.76,0:44:38.25,Default,,0,0,0,,会说：如果我有一个参数表\nDialogue: 0,0:44:38.28,0:44:40.62,Default,,0,0,0,,我最好将它们用CONS连接到表里\nDialogue: 0,0:44:41.63,0:44:44.14,Default,,0,0,0,,并指出有多少个参数\nDialogue: 0,0:44:44.72,0:44:46.16,Default,,0,0,0,,这样效率非常低下\nDialogue: 0,0:44:46.81,0:44:49.25,Default,,0,0,0,,因为大部分时间你在把两个数相加\nDialogue: 0,0:44:49.25,0:44:51.24,Default,,0,0,0,,你不必把整个参数表连接到一起\nDialogue: 0,0:44:52.04,0:44:53.93,Default,,0,0,0,,所以你想做的是\nDialogue: 0,0:44:55.66,0:44:57.71,Default,,0,0,0,,构建把一堆东西相加的代码\nDialogue: 0,0:44:58.15,0:45:00.17,Default,,0,0,0,,所以它做的大部分事情是一样的\nDialogue: 0,0:45:00.49,0:45:01.95,Default,,0,0,0,,但这里可能有个特殊的入口\nDialogue: 0,0:45:01.98,0:45:03.92,Default,,0,0,0,,如果你知道只有两个参数\nDialogue: 0,0:45:04.56,0:45:05.87,Default,,0,0,0,,你会把它们放到寄存器中\nDialogue: 0,0:45:05.87,0:45:06.97,Default,,0,0,0,,它们不需要参数表\nDialogue: 0,0:45:06.99,0:45:07.98,Default,,0,0,0,,你也不必用CONS连接它们\nDialogue: 0,0:45:08.67,0:45:10.42,Default,,0,0,0,,这就是这些东西工作的原理\nDialogue: 0,0:45:12.30,0:45:13.72,Default,,0,0,0,,好吧 下课吧\nDialogue: 0,0:45:14.10,0:45:42.97,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:45:14.10,0:45:42.97,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec10a.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:11.84,0:00:13.84,EN,,0,0,0,,Compilation\nDialogue: 0,0:00:19.36,0:00:22.65,EN,,0,0,0,,PROFESSOR: Last time, we took a look at\nDialogue: 0,0:00:22.65,0:00:25.67,EN,,0,0,0,,an explicit control evaluator for Lisp\nDialogue: 0,0:00:25.67,0:00:28.97,EN,,0,0,0,,and that bridged the gap between all these high-level languages\nDialogue: 0,0:00:29.05,0:00:32.14,EN,,0,0,0,,like Lisp and query language all that stuff\nDialogue: 0,0:00:32.50,0:00:36.16,EN,,0,0,0,,bridged the gap between that and a conventional register machine.\nDialogue: 0,0:00:36.70,0:00:40.14,EN,,0,0,0,,And in fact, you can think of the explicit control evaluator\nDialogue: 0,0:00:40.16,0:00:44.38,EN,,0,0,0,,either as, say the code for a Lisp interpreter\nDialogue: 0,0:00:44.40,0:00:45.95,EN,,0,0,0,,if you wanted to implement it in the\nDialogue: 0,0:00:46.52,0:00:49.50,EN,,0,0,0,,assembly language of some conventional register transfer machine,\nDialogue: 0,0:00:49.50,0:00:51.50,EN,,0,0,0,,or, if you like, you can think of it as the microcode\nDialogue: 0,0:00:52.08,0:00:54.56,EN,,0,0,0,,of some machine that's going to be specially designed to run Lisp.\nDialogue: 0,0:00:55.20,0:00:55.92,EN,,0,0,0,,In either case,\nDialogue: 0,0:00:55.92,0:00:58.68,EN,,0,0,0,,Nwhat we're doing is we're taking a machine\nDialogue: 0,0:00:58.94,0:01:00.51,EN,,0,0,0,,that speaks some low-level language\nDialogue: 0,0:01:01.42,0:01:03.32,EN,,0,0,0,,and we're raising the machine\nDialogue: 0,0:01:03.37,0:01:04.88,EN,,0,0,0,,to a high-level language like Lisp\nDialogue: 0,0:01:05.36,0:01:06.35,EN,,0,0,0,,by writing an interpreter.\nDialogue: 0,0:01:08.22,0:01:09.58,EN,,0,0,0,,So for instance\nDialogue: 0,0:01:11.82,0:01:13.77,EN,,0,0,0,,here, conceptually,\nDialogue: 0,0:01:18.01,0:01:19.47,EN,,0,0,0,,here conceptually is a\nDialogue: 0,0:01:20.54,0:01:23.44,EN,,0,0,0,,a special purpose machine for computing factorials.\nDialogue: 0,0:01:24.09,0:01:27.39,EN,,0,0,0,,It takes in five and puts out 120.\nDialogue: 0,0:01:28.92,0:01:30.83,EN,,0,0,0,,And what this special purpose machine is\nDialogue: 0,0:01:30.97,0:01:32.72,EN,,0,0,0,,actually a Lisp interpreter\nDialogue: 0,0:01:33.50,0:01:36.17,EN,,0,0,0,,that's configured itself to run factorials\nDialogue: 0,0:01:38.35,0:01:40.99,EN,,0,0,0,,because you feed into it a description of the factorial machine.\nDialogue: 0,0:01:42.12,0:01:43.70,EN,,0,0,0,,So that's what an interpreter is.\nDialogue: 0,0:01:43.70,0:01:45.66,EN,,0,0,0,,It configures itself to\nDialogue: 0,0:01:46.37,0:01:49.24,EN,,0,0,0,,emulate a machine whose description you read in.\nDialogue: 0,0:01:50.07,0:01:51.93,EN,,0,0,0,,Now, inside the Lisp interpreter, what's that?\nDialogue: 0,0:01:52.04,0:01:55.44,EN,,0,0,0,,Well, that might be your general register language interpreter\nDialogue: 0,0:01:56.98,0:02:00.18,EN,,0,0,0,,that configures itself to behave like a Lisp interpreter\nDialogue: 0,0:02:00.18,0:02:02.03,EN,,0,0,0,,because you put in a whole bunch of instructions\nDialogue: 0,0:02:02.12,0:02:03.04,EN,,0,0,0,,in register language.\nDialogue: 0,0:02:03.37,0:02:05.16,EN,,0,0,0,,This is the explicit control evaluator.\nDialogue: 0,0:02:07.05,0:02:08.70,EN,,0,0,0,,And then it also has some sort of library\nDialogue: 0,0:02:08.73,0:02:11.08,EN,,0,0,0,,a library of primitive operators and Lisp operations\nDialogue: 0,0:02:11.12,0:02:12.28,EN,,0,0,0,,all sorts of things like that.\nDialogue: 0,0:02:12.75,0:02:16.89,EN,,0,0,0,,That's the general strategy of interpretation.\nDialogue: 0,0:02:17.32,0:02:18.51,EN,,0,0,0,,And the point is, what we're doing\nDialogue: 0,0:02:18.60,0:02:20.14,EN,,0,0,0,,is we're writing an interpreter\nDialogue: 0,0:02:21.62,0:02:23.40,EN,,0,0,0,,to raise the machine\nDialogue: 0,0:02:23.42,0:02:25.24,EN,,0,0,0,,to the level of the programs that we want to write.\nDialogue: 0,0:02:25.24,0:02:26.72,EN,,0,0,0,,Well, there's another strategy\nDialogue: 0,0:02:27.42,0:02:28.89,EN,,0,0,0,,a different one, which is compilation.\nDialogue: 0,0:02:29.04,0:02:30.43,EN,,0,0,0,,Compilation's a little bit different.\nDialogue: 0,0:02:31.04,0:02:31.50,EN,,0,0,0,,Here--\nDialogue: 0,0:02:33.37,0:02:34.75,EN,,0,0,0,,here we might have produced\nDialogue: 0,0:02:35.67,0:02:38.52,EN,,0,0,0,,a special purpose machine for,\nDialogue: 0,0:02:38.62,0:02:39.98,EN,,0,0,0,,for computing factorials\nDialogue: 0,0:02:43.62,0:02:46.26,EN,,0,0,0,,starting with some sort of machine that speaks register language\nDialogue: 0,0:02:46.26,0:02:47.72,EN,,0,0,0,,except we're going to do a different strategy.\nDialogue: 0,0:02:47.72,0:02:50.38,EN,,0,0,0,,We take our factorial program.\nDialogue: 0,0:02:51.55,0:02:53.92,EN,,0,0,0,,We use that as the source code into a compiler.\nDialogue: 0,0:02:53.92,0:02:55.15,EN,,0,0,0,,What the compiler will do\nDialogue: 0,0:02:55.15,0:02:57.62,EN,,0,0,0,,is translate that factorial program\nDialogue: 0,0:02:57.62,0:02:59.07,EN,,0,0,0,,into some register machine language.\nDialogue: 0,0:03:00.25,0:03:03.40,EN,,0,0,0,,And this will now be not the explicit control evaluator for Lisp\nDialogue: 0,0:03:03.40,0:03:06.17,EN,,0,0,0,,this will be some register language for computing factorials.\nDialogue: 0,0:03:06.49,0:03:08.36,EN,,0,0,0,,So this is the translation of that.\nDialogue: 0,0:03:10.54,0:03:12.41,EN,,0,0,0,,That will go into some sort of loader\nDialogue: 0,0:03:13.35,0:03:15.21,EN,,0,0,0,,which will combine this code\nDialogue: 0,0:03:15.31,0:03:16.84,EN,,0,0,0,,with code selected from the library\nDialogue: 0,0:03:16.86,0:03:18.65,EN,,0,0,0,,to do things like primitive multiplication.\nDialogue: 0,0:03:19.82,0:03:21.69,EN,,0,0,0,,And then we'll produce a load module\nDialogue: 0,0:03:22.22,0:03:25.06,EN,,0,0,0,,which configures the register language machine\nDialogue: 0,0:03:25.06,0:03:27.24,EN,,0,0,0,,to be a special purpose factorial machine.\nDialogue: 0,0:03:28.12,0:03:30.22,EN,,0,0,0,,So that's a, that's a different strategy.\nDialogue: 0,0:03:30.22,0:03:31.22,EN,,0,0,0,,In interpretation,\nDialogue: 0,0:03:31.22,0:03:32.01,EN,,0,0,0,,we're raising\nDialogue: 0,0:03:32.91,0:03:35.23,EN,,0,0,0,,the machine to the level of our language, like Lisp.\nDialogue: 0,0:03:35.32,0:03:36.34,EN,,0,0,0,,In compilation\nDialogue: 0,0:03:36.34,0:03:38.43,EN,,0,0,0,,we're taking our program and lowering\nDialogue: 0,0:03:38.48,0:03:40.56,EN,,0,0,0,,it to the language that's spoken by the machine.\nDialogue: 0,0:03:41.96,0:03:43.84,EN,,0,0,0,,Well, how do these two strategies compare?\nDialogue: 0,0:03:44.30,0:03:49.42,EN,,0,0,0,,The compiler can produce code that will execute more efficiently.\nDialogue: 0,0:03:52.05,0:03:53.90,EN,,0,0,0,,The essential reason for that\nDialogue: 0,0:03:54.17,0:03:58.89,EN,,0,0,0,,is that if you think about the register operations that are running\nDialogue: 0,0:04:01.92,0:04:04.49,EN,,0,0,0,,the interpreter has to produce register operations\nDialogue: 0,0:04:04.97,0:04:06.75,EN,,0,0,0,,which, in principle, are going to be general enough\nDialogue: 0,0:04:07.32,0:04:08.94,EN,,0,0,0,,to execute any Lisp procedure.\nDialogue: 0,0:04:10.22,0:04:12.25,EN,,0,0,0,,Whereas the compiler only has to worry about\nDialogue: 0,0:04:12.27,0:04:14.92,EN,,0,0,0,,producing a special bunch of register operations for\nDialogue: 0,0:04:15.52,0:04:18.22,EN,,0,0,0,,for doing the particular Lisp procedure that you've compiled.\nDialogue: 0,0:04:20.17,0:04:21.20,EN,,0,0,0,,Or another way to say that\nDialogue: 0,0:04:21.20,0:04:25.31,EN,,0,0,0,,is that the interpreter is a general purpose simulator\nDialogue: 0,0:04:25.92,0:04:27.58,EN,,0,0,0,,that when you read in a Lisp procedure\nDialogue: 0,0:04:27.58,0:04:31.32,EN,,0,0,0,,then those can simulate the program described by that, by that procedure.\nDialogue: 0,0:04:31.32,0:04:33.87,EN,,0,0,0,,So the interpreter is worrying about making a general purpose simulator\nDialogue: 0,0:04:34.62,0:04:35.96,EN,,0,0,0,,whereas the compiler, in effect,\nDialogue: 0,0:04:36.00,0:04:37.68,EN,,0,0,0,,is configuring the thing to be the machine\nDialogue: 0,0:04:37.71,0:04:39.34,EN,,0,0,0,,that the interpreter would have been simulating.\nDialogue: 0,0:04:40.02,0:04:41.34,EN,,0,0,0,,So the compiler can be faster.\nDialogue: 0,0:04:52.55,0:04:53.64,EN,,0,0,0,,OK, On the other hand\nDialogue: 0,0:04:55.97,0:04:58.28,EN,,0,0,0,,the interpreter is a nicer environment for debugging.\nDialogue: 0,0:04:59.43,0:05:01.25,EN,,0,0,0,,And the reason for that is that we've got the\nDialogue: 0,0:05:01.57,0:05:03.02,EN,,0,0,0,,the source code actually there.\nDialogue: 0,0:05:03.02,0:05:04.81,EN,,0,0,0,,We're interpreting it That's what we're working with.\nDialogue: 0,0:05:05.87,0:05:07.69,EN,,0,0,0,,And we also have the library around.\nDialogue: 0,0:05:07.90,0:05:10.89,EN,,0,0,0,,See, the interpreter--the library sitting there is part of the interpreter.\nDialogue: 0,0:05:11.30,0:05:13.16,EN,,0,0,0,,The compiler only pulls out from the library\nDialogue: 0,0:05:13.20,0:05:14.56,EN,,0,0,0,,what it needs to run the program.\nDialogue: 0,0:05:14.87,0:05:17.00,EN,,0,0,0,,So if you're in the middle of debugging\nDialogue: 0,0:05:18.00,0:05:20.72,EN,,0,0,0,,and you might like to write a little extra program\nDialogue: 0,0:05:20.80,0:05:22.57,EN,,0,0,0,,to examine some run time data structure\nDialogue: 0,0:05:23.05,0:05:24.25,EN,,0,0,0,,or to produce some computation\nDialogue: 0,0:05:24.30,0:05:25.92,EN,,0,0,0,,that you didn't think of when you wrote the program\nDialogue: 0,0:05:25.95,0:05:27.53,EN,,0,0,0,,the interpreter can do that perfectly well\nDialogue: 0,0:05:28.05,0:05:29.21,EN,,0,0,0,,whereas the compiler can't.\nDialogue: 0,0:05:29.62,0:05:31.90,EN,,0,0,0,,So there are sort of dual, dual advantages.\nDialogue: 0,0:05:31.90,0:05:34.48,EN,,0,0,0,,The compiler will produce code that executes faster.\nDialogue: 0,0:05:34.85,0:05:37.02,EN,,0,0,0,,The interpreter is a better environment for debugging.\nDialogue: 0,0:05:38.95,0:05:41.40,EN,,0,0,0,,And most Lisp systems end up having both\nDialogue: 0,0:05:42.92,0:05:45.23,EN,,0,0,0,,end up being configured so you have an interpreter\nDialogue: 0,0:05:45.24,0:05:47.08,EN,,0,0,0,,that you use when you're developing your code.\nDialogue: 0,0:05:47.08,0:05:48.62,EN,,0,0,0,,Then you can speed it up by compiling.\nDialogue: 0,0:05:49.02,0:05:50.03,EN,,0,0,0,,And very often,\nDialogue: 0,0:05:50.04,0:05:51.68,EN,,0,0,0,,you can arrange that compiled code\nDialogue: 0,0:05:51.69,0:05:53.56,EN,,0,0,0,,and interpreted code can call each other.\nDialogue: 0,0:05:54.60,0:05:56.33,EN,,0,0,0,,We'll see how to do that, That's not hard.\nDialogue: 0,0:05:59.27,0:05:59.85,EN,,0,0,0,,OK\nDialogue: 0,0:06:00.97,0:06:02.09,EN,,0,0,0,,In fact, the way we'll--\nDialogue: 0,0:06:04.30,0:06:05.75,EN,,0,0,0,,in the compiler we're going to make\nDialogue: 0,0:06:05.75,0:06:07.58,EN,,0,0,0,,the way we'll arrange for compiled coding\nDialogue: 0,0:06:07.58,0:06:09.45,EN,,0,0,0,,and interpreted code to call to call each other\nDialogue: 0,0:06:09.90,0:06:12.06,EN,,0,0,0,,is that we'll have the compiler use exactly\nDialogue: 0,0:06:12.11,0:06:14.40,EN,,0,0,0,,the same register conventions as the interpreter.\nDialogue: 0,0:06:18.42,0:06:21.72,EN,,0,0,0,,Well, the idea of a compiler\nDialogue: 0,0:06:21.76,0:06:25.74,EN,,0,0,0,,is very much like the idea of an interpreter or evaluator.\nDialogue: 0,0:06:25.87,0:06:26.46,EN,,0,0,0,,It's the same thing.\nDialogue: 0,0:06:27.05,0:06:29.39,EN,,0,0,0,,See, the evaluator walks over the code\nDialogue: 0,0:06:29.82,0:06:32.35,EN,,0,0,0,,and performs some register operations.\nDialogue: 0,0:06:33.65,0:06:34.97,EN,,0,0,0,,That's what we did yesterday.\nDialogue: 0,0:06:37.10,0:06:40.27,EN,,0,0,0,,Well, the compiler essentially would like to walk over the code\nDialogue: 0,0:06:40.52,0:06:43.00,EN,,0,0,0,,and produce the register operations\nDialogue: 0,0:06:43.04,0:06:44.67,EN,,0,0,0,,that the evaluator would have done\nDialogue: 0,0:06:45.23,0:06:46.64,EN,,0,0,0,,were it evaluating the thing.\nDialogue: 0,0:06:48.60,0:06:49.95,EN,,0,0,0,,And that gives us some model\nDialogue: 0,0:06:50.60,0:06:53.77,EN,,0,0,0,,for how to implement a zeroth-order compiler\nDialogue: 0,0:06:55.30,0:06:58.32,EN,,0,0,0,,a very bad compiler but essentially a compiler.\nDialogue: 0,0:06:58.32,0:06:59.32,EN,,0,0,0,,A model for doing that\nDialogue: 0,0:06:59.36,0:07:00.59,EN,,0,0,0,,is you just take the evaluator,\nDialogue: 0,0:07:00.68,0:07:01.88,EN,,0,0,0,,you run it over the code\nDialogue: 0,0:07:02.80,0:07:06.06,EN,,0,0,0,,but instead of executing the actual operations\nDialogue: 0,0:07:06.06,0:07:07.15,EN,,0,0,0,,you just save them away.\nDialogue: 0,0:07:07.55,0:07:08.82,EN,,0,0,0,,And that's your compiled code.\nDialogue: 0,0:07:08.82,0:07:10.24,EN,,0,0,0,,So let me give you an example of that.\nDialogue: 0,0:07:12.70,0:07:14.14,EN,,0,0,0,,Suppose we're going to compile--\nDialogue: 0,0:07:15.10,0:07:17.90,EN,,0,0,0,,Suppose we want to compile the expression f of x.\nDialogue: 0,0:07:25.07,0:07:25.96,EN,,0,0,0,,So let's assume that\nDialogue: 0,0:07:25.96,0:07:28.06,EN,,0,0,0,,we've got f of x in the exp register\nDialogue: 0,0:07:28.06,0:07:29.55,EN,,0,0,0,,and something in the environment register.\nDialogue: 0,0:07:30.10,0:07:32.20,EN,,0,0,0,,And now imagine starting up the evaluator.\nDialogue: 0,0:07:34.60,0:07:35.71,EN,,0,0,0,,Well, it looks at the expression\nDialogue: 0,0:07:35.71,0:07:37.36,EN,,0,0,0,,and it sees that it's an application.\nDialogue: 0,0:07:37.92,0:07:41.90,EN,,0,0,0,,And it branches to a place in the\nDialogue: 0,0:07:42.52,0:07:45.15,EN,,0,0,0,,in the evaluator code we saw called ev-application.\nDialogue: 0,0:07:47.12,0:07:48.12,EN,,0,0,0,,And then it begins.\nDialogue: 0,0:07:48.16,0:07:50.08,EN,,0,0,0,,It stores away the operands and unev\nDialogue: 0,0:07:50.08,0:07:52.44,EN,,0,0,0,,and then it's going to put the operator in exp,\nDialogue: 0,0:07:52.48,0:07:54.27,EN,,0,0,0,,and it's going to go recursively evaluate it.\nDialogue: 0,0:07:54.47,0:07:56.08,EN,,0,0,0,,That's the process that we walk through.\nDialogue: 0,0:07:56.67,0:07:57.84,EN,,0,0,0,,And if you start looking at the code,\nDialogue: 0,0:07:57.87,0:07:59.74,EN,,0,0,0,,you start seeing some register operations.\nDialogue: 0,0:08:00.20,0:08:02.30,EN,,0,0,0,,You see assign to unev the operands\nDialogue: 0,0:08:02.30,0:08:03.95,EN,,0,0,0,,assign to exp the operator,\nDialogue: 0,0:08:04.09,0:08:06.20,EN,,0,0,0,,save the environment, generate that, and so on.\nDialogue: 0,0:08:10.22,0:08:11.93,EN,,0,0,0,,Well, if we look on the overhead here\nDialogue: 0,0:08:15.75,0:08:19.58,EN,,0,0,0,,we can see those operations starting to be produced.\nDialogue: 0,0:08:20.82,0:08:22.52,EN,,0,0,0,,Here's sort of the first real operation\nDialogue: 0,0:08:22.72,0:08:24.80,EN,,0,0,0,,that the evaluator would have done.\nDialogue: 0,0:08:25.00,0:08:27.20,EN,,0,0,0,,It pulls the operands out of the exp register\nDialogue: 0,0:08:27.47,0:08:28.62,EN,,0,0,0,,and assigns it to unev.\nDialogue: 0,0:08:30.03,0:08:32.27,EN,,0,0,0,,And then it assigns something to the expression register,\nDialogue: 0,0:08:32.30,0:08:33.46,EN,,0,0,0,,and it saves continue\nDialogue: 0,0:08:33.46,0:08:34.62,EN,,0,0,0,,and it saves env.\nDialogue: 0,0:08:34.62,0:08:38.65,EN,,0,0,0,,And all I'm doing here is writing down the register assignments\nDialogue: 0,0:08:39.57,0:08:42.32,EN,,0,0,0,,that the evaluator would have done in executing that code.\nDialogue: 0,0:08:42.77,0:08:43.79,EN,,0,0,0,,And can zoom out a little bit.\nDialogue: 0,0:08:44.30,0:08:47.13,EN,,0,0,0,,Altogether, there are about 19 operations there.\nDialogue: 0,0:08:49.40,0:08:51.64,EN,,0,0,0,,And this is the--this will be the piece of code\nDialogue: 0,0:08:52.05,0:08:53.90,EN,,0,0,0,,up until the point where\nDialogue: 0,0:08:54.75,0:08:57.10,EN,,0,0,0,,the evaluator branches off to apply-dispatch.\nDialogue: 0,0:08:57.86,0:08:59.16,EN,,0,0,0,,And in fact, in this compiler\nDialogue: 0,0:08:59.20,0:09:01.18,EN,,0,0,0,,we're not going to worry about apply-dispatch at all.\nDialogue: 0,0:09:01.30,0:09:02.11,EN,,0,0,0,,We're going to have everything\nDialogue: 0,0:09:02.35,0:09:05.04,EN,,0,0,0,,we're going to have both interpreted code and compiled code.\nDialogue: 0,0:09:06.07,0:09:07.61,EN,,0,0,0,,Always evaluate procedures,\nDialogue: 0,0:09:07.61,0:09:09.85,EN,,0,0,0,,always apply procedures by going to apply-dispatch.\nDialogue: 0,0:09:10.27,0:09:12.32,EN,,0,0,0,,That will easily allow interpreted code and\nDialogue: 0,0:09:12.36,0:09:13.71,EN,,0,0,0,,compiled code to call each other.\nDialogue: 0,0:09:18.27,0:09:19.87,EN,,0,0,0,,Well, in principle, that's all we need to do.\nDialogue: 0,0:09:21.05,0:09:22.66,EN,,0,0,0,,You just run the evaluator.\nDialogue: 0,0:09:22.66,0:09:24.50,EN,,0,0,0,,So the compiler's a lot like the evaluator.\nDialogue: 0,0:09:24.50,0:09:26.47,EN,,0,0,0,,You run it, except it stashes away these operations\nDialogue: 0,0:09:26.47,0:09:28.40,EN,,0,0,0,,instead of actually executing them.\nDialogue: 0,0:09:29.35,0:09:31.39,EN,,0,0,0,,Well, that's not, that's not quite true. there's\nDialogue: 0,0:09:32.91,0:09:34.99,EN,,0,0,0,,There's only one little lie in that.\nDialogue: 0,0:09:36.24,0:09:39.29,EN,,0,0,0,,What you have to worry about is if you have a, a predicate.\nDialogue: 0,0:09:40.12,0:09:42.16,EN,,0,0,0,,If you have some kind of test you want to do\nDialogue: 0,0:09:43.45,0:09:46.03,EN,,0,0,0,,obviously, at the point when you're compiling it\nDialogue: 0,0:09:46.52,0:09:47.98,EN,,0,0,0,,you don't know which branch of these--\nDialogue: 0,0:09:48.32,0:09:50.14,EN,,0,0,0,,of a conditional like this you're going to do.\nDialogue: 0,0:09:51.13,0:09:53.92,EN,,0,0,0,,So you can't say which one the evaluator would have done.\nDialogue: 0,0:09:54.90,0:09:57.12,EN,,0,0,0,,So all you do there is very simple.\nDialogue: 0,0:09:57.12,0:09:58.49,EN,,0,0,0,,You compile both branches.\nDialogue: 0,0:09:59.32,0:10:01.29,EN,,0,0,0,,So you compile a structure that looks like this.\nDialogue: 0,0:10:02.00,0:10:03.98,EN,,0,0,0,,That'll compile into something that says,\nDialogue: 0,0:10:05.31,0:10:09.15,EN,,0,0,0,,the code, the code for P.\nDialogue: 0,0:10:10.71,0:10:16.51,EN,,0,0,0,,And it puts its results in, say, the val register.\nDialogue: 0,0:10:18.17,0:10:20.64,EN,,0,0,0,,So you walk the interpreter over the predicate\nDialogue: 0,0:10:21.35,0:10:24.19,EN,,0,0,0,,and make sure that the result would go into the val register.\nDialogue: 0,0:10:24.70,0:10:27.22,EN,,0,0,0,,And then you compile an instruction that says\nDialogue: 0,0:10:27.22,0:10:33.79,EN,,0,0,0,,branch if, if val is true\nDialogue: 0,0:10:37.17,0:10:38.75,EN,,0,0,0,,to a place we'll call label one.\nDialogue: 0,0:10:44.97,0:10:47.52,EN,,0,0,0,,Then we, we will put the code for B\nDialogue: 0,0:10:49.42,0:10:52.32,EN,,0,0,0,,to walk the interpreter--walk the interpreter over B.\nDialogue: 0,0:10:53.62,0:10:57.21,EN,,0,0,0,,And then go to put in an instruction that says,\nDialogue: 0,0:10:57.23,0:10:58.75,EN,,0,0,0,,go to the next thing, whatever\nDialogue: 0,0:11:02.20,0:11:04.56,EN,,0,0,0,,whatever was supposed to happen after this thing was done.\nDialogue: 0,0:11:04.95,0:11:06.09,EN,,0,0,0,,You put in that instruction.\nDialogue: 0,0:11:06.88,0:11:08.62,EN,,0,0,0,,And here you put label one.\nDialogue: 0,0:11:12.12,0:11:13.80,EN,,0,0,0,,And here you put the code for A.\nDialogue: 0,0:11:19.47,0:11:25.85,EN,,0,0,0,,And you put go to next thing.\nDialogue: 0,0:11:31.42,0:11:32.88,EN,,0,0,0,,So that's how you treat a conditional.\nDialogue: 0,0:11:32.98,0:11:34.65,EN,,0,0,0,,You generate a little block like that.\nDialogue: 0,0:11:35.75,0:11:38.12,EN,,0,0,0,,And other than that\nDialogue: 0,0:11:38.95,0:11:41.55,EN,,0,0,0,,this zeroth-order compiler is the same as the evaluator.\nDialogue: 0,0:11:42.55,0:11:45.12,EN,,0,0,0,,It's just stashing away the instructions instead of executing them.\nDialogue: 0,0:11:46.55,0:11:47.60,EN,,0,0,0,,That seems pretty simple,\nDialogue: 0,0:11:47.64,0:11:49.08,EN,,0,0,0,,but we've gained something by that.\nDialogue: 0,0:11:50.12,0:11:52.62,EN,,0,0,0,,See, already that's going to be more efficient than the evaluator.\nDialogue: 0,0:11:53.52,0:11:56.14,EN,,0,0,0,,Because, if you watch the evaluator run\nDialogue: 0,0:11:56.35,0:12:01.05,EN,,0,0,0,,it's not only generating the register operations we wrote down\nDialogue: 0,0:12:01.27,0:12:03.50,EN,,0,0,0,,it's also doing things to decide which ones to generate.\nDialogue: 0,0:12:04.70,0:12:07.23,EN,,0,0,0,,So the very first thing it does, say here\nDialogue: 0,0:12:07.92,0:12:09.77,EN,,0,0,0,,here for instance, is go do some tests\nDialogue: 0,0:12:09.77,0:12:11.56,EN,,0,0,0,,and decide that this is an application\nDialogue: 0,0:12:13.57,0:12:15.05,EN,,0,0,0,,and then branch off to the place that,\nDialogue: 0,0:12:15.39,0:12:16.62,EN,,0,0,0,,that handles applications.\nDialogue: 0,0:12:16.62,0:12:18.44,EN,,0,0,0,,In other words, what the evaluator's doing\nDialogue: 0,0:12:18.62,0:12:22.76,EN,,0,0,0,,is simultaneously analyzing the code to see what to do\nDialogue: 0,0:12:23.47,0:12:24.99,EN,,0,0,0,,and running these operations.\nDialogue: 0,0:12:25.55,0:12:28.28,EN,,0,0,0,,And when you-- if you run the evaluator a million times\nDialogue: 0,0:12:28.28,0:12:30.30,EN,,0,0,0,,that analysis phase happens a million times\nDialogue: 0,0:12:30.85,0:12:32.58,EN,,0,0,0,,whereas in the compiler, it's happened once\nDialogue: 0,0:12:32.58,0:12:34.81,EN,,0,0,0,,and then you just have the register operations themselves.\nDialogue: 0,0:12:39.20,0:12:41.68,EN,,0,0,0,,Ok, that's a, a zeroth-order compiler\nDialogue: 0,0:12:41.80,0:12:44.04,EN,,0,0,0,,but it is a wretched, wretched compiler.\nDialogue: 0,0:12:44.45,0:12:45.28,EN,,0,0,0,,It's really dumb.\nDialogue: 0,0:12:46.90,0:12:48.41,EN,,0,0,0,,Let's--let's go back and,\nDialogue: 0,0:12:49.88,0:12:50.97,EN,,0,0,0,,and look at this overhead.\nDialogue: 0,0:12:52.02,0:12:55.29,EN,,0,0,0,,So look at look at some of the operations this thing is doing.\nDialogue: 0,0:12:55.85,0:12:56.88,EN,,0,0,0,,We're supposedly\nDialogue: 0,0:12:59.72,0:13:02.28,EN,,0,0,0,,looking at the operations in interpreting f of x.\nDialogue: 0,0:13:03.52,0:13:04.84,EN,,0,0,0,,Now, look here what it's doing.\nDialogue: 0,0:13:05.17,0:13:06.11,EN,,0,0,0,,For example, here\nDialogue: 0,0:13:07.15,0:13:11.98,EN,,0,0,0,,it assigns to exp the operator in fetch of exp.\nDialogue: 0,0:13:13.75,0:13:15.87,EN,,0,0,0,,But see, there's no reason to do that, because this is--\nDialogue: 0,0:13:16.22,0:13:17.47,EN,,0,0,0,,the compiler knows\nDialogue: 0,0:13:17.66,0:13:21.84,EN,,0,0,0,,that the operator, fetch of exp,  is f right here.\nDialogue: 0,0:13:23.35,0:13:25.56,EN,,0,0,0,,So there's no reason why this instruction should say that.\nDialogue: 0,0:13:25.70,0:13:28.88,EN,,0,0,0,,It should say, we'll assign to exp, f.\nDialogue: 0,0:13:29.45,0:13:31.08,EN,,0,0,0,,Or in fact, you don't need exp at all.\nDialogue: 0,0:13:31.87,0:13:33.56,EN,,0,0,0,,There's no reason it should have exp at all.\nDialogue: 0,0:13:33.56,0:13:35.16,EN,,0,0,0,,What, what did exp get used for?\nDialogue: 0,0:13:35.18,0:13:36.33,EN,,0,0,0,,Well, if we come down here\nDialogue: 0,0:13:40.77,0:13:42.20,EN,,0,0,0,,we're going to assign to val\nDialogue: 0,0:13:43.05,0:13:47.34,EN,,0,0,0,,look up the stuff in exp in the environment.\nDialogue: 0,0:13:48.68,0:13:49.53,EN,,0,0,0,,So what we really should do\nDialogue: 0,0:13:49.55,0:13:51.54,EN,,0,0,0,,get rid of the exp register altogether\nDialogue: 0,0:13:51.54,0:13:53.32,EN,,0,0,0,,and just change this instruction to say,\nDialogue: 0,0:13:53.34,0:13:54.16,EN,,0,0,0,,assign to val\nDialogue: 0,0:13:54.45,0:13:56.06,EN,,0,0,0,,look up the variable value\nDialogue: 0,0:13:56.36,0:13:58.40,EN,,0,0,0,,of the symbol f in the environment.\nDialogue: 0,0:14:01.09,0:14:01.77,EN,,0,0,0,,Similarly\nDialogue: 0,0:14:02.57,0:14:04.27,EN,,0,0,0,,back up here, we don't need unev at all\nDialogue: 0,0:14:04.72,0:14:05.79,EN,,0,0,0,,because we know\nDialogue: 0,0:14:06.22,0:14:09.16,EN,,0,0,0,,what the operands of fetch of exp are for this piece of code.\nDialogue: 0,0:14:09.16,0:14:10.62,EN,,0,0,0,,It's the, it's the list x.\nDialogue: 0,0:14:13.25,0:14:14.06,EN,,0,0,0,,So in some sense\nDialogue: 0,0:14:16.17,0:14:19.39,EN,,0,0,0,,you don't want unev and exp at all.\nDialogue: 0,0:14:19.67,0:14:21.05,EN,,0,0,0,,See, what they really are in some sense,\nDialogue: 0,0:14:21.08,0:14:25.30,EN,,0,0,0,,those aren't registers of the actual machine that's supposed to run.\nDialogue: 0,0:14:25.30,0:14:26.40,EN,,0,0,0,,Those are registers\nDialogue: 0,0:14:26.60,0:14:29.50,EN,,0,0,0,,that have to do with arranging the thing that can simulate that machine.\nDialogue: 0,0:14:30.72,0:14:33.77,EN,,0,0,0,,So they're always going to hold expressions\nDialogue: 0,0:14:34.00,0:14:36.04,EN,,0,0,0,,which from the compiler's point of view,\nDialogue: 0,0:14:36.06,0:14:36.81,EN,,0,0,0,,are just constants,\nDialogue: 0,0:14:36.95,0:14:38.48,EN,,0,0,0,,so can be put right into the code.\nDialogue: 0,0:14:39.47,0:14:41.34,EN,,0,0,0,,So you can forget about all the operations\nDialogue: 0,0:14:41.36,0:14:42.54,EN,,0,0,0,,worrying about exp and unev\nDialogue: 0,0:14:42.57,0:14:43.77,EN,,0,0,0,,and just use those constants.\nDialogue: 0,0:14:44.02,0:14:48.00,EN,,0,0,0,,Similarly, again, if we go, go back and look here\nDialogue: 0,0:14:48.00,0:14:51.32,EN,,0,0,0,,there are things like assign to continue eval-args.\nDialogue: 0,0:14:53.75,0:14:55.39,EN,,0,0,0,,Now, that has nothing to do with anything.\nDialogue: 0,0:14:55.62,0:14:57.76,EN,,0,0,0,,That was just the evaluator\nDialogue: 0,0:14:58.08,0:15:00.17,EN,,0,0,0,,keeping track of where it should go next\nDialogue: 0,0:15:02.70,0:15:05.96,EN,,0,0,0,,to evaluate the arguments in some, in some application.\nDialogue: 0,0:15:06.82,0:15:08.65,EN,,0,0,0,,But of course, that's irrelevant to the compiler,\nDialogue: 0,0:15:08.65,0:15:13.88,EN,,0,0,0,,because you-- the analysis phase will have already done that.\nDialogue: 0,0:15:15.05,0:15:16.83,EN,,0,0,0,,So this is completely irrelevant.\nDialogue: 0,0:15:17.70,0:15:19.32,EN,,0,0,0,,So a lot of these, these assignments\nDialogue: 0,0:15:19.32,0:15:21.30,EN,,0,0,0,,to continue have not to do\nDialogue: 0,0:15:21.30,0:15:24.62,EN,,0,0,0,,where the running machine is supposed to continue\nDialogue: 0,0:15:24.64,0:15:25.77,EN,,0,0,0,,in keeping track of its state.\nDialogue: 0,0:15:26.07,0:15:28.72,EN,,0,0,0,,It has to, to do with where the evaluator analysis should continue\nDialogue: 0,0:15:28.72,0:15:30.03,EN,,0,0,0,,and those are completely irrelevant.\nDialogue: 0,0:15:30.06,0:15:31.23,EN,,0,0,0,,So we can get rid of them.\nDialogue: 0,0:15:43.90,0:15:45.98,EN,,0,0,0,,Ok, well, if we, if we simply do that,\nDialogue: 0,0:15:46.16,0:15:47.75,EN,,0,0,0,,make those kinds of optimizations\nDialogue: 0,0:15:47.75,0:15:51.64,EN,,0,0,0,,get rid, get rid of worrying about exp and unev\nDialogue: 0,0:15:51.75,0:15:56.22,EN,,0,0,0,,and get rid of these irrelevant register assignments to continue\nDialogue: 0,0:15:57.25,0:15:59.96,EN,,0,0,0,,then we can take this literal code\nDialogue: 0,0:16:01.48,0:16:06.20,EN,,0,0,0,,these sort of 19 instructions that the evaluator would have done\nDialogue: 0,0:16:06.91,0:16:08.12,EN,,0,0,0,,and then replace them.\nDialogue: 0,0:16:08.36,0:16:10.33,EN,,0,0,0,,Let's look at the, at the slide.\nDialogue: 0,0:16:12.27,0:16:15.34,EN,,0,0,0,,Replace them by--we get rid of about half of them.\nDialogue: 0,0:16:18.28,0:16:20.75,EN,,0,0,0,,And again, this is just sort of filtering\nDialogue: 0,0:16:21.07,0:16:24.46,EN,,0,0,0,,what the evaluator would have done by getting rid of the irrelevant stuff.\nDialogue: 0,0:16:25.17,0:16:26.22,EN,,0,0,0,,And you see, for instance\nDialogue: 0,0:16:27.47,0:16:29.66,EN,,0,0,0,,here the--where the evaluator said,\nDialogue: 0,0:16:29.68,0:16:32.43,EN,,0,0,0,,assign val, look up variable value, fetch of exp\nDialogue: 0,0:16:32.46,0:16:34.22,EN,,0,0,0,,here we have put in the constant f.\nDialogue: 0,0:16:35.44,0:16:37.02,EN,,0,0,0,,Here we've put in the constant x.\nDialogue: 0,0:16:40.02,0:16:42.41,EN,,0,0,0,,So there's a, there's a little better compiler.\nDialogue: 0,0:16:43.79,0:16:46.76,EN,,0,0,0,,It's still pretty dumb.\nDialogue: 0,0:16:47.95,0:16:49.58,EN,,0,0,0,,It's still doing a lot of dumb things.\nDialogue: 0,0:16:50.45,0:16:52.52,EN,,0,0,0,,Again, if we go look at the slide again\nDialogue: 0,0:16:52.88,0:16:53.93,EN,,0,0,0,,look at the very beginning here\nDialogue: 0,0:16:56.34,0:16:58.17,EN,,0,0,0,,we see a save the environment\nDialogue: 0,0:16:59.35,0:17:01.72,EN,,0,0,0,,assign something to the val register\nDialogue: 0,0:17:01.80,0:17:03.35,EN,,0,0,0,,and restore the environment.\nDialogue: 0,0:17:03.35,0:17:04.41,EN,,0,0,0,,Where'd that come from?\nDialogue: 0,0:17:04.91,0:17:07.10,EN,,0,0,0,,That came from the evaluator back here saying\nDialogue: 0,0:17:07.15,0:17:10.28,EN,,0,0,0,,oh, I'm in the middle of evaluating an application.\nDialogue: 0,0:17:11.10,0:17:14.68,EN,,0,0,0,,So I'm going to recursively call eval dispatch.\nDialogue: 0,0:17:15.87,0:17:17.98,EN,,0,0,0,,So I'd better save the thing I'm going to need later,\nDialogue: 0,0:17:17.98,0:17:19.08,EN,,0,0,0,,which is the environment.\nDialogue: 0,0:17:19.77,0:17:22.86,EN,,0,0,0,,This was the result of recursively calling eval dispatch.\nDialogue: 0,0:17:23.47,0:17:25.77,EN,,0,0,0,,It was evaluating the symbol f in that case.\nDialogue: 0,0:17:26.50,0:17:28.27,EN,,0,0,0,,Then it came back from eval dispatch,\nDialogue: 0,0:17:28.28,0:17:29.66,EN,,0,0,0,,restored the environment.\nDialogue: 0,0:17:31.25,0:17:32.28,EN,,0,0,0,,But in fact,\nDialogue: 0,0:17:32.59,0:17:35.88,EN,,0,0,0,,the actual thing it ended up doing in the evaluation\nDialogue: 0,0:17:35.92,0:17:37.71,EN,,0,0,0,,is not going to hurt the environment at all.\nDialogue: 0,0:17:38.67,0:17:40.80,EN,,0,0,0,,So there's no reason to be saving the environment\nDialogue: 0,0:17:40.84,0:17:42.22,EN,,0,0,0,,and restoring the environment here.\nDialogue: 0,0:17:45.67,0:17:46.62,EN,,0,0,0,,Similarly\nDialogue: 0,0:17:49.79,0:17:51.39,EN,,0,0,0,,here I'm saving the argument list.\nDialogue: 0,0:17:53.07,0:17:55.80,EN,,0,0,0,,That's a piece of the argument evaluation loop,\nDialogue: 0,0:17:55.82,0:17:56.86,EN,,0,0,0,,saving the argument list\nDialogue: 0,0:17:57.20,0:17:58.03,EN,,0,0,0,,and here you restore it.\nDialogue: 0,0:17:58.08,0:18:00.51,EN,,0,0,0,,But the actual thing that you ended up doing\nDialogue: 0,0:18:00.80,0:18:02.28,EN,,0,0,0,,didn't trash the argument list.\nDialogue: 0,0:18:02.84,0:18:04.17,EN,,0,0,0,,So there was no reason to save it.\nDialogue: 0,0:18:08.65,0:18:12.88,EN,,0,0,0,,So another way to say, another way to say that\nDialogue: 0,0:18:13.77,0:18:14.80,EN,,0,0,0,,is that the,\nDialogue: 0,0:18:16.43,0:18:19.13,EN,,0,0,0,,the evaluator has to be maximally pessimistic\nDialogue: 0,0:18:19.87,0:18:21.07,EN,,0,0,0,,because as far from its point of view\nDialogue: 0,0:18:21.08,0:18:23.06,EN,,0,0,0,,it's just going off to evaluate something.\nDialogue: 0,0:18:23.24,0:18:24.97,EN,,0,0,0,,So it better save what it's going to need later.\nDialogue: 0,0:18:26.12,0:18:27.79,EN,,0,0,0,,But once you've done the analysis,\nDialogue: 0,0:18:27.82,0:18:29.68,EN,,0,0,0,,the compiler is in a position to say\nDialogue: 0,0:18:29.72,0:18:31.47,EN,,0,0,0,,well, what actually did I need to save?\nDialogue: 0,0:18:32.12,0:18:33.31,EN,,0,0,0,,And doesn't need to do any--\nDialogue: 0,0:18:33.42,0:18:37.30,EN,,0,0,0,,it doesn't need to be as careful as the evaluator\nDialogue: 0,0:18:37.30,0:18:38.80,EN,,0,0,0,,because it knows what it actually needs\nDialogue: 0,0:18:39.69,0:18:41.16,EN,,0,0,0,,Well, in any case, if we do that\nDialogue: 0,0:18:42.50,0:18:45.71,EN,,0,0,0,,and eliminate all those redundant saves and restores\nDialogue: 0,0:18:46.40,0:18:49.05,EN,,0,0,0,,then we can get it down to this.\nDialogue: 0,0:18:49.90,0:18:51.53,EN,,0,0,0,,And you see there are actually only three\nDialogue: 0,0:18:51.64,0:18:53.71,EN,,0,0,0,,only three instructions that we actually need\nDialogue: 0,0:18:54.07,0:18:55.72,EN,,0,0,0,,down from the initial 11 or so\nDialogue: 0,0:18:55.97,0:18:58.81,EN,,0,0,0,,or the initial 20 or so in the original one.\nDialogue: 0,0:18:59.87,0:19:00.92,EN,,0,0,0,,And that's just saying,\nDialogue: 0,0:19:01.12,0:19:03.18,EN,,0,0,0,,of those register operations\nDialogue: 0,0:19:03.27,0:19:04.94,EN,,0,0,0,,which ones did we actually need?\nDialogue: 0,0:19:09.42,0:19:11.74,EN,,0,0,0,,Let me just sort of summarize that in another way,\nDialogue: 0,0:19:11.74,0:19:13.48,EN,,0,0,0,,just to show you in a little better picture.\nDialogue: 0,0:19:16.00,0:19:17.52,EN,,0,0,0,,Here's a picture of starting--\nDialogue: 0,0:19:18.77,0:19:20.81,EN,,0,0,0,,This is looking at all the saves and restores.\nDialogue: 0,0:19:23.50,0:19:25.23,EN,,0,0,0,,So here's the expression, f of x\nDialogue: 0,0:19:25.32,0:19:27.87,EN,,0,0,0,,and then this traces through, on the bottom here\nDialogue: 0,0:19:28.75,0:19:31.80,EN,,0,0,0,,the various places in the evaluator\nDialogue: 0,0:19:34.97,0:19:38.04,EN,,0,0,0,,that were passed when the evaluation happened.\nDialogue: 0,0:19:38.04,0:19:40.01,EN,,0,0,0,,And then here, here you see arrows.\nDialogue: 0,0:19:40.22,0:19:42.08,EN,,0,0,0,,Arrow down means register saved.\nDialogue: 0,0:19:42.40,0:19:44.84,EN,,0,0,0,,So the first thing that happened is the environment got saved.\nDialogue: 0,0:19:46.82,0:19:48.68,EN,,0,0,0,,And over here, the environment got restored.\nDialogue: 0,0:19:52.38,0:19:54.54,EN,,0,0,0,,so there are all the pairs of stack operations.\nDialogue: 0,0:19:56.12,0:19:57.56,EN,,0,0,0,,Now, if you go ahead and say\nDialogue: 0,0:19:58.12,0:20:00.78,EN,,0,0,0,,well, let's remember that we don't--that unev\nDialogue: 0,0:20:00.89,0:20:03.02,EN,,0,0,0,,for instance, is a completely useless register.\nDialogue: 0,0:20:07.80,0:20:09.78,EN,,0,0,0,,And if we use the constant structure of the code\nDialogue: 0,0:20:09.78,0:20:12.52,EN,,0,0,0,,well, we don't need, we don't need to save unev.\nDialogue: 0,0:20:16.20,0:20:19.15,EN,,0,0,0,,And then, depending on how we set up the discipline of the--\nDialogue: 0,0:20:19.16,0:20:21.88,EN,,0,0,0,,of calling other things that apply,\nDialogue: 0,0:20:21.88,0:20:23.85,EN,,0,0,0,,we may or may not need to save continue.\nDialogue: 0,0:20:27.40,0:20:28.74,EN,,0,0,0,,That's the first step I did.\nDialogue: 0,0:20:28.74,0:20:30.51,EN,,0,0,0,,And then we can look and see what's actually,\nDialogue: 0,0:20:31.71,0:20:32.70,EN,,0,0,0,,what's actually needed.\nDialogue: 0,0:20:33.07,0:20:35.56,EN,,0,0,0,,See, we don't-- didn't really need to save env\nDialogue: 0,0:20:36.04,0:20:37.82,EN,,0,0,0,,across-evaluating f\nDialogue: 0,0:20:38.08,0:20:39.92,EN,,0,0,0,,because it wouldn't, it wouldn't trash it.\nDialogue: 0,0:20:39.92,0:20:41.31,EN,,0,0,0,,So if we take advantage of that\nDialogue: 0,0:20:44.12,0:20:47.56,EN,,0,0,0,,and see the evaluation of f here\nDialogue: 0,0:20:48.57,0:20:50.44,EN,,0,0,0,,doesn't really need to worry about,\nDialogue: 0,0:20:51.61,0:20:52.60,EN,,0,0,0,,about hurting env.\nDialogue: 0,0:20:52.60,0:20:54.94,EN,,0,0,0,,And similarly, the evaluation of x here\nDialogue: 0,0:20:57.17,0:20:58.89,EN,,0,0,0,,when the evaluator did that it said\nDialogue: 0,0:20:58.91,0:21:01.64,EN,,0,0,0,,Oh, I'd better preserve the function register around that\nDialogue: 0,0:21:02.07,0:21:03.22,EN,,0,0,0,,because I might need it later.\nDialogue: 0,0:21:03.28,0:21:04.89,EN,,0,0,0,,And I better preserve the argument list.\nDialogue: 0,0:21:06.90,0:21:09.05,EN,,0,0,0,,Whereas the compiler is now in a position to know\nDialogue: 0,0:21:09.05,0:21:10.38,EN,,0,0,0,,well, we didn't really need to save--\nDialogue: 0,0:21:10.52,0:21:11.84,EN,,0,0,0,,to do those saves and restores.\nDialogue: 0,0:21:12.70,0:21:16.09,EN,,0,0,0,,So in fact, all of the stack operations done by the evaluator\nDialogue: 0,0:21:16.32,0:21:19.58,EN,,0,0,0,,turned out to be unnecessary or overly pessimistic.\nDialogue: 0,0:21:19.62,0:21:21.45,EN,,0,0,0,,And the compiler is in a position to know that.\nDialogue: 0,0:21:27.35,0:21:28.48,EN,,0,0,0,,Well that's the basic idea.\nDialogue: 0,0:21:29.80,0:21:31.00,EN,,0,0,0,,We take the evaluator\nDialogue: 0,0:21:31.00,0:21:33.24,EN,,0,0,0,,we eliminate the things that you don't need\nDialogue: 0,0:21:33.24,0:21:35.24,EN,,0,0,0,,that in some sense have nothing to do with the compiler at all\nDialogue: 0,0:21:35.24,0:21:36.19,EN,,0,0,0,,just the evaluator\nDialogue: 0,0:21:37.40,0:21:40.40,EN,,0,0,0,,and then you see which stack operations are unnecessary.\nDialogue: 0,0:21:40.82,0:21:43.76,EN,,0,0,0,,That's the basic structure of the compiler that's\nDialogue: 0,0:21:43.85,0:21:45.04,EN,,0,0,0,,that's described in the book.\nDialogue: 0,0:21:45.04,0:21:47.00,EN,,0,0,0,,Let me just show you how a\nDialogue: 0,0:21:47.76,0:21:49.68,EN,,0,0,0,,that examples a little bit too simple.\nDialogue: 0,0:21:51.20,0:21:53.26,EN,,0,0,0,,To see how you, how you actually save a lot\nDialogue: 0,0:21:53.29,0:21:56.06,EN,,0,0,0,,let's look at a little bit more complicated expression.\nDialogue: 0,0:21:58.15,0:22:01.93,EN,,0,0,0,,(F (G X) 1)\nDialogue: 0,0:22:03.87,0:22:05.52,EN,,0,0,0,,And I'm not going to go through all the code.\nDialogue: 0,0:22:06.40,0:22:08.56,EN,,0,0,0,,There's a, there's a fair pile of it.\nDialogue: 0,0:22:09.72,0:22:12.35,EN,,0,0,0,,I think there are, there are something like 16\nDialogue: 0,0:22:12.35,0:22:14.67,EN,,0,0,0,,16 pairs of register saves and restores\nDialogue: 0,0:22:14.70,0:22:16.25,EN,,0,0,0,,as the evaluator walks through that.\nDialogue: 0,0:22:17.00,0:22:18.57,EN,,0,0,0,,Here's a diagram of them.\nDialogue: 0,0:22:20.57,0:22:21.95,EN,,0,0,0,,Let's see. You see what's going on.\nDialogue: 0,0:22:22.97,0:22:23.90,EN,,0,0,0,,You start out by--\nDialogue: 0,0:22:24.25,0:22:26.62,EN,,0,0,0,,the evaluator says, oh, I'm about to do an application.\nDialogue: 0,0:22:26.90,0:22:29.13,EN,,0,0,0,,I'll preserve the environment. I'll restore it here.\nDialogue: 0,0:22:30.65,0:22:34.44,EN,,0,0,0,,Then I'm about to do the first operand.\nDialogue: 0,0:22:36.81,0:22:39.28,EN,,0,0,0,,Here it recursively goes to the evaluator.\nDialogue: 0,0:22:39.28,0:22:40.89,EN,,0,0,0,,The evaluator says, oh, this is an application,\nDialogue: 0,0:22:40.91,0:22:42.10,EN,,0,0,0,,I'll save the environment\nDialogue: 0,0:22:42.10,0:22:44.97,EN,,0,0,0,,do the operator of that combination, restore it here.\nDialogue: 0,0:22:45.80,0:22:48.92,EN,,0,0,0,,This save--this restore matches that save.\nDialogue: 0,0:22:49.77,0:22:50.78,EN,,0,0,0,,And so on.\nDialogue: 0,0:22:51.65,0:22:52.51,EN,,0,0,0,,There's unev here,\nDialogue: 0,0:22:52.52,0:22:54.62,EN,,0,0,0,,which turns out to be completely unnecessary\nDialogue: 0,0:22:54.97,0:22:56.60,EN,,0,0,0,,continues getting bumped around here.\nDialogue: 0,0:22:57.42,0:23:00.41,EN,,0,0,0,,The function register is getting, getting saved\nDialogue: 0,0:23:00.78,0:23:04.36,EN,,0,0,0,,across the first operands, across the operands.\nDialogue: 0,0:23:05.10,0:23:06.52,EN,,0,0,0,,All sorts of things are going on.\nDialogue: 0,0:23:06.78,0:23:09.39,EN,,0,0,0,,But if you say, well, what of those really were the business of\nDialogue: 0,0:23:09.87,0:23:11.66,EN,,0,0,0,,the compiler as opposed to the evaluator\nDialogue: 0,0:23:12.27,0:23:13.55,EN,,0,0,0,,you get rid of a whole bunch.\nDialogue: 0,0:23:14.30,0:23:16.64,EN,,0,0,0,,And then on top of that, if you say things like\nDialogue: 0,0:23:19.40,0:23:22.54,EN,,0,0,0,,the evaluation of F doesn't hurt the environment register,\nDialogue: 0,0:23:23.82,0:23:26.51,EN,,0,0,0,,or simply looking up the symbol X,\nDialogue: 0,0:23:29.28,0:23:32.09,EN,,0,0,0,,you don't have to protect the function register against that.\nDialogue: 0,0:23:34.30,0:23:37.60,EN,,0,0,0,,So you come down to just a couple of, a couple of pairs here.\nDialogue: 0,0:23:40.25,0:23:42.27,EN,,0,0,0,,And still, you can do a little better.\nDialogue: 0,0:23:42.27,0:23:44.33,EN,,0,0,0,,Look what's going on here with the environment register.\nDialogue: 0,0:23:45.21,0:23:47.39,EN,,0,0,0,,The environment register comes along and says, oh,\nDialogue: 0,0:23:51.00,0:23:52.25,EN,,0,0,0,,here's a combination.\nDialogue: 0,0:23:54.33,0:23:55.69,EN,,0,0,0,,This evaluator, by the way,\nDialogue: 0,0:23:55.78,0:23:57.27,EN,,0,0,0,,doesn't know anything about G.\nDialogue: 0,0:23:58.57,0:24:00.73,EN,,0,0,0,,So here it says, so it says,\nDialogue: 0,0:24:01.29,0:24:03.45,EN,,0,0,0,,I'd better save the environment register,\nDialogue: 0,0:24:03.96,0:24:05.42,EN,,0,0,0,,because evaluating G might be\nDialogue: 0,0:24:05.42,0:24:07.42,EN,,0,0,0,,some arbitrary piece of code that would trash it\nDialogue: 0,0:24:07.55,0:24:09.45,EN,,0,0,0,,and I'm going to need it later,\nDialogue: 0,0:24:10.17,0:24:11.40,EN,,0,0,0,,after this argument,\nDialogue: 0,0:24:12.22,0:24:13.37,EN,,0,0,0,,for doing the second argument.\nDialogue: 0,0:24:15.60,0:24:17.24,EN,,0,0,0,,So that's why this one didn't go away,\nDialogue: 0,0:24:19.07,0:24:22.54,EN,,0,0,0,,because the compiler made no assumptions about what G would do.\nDialogue: 0,0:24:22.54,0:24:23.60,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:24:24.61,0:24:26.52,EN,,0,0,0,,if you look at what the second argument is,\nDialogue: 0,0:24:26.64,0:24:27.70,EN,,0,0,0,,that's just looking up one.\nDialogue: 0,0:24:27.70,0:24:29.60,EN,,0,0,0,,That doesn't need this environment register.\nDialogue: 0,0:24:30.77,0:24:32.04,EN,,0,0,0,,So there's no reason to save it.\nDialogue: 0,0:24:32.06,0:24:33.77,EN,,0,0,0,,So in fact, you can get rid of that one, too.\nDialogue: 0,0:24:34.85,0:24:37.81,EN,,0,0,0,,And from this whole pile of, of register operations,\nDialogue: 0,0:24:37.98,0:24:40.08,EN,,0,0,0,,if you simply do a little bit of reasoning like that,\nDialogue: 0,0:24:40.55,0:24:43.05,EN,,0,0,0,,you get down to, I think, just two pairs of saves and restores.\nDialogue: 0,0:24:45.10,0:24:46.97,EN,,0,0,0,,And those, in fact, could go away further if you,\nDialogue: 0,0:24:47.52,0:24:49.08,EN,,0,0,0,,if you knew something about G.\nDialogue: 0,0:24:56.27,0:24:57.85,EN,,0,0,0,,So again, the general idea\nDialogue: 0,0:24:57.95,0:24:59.98,EN,,0,0,0,,is that the reason the compiler can be better\nDialogue: 0,0:24:59.98,0:25:02.56,EN,,0,0,0,,is that the interpreter doesn't know what it's about to encounter.\nDialogue: 0,0:25:03.25,0:25:05.04,EN,,0,0,0,,It has to be maximally pessimistic\nDialogue: 0,0:25:05.05,0:25:06.70,EN,,0,0,0,,to protect itself.\nDialogue: 0,0:25:07.90,0:25:08.76,EN,,0,0,0,,The compiler\nDialogue: 0,0:25:09.48,0:25:12.38,EN,,0,0,0,,only has to deal with what actually had to be saved.\nDialogue: 0,0:25:13.37,0:25:15.20,EN,,0,0,0,,And there are two reasons that something\nDialogue: 0,0:25:15.24,0:25:17.37,EN,,0,0,0,,might not have to be saved.\nDialogue: 0,0:25:17.82,0:25:18.70,EN,,0,0,0,,One is that\nDialogue: 0,0:25:18.70,0:25:19.82,EN,,0,0,0,,what you're protecting it against,\nDialogue: 0,0:25:19.95,0:25:21.44,EN,,0,0,0,,in fact, didn't trash the register,\nDialogue: 0,0:25:22.08,0:25:23.58,EN,,0,0,0,,like it was just a variable look-up.\nDialogue: 0,0:25:24.12,0:25:25.20,EN,,0,0,0,,And the other one is,\nDialogue: 0,0:25:25.32,0:25:27.10,EN,,0,0,0,,that the thing that you were saving it for\nDialogue: 0,0:25:28.28,0:25:29.92,EN,,0,0,0,,might turn out not to actually need it.\nDialogue: 0,0:25:30.81,0:25:34.27,EN,,0,0,0,,So those are the two basic pieces of knowledge\nDialogue: 0,0:25:34.30,0:25:35.88,EN,,0,0,0,,that the compiler can take advantage of\nDialogue: 0,0:25:36.27,0:25:37.76,EN,,0,0,0,,in making the code more efficient.\nDialogue: 0,0:25:44.27,0:25:45.32,EN,,0,0,0,,Let's break for questions.\nDialogue: 0,0:25:51.20,0:25:53.10,EN,,0,0,0,,AUDIENCE: You kept saying that the uneval register,\nDialogue: 0,0:25:53.13,0:25:56.40,EN,,0,0,0,,unev register didn't need to be used at all.\nDialogue: 0,0:25:56.41,0:25:58.68,EN,,0,0,0,,Does that mean that you could just map a six-register machine?\nDialogue: 0,0:25:58.70,0:26:00.08,EN,,0,0,0,,Or is that, in this particular example,\nDialogue: 0,0:26:00.11,0:26:01.18,EN,,0,0,0,,it didn't need to be used?\nDialogue: 0,0:26:01.72,0:26:02.81,EN,,0,0,0,,PROFESSOR: For the compiler,\nDialogue: 0,0:26:04.31,0:26:07.42,EN,,0,0,0,,you could generate code for the six-register, five, right?\nDialogue: 0,0:26:07.56,0:26:09.02,EN,,0,0,0,,Because that exp goes away also.\nDialogue: 0,0:26:09.40,0:26:14.57,EN,,0,0,0,,Assuming--yeah, you can get rid of both exp and unev\nDialogue: 0,0:26:14.57,0:26:16.87,EN,,0,0,0,,because, see, those are data structures of the evaluator.\nDialogue: 0,0:26:17.36,0:26:19.36,EN,,0,0,0,,Those are all things that would be constants\nDialogue: 0,0:26:19.39,0:26:20.87,EN,,0,0,0,,from the point of view of the compiler.\nDialogue: 0,0:26:21.65,0:26:22.44,EN,,0,0,0,,The only thing is\nDialogue: 0,0:26:22.48,0:26:24.59,EN,,0,0,0,,this particular compiler is set up\nDialogue: 0,0:26:24.79,0:26:27.92,EN,,0,0,0,,so that interpreted code and compiled code can coexist.\nDialogue: 0,0:26:29.32,0:26:30.72,EN,,0,0,0,,So the way to think about it is,\nDialogue: 0,0:26:30.97,0:26:32.29,EN,,0,0,0,,is maybe you build a chip\nDialogue: 0,0:26:34.30,0:26:35.50,EN,,0,0,0,,which is the evaluator,\nDialogue: 0,0:26:35.88,0:26:37.28,EN,,0,0,0,,and what the compiler might do\nDialogue: 0,0:26:37.31,0:26:39.02,EN,,0,0,0,,is generate code for that chip.\nDialogue: 0,0:26:40.40,0:26:41.90,EN,,0,0,0,,It just wouldn't use two of the registers.\nDialogue: 0,0:26:51.52,0:26:52.47,EN,,0,0,0,,All right, let's take a break.\nDialogue: 0,0:26:53.55,0:27:07.18,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:27:07.37,0:27:11.42,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:27:14.57,0:27:18.12,EN,,0,0,0,,By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:27:18.17,0:27:22.08,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:27:22.22,0:27:26.48,EN,,0,0,0,,Compilation\nDialogue: 0,0:27:29.21,0:27:32.43,EN,,0,0,0,,We just looked at what the compiler is supposed to do.\nDialogue: 0,0:27:32.78,0:27:36.04,EN,,0,0,0,,Now let's very briefly look at how,\nDialogue: 0,0:27:36.15,0:27:37.47,EN,,0,0,0,,how this gets accomplished.\nDialogue: 0,0:27:38.26,0:27:39.58,EN,,0,0,0,,And I'm going to give no details.\nDialogue: 0,0:27:39.60,0:27:42.17,EN,,0,0,0,,There's, there's a giant pile of code in the book\nDialogue: 0,0:27:42.22,0:27:43.42,EN,,0,0,0,,that gives all the details.\nDialogue: 0,0:27:43.45,0:27:45.31,EN,,0,0,0,,But what I want to do is just show you the,\nDialogue: 0,0:27:45.96,0:27:47.26,EN,,0,0,0,,the essential idea here.\nDialogue: 0,0:27:49.49,0:27:51.36,EN,,0,0,0,,Worry about the details some other time.\nDialogue: 0,0:27:51.51,0:27:55.30,EN,,0,0,0,,Let's imagine that we're compiling an expression\nDialogue: 0,0:27:55.30,0:27:57.01,EN,,0,0,0,,that looks like there's some operator\nDialogue: 0,0:27:57.48,0:27:58.56,EN,,0,0,0,,and there are two arguments.\nDialogue: 0,0:28:03.56,0:28:04.24,EN,,0,0,0,,Now, the--\nDialogue: 0,0:28:06.27,0:28:08.14,EN,,0,0,0,,what's the code that the compiler should generate?\nDialogue: 0,0:28:08.85,0:28:09.78,EN,,0,0,0,,Well, first of all,\nDialogue: 0,0:28:09.83,0:28:11.20,EN,,0,0,0,,it should recursively go off\nDialogue: 0,0:28:11.90,0:28:13.28,EN,,0,0,0,,and compile the operator.\nDialogue: 0,0:28:14.37,0:28:19.02,EN,,0,0,0,,So it says, I'll compile the operator.\nDialogue: 0,0:28:21.16,0:28:24.54,EN,,0,0,0,,And where I'm going to need that\nDialogue: 0,0:28:24.84,0:28:27.95,EN,,0,0,0,,is to be in the function register, eventually.\nDialogue: 0,0:28:28.42,0:28:29.60,EN,,0,0,0,,So I'll compile some instructions\nDialogue: 0,0:28:29.64,0:28:31.56,EN,,0,0,0,,that will compile the operator\nDialogue: 0,0:28:31.69,0:28:38.62,EN,,0,0,0,,and end up with the result in the function register.\nDialogue: 0,0:28:45.51,0:28:46.94,EN,,0,0,0,,The next thing it's going to do,\nDialogue: 0,0:28:47.71,0:28:49.68,EN,,0,0,0,,another piece is to say,\nDialogue: 0,0:28:49.68,0:28:55.17,EN,,0,0,0,,I have to compile the first argument.\nDialogue: 0,0:28:55.17,0:28:56.80,EN,,0,0,0,,So it calls itself recursively.\nDialogue: 0,0:28:58.04,0:29:03.36,EN,,0,0,0,,And let's say the result will go into val.\nDialogue: 0,0:29:09.07,0:29:10.75,EN,,0,0,0,,And then what it's going to need to do is\nDialogue: 0,0:29:10.75,0:29:12.26,EN,,0,0,0,,start setting up the argument list.\nDialogue: 0,0:29:12.95,0:29:25.50,EN,,0,0,0,,So it'll say, assign to argl cons of fetch--\nDialogue: 0,0:29:25.55,0:29:27.10,EN,,0,0,0,,so it generates this literal instruction--\nDialogue: 0,0:29:27.50,0:29:32.51,EN,,0,0,0,,fetch of val onto empty list.\nDialogue: 0,0:29:35.00,0:29:36.05,EN,,0,0,0,,However,\nDialogue: 0,0:29:37.99,0:29:40.61,EN,,0,0,0,,it might have to work--  when it gets here,\nDialogue: 0,0:29:41.32,0:29:42.82,EN,,0,0,0,,it's going to need the environment.\nDialogue: 0,0:29:43.95,0:29:45.29,EN,,0,0,0,,It's going to need whatever environment was here\nDialogue: 0,0:29:45.32,0:29:48.21,EN,,0,0,0,,in order to do this evaluation of the first argument.\nDialogue: 0,0:29:49.04,0:29:51.18,EN,,0,0,0,,So it has to ensure that\nDialogue: 0,0:29:51.92,0:29:53.76,EN,,0,0,0,,the compilation of this operand,\nDialogue: 0,0:29:55.32,0:29:57.85,EN,,0,0,0,,or it has to protect the function register\nDialogue: 0,0:29:58.01,0:30:00.98,EN,,0,0,0,,against whatever might happen in the compilation of this operand.\nDialogue: 0,0:30:01.30,0:30:03.08,EN,,0,0,0,,So it puts a note here and says, oh,\nDialogue: 0,0:30:03.37,0:30:12.89,EN,,0,0,0,,this piece should be done preserving the environment register.\nDialogue: 0,0:30:17.39,0:30:18.44,EN,,0,0,0,,Similarly, here,\nDialogue: 0,0:30:21.02,0:30:23.30,EN,,0,0,0,,after it gets done compiling the first operand,\nDialogue: 0,0:30:23.57,0:30:24.67,EN,,0,0,0,,it's going to say, I'd better--\nDialogue: 0,0:30:24.71,0:30:27.92,EN,,0,0,0,,I'm going to need to know the environment for the second operand.\nDialogue: 0,0:30:27.92,0:30:29.46,EN,,0,0,0,,So it puts a little note here, saying,\nDialogue: 0,0:30:29.71,0:30:35.96,EN,,0,0,0,,yeah, this is also done preserving env.\nDialogue: 0,0:30:39.42,0:30:41.02,EN,,0,0,0,,Now it goes on and says, well,\nDialogue: 0,0:30:41.12,0:30:42.83,EN,,0,0,0,,the next chunk of code\nDialogue: 0,0:30:43.31,0:30:49.74,EN,,0,0,0,,is the one that's going to compile the second argument.\nDialogue: 0,0:30:50.82,0:30:52.64,EN,,0,0,0,,And let's say\nDialogue: 0,0:30:52.99,0:30:59.28,EN,,0,0,0,,And let's say it'll compile it with a targeted to val, as they say.\nDialogue: 0,0:31:03.86,0:31:06.70,EN,,0,0,0,,And then it'll generate the literal instruction,\nDialogue: 0,0:31:07.84,0:31:09.25,EN,,0,0,0,,building up the argument list.\nDialogue: 0,0:31:09.55,0:31:15.28,EN,,0,0,0,,So it'll say, assign to argl\nDialogue: 0,0:31:20.22,0:31:28.94,EN,,0,0,0,,cons of the new value it just got onto the old argument list.\nDialogue: 0,0:31:33.97,0:31:34.64,EN,,0,0,0,,However,\nDialogue: 0,0:31:34.81,0:31:36.58,EN,,0,0,0,,in order to have the old argument list,\nDialogue: 0,0:31:37.15,0:31:40.99,EN,,0,0,0,,it better have arranged that the argument list didn't get trashed\nDialogue: 0,0:31:41.30,0:31:42.69,EN,,0,0,0,,by whatever happened in here.\nDialogue: 0,0:31:43.50,0:31:45.17,EN,,0,0,0,,So it puts a little note here and says,\nDialogue: 0,0:31:45.34,0:31:51.64,EN,,0,0,0,,oh, this has to be done preserving argl.\nDialogue: 0,0:31:54.16,0:31:56.03,EN,,0,0,0,,Now it's got the argument list set up.\nDialogue: 0,0:31:58.01,0:32:02.86,EN,,0,0,0,,And it's all ready to go to apply dispatch.\nDialogue: 0,0:32:07.02,0:32:10.80,EN,,0,0,0,,It generates this literal instruction.\nDialogue: 0,0:32:15.19,0:32:17.37,EN,,0,0,0,,Because now it's got the arguments in argl\nDialogue: 0,0:32:18.15,0:32:20.59,EN,,0,0,0,,and the operator in fun,\nDialogue: 0,0:32:20.59,0:32:22.89,EN,,0,0,0,,but wait, it's only got the operator in fun\nDialogue: 0,0:32:23.27,0:32:26.64,EN,,0,0,0,,if it had ensured that this block of code\nDialogue: 0,0:32:27.09,0:32:29.27,EN,,0,0,0,,didn't trash what was in the function register.\nDialogue: 0,0:32:29.67,0:32:31.24,EN,,0,0,0,,So it puts a little note here and says,\nDialogue: 0,0:32:31.55,0:32:32.73,EN,,0,0,0,,oh, yes, all this stuff here\nDialogue: 0,0:32:34.88,0:32:40.73,EN,,0,0,0,,had better be done preserving the function register.\nDialogue: 0,0:32:43.71,0:32:46.15,EN,,0,0,0,,So that's the little--so when it starts ticking--\nDialogue: 0,0:32:46.15,0:32:47.10,EN,,0,0,0,,so basically, what the\nDialogue: 0,0:32:48.20,0:32:50.24,EN,,0,0,0,,what the compiler does is\nDialogue: 0,0:32:50.54,0:32:52.46,EN,,0,0,0,,append a whole bunch of code sequences.\nDialogue: 0,0:32:53.50,0:32:58.83,EN,,0,0,0,,See, what it's got in it is little primitive pieces of things\nDialogue: 0,0:32:58.86,0:33:00.12,EN,,0,0,0,,like how to look up a symbol,\nDialogue: 0,0:33:01.44,0:33:02.60,EN,,0,0,0,,how to do a conditional.\nDialogue: 0,0:33:02.64,0:33:05.44,EN,,0,0,0,,Those are all little pieces of things.\nDialogue: 0,0:33:05.44,0:33:07.99,EN,,0,0,0,,And then it appends them together in this sort of discipline.\nDialogue: 0,0:33:08.78,0:33:10.79,EN,,0,0,0,,So the basic means of combining things\nDialogue: 0,0:33:10.86,0:33:13.18,EN,,0,0,0,,is to append two code sequences.\nDialogue: 0,0:33:21.55,0:33:22.86,EN,,0,0,0,,That's what's going on here.\nDialogue: 0,0:33:25.58,0:33:27.24,EN,,0,0,0,,And it's a little bit tricky.\nDialogue: 0,0:33:27.56,0:33:30.37,EN,,0,0,0,,The idea is that it appends two code sequences,\nDialogue: 0,0:33:31.60,0:33:33.76,EN,,0,0,0,,taking care to preserve a register.\nDialogue: 0,0:33:35.63,0:33:37.93,EN,,0,0,0,,So the actual append operation looks like this.\nDialogue: 0,0:33:39.15,0:33:40.65,EN,,0,0,0,,What it wants to do is say, if--\nDialogue: 0,0:33:41.20,0:33:44.11,EN,,0,0,0,,here's what it means to append two code sequences.\nDialogue: 0,0:33:44.53,0:33:53.63,EN,,0,0,0,,So if sequence one needs register--\nDialogue: 0,0:33:53.66,0:33:54.72,EN,,0,0,0,,I should change this.\nDialogue: 0,0:33:54.72,0:33:56.87,EN,,0,0,0,,Append sequence one to sequence two,\nDialogue: 0,0:33:57.42,0:34:03.96,EN,,0,0,0,,preserving some register.\nDialogue: 0,0:34:08.52,0:34:09.91,EN,,0,0,0,,Let me say, and.\nDialogue: 0,0:34:11.36,0:34:13.03,EN,,0,0,0,,So it's clear that sequence one comes first.\nDialogue: 0,0:34:13.88,0:34:19.87,EN,,0,0,0,,So if sequence two needs the register\nDialogue: 0,0:34:21.12,0:34:27.85,EN,,0,0,0,,and sequence one modifies the register,\nDialogue: 0,0:34:33.68,0:34:36.30,EN,,0,0,0,,then the instructions that the compiler spits out,\nDialogue: 0,0:34:36.97,0:34:41.34,EN,,0,0,0,,are save the register.\nDialogue: 0,0:34:43.02,0:34:44.19,EN,,0,0,0,,Here's the code.\nDialogue: 0,0:34:44.35,0:34:45.35,EN,,0,0,0,,You generate this code.\nDialogue: 0,0:34:45.35,0:34:46.28,EN,,0,0,0,,Save the register,\nDialogue: 0,0:34:46.72,0:34:52.97,EN,,0,0,0,,and then you put out the recursively compiled stuff for sequence one.\nDialogue: 0,0:34:53.30,0:34:54.84,EN,,0,0,0,,And then you restore the register.\nDialogue: 0,0:35:00.52,0:35:03.92,EN,,0,0,0,,And then you put out the recursively compiled stuff\nDialogue: 0,0:35:04.46,0:35:05.47,EN,,0,0,0,,for sequence two.\nDialogue: 0,0:35:07.07,0:35:09.62,EN,,0,0,0,,That's in the case where you need to do it.\nDialogue: 0,0:35:09.62,0:35:11.82,EN,,0,0,0,,Sequence two actually needs the register,\nDialogue: 0,0:35:11.82,0:35:13.74,EN,,0,0,0,,and sequence one actually clobbers it.\nDialogue: 0,0:35:15.12,0:35:17.07,EN,,0,0,0,,So that's sort of if. Otherwise,\nDialogue: 0,0:35:20.50,0:35:26.57,EN,,0,0,0,,all you spit out is sequence one followed by sequence two.\nDialogue: 0,0:35:28.17,0:35:30.30,EN,,0,0,0,,So that's the basic operation\nDialogue: 0,0:35:30.59,0:35:33.52,EN,,0,0,0,,for sticking together these bits of code fragments,\nDialogue: 0,0:35:33.93,0:35:35.93,EN,,0,0,0,,these bits of instructions into a sequence.\nDialogue: 0,0:35:36.89,0:35:38.87,EN,,0,0,0,,And you see, from this point of view,\nDialogue: 0,0:35:40.94,0:35:45.96,EN,,0,0,0,,the difference between the interpreter and the compiler, in some sense,\nDialogue: 0,0:35:46.82,0:35:49.34,EN,,0,0,0,,is that where the compiler has these preserving notes,\nDialogue: 0,0:35:50.14,0:35:52.22,EN,,0,0,0,,and says, maybe I'll actually generate the\nDialogue: 0,0:35:52.49,0:35:54.22,EN,,0,0,0,,saves and restores and maybe I won't,\nDialogue: 0,0:35:55.19,0:35:57.24,EN,,0,0,0,,the interpreter being maximally pessimistic\nDialogue: 0,0:35:57.28,0:35:58.90,EN,,0,0,0,,always has a save and restore here.\nDialogue: 0,0:36:00.76,0:36:01.93,EN,,0,0,0,,That's the essential difference.\nDialogue: 0,0:36:04.16,0:36:06.05,EN,,0,0,0,,Well, in order to do this, of course,\nDialogue: 0,0:36:06.65,0:36:09.40,EN,,0,0,0,,the compiler needs some theory of\nDialogue: 0,0:36:09.56,0:36:11.96,EN,,0,0,0,,what code sequences need and modifier registers.\nDialogue: 0,0:36:14.26,0:36:17.28,EN,,0,0,0,,So the tiny little fragments that you put in, like\nDialogue: 0,0:36:17.48,0:36:21.00,EN,,0,0,0,,the basic primitive code fragments,\nDialogue: 0,0:36:22.74,0:36:24.59,EN,,0,0,0,,say, what are the operations that you do\nDialogue: 0,0:36:24.92,0:36:26.04,EN,,0,0,0,,when you look up a variable?\nDialogue: 0,0:36:26.89,0:36:29.02,EN,,0,0,0,,What are the sequence of things that you do\nDialogue: 0,0:36:29.05,0:36:30.68,EN,,0,0,0,,when you compile a constant\nDialogue: 0,0:36:30.97,0:36:32.10,EN,,0,0,0,,or apply a function?\nDialogue: 0,0:36:32.97,0:36:34.48,EN,,0,0,0,,Those have little notations in there\nDialogue: 0,0:36:34.67,0:36:36.46,EN,,0,0,0,,about what they need and what they modify.\nDialogue: 0,0:36:38.78,0:36:41.50,EN,,0,0,0,,So the bottom-level data structures--\nDialogue: 0,0:36:42.66,0:36:44.33,EN,,0,0,0,,Well, I'll say this.\nDialogue: 0,0:36:44.39,0:36:47.91,EN,,0,0,0,,A code sequence to the compiler looks like this.\nDialogue: 0,0:36:48.07,0:36:51.42,EN,,0,0,0,,It has the actual sequence of instructions.\nDialogue: 0,0:36:55.67,0:36:56.81,EN,,0,0,0,,And then, along with it,\nDialogue: 0,0:36:57.18,0:37:02.60,EN,,0,0,0,,there's the set of registers modified.\nDialogue: 0,0:37:10.54,0:37:12.60,EN,,0,0,0,,And then there's the set of registers needed.\nDialogue: 0,0:37:20.00,0:37:22.46,EN,,0,0,0,,So that's the information the compiler has\nDialogue: 0,0:37:23.00,0:37:26.41,EN,,0,0,0,,that it draws on in order to be able to do this operation.\nDialogue: 0,0:37:29.30,0:37:31.08,EN,,0,0,0,,And where do those come from? Well.\nDialogue: 0,0:37:32.91,0:37:34.49,EN,,0,0,0,,Well, those come from, you might expect,\nDialogue: 0,0:37:34.51,0:37:35.53,EN,,0,0,0,,for the very primitive ones,\nDialogue: 0,0:37:35.55,0:37:36.84,EN,,0,0,0,,we're going to put them in by hand.\nDialogue: 0,0:37:37.24,0:37:38.86,EN,,0,0,0,,And then, when we combine two sequences,\nDialogue: 0,0:37:38.89,0:37:41.02,EN,,0,0,0,,we'll figure out what these things should be.\nDialogue: 0,0:37:42.16,0:37:44.12,EN,,0,0,0,,So for example, a very primitive one, let's see.\nDialogue: 0,0:37:48.43,0:37:51.40,EN,,0,0,0,,How about doing a register assignment.\nDialogue: 0,0:37:51.77,0:37:53.50,EN,,0,0,0,,So a primitive sequence might say,\nDialogue: 0,0:37:53.52,0:37:56.22,EN,,0,0,0,,oh, it's code fragment.\nDialogue: 0,0:37:56.22,0:38:03.17,EN,,0,0,0,,Its code instruction is assigned to R1, fetch of R2.\nDialogue: 0,0:38:03.17,0:38:04.27,EN,,0,0,0,,So this is an example.\nDialogue: 0,0:38:05.42,0:38:08.52,EN,,0,0,0,,That might be an example of a sequence of instructions.\nDialogue: 0,0:38:08.77,0:38:10.53,EN,,0,0,0,,And along with that, it'll say, Oh\nDialogue: 0,0:38:10.64,0:38:15.76,EN,,0,0,0,,oh, what I need to remember is that that modifies R1\nDialogue: 0,0:38:18.60,0:38:21.16,EN,,0,0,0,,and then it needs R2.\nDialogue: 0,0:38:24.69,0:38:26.99,EN,,0,0,0,,So when you're first building this compiler,\nDialogue: 0,0:38:27.10,0:38:29.35,EN,,0,0,0,,you put in little fragments of stuff like that.\nDialogue: 0,0:38:30.95,0:38:33.20,EN,,0,0,0,,And now, when it combines two sequences,\nDialogue: 0,0:38:36.70,0:38:38.04,EN,,0,0,0,,if I'm going to combine,\nDialogue: 0,0:38:38.92,0:38:41.58,EN,,0,0,0,,let's say, sequence one,\nDialogue: 0,0:38:42.88,0:38:47.16,EN,,0,0,0,,that modifies a bunch of registers M1,\nDialogue: 0,0:38:48.45,0:38:51.42,EN,,0,0,0,,and needs a bunch of registers N1.\nDialogue: 0,0:38:54.85,0:38:59.48,EN,,0,0,0,,And I'm going to combine that with sequence two.\nDialogue: 0,0:39:00.81,0:39:05.96,EN,,0,0,0,,That modifies a bunch of registers M2,\nDialogue: 0,0:39:07.11,0:39:10.00,EN,,0,0,0,,and needs a bunch of registers N2.\nDialogue: 0,0:39:12.44,0:39:14.83,EN,,0,0,0,,Then, well, we can reason it out.\nDialogue: 0,0:39:15.11,0:39:16.32,EN,,0,0,0,,The new code fragment,\nDialogue: 0,0:39:17.18,0:39:21.82,EN,,0,0,0,,sequence one, and-- followed by sequence two,\nDialogue: 0,0:39:24.09,0:39:26.45,EN,,0,0,0,,well, what's it going to modify?\nDialogue: 0,0:39:27.80,0:39:29.18,EN,,0,0,0,,The things that it will modify are the things\nDialogue: 0,0:39:29.20,0:39:32.68,EN,,0,0,0,,that are modified either by sequence one or sequence two.\nDialogue: 0,0:39:34.00,0:39:36.35,EN,,0,0,0,,So the union of these two\nDialogue: 0,0:39:37.68,0:39:39.64,EN,,0,0,0,,sets are what the new thing modifies.\nDialogue: 0,0:39:40.46,0:39:41.79,EN,,0,0,0,,And then you say, well, what is this--\nDialogue: 0,0:39:44.66,0:39:46.41,EN,,0,0,0,,what registers is it going to need?\nDialogue: 0,0:39:47.95,0:39:49.77,EN,,0,0,0,,It's going to need the things that are,\nDialogue: 0,0:39:49.93,0:39:51.85,EN,,0,0,0,,first of all, needed by sequence one.\nDialogue: 0,0:39:52.91,0:39:54.49,EN,,0,0,0,,So what it needs is sequence one.\nDialogue: 0,0:39:55.19,0:39:58.28,EN,,0,0,0,,And then, well, not quite all of the ones\nDialogue: 0,0:39:58.32,0:39:59.61,EN,,0,0,0,,that are needed by sequence two.\nDialogue: 0,0:39:59.75,0:40:03.49,EN,,0,0,0,,What it needs are the ones that are needed by sequence two\nDialogue: 0,0:40:03.88,0:40:06.88,EN,,0,0,0,,that have not been set up by sequence one.\nDialogue: 0,0:40:08.14,0:40:09.72,EN,,0,0,0,,So it's sort of the union of\nDialogue: 0,0:40:11.66,0:40:13.40,EN,,0,0,0,,the things that sequence two needs\nDialogue: 0,0:40:14.51,0:40:18.52,EN,,0,0,0,,minus the ones that sequence one modifies.\nDialogue: 0,0:40:19.31,0:40:20.88,EN,,0,0,0,,Because it worries about setting them up.\nDialogue: 0,0:40:23.95,0:40:26.26,EN,,0,0,0,,So there's the basic structure of the compiler.\nDialogue: 0,0:40:26.70,0:40:29.82,EN,,0,0,0,,The way you do register optimizations is you\nDialogue: 0,0:40:30.22,0:40:32.70,EN,,0,0,0,,you have some strategies for what needs to be preserved.\nDialogue: 0,0:40:34.10,0:40:35.63,EN,,0,0,0,,That depends on a data structure.\nDialogue: 0,0:40:35.72,0:40:38.51,EN,,0,0,0,,Well, it depends on the operation of what it means to put things together.\nDialogue: 0,0:40:39.03,0:40:41.63,EN,,0,0,0,,Preserving something, that depends on knowing\nDialogue: 0,0:40:41.93,0:40:47.28,EN,,0,0,0,,what registers are needed and modified by these code fragments.\nDialogue: 0,0:40:48.75,0:40:51.26,EN,,0,0,0,,That depends on having little data structures,\nDialogue: 0,0:40:51.42,0:40:55.43,EN,,0,0,0,,which say, a code sequence is the actual instructions,\nDialogue: 0,0:40:55.60,0:40:57.33,EN,,0,0,0,,what they modify and what they need.\nDialogue: 0,0:40:57.33,0:40:59.77,EN,,0,0,0,,That comes from, at the primitive level, building it in.\nDialogue: 0,0:40:59.79,0:41:01.36,EN,,0,0,0,,At the primitive level,\nDialogue: 0,0:41:01.37,0:41:02.52,EN,,0,0,0,,it's going to be completely obvious\nDialogue: 0,0:41:03.00,0:41:04.44,EN,,0,0,0,,what something needs and modifies.\nDialogue: 0,0:41:04.82,0:41:05.35,EN,,0,0,0,,Plus,\nDialogue: 0,0:41:05.44,0:41:08.60,EN,,0,0,0,,this particular way that says, when I build up bigger ones,\nDialogue: 0,0:41:09.28,0:41:11.89,EN,,0,0,0,,here's how I generate the new set of registers modified\nDialogue: 0,0:41:11.93,0:41:13.37,EN,,0,0,0,,and the new set of registers needed.\nDialogue: 0,0:41:15.27,0:41:17.77,EN,,0,0,0,,And that's the whole-- well, I shouldn't say that's the whole thing.\nDialogue: 0,0:41:17.77,0:41:19.34,EN,,0,0,0,,That's the whole thing except for about\nDialogue: 0,0:41:19.74,0:41:21.87,EN,,0,0,0,,about 30 pages of details in the book.\nDialogue: 0,0:41:22.31,0:41:27.69,EN,,0,0,0,,But it is a perfectly usable rudimentary compiler.\nDialogue: 0,0:41:28.76,0:41:31.37,EN,,0,0,0,,Let me kind of show you what it does.\nDialogue: 0,0:41:31.39,0:41:35.56,EN,,0,0,0,,Suppose we start out with recursive factorial.\nDialogue: 0,0:41:36.20,0:41:38.60,EN,,0,0,0,,And these slides are going to be much too small to read.\nDialogue: 0,0:41:38.60,0:41:39.79,EN,,0,0,0,,I just want to flash through the code\nDialogue: 0,0:41:39.79,0:41:41.28,EN,,0,0,0,,and show you about how much it is.\nDialogue: 0,0:41:42.25,0:41:43.29,EN,,0,0,0,,That starts out with--\nDialogue: 0,0:41:44.32,0:41:45.68,EN,,0,0,0,,here's a first block of it,\nDialogue: 0,0:41:45.95,0:41:47.68,EN,,0,0,0,,where it compiles a procedure entry\nDialogue: 0,0:41:47.69,0:41:48.73,EN,,0,0,0,,and does a bunch of assignments.\nDialogue: 0,0:41:48.75,0:41:51.48,EN,,0,0,0,,And this thing is basically up through the part where\nDialogue: 0,0:41:52.65,0:41:53.90,EN,,0,0,0,,sets up to do the predicate\nDialogue: 0,0:41:54.31,0:41:56.59,EN,,0,0,0,,and test whether the predicate's true.\nDialogue: 0,0:41:56.97,0:41:57.85,EN,,0,0,0,,The second part\nDialogue: 0,0:41:58.46,0:42:03.73,EN,,0,0,0,,is what results from-- in the recursive call to fact of n minus one.\nDialogue: 0,0:42:04.12,0:42:05.05,EN,,0,0,0,,And this last part\nDialogue: 0,0:42:06.07,0:42:07.48,EN,,0,0,0,,is coming back from that\nDialogue: 0,0:42:07.87,0:42:09.90,EN,,0,0,0,,and then taking care of the constant case.\nDialogue: 0,0:42:09.90,0:42:13.16,EN,,0,0,0,,So that's about how much code it would produce for factorial.\nDialogue: 0,0:42:13.72,0:42:17.69,EN,,0,0,0,,We could make this compiler much, much better, of course.\nDialogue: 0,0:42:18.67,0:42:21.24,EN,,0,0,0,,The main way we could make it better is\nDialogue: 0,0:42:21.24,0:42:24.00,EN,,0,0,0,,to allow the compiler to make any assumptions at all\nDialogue: 0,0:42:24.35,0:42:26.27,EN,,0,0,0,,about what happens when you call a procedure.\nDialogue: 0,0:42:26.97,0:42:28.28,EN,,0,0,0,,So this compiler, for instance,\nDialogue: 0,0:42:28.30,0:42:32.32,EN,,0,0,0,,doesn't even know, say, that multiplication\nDialogue: 0,0:42:33.12,0:42:36.14,EN,,0,0,0,,you say, is something that could be coded in line.\nDialogue: 0,0:42:36.14,0:42:37.87,EN,,0,0,0,,Instead, it sets up this whole mechanism.\nDialogue: 0,0:42:38.00,0:42:39.34,EN,,0,0,0,,It goes to apply-dispatch.\nDialogue: 0,0:42:41.37,0:42:42.49,EN,,0,0,0,,That's a tremendous waste,\nDialogue: 0,0:42:42.54,0:42:45.02,EN,,0,0,0,,because what you do every time you go to apply-dispatch\nDialogue: 0,0:42:45.02,0:42:46.80,EN,,0,0,0,,is you have to concern about this argument list,\nDialogue: 0,0:42:47.40,0:42:49.10,EN,,0,0,0,,because it's a very general thing you're going to.\nDialogue: 0,0:42:49.13,0:42:51.07,EN,,0,0,0,,In any real compiler, of course,\nDialogue: 0,0:42:51.08,0:42:53.29,EN,,0,0,0,,you're going to have registers for holding arguments.\nDialogue: 0,0:42:53.77,0:42:55.31,EN,,0,0,0,,And you're going to start preserving\nDialogue: 0,0:42:56.38,0:42:58.05,EN,,0,0,0,,saving the way you use those registers\nDialogue: 0,0:42:58.05,0:43:01.61,EN,,0,0,0,,similar to the same strategy here.\nDialogue: 0,0:43:02.85,0:43:05.93,EN,,0,0,0,,So that's probably the very main way\nDialogue: 0,0:43:05.95,0:43:08.30,EN,,0,0,0,,this particular compiler in the book could be fixed.\nDialogue: 0,0:43:08.69,0:43:09.70,EN,,0,0,0,,There are other things like\nDialogue: 0,0:43:09.70,0:43:11.82,EN,,0,0,0,,looking up variable values and\nDialogue: 0,0:43:11.83,0:43:13.87,EN,,0,0,0,,making more efficient primitive operations,\nDialogue: 0,0:43:13.88,0:43:14.56,EN,,0,0,0,,and all sorts of things.\nDialogue: 0,0:43:14.59,0:43:16.60,EN,,0,0,0,,Essentially, a good Lisp compiler\nDialogue: 0,0:43:16.62,0:43:18.49,EN,,0,0,0,,can absorb an arbitrary amount of effort.\nDialogue: 0,0:43:19.72,0:43:21.63,EN,,0,0,0,,And probably one of the reasons\nDialogue: 0,0:43:21.89,0:43:23.04,EN,,0,0,0,,Lisp is slow\nDialogue: 0,0:43:23.63,0:43:25.44,EN,,0,0,0,,with compared to languages like FORTRAN\nDialogue: 0,0:43:25.90,0:43:28.19,EN,,0,0,0,,is that, if you look over history\nDialogue: 0,0:43:28.22,0:43:31.12,EN,,0,0,0,,the amount of effort that's gone into building Lisp compilers,\nDialogue: 0,0:43:31.16,0:43:32.35,EN,,0,0,0,,it's nowhere near the amount of effort\nDialogue: 0,0:43:32.36,0:43:33.90,EN,,0,0,0,,that's gone into FORTRAN compilers.\nDialogue: 0,0:43:34.43,0:43:35.79,EN,,0,0,0,,And maybe that's something that will\nDialogue: 0,0:43:35.92,0:43:37.68,EN,,0,0,0,,that will change over the next couple of years.\nDialogue: 0,0:43:38.00,0:43:38.83,EN,,0,0,0,,OK, let's break.\nDialogue: 0,0:43:43.80,0:43:44.65,EN,,0,0,0,,Questions?\nDialogue: 0,0:43:48.27,0:43:49.95,EN,,0,0,0,,AUDIENCE: One of the very first classes--\nDialogue: 0,0:43:49.95,0:43:51.40,EN,,0,0,0,,I don't know if it was during class or after class-\nDialogue: 0,0:43:51.47,0:43:53.88,EN,,0,0,0,,you showed me the, the\nDialogue: 0,0:43:54.00,0:43:57.52,EN,,0,0,0,,say, addition has a primitive that we don't see,\nDialogue: 0,0:43:57.69,0:43:59.21,EN,,0,0,0,,and-percent add or something like that.\nDialogue: 0,0:43:59.82,0:44:01.65,EN,,0,0,0,,Is that because,\nDialogue: 0,0:44:01.65,0:44:02.60,EN,,0,0,0,,if you're doing inline code\nDialogue: 0,0:44:02.60,0:44:08.19,EN,,0,0,0,,you'd want to just do it for two operators, operands?\nDialogue: 0,0:44:08.70,0:44:10.25,EN,,0,0,0,,But if you had more operands,\nDialogue: 0,0:44:10.28,0:44:11.47,EN,,0,0,0,,you'd want to do something special?\nDialogue: 0,0:44:12.71,0:44:16.04,EN,,0,0,0,,PROFESSOR: Yeah, you're looking in the actual scheme implementation.\nDialogue: 0,0:44:16.06,0:44:17.84,EN,,0,0,0,,There's a plus, and a plus is some operator.\nDialogue: 0,0:44:17.90,0:44:20.19,EN,,0,0,0,,And then if you go look inside the code for plus,\nDialogue: 0,0:44:20.33,0:44:21.37,EN,,0,0,0,,you see something called--\nDialogue: 0,0:44:21.57,0:44:24.14,EN,,0,0,0,,I forget-- and-percent plus or something like that.\nDialogue: 0,0:44:24.55,0:44:25.79,EN,,0,0,0,,And what's going on there is\nDialogue: 0,0:44:25.79,0:44:27.92,EN,,0,0,0,,is that particular kind of optimization.\nDialogue: 0,0:44:28.47,0:44:31.87,EN,,0,0,0,,Because, see, general plus takes an arbitrary number of arguments.\nDialogue: 0,0:44:35.02,0:44:36.38,EN,,0,0,0,,So the most general plus\nDialogue: 0,0:44:36.76,0:44:38.25,EN,,0,0,0,,says, oh, if I have an argument list,\nDialogue: 0,0:44:38.28,0:44:40.62,EN,,0,0,0,,I'd better cons it up in some list\nDialogue: 0,0:44:41.63,0:44:44.14,EN,,0,0,0,,and then figure out how many there were or something like that.\nDialogue: 0,0:44:44.72,0:44:46.16,EN,,0,0,0,,That's terribly inefficient,\nDialogue: 0,0:44:46.81,0:44:49.25,EN,,0,0,0,,especially since most of the time you're probably adding two numbers.\nDialogue: 0,0:44:49.25,0:44:51.24,EN,,0,0,0,,You don't want to really have to cons this argument list.\nDialogue: 0,0:44:52.04,0:44:53.93,EN,,0,0,0,,So what you'd like to do is build\nDialogue: 0,0:44:55.66,0:44:57.71,EN,,0,0,0,,the code for plus with a bunch of entries.\nDialogue: 0,0:44:58.15,0:45:00.17,EN,,0,0,0,,So most of what it's doing is the same.\nDialogue: 0,0:45:00.49,0:45:01.95,EN,,0,0,0,,However, there might be a special entry\nDialogue: 0,0:45:01.98,0:45:03.92,EN,,0,0,0,,that you'd go to if you knew there were only two arguments.\nDialogue: 0,0:45:04.56,0:45:05.87,EN,,0,0,0,,And those you'll put in registers.\nDialogue: 0,0:45:05.87,0:45:06.97,EN,,0,0,0,,they won't be in an argument list\nDialogue: 0,0:45:06.99,0:45:07.98,EN,,0,0,0,,and you won't have to CONS.\nDialogue: 0,0:45:08.67,0:45:10.42,EN,,0,0,0,,That's how a lot of these things work.\nDialogue: 0,0:45:12.30,0:45:13.72,EN,,0,0,0,,OK, let's take a break.\n"
  },
  {
    "path": "Ass/lec10b.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 2622\nVideo Position: 105949\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:18.91,0:00:20.61,EN,,0,0,0,,PROFESSOR: Well, there's one bit of mystery left,\nDialogue: 0,0:00:21.16,0:00:23.36,EN,,0,0,0,,which I'd like to get rid of right now.\nDialogue: 0,0:00:24.44,0:00:28.80,EN,,0,0,0,,And that's that we've been blithely doing things like cons\nDialogue: 0,0:00:30.00,0:00:31.62,EN,,0,0,0,,assuming there's always another one.\nDialogue: 0,0:00:32.80,0:00:36.32,EN,,0,0,0,,That we've been doing these things like\nDialogue: 0,0:00:36.51,0:00:37.44,EN,,0,0,0,,car-ing and cdr-ing\nDialogue: 0,0:00:37.47,0:00:38.72,EN,,0,0,0,,and assuming that we had some idea\nDialogue: 0,0:00:38.75,0:00:39.74,EN,,0,0,0,,how this can be done.\nDialogue: 0,0:00:40.02,0:00:40.67,EN,,0,0,0,,Now indeed\nDialogue: 0,0:00:41.07,0:00:44.40,EN,,0,0,0,,we said that that's equivalent to having procedures.\nDialogue: 0,0:00:45.37,0:00:47.57,EN,,0,0,0,,OK? But that doesn't really solve the problem,\nDialogue: 0,0:00:47.73,0:00:50.25,EN,,0,0,0,,because the procedure need all sorts of complicated mechanisms\nDialogue: 0,0:00:50.27,0:00:51.37,EN,,0,0,0,,like environment structures\nDialogue: 0,0:00:51.64,0:00:52.76,EN,,0,0,0,,and things like that to work.\nDialogue: 0,0:00:53.01,0:00:54.89,EN,,0,0,0,,And those were ultimately made out of conses\nDialogue: 0,0:00:54.89,0:00:56.42,EN,,0,0,0,,in the model that we had,\nDialogue: 0,0:00:56.70,0:00:58.47,EN,,0,0,0,,so that really doesn't solve the problem.\nDialogue: 0,0:00:59.38,0:01:01.13,EN,,0,0,0,,Now the problem here is\nDialogue: 0,0:01:01.31,0:01:03.97,EN,,0,0,0,,is the glue the data structure's made out of.\nDialogue: 0,0:01:04.76,0:01:06.40,EN,,0,0,0,,What kind of possible thing could it be?\nDialogue: 0,0:01:07.04,0:01:10.46,EN,,0,0,0,,OK? We've been showing you things like a machine,\nDialogue: 0,0:01:10.46,0:01:13.96,EN,,0,0,0,,a computer that has a controller,\nDialogue: 0,0:01:14.27,0:01:15.45,EN,,0,0,0,,and some registers,\nDialogue: 0,0:01:15.45,0:01:16.47,EN,,0,0,0,,and maybe a stack.\nDialogue: 0,0:01:16.98,0:01:18.12,EN,,0,0,0,,And we haven't said anything about,\nDialogue: 0,0:01:18.16,0:01:19.95,EN,,0,0,0,,for example, larger memory.\nDialogue: 0,0:01:20.57,0:01:22.38,EN,,0,0,0,,And I think that's what we have to worry about right now.\nDialogue: 0,0:01:23.74,0:01:26.56,EN,,0,0,0,,But just to make it perfectly clear\nDialogue: 0,0:01:26.59,0:01:27.88,EN,,0,0,0,,that this is an inessential,\nDialogue: 0,0:01:28.82,0:01:30.79,EN,,0,0,0,,purely implementational thing,\nDialogue: 0,0:01:31.10,0:01:32.60,EN,,0,0,0,,I'd like to show you, for example,\nDialogue: 0,0:01:32.60,0:01:34.20,EN,,0,0,0,,how you can do it all with the numbers.\nDialogue: 0,0:01:35.23,0:01:36.82,EN,,0,0,0,,That's an easy one.\nDialogue: 0,0:01:37.59,0:01:39.00,EN,,0,0,0,,Famous fellow by the name of Godel,\nDialogue: 0,0:01:44.09,0:01:46.01,EN,,0,0,0,,a logician at the end of the 1930s,\nDialogue: 0,0:01:46.38,0:01:48.70,EN,,0,0,0,,invented a very clever way\nDialogue: 0,0:01:48.70,0:01:52.27,EN,,0,0,0,,of encoding the complicated expressions\nDialogue: 0,0:01:52.81,0:01:53.52,EN,,0,0,0,,as numbers.\nDialogue: 0,0:01:54.32,0:01:55.05,EN,,0,0,0,,For example--\nDialogue: 0,0:01:55.05,0:01:58.00,EN,,0,0,0,,I'm not saying exactly what Godel's scheme is,\nDialogue: 0,0:01:58.00,0:01:59.48,EN,,0,0,0,,because he didn't use words like cons.\nDialogue: 0,0:01:59.66,0:02:00.60,EN,,0,0,0,,He had other kinds of\nDialogue: 0,0:02:00.91,0:02:02.60,EN,,0,0,0,,of ways of combining to make expressions.\nDialogue: 0,0:02:03.09,0:02:03.88,EN,,0,0,0,,But he said,\nDialogue: 0,0:02:03.92,0:02:06.81,EN,,0,0,0,,I'm going to assign a number to every algebraic expression.\nDialogue: 0,0:02:07.92,0:02:09.72,EN,,0,0,0,,And the way I'm going to manufacture these numbers\nDialogue: 0,0:02:09.72,0:02:11.65,EN,,0,0,0,,is by combining the numbers of the parts.\nDialogue: 0,0:02:12.47,0:02:13.45,EN,,0,0,0,,So for example,\nDialogue: 0,0:02:13.62,0:02:15.35,EN,,0,0,0,,what we were doing our world,\nDialogue: 0,0:02:15.35,0:02:18.01,EN,,0,0,0,,we could say that if objects\nDialogue: 0,0:02:20.78,0:02:22.22,EN,,0,0,0,,are represented by numbers,\nDialogue: 0,0:02:30.67,0:02:37.93,EN,,0,0,0,,then cons of x and y\nDialogue: 0,0:02:38.04,0:02:41.07,EN,,0,0,0,,could be represented by,\nDialogue: 0,0:02:41.55,0:02:43.77,EN,,0,0,0,,2 to the x times 3 to the y.\nDialogue: 0,0:02:46.13,0:02:48.03,EN,,0,0,0,,Because then we could extract the parts.\nDialogue: 0,0:02:49.56,0:02:50.97,EN,,0,0,0,,We could say, for example,\nDialogue: 0,0:02:51.18,0:02:55.88,EN,,0,0,0,,that then car of, say, x\nDialogue: 0,0:02:56.55,0:03:05.18,EN,,0,0,0,,is the number of factors of 2 in x.\nDialogue: 0,0:03:06.69,0:03:08.78,EN,,0,0,0,,OK? And of course cdr is the same thing.\nDialogue: 0,0:03:10.69,0:03:15.57,EN,,0,0,0,,It's the number of factors of 3 in x.\nDialogue: 0,0:03:16.51,0:03:18.65,EN,,0,0,0,,Now this is a perfectly reasonable scheme,\nDialogue: 0,0:03:19.10,0:03:20.11,EN,,0,0,0,,except for the fact that\nDialogue: 0,0:03:20.12,0:03:22.52,EN,,0,0,0,,the numbers rapidly get to be much larger\nDialogue: 0,0:03:22.83,0:03:23.98,EN,,0,0,0,,in number of digits\nDialogue: 0,0:03:24.32,0:03:26.55,EN,,0,0,0,,than the number of protons in the universe.\nDialogue: 0,0:03:27.95,0:03:29.88,EN,,0,0,0,,So there's no easy way to use this scheme\nDialogue: 0,0:03:29.90,0:03:31.21,EN,,0,0,0,,other than the theoretical one.\nDialogue: 0,0:03:33.43,0:03:34.48,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:03:35.12,0:03:37.55,EN,,0,0,0,,there are other ways of representing these things.\nDialogue: 0,0:03:38.45,0:03:40.01,EN,,0,0,0,,We have been thinking in terms\nDialogue: 0,0:03:40.25,0:03:42.42,EN,,0,0,0,,of little boxes, boxes.\nDialogue: 0,0:03:43.32,0:03:46.43,EN,,0,0,0,,We've been thinking about our cons structures\nDialogue: 0,0:03:46.50,0:03:48.05,EN,,0,0,0,,as looking sort of like this.\nDialogue: 0,0:03:50.28,0:03:52.57,EN,,0,0,0,,They're little pigeon holes with things in them.\nDialogue: 0,0:03:53.56,0:03:55.47,EN,,0,0,0,,And of course we arrange them in little trees.\nDialogue: 0,0:03:57.21,0:03:59.97,EN,,0,0,0,,I wish that the semiconductor manufacturers\nDialogue: 0,0:03:59.97,0:04:02.07,EN,,0,0,0,,would supply me with something appropriate for this,\nDialogue: 0,0:04:02.70,0:04:03.76,EN,,0,0,0,,but actually\nDialogue: 0,0:04:03.85,0:04:05.31,EN,,0,0,0,,what they do supply me with\nDialogue: 0,0:04:06.20,0:04:07.96,EN,,0,0,0,,is a linear memory.\nDialogue: 0,0:04:09.38,0:04:13.46,EN,,0,0,0,,Memory is sort of a big pile of pigeonholes,\nDialogue: 0,0:04:15.12,0:04:16.34,EN,,0,0,0,,pigeonholes like this.\nDialogue: 0,0:04:17.72,0:04:20.25,EN,,0,0,0,,Each of which can hold a certain sized object,\nDialogue: 0,0:04:20.94,0:04:22.20,EN,,0,0,0,,a fixed size object.\nDialogue: 0,0:04:23.39,0:04:24.07,EN,,0,0,0,,So, for example,\nDialogue: 0,0:04:24.07,0:04:25.66,EN,,0,0,0,,a complicated list with 25 elements\nDialogue: 0,0:04:25.66,0:04:26.64,EN,,0,0,0,,won't fit in one of these.\nDialogue: 0,0:04:28.55,0:04:29.26,EN,,0,0,0,,However, each of these\nDialogue: 0,0:04:29.29,0:04:30.88,EN,,0,0,0,,is indexed by an address.\nDialogue: 0,0:04:33.97,0:04:34.99,EN,,0,0,0,,So the address might be\nDialogue: 0,0:04:35.02,0:04:35.50,EN,,0,0,0,,zero here,\nDialogue: 0,0:04:35.50,0:04:36.22,EN,,0,0,0,,one here,\nDialogue: 0,0:04:36.22,0:04:36.70,EN,,0,0,0,,two here,\nDialogue: 0,0:04:36.70,0:04:37.25,EN,,0,0,0,,three here,\nDialogue: 0,0:04:37.25,0:04:37.94,EN,,0,0,0,,and so on.\nDialogue: 0,0:04:38.06,0:04:40.40,EN,,0,0,0,,That we write these down as numbers is unimportant.\nDialogue: 0,0:04:40.40,0:04:41.68,EN,,0,0,0,,What matters is that they're distinct\nDialogue: 0,0:04:41.95,0:04:43.42,EN,,0,0,0,,as a way to get to the next one.\nDialogue: 0,0:04:44.97,0:04:46.14,EN,,0,0,0,,And inside of each of these,\nDialogue: 0,0:04:46.36,0:04:49.11,EN,,0,0,0,,we can stuff something into these pigeonholes.\nDialogue: 0,0:04:49.53,0:04:50.77,EN,,0,0,0,,That's what memory is like,\nDialogue: 0,0:04:51.02,0:04:53.66,EN,,0,0,0,,for those of you who haven't built a computer.\nDialogue: 0,0:04:54.15,0:04:54.65,EN,,0,0,0,,Now.\nDialogue: 0,0:04:56.69,0:04:57.53,EN,,0,0,0,,Now the problem is\nDialogue: 0,0:04:57.53,0:04:59.97,EN,,0,0,0,,how are we going to impose on this type of structure,\nDialogue: 0,0:05:00.42,0:05:01.72,EN,,0,0,0,,this nice tree structure.\nDialogue: 0,0:05:03.29,0:05:04.57,EN,,0,0,0,,Well it's not very hard,\nDialogue: 0,0:05:04.57,0:05:06.35,EN,,0,0,0,,and there have been numerous schemes involved in this.\nDialogue: 0,0:05:06.87,0:05:08.80,EN,,0,0,0,,The most important one is to say,\nDialogue: 0,0:05:08.80,0:05:11.18,EN,,0,0,0,,well assuming that the semiconductor manufacturer\nDialogue: 0,0:05:11.20,0:05:13.90,EN,,0,0,0,,allows me to arrange my memory\nDialogue: 0,0:05:13.98,0:05:15.77,EN,,0,0,0,,so that one of these pigeonholes is big enough\nDialogue: 0,0:05:16.28,0:05:18.20,EN,,0,0,0,,to hold the address of another\nDialogue: 0,0:05:19.35,0:05:20.83,EN,,0,0,0,,OK. I have been made.\nDialogue: 0,0:05:22.05,0:05:23.45,EN,,0,0,0,,Now it actually has to be a little bit bigger\nDialogue: 0,0:05:23.48,0:05:27.52,EN,,0,0,0,,because I have to also install or store some information\nDialogue: 0,0:05:27.56,0:05:30.09,EN,,0,0,0,,as to a tag which describes the kind of thing that's there.\nDialogue: 0,0:05:30.39,0:05:31.64,EN,,0,0,0,,And we'll see that in a second.\nDialogue: 0,0:05:32.62,0:05:34.40,EN,,0,0,0,,And of course if the semiconductor manufacturer\nDialogue: 0,0:05:34.43,0:05:35.88,EN,,0,0,0,,doesn't arrange it so I can do that,\nDialogue: 0,0:05:36.08,0:05:38.44,EN,,0,0,0,,then of course I can, with some cleverness,\nDialogue: 0,0:05:38.57,0:05:41.82,EN,,0,0,0,,arrange combinations of these to fit together in that way.\nDialogue: 0,0:05:43.77,0:05:47.05,EN,,0,0,0,,So we're going to have to imagine\nDialogue: 0,0:05:47.05,0:05:49.54,EN,,0,0,0,,imposing this complicated tree structure\nDialogue: 0,0:05:49.54,0:05:51.20,EN,,0,0,0,,on our nice linear memory.\nDialogue: 0,0:05:51.74,0:05:54.47,EN,,0,0,0,,If we look at the first still store,\nDialogue: 0,0:05:54.47,0:05:58.30,EN,,0,0,0,,we see a classic scheme for doing that.\nDialogue: 0,0:05:59.49,0:06:02.62,EN,,0,0,0,,It's a standard way of representing list structures\nDialogue: 0,0:06:03.22,0:06:05.87,EN,,0,0,0,,in a linear memory.\nDialogue: 0,0:06:06.27,0:06:08.32,EN,,0,0,0,,What we do is we divide this memory\nDialogue: 0,0:06:08.88,0:06:11.12,EN,,0,0,0,,into two parts.\nDialogue: 0,0:06:12.03,0:06:13.42,EN,,0,0,0,,An array called the cars,\nDialogue: 0,0:06:14.45,0:06:15.88,EN,,0,0,0,,and an array called the cdrs.\nDialogue: 0,0:06:17.58,0:06:18.86,EN,,0,0,0,,Now whether those happen to be\nDialogue: 0,0:06:18.88,0:06:21.04,EN,,0,0,0,,sequential addresses or whatever,\nDialogue: 0,0:06:21.12,0:06:22.00,EN,,0,0,0,,it's not important.\nDialogue: 0,0:06:22.87,0:06:25.20,EN,,0,0,0,,That's somebody's implementation details.\nDialogue: 0,0:06:25.80,0:06:28.40,EN,,0,0,0,,But there are two arrays here.\nDialogue: 0,0:06:28.96,0:06:30.36,EN,,0,0,0,,Linear arrays indexed\nDialogue: 0,0:06:30.46,0:06:32.59,EN,,0,0,0,,by sequential indices like this.\nDialogue: 0,0:06:34.84,0:06:36.85,EN,,0,0,0,,What is stored in each of these pigeonholes\nDialogue: 0,0:06:37.46,0:06:39.85,EN,,0,0,0,,is a typed object.\nDialogue: 0,0:06:41.43,0:06:42.57,EN,,0,0,0,,And what we have here\nDialogue: 0,0:06:42.57,0:06:45.71,EN,,0,0,0,,are types which begin with letters like p,\nDialogue: 0,0:06:45.71,0:06:46.57,EN,,0,0,0,,standing for a pair.\nDialogue: 0,0:06:47.79,0:06:49.37,EN,,0,0,0,,Or n, standing for a number.\nDialogue: 0,0:06:50.04,0:06:52.25,EN,,0,0,0,,Or e, standing for an empty list.\nDialogue: 0,0:06:54.81,0:06:55.83,EN,,0,0,0,,The end of the list.\nDialogue: 0,0:06:57.02,0:06:58.59,EN,,0,0,0,,And so if we wish to represent\nDialogue: 0,0:06:58.99,0:06:59.97,EN,,0,0,0,,an object like this,\nDialogue: 0,0:07:00.01,0:07:02.16,EN,,0,0,0,,the list beginning with 1, 2\nDialogue: 0,0:07:02.65,0:07:04.01,EN,,0,0,0,,and then having a 3 and a 4\nDialogue: 0,0:07:04.01,0:07:05.50,EN,,0,0,0,,and then having a 3 and a 4 as its second and third elements.\nDialogue: 0,0:07:06.43,0:07:08.83,EN,,0,0,0,,A list containing a list as its first part\nDialogue: 0,0:07:09.35,0:07:10.65,EN,,0,0,0,,and then two numbers\nDialogue: 0,0:07:10.65,0:07:12.00,EN,,0,0,0,,as a second and third parts.\nDialogue: 0,0:07:12.87,0:07:14.81,EN,,0,0,0,,Then of course we draw it sort of like this these days,\nDialogue: 0,0:07:14.84,0:07:16.67,EN,,0,0,0,,in box-and-pointer notation.\nDialogue: 0,0:07:17.32,0:07:18.00,EN,,0,0,0,,And you see,\nDialogue: 0,0:07:18.00,0:07:20.04,EN,,0,0,0,,these are the three cells\nDialogue: 0,0:07:20.25,0:07:22.01,EN,,0,0,0,,that have as their car pointer\nDialogue: 0,0:07:22.27,0:07:27.10,EN,,0,0,0,,the object which is either 1, 2 or 3 or 4.\nDialogue: 0,0:07:28.39,0:07:29.75,EN,,0,0,0,,And then of course the 1, 2,\nDialogue: 0,0:07:29.75,0:07:31.32,EN,,0,0,0,,the car of this entire structure,\nDialogue: 0,0:07:31.32,0:07:32.65,EN,,0,0,0,,is itself a substructure\nDialogue: 0,0:07:32.88,0:07:34.75,EN,,0,0,0,,which contains a sublist like that.\nDialogue: 0,0:07:35.94,0:07:37.07,EN,,0,0,0,,What I'm about to do\nDialogue: 0,0:07:37.20,0:07:39.92,EN,,0,0,0,,is put down places which are--\nDialogue: 0,0:07:39.95,0:07:41.46,EN,,0,0,0,,I'm going to assign indices.\nDialogue: 0,0:07:41.84,0:07:43.40,EN,,0,0,0,,Like this 1, over here,\nDialogue: 0,0:07:43.56,0:07:47.05,EN,,0,0,0,,represents the index of this cell.\nDialogue: 0,0:07:49.85,0:07:51.47,EN,,0,0,0,,But that pointer that we see here\nDialogue: 0,0:07:52.37,0:07:54.86,EN,,0,0,0,,is a reference to the\nDialogue: 0,0:07:55.07,0:07:57.29,EN,,0,0,0,,pair of pigeonholes in the cars and the cdrs\nDialogue: 0,0:07:57.40,0:07:58.67,EN,,0,0,0,,that are labeled by 1\nDialogue: 0,0:07:58.76,0:08:00.33,EN,,0,0,0,,in my linear memory down here.\nDialogue: 0,0:08:02.00,0:08:04.06,EN,,0,0,0,,So if I wish to impose this structure\nDialogue: 0,0:08:04.16,0:08:05.26,EN,,0,0,0,,on my linear memory,\nDialogue: 0,0:08:05.85,0:08:07.52,EN,,0,0,0,,what I do is I say, oh yes,\nDialogue: 0,0:08:07.52,0:08:11.88,EN,,0,0,0,,why don't we drop this into cell 1?\nDialogue: 0,0:08:11.95,0:08:12.66,EN,,0,0,0,,Well I said, I pick 1.\nDialogue: 0,0:08:12.66,0:08:13.85,EN,,0,0,0,,There's 1. OK?\nDialogue: 0,0:08:14.27,0:08:16.22,EN,,0,0,0,,And that says that its car,\nDialogue: 0,0:08:16.22,0:08:17.74,EN,,0,0,0,,I'm going to assign it to be a pair.\nDialogue: 0,0:08:17.95,0:08:18.72,EN,,0,0,0,,It's a pair,\nDialogue: 0,0:08:20.02,0:08:21.55,EN,,0,0,0,,which is in index 5.\nDialogue: 0,0:08:22.59,0:08:23.90,EN,,0,0,0,,And the cdr,\nDialogue: 0,0:08:23.90,0:08:25.13,EN,,0,0,0,,which is this one over here,\nDialogue: 0,0:08:25.39,0:08:26.13,EN,,0,0,0,,is a pair\nDialogue: 0,0:08:26.13,0:08:27.70,EN,,0,0,0,,which I'm going to stick into place 2.\nDialogue: 0,0:08:28.34,0:08:28.98,EN,,0,0,0,,p2.\nDialogue: 0,0:08:30.89,0:08:32.95,EN,,0,0,0,,And take a look at p2.\nDialogue: 0,0:08:32.95,0:08:34.72,EN,,0,0,0,,Oh yes, well p2 is a thing\nDialogue: 0,0:08:34.90,0:08:37.22,EN,,0,0,0,,whose car is the number 3,\nDialogue: 0,0:08:37.34,0:08:38.64,EN,,0,0,0,,so as you see, an n3.\nDialogue: 0,0:08:39.52,0:08:41.52,EN,,0,0,0,,And whose cdr, over here,\nDialogue: 0,0:08:41.72,0:08:43.40,EN,,0,0,0,,is a pair,\nDialogue: 0,0:08:43.97,0:08:45.81,EN,,0,0,0,,which lives in place 4.\nDialogue: 0,0:08:46.64,0:08:47.79,EN,,0,0,0,,So that's what this p4 is.\nDialogue: 0,0:08:48.65,0:08:51.16,EN,,0,0,0,,p4 is a number\nDialogue: 0,0:08:51.85,0:08:53.87,EN,,0,0,0,,whose value is 4 in its car\nDialogue: 0,0:08:54.60,0:08:55.65,EN,,0,0,0,,and whose cdr\nDialogue: 0,0:08:55.84,0:08:58.48,EN,,0,0,0,,is an empty list right there.\nDialogue: 0,0:08:59.17,0:08:59.90,EN,,0,0,0,,And that ends it.\nDialogue: 0,0:09:00.69,0:09:04.57,EN,,0,0,0,,So this is the traditional way of representing\nDialogue: 0,0:09:04.90,0:09:09.55,EN,,0,0,0,,this kind of binary tree in a linear memory.\nDialogue: 0,0:09:11.62,0:09:15.10,EN,,0,0,0,,Now the next question, of course,\nDialogue: 0,0:09:15.10,0:09:16.36,EN,,0,0,0,,that we might want to worry about\nDialogue: 0,0:09:16.60,0:09:18.19,EN,,0,0,0,,is just a little bit of implementation.\nDialogue: 0,0:09:18.44,0:09:20.33,EN,,0,0,0,,That means that when I write procedures\nDialogue: 0,0:09:20.36,0:09:23.62,EN,,0,0,0,,of the form assigned a,\nDialogue: 0,0:09:24.54,0:09:27.10,EN,,0,0,0,,lines of register machine code\nDialogue: 0,0:09:27.21,0:09:30.14,EN,,0,0,0,,of the form assigned a, the car of fetch of b,\nDialogue: 0,0:09:30.84,0:09:31.85,EN,,0,0,0,,what I really mean\nDialogue: 0,0:09:31.97,0:09:37.10,EN,,0,0,0,,is addressing these elements.\nDialogue: 0,0:09:38.74,0:09:40.25,EN,,0,0,0,,And so we're going to think of that as\nDialogue: 0,0:09:40.68,0:09:42.94,EN,,0,0,0,,a abbreviation for it.\nDialogue: 0,0:09:44.47,0:09:46.33,EN,,0,0,0,,Now of course in order to write that down\nDialogue: 0,0:09:46.35,0:09:48.59,EN,,0,0,0,,I'm going to introduce some sort of a structure\nDialogue: 0,0:09:48.62,0:09:49.42,EN,,0,0,0,,called a vector.\nDialogue: 0,0:09:52.12,0:09:53.31,EN,,0,0,0,,And we're going to have something which will\nDialogue: 0,0:09:53.48,0:09:54.54,EN,,0,0,0,,reference a vector,\nDialogue: 0,0:09:56.84,0:09:58.51,EN,,0,0,0,,just so we can write it down.\nDialogue: 0,0:09:58.71,0:10:00.22,EN,,0,0,0,,Which takes the name of the vector,\nDialogue: 0,0:10:01.02,0:10:03.97,EN,,0,0,0,,or the-- I don't think that name is the right word.\nDialogue: 0,0:10:03.97,0:10:09.40,EN,,0,0,0,,Which takes the vector and the index,\nDialogue: 0,0:10:11.20,0:10:13.05,EN,,0,0,0,,and I have to have a way of setting one of those\nDialogue: 0,0:10:13.10,0:10:14.27,EN,,0,0,0,,with something called a vector set,\nDialogue: 0,0:10:14.65,0:10:15.60,EN,,0,0,0,,I don't really care.\nDialogue: 0,0:10:16.28,0:10:17.55,EN,,0,0,0,,But let's look, for example,\nDialogue: 0,0:10:18.11,0:10:20.42,EN,,0,0,0,,at then that kind of implementation\nDialogue: 0,0:10:21.25,0:10:23.18,EN,,0,0,0,,of car and cdr.\nDialogue: 0,0:10:26.47,0:10:28.41,EN,,0,0,0,,So for example if I happen to have\nDialogue: 0,0:10:28.88,0:10:30.80,EN,,0,0,0,,a register b,\nDialogue: 0,0:10:31.15,0:10:34.64,EN,,0,0,0,,which contains the type index of a pair,\nDialogue: 0,0:10:35.95,0:10:38.80,EN,,0,0,0,,and therefore it is the pointer to a pair,\nDialogue: 0,0:10:39.35,0:10:40.85,EN,,0,0,0,,then I could take the car of that and\nDialogue: 0,0:10:41.55,0:10:44.11,EN,,0,0,0,,OK if I-- write this down-- I might put that in register a.\nDialogue: 0,0:10:44.49,0:10:46.86,EN,,0,0,0,,What that really is is a representation of\nDialogue: 0,0:10:47.37,0:10:50.19,EN,,0,0,0,,the assign to a,\nDialogue: 0,0:10:50.19,0:10:51.92,EN,,0,0,0,,the value of vector reffing--\nDialogue: 0,0:10:52.80,0:10:55.24,EN,,0,0,0,,or array indexing, if you will-- or something,\nDialogue: 0,0:10:55.42,0:10:57.63,EN,,0,0,0,,the cars object--\nDialogue: 0,0:10:58.40,0:11:00.92,EN,,0,0,0,,whatever that is-- with the index, b.\nDialogue: 0,0:11:02.65,0:11:03.63,EN,,0,0,0,,And similarly for cdr.\nDialogue: 0,0:11:04.10,0:11:05.72,EN,,0,0,0,,And we can do the same thing\nDialogue: 0,0:11:05.90,0:11:08.32,EN,,0,0,0,,for assignment to data structures,\nDialogue: 0,0:11:08.92,0:11:10.92,EN,,0,0,0,,If we need to do that sort of things at all.\nDialogue: 0,0:11:11.84,0:11:13.80,EN,,0,0,0,,It's not too hard to build that.\nDialogue: 0,0:11:14.58,0:11:15.72,EN,,0,0,0,,Well now the next question is\nDialogue: 0,0:11:15.72,0:11:17.00,EN,,0,0,0,,how are we going to do allocation.\nDialogue: 0,0:11:18.01,0:11:20.13,EN,,0,0,0,,And every so often I say I want a cons.\nDialogue: 0,0:11:21.40,0:11:23.42,EN,,0,0,0,,Now conses don't grow on trees.\nDialogue: 0,0:11:23.79,0:11:24.81,EN,,0,0,0,,Or maybe they should.\nDialogue: 0,0:11:25.34,0:11:26.56,EN,,0,0,0,,But I have to have some way\nDialogue: 0,0:11:26.70,0:11:28.97,EN,,0,0,0,,I have to have some way of getting the next one.\nDialogue: 0,0:11:29.98,0:11:31.47,EN,,0,0,0,,I have to have some idea of\nDialogue: 0,0:11:31.47,0:11:33.04,EN,,0,0,0,,if their memory is unused\nDialogue: 0,0:11:33.69,0:11:35.05,EN,,0,0,0,,that I might want to allocate from.\nDialogue: 0,0:11:35.63,0:11:37.38,EN,,0,0,0,,And there are many schemes for doing this.\nDialogue: 0,0:11:37.38,0:11:39.07,EN,,0,0,0,,And the particular thing I'm showing you right now\nDialogue: 0,0:11:39.23,0:11:40.45,EN,,0,0,0,,is not essential.\nDialogue: 0,0:11:42.10,0:11:43.18,EN,,0,0,0,,However it's convenient\nDialogue: 0,0:11:43.20,0:11:44.44,EN,,0,0,0,,and has been done many times.\nDialogue: 0,0:11:44.60,0:11:47.20,EN,,0,0,0,,It's one schemes called the free list allocation scheme.\nDialogue: 0,0:11:47.66,0:11:48.68,EN,,0,0,0,,What that means is\nDialogue: 0,0:11:48.68,0:11:51.12,EN,,0,0,0,,that all of the free memory that there is in the world\nDialogue: 0,0:11:51.55,0:11:53.08,EN,,0,0,0,,is linked together in a linked list,\nDialogue: 0,0:11:54.55,0:11:56.22,EN,,0,0,0,,just like all the other stuff.\nDialogue: 0,0:11:56.96,0:11:59.07,EN,,0,0,0,,And whenever you need a free cell\nDialogue: 0,0:11:59.07,0:12:00.12,EN,,0,0,0,,to make a new cons,\nDialogue: 0,0:12:00.95,0:12:02.26,EN,,0,0,0,,you grab the first one\nDialogue: 0,0:12:02.26,0:12:03.82,EN,,0,0,0,,make the free list be the cdr of it,\nDialogue: 0,0:12:04.32,0:12:05.55,EN,,0,0,0,,and then allocate that.\nDialogue: 0,0:12:06.03,0:12:08.32,EN,,0,0,0,,And so what that looks like is something like this.\nDialogue: 0,0:12:09.53,0:12:13.32,EN,,0,0,0,,Here we have the free list\nDialogue: 0,0:12:13.95,0:12:16.81,EN,,0,0,0,,starting in 6.\nDialogue: 0,0:12:18.51,0:12:23.47,EN,,0,0,0,,And what that is is a pointer-off to say 8.\nDialogue: 0,0:12:24.86,0:12:25.62,EN,,0,0,0,,So what it says is,\nDialogue: 0,0:12:25.62,0:12:26.55,EN,,0,0,0,,this one is free\nDialogue: 0,0:12:26.55,0:12:27.95,EN,,0,0,0,,and the next one is an 8.\nDialogue: 0,0:12:28.87,0:12:29.88,EN,,0,0,0,,This one is free\nDialogue: 0,0:12:30.04,0:12:32.08,EN,,0,0,0,,and the next one is in 3,\nDialogue: 0,0:12:32.32,0:12:33.45,EN,,0,0,0,,the next one that's free.\nDialogue: 0,0:12:33.93,0:12:34.95,EN,,0,0,0,,That one's free\nDialogue: 0,0:12:35.04,0:12:37.68,EN,,0,0,0,,and the next one is in 0.\nDialogue: 0,0:12:37.87,0:12:38.49,EN,,0,0,0,,That one's free\nDialogue: 0,0:12:38.52,0:12:39.82,EN,,0,0,0,,and the next one's in 15.\nDialogue: 0,0:12:40.94,0:12:41.84,EN,,0,0,0,,Something like that.\nDialogue: 0,0:12:42.78,0:12:44.64,EN,,0,0,0,,We can imagine having such a structure.\nDialogue: 0,0:12:46.40,0:12:48.03,EN,,0,0,0,,Given that we have something like that,\nDialogue: 0,0:12:49.45,0:12:50.92,EN,,0,0,0,,then it's possible to\nDialogue: 0,0:12:50.92,0:12:52.22,EN,,0,0,0,,just get one when you need it.\nDialogue: 0,0:12:53.82,0:12:56.46,EN,,0,0,0,,And so a program for doing cons,\nDialogue: 0,0:12:57.45,0:12:59.13,EN,,0,0,0,,this is what cons might turn into.\nDialogue: 0,0:12:59.32,0:13:02.57,EN,,0,0,0,,To assign to a register A the result of cons-ing,\nDialogue: 0,0:13:02.95,0:13:05.82,EN,,0,0,0,,a B onto C,\nDialogue: 0,0:13:06.20,0:13:09.04,EN,,0,0,0,,the value in this containing B and the value containing C,\nDialogue: 0,0:13:09.27,0:13:10.52,EN,,0,0,0,,what we have to do is\nDialogue: 0,0:13:10.56,0:13:12.24,EN,,0,0,0,,get the current tail ahead of the freelist,\nDialogue: 0,0:13:12.47,0:13:14.30,EN,,0,0,0,,make the free list be its cdr.\nDialogue: 0,0:13:15.64,0:13:18.33,EN,,0,0,0,,Then we have to change the cars\nDialogue: 0,0:13:18.41,0:13:22.49,EN,,0,0,0,,to be the thing we're making up to be in A\nDialogue: 0,0:13:23.13,0:13:25.45,EN,,0,0,0,,to be the B, the thing in B.\nDialogue: 0,0:13:25.90,0:13:28.65,EN,,0,0,0,,And we have to make change the cdrs of\nDialogue: 0,0:13:29.20,0:13:31.72,EN,,0,0,0,,the thing that's in A to be C.\nDialogue: 0,0:13:33.20,0:13:34.76,EN,,0,0,0,,And then what we have in A\nDialogue: 0,0:13:34.78,0:13:36.65,EN,,0,0,0,,is the right new frob, whatever it is.\nDialogue: 0,0:13:36.81,0:13:37.92,EN,,0,0,0,,The object that we want.\nDialogue: 0,0:13:40.47,0:13:42.50,EN,,0,0,0,,Now there's a little bit of\nDialogue: 0,0:13:42.50,0:13:43.97,EN,,0,0,0,,a cheat here that I haven't told you about,\nDialogue: 0,0:13:43.97,0:13:45.32,EN,,0,0,0,,which is somewhere around here\nDialogue: 0,0:13:45.53,0:13:47.32,EN,,0,0,0,,I haven't set the type of the thing that I've\nDialogue: 0,0:13:48.45,0:13:50.48,EN,,0,0,0,,the type of the thing\nDialogue: 0,0:13:50.51,0:13:51.87,EN,,0,0,0,,that I'm cons-ing up to be a pair,\nDialogue: 0,0:13:52.30,0:13:53.05,EN,,0,0,0,,and I ought to.\nDialogue: 0,0:13:53.51,0:13:56.57,EN,,0,0,0,,So there should be some sort of bits here are being set,\nDialogue: 0,0:13:56.60,0:13:57.76,EN,,0,0,0,,and I just haven't written that down.\nDialogue: 0,0:13:59.81,0:14:00.86,EN,,0,0,0,,We could have arranged it, of course,\nDialogue: 0,0:14:00.89,0:14:02.45,EN,,0,0,0,,for the free list to be made out of pairs.\nDialogue: 0,0:14:03.10,0:14:04.88,EN,,0,0,0,,And so then there's no problem with that.\nDialogue: 0,0:14:06.43,0:14:07.74,EN,,0,0,0,,But that sort of--\nDialogue: 0,0:14:07.82,0:14:09.92,EN,,0,0,0,,again, an inessential detail in a way\nDialogue: 0,0:14:10.22,0:14:12.88,EN,,0,0,0,,some particular programmer or architect\nDialogue: 0,0:14:12.92,0:14:14.27,EN,,0,0,0,,or whatever might manufacture\nDialogue: 0,0:14:14.33,0:14:16.68,EN,,0,0,0,,his machine or Lisp system.\nDialogue: 0,0:14:17.54,0:14:18.71,EN,,0,0,0,,So for example,\nDialogue: 0,0:14:19.07,0:14:20.24,EN,,0,0,0,,just looking at this,\nDialogue: 0,0:14:20.65,0:14:23.45,EN,,0,0,0,,to allocate\nDialogue: 0,0:14:23.55,0:14:26.83,EN,,0,0,0,,given that I had already the structure that you saw before,\nDialogue: 0,0:14:27.21,0:14:30.26,EN,,0,0,0,,supposing I wanted to allocate a new cell,\nDialogue: 0,0:14:30.55,0:14:36.61,EN,,0,0,0,,which is going to be representation of list one, one, two,\nDialogue: 0,0:14:37.24,0:14:39.87,EN,,0,0,0,,where already one two was the car\nDialogue: 0,0:14:40.28,0:14:42.16,EN,,0,0,0,,of the list we were playing with before.\nDialogue: 0,0:14:43.43,0:14:44.45,EN,,0,0,0,,Well that's not so hard.\nDialogue: 0,0:14:44.78,0:14:46.20,EN,,0,0,0,,I stored that one in one,\nDialogue: 0,0:14:46.20,0:14:49.17,EN,,0,0,0,,so p1 one is the representation of this.\nDialogue: 0,0:14:49.53,0:14:50.83,EN,,0,0,0,,This is p5.\nDialogue: 0,0:14:51.67,0:14:53.51,EN,,0,0,0,,That's going to be the cdr of this.\nDialogue: 0,0:14:54.07,0:14:55.52,EN,,0,0,0,,Now we're going to pull something off the free list,\nDialogue: 0,0:14:55.52,0:14:57.30,EN,,0,0,0,,but remember the free list started at six.\nDialogue: 0,0:14:57.78,0:15:00.18,EN,,0,0,0,,The new free list after this allocation is eight,\nDialogue: 0,0:15:00.60,0:15:02.55,EN,,0,0,0,,a free list beginning at eight.\nDialogue: 0,0:15:02.89,0:15:03.52,EN,,0,0,0,,And of course\nDialogue: 0,0:15:03.72,0:15:06.04,EN,,0,0,0,,in six now we have a number one,\nDialogue: 0,0:15:06.15,0:15:07.10,EN,,0,0,0,,which is what we wanted,\nDialogue: 0,0:15:07.39,0:15:11.56,EN,,0,0,0,,with its cdr being the pair starting in location five.\nDialogue: 0,0:15:13.33,0:15:14.50,EN,,0,0,0,,And that's no big deal.\nDialogue: 0,0:15:16.81,0:15:20.45,EN,,0,0,0,,So the only problem really remaining here is,\nDialogue: 0,0:15:21.00,0:15:23.40,EN,,0,0,0,,well, I don't have an infinitely large memory.\nDialogue: 0,0:15:25.08,0:15:26.66,EN,,0,0,0,,If I do this for a little while,\nDialogue: 0,0:15:27.25,0:15:28.00,EN,,0,0,0,,say, for example,\nDialogue: 0,0:15:28.01,0:15:30.14,EN,,0,0,0,,supposing it takes me a microsecond to do a cons,\nDialogue: 0,0:15:30.60,0:15:32.97,EN,,0,0,0,,and I have a million cons memory\nDialogue: 0,0:15:33.60,0:15:35.27,EN,,0,0,0,,then I'm only going to run out in a second,\nDialogue: 0,0:15:35.95,0:15:37.00,EN,,0,0,0,,and that's pretty bad.\nDialogue: 0,0:15:38.00,0:15:40.62,EN,,0,0,0,,So what we do to prevent that disaster,\nDialogue: 0,0:15:40.62,0:15:42.19,EN,,0,0,0,,that ecological disaster,\nDialogue: 0,0:15:42.60,0:15:44.30,EN,,0,0,0,,talk about right after questions.\nDialogue: 0,0:15:44.30,0:15:45.26,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:15:51.50,0:15:51.69,EN,,0,0,0,,Yes.\nDialogue: 0,0:15:52.03,0:15:54.67,EN,,0,0,0,,AUDIENCE: In the environment diagrams that we were drawing\nDialogue: 0,0:15:54.67,0:15:58.25,EN,,0,0,0,,we would use the body of procedures,\nDialogue: 0,0:15:58.25,0:16:00.67,EN,,0,0,0,,and you would eventually wind up with\nDialogue: 0,0:16:00.80,0:16:03.60,EN,,0,0,0,,things that were no longer useful in that structure.\nDialogue: 0,0:16:03.60,0:16:04.16,EN,,0,0,0,,PROFESSOR: Yes, madam.\nDialogue: 0,0:16:04.93,0:16:06.67,EN,,0,0,0,,AUDIENCE: How is that represented?\nDialogue: 0,0:16:06.76,0:16:08.75,EN,,0,0,0,,PROFESSOR: There's two problems here. OK?\nDialogue: 0,0:16:09.18,0:16:10.25,EN,,0,0,0,,One you were asking\nDialogue: 0,0:16:10.25,0:16:13.43,EN,,0,0,0,,is that material becomes useless.\nDialogue: 0,0:16:13.87,0:16:14.92,EN,,0,0,0,,We'll talk about that in a second.\nDialogue: 0,0:16:14.92,0:16:17.00,EN,,0,0,0,,That has to do with how to prevent ecological disasters.\nDialogue: 0,0:16:17.63,0:16:19.20,EN,,0,0,0,,Right? If I make a lot of garbage\nDialogue: 0,0:16:19.20,0:16:21.39,EN,,0,0,0,,I have to somehow be able to clean up after myself.\nDialogue: 0,0:16:21.82,0:16:22.97,EN,,0,0,0,,And we'll talk about that in a second.\nDialogue: 0,0:16:23.43,0:16:24.57,EN,,0,0,0,,The other question you're asking\nDialogue: 0,0:16:24.57,0:16:27.21,EN,,0,0,0,,is how you represent the environments, I think.\nDialogue: 0,0:16:27.28,0:16:27.60,EN,,0,0,0,,AUDIENCE: Yes.\nDialogue: 0,0:16:27.60,0:16:28.19,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:16:28.19,0:16:30.62,EN,,0,0,0,,And the environment structures can be represented in arbitrary ways.\nDialogue: 0,0:16:30.92,0:16:31.78,EN,,0,0,0,,There are lots of them.\nDialogue: 0,0:16:31.78,0:16:33.34,EN,,0,0,0,,I mean, here I'm just telling you about list cells.\nDialogue: 0,0:16:33.63,0:16:34.92,EN,,0,0,0,,Of course every real system\nDialogue: 0,0:16:34.92,0:16:36.72,EN,,0,0,0,,has vectors of arbitrary length\nDialogue: 0,0:16:36.72,0:16:39.15,EN,,0,0,0,,as well as the vectors of length, too,\nDialogue: 0,0:16:39.31,0:16:40.51,EN,,0,0,0,,which represent list cells.\nDialogue: 0,0:16:41.08,0:16:44.90,EN,,0,0,0,,And the environment structures that one uses in a\nDialogue: 0,0:16:44.90,0:16:46.99,EN,,0,0,0,,professionally written Lisp system\nDialogue: 0,0:16:47.30,0:16:49.69,EN,,0,0,0,,tend to be vectors\nDialogue: 0,0:16:49.69,0:16:51.92,EN,,0,0,0,,which contain a number of elements approximately\nDialogue: 0,0:16:51.92,0:16:54.60,EN,,0,0,0,,equal to the number of arguments-- a little bit more\nDialogue: 0,0:16:55.35,0:16:56.86,EN,,0,0,0,,because you need sort of glue.\nDialogue: 0,0:16:57.40,0:17:00.74,EN,,0,0,0,,OK? So remember, the environment is in a frame.\nDialogue: 0,0:17:00.74,0:17:03.98,EN,,0,0,0,,The frames are constructed by applying a procedure.\nDialogue: 0,0:17:03.98,0:17:04.78,EN,,0,0,0,,In doing so,\nDialogue: 0,0:17:04.80,0:17:07.60,EN,,0,0,0,,an allocation is made of a place\nDialogue: 0,0:17:07.64,0:17:11.27,EN,,0,0,0,,which is the number of arguments long plus some glue\nDialogue: 0,0:17:11.27,0:17:12.71,EN,,0,0,0,,that gets linked into a chain.\nDialogue: 0,0:17:13.32,0:17:15.66,EN,,0,0,0,,It's just like algol at that level.\nDialogue: 0,0:17:19.81,0:17:20.72,EN,,0,0,0,,There any other questions?\nDialogue: 0,0:17:23.70,0:17:23.92,EN,,0,0,0,,OK.\nDialogue: 0,0:17:23.92,0:17:25.55,EN,,0,0,0,,Thank you, and let's take a short break.\nDialogue: 0,0:17:26.35,0:17:45.48,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:18:12.27,0:18:14.24,EN,,0,0,0,,PROFESSOR: Well, as I just said,\nDialogue: 0,0:18:14.55,0:18:15.50,EN,,0,0,0,,computer memories\nDialogue: 0,0:18:15.82,0:18:17.96,EN,,0,0,0,,supplied by the semiconductor manufacturers\nDialogue: 0,0:18:18.16,0:18:19.00,EN,,0,0,0,,are finite.\nDialogue: 0,0:18:19.42,0:18:20.40,EN,,0,0,0,,And that's quite a pity.\nDialogue: 0,0:18:21.62,0:18:23.35,EN,,0,0,0,,It might not always be that way.\nDialogue: 0,0:18:24.03,0:18:25.40,EN,,0,0,0,,Just for a quick calculation,\nDialogue: 0,0:18:25.44,0:18:28.86,EN,,0,0,0,,you can see that it's possible that if memory's\nDialogue: 0,0:18:28.86,0:18:30.80,EN,,0,0,0,,prices keep going at the rate they're going\nDialogue: 0,0:18:31.22,0:18:33.68,EN,,0,0,0,,that if you still took a microsecond second to do a cons,\nDialogue: 0,0:18:34.42,0:18:35.90,EN,,0,0,0,,then-- first of all, everybody\nDialogue: 0,0:18:35.90,0:18:37.07,EN,,0,0,0,,should know that there's about pi\nDialogue: 0,0:18:37.10,0:18:38.86,EN,,0,0,0,,times ten to the seventh seconds in a year.\nDialogue: 0,0:18:39.45,0:18:41.12,EN,,0,0,0,,And so that would be\nDialogue: 0,0:18:41.50,0:18:42.73,EN,,0,0,0,,ten to the seventh plus ten to the sixth\nDialogue: 0,0:18:42.73,0:18:43.94,EN,,0,0,0,,is ten to the thirteenth.\nDialogue: 0,0:18:43.94,0:18:45.50,EN,,0,0,0,,So there's maybe ten to the fourteenth conses\nDialogue: 0,0:18:45.50,0:18:46.80,EN,,0,0,0,,in the life of a machine.\nDialogue: 0,0:18:47.52,0:18:49.40,EN,,0,0,0,,If there was ten to the fourteenth words of memory\nDialogue: 0,0:18:49.68,0:18:50.57,EN,,0,0,0,,on your machine,\nDialogue: 0,0:18:51.20,0:18:52.16,EN,,0,0,0,,you'd never run out.\nDialogue: 0,0:18:53.04,0:18:53.85,EN,,0,0,0,,OK so that will be,\nDialogue: 0,0:18:53.95,0:18:55.76,EN,,0,0,0,,And that's not completely unreasonable.\nDialogue: 0,0:18:56.31,0:18:58.46,EN,,0,0,0,,Ten to the fourteenth is not a very large number.\nDialogue: 0,0:19:01.45,0:19:04.70,EN,,0,0,0,,Even for... I don't think it is.\nDialogue: 0,0:19:05.18,0:19:07.39,EN,,0,0,0,,But then again I like to play with astronomy.\nDialogue: 0,0:19:07.93,0:19:11.04,EN,,0,0,0,,It's at least ten to the eighteenth centimeters\nDialogue: 0,0:19:11.10,0:19:12.45,EN,,0,0,0,,between us and the nearest star.\nDialogue: 0,0:19:12.93,0:19:18.85,EN,,0,0,0,,But the thing I'm about to worry about is,\nDialogue: 0,0:19:19.15,0:19:21.27,EN,,0,0,0,,at least in the current economic state of affairs,\nDialogue: 0,0:19:21.27,0:19:23.57,EN,,0,0,0,,ten to the fourteenth pieces of memory is expensive.\nDialogue: 0,0:19:24.20,0:19:26.62,EN,,0,0,0,,And so I suppose what we have to do\nDialogue: 0,0:19:26.81,0:19:28.51,EN,,0,0,0,,is make do with much smaller memories.\nDialogue: 0,0:19:30.02,0:19:30.59,EN,,0,0,0,,Now\nDialogue: 0,0:19:32.84,0:19:35.07,EN,,0,0,0,,in general we want to have an illusion of infinity.\nDialogue: 0,0:19:35.80,0:19:37.22,EN,,0,0,0,,All we need to do is arrange it\nDialogue: 0,0:19:37.82,0:19:39.68,EN,,0,0,0,,so that whenever you look, the thing is there.\nDialogue: 0,0:19:41.92,0:19:45.55,EN,,0,0,0,,That's, that's really an important idea.\nDialogue: 0,0:19:49.54,0:19:51.97,EN,,0,0,0,,A person or a computer lives only a finite amount of time\nDialogue: 0,0:19:52.32,0:19:54.59,EN,,0,0,0,,and can only take a finite number of looks at something.\nDialogue: 0,0:19:55.28,0:19:57.37,EN,,0,0,0,,And so you really only need a finite amount of stuff.\nDialogue: 0,0:19:58.19,0:19:59.00,EN,,0,0,0,,But you have to arrange it\nDialogue: 0,0:19:59.00,0:20:00.38,EN,,0,0,0,,so no matter how much there is,\nDialogue: 0,0:20:00.77,0:20:03.46,EN,,0,0,0,,how much you really claim there is,\nDialogue: 0,0:20:03.46,0:20:04.74,EN,,0,0,0,,there's always enough stuff\nDialogue: 0,0:20:04.74,0:20:06.90,EN,,0,0,0,,so that when you take a look, it's there.\nDialogue: 0,0:20:06.90,0:20:08.15,EN,,0,0,0,,And so you only need a finite amount.\nDialogue: 0,0:20:08.75,0:20:09.94,EN,,0,0,0,,But let's see.\nDialogue: 0,0:20:11.63,0:20:13.32,EN,,0,0,0,,One problem is, as was brought up,\nDialogue: 0,0:20:13.92,0:20:15.45,EN,,0,0,0,,that there are possible ways\nDialogue: 0,0:20:15.72,0:20:17.84,EN,,0,0,0,,that there is lots of stuff\nDialogue: 0,0:20:17.88,0:20:19.16,EN,,0,0,0,,that we make that we don't need.\nDialogue: 0,0:20:19.41,0:20:21.81,EN,,0,0,0,,And we could recycle the material out of which its made.\nDialogue: 0,0:20:22.62,0:20:23.53,EN,,0,0,0,,An example\nDialogue: 0,0:20:24.15,0:20:25.79,EN,,0,0,0,,for is, is the fact\nDialogue: 0,0:20:25.79,0:20:28.40,EN,,0,0,0,,when we're building environment structures,\nDialogue: 0,0:20:28.40,0:20:30.47,EN,,0,0,0,,and we do so every time we call a procedure.\nDialogue: 0,0:20:30.47,0:20:32.56,EN,,0,0,0,,We have built in it a environment frame.\nDialogue: 0,0:20:33.14,0:20:34.03,EN,,0,0,0,,That environment frame\nDialogue: 0,0:20:34.22,0:20:36.07,EN,,0,0,0,,doesn't necessarily have a very long lifetime.\nDialogue: 0,0:20:36.73,0:20:38.69,EN,,0,0,0,,Its lifetime, meaning its usefulness,\nDialogue: 0,0:20:39.42,0:20:42.60,EN,,0,0,0,,may exist only over the invocation of the procedure.\nDialogue: 0,0:20:42.85,0:20:45.27,EN,,0,0,0,,Or if the procedure exports another procedure\nDialogue: 0,0:20:45.27,0:20:46.67,EN,,0,0,0,,by returning it as a value\nDialogue: 0,0:20:46.87,0:20:48.52,EN,,0,0,0,,and that procedure is defined inside of it,\nDialogue: 0,0:20:48.52,0:20:50.80,EN,,0,0,0,,well then the lifetime of the\nDialogue: 0,0:20:51.07,0:20:53.39,EN,,0,0,0,,frame of the outer procedure still is\nDialogue: 0,0:20:53.50,0:20:56.12,EN,,0,0,0,,only the lifetime of the procedure\nDialogue: 0,0:20:57.02,0:20:57.90,EN,,0,0,0,,which was exported.\nDialogue: 0,0:20:58.53,0:20:59.57,EN,,0,0,0,,And so ultimately,\nDialogue: 0,0:20:59.57,0:21:00.97,EN,,0,0,0,,a lot of that is garbage.\nDialogue: 0,0:21:01.96,0:21:04.10,EN,,0,0,0,,There are other ways of producing garbage as well.\nDialogue: 0,0:21:05.37,0:21:06.67,EN,,0,0,0,,Users produce garbage.\nDialogue: 0,0:21:07.24,0:21:08.07,EN,,0,0,0,,An example of\nDialogue: 0,0:21:08.07,0:21:10.22,EN,,0,0,0,,user garbage is something like this.\nDialogue: 0,0:21:10.93,0:21:14.00,EN,,0,0,0,,If we write a program to, for example,\nDialogue: 0,0:21:14.00,0:21:15.80,EN,,0,0,0,,append two lists together,\nDialogue: 0,0:21:16.05,0:21:18.14,EN,,0,0,0,,well one way to do it is to\nDialogue: 0,0:21:18.32,0:21:21.37,EN,,0,0,0,,reverse the first list onto the empty list\nDialogue: 0,0:21:21.37,0:21:23.72,EN,,0,0,0,,and reverse that onto the second list.\nDialogue: 0,0:21:24.70,0:21:26.92,EN,,0,0,0,,Now that's not terribly bad way of doing it.\nDialogue: 0,0:21:28.16,0:21:28.85,EN,,0,0,0,,And however,\nDialogue: 0,0:21:28.85,0:21:30.09,EN,,0,0,0,,the intermediate result,\nDialogue: 0,0:21:30.11,0:21:32.02,EN,,0,0,0,,which is the reversal of the first list\nDialogue: 0,0:21:33.87,0:21:35.57,EN,,0,0,0,,as done by this program,\nDialogue: 0,0:21:36.70,0:21:38.52,EN,,0,0,0,,is never going to be accessed ever again\nDialogue: 0,0:21:38.52,0:21:40.56,EN,,0,0,0,,after it's copied back on to the second.\nDialogue: 0,0:21:41.01,0:21:42.23,EN,,0,0,0,,It's an intermediate result.\nDialogue: 0,0:21:43.58,0:21:45.43,EN,,0,0,0,,It's going to be hard to ever see\nDialogue: 0,0:21:46.07,0:21:48.05,EN,,0,0,0,,how anybody would ever be able to access it.\nDialogue: 0,0:21:48.60,0:21:49.84,EN,,0,0,0,,In fact, it will go away.\nDialogue: 0,0:21:51.05,0:21:52.90,EN,,0,0,0,,Now if we make a lot of garbage like that,\nDialogue: 0,0:21:52.90,0:21:54.20,EN,,0,0,0,,and we should be allowed to,\nDialogue: 0,0:21:54.80,0:21:57.29,EN,,0,0,0,,then there's got to be some way to reclaim that garbage.\nDialogue: 0,0:21:58.80,0:22:00.90,EN,,0,0,0,,Well, what I'd like to tell you about now\nDialogue: 0,0:22:01.70,0:22:03.77,EN,,0,0,0,,is a very clever technique\nDialogue: 0,0:22:04.32,0:22:07.58,EN,,0,0,0,,whereby a Lisp system\nDialogue: 0,0:22:07.95,0:22:11.21,EN,,0,0,0,,can prove a small theorem every so often\nDialogue: 0,0:22:11.29,0:22:13.50,EN,,0,0,0,,on the form the following piece of junk\nDialogue: 0,0:22:14.72,0:22:16.09,EN,,0,0,0,,will never be accessed again.\nDialogue: 0,0:22:17.41,0:22:19.80,EN,,0,0,0,,It can have no affect on the future of the computation.\nDialogue: 0,0:22:21.40,0:22:23.61,EN,,0,0,0,,It's actually based on a very simple idea.\nDialogue: 0,0:22:24.72,0:22:28.06,EN,,0,0,0,,We've designed our computers to look sort of like this.\nDialogue: 0,0:22:28.95,0:22:30.67,EN,,0,0,0,,There's some data path,\nDialogue: 0,0:22:31.87,0:22:33.40,EN,,0,0,0,,which contains the registers.\nDialogue: 0,0:22:34.92,0:22:38.04,EN,,0,0,0,,You know, there are things like exp, and env,\nDialogue: 0,0:22:39.04,0:22:42.19,EN,,0,0,0,,and val, and so on.\nDialogue: 0,0:22:42.61,0:22:44.02,EN,,0,0,0,,And there's one here called stack,\nDialogue: 0,0:22:46.02,0:22:49.45,EN,,0,0,0,,some sort which points off to a structure somewhere,\nDialogue: 0,0:22:49.50,0:22:50.22,EN,,0,0,0,,which is the stack.\nDialogue: 0,0:22:50.24,0:22:51.48,EN,,0,0,0,,And we'll worry about that in a second.\nDialogue: 0,0:22:51.64,0:22:53.62,EN,,0,0,0,,There's some finite controller,\nDialogue: 0,0:22:54.38,0:22:56.57,EN,,0,0,0,,finite state machine controller.\nDialogue: 0,0:22:56.73,0:22:59.51,EN,,0,0,0,,And there's some control signals that go this way and\nDialogue: 0,0:22:59.80,0:23:01.44,EN,,0,0,0,,predicate results that come this way,\nDialogue: 0,0:23:01.87,0:23:03.13,EN,,0,0,0,,not the interesting part.\nDialogue: 0,0:23:03.35,0:23:06.51,EN,,0,0,0,,There's some sort of structured memory,\nDialogue: 0,0:23:06.80,0:23:08.27,EN,,0,0,0,,which I just told you how to make,\nDialogue: 0,0:23:08.27,0:23:10.17,EN,,0,0,0,,which may contain a stack.\nDialogue: 0,0:23:10.46,0:23:11.48,EN,,0,0,0,,I didn't tell you how to make things\nDialogue: 0,0:23:11.48,0:23:12.43,EN,,0,0,0,,of arbitrary shape,\nDialogue: 0,0:23:12.56,0:23:13.39,EN,,0,0,0,,only pairs.\nDialogue: 0,0:23:13.60,0:23:14.20,EN,,0,0,0,,But in fact\nDialogue: 0,0:23:14.35,0:23:15.44,EN,,0,0,0,,with what I've told you can\nDialogue: 0,0:23:15.47,0:23:16.96,EN,,0,0,0,,with what I've told you can simulate a stack by a big list.\nDialogue: 0,0:23:17.77,0:23:18.85,EN,,0,0,0,,I don't plan to do that,\nDialogue: 0,0:23:18.85,0:23:20.01,EN,,0,0,0,,it's not a nice way to do it.\nDialogue: 0,0:23:20.36,0:23:22.60,EN,,0,0,0,,But we could have something like that.\nDialogue: 0,0:23:22.99,0:23:25.28,EN,,0,0,0,,We have all sorts of little data structures in here\nDialogue: 0,0:23:25.64,0:23:27.75,EN,,0,0,0,,that are hooked together in funny ways.\nDialogue: 0,0:23:30.11,0:23:32.02,EN,,0,0,0,,They connect to other things.\nDialogue: 0,0:23:32.56,0:23:33.25,EN,,0,0,0,,And so on.\nDialogue: 0,0:23:33.25,0:23:34.22,EN,,0,0,0,,And ultimately\nDialogue: 0,0:23:34.45,0:23:37.19,EN,,0,0,0,,things up there are pointers to these.\nDialogue: 0,0:23:37.19,0:23:38.87,EN,,0,0,0,,The things that are in the registers\nDialogue: 0,0:23:39.40,0:23:41.40,EN,,0,0,0,,are pointers off to the data structures\nDialogue: 0,0:23:41.44,0:23:43.08,EN,,0,0,0,,that live in this list structure memory.\nDialogue: 0,0:23:44.91,0:23:49.80,EN,,0,0,0,,Now the truth of the matter is\nDialogue: 0,0:23:51.05,0:23:52.56,EN,,0,0,0,,that the entire consciousness\nDialogue: 0,0:23:52.57,0:23:53.92,EN,,0,0,0,,of this machine is in these registers.\nDialogue: 0,0:23:55.76,0:23:58.51,EN,,0,0,0,,There is no possible way that the machine,\nDialogue: 0,0:23:58.75,0:24:01.07,EN,,0,0,0,,if done correctly, if built correctly,\nDialogue: 0,0:24:01.37,0:24:03.41,EN,,0,0,0,,can access anything in this list structure memory\nDialogue: 0,0:24:04.57,0:24:07.05,EN,,0,0,0,,unless the thing in that list structure memory is\nDialogue: 0,0:24:08.09,0:24:10.88,EN,,0,0,0,,is connected by a sequence of data structures\nDialogue: 0,0:24:11.64,0:24:13.06,EN,,0,0,0,,to the registers.\nDialogue: 0,0:24:15.07,0:24:15.98,EN,,0,0,0,,If it's accessible\nDialogue: 0,0:24:16.22,0:24:18.31,EN,,0,0,0,,by legitimate data structure selectors\nDialogue: 0,0:24:19.08,0:24:21.12,EN,,0,0,0,,from the pointers that are stored in these registers.\nDialogue: 0,0:24:22.28,0:24:24.46,EN,,0,0,0,,Things like array references, perhaps.\nDialogue: 0,0:24:24.94,0:24:27.92,EN,,0,0,0,,Or cons cell references, cars and cdrs.\nDialogue: 0,0:24:29.08,0:24:30.95,EN,,0,0,0,,But I can't just talk about a random place in this memory,\nDialogue: 0,0:24:30.95,0:24:31.95,EN,,0,0,0,,because I can't get to it.\nDialogue: 0,0:24:32.74,0:24:34.90,EN,,0,0,0,,These are being arbitrary names I'm not allowed to count,\nDialogue: 0,0:24:37.00,0:24:39.16,EN,,0,0,0,,at least as I'm evaluating expressions.\nDialogue: 0,0:24:41.62,0:24:42.57,EN,,0,0,0,,If that's the case\nDialogue: 0,0:24:43.27,0:24:45.07,EN,,0,0,0,,then there's a very simple theorem to be proved.\nDialogue: 0,0:24:47.16,0:24:47.69,EN,,0,0,0,,Which is,\nDialogue: 0,0:24:47.90,0:24:50.52,EN,,0,0,0,,if I start with all lead pointers that are in all these registers\nDialogue: 0,0:24:51.16,0:24:52.55,EN,,0,0,0,,and recursively chase out,\nDialogue: 0,0:24:52.82,0:24:56.15,EN,,0,0,0,,marking all the places I can get to by selectors,\nDialogue: 0,0:24:56.90,0:24:59.40,EN,,0,0,0,,then eventually I mark everything they can be gotten to.\nDialogue: 0,0:25:00.65,0:25:02.69,EN,,0,0,0,,Anything which is not so marked is garbage\nDialogue: 0,0:25:02.69,0:25:03.75,EN,,0,0,0,,and can be recycled.\nDialogue: 0,0:25:05.56,0:25:06.20,EN,,0,0,0,,Very simple.\nDialogue: 0,0:25:07.20,0:25:09.10,EN,,0,0,0,,Cannot affect the future of the computation.\nDialogue: 0,0:25:11.18,0:25:12.84,EN,,0,0,0,,So let me show you that in a particular\nDialogue: 0,0:25:13.93,0:25:15.75,EN,,0,0,0,,in a particular example.\nDialogue: 0,0:25:17.12,0:25:19.37,EN,,0,0,0,,Now that means I'm going to have to append to my\nDialogue: 0,0:25:19.69,0:25:22.08,EN,,0,0,0,,description of the list structure a mark.\nDialogue: 0,0:25:23.64,0:25:24.89,EN,,0,0,0,,And so here, for example,\nDialogue: 0,0:25:25.37,0:25:27.28,EN,,0,0,0,,is a list structured memory.\nDialogue: 0,0:25:29.08,0:25:30.32,EN,,0,0,0,,And in this list structured memory\nDialogue: 0,0:25:30.33,0:25:31.33,EN,,0,0,0,,is a list structure\nDialogue: 0,0:25:31.33,0:25:33.95,EN,,0,0,0,,beginning in a place I'm going to call--\nDialogue: 0,0:25:35.87,0:25:36.62,EN,,0,0,0,,this is the root.\nDialogue: 0,0:25:38.59,0:25:40.12,EN,,0,0,0,,Now it doesn't really have to have a root.\nDialogue: 0,0:25:40.12,0:25:41.95,EN,,0,0,0,,It could be a bunch of them, like all the registers.\nDialogue: 0,0:25:42.67,0:25:43.98,EN,,0,0,0,,But I could cleverly arrange it\nDialogue: 0,0:25:44.13,0:25:46.30,EN,,0,0,0,,so all the registers, all the things that are in old registers\nDialogue: 0,0:25:46.30,0:25:47.77,EN,,0,0,0,,are also at the right moment\nDialogue: 0,0:25:48.28,0:25:50.46,EN,,0,0,0,,put into this root structure,\nDialogue: 0,0:25:50.46,0:25:51.85,EN,,0,0,0,,and then we've got one pointer to it.\nDialogue: 0,0:25:51.85,0:25:52.67,EN,,0,0,0,,I don't really care.\nDialogue: 0,0:25:54.57,0:25:55.63,EN,,0,0,0,,So the idea is\nDialogue: 0,0:25:55.64,0:25:56.65,EN,,0,0,0,,we're going to cons up stuff\nDialogue: 0,0:25:56.67,0:25:58.01,EN,,0,0,0,,until our free list is empty.\nDialogue: 0,0:25:58.72,0:25:59.67,EN,,0,0,0,,We've run out of things.\nDialogue: 0,0:26:00.95,0:26:04.47,EN,,0,0,0,,Now we're going to do this process of proving the theorem\nDialogue: 0,0:26:04.47,0:26:05.90,EN,,0,0,0,,that a certain percentage of the memory\nDialogue: 0,0:26:05.95,0:26:06.90,EN,,0,0,0,,is got crap in it.\nDialogue: 0,0:26:07.85,0:26:09.15,EN,,0,0,0,,And then we're going to recycle that\nDialogue: 0,0:26:09.78,0:26:10.87,EN,,0,0,0,,to grow new trees,\nDialogue: 0,0:26:12.19,0:26:14.57,EN,,0,0,0,,a standard use of such garbage.\nDialogue: 0,0:26:17.09,0:26:18.64,EN,,0,0,0,,So in any case, what do we have here?\nDialogue: 0,0:26:18.84,0:26:20.78,EN,,0,0,0,,Well we have some data structure\nDialogue: 0,0:26:20.89,0:26:24.27,EN,,0,0,0,,which starts out over here in p5.\nDialogue: 0,0:26:25.15,0:26:26.75,EN,,0,0,0,,Sorry, and it will start at one\nDialogue: 0,0:26:27.27,0:26:28.51,EN,,0,0,0,,And in fact\nDialogue: 0,0:26:28.89,0:26:32.20,EN,,0,0,0,,it has a car in p5,\nDialogue: 0,0:26:32.27,0:26:33.58,EN,,0,0,0,,and its cdr is in two.\nDialogue: 0,0:26:33.98,0:26:35.64,EN,,0,0,0,,And all the marks start out at zero.\nDialogue: 0,0:26:36.70,0:26:39.00,EN,,0,0,0,,Well let's start marking, just to play this game.\nDialogue: 0,0:26:39.92,0:26:40.52,EN,,0,0,0,,OK.\nDialogue: 0,0:26:42.54,0:26:44.27,EN,,0,0,0,,So for example,\nDialogue: 0,0:26:44.47,0:26:46.95,EN,,0,0,0,,since I can access one from the root\nDialogue: 0,0:26:46.95,0:26:47.82,EN,,0,0,0,,I will mark that.\nDialogue: 0,0:26:48.39,0:26:49.17,EN,,0,0,0,,Let me mark it.\nDialogue: 0,0:26:50.96,0:26:51.45,EN,,0,0,0,,Bang.\nDialogue: 0,0:26:52.22,0:26:52.94,EN,,0,0,0,,That's marked.\nDialogue: 0,0:26:54.41,0:26:57.51,EN,,0,0,0,,OK. Now since I have a five here\nDialogue: 0,0:26:57.64,0:26:58.64,EN,,0,0,0,,I can go to five\nDialogue: 0,0:26:59.02,0:27:00.72,EN,,0,0,0,,and see, well I'll mark that.\nDialogue: 0,0:27:01.45,0:27:01.76,EN,,0,0,0,,Bang.\nDialogue: 0,0:27:01.76,0:27:02.60,EN,,0,0,0,,That's useful stuff.\nDialogue: 0,0:27:02.90,0:27:05.10,EN,,0,0,0,,But five references as a number in its car,\nDialogue: 0,0:27:05.27,0:27:06.65,EN,,0,0,0,,I'm not interested in marking numbers\nDialogue: 0,0:27:06.91,0:27:08.17,EN,,0,0,0,,but its cdr is seven.\nDialogue: 0,0:27:08.70,0:27:09.75,EN,,0,0,0,,So I can mark that.\nDialogue: 0,0:27:10.45,0:27:10.81,EN,,0,0,0,,Bang.\nDialogue: 0,0:27:11.80,0:27:13.40,EN,,0,0,0,,OK? Seven is the empty list,\nDialogue: 0,0:27:13.67,0:27:15.10,EN,,0,0,0,,the only thing that references,\nDialogue: 0,0:27:15.59,0:27:17.12,EN,,0,0,0,,and it's got a number in its car.\nDialogue: 0,0:27:17.12,0:27:17.85,EN,,0,0,0,,Not interesting.\nDialogue: 0,0:27:19.49,0:27:20.50,EN,,0,0,0,,Well now let's go back here.\nDialogue: 0,0:27:20.50,0:27:21.65,EN,,0,0,0,,I forgot about something.\nDialogue: 0,0:27:21.65,0:27:22.17,EN,,0,0,0,,Two.\nDialogue: 0,0:27:22.84,0:27:24.85,EN,,0,0,0,,See in other words, if I'm looking at cell one,\nDialogue: 0,0:27:25.42,0:27:29.45,EN,,0,0,0,,cell one contains a two right over here.\nDialogue: 0,0:27:30.37,0:27:31.30,EN,,0,0,0,,A reference to two.\nDialogue: 0,0:27:32.01,0:27:34.97,EN,,0,0,0,,That means I should go mark two.\nDialogue: 0,0:27:35.70,0:27:36.27,EN,,0,0,0,,Bang.\nDialogue: 0,0:27:37.14,0:27:38.89,EN,,0,0,0,,Two contains a reference to four.\nDialogue: 0,0:27:39.13,0:27:40.27,EN,,0,0,0,,It's got a number in its car,\nDialogue: 0,0:27:40.27,0:27:41.20,EN,,0,0,0,,I'm not interested in that\nDialogue: 0,0:27:41.47,0:27:42.60,EN,,0,0,0,,so I'm going to go mark that.\nDialogue: 0,0:27:43.78,0:27:46.10,EN,,0,0,0,,Four refers to seven through its car,\nDialogue: 0,0:27:46.75,0:27:48.17,EN,,0,0,0,,and is empty in its cdr,\nDialogue: 0,0:27:48.47,0:27:49.57,EN,,0,0,0,,but I've already marked that one\nDialogue: 0,0:27:49.57,0:27:50.75,EN,,0,0,0,,so I don't have to mark it again.\nDialogue: 0,0:27:51.40,0:27:53.05,EN,,0,0,0,,This is all the accessible structure\nDialogue: 0,0:27:53.07,0:27:53.87,EN,,0,0,0,,from that place.\nDialogue: 0,0:27:55.00,0:27:56.57,EN,,0,0,0,,Simple recursive mark algorithm.\nDialogue: 0,0:27:58.71,0:28:01.79,EN,,0,0,0,,Now there are some unhappinesses about that algorithm,\nDialogue: 0,0:28:01.90,0:28:04.02,EN,,0,0,0,,and we can worry about that a second.\nDialogue: 0,0:28:04.92,0:28:06.16,EN,,0,0,0,,But basically you'll see\nDialogue: 0,0:28:06.19,0:28:07.85,EN,,0,0,0,,that all the things that have not been marked\nDialogue: 0,0:28:09.62,0:28:11.50,EN,,0,0,0,,are places that are free,\nDialogue: 0,0:28:11.50,0:28:12.41,EN,,0,0,0,,and I could recycle.\nDialogue: 0,0:28:14.25,0:28:15.75,EN,,0,0,0,,So the next stage after that is going to be\nDialogue: 0,0:28:15.75,0:28:17.05,EN,,0,0,0,,to scan through all of my memory,\nDialogue: 0,0:28:17.94,0:28:20.35,EN,,0,0,0,,looking for things that are not marked.\nDialogue: 0,0:28:21.18,0:28:22.45,EN,,0,0,0,,Every time I come across a marked thing\nDialogue: 0,0:28:22.45,0:28:23.22,EN,,0,0,0,,I unmark it,\nDialogue: 0,0:28:23.22,0:28:24.86,EN,,0,0,0,,and every time I come across an unmarked thing\nDialogue: 0,0:28:25.07,0:28:27.82,EN,,0,0,0,,I'm going to link it together in my free list.\nDialogue: 0,0:28:28.77,0:28:30.30,EN,,0,0,0,,Classic, very simple algorithm.\nDialogue: 0,0:28:32.12,0:28:33.10,EN,,0,0,0,,So let's see.\nDialogue: 0,0:28:33.84,0:28:34.77,EN,,0,0,0,,Is that very simple?\nDialogue: 0,0:28:34.77,0:28:35.42,EN,,0,0,0,,Yes it is.\nDialogue: 0,0:28:35.57,0:28:37.79,EN,,0,0,0,,I'm not going to go through the code in any detail,\nDialogue: 0,0:28:38.00,0:28:39.65,EN,,0,0,0,,but I just want to show you about how long it is.\nDialogue: 0,0:28:40.09,0:28:41.10,EN,,0,0,0,,Let's look at the mark phase.\nDialogue: 0,0:28:41.72,0:28:43.98,EN,,0,0,0,,Here's the first part of the mark phase.\nDialogue: 0,0:28:45.06,0:28:46.00,EN,,0,0,0,,We pick up the root.\nDialogue: 0,0:28:46.32,0:28:47.52,EN,,0,0,0,,We're going to do some\nDialogue: 0,0:28:47.67,0:28:51.05,EN,,0,0,0,,We're going to use that as a recursive procedure call.\nDialogue: 0,0:28:52.38,0:28:54.47,EN,,0,0,0,,We're going to sweep from there,\nDialogue: 0,0:28:54.77,0:28:56.95,EN,,0,0,0,,after when we're done with marking.\nDialogue: 0,0:28:57.38,0:28:59.79,EN,,0,0,0,,And then we're going to do a little couple of instructions\nDialogue: 0,0:28:59.80,0:29:01.36,EN,,0,0,0,,that do this checking out on the marks\nDialogue: 0,0:29:01.39,0:29:03.07,EN,,0,0,0,,and changing the marks and things like that,\nDialogue: 0,0:29:03.07,0:29:04.90,EN,,0,0,0,,according to the algorithm I've just shown you.\nDialogue: 0,0:29:05.23,0:29:06.47,EN,,0,0,0,,OK? It comes out here.\nDialogue: 0,0:29:06.47,0:29:07.65,EN,,0,0,0,,You have to mark the cars of things\nDialogue: 0,0:29:07.87,0:29:10.21,EN,,0,0,0,,and you also have to be able to mark the cdrs of things.\nDialogue: 0,0:29:10.66,0:29:12.10,EN,,0,0,0,,That's the entire mark phase.\nDialogue: 0,0:29:14.37,0:29:16.16,EN,,0,0,0,,I'll just tell you a little story about this.\nDialogue: 0,0:29:16.59,0:29:19.37,EN,,0,0,0,,The old DEC PDP-6 computer,\nDialogue: 0,0:29:20.93,0:29:22.09,EN,,0,0,0,,this was the way that\nDialogue: 0,0:29:22.35,0:29:24.85,EN,,0,0,0,,the mark-sweep garbage collection, as it was, was written.\nDialogue: 0,0:29:26.91,0:29:28.40,EN,,0,0,0,,The program was so small\nDialogue: 0,0:29:29.25,0:29:31.60,EN,,0,0,0,,that with the data that it needed,\nDialogue: 0,0:29:32.20,0:29:34.87,EN,,0,0,0,,with the registers that it needed to manipulate the memory,\nDialogue: 0,0:29:36.16,0:29:38.14,EN,,0,0,0,,it fit into the fast registers of the machine,\nDialogue: 0,0:29:38.16,0:29:38.97,EN,,0,0,0,,which were 16.\nDialogue: 0,0:29:39.28,0:29:39.80,EN,,0,0,0,,The whole program.\nDialogue: 0,0:29:40.01,0:29:42.01,EN,,0,0,0,,And you could execute instructions in the fast registers.\nDialogue: 0,0:29:43.17,0:29:44.83,EN,,0,0,0,,So it's an extremely small program,\nDialogue: 0,0:29:45.85,0:29:46.88,EN,,0,0,0,,and it could run very fast.\nDialogue: 0,0:29:48.87,0:29:51.30,EN,,0,0,0,,Now unfortunately, of course,\nDialogue: 0,0:29:51.61,0:29:54.02,EN,,0,0,0,,this program, because the fact that it's recursive\nDialogue: 0,0:29:54.80,0:29:57.55,EN,,0,0,0,,in the way that you do something first\nDialogue: 0,0:29:57.55,0:29:58.99,EN,,0,0,0,,and then you do something after that,\nDialogue: 0,0:29:59.21,0:30:00.88,EN,,0,0,0,,you have to work on the cars and then the cdrs,\nDialogue: 0,0:30:01.15,0:30:02.75,EN,,0,0,0,,it requires auxiliary memory.\nDialogue: 0,0:30:03.41,0:30:05.23,EN,,0,0,0,,So Lisp systems--\nDialogue: 0,0:30:05.44,0:30:07.42,EN,,0,0,0,,those requires a stack for marking.\nDialogue: 0,0:30:08.26,0:30:11.05,EN,,0,0,0,,Lisp systems that are built this way\nDialogue: 0,0:30:11.57,0:30:14.16,EN,,0,0,0,,have a limit to the depth of recursion you can have\nDialogue: 0,0:30:14.42,0:30:17.37,EN,,0,0,0,,in data structures in either the car or the cdr,\nDialogue: 0,0:30:17.81,0:30:19.35,EN,,0,0,0,,and that doesn't work very nicely.\nDialogue: 0,0:30:19.93,0:30:20.60,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:30:20.64,0:30:22.12,EN,,0,0,0,,you never notice it if it's big enough.\nDialogue: 0,0:30:23.18,0:30:25.13,EN,,0,0,0,,And that's certainly been\nDialogue: 0,0:30:25.55,0:30:28.17,EN,,0,0,0,,the case for most Maclisp, for example,\nDialogue: 0,0:30:28.69,0:30:29.88,EN,,0,0,0,,which ran Macsyma\nDialogue: 0,0:30:29.96,0:30:31.10,EN,,0,0,0,,where you could deal with expressions\nDialogue: 0,0:30:31.10,0:30:32.72,EN,,0,0,0,,of thousands of elements long.\nDialogue: 0,0:30:33.56,0:30:36.02,EN,,0,0,0,,These are algebraic expressions with thousand of terms.\nDialogue: 0,0:30:36.82,0:30:38.10,EN,,0,0,0,,And there's no problem with that.\nDialogue: 0,0:30:39.49,0:30:40.82,EN,,0,0,0,,Such, the garbage collector does work.\nDialogue: 0,0:30:42.19,0:30:42.92,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:30:42.92,0:30:45.37,EN,,0,0,0,,there's a very clever modification to this algorithm,\nDialogue: 0,0:30:45.37,0:30:46.47,EN,,0,0,0,,which I will not describe,\nDialogue: 0,0:30:46.80,0:30:48.22,EN,,0,0,0,,by Peter Deutsch and Schorr and Waite--\nDialogue: 0,0:30:48.64,0:30:51.82,EN,,0,0,0,,and Schorr and Waite, Herb Schorr from IBM\nDialogue: 0,0:30:51.87,0:30:53.52,EN,,0,0,0,,and Waite who I don't know.\nDialogue: 0,0:30:54.01,0:30:56.51,EN,,0,0,0,,Whrere... That algorithm\nDialogue: 0,0:30:56.67,0:30:57.79,EN,,0,0,0,,allows you build\nDialogue: 0,0:30:57.84,0:30:59.55,EN,,0,0,0,,you do can do this without auxiliary memory,\nDialogue: 0,0:31:00.50,0:31:02.80,EN,,0,0,0,,by remembering as you walk the data structures\nDialogue: 0,0:31:02.97,0:31:05.52,EN,,0,0,0,,where you came from by reversing the pointers as you go down\nDialogue: 0,0:31:05.52,0:31:07.52,EN,,0,0,0,,and crawling up the reverse pointers as you go up.\nDialogue: 0,0:31:07.79,0:31:08.99,EN,,0,0,0,,It's a rather tricky algorithm.\nDialogue: 0,0:31:09.13,0:31:10.24,EN,,0,0,0,,The first time you write it--\nDialogue: 0,0:31:10.25,0:31:11.71,EN,,0,0,0,,or in fact, the first three times you write it it\nDialogue: 0,0:31:11.71,0:31:12.72,EN,,0,0,0,,it has a terrible bug in it.\nDialogue: 0,0:31:14.35,0:31:16.72,EN,,0,0,0,,And it's also about, it's quite rather slow,\nDialogue: 0,0:31:16.72,0:31:17.67,EN,,0,0,0,,because it's complicated.\nDialogue: 0,0:31:18.11,0:31:20.30,EN,,0,0,0,,It takes about six times as many memory references\nDialogue: 0,0:31:20.85,0:31:23.22,EN,,0,0,0,,to do the sorts of things that we're talking about.\nDialogue: 0,0:31:24.58,0:31:27.07,EN,,0,0,0,,Well now once I've done this marking phase,\nDialogue: 0,0:31:27.50,0:31:30.12,EN,,0,0,0,,and I get into a position where things look like this,\nDialogue: 0,0:31:30.17,0:31:31.26,EN,,0,0,0,,let's look-- yes.\nDialogue: 0,0:31:31.51,0:31:34.03,EN,,0,0,0,,Here we have the mark done,\nDialogue: 0,0:31:34.08,0:31:35.00,EN,,0,0,0,,just as I did it.\nDialogue: 0,0:31:35.59,0:31:37.33,EN,,0,0,0,,Now we have to perform the sweep phase.\nDialogue: 0,0:31:37.60,0:31:39.32,EN,,0,0,0,,And I described to you what this sweep is like.\nDialogue: 0,0:31:39.82,0:31:42.34,EN,,0,0,0,,I'm going to walk down from one end of memory or the other,\nDialogue: 0,0:31:42.34,0:31:43.34,EN,,0,0,0,,I don't care where,\nDialogue: 0,0:31:43.62,0:31:46.17,EN,,0,0,0,,scanning every cell that's in the memory.\nDialogue: 0,0:31:47.17,0:31:48.67,EN,,0,0,0,,And as I scan these cells,\nDialogue: 0,0:31:49.20,0:31:50.97,EN,,0,0,0,,I'm going to link them together,\nDialogue: 0,0:31:50.99,0:31:52.84,EN,,0,0,0,,if they are free, into the free list.\nDialogue: 0,0:31:53.15,0:31:54.05,EN,,0,0,0,,And if they're not free,\nDialogue: 0,0:31:54.05,0:31:56.07,EN,,0,0,0,,I'm going to unmark them so the marks become zero.\nDialogue: 0,0:31:57.50,0:31:58.57,EN,,0,0,0,,And in fact what I get--\nDialogue: 0,0:31:58.70,0:32:00.46,EN,,0,0,0,,well the program is not very complicated.\nDialogue: 0,0:32:00.46,0:32:02.22,EN,,0,0,0,,It looks sort of like this-- it's a little longer.\nDialogue: 0,0:32:02.78,0:32:04.17,EN,,0,0,0,,Here's the first piece of it.\nDialogue: 0,0:32:04.82,0:32:06.71,EN,,0,0,0,,This one's coming down from the top of memory.\nDialogue: 0,0:32:06.71,0:32:09.58,EN,,0,0,0,,I don't want you to try to understand this at this point.\nDialogue: 0,0:32:09.58,0:32:10.55,EN,,0,0,0,,It's rather simple.\nDialogue: 0,0:32:11.03,0:32:12.52,EN,,0,0,0,,It's a very simple algorithm,\nDialogue: 0,0:32:13.07,0:32:15.97,EN,,0,0,0,,but there's pieces of it that just sort of look like this.\nDialogue: 0,0:32:15.97,0:32:17.37,EN,,0,0,0,,They're all sort of obvious.\nDialogue: 0,0:32:18.60,0:32:20.08,EN,,0,0,0,,And after we've done the sweep,\nDialogue: 0,0:32:20.30,0:32:21.77,EN,,0,0,0,,we get an answer that looks like that.\nDialogue: 0,0:32:25.33,0:32:26.54,EN,,0,0,0,,Now there are some disadvantages\nDialogue: 0,0:32:26.56,0:32:28.20,EN,,0,0,0,,with mark-sweep algorithms of this sort.\nDialogue: 0,0:32:29.59,0:32:30.35,EN,,0,0,0,,Serious ones.\nDialogue: 0,0:32:31.45,0:32:33.20,EN,,0,0,0,,One important disadvantage is\nDialogue: 0,0:32:33.20,0:32:34.97,EN,,0,0,0,,that your memories get larger and larger.\nDialogue: 0,0:32:36.82,0:32:38.87,EN,,0,0,0,,As you say, address spaces get larger and larger,\nDialogue: 0,0:32:38.87,0:32:40.80,EN,,0,0,0,,you're willing to represent more and more stuff,\nDialogue: 0,0:32:41.37,0:32:44.52,EN,,0,0,0,,then it gets very costly to scan all of memory.\nDialogue: 0,0:32:46.36,0:32:47.39,EN,,0,0,0,,What you'd really like to do\nDialogue: 0,0:32:47.40,0:32:48.68,EN,,0,0,0,,is only scan useful stuff.\nDialogue: 0,0:32:50.49,0:32:51.55,EN,,0,0,0,,It would even be better\nDialogue: 0,0:32:52.07,0:32:53.90,EN,,0,0,0,,if you realized that some stuff\nDialogue: 0,0:32:54.48,0:32:57.72,EN,,0,0,0,,was known to be good and useful,\nDialogue: 0,0:32:58.28,0:33:00.37,EN,,0,0,0,,and you don't have to look at it more than once or twice.\nDialogue: 0,0:33:00.37,0:33:01.20,EN,,0,0,0,,Or very rarely.\nDialogue: 0,0:33:01.55,0:33:04.32,EN,,0,0,0,,Whereas other stuff that you're not so sure about,\nDialogue: 0,0:33:05.00,0:33:06.22,EN,,0,0,0,,you can look at more detail\nDialogue: 0,0:33:07.10,0:33:08.75,EN,,0,0,0,,every time you want to do this,\nDialogue: 0,0:33:09.93,0:33:10.85,EN,,0,0,0,,want to garbage collect.\nDialogue: 0,0:33:11.91,0:33:13.74,EN,,0,0,0,,Well there are algorithms\nDialogue: 0,0:33:13.76,0:33:15.10,EN,,0,0,0,,that are organized in this way.\nDialogue: 0,0:33:15.66,0:33:18.16,EN,,0,0,0,,Let me tell you about a famous old algorithm\nDialogue: 0,0:33:18.28,0:33:19.47,EN,,0,0,0,,which allows you only look at\nDialogue: 0,0:33:19.50,0:33:21.37,EN,,0,0,0,,the part of memory which is known to be useful.\nDialogue: 0,0:33:23.12,0:33:23.85,EN,,0,0,0,,And which happens to be\nDialogue: 0,0:33:23.87,0:33:25.29,EN,,0,0,0,,the fastest known garbage collector algorithm.\nDialogue: 0,0:33:26.31,0:33:29.45,EN,,0,0,0,,This is the Minsky-Fenichel-Yochelson garbage collector algorithm.\nDialogue: 0,0:33:30.40,0:33:33.18,EN,,0,0,0,,It was invented by Minsky\nDialogue: 0,0:33:33.20,0:33:36.06,EN,,0,0,0,,in 1961 or '60 or something,\nDialogue: 0,0:33:36.52,0:33:40.48,EN,,0,0,0,,for the RLE PDP-1 Lisp,\nDialogue: 0,0:33:40.51,0:33:43.44,EN,,0,0,0,,which had 4,096 words of list memory,\nDialogue: 0,0:33:45.79,0:33:46.76,EN,,0,0,0,,and a drum.\nDialogue: 0,0:33:48.48,0:33:49.39,EN,,0,0,0,,And the whole idea\nDialogue: 0,0:33:50.03,0:33:51.87,EN,,0,0,0,,was to garbage collect this terrible memory.\nDialogue: 0,0:33:53.05,0:33:54.35,EN,,0,0,0,,What Minsky realized\nDialogue: 0,0:33:54.38,0:33:55.62,EN,,0,0,0,,was the easiest way to do this\nDialogue: 0,0:33:56.20,0:33:58.47,EN,,0,0,0,,is to scan the memory in the same sense,\nDialogue: 0,0:33:58.47,0:34:00.60,EN,,0,0,0,,walking the good structure,\nDialogue: 0,0:34:01.57,0:34:03.52,EN,,0,0,0,,copying it out into the drum,\nDialogue: 0,0:34:04.70,0:34:05.47,EN,,0,0,0,,compacted.\nDialogue: 0,0:34:06.35,0:34:08.86,EN,,0,0,0,,And then when we were done copying it all out,\nDialogue: 0,0:34:09.12,0:34:10.90,EN,,0,0,0,,then you swap that back into your memory.\nDialogue: 0,0:34:12.30,0:34:13.68,EN,,0,0,0,,Now whether or you not use a drum,\nDialogue: 0,0:34:13.72,0:34:14.71,EN,,0,0,0,,or another piece of memory,\nDialogue: 0,0:34:14.71,0:34:16.42,EN,,0,0,0,,or something like that isn't important.\nDialogue: 0,0:34:17.03,0:34:17.42,EN,,0,0,0,,In fact,\nDialogue: 0,0:34:17.44,0:34:19.60,EN,,0,0,0,,I don't think people use drums anymore for anything.\nDialogue: 0,0:34:20.35,0:34:23.77,EN,,0,0,0,,But this algorithm basically\nDialogue: 0,0:34:24.03,0:34:25.42,EN,,0,0,0,,depends upon having\nDialogue: 0,0:34:25.42,0:34:27.42,EN,,0,0,0,,about twice as much address space\nDialogue: 0,0:34:27.48,0:34:28.57,EN,,0,0,0,,you're actually using.\nDialogue: 0,0:34:30.27,0:34:32.96,EN,,0,0,0,,And so what you have is some, initially,\nDialogue: 0,0:34:33.12,0:34:36.60,EN,,0,0,0,,some mixture of useful data and garbage.\nDialogue: 0,0:34:37.11,0:34:38.97,EN,,0,0,0,,So this is called fromspace.\nDialogue: 0,0:34:45.17,0:34:47.05,EN,,0,0,0,,And this is a mixture of crud.\nDialogue: 0,0:34:47.87,0:34:49.79,EN,,0,0,0,,Some of it's important and some of it isn't.\nDialogue: 0,0:34:52.00,0:34:53.85,EN,,0,0,0,,Now there's another place\nDialogue: 0,0:34:54.17,0:34:55.61,EN,,0,0,0,,which is hopefully big enough,\nDialogue: 0,0:34:55.77,0:34:57.00,EN,,0,0,0,,if we recall, tospace,\nDialogue: 0,0:34:57.12,0:34:58.24,EN,,0,0,0,,which is where we're copying to.\nDialogue: 0,0:35:01.59,0:35:02.60,EN,,0,0,0,,And what happens is--\nDialogue: 0,0:35:02.60,0:35:04.06,EN,,0,0,0,,and I'm not going to go through this detail.\nDialogue: 0,0:35:04.16,0:35:07.07,EN,,0,0,0,,It's in our book quite explicitly.\nDialogue: 0,0:35:07.59,0:35:10.40,EN,,0,0,0,,There's a root point where you start from.\nDialogue: 0,0:35:11.03,0:35:14.30,EN,,0,0,0,,And the idea is that you start with the root.\nDialogue: 0,0:35:14.60,0:35:16.42,EN,,0,0,0,,You copy the first thing you see,\nDialogue: 0,0:35:17.83,0:35:19.37,EN,,0,0,0,,the first thing that the root points at,\nDialogue: 0,0:35:19.75,0:35:21.31,EN,,0,0,0,,to the beginning of tospace.\nDialogue: 0,0:35:22.81,0:35:24.12,EN,,0,0,0,,The first thing is a pair\nDialogue: 0,0:35:24.16,0:35:25.60,EN,,0,0,0,,or something like, a data structure.\nDialogue: 0,0:35:27.56,0:35:30.19,EN,,0,0,0,,You then also leave behind\nDialogue: 0,0:35:30.38,0:35:31.56,EN,,0,0,0,,a broken heart saying,\nDialogue: 0,0:35:31.77,0:35:35.74,EN,,0,0,0,,I moved this object from here to here,\nDialogue: 0,0:35:35.74,0:35:37.05,EN,,0,0,0,,giving the place where it moved to.\nDialogue: 0,0:35:37.80,0:35:39.65,EN,,0,0,0,,This is called a broken heart because\nDialogue: 0,0:35:39.65,0:35:40.78,EN,,0,0,0,,a friend of mine who implemented\nDialogue: 0,0:35:40.78,0:35:43.39,EN,,0,0,0,,one of these in 1966\nDialogue: 0,0:35:43.82,0:35:45.26,EN,,0,0,0,,was a very romantic character\nDialogue: 0,0:35:45.26,0:35:46.76,EN,,0,0,0,,and called it a broken heart.\nDialogue: 0,0:35:49.58,0:35:50.54,EN,,0,0,0,,But in any case,\nDialogue: 0,0:35:51.15,0:35:52.72,EN,,0,0,0,,the next thing you do\nDialogue: 0,0:35:52.94,0:35:55.00,EN,,0,0,0,,is now you have a new free pointer which is here,\nDialogue: 0,0:35:55.17,0:35:56.38,EN,,0,0,0,,and you start scanning.\nDialogue: 0,0:35:56.88,0:35:59.68,EN,,0,0,0,,You scan this data structure you just copied.\nDialogue: 0,0:36:00.55,0:36:02.19,EN,,0,0,0,,And every time you encounter a pointer in it,\nDialogue: 0,0:36:02.19,0:36:03.92,EN,,0,0,0,,you treat it as if it was the root pointer here.\nDialogue: 0,0:36:04.00,0:36:04.59,EN,,0,0,0,,Oh, I'm sorry.\nDialogue: 0,0:36:04.60,0:36:05.69,EN,,0,0,0,,The other thing you do\nDialogue: 0,0:36:05.71,0:36:07.08,EN,,0,0,0,,is you now move the root pointer to there.\nDialogue: 0,0:36:09.22,0:36:10.17,EN,,0,0,0,,So now you scan this,\nDialogue: 0,0:36:10.17,0:36:10.99,EN,,0,0,0,,and everything you see\nDialogue: 0,0:36:11.00,0:36:12.41,EN,,0,0,0,,you treat as it were the root pointer.\nDialogue: 0,0:36:14.11,0:36:15.45,EN,,0,0,0,,So if you see something,\nDialogue: 0,0:36:15.45,0:36:17.40,EN,,0,0,0,,well it points up into there somewhere.\nDialogue: 0,0:36:18.51,0:36:19.92,EN,,0,0,0,,Is it pointing at a thing\nDialogue: 0,0:36:19.93,0:36:20.99,EN,,0,0,0,,which you've not copied yet?\nDialogue: 0,0:36:21.78,0:36:22.87,EN,,0,0,0,,Is there a broken heart there?\nDialogue: 0,0:36:23.88,0:36:24.84,EN,,0,0,0,,If there's a broken heart there\nDialogue: 0,0:36:24.84,0:36:26.11,EN,,0,0,0,,and it's something you have copied,\nDialogue: 0,0:36:26.20,0:36:27.34,EN,,0,0,0,,you've just replaced this pointer\nDialogue: 0,0:36:27.36,0:36:28.75,EN,,0,0,0,,with the thing a broken heart points at.\nDialogue: 0,0:36:29.82,0:36:32.03,EN,,0,0,0,,If this thing has not been copied,\nDialogue: 0,0:36:32.12,0:36:34.08,EN,,0,0,0,,you copy it to the next place over here.\nDialogue: 0,0:36:34.43,0:36:35.95,EN,,0,0,0,,Move your free pointer over here,\nDialogue: 0,0:36:37.05,0:36:40.60,EN,,0,0,0,,and then leave a broken heart behind\nDialogue: 0,0:36:41.05,0:36:41.80,EN,,0,0,0,,and scan.\nDialogue: 0,0:36:43.67,0:36:46.40,EN,,0,0,0,,And eventually when the scant pointer hits the free pointer,\nDialogue: 0,0:36:46.82,0:36:48.52,EN,,0,0,0,,everything in memory has been copied.\nDialogue: 0,0:36:50.14,0:36:51.04,EN,,0,0,0,,And then there's a whole bunch\nDialogue: 0,0:36:51.05,0:36:51.95,EN,,0,0,0,,of empty space up here,\nDialogue: 0,0:36:51.96,0:36:53.28,EN,,0,0,0,,which you could either make into a free list,\nDialogue: 0,0:36:53.31,0:36:54.47,EN,,0,0,0,,if that's what you want to do.\nDialogue: 0,0:36:54.47,0:36:56.27,EN,,0,0,0,,But generally you don't in this kind of system.\nDialogue: 0,0:36:56.27,0:36:59.15,EN,,0,0,0,,In this system you sequentially allocate your memory.\nDialogue: 0,0:37:00.91,0:37:02.48,EN,,0,0,0,,That is a very, very nice algorithm,\nDialogue: 0,0:37:02.97,0:37:04.57,EN,,0,0,0,,and sort of the one we use in the\nDialogue: 0,0:37:04.67,0:37:05.97,EN,,0,0,0,,the scheme that you've been using.\nDialogue: 0,0:37:06.79,0:37:09.47,EN,,0,0,0,,And it's known to be... it's expected--\nDialogue: 0,0:37:09.47,0:37:10.86,EN,,0,0,0,,I believe no one has found\nDialogue: 0,0:37:10.89,0:37:12.12,EN,,0,0,0,,a faster algorithm than that.\nDialogue: 0,0:37:12.40,0:37:14.85,EN,,0,0,0,,There are very simple modifications to this algorithm\nDialogue: 0,0:37:14.85,0:37:16.77,EN,,0,0,0,,invented by Henry Baker\nDialogue: 0,0:37:17.17,0:37:20.31,EN,,0,0,0,,which allow one to run this algorithm in real time,\nDialogue: 0,0:37:20.31,0:37:21.92,EN,,0,0,0,,meaning you don't have to stop to garbage collect.\nDialogue: 0,0:37:22.14,0:37:24.33,EN,,0,0,0,,But you could interleave the consing\nDialogue: 0,0:37:24.36,0:37:26.17,EN,,0,0,0,,that the machine does when its running\nDialogue: 0,0:37:26.32,0:37:28.40,EN,,0,0,0,,with steps of the garbage collection process,\nDialogue: 0,0:37:28.85,0:37:31.20,EN,,0,0,0,,so that the thing, the garbage collector's distributed\nDialogue: 0,0:37:31.20,0:37:32.19,EN,,0,0,0,,and the machine doesn't have to stop,\nDialogue: 0,0:37:32.41,0:37:33.47,EN,,0,0,0,,and garbage collecting can start.\nDialogue: 0,0:37:34.64,0:37:37.87,EN,,0,0,0,,Of course in the case of machines with virtual memory\nDialogue: 0,0:37:38.90,0:37:41.20,EN,,0,0,0,,where a lot of it is in inaccessible places,\nDialogue: 0,0:37:41.50,0:37:43.60,EN,,0,0,0,,this becomes a very expensive process.\nDialogue: 0,0:37:44.28,0:37:46.43,EN,,0,0,0,,And there have been numerous\nDialogue: 0,0:37:47.16,0:37:48.65,EN,,0,0,0,,attempts to make this much better.\nDialogue: 0,0:37:49.19,0:37:51.15,EN,,0,0,0,,There is a nice paper,\nDialogue: 0,0:37:51.16,0:37:52.41,EN,,0,0,0,,for those of you who are interested,\nDialogue: 0,0:37:52.64,0:37:54.27,EN,,0,0,0,,by Moon and other people\nDialogue: 0,0:37:54.65,0:37:56.89,EN,,0,0,0,,which describes a modification to\nDialogue: 0,0:37:56.92,0:37:59.44,EN,,0,0,0,,the incremental Minsky-Fenichel-Yochelson algorithm,\nDialogue: 0,0:37:59.51,0:38:01.20,EN,,0,0,0,,and modification the Baker algorithm\nDialogue: 0,0:38:01.42,0:38:06.54,EN,,0,0,0,,which is more efficient for virtual memory systems.\nDialogue: 0,0:38:08.27,0:38:12.32,EN,,0,0,0,,Well I think now the mystery to this is sort of gone.\nDialogue: 0,0:38:12.84,0:38:14.09,EN,,0,0,0,,And I'd like to see if there are any questions.\nDialogue: 0,0:38:19.78,0:38:19.95,EN,,0,0,0,,Yes.\nDialogue: 0,0:38:20.60,0:38:23.58,EN,,0,0,0,,AUDIENCE: I saw one of you run the garbage collector\nDialogue: 0,0:38:23.64,0:38:25.05,EN,,0,0,0,,on the systems upstairs,\nDialogue: 0,0:38:25.93,0:38:27.88,EN,,0,0,0,,and it seemed to me to run extremely fast.\nDialogue: 0,0:38:27.96,0:38:28.40,EN,,0,0,0,,PROFESSOR: Yes\nDialogue: 0,0:38:28.49,0:38:29.52,EN,,0,0,0,,AUDIENCE: Did the whole thing take--\nDialogue: 0,0:38:30.11,0:38:31.88,EN,,0,0,0,,does it sweep through all of memory?\nDialogue: 0,0:38:31.88,0:38:32.22,EN,,0,0,0,,PROFESSOR: No.\nDialogue: 0,0:38:32.25,0:38:34.11,EN,,0,0,0,,It swept through exactly what was needed\nDialogue: 0,0:38:34.33,0:38:35.63,EN,,0,0,0,,to copy the useful structure.\nDialogue: 0,0:38:37.32,0:38:38.36,EN,,0,0,0,,It's a copying collector.\nDialogue: 0,0:38:38.44,0:38:38.91,EN,,0,0,0,,AUDIENCE: OK.\nDialogue: 0,0:38:39.30,0:38:40.88,EN,,0,0,0,,PROFESSOR: And it's rather... it is very fast.\nDialogue: 0,0:38:41.85,0:38:45.88,EN,,0,0,0,,On the whole, I suppose to copy in a Bobcat\nDialogue: 0,0:38:47.12,0:38:51.56,EN,,0,0,0,,to copy, I think, a three megabyte thing or something\nDialogue: 0,0:38:52.43,0:38:53.24,EN,,0,0,0,,is less than a second,\nDialogue: 0,0:38:55.00,0:38:55.69,EN,,0,0,0,,real time\nDialogue: 0,0:38:56.54,0:38:58.46,EN,,0,0,0,,Really, these are very small programs.\nDialogue: 0,0:38:58.62,0:39:01.50,EN,,0,0,0,,One thing you should realise is that\nDialogue: 0,0:39:02.91,0:39:04.40,EN,,0,0,0,,garbage collectors have to be small.\nDialogue: 0,0:39:05.40,0:39:07.10,EN,,0,0,0,,Not because they have to be fast,\nDialogue: 0,0:39:07.90,0:39:09.23,EN,,0,0,0,,but because no one can debug\nDialogue: 0,0:39:09.26,0:39:10.48,EN,,0,0,0,,a complicated garbage collector.\nDialogue: 0,0:39:11.34,0:39:12.91,EN,,0,0,0,,A garbage collector, if it doesn't work,\nDialogue: 0,0:39:14.04,0:39:15.93,EN,,0,0,0,,will trash your memory in such a way\nDialogue: 0,0:39:15.93,0:39:17.39,EN,,0,0,0,,that you cannot figure out what the hell happened.\nDialogue: 0,0:39:18.35,0:39:19.67,EN,,0,0,0,,You need an audit trail.\nDialogue: 0,0:39:20.66,0:39:22.01,EN,,0,0,0,,Because it rearranges everything,\nDialogue: 0,0:39:22.04,0:39:23.24,EN,,0,0,0,,and how do you know what happened there?\nDialogue: 0,0:39:23.74,0:39:26.58,EN,,0,0,0,,So this is the only kind of program that\nDialogue: 0,0:39:26.92,0:39:28.40,EN,,0,0,0,,it really, seriously matters\nDialogue: 0,0:39:28.54,0:39:29.79,EN,,0,0,0,,if you stare at it long enough\nDialogue: 0,0:39:29.82,0:39:31.07,EN,,0,0,0,,so you believe that it works.\nDialogue: 0,0:39:31.34,0:39:33.36,EN,,0,0,0,,That means and sort of prove it to yourself.\nDialogue: 0,0:39:33.92,0:39:36.11,EN,,0,0,0,,And that, that... So there's no way to debug it.\nDialogue: 0,0:39:36.94,0:39:38.96,EN,,0,0,0,,And that takes it being small enough\nDialogue: 0,0:39:38.96,0:39:39.97,EN,,0,0,0,,so you can hold it in your head.\nDialogue: 0,0:39:41.45,0:39:43.90,EN,,0,0,0,,So garbage collectors are special in this way.\nDialogue: 0,0:39:45.02,0:39:47.12,EN,,0,0,0,,So every reasonable garbage collector has gotten small,\nDialogue: 0,0:39:47.13,0:39:48.45,EN,,0,0,0,,and generally small programs are fast.\nDialogue: 0,0:39:52.05,0:39:52.43,EN,,0,0,0,,Yes.\nDialogue: 0,0:39:52.43,0:39:54.51,EN,,0,0,0,,AUDIENCE: Can you repeat the name of this technique once again?\nDialogue: 0,0:39:54.68,0:39:56.92,EN,,0,0,0,,PROFESSOR: That's the Minsky-Fenichel-Yochelson garbage collector.\nDialogue: 0,0:39:57.88,0:39:58.43,EN,,0,0,0,,AUDIENCE: You got that?\nDialogue: 0,0:39:59.00,0:40:00.78,EN,,0,0,0,,PROFESSOR: Minsky invented it in '61\nDialogue: 0,0:40:00.81,0:40:02.21,EN,,0,0,0,,for the RLE PDP-1.\nDialogue: 0,0:40:02.21,0:40:06.17,EN,,0,0,0,,A version of it was developed and elaborated\nDialogue: 0,0:40:06.45,0:40:10.27,EN,,0,0,0,,to be used in Multics Maclisp by Fenichel and Yochelson\nDialogue: 0,0:40:11.37,0:40:14.75,EN,,0,0,0,,in somewhere around 1968 or '69.\nDialogue: 0,0:40:19.57,0:40:21.36,EN,,0,0,0,,OK. Let's take a break.\nDialogue: 0,0:40:22.64,0:40:32.36,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:41:17.31,0:41:19.67,EN,,0,0,0,,PROFESSOR: Well we've come to the end of this subject,\nDialogue: 0,0:41:20.08,0:41:23.85,EN,,0,0,0,,and we've already shown you a universal machine\nDialogue: 0,0:41:24.47,0:41:26.74,EN,,0,0,0,,which is down to evaluator.\nDialogue: 0,0:41:27.02,0:41:28.38,EN,,0,0,0,,It's down to the level of detail\nDialogue: 0,0:41:28.38,0:41:29.67,EN,,0,0,0,,you could imagine you could make one.\nDialogue: 0,0:41:30.19,0:41:33.32,EN,,0,0,0,,This is a particular implementation of Lisp,\nDialogue: 0,0:41:33.90,0:41:36.01,EN,,0,0,0,,built on one of those\nDialogue: 0,0:41:36.16,0:41:38.05,EN,,0,0,0,,scheme chips that was talked about yesterday,\nDialogue: 0,0:41:38.20,0:41:38.91,EN,,0,0,0,,sitting over here.\nDialogue: 0,0:41:39.35,0:41:42.00,EN,,0,0,0,,This is mostly interface to somebody's memory\nDialogue: 0,0:41:42.60,0:41:44.75,EN,,0,0,0,,with a little bit of timing and other such stuff.\nDialogue: 0,0:41:45.22,0:41:47.25,EN,,0,0,0,,But this fellow actually ran Lisp\nDialogue: 0,0:41:47.77,0:41:50.17,EN,,0,0,0,,at a fairly reasonable rate, as interpretive.\nDialogue: 0,0:41:50.61,0:41:53.82,EN,,0,0,0,,It ran Lisp as fast as a DEC PDP-10\nDialogue: 0,0:41:54.22,0:41:55.65,EN,,0,0,0,,back in 1979.\nDialogue: 0,0:41:56.50,0:41:59.67,EN,,0,0,0,,And so it's gotten pretty hardware.\nDialogue: 0,0:42:00.02,0:42:00.89,EN,,0,0,0,,Pretty concrete.\nDialogue: 0,0:42:02.47,0:42:04.70,EN,,0,0,0,,We've also downed you a bit\nDialogue: 0,0:42:04.72,0:42:06.07,EN,,0,0,0,,with the things you can compute.\nDialogue: 0,0:42:07.37,0:42:08.76,EN,,0,0,0,,But is it the case that\nDialogue: 0,0:42:09.32,0:42:10.55,EN,,0,0,0,,there are things we can't compute?\nDialogue: 0,0:42:11.85,0:42:13.50,EN,,0,0,0,,And so I'd like to end this with\nDialogue: 0,0:42:13.75,0:42:15.87,EN,,0,0,0,,showing you some things that you'd like be able to compute\nDialogue: 0,0:42:16.60,0:42:17.22,EN,,0,0,0,,that you can't.\nDialogue: 0,0:42:18.19,0:42:19.45,EN,,0,0,0,,The answer is yes,\nDialogue: 0,0:42:19.45,0:42:20.82,EN,,0,0,0,,there are things you can't compute.\nDialogue: 0,0:42:22.72,0:42:23.47,EN,,0,0,0,,For example,\nDialogue: 0,0:42:24.45,0:42:25.82,EN,,0,0,0,,something you'd really like is--\nDialogue: 0,0:42:27.80,0:42:29.36,EN,,0,0,0,,if you're writing a compiler\nDialogue: 0,0:42:29.77,0:42:31.42,EN,,0,0,0,,you'd like a program that would check\nDialogue: 0,0:42:32.00,0:42:33.97,EN,,0,0,0,,that the thing you're going to do will work.\nDialogue: 0,0:42:34.63,0:42:35.40,EN,,0,0,0,,Wouldn't that be nice?\nDialogue: 0,0:42:36.08,0:42:37.87,EN,,0,0,0,,You'd like something that would catch infinite loops,\nDialogue: 0,0:42:37.87,0:42:38.54,EN,,0,0,0,,for example,\nDialogue: 0,0:42:39.45,0:42:42.42,EN,,0,0,0,,in programs that were written by users.\nDialogue: 0,0:42:43.19,0:42:45.12,EN,,0,0,0,,But in general you can't write such a program\nDialogue: 0,0:42:45.35,0:42:46.49,EN,,0,0,0,,that will read any program\nDialogue: 0,0:42:46.51,0:42:47.45,EN,,0,0,0,,and determine whether or not\nDialogue: 0,0:42:48.35,0:42:49.30,EN,,0,0,0,,it's an infinite loop.\nDialogue: 0,0:42:50.99,0:42:51.71,EN,,0,0,0,,Let me show you that.\nDialogue: 0,0:42:51.76,0:42:53.80,EN,,0,0,0,,It's a little bit of a minor mathematics.\nDialogue: 0,0:42:58.78,0:42:59.65,EN,,0,0,0,,Let's imagine\nDialogue: 0,0:43:00.05,0:43:01.78,EN,,0,0,0,,that we just had a mathematical function\nDialogue: 0,0:43:01.78,0:43:02.62,EN,,0,0,0,,before we start.\nDialogue: 0,0:43:02.62,0:43:03.42,EN,,0,0,0,,And there is one,\nDialogue: 0,0:43:03.84,0:43:04.67,EN,,0,0,0,,called s,\nDialogue: 0,0:43:05.47,0:43:07.54,EN,,0,0,0,,which takes a procedure\nDialogue: 0,0:43:12.64,0:43:14.23,EN,,0,0,0,,and its argument, a.\nDialogue: 0,0:43:19.17,0:43:20.52,EN,,0,0,0,,And what s does\nDialogue: 0,0:43:21.65,0:43:24.01,EN,,0,0,0,,is it determines whether or not\nDialogue: 0,0:43:24.01,0:43:25.97,EN,,0,0,0,,it's safe to run p on a.\nDialogue: 0,0:43:26.90,0:43:28.17,EN,,0,0,0,,And what I mean by that is this:\nDialogue: 0,0:43:28.76,0:43:35.12,EN,,0,0,0,,it's true if p applied to a\nDialogue: 0,0:43:35.62,0:43:36.74,EN,,0,0,0,,will converge\nDialogue: 0,0:43:41.40,0:43:42.45,EN,,0,0,0,,to a value\nDialogue: 0,0:43:44.35,0:43:45.33,EN,,0,0,0,,without an error.\nDialogue: 0,0:43:52.70,0:43:53.68,EN,,0,0,0,,And it's false\nDialogue: 0,0:43:56.10,0:43:57.04,EN,,0,0,0,,if p of a\nDialogue: 0,0:43:59.67,0:44:00.76,EN,,0,0,0,,loops forever\nDialogue: 0,0:44:05.87,0:44:06.95,EN,,0,0,0,,or makes an error.\nDialogue: 0,0:44:15.23,0:44:17.22,EN,,0,0,0,,Now that's surely a function.\nDialogue: 0,0:44:18.78,0:44:20.72,EN,,0,0,0,,There is some for every procedure\nDialogue: 0,0:44:21.20,0:44:22.85,EN,,0,0,0,,and for every argument you could give it\nDialogue: 0,0:44:23.92,0:44:25.45,EN,,0,0,0,,that is either true or false\nDialogue: 0,0:44:25.92,0:44:27.85,EN,,0,0,0,,that it converges without making an error.\nDialogue: 0,0:44:28.44,0:44:30.15,EN,,0,0,0,,And you could make a giant table of them.\nDialogue: 0,0:44:32.22,0:44:32.92,EN,,0,0,0,,But the question is,\nDialogue: 0,0:44:32.92,0:44:34.09,EN,,0,0,0,,can you write a procedure\nDialogue: 0,0:44:34.09,0:44:35.92,EN,,0,0,0,,that compute the values of this function?\nDialogue: 0,0:44:37.43,0:44:38.92,EN,,0,0,0,,Well let's assume that we can.\nDialogue: 0,0:44:39.72,0:44:40.55,EN,,0,0,0,,Suppose\nDialogue: 0,0:44:44.33,0:44:45.58,EN,,0,0,0,,that we have a procedure\nDialogue: 0,0:44:48.55,0:44:52.73,EN,,0,0,0,,procedure called \"safe\"\nDialogue: 0,0:44:56.54,0:44:59.90,EN,,0,0,0,,that computes the value of s.\nDialogue: 0,0:45:12.65,0:45:14.89,EN,,0,0,0,,Now I'm going to show you by several methods\nDialogue: 0,0:45:15.90,0:45:18.51,EN,,0,0,0,,that you can't do this.\nDialogue: 0,0:45:19.76,0:45:20.62,EN,,0,0,0,,The easiest one,\nDialogue: 0,0:45:20.62,0:45:21.28,EN,,0,0,0,,or the first one,\nDialogue: 0,0:45:21.31,0:45:23.45,EN,,0,0,0,,let's define a procedure called diag1.\nDialogue: 0,0:45:23.76,0:45:24.86,EN,,0,0,0,,Given that we have safe,\nDialogue: 0,0:45:25.20,0:45:26.99,EN,,0,0,0,,we can define diag1\nDialogue: 0,0:45:34.42,0:45:35.55,EN,,0,0,0,,diag1\nDialogue: 0,0:45:37.82,0:45:41.60,EN,,0,0,0,,to be the procedure of one argument, p,\nDialogue: 0,0:45:42.45,0:45:44.05,EN,,0,0,0,,which has the following properties.\nDialogue: 0,0:45:44.78,0:45:50.67,EN,,0,0,0,,If it's safe to apply p to itself,\nDialogue: 0,0:45:53.32,0:45:55.32,EN,,0,0,0,,then I wish to have an infinite loop.\nDialogue: 0,0:45:59.22,0:46:00.92,EN,,0,0,0,,Otherwise I'm going to return 3.\nDialogue: 0,0:46:03.68,0:46:04.47,EN,,0,0,0,,Maybe it was 42.\nDialogue: 0,0:46:04.47,0:46:06.42,EN,,0,0,0,,What's the answer to the big question?\nDialogue: 0,0:46:07.06,0:46:08.87,EN,,0,0,0,,Where of course we know what an infinite loop is.\nDialogue: 0,0:46:12.05,0:46:12.96,EN,,0,0,0,,Infinite loop,\nDialogue: 0,0:46:13.82,0:46:16.02,EN,,0,0,0,,to be a procedure of no arguments,\nDialogue: 0,0:46:16.02,0:46:18.07,EN,,0,0,0,,which is that nice lambda calculus loop.\nDialogue: 0,0:46:18.35,0:46:20.44,EN,,0,0,0,,Lambda of x,\nDialogue: 0,0:46:21.30,0:46:24.68,EN,,0,0,0,,applied to lambda of x, x of x.\nDialogue: 0,0:46:24.68,0:46:26.55,EN,,0,0,0,,So there's nothing left to the imagination here.\nDialogue: 0,0:46:29.83,0:46:31.17,EN,,0,0,0,,Well let's see what the story is.\nDialogue: 0,0:46:32.50,0:46:33.90,EN,,0,0,0,,I'm supposing it's the case\nDialogue: 0,0:46:35.45,0:46:38.77,EN,,0,0,0,,that we worry about the procedure\nDialogue: 0,0:46:39.00,0:46:43.45,EN,,0,0,0,,called diag1 applied to diag1.\nDialogue: 0,0:46:46.27,0:46:47.77,EN,,0,0,0,,Well what could it possibly be?\nDialogue: 0,0:46:49.97,0:46:51.39,EN,,0,0,0,,Well I don't know.\nDialogue: 0,0:46:51.39,0:46:53.21,EN,,0,0,0,,We're going to substitute diag1\nDialogue: 0,0:46:53.55,0:46:55.50,EN,,0,0,0,,for p in the body here.\nDialogue: 0,0:46:57.31,0:47:00.22,EN,,0,0,0,,Well is it safe to compute diag1 of diag1?\nDialogue: 0,0:47:00.22,0:47:00.78,EN,,0,0,0,,I don't know.\nDialogue: 0,0:47:00.78,0:47:01.82,EN,,0,0,0,,There are two possibilities.\nDialogue: 0,0:47:03.40,0:47:05.50,EN,,0,0,0,,If it's safe to compute diag1 of diag1\nDialogue: 0,0:47:05.92,0:47:06.89,EN,,0,0,0,,that means it shouldn't loop.\nDialogue: 0,0:47:08.49,0:47:09.22,EN,,0,0,0,,That means I go to here,\nDialogue: 0,0:47:09.22,0:47:10.35,EN,,0,0,0,,but then I produce an infinite loop.\nDialogue: 0,0:47:10.56,0:47:11.57,EN,,0,0,0,,So it can't be safe.\nDialogue: 0,0:47:12.21,0:47:14.78,EN,,0,0,0,,But if it's not safe to compute diag1 of diag1\nDialogue: 0,0:47:14.90,0:47:16.02,EN,,0,0,0,,then the answer to this is 3.\nDialogue: 0,0:47:16.02,0:47:17.26,EN,,0,0,0,,But that's diag1 of diag1,\nDialogue: 0,0:47:17.26,0:47:17.93,EN,,0,0,0,,so it had to be safe.\nDialogue: 0,0:47:20.53,0:47:23.60,EN,,0,0,0,,So therefore by contradiction\nDialogue: 0,0:47:24.32,0:47:26.30,EN,,0,0,0,,you cannot produce safe.\nDialogue: 0,0:47:27.40,0:47:29.80,EN,,0,0,0,,For those of you who were boggled by that one\nDialogue: 0,0:47:30.25,0:47:32.15,EN,,0,0,0,,I'm going to say it again, in a different way.\nDialogue: 0,0:47:32.82,0:47:34.00,EN,,0,0,0,,Listen to one more alternative.\nDialogue: 0,0:47:35.53,0:47:36.95,EN,,0,0,0,,Let's define diag2.\nDialogue: 0,0:47:39.84,0:47:41.60,EN,,0,0,0,,These are named diag because\nDialogue: 0,0:47:42.65,0:47:44.72,EN,,0,0,0,,of Cantor's diagonal argument.\nDialogue: 0,0:47:45.00,0:47:47.05,EN,,0,0,0,,These are instances of\nDialogue: 0,0:47:47.05,0:47:49.05,EN,,0,0,0,,a famous argument which was originally used by\nDialogue: 0,0:47:49.45,0:47:52.65,EN,,0,0,0,,Cantor in the late part of the last century\nDialogue: 0,0:47:52.77,0:47:56.10,EN,,0,0,0,,to prove that the real numbers were not countable,\nDialogue: 0,0:47:56.67,0:47:58.00,EN,,0,0,0,,that there are too many real numbers\nDialogue: 0,0:47:58.06,0:47:59.42,EN,,0,0,0,,to be counted by integers.\nDialogue: 0,0:48:00.19,0:48:01.74,EN,,0,0,0,,That there are more points on a line,\nDialogue: 0,0:48:01.74,0:48:02.50,EN,,0,0,0,,for example,\nDialogue: 0,0:48:02.50,0:48:04.42,EN,,0,0,0,,than there are counting numbers.\nDialogue: 0,0:48:05.26,0:48:06.85,EN,,0,0,0,,It may or may not be obvious,\nDialogue: 0,0:48:06.85,0:48:08.17,EN,,0,0,0,,and I don't want to get into that now.\nDialogue: 0,0:48:10.90,0:48:12.45,EN,,0,0,0,,But diag2\nDialogue: 0,0:48:13.30,0:48:15.82,EN,,0,0,0,,is again a procedure of one argument p.\nDialogue: 0,0:48:15.82,0:48:17.47,EN,,0,0,0,,It's almost the same as the previous one,\nDialogue: 0,0:48:17.72,0:48:24.32,EN,,0,0,0,,which is, if it's safe to compute p on p,\nDialogue: 0,0:48:25.17,0:48:26.67,EN,,0,0,0,,then I'm going to produce--\nDialogue: 0,0:48:27.26,0:48:28.14,EN,,0,0,0,,Oops, if\nDialogue: 0,0:48:29.31,0:48:31.02,EN,,0,0,0,,then I want to compute\nDialogue: 0,0:48:31.57,0:48:37.58,EN,,0,0,0,,some other things\nDialogue: 0,0:48:38.96,0:48:40.21,EN,,0,0,0,,Otherwise I'm going to put out false.\nDialogue: 0,0:48:43.60,0:48:45.30,EN,,0,0,0,,Where other then it says,\nDialogue: 0,0:48:45.47,0:48:46.35,EN,,0,0,0,,whatever p of p,\nDialogue: 0,0:48:46.35,0:48:47.47,EN,,0,0,0,,I'm going to put out something else.\nDialogue: 0,0:48:48.88,0:48:50.03,EN,,0,0,0,,I can give you an example of\nDialogue: 0,0:48:50.07,0:48:51.52,EN,,0,0,0,,a definition of other than\nDialogue: 0,0:48:51.60,0:48:52.57,EN,,0,0,0,,which I think works.\nDialogue: 0,0:48:53.89,0:48:54.51,EN,,0,0,0,,Let's see.\nDialogue: 0,0:48:55.64,0:48:56.08,EN,,0,0,0,,Yes.\nDialogue: 0,0:48:56.33,0:48:57.26,EN,,0,0,0,,Where other than\nDialogue: 0,0:49:04.03,0:49:06.11,EN,,0,0,0,,be a procedure of one argument x\nDialogue: 0,0:49:06.57,0:49:07.26,EN,,0,0,0,,which says,\nDialogue: 0,0:49:08.05,0:49:12.96,EN,,0,0,0,,if its eq x to, say, quote a,\nDialogue: 0,0:49:13.47,0:49:15.07,EN,,0,0,0,,then the answer is quote b.\nDialogue: 0,0:49:15.72,0:49:16.80,EN,,0,0,0,,Otherwise it's quote a.\nDialogue: 0,0:49:20.27,0:49:21.90,EN,,0,0,0,,That always produces something\nDialogue: 0,0:49:22.07,0:49:23.45,EN,,0,0,0,,which is not what its argument is.\nDialogue: 0,0:49:25.20,0:49:26.12,EN,,0,0,0,,That's all it is.\nDialogue: 0,0:49:26.54,0:49:27.37,EN,,0,0,0,,That's all I wanted.\nDialogue: 0,0:49:28.25,0:49:29.58,EN,,0,0,0,,Well now let's consider this one,\nDialogue: 0,0:49:29.58,0:49:31.15,EN,,0,0,0,,diag2 of diag2.\nDialogue: 0,0:49:38.28,0:49:38.94,EN,,0,0,0,,Well look.\nDialogue: 0,0:49:39.95,0:49:41.72,EN,,0,0,0,,This only does something dangerous,\nDialogue: 0,0:49:42.00,0:49:43.45,EN,,0,0,0,,like calling p of p,\nDialogue: 0,0:49:44.75,0:49:45.95,EN,,0,0,0,,if it's safe to do so.\nDialogue: 0,0:49:47.47,0:49:49.16,EN,,0,0,0,,So if safe defined at all,\nDialogue: 0,0:49:50.30,0:49:52.49,EN,,0,0,0,,if you can define such a procedure, safe,\nDialogue: 0,0:49:52.97,0:49:54.32,EN,,0,0,0,,then this procedure\nDialogue: 0,0:49:54.60,0:49:56.40,EN,,0,0,0,,is always defined and therefore safe\nDialogue: 0,0:49:56.52,0:49:57.22,EN,,0,0,0,,on any inputs.\nDialogue: 0,0:50:01.54,0:50:03.50,EN,,0,0,0,,So diag2 of diag2\nDialogue: 0,0:50:03.87,0:50:12.20,EN,,0,0,0,,must reduce to other than diag2 of diag2.\nDialogue: 0,0:50:15.82,0:50:16.97,EN,,0,0,0,,And that doesn't make sense,\nDialogue: 0,0:50:17.80,0:50:19.02,EN,,0,0,0,,so we have a contradiction,\nDialogue: 0,0:50:19.85,0:50:21.57,EN,,0,0,0,,and therefore we can't define safe.\nDialogue: 0,0:50:22.95,0:50:24.23,EN,,0,0,0,,I just waned to do that twice,\nDialogue: 0,0:50:24.78,0:50:25.82,EN,,0,0,0,,slightly differently,\nDialogue: 0,0:50:26.84,0:50:27.90,EN,,0,0,0,,so you wouldn't feel\nDialogue: 0,0:50:29.07,0:50:30.86,EN,,0,0,0,,that the first one was a trick.\nDialogue: 0,0:50:32.54,0:50:33.45,EN,,0,0,0,,They may be both tricks,\nDialogue: 0,0:50:33.80,0:50:35.15,EN,,0,0,0,,but they're at least slightly different.\nDialogue: 0,0:50:37.30,0:50:39.20,EN,,0,0,0,,So I suppose that pretty much wraps it up.\nDialogue: 0,0:50:40.03,0:50:41.97,EN,,0,0,0,,I've just proved what we call the halting theorem,\nDialogue: 0,0:50:43.00,0:50:44.70,EN,,0,0,0,,and I suppose with that we're going to halt.\nDialogue: 0,0:50:46.72,0:50:47.63,EN,,0,0,0,,I hope you have a good time.\nDialogue: 0,0:50:50.90,0:50:51.76,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:50:53.30,0:50:53.56,EN,,0,0,0,,Yes.\nDialogue: 0,0:50:53.81,0:50:56.27,EN,,0,0,0,,AUDIENCE: What is the value of s of diag1?\nDialogue: 0,0:50:56.75,0:50:57.23,EN,,0,0,0,,PROFESSOR: Of what?\nDialogue: 0,0:50:57.50,0:50:58.80,EN,,0,0,0,,AUDIENCE: S of diag1.\nDialogue: 0,0:51:00.12,0:51:02.20,EN,,0,0,0,,If you said s is a function, and then we can\nDialogue: 0,0:51:02.30,0:51:03.63,EN,,0,0,0,,PROFESSOR: Oh, I don't know.\nDialogue: 0,0:51:03.87,0:51:04.35,EN,,0,0,0,,I don't know.\nDialogue: 0,0:51:04.35,0:51:04.88,EN,,0,0,0,,It's a function,\nDialogue: 0,0:51:04.88,0:51:05.85,EN,,0,0,0,,but I don't know how to compute it.\nDialogue: 0,0:51:06.80,0:51:08.00,EN,,0,0,0,,I can't do it.\nDialogue: 0,0:51:08.61,0:51:09.64,EN,,0,0,0,,I'm just a machine, too.\nDialogue: 0,0:51:11.53,0:51:11.88,EN,,0,0,0,,Right?\nDialogue: 0,0:51:11.90,0:51:13.37,EN,,0,0,0,,And there's no machine\nDialogue: 0,0:51:13.37,0:51:14.05,EN,,0,0,0,,that in principle--\nDialogue: 0,0:51:14.47,0:51:16.87,EN,,0,0,0,,it might be that in that particular case you just asked,\nDialogue: 0,0:51:16.87,0:51:18.32,EN,,0,0,0,,with some thinking I could figure it out.\nDialogue: 0,0:51:18.58,0:51:19.37,EN,,0,0,0,,But in general\nDialogue: 0,0:51:19.60,0:51:21.05,EN,,0,0,0,,I can't compute the value of s\nDialogue: 0,0:51:21.05,0:51:22.52,EN,,0,0,0,,any better than any other machine can.\nDialogue: 0,0:51:23.78,0:51:24.92,EN,,0,0,0,,There is such a function,\nDialogue: 0,0:51:25.92,0:51:28.00,EN,,0,0,0,,it's just that no machine can be built to compute it.\nDialogue: 0,0:51:29.58,0:51:30.05,EN,,0,0,0,,Now\nDialogue: 0,0:51:30.67,0:51:33.67,EN,,0,0,0,,there's a way of saying that that should not be surprising.\nDialogue: 0,0:51:35.22,0:51:36.25,EN,,0,0,0,,Going through this--\nDialogue: 0,0:51:36.25,0:51:38.36,EN,,0,0,0,,I mean, I don't have time to do this here,\nDialogue: 0,0:51:38.45,0:51:43.00,EN,,0,0,0,,but the number of functions is very large.\nDialogue: 0,0:51:44.40,0:51:47.58,EN,,0,0,0,,If there's a certain number of answers possible\nDialogue: 0,0:51:47.75,0:51:49.62,EN,,0,0,0,,and a certain number of inputs possible,\nDialogue: 0,0:51:49.87,0:51:51.80,EN,,0,0,0,,then it's the number of answers raised to the number inputs\nDialogue: 0,0:51:51.80,0:51:53.20,EN,,0,0,0,,is the number of possible functions.\nDialogue: 0,0:51:54.50,0:51:55.48,EN,,0,0,0,,On one variable.\nDialogue: 0,0:51:56.51,0:51:59.24,EN,,0,0,0,,Now that's always bigger\nDialogue: 0,0:52:00.09,0:52:03.21,EN,,0,0,0,,than the thing you're raising to,\nDialogue: 0,0:52:03.58,0:52:04.32,EN,,0,0,0,,the exponent.\nDialogue: 0,0:52:05.48,0:52:09.80,EN,,0,0,0,,The number of functions is larger\nDialogue: 0,0:52:09.95,0:52:12.72,EN,,0,0,0,,than the number of programs\nDialogue: 0,0:52:13.30,0:52:14.10,EN,,0,0,0,,that one can write,\nDialogue: 0,0:52:14.82,0:52:16.45,EN,,0,0,0,,by an infinity counting argument.\nDialogue: 0,0:52:17.57,0:52:19.00,EN,,0,0,0,,And it's much larger.\nDialogue: 0,0:52:19.47,0:52:22.12,EN,,0,0,0,,So there must be a lot of functions\nDialogue: 0,0:52:22.12,0:52:23.48,EN,,0,0,0,,that can't be computed by programs.\nDialogue: 0,0:52:25.92,0:52:26.59,EN,,0,0,0,,AUDIENCE: A few moments ago\nDialogue: 0,0:52:26.64,0:52:28.25,EN,,0,0,0,,you were talking about specifications\nDialogue: 0,0:52:28.30,0:52:30.04,EN,,0,0,0,,and automatic generation of solutions.\nDialogue: 0,0:52:30.64,0:52:31.61,EN,,0,0,0,,Do you see any steps\nDialogue: 0,0:52:31.82,0:52:33.36,EN,,0,0,0,,between specifications and solutions?\nDialogue: 0,0:52:37.25,0:52:38.22,EN,,0,0,0,,PROFESSOR: Steps between.\nDialogue: 0,0:52:38.72,0:52:39.37,EN,,0,0,0,,You mean, you're saying,\nDialogue: 0,0:52:39.37,0:52:42.60,EN,,0,0,0,,how you go about constructing\nDialogue: 0,0:52:42.60,0:52:44.78,EN,,0,0,0,,devices given that have specifications for the device?\nDialogue: 0,0:52:45.05,0:52:48.36,EN,,0,0,0,,AUDIENCE: There's a lot of software engineering\nDialogue: 0,0:52:48.36,0:52:49.90,EN,,0,0,0,,that goes through specifications through\nDialogue: 0,0:52:49.90,0:52:51.90,EN,,0,0,0,,many layers of design and then implementation.\nDialogue: 0,0:52:52.43,0:52:52.85,EN,,0,0,0,,PROFESSOR: Yes?\nDialogue: 0,0:52:52.85,0:52:53.70,EN,,0,0,0,,AUDIENCE: I was curious\nDialogue: 0,0:52:53.70,0:52:54.62,EN,,0,0,0,,if you think that's realistic.\nDialogue: 0,0:52:55.60,0:52:57.17,EN,,0,0,0,,PROFESSOR: Well I think that some of it's realistic\nDialogue: 0,0:52:57.17,0:52:58.10,EN,,0,0,0,,and some of it isn't.\nDialogue: 0,0:52:58.10,0:53:00.32,EN,,0,0,0,,I mean, surely if I want to build an electrical filter\nDialogue: 0,0:53:01.17,0:53:07.16,EN,,0,0,0,,and I have a rather interesting possibility.\nDialogue: 0,0:53:07.16,0:53:09.42,EN,,0,0,0,,Supposing I want to build a thing that matches\nDialogue: 0,0:53:09.64,0:53:14.07,EN,,0,0,0,,that matches some power output to the radio transmitter,\nDialogue: 0,0:53:14.47,0:53:18.75,EN,,0,0,0,,to some antenna.\nDialogue: 0,0:53:19.90,0:53:21.47,EN,,0,0,0,,And I'm really out of this power--\nDialogue: 0,0:53:21.48,0:53:23.04,EN,,0,0,0,,it's output tube out here.\nDialogue: 0,0:53:23.23,0:53:25.26,EN,,0,0,0,,And the problem is that they have different impedances.\nDialogue: 0,0:53:25.92,0:53:27.55,EN,,0,0,0,,I want them to match the impedances.\nDialogue: 0,0:53:27.55,0:53:28.97,EN,,0,0,0,,I also want to make a filter in there\nDialogue: 0,0:53:29.15,0:53:31.71,EN,,0,0,0,,which is going to get rid of some harmonic radiation.\nDialogue: 0,0:53:32.78,0:53:36.63,EN,,0,0,0,,Well one old-fashioned technique for doing this is called\nDialogue: 0,0:53:36.82,0:53:38.67,EN,,0,0,0,,image impedances, or something like that.\nDialogue: 0,0:53:38.86,0:53:39.50,EN,,0,0,0,,And what you do\nDialogue: 0,0:53:39.50,0:53:40.85,EN,,0,0,0,,is you say you have a basic module\nDialogue: 0,0:53:40.85,0:53:42.75,EN,,0,0,0,,called an L-section.\nDialogue: 0,0:53:43.30,0:53:43.98,EN,,0,0,0,,Looks like this.\nDialogue: 0,0:53:47.08,0:53:49.80,EN,,0,0,0,,If I happen to connect this to some resistance, r,\nDialogue: 0,0:53:50.05,0:53:52.60,EN,,0,0,0,,and if I make this impedance x, xl,\nDialogue: 0,0:53:52.72,0:53:55.20,EN,,0,0,0,,and if it happens to be q times r,\nDialogue: 0,0:53:55.26,0:53:58.52,EN,,0,0,0,,then this produces a low pass filter\nDialogue: 0,0:53:58.52,0:54:00.72,EN,,0,0,0,,with a q square plus one impedance match.\nDialogue: 0,0:54:02.11,0:54:02.86,EN,,0,0,0,,Just what I need.\nDialogue: 0,0:54:03.12,0:54:04.28,EN,,0,0,0,,Because now I can take two of these,\nDialogue: 0,0:54:04.30,0:54:05.08,EN,,0,0,0,,hook them together\nDialogue: 0,0:54:05.82,0:54:06.38,EN,,0,0,0,,like this.\nDialogue: 0,0:54:11.66,0:54:13.15,EN,,0,0,0,,OK, and I take another one\nDialogue: 0,0:54:16.00,0:54:17.45,EN,,0,0,0,,and I'll hook them together like that.\nDialogue: 0,0:54:18.29,0:54:19.95,EN,,0,0,0,,And I have two L-sections hooked together.\nDialogue: 0,0:54:20.32,0:54:23.07,EN,,0,0,0,,And this will step the impedance down to one that I know,\nDialogue: 0,0:54:23.37,0:54:25.22,EN,,0,0,0,,and this will step it up to one I know.\nDialogue: 0,0:54:25.53,0:54:26.64,EN,,0,0,0,,Each of these is a low pass filter\nDialogue: 0,0:54:26.67,0:54:27.82,EN,,0,0,0,,getting rid of some harmonics.\nDialogue: 0,0:54:28.09,0:54:29.07,EN,,0,0,0,,It's good filter,\nDialogue: 0,0:54:29.07,0:54:30.27,EN,,0,0,0,,it's called a pie-section filter.\nDialogue: 0,0:54:30.27,0:54:30.62,EN,,0,0,0,,Great.\nDialogue: 0,0:54:31.70,0:54:34.09,EN,,0,0,0,,Except for the fact that in doing what I just did,\nDialogue: 0,0:54:34.12,0:54:37.85,EN,,0,0,0,,I've made a terrible inefficiency in this system.\nDialogue: 0,0:54:38.62,0:54:39.60,EN,,0,0,0,,I've made two coils\nDialogue: 0,0:54:39.61,0:54:40.59,EN,,0,0,0,,where I should have made one.\nDialogue: 0,0:54:41.62,0:54:44.60,EN,,0,0,0,,And the problem with most software engineering art\nDialogue: 0,0:54:44.89,0:54:46.88,EN,,0,0,0,,is that there's no mechanism,\nDialogue: 0,0:54:46.92,0:54:48.65,EN,,0,0,0,,other than people optimization and compilers,\nDialogue: 0,0:54:48.80,0:54:51.34,EN,,0,0,0,,for getting rid of the redundant parts\nDialogue: 0,0:54:51.34,0:54:53.55,EN,,0,0,0,,that are constructed when doing top down design.\nDialogue: 0,0:54:55.35,0:54:56.07,EN,,0,0,0,,It's even worse,\nDialogue: 0,0:54:56.07,0:54:57.58,EN,,0,0,0,,there are lots of very important structures\nDialogue: 0,0:54:57.60,0:54:59.02,EN,,0,0,0,,that you can't construct at all this way.\nDialogue: 0,0:55:01.11,0:55:03.53,EN,,0,0,0,,So I think that the standard top down design\nDialogue: 0,0:55:03.53,0:55:04.87,EN,,0,0,0,,is a rather shallow business.\nDialogue: 0,0:55:05.71,0:55:06.60,EN,,0,0,0,,Doesn't really capture\nDialogue: 0,0:55:06.60,0:55:08.10,EN,,0,0,0,,what people want to do in design.\nDialogue: 0,0:55:08.31,0:55:10.10,EN,,0,0,0,,I'll give you another electrical example.\nDialogue: 0,0:55:10.10,0:55:11.75,EN,,0,0,0,,Electrical examples are so much clearer\nDialogue: 0,0:55:11.90,0:55:13.13,EN,,0,0,0,,than computational examples,\nDialogue: 0,0:55:13.16,0:55:14.78,EN,,0,0,0,,because computation examples require\nDialogue: 0,0:55:14.80,0:55:16.52,EN,,0,0,0,,a certain degree of complexity to explain them.\nDialogue: 0,0:55:17.22,0:55:19.16,EN,,0,0,0,,But one of my favorite examples\nDialogue: 0,0:55:19.16,0:55:20.04,EN,,0,0,0,,in the electrical world\nDialogue: 0,0:55:20.60,0:55:22.80,EN,,0,0,0,,is how would I ever come up with the output stage\nDialogue: 0,0:55:23.28,0:55:26.55,EN,,0,0,0,,of this inter-stage connection in an IF amplifier.\nDialogue: 0,0:55:27.53,0:55:29.44,EN,,0,0,0,,It's a little transistor here,\nDialogue: 0,0:55:29.52,0:55:31.50,EN,,0,0,0,,and let's see.\nDialogue: 0,0:55:32.41,0:55:33.40,EN,,0,0,0,,Well I'm going to have a tank,\nDialogue: 0,0:55:36.45,0:55:39.17,EN,,0,0,0,,and I'm going to hook this up to, say,\nDialogue: 0,0:55:41.37,0:55:43.97,EN,,0,0,0,,I'm going to link-couple that to the input of the next stage.\nDialogue: 0,0:55:44.36,0:55:47.47,EN,,0,0,0,,Here's a perfectly plausible plan--\nDialogue: 0,0:55:48.22,0:55:50.87,EN,,0,0,0,,well except for the fact that since I put that going up\nDialogue: 0,0:55:50.87,0:55:52.92,EN,,0,0,0,,I should make that going that way. OK?\nDialogue: 0,0:55:53.17,0:55:55.45,EN,,0,0,0,,Here's a perfectly plausible plan for a--\nDialogue: 0,0:55:55.98,0:55:56.57,EN,,0,0,0,,no I shouldn't.\nDialogue: 0,0:55:57.12,0:55:57.79,EN,,0,0,0,,I'm dumb.\nDialogue: 0,0:55:58.40,0:55:59.07,EN,,0,0,0,,Excuse me.\nDialogue: 0,0:55:59.69,0:56:00.42,EN,,0,0,0,,Doesn't matter.\nDialogue: 0,0:56:00.73,0:56:01.54,EN,,0,0,0,,The point is it's a perfect\nDialogue: 0,0:56:01.54,0:56:03.42,EN,,0,0,0,,plan for a couple two stages together.\nDialogue: 0,0:56:04.54,0:56:06.92,EN,,0,0,0,,Now what the problem is what's this hierarchically?\nDialogue: 0,0:56:07.62,0:56:08.80,EN,,0,0,0,,It's not one thing.\nDialogue: 0,0:56:09.48,0:56:11.99,EN,,0,0,0,,Hierarchically it doesn't make any sense at all.\nDialogue: 0,0:56:11.99,0:56:14.32,EN,,0,0,0,,It's the inductance of a tuned circuit,\nDialogue: 0,0:56:15.55,0:56:18.02,EN,,0,0,0,,it's the primary of a transformer,\nDialogue: 0,0:56:19.10,0:56:21.82,EN,,0,0,0,,and it's also the DC path by\nDialogue: 0,0:56:21.82,0:56:23.57,EN,,0,0,0,,which bias conditions get to the\nDialogue: 0,0:56:23.57,0:56:25.10,EN,,0,0,0,,collector of that transistor.\nDialogue: 0,0:56:26.46,0:56:28.35,EN,,0,0,0,,And there's no simple top-down design\nDialogue: 0,0:56:28.38,0:56:30.17,EN,,0,0,0,,that's going to produce a structure like that\nDialogue: 0,0:56:30.22,0:56:34.02,EN,,0,0,0,,with so many overlapping uses for a particular thing.\nDialogue: 0,0:56:34.53,0:56:36.72,EN,,0,0,0,,Playing Scrabble,\nDialogue: 0,0:56:36.96,0:56:39.88,EN,,0,0,0,,where you have to do triple word scores, or whatever,\nDialogue: 0,0:56:40.49,0:56:43.60,EN,,0,0,0,,is not so easy in top-down design strategy.\nDialogue: 0,0:56:44.95,0:56:47.08,EN,,0,0,0,,Yet most of real engineering is based on\nDialogue: 0,0:56:47.36,0:56:50.70,EN,,0,0,0,,on getting the most oomph for effort.\nDialogue: 0,0:56:52.14,0:56:53.52,EN,,0,0,0,,And that's what you're seeing here.\nDialogue: 0,0:56:54.86,0:56:55.55,EN,,0,0,0,,Yeah?\nDialogue: 0,0:56:55.55,0:56:56.81,EN,,0,0,0,,AUDIENCE: Is this the last question?\nDialogue: 0,0:57:00.28,0:57:02.03,EN,,0,0,0,,[LAUGHTER]\nDialogue: 0,0:57:18.64,0:57:19.63,EN,,0,0,0,,PROFESSOR: Apparently so.\nDialogue: 0,0:57:23.57,0:57:24.12,EN,,0,0,0,,Thank you.\nDialogue: 0,0:57:25.90,0:57:36.50,EN,,0,0,0,,[APPLAUSE]\nDialogue: 0,0:00:00.00,0:00:03.48,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:00.00,0:00:03.48,Declare,,0,0,0,,{\\fad(500,500)\\pos(313,99)}“让我们举杯，祝福那些\\N\\N\\N\\N将他们的思想镶嵌在\\N\\N\\N\\N　　　重重括号之间的Lisp程序员。”\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N杨启钊\\N（windfarer）\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:04.75,0:00:11.77,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:11.88,0:00:15.72,Declare,,0,0,0,,{\\an2\\fad(500,500)}存储分配与垃圾收集\nDialogue: 0,0:00:18.91,0:00:20.61,Default,,0,0,0,,教授: 接下来我要解开\nDialogue: 0,0:00:21.16,0:00:23.36,Default,,0,0,0,,目前仅剩的谜团\nDialogue: 0,0:00:24.44,0:00:28.80,Default,,0,0,0,,我们能毫无顾虑地进行CONS\nDialogue: 0,0:00:30.00,0:00:31.62,Default,,0,0,0,,就好像空间足够多一样\nDialogue: 0,0:00:32.80,0:00:36.32,Default,,0,0,0,,我们总是在使用\nDialogue: 0,0:00:36.51,0:00:37.44,Default,,0,0,0,,CAR和CDR\nDialogue: 0,0:00:37.47,0:00:38.72,Default,,0,0,0,,并假设知道我们知道\nDialogue: 0,0:00:38.75,0:00:39.74,Default,,0,0,0,,它们是如何实现的\nDialogue: 0,0:00:40.02,0:00:40.67,Default,,0,0,0,,事实上\nDialogue: 0,0:00:41.07,0:00:44.40,Default,,0,0,0,,我们认为它们是基本过程\nDialogue: 0,0:00:45.37,0:00:47.57,Default,,0,0,0,,但这没有真正解决问题\nDialogue: 0,0:00:47.73,0:00:50.25,Default,,0,0,0,,因为过程依赖各种复杂的机制\nDialogue: 0,0:00:50.27,0:00:51.37,Default,,0,0,0,,需要诸如环境结构之类的东西\nDialogue: 0,0:00:51.64,0:00:52.76,Default,,0,0,0,,才能运行起来\nDialogue: 0,0:00:53.01,0:00:54.89,Default,,0,0,0,,而归根结底它们也是\nDialogue: 0,0:00:54.89,0:00:56.42,Default,,0,0,0,,由CONS之类的东西构成的\nDialogue: 0,0:00:56.70,0:00:58.47,Default,,0,0,0,,这的确没有解决问题\nDialogue: 0,0:00:59.38,0:01:01.13,Default,,0,0,0,,目前的问题是\nDialogue: 0,0:01:01.31,0:01:03.97,Default,,0,0,0,,粘合这些数据结构的是什么东西？\nDialogue: 0,0:01:04.76,0:01:06.40,Default,,0,0,0,,它可能是怎样的一个东西?\nDialogue: 0,0:01:07.04,0:01:10.46,Default,,0,0,0,,我们已经见过了一台机器\nDialogue: 0,0:01:10.46,0:01:13.96,Default,,0,0,0,,一台计算机具有一个控制器\nDialogue: 0,0:01:14.27,0:01:15.45,Default,,0,0,0,,和一些寄存器\nDialogue: 0,0:01:15.45,0:01:16.47,Default,,0,0,0,,还可能有一个栈\nDialogue: 0,0:01:16.98,0:01:18.12,Default,,0,0,0,,但是我们还没提到一些东西\nDialogue: 0,0:01:18.16,0:01:19.95,Default,,0,0,0,,例如 大内存\nDialogue: 0,0:01:20.57,0:01:22.38,Default,,0,0,0,,我想 现在是时候讨论它们了\nDialogue: 0,0:01:23.74,0:01:26.56,Default,,0,0,0,,但是先要说清楚\nDialogue: 0,0:01:26.59,0:01:27.88,Default,,0,0,0,,这个并不是必须的\nDialogue: 0,0:01:28.82,0:01:30.79,Default,,0,0,0,,只是一些实现上的细节\nDialogue: 0,0:01:31.10,0:01:32.60,Default,,0,0,0,,让我举个例子\nDialogue: 0,0:01:32.60,0:01:34.20,Default,,0,0,0,,如何用数字来表示这些东西\nDialogue: 0,0:01:35.23,0:01:36.82,Default,,0,0,0,,有个比较简单的方法\nDialogue: 0,0:01:37.59,0:01:39.00,Default,,0,0,0,,一位著名的逻辑学家 哥德尔\nDialogue: 0,0:01:44.09,0:01:46.01,Default,,0,0,0,,在20世纪30年代末\nDialogue: 0,0:01:46.38,0:01:48.70,Default,,0,0,0,,发明了一个很巧妙的方法\nDialogue: 0,0:01:48.70,0:01:52.27,Default,,0,0,0,,能够把复杂的表达式\nDialogue: 0,0:01:52.81,0:01:53.52,Default,,0,0,0,,表示成数字\nDialogue: 0,0:01:54.32,0:01:55.05,Default,,0,0,0,,例如\nDialogue: 0,0:01:55.05,0:01:58.00,Default,,0,0,0,,我不会照搬哥德尔的方法\nDialogue: 0,0:01:58.00,0:01:59.48,Default,,0,0,0,,因为他没有使用CONS之类的术语\nDialogue: 0,0:01:59.66,0:02:00.60,Default,,0,0,0,,他使用了其它的组合手段\nDialogue: 0,0:02:00.91,0:02:02.60,Default,,0,0,0,,来编码表达式\nDialogue: 0,0:02:03.09,0:02:03.88,Default,,0,0,0,,他的思路是\nDialogue: 0,0:02:03.92,0:02:06.81,Default,,0,0,0,,用不同数字分别代表每个代数式\nDialogue: 0,0:02:07.92,0:02:09.72,Default,,0,0,0,,通过组合各个部分的数字\nDialogue: 0,0:02:09.72,0:02:11.65,Default,,0,0,0,,来形成新的表达式\nDialogue: 0,0:02:12.47,0:02:13.45,Default,,0,0,0,,举例来说\nDialogue: 0,0:02:13.62,0:02:15.35,Default,,0,0,0,,我们在创造世界的时候\nDialogue: 0,0:02:15.35,0:02:18.01,Default,,0,0,0,,如果用数字\nDialogue: 0,0:02:20.78,0:02:22.22,Default,,0,0,0,,来表示对象\nDialogue: 0,0:02:30.67,0:02:37.93,Default,,0,0,0,,那么(CONS X Y)\nDialogue: 0,0:02:38.04,0:02:41.07,Default,,0,0,0,,就可以表示为\nDialogue: 0,0:02:41.55,0:02:43.77,Default,,0,0,0,,2^X * 3^Y\nDialogue: 0,0:02:46.13,0:02:48.03,Default,,0,0,0,,因为这样我们还能取出它的每一部分\nDialogue: 0,0:02:49.56,0:02:50.97,Default,,0,0,0,,举例来说\nDialogue: 0,0:02:51.18,0:02:55.88,Default,,0,0,0,,(CAR X)\nDialogue: 0,0:02:56.55,0:03:05.18,Default,,0,0,0,,就是X中因数2的个数\nDialogue: 0,0:03:06.69,0:03:08.78,Default,,0,0,0,,当然(CDR X)是一样的\nDialogue: 0,0:03:10.69,0:03:15.57,Default,,0,0,0,,它就X中因数3的个数\nDialogue: 0,0:03:16.51,0:03:18.65,Default,,0,0,0,,这是个非常合理的方案\nDialogue: 0,0:03:19.10,0:03:20.11,Default,,0,0,0,,只不过就是\nDialogue: 0,0:03:20.12,0:03:22.52,Default,,0,0,0,,数字的位数\nDialogue: 0,0:03:22.83,0:03:23.98,Default,,0,0,0,,会急剧地增大\nDialogue: 0,0:03:24.32,0:03:26.55,Default,,0,0,0,,甚至比宇宙中的粒子还多\nDialogue: 0,0:03:27.95,0:03:29.88,Default,,0,0,0,,所以除了在理论中\nDialogue: 0,0:03:29.90,0:03:31.21,Default,,0,0,0,,没有实现这种方案的好办法\nDialogue: 0,0:03:33.43,0:03:34.48,Default,,0,0,0,,另一方面\nDialogue: 0,0:03:35.12,0:03:37.55,Default,,0,0,0,,也有其它的表示方式\nDialogue: 0,0:03:38.45,0:03:40.01,Default,,0,0,0,,我们把它们表示为\nDialogue: 0,0:03:40.25,0:03:42.42,Default,,0,0,0,,一些小盒子\nDialogue: 0,0:03:43.32,0:03:46.43,Default,,0,0,0,,我们把CONS结构\nDialogue: 0,0:03:46.50,0:03:48.05,Default,,0,0,0,,想象为这样的东西\nDialogue: 0,0:03:50.28,0:03:52.57,Default,,0,0,0,,它们是里面装着东西的小隔间\nDialogue: 0,0:03:53.56,0:03:55.47,Default,,0,0,0,,这些格子组成一个树\nDialogue: 0,0:03:57.21,0:03:59.97,Default,,0,0,0,,我希望半导体制造商\nDialogue: 0,0:03:59.97,0:04:02.07,Default,,0,0,0,,能够提供适配这样需求的芯片\nDialogue: 0,0:04:02.70,0:04:03.76,Default,,0,0,0,,但事实上\nDialogue: 0,0:04:03.85,0:04:05.31,Default,,0,0,0,,他们提供给我的却是\nDialogue: 0,0:04:06.20,0:04:07.96,Default,,0,0,0,,线性的内存\nDialogue: 0,0:04:09.38,0:04:13.46,Default,,0,0,0,,内存是一串小隔间\nDialogue: 0,0:04:15.12,0:04:16.34,Default,,0,0,0,,像这样的小隔间\nDialogue: 0,0:04:17.72,0:04:20.25,Default,,0,0,0,,每个小隔间里可以保存确定大小的对象\nDialogue: 0,0:04:20.94,0:04:22.20,Default,,0,0,0,,一个尺寸固定的对象\nDialogue: 0,0:04:23.39,0:04:24.07,Default,,0,0,0,,例如\nDialogue: 0,0:04:24.07,0:04:25.66,Default,,0,0,0,,一个含25个元素的表\nDialogue: 0,0:04:25.66,0:04:26.64,Default,,0,0,0,,就放不进这里\nDialogue: 0,0:04:28.55,0:04:29.26,Default,,0,0,0,,然而 它们中的每一个\nDialogue: 0,0:04:29.29,0:04:30.88,Default,,0,0,0,,都是由地址索引的\nDialogue: 0,0:04:33.97,0:04:34.99,Default,,0,0,0,,因此它们的地址可能是\nDialogue: 0,0:04:35.02,0:04:35.50,Default,,0,0,0,,这里是0\nDialogue: 0,0:04:35.50,0:04:36.22,Default,,0,0,0,,这里是1\nDialogue: 0,0:04:36.22,0:04:36.70,Default,,0,0,0,,这里是2\nDialogue: 0,0:04:36.70,0:04:37.25,Default,,0,0,0,,这里是3\nDialogue: 0,0:04:37.25,0:04:37.94,Default,,0,0,0,,以此类推\nDialogue: 0,0:04:38.06,0:04:40.40,Default,,0,0,0,,这里写的数字并不重要\nDialogue: 0,0:04:40.40,0:04:41.68,Default,,0,0,0,,重要的是 它们不重复\nDialogue: 0,0:04:41.95,0:04:43.42,Default,,0,0,0,,有了它们就能找到下一个在哪\nDialogue: 0,0:04:44.97,0:04:46.14,Default,,0,0,0,,在其中每一个小隔间里面\nDialogue: 0,0:04:46.36,0:04:49.11,Default,,0,0,0,,我们可以把东西放进去\nDialogue: 0,0:04:49.53,0:04:50.77,Default,,0,0,0,,对于没有造过计算机的我们来说\nDialogue: 0,0:04:51.02,0:04:53.66,Default,,0,0,0,,内存就是这样子的\nDialogue: 0,0:04:54.15,0:04:54.65,Default,,0,0,0,,现在\nDialogue: 0,0:04:56.69,0:04:57.53,Default,,0,0,0,,现在的问题是\nDialogue: 0,0:04:57.53,0:04:59.97,Default,,0,0,0,,如何用这样的结构\nDialogue: 0,0:05:00.42,0:05:01.72,Default,,0,0,0,,来实现这个树形结构\nDialogue: 0,0:05:03.29,0:05:04.57,Default,,0,0,0,,其实并不难\nDialogue: 0,0:05:04.57,0:05:06.35,Default,,0,0,0,,已经有大量的方案来做这个了\nDialogue: 0,0:05:06.87,0:05:08.80,Default,,0,0,0,,最重要的一个方案是\nDialogue: 0,0:05:08.80,0:05:11.18,Default,,0,0,0,,假设半导体制造商\nDialogue: 0,0:05:11.20,0:05:13.90,Default,,0,0,0,,允许我安排自己的内存\nDialogue: 0,0:05:13.98,0:05:15.77,Default,,0,0,0,,使得其中每个小隔间都足够大\nDialogue: 0,0:05:16.28,0:05:18.20,Default,,0,0,0,,能够装得下另一个的地址\nDialogue: 0,0:05:19.35,0:05:20.83,Default,,0,0,0,,我需要这么来安排\nDialogue: 0,0:05:22.05,0:05:23.45,Default,,0,0,0,,事实上它需要更大一点\nDialogue: 0,0:05:23.48,0:05:27.52,Default,,0,0,0,,因为我还要在里面存放一些信息\nDialogue: 0,0:05:27.56,0:05:30.09,Default,,0,0,0,,它标示了这里面是什么东西\nDialogue: 0,0:05:30.39,0:05:31.64,Default,,0,0,0,,我们过一会就能看到\nDialogue: 0,0:05:32.62,0:05:34.40,Default,,0,0,0,,当然 如果半导体制造商\nDialogue: 0,0:05:34.43,0:05:35.88,Default,,0,0,0,,没有这么来制造\nDialogue: 0,0:05:36.08,0:05:38.44,Default,,0,0,0,,我就需要用一些机智的方式\nDialogue: 0,0:05:38.57,0:05:41.82,Default,,0,0,0,,把它们组合起来以供使用\nDialogue: 0,0:05:43.77,0:05:47.05,Default,,0,0,0,,我们想象一下\nDialogue: 0,0:05:47.05,0:05:49.54,Default,,0,0,0,,把这个复杂的树形结构\nDialogue: 0,0:05:49.54,0:05:51.20,Default,,0,0,0,,塞进线性内存里\nDialogue: 0,0:05:51.74,0:05:54.47,Default,,0,0,0,,我们来看第一张幻灯片\nDialogue: 0,0:05:54.47,0:05:58.30,Default,,0,0,0,,可以看到一个传统的实现方案\nDialogue: 0,0:05:59.49,0:06:02.62,Default,,0,0,0,,它是把表结构放入线性内存\nDialogue: 0,0:06:03.22,0:06:05.87,Default,,0,0,0,,的标准方式\nDialogue: 0,0:06:06.27,0:06:08.32,Default,,0,0,0,,我们把这块内存\nDialogue: 0,0:06:08.88,0:06:11.12,Default,,0,0,0,,分为两部分\nDialogue: 0,0:06:12.03,0:06:13.42,Default,,0,0,0,,一个叫THE-CARS的数组\nDialogue: 0,0:06:14.45,0:06:15.88,Default,,0,0,0,,一个叫THE-CDRS的数组\nDialogue: 0,0:06:17.58,0:06:18.86,Default,,0,0,0,,无论它们是\nDialogue: 0,0:06:18.88,0:06:21.04,Default,,0,0,0,,顺序的地址或是其它的\nDialogue: 0,0:06:21.12,0:06:22.00,Default,,0,0,0,,其实并不重要\nDialogue: 0,0:06:22.87,0:06:25.20,Default,,0,0,0,,这是实现细节了\nDialogue: 0,0:06:25.80,0:06:28.40,Default,,0,0,0,,但有两个数组\nDialogue: 0,0:06:28.96,0:06:30.36,Default,,0,0,0,,线性数组是由\nDialogue: 0,0:06:30.46,0:06:32.59,Default,,0,0,0,,顺序的下标索引的\nDialogue: 0,0:06:34.84,0:06:36.85,Default,,0,0,0,,每个小格子里存的\nDialogue: 0,0:06:37.46,0:06:39.85,Default,,0,0,0,,是一个带类型的对象\nDialogue: 0,0:06:41.43,0:06:42.57,Default,,0,0,0,,这里的类型\nDialogue: 0,0:06:42.57,0:06:45.71,Default,,0,0,0,,以字母P开头\nDialogue: 0,0:06:45.71,0:06:46.57,Default,,0,0,0,,表示序对\nDialogue: 0,0:06:47.79,0:06:49.37,Default,,0,0,0,,以N开头 表示数字\nDialogue: 0,0:06:50.04,0:06:52.25,Default,,0,0,0,,E开头 表示空表\nDialogue: 0,0:06:54.81,0:06:55.83,Default,,0,0,0,,也就是表尾标志\nDialogue: 0,0:06:57.02,0:06:58.59,Default,,0,0,0,,如果我们想表示\nDialogue: 0,0:06:58.99,0:06:59.97,Default,,0,0,0,,这样一个对象\nDialogue: 0,0:07:00.01,0:07:02.16,Default,,0,0,0,,首元素为(1 2)\nDialogue: 0,0:07:02.65,0:07:04.01,Default,,0,0,0,,然后3、4分别作为\nDialogue: 0,0:07:04.01,0:07:05.50,Default,,0,0,0,,它的第二和第三个元素\nDialogue: 0,0:07:06.43,0:07:08.83,Default,,0,0,0,,这个表的第一部分也是一个表\nDialogue: 0,0:07:09.35,0:07:10.65,Default,,0,0,0,,后面接着是两个数字\nDialogue: 0,0:07:10.65,0:07:12.00,Default,,0,0,0,,分别为第二和第三部分\nDialogue: 0,0:07:12.87,0:07:14.81,Default,,0,0,0,,现在我们用盒子-指针表示法\nDialogue: 0,0:07:14.84,0:07:16.67,Default,,0,0,0,,来描绘它\nDialogue: 0,0:07:17.32,0:07:18.00,Default,,0,0,0,,你能发现\nDialogue: 0,0:07:18.00,0:07:20.04,Default,,0,0,0,,这里有三个单元\nDialogue: 0,0:07:20.25,0:07:22.01,Default,,0,0,0,,它们的CAR指针\nDialogue: 0,0:07:22.27,0:07:27.10,Default,,0,0,0,,分别指向对象(1 2)、3以及4\nDialogue: 0,0:07:28.39,0:07:29.75,Default,,0,0,0,,当然这个(1 2)\nDialogue: 0,0:07:29.75,0:07:31.32,Default,,0,0,0,,即整个结构的CAR\nDialogue: 0,0:07:31.32,0:07:32.65,Default,,0,0,0,,本身就是一个子结构\nDialogue: 0,0:07:32.88,0:07:34.75,Default,,0,0,0,,包含一个像这样的子表\nDialogue: 0,0:07:35.94,0:07:37.07,Default,,0,0,0,,我要做的是\nDialogue: 0,0:07:37.20,0:07:39.92,Default,,0,0,0,,就是按照下标\nDialogue: 0,0:07:39.95,0:07:41.46,Default,,0,0,0,,把它们放进去\nDialogue: 0,0:07:41.84,0:07:43.40,Default,,0,0,0,,像这里的1\nDialogue: 0,0:07:43.56,0:07:47.05,Default,,0,0,0,,代表了这个格子的下标\nDialogue: 0,0:07:49.85,0:07:51.47,Default,,0,0,0,,这里的指针\nDialogue: 0,0:07:52.37,0:07:54.86,Default,,0,0,0,,是对THE-CARS\nDialogue: 0,0:07:55.07,0:07:57.29,Default,,0,0,0,,和THE-CDRS里的小格子的引用\nDialogue: 0,0:07:57.40,0:07:58.67,Default,,0,0,0,,它在我的线性内存中\nDialogue: 0,0:07:58.76,0:08:00.33,Default,,0,0,0,,被标记为1的地方\nDialogue: 0,0:08:02.00,0:08:04.06,Default,,0,0,0,,如果我想把这个结构\nDialogue: 0,0:08:04.16,0:08:05.26,Default,,0,0,0,,塞进线性内存中\nDialogue: 0,0:08:05.85,0:08:07.52,Default,,0,0,0,,要做的是\nDialogue: 0,0:08:07.52,0:08:11.88,Default,,0,0,0,,把它放进格子1中\nDialogue: 0,0:08:11.95,0:08:12.66,Default,,0,0,0,,我要选取1号格子\nDialogue: 0,0:08:12.66,0:08:13.85,Default,,0,0,0,,这个就是1号格子\nDialogue: 0,0:08:14.27,0:08:16.22,Default,,0,0,0,,这是它的CAR\nDialogue: 0,0:08:16.22,0:08:17.74,Default,,0,0,0,,我要把它赋值给一个序对\nDialogue: 0,0:08:17.95,0:08:18.72,Default,,0,0,0,,这个序对\nDialogue: 0,0:08:20.02,0:08:21.55,Default,,0,0,0,,序号是5\nDialogue: 0,0:08:22.59,0:08:23.90,Default,,0,0,0,,它的CDR\nDialogue: 0,0:08:23.90,0:08:25.13,Default,,0,0,0,,就是这个\nDialogue: 0,0:08:25.39,0:08:26.13,Default,,0,0,0,,它是个序对\nDialogue: 0,0:08:26.13,0:08:27.70,Default,,0,0,0,,我会把它放到2的位置\nDialogue: 0,0:08:28.34,0:08:28.98,Default,,0,0,0,,即P2\nDialogue: 0,0:08:30.89,0:08:32.95,Default,,0,0,0,,我们看P2\nDialogue: 0,0:08:32.95,0:08:34.72,Default,,0,0,0,,P2的CAR\nDialogue: 0,0:08:34.90,0:08:37.22,Default,,0,0,0,,是数字3\nDialogue: 0,0:08:37.34,0:08:38.64,Default,,0,0,0,,如你所见N3\nDialogue: 0,0:08:39.52,0:08:41.52,Default,,0,0,0,,这里 它的CDR\nDialogue: 0,0:08:41.72,0:08:43.40,Default,,0,0,0,,是一个序对\nDialogue: 0,0:08:43.97,0:08:45.81,Default,,0,0,0,,在位置4\nDialogue: 0,0:08:46.64,0:08:47.79,Default,,0,0,0,,这就是P4\nDialogue: 0,0:08:48.65,0:08:51.16,Default,,0,0,0,,P4是一个数字\nDialogue: 0,0:08:51.85,0:08:53.87,Default,,0,0,0,,它的CAR部分是数字4\nDialogue: 0,0:08:54.60,0:08:55.65,Default,,0,0,0,,它的CDR\nDialogue: 0,0:08:55.84,0:08:58.48,Default,,0,0,0,,是个空表 就在这儿\nDialogue: 0,0:08:59.17,0:08:59.90,Default,,0,0,0,,这个表就结束了\nDialogue: 0,0:09:00.69,0:09:04.57,Default,,0,0,0,,这就是在线性内存中\nDialogue: 0,0:09:04.90,0:09:09.55,Default,,0,0,0,,表示二叉树的传统方式\nDialogue: 0,0:09:11.62,0:09:15.10,Default,,0,0,0,,那么 下一个问题是\nDialogue: 0,0:09:15.10,0:09:16.36,Default,,0,0,0,,我们需要关心\nDialogue: 0,0:09:16.60,0:09:18.19,Default,,0,0,0,,如何去实现\nDialogue: 0,0:09:18.44,0:09:20.33,Default,,0,0,0,,这意味着当我写下一个过程\nDialogue: 0,0:09:20.36,0:09:23.62,Default,,0,0,0,,用来给A赋值时\nDialogue: 0,0:09:24.54,0:09:27.10,Default,,0,0,0,,使用寄存机器的代码来编写的\nDialogue: 0,0:09:27.21,0:09:30.14,Default,,0,0,0,,(ASSIGN A (FETCH B))\nDialogue: 0,0:09:30.84,0:09:31.85,Default,,0,0,0,,我实际上想做的是\nDialogue: 0,0:09:31.97,0:09:37.10,Default,,0,0,0,,定位这些元素\nDialogue: 0,0:09:38.74,0:09:40.25,Default,,0,0,0,,那段机器代码只是\nDialogue: 0,0:09:40.68,0:09:42.94,Default,,0,0,0,,这个复杂过程的简写\nDialogue: 0,0:09:44.47,0:09:46.33,Default,,0,0,0,,当然 为了把它“写下来”\nDialogue: 0,0:09:46.35,0:09:48.59,Default,,0,0,0,,我要引入一种\nDialogue: 0,0:09:48.62,0:09:49.42,Default,,0,0,0,,称为“向量”的结构\nDialogue: 0,0:09:52.12,0:09:53.31,Default,,0,0,0,,我们得有一种东西\nDialogue: 0,0:09:53.48,0:09:54.54,Default,,0,0,0,,用来引用向量\nDialogue: 0,0:09:56.84,0:09:58.51,Default,,0,0,0,,这样我们就能把它写下来\nDialogue: 0,0:09:58.71,0:10:00.22,Default,,0,0,0,,它的参数之一是向量的名字\nDialogue: 0,0:10:01.02,0:10:03.97,Default,,0,0,0,,我觉得这个名字起得不太靠谱\nDialogue: 0,0:10:03.97,0:10:09.40,Default,,0,0,0,,它接受VECTOR和INDEX两个参数\nDialogue: 0,0:10:11.20,0:10:13.05,Default,,0,0,0,,我可以用VECTOR-SET!\nDialogue: 0,0:10:13.10,0:10:14.27,Default,,0,0,0,,来为其中的分量赋值\nDialogue: 0,0:10:14.65,0:10:15.60,Default,,0,0,0,,我不太在意\nDialogue: 0,0:10:16.28,0:10:17.55,Default,,0,0,0,,我们来看一看\nDialogue: 0,0:10:18.11,0:10:20.42,Default,,0,0,0,,在这种实现中\nDialogue: 0,0:10:21.25,0:10:23.18,Default,,0,0,0,,CAR和CDR是什么样子的\nDialogue: 0,0:10:26.47,0:10:28.41,Default,,0,0,0,,比如说 如果我刚好有\nDialogue: 0,0:10:28.88,0:10:30.80,Default,,0,0,0,,一个寄存器B\nDialogue: 0,0:10:31.15,0:10:34.64,Default,,0,0,0,,它存了一个序对的下标\nDialogue: 0,0:10:35.95,0:10:38.80,Default,,0,0,0,,即它是指向一个序对的指针\nDialogue: 0,0:10:39.35,0:10:40.85,Default,,0,0,0,,我可以取它的CAR\nDialogue: 0,0:10:41.55,0:10:44.11,Default,,0,0,0,,存到寄存器A里面\nDialogue: 0,0:10:44.49,0:10:46.86,Default,,0,0,0,,事实上它是\nDialogue: 0,0:10:47.37,0:10:50.19,Default,,0,0,0,,把A赋值为--\nDialogue: 0,0:10:50.19,0:10:51.92,Default,,0,0,0,,引用向量的一个分量--\nDialogue: 0,0:10:52.80,0:10:55.24,Default,,0,0,0,,或者你可以把它叫做索引一个数组\nDialogue: 0,0:10:55.42,0:10:57.63,Default,,0,0,0,,目标向量为THE-CARS\nDialogue: 0,0:10:58.40,0:11:00.92,Default,,0,0,0,,而目标分量是B\nDialogue: 0,0:11:02.65,0:11:03.63,Default,,0,0,0,,CDR的操作也类似\nDialogue: 0,0:11:04.10,0:11:05.72,Default,,0,0,0,,我们可以用同样的方式\nDialogue: 0,0:11:05.90,0:11:08.32,Default,,0,0,0,,来对数据结构赋值\nDialogue: 0,0:11:08.92,0:11:10.92,Default,,0,0,0,,如果我们需要这么做的话\nDialogue: 0,0:11:11.84,0:11:13.80,Default,,0,0,0,,构建这个并不太难\nDialogue: 0,0:11:14.58,0:11:15.72,Default,,0,0,0,,下一个问题是\nDialogue: 0,0:11:15.72,0:11:17.00,Default,,0,0,0,,我们如何分配它们\nDialogue: 0,0:11:18.01,0:11:20.13,Default,,0,0,0,,我们经常需要一个新的序对\nDialogue: 0,0:11:21.40,0:11:23.42,Default,,0,0,0,,当然 CONS并没有长在树上\nDialogue: 0,0:11:23.79,0:11:24.81,Default,,0,0,0,,或许它们应该那样\nDialogue: 0,0:11:25.34,0:11:26.56,Default,,0,0,0,,我必须得有某种方法\nDialogue: 0,0:11:26.70,0:11:28.97,Default,,0,0,0,,来获得一个可用的序对\nDialogue: 0,0:11:29.98,0:11:31.47,Default,,0,0,0,,我需要某种方案\nDialogue: 0,0:11:31.47,0:11:33.04,Default,,0,0,0,,当内存不再使用的时候\nDialogue: 0,0:11:33.69,0:11:35.05,Default,,0,0,0,,我可以重新分配它们\nDialogue: 0,0:11:35.63,0:11:37.38,Default,,0,0,0,,有很多方案可以实现这一点\nDialogue: 0,0:11:37.38,0:11:39.07,Default,,0,0,0,,现在我给你们展示的这个东西\nDialogue: 0,0:11:39.23,0:11:40.45,Default,,0,0,0,,并是不必要的\nDialogue: 0,0:11:42.10,0:11:43.18,Default,,0,0,0,,然而它很方便\nDialogue: 0,0:11:43.20,0:11:44.44,Default,,0,0,0,,并且被实现很多次了\nDialogue: 0,0:11:44.60,0:11:47.20,Default,,0,0,0,,其中一种基于“空闲表”的分配方案\nDialogue: 0,0:11:47.66,0:11:48.68,Default,,0,0,0,,它的意思就是\nDialogue: 0,0:11:48.68,0:11:51.12,Default,,0,0,0,,世界上所有的空闲内存\nDialogue: 0,0:11:51.55,0:11:53.08,Default,,0,0,0,,都连在一个链表中\nDialogue: 0,0:11:54.55,0:11:56.22,Default,,0,0,0,,就像其它东西一样\nDialogue: 0,0:11:56.96,0:11:59.07,Default,,0,0,0,,每当你需要一个新的格子\nDialogue: 0,0:11:59.07,0:12:00.12,Default,,0,0,0,,来进行CONS的时候\nDialogue: 0,0:12:00.95,0:12:02.26,Default,,0,0,0,,你选择第一个格子\nDialogue: 0,0:12:02.26,0:12:03.82,Default,,0,0,0,,将它的CDR指向空闲表\nDialogue: 0,0:12:04.32,0:12:05.55,Default,,0,0,0,,然后分配它\nDialogue: 0,0:12:06.03,0:12:08.32,Default,,0,0,0,,就像这样\nDialogue: 0,0:12:09.53,0:12:13.32,Default,,0,0,0,,这里 我们的空闲表\nDialogue: 0,0:12:13.95,0:12:16.81,Default,,0,0,0,,就是从6开始\nDialogue: 0,0:12:18.51,0:12:23.47,Default,,0,0,0,,它是一个指向8的指针\nDialogue: 0,0:12:24.86,0:12:25.62,Default,,0,0,0,,它表示\nDialogue: 0,0:12:25.62,0:12:26.55,Default,,0,0,0,,当前这个是空闲的\nDialogue: 0,0:12:26.55,0:12:27.95,Default,,0,0,0,,下一个在位置8\nDialogue: 0,0:12:28.87,0:12:29.88,Default,,0,0,0,,这个是空闲的\nDialogue: 0,0:12:30.04,0:12:32.08,Default,,0,0,0,,下一个在位置3\nDialogue: 0,0:12:32.32,0:12:33.45,Default,,0,0,0,,下一个是空闲的\nDialogue: 0,0:12:33.93,0:12:34.95,Default,,0,0,0,,这个是空闲的\nDialogue: 0,0:12:35.04,0:12:37.68,Default,,0,0,0,,下一个在位置0\nDialogue: 0,0:12:37.87,0:12:38.49,Default,,0,0,0,,这个是空闲的\nDialogue: 0,0:12:38.52,0:12:39.82,Default,,0,0,0,,下一个在位置15\nDialogue: 0,0:12:40.94,0:12:41.84,Default,,0,0,0,,以此类推\nDialogue: 0,0:12:42.78,0:12:44.64,Default,,0,0,0,,我们可以想象有这样的结构\nDialogue: 0,0:12:46.40,0:12:48.03,Default,,0,0,0,,一旦我们有了这样的机制\nDialogue: 0,0:12:49.45,0:12:50.92,Default,,0,0,0,,那么当你需要空间的时候\nDialogue: 0,0:12:50.92,0:12:52.22,Default,,0,0,0,,就能获取一个\nDialogue: 0,0:12:53.82,0:12:56.46,Default,,0,0,0,,那些使用了CONS的程序\nDialogue: 0,0:12:57.45,0:12:59.13,Default,,0,0,0,,内存可能就是像这样的\nDialogue: 0,0:12:59.32,0:13:02.57,Default,,0,0,0,,把B和C进行CONS之后的值\nDialogue: 0,0:13:02.95,0:13:05.82,Default,,0,0,0,,赋值给A寄存器\nDialogue: 0,0:13:06.20,0:13:09.04,Default,,0,0,0,,结果包括B和C\nDialogue: 0,0:13:09.27,0:13:10.52,Default,,0,0,0,,我们要做的是\nDialogue: 0,0:13:10.56,0:13:12.24,Default,,0,0,0,,把当前的尾部格子 即空闲表的前个格子\nDialogue: 0,0:13:12.47,0:13:14.30,Default,,0,0,0,,让它的CDR指向空闲表\nDialogue: 0,0:13:15.64,0:13:18.33,Default,,0,0,0,,我们要把THE-CARS中\nDialogue: 0,0:13:18.41,0:13:22.49,Default,,0,0,0,,由A索引的格子\nDialogue: 0,0:13:23.13,0:13:25.45,Default,,0,0,0,,修改为B中的内容\nDialogue: 0,0:13:25.90,0:13:28.65,Default,,0,0,0,,THE-CDRS中由A索引的格子\nDialogue: 0,0:13:29.20,0:13:31.72,Default,,0,0,0,,修改为C的值\nDialogue: 0,0:13:33.20,0:13:34.76,Default,,0,0,0,,现在A所指的格子里面\nDialogue: 0,0:13:34.78,0:13:36.65,Default,,0,0,0,,就是新构建好的对象了\nDialogue: 0,0:13:36.81,0:13:37.92,Default,,0,0,0,,这就是我们要的对象\nDialogue: 0,0:13:40.47,0:13:42.50,Default,,0,0,0,,我之前告诉过你们\nDialogue: 0,0:13:42.50,0:13:43.97,Default,,0,0,0,,这里撒了个谎\nDialogue: 0,0:13:43.97,0:13:45.32,Default,,0,0,0,,也就是在这里的某处\nDialogue: 0,0:13:45.53,0:13:47.32,Default,,0,0,0,,我本来应该\nDialogue: 0,0:13:48.45,0:13:50.48,Default,,0,0,0,,把我CONS起来的对象\nDialogue: 0,0:13:50.51,0:13:51.87,Default,,0,0,0,,设置为序对类型\nDialogue: 0,0:13:52.30,0:13:53.05,Default,,0,0,0,,但我没有\nDialogue: 0,0:13:53.51,0:13:56.57,Default,,0,0,0,,因此这里应该需要设置一些比特位\nDialogue: 0,0:13:56.60,0:13:57.76,Default,,0,0,0,,我只是还没把它写下来\nDialogue: 0,0:13:59.81,0:14:00.86,Default,,0,0,0,,当然 这个很好实现\nDialogue: 0,0:14:00.89,0:14:02.45,Default,,0,0,0,,因为空闲表本来就是用序对实现的\nDialogue: 0,0:14:03.10,0:14:04.88,Default,,0,0,0,,因此这是没问题的\nDialogue: 0,0:14:06.43,0:14:07.74,Default,,0,0,0,,但这也就是--\nDialogue: 0,0:14:07.82,0:14:09.92,Default,,0,0,0,,这些都是无关紧要的细节\nDialogue: 0,0:14:10.22,0:14:12.88,Default,,0,0,0,,取决于那些想要自制\nDialogue: 0,0:14:12.92,0:14:14.27,Default,,0,0,0,,计算机或Lisp系统的\nDialogue: 0,0:14:14.33,0:14:16.68,Default,,0,0,0,,程序员或架构师\nDialogue: 0,0:14:17.54,0:14:18.71,Default,,0,0,0,,例如\nDialogue: 0,0:14:19.07,0:14:20.24,Default,,0,0,0,,看这个\nDialogue: 0,0:14:20.65,0:14:23.45,Default,,0,0,0,,假设我们要为\nDialogue: 0,0:14:23.55,0:14:26.83,Default,,0,0,0,,这个之前见过的数据结构分配空间\nDialogue: 0,0:14:27.21,0:14:30.26,Default,,0,0,0,,假设我要分配一个新格子\nDialogue: 0,0:14:30.55,0:14:36.61,Default,,0,0,0,,来表示表(1 1 2)\nDialogue: 0,0:14:37.24,0:14:39.87,Default,,0,0,0,,其中(1 2)又是\nDialogue: 0,0:14:40.28,0:14:42.16,Default,,0,0,0,,之前一个表的CAR元素\nDialogue: 0,0:14:43.43,0:14:44.45,Default,,0,0,0,,这不怎么难\nDialogue: 0,0:14:44.78,0:14:46.20,Default,,0,0,0,,我用1号单元来存放数字“1”\nDialogue: 0,0:14:46.20,0:14:49.17,Default,,0,0,0,,那么P1表示的就是这个单元\nDialogue: 0,0:14:49.53,0:14:50.83,Default,,0,0,0,,这个是P5\nDialogue: 0,0:14:51.67,0:14:53.51,Default,,0,0,0,,它是应该是这个的CDR\nDialogue: 0,0:14:54.07,0:14:55.52,Default,,0,0,0,,现在我们要从空闲表中取出一些东西\nDialogue: 0,0:14:55.52,0:14:57.30,Default,,0,0,0,,空闲表现在是从6开始的\nDialogue: 0,0:14:57.78,0:15:00.18,Default,,0,0,0,,而在分配之后 空闲表将从8开始\nDialogue: 0,0:15:00.60,0:15:02.55,Default,,0,0,0,,一个从8开始的空闲表\nDialogue: 0,0:15:02.89,0:15:03.52,Default,,0,0,0,,当然\nDialogue: 0,0:15:03.72,0:15:06.04,Default,,0,0,0,,现在6里面是数字1\nDialogue: 0,0:15:06.15,0:15:07.10,Default,,0,0,0,,就是我们想要的\nDialogue: 0,0:15:07.39,0:15:11.56,Default,,0,0,0,,它的CDR是在位置5的序对\nDialogue: 0,0:15:13.33,0:15:14.50,Default,,0,0,0,,没费多少力气\nDialogue: 0,0:15:16.81,0:15:20.45,Default,,0,0,0,,这里依然存在的一个问题是\nDialogue: 0,0:15:21.00,0:15:23.40,Default,,0,0,0,,我们没有无限大的内存\nDialogue: 0,0:15:25.08,0:15:26.66,Default,,0,0,0,,如果我像这么操作了一会儿\nDialogue: 0,0:15:27.25,0:15:28.00,Default,,0,0,0,,比如说\nDialogue: 0,0:15:28.01,0:15:30.14,Default,,0,0,0,,假设进行一次CONS花费1微秒\nDialogue: 0,0:15:30.60,0:15:32.97,Default,,0,0,0,,如果要进行一百万次CONS\nDialogue: 0,0:15:33.60,0:15:35.27,Default,,0,0,0,,那么我就要消耗1秒钟的时间\nDialogue: 0,0:15:35.95,0:15:37.00,Default,,0,0,0,,这就很糟糕了\nDialogue: 0,0:15:38.00,0:15:40.62,Default,,0,0,0,,如何预防这样的灾难\nDialogue: 0,0:15:40.62,0:15:42.19,Default,,0,0,0,,这种生态灾难\nDialogue: 0,0:15:42.60,0:15:44.30,Default,,0,0,0,,在提问环节之后我们再继续讨论\nDialogue: 0,0:15:44.30,0:15:45.26,Default,,0,0,0,,有人要提问吗?\nDialogue: 0,0:15:51.50,0:15:51.69,Default,,0,0,0,,请讲\nDialogue: 0,0:15:52.03,0:15:54.67,Default,,0,0,0,,学生：在环境图表中\nDialogue: 0,0:15:54.67,0:15:58.25,Default,,0,0,0,,我们画了过程体\nDialogue: 0,0:15:58.25,0:16:00.67,Default,,0,0,0,,但是在过程应用结束后\nDialogue: 0,0:16:00.80,0:16:03.60,Default,,0,0,0,,这些环境中的东西就不再有用了\nDialogue: 0,0:16:03.60,0:16:04.16,Default,,0,0,0,,教授：说得很对\nDialogue: 0,0:16:04.93,0:16:06.67,Default,,0,0,0,,学生：它是如何表示的？\nDialogue: 0,0:16:06.76,0:16:08.75,Default,,0,0,0,,教授：这其实是两个问题\nDialogue: 0,0:16:09.18,0:16:10.25,Default,,0,0,0,,第一个问题是\nDialogue: 0,0:16:10.25,0:16:13.43,Default,,0,0,0,,材料没用了\nDialogue: 0,0:16:13.87,0:16:14.92,Default,,0,0,0,,我们稍后就会讲\nDialogue: 0,0:16:14.92,0:16:17.00,Default,,0,0,0,,如何预防生态灾难\nDialogue: 0,0:16:17.63,0:16:19.20,Default,,0,0,0,,如果我制造了一堆垃圾\nDialogue: 0,0:16:19.20,0:16:21.39,Default,,0,0,0,,我需要自己清理掉\nDialogue: 0,0:16:21.82,0:16:22.97,Default,,0,0,0,,我们一会儿就要讲\nDialogue: 0,0:16:23.43,0:16:24.57,Default,,0,0,0,,第二个问题\nDialogue: 0,0:16:24.57,0:16:27.21,Default,,0,0,0,,你问的是如何表示环境\nDialogue: 0,0:16:27.28,0:16:27.60,Default,,0,0,0,,学生：对\nDialogue: 0,0:16:27.60,0:16:28.19,Default,,0,0,0,,教授：好\nDialogue: 0,0:16:28.19,0:16:30.62,Default,,0,0,0,,环境结构能够以任意的方式表示\nDialogue: 0,0:16:30.92,0:16:31.78,Default,,0,0,0,,有很多种表示方式\nDialogue: 0,0:16:31.78,0:16:33.34,Default,,0,0,0,,这里 我只讲了基于表结构的内存\nDialogue: 0,0:16:33.63,0:16:34.92,Default,,0,0,0,,当然 每个真实的系统\nDialogue: 0,0:16:34.92,0:16:36.72,Default,,0,0,0,,都有任意长度的向量\nDialogue: 0,0:16:36.72,0:16:39.15,Default,,0,0,0,,也有固定长度的向量\nDialogue: 0,0:16:39.31,0:16:40.51,Default,,0,0,0,,它们都可以作为内存的表示方法\nDialogue: 0,0:16:41.08,0:16:44.90,Default,,0,0,0,,在一个专业的Lisp系统中\nDialogue: 0,0:16:44.90,0:16:46.99,Default,,0,0,0,,环境结构是用\nDialogue: 0,0:16:47.30,0:16:49.69,Default,,0,0,0,,向量表示的\nDialogue: 0,0:16:49.69,0:16:51.92,Default,,0,0,0,,它所包含的元素的数量\nDialogue: 0,0:16:51.92,0:16:54.60,Default,,0,0,0,,比参数的个数稍微多一点\nDialogue: 0,0:16:55.35,0:16:56.86,Default,,0,0,0,,因为你需要某种“粘合剂”\nDialogue: 0,0:16:57.40,0:17:00.74,Default,,0,0,0,,记住环境是在框架里的\nDialogue: 0,0:17:00.74,0:17:03.98,Default,,0,0,0,,框架是应用过程时被构建出来的\nDialogue: 0,0:17:03.98,0:17:04.78,Default,,0,0,0,,这种情况下\nDialogue: 0,0:17:04.80,0:17:07.60,Default,,0,0,0,,所分配的空间大小为\nDialogue: 0,0:17:07.64,0:17:11.27,Default,,0,0,0,,实际参数加上“粘合剂”占用的空间\nDialogue: 0,0:17:11.27,0:17:12.71,Default,,0,0,0,,然后将它连接到某条链上\nDialogue: 0,0:17:13.32,0:17:15.66,Default,,0,0,0,,在这个层次上 和ALGOL差不多\nDialogue: 0,0:17:19.81,0:17:20.72,Default,,0,0,0,,还有其它问题吗?\nDialogue: 0,0:17:23.70,0:17:23.92,Default,,0,0,0,,好\nDialogue: 0,0:17:23.92,0:17:25.55,Default,,0,0,0,,谢谢 我们休息一下\nDialogue: 0,0:17:26.35,0:17:45.48,Default,,0,0,0,,[音乐]\nDialogue: 0,0:17:45.53,0:17:50.01,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:17:55.74,0:17:59.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:17:59.13,0:18:04.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:18:04.32,0:18:09.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}存储分配与垃圾收集\nDialogue: 0,0:18:12.27,0:18:14.24,Default,,0,0,0,,教授：如同我刚才说过的那样\nDialogue: 0,0:18:14.55,0:18:15.50,Default,,0,0,0,,半导体厂商\nDialogue: 0,0:18:15.82,0:18:17.96,Default,,0,0,0,,所生产的计算机内存\nDialogue: 0,0:18:18.16,0:18:19.00,Default,,0,0,0,,容量是有限的\nDialogue: 0,0:18:19.42,0:18:20.40,Default,,0,0,0,,这的确很可惜\nDialogue: 0,0:18:21.62,0:18:23.35,Default,,0,0,0,,但它也可能不总是这样\nDialogue: 0,0:18:24.03,0:18:25.40,Default,,0,0,0,,简单算一下\nDialogue: 0,0:18:25.44,0:18:28.86,Default,,0,0,0,,你可以看到 如果内存的价格\nDialogue: 0,0:18:28.86,0:18:30.80,Default,,0,0,0,,继续保持当前的趋势的话\nDialogue: 0,0:18:31.22,0:18:33.68,Default,,0,0,0,,如果你执行CONS的时候也只需要1微秒\nDialogue: 0,0:18:34.42,0:18:35.90,Default,,0,0,0,,那么 首先大家知道\nDialogue: 0,0:18:35.90,0:18:37.07,Default,,0,0,0,,一年大约有\nDialogue: 0,0:18:37.10,0:18:38.86,Default,,0,0,0,,PI*10^7秒\nDialogue: 0,0:18:39.45,0:18:41.12,Default,,0,0,0,,那么就有\nDialogue: 0,0:18:41.50,0:18:42.73,Default,,0,0,0,,10^6乘以10^7\nDialogue: 0,0:18:42.73,0:18:43.94,Default,,0,0,0,,也就是10^13\nDialogue: 0,0:18:43.94,0:18:45.50,Default,,0,0,0,,那么在机器的一生中\nDialogue: 0,0:18:45.50,0:18:46.80,Default,,0,0,0,,就能有10^14个CONS\nDialogue: 0,0:18:47.52,0:18:49.40,Default,,0,0,0,,如果你的机器上\nDialogue: 0,0:18:49.68,0:18:50.57,Default,,0,0,0,,有10^14个字的内存\nDialogue: 0,0:18:51.20,0:18:52.16,Default,,0,0,0,,你就永远不会用完\nDialogue: 0,0:18:53.04,0:18:53.85,Default,,0,0,0,,这样就会……\nDialogue: 0,0:18:53.95,0:18:55.76,Default,,0,0,0,,这并不是完全没有道理\nDialogue: 0,0:18:56.31,0:18:58.46,Default,,0,0,0,,10^14次方不是个非常大的数字\nDialogue: 0,0:19:01.45,0:19:04.70,Default,,0,0,0,,我不觉得它是个很大的数字\nDialogue: 0,0:19:05.18,0:19:07.39,Default,,0,0,0,,但我喜欢在天文学领域进行比较\nDialogue: 0,0:19:07.93,0:19:11.04,Default,,0,0,0,,距离我们最近的星星\nDialogue: 0,0:19:11.10,0:19:12.45,Default,,0,0,0,,至少有10^18次方厘米远\nDialogue: 0,0:19:12.93,0:19:18.85,Default,,0,0,0,,我担心的是\nDialogue: 0,0:19:19.15,0:19:21.27,Default,,0,0,0,,至少以现在的经济状况\nDialogue: 0,0:19:21.27,0:19:23.57,Default,,0,0,0,,10^14大小的内存很贵\nDialogue: 0,0:19:24.20,0:19:26.62,Default,,0,0,0,,因此我认为我们需要\nDialogue: 0,0:19:26.81,0:19:28.51,Default,,0,0,0,,适应更小的内存\nDialogue: 0,0:19:30.02,0:19:30.59,Default,,0,0,0,,现在\nDialogue: 0,0:19:32.84,0:19:35.07,Default,,0,0,0,,广义地说 我们营造一种无限内存的假象\nDialogue: 0,0:19:35.80,0:19:37.22,Default,,0,0,0,,我们需要整理它\nDialogue: 0,0:19:37.82,0:19:39.68,Default,,0,0,0,,以便在我们需要内存的时候就能获得它\nDialogue: 0,0:19:41.92,0:19:45.55,Default,,0,0,0,,这个想法非常重要\nDialogue: 0,0:19:49.54,0:19:51.97,Default,,0,0,0,,人或者计算机只能存在有限的时间\nDialogue: 0,0:19:52.32,0:19:54.59,Default,,0,0,0,,只能看有限的东西\nDialogue: 0,0:19:55.28,0:19:57.37,Default,,0,0,0,,因此你只需要有限的东西\nDialogue: 0,0:19:58.19,0:19:59.00,Default,,0,0,0,,只要你合理地安排它们\nDialogue: 0,0:19:59.00,0:20:00.38,Default,,0,0,0,,使得不管实际有多少内存\nDialogue: 0,0:20:00.77,0:20:03.46,Default,,0,0,0,,你要求这里有多少\nDialogue: 0,0:20:03.46,0:20:04.74,Default,,0,0,0,,当你去看的时候\nDialogue: 0,0:20:04.74,0:20:06.90,Default,,0,0,0,,总有足够的东西\nDialogue: 0,0:20:06.90,0:20:08.15,Default,,0,0,0,,因此你只需要有限的数量\nDialogue: 0,0:20:08.75,0:20:09.94,Default,,0,0,0,,我们来看看\nDialogue: 0,0:20:11.63,0:20:13.32,Default,,0,0,0,,我们之前提过一个问题\nDialogue: 0,0:20:13.92,0:20:15.45,Default,,0,0,0,,在很多情况下\nDialogue: 0,0:20:15.72,0:20:17.84,Default,,0,0,0,,我们制造了大量\nDialogue: 0,0:20:17.88,0:20:19.16,Default,,0,0,0,,不需要的东西\nDialogue: 0,0:20:19.41,0:20:21.81,Default,,0,0,0,,我们可以进行回收再利用\nDialogue: 0,0:20:22.62,0:20:23.53,Default,,0,0,0,,举个例子\nDialogue: 0,0:20:24.15,0:20:25.79,Default,,0,0,0,,事实上\nDialogue: 0,0:20:25.79,0:20:28.40,Default,,0,0,0,,当我们调用一个过程的时候\nDialogue: 0,0:20:28.40,0:20:30.47,Default,,0,0,0,,都会构建环境结构\nDialogue: 0,0:20:30.47,0:20:32.56,Default,,0,0,0,,我们把它构建在一个环境框架中\nDialogue: 0,0:20:33.14,0:20:34.03,Default,,0,0,0,,这个环境框架\nDialogue: 0,0:20:34.22,0:20:36.07,Default,,0,0,0,,不用存在很长时间\nDialogue: 0,0:20:36.73,0:20:38.69,Default,,0,0,0,,只有在进行过程调用的时候\nDialogue: 0,0:20:39.42,0:20:42.60,Default,,0,0,0,,它的存在才是有用的\nDialogue: 0,0:20:42.85,0:20:45.27,Default,,0,0,0,,如果过程把另一个过程\nDialogue: 0,0:20:45.27,0:20:46.67,Default,,0,0,0,,作为返回值返回\nDialogue: 0,0:20:46.87,0:20:48.52,Default,,0,0,0,,并且这个过程是在它的内部定义的\nDialogue: 0,0:20:48.52,0:20:50.80,Default,,0,0,0,,那么外层过程的\nDialogue: 0,0:20:51.07,0:20:53.39,Default,,0,0,0,,存活时间仍然是\nDialogue: 0,0:20:53.50,0:20:56.12,Default,,0,0,0,,被返回的过程的\nDialogue: 0,0:20:57.02,0:20:57.90,Default,,0,0,0,,存活时间\nDialogue: 0,0:20:58.53,0:20:59.57,Default,,0,0,0,,最终\nDialogue: 0,0:20:59.57,0:21:00.97,Default,,0,0,0,,就会制造很多垃圾\nDialogue: 0,0:21:01.96,0:21:04.10,Default,,0,0,0,,还有其它的途径可以制造垃圾\nDialogue: 0,0:21:05.37,0:21:06.67,Default,,0,0,0,,用户也会制造垃圾\nDialogue: 0,0:21:07.24,0:21:08.07,Default,,0,0,0,,举例来说\nDialogue: 0,0:21:08.07,0:21:10.22,Default,,0,0,0,,用户制造的垃圾像是这样\nDialogue: 0,0:21:10.93,0:21:14.00,Default,,0,0,0,,如果我们写个程序\nDialogue: 0,0:21:14.00,0:21:15.80,Default,,0,0,0,,把两个表连接到一起\nDialogue: 0,0:21:16.05,0:21:18.14,Default,,0,0,0,,唯一的办法是\nDialogue: 0,0:21:18.32,0:21:21.37,Default,,0,0,0,,把第一个表逆序塞到空表中\nDialogue: 0,0:21:21.37,0:21:23.72,Default,,0,0,0,,再把新表逆序塞到第二个表中\nDialogue: 0,0:21:24.70,0:21:26.92,Default,,0,0,0,,这种解法并不是很糟糕\nDialogue: 0,0:21:28.16,0:21:28.85,Default,,0,0,0,,然而\nDialogue: 0,0:21:28.85,0:21:30.09,Default,,0,0,0,,程序所生成的\nDialogue: 0,0:21:30.11,0:21:32.02,Default,,0,0,0,,中间结果\nDialogue: 0,0:21:33.87,0:21:35.57,Default,,0,0,0,,即第一个表的逆序表\nDialogue: 0,0:21:36.70,0:21:38.52,Default,,0,0,0,,在它被复制到第二个表之后\nDialogue: 0,0:21:38.52,0:21:40.56,Default,,0,0,0,,就再也不会被用到了\nDialogue: 0,0:21:41.01,0:21:42.23,Default,,0,0,0,,它是个中间结果\nDialogue: 0,0:21:43.58,0:21:45.43,Default,,0,0,0,,它很难被找到\nDialogue: 0,0:21:46.07,0:21:48.05,Default,,0,0,0,,没有人能访问到它\nDialogue: 0,0:21:48.60,0:21:49.84,Default,,0,0,0,,事实上 它会消失掉\nDialogue: 0,0:21:51.05,0:21:52.90,Default,,0,0,0,,如果我们像这样制造了大量的垃圾\nDialogue: 0,0:21:52.90,0:21:54.20,Default,,0,0,0,,系统也应该允许我们这么干\nDialogue: 0,0:21:54.80,0:21:57.29,Default,,0,0,0,,但应该有某些方法去回收这些垃圾\nDialogue: 0,0:21:58.80,0:22:00.90,Default,,0,0,0,,现在 我要告诉你\nDialogue: 0,0:22:01.70,0:22:03.77,Default,,0,0,0,,一个非常聪明的技巧\nDialogue: 0,0:22:04.32,0:22:07.58,Default,,0,0,0,,一个Lisp系统\nDialogue: 0,0:22:07.95,0:22:11.21,Default,,0,0,0,,通常可以证明一条小定理\nDialogue: 0,0:22:11.29,0:22:13.50,Default,,0,0,0,,也就是 某段内存中的值\nDialogue: 0,0:22:14.72,0:22:16.09,Default,,0,0,0,,之后不再会被用到\nDialogue: 0,0:22:17.41,0:22:19.80,Default,,0,0,0,,它对以后的计算没有任何影响\nDialogue: 0,0:22:21.40,0:22:23.61,Default,,0,0,0,,事实上 这基于一个很简单的想法\nDialogue: 0,0:22:24.72,0:22:28.06,Default,,0,0,0,,我们已经把计算机设计成这个样子\nDialogue: 0,0:22:28.95,0:22:30.67,Default,,0,0,0,,有一些数据通路\nDialogue: 0,0:22:31.87,0:22:33.40,Default,,0,0,0,,其中有寄存器\nDialogue: 0,0:22:34.92,0:22:38.04,Default,,0,0,0,,有EXP、ENV\nDialogue: 0,0:22:39.04,0:22:42.19,Default,,0,0,0,,和VAL之类的寄存器\nDialogue: 0,0:22:42.61,0:22:44.02,Default,,0,0,0,,这里有个叫STACK的东西\nDialogue: 0,0:22:46.02,0:22:49.45,Default,,0,0,0,,某种指向一个结构的东西\nDialogue: 0,0:22:49.50,0:22:50.22,Default,,0,0,0,,它是个栈\nDialogue: 0,0:22:50.24,0:22:51.48,Default,,0,0,0,,我们过一会再研究它\nDialogue: 0,0:22:51.64,0:22:53.62,Default,,0,0,0,,这里有一些\nDialogue: 0,0:22:54.38,0:22:56.57,Default,,0,0,0,,有穷状态控制器\nDialogue: 0,0:22:56.73,0:22:59.51,Default,,0,0,0,,控制信号在这之间流通\nDialogue: 0,0:22:59.80,0:23:01.44,Default,,0,0,0,,比如谓词的返回结果\nDialogue: 0,0:23:01.87,0:23:03.13,Default,,0,0,0,,这部分并不太有趣\nDialogue: 0,0:23:03.35,0:23:06.51,Default,,0,0,0,,这里有某种结构化的内存\nDialogue: 0,0:23:06.80,0:23:08.27,Default,,0,0,0,,我刚才给你讲过如何构建它\nDialogue: 0,0:23:08.27,0:23:10.17,Default,,0,0,0,,它可能包括一个栈\nDialogue: 0,0:23:10.46,0:23:11.48,Default,,0,0,0,,我没有告诉你如何把东西\nDialogue: 0,0:23:11.48,0:23:12.43,Default,,0,0,0,,构建成任意形状\nDialogue: 0,0:23:12.56,0:23:13.39,Default,,0,0,0,,只有序对\nDialogue: 0,0:23:13.60,0:23:14.20,Default,,0,0,0,,但事实上\nDialogue: 0,0:23:14.35,0:23:15.44,Default,,0,0,0,,我告诉过你\nDialogue: 0,0:23:15.47,0:23:16.96,Default,,0,0,0,,可以用一张大表来模拟栈\nDialogue: 0,0:23:17.77,0:23:18.85,Default,,0,0,0,,我没准备干这个\nDialogue: 0,0:23:18.85,0:23:20.01,Default,,0,0,0,,这不是个好办法\nDialogue: 0,0:23:20.36,0:23:22.60,Default,,0,0,0,,但是我们可以有这样一个东西\nDialogue: 0,0:23:22.99,0:23:25.28,Default,,0,0,0,,这里有各种数据结构\nDialogue: 0,0:23:25.64,0:23:27.75,Default,,0,0,0,,它们通过有趣的方式互相连接\nDialogue: 0,0:23:30.11,0:23:32.02,Default,,0,0,0,,它们和其它东西连接到一起\nDialogue: 0,0:23:32.56,0:23:33.25,Default,,0,0,0,,以此类推\nDialogue: 0,0:23:33.25,0:23:34.22,Default,,0,0,0,,归根结底\nDialogue: 0,0:23:34.45,0:23:37.19,Default,,0,0,0,,这里的东西是指向这里的指针\nDialogue: 0,0:23:37.19,0:23:38.87,Default,,0,0,0,,寄存器里的指针\nDialogue: 0,0:23:39.40,0:23:41.40,Default,,0,0,0,,指向的是表结构内存中\nDialogue: 0,0:23:41.44,0:23:43.08,Default,,0,0,0,,数据结构\nDialogue: 0,0:23:44.91,0:23:49.80,Default,,0,0,0,,现在 我们的问题是\nDialogue: 0,0:23:51.05,0:23:52.56,Default,,0,0,0,,机器的整个意识\nDialogue: 0,0:23:52.57,0:23:53.92,Default,,0,0,0,,是在寄存器里的\nDialogue: 0,0:23:55.76,0:23:58.51,Default,,0,0,0,,如果这个机器\nDialogue: 0,0:23:58.75,0:24:01.07,Default,,0,0,0,,构建得正确的话\nDialogue: 0,0:24:01.37,0:24:03.41,Default,,0,0,0,,它无法访问表结构内存中任何的东西\nDialogue: 0,0:24:04.57,0:24:07.05,Default,,0,0,0,,除非这个表结构内存中的数据\nDialogue: 0,0:24:08.09,0:24:10.88,Default,,0,0,0,,通过一系列的数据结构\nDialogue: 0,0:24:11.64,0:24:13.06,Default,,0,0,0,,与寄存器相连接\nDialogue: 0,0:24:15.07,0:24:15.98,Default,,0,0,0,,如果它能够\nDialogue: 0,0:24:16.22,0:24:18.31,Default,,0,0,0,,被合法的数据结构选择函数访问到\nDialogue: 0,0:24:19.08,0:24:21.12,Default,,0,0,0,,通过寄存器里保存的指针能够访问它\nDialogue: 0,0:24:22.28,0:24:24.46,Default,,0,0,0,,比如说 数组引用\nDialogue: 0,0:24:24.94,0:24:27.92,Default,,0,0,0,,或者针对序对的引用--CAR或者CDR\nDialogue: 0,0:24:29.08,0:24:30.95,Default,,0,0,0,,但我不能随意访问内存中的位置\nDialogue: 0,0:24:30.95,0:24:31.95,Default,,0,0,0,,因为我找不到它\nDialogue: 0,0:24:32.74,0:24:34.90,Default,,0,0,0,,至少在我求值某条表达式的时候\nDialogue: 0,0:24:37.00,0:24:39.16,Default,,0,0,0,,我是不允许去访问那个任意名字的\nDialogue: 0,0:24:41.62,0:24:42.57,Default,,0,0,0,,如果是这样的话\nDialogue: 0,0:24:43.27,0:24:45.07,Default,,0,0,0,,就可以证明一个简单的理论\nDialogue: 0,0:24:47.16,0:24:47.69,Default,,0,0,0,,就是说\nDialogue: 0,0:24:47.90,0:24:50.52,Default,,0,0,0,,如果我从这些寄存器指向的地方开始\nDialogue: 0,0:24:51.16,0:24:52.55,Default,,0,0,0,,递归地遍历\nDialogue: 0,0:24:52.82,0:24:56.15,Default,,0,0,0,,标记选择函数所有能访问到内存\nDialogue: 0,0:24:56.90,0:24:59.40,Default,,0,0,0,,最终就能标记所有能访问的东西\nDialogue: 0,0:25:00.65,0:25:02.69,Default,,0,0,0,,任何未标记的都是垃圾\nDialogue: 0,0:25:02.69,0:25:03.75,Default,,0,0,0,,它们可以被回收\nDialogue: 0,0:25:05.56,0:25:06.20,Default,,0,0,0,,非常简单\nDialogue: 0,0:25:07.20,0:25:09.10,Default,,0,0,0,,不会影响之后的计算\nDialogue: 0,0:25:11.18,0:25:12.84,Default,,0,0,0,,我来举一个\nDialogue: 0,0:25:13.93,0:25:15.75,Default,,0,0,0,,具体的例子\nDialogue: 0,0:25:17.12,0:25:19.37,Default,,0,0,0,,在此之前 需要给我的表结构内存\nDialogue: 0,0:25:19.69,0:25:22.08,Default,,0,0,0,,添加一个叫MARK的标志位\nDialogue: 0,0:25:23.64,0:25:24.89,Default,,0,0,0,,因此 在这里\nDialogue: 0,0:25:25.37,0:25:27.28,Default,,0,0,0,,就有一个表结构内存\nDialogue: 0,0:25:29.08,0:25:30.32,Default,,0,0,0,,这块表内存中\nDialogue: 0,0:25:30.33,0:25:31.33,Default,,0,0,0,,存放了一个表数据结构\nDialogue: 0,0:25:31.33,0:25:33.95,Default,,0,0,0,,我们把这个起始位置\nDialogue: 0,0:25:35.87,0:25:36.62,Default,,0,0,0,,称为“根”\nDialogue: 0,0:25:38.59,0:25:40.12,Default,,0,0,0,,不一定只有一个根\nDialogue: 0,0:25:40.12,0:25:41.95,Default,,0,0,0,,与寄存器类似 可以有很多这种东西\nDialogue: 0,0:25:42.67,0:25:43.98,Default,,0,0,0,,但我可以巧妙地安排它们\nDialogue: 0,0:25:44.13,0:25:46.30,Default,,0,0,0,,把所有在旧寄存器里的东西\nDialogue: 0,0:25:46.30,0:25:47.77,Default,,0,0,0,,在何时的时间点\nDialogue: 0,0:25:48.28,0:25:50.46,Default,,0,0,0,,放入到这个根结构中\nDialogue: 0,0:25:50.46,0:25:51.85,Default,,0,0,0,,然后用一个指针指向它\nDialogue: 0,0:25:51.85,0:25:52.67,Default,,0,0,0,,这不是重点\nDialogue: 0,0:25:54.57,0:25:55.63,Default,,0,0,0,,思路就是\nDialogue: 0,0:25:55.64,0:25:56.65,Default,,0,0,0,,我们要不断地进行CONS\nDialogue: 0,0:25:56.67,0:25:58.01,Default,,0,0,0,,直到空闲表为空\nDialogue: 0,0:25:58.72,0:25:59.67,Default,,0,0,0,,这样就用尽了所有空间\nDialogue: 0,0:26:00.95,0:26:04.47,Default,,0,0,0,,现在我们要证明这个理论\nDialogue: 0,0:26:04.47,0:26:05.90,Default,,0,0,0,,也就是一部分的内存\nDialogue: 0,0:26:05.95,0:26:06.90,Default,,0,0,0,,已经没有用了\nDialogue: 0,0:26:07.85,0:26:09.15,Default,,0,0,0,,然后我们要回收它\nDialogue: 0,0:26:09.78,0:26:10.87,Default,,0,0,0,,构建一个新的树\nDialogue: 0,0:26:12.19,0:26:14.57,Default,,0,0,0,,这是这些垃圾的标准使用方式\nDialogue: 0,0:26:17.09,0:26:18.64,Default,,0,0,0,,那么我们要做什么呢?\nDialogue: 0,0:26:18.84,0:26:20.78,Default,,0,0,0,,从P5这个位置开始\nDialogue: 0,0:26:20.89,0:26:24.27,Default,,0,0,0,,存了一些数据结构\nDialogue: 0,0:26:25.15,0:26:26.75,Default,,0,0,0,,说错了--是从1开始\nDialogue: 0,0:26:27.27,0:26:28.51,Default,,0,0,0,,事实上\nDialogue: 0,0:26:28.89,0:26:32.20,Default,,0,0,0,,它的CAR部分存放在P5这个位置\nDialogue: 0,0:26:32.27,0:26:33.58,Default,,0,0,0,,而CDR部分存在在P2这个位置\nDialogue: 0,0:26:33.98,0:26:35.64,Default,,0,0,0,,最开始 所有的标记都是0\nDialogue: 0,0:26:36.70,0:26:39.00,Default,,0,0,0,,我们要开始标记了\nDialogue: 0,0:26:39.92,0:26:40.52,Default,,0,0,0,,好\nDialogue: 0,0:26:42.54,0:26:44.27,Default,,0,0,0,,例如\nDialogue: 0,0:26:44.47,0:26:46.95,Default,,0,0,0,,因为我可以从根访问到位置P1\nDialogue: 0,0:26:46.95,0:26:47.82,Default,,0,0,0,,我就标记一下\nDialogue: 0,0:26:48.39,0:26:49.17,Default,,0,0,0,,我来标一下\nDialogue: 0,0:26:50.96,0:26:51.45,Default,,0,0,0,,好了\nDialogue: 0,0:26:52.22,0:26:52.94,Default,,0,0,0,,这个被标记了\nDialogue: 0,0:26:54.41,0:26:57.51,Default,,0,0,0,,因为它指向位置P5\nDialogue: 0,0:26:57.64,0:26:58.64,Default,,0,0,0,,所以我来到了5号格子\nDialogue: 0,0:26:59.02,0:27:00.72,Default,,0,0,0,,然后 我要标记这个\nDialogue: 0,0:27:01.45,0:27:01.76,Default,,0,0,0,,标好了\nDialogue: 0,0:27:01.76,0:27:02.60,Default,,0,0,0,,这个笔真好用\nDialogue: 0,0:27:02.90,0:27:05.10,Default,,0,0,0,,但是5号位置的CAR部分是一个数字\nDialogue: 0,0:27:05.27,0:27:06.65,Default,,0,0,0,,我对标记数字不感兴趣\nDialogue: 0,0:27:06.91,0:27:08.17,Default,,0,0,0,,但它的CDR部分是P7\nDialogue: 0,0:27:08.70,0:27:09.75,Default,,0,0,0,,所以我可以标记它\nDialogue: 0,0:27:10.45,0:27:10.81,Default,,0,0,0,,又标好了\nDialogue: 0,0:27:11.80,0:27:13.40,Default,,0,0,0,,P7的CDR部分是空表\nDialogue: 0,0:27:13.67,0:27:15.10,Default,,0,0,0,,而它唯一所引用的元素则是\nDialogue: 0,0:27:15.59,0:27:17.12,Default,,0,0,0,,它的CAR部分是个数字\nDialogue: 0,0:27:17.12,0:27:17.85,Default,,0,0,0,,我对它不感兴趣\nDialogue: 0,0:27:19.49,0:27:20.50,Default,,0,0,0,,让我们回到这里\nDialogue: 0,0:27:20.50,0:27:21.65,Default,,0,0,0,,我忘记了一些事情\nDialogue: 0,0:27:21.65,0:27:22.17,Default,,0,0,0,,P2\nDialogue: 0,0:27:22.84,0:27:24.85,Default,,0,0,0,,换句话说 如果我看1号格子\nDialogue: 0,0:27:25.42,0:27:29.45,Default,,0,0,0,,1号格子的CDR部分指向P2\nDialogue: 0,0:27:30.37,0:27:31.30,Default,,0,0,0,,一个指向P2的引用\nDialogue: 0,0:27:32.01,0:27:34.97,Default,,0,0,0,,这意味着我应该标记P2\nDialogue: 0,0:27:35.70,0:27:36.27,Default,,0,0,0,,好了\nDialogue: 0,0:27:37.14,0:27:38.89,Default,,0,0,0,,P2包含了了一个到P4的引用\nDialogue: 0,0:27:39.13,0:27:40.27,Default,,0,0,0,,而P2的CAR部分是个数字\nDialogue: 0,0:27:40.27,0:27:41.20,Default,,0,0,0,,我对它不感兴趣\nDialogue: 0,0:27:41.47,0:27:42.60,Default,,0,0,0,,所以我要标记P4\nDialogue: 0,0:27:43.78,0:27:46.10,Default,,0,0,0,,P4的CAR部分引用了P7\nDialogue: 0,0:27:46.75,0:27:48.17,Default,,0,0,0,,它的CDR是空的\nDialogue: 0,0:27:48.47,0:27:49.57,Default,,0,0,0,,但由于我已经标记过P7了\nDialogue: 0,0:27:49.57,0:27:50.75,Default,,0,0,0,,就不再次标记它了\nDialogue: 0,0:27:51.40,0:27:53.05,Default,,0,0,0,,这就是这个地方\nDialogue: 0,0:27:53.07,0:27:53.87,Default,,0,0,0,,所能访问的所有单元\nDialogue: 0,0:27:55.00,0:27:56.57,Default,,0,0,0,,很简单的递归标记算法\nDialogue: 0,0:27:58.71,0:28:01.79,Default,,0,0,0,,这个算法有一些不足的地方\nDialogue: 0,0:28:01.90,0:28:04.02,Default,,0,0,0,,我们稍后会说\nDialogue: 0,0:28:04.92,0:28:06.16,Default,,0,0,0,,但基本上你能看到\nDialogue: 0,0:28:06.19,0:28:07.85,Default,,0,0,0,,所有没被标记的地方\nDialogue: 0,0:28:09.62,0:28:11.50,Default,,0,0,0,,都是无用的\nDialogue: 0,0:28:11.50,0:28:12.41,Default,,0,0,0,,可以回收\nDialogue: 0,0:28:14.25,0:28:15.75,Default,,0,0,0,,所以下一步就是\nDialogue: 0,0:28:15.75,0:28:17.05,Default,,0,0,0,,扫描整个内存\nDialogue: 0,0:28:17.94,0:28:20.35,Default,,0,0,0,,寻找未被标记的格子\nDialogue: 0,0:28:21.18,0:28:22.45,Default,,0,0,0,,每当遇到一个已标记的格子\nDialogue: 0,0:28:22.45,0:28:23.22,Default,,0,0,0,,就把标记去掉\nDialogue: 0,0:28:23.22,0:28:24.86,Default,,0,0,0,,每当遇到未标记的格子时\nDialogue: 0,0:28:25.07,0:28:27.82,Default,,0,0,0,,我就把它连接到我的空闲表中\nDialogue: 0,0:28:28.77,0:28:30.30,Default,,0,0,0,,传统而且非常简单的算法\nDialogue: 0,0:28:32.12,0:28:33.10,Default,,0,0,0,,我们来看看\nDialogue: 0,0:28:33.84,0:28:34.77,Default,,0,0,0,,它很简单吗?\nDialogue: 0,0:28:34.77,0:28:35.42,Default,,0,0,0,,是的\nDialogue: 0,0:28:35.57,0:28:37.79,Default,,0,0,0,,我不会深入代码细节\nDialogue: 0,0:28:38.00,0:28:39.65,Default,,0,0,0,,只是想给你看看它有多长\nDialogue: 0,0:28:40.09,0:28:41.10,Default,,0,0,0,,看这个标记阶段\nDialogue: 0,0:28:41.72,0:28:43.98,Default,,0,0,0,,这是标记阶段的第一部分\nDialogue: 0,0:28:45.06,0:28:46.00,Default,,0,0,0,,我们找到根\nDialogue: 0,0:28:46.32,0:28:47.52,Default,,0,0,0,,我们要\nDialogue: 0,0:28:47.67,0:28:51.05,Default,,0,0,0,,对它进行递归过程调用\nDialogue: 0,0:28:52.38,0:28:54.47,Default,,0,0,0,,当我们完成标记之后\nDialogue: 0,0:28:54.77,0:28:56.95,Default,,0,0,0,,就从这里开始清除\nDialogue: 0,0:28:57.38,0:28:59.79,Default,,0,0,0,,然后我们将执行一些指令\nDialogue: 0,0:28:59.80,0:29:01.36,Default,,0,0,0,,来检查这些标记\nDialogue: 0,0:29:01.39,0:29:03.07,Default,,0,0,0,,或者更改这些标记\nDialogue: 0,0:29:03.07,0:29:04.90,Default,,0,0,0,,按照我刚才讲的那个算法进行\nDialogue: 0,0:29:05.23,0:29:06.47,Default,,0,0,0,,代码在这里\nDialogue: 0,0:29:06.47,0:29:07.65,Default,,0,0,0,,你需要标记它们的CAR\nDialogue: 0,0:29:07.87,0:29:10.21,Default,,0,0,0,,也需要标记它们的CDR\nDialogue: 0,0:29:10.66,0:29:12.10,Default,,0,0,0,,这就是整个标记阶段\nDialogue: 0,0:29:14.37,0:29:16.16,Default,,0,0,0,,我给你讲个关于它的小故事\nDialogue: 0,0:29:16.59,0:29:19.37,Default,,0,0,0,,古董货DEC PDP-6计算机\nDialogue: 0,0:29:20.93,0:29:22.09,Default,,0,0,0,,它上面的\nDialogue: 0,0:29:22.35,0:29:24.85,Default,,0,0,0,,标记-清除垃圾回收系统就是这么写的\nDialogue: 0,0:29:26.91,0:29:28.40,Default,,0,0,0,,程序很短\nDialogue: 0,0:29:29.25,0:29:31.60,Default,,0,0,0,,以至于它需要的数据\nDialogue: 0,0:29:32.20,0:29:34.87,Default,,0,0,0,,以及用来操作内存的所需的寄存器\nDialogue: 0,0:29:36.16,0:29:38.14,Default,,0,0,0,,都能够放入到计算机的\nDialogue: 0,0:29:38.16,0:29:38.97,Default,,0,0,0,,16个快速寄存器中\nDialogue: 0,0:29:39.28,0:29:39.80,Default,,0,0,0,,整个程序\nDialogue: 0,0:29:40.01,0:29:42.01,Default,,0,0,0,,你可以在快速寄存器里执行指令\nDialogue: 0,0:29:43.17,0:29:44.83,Default,,0,0,0,,所以这是个非常小的程序\nDialogue: 0,0:29:45.85,0:29:46.88,Default,,0,0,0,,它跑得飞快\nDialogue: 0,0:29:48.87,0:29:51.30,Default,,0,0,0,,然而很不幸\nDialogue: 0,0:29:51.61,0:29:54.02,Default,,0,0,0,,因为这个程序是递归的\nDialogue: 0,0:29:54.80,0:29:57.55,Default,,0,0,0,,因为你需要先做某件事儿\nDialogue: 0,0:29:57.55,0:29:58.99,Default,,0,0,0,,然后再去做另外一件事儿\nDialogue: 0,0:29:59.21,0:30:00.88,Default,,0,0,0,,你得先处理CAR 再处理CDR\nDialogue: 0,0:30:01.15,0:30:02.75,Default,,0,0,0,,这就需要辅助内存\nDialogue: 0,0:30:03.41,0:30:05.23,Default,,0,0,0,,所以Lisp系统\nDialogue: 0,0:30:05.44,0:30:07.42,Default,,0,0,0,,需要一个栈来进行标记\nDialogue: 0,0:30:08.26,0:30:11.05,Default,,0,0,0,,Lisp系统通过这样的方式\nDialogue: 0,0:30:11.57,0:30:14.16,Default,,0,0,0,,限制了你在数据结构上\nDialogue: 0,0:30:14.42,0:30:17.37,Default,,0,0,0,,进行CAR或者CDR递归的深度\nDialogue: 0,0:30:17.81,0:30:19.35,Default,,0,0,0,,这并不太靠谱\nDialogue: 0,0:30:19.93,0:30:20.60,Default,,0,0,0,,另外一方面\nDialogue: 0,0:30:20.64,0:30:22.12,Default,,0,0,0,,当它足够大的时候你不会发现\nDialogue: 0,0:30:23.18,0:30:25.13,Default,,0,0,0,,例如 这样的情况\nDialogue: 0,0:30:25.55,0:30:28.17,Default,,0,0,0,,发生在大多数MacLisp系统上\nDialogue: 0,0:30:28.69,0:30:29.88,Default,,0,0,0,,在它上面运行的Macsyma\nDialogue: 0,0:30:29.96,0:30:31.10,Default,,0,0,0,,允许你处理\nDialogue: 0,0:30:31.10,0:30:32.72,Default,,0,0,0,,有成千上万个元素的表达式\nDialogue: 0,0:30:33.56,0:30:36.02,Default,,0,0,0,,有很多代数式有大量的项\nDialogue: 0,0:30:36.82,0:30:38.10,Default,,0,0,0,,这没什么问题\nDialogue: 0,0:30:39.49,0:30:40.82,Default,,0,0,0,,垃圾回收器能正常工作\nDialogue: 0,0:30:42.19,0:30:42.92,Default,,0,0,0,,另一方面\nDialogue: 0,0:30:42.92,0:30:45.37,Default,,0,0,0,,这个算法有个很精妙的修改版\nDialogue: 0,0:30:45.37,0:30:46.47,Default,,0,0,0,,但我不会去讲\nDialogue: 0,0:30:46.80,0:30:48.22,Default,,0,0,0,,它是由Peter Deutsch\nDialogue: 0,0:30:48.64,0:30:51.82,Default,,0,0,0,,来自IBM的Herb Schorr\nDialogue: 0,0:30:51.87,0:30:53.52,Default,,0,0,0,,和我不太认识的Waite所提出\nDialogue: 0,0:30:54.01,0:30:56.51,Default,,0,0,0,,这个算法\nDialogue: 0,0:30:56.67,0:30:57.79,Default,,0,0,0,,可以不使用\nDialogue: 0,0:30:57.84,0:30:59.55,Default,,0,0,0,,额外的辅助内存\nDialogue: 0,0:31:00.50,0:31:02.80,Default,,0,0,0,,只需要在遍历整个数据结构的时候\nDialogue: 0,0:31:02.97,0:31:05.52,Default,,0,0,0,,记住你是从哪里来的并反转指针\nDialogue: 0,0:31:05.52,0:31:07.52,Default,,0,0,0,,回溯的时候 再去反转这个指针\nDialogue: 0,0:31:07.79,0:31:08.99,Default,,0,0,0,,这是个很取巧的算法\nDialogue: 0,0:31:09.13,0:31:10.24,Default,,0,0,0,,你第一次写它的时候\nDialogue: 0,0:31:10.25,0:31:11.71,Default,,0,0,0,,事实上 你前三次写它的时候\nDialogue: 0,0:31:11.71,0:31:12.72,Default,,0,0,0,,都会遇到严重的BUG\nDialogue: 0,0:31:14.35,0:31:16.72,Default,,0,0,0,,也可能奇慢无比\nDialogue: 0,0:31:16.72,0:31:17.67,Default,,0,0,0,,因为这个算法太复杂了\nDialogue: 0,0:31:18.11,0:31:20.30,Default,,0,0,0,,它用了大概六倍的内存引用\nDialogue: 0,0:31:20.85,0:31:23.22,Default,,0,0,0,,来完成我们刚才讨论的任务\nDialogue: 0,0:31:24.58,0:31:27.07,Default,,0,0,0,,一旦我完成了标记阶段\nDialogue: 0,0:31:27.50,0:31:30.12,Default,,0,0,0,,我们就面临着这样的状况\nDialogue: 0,0:31:30.17,0:31:31.26,Default,,0,0,0,,请看\nDialogue: 0,0:31:31.51,0:31:34.03,Default,,0,0,0,,这里完成了标记工作\nDialogue: 0,0:31:34.08,0:31:35.00,Default,,0,0,0,,和我刚才描述的一样\nDialogue: 0,0:31:35.59,0:31:37.33,Default,,0,0,0,,现在我们要进行清除阶段\nDialogue: 0,0:31:37.60,0:31:39.32,Default,,0,0,0,,我刚才已经讲过如何清除了\nDialogue: 0,0:31:39.82,0:31:42.34,Default,,0,0,0,,我要从内存的一端开始\nDialogue: 0,0:31:42.34,0:31:43.34,Default,,0,0,0,,哪一端都可以\nDialogue: 0,0:31:43.62,0:31:46.17,Default,,0,0,0,,扫描内存中的每个格子\nDialogue: 0,0:31:47.17,0:31:48.67,Default,,0,0,0,,在扫描的同时\nDialogue: 0,0:31:49.20,0:31:50.97,Default,,0,0,0,,如果是空闲内存\nDialogue: 0,0:31:50.99,0:31:52.84,Default,,0,0,0,,就把它们连接到空闲表中\nDialogue: 0,0:31:53.15,0:31:54.05,Default,,0,0,0,,如果它们不是空闲内存\nDialogue: 0,0:31:54.05,0:31:56.07,Default,,0,0,0,,我就把它们的标记清除掉\nDialogue: 0,0:31:57.50,0:31:58.57,Default,,0,0,0,,事实上\nDialogue: 0,0:31:58.70,0:32:00.46,Default,,0,0,0,,最终的程序并不很复杂\nDialogue: 0,0:32:00.46,0:32:02.22,Default,,0,0,0,,它只是变长了一些\nDialogue: 0,0:32:02.78,0:32:04.17,Default,,0,0,0,,这是第一部分\nDialogue: 0,0:32:04.82,0:32:06.71,Default,,0,0,0,,它从内存的顶端向下遍历\nDialogue: 0,0:32:06.71,0:32:09.58,Default,,0,0,0,,我不期望你现在就搞懂它\nDialogue: 0,0:32:09.58,0:32:10.55,Default,,0,0,0,,它挺简单的\nDialogue: 0,0:32:11.03,0:32:12.52,Default,,0,0,0,,这是个非常简单的算法\nDialogue: 0,0:32:13.07,0:32:15.97,Default,,0,0,0,,其中的一段代码像是这样\nDialogue: 0,0:32:15.97,0:32:17.37,Default,,0,0,0,,非常显而易见\nDialogue: 0,0:32:18.60,0:32:20.08,Default,,0,0,0,,在清理结束后\nDialogue: 0,0:32:20.30,0:32:21.77,Default,,0,0,0,,我们就得到了像这样的结果\nDialogue: 0,0:32:25.33,0:32:26.54,Default,,0,0,0,,这种标记-清除算法\nDialogue: 0,0:32:26.56,0:32:28.20,Default,,0,0,0,,有一些缺点\nDialogue: 0,0:32:29.59,0:32:30.35,Default,,0,0,0,,最严重的一个是\nDialogue: 0,0:32:31.45,0:32:33.20,Default,,0,0,0,,最严重的缺点是\nDialogue: 0,0:32:33.20,0:32:34.97,Default,,0,0,0,,当你的内存越来越大\nDialogue: 0,0:32:36.82,0:32:38.87,Default,,0,0,0,,地址空间也就会越来越大\nDialogue: 0,0:32:38.87,0:32:40.80,Default,,0,0,0,,你想用它存更多东西\nDialogue: 0,0:32:41.37,0:32:44.52,Default,,0,0,0,,那么扫描整个内存就会非常耗时\nDialogue: 0,0:32:46.36,0:32:47.39,Default,,0,0,0,,你真正想做的是\nDialogue: 0,0:32:47.40,0:32:48.68,Default,,0,0,0,,只扫描有用的东西\nDialogue: 0,0:32:50.49,0:32:51.55,Default,,0,0,0,,这样就会好一点\nDialogue: 0,0:32:52.07,0:32:53.90,Default,,0,0,0,,如果你意识到\nDialogue: 0,0:32:54.48,0:32:57.72,Default,,0,0,0,,哪些东西已知是有用的\nDialogue: 0,0:32:58.28,0:33:00.37,Default,,0,0,0,,你就没必要去多次检查它\nDialogue: 0,0:33:00.37,0:33:01.20,Default,,0,0,0,,或者不用经常去检查它\nDialogue: 0,0:33:01.55,0:33:04.32,Default,,0,0,0,,对于那些你不太确定的\nDialogue: 0,0:33:05.00,0:33:06.22,Default,,0,0,0,,你可以在每次需要的时候\nDialogue: 0,0:33:07.10,0:33:08.75,Default,,0,0,0,,进行仔细检查\nDialogue: 0,0:33:09.93,0:33:10.85,Default,,0,0,0,,也就是垃圾收集的时候\nDialogue: 0,0:33:11.91,0:33:13.74,Default,,0,0,0,,这些算法\nDialogue: 0,0:33:13.76,0:33:15.10,Default,,0,0,0,,就是用了这样的方法\nDialogue: 0,0:33:15.66,0:33:18.16,Default,,0,0,0,,我要介绍一个著名的古老算法\nDialogue: 0,0:33:18.28,0:33:19.47,Default,,0,0,0,,这种算法允许你\nDialogue: 0,0:33:19.50,0:33:21.37,Default,,0,0,0,,只检查内存中已知是有用的部分\nDialogue: 0,0:33:23.12,0:33:23.85,Default,,0,0,0,,这让它成为了\nDialogue: 0,0:33:23.87,0:33:25.29,Default,,0,0,0,,目前已知最快的垃圾收集算法\nDialogue: 0,0:33:26.31,0:33:29.45,Default,,0,0,0,,它就是 Minsky-Fenichel-Yochelson 垃圾收集算法\nDialogue: 0,0:33:30.40,0:33:33.18,Default,,0,0,0,,它是由Minsky\nDialogue: 0,0:33:33.20,0:33:36.06,Default,,0,0,0,,在1960、61年左右发明的\nDialogue: 0,0:33:36.52,0:33:40.48,Default,,0,0,0,,当时是给RLE PDP-1 Lisp用的\nDialogue: 0,0:33:40.51,0:33:43.44,Default,,0,0,0,,这个机器只有4096个字的线性内存\nDialogue: 0,0:33:45.79,0:33:46.76,Default,,0,0,0,,还有个磁鼓\nDialogue: 0,0:33:48.48,0:33:49.39,Default,,0,0,0,,为了能够\nDialogue: 0,0:33:50.03,0:33:51.87,Default,,0,0,0,,在这种恶劣的条件下进行垃圾收集\nDialogue: 0,0:33:53.05,0:33:54.35,Default,,0,0,0,,Minsky意识到\nDialogue: 0,0:33:54.38,0:33:55.62,Default,,0,0,0,,达成目的最容易的方法是\nDialogue: 0,0:33:56.20,0:33:58.47,Default,,0,0,0,,在扫描内存的同时\nDialogue: 0,0:33:58.47,0:34:00.60,Default,,0,0,0,,遍历那些好的数据结构\nDialogue: 0,0:34:01.57,0:34:03.52,Default,,0,0,0,,把它复制到磁鼓中\nDialogue: 0,0:34:04.70,0:34:05.47,Default,,0,0,0,,压缩一下\nDialogue: 0,0:34:06.35,0:34:08.86,Default,,0,0,0,,之后把它们复制出来\nDialogue: 0,0:34:09.12,0:34:10.90,Default,,0,0,0,,并把它们交换回内存里\nDialogue: 0,0:34:12.30,0:34:13.68,Default,,0,0,0,,不管是使用的是磁鼓\nDialogue: 0,0:34:13.72,0:34:14.71,Default,,0,0,0,,或者其它的内存\nDialogue: 0,0:34:14.71,0:34:16.42,Default,,0,0,0,,这都不重要\nDialogue: 0,0:34:17.03,0:34:17.42,Default,,0,0,0,,事实上\nDialogue: 0,0:34:17.44,0:34:19.60,Default,,0,0,0,,我觉得现在应该没人用磁鼓了吧\nDialogue: 0,0:34:20.35,0:34:23.77,Default,,0,0,0,,但这个算法基本上\nDialogue: 0,0:34:24.03,0:34:25.42,Default,,0,0,0,,要依赖于\nDialogue: 0,0:34:25.42,0:34:27.42,Default,,0,0,0,,大约两倍于\nDialogue: 0,0:34:27.48,0:34:28.57,Default,,0,0,0,,你实际使用的内存\nDialogue: 0,0:34:30.27,0:34:32.96,Default,,0,0,0,,最开始的情况是\nDialogue: 0,0:34:33.12,0:34:36.60,Default,,0,0,0,,有用的数据和垃圾混在了一起\nDialogue: 0,0:34:37.11,0:34:38.97,Default,,0,0,0,,它被称为FROMSPACE\nDialogue: 0,0:34:45.17,0:34:47.05,Default,,0,0,0,,这是CRUD的混合\nDialogue: 0,0:34:47.87,0:34:49.79,Default,,0,0,0,,有些是有用的 有些没有用\nDialogue: 0,0:34:52.00,0:34:53.85,Default,,0,0,0,,现在还有另外一块空间\nDialogue: 0,0:34:54.17,0:34:55.61,Default,,0,0,0,,它需要足够大\nDialogue: 0,0:34:55.77,0:34:57.00,Default,,0,0,0,,这个地方叫TOSPACE\nDialogue: 0,0:34:57.12,0:34:58.24,Default,,0,0,0,,要把东西复制进去\nDialogue: 0,0:35:01.59,0:35:02.60,Default,,0,0,0,,接下来会发生的是\nDialogue: 0,0:35:02.60,0:35:04.06,Default,,0,0,0,,我不会深入细节\nDialogue: 0,0:35:04.16,0:35:07.07,Default,,0,0,0,,书上写得很清楚了\nDialogue: 0,0:35:07.59,0:35:10.40,Default,,0,0,0,,这里有一个根节点\nDialogue: 0,0:35:11.03,0:35:14.30,Default,,0,0,0,,你从根节点开始\nDialogue: 0,0:35:14.60,0:35:16.42,Default,,0,0,0,,复制你看到的第一个东西\nDialogue: 0,0:35:17.83,0:35:19.37,Default,,0,0,0,,根指针指向的第一个东西\nDialogue: 0,0:35:19.75,0:35:21.31,Default,,0,0,0,,复制到TOSPACE的头部\nDialogue: 0,0:35:22.81,0:35:24.12,Default,,0,0,0,,这些东西一般是一个序对\nDialogue: 0,0:35:24.16,0:35:25.60,Default,,0,0,0,,或者是类似的数据结构\nDialogue: 0,0:35:27.56,0:35:30.19,Default,,0,0,0,,然后在那里留下\nDialogue: 0,0:35:30.38,0:35:31.56,Default,,0,0,0,,一颗“破碎的心”\nDialogue: 0,0:35:31.77,0:35:35.74,Default,,0,0,0,,表示我把东西从这里移动到了这里\nDialogue: 0,0:35:35.74,0:35:37.05,Default,,0,0,0,,指示了移动的目的地\nDialogue: 0,0:35:37.80,0:35:39.65,Default,,0,0,0,,叫作破碎的心是因为\nDialogue: 0,0:35:39.65,0:35:40.78,Default,,0,0,0,,我的一个朋友\nDialogue: 0,0:35:40.78,0:35:43.39,Default,,0,0,0,,在1966年实现了这个算法\nDialogue: 0,0:35:43.82,0:35:45.26,Default,,0,0,0,,而他是个文艺青年\nDialogue: 0,0:35:45.26,0:35:46.76,Default,,0,0,0,,就取名叫“破碎的心”\nDialogue: 0,0:35:49.58,0:35:50.54,Default,,0,0,0,,不论如何\nDialogue: 0,0:35:51.15,0:35:52.72,Default,,0,0,0,,接下来要做的是\nDialogue: 0,0:35:52.94,0:35:55.00,Default,,0,0,0,,FREE指针现在指向这里\nDialogue: 0,0:35:55.17,0:35:56.38,Default,,0,0,0,,然后开始扫描\nDialogue: 0,0:35:56.88,0:35:59.68,Default,,0,0,0,,扫描这个刚复制过来的数据结构\nDialogue: 0,0:36:00.55,0:36:02.19,Default,,0,0,0,,每当你遇到其中的指针\nDialogue: 0,0:36:02.19,0:36:03.92,Default,,0,0,0,,你把它当作是这里的根指针\nDialogue: 0,0:36:04.00,0:36:04.59,Default,,0,0,0,,哦 不好意思\nDialogue: 0,0:36:04.60,0:36:05.69,Default,,0,0,0,,我们还需要做的是\nDialogue: 0,0:36:05.71,0:36:07.08,Default,,0,0,0,,你将根指针移动到这里\nDialogue: 0,0:36:09.22,0:36:10.17,Default,,0,0,0,,因此在扫描的过程中\nDialogue: 0,0:36:10.17,0:36:10.99,Default,,0,0,0,,把遇到的每个指针\nDialogue: 0,0:36:11.00,0:36:12.41,Default,,0,0,0,,都可以当作是ROOT指针\nDialogue: 0,0:36:14.11,0:36:15.45,Default,,0,0,0,,如果你遇到了某个指针\nDialogue: 0,0:36:15.45,0:36:17.40,Default,,0,0,0,,指向了这里的某个地方\nDialogue: 0,0:36:18.51,0:36:19.92,Default,,0,0,0,,它指向的东西\nDialogue: 0,0:36:19.93,0:36:20.99,Default,,0,0,0,,你复制过了吗？\nDialogue: 0,0:36:21.78,0:36:22.87,Default,,0,0,0,,这里是“破碎的心”吗\nDialogue: 0,0:36:23.88,0:36:24.84,Default,,0,0,0,,如果那里是破碎的心\nDialogue: 0,0:36:24.84,0:36:26.11,Default,,0,0,0,,就说明那里的东西复制过了\nDialogue: 0,0:36:26.20,0:36:27.34,Default,,0,0,0,,只需要用破碎的心所指向的地址\nDialogue: 0,0:36:27.36,0:36:28.75,Default,,0,0,0,,来替换它指针即可\nDialogue: 0,0:36:29.82,0:36:32.03,Default,,0,0,0,,如果它还没被复制\nDialogue: 0,0:36:32.12,0:36:34.08,Default,,0,0,0,,你把它复制到这里\nDialogue: 0,0:36:34.43,0:36:35.95,Default,,0,0,0,,把FREE指针移到这里\nDialogue: 0,0:36:37.05,0:36:40.60,Default,,0,0,0,,然后在那里放置一颗破碎的心\nDialogue: 0,0:36:41.05,0:36:41.80,Default,,0,0,0,,继续扫描\nDialogue: 0,0:36:43.67,0:36:46.40,Default,,0,0,0,,最终SCAN指针追上了FREE指针\nDialogue: 0,0:36:46.82,0:36:48.52,Default,,0,0,0,,内存里的所有东西都被复制了\nDialogue: 0,0:36:50.14,0:36:51.04,Default,,0,0,0,,这样这里就剩下了\nDialogue: 0,0:36:51.05,0:36:51.95,Default,,0,0,0,,大量的空闲空间\nDialogue: 0,0:36:51.96,0:36:53.28,Default,,0,0,0,,如果你需要的话\nDialogue: 0,0:36:53.31,0:36:54.47,Default,,0,0,0,,你可以把它组织为空闲表\nDialogue: 0,0:36:54.47,0:36:56.27,Default,,0,0,0,,但这种系统通常不这么来做\nDialogue: 0,0:36:56.27,0:36:59.15,Default,,0,0,0,,这类系统中 内存是顺序分配的\nDialogue: 0,0:37:00.91,0:37:02.48,Default,,0,0,0,,这是个非常 非常好的算法\nDialogue: 0,0:37:02.97,0:37:04.57,Default,,0,0,0,,你们现在使用的Scheme系统中\nDialogue: 0,0:37:04.67,0:37:05.97,Default,,0,0,0,,就使用了这种算法\nDialogue: 0,0:37:06.79,0:37:09.47,Default,,0,0,0,,它应该是--\nDialogue: 0,0:37:09.47,0:37:10.86,Default,,0,0,0,,我相信还没有人发现\nDialogue: 0,0:37:10.89,0:37:12.12,Default,,0,0,0,,比它跑得更快的算法\nDialogue: 0,0:37:12.40,0:37:14.85,Default,,0,0,0,,有一些对这个算法的简单修改\nDialogue: 0,0:37:14.85,0:37:16.77,Default,,0,0,0,,由Henry Baker发明\nDialogue: 0,0:37:17.17,0:37:20.31,Default,,0,0,0,,它让你能实时运行这个算法\nDialogue: 0,0:37:20.31,0:37:21.92,Default,,0,0,0,,也就是说进行回收时不需要暂停程序\nDialogue: 0,0:37:22.14,0:37:24.33,Default,,0,0,0,,你能够让机器运行时\nDialogue: 0,0:37:24.36,0:37:26.17,Default,,0,0,0,,进行的各种CONS操作\nDialogue: 0,0:37:26.32,0:37:28.40,Default,,0,0,0,,与垃圾回收过程交错进行\nDialogue: 0,0:37:28.85,0:37:31.20,Default,,0,0,0,,垃圾回收器是分散的\nDialogue: 0,0:37:31.20,0:37:32.19,Default,,0,0,0,,机器不需要停下来\nDialogue: 0,0:37:32.41,0:37:33.47,Default,,0,0,0,,再让垃圾回收开始运作\nDialogue: 0,0:37:34.64,0:37:37.87,Default,,0,0,0,,当然 在使用虚拟内存的机器中\nDialogue: 0,0:37:38.90,0:37:41.20,Default,,0,0,0,,有很多内存无法访问\nDialogue: 0,0:37:41.50,0:37:43.60,Default,,0,0,0,,这会让整个过程变得耗时\nDialogue: 0,0:37:44.28,0:37:46.43,Default,,0,0,0,,有很多人尝试\nDialogue: 0,0:37:47.16,0:37:48.65,Default,,0,0,0,,将它改进得更好\nDialogue: 0,0:37:49.19,0:37:51.15,Default,,0,0,0,,对于感兴趣的同学\nDialogue: 0,0:37:51.16,0:37:52.41,Default,,0,0,0,,这有一篇论文\nDialogue: 0,0:37:52.64,0:37:54.27,Default,,0,0,0,,作者是Moon等人\nDialogue: 0,0:37:54.65,0:37:56.89,Default,,0,0,0,,这篇论文描述了\nDialogue: 0,0:37:56.92,0:37:59.44,Default,,0,0,0,,增量式Minsky-Fenichel-Yochelson算法\nDialogue: 0,0:37:59.51,0:38:01.20,Default,,0,0,0,,和Baker算法的修改\nDialogue: 0,0:38:01.42,0:38:06.54,Default,,0,0,0,,让使用虚拟内存的系统更加高效\nDialogue: 0,0:38:08.27,0:38:12.32,Default,,0,0,0,,现在最后一个谜团也解开了\nDialogue: 0,0:38:12.84,0:38:14.09,Default,,0,0,0,,有什么疑惑吗？\nDialogue: 0,0:38:19.78,0:38:19.95,Default,,0,0,0,,请讲\nDialogue: 0,0:38:20.60,0:38:23.58,Default,,0,0,0,,学生：我在楼上的系统上\nDialogue: 0,0:38:23.64,0:38:25.05,Default,,0,0,0,,你们运行垃圾收集器的时候\nDialogue: 0,0:38:25.93,0:38:27.88,Default,,0,0,0,,它看起来跑得飞快\nDialogue: 0,0:38:27.96,0:38:28.40,Default,,0,0,0,,教授：是的\nDialogue: 0,0:38:28.49,0:38:29.52,Default,,0,0,0,,学生：整个过程花费了--\nDialogue: 0,0:38:30.11,0:38:31.88,Default,,0,0,0,,它真的扫描了整个内存吗？\nDialogue: 0,0:38:31.88,0:38:32.22,Default,,0,0,0,,教授：没有\nDialogue: 0,0:38:32.25,0:38:34.11,Default,,0,0,0,,它只扫描了那些需要的\nDialogue: 0,0:38:34.33,0:38:35.63,Default,,0,0,0,,去复制那些有用的数据结构\nDialogue: 0,0:38:37.32,0:38:38.36,Default,,0,0,0,,它是个复制收集器\nDialogue: 0,0:38:38.44,0:38:38.91,Default,,0,0,0,,学生：好吧\nDialogue: 0,0:38:39.30,0:38:40.88,Default,,0,0,0,,教授：但它确实很快\nDialogue: 0,0:38:41.85,0:38:45.88,Default,,0,0,0,,整体来说 我想如果要复制\nDialogue: 0,0:38:47.12,0:38:51.56,Default,,0,0,0,,一个大约3MB的东西\nDialogue: 0,0:38:52.43,0:38:53.24,Default,,0,0,0,,将在一秒内完成\nDialogue: 0,0:38:55.00,0:38:55.69,Default,,0,0,0,,而且是实时的\nDialogue: 0,0:38:56.54,0:38:58.46,Default,,0,0,0,,它们是非常小的程序\nDialogue: 0,0:38:58.62,0:39:01.50,Default,,0,0,0,,你需要注意到的一件事是\nDialogue: 0,0:39:02.91,0:39:04.40,Default,,0,0,0,,垃圾收集器必须要小\nDialogue: 0,0:39:05.40,0:39:07.10,Default,,0,0,0,,不是因为它们需要运行得快\nDialogue: 0,0:39:07.90,0:39:09.23,Default,,0,0,0,,因为没有人能够调试\nDialogue: 0,0:39:09.26,0:39:10.48,Default,,0,0,0,,复杂的垃圾收集器\nDialogue: 0,0:39:11.34,0:39:12.91,Default,,0,0,0,,如果一个垃圾收集器不能正常工作\nDialogue: 0,0:39:14.04,0:39:15.93,Default,,0,0,0,,它会把你的内存搞得一团糟\nDialogue: 0,0:39:15.93,0:39:17.39,Default,,0,0,0,,而你却束手无策\nDialogue: 0,0:39:18.35,0:39:19.67,Default,,0,0,0,,你需要跟踪审计\nDialogue: 0,0:39:20.66,0:39:22.01,Default,,0,0,0,,因为它把所有东西都换了位置\nDialogue: 0,0:39:22.04,0:39:23.24,Default,,0,0,0,,你需要知道那里发生了什么\nDialogue: 0,0:39:23.74,0:39:26.58,Default,,0,0,0,,所以这是唯一一种\nDialogue: 0,0:39:26.92,0:39:28.40,Default,,0,0,0,,真正非常重要的程序\nDialogue: 0,0:39:28.54,0:39:29.79,Default,,0,0,0,,如果你盯着它看足够久\nDialogue: 0,0:39:29.82,0:39:31.07,Default,,0,0,0,,那么你就相信它有效\nDialogue: 0,0:39:31.34,0:39:33.36,Default,,0,0,0,,这意味着某种“自我证明”\nDialogue: 0,0:39:33.92,0:39:36.11,Default,,0,0,0,,因此我们无法对它进行查错\nDialogue: 0,0:39:36.94,0:39:38.96,Default,,0,0,0,,这意味着它需要足够小\nDialogue: 0,0:39:38.96,0:39:39.97,Default,,0,0,0,,你的大脑能够思考它的工作情况\nDialogue: 0,0:39:41.45,0:39:43.90,Default,,0,0,0,,正因如此 垃圾收集器十分特殊\nDialogue: 0,0:39:45.02,0:39:47.12,Default,,0,0,0,,所以实用的垃圾收集器一定要短小\nDialogue: 0,0:39:47.13,0:39:48.45,Default,,0,0,0,,而通常短小的程序运行得就快\nDialogue: 0,0:39:52.05,0:39:52.43,Default,,0,0,0,,请讲\nDialogue: 0,0:39:52.43,0:39:54.51,Default,,0,0,0,,学生：您能再重复一遍这个技术的名字吗?\nDialogue: 0,0:39:54.68,0:39:56.92,Default,,0,0,0,,教授：Minsky-Fenichel-Yochelson垃圾回收器\nDialogue: 0,0:39:57.88,0:39:58.43,Default,,0,0,0,,学生：什么?\nDialogue: 0,0:39:59.00,0:40:00.78,Default,,0,0,0,,教授：Minsky在1961年\nDialogue: 0,0:40:00.81,0:40:02.21,Default,,0,0,0,,为RLE PDP-1设计了这个算法\nDialogue: 0,0:40:02.21,0:40:06.17,Default,,0,0,0,,Fenichel和Yochelson改进并精化了算法\nDialogue: 0,0:40:06.45,0:40:10.27,Default,,0,0,0,,将它用在了Multics平台的MacLisp中\nDialogue: 0,0:40:11.37,0:40:14.75,Default,,0,0,0,,那时大约是1968或者1969年\nDialogue: 0,0:40:19.57,0:40:21.36,Default,,0,0,0,,好吧 我们休息一下\nDialogue: 0,0:40:22.64,0:40:32.36,Default,,0,0,0,,[音乐]\nDialogue: 0,0:40:32.41,0:40:36.19,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:41:03.15,0:41:07.18,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:41:07.20,0:41:10.17,Declare,,0,0,0,,{\\an2\\fad(500,500)\\pos(320,470)}《计算机程序的构造和解释》\nDialogue: 0,0:41:10.20,0:41:14.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算的极限\nDialogue: 0,0:41:17.31,0:41:19.67,Default,,0,0,0,,教授：我们已经到课程的最后一部分了\nDialogue: 0,0:41:20.08,0:41:23.85,Default,,0,0,0,,我已经给你们展示了一台通用机器\nDialogue: 0,0:41:24.47,0:41:26.74,Default,,0,0,0,,它被简化为求值器\nDialogue: 0,0:41:27.02,0:41:28.38,Default,,0,0,0,,它被简化到\nDialogue: 0,0:41:28.38,0:41:29.67,Default,,0,0,0,,你自己也能构造出来\nDialogue: 0,0:41:30.19,0:41:33.32,Default,,0,0,0,,这是一个特定的Lisp实现\nDialogue: 0,0:41:33.90,0:41:36.01,Default,,0,0,0,,它是用\nDialogue: 0,0:41:36.16,0:41:38.05,Default,,0,0,0,,昨天讲过的Scheme芯片制作的\nDialogue: 0,0:41:38.20,0:41:38.91,Default,,0,0,0,,就是这个\nDialogue: 0,0:41:39.35,0:41:42.00,Default,,0,0,0,,这基本上就是暴露给他人内存的接口了\nDialogue: 0,0:41:42.60,0:41:44.75,Default,,0,0,0,,里面有节拍发生器等组件\nDialogue: 0,0:41:45.22,0:41:47.25,Default,,0,0,0,,尽管是解释执行\nDialogue: 0,0:41:47.77,0:41:50.17,Default,,0,0,0,,但它们运行Lisp的速度还算不错\nDialogue: 0,0:41:50.61,0:41:53.82,Default,,0,0,0,,它跑得像1979年的\nDialogue: 0,0:41:54.22,0:41:55.65,Default,,0,0,0,,DEC PDP-10一样快\nDialogue: 0,0:41:56.50,0:41:59.67,Default,,0,0,0,,作为一个十足的硬件\nDialogue: 0,0:42:00.02,0:42:00.89,Default,,0,0,0,,算是十分“实在”了\nDialogue: 0,0:42:02.47,0:42:04.70,Default,,0,0,0,,我们为你们讲解了一些\nDialogue: 0,0:42:04.72,0:42:06.07,Default,,0,0,0,,可以被计算的东西\nDialogue: 0,0:42:07.37,0:42:08.76,Default,,0,0,0,,但我们是否可能遇到\nDialogue: 0,0:42:09.32,0:42:10.55,Default,,0,0,0,,我们无法计算的情况？\nDialogue: 0,0:42:11.85,0:42:13.50,Default,,0,0,0,,课程的最后\nDialogue: 0,0:42:13.75,0:42:15.87,Default,,0,0,0,,我想展示一些你认为可以被计算\nDialogue: 0,0:42:16.60,0:42:17.22,Default,,0,0,0,,但实际上不能的东西\nDialogue: 0,0:42:18.19,0:42:19.45,Default,,0,0,0,,实际上\nDialogue: 0,0:42:19.45,0:42:20.82,Default,,0,0,0,,确实有我们无法计算的东西\nDialogue: 0,0:42:22.72,0:42:23.47,Default,,0,0,0,,例如\nDialogue: 0,0:42:24.45,0:42:25.82,Default,,0,0,0,,我们想要这样的一种东西\nDialogue: 0,0:42:27.80,0:42:29.36,Default,,0,0,0,,当我们在编写编译器时\nDialogue: 0,0:42:29.77,0:42:31.42,Default,,0,0,0,,你想用一个程序检查\nDialogue: 0,0:42:32.00,0:42:33.97,Default,,0,0,0,,你的代码能否正常运行\nDialogue: 0,0:42:34.63,0:42:35.40,Default,,0,0,0,,这不是很棒吗?\nDialogue: 0,0:42:36.08,0:42:37.87,Default,,0,0,0,,你希望能够捕获死循环\nDialogue: 0,0:42:37.87,0:42:38.54,Default,,0,0,0,,例如\nDialogue: 0,0:42:39.45,0:42:42.42,Default,,0,0,0,,用户编写的程序里的死循环\nDialogue: 0,0:42:43.19,0:42:45.12,Default,,0,0,0,,但通常来说 你写不出这样的程序\nDialogue: 0,0:42:45.35,0:42:46.49,Default,,0,0,0,,它读取某个程序\nDialogue: 0,0:42:46.51,0:42:47.45,Default,,0,0,0,,并检测它\nDialogue: 0,0:42:48.35,0:42:49.30,Default,,0,0,0,,是不是死循环\nDialogue: 0,0:42:50.99,0:42:51.71,Default,,0,0,0,,我来展示一下\nDialogue: 0,0:42:51.76,0:42:53.80,Default,,0,0,0,,这个需要涉及到数学知识\nDialogue: 0,0:42:58.78,0:42:59.65,Default,,0,0,0,,设想\nDialogue: 0,0:43:00.05,0:43:01.78,Default,,0,0,0,,在我们开始之前\nDialogue: 0,0:43:01.78,0:43:02.62,Default,,0,0,0,,有一个数学函数\nDialogue: 0,0:43:02.62,0:43:03.42,Default,,0,0,0,,这里就有一个\nDialogue: 0,0:43:03.84,0:43:04.67,Default,,0,0,0,,记作S\nDialogue: 0,0:43:05.47,0:43:07.54,Default,,0,0,0,,它接受一个过程\nDialogue: 0,0:43:12.64,0:43:14.23,Default,,0,0,0,,和它的参数A\nDialogue: 0,0:43:19.17,0:43:20.52,Default,,0,0,0,,S所做的是\nDialogue: 0,0:43:21.65,0:43:24.01,Default,,0,0,0,,检测以A为参数运行P时\nDialogue: 0,0:43:24.01,0:43:25.97,Default,,0,0,0,,是否安全\nDialogue: 0,0:43:26.90,0:43:28.17,Default,,0,0,0,,换句话说就是\nDialogue: 0,0:43:28.76,0:43:35.12,Default,,0,0,0,,如果(P A)\nDialogue: 0,0:43:35.62,0:43:36.74,Default,,0,0,0,,在没有出错的情况下\nDialogue: 0,0:43:41.40,0:43:42.45,Default,,0,0,0,,能够返回一个值\nDialogue: 0,0:43:44.35,0:43:45.33,Default,,0,0,0,,那么S就为TRUE\nDialogue: 0,0:43:52.70,0:43:53.68,Default,,0,0,0,,但如果(P A)\nDialogue: 0,0:43:56.10,0:43:57.04,Default,,0,0,0,,是死循环\nDialogue: 0,0:43:59.67,0:44:00.76,Default,,0,0,0,,或者抛出错误\nDialogue: 0,0:44:05.87,0:44:06.95,Default,,0,0,0,,那么S就为FALSE\nDialogue: 0,0:44:15.23,0:44:17.22,Default,,0,0,0,,这确实是个函数\nDialogue: 0,0:44:18.78,0:44:20.72,Default,,0,0,0,,对于你输入的任何过程\nDialogue: 0,0:44:21.20,0:44:22.85,Default,,0,0,0,,或者任何参数\nDialogue: 0,0:44:23.92,0:44:25.45,Default,,0,0,0,,它只能返回TRUE或FALSE\nDialogue: 0,0:44:25.92,0:44:27.85,Default,,0,0,0,,它会返回一个值而且不会报错\nDialogue: 0,0:44:28.44,0:44:30.15,Default,,0,0,0,,你可以为它们画一张巨大的表格\nDialogue: 0,0:44:32.22,0:44:32.92,Default,,0,0,0,,但问题是\nDialogue: 0,0:44:32.92,0:44:34.09,Default,,0,0,0,,你能写一个过程\nDialogue: 0,0:44:34.09,0:44:35.92,Default,,0,0,0,,来计算这个函数的值吗?\nDialogue: 0,0:44:37.43,0:44:38.92,Default,,0,0,0,,假设我们能做到\nDialogue: 0,0:44:39.72,0:44:40.55,Default,,0,0,0,,假设\nDialogue: 0,0:44:44.33,0:44:45.58,Default,,0,0,0,,我们有个过程\nDialogue: 0,0:44:48.55,0:44:52.73,Default,,0,0,0,,一个叫作SAFE?的过程\nDialogue: 0,0:44:56.54,0:44:59.90,Default,,0,0,0,,它能计算S的值\nDialogue: 0,0:45:12.65,0:45:14.89,Default,,0,0,0,,现在我要用几种方法\nDialogue: 0,0:45:15.90,0:45:18.51,Default,,0,0,0,,证明你做不到\nDialogue: 0,0:45:19.76,0:45:20.62,Default,,0,0,0,,最简单的一个\nDialogue: 0,0:45:20.62,0:45:21.28,Default,,0,0,0,,或者说第一个\nDialogue: 0,0:45:21.31,0:45:23.45,Default,,0,0,0,,我们定义一个叫DIAG1的过程\nDialogue: 0,0:45:23.76,0:45:24.86,Default,,0,0,0,,给定了SAFE?过程\nDialogue: 0,0:45:25.20,0:45:26.99,Default,,0,0,0,,我们可以把DIAG1定义为\nDialogue: 0,0:45:34.42,0:45:35.55,Default,,0,0,0,,把DIAG1定义为\nDialogue: 0,0:45:37.82,0:45:41.60,Default,,0,0,0,,只含有参数P的过程\nDialogue: 0,0:45:42.45,0:45:44.05,Default,,0,0,0,,它有着这样的属性\nDialogue: 0,0:45:44.78,0:45:50.67,Default,,0,0,0,,如果(SAFE? P P)为真\nDialogue: 0,0:45:53.32,0:45:55.32,Default,,0,0,0,,那么我就主动陷入死循环\nDialogue: 0,0:45:59.22,0:46:00.92,Default,,0,0,0,,否则我会返回3\nDialogue: 0,0:46:03.68,0:46:04.47,Default,,0,0,0,,它也可能是42\nDialogue: 0,0:46:04.47,0:46:06.42,Default,,0,0,0,,宇宙的终极答案是什么?\nDialogue: 0,0:46:07.06,0:46:08.87,Default,,0,0,0,,我们当然知道死循环是什么\nDialogue: 0,0:46:12.05,0:46:12.96,Default,,0,0,0,,死循环INF是\nDialogue: 0,0:46:13.82,0:46:16.02,Default,,0,0,0,,一个无参过程\nDialogue: 0,0:46:16.02,0:46:18.07,Default,,0,0,0,,这是一个极好的LAMBADA演算循环\nDialogue: 0,0:46:18.35,0:46:20.44,Default,,0,0,0,,(LAMBDA (X) (X X))\nDialogue: 0,0:46:21.30,0:46:24.68,Default,,0,0,0,,应用到(LAMBDA (X) (X X))\nDialogue: 0,0:46:24.68,0:46:26.55,Default,,0,0,0,,没什么想象的余地了\nDialogue: 0,0:46:29.83,0:46:31.17,Default,,0,0,0,,我们来看下会发生什么\nDialogue: 0,0:46:32.50,0:46:33.90,Default,,0,0,0,,我假设\nDialogue: 0,0:46:35.45,0:46:38.77,Default,,0,0,0,,我们考虑\nDialogue: 0,0:46:39.00,0:46:43.45,Default,,0,0,0,,把DIAG1应用到DIAG1上\nDialogue: 0,0:46:46.27,0:46:47.77,Default,,0,0,0,,那会发生什么呢?\nDialogue: 0,0:46:49.97,0:46:51.39,Default,,0,0,0,,我不知道\nDialogue: 0,0:46:51.39,0:46:53.21,Default,,0,0,0,,将DIAG1代换为\nDialogue: 0,0:46:53.55,0:46:55.50,Default,,0,0,0,,P的过程体\nDialogue: 0,0:46:57.31,0:47:00.22,Default,,0,0,0,,(SAFE? DIAG1 DIAG1)会返回什么呢？\nDialogue: 0,0:47:00.22,0:47:00.78,Default,,0,0,0,,我不知道\nDialogue: 0,0:47:00.78,0:47:01.82,Default,,0,0,0,,有两种可能\nDialogue: 0,0:47:03.40,0:47:05.50,Default,,0,0,0,,如果计算(DIAG1 DIAG1)是安全的\nDialogue: 0,0:47:05.92,0:47:06.89,Default,,0,0,0,,这意味着没有死循环\nDialogue: 0,0:47:08.49,0:47:09.22,Default,,0,0,0,,那么我就要来到这里\nDialogue: 0,0:47:09.22,0:47:10.35,Default,,0,0,0,,但是随即我就陷入了死循环\nDialogue: 0,0:47:10.56,0:47:11.57,Default,,0,0,0,,所以它不是安全的\nDialogue: 0,0:47:12.21,0:47:14.78,Default,,0,0,0,,但如果计算(DIAG1 DIAG1)不安全\nDialogue: 0,0:47:14.90,0:47:16.02,Default,,0,0,0,,那么它的结果是3\nDialogue: 0,0:47:16.02,0:47:17.26,Default,,0,0,0,,但是调用(DIAG1 DIAG1)又必须能够返回\nDialogue: 0,0:47:17.26,0:47:17.93,Default,,0,0,0,,所以它必须安全才行\nDialogue: 0,0:47:20.53,0:47:23.60,Default,,0,0,0,,因此 通过归纳出这个矛盾\nDialogue: 0,0:47:24.32,0:47:26.30,Default,,0,0,0,,我们无法写出这个SAFE?过程\nDialogue: 0,0:47:27.40,0:47:29.80,Default,,0,0,0,,如果大家没有听明白这种表述\nDialogue: 0,0:47:30.25,0:47:32.15,Default,,0,0,0,,我换个方式再讲一遍\nDialogue: 0,0:47:32.82,0:47:34.00,Default,,0,0,0,,请听另一个版本\nDialogue: 0,0:47:35.53,0:47:36.95,Default,,0,0,0,,我们定义DIAG2\nDialogue: 0,0:47:39.84,0:47:41.60,Default,,0,0,0,,取名叫DIAG是因为\nDialogue: 0,0:47:42.65,0:47:44.72,Default,,0,0,0,,它来源于康托尔的对角论证法\nDialogue: 0,0:47:45.00,0:47:47.05,Default,,0,0,0,,这些事例最初都来自于\nDialogue: 0,0:47:47.05,0:47:49.05,Default,,0,0,0,,一个著名的论证\nDialogue: 0,0:47:49.45,0:47:52.65,Default,,0,0,0,,也就是康托尔在19世纪末\nDialogue: 0,0:47:52.77,0:47:56.10,Default,,0,0,0,,证明了实数是不可数的\nDialogue: 0,0:47:56.67,0:47:58.00,Default,,0,0,0,,整数与实数\nDialogue: 0,0:47:58.06,0:47:59.42,Default,,0,0,0,,无法形成一一映射\nDialogue: 0,0:48:00.19,0:48:01.74,Default,,0,0,0,,数轴上的点\nDialogue: 0,0:48:01.74,0:48:02.50,Default,,0,0,0,,举例来说\nDialogue: 0,0:48:02.50,0:48:04.42,Default,,0,0,0,,比数轴上的刻度还要多\nDialogue: 0,0:48:05.26,0:48:06.85,Default,,0,0,0,,这或许不是个显而易见的结论\nDialogue: 0,0:48:06.85,0:48:08.17,Default,,0,0,0,,但我不想深入讨论这个\nDialogue: 0,0:48:10.90,0:48:12.45,Default,,0,0,0,,但是DIAG2\nDialogue: 0,0:48:13.30,0:48:15.82,Default,,0,0,0,,也是一个参数为P的单参过程\nDialogue: 0,0:48:15.82,0:48:17.47,Default,,0,0,0,,这几乎与之前的例子相同\nDialogue: 0,0:48:17.72,0:48:24.32,Default,,0,0,0,,如果计算(P P)是安全的\nDialogue: 0,0:48:25.17,0:48:26.67,Default,,0,0,0,,那么我就要\nDialogue: 0,0:48:27.26,0:48:28.14,Default,,0,0,0,,哦 漏了一个IF\nDialogue: 0,0:48:29.31,0:48:31.02,Default,,0,0,0,,那么我就去计算\nDialogue: 0,0:48:31.57,0:48:37.58,Default,,0,0,0,,一些(P P)之外的东西\nDialogue: 0,0:48:38.96,0:48:40.21,Default,,0,0,0,,否则我就返回FALSE\nDialogue: 0,0:48:43.60,0:48:45.30,Default,,0,0,0,,这里的OTHER-THAN意思是\nDialogue: 0,0:48:45.47,0:48:46.35,Default,,0,0,0,,不管这个(P P)是什么\nDialogue: 0,0:48:46.35,0:48:47.47,Default,,0,0,0,,我都返回一些别的东西\nDialogue: 0,0:48:48.88,0:48:50.03,Default,,0,0,0,,我来给出一个\nDialogue: 0,0:48:50.07,0:48:51.52,Default,,0,0,0,,OTHER-THAN的一个定义\nDialogue: 0,0:48:51.60,0:48:52.57,Default,,0,0,0,,我觉得它是可用的\nDialogue: 0,0:48:53.89,0:48:54.51,Default,,0,0,0,,来看看\nDialogue: 0,0:48:55.64,0:48:56.08,Default,,0,0,0,,好\nDialogue: 0,0:48:56.33,0:48:57.26,Default,,0,0,0,,定义OTHER-THAN\nDialogue: 0,0:49:04.03,0:49:06.11,Default,,0,0,0,,参数为X的单参过程\nDialogue: 0,0:49:06.57,0:49:07.26,Default,,0,0,0,,过程体是\nDialogue: 0,0:49:08.05,0:49:12.96,Default,,0,0,0,,如果(EQ? X 'A)\nDialogue: 0,0:49:13.47,0:49:15.07,Default,,0,0,0,,那么结果是'B\nDialogue: 0,0:49:15.72,0:49:16.80,Default,,0,0,0,,否则结果是'A\nDialogue: 0,0:49:20.27,0:49:21.90,Default,,0,0,0,,这样无论参数是什么\nDialogue: 0,0:49:22.07,0:49:23.45,Default,,0,0,0,,返回值跟参数总是不相同的\nDialogue: 0,0:49:25.20,0:49:26.12,Default,,0,0,0,,就是这样了\nDialogue: 0,0:49:26.54,0:49:27.37,Default,,0,0,0,,这就是我要的\nDialogue: 0,0:49:28.25,0:49:29.58,Default,,0,0,0,,我们考虑一下这个\nDialogue: 0,0:49:29.58,0:49:31.15,Default,,0,0,0,,(DIAG2 DIAG2)\nDialogue: 0,0:49:38.28,0:49:38.94,Default,,0,0,0,,看\nDialogue: 0,0:49:39.95,0:49:41.72,Default,,0,0,0,,这个东西会做些危险的事情\nDialogue: 0,0:49:42.00,0:49:43.45,Default,,0,0,0,,比如求值(P P)\nDialogue: 0,0:49:44.75,0:49:45.95,Default,,0,0,0,,如果它是安全的\nDialogue: 0,0:49:47.47,0:49:49.16,Default,,0,0,0,,如果SAFE?能够被定义的话\nDialogue: 0,0:49:50.30,0:49:52.49,Default,,0,0,0,,如果你能定义SAFE?过程\nDialogue: 0,0:49:52.97,0:49:54.32,Default,,0,0,0,,那么这个过程\nDialogue: 0,0:49:54.60,0:49:56.40,Default,,0,0,0,,也就顺理成章地是安全的\nDialogue: 0,0:49:56.52,0:49:57.22,Default,,0,0,0,,对于任意输入来说都是\nDialogue: 0,0:50:01.54,0:50:03.50,Default,,0,0,0,,那么(DIAG2 DIAG2)\nDialogue: 0,0:50:03.87,0:50:12.20,Default,,0,0,0,,就会返回(OTHER-THAN (DIAG2 DIAG2))\nDialogue: 0,0:50:15.82,0:50:16.97,Default,,0,0,0,,这说不通\nDialogue: 0,0:50:17.80,0:50:19.02,Default,,0,0,0,,又产生了悖论\nDialogue: 0,0:50:19.85,0:50:21.57,Default,,0,0,0,,因此我们不能定义SAFE?\nDialogue: 0,0:50:22.95,0:50:24.23,Default,,0,0,0,,我只想这样证明两次\nDialogue: 0,0:50:24.78,0:50:25.82,Default,,0,0,0,,有些许不同\nDialogue: 0,0:50:26.84,0:50:27.90,Default,,0,0,0,,你不会感到\nDialogue: 0,0:50:29.07,0:50:30.86,Default,,0,0,0,,第一个证明是个把戏\nDialogue: 0,0:50:32.54,0:50:33.45,Default,,0,0,0,,它们可能都是把戏\nDialogue: 0,0:50:33.80,0:50:35.15,Default,,0,0,0,,但它们稍微有些不同\nDialogue: 0,0:50:37.30,0:50:39.20,Default,,0,0,0,,因此 我想这就基本上讲清楚了\nDialogue: 0,0:50:40.03,0:50:41.97,Default,,0,0,0,,我们刚刚证明了所谓的“停机问题”\nDialogue: 0,0:50:43.00,0:50:44.70,Default,,0,0,0,,我想 本课程也即将画上句号\nDialogue: 0,0:50:46.72,0:50:47.63,Default,,0,0,0,,希望你们有所收获\nDialogue: 0,0:50:50.90,0:50:51.76,Default,,0,0,0,,有什么问题吗?\nDialogue: 0,0:50:53.30,0:50:53.56,Default,,0,0,0,,请讲\nDialogue: 0,0:50:53.81,0:50:56.27,Default,,0,0,0,,学生: (S DIAG1)的值是什么?\nDialogue: 0,0:50:56.75,0:50:57.23,Default,,0,0,0,,教授: 什么的值?\nDialogue: 0,0:50:57.50,0:50:58.80,Default,,0,0,0,,学生: (S DIAG1)的值\nDialogue: 0,0:51:00.12,0:51:02.20,Default,,0,0,0,,如果你说S是个函数 我们就可以--\nDialogue: 0,0:51:02.30,0:51:03.63,Default,,0,0,0,,教授: 噢 我不知道啊\nDialogue: 0,0:51:03.87,0:51:04.35,Default,,0,0,0,,我不知道\nDialogue: 0,0:51:04.35,0:51:04.88,Default,,0,0,0,,它是一个函数\nDialogue: 0,0:51:04.88,0:51:05.85,Default,,0,0,0,,但我不知道如何计算它\nDialogue: 0,0:51:06.80,0:51:08.00,Default,,0,0,0,,我做不到\nDialogue: 0,0:51:08.61,0:51:09.64,Default,,0,0,0,,我也只是个机器\nDialogue: 0,0:51:11.53,0:51:11.88,Default,,0,0,0,,对吧?\nDialogue: 0,0:51:11.90,0:51:13.37,Default,,0,0,0,,原则上来说\nDialogue: 0,0:51:13.37,0:51:14.05,Default,,0,0,0,,没有机器\nDialogue: 0,0:51:14.47,0:51:16.87,Default,,0,0,0,,当然 也有可能会处在你刚才问的那个情况中\nDialogue: 0,0:51:16.87,0:51:18.32,Default,,0,0,0,,花点时间还是可以计算出来\nDialogue: 0,0:51:18.58,0:51:19.37,Default,,0,0,0,,但通常情况下\nDialogue: 0,0:51:19.60,0:51:21.05,Default,,0,0,0,,我无法计算S的值\nDialogue: 0,0:51:21.05,0:51:22.52,Default,,0,0,0,,别的机器也做不到\nDialogue: 0,0:51:23.78,0:51:24.92,Default,,0,0,0,,存在这样一个函数\nDialogue: 0,0:51:25.92,0:51:28.00,Default,,0,0,0,,没有任何机器能够计算它\nDialogue: 0,0:51:29.58,0:51:30.05,Default,,0,0,0,,现在\nDialogue: 0,0:51:30.67,0:51:33.67,Default,,0,0,0,,我这么来说也不会让你们吃惊\nDialogue: 0,0:51:35.22,0:51:36.25,Default,,0,0,0,,来想一想\nDialogue: 0,0:51:36.25,0:51:38.36,Default,,0,0,0,,现在我没有时间给你们展示\nDialogue: 0,0:51:38.45,0:51:43.00,Default,,0,0,0,,但这样的函数非常多\nDialogue: 0,0:51:44.40,0:51:47.58,Default,,0,0,0,,如果有一定量的可能输入\nDialogue: 0,0:51:47.75,0:51:49.62,Default,,0,0,0,,和一定量可能的结果\nDialogue: 0,0:51:49.87,0:51:51.80,Default,,0,0,0,,那么结果数量的输入数量次幂\nDialogue: 0,0:51:51.80,0:51:53.20,Default,,0,0,0,,就是可能的函数的数量\nDialogue: 0,0:51:54.50,0:51:55.48,Default,,0,0,0,,这还是单参的函数\nDialogue: 0,0:51:56.51,0:51:59.24,Default,,0,0,0,,而多参函数的个数\nDialogue: 0,0:52:00.09,0:52:03.21,Default,,0,0,0,,又比这个幂次方\nDialogue: 0,0:52:03.58,0:52:04.32,Default,,0,0,0,,这个指数还要大\nDialogue: 0,0:52:05.48,0:52:09.80,Default,,0,0,0,,函数的数量\nDialogue: 0,0:52:09.95,0:52:12.72,Default,,0,0,0,,比一个人能写出的\nDialogue: 0,0:52:13.30,0:52:14.10,Default,,0,0,0,,程序的数量更多\nDialogue: 0,0:52:14.82,0:52:16.45,Default,,0,0,0,,因为有无穷多的参数\nDialogue: 0,0:52:17.57,0:52:19.00,Default,,0,0,0,,可能会更多\nDialogue: 0,0:52:19.47,0:52:22.12,Default,,0,0,0,,所以不可计算的函数数量\nDialogue: 0,0:52:22.12,0:52:23.48,Default,,0,0,0,,一定会非常多\nDialogue: 0,0:52:25.92,0:52:26.59,Default,,0,0,0,,学生：不久前\nDialogue: 0,0:52:26.64,0:52:28.25,Default,,0,0,0,,你讲了规范\nDialogue: 0,0:52:28.30,0:52:30.04,Default,,0,0,0,,和自动生成解决方案\nDialogue: 0,0:52:30.64,0:52:31.61,Default,,0,0,0,,您觉得通过规范\nDialogue: 0,0:52:31.82,0:52:33.36,Default,,0,0,0,,能够生成解决方案么？\nDialogue: 0,0:52:37.25,0:52:38.22,Default,,0,0,0,,教授：“生成”\nDialogue: 0,0:52:38.72,0:52:39.37,Default,,0,0,0,,你是说\nDialogue: 0,0:52:39.37,0:52:42.60,Default,,0,0,0,,如何按照规范\nDialogue: 0,0:52:42.60,0:52:44.78,Default,,0,0,0,,构建相应的装置吗?\nDialogue: 0,0:52:45.05,0:52:48.36,Default,,0,0,0,,学生：软件工程中有很多\nDialogue: 0,0:52:48.36,0:52:49.90,Default,,0,0,0,,层次化的设计\nDialogue: 0,0:52:49.90,0:52:51.90,Default,,0,0,0,,并进行实现的规范\nDialogue: 0,0:52:52.43,0:52:52.85,Default,,0,0,0,,教授：是的\nDialogue: 0,0:52:52.85,0:52:53.70,Default,,0,0,0,,学生：我很好奇\nDialogue: 0,0:52:53.70,0:52:54.62,Default,,0,0,0,,您觉得这现实吗?\nDialogue: 0,0:52:55.60,0:52:57.17,Default,,0,0,0,,教授：我觉得其中一些是现实的\nDialogue: 0,0:52:57.17,0:52:58.10,Default,,0,0,0,,另一些不现实\nDialogue: 0,0:52:58.10,0:53:00.32,Default,,0,0,0,,如果你想制造一个滤波器\nDialogue: 0,0:53:01.17,0:53:07.16,Default,,0,0,0,,我这有个挺有趣的例子\nDialogue: 0,0:53:07.16,0:53:09.42,Default,,0,0,0,,假设我想制造一个东西\nDialogue: 0,0:53:09.64,0:53:14.07,Default,,0,0,0,,把无线电发射器的输出\nDialogue: 0,0:53:14.47,0:53:18.75,Default,,0,0,0,,连接到某条天线上\nDialogue: 0,0:53:19.90,0:53:21.47,Default,,0,0,0,,我先把它引出来\nDialogue: 0,0:53:21.48,0:53:23.04,Default,,0,0,0,,这里是输出管线\nDialogue: 0,0:53:23.23,0:53:25.26,Default,,0,0,0,,问题是它们的阻抗不同\nDialogue: 0,0:53:25.92,0:53:27.55,Default,,0,0,0,,我希望能够匹配阻抗\nDialogue: 0,0:53:27.55,0:53:28.97,Default,,0,0,0,,我也想在其中加入一个滤波器\nDialogue: 0,0:53:29.15,0:53:31.71,Default,,0,0,0,,用来过滤一些谐波辐射\nDialogue: 0,0:53:32.78,0:53:36.63,Default,,0,0,0,,一种老派的技术叫作\nDialogue: 0,0:53:36.82,0:53:38.67,Default,,0,0,0,,“影像阻抗”之类的东西\nDialogue: 0,0:53:38.86,0:53:39.50,Default,,0,0,0,,你要做的是\nDialogue: 0,0:53:39.50,0:53:40.85,Default,,0,0,0,,你有个基础的模块\nDialogue: 0,0:53:40.85,0:53:42.75,Default,,0,0,0,,称为L型滤波器\nDialogue: 0,0:53:43.30,0:53:43.98,Default,,0,0,0,,就像这样\nDialogue: 0,0:53:47.08,0:53:49.80,Default,,0,0,0,,如果把它连接到某些电阻R上\nDialogue: 0,0:53:50.05,0:53:52.60,Default,,0,0,0,,如果我把它的阻抗记作X_L\nDialogue: 0,0:53:52.72,0:53:55.20,Default,,0,0,0,,而它的值刚好又等于Q*R\nDialogue: 0,0:53:55.26,0:53:58.52,Default,,0,0,0,,这就成了一个低通滤波器\nDialogue: 0,0:53:58.52,0:54:00.72,Default,,0,0,0,,有Q^2+1的等效阻抗\nDialogue: 0,0:54:02.11,0:54:02.86,Default,,0,0,0,,这就是我想要的\nDialogue: 0,0:54:03.12,0:54:04.28,Default,,0,0,0,,因为这样我就可以\nDialogue: 0,0:54:04.30,0:54:05.08,Default,,0,0,0,,把它们匹配到一起了\nDialogue: 0,0:54:05.82,0:54:06.38,Default,,0,0,0,,就像这样\nDialogue: 0,0:54:11.66,0:54:13.15,Default,,0,0,0,,我拿来另一个\nDialogue: 0,0:54:16.00,0:54:17.45,Default,,0,0,0,,想这样把它们连到一起\nDialogue: 0,0:54:18.29,0:54:19.95,Default,,0,0,0,,有两个L型滤波器连接起来\nDialogue: 0,0:54:20.32,0:54:23.07,Default,,0,0,0,,这能让它的阻抗降到我知道的值\nDialogue: 0,0:54:23.37,0:54:25.22,Default,,0,0,0,,让它的阻抗升到我知道的值\nDialogue: 0,0:54:25.53,0:54:26.64,Default,,0,0,0,,这两个低通滤波器\nDialogue: 0,0:54:26.67,0:54:27.82,Default,,0,0,0,,都过滤掉了一些谐波\nDialogue: 0,0:54:28.09,0:54:29.07,Default,,0,0,0,,这是个不错的滤波器\nDialogue: 0,0:54:29.07,0:54:30.27,Default,,0,0,0,,这就是π型滤波器\nDialogue: 0,0:54:30.27,0:54:30.62,Default,,0,0,0,,很好\nDialogue: 0,0:54:31.70,0:54:34.09,Default,,0,0,0,,除了实际上\nDialogue: 0,0:54:34.12,0:54:37.85,Default,,0,0,0,,我在系统里放了些无用的东西\nDialogue: 0,0:54:38.62,0:54:39.60,Default,,0,0,0,,我在本该只用一个的地方\nDialogue: 0,0:54:39.61,0:54:40.59,Default,,0,0,0,,用了两个线圈\nDialogue: 0,0:54:41.62,0:54:44.60,Default,,0,0,0,,在大多数软件工程技艺中\nDialogue: 0,0:54:44.89,0:54:46.88,Default,,0,0,0,,在人工优化和编译之外\nDialogue: 0,0:54:46.92,0:54:48.65,Default,,0,0,0,,不存在一种机制\nDialogue: 0,0:54:48.80,0:54:51.34,Default,,0,0,0,,能在自顶向下的设计中\nDialogue: 0,0:54:51.34,0:54:53.55,Default,,0,0,0,,去掉冗余的部分\nDialogue: 0,0:54:55.35,0:54:56.07,Default,,0,0,0,,或许会更糟\nDialogue: 0,0:54:56.07,0:54:57.58,Default,,0,0,0,,有很多重要的结构\nDialogue: 0,0:54:57.60,0:54:59.02,Default,,0,0,0,,你无法采用这种方式构建\nDialogue: 0,0:55:01.11,0:55:03.53,Default,,0,0,0,,我觉得标准的自上而下的设计方式\nDialogue: 0,0:55:03.53,0:55:04.87,Default,,0,0,0,,是一种很短视的手段\nDialogue: 0,0:55:05.71,0:55:06.60,Default,,0,0,0,,它不会真的抓到\nDialogue: 0,0:55:06.60,0:55:08.10,Default,,0,0,0,,设计者真正想要的结果\nDialogue: 0,0:55:08.31,0:55:10.10,Default,,0,0,0,,我再举一个电子学的例子\nDialogue: 0,0:55:10.10,0:55:11.75,Default,,0,0,0,,电子学的例子\nDialogue: 0,0:55:11.90,0:55:13.13,Default,,0,0,0,,要比计算的例子直观得多\nDialogue: 0,0:55:13.16,0:55:14.78,Default,,0,0,0,,因为计算的例子\nDialogue: 0,0:55:14.80,0:55:16.52,Default,,0,0,0,,解释起来比较复杂\nDialogue: 0,0:55:17.22,0:55:19.16,Default,,0,0,0,,在电子学世界中\nDialogue: 0,0:55:19.16,0:55:20.04,Default,,0,0,0,,我最喜欢的例子之一是\nDialogue: 0,0:55:20.60,0:55:22.80,Default,,0,0,0,,是如何设计中频放大器中\nDialogue: 0,0:55:23.28,0:55:26.55,Default,,0,0,0,,输入级和输出级的连接方式\nDialogue: 0,0:55:27.53,0:55:29.44,Default,,0,0,0,,这是一个三极管\nDialogue: 0,0:55:29.52,0:55:31.50,Default,,0,0,0,,我们来看看\nDialogue: 0,0:55:32.41,0:55:33.40,Default,,0,0,0,,这有个LC震荡电路\nDialogue: 0,0:55:36.45,0:55:39.17,Default,,0,0,0,,我要把它\nDialogue: 0,0:55:41.37,0:55:43.97,Default,,0,0,0,,把它与下一级的输入线圈耦合在一起\nDialogue: 0,0:55:44.36,0:55:47.47,Default,,0,0,0,,这是个完美的可行方案\nDialogue: 0,0:55:48.22,0:55:50.87,Default,,0,0,0,,除了我这个电流方向画错了\nDialogue: 0,0:55:50.87,0:55:52.92,Default,,0,0,0,,电流应该是这个方向\nDialogue: 0,0:55:53.17,0:55:55.45,Default,,0,0,0,,这是个完美的可行方案\nDialogue: 0,0:55:55.98,0:55:56.57,Default,,0,0,0,,不对\nDialogue: 0,0:55:57.12,0:55:57.79,Default,,0,0,0,,我犯蠢了\nDialogue: 0,0:55:58.40,0:55:59.07,Default,,0,0,0,,对不起\nDialogue: 0,0:55:59.69,0:56:00.42,Default,,0,0,0,,这不重要\nDialogue: 0,0:56:00.73,0:56:01.54,Default,,0,0,0,,关键在于这是一个\nDialogue: 0,0:56:01.54,0:56:03.42,Default,,0,0,0,,把两级耦合起来的完美方案\nDialogue: 0,0:56:04.54,0:56:06.92,Default,,0,0,0,,分层来看时会产生什么问题?\nDialogue: 0,0:56:07.62,0:56:08.80,Default,,0,0,0,,它就不是同一个东西了\nDialogue: 0,0:56:09.48,0:56:11.99,Default,,0,0,0,,当分层来看时它就没有任何意义了\nDialogue: 0,0:56:11.99,0:56:14.32,Default,,0,0,0,,这是一个调谐电路的电感\nDialogue: 0,0:56:15.55,0:56:18.02,Default,,0,0,0,,这是变压器的初级线圈\nDialogue: 0,0:56:19.10,0:56:21.82,Default,,0,0,0,,这是直流的通路\nDialogue: 0,0:56:21.82,0:56:23.57,Default,,0,0,0,,它是三极管的集电极\nDialogue: 0,0:56:23.57,0:56:25.10,Default,,0,0,0,,的偏置条件\nDialogue: 0,0:56:26.46,0:56:28.35,Default,,0,0,0,,没有任何简单的自顶向下设计\nDialogue: 0,0:56:28.38,0:56:30.17,Default,,0,0,0,,能够得到这样的结构\nDialogue: 0,0:56:30.22,0:56:34.02,Default,,0,0,0,,对于同一个东西有大量的复用\nDialogue: 0,0:56:34.53,0:56:36.72,Default,,0,0,0,,玩拼字游戏\nDialogue: 0,0:56:36.96,0:56:39.88,Default,,0,0,0,,当你要完成三倍分数的词时\nDialogue: 0,0:56:40.49,0:56:43.60,Default,,0,0,0,,自顶向下的设计策略并不容易\nDialogue: 0,0:56:44.95,0:56:47.08,Default,,0,0,0,,然而 大多数实际的工程学都是\nDialogue: 0,0:56:47.36,0:56:50.70,Default,,0,0,0,,秉承着“尽其力而为之”\nDialogue: 0,0:56:52.14,0:56:53.52,Default,,0,0,0,,那就是你所看到的东西\nDialogue: 0,0:56:54.86,0:56:55.55,Default,,0,0,0,,嗯？\nDialogue: 0,0:56:55.55,0:56:56.81,Default,,0,0,0,,学生：这是最后一个问题吗?\nDialogue: 0,0:57:00.28,0:57:02.03,Default,,0,0,0,,[笑声]\nDialogue: 0,0:57:18.64,0:57:19.63,Default,,0,0,0,,教授：看起来是\nDialogue: 0,0:57:23.57,0:57:24.12,Default,,0,0,0,,谢谢大家\nDialogue: 0,0:57:25.90,0:57:36.50,Default,,0,0,0,,[掌声]\nDialogue: 0,0:58:47.29,0:58:51.13,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:58:47.29,0:58:51.13,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\nDialogue: 0,0:58:51.87,0:58:53.71,Default,,0,0,0,,{\\an4\\pos(33,231)}　　你所知道的有关计算的东西，其他人也都能学到。绝不要认为\\N\\N\\N似乎成功计算的钥匙就掌握在你的手里。你所掌握的，也是我认为\\N\\N\\N并希望的，也就是智慧：那种看到这一机器比你第一次站在它面前\\N\\N\\N时能做得更多的能力，这样你才能将它向前推进。\\N\\N\\N\\N\\N　　　　　　　　　　　　　  　Alan J. Perlis (1922.4.1 - 1990.1.7)\n"
  },
  {
    "path": "Ass/lec10b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nAudio File: ../../../../Movies/Lec10b_480_muxed.mp4\nVideo File: ../../../../Movies/Lec10b_480_muxed.mp4\nVideo AR Mode: 4\nVideo AR Value: 1.333333\nVideo Zoom Percent: 2.000000\nScroll Position: 1311\nActive Line: 1321\nVideo Position: 105851\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:03.48,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:00.00,0:00:03.48,Declare,,0,0,0,,{\\fad(500,500)\\pos(316,274)}“让我们举杯，祝福那些\\N\\N\\N\\N将他们的思想镶嵌在\\N\\N\\N\\N　　　重重括号之间的Lisp程序员。”\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N杨启钊\\N（windfarer）\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:04.75,0:00:11.77,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:04.75,0:00:11.77,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:11.88,0:00:15.72,Declare,,0,0,0,,{\\an2\\fad(500,500)}存储分配与垃圾收集\nDialogue: 0,0:00:18.91,0:00:20.61,Default,,0,0,0,,教授: 接下来我要解开\nDialogue: 0,0:00:21.16,0:00:23.36,Default,,0,0,0,,目前仅剩的谜团\nDialogue: 0,0:00:24.44,0:00:28.80,Default,,0,0,0,,我们能毫无顾虑地进行CONS\nDialogue: 0,0:00:30.00,0:00:31.62,Default,,0,0,0,,就好像空间足够多一样\nDialogue: 0,0:00:32.80,0:00:36.32,Default,,0,0,0,,我们总是在使用\nDialogue: 0,0:00:36.51,0:00:37.44,Default,,0,0,0,,CAR和CDR\nDialogue: 0,0:00:37.47,0:00:38.72,Default,,0,0,0,,并假设知道我们知道\nDialogue: 0,0:00:38.75,0:00:39.74,Default,,0,0,0,,它们是如何实现的\nDialogue: 0,0:00:40.02,0:00:40.67,Default,,0,0,0,,事实上\nDialogue: 0,0:00:41.07,0:00:44.40,Default,,0,0,0,,我们认为它们是基本过程\nDialogue: 0,0:00:45.37,0:00:47.57,Default,,0,0,0,,但这没有真正解决问题\nDialogue: 0,0:00:47.73,0:00:50.25,Default,,0,0,0,,因为过程依赖各种复杂的机制\nDialogue: 0,0:00:50.27,0:00:51.37,Default,,0,0,0,,需要诸如环境结构之类的东西\nDialogue: 0,0:00:51.64,0:00:52.76,Default,,0,0,0,,才能运行起来\nDialogue: 0,0:00:53.01,0:00:54.89,Default,,0,0,0,,而归根结底它们也是\nDialogue: 0,0:00:54.89,0:00:56.42,Default,,0,0,0,,由CONS之类的东西构成的\nDialogue: 0,0:00:56.70,0:00:58.47,Default,,0,0,0,,这的确没有解决问题\nDialogue: 0,0:00:59.38,0:01:01.13,Default,,0,0,0,,目前的问题是\nDialogue: 0,0:01:01.31,0:01:03.97,Default,,0,0,0,,粘合这些数据结构的是什么东西？\nDialogue: 0,0:01:04.76,0:01:06.40,Default,,0,0,0,,它可能是怎样的一个东西?\nDialogue: 0,0:01:07.04,0:01:10.46,Default,,0,0,0,,我们已经见过了一台机器\nDialogue: 0,0:01:10.46,0:01:13.96,Default,,0,0,0,,一台计算机具有一个控制器\nDialogue: 0,0:01:14.27,0:01:15.45,Default,,0,0,0,,和一些寄存器\nDialogue: 0,0:01:15.45,0:01:16.47,Default,,0,0,0,,还可能有一个栈\nDialogue: 0,0:01:16.98,0:01:18.12,Default,,0,0,0,,但是我们还没提到一些东西\nDialogue: 0,0:01:18.16,0:01:19.95,Default,,0,0,0,,例如 大内存\nDialogue: 0,0:01:20.57,0:01:22.38,Default,,0,0,0,,我想 现在是时候讨论它们了\nDialogue: 0,0:01:23.74,0:01:26.56,Default,,0,0,0,,但是先要说清楚\nDialogue: 0,0:01:26.59,0:01:27.88,Default,,0,0,0,,这个并不是必须的\nDialogue: 0,0:01:28.82,0:01:30.79,Default,,0,0,0,,只是一些实现上的细节\nDialogue: 0,0:01:31.10,0:01:32.60,Default,,0,0,0,,让我举个例子\nDialogue: 0,0:01:32.60,0:01:34.20,Default,,0,0,0,,如何用数字来表示这些东西\nDialogue: 0,0:01:35.23,0:01:36.82,Default,,0,0,0,,有个比较简单的方法\nDialogue: 0,0:01:37.59,0:01:39.00,Default,,0,0,0,,一位著名的逻辑学家 哥德尔\nDialogue: 0,0:01:44.09,0:01:46.01,Default,,0,0,0,,在20世纪30年代末\nDialogue: 0,0:01:46.38,0:01:48.70,Default,,0,0,0,,发明了一个很巧妙的方法\nDialogue: 0,0:01:48.70,0:01:52.27,Default,,0,0,0,,能够把复杂的表达式\nDialogue: 0,0:01:52.81,0:01:53.52,Default,,0,0,0,,表示成数字\nDialogue: 0,0:01:54.32,0:01:55.05,Default,,0,0,0,,例如\nDialogue: 0,0:01:55.05,0:01:58.00,Default,,0,0,0,,我不会照搬哥德尔的方法\nDialogue: 0,0:01:58.00,0:01:59.48,Default,,0,0,0,,因为他没有使用CONS之类的术语\nDialogue: 0,0:01:59.66,0:02:00.60,Default,,0,0,0,,他使用了其它的组合手段\nDialogue: 0,0:02:00.91,0:02:02.60,Default,,0,0,0,,来编码表达式\nDialogue: 0,0:02:03.09,0:02:03.88,Default,,0,0,0,,他的思路是\nDialogue: 0,0:02:03.92,0:02:06.81,Default,,0,0,0,,用不同数字分别代表每个代数式\nDialogue: 0,0:02:07.92,0:02:09.72,Default,,0,0,0,,通过组合各个部分的数字\nDialogue: 0,0:02:09.72,0:02:11.65,Default,,0,0,0,,来形成新的表达式\nDialogue: 0,0:02:12.47,0:02:13.45,Default,,0,0,0,,举例来说\nDialogue: 0,0:02:13.62,0:02:15.35,Default,,0,0,0,,我们在创造世界的时候\nDialogue: 0,0:02:15.35,0:02:18.01,Default,,0,0,0,,如果用数字\nDialogue: 0,0:02:20.78,0:02:22.22,Default,,0,0,0,,来表示对象\nDialogue: 0,0:02:30.67,0:02:37.93,Default,,0,0,0,,那么(CONS X Y)\nDialogue: 0,0:02:38.04,0:02:41.07,Default,,0,0,0,,就可以表示为\nDialogue: 0,0:02:41.55,0:02:43.77,Default,,0,0,0,,2^X * 3^Y\nDialogue: 0,0:02:46.13,0:02:48.03,Default,,0,0,0,,因为这样我们还能取出它的每一部分\nDialogue: 0,0:02:49.56,0:02:50.97,Default,,0,0,0,,举例来说\nDialogue: 0,0:02:51.18,0:02:55.88,Default,,0,0,0,,(CAR X)\nDialogue: 0,0:02:56.55,0:03:05.18,Default,,0,0,0,,就是X中因数2的个数\nDialogue: 0,0:03:06.69,0:03:08.78,Default,,0,0,0,,当然(CDR X)是一样的\nDialogue: 0,0:03:10.69,0:03:15.57,Default,,0,0,0,,它就X中因数3的个数\nDialogue: 0,0:03:16.51,0:03:18.65,Default,,0,0,0,,这是个非常合理的方案\nDialogue: 0,0:03:19.10,0:03:20.11,Default,,0,0,0,,只不过就是\nDialogue: 0,0:03:20.12,0:03:22.52,Default,,0,0,0,,数字的位数\nDialogue: 0,0:03:22.83,0:03:23.98,Default,,0,0,0,,会急剧地增大\nDialogue: 0,0:03:24.32,0:03:26.55,Default,,0,0,0,,甚至比宇宙中的粒子还多\nDialogue: 0,0:03:27.95,0:03:29.88,Default,,0,0,0,,所以除了在理论中\nDialogue: 0,0:03:29.90,0:03:31.21,Default,,0,0,0,,没有实现这种方案的好办法\nDialogue: 0,0:03:33.43,0:03:34.48,Default,,0,0,0,,另一方面\nDialogue: 0,0:03:35.12,0:03:37.55,Default,,0,0,0,,也有其它的表示方式\nDialogue: 0,0:03:38.45,0:03:40.01,Default,,0,0,0,,我们把它们表示为\nDialogue: 0,0:03:40.25,0:03:42.42,Default,,0,0,0,,一些小盒子\nDialogue: 0,0:03:43.32,0:03:46.43,Default,,0,0,0,,我们把CONS结构\nDialogue: 0,0:03:46.50,0:03:48.05,Default,,0,0,0,,想象为这样的东西\nDialogue: 0,0:03:50.28,0:03:52.57,Default,,0,0,0,,它们是里面装着东西的小隔间\nDialogue: 0,0:03:53.56,0:03:55.47,Default,,0,0,0,,这些格子组成一个树\nDialogue: 0,0:03:57.21,0:03:59.97,Default,,0,0,0,,我希望半导体制造商\nDialogue: 0,0:03:59.97,0:04:02.07,Default,,0,0,0,,能够提供适配这样需求的芯片\nDialogue: 0,0:04:02.70,0:04:03.76,Default,,0,0,0,,但事实上\nDialogue: 0,0:04:03.85,0:04:05.31,Default,,0,0,0,,他们提供给我的却是\nDialogue: 0,0:04:06.20,0:04:07.96,Default,,0,0,0,,线性的内存\nDialogue: 0,0:04:09.38,0:04:13.46,Default,,0,0,0,,内存是一串小隔间\nDialogue: 0,0:04:15.12,0:04:16.34,Default,,0,0,0,,像这样的小隔间\nDialogue: 0,0:04:17.72,0:04:20.25,Default,,0,0,0,,每个小隔间里可以保存确定大小的对象\nDialogue: 0,0:04:20.94,0:04:22.20,Default,,0,0,0,,一个尺寸固定的对象\nDialogue: 0,0:04:23.39,0:04:24.07,Default,,0,0,0,,例如\nDialogue: 0,0:04:24.07,0:04:25.66,Default,,0,0,0,,一个含25个元素的表\nDialogue: 0,0:04:25.66,0:04:26.64,Default,,0,0,0,,就放不进这里\nDialogue: 0,0:04:28.55,0:04:29.26,Default,,0,0,0,,然而 它们中的每一个\nDialogue: 0,0:04:29.29,0:04:30.88,Default,,0,0,0,,都是由地址索引的\nDialogue: 0,0:04:33.97,0:04:34.99,Default,,0,0,0,,因此它们的地址可能是\nDialogue: 0,0:04:35.02,0:04:35.50,Default,,0,0,0,,这里是0\nDialogue: 0,0:04:35.50,0:04:36.22,Default,,0,0,0,,这里是1\nDialogue: 0,0:04:36.22,0:04:36.70,Default,,0,0,0,,这里是2\nDialogue: 0,0:04:36.70,0:04:37.25,Default,,0,0,0,,这里是3\nDialogue: 0,0:04:37.25,0:04:37.94,Default,,0,0,0,,以此类推\nDialogue: 0,0:04:38.06,0:04:40.40,Default,,0,0,0,,这里写的数字并不重要\nDialogue: 0,0:04:40.40,0:04:41.68,Default,,0,0,0,,重要的是 它们不重复\nDialogue: 0,0:04:41.95,0:04:43.42,Default,,0,0,0,,有了它们就能找到下一个在哪\nDialogue: 0,0:04:44.97,0:04:46.14,Default,,0,0,0,,在其中每一个小隔间里面\nDialogue: 0,0:04:46.36,0:04:49.11,Default,,0,0,0,,我们可以把东西放进去\nDialogue: 0,0:04:49.53,0:04:50.77,Default,,0,0,0,,对于没有造过计算机的我们来说\nDialogue: 0,0:04:51.02,0:04:53.66,Default,,0,0,0,,内存就是这样子的\nDialogue: 0,0:04:54.15,0:04:54.65,Default,,0,0,0,,现在\nDialogue: 0,0:04:56.69,0:04:57.53,Default,,0,0,0,,现在的问题是\nDialogue: 0,0:04:57.53,0:04:59.97,Default,,0,0,0,,如何用这样的结构\nDialogue: 0,0:05:00.42,0:05:01.72,Default,,0,0,0,,来实现这个树形结构\nDialogue: 0,0:05:03.29,0:05:04.57,Default,,0,0,0,,其实并不难\nDialogue: 0,0:05:04.57,0:05:06.35,Default,,0,0,0,,已经有大量的方案来做这个了\nDialogue: 0,0:05:06.87,0:05:08.80,Default,,0,0,0,,最重要的一个方案是\nDialogue: 0,0:05:08.80,0:05:11.18,Default,,0,0,0,,假设半导体制造商\nDialogue: 0,0:05:11.20,0:05:13.90,Default,,0,0,0,,允许我安排自己的内存\nDialogue: 0,0:05:13.98,0:05:15.77,Default,,0,0,0,,使得其中每个小隔间都足够大\nDialogue: 0,0:05:16.28,0:05:18.20,Default,,0,0,0,,能够装得下另一个的地址\nDialogue: 0,0:05:19.35,0:05:20.83,Default,,0,0,0,,我需要这么来安排\nDialogue: 0,0:05:22.05,0:05:23.45,Default,,0,0,0,,事实上它需要更大一点\nDialogue: 0,0:05:23.48,0:05:27.52,Default,,0,0,0,,因为我还要在里面存放一些信息\nDialogue: 0,0:05:27.56,0:05:30.09,Default,,0,0,0,,它标示了这里面是什么东西\nDialogue: 0,0:05:30.39,0:05:31.64,Default,,0,0,0,,我们过一会就能看到\nDialogue: 0,0:05:32.62,0:05:34.40,Default,,0,0,0,,当然 如果半导体制造商\nDialogue: 0,0:05:34.43,0:05:35.88,Default,,0,0,0,,没有这么来制造\nDialogue: 0,0:05:36.08,0:05:38.44,Default,,0,0,0,,我就需要用一些机智的方式\nDialogue: 0,0:05:38.57,0:05:41.82,Default,,0,0,0,,把它们组合起来以供使用\nDialogue: 0,0:05:43.77,0:05:47.05,Default,,0,0,0,,我们想象一下\nDialogue: 0,0:05:47.05,0:05:49.54,Default,,0,0,0,,把这个复杂的树形结构\nDialogue: 0,0:05:49.54,0:05:51.20,Default,,0,0,0,,塞进线性内存里\nDialogue: 0,0:05:51.74,0:05:54.47,Default,,0,0,0,,我们来看第一张幻灯片\nDialogue: 0,0:05:54.47,0:05:58.30,Default,,0,0,0,,可以看到一个传统的实现方案\nDialogue: 0,0:05:59.49,0:06:02.62,Default,,0,0,0,,它是把表结构放入线性内存\nDialogue: 0,0:06:03.22,0:06:05.87,Default,,0,0,0,,的标准方式\nDialogue: 0,0:06:06.27,0:06:08.32,Default,,0,0,0,,我们把这块内存\nDialogue: 0,0:06:08.88,0:06:11.12,Default,,0,0,0,,分为两部分\nDialogue: 0,0:06:12.03,0:06:13.42,Default,,0,0,0,,一个叫THE-CARS的数组\nDialogue: 0,0:06:14.45,0:06:15.88,Default,,0,0,0,,一个叫THE-CDRS的数组\nDialogue: 0,0:06:17.58,0:06:18.86,Default,,0,0,0,,无论它们是\nDialogue: 0,0:06:18.88,0:06:21.04,Default,,0,0,0,,顺序的地址或是其它的\nDialogue: 0,0:06:21.12,0:06:22.00,Default,,0,0,0,,其实并不重要\nDialogue: 0,0:06:22.87,0:06:25.20,Default,,0,0,0,,这是实现细节了\nDialogue: 0,0:06:25.80,0:06:28.40,Default,,0,0,0,,但有两个数组\nDialogue: 0,0:06:28.96,0:06:30.36,Default,,0,0,0,,线性数组是由\nDialogue: 0,0:06:30.46,0:06:32.59,Default,,0,0,0,,顺序的下标索引的\nDialogue: 0,0:06:34.84,0:06:36.85,Default,,0,0,0,,每个小格子里存的\nDialogue: 0,0:06:37.46,0:06:39.85,Default,,0,0,0,,是一个带类型的对象\nDialogue: 0,0:06:41.43,0:06:42.57,Default,,0,0,0,,这里的类型\nDialogue: 0,0:06:42.57,0:06:45.71,Default,,0,0,0,,以字母P开头\nDialogue: 0,0:06:45.71,0:06:46.57,Default,,0,0,0,,表示序对\nDialogue: 0,0:06:47.79,0:06:49.37,Default,,0,0,0,,以N开头 表示数字\nDialogue: 0,0:06:50.04,0:06:52.25,Default,,0,0,0,,E开头 表示空表\nDialogue: 0,0:06:54.81,0:06:55.83,Default,,0,0,0,,也就是表尾标志\nDialogue: 0,0:06:57.02,0:06:58.59,Default,,0,0,0,,如果我们想表示\nDialogue: 0,0:06:58.99,0:06:59.97,Default,,0,0,0,,这样一个对象\nDialogue: 0,0:07:00.01,0:07:02.16,Default,,0,0,0,,首元素为(1 2)\nDialogue: 0,0:07:02.65,0:07:04.01,Default,,0,0,0,,然后3、4分别作为\nDialogue: 0,0:07:04.01,0:07:05.50,Default,,0,0,0,,它的第二和第三个元素\nDialogue: 0,0:07:06.43,0:07:08.83,Default,,0,0,0,,这个表的第一部分也是一个表\nDialogue: 0,0:07:09.35,0:07:10.65,Default,,0,0,0,,后面接着是两个数字\nDialogue: 0,0:07:10.65,0:07:12.00,Default,,0,0,0,,分别为第二和第三部分\nDialogue: 0,0:07:12.87,0:07:14.81,Default,,0,0,0,,现在我们用盒子-指针表示法\nDialogue: 0,0:07:14.84,0:07:16.67,Default,,0,0,0,,来描绘它\nDialogue: 0,0:07:17.32,0:07:18.00,Default,,0,0,0,,你能发现\nDialogue: 0,0:07:18.00,0:07:20.04,Default,,0,0,0,,这里有三个单元\nDialogue: 0,0:07:20.25,0:07:22.01,Default,,0,0,0,,它们的CAR指针\nDialogue: 0,0:07:22.27,0:07:27.10,Default,,0,0,0,,分别指向对象(1 2)、3以及4\nDialogue: 0,0:07:28.39,0:07:29.75,Default,,0,0,0,,当然这个(1 2)\nDialogue: 0,0:07:29.75,0:07:31.32,Default,,0,0,0,,即整个结构的CAR\nDialogue: 0,0:07:31.32,0:07:32.65,Default,,0,0,0,,本身就是一个子结构\nDialogue: 0,0:07:32.88,0:07:34.75,Default,,0,0,0,,包含一个像这样的子表\nDialogue: 0,0:07:35.94,0:07:37.07,Default,,0,0,0,,我要做的是\nDialogue: 0,0:07:37.20,0:07:39.92,Default,,0,0,0,,就是按照下标\nDialogue: 0,0:07:39.95,0:07:41.46,Default,,0,0,0,,把它们放进去\nDialogue: 0,0:07:41.84,0:07:43.40,Default,,0,0,0,,像这里的1\nDialogue: 0,0:07:43.56,0:07:47.05,Default,,0,0,0,,代表了这个格子的下标\nDialogue: 0,0:07:49.85,0:07:51.47,Default,,0,0,0,,这里的指针\nDialogue: 0,0:07:52.37,0:07:54.86,Default,,0,0,0,,是对THE-CARS\nDialogue: 0,0:07:55.07,0:07:57.29,Default,,0,0,0,,和THE-CDRS里的小格子的引用\nDialogue: 0,0:07:57.40,0:07:58.67,Default,,0,0,0,,它在我的线性内存中\nDialogue: 0,0:07:58.76,0:08:00.33,Default,,0,0,0,,被标记为1的地方\nDialogue: 0,0:08:02.00,0:08:04.06,Default,,0,0,0,,如果我想把这个结构\nDialogue: 0,0:08:04.16,0:08:05.26,Default,,0,0,0,,塞进线性内存中\nDialogue: 0,0:08:05.85,0:08:07.52,Default,,0,0,0,,要做的是\nDialogue: 0,0:08:07.52,0:08:11.88,Default,,0,0,0,,把它放进格子1中\nDialogue: 0,0:08:11.95,0:08:12.66,Default,,0,0,0,,我要选取1号格子\nDialogue: 0,0:08:12.66,0:08:13.85,Default,,0,0,0,,这个就是1号格子\nDialogue: 0,0:08:14.27,0:08:16.22,Default,,0,0,0,,这是它的CAR\nDialogue: 0,0:08:16.22,0:08:17.74,Default,,0,0,0,,我要把它赋值给一个序对\nDialogue: 0,0:08:17.95,0:08:18.72,Default,,0,0,0,,这个序对\nDialogue: 0,0:08:20.02,0:08:21.55,Default,,0,0,0,,序号是5\nDialogue: 0,0:08:22.59,0:08:23.90,Default,,0,0,0,,它的CDR\nDialogue: 0,0:08:23.90,0:08:25.13,Default,,0,0,0,,就是这个\nDialogue: 0,0:08:25.39,0:08:26.13,Default,,0,0,0,,它是个序对\nDialogue: 0,0:08:26.13,0:08:27.70,Default,,0,0,0,,我会把它放到2的位置\nDialogue: 0,0:08:28.34,0:08:28.98,Default,,0,0,0,,即P2\nDialogue: 0,0:08:30.89,0:08:32.95,Default,,0,0,0,,我们看P2\nDialogue: 0,0:08:32.95,0:08:34.72,Default,,0,0,0,,P2的CAR\nDialogue: 0,0:08:34.90,0:08:37.22,Default,,0,0,0,,是数字3\nDialogue: 0,0:08:37.34,0:08:38.64,Default,,0,0,0,,如你所见N3\nDialogue: 0,0:08:39.52,0:08:41.52,Default,,0,0,0,,这里 它的CDR\nDialogue: 0,0:08:41.72,0:08:43.40,Default,,0,0,0,,是一个序对\nDialogue: 0,0:08:43.97,0:08:45.81,Default,,0,0,0,,在位置4\nDialogue: 0,0:08:46.64,0:08:47.79,Default,,0,0,0,,这就是P4\nDialogue: 0,0:08:48.65,0:08:51.16,Default,,0,0,0,,P4是一个数字\nDialogue: 0,0:08:51.85,0:08:53.87,Default,,0,0,0,,它的CAR部分是数字4\nDialogue: 0,0:08:54.60,0:08:55.65,Default,,0,0,0,,它的CDR\nDialogue: 0,0:08:55.84,0:08:58.48,Default,,0,0,0,,是个空表 就在这儿\nDialogue: 0,0:08:59.17,0:08:59.90,Default,,0,0,0,,这个表就结束了\nDialogue: 0,0:09:00.69,0:09:04.57,Default,,0,0,0,,这就是在线性内存中\nDialogue: 0,0:09:04.90,0:09:09.55,Default,,0,0,0,,表示二叉树的传统方式\nDialogue: 0,0:09:11.62,0:09:15.10,Default,,0,0,0,,那么 下一个问题是\nDialogue: 0,0:09:15.10,0:09:16.36,Default,,0,0,0,,我们需要关心\nDialogue: 0,0:09:16.60,0:09:18.19,Default,,0,0,0,,如何去实现\nDialogue: 0,0:09:18.44,0:09:20.33,Default,,0,0,0,,这意味着当我写下一个过程\nDialogue: 0,0:09:20.36,0:09:23.62,Default,,0,0,0,,用来给A赋值时\nDialogue: 0,0:09:24.54,0:09:27.10,Default,,0,0,0,,使用寄存机器的代码来编写的\nDialogue: 0,0:09:27.21,0:09:30.14,Default,,0,0,0,,(ASSIGN A (FETCH B))\nDialogue: 0,0:09:30.84,0:09:31.85,Default,,0,0,0,,我实际上想做的是\nDialogue: 0,0:09:31.97,0:09:37.10,Default,,0,0,0,,定位这些元素\nDialogue: 0,0:09:38.74,0:09:40.25,Default,,0,0,0,,那段机器代码只是\nDialogue: 0,0:09:40.68,0:09:42.94,Default,,0,0,0,,这个复杂过程的简写\nDialogue: 0,0:09:44.47,0:09:46.33,Default,,0,0,0,,当然 为了把它“写下来”\nDialogue: 0,0:09:46.35,0:09:48.59,Default,,0,0,0,,我要引入一种\nDialogue: 0,0:09:48.62,0:09:49.42,Default,,0,0,0,,称为“向量”的结构\nDialogue: 0,0:09:52.12,0:09:53.31,Default,,0,0,0,,我们得有一种东西\nDialogue: 0,0:09:53.48,0:09:54.54,Default,,0,0,0,,用来引用向量\nDialogue: 0,0:09:56.84,0:09:58.51,Default,,0,0,0,,这样我们就能把它写下来\nDialogue: 0,0:09:58.71,0:10:00.22,Default,,0,0,0,,它的参数之一是向量的名字\nDialogue: 0,0:10:01.02,0:10:03.97,Default,,0,0,0,,我觉得这个名字起得不太靠谱\nDialogue: 0,0:10:03.97,0:10:09.40,Default,,0,0,0,,它接受VECTOR和INDEX两个参数\nDialogue: 0,0:10:11.20,0:10:13.05,Default,,0,0,0,,我可以用VECTOR-SET!\nDialogue: 0,0:10:13.10,0:10:14.27,Default,,0,0,0,,来为其中的分量赋值\nDialogue: 0,0:10:14.65,0:10:15.60,Default,,0,0,0,,我不太在意\nDialogue: 0,0:10:16.28,0:10:17.55,Default,,0,0,0,,我们来看一看\nDialogue: 0,0:10:18.11,0:10:20.42,Default,,0,0,0,,在这种实现中\nDialogue: 0,0:10:21.25,0:10:23.18,Default,,0,0,0,,CAR和CDR是什么样子的\nDialogue: 0,0:10:26.47,0:10:28.41,Default,,0,0,0,,比如说 如果我刚好有\nDialogue: 0,0:10:28.88,0:10:30.80,Default,,0,0,0,,一个寄存器B\nDialogue: 0,0:10:31.15,0:10:34.64,Default,,0,0,0,,它存了一个序对的下标\nDialogue: 0,0:10:35.95,0:10:38.80,Default,,0,0,0,,即它是指向一个序对的指针\nDialogue: 0,0:10:39.35,0:10:40.85,Default,,0,0,0,,我可以取它的CAR\nDialogue: 0,0:10:41.55,0:10:44.11,Default,,0,0,0,,存到寄存器A里面\nDialogue: 0,0:10:44.49,0:10:46.86,Default,,0,0,0,,事实上它是\nDialogue: 0,0:10:47.37,0:10:50.19,Default,,0,0,0,,把A赋值为--\nDialogue: 0,0:10:50.19,0:10:51.92,Default,,0,0,0,,引用向量的一个分量--\nDialogue: 0,0:10:52.80,0:10:55.24,Default,,0,0,0,,或者你可以把它叫做索引一个数组\nDialogue: 0,0:10:55.42,0:10:57.63,Default,,0,0,0,,目标向量为THE-CARS\nDialogue: 0,0:10:58.40,0:11:00.92,Default,,0,0,0,,而目标分量是B\nDialogue: 0,0:11:02.65,0:11:03.63,Default,,0,0,0,,CDR的操作也类似\nDialogue: 0,0:11:04.10,0:11:05.72,Default,,0,0,0,,我们可以用同样的方式\nDialogue: 0,0:11:05.90,0:11:08.32,Default,,0,0,0,,来对数据结构赋值\nDialogue: 0,0:11:08.92,0:11:10.92,Default,,0,0,0,,如果我们需要这么做的话\nDialogue: 0,0:11:11.84,0:11:13.80,Default,,0,0,0,,构建这个并不太难\nDialogue: 0,0:11:14.58,0:11:15.72,Default,,0,0,0,,下一个问题是\nDialogue: 0,0:11:15.72,0:11:17.00,Default,,0,0,0,,我们如何分配它们\nDialogue: 0,0:11:18.01,0:11:20.13,Default,,0,0,0,,我们经常需要一个新的序对\nDialogue: 0,0:11:21.40,0:11:23.42,Default,,0,0,0,,当然 CONS并没有长在树上\nDialogue: 0,0:11:23.79,0:11:24.81,Default,,0,0,0,,或许它们应该那样\nDialogue: 0,0:11:25.34,0:11:26.56,Default,,0,0,0,,我必须得有某种方法\nDialogue: 0,0:11:26.70,0:11:28.97,Default,,0,0,0,,来获得一个可用的序对\nDialogue: 0,0:11:29.98,0:11:31.47,Default,,0,0,0,,我需要某种方案\nDialogue: 0,0:11:31.47,0:11:33.04,Default,,0,0,0,,当内存不再使用的时候\nDialogue: 0,0:11:33.69,0:11:35.05,Default,,0,0,0,,我可以重新分配它们\nDialogue: 0,0:11:35.63,0:11:37.38,Default,,0,0,0,,有很多方案可以实现这一点\nDialogue: 0,0:11:37.38,0:11:39.07,Default,,0,0,0,,现在我给你们展示的这个东西\nDialogue: 0,0:11:39.23,0:11:40.45,Default,,0,0,0,,并是不必要的\nDialogue: 0,0:11:42.10,0:11:43.18,Default,,0,0,0,,然而它很方便\nDialogue: 0,0:11:43.20,0:11:44.44,Default,,0,0,0,,并且被实现很多次了\nDialogue: 0,0:11:44.60,0:11:47.20,Default,,0,0,0,,其中一种基于“空闲表”的分配方案\nDialogue: 0,0:11:47.66,0:11:48.68,Default,,0,0,0,,它的意思就是\nDialogue: 0,0:11:48.68,0:11:51.12,Default,,0,0,0,,世界上所有的空闲内存\nDialogue: 0,0:11:51.55,0:11:53.08,Default,,0,0,0,,都连在一个链表中\nDialogue: 0,0:11:54.55,0:11:56.22,Default,,0,0,0,,就像其它东西一样\nDialogue: 0,0:11:56.96,0:11:59.07,Default,,0,0,0,,每当你需要一个新的格子\nDialogue: 0,0:11:59.07,0:12:00.12,Default,,0,0,0,,来进行CONS的时候\nDialogue: 0,0:12:00.95,0:12:02.26,Default,,0,0,0,,你选择第一个格子\nDialogue: 0,0:12:02.26,0:12:03.82,Default,,0,0,0,,将它的CDR指向空闲表\nDialogue: 0,0:12:04.32,0:12:05.55,Default,,0,0,0,,然后分配它\nDialogue: 0,0:12:06.03,0:12:08.32,Default,,0,0,0,,就像这样\nDialogue: 0,0:12:09.53,0:12:13.32,Default,,0,0,0,,这里 我们的空闲表\nDialogue: 0,0:12:13.95,0:12:16.81,Default,,0,0,0,,就是从6开始\nDialogue: 0,0:12:18.51,0:12:23.47,Default,,0,0,0,,它是一个指向8的指针\nDialogue: 0,0:12:24.86,0:12:25.62,Default,,0,0,0,,它表示\nDialogue: 0,0:12:25.62,0:12:26.55,Default,,0,0,0,,当前这个是空闲的\nDialogue: 0,0:12:26.55,0:12:27.95,Default,,0,0,0,,下一个在位置8\nDialogue: 0,0:12:28.87,0:12:29.88,Default,,0,0,0,,这个是空闲的\nDialogue: 0,0:12:30.04,0:12:32.08,Default,,0,0,0,,下一个在位置3\nDialogue: 0,0:12:32.32,0:12:33.45,Default,,0,0,0,,下一个是空闲的\nDialogue: 0,0:12:33.93,0:12:34.95,Default,,0,0,0,,这个是空闲的\nDialogue: 0,0:12:35.04,0:12:37.68,Default,,0,0,0,,下一个在位置0\nDialogue: 0,0:12:37.87,0:12:38.49,Default,,0,0,0,,这个是空闲的\nDialogue: 0,0:12:38.52,0:12:39.82,Default,,0,0,0,,下一个在位置15\nDialogue: 0,0:12:40.94,0:12:41.84,Default,,0,0,0,,以此类推\nDialogue: 0,0:12:42.78,0:12:44.64,Default,,0,0,0,,我们可以想象有这样的结构\nDialogue: 0,0:12:46.40,0:12:48.03,Default,,0,0,0,,一旦我们有了这样的机制\nDialogue: 0,0:12:49.45,0:12:50.92,Default,,0,0,0,,那么当你需要空间的时候\nDialogue: 0,0:12:50.92,0:12:52.22,Default,,0,0,0,,就能获取一个\nDialogue: 0,0:12:53.82,0:12:56.46,Default,,0,0,0,,那些使用了CONS的程序\nDialogue: 0,0:12:57.45,0:12:59.13,Default,,0,0,0,,内存可能就是像这样的\nDialogue: 0,0:12:59.32,0:13:02.57,Default,,0,0,0,,把B和C进行CONS之后的值\nDialogue: 0,0:13:02.95,0:13:05.82,Default,,0,0,0,,赋值给A寄存器\nDialogue: 0,0:13:06.20,0:13:09.04,Default,,0,0,0,,结果包括B和C\nDialogue: 0,0:13:09.27,0:13:10.52,Default,,0,0,0,,我们要做的是\nDialogue: 0,0:13:10.56,0:13:12.24,Default,,0,0,0,,把当前的尾部格子 即空闲表的前个格子\nDialogue: 0,0:13:12.47,0:13:14.30,Default,,0,0,0,,让它的CDR指向空闲表\nDialogue: 0,0:13:15.64,0:13:18.33,Default,,0,0,0,,我们要把THE-CARS中\nDialogue: 0,0:13:18.41,0:13:22.49,Default,,0,0,0,,由A索引的格子\nDialogue: 0,0:13:23.13,0:13:25.45,Default,,0,0,0,,修改为B中的内容\nDialogue: 0,0:13:25.90,0:13:28.65,Default,,0,0,0,,THE-CDRS中由A索引的格子\nDialogue: 0,0:13:29.20,0:13:31.72,Default,,0,0,0,,修改为C的值\nDialogue: 0,0:13:33.20,0:13:34.76,Default,,0,0,0,,现在A所指的格子里面\nDialogue: 0,0:13:34.78,0:13:36.65,Default,,0,0,0,,就是新构建好的对象了\nDialogue: 0,0:13:36.81,0:13:37.92,Default,,0,0,0,,这就是我们要的对象\nDialogue: 0,0:13:40.47,0:13:42.50,Default,,0,0,0,,我之前告诉过你们\nDialogue: 0,0:13:42.50,0:13:43.97,Default,,0,0,0,,这里撒了个谎\nDialogue: 0,0:13:43.97,0:13:45.32,Default,,0,0,0,,也就是在这里的某处\nDialogue: 0,0:13:45.53,0:13:47.32,Default,,0,0,0,,我本来应该\nDialogue: 0,0:13:48.45,0:13:50.48,Default,,0,0,0,,把我CONS起来的对象\nDialogue: 0,0:13:50.51,0:13:51.87,Default,,0,0,0,,设置为序对类型\nDialogue: 0,0:13:52.30,0:13:53.05,Default,,0,0,0,,但我没有\nDialogue: 0,0:13:53.51,0:13:56.57,Default,,0,0,0,,因此这里应该需要设置一些比特位\nDialogue: 0,0:13:56.60,0:13:57.76,Default,,0,0,0,,我只是还没把它写下来\nDialogue: 0,0:13:59.81,0:14:00.86,Default,,0,0,0,,当然 这个很好实现\nDialogue: 0,0:14:00.89,0:14:02.45,Default,,0,0,0,,因为空闲表本来就是用序对实现的\nDialogue: 0,0:14:03.10,0:14:04.88,Default,,0,0,0,,因此这是没问题的\nDialogue: 0,0:14:06.43,0:14:07.74,Default,,0,0,0,,但这也就是--\nDialogue: 0,0:14:07.82,0:14:09.92,Default,,0,0,0,,这些都是无关紧要的细节\nDialogue: 0,0:14:10.22,0:14:12.88,Default,,0,0,0,,取决于那些想要自制\nDialogue: 0,0:14:12.92,0:14:14.27,Default,,0,0,0,,计算机或Lisp系统的\nDialogue: 0,0:14:14.33,0:14:16.68,Default,,0,0,0,,程序员或架构师\nDialogue: 0,0:14:17.54,0:14:18.71,Default,,0,0,0,,例如\nDialogue: 0,0:14:19.07,0:14:20.24,Default,,0,0,0,,看这个\nDialogue: 0,0:14:20.65,0:14:23.45,Default,,0,0,0,,假设我们要为\nDialogue: 0,0:14:23.55,0:14:26.83,Default,,0,0,0,,这个之前见过的数据结构分配空间\nDialogue: 0,0:14:27.21,0:14:30.26,Default,,0,0,0,,假设我要分配一个新格子\nDialogue: 0,0:14:30.55,0:14:36.61,Default,,0,0,0,,来表示表(1 1 2)\nDialogue: 0,0:14:37.24,0:14:39.87,Default,,0,0,0,,其中(1 2)又是\nDialogue: 0,0:14:40.28,0:14:42.16,Default,,0,0,0,,之前一个表的CAR元素\nDialogue: 0,0:14:43.43,0:14:44.45,Default,,0,0,0,,这不怎么难\nDialogue: 0,0:14:44.78,0:14:46.20,Default,,0,0,0,,我用1号单元来存放数字“1”\nDialogue: 0,0:14:46.20,0:14:49.17,Default,,0,0,0,,那么P1表示的就是这个单元\nDialogue: 0,0:14:49.53,0:14:50.83,Default,,0,0,0,,这个是P5\nDialogue: 0,0:14:51.67,0:14:53.51,Default,,0,0,0,,它是应该是这个的CDR\nDialogue: 0,0:14:54.07,0:14:55.52,Default,,0,0,0,,现在我们要从空闲表中取出一些东西\nDialogue: 0,0:14:55.52,0:14:57.30,Default,,0,0,0,,空闲表现在是从6开始的\nDialogue: 0,0:14:57.78,0:15:00.18,Default,,0,0,0,,而在分配之后 空闲表将从8开始\nDialogue: 0,0:15:00.60,0:15:02.55,Default,,0,0,0,,一个从8开始的空闲表\nDialogue: 0,0:15:02.89,0:15:03.52,Default,,0,0,0,,当然\nDialogue: 0,0:15:03.72,0:15:06.04,Default,,0,0,0,,现在6里面是数字1\nDialogue: 0,0:15:06.15,0:15:07.10,Default,,0,0,0,,就是我们想要的\nDialogue: 0,0:15:07.39,0:15:11.56,Default,,0,0,0,,它的CDR是在位置5的序对\nDialogue: 0,0:15:13.33,0:15:14.50,Default,,0,0,0,,没费多少力气\nDialogue: 0,0:15:16.81,0:15:20.45,Default,,0,0,0,,这里依然存在的一个问题是\nDialogue: 0,0:15:21.00,0:15:23.40,Default,,0,0,0,,我们没有无限大的内存\nDialogue: 0,0:15:25.08,0:15:26.66,Default,,0,0,0,,如果我像这么操作了一会儿\nDialogue: 0,0:15:27.25,0:15:28.00,Default,,0,0,0,,比如说\nDialogue: 0,0:15:28.01,0:15:30.14,Default,,0,0,0,,假设进行一次CONS花费1微秒\nDialogue: 0,0:15:30.60,0:15:32.97,Default,,0,0,0,,如果要进行一百万次CONS\nDialogue: 0,0:15:33.60,0:15:35.27,Default,,0,0,0,,那么我就要消耗1秒钟的时间\nDialogue: 0,0:15:35.95,0:15:37.00,Default,,0,0,0,,这就很糟糕了\nDialogue: 0,0:15:38.00,0:15:40.62,Default,,0,0,0,,如何预防这样的灾难\nDialogue: 0,0:15:40.62,0:15:42.19,Default,,0,0,0,,这种生态灾难\nDialogue: 0,0:15:42.60,0:15:44.30,Default,,0,0,0,,在提问环节之后我们再继续讨论\nDialogue: 0,0:15:44.30,0:15:45.26,Default,,0,0,0,,有人要提问吗?\nDialogue: 0,0:15:51.50,0:15:51.69,Default,,0,0,0,,请讲\nDialogue: 0,0:15:52.03,0:15:54.67,Default,,0,0,0,,学生：在环境图表中\nDialogue: 0,0:15:54.67,0:15:58.25,Default,,0,0,0,,我们画了过程体\nDialogue: 0,0:15:58.25,0:16:00.67,Default,,0,0,0,,但是在过程应用结束后\nDialogue: 0,0:16:00.80,0:16:03.60,Default,,0,0,0,,这些环境中的东西就不再有用了\nDialogue: 0,0:16:03.60,0:16:04.16,Default,,0,0,0,,教授：说得很对\nDialogue: 0,0:16:04.93,0:16:06.67,Default,,0,0,0,,学生：它是如何表示的？\nDialogue: 0,0:16:06.76,0:16:08.75,Default,,0,0,0,,教授：这其实是两个问题\nDialogue: 0,0:16:09.18,0:16:10.25,Default,,0,0,0,,第一个问题是\nDialogue: 0,0:16:10.25,0:16:13.43,Default,,0,0,0,,材料没用了\nDialogue: 0,0:16:13.87,0:16:14.92,Default,,0,0,0,,我们稍后就会讲\nDialogue: 0,0:16:14.92,0:16:17.00,Default,,0,0,0,,如何预防生态灾难\nDialogue: 0,0:16:17.63,0:16:19.20,Default,,0,0,0,,如果我制造了一堆垃圾\nDialogue: 0,0:16:19.20,0:16:21.39,Default,,0,0,0,,我需要自己清理掉\nDialogue: 0,0:16:21.82,0:16:22.97,Default,,0,0,0,,我们一会儿就要讲\nDialogue: 0,0:16:23.43,0:16:24.57,Default,,0,0,0,,第二个问题\nDialogue: 0,0:16:24.57,0:16:27.21,Default,,0,0,0,,你问的是如何表示环境\nDialogue: 0,0:16:27.28,0:16:27.60,Default,,0,0,0,,学生：对\nDialogue: 0,0:16:27.60,0:16:28.19,Default,,0,0,0,,教授：好\nDialogue: 0,0:16:28.19,0:16:30.62,Default,,0,0,0,,环境结构能够以任意的方式表示\nDialogue: 0,0:16:30.92,0:16:31.78,Default,,0,0,0,,有很多种表示方式\nDialogue: 0,0:16:31.78,0:16:33.34,Default,,0,0,0,,这里 我只讲了基于表结构的内存\nDialogue: 0,0:16:33.63,0:16:34.92,Default,,0,0,0,,当然 每个真实的系统\nDialogue: 0,0:16:34.92,0:16:36.72,Default,,0,0,0,,都有任意长度的向量\nDialogue: 0,0:16:36.72,0:16:39.15,Default,,0,0,0,,也有固定长度的向量\nDialogue: 0,0:16:39.31,0:16:40.51,Default,,0,0,0,,它们都可以作为内存的表示方法\nDialogue: 0,0:16:41.08,0:16:44.90,Default,,0,0,0,,在一个专业的Lisp系统中\nDialogue: 0,0:16:44.90,0:16:46.99,Default,,0,0,0,,环境结构是用\nDialogue: 0,0:16:47.30,0:16:49.69,Default,,0,0,0,,向量表示的\nDialogue: 0,0:16:49.69,0:16:51.92,Default,,0,0,0,,它所包含的元素的数量\nDialogue: 0,0:16:51.92,0:16:54.60,Default,,0,0,0,,比参数的个数稍微多一点\nDialogue: 0,0:16:55.35,0:16:56.86,Default,,0,0,0,,因为你需要某种“粘合剂”\nDialogue: 0,0:16:57.40,0:17:00.74,Default,,0,0,0,,记住环境是在框架里的\nDialogue: 0,0:17:00.74,0:17:03.98,Default,,0,0,0,,框架是应用过程时被构建出来的\nDialogue: 0,0:17:03.98,0:17:04.78,Default,,0,0,0,,这种情况下\nDialogue: 0,0:17:04.80,0:17:07.60,Default,,0,0,0,,所分配的空间大小为\nDialogue: 0,0:17:07.64,0:17:11.27,Default,,0,0,0,,实际参数加上“粘合剂”占用的空间\nDialogue: 0,0:17:11.27,0:17:12.71,Default,,0,0,0,,然后将它连接到某条链上\nDialogue: 0,0:17:13.32,0:17:15.66,Default,,0,0,0,,在这个层次上 和ALGOL差不多\nDialogue: 0,0:17:19.81,0:17:20.72,Default,,0,0,0,,还有其它问题吗?\nDialogue: 0,0:17:23.70,0:17:23.92,Default,,0,0,0,,好\nDialogue: 0,0:17:23.92,0:17:25.55,Default,,0,0,0,,谢谢 我们休息一下\nDialogue: 0,0:17:26.35,0:17:45.48,Default,,0,0,0,,[音乐]\nDialogue: 0,0:17:45.53,0:17:50.01,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:17:55.74,0:17:59.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:17:59.13,0:18:04.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:18:04.32,0:18:09.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}存储分配与垃圾收集\nDialogue: 0,0:18:12.27,0:18:14.24,Default,,0,0,0,,教授：如同我刚才说过的那样\nDialogue: 0,0:18:14.55,0:18:15.50,Default,,0,0,0,,半导体厂商\nDialogue: 0,0:18:15.82,0:18:17.96,Default,,0,0,0,,所生产的计算机内存\nDialogue: 0,0:18:18.16,0:18:19.00,Default,,0,0,0,,容量是有限的\nDialogue: 0,0:18:19.42,0:18:20.40,Default,,0,0,0,,这的确很可惜\nDialogue: 0,0:18:21.62,0:18:23.35,Default,,0,0,0,,但它也可能不总是这样\nDialogue: 0,0:18:24.03,0:18:25.40,Default,,0,0,0,,简单算一下\nDialogue: 0,0:18:25.44,0:18:28.86,Default,,0,0,0,,你可以看到 如果内存的价格\nDialogue: 0,0:18:28.86,0:18:30.80,Default,,0,0,0,,继续保持当前的趋势的话\nDialogue: 0,0:18:31.22,0:18:33.68,Default,,0,0,0,,如果你执行CONS的时候也只需要1微秒\nDialogue: 0,0:18:34.42,0:18:35.90,Default,,0,0,0,,那么 首先大家知道\nDialogue: 0,0:18:35.90,0:18:37.07,Default,,0,0,0,,一年大约有\nDialogue: 0,0:18:37.10,0:18:38.86,Default,,0,0,0,,PI*10^7秒\nDialogue: 0,0:18:39.45,0:18:41.12,Default,,0,0,0,,那么就有\nDialogue: 0,0:18:41.50,0:18:42.73,Default,,0,0,0,,10^6乘以10^7\nDialogue: 0,0:18:42.73,0:18:43.94,Default,,0,0,0,,也就是10^13\nDialogue: 0,0:18:43.94,0:18:45.50,Default,,0,0,0,,那么在机器的一生中\nDialogue: 0,0:18:45.50,0:18:46.80,Default,,0,0,0,,就能有10^14个CONS\nDialogue: 0,0:18:47.52,0:18:49.40,Default,,0,0,0,,如果你的机器上\nDialogue: 0,0:18:49.68,0:18:50.57,Default,,0,0,0,,有10^14个字的内存\nDialogue: 0,0:18:51.20,0:18:52.16,Default,,0,0,0,,你就永远不会用完\nDialogue: 0,0:18:53.04,0:18:53.85,Default,,0,0,0,,这样就会……\nDialogue: 0,0:18:53.95,0:18:55.76,Default,,0,0,0,,这并不是完全没有道理\nDialogue: 0,0:18:56.31,0:18:58.46,Default,,0,0,0,,10^14次方不是个非常大的数字\nDialogue: 0,0:19:01.45,0:19:04.70,Default,,0,0,0,,我不觉得它是个很大的数字\nDialogue: 0,0:19:05.18,0:19:07.39,Default,,0,0,0,,但我喜欢在天文学领域进行比较\nDialogue: 0,0:19:07.93,0:19:11.04,Default,,0,0,0,,距离我们最近的星星\nDialogue: 0,0:19:11.10,0:19:12.45,Default,,0,0,0,,至少有10^18次方厘米远\nDialogue: 0,0:19:12.93,0:19:18.85,Default,,0,0,0,,我担心的是\nDialogue: 0,0:19:19.15,0:19:21.27,Default,,0,0,0,,至少以现在的经济状况\nDialogue: 0,0:19:21.27,0:19:23.57,Default,,0,0,0,,10^14大小的内存很贵\nDialogue: 0,0:19:24.20,0:19:26.62,Default,,0,0,0,,因此我认为我们需要\nDialogue: 0,0:19:26.81,0:19:28.51,Default,,0,0,0,,适应更小的内存\nDialogue: 0,0:19:30.02,0:19:30.59,Default,,0,0,0,,现在\nDialogue: 0,0:19:32.84,0:19:35.07,Default,,0,0,0,,广义地说 我们营造一种无限内存的假象\nDialogue: 0,0:19:35.80,0:19:37.22,Default,,0,0,0,,我们需要整理它\nDialogue: 0,0:19:37.82,0:19:39.68,Default,,0,0,0,,以便在我们需要内存的时候就能获得它\nDialogue: 0,0:19:41.92,0:19:45.55,Default,,0,0,0,,这个想法非常重要\nDialogue: 0,0:19:49.54,0:19:51.97,Default,,0,0,0,,人或者计算机只能存在有限的时间\nDialogue: 0,0:19:52.32,0:19:54.59,Default,,0,0,0,,只能看有限的东西\nDialogue: 0,0:19:55.28,0:19:57.37,Default,,0,0,0,,因此你只需要有限的东西\nDialogue: 0,0:19:58.19,0:19:59.00,Default,,0,0,0,,只要你合理地安排它们\nDialogue: 0,0:19:59.00,0:20:00.38,Default,,0,0,0,,使得不管实际有多少内存\nDialogue: 0,0:20:00.77,0:20:03.46,Default,,0,0,0,,你要求这里有多少\nDialogue: 0,0:20:03.46,0:20:04.74,Default,,0,0,0,,当你去看的时候\nDialogue: 0,0:20:04.74,0:20:06.90,Default,,0,0,0,,总有足够的东西\nDialogue: 0,0:20:06.90,0:20:08.15,Default,,0,0,0,,因此你只需要有限的数量\nDialogue: 0,0:20:08.75,0:20:09.94,Default,,0,0,0,,我们来看看\nDialogue: 0,0:20:11.63,0:20:13.32,Default,,0,0,0,,我们之前提过一个问题\nDialogue: 0,0:20:13.92,0:20:15.45,Default,,0,0,0,,在很多情况下\nDialogue: 0,0:20:15.72,0:20:17.84,Default,,0,0,0,,我们制造了大量\nDialogue: 0,0:20:17.88,0:20:19.16,Default,,0,0,0,,不需要的东西\nDialogue: 0,0:20:19.41,0:20:21.81,Default,,0,0,0,,我们可以进行回收再利用\nDialogue: 0,0:20:22.62,0:20:23.53,Default,,0,0,0,,举个例子\nDialogue: 0,0:20:24.15,0:20:25.79,Default,,0,0,0,,事实上\nDialogue: 0,0:20:25.79,0:20:28.40,Default,,0,0,0,,当我们调用一个过程的时候\nDialogue: 0,0:20:28.40,0:20:30.47,Default,,0,0,0,,都会构建环境结构\nDialogue: 0,0:20:30.47,0:20:32.56,Default,,0,0,0,,我们把它构建在一个环境框架中\nDialogue: 0,0:20:33.14,0:20:34.03,Default,,0,0,0,,这个环境框架\nDialogue: 0,0:20:34.22,0:20:36.07,Default,,0,0,0,,不用存在很长时间\nDialogue: 0,0:20:36.73,0:20:38.69,Default,,0,0,0,,只有在进行过程调用的时候\nDialogue: 0,0:20:39.42,0:20:42.60,Default,,0,0,0,,它的存在才是有用的\nDialogue: 0,0:20:42.85,0:20:45.27,Default,,0,0,0,,如果过程把另一个过程\nDialogue: 0,0:20:45.27,0:20:46.67,Default,,0,0,0,,作为返回值返回\nDialogue: 0,0:20:46.87,0:20:48.52,Default,,0,0,0,,并且这个过程是在它的内部定义的\nDialogue: 0,0:20:48.52,0:20:50.80,Default,,0,0,0,,那么外层过程的\nDialogue: 0,0:20:51.07,0:20:53.39,Default,,0,0,0,,存活时间仍然是\nDialogue: 0,0:20:53.50,0:20:56.12,Default,,0,0,0,,被返回的过程的\nDialogue: 0,0:20:57.02,0:20:57.90,Default,,0,0,0,,存活时间\nDialogue: 0,0:20:58.53,0:20:59.57,Default,,0,0,0,,最终\nDialogue: 0,0:20:59.57,0:21:00.97,Default,,0,0,0,,就会制造很多垃圾\nDialogue: 0,0:21:01.96,0:21:04.10,Default,,0,0,0,,还有其它的途径可以制造垃圾\nDialogue: 0,0:21:05.37,0:21:06.67,Default,,0,0,0,,用户也会制造垃圾\nDialogue: 0,0:21:07.24,0:21:08.07,Default,,0,0,0,,举例来说\nDialogue: 0,0:21:08.07,0:21:10.22,Default,,0,0,0,,用户制造的垃圾像是这样\nDialogue: 0,0:21:10.93,0:21:14.00,Default,,0,0,0,,如果我们写个程序\nDialogue: 0,0:21:14.00,0:21:15.80,Default,,0,0,0,,把两个表连接到一起\nDialogue: 0,0:21:16.05,0:21:18.14,Default,,0,0,0,,唯一的办法是\nDialogue: 0,0:21:18.32,0:21:21.37,Default,,0,0,0,,把第一个表逆序塞到空表中\nDialogue: 0,0:21:21.37,0:21:23.72,Default,,0,0,0,,再把新表逆序塞到第二个表中\nDialogue: 0,0:21:24.70,0:21:26.92,Default,,0,0,0,,这种解法并不是很糟糕\nDialogue: 0,0:21:28.16,0:21:28.85,Default,,0,0,0,,然而\nDialogue: 0,0:21:28.85,0:21:30.09,Default,,0,0,0,,程序所生成的\nDialogue: 0,0:21:30.11,0:21:32.02,Default,,0,0,0,,中间结果\nDialogue: 0,0:21:33.87,0:21:35.57,Default,,0,0,0,,即第一个表的逆序表\nDialogue: 0,0:21:36.70,0:21:38.52,Default,,0,0,0,,在它被复制到第二个表之后\nDialogue: 0,0:21:38.52,0:21:40.56,Default,,0,0,0,,就再也不会被用到了\nDialogue: 0,0:21:41.01,0:21:42.23,Default,,0,0,0,,它是个中间结果\nDialogue: 0,0:21:43.58,0:21:45.43,Default,,0,0,0,,它很难被找到\nDialogue: 0,0:21:46.07,0:21:48.05,Default,,0,0,0,,没有人能访问到它\nDialogue: 0,0:21:48.60,0:21:49.84,Default,,0,0,0,,事实上 它会消失掉\nDialogue: 0,0:21:51.05,0:21:52.90,Default,,0,0,0,,如果我们像这样制造了大量的垃圾\nDialogue: 0,0:21:52.90,0:21:54.20,Default,,0,0,0,,系统也应该允许我们这么干\nDialogue: 0,0:21:54.80,0:21:57.29,Default,,0,0,0,,但应该有某些方法去回收这些垃圾\nDialogue: 0,0:21:58.80,0:22:00.90,Default,,0,0,0,,现在 我要告诉你\nDialogue: 0,0:22:01.70,0:22:03.77,Default,,0,0,0,,一个非常聪明的技巧\nDialogue: 0,0:22:04.32,0:22:07.58,Default,,0,0,0,,一个Lisp系统\nDialogue: 0,0:22:07.95,0:22:11.21,Default,,0,0,0,,通常可以证明一条小定理\nDialogue: 0,0:22:11.29,0:22:13.50,Default,,0,0,0,,也就是 某段内存中的值\nDialogue: 0,0:22:14.72,0:22:16.09,Default,,0,0,0,,之后不再会被用到\nDialogue: 0,0:22:17.41,0:22:19.80,Default,,0,0,0,,它对以后的计算没有任何影响\nDialogue: 0,0:22:21.40,0:22:23.61,Default,,0,0,0,,事实上 这基于一个很简单的想法\nDialogue: 0,0:22:24.72,0:22:28.06,Default,,0,0,0,,我们已经把计算机设计成这个样子\nDialogue: 0,0:22:28.95,0:22:30.67,Default,,0,0,0,,有一些数据通路\nDialogue: 0,0:22:31.87,0:22:33.40,Default,,0,0,0,,其中有寄存器\nDialogue: 0,0:22:34.92,0:22:38.04,Default,,0,0,0,,有EXP、ENV\nDialogue: 0,0:22:39.04,0:22:42.19,Default,,0,0,0,,和VAL之类的寄存器\nDialogue: 0,0:22:42.61,0:22:44.02,Default,,0,0,0,,这里有个叫STACK的东西\nDialogue: 0,0:22:46.02,0:22:49.45,Default,,0,0,0,,某种指向一个结构的东西\nDialogue: 0,0:22:49.50,0:22:50.22,Default,,0,0,0,,它是个栈\nDialogue: 0,0:22:50.24,0:22:51.48,Default,,0,0,0,,我们过一会再研究它\nDialogue: 0,0:22:51.64,0:22:53.62,Default,,0,0,0,,这里有一些\nDialogue: 0,0:22:54.38,0:22:56.57,Default,,0,0,0,,有穷状态控制器\nDialogue: 0,0:22:56.73,0:22:59.51,Default,,0,0,0,,控制信号在这之间流通\nDialogue: 0,0:22:59.80,0:23:01.44,Default,,0,0,0,,比如谓词的返回结果\nDialogue: 0,0:23:01.87,0:23:03.13,Default,,0,0,0,,这部分并不太有趣\nDialogue: 0,0:23:03.35,0:23:06.51,Default,,0,0,0,,这里有某种结构化的内存\nDialogue: 0,0:23:06.80,0:23:08.27,Default,,0,0,0,,我刚才给你讲过如何构建它\nDialogue: 0,0:23:08.27,0:23:10.17,Default,,0,0,0,,它可能包括一个栈\nDialogue: 0,0:23:10.46,0:23:11.48,Default,,0,0,0,,我没有告诉你如何把东西\nDialogue: 0,0:23:11.48,0:23:12.43,Default,,0,0,0,,构建成任意形状\nDialogue: 0,0:23:12.56,0:23:13.39,Default,,0,0,0,,只有序对\nDialogue: 0,0:23:13.60,0:23:14.20,Default,,0,0,0,,但事实上\nDialogue: 0,0:23:14.35,0:23:15.44,Default,,0,0,0,,我告诉过你\nDialogue: 0,0:23:15.47,0:23:16.96,Default,,0,0,0,,可以用一张大表来模拟栈\nDialogue: 0,0:23:17.77,0:23:18.85,Default,,0,0,0,,我没准备干这个\nDialogue: 0,0:23:18.85,0:23:20.01,Default,,0,0,0,,这不是个好办法\nDialogue: 0,0:23:20.36,0:23:22.60,Default,,0,0,0,,但是我们可以有这样一个东西\nDialogue: 0,0:23:22.99,0:23:25.28,Default,,0,0,0,,这里有各种数据结构\nDialogue: 0,0:23:25.64,0:23:27.75,Default,,0,0,0,,它们通过有趣的方式互相连接\nDialogue: 0,0:23:30.11,0:23:32.02,Default,,0,0,0,,它们和其它东西连接到一起\nDialogue: 0,0:23:32.56,0:23:33.25,Default,,0,0,0,,以此类推\nDialogue: 0,0:23:33.25,0:23:34.22,Default,,0,0,0,,归根结底\nDialogue: 0,0:23:34.45,0:23:37.19,Default,,0,0,0,,这里的东西是指向这里的指针\nDialogue: 0,0:23:37.19,0:23:38.87,Default,,0,0,0,,寄存器里的指针\nDialogue: 0,0:23:39.40,0:23:41.40,Default,,0,0,0,,指向的是表结构内存中\nDialogue: 0,0:23:41.44,0:23:43.08,Default,,0,0,0,,数据结构\nDialogue: 0,0:23:44.91,0:23:49.80,Default,,0,0,0,,现在 我们的问题是\nDialogue: 0,0:23:51.05,0:23:52.56,Default,,0,0,0,,机器的整个意识\nDialogue: 0,0:23:52.57,0:23:53.92,Default,,0,0,0,,是在寄存器里的\nDialogue: 0,0:23:55.76,0:23:58.51,Default,,0,0,0,,如果这个机器\nDialogue: 0,0:23:58.75,0:24:01.07,Default,,0,0,0,,构建得正确的话\nDialogue: 0,0:24:01.37,0:24:03.41,Default,,0,0,0,,它无法访问表结构内存中任何的东西\nDialogue: 0,0:24:04.57,0:24:07.05,Default,,0,0,0,,除非这个表结构内存中的数据\nDialogue: 0,0:24:08.09,0:24:10.88,Default,,0,0,0,,通过一系列的数据结构\nDialogue: 0,0:24:11.64,0:24:13.06,Default,,0,0,0,,与寄存器相连接\nDialogue: 0,0:24:15.07,0:24:15.98,Default,,0,0,0,,如果它能够\nDialogue: 0,0:24:16.22,0:24:18.31,Default,,0,0,0,,被合法的数据结构选择函数访问到\nDialogue: 0,0:24:19.08,0:24:21.12,Default,,0,0,0,,通过寄存器里保存的指针能够访问它\nDialogue: 0,0:24:22.28,0:24:24.46,Default,,0,0,0,,比如说 数组引用\nDialogue: 0,0:24:24.94,0:24:27.92,Default,,0,0,0,,或者针对序对的引用--CAR或者CDR\nDialogue: 0,0:24:29.08,0:24:30.95,Default,,0,0,0,,但我不能随意访问内存中的位置\nDialogue: 0,0:24:30.95,0:24:31.95,Default,,0,0,0,,因为我找不到它\nDialogue: 0,0:24:32.74,0:24:34.90,Default,,0,0,0,,至少在我求值某条表达式的时候\nDialogue: 0,0:24:37.00,0:24:39.16,Default,,0,0,0,,我是不允许去访问那个任意名字的\nDialogue: 0,0:24:41.62,0:24:42.57,Default,,0,0,0,,如果是这样的话\nDialogue: 0,0:24:43.27,0:24:45.07,Default,,0,0,0,,就可以证明一个简单的理论\nDialogue: 0,0:24:47.16,0:24:47.69,Default,,0,0,0,,就是说\nDialogue: 0,0:24:47.90,0:24:50.52,Default,,0,0,0,,如果我从这些寄存器指向的地方开始\nDialogue: 0,0:24:51.16,0:24:52.55,Default,,0,0,0,,递归地遍历\nDialogue: 0,0:24:52.82,0:24:56.15,Default,,0,0,0,,标记选择函数所有能访问到内存\nDialogue: 0,0:24:56.90,0:24:59.40,Default,,0,0,0,,最终就能标记所有能访问的东西\nDialogue: 0,0:25:00.65,0:25:02.69,Default,,0,0,0,,任何未标记的都是垃圾\nDialogue: 0,0:25:02.69,0:25:03.75,Default,,0,0,0,,它们可以被回收\nDialogue: 0,0:25:05.56,0:25:06.20,Default,,0,0,0,,非常简单\nDialogue: 0,0:25:07.20,0:25:09.10,Default,,0,0,0,,不会影响之后的计算\nDialogue: 0,0:25:11.18,0:25:12.84,Default,,0,0,0,,我来举一个\nDialogue: 0,0:25:13.93,0:25:15.75,Default,,0,0,0,,具体的例子\nDialogue: 0,0:25:17.12,0:25:19.37,Default,,0,0,0,,在此之前 需要给我的表结构内存\nDialogue: 0,0:25:19.69,0:25:22.08,Default,,0,0,0,,添加一个叫MARK的标志位\nDialogue: 0,0:25:23.64,0:25:24.89,Default,,0,0,0,,因此 在这里\nDialogue: 0,0:25:25.37,0:25:27.28,Default,,0,0,0,,就有一个表结构内存\nDialogue: 0,0:25:29.08,0:25:30.32,Default,,0,0,0,,这块表内存中\nDialogue: 0,0:25:30.33,0:25:31.33,Default,,0,0,0,,存放了一个表数据结构\nDialogue: 0,0:25:31.33,0:25:33.95,Default,,0,0,0,,我们把这个起始位置\nDialogue: 0,0:25:35.87,0:25:36.62,Default,,0,0,0,,称为“根”\nDialogue: 0,0:25:38.59,0:25:40.12,Default,,0,0,0,,不一定只有一个根\nDialogue: 0,0:25:40.12,0:25:41.95,Default,,0,0,0,,与寄存器类似 可以有很多这种东西\nDialogue: 0,0:25:42.67,0:25:43.98,Default,,0,0,0,,但我可以巧妙地安排它们\nDialogue: 0,0:25:44.13,0:25:46.30,Default,,0,0,0,,把所有在旧寄存器里的东西\nDialogue: 0,0:25:46.30,0:25:47.77,Default,,0,0,0,,在何时的时间点\nDialogue: 0,0:25:48.28,0:25:50.46,Default,,0,0,0,,放入到这个根结构中\nDialogue: 0,0:25:50.46,0:25:51.85,Default,,0,0,0,,然后用一个指针指向它\nDialogue: 0,0:25:51.85,0:25:52.67,Default,,0,0,0,,这不是重点\nDialogue: 0,0:25:54.57,0:25:55.63,Default,,0,0,0,,思路就是\nDialogue: 0,0:25:55.64,0:25:56.65,Default,,0,0,0,,我们要不断地进行CONS\nDialogue: 0,0:25:56.67,0:25:58.01,Default,,0,0,0,,直到空闲表为空\nDialogue: 0,0:25:58.72,0:25:59.67,Default,,0,0,0,,这样就用尽了所有空间\nDialogue: 0,0:26:00.95,0:26:04.47,Default,,0,0,0,,现在我们要证明这个理论\nDialogue: 0,0:26:04.47,0:26:05.90,Default,,0,0,0,,也就是一部分的内存\nDialogue: 0,0:26:05.95,0:26:06.90,Default,,0,0,0,,已经没有用了\nDialogue: 0,0:26:07.85,0:26:09.15,Default,,0,0,0,,然后我们要回收它\nDialogue: 0,0:26:09.78,0:26:10.87,Default,,0,0,0,,构建一个新的树\nDialogue: 0,0:26:12.19,0:26:14.57,Default,,0,0,0,,这是这些垃圾的标准使用方式\nDialogue: 0,0:26:17.09,0:26:18.64,Default,,0,0,0,,那么我们要做什么呢?\nDialogue: 0,0:26:18.84,0:26:20.78,Default,,0,0,0,,从P5这个位置开始\nDialogue: 0,0:26:20.89,0:26:24.27,Default,,0,0,0,,存了一些数据结构\nDialogue: 0,0:26:25.15,0:26:26.75,Default,,0,0,0,,说错了--是从1开始\nDialogue: 0,0:26:27.27,0:26:28.51,Default,,0,0,0,,事实上\nDialogue: 0,0:26:28.89,0:26:32.20,Default,,0,0,0,,它的CAR部分存放在P5这个位置\nDialogue: 0,0:26:32.27,0:26:33.58,Default,,0,0,0,,而CDR部分存在在P2这个位置\nDialogue: 0,0:26:33.98,0:26:35.64,Default,,0,0,0,,最开始 所有的标记都是0\nDialogue: 0,0:26:36.70,0:26:39.00,Default,,0,0,0,,我们要开始标记了\nDialogue: 0,0:26:39.92,0:26:40.52,Default,,0,0,0,,好\nDialogue: 0,0:26:42.54,0:26:44.27,Default,,0,0,0,,例如\nDialogue: 0,0:26:44.47,0:26:46.95,Default,,0,0,0,,因为我可以从根访问到位置P1\nDialogue: 0,0:26:46.95,0:26:47.82,Default,,0,0,0,,我就标记一下\nDialogue: 0,0:26:48.39,0:26:49.17,Default,,0,0,0,,我来标一下\nDialogue: 0,0:26:50.96,0:26:51.45,Default,,0,0,0,,好了\nDialogue: 0,0:26:52.22,0:26:52.94,Default,,0,0,0,,这个被标记了\nDialogue: 0,0:26:54.41,0:26:57.51,Default,,0,0,0,,因为它指向位置P5\nDialogue: 0,0:26:57.64,0:26:58.64,Default,,0,0,0,,所以我来到了5号格子\nDialogue: 0,0:26:59.02,0:27:00.72,Default,,0,0,0,,然后 我要标记这个\nDialogue: 0,0:27:01.45,0:27:01.76,Default,,0,0,0,,标好了\nDialogue: 0,0:27:01.76,0:27:02.60,Default,,0,0,0,,这个笔真好用\nDialogue: 0,0:27:02.90,0:27:05.10,Default,,0,0,0,,但是5号位置的CAR部分是一个数字\nDialogue: 0,0:27:05.27,0:27:06.65,Default,,0,0,0,,我对标记数字不感兴趣\nDialogue: 0,0:27:06.91,0:27:08.17,Default,,0,0,0,,但它的CDR部分是P7\nDialogue: 0,0:27:08.70,0:27:09.75,Default,,0,0,0,,所以我可以标记它\nDialogue: 0,0:27:10.45,0:27:10.81,Default,,0,0,0,,又标好了\nDialogue: 0,0:27:11.80,0:27:13.40,Default,,0,0,0,,P7的CDR部分是空表\nDialogue: 0,0:27:13.67,0:27:15.10,Default,,0,0,0,,而它唯一所引用的元素则是\nDialogue: 0,0:27:15.59,0:27:17.12,Default,,0,0,0,,它的CAR部分是个数字\nDialogue: 0,0:27:17.12,0:27:17.85,Default,,0,0,0,,我对它不感兴趣\nDialogue: 0,0:27:19.49,0:27:20.50,Default,,0,0,0,,让我们回到这里\nDialogue: 0,0:27:20.50,0:27:21.65,Default,,0,0,0,,我忘记了一些事情\nDialogue: 0,0:27:21.65,0:27:22.17,Default,,0,0,0,,P2\nDialogue: 0,0:27:22.84,0:27:24.85,Default,,0,0,0,,换句话说 如果我看1号格子\nDialogue: 0,0:27:25.42,0:27:29.45,Default,,0,0,0,,1号格子的CDR部分指向P2\nDialogue: 0,0:27:30.37,0:27:31.30,Default,,0,0,0,,一个指向P2的引用\nDialogue: 0,0:27:32.01,0:27:34.97,Default,,0,0,0,,这意味着我应该标记P2\nDialogue: 0,0:27:35.70,0:27:36.27,Default,,0,0,0,,好了\nDialogue: 0,0:27:37.14,0:27:38.89,Default,,0,0,0,,P2包含了了一个到P4的引用\nDialogue: 0,0:27:39.13,0:27:40.27,Default,,0,0,0,,而P2的CAR部分是个数字\nDialogue: 0,0:27:40.27,0:27:41.20,Default,,0,0,0,,我对它不感兴趣\nDialogue: 0,0:27:41.47,0:27:42.60,Default,,0,0,0,,所以我要标记P4\nDialogue: 0,0:27:43.78,0:27:46.10,Default,,0,0,0,,P4的CAR部分引用了P7\nDialogue: 0,0:27:46.75,0:27:48.17,Default,,0,0,0,,它的CDR是空的\nDialogue: 0,0:27:48.47,0:27:49.57,Default,,0,0,0,,但由于我已经标记过P7了\nDialogue: 0,0:27:49.57,0:27:50.75,Default,,0,0,0,,就不再次标记它了\nDialogue: 0,0:27:51.40,0:27:53.05,Default,,0,0,0,,这就是这个地方\nDialogue: 0,0:27:53.07,0:27:53.87,Default,,0,0,0,,所能访问的所有单元\nDialogue: 0,0:27:55.00,0:27:56.57,Default,,0,0,0,,很简单的递归标记算法\nDialogue: 0,0:27:58.71,0:28:01.79,Default,,0,0,0,,这个算法有一些不足的地方\nDialogue: 0,0:28:01.90,0:28:04.02,Default,,0,0,0,,我们稍后会说\nDialogue: 0,0:28:04.92,0:28:06.16,Default,,0,0,0,,但基本上你能看到\nDialogue: 0,0:28:06.19,0:28:07.85,Default,,0,0,0,,所有没被标记的地方\nDialogue: 0,0:28:09.62,0:28:11.50,Default,,0,0,0,,都是无用的\nDialogue: 0,0:28:11.50,0:28:12.41,Default,,0,0,0,,可以回收\nDialogue: 0,0:28:14.25,0:28:15.75,Default,,0,0,0,,所以下一步就是\nDialogue: 0,0:28:15.75,0:28:17.05,Default,,0,0,0,,扫描整个内存\nDialogue: 0,0:28:17.94,0:28:20.35,Default,,0,0,0,,寻找未被标记的格子\nDialogue: 0,0:28:21.18,0:28:22.45,Default,,0,0,0,,每当遇到一个已标记的格子\nDialogue: 0,0:28:22.45,0:28:23.22,Default,,0,0,0,,就把标记去掉\nDialogue: 0,0:28:23.22,0:28:24.86,Default,,0,0,0,,每当遇到未标记的格子时\nDialogue: 0,0:28:25.07,0:28:27.82,Default,,0,0,0,,我就把它连接到我的空闲表中\nDialogue: 0,0:28:28.77,0:28:30.30,Default,,0,0,0,,传统而且非常简单的算法\nDialogue: 0,0:28:32.12,0:28:33.10,Default,,0,0,0,,我们来看看\nDialogue: 0,0:28:33.84,0:28:34.77,Default,,0,0,0,,它很简单吗?\nDialogue: 0,0:28:34.77,0:28:35.42,Default,,0,0,0,,是的\nDialogue: 0,0:28:35.57,0:28:37.79,Default,,0,0,0,,我不会深入代码细节\nDialogue: 0,0:28:38.00,0:28:39.65,Default,,0,0,0,,只是想给你看看它有多长\nDialogue: 0,0:28:40.09,0:28:41.10,Default,,0,0,0,,看这个标记阶段\nDialogue: 0,0:28:41.72,0:28:43.98,Default,,0,0,0,,这是标记阶段的第一部分\nDialogue: 0,0:28:45.06,0:28:46.00,Default,,0,0,0,,我们找到根\nDialogue: 0,0:28:46.32,0:28:47.52,Default,,0,0,0,,我们要\nDialogue: 0,0:28:47.67,0:28:51.05,Default,,0,0,0,,对它进行递归过程调用\nDialogue: 0,0:28:52.38,0:28:54.47,Default,,0,0,0,,当我们完成标记之后\nDialogue: 0,0:28:54.77,0:28:56.95,Default,,0,0,0,,就从这里开始清除\nDialogue: 0,0:28:57.38,0:28:59.79,Default,,0,0,0,,然后我们将执行一些指令\nDialogue: 0,0:28:59.80,0:29:01.36,Default,,0,0,0,,来检查这些标记\nDialogue: 0,0:29:01.39,0:29:03.07,Default,,0,0,0,,或者更改这些标记\nDialogue: 0,0:29:03.07,0:29:04.90,Default,,0,0,0,,按照我刚才讲的那个算法进行\nDialogue: 0,0:29:05.23,0:29:06.47,Default,,0,0,0,,代码在这里\nDialogue: 0,0:29:06.47,0:29:07.65,Default,,0,0,0,,你需要标记它们的CAR\nDialogue: 0,0:29:07.87,0:29:10.21,Default,,0,0,0,,也需要标记它们的CDR\nDialogue: 0,0:29:10.66,0:29:12.10,Default,,0,0,0,,这就是整个标记阶段\nDialogue: 0,0:29:14.37,0:29:16.16,Default,,0,0,0,,我给你讲个关于它的小故事\nDialogue: 0,0:29:16.59,0:29:19.37,Default,,0,0,0,,古董货DEC PDP-6计算机\nDialogue: 0,0:29:20.93,0:29:22.09,Default,,0,0,0,,它上面的\nDialogue: 0,0:29:22.35,0:29:24.85,Default,,0,0,0,,标记-清除垃圾回收系统就是这么写的\nDialogue: 0,0:29:26.91,0:29:28.40,Default,,0,0,0,,程序很短\nDialogue: 0,0:29:29.25,0:29:31.60,Default,,0,0,0,,以至于它需要的数据\nDialogue: 0,0:29:32.20,0:29:34.87,Default,,0,0,0,,以及用来操作内存的所需的寄存器\nDialogue: 0,0:29:36.16,0:29:38.14,Default,,0,0,0,,都能够放入到计算机的\nDialogue: 0,0:29:38.16,0:29:38.97,Default,,0,0,0,,16个快速寄存器中\nDialogue: 0,0:29:39.28,0:29:39.80,Default,,0,0,0,,整个程序\nDialogue: 0,0:29:40.01,0:29:42.01,Default,,0,0,0,,你可以在快速寄存器里执行指令\nDialogue: 0,0:29:43.17,0:29:44.83,Default,,0,0,0,,所以这是个非常小的程序\nDialogue: 0,0:29:45.85,0:29:46.88,Default,,0,0,0,,它跑得飞快\nDialogue: 0,0:29:48.87,0:29:51.30,Default,,0,0,0,,然而很不幸\nDialogue: 0,0:29:51.61,0:29:54.02,Default,,0,0,0,,因为这个程序是递归的\nDialogue: 0,0:29:54.80,0:29:57.55,Default,,0,0,0,,因为你需要先做某件事儿\nDialogue: 0,0:29:57.55,0:29:58.99,Default,,0,0,0,,然后再去做另外一件事儿\nDialogue: 0,0:29:59.21,0:30:00.88,Default,,0,0,0,,你得先处理CAR 再处理CDR\nDialogue: 0,0:30:01.15,0:30:02.75,Default,,0,0,0,,这就需要辅助内存\nDialogue: 0,0:30:03.41,0:30:05.23,Default,,0,0,0,,所以Lisp系统\nDialogue: 0,0:30:05.44,0:30:07.42,Default,,0,0,0,,需要一个栈来进行标记\nDialogue: 0,0:30:08.26,0:30:11.05,Default,,0,0,0,,Lisp系统通过这样的方式\nDialogue: 0,0:30:11.57,0:30:14.16,Default,,0,0,0,,限制了你在数据结构上\nDialogue: 0,0:30:14.42,0:30:17.37,Default,,0,0,0,,进行CAR或者CDR递归的深度\nDialogue: 0,0:30:17.81,0:30:19.35,Default,,0,0,0,,这并不太靠谱\nDialogue: 0,0:30:19.93,0:30:20.60,Default,,0,0,0,,另外一方面\nDialogue: 0,0:30:20.64,0:30:22.12,Default,,0,0,0,,当它足够大的时候你不会发现\nDialogue: 0,0:30:23.18,0:30:25.13,Default,,0,0,0,,例如 这样的情况\nDialogue: 0,0:30:25.55,0:30:28.17,Default,,0,0,0,,发生在大多数MacLisp系统上\nDialogue: 0,0:30:28.69,0:30:29.88,Default,,0,0,0,,在它上面运行的Macsyma\nDialogue: 0,0:30:29.96,0:30:31.10,Default,,0,0,0,,允许你处理\nDialogue: 0,0:30:31.10,0:30:32.72,Default,,0,0,0,,有成千上万个元素的表达式\nDialogue: 0,0:30:33.56,0:30:36.02,Default,,0,0,0,,有很多代数式有大量的项\nDialogue: 0,0:30:36.82,0:30:38.10,Default,,0,0,0,,这没什么问题\nDialogue: 0,0:30:39.49,0:30:40.82,Default,,0,0,0,,垃圾回收器能正常工作\nDialogue: 0,0:30:42.19,0:30:42.92,Default,,0,0,0,,另一方面\nDialogue: 0,0:30:42.92,0:30:45.37,Default,,0,0,0,,这个算法有个很精妙的修改版\nDialogue: 0,0:30:45.37,0:30:46.47,Default,,0,0,0,,但我不会去讲\nDialogue: 0,0:30:46.80,0:30:48.22,Default,,0,0,0,,它是由Peter Deutsch\nDialogue: 0,0:30:48.64,0:30:51.82,Default,,0,0,0,,来自IBM的Herb Schorr\nDialogue: 0,0:30:51.87,0:30:53.52,Default,,0,0,0,,和我不太认识的Waite所提出\nDialogue: 0,0:30:54.01,0:30:56.51,Default,,0,0,0,,这个算法\nDialogue: 0,0:30:56.67,0:30:57.79,Default,,0,0,0,,可以不使用\nDialogue: 0,0:30:57.84,0:30:59.55,Default,,0,0,0,,额外的辅助内存\nDialogue: 0,0:31:00.50,0:31:02.80,Default,,0,0,0,,只需要在遍历整个数据结构的时候\nDialogue: 0,0:31:02.97,0:31:05.52,Default,,0,0,0,,记住你是从哪里来的并反转指针\nDialogue: 0,0:31:05.52,0:31:07.52,Default,,0,0,0,,回溯的时候 再去反转这个指针\nDialogue: 0,0:31:07.79,0:31:08.99,Default,,0,0,0,,这是个很取巧的算法\nDialogue: 0,0:31:09.13,0:31:10.24,Default,,0,0,0,,你第一次写它的时候\nDialogue: 0,0:31:10.25,0:31:11.71,Default,,0,0,0,,事实上 你前三次写它的时候\nDialogue: 0,0:31:11.71,0:31:12.72,Default,,0,0,0,,都会遇到严重的BUG\nDialogue: 0,0:31:14.35,0:31:16.72,Default,,0,0,0,,也可能奇慢无比\nDialogue: 0,0:31:16.72,0:31:17.67,Default,,0,0,0,,因为这个算法太复杂了\nDialogue: 0,0:31:18.11,0:31:20.30,Default,,0,0,0,,它用了大概六倍的内存引用\nDialogue: 0,0:31:20.85,0:31:23.22,Default,,0,0,0,,来完成我们刚才讨论的任务\nDialogue: 0,0:31:24.58,0:31:27.07,Default,,0,0,0,,一旦我完成了标记阶段\nDialogue: 0,0:31:27.50,0:31:30.12,Default,,0,0,0,,我们就面临着这样的状况\nDialogue: 0,0:31:30.17,0:31:31.26,Default,,0,0,0,,请看\nDialogue: 0,0:31:31.51,0:31:34.03,Default,,0,0,0,,这里完成了标记工作\nDialogue: 0,0:31:34.08,0:31:35.00,Default,,0,0,0,,和我刚才描述的一样\nDialogue: 0,0:31:35.59,0:31:37.33,Default,,0,0,0,,现在我们要进行清除阶段\nDialogue: 0,0:31:37.60,0:31:39.32,Default,,0,0,0,,我刚才已经讲过如何清除了\nDialogue: 0,0:31:39.82,0:31:42.34,Default,,0,0,0,,我要从内存的一端开始\nDialogue: 0,0:31:42.34,0:31:43.34,Default,,0,0,0,,哪一端都可以\nDialogue: 0,0:31:43.62,0:31:46.17,Default,,0,0,0,,扫描内存中的每个格子\nDialogue: 0,0:31:47.17,0:31:48.67,Default,,0,0,0,,在扫描的同时\nDialogue: 0,0:31:49.20,0:31:50.97,Default,,0,0,0,,如果是空闲内存\nDialogue: 0,0:31:50.99,0:31:52.84,Default,,0,0,0,,就把它们连接到空闲表中\nDialogue: 0,0:31:53.15,0:31:54.05,Default,,0,0,0,,如果它们不是空闲内存\nDialogue: 0,0:31:54.05,0:31:56.07,Default,,0,0,0,,我就把它们的标记清除掉\nDialogue: 0,0:31:57.50,0:31:58.57,Default,,0,0,0,,事实上\nDialogue: 0,0:31:58.70,0:32:00.46,Default,,0,0,0,,最终的程序并不很复杂\nDialogue: 0,0:32:00.46,0:32:02.22,Default,,0,0,0,,它只是变长了一些\nDialogue: 0,0:32:02.78,0:32:04.17,Default,,0,0,0,,这是第一部分\nDialogue: 0,0:32:04.82,0:32:06.71,Default,,0,0,0,,它从内存的顶端向下遍历\nDialogue: 0,0:32:06.71,0:32:09.58,Default,,0,0,0,,我不期望你现在就搞懂它\nDialogue: 0,0:32:09.58,0:32:10.55,Default,,0,0,0,,它挺简单的\nDialogue: 0,0:32:11.03,0:32:12.52,Default,,0,0,0,,这是个非常简单的算法\nDialogue: 0,0:32:13.07,0:32:15.97,Default,,0,0,0,,其中的一段代码像是这样\nDialogue: 0,0:32:15.97,0:32:17.37,Default,,0,0,0,,非常显而易见\nDialogue: 0,0:32:18.60,0:32:20.08,Default,,0,0,0,,在清理结束后\nDialogue: 0,0:32:20.30,0:32:21.77,Default,,0,0,0,,我们就得到了像这样的结果\nDialogue: 0,0:32:25.33,0:32:26.54,Default,,0,0,0,,这种标记-清除算法\nDialogue: 0,0:32:26.56,0:32:28.20,Default,,0,0,0,,有一些缺点\nDialogue: 0,0:32:29.59,0:32:30.35,Default,,0,0,0,,最严重的一个是\nDialogue: 0,0:32:31.45,0:32:33.20,Default,,0,0,0,,最严重的缺点是\nDialogue: 0,0:32:33.20,0:32:34.97,Default,,0,0,0,,当你的内存越来越大\nDialogue: 0,0:32:36.82,0:32:38.87,Default,,0,0,0,,地址空间也就会越来越大\nDialogue: 0,0:32:38.87,0:32:40.80,Default,,0,0,0,,你想用它存更多东西\nDialogue: 0,0:32:41.37,0:32:44.52,Default,,0,0,0,,那么扫描整个内存就会非常耗时\nDialogue: 0,0:32:46.36,0:32:47.39,Default,,0,0,0,,你真正想做的是\nDialogue: 0,0:32:47.40,0:32:48.68,Default,,0,0,0,,只扫描有用的东西\nDialogue: 0,0:32:50.49,0:32:51.55,Default,,0,0,0,,这样就会好一点\nDialogue: 0,0:32:52.07,0:32:53.90,Default,,0,0,0,,如果你意识到\nDialogue: 0,0:32:54.48,0:32:57.72,Default,,0,0,0,,哪些东西已知是有用的\nDialogue: 0,0:32:58.28,0:33:00.37,Default,,0,0,0,,你就没必要去多次检查它\nDialogue: 0,0:33:00.37,0:33:01.20,Default,,0,0,0,,或者不用经常去检查它\nDialogue: 0,0:33:01.55,0:33:04.32,Default,,0,0,0,,对于那些你不太确定的\nDialogue: 0,0:33:05.00,0:33:06.22,Default,,0,0,0,,你可以在每次需要的时候\nDialogue: 0,0:33:07.10,0:33:08.75,Default,,0,0,0,,进行仔细检查\nDialogue: 0,0:33:09.93,0:33:10.85,Default,,0,0,0,,也就是垃圾收集的时候\nDialogue: 0,0:33:11.91,0:33:13.74,Default,,0,0,0,,这些算法\nDialogue: 0,0:33:13.76,0:33:15.10,Default,,0,0,0,,就是用了这样的方法\nDialogue: 0,0:33:15.66,0:33:18.16,Default,,0,0,0,,我要介绍一个著名的古老算法\nDialogue: 0,0:33:18.28,0:33:19.47,Default,,0,0,0,,这种算法允许你\nDialogue: 0,0:33:19.50,0:33:21.37,Default,,0,0,0,,只检查内存中已知是有用的部分\nDialogue: 0,0:33:23.12,0:33:23.85,Default,,0,0,0,,这让它成为了\nDialogue: 0,0:33:23.87,0:33:25.29,Default,,0,0,0,,目前已知最快的垃圾收集算法\nDialogue: 0,0:33:26.31,0:33:29.45,Default,,0,0,0,,它就是 Minsky-Fenichel-Yochelson 垃圾收集算法\nDialogue: 0,0:33:30.40,0:33:33.18,Default,,0,0,0,,它是由Minsky\nDialogue: 0,0:33:33.20,0:33:36.06,Default,,0,0,0,,在1960、61年左右发明的\nDialogue: 0,0:33:36.52,0:33:40.48,Default,,0,0,0,,当时是给RLE PDP-1 Lisp用的\nDialogue: 0,0:33:40.51,0:33:43.44,Default,,0,0,0,,这个机器只有4096个字的线性内存\nDialogue: 0,0:33:45.79,0:33:46.76,Default,,0,0,0,,还有个磁鼓\nDialogue: 0,0:33:48.48,0:33:49.39,Default,,0,0,0,,为了能够\nDialogue: 0,0:33:50.03,0:33:51.87,Default,,0,0,0,,在这种恶劣的条件下进行垃圾收集\nDialogue: 0,0:33:53.05,0:33:54.35,Default,,0,0,0,,Minsky意识到\nDialogue: 0,0:33:54.38,0:33:55.62,Default,,0,0,0,,达成目的最容易的方法是\nDialogue: 0,0:33:56.20,0:33:58.47,Default,,0,0,0,,在扫描内存的同时\nDialogue: 0,0:33:58.47,0:34:00.60,Default,,0,0,0,,遍历那些好的数据结构\nDialogue: 0,0:34:01.57,0:34:03.52,Default,,0,0,0,,把它复制到磁鼓中\nDialogue: 0,0:34:04.70,0:34:05.47,Default,,0,0,0,,压缩一下\nDialogue: 0,0:34:06.35,0:34:08.86,Default,,0,0,0,,之后把它们复制出来\nDialogue: 0,0:34:09.12,0:34:10.90,Default,,0,0,0,,并把它们交换回内存里\nDialogue: 0,0:34:12.30,0:34:13.68,Default,,0,0,0,,不管是使用的是磁鼓\nDialogue: 0,0:34:13.72,0:34:14.71,Default,,0,0,0,,或者其它的内存\nDialogue: 0,0:34:14.71,0:34:16.42,Default,,0,0,0,,这都不重要\nDialogue: 0,0:34:17.03,0:34:17.42,Default,,0,0,0,,事实上\nDialogue: 0,0:34:17.44,0:34:19.60,Default,,0,0,0,,我觉得现在应该没人用磁鼓了吧\nDialogue: 0,0:34:20.35,0:34:23.77,Default,,0,0,0,,但这个算法基本上\nDialogue: 0,0:34:24.03,0:34:25.42,Default,,0,0,0,,要依赖于\nDialogue: 0,0:34:25.42,0:34:27.42,Default,,0,0,0,,大约两倍于\nDialogue: 0,0:34:27.48,0:34:28.57,Default,,0,0,0,,你实际使用的内存\nDialogue: 0,0:34:30.27,0:34:32.96,Default,,0,0,0,,最开始的情况是\nDialogue: 0,0:34:33.12,0:34:36.60,Default,,0,0,0,,有用的数据和垃圾混在了一起\nDialogue: 0,0:34:37.11,0:34:38.97,Default,,0,0,0,,它被称为FROMSPACE\nDialogue: 0,0:34:45.17,0:34:47.05,Default,,0,0,0,,这是CRUD的混合\nDialogue: 0,0:34:47.87,0:34:49.79,Default,,0,0,0,,有些是有用的 有些没有用\nDialogue: 0,0:34:52.00,0:34:53.85,Default,,0,0,0,,现在还有另外一块空间\nDialogue: 0,0:34:54.17,0:34:55.61,Default,,0,0,0,,它需要足够大\nDialogue: 0,0:34:55.77,0:34:57.00,Default,,0,0,0,,这个地方叫TOSPACE\nDialogue: 0,0:34:57.12,0:34:58.24,Default,,0,0,0,,要把东西复制进去\nDialogue: 0,0:35:01.59,0:35:02.60,Default,,0,0,0,,接下来会发生的是\nDialogue: 0,0:35:02.60,0:35:04.06,Default,,0,0,0,,我不会深入细节\nDialogue: 0,0:35:04.16,0:35:07.07,Default,,0,0,0,,书上写得很清楚了\nDialogue: 0,0:35:07.59,0:35:10.40,Default,,0,0,0,,这里有一个根节点\nDialogue: 0,0:35:11.03,0:35:14.30,Default,,0,0,0,,你从根节点开始\nDialogue: 0,0:35:14.60,0:35:16.42,Default,,0,0,0,,复制你看到的第一个东西\nDialogue: 0,0:35:17.83,0:35:19.37,Default,,0,0,0,,根指针指向的第一个东西\nDialogue: 0,0:35:19.75,0:35:21.31,Default,,0,0,0,,复制到TOSPACE的头部\nDialogue: 0,0:35:22.81,0:35:24.12,Default,,0,0,0,,这些东西一般是一个序对\nDialogue: 0,0:35:24.16,0:35:25.60,Default,,0,0,0,,或者是类似的数据结构\nDialogue: 0,0:35:27.56,0:35:30.19,Default,,0,0,0,,然后在那里留下\nDialogue: 0,0:35:30.38,0:35:31.56,Default,,0,0,0,,一颗“破碎的心”\nDialogue: 0,0:35:31.77,0:35:35.74,Default,,0,0,0,,表示我把东西从这里移动到了这里\nDialogue: 0,0:35:35.74,0:35:37.05,Default,,0,0,0,,指示了移动的目的地\nDialogue: 0,0:35:37.80,0:35:39.65,Default,,0,0,0,,叫作破碎的心是因为\nDialogue: 0,0:35:39.65,0:35:40.78,Default,,0,0,0,,我的一个朋友\nDialogue: 0,0:35:40.78,0:35:43.39,Default,,0,0,0,,在1966年实现了这个算法\nDialogue: 0,0:35:43.82,0:35:45.26,Default,,0,0,0,,而他是个文艺青年\nDialogue: 0,0:35:45.26,0:35:46.76,Default,,0,0,0,,就取名叫“破碎的心”\nDialogue: 0,0:35:49.58,0:35:50.54,Default,,0,0,0,,不论如何\nDialogue: 0,0:35:51.15,0:35:52.72,Default,,0,0,0,,接下来要做的是\nDialogue: 0,0:35:52.94,0:35:55.00,Default,,0,0,0,,FREE指针现在指向这里\nDialogue: 0,0:35:55.17,0:35:56.38,Default,,0,0,0,,然后开始扫描\nDialogue: 0,0:35:56.88,0:35:59.68,Default,,0,0,0,,扫描这个刚复制过来的数据结构\nDialogue: 0,0:36:00.55,0:36:02.19,Default,,0,0,0,,每当你遇到其中的指针\nDialogue: 0,0:36:02.19,0:36:03.92,Default,,0,0,0,,你把它当作是这里的根指针\nDialogue: 0,0:36:04.00,0:36:04.59,Default,,0,0,0,,哦 不好意思\nDialogue: 0,0:36:04.60,0:36:05.69,Default,,0,0,0,,我们还需要做的是\nDialogue: 0,0:36:05.71,0:36:07.08,Default,,0,0,0,,你将根指针移动到这里\nDialogue: 0,0:36:09.22,0:36:10.17,Default,,0,0,0,,因此在扫描的过程中\nDialogue: 0,0:36:10.17,0:36:10.99,Default,,0,0,0,,把遇到的每个指针\nDialogue: 0,0:36:11.00,0:36:12.41,Default,,0,0,0,,都可以当作是ROOT指针\nDialogue: 0,0:36:14.11,0:36:15.45,Default,,0,0,0,,如果你遇到了某个指针\nDialogue: 0,0:36:15.45,0:36:17.40,Default,,0,0,0,,指向了这里的某个地方\nDialogue: 0,0:36:18.51,0:36:19.92,Default,,0,0,0,,它指向的东西\nDialogue: 0,0:36:19.93,0:36:20.99,Default,,0,0,0,,你复制过了吗？\nDialogue: 0,0:36:21.78,0:36:22.87,Default,,0,0,0,,这里是“破碎的心”吗\nDialogue: 0,0:36:23.88,0:36:24.84,Default,,0,0,0,,如果那里是破碎的心\nDialogue: 0,0:36:24.84,0:36:26.11,Default,,0,0,0,,就说明那里的东西复制过了\nDialogue: 0,0:36:26.20,0:36:27.34,Default,,0,0,0,,只需要用破碎的心所指向的地址\nDialogue: 0,0:36:27.36,0:36:28.75,Default,,0,0,0,,来替换它指针即可\nDialogue: 0,0:36:29.82,0:36:32.03,Default,,0,0,0,,如果它还没被复制\nDialogue: 0,0:36:32.12,0:36:34.08,Default,,0,0,0,,你把它复制到这里\nDialogue: 0,0:36:34.43,0:36:35.95,Default,,0,0,0,,把FREE指针移到这里\nDialogue: 0,0:36:37.05,0:36:40.60,Default,,0,0,0,,然后在那里放置一颗破碎的心\nDialogue: 0,0:36:41.05,0:36:41.80,Default,,0,0,0,,继续扫描\nDialogue: 0,0:36:43.67,0:36:46.40,Default,,0,0,0,,最终SCAN指针追上了FREE指针\nDialogue: 0,0:36:46.82,0:36:48.52,Default,,0,0,0,,内存里的所有东西都被复制了\nDialogue: 0,0:36:50.14,0:36:51.04,Default,,0,0,0,,这样这里就剩下了\nDialogue: 0,0:36:51.05,0:36:51.95,Default,,0,0,0,,大量的空闲空间\nDialogue: 0,0:36:51.96,0:36:53.28,Default,,0,0,0,,如果你需要的话\nDialogue: 0,0:36:53.31,0:36:54.47,Default,,0,0,0,,你可以把它组织为空闲表\nDialogue: 0,0:36:54.47,0:36:56.27,Default,,0,0,0,,但这种系统通常不这么来做\nDialogue: 0,0:36:56.27,0:36:59.15,Default,,0,0,0,,这类系统中 内存是顺序分配的\nDialogue: 0,0:37:00.91,0:37:02.48,Default,,0,0,0,,这是个非常 非常好的算法\nDialogue: 0,0:37:02.97,0:37:04.57,Default,,0,0,0,,你们现在使用的Scheme系统中\nDialogue: 0,0:37:04.67,0:37:05.97,Default,,0,0,0,,就使用了这种算法\nDialogue: 0,0:37:06.79,0:37:09.47,Default,,0,0,0,,它应该是--\nDialogue: 0,0:37:09.47,0:37:10.86,Default,,0,0,0,,我相信还没有人发现\nDialogue: 0,0:37:10.89,0:37:12.12,Default,,0,0,0,,比它跑得更快的算法\nDialogue: 0,0:37:12.40,0:37:14.85,Default,,0,0,0,,有一些对这个算法的简单修改\nDialogue: 0,0:37:14.85,0:37:16.77,Default,,0,0,0,,由Henry Baker发明\nDialogue: 0,0:37:17.17,0:37:20.31,Default,,0,0,0,,它让你能实时运行这个算法\nDialogue: 0,0:37:20.31,0:37:21.92,Default,,0,0,0,,也就是说进行回收时不需要暂停程序\nDialogue: 0,0:37:22.14,0:37:24.33,Default,,0,0,0,,你能够让机器运行时\nDialogue: 0,0:37:24.36,0:37:26.17,Default,,0,0,0,,进行的各种CONS操作\nDialogue: 0,0:37:26.32,0:37:28.40,Default,,0,0,0,,与垃圾回收过程交错进行\nDialogue: 0,0:37:28.85,0:37:31.20,Default,,0,0,0,,垃圾回收器是分散的\nDialogue: 0,0:37:31.20,0:37:32.19,Default,,0,0,0,,机器不需要停下来\nDialogue: 0,0:37:32.41,0:37:33.47,Default,,0,0,0,,再让垃圾回收开始运作\nDialogue: 0,0:37:34.64,0:37:37.87,Default,,0,0,0,,当然 在使用虚拟内存的机器中\nDialogue: 0,0:37:38.90,0:37:41.20,Default,,0,0,0,,有很多内存无法访问\nDialogue: 0,0:37:41.50,0:37:43.60,Default,,0,0,0,,这会让整个过程变得耗时\nDialogue: 0,0:37:44.28,0:37:46.43,Default,,0,0,0,,有很多人尝试\nDialogue: 0,0:37:47.16,0:37:48.65,Default,,0,0,0,,将它改进得更好\nDialogue: 0,0:37:49.19,0:37:51.15,Default,,0,0,0,,对于感兴趣的同学\nDialogue: 0,0:37:51.16,0:37:52.41,Default,,0,0,0,,这有一篇论文\nDialogue: 0,0:37:52.64,0:37:54.27,Default,,0,0,0,,作者是Moon等人\nDialogue: 0,0:37:54.65,0:37:56.89,Default,,0,0,0,,这篇论文描述了\nDialogue: 0,0:37:56.92,0:37:59.44,Default,,0,0,0,,增量式Minsky-Fenichel-Yochelson算法\nDialogue: 0,0:37:59.51,0:38:01.20,Default,,0,0,0,,和Baker算法的修改\nDialogue: 0,0:38:01.42,0:38:06.54,Default,,0,0,0,,让使用虚拟内存的系统更加高效\nDialogue: 0,0:38:08.27,0:38:12.32,Default,,0,0,0,,现在最后一个谜团也解开了\nDialogue: 0,0:38:12.84,0:38:14.09,Default,,0,0,0,,有什么疑惑吗？\nDialogue: 0,0:38:19.78,0:38:19.95,Default,,0,0,0,,请讲\nDialogue: 0,0:38:20.60,0:38:23.58,Default,,0,0,0,,学生：我在楼上的系统上\nDialogue: 0,0:38:23.64,0:38:25.05,Default,,0,0,0,,你们运行垃圾收集器的时候\nDialogue: 0,0:38:25.93,0:38:27.88,Default,,0,0,0,,它看起来跑得飞快\nDialogue: 0,0:38:27.96,0:38:28.40,Default,,0,0,0,,教授：是的\nDialogue: 0,0:38:28.49,0:38:29.52,Default,,0,0,0,,学生：整个过程花费了--\nDialogue: 0,0:38:30.11,0:38:31.88,Default,,0,0,0,,它真的扫描了整个内存吗？\nDialogue: 0,0:38:31.88,0:38:32.22,Default,,0,0,0,,教授：没有\nDialogue: 0,0:38:32.25,0:38:34.11,Default,,0,0,0,,它只扫描了那些需要的\nDialogue: 0,0:38:34.33,0:38:35.63,Default,,0,0,0,,去复制那些有用的数据结构\nDialogue: 0,0:38:37.32,0:38:38.36,Default,,0,0,0,,它是个复制收集器\nDialogue: 0,0:38:38.44,0:38:38.91,Default,,0,0,0,,学生：好吧\nDialogue: 0,0:38:39.30,0:38:40.88,Default,,0,0,0,,教授：但它确实很快\nDialogue: 0,0:38:41.85,0:38:45.88,Default,,0,0,0,,整体来说 我想如果要复制\nDialogue: 0,0:38:47.12,0:38:51.56,Default,,0,0,0,,一个大约3MB的东西\nDialogue: 0,0:38:52.43,0:38:53.24,Default,,0,0,0,,将在一秒内完成\nDialogue: 0,0:38:55.00,0:38:55.69,Default,,0,0,0,,而且是实时的\nDialogue: 0,0:38:56.54,0:38:58.46,Default,,0,0,0,,它们是非常小的程序\nDialogue: 0,0:38:58.62,0:39:01.50,Default,,0,0,0,,你需要注意到的一件事是\nDialogue: 0,0:39:02.91,0:39:04.40,Default,,0,0,0,,垃圾收集器必须要小\nDialogue: 0,0:39:05.40,0:39:07.10,Default,,0,0,0,,不是因为它们需要运行得快\nDialogue: 0,0:39:07.90,0:39:09.23,Default,,0,0,0,,因为没有人能够调试\nDialogue: 0,0:39:09.26,0:39:10.48,Default,,0,0,0,,复杂的垃圾收集器\nDialogue: 0,0:39:11.34,0:39:12.91,Default,,0,0,0,,如果一个垃圾收集器不能正常工作\nDialogue: 0,0:39:14.04,0:39:15.93,Default,,0,0,0,,它会把你的内存搞得一团糟\nDialogue: 0,0:39:15.93,0:39:17.39,Default,,0,0,0,,而你却束手无策\nDialogue: 0,0:39:18.35,0:39:19.67,Default,,0,0,0,,你需要跟踪审计\nDialogue: 0,0:39:20.66,0:39:22.01,Default,,0,0,0,,因为它把所有东西都换了位置\nDialogue: 0,0:39:22.04,0:39:23.24,Default,,0,0,0,,你需要知道那里发生了什么\nDialogue: 0,0:39:23.74,0:39:26.58,Default,,0,0,0,,所以这是唯一一种\nDialogue: 0,0:39:26.92,0:39:28.40,Default,,0,0,0,,真正非常重要的程序\nDialogue: 0,0:39:28.54,0:39:29.79,Default,,0,0,0,,如果你盯着它看足够久\nDialogue: 0,0:39:29.82,0:39:31.07,Default,,0,0,0,,那么你就相信它有效\nDialogue: 0,0:39:31.34,0:39:33.36,Default,,0,0,0,,这意味着某种“自我证明”\nDialogue: 0,0:39:33.92,0:39:36.11,Default,,0,0,0,,因此我们无法对它进行查错\nDialogue: 0,0:39:36.94,0:39:38.96,Default,,0,0,0,,这意味着它需要足够小\nDialogue: 0,0:39:38.96,0:39:39.97,Default,,0,0,0,,你的大脑能够思考它的工作情况\nDialogue: 0,0:39:41.45,0:39:43.90,Default,,0,0,0,,正因如此 垃圾收集器十分特殊\nDialogue: 0,0:39:45.02,0:39:47.12,Default,,0,0,0,,所以实用的垃圾收集器一定要短小\nDialogue: 0,0:39:47.13,0:39:48.45,Default,,0,0,0,,而通常短小的程序运行得就快\nDialogue: 0,0:39:52.05,0:39:52.43,Default,,0,0,0,,请讲\nDialogue: 0,0:39:52.43,0:39:54.51,Default,,0,0,0,,学生：您能再重复一遍这个技术的名字吗?\nDialogue: 0,0:39:54.68,0:39:56.92,Default,,0,0,0,,教授：Minsky-Fenichel-Yochelson垃圾回收器\nDialogue: 0,0:39:57.88,0:39:58.43,Default,,0,0,0,,学生：什么?\nDialogue: 0,0:39:59.00,0:40:00.78,Default,,0,0,0,,教授：Minsky在1961年\nDialogue: 0,0:40:00.81,0:40:02.21,Default,,0,0,0,,为RLE PDP-1设计了这个算法\nDialogue: 0,0:40:02.21,0:40:06.17,Default,,0,0,0,,Fenichel和Yochelson改进并精化了算法\nDialogue: 0,0:40:06.45,0:40:10.27,Default,,0,0,0,,将它用在了Multics平台的MacLisp中\nDialogue: 0,0:40:11.37,0:40:14.75,Default,,0,0,0,,那时大约是1968或者1969年\nDialogue: 0,0:40:19.57,0:40:21.36,Default,,0,0,0,,好吧 我们休息一下\nDialogue: 0,0:40:22.64,0:40:32.36,Default,,0,0,0,,[音乐]\nDialogue: 0,0:40:32.41,0:40:36.19,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:41:03.15,0:41:07.18,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:41:07.20,0:41:10.17,Declare,,0,0,0,,{\\an2\\fad(500,500)\\pos(320,470)}《计算机程序的构造和解释》\nDialogue: 0,0:41:10.20,0:41:14.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算的极限\nDialogue: 0,0:41:17.31,0:41:19.67,Default,,0,0,0,,教授：我们已经到课程的最后一部分了\nDialogue: 0,0:41:20.08,0:41:23.85,Default,,0,0,0,,我已经给你们展示了一台通用机器\nDialogue: 0,0:41:24.47,0:41:26.74,Default,,0,0,0,,它被简化为求值器\nDialogue: 0,0:41:27.02,0:41:28.38,Default,,0,0,0,,它被简化到\nDialogue: 0,0:41:28.38,0:41:29.67,Default,,0,0,0,,你自己也能构造出来\nDialogue: 0,0:41:30.19,0:41:33.32,Default,,0,0,0,,这是一个特定的Lisp实现\nDialogue: 0,0:41:33.90,0:41:36.01,Default,,0,0,0,,它是用\nDialogue: 0,0:41:36.16,0:41:38.05,Default,,0,0,0,,昨天讲过的Scheme芯片制作的\nDialogue: 0,0:41:38.20,0:41:38.91,Default,,0,0,0,,就是这个\nDialogue: 0,0:41:39.35,0:41:42.00,Default,,0,0,0,,这基本上就是暴露给他人内存的接口了\nDialogue: 0,0:41:42.60,0:41:44.75,Default,,0,0,0,,里面有节拍发生器等组件\nDialogue: 0,0:41:45.22,0:41:47.25,Default,,0,0,0,,尽管是解释执行\nDialogue: 0,0:41:47.77,0:41:50.17,Default,,0,0,0,,但它们运行Lisp的速度还算不错\nDialogue: 0,0:41:50.61,0:41:53.82,Default,,0,0,0,,它跑得像1979年的\nDialogue: 0,0:41:54.22,0:41:55.65,Default,,0,0,0,,DEC PDP-10一样快\nDialogue: 0,0:41:56.50,0:41:59.67,Default,,0,0,0,,作为一个十足的硬件\nDialogue: 0,0:42:00.02,0:42:00.89,Default,,0,0,0,,算是十分“实在”了\nDialogue: 0,0:42:02.47,0:42:04.70,Default,,0,0,0,,我们为你们讲解了一些\nDialogue: 0,0:42:04.72,0:42:06.07,Default,,0,0,0,,可以被计算的东西\nDialogue: 0,0:42:07.37,0:42:08.76,Default,,0,0,0,,但我们是否可能遇到\nDialogue: 0,0:42:09.32,0:42:10.55,Default,,0,0,0,,我们无法计算的情况？\nDialogue: 0,0:42:11.85,0:42:13.50,Default,,0,0,0,,课程的最后\nDialogue: 0,0:42:13.75,0:42:15.87,Default,,0,0,0,,我想展示一些你认为可以被计算\nDialogue: 0,0:42:16.60,0:42:17.22,Default,,0,0,0,,但实际上不能的东西\nDialogue: 0,0:42:18.19,0:42:19.45,Default,,0,0,0,,实际上\nDialogue: 0,0:42:19.45,0:42:20.82,Default,,0,0,0,,确实有我们无法计算的东西\nDialogue: 0,0:42:22.72,0:42:23.47,Default,,0,0,0,,例如\nDialogue: 0,0:42:24.45,0:42:25.82,Default,,0,0,0,,我们想要这样的一种东西\nDialogue: 0,0:42:27.80,0:42:29.36,Default,,0,0,0,,当我们在编写编译器时\nDialogue: 0,0:42:29.77,0:42:31.42,Default,,0,0,0,,你想用一个程序检查\nDialogue: 0,0:42:32.00,0:42:33.97,Default,,0,0,0,,你的代码能否正常运行\nDialogue: 0,0:42:34.63,0:42:35.40,Default,,0,0,0,,这不是很棒吗?\nDialogue: 0,0:42:36.08,0:42:37.87,Default,,0,0,0,,你希望能够捕获死循环\nDialogue: 0,0:42:37.87,0:42:38.54,Default,,0,0,0,,例如\nDialogue: 0,0:42:39.45,0:42:42.42,Default,,0,0,0,,用户编写的程序里的死循环\nDialogue: 0,0:42:43.19,0:42:45.12,Default,,0,0,0,,但通常来说 你写不出这样的程序\nDialogue: 0,0:42:45.35,0:42:46.49,Default,,0,0,0,,它读取某个程序\nDialogue: 0,0:42:46.51,0:42:47.45,Default,,0,0,0,,并检测它\nDialogue: 0,0:42:48.35,0:42:49.30,Default,,0,0,0,,是不是死循环\nDialogue: 0,0:42:50.99,0:42:51.71,Default,,0,0,0,,我来展示一下\nDialogue: 0,0:42:51.76,0:42:53.80,Default,,0,0,0,,这个需要涉及到数学知识\nDialogue: 0,0:42:58.78,0:42:59.65,Default,,0,0,0,,设想\nDialogue: 0,0:43:00.05,0:43:01.78,Default,,0,0,0,,在我们开始之前\nDialogue: 0,0:43:01.78,0:43:02.62,Default,,0,0,0,,有一个数学函数\nDialogue: 0,0:43:02.62,0:43:03.42,Default,,0,0,0,,这里就有一个\nDialogue: 0,0:43:03.84,0:43:04.67,Default,,0,0,0,,记作S\nDialogue: 0,0:43:05.47,0:43:07.54,Default,,0,0,0,,它接受一个过程\nDialogue: 0,0:43:12.64,0:43:14.23,Default,,0,0,0,,和它的参数A\nDialogue: 0,0:43:19.17,0:43:20.52,Default,,0,0,0,,S所做的是\nDialogue: 0,0:43:21.65,0:43:24.01,Default,,0,0,0,,检测以A为参数运行P时\nDialogue: 0,0:43:24.01,0:43:25.97,Default,,0,0,0,,是否安全\nDialogue: 0,0:43:26.90,0:43:28.17,Default,,0,0,0,,换句话说就是\nDialogue: 0,0:43:28.76,0:43:35.12,Default,,0,0,0,,如果(P A)\nDialogue: 0,0:43:35.62,0:43:36.74,Default,,0,0,0,,在没有出错的情况下\nDialogue: 0,0:43:41.40,0:43:42.45,Default,,0,0,0,,能够返回一个值\nDialogue: 0,0:43:44.35,0:43:45.33,Default,,0,0,0,,那么S就为TRUE\nDialogue: 0,0:43:52.70,0:43:53.68,Default,,0,0,0,,但如果(P A)\nDialogue: 0,0:43:56.10,0:43:57.04,Default,,0,0,0,,是死循环\nDialogue: 0,0:43:59.67,0:44:00.76,Default,,0,0,0,,或者抛出错误\nDialogue: 0,0:44:05.87,0:44:06.95,Default,,0,0,0,,那么S就为FALSE\nDialogue: 0,0:44:15.23,0:44:17.22,Default,,0,0,0,,这确实是个函数\nDialogue: 0,0:44:18.78,0:44:20.72,Default,,0,0,0,,对于你输入的任何过程\nDialogue: 0,0:44:21.20,0:44:22.85,Default,,0,0,0,,或者任何参数\nDialogue: 0,0:44:23.92,0:44:25.45,Default,,0,0,0,,它只能返回TRUE或FALSE\nDialogue: 0,0:44:25.92,0:44:27.85,Default,,0,0,0,,它会返回一个值而且不会报错\nDialogue: 0,0:44:28.44,0:44:30.15,Default,,0,0,0,,你可以为它们画一张巨大的表格\nDialogue: 0,0:44:32.22,0:44:32.92,Default,,0,0,0,,但问题是\nDialogue: 0,0:44:32.92,0:44:34.09,Default,,0,0,0,,你能写一个过程\nDialogue: 0,0:44:34.09,0:44:35.92,Default,,0,0,0,,来计算这个函数的值吗?\nDialogue: 0,0:44:37.43,0:44:38.92,Default,,0,0,0,,假设我们能做到\nDialogue: 0,0:44:39.72,0:44:40.55,Default,,0,0,0,,假设\nDialogue: 0,0:44:44.33,0:44:45.58,Default,,0,0,0,,我们有个过程\nDialogue: 0,0:44:48.55,0:44:52.73,Default,,0,0,0,,一个叫作SAFE?的过程\nDialogue: 0,0:44:56.54,0:44:59.90,Default,,0,0,0,,它能计算S的值\nDialogue: 0,0:45:12.65,0:45:14.89,Default,,0,0,0,,现在我要用几种方法\nDialogue: 0,0:45:15.90,0:45:18.51,Default,,0,0,0,,证明你做不到\nDialogue: 0,0:45:19.76,0:45:20.62,Default,,0,0,0,,最简单的一个\nDialogue: 0,0:45:20.62,0:45:21.28,Default,,0,0,0,,或者说第一个\nDialogue: 0,0:45:21.31,0:45:23.45,Default,,0,0,0,,我们定义一个叫DIAG1的过程\nDialogue: 0,0:45:23.76,0:45:24.86,Default,,0,0,0,,给定了SAFE?过程\nDialogue: 0,0:45:25.20,0:45:26.99,Default,,0,0,0,,我们可以把DIAG1定义为\nDialogue: 0,0:45:34.42,0:45:35.55,Default,,0,0,0,,把DIAG1定义为\nDialogue: 0,0:45:37.82,0:45:41.60,Default,,0,0,0,,只含有参数P的过程\nDialogue: 0,0:45:42.45,0:45:44.05,Default,,0,0,0,,它有着这样的属性\nDialogue: 0,0:45:44.78,0:45:50.67,Default,,0,0,0,,如果(SAFE? P P)为真\nDialogue: 0,0:45:53.32,0:45:55.32,Default,,0,0,0,,那么我就主动陷入死循环\nDialogue: 0,0:45:59.22,0:46:00.92,Default,,0,0,0,,否则我会返回3\nDialogue: 0,0:46:03.68,0:46:04.47,Default,,0,0,0,,它也可能是42\nDialogue: 0,0:46:04.47,0:46:06.42,Default,,0,0,0,,宇宙的终极答案是什么?\nDialogue: 0,0:46:07.06,0:46:08.87,Default,,0,0,0,,我们当然知道死循环是什么\nDialogue: 0,0:46:12.05,0:46:12.96,Default,,0,0,0,,死循环INF是\nDialogue: 0,0:46:13.82,0:46:16.02,Default,,0,0,0,,一个无参过程\nDialogue: 0,0:46:16.02,0:46:18.07,Default,,0,0,0,,这是一个极好的LAMBADA演算循环\nDialogue: 0,0:46:18.35,0:46:20.44,Default,,0,0,0,,(LAMBDA (X) (X X))\nDialogue: 0,0:46:21.30,0:46:24.68,Default,,0,0,0,,应用到(LAMBDA (X) (X X))\nDialogue: 0,0:46:24.68,0:46:26.55,Default,,0,0,0,,没什么想象的余地了\nDialogue: 0,0:46:29.83,0:46:31.17,Default,,0,0,0,,我们来看下会发生什么\nDialogue: 0,0:46:32.50,0:46:33.90,Default,,0,0,0,,我假设\nDialogue: 0,0:46:35.45,0:46:38.77,Default,,0,0,0,,我们考虑\nDialogue: 0,0:46:39.00,0:46:43.45,Default,,0,0,0,,把DIAG1应用到DIAG1上\nDialogue: 0,0:46:46.27,0:46:47.77,Default,,0,0,0,,那会发生什么呢?\nDialogue: 0,0:46:49.97,0:46:51.39,Default,,0,0,0,,我不知道\nDialogue: 0,0:46:51.39,0:46:53.21,Default,,0,0,0,,将DIAG1代换为\nDialogue: 0,0:46:53.55,0:46:55.50,Default,,0,0,0,,P的过程体\nDialogue: 0,0:46:57.31,0:47:00.22,Default,,0,0,0,,(SAFE? DIAG1 DIAG1)会返回什么呢？\nDialogue: 0,0:47:00.22,0:47:00.78,Default,,0,0,0,,我不知道\nDialogue: 0,0:47:00.78,0:47:01.82,Default,,0,0,0,,有两种可能\nDialogue: 0,0:47:03.40,0:47:05.50,Default,,0,0,0,,如果计算(DIAG1 DIAG1)是安全的\nDialogue: 0,0:47:05.92,0:47:06.89,Default,,0,0,0,,这意味着没有死循环\nDialogue: 0,0:47:08.49,0:47:09.22,Default,,0,0,0,,那么我就要来到这里\nDialogue: 0,0:47:09.22,0:47:10.35,Default,,0,0,0,,但是随即我就陷入了死循环\nDialogue: 0,0:47:10.56,0:47:11.57,Default,,0,0,0,,所以它不是安全的\nDialogue: 0,0:47:12.21,0:47:14.78,Default,,0,0,0,,但如果计算(DIAG1 DIAG1)不安全\nDialogue: 0,0:47:14.90,0:47:16.02,Default,,0,0,0,,那么它的结果是3\nDialogue: 0,0:47:16.02,0:47:17.26,Default,,0,0,0,,但是调用(DIAG1 DIAG1)又必须能够返回\nDialogue: 0,0:47:17.26,0:47:17.93,Default,,0,0,0,,所以它必须安全才行\nDialogue: 0,0:47:20.53,0:47:23.60,Default,,0,0,0,,因此 通过归纳出这个矛盾\nDialogue: 0,0:47:24.32,0:47:26.30,Default,,0,0,0,,我们无法写出这个SAFE?过程\nDialogue: 0,0:47:27.40,0:47:29.80,Default,,0,0,0,,如果大家没有听明白这种表述\nDialogue: 0,0:47:30.25,0:47:32.15,Default,,0,0,0,,我换个方式再讲一遍\nDialogue: 0,0:47:32.82,0:47:34.00,Default,,0,0,0,,请听另一个版本\nDialogue: 0,0:47:35.53,0:47:36.95,Default,,0,0,0,,我们定义DIAG2\nDialogue: 0,0:47:39.84,0:47:41.60,Default,,0,0,0,,取名叫DIAG是因为\nDialogue: 0,0:47:42.65,0:47:44.72,Default,,0,0,0,,它来源于康托尔的对角论证法\nDialogue: 0,0:47:45.00,0:47:47.05,Default,,0,0,0,,这些事例最初都来自于\nDialogue: 0,0:47:47.05,0:47:49.05,Default,,0,0,0,,一个著名的论证\nDialogue: 0,0:47:49.45,0:47:52.65,Default,,0,0,0,,也就是康托尔在19世纪末\nDialogue: 0,0:47:52.77,0:47:56.10,Default,,0,0,0,,证明了实数是不可数的\nDialogue: 0,0:47:56.67,0:47:58.00,Default,,0,0,0,,整数与实数\nDialogue: 0,0:47:58.06,0:47:59.42,Default,,0,0,0,,无法形成一一映射\nDialogue: 0,0:48:00.19,0:48:01.74,Default,,0,0,0,,数轴上的点\nDialogue: 0,0:48:01.74,0:48:02.50,Default,,0,0,0,,举例来说\nDialogue: 0,0:48:02.50,0:48:04.42,Default,,0,0,0,,比数轴上的刻度还要多\nDialogue: 0,0:48:05.26,0:48:06.85,Default,,0,0,0,,这或许不是个显而易见的结论\nDialogue: 0,0:48:06.85,0:48:08.17,Default,,0,0,0,,但我不想深入讨论这个\nDialogue: 0,0:48:10.90,0:48:12.45,Default,,0,0,0,,但是DIAG2\nDialogue: 0,0:48:13.30,0:48:15.82,Default,,0,0,0,,也是一个参数为P的单参过程\nDialogue: 0,0:48:15.82,0:48:17.47,Default,,0,0,0,,这几乎与之前的例子相同\nDialogue: 0,0:48:17.72,0:48:24.32,Default,,0,0,0,,如果计算(P P)是安全的\nDialogue: 0,0:48:25.17,0:48:26.67,Default,,0,0,0,,那么我就要\nDialogue: 0,0:48:27.26,0:48:28.14,Default,,0,0,0,,哦 漏了一个IF\nDialogue: 0,0:48:29.31,0:48:31.02,Default,,0,0,0,,那么我就去计算\nDialogue: 0,0:48:31.57,0:48:37.58,Default,,0,0,0,,一些(P P)之外的东西\nDialogue: 0,0:48:38.96,0:48:40.21,Default,,0,0,0,,否则我就返回FALSE\nDialogue: 0,0:48:43.60,0:48:45.30,Default,,0,0,0,,这里的OTHER-THAN意思是\nDialogue: 0,0:48:45.47,0:48:46.35,Default,,0,0,0,,不管这个(P P)是什么\nDialogue: 0,0:48:46.35,0:48:47.47,Default,,0,0,0,,我都返回一些别的东西\nDialogue: 0,0:48:48.88,0:48:50.03,Default,,0,0,0,,我来给出一个\nDialogue: 0,0:48:50.07,0:48:51.52,Default,,0,0,0,,OTHER-THAN的一个定义\nDialogue: 0,0:48:51.60,0:48:52.57,Default,,0,0,0,,我觉得它是可用的\nDialogue: 0,0:48:53.89,0:48:54.51,Default,,0,0,0,,来看看\nDialogue: 0,0:48:55.64,0:48:56.08,Default,,0,0,0,,好\nDialogue: 0,0:48:56.33,0:48:57.26,Default,,0,0,0,,定义OTHER-THAN\nDialogue: 0,0:49:04.03,0:49:06.11,Default,,0,0,0,,参数为X的单参过程\nDialogue: 0,0:49:06.57,0:49:07.26,Default,,0,0,0,,过程体是\nDialogue: 0,0:49:08.05,0:49:12.96,Default,,0,0,0,,如果(EQ? X 'A)\nDialogue: 0,0:49:13.47,0:49:15.07,Default,,0,0,0,,那么结果是'B\nDialogue: 0,0:49:15.72,0:49:16.80,Default,,0,0,0,,否则结果是'A\nDialogue: 0,0:49:20.27,0:49:21.90,Default,,0,0,0,,这样无论参数是什么\nDialogue: 0,0:49:22.07,0:49:23.45,Default,,0,0,0,,返回值跟参数总是不相同的\nDialogue: 0,0:49:25.20,0:49:26.12,Default,,0,0,0,,就是这样了\nDialogue: 0,0:49:26.54,0:49:27.37,Default,,0,0,0,,这就是我要的\nDialogue: 0,0:49:28.25,0:49:29.58,Default,,0,0,0,,我们考虑一下这个\nDialogue: 0,0:49:29.58,0:49:31.15,Default,,0,0,0,,(DIAG2 DIAG2)\nDialogue: 0,0:49:38.28,0:49:38.94,Default,,0,0,0,,看\nDialogue: 0,0:49:39.95,0:49:41.72,Default,,0,0,0,,这个东西会做些危险的事情\nDialogue: 0,0:49:42.00,0:49:43.45,Default,,0,0,0,,比如求值(P P)\nDialogue: 0,0:49:44.75,0:49:45.95,Default,,0,0,0,,如果它是安全的\nDialogue: 0,0:49:47.47,0:49:49.16,Default,,0,0,0,,如果SAFE?能够被定义的话\nDialogue: 0,0:49:50.30,0:49:52.49,Default,,0,0,0,,如果你能定义SAFE?过程\nDialogue: 0,0:49:52.97,0:49:54.32,Default,,0,0,0,,那么这个过程\nDialogue: 0,0:49:54.60,0:49:56.40,Default,,0,0,0,,也就顺理成章地是安全的\nDialogue: 0,0:49:56.52,0:49:57.22,Default,,0,0,0,,对于任意输入来说都是\nDialogue: 0,0:50:01.54,0:50:03.50,Default,,0,0,0,,那么(DIAG2 DIAG2)\nDialogue: 0,0:50:03.87,0:50:12.20,Default,,0,0,0,,就会返回(OTHER-THAN (DIAG2 DIAG2))\nDialogue: 0,0:50:15.82,0:50:16.97,Default,,0,0,0,,这说不通\nDialogue: 0,0:50:17.80,0:50:19.02,Default,,0,0,0,,又产生了悖论\nDialogue: 0,0:50:19.85,0:50:21.57,Default,,0,0,0,,因此我们不能定义SAFE?\nDialogue: 0,0:50:22.95,0:50:24.23,Default,,0,0,0,,我只想这样证明两次\nDialogue: 0,0:50:24.78,0:50:25.82,Default,,0,0,0,,有些许不同\nDialogue: 0,0:50:26.84,0:50:27.90,Default,,0,0,0,,你不会感到\nDialogue: 0,0:50:29.07,0:50:30.86,Default,,0,0,0,,第一个证明是个把戏\nDialogue: 0,0:50:32.54,0:50:33.45,Default,,0,0,0,,它们可能都是把戏\nDialogue: 0,0:50:33.80,0:50:35.15,Default,,0,0,0,,但它们稍微有些不同\nDialogue: 0,0:50:37.30,0:50:39.20,Default,,0,0,0,,因此 我想这就基本上讲清楚了\nDialogue: 0,0:50:40.03,0:50:41.97,Default,,0,0,0,,我们刚刚证明了所谓的“停机问题”\nDialogue: 0,0:50:43.00,0:50:44.70,Default,,0,0,0,,我想 本课程也即将画上句号\nDialogue: 0,0:50:46.72,0:50:47.63,Default,,0,0,0,,希望你们有所收获\nDialogue: 0,0:50:50.90,0:50:51.76,Default,,0,0,0,,有什么问题吗?\nDialogue: 0,0:50:53.30,0:50:53.56,Default,,0,0,0,,请讲\nDialogue: 0,0:50:53.81,0:50:56.27,Default,,0,0,0,,学生: (S DIAG1)的值是什么?\nDialogue: 0,0:50:56.75,0:50:57.23,Default,,0,0,0,,教授: 什么的值?\nDialogue: 0,0:50:57.50,0:50:58.80,Default,,0,0,0,,学生: (S DIAG1)的值\nDialogue: 0,0:51:00.12,0:51:02.20,Default,,0,0,0,,如果你说S是个函数 我们就可以--\nDialogue: 0,0:51:02.30,0:51:03.63,Default,,0,0,0,,教授: 噢 我不知道啊\nDialogue: 0,0:51:03.87,0:51:04.35,Default,,0,0,0,,我不知道\nDialogue: 0,0:51:04.35,0:51:04.88,Default,,0,0,0,,它是一个函数\nDialogue: 0,0:51:04.88,0:51:05.85,Default,,0,0,0,,但我不知道如何计算它\nDialogue: 0,0:51:06.80,0:51:08.00,Default,,0,0,0,,我做不到\nDialogue: 0,0:51:08.61,0:51:09.64,Default,,0,0,0,,我也只是个机器\nDialogue: 0,0:51:11.53,0:51:11.88,Default,,0,0,0,,对吧?\nDialogue: 0,0:51:11.90,0:51:13.37,Default,,0,0,0,,原则上来说\nDialogue: 0,0:51:13.37,0:51:14.05,Default,,0,0,0,,没有机器\nDialogue: 0,0:51:14.47,0:51:16.87,Default,,0,0,0,,当然 也有可能会处在你刚才问的那个情况中\nDialogue: 0,0:51:16.87,0:51:18.32,Default,,0,0,0,,花点时间还是可以计算出来\nDialogue: 0,0:51:18.58,0:51:19.37,Default,,0,0,0,,但通常情况下\nDialogue: 0,0:51:19.60,0:51:21.05,Default,,0,0,0,,我无法计算S的值\nDialogue: 0,0:51:21.05,0:51:22.52,Default,,0,0,0,,别的机器也做不到\nDialogue: 0,0:51:23.78,0:51:24.92,Default,,0,0,0,,存在这样一个函数\nDialogue: 0,0:51:25.92,0:51:28.00,Default,,0,0,0,,没有任何机器能够计算它\nDialogue: 0,0:51:29.58,0:51:30.05,Default,,0,0,0,,现在\nDialogue: 0,0:51:30.67,0:51:33.67,Default,,0,0,0,,我这么来说也不会让你们吃惊\nDialogue: 0,0:51:35.22,0:51:36.25,Default,,0,0,0,,来想一想\nDialogue: 0,0:51:36.25,0:51:38.36,Default,,0,0,0,,现在我没有时间给你们展示\nDialogue: 0,0:51:38.45,0:51:43.00,Default,,0,0,0,,但这样的函数非常多\nDialogue: 0,0:51:44.40,0:51:47.58,Default,,0,0,0,,如果有一定量的可能输入\nDialogue: 0,0:51:47.75,0:51:49.62,Default,,0,0,0,,和一定量可能的结果\nDialogue: 0,0:51:49.87,0:51:51.80,Default,,0,0,0,,那么结果数量的输入数量次幂\nDialogue: 0,0:51:51.80,0:51:53.20,Default,,0,0,0,,就是可能的函数的数量\nDialogue: 0,0:51:54.50,0:51:55.48,Default,,0,0,0,,这还是单参的函数\nDialogue: 0,0:51:56.51,0:51:59.24,Default,,0,0,0,,而多参函数的个数\nDialogue: 0,0:52:00.09,0:52:03.21,Default,,0,0,0,,又比这个幂次方\nDialogue: 0,0:52:03.58,0:52:04.32,Default,,0,0,0,,这个指数还要大\nDialogue: 0,0:52:05.48,0:52:09.80,Default,,0,0,0,,函数的数量\nDialogue: 0,0:52:09.95,0:52:12.72,Default,,0,0,0,,比一个人能写出的\nDialogue: 0,0:52:13.30,0:52:14.10,Default,,0,0,0,,程序的数量更多\nDialogue: 0,0:52:14.82,0:52:16.45,Default,,0,0,0,,因为有无穷多的参数\nDialogue: 0,0:52:17.57,0:52:19.00,Default,,0,0,0,,可能会更多\nDialogue: 0,0:52:19.47,0:52:22.12,Default,,0,0,0,,所以不可计算的函数数量\nDialogue: 0,0:52:22.12,0:52:23.48,Default,,0,0,0,,一定会非常多\nDialogue: 0,0:52:25.92,0:52:26.59,Default,,0,0,0,,学生：不久前\nDialogue: 0,0:52:26.64,0:52:28.25,Default,,0,0,0,,你讲了规范\nDialogue: 0,0:52:28.30,0:52:30.04,Default,,0,0,0,,和自动生成解决方案\nDialogue: 0,0:52:30.64,0:52:31.61,Default,,0,0,0,,您觉得通过规范\nDialogue: 0,0:52:31.82,0:52:33.36,Default,,0,0,0,,能够生成解决方案么？\nDialogue: 0,0:52:37.25,0:52:38.22,Default,,0,0,0,,教授：“生成”\nDialogue: 0,0:52:38.72,0:52:39.37,Default,,0,0,0,,你是说\nDialogue: 0,0:52:39.37,0:52:42.60,Default,,0,0,0,,如何按照规范\nDialogue: 0,0:52:42.60,0:52:44.78,Default,,0,0,0,,构建相应的装置吗?\nDialogue: 0,0:52:45.05,0:52:48.36,Default,,0,0,0,,学生：软件工程中有很多\nDialogue: 0,0:52:48.36,0:52:49.90,Default,,0,0,0,,层次化的设计\nDialogue: 0,0:52:49.90,0:52:51.90,Default,,0,0,0,,并进行实现的规范\nDialogue: 0,0:52:52.43,0:52:52.85,Default,,0,0,0,,教授：是的\nDialogue: 0,0:52:52.85,0:52:53.70,Default,,0,0,0,,学生：我很好奇\nDialogue: 0,0:52:53.70,0:52:54.62,Default,,0,0,0,,您觉得这现实吗?\nDialogue: 0,0:52:55.60,0:52:57.17,Default,,0,0,0,,教授：我觉得其中一些是现实的\nDialogue: 0,0:52:57.17,0:52:58.10,Default,,0,0,0,,另一些不现实\nDialogue: 0,0:52:58.10,0:53:00.32,Default,,0,0,0,,如果你想制造一个滤波器\nDialogue: 0,0:53:01.17,0:53:07.16,Default,,0,0,0,,我这有个挺有趣的例子\nDialogue: 0,0:53:07.16,0:53:09.42,Default,,0,0,0,,假设我想制造一个东西\nDialogue: 0,0:53:09.64,0:53:14.07,Default,,0,0,0,,把无线电发射器的输出\nDialogue: 0,0:53:14.47,0:53:18.75,Default,,0,0,0,,连接到某条天线上\nDialogue: 0,0:53:19.90,0:53:21.47,Default,,0,0,0,,我先把它引出来\nDialogue: 0,0:53:21.48,0:53:23.04,Default,,0,0,0,,这里是输出管线\nDialogue: 0,0:53:23.23,0:53:25.26,Default,,0,0,0,,问题是它们的阻抗不同\nDialogue: 0,0:53:25.92,0:53:27.55,Default,,0,0,0,,我希望能够匹配阻抗\nDialogue: 0,0:53:27.55,0:53:28.97,Default,,0,0,0,,我也想在其中加入一个滤波器\nDialogue: 0,0:53:29.15,0:53:31.71,Default,,0,0,0,,用来过滤一些谐波辐射\nDialogue: 0,0:53:32.78,0:53:36.63,Default,,0,0,0,,一种老派的技术叫作\nDialogue: 0,0:53:36.82,0:53:38.67,Default,,0,0,0,,“影像阻抗”之类的东西\nDialogue: 0,0:53:38.86,0:53:39.50,Default,,0,0,0,,你要做的是\nDialogue: 0,0:53:39.50,0:53:40.85,Default,,0,0,0,,你有个基础的模块\nDialogue: 0,0:53:40.85,0:53:42.75,Default,,0,0,0,,称为L型滤波器\nDialogue: 0,0:53:43.30,0:53:43.98,Default,,0,0,0,,就像这样\nDialogue: 0,0:53:47.08,0:53:49.80,Default,,0,0,0,,如果把它连接到某些电阻R上\nDialogue: 0,0:53:50.05,0:53:52.60,Default,,0,0,0,,如果我把它的阻抗记作X_L\nDialogue: 0,0:53:52.72,0:53:55.20,Default,,0,0,0,,而它的值刚好又等于Q*R\nDialogue: 0,0:53:55.26,0:53:58.52,Default,,0,0,0,,这就成了一个低通滤波器\nDialogue: 0,0:53:58.52,0:54:00.72,Default,,0,0,0,,有Q^2+1的等效阻抗\nDialogue: 0,0:54:02.11,0:54:02.86,Default,,0,0,0,,这就是我想要的\nDialogue: 0,0:54:03.12,0:54:04.28,Default,,0,0,0,,因为这样我就可以\nDialogue: 0,0:54:04.30,0:54:05.08,Default,,0,0,0,,把它们匹配到一起了\nDialogue: 0,0:54:05.82,0:54:06.38,Default,,0,0,0,,就像这样\nDialogue: 0,0:54:11.66,0:54:13.15,Default,,0,0,0,,我拿来另一个\nDialogue: 0,0:54:16.00,0:54:17.45,Default,,0,0,0,,想这样把它们连到一起\nDialogue: 0,0:54:18.29,0:54:19.95,Default,,0,0,0,,有两个L型滤波器连接起来\nDialogue: 0,0:54:20.32,0:54:23.07,Default,,0,0,0,,这能让它的阻抗降到我知道的值\nDialogue: 0,0:54:23.37,0:54:25.22,Default,,0,0,0,,让它的阻抗升到我知道的值\nDialogue: 0,0:54:25.53,0:54:26.64,Default,,0,0,0,,这两个低通滤波器\nDialogue: 0,0:54:26.67,0:54:27.82,Default,,0,0,0,,都过滤掉了一些谐波\nDialogue: 0,0:54:28.09,0:54:29.07,Default,,0,0,0,,这是个不错的滤波器\nDialogue: 0,0:54:29.07,0:54:30.27,Default,,0,0,0,,这就是π型滤波器\nDialogue: 0,0:54:30.27,0:54:30.62,Default,,0,0,0,,很好\nDialogue: 0,0:54:31.70,0:54:34.09,Default,,0,0,0,,除了实际上\nDialogue: 0,0:54:34.12,0:54:37.85,Default,,0,0,0,,我在系统里放了些无用的东西\nDialogue: 0,0:54:38.62,0:54:39.60,Default,,0,0,0,,我在本该只用一个的地方\nDialogue: 0,0:54:39.61,0:54:40.59,Default,,0,0,0,,用了两个线圈\nDialogue: 0,0:54:41.62,0:54:44.60,Default,,0,0,0,,在大多数软件工程技艺中\nDialogue: 0,0:54:44.89,0:54:46.88,Default,,0,0,0,,在人工优化和编译之外\nDialogue: 0,0:54:46.92,0:54:48.65,Default,,0,0,0,,不存在一种机制\nDialogue: 0,0:54:48.80,0:54:51.34,Default,,0,0,0,,能在自顶向下的设计中\nDialogue: 0,0:54:51.34,0:54:53.55,Default,,0,0,0,,去掉冗余的部分\nDialogue: 0,0:54:55.35,0:54:56.07,Default,,0,0,0,,或许会更糟\nDialogue: 0,0:54:56.07,0:54:57.58,Default,,0,0,0,,有很多重要的结构\nDialogue: 0,0:54:57.60,0:54:59.02,Default,,0,0,0,,你无法采用这种方式构建\nDialogue: 0,0:55:01.11,0:55:03.53,Default,,0,0,0,,我觉得标准的自上而下的设计方式\nDialogue: 0,0:55:03.53,0:55:04.87,Default,,0,0,0,,是一种很短视的手段\nDialogue: 0,0:55:05.71,0:55:06.60,Default,,0,0,0,,它不会真的抓到\nDialogue: 0,0:55:06.60,0:55:08.10,Default,,0,0,0,,设计者真正想要的结果\nDialogue: 0,0:55:08.31,0:55:10.10,Default,,0,0,0,,我再举一个电子学的例子\nDialogue: 0,0:55:10.10,0:55:11.75,Default,,0,0,0,,电子学的例子\nDialogue: 0,0:55:11.90,0:55:13.13,Default,,0,0,0,,要比计算的例子直观得多\nDialogue: 0,0:55:13.16,0:55:14.78,Default,,0,0,0,,因为计算的例子\nDialogue: 0,0:55:14.80,0:55:16.52,Default,,0,0,0,,解释起来比较复杂\nDialogue: 0,0:55:17.22,0:55:19.16,Default,,0,0,0,,在电子学世界中\nDialogue: 0,0:55:19.16,0:55:20.04,Default,,0,0,0,,我最喜欢的例子之一是\nDialogue: 0,0:55:20.60,0:55:22.80,Default,,0,0,0,,是如何设计中频放大器中\nDialogue: 0,0:55:23.28,0:55:26.55,Default,,0,0,0,,输入级和输出级的连接方式\nDialogue: 0,0:55:27.53,0:55:29.44,Default,,0,0,0,,这是一个三极管\nDialogue: 0,0:55:29.52,0:55:31.50,Default,,0,0,0,,我们来看看\nDialogue: 0,0:55:32.41,0:55:33.40,Default,,0,0,0,,这有个LC震荡电路\nDialogue: 0,0:55:36.45,0:55:39.17,Default,,0,0,0,,我要把它\nDialogue: 0,0:55:41.37,0:55:43.97,Default,,0,0,0,,把它与下一级的输入线圈耦合在一起\nDialogue: 0,0:55:44.36,0:55:47.47,Default,,0,0,0,,这是个完美的可行方案\nDialogue: 0,0:55:48.22,0:55:50.87,Default,,0,0,0,,除了我这个电流方向画错了\nDialogue: 0,0:55:50.87,0:55:52.92,Default,,0,0,0,,电流应该是这个方向\nDialogue: 0,0:55:53.17,0:55:55.45,Default,,0,0,0,,这是个完美的可行方案\nDialogue: 0,0:55:55.98,0:55:56.57,Default,,0,0,0,,不对\nDialogue: 0,0:55:57.12,0:55:57.79,Default,,0,0,0,,我犯蠢了\nDialogue: 0,0:55:58.40,0:55:59.07,Default,,0,0,0,,对不起\nDialogue: 0,0:55:59.69,0:56:00.42,Default,,0,0,0,,这不重要\nDialogue: 0,0:56:00.73,0:56:01.54,Default,,0,0,0,,关键在于这是一个\nDialogue: 0,0:56:01.54,0:56:03.42,Default,,0,0,0,,把两级耦合起来的完美方案\nDialogue: 0,0:56:04.54,0:56:06.92,Default,,0,0,0,,分层来看时会产生什么问题?\nDialogue: 0,0:56:07.62,0:56:08.80,Default,,0,0,0,,它就不是同一个东西了\nDialogue: 0,0:56:09.48,0:56:11.99,Default,,0,0,0,,当分层来看时它就没有任何意义了\nDialogue: 0,0:56:11.99,0:56:14.32,Default,,0,0,0,,这是一个调谐电路的电感\nDialogue: 0,0:56:15.55,0:56:18.02,Default,,0,0,0,,这是变压器的初级线圈\nDialogue: 0,0:56:19.10,0:56:21.82,Default,,0,0,0,,这是直流的通路\nDialogue: 0,0:56:21.82,0:56:23.57,Default,,0,0,0,,它是三极管的集电极\nDialogue: 0,0:56:23.57,0:56:25.10,Default,,0,0,0,,的偏置条件\nDialogue: 0,0:56:26.46,0:56:28.35,Default,,0,0,0,,没有任何简单的自顶向下设计\nDialogue: 0,0:56:28.38,0:56:30.17,Default,,0,0,0,,能够得到这样的结构\nDialogue: 0,0:56:30.22,0:56:34.02,Default,,0,0,0,,对于同一个东西有大量的复用\nDialogue: 0,0:56:34.53,0:56:36.72,Default,,0,0,0,,玩拼字游戏\nDialogue: 0,0:56:36.96,0:56:39.88,Default,,0,0,0,,当你要完成三倍分数的词时\nDialogue: 0,0:56:40.49,0:56:43.60,Default,,0,0,0,,自顶向下的设计策略并不容易\nDialogue: 0,0:56:44.95,0:56:47.08,Default,,0,0,0,,然而 大多数实际的工程学都是\nDialogue: 0,0:56:47.36,0:56:50.70,Default,,0,0,0,,秉承着“尽其力而为之”\nDialogue: 0,0:56:52.14,0:56:53.52,Default,,0,0,0,,那就是你所看到的东西\nDialogue: 0,0:56:54.86,0:56:55.55,Default,,0,0,0,,嗯？\nDialogue: 0,0:56:55.55,0:56:56.81,Default,,0,0,0,,学生：这是最后一个问题吗?\nDialogue: 0,0:57:00.28,0:57:02.03,Default,,0,0,0,,[笑声]\nDialogue: 0,0:57:18.64,0:57:19.63,Default,,0,0,0,,教授：看起来是\nDialogue: 0,0:57:23.57,0:57:24.12,Default,,0,0,0,,谢谢大家\nDialogue: 0,0:57:25.90,0:57:36.50,Default,,0,0,0,,[掌声]\nDialogue: 0,0:58:47.29,0:58:51.13,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:58:47.29,0:58:51.13,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\nDialogue: 0,0:58:51.87,0:58:53.71,Default,,0,0,0,,{\\an4\\pos(33,231)}　　你所知道的有关计算的东西，其他人也都能学到。绝不要认为\\N\\N\\N似乎成功计算的钥匙就掌握在你的手里。你所掌握的，也是我认为\\N\\N\\N并希望的，也就是智慧：那种看到这一机器比你第一次站在它面前\\N\\N\\N时能做得更多的能力，这样你才能将它向前推进。\\N\\N\\N\\N\\N　　　　　　　　　　　　　  　Alan J. Perlis (1922.4.1 - 1990.1.7)\n"
  },
  {
    "path": "Ass/lec10b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 1311\nVideo Position: 103256\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:11.88,0:00:18.11,EN,,0,0,0,,Storage Allocation & Garbage Collection\nDialogue: 0,0:00:18.91,0:00:20.61,EN,,0,0,0,,PROFESSOR: Well, there's one bit of mystery left,\nDialogue: 0,0:00:21.16,0:00:23.36,EN,,0,0,0,,which I'd like to get rid of right now.\nDialogue: 0,0:00:24.44,0:00:28.80,EN,,0,0,0,,And that's that we've been blithely doing things like cons\nDialogue: 0,0:00:30.00,0:00:31.62,EN,,0,0,0,,assuming there's always another one.\nDialogue: 0,0:00:32.80,0:00:36.32,EN,,0,0,0,,That we've been doing these things like\nDialogue: 0,0:00:36.51,0:00:37.44,EN,,0,0,0,,car-ing and cdr-ing\nDialogue: 0,0:00:37.47,0:00:38.72,EN,,0,0,0,,and assuming that we had some idea\nDialogue: 0,0:00:38.75,0:00:39.74,EN,,0,0,0,,how this can be done.\nDialogue: 0,0:00:40.02,0:00:40.67,EN,,0,0,0,,Now indeed\nDialogue: 0,0:00:41.07,0:00:44.40,EN,,0,0,0,,we said that that's equivalent to having procedures.\nDialogue: 0,0:00:45.37,0:00:47.57,EN,,0,0,0,,OK? But that doesn't really solve the problem,\nDialogue: 0,0:00:47.73,0:00:50.25,EN,,0,0,0,,because the procedure need all sorts of complicated mechanisms\nDialogue: 0,0:00:50.27,0:00:51.37,EN,,0,0,0,,like environment structures\nDialogue: 0,0:00:51.64,0:00:52.76,EN,,0,0,0,,and things like that to work.\nDialogue: 0,0:00:53.01,0:00:54.89,EN,,0,0,0,,And those were ultimately made out of conses\nDialogue: 0,0:00:54.89,0:00:56.42,EN,,0,0,0,,in the model that we had,\nDialogue: 0,0:00:56.70,0:00:58.47,EN,,0,0,0,,so that really doesn't solve the problem.\nDialogue: 0,0:00:59.38,0:01:01.13,EN,,0,0,0,,Now the problem here is\nDialogue: 0,0:01:01.31,0:01:03.97,EN,,0,0,0,,is the glue the data structure's made out of.\nDialogue: 0,0:01:04.76,0:01:06.40,EN,,0,0,0,,What kind of possible thing could it be?\nDialogue: 0,0:01:07.04,0:01:10.46,EN,,0,0,0,,OK? We've been showing you things like a machine,\nDialogue: 0,0:01:10.46,0:01:13.96,EN,,0,0,0,,a computer that has a controller,\nDialogue: 0,0:01:14.27,0:01:15.45,EN,,0,0,0,,and some registers,\nDialogue: 0,0:01:15.45,0:01:16.47,EN,,0,0,0,,and maybe a stack.\nDialogue: 0,0:01:16.98,0:01:18.12,EN,,0,0,0,,And we haven't said anything about,\nDialogue: 0,0:01:18.16,0:01:19.95,EN,,0,0,0,,for example, larger memory.\nDialogue: 0,0:01:20.57,0:01:22.38,EN,,0,0,0,,And I think that's what we have to worry about right now.\nDialogue: 0,0:01:23.74,0:01:26.56,EN,,0,0,0,,But just to make it perfectly clear\nDialogue: 0,0:01:26.59,0:01:27.88,EN,,0,0,0,,that this is an inessential,\nDialogue: 0,0:01:28.82,0:01:30.79,EN,,0,0,0,,purely implementational thing,\nDialogue: 0,0:01:31.10,0:01:32.60,EN,,0,0,0,,I'd like to show you, for example,\nDialogue: 0,0:01:32.60,0:01:34.20,EN,,0,0,0,,how you can do it all with the numbers.\nDialogue: 0,0:01:35.23,0:01:36.82,EN,,0,0,0,,That's an easy one.\nDialogue: 0,0:01:37.59,0:01:39.00,EN,,0,0,0,,Famous fellow by the name of Godel,\nDialogue: 0,0:01:44.09,0:01:46.01,EN,,0,0,0,,a logician at the end of the 1930s,\nDialogue: 0,0:01:46.38,0:01:48.70,EN,,0,0,0,,invented a very clever way\nDialogue: 0,0:01:48.70,0:01:52.27,EN,,0,0,0,,of encoding the complicated expressions\nDialogue: 0,0:01:52.81,0:01:53.52,EN,,0,0,0,,as numbers.\nDialogue: 0,0:01:54.32,0:01:55.05,EN,,0,0,0,,For example--\nDialogue: 0,0:01:55.05,0:01:58.00,EN,,0,0,0,,I'm not saying exactly what Godel's scheme is,\nDialogue: 0,0:01:58.00,0:01:59.48,EN,,0,0,0,,because he didn't use words like cons.\nDialogue: 0,0:01:59.66,0:02:00.60,EN,,0,0,0,,He had other kinds of\nDialogue: 0,0:02:00.91,0:02:02.60,EN,,0,0,0,,of ways of combining to make expressions.\nDialogue: 0,0:02:03.09,0:02:03.88,EN,,0,0,0,,But he said,\nDialogue: 0,0:02:03.92,0:02:06.81,EN,,0,0,0,,I'm going to assign a number to every algebraic expression.\nDialogue: 0,0:02:07.92,0:02:09.72,EN,,0,0,0,,And the way I'm going to manufacture these numbers\nDialogue: 0,0:02:09.72,0:02:11.65,EN,,0,0,0,,is by combining the numbers of the parts.\nDialogue: 0,0:02:12.47,0:02:13.45,EN,,0,0,0,,So for example,\nDialogue: 0,0:02:13.62,0:02:15.35,EN,,0,0,0,,what we were doing our world,\nDialogue: 0,0:02:15.35,0:02:18.01,EN,,0,0,0,,we could say that if objects\nDialogue: 0,0:02:20.78,0:02:22.22,EN,,0,0,0,,are represented by numbers,\nDialogue: 0,0:02:30.67,0:02:37.93,EN,,0,0,0,,then cons of x and y\nDialogue: 0,0:02:38.04,0:02:41.07,EN,,0,0,0,,could be represented by,\nDialogue: 0,0:02:41.55,0:02:43.77,EN,,0,0,0,,2 to the x times 3 to the y.\nDialogue: 0,0:02:46.13,0:02:48.03,EN,,0,0,0,,Because then we could extract the parts.\nDialogue: 0,0:02:49.56,0:02:50.97,EN,,0,0,0,,We could say, for example,\nDialogue: 0,0:02:51.18,0:02:55.88,EN,,0,0,0,,that then car of, say, x\nDialogue: 0,0:02:56.55,0:03:05.18,EN,,0,0,0,,is the number of factors of 2 in x.\nDialogue: 0,0:03:06.69,0:03:08.78,EN,,0,0,0,,OK? And of course cdr is the same thing.\nDialogue: 0,0:03:10.69,0:03:15.57,EN,,0,0,0,,It's the number of factors of 3 in x.\nDialogue: 0,0:03:16.51,0:03:18.65,EN,,0,0,0,,Now this is a perfectly reasonable scheme,\nDialogue: 0,0:03:19.10,0:03:20.11,EN,,0,0,0,,except for the fact that\nDialogue: 0,0:03:20.12,0:03:22.52,EN,,0,0,0,,the numbers rapidly get to be much larger\nDialogue: 0,0:03:22.83,0:03:23.98,EN,,0,0,0,,in number of digits\nDialogue: 0,0:03:24.32,0:03:26.55,EN,,0,0,0,,than the number of protons in the universe.\nDialogue: 0,0:03:27.95,0:03:29.88,EN,,0,0,0,,So there's no easy way to use this scheme\nDialogue: 0,0:03:29.90,0:03:31.21,EN,,0,0,0,,other than the theoretical one.\nDialogue: 0,0:03:33.43,0:03:34.48,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:03:35.12,0:03:37.55,EN,,0,0,0,,there are other ways of representing these things.\nDialogue: 0,0:03:38.45,0:03:40.01,EN,,0,0,0,,We have been thinking in terms\nDialogue: 0,0:03:40.25,0:03:42.42,EN,,0,0,0,,of little boxes, boxes.\nDialogue: 0,0:03:43.32,0:03:46.43,EN,,0,0,0,,We've been thinking about our cons structures\nDialogue: 0,0:03:46.50,0:03:48.05,EN,,0,0,0,,as looking sort of like this.\nDialogue: 0,0:03:50.28,0:03:52.57,EN,,0,0,0,,They're little pigeon holes with things in them.\nDialogue: 0,0:03:53.56,0:03:55.47,EN,,0,0,0,,And of course we arrange them in little trees.\nDialogue: 0,0:03:57.21,0:03:59.97,EN,,0,0,0,,I wish that the semiconductor manufacturers\nDialogue: 0,0:03:59.97,0:04:02.07,EN,,0,0,0,,would supply me with something appropriate for this,\nDialogue: 0,0:04:02.70,0:04:03.76,EN,,0,0,0,,but actually\nDialogue: 0,0:04:03.85,0:04:05.31,EN,,0,0,0,,what they do supply me with\nDialogue: 0,0:04:06.20,0:04:07.96,EN,,0,0,0,,is a linear memory.\nDialogue: 0,0:04:09.38,0:04:13.46,EN,,0,0,0,,Memory is sort of a big pile of pigeonholes,\nDialogue: 0,0:04:15.12,0:04:16.34,EN,,0,0,0,,pigeonholes like this.\nDialogue: 0,0:04:17.72,0:04:20.25,EN,,0,0,0,,Each of which can hold a certain sized object,\nDialogue: 0,0:04:20.94,0:04:22.20,EN,,0,0,0,,a fixed size object.\nDialogue: 0,0:04:23.39,0:04:24.07,EN,,0,0,0,,So, for example,\nDialogue: 0,0:04:24.07,0:04:25.66,EN,,0,0,0,,a complicated list with 25 elements\nDialogue: 0,0:04:25.66,0:04:26.64,EN,,0,0,0,,won't fit in one of these.\nDialogue: 0,0:04:28.55,0:04:29.26,EN,,0,0,0,,However, each of these\nDialogue: 0,0:04:29.29,0:04:30.88,EN,,0,0,0,,is indexed by an address.\nDialogue: 0,0:04:33.97,0:04:34.99,EN,,0,0,0,,So the address might be\nDialogue: 0,0:04:35.02,0:04:35.50,EN,,0,0,0,,zero here,\nDialogue: 0,0:04:35.50,0:04:36.22,EN,,0,0,0,,one here,\nDialogue: 0,0:04:36.22,0:04:36.70,EN,,0,0,0,,two here,\nDialogue: 0,0:04:36.70,0:04:37.25,EN,,0,0,0,,three here,\nDialogue: 0,0:04:37.25,0:04:37.94,EN,,0,0,0,,and so on.\nDialogue: 0,0:04:38.06,0:04:40.40,EN,,0,0,0,,That we write these down as numbers is unimportant.\nDialogue: 0,0:04:40.40,0:04:41.68,EN,,0,0,0,,What matters is that they're distinct\nDialogue: 0,0:04:41.95,0:04:43.42,EN,,0,0,0,,as a way to get to the next one.\nDialogue: 0,0:04:44.97,0:04:46.14,EN,,0,0,0,,And inside of each of these,\nDialogue: 0,0:04:46.36,0:04:49.11,EN,,0,0,0,,we can stuff something into these pigeonholes.\nDialogue: 0,0:04:49.53,0:04:50.77,EN,,0,0,0,,That's what memory is like,\nDialogue: 0,0:04:51.02,0:04:53.66,EN,,0,0,0,,for those of you who haven't built a computer.\nDialogue: 0,0:04:54.15,0:04:54.65,EN,,0,0,0,,Now.\nDialogue: 0,0:04:56.69,0:04:57.53,EN,,0,0,0,,Now the problem is\nDialogue: 0,0:04:57.53,0:04:59.97,EN,,0,0,0,,how are we going to impose on this type of structure,\nDialogue: 0,0:05:00.42,0:05:01.72,EN,,0,0,0,,this nice tree structure.\nDialogue: 0,0:05:03.29,0:05:04.57,EN,,0,0,0,,Well it's not very hard,\nDialogue: 0,0:05:04.57,0:05:06.35,EN,,0,0,0,,and there have been numerous schemes involved in this.\nDialogue: 0,0:05:06.87,0:05:08.80,EN,,0,0,0,,The most important one is to say,\nDialogue: 0,0:05:08.80,0:05:11.18,EN,,0,0,0,,well assuming that the semiconductor manufacturer\nDialogue: 0,0:05:11.20,0:05:13.90,EN,,0,0,0,,allows me to arrange my memory\nDialogue: 0,0:05:13.98,0:05:15.77,EN,,0,0,0,,so that one of these pigeonholes is big enough\nDialogue: 0,0:05:16.28,0:05:18.20,EN,,0,0,0,,to hold the address of another\nDialogue: 0,0:05:19.35,0:05:20.83,EN,,0,0,0,,OK. I have been made.\nDialogue: 0,0:05:22.05,0:05:23.45,EN,,0,0,0,,Now it actually has to be a little bit bigger\nDialogue: 0,0:05:23.48,0:05:27.52,EN,,0,0,0,,because I have to also install or store some information\nDialogue: 0,0:05:27.56,0:05:30.09,EN,,0,0,0,,as to a tag which describes the kind of thing that's there.\nDialogue: 0,0:05:30.39,0:05:31.64,EN,,0,0,0,,And we'll see that in a second.\nDialogue: 0,0:05:32.62,0:05:34.40,EN,,0,0,0,,And of course if the semiconductor manufacturer\nDialogue: 0,0:05:34.43,0:05:35.88,EN,,0,0,0,,doesn't arrange it so I can do that,\nDialogue: 0,0:05:36.08,0:05:38.44,EN,,0,0,0,,then of course I can, with some cleverness,\nDialogue: 0,0:05:38.57,0:05:41.82,EN,,0,0,0,,arrange combinations of these to fit together in that way.\nDialogue: 0,0:05:43.77,0:05:47.05,EN,,0,0,0,,So we're going to have to imagine\nDialogue: 0,0:05:47.05,0:05:49.54,EN,,0,0,0,,imposing this complicated tree structure\nDialogue: 0,0:05:49.54,0:05:51.20,EN,,0,0,0,,on our nice linear memory.\nDialogue: 0,0:05:51.74,0:05:54.47,EN,,0,0,0,,If we look at the first still store,\nDialogue: 0,0:05:54.47,0:05:58.30,EN,,0,0,0,,we see a classic scheme for doing that.\nDialogue: 0,0:05:59.49,0:06:02.62,EN,,0,0,0,,It's a standard way of representing list structures\nDialogue: 0,0:06:03.22,0:06:05.87,EN,,0,0,0,,in a linear memory.\nDialogue: 0,0:06:06.27,0:06:08.32,EN,,0,0,0,,What we do is we divide this memory\nDialogue: 0,0:06:08.88,0:06:11.12,EN,,0,0,0,,into two parts.\nDialogue: 0,0:06:12.03,0:06:13.42,EN,,0,0,0,,An array called the cars,\nDialogue: 0,0:06:14.45,0:06:15.88,EN,,0,0,0,,and an array called the cdrs.\nDialogue: 0,0:06:17.58,0:06:18.86,EN,,0,0,0,,Now whether those happen to be\nDialogue: 0,0:06:18.88,0:06:21.04,EN,,0,0,0,,sequential addresses or whatever,\nDialogue: 0,0:06:21.12,0:06:22.00,EN,,0,0,0,,it's not important.\nDialogue: 0,0:06:22.87,0:06:25.20,EN,,0,0,0,,That's somebody's implementation details.\nDialogue: 0,0:06:25.80,0:06:28.40,EN,,0,0,0,,But there are two arrays here.\nDialogue: 0,0:06:28.96,0:06:30.36,EN,,0,0,0,,Linear arrays indexed\nDialogue: 0,0:06:30.46,0:06:32.59,EN,,0,0,0,,by sequential indices like this.\nDialogue: 0,0:06:34.84,0:06:36.85,EN,,0,0,0,,What is stored in each of these pigeonholes\nDialogue: 0,0:06:37.46,0:06:39.85,EN,,0,0,0,,is a typed object.\nDialogue: 0,0:06:41.43,0:06:42.57,EN,,0,0,0,,And what we have here\nDialogue: 0,0:06:42.57,0:06:45.71,EN,,0,0,0,,are types which begin with letters like p,\nDialogue: 0,0:06:45.71,0:06:46.57,EN,,0,0,0,,standing for a pair.\nDialogue: 0,0:06:47.79,0:06:49.37,EN,,0,0,0,,Or n, standing for a number.\nDialogue: 0,0:06:50.04,0:06:52.25,EN,,0,0,0,,Or e, standing for an empty list.\nDialogue: 0,0:06:54.81,0:06:55.83,EN,,0,0,0,,The end of the list.\nDialogue: 0,0:06:57.02,0:06:58.59,EN,,0,0,0,,And so if we wish to represent\nDialogue: 0,0:06:58.99,0:06:59.97,EN,,0,0,0,,an object like this,\nDialogue: 0,0:07:00.01,0:07:02.16,EN,,0,0,0,,the list beginning with 1, 2\nDialogue: 0,0:07:02.65,0:07:04.01,EN,,0,0,0,,and then having a 3 and a 4\nDialogue: 0,0:07:04.01,0:07:05.50,EN,,0,0,0,,and then having a 3 and a 4 as its second and third elements.\nDialogue: 0,0:07:06.43,0:07:08.83,EN,,0,0,0,,A list containing a list as its first part\nDialogue: 0,0:07:09.35,0:07:10.65,EN,,0,0,0,,and then two numbers\nDialogue: 0,0:07:10.65,0:07:12.00,EN,,0,0,0,,as a second and third parts.\nDialogue: 0,0:07:12.87,0:07:14.81,EN,,0,0,0,,Then of course we draw it sort of like this these days,\nDialogue: 0,0:07:14.84,0:07:16.67,EN,,0,0,0,,in box-and-pointer notation.\nDialogue: 0,0:07:17.32,0:07:18.00,EN,,0,0,0,,And you see,\nDialogue: 0,0:07:18.00,0:07:20.04,EN,,0,0,0,,these are the three cells\nDialogue: 0,0:07:20.25,0:07:22.01,EN,,0,0,0,,that have as their car pointer\nDialogue: 0,0:07:22.27,0:07:27.10,EN,,0,0,0,,the object which is either 1, 2 or 3 or 4.\nDialogue: 0,0:07:28.39,0:07:29.75,EN,,0,0,0,,And then of course the 1, 2,\nDialogue: 0,0:07:29.75,0:07:31.32,EN,,0,0,0,,the car of this entire structure,\nDialogue: 0,0:07:31.32,0:07:32.65,EN,,0,0,0,,is itself a substructure\nDialogue: 0,0:07:32.88,0:07:34.75,EN,,0,0,0,,which contains a sublist like that.\nDialogue: 0,0:07:35.94,0:07:37.07,EN,,0,0,0,,What I'm about to do\nDialogue: 0,0:07:37.20,0:07:39.92,EN,,0,0,0,,is put down places which are--\nDialogue: 0,0:07:39.95,0:07:41.46,EN,,0,0,0,,I'm going to assign indices.\nDialogue: 0,0:07:41.84,0:07:43.40,EN,,0,0,0,,Like this 1, over here,\nDialogue: 0,0:07:43.56,0:07:47.05,EN,,0,0,0,,represents the index of this cell.\nDialogue: 0,0:07:49.85,0:07:51.47,EN,,0,0,0,,But that pointer that we see here\nDialogue: 0,0:07:52.37,0:07:54.86,EN,,0,0,0,,is a reference to the\nDialogue: 0,0:07:55.07,0:07:57.29,EN,,0,0,0,,pair of pigeonholes in the cars and the cdrs\nDialogue: 0,0:07:57.40,0:07:58.67,EN,,0,0,0,,that are labeled by 1\nDialogue: 0,0:07:58.76,0:08:00.33,EN,,0,0,0,,in my linear memory down here.\nDialogue: 0,0:08:02.00,0:08:04.06,EN,,0,0,0,,So if I wish to impose this structure\nDialogue: 0,0:08:04.16,0:08:05.26,EN,,0,0,0,,on my linear memory,\nDialogue: 0,0:08:05.85,0:08:07.52,EN,,0,0,0,,what I do is I say, oh yes,\nDialogue: 0,0:08:07.52,0:08:11.88,EN,,0,0,0,,why don't we drop this into cell 1?\nDialogue: 0,0:08:11.95,0:08:12.66,EN,,0,0,0,,Well I said, I pick 1.\nDialogue: 0,0:08:12.66,0:08:13.85,EN,,0,0,0,,There's 1. OK?\nDialogue: 0,0:08:14.27,0:08:16.22,EN,,0,0,0,,And that says that its car,\nDialogue: 0,0:08:16.22,0:08:17.74,EN,,0,0,0,,I'm going to assign it to be a pair.\nDialogue: 0,0:08:17.95,0:08:18.72,EN,,0,0,0,,It's a pair,\nDialogue: 0,0:08:20.02,0:08:21.55,EN,,0,0,0,,which is in index 5.\nDialogue: 0,0:08:22.59,0:08:23.90,EN,,0,0,0,,And the cdr,\nDialogue: 0,0:08:23.90,0:08:25.13,EN,,0,0,0,,which is this one over here,\nDialogue: 0,0:08:25.39,0:08:26.13,EN,,0,0,0,,is a pair\nDialogue: 0,0:08:26.13,0:08:27.70,EN,,0,0,0,,which I'm going to stick into place 2.\nDialogue: 0,0:08:28.34,0:08:28.98,EN,,0,0,0,,p2.\nDialogue: 0,0:08:30.89,0:08:32.95,EN,,0,0,0,,And take a look at p2.\nDialogue: 0,0:08:32.95,0:08:34.72,EN,,0,0,0,,Oh yes, well p2 is a thing\nDialogue: 0,0:08:34.90,0:08:37.22,EN,,0,0,0,,whose car is the number 3,\nDialogue: 0,0:08:37.34,0:08:38.64,EN,,0,0,0,,so as you see, an n3.\nDialogue: 0,0:08:39.52,0:08:41.52,EN,,0,0,0,,And whose cdr, over here,\nDialogue: 0,0:08:41.72,0:08:43.40,EN,,0,0,0,,is a pair,\nDialogue: 0,0:08:43.97,0:08:45.81,EN,,0,0,0,,which lives in place 4.\nDialogue: 0,0:08:46.64,0:08:47.79,EN,,0,0,0,,So that's what this p4 is.\nDialogue: 0,0:08:48.65,0:08:51.16,EN,,0,0,0,,p4 is a number\nDialogue: 0,0:08:51.85,0:08:53.87,EN,,0,0,0,,whose value is 4 in its car\nDialogue: 0,0:08:54.60,0:08:55.65,EN,,0,0,0,,and whose cdr\nDialogue: 0,0:08:55.84,0:08:58.48,EN,,0,0,0,,is an empty list right there.\nDialogue: 0,0:08:59.17,0:08:59.90,EN,,0,0,0,,And that ends it.\nDialogue: 0,0:09:00.69,0:09:04.57,EN,,0,0,0,,So this is the traditional way of representing\nDialogue: 0,0:09:04.90,0:09:09.55,EN,,0,0,0,,this kind of binary tree in a linear memory.\nDialogue: 0,0:09:11.62,0:09:15.10,EN,,0,0,0,,Now the next question, of course,\nDialogue: 0,0:09:15.10,0:09:16.36,EN,,0,0,0,,that we might want to worry about\nDialogue: 0,0:09:16.60,0:09:18.19,EN,,0,0,0,,is just a little bit of implementation.\nDialogue: 0,0:09:18.44,0:09:20.33,EN,,0,0,0,,That means that when I write procedures\nDialogue: 0,0:09:20.36,0:09:23.62,EN,,0,0,0,,of the form assigned a,\nDialogue: 0,0:09:24.54,0:09:27.10,EN,,0,0,0,,lines of register machine code\nDialogue: 0,0:09:27.21,0:09:30.14,EN,,0,0,0,,of the form assigned a, the car of fetch of b,\nDialogue: 0,0:09:30.84,0:09:31.85,EN,,0,0,0,,what I really mean\nDialogue: 0,0:09:31.97,0:09:37.10,EN,,0,0,0,,is addressing these elements.\nDialogue: 0,0:09:38.74,0:09:40.25,EN,,0,0,0,,And so we're going to think of that as\nDialogue: 0,0:09:40.68,0:09:42.94,EN,,0,0,0,,a abbreviation for it.\nDialogue: 0,0:09:44.47,0:09:46.33,EN,,0,0,0,,Now of course in order to write that down\nDialogue: 0,0:09:46.35,0:09:48.59,EN,,0,0,0,,I'm going to introduce some sort of a structure\nDialogue: 0,0:09:48.62,0:09:49.42,EN,,0,0,0,,called a vector.\nDialogue: 0,0:09:52.12,0:09:53.31,EN,,0,0,0,,And we're going to have something which will\nDialogue: 0,0:09:53.48,0:09:54.54,EN,,0,0,0,,reference a vector,\nDialogue: 0,0:09:56.84,0:09:58.51,EN,,0,0,0,,just so we can write it down.\nDialogue: 0,0:09:58.71,0:10:00.22,EN,,0,0,0,,Which takes the name of the vector,\nDialogue: 0,0:10:01.02,0:10:03.97,EN,,0,0,0,,or the-- I don't think that name is the right word.\nDialogue: 0,0:10:03.97,0:10:09.40,EN,,0,0,0,,Which takes the vector and the index,\nDialogue: 0,0:10:11.20,0:10:13.05,EN,,0,0,0,,and I have to have a way of setting one of those\nDialogue: 0,0:10:13.10,0:10:14.27,EN,,0,0,0,,with something called a vector set,\nDialogue: 0,0:10:14.65,0:10:15.60,EN,,0,0,0,,I don't really care.\nDialogue: 0,0:10:16.28,0:10:17.55,EN,,0,0,0,,But let's look, for example,\nDialogue: 0,0:10:18.11,0:10:20.42,EN,,0,0,0,,at then that kind of implementation\nDialogue: 0,0:10:21.25,0:10:23.18,EN,,0,0,0,,of car and cdr.\nDialogue: 0,0:10:26.47,0:10:28.41,EN,,0,0,0,,So for example if I happen to have\nDialogue: 0,0:10:28.88,0:10:30.80,EN,,0,0,0,,a register b,\nDialogue: 0,0:10:31.15,0:10:34.64,EN,,0,0,0,,which contains the type index of a pair,\nDialogue: 0,0:10:35.95,0:10:38.80,EN,,0,0,0,,and therefore it is the pointer to a pair,\nDialogue: 0,0:10:39.35,0:10:40.85,EN,,0,0,0,,then I could take the car of that and\nDialogue: 0,0:10:41.55,0:10:44.11,EN,,0,0,0,,OK if I-- write this down-- I might put that in register a.\nDialogue: 0,0:10:44.49,0:10:46.86,EN,,0,0,0,,What that really is is a representation of\nDialogue: 0,0:10:47.37,0:10:50.19,EN,,0,0,0,,the assign to a,\nDialogue: 0,0:10:50.19,0:10:51.92,EN,,0,0,0,,the value of vector reffing--\nDialogue: 0,0:10:52.80,0:10:55.24,EN,,0,0,0,,or array indexing, if you will-- or something,\nDialogue: 0,0:10:55.42,0:10:57.63,EN,,0,0,0,,the cars object--\nDialogue: 0,0:10:58.40,0:11:00.92,EN,,0,0,0,,whatever that is-- with the index, b.\nDialogue: 0,0:11:02.65,0:11:03.63,EN,,0,0,0,,And similarly for cdr.\nDialogue: 0,0:11:04.10,0:11:05.72,EN,,0,0,0,,And we can do the same thing\nDialogue: 0,0:11:05.90,0:11:08.32,EN,,0,0,0,,for assignment to data structures,\nDialogue: 0,0:11:08.92,0:11:10.92,EN,,0,0,0,,If we need to do that sort of things at all.\nDialogue: 0,0:11:11.84,0:11:13.80,EN,,0,0,0,,It's not too hard to build that.\nDialogue: 0,0:11:14.58,0:11:15.72,EN,,0,0,0,,Well now the next question is\nDialogue: 0,0:11:15.72,0:11:17.00,EN,,0,0,0,,how are we going to do allocation.\nDialogue: 0,0:11:18.01,0:11:20.13,EN,,0,0,0,,And every so often I say I want a cons.\nDialogue: 0,0:11:21.40,0:11:23.42,EN,,0,0,0,,Now conses don't grow on trees.\nDialogue: 0,0:11:23.79,0:11:24.81,EN,,0,0,0,,Or maybe they should.\nDialogue: 0,0:11:25.34,0:11:26.56,EN,,0,0,0,,But I have to have some way\nDialogue: 0,0:11:26.70,0:11:28.97,EN,,0,0,0,,I have to have some way of getting the next one.\nDialogue: 0,0:11:29.98,0:11:31.47,EN,,0,0,0,,I have to have some idea of\nDialogue: 0,0:11:31.47,0:11:33.04,EN,,0,0,0,,if their memory is unused\nDialogue: 0,0:11:33.69,0:11:35.05,EN,,0,0,0,,that I might want to allocate from.\nDialogue: 0,0:11:35.63,0:11:37.38,EN,,0,0,0,,And there are many schemes for doing this.\nDialogue: 0,0:11:37.38,0:11:39.07,EN,,0,0,0,,And the particular thing I'm showing you right now\nDialogue: 0,0:11:39.23,0:11:40.45,EN,,0,0,0,,is not essential.\nDialogue: 0,0:11:42.10,0:11:43.18,EN,,0,0,0,,However it's convenient\nDialogue: 0,0:11:43.20,0:11:44.44,EN,,0,0,0,,and has been done many times.\nDialogue: 0,0:11:44.60,0:11:47.20,EN,,0,0,0,,It's one schemes called the free list allocation scheme.\nDialogue: 0,0:11:47.66,0:11:48.68,EN,,0,0,0,,What that means is\nDialogue: 0,0:11:48.68,0:11:51.12,EN,,0,0,0,,that all of the free memory that there is in the world\nDialogue: 0,0:11:51.55,0:11:53.08,EN,,0,0,0,,is linked together in a linked list,\nDialogue: 0,0:11:54.55,0:11:56.22,EN,,0,0,0,,just like all the other stuff.\nDialogue: 0,0:11:56.96,0:11:59.07,EN,,0,0,0,,And whenever you need a free cell\nDialogue: 0,0:11:59.07,0:12:00.12,EN,,0,0,0,,to make a new cons,\nDialogue: 0,0:12:00.95,0:12:02.26,EN,,0,0,0,,you grab the first one\nDialogue: 0,0:12:02.26,0:12:03.82,EN,,0,0,0,,make the free list be the cdr of it,\nDialogue: 0,0:12:04.32,0:12:05.55,EN,,0,0,0,,and then allocate that.\nDialogue: 0,0:12:06.03,0:12:08.32,EN,,0,0,0,,And so what that looks like is something like this.\nDialogue: 0,0:12:09.53,0:12:13.32,EN,,0,0,0,,Here we have the free list\nDialogue: 0,0:12:13.95,0:12:16.81,EN,,0,0,0,,starting in 6.\nDialogue: 0,0:12:18.51,0:12:23.47,EN,,0,0,0,,And what that is is a pointer-off to say 8.\nDialogue: 0,0:12:24.86,0:12:25.62,EN,,0,0,0,,So what it says is,\nDialogue: 0,0:12:25.62,0:12:26.55,EN,,0,0,0,,this one is free\nDialogue: 0,0:12:26.55,0:12:27.95,EN,,0,0,0,,and the next one is an 8.\nDialogue: 0,0:12:28.87,0:12:29.88,EN,,0,0,0,,This one is free\nDialogue: 0,0:12:30.04,0:12:32.08,EN,,0,0,0,,and the next one is in 3,\nDialogue: 0,0:12:32.32,0:12:33.45,EN,,0,0,0,,the next one that's free.\nDialogue: 0,0:12:33.93,0:12:34.95,EN,,0,0,0,,That one's free\nDialogue: 0,0:12:35.04,0:12:37.68,EN,,0,0,0,,and the next one is in 0.\nDialogue: 0,0:12:37.87,0:12:38.49,EN,,0,0,0,,That one's free\nDialogue: 0,0:12:38.52,0:12:39.82,EN,,0,0,0,,and the next one's in 15.\nDialogue: 0,0:12:40.94,0:12:41.84,EN,,0,0,0,,Something like that.\nDialogue: 0,0:12:42.78,0:12:44.64,EN,,0,0,0,,We can imagine having such a structure.\nDialogue: 0,0:12:46.40,0:12:48.03,EN,,0,0,0,,Given that we have something like that,\nDialogue: 0,0:12:49.45,0:12:50.92,EN,,0,0,0,,then it's possible to\nDialogue: 0,0:12:50.92,0:12:52.22,EN,,0,0,0,,just get one when you need it.\nDialogue: 0,0:12:53.82,0:12:56.46,EN,,0,0,0,,And so a program for doing cons,\nDialogue: 0,0:12:57.45,0:12:59.13,EN,,0,0,0,,this is what cons might turn into.\nDialogue: 0,0:12:59.32,0:13:02.57,EN,,0,0,0,,To assign to a register A the result of cons-ing,\nDialogue: 0,0:13:02.95,0:13:05.82,EN,,0,0,0,,a B onto C,\nDialogue: 0,0:13:06.20,0:13:09.04,EN,,0,0,0,,the value in this containing B and the value containing C,\nDialogue: 0,0:13:09.27,0:13:10.52,EN,,0,0,0,,what we have to do is\nDialogue: 0,0:13:10.56,0:13:12.24,EN,,0,0,0,,get the current tail ahead of the freelist,\nDialogue: 0,0:13:12.47,0:13:14.30,EN,,0,0,0,,make the free list be its cdr.\nDialogue: 0,0:13:15.64,0:13:18.33,EN,,0,0,0,,Then we have to change the cars\nDialogue: 0,0:13:18.41,0:13:22.49,EN,,0,0,0,,to be the thing we're making up to be in A\nDialogue: 0,0:13:23.13,0:13:25.45,EN,,0,0,0,,to be the B, the thing in B.\nDialogue: 0,0:13:25.90,0:13:28.65,EN,,0,0,0,,And we have to make change the cdrs of\nDialogue: 0,0:13:29.20,0:13:31.72,EN,,0,0,0,,the thing that's in A to be C.\nDialogue: 0,0:13:33.20,0:13:34.76,EN,,0,0,0,,And then what we have in A\nDialogue: 0,0:13:34.78,0:13:36.65,EN,,0,0,0,,is the right new frob, whatever it is.\nDialogue: 0,0:13:36.81,0:13:37.92,EN,,0,0,0,,The object that we want.\nDialogue: 0,0:13:40.47,0:13:42.50,EN,,0,0,0,,Now there's a little bit of\nDialogue: 0,0:13:42.50,0:13:43.97,EN,,0,0,0,,a cheat here that I haven't told you about,\nDialogue: 0,0:13:43.97,0:13:45.32,EN,,0,0,0,,which is somewhere around here\nDialogue: 0,0:13:45.53,0:13:47.32,EN,,0,0,0,,I haven't set the type of the thing that I've\nDialogue: 0,0:13:48.45,0:13:50.48,EN,,0,0,0,,the type of the thing\nDialogue: 0,0:13:50.51,0:13:51.87,EN,,0,0,0,,that I'm cons-ing up to be a pair,\nDialogue: 0,0:13:52.30,0:13:53.05,EN,,0,0,0,,and I ought to.\nDialogue: 0,0:13:53.51,0:13:56.57,EN,,0,0,0,,So there should be some sort of bits here are being set,\nDialogue: 0,0:13:56.60,0:13:57.76,EN,,0,0,0,,and I just haven't written that down.\nDialogue: 0,0:13:59.81,0:14:00.86,EN,,0,0,0,,We could have arranged it, of course,\nDialogue: 0,0:14:00.89,0:14:02.45,EN,,0,0,0,,for the free list to be made out of pairs.\nDialogue: 0,0:14:03.10,0:14:04.88,EN,,0,0,0,,And so then there's no problem with that.\nDialogue: 0,0:14:06.43,0:14:07.74,EN,,0,0,0,,But that sort of--\nDialogue: 0,0:14:07.82,0:14:09.92,EN,,0,0,0,,again, an inessential detail in a way\nDialogue: 0,0:14:10.22,0:14:12.88,EN,,0,0,0,,some particular programmer or architect\nDialogue: 0,0:14:12.92,0:14:14.27,EN,,0,0,0,,or whatever might manufacture\nDialogue: 0,0:14:14.33,0:14:16.68,EN,,0,0,0,,his machine or Lisp system.\nDialogue: 0,0:14:17.54,0:14:18.71,EN,,0,0,0,,So for example,\nDialogue: 0,0:14:19.07,0:14:20.24,EN,,0,0,0,,just looking at this,\nDialogue: 0,0:14:20.65,0:14:23.45,EN,,0,0,0,,to allocate\nDialogue: 0,0:14:23.55,0:14:26.83,EN,,0,0,0,,given that I had already the structure that you saw before,\nDialogue: 0,0:14:27.21,0:14:30.26,EN,,0,0,0,,supposing I wanted to allocate a new cell,\nDialogue: 0,0:14:30.55,0:14:36.61,EN,,0,0,0,,which is going to be representation of list one, one, two,\nDialogue: 0,0:14:37.24,0:14:39.87,EN,,0,0,0,,where already one two was the car\nDialogue: 0,0:14:40.28,0:14:42.16,EN,,0,0,0,,of the list we were playing with before.\nDialogue: 0,0:14:43.43,0:14:44.45,EN,,0,0,0,,Well that's not so hard.\nDialogue: 0,0:14:44.78,0:14:46.20,EN,,0,0,0,,I stored that one in one,\nDialogue: 0,0:14:46.20,0:14:49.17,EN,,0,0,0,,so p1 one is the representation of this.\nDialogue: 0,0:14:49.53,0:14:50.83,EN,,0,0,0,,This is p5.\nDialogue: 0,0:14:51.67,0:14:53.51,EN,,0,0,0,,That's going to be the cdr of this.\nDialogue: 0,0:14:54.07,0:14:55.52,EN,,0,0,0,,Now we're going to pull something off the free list,\nDialogue: 0,0:14:55.52,0:14:57.30,EN,,0,0,0,,but remember the free list started at six.\nDialogue: 0,0:14:57.78,0:15:00.18,EN,,0,0,0,,The new free list after this allocation is eight,\nDialogue: 0,0:15:00.60,0:15:02.55,EN,,0,0,0,,a free list beginning at eight.\nDialogue: 0,0:15:02.89,0:15:03.52,EN,,0,0,0,,And of course\nDialogue: 0,0:15:03.72,0:15:06.04,EN,,0,0,0,,in six now we have a number one,\nDialogue: 0,0:15:06.15,0:15:07.10,EN,,0,0,0,,which is what we wanted,\nDialogue: 0,0:15:07.39,0:15:11.56,EN,,0,0,0,,with its cdr being the pair starting in location five.\nDialogue: 0,0:15:13.33,0:15:14.50,EN,,0,0,0,,And that's no big deal.\nDialogue: 0,0:15:16.81,0:15:20.45,EN,,0,0,0,,So the only problem really remaining here is,\nDialogue: 0,0:15:21.00,0:15:23.40,EN,,0,0,0,,well, I don't have an infinitely large memory.\nDialogue: 0,0:15:25.08,0:15:26.66,EN,,0,0,0,,If I do this for a little while,\nDialogue: 0,0:15:27.25,0:15:28.00,EN,,0,0,0,,say, for example,\nDialogue: 0,0:15:28.01,0:15:30.14,EN,,0,0,0,,supposing it takes me a microsecond to do a cons,\nDialogue: 0,0:15:30.60,0:15:32.97,EN,,0,0,0,,and I have a million cons memory\nDialogue: 0,0:15:33.60,0:15:35.27,EN,,0,0,0,,then I'm only going to run out in a second,\nDialogue: 0,0:15:35.95,0:15:37.00,EN,,0,0,0,,and that's pretty bad.\nDialogue: 0,0:15:38.00,0:15:40.62,EN,,0,0,0,,So what we do to prevent that disaster,\nDialogue: 0,0:15:40.62,0:15:42.19,EN,,0,0,0,,that ecological disaster,\nDialogue: 0,0:15:42.60,0:15:44.30,EN,,0,0,0,,talk about right after questions.\nDialogue: 0,0:15:44.30,0:15:45.26,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:15:51.50,0:15:51.69,EN,,0,0,0,,Yes.\nDialogue: 0,0:15:52.03,0:15:54.67,EN,,0,0,0,,AUDIENCE: In the environment diagrams that we were drawing\nDialogue: 0,0:15:54.67,0:15:58.25,EN,,0,0,0,,we would use the body of procedures,\nDialogue: 0,0:15:58.25,0:16:00.67,EN,,0,0,0,,and you would eventually wind up with\nDialogue: 0,0:16:00.80,0:16:03.60,EN,,0,0,0,,things that were no longer useful in that structure.\nDialogue: 0,0:16:03.60,0:16:04.16,EN,,0,0,0,,PROFESSOR: Yes, madam.\nDialogue: 0,0:16:04.93,0:16:06.67,EN,,0,0,0,,AUDIENCE: How is that represented?\nDialogue: 0,0:16:06.76,0:16:08.75,EN,,0,0,0,,PROFESSOR: There's two problems here. OK?\nDialogue: 0,0:16:09.18,0:16:10.25,EN,,0,0,0,,One you were asking\nDialogue: 0,0:16:10.25,0:16:13.43,EN,,0,0,0,,is that material becomes useless.\nDialogue: 0,0:16:13.87,0:16:14.92,EN,,0,0,0,,We'll talk about that in a second.\nDialogue: 0,0:16:14.92,0:16:17.00,EN,,0,0,0,,That has to do with how to prevent ecological disasters.\nDialogue: 0,0:16:17.63,0:16:19.20,EN,,0,0,0,,Right? If I make a lot of garbage\nDialogue: 0,0:16:19.20,0:16:21.39,EN,,0,0,0,,I have to somehow be able to clean up after myself.\nDialogue: 0,0:16:21.82,0:16:22.97,EN,,0,0,0,,And we'll talk about that in a second.\nDialogue: 0,0:16:23.43,0:16:24.57,EN,,0,0,0,,The other question you're asking\nDialogue: 0,0:16:24.57,0:16:27.21,EN,,0,0,0,,is how you represent the environments, I think.\nDialogue: 0,0:16:27.28,0:16:27.60,EN,,0,0,0,,AUDIENCE: Yes.\nDialogue: 0,0:16:27.60,0:16:28.19,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:16:28.19,0:16:30.62,EN,,0,0,0,,And the environment structures can be represented in arbitrary ways.\nDialogue: 0,0:16:30.92,0:16:31.78,EN,,0,0,0,,There are lots of them.\nDialogue: 0,0:16:31.78,0:16:33.34,EN,,0,0,0,,I mean, here I'm just telling you about list cells.\nDialogue: 0,0:16:33.63,0:16:34.92,EN,,0,0,0,,Of course every real system\nDialogue: 0,0:16:34.92,0:16:36.72,EN,,0,0,0,,has vectors of arbitrary length\nDialogue: 0,0:16:36.72,0:16:39.15,EN,,0,0,0,,as well as the vectors of length, too,\nDialogue: 0,0:16:39.31,0:16:40.51,EN,,0,0,0,,which represent list cells.\nDialogue: 0,0:16:41.08,0:16:44.90,EN,,0,0,0,,And the environment structures that one uses in a\nDialogue: 0,0:16:44.90,0:16:46.99,EN,,0,0,0,,professionally written Lisp system\nDialogue: 0,0:16:47.30,0:16:49.69,EN,,0,0,0,,tend to be vectors\nDialogue: 0,0:16:49.69,0:16:51.92,EN,,0,0,0,,which contain a number of elements approximately\nDialogue: 0,0:16:51.92,0:16:54.60,EN,,0,0,0,,equal to the number of arguments-- a little bit more\nDialogue: 0,0:16:55.35,0:16:56.86,EN,,0,0,0,,because you need sort of glue.\nDialogue: 0,0:16:57.40,0:17:00.74,EN,,0,0,0,,OK? So remember, the environment is in a frame.\nDialogue: 0,0:17:00.74,0:17:03.98,EN,,0,0,0,,The frames are constructed by applying a procedure.\nDialogue: 0,0:17:03.98,0:17:04.78,EN,,0,0,0,,In doing so,\nDialogue: 0,0:17:04.80,0:17:07.60,EN,,0,0,0,,an allocation is made of a place\nDialogue: 0,0:17:07.64,0:17:11.27,EN,,0,0,0,,which is the number of arguments long plus some glue\nDialogue: 0,0:17:11.27,0:17:12.71,EN,,0,0,0,,that gets linked into a chain.\nDialogue: 0,0:17:13.32,0:17:15.66,EN,,0,0,0,,It's just like algol at that level.\nDialogue: 0,0:17:19.81,0:17:20.72,EN,,0,0,0,,There any other questions?\nDialogue: 0,0:17:23.70,0:17:23.92,EN,,0,0,0,,OK.\nDialogue: 0,0:17:23.92,0:17:25.55,EN,,0,0,0,,Thank you, and let's take a short break.\nDialogue: 0,0:17:26.35,0:17:45.48,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:17:45.53,0:17:50.01,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:17:55.74,0:17:59.04,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:17:59.13,0:18:04.22,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:18:04.32,0:18:09.87,EN,,0,0,0,,Storage Allocation & Garbage Collection\nDialogue: 0,0:18:12.27,0:18:14.24,EN,,0,0,0,,PROFESSOR: Well, as I just said,\nDialogue: 0,0:18:14.55,0:18:15.50,EN,,0,0,0,,computer memories\nDialogue: 0,0:18:15.82,0:18:17.96,EN,,0,0,0,,supplied by the semiconductor manufacturers\nDialogue: 0,0:18:18.16,0:18:19.00,EN,,0,0,0,,are finite.\nDialogue: 0,0:18:19.42,0:18:20.40,EN,,0,0,0,,And that's quite a pity.\nDialogue: 0,0:18:21.62,0:18:23.35,EN,,0,0,0,,It might not always be that way.\nDialogue: 0,0:18:24.03,0:18:25.40,EN,,0,0,0,,Just for a quick calculation,\nDialogue: 0,0:18:25.44,0:18:28.86,EN,,0,0,0,,you can see that it's possible that if memory's\nDialogue: 0,0:18:28.86,0:18:30.80,EN,,0,0,0,,prices keep going at the rate they're going\nDialogue: 0,0:18:31.22,0:18:33.68,EN,,0,0,0,,that if you still took a microsecond second to do a cons,\nDialogue: 0,0:18:34.42,0:18:35.90,EN,,0,0,0,,then-- first of all, everybody\nDialogue: 0,0:18:35.90,0:18:37.07,EN,,0,0,0,,should know that there's about pi\nDialogue: 0,0:18:37.10,0:18:38.86,EN,,0,0,0,,times ten to the seventh seconds in a year.\nDialogue: 0,0:18:39.45,0:18:41.12,EN,,0,0,0,,And so that would be\nDialogue: 0,0:18:41.50,0:18:42.73,EN,,0,0,0,,ten to the seventh plus ten to the sixth\nDialogue: 0,0:18:42.73,0:18:43.94,EN,,0,0,0,,is ten to the thirteenth.\nDialogue: 0,0:18:43.94,0:18:45.50,EN,,0,0,0,,So there's maybe ten to the fourteenth conses\nDialogue: 0,0:18:45.50,0:18:46.80,EN,,0,0,0,,in the life of a machine.\nDialogue: 0,0:18:47.52,0:18:49.40,EN,,0,0,0,,If there was ten to the fourteenth words of memory\nDialogue: 0,0:18:49.68,0:18:50.57,EN,,0,0,0,,on your machine,\nDialogue: 0,0:18:51.20,0:18:52.16,EN,,0,0,0,,you'd never run out.\nDialogue: 0,0:18:53.04,0:18:53.85,EN,,0,0,0,,OK so that will be,\nDialogue: 0,0:18:53.95,0:18:55.76,EN,,0,0,0,,And that's not completely unreasonable.\nDialogue: 0,0:18:56.31,0:18:58.46,EN,,0,0,0,,Ten to the fourteenth is not a very large number.\nDialogue: 0,0:19:01.45,0:19:04.70,EN,,0,0,0,,Even for... I don't think it is.\nDialogue: 0,0:19:05.18,0:19:07.39,EN,,0,0,0,,But then again I like to play with astronomy.\nDialogue: 0,0:19:07.93,0:19:11.04,EN,,0,0,0,,It's at least ten to the eighteenth centimeters\nDialogue: 0,0:19:11.10,0:19:12.45,EN,,0,0,0,,between us and the nearest star.\nDialogue: 0,0:19:12.93,0:19:18.85,EN,,0,0,0,,But the thing I'm about to worry about is,\nDialogue: 0,0:19:19.15,0:19:21.27,EN,,0,0,0,,at least in the current economic state of affairs,\nDialogue: 0,0:19:21.27,0:19:23.57,EN,,0,0,0,,ten to the fourteenth pieces of memory is expensive.\nDialogue: 0,0:19:24.20,0:19:26.62,EN,,0,0,0,,And so I suppose what we have to do\nDialogue: 0,0:19:26.81,0:19:28.51,EN,,0,0,0,,is make do with much smaller memories.\nDialogue: 0,0:19:30.02,0:19:30.59,EN,,0,0,0,,Now\nDialogue: 0,0:19:32.84,0:19:35.07,EN,,0,0,0,,in general we want to have an illusion of infinity.\nDialogue: 0,0:19:35.80,0:19:37.22,EN,,0,0,0,,All we need to do is arrange it\nDialogue: 0,0:19:37.82,0:19:39.68,EN,,0,0,0,,so that whenever you look, the thing is there.\nDialogue: 0,0:19:41.92,0:19:45.55,EN,,0,0,0,,That's, that's really an important idea.\nDialogue: 0,0:19:49.54,0:19:51.97,EN,,0,0,0,,A person or a computer lives only a finite amount of time\nDialogue: 0,0:19:52.32,0:19:54.59,EN,,0,0,0,,and can only take a finite number of looks at something.\nDialogue: 0,0:19:55.28,0:19:57.37,EN,,0,0,0,,And so you really only need a finite amount of stuff.\nDialogue: 0,0:19:58.19,0:19:59.00,EN,,0,0,0,,But you have to arrange it\nDialogue: 0,0:19:59.00,0:20:00.38,EN,,0,0,0,,so no matter how much there is,\nDialogue: 0,0:20:00.77,0:20:03.46,EN,,0,0,0,,how much you really claim there is,\nDialogue: 0,0:20:03.46,0:20:04.74,EN,,0,0,0,,there's always enough stuff\nDialogue: 0,0:20:04.74,0:20:06.90,EN,,0,0,0,,so that when you take a look, it's there.\nDialogue: 0,0:20:06.90,0:20:08.15,EN,,0,0,0,,And so you only need a finite amount.\nDialogue: 0,0:20:08.75,0:20:09.94,EN,,0,0,0,,But let's see.\nDialogue: 0,0:20:11.63,0:20:13.32,EN,,0,0,0,,One problem is, as was brought up,\nDialogue: 0,0:20:13.92,0:20:15.45,EN,,0,0,0,,that there are possible ways\nDialogue: 0,0:20:15.72,0:20:17.84,EN,,0,0,0,,that there is lots of stuff\nDialogue: 0,0:20:17.88,0:20:19.16,EN,,0,0,0,,that we make that we don't need.\nDialogue: 0,0:20:19.41,0:20:21.81,EN,,0,0,0,,And we could recycle the material out of which its made.\nDialogue: 0,0:20:22.62,0:20:23.53,EN,,0,0,0,,An example\nDialogue: 0,0:20:24.15,0:20:25.79,EN,,0,0,0,,for is, is the fact\nDialogue: 0,0:20:25.79,0:20:28.40,EN,,0,0,0,,when we're building environment structures,\nDialogue: 0,0:20:28.40,0:20:30.47,EN,,0,0,0,,and we do so every time we call a procedure.\nDialogue: 0,0:20:30.47,0:20:32.56,EN,,0,0,0,,We have built in it a environment frame.\nDialogue: 0,0:20:33.14,0:20:34.03,EN,,0,0,0,,That environment frame\nDialogue: 0,0:20:34.22,0:20:36.07,EN,,0,0,0,,doesn't necessarily have a very long lifetime.\nDialogue: 0,0:20:36.73,0:20:38.69,EN,,0,0,0,,Its lifetime, meaning its usefulness,\nDialogue: 0,0:20:39.42,0:20:42.60,EN,,0,0,0,,may exist only over the invocation of the procedure.\nDialogue: 0,0:20:42.85,0:20:45.27,EN,,0,0,0,,Or if the procedure exports another procedure\nDialogue: 0,0:20:45.27,0:20:46.67,EN,,0,0,0,,by returning it as a value\nDialogue: 0,0:20:46.87,0:20:48.52,EN,,0,0,0,,and that procedure is defined inside of it,\nDialogue: 0,0:20:48.52,0:20:50.80,EN,,0,0,0,,well then the lifetime of the\nDialogue: 0,0:20:51.07,0:20:53.39,EN,,0,0,0,,frame of the outer procedure still is\nDialogue: 0,0:20:53.50,0:20:56.12,EN,,0,0,0,,only the lifetime of the procedure\nDialogue: 0,0:20:57.02,0:20:57.90,EN,,0,0,0,,which was exported.\nDialogue: 0,0:20:58.53,0:20:59.57,EN,,0,0,0,,And so ultimately,\nDialogue: 0,0:20:59.57,0:21:00.97,EN,,0,0,0,,a lot of that is garbage.\nDialogue: 0,0:21:01.96,0:21:04.10,EN,,0,0,0,,There are other ways of producing garbage as well.\nDialogue: 0,0:21:05.37,0:21:06.67,EN,,0,0,0,,Users produce garbage.\nDialogue: 0,0:21:07.24,0:21:08.07,EN,,0,0,0,,An example of\nDialogue: 0,0:21:08.07,0:21:10.22,EN,,0,0,0,,user garbage is something like this.\nDialogue: 0,0:21:10.93,0:21:14.00,EN,,0,0,0,,If we write a program to, for example,\nDialogue: 0,0:21:14.00,0:21:15.80,EN,,0,0,0,,append two lists together,\nDialogue: 0,0:21:16.05,0:21:18.14,EN,,0,0,0,,well one way to do it is to\nDialogue: 0,0:21:18.32,0:21:21.37,EN,,0,0,0,,reverse the first list onto the empty list\nDialogue: 0,0:21:21.37,0:21:23.72,EN,,0,0,0,,and reverse that onto the second list.\nDialogue: 0,0:21:24.70,0:21:26.92,EN,,0,0,0,,Now that's not terribly bad way of doing it.\nDialogue: 0,0:21:28.16,0:21:28.85,EN,,0,0,0,,And however,\nDialogue: 0,0:21:28.85,0:21:30.09,EN,,0,0,0,,the intermediate result,\nDialogue: 0,0:21:30.11,0:21:32.02,EN,,0,0,0,,which is the reversal of the first list\nDialogue: 0,0:21:33.87,0:21:35.57,EN,,0,0,0,,as done by this program,\nDialogue: 0,0:21:36.70,0:21:38.52,EN,,0,0,0,,is never going to be accessed ever again\nDialogue: 0,0:21:38.52,0:21:40.56,EN,,0,0,0,,after it's copied back on to the second.\nDialogue: 0,0:21:41.01,0:21:42.23,EN,,0,0,0,,It's an intermediate result.\nDialogue: 0,0:21:43.58,0:21:45.43,EN,,0,0,0,,It's going to be hard to ever see\nDialogue: 0,0:21:46.07,0:21:48.05,EN,,0,0,0,,how anybody would ever be able to access it.\nDialogue: 0,0:21:48.60,0:21:49.84,EN,,0,0,0,,In fact, it will go away.\nDialogue: 0,0:21:51.05,0:21:52.90,EN,,0,0,0,,Now if we make a lot of garbage like that,\nDialogue: 0,0:21:52.90,0:21:54.20,EN,,0,0,0,,and we should be allowed to,\nDialogue: 0,0:21:54.80,0:21:57.29,EN,,0,0,0,,then there's got to be some way to reclaim that garbage.\nDialogue: 0,0:21:58.80,0:22:00.90,EN,,0,0,0,,Well, what I'd like to tell you about now\nDialogue: 0,0:22:01.70,0:22:03.77,EN,,0,0,0,,is a very clever technique\nDialogue: 0,0:22:04.32,0:22:07.58,EN,,0,0,0,,whereby a Lisp system\nDialogue: 0,0:22:07.95,0:22:11.21,EN,,0,0,0,,can prove a small theorem every so often\nDialogue: 0,0:22:11.29,0:22:13.50,EN,,0,0,0,,on the form the following piece of junk\nDialogue: 0,0:22:14.72,0:22:16.09,EN,,0,0,0,,will never be accessed again.\nDialogue: 0,0:22:17.41,0:22:19.80,EN,,0,0,0,,It can have no affect on the future of the computation.\nDialogue: 0,0:22:21.40,0:22:23.61,EN,,0,0,0,,It's actually based on a very simple idea.\nDialogue: 0,0:22:24.72,0:22:28.06,EN,,0,0,0,,We've designed our computers to look sort of like this.\nDialogue: 0,0:22:28.95,0:22:30.67,EN,,0,0,0,,There's some data path,\nDialogue: 0,0:22:31.87,0:22:33.40,EN,,0,0,0,,which contains the registers.\nDialogue: 0,0:22:34.92,0:22:38.04,EN,,0,0,0,,You know, there are things like exp, and env,\nDialogue: 0,0:22:39.04,0:22:42.19,EN,,0,0,0,,and val, and so on.\nDialogue: 0,0:22:42.61,0:22:44.02,EN,,0,0,0,,And there's one here called stack,\nDialogue: 0,0:22:46.02,0:22:49.45,EN,,0,0,0,,some sort which points off to a structure somewhere,\nDialogue: 0,0:22:49.50,0:22:50.22,EN,,0,0,0,,which is the stack.\nDialogue: 0,0:22:50.24,0:22:51.48,EN,,0,0,0,,And we'll worry about that in a second.\nDialogue: 0,0:22:51.64,0:22:53.62,EN,,0,0,0,,There's some finite controller,\nDialogue: 0,0:22:54.38,0:22:56.57,EN,,0,0,0,,finite state machine controller.\nDialogue: 0,0:22:56.73,0:22:59.51,EN,,0,0,0,,And there's some control signals that go this way and\nDialogue: 0,0:22:59.80,0:23:01.44,EN,,0,0,0,,predicate results that come this way,\nDialogue: 0,0:23:01.87,0:23:03.13,EN,,0,0,0,,not the interesting part.\nDialogue: 0,0:23:03.35,0:23:06.51,EN,,0,0,0,,There's some sort of structured memory,\nDialogue: 0,0:23:06.80,0:23:08.27,EN,,0,0,0,,which I just told you how to make,\nDialogue: 0,0:23:08.27,0:23:10.17,EN,,0,0,0,,which may contain a stack.\nDialogue: 0,0:23:10.46,0:23:11.48,EN,,0,0,0,,I didn't tell you how to make things\nDialogue: 0,0:23:11.48,0:23:12.43,EN,,0,0,0,,of arbitrary shape,\nDialogue: 0,0:23:12.56,0:23:13.39,EN,,0,0,0,,only pairs.\nDialogue: 0,0:23:13.60,0:23:14.20,EN,,0,0,0,,But in fact\nDialogue: 0,0:23:14.35,0:23:15.44,EN,,0,0,0,,with what I've told you can\nDialogue: 0,0:23:15.47,0:23:16.96,EN,,0,0,0,,with what I've told you can simulate a stack by a big list.\nDialogue: 0,0:23:17.77,0:23:18.85,EN,,0,0,0,,I don't plan to do that,\nDialogue: 0,0:23:18.85,0:23:20.01,EN,,0,0,0,,it's not a nice way to do it.\nDialogue: 0,0:23:20.36,0:23:22.60,EN,,0,0,0,,But we could have something like that.\nDialogue: 0,0:23:22.99,0:23:25.28,EN,,0,0,0,,We have all sorts of little data structures in here\nDialogue: 0,0:23:25.64,0:23:27.75,EN,,0,0,0,,that are hooked together in funny ways.\nDialogue: 0,0:23:30.11,0:23:32.02,EN,,0,0,0,,They connect to other things.\nDialogue: 0,0:23:32.56,0:23:33.25,EN,,0,0,0,,And so on.\nDialogue: 0,0:23:33.25,0:23:34.22,EN,,0,0,0,,And ultimately\nDialogue: 0,0:23:34.45,0:23:37.19,EN,,0,0,0,,things up there are pointers to these.\nDialogue: 0,0:23:37.19,0:23:38.87,EN,,0,0,0,,The things that are in the registers\nDialogue: 0,0:23:39.40,0:23:41.40,EN,,0,0,0,,are pointers off to the data structures\nDialogue: 0,0:23:41.44,0:23:43.08,EN,,0,0,0,,that live in this list structure memory.\nDialogue: 0,0:23:44.91,0:23:49.80,EN,,0,0,0,,Now the truth of the matter is\nDialogue: 0,0:23:51.05,0:23:52.56,EN,,0,0,0,,that the entire consciousness\nDialogue: 0,0:23:52.57,0:23:53.92,EN,,0,0,0,,of this machine is in these registers.\nDialogue: 0,0:23:55.76,0:23:58.51,EN,,0,0,0,,There is no possible way that the machine,\nDialogue: 0,0:23:58.75,0:24:01.07,EN,,0,0,0,,if done correctly, if built correctly,\nDialogue: 0,0:24:01.37,0:24:03.41,EN,,0,0,0,,can access anything in this list structure memory\nDialogue: 0,0:24:04.57,0:24:07.05,EN,,0,0,0,,unless the thing in that list structure memory is\nDialogue: 0,0:24:08.09,0:24:10.88,EN,,0,0,0,,is connected by a sequence of data structures\nDialogue: 0,0:24:11.64,0:24:13.06,EN,,0,0,0,,to the registers.\nDialogue: 0,0:24:15.07,0:24:15.98,EN,,0,0,0,,If it's accessible\nDialogue: 0,0:24:16.22,0:24:18.31,EN,,0,0,0,,by legitimate data structure selectors\nDialogue: 0,0:24:19.08,0:24:21.12,EN,,0,0,0,,from the pointers that are stored in these registers.\nDialogue: 0,0:24:22.28,0:24:24.46,EN,,0,0,0,,Things like array references, perhaps.\nDialogue: 0,0:24:24.94,0:24:27.92,EN,,0,0,0,,Or cons cell references, cars and cdrs.\nDialogue: 0,0:24:29.08,0:24:30.95,EN,,0,0,0,,But I can't just talk about a random place in this memory,\nDialogue: 0,0:24:30.95,0:24:31.95,EN,,0,0,0,,because I can't get to it.\nDialogue: 0,0:24:32.74,0:24:34.90,EN,,0,0,0,,These are being arbitrary names I'm not allowed to count,\nDialogue: 0,0:24:37.00,0:24:39.16,EN,,0,0,0,,at least as I'm evaluating expressions.\nDialogue: 0,0:24:41.62,0:24:42.57,EN,,0,0,0,,If that's the case\nDialogue: 0,0:24:43.27,0:24:45.07,EN,,0,0,0,,then there's a very simple theorem to be proved.\nDialogue: 0,0:24:47.16,0:24:47.69,EN,,0,0,0,,Which is,\nDialogue: 0,0:24:47.90,0:24:50.52,EN,,0,0,0,,if I start with all lead pointers that are in all these registers\nDialogue: 0,0:24:51.16,0:24:52.55,EN,,0,0,0,,and recursively chase out,\nDialogue: 0,0:24:52.82,0:24:56.15,EN,,0,0,0,,marking all the places I can get to by selectors,\nDialogue: 0,0:24:56.90,0:24:59.40,EN,,0,0,0,,then eventually I mark everything they can be gotten to.\nDialogue: 0,0:25:00.65,0:25:02.69,EN,,0,0,0,,Anything which is not so marked is garbage\nDialogue: 0,0:25:02.69,0:25:03.75,EN,,0,0,0,,and can be recycled.\nDialogue: 0,0:25:05.56,0:25:06.20,EN,,0,0,0,,Very simple.\nDialogue: 0,0:25:07.20,0:25:09.10,EN,,0,0,0,,Cannot affect the future of the computation.\nDialogue: 0,0:25:11.18,0:25:12.84,EN,,0,0,0,,So let me show you that in a particular\nDialogue: 0,0:25:13.93,0:25:15.75,EN,,0,0,0,,in a particular example.\nDialogue: 0,0:25:17.12,0:25:19.37,EN,,0,0,0,,Now that means I'm going to have to append to my\nDialogue: 0,0:25:19.69,0:25:22.08,EN,,0,0,0,,description of the list structure a mark.\nDialogue: 0,0:25:23.64,0:25:24.89,EN,,0,0,0,,And so here, for example,\nDialogue: 0,0:25:25.37,0:25:27.28,EN,,0,0,0,,is a list structured memory.\nDialogue: 0,0:25:29.08,0:25:30.32,EN,,0,0,0,,And in this list structured memory\nDialogue: 0,0:25:30.33,0:25:31.33,EN,,0,0,0,,is a list structure\nDialogue: 0,0:25:31.33,0:25:33.95,EN,,0,0,0,,beginning in a place I'm going to call--\nDialogue: 0,0:25:35.87,0:25:36.62,EN,,0,0,0,,this is the root.\nDialogue: 0,0:25:38.59,0:25:40.12,EN,,0,0,0,,Now it doesn't really have to have a root.\nDialogue: 0,0:25:40.12,0:25:41.95,EN,,0,0,0,,It could be a bunch of them, like all the registers.\nDialogue: 0,0:25:42.67,0:25:43.98,EN,,0,0,0,,But I could cleverly arrange it\nDialogue: 0,0:25:44.13,0:25:46.30,EN,,0,0,0,,so all the registers, all the things that are in old registers\nDialogue: 0,0:25:46.30,0:25:47.77,EN,,0,0,0,,are also at the right moment\nDialogue: 0,0:25:48.28,0:25:50.46,EN,,0,0,0,,put into this root structure,\nDialogue: 0,0:25:50.46,0:25:51.85,EN,,0,0,0,,and then we've got one pointer to it.\nDialogue: 0,0:25:51.85,0:25:52.67,EN,,0,0,0,,I don't really care.\nDialogue: 0,0:25:54.57,0:25:55.63,EN,,0,0,0,,So the idea is\nDialogue: 0,0:25:55.64,0:25:56.65,EN,,0,0,0,,we're going to cons up stuff\nDialogue: 0,0:25:56.67,0:25:58.01,EN,,0,0,0,,until our free list is empty.\nDialogue: 0,0:25:58.72,0:25:59.67,EN,,0,0,0,,We've run out of things.\nDialogue: 0,0:26:00.95,0:26:04.47,EN,,0,0,0,,Now we're going to do this process of proving the theorem\nDialogue: 0,0:26:04.47,0:26:05.90,EN,,0,0,0,,that a certain percentage of the memory\nDialogue: 0,0:26:05.95,0:26:06.90,EN,,0,0,0,,is got crap in it.\nDialogue: 0,0:26:07.85,0:26:09.15,EN,,0,0,0,,And then we're going to recycle that\nDialogue: 0,0:26:09.78,0:26:10.87,EN,,0,0,0,,to grow new trees,\nDialogue: 0,0:26:12.19,0:26:14.57,EN,,0,0,0,,a standard use of such garbage.\nDialogue: 0,0:26:17.09,0:26:18.64,EN,,0,0,0,,So in any case, what do we have here?\nDialogue: 0,0:26:18.84,0:26:20.78,EN,,0,0,0,,Well we have some data structure\nDialogue: 0,0:26:20.89,0:26:24.27,EN,,0,0,0,,which starts out over here in p5.\nDialogue: 0,0:26:25.15,0:26:26.75,EN,,0,0,0,,Sorry, and it will start at one\nDialogue: 0,0:26:27.27,0:26:28.51,EN,,0,0,0,,And in fact\nDialogue: 0,0:26:28.89,0:26:32.20,EN,,0,0,0,,it has a car in p5,\nDialogue: 0,0:26:32.27,0:26:33.58,EN,,0,0,0,,and its cdr is in two.\nDialogue: 0,0:26:33.98,0:26:35.64,EN,,0,0,0,,And all the marks start out at zero.\nDialogue: 0,0:26:36.70,0:26:39.00,EN,,0,0,0,,Well let's start marking, just to play this game.\nDialogue: 0,0:26:39.92,0:26:40.52,EN,,0,0,0,,OK.\nDialogue: 0,0:26:42.54,0:26:44.27,EN,,0,0,0,,So for example,\nDialogue: 0,0:26:44.47,0:26:46.95,EN,,0,0,0,,since I can access one from the root\nDialogue: 0,0:26:46.95,0:26:47.82,EN,,0,0,0,,I will mark that.\nDialogue: 0,0:26:48.39,0:26:49.17,EN,,0,0,0,,Let me mark it.\nDialogue: 0,0:26:50.96,0:26:51.45,EN,,0,0,0,,Bang.\nDialogue: 0,0:26:52.22,0:26:52.94,EN,,0,0,0,,That's marked.\nDialogue: 0,0:26:54.41,0:26:57.51,EN,,0,0,0,,OK. Now since I have a five here\nDialogue: 0,0:26:57.64,0:26:58.64,EN,,0,0,0,,I can go to five\nDialogue: 0,0:26:59.02,0:27:00.72,EN,,0,0,0,,and see, well I'll mark that.\nDialogue: 0,0:27:01.45,0:27:01.76,EN,,0,0,0,,Bang.\nDialogue: 0,0:27:01.76,0:27:02.60,EN,,0,0,0,,That's useful stuff.\nDialogue: 0,0:27:02.90,0:27:05.10,EN,,0,0,0,,But five references as a number in its car,\nDialogue: 0,0:27:05.27,0:27:06.65,EN,,0,0,0,,I'm not interested in marking numbers\nDialogue: 0,0:27:06.91,0:27:08.17,EN,,0,0,0,,but its cdr is seven.\nDialogue: 0,0:27:08.70,0:27:09.75,EN,,0,0,0,,So I can mark that.\nDialogue: 0,0:27:10.45,0:27:10.81,EN,,0,0,0,,Bang.\nDialogue: 0,0:27:11.80,0:27:13.40,EN,,0,0,0,,OK? Seven is the empty list,\nDialogue: 0,0:27:13.67,0:27:15.10,EN,,0,0,0,,the only thing that references,\nDialogue: 0,0:27:15.59,0:27:17.12,EN,,0,0,0,,and it's got a number in its car.\nDialogue: 0,0:27:17.12,0:27:17.85,EN,,0,0,0,,Not interesting.\nDialogue: 0,0:27:19.49,0:27:20.50,EN,,0,0,0,,Well now let's go back here.\nDialogue: 0,0:27:20.50,0:27:21.65,EN,,0,0,0,,I forgot about something.\nDialogue: 0,0:27:21.65,0:27:22.17,EN,,0,0,0,,Two.\nDialogue: 0,0:27:22.84,0:27:24.85,EN,,0,0,0,,See in other words, if I'm looking at cell one,\nDialogue: 0,0:27:25.42,0:27:29.45,EN,,0,0,0,,cell one contains a two right over here.\nDialogue: 0,0:27:30.37,0:27:31.30,EN,,0,0,0,,A reference to two.\nDialogue: 0,0:27:32.01,0:27:34.97,EN,,0,0,0,,That means I should go mark two.\nDialogue: 0,0:27:35.70,0:27:36.27,EN,,0,0,0,,Bang.\nDialogue: 0,0:27:37.14,0:27:38.89,EN,,0,0,0,,Two contains a reference to four.\nDialogue: 0,0:27:39.13,0:27:40.27,EN,,0,0,0,,It's got a number in its car,\nDialogue: 0,0:27:40.27,0:27:41.20,EN,,0,0,0,,I'm not interested in that\nDialogue: 0,0:27:41.47,0:27:42.60,EN,,0,0,0,,so I'm going to go mark that.\nDialogue: 0,0:27:43.78,0:27:46.10,EN,,0,0,0,,Four refers to seven through its car,\nDialogue: 0,0:27:46.75,0:27:48.17,EN,,0,0,0,,and is empty in its cdr,\nDialogue: 0,0:27:48.47,0:27:49.57,EN,,0,0,0,,but I've already marked that one\nDialogue: 0,0:27:49.57,0:27:50.75,EN,,0,0,0,,so I don't have to mark it again.\nDialogue: 0,0:27:51.40,0:27:53.05,EN,,0,0,0,,This is all the accessible structure\nDialogue: 0,0:27:53.07,0:27:53.87,EN,,0,0,0,,from that place.\nDialogue: 0,0:27:55.00,0:27:56.57,EN,,0,0,0,,Simple recursive mark algorithm.\nDialogue: 0,0:27:58.71,0:28:01.79,EN,,0,0,0,,Now there are some unhappinesses about that algorithm,\nDialogue: 0,0:28:01.90,0:28:04.02,EN,,0,0,0,,and we can worry about that a second.\nDialogue: 0,0:28:04.92,0:28:06.16,EN,,0,0,0,,But basically you'll see\nDialogue: 0,0:28:06.19,0:28:07.85,EN,,0,0,0,,that all the things that have not been marked\nDialogue: 0,0:28:09.62,0:28:11.50,EN,,0,0,0,,are places that are free,\nDialogue: 0,0:28:11.50,0:28:12.41,EN,,0,0,0,,and I could recycle.\nDialogue: 0,0:28:14.25,0:28:15.75,EN,,0,0,0,,So the next stage after that is going to be\nDialogue: 0,0:28:15.75,0:28:17.05,EN,,0,0,0,,to scan through all of my memory,\nDialogue: 0,0:28:17.94,0:28:20.35,EN,,0,0,0,,looking for things that are not marked.\nDialogue: 0,0:28:21.18,0:28:22.45,EN,,0,0,0,,Every time I come across a marked thing\nDialogue: 0,0:28:22.45,0:28:23.22,EN,,0,0,0,,I unmark it,\nDialogue: 0,0:28:23.22,0:28:24.86,EN,,0,0,0,,and every time I come across an unmarked thing\nDialogue: 0,0:28:25.07,0:28:27.82,EN,,0,0,0,,I'm going to link it together in my free list.\nDialogue: 0,0:28:28.77,0:28:30.30,EN,,0,0,0,,Classic, very simple algorithm.\nDialogue: 0,0:28:32.12,0:28:33.10,EN,,0,0,0,,So let's see.\nDialogue: 0,0:28:33.84,0:28:34.77,EN,,0,0,0,,Is that very simple?\nDialogue: 0,0:28:34.77,0:28:35.42,EN,,0,0,0,,Yes it is.\nDialogue: 0,0:28:35.57,0:28:37.79,EN,,0,0,0,,I'm not going to go through the code in any detail,\nDialogue: 0,0:28:38.00,0:28:39.65,EN,,0,0,0,,but I just want to show you about how long it is.\nDialogue: 0,0:28:40.09,0:28:41.10,EN,,0,0,0,,Let's look at the mark phase.\nDialogue: 0,0:28:41.72,0:28:43.98,EN,,0,0,0,,Here's the first part of the mark phase.\nDialogue: 0,0:28:45.06,0:28:46.00,EN,,0,0,0,,We pick up the root.\nDialogue: 0,0:28:46.32,0:28:47.52,EN,,0,0,0,,We're going to do some\nDialogue: 0,0:28:47.67,0:28:51.05,EN,,0,0,0,,We're going to use that as a recursive procedure call.\nDialogue: 0,0:28:52.38,0:28:54.47,EN,,0,0,0,,We're going to sweep from there,\nDialogue: 0,0:28:54.77,0:28:56.95,EN,,0,0,0,,after when we're done with marking.\nDialogue: 0,0:28:57.38,0:28:59.79,EN,,0,0,0,,And then we're going to do a little couple of instructions\nDialogue: 0,0:28:59.80,0:29:01.36,EN,,0,0,0,,that do this checking out on the marks\nDialogue: 0,0:29:01.39,0:29:03.07,EN,,0,0,0,,and changing the marks and things like that,\nDialogue: 0,0:29:03.07,0:29:04.90,EN,,0,0,0,,according to the algorithm I've just shown you.\nDialogue: 0,0:29:05.23,0:29:06.47,EN,,0,0,0,,OK? It comes out here.\nDialogue: 0,0:29:06.47,0:29:07.65,EN,,0,0,0,,You have to mark the cars of things\nDialogue: 0,0:29:07.87,0:29:10.21,EN,,0,0,0,,and you also have to be able to mark the cdrs of things.\nDialogue: 0,0:29:10.66,0:29:12.10,EN,,0,0,0,,That's the entire mark phase.\nDialogue: 0,0:29:14.37,0:29:16.16,EN,,0,0,0,,I'll just tell you a little story about this.\nDialogue: 0,0:29:16.59,0:29:19.37,EN,,0,0,0,,The old DEC PDP-6 computer,\nDialogue: 0,0:29:20.93,0:29:22.09,EN,,0,0,0,,this was the way that\nDialogue: 0,0:29:22.35,0:29:24.85,EN,,0,0,0,,the mark-sweep garbage collection, as it was, was written.\nDialogue: 0,0:29:26.91,0:29:28.40,EN,,0,0,0,,The program was so small\nDialogue: 0,0:29:29.25,0:29:31.60,EN,,0,0,0,,that with the data that it needed,\nDialogue: 0,0:29:32.20,0:29:34.87,EN,,0,0,0,,with the registers that it needed to manipulate the memory,\nDialogue: 0,0:29:36.16,0:29:38.14,EN,,0,0,0,,it fit into the fast registers of the machine,\nDialogue: 0,0:29:38.16,0:29:38.97,EN,,0,0,0,,which were 16.\nDialogue: 0,0:29:39.28,0:29:39.80,EN,,0,0,0,,The whole program.\nDialogue: 0,0:29:40.01,0:29:42.01,EN,,0,0,0,,And you could execute instructions in the fast registers.\nDialogue: 0,0:29:43.17,0:29:44.83,EN,,0,0,0,,So it's an extremely small program,\nDialogue: 0,0:29:45.85,0:29:46.88,EN,,0,0,0,,and it could run very fast.\nDialogue: 0,0:29:48.87,0:29:51.30,EN,,0,0,0,,Now unfortunately, of course,\nDialogue: 0,0:29:51.61,0:29:54.02,EN,,0,0,0,,this program, because the fact that it's recursive\nDialogue: 0,0:29:54.80,0:29:57.55,EN,,0,0,0,,in the way that you do something first\nDialogue: 0,0:29:57.55,0:29:58.99,EN,,0,0,0,,and then you do something after that,\nDialogue: 0,0:29:59.21,0:30:00.88,EN,,0,0,0,,you have to work on the cars and then the cdrs,\nDialogue: 0,0:30:01.15,0:30:02.75,EN,,0,0,0,,it requires auxiliary memory.\nDialogue: 0,0:30:03.41,0:30:05.23,EN,,0,0,0,,So Lisp systems--\nDialogue: 0,0:30:05.44,0:30:07.42,EN,,0,0,0,,those requires a stack for marking.\nDialogue: 0,0:30:08.26,0:30:11.05,EN,,0,0,0,,Lisp systems that are built this way\nDialogue: 0,0:30:11.57,0:30:14.16,EN,,0,0,0,,have a limit to the depth of recursion you can have\nDialogue: 0,0:30:14.42,0:30:17.37,EN,,0,0,0,,in data structures in either the car or the cdr,\nDialogue: 0,0:30:17.81,0:30:19.35,EN,,0,0,0,,and that doesn't work very nicely.\nDialogue: 0,0:30:19.93,0:30:20.60,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:30:20.64,0:30:22.12,EN,,0,0,0,,you never notice it if it's big enough.\nDialogue: 0,0:30:23.18,0:30:25.13,EN,,0,0,0,,And that's certainly been\nDialogue: 0,0:30:25.55,0:30:28.17,EN,,0,0,0,,the case for most Maclisp, for example,\nDialogue: 0,0:30:28.69,0:30:29.88,EN,,0,0,0,,which ran Macsyma\nDialogue: 0,0:30:29.96,0:30:31.10,EN,,0,0,0,,where you could deal with expressions\nDialogue: 0,0:30:31.10,0:30:32.72,EN,,0,0,0,,of thousands of elements long.\nDialogue: 0,0:30:33.56,0:30:36.02,EN,,0,0,0,,These are algebraic expressions with thousand of terms.\nDialogue: 0,0:30:36.82,0:30:38.10,EN,,0,0,0,,And there's no problem with that.\nDialogue: 0,0:30:39.49,0:30:40.82,EN,,0,0,0,,Such, the garbage collector does work.\nDialogue: 0,0:30:42.19,0:30:42.92,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:30:42.92,0:30:45.37,EN,,0,0,0,,there's a very clever modification to this algorithm,\nDialogue: 0,0:30:45.37,0:30:46.47,EN,,0,0,0,,which I will not describe,\nDialogue: 0,0:30:46.80,0:30:48.22,EN,,0,0,0,,by Peter Deutsch and Schorr and Waite--\nDialogue: 0,0:30:48.64,0:30:51.82,EN,,0,0,0,,and Schorr and Waite, Herb Schorr from IBM\nDialogue: 0,0:30:51.87,0:30:53.52,EN,,0,0,0,,and Waite who I don't know.\nDialogue: 0,0:30:54.01,0:30:56.51,EN,,0,0,0,,Whrere... That algorithm\nDialogue: 0,0:30:56.67,0:30:57.79,EN,,0,0,0,,allows you build\nDialogue: 0,0:30:57.84,0:30:59.55,EN,,0,0,0,,you do can do this without auxiliary memory,\nDialogue: 0,0:31:00.50,0:31:02.80,EN,,0,0,0,,by remembering as you walk the data structures\nDialogue: 0,0:31:02.97,0:31:05.52,EN,,0,0,0,,where you came from by reversing the pointers as you go down\nDialogue: 0,0:31:05.52,0:31:07.52,EN,,0,0,0,,and crawling up the reverse pointers as you go up.\nDialogue: 0,0:31:07.79,0:31:08.99,EN,,0,0,0,,It's a rather tricky algorithm.\nDialogue: 0,0:31:09.13,0:31:10.24,EN,,0,0,0,,The first time you write it--\nDialogue: 0,0:31:10.25,0:31:11.71,EN,,0,0,0,,or in fact, the first three times you write it it\nDialogue: 0,0:31:11.71,0:31:12.72,EN,,0,0,0,,it has a terrible bug in it.\nDialogue: 0,0:31:14.35,0:31:16.72,EN,,0,0,0,,And it's also about, it's quite rather slow,\nDialogue: 0,0:31:16.72,0:31:17.67,EN,,0,0,0,,because it's complicated.\nDialogue: 0,0:31:18.11,0:31:20.30,EN,,0,0,0,,It takes about six times as many memory references\nDialogue: 0,0:31:20.85,0:31:23.22,EN,,0,0,0,,to do the sorts of things that we're talking about.\nDialogue: 0,0:31:24.58,0:31:27.07,EN,,0,0,0,,Well now once I've done this marking phase,\nDialogue: 0,0:31:27.50,0:31:30.12,EN,,0,0,0,,and I get into a position where things look like this,\nDialogue: 0,0:31:30.17,0:31:31.26,EN,,0,0,0,,let's look-- yes.\nDialogue: 0,0:31:31.51,0:31:34.03,EN,,0,0,0,,Here we have the mark done,\nDialogue: 0,0:31:34.08,0:31:35.00,EN,,0,0,0,,just as I did it.\nDialogue: 0,0:31:35.59,0:31:37.33,EN,,0,0,0,,Now we have to perform the sweep phase.\nDialogue: 0,0:31:37.60,0:31:39.32,EN,,0,0,0,,And I described to you what this sweep is like.\nDialogue: 0,0:31:39.82,0:31:42.34,EN,,0,0,0,,I'm going to walk down from one end of memory or the other,\nDialogue: 0,0:31:42.34,0:31:43.34,EN,,0,0,0,,I don't care where,\nDialogue: 0,0:31:43.62,0:31:46.17,EN,,0,0,0,,scanning every cell that's in the memory.\nDialogue: 0,0:31:47.17,0:31:48.67,EN,,0,0,0,,And as I scan these cells,\nDialogue: 0,0:31:49.20,0:31:50.97,EN,,0,0,0,,I'm going to link them together,\nDialogue: 0,0:31:50.99,0:31:52.84,EN,,0,0,0,,if they are free, into the free list.\nDialogue: 0,0:31:53.15,0:31:54.05,EN,,0,0,0,,And if they're not free,\nDialogue: 0,0:31:54.05,0:31:56.07,EN,,0,0,0,,I'm going to unmark them so the marks become zero.\nDialogue: 0,0:31:57.50,0:31:58.57,EN,,0,0,0,,And in fact what I get--\nDialogue: 0,0:31:58.70,0:32:00.46,EN,,0,0,0,,well the program is not very complicated.\nDialogue: 0,0:32:00.46,0:32:02.22,EN,,0,0,0,,It looks sort of like this-- it's a little longer.\nDialogue: 0,0:32:02.78,0:32:04.17,EN,,0,0,0,,Here's the first piece of it.\nDialogue: 0,0:32:04.82,0:32:06.71,EN,,0,0,0,,This one's coming down from the top of memory.\nDialogue: 0,0:32:06.71,0:32:09.58,EN,,0,0,0,,I don't want you to try to understand this at this point.\nDialogue: 0,0:32:09.58,0:32:10.55,EN,,0,0,0,,It's rather simple.\nDialogue: 0,0:32:11.03,0:32:12.52,EN,,0,0,0,,It's a very simple algorithm,\nDialogue: 0,0:32:13.07,0:32:15.97,EN,,0,0,0,,but there's pieces of it that just sort of look like this.\nDialogue: 0,0:32:15.97,0:32:17.37,EN,,0,0,0,,They're all sort of obvious.\nDialogue: 0,0:32:18.60,0:32:20.08,EN,,0,0,0,,And after we've done the sweep,\nDialogue: 0,0:32:20.30,0:32:21.77,EN,,0,0,0,,we get an answer that looks like that.\nDialogue: 0,0:32:25.33,0:32:26.54,EN,,0,0,0,,Now there are some disadvantages\nDialogue: 0,0:32:26.56,0:32:28.20,EN,,0,0,0,,with mark-sweep algorithms of this sort.\nDialogue: 0,0:32:29.59,0:32:30.35,EN,,0,0,0,,Serious ones.\nDialogue: 0,0:32:31.45,0:32:33.20,EN,,0,0,0,,One important disadvantage is\nDialogue: 0,0:32:33.20,0:32:34.97,EN,,0,0,0,,that your memories get larger and larger.\nDialogue: 0,0:32:36.82,0:32:38.87,EN,,0,0,0,,As you say, address spaces get larger and larger,\nDialogue: 0,0:32:38.87,0:32:40.80,EN,,0,0,0,,you're willing to represent more and more stuff,\nDialogue: 0,0:32:41.37,0:32:44.52,EN,,0,0,0,,then it gets very costly to scan all of memory.\nDialogue: 0,0:32:46.36,0:32:47.39,EN,,0,0,0,,What you'd really like to do\nDialogue: 0,0:32:47.40,0:32:48.68,EN,,0,0,0,,is only scan useful stuff.\nDialogue: 0,0:32:50.49,0:32:51.55,EN,,0,0,0,,It would even be better\nDialogue: 0,0:32:52.07,0:32:53.90,EN,,0,0,0,,if you realized that some stuff\nDialogue: 0,0:32:54.48,0:32:57.72,EN,,0,0,0,,was known to be good and useful,\nDialogue: 0,0:32:58.28,0:33:00.37,EN,,0,0,0,,and you don't have to look at it more than once or twice.\nDialogue: 0,0:33:00.37,0:33:01.20,EN,,0,0,0,,Or very rarely.\nDialogue: 0,0:33:01.55,0:33:04.32,EN,,0,0,0,,Whereas other stuff that you're not so sure about,\nDialogue: 0,0:33:05.00,0:33:06.22,EN,,0,0,0,,you can look at more detail\nDialogue: 0,0:33:07.10,0:33:08.75,EN,,0,0,0,,every time you want to do this,\nDialogue: 0,0:33:09.93,0:33:10.85,EN,,0,0,0,,want to garbage collect.\nDialogue: 0,0:33:11.91,0:33:13.74,EN,,0,0,0,,Well there are algorithms\nDialogue: 0,0:33:13.76,0:33:15.10,EN,,0,0,0,,that are organized in this way.\nDialogue: 0,0:33:15.66,0:33:18.16,EN,,0,0,0,,Let me tell you about a famous old algorithm\nDialogue: 0,0:33:18.28,0:33:19.47,EN,,0,0,0,,which allows you only look at\nDialogue: 0,0:33:19.50,0:33:21.37,EN,,0,0,0,,the part of memory which is known to be useful.\nDialogue: 0,0:33:23.12,0:33:23.85,EN,,0,0,0,,And which happens to be\nDialogue: 0,0:33:23.87,0:33:25.29,EN,,0,0,0,,the fastest known garbage collector algorithm.\nDialogue: 0,0:33:26.31,0:33:29.45,EN,,0,0,0,,This is the Minsky-Fenichel-Yochelson garbage collector algorithm.\nDialogue: 0,0:33:30.40,0:33:33.18,EN,,0,0,0,,It was invented by Minsky\nDialogue: 0,0:33:33.20,0:33:36.06,EN,,0,0,0,,in 1961 or '60 or something,\nDialogue: 0,0:33:36.52,0:33:40.48,EN,,0,0,0,,for the RLE PDP-1 Lisp,\nDialogue: 0,0:33:40.51,0:33:43.44,EN,,0,0,0,,which had 4,096 words of list memory,\nDialogue: 0,0:33:45.79,0:33:46.76,EN,,0,0,0,,and a drum.\nDialogue: 0,0:33:48.48,0:33:49.39,EN,,0,0,0,,And the whole idea\nDialogue: 0,0:33:50.03,0:33:51.87,EN,,0,0,0,,was to garbage collect this terrible memory.\nDialogue: 0,0:33:53.05,0:33:54.35,EN,,0,0,0,,What Minsky realized\nDialogue: 0,0:33:54.38,0:33:55.62,EN,,0,0,0,,was the easiest way to do this\nDialogue: 0,0:33:56.20,0:33:58.47,EN,,0,0,0,,is to scan the memory in the same sense,\nDialogue: 0,0:33:58.47,0:34:00.60,EN,,0,0,0,,walking the good structure,\nDialogue: 0,0:34:01.57,0:34:03.52,EN,,0,0,0,,copying it out into the drum,\nDialogue: 0,0:34:04.70,0:34:05.47,EN,,0,0,0,,compacted.\nDialogue: 0,0:34:06.35,0:34:08.86,EN,,0,0,0,,And then when we were done copying it all out,\nDialogue: 0,0:34:09.12,0:34:10.90,EN,,0,0,0,,then you swap that back into your memory.\nDialogue: 0,0:34:12.30,0:34:13.68,EN,,0,0,0,,Now whether or you not use a drum,\nDialogue: 0,0:34:13.72,0:34:14.71,EN,,0,0,0,,or another piece of memory,\nDialogue: 0,0:34:14.71,0:34:16.42,EN,,0,0,0,,or something like that isn't important.\nDialogue: 0,0:34:17.03,0:34:17.42,EN,,0,0,0,,In fact,\nDialogue: 0,0:34:17.44,0:34:19.60,EN,,0,0,0,,I don't think people use drums anymore for anything.\nDialogue: 0,0:34:20.35,0:34:23.77,EN,,0,0,0,,But this algorithm basically\nDialogue: 0,0:34:24.03,0:34:25.42,EN,,0,0,0,,depends upon having\nDialogue: 0,0:34:25.42,0:34:27.42,EN,,0,0,0,,about twice as much address space\nDialogue: 0,0:34:27.48,0:34:28.57,EN,,0,0,0,,you're actually using.\nDialogue: 0,0:34:30.27,0:34:32.96,EN,,0,0,0,,And so what you have is some, initially,\nDialogue: 0,0:34:33.12,0:34:36.60,EN,,0,0,0,,some mixture of useful data and garbage.\nDialogue: 0,0:34:37.11,0:34:38.97,EN,,0,0,0,,So this is called fromspace.\nDialogue: 0,0:34:45.17,0:34:47.05,EN,,0,0,0,,And this is a mixture of crud.\nDialogue: 0,0:34:47.87,0:34:49.79,EN,,0,0,0,,Some of it's important and some of it isn't.\nDialogue: 0,0:34:52.00,0:34:53.85,EN,,0,0,0,,Now there's another place\nDialogue: 0,0:34:54.17,0:34:55.61,EN,,0,0,0,,which is hopefully big enough,\nDialogue: 0,0:34:55.77,0:34:57.00,EN,,0,0,0,,if we recall, tospace,\nDialogue: 0,0:34:57.12,0:34:58.24,EN,,0,0,0,,which is where we're copying to.\nDialogue: 0,0:35:01.59,0:35:02.60,EN,,0,0,0,,And what happens is--\nDialogue: 0,0:35:02.60,0:35:04.06,EN,,0,0,0,,and I'm not going to go through this detail.\nDialogue: 0,0:35:04.16,0:35:07.07,EN,,0,0,0,,It's in our book quite explicitly.\nDialogue: 0,0:35:07.59,0:35:10.40,EN,,0,0,0,,There's a root point where you start from.\nDialogue: 0,0:35:11.03,0:35:14.30,EN,,0,0,0,,And the idea is that you start with the root.\nDialogue: 0,0:35:14.60,0:35:16.42,EN,,0,0,0,,You copy the first thing you see,\nDialogue: 0,0:35:17.83,0:35:19.37,EN,,0,0,0,,the first thing that the root points at,\nDialogue: 0,0:35:19.75,0:35:21.31,EN,,0,0,0,,to the beginning of tospace.\nDialogue: 0,0:35:22.81,0:35:24.12,EN,,0,0,0,,The first thing is a pair\nDialogue: 0,0:35:24.16,0:35:25.60,EN,,0,0,0,,or something like, a data structure.\nDialogue: 0,0:35:27.56,0:35:30.19,EN,,0,0,0,,You then also leave behind\nDialogue: 0,0:35:30.38,0:35:31.56,EN,,0,0,0,,a broken heart saying,\nDialogue: 0,0:35:31.77,0:35:35.74,EN,,0,0,0,,I moved this object from here to here,\nDialogue: 0,0:35:35.74,0:35:37.05,EN,,0,0,0,,giving the place where it moved to.\nDialogue: 0,0:35:37.80,0:35:39.65,EN,,0,0,0,,This is called a broken heart because\nDialogue: 0,0:35:39.65,0:35:40.78,EN,,0,0,0,,a friend of mine who implemented\nDialogue: 0,0:35:40.78,0:35:43.39,EN,,0,0,0,,one of these in 1966\nDialogue: 0,0:35:43.82,0:35:45.26,EN,,0,0,0,,was a very romantic character\nDialogue: 0,0:35:45.26,0:35:46.76,EN,,0,0,0,,and called it a broken heart.\nDialogue: 0,0:35:49.58,0:35:50.54,EN,,0,0,0,,But in any case,\nDialogue: 0,0:35:51.15,0:35:52.72,EN,,0,0,0,,the next thing you do\nDialogue: 0,0:35:52.94,0:35:55.00,EN,,0,0,0,,is now you have a new free pointer which is here,\nDialogue: 0,0:35:55.17,0:35:56.38,EN,,0,0,0,,and you start scanning.\nDialogue: 0,0:35:56.88,0:35:59.68,EN,,0,0,0,,You scan this data structure you just copied.\nDialogue: 0,0:36:00.55,0:36:02.19,EN,,0,0,0,,And every time you encounter a pointer in it,\nDialogue: 0,0:36:02.19,0:36:03.92,EN,,0,0,0,,you treat it as if it was the root pointer here.\nDialogue: 0,0:36:04.00,0:36:04.59,EN,,0,0,0,,Oh, I'm sorry.\nDialogue: 0,0:36:04.60,0:36:05.69,EN,,0,0,0,,The other thing you do\nDialogue: 0,0:36:05.71,0:36:07.08,EN,,0,0,0,,is you now move the root pointer to there.\nDialogue: 0,0:36:09.22,0:36:10.17,EN,,0,0,0,,So now you scan this,\nDialogue: 0,0:36:10.17,0:36:10.99,EN,,0,0,0,,and everything you see\nDialogue: 0,0:36:11.00,0:36:12.41,EN,,0,0,0,,you treat as it were the root pointer.\nDialogue: 0,0:36:14.11,0:36:15.45,EN,,0,0,0,,So if you see something,\nDialogue: 0,0:36:15.45,0:36:17.40,EN,,0,0,0,,well it points up into there somewhere.\nDialogue: 0,0:36:18.51,0:36:19.92,EN,,0,0,0,,Is it pointing at a thing\nDialogue: 0,0:36:19.93,0:36:20.99,EN,,0,0,0,,which you've not copied yet?\nDialogue: 0,0:36:21.78,0:36:22.87,EN,,0,0,0,,Is there a broken heart there?\nDialogue: 0,0:36:23.88,0:36:24.84,EN,,0,0,0,,If there's a broken heart there\nDialogue: 0,0:36:24.84,0:36:26.11,EN,,0,0,0,,and it's something you have copied,\nDialogue: 0,0:36:26.20,0:36:27.34,EN,,0,0,0,,you've just replaced this pointer\nDialogue: 0,0:36:27.36,0:36:28.75,EN,,0,0,0,,with the thing a broken heart points at.\nDialogue: 0,0:36:29.82,0:36:32.03,EN,,0,0,0,,If this thing has not been copied,\nDialogue: 0,0:36:32.12,0:36:34.08,EN,,0,0,0,,you copy it to the next place over here.\nDialogue: 0,0:36:34.43,0:36:35.95,EN,,0,0,0,,Move your free pointer over here,\nDialogue: 0,0:36:37.05,0:36:40.60,EN,,0,0,0,,and then leave a broken heart behind\nDialogue: 0,0:36:41.05,0:36:41.80,EN,,0,0,0,,and scan.\nDialogue: 0,0:36:43.67,0:36:46.40,EN,,0,0,0,,And eventually when the scant pointer hits the free pointer,\nDialogue: 0,0:36:46.82,0:36:48.52,EN,,0,0,0,,everything in memory has been copied.\nDialogue: 0,0:36:50.14,0:36:51.04,EN,,0,0,0,,And then there's a whole bunch\nDialogue: 0,0:36:51.05,0:36:51.95,EN,,0,0,0,,of empty space up here,\nDialogue: 0,0:36:51.96,0:36:53.28,EN,,0,0,0,,which you could either make into a free list,\nDialogue: 0,0:36:53.31,0:36:54.47,EN,,0,0,0,,if that's what you want to do.\nDialogue: 0,0:36:54.47,0:36:56.27,EN,,0,0,0,,But generally you don't in this kind of system.\nDialogue: 0,0:36:56.27,0:36:59.15,EN,,0,0,0,,In this system you sequentially allocate your memory.\nDialogue: 0,0:37:00.91,0:37:02.48,EN,,0,0,0,,That is a very, very nice algorithm,\nDialogue: 0,0:37:02.97,0:37:04.57,EN,,0,0,0,,and sort of the one we use in the\nDialogue: 0,0:37:04.67,0:37:05.97,EN,,0,0,0,,the scheme that you've been using.\nDialogue: 0,0:37:06.79,0:37:09.47,EN,,0,0,0,,And it's known to be... it's expected--\nDialogue: 0,0:37:09.47,0:37:10.86,EN,,0,0,0,,I believe no one has found\nDialogue: 0,0:37:10.89,0:37:12.12,EN,,0,0,0,,a faster algorithm than that.\nDialogue: 0,0:37:12.40,0:37:14.85,EN,,0,0,0,,There are very simple modifications to this algorithm\nDialogue: 0,0:37:14.85,0:37:16.77,EN,,0,0,0,,invented by Henry Baker\nDialogue: 0,0:37:17.17,0:37:20.31,EN,,0,0,0,,which allow one to run this algorithm in real time,\nDialogue: 0,0:37:20.31,0:37:21.92,EN,,0,0,0,,meaning you don't have to stop to garbage collect.\nDialogue: 0,0:37:22.14,0:37:24.33,EN,,0,0,0,,But you could interleave the consing\nDialogue: 0,0:37:24.36,0:37:26.17,EN,,0,0,0,,that the machine does when its running\nDialogue: 0,0:37:26.32,0:37:28.40,EN,,0,0,0,,with steps of the garbage collection process,\nDialogue: 0,0:37:28.85,0:37:31.20,EN,,0,0,0,,so that the thing, the garbage collector's distributed\nDialogue: 0,0:37:31.20,0:37:32.19,EN,,0,0,0,,and the machine doesn't have to stop,\nDialogue: 0,0:37:32.41,0:37:33.47,EN,,0,0,0,,and garbage collecting can start.\nDialogue: 0,0:37:34.64,0:37:37.87,EN,,0,0,0,,Of course in the case of machines with virtual memory\nDialogue: 0,0:37:38.90,0:37:41.20,EN,,0,0,0,,where a lot of it is in inaccessible places,\nDialogue: 0,0:37:41.50,0:37:43.60,EN,,0,0,0,,this becomes a very expensive process.\nDialogue: 0,0:37:44.28,0:37:46.43,EN,,0,0,0,,And there have been numerous\nDialogue: 0,0:37:47.16,0:37:48.65,EN,,0,0,0,,attempts to make this much better.\nDialogue: 0,0:37:49.19,0:37:51.15,EN,,0,0,0,,There is a nice paper,\nDialogue: 0,0:37:51.16,0:37:52.41,EN,,0,0,0,,for those of you who are interested,\nDialogue: 0,0:37:52.64,0:37:54.27,EN,,0,0,0,,by Moon and other people\nDialogue: 0,0:37:54.65,0:37:56.89,EN,,0,0,0,,which describes a modification to\nDialogue: 0,0:37:56.92,0:37:59.44,EN,,0,0,0,,the incremental Minsky-Fenichel-Yochelson algorithm,\nDialogue: 0,0:37:59.51,0:38:01.20,EN,,0,0,0,,and modification the Baker algorithm\nDialogue: 0,0:38:01.42,0:38:06.54,EN,,0,0,0,,which is more efficient for virtual memory systems.\nDialogue: 0,0:38:08.27,0:38:12.32,EN,,0,0,0,,Well I think now the mystery to this is sort of gone.\nDialogue: 0,0:38:12.84,0:38:14.09,EN,,0,0,0,,And I'd like to see if there are any questions.\nDialogue: 0,0:38:19.78,0:38:19.95,EN,,0,0,0,,Yes.\nDialogue: 0,0:38:20.60,0:38:23.58,EN,,0,0,0,,AUDIENCE: I saw one of you run the garbage collector\nDialogue: 0,0:38:23.64,0:38:25.05,EN,,0,0,0,,on the systems upstairs,\nDialogue: 0,0:38:25.93,0:38:27.88,EN,,0,0,0,,and it seemed to me to run extremely fast.\nDialogue: 0,0:38:27.96,0:38:28.40,EN,,0,0,0,,PROFESSOR: Yes\nDialogue: 0,0:38:28.49,0:38:29.52,EN,,0,0,0,,AUDIENCE: Did the whole thing take--\nDialogue: 0,0:38:30.11,0:38:31.88,EN,,0,0,0,,does it sweep through all of memory?\nDialogue: 0,0:38:31.88,0:38:32.22,EN,,0,0,0,,PROFESSOR: No.\nDialogue: 0,0:38:32.25,0:38:34.11,EN,,0,0,0,,It swept through exactly what was needed\nDialogue: 0,0:38:34.33,0:38:35.63,EN,,0,0,0,,to copy the useful structure.\nDialogue: 0,0:38:37.32,0:38:38.36,EN,,0,0,0,,It's a copying collector.\nDialogue: 0,0:38:38.44,0:38:38.91,EN,,0,0,0,,AUDIENCE: OK.\nDialogue: 0,0:38:39.30,0:38:40.88,EN,,0,0,0,,PROFESSOR: And it's rather... it is very fast.\nDialogue: 0,0:38:41.85,0:38:45.88,EN,,0,0,0,,On the whole, I suppose to copy in a Bobcat\nDialogue: 0,0:38:47.12,0:38:51.56,EN,,0,0,0,,to copy, I think, a three megabyte thing or something\nDialogue: 0,0:38:52.43,0:38:53.24,EN,,0,0,0,,is less than a second,\nDialogue: 0,0:38:55.00,0:38:55.69,EN,,0,0,0,,real time\nDialogue: 0,0:38:56.54,0:38:58.46,EN,,0,0,0,,Really, these are very small programs.\nDialogue: 0,0:38:58.62,0:39:01.50,EN,,0,0,0,,One thing you should realise is that\nDialogue: 0,0:39:02.91,0:39:04.40,EN,,0,0,0,,garbage collectors have to be small.\nDialogue: 0,0:39:05.40,0:39:07.10,EN,,0,0,0,,Not because they have to be fast,\nDialogue: 0,0:39:07.90,0:39:09.23,EN,,0,0,0,,but because no one can debug\nDialogue: 0,0:39:09.26,0:39:10.48,EN,,0,0,0,,a complicated garbage collector.\nDialogue: 0,0:39:11.34,0:39:12.91,EN,,0,0,0,,A garbage collector, if it doesn't work,\nDialogue: 0,0:39:14.04,0:39:15.93,EN,,0,0,0,,will trash your memory in such a way\nDialogue: 0,0:39:15.93,0:39:17.39,EN,,0,0,0,,that you cannot figure out what the hell happened.\nDialogue: 0,0:39:18.35,0:39:19.67,EN,,0,0,0,,You need an audit trail.\nDialogue: 0,0:39:20.66,0:39:22.01,EN,,0,0,0,,Because it rearranges everything,\nDialogue: 0,0:39:22.04,0:39:23.24,EN,,0,0,0,,and how do you know what happened there?\nDialogue: 0,0:39:23.74,0:39:26.58,EN,,0,0,0,,So this is the only kind of program that\nDialogue: 0,0:39:26.92,0:39:28.40,EN,,0,0,0,,it really, seriously matters\nDialogue: 0,0:39:28.54,0:39:29.79,EN,,0,0,0,,if you stare at it long enough\nDialogue: 0,0:39:29.82,0:39:31.07,EN,,0,0,0,,so you believe that it works.\nDialogue: 0,0:39:31.34,0:39:33.36,EN,,0,0,0,,That means and sort of prove it to yourself.\nDialogue: 0,0:39:33.92,0:39:36.11,EN,,0,0,0,,And that, that... So there's no way to debug it.\nDialogue: 0,0:39:36.94,0:39:38.96,EN,,0,0,0,,And that takes it being small enough\nDialogue: 0,0:39:38.96,0:39:39.97,EN,,0,0,0,,so you can hold it in your head.\nDialogue: 0,0:39:41.45,0:39:43.90,EN,,0,0,0,,So garbage collectors are special in this way.\nDialogue: 0,0:39:45.02,0:39:47.12,EN,,0,0,0,,So every reasonable garbage collector has gotten small,\nDialogue: 0,0:39:47.13,0:39:48.45,EN,,0,0,0,,and generally small programs are fast.\nDialogue: 0,0:39:52.05,0:39:52.43,EN,,0,0,0,,Yes.\nDialogue: 0,0:39:52.43,0:39:54.51,EN,,0,0,0,,AUDIENCE: Can you repeat the name of this technique once again?\nDialogue: 0,0:39:54.68,0:39:56.92,EN,,0,0,0,,PROFESSOR: That's the Minsky-Fenichel-Yochelson garbage collector.\nDialogue: 0,0:39:57.88,0:39:58.43,EN,,0,0,0,,AUDIENCE: You got that?\nDialogue: 0,0:39:59.00,0:40:00.78,EN,,0,0,0,,PROFESSOR: Minsky invented it in '61\nDialogue: 0,0:40:00.81,0:40:02.21,EN,,0,0,0,,for the RLE PDP-1.\nDialogue: 0,0:40:02.21,0:40:06.17,EN,,0,0,0,,A version of it was developed and elaborated\nDialogue: 0,0:40:06.45,0:40:10.27,EN,,0,0,0,,to be used in Multics Maclisp by Fenichel and Yochelson\nDialogue: 0,0:40:11.37,0:40:14.75,EN,,0,0,0,,in somewhere around 1968 or '69.\nDialogue: 0,0:40:19.57,0:40:21.36,EN,,0,0,0,,OK. Let's take a break.\nDialogue: 0,0:40:22.64,0:40:32.36,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:40:32.41,0:40:36.19,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:41:03.15,0:41:07.18,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:41:07.20,0:41:10.17,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:41:10.20,0:41:14.22,EN,,0,0,0,,Not Everything Can Be Computed\nDialogue: 0,0:41:17.31,0:41:19.67,EN,,0,0,0,,PROFESSOR: Well we've come to the end of this subject,\nDialogue: 0,0:41:20.08,0:41:23.85,EN,,0,0,0,,and we've already shown you a universal machine\nDialogue: 0,0:41:24.47,0:41:26.74,EN,,0,0,0,,which is down to evaluator.\nDialogue: 0,0:41:27.02,0:41:28.38,EN,,0,0,0,,It's down to the level of detail\nDialogue: 0,0:41:28.38,0:41:29.67,EN,,0,0,0,,you could imagine you could make one.\nDialogue: 0,0:41:30.19,0:41:33.32,EN,,0,0,0,,This is a particular implementation of Lisp,\nDialogue: 0,0:41:33.90,0:41:36.01,EN,,0,0,0,,built on one of those\nDialogue: 0,0:41:36.16,0:41:38.05,EN,,0,0,0,,scheme chips that was talked about yesterday,\nDialogue: 0,0:41:38.20,0:41:38.91,EN,,0,0,0,,sitting over here.\nDialogue: 0,0:41:39.35,0:41:42.00,EN,,0,0,0,,This is mostly interface to somebody's memory\nDialogue: 0,0:41:42.60,0:41:44.75,EN,,0,0,0,,with a little bit of timing and other such stuff.\nDialogue: 0,0:41:45.22,0:41:47.25,EN,,0,0,0,,But this fellow actually ran Lisp\nDialogue: 0,0:41:47.77,0:41:50.17,EN,,0,0,0,,at a fairly reasonable rate, as interpretive.\nDialogue: 0,0:41:50.61,0:41:53.82,EN,,0,0,0,,It ran Lisp as fast as a DEC PDP-10\nDialogue: 0,0:41:54.22,0:41:55.65,EN,,0,0,0,,back in 1979.\nDialogue: 0,0:41:56.50,0:41:59.67,EN,,0,0,0,,And so it's gotten pretty hardware.\nDialogue: 0,0:42:00.02,0:42:00.89,EN,,0,0,0,,Pretty concrete.\nDialogue: 0,0:42:02.47,0:42:04.70,EN,,0,0,0,,We've also downed you a bit\nDialogue: 0,0:42:04.72,0:42:06.07,EN,,0,0,0,,with the things you can compute.\nDialogue: 0,0:42:07.37,0:42:08.76,EN,,0,0,0,,But is it the case that\nDialogue: 0,0:42:09.32,0:42:10.55,EN,,0,0,0,,there are things we can't compute?\nDialogue: 0,0:42:11.85,0:42:13.50,EN,,0,0,0,,And so I'd like to end this with\nDialogue: 0,0:42:13.75,0:42:15.87,EN,,0,0,0,,showing you some things that you'd like be able to compute\nDialogue: 0,0:42:16.60,0:42:17.22,EN,,0,0,0,,that you can't.\nDialogue: 0,0:42:18.19,0:42:19.45,EN,,0,0,0,,The answer is yes,\nDialogue: 0,0:42:19.45,0:42:20.82,EN,,0,0,0,,there are things you can't compute.\nDialogue: 0,0:42:22.72,0:42:23.47,EN,,0,0,0,,For example,\nDialogue: 0,0:42:24.45,0:42:25.82,EN,,0,0,0,,something you'd really like is--\nDialogue: 0,0:42:27.80,0:42:29.36,EN,,0,0,0,,if you're writing a compiler\nDialogue: 0,0:42:29.77,0:42:31.42,EN,,0,0,0,,you'd like a program that would check\nDialogue: 0,0:42:32.00,0:42:33.97,EN,,0,0,0,,that the thing you're going to do will work.\nDialogue: 0,0:42:34.63,0:42:35.40,EN,,0,0,0,,Wouldn't that be nice?\nDialogue: 0,0:42:36.08,0:42:37.87,EN,,0,0,0,,You'd like something that would catch infinite loops,\nDialogue: 0,0:42:37.87,0:42:38.54,EN,,0,0,0,,for example,\nDialogue: 0,0:42:39.45,0:42:42.42,EN,,0,0,0,,in programs that were written by users.\nDialogue: 0,0:42:43.19,0:42:45.12,EN,,0,0,0,,But in general you can't write such a program\nDialogue: 0,0:42:45.35,0:42:46.49,EN,,0,0,0,,that will read any program\nDialogue: 0,0:42:46.51,0:42:47.45,EN,,0,0,0,,and determine whether or not\nDialogue: 0,0:42:48.35,0:42:49.30,EN,,0,0,0,,it's an infinite loop.\nDialogue: 0,0:42:50.99,0:42:51.71,EN,,0,0,0,,Let me show you that.\nDialogue: 0,0:42:51.76,0:42:53.80,EN,,0,0,0,,It's a little bit of a minor mathematics.\nDialogue: 0,0:42:58.78,0:42:59.65,EN,,0,0,0,,Let's imagine\nDialogue: 0,0:43:00.05,0:43:01.78,EN,,0,0,0,,that we just had a mathematical function\nDialogue: 0,0:43:01.78,0:43:02.62,EN,,0,0,0,,before we start.\nDialogue: 0,0:43:02.62,0:43:03.42,EN,,0,0,0,,And there is one,\nDialogue: 0,0:43:03.84,0:43:04.67,EN,,0,0,0,,called s,\nDialogue: 0,0:43:05.47,0:43:07.54,EN,,0,0,0,,which takes a procedure\nDialogue: 0,0:43:12.64,0:43:14.23,EN,,0,0,0,,and its argument, a.\nDialogue: 0,0:43:19.17,0:43:20.52,EN,,0,0,0,,And what s does\nDialogue: 0,0:43:21.65,0:43:24.01,EN,,0,0,0,,is it determines whether or not\nDialogue: 0,0:43:24.01,0:43:25.97,EN,,0,0,0,,it's safe to run p on a.\nDialogue: 0,0:43:26.90,0:43:28.17,EN,,0,0,0,,And what I mean by that is this:\nDialogue: 0,0:43:28.76,0:43:35.12,EN,,0,0,0,,it's true if p applied to a\nDialogue: 0,0:43:35.62,0:43:36.74,EN,,0,0,0,,will converge\nDialogue: 0,0:43:41.40,0:43:42.45,EN,,0,0,0,,to a value\nDialogue: 0,0:43:44.35,0:43:45.33,EN,,0,0,0,,without an error.\nDialogue: 0,0:43:52.70,0:43:53.68,EN,,0,0,0,,And it's false\nDialogue: 0,0:43:56.10,0:43:57.04,EN,,0,0,0,,if p of a\nDialogue: 0,0:43:59.67,0:44:00.76,EN,,0,0,0,,loops forever\nDialogue: 0,0:44:05.87,0:44:06.95,EN,,0,0,0,,or makes an error.\nDialogue: 0,0:44:15.23,0:44:17.22,EN,,0,0,0,,Now that's surely a function.\nDialogue: 0,0:44:18.78,0:44:20.72,EN,,0,0,0,,There is some for every procedure\nDialogue: 0,0:44:21.20,0:44:22.85,EN,,0,0,0,,and for every argument you could give it\nDialogue: 0,0:44:23.92,0:44:25.45,EN,,0,0,0,,that is either true or false\nDialogue: 0,0:44:25.92,0:44:27.85,EN,,0,0,0,,that it converges without making an error.\nDialogue: 0,0:44:28.44,0:44:30.15,EN,,0,0,0,,And you could make a giant table of them.\nDialogue: 0,0:44:32.22,0:44:32.92,EN,,0,0,0,,But the question is,\nDialogue: 0,0:44:32.92,0:44:34.09,EN,,0,0,0,,can you write a procedure\nDialogue: 0,0:44:34.09,0:44:35.92,EN,,0,0,0,,that compute the values of this function?\nDialogue: 0,0:44:37.43,0:44:38.92,EN,,0,0,0,,Well let's assume that we can.\nDialogue: 0,0:44:39.72,0:44:40.55,EN,,0,0,0,,Suppose\nDialogue: 0,0:44:44.33,0:44:45.58,EN,,0,0,0,,that we have a procedure\nDialogue: 0,0:44:48.55,0:44:52.73,EN,,0,0,0,,procedure called \"safe\"\nDialogue: 0,0:44:56.54,0:44:59.90,EN,,0,0,0,,that computes the value of s.\nDialogue: 0,0:45:12.65,0:45:14.89,EN,,0,0,0,,Now I'm going to show you by several methods\nDialogue: 0,0:45:15.90,0:45:18.51,EN,,0,0,0,,that you can't do this.\nDialogue: 0,0:45:19.76,0:45:20.62,EN,,0,0,0,,The easiest one,\nDialogue: 0,0:45:20.62,0:45:21.28,EN,,0,0,0,,or the first one,\nDialogue: 0,0:45:21.31,0:45:23.45,EN,,0,0,0,,let's define a procedure called diag1.\nDialogue: 0,0:45:23.76,0:45:24.86,EN,,0,0,0,,Given that we have safe,\nDialogue: 0,0:45:25.20,0:45:26.99,EN,,0,0,0,,we can define diag1\nDialogue: 0,0:45:34.42,0:45:35.55,EN,,0,0,0,,diag1\nDialogue: 0,0:45:37.82,0:45:41.60,EN,,0,0,0,,to be the procedure of one argument, p,\nDialogue: 0,0:45:42.45,0:45:44.05,EN,,0,0,0,,which has the following properties.\nDialogue: 0,0:45:44.78,0:45:50.67,EN,,0,0,0,,If it's safe to apply p to itself,\nDialogue: 0,0:45:53.32,0:45:55.32,EN,,0,0,0,,then I wish to have an infinite loop.\nDialogue: 0,0:45:59.22,0:46:00.92,EN,,0,0,0,,Otherwise I'm going to return 3.\nDialogue: 0,0:46:03.68,0:46:04.47,EN,,0,0,0,,Maybe it was 42.\nDialogue: 0,0:46:04.47,0:46:06.42,EN,,0,0,0,,What's the answer to the big question?\nDialogue: 0,0:46:07.06,0:46:08.87,EN,,0,0,0,,Where of course we know what an infinite loop is.\nDialogue: 0,0:46:12.05,0:46:12.96,EN,,0,0,0,,Infinite loop,\nDialogue: 0,0:46:13.82,0:46:16.02,EN,,0,0,0,,to be a procedure of no arguments,\nDialogue: 0,0:46:16.02,0:46:18.07,EN,,0,0,0,,which is that nice lambda calculus loop.\nDialogue: 0,0:46:18.35,0:46:20.44,EN,,0,0,0,,Lambda of x,\nDialogue: 0,0:46:21.30,0:46:24.68,EN,,0,0,0,,applied to lambda of x, x of x.\nDialogue: 0,0:46:24.68,0:46:26.55,EN,,0,0,0,,So there's nothing left to the imagination here.\nDialogue: 0,0:46:29.83,0:46:31.17,EN,,0,0,0,,Well let's see what the story is.\nDialogue: 0,0:46:32.50,0:46:33.90,EN,,0,0,0,,I'm supposing it's the case\nDialogue: 0,0:46:35.45,0:46:38.77,EN,,0,0,0,,that we worry about the procedure\nDialogue: 0,0:46:39.00,0:46:43.45,EN,,0,0,0,,called diag1 applied to diag1.\nDialogue: 0,0:46:46.27,0:46:47.77,EN,,0,0,0,,Well what could it possibly be?\nDialogue: 0,0:46:49.97,0:46:51.39,EN,,0,0,0,,Well I don't know.\nDialogue: 0,0:46:51.39,0:46:53.21,EN,,0,0,0,,We're going to substitute diag1\nDialogue: 0,0:46:53.55,0:46:55.50,EN,,0,0,0,,for p in the body here.\nDialogue: 0,0:46:57.31,0:47:00.22,EN,,0,0,0,,Well is it safe to compute diag1 of diag1?\nDialogue: 0,0:47:00.22,0:47:00.78,EN,,0,0,0,,I don't know.\nDialogue: 0,0:47:00.78,0:47:01.82,EN,,0,0,0,,There are two possibilities.\nDialogue: 0,0:47:03.40,0:47:05.50,EN,,0,0,0,,If it's safe to compute diag1 of diag1\nDialogue: 0,0:47:05.92,0:47:06.89,EN,,0,0,0,,that means it shouldn't loop.\nDialogue: 0,0:47:08.49,0:47:09.22,EN,,0,0,0,,That means I go to here,\nDialogue: 0,0:47:09.22,0:47:10.35,EN,,0,0,0,,but then I produce an infinite loop.\nDialogue: 0,0:47:10.56,0:47:11.57,EN,,0,0,0,,So it can't be safe.\nDialogue: 0,0:47:12.21,0:47:14.78,EN,,0,0,0,,But if it's not safe to compute diag1 of diag1\nDialogue: 0,0:47:14.90,0:47:16.02,EN,,0,0,0,,then the answer to this is 3.\nDialogue: 0,0:47:16.02,0:47:17.26,EN,,0,0,0,,But that's diag1 of diag1,\nDialogue: 0,0:47:17.26,0:47:17.93,EN,,0,0,0,,so it had to be safe.\nDialogue: 0,0:47:20.53,0:47:23.60,EN,,0,0,0,,So therefore by contradiction\nDialogue: 0,0:47:24.32,0:47:26.30,EN,,0,0,0,,you cannot produce safe.\nDialogue: 0,0:47:27.40,0:47:29.80,EN,,0,0,0,,For those of you who were boggled by that one\nDialogue: 0,0:47:30.25,0:47:32.15,EN,,0,0,0,,I'm going to say it again, in a different way.\nDialogue: 0,0:47:32.82,0:47:34.00,EN,,0,0,0,,Listen to one more alternative.\nDialogue: 0,0:47:35.53,0:47:36.95,EN,,0,0,0,,Let's define diag2.\nDialogue: 0,0:47:39.84,0:47:41.60,EN,,0,0,0,,These are named diag because\nDialogue: 0,0:47:42.65,0:47:44.72,EN,,0,0,0,,of Cantor's diagonal argument.\nDialogue: 0,0:47:45.00,0:47:47.05,EN,,0,0,0,,These are instances of\nDialogue: 0,0:47:47.05,0:47:49.05,EN,,0,0,0,,a famous argument which was originally used by\nDialogue: 0,0:47:49.45,0:47:52.65,EN,,0,0,0,,Cantor in the late part of the last century\nDialogue: 0,0:47:52.77,0:47:56.10,EN,,0,0,0,,to prove that the real numbers were not countable,\nDialogue: 0,0:47:56.67,0:47:58.00,EN,,0,0,0,,that there are too many real numbers\nDialogue: 0,0:47:58.06,0:47:59.42,EN,,0,0,0,,to be counted by integers.\nDialogue: 0,0:48:00.19,0:48:01.74,EN,,0,0,0,,That there are more points on a line,\nDialogue: 0,0:48:01.74,0:48:02.50,EN,,0,0,0,,for example,\nDialogue: 0,0:48:02.50,0:48:04.42,EN,,0,0,0,,than there are counting numbers.\nDialogue: 0,0:48:05.26,0:48:06.85,EN,,0,0,0,,It may or may not be obvious,\nDialogue: 0,0:48:06.85,0:48:08.17,EN,,0,0,0,,and I don't want to get into that now.\nDialogue: 0,0:48:10.90,0:48:12.45,EN,,0,0,0,,But diag2\nDialogue: 0,0:48:13.30,0:48:15.82,EN,,0,0,0,,is again a procedure of one argument p.\nDialogue: 0,0:48:15.82,0:48:17.47,EN,,0,0,0,,It's almost the same as the previous one,\nDialogue: 0,0:48:17.72,0:48:24.32,EN,,0,0,0,,which is, if it's safe to compute p on p,\nDialogue: 0,0:48:25.17,0:48:26.67,EN,,0,0,0,,then I'm going to produce--\nDialogue: 0,0:48:27.26,0:48:28.14,EN,,0,0,0,,Oops, if\nDialogue: 0,0:48:29.31,0:48:31.02,EN,,0,0,0,,then I want to compute\nDialogue: 0,0:48:31.57,0:48:37.58,EN,,0,0,0,,some other things\nDialogue: 0,0:48:38.96,0:48:40.21,EN,,0,0,0,,Otherwise I'm going to put out false.\nDialogue: 0,0:48:43.60,0:48:45.30,EN,,0,0,0,,Where other then it says,\nDialogue: 0,0:48:45.47,0:48:46.35,EN,,0,0,0,,whatever p of p,\nDialogue: 0,0:48:46.35,0:48:47.47,EN,,0,0,0,,I'm going to put out something else.\nDialogue: 0,0:48:48.88,0:48:50.03,EN,,0,0,0,,I can give you an example of\nDialogue: 0,0:48:50.07,0:48:51.52,EN,,0,0,0,,a definition of other than\nDialogue: 0,0:48:51.60,0:48:52.57,EN,,0,0,0,,which I think works.\nDialogue: 0,0:48:53.89,0:48:54.51,EN,,0,0,0,,Let's see.\nDialogue: 0,0:48:55.64,0:48:56.08,EN,,0,0,0,,Yes.\nDialogue: 0,0:48:56.33,0:48:57.26,EN,,0,0,0,,Where other than\nDialogue: 0,0:49:04.03,0:49:06.11,EN,,0,0,0,,be a procedure of one argument x\nDialogue: 0,0:49:06.57,0:49:07.26,EN,,0,0,0,,which says,\nDialogue: 0,0:49:08.05,0:49:12.96,EN,,0,0,0,,if its eq x to, say, quote a,\nDialogue: 0,0:49:13.47,0:49:15.07,EN,,0,0,0,,then the answer is quote b.\nDialogue: 0,0:49:15.72,0:49:16.80,EN,,0,0,0,,Otherwise it's quote a.\nDialogue: 0,0:49:20.27,0:49:21.90,EN,,0,0,0,,That always produces something\nDialogue: 0,0:49:22.07,0:49:23.45,EN,,0,0,0,,which is not what its argument is.\nDialogue: 0,0:49:25.20,0:49:26.12,EN,,0,0,0,,That's all it is.\nDialogue: 0,0:49:26.54,0:49:27.37,EN,,0,0,0,,That's all I wanted.\nDialogue: 0,0:49:28.25,0:49:29.58,EN,,0,0,0,,Well now let's consider this one,\nDialogue: 0,0:49:29.58,0:49:31.15,EN,,0,0,0,,diag2 of diag2.\nDialogue: 0,0:49:38.28,0:49:38.94,EN,,0,0,0,,Well look.\nDialogue: 0,0:49:39.95,0:49:41.72,EN,,0,0,0,,This only does something dangerous,\nDialogue: 0,0:49:42.00,0:49:43.45,EN,,0,0,0,,like calling p of p,\nDialogue: 0,0:49:44.75,0:49:45.95,EN,,0,0,0,,if it's safe to do so.\nDialogue: 0,0:49:47.47,0:49:49.16,EN,,0,0,0,,So if safe defined at all,\nDialogue: 0,0:49:50.30,0:49:52.49,EN,,0,0,0,,if you can define such a procedure, safe,\nDialogue: 0,0:49:52.97,0:49:54.32,EN,,0,0,0,,then this procedure\nDialogue: 0,0:49:54.60,0:49:56.40,EN,,0,0,0,,is always defined and therefore safe\nDialogue: 0,0:49:56.52,0:49:57.22,EN,,0,0,0,,on any inputs.\nDialogue: 0,0:50:01.54,0:50:03.50,EN,,0,0,0,,So diag2 of diag2\nDialogue: 0,0:50:03.87,0:50:12.20,EN,,0,0,0,,must reduce to other than diag2 of diag2.\nDialogue: 0,0:50:15.82,0:50:16.97,EN,,0,0,0,,And that doesn't make sense,\nDialogue: 0,0:50:17.80,0:50:19.02,EN,,0,0,0,,so we have a contradiction,\nDialogue: 0,0:50:19.85,0:50:21.57,EN,,0,0,0,,and therefore we can't define safe.\nDialogue: 0,0:50:22.95,0:50:24.23,EN,,0,0,0,,I just waned to do that twice,\nDialogue: 0,0:50:24.78,0:50:25.82,EN,,0,0,0,,slightly differently,\nDialogue: 0,0:50:26.84,0:50:27.90,EN,,0,0,0,,so you wouldn't feel\nDialogue: 0,0:50:29.07,0:50:30.86,EN,,0,0,0,,that the first one was a trick.\nDialogue: 0,0:50:32.54,0:50:33.45,EN,,0,0,0,,They may be both tricks,\nDialogue: 0,0:50:33.80,0:50:35.15,EN,,0,0,0,,but they're at least slightly different.\nDialogue: 0,0:50:37.30,0:50:39.20,EN,,0,0,0,,So I suppose that pretty much wraps it up.\nDialogue: 0,0:50:40.03,0:50:41.97,EN,,0,0,0,,I've just proved what we call the halting theorem,\nDialogue: 0,0:50:43.00,0:50:44.70,EN,,0,0,0,,and I suppose with that we're going to halt.\nDialogue: 0,0:50:46.72,0:50:47.63,EN,,0,0,0,,I hope you have a good time.\nDialogue: 0,0:50:50.90,0:50:51.76,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:50:53.30,0:50:53.56,EN,,0,0,0,,Yes.\nDialogue: 0,0:50:53.81,0:50:56.27,EN,,0,0,0,,AUDIENCE: What is the value of s of diag1?\nDialogue: 0,0:50:56.75,0:50:57.23,EN,,0,0,0,,PROFESSOR: Of what?\nDialogue: 0,0:50:57.50,0:50:58.80,EN,,0,0,0,,AUDIENCE: S of diag1.\nDialogue: 0,0:51:00.12,0:51:02.20,EN,,0,0,0,,If you said s is a function, and then we can\nDialogue: 0,0:51:02.30,0:51:03.63,EN,,0,0,0,,PROFESSOR: Oh, I don't know.\nDialogue: 0,0:51:03.87,0:51:04.35,EN,,0,0,0,,I don't know.\nDialogue: 0,0:51:04.35,0:51:04.88,EN,,0,0,0,,It's a function,\nDialogue: 0,0:51:04.88,0:51:05.85,EN,,0,0,0,,but I don't know how to compute it.\nDialogue: 0,0:51:06.80,0:51:08.00,EN,,0,0,0,,I can't do it.\nDialogue: 0,0:51:08.61,0:51:09.64,EN,,0,0,0,,I'm just a machine, too.\nDialogue: 0,0:51:11.53,0:51:11.88,EN,,0,0,0,,Right?\nDialogue: 0,0:51:11.90,0:51:13.37,EN,,0,0,0,,And there's no machine\nDialogue: 0,0:51:13.37,0:51:14.05,EN,,0,0,0,,that in principle--\nDialogue: 0,0:51:14.47,0:51:16.87,EN,,0,0,0,,it might be that in that particular case you just asked,\nDialogue: 0,0:51:16.87,0:51:18.32,EN,,0,0,0,,with some thinking I could figure it out.\nDialogue: 0,0:51:18.58,0:51:19.37,EN,,0,0,0,,But in general\nDialogue: 0,0:51:19.60,0:51:21.05,EN,,0,0,0,,I can't compute the value of s\nDialogue: 0,0:51:21.05,0:51:22.52,EN,,0,0,0,,any better than any other machine can.\nDialogue: 0,0:51:23.78,0:51:24.92,EN,,0,0,0,,There is such a function,\nDialogue: 0,0:51:25.92,0:51:28.00,EN,,0,0,0,,it's just that no machine can be built to compute it.\nDialogue: 0,0:51:29.58,0:51:30.05,EN,,0,0,0,,Now\nDialogue: 0,0:51:30.67,0:51:33.67,EN,,0,0,0,,there's a way of saying that that should not be surprising.\nDialogue: 0,0:51:35.22,0:51:36.25,EN,,0,0,0,,Going through this--\nDialogue: 0,0:51:36.25,0:51:38.36,EN,,0,0,0,,I mean, I don't have time to do this here,\nDialogue: 0,0:51:38.45,0:51:43.00,EN,,0,0,0,,but the number of functions is very large.\nDialogue: 0,0:51:44.40,0:51:47.58,EN,,0,0,0,,If there's a certain number of answers possible\nDialogue: 0,0:51:47.75,0:51:49.62,EN,,0,0,0,,and a certain number of inputs possible,\nDialogue: 0,0:51:49.87,0:51:51.80,EN,,0,0,0,,then it's the number of answers raised to the number inputs\nDialogue: 0,0:51:51.80,0:51:53.20,EN,,0,0,0,,is the number of possible functions.\nDialogue: 0,0:51:54.50,0:51:55.48,EN,,0,0,0,,On one variable.\nDialogue: 0,0:51:56.51,0:51:59.24,EN,,0,0,0,,Now that's always bigger\nDialogue: 0,0:52:00.09,0:52:03.21,EN,,0,0,0,,than the thing you're raising to,\nDialogue: 0,0:52:03.58,0:52:04.32,EN,,0,0,0,,the exponent.\nDialogue: 0,0:52:05.48,0:52:09.80,EN,,0,0,0,,The number of functions is larger\nDialogue: 0,0:52:09.95,0:52:12.72,EN,,0,0,0,,than the number of programs\nDialogue: 0,0:52:13.30,0:52:14.10,EN,,0,0,0,,that one can write,\nDialogue: 0,0:52:14.82,0:52:16.45,EN,,0,0,0,,by an infinity counting argument.\nDialogue: 0,0:52:17.57,0:52:19.00,EN,,0,0,0,,And it's much larger.\nDialogue: 0,0:52:19.47,0:52:22.12,EN,,0,0,0,,So there must be a lot of functions\nDialogue: 0,0:52:22.12,0:52:23.48,EN,,0,0,0,,that can't be computed by programs.\nDialogue: 0,0:52:25.92,0:52:26.59,EN,,0,0,0,,AUDIENCE: A few moments ago\nDialogue: 0,0:52:26.64,0:52:28.25,EN,,0,0,0,,you were talking about specifications\nDialogue: 0,0:52:28.30,0:52:30.04,EN,,0,0,0,,and automatic generation of solutions.\nDialogue: 0,0:52:30.64,0:52:31.61,EN,,0,0,0,,Do you see any steps\nDialogue: 0,0:52:31.82,0:52:33.36,EN,,0,0,0,,between specifications and solutions?\nDialogue: 0,0:52:37.25,0:52:38.22,EN,,0,0,0,,PROFESSOR: Steps between.\nDialogue: 0,0:52:38.72,0:52:39.37,EN,,0,0,0,,You mean, you're saying,\nDialogue: 0,0:52:39.37,0:52:42.60,EN,,0,0,0,,how you go about constructing\nDialogue: 0,0:52:42.60,0:52:44.78,EN,,0,0,0,,devices given that have specifications for the device?\nDialogue: 0,0:52:45.05,0:52:48.36,EN,,0,0,0,,AUDIENCE: There's a lot of software engineering\nDialogue: 0,0:52:48.36,0:52:49.90,EN,,0,0,0,,that goes through specifications through\nDialogue: 0,0:52:49.90,0:52:51.90,EN,,0,0,0,,many layers of design and then implementation.\nDialogue: 0,0:52:52.43,0:52:52.85,EN,,0,0,0,,PROFESSOR: Yes?\nDialogue: 0,0:52:52.85,0:52:53.70,EN,,0,0,0,,AUDIENCE: I was curious\nDialogue: 0,0:52:53.70,0:52:54.62,EN,,0,0,0,,if you think that's realistic.\nDialogue: 0,0:52:55.60,0:52:57.17,EN,,0,0,0,,PROFESSOR: Well I think that some of it's realistic\nDialogue: 0,0:52:57.17,0:52:58.10,EN,,0,0,0,,and some of it isn't.\nDialogue: 0,0:52:58.10,0:53:00.32,EN,,0,0,0,,I mean, surely if I want to build an electrical filter\nDialogue: 0,0:53:01.17,0:53:07.16,EN,,0,0,0,,and I have a rather interesting possibility.\nDialogue: 0,0:53:07.16,0:53:09.42,EN,,0,0,0,,Supposing I want to build a thing that matches\nDialogue: 0,0:53:09.64,0:53:14.07,EN,,0,0,0,,that matches some power output to the radio transmitter,\nDialogue: 0,0:53:14.47,0:53:18.75,EN,,0,0,0,,to some antenna.\nDialogue: 0,0:53:19.90,0:53:21.47,EN,,0,0,0,,And I'm really out of this power--\nDialogue: 0,0:53:21.48,0:53:23.04,EN,,0,0,0,,it's output tube out here.\nDialogue: 0,0:53:23.23,0:53:25.26,EN,,0,0,0,,And the problem is that they have different impedances.\nDialogue: 0,0:53:25.92,0:53:27.55,EN,,0,0,0,,I want them to match the impedances.\nDialogue: 0,0:53:27.55,0:53:28.97,EN,,0,0,0,,I also want to make a filter in there\nDialogue: 0,0:53:29.15,0:53:31.71,EN,,0,0,0,,which is going to get rid of some harmonic radiation.\nDialogue: 0,0:53:32.78,0:53:36.63,EN,,0,0,0,,Well one old-fashioned technique for doing this is called\nDialogue: 0,0:53:36.82,0:53:38.67,EN,,0,0,0,,image impedances, or something like that.\nDialogue: 0,0:53:38.86,0:53:39.50,EN,,0,0,0,,And what you do\nDialogue: 0,0:53:39.50,0:53:40.85,EN,,0,0,0,,is you say you have a basic module\nDialogue: 0,0:53:40.85,0:53:42.75,EN,,0,0,0,,called an L-section.\nDialogue: 0,0:53:43.30,0:53:43.98,EN,,0,0,0,,Looks like this.\nDialogue: 0,0:53:47.08,0:53:49.80,EN,,0,0,0,,If I happen to connect this to some resistance, r,\nDialogue: 0,0:53:50.05,0:53:52.60,EN,,0,0,0,,and if I make this impedance x, xl,\nDialogue: 0,0:53:52.72,0:53:55.20,EN,,0,0,0,,and if it happens to be q times r,\nDialogue: 0,0:53:55.26,0:53:58.52,EN,,0,0,0,,then this produces a low pass filter\nDialogue: 0,0:53:58.52,0:54:00.72,EN,,0,0,0,,with a q square plus one impedance match.\nDialogue: 0,0:54:02.11,0:54:02.86,EN,,0,0,0,,Just what I need.\nDialogue: 0,0:54:03.12,0:54:04.28,EN,,0,0,0,,Because now I can take two of these,\nDialogue: 0,0:54:04.30,0:54:05.08,EN,,0,0,0,,hook them together\nDialogue: 0,0:54:05.82,0:54:06.38,EN,,0,0,0,,like this.\nDialogue: 0,0:54:11.66,0:54:13.15,EN,,0,0,0,,OK, and I take another one\nDialogue: 0,0:54:16.00,0:54:17.45,EN,,0,0,0,,and I'll hook them together like that.\nDialogue: 0,0:54:18.29,0:54:19.95,EN,,0,0,0,,And I have two L-sections hooked together.\nDialogue: 0,0:54:20.32,0:54:23.07,EN,,0,0,0,,And this will step the impedance down to one that I know,\nDialogue: 0,0:54:23.37,0:54:25.22,EN,,0,0,0,,and this will step it up to one I know.\nDialogue: 0,0:54:25.53,0:54:26.64,EN,,0,0,0,,Each of these is a low pass filter\nDialogue: 0,0:54:26.67,0:54:27.82,EN,,0,0,0,,getting rid of some harmonics.\nDialogue: 0,0:54:28.09,0:54:29.07,EN,,0,0,0,,It's good filter,\nDialogue: 0,0:54:29.07,0:54:30.27,EN,,0,0,0,,it's called a pie-section filter.\nDialogue: 0,0:54:30.27,0:54:30.62,EN,,0,0,0,,Great.\nDialogue: 0,0:54:31.70,0:54:34.09,EN,,0,0,0,,Except for the fact that in doing what I just did,\nDialogue: 0,0:54:34.12,0:54:37.85,EN,,0,0,0,,I've made a terrible inefficiency in this system.\nDialogue: 0,0:54:38.62,0:54:39.60,EN,,0,0,0,,I've made two coils\nDialogue: 0,0:54:39.61,0:54:40.59,EN,,0,0,0,,where I should have made one.\nDialogue: 0,0:54:41.62,0:54:44.60,EN,,0,0,0,,And the problem with most software engineering art\nDialogue: 0,0:54:44.89,0:54:46.88,EN,,0,0,0,,is that there's no mechanism,\nDialogue: 0,0:54:46.92,0:54:48.65,EN,,0,0,0,,other than people optimization and compilers,\nDialogue: 0,0:54:48.80,0:54:51.34,EN,,0,0,0,,for getting rid of the redundant parts\nDialogue: 0,0:54:51.34,0:54:53.55,EN,,0,0,0,,that are constructed when doing top down design.\nDialogue: 0,0:54:55.35,0:54:56.07,EN,,0,0,0,,It's even worse,\nDialogue: 0,0:54:56.07,0:54:57.58,EN,,0,0,0,,there are lots of very important structures\nDialogue: 0,0:54:57.60,0:54:59.02,EN,,0,0,0,,that you can't construct at all this way.\nDialogue: 0,0:55:01.11,0:55:03.53,EN,,0,0,0,,So I think that the standard top down design\nDialogue: 0,0:55:03.53,0:55:04.87,EN,,0,0,0,,is a rather shallow business.\nDialogue: 0,0:55:05.71,0:55:06.60,EN,,0,0,0,,Doesn't really capture\nDialogue: 0,0:55:06.60,0:55:08.10,EN,,0,0,0,,what people want to do in design.\nDialogue: 0,0:55:08.31,0:55:10.10,EN,,0,0,0,,I'll give you another electrical example.\nDialogue: 0,0:55:10.10,0:55:11.75,EN,,0,0,0,,Electrical examples are so much clearer\nDialogue: 0,0:55:11.90,0:55:13.13,EN,,0,0,0,,than computational examples,\nDialogue: 0,0:55:13.16,0:55:14.78,EN,,0,0,0,,because computation examples require\nDialogue: 0,0:55:14.80,0:55:16.52,EN,,0,0,0,,a certain degree of complexity to explain them.\nDialogue: 0,0:55:17.22,0:55:19.16,EN,,0,0,0,,But one of my favorite examples\nDialogue: 0,0:55:19.16,0:55:20.04,EN,,0,0,0,,in the electrical world\nDialogue: 0,0:55:20.60,0:55:22.80,EN,,0,0,0,,is how would I ever come up with the output stage\nDialogue: 0,0:55:23.28,0:55:26.55,EN,,0,0,0,,of this inter-stage connection in an IF amplifier.\nDialogue: 0,0:55:27.53,0:55:29.44,EN,,0,0,0,,It's a little transistor here,\nDialogue: 0,0:55:29.52,0:55:31.50,EN,,0,0,0,,and let's see.\nDialogue: 0,0:55:32.41,0:55:33.40,EN,,0,0,0,,Well I'm going to have a tank,\nDialogue: 0,0:55:36.45,0:55:39.17,EN,,0,0,0,,and I'm going to hook this up to, say,\nDialogue: 0,0:55:41.37,0:55:43.97,EN,,0,0,0,,I'm going to link-couple that to the input of the next stage.\nDialogue: 0,0:55:44.36,0:55:47.47,EN,,0,0,0,,Here's a perfectly plausible plan--\nDialogue: 0,0:55:48.22,0:55:50.87,EN,,0,0,0,,well except for the fact that since I put that going up\nDialogue: 0,0:55:50.87,0:55:52.92,EN,,0,0,0,,I should make that going that way. OK?\nDialogue: 0,0:55:53.17,0:55:55.45,EN,,0,0,0,,Here's a perfectly plausible plan for a--\nDialogue: 0,0:55:55.98,0:55:56.57,EN,,0,0,0,,no I shouldn't.\nDialogue: 0,0:55:57.12,0:55:57.79,EN,,0,0,0,,I'm dumb.\nDialogue: 0,0:55:58.40,0:55:59.07,EN,,0,0,0,,Excuse me.\nDialogue: 0,0:55:59.69,0:56:00.42,EN,,0,0,0,,Doesn't matter.\nDialogue: 0,0:56:00.73,0:56:01.54,EN,,0,0,0,,The point is it's a perfect\nDialogue: 0,0:56:01.54,0:56:03.42,EN,,0,0,0,,plan for a couple two stages together.\nDialogue: 0,0:56:04.54,0:56:06.92,EN,,0,0,0,,Now what the problem is what's this hierarchically?\nDialogue: 0,0:56:07.62,0:56:08.80,EN,,0,0,0,,It's not one thing.\nDialogue: 0,0:56:09.48,0:56:11.99,EN,,0,0,0,,Hierarchically it doesn't make any sense at all.\nDialogue: 0,0:56:11.99,0:56:14.32,EN,,0,0,0,,It's the inductance of a tuned circuit,\nDialogue: 0,0:56:15.55,0:56:18.02,EN,,0,0,0,,it's the primary of a transformer,\nDialogue: 0,0:56:19.10,0:56:21.82,EN,,0,0,0,,and it's also the DC path by\nDialogue: 0,0:56:21.82,0:56:23.57,EN,,0,0,0,,which bias conditions get to the\nDialogue: 0,0:56:23.57,0:56:25.10,EN,,0,0,0,,collector of that transistor.\nDialogue: 0,0:56:26.46,0:56:28.35,EN,,0,0,0,,And there's no simple top-down design\nDialogue: 0,0:56:28.38,0:56:30.17,EN,,0,0,0,,that's going to produce a structure like that\nDialogue: 0,0:56:30.22,0:56:34.02,EN,,0,0,0,,with so many overlapping uses for a particular thing.\nDialogue: 0,0:56:34.53,0:56:36.72,EN,,0,0,0,,Playing Scrabble,\nDialogue: 0,0:56:36.96,0:56:39.88,EN,,0,0,0,,where you have to do triple word scores, or whatever,\nDialogue: 0,0:56:40.49,0:56:43.60,EN,,0,0,0,,is not so easy in top-down design strategy.\nDialogue: 0,0:56:44.95,0:56:47.08,EN,,0,0,0,,Yet most of real engineering is based on\nDialogue: 0,0:56:47.36,0:56:50.70,EN,,0,0,0,,on getting the most oomph for effort.\nDialogue: 0,0:56:52.14,0:56:53.52,EN,,0,0,0,,And that's what you're seeing here.\nDialogue: 0,0:56:54.86,0:56:55.55,EN,,0,0,0,,Yeah?\nDialogue: 0,0:56:55.55,0:56:56.81,EN,,0,0,0,,AUDIENCE: Is this the last question?\nDialogue: 0,0:57:00.28,0:57:02.03,EN,,0,0,0,,[LAUGHTER]\nDialogue: 0,0:57:18.64,0:57:19.63,EN,,0,0,0,,PROFESSOR: Apparently so.\nDialogue: 0,0:57:23.57,0:57:24.12,EN,,0,0,0,,Thank you.\nDialogue: 0,0:57:25.30,0:57:36.50,EN,,0,0,0,,[APPLAUSE]\n"
  },
  {
    "path": "Ass/lec1a.chn+eng.ass",
    "content": "﻿[Script Info]\r\n; Script generated by Aegisub 3.0.2\r\n; http://www.aegisub.org/\r\nTitle: Default Aegisub file\r\nScriptType: v4.00+\r\nWrapStyle: 0\r\nScaledBorderAndShadow: yes\r\nCollisions: Normal\r\nPlayResX: 640\r\nPlayResY: 480\r\nScroll Position: 1037\r\nActive Line: 1035\r\nAudio URI: lec1a_Rerip_remux.mp4\r\nVideo Zoom Percent: 0.875\r\nVideo File: lec1a_Rerip_remux.mp4\r\nVideo Aspect Ratio: c1.33333\r\nVideo Position: 1302\r\nLast Style Storage: Default\r\nYCbCr Matrix: TV.601\r\n\r\n[V4+ Styles]\r\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\r\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\r\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\r\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\r\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\r\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\r\n\r\n[Events]\r\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\nDialogue: 0,0:00:14.71,0:00:17.89,EN,,0,0,0,,I'd like to welcome you to this course on computer science.\r\nDialogue: 0,0:00:28.40,0:00:29.85,EN,,0,0,0,,Actually, that's a terrible way to start.\r\nDialogue: 0,0:00:29.85,0:00:32.34,EN,,0,0,0,,Computer science is a terrible name for this business.\r\nDialogue: 0,0:00:32.83,0:00:34.30,EN,,0,0,0,,First of all, it's not a science.\r\nDialogue: 0,0:00:35.92,0:00:39.81,EN,,0,0,0,,It might be engineering or it might be art,\r\nDialogue: 0,0:00:40.09,0:00:42.91,EN,,0,0,0,,but we'll actually see that computer so-called science\r\nDialogue: 0,0:00:42.93,0:00:44.97,EN,,0,0,0,,actually has a lot in common with magic,\r\nDialogue: 0,0:00:45.01,0:00:46.35,EN,,0,0,0,,and we'll see that in this course.\r\nDialogue: 0,0:00:47.28,0:00:48.22,EN,,0,0,0,,So it's not a science.\r\nDialogue: 0,0:00:48.23,0:00:52.30,EN,,0,0,0,,It's also not really very much about computers.\r\nDialogue: 0,0:00:53.39,0:00:55.47,EN,,0,0,0,,And it's not about computers in the same sense\r\nDialogue: 0,0:00:55.47,0:01:00.05,EN,,0,0,0,,that physics is not really about particle accelerators,\r\nDialogue: 0,0:01:00.80,0:01:05.58,EN,,0,0,0,,and biology is not really about microscopes and petri dishes.\r\nDialogue: 0,0:01:06.46,0:01:10.25,EN,,0,0,0,,And it's not about computers in the same sense\r\nDialogue: 0,0:01:10.31,0:01:14.88,EN,,0,0,0,,that geometry is not really about using surveying instruments.\r\nDialogue: 0,0:01:16.48,0:01:19.01,EN,,0,0,0,,In fact, there's a lot of commonality\r\nDialogue: 0,0:01:19.33,0:01:21.45,EN,,0,0,0,,between computer science and geometry.\r\nDialogue: 0,0:01:21.45,0:01:22.66,EN,,0,0,0,,Geometry, first of all,\r\nDialogue: 0,0:01:23.02,0:01:24.98,EN,,0,0,0,,is another subject with a lousy name.\r\nDialogue: 0,0:01:25.58,0:01:27.85,EN,,0,0,0,,The name comes from Gaia, meaning the Earth,\r\nDialogue: 0,0:01:27.90,0:01:29.09,EN,,0,0,0,,and metron, meaning to measure.\r\nDialogue: 0,0:01:29.82,0:01:33.39,EN,,0,0,0,,Geometry originally meant measuring the Earth or surveying.\r\nDialogue: 0,0:01:34.37,0:01:36.89,EN,,0,0,0,,And the reason for that was that, thousands of years ago,\r\nDialogue: 0,0:01:37.69,0:01:41.69,EN,,0,0,0,,the Egyptian priesthood developed the rudiments of geometry\r\nDialogue: 0,0:01:42.59,0:01:46.33,EN,,0,0,0,,in order to figure out how to restore the boundaries of fields\r\nDialogue: 0,0:01:46.35,0:01:48.69,EN,,0,0,0,,that were destroyed in the annual flooding of the Nile.\r\nDialogue: 0,0:01:49.47,0:01:50.65,EN,,0,0,0,,And to the Egyptians who did that,\r\nDialogue: 0,0:01:50.65,0:01:53.93,EN,,0,0,0,,geometry really was the use of surveying instruments.\r\nDialogue: 0,0:01:55.63,0:01:58.55,EN,,0,0,0,,Now, the reason that we think computer science is about computers\r\nDialogue: 0,0:01:58.57,0:02:02.49,EN,,0,0,0,,is pretty much the same reason that the Egyptians thought geometry\r\nDialogue: 0,0:02:02.51,0:02:04.10,EN,,0,0,0,,was about surveying instruments.\r\nDialogue: 0,0:02:04.59,0:02:07.37,EN,,0,0,0,,And that is, when some field is just getting started\r\nDialogue: 0,0:02:07.39,0:02:09.86,EN,,0,0,0,,and you don't really understand it very well,\r\nDialogue: 0,0:02:11.10,0:02:16.64,EN,,0,0,0,,it's very easy to confuse the essence of what you're doing with the tools that you use.\r\nDialogue: 0,0:02:17.65,0:02:20.30,EN,,0,0,0,,And indeed, on some absolute scale of things,\r\nDialogue: 0,0:02:20.30,0:02:24.82,EN,,0,0,0,,we probably know less about the essence of computer science\r\nDialogue: 0,0:02:24.83,0:02:27.49,EN,,0,0,0,,than the ancient Egyptians really knew about geometry.\r\nDialogue: 0,0:02:30.25,0:02:32.64,EN,,0,0,0,,Well, what do I mean by the essence of computer science?\r\nDialogue: 0,0:02:32.65,0:02:34.41,EN,,0,0,0,,What do I mean by the essence of geometry?\r\nDialogue: 0,0:02:34.41,0:02:36.45,EN,,0,0,0,,See, it's certainly true that these Egyptians went off\r\nDialogue: 0,0:02:36.46,0:02:37.67,EN,,0,0,0,,and used surveying instruments,\r\nDialogue: 0,0:02:37.69,0:02:41.55,EN,,0,0,0,,but when we look back on them after a couple of thousand years,\r\nDialogue: 0,0:02:41.57,0:02:41.85,EN,,0,0,0,,we say,\r\nDialogue: 0,0:02:41.87,0:02:43.64,EN,,0,0,0,,gee, what they were doing,\r\nDialogue: 0,0:02:43.71,0:02:45.48,EN,,0,0,0,,the important stuff they were doing,\r\nDialogue: 0,0:02:45.62,0:02:50.45,EN,,0,0,0,,was to begin to formalize notions about space and time,\r\nDialogue: 0,0:02:51.58,0:02:57.53,EN,,0,0,0,,to start a way of talking about mathematical truths formally.\r\nDialogue: 0,0:02:58.01,0:02:59.61,EN,,0,0,0,,That led to the axiomatic method.\r\nDialogue: 0,0:02:59.61,0:03:02.53,EN,,0,0,0,,That led to sort of all of modern mathematics,\r\nDialogue: 0,0:03:04.16,0:03:06.90,EN,,0,0,0,,figuring out a way to talk precisely about\r\nDialogue: 0,0:03:07.25,0:03:10.19,EN,,0,0,0,,so-called declarative knowledge, what is true.\r\nDialogue: 0,0:03:12.45,0:03:16.25,EN,,0,0,0,,Well, similarly, I think in the future people will look back and say,\r\nDialogue: 0,0:03:16.27,0:03:19.36,EN,,0,0,0,,yes, those primitives in the 20th century were fiddling around\r\nDialogue: 0,0:03:19.36,0:03:21.20,EN,,0,0,0,,with these gadgets called computers,\r\nDialogue: 0,0:03:21.77,0:03:26.25,EN,,0,0,0,,but really what they were doing is starting to learn\r\nDialogue: 0,0:03:26.25,0:03:32.55,EN,,0,0,0,,how to formalize intuitions about process,\r\nDialogue: 0,0:03:32.64,0:03:34.13,EN,,0,0,0,,how to do things,\r\nDialogue: 0,0:03:39.02,0:03:51.25,EN,,0,0,0,,starting to develop a way to talk precisely about how-to knowledge,\r\nDialogue: 0,0:03:51.76,0:03:56.03,EN,,0,0,0,,as opposed to geometry that talks about what is true.\r\nDialogue: 0,0:03:56.53,0:03:58.57,EN,,0,0,0,,Let me give you an example of that.\r\nDialogue: 0,0:04:02.30,0:04:02.69,EN,,0,0,0,,Let's take a look\r\nDialogue: 0,0:04:02.70,0:04:09.82,EN,,0,0,0,,Here is a piece of mathematics that says what a square root is.\r\nDialogue: 0,0:04:10.09,0:04:14.35,EN,,0,0,0,,The square root of X is the number Y,\r\nDialogue: 0,0:04:15.98,0:04:20.38,EN,,0,0,0,,such that Y squared is equal to X and Y is greater than 0.\r\nDialogue: 0,0:04:20.43,0:04:22.50,EN,,0,0,0,,Now, that's a fine piece of mathematics,\r\nDialogue: 0,0:04:22.88,0:04:25.25,EN,,0,0,0,,but just telling you what a square root is\r\nDialogue: 0,0:04:25.63,0:04:30.29,EN,,0,0,0,,doesn't really say anything about how you might go out and find one.\r\nDialogue: 0,0:04:31.42,0:04:35.90,EN,,0,0,0,,So let's contrast that with a piece of imperative knowledge,\r\nDialogue: 0,0:04:37.13,0:04:39.92,EN,,0,0,0,,how you might go out and find a square root.\r\nDialogue: 0,0:04:39.95,0:04:45.74,EN,,0,0,0,,This, in fact, also comes from Egypt, not ancient, ancient Egypt.\r\nDialogue: 0,0:04:45.76,0:04:48.88,EN,,0,0,0,,This is an algorithm due to Heron of Alexandria,\r\nDialogue: 0,0:04:49.90,0:04:52.77,EN,,0,0,0,,called how to find a square root by successive averaging.\r\nDialogue: 0,0:04:52.89,0:04:55.13,EN,,0,0,0,,And what it says is that,\r\nDialogue: 0,0:04:55.15,0:04:58.06,EN,,0,0,0,,in order to find a square root,\r\nDialogue: 0,0:05:03.34,0:05:08.33,EN,,0,0,0,,you make a guess, you improve that guess --\r\nDialogue: 0,0:05:10.19,0:05:11.44,EN,,0,0,0,,and the way you improve the guess\r\nDialogue: 0,0:05:11.45,0:05:13.95,EN,,0,0,0,,is to average the guess and X over the guess,\r\nDialogue: 0,0:05:14.41,0:05:15.60,EN,,0,0,0,,and we'll talk a little bit later about\r\nDialogue: 0,0:05:15.61,0:05:17.12,EN,,0,0,0,,why that's a reasonable thing--\r\nDialogue: 0,0:05:17.14,0:05:19.37,EN,,0,0,0,,and you keep improving the guess until it's good enough.\r\nDialogue: 0,0:05:19.73,0:05:20.85,EN,,0,0,0,,That's a method.\r\nDialogue: 0,0:05:20.99,0:05:24.65,EN,,0,0,0,,That's how to do something as opposed to\r\nDialogue: 0,0:05:24.72,0:05:27.33,EN,,0,0,0,,declarative knowledge that says what you're looking for.\r\nDialogue: 0,0:05:28.05,0:05:29.76,EN,,0,0,0,,That's a process.\r\nDialogue: 0,0:05:34.40,0:05:38.25,EN,,0,0,0,,Well, what's a process in general?\r\nDialogue: 0,0:05:39.01,0:05:40.14,EN,,0,0,0,,It's kind of hard to say.\r\nDialogue: 0,0:05:40.16,0:05:43.72,EN,,0,0,0,,You can think of it as like a magical spirit\r\nDialogue: 0,0:05:44.77,0:05:47.33,EN,,0,0,0,,that sort of lives in the computer and does something.\r\nDialogue: 0,0:05:48.01,0:05:54.11,EN,,0,0,0,,And the thing that directs a process is\r\nDialogue: 0,0:05:54.13,0:05:57.98,EN,,0,0,0,,a pattern of rules called a procedure.\r\nDialogue: 0,0:06:01.98,0:06:04.73,EN,,0,0,0,,So procedures are the spells, if you like,\r\nDialogue: 0,0:06:05.23,0:06:09.40,EN,,0,0,0,,that control these magical spirits that are the processes.\r\nDialogue: 0,0:06:10.75,0:06:12.75,EN,,0,0,0,,I guess you know everyone needs a magical language,\r\nDialogue: 0,0:06:12.77,0:06:14.55,EN,,0,0,0,,and sorcerers, real sorcerers,\r\nDialogue: 0,0:06:14.57,0:06:18.59,EN,,0,0,0,,use ancient Arcadian or Sumerian or Babylonian or whatever.\r\nDialogue: 0,0:06:18.62,0:06:20.09,EN,,0,0,0,,We're going to conjure our spirits\r\nDialogue: 0,0:06:20.13,0:06:22.71,EN,,0,0,0,,in a magical language called Lisp,\r\nDialogue: 0,0:06:24.37,0:06:28.01,EN,,0,0,0,,which is a language designed for talking about,\r\nDialogue: 0,0:06:28.57,0:06:31.84,EN,,0,0,0,,for casting the spells that are procedures to direct the processes.\r\nDialogue: 0,0:06:31.87,0:06:33.91,EN,,0,0,0,,Now, it's very easy to learn Lisp.\r\nDialogue: 0,0:06:33.97,0:06:35.98,EN,,0,0,0,,In fact, in a few minutes, I'm going to teach you,\r\nDialogue: 0,0:06:36.00,0:06:37.16,EN,,0,0,0,,essentially, all of Lisp.\r\nDialogue: 0,0:06:37.37,0:06:38.96,EN,,0,0,0,,I'm going to teach you, essentially, all of the rules.\r\nDialogue: 0,0:06:40.77,0:06:43.65,EN,,0,0,0,,And you shouldn't find that particularly surprising.\r\nDialogue: 0,0:06:43.69,0:06:45.87,EN,,0,0,0,,That's sort of like saying it's very easy\r\nDialogue: 0,0:06:45.90,0:06:47.01,EN,,0,0,0,,to learn the rules of chess.\r\nDialogue: 0,0:06:47.04,0:06:48.13,EN,,0,0,0,,And indeed, in a few minutes,\r\nDialogue: 0,0:06:48.17,0:06:49.70,EN,,0,0,0,,you can tell somebody the rules of chess.\r\nDialogue: 0,0:06:50.81,0:06:52.24,EN,,0,0,0,,But of course, that's very different from\r\nDialogue: 0,0:06:52.25,0:06:55.37,EN,,0,0,0,,saying you understand the implications of those rules\r\nDialogue: 0,0:06:55.42,0:06:58.05,EN,,0,0,0,,and how to use those rules to become a masterful chess player.\r\nDialogue: 0,0:06:58.49,0:06:59.82,EN,,0,0,0,,Well, Lisp is the same way.\r\nDialogue: 0,0:07:00.41,0:07:02.18,EN,,0,0,0,,We're going to state the rules in a few minutes,\r\nDialogue: 0,0:07:02.36,0:07:03.55,EN,,0,0,0,,and it'll be very easy to see.\r\nDialogue: 0,0:07:03.62,0:07:07.09,EN,,0,0,0,,But what's really hard is going to be the implications of those rules,\r\nDialogue: 0,0:07:07.32,0:07:10.46,EN,,0,0,0,,how you exploit those rules to be a master programmer.\r\nDialogue: 0,0:07:12.06,0:07:15.29,EN,,0,0,0,,And the implications of those rules are going to take us the,\r\nDialogue: 0,0:07:15.31,0:07:18.56,EN,,0,0,0,,well, the whole rest of the subject and, of course, way beyond.\r\nDialogue: 0,0:07:21.45,0:07:23.11,EN,,0,0,0,,OK, so in computer science,\r\nDialogue: 0,0:07:24.49,0:07:26.19,EN,,0,0,0,,we're in the business of\r\nDialogue: 0,0:07:26.21,0:07:30.58,EN,,0,0,0,,formalizing this sort of how-to imperative knowledge,\r\nDialogue: 0,0:07:30.62,0:07:32.10,EN,,0,0,0,,how to do stuff.\r\nDialogue: 0,0:07:33.37,0:07:35.39,EN,,0,0,0,,And the real issues of computer science are, of course,\r\nDialogue: 0,0:07:35.41,0:07:38.36,EN,,0,0,0,,not telling people how to do square roots.\r\nDialogue: 0,0:07:39.09,0:07:40.06,EN,,0,0,0,,Because if that was all it was,\r\nDialogue: 0,0:07:40.09,0:07:41.34,EN,,0,0,0,,there wouldn't be no big deal.\r\nDialogue: 0,0:07:41.57,0:07:44.05,EN,,0,0,0,,The real problems come when we try to\r\nDialogue: 0,0:07:44.08,0:07:46.16,EN,,0,0,0,,build very, very large systems,\r\nDialogue: 0,0:07:46.61,0:07:49.53,EN,,0,0,0,,computer programs that are thousands of pages long,\r\nDialogue: 0,0:07:49.58,0:07:53.98,EN,,0,0,0,,so long that nobody can really hold them in their heads all at once.\r\nDialogue: 0,0:07:54.73,0:07:58.81,EN,,0,0,0,,And the only reason that that's possible is because\r\nDialogue: 0,0:07:58.86,0:08:18.97,EN,,0,0,0,,there are techniques for controlling the complexity of these large systems.\r\nDialogue: 0,0:08:20.30,0:08:22.69,EN,,0,0,0,,And these techniques that are controlling complexity\r\nDialogue: 0,0:08:22.72,0:08:24.17,EN,,0,0,0,,are what this course is really about.\r\nDialogue: 0,0:08:24.65,0:08:25.47,EN,,0,0,0,,And in some sense,\r\nDialogue: 0,0:08:25.50,0:08:27.47,EN,,0,0,0,,that's really what computer science is about.\r\nDialogue: 0,0:08:29.63,0:08:31.89,EN,,0,0,0,,Now, that may seem like a very strange thing to say.\r\nDialogue: 0,0:08:31.92,0:08:35.61,EN,,0,0,0,,Because after all, a lot of people besides computer scientists\r\nDialogue: 0,0:08:35.65,0:08:37.82,EN,,0,0,0,,deal with controlling complexity.\r\nDialogue: 0,0:08:37.84,0:08:41.02,EN,,0,0,0,,A large airliner is an extremely complex system,\r\nDialogue: 0,0:08:41.82,0:08:43.79,EN,,0,0,0,,and the aeronautical engineers who design that\r\nDialogue: 0,0:08:44.05,0:08:46.13,EN,,0,0,0,,are dealing with immense complexity.\r\nDialogue: 0,0:08:47.09,0:08:50.19,EN,,0,0,0,,But there's a difference between that kind of complexity\r\nDialogue: 0,0:08:50.75,0:08:52.60,EN,,0,0,0,,and what we deal with in computer science.\r\nDialogue: 0,0:08:55.18,0:08:57.73,EN,,0,0,0,,And that is that computer science,\r\nDialogue: 0,0:08:57.79,0:09:00.09,EN,,0,0,0,,in some sense, isn't real.\r\nDialogue: 0,0:09:02.69,0:09:06.62,EN,,0,0,0,,You see, when an engineer is designing a physical system,\r\nDialogue: 0,0:09:07.14,0:09:08.49,EN,,0,0,0,,that's made out of real parts.\r\nDialogue: 0,0:09:09.40,0:09:11.18,EN,,0,0,0,,The engineers who worry about that\r\nDialogue: 0,0:09:11.85,0:09:16.65,EN,,0,0,0,,have to address problems of tolerance and approximation and noise in the system.\r\nDialogue: 0,0:09:16.67,0:09:19.02,EN,,0,0,0,,So for example, as an electrical engineer,\r\nDialogue: 0,0:09:19.09,0:09:21.71,EN,,0,0,0,,I can go off and easily build a one-stage amplifier\r\nDialogue: 0,0:09:21.73,0:09:23.03,EN,,0,0,0,,or a two-stage amplifier,\r\nDialogue: 0,0:09:23.41,0:09:25.39,EN,,0,0,0,,and I can imagine cascading a lot of them\r\nDialogue: 0,0:09:25.45,0:09:26.91,EN,,0,0,0,,to build a million-stage amplifier.\r\nDialogue: 0,0:09:26.99,0:09:28.75,EN,,0,0,0,,But it's ridiculous to build such a thing,\r\nDialogue: 0,0:09:28.98,0:09:32.15,EN,,0,0,0,,because long before the millionth stage,\r\nDialogue: 0,0:09:32.16,0:09:34.56,EN,,0,0,0,,the thermal noise in those components way at the beginning\r\nDialogue: 0,0:09:34.57,0:09:36.80,EN,,0,0,0,,is going to get amplified and make the whole thing meaningless.\r\nDialogue: 0,0:09:39.10,0:09:43.12,EN,,0,0,0,,Computer science deals with idealized components.\r\nDialogue: 0,0:09:44.12,0:09:47.63,EN,,0,0,0,,We know as much as we want about these little program\r\nDialogue: 0,0:09:47.65,0:09:49.56,EN,,0,0,0,,and data pieces that we're fitting things together.\r\nDialogue: 0,0:09:51.90,0:09:53.20,EN,,0,0,0,,We don't have to worry about tolerance.\r\nDialogue: 0,0:09:53.21,0:09:56.99,EN,,0,0,0,,And that means that, in building a large program,\r\nDialogue: 0,0:09:58.13,0:10:00.03,EN,,0,0,0,,there's not all that much difference\r\nDialogue: 0,0:10:00.35,0:10:04.18,EN,,0,0,0,,between what I can build and what I can imagine,\r\nDialogue: 0,0:10:05.53,0:10:07.60,EN,,0,0,0,,because the parts are these abstract entities\r\nDialogue: 0,0:10:07.63,0:10:10.32,EN,,0,0,0,,that I know as much as I want.\r\nDialogue: 0,0:10:10.33,0:10:12.39,EN,,0,0,0,,I know about them as precisely as I'd like.\r\nDialogue: 0,0:10:13.45,0:10:15.50,EN,,0,0,0,,So as opposed to other kinds of engineering,\r\nDialogue: 0,0:10:15.66,0:10:17.42,EN,,0,0,0,,where the constraints on what you can build\r\nDialogue: 0,0:10:17.44,0:10:18.90,EN,,0,0,0,,are the constraints of physical systems,\r\nDialogue: 0,0:10:18.94,0:10:21.02,EN,,0,0,0,,the constraints of physics and noise and approximation,\r\nDialogue: 0,0:10:21.21,0:10:25.60,EN,,0,0,0,,the constraints imposed in building large software systems\r\nDialogue: 0,0:10:25.64,0:10:27.58,EN,,0,0,0,,are the limitations of our own minds.\r\nDialogue: 0,0:10:29.12,0:10:29.98,EN,,0,0,0,,So in that sense,\r\nDialogue: 0,0:10:30.00,0:10:33.67,EN,,0,0,0,,computer science is like an abstract form of engineering.\r\nDialogue: 0,0:10:33.80,0:10:35.73,EN,,0,0,0,,It's the kind of engineering where you ignore\r\nDialogue: 0,0:10:35.76,0:10:38.02,EN,,0,0,0,,the constraints that are imposed by reality.\r\nDialogue: 0,0:10:41.97,0:10:46.15,EN,,0,0,0,,Well, what are some of these techniques?\r\nDialogue: 0,0:10:46.28,0:10:48.39,EN,,0,0,0,,They're not special to computer science.\r\nDialogue: 0,0:10:50.39,0:10:52.55,EN,,0,0,0,,First technique, which is used in all of engineering,\r\nDialogue: 0,0:10:53.36,0:10:58.91,EN,,0,0,0,,is a kind of abstraction called black-box abstraction.\r\nDialogue: 0,0:11:07.71,0:11:12.58,EN,,0,0,0,,Take something and build a box about it.\r\nDialogue: 0,0:11:14.37,0:11:20.09,EN,,0,0,0,,Let's see, for example, if we looked at that square root method,\r\nDialogue: 0,0:11:22.64,0:11:28.53,EN,,0,0,0,,I might want to take that and build a box.\r\nDialogue: 0,0:11:29.89,0:11:37.52,EN,,0,0,0,,That sort of says, to find the square root of X.\r\nDialogue: 0,0:11:38.86,0:11:41.27,EN,,0,0,0,,And that might be a whole complicated set of rules.\r\nDialogue: 0,0:11:42.64,0:11:46.69,EN,,0,0,0,,And that might end up being a kind of thing where I can put in,\r\nDialogue: 0,0:11:46.81,0:11:50.06,EN,,0,0,0,,say, 36 and say, what's the square root of 36?\r\nDialogue: 0,0:11:50.25,0:11:51.46,EN,,0,0,0,,And out comes 6.\r\nDialogue: 0,0:11:53.89,0:11:56.22,EN,,0,0,0,,And the important thing is that\r\nDialogue: 0,0:11:56.24,0:12:00.03,EN,,0,0,0,,I'd like to design that so that\r\nDialogue: 0,0:12:00.06,0:12:04.08,EN,,0,0,0,,if George comes along and would like to compute,\r\nDialogue: 0,0:12:05.10,0:12:09.37,EN,,0,0,0,,say, the square root of A plus the square root of B,\r\nDialogue: 0,0:12:11.34,0:12:14.38,EN,,0,0,0,,he can take this thing and use it as a module\r\nDialogue: 0,0:12:14.43,0:12:15.74,EN,,0,0,0,,without having to look inside\r\nDialogue: 0,0:12:15.77,0:12:17.31,EN,,0,0,0,,and build something that looks like this,\r\nDialogue: 0,0:12:18.45,0:12:24.20,EN,,0,0,0,,like an A and a B and a square root box and another square root box\r\nDialogue: 0,0:12:24.53,0:12:33.87,EN,,0,0,0,,and then something that adds that would put out the answer.\r\nDialogue: 0,0:12:33.96,0:12:38.15,EN,,0,0,0,,And you can see, just from the fact that I want to do that,\r\nDialogue: 0,0:12:38.92,0:12:40.42,EN,,0,0,0,,is from George's point of view,\r\nDialogue: 0,0:12:40.51,0:12:43.10,EN,,0,0,0,,the internals of what's in here should not be important.\r\nDialogue: 0,0:12:44.19,0:12:47.25,EN,,0,0,0,,So for instance, it shouldn't matter that, when I wrote this,\r\nDialogue: 0,0:12:47.27,0:12:50.43,EN,,0,0,0,,I said I want to find the square root of X.\r\nDialogue: 0,0:12:50.61,0:12:52.27,EN,,0,0,0,,I could have said the square root of Y,\r\nDialogue: 0,0:12:52.72,0:12:55.62,EN,,0,0,0,,or the square root of A, or anything at all\r\nDialogue: 0,0:12:56.70,0:13:02.35,EN,,0,0,0,,That's the fundamental notion of putting something in a box\r\nDialogue: 0,0:13:03.53,0:13:06.44,EN,,0,0,0,,using black-box abstraction to suppress detail.\r\nDialogue: 0,0:13:07.60,0:13:10.99,EN,,0,0,0,,And the reason for that is you want to go off and build bigger boxes.\r\nDialogue: 0,0:13:12.05,0:13:14.57,EN,,0,0,0,,Now, there's another reason for doing black-box abstraction\r\nDialogue: 0,0:13:14.59,0:13:18.41,EN,,0,0,0,,other than you want to suppress detail for building bigger boxes.\r\nDialogue: 0,0:13:18.48,0:13:25.02,EN,,0,0,0,,Sometimes you want to say that your way of doing something,\r\nDialogue: 0,0:13:25.04,0:13:26.88,EN,,0,0,0,,your how-to method,\r\nDialogue: 0,0:13:28.44,0:13:30.79,EN,,0,0,0,,is an instance of a more general thing,\r\nDialogue: 0,0:13:31.16,0:13:34.57,EN,,0,0,0,,and you'd like your language to be able to express that generality.\r\nDialogue: 0,0:13:35.57,0:13:37.93,EN,,0,0,0,,Let me show you another example\r\nDialogue: 0,0:13:37.97,0:13:38.86,EN,,0,0,0,,sticking with square roots.\r\nDialogue: 0,0:13:38.89,0:13:42.16,EN,,0,0,0,,Let's go back and take another look at that slide\r\nDialogue: 0,0:13:42.19,0:13:43.75,EN,,0,0,0,,with the square root algorithm on it.\r\nDialogue: 0,0:13:44.16,0:13:45.62,EN,,0,0,0,,Remember what that says.\r\nDialogue: 0,0:13:45.79,0:13:49.82,EN,,0,0,0,,That says, in order to do something, I make a guess,\r\nDialogue: 0,0:13:50.62,0:13:54.84,EN,,0,0,0,,and I improve that guess, and I sort of keep improving that guess.\r\nDialogue: 0,0:13:55.66,0:14:00.14,EN,,0,0,0,,So there's the general strategy of, I'm looking for something,\r\nDialogue: 0,0:14:01.15,0:14:04.00,EN,,0,0,0,,and the way I find it is that I keep improving it.\r\nDialogue: 0,0:14:04.16,0:14:10.25,EN,,0,0,0,,Now, that's a particular case of another kind of strategy\r\nDialogue: 0,0:14:10.97,0:14:13.23,EN,,0,0,0,,for finding a fixed point of something.\r\nDialogue: 0,0:14:14.57,0:14:16.59,EN,,0,0,0,,So you have a fixed point of a function.\r\nDialogue: 0,0:14:17.13,0:14:26.03,EN,,0,0,0,,A fixed point of a function is something, is a value.\r\nDialogue: 0,0:14:26.13,0:14:31.79,EN,,0,0,0,,A fixed point of a function F is a value Y, such that F of Y equals Y.\r\nDialogue: 0,0:14:32.97,0:14:40.89,EN,,0,0,0,,And the way I might do that is start with a guess.\r\nDialogue: 0,0:14:42.00,0:14:45.85,EN,,0,0,0,,And then if I want something that doesn't change when I keep applying F,\r\nDialogue: 0,0:14:45.96,0:14:49.45,EN,,0,0,0,,is I'll keep applying F over and over until that result doesn't change very much.\r\nDialogue: 0,0:14:50.05,0:14:51.93,EN,,0,0,0,,So there's a general strategy.\r\nDialogue: 0,0:14:52.24,0:14:56.17,EN,,0,0,0,,And then, for example, to compute the square root of X,\r\nDialogue: 0,0:14:56.24,0:15:03.45,EN,,0,0,0,,I can try and find a fixed point of the function which takes Y to the average of X/Y.\r\nDialogue: 0,0:15:03.55,0:15:07.52,EN,,0,0,0,,And the idea that is that if I really had Y equal to the square root of X,\r\nDialogue: 0,0:15:08.01,0:15:11.80,EN,,0,0,0,,then Y and X/Y would be the same value.\r\nDialogue: 0,0:15:12.00,0:15:13.90,EN,,0,0,0,,They'd both be the square root of X,\r\nDialogue: 0,0:15:14.86,0:15:18.85,EN,,0,0,0,,because X over the square root of X is the square root of X.\r\nDialogue: 0,0:15:19.09,0:15:21.84,EN,,0,0,0,,And so the average if Y were equal to the square of X,\r\nDialogue: 0,0:15:22.25,0:15:25.21,EN,,0,0,0,,then the average wouldn't change.\r\nDialogue: 0,0:15:25.98,0:15:28.93,EN,,0,0,0,,So the square root of X is a fixed point of that particular function.\r\nDialogue: 0,0:15:30.09,0:15:33.85,EN,,0,0,0,,Now, what I'd like to have, I'd like to express\r\nDialogue: 0,0:15:33.98,0:15:36.42,EN,,0,0,0,,the general strategy for finding fixed points.\r\nDialogue: 0,0:15:36.57,0:15:40.13,EN,,0,0,0,,So what I might imagine doing, is to find,\r\nDialogue: 0,0:15:41.02,0:15:46.45,EN,,0,0,0,,is to be able to use my language to define a box that says \"fixed point,\"\r\nDialogue: 0,0:15:49.58,0:15:52.19,EN,,0,0,0,,just like I could make a box that says \"square root.\"\r\nDialogue: 0,0:15:52.21,0:15:55.18,EN,,0,0,0,,And I'd like to be able to express this in my language.\r\nDialogue: 0,0:15:56.08,0:16:01.37,EN,,0,0,0,,So I'd like to express not only the imperative how-to knowledge\r\nDialogue: 0,0:16:01.42,0:16:03.21,EN,,0,0,0,,of a particular thing like square root,\r\nDialogue: 0,0:16:03.58,0:16:05.60,EN,,0,0,0,,but I'd like to be able to express the imperative knowledge\r\nDialogue: 0,0:16:05.66,0:16:08.27,EN,,0,0,0,,of how to do a general thing like how to find fixed point.\r\nDialogue: 0,0:16:09.82,0:16:12.25,EN,,0,0,0,,And in fact, let's go back and look at that slide again.\r\nDialogue: 0,0:16:15.02,0:16:23.28,EN,,0,0,0,,See, not only is this a piece of imperative knowledge,\r\nDialogue: 0,0:16:23.33,0:16:25.32,EN,,0,0,0,,how to find a fixed point,\r\nDialogue: 0,0:16:26.25,0:16:27.39,EN,,0,0,0,,but over here on the bottom,\r\nDialogue: 0,0:16:27.42,0:16:30.32,EN,,0,0,0,,there's another piece of imperative knowledge which says,\r\nDialogue: 0,0:16:30.41,0:16:35.85,EN,,0,0,0,,one way to compute square root is to apply this general fixed point method.\r\nDialogue: 0,0:16:36.17,0:16:38.89,EN,,0,0,0,,So I'd like to also be able to express that imperative knowledge.\r\nDialogue: 0,0:16:39.74,0:16:40.70,EN,,0,0,0,,What would that look like?\r\nDialogue: 0,0:16:40.73,0:16:44.90,EN,,0,0,0,,That would say, this fixed point box is such that\r\nDialogue: 0,0:16:45.76,0:16:58.21,EN,,0,0,0,,if I input to it the function that takes Y to the average of Y and X/Y,\r\nDialogue: 0,0:16:59.77,0:17:06.23,EN,,0,0,0,,then what should come out of that fixed point box is a method for finding square roots.\r\nDialogue: 0,0:17:08.91,0:17:10.24,EN,,0,0,0,,So in these boxes we're building,\r\nDialogue: 0,0:17:10.27,0:17:15.07,EN,,0,0,0,,we're not only building boxes that you input numbers and output numbers,\r\nDialogue: 0,0:17:16.40,0:17:18.54,EN,,0,0,0,,we're going to be building in boxes that,\r\nDialogue: 0,0:17:18.67,0:17:21.34,EN,,0,0,0,,in effect, compute methods like finding square root.\r\nDialogue: 0,0:17:22.22,0:17:25.85,EN,,0,0,0,,And my take is their inputs functions,\r\nDialogue: 0,0:17:26.49,0:17:29.29,EN,,0,0,0,,like Y goes to the average of Y and X/Y.\r\nDialogue: 0,0:17:29.71,0:17:31.49,EN,,0,0,0,,The reason we want to do that,\r\nDialogue: 0,0:17:32.21,0:17:35.60,EN,,0,0,0,,the reason this is a procedure, will end up being a procedure,\r\nDialogue: 0,0:17:35.63,0:17:38.61,EN,,0,0,0,,as we'll see, whose value is another procedure,\r\nDialogue: 0,0:17:39.31,0:17:41.10,EN,,0,0,0,,the reason we want to do that is because\r\nDialogue: 0,0:17:41.52,0:17:46.27,EN,,0,0,0,,procedures are going to be our ways of talking about imperative knowledge.\r\nDialogue: 0,0:17:48.00,0:17:49.93,EN,,0,0,0,,And the way to make that very powerful is\r\nDialogue: 0,0:17:49.93,0:17:52.13,EN,,0,0,0,,to be able to talk about other kinds of knowledge.\r\nDialogue: 0,0:17:53.42,0:17:56.52,EN,,0,0,0,,So here is a procedure that, in effect, talks about another procedure,\r\nDialogue: 0,0:17:57.10,0:18:00.34,EN,,0,0,0,,a general strategy that itself talks about general strategies.\r\nDialogue: 0,0:18:03.57,0:18:08.24,EN,,0,0,0,,Well, our first topic in this course--\r\nDialogue: 0,0:18:08.25,0:18:09.69,EN,,0,0,0,,there'll be three major topics--\r\nDialogue: 0,0:18:09.74,0:18:10.94,EN,,0,0,0,,will be black-box abstraction.\r\nDialogue: 0,0:18:10.97,0:18:13.31,EN,,0,0,0,,Let's look at that in a little bit more detail.\r\nDialogue: 0,0:18:15.12,0:18:24.04,EN,,0,0,0,,What we're going to do is we will start out talking about\r\nDialogue: 0,0:18:24.08,0:18:26.72,EN,,0,0,0,,how Lisp is built up out of primitive objects.\r\nDialogue: 0,0:18:27.36,0:18:29.20,EN,,0,0,0,,What does the language supply with us?\r\nDialogue: 0,0:18:29.49,0:18:33.58,EN,,0,0,0,,And we'll see that there are primitive procedures and primitive data.\r\nDialogue: 0,0:18:36.16,0:18:37.04,EN,,0,0,0,,Then we're going to see,\r\nDialogue: 0,0:18:37.05,0:18:38.77,EN,,0,0,0,,how do you take those primitives and\r\nDialogue: 0,0:18:38.81,0:18:40.76,EN,,0,0,0,,combine them to make more complicated things,\r\nDialogue: 0,0:18:41.45,0:18:42.92,EN,,0,0,0,,means of combination?\r\nDialogue: 0,0:18:43.20,0:18:46.30,EN,,0,0,0,,And what we'll see is that there are ways of putting things together,\r\nDialogue: 0,0:18:46.45,0:18:50.48,EN,,0,0,0,,putting primitive procedures together to make more complicated procedures.\r\nDialogue: 0,0:18:50.96,0:18:54.43,EN,,0,0,0,,And we'll see how to put primitive data together to make compound data.\r\nDialogue: 0,0:18:56.21,0:18:59.34,EN,,0,0,0,,Then we'll say, well, having made those compounds things,\r\nDialogue: 0,0:18:59.79,0:19:01.29,EN,,0,0,0,,how do you abstract them?\r\nDialogue: 0,0:19:02.91,0:19:04.97,EN,,0,0,0,,How do you put those black boxes around them\r\nDialogue: 0,0:19:05.04,0:19:07.73,EN,,0,0,0,,so you can use them as components in more complex things?\r\nDialogue: 0,0:19:08.16,0:19:10.93,EN,,0,0,0,,And we'll see that's done by defining procedures and\r\nDialogue: 0,0:19:11.52,0:19:14.79,EN,,0,0,0,,a technique for dealing with compound data called data abstraction.\r\nDialogue: 0,0:19:15.61,0:19:17.36,EN,,0,0,0,,And then, what's maybe the most important thing,\r\nDialogue: 0,0:19:17.92,0:19:21.49,EN,,0,0,0,,is going from just the rules to how does an expert work?\r\nDialogue: 0,0:19:21.61,0:19:27.12,EN,,0,0,0,,How do you express common patterns of doing things, like saying, well,\r\nDialogue: 0,0:19:27.15,0:19:28.64,EN,,0,0,0,,there's a general method of fixed point and\r\nDialogue: 0,0:19:28.69,0:19:30.87,EN,,0,0,0,,square root is a particular case of that?\r\nDialogue: 0,0:19:31.90,0:19:34.41,EN,,0,0,0,,And we're going to use--\r\nDialogue: 0,0:19:34.59,0:19:35.63,EN,,0,0,0,,I've already hinted at it--\r\nDialogue: 0,0:19:35.66,0:19:37.30,EN,,0,0,0,,something called higher-order procedures,\r\nDialogue: 0,0:19:37.34,0:19:42.05,EN,,0,0,0,,namely procedures whose inputs and outputs are themselves procedures.\r\nDialogue: 0,0:19:42.96,0:19:44.86,EN,,0,0,0,,And then we'll also see something very interesting.\r\nDialogue: 0,0:19:44.86,0:19:48.49,EN,,0,0,0,,We'll see, as we go further and further on and become more abstract,\r\nDialogue: 0,0:19:48.80,0:19:50.31,EN,,0,0,0,,there'll be very--\r\nDialogue: 0,0:19:50.43,0:19:53.61,EN,,0,0,0,,well, the line between what we consider to be data and\r\nDialogue: 0,0:19:53.63,0:19:57.80,EN,,0,0,0,,what we consider to be procedures is going to blur at an incredible rate.\r\nDialogue: 0,0:20:02.89,0:20:07.12,EN,,0,0,0,,Well, that's our first subject, black-box abstraction.\r\nDialogue: 0,0:20:07.12,0:20:08.62,EN,,0,0,0,,Let's look at the second topic.\r\nDialogue: 0,0:20:11.10,0:20:13.88,EN,,0,0,0,,I can introduce it like this.\r\nDialogue: 0,0:20:13.89,0:20:18.09,EN,,0,0,0,,See, suppose I want to express the idea--\r\nDialogue: 0,0:20:19.42,0:20:22.51,EN,,0,0,0,,remember, we're talking about ideas--\r\nDialogue: 0,0:20:22.91,0:20:25.53,EN,,0,0,0,,suppose I want to express the idea that\r\nDialogue: 0,0:20:26.41,0:20:35.12,EN,,0,0,0,,I can take something and multiply it by the sum of two other things.\r\nDialogue: 0,0:20:36.09,0:20:37.93,EN,,0,0,0,,So for example, I might say,\r\nDialogue: 0,0:20:38.11,0:20:41.52,EN,,0,0,0,,if I had 1 and 3 and multiply that by 2, I get 8.\r\nDialogue: 0,0:20:42.03,0:20:45.11,EN,,0,0,0,,But I'm talking about the general idea of what's called linear combination,\r\nDialogue: 0,0:20:45.44,0:20:47.98,EN,,0,0,0,,that you can add two things and multiply them by something else.\r\nDialogue: 0,0:20:49.28,0:20:51.01,EN,,0,0,0,,It's very easy when I think about it for numbers,\r\nDialogue: 0,0:20:51.05,0:20:55.41,EN,,0,0,0,,but suppose I also want to use that same idea to think about,\r\nDialogue: 0,0:20:56.08,0:20:58.58,EN,,0,0,0,,I could add two vectors, a1 and a2,\r\nDialogue: 0,0:20:59.89,0:21:03.26,EN,,0,0,0,,and then scale them by some factor x and get another vector.\r\nDialogue: 0,0:21:03.33,0:21:09.75,EN,,0,0,0,,Or I might say, I want to think about a1 and a2 as being polynomials,\r\nDialogue: 0,0:21:11.07,0:21:13.90,EN,,0,0,0,,and I might want to add those two polynomials and\r\nDialogue: 0,0:21:13.92,0:21:16.86,EN,,0,0,0,,then multiply them by 2 to get a more complicated one.\r\nDialogue: 0,0:21:20.16,0:21:23.83,EN,,0,0,0,,Or a1 and a2 might be electrical signals,\r\nDialogue: 0,0:21:24.56,0:21:27.77,EN,,0,0,0,,and I might want to think about summing those two electrical signals and\r\nDialogue: 0,0:21:27.81,0:21:30.27,EN,,0,0,0,,then putting the whole thing through an amplifier,\r\nDialogue: 0,0:21:30.28,0:21:33.03,EN,,0,0,0,,multiplying it by some factor of 2 or something.\r\nDialogue: 0,0:21:33.82,0:21:36.93,EN,,0,0,0,,The idea is I want to think about the general notion of that.\r\nDialogue: 0,0:21:38.32,0:21:45.42,EN,,0,0,0,,Now, if our language is going to be good language for expressing those kind of general ideas,\r\nDialogue: 0,0:21:47.07,0:21:49.31,EN,,0,0,0,,if I really, really can do that,\r\nDialogue: 0,0:21:50.65,0:21:52.09,EN,,0,0,0,,I'd like to be able to say\r\nDialogue: 0,0:21:54.99,0:22:00.41,EN,,0,0,0,,I'm going to multiply by x the sum of a1 and a2,\r\nDialogue: 0,0:22:02.80,0:22:05.07,EN,,0,0,0,,and I'd like that to express the general idea of\r\nDialogue: 0,0:22:06.03,0:22:09.23,EN,,0,0,0,,all different kinds of things that a1 and a2 could be.\r\nDialogue: 0,0:22:10.03,0:22:11.58,EN,,0,0,0,,Now, if you think about that, there's a problem,\r\nDialogue: 0,0:22:11.58,0:22:16.17,EN,,0,0,0,,because after all, the actual primitive operations\r\nDialogue: 0,0:22:16.21,0:22:18.33,EN,,0,0,0,,that go on in the machine are obviously going to be different\r\nDialogue: 0,0:22:18.38,0:22:22.98,EN,,0,0,0,,if I'm adding two numbers than if I'm adding two polynomials,\r\nDialogue: 0,0:22:23.29,0:22:27.49,EN,,0,0,0,,or if I'm adding the representation of two electrical signals or wave forms.\r\nDialogue: 0,0:22:27.89,0:22:32.53,EN,,0,0,0,,Somewhere, there has to be the knowledge of the kinds of various things\r\nDialogue: 0,0:22:32.87,0:22:34.25,EN,,0,0,0,,that you can add and the ways of adding them.\r\nDialogue: 0,0:22:37.09,0:22:38.64,EN,,0,0,0,,Now, to construct such a system,\r\nDialogue: 0,0:22:38.78,0:22:40.67,EN,,0,0,0,,the question is, where do I put that knowledge?\r\nDialogue: 0,0:22:41.20,0:22:44.41,EN,,0,0,0,,How do I think about the different kinds of choices I have?\r\nDialogue: 0,0:22:44.56,0:22:48.42,EN,,0,0,0,,And if tomorrow George comes up with a new kind of object\r\nDialogue: 0,0:22:48.45,0:22:50.32,EN,,0,0,0,,that might be added and multiplied,\r\nDialogue: 0,0:22:51.01,0:22:53.32,EN,,0,0,0,,how do I add George's new object to the system\r\nDialogue: 0,0:22:53.52,0:22:55.68,EN,,0,0,0,,without screwing up everything that was already there?\r\nDialogue: 0,0:22:57.81,0:23:00.54,EN,,0,0,0,,Well, that's going to be the second big topic,\r\nDialogue: 0,0:23:00.57,0:23:03.16,EN,,0,0,0,,the way of controlling that kind of complexity.\r\nDialogue: 0,0:23:03.84,0:23:08.43,EN,,0,0,0,,And the way you do that is by establishing conventional interfaces,\r\nDialogue: 0,0:23:17.44,0:23:20.21,EN,,0,0,0,,agreed upon ways of plugging things together.\r\nDialogue: 0,0:23:20.25,0:23:22.04,EN,,0,0,0,,Just like in electrical engineering,\r\nDialogue: 0,0:23:22.94,0:23:25.39,EN,,0,0,0,,people have standard impedances for connectors,\r\nDialogue: 0,0:23:26.16,0:23:28.62,EN,,0,0,0,,and then you know if you build something with one of those standard impedances,\r\nDialogue: 0,0:23:28.67,0:23:30.40,EN,,0,0,0,,you can plug it together with something else.\r\nDialogue: 0,0:23:32.78,0:23:35.68,EN,,0,0,0,,So that's going to be our second large topic, conventional interfaces.\r\nDialogue: 0,0:23:35.73,0:23:40.94,EN,,0,0,0,,What we're going to see is, first, we're going to talk about the problem of generic operations,\r\nDialogue: 0,0:23:40.97,0:23:42.22,EN,,0,0,0,,which is the one I alluded to,\r\nDialogue: 0,0:23:42.59,0:23:47.28,EN,,0,0,0,,things like \"plus\" that have to work with all different kinds of data.\r\nDialogue: 0,0:23:52.61,0:23:54.57,EN,,0,0,0,,So we talk about generic operations.\r\nDialogue: 0,0:23:54.61,0:23:56.99,EN,,0,0,0,,Then we're going to talk about really large-scale structures.\r\nDialogue: 0,0:23:58.32,0:24:00.83,EN,,0,0,0,,How do you put together very large programs\r\nDialogue: 0,0:24:01.02,0:24:04.89,EN,,0,0,0,,that model the kinds of complex systems in the real world that you'd like to model?\r\nDialogue: 0,0:24:05.53,0:24:06.53,EN,,0,0,0,,And what we're going to see is that\r\nDialogue: 0,0:24:06.57,0:24:11.81,EN,,0,0,0,,there are two very important metaphors for putting together such systems.\r\nDialogue: 0,0:24:11.85,0:24:13.90,EN,,0,0,0,,One is called object-oriented programming,\r\nDialogue: 0,0:24:14.09,0:24:18.94,EN,,0,0,0,,where you sort of think of your system as a kind of society\r\nDialogue: 0,0:24:19.37,0:24:22.36,EN,,0,0,0,,full of little things that interact by sending information between them.\r\nDialogue: 0,0:24:23.44,0:24:27.81,EN,,0,0,0,,And then the second one is operations on aggregates, called streams,\r\nDialogue: 0,0:24:27.98,0:24:31.50,EN,,0,0,0,,where you think of a large system put together kind of\r\nDialogue: 0,0:24:31.50,0:24:35.29,EN,,0,0,0,,like a signal processing engineer puts together a large electrical system.\r\nDialogue: 0,0:24:38.93,0:24:40.49,EN,,0,0,0,,That's going to be our second topic.\r\nDialogue: 0,0:24:43.37,0:24:45.93,EN,,0,0,0,,Now, the third thing we're going to come to,\r\nDialogue: 0,0:24:45.95,0:24:49.70,EN,,0,0,0,,the third basic technique for controlling complexity,\r\nDialogue: 0,0:24:49.74,0:24:50.94,EN,,0,0,0,,is making new languages.\r\nDialogue: 0,0:24:51.69,0:24:55.42,EN,,0,0,0,,Because sometimes, when you're sort of overwhelmed by the complexity of a design,\r\nDialogue: 0,0:24:55.47,0:24:59.69,EN,,0,0,0,,the way that you control that complexity is to pick a new design language.\r\nDialogue: 0,0:25:01.41,0:25:05.60,EN,,0,0,0,,And the purpose of the new design language will be to highlight different aspects of the system.\r\nDialogue: 0,0:25:05.79,0:25:09.36,EN,,0,0,0,,It will suppress some kinds of details and emphasize other kinds of details.\r\nDialogue: 0,0:25:12.99,0:25:15.93,EN,,0,0,0,,This is going to be the most magical part of the course.\r\nDialogue: 0,0:25:16.03,0:25:21.20,EN,,0,0,0,,We're going to start out by actually looking at the technology for building new computer languages.\r\nDialogue: 0,0:25:21.82,0:25:26.30,EN,,0,0,0,,The first thing we're going to do is actually build in Lisp.\r\nDialogue: 0,0:25:29.23,0:25:34.02,EN,,0,0,0,,We're going to express in Lisp the process of interpreting Lisp itself.\r\nDialogue: 0,0:25:34.29,0:25:36.94,EN,,0,0,0,,And that's going to be a very sort of self-circular thing.\r\nDialogue: 0,0:25:36.96,0:25:39.92,EN,,0,0,0,,There's a little mystical symbol that has to do with that.\r\nDialogue: 0,0:25:40.97,0:25:46.38,EN,,0,0,0,,The process of interpreting Lisp is sort of a giant wheel of two processes,\r\nDialogue: 0,0:25:46.57,0:25:47.71,EN,,0,0,0,,apply and eval,\r\nDialogue: 0,0:25:47.89,0:25:50.87,EN,,0,0,0,,which sort of constantly reduce expressions to each other.\r\nDialogue: 0,0:25:52.54,0:25:54.24,EN,,0,0,0,,Then we're going to see all sorts of other magical things.\r\nDialogue: 0,0:25:54.25,0:25:56.85,EN,,0,0,0,,Here's another magical symbol.\r\nDialogue: 0,0:25:57.12,0:26:01.52,EN,,0,0,0,,This is sort of the Y operator,\r\nDialogue: 0,0:26:01.55,0:26:06.45,EN,,0,0,0,,which is, in some sense, the expression of infinity inside our procedural language.\r\nDialogue: 0,0:26:06.51,0:26:07.44,EN,,0,0,0,,We'll take a look at that.\r\nDialogue: 0,0:26:08.40,0:26:13.73,EN,,0,0,0,,In any case, this section of the course is called Metalinguistic Abstraction,\r\nDialogue: 0,0:26:16.17,0:26:26.23,EN,,0,0,0,,abstracting by talking about how you construct new languages.\r\nDialogue: 0,0:26:30.22,0:26:35.71,EN,,0,0,0,,As I said, we're going to start out by looking at the process of interpretation.\r\nDialogue: 0,0:26:35.74,0:26:42.12,EN,,0,0,0,,We're going to look at this apply-eval loop, and build Lisp.\r\nDialogue: 0,0:26:42.16,0:26:44.17,EN,,0,0,0,,Then, just to show you that this is very general,\r\nDialogue: 0,0:26:44.37,0:26:48.26,EN,,0,0,0,,we're going to use exactly the same technology to build a very different kind of language,\r\nDialogue: 0,0:26:48.53,0:26:50.31,EN,,0,0,0,,a so-called logic programming language,\r\nDialogue: 0,0:26:50.53,0:26:54.83,EN,,0,0,0,,where you don't really talk about procedures at all that have inputs and outputs.\r\nDialogue: 0,0:26:54.86,0:26:57.25,EN,,0,0,0,,What you do is talk about relations between things.\r\nDialogue: 0,0:26:57.31,0:27:03.92,EN,,0,0,0,,And then finally, we're going to talk about how you implement these things very concretely\r\nDialogue: 0,0:27:03.95,0:27:05.60,EN,,0,0,0,,on the very simplest kind of machines.\r\nDialogue: 0,0:27:05.65,0:27:08.39,EN,,0,0,0,,We'll see something like this.\r\nDialogue: 0,0:27:09.13,0:27:12.14,EN,,0,0,0,,This is a picture of a chip,\r\nDialogue: 0,0:27:12.16,0:27:17.47,EN,,0,0,0,,which is the Lisp interpreter that we will be talking about then in hardware.\r\nDialogue: 0,0:27:20.88,0:27:23.79,EN,,0,0,0,,Well, there's an outline of the course, three big topics.\r\nDialogue: 0,0:27:24.88,0:27:29.41,EN,,0,0,0,,Black-box abstraction, conventional interfaces, metalinguistic abstraction.\r\nDialogue: 0,0:27:31.58,0:27:33.57,EN,,0,0,0,,Now, let's take a break now and then we'll get started.\r\nDialogue: 0,0:27:52.19,0:28:03.42,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\r\nDialogue: 0,0:28:03.92,0:28:06.84,EN,,0,0,0,,Let's actually start in learning Lisp now.\r\nDialogue: 0,0:28:08.06,0:28:10.75,EN,,0,0,0,,Actually, we'll start out by learning something much more important,\r\nDialogue: 0,0:28:10.80,0:28:14.33,EN,,0,0,0,,maybe the very most important thing in this course, which is not Lisp,\r\nDialogue: 0,0:28:14.38,0:28:18.41,EN,,0,0,0,,in particular, of course, but rather a general framework\r\nDialogue: 0,0:28:18.62,0:28:21.89,EN,,0,0,0,,for thinking about languages that I already alluded to.\r\nDialogue: 0,0:28:22.12,0:28:25.10,EN,,0,0,0,,When somebody tells you they're going to show you a language,\r\nDialogue: 0,0:28:25.13,0:28:26.16,EN,,0,0,0,,what you should say is,\r\nDialogue: 0,0:28:26.19,0:28:32.87,EN,,0,0,0,,what I'd like you to tell me is what are the primitive elements?\r\nDialogue: 0,0:28:37.50,0:28:38.78,EN,,0,0,0,,What does the language come with?\r\nDialogue: 0,0:28:38.96,0:28:43.53,EN,,0,0,0,,Then, what are the ways you put those together?\r\nDialogue: 0,0:28:43.68,0:28:47.42,EN,,0,0,0,,What are the means of combination?\r\nDialogue: 0,0:28:50.17,0:28:54.18,EN,,0,0,0,,What are the things that allow you to take these primitive elements\r\nDialogue: 0,0:28:54.37,0:28:56.51,EN,,0,0,0,,and build bigger things out of them?\r\nDialogue: 0,0:28:58.01,0:28:59.61,EN,,0,0,0,,What are the ways of putting things together?\r\nDialogue: 0,0:29:01.39,0:29:05.69,EN,,0,0,0,,And then, what are the means of abstraction?\r\nDialogue: 0,0:29:08.35,0:29:16.85,EN,,0,0,0,,How do we take those complicated things and draw those boxes around them?\r\nDialogue: 0,0:29:16.88,0:29:19.66,EN,,0,0,0,,How do we name them so that we can now use them\r\nDialogue: 0,0:29:19.68,0:29:23.85,EN,,0,0,0,,as if they were primitive elements in making still more complex things?\r\nDialogue: 0,0:29:23.89,0:29:25.66,EN,,0,0,0,,And so on, and so on, and so on.\r\nDialogue: 0,0:29:26.89,0:29:28.08,EN,,0,0,0,,So when someone says to you, gee,\r\nDialogue: 0,0:29:28.09,0:29:29.55,EN,,0,0,0,,I have a great new computer language,\r\nDialogue: 0,0:29:30.86,0:29:34.70,EN,,0,0,0,,you don't say, how many characters does it take to invert a matrix?\r\nDialogue: 0,0:29:35.73,0:29:36.88,EN,,0,0,0,,It's irrelevant.\r\nDialogue: 0,0:29:37.39,0:29:42.30,EN,,0,0,0,,What you say is, if the language did not come with matrices built in\r\nDialogue: 0,0:29:42.33,0:29:43.37,EN,,0,0,0,,or with something else built in,\r\nDialogue: 0,0:29:43.37,0:29:46.03,EN,,0,0,0,,how could I then build that thing?\r\nDialogue: 0,0:29:46.05,0:29:48.47,EN,,0,0,0,,What are the means of combination which would allow me to do that?\r\nDialogue: 0,0:29:48.62,0:29:50.71,EN,,0,0,0,,And then, what are the means of abstraction\r\nDialogue: 0,0:29:51.68,0:29:54.21,EN,,0,0,0,,which allow me then to use those as elements\r\nDialogue: 0,0:29:54.22,0:29:56.52,EN,,0,0,0,,in making more complicated things yet?\r\nDialogue: 0,0:29:58.75,0:30:04.61,EN,,0,0,0,,Well, we're going to see that Lisp has some primitive data and some primitive procedures.\r\nDialogue: 0,0:30:05.25,0:30:07.50,EN,,0,0,0,,In fact, let's really start.\r\nDialogue: 0,0:30:07.55,0:30:14.89,EN,,0,0,0,,And here's a piece of primitive data in Lisp, number 3.\r\nDialogue: 0,0:30:16.27,0:30:19.87,EN,,0,0,0,,Actually, if I'm being very pedantic, that's not the number 3.\r\nDialogue: 0,0:30:19.93,0:30:25.57,EN,,0,0,0,,That's some symbol that represents Plato's concept of the number 3.\r\nDialogue: 0,0:30:26.67,0:30:28.93,EN,,0,0,0,,And here's another.\r\nDialogue: 0,0:30:30.48,0:30:36.06,EN,,0,0,0,,Here's some more primitive data in Lisp, 17.4.\r\nDialogue: 0,0:30:36.08,0:30:39.42,EN,,0,0,0,,Or actually, some representation of 17.4.\r\nDialogue: 0,0:30:40.99,0:30:44.48,EN,,0,0,0,,And here's another one, 5.\r\nDialogue: 0,0:30:46.86,0:30:52.21,EN,,0,0,0,,Here's another primitive object that's built in Lisp, addition.\r\nDialogue: 0,0:30:52.25,0:30:55.68,EN,,0,0,0,,Actually, to use the same kind of pedantic--\r\nDialogue: 0,0:30:55.71,0:31:00.47,EN,,0,0,0,,this is a name for the primitive method of adding things.\r\nDialogue: 0,0:31:00.53,0:31:02.53,EN,,0,0,0,,Just like this is a name for Plato's number 3,\r\nDialogue: 0,0:31:02.61,0:31:09.32,EN,,0,0,0,,this is a name for Plato's concept of how you add things.\r\nDialogue: 0,0:31:10.32,0:31:11.98,EN,,0,0,0,,So those are some primitive elements.\r\nDialogue: 0,0:31:12.14,0:31:13.76,EN,,0,0,0,,I can put them together.\r\nDialogue: 0,0:31:14.14,0:31:18.29,EN,,0,0,0,,I can say, gee, what's the sum of 3 and 17.4 and 5?\r\nDialogue: 0,0:31:18.69,0:31:21.31,EN,,0,0,0,,And the way I do that is to say,\r\nDialogue: 0,0:31:21.33,0:31:27.71,EN,,0,0,0,,let's apply the sum operator to these three numbers.\r\nDialogue: 0,0:31:27.74,0:31:31.15,EN,,0,0,0,,And I should get, what? 8, 17. 25.4.\r\nDialogue: 0,0:31:34.43,0:31:38.05,EN,,0,0,0,,So I should be able to ask Lisp what the value of this is,\r\nDialogue: 0,0:31:38.94,0:31:40.77,EN,,0,0,0,,and it will return 25.4.\r\nDialogue: 0,0:31:43.58,0:31:44.83,EN,,0,0,0,,Let's introduce some names.\r\nDialogue: 0,0:31:44.88,0:31:51.47,EN,,0,0,0,,This thing that I typed is called a combination.\r\nDialogue: 0,0:31:56.88,0:32:01.94,EN,,0,0,0,,And a combination consists, in general, of applying an operator--\r\nDialogue: 0,0:32:03.39,0:32:04.72,EN,,0,0,0,,so this is an operator--\r\nDialogue: 0,0:32:09.71,0:32:12.05,EN,,0,0,0,,to some operands.\r\nDialogue: 0,0:32:13.25,0:32:14.54,EN,,0,0,0,,These are the operands.\r\nDialogue: 0,0:32:21.89,0:32:23.79,EN,,0,0,0,,And of course, I can make more complex things.\r\nDialogue: 0,0:32:23.82,0:32:28.56,EN,,0,0,0,,The reason I can get complexity out of this is because the operands themselves,\r\nDialogue: 0,0:32:29.52,0:32:31.09,EN,,0,0,0,,in general, can be combinations.\r\nDialogue: 0,0:32:31.15,0:32:44.47,EN,,0,0,0,,So for instance, I could say, what is the sum of 3 and the product of 5 and 6 and 8 and 2?\r\nDialogue: 0,0:32:45.66,0:32:52.16,EN,,0,0,0,,And I should get-- let's see-- 30, 40, 43.\r\nDialogue: 0,0:32:52.73,0:32:54.81,EN,,0,0,0,,So Lisp should tell me that that's 43.\r\nDialogue: 0,0:32:56.56,0:33:02.80,EN,,0,0,0,,Forming combinations is the basic needs of combination that we'll be looking at.\r\nDialogue: 0,0:33:04.65,0:33:09.22,EN,,0,0,0,,And then, well, you see some syntax here.\r\nDialogue: 0,0:33:10.56,0:33:13.04,EN,,0,0,0,,Lisp uses what's called prefix notation,\r\nDialogue: 0,0:33:16.22,0:33:25.21,EN,,0,0,0,,which means that the operator is written to the left of the operands.\r\nDialogue: 0,0:33:25.47,0:33:26.48,EN,,0,0,0,,It's just a convention.\r\nDialogue: 0,0:33:27.66,0:33:29.77,EN,,0,0,0,,And notice, it's fully parenthesized.\r\nDialogue: 0,0:33:30.08,0:33:32.32,EN,,0,0,0,,And the parentheses make it completely unambiguous.\r\nDialogue: 0,0:33:32.32,0:33:36.99,EN,,0,0,0,,So by looking at this, I can see that there's the operator,\r\nDialogue: 0,0:33:37.01,0:33:40.99,EN,,0,0,0,,and there are 1, 2, 3, 4 operands.\r\nDialogue: 0,0:33:42.38,0:33:47.97,EN,,0,0,0,,And I can see that the second operand here is itself some combination\r\nDialogue: 0,0:33:48.88,0:33:51.55,EN,,0,0,0,,that has one operator and two operands.\r\nDialogue: 0,0:33:52.43,0:33:54.27,EN,,0,0,0,,Parentheses in Lisp are a little bit,\r\nDialogue: 0,0:33:54.61,0:33:57.71,EN,,0,0,0,,or are very unlike parentheses in conventional mathematics.\r\nDialogue: 0,0:33:57.77,0:34:00.11,EN,,0,0,0,,In mathematics, we sort of use them to mean grouping,\r\nDialogue: 0,0:34:01.21,0:34:03.75,EN,,0,0,0,,and it sort of doesn't hurt if sometimes you leave out parentheses\r\nDialogue: 0,0:34:03.77,0:34:05.56,EN,,0,0,0,,if people understand that that's a group.\r\nDialogue: 0,0:34:05.76,0:34:08.51,EN,,0,0,0,,And in general, it doesn't hurt if you put in extra parentheses,\r\nDialogue: 0,0:34:08.86,0:34:10.94,EN,,0,0,0,,because that maybe makes the grouping more distinct.\r\nDialogue: 0,0:34:10.96,0:34:11.77,EN,,0,0,0,,Lisp is not like that.\r\nDialogue: 0,0:34:13.12,0:34:15.37,EN,,0,0,0,,In Lisp, you cannot leave out parentheses,\r\nDialogue: 0,0:34:16.38,0:34:18.56,EN,,0,0,0,,and you cannot put in extra parentheses,\r\nDialogue: 0,0:34:19.33,0:34:21.28,EN,,0,0,0,,because putting in parentheses always means,\r\nDialogue: 0,0:34:21.37,0:34:27.05,EN,,0,0,0,,exactly and precisely, this is a combination which has meaning,\r\nDialogue: 0,0:34:27.09,0:34:28.81,EN,,0,0,0,,applying operators to operands.\r\nDialogue: 0,0:34:29.04,0:34:32.62,EN,,0,0,0,,And if I left this out, if I left those parentheses out,\r\nDialogue: 0,0:34:32.65,0:34:33.96,EN,,0,0,0,,it would mean something else.\r\nDialogue: 0,0:34:35.41,0:34:37.25,EN,,0,0,0,,In fact, the way to think about this,\r\nDialogue: 0,0:34:37.41,0:34:41.65,EN,,0,0,0,,is really what I'm doing when I write something like this is writing a tree.\r\nDialogue: 0,0:34:42.37,0:34:47.30,EN,,0,0,0,,So this combination is a tree that has a plus and\r\nDialogue: 0,0:34:47.37,0:34:54.46,EN,,0,0,0,,then a 3 and then a something else and an 8 and a 2.\r\nDialogue: 0,0:34:54.48,0:34:56.35,EN,,0,0,0,,And then this something else here is\r\nDialogue: 0,0:34:56.35,0:35:03.22,EN,,0,0,0,,itself a little subtree that has a star and a 5 and a 6.\r\nDialogue: 0,0:35:03.95,0:35:05.53,EN,,0,0,0,,And the way to think of that is, really,\r\nDialogue: 0,0:35:05.55,0:35:09.00,EN,,0,0,0,,what's going on are we're writing these trees,\r\nDialogue: 0,0:35:09.21,0:35:15.10,EN,,0,0,0,,and parentheses are just a way to write this two-dimensional structure\r\nDialogue: 0,0:35:15.79,0:35:17.34,EN,,0,0,0,,as a linear character string.\r\nDialogue: 0,0:35:19.23,0:35:23.81,EN,,0,0,0,,Because at least when Lisp first started and people had teletypes or punch cards or whatever,\r\nDialogue: 0,0:35:24.17,0:35:25.60,EN,,0,0,0,,this was more convenient.\r\nDialogue: 0,0:35:25.97,0:35:30.52,EN,,0,0,0,,Maybe if Lisp started today, the syntax of Lisp would look like that.\r\nDialogue: 0,0:35:31.76,0:35:35.07,EN,,0,0,0,,Well, let's look at what that actually looks like on the computer.\r\nDialogue: 0,0:35:36.29,0:35:39.37,EN,,0,0,0,,Here I have a Lisp interaction set up.\r\nDialogue: 0,0:35:39.41,0:35:40.43,EN,,0,0,0,,There's a editor.\r\nDialogue: 0,0:35:41.13,0:35:44.86,EN,,0,0,0,,And on the top, I'm going to type some values and ask Lisp what they are.\r\nDialogue: 0,0:35:45.12,0:35:46.75,EN,,0,0,0,,So for instance, I can say to Lisp,\r\nDialogue: 0,0:35:46.83,0:35:48.53,EN,,0,0,0,,what's the value of that symbol?\r\nDialogue: 0,0:35:49.44,0:35:50.50,EN,,0,0,0,,That's 3.\r\nDialogue: 0,0:35:50.57,0:35:52.20,EN,,0,0,0,,And I ask Lisp to evaluate it.\r\nDialogue: 0,0:35:52.32,0:35:54.77,EN,,0,0,0,,And there you see Lisp has returned on the bottom,\r\nDialogue: 0,0:35:55.39,0:35:56.84,EN,,0,0,0,,and said, oh yeah, that's 3.\r\nDialogue: 0,0:35:57.58,0:36:04.96,EN,,0,0,0,,Or I can say, what's the sum of 3 and 4 and 8?\r\nDialogue: 0,0:36:06.45,0:36:08.05,EN,,0,0,0,,What's that combination?\r\nDialogue: 0,0:36:08.93,0:36:10.66,EN,,0,0,0,,And ask Lisp to evaluate it.\r\nDialogue: 0,0:36:14.49,0:36:15.68,EN,,0,0,0,,That's 15.\r\nDialogue: 0,0:36:16.57,0:36:18.80,EN,,0,0,0,,Or I can type in something more complicated.\r\nDialogue: 0,0:36:19.25,0:36:34.14,EN,,0,0,0,,I can say, what's the sum of the product of 3 and the sum of 7 and 19.5?\r\nDialogue: 0,0:36:35.21,0:36:38.00,EN,,0,0,0,,And you'll notice here that Lisp has something built in\r\nDialogue: 0,0:36:38.01,0:36:39.76,EN,,0,0,0,,that helps me keep track of all these parentheses.\r\nDialogue: 0,0:36:39.77,0:36:42.13,EN,,0,0,0,,Watch as I type the next closed parentheses,\r\nDialogue: 0,0:36:42.21,0:36:45.01,EN,,0,0,0,,which is going to close the combination starting with the star.\r\nDialogue: 0,0:36:45.52,0:36:47.30,EN,,0,0,0,,The opening one will flash.\r\nDialogue: 0,0:36:47.76,0:36:49.69,EN,,0,0,0,,Here, I'll rub those out and do it again.\r\nDialogue: 0,0:36:50.14,0:36:52.70,EN,,0,0,0,,Type close, and you see that closes the plus.\r\nDialogue: 0,0:36:53.58,0:36:56.41,EN,,0,0,0,,Close again, that closes the star.\r\nDialogue: 0,0:36:57.90,0:37:00.76,EN,,0,0,0,,Now I'm back to the sum, and maybe I'm going to add that all to 4.\r\nDialogue: 0,0:37:01.66,0:37:02.69,EN,,0,0,0,,That closes the plus.\r\nDialogue: 0,0:37:02.73,0:37:07.07,EN,,0,0,0,,Now I have a complete combination, and I can ask Lisp for the value of that.\r\nDialogue: 0,0:37:07.26,0:37:11.66,EN,,0,0,0,,That kind of paren balancing is something that's built into\r\nDialogue: 0,0:37:11.76,0:37:13.29,EN,,0,0,0,,a lot of Lisp systems to help you keep track,\r\nDialogue: 0,0:37:13.36,0:37:16.55,EN,,0,0,0,,because it is kind of hard just by hand doing all these parentheses.\r\nDialogue: 0,0:37:16.81,0:37:21.20,EN,,0,0,0,,There's another kind of convention for keeping track of parentheses.\r\nDialogue: 0,0:37:21.25,0:37:23.68,EN,,0,0,0,,Let me write another complicated combination.\r\nDialogue: 0,0:37:24.77,0:37:34.00,EN,,0,0,0,,Let's take the sum of the product of 3 and 5 and add that to something.\r\nDialogue: 0,0:37:34.03,0:37:35.23,EN,,0,0,0,,And now what I'm going to do is\r\nDialogue: 0,0:37:35.28,0:37:39.85,EN,,0,0,0,,I'm going to indent so that the operands are written vertically.\r\nDialogue: 0,0:37:40.30,0:37:45.65,EN,,0,0,0,,Which the sum of that and the product of 47 and--\r\nDialogue: 0,0:37:47.02,0:37:54.59,EN,,0,0,0,,let's say the product of 47 with a difference of 20 and 6.8.\r\nDialogue: 0,0:37:54.62,0:37:57.09,EN,,0,0,0,,That means subtract 6.8 from 20.\r\nDialogue: 0,0:37:58.97,0:38:00.19,EN,,0,0,0,,And then you see the parentheses close.\r\nDialogue: 0,0:38:00.22,0:38:03.47,EN,,0,0,0,,Close the minus. Close the star.\r\nDialogue: 0,0:38:03.76,0:38:05.42,EN,,0,0,0,,And now let's get another operator.\r\nDialogue: 0,0:38:05.44,0:38:09.49,EN,,0,0,0,,You see the Lisp editor here is indenting to the right position automatically\r\nDialogue: 0,0:38:10.40,0:38:11.50,EN,,0,0,0,,to help me keep track.\r\nDialogue: 0,0:38:12.61,0:38:14.09,EN,,0,0,0,,I'll do that again.\r\nDialogue: 0,0:38:14.13,0:38:15.89,EN,,0,0,0,,I'll close that last parentheses again.\r\nDialogue: 0,0:38:16.25,0:38:17.71,EN,,0,0,0,,You see it balances the plus.\r\nDialogue: 0,0:38:20.40,0:38:22.64,EN,,0,0,0,,Now I can say, what's the value of that?\r\nDialogue: 0,0:38:23.87,0:38:29.28,EN,,0,0,0,,So those two things, indenting to the right level,\r\nDialogue: 0,0:38:29.31,0:38:30.86,EN,,0,0,0,,which is called pretty printing,\r\nDialogue: 0,0:38:31.55,0:38:33.58,EN,,0,0,0,,and flashing parentheses,\r\nDialogue: 0,0:38:33.89,0:38:37.73,EN,,0,0,0,,are two things that a lot of Lisp systems have built in to help you keep track.\r\nDialogue: 0,0:38:37.76,0:38:39.01,EN,,0,0,0,,And you should learn how to use them.\r\nDialogue: 0,0:38:41.52,0:38:43.17,EN,,0,0,0,,Ok, those are the primitives.\r\nDialogue: 0,0:38:44.73,0:38:46.31,EN,,0,0,0,,There's a means of combination.\r\nDialogue: 0,0:38:46.33,0:38:47.93,EN,,0,0,0,,Now let's go up to the means of abstraction.\r\nDialogue: 0,0:38:49.44,0:38:53.84,EN,,0,0,0,,I'd like to be able to take the idea that I do some combination like this,\r\nDialogue: 0,0:38:53.85,0:38:55.77,EN,,0,0,0,,and abstract it and give it a simple name,\r\nDialogue: 0,0:38:55.81,0:38:57.26,EN,,0,0,0,,so I can use that as an element.\r\nDialogue: 0,0:38:57.31,0:38:59.92,EN,,0,0,0,,And I do that in Lisp with \"define.\"\r\nDialogue: 0,0:39:01.17,0:39:02.43,EN,,0,0,0,,So I can say, for example,\r\nDialogue: 0,0:39:02.73,0:39:15.05,EN,,0,0,0,,define A to be the product of 5 and 5.\r\nDialogue: 0,0:39:18.40,0:39:22.35,EN,,0,0,0,,And now I could say, for example, to Lisp,\r\nDialogue: 0,0:39:22.38,0:39:26.01,EN,,0,0,0,,what is the product of A and A?\r\nDialogue: 0,0:39:27.18,0:39:29.81,EN,,0,0,0,,And this should be 25, and this should be 625.\r\nDialogue: 0,0:39:31.97,0:39:36.01,EN,,0,0,0,,And then, crucial thing, I can now use A--\r\nDialogue: 0,0:39:36.21,0:39:37.92,EN,,0,0,0,,here I've used it in a combination--\r\nDialogue: 0,0:39:38.41,0:39:43.55,EN,,0,0,0,,but I could use that in other more complicated things that I name in turn.\r\nDialogue: 0,0:39:43.58,0:39:50.93,EN,,0,0,0,,So I could say, define B to be the sum of,\r\nDialogue: 0,0:39:50.97,0:39:57.45,EN,,0,0,0,,we'll say, A and the product of 5 and A.\r\nDialogue: 0,0:39:59.44,0:40:00.72,EN,,0,0,0,,And then close the plus.\r\nDialogue: 0,0:40:03.45,0:40:05.85,EN,,0,0,0,,Let's take a look at that on the computer and see how that looks.\r\nDialogue: 0,0:40:07.28,0:40:10.68,EN,,0,0,0,,So I'll just type what I wrote on the board.\r\nDialogue: 0,0:40:10.83,0:40:21.73,EN,,0,0,0,,I could say, define A to be the product of 5 and 5.\r\nDialogue: 0,0:40:23.74,0:40:25.38,EN,,0,0,0,,And I'll tell that to Lisp.\r\nDialogue: 0,0:40:25.52,0:40:28.94,EN,,0,0,0,,And notice what Lisp responded there with was an A in the bottom.\r\nDialogue: 0,0:40:29.09,0:40:31.38,EN,,0,0,0,,In general, when you type in a definition in Lisp,\r\nDialogue: 0,0:40:31.50,0:40:35.02,EN,,0,0,0,,it responds with the symbol being defined.\r\nDialogue: 0,0:40:35.63,0:40:39.66,EN,,0,0,0,,Now I could say to Lisp, what is the product of A and A?\r\nDialogue: 0,0:40:42.81,0:40:44.33,EN,,0,0,0,,And it says that's 625.\r\nDialogue: 0,0:40:46.05,0:41:00.34,EN,,0,0,0,,I can define B to be the sum of A and the product of 5 and A.\r\nDialogue: 0,0:41:00.48,0:41:05.70,EN,,0,0,0,,Close a paren closes the star.  Close the plus. Close the \"define.\"\r\nDialogue: 0,0:41:07.63,0:41:10.37,EN,,0,0,0,,Lisp says, OK, B, there on the bottom.\r\nDialogue: 0,0:41:11.04,0:41:13.24,EN,,0,0,0,,And now I can say to Lisp, what's the value of B?\r\nDialogue: 0,0:41:17.18,0:41:18.88,EN,,0,0,0,,And I can say something more complicated,\r\nDialogue: 0,0:41:18.93,0:41:26.69,EN,,0,0,0,,like what's the sum of A and the quotient of B and 5?\r\nDialogue: 0,0:41:26.73,0:41:30.25,EN,,0,0,0,,That slash is divide, another primitive operator.\r\nDialogue: 0,0:41:30.38,0:41:32.78,EN,,0,0,0,,I've divided B by 5, added it to A.\r\nDialogue: 0,0:41:33.65,0:41:35.23,EN,,0,0,0,,Lisp says, OK, that's 55.\r\nDialogue: 0,0:41:36.57,0:41:37.92,EN,,0,0,0,,So there's what it looks like.\r\nDialogue: 0,0:41:39.82,0:41:43.40,EN,,0,0,0,,There's the basic means of defining something.\r\nDialogue: 0,0:41:43.44,0:41:49.02,EN,,0,0,0,,It's the simplest kind of naming, but it's not really very powerful.\r\nDialogue: 0,0:41:50.06,0:41:51.60,EN,,0,0,0,,See, what I'd really like to name--\r\nDialogue: 0,0:41:51.84,0:41:53.37,EN,,0,0,0,,remember, we're talking about general methods--\r\nDialogue: 0,0:41:53.57,0:41:57.68,EN,,0,0,0,,I'd like to name, oh, the general idea that, for example,\r\nDialogue: 0,0:41:58.11,0:42:17.53,EN,,0,0,0,,I could multiply 5 by 5, or 6 by 6, or 1,001 by 1,001, 1,001.7 by 1,001.7.\r\nDialogue: 0,0:42:17.76,0:42:24.16,EN,,0,0,0,,I'd like to be able to name the general idea of multiplying something by itself.\r\nDialogue: 0,0:42:28.48,0:42:30.11,EN,,0,0,0,,Well, you know what that is. That's called squaring.\r\nDialogue: 0,0:42:31.69,0:42:35.63,EN,,0,0,0,,And the way I can do that in Lisp is I can say,\r\nDialogue: 0,0:42:37.97,0:42:56.25,EN,,0,0,0,,define to square something x, multiply x by itself.\r\nDialogue: 0,0:42:57.87,0:43:01.12,EN,,0,0,0,,And then having done that, I could say to Lisp,\r\nDialogue: 0,0:43:01.12,0:43:05.49,EN,,0,0,0,,for example, what's the square of 10?\r\nDialogue: 0,0:43:06.67,0:43:07.87,EN,,0,0,0,,And Lisp will say 100.\r\nDialogue: 0,0:43:10.70,0:43:14.24,EN,,0,0,0,,So now let's actually look at that a little more closely.\r\nDialogue: 0,0:43:15.29,0:43:16.88,EN,,0,0,0,,Right, there's the definition of square.\r\nDialogue: 0,0:43:17.50,0:43:22.55,EN,,0,0,0,,To square something, multiply it by itself.\r\nDialogue: 0,0:43:23.69,0:43:25.34,EN,,0,0,0,,You see this x here.\r\nDialogue: 0,0:43:26.29,0:43:27.81,EN,,0,0,0,,That x is kind of a pronoun,\r\nDialogue: 0,0:43:27.87,0:43:29.53,EN,,0,0,0,,which is the something that I'm going to square.\r\nDialogue: 0,0:43:31.49,0:43:37.41,EN,,0,0,0,,And what I do with it is I multiply x, I multiply it by itself.\r\nDialogue: 0,0:43:42.22,0:43:48.27,EN,,0,0,0,,OK. So there's the notation for defining a procedure.\r\nDialogue: 0,0:43:48.29,0:43:50.29,EN,,0,0,0,,Actually, this is a little bit confusing,\r\nDialogue: 0,0:43:50.81,0:43:53.97,EN,,0,0,0,,because this is sort of how I might use square.\r\nDialogue: 0,0:43:54.00,0:43:56.80,EN,,0,0,0,,And I say square root of x or square root of 10,\r\nDialogue: 0,0:43:57.55,0:44:00.81,EN,,0,0,0,,but it's not making it very clear that I'm actually naming something.\r\nDialogue: 0,0:44:03.10,0:44:04.91,EN,,0,0,0,,So let me write this definition in another way\r\nDialogue: 0,0:44:05.74,0:44:08.21,EN,,0,0,0,,that makes it a little bit more clear that I'm naming something.\r\nDialogue: 0,0:44:08.54,0:44:29.39,EN,,0,0,0,,I'll say, \"define\" square to be lambda of x times xx.\r\nDialogue: 0,0:44:36.56,0:44:42.05,EN,,0,0,0,,Here, I'm naming something square, just like over here, I'm naming something A.\r\nDialogue: 0,0:44:43.23,0:44:44.72,EN,,0,0,0,,The thing that I'm naming square--\r\nDialogue: 0,0:44:44.75,0:44:48.39,EN,,0,0,0,,here, the thing I named A was the value of this combination.\r\nDialogue: 0,0:44:49.29,0:44:52.41,EN,,0,0,0,,Here, the thing that I'm naming square is this thing\r\nDialogue: 0,0:44:52.43,0:44:53.44,EN,,0,0,0,,that begins with lambda,\r\nDialogue: 0,0:44:53.45,0:44:56.77,EN,,0,0,0,,and lambda is Lisp's way of saying make a procedure.\r\nDialogue: 0,0:45:00.24,0:45:02.91,EN,,0,0,0,,Let's look at that more closely on the slide.\r\nDialogue: 0,0:45:04.27,0:45:05.81,EN,,0,0,0,,The way I read that definition is to say,\r\nDialogue: 0,0:45:05.85,0:45:10.33,EN,,0,0,0,,I define square to be make a procedure--\r\nDialogue: 0,0:45:12.78,0:45:13.97,EN,,0,0,0,,that's what the lambda is--\r\nDialogue: 0,0:45:14.06,0:45:17.49,EN,,0,0,0,,make a procedure with an argument named x.\r\nDialogue: 0,0:45:19.26,0:45:24.09,EN,,0,0,0,,And what it does is return the results of multiplying x by itself.\r\nDialogue: 0,0:45:24.97,0:45:33.12,EN,,0,0,0,,Now, in general, we're going to be using this top form of defining,\r\nDialogue: 0,0:45:33.41,0:45:35.20,EN,,0,0,0,,just because it's a little bit more convenient.\r\nDialogue: 0,0:45:35.21,0:45:38.67,EN,,0,0,0,,But don't lose sight of the fact that it's really this.\r\nDialogue: 0,0:45:38.86,0:45:41.41,EN,,0,0,0,,In fact, as far as the Lisp interpreter's concerned,\r\nDialogue: 0,0:45:41.61,0:45:45.55,EN,,0,0,0,,there's no difference between typing this to it and typing this to it.\r\nDialogue: 0,0:45:46.51,0:45:53.29,EN,,0,0,0,,And there's a word for that, sort of syntactic sugar.\r\nDialogue: 0,0:45:54.41,0:45:55.80,EN,,0,0,0,,What syntactic sugar means,\r\nDialogue: 0,0:45:56.35,0:46:00.83,EN,,0,0,0,,it's having somewhat more convenient surface forms for typing something.\r\nDialogue: 0,0:46:01.12,0:46:06.11,EN,,0,0,0,,So this is just really syntactic sugar for this underlying Greek thing with the lambda.\r\nDialogue: 0,0:46:07.31,0:46:10.62,EN,,0,0,0,,And the reason you should remember that is don't forget that,\r\nDialogue: 0,0:46:10.80,0:46:13.87,EN,,0,0,0,,when I write something like this, I'm really naming something.\r\nDialogue: 0,0:46:14.46,0:46:16.22,EN,,0,0,0,,I'm naming something square,\r\nDialogue: 0,0:46:16.24,0:46:19.90,EN,,0,0,0,,and the something that I'm naming square is a procedure that's getting constructed.\r\nDialogue: 0,0:46:21.20,0:46:23.90,EN,,0,0,0,,Well, let's look at that on the computer, too.\r\nDialogue: 0,0:46:24.78,0:46:35.95,EN,,0,0,0,,So I'll come and I'll say, define square of x to be times xx.\r\nDialogue: 0,0:46:49.65,0:46:52.32,EN,,0,0,0,,Now I'll tell Lisp that.\r\nDialogue: 0,0:46:53.49,0:46:53.92,EN,,0,0,0,,It says \"square.\"\r\nDialogue: 0,0:46:53.93,0:46:56.29,EN,,0,0,0,,See, I've named something \"square.\"\r\nDialogue: 0,0:46:56.45,0:47:02.88,EN,,0,0,0,,Now, having done that, I can ask Lisp for, what's the square of 1,001?\r\nDialogue: 0,0:47:05.26,0:47:17.69,EN,,0,0,0,,Or in general, I could say, what's the square of the sum of 5 and 7?\r\nDialogue: 0,0:47:22.81,0:47:24.95,EN,,0,0,0,,The square of 12's 144.\r\nDialogue: 0,0:47:25.07,0:47:28.86,EN,,0,0,0,,Or I can use square itself as an element in some combination.\r\nDialogue: 0,0:47:28.88,0:47:37.50,EN,,0,0,0,,I can say, what's the sum of the square of 3 and the square of 4?\r\nDialogue: 0,0:47:42.53,0:47:44.09,EN,,0,0,0,,9 and 16 is 25.\r\nDialogue: 0,0:47:44.91,0:47:50.54,EN,,0,0,0,,Or I can use square as an element in some much more complicated thing.\r\nDialogue: 0,0:47:50.59,0:48:00.51,EN,,0,0,0,,I can say, what's the square of, the sqare of, the square of 1,001?\r\nDialogue: 0,0:48:07.89,0:48:10.63,EN,,0,0,0,,And there's the square of the square of the square of 1,001.\r\nDialogue: 0,0:48:11.20,0:48:15.45,EN,,0,0,0,,Or I can say to Lisp, what is square itself?\r\nDialogue: 0,0:48:15.68,0:48:17.16,EN,,0,0,0,,What's the value of that?\r\nDialogue: 0,0:48:17.44,0:48:22.14,EN,,0,0,0,,And Lisp returns some conventional way of telling me that that's a procedure.\r\nDialogue: 0,0:48:22.27,0:48:23.98,EN,,0,0,0,,It says, \"compound procedure square.\"\r\nDialogue: 0,0:48:24.25,0:48:27.92,EN,,0,0,0,,Remember, the value of square is this procedure,\r\nDialogue: 0,0:48:29.15,0:48:30.89,EN,,0,0,0,,and the thing with the stars and the brackets\r\nDialogue: 0,0:48:31.10,0:48:34.78,EN,,0,0,0,,are just Lisp's conventional way of describing that.\r\nDialogue: 0,0:48:36.11,0:48:41.33,EN,,0,0,0,,Let's look at two more examples of defining.\r\nDialogue: 0,0:48:44.91,0:48:46.91,EN,,0,0,0,,Here are two more procedures.\r\nDialogue: 0,0:48:47.36,0:48:52.84,EN,,0,0,0,,I can define the average of x and y to be the sum of x and y divided by 2.\r\nDialogue: 0,0:48:54.67,0:49:01.49,EN,,0,0,0,,Or having had average and mean square, having had average and square,\r\nDialogue: 0,0:49:01.65,0:49:04.71,EN,,0,0,0,,I can use that to talk about the mean square of something,\r\nDialogue: 0,0:49:04.91,0:49:09.26,EN,,0,0,0,,which is the average of the square of x and the square of y.\r\nDialogue: 0,0:49:10.97,0:49:13.63,EN,,0,0,0,,So for example, having done that, I could say,\r\nDialogue: 0,0:49:13.66,0:49:24.88,EN,,0,0,0,,what's the mean square of 2 and 3?\r\nDialogue: 0,0:49:25.23,0:49:30.24,EN,,0,0,0,,And I should get the average of 4 and 9, which is 6.5.\r\nDialogue: 0,0:49:32.85,0:49:36.64,EN,,0,0,0,,The key thing here is that, having defined square,\r\nDialogue: 0,0:49:36.64,0:49:38.67,EN,,0,0,0,,I can use it as if it were primitive.\r\nDialogue: 0,0:49:41.41,0:49:43.07,EN,,0,0,0,,So if we look here on the slide,\r\nDialogue: 0,0:49:44.65,0:49:45.74,EN,,0,0,0,,if I look at mean square,\r\nDialogue: 0,0:49:47.29,0:49:52.56,EN,,0,0,0,,the person defining mean square doesn't have to know, at this point,\r\nDialogue: 0,0:49:52.61,0:49:55.76,EN,,0,0,0,,whether square was something built into the language\r\nDialogue: 0,0:49:56.94,0:49:58.93,EN,,0,0,0,,or whether it was a procedure that was defined.\r\nDialogue: 0,0:49:59.73,0:50:01.28,EN,,0,0,0,,And that's a key thing in Lisp,\r\nDialogue: 0,0:50:02.30,0:50:07.52,EN,,0,0,0,,that you do not make arbitrary distinctions between things\r\nDialogue: 0,0:50:07.53,0:50:11.82,EN,,0,0,0,,that happen to be primitive in the language and things that happen to be built in.\r\nDialogue: 0,0:50:12.83,0:50:14.73,EN,,0,0,0,,A person using that shouldn't even have to know.\r\nDialogue: 0,0:50:14.93,0:50:18.51,EN,,0,0,0,,So the things you construct get used with all the power and flexibility\r\nDialogue: 0,0:50:18.51,0:50:19.53,EN,,0,0,0,,as if they were primitives.\r\nDialogue: 0,0:50:19.57,0:50:22.57,EN,,0,0,0,,In fact, you can drive that home by looking on the computer one more time.\r\nDialogue: 0,0:50:24.75,0:50:26.30,EN,,0,0,0,,We talked about plus.\r\nDialogue: 0,0:50:26.72,0:50:30.09,EN,,0,0,0,,And in fact, if I come here on the computer screen and say,\r\nDialogue: 0,0:50:30.11,0:50:32.33,EN,,0,0,0,,what is the value of plus?\r\nDialogue: 0,0:50:34.40,0:50:37.20,EN,,0,0,0,,Notice what Lisp types out. On the bottom there, it typed out,\r\nDialogue: 0,0:50:37.25,0:50:38.81,EN,,0,0,0,,\"compound procedure plus.\"\r\nDialogue: 0,0:50:39.89,0:50:42.29,EN,,0,0,0,,Because, in this system,\r\nDialogue: 0,0:50:42.33,0:50:45.49,EN,,0,0,0,,it turns out that the addition operator is itself a compound procedure.\r\nDialogue: 0,0:50:45.97,0:50:47.97,EN,,0,0,0,,And if I didn't just type that in, you'd never know that,\r\nDialogue: 0,0:50:48.06,0:50:49.68,EN,,0,0,0,,and it wouldn't make any difference anyway.\r\nDialogue: 0,0:50:49.84,0:50:50.51,EN,,0,0,0,,We don't care.\r\nDialogue: 0,0:50:50.56,0:50:53.39,EN,,0,0,0,,It's below the level of the abstraction that we're dealing with.\r\nDialogue: 0,0:50:54.17,0:50:59.11,EN,,0,0,0,,So the key thing is you cannot tell, should not be able to tell, in general,\r\nDialogue: 0,0:50:59.17,0:51:03.82,EN,,0,0,0,,the difference between things that are built in and things that are compound.\r\nDialogue: 0,0:51:03.84,0:51:04.38,EN,,0,0,0,,Why is that?\r\nDialogue: 0,0:51:04.38,0:51:08.07,EN,,0,0,0,,Because the things that are compound have an abstraction wrapper wrapped around them.\r\nDialogue: 0,0:51:09.05,0:51:11.61,EN,,0,0,0,,We've seen almost all the elements of Lisp now.\r\nDialogue: 0,0:51:12.67,0:51:14.53,EN,,0,0,0,,There's only one more we have to look at,\r\nDialogue: 0,0:51:14.57,0:51:16.53,EN,,0,0,0,,and that is how to make a case analysis.\r\nDialogue: 0,0:51:16.59,0:51:17.70,EN,,0,0,0,,Let me show you what I mean.\r\nDialogue: 0,0:51:18.96,0:51:24.08,EN,,0,0,0,,We might want to think about the mathematical definition of the absolute value functions.\r\nDialogue: 0,0:51:24.11,0:51:30.03,EN,,0,0,0,,I might say the absolute value of x is the function\r\nDialogue: 0,0:51:30.16,0:51:37.24,EN,,0,0,0,,which has the property that it's negative of x. For x less than 0,\r\nDialogue: 0,0:51:37.92,0:51:41.13,EN,,0,0,0,,it's 0 for x equal to 0.\r\nDialogue: 0,0:51:42.64,0:51:46.62,EN,,0,0,0,,And it's x for x greater than 0.\r\nDialogue: 0,0:51:49.15,0:51:51.90,EN,,0,0,0,,And Lisp has a way of making case analyses.\r\nDialogue: 0,0:51:52.11,0:51:53.85,EN,,0,0,0,,Let me define for you absolute value.\r\nDialogue: 0,0:51:55.55,0:52:02.41,EN,,0,0,0,,Say define the absolute value of x is conditional.\r\nDialogue: 0,0:52:03.02,0:52:05.67,EN,,0,0,0,,This means case analysis, COND.\r\nDialogue: 0,0:52:09.23,0:52:19.09,EN,,0,0,0,,If x is less than 0, the answer is negate x.\r\nDialogue: 0,0:52:22.99,0:52:24.88,EN,,0,0,0,,What I've written here is a clause.\r\nDialogue: 0,0:52:24.99,0:52:35.54,EN,,0,0,0,,This whole thing is a conditional clause, and it has two parts.\r\nDialogue: 0,0:52:36.35,0:52:44.70,EN,,0,0,0,,This part here is a predicate or a condition.\r\nDialogue: 0,0:52:44.83,0:52:45.90,EN,,0,0,0,,That's a condition.\r\nDialogue: 0,0:52:46.11,0:52:48.29,EN,,0,0,0,,And the condition is expressed by something called a predicate,\r\nDialogue: 0,0:52:48.33,0:52:51.05,EN,,0,0,0,,and a predicate in Lisp is some sort of thing\r\nDialogue: 0,0:52:51.37,0:52:52.87,EN,,0,0,0,,that returns either true or false.\r\nDialogue: 0,0:52:53.53,0:52:56.13,EN,,0,0,0,,And you see Lisp has a primitive procedure, less-than,\r\nDialogue: 0,0:52:57.29,0:52:59.08,EN,,0,0,0,,that tests whether something is true or false.\r\nDialogue: 0,0:53:00.54,0:53:06.32,EN,,0,0,0,,And the other part of a clause is an action or a thing to do,\r\nDialogue: 0,0:53:06.93,0:53:08.14,EN,,0,0,0,,in the case where that's true.\r\nDialogue: 0,0:53:08.17,0:53:09.81,EN,,0,0,0,,And here, what I'm doing is negating x.\r\nDialogue: 0,0:53:10.08,0:53:14.41,EN,,0,0,0,,The negation operator, the minus sign in Lisp is a little bit funny.\r\nDialogue: 0,0:53:14.56,0:53:18.43,EN,,0,0,0,,If there's two or more arguments,\r\nDialogue: 0,0:53:18.58,0:53:22.49,EN,,0,0,0,,if there's two arguments it subtracts the second one from the first, and we saw that.\r\nDialogue: 0,0:53:22.53,0:53:24.13,EN,,0,0,0,,And if there's one argument, it negates it.\r\nDialogue: 0,0:53:25.13,0:53:27.87,EN,,0,0,0,,So this corresponds to that.\r\nDialogue: 0,0:53:27.87,0:53:29.69,EN,,0,0,0,,And then there's another COND clause.\r\nDialogue: 0,0:53:30.64,0:53:35.87,EN,,0,0,0,,It says, in the case where x is equal to 0, the answer is 0.\r\nDialogue: 0,0:53:37.95,0:53:44.75,EN,,0,0,0,,And in the case where x is greater than 0, the answer is x.\r\nDialogue: 0,0:53:45.33,0:53:49.38,EN,,0,0,0,,Close that clause. Close the COND. Close the definition.\r\nDialogue: 0,0:53:49.57,0:53:51.29,EN,,0,0,0,,And there's the definition of absolute value.\r\nDialogue: 0,0:53:51.31,0:53:53.66,EN,,0,0,0,,And you see it's the case analysis that looks very much\r\nDialogue: 0,0:53:53.66,0:53:56.04,EN,,0,0,0,,like the case analysis you use in mathematics.\r\nDialogue: 0,0:53:58.14,0:54:03.07,EN,,0,0,0,,There's a somewhat different way of writing a restricted case analysis.\r\nDialogue: 0,0:54:03.07,0:54:06.24,EN,,0,0,0,,Often, you have a case analysis where you only have one case,\r\nDialogue: 0,0:54:06.93,0:54:08.07,EN,,0,0,0,,where you test something,\r\nDialogue: 0,0:54:08.33,0:54:10.75,EN,,0,0,0,,and then depending on whether it's true or false, you do something.\r\nDialogue: 0,0:54:11.01,0:54:15.90,EN,,0,0,0,,And here's another definition of absolute value\r\nDialogue: 0,0:54:16.00,0:54:17.19,EN,,0,0,0,,which looks almost the same,\r\nDialogue: 0,0:54:17.66,0:54:22.56,EN,,0,0,0,,which says, if x is less than 0, the result is negate x.\r\nDialogue: 0,0:54:24.41,0:54:25.97,EN,,0,0,0,,Otherwise, the answer is x.\r\nDialogue: 0,0:54:26.05,0:54:27.25,EN,,0,0,0,,And we'll be using \"if\" a lot.\r\nDialogue: 0,0:54:27.29,0:54:29.13,EN,,0,0,0,,But again, the thing to remember is that\r\nDialogue: 0,0:54:29.13,0:54:32.70,EN,,0,0,0,,this form of absolute value that you're looking at here,\r\nDialogue: 0,0:54:34.30,0:54:36.98,EN,,0,0,0,,and then this one over here that I wrote on the board,\r\nDialogue: 0,0:54:37.52,0:54:38.80,EN,,0,0,0,,are essentially the same.\r\nDialogue: 0,0:54:39.09,0:54:42.26,EN,,0,0,0,,And \"if\" and COND are-- well, whichever way you like it.\r\nDialogue: 0,0:54:42.30,0:54:44.45,EN,,0,0,0,,You can think of COND as syntactic sugar for \"if\",\r\nDialogue: 0,0:54:44.99,0:54:47.36,EN,,0,0,0,,or you can think of \"if\" as syntactic sugar for COND,\r\nDialogue: 0,0:54:47.39,0:54:48.65,EN,,0,0,0,,and it doesn't make any difference.\r\nDialogue: 0,0:54:49.21,0:54:51.35,EN,,0,0,0,,The person implementing a Lisp system will pick one\r\nDialogue: 0,0:54:51.39,0:54:52.97,EN,,0,0,0,,and implement the other in terms of that.\r\nDialogue: 0,0:54:53.15,0:54:54.67,EN,,0,0,0,,And it doesn't matter which one you pick.\r\nDialogue: 0,0:55:02.27,0:55:05.36,EN,,0,0,0,,Why don't we break now, and then take some questions.\r\nDialogue: 0,0:55:05.69,0:55:10.08,EN,,0,0,0,,How come sometimes when I write define,\r\nDialogue: 0,0:55:11.09,0:55:14.75,EN,,0,0,0,,I put an open paren here and say,\r\nDialogue: 0,0:55:14.81,0:55:16.45,EN,,0,0,0,,define open paren something or other,\r\nDialogue: 0,0:55:16.86,0:55:20.81,EN,,0,0,0,,and sometimes when I write this, I don't put an open paren?\r\nDialogue: 0,0:55:22.06,0:55:27.23,EN,,0,0,0,,The answer is, this particular form of \"define\",\r\nDialogue: 0,0:55:27.26,0:55:29.41,EN,,0,0,0,,where you say define some expression,\r\nDialogue: 0,0:55:29.47,0:55:32.13,EN,,0,0,0,,is this very special thing for defining procedures.\r\nDialogue: 0,0:55:33.61,0:55:40.21,EN,,0,0,0,,But again, what it really means is I'm defining this symbol, square, to be that.\r\nDialogue: 0,0:55:41.45,0:55:45.98,EN,,0,0,0,,So the way you should think about it is what \"define\" does is you write \"define\",\r\nDialogue: 0,0:55:47.15,0:55:50.06,EN,,0,0,0,,and the second thing you write is the symbol here-- no open paren--\r\nDialogue: 0,0:55:50.17,0:55:51.49,EN,,0,0,0,,the symbol you're defining\r\nDialogue: 0,0:55:52.08,0:55:53.70,EN,,0,0,0,,and what you're defining it to be.\r\nDialogue: 0,0:55:54.65,0:55:57.55,EN,,0,0,0,,That's like here and like here.\r\nDialogue: 0,0:55:57.61,0:56:00.29,EN,,0,0,0,,That's sort of the basic way you use \"define.\"\r\nDialogue: 0,0:56:01.12,0:56:03.65,EN,,0,0,0,,And then, there's this special syntactic trick\r\nDialogue: 0,0:56:04.29,0:56:07.04,EN,,0,0,0,,which allows you to define procedures that look like this.\r\nDialogue: 0,0:56:08.17,0:56:11.49,EN,,0,0,0,,So the difference is, it's whether or not you're defining a procedure.\r\nDialogue: 0,0:56:12.91,0:56:37.60,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\r\nDialogue: 0,0:56:38.05,0:56:41.98,EN,,0,0,0,,Well, believe it or not, you actually now know enough Lisp\r\nDialogue: 0,0:56:42.78,0:56:45.42,EN,,0,0,0,,to write essentially any numerical procedure\r\nDialogue: 0,0:56:46.25,0:56:49.63,EN,,0,0,0,,that you'd write in a language like FORTRAN or Basic or whatever,\r\nDialogue: 0,0:56:49.66,0:56:51.01,EN,,0,0,0,,or, essentially, any other language.\r\nDialogue: 0,0:56:52.05,0:56:54.76,EN,,0,0,0,,And you're probably saying, that's not believable,\r\nDialogue: 0,0:56:54.81,0:56:56.65,EN,,0,0,0,,because you know that these languages have things\r\nDialogue: 0,0:56:56.65,0:57:00.22,EN,,0,0,0,,like \"for statements\", and \"do until while\" or something.\r\nDialogue: 0,0:57:00.99,0:57:04.59,EN,,0,0,0,,But we don't really need any of that.\r\nDialogue: 0,0:57:05.05,0:57:07.13,EN,,0,0,0,,In fact, we're not going to use any of that in this course.\r\nDialogue: 0,0:57:08.25,0:57:10.16,EN,,0,0,0,,Let me show you.\r\nDialogue: 0,0:57:10.25,0:57:13.61,EN,,0,0,0,,Again, looking back at square root,\r\nDialogue: 0,0:57:13.65,0:57:19.03,EN,,0,0,0,,let's go back to this square root algorithm of Heron of Alexandria.\r\nDialogue: 0,0:57:19.09,0:57:19.97,EN,,0,0,0,,Remember what that said.\r\nDialogue: 0,0:57:20.06,0:57:23.67,EN,,0,0,0,,It said, to find an approximation to the square root of X,\r\nDialogue: 0,0:57:25.07,0:57:26.16,EN,,0,0,0,,you make a guess,\r\nDialogue: 0,0:57:27.45,0:57:31.88,EN,,0,0,0,,you improve that guess by averaging the guess and X over the guess.\r\nDialogue: 0,0:57:32.94,0:57:36.06,EN,,0,0,0,,You keep improving that until the guess is good enough.\r\nDialogue: 0,0:57:36.72,0:57:38.43,EN,,0,0,0,,I already alluded to the idea.\r\nDialogue: 0,0:57:38.56,0:57:42.24,EN,,0,0,0,,The idea is that, if the initial guess that you took\r\nDialogue: 0,0:57:43.04,0:57:46.91,EN,,0,0,0,,was actually equal to the square root of X,\r\nDialogue: 0,0:57:47.15,0:57:50.06,EN,,0,0,0,,then G here would be equal to X/G.\r\nDialogue: 0,0:57:52.89,0:57:55.33,EN,,0,0,0,,So if you hit the square root, averaging them wouldn't change it.\r\nDialogue: 0,0:57:55.69,0:57:59.62,EN,,0,0,0,,If the G that you picked was larger than the square root of X,\r\nDialogue: 0,0:58:00.38,0:58:02.94,EN,,0,0,0,,then X/G will be smaller than the square root of X,\r\nDialogue: 0,0:58:03.21,0:58:05.37,EN,,0,0,0,,so that when you average G and X/G,\r\nDialogue: 0,0:58:05.63,0:58:07.57,EN,,0,0,0,,you get something in between.\r\nDialogue: 0,0:58:08.96,0:58:12.95,EN,,0,0,0,,So if you pick a G that's too small, your answer will be too large.\r\nDialogue: 0,0:58:13.12,0:58:14.81,EN,,0,0,0,,If you pick a G that's too large,\r\nDialogue: 0,0:58:16.32,0:58:18.06,EN,,0,0,0,,if your G is larger than the square root of X\r\nDialogue: 0,0:58:18.08,0:58:20.35,EN,,0,0,0,,and X/G will be smaller than the square root of X.\r\nDialogue: 0,0:58:21.23,0:58:23.65,EN,,0,0,0,,So averaging always gives you something in between.\r\nDialogue: 0,0:58:24.53,0:58:28.13,EN,,0,0,0,,And then, it's not quite trivial, but it's possible to show that,\r\nDialogue: 0,0:58:28.17,0:58:31.76,EN,,0,0,0,,in fact, if G misses the square root of X by a little bit,\r\nDialogue: 0,0:58:31.81,0:58:37.99,EN,,0,0,0,,the average of G and X/G will actually keep getting closer to the square root of X.\r\nDialogue: 0,0:58:38.03,0:58:38.99,EN,,0,0,0,,So if you keep doing this enough,\r\nDialogue: 0,0:58:39.42,0:58:41.18,EN,,0,0,0,,you'll eventually get as close as you want.\r\nDialogue: 0,0:58:41.71,0:58:42.85,EN,,0,0,0,,And then there's another fact,\r\nDialogue: 0,0:58:43.02,0:58:47.65,EN,,0,0,0,,that you can always start out this process by using 1 as an initial guess.\r\nDialogue: 0,0:58:49.23,0:58:51.35,EN,,0,0,0,,And it'll always converge to the square root of X.\r\nDialogue: 0,0:58:52.24,0:58:56.77,EN,,0,0,0,,So that's this method of successive averaging due to Heron of Alexandria.\r\nDialogue: 0,0:58:56.81,0:58:59.21,EN,,0,0,0,,Let's write it in Lisp.\r\nDialogue: 0,0:59:00.57,0:59:02.61,EN,,0,0,0,,Well, the central idea is,\r\nDialogue: 0,0:59:02.65,0:59:07.19,EN,,0,0,0,,what does it mean to try a guess for the square root of X?\r\nDialogue: 0,0:59:08.30,0:59:09.37,EN,,0,0,0,,Let's write that.\r\nDialogue: 0,0:59:09.79,0:59:25.02,EN,,0,0,0,,So we'll say, define to try a guess for the square root of X,\r\nDialogue: 0,0:59:26.45,0:59:28.24,EN,,0,0,0,,what do we do? We'll say,\r\nDialogue: 0,0:59:28.29,0:59:45.26,EN,,0,0,0,,if the guess is good enough to be a guess for the square root of X,\r\nDialogue: 0,0:59:46.54,0:59:49.52,EN,,0,0,0,,then, as an answer, we'll take the guess.\r\nDialogue: 0,0:59:51.61,0:59:57.01,EN,,0,0,0,,Otherwise, we will try the improved guess.\r\nDialogue: 0,0:59:58.19,1:00:04.24,EN,,0,0,0,,We'll improve that guess for the square root of X,\r\nDialogue: 0,1:00:05.26,1:00:09.33,EN,,0,0,0,,and we'll try that as a guess for the square root of X.\r\nDialogue: 0,1:00:09.36,1:00:12.96,EN,,0,0,0,,Close the \"try.\" Close the \"if.\" Close the \"define.\"\r\nDialogue: 0,1:00:13.31,1:00:14.81,EN,,0,0,0,,So that's how we try a guess.\r\nDialogue: 0,1:00:15.85,1:00:17.60,EN,,0,0,0,,And then, the next part of the process said,\r\nDialogue: 0,1:00:17.73,1:00:21.90,EN,,0,0,0,,in order to compute square roots, we'll say,\r\nDialogue: 0,1:00:21.93,1:00:30.17,EN,,0,0,0,,define to compute the square root of X,\r\nDialogue: 0,1:00:30.80,1:00:35.79,EN,,0,0,0,,we will try 1 as a guess for the square root of X.\r\nDialogue: 0,1:00:37.42,1:00:39.59,EN,,0,0,0,,Well, we have to define a couple more things.\r\nDialogue: 0,1:00:40.08,1:00:43.36,EN,,0,0,0,,We have to say, how is a guess good enough?\r\nDialogue: 0,1:00:43.84,1:00:45.29,EN,,0,0,0,,And how do we improve a guess?\r\nDialogue: 0,1:00:45.85,1:00:47.10,EN,,0,0,0,,So let's look at that.\r\nDialogue: 0,1:00:47.39,1:00:54.24,EN,,0,0,0,,The algorithm to improve a guess for the square root of X,\r\nDialogue: 0,1:00:54.64,1:00:57.18,EN,,0,0,0,,we average-- that was the algorithm--\r\nDialogue: 0,1:00:57.18,1:01:02.16,EN,,0,0,0,,we average the guess with the quotient of dividing X by the guess.\r\nDialogue: 0,1:01:02.99,1:01:04.57,EN,,0,0,0,,That's how we improve a guess.\r\nDialogue: 0,1:01:05.85,1:01:08.80,EN,,0,0,0,,And to tell whether a guess is good enough, well, we have to decide something.\r\nDialogue: 0,1:01:08.86,1:01:11.36,EN,,0,0,0,,This is supposed to be a guess for the square root of X,\r\nDialogue: 0,1:01:11.37,1:01:14.03,EN,,0,0,0,,so one possible thing you can do is say,\r\nDialogue: 0,1:01:14.06,1:01:16.07,EN,,0,0,0,,when you take that guess and square it,\r\nDialogue: 0,1:01:16.64,1:01:18.41,EN,,0,0,0,,do you get something very close to X?\r\nDialogue: 0,1:01:18.59,1:01:21.10,EN,,0,0,0,,So one way to say that is to say,\r\nDialogue: 0,1:01:21.12,1:01:24.31,EN,,0,0,0,,I square the guess, subtract X from that,\r\nDialogue: 0,1:01:25.15,1:01:27.15,EN,,0,0,0,,and see if the absolute value of that\r\nDialogue: 0,1:01:27.20,1:01:32.05,EN,,0,0,0,,whole thing is less than some small number, which depends on my purposes.\r\nDialogue: 0,1:01:34.70,1:01:41.42,EN,,0,0,0,,So there's a complete procedure for how to compute the square root of X.\r\nDialogue: 0,1:01:41.47,1:01:43.53,EN,,0,0,0,,Let's look at the structure of that a little bit.\r\nDialogue: 0,1:01:47.84,1:01:49.12,EN,,0,0,0,,I have the whole thing.\r\nDialogue: 0,1:01:49.15,1:01:55.44,EN,,0,0,0,,I have the notion of how to compute a square root.\r\nDialogue: 0,1:01:55.53,1:01:56.88,EN,,0,0,0,,That's some kind of module.\r\nDialogue: 0,1:01:57.05,1:01:58.46,EN,,0,0,0,,That's some kind of black box.\r\nDialogue: 0,1:01:58.72,1:02:08.02,EN,,0,0,0,,It's defined in terms of how to try a guess for the square root of X.\r\nDialogue: 0,1:02:09.31,1:02:14.10,EN,,0,0,0,,\"Try\" is defined in terms of, well,\r\nDialogue: 0,1:02:14.61,1:02:18.03,EN,,0,0,0,,telling whether something is good enough and telling how to improve something.\r\nDialogue: 0,1:02:18.73,1:02:19.68,EN,,0,0,0,,So good enough.\r\nDialogue: 0,1:02:19.89,1:02:28.85,EN,,0,0,0,,\"Try\" is defined in terms of \"good enough\" and \"improve\".\r\nDialogue: 0,1:02:30.96,1:02:32.56,EN,,0,0,0,,And let's see what else I fill in.\r\nDialogue: 0,1:02:32.71,1:02:34.29,EN,,0,0,0,,Well, I'll go down this tree.\r\nDialogue: 0,1:02:34.73,1:02:38.49,EN,,0,0,0,,\"Good enough\" was defined in terms of absolute value, and square.\r\nDialogue: 0,1:02:40.97,1:02:44.13,EN,,0,0,0,,And improve was defined in terms of something called averaging\r\nDialogue: 0,1:02:45.17,1:02:46.70,EN,,0,0,0,,and then some other primitive operator.\r\nDialogue: 0,1:02:46.72,1:02:48.88,EN,,0,0,0,,Square root's defined in terms of \"try\".\r\nDialogue: 0,1:02:48.88,1:02:53.31,EN,,0,0,0,,\"Try\" is defined in terms of \"good enough\" and \"improve\",\r\nDialogue: 0,1:02:54.01,1:02:55.39,EN,,0,0,0,,but also \"try\" itself.\r\nDialogue: 0,1:02:55.58,1:03:00.86,EN,,0,0,0,,So \"try\" is also defined in terms of how to try itself.\r\nDialogue: 0,1:03:02.75,1:03:04.72,EN,,0,0,0,,Well, that may give you some problems.\r\nDialogue: 0,1:03:04.72,1:03:08.16,EN,,0,0,0,,Your high school geometry teacher probably told you\r\nDialogue: 0,1:03:08.67,1:03:12.57,EN,,0,0,0,,that it's naughty to try and define things in terms of themselves,\r\nDialogue: 0,1:03:12.88,1:03:13.92,EN,,0,0,0,,because it doesn't make sense.\r\nDialogue: 0,1:03:13.92,1:03:14.72,EN,,0,0,0,,But that's false.\r\nDialogue: 0,1:03:16.03,1:03:19.68,EN,,0,0,0,,Sometimes it makes perfect sense to define things in terms of themselves.\r\nDialogue: 0,1:03:20.16,1:03:24.38,EN,,0,0,0,,And this is the case. And we can look at that.\r\nDialogue: 0,1:03:24.38,1:03:26.89,EN,,0,0,0,,We could write down what this means, and say,\r\nDialogue: 0,1:03:26.91,1:03:30.33,EN,,0,0,0,,suppose I asked Lisp what the square root of 2 is.\r\nDialogue: 0,1:03:32.65,1:03:34.67,EN,,0,0,0,,What's the square root of 2 mean?\r\nDialogue: 0,1:03:35.79,1:03:43.61,EN,,0,0,0,,Well, that means I try 1 as a guess for the square root of 2.\r\nDialogue: 0,1:03:46.97,1:03:50.92,EN,,0,0,0,,Now I look. I say, gee, is 1 a good enough guess for the square root of 2?\r\nDialogue: 0,1:03:51.65,1:03:53.69,EN,,0,0,0,,And that depends on the test that \"good enough\" does.\r\nDialogue: 0,1:03:54.61,1:03:56.56,EN,,0,0,0,,And in this case, \"good enough\" will say,\r\nDialogue: 0,1:03:56.65,1:03:59.05,EN,,0,0,0,,no, 1 is not a good enough guess for the square root of 2.\r\nDialogue: 0,1:03:59.79,1:04:08.22,EN,,0,0,0,,So that will reduce to saying, I have to try an improved--\r\nDialogue: 0,1:04:08.64,1:04:12.63,EN,,0,0,0,,improve 1 as a guess for the square root of 2,\r\nDialogue: 0,1:04:15.15,1:04:17.46,EN,,0,0,0,,and try that as a guess for the square root of 2.\r\nDialogue: 0,1:04:19.13,1:04:22.07,EN,,0,0,0,,Improving 1 as a guess for the square root of 2\r\nDialogue: 0,1:04:22.09,1:04:25.08,EN,,0,0,0,,means I average 1 and 2 divided by 1.\r\nDialogue: 0,1:04:27.10,1:04:29.10,EN,,0,0,0,,So this is going to be average.\r\nDialogue: 0,1:04:29.58,1:04:39.44,EN,,0,0,0,,This piece here will be the average of 1 and the quotient of 2 by 1.\r\nDialogue: 0,1:04:40.83,1:04:42.75,EN,,0,0,0,,That's this piece here.\r\nDialogue: 0,1:04:43.85,1:04:46.72,EN,,0,0,0,,And I'm gonna try... And this is 1.5.\r\nDialogue: 0,1:04:49.07,1:04:54.40,EN,,0,0,0,,So this square root of 2 reduces to trying 1 for the square root of 2,\r\nDialogue: 0,1:04:54.56,1:05:04.83,EN,,0,0,0,,which reduces to trying 1.5 as a guess for the square root of 2.\r\nDialogue: 0,1:05:06.03,1:05:08.06,EN,,0,0,0,,So that makes sense.\r\nDialogue: 0,1:05:08.11,1:05:09.52,EN,,0,0,0,,Let's look at the rest of the process.\r\nDialogue: 0,1:05:09.73,1:05:15.00,EN,,0,0,0,,If I try 1.5, that reduces.\r\nDialogue: 0,1:05:15.01,1:05:19.05,EN,,0,0,0,,1.5 turns out to be not good enough as a guess for the square root of 2.\r\nDialogue: 0,1:05:20.22,1:05:22.00,EN,,0,0,0,,So that reduces to trying the average of\r\nDialogue: 0,1:05:22.01,1:05:26.17,EN,,0,0,0,,1.5 and 2 divided by 1.5 as a guess for the square root of 2.\r\nDialogue: 0,1:05:28.29,1:05:30.37,EN,,0,0,0,,That average turns out to be 1.333.\r\nDialogue: 0,1:05:31.18,1:05:35.24,EN,,0,0,0,,So this whole thing reduces to trying 1.333 as a guess for the square root of 2.\r\nDialogue: 0,1:05:35.28,1:05:36.06,EN,,0,0,0,,And then so on.\r\nDialogue: 0,1:05:38.01,1:05:41.66,EN,,0,0,0,,That reduces to another called a \"good enough\", 1.4 something or other.\r\nDialogue: 0,1:05:41.73,1:05:44.47,EN,,0,0,0,,And then it keeps going until the process finally stops\r\nDialogue: 0,1:05:44.85,1:05:47.92,EN,,0,0,0,,with something that \"good enough\" thinks is good enough, which,\r\nDialogue: 0,1:05:47.97,1:05:51.28,EN,,0,0,0,,in this case, is 1.4142 something or other.\r\nDialogue: 0,1:05:52.51,1:05:56.05,EN,,0,0,0,,So the process makes perfect sense.\r\nDialogue: 0,1:05:59.93,1:06:03.10,EN,,0,0,0,,This, by the way, is called a recursive definition.\r\nDialogue: 0,1:06:14.40,1:06:20.96,EN,,0,0,0,,And the ability to make recursive definitions is a source of incredible power.\r\nDialogue: 0,1:06:21.95,1:06:23.05,EN,,0,0,0,,And as you can already see I've hinted at,\r\nDialogue: 0,1:06:23.09,1:06:27.21,EN,,0,0,0,,it's the thing that effectively allows you to do these infinite computations\r\nDialogue: 0,1:06:27.25,1:06:28.83,EN,,0,0,0,,that go on until something is true,\r\nDialogue: 0,1:06:29.73,1:06:33.66,EN,,0,0,0,,without having any other constricts other than the ability to call a procedure.\r\nDialogue: 0,1:06:35.97,1:06:37.47,EN,,0,0,0,,Well, let's see, there's one more thing.\r\nDialogue: 0,1:06:37.71,1:06:44.21,EN,,0,0,0,,Let me show you a variant of this definition of square root here on the slide.\r\nDialogue: 0,1:06:44.43,1:06:48.16,EN,,0,0,0,,Here's sort of the same thing.\r\nDialogue: 0,1:06:48.40,1:06:51.49,EN,,0,0,0,,What I've done here is packaged the definitions of\r\nDialogue: 0,1:06:51.52,1:06:56.16,EN,,0,0,0,,\"improve\" and \"good enough\" and \"try\" inside \"square root\".\r\nDialogue: 0,1:06:56.75,1:07:00.99,EN,,0,0,0,,So, in effect, what I've done is I've built a square root box.\r\nDialogue: 0,1:07:01.81,1:07:08.53,EN,,0,0,0,,So I've built a box that's the square root procedure that someone can use.\r\nDialogue: 0,1:07:08.57,1:07:11.47,EN,,0,0,0,,They might put in 36 and get out 6.\r\nDialogue: 0,1:07:11.81,1:07:13.83,EN,,0,0,0,,And then, packaged inside this box\r\nDialogue: 0,1:07:14.16,1:07:23.85,EN,,0,0,0,,are the definitions of \"try\" and \"good enough\" and \"improve.\"\r\nDialogue: 0,1:07:26.78,1:07:28.35,EN,,0,0,0,,So they're hidden inside this box.\r\nDialogue: 0,1:07:28.40,1:07:30.76,EN,,0,0,0,,And the reason for doing that is that,\r\nDialogue: 0,1:07:31.18,1:07:32.85,EN,,0,0,0,,if someone's using this square root,\r\nDialogue: 0,1:07:33.21,1:07:34.73,EN,,0,0,0,,if George is using this square root,\r\nDialogue: 0,1:07:34.75,1:07:37.36,EN,,0,0,0,,George probably doesn't care very much that,\r\nDialogue: 0,1:07:38.29,1:07:40.03,EN,,0,0,0,,when I implemented square root,\r\nDialogue: 0,1:07:40.21,1:07:44.45,EN,,0,0,0,,I had things inside there called \"try\" and \"good enough\" and \"improve\".\r\nDialogue: 0,1:07:46.40,1:07:49.33,EN,,0,0,0,,And in fact, Harry might have a cube root procedure\r\nDialogue: 0,1:07:49.37,1:07:50.96,EN,,0,0,0,,that has \"try\" and \"good enough\" and \"improve\".\r\nDialogue: 0,1:07:51.44,1:07:53.34,EN,,0,0,0,,And in order to not get the whole system confused,\r\nDialogue: 0,1:07:53.36,1:07:57.66,EN,,0,0,0,,it'd be good for Harry to package his internal procedures inside his cube root procedure.\r\nDialogue: 0,1:07:58.40,1:08:00.06,EN,,0,0,0,,Well, this is called block structure,\r\nDialogue: 0,1:08:00.32,1:08:08.96,EN,,0,0,0,,this particular way of packaging internals inside of a definition.\r\nDialogue: 0,1:08:09.97,1:08:12.96,EN,,0,0,0,,And let's go back and look at the slide again.\r\nDialogue: 0,1:08:13.12,1:08:18.57,EN,,0,0,0,,The way to read this kind of procedure is to say, to define \"square root\",\r\nDialogue: 0,1:08:19.87,1:08:21.84,EN,,0,0,0,,well, inside that definition,\r\nDialogue: 0,1:08:22.13,1:08:25.49,EN,,0,0,0,,I'll have the definition of an \"improve\" and\r\nDialogue: 0,1:08:25.56,1:08:28.88,EN,,0,0,0,,the definition of \"good enough\" and the definition of \"try.\"\r\nDialogue: 0,1:08:29.73,1:08:32.38,EN,,0,0,0,,And then, subject to those definitions,\r\nDialogue: 0,1:08:32.48,1:08:35.07,EN,,0,0,0,,the way I do square root is to try 1.\r\nDialogue: 0,1:08:36.08,1:08:39.33,EN,,0,0,0,,And notice here, I don't have to say 1 as a guess for the square root of X,\r\nDialogue: 0,1:08:39.87,1:08:42.32,EN,,0,0,0,,because since it's all inside the square root,\r\nDialogue: 0,1:08:42.84,1:08:44.65,EN,,0,0,0,,it sort of has this X known.\r\nDialogue: 0,1:08:54.06,1:08:56.37,EN,,0,0,0,,Let me summarize.\r\nDialogue: 0,1:08:56.49,1:08:59.49,EN,,0,0,0,,We started out with the idea that\r\nDialogue: 0,1:08:59.51,1:09:03.18,EN,,0,0,0,,what we're going to be doing is expressing imperative knowledge.\r\nDialogue: 0,1:09:04.99,1:09:09.74,EN,,0,0,0,,And in fact, here's a slide that summarizes the way we looked at Lisp.\r\nDialogue: 0,1:09:09.74,1:09:15.12,EN,,0,0,0,,We started out by looking at some primitive elements in addition and multiplication,\r\nDialogue: 0,1:09:15.85,1:09:19.50,EN,,0,0,0,,some predicates for testing whether something is less-than or something's equal.\r\nDialogue: 0,1:09:19.52,1:09:22.99,EN,,0,0,0,,And in fact, we saw really sneakily in the system we're actually using,\r\nDialogue: 0,1:09:23.02,1:09:25.85,EN,,0,0,0,,these aren't actually primitives, but it doesn't matter.\r\nDialogue: 0,1:09:26.62,1:09:28.59,EN,,0,0,0,,What matters is we're going to use them as if they're primitives.\r\nDialogue: 0,1:09:28.61,1:09:29.81,EN,,0,0,0,,We're not going to look inside.\r\nDialogue: 0,1:09:30.29,1:09:33.15,EN,,0,0,0,,We also have some primitive data and some numbers.\r\nDialogue: 0,1:09:34.62,1:09:37.66,EN,,0,0,0,,We saw some means of composition, means of combination,\r\nDialogue: 0,1:09:37.74,1:09:41.37,EN,,0,0,0,,the basic one being composing functions and\r\nDialogue: 0,1:09:41.41,1:09:43.76,EN,,0,0,0,,building combinations with operators and operands.\r\nDialogue: 0,1:09:44.81,1:09:48.43,EN,,0,0,0,,And there were some other things, like COND and \"if\" and \"define\".\r\nDialogue: 0,1:09:51.29,1:09:53.69,EN,,0,0,0,,But the main thing about \"define,\" in particular,\r\nDialogue: 0,1:09:53.87,1:09:55.71,EN,,0,0,0,,was that it was the means of abstraction.\r\nDialogue: 0,1:09:55.73,1:09:57.70,EN,,0,0,0,,It was the way that we name things.\r\nDialogue: 0,1:09:57.79,1:10:00.30,EN,,0,0,0,,You can also see from this slide not only where we've been,\r\nDialogue: 0,1:10:01.57,1:10:06.28,EN,,0,0,0,,At some point, we'll have to talk about how you combine primitive data to get compound data,\r\nDialogue: 0,1:10:06.56,1:10:12.03,EN,,0,0,0,,and how you abstract data so you can use large globs of data\r\nDialogue: 0,1:10:12.06,1:10:13.07,EN,,0,0,0,,as if they were primitive.\r\nDialogue: 0,1:10:13.90,1:10:15.87,EN,,0,0,0,,So that's where we're going.\r\nDialogue: 0,1:10:16.38,1:10:22.05,EN,,0,0,0,,But before we do that, for the next couple of lectures we're going to be talking about,\r\nDialogue: 0,1:10:23.26,1:10:26.76,EN,,0,0,0,,first of all, how it is that you make a link\r\nDialogue: 0,1:10:26.88,1:10:30.77,EN,,0,0,0,,between these procedures we write and the processes that happen in the machine.\r\nDialogue: 0,1:10:32.14,1:10:35.98,EN,,0,0,0,,And then, how it is that you start using the power of Lisp\r\nDialogue: 0,1:10:36.38,1:10:39.77,EN,,0,0,0,,to talk not only about these individual little computations,\r\nDialogue: 0,1:10:40.08,1:10:44.15,EN,,0,0,0,,but about general conventional methods of doing things.\r\nDialogue: 0,1:10:44.81,1:10:46.17,EN,,0,0,0,,OK, are there any questions?\r\nDialogue: 0,1:10:46.75,1:10:52.27,EN,,0,0,0,,AUDIENCE: Yes. If we defined A using parentheses instead of as we did,\r\nDialogue: 0,1:10:52.32,1:10:53.50,EN,,0,0,0,,what would be the difference?\r\nDialogue: 0,1:10:53.60,1:10:56.88,EN,,0,0,0,,PROFESSOR: If I wrote this, if I wrote that,\r\nDialogue: 0,1:10:57.53,1:11:02.13,EN,,0,0,0,,what I would be doing is defining a procedure named A.\r\nDialogue: 0,1:11:03.21,1:11:06.85,EN,,0,0,0,,In this case, a procedure of no arguments, which,\r\nDialogue: 0,1:11:06.85,1:11:09.61,EN,,0,0,0,,when I ran it, would give me back 5 times 5.\r\nDialogue: 0,1:11:11.07,1:11:12.29,EN,,0,0,0,,AUDIENCE: Right. I mean, you come up with the same thing,\r\nDialogue: 0,1:11:12.32,1:11:13.92,EN,,0,0,0,,except for you really got a different--\r\nDialogue: 0,1:11:14.05,1:11:16.63,EN,,0,0,0,,PROFESSOR: Right. And the difference would be, in the old one--\r\nDialogue: 0,1:11:17.02,1:11:18.35,EN,,0,0,0,,Let me be a little bit clearer here.\r\nDialogue: 0,1:11:19.13,1:11:23.44,EN,,0,0,0,,Let's call this A, like here.\r\nDialogue: 0,1:11:24.13,1:11:27.76,EN,,0,0,0,,And pretend here, just for contrast, I wrote,\r\nDialogue: 0,1:11:27.79,1:11:37.56,EN,,0,0,0,,define D to be the product of 5 and 5.\r\nDialogue: 0,1:11:40.22,1:11:41.57,EN,,0,0,0,,And the difference between those,\r\nDialogue: 0,1:11:41.96,1:11:44.24,EN,,0,0,0,,let's think about interactions with the Lisp interpreter.\r\nDialogue: 0,1:11:45.74,1:11:49.13,EN,,0,0,0,,I could type in A and Lisp would return 25.\r\nDialogue: 0,1:11:52.83,1:11:57.81,EN,,0,0,0,,I could type in D, if I just typed in D,\r\nDialogue: 0,1:11:58.49,1:12:05.55,EN,,0,0,0,,Lisp would return compound procedure D,\r\nDialogue: 0,1:12:07.12,1:12:09.13,EN,,0,0,0,,because that's what it is. It's a procedure.\r\nDialogue: 0,1:12:09.69,1:12:12.59,EN,,0,0,0,,I could run D. I could say, what's the value of running D?\r\nDialogue: 0,1:12:12.59,1:12:15.23,EN,,0,0,0,,Here is a combination with no operands.\r\nDialogue: 0,1:12:16.45,1:12:19.07,EN,,0,0,0,,I see there are no operands. I didn't put any after D.\r\nDialogue: 0,1:12:19.39,1:12:21.34,EN,,0,0,0,,And it would say, oh, that's 25.\r\nDialogue: 0,1:12:23.01,1:12:29.52,EN,,0,0,0,,Or I could say, just for completeness, if I typed in, what's the value of running A?\r\nDialogue: 0,1:12:29.54,1:12:30.57,EN,,0,0,0,,I get an error.\r\nDialogue: 0,1:12:31.79,1:12:35.29,EN,,0,0,0,,The error would be the same one as over there.\r\nDialogue: 0,1:12:35.33,1:12:40.51,EN,,0,0,0,,It'd be the error would say, sorry, 25, which is the value of A,\r\nDialogue: 0,1:12:40.56,1:12:43.24,EN,,0,0,0,,is not an operator that I can apply to something.\r\nDialogue: 0,0:00:00.01,0:00:03.77,Declare,,0,0,0,,{\\fad(200,200)}哈尔滨工业大学 IBM技术中心\r\nDialogue: 0,0:00:00.01,0:00:03.77,Declare,,0,0,0,,{\\fad(200,200)\\an2}倾情制作\r\nDialogue: 0,0:00:04.08,0:00:11.36,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\r\nDialogue: 0,0:00:04.08,0:00:11.05,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}字幕&时间轴\\N邓雄飞\\N(Dysprosium)\r\nDialogue: 0,0:00:04.08,0:00:11.05,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}后期&特效\\N蔡钟毓\\N(JohnTitor)\r\nDialogue: 0,0:00:04.08,0:00:11.06,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N匿名\r\nDialogue: 0,0:00:04.08,0:00:11.06,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\r\nDialogue: 0,0:00:14.71,0:00:17.89,Default,,0,0,0,,欢迎大家来一起学习这门计算机科学的基础课程\r\nDialogue: 0,0:00:28.40,0:00:29.85,Default,,0,0,0,,事实上 以这样的方式来表述并不恰当\r\nDialogue: 0,0:00:29.85,0:00:32.34,Default,,0,0,0,,于此来说 计算机科学是个糟糕的名字\r\nDialogue: 0,0:00:32.83,0:00:34.30,Default,,0,0,0,,首先 它不算是一门科学\r\nDialogue: 0,0:00:35.92,0:00:39.47,Default,,0,0,0,,它更应该被称为工程或者是艺术\r\nDialogue: 0,0:00:40.09,0:00:42.91,Default,,0,0,0,,但我们实际上会发现 这个所谓的计算机科学\r\nDialogue: 0,0:00:42.93,0:00:44.97,Default,,0,0,0,,却与魔法一样的有众多神奇之处\r\nDialogue: 0,0:00:45.01,0:00:46.35,Default,,0,0,0,,这些将会在课程中一一体现\r\nDialogue: 0,0:00:47.28,0:00:48.22,Default,,0,0,0,,所以 不能称其为一门科学\r\nDialogue: 0,0:00:49.09,0:00:52.30,Default,,0,0,0,,这门学科和“计算机”也并非紧密相关\r\nDialogue: 0,0:00:53.39,0:00:55.47,Default,,0,0,0,,类似的 就像我们说\r\nDialogue: 0,0:00:55.47,0:01:00.05,Default,,0,0,0,,物理学中并不仅仅有关粒子加速器\r\nDialogue: 0,0:01:00.80,0:01:05.58,Default,,0,0,0,,生物学中并不全然是显微镜和培养皿一样\r\nDialogue: 0,0:01:06.46,0:01:10.25,Default,,0,0,0,,同理\r\nDialogue: 0,0:01:10.31,0:01:14.88,Default,,0,0,0,,几何学中也并不全是介绍如何使用测量仪器\r\nDialogue: 0,0:01:16.48,0:01:19.01,Default,,0,0,0,,事实上 计算机科学和几何学\r\nDialogue: 0,0:01:19.33,0:01:21.45,Default,,0,0,0,,有很多共性\r\nDialogue: 0,0:01:21.45,0:01:22.66,Default,,0,0,0,,首先 几何学\r\nDialogue: 0,0:01:23.02,0:01:24.98,Default,,0,0,0,,只是另一个有个糟糕名字的学科\r\nDialogue: 0,0:01:25.58,0:01:27.85,Default,,0,0,0,,这个名字来自于Gaia 意为土地\r\nDialogue: 0,0:01:27.90,0:01:29.09,Default,,0,0,0,,以及metron 意为测量\r\nDialogue: 0,0:01:29.82,0:01:33.39,Default,,0,0,0,,几何学最初意为测地或者勘探\r\nDialogue: 0,0:01:34.37,0:01:36.89,Default,,0,0,0,,这是因为数千年前的埃及祭司\r\nDialogue: 0,0:01:37.69,0:01:41.69,Default,,0,0,0,,为了计算如何去修复年年被尼罗河的洪水\r\nDialogue: 0,0:01:42.59,0:01:46.33,Default,,0,0,0,,所毁坏的牧田边界\r\nDialogue: 0,0:01:46.35,0:01:48.69,Default,,0,0,0,,而建立了几何学基础\r\nDialogue: 0,0:01:49.47,0:01:50.65,Default,,0,0,0,,而对出于这个目的的埃及人来说\r\nDialogue: 0,0:01:50.65,0:01:53.93,Default,,0,0,0,,几何学的确是掌握对测量仪器的使用\r\nDialogue: 0,0:01:55.63,0:01:58.55,Default,,0,0,0,,现在 我们以为计算机科学就是介绍计算机的使用\r\nDialogue: 0,0:01:58.57,0:02:02.49,Default,,0,0,0,,就正如埃及人认为\r\nDialogue: 0,0:02:02.51,0:02:04.10,Default,,0,0,0,,几何学是介绍如何使用测量仪器的\r\nDialogue: 0,0:02:04.59,0:02:07.37,Default,,0,0,0,,换句话说 任何一门学科起步的时候\r\nDialogue: 0,0:02:07.39,0:02:09.86,Default,,0,0,0,,你都对它了解不深\r\nDialogue: 0,0:02:11.10,0:02:16.64,Default,,0,0,0,,这很容易使你混淆所做的事与所用之物\r\nDialogue: 0,0:02:17.65,0:02:20.30,Default,,0,0,0,,确实 就绝对规模来说\r\nDialogue: 0,0:02:20.30,0:02:24.82,Default,,0,0,0,,我们对计算机科学的实质的了解\r\nDialogue: 0,0:02:24.83,0:02:27.49,Default,,0,0,0,,比埃及人对几何学的了解还少\r\nDialogue: 0,0:02:30.25,0:02:32.64,Default,,0,0,0,,那么 我所谓的计算机科学的本质是什么呢\r\nDialogue: 0,0:02:32.65,0:02:34.41,Default,,0,0,0,,我所谓的几何学本质又是什么呢\r\nDialogue: 0,0:02:34.41,0:02:36.45,Default,,0,0,0,,看 可以确认的是 古埃及人确实使用测量仪器\r\nDialogue: 0,0:02:36.46,0:02:37.67,Default,,0,0,0,,并且已经消失多年\r\nDialogue: 0,0:02:37.69,0:02:41.55,Default,,0,0,0,,但当我们在几千年后回过头来重新审视这段历史\r\nDialogue: 0,0:02:41.57,0:02:41.85,Default,,0,0,0,,我们会说\r\nDialogue: 0,0:02:41.87,0:02:43.64,Default,,0,0,0,,天啊 看他们在做什么\r\nDialogue: 0,0:02:43.71,0:02:45.48,Default,,0,0,0,,他们的工作是多么的重要\r\nDialogue: 0,0:02:45.62,0:02:50.45,Default,,0,0,0,,已经开始对时间和空间进行形式化表述\r\nDialogue: 0,0:02:51.58,0:02:57.53,Default,,0,0,0,,并归纳出一套讨论数学真理的形式化方法\r\nDialogue: 0,0:02:58.01,0:02:59.61,Default,,0,0,0,,这直接导致了公理化方法\r\nDialogue: 0,0:02:59.61,0:03:02.53,Default,,0,0,0,,以及各种现代数学的产生\r\nDialogue: 0,0:03:04.16,0:03:06.90,Default,,0,0,0,,同时也指明了一种精确讨论\r\nDialogue: 0,0:03:07.25,0:03:10.19,Default,,0,0,0,,所谓的描述真理的陈述性知识的方法\r\nDialogue: 0,0:03:12.45,0:03:16.25,Default,,0,0,0,,与此相似的 我认为未来人们会回过头来审视并说\r\nDialogue: 0,0:03:16.27,0:03:19.36,Default,,0,0,0,,啊 这些20世纪的原始人\r\nDialogue: 0,0:03:19.36,0:03:21.20,Default,,0,0,0,,不务正业地玩弄着叫计算机的小玩意\r\nDialogue: 0,0:03:21.77,0:03:26.25,Default,,0,0,0,,但它们真正在做的是开始学习\r\nDialogue: 0,0:03:26.25,0:03:32.55,Default,,0,0,0,,如何去对计算过程进行形式化表述\r\nDialogue: 0,0:03:32.64,0:03:34.13,Default,,0,0,0,,如何去解决问题\r\nDialogue: 0,0:03:39.02,0:03:51.25,Default,,0,0,0,,并结合两者发展一套对问题处理过程精确表述的方法\r\nDialogue: 0,0:03:51.76,0:03:56.03,Default,,0,0,0,,这与讨论真理的几何学形成了对照\r\nDialogue: 0,0:03:56.53,0:03:58.57,Default,,0,0,0,,让我给你们举个例子吧\r\nDialogue: 0,0:04:02.30,0:04:02.69,Default,,0,0,0,,来瞧瞧\r\nDialogue: 0,0:04:02.70,0:04:09.82,Default,,0,0,0,,数学中是这样来定义平方根的:\r\nDialogue: 0,0:04:10.09,0:04:14.35,Default,,0,0,0,,定义X的平方根Y是这样一个数\r\nDialogue: 0,0:04:15.98,0:04:20.38,Default,,0,0,0,,Y的平方等于X 且Y大于等于0\r\nDialogue: 0,0:04:20.43,0:04:22.50,Default,,0,0,0,,这是一个很好的定义\r\nDialogue: 0,0:04:22.88,0:04:25.25,Default,,0,0,0,,但它只告诉了你平方根是什么\r\nDialogue: 0,0:04:25.63,0:04:30.29,Default,,0,0,0,,却没有告诉你如何去求取一个平方根\r\nDialogue: 0,0:04:31.42,0:04:35.90,Default,,0,0,0,,那么我们将其与一条指令性知识做比较\r\nDialogue: 0,0:04:37.13,0:04:39.92,Default,,0,0,0,,你如何去求取一个平方根\r\nDialogue: 0,0:04:39.95,0:04:45.74,Default,,0,0,0,,事实上 这来自于埃及 不太久远的埃及\r\nDialogue: 0,0:04:45.76,0:04:48.88,Default,,0,0,0,,亚历山大的Heron提出的一个算法\r\nDialogue: 0,0:04:49.90,0:04:52.77,Default,,0,0,0,,称作连续取均值求平方根法\r\nDialogue: 0,0:04:52.89,0:04:55.13,Default,,0,0,0,,这个算法是说\r\nDialogue: 0,0:04:55.15,0:04:58.06,Default,,0,0,0,,为了算出平方根\r\nDialogue: 0,0:05:03.34,0:05:08.33,Default,,0,0,0,,首先你应该给出一个猜测值guess 并不断改进\r\nDialogue: 0,0:05:10.19,0:05:11.44,Default,,0,0,0,,改进的方法是通过\r\nDialogue: 0,0:05:11.45,0:05:13.95,Default,,0,0,0,,不断求猜测值guess与X/guess的平均值\r\nDialogue: 0,0:05:14.41,0:05:15.60,Default,,0,0,0,,我们稍后将会讨论\r\nDialogue: 0,0:05:15.61,0:05:17.12,Default,,0,0,0,,为什么这是合理的\r\nDialogue: 0,0:05:17.14,0:05:19.37,Default,,0,0,0,,通过不断改进 直到它足够精确\r\nDialogue: 0,0:05:19.73,0:05:20.85,Default,,0,0,0,,这就是实现方法\r\nDialogue: 0,0:05:20.99,0:05:24.65,Default,,0,0,0,,这也是如何完成一项工作与\r\nDialogue: 0,0:05:24.72,0:05:27.33,Default,,0,0,0,,其对应的陈述性知识的对照\r\nDialogue: 0,0:05:28.05,0:05:29.76,Default,,0,0,0,,这就是一个过程\r\nDialogue: 0,0:05:34.40,0:05:38.25,Default,,0,0,0,,那么 通常来说什么是过程呢？\r\nDialogue: 0,0:05:39.01,0:05:40.14,Default,,0,0,0,,这定义起来非常困难\r\nDialogue: 0,0:05:40.16,0:05:43.72,Default,,0,0,0,,你可以将它象征性地看成一个活在计算机内\r\nDialogue: 0,0:05:44.77,0:05:47.33,Default,,0,0,0,,并且可以完成一些操作的精灵\r\nDialogue: 0,0:05:48.01,0:05:54.11,Default,,0,0,0,,一些被称为程序的规则模式\r\nDialogue: 0,0:05:54.13,0:05:57.98,Default,,0,0,0,,指导着这类过程的进行\r\nDialogue: 0,0:06:01.98,0:06:04.73,Default,,0,0,0,,程序可以被认为是符咒\r\nDialogue: 0,0:06:05.23,0:06:09.40,Default,,0,0,0,,使用程序来控制这些精灵完成一些操作就叫做过程\r\nDialogue: 0,0:06:10.75,0:06:12.75,Default,,0,0,0,,你们知道人人都需要一门魔法语言\r\nDialogue: 0,0:06:12.77,0:06:14.55,Default,,0,0,0,,那些魔术师 真正的魔术师 用远古的阿卡狄亚语\r\nDialogue: 0,0:06:14.57,0:06:18.59,Default,,0,0,0,,或者苏美尔语 或者巴比伦语 或者其它的\r\nDialogue: 0,0:06:18.62,0:06:20.09,Default,,0,0,0,,而我们将用一门叫Lisp的魔法语言\r\nDialogue: 0,0:06:20.13,0:06:22.71,Default,,0,0,0,,来召唤出我们的精灵\r\nDialogue: 0,0:06:24.37,0:06:28.01,Default,,0,0,0,,这门语言是被设计用来\r\nDialogue: 0,0:06:28.57,0:06:31.84,Default,,0,0,0,,编写如咒语般的程序 来指导过程的进行\r\nDialogue: 0,0:06:31.87,0:06:33.91,Default,,0,0,0,,学习Lisp非常容易\r\nDialogue: 0,0:06:33.97,0:06:35.98,Default,,0,0,0,,事实上 我会在几分钟内教会你\r\nDialogue: 0,0:06:36.00,0:06:37.16,Default,,0,0,0,,整个Lisp\r\nDialogue: 0,0:06:37.37,0:06:38.96,Default,,0,0,0,,及其所有的规则\r\nDialogue: 0,0:06:40.77,0:06:43.65,Default,,0,0,0,,你不必感到很惊讶\r\nDialogue: 0,0:06:43.69,0:06:45.87,Default,,0,0,0,,这就像你在学习象棋时\r\nDialogue: 0,0:06:45.90,0:06:47.01,Default,,0,0,0,,认为象棋的规则十分简单一样\r\nDialogue: 0,0:06:47.04,0:06:48.13,Default,,0,0,0,,事实也如此 几分钟内\r\nDialogue: 0,0:06:48.17,0:06:49.70,Default,,0,0,0,,你可以与任何人谈论象棋的规则\r\nDialogue: 0,0:06:50.81,0:06:52.24,Default,,0,0,0,,但是 这全然不等同于说\r\nDialogue: 0,0:06:52.25,0:06:55.37,Default,,0,0,0,,你所知道这些规则所蕴含的东西\r\nDialogue: 0,0:06:55.42,0:06:58.05,Default,,0,0,0,,以及如何利用这些规则去成为象棋大师\r\nDialogue: 0,0:06:58.49,0:06:59.82,Default,,0,0,0,,Lisp也是如此\r\nDialogue: 0,0:07:00.41,0:07:02.18,Default,,0,0,0,,我将在几分钟内道清规则\r\nDialogue: 0,0:07:02.36,0:07:03.55,Default,,0,0,0,,这说起来非常容易\r\nDialogue: 0,0:07:03.62,0:07:07.09,Default,,0,0,0,,但真正困难的是如何运用这些规则\r\nDialogue: 0,0:07:07.32,0:07:10.46,Default,,0,0,0,,以及你如何利用这些规则成为编程大师\r\nDialogue: 0,0:07:12.06,0:07:15.29,Default,,0,0,0,,这些规则的应用将占据我们\r\nDialogue: 0,0:07:15.31,0:07:18.56,Default,,0,0,0,,余下的课程 甚至更多\r\nDialogue: 0,0:07:21.45,0:07:23.11,Default,,0,0,0,,所以 在计算机科学中\r\nDialogue: 0,0:07:24.49,0:07:26.19,Default,,0,0,0,,我们的任务则是\r\nDialogue: 0,0:07:26.21,0:07:30.58,Default,,0,0,0,,形式化这种如有关“怎么做”的指令性知识\r\nDialogue: 0,0:07:30.62,0:07:32.10,Default,,0,0,0,,并将之付诸实际\r\nDialogue: 0,0:07:33.37,0:07:35.39,Default,,0,0,0,,这也便是计算机科学的真正的议题\r\nDialogue: 0,0:07:35.41,0:07:38.36,Default,,0,0,0,,当然 并不是告诉人们如何去求平方根\r\nDialogue: 0,0:07:39.09,0:07:40.06,Default,,0,0,0,,因为如果那是计算机科学的全部的的话\r\nDialogue: 0,0:07:40.09,0:07:41.34,Default,,0,0,0,,就不会有什么大问题了\r\nDialogue: 0,0:07:41.57,0:07:44.05,Default,,0,0,0,,真正的问题来自于当我们尝试\r\nDialogue: 0,0:07:44.08,0:07:46.16,Default,,0,0,0,,构建非常非常大的系统时\r\nDialogue: 0,0:07:46.61,0:07:49.53,Default,,0,0,0,,程序可能会长达数千页\r\nDialogue: 0,0:07:49.58,0:07:53.98,Default,,0,0,0,,长得没有人能马上将其装入脑中\r\nDialogue: 0,0:07:54.73,0:07:58.81,Default,,0,0,0,,而使这些得以实现则是因为\r\nDialogue: 0,0:07:58.86,0:08:18.97,Default,,0,0,0,,我们有在大系统中控制复杂度的技术\r\nDialogue: 0,0:08:20.30,0:08:22.69,Default,,0,0,0,,这些控制复杂度的技术\r\nDialogue: 0,0:08:22.72,0:08:24.17,Default,,0,0,0,,正是我们课程所讨论的\r\nDialogue: 0,0:08:24.65,0:08:25.47,Default,,0,0,0,,从某种意义上来说\r\nDialogue: 0,0:08:25.50,0:08:27.47,Default,,0,0,0,,这也正是计算机科学的关键所在\r\nDialogue: 0,0:08:29.63,0:08:31.89,Default,,0,0,0,,这样说听起来或许很奇怪\r\nDialogue: 0,0:08:31.92,0:08:35.61,Default,,0,0,0,,毕竟 除了计算机科学家外\r\nDialogue: 0,0:08:35.65,0:08:37.82,Default,,0,0,0,,仍然有很多人在做复杂度控制相关的工作\r\nDialogue: 0,0:08:37.84,0:08:41.02,Default,,0,0,0,,一个航班就是一个非常复杂的系统\r\nDialogue: 0,0:08:41.82,0:08:43.79,Default,,0,0,0,,设计它的航空工程师\r\nDialogue: 0,0:08:44.05,0:08:46.13,Default,,0,0,0,,便在处理这个巨大的复杂度\r\nDialogue: 0,0:08:47.09,0:08:50.19,Default,,0,0,0,,但这种复杂度又与\r\nDialogue: 0,0:08:50.75,0:08:52.60,Default,,0,0,0,,计算机科学中的（复杂度）有别\r\nDialogue: 0,0:08:55.18,0:08:57.73,Default,,0,0,0,,从某种意义上来说\r\nDialogue: 0,0:08:57.79,0:09:00.09,Default,,0,0,0,,因为计算机科学不是“现实”的\r\nDialogue: 0,0:09:02.69,0:09:06.62,Default,,0,0,0,,例如 当一名工程师设计物理系统时\r\nDialogue: 0,0:09:07.14,0:09:08.49,Default,,0,0,0,,这些都是由实在的物理部件构成\r\nDialogue: 0,0:09:09.40,0:09:11.18,Default,,0,0,0,,负责的该工作的工程师\r\nDialogue: 0,0:09:11.85,0:09:16.65,Default,,0,0,0,,就得对付系统中的公差、近似值以及噪声\r\nDialogue: 0,0:09:16.67,0:09:19.02,Default,,0,0,0,,譬如说 作为一名电气工程师\r\nDialogue: 0,0:09:19.09,0:09:21.71,Default,,0,0,0,,可以很容易的做一个单极放大器\r\nDialogue: 0,0:09:21.73,0:09:23.03,Default,,0,0,0,,或者是一个双极放大器\r\nDialogue: 0,0:09:23.41,0:09:25.39,Default,,0,0,0,,也可想象将其大量串联\r\nDialogue: 0,0:09:25.45,0:09:26.91,Default,,0,0,0,,来建造一个百万极的放大器\r\nDialogue: 0,0:09:26.99,0:09:28.75,Default,,0,0,0,,但这样做是不可行的\r\nDialogue: 0,0:09:28.98,0:09:32.15,Default,,0,0,0,,因为在远没到百万数量级的时候\r\nDialogue: 0,0:09:32.16,0:09:34.56,Default,,0,0,0,,这种组合方法打从头产生的热噪声\r\nDialogue: 0,0:09:34.57,0:09:36.80,Default,,0,0,0,,会慢慢增强 并使得我们的幸苦付之一炬\r\nDialogue: 0,0:09:39.10,0:09:43.12,Default,,0,0,0,,计算机科学处理的是理想化组件\r\nDialogue: 0,0:09:44.12,0:09:47.63,Default,,0,0,0,,我们对将要结合在一起的\r\nDialogue: 0,0:09:47.65,0:09:49.56,Default,,0,0,0,,程序和数据了如指掌\r\nDialogue: 0,0:09:51.90,0:09:53.20,Default,,0,0,0,,我们不需要去关心公差\r\nDialogue: 0,0:09:53.21,0:09:56.99,Default,,0,0,0,,也就是说 在构建大系统时\r\nDialogue: 0,0:09:58.13,0:10:00.03,Default,,0,0,0,,在我理想和现实之间\r\nDialogue: 0,0:10:00.35,0:10:04.18,Default,,0,0,0,,并不没有太大的不同\r\nDialogue: 0,0:10:05.53,0:10:07.60,Default,,0,0,0,,因为这些部分都是抽象单元\r\nDialogue: 0,0:10:07.63,0:10:10.32,Default,,0,0,0,,可以随心所欲的组合\r\nDialogue: 0,0:10:10.33,0:10:12.39,Default,,0,0,0,,可以据目前所知而自由构建\r\nDialogue: 0,0:10:13.45,0:10:15.50,Default,,0,0,0,,就是与其它的工程不同之处\r\nDialogue: 0,0:10:15.66,0:10:17.42,Default,,0,0,0,,（在其它的工程中）对你所构建系统的约束\r\nDialogue: 0,0:10:17.44,0:10:18.90,Default,,0,0,0,,来自于物理系统以及\r\nDialogue: 0,0:10:18.94,0:10:21.02,Default,,0,0,0,,物理定律 噪声 近似值等\r\nDialogue: 0,0:10:21.21,0:10:25.60,Default,,0,0,0,,而建立大型软件系统时所施加的约束\r\nDialogue: 0,0:10:25.64,0:10:27.58,Default,,0,0,0,,就是对我们大脑的限制\r\nDialogue: 0,0:10:29.12,0:10:29.98,Default,,0,0,0,,从这个角度来看\r\nDialogue: 0,0:10:30.00,0:10:33.67,Default,,0,0,0,,计算机科学就像是工程中的一种抽象形式\r\nDialogue: 0,0:10:33.80,0:10:35.73,Default,,0,0,0,,在这种工程中 我们忽略\r\nDialogue: 0,0:10:35.76,0:10:38.02,Default,,0,0,0,,现实所施加的约束\r\nDialogue: 0,0:10:41.97,0:10:46.15,Default,,0,0,0,,那么 这其中有哪些技术呢\r\nDialogue: 0,0:10:46.28,0:10:48.39,Default,,0,0,0,,计算机科学中并没有特别的技术\r\nDialogue: 0,0:10:50.39,0:10:52.55,Default,,0,0,0,,第一个技术是在很多工程中都使用的\r\nDialogue: 0,0:10:53.36,0:10:58.91,Default,,0,0,0,,被称为“黑盒抽象”的方法\r\nDialogue: 0,0:11:07.71,0:11:12.58,Default,,0,0,0,,即将一些东西组合并封装起来\r\nDialogue: 0,0:11:14.37,0:11:20.09,Default,,0,0,0,,以之前我们提到的求取平方根的方法为例\r\nDialogue: 0,0:11:22.64,0:11:28.53,Default,,0,0,0,,我将这些操作视为一个“盒子”\r\nDialogue: 0,0:11:29.89,0:11:37.52,Default,,0,0,0,,也就是说 为了找到X的平方根\r\nDialogue: 0,0:11:38.86,0:11:41.27,Default,,0,0,0,,或许会有一系列的复杂规则\r\nDialogue: 0,0:11:42.64,0:11:46.69,Default,,0,0,0,,我们将规则封装 输入数据即可获得结果\r\nDialogue: 0,0:11:46.81,0:11:50.06,Default,,0,0,0,,比如说 输入36 然后说36的平方根是多少呢\r\nDialogue: 0,0:11:50.25,0:11:51.46,Default,,0,0,0,,则给出结果 6\r\nDialogue: 0,0:11:53.89,0:11:56.22,Default,,0,0,0,,重点是\r\nDialogue: 0,0:11:56.24,0:12:00.03,Default,,0,0,0,,通过这样的设计\r\nDialogue: 0,0:12:00.06,0:12:04.08,Default,,0,0,0,,可以方便他人的使用\r\nDialogue: 0,0:12:05.10,0:12:09.37,Default,,0,0,0,,例如Goerge想计算A的平方根加上B的平方根\r\nDialogue: 0,0:12:11.34,0:12:14.38,Default,,0,0,0,,他无需了解“盒子”内部的构成\r\nDialogue: 0,0:12:14.43,0:12:15.74,Default,,0,0,0,,而直接可以以模块的形式使用它\r\nDialogue: 0,0:12:15.77,0:12:17.31,Default,,0,0,0,,也可以利用它去构建新的“盒子”\r\nDialogue: 0,0:12:18.45,0:12:24.20,Default,,0,0,0,,例如构建一个 A和B以及一个平方根和或者另一个平方根盒子\r\nDialogue: 0,0:12:24.53,0:12:33.87,Default,,0,0,0,,然后将这些结果加在一起并输出答案\r\nDialogue: 0,0:12:33.96,0:12:38.15,Default,,0,0,0,,如你所见 就我想实现的功能的层面来看\r\nDialogue: 0,0:12:38.92,0:12:40.42,Default,,0,0,0,,对于George来说\r\nDialogue: 0,0:12:40.51,0:12:43.10,Default,,0,0,0,,盒子内部是什么样并不重要\r\nDialogue: 0,0:12:44.19,0:12:47.25,Default,,0,0,0,,例如 以下这些说法都没什么问题\r\nDialogue: 0,0:12:47.27,0:12:50.43,Default,,0,0,0,,我说求X的平方根\r\nDialogue: 0,0:12:50.61,0:12:52.27,Default,,0,0,0,,也可以说计算Y的平方根\r\nDialogue: 0,0:12:52.72,0:12:55.62,Default,,0,0,0,,或者其它任何数的平方根\r\nDialogue: 0,0:12:56.70,0:13:02.35,Default,,0,0,0,,黑盒抽象的基本规则是\r\nDialogue: 0,0:13:03.53,0:13:06.44,Default,,0,0,0,,将处理过程放入盒子里以隐藏细节\r\nDialogue: 0,0:13:07.60,0:13:10.99,Default,,0,0,0,,这样做的原因则是你可以脱身去构建更大的盒子\r\nDialogue: 0,0:13:12.05,0:13:14.57,Default,,0,0,0,,现在 除了隐藏细节外\r\nDialogue: 0,0:13:14.59,0:13:18.41,Default,,0,0,0,,使用黑盒抽象还有另外一个原因\r\nDialogue: 0,0:13:18.48,0:13:25.02,Default,,0,0,0,,有的时候 你想要用你的方法去完成一件事\r\nDialogue: 0,0:13:25.04,0:13:26.88,Default,,0,0,0,,你的方法\r\nDialogue: 0,0:13:28.44,0:13:30.79,Default,,0,0,0,,就是一个通法的具体实例\r\nDialogue: 0,0:13:31.16,0:13:34.57,Default,,0,0,0,,同时 你也希望你的表述方式能够具有普遍性\r\nDialogue: 0,0:13:35.57,0:13:37.93,Default,,0,0,0,,我们接着用实例来说明\r\nDialogue: 0,0:13:37.97,0:13:38.86,Default,,0,0,0,,继续刚才关于平方根的讨论\r\nDialogue: 0,0:13:38.89,0:13:42.16,Default,,0,0,0,,让我们回过头再来看看\r\nDialogue: 0,0:13:42.19,0:13:43.75,Default,,0,0,0,,求平方根的算法\r\nDialogue: 0,0:13:44.16,0:13:45.62,Default,,0,0,0,,想一想之前是怎么说的\r\nDialogue: 0,0:13:45.79,0:13:49.82,Default,,0,0,0,,为了求解 首先要作出猜测\r\nDialogue: 0,0:13:50.62,0:13:54.84,Default,,0,0,0,,然后基于这个猜测 做出持续不断的改进\r\nDialogue: 0,0:13:55.66,0:14:00.14,Default,,0,0,0,,因此就存在一个找到某个到结果的通用方法\r\nDialogue: 0,0:14:01.15,0:14:04.00,Default,,0,0,0,,就是持续不断地改进结果\r\nDialogue: 0,0:14:04.16,0:14:10.25,Default,,0,0,0,,求取不动点的方法有很多\r\nDialogue: 0,0:14:10.97,0:14:13.23,Default,,0,0,0,,这种方法只是其中的一个特例\r\nDialogue: 0,0:14:14.57,0:14:16.59,Default,,0,0,0,,每个函数都有一个不动点\r\nDialogue: 0,0:14:17.13,0:14:26.03,Default,,0,0,0,,函数的不动点是一个值\r\nDialogue: 0,0:14:26.13,0:14:31.79,Default,,0,0,0,,F的不动点Y满足F(Y)=Y\r\nDialogue: 0,0:14:32.97,0:14:40.89,Default,,0,0,0,,首先要做是做出一个猜测\r\nDialogue: 0,0:14:42.00,0:14:45.85,Default,,0,0,0,,在迭代函数F时不会改变的东西则是我们所求的结果\r\nDialogue: 0,0:14:45.96,0:14:49.45,Default,,0,0,0,,我会不断迭代函数F直到结果不会有很大改变\r\nDialogue: 0,0:14:50.05,0:14:51.93,Default,,0,0,0,,这就是一个通法\r\nDialogue: 0,0:14:52.24,0:14:56.17,Default,,0,0,0,,因此 为了计算X的平方根\r\nDialogue: 0,0:14:56.24,0:15:03.45,Default,,0,0,0,,我可以试着找到Y与X/Y的平均值函数的不动点\r\nDialogue: 0,0:15:03.55,0:15:07.52,Default,,0,0,0,,因为如果我真有一个等于X平方根的Y\r\nDialogue: 0,0:15:08.01,0:15:11.80,Default,,0,0,0,,那么Y和X/Y应为同一值\r\nDialogue: 0,0:15:12.00,0:15:13.90,Default,,0,0,0,,它们俩都是X的平方根\r\nDialogue: 0,0:15:14.86,0:15:18.85,Default,,0,0,0,,因为X除根号X得根号X\r\nDialogue: 0,0:15:19.09,0:15:21.84,Default,,0,0,0,,如果平均值Y等于X的平方根\r\nDialogue: 0,0:15:22.25,0:15:25.21,Default,,0,0,0,,那么这个平均值就不会改变\r\nDialogue: 0,0:15:25.98,0:15:28.93,Default,,0,0,0,,因此X的平方根即是某一特定函数的不动点\r\nDialogue: 0,0:15:30.09,0:15:33.85,Default,,0,0,0,,现在 我将要描述\r\nDialogue: 0,0:15:33.98,0:15:36.42,Default,,0,0,0,,寻找不动点的通法\r\nDialogue: 0,0:15:36.57,0:15:40.13,Default,,0,0,0,,我所希望做的就是\r\nDialogue: 0,0:15:41.02,0:15:46.45,Default,,0,0,0,,用我自己的语言定义一个可以获得不动点的“盒子”\r\nDialogue: 0,0:15:49.58,0:15:52.19,Default,,0,0,0,,正如我可以定义一个输出平方根的盒子一样\r\nDialogue: 0,0:15:52.21,0:15:55.18,Default,,0,0,0,,我想要用自己的语言来表述\r\nDialogue: 0,0:15:56.08,0:16:01.37,Default,,0,0,0,,因此 对于这种“怎么做”的指令性知识\r\nDialogue: 0,0:16:01.42,0:16:03.21,Default,,0,0,0,,我不仅是想表达具体应该如何求平方根\r\nDialogue: 0,0:16:03.58,0:16:05.60,Default,,0,0,0,,我也希望能够表述更加通用问题\r\nDialogue: 0,0:16:05.66,0:16:08.27,Default,,0,0,0,,例如 怎么求取不动点\r\nDialogue: 0,0:16:09.82,0:16:12.25,Default,,0,0,0,,让我们再回过头来看看之前的幻灯片\r\nDialogue: 0,0:16:15.02,0:16:23.28,Default,,0,0,0,,不但如何去求取一个不动点\r\nDialogue: 0,0:16:23.33,0:16:25.32,Default,,0,0,0,,是一种指令性知识\r\nDialogue: 0,0:16:26.25,0:16:27.39,Default,,0,0,0,,在这下面 这里\r\nDialogue: 0,0:16:27.42,0:16:30.32,Default,,0,0,0,,这儿还有另一种指令性知识 说的是\r\nDialogue: 0,0:16:30.41,0:16:35.85,Default,,0,0,0,,计算平方根的一种方法就是应用找不动点的方法\r\nDialogue: 0,0:16:36.17,0:16:38.89,Default,,0,0,0,,如果 也想要表述这种指令性知识\r\nDialogue: 0,0:16:39.74,0:16:40.70,Default,,0,0,0,,那结果会是什么样呢？\r\nDialogue: 0,0:16:40.73,0:16:44.90,Default,,0,0,0,,这个不动点盒子可能会是这样\r\nDialogue: 0,0:16:45.76,0:16:58.21,Default,,0,0,0,,如果我输入一个函数 该函数从Y映射到Y和X/Y的平均值\r\nDialogue: 0,0:16:59.77,0:17:06.23,Default,,0,0,0,,然后我们将会得到求不动点的盒子就是求平方根的一个方法\r\nDialogue: 0,0:17:08.91,0:17:10.24,Default,,0,0,0,,因此在这些我们构建的盒子中\r\nDialogue: 0,0:17:10.27,0:17:15.07,Default,,0,0,0,,输入和输出都不局限于数字\r\nDialogue: 0,0:17:16.40,0:17:18.54,Default,,0,0,0,,我们将要构建能够\r\nDialogue: 0,0:17:18.67,0:17:21.34,Default,,0,0,0,,找到平方根计算方法的盒子\r\nDialogue: 0,0:17:22.22,0:17:25.85,Default,,0,0,0,,我输入的是一个函数\r\nDialogue: 0,0:17:26.49,0:17:29.29,Default,,0,0,0,,比如Y映射到Y和X/Y的平均值的函数\r\nDialogue: 0,0:17:29.71,0:17:31.49,Default,,0,0,0,,我们之所以采用这种方式是希望\r\nDialogue: 0,0:17:32.21,0:17:35.60,Default,,0,0,0,,输入是一个过程 输出也是一个过程\r\nDialogue: 0,0:17:35.63,0:17:38.61,Default,,0,0,0,,如我们所见 一个过程输出了另一个过程\r\nDialogue: 0,0:17:39.31,0:17:41.10,Default,,0,0,0,,之所以这样做是因为\r\nDialogue: 0,0:17:41.52,0:17:46.27,Default,,0,0,0,,我们将通过程序来讨论指令性知识\r\nDialogue: 0,0:17:48.00,0:17:49.93,Default,,0,0,0,,这种处理方式很强大\r\nDialogue: 0,0:17:49.93,0:17:52.13,Default,,0,0,0,,我们将可以基于此来讨论其它类型的知识\r\nDialogue: 0,0:17:53.42,0:17:56.52,Default,,0,0,0,,实际上 我们讨论的是一种生成过程的过程\r\nDialogue: 0,0:17:57.10,0:18:00.34,Default,,0,0,0,,一种生成通法的通法\r\nDialogue: 0,0:18:03.57,0:18:08.24,Default,,0,0,0,,那么 我们将主要讨论三个主题的内容\r\nDialogue: 0,0:18:08.25,0:18:09.69,Default,,0,0,0,,而首个主题则是\r\nDialogue: 0,0:18:09.74,0:18:10.94,Default,,0,0,0,,黑盒抽象\r\nDialogue: 0,0:18:10.97,0:18:13.31,Default,,0,0,0,,让我们稍稍深入一点\r\nDialogue: 0,0:18:15.12,0:18:24.04,Default,,0,0,0,,我们将讨论\r\nDialogue: 0,0:18:24.08,0:18:26.72,Default,,0,0,0,,Lisp是如何通过基本对象建立起来的\r\nDialogue: 0,0:18:27.36,0:18:29.20,Default,,0,0,0,,以及Lisp的构成\r\nDialogue: 0,0:18:29.49,0:18:33.58,Default,,0,0,0,,接下来 将会涉及到一些基本过程和基础数据\r\nDialogue: 0,0:18:36.16,0:18:37.04,Default,,0,0,0,,然后我们将会看到\r\nDialogue: 0,0:18:37.05,0:18:38.77,Default,,0,0,0,,我们如何使用这些基本对象\r\nDialogue: 0,0:18:38.81,0:18:40.76,Default,,0,0,0,,并把它们组合起来构建更复杂的东西\r\nDialogue: 0,0:18:41.45,0:18:42.92,Default,,0,0,0,,及相应的组合方法\r\nDialogue: 0,0:18:43.20,0:18:46.30,Default,,0,0,0,,后续将讨论各种进行组合的方法以及\r\nDialogue: 0,0:18:46.45,0:18:50.48,Default,,0,0,0,,如何用基本过程来构建更复杂的过程\r\nDialogue: 0,0:18:50.96,0:18:54.43,Default,,0,0,0,,同时 我们也将看到如何将基本数据组合成复合数据\r\nDialogue: 0,0:18:56.21,0:18:59.34,Default,,0,0,0,,然后我们将会介绍如何对复合数据\r\nDialogue: 0,0:18:59.79,0:19:01.29,Default,,0,0,0,,如何将它们抽象出来\r\nDialogue: 0,0:19:02.91,0:19:04.97,Default,,0,0,0,,如何用黑盒对它们进行封装\r\nDialogue: 0,0:19:05.04,0:19:07.73,Default,,0,0,0,,使得你可以将它们作为组件用于更复杂的东西\r\nDialogue: 0,0:19:08.16,0:19:10.93,Default,,0,0,0,,我们会发现这些都是通过定义程序\r\nDialogue: 0,0:19:11.52,0:19:14.79,Default,,0,0,0,,以及一种处理复合数据的数据抽象技术完成的\r\nDialogue: 0,0:19:15.61,0:19:17.36,Default,,0,0,0,,最重要的是\r\nDialogue: 0,0:19:17.92,0:19:21.49,Default,,0,0,0,,我们可以从中了解到专家是如何工作的\r\nDialogue: 0,0:19:21.61,0:19:27.12,Default,,0,0,0,,对于找不动点的方法来讲\r\nDialogue: 0,0:19:27.15,0:19:28.64,Default,,0,0,0,,找平方根的方式是它的一个特例\r\nDialogue: 0,0:19:28.69,0:19:30.87,Default,,0,0,0,,你如何表述完成工作中所存在的通用模式呢？\r\nDialogue: 0,0:19:31.90,0:19:34.41,Default,,0,0,0,,我们将会使用\r\nDialogue: 0,0:19:34.59,0:19:35.63,Default,,0,0,0,,之前已经提到过的\r\nDialogue: 0,0:19:35.66,0:19:37.30,Default,,0,0,0,,某种叫做高阶过程的东西\r\nDialogue: 0,0:19:37.34,0:19:42.05,Default,,0,0,0,,也就是说 它的输入、输出和它本身都是过程\r\nDialogue: 0,0:19:42.96,0:19:44.86,Default,,0,0,0,,我们将会看到一些有趣的东西\r\nDialogue: 0,0:19:44.86,0:19:48.49,Default,,0,0,0,,随着学习的深入 将会越发抽象\r\nDialogue: 0,0:19:48.80,0:19:50.31,Default,,0,0,0,,那么将会发现\r\nDialogue: 0,0:19:50.43,0:19:53.61,Default,,0,0,0,,我们认为是数据和我们认为是过程之间的\r\nDialogue: 0,0:19:53.63,0:19:57.80,Default,,0,0,0,,分界线将变得模糊到难以置信的程度\r\nDialogue: 0,0:20:02.89,0:20:07.12,Default,,0,0,0,,这便是我们的第一个主题 黑盒抽象\r\nDialogue: 0,0:20:07.12,0:20:08.62,Default,,0,0,0,,让我们来看看第二个主题\r\nDialogue: 0,0:20:11.10,0:20:13.88,Default,,0,0,0,,这样说吧\r\nDialogue: 0,0:20:13.89,0:20:18.09,Default,,0,0,0,,假设我想表达某个想法\r\nDialogue: 0,0:20:19.42,0:20:22.51,Default,,0,0,0,,请注意 我们讨论的是想法\r\nDialogue: 0,0:20:22.91,0:20:25.53,Default,,0,0,0,,比如说\r\nDialogue: 0,0:20:26.41,0:20:35.12,Default,,0,0,0,,我想将某个元素与另两个元素之和相乘\r\nDialogue: 0,0:20:36.09,0:20:37.93,Default,,0,0,0,,举例来说\r\nDialogue: 0,0:20:38.11,0:20:41.52,Default,,0,0,0,,我用1和3（之和）乘2 得8\r\nDialogue: 0,0:20:42.03,0:20:45.11,Default,,0,0,0,,但我这里想讨论的是关于线性组合的基本想法\r\nDialogue: 0,0:20:45.44,0:20:47.98,Default,,0,0,0,,是说你可以将两个元素的和乘以另一个元素\r\nDialogue: 0,0:20:49.28,0:20:51.01,Default,,0,0,0,,在数集内思考这个问题是很容易的\r\nDialogue: 0,0:20:51.05,0:20:55.41,Default,,0,0,0,,但假设我想将这个想法应用于\r\nDialogue: 0,0:20:56.08,0:20:58.58,Default,,0,0,0,,对两向量a1和a2相加\r\nDialogue: 0,0:20:59.89,0:21:03.26,Default,,0,0,0,,乘以某一因子x然后得到另一向量\r\nDialogue: 0,0:21:03.33,0:21:09.75,Default,,0,0,0,,我甚至可以说 若a1和a2皆为多项式\r\nDialogue: 0,0:21:11.07,0:21:13.90,Default,,0,0,0,,我想对这两个多项式求和\r\nDialogue: 0,0:21:13.92,0:21:16.86,Default,,0,0,0,,然后乘以2得到一个多项式\r\nDialogue: 0,0:21:20.16,0:21:23.83,Default,,0,0,0,,同理 a1或a2也可以是电信号\r\nDialogue: 0,0:21:24.56,0:21:27.77,Default,,0,0,0,,我想将二个信号加和\r\nDialogue: 0,0:21:27.81,0:21:30.27,Default,,0,0,0,,并将结果放入一个放大器\r\nDialogue: 0,0:21:30.28,0:21:33.03,Default,,0,0,0,,用一个类似于2的因子乘以它们\r\nDialogue: 0,0:21:33.82,0:21:36.93,Default,,0,0,0,,这种想法的基本点是 我希望用一个通用记号表示它们\r\nDialogue: 0,0:21:38.32,0:21:45.42,Default,,0,0,0,,假如我们的语言可以很好的表述这类想法\r\nDialogue: 0,0:21:47.07,0:21:49.31,Default,,0,0,0,,如果真可以这样的话\r\nDialogue: 0,0:21:50.65,0:21:52.09,Default,,0,0,0,,我将会以这样的方式表述\r\nDialogue: 0,0:21:54.99,0:22:00.41,Default,,0,0,0,,用x乘以a1和a2的和\r\nDialogue: 0,0:22:02.80,0:22:05.07,Default,,0,0,0,,更进一步 我希望做更抽象更基本的表述\r\nDialogue: 0,0:22:06.03,0:22:09.23,Default,,0,0,0,,使其可以适应各个不同类型的a1和a2\r\nDialogue: 0,0:22:10.03,0:22:11.58,Default,,0,0,0,,现在回过头来想想 似乎有点问题\r\nDialogue: 0,0:22:11.58,0:22:16.17,Default,,0,0,0,,毕竟 对两个数字和两个多项式进行加和运算\r\nDialogue: 0,0:22:16.21,0:22:18.33,Default,,0,0,0,,所用的基本操作\r\nDialogue: 0,0:22:18.38,0:22:22.98,Default,,0,0,0,,在机器内部显然是不同的\r\nDialogue: 0,0:22:23.29,0:22:27.49,Default,,0,0,0,,对两个电信号或声波加和也有同样的问题\r\nDialogue: 0,0:22:27.89,0:22:32.53,Default,,0,0,0,,无论怎样 对不同类型的元素进行求和运算\r\nDialogue: 0,0:22:32.87,0:22:34.25,Default,,0,0,0,,总是需要使用不同的方法\r\nDialogue: 0,0:22:37.09,0:22:38.64,Default,,0,0,0,,现在 为了构建这样一个系统\r\nDialogue: 0,0:22:38.78,0:22:40.67,Default,,0,0,0,,我们将如何使用这些知识呢？\r\nDialogue: 0,0:22:41.20,0:22:44.41,Default,,0,0,0,,如何在各种方法中进行选择？\r\nDialogue: 0,0:22:44.56,0:22:48.42,Default,,0,0,0,,而如果明天George又想出了一种新类型的对象\r\nDialogue: 0,0:22:48.45,0:22:50.32,Default,,0,0,0,,并将它用于加和以及乘积\r\nDialogue: 0,0:22:51.01,0:22:53.32,Default,,0,0,0,,我又该如何把这个新类型引入到系统中\r\nDialogue: 0,0:22:53.52,0:22:55.68,Default,,0,0,0,,而且能够做到不把已有的系统弄得一团糟？\r\nDialogue: 0,0:22:57.81,0:23:00.54,Default,,0,0,0,,这便是我们的第二大主题\r\nDialogue: 0,0:23:00.57,0:23:03.16,Default,,0,0,0,,控制复杂度的方法\r\nDialogue: 0,0:23:03.84,0:23:08.43,Default,,0,0,0,,我们实现的方法是按照约定来实现相应的接口\r\nDialogue: 0,0:23:17.44,0:23:20.21,Default,,0,0,0,,并以此将各部分组合起来\r\nDialogue: 0,0:23:20.25,0:23:22.04,Default,,0,0,0,,就如同电气工程中\r\nDialogue: 0,0:23:22.94,0:23:25.39,Default,,0,0,0,,人们为连接器规定标准阻抗\r\nDialogue: 0,0:23:26.16,0:23:28.62,Default,,0,0,0,,如果用符合这个标准的东西来构建系统\r\nDialogue: 0,0:23:28.67,0:23:30.40,Default,,0,0,0,,你就知道你可以把各个部件组合在一起\r\nDialogue: 0,0:23:32.78,0:23:35.68,Default,,0,0,0,,这就是我们将要讨论的第二个主题：约定接口\r\nDialogue: 0,0:23:35.73,0:23:40.94,Default,,0,0,0,,如我之前提到的\r\nDialogue: 0,0:23:40.97,0:23:42.22,Default,,0,0,0,,接下来我们将讨论通用操作中的问题\r\nDialogue: 0,0:23:42.59,0:23:47.28,Default,,0,0,0,,例如对各种不同类型数据进行均适用的加法操作\r\nDialogue: 0,0:23:52.61,0:23:54.57,Default,,0,0,0,,随后则会讨论通用操作\r\nDialogue: 0,0:23:54.61,0:23:56.99,Default,,0,0,0,,然后我们将讨论大型架构问题\r\nDialogue: 0,0:23:58.32,0:24:00.83,Default,,0,0,0,,如果通过对现实世界的复杂系统建模\r\nDialogue: 0,0:24:01.02,0:24:04.89,Default,,0,0,0,,来构建大型程序\r\nDialogue: 0,0:24:05.53,0:24:06.53,Default,,0,0,0,,我们将看到 在构建这样的系统时\r\nDialogue: 0,0:24:06.57,0:24:11.81,Default,,0,0,0,,有两种非常重要的方法\r\nDialogue: 0,0:24:11.85,0:24:13.90,Default,,0,0,0,,其一是面向对象编程\r\nDialogue: 0,0:24:14.09,0:24:18.94,Default,,0,0,0,,在这种模式中 你把你的系统想象成一个社区\r\nDialogue: 0,0:24:19.37,0:24:22.36,Default,,0,0,0,,社区中的各个部分都是通过相互间传递消息联系起来的\r\nDialogue: 0,0:24:23.44,0:24:27.81,Default,,0,0,0,,其二是关于聚集的操作 称作“流”\r\nDialogue: 0,0:24:27.98,0:24:31.50,Default,,0,0,0,,使用这种方式构建大型系统\r\nDialogue: 0,0:24:31.50,0:24:35.29,Default,,0,0,0,,类似于电气工程师构造大型电气系统\r\nDialogue: 0,0:24:38.93,0:24:40.49,Default,,0,0,0,,这就是我们的第二个话题\r\nDialogue: 0,0:24:43.37,0:24:45.93,Default,,0,0,0,,现在 我们将要讨论第三个话题\r\nDialogue: 0,0:24:45.95,0:24:49.70,Default,,0,0,0,,控制复杂度的第三个技术\r\nDialogue: 0,0:24:49.74,0:24:50.94,Default,,0,0,0,,便是定义新的语言\r\nDialogue: 0,0:24:51.69,0:24:55.42,Default,,0,0,0,,因为有时 当你有点受不了设计的复杂度时\r\nDialogue: 0,0:24:55.47,0:24:59.69,Default,,0,0,0,,你可以通过定义一门新的语言来控制系统复杂度\r\nDialogue: 0,0:25:01.41,0:25:05.60,Default,,0,0,0,,新语言的设计意图是为了强调系统的某个方面\r\nDialogue: 0,0:25:05.79,0:25:09.36,Default,,0,0,0,,它一方面隐藏了部分细节 另一方面则但强调一些其他的细节\r\nDialogue: 0,0:25:12.99,0:25:15.93,Default,,0,0,0,,这部分将是课程中最神奇的部分\r\nDialogue: 0,0:25:16.03,0:25:21.20,Default,,0,0,0,,我们将开始于构建新的计算机语言\r\nDialogue: 0,0:25:21.82,0:25:26.30,Default,,0,0,0,,实际上我们首先要完成的工作已经内建于Lisp之中了\r\nDialogue: 0,0:25:29.23,0:25:34.02,Default,,0,0,0,,我们将展现如何用Lisp来解释Lisp\r\nDialogue: 0,0:25:34.29,0:25:36.94,Default,,0,0,0,,这是一个非常类似于自循环的过程\r\nDialogue: 0,0:25:36.96,0:25:39.92,Default,,0,0,0,,这与（Lisp中）一个神奇的符号有关\r\nDialogue: 0,0:25:40.97,0:25:46.38,Default,,0,0,0,,解释Lisp的步骤是\r\nDialogue: 0,0:25:46.57,0:25:47.71,Default,,0,0,0,,应用和求值——这两大步骤的轮转\r\nDialogue: 0,0:25:47.89,0:25:50.87,Default,,0,0,0,,这两者不断地互相交替进行\r\nDialogue: 0,0:25:52.54,0:25:54.24,Default,,0,0,0,,接下来 我们将看到其余神奇的东西\r\nDialogue: 0,0:25:54.25,0:25:56.85,Default,,0,0,0,,譬如另一种魔法符号\r\nDialogue: 0,0:25:57.12,0:26:01.52,Default,,0,0,0,,一种叫做Y运算符的东西\r\nDialogue: 0,0:26:01.55,0:26:06.45,Default,,0,0,0,,某种意义上 它在过程式语言中用于 表达无限\r\nDialogue: 0,0:26:06.51,0:26:07.44,Default,,0,0,0,,我们也会谈论到它\r\nDialogue: 0,0:26:08.40,0:26:13.73,Default,,0,0,0,,总之 这部分课程被称作“元语言抽象”\r\nDialogue: 0,0:26:16.17,0:26:26.23,Default,,0,0,0,,主要讨论如何构建一门新语言\r\nDialogue: 0,0:26:30.22,0:26:35.71,Default,,0,0,0,,如我所言 我们将从了解解释的过程开始\r\nDialogue: 0,0:26:35.74,0:26:42.12,Default,,0,0,0,,随后则一起讨论应用-求值循环和构建Lisp\r\nDialogue: 0,0:26:42.16,0:26:44.17,Default,,0,0,0,,你将发现这种方法具有相当的普遍性\r\nDialogue: 0,0:26:44.37,0:26:48.26,Default,,0,0,0,,我们将用同样的技术去构建一门全完不同的语言\r\nDialogue: 0,0:26:48.53,0:26:50.31,Default,,0,0,0,,一种所谓的逻辑编程语言\r\nDialogue: 0,0:26:50.53,0:26:54.83,Default,,0,0,0,,一种无关具有输入和输出的过程\r\nDialogue: 0,0:26:54.86,0:26:57.25,Default,,0,0,0,,而仅关注元素之间关系的语言\r\nDialogue: 0,0:26:57.31,0:27:03.92,Default,,0,0,0,,最终 我们将讨论如何将这些东西\r\nDialogue: 0,0:27:03.95,0:27:05.60,Default,,0,0,0,,实实在在的实现在简单的机器上\r\nDialogue: 0,0:27:05.65,0:27:08.39,Default,,0,0,0,,比如说这个\r\nDialogue: 0,0:27:09.13,0:27:12.14,Default,,0,0,0,,如图所示的芯片\r\nDialogue: 0,0:27:12.16,0:27:17.47,Default,,0,0,0,,就是我们在硬件部分谈及的Lisp解释器\r\nDialogue: 0,0:27:20.88,0:27:23.79,Default,,0,0,0,,这三大主题就是本课的提纲\r\nDialogue: 0,0:27:24.88,0:27:29.41,Default,,0,0,0,,黑盒抽象 约定接口 元语言抽象\r\nDialogue: 0,0:27:31.58,0:27:33.57,Default,,0,0,0,,好 先休息一会儿 然后正式开始\r\nDialogue: 0,0:27:52.19,0:28:03.42,Default,,0,0,0,,[音乐]\r\nDialogue: 0,0:28:03.92,0:28:06.84,Default,,0,0,0,,现在让我们正式开始学习Lisp\r\nDialogue: 0,0:28:08.06,0:28:10.75,Default,,0,0,0,,事实上 我们将开始学习一些非常重要的内容\r\nDialogue: 0,0:28:10.80,0:28:14.33,Default,,0,0,0,,在这门课程中最重要的 不是Lisp本身\r\nDialogue: 0,0:28:14.38,0:28:18.41,Default,,0,0,0,,而是一种的通用框架体系\r\nDialogue: 0,0:28:18.62,0:28:21.89,Default,,0,0,0,,我们用它来组织我之前提到的语言\r\nDialogue: 0,0:28:22.12,0:28:25.10,Default,,0,0,0,,当有人要向你展示一门新语言\r\nDialogue: 0,0:28:25.13,0:28:26.16,Default,,0,0,0,,你应该问他\r\nDialogue: 0,0:28:26.19,0:28:32.87,Default,,0,0,0,,（构成语言的）基本元素有哪些？\r\nDialogue: 0,0:28:37.50,0:28:38.78,Default,,0,0,0,,这门语言使用哪些基本元素？\r\nDialogue: 0,0:28:38.96,0:28:43.53,Default,,0,0,0,,你是如何将这些元素组合在一起的？\r\nDialogue: 0,0:28:43.68,0:28:47.42,Default,,0,0,0,,组合的方法是什么？\r\nDialogue: 0,0:28:50.17,0:28:54.18,Default,,0,0,0,,允许你将这些基本元素整合在一起\r\nDialogue: 0,0:28:54.37,0:28:56.51,Default,,0,0,0,,以构建更大的对象的又是什么？\r\nDialogue: 0,0:28:58.01,0:28:59.61,Default,,0,0,0,,把东西构建在一起的方法是什么？\r\nDialogue: 0,0:29:01.39,0:29:05.69,Default,,0,0,0,,以及 抽象的方法是什么？\r\nDialogue: 0,0:29:08.35,0:29:16.85,Default,,0,0,0,,我们如何利用这些元素并把它们封装成盒子？\r\nDialogue: 0,0:29:16.88,0:29:19.66,Default,,0,0,0,,我们如何为它们命名使得我们可以\r\nDialogue: 0,0:29:19.68,0:29:23.85,Default,,0,0,0,,把它们当作基本元素来用于构建更复杂的东西？\r\nDialogue: 0,0:29:23.89,0:29:25.66,Default,,0,0,0,,等等 等等 等等\r\nDialogue: 0,0:29:26.89,0:29:28.08,Default,,0,0,0,,因此 当有人告诉你\r\nDialogue: 0,0:29:28.09,0:29:29.55,Default,,0,0,0,,嘿 我发明了一种新的计算机语言\r\nDialogue: 0,0:29:30.86,0:29:34.70,Default,,0,0,0,,你不应该问 用你的语言编写求逆矩阵需要多少代码\r\nDialogue: 0,0:29:35.73,0:29:36.88,Default,,0,0,0,,这是风马牛不相及的\r\nDialogue: 0,0:29:37.39,0:29:42.30,Default,,0,0,0,,如果该语言没有内建了矩阵或者类似的东西\r\nDialogue: 0,0:29:42.33,0:29:43.37,Default,,0,0,0,,那你就应该问他\r\nDialogue: 0,0:29:43.37,0:29:46.03,Default,,0,0,0,,应该如何构建矩阵？\r\nDialogue: 0,0:29:46.05,0:29:48.47,Default,,0,0,0,,如何通过组合来构建？\r\nDialogue: 0,0:29:48.62,0:29:50.71,Default,,0,0,0,,如何对其进行抽象\r\nDialogue: 0,0:29:51.68,0:29:54.21,Default,,0,0,0,,把它作为基本元素\r\nDialogue: 0,0:29:54.22,0:29:56.52,Default,,0,0,0,,来构建更复杂的东西？\r\nDialogue: 0,0:29:58.75,0:30:04.61,Default,,0,0,0,,我们将了解到Lisp的一些基本数据和基本过程\r\nDialogue: 0,0:30:05.25,0:30:07.50,Default,,0,0,0,,好吧 这次是真的开始了\r\nDialogue: 0,0:30:07.55,0:30:14.89,Default,,0,0,0,,这里有一个Lisp的基本数据 数字3\r\nDialogue: 0,0:30:16.27,0:30:19.87,Default,,0,0,0,,事实上 如果打破沙锅问到底的话 这不是数字3\r\nDialogue: 0,0:30:19.93,0:30:25.57,Default,,0,0,0,,这只是一个符号 用以代表柏拉图观念下的数字3的\r\nDialogue: 0,0:30:26.67,0:30:28.93,Default,,0,0,0,,这又是另一个\r\nDialogue: 0,0:30:30.48,0:30:36.06,Default,,0,0,0,,这个是Lisp中又一个基本数据 17.4\r\nDialogue: 0,0:30:36.08,0:30:39.42,Default,,0,0,0,,又或者说 代表17.4\r\nDialogue: 0,0:30:40.99,0:30:44.48,Default,,0,0,0,,这儿还有一个5\r\nDialogue: 0,0:30:46.86,0:30:52.21,Default,,0,0,0,,然后这儿又有一个内建于Lisp的基本对象“+”\r\nDialogue: 0,0:30:52.25,0:30:55.68,Default,,0,0,0,,如果又要继续深究的话\r\nDialogue: 0,0:30:55.71,0:31:00.47,Default,,0,0,0,,这只是一个名字 代表对元素进行加和的基本方法而已\r\nDialogue: 0,0:31:00.53,0:31:02.53,Default,,0,0,0,,就像这个是柏拉图式的3\r\nDialogue: 0,0:31:02.61,0:31:09.32,Default,,0,0,0,,这也只是一个代表柏拉图观念下的将某些元素加和起来\r\nDialogue: 0,0:31:10.32,0:31:11.98,Default,,0,0,0,,这些都是基本元素\r\nDialogue: 0,0:31:12.14,0:31:13.76,Default,,0,0,0,,我可以将它们放在一起\r\nDialogue: 0,0:31:14.14,0:31:18.29,Default,,0,0,0,,我可以说 3加17.4加5的和是多少\r\nDialogue: 0,0:31:18.69,0:31:21.31,Default,,0,0,0,,这等同于说\r\nDialogue: 0,0:31:21.33,0:31:27.71,Default,,0,0,0,,让我们把求和运算符应用于这三个数\r\nDialogue: 0,0:31:27.74,0:31:31.15,Default,,0,0,0,,我可以得到什么呢 是8 是17 还是25.4\r\nDialogue: 0,0:31:34.43,0:31:38.05,Default,,0,0,0,,因此 我可以问Lisp这个的值是多少\r\nDialogue: 0,0:31:38.94,0:31:40.77,Default,,0,0,0,,（表达式）返回25.4\r\nDialogue: 0,0:31:43.58,0:31:44.83,Default,,0,0,0,,介绍一些术语吧\r\nDialogue: 0,0:31:44.88,0:31:51.47,Default,,0,0,0,,我所写的这些东西就叫做组合式\r\nDialogue: 0,0:31:56.88,0:32:01.94,Default,,0,0,0,,通常 一个组合式是由运算符\r\nDialogue: 0,0:32:03.39,0:32:04.72,Default,,0,0,0,,这些就是运算符\r\nDialogue: 0,0:32:09.71,0:32:12.05,Default,,0,0,0,,和应用该运算符的运算对象组成\r\nDialogue: 0,0:32:13.25,0:32:14.54,Default,,0,0,0,,这些是运算对象\r\nDialogue: 0,0:32:21.89,0:32:23.79,Default,,0,0,0,,当然 我可以完成更复杂的事\r\nDialogue: 0,0:32:23.82,0:32:28.56,Default,,0,0,0,,我可以使之更复杂是因为 这些运算对象\r\nDialogue: 0,0:32:29.52,0:32:31.09,Default,,0,0,0,,通常来说 也可以是组合式\r\nDialogue: 0,0:32:31.15,0:32:44.47,Default,,0,0,0,,比如 3加上5乘以6乘以8乘以2的积的和是多少\r\nDialogue: 0,0:32:45.66,0:32:52.16,Default,,0,0,0,,而我应该得到 我算一下 30 40 43\r\nDialogue: 0,0:32:52.73,0:32:54.81,Default,,0,0,0,,因此Lisp会返回这个表达式的值是43\r\nDialogue: 0,0:32:56.56,0:33:02.80,Default,,0,0,0,,后续我们将看到构造组合式是组合的基本需求\r\nDialogue: 0,0:33:04.65,0:33:09.22,Default,,0,0,0,,你所看到的这些语法\r\nDialogue: 0,0:33:10.56,0:33:13.04,Default,,0,0,0,,就是Lisp用的所谓的前缀表示法\r\nDialogue: 0,0:33:16.22,0:33:25.21,Default,,0,0,0,,意即操作符在操作数的左端\r\nDialogue: 0,0:33:25.47,0:33:26.48,Default,,0,0,0,,这只是个约定\r\nDialogue: 0,0:33:27.66,0:33:29.77,Default,,0,0,0,,注意 这些都被括起来了\r\nDialogue: 0,0:33:30.08,0:33:32.32,Default,,0,0,0,,这些括号使得它们区别开来\r\nDialogue: 0,0:33:32.32,0:33:36.99,Default,,0,0,0,,因此只要看看这个 我就可以知道这个是运算符\r\nDialogue: 0,0:33:37.01,0:33:40.99,Default,,0,0,0,,以及这有1个 2个 3个 4个运算对象\r\nDialogue: 0,0:33:42.38,0:33:47.97,Default,,0,0,0,,而且我也可以发现第二个运算对象是个组合式\r\nDialogue: 0,0:33:48.88,0:33:51.55,Default,,0,0,0,,该组合式有一个运算符和两个运算对象\r\nDialogue: 0,0:33:52.43,0:33:54.27,Default,,0,0,0,,Lisp中的括号 有点或者非常不同于\r\nDialogue: 0,0:33:54.61,0:33:57.71,Default,,0,0,0,,通常数学中的括号\r\nDialogue: 0,0:33:57.77,0:34:00.11,Default,,0,0,0,,数学中 我们常将其用于分组\r\nDialogue: 0,0:34:01.21,0:34:03.75,Default,,0,0,0,,如果有时你忘了闭合括号 但其他人能理解你的意图\r\nDialogue: 0,0:34:03.77,0:34:05.56,Default,,0,0,0,,这也无关紧要\r\nDialogue: 0,0:34:05.76,0:34:08.51,Default,,0,0,0,,通常的 你多加了括号也无所谓\r\nDialogue: 0,0:34:08.86,0:34:10.94,Default,,0,0,0,,因为这样只会使得分组更加明确\r\nDialogue: 0,0:34:10.96,0:34:11.77,Default,,0,0,0,,Lisp可不像这样\r\nDialogue: 0,0:34:13.12,0:34:15.37,Default,,0,0,0,,Lisp中你既不能不闭合括号\r\nDialogue: 0,0:34:16.38,0:34:18.56,Default,,0,0,0,,亦不能添加多余的括号\r\nDialogue: 0,0:34:19.33,0:34:21.28,Default,,0,0,0,,因为加括号总是意味着\r\nDialogue: 0,0:34:21.37,0:34:27.05,Default,,0,0,0,,确切的来说 所括之物是一个组合式\r\nDialogue: 0,0:34:27.09,0:34:28.81,Default,,0,0,0,,表示将运算符应用于运算对象\r\nDialogue: 0,0:34:29.04,0:34:32.62,Default,,0,0,0,,如果我不闭合这个括号\r\nDialogue: 0,0:34:32.65,0:34:33.96,Default,,0,0,0,,这个就变成其它的意思了\r\nDialogue: 0,0:34:35.41,0:34:37.25,Default,,0,0,0,,事实上 我们可以这么来理解这个问题\r\nDialogue: 0,0:34:37.41,0:34:41.65,Default,,0,0,0,,把我写的这些东西想作一个树\r\nDialogue: 0,0:34:42.37,0:34:47.30,Default,,0,0,0,,这个组合式实际上是一个树 树具有一个“+”\r\nDialogue: 0,0:34:47.37,0:34:54.46,Default,,0,0,0,,以及 一个3和一些其它的东西和一个8 还有一个2\r\nDialogue: 0,0:34:54.48,0:34:56.35,Default,,0,0,0,,而这里的其它的东西\r\nDialogue: 0,0:34:56.35,0:35:03.22,Default,,0,0,0,,它本身是一个有一个“*”一个5和一个6的子树\r\nDialogue: 0,0:35:03.95,0:35:05.53,Default,,0,0,0,,我们可以这样认为\r\nDialogue: 0,0:35:05.55,0:35:09.00,Default,,0,0,0,,我们只是在构建这些树而已\r\nDialogue: 0,0:35:09.21,0:35:15.10,Default,,0,0,0,,括号只是将这种二维结构写作线性字符串\r\nDialogue: 0,0:35:15.79,0:35:17.34,Default,,0,0,0,,的一种方法罢了\r\nDialogue: 0,0:35:19.23,0:35:23.81,Default,,0,0,0,,因为至少在Lisp发明时 人们还在用电传打字机或者打孔卡\r\nDialogue: 0,0:35:24.17,0:35:25.60,Default,,0,0,0,,这种记法方便多了\r\nDialogue: 0,0:35:25.97,0:35:30.52,Default,,0,0,0,,如果Lisp是在当下被发明的 语法可能会像树那样\r\nDialogue: 0,0:35:31.76,0:35:35.07,Default,,0,0,0,,那么 让我们看看在计算机里面它究竟是什么样\r\nDialogue: 0,0:35:36.29,0:35:39.37,Default,,0,0,0,,这里有个Lisp解释套件\r\nDialogue: 0,0:35:39.41,0:35:40.43,Default,,0,0,0,,这是个编辑器\r\nDialogue: 0,0:35:41.13,0:35:44.86,Default,,0,0,0,,我将要在上方写一些表达式并让Lisp对其求值\r\nDialogue: 0,0:35:45.12,0:35:46.75,Default,,0,0,0,,比如 我可以问Lisp\r\nDialogue: 0,0:35:46.83,0:35:48.53,Default,,0,0,0,,这个符号的值是多少\r\nDialogue: 0,0:35:49.44,0:35:50.50,Default,,0,0,0,,我键入3\r\nDialogue: 0,0:35:50.57,0:35:52.20,Default,,0,0,0,,然后叫Lisp对其求值\r\nDialogue: 0,0:35:52.32,0:35:54.77,Default,,0,0,0,,然后你就会看到Lisp在下面返回了一些信息\r\nDialogue: 0,0:35:55.39,0:35:56.84,Default,,0,0,0,,这个值就是3\r\nDialogue: 0,0:35:57.58,0:36:04.96,Default,,0,0,0,,我也可以问 3加上4加上8的和是多少\r\nDialogue: 0,0:36:06.45,0:36:08.05,Default,,0,0,0,,键入这个组合式\r\nDialogue: 0,0:36:08.93,0:36:10.66,Default,,0,0,0,,让Lisp对其求值\r\nDialogue: 0,0:36:14.49,0:36:15.68,Default,,0,0,0,,返回15\r\nDialogue: 0,0:36:16.57,0:36:18.80,Default,,0,0,0,,我可以键入一些更复杂的东西\r\nDialogue: 0,0:36:19.25,0:36:34.14,Default,,0,0,0,,将3乘以7加19.5的和的乘积求和得多少\r\nDialogue: 0,0:36:35.21,0:36:38.00,Default,,0,0,0,,你会发现Lisp内建了一些功能\r\nDialogue: 0,0:36:38.01,0:36:39.76,Default,,0,0,0,,帮你跟踪这些括号\r\nDialogue: 0,0:36:39.77,0:36:42.13,Default,,0,0,0,,看我键入下一个右圆括号\r\nDialogue: 0,0:36:42.21,0:36:45.01,Default,,0,0,0,,用于闭合以“*”开头的那个组合式\r\nDialogue: 0,0:36:45.52,0:36:47.30,Default,,0,0,0,,开头的那个左括号会闪一下\r\nDialogue: 0,0:36:47.76,0:36:49.69,Default,,0,0,0,,我把这些括号擦去 再示范一次\r\nDialogue: 0,0:36:50.14,0:36:52.70,Default,,0,0,0,,键入右括号 闭合了“+”组合式\r\nDialogue: 0,0:36:53.58,0:36:56.41,Default,,0,0,0,,再键入右括号 闭合了“*”组合式\r\nDialogue: 0,0:36:57.90,0:37:00.76,Default,,0,0,0,,现在我又回到了加 我将它们与4相加\r\nDialogue: 0,0:37:01.66,0:37:02.69,Default,,0,0,0,,闭合了“+”组合式\r\nDialogue: 0,0:37:02.73,0:37:07.07,Default,,0,0,0,,现在我补全了组合式 然后我问Lisp它们的值是多少\r\nDialogue: 0,0:37:07.26,0:37:11.66,Default,,0,0,0,,这种内建于各种Lisp系统的\r\nDialogue: 0,0:37:11.76,0:37:13.29,Default,,0,0,0,,括号匹配工具帮你跟进（括号匹配）\r\nDialogue: 0,0:37:13.36,0:37:16.55,Default,,0,0,0,,因为手工闭合这些括号太辛苦了\r\nDialogue: 0,0:37:16.81,0:37:21.20,Default,,0,0,0,,这又是另外一种保持括号跟进的约定\r\nDialogue: 0,0:37:21.25,0:37:23.68,Default,,0,0,0,,我另外写一个复杂的组合式\r\nDialogue: 0,0:37:24.77,0:37:34.00,Default,,0,0,0,,将3和5的积与某个元素求和\r\nDialogue: 0,0:37:34.03,0:37:35.23,Default,,0,0,0,,现在我将要缩进\r\nDialogue: 0,0:37:35.28,0:37:39.85,Default,,0,0,0,,使得这些运算对象都是垂直书写的\r\nDialogue: 0,0:37:40.30,0:37:45.65,Default,,0,0,0,,将这些加上47乘以\r\nDialogue: 0,0:37:47.02,0:37:54.59,Default,,0,0,0,,恩…… 47乘以20和6.8的差\r\nDialogue: 0,0:37:54.62,0:37:57.09,Default,,0,0,0,,意即从20中减去6.8\r\nDialogue: 0,0:37:58.97,0:38:00.19,Default,,0,0,0,,然后 这个括号闭合了\r\nDialogue: 0,0:38:00.22,0:38:03.47,Default,,0,0,0,,闭合“-” 闭合“*”\r\nDialogue: 0,0:38:03.76,0:38:05.42,Default,,0,0,0,,现在 我们再写一个运算符\r\nDialogue: 0,0:38:05.44,0:38:09.49,Default,,0,0,0,,Lisp编辑器自动缩进到正确的位置\r\nDialogue: 0,0:38:10.40,0:38:11.50,Default,,0,0,0,,来帮助我保持跟进\r\nDialogue: 0,0:38:12.61,0:38:14.09,Default,,0,0,0,,我再示范一次\r\nDialogue: 0,0:38:14.13,0:38:15.89,Default,,0,0,0,,这样就又闭合了最后一个括号\r\nDialogue: 0,0:38:16.25,0:38:17.71,Default,,0,0,0,,它匹配了这个“+”（的括号）\r\nDialogue: 0,0:38:20.40,0:38:22.64,Default,,0,0,0,,现在我想问 这个的值是多少\r\nDialogue: 0,0:38:23.87,0:38:29.28,Default,,0,0,0,,因此 这两件事 缩进到正确的位置\r\nDialogue: 0,0:38:29.31,0:38:30.86,Default,,0,0,0,,也就是所谓的美观的输出\r\nDialogue: 0,0:38:31.55,0:38:33.58,Default,,0,0,0,,以及闭合提示\r\nDialogue: 0,0:38:33.89,0:38:37.73,Default,,0,0,0,,是许多Lisp系统所内建用于帮你保持跟进的工具\r\nDialogue: 0,0:38:37.76,0:38:39.01,Default,,0,0,0,,你应该学习如何使用它们\r\nDialogue: 0,0:38:41.52,0:38:43.17,Default,,0,0,0,,好 这些都是基本的内容\r\nDialogue: 0,0:38:44.73,0:38:46.31,Default,,0,0,0,,这就是一种组合的方法\r\nDialogue: 0,0:38:46.33,0:38:47.93,Default,,0,0,0,,现在让我们来看看抽象的方法\r\nDialogue: 0,0:38:49.44,0:38:53.84,Default,,0,0,0,,我希望我能够写一些像这样的组合式\r\nDialogue: 0,0:38:53.85,0:38:55.77,Default,,0,0,0,,将它抽象化并给它命名\r\nDialogue: 0,0:38:55.81,0:38:57.26,Default,,0,0,0,,使得我可以将其作为一个（我们语言的）元素\r\nDialogue: 0,0:38:57.31,0:38:59.92,Default,,0,0,0,,在Lisp中 我可以用“define”来实现\r\nDialogue: 0,0:39:01.17,0:39:02.43,Default,,0,0,0,,比如说\r\nDialogue: 0,0:39:02.73,0:39:15.05,Default,,0,0,0,,定义A为5乘以5\r\nDialogue: 0,0:39:18.40,0:39:22.35,Default,,0,0,0,,现在我可以问Lisp\r\nDialogue: 0,0:39:22.38,0:39:26.01,Default,,0,0,0,,A和A的乘积是多少\r\nDialogue: 0,0:39:27.18,0:39:29.81,Default,,0,0,0,,这个是25所以这个就是625\r\nDialogue: 0,0:39:31.97,0:39:36.01,Default,,0,0,0,,但更重要的则是 我现在可以使用A\r\nDialogue: 0,0:39:36.21,0:39:37.92,Default,,0,0,0,,我已经在这个组合式里面用过了\r\nDialogue: 0,0:39:38.41,0:39:43.55,Default,,0,0,0,,但我也可以在更复杂的组合式里面使用它\r\nDialogue: 0,0:39:43.58,0:39:50.93,Default,,0,0,0,,我也可以说 定义B为\r\nDialogue: 0,0:39:50.97,0:39:57.45,Default,,0,0,0,,A与5乘以A的积的和\r\nDialogue: 0,0:39:59.44,0:40:00.72,Default,,0,0,0,,闭合“+”\r\nDialogue: 0,0:40:03.45,0:40:05.85,Default,,0,0,0,,让我们来看看它在计算机中是怎样的吧\r\nDialogue: 0,0:40:07.28,0:40:10.68,Default,,0,0,0,,我就像黑板上写的那样键入就可以了\r\nDialogue: 0,0:40:10.83,0:40:21.73,Default,,0,0,0,,我告诉Lisp\r\nDialogue: 0,0:40:23.74,0:40:25.38,Default,,0,0,0,,定义A为5乘以5的积\r\nDialogue: 0,0:40:25.52,0:40:28.94,Default,,0,0,0,,注意Lisp在下方回应了一个A\r\nDialogue: 0,0:40:29.09,0:40:31.38,Default,,0,0,0,,通常来说 你如果在Lisp中键入了一个定义\r\nDialogue: 0,0:40:31.50,0:40:35.02,Default,,0,0,0,,它返回被定义的符号\r\nDialogue: 0,0:40:35.63,0:40:39.66,Default,,0,0,0,,现在我问Lisp A乘以A的积是多少\r\nDialogue: 0,0:40:42.81,0:40:44.33,Default,,0,0,0,,Lisp返回625\r\nDialogue: 0,0:40:46.05,0:41:00.34,Default,,0,0,0,,我也可以定义B为A加上5乘以A的积的和\r\nDialogue: 0,0:41:00.48,0:41:05.70,Default,,0,0,0,,闭合“*” 闭合“+” 闭合“define”\r\nDialogue: 0,0:41:07.63,0:41:10.37,Default,,0,0,0,,Lisp在下方正常返回B\r\nDialogue: 0,0:41:11.04,0:41:13.24,Default,,0,0,0,,现在我可以问Lisp B的值是多少\r\nDialogue: 0,0:41:17.18,0:41:18.88,Default,,0,0,0,,我也可以问一些更复杂的事\r\nDialogue: 0,0:41:18.93,0:41:26.69,Default,,0,0,0,,比如A加上B除以5的商的和是多少\r\nDialogue: 0,0:41:26.73,0:41:30.25,Default,,0,0,0,,这个“/”是另一个基本运算符 代表除\r\nDialogue: 0,0:41:30.38,0:41:32.78,Default,,0,0,0,,我让B除以5 并加在A上\r\nDialogue: 0,0:41:33.65,0:41:35.23,Default,,0,0,0,,Lisp正常返回55\r\nDialogue: 0,0:41:36.57,0:41:37.92,Default,,0,0,0,,就像这样\r\nDialogue: 0,0:41:39.82,0:41:43.40,Default,,0,0,0,,这是定义东西的基本方法\r\nDialogue: 0,0:41:43.44,0:41:49.02,Default,,0,0,0,,这是最简单的命名方法 但并不是很强大\r\nDialogue: 0,0:41:50.06,0:41:51.60,Default,,0,0,0,,注意我们讨论的是通用方法\r\nDialogue: 0,0:41:51.84,0:41:53.37,Default,,0,0,0,,因此我真正想定义的是\r\nDialogue: 0,0:41:53.57,0:41:57.68,Default,,0,0,0,,一种通用方法 可以\r\nDialogue: 0,0:41:58.11,0:42:17.53,Default,,0,0,0,,得到 5乘5 6乘6 1001乘1001 1001.7乘1001.7\r\nDialogue: 0,0:42:17.76,0:42:24.16,Default,,0,0,0,,我想给一个数与其自身相乘这种想法一个名字\r\nDialogue: 0,0:42:28.48,0:42:30.11,Default,,0,0,0,,你应该知道 这叫做平方\r\nDialogue: 0,0:42:31.69,0:42:35.63,Default,,0,0,0,,而在Lisp中我应该这样实现\r\nDialogue: 0,0:42:37.97,0:42:56.25,Default,,0,0,0,,定义 square某个叫x的东西 为 将x乘以x自己\r\nDialogue: 0,0:42:57.87,0:43:01.12,Default,,0,0,0,,定义完毕后 我可以问Lisp\r\nDialogue: 0,0:43:01.12,0:43:05.49,Default,,0,0,0,,比如 10的平方是多少\r\nDialogue: 0,0:43:06.67,0:43:07.87,Default,,0,0,0,,Lisp返回100\r\nDialogue: 0,0:43:10.70,0:43:14.24,Default,,0,0,0,,让我们深入讨论一下\r\nDialogue: 0,0:43:15.29,0:43:16.88,Default,,0,0,0,,这儿是square的定义\r\nDialogue: 0,0:43:17.50,0:43:22.55,Default,,0,0,0,,square某个元素 即是将该元素进行自乘\r\nDialogue: 0,0:43:23.69,0:43:25.34,Default,,0,0,0,,这里的x\r\nDialogue: 0,0:43:26.29,0:43:27.81,Default,,0,0,0,,应该算是一种代词\r\nDialogue: 0,0:43:27.87,0:43:29.53,Default,,0,0,0,,指代了我要做平方的元素\r\nDialogue: 0,0:43:31.49,0:43:37.41,Default,,0,0,0,,实际上我将其乘以x 即是乘以它自己\r\nDialogue: 0,0:43:42.22,0:43:48.27,Default,,0,0,0,,这些就是定义一个过程的记法\r\nDialogue: 0,0:43:48.29,0:43:50.29,Default,,0,0,0,,这样说可能把你搞糊涂了\r\nDialogue: 0,0:43:50.81,0:43:53.97,Default,,0,0,0,,因为这就像我在用square一样\r\nDialogue: 0,0:43:54.00,0:43:56.80,Default,,0,0,0,,但如果我说x的平方根或者10的平方根\r\nDialogue: 0,0:43:57.55,0:44:00.81,Default,,0,0,0,,并没有说清楚我对什么做了定义\r\nDialogue: 0,0:44:03.10,0:44:04.91,Default,,0,0,0,,所以让我换个方式来进行定义\r\nDialogue: 0,0:44:05.74,0:44:08.21,Default,,0,0,0,,这样可以清楚的看到定义的具体内容\r\nDialogue: 0,0:44:08.54,0:44:29.39,Default,,0,0,0,,我定义“square”为“(lambda (x) (* x x))”\r\nDialogue: 0,0:44:36.56,0:44:42.05,Default,,0,0,0,,这里 我定义square就像我某命名为A一样\r\nDialogue: 0,0:44:43.23,0:44:44.72,Default,,0,0,0,,我定义square\r\nDialogue: 0,0:44:44.75,0:44:48.39,Default,,0,0,0,,这里 我把这个组合式的值命名为A\r\nDialogue: 0,0:44:49.29,0:44:52.41,Default,,0,0,0,,在这里 我把这个东西命名为square\r\nDialogue: 0,0:44:52.43,0:44:53.44,Default,,0,0,0,,以lambda开头\r\nDialogue: 0,0:44:53.45,0:44:56.77,Default,,0,0,0,,lambda在Lisp中用以构建一个过程\r\nDialogue: 0,0:45:00.24,0:45:02.91,Default,,0,0,0,,请仔细看一下幻灯片上的内容\r\nDialogue: 0,0:45:04.27,0:45:05.81,Default,,0,0,0,,这个定义读作\r\nDialogue: 0,0:45:05.85,0:45:10.33,Default,,0,0,0,,将square定义为\r\nDialogue: 0,0:45:12.78,0:45:13.97,Default,,0,0,0,,一个由lambda构造的\r\nDialogue: 0,0:45:14.06,0:45:17.49,Default,,0,0,0,,一个有带有参数x的过程\r\nDialogue: 0,0:45:19.26,0:45:24.09,Default,,0,0,0,,而该过程返回将x自乘的结果\r\nDialogue: 0,0:45:24.97,0:45:33.12,Default,,0,0,0,,一般来讲 这是最佳的定义方式\r\nDialogue: 0,0:45:33.41,0:45:35.20,Default,,0,0,0,,因为这个更加方便一点\r\nDialogue: 0,0:45:35.21,0:45:38.67,Default,,0,0,0,,但是也别忘了它实质上也是这个\r\nDialogue: 0,0:45:38.86,0:45:41.41,Default,,0,0,0,,事实上 就Lisp解释器而言\r\nDialogue: 0,0:45:41.61,0:45:45.55,Default,,0,0,0,,这两种方法没有区别\r\nDialogue: 0,0:45:46.51,0:45:53.29,Default,,0,0,0,,换句话说 这只是一种语法糖\r\nDialogue: 0,0:45:54.41,0:45:55.80,Default,,0,0,0,,语法糖的意思就是\r\nDialogue: 0,0:45:56.35,0:46:00.83,Default,,0,0,0,,这种形式输入更方便一些\r\nDialogue: 0,0:46:01.12,0:46:06.11,Default,,0,0,0,,这只是这下面的有lambda的表达式的语法糖而已\r\nDialogue: 0,0:46:07.31,0:46:10.62,Default,,0,0,0,,你应该记住\r\nDialogue: 0,0:46:10.80,0:46:13.87,Default,,0,0,0,,当我这样写的时候 其实是在对某个东西进行命名\r\nDialogue: 0,0:46:14.46,0:46:16.22,Default,,0,0,0,,我将其命名为square\r\nDialogue: 0,0:46:16.24,0:46:19.90,Default,,0,0,0,,square代表一个构建好的过程\r\nDialogue: 0,0:46:21.20,0:46:23.90,Default,,0,0,0,,让我们看看在计算机里面又是 怎样的吧\r\nDialogue: 0,0:46:24.78,0:46:35.95,Default,,0,0,0,,定义“(square x)”为x乘以x的积\r\nDialogue: 0,0:46:49.65,0:46:52.32,Default,,0,0,0,,将它送入Lisp\r\nDialogue: 0,0:46:53.49,0:46:53.92,Default,,0,0,0,,返回square\r\nDialogue: 0,0:46:53.93,0:46:56.29,Default,,0,0,0,,现在 我已经将某个东西命名为square了\r\nDialogue: 0,0:46:56.45,0:47:02.88,Default,,0,0,0,,完毕后 我就可以问Lisp 1001的平方是多少\r\nDialogue: 0,0:47:05.26,0:47:17.69,Default,,0,0,0,,或者更通常的来说 我可以问 5加上7的和的平方是多少\r\nDialogue: 0,0:47:22.81,0:47:24.95,Default,,0,0,0,,12的平方是144\r\nDialogue: 0,0:47:25.07,0:47:28.86,Default,,0,0,0,,在某些组合式中我亦可把square当作一个元素\r\nDialogue: 0,0:47:28.88,0:47:37.50,Default,,0,0,0,,3的平方加上4的平方的和是多少\r\nDialogue: 0,0:47:42.53,0:47:44.09,Default,,0,0,0,,9加上16得25\r\nDialogue: 0,0:47:44.91,0:47:50.54,Default,,0,0,0,,我可以将square作为元素用于更复杂的式子\r\nDialogue: 0,0:47:50.59,0:48:00.51,Default,,0,0,0,,比如 1001的平方点的平方的平方是多少\r\nDialogue: 0,0:48:07.89,0:48:10.63,Default,,0,0,0,,这就是1001点的平方的平方的平方\r\nDialogue: 0,0:48:11.20,0:48:15.45,Default,,0,0,0,,我也可以问Lisp square本身是什么\r\nDialogue: 0,0:48:15.68,0:48:17.16,Default,,0,0,0,,它的值是是什么\r\nDialogue: 0,0:48:17.44,0:48:22.14,Default,,0,0,0,,Lisp用一种约定的方法告诉我这是一个过程\r\nDialogue: 0,0:48:22.27,0:48:23.98,Default,,0,0,0,,它返回 复合过程square\r\nDialogue: 0,0:48:24.25,0:48:27.92,Default,,0,0,0,,记住 square的值是一个过程\r\nDialogue: 0,0:48:29.15,0:48:30.89,Default,,0,0,0,,而那些用星号和括号的记法\r\nDialogue: 0,0:48:31.10,0:48:34.78,Default,,0,0,0,,只是Lisp用来描述这个过程的约定\r\nDialogue: 0,0:48:36.11,0:48:41.33,Default,,0,0,0,,让我们再看两个关于define的例子\r\nDialogue: 0,0:48:44.91,0:48:46.91,Default,,0,0,0,,这有两个过程\r\nDialogue: 0,0:48:47.36,0:48:52.84,Default,,0,0,0,,定义x和y的平均值为x加上y的和除以2的商\r\nDialogue: 0,0:48:54.67,0:49:01.49,Default,,0,0,0,,以及定义好平方和平均值后 我可以定义均方\r\nDialogue: 0,0:49:01.65,0:49:04.71,Default,,0,0,0,,我可以用它们来讨论某元素的均方\r\nDialogue: 0,0:49:04.91,0:49:09.26,Default,,0,0,0,,即x的平方与y的平方的平均值\r\nDialogue: 0,0:49:10.97,0:49:13.63,Default,,0,0,0,,当定义好它们后 我可以问\r\nDialogue: 0,0:49:13.66,0:49:24.88,Default,,0,0,0,,2和3的均方是多少\r\nDialogue: 0,0:49:25.23,0:49:30.24,Default,,0,0,0,,我将会得到 4和9的平均值 即6.5\r\nDialogue: 0,0:49:32.85,0:49:36.64,Default,,0,0,0,,关键点在于 定义了square后\r\nDialogue: 0,0:49:36.64,0:49:38.67,Default,,0,0,0,,我可以把它当作一个基本元素来使用\r\nDialogue: 0,0:49:41.41,0:49:43.07,Default,,0,0,0,,因此在这里\r\nDialogue: 0,0:49:44.65,0:49:45.74,Default,,0,0,0,,我在讨论均方的时候\r\nDialogue: 0,0:49:47.29,0:49:52.56,Default,,0,0,0,,从这点来说 定义均方的人没有必要知道\r\nDialogue: 0,0:49:52.61,0:49:55.76,Default,,0,0,0,,究竟square是由语言内建支持\r\nDialogue: 0,0:49:56.94,0:49:58.93,Default,,0,0,0,,还是自定义的过程\r\nDialogue: 0,0:49:59.73,0:50:01.28,Default,,0,0,0,,这是Lisp的关键之一\r\nDialogue: 0,0:50:02.30,0:50:07.52,Default,,0,0,0,,你无法准确区别\r\nDialogue: 0,0:50:07.53,0:50:11.82,Default,,0,0,0,,哪些是语言的基本对象 哪些是语言的内建支持\r\nDialogue: 0,0:50:12.83,0:50:14.73,Default,,0,0,0,,用户使用时则无需关心这些\r\nDialogue: 0,0:50:14.93,0:50:18.51,Default,,0,0,0,,你自己构建的东西看起来就像是语言自带的基本对象\r\nDialogue: 0,0:50:18.51,0:50:19.53,Default,,0,0,0,,具有同样的能力和灵活性\r\nDialogue: 0,0:50:19.57,0:50:22.57,Default,,0,0,0,,大家可以在课后上机做做测试\r\nDialogue: 0,0:50:24.75,0:50:26.30,Default,,0,0,0,,我们接下来讨论一下“+”吧\r\nDialogue: 0,0:50:26.72,0:50:30.09,Default,,0,0,0,,好的 让我们在计算机中看看\r\nDialogue: 0,0:50:30.11,0:50:32.33,Default,,0,0,0,,“+”的值是什么\r\nDialogue: 0,0:50:34.40,0:50:37.20,Default,,0,0,0,,注意Lisp在下面的输出\r\nDialogue: 0,0:50:37.25,0:50:38.81,Default,,0,0,0,,复合过程“+”\r\nDialogue: 0,0:50:39.89,0:50:42.29,Default,,0,0,0,,因为在此系统中\r\nDialogue: 0,0:50:42.33,0:50:45.49,Default,,0,0,0,,“+”运算符是一个复合过程\r\nDialogue: 0,0:50:45.97,0:50:47.97,Default,,0,0,0,,但如果我不输入进去做下测试 你永远不会知道\r\nDialogue: 0,0:50:48.06,0:50:49.68,Default,,0,0,0,,所以这没什么不同\r\nDialogue: 0,0:50:49.84,0:50:50.51,Default,,0,0,0,,我们并不关心这些\r\nDialogue: 0,0:50:50.56,0:50:53.39,Default,,0,0,0,,它比我们日常处理的问题更加抽象一些\r\nDialogue: 0,0:50:54.17,0:50:59.11,Default,,0,0,0,,其关键点在于你无法分辨出\r\nDialogue: 0,0:50:59.17,0:51:03.82,Default,,0,0,0,,内建元素与复合元素之间的不同\r\nDialogue: 0,0:51:03.84,0:51:04.38,Default,,0,0,0,,为什么会这样呢？\r\nDialogue: 0,0:51:04.38,0:51:08.07,Default,,0,0,0,,因为复合元素经过了一次抽象封装 (以致于无法分辨)\r\nDialogue: 0,0:51:09.05,0:51:11.61,Default,,0,0,0,,我们已经介绍了Lisp的大多数元素了\r\nDialogue: 0,0:51:12.67,0:51:14.53,Default,,0,0,0,,还有一个需要进行讨论的\r\nDialogue: 0,0:51:14.57,0:51:16.53,Default,,0,0,0,,就是如何进行分情况分析\r\nDialogue: 0,0:51:16.59,0:51:17.70,Default,,0,0,0,,举个例子\r\nDialogue: 0,0:51:18.96,0:51:24.08,Default,,0,0,0,,让我们考虑绝对值函数的数学定义\r\nDialogue: 0,0:51:24.11,0:51:30.03,Default,,0,0,0,,我或许会说x的绝对值这样是一个函数\r\nDialogue: 0,0:51:30.16,0:51:37.24,Default,,0,0,0,,若x小于0 则为-x\r\nDialogue: 0,0:51:37.92,0:51:41.13,Default,,0,0,0,,若x等于0 则为0\r\nDialogue: 0,0:51:42.64,0:51:46.62,Default,,0,0,0,,若x大于0 则就是x\r\nDialogue: 0,0:51:49.15,0:51:51.90,Default,,0,0,0,,而Lisp则有一套分情况分析方法\r\nDialogue: 0,0:51:52.11,0:51:53.85,Default,,0,0,0,,以绝对值定义为例 我给大家说明一下\r\nDialogue: 0,0:51:55.55,0:52:02.41,Default,,0,0,0,,定义绝对值为 x是有多种情况的\r\nDialogue: 0,0:52:03.02,0:52:05.67,Default,,0,0,0,,这就是分情况分析\r\nDialogue: 0,0:52:09.23,0:52:19.09,Default,,0,0,0,,如果x小于0 则结果为-x\r\nDialogue: 0,0:52:22.99,0:52:24.88,Default,,0,0,0,,我这里写的是一个子句\r\nDialogue: 0,0:52:24.99,0:52:35.54,Default,,0,0,0,,这整个是一个由两部分组成的条件表达式\r\nDialogue: 0,0:52:36.35,0:52:44.70,Default,,0,0,0,,这个部分叫做谓词或者条件\r\nDialogue: 0,0:52:44.83,0:52:45.90,Default,,0,0,0,,这就是一种情况（条件）\r\nDialogue: 0,0:52:46.11,0:52:48.29,Default,,0,0,0,,用以表达条件的东西叫做谓词\r\nDialogue: 0,0:52:48.33,0:52:51.05,Default,,0,0,0,,Lisp中的谓词是一种\r\nDialogue: 0,0:52:51.37,0:52:52.87,Default,,0,0,0,,可以返回true或者false的东西\r\nDialogue: 0,0:52:53.53,0:52:56.13,Default,,0,0,0,,比如说“小于”是Lisp中的一个基本过程\r\nDialogue: 0,0:52:57.29,0:52:59.08,Default,,0,0,0,,它返回true或者false\r\nDialogue: 0,0:53:00.54,0:53:06.32,Default,,0,0,0,,子句其余部分为一个动作或者需要做的事\r\nDialogue: 0,0:53:06.93,0:53:08.14,Default,,0,0,0,,本例中为true\r\nDialogue: 0,0:53:08.17,0:53:09.81,Default,,0,0,0,,在这里 我则是取x的相反数\r\nDialogue: 0,0:53:10.08,0:53:14.41,Default,,0,0,0,,有趣的是 Lisp中减运算符符与相反数运算符相同\r\nDialogue: 0,0:53:14.56,0:53:18.43,Default,,0,0,0,,如果有两个及两个以上的参数\r\nDialogue: 0,0:53:18.58,0:53:22.49,Default,,0,0,0,,正如我们看到的 假设刚好有两个参数 就从第一个中减去第二个\r\nDialogue: 0,0:53:22.53,0:53:24.13,Default,,0,0,0,,如果只有一个参数 则取其相反数\r\nDialogue: 0,0:53:25.13,0:53:27.87,Default,,0,0,0,,这与前面相符合\r\nDialogue: 0,0:53:27.87,0:53:29.69,Default,,0,0,0,,这又是一个COND子句\r\nDialogue: 0,0:53:30.64,0:53:35.87,Default,,0,0,0,,这是说 在x等于0的时候 结果为0\r\nDialogue: 0,0:53:37.95,0:53:44.75,Default,,0,0,0,,在x大于0的时候 结果为x\r\nDialogue: 0,0:53:45.33,0:53:49.38,Default,,0,0,0,,闭合子句 闭合COND 闭合define\r\nDialogue: 0,0:53:49.57,0:53:51.29,Default,,0,0,0,,这就是绝对值的定义\r\nDialogue: 0,0:53:51.31,0:53:53.66,Default,,0,0,0,,你会发现分情况分析\r\nDialogue: 0,0:53:53.66,0:53:56.04,Default,,0,0,0,,与数学中所用的非常相似\r\nDialogue: 0,0:53:58.14,0:54:03.07,Default,,0,0,0,,当然还有一些不常用的受限的分情况分析方法\r\nDialogue: 0,0:54:03.07,0:54:06.24,Default,,0,0,0,,很多时候 你在进行分情况分析时只有一种情况\r\nDialogue: 0,0:54:06.93,0:54:08.07,Default,,0,0,0,,你首先进行测试\r\nDialogue: 0,0:54:08.33,0:54:10.75,Default,,0,0,0,,然后根据返回的为true或false来决定如何处理\r\nDialogue: 0,0:54:11.01,0:54:15.90,Default,,0,0,0,,这是另外一种定义绝对值的方法\r\nDialogue: 0,0:54:16.00,0:54:17.19,Default,,0,0,0,,但看起来是几乎一样的\r\nDialogue: 0,0:54:17.66,0:54:22.56,Default,,0,0,0,,像这样 如果x小于0 结果则为x的相反数\r\nDialogue: 0,0:54:24.41,0:54:25.97,Default,,0,0,0,,否则 结果即为x\r\nDialogue: 0,0:54:26.05,0:54:27.25,Default,,0,0,0,,我们将会大量的使用“if”\r\nDialogue: 0,0:54:27.29,0:54:29.13,Default,,0,0,0,,再次声明\r\nDialogue: 0,0:54:29.13,0:54:32.70,Default,,0,0,0,,你们在这里看到的绝对值形式\r\nDialogue: 0,0:54:34.30,0:54:36.98,Default,,0,0,0,,和我在黑板上写的那种\r\nDialogue: 0,0:54:37.52,0:54:38.80,Default,,0,0,0,,本质上是一样的\r\nDialogue: 0,0:54:39.09,0:54:42.26,Default,,0,0,0,,而“if”和“COND”则是——\r\nDialogue: 0,0:54:42.30,0:54:44.45,Default,,0,0,0,,你可以把“COND”当做“if”的语法糖\r\nDialogue: 0,0:54:44.99,0:54:47.36,Default,,0,0,0,,或者“if”是“COND”的语法糖\r\nDialogue: 0,0:54:47.39,0:54:48.65,Default,,0,0,0,,这没什么区别\r\nDialogue: 0,0:54:49.21,0:54:51.35,Default,,0,0,0,,Lisp系统的设计者会从中会选择一个\r\nDialogue: 0,0:54:51.39,0:54:52.97,Default,,0,0,0,,然后依照这个来实现另外一个\r\nDialogue: 0,0:54:53.15,0:54:54.67,Default,,0,0,0,,你首先实现哪一个都无所谓\r\nDialogue: 0,0:55:02.27,0:55:05.36,Default,,0,0,0,,让我们停下来 解决几点疑问\r\nDialogue: 0,0:55:05.69,0:55:10.08,Default,,0,0,0,,为什么我有时用define时\r\nDialogue: 0,0:55:11.09,0:55:14.75,Default,,0,0,0,,我在这里使用了一个左括号\r\nDialogue: 0,0:55:14.81,0:55:16.45,Default,,0,0,0,,输入 define (XXX\r\nDialogue: 0,0:55:16.86,0:55:20.81,Default,,0,0,0,,而有时我这样写时却没加左括号\r\nDialogue: 0,0:55:22.06,0:55:27.23,Default,,0,0,0,,是因为你所见的\r\nDialogue: 0,0:55:27.26,0:55:29.41,Default,,0,0,0,,这种“define”表达式\r\nDialogue: 0,0:55:29.47,0:55:32.13,Default,,0,0,0,,对于定义过程来讲是非常特殊\r\nDialogue: 0,0:55:33.61,0:55:40.21,Default,,0,0,0,,再次强调 这实际上是说我定义这个叫square的符号为这个\r\nDialogue: 0,0:55:41.45,0:55:45.98,Default,,0,0,0,,你所知道的则是 你先写一个“define”\r\nDialogue: 0,0:55:47.15,0:55:50.06,Default,,0,0,0,,然后你再写一个符号 没有左括号\r\nDialogue: 0,0:55:50.17,0:55:51.49,Default,,0,0,0,,这是你将要定义的符号\r\nDialogue: 0,0:55:52.08,0:55:53.70,Default,,0,0,0,,这又是你要将其定义为什么\r\nDialogue: 0,0:55:54.65,0:55:57.55,Default,,0,0,0,,就像这儿和这儿\r\nDialogue: 0,0:55:57.61,0:56:00.29,Default,,0,0,0,,这是“define”的基本使用方法\r\nDialogue: 0,0:56:01.12,0:56:03.65,Default,,0,0,0,,然而 这种特殊的语法技巧\r\nDialogue: 0,0:56:04.29,0:56:07.04,Default,,0,0,0,,使得你可以定义像这样的过程\r\nDialogue: 0,0:56:08.17,0:56:11.49,Default,,0,0,0,,因此区别就在于你是否定义了一个过程\r\nDialogue: 0,0:56:12.91,0:56:37.60,Default,,0,0,0,,[音乐]\r\nDialogue: 0,0:56:38.05,0:56:41.98,Default,,0,0,0,,信不信由你 你们已经学了足够多的Lisp的知识了\r\nDialogue: 0,0:56:42.78,0:56:45.42,Default,,0,0,0,,现在你基本上可以编写\r\nDialogue: 0,0:56:46.25,0:56:49.63,Default,,0,0,0,,FORTRAN、Basic或者其它语言中一样的\r\nDialogue: 0,0:56:49.66,0:56:51.01,Default,,0,0,0,,数值计算过程了\r\nDialogue: 0,0:56:52.05,0:56:54.76,Default,,0,0,0,,或许你会说 这不可能\r\nDialogue: 0,0:56:54.81,0:56:56.65,Default,,0,0,0,,因为你知道这些语言有\r\nDialogue: 0,0:56:56.65,0:57:00.22,Default,,0,0,0,,像“for”语句和“do-until-whil”语句的东西\r\nDialogue: 0,0:57:00.99,0:57:04.59,Default,,0,0,0,,实际上这些我们一点也用不着\r\nDialogue: 0,0:57:05.05,0:57:07.13,Default,,0,0,0,,本课中我们一点也不会使用这些东西\r\nDialogue: 0,0:57:08.25,0:57:10.16,Default,,0,0,0,,我给你们来个下马威\r\nDialogue: 0,0:57:10.25,0:57:13.61,Default,,0,0,0,,回过头来看看平方根\r\nDialogue: 0,0:57:13.65,0:57:19.03,Default,,0,0,0,,让我们看看亚历山大的Heron提出的平方根算法\r\nDialogue: 0,0:57:19.09,0:57:19.97,Default,,0,0,0,,想想它是怎么说的\r\nDialogue: 0,0:57:20.06,0:57:23.67,Default,,0,0,0,,算法说 为了找到X的平方根的近似值\r\nDialogue: 0,0:57:25.07,0:57:26.16,Default,,0,0,0,,你做出猜测\r\nDialogue: 0,0:57:27.45,0:57:31.88,Default,,0,0,0,,然后通过取guess和X/guess的平均数来改进猜测\r\nDialogue: 0,0:57:32.94,0:57:36.06,Default,,0,0,0,,你不断改进猜测 直到这个猜测足够好\r\nDialogue: 0,0:57:36.72,0:57:38.43,Default,,0,0,0,,我已经提到过这种想法\r\nDialogue: 0,0:57:38.56,0:57:42.24,Default,,0,0,0,,这种想法是说 如果你最初采用的猜测\r\nDialogue: 0,0:57:43.04,0:57:46.91,Default,,0,0,0,,真真切切的等于X的平方根\r\nDialogue: 0,0:57:47.15,0:57:50.06,Default,,0,0,0,,那么G就会等于X/G\r\nDialogue: 0,0:57:52.89,0:57:55.33,Default,,0,0,0,,如果你算出平方根 对其取平均数并不会改变它\r\nDialogue: 0,0:57:55.69,0:57:59.62,Default,,0,0,0,,如果你所采用的G比X的平方根大\r\nDialogue: 0,0:58:00.38,0:58:02.94,Default,,0,0,0,,那么X/G就会比X的平方根小\r\nDialogue: 0,0:58:03.21,0:58:05.37,Default,,0,0,0,,因此当你取G与X/G的平均值时\r\nDialogue: 0,0:58:05.63,0:58:07.57,Default,,0,0,0,,就得到了两者之间的某数\r\nDialogue: 0,0:58:08.96,0:58:12.95,Default,,0,0,0,,同理 若你采用的G过小 答案则会过大\r\nDialogue: 0,0:58:13.12,0:58:14.81,Default,,0,0,0,,如果你采用了一个太大的G\r\nDialogue: 0,0:58:16.32,0:58:18.06,Default,,0,0,0,,如果你的G比X的平方根还要大的话\r\nDialogue: 0,0:58:18.08,0:58:20.35,Default,,0,0,0,,X/G就会比X的平方根还要小\r\nDialogue: 0,0:58:21.23,0:58:23.65,Default,,0,0,0,,因此取平均值使得你总可以得到两者间的某数\r\nDialogue: 0,0:58:24.53,0:58:28.13,Default,,0,0,0,,这不是毫无意义的 它表明\r\nDialogue: 0,0:58:28.17,0:58:31.76,Default,,0,0,0,,事实上 如果G只差X的平方根一点的话\r\nDialogue: 0,0:58:31.81,0:58:37.99,Default,,0,0,0,,G和X/G的平均值就会慢慢的向X的平方根靠近\r\nDialogue: 0,0:58:38.03,0:58:38.99,Default,,0,0,0,,只要你不断的这样做\r\nDialogue: 0,0:58:39.42,0:58:41.18,Default,,0,0,0,,最终就可以不断地靠近\r\nDialogue: 0,0:58:41.71,0:58:42.85,Default,,0,0,0,,另外一个事实则是\r\nDialogue: 0,0:58:43.02,0:58:47.65,Default,,0,0,0,,你总可以使用1作为一个初始猜测值来开始计算\r\nDialogue: 0,0:58:49.23,0:58:51.35,Default,,0,0,0,,它总是朝X的平方根聚拢\r\nDialogue: 0,0:58:52.24,0:58:56.77,Default,,0,0,0,,这就是亚历山大的Heron的连续求平均值法\r\nDialogue: 0,0:58:56.81,0:58:59.21,Default,,0,0,0,,让我们在Lisp中实现\r\nDialogue: 0,0:59:00.57,0:59:02.61,Default,,0,0,0,,中心思想是\r\nDialogue: 0,0:59:02.65,0:59:07.19,Default,,0,0,0,,尝试将guess作为X的平方根的一个猜想意味着什么\r\nDialogue: 0,0:59:08.30,0:59:09.37,Default,,0,0,0,,我来编码\r\nDialogue: 0,0:59:09.79,0:59:25.02,Default,,0,0,0,,定义（try guess x）\r\nDialogue: 0,0:59:26.45,0:59:28.24,Default,,0,0,0,,我们该如何做 我们会说\r\nDialogue: 0,0:59:28.29,0:59:45.26,Default,,0,0,0,,如果猜测精确到可以作为X的平方根\r\nDialogue: 0,0:59:46.54,0:59:49.52,Default,,0,0,0,,那么我们就可以将这个猜测作为答案\r\nDialogue: 0,0:59:51.61,0:59:57.01,Default,,0,0,0,,否则 我们就会尝试改进猜测\r\nDialogue: 0,0:59:58.19,1:00:04.24,Default,,0,0,0,,我们将通过改进这个猜测来作为X的平方根\r\nDialogue: 0,1:00:05.26,1:00:09.33,Default,,0,0,0,,并尝试是否为X平方根\r\nDialogue: 0,1:00:09.36,1:00:12.96,Default,,0,0,0,,闭合try 闭合if 闭合define\r\nDialogue: 0,1:00:13.31,1:00:14.81,Default,,0,0,0,,这就是我们如何尝试一个猜测\r\nDialogue: 0,1:00:15.85,1:00:17.60,Default,,0,0,0,,然后 这个过程的下一步是说\r\nDialogue: 0,1:00:17.73,1:00:21.90,Default,,0,0,0,,为了计算平方根\r\nDialogue: 0,1:00:21.93,1:00:30.17,Default,,0,0,0,,定义计算X的平方根为\r\nDialogue: 0,1:00:30.80,1:00:35.79,Default,,0,0,0,,从1作为X的平方根的一个猜测开始尝试\r\nDialogue: 0,1:00:37.42,1:00:39.59,Default,,0,0,0,,我们必须定义一些其它的东西\r\nDialogue: 0,1:00:40.08,1:00:43.36,Default,,0,0,0,,我们必须说明 一个猜测如何才叫“足够好”\r\nDialogue: 0,1:00:43.84,1:00:45.29,Default,,0,0,0,,我们又该如何改进这个猜测\r\nDialogue: 0,1:00:45.85,1:00:47.10,Default,,0,0,0,,那么让我们来看看\r\nDialogue: 0,1:00:47.39,1:00:54.24,Default,,0,0,0,,而改进一个X的平方根的一个猜测的算法则是\r\nDialogue: 0,1:00:54.64,1:00:57.18,Default,,0,0,0,,取平均数\r\nDialogue: 0,1:00:57.18,1:01:02.16,Default,,0,0,0,,我们取guess和X/guess的平均数\r\nDialogue: 0,1:01:02.99,1:01:04.57,Default,,0,0,0,,这就是我们如何改进一个猜测\r\nDialogue: 0,1:01:05.85,1:01:08.80,Default,,0,0,0,,为了确定一个猜测是否足够精确 我们需要做一下规定\r\nDialogue: 0,1:01:08.86,1:01:11.36,Default,,0,0,0,,假设这个是X的平方根的一个猜测\r\nDialogue: 0,1:01:11.37,1:01:14.03,Default,,0,0,0,,你可能做的一件事就是\r\nDialogue: 0,1:01:14.06,1:01:16.07,Default,,0,0,0,,当你采用这个猜测并将其平方\r\nDialogue: 0,1:01:16.64,1:01:18.41,Default,,0,0,0,,你会得到一个非常接近于X的数\r\nDialogue: 0,1:01:18.59,1:01:21.10,Default,,0,0,0,,而表达这个想法的一种方式是\r\nDialogue: 0,1:01:21.12,1:01:24.31,Default,,0,0,0,,我们用X减去guess的平方\r\nDialogue: 0,1:01:25.15,1:01:27.15,Default,,0,0,0,,并且确认所得结果的绝对值是否\r\nDialogue: 0,1:01:27.20,1:01:32.05,Default,,0,0,0,,比一个由你规定的很小的数还要小\r\nDialogue: 0,1:01:34.70,1:01:41.42,Default,,0,0,0,,因此 我们就有了计算X的平方根的一整套过程\r\nDialogue: 0,1:01:41.47,1:01:43.53,Default,,0,0,0,,我们再来深入观察一下这个结构\r\nDialogue: 0,1:01:47.84,1:01:49.12,Default,,0,0,0,,我搞定了整件事\r\nDialogue: 0,1:01:49.15,1:01:55.44,Default,,0,0,0,,我有一个用于计算X的平方根的记号\r\nDialogue: 0,1:01:55.53,1:01:56.88,Default,,0,0,0,,这是一种模块\r\nDialogue: 0,1:01:57.05,1:01:58.46,Default,,0,0,0,,也是一种黑盒\r\nDialogue: 0,1:01:58.72,1:02:08.02,Default,,0,0,0,,它的定义依赖于如何尝试将一个猜测值作为X的平方根\r\nDialogue: 0,1:02:09.31,1:02:14.10,Default,,0,0,0,,定义try是用来\r\nDialogue: 0,1:02:14.61,1:02:18.03,Default,,0,0,0,,确认某数是否足够精确以及如何去改进该数\r\nDialogue: 0,1:02:18.73,1:02:19.68,Default,,0,0,0,,这是good-enogh?\r\nDialogue: 0,1:02:19.89,1:02:28.85,Default,,0,0,0,,try的定义依赖于good-enough?和improve\r\nDialogue: 0,1:02:30.96,1:02:32.56,Default,,0,0,0,,让我们来看看我填入了些什么\r\nDialogue: 0,1:02:32.71,1:02:34.29,Default,,0,0,0,,如果我向下拓展这棵树\r\nDialogue: 0,1:02:34.73,1:02:38.49,Default,,0,0,0,,good-enough?的定义依赖于abs和square\r\nDialogue: 0,1:02:40.97,1:02:44.13,Default,,0,0,0,,而improve的定义依赖于averaging\r\nDialogue: 0,1:02:45.17,1:02:46.70,Default,,0,0,0,,而其它的都是一些基本运算符\r\nDialogue: 0,1:02:46.72,1:02:48.88,Default,,0,0,0,,平方根的定义依赖于try\r\nDialogue: 0,1:02:48.88,1:02:53.31,Default,,0,0,0,,try的定义依赖于good-enough?和improve\r\nDialogue: 0,1:02:54.01,1:02:55.39,Default,,0,0,0,,甚至依赖于try本身\r\nDialogue: 0,1:02:55.58,1:03:00.86,Default,,0,0,0,,因此try也按照它如何应用于自身而进行定义\r\nDialogue: 0,1:03:02.75,1:03:04.72,Default,,0,0,0,,额 这可能会使你有点糊涂\r\nDialogue: 0,1:03:04.72,1:03:08.16,Default,,0,0,0,,你的高中几何老师或许告诉过你\r\nDialogue: 0,1:03:08.67,1:03:12.57,Default,,0,0,0,,用一个东西自己去定义自己是很不对的\r\nDialogue: 0,1:03:12.88,1:03:13.92,Default,,0,0,0,,因为这根本行不通\r\nDialogue: 0,1:03:13.92,1:03:14.72,Default,,0,0,0,,这（种说法）是错的\r\nDialogue: 0,1:03:16.03,1:03:19.68,Default,,0,0,0,,有时候用一个东西自己来定义自己非常有意义\r\nDialogue: 0,1:03:20.16,1:03:24.38,Default,,0,0,0,,我们来看看这个例子\r\nDialogue: 0,1:03:24.38,1:03:26.89,Default,,0,0,0,,假设我问Lisp：2的平方根是多少\r\nDialogue: 0,1:03:26.91,1:03:30.33,Default,,0,0,0,,我们可以写出它究竟是什么意思\r\nDialogue: 0,1:03:32.65,1:03:34.67,Default,,0,0,0,,2的平方根是什么意思\r\nDialogue: 0,1:03:35.79,1:03:43.61,Default,,0,0,0,,意思就是我将用1作为2的平方根的一个猜测\r\nDialogue: 0,1:03:46.97,1:03:50.92,Default,,0,0,0,,然后我考虑 对于2的平方根来说 1是一个足够好的猜测么\r\nDialogue: 0,1:03:51.65,1:03:53.69,Default,,0,0,0,,这取决于good-enough?是如何判断的\r\nDialogue: 0,1:03:54.61,1:03:56.56,Default,,0,0,0,,本例中 good-enough?会说\r\nDialogue: 0,1:03:56.65,1:03:59.05,Default,,0,0,0,,不 对于2的平方根来说 1不是一个足够好的猜测\r\nDialogue: 0,1:03:59.79,1:04:08.22,Default,,0,0,0,,因此我会继续说 我试试一个改进值\r\nDialogue: 0,1:04:08.64,1:04:12.63,Default,,0,0,0,,改进猜测值1\r\nDialogue: 0,1:04:15.15,1:04:17.46,Default,,0,0,0,,然后将其作为2的平方根的一个猜测\r\nDialogue: 0,1:04:19.13,1:04:22.07,Default,,0,0,0,,改进猜测值1用作2的平方根\r\nDialogue: 0,1:04:22.09,1:04:25.08,Default,,0,0,0,,也就是说我取1和2/1的平均值\r\nDialogue: 0,1:04:27.10,1:04:29.10,Default,,0,0,0,,因此我们将取平均数\r\nDialogue: 0,1:04:29.58,1:04:39.44,Default,,0,0,0,,这段代码将会取1和2/1的平均数\r\nDialogue: 0,1:04:40.83,1:04:42.75,Default,,0,0,0,,那么这段代码\r\nDialogue: 0,1:04:43.85,1:04:46.72,Default,,0,0,0,,我算算 结果是1.5\r\nDialogue: 0,1:04:49.07,1:04:54.40,Default,,0,0,0,,因此这个(sqrt 2)还原到(try 1 2)\r\nDialogue: 0,1:04:54.56,1:05:04.83,Default,,0,0,0,,然后还原到(try 1.5 2)\r\nDialogue: 0,1:05:06.03,1:05:08.06,Default,,0,0,0,,因此这行得通\r\nDialogue: 0,1:05:08.11,1:05:09.52,Default,,0,0,0,,让我们看下剩下的步骤\r\nDialogue: 0,1:05:09.73,1:05:15.00,Default,,0,0,0,,如果我尝试1.5 则会还原到\r\nDialogue: 0,1:05:15.01,1:05:19.05,Default,,0,0,0,,1.5作为2的平方根的猜测 并不是足够好\r\nDialogue: 0,1:05:20.22,1:05:22.00,Default,,0,0,0,,然后又还原到\r\nDialogue: 0,1:05:22.01,1:05:26.17,Default,,0,0,0,,(try (average 1.5 (/ 2 1.5)))\r\nDialogue: 0,1:05:28.29,1:05:30.37,Default,,0,0,0,,平均值是1.333\r\nDialogue: 0,1:05:31.18,1:05:35.24,Default,,0,0,0,,然后整个事又还原到(try 1.3333 2)\r\nDialogue: 0,1:05:35.28,1:05:36.06,Default,,0,0,0,,如此进行下去\r\nDialogue: 0,1:05:38.01,1:05:41.66,Default,,0,0,0,,然后又还原到(good-enough? 1.4)或者其它的\r\nDialogue: 0,1:05:41.73,1:05:44.47,Default,,0,0,0,,然后这个（步骤）会持续进行到\r\nDialogue: 0,1:05:44.85,1:05:47.92,Default,,0,0,0,,good-enough?认为足够好了才停止\r\nDialogue: 0,1:05:47.97,1:05:51.28,Default,,0,0,0,,本例中 是1.4242或者其它的东西\r\nDialogue: 0,1:05:52.51,1:05:56.05,Default,,0,0,0,,因此这个这个过程运行得非常完美\r\nDialogue: 0,1:05:59.93,1:06:03.10,Default,,0,0,0,,这种定义方法叫做“递归定义”\r\nDialogue: 0,1:06:14.40,1:06:20.96,Default,,0,0,0,,进行递归定义将会给你带来无穷威力\r\nDialogue: 0,1:06:21.95,1:06:23.05,Default,,0,0,0,,之前我已提到过\r\nDialogue: 0,1:06:23.09,1:06:27.21,Default,,0,0,0,,递归定义可以在不增加任何负担的前提下\r\nDialogue: 0,1:06:27.25,1:06:28.83,Default,,0,0,0,,仅仅通过调用过程 在达到条件之前\r\nDialogue: 0,1:06:29.73,1:06:33.66,Default,,0,0,0,,完成无限次的计算\r\nDialogue: 0,1:06:35.97,1:06:37.47,Default,,0,0,0,,还有一点要说明的\r\nDialogue: 0,1:06:37.71,1:06:44.21,Default,,0,0,0,,我再在这里给你们演示另外一种平方根的定义方法\r\nDialogue: 0,1:06:44.43,1:06:48.16,Default,,0,0,0,,这两种方法看起来像是一样的\r\nDialogue: 0,1:06:48.40,1:06:51.49,Default,,0,0,0,,在这儿 我把improve、good-enough?、try的定义\r\nDialogue: 0,1:06:51.52,1:06:56.16,Default,,0,0,0,,全都封装在了sqrt里面\r\nDialogue: 0,1:06:56.75,1:07:00.99,Default,,0,0,0,,因此实际上 我们构建了一个平方根盒子\r\nDialogue: 0,1:07:01.81,1:07:08.53,Default,,0,0,0,,我构建了一个其它人可以使用的平方根盒子\r\nDialogue: 0,1:07:08.57,1:07:11.47,Default,,0,0,0,,它们输入36 然后（盒子）输出6\r\nDialogue: 0,1:07:11.81,1:07:13.83,Default,,0,0,0,,但是 盒子里面封装的过程\r\nDialogue: 0,1:07:14.16,1:07:23.85,Default,,0,0,0,,就是try、good-enough?和improve的定义\r\nDialogue: 0,1:07:26.78,1:07:28.35,Default,,0,0,0,,它们都隐藏在盒子里面\r\nDialogue: 0,1:07:28.40,1:07:30.76,Default,,0,0,0,,这样做是因为\r\nDialogue: 0,1:07:31.18,1:07:32.85,Default,,0,0,0,,如果有人正在使用这个平方根\r\nDialogue: 0,1:07:33.21,1:07:34.73,Default,,0,0,0,,如果George正在使用这个平方根\r\nDialogue: 0,1:07:34.75,1:07:37.36,Default,,0,0,0,,George并不会关心\r\nDialogue: 0,1:07:38.29,1:07:40.03,Default,,0,0,0,,当我在实现平方根时\r\nDialogue: 0,1:07:40.21,1:07:44.45,Default,,0,0,0,,我定义了盒子内的那些try、good-enough?和improve过程\r\nDialogue: 0,1:07:46.40,1:07:49.33,Default,,0,0,0,,事实上 Harry可能会实现一个也具有\r\nDialogue: 0,1:07:49.37,1:07:50.96,Default,,0,0,0,,try、good-enough?和improve的立方根盒子\r\nDialogue: 0,1:07:51.44,1:07:53.34,Default,,0,0,0,,因此 为了不让整个系统变得混乱\r\nDialogue: 0,1:07:53.36,1:07:57.66,Default,,0,0,0,,Harry最好把这些内部过程封装在它的立方根过程里\r\nDialogue: 0,1:07:58.40,1:08:00.06,Default,,0,0,0,,这个叫做块结构\r\nDialogue: 0,1:08:00.32,1:08:08.96,Default,,0,0,0,,这是把东西打包到定义内部的一种方法\r\nDialogue: 0,1:08:09.97,1:08:12.96,Default,,0,0,0,,让我们回过头来再看看\r\nDialogue: 0,1:08:13.12,1:08:18.57,Default,,0,0,0,,这种过程的定义读作 定义“sqrt”为\r\nDialogue: 0,1:08:19.87,1:08:21.84,Default,,0,0,0,,那么 在其内部\r\nDialogue: 0,1:08:22.13,1:08:25.49,Default,,0,0,0,,我们已有improve的定义\r\nDialogue: 0,1:08:25.56,1:08:28.88,Default,,0,0,0,,我们已有good-enough?和try的定义\r\nDialogue: 0,1:08:29.73,1:08:32.38,Default,,0,0,0,,以及这些定义的实体\r\nDialogue: 0,1:08:32.48,1:08:35.07,Default,,0,0,0,,我求平方根的定义实体是从1开始尝试\r\nDialogue: 0,1:08:36.08,1:08:39.33,Default,,0,0,0,,注意这里 我不必将X当做参数传递\r\nDialogue: 0,1:08:39.87,1:08:42.32,Default,,0,0,0,,因为它们都在平方根内部\r\nDialogue: 0,1:08:42.84,1:08:44.65,Default,,0,0,0,,它相当于已知这个X了\r\nDialogue: 0,1:08:54.06,1:08:56.37,Default,,0,0,0,,我来总结下\r\nDialogue: 0,1:08:56.49,1:08:59.49,Default,,0,0,0,,我们从表述指令性知识\r\nDialogue: 0,1:08:59.51,1:09:03.18,Default,,0,0,0,,开始学习\r\nDialogue: 0,1:09:04.99,1:09:09.74,Default,,0,0,0,,这张幻灯片总结了一些关于Lisp的知识\r\nDialogue: 0,1:09:09.74,1:09:15.12,Default,,0,0,0,,我们从基本元素如“+”和“*”开始\r\nDialogue: 0,1:09:15.85,1:09:19.50,Default,,0,0,0,,一些用于测试某物小于或等于的谓词\r\nDialogue: 0,1:09:19.52,1:09:22.99,Default,,0,0,0,,事实上 我们正在使用的系统掩盖了很多细节\r\nDialogue: 0,1:09:23.02,1:09:25.85,Default,,0,0,0,,这些并不是系统的基本元素 但这无所谓\r\nDialogue: 0,1:09:26.62,1:09:28.59,Default,,0,0,0,,重要的是我们会把它们当作是基本元素\r\nDialogue: 0,1:09:28.61,1:09:29.81,Default,,0,0,0,,我们不会去研究系统的内部\r\nDialogue: 0,1:09:30.29,1:09:33.15,Default,,0,0,0,,我们也有一些基本数据和一些数\r\nDialogue: 0,1:09:34.62,1:09:37.66,Default,,0,0,0,,我们学习了合成的手段 组合的手段\r\nDialogue: 0,1:09:37.74,1:09:41.37,Default,,0,0,0,,用运算符和运算对象合成函数\r\nDialogue: 0,1:09:41.41,1:09:43.76,Default,,0,0,0,,和构建组合式的基本方法\r\nDialogue: 0,1:09:44.81,1:09:48.43,Default,,0,0,0,,还有一些像是“COND”、“if”和“define”的东西\r\nDialogue: 0,1:09:51.29,1:09:53.69,Default,,0,0,0,,具体来说 关于“define”的重点则是\r\nDialogue: 0,1:09:53.87,1:09:55.71,Default,,0,0,0,,它是一种进行抽象的方法\r\nDialogue: 0,1:09:55.73,1:09:57.70,Default,,0,0,0,,它是我们为某物命名的方法\r\nDialogue: 0,1:09:57.79,1:10:00.30,Default,,0,0,0,,我们之前提到过  从这里也可以看出来\r\nDialogue: 0,1:10:01.57,1:10:06.28,Default,,0,0,0,,有时候 我们需要研究如何通过组合基本数据来得到复合数据\r\nDialogue: 0,1:10:06.56,1:10:12.03,Default,,0,0,0,,以及如何抽象数据 使得你可以在一个更大的环境中\r\nDialogue: 0,1:10:12.06,1:10:13.07,Default,,0,0,0,,将其当作基本数据使用\r\nDialogue: 0,1:10:13.90,1:10:15.87,Default,,0,0,0,,这也是我们的目的所在\r\nDialogue: 0,1:10:16.38,1:10:22.05,Default,,0,0,0,,在我们讨论这个问题之前 下节课我们首先将会讨论\r\nDialogue: 0,1:10:23.26,1:10:26.76,Default,,0,0,0,,我们编写的过程与机器内部\r\nDialogue: 0,1:10:26.88,1:10:30.77,Default,,0,0,0,,进程之间的联系\r\nDialogue: 0,1:10:32.14,1:10:35.98,Default,,0,0,0,,接着 我们将跳出小规模的计算问题\r\nDialogue: 0,1:10:36.38,1:10:39.77,Default,,0,0,0,,来学习如何发挥Lisp的威力\r\nDialogue: 0,1:10:40.08,1:10:44.15,Default,,0,0,0,,来解决更加通用的计算问题\r\nDialogue: 0,1:10:44.81,1:10:46.17,Default,,0,0,0,,好了 大家还有什么问题么\r\nDialogue: 0,1:10:46.75,1:10:52.27,Default,,0,0,0,,学生：在定义A时 如果我们用一个括号将A括起来\r\nDialogue: 0,1:10:52.32,1:10:53.50,Default,,0,0,0,,会与不使用括号不同么？\r\nDialogue: 0,1:10:53.60,1:10:56.88,Default,,0,0,0,,教授：如果我这样写\r\nDialogue: 0,1:10:57.53,1:11:02.13,Default,,0,0,0,,我则会是定义一个过程并命名为A\r\nDialogue: 0,1:11:03.21,1:11:06.85,Default,,0,0,0,,本例中 这个过程没有参数\r\nDialogue: 0,1:11:06.85,1:11:09.61,Default,,0,0,0,,而当我运行它 则会返回5乘以5\r\nDialogue: 0,1:11:11.07,1:11:12.29,Default,,0,0,0,,学生：它们俩完成了相同的事\r\nDialogue: 0,1:11:12.32,1:11:13.92,Default,,0,0,0,,但本质上是否相同？\r\nDialogue: 0,1:11:14.05,1:11:16.63,Default,,0,0,0,,教授：好 的确会有不同 之前的那一个\r\nDialogue: 0,1:11:17.02,1:11:18.35,Default,,0,0,0,,我还是在这里写清楚一点吧\r\nDialogue: 0,1:11:19.13,1:11:23.44,Default,,0,0,0,,我们还是把这个叫做A\r\nDialogue: 0,1:11:24.13,1:11:27.76,Default,,0,0,0,,作为对比 我们假装这里有一个\r\nDialogue: 0,1:11:27.79,1:11:37.56,Default,,0,0,0,,我定义D为5乘以5\r\nDialogue: 0,1:11:40.22,1:11:41.57,Default,,0,0,0,,这两者的区别则是\r\nDialogue: 0,1:11:41.96,1:11:44.24,Default,,0,0,0,,让我们看看它们在Lisp解释器中是怎样的\r\nDialogue: 0,1:11:45.74,1:11:49.13,Default,,0,0,0,,我在Lisp中键入A 返回25\r\nDialogue: 0,1:11:52.83,1:11:57.81,Default,,0,0,0,,如果我仅仅键入D\r\nDialogue: 0,1:11:58.49,1:12:05.55,Default,,0,0,0,,Lisp返回复合过程D\r\nDialogue: 0,1:12:07.12,1:12:09.13,Default,,0,0,0,,因为D就是一个过程\r\nDialogue: 0,1:12:09.69,1:12:12.59,Default,,0,0,0,,我可以运行D 我可以问运行D的结果是什么\r\nDialogue: 0,1:12:12.59,1:12:15.23,Default,,0,0,0,,这是一个没有运算数的组合式\r\nDialogue: 0,1:12:16.45,1:12:19.07,Default,,0,0,0,,我考虑到它没有运算数 所以我在D后面没有键入任何东西\r\nDialogue: 0,1:12:19.39,1:12:21.34,Default,,0,0,0,,Lisp则会说结果是25\r\nDialogue: 0,1:12:23.01,1:12:29.52,Default,,0,0,0,,我再说周全一点 如果我键入 A的运行结果是多少\r\nDialogue: 0,1:12:29.54,1:12:30.57,Default,,0,0,0,,只能得到一个错误\r\nDialogue: 0,1:12:31.79,1:12:35.29,Default,,0,0,0,,跟这里的错误一样\r\nDialogue: 0,1:12:35.33,1:12:40.51,Default,,0,0,0,,这个错误是因为 A的值——25\r\nDialogue: 0,1:12:40.56,1:12:43.24,Default,,0,0,0,,并不是我可以应用于某物的运算符\r\nDialogue: 0,1:12:43.36,1:12:55.05,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\r\nDialogue: 0,1:12:43.37,1:12:55.05,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/FoOTOo/Learning-SICP\r\nDialogue: 0,1:12:49.11,1:12:51.11,Default,,0,0,0,,\r\n"
  },
  {
    "path": "Ass/lec1a.chn.ass",
    "content": "﻿[Script Info]\r\n; Script generated by Aegisub 3.0.2\r\n; http://www.aegisub.org/\r\nTitle: Default Aegisub file\r\nScriptType: v4.00+\r\nWrapStyle: 0\r\nScaledBorderAndShadow: yes\r\nCollisions: Normal\r\nPlayResX: 640\r\nPlayResY: 480\r\nScroll Position: 982\r\nActive Line: 988\r\nAudio URI: lec1a_Rerip_remux.mp4\r\nVideo Zoom Percent: 0.75\r\nVideo File: lec1a_Rerip_remux.mp4\r\nVideo Aspect Ratio: c1.33333\r\nVideo Position: 124661\r\nLast Style Storage: Default\r\nYCbCr Matrix: TV.601\r\n\r\n[V4+ Styles]\r\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\r\nStyle: Default,雅黑宋体,24,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,2,10,10,35,1\r\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\r\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\r\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\r\n\r\n[Events]\r\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\nDialogue: 0,0:00:00.01,0:00:03.77,Declare,,0,0,0,,{\\fad(200,200)}哈尔滨工业大学 IBM技术中心\r\nDialogue: 0,0:00:00.01,0:00:03.77,Declare,,0,0,0,,{\\fad(200,200)\\an2}倾情制作\r\nDialogue: 0,0:00:04.08,0:00:11.36,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\r\nDialogue: 0,0:00:04.08,0:00:11.05,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}字幕&时间轴\\N邓雄飞\\N(Dysprosium)\r\nDialogue: 0,0:00:04.08,0:00:11.05,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}后期&特效\\N蔡钟毓\\N(JohnTitor)\r\nDialogue: 0,0:00:04.08,0:00:11.06,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N匿名\r\nDialogue: 0,0:00:04.08,0:00:11.06,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\r\nDialogue: 0,0:00:14.71,0:00:17.89,Default,,0,0,0,,欢迎大家来一起学习这门计算机科学的基础课程\r\nDialogue: 0,0:00:28.40,0:00:29.85,Default,,0,0,0,,事实上 以这样的方式来表述并不恰当\r\nDialogue: 0,0:00:29.85,0:00:32.34,Default,,0,0,0,,于此来说 计算机科学是个糟糕的名字\r\nDialogue: 0,0:00:32.83,0:00:34.30,Default,,0,0,0,,首先 它不算是一门科学\r\nDialogue: 0,0:00:35.92,0:00:39.47,Default,,0,0,0,,它更应该被称为工程或者是艺术\r\nDialogue: 0,0:00:40.09,0:00:42.91,Default,,0,0,0,,但我们实际上会发现 这个所谓的计算机科学\r\nDialogue: 0,0:00:42.93,0:00:44.97,Default,,0,0,0,,却与魔法一样的有众多神奇之处\r\nDialogue: 0,0:00:45.01,0:00:46.35,Default,,0,0,0,,这些将会在课程中一一体现\r\nDialogue: 0,0:00:47.28,0:00:48.22,Default,,0,0,0,,所以 不能称其为一门科学\r\nDialogue: 0,0:00:49.09,0:00:52.30,Default,,0,0,0,,这门学科和“计算机”也并非紧密相关\r\nDialogue: 0,0:00:53.39,0:00:55.47,Default,,0,0,0,,类似的 就像我们说\r\nDialogue: 0,0:00:55.47,0:01:00.05,Default,,0,0,0,,物理学中并不仅仅有关粒子加速器\r\nDialogue: 0,0:01:00.80,0:01:05.58,Default,,0,0,0,,生物学中并不全然是显微镜和培养皿一样\r\nDialogue: 0,0:01:06.46,0:01:10.25,Default,,0,0,0,,同理\r\nDialogue: 0,0:01:10.31,0:01:14.88,Default,,0,0,0,,几何学中也并不全是介绍如何使用测量仪器\r\nDialogue: 0,0:01:16.48,0:01:19.01,Default,,0,0,0,,事实上 计算机科学和几何学\r\nDialogue: 0,0:01:19.33,0:01:21.45,Default,,0,0,0,,有很多共性\r\nDialogue: 0,0:01:21.45,0:01:22.66,Default,,0,0,0,,首先 几何学\r\nDialogue: 0,0:01:23.02,0:01:24.98,Default,,0,0,0,,只是另一个有个糟糕名字的学科\r\nDialogue: 0,0:01:25.58,0:01:27.85,Default,,0,0,0,,这个名字来自于Gaia 意为土地\r\nDialogue: 0,0:01:27.90,0:01:29.09,Default,,0,0,0,,以及metron 意为测量\r\nDialogue: 0,0:01:29.82,0:01:33.39,Default,,0,0,0,,几何学最初意为测地或者勘探\r\nDialogue: 0,0:01:34.37,0:01:36.89,Default,,0,0,0,,这是因为数千年前的埃及祭司\r\nDialogue: 0,0:01:37.69,0:01:41.69,Default,,0,0,0,,为了计算如何去修复年年被尼罗河的洪水\r\nDialogue: 0,0:01:42.59,0:01:46.33,Default,,0,0,0,,所毁坏的牧田边界\r\nDialogue: 0,0:01:46.35,0:01:48.69,Default,,0,0,0,,而建立了几何学基础\r\nDialogue: 0,0:01:49.47,0:01:50.65,Default,,0,0,0,,而对出于这个目的的埃及人来说\r\nDialogue: 0,0:01:50.65,0:01:53.93,Default,,0,0,0,,几何学的确是掌握对测量仪器的使用\r\nDialogue: 0,0:01:55.63,0:01:58.55,Default,,0,0,0,,现在 我们以为计算机科学就是介绍计算机的使用\r\nDialogue: 0,0:01:58.57,0:02:02.49,Default,,0,0,0,,就正如埃及人认为\r\nDialogue: 0,0:02:02.51,0:02:04.10,Default,,0,0,0,,几何学是介绍如何使用测量仪器的\r\nDialogue: 0,0:02:04.59,0:02:07.37,Default,,0,0,0,,换句话说 任何一门学科起步的时候\r\nDialogue: 0,0:02:07.39,0:02:09.86,Default,,0,0,0,,你都对它了解不深\r\nDialogue: 0,0:02:11.10,0:02:16.64,Default,,0,0,0,,这很容易使你混淆所做的事与所用之物\r\nDialogue: 0,0:02:17.65,0:02:20.30,Default,,0,0,0,,确实 就绝对规模来说\r\nDialogue: 0,0:02:20.30,0:02:24.82,Default,,0,0,0,,我们对计算机科学的实质的了解\r\nDialogue: 0,0:02:24.83,0:02:27.49,Default,,0,0,0,,比埃及人对几何学的了解还少\r\nDialogue: 0,0:02:30.25,0:02:32.64,Default,,0,0,0,,那么 我所谓的计算机科学的本质是什么呢\r\nDialogue: 0,0:02:32.65,0:02:34.41,Default,,0,0,0,,我所谓的几何学本质又是什么呢\r\nDialogue: 0,0:02:34.41,0:02:36.45,Default,,0,0,0,,看 可以确认的是 古埃及人确实使用测量仪器\r\nDialogue: 0,0:02:36.46,0:02:37.67,Default,,0,0,0,,并且已经消失多年\r\nDialogue: 0,0:02:37.69,0:02:41.55,Default,,0,0,0,,但当我们在几千年后回过头来重新审视这段历史\r\nDialogue: 0,0:02:41.57,0:02:41.85,Default,,0,0,0,,我们会说\r\nDialogue: 0,0:02:41.87,0:02:43.64,Default,,0,0,0,,天啊 看他们在做什么\r\nDialogue: 0,0:02:43.71,0:02:45.48,Default,,0,0,0,,他们的工作是多么的重要\r\nDialogue: 0,0:02:45.62,0:02:50.45,Default,,0,0,0,,已经开始对时间和空间进行形式化表述\r\nDialogue: 0,0:02:51.58,0:02:57.53,Default,,0,0,0,,并归纳出一套讨论数学真理的形式化方法\r\nDialogue: 0,0:02:58.01,0:02:59.61,Default,,0,0,0,,这直接导致了公理化方法\r\nDialogue: 0,0:02:59.61,0:03:02.53,Default,,0,0,0,,以及各种现代数学的产生\r\nDialogue: 0,0:03:04.16,0:03:06.90,Default,,0,0,0,,同时也指明了一种精确讨论\r\nDialogue: 0,0:03:07.25,0:03:10.19,Default,,0,0,0,,所谓的描述真理的陈述性知识的方法\r\nDialogue: 0,0:03:12.45,0:03:16.25,Default,,0,0,0,,与此相似的 我认为未来人们会回过头来审视并说\r\nDialogue: 0,0:03:16.27,0:03:19.36,Default,,0,0,0,,啊 这些20世纪的原始人\r\nDialogue: 0,0:03:19.36,0:03:21.20,Default,,0,0,0,,不务正业地玩弄着叫计算机的小玩意\r\nDialogue: 0,0:03:21.77,0:03:26.25,Default,,0,0,0,,但它们真正在做的是开始学习\r\nDialogue: 0,0:03:26.25,0:03:32.55,Default,,0,0,0,,如何去对计算过程进行形式化表述\r\nDialogue: 0,0:03:32.64,0:03:34.13,Default,,0,0,0,,如何去解决问题\r\nDialogue: 0,0:03:39.02,0:03:51.25,Default,,0,0,0,,并结合两者发展一套对问题处理过程精确表述的方法\r\nDialogue: 0,0:03:51.76,0:03:56.03,Default,,0,0,0,,这与讨论真理的几何学形成了对照\r\nDialogue: 0,0:03:56.53,0:03:58.57,Default,,0,0,0,,让我给你们举个例子吧\r\nDialogue: 0,0:04:02.30,0:04:02.69,Default,,0,0,0,,来瞧瞧\r\nDialogue: 0,0:04:02.70,0:04:09.82,Default,,0,0,0,,数学中是这样来定义平方根的:\r\nDialogue: 0,0:04:10.09,0:04:14.35,Default,,0,0,0,,定义X的平方根Y是这样一个数\r\nDialogue: 0,0:04:15.98,0:04:20.38,Default,,0,0,0,,Y的平方等于X 且Y大于等于0\r\nDialogue: 0,0:04:20.43,0:04:22.50,Default,,0,0,0,,这是一个很好的定义\r\nDialogue: 0,0:04:22.88,0:04:25.25,Default,,0,0,0,,但它只告诉了你平方根是什么\r\nDialogue: 0,0:04:25.63,0:04:30.29,Default,,0,0,0,,却没有告诉你如何去求取一个平方根\r\nDialogue: 0,0:04:31.42,0:04:35.90,Default,,0,0,0,,那么我们将其与一条指令性知识做比较\r\nDialogue: 0,0:04:37.13,0:04:39.92,Default,,0,0,0,,你如何去求取一个平方根\r\nDialogue: 0,0:04:39.95,0:04:45.74,Default,,0,0,0,,事实上 这来自于埃及 不太久远的埃及\r\nDialogue: 0,0:04:45.76,0:04:48.88,Default,,0,0,0,,亚历山大的Heron提出的一个算法\r\nDialogue: 0,0:04:49.90,0:04:52.77,Default,,0,0,0,,称作连续取均值求平方根法\r\nDialogue: 0,0:04:52.89,0:04:55.13,Default,,0,0,0,,这个算法是说\r\nDialogue: 0,0:04:55.15,0:04:58.06,Default,,0,0,0,,为了算出平方根\r\nDialogue: 0,0:05:03.34,0:05:08.33,Default,,0,0,0,,首先你应该给出一个猜测值guess 并不断改进\r\nDialogue: 0,0:05:10.19,0:05:11.44,Default,,0,0,0,,改进的方法是通过\r\nDialogue: 0,0:05:11.45,0:05:13.95,Default,,0,0,0,,不断求猜测值guess与X/guess的平均值\r\nDialogue: 0,0:05:14.41,0:05:15.60,Default,,0,0,0,,我们稍后将会讨论\r\nDialogue: 0,0:05:15.61,0:05:17.12,Default,,0,0,0,,为什么这是合理的\r\nDialogue: 0,0:05:17.14,0:05:19.37,Default,,0,0,0,,通过不断改进 直到它足够精确\r\nDialogue: 0,0:05:19.73,0:05:20.85,Default,,0,0,0,,这就是实现方法\r\nDialogue: 0,0:05:20.99,0:05:24.65,Default,,0,0,0,,这也是如何完成一项工作与\r\nDialogue: 0,0:05:24.72,0:05:27.33,Default,,0,0,0,,其对应的陈述性知识的对照\r\nDialogue: 0,0:05:28.05,0:05:29.76,Default,,0,0,0,,这就是一个过程\r\nDialogue: 0,0:05:34.40,0:05:38.25,Default,,0,0,0,,那么 通常来说什么是过程呢？\r\nDialogue: 0,0:05:39.01,0:05:40.14,Default,,0,0,0,,这定义起来非常困难\r\nDialogue: 0,0:05:40.16,0:05:43.72,Default,,0,0,0,,你可以将它象征性地看成一个活在计算机内\r\nDialogue: 0,0:05:44.77,0:05:47.33,Default,,0,0,0,,并且可以完成一些操作的精灵\r\nDialogue: 0,0:05:48.01,0:05:54.11,Default,,0,0,0,,一些被称为程序的规则模式\r\nDialogue: 0,0:05:54.13,0:05:57.98,Default,,0,0,0,,指导着这类过程的进行\r\nDialogue: 0,0:06:01.98,0:06:04.73,Default,,0,0,0,,程序可以被认为是符咒\r\nDialogue: 0,0:06:05.23,0:06:09.40,Default,,0,0,0,,使用程序来控制这些精灵完成一些操作就叫做过程\r\nDialogue: 0,0:06:10.75,0:06:12.75,Default,,0,0,0,,你们知道人人都需要一门魔法语言\r\nDialogue: 0,0:06:12.77,0:06:14.55,Default,,0,0,0,,那些魔术师 真正的魔术师 用远古的阿卡狄亚语\r\nDialogue: 0,0:06:14.57,0:06:18.59,Default,,0,0,0,,或者苏美尔语 或者巴比伦语 或者其它的\r\nDialogue: 0,0:06:18.62,0:06:20.09,Default,,0,0,0,,而我们将用一门叫Lisp的魔法语言\r\nDialogue: 0,0:06:20.13,0:06:22.71,Default,,0,0,0,,来召唤出我们的精灵\r\nDialogue: 0,0:06:24.37,0:06:28.01,Default,,0,0,0,,这门语言是被设计用来\r\nDialogue: 0,0:06:28.57,0:06:31.84,Default,,0,0,0,,编写如咒语般的程序 来指导过程的进行\r\nDialogue: 0,0:06:31.87,0:06:33.91,Default,,0,0,0,,学习Lisp非常容易\r\nDialogue: 0,0:06:33.97,0:06:35.98,Default,,0,0,0,,事实上 我会在几分钟内教会你\r\nDialogue: 0,0:06:36.00,0:06:37.16,Default,,0,0,0,,整个Lisp\r\nDialogue: 0,0:06:37.37,0:06:38.96,Default,,0,0,0,,及其所有的规则\r\nDialogue: 0,0:06:40.77,0:06:43.65,Default,,0,0,0,,你不必感到很惊讶\r\nDialogue: 0,0:06:43.69,0:06:45.87,Default,,0,0,0,,这就像你在学习象棋时\r\nDialogue: 0,0:06:45.90,0:06:47.01,Default,,0,0,0,,认为象棋的规则十分简单一样\r\nDialogue: 0,0:06:47.04,0:06:48.13,Default,,0,0,0,,事实也如此 几分钟内\r\nDialogue: 0,0:06:48.17,0:06:49.70,Default,,0,0,0,,你可以与任何人谈论象棋的规则\r\nDialogue: 0,0:06:50.81,0:06:52.24,Default,,0,0,0,,但是 这全然不等同于说\r\nDialogue: 0,0:06:52.25,0:06:55.37,Default,,0,0,0,,你所知道这些规则所蕴含的东西\r\nDialogue: 0,0:06:55.42,0:06:58.05,Default,,0,0,0,,以及如何利用这些规则去成为象棋大师\r\nDialogue: 0,0:06:58.49,0:06:59.82,Default,,0,0,0,,Lisp也是如此\r\nDialogue: 0,0:07:00.41,0:07:02.18,Default,,0,0,0,,我将在几分钟内道清规则\r\nDialogue: 0,0:07:02.36,0:07:03.55,Default,,0,0,0,,这说起来非常容易\r\nDialogue: 0,0:07:03.62,0:07:07.09,Default,,0,0,0,,但真正困难的是如何运用这些规则\r\nDialogue: 0,0:07:07.32,0:07:10.46,Default,,0,0,0,,以及你如何利用这些规则成为编程大师\r\nDialogue: 0,0:07:12.06,0:07:15.29,Default,,0,0,0,,这些规则的应用将占据我们\r\nDialogue: 0,0:07:15.31,0:07:18.56,Default,,0,0,0,,余下的课程 甚至更多\r\nDialogue: 0,0:07:21.45,0:07:23.11,Default,,0,0,0,,所以 在计算机科学中\r\nDialogue: 0,0:07:24.49,0:07:26.19,Default,,0,0,0,,我们的任务则是\r\nDialogue: 0,0:07:26.21,0:07:30.58,Default,,0,0,0,,形式化这种如有关“怎么做”的指令性知识\r\nDialogue: 0,0:07:30.62,0:07:32.10,Default,,0,0,0,,并将之付诸实际\r\nDialogue: 0,0:07:33.37,0:07:35.39,Default,,0,0,0,,这也便是计算机科学的真正的议题\r\nDialogue: 0,0:07:35.41,0:07:38.36,Default,,0,0,0,,当然 并不是告诉人们如何去求平方根\r\nDialogue: 0,0:07:39.09,0:07:40.06,Default,,0,0,0,,因为如果那是计算机科学的全部的的话\r\nDialogue: 0,0:07:40.09,0:07:41.34,Default,,0,0,0,,就不会有什么大问题了\r\nDialogue: 0,0:07:41.57,0:07:44.05,Default,,0,0,0,,真正的问题来自于当我们尝试\r\nDialogue: 0,0:07:44.08,0:07:46.16,Default,,0,0,0,,构建非常非常大的系统时\r\nDialogue: 0,0:07:46.61,0:07:49.53,Default,,0,0,0,,程序可能会长达数千页\r\nDialogue: 0,0:07:49.58,0:07:53.98,Default,,0,0,0,,长得没有人能马上将其装入脑中\r\nDialogue: 0,0:07:54.73,0:07:58.81,Default,,0,0,0,,而使这些得以实现则是因为\r\nDialogue: 0,0:07:58.86,0:08:18.97,Default,,0,0,0,,我们有在大系统中控制复杂度的技术\r\nDialogue: 0,0:08:20.30,0:08:22.69,Default,,0,0,0,,这些控制复杂度的技术\r\nDialogue: 0,0:08:22.72,0:08:24.17,Default,,0,0,0,,正是我们课程所讨论的\r\nDialogue: 0,0:08:24.65,0:08:25.47,Default,,0,0,0,,从某种意义上来说\r\nDialogue: 0,0:08:25.50,0:08:27.47,Default,,0,0,0,,这也正是计算机科学的关键所在\r\nDialogue: 0,0:08:29.63,0:08:31.89,Default,,0,0,0,,这样说听起来或许很奇怪\r\nDialogue: 0,0:08:31.92,0:08:35.61,Default,,0,0,0,,毕竟 除了计算机科学家外\r\nDialogue: 0,0:08:35.65,0:08:37.82,Default,,0,0,0,,仍然有很多人在做复杂度控制相关的工作\r\nDialogue: 0,0:08:37.84,0:08:41.02,Default,,0,0,0,,一个航班就是一个非常复杂的系统\r\nDialogue: 0,0:08:41.82,0:08:43.79,Default,,0,0,0,,设计它的航空工程师\r\nDialogue: 0,0:08:44.05,0:08:46.13,Default,,0,0,0,,便在处理这个巨大的复杂度\r\nDialogue: 0,0:08:47.09,0:08:50.19,Default,,0,0,0,,但这种复杂度又与\r\nDialogue: 0,0:08:50.75,0:08:52.60,Default,,0,0,0,,计算机科学中的（复杂度）有别\r\nDialogue: 0,0:08:55.18,0:08:57.73,Default,,0,0,0,,从某种意义上来说\r\nDialogue: 0,0:08:57.79,0:09:00.09,Default,,0,0,0,,因为计算机科学不是“现实”的\r\nDialogue: 0,0:09:02.69,0:09:06.62,Default,,0,0,0,,例如 当一名工程师设计物理系统时\r\nDialogue: 0,0:09:07.14,0:09:08.49,Default,,0,0,0,,这些都是由实在的物理部件构成\r\nDialogue: 0,0:09:09.40,0:09:11.18,Default,,0,0,0,,负责的该工作的工程师\r\nDialogue: 0,0:09:11.85,0:09:16.65,Default,,0,0,0,,就得对付系统中的公差、近似值以及噪声\r\nDialogue: 0,0:09:16.67,0:09:19.02,Default,,0,0,0,,譬如说 作为一名电气工程师\r\nDialogue: 0,0:09:19.09,0:09:21.71,Default,,0,0,0,,可以很容易的做一个单极放大器\r\nDialogue: 0,0:09:21.73,0:09:23.03,Default,,0,0,0,,或者是一个双极放大器\r\nDialogue: 0,0:09:23.41,0:09:25.39,Default,,0,0,0,,也可想象将其大量串联\r\nDialogue: 0,0:09:25.45,0:09:26.91,Default,,0,0,0,,来建造一个百万极的放大器\r\nDialogue: 0,0:09:26.99,0:09:28.75,Default,,0,0,0,,但这样做是不可行的\r\nDialogue: 0,0:09:28.98,0:09:32.15,Default,,0,0,0,,因为在远没到百万数量级的时候\r\nDialogue: 0,0:09:32.16,0:09:34.56,Default,,0,0,0,,这种组合方法打从头产生的热噪声\r\nDialogue: 0,0:09:34.57,0:09:36.80,Default,,0,0,0,,会慢慢增强 并使得我们的幸苦付之一炬\r\nDialogue: 0,0:09:39.10,0:09:43.12,Default,,0,0,0,,计算机科学处理的是理想化组件\r\nDialogue: 0,0:09:44.12,0:09:47.63,Default,,0,0,0,,我们对将要结合在一起的\r\nDialogue: 0,0:09:47.65,0:09:49.56,Default,,0,0,0,,程序和数据了如指掌\r\nDialogue: 0,0:09:51.90,0:09:53.20,Default,,0,0,0,,我们不需要去关心公差\r\nDialogue: 0,0:09:53.21,0:09:56.99,Default,,0,0,0,,也就是说 在构建大系统时\r\nDialogue: 0,0:09:58.13,0:10:00.03,Default,,0,0,0,,在我理想和现实之间\r\nDialogue: 0,0:10:00.35,0:10:04.18,Default,,0,0,0,,并不没有太大的不同\r\nDialogue: 0,0:10:05.53,0:10:07.60,Default,,0,0,0,,因为这些部分都是抽象单元\r\nDialogue: 0,0:10:07.63,0:10:10.32,Default,,0,0,0,,可以随心所欲的组合\r\nDialogue: 0,0:10:10.33,0:10:12.39,Default,,0,0,0,,可以据目前所知而自由构建\r\nDialogue: 0,0:10:13.45,0:10:15.50,Default,,0,0,0,,就是与其它的工程不同之处\r\nDialogue: 0,0:10:15.66,0:10:17.42,Default,,0,0,0,,（在其它的工程中）对你所构建系统的约束\r\nDialogue: 0,0:10:17.44,0:10:18.90,Default,,0,0,0,,来自于物理系统以及\r\nDialogue: 0,0:10:18.94,0:10:21.02,Default,,0,0,0,,物理定律 噪声 近似值等\r\nDialogue: 0,0:10:21.21,0:10:25.60,Default,,0,0,0,,而建立大型软件系统时所施加的约束\r\nDialogue: 0,0:10:25.64,0:10:27.58,Default,,0,0,0,,就是对我们大脑的限制\r\nDialogue: 0,0:10:29.12,0:10:29.98,Default,,0,0,0,,从这个角度来看\r\nDialogue: 0,0:10:30.00,0:10:33.67,Default,,0,0,0,,计算机科学就像是工程中的一种抽象形式\r\nDialogue: 0,0:10:33.80,0:10:35.73,Default,,0,0,0,,在这种工程中 我们忽略\r\nDialogue: 0,0:10:35.76,0:10:38.02,Default,,0,0,0,,现实所施加的约束\r\nDialogue: 0,0:10:41.97,0:10:46.15,Default,,0,0,0,,那么 这其中有哪些技术呢\r\nDialogue: 0,0:10:46.28,0:10:48.39,Default,,0,0,0,,计算机科学中并没有特别的技术\r\nDialogue: 0,0:10:50.39,0:10:52.55,Default,,0,0,0,,第一个技术是在很多工程中都使用的\r\nDialogue: 0,0:10:53.36,0:10:58.91,Default,,0,0,0,,被称为“黑盒抽象”的方法\r\nDialogue: 0,0:11:07.71,0:11:12.58,Default,,0,0,0,,即将一些东西组合并封装起来\r\nDialogue: 0,0:11:14.37,0:11:20.09,Default,,0,0,0,,以之前我们提到的求取平方根的方法为例\r\nDialogue: 0,0:11:22.64,0:11:28.53,Default,,0,0,0,,我将这些操作视为一个“盒子”\r\nDialogue: 0,0:11:29.89,0:11:37.52,Default,,0,0,0,,也就是说 为了找到X的平方根\r\nDialogue: 0,0:11:38.86,0:11:41.27,Default,,0,0,0,,或许会有一系列的复杂规则\r\nDialogue: 0,0:11:42.64,0:11:46.69,Default,,0,0,0,,我们将规则封装 输入数据即可获得结果\r\nDialogue: 0,0:11:46.81,0:11:50.06,Default,,0,0,0,,比如说 输入36 然后说36的平方根是多少呢\r\nDialogue: 0,0:11:50.25,0:11:51.46,Default,,0,0,0,,则给出结果 6\r\nDialogue: 0,0:11:53.89,0:11:56.22,Default,,0,0,0,,重点是\r\nDialogue: 0,0:11:56.24,0:12:00.03,Default,,0,0,0,,通过这样的设计\r\nDialogue: 0,0:12:00.06,0:12:04.08,Default,,0,0,0,,可以方便他人的使用\r\nDialogue: 0,0:12:05.10,0:12:09.37,Default,,0,0,0,,例如Goerge想计算A的平方根加上B的平方根\r\nDialogue: 0,0:12:11.34,0:12:14.38,Default,,0,0,0,,他无需了解“盒子”内部的构成\r\nDialogue: 0,0:12:14.43,0:12:15.74,Default,,0,0,0,,而直接可以以模块的形式使用它\r\nDialogue: 0,0:12:15.77,0:12:17.31,Default,,0,0,0,,也可以利用它去构建新的“盒子”\r\nDialogue: 0,0:12:18.45,0:12:24.20,Default,,0,0,0,,例如构建一个 A和B以及一个平方根和或者另一个平方根盒子\r\nDialogue: 0,0:12:24.53,0:12:33.87,Default,,0,0,0,,然后将这些结果加在一起并输出答案\r\nDialogue: 0,0:12:33.96,0:12:38.15,Default,,0,0,0,,如你所见 就我想实现的功能的层面来看\r\nDialogue: 0,0:12:38.92,0:12:40.42,Default,,0,0,0,,对于George来说\r\nDialogue: 0,0:12:40.51,0:12:43.10,Default,,0,0,0,,盒子内部是什么样并不重要\r\nDialogue: 0,0:12:44.19,0:12:47.25,Default,,0,0,0,,例如 以下这些说法都没什么问题\r\nDialogue: 0,0:12:47.27,0:12:50.43,Default,,0,0,0,,我说求X的平方根\r\nDialogue: 0,0:12:50.61,0:12:52.27,Default,,0,0,0,,也可以说计算Y的平方根\r\nDialogue: 0,0:12:52.72,0:12:55.62,Default,,0,0,0,,或者其它任何数的平方根\r\nDialogue: 0,0:12:56.70,0:13:02.35,Default,,0,0,0,,黑盒抽象的基本规则是\r\nDialogue: 0,0:13:03.53,0:13:06.44,Default,,0,0,0,,将处理过程放入盒子里以隐藏细节\r\nDialogue: 0,0:13:07.60,0:13:10.99,Default,,0,0,0,,这样做的原因则是你可以脱身去构建更大的盒子\r\nDialogue: 0,0:13:12.05,0:13:14.57,Default,,0,0,0,,现在 除了隐藏细节外\r\nDialogue: 0,0:13:14.59,0:13:18.41,Default,,0,0,0,,使用黑盒抽象还有另外一个原因\r\nDialogue: 0,0:13:18.48,0:13:25.02,Default,,0,0,0,,有的时候 你想要用你的方法去完成一件事\r\nDialogue: 0,0:13:25.04,0:13:26.88,Default,,0,0,0,,你的方法\r\nDialogue: 0,0:13:28.44,0:13:30.79,Default,,0,0,0,,就是一个通法的具体实例\r\nDialogue: 0,0:13:31.16,0:13:34.57,Default,,0,0,0,,同时 你也希望你的表述方式能够具有普遍性\r\nDialogue: 0,0:13:35.57,0:13:37.93,Default,,0,0,0,,我们接着用实例来说明\r\nDialogue: 0,0:13:37.97,0:13:38.86,Default,,0,0,0,,继续刚才关于平方根的讨论\r\nDialogue: 0,0:13:38.89,0:13:42.16,Default,,0,0,0,,让我们回过头再来看看\r\nDialogue: 0,0:13:42.19,0:13:43.75,Default,,0,0,0,,求平方根的算法\r\nDialogue: 0,0:13:44.16,0:13:45.62,Default,,0,0,0,,想一想之前是怎么说的\r\nDialogue: 0,0:13:45.79,0:13:49.82,Default,,0,0,0,,为了求解 首先要作出猜测\r\nDialogue: 0,0:13:50.62,0:13:54.84,Default,,0,0,0,,然后基于这个猜测 做出持续不断的改进\r\nDialogue: 0,0:13:55.66,0:14:00.14,Default,,0,0,0,,因此就存在一个找到某个到结果的通用方法\r\nDialogue: 0,0:14:01.15,0:14:04.00,Default,,0,0,0,,就是持续不断地改进结果\r\nDialogue: 0,0:14:04.16,0:14:10.25,Default,,0,0,0,,求取不动点的方法有很多\r\nDialogue: 0,0:14:10.97,0:14:13.23,Default,,0,0,0,,这种方法只是其中的一个特例\r\nDialogue: 0,0:14:14.57,0:14:16.59,Default,,0,0,0,,每个函数都有一个不动点\r\nDialogue: 0,0:14:17.13,0:14:26.03,Default,,0,0,0,,函数的不动点是一个值\r\nDialogue: 0,0:14:26.13,0:14:31.79,Default,,0,0,0,,F的不动点Y满足F(Y)=Y\r\nDialogue: 0,0:14:32.97,0:14:40.89,Default,,0,0,0,,首先要做是做出一个猜测\r\nDialogue: 0,0:14:42.00,0:14:45.85,Default,,0,0,0,,在迭代函数F时不会改变的东西则是我们所求的结果\r\nDialogue: 0,0:14:45.96,0:14:49.45,Default,,0,0,0,,我会不断迭代函数F直到结果不会有很大改变\r\nDialogue: 0,0:14:50.05,0:14:51.93,Default,,0,0,0,,这就是一个通法\r\nDialogue: 0,0:14:52.24,0:14:56.17,Default,,0,0,0,,因此 为了计算X的平方根\r\nDialogue: 0,0:14:56.24,0:15:03.45,Default,,0,0,0,,我可以试着找到Y与X/Y的平均值函数的不动点\r\nDialogue: 0,0:15:03.55,0:15:07.52,Default,,0,0,0,,因为如果我真有一个等于X平方根的Y\r\nDialogue: 0,0:15:08.01,0:15:11.80,Default,,0,0,0,,那么Y和X/Y应为同一值\r\nDialogue: 0,0:15:12.00,0:15:13.90,Default,,0,0,0,,它们俩都是X的平方根\r\nDialogue: 0,0:15:14.86,0:15:18.85,Default,,0,0,0,,因为X除根号X得根号X\r\nDialogue: 0,0:15:19.09,0:15:21.84,Default,,0,0,0,,如果平均值Y等于X的平方根\r\nDialogue: 0,0:15:22.25,0:15:25.21,Default,,0,0,0,,那么这个平均值就不会改变\r\nDialogue: 0,0:15:25.98,0:15:28.93,Default,,0,0,0,,因此X的平方根即是某一特定函数的不动点\r\nDialogue: 0,0:15:30.09,0:15:33.85,Default,,0,0,0,,现在 我将要描述\r\nDialogue: 0,0:15:33.98,0:15:36.42,Default,,0,0,0,,寻找不动点的通法\r\nDialogue: 0,0:15:36.57,0:15:40.13,Default,,0,0,0,,我所希望做的就是\r\nDialogue: 0,0:15:41.02,0:15:46.45,Default,,0,0,0,,用我自己的语言定义一个可以获得不动点的“盒子”\r\nDialogue: 0,0:15:49.58,0:15:52.19,Default,,0,0,0,,正如我可以定义一个输出平方根的盒子一样\r\nDialogue: 0,0:15:52.21,0:15:55.18,Default,,0,0,0,,我想要用自己的语言来表述\r\nDialogue: 0,0:15:56.08,0:16:01.37,Default,,0,0,0,,因此 对于这种“怎么做”的指令性知识\r\nDialogue: 0,0:16:01.42,0:16:03.21,Default,,0,0,0,,我不仅是想表达具体应该如何求平方根\r\nDialogue: 0,0:16:03.58,0:16:05.60,Default,,0,0,0,,我也希望能够表述更加通用问题\r\nDialogue: 0,0:16:05.66,0:16:08.27,Default,,0,0,0,,例如 怎么求取不动点\r\nDialogue: 0,0:16:09.82,0:16:12.25,Default,,0,0,0,,让我们再回过头来看看之前的幻灯片\r\nDialogue: 0,0:16:15.02,0:16:23.28,Default,,0,0,0,,不但如何去求取一个不动点\r\nDialogue: 0,0:16:23.33,0:16:25.32,Default,,0,0,0,,是一种指令性知识\r\nDialogue: 0,0:16:26.25,0:16:27.39,Default,,0,0,0,,在这下面 这里\r\nDialogue: 0,0:16:27.42,0:16:30.32,Default,,0,0,0,,这儿还有另一种指令性知识 说的是\r\nDialogue: 0,0:16:30.41,0:16:35.85,Default,,0,0,0,,计算平方根的一种方法就是应用找不动点的方法\r\nDialogue: 0,0:16:36.17,0:16:38.89,Default,,0,0,0,,如果 也想要表述这种指令性知识\r\nDialogue: 0,0:16:39.74,0:16:40.70,Default,,0,0,0,,那结果会是什么样呢？\r\nDialogue: 0,0:16:40.73,0:16:44.90,Default,,0,0,0,,这个不动点盒子可能会是这样\r\nDialogue: 0,0:16:45.76,0:16:58.21,Default,,0,0,0,,如果我输入一个函数 该函数从Y映射到Y和X/Y的平均值\r\nDialogue: 0,0:16:59.77,0:17:06.23,Default,,0,0,0,,然后我们将会得到求不动点的盒子就是求平方根的一个方法\r\nDialogue: 0,0:17:08.91,0:17:10.24,Default,,0,0,0,,因此在这些我们构建的盒子中\r\nDialogue: 0,0:17:10.27,0:17:15.07,Default,,0,0,0,,输入和输出都不局限于数字\r\nDialogue: 0,0:17:16.40,0:17:18.54,Default,,0,0,0,,我们将要构建能够\r\nDialogue: 0,0:17:18.67,0:17:21.34,Default,,0,0,0,,找到平方根计算方法的盒子\r\nDialogue: 0,0:17:22.22,0:17:25.85,Default,,0,0,0,,我输入的是一个函数\r\nDialogue: 0,0:17:26.49,0:17:29.29,Default,,0,0,0,,比如Y映射到Y和X/Y的平均值的函数\r\nDialogue: 0,0:17:29.71,0:17:31.49,Default,,0,0,0,,我们之所以采用这种方式是希望\r\nDialogue: 0,0:17:32.21,0:17:35.60,Default,,0,0,0,,输入是一个过程 输出也是一个过程\r\nDialogue: 0,0:17:35.63,0:17:38.61,Default,,0,0,0,,如我们所见 一个过程输出了另一个过程\r\nDialogue: 0,0:17:39.31,0:17:41.10,Default,,0,0,0,,之所以这样做是因为\r\nDialogue: 0,0:17:41.52,0:17:46.27,Default,,0,0,0,,我们将通过程序来讨论指令性知识\r\nDialogue: 0,0:17:48.00,0:17:49.93,Default,,0,0,0,,这种处理方式很强大\r\nDialogue: 0,0:17:49.93,0:17:52.13,Default,,0,0,0,,我们将可以基于此来讨论其它类型的知识\r\nDialogue: 0,0:17:53.42,0:17:56.52,Default,,0,0,0,,实际上 我们讨论的是一种生成过程的过程\r\nDialogue: 0,0:17:57.10,0:18:00.34,Default,,0,0,0,,一种生成通法的通法\r\nDialogue: 0,0:18:03.57,0:18:08.24,Default,,0,0,0,,那么 我们将主要讨论三个主题的内容\r\nDialogue: 0,0:18:08.25,0:18:09.69,Default,,0,0,0,,而首个主题则是\r\nDialogue: 0,0:18:09.74,0:18:10.94,Default,,0,0,0,,黑盒抽象\r\nDialogue: 0,0:18:10.97,0:18:13.31,Default,,0,0,0,,让我们稍稍深入一点\r\nDialogue: 0,0:18:15.12,0:18:24.04,Default,,0,0,0,,我们将讨论\r\nDialogue: 0,0:18:24.08,0:18:26.72,Default,,0,0,0,,Lisp是如何通过基本对象建立起来的\r\nDialogue: 0,0:18:27.36,0:18:29.20,Default,,0,0,0,,以及Lisp的构成\r\nDialogue: 0,0:18:29.49,0:18:33.58,Default,,0,0,0,,接下来 将会涉及到一些基本过程和基础数据\r\nDialogue: 0,0:18:36.16,0:18:37.04,Default,,0,0,0,,然后我们将会看到\r\nDialogue: 0,0:18:37.05,0:18:38.77,Default,,0,0,0,,我们如何使用这些基本对象\r\nDialogue: 0,0:18:38.81,0:18:40.76,Default,,0,0,0,,并把它们组合起来构建更复杂的东西\r\nDialogue: 0,0:18:41.45,0:18:42.92,Default,,0,0,0,,及相应的组合方法\r\nDialogue: 0,0:18:43.20,0:18:46.30,Default,,0,0,0,,后续将讨论各种进行组合的方法以及\r\nDialogue: 0,0:18:46.45,0:18:50.48,Default,,0,0,0,,如何用基本过程来构建更复杂的过程\r\nDialogue: 0,0:18:50.96,0:18:54.43,Default,,0,0,0,,同时 我们也将看到如何将基本数据组合成复合数据\r\nDialogue: 0,0:18:56.21,0:18:59.34,Default,,0,0,0,,然后我们将会介绍如何对复合数据\r\nDialogue: 0,0:18:59.79,0:19:01.29,Default,,0,0,0,,如何将它们抽象出来\r\nDialogue: 0,0:19:02.91,0:19:04.97,Default,,0,0,0,,如何用黑盒对它们进行封装\r\nDialogue: 0,0:19:05.04,0:19:07.73,Default,,0,0,0,,使得你可以将它们作为组件用于更复杂的东西\r\nDialogue: 0,0:19:08.16,0:19:10.93,Default,,0,0,0,,我们会发现这些都是通过定义程序\r\nDialogue: 0,0:19:11.52,0:19:14.79,Default,,0,0,0,,以及一种处理复合数据的数据抽象技术完成的\r\nDialogue: 0,0:19:15.61,0:19:17.36,Default,,0,0,0,,最重要的是\r\nDialogue: 0,0:19:17.92,0:19:21.49,Default,,0,0,0,,我们可以从中了解到专家是如何工作的\r\nDialogue: 0,0:19:21.61,0:19:27.12,Default,,0,0,0,,对于找不动点的方法来讲\r\nDialogue: 0,0:19:27.15,0:19:28.64,Default,,0,0,0,,找平方根的方式是它的一个特例\r\nDialogue: 0,0:19:28.69,0:19:30.87,Default,,0,0,0,,你如何表述完成工作中所存在的通用模式呢？\r\nDialogue: 0,0:19:31.90,0:19:34.41,Default,,0,0,0,,我们将会使用\r\nDialogue: 0,0:19:34.59,0:19:35.63,Default,,0,0,0,,之前已经提到过的\r\nDialogue: 0,0:19:35.66,0:19:37.30,Default,,0,0,0,,某种叫做高阶过程的东西\r\nDialogue: 0,0:19:37.34,0:19:42.05,Default,,0,0,0,,也就是说 它的输入、输出和它本身都是过程\r\nDialogue: 0,0:19:42.96,0:19:44.86,Default,,0,0,0,,我们将会看到一些有趣的东西\r\nDialogue: 0,0:19:44.86,0:19:48.49,Default,,0,0,0,,随着学习的深入 将会越发抽象\r\nDialogue: 0,0:19:48.80,0:19:50.31,Default,,0,0,0,,那么将会发现\r\nDialogue: 0,0:19:50.43,0:19:53.61,Default,,0,0,0,,我们认为是数据和我们认为是过程之间的\r\nDialogue: 0,0:19:53.63,0:19:57.80,Default,,0,0,0,,分界线将变得模糊到难以置信的程度\r\nDialogue: 0,0:20:02.89,0:20:07.12,Default,,0,0,0,,这便是我们的第一个主题 黑盒抽象\r\nDialogue: 0,0:20:07.12,0:20:08.62,Default,,0,0,0,,让我们来看看第二个主题\r\nDialogue: 0,0:20:11.10,0:20:13.88,Default,,0,0,0,,这样说吧\r\nDialogue: 0,0:20:13.89,0:20:18.09,Default,,0,0,0,,假设我想表达某个想法\r\nDialogue: 0,0:20:19.42,0:20:22.51,Default,,0,0,0,,请注意 我们讨论的是想法\r\nDialogue: 0,0:20:22.91,0:20:25.53,Default,,0,0,0,,比如说\r\nDialogue: 0,0:20:26.41,0:20:35.12,Default,,0,0,0,,我想将某个元素与另两个元素之和相乘\r\nDialogue: 0,0:20:36.09,0:20:37.93,Default,,0,0,0,,举例来说\r\nDialogue: 0,0:20:38.11,0:20:41.52,Default,,0,0,0,,我用1和3（之和）乘2 得8\r\nDialogue: 0,0:20:42.03,0:20:45.11,Default,,0,0,0,,但我这里想讨论的是关于线性组合的基本想法\r\nDialogue: 0,0:20:45.44,0:20:47.98,Default,,0,0,0,,是说你可以将两个元素的和乘以另一个元素\r\nDialogue: 0,0:20:49.28,0:20:51.01,Default,,0,0,0,,在数集内思考这个问题是很容易的\r\nDialogue: 0,0:20:51.05,0:20:55.41,Default,,0,0,0,,但假设我想将这个想法应用于\r\nDialogue: 0,0:20:56.08,0:20:58.58,Default,,0,0,0,,对两向量a1和a2相加\r\nDialogue: 0,0:20:59.89,0:21:03.26,Default,,0,0,0,,乘以某一因子x然后得到另一向量\r\nDialogue: 0,0:21:03.33,0:21:09.75,Default,,0,0,0,,我甚至可以说 若a1和a2皆为多项式\r\nDialogue: 0,0:21:11.07,0:21:13.90,Default,,0,0,0,,我想对这两个多项式求和\r\nDialogue: 0,0:21:13.92,0:21:16.86,Default,,0,0,0,,然后乘以2得到一个多项式\r\nDialogue: 0,0:21:20.16,0:21:23.83,Default,,0,0,0,,同理 a1或a2也可以是电信号\r\nDialogue: 0,0:21:24.56,0:21:27.77,Default,,0,0,0,,我想将二个信号加和\r\nDialogue: 0,0:21:27.81,0:21:30.27,Default,,0,0,0,,并将结果放入一个放大器\r\nDialogue: 0,0:21:30.28,0:21:33.03,Default,,0,0,0,,用一个类似于2的因子乘以它们\r\nDialogue: 0,0:21:33.82,0:21:36.93,Default,,0,0,0,,这种想法的基本点是 我希望用一个通用记号表示它们\r\nDialogue: 0,0:21:38.32,0:21:45.42,Default,,0,0,0,,假如我们的语言可以很好的表述这类想法\r\nDialogue: 0,0:21:47.07,0:21:49.31,Default,,0,0,0,,如果真可以这样的话\r\nDialogue: 0,0:21:50.65,0:21:52.09,Default,,0,0,0,,我将会以这样的方式表述\r\nDialogue: 0,0:21:54.99,0:22:00.41,Default,,0,0,0,,用x乘以a1和a2的和\r\nDialogue: 0,0:22:02.80,0:22:05.07,Default,,0,0,0,,更进一步 我希望做更抽象更基本的表述\r\nDialogue: 0,0:22:06.03,0:22:09.23,Default,,0,0,0,,使其可以适应各个不同类型的a1和a2\r\nDialogue: 0,0:22:10.03,0:22:11.58,Default,,0,0,0,,现在回过头来想想 似乎有点问题\r\nDialogue: 0,0:22:11.58,0:22:16.17,Default,,0,0,0,,毕竟 对两个数字和两个多项式进行加和运算\r\nDialogue: 0,0:22:16.21,0:22:18.33,Default,,0,0,0,,所用的基本操作\r\nDialogue: 0,0:22:18.38,0:22:22.98,Default,,0,0,0,,在机器内部显然是不同的\r\nDialogue: 0,0:22:23.29,0:22:27.49,Default,,0,0,0,,对两个电信号或声波加和也有同样的问题\r\nDialogue: 0,0:22:27.89,0:22:32.53,Default,,0,0,0,,无论怎样 对不同类型的元素进行求和运算\r\nDialogue: 0,0:22:32.87,0:22:34.25,Default,,0,0,0,,总是需要使用不同的方法\r\nDialogue: 0,0:22:37.09,0:22:38.64,Default,,0,0,0,,现在 为了构建这样一个系统\r\nDialogue: 0,0:22:38.78,0:22:40.67,Default,,0,0,0,,我们将如何使用这些知识呢？\r\nDialogue: 0,0:22:41.20,0:22:44.41,Default,,0,0,0,,如何在各种方法中进行选择？\r\nDialogue: 0,0:22:44.56,0:22:48.42,Default,,0,0,0,,而如果明天George又想出了一种新类型的对象\r\nDialogue: 0,0:22:48.45,0:22:50.32,Default,,0,0,0,,并将它用于加和以及乘积\r\nDialogue: 0,0:22:51.01,0:22:53.32,Default,,0,0,0,,我又该如何把这个新类型引入到系统中\r\nDialogue: 0,0:22:53.52,0:22:55.68,Default,,0,0,0,,而且能够做到不把已有的系统弄得一团糟？\r\nDialogue: 0,0:22:57.81,0:23:00.54,Default,,0,0,0,,这便是我们的第二大主题\r\nDialogue: 0,0:23:00.57,0:23:03.16,Default,,0,0,0,,控制复杂度的方法\r\nDialogue: 0,0:23:03.84,0:23:08.43,Default,,0,0,0,,我们实现的方法是按照约定来实现相应的接口\r\nDialogue: 0,0:23:17.44,0:23:20.21,Default,,0,0,0,,并以此将各部分组合起来\r\nDialogue: 0,0:23:20.25,0:23:22.04,Default,,0,0,0,,就如同电气工程中\r\nDialogue: 0,0:23:22.94,0:23:25.39,Default,,0,0,0,,人们为连接器规定标准阻抗\r\nDialogue: 0,0:23:26.16,0:23:28.62,Default,,0,0,0,,如果用符合这个标准的东西来构建系统\r\nDialogue: 0,0:23:28.67,0:23:30.40,Default,,0,0,0,,你就知道你可以把各个部件组合在一起\r\nDialogue: 0,0:23:32.78,0:23:35.68,Default,,0,0,0,,这就是我们将要讨论的第二个主题：约定接口\r\nDialogue: 0,0:23:35.73,0:23:40.94,Default,,0,0,0,,如我之前提到的\r\nDialogue: 0,0:23:40.97,0:23:42.22,Default,,0,0,0,,接下来我们将讨论通用操作中的问题\r\nDialogue: 0,0:23:42.59,0:23:47.28,Default,,0,0,0,,例如对各种不同类型数据进行均适用的加法操作\r\nDialogue: 0,0:23:52.61,0:23:54.57,Default,,0,0,0,,随后则会讨论通用操作\r\nDialogue: 0,0:23:54.61,0:23:56.99,Default,,0,0,0,,然后我们将讨论大型架构问题\r\nDialogue: 0,0:23:58.32,0:24:00.83,Default,,0,0,0,,如果通过对现实世界的复杂系统建模\r\nDialogue: 0,0:24:01.02,0:24:04.89,Default,,0,0,0,,来构建大型程序\r\nDialogue: 0,0:24:05.53,0:24:06.53,Default,,0,0,0,,我们将看到 在构建这样的系统时\r\nDialogue: 0,0:24:06.57,0:24:11.81,Default,,0,0,0,,有两种非常重要的方法\r\nDialogue: 0,0:24:11.85,0:24:13.90,Default,,0,0,0,,其一是面向对象编程\r\nDialogue: 0,0:24:14.09,0:24:18.94,Default,,0,0,0,,在这种模式中 你把你的系统想象成一个社区\r\nDialogue: 0,0:24:19.37,0:24:22.36,Default,,0,0,0,,社区中的各个部分都是通过相互间传递消息联系起来的\r\nDialogue: 0,0:24:23.44,0:24:27.81,Default,,0,0,0,,其二是关于聚集的操作 称作“流”\r\nDialogue: 0,0:24:27.98,0:24:31.50,Default,,0,0,0,,使用这种方式构建大型系统\r\nDialogue: 0,0:24:31.50,0:24:35.29,Default,,0,0,0,,类似于电气工程师构造大型电气系统\r\nDialogue: 0,0:24:38.93,0:24:40.49,Default,,0,0,0,,这就是我们的第二个话题\r\nDialogue: 0,0:24:43.37,0:24:45.93,Default,,0,0,0,,现在 我们将要讨论第三个话题\r\nDialogue: 0,0:24:45.95,0:24:49.70,Default,,0,0,0,,控制复杂度的第三个技术\r\nDialogue: 0,0:24:49.74,0:24:50.94,Default,,0,0,0,,便是定义新的语言\r\nDialogue: 0,0:24:51.69,0:24:55.42,Default,,0,0,0,,因为有时 当你有点受不了设计的复杂度时\r\nDialogue: 0,0:24:55.47,0:24:59.69,Default,,0,0,0,,你可以通过定义一门新的语言来控制系统复杂度\r\nDialogue: 0,0:25:01.41,0:25:05.60,Default,,0,0,0,,新语言的设计意图是为了强调系统的某个方面\r\nDialogue: 0,0:25:05.79,0:25:09.36,Default,,0,0,0,,它一方面隐藏了部分细节 另一方面则但强调一些其他的细节\r\nDialogue: 0,0:25:12.99,0:25:15.93,Default,,0,0,0,,这部分将是课程中最神奇的部分\r\nDialogue: 0,0:25:16.03,0:25:21.20,Default,,0,0,0,,我们将开始于构建新的计算机语言\r\nDialogue: 0,0:25:21.82,0:25:26.30,Default,,0,0,0,,实际上我们首先要完成的工作已经内建于Lisp之中了\r\nDialogue: 0,0:25:29.23,0:25:34.02,Default,,0,0,0,,我们将展现如何用Lisp来解释Lisp\r\nDialogue: 0,0:25:34.29,0:25:36.94,Default,,0,0,0,,这是一个非常类似于自循环的过程\r\nDialogue: 0,0:25:36.96,0:25:39.92,Default,,0,0,0,,这与（Lisp中）一个神奇的符号有关\r\nDialogue: 0,0:25:40.97,0:25:46.38,Default,,0,0,0,,解释Lisp的步骤是\r\nDialogue: 0,0:25:46.57,0:25:47.71,Default,,0,0,0,,应用和求值——这两大步骤的轮转\r\nDialogue: 0,0:25:47.89,0:25:50.87,Default,,0,0,0,,这两者不断地互相交替进行\r\nDialogue: 0,0:25:52.54,0:25:54.24,Default,,0,0,0,,接下来 我们将看到其余神奇的东西\r\nDialogue: 0,0:25:54.25,0:25:56.85,Default,,0,0,0,,譬如另一种魔法符号\r\nDialogue: 0,0:25:57.12,0:26:01.52,Default,,0,0,0,,一种叫做Y运算符的东西\r\nDialogue: 0,0:26:01.55,0:26:06.45,Default,,0,0,0,,某种意义上 它在过程式语言中用于 表达无限\r\nDialogue: 0,0:26:06.51,0:26:07.44,Default,,0,0,0,,我们也会谈论到它\r\nDialogue: 0,0:26:08.40,0:26:13.73,Default,,0,0,0,,总之 这部分课程被称作“元语言抽象”\r\nDialogue: 0,0:26:16.17,0:26:26.23,Default,,0,0,0,,主要讨论如何构建一门新语言\r\nDialogue: 0,0:26:30.22,0:26:35.71,Default,,0,0,0,,如我所言 我们将从了解解释的过程开始\r\nDialogue: 0,0:26:35.74,0:26:42.12,Default,,0,0,0,,随后则一起讨论应用-求值循环和构建Lisp\r\nDialogue: 0,0:26:42.16,0:26:44.17,Default,,0,0,0,,你将发现这种方法具有相当的普遍性\r\nDialogue: 0,0:26:44.37,0:26:48.26,Default,,0,0,0,,我们将用同样的技术去构建一门全完不同的语言\r\nDialogue: 0,0:26:48.53,0:26:50.31,Default,,0,0,0,,一种所谓的逻辑编程语言\r\nDialogue: 0,0:26:50.53,0:26:54.83,Default,,0,0,0,,一种无关具有输入和输出的过程\r\nDialogue: 0,0:26:54.86,0:26:57.25,Default,,0,0,0,,而仅关注元素之间关系的语言\r\nDialogue: 0,0:26:57.31,0:27:03.92,Default,,0,0,0,,最终 我们将讨论如何将这些东西\r\nDialogue: 0,0:27:03.95,0:27:05.60,Default,,0,0,0,,实实在在的实现在简单的机器上\r\nDialogue: 0,0:27:05.65,0:27:08.39,Default,,0,0,0,,比如说这个\r\nDialogue: 0,0:27:09.13,0:27:12.14,Default,,0,0,0,,如图所示的芯片\r\nDialogue: 0,0:27:12.16,0:27:17.47,Default,,0,0,0,,就是我们在硬件部分谈及的Lisp解释器\r\nDialogue: 0,0:27:20.88,0:27:23.79,Default,,0,0,0,,这三大主题就是本课的提纲\r\nDialogue: 0,0:27:24.88,0:27:29.41,Default,,0,0,0,,黑盒抽象 约定接口 元语言抽象\r\nDialogue: 0,0:27:31.58,0:27:33.57,Default,,0,0,0,,好 先休息一会儿 然后正式开始\r\nDialogue: 0,0:27:52.19,0:28:03.42,Default,,0,0,0,,[音乐]\r\nDialogue: 0,0:28:03.92,0:28:06.84,Default,,0,0,0,,现在让我们正式开始学习Lisp\r\nDialogue: 0,0:28:08.06,0:28:10.75,Default,,0,0,0,,事实上 我们将开始学习一些非常重要的内容\r\nDialogue: 0,0:28:10.80,0:28:14.33,Default,,0,0,0,,在这门课程中最重要的 不是Lisp本身\r\nDialogue: 0,0:28:14.38,0:28:18.41,Default,,0,0,0,,而是一种的通用框架体系\r\nDialogue: 0,0:28:18.62,0:28:21.89,Default,,0,0,0,,我们用它来组织我之前提到的语言\r\nDialogue: 0,0:28:22.12,0:28:25.10,Default,,0,0,0,,当有人要向你展示一门新语言\r\nDialogue: 0,0:28:25.13,0:28:26.16,Default,,0,0,0,,你应该问他\r\nDialogue: 0,0:28:26.19,0:28:32.87,Default,,0,0,0,,（构成语言的）基本元素有哪些？\r\nDialogue: 0,0:28:37.50,0:28:38.78,Default,,0,0,0,,这门语言使用哪些基本元素？\r\nDialogue: 0,0:28:38.96,0:28:43.53,Default,,0,0,0,,你是如何将这些元素组合在一起的？\r\nDialogue: 0,0:28:43.68,0:28:47.42,Default,,0,0,0,,组合的方法是什么？\r\nDialogue: 0,0:28:50.17,0:28:54.18,Default,,0,0,0,,允许你将这些基本元素整合在一起\r\nDialogue: 0,0:28:54.37,0:28:56.51,Default,,0,0,0,,以构建更大的对象的又是什么？\r\nDialogue: 0,0:28:58.01,0:28:59.61,Default,,0,0,0,,把东西构建在一起的方法是什么？\r\nDialogue: 0,0:29:01.39,0:29:05.69,Default,,0,0,0,,以及 抽象的方法是什么？\r\nDialogue: 0,0:29:08.35,0:29:16.85,Default,,0,0,0,,我们如何利用这些元素并把它们封装成盒子？\r\nDialogue: 0,0:29:16.88,0:29:19.66,Default,,0,0,0,,我们如何为它们命名使得我们可以\r\nDialogue: 0,0:29:19.68,0:29:23.85,Default,,0,0,0,,把它们当作基本元素来用于构建更复杂的东西？\r\nDialogue: 0,0:29:23.89,0:29:25.66,Default,,0,0,0,,等等 等等 等等\r\nDialogue: 0,0:29:26.89,0:29:28.08,Default,,0,0,0,,因此 当有人告诉你\r\nDialogue: 0,0:29:28.09,0:29:29.55,Default,,0,0,0,,嘿 我发明了一种新的计算机语言\r\nDialogue: 0,0:29:30.86,0:29:34.70,Default,,0,0,0,,你不应该问 用你的语言编写求逆矩阵需要多少代码\r\nDialogue: 0,0:29:35.73,0:29:36.88,Default,,0,0,0,,这是风马牛不相及的\r\nDialogue: 0,0:29:37.39,0:29:42.30,Default,,0,0,0,,如果该语言没有内建了矩阵或者类似的东西\r\nDialogue: 0,0:29:42.33,0:29:43.37,Default,,0,0,0,,那你就应该问他\r\nDialogue: 0,0:29:43.37,0:29:46.03,Default,,0,0,0,,应该如何构建矩阵？\r\nDialogue: 0,0:29:46.05,0:29:48.47,Default,,0,0,0,,如何通过组合来构建？\r\nDialogue: 0,0:29:48.62,0:29:50.71,Default,,0,0,0,,如何对其进行抽象\r\nDialogue: 0,0:29:51.68,0:29:54.21,Default,,0,0,0,,把它作为基本元素\r\nDialogue: 0,0:29:54.22,0:29:56.52,Default,,0,0,0,,来构建更复杂的东西？\r\nDialogue: 0,0:29:58.75,0:30:04.61,Default,,0,0,0,,我们将了解到Lisp的一些基本数据和基本过程\r\nDialogue: 0,0:30:05.25,0:30:07.50,Default,,0,0,0,,好吧 这次是真的开始了\r\nDialogue: 0,0:30:07.55,0:30:14.89,Default,,0,0,0,,这里有一个Lisp的基本数据 数字3\r\nDialogue: 0,0:30:16.27,0:30:19.87,Default,,0,0,0,,事实上 如果打破沙锅问到底的话 这不是数字3\r\nDialogue: 0,0:30:19.93,0:30:25.57,Default,,0,0,0,,这只是一个符号 用以代表柏拉图观念下的数字3的\r\nDialogue: 0,0:30:26.67,0:30:28.93,Default,,0,0,0,,这又是另一个\r\nDialogue: 0,0:30:30.48,0:30:36.06,Default,,0,0,0,,这个是Lisp中又一个基本数据 17.4\r\nDialogue: 0,0:30:36.08,0:30:39.42,Default,,0,0,0,,又或者说 代表17.4\r\nDialogue: 0,0:30:40.99,0:30:44.48,Default,,0,0,0,,这儿还有一个5\r\nDialogue: 0,0:30:46.86,0:30:52.21,Default,,0,0,0,,然后这儿又有一个内建于Lisp的基本对象“+”\r\nDialogue: 0,0:30:52.25,0:30:55.68,Default,,0,0,0,,如果又要继续深究的话\r\nDialogue: 0,0:30:55.71,0:31:00.47,Default,,0,0,0,,这只是一个名字 代表对元素进行加和的基本方法而已\r\nDialogue: 0,0:31:00.53,0:31:02.53,Default,,0,0,0,,就像这个是柏拉图式的3\r\nDialogue: 0,0:31:02.61,0:31:09.32,Default,,0,0,0,,这也只是一个代表柏拉图观念下的将某些元素加和起来\r\nDialogue: 0,0:31:10.32,0:31:11.98,Default,,0,0,0,,这些都是基本元素\r\nDialogue: 0,0:31:12.14,0:31:13.76,Default,,0,0,0,,我可以将它们放在一起\r\nDialogue: 0,0:31:14.14,0:31:18.29,Default,,0,0,0,,我可以说 3加17.4加5的和是多少\r\nDialogue: 0,0:31:18.69,0:31:21.31,Default,,0,0,0,,这等同于说\r\nDialogue: 0,0:31:21.33,0:31:27.71,Default,,0,0,0,,让我们把求和运算符应用于这三个数\r\nDialogue: 0,0:31:27.74,0:31:31.15,Default,,0,0,0,,我可以得到什么呢 是8 是17 还是25.4\r\nDialogue: 0,0:31:34.43,0:31:38.05,Default,,0,0,0,,因此 我可以问Lisp这个的值是多少\r\nDialogue: 0,0:31:38.94,0:31:40.77,Default,,0,0,0,,（表达式）返回25.4\r\nDialogue: 0,0:31:43.58,0:31:44.83,Default,,0,0,0,,介绍一些术语吧\r\nDialogue: 0,0:31:44.88,0:31:51.47,Default,,0,0,0,,我所写的这些东西就叫做组合式\r\nDialogue: 0,0:31:56.88,0:32:01.94,Default,,0,0,0,,通常 一个组合式是由运算符\r\nDialogue: 0,0:32:03.39,0:32:04.72,Default,,0,0,0,,这些就是运算符\r\nDialogue: 0,0:32:09.71,0:32:12.05,Default,,0,0,0,,和应用该运算符的运算对象组成\r\nDialogue: 0,0:32:13.25,0:32:14.54,Default,,0,0,0,,这些是运算对象\r\nDialogue: 0,0:32:21.89,0:32:23.79,Default,,0,0,0,,当然 我可以完成更复杂的事\r\nDialogue: 0,0:32:23.82,0:32:28.56,Default,,0,0,0,,我可以使之更复杂是因为 这些运算对象\r\nDialogue: 0,0:32:29.52,0:32:31.09,Default,,0,0,0,,通常来说 也可以是组合式\r\nDialogue: 0,0:32:31.15,0:32:44.47,Default,,0,0,0,,比如 3加上5乘以6乘以8乘以2的积的和是多少\r\nDialogue: 0,0:32:45.66,0:32:52.16,Default,,0,0,0,,而我应该得到 我算一下 30 40 43\r\nDialogue: 0,0:32:52.73,0:32:54.81,Default,,0,0,0,,因此Lisp会返回这个表达式的值是43\r\nDialogue: 0,0:32:56.56,0:33:02.80,Default,,0,0,0,,后续我们将看到构造组合式是组合的基本需求\r\nDialogue: 0,0:33:04.65,0:33:09.22,Default,,0,0,0,,你所看到的这些语法\r\nDialogue: 0,0:33:10.56,0:33:13.04,Default,,0,0,0,,就是Lisp用的所谓的前缀表示法\r\nDialogue: 0,0:33:16.22,0:33:25.21,Default,,0,0,0,,意即操作符在操作数的左端\r\nDialogue: 0,0:33:25.47,0:33:26.48,Default,,0,0,0,,这只是个约定\r\nDialogue: 0,0:33:27.66,0:33:29.77,Default,,0,0,0,,注意 这些都被括起来了\r\nDialogue: 0,0:33:30.08,0:33:32.32,Default,,0,0,0,,这些括号使得它们区别开来\r\nDialogue: 0,0:33:32.32,0:33:36.99,Default,,0,0,0,,因此只要看看这个 我就可以知道这个是运算符\r\nDialogue: 0,0:33:37.01,0:33:40.99,Default,,0,0,0,,以及这有1个 2个 3个 4个运算对象\r\nDialogue: 0,0:33:42.38,0:33:47.97,Default,,0,0,0,,而且我也可以发现第二个运算对象是个组合式\r\nDialogue: 0,0:33:48.88,0:33:51.55,Default,,0,0,0,,该组合式有一个运算符和两个运算对象\r\nDialogue: 0,0:33:52.43,0:33:54.27,Default,,0,0,0,,Lisp中的括号 有点或者非常不同于\r\nDialogue: 0,0:33:54.61,0:33:57.71,Default,,0,0,0,,通常数学中的括号\r\nDialogue: 0,0:33:57.77,0:34:00.11,Default,,0,0,0,,数学中 我们常将其用于分组\r\nDialogue: 0,0:34:01.21,0:34:03.75,Default,,0,0,0,,如果有时你忘了闭合括号 但其他人能理解你的意图\r\nDialogue: 0,0:34:03.77,0:34:05.56,Default,,0,0,0,,这也无关紧要\r\nDialogue: 0,0:34:05.76,0:34:08.51,Default,,0,0,0,,通常的 你多加了括号也无所谓\r\nDialogue: 0,0:34:08.86,0:34:10.94,Default,,0,0,0,,因为这样只会使得分组更加明确\r\nDialogue: 0,0:34:10.96,0:34:11.77,Default,,0,0,0,,Lisp可不像这样\r\nDialogue: 0,0:34:13.12,0:34:15.37,Default,,0,0,0,,Lisp中你既不能不闭合括号\r\nDialogue: 0,0:34:16.38,0:34:18.56,Default,,0,0,0,,亦不能添加多余的括号\r\nDialogue: 0,0:34:19.33,0:34:21.28,Default,,0,0,0,,因为加括号总是意味着\r\nDialogue: 0,0:34:21.37,0:34:27.05,Default,,0,0,0,,确切的来说 所括之物是一个组合式\r\nDialogue: 0,0:34:27.09,0:34:28.81,Default,,0,0,0,,表示将运算符应用于运算对象\r\nDialogue: 0,0:34:29.04,0:34:32.62,Default,,0,0,0,,如果我不闭合这个括号\r\nDialogue: 0,0:34:32.65,0:34:33.96,Default,,0,0,0,,这个就变成其它的意思了\r\nDialogue: 0,0:34:35.41,0:34:37.25,Default,,0,0,0,,事实上 我们可以这么来理解这个问题\r\nDialogue: 0,0:34:37.41,0:34:41.65,Default,,0,0,0,,把我写的这些东西想作一个树\r\nDialogue: 0,0:34:42.37,0:34:47.30,Default,,0,0,0,,这个组合式实际上是一个树 树具有一个“+”\r\nDialogue: 0,0:34:47.37,0:34:54.46,Default,,0,0,0,,以及 一个3和一些其它的东西和一个8 还有一个2\r\nDialogue: 0,0:34:54.48,0:34:56.35,Default,,0,0,0,,而这里的其它的东西\r\nDialogue: 0,0:34:56.35,0:35:03.22,Default,,0,0,0,,它本身是一个有一个“*”一个5和一个6的子树\r\nDialogue: 0,0:35:03.95,0:35:05.53,Default,,0,0,0,,我们可以这样认为\r\nDialogue: 0,0:35:05.55,0:35:09.00,Default,,0,0,0,,我们只是在构建这些树而已\r\nDialogue: 0,0:35:09.21,0:35:15.10,Default,,0,0,0,,括号只是将这种二维结构写作线性字符串\r\nDialogue: 0,0:35:15.79,0:35:17.34,Default,,0,0,0,,的一种方法罢了\r\nDialogue: 0,0:35:19.23,0:35:23.81,Default,,0,0,0,,因为至少在Lisp发明时 人们还在用电传打字机或者打孔卡\r\nDialogue: 0,0:35:24.17,0:35:25.60,Default,,0,0,0,,这种记法方便多了\r\nDialogue: 0,0:35:25.97,0:35:30.52,Default,,0,0,0,,如果Lisp是在当下被发明的 语法可能会像树那样\r\nDialogue: 0,0:35:31.76,0:35:35.07,Default,,0,0,0,,那么 让我们看看在计算机里面它究竟是什么样\r\nDialogue: 0,0:35:36.29,0:35:39.37,Default,,0,0,0,,这里有个Lisp解释套件\r\nDialogue: 0,0:35:39.41,0:35:40.43,Default,,0,0,0,,这是个编辑器\r\nDialogue: 0,0:35:41.13,0:35:44.86,Default,,0,0,0,,我将要在上方写一些表达式并让Lisp对其求值\r\nDialogue: 0,0:35:45.12,0:35:46.75,Default,,0,0,0,,比如 我可以问Lisp\r\nDialogue: 0,0:35:46.83,0:35:48.53,Default,,0,0,0,,这个符号的值是多少\r\nDialogue: 0,0:35:49.44,0:35:50.50,Default,,0,0,0,,我键入3\r\nDialogue: 0,0:35:50.57,0:35:52.20,Default,,0,0,0,,然后叫Lisp对其求值\r\nDialogue: 0,0:35:52.32,0:35:54.77,Default,,0,0,0,,然后你就会看到Lisp在下面返回了一些信息\r\nDialogue: 0,0:35:55.39,0:35:56.84,Default,,0,0,0,,这个值就是3\r\nDialogue: 0,0:35:57.58,0:36:04.96,Default,,0,0,0,,我也可以问 3加上4加上8的和是多少\r\nDialogue: 0,0:36:06.45,0:36:08.05,Default,,0,0,0,,键入这个组合式\r\nDialogue: 0,0:36:08.93,0:36:10.66,Default,,0,0,0,,让Lisp对其求值\r\nDialogue: 0,0:36:14.49,0:36:15.68,Default,,0,0,0,,返回15\r\nDialogue: 0,0:36:16.57,0:36:18.80,Default,,0,0,0,,我可以键入一些更复杂的东西\r\nDialogue: 0,0:36:19.25,0:36:34.14,Default,,0,0,0,,将3乘以7加19.5的和的乘积求和得多少\r\nDialogue: 0,0:36:35.21,0:36:38.00,Default,,0,0,0,,你会发现Lisp内建了一些功能\r\nDialogue: 0,0:36:38.01,0:36:39.76,Default,,0,0,0,,帮你跟踪这些括号\r\nDialogue: 0,0:36:39.77,0:36:42.13,Default,,0,0,0,,看我键入下一个右圆括号\r\nDialogue: 0,0:36:42.21,0:36:45.01,Default,,0,0,0,,用于闭合以“*”开头的那个组合式\r\nDialogue: 0,0:36:45.52,0:36:47.30,Default,,0,0,0,,开头的那个左括号会闪一下\r\nDialogue: 0,0:36:47.76,0:36:49.69,Default,,0,0,0,,我把这些括号擦去 再示范一次\r\nDialogue: 0,0:36:50.14,0:36:52.70,Default,,0,0,0,,键入右括号 闭合了“+”组合式\r\nDialogue: 0,0:36:53.58,0:36:56.41,Default,,0,0,0,,再键入右括号 闭合了“*”组合式\r\nDialogue: 0,0:36:57.90,0:37:00.76,Default,,0,0,0,,现在我又回到了加 我将它们与4相加\r\nDialogue: 0,0:37:01.66,0:37:02.69,Default,,0,0,0,,闭合了“+”组合式\r\nDialogue: 0,0:37:02.73,0:37:07.07,Default,,0,0,0,,现在我补全了组合式 然后我问Lisp它们的值是多少\r\nDialogue: 0,0:37:07.26,0:37:11.66,Default,,0,0,0,,这种内建于各种Lisp系统的\r\nDialogue: 0,0:37:11.76,0:37:13.29,Default,,0,0,0,,括号匹配工具帮你跟进（括号匹配）\r\nDialogue: 0,0:37:13.36,0:37:16.55,Default,,0,0,0,,因为手工闭合这些括号太辛苦了\r\nDialogue: 0,0:37:16.81,0:37:21.20,Default,,0,0,0,,这又是另外一种保持括号跟进的约定\r\nDialogue: 0,0:37:21.25,0:37:23.68,Default,,0,0,0,,我另外写一个复杂的组合式\r\nDialogue: 0,0:37:24.77,0:37:34.00,Default,,0,0,0,,将3和5的积与某个元素求和\r\nDialogue: 0,0:37:34.03,0:37:35.23,Default,,0,0,0,,现在我将要缩进\r\nDialogue: 0,0:37:35.28,0:37:39.85,Default,,0,0,0,,使得这些运算对象都是垂直书写的\r\nDialogue: 0,0:37:40.30,0:37:45.65,Default,,0,0,0,,将这些加上47乘以\r\nDialogue: 0,0:37:47.02,0:37:54.59,Default,,0,0,0,,恩…… 47乘以20和6.8的差\r\nDialogue: 0,0:37:54.62,0:37:57.09,Default,,0,0,0,,意即从20中减去6.8\r\nDialogue: 0,0:37:58.97,0:38:00.19,Default,,0,0,0,,然后 这个括号闭合了\r\nDialogue: 0,0:38:00.22,0:38:03.47,Default,,0,0,0,,闭合“-” 闭合“*”\r\nDialogue: 0,0:38:03.76,0:38:05.42,Default,,0,0,0,,现在 我们再写一个运算符\r\nDialogue: 0,0:38:05.44,0:38:09.49,Default,,0,0,0,,Lisp编辑器自动缩进到正确的位置\r\nDialogue: 0,0:38:10.40,0:38:11.50,Default,,0,0,0,,来帮助我保持跟进\r\nDialogue: 0,0:38:12.61,0:38:14.09,Default,,0,0,0,,我再示范一次\r\nDialogue: 0,0:38:14.13,0:38:15.89,Default,,0,0,0,,这样就又闭合了最后一个括号\r\nDialogue: 0,0:38:16.25,0:38:17.71,Default,,0,0,0,,它匹配了这个“+”（的括号）\r\nDialogue: 0,0:38:20.40,0:38:22.64,Default,,0,0,0,,现在我想问 这个的值是多少\r\nDialogue: 0,0:38:23.87,0:38:29.28,Default,,0,0,0,,因此 这两件事 缩进到正确的位置\r\nDialogue: 0,0:38:29.31,0:38:30.86,Default,,0,0,0,,也就是所谓的美观的输出\r\nDialogue: 0,0:38:31.55,0:38:33.58,Default,,0,0,0,,以及闭合提示\r\nDialogue: 0,0:38:33.89,0:38:37.73,Default,,0,0,0,,是许多Lisp系统所内建用于帮你保持跟进的工具\r\nDialogue: 0,0:38:37.76,0:38:39.01,Default,,0,0,0,,你应该学习如何使用它们\r\nDialogue: 0,0:38:41.52,0:38:43.17,Default,,0,0,0,,好 这些都是基本的内容\r\nDialogue: 0,0:38:44.73,0:38:46.31,Default,,0,0,0,,这就是一种组合的方法\r\nDialogue: 0,0:38:46.33,0:38:47.93,Default,,0,0,0,,现在让我们来看看抽象的方法\r\nDialogue: 0,0:38:49.44,0:38:53.84,Default,,0,0,0,,我希望我能够写一些像这样的组合式\r\nDialogue: 0,0:38:53.85,0:38:55.77,Default,,0,0,0,,将它抽象化并给它命名\r\nDialogue: 0,0:38:55.81,0:38:57.26,Default,,0,0,0,,使得我可以将其作为一个（我们语言的）元素\r\nDialogue: 0,0:38:57.31,0:38:59.92,Default,,0,0,0,,在Lisp中 我可以用“define”来实现\r\nDialogue: 0,0:39:01.17,0:39:02.43,Default,,0,0,0,,比如说\r\nDialogue: 0,0:39:02.73,0:39:15.05,Default,,0,0,0,,定义A为5乘以5\r\nDialogue: 0,0:39:18.40,0:39:22.35,Default,,0,0,0,,现在我可以问Lisp\r\nDialogue: 0,0:39:22.38,0:39:26.01,Default,,0,0,0,,A和A的乘积是多少\r\nDialogue: 0,0:39:27.18,0:39:29.81,Default,,0,0,0,,这个是25所以这个就是625\r\nDialogue: 0,0:39:31.97,0:39:36.01,Default,,0,0,0,,但更重要的则是 我现在可以使用A\r\nDialogue: 0,0:39:36.21,0:39:37.92,Default,,0,0,0,,我已经在这个组合式里面用过了\r\nDialogue: 0,0:39:38.41,0:39:43.55,Default,,0,0,0,,但我也可以在更复杂的组合式里面使用它\r\nDialogue: 0,0:39:43.58,0:39:50.93,Default,,0,0,0,,我也可以说 定义B为\r\nDialogue: 0,0:39:50.97,0:39:57.45,Default,,0,0,0,,A与5乘以A的积的和\r\nDialogue: 0,0:39:59.44,0:40:00.72,Default,,0,0,0,,闭合“+”\r\nDialogue: 0,0:40:03.45,0:40:05.85,Default,,0,0,0,,让我们来看看它在计算机中是怎样的吧\r\nDialogue: 0,0:40:07.28,0:40:10.68,Default,,0,0,0,,我就像黑板上写的那样键入就可以了\r\nDialogue: 0,0:40:10.83,0:40:21.73,Default,,0,0,0,,我告诉Lisp\r\nDialogue: 0,0:40:23.74,0:40:25.38,Default,,0,0,0,,定义A为5乘以5的积\r\nDialogue: 0,0:40:25.52,0:40:28.94,Default,,0,0,0,,注意Lisp在下方回应了一个A\r\nDialogue: 0,0:40:29.09,0:40:31.38,Default,,0,0,0,,通常来说 你如果在Lisp中键入了一个定义\r\nDialogue: 0,0:40:31.50,0:40:35.02,Default,,0,0,0,,它返回被定义的符号\r\nDialogue: 0,0:40:35.63,0:40:39.66,Default,,0,0,0,,现在我问Lisp A乘以A的积是多少\r\nDialogue: 0,0:40:42.81,0:40:44.33,Default,,0,0,0,,Lisp返回625\r\nDialogue: 0,0:40:46.05,0:41:00.34,Default,,0,0,0,,我也可以定义B为A加上5乘以A的积的和\r\nDialogue: 0,0:41:00.48,0:41:05.70,Default,,0,0,0,,闭合“*” 闭合“+” 闭合“define”\r\nDialogue: 0,0:41:07.63,0:41:10.37,Default,,0,0,0,,Lisp在下方正常返回B\r\nDialogue: 0,0:41:11.04,0:41:13.24,Default,,0,0,0,,现在我可以问Lisp B的值是多少\r\nDialogue: 0,0:41:17.18,0:41:18.88,Default,,0,0,0,,我也可以问一些更复杂的事\r\nDialogue: 0,0:41:18.93,0:41:26.69,Default,,0,0,0,,比如A加上B除以5的商的和是多少\r\nDialogue: 0,0:41:26.73,0:41:30.25,Default,,0,0,0,,这个“/”是另一个基本运算符 代表除\r\nDialogue: 0,0:41:30.38,0:41:32.78,Default,,0,0,0,,我让B除以5 并加在A上\r\nDialogue: 0,0:41:33.65,0:41:35.23,Default,,0,0,0,,Lisp正常返回55\r\nDialogue: 0,0:41:36.57,0:41:37.92,Default,,0,0,0,,就像这样\r\nDialogue: 0,0:41:39.82,0:41:43.40,Default,,0,0,0,,这是定义东西的基本方法\r\nDialogue: 0,0:41:43.44,0:41:49.02,Default,,0,0,0,,这是最简单的命名方法 但并不是很强大\r\nDialogue: 0,0:41:50.06,0:41:51.60,Default,,0,0,0,,注意我们讨论的是通用方法\r\nDialogue: 0,0:41:51.84,0:41:53.37,Default,,0,0,0,,因此我真正想定义的是\r\nDialogue: 0,0:41:53.57,0:41:57.68,Default,,0,0,0,,一种通用方法 可以\r\nDialogue: 0,0:41:58.11,0:42:17.53,Default,,0,0,0,,得到 5乘5 6乘6 1001乘1001 1001.7乘1001.7\r\nDialogue: 0,0:42:17.76,0:42:24.16,Default,,0,0,0,,我想给一个数与其自身相乘这种想法一个名字\r\nDialogue: 0,0:42:28.48,0:42:30.11,Default,,0,0,0,,你应该知道 这叫做平方\r\nDialogue: 0,0:42:31.69,0:42:35.63,Default,,0,0,0,,而在Lisp中我应该这样实现\r\nDialogue: 0,0:42:37.97,0:42:56.25,Default,,0,0,0,,定义 square某个叫x的东西 为 将x乘以x自己\r\nDialogue: 0,0:42:57.87,0:43:01.12,Default,,0,0,0,,定义完毕后 我可以问Lisp\r\nDialogue: 0,0:43:01.12,0:43:05.49,Default,,0,0,0,,比如 10的平方是多少\r\nDialogue: 0,0:43:06.67,0:43:07.87,Default,,0,0,0,,Lisp返回100\r\nDialogue: 0,0:43:10.70,0:43:14.24,Default,,0,0,0,,让我们深入讨论一下\r\nDialogue: 0,0:43:15.29,0:43:16.88,Default,,0,0,0,,这儿是square的定义\r\nDialogue: 0,0:43:17.50,0:43:22.55,Default,,0,0,0,,square某个元素 即是将该元素进行自乘\r\nDialogue: 0,0:43:23.69,0:43:25.34,Default,,0,0,0,,这里的x\r\nDialogue: 0,0:43:26.29,0:43:27.81,Default,,0,0,0,,应该算是一种代词\r\nDialogue: 0,0:43:27.87,0:43:29.53,Default,,0,0,0,,指代了我要做平方的元素\r\nDialogue: 0,0:43:31.49,0:43:37.41,Default,,0,0,0,,实际上我将其乘以x 即是乘以它自己\r\nDialogue: 0,0:43:42.22,0:43:48.27,Default,,0,0,0,,这些就是定义一个过程的记法\r\nDialogue: 0,0:43:48.29,0:43:50.29,Default,,0,0,0,,这样说可能把你搞糊涂了\r\nDialogue: 0,0:43:50.81,0:43:53.97,Default,,0,0,0,,因为这就像我在用square一样\r\nDialogue: 0,0:43:54.00,0:43:56.80,Default,,0,0,0,,但如果我说x的平方根或者10的平方根\r\nDialogue: 0,0:43:57.55,0:44:00.81,Default,,0,0,0,,并没有说清楚我对什么做了定义\r\nDialogue: 0,0:44:03.10,0:44:04.91,Default,,0,0,0,,所以让我换个方式来进行定义\r\nDialogue: 0,0:44:05.74,0:44:08.21,Default,,0,0,0,,这样可以清楚的看到定义的具体内容\r\nDialogue: 0,0:44:08.54,0:44:29.39,Default,,0,0,0,,我定义“square”为“(lambda (x) (* x x))”\r\nDialogue: 0,0:44:36.56,0:44:42.05,Default,,0,0,0,,这里 我定义square就像我某命名为A一样\r\nDialogue: 0,0:44:43.23,0:44:44.72,Default,,0,0,0,,我定义square\r\nDialogue: 0,0:44:44.75,0:44:48.39,Default,,0,0,0,,这里 我把这个组合式的值命名为A\r\nDialogue: 0,0:44:49.29,0:44:52.41,Default,,0,0,0,,在这里 我把这个东西命名为square\r\nDialogue: 0,0:44:52.43,0:44:53.44,Default,,0,0,0,,以lambda开头\r\nDialogue: 0,0:44:53.45,0:44:56.77,Default,,0,0,0,,lambda在Lisp中用以构建一个过程\r\nDialogue: 0,0:45:00.24,0:45:02.91,Default,,0,0,0,,请仔细看一下幻灯片上的内容\r\nDialogue: 0,0:45:04.27,0:45:05.81,Default,,0,0,0,,这个定义读作\r\nDialogue: 0,0:45:05.85,0:45:10.33,Default,,0,0,0,,将square定义为\r\nDialogue: 0,0:45:12.78,0:45:13.97,Default,,0,0,0,,一个由lambda构造的\r\nDialogue: 0,0:45:14.06,0:45:17.49,Default,,0,0,0,,一个有带有参数x的过程\r\nDialogue: 0,0:45:19.26,0:45:24.09,Default,,0,0,0,,而该过程返回将x自乘的结果\r\nDialogue: 0,0:45:24.97,0:45:33.12,Default,,0,0,0,,一般来讲 这是最佳的定义方式\r\nDialogue: 0,0:45:33.41,0:45:35.20,Default,,0,0,0,,因为这个更加方便一点\r\nDialogue: 0,0:45:35.21,0:45:38.67,Default,,0,0,0,,但是也别忘了它实质上也是这个\r\nDialogue: 0,0:45:38.86,0:45:41.41,Default,,0,0,0,,事实上 就Lisp解释器而言\r\nDialogue: 0,0:45:41.61,0:45:45.55,Default,,0,0,0,,这两种方法没有区别\r\nDialogue: 0,0:45:46.51,0:45:53.29,Default,,0,0,0,,换句话说 这只是一种语法糖\r\nDialogue: 0,0:45:54.41,0:45:55.80,Default,,0,0,0,,语法糖的意思就是\r\nDialogue: 0,0:45:56.35,0:46:00.83,Default,,0,0,0,,这种形式输入更方便一些\r\nDialogue: 0,0:46:01.12,0:46:06.11,Default,,0,0,0,,这只是这下面的有lambda的表达式的语法糖而已\r\nDialogue: 0,0:46:07.31,0:46:10.62,Default,,0,0,0,,你应该记住\r\nDialogue: 0,0:46:10.80,0:46:13.87,Default,,0,0,0,,当我这样写的时候 其实是在对某个东西进行命名\r\nDialogue: 0,0:46:14.46,0:46:16.22,Default,,0,0,0,,我将其命名为square\r\nDialogue: 0,0:46:16.24,0:46:19.90,Default,,0,0,0,,square代表一个构建好的过程\r\nDialogue: 0,0:46:21.20,0:46:23.90,Default,,0,0,0,,让我们看看在计算机里面又是 怎样的吧\r\nDialogue: 0,0:46:24.78,0:46:35.95,Default,,0,0,0,,定义“(square x)”为x乘以x的积\r\nDialogue: 0,0:46:49.65,0:46:52.32,Default,,0,0,0,,将它送入Lisp\r\nDialogue: 0,0:46:53.49,0:46:53.92,Default,,0,0,0,,返回square\r\nDialogue: 0,0:46:53.93,0:46:56.29,Default,,0,0,0,,现在 我已经将某个东西命名为square了\r\nDialogue: 0,0:46:56.45,0:47:02.88,Default,,0,0,0,,完毕后 我就可以问Lisp 1001的平方是多少\r\nDialogue: 0,0:47:05.26,0:47:17.69,Default,,0,0,0,,或者更通常的来说 我可以问 5加上7的和的平方是多少\r\nDialogue: 0,0:47:22.81,0:47:24.95,Default,,0,0,0,,12的平方是144\r\nDialogue: 0,0:47:25.07,0:47:28.86,Default,,0,0,0,,在某些组合式中我亦可把square当作一个元素\r\nDialogue: 0,0:47:28.88,0:47:37.50,Default,,0,0,0,,3的平方加上4的平方的和是多少\r\nDialogue: 0,0:47:42.53,0:47:44.09,Default,,0,0,0,,9加上16得25\r\nDialogue: 0,0:47:44.91,0:47:50.54,Default,,0,0,0,,我可以将square作为元素用于更复杂的式子\r\nDialogue: 0,0:47:50.59,0:48:00.51,Default,,0,0,0,,比如 1001的平方点的平方的平方是多少\r\nDialogue: 0,0:48:07.89,0:48:10.63,Default,,0,0,0,,这就是1001点的平方的平方的平方\r\nDialogue: 0,0:48:11.20,0:48:15.45,Default,,0,0,0,,我也可以问Lisp square本身是什么\r\nDialogue: 0,0:48:15.68,0:48:17.16,Default,,0,0,0,,它的值是是什么\r\nDialogue: 0,0:48:17.44,0:48:22.14,Default,,0,0,0,,Lisp用一种约定的方法告诉我这是一个过程\r\nDialogue: 0,0:48:22.27,0:48:23.98,Default,,0,0,0,,它返回 复合过程square\r\nDialogue: 0,0:48:24.25,0:48:27.92,Default,,0,0,0,,记住 square的值是一个过程\r\nDialogue: 0,0:48:29.15,0:48:30.89,Default,,0,0,0,,而那些用星号和括号的记法\r\nDialogue: 0,0:48:31.10,0:48:34.78,Default,,0,0,0,,只是Lisp用来描述这个过程的约定\r\nDialogue: 0,0:48:36.11,0:48:41.33,Default,,0,0,0,,让我们再看两个关于define的例子\r\nDialogue: 0,0:48:44.91,0:48:46.91,Default,,0,0,0,,这有两个过程\r\nDialogue: 0,0:48:47.36,0:48:52.84,Default,,0,0,0,,定义x和y的平均值为x加上y的和除以2的商\r\nDialogue: 0,0:48:54.67,0:49:01.49,Default,,0,0,0,,以及定义好平方和平均值后 我可以定义均方\r\nDialogue: 0,0:49:01.65,0:49:04.71,Default,,0,0,0,,我可以用它们来讨论某元素的均方\r\nDialogue: 0,0:49:04.91,0:49:09.26,Default,,0,0,0,,即x的平方与y的平方的平均值\r\nDialogue: 0,0:49:10.97,0:49:13.63,Default,,0,0,0,,当定义好它们后 我可以问\r\nDialogue: 0,0:49:13.66,0:49:24.88,Default,,0,0,0,,2和3的均方是多少\r\nDialogue: 0,0:49:25.23,0:49:30.24,Default,,0,0,0,,我将会得到 4和9的平均值 即6.5\r\nDialogue: 0,0:49:32.85,0:49:36.64,Default,,0,0,0,,关键点在于 定义了square后\r\nDialogue: 0,0:49:36.64,0:49:38.67,Default,,0,0,0,,我可以把它当作一个基本元素来使用\r\nDialogue: 0,0:49:41.41,0:49:43.07,Default,,0,0,0,,因此在这里\r\nDialogue: 0,0:49:44.65,0:49:45.74,Default,,0,0,0,,我在讨论均方的时候\r\nDialogue: 0,0:49:47.29,0:49:52.56,Default,,0,0,0,,从这点来说 定义均方的人没有必要知道\r\nDialogue: 0,0:49:52.61,0:49:55.76,Default,,0,0,0,,究竟square是由语言内建支持\r\nDialogue: 0,0:49:56.94,0:49:58.93,Default,,0,0,0,,还是自定义的过程\r\nDialogue: 0,0:49:59.73,0:50:01.28,Default,,0,0,0,,这是Lisp的关键之一\r\nDialogue: 0,0:50:02.30,0:50:07.52,Default,,0,0,0,,你无法准确区别\r\nDialogue: 0,0:50:07.53,0:50:11.82,Default,,0,0,0,,哪些是语言的基本对象 哪些是语言的内建支持\r\nDialogue: 0,0:50:12.83,0:50:14.73,Default,,0,0,0,,用户使用时则无需关心这些\r\nDialogue: 0,0:50:14.93,0:50:18.51,Default,,0,0,0,,你自己构建的东西看起来就像是语言自带的基本对象\r\nDialogue: 0,0:50:18.51,0:50:19.53,Default,,0,0,0,,具有同样的能力和灵活性\r\nDialogue: 0,0:50:19.57,0:50:22.57,Default,,0,0,0,,大家可以在课后上机做做测试\r\nDialogue: 0,0:50:24.75,0:50:26.30,Default,,0,0,0,,我们接下来讨论一下“+”吧\r\nDialogue: 0,0:50:26.72,0:50:30.09,Default,,0,0,0,,好的 让我们在计算机中看看\r\nDialogue: 0,0:50:30.11,0:50:32.33,Default,,0,0,0,,“+”的值是什么\r\nDialogue: 0,0:50:34.40,0:50:37.20,Default,,0,0,0,,注意Lisp在下面的输出\r\nDialogue: 0,0:50:37.25,0:50:38.81,Default,,0,0,0,,复合过程“+”\r\nDialogue: 0,0:50:39.89,0:50:42.29,Default,,0,0,0,,因为在此系统中\r\nDialogue: 0,0:50:42.33,0:50:45.49,Default,,0,0,0,,“+”运算符是一个复合过程\r\nDialogue: 0,0:50:45.97,0:50:47.97,Default,,0,0,0,,但如果我不输入进去做下测试 你永远不会知道\r\nDialogue: 0,0:50:48.06,0:50:49.68,Default,,0,0,0,,所以这没什么不同\r\nDialogue: 0,0:50:49.84,0:50:50.51,Default,,0,0,0,,我们并不关心这些\r\nDialogue: 0,0:50:50.56,0:50:53.39,Default,,0,0,0,,它比我们日常处理的问题更加抽象一些\r\nDialogue: 0,0:50:54.17,0:50:59.11,Default,,0,0,0,,其关键点在于你无法分辨出\r\nDialogue: 0,0:50:59.17,0:51:03.82,Default,,0,0,0,,内建元素与复合元素之间的不同\r\nDialogue: 0,0:51:03.84,0:51:04.38,Default,,0,0,0,,为什么会这样呢？\r\nDialogue: 0,0:51:04.38,0:51:08.07,Default,,0,0,0,,因为复合元素经过了一次抽象封装 (以致于无法分辨)\r\nDialogue: 0,0:51:09.05,0:51:11.61,Default,,0,0,0,,我们已经介绍了Lisp的大多数元素了\r\nDialogue: 0,0:51:12.67,0:51:14.53,Default,,0,0,0,,还有一个需要进行讨论的\r\nDialogue: 0,0:51:14.57,0:51:16.53,Default,,0,0,0,,就是如何进行分情况分析\r\nDialogue: 0,0:51:16.59,0:51:17.70,Default,,0,0,0,,举个例子\r\nDialogue: 0,0:51:18.96,0:51:24.08,Default,,0,0,0,,让我们考虑绝对值函数的数学定义\r\nDialogue: 0,0:51:24.11,0:51:30.03,Default,,0,0,0,,我或许会说x的绝对值这样是一个函数\r\nDialogue: 0,0:51:30.16,0:51:37.24,Default,,0,0,0,,若x小于0 则为-x\r\nDialogue: 0,0:51:37.92,0:51:41.13,Default,,0,0,0,,若x等于0 则为0\r\nDialogue: 0,0:51:42.64,0:51:46.62,Default,,0,0,0,,若x大于0 则就是x\r\nDialogue: 0,0:51:49.15,0:51:51.90,Default,,0,0,0,,而Lisp则有一套分情况分析方法\r\nDialogue: 0,0:51:52.11,0:51:53.85,Default,,0,0,0,,以绝对值定义为例 我给大家说明一下\r\nDialogue: 0,0:51:55.55,0:52:02.41,Default,,0,0,0,,定义绝对值为 x是有多种情况的\r\nDialogue: 0,0:52:03.02,0:52:05.67,Default,,0,0,0,,这就是分情况分析\r\nDialogue: 0,0:52:09.23,0:52:19.09,Default,,0,0,0,,如果x小于0 则结果为-x\r\nDialogue: 0,0:52:22.99,0:52:24.88,Default,,0,0,0,,我这里写的是一个子句\r\nDialogue: 0,0:52:24.99,0:52:35.54,Default,,0,0,0,,这整个是一个由两部分组成的条件表达式\r\nDialogue: 0,0:52:36.35,0:52:44.70,Default,,0,0,0,,这个部分叫做谓词或者条件\r\nDialogue: 0,0:52:44.83,0:52:45.90,Default,,0,0,0,,这就是一种情况（条件）\r\nDialogue: 0,0:52:46.11,0:52:48.29,Default,,0,0,0,,用以表达条件的东西叫做谓词\r\nDialogue: 0,0:52:48.33,0:52:51.05,Default,,0,0,0,,Lisp中的谓词是一种\r\nDialogue: 0,0:52:51.37,0:52:52.87,Default,,0,0,0,,可以返回true或者false的东西\r\nDialogue: 0,0:52:53.53,0:52:56.13,Default,,0,0,0,,比如说“小于”是Lisp中的一个基本过程\r\nDialogue: 0,0:52:57.29,0:52:59.08,Default,,0,0,0,,它返回true或者false\r\nDialogue: 0,0:53:00.54,0:53:06.32,Default,,0,0,0,,子句其余部分为一个动作或者需要做的事\r\nDialogue: 0,0:53:06.93,0:53:08.14,Default,,0,0,0,,本例中为true\r\nDialogue: 0,0:53:08.17,0:53:09.81,Default,,0,0,0,,在这里 我则是取x的相反数\r\nDialogue: 0,0:53:10.08,0:53:14.41,Default,,0,0,0,,有趣的是 Lisp中减运算符符与相反数运算符相同\r\nDialogue: 0,0:53:14.56,0:53:18.43,Default,,0,0,0,,如果有两个及两个以上的参数\r\nDialogue: 0,0:53:18.58,0:53:22.49,Default,,0,0,0,,正如我们看到的 假设刚好有两个参数 就从第一个中减去第二个\r\nDialogue: 0,0:53:22.53,0:53:24.13,Default,,0,0,0,,如果只有一个参数 则取其相反数\r\nDialogue: 0,0:53:25.13,0:53:27.87,Default,,0,0,0,,这与前面相符合\r\nDialogue: 0,0:53:27.87,0:53:29.69,Default,,0,0,0,,这又是一个COND子句\r\nDialogue: 0,0:53:30.64,0:53:35.87,Default,,0,0,0,,这是说 在x等于0的时候 结果为0\r\nDialogue: 0,0:53:37.95,0:53:44.75,Default,,0,0,0,,在x大于0的时候 结果为x\r\nDialogue: 0,0:53:45.33,0:53:49.38,Default,,0,0,0,,闭合子句 闭合COND 闭合define\r\nDialogue: 0,0:53:49.57,0:53:51.29,Default,,0,0,0,,这就是绝对值的定义\r\nDialogue: 0,0:53:51.31,0:53:53.66,Default,,0,0,0,,你会发现分情况分析\r\nDialogue: 0,0:53:53.66,0:53:56.04,Default,,0,0,0,,与数学中所用的非常相似\r\nDialogue: 0,0:53:58.14,0:54:03.07,Default,,0,0,0,,当然还有一些不常用的受限的分情况分析方法\r\nDialogue: 0,0:54:03.07,0:54:06.24,Default,,0,0,0,,很多时候 你在进行分情况分析时只有一种情况\r\nDialogue: 0,0:54:06.93,0:54:08.07,Default,,0,0,0,,你首先进行测试\r\nDialogue: 0,0:54:08.33,0:54:10.75,Default,,0,0,0,,然后根据返回的为true或false来决定如何处理\r\nDialogue: 0,0:54:11.01,0:54:15.90,Default,,0,0,0,,这是另外一种定义绝对值的方法\r\nDialogue: 0,0:54:16.00,0:54:17.19,Default,,0,0,0,,但看起来是几乎一样的\r\nDialogue: 0,0:54:17.66,0:54:22.56,Default,,0,0,0,,像这样 如果x小于0 结果则为x的相反数\r\nDialogue: 0,0:54:24.41,0:54:25.97,Default,,0,0,0,,否则 结果即为x\r\nDialogue: 0,0:54:26.05,0:54:27.25,Default,,0,0,0,,我们将会大量的使用“if”\r\nDialogue: 0,0:54:27.29,0:54:29.13,Default,,0,0,0,,再次声明\r\nDialogue: 0,0:54:29.13,0:54:32.70,Default,,0,0,0,,你们在这里看到的绝对值形式\r\nDialogue: 0,0:54:34.30,0:54:36.98,Default,,0,0,0,,和我在黑板上写的那种\r\nDialogue: 0,0:54:37.52,0:54:38.80,Default,,0,0,0,,本质上是一样的\r\nDialogue: 0,0:54:39.09,0:54:42.26,Default,,0,0,0,,而“if”和“COND”则是——\r\nDialogue: 0,0:54:42.30,0:54:44.45,Default,,0,0,0,,你可以把“COND”当做“if”的语法糖\r\nDialogue: 0,0:54:44.99,0:54:47.36,Default,,0,0,0,,或者“if”是“COND”的语法糖\r\nDialogue: 0,0:54:47.39,0:54:48.65,Default,,0,0,0,,这没什么区别\r\nDialogue: 0,0:54:49.21,0:54:51.35,Default,,0,0,0,,Lisp系统的设计者会从中会选择一个\r\nDialogue: 0,0:54:51.39,0:54:52.97,Default,,0,0,0,,然后依照这个来实现另外一个\r\nDialogue: 0,0:54:53.15,0:54:54.67,Default,,0,0,0,,你首先实现哪一个都无所谓\r\nDialogue: 0,0:55:02.27,0:55:05.36,Default,,0,0,0,,让我们停下来 解决几点疑问\r\nDialogue: 0,0:55:05.69,0:55:10.08,Default,,0,0,0,,为什么我有时用define时\r\nDialogue: 0,0:55:11.09,0:55:14.75,Default,,0,0,0,,我在这里使用了一个左括号\r\nDialogue: 0,0:55:14.81,0:55:16.45,Default,,0,0,0,,输入 define (XXX\r\nDialogue: 0,0:55:16.86,0:55:20.81,Default,,0,0,0,,而有时我这样写时却没加左括号\r\nDialogue: 0,0:55:22.06,0:55:27.23,Default,,0,0,0,,是因为你所见的\r\nDialogue: 0,0:55:27.26,0:55:29.41,Default,,0,0,0,,这种“define”表达式\r\nDialogue: 0,0:55:29.47,0:55:32.13,Default,,0,0,0,,对于定义过程来讲是非常特殊\r\nDialogue: 0,0:55:33.61,0:55:40.21,Default,,0,0,0,,再次强调 这实际上是说我定义这个叫square的符号为这个\r\nDialogue: 0,0:55:41.45,0:55:45.98,Default,,0,0,0,,你所知道的则是 你先写一个“define”\r\nDialogue: 0,0:55:47.15,0:55:50.06,Default,,0,0,0,,然后你再写一个符号 没有左括号\r\nDialogue: 0,0:55:50.17,0:55:51.49,Default,,0,0,0,,这是你将要定义的符号\r\nDialogue: 0,0:55:52.08,0:55:53.70,Default,,0,0,0,,这又是你要将其定义为什么\r\nDialogue: 0,0:55:54.65,0:55:57.55,Default,,0,0,0,,就像这儿和这儿\r\nDialogue: 0,0:55:57.61,0:56:00.29,Default,,0,0,0,,这是“define”的基本使用方法\r\nDialogue: 0,0:56:01.12,0:56:03.65,Default,,0,0,0,,然而 这种特殊的语法技巧\r\nDialogue: 0,0:56:04.29,0:56:07.04,Default,,0,0,0,,使得你可以定义像这样的过程\r\nDialogue: 0,0:56:08.17,0:56:11.49,Default,,0,0,0,,因此区别就在于你是否定义了一个过程\r\nDialogue: 0,0:56:12.91,0:56:37.60,Default,,0,0,0,,[音乐]\r\nDialogue: 0,0:56:38.05,0:56:41.98,Default,,0,0,0,,信不信由你 你们已经学了足够多的Lisp的知识了\r\nDialogue: 0,0:56:42.78,0:56:45.42,Default,,0,0,0,,现在你基本上可以编写\r\nDialogue: 0,0:56:46.25,0:56:49.63,Default,,0,0,0,,FORTRAN、Basic或者其它语言中一样的\r\nDialogue: 0,0:56:49.66,0:56:51.01,Default,,0,0,0,,数值计算过程了\r\nDialogue: 0,0:56:52.05,0:56:54.76,Default,,0,0,0,,或许你会说 这不可能\r\nDialogue: 0,0:56:54.81,0:56:56.65,Default,,0,0,0,,因为你知道这些语言有\r\nDialogue: 0,0:56:56.65,0:57:00.22,Default,,0,0,0,,像“for”语句和“do-until-whil”语句的东西\r\nDialogue: 0,0:57:00.99,0:57:04.59,Default,,0,0,0,,实际上这些我们一点也用不着\r\nDialogue: 0,0:57:05.05,0:57:07.13,Default,,0,0,0,,本课中我们一点也不会使用这些东西\r\nDialogue: 0,0:57:08.25,0:57:10.16,Default,,0,0,0,,我给你们来个下马威\r\nDialogue: 0,0:57:10.25,0:57:13.61,Default,,0,0,0,,回过头来看看平方根\r\nDialogue: 0,0:57:13.65,0:57:19.03,Default,,0,0,0,,让我们看看亚历山大的Heron提出的平方根算法\r\nDialogue: 0,0:57:19.09,0:57:19.97,Default,,0,0,0,,想想它是怎么说的\r\nDialogue: 0,0:57:20.06,0:57:23.67,Default,,0,0,0,,算法说 为了找到X的平方根的近似值\r\nDialogue: 0,0:57:25.07,0:57:26.16,Default,,0,0,0,,你做出猜测\r\nDialogue: 0,0:57:27.45,0:57:31.88,Default,,0,0,0,,然后通过取guess和X/guess的平均数来改进猜测\r\nDialogue: 0,0:57:32.94,0:57:36.06,Default,,0,0,0,,你不断改进猜测 直到这个猜测足够好\r\nDialogue: 0,0:57:36.72,0:57:38.43,Default,,0,0,0,,我已经提到过这种想法\r\nDialogue: 0,0:57:38.56,0:57:42.24,Default,,0,0,0,,这种想法是说 如果你最初采用的猜测\r\nDialogue: 0,0:57:43.04,0:57:46.91,Default,,0,0,0,,真真切切的等于X的平方根\r\nDialogue: 0,0:57:47.15,0:57:50.06,Default,,0,0,0,,那么G就会等于X/G\r\nDialogue: 0,0:57:52.89,0:57:55.33,Default,,0,0,0,,如果你算出平方根 对其取平均数并不会改变它\r\nDialogue: 0,0:57:55.69,0:57:59.62,Default,,0,0,0,,如果你所采用的G比X的平方根大\r\nDialogue: 0,0:58:00.38,0:58:02.94,Default,,0,0,0,,那么X/G就会比X的平方根小\r\nDialogue: 0,0:58:03.21,0:58:05.37,Default,,0,0,0,,因此当你取G与X/G的平均值时\r\nDialogue: 0,0:58:05.63,0:58:07.57,Default,,0,0,0,,就得到了两者之间的某数\r\nDialogue: 0,0:58:08.96,0:58:12.95,Default,,0,0,0,,同理 若你采用的G过小 答案则会过大\r\nDialogue: 0,0:58:13.12,0:58:14.81,Default,,0,0,0,,如果你采用了一个太大的G\r\nDialogue: 0,0:58:16.32,0:58:18.06,Default,,0,0,0,,如果你的G比X的平方根还要大的话\r\nDialogue: 0,0:58:18.08,0:58:20.35,Default,,0,0,0,,X/G就会比X的平方根还要小\r\nDialogue: 0,0:58:21.23,0:58:23.65,Default,,0,0,0,,因此取平均值使得你总可以得到两者间的某数\r\nDialogue: 0,0:58:24.53,0:58:28.13,Default,,0,0,0,,这不是毫无意义的 它表明\r\nDialogue: 0,0:58:28.17,0:58:31.76,Default,,0,0,0,,事实上 如果G只差X的平方根一点的话\r\nDialogue: 0,0:58:31.81,0:58:37.99,Default,,0,0,0,,G和X/G的平均值就会慢慢的向X的平方根靠近\r\nDialogue: 0,0:58:38.03,0:58:38.99,Default,,0,0,0,,只要你不断的这样做\r\nDialogue: 0,0:58:39.42,0:58:41.18,Default,,0,0,0,,最终就可以不断地靠近\r\nDialogue: 0,0:58:41.71,0:58:42.85,Default,,0,0,0,,另外一个事实则是\r\nDialogue: 0,0:58:43.02,0:58:47.65,Default,,0,0,0,,你总可以使用1作为一个初始猜测值来开始计算\r\nDialogue: 0,0:58:49.23,0:58:51.35,Default,,0,0,0,,它总是朝X的平方根聚拢\r\nDialogue: 0,0:58:52.24,0:58:56.77,Default,,0,0,0,,这就是亚历山大的Heron的连续求平均值法\r\nDialogue: 0,0:58:56.81,0:58:59.21,Default,,0,0,0,,让我们在Lisp中实现\r\nDialogue: 0,0:59:00.57,0:59:02.61,Default,,0,0,0,,中心思想是\r\nDialogue: 0,0:59:02.65,0:59:07.19,Default,,0,0,0,,尝试将guess作为X的平方根的一个猜想意味着什么\r\nDialogue: 0,0:59:08.30,0:59:09.37,Default,,0,0,0,,我来编码\r\nDialogue: 0,0:59:09.79,0:59:25.02,Default,,0,0,0,,定义（try guess x）\r\nDialogue: 0,0:59:26.45,0:59:28.24,Default,,0,0,0,,我们该如何做 我们会说\r\nDialogue: 0,0:59:28.29,0:59:45.26,Default,,0,0,0,,如果猜测精确到可以作为X的平方根\r\nDialogue: 0,0:59:46.54,0:59:49.52,Default,,0,0,0,,那么我们就可以将这个猜测作为答案\r\nDialogue: 0,0:59:51.61,0:59:57.01,Default,,0,0,0,,否则 我们就会尝试改进猜测\r\nDialogue: 0,0:59:58.19,1:00:04.24,Default,,0,0,0,,我们将通过改进这个猜测来作为X的平方根\r\nDialogue: 0,1:00:05.26,1:00:09.33,Default,,0,0,0,,并尝试是否为X平方根\r\nDialogue: 0,1:00:09.36,1:00:12.96,Default,,0,0,0,,闭合try 闭合if 闭合define\r\nDialogue: 0,1:00:13.31,1:00:14.81,Default,,0,0,0,,这就是我们如何尝试一个猜测\r\nDialogue: 0,1:00:15.85,1:00:17.60,Default,,0,0,0,,然后 这个过程的下一步是说\r\nDialogue: 0,1:00:17.73,1:00:21.90,Default,,0,0,0,,为了计算平方根\r\nDialogue: 0,1:00:21.93,1:00:30.17,Default,,0,0,0,,定义计算X的平方根为\r\nDialogue: 0,1:00:30.80,1:00:35.79,Default,,0,0,0,,从1作为X的平方根的一个猜测开始尝试\r\nDialogue: 0,1:00:37.42,1:00:39.59,Default,,0,0,0,,我们必须定义一些其它的东西\r\nDialogue: 0,1:00:40.08,1:00:43.36,Default,,0,0,0,,我们必须说明 一个猜测如何才叫“足够好”\r\nDialogue: 0,1:00:43.84,1:00:45.29,Default,,0,0,0,,我们又该如何改进这个猜测\r\nDialogue: 0,1:00:45.85,1:00:47.10,Default,,0,0,0,,那么让我们来看看\r\nDialogue: 0,1:00:47.39,1:00:54.24,Default,,0,0,0,,而改进一个X的平方根的一个猜测的算法则是\r\nDialogue: 0,1:00:54.64,1:00:57.18,Default,,0,0,0,,取平均数\r\nDialogue: 0,1:00:57.18,1:01:02.16,Default,,0,0,0,,我们取guess和X/guess的平均数\r\nDialogue: 0,1:01:02.99,1:01:04.57,Default,,0,0,0,,这就是我们如何改进一个猜测\r\nDialogue: 0,1:01:05.85,1:01:08.80,Default,,0,0,0,,为了确定一个猜测是否足够精确 我们需要做一下规定\r\nDialogue: 0,1:01:08.86,1:01:11.36,Default,,0,0,0,,假设这个是X的平方根的一个猜测\r\nDialogue: 0,1:01:11.37,1:01:14.03,Default,,0,0,0,,你可能做的一件事就是\r\nDialogue: 0,1:01:14.06,1:01:16.07,Default,,0,0,0,,当你采用这个猜测并将其平方\r\nDialogue: 0,1:01:16.64,1:01:18.41,Default,,0,0,0,,你会得到一个非常接近于X的数\r\nDialogue: 0,1:01:18.59,1:01:21.10,Default,,0,0,0,,而表达这个想法的一种方式是\r\nDialogue: 0,1:01:21.12,1:01:24.31,Default,,0,0,0,,我们用X减去guess的平方\r\nDialogue: 0,1:01:25.15,1:01:27.15,Default,,0,0,0,,并且确认所得结果的绝对值是否\r\nDialogue: 0,1:01:27.20,1:01:32.05,Default,,0,0,0,,比一个由你规定的很小的数还要小\r\nDialogue: 0,1:01:34.70,1:01:41.42,Default,,0,0,0,,因此 我们就有了计算X的平方根的一整套过程\r\nDialogue: 0,1:01:41.47,1:01:43.53,Default,,0,0,0,,我们再来深入观察一下这个结构\r\nDialogue: 0,1:01:47.84,1:01:49.12,Default,,0,0,0,,我搞定了整件事\r\nDialogue: 0,1:01:49.15,1:01:55.44,Default,,0,0,0,,我有一个用于计算X的平方根的记号\r\nDialogue: 0,1:01:55.53,1:01:56.88,Default,,0,0,0,,这是一种模块\r\nDialogue: 0,1:01:57.05,1:01:58.46,Default,,0,0,0,,也是一种黑盒\r\nDialogue: 0,1:01:58.72,1:02:08.02,Default,,0,0,0,,它的定义依赖于如何尝试将一个猜测值作为X的平方根\r\nDialogue: 0,1:02:09.31,1:02:14.10,Default,,0,0,0,,定义try是用来\r\nDialogue: 0,1:02:14.61,1:02:18.03,Default,,0,0,0,,确认某数是否足够精确以及如何去改进该数\r\nDialogue: 0,1:02:18.73,1:02:19.68,Default,,0,0,0,,这是good-enogh?\r\nDialogue: 0,1:02:19.89,1:02:28.85,Default,,0,0,0,,try的定义依赖于good-enough?和improve\r\nDialogue: 0,1:02:30.96,1:02:32.56,Default,,0,0,0,,让我们来看看我填入了些什么\r\nDialogue: 0,1:02:32.71,1:02:34.29,Default,,0,0,0,,如果我向下拓展这棵树\r\nDialogue: 0,1:02:34.73,1:02:38.49,Default,,0,0,0,,good-enough?的定义依赖于abs和square\r\nDialogue: 0,1:02:40.97,1:02:44.13,Default,,0,0,0,,而improve的定义依赖于averaging\r\nDialogue: 0,1:02:45.17,1:02:46.70,Default,,0,0,0,,而其它的都是一些基本运算符\r\nDialogue: 0,1:02:46.72,1:02:48.88,Default,,0,0,0,,平方根的定义依赖于try\r\nDialogue: 0,1:02:48.88,1:02:53.31,Default,,0,0,0,,try的定义依赖于good-enough?和improve\r\nDialogue: 0,1:02:54.01,1:02:55.39,Default,,0,0,0,,甚至依赖于try本身\r\nDialogue: 0,1:02:55.58,1:03:00.86,Default,,0,0,0,,因此try也按照它如何应用于自身而进行定义\r\nDialogue: 0,1:03:02.75,1:03:04.72,Default,,0,0,0,,额 这可能会使你有点糊涂\r\nDialogue: 0,1:03:04.72,1:03:08.16,Default,,0,0,0,,你的高中几何老师或许告诉过你\r\nDialogue: 0,1:03:08.67,1:03:12.57,Default,,0,0,0,,用一个东西自己去定义自己是很不对的\r\nDialogue: 0,1:03:12.88,1:03:13.92,Default,,0,0,0,,因为这根本行不通\r\nDialogue: 0,1:03:13.92,1:03:14.72,Default,,0,0,0,,这（种说法）是错的\r\nDialogue: 0,1:03:16.03,1:03:19.68,Default,,0,0,0,,有时候用一个东西自己来定义自己非常有意义\r\nDialogue: 0,1:03:20.16,1:03:24.38,Default,,0,0,0,,我们来看看这个例子\r\nDialogue: 0,1:03:24.38,1:03:26.89,Default,,0,0,0,,假设我问Lisp：2的平方根是多少\r\nDialogue: 0,1:03:26.91,1:03:30.33,Default,,0,0,0,,我们可以写出它究竟是什么意思\r\nDialogue: 0,1:03:32.65,1:03:34.67,Default,,0,0,0,,2的平方根是什么意思\r\nDialogue: 0,1:03:35.79,1:03:43.61,Default,,0,0,0,,意思就是我将用1作为2的平方根的一个猜测\r\nDialogue: 0,1:03:46.97,1:03:50.92,Default,,0,0,0,,然后我考虑 对于2的平方根来说 1是一个足够好的猜测么\r\nDialogue: 0,1:03:51.65,1:03:53.69,Default,,0,0,0,,这取决于good-enough?是如何判断的\r\nDialogue: 0,1:03:54.61,1:03:56.56,Default,,0,0,0,,本例中 good-enough?会说\r\nDialogue: 0,1:03:56.65,1:03:59.05,Default,,0,0,0,,不 对于2的平方根来说 1不是一个足够好的猜测\r\nDialogue: 0,1:03:59.79,1:04:08.22,Default,,0,0,0,,因此我会继续说 我试试一个改进值\r\nDialogue: 0,1:04:08.64,1:04:12.63,Default,,0,0,0,,改进猜测值1\r\nDialogue: 0,1:04:15.15,1:04:17.46,Default,,0,0,0,,然后将其作为2的平方根的一个猜测\r\nDialogue: 0,1:04:19.13,1:04:22.07,Default,,0,0,0,,改进猜测值1用作2的平方根\r\nDialogue: 0,1:04:22.09,1:04:25.08,Default,,0,0,0,,也就是说我取1和2/1的平均值\r\nDialogue: 0,1:04:27.10,1:04:29.10,Default,,0,0,0,,因此我们将取平均数\r\nDialogue: 0,1:04:29.58,1:04:39.44,Default,,0,0,0,,这段代码将会取1和2/1的平均数\r\nDialogue: 0,1:04:40.83,1:04:42.75,Default,,0,0,0,,那么这段代码\r\nDialogue: 0,1:04:43.85,1:04:46.72,Default,,0,0,0,,我算算 结果是1.5\r\nDialogue: 0,1:04:49.07,1:04:54.40,Default,,0,0,0,,因此这个(sqrt 2)还原到(try 1 2)\r\nDialogue: 0,1:04:54.56,1:05:04.83,Default,,0,0,0,,然后还原到(try 1.5 2)\r\nDialogue: 0,1:05:06.03,1:05:08.06,Default,,0,0,0,,因此这行得通\r\nDialogue: 0,1:05:08.11,1:05:09.52,Default,,0,0,0,,让我们看下剩下的步骤\r\nDialogue: 0,1:05:09.73,1:05:15.00,Default,,0,0,0,,如果我尝试1.5 则会还原到\r\nDialogue: 0,1:05:15.01,1:05:19.05,Default,,0,0,0,,1.5作为2的平方根的猜测 并不是足够好\r\nDialogue: 0,1:05:20.22,1:05:22.00,Default,,0,0,0,,然后又还原到\r\nDialogue: 0,1:05:22.01,1:05:26.17,Default,,0,0,0,,(try (average 1.5 (/ 2 1.5)))\r\nDialogue: 0,1:05:28.29,1:05:30.37,Default,,0,0,0,,平均值是1.333\r\nDialogue: 0,1:05:31.18,1:05:35.24,Default,,0,0,0,,然后整个事又还原到(try 1.3333 2)\r\nDialogue: 0,1:05:35.28,1:05:36.06,Default,,0,0,0,,如此进行下去\r\nDialogue: 0,1:05:38.01,1:05:41.66,Default,,0,0,0,,然后又还原到(good-enough? 1.4)或者其它的\r\nDialogue: 0,1:05:41.73,1:05:44.47,Default,,0,0,0,,然后这个（步骤）会持续进行到\r\nDialogue: 0,1:05:44.85,1:05:47.92,Default,,0,0,0,,good-enough?认为足够好了才停止\r\nDialogue: 0,1:05:47.97,1:05:51.28,Default,,0,0,0,,本例中 是1.4242或者其它的东西\r\nDialogue: 0,1:05:52.51,1:05:56.05,Default,,0,0,0,,因此这个这个过程运行得非常完美\r\nDialogue: 0,1:05:59.93,1:06:03.10,Default,,0,0,0,,这种定义方法叫做“递归定义”\r\nDialogue: 0,1:06:14.40,1:06:20.96,Default,,0,0,0,,进行递归定义将会给你带来无穷威力\r\nDialogue: 0,1:06:21.95,1:06:23.05,Default,,0,0,0,,之前我已提到过\r\nDialogue: 0,1:06:23.09,1:06:27.21,Default,,0,0,0,,递归定义可以在不增加任何负担的前提下\r\nDialogue: 0,1:06:27.25,1:06:28.83,Default,,0,0,0,,仅仅通过调用过程 在达到条件之前\r\nDialogue: 0,1:06:29.73,1:06:33.66,Default,,0,0,0,,完成无限次的计算\r\nDialogue: 0,1:06:35.97,1:06:37.47,Default,,0,0,0,,还有一点要说明的\r\nDialogue: 0,1:06:37.71,1:06:44.21,Default,,0,0,0,,我再在这里给你们演示另外一种平方根的定义方法\r\nDialogue: 0,1:06:44.43,1:06:48.16,Default,,0,0,0,,这两种方法看起来像是一样的\r\nDialogue: 0,1:06:48.40,1:06:51.49,Default,,0,0,0,,在这儿 我把improve、good-enough?、try的定义\r\nDialogue: 0,1:06:51.52,1:06:56.16,Default,,0,0,0,,全都封装在了sqrt里面\r\nDialogue: 0,1:06:56.75,1:07:00.99,Default,,0,0,0,,因此实际上 我们构建了一个平方根盒子\r\nDialogue: 0,1:07:01.81,1:07:08.53,Default,,0,0,0,,我构建了一个其它人可以使用的平方根盒子\r\nDialogue: 0,1:07:08.57,1:07:11.47,Default,,0,0,0,,它们输入36 然后（盒子）输出6\r\nDialogue: 0,1:07:11.81,1:07:13.83,Default,,0,0,0,,但是 盒子里面封装的过程\r\nDialogue: 0,1:07:14.16,1:07:23.85,Default,,0,0,0,,就是try、good-enough?和improve的定义\r\nDialogue: 0,1:07:26.78,1:07:28.35,Default,,0,0,0,,它们都隐藏在盒子里面\r\nDialogue: 0,1:07:28.40,1:07:30.76,Default,,0,0,0,,这样做是因为\r\nDialogue: 0,1:07:31.18,1:07:32.85,Default,,0,0,0,,如果有人正在使用这个平方根\r\nDialogue: 0,1:07:33.21,1:07:34.73,Default,,0,0,0,,如果George正在使用这个平方根\r\nDialogue: 0,1:07:34.75,1:07:37.36,Default,,0,0,0,,George并不会关心\r\nDialogue: 0,1:07:38.29,1:07:40.03,Default,,0,0,0,,当我在实现平方根时\r\nDialogue: 0,1:07:40.21,1:07:44.45,Default,,0,0,0,,我定义了盒子内的那些try、good-enough?和improve过程\r\nDialogue: 0,1:07:46.40,1:07:49.33,Default,,0,0,0,,事实上 Harry可能会实现一个也具有\r\nDialogue: 0,1:07:49.37,1:07:50.96,Default,,0,0,0,,try、good-enough?和improve的立方根盒子\r\nDialogue: 0,1:07:51.44,1:07:53.34,Default,,0,0,0,,因此 为了不让整个系统变得混乱\r\nDialogue: 0,1:07:53.36,1:07:57.66,Default,,0,0,0,,Harry最好把这些内部过程封装在它的立方根过程里\r\nDialogue: 0,1:07:58.40,1:08:00.06,Default,,0,0,0,,这个叫做块结构\r\nDialogue: 0,1:08:00.32,1:08:08.96,Default,,0,0,0,,这是把东西打包到定义内部的一种方法\r\nDialogue: 0,1:08:09.97,1:08:12.96,Default,,0,0,0,,让我们回过头来再看看\r\nDialogue: 0,1:08:13.12,1:08:18.57,Default,,0,0,0,,这种过程的定义读作 定义“sqrt”为\r\nDialogue: 0,1:08:19.87,1:08:21.84,Default,,0,0,0,,那么 在其内部\r\nDialogue: 0,1:08:22.13,1:08:25.49,Default,,0,0,0,,我们已有improve的定义\r\nDialogue: 0,1:08:25.56,1:08:28.88,Default,,0,0,0,,我们已有good-enough?和try的定义\r\nDialogue: 0,1:08:29.73,1:08:32.38,Default,,0,0,0,,以及这些定义的实体\r\nDialogue: 0,1:08:32.48,1:08:35.07,Default,,0,0,0,,我求平方根的定义实体是从1开始尝试\r\nDialogue: 0,1:08:36.08,1:08:39.33,Default,,0,0,0,,注意这里 我不必将X当做参数传递\r\nDialogue: 0,1:08:39.87,1:08:42.32,Default,,0,0,0,,因为它们都在平方根内部\r\nDialogue: 0,1:08:42.84,1:08:44.65,Default,,0,0,0,,它相当于已知这个X了\r\nDialogue: 0,1:08:54.06,1:08:56.37,Default,,0,0,0,,我来总结下\r\nDialogue: 0,1:08:56.49,1:08:59.49,Default,,0,0,0,,我们从表述指令性知识\r\nDialogue: 0,1:08:59.51,1:09:03.18,Default,,0,0,0,,开始学习\r\nDialogue: 0,1:09:04.99,1:09:09.74,Default,,0,0,0,,这张幻灯片总结了一些关于Lisp的知识\r\nDialogue: 0,1:09:09.74,1:09:15.12,Default,,0,0,0,,我们从基本元素如“+”和“*”开始\r\nDialogue: 0,1:09:15.85,1:09:19.50,Default,,0,0,0,,一些用于测试某物小于或等于的谓词\r\nDialogue: 0,1:09:19.52,1:09:22.99,Default,,0,0,0,,事实上 我们正在使用的系统掩盖了很多细节\r\nDialogue: 0,1:09:23.02,1:09:25.85,Default,,0,0,0,,这些并不是系统的基本元素 但这无所谓\r\nDialogue: 0,1:09:26.62,1:09:28.59,Default,,0,0,0,,重要的是我们会把它们当作是基本元素\r\nDialogue: 0,1:09:28.61,1:09:29.81,Default,,0,0,0,,我们不会去研究系统的内部\r\nDialogue: 0,1:09:30.29,1:09:33.15,Default,,0,0,0,,我们也有一些基本数据和一些数\r\nDialogue: 0,1:09:34.62,1:09:37.66,Default,,0,0,0,,我们学习了合成的手段 组合的手段\r\nDialogue: 0,1:09:37.74,1:09:41.37,Default,,0,0,0,,用运算符和运算对象合成函数\r\nDialogue: 0,1:09:41.41,1:09:43.76,Default,,0,0,0,,和构建组合式的基本方法\r\nDialogue: 0,1:09:44.81,1:09:48.43,Default,,0,0,0,,还有一些像是“COND”、“if”和“define”的东西\r\nDialogue: 0,1:09:51.29,1:09:53.69,Default,,0,0,0,,具体来说 关于“define”的重点则是\r\nDialogue: 0,1:09:53.87,1:09:55.71,Default,,0,0,0,,它是一种进行抽象的方法\r\nDialogue: 0,1:09:55.73,1:09:57.70,Default,,0,0,0,,它是我们为某物命名的方法\r\nDialogue: 0,1:09:57.79,1:10:00.30,Default,,0,0,0,,我们之前提到过  从这里也可以看出来\r\nDialogue: 0,1:10:01.57,1:10:06.28,Default,,0,0,0,,有时候 我们需要研究如何通过组合基本数据来得到复合数据\r\nDialogue: 0,1:10:06.56,1:10:12.03,Default,,0,0,0,,以及如何抽象数据 使得你可以在一个更大的环境中\r\nDialogue: 0,1:10:12.06,1:10:13.07,Default,,0,0,0,,将其当作基本数据使用\r\nDialogue: 0,1:10:13.90,1:10:15.87,Default,,0,0,0,,这也是我们的目的所在\r\nDialogue: 0,1:10:16.38,1:10:22.05,Default,,0,0,0,,在我们讨论这个问题之前 下节课我们首先将会讨论\r\nDialogue: 0,1:10:23.26,1:10:26.76,Default,,0,0,0,,我们编写的过程与机器内部\r\nDialogue: 0,1:10:26.88,1:10:30.77,Default,,0,0,0,,进程之间的联系\r\nDialogue: 0,1:10:32.14,1:10:35.98,Default,,0,0,0,,接着 我们将跳出小规模的计算问题\r\nDialogue: 0,1:10:36.38,1:10:39.77,Default,,0,0,0,,来学习如何发挥Lisp的威力\r\nDialogue: 0,1:10:40.08,1:10:44.15,Default,,0,0,0,,来解决更加通用的计算问题\r\nDialogue: 0,1:10:44.81,1:10:46.17,Default,,0,0,0,,好了 大家还有什么问题么\r\nDialogue: 0,1:10:46.75,1:10:52.27,Default,,0,0,0,,学生：在定义A时 如果我们用一个括号将A括起来\r\nDialogue: 0,1:10:52.32,1:10:53.50,Default,,0,0,0,,会与不使用括号不同么？\r\nDialogue: 0,1:10:53.60,1:10:56.88,Default,,0,0,0,,教授：如果我这样写\r\nDialogue: 0,1:10:57.53,1:11:02.13,Default,,0,0,0,,我则会是定义一个过程并命名为A\r\nDialogue: 0,1:11:03.21,1:11:06.85,Default,,0,0,0,,本例中 这个过程没有参数\r\nDialogue: 0,1:11:06.85,1:11:09.61,Default,,0,0,0,,而当我运行它 则会返回5乘以5\r\nDialogue: 0,1:11:11.07,1:11:12.29,Default,,0,0,0,,学生：它们俩完成了相同的事\r\nDialogue: 0,1:11:12.32,1:11:13.92,Default,,0,0,0,,但本质上是否相同？\r\nDialogue: 0,1:11:14.05,1:11:16.63,Default,,0,0,0,,教授：好 的确会有不同 之前的那一个\r\nDialogue: 0,1:11:17.02,1:11:18.35,Default,,0,0,0,,我还是在这里写清楚一点吧\r\nDialogue: 0,1:11:19.13,1:11:23.44,Default,,0,0,0,,我们还是把这个叫做A\r\nDialogue: 0,1:11:24.13,1:11:27.76,Default,,0,0,0,,作为对比 我们假装这里有一个\r\nDialogue: 0,1:11:27.79,1:11:37.56,Default,,0,0,0,,我定义D为5乘以5\r\nDialogue: 0,1:11:40.22,1:11:41.57,Default,,0,0,0,,这两者的区别则是\r\nDialogue: 0,1:11:41.96,1:11:44.24,Default,,0,0,0,,让我们看看它们在Lisp解释器中是怎样的\r\nDialogue: 0,1:11:45.74,1:11:49.13,Default,,0,0,0,,我在Lisp中键入A 返回25\r\nDialogue: 0,1:11:52.83,1:11:57.81,Default,,0,0,0,,如果我仅仅键入D\r\nDialogue: 0,1:11:58.49,1:12:05.55,Default,,0,0,0,,Lisp返回复合过程D\r\nDialogue: 0,1:12:07.12,1:12:09.13,Default,,0,0,0,,因为D就是一个过程\r\nDialogue: 0,1:12:09.69,1:12:12.59,Default,,0,0,0,,我可以运行D 我可以问运行D的结果是什么\r\nDialogue: 0,1:12:12.59,1:12:15.23,Default,,0,0,0,,这是一个没有运算数的组合式\r\nDialogue: 0,1:12:16.45,1:12:19.07,Default,,0,0,0,,我考虑到它没有运算数 所以我在D后面没有键入任何东西\r\nDialogue: 0,1:12:19.39,1:12:21.34,Default,,0,0,0,,Lisp则会说结果是25\r\nDialogue: 0,1:12:23.01,1:12:29.52,Default,,0,0,0,,我再说周全一点 如果我键入 A的运行结果是多少\r\nDialogue: 0,1:12:29.54,1:12:30.57,Default,,0,0,0,,只能得到一个错误\r\nDialogue: 0,1:12:31.79,1:12:35.29,Default,,0,0,0,,跟这里的错误一样\r\nDialogue: 0,1:12:35.33,1:12:40.51,Default,,0,0,0,,这个错误是因为 A的值——25\r\nDialogue: 0,1:12:40.56,1:12:43.24,Default,,0,0,0,,并不是我可以应用于某物的运算符\r\nDialogue: 0,1:12:43.84,1:12:48.88,Default,,0,0,0,,MIT OpenCourseWare\\Nhttp://ocw.mit.edu\r\nDialogue: 0,1:12:49.13,1:12:54.86,Default,,0,0,0,,本项目主页\\Nhttps://github.com/FoOTOo/Learning-SICP\r\n"
  },
  {
    "path": "Ass/lec1a.eng.ass",
    "content": "﻿[Script Info]\r\n; Script generated by Aegisub 3.0.2\r\n; http://www.aegisub.org/\r\nTitle: Default Aegisub file\r\nScriptType: v4.00+\r\nWrapStyle: 0\r\nScaledBorderAndShadow: yes\r\nCollisions: Normal\r\nPlayResX: 640\r\nPlayResY: 480\r\nAudio URI: lec1a_Rerip_remux.mp4\r\nScroll Position: 752\r\nActive Line: 753\r\nVideo Zoom Percent: 0.875\r\nVideo File: lec1a_Rerip_remux.mp4\r\nVideo Aspect Ratio: c1.33333\r\nVideo Position: 95862\r\nLast Style Storage: Default\r\nYCbCr Matrix: TV.601\r\n\r\n[V4+ Styles]\r\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\r\nStyle: Default,Calisto MT,23,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\r\n\r\n[Events]\r\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\nDialogue: 0,0:00:14.71,0:00:17.89,Default,,0,0,0,,I'd like to welcome you to this course on computer science.\r\nDialogue: 0,0:00:28.40,0:00:29.85,Default,,0,0,0,,Actually, that's a terrible way to start.\r\nDialogue: 0,0:00:29.85,0:00:32.34,Default,,0,0,0,,Computer science is a terrible name for this business.\r\nDialogue: 0,0:00:32.83,0:00:34.30,Default,,0,0,0,,First of all, it's not a science.\r\nDialogue: 0,0:00:35.92,0:00:39.81,Default,,0,0,0,,It might be engineering or it might be art,\r\nDialogue: 0,0:00:40.09,0:00:42.91,Default,,0,0,0,,but we'll actually see that computer so-called science\r\nDialogue: 0,0:00:42.93,0:00:44.97,Default,,0,0,0,,actually has a lot in common with magic,\r\nDialogue: 0,0:00:45.01,0:00:46.35,Default,,0,0,0,,and we'll see that in this course.\r\nDialogue: 0,0:00:47.28,0:00:48.22,Default,,0,0,0,,So it's not a science.\r\nDialogue: 0,0:00:48.23,0:00:52.30,Default,,0,0,0,,It's also not really very much about computers.\r\nDialogue: 0,0:00:53.39,0:00:55.47,Default,,0,0,0,,And it's not about computers in the same sense\r\nDialogue: 0,0:00:55.47,0:01:00.05,Default,,0,0,0,,that physics is not really about particle accelerators,\r\nDialogue: 0,0:01:00.80,0:01:05.58,Default,,0,0,0,,and biology is not really about microscopes and petri dishes.\r\nDialogue: 0,0:01:06.46,0:01:10.25,Default,,0,0,0,,And it's not about computers in the same sense\r\nDialogue: 0,0:01:10.31,0:01:14.88,Default,,0,0,0,,that geometry is not really about using surveying instruments.\r\nDialogue: 0,0:01:16.48,0:01:19.01,Default,,0,0,0,,In fact, there's a lot of commonality\r\nDialogue: 0,0:01:19.33,0:01:21.45,Default,,0,0,0,,between computer science and geometry.\r\nDialogue: 0,0:01:21.45,0:01:22.66,Default,,0,0,0,,Geometry, first of all,\r\nDialogue: 0,0:01:23.02,0:01:24.98,Default,,0,0,0,,is another subject with a lousy name.\r\nDialogue: 0,0:01:25.58,0:01:27.85,Default,,0,0,0,,The name comes from Gaia, meaning the Earth,\r\nDialogue: 0,0:01:27.90,0:01:29.09,Default,,0,0,0,,and metron, meaning to measure.\r\nDialogue: 0,0:01:29.82,0:01:33.39,Default,,0,0,0,,Geometry originally meant measuring the Earth or surveying.\r\nDialogue: 0,0:01:34.37,0:01:36.89,Default,,0,0,0,,And the reason for that was that, thousands of years ago,\r\nDialogue: 0,0:01:37.69,0:01:41.69,Default,,0,0,0,,the Egyptian priesthood developed the rudiments of geometry\r\nDialogue: 0,0:01:42.59,0:01:46.33,Default,,0,0,0,,in order to figure out how to restore the boundaries of fields\r\nDialogue: 0,0:01:46.35,0:01:48.69,Default,,0,0,0,,that were destroyed in the annual flooding of the Nile.\r\nDialogue: 0,0:01:49.47,0:01:50.65,Default,,0,0,0,,And to the Egyptians who did that,\r\nDialogue: 0,0:01:50.65,0:01:53.93,Default,,0,0,0,,geometry really was the use of surveying instruments.\r\nDialogue: 0,0:01:55.63,0:01:58.55,Default,,0,0,0,,Now, the reason that we think computer science is about computers\r\nDialogue: 0,0:01:58.57,0:02:02.49,Default,,0,0,0,,is pretty much the same reason that the Egyptians thought geometry\r\nDialogue: 0,0:02:02.51,0:02:04.10,Default,,0,0,0,,was about surveying instruments.\r\nDialogue: 0,0:02:04.59,0:02:07.37,Default,,0,0,0,,And that is, when some field is just getting started\r\nDialogue: 0,0:02:07.39,0:02:09.86,Default,,0,0,0,,and you don't really understand it very well,\r\nDialogue: 0,0:02:11.10,0:02:16.64,Default,,0,0,0,,it's very easy to confuse the essence of what you're doing with the tools that you use.\r\nDialogue: 0,0:02:17.65,0:02:20.30,Default,,0,0,0,,And indeed, on some absolute scale of things,\r\nDialogue: 0,0:02:20.30,0:02:24.82,Default,,0,0,0,,we probably know less about the essence of computer science\r\nDialogue: 0,0:02:24.83,0:02:27.49,Default,,0,0,0,,than the ancient Egyptians really knew about geometry.\r\nDialogue: 0,0:02:30.25,0:02:32.64,Default,,0,0,0,,Well, what do I mean by the essence of computer science?\r\nDialogue: 0,0:02:32.65,0:02:34.41,Default,,0,0,0,,What do I mean by the essence of geometry?\r\nDialogue: 0,0:02:34.41,0:02:36.45,Default,,0,0,0,,See, it's certainly true that these Egyptians went off\r\nDialogue: 0,0:02:36.46,0:02:37.67,Default,,0,0,0,,and used surveying instruments,\r\nDialogue: 0,0:02:37.69,0:02:41.55,Default,,0,0,0,,but when we look back on them after a couple of thousand years,\r\nDialogue: 0,0:02:41.57,0:02:41.85,Default,,0,0,0,,we say,\r\nDialogue: 0,0:02:41.87,0:02:43.64,Default,,0,0,0,,gee, what they were doing,\r\nDialogue: 0,0:02:43.71,0:02:45.48,Default,,0,0,0,,the important stuff they were doing,\r\nDialogue: 0,0:02:45.62,0:02:50.45,Default,,0,0,0,,was to begin to formalize notions about space and time,\r\nDialogue: 0,0:02:51.58,0:02:57.53,Default,,0,0,0,,to start a way of talking about mathematical truths formally.\r\nDialogue: 0,0:02:58.01,0:02:59.61,Default,,0,0,0,,That led to the axiomatic method.\r\nDialogue: 0,0:02:59.61,0:03:02.53,Default,,0,0,0,,That led to sort of all of modern mathematics,\r\nDialogue: 0,0:03:04.16,0:03:06.90,Default,,0,0,0,,figuring out a way to talk precisely about\r\nDialogue: 0,0:03:07.25,0:03:10.19,Default,,0,0,0,,so-called declarative knowledge, what is true.\r\nDialogue: 0,0:03:12.45,0:03:16.25,Default,,0,0,0,,Well, similarly, I think in the future people will look back and say,\r\nDialogue: 0,0:03:16.27,0:03:19.36,Default,,0,0,0,,yes, those primitives in the 20th century were fiddling around\r\nDialogue: 0,0:03:19.36,0:03:21.20,Default,,0,0,0,,with these gadgets called computers,\r\nDialogue: 0,0:03:21.77,0:03:26.25,Default,,0,0,0,,but really what they were doing is starting to learn\r\nDialogue: 0,0:03:26.25,0:03:32.55,Default,,0,0,0,,how to formalize intuitions about process,\r\nDialogue: 0,0:03:32.64,0:03:34.13,Default,,0,0,0,,how to do things,\r\nDialogue: 0,0:03:39.02,0:03:51.25,Default,,0,0,0,,starting to develop a way to talk precisely about how-to knowledge,\r\nDialogue: 0,0:03:51.76,0:03:56.03,Default,,0,0,0,,as opposed to geometry that talks about what is true.\r\nDialogue: 0,0:03:56.53,0:03:58.57,Default,,0,0,0,,Let me give you an example of that.\r\nDialogue: 0,0:04:02.30,0:04:02.69,Default,,0,0,0,,Let's take a look\r\nDialogue: 0,0:04:02.70,0:04:09.82,Default,,0,0,0,,Here is a piece of mathematics that says what a square root is.\r\nDialogue: 0,0:04:10.09,0:04:14.35,Default,,0,0,0,,The square root of X is the number Y,\r\nDialogue: 0,0:04:15.98,0:04:20.38,Default,,0,0,0,,such that Y squared is equal to X and Y is greater than 0.\r\nDialogue: 0,0:04:20.43,0:04:22.50,Default,,0,0,0,,Now, that's a fine piece of mathematics,\r\nDialogue: 0,0:04:22.88,0:04:25.25,Default,,0,0,0,,but just telling you what a square root is\r\nDialogue: 0,0:04:25.63,0:04:30.29,Default,,0,0,0,,doesn't really say anything about how you might go out and find one.\r\nDialogue: 0,0:04:31.42,0:04:35.90,Default,,0,0,0,,So let's contrast that with a piece of imperative knowledge,\r\nDialogue: 0,0:04:37.13,0:04:39.92,Default,,0,0,0,,how you might go out and find a square root.\r\nDialogue: 0,0:04:39.95,0:04:45.74,Default,,0,0,0,,This, in fact, also comes from Egypt, not ancient, ancient Egypt.\r\nDialogue: 0,0:04:45.76,0:04:48.88,Default,,0,0,0,,This is an algorithm due to Heron of Alexandria,\r\nDialogue: 0,0:04:49.90,0:04:52.77,Default,,0,0,0,,called how to find a square root by successive averaging.\r\nDialogue: 0,0:04:52.89,0:04:55.13,Default,,0,0,0,,And what it says is that,\r\nDialogue: 0,0:04:55.15,0:04:58.06,Default,,0,0,0,,in order to find a square root,\r\nDialogue: 0,0:05:03.34,0:05:08.33,Default,,0,0,0,,you make a guess, you improve that guess --\r\nDialogue: 0,0:05:10.19,0:05:11.44,Default,,0,0,0,,and the way you improve the guess\r\nDialogue: 0,0:05:11.45,0:05:13.95,Default,,0,0,0,,is to average the guess and X over the guess,\r\nDialogue: 0,0:05:14.41,0:05:15.60,Default,,0,0,0,,and we'll talk a little bit later about\r\nDialogue: 0,0:05:15.61,0:05:17.12,Default,,0,0,0,,why that's a reasonable thing--\r\nDialogue: 0,0:05:17.14,0:05:19.37,Default,,0,0,0,,and you keep improving the guess until it's good enough.\r\nDialogue: 0,0:05:19.73,0:05:20.85,Default,,0,0,0,,That's a method.\r\nDialogue: 0,0:05:20.99,0:05:24.65,Default,,0,0,0,,That's how to do something as opposed to\r\nDialogue: 0,0:05:24.72,0:05:27.33,Default,,0,0,0,,declarative knowledge that says what you're looking for.\r\nDialogue: 0,0:05:28.05,0:05:29.76,Default,,0,0,0,,That's a process.\r\nDialogue: 0,0:05:34.40,0:05:38.25,Default,,0,0,0,,Well, what's a process in general?\r\nDialogue: 0,0:05:39.01,0:05:40.14,Default,,0,0,0,,It's kind of hard to say.\r\nDialogue: 0,0:05:40.16,0:05:43.72,Default,,0,0,0,,You can think of it as like a magical spirit\r\nDialogue: 0,0:05:44.77,0:05:47.33,Default,,0,0,0,,that sort of lives in the computer and does something.\r\nDialogue: 0,0:05:48.01,0:05:54.11,Default,,0,0,0,,And the thing that directs a process is\r\nDialogue: 0,0:05:54.13,0:05:57.98,Default,,0,0,0,,a pattern of rules called a procedure.\r\nDialogue: 0,0:06:01.98,0:06:04.73,Default,,0,0,0,,So procedures are the spells, if you like,\r\nDialogue: 0,0:06:05.23,0:06:09.40,Default,,0,0,0,,that control these magical spirits that are the processes.\r\nDialogue: 0,0:06:10.75,0:06:12.75,Default,,0,0,0,,I guess you know everyone needs a magical language,\r\nDialogue: 0,0:06:12.77,0:06:14.55,Default,,0,0,0,,and sorcerers, real sorcerers,\r\nDialogue: 0,0:06:14.57,0:06:18.59,Default,,0,0,0,,use ancient Arcadian or Sumerian or Babylonian or whatever.\r\nDialogue: 0,0:06:18.62,0:06:20.09,Default,,0,0,0,,We're going to conjure our spirits\r\nDialogue: 0,0:06:20.13,0:06:22.71,Default,,0,0,0,,in a magical language called Lisp,\r\nDialogue: 0,0:06:24.37,0:06:28.01,Default,,0,0,0,,which is a language designed for talking about,\r\nDialogue: 0,0:06:28.57,0:06:31.84,Default,,0,0,0,,for casting the spells that are procedures to direct the processes.\r\nDialogue: 0,0:06:31.87,0:06:33.91,Default,,0,0,0,,Now, it's very easy to learn Lisp.\r\nDialogue: 0,0:06:33.97,0:06:35.98,Default,,0,0,0,,In fact, in a few minutes, I'm going to teach you,\r\nDialogue: 0,0:06:36.00,0:06:37.16,Default,,0,0,0,,essentially, all of Lisp.\r\nDialogue: 0,0:06:37.37,0:06:38.96,Default,,0,0,0,,I'm going to teach you, essentially, all of the rules.\r\nDialogue: 0,0:06:40.77,0:06:43.65,Default,,0,0,0,,And you shouldn't find that particularly surprising.\r\nDialogue: 0,0:06:43.69,0:06:45.87,Default,,0,0,0,,That's sort of like saying it's very easy\r\nDialogue: 0,0:06:45.90,0:06:47.01,Default,,0,0,0,,to learn the rules of chess.\r\nDialogue: 0,0:06:47.04,0:06:48.13,Default,,0,0,0,,And indeed, in a few minutes,\r\nDialogue: 0,0:06:48.17,0:06:49.70,Default,,0,0,0,,you can tell somebody the rules of chess.\r\nDialogue: 0,0:06:50.81,0:06:52.24,Default,,0,0,0,,But of course, that's very different from\r\nDialogue: 0,0:06:52.25,0:06:55.37,Default,,0,0,0,,saying you understand the implications of those rules\r\nDialogue: 0,0:06:55.42,0:06:58.05,Default,,0,0,0,,and how to use those rules to become a masterful chess player.\r\nDialogue: 0,0:06:58.49,0:06:59.82,Default,,0,0,0,,Well, Lisp is the same way.\r\nDialogue: 0,0:07:00.41,0:07:02.18,Default,,0,0,0,,We're going to state the rules in a few minutes,\r\nDialogue: 0,0:07:02.36,0:07:03.55,Default,,0,0,0,,and it'll be very easy to see.\r\nDialogue: 0,0:07:03.62,0:07:07.09,Default,,0,0,0,,But what's really hard is going to be the implications of those rules,\r\nDialogue: 0,0:07:07.32,0:07:10.46,Default,,0,0,0,,how you exploit those rules to be a master programmer.\r\nDialogue: 0,0:07:12.06,0:07:15.29,Default,,0,0,0,,And the implications of those rules are going to take us the,\r\nDialogue: 0,0:07:15.31,0:07:18.56,Default,,0,0,0,,well, the whole rest of the subject and, of course, way beyond.\r\nDialogue: 0,0:07:21.45,0:07:23.11,Default,,0,0,0,,OK, so in computer science,\r\nDialogue: 0,0:07:24.49,0:07:26.19,Default,,0,0,0,,we're in the business of\r\nDialogue: 0,0:07:26.21,0:07:30.58,Default,,0,0,0,,formalizing this sort of how-to imperative knowledge,\r\nDialogue: 0,0:07:30.62,0:07:32.10,Default,,0,0,0,,how to do stuff.\r\nDialogue: 0,0:07:33.37,0:07:35.39,Default,,0,0,0,,And the real issues of computer science are, of course,\r\nDialogue: 0,0:07:35.41,0:07:38.36,Default,,0,0,0,,not telling people how to do square roots.\r\nDialogue: 0,0:07:39.09,0:07:40.06,Default,,0,0,0,,Because if that was all it was,\r\nDialogue: 0,0:07:40.09,0:07:41.34,Default,,0,0,0,,there wouldn't be no big deal.\r\nDialogue: 0,0:07:41.57,0:07:44.05,Default,,0,0,0,,The real problems come when we try to\r\nDialogue: 0,0:07:44.08,0:07:46.16,Default,,0,0,0,,build very, very large systems,\r\nDialogue: 0,0:07:46.61,0:07:49.53,Default,,0,0,0,,computer programs that are thousands of pages long,\r\nDialogue: 0,0:07:49.58,0:07:53.98,Default,,0,0,0,,so long that nobody can really hold them in their heads all at once.\r\nDialogue: 0,0:07:54.73,0:07:58.81,Default,,0,0,0,,And the only reason that that's possible is because\r\nDialogue: 0,0:07:58.86,0:08:18.97,Default,,0,0,0,,there are techniques for controlling the complexity of these large systems.\r\nDialogue: 0,0:08:20.30,0:08:22.69,Default,,0,0,0,,And these techniques that are controlling complexity\r\nDialogue: 0,0:08:22.72,0:08:24.17,Default,,0,0,0,,are what this course is really about.\r\nDialogue: 0,0:08:24.65,0:08:25.47,Default,,0,0,0,,And in some sense,\r\nDialogue: 0,0:08:25.50,0:08:27.47,Default,,0,0,0,,that's really what computer science is about.\r\nDialogue: 0,0:08:29.63,0:08:31.89,Default,,0,0,0,,Now, that may seem like a very strange thing to say.\r\nDialogue: 0,0:08:31.92,0:08:35.61,Default,,0,0,0,,Because after all, a lot of people besides computer scientists\r\nDialogue: 0,0:08:35.65,0:08:37.82,Default,,0,0,0,,deal with controlling complexity.\r\nDialogue: 0,0:08:37.84,0:08:41.02,Default,,0,0,0,,A large airliner is an extremely complex system,\r\nDialogue: 0,0:08:41.82,0:08:43.79,Default,,0,0,0,,and the aeronautical engineers who design that\r\nDialogue: 0,0:08:44.05,0:08:46.13,Default,,0,0,0,,are dealing with immense complexity.\r\nDialogue: 0,0:08:47.09,0:08:50.19,Default,,0,0,0,,But there's a difference between that kind of complexity\r\nDialogue: 0,0:08:50.75,0:08:52.60,Default,,0,0,0,,and what we deal with in computer science.\r\nDialogue: 0,0:08:55.18,0:08:57.73,Default,,0,0,0,,And that is that computer science,\r\nDialogue: 0,0:08:57.79,0:09:00.09,Default,,0,0,0,,in some sense, isn't real.\r\nDialogue: 0,0:09:02.69,0:09:06.62,Default,,0,0,0,,You see, when an engineer is designing a physical system,\r\nDialogue: 0,0:09:07.14,0:09:08.49,Default,,0,0,0,,that's made out of real parts.\r\nDialogue: 0,0:09:09.40,0:09:11.18,Default,,0,0,0,,The engineers who worry about that\r\nDialogue: 0,0:09:11.85,0:09:16.65,Default,,0,0,0,,have to address problems of tolerance and approximation and noise in the system.\r\nDialogue: 0,0:09:16.67,0:09:19.02,Default,,0,0,0,,So for example, as an electrical engineer,\r\nDialogue: 0,0:09:19.09,0:09:21.71,Default,,0,0,0,,I can go off and easily build a one-stage amplifier\r\nDialogue: 0,0:09:21.73,0:09:23.03,Default,,0,0,0,,or a two-stage amplifier,\r\nDialogue: 0,0:09:23.41,0:09:25.39,Default,,0,0,0,,and I can imagine cascading a lot of them\r\nDialogue: 0,0:09:25.45,0:09:26.91,Default,,0,0,0,,to build a million-stage amplifier.\r\nDialogue: 0,0:09:26.99,0:09:28.75,Default,,0,0,0,,But it's ridiculous to build such a thing,\r\nDialogue: 0,0:09:28.98,0:09:32.15,Default,,0,0,0,,because long before the millionth stage,\r\nDialogue: 0,0:09:32.16,0:09:34.56,Default,,0,0,0,,the thermal noise in those components way at the beginning\r\nDialogue: 0,0:09:34.57,0:09:36.80,Default,,0,0,0,,is going to get amplified and make the whole thing meaningless.\r\nDialogue: 0,0:09:39.10,0:09:43.12,Default,,0,0,0,,Computer science deals with idealized components.\r\nDialogue: 0,0:09:44.12,0:09:47.63,Default,,0,0,0,,We know as much as we want about these little program\r\nDialogue: 0,0:09:47.65,0:09:49.56,Default,,0,0,0,,and data pieces that we're fitting things together.\r\nDialogue: 0,0:09:51.90,0:09:53.20,Default,,0,0,0,,We don't have to worry about tolerance.\r\nDialogue: 0,0:09:53.21,0:09:56.99,Default,,0,0,0,,And that means that, in building a large program,\r\nDialogue: 0,0:09:58.13,0:10:00.03,Default,,0,0,0,,there's not all that much difference\r\nDialogue: 0,0:10:00.35,0:10:04.18,Default,,0,0,0,,between what I can build and what I can imagine,\r\nDialogue: 0,0:10:05.53,0:10:07.60,Default,,0,0,0,,because the parts are these abstract entities\r\nDialogue: 0,0:10:07.63,0:10:10.32,Default,,0,0,0,,that I know as much as I want.\r\nDialogue: 0,0:10:10.33,0:10:12.39,Default,,0,0,0,,I know about them as precisely as I'd like.\r\nDialogue: 0,0:10:13.45,0:10:15.50,Default,,0,0,0,,So as opposed to other kinds of engineering,\r\nDialogue: 0,0:10:15.66,0:10:17.42,Default,,0,0,0,,where the constraints on what you can build\r\nDialogue: 0,0:10:17.44,0:10:18.90,Default,,0,0,0,,are the constraints of physical systems,\r\nDialogue: 0,0:10:18.94,0:10:21.02,Default,,0,0,0,,the constraints of physics and noise and approximation,\r\nDialogue: 0,0:10:21.21,0:10:25.60,Default,,0,0,0,,the constraints imposed in building large software systems\r\nDialogue: 0,0:10:25.64,0:10:27.58,Default,,0,0,0,,are the limitations of our own minds.\r\nDialogue: 0,0:10:29.12,0:10:29.98,Default,,0,0,0,,So in that sense,\r\nDialogue: 0,0:10:30.00,0:10:33.67,Default,,0,0,0,,computer science is like an abstract form of engineering.\r\nDialogue: 0,0:10:33.80,0:10:35.73,Default,,0,0,0,,It's the kind of engineering where you ignore\r\nDialogue: 0,0:10:35.76,0:10:38.02,Default,,0,0,0,,the constraints that are imposed by reality.\r\nDialogue: 0,0:10:41.97,0:10:46.15,Default,,0,0,0,,Well, what are some of these techniques?\r\nDialogue: 0,0:10:46.28,0:10:48.39,Default,,0,0,0,,They're not special to computer science.\r\nDialogue: 0,0:10:50.39,0:10:52.55,Default,,0,0,0,,First technique, which is used in all of engineering,\r\nDialogue: 0,0:10:53.36,0:10:58.91,Default,,0,0,0,,is a kind of abstraction called black-box abstraction.\r\nDialogue: 0,0:11:07.71,0:11:12.58,Default,,0,0,0,,Take something and build a box about it.\r\nDialogue: 0,0:11:14.37,0:11:20.09,Default,,0,0,0,,Let's see, for example, if we looked at that square root method,\r\nDialogue: 0,0:11:22.64,0:11:28.53,Default,,0,0,0,,I might want to take that and build a box.\r\nDialogue: 0,0:11:29.89,0:11:37.52,Default,,0,0,0,,That sort of says, to find the square root of X.\r\nDialogue: 0,0:11:38.86,0:11:41.27,Default,,0,0,0,,And that might be a whole complicated set of rules.\r\nDialogue: 0,0:11:42.64,0:11:46.69,Default,,0,0,0,,And that might end up being a kind of thing where I can put in,\r\nDialogue: 0,0:11:46.81,0:11:50.06,Default,,0,0,0,,say, 36 and say, what's the square root of 36?\r\nDialogue: 0,0:11:50.25,0:11:51.46,Default,,0,0,0,,And out comes 6.\r\nDialogue: 0,0:11:53.89,0:11:56.22,Default,,0,0,0,,And the important thing is that\r\nDialogue: 0,0:11:56.24,0:12:00.03,Default,,0,0,0,,I'd like to design that so that\r\nDialogue: 0,0:12:00.06,0:12:04.08,Default,,0,0,0,,if George comes along and would like to compute,\r\nDialogue: 0,0:12:05.10,0:12:09.37,Default,,0,0,0,,say, the square root of A plus the square root of B,\r\nDialogue: 0,0:12:11.34,0:12:14.38,Default,,0,0,0,,he can take this thing and use it as a module\r\nDialogue: 0,0:12:14.43,0:12:15.74,Default,,0,0,0,,without having to look inside\r\nDialogue: 0,0:12:15.77,0:12:17.31,Default,,0,0,0,,and build something that looks like this,\r\nDialogue: 0,0:12:18.45,0:12:24.20,Default,,0,0,0,,like an A and a B and a square root box and another square root box\r\nDialogue: 0,0:12:24.53,0:12:33.87,Default,,0,0,0,,and then something that adds that would put out the answer.\r\nDialogue: 0,0:12:33.96,0:12:38.15,Default,,0,0,0,,And you can see, just from the fact that I want to do that,\r\nDialogue: 0,0:12:38.92,0:12:40.42,Default,,0,0,0,,is from George's point of view,\r\nDialogue: 0,0:12:40.51,0:12:43.10,Default,,0,0,0,,the internals of what's in here should not be important.\r\nDialogue: 0,0:12:44.19,0:12:47.25,Default,,0,0,0,,So for instance, it shouldn't matter that, when I wrote this,\r\nDialogue: 0,0:12:47.27,0:12:50.43,Default,,0,0,0,,I said I want to find the square root of X.\r\nDialogue: 0,0:12:50.61,0:12:52.27,Default,,0,0,0,,I could have said the square root of Y,\r\nDialogue: 0,0:12:52.72,0:12:55.62,Default,,0,0,0,,or the square root of A, or anything at all\r\nDialogue: 0,0:12:56.70,0:13:02.35,Default,,0,0,0,,That's the fundamental notion of putting something in a box\r\nDialogue: 0,0:13:03.53,0:13:06.44,Default,,0,0,0,,using black-box abstraction to suppress detail.\r\nDialogue: 0,0:13:07.60,0:13:10.99,Default,,0,0,0,,And the reason for that is you want to go off and build bigger boxes.\r\nDialogue: 0,0:13:12.05,0:13:14.57,Default,,0,0,0,,Now, there's another reason for doing black-box abstraction\r\nDialogue: 0,0:13:14.59,0:13:18.41,Default,,0,0,0,,other than you want to suppress detail for building bigger boxes.\r\nDialogue: 0,0:13:18.48,0:13:25.02,Default,,0,0,0,,Sometimes you want to say that your way of doing something,\r\nDialogue: 0,0:13:25.04,0:13:26.88,Default,,0,0,0,,your how-to method,\r\nDialogue: 0,0:13:28.44,0:13:30.79,Default,,0,0,0,,is an instance of a more general thing,\r\nDialogue: 0,0:13:31.16,0:13:34.57,Default,,0,0,0,,and you'd like your language to be able to express that generality.\r\nDialogue: 0,0:13:35.57,0:13:37.93,Default,,0,0,0,,Let me show you another example\r\nDialogue: 0,0:13:37.97,0:13:38.86,Default,,0,0,0,,sticking with square roots.\r\nDialogue: 0,0:13:38.89,0:13:42.16,Default,,0,0,0,,Let's go back and take another look at that slide\r\nDialogue: 0,0:13:42.19,0:13:43.75,Default,,0,0,0,,with the square root algorithm on it.\r\nDialogue: 0,0:13:44.16,0:13:45.62,Default,,0,0,0,,Remember what that says.\r\nDialogue: 0,0:13:45.79,0:13:49.82,Default,,0,0,0,,That says, in order to do something, I make a guess,\r\nDialogue: 0,0:13:50.62,0:13:54.84,Default,,0,0,0,,and I improve that guess, and I sort of keep improving that guess.\r\nDialogue: 0,0:13:55.66,0:14:00.14,Default,,0,0,0,,So there's the general strategy of, I'm looking for something,\r\nDialogue: 0,0:14:01.15,0:14:04.00,Default,,0,0,0,,and the way I find it is that I keep improving it.\r\nDialogue: 0,0:14:04.16,0:14:10.25,Default,,0,0,0,,Now, that's a particular case of another kind of strategy\r\nDialogue: 0,0:14:10.97,0:14:13.23,Default,,0,0,0,,for finding a fixed point of something.\r\nDialogue: 0,0:14:14.57,0:14:16.59,Default,,0,0,0,,So you have a fixed point of a function.\r\nDialogue: 0,0:14:17.13,0:14:26.03,Default,,0,0,0,,A fixed point of a function is something, is a value.\r\nDialogue: 0,0:14:26.13,0:14:31.79,Default,,0,0,0,,A fixed point of a function F is a value Y, such that F of Y equals Y.\r\nDialogue: 0,0:14:32.97,0:14:40.89,Default,,0,0,0,,And the way I might do that is start with a guess.\r\nDialogue: 0,0:14:42.00,0:14:45.85,Default,,0,0,0,,And then if I want something that doesn't change when I keep applying F,\r\nDialogue: 0,0:14:45.96,0:14:49.45,Default,,0,0,0,,is I'll keep applying F over and over until that result doesn't change very much.\r\nDialogue: 0,0:14:50.05,0:14:51.93,Default,,0,0,0,,So there's a general strategy.\r\nDialogue: 0,0:14:52.24,0:14:56.17,Default,,0,0,0,,And then, for example, to compute the square root of X,\r\nDialogue: 0,0:14:56.24,0:15:03.45,Default,,0,0,0,,I can try and find a fixed point of the function which takes Y to the average of X/Y.\r\nDialogue: 0,0:15:03.55,0:15:07.52,Default,,0,0,0,,And the idea that is that if I really had Y equal to the square root of X,\r\nDialogue: 0,0:15:08.01,0:15:11.80,Default,,0,0,0,,then Y and X/Y would be the same value.\r\nDialogue: 0,0:15:12.00,0:15:13.90,Default,,0,0,0,,They'd both be the square root of X,\r\nDialogue: 0,0:15:14.86,0:15:18.85,Default,,0,0,0,,because X over the square root of X is the square root of X.\r\nDialogue: 0,0:15:19.09,0:15:21.84,Default,,0,0,0,,And so the average if Y were equal to the square of X,\r\nDialogue: 0,0:15:22.25,0:15:25.21,Default,,0,0,0,,then the average wouldn't change.\r\nDialogue: 0,0:15:25.98,0:15:28.93,Default,,0,0,0,,So the square root of X is a fixed point of that particular function.\r\nDialogue: 0,0:15:30.09,0:15:33.85,Default,,0,0,0,,Now, what I'd like to have, I'd like to express\r\nDialogue: 0,0:15:33.98,0:15:36.42,Default,,0,0,0,,the general strategy for finding fixed points.\r\nDialogue: 0,0:15:36.57,0:15:40.13,Default,,0,0,0,,So what I might imagine doing, is to find,\r\nDialogue: 0,0:15:41.02,0:15:46.45,Default,,0,0,0,,is to be able to use my language to define a box that says \"fixed point,\"\r\nDialogue: 0,0:15:49.58,0:15:52.19,Default,,0,0,0,,just like I could make a box that says \"square root.\"\r\nDialogue: 0,0:15:52.21,0:15:55.18,Default,,0,0,0,,And I'd like to be able to express this in my language.\r\nDialogue: 0,0:15:56.08,0:16:01.37,Default,,0,0,0,,So I'd like to express not only the imperative how-to knowledge\r\nDialogue: 0,0:16:01.42,0:16:03.21,Default,,0,0,0,,of a particular thing like square root,\r\nDialogue: 0,0:16:03.58,0:16:05.60,Default,,0,0,0,,but I'd like to be able to express the imperative knowledge\r\nDialogue: 0,0:16:05.66,0:16:08.27,Default,,0,0,0,,of how to do a general thing like how to find fixed point.\r\nDialogue: 0,0:16:09.82,0:16:12.25,Default,,0,0,0,,And in fact, let's go back and look at that slide again.\r\nDialogue: 0,0:16:15.02,0:16:23.28,Default,,0,0,0,,See, not only is this a piece of imperative knowledge,\r\nDialogue: 0,0:16:23.33,0:16:25.32,Default,,0,0,0,,how to find a fixed point,\r\nDialogue: 0,0:16:26.25,0:16:27.39,Default,,0,0,0,,but over here on the bottom,\r\nDialogue: 0,0:16:27.42,0:16:30.32,Default,,0,0,0,,there's another piece of imperative knowledge which says,\r\nDialogue: 0,0:16:30.41,0:16:35.85,Default,,0,0,0,,one way to compute square root is to apply this general fixed point method.\r\nDialogue: 0,0:16:36.17,0:16:38.89,Default,,0,0,0,,So I'd like to also be able to express that imperative knowledge.\r\nDialogue: 0,0:16:39.74,0:16:40.70,Default,,0,0,0,,What would that look like?\r\nDialogue: 0,0:16:40.73,0:16:44.90,Default,,0,0,0,,That would say, this fixed point box is such that\r\nDialogue: 0,0:16:45.76,0:16:58.21,Default,,0,0,0,,if I input to it the function that takes Y to the average of Y and X/Y,\r\nDialogue: 0,0:16:59.77,0:17:06.23,Default,,0,0,0,,then what should come out of that fixed point box is a method for finding square roots.\r\nDialogue: 0,0:17:08.91,0:17:10.24,Default,,0,0,0,,So in these boxes we're building,\r\nDialogue: 0,0:17:10.27,0:17:15.07,Default,,0,0,0,,we're not only building boxes that you input numbers and output numbers,\r\nDialogue: 0,0:17:16.40,0:17:18.54,Default,,0,0,0,,we're going to be building in boxes that,\r\nDialogue: 0,0:17:18.67,0:17:21.34,Default,,0,0,0,,in effect, compute methods like finding square root.\r\nDialogue: 0,0:17:22.22,0:17:25.85,Default,,0,0,0,,And my take is their inputs functions,\r\nDialogue: 0,0:17:26.49,0:17:29.29,Default,,0,0,0,,like Y goes to the average of Y and X/Y.\r\nDialogue: 0,0:17:29.71,0:17:31.49,Default,,0,0,0,,The reason we want to do that,\r\nDialogue: 0,0:17:32.21,0:17:35.60,Default,,0,0,0,,the reason this is a procedure, will end up being a procedure,\r\nDialogue: 0,0:17:35.63,0:17:38.61,Default,,0,0,0,,as we'll see, whose value is another procedure,\r\nDialogue: 0,0:17:39.31,0:17:41.10,Default,,0,0,0,,the reason we want to do that is because\r\nDialogue: 0,0:17:41.52,0:17:46.27,Default,,0,0,0,,procedures are going to be our ways of talking about imperative knowledge.\r\nDialogue: 0,0:17:48.00,0:17:49.93,Default,,0,0,0,,And the way to make that very powerful is\r\nDialogue: 0,0:17:49.93,0:17:52.13,Default,,0,0,0,,to be able to talk about other kinds of knowledge.\r\nDialogue: 0,0:17:53.42,0:17:56.52,Default,,0,0,0,,So here is a procedure that, in effect, talks about another procedure,\r\nDialogue: 0,0:17:57.10,0:18:00.34,Default,,0,0,0,,a general strategy that itself talks about general strategies.\r\nDialogue: 0,0:18:03.57,0:18:08.24,Default,,0,0,0,,Well, our first topic in this course--\r\nDialogue: 0,0:18:08.25,0:18:09.69,Default,,0,0,0,,there'll be three major topics--\r\nDialogue: 0,0:18:09.74,0:18:10.94,Default,,0,0,0,,will be black-box abstraction.\r\nDialogue: 0,0:18:10.97,0:18:13.31,Default,,0,0,0,,Let's look at that in a little bit more detail.\r\nDialogue: 0,0:18:15.12,0:18:24.04,Default,,0,0,0,,What we're going to do is we will start out talking about\r\nDialogue: 0,0:18:24.08,0:18:26.72,Default,,0,0,0,,how Lisp is built up out of primitive objects.\r\nDialogue: 0,0:18:27.36,0:18:29.20,Default,,0,0,0,,What does the language supply with us?\r\nDialogue: 0,0:18:29.49,0:18:33.58,Default,,0,0,0,,And we'll see that there are primitive procedures and primitive data.\r\nDialogue: 0,0:18:36.16,0:18:37.04,Default,,0,0,0,,Then we're going to see,\r\nDialogue: 0,0:18:37.05,0:18:38.77,Default,,0,0,0,,how do you take those primitives and\r\nDialogue: 0,0:18:38.81,0:18:40.76,Default,,0,0,0,,combine them to make more complicated things,\r\nDialogue: 0,0:18:41.45,0:18:42.92,Default,,0,0,0,,means of combination?\r\nDialogue: 0,0:18:43.20,0:18:46.30,Default,,0,0,0,,And what we'll see is that there are ways of putting things together,\r\nDialogue: 0,0:18:46.45,0:18:50.48,Default,,0,0,0,,putting primitive procedures together to make more complicated procedures.\r\nDialogue: 0,0:18:50.96,0:18:54.43,Default,,0,0,0,,And we'll see how to put primitive data together to make compound data.\r\nDialogue: 0,0:18:56.21,0:18:59.34,Default,,0,0,0,,Then we'll say, well, having made those compounds things,\r\nDialogue: 0,0:18:59.79,0:19:01.29,Default,,0,0,0,,how do you abstract them?\r\nDialogue: 0,0:19:02.91,0:19:04.97,Default,,0,0,0,,How do you put those black boxes around them\r\nDialogue: 0,0:19:05.04,0:19:07.73,Default,,0,0,0,,so you can use them as components in more complex things?\r\nDialogue: 0,0:19:08.16,0:19:10.93,Default,,0,0,0,,And we'll see that's done by defining procedures and\r\nDialogue: 0,0:19:11.52,0:19:14.79,Default,,0,0,0,,a technique for dealing with compound data called data abstraction.\r\nDialogue: 0,0:19:15.61,0:19:17.36,Default,,0,0,0,,And then, what's maybe the most important thing,\r\nDialogue: 0,0:19:17.92,0:19:21.49,Default,,0,0,0,,is going from just the rules to how does an expert work?\r\nDialogue: 0,0:19:21.61,0:19:27.12,Default,,0,0,0,,How do you express common patterns of doing things, like saying, well,\r\nDialogue: 0,0:19:27.15,0:19:28.64,Default,,0,0,0,,there's a general method of fixed point and\r\nDialogue: 0,0:19:28.69,0:19:30.87,Default,,0,0,0,,square root is a particular case of that?\r\nDialogue: 0,0:19:31.90,0:19:34.41,Default,,0,0,0,,And we're going to use--\r\nDialogue: 0,0:19:34.59,0:19:35.63,Default,,0,0,0,,I've already hinted at it--\r\nDialogue: 0,0:19:35.66,0:19:37.30,Default,,0,0,0,,something called higher-order procedures,\r\nDialogue: 0,0:19:37.34,0:19:42.05,Default,,0,0,0,,namely procedures whose inputs and outputs are themselves procedures.\r\nDialogue: 0,0:19:42.96,0:19:44.86,Default,,0,0,0,,And then we'll also see something very interesting.\r\nDialogue: 0,0:19:44.86,0:19:48.49,Default,,0,0,0,,We'll see, as we go further and further on and become more abstract,\r\nDialogue: 0,0:19:48.80,0:19:50.31,Default,,0,0,0,,there'll be very--\r\nDialogue: 0,0:19:50.43,0:19:53.61,Default,,0,0,0,,well, the line between what we consider to be data and\r\nDialogue: 0,0:19:53.63,0:19:57.80,Default,,0,0,0,,what we consider to be procedures is going to blur at an incredible rate.\r\nDialogue: 0,0:20:02.89,0:20:07.12,Default,,0,0,0,,Well, that's our first subject, black-box abstraction.\r\nDialogue: 0,0:20:07.12,0:20:08.62,Default,,0,0,0,,Let's look at the second topic.\r\nDialogue: 0,0:20:11.10,0:20:13.88,Default,,0,0,0,,I can introduce it like this.\r\nDialogue: 0,0:20:13.89,0:20:18.09,Default,,0,0,0,,See, suppose I want to express the idea--\r\nDialogue: 0,0:20:19.42,0:20:22.51,Default,,0,0,0,,remember, we're talking about ideas--\r\nDialogue: 0,0:20:22.91,0:20:25.53,Default,,0,0,0,,suppose I want to express the idea that\r\nDialogue: 0,0:20:26.41,0:20:35.12,Default,,0,0,0,,I can take something and multiply it by the sum of two other things.\r\nDialogue: 0,0:20:36.09,0:20:37.93,Default,,0,0,0,,So for example, I might say,\r\nDialogue: 0,0:20:38.11,0:20:41.52,Default,,0,0,0,,if I had 1 and 3 and multiply that by 2, I get 8.\r\nDialogue: 0,0:20:42.03,0:20:45.11,Default,,0,0,0,,But I'm talking about the general idea of what's called linear combination,\r\nDialogue: 0,0:20:45.44,0:20:47.98,Default,,0,0,0,,that you can add two things and multiply them by something else.\r\nDialogue: 0,0:20:49.28,0:20:51.01,Default,,0,0,0,,It's very easy when I think about it for numbers,\r\nDialogue: 0,0:20:51.05,0:20:55.41,Default,,0,0,0,,but suppose I also want to use that same idea to think about,\r\nDialogue: 0,0:20:56.08,0:20:58.58,Default,,0,0,0,,I could add two vectors, a1 and a2,\r\nDialogue: 0,0:20:59.89,0:21:03.26,Default,,0,0,0,,and then scale them by some factor x and get another vector.\r\nDialogue: 0,0:21:03.33,0:21:09.75,Default,,0,0,0,,Or I might say, I want to think about a1 and a2 as being polynomials,\r\nDialogue: 0,0:21:11.07,0:21:13.90,Default,,0,0,0,,and I might want to add those two polynomials and\r\nDialogue: 0,0:21:13.92,0:21:16.86,Default,,0,0,0,,then multiply them by 2 to get a more complicated one.\r\nDialogue: 0,0:21:20.16,0:21:23.83,Default,,0,0,0,,Or a1 and a2 might be electrical signals,\r\nDialogue: 0,0:21:24.56,0:21:27.77,Default,,0,0,0,,and I might want to think about summing those two electrical signals and\r\nDialogue: 0,0:21:27.81,0:21:30.27,Default,,0,0,0,,then putting the whole thing through an amplifier,\r\nDialogue: 0,0:21:30.28,0:21:33.03,Default,,0,0,0,,multiplying it by some factor of 2 or something.\r\nDialogue: 0,0:21:33.82,0:21:36.93,Default,,0,0,0,,The idea is I want to think about the general notion of that.\r\nDialogue: 0,0:21:38.32,0:21:45.42,Default,,0,0,0,,Now, if our language is going to be good language for expressing those kind of general ideas,\r\nDialogue: 0,0:21:47.07,0:21:49.31,Default,,0,0,0,,if I really, really can do that,\r\nDialogue: 0,0:21:50.65,0:21:52.09,Default,,0,0,0,,I'd like to be able to say\r\nDialogue: 0,0:21:54.99,0:22:00.41,Default,,0,0,0,,I'm going to multiply by x the sum of a1 and a2,\r\nDialogue: 0,0:22:02.80,0:22:05.07,Default,,0,0,0,,and I'd like that to express the general idea of\r\nDialogue: 0,0:22:06.03,0:22:09.23,Default,,0,0,0,,all different kinds of things that a1 and a2 could be.\r\nDialogue: 0,0:22:10.03,0:22:11.58,Default,,0,0,0,,Now, if you think about that, there's a problem,\r\nDialogue: 0,0:22:11.58,0:22:16.17,Default,,0,0,0,,because after all, the actual primitive operations\r\nDialogue: 0,0:22:16.21,0:22:18.33,Default,,0,0,0,,that go on in the machine are obviously going to be different\r\nDialogue: 0,0:22:18.38,0:22:22.98,Default,,0,0,0,,if I'm adding two numbers than if I'm adding two polynomials,\r\nDialogue: 0,0:22:23.29,0:22:27.49,Default,,0,0,0,,or if I'm adding the representation of two electrical signals or wave forms.\r\nDialogue: 0,0:22:27.89,0:22:32.53,Default,,0,0,0,,Somewhere, there has to be the knowledge of the kinds of various things\r\nDialogue: 0,0:22:32.87,0:22:34.25,Default,,0,0,0,,that you can add and the ways of adding them.\r\nDialogue: 0,0:22:37.09,0:22:38.64,Default,,0,0,0,,Now, to construct such a system,\r\nDialogue: 0,0:22:38.78,0:22:40.67,Default,,0,0,0,,the question is, where do I put that knowledge?\r\nDialogue: 0,0:22:41.20,0:22:44.41,Default,,0,0,0,,How do I think about the different kinds of choices I have?\r\nDialogue: 0,0:22:44.56,0:22:48.42,Default,,0,0,0,,And if tomorrow George comes up with a new kind of object\r\nDialogue: 0,0:22:48.45,0:22:50.32,Default,,0,0,0,,that might be added and multiplied,\r\nDialogue: 0,0:22:51.01,0:22:53.32,Default,,0,0,0,,how do I add George's new object to the system\r\nDialogue: 0,0:22:53.52,0:22:55.68,Default,,0,0,0,,without screwing up everything that was already there?\r\nDialogue: 0,0:22:57.81,0:23:00.54,Default,,0,0,0,,Well, that's going to be the second big topic,\r\nDialogue: 0,0:23:00.57,0:23:03.16,Default,,0,0,0,,the way of controlling that kind of complexity.\r\nDialogue: 0,0:23:03.84,0:23:08.43,Default,,0,0,0,,And the way you do that is by establishing conventional interfaces,\r\nDialogue: 0,0:23:17.44,0:23:20.21,Default,,0,0,0,,agreed upon ways of plugging things together.\r\nDialogue: 0,0:23:20.25,0:23:22.04,Default,,0,0,0,,Just like in electrical engineering,\r\nDialogue: 0,0:23:22.94,0:23:25.39,Default,,0,0,0,,people have standard impedances for connectors,\r\nDialogue: 0,0:23:26.16,0:23:28.62,Default,,0,0,0,,and then you know if you build something with one of those standard impedances,\r\nDialogue: 0,0:23:28.67,0:23:30.40,Default,,0,0,0,,you can plug it together with something else.\r\nDialogue: 0,0:23:32.78,0:23:35.68,Default,,0,0,0,,So that's going to be our second large topic, conventional interfaces.\r\nDialogue: 0,0:23:35.73,0:23:40.94,Default,,0,0,0,,What we're going to see is, first, we're going to talk about the problem of generic operations,\r\nDialogue: 0,0:23:40.97,0:23:42.22,Default,,0,0,0,,which is the one I alluded to,\r\nDialogue: 0,0:23:42.59,0:23:47.28,Default,,0,0,0,,things like \"plus\" that have to work with all different kinds of data.\r\nDialogue: 0,0:23:52.61,0:23:54.57,Default,,0,0,0,,So we talk about generic operations.\r\nDialogue: 0,0:23:54.61,0:23:56.99,Default,,0,0,0,,Then we're going to talk about really large-scale structures.\r\nDialogue: 0,0:23:58.32,0:24:00.83,Default,,0,0,0,,How do you put together very large programs\r\nDialogue: 0,0:24:01.02,0:24:04.89,Default,,0,0,0,,that model the kinds of complex systems in the real world that you'd like to model?\r\nDialogue: 0,0:24:05.53,0:24:06.53,Default,,0,0,0,,And what we're going to see is that\r\nDialogue: 0,0:24:06.57,0:24:11.81,Default,,0,0,0,,there are two very important metaphors for putting together such systems.\r\nDialogue: 0,0:24:11.85,0:24:13.90,Default,,0,0,0,,One is called object-oriented programming,\r\nDialogue: 0,0:24:14.09,0:24:18.94,Default,,0,0,0,,where you sort of think of your system as a kind of society\r\nDialogue: 0,0:24:19.37,0:24:22.36,Default,,0,0,0,,full of little things that interact by sending information between them.\r\nDialogue: 0,0:24:23.44,0:24:27.81,Default,,0,0,0,,And then the second one is operations on aggregates, called streams,\r\nDialogue: 0,0:24:27.98,0:24:31.50,Default,,0,0,0,,where you think of a large system put together kind of\r\nDialogue: 0,0:24:31.50,0:24:35.29,Default,,0,0,0,,like a signal processing engineer puts together a large electrical system.\r\nDialogue: 0,0:24:38.93,0:24:40.49,Default,,0,0,0,,That's going to be our second topic.\r\nDialogue: 0,0:24:43.37,0:24:45.93,Default,,0,0,0,,Now, the third thing we're going to come to,\r\nDialogue: 0,0:24:45.95,0:24:49.70,Default,,0,0,0,,the third basic technique for controlling complexity,\r\nDialogue: 0,0:24:49.74,0:24:50.94,Default,,0,0,0,,is making new languages.\r\nDialogue: 0,0:24:51.69,0:24:55.42,Default,,0,0,0,,Because sometimes, when you're sort of overwhelmed by the complexity of a design,\r\nDialogue: 0,0:24:55.47,0:24:59.69,Default,,0,0,0,,the way that you control that complexity is to pick a new design language.\r\nDialogue: 0,0:25:01.41,0:25:05.60,Default,,0,0,0,,And the purpose of the new design language will be to highlight different aspects of the system.\r\nDialogue: 0,0:25:05.79,0:25:09.36,Default,,0,0,0,,It will suppress some kinds of details and emphasize other kinds of details.\r\nDialogue: 0,0:25:12.99,0:25:15.93,Default,,0,0,0,,This is going to be the most magical part of the course.\r\nDialogue: 0,0:25:16.03,0:25:21.20,Default,,0,0,0,,We're going to start out by actually looking at the technology for building new computer languages.\r\nDialogue: 0,0:25:21.82,0:25:26.30,Default,,0,0,0,,The first thing we're going to do is actually build in Lisp.\r\nDialogue: 0,0:25:29.23,0:25:34.02,Default,,0,0,0,,We're going to express in Lisp the process of interpreting Lisp itself.\r\nDialogue: 0,0:25:34.29,0:25:36.94,Default,,0,0,0,,And that's going to be a very sort of self-circular thing.\r\nDialogue: 0,0:25:36.96,0:25:39.92,Default,,0,0,0,,There's a little mystical symbol that has to do with that.\r\nDialogue: 0,0:25:40.97,0:25:46.38,Default,,0,0,0,,The process of interpreting Lisp is sort of a giant wheel of two processes,\r\nDialogue: 0,0:25:46.57,0:25:47.71,Default,,0,0,0,,apply and eval,\r\nDialogue: 0,0:25:47.89,0:25:50.87,Default,,0,0,0,,which sort of constantly reduce expressions to each other.\r\nDialogue: 0,0:25:52.54,0:25:54.24,Default,,0,0,0,,Then we're going to see all sorts of other magical things.\r\nDialogue: 0,0:25:54.25,0:25:56.85,Default,,0,0,0,,Here's another magical symbol.\r\nDialogue: 0,0:25:57.12,0:26:01.52,Default,,0,0,0,,This is sort of the Y operator,\r\nDialogue: 0,0:26:01.55,0:26:06.45,Default,,0,0,0,,which is, in some sense, the expression of infinity inside our procedural language.\r\nDialogue: 0,0:26:06.51,0:26:07.44,Default,,0,0,0,,We'll take a look at that.\r\nDialogue: 0,0:26:08.40,0:26:13.73,Default,,0,0,0,,In any case, this section of the course is called Metalinguistic Abstraction,\r\nDialogue: 0,0:26:16.17,0:26:26.23,Default,,0,0,0,,abstracting by talking about how you construct new languages.\r\nDialogue: 0,0:26:30.22,0:26:35.71,Default,,0,0,0,,As I said, we're going to start out by looking at the process of interpretation.\r\nDialogue: 0,0:26:35.74,0:26:42.12,Default,,0,0,0,,We're going to look at this apply-eval loop, and build Lisp.\r\nDialogue: 0,0:26:42.16,0:26:44.17,Default,,0,0,0,,Then, just to show you that this is very general,\r\nDialogue: 0,0:26:44.37,0:26:48.26,Default,,0,0,0,,we're going to use exactly the same technology to build a very different kind of language,\r\nDialogue: 0,0:26:48.53,0:26:50.31,Default,,0,0,0,,a so-called logic programming language,\r\nDialogue: 0,0:26:50.53,0:26:54.83,Default,,0,0,0,,where you don't really talk about procedures at all that have inputs and outputs.\r\nDialogue: 0,0:26:54.86,0:26:57.25,Default,,0,0,0,,What you do is talk about relations between things.\r\nDialogue: 0,0:26:57.31,0:27:03.92,Default,,0,0,0,,And then finally, we're going to talk about how you implement these things very concretely\r\nDialogue: 0,0:27:03.95,0:27:05.60,Default,,0,0,0,,on the very simplest kind of machines.\r\nDialogue: 0,0:27:05.65,0:27:08.39,Default,,0,0,0,,We'll see something like this.\r\nDialogue: 0,0:27:09.13,0:27:12.14,Default,,0,0,0,,This is a picture of a chip,\r\nDialogue: 0,0:27:12.16,0:27:17.47,Default,,0,0,0,,which is the Lisp interpreter that we will be talking about then in hardware.\r\nDialogue: 0,0:27:20.88,0:27:23.79,Default,,0,0,0,,Well, there's an outline of the course, three big topics.\r\nDialogue: 0,0:27:24.88,0:27:29.41,Default,,0,0,0,,Black-box abstraction, conventional interfaces, metalinguistic abstraction.\r\nDialogue: 0,0:27:31.58,0:27:33.57,Default,,0,0,0,,Now, let's take a break now and then we'll get started.\r\nDialogue: 0,0:27:52.19,0:28:03.42,Default,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\r\nDialogue: 0,0:28:03.92,0:28:06.84,Default,,0,0,0,,Let's actually start in learning Lisp now.\r\nDialogue: 0,0:28:08.06,0:28:10.75,Default,,0,0,0,,Actually, we'll start out by learning something much more important,\r\nDialogue: 0,0:28:10.80,0:28:14.33,Default,,0,0,0,,maybe the very most important thing in this course, which is not Lisp,\r\nDialogue: 0,0:28:14.38,0:28:18.41,Default,,0,0,0,,in particular, of course, but rather a general framework\r\nDialogue: 0,0:28:18.62,0:28:21.89,Default,,0,0,0,,for thinking about languages that I already alluded to.\r\nDialogue: 0,0:28:22.12,0:28:25.10,Default,,0,0,0,,When somebody tells you they're going to show you a language,\r\nDialogue: 0,0:28:25.13,0:28:26.16,Default,,0,0,0,,what you should say is,\r\nDialogue: 0,0:28:26.19,0:28:32.87,Default,,0,0,0,,what I'd like you to tell me is what are the primitive elements?\r\nDialogue: 0,0:28:37.50,0:28:38.78,Default,,0,0,0,,What does the language come with?\r\nDialogue: 0,0:28:38.96,0:28:43.53,Default,,0,0,0,,Then, what are the ways you put those together?\r\nDialogue: 0,0:28:43.68,0:28:47.42,Default,,0,0,0,,What are the means of combination?\r\nDialogue: 0,0:28:50.17,0:28:54.18,Default,,0,0,0,,What are the things that allow you to take these primitive elements\r\nDialogue: 0,0:28:54.37,0:28:56.51,Default,,0,0,0,,and build bigger things out of them?\r\nDialogue: 0,0:28:58.01,0:28:59.61,Default,,0,0,0,,What are the ways of putting things together?\r\nDialogue: 0,0:29:01.39,0:29:05.69,Default,,0,0,0,,And then, what are the means of abstraction?\r\nDialogue: 0,0:29:08.35,0:29:16.85,Default,,0,0,0,,How do we take those complicated things and draw those boxes around them?\r\nDialogue: 0,0:29:16.88,0:29:19.66,Default,,0,0,0,,How do we name them so that we can now use them\r\nDialogue: 0,0:29:19.68,0:29:23.85,Default,,0,0,0,,as if they were primitive elements in making still more complex things?\r\nDialogue: 0,0:29:23.89,0:29:25.66,Default,,0,0,0,,And so on, and so on, and so on.\r\nDialogue: 0,0:29:26.89,0:29:28.08,Default,,0,0,0,,So when someone says to you, gee,\r\nDialogue: 0,0:29:28.09,0:29:29.55,Default,,0,0,0,,I have a great new computer language,\r\nDialogue: 0,0:29:30.86,0:29:34.70,Default,,0,0,0,,you don't say, how many characters does it take to invert a matrix?\r\nDialogue: 0,0:29:35.73,0:29:36.88,Default,,0,0,0,,It's irrelevant.\r\nDialogue: 0,0:29:37.39,0:29:42.30,Default,,0,0,0,,What you say is, if the language did not come with matrices built in\r\nDialogue: 0,0:29:42.33,0:29:43.37,Default,,0,0,0,,or with something else built in,\r\nDialogue: 0,0:29:43.37,0:29:46.03,Default,,0,0,0,,how could I then build that thing?\r\nDialogue: 0,0:29:46.05,0:29:48.47,Default,,0,0,0,,What are the means of combination which would allow me to do that?\r\nDialogue: 0,0:29:48.62,0:29:50.71,Default,,0,0,0,,And then, what are the means of abstraction\r\nDialogue: 0,0:29:51.68,0:29:54.21,Default,,0,0,0,,which allow me then to use those as elements\r\nDialogue: 0,0:29:54.22,0:29:56.52,Default,,0,0,0,,in making more complicated things yet?\r\nDialogue: 0,0:29:58.75,0:30:04.61,Default,,0,0,0,,Well, we're going to see that Lisp has some primitive data and some primitive procedures.\r\nDialogue: 0,0:30:05.25,0:30:07.50,Default,,0,0,0,,In fact, let's really start.\r\nDialogue: 0,0:30:07.55,0:30:14.89,Default,,0,0,0,,And here's a piece of primitive data in Lisp, number 3.\r\nDialogue: 0,0:30:16.27,0:30:19.87,Default,,0,0,0,,Actually, if I'm being very pedantic, that's not the number 3.\r\nDialogue: 0,0:30:19.93,0:30:25.57,Default,,0,0,0,,That's some symbol that represents Plato's concept of the number 3.\r\nDialogue: 0,0:30:26.67,0:30:28.93,Default,,0,0,0,,And here's another.\r\nDialogue: 0,0:30:30.48,0:30:36.06,Default,,0,0,0,,Here's some more primitive data in Lisp, 17.4.\r\nDialogue: 0,0:30:36.08,0:30:39.42,Default,,0,0,0,,Or actually, some representation of 17.4.\r\nDialogue: 0,0:30:40.99,0:30:44.48,Default,,0,0,0,,And here's another one, 5.\r\nDialogue: 0,0:30:46.86,0:30:52.21,Default,,0,0,0,,Here's another primitive object that's built in Lisp, addition.\r\nDialogue: 0,0:30:52.25,0:30:55.68,Default,,0,0,0,,Actually, to use the same kind of pedantic--\r\nDialogue: 0,0:30:55.71,0:31:00.47,Default,,0,0,0,,this is a name for the primitive method of adding things.\r\nDialogue: 0,0:31:00.53,0:31:02.53,Default,,0,0,0,,Just like this is a name for Plato's number 3,\r\nDialogue: 0,0:31:02.61,0:31:09.32,Default,,0,0,0,,this is a name for Plato's concept of how you add things.\r\nDialogue: 0,0:31:10.32,0:31:11.98,Default,,0,0,0,,So those are some primitive elements.\r\nDialogue: 0,0:31:12.14,0:31:13.76,Default,,0,0,0,,I can put them together.\r\nDialogue: 0,0:31:14.14,0:31:18.29,Default,,0,0,0,,I can say, gee, what's the sum of 3 and 17.4 and 5?\r\nDialogue: 0,0:31:18.69,0:31:21.31,Default,,0,0,0,,And the way I do that is to say,\r\nDialogue: 0,0:31:21.33,0:31:27.71,Default,,0,0,0,,let's apply the sum operator to these three numbers.\r\nDialogue: 0,0:31:27.74,0:31:31.15,Default,,0,0,0,,And I should get, what? 8, 17. 25.4.\r\nDialogue: 0,0:31:34.43,0:31:38.05,Default,,0,0,0,,So I should be able to ask Lisp what the value of this is,\r\nDialogue: 0,0:31:38.94,0:31:40.77,Default,,0,0,0,,and it will return 25.4.\r\nDialogue: 0,0:31:43.58,0:31:44.83,Default,,0,0,0,,Let's introduce some names.\r\nDialogue: 0,0:31:44.88,0:31:51.47,Default,,0,0,0,,This thing that I typed is called a combination.\r\nDialogue: 0,0:31:56.88,0:32:01.94,Default,,0,0,0,,And a combination consists, in general, of applying an operator--\r\nDialogue: 0,0:32:03.39,0:32:04.72,Default,,0,0,0,,so this is an operator--\r\nDialogue: 0,0:32:09.71,0:32:12.05,Default,,0,0,0,,to some operands.\r\nDialogue: 0,0:32:13.25,0:32:14.54,Default,,0,0,0,,These are the operands.\r\nDialogue: 0,0:32:21.89,0:32:23.79,Default,,0,0,0,,And of course, I can make more complex things.\r\nDialogue: 0,0:32:23.82,0:32:28.56,Default,,0,0,0,,The reason I can get complexity out of this is because the operands themselves,\r\nDialogue: 0,0:32:29.52,0:32:31.09,Default,,0,0,0,,in general, can be combinations.\r\nDialogue: 0,0:32:31.15,0:32:44.47,Default,,0,0,0,,So for instance, I could say, what is the sum of 3 and the product of 5 and 6 and 8 and 2?\r\nDialogue: 0,0:32:45.66,0:32:52.16,Default,,0,0,0,,And I should get-- let's see-- 30, 40, 43.\r\nDialogue: 0,0:32:52.73,0:32:54.81,Default,,0,0,0,,So Lisp should tell me that that's 43.\r\nDialogue: 0,0:32:56.56,0:33:02.80,Default,,0,0,0,,Forming combinations is the basic needs of combination that we'll be looking at.\r\nDialogue: 0,0:33:04.65,0:33:09.22,Default,,0,0,0,,And then, well, you see some syntax here.\r\nDialogue: 0,0:33:10.56,0:33:13.04,Default,,0,0,0,,Lisp uses what's called prefix notation,\r\nDialogue: 0,0:33:16.22,0:33:25.21,Default,,0,0,0,,which means that the operator is written to the left of the operands.\r\nDialogue: 0,0:33:25.47,0:33:26.48,Default,,0,0,0,,It's just a convention.\r\nDialogue: 0,0:33:27.66,0:33:29.77,Default,,0,0,0,,And notice, it's fully parenthesized.\r\nDialogue: 0,0:33:30.08,0:33:32.32,Default,,0,0,0,,And the parentheses make it completely unambiguous.\r\nDialogue: 0,0:33:32.32,0:33:36.99,Default,,0,0,0,,So by looking at this, I can see that there's the operator,\r\nDialogue: 0,0:33:37.01,0:33:40.99,Default,,0,0,0,,and there are 1, 2, 3, 4 operands.\r\nDialogue: 0,0:33:42.38,0:33:47.97,Default,,0,0,0,,And I can see that the second operand here is itself some combination\r\nDialogue: 0,0:33:48.88,0:33:51.55,Default,,0,0,0,,that has one operator and two operands.\r\nDialogue: 0,0:33:52.43,0:33:54.27,Default,,0,0,0,,Parentheses in Lisp are a little bit,\r\nDialogue: 0,0:33:54.61,0:33:57.71,Default,,0,0,0,,or are very unlike parentheses in conventional mathematics.\r\nDialogue: 0,0:33:57.77,0:34:00.11,Default,,0,0,0,,In mathematics, we sort of use them to mean grouping,\r\nDialogue: 0,0:34:01.21,0:34:03.75,Default,,0,0,0,,and it sort of doesn't hurt if sometimes you leave out parentheses\r\nDialogue: 0,0:34:03.77,0:34:05.56,Default,,0,0,0,,if people understand that that's a group.\r\nDialogue: 0,0:34:05.76,0:34:08.51,Default,,0,0,0,,And in general, it doesn't hurt if you put in extra parentheses,\r\nDialogue: 0,0:34:08.86,0:34:10.94,Default,,0,0,0,,because that maybe makes the grouping more distinct.\r\nDialogue: 0,0:34:10.96,0:34:11.77,Default,,0,0,0,,Lisp is not like that.\r\nDialogue: 0,0:34:13.12,0:34:15.37,Default,,0,0,0,,In Lisp, you cannot leave out parentheses,\r\nDialogue: 0,0:34:16.38,0:34:18.56,Default,,0,0,0,,and you cannot put in extra parentheses,\r\nDialogue: 0,0:34:19.33,0:34:21.28,Default,,0,0,0,,because putting in parentheses always means,\r\nDialogue: 0,0:34:21.37,0:34:27.05,Default,,0,0,0,,exactly and precisely, this is a combination which has meaning,\r\nDialogue: 0,0:34:27.09,0:34:28.81,Default,,0,0,0,,applying operators to operands.\r\nDialogue: 0,0:34:29.04,0:34:32.62,Default,,0,0,0,,And if I left this out, if I left those parentheses out,\r\nDialogue: 0,0:34:32.65,0:34:33.96,Default,,0,0,0,,it would mean something else.\r\nDialogue: 0,0:34:35.41,0:34:37.25,Default,,0,0,0,,In fact, the way to think about this,\r\nDialogue: 0,0:34:37.41,0:34:41.65,Default,,0,0,0,,is really what I'm doing when I write something like this is writing a tree.\r\nDialogue: 0,0:34:42.37,0:34:47.30,Default,,0,0,0,,So this combination is a tree that has a plus and\r\nDialogue: 0,0:34:47.37,0:34:54.46,Default,,0,0,0,,then a 3 and then a something else and an 8 and a 2.\r\nDialogue: 0,0:34:54.48,0:34:56.35,Default,,0,0,0,,And then this something else here is\r\nDialogue: 0,0:34:56.35,0:35:03.22,Default,,0,0,0,,itself a little subtree that has a star and a 5 and a 6.\r\nDialogue: 0,0:35:03.95,0:35:05.53,Default,,0,0,0,,And the way to think of that is, really,\r\nDialogue: 0,0:35:05.55,0:35:09.00,Default,,0,0,0,,what's going on are we're writing these trees,\r\nDialogue: 0,0:35:09.21,0:35:15.10,Default,,0,0,0,,and parentheses are just a way to write this two-dimensional structure\r\nDialogue: 0,0:35:15.79,0:35:17.34,Default,,0,0,0,,as a linear character string.\r\nDialogue: 0,0:35:19.23,0:35:23.81,Default,,0,0,0,,Because at least when Lisp first started and people had teletypes or punch cards or whatever,\r\nDialogue: 0,0:35:24.17,0:35:25.60,Default,,0,0,0,,this was more convenient.\r\nDialogue: 0,0:35:25.97,0:35:30.52,Default,,0,0,0,,Maybe if Lisp started today, the syntax of Lisp would look like that.\r\nDialogue: 0,0:35:31.76,0:35:35.07,Default,,0,0,0,,Well, let's look at what that actually looks like on the computer.\r\nDialogue: 0,0:35:36.29,0:35:39.37,Default,,0,0,0,,Here I have a Lisp interaction set up.\r\nDialogue: 0,0:35:39.41,0:35:40.43,Default,,0,0,0,,There's a editor.\r\nDialogue: 0,0:35:41.13,0:35:44.86,Default,,0,0,0,,And on the top, I'm going to type some values and ask Lisp what they are.\r\nDialogue: 0,0:35:45.12,0:35:46.75,Default,,0,0,0,,So for instance, I can say to Lisp,\r\nDialogue: 0,0:35:46.83,0:35:48.53,Default,,0,0,0,,what's the value of that symbol?\r\nDialogue: 0,0:35:49.44,0:35:50.50,Default,,0,0,0,,That's 3.\r\nDialogue: 0,0:35:50.57,0:35:52.20,Default,,0,0,0,,And I ask Lisp to evaluate it.\r\nDialogue: 0,0:35:52.32,0:35:54.77,Default,,0,0,0,,And there you see Lisp has returned on the bottom,\r\nDialogue: 0,0:35:55.39,0:35:56.84,Default,,0,0,0,,and said, oh yeah, that's 3.\r\nDialogue: 0,0:35:57.58,0:36:04.96,Default,,0,0,0,,Or I can say, what's the sum of 3 and 4 and 8?\r\nDialogue: 0,0:36:06.45,0:36:08.05,Default,,0,0,0,,What's that combination?\r\nDialogue: 0,0:36:08.93,0:36:10.66,Default,,0,0,0,,And ask Lisp to evaluate it.\r\nDialogue: 0,0:36:14.49,0:36:15.68,Default,,0,0,0,,That's 15.\r\nDialogue: 0,0:36:16.57,0:36:18.80,Default,,0,0,0,,Or I can type in something more complicated.\r\nDialogue: 0,0:36:19.25,0:36:34.14,Default,,0,0,0,,I can say, what's the sum of the product of 3 and the sum of 7 and 19.5?\r\nDialogue: 0,0:36:35.21,0:36:38.00,Default,,0,0,0,,And you'll notice here that Lisp has something built in\r\nDialogue: 0,0:36:38.01,0:36:39.76,Default,,0,0,0,,that helps me keep track of all these parentheses.\r\nDialogue: 0,0:36:39.77,0:36:42.13,Default,,0,0,0,,Watch as I type the next closed parentheses,\r\nDialogue: 0,0:36:42.21,0:36:45.01,Default,,0,0,0,,which is going to close the combination starting with the star.\r\nDialogue: 0,0:36:45.52,0:36:47.30,Default,,0,0,0,,The opening one will flash.\r\nDialogue: 0,0:36:47.76,0:36:49.69,Default,,0,0,0,,Here, I'll rub those out and do it again.\r\nDialogue: 0,0:36:50.14,0:36:52.70,Default,,0,0,0,,Type close, and you see that closes the plus.\r\nDialogue: 0,0:36:53.58,0:36:56.41,Default,,0,0,0,,Close again, that closes the star.\r\nDialogue: 0,0:36:57.90,0:37:00.76,Default,,0,0,0,,Now I'm back to the sum, and maybe I'm going to add that all to 4.\r\nDialogue: 0,0:37:01.66,0:37:02.69,Default,,0,0,0,,That closes the plus.\r\nDialogue: 0,0:37:02.73,0:37:07.07,Default,,0,0,0,,Now I have a complete combination, and I can ask Lisp for the value of that.\r\nDialogue: 0,0:37:07.26,0:37:11.66,Default,,0,0,0,,That kind of paren balancing is something that's built into\r\nDialogue: 0,0:37:11.76,0:37:13.29,Default,,0,0,0,,a lot of Lisp systems to help you keep track,\r\nDialogue: 0,0:37:13.36,0:37:16.55,Default,,0,0,0,,because it is kind of hard just by hand doing all these parentheses.\r\nDialogue: 0,0:37:16.81,0:37:21.20,Default,,0,0,0,,There's another kind of convention for keeping track of parentheses.\r\nDialogue: 0,0:37:21.25,0:37:23.68,Default,,0,0,0,,Let me write another complicated combination.\r\nDialogue: 0,0:37:24.77,0:37:34.00,Default,,0,0,0,,Let's take the sum of the product of 3 and 5 and add that to something.\r\nDialogue: 0,0:37:34.03,0:37:35.23,Default,,0,0,0,,And now what I'm going to do is\r\nDialogue: 0,0:37:35.28,0:37:39.85,Default,,0,0,0,,I'm going to indent so that the operands are written vertically.\r\nDialogue: 0,0:37:40.30,0:37:45.65,Default,,0,0,0,,Which the sum of that and the product of 47 and--\r\nDialogue: 0,0:37:47.02,0:37:54.59,Default,,0,0,0,,let's say the product of 47 with a difference of 20 and 6.8.\r\nDialogue: 0,0:37:54.62,0:37:57.09,Default,,0,0,0,,That means subtract 6.8 from 20.\r\nDialogue: 0,0:37:58.97,0:38:00.19,Default,,0,0,0,,And then you see the parentheses close.\r\nDialogue: 0,0:38:00.22,0:38:03.47,Default,,0,0,0,,Close the minus. Close the star.\r\nDialogue: 0,0:38:03.76,0:38:05.42,Default,,0,0,0,,And now let's get another operator.\r\nDialogue: 0,0:38:05.44,0:38:09.49,Default,,0,0,0,,You see the Lisp editor here is indenting to the right position automatically\r\nDialogue: 0,0:38:10.40,0:38:11.50,Default,,0,0,0,,to help me keep track.\r\nDialogue: 0,0:38:12.61,0:38:14.09,Default,,0,0,0,,I'll do that again.\r\nDialogue: 0,0:38:14.13,0:38:15.89,Default,,0,0,0,,I'll close that last parentheses again.\r\nDialogue: 0,0:38:16.25,0:38:17.71,Default,,0,0,0,,You see it balances the plus.\r\nDialogue: 0,0:38:20.40,0:38:22.64,Default,,0,0,0,,Now I can say, what's the value of that?\r\nDialogue: 0,0:38:23.87,0:38:29.28,Default,,0,0,0,,So those two things, indenting to the right level,\r\nDialogue: 0,0:38:29.31,0:38:30.86,Default,,0,0,0,,which is called pretty printing,\r\nDialogue: 0,0:38:31.55,0:38:33.58,Default,,0,0,0,,and flashing parentheses,\r\nDialogue: 0,0:38:33.89,0:38:37.73,Default,,0,0,0,,are two things that a lot of Lisp systems have built in to help you keep track.\r\nDialogue: 0,0:38:37.76,0:38:39.01,Default,,0,0,0,,And you should learn how to use them.\r\nDialogue: 0,0:38:41.52,0:38:43.17,Default,,0,0,0,,Ok, those are the primitives.\r\nDialogue: 0,0:38:44.73,0:38:46.31,Default,,0,0,0,,There's a means of combination.\r\nDialogue: 0,0:38:46.33,0:38:47.93,Default,,0,0,0,,Now let's go up to the means of abstraction.\r\nDialogue: 0,0:38:49.44,0:38:53.84,Default,,0,0,0,,I'd like to be able to take the idea that I do some combination like this,\r\nDialogue: 0,0:38:53.85,0:38:55.77,Default,,0,0,0,,and abstract it and give it a simple name,\r\nDialogue: 0,0:38:55.81,0:38:57.26,Default,,0,0,0,,so I can use that as an element.\r\nDialogue: 0,0:38:57.31,0:38:59.92,Default,,0,0,0,,And I do that in Lisp with \"define.\"\r\nDialogue: 0,0:39:01.17,0:39:02.43,Default,,0,0,0,,So I can say, for example,\r\nDialogue: 0,0:39:02.73,0:39:15.05,Default,,0,0,0,,define A to be the product of 5 and 5.\r\nDialogue: 0,0:39:18.40,0:39:22.35,Default,,0,0,0,,And now I could say, for example, to Lisp,\r\nDialogue: 0,0:39:22.38,0:39:26.01,Default,,0,0,0,,what is the product of A and A?\r\nDialogue: 0,0:39:27.18,0:39:29.81,Default,,0,0,0,,And this should be 25, and this should be 625.\r\nDialogue: 0,0:39:31.97,0:39:36.01,Default,,0,0,0,,And then, crucial thing, I can now use A--\r\nDialogue: 0,0:39:36.21,0:39:37.92,Default,,0,0,0,,here I've used it in a combination--\r\nDialogue: 0,0:39:38.41,0:39:43.55,Default,,0,0,0,,but I could use that in other more complicated things that I name in turn.\r\nDialogue: 0,0:39:43.58,0:39:50.93,Default,,0,0,0,,So I could say, define B to be the sum of,\r\nDialogue: 0,0:39:50.97,0:39:57.45,Default,,0,0,0,,we'll say, A and the product of 5 and A.\r\nDialogue: 0,0:39:59.44,0:40:00.72,Default,,0,0,0,,And then close the plus.\r\nDialogue: 0,0:40:03.45,0:40:05.85,Default,,0,0,0,,Let's take a look at that on the computer and see how that looks.\r\nDialogue: 0,0:40:07.28,0:40:10.68,Default,,0,0,0,,So I'll just type what I wrote on the board.\r\nDialogue: 0,0:40:10.83,0:40:21.73,Default,,0,0,0,,I could say, define A to be the product of 5 and 5.\r\nDialogue: 0,0:40:23.74,0:40:25.38,Default,,0,0,0,,And I'll tell that to Lisp.\r\nDialogue: 0,0:40:25.52,0:40:28.94,Default,,0,0,0,,And notice what Lisp responded there with was an A in the bottom.\r\nDialogue: 0,0:40:29.09,0:40:31.38,Default,,0,0,0,,In general, when you type in a definition in Lisp,\r\nDialogue: 0,0:40:31.50,0:40:35.02,Default,,0,0,0,,it responds with the symbol being defined.\r\nDialogue: 0,0:40:35.63,0:40:39.66,Default,,0,0,0,,Now I could say to Lisp, what is the product of A and A?\r\nDialogue: 0,0:40:42.81,0:40:44.33,Default,,0,0,0,,And it says that's 625.\r\nDialogue: 0,0:40:46.05,0:41:00.34,Default,,0,0,0,,I can define B to be the sum of A and the product of 5 and A.\r\nDialogue: 0,0:41:00.48,0:41:05.70,Default,,0,0,0,,Close a paren closes the star.  Close the plus. Close the \"define.\"\r\nDialogue: 0,0:41:07.63,0:41:10.37,Default,,0,0,0,,Lisp says, OK, B, there on the bottom.\r\nDialogue: 0,0:41:11.04,0:41:13.24,Default,,0,0,0,,And now I can say to Lisp, what's the value of B?\r\nDialogue: 0,0:41:17.18,0:41:18.88,Default,,0,0,0,,And I can say something more complicated,\r\nDialogue: 0,0:41:18.93,0:41:26.69,Default,,0,0,0,,like what's the sum of A and the quotient of B and 5?\r\nDialogue: 0,0:41:26.73,0:41:30.25,Default,,0,0,0,,That slash is divide, another primitive operator.\r\nDialogue: 0,0:41:30.38,0:41:32.78,Default,,0,0,0,,I've divided B by 5, added it to A.\r\nDialogue: 0,0:41:33.65,0:41:35.23,Default,,0,0,0,,Lisp says, OK, that's 55.\r\nDialogue: 0,0:41:36.57,0:41:37.92,Default,,0,0,0,,So there's what it looks like.\r\nDialogue: 0,0:41:39.82,0:41:43.40,Default,,0,0,0,,There's the basic means of defining something.\r\nDialogue: 0,0:41:43.44,0:41:49.02,Default,,0,0,0,,It's the simplest kind of naming, but it's not really very powerful.\r\nDialogue: 0,0:41:50.06,0:41:51.60,Default,,0,0,0,,See, what I'd really like to name--\r\nDialogue: 0,0:41:51.84,0:41:53.37,Default,,0,0,0,,remember, we're talking about general methods--\r\nDialogue: 0,0:41:53.57,0:41:57.68,Default,,0,0,0,,I'd like to name, oh, the general idea that, for example,\r\nDialogue: 0,0:41:58.11,0:42:17.53,Default,,0,0,0,,I could multiply 5 by 5, or 6 by 6, or 1,001 by 1,001, 1,001.7 by 1,001.7.\r\nDialogue: 0,0:42:17.76,0:42:24.16,Default,,0,0,0,,I'd like to be able to name the general idea of multiplying something by itself.\r\nDialogue: 0,0:42:28.48,0:42:30.11,Default,,0,0,0,,Well, you know what that is. That's called squaring.\r\nDialogue: 0,0:42:31.69,0:42:35.63,Default,,0,0,0,,And the way I can do that in Lisp is I can say,\r\nDialogue: 0,0:42:37.97,0:42:56.25,Default,,0,0,0,,define to square something x, multiply x by itself.\r\nDialogue: 0,0:42:57.87,0:43:01.12,Default,,0,0,0,,And then having done that, I could say to Lisp,\r\nDialogue: 0,0:43:01.12,0:43:05.49,Default,,0,0,0,,for example, what's the square of 10?\r\nDialogue: 0,0:43:06.67,0:43:07.87,Default,,0,0,0,,And Lisp will say 100.\r\nDialogue: 0,0:43:10.70,0:43:14.24,Default,,0,0,0,,So now let's actually look at that a little more closely.\r\nDialogue: 0,0:43:15.29,0:43:16.88,Default,,0,0,0,,Right, there's the definition of square.\r\nDialogue: 0,0:43:17.50,0:43:22.55,Default,,0,0,0,,To square something, multiply it by itself.\r\nDialogue: 0,0:43:23.69,0:43:25.34,Default,,0,0,0,,You see this x here.\r\nDialogue: 0,0:43:26.29,0:43:27.81,Default,,0,0,0,,That x is kind of a pronoun,\r\nDialogue: 0,0:43:27.87,0:43:29.53,Default,,0,0,0,,which is the something that I'm going to square.\r\nDialogue: 0,0:43:31.49,0:43:37.41,Default,,0,0,0,,And what I do with it is I multiply x, I multiply it by itself.\r\nDialogue: 0,0:43:42.22,0:43:48.27,Default,,0,0,0,,OK. So there's the notation for defining a procedure.\r\nDialogue: 0,0:43:48.29,0:43:50.29,Default,,0,0,0,,Actually, this is a little bit confusing,\r\nDialogue: 0,0:43:50.81,0:43:53.97,Default,,0,0,0,,because this is sort of how I might use square.\r\nDialogue: 0,0:43:54.00,0:43:56.80,Default,,0,0,0,,And I say square root of x or square root of 10,\r\nDialogue: 0,0:43:57.55,0:44:00.81,Default,,0,0,0,,but it's not making it very clear that I'm actually naming something.\r\nDialogue: 0,0:44:03.10,0:44:04.91,Default,,0,0,0,,So let me write this definition in another way\r\nDialogue: 0,0:44:05.74,0:44:08.21,Default,,0,0,0,,that makes it a little bit more clear that I'm naming something.\r\nDialogue: 0,0:44:08.54,0:44:29.39,Default,,0,0,0,,I'll say, \"define\" square to be lambda of x times xx.\r\nDialogue: 0,0:44:36.56,0:44:42.05,Default,,0,0,0,,Here, I'm naming something square, just like over here, I'm naming something A.\r\nDialogue: 0,0:44:43.23,0:44:44.72,Default,,0,0,0,,The thing that I'm naming square--\r\nDialogue: 0,0:44:44.75,0:44:48.39,Default,,0,0,0,,here, the thing I named A was the value of this combination.\r\nDialogue: 0,0:44:49.29,0:44:52.41,Default,,0,0,0,,Here, the thing that I'm naming square is this thing\r\nDialogue: 0,0:44:52.43,0:44:53.44,Default,,0,0,0,,that begins with lambda,\r\nDialogue: 0,0:44:53.45,0:44:56.77,Default,,0,0,0,,and lambda is Lisp's way of saying make a procedure.\r\nDialogue: 0,0:45:00.24,0:45:02.91,Default,,0,0,0,,Let's look at that more closely on the slide.\r\nDialogue: 0,0:45:04.27,0:45:05.81,Default,,0,0,0,,The way I read that definition is to say,\r\nDialogue: 0,0:45:05.85,0:45:10.33,Default,,0,0,0,,I define square to be make a procedure--\r\nDialogue: 0,0:45:12.78,0:45:13.97,Default,,0,0,0,,that's what the lambda is--\r\nDialogue: 0,0:45:14.06,0:45:17.49,Default,,0,0,0,,make a procedure with an argument named x.\r\nDialogue: 0,0:45:19.26,0:45:24.09,Default,,0,0,0,,And what it does is return the results of multiplying x by itself.\r\nDialogue: 0,0:45:24.97,0:45:33.12,Default,,0,0,0,,Now, in general, we're going to be using this top form of defining,\r\nDialogue: 0,0:45:33.41,0:45:35.20,Default,,0,0,0,,just because it's a little bit more convenient.\r\nDialogue: 0,0:45:35.21,0:45:38.67,Default,,0,0,0,,But don't lose sight of the fact that it's really this.\r\nDialogue: 0,0:45:38.86,0:45:41.41,Default,,0,0,0,,In fact, as far as the Lisp interpreter's concerned,\r\nDialogue: 0,0:45:41.61,0:45:45.55,Default,,0,0,0,,there's no difference between typing this to it and typing this to it.\r\nDialogue: 0,0:45:46.51,0:45:53.29,Default,,0,0,0,,And there's a word for that, sort of syntactic sugar.\r\nDialogue: 0,0:45:54.41,0:45:55.80,Default,,0,0,0,,What syntactic sugar means,\r\nDialogue: 0,0:45:56.35,0:46:00.83,Default,,0,0,0,,it's having somewhat more convenient surface forms for typing something.\r\nDialogue: 0,0:46:01.12,0:46:06.11,Default,,0,0,0,,So this is just really syntactic sugar for this underlying Greek thing with the lambda.\r\nDialogue: 0,0:46:07.31,0:46:10.62,Default,,0,0,0,,And the reason you should remember that is don't forget that,\r\nDialogue: 0,0:46:10.80,0:46:13.87,Default,,0,0,0,,when I write something like this, I'm really naming something.\r\nDialogue: 0,0:46:14.46,0:46:16.22,Default,,0,0,0,,I'm naming something square,\r\nDialogue: 0,0:46:16.24,0:46:19.90,Default,,0,0,0,,and the something that I'm naming square is a procedure that's getting constructed.\r\nDialogue: 0,0:46:21.20,0:46:23.90,Default,,0,0,0,,Well, let's look at that on the computer, too.\r\nDialogue: 0,0:46:24.78,0:46:35.95,Default,,0,0,0,,So I'll come and I'll say, define square of x to be times xx.\r\nDialogue: 0,0:46:49.65,0:46:52.32,Default,,0,0,0,,Now I'll tell Lisp that.\r\nDialogue: 0,0:46:53.49,0:46:53.92,Default,,0,0,0,,It says \"square.\"\r\nDialogue: 0,0:46:53.93,0:46:56.29,Default,,0,0,0,,See, I've named something \"square.\"\r\nDialogue: 0,0:46:56.45,0:47:02.88,Default,,0,0,0,,Now, having done that, I can ask Lisp for, what's the square of 1,001?\r\nDialogue: 0,0:47:05.26,0:47:17.69,Default,,0,0,0,,Or in general, I could say, what's the square of the sum of 5 and 7?\r\nDialogue: 0,0:47:22.81,0:47:24.95,Default,,0,0,0,,The square of 12's 144.\r\nDialogue: 0,0:47:25.07,0:47:28.86,Default,,0,0,0,,Or I can use square itself as an element in some combination.\r\nDialogue: 0,0:47:28.88,0:47:37.50,Default,,0,0,0,,I can say, what's the sum of the square of 3 and the square of 4?\r\nDialogue: 0,0:47:42.53,0:47:44.09,Default,,0,0,0,,9 and 16 is 25.\r\nDialogue: 0,0:47:44.91,0:47:50.54,Default,,0,0,0,,Or I can use square as an element in some much more complicated thing.\r\nDialogue: 0,0:47:50.59,0:48:00.51,Default,,0,0,0,,I can say, what's the square of, the sqare of, the square of 1,001?\r\nDialogue: 0,0:48:07.89,0:48:10.63,Default,,0,0,0,,And there's the square of the square of the square of 1,001.\r\nDialogue: 0,0:48:11.20,0:48:15.45,Default,,0,0,0,,Or I can say to Lisp, what is square itself?\r\nDialogue: 0,0:48:15.68,0:48:17.16,Default,,0,0,0,,What's the value of that?\r\nDialogue: 0,0:48:17.44,0:48:22.14,Default,,0,0,0,,And Lisp returns some conventional way of telling me that that's a procedure.\r\nDialogue: 0,0:48:22.27,0:48:23.98,Default,,0,0,0,,It says, \"compound procedure square.\"\r\nDialogue: 0,0:48:24.25,0:48:27.92,Default,,0,0,0,,Remember, the value of square is this procedure,\r\nDialogue: 0,0:48:29.15,0:48:30.89,Default,,0,0,0,,and the thing with the stars and the brackets\r\nDialogue: 0,0:48:31.10,0:48:34.78,Default,,0,0,0,,are just Lisp's conventional way of describing that.\r\nDialogue: 0,0:48:36.11,0:48:41.33,Default,,0,0,0,,Let's look at two more examples of defining.\r\nDialogue: 0,0:48:44.91,0:48:46.91,Default,,0,0,0,,Here are two more procedures.\r\nDialogue: 0,0:48:47.36,0:48:52.84,Default,,0,0,0,,I can define the average of x and y to be the sum of x and y divided by 2.\r\nDialogue: 0,0:48:54.67,0:49:01.49,Default,,0,0,0,,Or having had average and mean square, having had average and square,\r\nDialogue: 0,0:49:01.65,0:49:04.71,Default,,0,0,0,,I can use that to talk about the mean square of something,\r\nDialogue: 0,0:49:04.91,0:49:09.26,Default,,0,0,0,,which is the average of the square of x and the square of y.\r\nDialogue: 0,0:49:10.97,0:49:13.63,Default,,0,0,0,,So for example, having done that, I could say,\r\nDialogue: 0,0:49:13.66,0:49:24.88,Default,,0,0,0,,what's the mean square of 2 and 3?\r\nDialogue: 0,0:49:25.23,0:49:30.24,Default,,0,0,0,,And I should get the average of 4 and 9, which is 6.5.\r\nDialogue: 0,0:49:32.85,0:49:36.64,Default,,0,0,0,,The key thing here is that, having defined square,\r\nDialogue: 0,0:49:36.64,0:49:38.67,Default,,0,0,0,,I can use it as if it were primitive.\r\nDialogue: 0,0:49:41.41,0:49:43.07,Default,,0,0,0,,So if we look here on the slide,\r\nDialogue: 0,0:49:44.65,0:49:45.74,Default,,0,0,0,,if I look at mean square,\r\nDialogue: 0,0:49:47.29,0:49:52.56,Default,,0,0,0,,the person defining mean square doesn't have to know, at this point,\r\nDialogue: 0,0:49:52.61,0:49:55.76,Default,,0,0,0,,whether square was something built into the language\r\nDialogue: 0,0:49:56.94,0:49:58.93,Default,,0,0,0,,or whether it was a procedure that was defined.\r\nDialogue: 0,0:49:59.73,0:50:01.28,Default,,0,0,0,,And that's a key thing in Lisp,\r\nDialogue: 0,0:50:02.30,0:50:07.52,Default,,0,0,0,,that you do not make arbitrary distinctions between things\r\nDialogue: 0,0:50:07.53,0:50:11.82,Default,,0,0,0,,that happen to be primitive in the language and things that happen to be built in.\r\nDialogue: 0,0:50:12.83,0:50:14.73,Default,,0,0,0,,A person using that shouldn't even have to know.\r\nDialogue: 0,0:50:14.93,0:50:18.51,Default,,0,0,0,,So the things you construct get used with all the power and flexibility\r\nDialogue: 0,0:50:18.51,0:50:19.53,Default,,0,0,0,,as if they were primitives.\r\nDialogue: 0,0:50:19.57,0:50:22.57,Default,,0,0,0,,In fact, you can drive that home by looking on the computer one more time.\r\nDialogue: 0,0:50:24.75,0:50:26.30,Default,,0,0,0,,We talked about plus.\r\nDialogue: 0,0:50:26.72,0:50:30.09,Default,,0,0,0,,And in fact, if I come here on the computer screen and say,\r\nDialogue: 0,0:50:30.11,0:50:32.33,Default,,0,0,0,,what is the value of plus?\r\nDialogue: 0,0:50:34.40,0:50:37.20,Default,,0,0,0,,Notice what Lisp types out. On the bottom there, it typed out,\r\nDialogue: 0,0:50:37.25,0:50:38.81,Default,,0,0,0,,\"compound procedure plus.\"\r\nDialogue: 0,0:50:39.89,0:50:42.29,Default,,0,0,0,,Because, in this system,\r\nDialogue: 0,0:50:42.33,0:50:45.49,Default,,0,0,0,,it turns out that the addition operator is itself a compound procedure.\r\nDialogue: 0,0:50:45.97,0:50:47.97,Default,,0,0,0,,And if I didn't just type that in, you'd never know that,\r\nDialogue: 0,0:50:48.06,0:50:49.68,Default,,0,0,0,,and it wouldn't make any difference anyway.\r\nDialogue: 0,0:50:49.84,0:50:50.51,Default,,0,0,0,,We don't care.\r\nDialogue: 0,0:50:50.56,0:50:53.39,Default,,0,0,0,,It's below the level of the abstraction that we're dealing with.\r\nDialogue: 0,0:50:54.17,0:50:59.11,Default,,0,0,0,,So the key thing is you cannot tell, should not be able to tell, in general,\r\nDialogue: 0,0:50:59.17,0:51:03.82,Default,,0,0,0,,the difference between things that are built in and things that are compound.\r\nDialogue: 0,0:51:03.84,0:51:04.38,Default,,0,0,0,,Why is that?\r\nDialogue: 0,0:51:04.38,0:51:08.07,Default,,0,0,0,,Because the things that are compound have an abstraction wrapper wrapped around them.\r\nDialogue: 0,0:51:09.05,0:51:11.61,Default,,0,0,0,,We've seen almost all the elements of Lisp now.\r\nDialogue: 0,0:51:12.67,0:51:14.53,Default,,0,0,0,,There's only one more we have to look at,\r\nDialogue: 0,0:51:14.57,0:51:16.53,Default,,0,0,0,,and that is how to make a case analysis.\r\nDialogue: 0,0:51:16.59,0:51:17.70,Default,,0,0,0,,Let me show you what I mean.\r\nDialogue: 0,0:51:18.96,0:51:24.08,Default,,0,0,0,,We might want to think about the mathematical definition of the absolute value functions.\r\nDialogue: 0,0:51:24.11,0:51:30.03,Default,,0,0,0,,I might say the absolute value of x is the function\r\nDialogue: 0,0:51:30.16,0:51:37.24,Default,,0,0,0,,which has the property that it's negative of x. For x less than 0,\r\nDialogue: 0,0:51:37.92,0:51:41.13,Default,,0,0,0,,it's 0 for x equal to 0.\r\nDialogue: 0,0:51:42.64,0:51:46.62,Default,,0,0,0,,And it's x for x greater than 0.\r\nDialogue: 0,0:51:49.15,0:51:51.90,Default,,0,0,0,,And Lisp has a way of making case analyses.\r\nDialogue: 0,0:51:52.11,0:51:53.85,Default,,0,0,0,,Let me define for you absolute value.\r\nDialogue: 0,0:51:55.55,0:52:02.41,Default,,0,0,0,,Say define the absolute value of x is conditional.\r\nDialogue: 0,0:52:03.02,0:52:05.67,Default,,0,0,0,,This means case analysis, COND.\r\nDialogue: 0,0:52:09.23,0:52:19.09,Default,,0,0,0,,If x is less than 0, the answer is negate x.\r\nDialogue: 0,0:52:22.99,0:52:24.88,Default,,0,0,0,,What I've written here is a clause.\r\nDialogue: 0,0:52:24.99,0:52:35.54,Default,,0,0,0,,This whole thing is a conditional clause, and it has two parts.\r\nDialogue: 0,0:52:36.35,0:52:44.70,Default,,0,0,0,,This part here is a predicate or a condition.\r\nDialogue: 0,0:52:44.83,0:52:45.90,Default,,0,0,0,,That's a condition.\r\nDialogue: 0,0:52:46.11,0:52:48.29,Default,,0,0,0,,And the condition is expressed by something called a predicate,\r\nDialogue: 0,0:52:48.33,0:52:51.05,Default,,0,0,0,,and a predicate in Lisp is some sort of thing\r\nDialogue: 0,0:52:51.37,0:52:52.87,Default,,0,0,0,,that returns either true or false.\r\nDialogue: 0,0:52:53.53,0:52:56.13,Default,,0,0,0,,And you see Lisp has a primitive procedure, less-than,\r\nDialogue: 0,0:52:57.29,0:52:59.08,Default,,0,0,0,,that tests whether something is true or false.\r\nDialogue: 0,0:53:00.54,0:53:06.32,Default,,0,0,0,,And the other part of a clause is an action or a thing to do,\r\nDialogue: 0,0:53:06.93,0:53:08.14,Default,,0,0,0,,in the case where that's true.\r\nDialogue: 0,0:53:08.17,0:53:09.81,Default,,0,0,0,,And here, what I'm doing is negating x.\r\nDialogue: 0,0:53:10.08,0:53:14.41,Default,,0,0,0,,The negation operator, the minus sign in Lisp is a little bit funny.\r\nDialogue: 0,0:53:14.56,0:53:18.43,Default,,0,0,0,,If there's two or more arguments,\r\nDialogue: 0,0:53:18.58,0:53:22.49,Default,,0,0,0,,if there's two arguments it subtracts the second one from the first, and we saw that.\r\nDialogue: 0,0:53:22.53,0:53:24.13,Default,,0,0,0,,And if there's one argument, it negates it.\r\nDialogue: 0,0:53:25.13,0:53:27.87,Default,,0,0,0,,So this corresponds to that.\r\nDialogue: 0,0:53:27.87,0:53:29.69,Default,,0,0,0,,And then there's another COND clause.\r\nDialogue: 0,0:53:30.64,0:53:35.87,Default,,0,0,0,,It says, in the case where x is equal to 0, the answer is 0.\r\nDialogue: 0,0:53:37.95,0:53:44.75,Default,,0,0,0,,And in the case where x is greater than 0, the answer is x.\r\nDialogue: 0,0:53:45.33,0:53:49.38,Default,,0,0,0,,Close that clause. Close the COND. Close the definition.\r\nDialogue: 0,0:53:49.57,0:53:51.29,Default,,0,0,0,,And there's the definition of absolute value.\r\nDialogue: 0,0:53:51.31,0:53:53.66,Default,,0,0,0,,And you see it's the case analysis that looks very much\r\nDialogue: 0,0:53:53.66,0:53:56.04,Default,,0,0,0,,like the case analysis you use in mathematics.\r\nDialogue: 0,0:53:58.14,0:54:03.07,Default,,0,0,0,,There's a somewhat different way of writing a restricted case analysis.\r\nDialogue: 0,0:54:03.07,0:54:06.24,Default,,0,0,0,,Often, you have a case analysis where you only have one case,\r\nDialogue: 0,0:54:06.93,0:54:08.07,Default,,0,0,0,,where you test something,\r\nDialogue: 0,0:54:08.33,0:54:10.75,Default,,0,0,0,,and then depending on whether it's true or false, you do something.\r\nDialogue: 0,0:54:11.01,0:54:15.90,Default,,0,0,0,,And here's another definition of absolute value\r\nDialogue: 0,0:54:16.00,0:54:17.19,Default,,0,0,0,,which looks almost the same,\r\nDialogue: 0,0:54:17.66,0:54:22.56,Default,,0,0,0,,which says, if x is less than 0, the result is negate x.\r\nDialogue: 0,0:54:24.41,0:54:25.97,Default,,0,0,0,,Otherwise, the answer is x.\r\nDialogue: 0,0:54:26.05,0:54:27.25,Default,,0,0,0,,And we'll be using \"if\" a lot.\r\nDialogue: 0,0:54:27.29,0:54:29.13,Default,,0,0,0,,But again, the thing to remember is that\r\nDialogue: 0,0:54:29.13,0:54:32.70,Default,,0,0,0,,this form of absolute value that you're looking at here,\r\nDialogue: 0,0:54:34.30,0:54:36.98,Default,,0,0,0,,and then this one over here that I wrote on the board,\r\nDialogue: 0,0:54:37.52,0:54:38.80,Default,,0,0,0,,are essentially the same.\r\nDialogue: 0,0:54:39.09,0:54:42.26,Default,,0,0,0,,And \"if\" and COND are-- well, whichever way you like it.\r\nDialogue: 0,0:54:42.30,0:54:44.45,Default,,0,0,0,,You can think of COND as syntactic sugar for \"if\",\r\nDialogue: 0,0:54:44.99,0:54:47.36,Default,,0,0,0,,or you can think of \"if\" as syntactic sugar for COND,\r\nDialogue: 0,0:54:47.39,0:54:48.65,Default,,0,0,0,,and it doesn't make any difference.\r\nDialogue: 0,0:54:49.21,0:54:51.35,Default,,0,0,0,,The person implementing a Lisp system will pick one\r\nDialogue: 0,0:54:51.39,0:54:52.97,Default,,0,0,0,,and implement the other in terms of that.\r\nDialogue: 0,0:54:53.15,0:54:54.67,Default,,0,0,0,,And it doesn't matter which one you pick.\r\nDialogue: 0,0:55:02.27,0:55:05.36,Default,,0,0,0,,Why don't we break now, and then take some questions.\r\nDialogue: 0,0:55:05.69,0:55:10.08,Default,,0,0,0,,How come sometimes when I write define,\r\nDialogue: 0,0:55:11.09,0:55:14.75,Default,,0,0,0,,I put an open paren here and say,\r\nDialogue: 0,0:55:14.81,0:55:16.45,Default,,0,0,0,,define open paren something or other,\r\nDialogue: 0,0:55:16.86,0:55:20.81,Default,,0,0,0,,and sometimes when I write this, I don't put an open paren?\r\nDialogue: 0,0:55:22.06,0:55:27.23,Default,,0,0,0,,The answer is, this particular form of \"define\",\r\nDialogue: 0,0:55:27.26,0:55:29.41,Default,,0,0,0,,where you say define some expression,\r\nDialogue: 0,0:55:29.47,0:55:32.13,Default,,0,0,0,,is this very special thing for defining procedures.\r\nDialogue: 0,0:55:33.61,0:55:40.21,Default,,0,0,0,,But again, what it really means is I'm defining this symbol, square, to be that.\r\nDialogue: 0,0:55:41.45,0:55:45.98,Default,,0,0,0,,So the way you should think about it is what \"define\" does is you write \"define\",\r\nDialogue: 0,0:55:47.15,0:55:50.06,Default,,0,0,0,,and the second thing you write is the symbol here-- no open paren--\r\nDialogue: 0,0:55:50.17,0:55:51.49,Default,,0,0,0,,the symbol you're defining\r\nDialogue: 0,0:55:52.08,0:55:53.70,Default,,0,0,0,,and what you're defining it to be.\r\nDialogue: 0,0:55:54.65,0:55:57.55,Default,,0,0,0,,That's like here and like here.\r\nDialogue: 0,0:55:57.61,0:56:00.29,Default,,0,0,0,,That's sort of the basic way you use \"define.\"\r\nDialogue: 0,0:56:01.12,0:56:03.65,Default,,0,0,0,,And then, there's this special syntactic trick\r\nDialogue: 0,0:56:04.29,0:56:07.04,Default,,0,0,0,,which allows you to define procedures that look like this.\r\nDialogue: 0,0:56:08.17,0:56:11.49,Default,,0,0,0,,So the difference is, it's whether or not you're defining a procedure.\r\nDialogue: 0,0:56:12.91,0:56:37.60,Default,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\r\nDialogue: 0,0:56:38.05,0:56:41.98,Default,,0,0,0,,Well, believe it or not, you actually now know enough Lisp\r\nDialogue: 0,0:56:42.78,0:56:45.42,Default,,0,0,0,,to write essentially any numerical procedure\r\nDialogue: 0,0:56:46.25,0:56:49.63,Default,,0,0,0,,that you'd write in a language like FORTRAN or Basic or whatever,\r\nDialogue: 0,0:56:49.66,0:56:51.01,Default,,0,0,0,,or, essentially, any other language.\r\nDialogue: 0,0:56:52.05,0:56:54.76,Default,,0,0,0,,And you're probably saying, that's not believable,\r\nDialogue: 0,0:56:54.81,0:56:56.65,Default,,0,0,0,,because you know that these languages have things\r\nDialogue: 0,0:56:56.65,0:57:00.22,Default,,0,0,0,,like \"for statements\", and \"do until while\" or something.\r\nDialogue: 0,0:57:00.99,0:57:04.59,Default,,0,0,0,,But we don't really need any of that.\r\nDialogue: 0,0:57:05.05,0:57:07.13,Default,,0,0,0,,In fact, we're not going to use any of that in this course.\r\nDialogue: 0,0:57:08.25,0:57:10.16,Default,,0,0,0,,Let me show you.\r\nDialogue: 0,0:57:10.25,0:57:13.61,Default,,0,0,0,,Again, looking back at square root,\r\nDialogue: 0,0:57:13.65,0:57:19.03,Default,,0,0,0,,let's go back to this square root algorithm of Heron of Alexandria.\r\nDialogue: 0,0:57:19.09,0:57:19.97,Default,,0,0,0,,Remember what that said.\r\nDialogue: 0,0:57:20.06,0:57:23.67,Default,,0,0,0,,It said, to find an approximation to the square root of X,\r\nDialogue: 0,0:57:25.07,0:57:26.16,Default,,0,0,0,,you make a guess,\r\nDialogue: 0,0:57:27.45,0:57:31.88,Default,,0,0,0,,you improve that guess by averaging the guess and X over the guess.\r\nDialogue: 0,0:57:32.94,0:57:36.06,Default,,0,0,0,,You keep improving that until the guess is good enough.\r\nDialogue: 0,0:57:36.72,0:57:38.43,Default,,0,0,0,,I already alluded to the idea.\r\nDialogue: 0,0:57:38.56,0:57:42.24,Default,,0,0,0,,The idea is that, if the initial guess that you took\r\nDialogue: 0,0:57:43.04,0:57:46.91,Default,,0,0,0,,was actually equal to the square root of X,\r\nDialogue: 0,0:57:47.15,0:57:50.06,Default,,0,0,0,,then G here would be equal to X/G.\r\nDialogue: 0,0:57:52.89,0:57:55.33,Default,,0,0,0,,So if you hit the square root, averaging them wouldn't change it.\r\nDialogue: 0,0:57:55.69,0:57:59.62,Default,,0,0,0,,If the G that you picked was larger than the square root of X,\r\nDialogue: 0,0:58:00.38,0:58:02.94,Default,,0,0,0,,then X/G will be smaller than the square root of X,\r\nDialogue: 0,0:58:03.21,0:58:05.37,Default,,0,0,0,,so that when you average G and X/G,\r\nDialogue: 0,0:58:05.63,0:58:07.57,Default,,0,0,0,,you get something in between.\r\nDialogue: 0,0:58:08.96,0:58:12.95,Default,,0,0,0,,So if you pick a G that's too small, your answer will be too large.\r\nDialogue: 0,0:58:13.12,0:58:14.81,Default,,0,0,0,,If you pick a G that's too large,\r\nDialogue: 0,0:58:16.32,0:58:18.06,Default,,0,0,0,,if your G is larger than the square root of X\r\nDialogue: 0,0:58:18.08,0:58:20.35,Default,,0,0,0,,and X/G will be smaller than the square root of X.\r\nDialogue: 0,0:58:21.23,0:58:23.65,Default,,0,0,0,,So averaging always gives you something in between.\r\nDialogue: 0,0:58:24.53,0:58:28.13,Default,,0,0,0,,And then, it's not quite trivial, but it's possible to show that,\r\nDialogue: 0,0:58:28.17,0:58:31.76,Default,,0,0,0,,in fact, if G misses the square root of X by a little bit,\r\nDialogue: 0,0:58:31.81,0:58:37.99,Default,,0,0,0,,the average of G and X/G will actually keep getting closer to the square root of X.\r\nDialogue: 0,0:58:38.03,0:58:38.99,Default,,0,0,0,,So if you keep doing this enough,\r\nDialogue: 0,0:58:39.42,0:58:41.18,Default,,0,0,0,,you'll eventually get as close as you want.\r\nDialogue: 0,0:58:41.71,0:58:42.85,Default,,0,0,0,,And then there's another fact,\r\nDialogue: 0,0:58:43.02,0:58:47.65,Default,,0,0,0,,that you can always start out this process by using 1 as an initial guess.\r\nDialogue: 0,0:58:49.23,0:58:51.35,Default,,0,0,0,,And it'll always converge to the square root of X.\r\nDialogue: 0,0:58:52.24,0:58:56.77,Default,,0,0,0,,So that's this method of successive averaging due to Heron of Alexandria.\r\nDialogue: 0,0:58:56.81,0:58:59.21,Default,,0,0,0,,Let's write it in Lisp.\r\nDialogue: 0,0:59:00.57,0:59:02.61,Default,,0,0,0,,Well, the central idea is,\r\nDialogue: 0,0:59:02.65,0:59:07.19,Default,,0,0,0,,what does it mean to try a guess for the square root of X?\r\nDialogue: 0,0:59:08.30,0:59:09.37,Default,,0,0,0,,Let's write that.\r\nDialogue: 0,0:59:09.79,0:59:25.02,Default,,0,0,0,,So we'll say, define to try a guess for the square root of X,\r\nDialogue: 0,0:59:26.45,0:59:28.24,Default,,0,0,0,,what do we do? We'll say,\r\nDialogue: 0,0:59:28.29,0:59:45.26,Default,,0,0,0,,if the guess is good enough to be a guess for the square root of X,\r\nDialogue: 0,0:59:46.54,0:59:49.52,Default,,0,0,0,,then, as an answer, we'll take the guess.\r\nDialogue: 0,0:59:51.61,0:59:57.01,Default,,0,0,0,,Otherwise, we will try the improved guess.\r\nDialogue: 0,0:59:58.19,1:00:04.24,Default,,0,0,0,,We'll improve that guess for the square root of X,\r\nDialogue: 0,1:00:05.26,1:00:09.33,Default,,0,0,0,,and we'll try that as a guess for the square root of X.\r\nDialogue: 0,1:00:09.36,1:00:12.96,Default,,0,0,0,,Close the \"try.\" Close the \"if.\" Close the \"define.\"\r\nDialogue: 0,1:00:13.31,1:00:14.81,Default,,0,0,0,,So that's how we try a guess.\r\nDialogue: 0,1:00:15.85,1:00:17.60,Default,,0,0,0,,And then, the next part of the process said,\r\nDialogue: 0,1:00:17.73,1:00:21.90,Default,,0,0,0,,in order to compute square roots, we'll say,\r\nDialogue: 0,1:00:21.93,1:00:30.17,Default,,0,0,0,,define to compute the square root of X,\r\nDialogue: 0,1:00:30.80,1:00:35.79,Default,,0,0,0,,we will try 1 as a guess for the square root of X.\r\nDialogue: 0,1:00:37.42,1:00:39.59,Default,,0,0,0,,Well, we have to define a couple more things.\r\nDialogue: 0,1:00:40.08,1:00:43.36,Default,,0,0,0,,We have to say, how is a guess good enough?\r\nDialogue: 0,1:00:43.84,1:00:45.29,Default,,0,0,0,,And how do we improve a guess?\r\nDialogue: 0,1:00:45.85,1:00:47.10,Default,,0,0,0,,So let's look at that.\r\nDialogue: 0,1:00:47.39,1:00:54.24,Default,,0,0,0,,The algorithm to improve a guess for the square root of X,\r\nDialogue: 0,1:00:54.64,1:00:57.18,Default,,0,0,0,,we average-- that was the algorithm--\r\nDialogue: 0,1:00:57.18,1:01:02.16,Default,,0,0,0,,we average the guess with the quotient of dividing X by the guess.\r\nDialogue: 0,1:01:02.99,1:01:04.57,Default,,0,0,0,,That's how we improve a guess.\r\nDialogue: 0,1:01:05.85,1:01:08.80,Default,,0,0,0,,And to tell whether a guess is good enough, well, we have to decide something.\r\nDialogue: 0,1:01:08.86,1:01:11.36,Default,,0,0,0,,This is supposed to be a guess for the square root of X,\r\nDialogue: 0,1:01:11.37,1:01:14.03,Default,,0,0,0,,so one possible thing you can do is say,\r\nDialogue: 0,1:01:14.06,1:01:16.07,Default,,0,0,0,,when you take that guess and square it,\r\nDialogue: 0,1:01:16.64,1:01:18.41,Default,,0,0,0,,do you get something very close to X?\r\nDialogue: 0,1:01:18.59,1:01:21.10,Default,,0,0,0,,So one way to say that is to say,\r\nDialogue: 0,1:01:21.12,1:01:24.31,Default,,0,0,0,,I square the guess, subtract X from that,\r\nDialogue: 0,1:01:25.15,1:01:27.15,Default,,0,0,0,,and see if the absolute value of that\r\nDialogue: 0,1:01:27.20,1:01:32.05,Default,,0,0,0,,whole thing is less than some small number, which depends on my purposes.\r\nDialogue: 0,1:01:34.70,1:01:41.42,Default,,0,0,0,,So there's a complete procedure for how to compute the square root of X.\r\nDialogue: 0,1:01:41.47,1:01:43.53,Default,,0,0,0,,Let's look at the structure of that a little bit.\r\nDialogue: 0,1:01:47.84,1:01:49.12,Default,,0,0,0,,I have the whole thing.\r\nDialogue: 0,1:01:49.15,1:01:55.44,Default,,0,0,0,,I have the notion of how to compute a square root.\r\nDialogue: 0,1:01:55.53,1:01:56.88,Default,,0,0,0,,That's some kind of module.\r\nDialogue: 0,1:01:57.05,1:01:58.46,Default,,0,0,0,,That's some kind of black box.\r\nDialogue: 0,1:01:58.72,1:02:08.02,Default,,0,0,0,,It's defined in terms of how to try a guess for the square root of X.\r\nDialogue: 0,1:02:09.31,1:02:14.10,Default,,0,0,0,,\"Try\" is defined in terms of, well,\r\nDialogue: 0,1:02:14.61,1:02:18.03,Default,,0,0,0,,telling whether something is good enough and telling how to improve something.\r\nDialogue: 0,1:02:18.73,1:02:19.68,Default,,0,0,0,,So good enough.\r\nDialogue: 0,1:02:19.89,1:02:28.85,Default,,0,0,0,,\"Try\" is defined in terms of \"good enough\" and \"improve\".\r\nDialogue: 0,1:02:30.96,1:02:32.56,Default,,0,0,0,,And let's see what else I fill in.\r\nDialogue: 0,1:02:32.71,1:02:34.29,Default,,0,0,0,,Well, I'll go down this tree.\r\nDialogue: 0,1:02:34.73,1:02:38.49,Default,,0,0,0,,\"Good enough\" was defined in terms of absolute value, and square.\r\nDialogue: 0,1:02:40.97,1:02:44.13,Default,,0,0,0,,And improve was defined in terms of something called averaging\r\nDialogue: 0,1:02:45.17,1:02:46.70,Default,,0,0,0,,and then some other primitive operator.\r\nDialogue: 0,1:02:46.72,1:02:48.88,Default,,0,0,0,,Square root's defined in terms of \"try\".\r\nDialogue: 0,1:02:48.88,1:02:53.31,Default,,0,0,0,,\"Try\" is defined in terms of \"good enough\" and \"improve\",\r\nDialogue: 0,1:02:54.01,1:02:55.39,Default,,0,0,0,,but also \"try\" itself.\r\nDialogue: 0,1:02:55.58,1:03:00.86,Default,,0,0,0,,So \"try\" is also defined in terms of how to try itself.\r\nDialogue: 0,1:03:02.75,1:03:04.72,Default,,0,0,0,,Well, that may give you some problems.\r\nDialogue: 0,1:03:04.72,1:03:08.16,Default,,0,0,0,,Your high school geometry teacher probably told you\r\nDialogue: 0,1:03:08.67,1:03:12.57,Default,,0,0,0,,that it's naughty to try and define things in terms of themselves,\r\nDialogue: 0,1:03:12.88,1:03:13.92,Default,,0,0,0,,because it doesn't make sense.\r\nDialogue: 0,1:03:13.92,1:03:14.72,Default,,0,0,0,,But that's false.\r\nDialogue: 0,1:03:16.03,1:03:19.68,Default,,0,0,0,,Sometimes it makes perfect sense to define things in terms of themselves.\r\nDialogue: 0,1:03:20.16,1:03:24.38,Default,,0,0,0,,And this is the case. And we can look at that.\r\nDialogue: 0,1:03:24.38,1:03:26.89,Default,,0,0,0,,We could write down what this means, and say,\r\nDialogue: 0,1:03:26.91,1:03:30.33,Default,,0,0,0,,suppose I asked Lisp what the square root of 2 is.\r\nDialogue: 0,1:03:32.65,1:03:34.67,Default,,0,0,0,,What's the square root of 2 mean?\r\nDialogue: 0,1:03:35.79,1:03:43.61,Default,,0,0,0,,Well, that means I try 1 as a guess for the square root of 2.\r\nDialogue: 0,1:03:46.97,1:03:50.92,Default,,0,0,0,,Now I look. I say, gee, is 1 a good enough guess for the square root of 2?\r\nDialogue: 0,1:03:51.65,1:03:53.69,Default,,0,0,0,,And that depends on the test that \"good enough\" does.\r\nDialogue: 0,1:03:54.61,1:03:56.56,Default,,0,0,0,,And in this case, \"good enough\" will say,\r\nDialogue: 0,1:03:56.65,1:03:59.05,Default,,0,0,0,,no, 1 is not a good enough guess for the square root of 2.\r\nDialogue: 0,1:03:59.79,1:04:08.22,Default,,0,0,0,,So that will reduce to saying, I have to try an improved--\r\nDialogue: 0,1:04:08.64,1:04:12.63,Default,,0,0,0,,improve 1 as a guess for the square root of 2,\r\nDialogue: 0,1:04:15.15,1:04:17.46,Default,,0,0,0,,and try that as a guess for the square root of 2.\r\nDialogue: 0,1:04:19.13,1:04:22.07,Default,,0,0,0,,Improving 1 as a guess for the square root of 2\r\nDialogue: 0,1:04:22.09,1:04:25.08,Default,,0,0,0,,means I average 1 and 2 divided by 1.\r\nDialogue: 0,1:04:27.10,1:04:29.10,Default,,0,0,0,,So this is going to be average.\r\nDialogue: 0,1:04:29.58,1:04:39.44,Default,,0,0,0,,This piece here will be the average of 1 and the quotient of 2 by 1.\r\nDialogue: 0,1:04:40.83,1:04:42.75,Default,,0,0,0,,That's this piece here.\r\nDialogue: 0,1:04:43.85,1:04:46.72,Default,,0,0,0,,And I'm gonna try... And this is 1.5.\r\nDialogue: 0,1:04:49.07,1:04:54.40,Default,,0,0,0,,So this square root of 2 reduces to trying 1 for the square root of 2,\r\nDialogue: 0,1:04:54.56,1:05:04.83,Default,,0,0,0,,which reduces to trying 1.5 as a guess for the square root of 2.\r\nDialogue: 0,1:05:06.03,1:05:08.06,Default,,0,0,0,,So that makes sense.\r\nDialogue: 0,1:05:08.11,1:05:09.52,Default,,0,0,0,,Let's look at the rest of the process.\r\nDialogue: 0,1:05:09.73,1:05:15.00,Default,,0,0,0,,If I try 1.5, that reduces.\r\nDialogue: 0,1:05:15.01,1:05:19.05,Default,,0,0,0,,1.5 turns out to be not good enough as a guess for the square root of 2.\r\nDialogue: 0,1:05:20.22,1:05:22.00,Default,,0,0,0,,So that reduces to trying the average of\r\nDialogue: 0,1:05:22.01,1:05:26.17,Default,,0,0,0,,1.5 and 2 divided by 1.5 as a guess for the square root of 2.\r\nDialogue: 0,1:05:28.29,1:05:30.37,Default,,0,0,0,,That average turns out to be 1.333.\r\nDialogue: 0,1:05:31.18,1:05:35.24,Default,,0,0,0,,So this whole thing reduces to trying 1.333 as a guess for the square root of 2.\r\nDialogue: 0,1:05:35.28,1:05:36.06,Default,,0,0,0,,And then so on.\r\nDialogue: 0,1:05:38.01,1:05:41.66,Default,,0,0,0,,That reduces to another called a \"good enough\", 1.4 something or other.\r\nDialogue: 0,1:05:41.73,1:05:44.47,Default,,0,0,0,,And then it keeps going until the process finally stops\r\nDialogue: 0,1:05:44.85,1:05:47.92,Default,,0,0,0,,with something that \"good enough\" thinks is good enough, which,\r\nDialogue: 0,1:05:47.97,1:05:51.28,Default,,0,0,0,,in this case, is 1.4142 something or other.\r\nDialogue: 0,1:05:52.51,1:05:56.05,Default,,0,0,0,,So the process makes perfect sense.\r\nDialogue: 0,1:05:59.93,1:06:03.10,Default,,0,0,0,,This, by the way, is called a recursive definition.\r\nDialogue: 0,1:06:14.40,1:06:20.96,Default,,0,0,0,,And the ability to make recursive definitions is a source of incredible power.\r\nDialogue: 0,1:06:21.95,1:06:23.05,Default,,0,0,0,,And as you can already see I've hinted at,\r\nDialogue: 0,1:06:23.09,1:06:27.21,Default,,0,0,0,,it's the thing that effectively allows you to do these infinite computations\r\nDialogue: 0,1:06:27.25,1:06:28.83,Default,,0,0,0,,that go on until something is true,\r\nDialogue: 0,1:06:29.73,1:06:33.66,Default,,0,0,0,,without having any other constricts other than the ability to call a procedure.\r\nDialogue: 0,1:06:35.97,1:06:37.47,Default,,0,0,0,,Well, let's see, there's one more thing.\r\nDialogue: 0,1:06:37.71,1:06:44.21,Default,,0,0,0,,Let me show you a variant of this definition of square root here on the slide.\r\nDialogue: 0,1:06:44.43,1:06:48.16,Default,,0,0,0,,Here's sort of the same thing.\r\nDialogue: 0,1:06:48.40,1:06:51.49,Default,,0,0,0,,What I've done here is packaged the definitions of\r\nDialogue: 0,1:06:51.52,1:06:56.16,Default,,0,0,0,,\"improve\" and \"good enough\" and \"try\" inside \"square root\".\r\nDialogue: 0,1:06:56.75,1:07:00.99,Default,,0,0,0,,So, in effect, what I've done is I've built a square root box.\r\nDialogue: 0,1:07:01.81,1:07:08.53,Default,,0,0,0,,So I've built a box that's the square root procedure that someone can use.\r\nDialogue: 0,1:07:08.57,1:07:11.47,Default,,0,0,0,,They might put in 36 and get out 6.\r\nDialogue: 0,1:07:11.81,1:07:13.83,Default,,0,0,0,,And then, packaged inside this box\r\nDialogue: 0,1:07:14.16,1:07:23.85,Default,,0,0,0,,are the definitions of \"try\" and \"good enough\" and \"improve.\"\r\nDialogue: 0,1:07:26.78,1:07:28.35,Default,,0,0,0,,So they're hidden inside this box.\r\nDialogue: 0,1:07:28.40,1:07:30.76,Default,,0,0,0,,And the reason for doing that is that,\r\nDialogue: 0,1:07:31.18,1:07:32.85,Default,,0,0,0,,if someone's using this square root,\r\nDialogue: 0,1:07:33.21,1:07:34.73,Default,,0,0,0,,if George is using this square root,\r\nDialogue: 0,1:07:34.75,1:07:37.36,Default,,0,0,0,,George probably doesn't care very much that,\r\nDialogue: 0,1:07:38.29,1:07:40.03,Default,,0,0,0,,when I implemented square root,\r\nDialogue: 0,1:07:40.21,1:07:44.45,Default,,0,0,0,,I had things inside there called \"try\" and \"good enough\" and \"improve\".\r\nDialogue: 0,1:07:46.40,1:07:49.33,Default,,0,0,0,,And in fact, Harry might have a cube root procedure\r\nDialogue: 0,1:07:49.37,1:07:50.96,Default,,0,0,0,,that has \"try\" and \"good enough\" and \"improve\".\r\nDialogue: 0,1:07:51.44,1:07:53.34,Default,,0,0,0,,And in order to not get the whole system confused,\r\nDialogue: 0,1:07:53.36,1:07:57.66,Default,,0,0,0,,it'd be good for Harry to package his internal procedures inside his cube root procedure.\r\nDialogue: 0,1:07:58.40,1:08:00.06,Default,,0,0,0,,Well, this is called block structure,\r\nDialogue: 0,1:08:00.32,1:08:08.96,Default,,0,0,0,,this particular way of packaging internals inside of a definition.\r\nDialogue: 0,1:08:09.97,1:08:12.96,Default,,0,0,0,,And let's go back and look at the slide again.\r\nDialogue: 0,1:08:13.12,1:08:18.57,Default,,0,0,0,,The way to read this kind of procedure is to say, to define \"square root\",\r\nDialogue: 0,1:08:19.87,1:08:21.84,Default,,0,0,0,,well, inside that definition,\r\nDialogue: 0,1:08:22.13,1:08:25.49,Default,,0,0,0,,I'll have the definition of an \"improve\" and\r\nDialogue: 0,1:08:25.56,1:08:28.88,Default,,0,0,0,,the definition of \"good enough\" and the definition of \"try.\"\r\nDialogue: 0,1:08:29.73,1:08:32.38,Default,,0,0,0,,And then, subject to those definitions,\r\nDialogue: 0,1:08:32.48,1:08:35.07,Default,,0,0,0,,the way I do square root is to try 1.\r\nDialogue: 0,1:08:36.08,1:08:39.33,Default,,0,0,0,,And notice here, I don't have to say 1 as a guess for the square root of X,\r\nDialogue: 0,1:08:39.87,1:08:42.32,Default,,0,0,0,,because since it's all inside the square root,\r\nDialogue: 0,1:08:42.84,1:08:44.65,Default,,0,0,0,,it sort of has this X known.\r\nDialogue: 0,1:08:54.06,1:08:56.37,Default,,0,0,0,,Let me summarize.\r\nDialogue: 0,1:08:56.49,1:08:59.49,Default,,0,0,0,,We started out with the idea that\r\nDialogue: 0,1:08:59.51,1:09:03.18,Default,,0,0,0,,what we're going to be doing is expressing imperative knowledge.\r\nDialogue: 0,1:09:04.99,1:09:09.74,Default,,0,0,0,,And in fact, here's a slide that summarizes the way we looked at Lisp.\r\nDialogue: 0,1:09:09.74,1:09:15.12,Default,,0,0,0,,We started out by looking at some primitive elements in addition and multiplication,\r\nDialogue: 0,1:09:15.85,1:09:19.50,Default,,0,0,0,,some predicates for testing whether something is less-than or something's equal.\r\nDialogue: 0,1:09:19.52,1:09:22.99,Default,,0,0,0,,And in fact, we saw really sneakily in the system we're actually using,\r\nDialogue: 0,1:09:23.02,1:09:25.85,Default,,0,0,0,,these aren't actually primitives, but it doesn't matter.\r\nDialogue: 0,1:09:26.62,1:09:28.59,Default,,0,0,0,,What matters is we're going to use them as if they're primitives.\r\nDialogue: 0,1:09:28.61,1:09:29.81,Default,,0,0,0,,We're not going to look inside.\r\nDialogue: 0,1:09:30.29,1:09:33.15,Default,,0,0,0,,We also have some primitive data and some numbers.\r\nDialogue: 0,1:09:34.62,1:09:37.66,Default,,0,0,0,,We saw some means of composition, means of combination,\r\nDialogue: 0,1:09:37.74,1:09:41.37,Default,,0,0,0,,the basic one being composing functions and\r\nDialogue: 0,1:09:41.41,1:09:43.76,Default,,0,0,0,,building combinations with operators and operands.\r\nDialogue: 0,1:09:44.81,1:09:48.43,Default,,0,0,0,,And there were some other things, like COND and \"if\" and \"define\".\r\nDialogue: 0,1:09:51.29,1:09:53.69,Default,,0,0,0,,But the main thing about \"define,\" in particular,\r\nDialogue: 0,1:09:53.87,1:09:55.71,Default,,0,0,0,,was that it was the means of abstraction.\r\nDialogue: 0,1:09:55.73,1:09:57.70,Default,,0,0,0,,It was the way that we name things.\r\nDialogue: 0,1:09:57.79,1:10:00.30,Default,,0,0,0,,You can also see from this slide not only where we've been,\r\nDialogue: 0,1:10:01.57,1:10:06.28,Default,,0,0,0,,At some point, we'll have to talk about how you combine primitive data to get compound data,\r\nDialogue: 0,1:10:06.56,1:10:12.03,Default,,0,0,0,,and how you abstract data so you can use large globs of data\r\nDialogue: 0,1:10:12.06,1:10:13.07,Default,,0,0,0,,as if they were primitive.\r\nDialogue: 0,1:10:13.90,1:10:15.87,Default,,0,0,0,,So that's where we're going.\r\nDialogue: 0,1:10:16.38,1:10:22.05,Default,,0,0,0,,But before we do that, for the next couple of lectures we're going to be talking about,\r\nDialogue: 0,1:10:23.26,1:10:26.76,Default,,0,0,0,,first of all, how it is that you make a link\r\nDialogue: 0,1:10:26.88,1:10:30.77,Default,,0,0,0,,between these procedures we write and the processes that happen in the machine.\r\nDialogue: 0,1:10:32.14,1:10:35.98,Default,,0,0,0,,And then, how it is that you start using the power of Lisp\r\nDialogue: 0,1:10:36.38,1:10:39.77,Default,,0,0,0,,to talk not only about these individual little computations,\r\nDialogue: 0,1:10:40.08,1:10:44.15,Default,,0,0,0,,but about general conventional methods of doing things.\r\nDialogue: 0,1:10:44.81,1:10:46.17,Default,,0,0,0,,OK, are there any questions?\r\nDialogue: 0,1:10:46.75,1:10:52.27,Default,,0,0,0,,AUDIENCE: Yes. If we defined A using parentheses instead of as we did,\r\nDialogue: 0,1:10:52.32,1:10:53.50,Default,,0,0,0,,what would be the difference?\r\nDialogue: 0,1:10:53.60,1:10:56.88,Default,,0,0,0,,PROFESSOR: If I wrote this, if I wrote that,\r\nDialogue: 0,1:10:57.53,1:11:02.13,Default,,0,0,0,,what I would be doing is defining a procedure named A.\r\nDialogue: 0,1:11:03.21,1:11:06.85,Default,,0,0,0,,In this case, a procedure of no arguments, which,\r\nDialogue: 0,1:11:06.85,1:11:09.61,Default,,0,0,0,,when I ran it, would give me back 5 times 5.\r\nDialogue: 0,1:11:11.07,1:11:12.29,Default,,0,0,0,,AUDIENCE: Right. I mean, you come up with the same thing,\r\nDialogue: 0,1:11:12.32,1:11:13.92,Default,,0,0,0,,except for you really got a different--\r\nDialogue: 0,1:11:14.05,1:11:16.63,Default,,0,0,0,,PROFESSOR: Right. And the difference would be, in the old one--\r\nDialogue: 0,1:11:17.02,1:11:18.35,Default,,0,0,0,,Let me be a little bit clearer here.\r\nDialogue: 0,1:11:19.13,1:11:23.44,Default,,0,0,0,,Let's call this A, like here.\r\nDialogue: 0,1:11:24.13,1:11:27.76,Default,,0,0,0,,And pretend here, just for contrast, I wrote,\r\nDialogue: 0,1:11:27.79,1:11:37.56,Default,,0,0,0,,define D to be the product of 5 and 5.\r\nDialogue: 0,1:11:40.22,1:11:41.57,Default,,0,0,0,,And the difference between those,\r\nDialogue: 0,1:11:41.96,1:11:44.24,Default,,0,0,0,,let's think about interactions with the Lisp interpreter.\r\nDialogue: 0,1:11:45.74,1:11:49.13,Default,,0,0,0,,I could type in A and Lisp would return 25.\r\nDialogue: 0,1:11:52.83,1:11:57.81,Default,,0,0,0,,I could type in D, if I just typed in D,\r\nDialogue: 0,1:11:58.49,1:12:05.55,Default,,0,0,0,,Lisp would return compound procedure D,\r\nDialogue: 0,1:12:07.12,1:12:09.13,Default,,0,0,0,,because that's what it is. It's a procedure.\r\nDialogue: 0,1:12:09.69,1:12:12.59,Default,,0,0,0,,I could run D. I could say, what's the value of running D?\r\nDialogue: 0,1:12:12.59,1:12:15.23,Default,,0,0,0,,Here is a combination with no operands.\r\nDialogue: 0,1:12:16.45,1:12:19.07,Default,,0,0,0,,I see there are no operands. I didn't put any after D.\r\nDialogue: 0,1:12:19.39,1:12:21.34,Default,,0,0,0,,And it would say, oh, that's 25.\r\nDialogue: 0,1:12:23.01,1:12:29.52,Default,,0,0,0,,Or I could say, just for completeness, if I typed in, what's the value of running A?\r\nDialogue: 0,1:12:29.54,1:12:30.57,Default,,0,0,0,,I get an error.\r\nDialogue: 0,1:12:31.79,1:12:35.29,Default,,0,0,0,,The error would be the same one as over there.\r\nDialogue: 0,1:12:35.33,1:12:40.51,Default,,0,0,0,,It'd be the error would say, sorry, 25, which is the value of A,\r\nDialogue: 0,1:12:40.56,1:12:43.24,Default,,0,0,0,,is not an operator that I can apply to something.\r\n"
  },
  {
    "path": "Ass/lec3a.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: SICP\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nLast Style Storage: Default\nAudio URI: G:\\untitled\\ref\\lec3a_480_muxed.mp4\nVideo Zoom Percent: 0.625\nScroll Position: 1836\nActive Line: 1841\nVideo File: G:\\untitled\\ref\\lec3a_480_muxed.bk.mp4\nVideo Aspect Ratio: c1.33333\nVideo Position: 135623\nPlayResX: 640\nPlayResY: 480\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:20.94,0:00:23.86,EN,,0,0,0,,PROFESSOR: Well, last time we talked about compound data,\nDialogue: 0,0:00:24.94,0:00:29.74,EN,,0,0,0,,and there were two main points to that business.\nDialogue: 0,0:00:29.74,0:00:32.48,EN,,0,0,0,,First of all, there was a methodology of data abstraction,\nDialogue: 0,0:00:32.94,0:00:39.10,EN,,0,0,0,,and the point of that was that you could isolate the way that data objects are used\nDialogue: 0,0:00:40.06,0:00:41.50,EN,,0,0,0,,from the way that they're represented:\nDialogue: 0,0:00:41.55,0:00:45.20,EN,,0,0,0,,this idea that there's this guy, George, and you go out make a contract with him;\nDialogue: 0,0:00:45.20,0:00:47.48,EN,,0,0,0,,and it's his business to represent the data objects;\nDialogue: 0,0:00:47.48,0:00:49.36,EN,,0,0,0,,and at the moment you are using them,\nDialogue: 0,0:00:49.36,0:00:51.36,EN,,0,0,0,,you don't think about George's problem.\nDialogue: 0,0:00:51.98,0:00:58.44,EN,,0,0,0,,And then secondly, there was this particular way that Lisp has of gluing together things\nDialogue: 0,0:00:58.94,0:01:00.52,EN,,0,0,0,,to form objects called pairs,\nDialogue: 0,0:01:00.52,0:01:03.54,EN,,0,0,0,,and that's done with cons, car and cdr.\nDialogue: 0,0:01:03.54,0:01:07.16,EN,,0,0,0,,And the way that cons, car and cdr are implemented is basically irrelevant.\nDialogue: 0,0:01:07.16,0:01:10.02,EN,,0,0,0,,That's sort of George's problem of how to build those things.\nDialogue: 0,0:01:10.02,0:01:11.16,EN,,0,0,0,,It could be done as primitives.\nDialogue: 0,0:01:11.16,0:01:13.80,EN,,0,0,0,,It could be done using procedures in some weird way,\nDialogue: 0,0:01:13.80,0:01:15.22,EN,,0,0,0,,but we're not going to worry about that.\nDialogue: 0,0:01:16.02,0:01:19.66,EN,,0,0,0,,And as an example, we looked at rational number arithmetic.\nDialogue: 0,0:01:19.66,0:01:21.50,EN,,0,0,0,,We looked at vectors,\nDialogue: 0,0:01:21.50,0:01:24.18,EN,,0,0,0,,and here's just a review of vectors.\nDialogue: 0,0:01:24.18,0:01:27.64,EN,,0,0,0,,Here's an operation that takes the sum of of two vectors,\nDialogue: 0,0:01:27.64,0:01:33.32,EN,,0,0,0,,so we want to add this vector, v1, and this vector, v2, and we get the sum.\nDialogue: 0,0:01:34.46,0:01:40.84,EN,,0,0,0,,And the sum is the vector whose coordinates are the sum of the coordinates of the pieces you're adding.\nDialogue: 0,0:01:41.28,0:01:45.66,EN,,0,0,0,,So I can say, to define make-vect, right, to add two vectors\nDialogue: 0,0:01:45.66,0:01:51.72,EN,,0,0,0,,I make a vector, whose x coordinate is the sum of the two x coordinates,\nDialogue: 0,0:01:52.10,0:01:54.82,EN,,0,0,0,,and whose y coordinate is the sum of the two y coordinates.\nDialogue: 0,0:01:56.06,0:02:04.10,EN,,0,0,0,,And then similarly, we could have an operation that scales vectors,\nDialogue: 0,0:02:04.94,0:02:12.66,EN,,0,0,0,,so here's a procedure scale that multiplies a vector, v, by some number, s.\nDialogue: 0,0:02:13.08,0:02:16.14,EN,,0,0,0,,So here's v, v goes from there to there\nDialogue: 0,0:02:16.32,0:02:20.22,EN,,0,0,0,,and I scale v, and I get a vector in the same direction that's longer.\nDialogue: 0,0:02:21.56,0:02:24.26,EN,,0,0,0,,And again, to scale a vector, I multiply the successive coordinates.\nDialogue: 0,0:02:24.26,0:02:30.22,EN,,0,0,0,,So I make a vector, whose x coordinate is the scale factor times the x coordinate\nDialogue: 0,0:02:30.56,0:02:33.54,EN,,0,0,0,,and whose y coordinate is the scale factor times the y coordinate.\nDialogue: 0,0:02:33.54,0:02:40.28,EN,,0,0,0,,So those are two operations that are implemented using the representation of vectors.\nDialogue: 0,0:02:40.28,0:02:45.02,EN,,0,0,0,,And the representation of vectors, for instance, is something that we can build in terms of pairs.\nDialogue: 0,0:02:45.34,0:02:51.28,EN,,0,0,0,,So George has gone out and implemented for us make-vector and x coordinate and y coordinate,\nDialogue: 0,0:02:53.02,0:02:57.98,EN,,0,0,0,,and this could be done, for instance, using cons,car and cdr;\nDialogue: 0,0:02:58.88,0:03:06.78,EN,,0,0,0,,and notice here, I wrote this in a slightly different way.\nDialogue: 0,0:03:08.04,0:03:11.00,EN,,0,0,0,,The procedures we've seen before, I've said something like\nDialogue: 0,0:03:11.14,0:03:16.22,EN,,0,0,0,,say, make-vector of x and y: cons of x and y.\nDialogue: 0,0:03:16.22,0:03:17.98,EN,,0,0,0,,And here I just wrote make-vector cons.\nDialogue: 0,0:03:17.98,0:03:20.48,EN,,0,0,0,,And that means something slightly different.\nDialogue: 0,0:03:20.48,0:03:26.22,EN,,0,0,0,,Previously we'd say, define make-vector to be a procedure that takes two arguments, x and y,\nDialogue: 0,0:03:26.22,0:03:28.04,EN,,0,0,0,,and does cons of x and y.\nDialogue: 0,0:03:28.04,0:03:34.12,EN,,0,0,0,,And here I am saying define make-vector to be the thing that cons is,\nDialogue: 0,0:03:35.18,0:03:39.66,EN,,0,0,0,,and that's almost the same as the other way we've been writing things.\nDialogue: 0,0:03:39.66,0:03:46.58,EN,,0,0,0,,And I just want you to get used to the idea that procedures can be objects, and that you can name them.\nDialogue: 0,0:03:48.70,0:03:51.80,EN,,0,0,0,,OK, well there's vector representation, and again,\nDialogue: 0,0:03:51.80,0:03:55.68,EN,,0,0,0,,if that was all there was to it,this would all be pretty boring.\nDialogue: 0,0:03:57.02,0:04:02.16,EN,,0,0,0,,And the point is, remember, that you can use cons to glue together not just numbers to form pairs,\nDialogue: 0,0:04:02.16,0:04:04.16,EN,,0,0,0,,but to glue together arbitrary things.\nDialogue: 0,0:04:05.20,0:04:11.60,EN,,0,0,0,,So for instance, if we'd like to represent a line segment,\nDialogue: 0,0:04:11.60,0:04:15.64,EN,,0,0,0,,say the line segment that goes from a certain vector:\nDialogue: 0,0:04:16.06,0:04:28.30,EN,,0,0,0,,say, the segment from the vector 2,3 to the point represented by the vector 5,1.\nDialogue: 0,0:04:28.30,0:04:31.82,EN,,0,0,0,,If we want to represent that line segment,\nDialogue: 0,0:04:33.26,0:04:36.20,EN,,0,0,0,,then we can build that as a pair of pairs.\nDialogue: 0,0:04:40.72,0:04:42.94,EN,,0,0,0,,So again, we can represent line segments.\nDialogue: 0,0:04:42.94,0:04:47.34,EN,,0,0,0,,We can make a constructor that makes a segment using cons,\nDialogue: 0,0:04:47.98,0:04:51.60,EN,,0,0,0,,selects out the start of a segment, selects out the end point of the segment;\nDialogue: 0,0:04:55.24,0:04:59.76,EN,,0,0,0,,and then if we actually look at that, if we peel away the abstraction layers,\nDialogue: 0,0:04:59.88,0:05:02.10,EN,,0,0,0,,and see what's that really is a pair of pairs,\nDialogue: 0,0:05:04.66,0:05:06.22,EN,,0,0,0,,we'd say well that's a pair.\nDialogue: 0,0:05:06.22,0:05:08.22,EN,,0,0,0,,Here's the segment.\nDialogue: 0,0:05:10.00,0:05:16.72,EN,,0,0,0,,It's car, right, it's car pointer is a pair, and it's cdr is also a pair,\nDialogue: 0,0:05:18.32,0:05:25.54,EN,,0,0,0,,and then what the car is--here's the car, that itself is a pair of 2 and 3.\nDialogue: 0,0:05:26.02,0:05:28.08,EN,,0,0,0,,And similarly the cdr is a pair of 2 and 3.\nDialogue: 0,0:05:28.16,0:05:29.24,EN,,0,0,0,,And let me remind you again\nDialogue: 0,0:05:29.32,0:05:33.46,EN,,0,0,0,,that a lot of people have some idea that if I'd taken this arrow and somehow\nDialogue: 0,0:05:33.80,0:05:36.90,EN,,0,0,0,,written it to point down, that would mean something else.\nDialogue: 0,0:05:36.98,0:05:38.28,EN,,0,0,0,,That's irrelevant.\nDialogue: 0,0:05:38.58,0:05:43.90,EN,,0,0,0,,It's only how these are connected and not whether this arrow happens to go vertically or horizontally.\nDialogue: 0,0:05:47.48,0:05:52.18,EN,,0,0,0,,And again just to remind you, there was this notion of closure.\nDialogue: 0,0:05:52.94,0:06:05.62,EN,,0,0,0,,See, closure was the thing that allowed us to start building up complexity, that didn't trap us in pairs.\nDialogue: 0,0:06:06.64,0:06:15.24,EN,,0,0,0,,Particularly what I mean is the things that we make, having combined things using cons to get a pair,\nDialogue: 0,0:06:16.44,0:06:22.64,EN,,0,0,0,,those things themselves can be combined using cons to make more complicated things.\nDialogue: 0,0:06:23.28,0:06:31.98,EN,,0,0,0,,Or as a mathematician might say, the set of data objects in Lisp is closed under the operation of forming pairs.\nDialogue: 0,0:06:33.82,0:06:36.34,EN,,0,0,0,,That's the thing that allows us to build complexity.\nDialogue: 0,0:06:36.34,0:06:38.04,EN,,0,0,0,,And that seems obvious, but remember\nDialogue: 0,0:06:39.06,0:06:42.46,EN,,0,0,0,,a lot of the things in the computer languages that people use are not closed.\nDialogue: 0,0:06:42.46,0:06:48.06,EN,,0,0,0,,So for example, forming arrays in Basic and Fortran is not a closed operation,\nDialogue: 0,0:06:48.08,0:06:51.94,EN,,0,0,0,,because you can make an array of numbers or character strings or something,\nDialogue: 0,0:06:52.04,0:06:54.18,EN,,0,0,0,,but you can't make an array of arrays.\nDialogue: 0,0:06:54.64,0:06:56.68,EN,,0,0,0,,And when you look at means of combination\nDialogue: 0,0:06:57.60,0:07:02.78,EN,,0,0,0,,you should be asking yourself whether things are closed under that means of combination.\nDialogue: 0,0:07:05.06,0:07:08.26,EN,,0,0,0,,Well in any case, because we can form pairs of pairs,\nDialogue: 0,0:07:08.86,0:07:12.78,EN,,0,0,0,,we can start using pairs to glue things together in all sorts of different ways.\nDialogue: 0,0:07:14.02,0:07:18.26,EN,,0,0,0,,So for instance if I'd like to glue together the four things, 1, 2, 3 and 4,\nDialogue: 0,0:07:18.26,0:07:19.82,EN,,0,0,0,,there are a lot of ways I can do it.\nDialogue: 0,0:07:20.74,0:07:26.12,EN,,0,0,0,,I could, for example, like we did with that line segment, i could make a pair\nDialogue: 0,0:07:29.02,0:07:36.88,EN,,0,0,0,,that had a 1 and a 2 and a 3 and a 4, right?\nDialogue: 0,0:07:36.88,0:07:40.06,EN,,0,0,0,,Or if I liked, I could do something like this.\nDialogue: 0,0:07:40.06,0:07:45.52,EN,,0,0,0,,I could make a pair, whose first thing is a pair,\nDialogue: 0,0:07:46.44,0:07:53.20,EN,,0,0,0,,whose car is 1, and his cdr is itself a pair that has the 2 and the 3\nDialogue: 0,0:07:53.26,0:07:55.08,EN,,0,0,0,,and then I could put the 4 up here.\nDialogue: 0,0:07:56.92,0:08:02.16,EN,,0,0,0,,So you see, there are a lot of different ways that I can start using pairs to glue things together,\nDialogue: 0,0:08:02.16,0:08:07.74,EN,,0,0,0,,and so it'll be a good idea to establish some kind of conventions,right,\nDialogue: 0,0:08:07.74,0:08:11.58,EN,,0,0,0,,that allow us to deal with this thing in some conventional way,\nDialogue: 0,0:08:11.58,0:08:14.00,EN,,0,0,0,,so we're not constantly making an ad hoc choice.\nDialogue: 0,0:08:15.94,0:08:19.04,EN,,0,0,0,,And Lisp has a particular convention\nDialogue: 0,0:08:20.74,0:08:25.82,EN,,0,0,0,,for representing a sequence of things as, essentially, a chain of pairs,\nDialogue: 0,0:08:26.78,0:08:28.18,EN,,0,0,0,,and that's called a List.\nDialogue: 0,0:08:34.72,0:08:40.50,EN,,0,0,0,,And what a list is is essentially just a convention for representing a sequence.\nDialogue: 0,0:08:40.70,0:08:47.38,EN,,0,0,0,,I would represent the sequence 1, 2, 3 and 4 by a sequence of pairs.\nDialogue: 0,0:08:48.26,0:08:54.68,EN,,0,0,0,,I'd put 1 here and then the cdr of this would point to another pair\nDialogue: 0,0:08:59.20,0:09:01.40,EN,,0,0,0,,whose car was the next thing in the sequence,\nDialogue: 0,0:09:01.52,0:09:03.42,EN,,0,0,0,,and the cdr would point to another pair\nDialogue: 0,0:09:05.44,0:09:07.30,EN,,0,0,0,,whose car was the next thing in the sequence--\nDialogue: 0,0:09:07.36,0:09:08.44,EN,,0,0,0,,so there's 3--\nDialogue: 0,0:09:08.44,0:09:09.74,EN,,0,0,0,,and then another one.\nDialogue: 0,0:09:09.74,0:09:13.22,EN,,0,0,0,,So for each item in the sequence, I'll get a pair.\nDialogue: 0,0:09:15.82,0:09:18.32,EN,,0,0,0,,And now there are no more, so I put a special marker\nDialogue: 0,0:09:20.72,0:09:22.74,EN,,0,0,0,,that means there's nothing more in the List.\nDialogue: 0,0:09:24.14,0:09:34.64,EN,,0,0,0,,OK, so that's a conventional way to glue things together if you want to represent a sequence, right.\nDialogue: 0,0:09:34.64,0:09:37.98,EN,,0,0,0,,And what it is is a bunch of pairs,\nDialogue: 0,0:09:39.40,0:09:44.80,EN,,0,0,0,,the successive cars of each pair are the items that you want to glue together,\nDialogue: 0,0:09:46.00,0:09:48.46,EN,,0,0,0,,and the cdr pointer points to the next pair.\nDialogue: 0,0:09:50.02,0:09:56.04,EN,,0,0,0,,Now if I actually wanted to construct that, what I would type into Lisp is this:\nDialogue: 0,0:09:56.62,0:09:58.76,EN,,0,0,0,,I'd actually construct that as saying, well this thing is\nDialogue: 0,0:09:59.22,0:10:15.28,EN,,0,0,0,,the cons of 1 onto the cons of 2 onto the cons of 3 onto the cons of 4 onto, well, this thing nil.\nDialogue: 0,0:10:15.28,0:10:20.00,EN,,0,0,0,,And what nil is is a name for the end of List marker.\nDialogue: 0,0:10:20.80,0:10:23.24,EN,,0,0,0,,It's a special name, which means this is the end of the List.\nDialogue: 0,0:10:26.24,0:10:30.26,EN,,0,0,0,,OK, so that's how I would actually construct that.\nDialogue: 0,0:10:37.54,0:10:41.40,EN,,0,0,0,,Of course, it's a terrible drag to constantly have to write something like\nDialogue: 0,0:10:41.45,0:10:45.18,EN,,0,0,0,,the cons of 1 onto the cons of 2 onto the cons of 3, whenever you want to make this thing.\nDialogue: 0,0:10:45.18,0:10:50.10,EN,,0,0,0,,So Lisp has an operation that's called LIST,\nDialogue: 0,0:10:53.70,0:10:57.72,EN,,0,0,0,,and List is just an abbreviation for this nest of conses.\nDialogue: 0,0:10:58.96,0:11:06.32,EN,,0,0,0,,So I could say, I could construct that by saying that is the List of 1, 2, 3 and 4.\nDialogue: 0,0:11:07.78,0:11:11.74,EN,,0,0,0,,And all this is is another way, a piece of syntactic sugar,\nDialogue: 0,0:11:11.94,0:11:14.76,EN,,0,0,0,,a more convenient way for writing that chain of conses--\nDialogue: 0,0:11:14.76,0:11:17.84,EN,,0,0,0,,cons of cons of cons of cons of cons of cons onto nil.\nDialogue: 0,0:11:18.48,0:11:39.78,EN,,0,0,0,,So for example, I could build this thing and say, I'll define 1-TO-4 to be the List of 1, 2, 3 and 4.\nDialogue: 0,0:11:47.96,0:11:53.02,EN,,0,0,0,,OK, well notice some of the consequences of using this convention.\nDialogue: 0,0:11:53.80,0:11:56.92,EN,,0,0,0,,First of all if I have this List, this 1, 2, 3 and 4,\nDialogue: 0,0:11:57.36,0:12:02.64,EN,,0,0,0,,the car of the whole thing is the first element in the List, right.\nDialogue: 0,0:12:04.06,0:12:05.28,EN,,0,0,0,,How do I get 2?\nDialogue: 0,0:12:05.28,0:12:23.94,EN,,0,0,0,,Well, 2 would be the car of the cdr of this thing 1-TO-4, it would be 2, right.\nDialogue: 0,0:12:23.98,0:12:29.48,EN,,0,0,0,,I take this thing, I take the cdr of it, which is this much,\nDialogue: 0,0:12:29.82,0:12:31.68,EN,,0,0,0,,and the car of that is 2,\nDialogue: 0,0:12:32.58,0:12:47.42,EN,,0,0,0,,and then similarly, the car of the cdr of the cdr of 1-TO-4, cdr, cdr, car--\nDialogue: 0,0:12:47.42,0:12:51.36,EN,,0,0,0,,would give me 3, and so on.\nDialogue: 0,0:12:52.68,0:12:55.84,EN,,0,0,0,,Let's take a look at that on the computer screen for a second.\nDialogue: 0,0:12:57.50,0:13:11.18,EN,,0,0,0,,I could come up to List, and I could type define 1-TO-4 to be the List of 1, 2, 3 and 4, right.\nDialogue: 0,0:13:13.78,0:13:21.28,EN,,0,0,0,,And I'll tell that to Lisp, and it says, fine, that's the definition of 1-TO-4.\nDialogue: 0,0:13:22.30,0:13:36.74,EN,,0,0,0,,And I could say, for instance, what's the car of the cdr of the cdr of 1-TO-4, close paren, close paren.\nDialogue: 0,0:13:38.34,0:13:42.42,EN,,0,0,0,,Right, so the car of the cdr of the cdr would be 3.\nDialogue: 0,0:13:44.08,0:13:50.08,EN,,0,0,0,,Right, or I could say, what's 1-TO-4 itself.\nDialogue: 0,0:13:51.26,0:13:57.22,EN,,0,0,0,,And you see what Lisp typed out is 1, 2, 3, 4, enclosed in parentheses,\nDialogue: 0,0:13:57.22,0:14:02.12,EN,,0,0,0,,and this notation, typing the elements of the List enclosed in parentheses\nDialogue: 0,0:14:02.12,0:14:08.90,EN,,0,0,0,,is Lisp's conventional way for printing back this chain of pairs that represents a sequence.\nDialogue: 0,0:14:08.90,0:14:17.14,EN,,0,0,0,,So for example, if I said, what's the cdr of 1-TO-4,\nDialogue: 0,0:14:19.30,0:14:21.12,EN,,0,0,0,,that's going to be the rest of the List.\nDialogue: 0,0:14:21.32,0:14:26.96,EN,,0,0,0,,That's the thing pointed to by the first pair, which is, again, a sequence that starts off with 2.\nDialogue: 0,0:14:28.52,0:14:37.74,EN,,0,0,0,,Or for example, I go off and say, what's the cdr of the cdr of 1-TO-4;\nDialogue: 0,0:14:43.24,0:14:44.68,EN,,0,0,0,,then that's 3,4.\nDialogue: 0,0:14:44.82,0:14:59.66,EN,,0,0,0,,Or if I say, what's the cdr of the cdr of the cdr of the cdr of 1-TO-4,\nDialogue: 0,0:15:04.74,0:15:10.46,EN,,0,0,0,,and I'm down there looking at the end of List pointer itself, and Lisp prints that as just open paren, close paren.\nDialogue: 0,0:15:10.96,0:15:13.48,EN,,0,0,0,,You can think of that as a List with nothing in there.\nDialogue: 0,0:15:14.12,0:15:21.38,EN,,0,0,0,,All right, see at the end what I did there was I looked at the cdr of the cdr of the cdr of 1-TO-4,\nDialogue: 0,0:15:21.42,0:15:25.20,EN,,0,0,0,,and I'm just left with the end of List pointer itself.\nDialogue: 0,0:15:25.20,0:15:27.20,EN,,0,0,0,,And that gets printed as open close.\nDialogue: 0,0:15:34.14,0:15:39.98,EN,,0,0,0,,All right, well that's a conventional way you can see for working down a List\nDialogue: 0,0:15:41.50,0:15:43.44,EN,,0,0,0,,by taking successive cdrs of things.\nDialogue: 0,0:15:43.44,0:15:45.00,EN,,0,0,0,,It's called cdring down a List.\nDialogue: 0,0:15:46.64,0:15:49.78,EN,,0,0,0,,And of course it's pretty much of a drag to type all those cdrs by hand.\nDialogue: 0,0:15:49.78,0:15:52.24,EN,,0,0,0,,You don't do that. You write procedures that do that.\nDialogue: 0,0:15:52.96,0:15:59.10,EN,,0,0,0,,And in fact one very, very common thing to do in Lisp is to write procedures that,\nDialogue: 0,0:15:59.85,0:16:06.54,EN,,0,0,0,,sort of, take a List of things and do something to every element in List, and return you a List of the results.\nDialogue: 0,0:16:07.42,0:16:11.92,EN,,0,0,0,,So what I mean for example, is I might write a procedure called Scale-List,\nDialogue: 0,0:16:16.80,0:16:25.24,EN,,0,0,0,,and Scale-List I might say I want to scale by 10 the entire List 1-TO-4,\nDialogue: 0,0:16:26.66,0:16:35.32,EN,,0,0,0,,and that would return for me the List 10, 20, 30, 40.\nDialogue: 0,0:16:38.25,0:16:40.25,EN,,0,0,0,,Right, it returns List, and\nDialogue: 0,0:16:44.49,0:16:49.30,EN,,0,0,0,,well you can see that there's going to be some kind of recursive strategy for doing it.\nDialogue: 0,0:16:49.30,0:16:51.30,EN,,0,0,0,,How would I actually write that procedure?\nDialogue: 0,0:16:52.52,0:16:59.80,EN,,0,0,0,,The idea would be, well if you'd like to build up a List where you've multiplied every element by 10,\nDialogue: 0,0:17:00.44,0:17:04.84,EN,,0,0,0,,what you'd say is well you imagine that you'd taken the rest of the List--\nDialogue: 0,0:17:05.86,0:17:08.42,EN,,0,0,0,,right, the thing represented by the cdr of the List,\nDialogue: 0,0:17:08.42,0:17:14.16,EN,,0,0,0,,and suppose I'd already built a List where each of these was multiplied by 10--\nDialogue: 0,0:17:16.06,0:17:19.68,EN,,0,0,0,,that would be Scale-List of the cdr of the List.\nDialogue: 0,0:17:20.12,0:17:23.82,EN,,0,0,0,,And then all I have to do is multiply the car of the List by 10,\nDialogue: 0,0:17:24.89,0:17:27.24,EN,,0,0,0,,and then cons that onto the rest, and I'll get a List.\nDialogue: 0,0:17:29.02,0:17:33.09,EN,,0,0,0,,Right and then similarly, to have scaled the cdr of the List, I'll scale the cdr of that\nDialogue: 0,0:17:33.30,0:17:36.20,EN,,0,0,0,,cons onto that 2 multiplied by 10.\nDialogue: 0,0:17:36.42,0:17:41.16,EN,,0,0,0,,And finally when I get all the way down to the end, and I only have this end of List pointer.\nDialogue: 0,0:17:41.72,0:17:45.28,EN,,0,0,0,,All right, this thing whose name is nil-- well I just returned an end of List pointer.\nDialogue: 0,0:17:45.54,0:17:47.68,EN,,0,0,0,,So there's a recursive strategy for doing that.\nDialogue: 0,0:17:47.68,0:17:50.52,EN,,0,0,0,,Here's the actual procedure that does that.\nDialogue: 0,0:17:50.96,0:17:55.04,EN,,0,0,0,,Right, this is an example of the general strategy of cdr-ing down a List and\nDialogue: 0,0:17:55.66,0:17:58.24,EN,,0,0,0,,so called cons-ing up the result, right.\nDialogue: 0,0:17:58.24,0:18:06.04,EN,,0,0,0,,So to Scale a List l by some scale factor s, what do I do?\nDialogue: 0,0:18:06.04,0:18:10.40,EN,,0,0,0,,Well there's a test, and Lisp has the predicate called null.\nDialogue: 0,0:18:10.40,0:18:13.22,EN,,0,0,0,,Null means is this thing the end of List pointer,\nDialogue: 0,0:18:13.90,0:18:17.16,EN,,0,0,0,,or another way to think of that is are there any elements in this List, right.\nDialogue: 0,0:18:18.17,0:18:23.00,EN,,0,0,0,,But in any case if I'm looking at the end of List pointer, then I just return the end of List pointer.\nDialogue: 0,0:18:23.65,0:18:24.60,EN,,0,0,0,,I just return nil,\nDialogue: 0,0:18:24.94,0:18:35.14,EN,,0,0,0,,otherwise I cons together the result of doing what I'm going to do to the first element in the List,\nDialogue: 0,0:18:35.54,0:18:39.29,EN,,0,0,0,,namely taking the car of l and multiplying it by s,\nDialogue: 0,0:18:40.36,0:18:46.34,EN,,0,0,0,,and I cons that onto recursively scaling the rest of the List.\nDialogue: 0,0:18:49.98,0:18:52.18,EN,,0,0,0,,OK, so again, the general idea is that you\nDialogue: 0,0:18:52.22,0:18:56.09,EN,,0,0,0,,you recursively do something to the rest of the List, to the cdr of the List,\nDialogue: 0,0:18:56.48,0:19:01.16,EN,,0,0,0,,and then you cons that onto actually doing something to the first element of the List.\nDialogue: 0,0:19:01.16,0:19:05.18,EN,,0,0,0,,When you get down to the end here, you return the end of List pointer,\nDialogue: 0,0:19:07.34,0:19:11.36,EN,,0,0,0,,and that's a general pattern for doing something to a list.\nDialogue: 0,0:19:14.05,0:19:19.52,EN,,0,0,0,,Well of course you should know by now that the very fact\nDialogue: 0,0:19:19.53,0:19:22.62,EN,,0,0,0,,that there's a general pattern there means I shouldn't be writing this procedure at all.\nDialogue: 0,0:19:22.62,0:19:24.90,EN,,0,0,0,,What I should do is write a procedure\nDialogue: 0,0:19:24.90,0:19:26.32,EN,,0,0,0,,that's the general pattern itself\nDialogue: 0,0:19:26.80,0:19:30.30,EN,,0,0,0,,that says, do something to everything in the List and define this thing in terms of that.\nDialogue: 0,0:19:30.68,0:19:32.30,EN,,0,0,0,,Right, make some higher order procedure,\nDialogue: 0,0:19:32.32,0:19:35.18,EN,,0,0,0,,and here's the higher order procedure that does that. It's called MAP,\nDialogue: 0,0:19:36.73,0:19:43.17,EN,,0,0,0,,and what MAP does is it takes a List, takes a List l, and it takes a procedure p,\nDialogue: 0,0:19:44.92,0:19:51.08,EN,,0,0,0,,and it returns the List of the elements gotten by applying p to each successive element in the List.\nDialogue: 0,0:19:51.81,0:19:55.40,EN,,0,0,0,,All right, so p of e1, p of e2, p of en.\nDialogue: 0,0:19:55.64,0:20:01.54,EN,,0,0,0,,Right, so I think of taking this List and transforming it by applying p to each element.\nDialogue: 0,0:20:02.52,0:20:07.08,EN,,0,0,0,,And you see all this procedure is is exactly the general strategy I said.\nDialogue: 0,0:20:07.08,0:20:09.08,EN,,0,0,0,,Instead of multiply by 10, it's do the procedure.\nDialogue: 0,0:20:09.08,0:20:11.64,EN,,0,0,0,,If the List is empty, return nil.\nDialogue: 0,0:20:11.86,0:20:16.60,EN,,0,0,0,,Otherwise, apply p to the first element of the List.\nDialogue: 0,0:20:17.14,0:20:18.74,EN,,0,0,0,,Right, apply p to car of l,\nDialogue: 0,0:20:19.30,0:20:25.40,EN,,0,0,0,,and cons that onto the result of applying p to everything in the cdr of the List,\nDialogue: 0,0:20:25.61,0:20:28.84,EN,,0,0,0,,so that's a general procedure called MAP.\nDialogue: 0,0:20:29.86,0:20:39.04,EN,,0,0,0,,And I could define Scale-List in terms of MAP.\nDialogue: 0,0:20:39.04,0:20:41.04,EN,,0,0,0,,Let me show you that first.\nDialogue: 0,0:20:43.46,0:20:52.50,EN,,0,0,0,,But I could say Scale-List is another way to define it is just MAP along the List by the procedure,\nDialogue: 0,0:20:52.50,0:20:55.54,EN,,0,0,0,,which takes an item and multiplies it by s.\nDialogue: 0,0:20:58.96,0:21:01.90,EN,,0,0,0,,Right, so this is really the way I should think about scaling the List,\nDialogue: 0,0:21:02.12,0:21:07.40,EN,,0,0,0,,build that actual recursion into the general strategy, not to every particular procedure I write.\nDialogue: 0,0:21:07.40,0:21:11.28,EN,,0,0,0,,And of course, one of the values of doing this is that you start to see commonality.\nDialogue: 0,0:21:12.16,0:21:15.02,EN,,0,0,0,,Right, again you're capturing general patterns of usage.\nDialogue: 0,0:21:15.96,0:21:31.18,EN,,0,0,0,,For instance, if I said MAP, the square procedure, down this List 1-TO-4, then I'd end up with 1, 4, 9 and 16.\nDialogue: 0,0:21:32.48,0:21:37.17,EN,,0,0,0,,Right, or if I said MAP down this List,\nDialogue: 0,0:21:37.57,0:21:46.32,EN,,0,0,0,,lambda of x plus x 10, if I MAP that down 1-TO-4,\nDialogue: 0,0:21:49.68,0:21:52.86,EN,,0,0,0,,then I'd get the List where everything had 10 added to it:\nDialogue: 0,0:21:53.34,0:21:58.17,EN,,0,0,0,,right, so I'd get 11,12, 13, 14.\nDialogue: 0,0:22:00.56,0:22:05.76,EN,,0,0,0,,And you can see that's going to be a very, very common idea: doing something to every element in the List.\nDialogue: 0,0:22:08.66,0:22:12.22,EN,,0,0,0,,One thing you might think about is writing MAP in an iterative style.\nDialogue: 0,0:22:12.22,0:22:16.04,EN,,0,0,0,,The one I wrote happens to evolve a recursive process,\nDialogue: 0,0:22:16.36,0:22:19.10,EN,,0,0,0,,but we could just as easily have made one that evolves an iterative process.\nDialogue: 0,0:22:19.10,0:22:23.16,EN,,0,0,0,,But see the interesting thing about it is that once you start thinking in terms of MAP--\nDialogue: 0,0:22:24.02,0:22:29.00,EN,,0,0,0,,see, once you say scale is just MAP, you stop thinking about whether it's iterative or recursive,\nDialogue: 0,0:22:29.00,0:22:31.82,EN,,0,0,0,,and you just say, well there's this aggregate, there's this List,\nDialogue: 0,0:22:32.22,0:22:34.52,EN,,0,0,0,,and what I do is transform every item in the List,\nDialogue: 0,0:22:34.56,0:22:38.36,EN,,0,0,0,,and I stop thinking about the particular control structure in order.\nDialogue: 0,0:22:38.88,0:22:41.09,EN,,0,0,0,,That's a very, very important idea,\nDialogue: 0,0:22:42.36,0:22:46.48,EN,,0,0,0,,and it, I guess it really comes out of APL.\nDialogue: 0,0:22:46.48,0:22:49.10,EN,,0,0,0,,It's, sort of, the really important idea in APL\nDialogue: 0,0:22:49.12,0:22:51.13,EN,,0,0,0,,that you stop thinking about control structures,\nDialogue: 0,0:22:51.41,0:22:53.92,EN,,0,0,0,,and you start thinking about operations on aggregates,\nDialogue: 0,0:22:55.01,0:23:00.01,EN,,0,0,0,,and then about halfway through this course,we'll see when we talk about something called stream processing,\nDialogue: 0,0:23:00.26,0:23:02.64,EN,,0,0,0,,how that view of the world really comes into its glory.\nDialogue: 0,0:23:02.64,0:23:05.30,EN,,0,0,0,,This is just us a, sort of, cute idea.\nDialogue: 0,0:23:05.30,0:23:08.70,EN,,0,0,0,,But we'll see much more applications of that later on.\nDialogue: 0,0:23:09.36,0:23:16.84,EN,,0,0,0,,Well let me mention that there's something that's very similar to MAP that's also a useful idea, and that's--\nDialogue: 0,0:23:17.56,0:23:22.54,EN,,0,0,0,,see, MAP says I take a List, I apply something to each item,\nDialogue: 0,0:23:22.98,0:23:25.62,EN,,0,0,0,,and I return a List of the successive values.\nDialogue: 0,0:23:25.98,0:23:28.69,EN,,0,0,0,,There's another thing I might do, which is very, very similar,\nDialogue: 0,0:23:29.32,0:23:35.86,EN,,0,0,0,,which is take a List and some action you want to do and then do it to each item in the List in sequence.\nDialogue: 0,0:23:36.29,0:23:39.40,EN,,0,0,0,,Don't make a List of the values, just do this particular action,\nDialogue: 0,0:23:40.02,0:23:45.10,EN,,0,0,0,,and that's something that's very much like MAP.\nDialogue: 0,0:23:45.10,0:23:46.02,EN,,0,0,0,,It's called for-each,\nDialogue: 0,0:23:46.74,0:23:49.48,EN,,0,0,0,,and for-each takes a procedure and a List,\nDialogue: 0,0:23:49.62,0:23:53.86,EN,,0,0,0,,and what it's going to do is do something to every item in the List.\nDialogue: 0,0:23:55.16,0:23:58.53,EN,,0,0,0,,So basically what it does: it says if the List is not empty,\nDialogue: 0,0:23:59.74,0:24:01.12,EN,,0,0,0,,if the List is not null,\nDialogue: 0,0:24:01.90,0:24:06.25,EN,,0,0,0,,then what I do is, I apply my procedure to the first item in the List,\nDialogue: 0,0:24:07.68,0:24:11.66,EN,,0,0,0,,and then I do this thing to the rest of the List.\nDialogue: 0,0:24:12.44,0:24:15.25,EN,,0,0,0,,I apply for-each to the cdr of the List.\nDialogue: 0,0:24:15.88,0:24:18.73,EN,,0,0,0,,All right, so I do it to the first of the List, do it to the rest of the List,\nDialogue: 0,0:24:19.32,0:24:23.92,EN,,0,0,0,,and of course, when I call it recursively, that's going to do it to the rest of the rest of the List and so on.\nDialogue: 0,0:24:23.92,0:24:28.12,EN,,0,0,0,,And finally, when I get done, I have to just do something to say I'm done,\nDialogue: 0,0:24:28.16,0:24:32.40,EN,,0,0,0,,so we'll return the message \"done.\" So that's very, very similar to MAP.\nDialogue: 0,0:24:32.80,0:24:35.12,EN,,0,0,0,,It's mostly different in what it returns.\nDialogue: 0,0:24:35.48,0:24:39.90,EN,,0,0,0,,And so for example, if I had some procedure that printed things on the screen,\nDialogue: 0,0:24:40.56,0:24:45.81,EN,,0,0,0,,if I wanted to print everything in the List, I could say for-each, print this List.\nDialogue: 0,0:24:46.78,0:24:51.33,EN,,0,0,0,,Or if I had a List of figures, and I wanted to draw them on the display,\nDialogue: 0,0:24:51.62,0:24:54.86,EN,,0,0,0,,I could say for-each, display on the screen this figure.\nDialogue: 0,0:24:58.18,0:24:59.32,EN,,0,0,0,,Take questions.\nDialogue: 0,0:25:00.62,0:25:04.26,EN,,0,0,0,,AUDIENCE: Does it create a new copy with something done to it,\nDialogue: 0,0:25:04.30,0:25:07.54,EN,,0,0,0,,unless you explicitly tell it to do that? Is that correct?\nDialogue: 0,0:25:07.54,0:25:09.18,EN,,0,0,0,,PROFESSOR: Right. Ah.\nDialogue: 0,0:25:09.93,0:25:10.94,EN,,0,0,0,,Yeah, that's right.\nDialogue: 0,0:25:10.94,0:25:15.14,EN,,0,0,0,,For-each does not create a List. It just sort of does something.\nDialogue: 0,0:25:15.14,0:25:17.29,EN,,0,0,0,,So if you have a bunch of things you want to do\nDialogue: 0,0:25:18.02,0:25:21.56,EN,,0,0,0,,and you're not worried about values like printing something, or drawing something on the screen,\nDialogue: 0,0:25:21.89,0:25:24.60,EN,,0,0,0,,or ringing the bell on the terminal,or for something,\nDialogue: 0,0:25:24.60,0:25:27.64,EN,,0,0,0,,you can say for-each, you know, do this for-each of those things in the List,\nDialogue: 0,0:25:28.21,0:25:32.42,EN,,0,0,0,,whereas MAP actually builds you this new collection of values that you might want to use.\nDialogue: 0,0:25:32.42,0:25:34.16,EN,,0,0,0,,It's just a subtle difference between them.\nDialogue: 0,0:25:34.16,0:25:36.30,EN,,0,0,0,,AUDIENCE: Could you write MAP using for-each,\nDialogue: 0,0:25:36.32,0:25:40.16,EN,,0,0,0,,so that you did some sort of cons or something to build the List back up?\nDialogue: 0,0:25:40.18,0:25:44.46,EN,,0,0,0,,PROFESSOR: Well, sort of. I mean, I probably could.\nDialogue: 0,0:25:44.46,0:25:49.98,EN,,0,0,0,,I can't think of how to do it right offhand, but yeah, I could arrange something.\nDialogue: 0,0:25:50.48,0:25:54.73,EN,,0,0,0,,AUDIENCE: The vital difference between MAP and for-each is one is recursive and the other is not\nDialogue: 0,0:25:54.73,0:26:00.62,EN,,0,0,0,,in the sense you defined early yesterday, I believe.\nDialogue: 0,0:26:01.24,0:26:03.86,EN,,0,0,0,,PROFESSOR: Yeah, about MAP and for-each and recursion.\nDialogue: 0,0:26:03.86,0:26:05.48,EN,,0,0,0,,Yeah, that's a good point.\nDialogue: 0,0:26:05.48,0:26:13.08,EN,,0,0,0,,For the MAP procedure I wrote, that happens to be a recursive process.\nDialogue: 0,0:26:13.82,0:26:17.06,EN,,0,0,0,,And the reason for that is that when you've done this thing to the rest of the List,\nDialogue: 0,0:26:17.08,0:26:20.96,EN,,0,0,0,,you're waiting for that value so that you can stick it on to the beginning of the List,\nDialogue: 0,0:26:21.73,0:26:24.53,EN,,0,0,0,,whereas for-each doesn't really have any values to wait for.\nDialogue: 0,0:26:24.84,0:26:26.66,EN,,0,0,0,,So that turns out to be an iterative process.\nDialogue: 0,0:26:26.66,0:26:27.72,EN,,0,0,0,,That's not fundamental.\nDialogue: 0,0:26:27.72,0:26:31.80,EN,,0,0,0,,I could have defined MAP so that it's evolved by an iterative process.\nDialogue: 0,0:26:31.82,0:26:32.82,EN,,0,0,0,,I just didn't happen to.\nDialogue: 0,0:26:34.24,0:26:42.90,EN,,0,0,0,,AUDIENCE: If you were to call for each with a List that had embedded Lists, I imagine it would work, right?\nDialogue: 0,0:26:42.90,0:26:48.10,EN,,0,0,0,,It would give you the internal elements of each of those internal Lists?\nDialogue: 0,0:26:48.70,0:26:50.40,EN,,0,0,0,,PROFESSOR: OK, the question is if I call\nDialogue: 0,0:26:50.40,0:26:52.28,EN,,0,0,0,,for-each or map, for that matter\nDialogue: 0,0:26:52.81,0:26:55.28,EN,,0,0,0,,with a List that had Lists in it\nDialogue: 0,0:26:56.69,0:27:00.60,EN,,0,0,0,,although we haven't really looked at that yet--would that work.\nDialogue: 0,0:27:01.02,0:27:06.56,EN,,0,0,0,,The answer is yes in the sense I mean work and no in the sense that you mean work,\nDialogue: 0,0:27:06.86,0:27:10.65,EN,,0,0,0,,because all that-- see if I give you a List,\nDialogue: 0,0:27:12.80,0:27:14.20,EN,,0,0,0,,where hanging off here is,\nDialogue: 0,0:27:16.06,0:27:21.46,EN,,0,0,0,,you know, is something that's not a number, maybe another List or you know, another cons or something,\nDialogue: 0,0:27:21.96,0:27:24.54,EN,,0,0,0,,for-each just says do something to each item in this List.\nDialogue: 0,0:27:24.54,0:27:26.96,EN,,0,0,0,,It goes down successively looking at the cdrs.\nDialogue: 0,0:27:26.96,0:27:27.20,EN,,0,0,0,,AUDIENCE: OK.\nDialogue: 0,0:27:27.20,0:27:31.06,EN,,0,0,0,,PROFESSOR: And as far as it's concerned, the first item in this List is whatever is hanging off here.\nDialogue: 0,0:27:31.06,0:27:31.65,EN,,0,0,0,,AUDIENCE: Mhm.\nDialogue: 0,0:27:31.65,0:27:33.94,EN,,0,0,0,,PROFESSOR: That might or might not be the right thing.\nDialogue: 0,0:27:33.94,0:27:35.57,EN,,0,0,0,,AUDIENCE: So it wouldn't go down into the--\nDialogue: 0,0:27:35.57,0:27:36.91,EN,,0,0,0,,PROFESSOR: Absolutely not.\nDialogue: 0,0:27:36.91,0:27:38.51,EN,,0,0,0,,I could certainly write something else.\nDialogue: 0,0:27:38.51,0:27:42.97,EN,,0,0,0,,There's another, what you're looking for is a common pattern of usage called tree recursion,\nDialogue: 0,0:27:43.01,0:27:47.94,EN,,0,0,0,,where you take a List, and you actually go all the way down to the what's called the leaves of the tree.\nDialogue: 0,0:27:47.94,0:27:51.05,EN,,0,0,0,,And you could write such a thing, but that's not for-each and it's not MAP.\nDialogue: 0,0:27:52.42,0:27:55.05,EN,,0,0,0,,Remember, these things are really being very simple minded.\nDialogue: 0,0:27:55.77,0:27:56.89,EN,,0,0,0,,OK, no more questions?\nDialogue: 0,0:27:57.68,0:27:58.57,EN,,0,0,0,,All right, let's break.\nDialogue: 0,0:27:59.11,0:28:10.99,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:28:11.46,0:28:14.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:28:14.32,0:28:17.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:28:27.38,0:28:34.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:28:34.86,0:28:38.58,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson Escher Example\nDialogue: 0,0:28:41.94,0:28:48.65,EN,,0,0,0,,PROFESSOR: What I'd like to do now is spend the rest of this time talking about one example,\nDialogue: 0,0:28:50.04,0:28:53.92,EN,,0,0,0,,and this example, I think, pretty much summarizes everything that we've done up until now:\nDialogue: 0,0:28:54.74,0:28:56.29,EN,,0,0,0,,all right, and that's List structure\nDialogue: 0,0:28:57.17,0:28:59.48,EN,,0,0,0,,and issues of abstraction,\nDialogue: 0,0:28:59.54,0:29:00.82,EN,,0,0,0,,and representation\nDialogue: 0,0:29:01.60,0:29:04.60,EN,,0,0,0,,and representation and capturing commonality with higher order procedures,\nDialogue: 0,0:29:04.60,0:29:09.80,EN,,0,0,0,,and also is going to introduce something we haven't really talked about a lot yet-- what I said is the major third theme in this course:\nDialogue: 0,0:29:09.85,0:29:13.46,EN,,0,0,0,,what I said is the major third theme in this course:\nDialogue: 0,0:29:13.96,0:29:15.53,EN,,0,0,0,,meta-linguistic abstraction,\nDialogue: 0,0:29:15.54,0:29:21.90,EN,,0,0,0,,which is the idea that one of the ways of tackling complexity in engineering design\nDialogue: 0,0:29:22.86,0:29:25.80,EN,,0,0,0,,is to build a suitable powerful language.\nDialogue: 0,0:29:28.17,0:29:34.74,EN,,0,0,0,,You might recall what I said was pretty much the very most important thing that we're going to tell you in this course is that\nDialogue: 0,0:29:34.74,0:29:41.17,EN,,0,0,0,,when you think about a language, you think about it in terms of what are the primitives;\nDialogue: 0,0:29:42.98,0:29:46.69,EN,,0,0,0,,what are the means of combination--\nDialogue: 0,0:29:49.72,0:29:52.80,EN,,0,0,0,,right, what are the things that allow you to build bigger things;\nDialogue: 0,0:29:53.61,0:29:55.24,EN,,0,0,0,,and then what are the means of abstraction.\nDialogue: 0,0:30:00.97,0:30:05.16,EN,,0,0,0,,How do you take those bigger things that you've built\nDialogue: 0,0:30:05.56,0:30:07.97,EN,,0,0,0,,put black boxes around them\nDialogue: 0,0:30:08.45,0:30:11.71,EN,,0,0,0,,and use them as elements in making something even more complicated?\nDialogue: 0,0:30:13.53,0:30:18.72,EN,,0,0,0,,Now the particular language I'm going to talk about is an example\nDialogue: 0,0:30:18.73,0:30:22.70,EN,,0,0,0,,that was made up by a friend of ours called Peter Henderson.\nDialogue: 0,0:30:28.24,0:30:31.74,EN,,0,0,0,,Peter Henderson is at the University of Stirling in Scotland.\nDialogue: 0,0:30:32.78,0:30:40.98,EN,,0,0,0,,And what this language is about is making figures that sort of look like this.\nDialogue: 0,0:30:41.86,0:30:46.66,EN,,0,0,0,,This is this is a woodcut by Escher called \"Square Limit.\"\nDialogue: 0,0:30:49.33,0:30:57.94,EN,,0,0,0,,You, sort of, see it has this complicated, kind of, recursive, sort of, recursive kind of figure,\nDialogue: 0,0:30:58.84,0:31:01.46,EN,,0,0,0,,where there's this fish pattern in the middle and things sort of\nDialogue: 0,0:31:01.70,0:31:04.56,EN,,0,0,0,,bleed out smaller and smaller in self similar ways.\nDialogue: 0,0:31:08.49,0:31:12.80,EN,,0,0,0,,Anyway, Peter Henderson's language was for describing figures that look like that\nDialogue: 0,0:31:13.37,0:31:18.28,EN,,0,0,0,,and designing new ones that look like that and drawing them on a display screen.\nDialogue: 0,0:31:20.24,0:31:27.48,EN,,0,0,0,,There's another theme that we'll see illustrated by this example,\nDialogue: 0,0:31:28.09,0:31:32.02,EN,,0,0,0,,and that's the issue of what Gerry and I have already mentioned a lot:\nDialogue: 0,0:31:32.02,0:31:36.17,EN,,0,0,0,,that there's no real difference, in some sense, between procedures and data.\nDialogue: 0,0:31:37.26,0:31:42.40,EN,,0,0,0,,And anyway I hope by the end of this morning, if you're not already,\nDialogue: 0,0:31:42.58,0:31:47.60,EN,,0,0,0,,you will be completely confused about what the difference between procedures and data are,\nDialogue: 0,0:31:47.96,0:31:49.58,EN,,0,0,0,,if you're not confused about that already.\nDialogue: 0,0:31:50.80,0:31:55.28,EN,,0,0,0,,Well in any case, let's start describing Peter's language.\nDialogue: 0,0:31:55.28,0:31:57.26,EN,,0,0,0,,I should start by telling you what the primitives are.\nDialogue: 0,0:31:58.29,0:32:00.92,EN,,0,0,0,,This language is very simple because there's only one primitive.\nDialogue: 0,0:32:03.33,0:32:06.30,EN,,0,0,0,,A primitive is not quite what you think it is.\nDialogue: 0,0:32:07.08,0:32:09.18,EN,,0,0,0,,There's only one primitive called a picture,\nDialogue: 0,0:32:09.70,0:32:12.11,EN,,0,0,0,,and a picture is not quite what you think it is.\nDialogue: 0,0:32:12.11,0:32:14.17,EN,,0,0,0,,Here's an example.\nDialogue: 0,0:32:14.17,0:32:15.17,EN,,0,0,0,,This is a picture of George.\nDialogue: 0,0:32:19.01,0:32:20.37,EN,,0,0,0,,The idea is that\nDialogue: 0,0:32:22.33,0:32:24.57,EN,,0,0,0,,a picture in this language is going to be something\nDialogue: 0,0:32:24.89,0:32:31.46,EN,,0,0,0,,that draws a figure scaled to fit a rectangle that you specify.\nDialogue: 0,0:32:33.00,0:32:34.42,EN,,0,0,0,,So here you see emphasis line\nDialogue: 0,0:32:34.42,0:32:37.70,EN,,0,0,0,,is outline of a rectangle, that's not really part of the picture,\nDialogue: 0,0:32:40.49,0:32:47.17,EN,,0,0,0,,but the picture-- you'll give it a rectangle, and it will draw this figure scaled to fit the rectangle.\nDialogue: 0,0:32:47.17,0:32:52.16,EN,,0,0,0,,So for example, there's George, and here, this is also George.\nDialogue: 0,0:32:53.21,0:32:56.65,EN,,0,0,0,,It's the same picture, right, just scaled to fit a different rectangle.\nDialogue: 0,0:32:57.40,0:32:59.28,EN,,0,0,0,,Here's George as a fat kid.\nDialogue: 0,0:33:00.01,0:33:03.44,EN,,0,0,0,,That's the same George.\nDialogue: 0,0:33:03.81,0:33:05.14,EN,,0,0,0,,It's all the same figure.\nDialogue: 0,0:33:05.14,0:33:09.57,EN,,0,0,0,,All of these three things are the same picture in this language.\nDialogue: 0,0:33:09.58,0:33:13.04,EN,,0,0,0,,I'm just giving it different rectangles to scale itself in.\nDialogue: 0,0:33:16.08,0:33:20.65,EN,,0,0,0,,OK, those are the primitives. That is the primitive.\nDialogue: 0,0:33:21.44,0:33:25.25,EN,,0,0,0,,Now let's start talking about the means of combination and the operations.\nDialogue: 0,0:33:25.90,0:33:30.17,EN,,0,0,0,,There is, for example, an operation called Rotate.\nDialogue: 0,0:33:31.09,0:33:33.66,EN,,0,0,0,,And what Rotate does is, if I have a picture,\nDialogue: 0,0:33:35.37,0:33:39.93,EN,,0,0,0,,say a picture that draws an \"A\" in some rectangle that I give it,\nDialogue: 0,0:33:41.84,0:33:45.73,EN,,0,0,0,,the Rotate of that--say the Rotate by 90 degrees would,\nDialogue: 0,0:33:47.02,0:33:50.65,EN,,0,0,0,,if I give it a rectangle, draw the same image,\nDialogue: 0,0:33:50.65,0:33:53.88,EN,,0,0,0,,but again, scaled to fit that rectangle.\nDialogue: 0,0:33:56.11,0:33:58.34,EN,,0,0,0,,So that's Rotate by 90 degrees.\nDialogue: 0,0:33:58.34,0:34:03.20,EN,,0,0,0,,There's another operation called Flip that can flip something, either horizontally or vertically.\nDialogue: 0,0:34:04.77,0:34:06.00,EN,,0,0,0,,All right, so those are, sort of, operations,\nDialogue: 0,0:34:06.01,0:34:10.40,EN,,0,0,0,,or you can think of those as means of combination of one element.\nDialogue: 0,0:34:10.89,0:34:12.42,EN,,0,0,0,,I can put things together.\nDialogue: 0,0:34:13.44,0:34:15.54,EN,,0,0,0,,There's a means of combination called Beside,\nDialogue: 0,0:34:16.46,0:34:24.78,EN,,0,0,0,,and what Beside does: it'll take two pictures, let's say A and B--\nDialogue: 0,0:34:29.02,0:34:33.25,EN,,0,0,0,,and by picture I mean something that's going to draw an image in a specified rectangle--\nDialogue: 0,0:34:34.05,0:34:36.51,EN,,0,0,0,,and what Beside will do--\nDialogue: 0,0:34:37.85,0:34:44.08,EN,,0,0,0,,I have to say, Beside of A and B, the side of two pictures and some number, s.\nDialogue: 0,0:34:45.34,0:34:48.08,EN,,0,0,0,,And s will be a number between zero and one.\nDialogue: 0,0:34:50.51,0:34:52.57,EN,,0,0,0,,And Beside will draw a picture that looks like this.\nDialogue: 0,0:34:52.57,0:34:56.71,EN,,0,0,0,,It will take the rectangle you give it and scale its base by s.\nDialogue: 0,0:34:56.71,0:34:58.71,EN,,0,0,0,,Say s is 0.5.\nDialogue: 0,0:35:00.18,0:35:07.17,EN,,0,0,0,,And then over here it will draw-- it'll put the first picture, and over here it'll put the second picture.\nDialogue: 0,0:35:07.81,0:35:12.65,EN,,0,0,0,,and over here it'll put the second picture.\nDialogue: 0,0:35:13.82,0:35:16.44,EN,,0,0,0,,Or for instance if I gave it a different value of s,\nDialogue: 0,0:35:16.81,0:35:23.02,EN,,0,0,0,,Or for instance if I gave it a different value of s, if I said Beside with a 0.25,\nDialogue: 0,0:35:25.94,0:35:29.09,EN,,0,0,0,,it would do the same thing, except the A would be much skinnier.\nDialogue: 0,0:35:34.05,0:35:36.28,EN,,0,0,0,,So it would draw something like that.\nDialogue: 0,0:35:37.82,0:35:40.29,EN,,0,0,0,,So there's a means of combination Beside,\nDialogue: 0,0:35:40.68,0:35:46.05,EN,,0,0,0,,and similarly there's an Above, which does the same thing except it puts them vertically instead of horizontally.\nDialogue: 0,0:35:47.84,0:35:48.89,EN,,0,0,0,,Well let's look at that.\nDialogue: 0,0:35:50.74,0:35:56.00,EN,,0,0,0,,All right, there's George and his kid brother,\nDialogue: 0,0:35:56.72,0:36:07.05,EN,,0,0,0,,which is, right, constructed by taking George and putting him Beside\nDialogue: 0,0:36:10.36,0:36:14.42,EN,,0,0,0,,The Above, taking the empty picture, and there's a thing called the empty picture,\nDialogue: 0,0:36:14.52,0:36:16.14,EN,,0,0,0,,which does the obvious thing--\nDialogue: 0,0:36:16.14,0:36:19.14,EN,,0,0,0,,putting the empty picture above a copy of George,\nDialogue: 0,0:36:19.14,0:36:21.14,EN,,0,0,0,,and then putting that whole thing Beside George.\nDialogue: 0,0:36:28.96,0:36:30.34,EN,,0,0,0,,Here's something called P which is,\nDialogue: 0,0:36:31.10,0:36:39.04,EN,,0,0,0,,which is, again, George Beside Flipping George,\nDialogue: 0,0:36:40.53,0:36:42.08,EN,,0,0,0,,I think, horizontally in this case,\nDialogue: 0,0:36:42.37,0:36:44.80,EN,,0,0,0,,Rotating the whole result 180 degrees\nDialogue: 0,0:36:45.80,0:36:50.82,EN,,0,0,0,,putting them Beside one another with the basic rectangle divided at 0.5,\nDialogue: 0,0:36:52.56,0:36:53.90,EN,,0,0,0,,right, and I can call that P.\nDialogue: 0,0:36:55.90,0:36:57.88,EN,,0,0,0,,And then I can take P,\nDialogue: 0,0:36:59.21,0:37:04.96,EN,,0,0,0,,And then I can take P, and put it above the Flipped copy of itself, and I can call that Q.\nDialogue: 0,0:37:09.20,0:37:13.26,EN,,0,0,0,,Notice how rapidly that we've built up complexity,\nDialogue: 0,0:37:14.36,0:37:21.05,EN,,0,0,0,,just in, you know, 15 seconds, you've gotten from George to that thing Q. Why is that?\nDialogue: 0,0:37:22.05,0:37:24.55,EN,,0,0,0,,How are how we able to do that so fast?\nDialogue: 0,0:37:25.85,0:37:28.02,EN,,0,0,0,,The answer is the closure property.\nDialogue: 0,0:37:28.69,0:37:32.98,EN,,0,0,0,,See, it's the fact that when I take a picture and put it Beside another picture,\nDialogue: 0,0:37:34.30,0:37:35.29,EN,,0,0,0,,that's then, again, a picture\nDialogue: 0,0:37:35.33,0:37:37.78,EN,,0,0,0,,that I can go and Rotate and Flip or put Above something else.\nDialogue: 0,0:37:39.17,0:37:40.88,EN,,0,0,0,,Right, and when I take that element P,\nDialogue: 0,0:37:40.89,0:37:44.88,EN,,0,0,0,,which is the Beside or the Flip or the Rotate of something, that's, again, a picture.\nDialogue: 0,0:37:45.22,0:37:50.20,EN,,0,0,0,,Right, the world of pictures is closed under those means of combination.\nDialogue: 0,0:37:50.77,0:37:52.24,EN,,0,0,0,,So whenever I have something,\nDialogue: 0,0:37:52.48,0:37:55.17,EN,,0,0,0,,I can turn right around and use that as an element in something else.\nDialogue: 0,0:37:56.33,0:37:58.52,EN,,0,0,0,,So maybe better than List and segments,\nDialogue: 0,0:37:58.54,0:38:03.28,EN,,0,0,0,,that just gives you an image for how fast you can build up complexity, because operations are closed.\nDialogue: 0,0:38:07.48,0:38:12.02,EN,,0,0,0,,OK, well before we go on with building more things,\nDialogue: 0,0:38:12.04,0:38:14.77,EN,,0,0,0,,let's talk about how this language is actually implemented.\nDialogue: 0,0:38:16.91,0:38:21.50,EN,,0,0,0,,The basic element that sits under the table here\nDialogue: 0,0:38:21.93,0:38:24.52,EN,,0,0,0,,is a thing called a rectangle,\nDialogue: 0,0:38:26.09,0:38:28.28,EN,,0,0,0,,and what a rectangle is going to be,\nDialogue: 0,0:38:28.28,0:38:33.68,EN,,0,0,0,,it's a thing that specified by an origin\nDialogue: 0,0:38:36.45,0:38:40.18,EN,,0,0,0,,that's going to be some vector that says where the rectangle starts.\nDialogue: 0,0:38:40.18,0:38:42.29,EN,,0,0,0,,And then there's going to be some other vector\nDialogue: 0,0:38:43.66,0:38:46.33,EN,,0,0,0,,that I'm going to call the horizontal part of the rectangle,\nDialogue: 0,0:38:55.76,0:38:59.25,EN,,0,0,0,,and another vector called the vertical part of the rectangle.\nDialogue: 0,0:39:00.49,0:39:02.68,EN,,0,0,0,,And those three pieces are the elements:\nDialogue: 0,0:39:02.68,0:39:04.51,EN,,0,0,0,,where the lower vertex is,\nDialogue: 0,0:39:04.93,0:39:09.97,EN,,0,0,0,,how you get to the next vertex over here, and how you get to the vertex over there.\nDialogue: 0,0:39:09.97,0:39:12.37,EN,,0,0,0,,The three vectors specify a rectangle.\nDialogue: 0,0:39:16.00,0:39:18.93,EN,,0,0,0,,Now to actually build rectangles, what I'll assume is\nDialogue: 0,0:39:19.77,0:39:22.06,EN,,0,0,0,,that we have a constructor called \"make rectangle,\"\nDialogue: 0,0:39:23.01,0:39:24.26,EN,,0,0,0,,or \"make-rect,\"\nDialogue: 0,0:39:27.56,0:39:35.17,EN,,0,0,0,,and selectors for horiz and vert and origin\nDialogue: 0,0:39:37.58,0:39:39.65,EN,,0,0,0,,that get out the pieces of that rectangle.\nDialogue: 0,0:39:39.65,0:39:42.54,EN,,0,0,0,,And well, you know a lot of ways you can do this now.\nDialogue: 0,0:39:42.54,0:39:47.62,EN,,0,0,0,,You can do it by using pairs in some way or other standard List or not.\nDialogue: 0,0:39:47.62,0:39:51.40,EN,,0,0,0,,But in any case, the implementation of these things, that's George's problem.\nDialogue: 0,0:39:51.40,0:39:53.17,EN,,0,0,0,,It's just a data representation problem.\nDialogue: 0,0:39:53.17,0:39:55.47,EN,,0,0,0,,So let's assume we have these rectangles to work with.\nDialogue: 0,0:39:59.05,0:40:05.08,EN,,0,0,0,,OK. Now the idea of this, remember what's got to happen.\nDialogue: 0,0:40:05.08,0:40:08.22,EN,,0,0,0,,Somehow we have to worry about taking the figure\nDialogue: 0,0:40:09.33,0:40:12.97,EN,,0,0,0,,and scaling it to fit some rectangle that you give it,\nDialogue: 0,0:40:13.60,0:40:16.60,EN,,0,0,0,,that's the basic thing you have to arrange,\nDialogue: 0,0:40:16.60,0:40:18.60,EN,,0,0,0,,that these pictures can do.\nDialogue: 0,0:40:22.22,0:40:23.65,EN,,0,0,0,,How do we think about that?\nDialogue: 0,0:40:23.65,0:40:27.08,EN,,0,0,0,,Well, one way to think about that is that any time I give you a rectangle,\nDialogue: 0,0:40:35.68,0:40:38.68,EN,,0,0,0,,Any time I gave you a rectangle, that defines,\nDialogue: 0,0:40:39.25,0:40:45.77,EN,,0,0,0,,that defines,in some sense, a transformation from the standard square into that rectangle.\nDialogue: 0,0:40:45.77,0:40:46.54,EN,,0,0,0,,Let me say what I mean.\nDialogue: 0,0:40:46.54,0:40:48.53,EN,,0,0,0,,By the standard square, I'll mean something,\nDialogue: 0,0:40:49.04,0:40:59.04,EN,,0,0,0,,which is a square whose coordinates are 0,0, and 1,0, and 0,1 and 1,1.\nDialogue: 0,0:41:01.40,0:41:05.72,EN,,0,0,0,,And there's some sort of the obvious scaling transformation,\nDialogue: 0,0:41:06.12,0:41:10.22,EN,,0,0,0,,which maps this to that and this to that,\nDialogue: 0,0:41:10.24,0:41:12.08,EN,,0,0,0,,and sort of, stretches everything uniformly.\nDialogue: 0,0:41:12.17,0:41:18.25,EN,,0,0,0,,So we take a line segment like this\nDialogue: 0,0:41:19.73,0:41:24.20,EN,,0,0,0,,and end up mapping it to a line segment like that,\nDialogue: 0,0:41:26.20,0:41:32.68,EN,,0,0,0,,so some point (x,y) goes to some other point up there.\nDialogue: 0,0:41:32.68,0:41:39.37,EN,,0,0,0,,And although it's not important, with a little vector algebra, you could write that formula.\nDialogue: 0,0:41:39.37,0:41:43.18,EN,,0,0,0,,The thing that (x,y) goes to, the point that (x,y) goes to is\nDialogue: 0,0:41:43.58,0:41:50.74,EN,,0,0,0,,gotten by taking the origin of the rectangle and then adding that as a vector to--\nDialogue: 0,0:41:51.16,0:41:55.48,EN,,0,0,0,,well, take x, the x coordinate, which is something between zero and one,\nDialogue: 0,0:41:55.98,0:42:01.84,EN,,0,0,0,,multiply that by the horizontal vector of the rectangle;\nDialogue: 0,0:42:07.62,0:42:11.00,EN,,0,0,0,,and take the y coordinate, which is also something between zero and one\nDialogue: 0,0:42:11.38,0:42:16.28,EN,,0,0,0,,and multiply that by the vertical vector of the rectangle.\nDialogue: 0,0:42:16.74,0:42:19.31,EN,,0,0,0,,That's just a little linear algebra.\nDialogue: 0,0:42:19.31,0:42:23.48,EN,,0,0,0,,Anyway, that's the formula, which is the right obvious transformation\nDialogue: 0,0:42:23.69,0:42:28.18,EN,,0,0,0,,that takes things into the unit square, into the interior of that rectangle.\nDialogue: 0,0:42:31.34,0:42:34.02,EN,,0,0,0,,OK well, let's actually look at that as a procedure.\nDialogue: 0,0:42:35.16,0:42:36.29,EN,,0,0,0,,So what we want is\nDialogue: 0,0:42:37.80,0:42:40.82,EN,,0,0,0,,the thing which tells us that particular transformation\nDialogue: 0,0:42:41.01,0:42:42.52,EN,,0,0,0,,that a rectangle defines.\nDialogue: 0,0:42:43.80,0:42:45.22,EN,,0,0,0,,So here's the procedure.\nDialogue: 0,0:42:45.22,0:42:47.22,EN,,0,0,0,,I'll call it coordinate-map.\nDialogue: 0,0:42:47.77,0:42:52.00,EN,,0,0,0,,Coordinate-map is the thing that takes as its argument a rectangle\nDialogue: 0,0:42:53.60,0:42:57.85,EN,,0,0,0,,and returns for you a procedure on points.\nDialogue: 0,0:43:00.45,0:43:06.82,EN,,0,0,0,,Right, so for each rectangle you get a way of transforming a point (x,y) into that rectangle.\nDialogue: 0,0:43:06.82,0:43:08.02,EN,,0,0,0,,And how do you get it?\nDialogue: 0,0:43:08.02,0:43:10.92,EN,,0,0,0,,Well I just--  writing in Lisp what I wrote there on the blackboard--\nDialogue: 0,0:43:10.92,0:43:16.01,EN,,0,0,0,,I add to the origin of the rectangle\nDialogue: 0,0:43:20.22,0:43:25.02,EN,,0,0,0,,the result of adding-- I take the horizontal part of the rectangle;\nDialogue: 0,0:43:25.02,0:43:27.68,EN,,0,0,0,,I scale that by the x coordinate of the point.\nDialogue: 0,0:43:29.65,0:43:32.62,EN,,0,0,0,,I take the vertical vector of the rectangle.\nDialogue: 0,0:43:33.51,0:43:37.14,EN,,0,0,0,,I scale that by the y coordinate of the point,\nDialogue: 0,0:43:37.14,0:43:39.14,EN,,0,0,0,,and then add all those three things up.\nDialogue: 0,0:43:40.13,0:43:41.34,EN,,0,0,0,,That's the procedure.\nDialogue: 0,0:43:41.34,0:43:44.54,EN,,0,0,0,,That is the procedure that I'm going to apply to a point.\nDialogue: 0,0:43:46.54,0:43:52.17,EN,,0,0,0,,And this whole thing is generated for each rectangle.\nDialogue: 0,0:43:52.17,0:43:57.25,EN,,0,0,0,,So any rectangle defines a Coordinate-MAP, which is a procedure on points.\nDialogue: 0,0:44:06.66,0:44:10.42,EN,,0,0,0,,All right, so for example, George here,\nDialogue: 0,0:44:11.36,0:44:16.34,EN,,0,0,0,,my original George, might have been something that I specified by segments in the unit square,\nDialogue: 0,0:44:19.50,0:44:21.96,EN,,0,0,0,,and then for each rectangle I give this thing,\nDialogue: 0,0:44:24.14,0:44:28.17,EN,,0,0,0,,I'm going to draw those segments inside that rectangle.\nDialogue: 0,0:44:28.17,0:44:29.88,EN,,0,0,0,,How actually do I do that?\nDialogue: 0,0:44:30.68,0:44:36.94,EN,,0,0,0,,Well I take each segment in my original reference George that was specified,\nDialogue: 0,0:44:38.64,0:44:40.58,EN,,0,0,0,,and to each of the end points of those segments,\nDialogue: 0,0:44:40.88,0:44:44.45,EN,,0,0,0,,I applied the COORDINATE-MAP of the particular rectangle I want to draw it in.\nDialogue: 0,0:44:44.45,0:44:46.06,EN,,0,0,0,,So for example, this lower rectangle,\nDialogue: 0,0:44:46.66,0:44:50.88,EN,,0,0,0,,this George as a fat kid rectangle, has its COORDINATE-MAP.\nDialogue: 0,0:44:51.25,0:44:53.69,EN,,0,0,0,,And if I want to draw this image,\nDialogue: 0,0:44:55.38,0:44:57.92,EN,,0,0,0,,And if I want to draw this image, what I do is for each segment here, say for this segment,\nDialogue: 0,0:44:59.29,0:45:05.34,EN,,0,0,0,,I transformed that point by the coordinate MAP, transform that point by the coordinate MAP.\nDialogue: 0,0:45:05.34,0:45:07.09,EN,,0,0,0,,That will give me this point and that point\nDialogue: 0,0:45:07.38,0:45:08.94,EN,,0,0,0,,and draw the segment between them.\nDialogue: 0,0:45:09.71,0:45:11.52,EN,,0,0,0,,Right, that's the idea.\nDialogue: 0,0:45:12.66,0:45:14.78,EN,,0,0,0,,Right, and if I give it a different rectangle like this one,\nDialogue: 0,0:45:14.80,0:45:15.76,EN,,0,0,0,,that's a different coordinate-MAP,\nDialogue: 0,0:45:15.79,0:45:17.84,EN,,0,0,0,,so I get a different image of those line segments.\nDialogue: 0,0:45:19.28,0:45:22.14,EN,,0,0,0,,Well how do we actually get a picture to start with?\nDialogue: 0,0:45:22.14,0:45:26.52,EN,,0,0,0,,I can build a picture to start with out of a List of line segments initially.\nDialogue: 0,0:45:27.61,0:45:32.20,EN,,0,0,0,,Here's a procedure that builds what I'll call a primitive picture,\nDialogue: 0,0:45:33.48,0:45:37.17,EN,,0,0,0,,meaning one I, sort of, got that didn't come out of Beside or Rotate or something.\nDialogue: 0,0:45:37.52,0:45:39.60,EN,,0,0,0,,It starts with a List of line segments,\nDialogue: 0,0:45:42.94,0:45:44.04,EN,,0,0,0,,And now it does what I said.\nDialogue: 0,0:45:44.04,0:45:45.58,EN,,0,0,0,,What's a picture have to be?\nDialogue: 0,0:45:45.58,0:45:49.44,EN,,0,0,0,,First of all it's a procedure that's defined on rectangles.\nDialogue: 0,0:45:51.70,0:45:53.00,EN,,0,0,0,,What does it do?\nDialogue: 0,0:45:53.00,0:45:56.56,EN,,0,0,0,,It says for each-- this is going to be a List of line segments--\nDialogue: 0,0:45:57.66,0:46:03.38,EN,,0,0,0,,for each segment, for each s, which is a segment in this List of segments,\nDialogue: 0,0:46:05.89,0:46:07.30,EN,,0,0,0,,well it draws a line.\nDialogue: 0,0:46:07.30,0:46:08.82,EN,,0,0,0,,What line does it draw?\nDialogue: 0,0:46:10.60,0:46:12.84,EN,,0,0,0,,It gets the start point of that segment,\nDialogue: 0,0:46:15.22,0:46:17.94,EN,,0,0,0,,transforms that by the coordinate MAP of the rectangle.\nDialogue: 0,0:46:19.54,0:46:21.76,EN,,0,0,0,,That's the first new point it wants to do.\nDialogue: 0,0:46:21.76,0:46:26.32,EN,,0,0,0,,Then it takes the endpoint of the segment, transforms that by the coordinate MAP of the rectangle,\nDialogue: 0,0:46:26.69,0:46:27.92,EN,,0,0,0,,and then draws a line between.\nDialogue: 0,0:46:27.92,0:46:30.84,EN,,0,0,0,,Let's assume drawline is some primitive that's built into the system\nDialogue: 0,0:46:31.09,0:46:33.22,EN,,0,0,0,,that actually draws a line on the display.\nDialogue: 0,0:46:33.96,0:46:37.10,EN,,0,0,0,,All right, so it transforms the endpoints by the coordinate MAP of the rectangle,\nDialogue: 0,0:46:37.13,0:46:38.20,EN,,0,0,0,,draws a line between them,\nDialogue: 0,0:46:39.61,0:46:44.12,EN,,0,0,0,,does that for each s in this List of segments.\nDialogue: 0,0:46:45.96,0:46:51.40,EN,,0,0,0,,And now remember again, a picture is a procedure that takes a rectangle as argument.\nDialogue: 0,0:46:51.40,0:46:55.65,EN,,0,0,0,,So when you hand it a rectangle, this is what it does: draws those lines.\nDialogue: 0,0:46:57.17,0:47:01.10,EN,,0,0,0,,All right, so there's-- how would I actually use this thing?\nDialogue: 0,0:47:01.22,0:47:04.08,EN,,0,0,0,,Let's make it a little bit more concrete.\nDialogue: 0,0:47:05.60,0:47:24.22,EN,,0,0,0,,Right, I would say for instance, define R to be make-rectangle of some stuff,\nDialogue: 0,0:47:24.50,0:47:28.66,EN,,0,0,0,,and I'd have to specify some vectors here using make-vector.\nDialogue: 0,0:47:29.84,0:47:46.18,EN,,0,0,0,,And then I could say, define say, G to be make-picture, and then some stuff.\nDialogue: 0,0:47:46.68,0:47:55.28,EN,,0,0,0,,And what I'd have to specify here is a List of line segments, right, using make segment.\nDialogue: 0,0:47:55.28,0:47:58.70,EN,,0,0,0,,Make-segment might be made out of vectors, and vectors might be made out of points.\nDialogue: 0,0:47:59.50,0:48:04.60,EN,,0,0,0,,And then if I actually wanted to see the image of G inside a rectangle,\nDialogue: 0,0:48:04.65,0:48:11.72,EN,,0,0,0,,well a picture is a procedure that takes a rectangle as argument.\nDialogue: 0,0:48:12.06,0:48:16.37,EN,,0,0,0,,So if I then called G with an input of R,\nDialogue: 0,0:48:17.96,0:48:23.25,EN,,0,0,0,,that would cause whatever image G is worrying about to be drawn inside the rectangle R.\nDialogue: 0,0:48:23.62,0:48:25.62,EN,,0,0,0,,Right, so that's how you'd use that.\nDialogue: 0,0:48:26.86,0:48:36.29,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:48:36.29,0:48:39.78,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:48:39.82,0:48:43.54,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:48:51.28,0:48:55.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:48:55.50,0:48:58.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:48:59.34,0:49:03.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson Escher Example\nDialogue: 0,0:49:07.72,0:49:12.48,EN,,0,0,0,,PROFESSOR: Well why is it that I say this example is nice?\nDialogue: 0,0:49:12.48,0:49:13.74,EN,,0,0,0,,You probably don't think it's nice.\nDialogue: 0,0:49:13.74,0:49:15.42,EN,,0,0,0,,You probably think it's more weird than nice.\nDialogue: 0,0:49:15.42,0:49:20.92,EN,,0,0,0,,Right, representing these pictures as procedures, which do complicated things with rectangles.\nDialogue: 0,0:49:20.92,0:49:22.72,EN,,0,0,0,,So why is it nice?\nDialogue: 0,0:49:25.36,0:49:26.69,EN,,0,0,0,,The reason it's nice\nDialogue: 0,0:49:27.22,0:49:30.40,EN,,0,0,0,,is that once you've implemented the primitives in this way,\nDialogue: 0,0:49:30.97,0:49:35.20,EN,,0,0,0,,the means of combination just fall out by implementing procedures.\nDialogue: 0,0:49:35.98,0:49:37.48,EN,,0,0,0,,Let me show you what I mean.\nDialogue: 0,0:49:37.48,0:49:39.02,EN,,0,0,0,,Suppose we want to implement Beside.\nDialogue: 0,0:49:41.56,0:49:47.36,EN,,0,0,0,,So I'd like to--  suppose I've got a picture. Let's call it P1.\nDialogue: 0,0:49:47.36,0:49:50.62,EN,,0,0,0,,P1 is going to be-- and now remember what a picture really is.\nDialogue: 0,0:49:50.62,0:49:54.82,EN,,0,0,0,,It's a thing that if you hand it some rectangle,\nDialogue: 0,0:49:56.52,0:50:01.46,EN,,0,0,0,,it will cause an image to be drawn in whatever rectangle you hand it.\nDialogue: 0,0:50:03.46,0:50:09.26,EN,,0,0,0,,And suppose P2 two is some other picture, and you hand that a rectangle.\nDialogue: 0,0:50:09.74,0:50:12.44,EN,,0,0,0,,And whatever rectangle you hand it, it draws some picture.\nDialogue: 0,0:50:14.84,0:50:26.60,EN,,0,0,0,,And now if I'd like to implement Beside of P1 and P2 with a scale factor A,\nDialogue: 0,0:50:27.04,0:50:28.38,EN,,0,0,0,,well what does that have to be?\nDialogue: 0,0:50:28.38,0:50:29.34,EN,,0,0,0,,That's gotta be a picture.\nDialogue: 0,0:50:29.92,0:50:33.88,EN,,0,0,0,,It's gotta be a thing that you handed a rectangle and draw something in that rectangle.\nDialogue: 0,0:50:34.77,0:50:37.18,EN,,0,0,0,,So if hand Beside this rectangle--\nDialogue: 0,0:50:38.58,0:50:40.12,EN,,0,0,0,,let's hand it a rectangle.\nDialogue: 0,0:50:41.50,0:50:42.74,EN,,0,0,0,,Well what's it going to do?\nDialogue: 0,0:50:42.76,0:50:46.36,EN,,0,0,0,,It's going to take this rectangle and split it into two\nDialogue: 0,0:50:49.29,0:50:51.57,EN,,0,0,0,,at a ratio of A and one minus A.\nDialogue: 0,0:50:52.65,0:50:55.12,EN,,0,0,0,,And it will say, oh sure, now I've got two rectangles.\nDialogue: 0,0:51:02.34,0:51:06.54,EN,,0,0,0,,And now it goes off to P1 and says P1, well draw yourself in this rectangle,\nDialogue: 0,0:51:07.36,0:51:11.64,EN,,0,0,0,,and goes off to P2, and says, P2, fine, draw yourself in this rectangle.\nDialogue: 0,0:51:13.28,0:51:16.88,EN,,0,0,0,,The only computation it has to do is figure out what these rectangles are.\nDialogue: 0,0:51:17.36,0:51:23.97,EN,,0,0,0,,Remember a rectangle is specified by an origin and a horizontal vector and a vertical vector.\nDialogue: 0,0:51:23.98,0:51:25.94,EN,,0,0,0,,so it's got to figure out what these things are.\nDialogue: 0,0:51:27.37,0:51:32.29,EN,,0,0,0,,So for this first rectangle, the origin turns out to be the origin of the original rectangle,\nDialogue: 0,0:51:33.64,0:51:37.80,EN,,0,0,0,,and the vertical vector is the same as the vertical vector of the original rectangle.\nDialogue: 0,0:51:38.89,0:51:46.60,EN,,0,0,0,,The horizontal vector is the horizontal vector of the original rectangle scaled by A.\nDialogue: 0,0:51:47.49,0:51:48.90,EN,,0,0,0,,And that's the first rectangle.\nDialogue: 0,0:51:49.46,0:51:52.69,EN,,0,0,0,,The second rectangle, the origin\nDialogue: 0,0:51:54.06,0:51:59.65,EN,,0,0,0,,The second rectangle, the origin is the original origin plus that horizontal vector scaled by A.\nDialogue: 0,0:52:01.20,0:52:03.40,EN,,0,0,0,,The horizontal vector of the second rectangle is\nDialogue: 0,0:52:03.77,0:52:06.04,EN,,0,0,0,,the rest of the horizontal vector of the first one,\nDialogue: 0,0:52:06.34,0:52:11.66,EN,,0,0,0,,which is 1 minus A times the original H,\nDialogue: 0,0:52:12.05,0:52:13.77,EN,,0,0,0,,and the vertical vector is still v.\nDialogue: 0,0:52:15.48,0:52:17.98,EN,,0,0,0,,But basically it goes and constructs these two rectangles,\nDialogue: 0,0:52:18.00,0:52:20.57,EN,,0,0,0,,and the important point is having constructed the rectangles,\nDialogue: 0,0:52:20.93,0:52:24.58,EN,,0,0,0,,it says OK, p1, you draw yourself in there, and p2, you draw yourself in there,\nDialogue: 0,0:52:24.62,0:52:26.18,EN,,0,0,0,,and that's all Beside has to do.\nDialogue: 0,0:52:27.80,0:52:29.30,EN,,0,0,0,,All right, let's look at that piece of code.\nDialogue: 0,0:52:34.33,0:52:35.13,EN,,0,0,0,,Beside\nDialogue: 0,0:52:39.64,0:52:46.44,EN,,0,0,0,,Beside of a picture and another picture with some scaling ratio\nDialogue: 0,0:52:47.84,0:52:53.64,EN,,0,0,0,,is first of all, since it's a picture, a procedure that's going to take a rectangle as argument.\nDialogue: 0,0:52:55.49,0:52:56.56,EN,,0,0,0,,What's it going to do?\nDialogue: 0,0:52:56.76,0:53:02.32,EN,,0,0,0,,It says, p1 draw yourself in some rectangle and p2 draw yourself in some other rectangle.\nDialogue: 0,0:53:03.21,0:53:04.46,EN,,0,0,0,,And now what are those rectangles?\nDialogue: 0,0:53:04.46,0:53:05.48,EN,,0,0,0,,Well here's the computation.\nDialogue: 0,0:53:05.48,0:53:06.54,EN,,0,0,0,,It makes a rectangle,\nDialogue: 0,0:53:07.52,0:53:10.40,EN,,0,0,0,,and this is the algebra I just did on the board: the origin, something;\nDialogue: 0,0:53:10.40,0:53:11.84,EN,,0,0,0,,the horizontal vector, something;\nDialogue: 0,0:53:11.84,0:53:13.44,EN,,0,0,0,,and the vertical vector, something.\nDialogue: 0,0:53:13.97,0:53:14.81,EN,,0,0,0,,For p2\nDialogue: 0,0:53:15.50,0:53:19.78,EN,,0,0,0,,And for p2, the rectangle it wants has some other origin and horizontal vector and vertical vector.\nDialogue: 0,0:53:19.78,0:53:20.70,EN,,0,0,0,,But the important point\nDialogue: 0,0:53:21.21,0:53:27.18,EN,,0,0,0,,is that all it's saying is, p1, go do your thing in one rectangle, and p2, go do your thing in another rectangle.\nDialogue: 0,0:53:27.74,0:53:29.42,EN,,0,0,0,,That's all the Beside has to do.\nDialogue: 0,0:53:30.84,0:53:35.62,EN,,0,0,0,,OK, similarly Rotate--\nDialogue: 0,0:53:36.96,0:53:42.00,EN,,0,0,0,,see if I have this picture A,\nDialogue: 0,0:53:42.97,0:53:46.12,EN,,0,0,0,,and I want to look at say rotating A by 90 degrees,\nDialogue: 0,0:53:46.37,0:53:51.92,EN,,0,0,0,,what that should mean is, well take this rectangle,\nDialogue: 0,0:53:53.94,0:53:58.44,EN,,0,0,0,,which is origin and horizontal vector and vertical vector,\nDialogue: 0,0:53:58.78,0:54:03.18,EN,,0,0,0,,and now pretend that it's really the rectangle that looks like this,\nDialogue: 0,0:54:03.74,0:54:09.12,EN,,0,0,0,,which has an origin and a horizontal vector up here, and a vertical vector there,\nDialogue: 0,0:54:09.60,0:54:12.46,EN,,0,0,0,,and now draw yourself with respect to that rectangle.\nDialogue: 0,0:54:13.26,0:54:15.04,EN,,0,0,0,,Let me show you that as a procedure.\nDialogue: 0,0:54:17.02,0:54:19.85,EN,,0,0,0,,All right, so we'll Rotate 90 of the picture,\nDialogue: 0,0:54:20.61,0:54:22.96,EN,,0,0,0,,because again, a procedure for rectangle,\nDialogue: 0,0:54:23.25,0:54:26.12,EN,,0,0,0,,which says, OK picture, draw yourself in some rectangle;\nDialogue: 0,0:54:27.21,0:54:30.66,EN,,0,0,0,,and then this algebra is the transformation on the rectangle.\nDialogue: 0,0:54:30.66,0:54:33.84,EN,,0,0,0,,It's the one which makes it look like the rectangle is sideways,\nDialogue: 0,0:54:33.86,0:54:36.52,EN,,0,0,0,,the origin is someplace else and the vertical vector is someplace else,\nDialogue: 0,0:54:37.13,0:54:39.74,EN,,0,0,0,,and the horizontal vector is someplace else, and vertical vector is someplace else.\nDialogue: 0,0:54:46.76,0:54:49.90,EN,,0,0,0,,OK, again notice, the crucial thing that's going on here\nDialogue: 0,0:54:50.53,0:55:00.97,EN,,0,0,0,,is you're using the representation of pictures as procedures to automatically get the closure property,\nDialogue: 0,0:55:01.74,0:55:05.22,EN,,0,0,0,,because what happens is, Beside just has this thing p1.\nDialogue: 0,0:55:05.22,0:55:09.40,EN,,0,0,0,,Beside doesn't care if that's a primitive picture or it's line segments\nDialogue: 0,0:55:09.61,0:55:12.69,EN,,0,0,0,,if p1 is, itself, the result of doing Aboves or Besides or Rotates.\nDialogue: 0,0:55:12.72,0:55:16.08,EN,,0,0,0,,All Beside has to know about, say, p1\nDialogue: 0,0:55:16.29,0:55:19.73,EN,,0,0,0,,p1 is that if you hand p1 a rectangle, it will cause something to be drawn.\nDialogue: 0,0:55:21.04,0:55:25.98,EN,,0,0,0,,And above that level, Beside just doesn't-- it's none of its business how p1 accomplishes that drawing.\nDialogue: 0,0:55:27.73,0:55:32.25,EN,,0,0,0,,All right, so you're using the procedural representation to ensure this closure.\nDialogue: 0,0:55:35.64,0:55:40.81,EN,,0,0,0,,So implementing pictures as procedures makes these means of combination,\nDialogue: 0,0:55:41.18,0:55:43.93,EN,,0,0,0,,both pretty simple and also, I think, elegant.\nDialogue: 0,0:55:45.92,0:55:48.22,EN,,0,0,0,,But that's not the real punchline.\nDialogue: 0,0:55:49.28,0:55:53.52,EN,,0,0,0,,The real punchline comes when you look at the means of abstraction in this language.\nDialogue: 0,0:55:54.70,0:55:56.24,EN,,0,0,0,,Because what have we done?\nDialogue: 0,0:55:56.24,0:56:03.72,EN,,0,0,0,,We've implemented the means of combination themselves as procedures.\nDialogue: 0,0:56:05.85,0:56:09.38,EN,,0,0,0,,And what that means is that when we go to abstract in this language,\nDialogue: 0,0:56:10.17,0:56:15.69,EN,,0,0,0,,everything that Lisp supplies us for manipulating procedures\nDialogue: 0,0:56:16.33,0:56:21.45,EN,,0,0,0,,automatically available to do things in this picture language.\nDialogue: 0,0:56:21.92,0:56:29.74,EN,,0,0,0,,The technical term I want to say is not only is this language implemented in Lisp, obviously it is,\nDialogue: 0,0:56:29.76,0:56:32.58,EN,,0,0,0,,but the language is nicely embedded in Lisp.\nDialogue: 0,0:56:37.64,0:56:42.08,EN,,0,0,0,,What I mean is by embedding the language in this way,\nDialogue: 0,0:56:42.90,0:56:48.86,EN,,0,0,0,,all the power of Lisp is automatically available as an extension to whatever you want to do.\nDialogue: 0,0:56:50.06,0:56:51.68,EN,,0,0,0,,And what do I mean by that?\nDialogue: 0,0:56:51.97,0:57:02.94,EN,,0,0,0,,Example: say, suppose I want to make a thing that takes four pictures A, B, C and D,\nDialogue: 0,0:57:03.76,0:57:07.06,EN,,0,0,0,,and makes a configuration that looks like this.\nDialogue: 0,0:57:12.50,0:57:16.96,EN,,0,0,0,,Well you might call that, you know, four pictures or something, four-pict configuration.\nDialogue: 0,0:57:16.96,0:57:17.70,EN,,0,0,0,,How do I do that?\nDialogue: 0,0:57:17.70,0:57:18.68,EN,,0,0,0,,Well I can obviously do that.\nDialogue: 0,0:57:18.68,0:57:23.33,EN,,0,0,0,,I just write a procedure that takes B above D\nDialogue: 0,0:57:24.13,0:57:25.85,EN,,0,0,0,,and A above C\nDialogue: 0,0:57:26.09,0:57:27.70,EN,,0,0,0,,and puts those things beside each other.\nDialogue: 0,0:57:28.24,0:57:31.82,EN,,0,0,0,,So I automatically have Lisp's ability to do procedure composition.\nDialogue: 0,0:57:32.92,0:57:35.82,EN,,0,0,0,,And I didn't have to make that specifically in the picture language.\nDialogue: 0,0:57:35.82,0:57:39.92,EN,,0,0,0,,It's automatic from the fact that the means of combination are themselves procedures.\nDialogue: 0,0:57:40.96,0:57:44.18,EN,,0,0,0,,Or suppose I wanted to do something a little bit more complicated.\nDialogue: 0,0:57:44.18,0:57:46.50,EN,,0,0,0,,I wanted to put in a parameter so that for each of these,\nDialogue: 0,0:57:46.52,0:57:50.08,EN,,0,0,0,,I could independently specify a rotation by 90 degrees.\nDialogue: 0,0:57:50.41,0:57:52.64,EN,,0,0,0,,That's just putting a parameter in the procedure.\nDialogue: 0,0:57:53.17,0:57:54.56,EN,,0,0,0,,It's automatically there.\nDialogue: 0,0:57:54.80,0:57:57.84,EN,,0,0,0,,Right, it automatically comes from the embedding.\nDialogue: 0,0:57:58.16,0:58:05.36,EN,,0,0,0,,Or even more, suppose I wanted to, you know, use recursion.\nDialogue: 0,0:58:06.16,0:58:10.78,EN,,0,0,0,,Let's look at a recursive means of combination on pictures.\nDialogue: 0,0:58:10.78,0:58:14.64,EN,,0,0,0,,I could say define-- let's see if you can figure out what this one is--\nDialogue: 0,0:58:14.69,0:58:18.97,EN,,0,0,0,,suppose I say define what it means to right-push a picture,\nDialogue: 0,0:58:22.84,0:58:29.80,EN,,0,0,0,,right-push a picture and some integer N and some scale factor A.\nDialogue: 0,0:58:31.46,0:58:41.22,EN,,0,0,0,,I'll define this to say if N equals 0, then the answer is the picture.\nDialogue: 0,0:58:42.20,0:58:54.02,EN,,0,0,0,,Otherwise I'm going to put-- oops, name change: P.\nDialogue: 0,0:58:55.88,0:59:00.21,EN,,0,0,0,,Otherwise, I'm going to take P and put it beside\nDialogue: 0,0:59:00.92,0:59:18.30,EN,,0,0,0,,the results of recursively right-pushing P with N minus 1 and A and use a scale factor of A. OK,\nDialogue: 0,0:59:24.72,0:59:31.12,EN,,0,0,0,,so if N 0 , it's P. Otherwise I put P with a scale factor of A--\nDialogue: 0,0:59:31.12,0:59:32.80,EN,,0,0,0,,I'm sorry I didn't align this right--\nDialogue: 0,0:59:33.66,0:59:38.50,EN,,0,0,0,,recursively beside the result of right-pushing P, N minus 1 times with a scale factor of A.\nDialogue: 0,0:59:38.50,0:59:42.00,EN,,0,0,0,,There's a recursive means of combination.\nDialogue: 0,0:59:43.78,0:59:44.76,EN,,0,0,0,,What's that look like?\nDialogue: 0,0:59:44.76,0:59:45.90,EN,,0,0,0,,Well, here's what it looks like.\nDialogue: 0,0:59:46.04,0:59:56.04,EN,,0,0,0,,There's George right-pushed against himself twice with a scale factor of 0.75.\nDialogue: 0,0:59:59.26,1:00:00.72,EN,,0,0,0,,Where'd that come from?\nDialogue: 0,1:00:00.72,1:00:02.34,EN,,0,0,0,,How did I get all this fancy recursion?\nDialogue: 0,1:00:02.34,1:00:05.24,EN,,0,0,0,,And the answer is just automatic, absolutely automatic.\nDialogue: 0,1:00:05.24,1:00:09.80,EN,,0,0,0,,Since these are procedures, the embedding says, well sure, I can define recursive procedures.\nDialogue: 0,1:00:10.36,1:00:11.68,EN,,0,0,0,,I didn't have to arrange that.\nDialogue: 0,1:00:13.56,1:00:16.42,EN,,0,0,0,,And of course, we can do more complicated things of the same sort.\nDialogue: 0,1:00:16.42,1:00:18.21,EN,,0,0,0,,I could make something that does an up-push.\nDialogue: 0,1:00:18.42,1:00:22.60,EN,,0,0,0,,Right, that sort of goes like this, by recursively putting something above.\nDialogue: 0,1:00:22.60,1:00:26.54,EN,,0,0,0,,Or I could make something that, sort of, was this scheme.\nDialogue: 0,1:00:26.56,1:00:28.85,EN,,0,0,0,,I might start out with a picture\nDialogue: 0,1:00:29.78,1:00:37.16,EN,,0,0,0,,and then, sort of, recursively both push it aside and above\nDialogue: 0,1:00:37.57,1:00:38.92,EN,,0,0,0,,and that might put something there.\nDialogue: 0,1:00:39.52,1:00:41.82,EN,,0,0,0,,And then up here I put the same recursive thing,\nDialogue: 0,1:00:42.36,1:00:44.20,EN,,0,0,0,,and I might end up with something like this.\nDialogue: 0,1:00:45.40,1:00:52.50,EN,,0,0,0,,Right, so there's a procedure that's a little bit more complicated than right-push but not much.\nDialogue: 0,1:00:53.64,1:00:58.14,EN,,0,0,0,,I just do an Above and a Beside, rather than just a Beside.\nDialogue: 0,1:01:01.12,1:01:06.78,EN,,0,0,0,,Now if I take that and apply that with the idea of putting four pictures together,\nDialogue: 0,1:01:07.53,1:01:08.65,EN,,0,0,0,,which I can surely do;\nDialogue: 0,1:01:09.01,1:01:14.17,EN,,0,0,0,,and I go and I apply that to Q, which we defined before, right,\nDialogue: 0,1:01:15.97,1:01:18.73,EN,,0,0,0,,what I end up with this is this thing,\nDialogue: 0,1:01:20.14,1:01:25.26,EN,,0,0,0,,which is, sort of, the square limit of Q, done twice.\nDialogue: 0,1:01:28.18,1:01:32.25,EN,,0,0,0,,Right, and then we can compare that with Escher's \"Square Limit.\"\nDialogue: 0,1:01:32.88,1:01:34.53,EN,,0,0,0,,And you see, it's sort of the same idea.\nDialogue: 0,1:01:34.74,1:01:36.94,EN,,0,0,0,,Escher's is, of course, much, much prettier.\nDialogue: 0,1:01:36.94,1:01:44.04,EN,,0,0,0,,If we go back and look at George, right, if we go look at George here--\nDialogue: 0,1:01:44.38,1:01:47.37,EN,,0,0,0,,see, I started with a fairly arbitrary design\nDialogue: 0,1:01:47.42,1:01:49.26,EN,,0,0,0,,this picture of George and did things with it.\nDialogue: 0,1:01:51.22,1:01:53.14,EN,,0,0,0,,Right, whereas if we go look at the Escher picture, right,\nDialogue: 0,1:01:54.08,1:01:56.14,EN,,0,0,0,,the Escher picture is not an arbitrary design.\nDialogue: 0,1:01:56.14,1:01:57.66,EN,,0,0,0,,It's this very, very clever thing,\nDialogue: 0,1:01:57.89,1:02:00.20,EN,,0,0,0,,so that when you take this fish body\nDialogue: 0,1:02:01.82,1:02:04.97,EN,,0,0,0,,and Rotate it and shrink it down, it bleeds into the next one really nicely.\nDialogue: 0,1:02:07.40,1:02:11.48,EN,,0,0,0,,And of course with George, I didn't really do anything like that.\nDialogue: 0,1:02:12.12,1:02:13.90,EN,,0,0,0,,So if we look at George,\nDialogue: 0,1:02:15.41,1:02:18.64,EN,,0,0,0,,right, there's a little bit of match up, but not very nice, and it's pretty arbitrary.\nDialogue: 0,1:02:18.64,1:02:21.53,EN,,0,0,0,,One very nice project, by the way,\nDialogue: 0,1:02:22.30,1:02:27.54,EN,,0,0,0,,would be to write a procedure that could take some basic figure like this George thing\nDialogue: 0,1:02:27.86,1:02:29.62,EN,,0,0,0,,and start moving the ends of the lines around,\nDialogue: 0,1:02:29.86,1:02:31.20,EN,,0,0,0,,so you got a really nice one\nDialogue: 0,1:02:32.13,1:02:34.06,EN,,0,0,0,,when you went and did that \"Square Limit\" process.\nDialogue: 0,1:02:34.68,1:02:36.30,EN,,0,0,0,,That'd be a really nice thing to think about.\nDialogue: 0,1:02:38.08,1:02:39.72,EN,,0,0,0,,Well so, we can combine things.\nDialogue: 0,1:02:39.72,1:02:41.04,EN,,0,0,0,,We can recursive procedures.\nDialogue: 0,1:02:41.04,1:02:43.48,EN,,0,0,0,,We can do all kinds of things, and that's all automatic.\nDialogue: 0,1:02:44.60,1:02:48.52,EN,,0,0,0,,Right, the important point, the difference between merely implementing something in a language\nDialogue: 0,1:02:48.69,1:02:50.44,EN,,0,0,0,,and embedding something in the language,\nDialogue: 0,1:02:50.44,1:02:53.72,EN,,0,0,0,,so that you don't lose the original power of the language, and what Lisp is great at,\nDialogue: 0,1:02:54.76,1:02:57.62,EN,,0,0,0,,see Lisp is a lousy language for doing any particular problem.\nDialogue: 0,1:02:57.62,1:03:02.10,EN,,0,0,0,,What it's good for is figuring out the right language that you want and embedding that in Lisp.\nDialogue: 0,1:03:02.10,1:03:05.44,EN,,0,0,0,,That's the real power of this approach to design.\nDialogue: 0,1:03:05.69,1:03:06.82,EN,,0,0,0,,Of course, we can go further.\nDialogue: 0,1:03:06.82,1:03:08.81,EN,,0,0,0,,See, you saw the other thing that we can do in Lisp\nDialogue: 0,1:03:09.21,1:03:17.52,EN,,0,0,0,,is capture general methods of doing things as higher order procedures.\nDialogue: 0,1:03:19.09,1:03:22.57,EN,,0,0,0,,And you probably just from me drawing it got the idea that right-push\nDialogue: 0,1:03:23.78,1:03:26.61,EN,,0,0,0,,and the analogous thing where you push something up and up and up and up\nDialogue: 0,1:03:26.93,1:03:33.82,EN,,0,0,0,,and this corner push thing are all generalizations of a common kind of idea.\nDialogue: 0,1:03:34.72,1:03:37.20,EN,,0,0,0,,So just to illustrate and give you practice in looking at a\nDialogue: 0,1:03:37.98,1:03:40.65,EN,,0,0,0,,at a fairly convoluted use of higher order procedures,\nDialogue: 0,1:03:41.12,1:03:47.24,EN,,0,0,0,,let me show you the general idea of pushing some means of combination to recursively repeat it.\nDialogue: 0,1:03:48.30,1:03:50.70,EN,,0,0,0,,So here's a good one to puzzle out.\nDialogue: 0,1:03:51.22,1:04:00.70,EN,,0,0,0,,We'll define it what it means to push using a means of combination.\nDialogue: 0,1:04:01.49,1:04:04.88,EN,,0,0,0,,Comb is going to be something like the Beside or Above.\nDialogue: 0,1:04:06.18,1:04:07.06,EN,,0,0,0,,Well what's that going to be.\nDialogue: 0,1:04:07.06,1:04:12.06,EN,,0,0,0,,That's going to be a procedure, remember what Beside actually was, right.\nDialogue: 0,1:04:13.22,1:04:15.18,EN,,0,0,0,,It took a picture,\nDialogue: 0,1:04:15.96,1:04:18.08,EN,,0,0,0,,took two pictures and a scale factor.\nDialogue: 0,1:04:18.62,1:04:24.28,EN,,0,0,0,,Using that I produced something that took a level number and a picture and a scale factor,\nDialogue: 0,1:04:24.28,1:04:25.45,EN,,0,0,0,,that I called right-push.\nDialogue: 0,1:04:26.16,1:04:33.66,EN,,0,0,0,,So this is going to be something that takes a picture, a level number and a scale factor, and it's going to say--\nDialogue: 0,1:04:36.16,1:04:39.12,EN,,0,0,0,,I'm going to do some repeated operation.\nDialogue: 0,1:04:39.45,1:04:46.62,EN,,0,0,0,,I'm going to repeatedly apply the procedure which takes a picture\nDialogue: 0,1:04:48.40,1:04:50.69,EN,,0,0,0,,and applies the means of combination\nDialogue: 0,1:04:51.20,1:04:59.08,EN,,0,0,0,,to the picture and the original picture and the one I took in here and the scale factor,\nDialogue: 0,1:05:02.26,1:05:07.28,EN,,0,0,0,,and I do the thing which repeats this procedure N times,\nDialogue: 0,1:05:12.04,1:05:16.20,EN,,0,0,0,,and I apply that whole thing to my original picture.\nDialogue: 0,1:05:19.56,1:05:24.48,EN,,0,0,0,,Repeated here, in case you haven't seen it, is another higher order procedure\nDialogue: 0,1:05:24.53,1:05:28.34,EN,,0,0,0,,that takes a procedure and a number\nDialogue: 0,1:05:29.54,1:05:34.29,EN,,0,0,0,,and returns for you another procedure that applies this procedure N times.\nDialogue: 0,1:05:36.04,1:05:39.30,EN,,0,0,0,,And I think some of you have already written repeated as an exercise,\nDialogue: 0,1:05:39.70,1:05:43.01,EN,,0,0,0,,but if you haven't, it's a very good exercise in thinking about higher order procedures.\nDialogue: 0,1:05:43.84,1:05:46.90,EN,,0,0,0,,But in any case, the result of this repeated is what I apply to picture.\nDialogue: 0,1:05:49.46,1:05:52.38,EN,,0,0,0,,And having done that, that's going to capture the --\nDialogue: 0,1:05:53.12,1:05:57.73,EN,,0,0,0,,that is the thing, the way I got from the idea of Beside to the idea of right-push\nDialogue: 0,1:05:59.01,1:06:13.17,EN,,0,0,0,,So having done that, I could say define right-push to be push of Beside.\nDialogue: 0,1:06:17.65,1:06:20.32,EN,,0,0,0,,Or if I say, define up-push to be push of Above\nDialogue: 0,1:06:20.34,1:06:25.48,EN,,0,0,0,,I'd get the analogous thing or define corner-push to be push of some appropriate thing that did both the Beside and Above,\nDialogue: 0,1:06:25.49,1:06:26.70,EN,,0,0,0,,or I could push anything.\nDialogue: 0,1:06:28.26,1:06:34.76,EN,,0,0,0,,Anyway this is, if you're having trouble with lambdas, this is an excellent exercise in figuring out what this means.\nDialogue: 0,1:06:38.98,1:06:41.00,EN,,0,0,0,,OK, well there's a lot to learn from this example.\nDialogue: 0,1:06:42.18,1:06:49.80,EN,,0,0,0,,The main point I've been welling on is the notion of nicely embedding a language inside another language.\nDialogue: 0,1:06:50.66,1:06:55.62,EN,,0,0,0,,Right, so that all the power of this language like Lisp of the surrounding language\nDialogue: 0,1:06:55.92,1:07:00.28,EN,,0,0,0,,is still accessible to you and appears as a natural extension of the language that you built.\nDialogue: 0,1:07:00.98,1:07:04.00,EN,,0,0,0,,That's one thing that this example shows very well.\nDialogue: 0,1:07:08.14,1:07:10.94,EN,,0,0,0,,Another thing is, if you go back and think about that,\nDialogue: 0,1:07:10.94,1:07:12.28,EN,,0,0,0,,what's procedures and what's data.\nDialogue: 0,1:07:12.28,1:07:16.20,EN,,0,0,0,,You know, by the time we get up to here, my God, what's going on.\nDialogue: 0,1:07:16.20,1:07:19.66,EN,,0,0,0,,I mean, this is some procedure, and it takes a picture and an argument,\nDialogue: 0,1:07:19.66,1:07:20.36,EN,,0,0,0,,and what's a picture.\nDialogue: 0,1:07:20.36,1:07:23.82,EN,,0,0,0,,Well, a picture itself, as you remember, was a procedure, and that took a rectangle.\nDialogue: 0,1:07:23.82,1:07:25.82,EN,,0,0,0,,And a rectangle is some abstraction.\nDialogue: 0,1:07:26.09,1:07:28.13,EN,,0,0,0,,And I hope now that by now you're completely lost\nDialogue: 0,1:07:29.14,1:07:33.74,EN,,0,0,0,,as to the question of what in the system is procedure and what's data.\nDialogue: 0,1:07:33.74,1:07:34.78,EN,,0,0,0,,You see, there isn't any difference.\nDialogue: 0,1:07:35.49,1:07:36.44,EN,,0,0,0,,There really isn't.\nDialogue: 0,1:07:37.93,1:07:41.42,EN,,0,0,0,,And you might think of a picture sometimes as a procedure and sometimes as data,\nDialogue: 0,1:07:41.84,1:07:44.90,EN,,0,0,0,,but that's just, sort of, you know, making you feel comfortable.\nDialogue: 0,1:07:44.90,1:07:47.30,EN,,0,0,0,,It's really both in some sense or neither in some sense.\nDialogue: 0,1:07:49.92,1:08:02.20,EN,,0,0,0,,OK, there's a more general point about the structure of the system as creating a language,\nDialogue: 0,1:08:02.52,1:08:06.74,EN,,0,0,0,,viewing the engineering design process as one of creating language or\nDialogue: 0,1:08:07.84,1:08:13.97,EN,,0,0,0,,or rather one of creating a sort of sequence of layers of language.\nDialogue: 0,1:08:14.77,1:08:20.01,EN,,0,0,0,,You see, there's this methodology, or maybe I should say mythology,\nDialogue: 0,1:08:20.74,1:08:24.90,EN,,0,0,0,,that's, sort of, charitably called software, quote, engineering.\nDialogue: 0,1:08:25.21,1:08:28.04,EN,,0,0,0,,All right, and what does it say, it's says well, you go and you figure out your task,\nDialogue: 0,1:08:28.04,1:08:30.04,EN,,0,0,0,,and you figure out exactly what you want to do.\nDialogue: 0,1:08:30.40,1:08:32.20,EN,,0,0,0,,And once you figure out exactly what you want to do,\nDialogue: 0,1:08:32.22,1:08:34.54,EN,,0,0,0,,you find out that it breaks out into three sub-tasks,\nDialogue: 0,1:08:34.54,1:08:35.76,EN,,0,0,0,,and you go and you start working on--\nDialogue: 0,1:08:35.97,1:08:38.94,EN,,0,0,0,,and you work on this sub-task, and you figure out exactly what that is.\nDialogue: 0,1:08:38.94,1:08:43.04,EN,,0,0,0,,And you find out that that breaks down into three sub-tasks, and you specify them completely,\nDialogue: 0,1:08:43.04,1:08:47.32,EN,,0,0,0,,and you go and you work on those two, and you work on this sub-one, and you specify that exactly.\nDialogue: 0,1:08:47.32,1:08:51.10,EN,,0,0,0,,And then finally when you're done, you come back way up here, and you work on your second sub-task,\nDialogue: 0,1:08:51.10,1:08:53.40,EN,,0,0,0,,and specify that out and work it out.\nDialogue: 0,1:08:53.40,1:08:57.64,EN,,0,0,0,,And then you end up with-- you end up at the end with this beautiful edifice.\nDialogue: 0,1:08:57.64,1:09:00.25,EN,,0,0,0,,Right, you end up with a marvelous tree,\nDialogue: 0,1:09:00.89,1:09:08.24,EN,,0,0,0,,that where you've broken your task into sub-tasks and broken each of these into sub-tasks and broken those into sub-tasks, right.\nDialogue: 0,1:09:09.88,1:09:15.02,EN,,0,0,0,,And each of these nodes is exactly and precisely defined\nDialogue: 0,1:09:15.26,1:09:18.66,EN,,0,0,0,,to do the wonderful, beautiful task to make it fit into the whole edifice\nDialogue: 0,1:09:18.96,1:09:21.14,EN,,0,0,0,,Right, that's this mythology.\nDialogue: 0,1:09:21.14,1:09:25.92,EN,,0,0,0,,See only a computer scientist could possibly believe that you build a complex system like that\nDialogue: 0,1:09:27.48,1:09:32.80,EN,,0,0,0,,Right. Contrast that with this Henderson example.\nDialogue: 0,1:09:32.80,1:09:34.30,EN,,0,0,0,,It didn't work like that.\nDialogue: 0,1:09:35.26,1:09:39.33,EN,,0,0,0,,What happened was that there was a sequence of layers of language.\nDialogue: 0,1:09:41.06,1:09:42.05,EN,,0,0,0,,What happened?\nDialogue: 0,1:09:42.18,1:09:48.76,EN,,0,0,0,,There was a layer of a thing that allowed us to build primitive pictures.\nDialogue: 0,1:09:51.69,1:09:56.24,EN,,0,0,0,,There's primitive pictures and that was a language.\nDialogue: 0,1:09:56.32,1:09:57.84,EN,,0,0,0,,I didn't say much about it.\nDialogue: 0,1:09:58.22,1:09:59.58,EN,,0,0,0,,We talked about how to construct George,\nDialogue: 0,1:09:59.61,1:10:04.88,EN,,0,0,0,,but that was a language where you talked about vectors and line segments and points and where they sat in the unit square.\nDialogue: 0,1:10:06.42,1:10:11.29,EN,,0,0,0,,And then on top of that, right, on top of that--\nDialogue: 0,1:10:11.97,1:10:14.10,EN,,0,0,0,,so this is the language of primitive pictures.\nDialogue: 0,1:10:17.08,1:10:20.36,EN,,0,0,0,,Right, talking about line segments in particular pictures in the unit square.\nDialogue: 0,1:10:21.40,1:10:23.80,EN,,0,0,0,,On top of that was a whole language.\nDialogue: 0,1:10:24.05,1:10:30.86,EN,,0,0,0,,There was a language of geometric combinators,\nDialogue: 0,1:10:32.66,1:10:36.62,EN,,0,0,0,,a language of geometric positions,\nDialogue: 0,1:10:38.77,1:10:46.50,EN,,0,0,0,,which talks about things like Above and Beside and right-push and Rotate.\nDialogue: 0,1:10:48.04,1:10:55.70,EN,,0,0,0,,And those things, sort of, happened with reference to the things that are talked about in this language.\nDialogue: 0,1:10:58.57,1:11:00.93,EN,,0,0,0,,And then if we like, we saw that above that\nDialogue: 0,1:11:02.61,1:11:15.10,EN,,0,0,0,,there was sort of a language of schemes of combination.\nDialogue: 0,1:11:21.25,1:11:22.44,EN,,0,0,0,,For example, push,\nDialogue: 0,1:11:24.45,1:11:27.88,EN,,0,0,0,,which talked about repeatedly doing something over with a scale factor.\nDialogue: 0,1:11:28.38,1:11:31.28,EN,,0,0,0,,And the things that were being discussed in that language\nDialogue: 0,1:11:31.50,1:11:34.34,EN,,0,0,0,,were, sort of, the things that happened down here.\nDialogue: 0,1:11:36.30,1:11:42.76,EN,,0,0,0,,So what you have is, at each level, the objects that are being talked about\nDialogue: 0,1:11:44.68,1:11:47.00,EN,,0,0,0,,are the things that were erected the previous level.\nDialogue: 0,1:11:48.08,1:11:52.06,EN,,0,0,0,,What's the difference between this thing and this thing?\nDialogue: 0,1:11:53.34,1:11:54.18,EN,,0,0,0,,The answer is\nDialogue: 0,1:11:56.14,1:12:01.73,EN,,0,0,0,,that over here in the tree, each node, and in fact, each decomposition down here,\nDialogue: 0,1:12:02.14,1:12:05.25,EN,,0,0,0,,is being designed to do a specific task,\nDialogue: 0,1:12:07.50,1:12:08.88,EN,,0,0,0,,whereas in the other scheme,\nDialogue: 0,1:12:09.21,1:12:14.80,EN,,0,0,0,,what you have is a full range of linguistic power at each level.\nDialogue: 0,1:12:16.00,1:12:18.08,EN,,0,0,0,,See what's happening there, at any level,\nDialogue: 0,1:12:20.24,1:12:22.72,EN,,0,0,0,,it's not being set up to do a particular task.\nDialogue: 0,1:12:23.14,1:12:26.17,EN,,0,0,0,,It's being set up to talk about a whole range of things.\nDialogue: 0,1:12:27.62,1:12:30.78,EN,,0,0,0,,The consequence of that for design\nDialogue: 0,1:12:31.14,1:12:35.58,EN,,0,0,0,,is that something that's designed in that method is likely to be more robust,\nDialogue: 0,1:12:36.61,1:12:38.20,EN,,0,0,0,,where by robust, I mean\nDialogue: 0,1:12:38.44,1:12:41.24,EN,,0,0,0,,that if you go and make some change in your description,\nDialogue: 0,1:12:42.70,1:12:48.04,EN,,0,0,0,,it's more likely to be captured by a corresponding change,\nDialogue: 0,1:12:49.22,1:12:52.60,EN,,0,0,0,,in the way that the language is implemented at the next level up,\nDialogue: 0,1:12:54.29,1:12:56.58,EN,,0,0,0,,right, because you've made these levels full.\nDialogue: 0,1:12:56.62,1:12:59.66,EN,,0,0,0,,So you're not talking about a particular thing like Beside.\nDialogue: 0,1:12:59.94,1:13:03.78,EN,,0,0,0,,You've given yourself a whole vocabulary to express things of that sort,\nDialogue: 0,1:13:04.77,1:13:07.02,EN,,0,0,0,,so if you go and change your specifications a little bit,\nDialogue: 0,1:13:07.02,1:13:11.38,EN,,0,0,0,,it's more likely that your methodology will able to adapt to capture that change,\nDialogue: 0,1:13:12.69,1:13:15.02,EN,,0,0,0,,whereas a design like this is not going to be robust,\nDialogue: 0,1:13:15.02,1:13:17.08,EN,,0,0,0,,because if I go and change something that's in here,\nDialogue: 0,1:13:17.53,1:13:21.69,EN,,0,0,0,,that might affect the entire way that I decomposed everything down, further down the tree.\nDialogue: 0,1:13:23.20,1:13:29.74,EN,,0,0,0,,Right, so very big difference in outlook in decomposition, levels of language rather than, sort of, a strict hierarchy.\nDialogue: 0,1:13:30.52,1:13:33.02,EN,,0,0,0,,Not only that, but when you have levels of language\nDialogue: 0,1:13:33.50,1:13:35.92,EN,,0,0,0,,you've given yourself a different vocabularies\nDialogue: 0,1:13:36.45,1:13:38.74,EN,,0,0,0,,for talking about the design at different levels.\nDialogue: 0,1:13:38.74,1:13:40.92,EN,,0,0,0,,So if we go back and look at George one last time,\nDialogue: 0,1:13:41.90,1:13:44.08,EN,,0,0,0,,if I wanted to change this picture George,\nDialogue: 0,1:13:45.85,1:13:48.68,EN,,0,0,0,,see suddenly I have a whole different ways of describing the change.\nDialogue: 0,1:13:48.68,1:13:56.08,EN,,0,0,0,,Like for example, I may want to go to the basic primitive design and move the endpoint of some vector.\nDialogue: 0,1:13:57.76,1:14:00.76,EN,,0,0,0,,That's a change that I would discuss at the lowest level.\nDialogue: 0,1:14:01.00,1:14:02.50,EN,,0,0,0,,I would say the endpoint is somewhere else.\nDialogue: 0,1:14:03.34,1:14:07.98,EN,,0,0,0,,Or I might come up and say, well the next thing I wanted to do, this little replicated element,\nDialogue: 0,1:14:09.10,1:14:10.94,EN,,0,0,0,,I might want to do by something else.\nDialogue: 0,1:14:10.94,1:14:13.84,EN,,0,0,0,,I might want to put a scale factor in that Beside.\nDialogue: 0,1:14:13.84,1:14:19.34,EN,,0,0,0,,That's a change that I would discuss at the next level of design, the level of combinators.\nDialogue: 0,1:14:19.34,1:14:25.05,EN,,0,0,0,,Or I might want to say, I might want to change the basic way that I took this pattern\nDialogue: 0,1:14:26.49,1:14:30.48,EN,,0,0,0,,and made some recursive decomposition, maybe not bleeding out toward the corners or something else.\nDialogue: 0,1:14:31.16,1:14:34.18,EN,,0,0,0,,That would be a change that I would discuss at the highest level.\nDialogue: 0,1:14:34.18,1:14:36.37,EN,,0,0,0,,And because I've structured the system to be this way,\nDialogue: 0,1:14:36.52,1:14:39.62,EN,,0,0,0,,I have all these vocabularies for talking about change in different ways\nDialogue: 0,1:14:39.65,1:14:42.48,EN,,0,0,0,,and a lot of flexibility to decide which one's appropriate.\nDialogue: 0,1:14:44.74,1:14:51.05,EN,,0,0,0,,OK, well that's sort of a big point about the difference in software methodology that comes out from Lisp,\nDialogue: 0,1:14:51.25,1:14:55.45,EN,,0,0,0,,and it all comes again, out of the notion that really, the design process\nDialogue: 0,1:14:56.12,1:14:59.62,EN,,0,0,0,,is not so much implementing programs as implementing languages.\nDialogue: 0,1:14:59.62,1:15:01.09,EN,,0,0,0,,And that's really the power of Lisp.\nDialogue: 0,1:15:02.21,1:15:03.61,EN,,0,0,0,,OK, thank you. Let's take a break.\nDialogue: 0,0:00:00.00,0:00:03.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:04.40,0:00:12.16,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:04.40,0:00:12.16,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}字幕&时间轴\\N邓雄飞 & S.Michael\nDialogue: 0,0:00:04.40,0:00:12.16,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}后期&特效\\N邓雄飞\\N(Dysprosium)\nDialogue: 0,0:00:04.40,0:00:12.16,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\\N\nDialogue: 0,0:00:04.40,0:00:12.16,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:12.37,0:00:16.32,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson-Escher的例子\\NHenderson Escher Example\nDialogue: 0,0:00:20.94,0:00:23.86,Default,,0,0,0,,上节课我们讨论了复合数据\nDialogue: 0,0:00:24.94,0:00:29.74,Default,,0,0,0,,其中有两个关键点\nDialogue: 0,0:00:29.74,0:00:32.48,Default,,0,0,0,,首先 有一种数据抽象的方法学\nDialogue: 0,0:00:32.94,0:00:39.10,Default,,0,0,0,,其要点是将数据的使用\nDialogue: 0,0:00:40.06,0:00:41.50,Default,,0,0,0,,和表示分离开来\nDialogue: 0,0:00:41.55,0:00:45.20,Default,,0,0,0,,比如说 我们可以与一个叫做George的人“签订契约”\nDialogue: 0,0:00:45.20,0:00:47.48,Default,,0,0,0,,让他负责数据的表示\nDialogue: 0,0:00:47.48,0:00:49.36,Default,,0,0,0,,而当我们使用这些数据的时候\nDialogue: 0,0:00:49.36,0:00:51.36,Default,,0,0,0,,不需要替George操心他是如何完成数据表示的工作的\nDialogue: 0,0:00:51.98,0:00:58.44,Default,,0,0,0,,其次 Lisp中有一种特殊的方式把对象连接在一起\nDialogue: 0,0:00:58.94,0:01:00.52,Default,,0,0,0,,就是构成“序对”\nDialogue: 0,0:01:00.52,0:01:03.54,Default,,0,0,0,,这是通过CONS CAR CDR实现的\nDialogue: 0,0:01:03.54,0:01:07.16,Default,,0,0,0,,而CONS CAR CDR本身是如何实现的 这不重要\nDialogue: 0,0:01:07.16,0:01:10.02,Default,,0,0,0,,George的任务就是如何构建这些东西\nDialogue: 0,0:01:10.02,0:01:11.16,Default,,0,0,0,,可以将它们实现为基本过程\nDialogue: 0,0:01:11.16,0:01:13.80,Default,,0,0,0,,也可以利用一些奇怪的过程来实现\nDialogue: 0,0:01:13.80,0:01:15.22,Default,,0,0,0,,但是我们不用操心这些\nDialogue: 0,0:01:16.02,0:01:19.66,Default,,0,0,0,,举个例子 我们来看下有理数算术\nDialogue: 0,0:01:19.66,0:01:21.50,Default,,0,0,0,,看下向量\nDialogue: 0,0:01:21.50,0:01:24.18,Default,,0,0,0,,我们简单回顾一下向量\nDialogue: 0,0:01:24.18,0:01:27.64,Default,,0,0,0,,这里有个对两个向量求和的操作\nDialogue: 0,0:01:27.64,0:01:33.32,Default,,0,0,0,,我们想要把向量v1和v2相加\nDialogue: 0,0:01:34.46,0:01:40.84,Default,,0,0,0,,它们的和也是一个向量 其坐标是两个向量的坐标的和\nDialogue: 0,0:01:41.28,0:01:45.66,Default,,0,0,0,,所以 定义(+VECT V1 V2)为\nDialogue: 0,0:01:45.66,0:01:51.72,Default,,0,0,0,,我创建一个向量 其X坐标是两向量X坐标的和\nDialogue: 0,0:01:52.10,0:01:54.82,Default,,0,0,0,,而Y坐标是两向量Y坐标的和\nDialogue: 0,0:01:56.06,0:02:04.10,Default,,0,0,0,,类似地 我们也可以定义一个缩放向量的操作\nDialogue: 0,0:02:04.94,0:02:12.66,Default,,0,0,0,,这里的SCALE过程是用数字S乘以向量V\nDialogue: 0,0:02:13.08,0:02:16.14,Default,,0,0,0,,向量V从这里到这里\nDialogue: 0,0:02:16.32,0:02:20.22,Default,,0,0,0,,我放大V 得到了与原来同向但更长的向量\nDialogue: 0,0:02:21.56,0:02:24.26,Default,,0,0,0,,为了缩放向量 我需要通过缩放坐标来实现\nDialogue: 0,0:02:24.26,0:02:30.22,Default,,0,0,0,,所以我构建了一个向量 它的X坐标是原向量X坐标的S倍\nDialogue: 0,0:02:30.56,0:02:33.54,Default,,0,0,0,,同时 它的Y坐标是原来向量Y坐标的S倍\nDialogue: 0,0:02:33.54,0:02:40.28,Default,,0,0,0,,上述两个操作都是利用了向量的表示来实现的\nDialogue: 0,0:02:40.28,0:02:45.02,Default,,0,0,0,,而这种向量的表示 我们则可以用序对来实现\nDialogue: 0,0:02:45.34,0:02:51.28,Default,,0,0,0,,因此George需要为我们提供MAKE-VECTOR、XCOR和YCOR\nDialogue: 0,0:02:53.02,0:02:57.98,Default,,0,0,0,,他可以使用CONS CAR CDR来实现\nDialogue: 0,0:02:58.88,0:03:06.78,Default,,0,0,0,,但是注意 我这里用了一个略微不同的方式\nDialogue: 0,0:03:08.04,0:03:11.00,Default,,0,0,0,,这个过程我们之前看过 其中我讲过\nDialogue: 0,0:03:11.14,0:03:16.22,Default,,0,0,0,,(MAKE-VECTOR X Y)也就是(CONS X Y)\nDialogue: 0,0:03:16.22,0:03:17.98,Default,,0,0,0,,而我这里简单定义MAKE-VECTOR为CONS\nDialogue: 0,0:03:17.98,0:03:20.48,Default,,0,0,0,,这就与之前有些不同了\nDialogue: 0,0:03:20.48,0:03:26.22,Default,,0,0,0,,之前我们我们把MAKE-VECTOR定义为需要两个参数的过程\nDialogue: 0,0:03:26.22,0:03:28.04,Default,,0,0,0,,效果是(CONS X Y)\nDialogue: 0,0:03:28.04,0:03:34.12,Default,,0,0,0,,这里 我就把MAKE-VECTOR定义为CONS\nDialogue: 0,0:03:35.18,0:03:39.66,Default,,0,0,0,,这跟我们之前使用的方式基本上是一样的\nDialogue: 0,0:03:39.66,0:03:46.58,Default,,0,0,0,,大家要习惯于“过程也是对象 而且你可以给他们命名”这种想法\nDialogue: 0,0:03:48.70,0:03:51.80,Default,,0,0,0,,这些就是向量的表示方法了\nDialogue: 0,0:03:51.80,0:03:55.68,Default,,0,0,0,,如果仅仅是那样 那就太无趣了\nDialogue: 0,0:03:57.02,0:04:02.16,Default,,0,0,0,,要记住 要点是我们不仅可以通过使用CONS将数字组合成序对\nDialogue: 0,0:04:02.16,0:04:04.16,Default,,0,0,0,,也可以组合任何东西\nDialogue: 0,0:04:05.20,0:04:11.60,Default,,0,0,0,,例如 如果我想表示一个线段\nDialogue: 0,0:04:11.60,0:04:15.64,Default,,0,0,0,,一个以某个向量为起点的线段\nDialogue: 0,0:04:16.06,0:04:28.30,Default,,0,0,0,,比如从向量(2,3)所代表的起点到向量(5,1)所代表的终点的线段\nDialogue: 0,0:04:28.30,0:04:31.82,Default,,0,0,0,,如果我们想表示这条线段\nDialogue: 0,0:04:33.26,0:04:36.20,Default,,0,0,0,,那么我们可以构建一个序对的序对\nDialogue: 0,0:04:40.72,0:04:42.94,Default,,0,0,0,,这样我们就可以表示一条线段了\nDialogue: 0,0:04:42.94,0:04:47.34,Default,,0,0,0,,我们可以编写一个使用CONS构造线段的构造函数\nDialogue: 0,0:04:47.98,0:04:51.60,Default,,0,0,0,,以及 析取出线段起点、终点的选择函数\nDialogue: 0,0:04:55.24,0:04:59.76,Default,,0,0,0,,那么如果我们剥开抽象层一探究竟\nDialogue: 0,0:04:59.88,0:05:02.10,Default,,0,0,0,,就会发现线段不过是 序对组成的序对\nDialogue: 0,0:05:04.66,0:05:06.22,Default,,0,0,0,,它还是一个序对\nDialogue: 0,0:05:06.22,0:05:08.22,Default,,0,0,0,,这里有个线段\nDialogue: 0,0:05:10.00,0:05:16.72,Default,,0,0,0,,它的CAR部分是个序对 CDR部分也是个序对\nDialogue: 0,0:05:18.32,0:05:25.54,Default,,0,0,0,,它的CAR部分是由2和3构成的序对\nDialogue: 0,0:05:26.02,0:05:28.08,Default,,0,0,0,,CDR部分则由5和1构成的序对\nDialogue: 0,0:05:28.16,0:05:29.24,Default,,0,0,0,,这里我再提醒大家一下\nDialogue: 0,0:05:29.32,0:05:33.46,Default,,0,0,0,,好多人认为如果我箭头向下画的话\nDialogue: 0,0:05:33.80,0:05:36.90,Default,,0,0,0,,会有其它的含意\nDialogue: 0,0:05:36.98,0:05:38.28,Default,,0,0,0,,这是不对的\nDialogue: 0,0:05:38.58,0:05:43.90,Default,,0,0,0,,箭头指示的是对象间如何连接 它指向水平或竖直方向都是无关紧要的\nDialogue: 0,0:05:47.48,0:05:52.18,Default,,0,0,0,,还要提醒一下 序对是具有闭包性质的\nDialogue: 0,0:05:52.94,0:06:05.62,Default,,0,0,0,,闭包性质使我们可以构建更复杂的东西 而不仅仅是简单的序对\nDialogue: 0,0:06:06.64,0:06:15.24,Default,,0,0,0,,在这里我要特别指出 在我们用CONS构建出来的序对的基础上\nDialogue: 0,0:06:16.44,0:06:22.64,Default,,0,0,0,,我们也可以进一步用CONS来构造更复杂的对象\nDialogue: 0,0:06:23.28,0:06:31.98,Default,,0,0,0,,或者用数学家的话说 Lisp中的数据对象在CONS运算下是封闭的\nDialogue: 0,0:06:33.82,0:06:36.34,Default,,0,0,0,,这个性质使我们能够构造更加复杂的数据对象\nDialogue: 0,0:06:36.34,0:06:38.04,Default,,0,0,0,,这个似乎是显然的 但是要记住\nDialogue: 0,0:06:39.06,0:06:42.46,Default,,0,0,0,,人们使用的编程语言中有很多东西并不是封闭的\nDialogue: 0,0:06:42.46,0:06:48.06,Default,,0,0,0,,举例来说 Basic和Fortran中的构造数组操作 就不是封闭的\nDialogue: 0,0:06:48.08,0:06:51.94,Default,,0,0,0,,因为 虽然你可以用数字、字符或字符串等来构造数组\nDialogue: 0,0:06:52.04,0:06:54.18,Default,,0,0,0,,但是你不能创建数组的数组\nDialogue: 0,0:06:54.64,0:06:56.68,Default,,0,0,0,,当考察某种组合的方法时\nDialogue: 0,0:06:57.60,0:07:02.78,Default,,0,0,0,,你应该考察该组合方法是否封闭\nDialogue: 0,0:07:05.06,0:07:08.26,Default,,0,0,0,,不管怎样 因为我们可以构造序对的序对\nDialogue: 0,0:07:08.86,0:07:12.78,Default,,0,0,0,,我们就可以用序对将数据以各种各样的方式组合起来\nDialogue: 0,0:07:14.02,0:07:18.26,Default,,0,0,0,,比如我想要组合四个数 -- 1 2 3 4\nDialogue: 0,0:07:18.26,0:07:19.82,Default,,0,0,0,,我有很多方法\nDialogue: 0,0:07:20.74,0:07:26.12,Default,,0,0,0,,比如 像构造线段那样 我可以构造一个序对\nDialogue: 0,0:07:29.02,0:07:36.88,Default,,0,0,0,,它是((1 2) (3 4)) 对吧？\nDialogue: 0,0:07:36.88,0:07:40.06,Default,,0,0,0,,或者如果我喜欢 我可以像这样做\nDialogue: 0,0:07:40.06,0:07:45.52,Default,,0,0,0,,我构造一个序对 它的CAR部分也是一个序对\nDialogue: 0,0:07:46.44,0:07:53.20,Default,,0,0,0,,这个序对的CAR部分为1 而CDR部分为由2、3构成的序对\nDialogue: 0,0:07:53.26,0:07:55.08,Default,,0,0,0,,最后 我把4放在这里\nDialogue: 0,0:07:56.92,0:08:02.16,Default,,0,0,0,,所以你可以看到 组合对象的方式有很多种\nDialogue: 0,0:08:02.16,0:08:07.74,Default,,0,0,0,,因此就有必要建立一些统一的约定\nDialogue: 0,0:08:07.74,0:08:11.58,Default,,0,0,0,,使我们能够用某种的通用的方式处理数据\nDialogue: 0,0:08:11.58,0:08:14.00,Default,,0,0,0,,而不用总是针对具体问题做一些生硬的选择\nDialogue: 0,0:08:15.94,0:08:19.04,Default,,0,0,0,,Lisp里面就有这样一种约定\nDialogue: 0,0:08:20.74,0:08:25.82,Default,,0,0,0,,这个约定将一系列的东西表示成一个序对组成的链\nDialogue: 0,0:08:26.78,0:08:28.18,Default,,0,0,0,,而这样一个数据序列就叫做一个“表”\nDialogue: 0,0:08:34.72,0:08:40.50,Default,,0,0,0,,表本质上就是Lisp用来表示序列数据的一个约定而已\nDialogue: 0,0:08:40.70,0:08:47.38,Default,,0,0,0,,我可以使用序对的序列来表示序列 1 2 3 4\nDialogue: 0,0:08:48.26,0:08:54.68,Default,,0,0,0,,我把1放在这里 它的CDR指向另一个序对\nDialogue: 0,0:08:59.20,0:09:01.40,Default,,0,0,0,,这个序对的CAR部分是序列中的下一个数\nDialogue: 0,0:09:01.52,0:09:03.42,Default,,0,0,0,,并且它的CDR指向了另一个序对\nDialogue: 0,0:09:05.44,0:09:07.30,Default,,0,0,0,,它的CAR部分是序列的再下一个数\nDialogue: 0,0:09:07.36,0:09:08.44,Default,,0,0,0,,这个是3\nDialogue: 0,0:09:08.44,0:09:09.74,Default,,0,0,0,,以此类推\nDialogue: 0,0:09:09.74,0:09:13.22,Default,,0,0,0,,所以 序列中的每一个元素都对应着一个序对\nDialogue: 0,0:09:15.82,0:09:18.32,Default,,0,0,0,,而当这个序列中没有其它元素时，我用一个特殊的标记\nDialogue: 0,0:09:20.72,0:09:22.74,Default,,0,0,0,,来表示列表中没有元素了\nDialogue: 0,0:09:24.14,0:09:34.64,Default,,0,0,0,,好 这就是将序列中的元素组合起来的一种约定方式\nDialogue: 0,0:09:34.64,0:09:37.98,Default,,0,0,0,,而它其实就是一堆序对\nDialogue: 0,0:09:39.40,0:09:44.80,Default,,0,0,0,,每个序对中的CAR部分就是我们想要组合到一起的元素\nDialogue: 0,0:09:46.00,0:09:48.46,Default,,0,0,0,,这些序对的CDR部分则指向下一个序对\nDialogue: 0,0:09:50.02,0:09:56.04,Default,,0,0,0,,现在 如果我想要构造它 我需要向Lisp中输入\nDialogue: 0,0:09:56.62,0:09:58.76,Default,,0,0,0,,我会像这样来构造\nDialogue: 0,0:09:59.22,0:10:15.28,Default,,0,0,0,,(CONS 1 (CONS 2 (CONS 3 (CONS 4 NIL))))\nDialogue: 0,0:10:15.28,0:10:20.00,Default,,0,0,0,,NIL是序列末尾标志的名字\nDialogue: 0,0:10:20.80,0:10:23.24,Default,,0,0,0,,它是一个特殊的名字 用以标识表的末尾\nDialogue: 0,0:10:26.24,0:10:30.26,Default,,0,0,0,,好 这就是如何构造一个表\nDialogue: 0,0:10:37.54,0:10:41.40,Default,,0,0,0,,如果每次构造一个表时 都要输入像\nDialogue: 0,0:10:41.45,0:10:45.18,Default,,0,0,0,,(CONS 1 (CONS 2 (CONS 3...的话 将会非常费力\nDialogue: 0,0:10:45.18,0:10:50.10,Default,,0,0,0,,因此Lisp提供了一种叫做LIST的操作\nDialogue: 0,0:10:53.70,0:10:57.72,Default,,0,0,0,,LIST其实是这种嵌套CONS的缩写\nDialogue: 0,0:10:58.96,0:11:06.32,Default,,0,0,0,,它可以让我用(LIST 1 2 3 4)来构造表\nDialogue: 0,0:11:07.78,0:11:11.74,Default,,0,0,0,,这只是另外一种方式 一种语法糖衣\nDialogue: 0,0:11:11.94,0:11:14.76,Default,,0,0,0,,用来简便地书写嵌套的CONS\nDialogue: 0,0:11:14.76,0:11:17.84,Default,,0,0,0,,(CONS (CONS (CONS (CONS NIL))))\nDialogue: 0,0:11:18.48,0:11:39.78,Default,,0,0,0,,举例来说 我将构造一个表(1 2 3 4) 并把它叫做1-TO-4\nDialogue: 0,0:11:47.96,0:11:53.02,Default,,0,0,0,,注意使用这种简便写法的结果\nDialogue: 0,0:11:53.80,0:11:56.92,Default,,0,0,0,,首先 如果我有这个表(1 2 3 4)\nDialogue: 0,0:11:57.36,0:12:02.64,Default,,0,0,0,,表的CAR把部分就是这个表的第一个元素 对吧？\nDialogue: 0,0:12:04.06,0:12:05.28,Default,,0,0,0,,那么 如何获得元素2呢？\nDialogue: 0,0:12:05.28,0:12:23.94,Default,,0,0,0,,2应该是1-TO-4的CDR部分的CAR部分\nDialogue: 0,0:12:23.98,0:12:29.48,Default,,0,0,0,,它的CDR是这个\nDialogue: 0,0:12:29.82,0:12:31.68,Default,,0,0,0,,而它的CAR部分是2\nDialogue: 0,0:12:32.58,0:12:47.42,Default,,0,0,0,,同理 1-TO-4的CDR的CDR的CAR部分\nDialogue: 0,0:12:47.42,0:12:51.36,Default,,0,0,0,,是3 以此类推\nDialogue: 0,0:12:52.68,0:12:55.84,Default,,0,0,0,,我们来看下屏幕\nDialogue: 0,0:12:57.50,0:13:11.18,Default,,0,0,0,,我定义一个表(1 2 3 4) 命名为1-TO-4\nDialogue: 0,0:13:13.78,0:13:21.28,Default,,0,0,0,,我这样写 计算机返回定义完成 这个就是1-TO-4的定义\nDialogue: 0,0:13:22.30,0:13:36.74,Default,,0,0,0,,我问 比如 1-TO-4的CDR的CDR的CAR\nDialogue: 0,0:13:38.34,0:13:42.42,Default,,0,0,0,,嗯 它是3\nDialogue: 0,0:13:44.08,0:13:50.08,Default,,0,0,0,,或者我问 1-TO-4是什么\nDialogue: 0,0:13:51.26,0:13:57.22,Default,,0,0,0,,Lisp输出的是用括号包围的 (1 2 3 4)\nDialogue: 0,0:13:57.22,0:14:02.12,Default,,0,0,0,,用括号将表中的元素包围起来的这种记号\nDialogue: 0,0:14:02.12,0:14:08.90,Default,,0,0,0,,通常用来打印输出表示序列的序对链\nDialogue: 0,0:14:08.90,0:14:17.14,Default,,0,0,0,,又比如 我问1-TO-4的CDR部分是什么\nDialogue: 0,0:14:19.30,0:14:21.12,Default,,0,0,0,,结果是表的剩余部分\nDialogue: 0,0:14:21.32,0:14:26.96,Default,,0,0,0,,这是原表首元素所指向的序对 新序列从2开始\nDialogue: 0,0:14:28.52,0:14:37.74,Default,,0,0,0,,比如 1-TO-4的CDR的CDR部分是什么\nDialogue: 0,0:14:43.24,0:14:44.68,Default,,0,0,0,,返回(3 4)\nDialogue: 0,0:14:44.82,0:14:59.66,Default,,0,0,0,,或者 1-TO-4的CDR的CDR的CDR的CDR部分是什么\nDialogue: 0,0:15:04.74,0:15:10.46,Default,,0,0,0,,我们看一下表的尾指针 Lisp返回()\nDialogue: 0,0:15:10.96,0:15:13.48,Default,,0,0,0,,你们可以认为这是一个空表\nDialogue: 0,0:15:14.12,0:15:21.38,Default,,0,0,0,,我求取 1-TO-4的CDR的CDR的CDR部分\nDialogue: 0,0:15:21.42,0:15:25.20,Default,,0,0,0,,这就只剩下表尾指针本身\nDialogue: 0,0:15:25.20,0:15:27.20,Default,,0,0,0,,它的输出是()\nDialogue: 0,0:15:34.14,0:15:39.98,Default,,0,0,0,,好了 这是处理表的一种常见方式\nDialogue: 0,0:15:41.50,0:15:43.44,Default,,0,0,0,,也就是不断地取CDR部分\nDialogue: 0,0:15:43.44,0:15:45.00,Default,,0,0,0,,这个叫做表的CDRING\nDialogue: 0,0:15:46.64,0:15:49.78,Default,,0,0,0,,当然手写这些CDR非常费劲\nDialogue: 0,0:15:49.78,0:15:52.24,Default,,0,0,0,,我们没必要这么做 我们编写程序来这么做\nDialogue: 0,0:15:52.96,0:15:59.10,Default,,0,0,0,,事实上 Lisp中非常普遍的事情是写一些过程\nDialogue: 0,0:15:59.85,0:16:06.54,Default,,0,0,0,,表中所有元素进行某种操作 得到的是由结果构成的表\nDialogue: 0,0:16:07.42,0:16:11.92,Default,,0,0,0,,比如 我写一个SCALE-LIST的过程\nDialogue: 0,0:16:16.80,0:16:25.24,Default,,0,0,0,,我要用SCALE-LIST将表1-TO-4放大10倍\nDialogue: 0,0:16:26.66,0:16:35.32,Default,,0,0,0,,那么它应该返回表(10 20 30 40)\nDialogue: 0,0:16:38.25,0:16:40.25,Default,,0,0,0,,没错 它返回一个表\nDialogue: 0,0:16:44.49,0:16:49.30,Default,,0,0,0,,我们可以猜想到这当中采用了某种递归策略\nDialogue: 0,0:16:49.30,0:16:51.30,Default,,0,0,0,,我应该如何编写这个过程呢？\nDialogue: 0,0:16:52.52,0:16:59.80,Default,,0,0,0,,如果要构建一个每个元素都乘以10的列表\nDialogue: 0,0:17:00.44,0:17:04.84,Default,,0,0,0,,需要做的是—假设已经得到了结果表的剩余元素\nDialogue: 0,0:17:05.86,0:17:08.42,Default,,0,0,0,,也就是表的CDR部分\nDialogue: 0,0:17:08.42,0:17:14.16,Default,,0,0,0,,这个子表中的每个元素都是原来元素乘以10\nDialogue: 0,0:17:16.06,0:17:19.68,Default,,0,0,0,,这是SCALE-LIST对表CDR部分作用的结果\nDialogue: 0,0:17:20.12,0:17:23.82,Default,,0,0,0,,我需要做的 就只有用表的CAR部分乘以10\nDialogue: 0,0:17:24.89,0:17:27.24,Default,,0,0,0,,然后用CONS将它和剩余部分连接起来 并返回这个表\nDialogue: 0,0:17:29.02,0:17:33.09,Default,,0,0,0,,类似地 为了缩放子表 我得先缩放子表的CDR部分\nDialogue: 0,0:17:33.30,0:17:36.20,Default,,0,0,0,,并将其与2*10连接起来\nDialogue: 0,0:17:36.42,0:17:41.16,Default,,0,0,0,,最终 当我处理到表尾时 这里就只剩表尾指针了\nDialogue: 0,0:17:41.72,0:17:45.28,Default,,0,0,0,,它叫做NIL 我就直接返回表尾指针\nDialogue: 0,0:17:45.54,0:17:47.68,Default,,0,0,0,,所以这就是这个过程的递归策略\nDialogue: 0,0:17:47.68,0:17:50.52,Default,,0,0,0,,这个过程就是这样\nDialogue: 0,0:17:50.96,0:17:55.04,Default,,0,0,0,,这个例子就是对表做CDRING操作的通用策略\nDialogue: 0,0:17:55.66,0:17:58.24,Default,,0,0,0,,也就是所谓的“通过CONS组合结果”\nDialogue: 0,0:17:58.24,0:18:06.04,Default,,0,0,0,,那么 对表L缩放S倍 我该如何做呢？\nDialogue: 0,0:18:06.04,0:18:10.40,Default,,0,0,0,,首先得做判断 Lisp中有个叫NULL?的谓词\nDialogue: 0,0:18:10.40,0:18:13.22,Default,,0,0,0,,NULL?判断对象是否为表尾\nDialogue: 0,0:18:13.90,0:18:17.16,Default,,0,0,0,,或者说 对象是否为空表\nDialogue: 0,0:18:18.17,0:18:23.00,Default,,0,0,0,,任何情况下 当我处理到表尾时 我就将其返回\nDialogue: 0,0:18:23.65,0:18:24.60,Default,,0,0,0,,简单地返回NIL\nDialogue: 0,0:18:24.94,0:18:35.14,Default,,0,0,0,,否则 我就用CONS把列表中的第一个元素经过操作（缩放）后的结果\nDialogue: 0,0:18:35.54,0:18:39.29,Default,,0,0,0,,就是说 取L的CAR部分 然后用它乘以S\nDialogue: 0,0:18:40.36,0:18:46.34,Default,,0,0,0,,然后我就用CONS将这个结果 与用递归形式缩放后的表的剩下部分 连接在一起\nDialogue: 0,0:18:49.98,0:18:52.18,Default,,0,0,0,,再说一次 总体的思想是\nDialogue: 0,0:18:52.22,0:18:56.09,Default,,0,0,0,,你要用递归的方式处理表中的剩余元素 即表的CDR部分\nDialogue: 0,0:18:56.48,0:19:01.16,Default,,0,0,0,,然后你用CONS将那部分的结果 与经过处理后的表的第一个元素连接在一起\nDialogue: 0,0:19:01.16,0:19:05.18,Default,,0,0,0,,当你处理到结尾的时候 返回表尾标志NIL\nDialogue: 0,0:19:07.34,0:19:11.36,Default,,0,0,0,,这就是对一个表中的数据做某种操作的通用模式\nDialogue: 0,0:19:14.05,0:19:19.52,Default,,0,0,0,,现在 你们应该清楚知道这样一个事实\nDialogue: 0,0:19:19.53,0:19:22.62,Default,,0,0,0,,也就是我不必额外为这种基本模式额外编写过程\nDialogue: 0,0:19:22.62,0:19:24.90,Default,,0,0,0,,我要做的事情就是写一个过程\nDialogue: 0,0:19:24.90,0:19:26.32,Default,,0,0,0,,这是这个基本模式\nDialogue: 0,0:19:26.80,0:19:30.30,Default,,0,0,0,,对表中的元素执行操作 并以表的形式返回结果\nDialogue: 0,0:19:30.68,0:19:32.30,Default,,0,0,0,,好了 我们定义一些高阶过程\nDialogue: 0,0:19:32.32,0:19:35.18,Default,,0,0,0,,我们定义一个叫MAP的高阶过程 来完成这些操作\nDialogue: 0,0:19:36.73,0:19:43.17,Default,,0,0,0,,MAP以表L和过程P为参数\nDialogue: 0,0:19:44.92,0:19:51.08,Default,,0,0,0,,并返回对表L中每个元素应用过程P后得到的新表\nDialogue: 0,0:19:51.81,0:19:55.40,Default,,0,0,0,,这个新表里的元素是(P E1) (P E2) ...  到(P En)\nDialogue: 0,0:19:55.64,0:20:01.54,Default,,0,0,0,,所以我指的就是对一个表做这样一种变换：将P应用到表的每一个元素上\nDialogue: 0,0:20:02.52,0:20:07.08,Default,,0,0,0,,你们看到的这些过程正是我提到的通用策略\nDialogue: 0,0:20:07.08,0:20:09.08,Default,,0,0,0,,我们用它写乘以10的过程\nDialogue: 0,0:20:09.08,0:20:11.64,Default,,0,0,0,,如果表是空的 则返回NIL\nDialogue: 0,0:20:11.86,0:20:16.60,Default,,0,0,0,,否则 对表的首元素应用P\nDialogue: 0,0:20:17.14,0:20:18.74,Default,,0,0,0,,将P应用于L的CAR部分\nDialogue: 0,0:20:19.30,0:20:25.40,Default,,0,0,0,,然后连接它和将P应用于表CDR部分中的剩余元素得到的子表连接起来\nDialogue: 0,0:20:25.61,0:20:28.84,Default,,0,0,0,,这就是一个通用过程--MAP\nDialogue: 0,0:20:29.86,0:20:39.04,Default,,0,0,0,,我们可以用MAP来定义SCALE-LIST\nDialogue: 0,0:20:39.04,0:20:41.04,Default,,0,0,0,,我给你们展示一下\nDialogue: 0,0:20:43.46,0:20:52.50,Default,,0,0,0,,SCALE-LIST就是用MAP在表L上映射一个特定的过程\nDialogue: 0,0:20:52.50,0:20:55.54,Default,,0,0,0,,这个过程需要一个参数 返回给定参数乘以S的结果\nDialogue: 0,0:20:58.96,0:21:01.90,Default,,0,0,0,,所以我思考缩放表这个过程的正确方式应该是\nDialogue: 0,0:21:02.12,0:21:07.40,Default,,0,0,0,,将这种递归实质实现为通用策略 而不是一个具体针对的过程\nDialogue: 0,0:21:07.40,0:21:11.28,Default,,0,0,0,,当然 这样做的意义之一是 是你会开始发现共性\nDialogue: 0,0:21:12.16,0:21:15.02,Default,,0,0,0,,我们正在掌握使用通用模式\nDialogue: 0,0:21:15.96,0:21:31.18,Default,,0,0,0,,比如 (MAP SQUARE 1-TO-4) 返回(1 4 9 16)\nDialogue: 0,0:21:32.48,0:21:37.17,Default,,0,0,0,,对这个表做映射\nDialogue: 0,0:21:37.57,0:21:46.32,Default,,0,0,0,,用(LAMBDA (X) (+ X 10))映射表1-TO-4\nDialogue: 0,0:21:49.68,0:21:52.86,Default,,0,0,0,,我让表的每个元素都加了10\nDialogue: 0,0:21:53.34,0:21:58.17,Default,,0,0,0,,也就是得到了(11 12 13 14)\nDialogue: 0,0:22:00.56,0:22:05.76,Default,,0,0,0,,我们看到对表中每个元素做操作是一种非常普遍的想法\nDialogue: 0,0:22:08.66,0:22:12.22,Default,,0,0,0,,而大家需要思考如何编写MAP的迭代版本\nDialogue: 0,0:22:12.22,0:22:16.04,Default,,0,0,0,,我碰巧写的是一个递归版本\nDialogue: 0,0:22:16.36,0:22:19.10,Default,,0,0,0,,但是我们也可以很容易地把它改成迭代过程\nDialogue: 0,0:22:19.10,0:22:23.16,Default,,0,0,0,,有趣的是 一旦你开始用MAP来思考\nDialogue: 0,0:22:24.02,0:22:29.00,Default,,0,0,0,,比如 一旦把缩放看作是一种MAP 就不用关心是迭代还是递归实现\nDialogue: 0,0:22:29.00,0:22:31.82,Default,,0,0,0,,你只会关心 啊 这里有这样一种数据集合 有这样一个表\nDialogue: 0,0:22:32.22,0:22:34.52,Default,,0,0,0,,我要做的是转化表中的每个元素\nDialogue: 0,0:22:34.56,0:22:38.36,Default,,0,0,0,,而不去考虑特别的控制流程或顺序\nDialogue: 0,0:22:38.88,0:22:41.09,Default,,0,0,0,,这是个非常非常重要的想法\nDialogue: 0,0:22:42.36,0:22:46.48,Default,,0,0,0,,我猜这个想法来自APL语言\nDialogue: 0,0:22:46.48,0:22:49.10,Default,,0,0,0,,它是APL中非常重要的思想\nDialogue: 0,0:22:49.12,0:22:51.13,Default,,0,0,0,,即不要去考虑控制结构\nDialogue: 0,0:22:51.41,0:22:53.92,Default,,0,0,0,,而是关注于策略操作\nDialogue: 0,0:22:55.01,0:23:00.01,Default,,0,0,0,,在本课程进行到一半的时候 我们将讨论一种叫做流处理的东西\nDialogue: 0,0:23:00.26,0:23:02.64,Default,,0,0,0,,那时我们将看到这种观点的真正威力\nDialogue: 0,0:23:02.64,0:23:05.30,Default,,0,0,0,,这是一种很聪明的思想\nDialogue: 0,0:23:05.30,0:23:08.70,Default,,0,0,0,,我们可以在以后看到更多应用\nDialogue: 0,0:23:09.36,0:23:16.84,Default,,0,0,0,,还有一些非常有用也非常像MAP的过程\nDialogue: 0,0:23:17.56,0:23:22.54,Default,,0,0,0,,MAP是将某个过程应用于表中每个元素\nDialogue: 0,0:23:22.98,0:23:25.62,Default,,0,0,0,,并返回相应结果构成的表\nDialogue: 0,0:23:25.98,0:23:28.69,Default,,0,0,0,,还有一种与此非常非常相似的操作\nDialogue: 0,0:23:29.32,0:23:35.86,Default,,0,0,0,,也就是给定一个列表和操作 依次将其应用于表中每个元素\nDialogue: 0,0:23:36.29,0:23:39.40,Default,,0,0,0,,而不会建立由结果构成的表 只是为了完成操作\nDialogue: 0,0:23:40.02,0:23:45.10,Default,,0,0,0,,这个过程非常像MAP\nDialogue: 0,0:23:45.10,0:23:46.02,Default,,0,0,0,,它就是FOR-EACH\nDialogue: 0,0:23:46.74,0:23:49.48,Default,,0,0,0,,它接受一个过程和一个表\nDialogue: 0,0:23:49.62,0:23:53.86,Default,,0,0,0,,它实际上是对表中每个元素执行此操作\nDialogue: 0,0:23:55.16,0:23:58.53,Default,,0,0,0,,通常是这样 如果表非空\nDialogue: 0,0:23:59.74,0:24:01.12,Default,,0,0,0,,也就是不为NIL\nDialogue: 0,0:24:01.90,0:24:06.25,Default,,0,0,0,,我将这个过程应用于表的第一个元素\nDialogue: 0,0:24:07.68,0:24:11.66,Default,,0,0,0,,然后对表中其余元素做同样的事情\nDialogue: 0,0:24:12.44,0:24:15.25,Default,,0,0,0,,我将FOR-EACH也应用于表的CDR部分\nDialogue: 0,0:24:15.88,0:24:18.73,Default,,0,0,0,,我对表的首元素进行处理 然后对表其余部分进行处理\nDialogue: 0,0:24:19.32,0:24:23.92,Default,,0,0,0,,当然 以此类推 递归地调用 又会对表其余部分的其余部分做处理\nDialogue: 0,0:24:23.92,0:24:28.12,Default,,0,0,0,,最终 过程结束时 我应该告知系统\nDialogue: 0,0:24:28.16,0:24:32.40,Default,,0,0,0,,所以就返回“DONE” 所以这非常像MAP\nDialogue: 0,0:24:32.80,0:24:35.12,Default,,0,0,0,,它们之间只是返回值不同\nDialogue: 0,0:24:35.48,0:24:39.90,Default,,0,0,0,,比如说 如果我有一个可以在屏幕上打印对象的过程\nDialogue: 0,0:24:40.56,0:24:45.81,Default,,0,0,0,,如果我想打印表中的所有元素 可以调用(FOR-EACH PRINT LIST)\nDialogue: 0,0:24:46.78,0:24:51.33,Default,,0,0,0,,如果我有一系列图表构成的表 想把它们输出在屏幕上\nDialogue: 0,0:24:51.62,0:24:54.86,Default,,0,0,0,,我可以对这个调用(FOR-EACH DISPLAY FIGURES)\nDialogue: 0,0:24:58.18,0:24:59.32,Default,,0,0,0,,有问题么？\nDialogue: 0,0:25:00.62,0:25:04.26,Default,,0,0,0,,学生：除非你明确地指定\nDialogue: 0,0:25:04.30,0:25:07.54,Default,,0,0,0,,Lisp会创建一个你正在处理的对象的新拷贝 是这样么？\nDialogue: 0,0:25:07.54,0:25:09.18,Default,,0,0,0,,教授：对\nDialogue: 0,0:25:09.93,0:25:10.94,Default,,0,0,0,,就是这样\nDialogue: 0,0:25:10.94,0:25:15.14,Default,,0,0,0,,FOR-EACH不创建新列表 它只是对列表的每一个元素进行处理\nDialogue: 0,0:25:15.14,0:25:17.29,Default,,0,0,0,,所以如果你有一堆事情等着做\nDialogue: 0,0:25:18.02,0:25:21.56,Default,,0,0,0,,并且你并不关心这些值 比如打印 绘图\nDialogue: 0,0:25:21.89,0:25:24.60,Default,,0,0,0,,或者在终端中响铃等等\nDialogue: 0,0:25:24.60,0:25:27.64,Default,,0,0,0,,FOR-EACH对表中每个元素做这些事\nDialogue: 0,0:25:28.21,0:25:32.42,Default,,0,0,0,,而MAP其实构建了一个新集合 这个集合也许是你想要用的\nDialogue: 0,0:25:32.42,0:25:34.16,Default,,0,0,0,,这就是它们之间的微妙关系\nDialogue: 0,0:25:34.16,0:25:36.30,Default,,0,0,0,,学生：你能否用FOR-EACH来构造MAP\nDialogue: 0,0:25:36.32,0:25:40.16,Default,,0,0,0,,其中你用类似CONS的操作将表又构造出来了？\nDialogue: 0,0:25:40.18,0:25:44.46,Default,,0,0,0,,教授：某种程度上 我也许可以\nDialogue: 0,0:25:44.46,0:25:49.98,Default,,0,0,0,,我不知道如何随手写出它 但是我可以给一些思路\nDialogue: 0,0:25:50.48,0:25:54.73,Default,,0,0,0,,学生：根据昨天的课程 我认为MAP和FOR-EACH的关键区别在于\nDialogue: 0,0:25:54.73,0:26:00.62,Default,,0,0,0,,它们之中一个是递归的 而另一个不是\nDialogue: 0,0:26:01.24,0:26:03.86,Default,,0,0,0,,教授：是的 关于MAP和FOR-EACH和递归\nDialogue: 0,0:26:03.86,0:26:05.48,Default,,0,0,0,,这个观点很好\nDialogue: 0,0:26:05.48,0:26:13.08,Default,,0,0,0,,我写的MAP过程恰巧是一个递归过程\nDialogue: 0,0:26:13.82,0:26:17.06,Default,,0,0,0,,这是因为 你需要得到处理完表的剩余部分后的值\nDialogue: 0,0:26:17.08,0:26:20.96,Default,,0,0,0,,使其与表的开头部分相连\nDialogue: 0,0:26:21.73,0:26:24.53,Default,,0,0,0,,但是FOR-EACH不需要等待返回值\nDialogue: 0,0:26:24.84,0:26:26.66,Default,,0,0,0,,所以它变成了一个迭代的过程\nDialogue: 0,0:26:26.66,0:26:27.72,Default,,0,0,0,,这不是本质\nDialogue: 0,0:26:27.72,0:26:31.80,Default,,0,0,0,,我可以用迭代的方式定义MAP过程\nDialogue: 0,0:26:31.82,0:26:32.82,Default,,0,0,0,,只是我没那么做\nDialogue: 0,0:26:34.24,0:26:42.90,Default,,0,0,0,,学生：将FOR-EACH用在一个列表的列表上的话 我想这是可行的吧？\nDialogue: 0,0:26:42.90,0:26:48.10,Default,,0,0,0,,它会对这些内部列表的元素进行处理么？\nDialogue: 0,0:26:48.70,0:26:50.40,Default,,0,0,0,,教授：问题是 如果我调用\nDialogue: 0,0:26:50.40,0:26:52.28,Default,,0,0,0,,FOR-EACH或者MAP\nDialogue: 0,0:26:52.81,0:26:55.28,Default,,0,0,0,,参数是一个嵌套有一个表的表\nDialogue: 0,0:26:56.69,0:27:00.60,Default,,0,0,0,,虽然我们还没有讲过这个 但是那是可行的\nDialogue: 0,0:27:01.02,0:27:06.56,Default,,0,0,0,,答案是肯定的 不过我俩对“可行”的定义可能有些不同\nDialogue: 0,0:27:06.86,0:27:10.65,Default,,0,0,0,,来看一下 如果我给你一个表\nDialogue: 0,0:27:12.80,0:27:14.20,Default,,0,0,0,,而在个箭头所指的\nDialogue: 0,0:27:16.06,0:27:21.46,Default,,0,0,0,,不是一个数 而是一个表 或者序对 或者是其它东西\nDialogue: 0,0:27:21.96,0:27:24.54,Default,,0,0,0,,FOR-EACH对表中的每个元素做处理\nDialogue: 0,0:27:24.54,0:27:26.96,Default,,0,0,0,,它会不断地处理表CDR部分\nDialogue: 0,0:27:26.96,0:27:27.20,Default,,0,0,0,,学生：嗯\nDialogue: 0,0:27:27.20,0:27:31.06,Default,,0,0,0,,教授：对FOR-EACH来说 表中的第一个元素就是这个箭头所指的东西\nDialogue: 0,0:27:31.06,0:27:31.65,Default,,0,0,0,,学生：唔\nDialogue: 0,0:27:31.65,0:27:33.94,Default,,0,0,0,,教授：这对于你要完成的任务而言 也许是对的 也许不是\nDialogue: 0,0:27:33.94,0:27:35.57,Default,,0,0,0,,学生：所以不能进入子表中\nDialogue: 0,0:27:35.57,0:27:36.91,Default,,0,0,0,,教授：绝对不能\nDialogue: 0,0:27:36.91,0:27:38.51,Default,,0,0,0,,当然我也可以那样写程序\nDialogue: 0,0:27:38.51,0:27:42.97,Default,,0,0,0,,你所说的是另一种公共模式 叫做树递归\nDialogue: 0,0:27:43.01,0:27:47.94,Default,,0,0,0,,当你给它一个表 它会不断向深度递归 直到遇到所谓的“树叶”\nDialogue: 0,0:27:47.94,0:27:51.05,Default,,0,0,0,,你可以写出来这个过程 但是它既不是FOR-EACH也不是MAP\nDialogue: 0,0:27:52.42,0:27:55.05,Default,,0,0,0,,FOR-EACH和MAP都很简单\nDialogue: 0,0:27:55.77,0:27:56.89,Default,,0,0,0,,好 还有问题么？\nDialogue: 0,0:27:57.68,0:27:58.57,Default,,0,0,0,,好的 大家休息一下吧\nDialogue: 0,0:27:59.11,0:28:10.99,Default,,0,0,0,,[音乐]\nDialogue: 0,0:28:11.46,0:28:14.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:14.32,0:28:17.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:28:27.38,0:28:34.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:34.86,0:28:38.58,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson-Escher的例子\nDialogue: 0,0:28:41.94,0:28:48.65,Default,,0,0,0,,教授：我将在本节课余下的时间中 讨论一个实例\nDialogue: 0,0:28:50.04,0:28:53.92,Default,,0,0,0,,这个实例 可以充分地总结我们所学的所有东西\nDialogue: 0,0:28:54.74,0:28:56.29,Default,,0,0,0,,比如 表结构\nDialogue: 0,0:28:57.17,0:28:59.48,Default,,0,0,0,,以及抽象的技术\nDialogue: 0,0:28:59.54,0:29:00.82,Default,,0,0,0,,数据的表示\nDialogue: 0,0:29:01.60,0:29:04.60,Default,,0,0,0,,和用高阶过程描绘共性\nDialogue: 0,0:29:04.60,0:29:09.80,Default,,0,0,0,,也会介绍目前为止还没怎么谈论过的\nDialogue: 0,0:29:09.85,0:29:13.46,Default,,0,0,0,,也就是这门课的第三大主题\nDialogue: 0,0:29:13.96,0:29:15.53,Default,,0,0,0,,元语言抽象\nDialogue: 0,0:29:15.54,0:29:21.90,Default,,0,0,0,,这种在工程设计中控制复杂度的思想\nDialogue: 0,0:29:22.86,0:29:25.80,Default,,0,0,0,,也就是建立一个合适而强大的语言\nDialogue: 0,0:29:28.17,0:29:34.74,Default,,0,0,0,,你们或许记得 我说过在这门课程中 你们将要学到的最重要的事情是\nDialogue: 0,0:29:34.74,0:29:41.17,Default,,0,0,0,,当我们考察一门语言时 关心的是它的基本元素\nDialogue: 0,0:29:42.98,0:29:46.69,Default,,0,0,0,,关心它的组合方法\nDialogue: 0,0:29:49.72,0:29:52.80,Default,,0,0,0,,关心那些让你能够构建更大东西的东西\nDialogue: 0,0:29:53.61,0:29:55.24,Default,,0,0,0,,以及 抽象的方式\nDialogue: 0,0:30:00.97,0:30:05.16,Default,,0,0,0,,如何取用这些你构造出来的“大东西”\nDialogue: 0,0:30:05.56,0:30:07.97,Default,,0,0,0,,并将它们放入“黑盒”中\nDialogue: 0,0:30:08.45,0:30:11.71,Default,,0,0,0,,然后用它们来构建更复杂的东西\nDialogue: 0,0:30:13.53,0:30:18.72,Default,,0,0,0,,我将要介绍的一种语言 就是元语言抽象的一个例子\nDialogue: 0,0:30:18.73,0:30:22.70,Default,,0,0,0,,那是我朋友Peter Handerson发明的\nDialogue: 0,0:30:28.24,0:30:31.74,Default,,0,0,0,,他来自苏格兰的Stirling大学\nDialogue: 0,0:30:32.78,0:30:40.98,Default,,0,0,0,,这个语言是用来画这样的图\nDialogue: 0,0:30:41.86,0:30:46.66,Default,,0,0,0,,这是埃舍尔的木版画 《方形极限》\nDialogue: 0,0:30:49.33,0:30:57.94,Default,,0,0,0,,正如大家所见 这里面有着很复杂的...图像的递归\nDialogue: 0,0:30:58.84,0:31:01.46,Default,,0,0,0,,其中中间的鱼形图案以自相似的方式\nDialogue: 0,0:31:01.70,0:31:04.56,Default,,0,0,0,,不断地以更小的形式出现在原来的图案旁边\nDialogue: 0,0:31:08.49,0:31:12.80,Default,,0,0,0,,总之 Peter Hendersion的语言是用来表述这类图形\nDialogue: 0,0:31:13.37,0:31:18.28,Default,,0,0,0,,并且设计类似的图形 将它画在显示器上\nDialogue: 0,0:31:20.24,0:31:27.48,Default,,0,0,0,,这个例子还展示了另外一个主题\nDialogue: 0,0:31:28.09,0:31:32.02,Default,,0,0,0,,这也是我跟Gerry教授多次强调的\nDialogue: 0,0:31:32.02,0:31:36.17,Default,,0,0,0,,也就是过程跟数据之间没有本质的区别\nDialogue: 0,0:31:37.26,0:31:42.40,Default,,0,0,0,,不管如何 我希望今早课程结束后\nDialogue: 0,0:31:42.58,0:31:47.60,Default,,0,0,0,,你们能将过程和数据当作一回事儿\nDialogue: 0,0:31:47.96,0:31:49.58,Default,,0,0,0,,即使现在你们还将它们区别对待\nDialogue: 0,0:31:50.80,0:31:55.28,Default,,0,0,0,,那么 先让我们看一下Peter的语言\nDialogue: 0,0:31:55.28,0:31:57.26,Default,,0,0,0,,我先告诉你们基本元素是什么\nDialogue: 0,0:31:58.29,0:32:00.92,Default,,0,0,0,,这个语言非常简单 因为它的基本元素只有一个\nDialogue: 0,0:32:03.33,0:32:06.30,Default,,0,0,0,,这个基本元素不是大家想象的那样\nDialogue: 0,0:32:07.08,0:32:09.18,Default,,0,0,0,,它唯一的基本元素叫做\"图像\"\nDialogue: 0,0:32:09.70,0:32:12.11,Default,,0,0,0,,但此“图像”非彼“图像”\nDialogue: 0,0:32:12.11,0:32:14.17,Default,,0,0,0,,具体地来说\nDialogue: 0,0:32:14.17,0:32:15.17,Default,,0,0,0,,这是George的图像\nDialogue: 0,0:32:19.01,0:32:20.37,Default,,0,0,0,,我们的想法是\nDialogue: 0,0:32:22.33,0:32:24.57,Default,,0,0,0,,在这个语言中的图像是这样一个东西\nDialogue: 0,0:32:24.89,0:32:31.46,Default,,0,0,0,,它能在你指定的一个矩形里画出一个缩放好图像\nDialogue: 0,0:32:33.00,0:32:34.42,Default,,0,0,0,,这里大家看到的强调线\nDialogue: 0,0:32:34.42,0:32:37.70,Default,,0,0,0,,是这个矩形的轮廓 但不是图像的一部分\nDialogue: 0,0:32:40.49,0:32:47.17,Default,,0,0,0,,但是一旦指定一个矩形区域 图像会以以填充的方式绘制满区域\nDialogue: 0,0:32:47.17,0:32:52.16,Default,,0,0,0,,比如 这个是George 在这里 这个也是George\nDialogue: 0,0:32:53.21,0:32:56.65,Default,,0,0,0,,它是同一个图像 只是缩放程度不同\nDialogue: 0,0:32:57.40,0:32:59.28,Default,,0,0,0,,这是“胖”George的版本\nDialogue: 0,0:33:00.01,0:33:03.44,Default,,0,0,0,,这个也是George\nDialogue: 0,0:33:03.81,0:33:05.14,Default,,0,0,0,,这是同一个图形\nDialogue: 0,0:33:05.14,0:33:09.57,Default,,0,0,0,,这个语言中 这三个都是同一个图像\nDialogue: 0,0:33:09.58,0:33:13.04,Default,,0,0,0,,仅仅是给了不同的矩形区域让它来填充\nDialogue: 0,0:33:16.08,0:33:20.65,Default,,0,0,0,,这就是基本元素\nDialogue: 0,0:33:21.44,0:33:25.25,Default,,0,0,0,,现在 我们来讨论元素组合和操作\nDialogue: 0,0:33:25.90,0:33:30.17,Default,,0,0,0,,比如 这里有一个叫做旋转的操作\nDialogue: 0,0:33:31.09,0:33:33.66,Default,,0,0,0,,如果我有一个图像 “旋转”操作就是\nDialogue: 0,0:33:35.37,0:33:39.93,Default,,0,0,0,,先假定有一个里面有个“A”的矩形\nDialogue: 0,0:33:41.84,0:33:45.73,Default,,0,0,0,,而旋转90度的操作则会\nDialogue: 0,0:33:47.02,0:33:50.65,Default,,0,0,0,,在一个给定的矩形内 绘制同样的图像\nDialogue: 0,0:33:50.65,0:33:53.88,Default,,0,0,0,,但是 会缩放图像以适应矩形\nDialogue: 0,0:33:56.11,0:33:58.34,Default,,0,0,0,,这个就是旋转90度\nDialogue: 0,0:33:58.34,0:34:03.20,Default,,0,0,0,,另一个操作是“翻转” 可以水平翻转也可以竖直翻转\nDialogue: 0,0:34:04.77,0:34:06.00,Default,,0,0,0,,就是这些操作了\nDialogue: 0,0:34:06.01,0:34:10.40,Default,,0,0,0,,或者你可以把它们认为是组合一个元素的各种方式\nDialogue: 0,0:34:10.89,0:34:12.42,Default,,0,0,0,,我可以把它们混合起来\nDialogue: 0,0:34:13.44,0:34:15.54,Default,,0,0,0,,我们有一种叫BESIDE的操作\nDialogue: 0,0:34:16.46,0:34:24.78,Default,,0,0,0,,它做的事情是 给定两个图像A、B --\nDialogue: 0,0:34:29.02,0:34:33.25,Default,,0,0,0,,这里图像是指能在指定的矩形中画一个图案的东西 --\nDialogue: 0,0:34:34.05,0:34:36.51,Default,,0,0,0,,BESIDE将会做的事情\nDialogue: 0,0:34:37.85,0:34:44.08,Default,,0,0,0,,类似于调用(BESIDE A B S) 其中S是一个数\nDialogue: 0,0:34:45.34,0:34:48.08,Default,,0,0,0,,是一个在0到1之间的数\nDialogue: 0,0:34:50.51,0:34:52.57,Default,,0,0,0,,BESIDE绘制像这样的图像\nDialogue: 0,0:34:52.57,0:34:56.71,Default,,0,0,0,,以给定的矩形为基础 但会将基底缩放S\nDialogue: 0,0:34:56.71,0:34:58.71,Default,,0,0,0,,这里S是0.5\nDialogue: 0,0:35:00.18,0:35:07.17,Default,,0,0,0,,在这里 它会在这里画第一个图案\nDialogue: 0,0:35:07.81,0:35:12.65,Default,,0,0,0,,在这里画第二个图案\nDialogue: 0,0:35:13.82,0:35:16.44,Default,,0,0,0,,又比如说 我另设一个S的值\nDialogue: 0,0:35:16.81,0:35:23.02,Default,,0,0,0,,比如调用(BESIDE A B 0.25)\nDialogue: 0,0:35:25.94,0:35:29.09,Default,,0,0,0,,效果相同 只不过A更瘦了\nDialogue: 0,0:35:34.05,0:35:36.28,Default,,0,0,0,,而B是这样的\nDialogue: 0,0:35:37.82,0:35:40.29,Default,,0,0,0,,这就是组合方法之一：BESIDE\nDialogue: 0,0:35:40.68,0:35:46.05,Default,,0,0,0,,类似地 ABOVE方法在竖直方向上做这种操作\nDialogue: 0,0:35:47.84,0:35:48.89,Default,,0,0,0,,我们来看一下\nDialogue: 0,0:35:50.74,0:35:56.00,Default,,0,0,0,,这是George和他的\"弟弟\"\nDialogue: 0,0:35:56.72,0:36:07.05,Default,,0,0,0,,这是通过将George放在一旁\nDialogue: 0,0:36:10.36,0:36:14.42,Default,,0,0,0,,George与空图像的上下组合放在另一旁\nDialogue: 0,0:36:14.52,0:36:16.14,Default,,0,0,0,,这样做的意图很明显\nDialogue: 0,0:36:16.14,0:36:19.14,Default,,0,0,0,,空图像放在了另一个George的上面\nDialogue: 0,0:36:19.14,0:36:21.14,Default,,0,0,0,,合成的图像又放在了George的旁边\nDialogue: 0,0:36:28.96,0:36:30.34,Default,,0,0,0,,这个是图像P\nDialogue: 0,0:36:31.10,0:36:39.04,Default,,0,0,0,,像之前一样 是George和翻转后George的BESIDE组合\nDialogue: 0,0:36:40.53,0:36:42.08,Default,,0,0,0,,这里 我们做的是水平翻转\nDialogue: 0,0:36:42.37,0:36:44.80,Default,,0,0,0,,然后整体旋转180度\nDialogue: 0,0:36:45.80,0:36:50.82,Default,,0,0,0,,然后调用BESIDE让它们组合在一起 系数是0.5\nDialogue: 0,0:36:52.56,0:36:53.90,Default,,0,0,0,,这样 我创建了图像P\nDialogue: 0,0:36:55.90,0:36:57.88,Default,,0,0,0,,然后使用图像P\nDialogue: 0,0:36:59.21,0:37:04.96,Default,,0,0,0,,与它的翻转图像做ABOVE操作 形成图像Q\nDialogue: 0,0:37:09.20,0:37:13.26,Default,,0,0,0,,请注意 我们是如何快速地增加复杂度\nDialogue: 0,0:37:14.36,0:37:21.05,Default,,0,0,0,,转瞬之间 我们使用George组合得到了Q 这说明了什么？\nDialogue: 0,0:37:22.05,0:37:24.55,Default,,0,0,0,,为什么我们可以做得如此迅速呢?\nDialogue: 0,0:37:25.85,0:37:28.02,Default,,0,0,0,,答案是闭包性质\nDialogue: 0,0:37:28.69,0:37:32.98,Default,,0,0,0,,这是因为 当我将两个图像做BESIDE操作后\nDialogue: 0,0:37:34.30,0:37:35.29,Default,,0,0,0,,得到的也是图像\nDialogue: 0,0:37:35.33,0:37:37.78,Default,,0,0,0,,我可以继续执行 ROTATE FLIP 或者 ABOVE操作\nDialogue: 0,0:37:39.17,0:37:40.88,Default,,0,0,0,,而操作的结果P\nDialogue: 0,0:37:40.89,0:37:44.88,Default,,0,0,0,,BESIDE FLIP ROTATE操作的结果也是一个图像\nDialogue: 0,0:37:45.22,0:37:50.20,Default,,0,0,0,,在这种组合方法下 图像的世界是封闭的\nDialogue: 0,0:37:50.77,0:37:52.24,Default,,0,0,0,,所以 任何时候我都可以\nDialogue: 0,0:37:52.48,0:37:55.17,Default,,0,0,0,,以一个东西为基本元素 去构造别的东西\nDialogue: 0,0:37:56.33,0:37:58.52,Default,,0,0,0,,这个例子比表和线段更直观\nDialogue: 0,0:37:58.54,0:38:03.28,Default,,0,0,0,,它揭示了 我们如和用封闭的操作 快速增加复杂度\nDialogue: 0,0:38:07.48,0:38:12.02,Default,,0,0,0,,在构建更多东西之前\nDialogue: 0,0:38:12.04,0:38:14.77,Default,,0,0,0,,我们先来看看这个语言是如何实现的\nDialogue: 0,0:38:16.91,0:38:21.50,Default,,0,0,0,,其中基本的一个元素\nDialogue: 0,0:38:21.93,0:38:24.52,Default,,0,0,0,,是一个称作“矩形”的东西\nDialogue: 0,0:38:26.09,0:38:28.28,Default,,0,0,0,,所谓的矩形就是\nDialogue: 0,0:38:28.28,0:38:33.68,Default,,0,0,0,,它有一个原点\nDialogue: 0,0:38:36.45,0:38:40.18,Default,,0,0,0,,原点是一个向量 用以说明矩形是从哪开始\nDialogue: 0,0:38:40.18,0:38:42.29,Default,,0,0,0,,至于其它的向量\nDialogue: 0,0:38:43.66,0:38:46.33,Default,,0,0,0,,我们称其为矩形的水平分量\nDialogue: 0,0:38:55.76,0:38:59.25,Default,,0,0,0,,还有就是矩形的竖直分量\nDialogue: 0,0:39:00.49,0:39:02.68,Default,,0,0,0,,这就是构成矩形的三个基本元素\nDialogue: 0,0:39:02.68,0:39:04.51,Default,,0,0,0,,两个向量用作\nDialogue: 0,0:39:04.93,0:39:09.97,Default,,0,0,0,,计算左上角和右下角的顶点坐标\nDialogue: 0,0:39:09.97,0:39:12.37,Default,,0,0,0,,这三个向量确定了一个矩形\nDialogue: 0,0:39:16.00,0:39:18.93,Default,,0,0,0,,为了构建矩形 我们假设\nDialogue: 0,0:39:19.77,0:39:22.06,Default,,0,0,0,,假设有个“构建矩形”的构造函数\nDialogue: 0,0:39:23.01,0:39:24.26,Default,,0,0,0,,也就是MAKE-RECT\nDialogue: 0,0:39:27.56,0:39:35.17,Default,,0,0,0,,以及选择函数 HORIZ、VERT 和 ORIGIN\nDialogue: 0,0:39:37.58,0:39:39.65,Default,,0,0,0,,用于取得对应的矩形属性\nDialogue: 0,0:39:39.65,0:39:42.54,Default,,0,0,0,,我们知道有很多方法可以实现它\nDialogue: 0,0:39:42.54,0:39:47.62,Default,,0,0,0,,可以用序对或者表 或者其它东西\nDialogue: 0,0:39:47.62,0:39:51.40,Default,,0,0,0,,但是 这些东西的实现是George的事\nDialogue: 0,0:39:51.40,0:39:53.17,Default,,0,0,0,,这是一个数据表示的问题\nDialogue: 0,0:39:53.17,0:39:55.47,Default,,0,0,0,,现在我们假设已经有了这些矩形了\nDialogue: 0,0:39:59.05,0:40:05.08,Default,,0,0,0,,好的 现在来看我们接下来要做的事情\nDialogue: 0,0:40:05.08,0:40:08.22,Default,,0,0,0,,我们需要关心如何取用图像\nDialogue: 0,0:40:09.33,0:40:12.97,Default,,0,0,0,,将它缩放以适应你给定的矩形\nDialogue: 0,0:40:13.60,0:40:16.60,Default,,0,0,0,,我们要来安排这些事\nDialogue: 0,0:40:16.60,0:40:18.60,Default,,0,0,0,,来完成图像的缩放\nDialogue: 0,0:40:22.22,0:40:23.65,Default,,0,0,0,,有哪些思路呢？\nDialogue: 0,0:40:23.65,0:40:27.08,Default,,0,0,0,,一种想法是：无论何时给定一个矩形\nDialogue: 0,0:40:35.68,0:40:38.68,Default,,0,0,0,,无论何时给定一个矩形 也就是说\nDialogue: 0,0:40:39.25,0:40:45.77,Default,,0,0,0,,这在某种意义上是把正方形转换成矩形\nDialogue: 0,0:40:45.77,0:40:46.54,Default,,0,0,0,,也就是说\nDialogue: 0,0:40:46.54,0:40:48.53,Default,,0,0,0,,我所谓的正方形\nDialogue: 0,0:40:49.04,0:40:59.04,Default,,0,0,0,,它的坐标是(0,0)、(1,0)和(1,1)\nDialogue: 0,0:41:01.40,0:41:05.72,Default,,0,0,0,,我们有一些显而易见的缩放变换\nDialogue: 0,0:41:06.12,0:41:10.22,Default,,0,0,0,,可以把这个映射成这个 把这个映射成这个\nDialogue: 0,0:41:10.24,0:41:12.08,Default,,0,0,0,,并且 把所有的东西统一地拉伸\nDialogue: 0,0:41:12.17,0:41:18.25,Default,,0,0,0,,我们将这样的一条的线段\nDialogue: 0,0:41:19.73,0:41:24.20,Default,,0,0,0,,将它最终映射到像那样的一条线段\nDialogue: 0,0:41:26.20,0:41:32.68,Default,,0,0,0,,而点(X,Y)变成了这里的另外一个点\nDialogue: 0,0:41:32.68,0:41:39.37,Default,,0,0,0,,这个不打紧 会点儿向量运算 就能写出变换公式\nDialogue: 0,0:41:39.37,0:41:43.18,Default,,0,0,0,,初始点(X,Y)将会变换到的点的坐标是\nDialogue: 0,0:41:43.58,0:41:50.74,Default,,0,0,0,,以矩形原点为基础做向量加法\nDialogue: 0,0:41:51.16,0:41:55.48,Default,,0,0,0,,加上 初始点X坐标 一个介于0和1之间的值\nDialogue: 0,0:41:55.98,0:42:01.84,Default,,0,0,0,,并乘上矩形的水平向量\nDialogue: 0,0:42:07.62,0:42:11.00,Default,,0,0,0,,再加上初始点的Y坐标 也是一个介于0和1的值\nDialogue: 0,0:42:11.38,0:42:16.28,Default,,0,0,0,,并乘上矩形的竖直向量\nDialogue: 0,0:42:16.74,0:42:19.31,Default,,0,0,0,,这是简单的线性代数\nDialogue: 0,0:42:19.31,0:42:23.48,Default,,0,0,0,,这个就是正确的变换公式\nDialogue: 0,0:42:23.69,0:42:28.18,Default,,0,0,0,,它将方形中的物件转化到对应矩形中\nDialogue: 0,0:42:31.34,0:42:34.02,Default,,0,0,0,,现在 我们把它看作是一个过程\nDialogue: 0,0:42:35.16,0:42:36.29,Default,,0,0,0,,我们想要得到的是\nDialogue: 0,0:42:37.80,0:42:40.82,Default,,0,0,0,,由一个单位正方形到特定矩形的\nDialogue: 0,0:42:41.01,0:42:42.52,Default,,0,0,0,,特定变换过程\nDialogue: 0,0:42:43.80,0:42:45.22,Default,,0,0,0,,这个过程具体是这样的\nDialogue: 0,0:42:45.22,0:42:47.22,Default,,0,0,0,,我叫它COORD-MAP\nDialogue: 0,0:42:47.77,0:42:52.00,Default,,0,0,0,,COORD-MAP以一个矩形作为参数\nDialogue: 0,0:42:53.60,0:42:57.85,Default,,0,0,0,,它返回一个以点为参数的过程\nDialogue: 0,0:43:00.45,0:43:06.82,Default,,0,0,0,,每个矩形 都对应一个变换点(X, Y)坐标的过程\nDialogue: 0,0:43:06.82,0:43:08.02,Default,,0,0,0,,是怎么得到的呢？\nDialogue: 0,0:43:08.02,0:43:10.92,Default,,0,0,0,,就如黑板上的Lisp代码所示\nDialogue: 0,0:43:10.92,0:43:16.01,Default,,0,0,0,,我让矩形的原点加上--\nDialogue: 0,0:43:20.22,0:43:25.02,Default,,0,0,0,,首先是 矩形水平部分\nDialogue: 0,0:43:25.02,0:43:27.68,Default,,0,0,0,,按照点POINT的X坐标缩放\nDialogue: 0,0:43:29.65,0:43:32.62,Default,,0,0,0,,然后是 矩形竖直部分\nDialogue: 0,0:43:33.51,0:43:37.14,Default,,0,0,0,,按照点POINT的Y坐标缩放\nDialogue: 0,0:43:37.14,0:43:39.14,Default,,0,0,0,,然后把它们三个加到一起\nDialogue: 0,0:43:40.13,0:43:41.34,Default,,0,0,0,,这个过程就是这样\nDialogue: 0,0:43:41.34,0:43:44.54,Default,,0,0,0,,这就是我将要应用在点POINT上的过程\nDialogue: 0,0:43:46.54,0:43:52.17,Default,,0,0,0,,这个过程由每个矩形自己生成\nDialogue: 0,0:43:52.17,0:43:57.25,Default,,0,0,0,,每个矩形对应了一个定义在点集上的过程 COORD-MAP\nDialogue: 0,0:44:06.66,0:44:10.42,Default,,0,0,0,,比如说 这里的George\nDialogue: 0,0:44:11.36,0:44:16.34,Default,,0,0,0,,最初的George 可能是我在单位正方形中通过线段绘制的\nDialogue: 0,0:44:19.50,0:44:21.96,Default,,0,0,0,,而当我把它应用到一个新的矩形中\nDialogue: 0,0:44:24.14,0:44:28.17,Default,,0,0,0,,我将会在新矩形中画出组成George的那些线段来\nDialogue: 0,0:44:28.17,0:44:29.88,Default,,0,0,0,,我是怎么做的呢？\nDialogue: 0,0:44:30.68,0:44:36.94,Default,,0,0,0,,我枚举原始George中的每条线段\nDialogue: 0,0:44:38.64,0:44:40.58,Default,,0,0,0,,我对每条线段的终点\nDialogue: 0,0:44:40.88,0:44:44.45,Default,,0,0,0,,应用目标矩形对应的COORD-MAP过程\nDialogue: 0,0:44:44.45,0:44:46.06,Default,,0,0,0,,比如下面的这个矩形\nDialogue: 0,0:44:46.66,0:44:50.88,Default,,0,0,0,,这个胖George 有它对应的COORD-MAP\nDialogue: 0,0:44:51.25,0:44:53.69,Default,,0,0,0,,如果我要绘制这个图像\nDialogue: 0,0:44:55.38,0:44:57.92,Default,,0,0,0,,需要做的就是对这里的每条线段 比如这条\nDialogue: 0,0:44:59.29,0:45:05.34,Default,,0,0,0,,用COORD-MAP变换这个点 同时变换这个点\nDialogue: 0,0:45:05.34,0:45:07.09,Default,,0,0,0,,我就得到了这两个点\nDialogue: 0,0:45:07.38,0:45:08.94,Default,,0,0,0,,就可以将在两点之间画线\nDialogue: 0,0:45:09.71,0:45:11.52,Default,,0,0,0,,这就是核心思路\nDialogue: 0,0:45:12.66,0:45:14.78,Default,,0,0,0,,那么如果我给一个不同的矩形 比如这个\nDialogue: 0,0:45:14.80,0:45:15.76,Default,,0,0,0,,得到的是不同的COORD-MAP\nDialogue: 0,0:45:15.79,0:45:17.84,Default,,0,0,0,,因此我得到这些线段的不同图像\nDialogue: 0,0:45:19.28,0:45:22.14,Default,,0,0,0,,基本图像又该如何表示呢？\nDialogue: 0,0:45:22.14,0:45:26.52,Default,,0,0,0,,可以用线段组成的表来表示\nDialogue: 0,0:45:27.61,0:45:32.20,Default,,0,0,0,,这是用于构建我所谓的“基本图像”的过程\nDialogue: 0,0:45:33.48,0:45:37.17,Default,,0,0,0,,意思是 没有用BESIDE ROTATE等操作\nDialogue: 0,0:45:37.52,0:45:39.60,Default,,0,0,0,,它以由线段组成的表为参数\nDialogue: 0,0:45:42.94,0:45:44.04,Default,,0,0,0,,代码具体行为如下\nDialogue: 0,0:45:44.04,0:45:45.58,Default,,0,0,0,,图像会是什么样子呢？\nDialogue: 0,0:45:45.58,0:45:49.44,Default,,0,0,0,,首先 它是一个根据矩形定义的过程\nDialogue: 0,0:45:51.70,0:45:53.00,Default,,0,0,0,,这个过程做什么呢？\nDialogue: 0,0:45:53.00,0:45:56.56,Default,,0,0,0,,对于由线段组成的表中每个元素\nDialogue: 0,0:45:57.66,0:46:03.38,Default,,0,0,0,,表中的每条线段S\nDialogue: 0,0:46:05.89,0:46:07.30,Default,,0,0,0,,都绘制了一条线\nDialogue: 0,0:46:07.30,0:46:08.82,Default,,0,0,0,,它画什么样的线段呢？\nDialogue: 0,0:46:10.60,0:46:12.84,Default,,0,0,0,,先得到线段的起点\nDialogue: 0,0:46:15.22,0:46:17.94,Default,,0,0,0,,用对应的COORD-MAP对其做变换\nDialogue: 0,0:46:19.54,0:46:21.76,Default,,0,0,0,,这是我们想要的第一个点\nDialogue: 0,0:46:21.76,0:46:26.32,Default,,0,0,0,,然后对线段终点做COORD-MAP操作\nDialogue: 0,0:46:26.69,0:46:27.92,Default,,0,0,0,,并将两点连线\nDialogue: 0,0:46:27.92,0:46:30.84,Default,,0,0,0,,我们假设在屏幕上绘制线段是基本操作\nDialogue: 0,0:46:31.09,0:46:33.22,Default,,0,0,0,,已经在系统中实现了\nDialogue: 0,0:46:33.96,0:46:37.10,Default,,0,0,0,,通过COORD-MAP变换了线段终点\nDialogue: 0,0:46:37.13,0:46:38.20,Default,,0,0,0,,再把起点和终点连线\nDialogue: 0,0:46:39.61,0:46:44.12,Default,,0,0,0,,对表中每一条线段S都执行这样的操作\nDialogue: 0,0:46:45.96,0:46:51.40,Default,,0,0,0,,请注意 图像就是一个以矩形为参数的过程\nDialogue: 0,0:46:51.40,0:46:55.65,Default,,0,0,0,,所以当你给图像一个矩形时 它就像这样绘制线段\nDialogue: 0,0:46:57.17,0:47:01.10,Default,,0,0,0,,那好 我应该如何使用它呢？\nDialogue: 0,0:47:01.22,0:47:04.08,Default,,0,0,0,,我来说得具体一点\nDialogue: 0,0:47:05.60,0:47:24.22,Default,,0,0,0,,就比如说 (DEFINE R (MAKE-RECT ...))\nDialogue: 0,0:47:24.50,0:47:28.66,Default,,0,0,0,,这里需要用MAKE-VECTOR来构造一些向量\nDialogue: 0,0:47:29.84,0:47:46.18,Default,,0,0,0,,然后定义G为 (DEFINE G (MAKE-PICT ...))\nDialogue: 0,0:47:46.68,0:47:55.28,Default,,0,0,0,,我要在这里使用MAKE-SEGMENT来构建线段组成的表\nDialogue: 0,0:47:55.28,0:47:58.70,Default,,0,0,0,,MAKE-SEGMENT由向量构成 向量由点构成\nDialogue: 0,0:47:59.50,0:48:04.60,Default,,0,0,0,,如果我想在一个矩形中呈现图像G\nDialogue: 0,0:48:04.65,0:48:11.72,Default,,0,0,0,,注意 图像是一个过程 它接受一个矩形作为参数\nDialogue: 0,0:48:12.06,0:48:16.37,Default,,0,0,0,,所以 如果我调用(G R)\nDialogue: 0,0:48:17.96,0:48:23.25,Default,,0,0,0,,那么无论G是什么 都会在矩形R中绘制出来\nDialogue: 0,0:48:23.62,0:48:25.62,Default,,0,0,0,,这就是我们如何使用它\nDialogue: 0,0:48:26.86,0:48:36.29,Default,,0,0,0,,[音乐]\nDialogue: 0,0:48:36.29,0:48:39.78,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:39.82,0:48:43.54,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:48:51.28,0:48:55.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:55.50,0:48:58.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:48:59.34,0:49:03.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson-Escher的例子\nDialogue: 0,0:49:07.72,0:49:12.48,Default,,0,0,0,,教授：为什么我说这个例子很好呢？\nDialogue: 0,0:49:12.48,0:49:13.74,Default,,0,0,0,,也许你们不这么认为\nDialogue: 0,0:49:13.74,0:49:15.42,Default,,0,0,0,,你们可能觉得它很奇怪\nDialogue: 0,0:49:15.42,0:49:20.92,Default,,0,0,0,,用来矩形做复杂变换的过程来表示图像 确实奇怪\nDialogue: 0,0:49:20.92,0:49:22.72,Default,,0,0,0,,那么 它好在哪里呢？\nDialogue: 0,0:49:25.36,0:49:26.69,Default,,0,0,0,,原因就是\nDialogue: 0,0:49:27.22,0:49:30.40,Default,,0,0,0,,一旦你按这种方法实现了基本元素\nDialogue: 0,0:49:30.97,0:49:35.20,Default,,0,0,0,,组合的方法就是构造Lisp过程\nDialogue: 0,0:49:35.98,0:49:37.48,Default,,0,0,0,,我给你们演示一下\nDialogue: 0,0:49:37.48,0:49:39.02,Default,,0,0,0,,假设我想实现BESIDE\nDialogue: 0,0:49:41.56,0:49:47.36,Default,,0,0,0,,我要做的是 假设有个叫P1的图像\nDialogue: 0,0:49:47.36,0:49:50.62,Default,,0,0,0,,一定要记得：图像本质上是一个过程\nDialogue: 0,0:49:50.62,0:49:54.82,Default,,0,0,0,,当你传递给它一个矩形\nDialogue: 0,0:49:56.52,0:50:01.46,Default,,0,0,0,,它会在你给定的矩形中绘制图形\nDialogue: 0,0:50:03.46,0:50:09.26,Default,,0,0,0,,假设P2是另一个图像 你传递给它一个矩形\nDialogue: 0,0:50:09.74,0:50:12.44,Default,,0,0,0,,无论给它什么矩形 它都会绘制一些图案\nDialogue: 0,0:50:14.84,0:50:26.60,Default,,0,0,0,,现在 我想实现(BESIDE P1 P2 A) A是缩放因子\nDialogue: 0,0:50:27.04,0:50:28.38,Default,,0,0,0,,会得到什么呢？\nDialogue: 0,0:50:28.38,0:50:29.34,Default,,0,0,0,,我们会得到一个图像\nDialogue: 0,0:50:29.92,0:50:33.88,Default,,0,0,0,,也就是说你传给它一个矩形 它就会在其中绘图\nDialogue: 0,0:50:34.77,0:50:37.18,Default,,0,0,0,,如果我们在一个矩形中执行BESIDE操作\nDialogue: 0,0:50:38.58,0:50:40.12,Default,,0,0,0,,比如这个矩形\nDialogue: 0,0:50:41.50,0:50:42.74,Default,,0,0,0,,要做什么呢？\nDialogue: 0,0:50:42.76,0:50:46.36,Default,,0,0,0,,这将把矩形切分为两部分\nDialogue: 0,0:50:49.29,0:50:51.57,Default,,0,0,0,,一部分比例是A 另一部分是1-A\nDialogue: 0,0:50:52.65,0:50:55.12,Default,,0,0,0,,现在 我们就有了两个矩形\nDialogue: 0,0:51:02.34,0:51:06.54,Default,,0,0,0,,然后先让P1在这个矩形中绘制\nDialogue: 0,0:51:07.36,0:51:11.64,Default,,0,0,0,,然后让P2在这个矩形中绘制\nDialogue: 0,0:51:13.28,0:51:16.88,Default,,0,0,0,,BESIDE仅仅需要计算出这些矩形来\nDialogue: 0,0:51:17.36,0:51:23.97,Default,,0,0,0,,由于矩形是由原点、水平向量和竖直向量组成\nDialogue: 0,0:51:23.98,0:51:25.94,Default,,0,0,0,,BESIDE操作需要计算出这些要素\nDialogue: 0,0:51:27.37,0:51:32.29,Default,,0,0,0,,所以对第一个矩形来说 原点变成了矩形的原点\nDialogue: 0,0:51:33.64,0:51:37.80,Default,,0,0,0,,竖直向量与原矩形相同 不发生变化\nDialogue: 0,0:51:38.89,0:51:46.60,Default,,0,0,0,,水平向量是原始矩形的水平向量缩放A倍得到的\nDialogue: 0,0:51:47.49,0:51:48.90,Default,,0,0,0,,这就是第一个矩形\nDialogue: 0,0:51:49.46,0:51:52.69,Default,,0,0,0,,第二个矩形的原点是\nDialogue: 0,0:51:54.06,0:51:59.65,Default,,0,0,0,,原矩形的原点加上矩形的水平向量缩放A倍\nDialogue: 0,0:52:01.20,0:52:03.40,Default,,0,0,0,,第二个矩形的水平向量是\nDialogue: 0,0:52:03.77,0:52:06.04,Default,,0,0,0,,除去前一个矩形水平向量所余下的部分\nDialogue: 0,0:52:06.34,0:52:11.66,Default,,0,0,0,,也就是(1-A)*H H是原矩形的水平向量\nDialogue: 0,0:52:12.05,0:52:13.77,Default,,0,0,0,,它的竖直向量还是V\nDialogue: 0,0:52:15.48,0:52:17.98,Default,,0,0,0,,基本上 BESIDE就是构造这两个矩形\nDialogue: 0,0:52:18.00,0:52:20.57,Default,,0,0,0,,但重要的是 一旦构造好这些矩形\nDialogue: 0,0:52:20.93,0:52:24.58,Default,,0,0,0,,它就能让P1、P2在正确的位置绘制\nDialogue: 0,0:52:24.62,0:52:26.18,Default,,0,0,0,,这就是BESIDE需要做的全部工作\nDialogue: 0,0:52:27.80,0:52:29.30,Default,,0,0,0,,我们看一下代码\nDialogue: 0,0:52:34.33,0:52:35.13,Default,,0,0,0,,这是BESIDE\nDialogue: 0,0:52:39.64,0:52:46.44,Default,,0,0,0,,(BESIDE P1 P2 A) A是缩放比例\nDialogue: 0,0:52:47.84,0:52:53.64,Default,,0,0,0,,因为该过程返回图像 所以结果是一个以矩形为参数的过程\nDialogue: 0,0:52:55.49,0:52:56.56,Default,,0,0,0,,它做什么呢？\nDialogue: 0,0:52:56.76,0:53:02.32,Default,,0,0,0,,它让P1在某个矩形中绘制 P2在另一个矩形中绘制\nDialogue: 0,0:53:03.21,0:53:04.46,Default,,0,0,0,,现在这些矩形又是什么呢?\nDialogue: 0,0:53:04.46,0:53:05.48,Default,,0,0,0,,就在这里计算\nDialogue: 0,0:53:05.48,0:53:06.54,Default,,0,0,0,,它创建了一个矩形\nDialogue: 0,0:53:07.52,0:53:10.40,Default,,0,0,0,,用的是我刚才在黑板上写的几何公式 这是矩形的原点\nDialogue: 0,0:53:10.40,0:53:11.84,Default,,0,0,0,,矩形的水平向量\nDialogue: 0,0:53:11.84,0:53:13.44,Default,,0,0,0,,还有矩形的竖直向量\nDialogue: 0,0:53:13.97,0:53:14.81,Default,,0,0,0,,对于P2\nDialogue: 0,0:53:15.50,0:53:19.78,Default,,0,0,0,,矩形需要不同的原点 水平向量和竖直向量\nDialogue: 0,0:53:19.78,0:53:20.70,Default,,0,0,0,,但重要的是\nDialogue: 0,0:53:21.21,0:53:27.18,Default,,0,0,0,,BESIDE只是将这两个矩形分别传递给了P1和P2而已\nDialogue: 0,0:53:27.74,0:53:29.42,Default,,0,0,0,,这就是BESIDE所需要做的\nDialogue: 0,0:53:30.84,0:53:35.62,Default,,0,0,0,,好 ROTATE也很类似\nDialogue: 0,0:53:36.96,0:53:42.00,Default,,0,0,0,,假设我有一个图像A\nDialogue: 0,0:53:42.97,0:53:46.12,Default,,0,0,0,,我想让它旋转90度\nDialogue: 0,0:53:46.37,0:53:51.92,Default,,0,0,0,,这意味着 给定这个矩形\nDialogue: 0,0:53:53.94,0:53:58.44,Default,,0,0,0,,它有原点、水平向量和竖直向量\nDialogue: 0,0:53:58.78,0:54:03.18,Default,,0,0,0,,现在假设已经有了这样的矩形\nDialogue: 0,0:54:03.74,0:54:09.12,Default,,0,0,0,,这个矩形的原点、水平向量和竖直向量在这里\nDialogue: 0,0:54:09.60,0:54:12.46,Default,,0,0,0,,然后在矩形里各自绘制自己\nDialogue: 0,0:54:13.26,0:54:15.04,Default,,0,0,0,,我们来看看代码\nDialogue: 0,0:54:17.02,0:54:19.85,Default,,0,0,0,,那么 ROTATE90过程\nDialogue: 0,0:54:20.61,0:54:22.96,Default,,0,0,0,,返回的也是一个以矩形为参数的过程\nDialogue: 0,0:54:23.25,0:54:26.12,Default,,0,0,0,,它就是将图像绘制在一个特定矩形中\nDialogue: 0,0:54:27.21,0:54:30.66,Default,,0,0,0,,这个几何公式就是这个矩形的变换规则\nDialogue: 0,0:54:30.66,0:54:33.84,Default,,0,0,0,,这句代码让矩形看起来像向侧面的\nDialogue: 0,0:54:33.86,0:54:36.52,Default,,0,0,0,,原点在别的地方 竖直向量在别的地方\nDialogue: 0,0:54:37.13,0:54:39.74,Default,,0,0,0,,水平向量在别的地方 竖直向量在别的地方\nDialogue: 0,0:54:46.76,0:54:49.90,Default,,0,0,0,,再次注意 这里的关键是\nDialogue: 0,0:54:50.53,0:55:00.97,Default,,0,0,0,,关键是使用过程来表示图像 使其自动地具有闭包性质\nDialogue: 0,0:55:01.74,0:55:05.22,Default,,0,0,0,,这是因为 实际上 BESIDE只是接受并使用P1\nDialogue: 0,0:55:05.22,0:55:09.40,Default,,0,0,0,,BESIDE并不关心它是一个基本图像还是一些线段\nDialogue: 0,0:55:09.61,0:55:12.69,Default,,0,0,0,,或者P1还是ABOVE、BESIDE、ROTATE等操作的结果\nDialogue: 0,0:55:12.72,0:55:16.08,Default,,0,0,0,,关于P1 BESIDE需要知道的就是\nDialogue: 0,0:55:16.29,0:55:19.73,Default,,0,0,0,,给P1传递一个矩形 就会导致某物的绘制\nDialogue: 0,0:55:21.04,0:55:25.98,Default,,0,0,0,,在这个层面上 BESIDE并不关心P1是如何完成绘制\nDialogue: 0,0:55:27.73,0:55:32.25,Default,,0,0,0,,我们使用过程来表示图像 以保持它的闭包性质\nDialogue: 0,0:55:35.64,0:55:40.81,Default,,0,0,0,,将图像实现为过程 使得组合的方法变得\nDialogue: 0,0:55:41.18,0:55:43.93,Default,,0,0,0,,变得简单而优雅\nDialogue: 0,0:55:45.92,0:55:48.22,Default,,0,0,0,,但这并不是点睛之笔\nDialogue: 0,0:55:49.28,0:55:53.52,Default,,0,0,0,,点睛之笔来自于这门语言中抽象的方法\nDialogue: 0,0:55:54.70,0:55:56.24,Default,,0,0,0,,我们做了些什么？\nDialogue: 0,0:55:56.24,0:56:03.72,Default,,0,0,0,,我们把组合的方法实现为了过程\nDialogue: 0,0:56:05.85,0:56:09.38,Default,,0,0,0,,这也就意味着 当我们对这个语言进行抽象时\nDialogue: 0,0:56:10.17,0:56:15.69,Default,,0,0,0,,Lisp提供的 操作过程的一切方法\nDialogue: 0,0:56:16.33,0:56:21.45,Default,,0,0,0,,都可以自动地在这个图像语言中使用\nDialogue: 0,0:56:21.92,0:56:29.74,Default,,0,0,0,,与其用术语“这个语言以Lisp实现” — 虽然确实如此\nDialogue: 0,0:56:29.76,0:56:32.58,Default,,0,0,0,,我想描述为“这个语言嵌入于Lisp”\nDialogue: 0,0:56:37.64,0:56:42.08,Default,,0,0,0,,也就是说 通过像这样将语言嵌入\nDialogue: 0,0:56:42.90,0:56:48.86,Default,,0,0,0,,可以以扩展的形式 自动地获得Lisp的所有力量\nDialogue: 0,0:56:50.06,0:56:51.68,Default,,0,0,0,,这又是什么意思呢？\nDialogue: 0,0:56:51.97,0:57:02.94,Default,,0,0,0,,举个例子 假设我想用A B C D四副图像做东西\nDialogue: 0,0:57:03.76,0:57:07.06,Default,,0,0,0,,让它们呈现像这样的格局\nDialogue: 0,0:57:12.50,0:57:16.96,Default,,0,0,0,,可以将其称为FOUR-PICT格局\nDialogue: 0,0:57:16.96,0:57:17.70,Default,,0,0,0,,我该如何做呢？\nDialogue: 0,0:57:17.70,0:57:18.68,Default,,0,0,0,,我可以很容易的做到这些\nDialogue: 0,0:57:18.68,0:57:23.33,Default,,0,0,0,,写个过程 让B和D做ABOVE\nDialogue: 0,0:57:24.13,0:57:25.85,Default,,0,0,0,,A和C做ABOVE\nDialogue: 0,0:57:26.09,0:57:27.70,Default,,0,0,0,,得到的结果做BESIDE\nDialogue: 0,0:57:28.24,0:57:31.82,Default,,0,0,0,,我自然地拥有Lisp组合过程的能力\nDialogue: 0,0:57:32.92,0:57:35.82,Default,,0,0,0,,这不需要我为图像语言做些特殊处理\nDialogue: 0,0:57:35.82,0:57:39.92,Default,,0,0,0,,事实上 这些组合本身就是过程\nDialogue: 0,0:57:40.96,0:57:44.18,Default,,0,0,0,,假设我想做一些更复杂的事情\nDialogue: 0,0:57:44.18,0:57:46.50,Default,,0,0,0,,我想为这里的每一个传递一个参数\nDialogue: 0,0:57:46.52,0:57:50.08,Default,,0,0,0,,我可以独立地做旋转90度的操作\nDialogue: 0,0:57:50.41,0:57:52.64,Default,,0,0,0,,这只需要我在这个过程中加入一个参数\nDialogue: 0,0:57:53.17,0:57:54.56,Default,,0,0,0,,它自然而然就有了这样的功能\nDialogue: 0,0:57:54.80,0:57:57.84,Default,,0,0,0,,它自动地嵌入进去了\nDialogue: 0,0:57:58.16,0:58:05.36,Default,,0,0,0,,甚至 假设我想使用递归\nDialogue: 0,0:58:06.16,0:58:10.78,Default,,0,0,0,,我们看一下图像递归组合的方法\nDialogue: 0,0:58:10.78,0:58:14.64,Default,,0,0,0,,定义--看看你们能理解这个不\nDialogue: 0,0:58:14.69,0:58:18.97,Default,,0,0,0,,(DEFINE (RIGHT-PUSH PICT N A))\nDialogue: 0,0:58:22.84,0:58:29.80,Default,,0,0,0,,RIGHT-PUSH需要图片P 整数N和缩放因数A\nDialogue: 0,0:58:31.46,0:58:41.22,Default,,0,0,0,,定义是：如果N为0 那么返回图像P\nDialogue: 0,0:58:42.20,0:58:54.02,Default,,0,0,0,,否则 就-- 哦 这里是P\nDialogue: 0,0:58:55.88,0:59:00.21,Default,,0,0,0,,否则 我用图形P做BESIDE操作\nDialogue: 0,0:59:00.92,0:59:18.30,Default,,0,0,0,,BESIDE的另一个操作数是(RIGHT-PUSH P (- N 1) A)的结果\nDialogue: 0,0:59:24.72,0:59:31.12,Default,,0,0,0,,如果N为0 就返回P 否则就对P进行A倍缩放\nDialogue: 0,0:59:31.12,0:59:32.80,Default,,0,0,0,,抱歉 我这里代码没对齐\nDialogue: 0,0:59:33.66,0:59:38.50,Default,,0,0,0,,递归地调用(RIGHT-PUSH P (- N 1) A) 将结果用BESIDE连接\nDialogue: 0,0:59:38.50,0:59:42.00,Default,,0,0,0,,这就是一种递归组合方法\nDialogue: 0,0:59:43.78,0:59:44.76,Default,,0,0,0,,调用的结果会是怎样的？\nDialogue: 0,0:59:44.76,0:59:45.90,Default,,0,0,0,,我们来看看\nDialogue: 0,0:59:46.04,0:59:56.04,Default,,0,0,0,,这是(RIGHT-PUSH GEORGE 2 0.75)的结果\nDialogue: 0,0:59:59.26,1:00:00.72,Default,,0,0,0,,这个是从什么地方来的呢？\nDialogue: 0,1:00:00.72,1:00:02.34,Default,,0,0,0,,我是如何想象出这些递归来的呢？\nDialogue: 0,1:00:02.34,1:00:05.24,Default,,0,0,0,,答案是无意识的 绝对是无意识的\nDialogue: 0,1:00:05.24,1:00:09.80,Default,,0,0,0,,由于它们都是过程 而嵌入的目标系统中允许定义递归过程\nDialogue: 0,1:00:10.36,1:00:11.68,Default,,0,0,0,,我不必自己去做\nDialogue: 0,1:00:13.56,1:00:16.42,Default,,0,0,0,,当然 我们可以模仿这个方法做些更复杂的事\nDialogue: 0,1:00:16.42,1:00:18.21,Default,,0,0,0,,我可以定义做UP-PUSH的过程\nDialogue: 0,1:00:18.42,1:00:22.60,Default,,0,0,0,,对 它可以递归地把图片放在原来的上面\nDialogue: 0,1:00:22.60,1:00:26.54,Default,,0,0,0,,我也可以用这种策略来做些其它事\nDialogue: 0,1:00:26.56,1:00:28.85,Default,,0,0,0,,给定一个图像\nDialogue: 0,1:00:29.78,1:00:37.16,Default,,0,0,0,,然后递归地把它放在原图片的旁边和上面\nDialogue: 0,1:00:37.57,1:00:38.92,Default,,0,0,0,,这里再放一些别的\nDialogue: 0,1:00:39.52,1:00:41.82,Default,,0,0,0,,然后我把同样递归的图像放在这里\nDialogue: 0,1:00:42.36,1:00:44.20,Default,,0,0,0,,我可以用这个来终止\nDialogue: 0,1:00:45.40,1:00:52.50,Default,,0,0,0,,这个过程比RIGHT-PUSH复杂一点 但也不算太多\nDialogue: 0,1:00:53.64,1:00:58.14,Default,,0,0,0,,在BESIDE的基础上 我多加了一个ABOVE操作\nDialogue: 0,1:01:01.12,1:01:06.78,Default,,0,0,0,,如果我把它应用于四张放在一起的图像上\nDialogue: 0,1:01:07.53,1:01:08.65,Default,,0,0,0,,这样做当然没问题\nDialogue: 0,1:01:09.01,1:01:14.17,Default,,0,0,0,,我把它应用于我们之前定义的Q上\nDialogue: 0,1:01:15.97,1:01:18.73,Default,,0,0,0,,我得到的是这个玩意儿\nDialogue: 0,1:01:20.14,1:01:25.26,Default,,0,0,0,,\"图像Q的方形极限\" 做了两次\nDialogue: 0,1:01:28.18,1:01:32.25,Default,,0,0,0,,好 现在我们将其与Escher的\"方形极限\"对比一下\nDialogue: 0,1:01:32.88,1:01:34.53,Default,,0,0,0,,可以看到 这都是基于同样的思想\nDialogue: 0,1:01:34.74,1:01:36.94,Default,,0,0,0,,当然 Escher的图像更加漂亮一些\nDialogue: 0,1:01:36.94,1:01:44.04,Default,,0,0,0,,如果我们回过头审视George\nDialogue: 0,1:01:44.38,1:01:47.37,Default,,0,0,0,,我最开始用的是非常随意的设计\nDialogue: 0,1:01:47.42,1:01:49.26,Default,,0,0,0,,用了George的图像 做了一些操作\nDialogue: 0,1:01:51.22,1:01:53.14,Default,,0,0,0,,我们再看看Escher的图片\nDialogue: 0,1:01:54.08,1:01:56.14,Default,,0,0,0,,Escher的图片不是随意设计的\nDialogue: 0,1:01:56.14,1:01:57.66,Default,,0,0,0,,这个图案非常精妙\nDialogue: 0,1:01:57.89,1:02:00.20,Default,,0,0,0,,当我们把鱼身\nDialogue: 0,1:02:01.82,1:02:04.97,Default,,0,0,0,,把鱼身旋转并放缩 就会优美地变成下一条鱼\nDialogue: 0,1:02:07.40,1:02:11.48,Default,,0,0,0,,当然我没有刻意处理过George\nDialogue: 0,1:02:12.12,1:02:13.90,Default,,0,0,0,,就图像George来说\nDialogue: 0,1:02:15.41,1:02:18.64,Default,,0,0,0,,也有一些地方匹配 但不够好 比较随意\nDialogue: 0,1:02:18.64,1:02:21.53,Default,,0,0,0,,顺便说下 一个好的程序\nDialogue: 0,1:02:22.30,1:02:27.54,Default,,0,0,0,,应该有个过程 能接受像这里George一样的基本图像\nDialogue: 0,1:02:27.86,1:02:29.62,Default,,0,0,0,,然后调整其中的线段终点\nDialogue: 0,1:02:29.86,1:02:31.20,Default,,0,0,0,,这样可以得到一个好看的图像\nDialogue: 0,1:02:32.13,1:02:34.06,Default,,0,0,0,,在做“方形极限”应该注意这些\nDialogue: 0,1:02:34.68,1:02:36.30,Default,,0,0,0,,这是一个非常值得思考的事情\nDialogue: 0,1:02:38.08,1:02:39.72,Default,,0,0,0,,同时 我还可以进行组合\nDialogue: 0,1:02:39.72,1:02:41.04,Default,,0,0,0,,我们还可以使用递归过程\nDialogue: 0,1:02:41.04,1:02:43.48,Default,,0,0,0,,我们可以自然而然地做任何事情\nDialogue: 0,1:02:44.60,1:02:48.52,Default,,0,0,0,,重点在于 在语言中实际实现另一个语言\nDialogue: 0,1:02:48.69,1:02:50.44,Default,,0,0,0,,在语言中嵌入另一个语言的差异\nDialogue: 0,1:02:50.44,1:02:53.72,Default,,0,0,0,,这可以让你不丢失原有语言的能力 而Lisp强大之处在于\nDialogue: 0,1:02:54.76,1:02:57.62,Default,,0,0,0,,Lisp是一个强悍的语言 可以处理任何特定问题\nDialogue: 0,1:02:57.62,1:03:02.10,Default,,0,0,0,,把你想要的语言嵌入到Lisp中才是真的好\nDialogue: 0,1:03:02.10,1:03:05.44,Default,,0,0,0,,这才是这种设计方法的真正力量\nDialogue: 0,1:03:05.69,1:03:06.82,Default,,0,0,0,,我们可以深入一下\nDialogue: 0,1:03:06.82,1:03:08.81,Default,,0,0,0,,在Lisp中我们还可以做些其它的事\nDialogue: 0,1:03:09.21,1:03:17.52,Default,,0,0,0,,就是将通用方法抽象成高阶过程\nDialogue: 0,1:03:19.09,1:03:22.57,Default,,0,0,0,,在我画那些图像时 你们可能已经发现\nDialogue: 0,1:03:23.78,1:03:26.61,Default,,0,0,0,,RIGHT-PUSH和类似的过程 就是一直在上面放东西\nDialogue: 0,1:03:26.93,1:03:33.82,Default,,0,0,0,,而这个CORNER-PUSH则是一种一般性思想的泛化\nDialogue: 0,1:03:34.72,1:03:37.20,Default,,0,0,0,,为了演示并让大家熟悉\nDialogue: 0,1:03:37.98,1:03:40.65,Default,,0,0,0,,使用廊腰缦回的高阶过程\nDialogue: 0,1:03:41.12,1:03:47.24,Default,,0,0,0,,我给大家示范一下“递归地重复某种组合方法”的一般性思想\nDialogue: 0,1:03:48.30,1:03:50.70,Default,,0,0,0,,这个例子可以说明一切\nDialogue: 0,1:03:51.22,1:04:00.70,Default,,0,0,0,,我们可以定义一个依赖于具体组合方式的PUSH过程\nDialogue: 0,1:04:01.49,1:04:04.88,Default,,0,0,0,,COMB的取值可以是BESIDE或ABOVE等\nDialogue: 0,1:04:06.18,1:04:07.06,Default,,0,0,0,,过程的体是什么呢？\nDialogue: 0,1:04:07.06,1:04:12.06,Default,,0,0,0,,它返回一个过程 想一想BESIDE实际上是什么\nDialogue: 0,1:04:13.22,1:04:15.18,Default,,0,0,0,,它接受一个图像\nDialogue: 0,1:04:15.96,1:04:18.08,Default,,0,0,0,,哦  它接受两个图像和一个缩放因数\nDialogue: 0,1:04:18.62,1:04:24.28,Default,,0,0,0,,利用这个过程 定义一个接受层数、图像和缩放因数的过程\nDialogue: 0,1:04:24.28,1:04:25.45,Default,,0,0,0,,我称之为RIGHT-PUSH\nDialogue: 0,1:04:26.16,1:04:33.66,Default,,0,0,0,,这个过程接受 图像PICT 层数N和缩放因数A\nDialogue: 0,1:04:36.16,1:04:39.12,Default,,0,0,0,,我要做一些重复操作\nDialogue: 0,1:04:39.45,1:04:46.62,Default,,0,0,0,,我会重复应用一个接受一个图像P的过程\nDialogue: 0,1:04:48.40,1:04:50.69,Default,,0,0,0,,并把组合的方式应用在\nDialogue: 0,1:04:51.20,1:04:59.08,Default,,0,0,0,,应用在图像PICT和在这里接受的图像P以及缩放因数A\nDialogue: 0,1:05:02.26,1:05:07.28,Default,,0,0,0,,我要重复应用这个过程N次\nDialogue: 0,1:05:12.04,1:05:16.20,Default,,0,0,0,,我则是把这整个过程应用在原图片PICT上\nDialogue: 0,1:05:19.56,1:05:24.48,Default,,0,0,0,,虽然之前没提过 这里的REPEATED也是一个高阶过程\nDialogue: 0,1:05:24.53,1:05:28.34,Default,,0,0,0,,它接受一个过程P和一个数字N\nDialogue: 0,1:05:29.54,1:05:34.29,Default,,0,0,0,,它返回另一个过程：将给定的过程P重复应用N次的过程\nDialogue: 0,1:05:36.04,1:05:39.30,Default,,0,0,0,,可能有些人已经在练习中编写过REPEATED了\nDialogue: 0,1:05:39.70,1:05:43.01,Default,,0,0,0,,如果还没做的话 这是理解和练习高阶过程的好机会\nDialogue: 0,1:05:43.84,1:05:46.90,Default,,0,0,0,,无论如何 我将把REPEATED过程的结果应用到PICT上\nDialogue: 0,1:05:49.46,1:05:52.38,Default,,0,0,0,,定义好PUSH后 这就\nDialogue: 0,1:05:53.12,1:05:57.73,Default,,0,0,0,,这就是从BESIDE、RIGHT-PUSH中总结出来的一般性思想\nDialogue: 0,1:05:59.01,1:06:13.17,Default,,0,0,0,,现在 我就可以把RIGHT-PUSH定义为 用BESIDE来做PUSH操作\nDialogue: 0,1:06:17.65,1:06:20.32,Default,,0,0,0,,我也可以把UP-PUSH定义为 用ABOVE来做PUSH操作\nDialogue: 0,1:06:20.34,1:06:25.48,Default,,0,0,0,,类似地 CORNER-PUSH就是用BESIDE和ABOVE的适当组合做PUSH操作\nDialogue: 0,1:06:25.49,1:06:26.70,Default,,0,0,0,,我可以用任何东西做PUSH操作\nDialogue: 0,1:06:28.26,1:06:34.76,Default,,0,0,0,,嗯 如果你还不太理解LAMBDA的话 可以参考这个例子\nDialogue: 0,1:06:38.98,1:06:41.00,Default,,0,0,0,,我们可以从这个例子中学到很多东西\nDialogue: 0,1:06:42.18,1:06:49.80,Default,,0,0,0,,我主要想要介绍的是在一个语言中嵌入另一个语言\nDialogue: 0,1:06:50.66,1:06:55.62,Default,,0,0,0,,这样 母体语言--本例中是Lisp--的所有能力\nDialogue: 0,1:06:55.92,1:07:00.28,Default,,0,0,0,,可以作为你所构建语言的一种扩展而取得\nDialogue: 0,1:07:00.98,1:07:04.00,Default,,0,0,0,,这个例子很好地展示了这点\nDialogue: 0,1:07:08.14,1:07:10.94,Default,,0,0,0,,另外 当我们回过头去思考\nDialogue: 0,1:07:10.94,1:07:12.28,Default,,0,0,0,,什么是过程 什么是数据\nDialogue: 0,1:07:12.28,1:07:16.20,Default,,0,0,0,,在这里 天啊 发生了什么\nDialogue: 0,1:07:16.20,1:07:19.66,Default,,0,0,0,,在这里 这是一个过程 它接受一个图像和一个参数\nDialogue: 0,1:07:19.66,1:07:20.36,Default,,0,0,0,,但是 什么是图像呢？\nDialogue: 0,1:07:20.36,1:07:23.82,Default,,0,0,0,,请回想 图像本身 就是一个以矩形为参数的过程\nDialogue: 0,1:07:23.82,1:07:25.82,Default,,0,0,0,,这个矩形是某种抽象\nDialogue: 0,1:07:26.09,1:07:28.13,Default,,0,0,0,,我希望你们现在能彻底明白\nDialogue: 0,1:07:29.14,1:07:33.74,Default,,0,0,0,,系统中什么是过程 什么是数据\nDialogue: 0,1:07:33.74,1:07:34.78,Default,,0,0,0,,我们发现 它们没有任何区别\nDialogue: 0,1:07:35.49,1:07:36.44,Default,,0,0,0,,真的没有区别\nDialogue: 0,1:07:37.93,1:07:41.42,Default,,0,0,0,,你可以认为图像有时候是过程 有时候是数据\nDialogue: 0,1:07:41.84,1:07:44.90,Default,,0,0,0,,但是 这只是让你容易理解的一种方法\nDialogue: 0,1:07:44.90,1:07:47.30,Default,,0,0,0,,这有一定道理 也没有道理\nDialogue: 0,1:07:49.92,1:08:02.20,Default,,0,0,0,,关于系统的结构 一种更普遍的观点将其视作创建一种语言\nDialogue: 0,1:08:02.52,1:08:06.74,Default,,0,0,0,,将工程设计过程看作是创建一门语言\nDialogue: 0,1:08:07.84,1:08:13.97,Default,,0,0,0,,准确来说 是创建各种层次的语言\nDialogue: 0,1:08:14.77,1:08:20.01,Default,,0,0,0,,众所周知 有一种方法学 或者叫做“神话学”\nDialogue: 0,1:08:20.74,1:08:24.90,Default,,0,0,0,,姑且叫做软件“工程”\nDialogue: 0,1:08:25.21,1:08:28.04,Default,,0,0,0,,它声称 你要先计算出你的任务\nDialogue: 0,1:08:28.04,1:08:30.04,Default,,0,0,0,,精确且正确地计算出你的任务\nDialogue: 0,1:08:30.40,1:08:32.20,Default,,0,0,0,,一但你搞清楚要做的东西\nDialogue: 0,1:08:32.22,1:08:34.54,Default,,0,0,0,,你把它划分为三个子任务\nDialogue: 0,1:08:34.54,1:08:35.76,Default,,0,0,0,,然后你开始继续做--\nDialogue: 0,1:08:35.97,1:08:38.94,Default,,0,0,0,,你开始处理这个子任务 然后你明确它是什么\nDialogue: 0,1:08:38.94,1:08:43.04,Default,,0,0,0,,这个子问题就分裂成三个子任务 你把它们处理完\nDialogue: 0,1:08:43.04,1:08:47.32,Default,,0,0,0,,然后你先处理这两个任务\nDialogue: 0,1:08:47.32,1:08:51.10,Default,,0,0,0,,解决完子任务后 你后退到这里 处理第二个子任务\nDialogue: 0,1:08:51.10,1:08:53.40,Default,,0,0,0,,然后把它详细地实现出来\nDialogue: 0,1:08:53.40,1:08:57.64,Default,,0,0,0,,结束之后-- 你完成了这个美丽的大厦\nDialogue: 0,1:08:57.64,1:09:00.25,Default,,0,0,0,,你最后得到了一棵非凡的树\nDialogue: 0,1:09:00.89,1:09:08.24,Default,,0,0,0,,你把任务划分为子任务 子任务再划分为子任务\nDialogue: 0,1:09:09.88,1:09:15.02,Default,,0,0,0,,树中的每个结点都被严谨而准确地定义\nDialogue: 0,1:09:15.26,1:09:18.66,Default,,0,0,0,,为奇妙而精美的任务 以构建整栋大厦\nDialogue: 0,1:09:18.96,1:09:21.14,Default,,0,0,0,,这个就是所谓的“神话学”\nDialogue: 0,1:09:21.14,1:09:25.92,Default,,0,0,0,,只有计算机科学家才可能相信你构建的复杂系统像这个样子\nDialogue: 0,1:09:27.48,1:09:32.80,Default,,0,0,0,,好了 我们用Henderson的例子来做对比\nDialogue: 0,1:09:32.80,1:09:34.30,Default,,0,0,0,,它的结构不是那样\nDialogue: 0,1:09:35.26,1:09:39.33,Default,,0,0,0,,事实是：这里有一个语言的层次序列\nDialogue: 0,1:09:41.06,1:09:42.05,Default,,0,0,0,,它是什么？\nDialogue: 0,1:09:42.18,1:09:48.76,Default,,0,0,0,,这里有一层 允许我们构建基本图像\nDialogue: 0,1:09:51.69,1:09:56.24,Default,,0,0,0,,这个语言描述基本图像\nDialogue: 0,1:09:56.32,1:09:57.84,Default,,0,0,0,,我们并没有做过多地讨论\nDialogue: 0,1:09:58.22,1:09:59.58,Default,,0,0,0,,我们讨论了如何构造George\nDialogue: 0,1:09:59.61,1:10:04.88,Default,,0,0,0,,这个语言是在单位正方形中讨论点、线和向量\nDialogue: 0,1:10:06.42,1:10:11.29,Default,,0,0,0,,而在这之上\nDialogue: 0,1:10:11.97,1:10:14.10,Default,,0,0,0,,这是讨论基本图像的语言\nDialogue: 0,1:10:17.08,1:10:20.36,Default,,0,0,0,,讨论在特定单位正方形中线段的构造\nDialogue: 0,1:10:21.40,1:10:23.80,Default,,0,0,0,,在这个上面是另一个完整的语言\nDialogue: 0,1:10:24.05,1:10:30.86,Default,,0,0,0,,关于几何组合子的语言\nDialogue: 0,1:10:32.66,1:10:36.62,Default,,0,0,0,,关于几何物件的位置\nDialogue: 0,1:10:38.77,1:10:46.50,Default,,0,0,0,,讨论像ABOVE、BESIDE、RIGHT-PUSH和ROTATE这样的东西\nDialogue: 0,1:10:48.04,1:10:55.70,Default,,0,0,0,,这些事情恰巧与我们在这个语言中谈论的事情有关\nDialogue: 0,1:10:58.57,1:11:00.93,Default,,0,0,0,,再细化一点 我们发现在这之上\nDialogue: 0,1:11:02.61,1:11:15.10,Default,,0,0,0,,还有一门语言 描述组合的模式\nDialogue: 0,1:11:21.25,1:11:22.44,Default,,0,0,0,,比如说PUSH\nDialogue: 0,1:11:24.45,1:11:27.88,Default,,0,0,0,,也就是用一个放缩因子重复地做一件事儿\nDialogue: 0,1:11:28.38,1:11:31.28,Default,,0,0,0,,我们在那门语言中讨论的问题\nDialogue: 0,1:11:31.50,1:11:34.34,Default,,0,0,0,,正是我这里构建的东西\nDialogue: 0,1:11:36.30,1:11:42.76,Default,,0,0,0,,我们在每一层上所讨论的对象\nDialogue: 0,1:11:44.68,1:11:47.00,Default,,0,0,0,,都是前一个层次所建立的\nDialogue: 0,1:11:48.08,1:11:52.06,Default,,0,0,0,,这个和这个有什么区别呢？\nDialogue: 0,1:11:53.34,1:11:54.18,Default,,0,0,0,,这是因为\nDialogue: 0,1:11:56.14,1:12:01.73,Default,,0,0,0,,实际上在这里 树的每一个结点 每一次分解\nDialogue: 0,1:12:02.14,1:12:05.25,Default,,0,0,0,,都是旨在分成确定的任务\nDialogue: 0,1:12:07.50,1:12:08.88,Default,,0,0,0,,而在另一个方案中\nDialogue: 0,1:12:09.21,1:12:14.80,Default,,0,0,0,,你在每个层级上的完完全全的语言层面的能力\nDialogue: 0,1:12:16.00,1:12:18.08,Default,,0,0,0,,这里的每一个层次\nDialogue: 0,1:12:20.24,1:12:22.72,Default,,0,0,0,,都不是被设计为完成一个特定任务\nDialogue: 0,1:12:23.14,1:12:26.17,Default,,0,0,0,,它被设计为讨论整个事情\nDialogue: 0,1:12:27.62,1:12:30.78,Default,,0,0,0,,这样设计导致的结果是：\nDialogue: 0,1:12:31.14,1:12:35.58,Default,,0,0,0,,用这种设计方法更加健壮\nDialogue: 0,1:12:36.61,1:12:38.20,Default,,0,0,0,,我所谓的“健壮”是指\nDialogue: 0,1:12:38.44,1:12:41.24,Default,,0,0,0,,当你在描述中做一些改变\nDialogue: 0,1:12:42.70,1:12:48.04,Default,,0,0,0,,我们可以做出相应的改变\nDialogue: 0,1:12:49.22,1:12:52.60,Default,,0,0,0,,用上一层语言实现的方法改变即可\nDialogue: 0,1:12:54.29,1:12:56.58,Default,,0,0,0,,因为你让每个层次都是完全的\nDialogue: 0,1:12:56.62,1:12:59.66,Default,,0,0,0,,所以你不需要讨论像BESIDE这样的特定操作\nDialogue: 0,1:12:59.94,1:13:03.78,Default,,0,0,0,,你为表达这类事物创造了完备的词汇\nDialogue: 0,1:13:04.77,1:13:07.02,Default,,0,0,0,,所以当你轻微修改规格指标时\nDialogue: 0,1:13:07.02,1:13:11.38,Default,,0,0,0,,这种方法论可以捕捉并适应那些变化\nDialogue: 0,1:13:12.69,1:13:15.02,Default,,0,0,0,,然而这种设计却不够健壮\nDialogue: 0,1:13:15.02,1:13:17.08,Default,,0,0,0,,因为 如果我在这里改变一下\nDialogue: 0,1:13:17.53,1:13:21.69,Default,,0,0,0,,那可能会影响我划分这些东西的方式 严重地影响\nDialogue: 0,1:13:23.20,1:13:29.74,Default,,0,0,0,,分解观点的最大不同在于 按层次还是严格继承分解\nDialogue: 0,1:13:30.52,1:13:33.02,Default,,0,0,0,,不只是如此 当你有多个层次的语言时\nDialogue: 0,1:13:33.50,1:13:35.92,Default,,0,0,0,,你就有了不同的词汇储备\nDialogue: 0,1:13:36.45,1:13:38.74,Default,,0,0,0,,用于讨论不同层次上的设计\nDialogue: 0,1:13:38.74,1:13:40.92,Default,,0,0,0,,我们再回过头来看看George\nDialogue: 0,1:13:41.90,1:13:44.08,Default,,0,0,0,,如果我想改变图像George\nDialogue: 0,1:13:45.85,1:13:48.68,Default,,0,0,0,,我立马得到了一种不同的方式来描述变化\nDialogue: 0,1:13:48.68,1:13:56.08,Default,,0,0,0,,比如 我想在基本设计的层面上 移动某些向量的终点\nDialogue: 0,1:13:57.76,1:14:00.76,Default,,0,0,0,,我会在最底层讨论这个改变\nDialogue: 0,1:14:01.00,1:14:02.50,Default,,0,0,0,,我会另外指定终点位置\nDialogue: 0,1:14:03.34,1:14:07.98,Default,,0,0,0,,我也可以说 我想在这个小的重复元素上做文章\nDialogue: 0,1:14:09.10,1:14:10.94,Default,,0,0,0,,我可能想做些其它操作\nDialogue: 0,1:14:10.94,1:14:13.84,Default,,0,0,0,,我想在BESIDE中使用一个缩放因数\nDialogue: 0,1:14:13.84,1:14:19.34,Default,,0,0,0,,这个改变我会在更高的层次上讨论：在组合子的层次\nDialogue: 0,1:14:19.34,1:14:25.05,Default,,0,0,0,,我也可以改变图像的基本组合模式\nDialogue: 0,1:14:26.49,1:14:30.48,Default,,0,0,0,,做一些递归地分解 可能不会让它们填充满角落\nDialogue: 0,1:14:31.16,1:14:34.18,Default,,0,0,0,,而这样的一个变化 我会在最高层次讨论\nDialogue: 0,1:14:34.18,1:14:36.37,Default,,0,0,0,,正是因为我按这种结构组织系统\nDialogue: 0,1:14:36.52,1:14:39.62,Default,,0,0,0,,我有所有的词汇 可以用不同的方式描述变化\nDialogue: 0,1:14:39.65,1:14:42.48,Default,,0,0,0,,而且可以灵活地决定哪个更合适\nDialogue: 0,1:14:44.74,1:14:51.05,Default,,0,0,0,,这就是Lisp中不同于软件工程方法论的最大要点\nDialogue: 0,1:14:51.25,1:14:55.45,Default,,0,0,0,,它来自于这样一个观点：真正的设计过程\nDialogue: 0,1:14:56.12,1:14:59.62,Default,,0,0,0,,与其说是在设计程序 不如说是在设计语言\nDialogue: 0,1:14:59.62,1:15:01.09,Default,,0,0,0,,而这就是Lisp的力量\nDialogue: 0,1:15:02.21,1:15:03.61,Default,,0,0,0,,谢谢大家 下课\nDialogue: 0,1:15:05.69,1:15:23.37,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:15:05.69,1:15:23.37,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec3a.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nAudio URI: G:\\untitled\\ref\\lec3a_480_muxed.mp4\nVideo Zoom Percent: 0.625\nScroll Position: 0\nActive Line: 336\nVideo File: G:\\untitled\\ref\\lec3a_480_muxed.mp4\nVideo Aspect Ratio: c1.33333\nVideo Position: 51395\nPlayResX: 640\nPlayResY: 480\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:03.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:04.40,0:00:08.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}翻译&&时间轴：邓雄飞（Dysprosium）、Savior Michael\\N压制&&特效：邓雄飞（Dysprosium）\\N校对：邓雄飞（Dysprosium）\nDialogue: 0,0:00:08.06,0:00:12.16,Declare,,0,0,0,,{\\an2\\fad(500,500)}特别感谢：裘宗燕教授\nDialogue: 0,0:00:12.37,0:00:16.32,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson-Escher的例子\nDialogue: 0,0:00:20.94,0:00:23.86,Default,,0,0,0,,上节课我们讨论了复合数据\nDialogue: 0,0:00:24.94,0:00:29.74,Default,,0,0,0,,其中有两个关键点\nDialogue: 0,0:00:29.74,0:00:32.48,Default,,0,0,0,,首先 有一种数据抽象的方法学\nDialogue: 0,0:00:32.94,0:00:39.10,Default,,0,0,0,,其要点是将数据的使用\nDialogue: 0,0:00:40.06,0:00:41.50,Default,,0,0,0,,和表示分离开来\nDialogue: 0,0:00:41.55,0:00:45.20,Default,,0,0,0,,比如说 我们可以与一个叫做George的人“签订契约”\nDialogue: 0,0:00:45.20,0:00:47.48,Default,,0,0,0,,让他负责数据的表示\nDialogue: 0,0:00:47.48,0:00:49.36,Default,,0,0,0,,而当我们使用这些数据的时候\nDialogue: 0,0:00:49.36,0:00:51.36,Default,,0,0,0,,不需要替George操心他是如何完成数据表示的工作的\nDialogue: 0,0:00:51.98,0:00:58.44,Default,,0,0,0,,其次 Lisp中有一种特殊的方式把对象连接在一起\nDialogue: 0,0:00:58.94,0:01:00.52,Default,,0,0,0,,就是构成“序对”\nDialogue: 0,0:01:00.52,0:01:03.54,Default,,0,0,0,,这是通过CONS CAR CDR实现的\nDialogue: 0,0:01:03.54,0:01:07.16,Default,,0,0,0,,而CONS CAR CDR本身是如何实现的 这不重要\nDialogue: 0,0:01:07.16,0:01:10.02,Default,,0,0,0,,George的任务就是如何构建这些东西\nDialogue: 0,0:01:10.02,0:01:11.16,Default,,0,0,0,,可以将它们实现为基本过程\nDialogue: 0,0:01:11.16,0:01:13.80,Default,,0,0,0,,也可以利用一些奇怪的过程来实现\nDialogue: 0,0:01:13.80,0:01:15.22,Default,,0,0,0,,但是我们不用操心这些\nDialogue: 0,0:01:16.02,0:01:19.66,Default,,0,0,0,,举个例子 我们来看下有理数算术\nDialogue: 0,0:01:19.66,0:01:21.50,Default,,0,0,0,,看下向量\nDialogue: 0,0:01:21.50,0:01:24.18,Default,,0,0,0,,我们简单回顾一下向量\nDialogue: 0,0:01:24.18,0:01:27.64,Default,,0,0,0,,这里有个对两个向量求和的操作\nDialogue: 0,0:01:27.64,0:01:33.32,Default,,0,0,0,,我们想要把向量v1和v2相加\nDialogue: 0,0:01:34.46,0:01:40.84,Default,,0,0,0,,它们的和也是一个向量 其坐标是两个向量的坐标的和\nDialogue: 0,0:01:41.28,0:01:45.66,Default,,0,0,0,,所以 定义(+VECT V1 V2)为\nDialogue: 0,0:01:45.66,0:01:51.72,Default,,0,0,0,,我创建一个向量 其X坐标是两向量X坐标的和\nDialogue: 0,0:01:52.10,0:01:54.82,Default,,0,0,0,,而Y坐标是两向量Y坐标的和\nDialogue: 0,0:01:56.06,0:02:04.10,Default,,0,0,0,,类似地 我们也可以定义一个缩放向量的操作\nDialogue: 0,0:02:04.94,0:02:12.66,Default,,0,0,0,,这里的SCALE过程是用数字S乘以向量V\nDialogue: 0,0:02:13.08,0:02:16.14,Default,,0,0,0,,向量V从这里到这里\nDialogue: 0,0:02:16.32,0:02:20.22,Default,,0,0,0,,我放大V 得到了与原来同向但更长的向量\nDialogue: 0,0:02:21.56,0:02:24.26,Default,,0,0,0,,为了缩放向量 我需要通过缩放坐标来实现\nDialogue: 0,0:02:24.26,0:02:30.22,Default,,0,0,0,,所以我构建了一个向量 它的X坐标是原向量X坐标的S倍\nDialogue: 0,0:02:30.56,0:02:33.54,Default,,0,0,0,,同时 它的Y坐标是原来向量Y坐标的S倍\nDialogue: 0,0:02:33.54,0:02:40.28,Default,,0,0,0,,上述两个操作都是利用了向量的表示来实现的\nDialogue: 0,0:02:40.28,0:02:45.02,Default,,0,0,0,,而这种向量的表示 我们则可以用序对来实现\nDialogue: 0,0:02:45.34,0:02:51.28,Default,,0,0,0,,因此George需要为我们提供MAKE-VECTOR、XCOR和YCOR\nDialogue: 0,0:02:53.02,0:02:57.98,Default,,0,0,0,,他可以使用CONS CAR CDR来实现\nDialogue: 0,0:02:58.88,0:03:06.78,Default,,0,0,0,,但是注意 我这里用了一个略微不同的方式\nDialogue: 0,0:03:08.04,0:03:11.00,Default,,0,0,0,,这个过程我们之前看过 其中我讲过\nDialogue: 0,0:03:11.14,0:03:16.22,Default,,0,0,0,,(MAKE-VECTOR X Y)也就是(CONS X Y)\nDialogue: 0,0:03:16.22,0:03:17.98,Default,,0,0,0,,而我这里简单定义MAKE-VECTOR为CONS\nDialogue: 0,0:03:17.98,0:03:20.48,Default,,0,0,0,,这就与之前有些不同了\nDialogue: 0,0:03:20.48,0:03:26.22,Default,,0,0,0,,之前我们我们把MAKE-VECTOR定义为需要两个参数的过程\nDialogue: 0,0:03:26.22,0:03:28.04,Default,,0,0,0,,效果是(CONS X Y)\nDialogue: 0,0:03:28.04,0:03:34.12,Default,,0,0,0,,这里 我就把MAKE-VECTOR定义为CONS\nDialogue: 0,0:03:35.18,0:03:39.66,Default,,0,0,0,,这跟我们之前使用的方式基本上是一样的\nDialogue: 0,0:03:39.66,0:03:46.58,Default,,0,0,0,,大家要习惯于“过程也是对象 而且你可以给他们命名”这种想法\nDialogue: 0,0:03:48.70,0:03:51.80,Default,,0,0,0,,这些就是向量的表示方法了\nDialogue: 0,0:03:51.80,0:03:55.68,Default,,0,0,0,,如果仅仅是那样 那就太无趣了\nDialogue: 0,0:03:57.02,0:04:02.16,Default,,0,0,0,,要记住 要点是我们不仅可以通过使用CONS将数字组合成序对\nDialogue: 0,0:04:02.16,0:04:04.16,Default,,0,0,0,,也可以组合任何东西\nDialogue: 0,0:04:05.20,0:04:11.60,Default,,0,0,0,,例如 如果我想表示一个线段\nDialogue: 0,0:04:11.60,0:04:15.64,Default,,0,0,0,,一个以某个向量为起点的线段\nDialogue: 0,0:04:16.06,0:04:28.30,Default,,0,0,0,,比如从向量(2,3)所代表的起点到向量(5,1)所代表的终点的线段\nDialogue: 0,0:04:28.30,0:04:31.82,Default,,0,0,0,,如果我们想表示这条线段\nDialogue: 0,0:04:33.26,0:04:36.20,Default,,0,0,0,,那么我们可以构建一个序对的序对\nDialogue: 0,0:04:40.72,0:04:42.94,Default,,0,0,0,,这样我们就可以表示一条线段了\nDialogue: 0,0:04:42.94,0:04:47.34,Default,,0,0,0,,我们可以编写一个使用CONS构造线段的构造函数\nDialogue: 0,0:04:47.98,0:04:51.60,Default,,0,0,0,,以及 析取出线段起点、终点的选择函数\nDialogue: 0,0:04:55.24,0:04:59.76,Default,,0,0,0,,那么如果我们剥开抽象层一探究竟\nDialogue: 0,0:04:59.88,0:05:02.10,Default,,0,0,0,,就会发现线段不过是 序对组成的序对\nDialogue: 0,0:05:04.66,0:05:06.22,Default,,0,0,0,,它还是一个序对\nDialogue: 0,0:05:06.22,0:05:08.22,Default,,0,0,0,,这里有个线段\nDialogue: 0,0:05:10.00,0:05:16.72,Default,,0,0,0,,它的CAR部分是个序对 CDR部分也是个序对\nDialogue: 0,0:05:18.32,0:05:25.54,Default,,0,0,0,,它的CAR部分是由2和3构成的序对\nDialogue: 0,0:05:26.02,0:05:28.08,Default,,0,0,0,,CDR部分则由5和1构成的序对\nDialogue: 0,0:05:28.16,0:05:29.24,Default,,0,0,0,,这里我再提醒大家一下\nDialogue: 0,0:05:29.32,0:05:33.46,Default,,0,0,0,,好多人认为如果我箭头向下画的话\nDialogue: 0,0:05:33.80,0:05:36.90,Default,,0,0,0,,会有其它的含意\nDialogue: 0,0:05:36.98,0:05:38.28,Default,,0,0,0,,这是不对的\nDialogue: 0,0:05:38.58,0:05:43.90,Default,,0,0,0,,箭头指示的是对象间如何连接 它指向水平或竖直方向都是无关紧要的\nDialogue: 0,0:05:47.48,0:05:52.18,Default,,0,0,0,,还要提醒一下 序对是具有闭包性质的\nDialogue: 0,0:05:52.94,0:06:05.62,Default,,0,0,0,,闭包性质使我们可以构建更复杂的东西 而不仅仅是简单的序对\nDialogue: 0,0:06:06.64,0:06:15.24,Default,,0,0,0,,在这里我要特别指出 在我们用CONS构建出来的序对的基础上\nDialogue: 0,0:06:16.44,0:06:22.64,Default,,0,0,0,,我们也可以进一步用CONS来构造更复杂的对象\nDialogue: 0,0:06:23.28,0:06:31.98,Default,,0,0,0,,或者用数学家的话说 Lisp中的数据对象在CONS运算下是封闭的\nDialogue: 0,0:06:33.82,0:06:36.34,Default,,0,0,0,,这个性质使我们能够构造更加复杂的数据对象\nDialogue: 0,0:06:36.34,0:06:38.04,Default,,0,0,0,,这个似乎是显然的 但是要记住\nDialogue: 0,0:06:39.06,0:06:42.46,Default,,0,0,0,,人们使用的编程语言中有很多东西并不是封闭的\nDialogue: 0,0:06:42.46,0:06:48.06,Default,,0,0,0,,举例来说 Basic和Fortran中的构造数组操作 就不是封闭的\nDialogue: 0,0:06:48.08,0:06:51.94,Default,,0,0,0,,因为 虽然你可以用数字、字符或字符串等来构造数组\nDialogue: 0,0:06:52.04,0:06:54.18,Default,,0,0,0,,但是你不能创建数组的数组\nDialogue: 0,0:06:54.64,0:06:56.68,Default,,0,0,0,,当考察某种组合的方法时\nDialogue: 0,0:06:57.60,0:07:02.78,Default,,0,0,0,,你应该考察该组合方法是否封闭\nDialogue: 0,0:07:05.06,0:07:08.26,Default,,0,0,0,,不管怎样 因为我们可以构造序对的序对\nDialogue: 0,0:07:08.86,0:07:12.78,Default,,0,0,0,,我们就可以用序对将数据以各种各样的方式组合起来\nDialogue: 0,0:07:14.02,0:07:18.26,Default,,0,0,0,,比如我想要组合四个数 -- 1 2 3 4\nDialogue: 0,0:07:18.26,0:07:19.82,Default,,0,0,0,,我有很多方法\nDialogue: 0,0:07:20.74,0:07:26.12,Default,,0,0,0,,比如 像构造线段那样 我可以构造一个序对\nDialogue: 0,0:07:29.02,0:07:36.88,Default,,0,0,0,,它是((1 2) (3 4)) 对吧？\nDialogue: 0,0:07:36.88,0:07:40.06,Default,,0,0,0,,或者如果我喜欢 我可以像这样做\nDialogue: 0,0:07:40.06,0:07:45.52,Default,,0,0,0,,我构造一个序对 它的CAR部分也是一个序对\nDialogue: 0,0:07:46.44,0:07:53.20,Default,,0,0,0,,这个序对的CAR部分为1 而CDR部分为由2、3构成的序对\nDialogue: 0,0:07:53.26,0:07:55.08,Default,,0,0,0,,最后 我把4放在这里\nDialogue: 0,0:07:56.92,0:08:02.16,Default,,0,0,0,,所以你可以看到 组合对象的方式有很多种\nDialogue: 0,0:08:02.16,0:08:07.74,Default,,0,0,0,,因此就有必要建立一些统一的约定\nDialogue: 0,0:08:07.74,0:08:11.58,Default,,0,0,0,,使我们能够用某种的通用的方式处理数据\nDialogue: 0,0:08:11.58,0:08:14.00,Default,,0,0,0,,而不用总是针对具体问题做一些生硬的选择\nDialogue: 0,0:08:15.94,0:08:19.04,Default,,0,0,0,,Lisp里面就有这样一种约定\nDialogue: 0,0:08:20.74,0:08:25.82,Default,,0,0,0,,这个约定将一系列的东西表示成一个序对组成的链\nDialogue: 0,0:08:26.78,0:08:28.18,Default,,0,0,0,,而这样一个数据序列就叫做一个“表”\nDialogue: 0,0:08:34.72,0:08:40.50,Default,,0,0,0,,表本质上就是Lisp用来表示序列数据的一个约定而已\nDialogue: 0,0:08:40.70,0:08:47.38,Default,,0,0,0,,我可以使用序对的序列来表示序列 1 2 3 4\nDialogue: 0,0:08:48.26,0:08:54.68,Default,,0,0,0,,我把1放在这里 它的CDR指向另一个序对\nDialogue: 0,0:08:59.20,0:09:01.40,Default,,0,0,0,,这个序对的CAR部分是序列中的下一个数\nDialogue: 0,0:09:01.52,0:09:03.42,Default,,0,0,0,,并且它的CDR指向了另一个序对\nDialogue: 0,0:09:05.44,0:09:07.30,Default,,0,0,0,,它的CAR部分是序列的再下一个数\nDialogue: 0,0:09:07.36,0:09:08.44,Default,,0,0,0,,这个是3\nDialogue: 0,0:09:08.44,0:09:09.74,Default,,0,0,0,,以此类推\nDialogue: 0,0:09:09.74,0:09:13.22,Default,,0,0,0,,所以 序列中的每一个元素都对应着一个序对\nDialogue: 0,0:09:15.82,0:09:18.32,Default,,0,0,0,,而当这个序列中没有其它元素时，我用一个特殊的标记\nDialogue: 0,0:09:20.72,0:09:22.74,Default,,0,0,0,,来表示列表中没有元素了\nDialogue: 0,0:09:24.14,0:09:34.64,Default,,0,0,0,,好 这就是将序列中的元素组合起来的一种约定方式\nDialogue: 0,0:09:34.64,0:09:37.98,Default,,0,0,0,,而它其实就是一堆序对\nDialogue: 0,0:09:39.40,0:09:44.80,Default,,0,0,0,,每个序对中的CAR部分就是我们想要组合到一起的元素\nDialogue: 0,0:09:46.00,0:09:48.46,Default,,0,0,0,,这些序对的CDR部分则指向下一个序对\nDialogue: 0,0:09:50.02,0:09:56.04,Default,,0,0,0,,现在 如果我想要构造它 我需要向Lisp中输入\nDialogue: 0,0:09:56.62,0:09:58.76,Default,,0,0,0,,我会像这样来构造\nDialogue: 0,0:09:59.22,0:10:15.28,Default,,0,0,0,,(CONS 1 (CONS 2 (CONS 3 (CONS 4 NIL))))\nDialogue: 0,0:10:15.28,0:10:20.00,Default,,0,0,0,,NIL是序列末尾标志的名字\nDialogue: 0,0:10:20.80,0:10:23.24,Default,,0,0,0,,它是一个特殊的名字 标识以达到表的末尾\nDialogue: 0,0:10:26.24,0:10:30.26,Default,,0,0,0,,好 这就是如何构造一个表\nDialogue: 0,0:10:37.54,0:10:41.40,Default,,0,0,0,,如果每次构造一个表时 都要输入像\nDialogue: 0,0:10:41.45,0:10:45.18,Default,,0,0,0,,(CONS 1 (CONS 2 (CONS 3...的话 将会非常费力\nDialogue: 0,0:10:45.18,0:10:50.10,Default,,0,0,0,,因此Lisp提供了一种叫做LIST的操作\nDialogue: 0,0:10:53.70,0:10:57.72,Default,,0,0,0,,LIST其实是这种嵌套CONS的缩写\nDialogue: 0,0:10:58.96,0:11:06.32,Default,,0,0,0,,它可以让我用(LIST 1 2 3 4)来构造表\nDialogue: 0,0:11:07.78,0:11:11.74,Default,,0,0,0,,这只是另外一种方式 一种语法糖衣\nDialogue: 0,0:11:11.94,0:11:14.76,Default,,0,0,0,,用来简便地书写嵌套的CONS\nDialogue: 0,0:11:14.76,0:11:17.84,Default,,0,0,0,,(CONS (CONS (CONS (CONS NIL))))\nDialogue: 0,0:11:18.48,0:11:39.78,Default,,0,0,0,,举例来说 我将构造一个表(1 2 3 4) 并把它叫做1-TO-4\nDialogue: 0,0:11:47.96,0:11:53.02,Default,,0,0,0,,注意使用这种简便写法的结果\nDialogue: 0,0:11:53.80,0:11:56.92,Default,,0,0,0,,首先 如果我有这个表(1 2 3 4)\nDialogue: 0,0:11:57.36,0:12:02.64,Default,,0,0,0,,表的CAR把部分就是这个表的第一个元素 对吧？\nDialogue: 0,0:12:04.06,0:12:05.28,Default,,0,0,0,,那么 如何获得元素2呢？\nDialogue: 0,0:12:05.28,0:12:23.94,Default,,0,0,0,,2应该是1-TO-4的CDR部分的CAR部分\nDialogue: 0,0:12:23.98,0:12:29.48,Default,,0,0,0,,它的CDR是这个\nDialogue: 0,0:12:29.82,0:12:31.68,Default,,0,0,0,,而它的CAR部分是2\nDialogue: 0,0:12:32.58,0:12:47.42,Default,,0,0,0,,同理 1-TO-4的CDR的CDR的CAR部分\nDialogue: 0,0:12:47.42,0:12:51.36,Default,,0,0,0,,是3 以此类推\nDialogue: 0,0:12:52.68,0:12:55.84,Default,,0,0,0,,我们来看下屏幕\nDialogue: 0,0:12:57.50,0:13:11.18,Default,,0,0,0,,我定义一个表(1 2 3 4) 命名为1-TO-4\nDialogue: 0,0:13:13.78,0:13:21.28,Default,,0,0,0,,我这样写 计算机返回定义完成 这个就是1-TO-4的定义\nDialogue: 0,0:13:22.30,0:13:36.74,Default,,0,0,0,,我问 比如 1-TO-4的CDR的CDR的CAR\nDialogue: 0,0:13:38.34,0:13:42.42,Default,,0,0,0,,嗯 它是3\nDialogue: 0,0:13:44.08,0:13:50.08,Default,,0,0,0,,或者我问 1-TO-4是什么\nDialogue: 0,0:13:51.26,0:13:57.22,Default,,0,0,0,,Lisp输出的是用括号包围的 (1 2 3 4)\nDialogue: 0,0:13:57.22,0:14:02.12,Default,,0,0,0,,用括号将表中的元素包围起来的这种记号\nDialogue: 0,0:14:02.12,0:14:08.90,Default,,0,0,0,,通常用来打印输出表示序列的序对链\nDialogue: 0,0:14:08.90,0:14:17.14,Default,,0,0,0,,又比如 我问1-TO-4的CDR部分是什么\nDialogue: 0,0:14:19.30,0:14:21.12,Default,,0,0,0,,结果是表的剩余部分\nDialogue: 0,0:14:21.32,0:14:26.96,Default,,0,0,0,,这是原表首元素所指向的序对 新序列从2开始\nDialogue: 0,0:14:28.52,0:14:37.74,Default,,0,0,0,,比如 1-TO-4的CDR的CDR部分是什么\nDialogue: 0,0:14:43.24,0:14:44.68,Default,,0,0,0,,返回(3 4)\nDialogue: 0,0:14:44.82,0:14:59.66,Default,,0,0,0,,或者 1-TO-4的CDR的CDR的CDR的CDR部分是什么\nDialogue: 0,0:15:04.74,0:15:10.46,Default,,0,0,0,,我们看一下表的尾指针 Lisp返回()\nDialogue: 0,0:15:10.96,0:15:13.48,Default,,0,0,0,,你们可以认为这是一个空表\nDialogue: 0,0:15:14.12,0:15:21.38,Default,,0,0,0,,我求取 1-TO-4的CDR的CDR的CDR部分\nDialogue: 0,0:15:21.42,0:15:25.20,Default,,0,0,0,,这就只剩下表尾指针本身\nDialogue: 0,0:15:25.20,0:15:27.20,Default,,0,0,0,,它的输出是()\nDialogue: 0,0:15:34.14,0:15:39.98,Default,,0,0,0,,好了 这是处理表的一种常见方式\nDialogue: 0,0:15:41.50,0:15:43.44,Default,,0,0,0,,也就是不断地取CDR部分\nDialogue: 0,0:15:43.44,0:15:45.00,Default,,0,0,0,,这个叫做表的CDRING\nDialogue: 0,0:15:46.64,0:15:49.78,Default,,0,0,0,,当然手写这些CDR非常费劲\nDialogue: 0,0:15:49.78,0:15:52.24,Default,,0,0,0,,我们没必要这么做 我们编写程序来这么做\nDialogue: 0,0:15:52.96,0:15:59.10,Default,,0,0,0,,事实上 Lisp中非常普遍的事情是写一些过程\nDialogue: 0,0:15:59.85,0:16:06.54,Default,,0,0,0,,表中所有元素进行某种操作 得到的是由结果构成的表\nDialogue: 0,0:16:07.42,0:16:11.92,Default,,0,0,0,,比如 我写一个SCALE-LIST的过程\nDialogue: 0,0:16:16.80,0:16:25.24,Default,,0,0,0,,我要用SCALE-LIST将表1-TO-4放大10倍\nDialogue: 0,0:16:26.66,0:16:35.32,Default,,0,0,0,,那么它应该返回表(10 20 30 40)\nDialogue: 0,0:16:38.25,0:16:40.25,Default,,0,0,0,,没错 它返回一个表\nDialogue: 0,0:16:44.49,0:16:49.30,Default,,0,0,0,,我们可以猜想到这当中采用了某种递归策略\nDialogue: 0,0:16:49.30,0:16:51.30,Default,,0,0,0,,我应该如何编写这个过程呢？\nDialogue: 0,0:16:52.52,0:16:59.80,Default,,0,0,0,,如果要构建一个每个元素都乘以10的列表\nDialogue: 0,0:17:00.44,0:17:04.84,Default,,0,0,0,,需要做的是—假设已经得到了结果表的剩余元素\nDialogue: 0,0:17:05.86,0:17:08.42,Default,,0,0,0,,也就是表的CDR部分\nDialogue: 0,0:17:08.42,0:17:14.16,Default,,0,0,0,,这个子表中的每个元素都是原来元素乘以10\nDialogue: 0,0:17:16.06,0:17:19.68,Default,,0,0,0,,这是SCALE-LIST对表CDR部分作用的结果\nDialogue: 0,0:17:20.12,0:17:23.82,Default,,0,0,0,,我需要做的 就只有用表的CAR部分乘以10\nDialogue: 0,0:17:24.89,0:17:27.24,Default,,0,0,0,,然后用CONS将它和剩余部分连接起来 并返回这个列表\nDialogue: 0,0:17:29.02,0:17:33.09,Default,,0,0,0,,类似地 为了缩放子表 我得先缩放子表的CDR部分\nDialogue: 0,0:17:33.30,0:17:36.20,Default,,0,0,0,,并将其与2*10连接起来\nDialogue: 0,0:17:36.42,0:17:41.16,Default,,0,0,0,,最终 当我处理到表尾时 这里就只剩表尾指针了\nDialogue: 0,0:17:41.72,0:17:45.28,Default,,0,0,0,,它叫做NIL 我就直接返回表尾指针\nDialogue: 0,0:17:45.54,0:17:47.68,Default,,0,0,0,,所以这就是这个过程的递归策略\nDialogue: 0,0:17:47.68,0:17:50.52,Default,,0,0,0,,这个过程就是这样\nDialogue: 0,0:17:50.96,0:17:55.04,Default,,0,0,0,,这个例子就是对表做CDRING操作的通用策略\nDialogue: 0,0:17:55.66,0:17:58.24,Default,,0,0,0,,也就是所谓的“通过CONS组合结果”\nDialogue: 0,0:17:58.24,0:18:06.04,Default,,0,0,0,,那么 对表L缩放S倍 我该如何做呢？\nDialogue: 0,0:18:06.04,0:18:10.40,Default,,0,0,0,,首先得做判断 Lisp中有个叫NULL?的谓词\nDialogue: 0,0:18:10.40,0:18:13.22,Default,,0,0,0,,NULL?判断对象是否为表尾\nDialogue: 0,0:18:13.90,0:18:17.16,Default,,0,0,0,,或者说 对象是否为空表\nDialogue: 0,0:18:18.17,0:18:23.00,Default,,0,0,0,,任何情况下 当我处理到表尾时 我就将其返回\nDialogue: 0,0:18:23.65,0:18:24.60,Default,,0,0,0,,简单地返回NIL\nDialogue: 0,0:18:24.94,0:18:35.14,Default,,0,0,0,,否则 我就用CONS把列表中的第一个元素经过操作（缩放）后的结果\nDialogue: 0,0:18:35.54,0:18:39.29,Default,,0,0,0,,就是说 取L的CAR部分 然后用它乘以S\nDialogue: 0,0:18:40.36,0:18:46.34,Default,,0,0,0,,然后我就用CONS将这个结果 与用递归形式缩放后的表的剩下部分 连接在一起\nDialogue: 0,0:18:49.98,0:18:52.18,Default,,0,0,0,,再说一次 总体的思想是\nDialogue: 0,0:18:52.22,0:18:56.09,Default,,0,0,0,,你要用递归的方式处理表中的剩余元素 即表的CDR部分\nDialogue: 0,0:18:56.48,0:19:01.16,Default,,0,0,0,,然后你用CONS将那部分的结果 与经过处理后的表的第一个元素连接在一起\nDialogue: 0,0:19:01.16,0:19:05.18,Default,,0,0,0,,当你处理到结尾的时候 返回表尾标志NIL\nDialogue: 0,0:19:07.34,0:19:11.36,Default,,0,0,0,,这就是对一个表里的数据做某种操作的通用模式\nDialogue: 0,0:19:14.05,0:19:19.52,Default,,0,0,0,,现在 你们应该清楚知道这样一个事实\nDialogue: 0,0:19:19.53,0:19:22.62,Default,,0,0,0,,也就是我不必额外为这种基本模式额外编写过程\nDialogue: 0,0:19:22.62,0:19:24.90,Default,,0,0,0,,我要做的事情就是写一个过程\nDialogue: 0,0:19:24.90,0:19:26.32,Default,,0,0,0,,这是这个基本模式\nDialogue: 0,0:19:26.80,0:19:30.30,Default,,0,0,0,,对表中的元素执行操作 并以表的形式返回结果\nDialogue: 0,0:19:30.68,0:19:32.30,Default,,0,0,0,,好了 我们定义一些高阶过程\nDialogue: 0,0:19:32.32,0:19:35.18,Default,,0,0,0,,我们定义一个叫MAP的高阶过程 来完成这些操作\nDialogue: 0,0:19:36.73,0:19:43.17,Default,,0,0,0,,MAP以表L和过程P为参数\nDialogue: 0,0:19:44.92,0:19:51.08,Default,,0,0,0,,并返回对表L中每个元素应用过程P后得到的新表\nDialogue: 0,0:19:51.81,0:19:55.40,Default,,0,0,0,,这个新表里的元素是(P E1) (P E2) ...  到(P En)\nDialogue: 0,0:19:55.64,0:20:01.54,Default,,0,0,0,,所以我指的就是对一个表做这样一种变换：将P应用到表的每一个元素上\nDialogue: 0,0:20:02.52,0:20:07.08,Default,,0,0,0,,你们看到的这些过程正是我提到的通用策略\nDialogue: 0,0:20:07.08,0:20:09.08,Default,,0,0,0,,我们用它写乘以10的过程\nDialogue: 0,0:20:09.08,0:20:11.64,Default,,0,0,0,,如果表是空的 则返回NIL\nDialogue: 0,0:20:11.86,0:20:16.60,Default,,0,0,0,,否则 对表的首元素应用P\nDialogue: 0,0:20:17.14,0:20:18.74,Default,,0,0,0,,将P应用于L的CAR部分\nDialogue: 0,0:20:19.30,0:20:25.40,Default,,0,0,0,,然后连接它和将P应用于表CDR部分中的剩余元素得到的子表连接起来\nDialogue: 0,0:20:25.61,0:20:28.84,Default,,0,0,0,,这就是一个通用过程--MAP\nDialogue: 0,0:20:29.86,0:20:39.04,Default,,0,0,0,,我们可以用MAP来定义SCALE-LIST\nDialogue: 0,0:20:39.04,0:20:41.04,Default,,0,0,0,,我给你们展示一下\nDialogue: 0,0:20:43.46,0:20:52.50,Default,,0,0,0,,SCALE-LIST就是对表MAP一个特定的过程\nDialogue: 0,0:20:52.50,0:20:55.54,Default,,0,0,0,,这个过程需要一个参数 返回给定参数乘以S的结果\nDialogue: 0,0:20:58.96,0:21:01.90,Default,,0,0,0,,所以我思考缩放表这个过程的正确方式应该是\nDialogue: 0,0:21:02.12,0:21:07.40,Default,,0,0,0,,将这种递归实质实现为通用策略 而不是一个具体针对的过程\nDialogue: 0,0:21:07.40,0:21:11.28,Default,,0,0,0,,当然 这样做的意义之一是 是你会开始发现共性\nDialogue: 0,0:21:12.16,0:21:15.02,Default,,0,0,0,,我们正在掌握使用通用模式\nDialogue: 0,0:21:15.96,0:21:31.18,Default,,0,0,0,,比如 (MAP SQUARE 1-TO-4) 返回(1 4 9 16)\nDialogue: 0,0:21:32.48,0:21:37.17,Default,,0,0,0,,对这个表做映射\nDialogue: 0,0:21:37.57,0:21:46.32,Default,,0,0,0,,用(LAMBDA (X) (+ X 10))映射表1-TO-4\nDialogue: 0,0:21:49.68,0:21:52.86,Default,,0,0,0,,我让表的每个元素都加了10\nDialogue: 0,0:21:53.34,0:21:58.17,Default,,0,0,0,,也就是得到了(11 12 13 14)\nDialogue: 0,0:22:00.56,0:22:05.76,Default,,0,0,0,,我们看到对表中每个元素做操作是一种非常普遍的想法\nDialogue: 0,0:22:08.66,0:22:12.22,Default,,0,0,0,,而大家需要思考如何编写MAP的迭代版本\nDialogue: 0,0:22:12.22,0:22:16.04,Default,,0,0,0,,我碰巧写的是一个递归版本\nDialogue: 0,0:22:16.36,0:22:19.10,Default,,0,0,0,,但是我们也可以很容易地把它改成迭代过程\nDialogue: 0,0:22:19.10,0:22:23.16,Default,,0,0,0,,有趣的是 一旦你开始用MAP来思考\nDialogue: 0,0:22:24.02,0:22:29.00,Default,,0,0,0,,比如 一旦把缩放看作是一种MAP 就不用关心是迭代还是递归实现\nDialogue: 0,0:22:29.00,0:22:31.82,Default,,0,0,0,,你只会关心 啊 这里有这样一种数据集合 有这样一个表\nDialogue: 0,0:22:32.22,0:22:34.52,Default,,0,0,0,,我要做的是转化表中的每个元素\nDialogue: 0,0:22:34.56,0:22:38.36,Default,,0,0,0,,而不去考虑特别的控制流程或顺序\nDialogue: 0,0:22:38.88,0:22:41.09,Default,,0,0,0,,这是个非常非常重要的想法\nDialogue: 0,0:22:42.36,0:22:46.48,Default,,0,0,0,,我猜这个想法来自APL语言\nDialogue: 0,0:22:46.48,0:22:49.10,Default,,0,0,0,,它是APL中非常重要的思想\nDialogue: 0,0:22:49.12,0:22:51.13,Default,,0,0,0,,即不要去考虑控制结构\nDialogue: 0,0:22:51.41,0:22:53.92,Default,,0,0,0,,而是关注于策略操作\nDialogue: 0,0:22:55.01,0:23:00.01,Default,,0,0,0,,在本课程进行到一半的时候 我们将讨论一种叫做流处理的东西\nDialogue: 0,0:23:00.26,0:23:02.64,Default,,0,0,0,,那时我们将看到这种观点的真正威力\nDialogue: 0,0:23:02.64,0:23:05.30,Default,,0,0,0,,这是一种很聪明的思想\nDialogue: 0,0:23:05.30,0:23:08.70,Default,,0,0,0,,我们可以在以后看到更多应用\nDialogue: 0,0:23:09.36,0:23:16.84,Default,,0,0,0,,还有一些非常有用也非常像MAP的过程\nDialogue: 0,0:23:17.56,0:23:22.54,Default,,0,0,0,,MAP是将某个过程应用于表中每个元素\nDialogue: 0,0:23:22.98,0:23:25.62,Default,,0,0,0,,并返回相应结果构成的表\nDialogue: 0,0:23:25.98,0:23:28.69,Default,,0,0,0,,还有一种与此非常非常相似的操作\nDialogue: 0,0:23:29.32,0:23:35.86,Default,,0,0,0,,也就是给定一个列表和操作 依次将其应用于表中每个元素\nDialogue: 0,0:23:36.29,0:23:39.40,Default,,0,0,0,,而不会建立由结果构成的表 只是为了完成操作\nDialogue: 0,0:23:40.02,0:23:45.10,Default,,0,0,0,,这个过程非常像MAP\nDialogue: 0,0:23:45.10,0:23:46.02,Default,,0,0,0,,它就是FOR-EACH\nDialogue: 0,0:23:46.74,0:23:49.48,Default,,0,0,0,,它接受一个过程和一个表\nDialogue: 0,0:23:49.62,0:23:53.86,Default,,0,0,0,,它实际上是对表中每个元素执行此操作\nDialogue: 0,0:23:55.16,0:23:58.53,Default,,0,0,0,,通常是这样 如果表非空\nDialogue: 0,0:23:59.74,0:24:01.12,Default,,0,0,0,,也就是不为NIL\nDialogue: 0,0:24:01.90,0:24:06.25,Default,,0,0,0,,我将这个过程应用于表的第一个元素\nDialogue: 0,0:24:07.68,0:24:11.66,Default,,0,0,0,,然后对表中其余元素做同样的事情\nDialogue: 0,0:24:12.44,0:24:15.25,Default,,0,0,0,,我将FOR-EACH也应用于表的CDR部分\nDialogue: 0,0:24:15.88,0:24:18.73,Default,,0,0,0,,我对表的首元素进行处理 然后对表其余部分进行处理\nDialogue: 0,0:24:19.32,0:24:23.92,Default,,0,0,0,,当然 以此类推 递归地调用 又会对表其余部分的其余部分做处理\nDialogue: 0,0:24:23.92,0:24:28.12,Default,,0,0,0,,最终 过程结束时 我应该告知系统\nDialogue: 0,0:24:28.16,0:24:32.40,Default,,0,0,0,,所以就返回“DONE” 所以这非常像MAP\nDialogue: 0,0:24:32.80,0:24:35.12,Default,,0,0,0,,它们之间只是返回值不同\nDialogue: 0,0:24:35.48,0:24:39.90,Default,,0,0,0,,比如说 如果我有一个可以在屏幕上打印对象的过程\nDialogue: 0,0:24:40.56,0:24:45.81,Default,,0,0,0,,如果我想打印表中的所有元素 可以调用(FOR-EACH PRINT LIST)\nDialogue: 0,0:24:46.78,0:24:51.33,Default,,0,0,0,,如果我有一系列图表构成的表 想把它们输出在屏幕上\nDialogue: 0,0:24:51.62,0:24:54.86,Default,,0,0,0,,我可以对这个调用(FOR-EACH DISPLAY FIGURES)\nDialogue: 0,0:24:58.18,0:24:59.32,Default,,0,0,0,,有问题么？\nDialogue: 0,0:25:00.62,0:25:04.26,Default,,0,0,0,,学生：除非你明确地指定\nDialogue: 0,0:25:04.30,0:25:07.54,Default,,0,0,0,,Lisp会创建一个你正在处理的对象的新拷贝 是这样么？\nDialogue: 0,0:25:07.54,0:25:09.18,Default,,0,0,0,,教授：对\nDialogue: 0,0:25:09.93,0:25:10.94,Default,,0,0,0,,就是这样\nDialogue: 0,0:25:10.94,0:25:15.14,Default,,0,0,0,,FOR-EACH不创建新列表 它只是对列表的每一个元素进行处理\nDialogue: 0,0:25:15.14,0:25:17.29,Default,,0,0,0,,所以如果你有一堆事情等着做\nDialogue: 0,0:25:18.02,0:25:21.56,Default,,0,0,0,,并且你并不关心这些值 比如打印 绘图\nDialogue: 0,0:25:21.89,0:25:24.60,Default,,0,0,0,,或者在终端中响铃等等\nDialogue: 0,0:25:24.60,0:25:27.64,Default,,0,0,0,,FOR-EACH对表中每个元素做这些事\nDialogue: 0,0:25:28.21,0:25:32.42,Default,,0,0,0,,而MAP其实构建了一个新集合 这个集合也许是你想要用的\nDialogue: 0,0:25:32.42,0:25:34.16,Default,,0,0,0,,这就是它们之间的微妙关系\nDialogue: 0,0:25:34.16,0:25:36.30,Default,,0,0,0,,学生：你能否用FOR-EACH来构造MAP\nDialogue: 0,0:25:36.32,0:25:40.16,Default,,0,0,0,,其中你用类似CONS的操作将表又构造出来了？\nDialogue: 0,0:25:40.18,0:25:44.46,Default,,0,0,0,,教授：某种程度上 我也许可以\nDialogue: 0,0:25:44.46,0:25:49.98,Default,,0,0,0,,我不知道如何随手写出它 但是我可以给一些思路\nDialogue: 0,0:25:50.48,0:25:54.73,Default,,0,0,0,,学生：根据昨天的课程 我认为MAP和FOR-EACH的关键区别在于\nDialogue: 0,0:25:54.73,0:26:00.62,Default,,0,0,0,,它们之中一个是递归的 而另一个不是\nDialogue: 0,0:26:01.24,0:26:03.86,Default,,0,0,0,,教授：是的 关于MAP和FOR-EACH和递归\nDialogue: 0,0:26:03.86,0:26:05.48,Default,,0,0,0,,这个观点很好\nDialogue: 0,0:26:05.48,0:26:13.08,Default,,0,0,0,,我写的MAP过程恰巧是一个递归过程\nDialogue: 0,0:26:13.82,0:26:17.06,Default,,0,0,0,,这是因为 你需要得到处理完表的剩余部分后的值\nDialogue: 0,0:26:17.08,0:26:20.96,Default,,0,0,0,,使其与表的开头部分相连\nDialogue: 0,0:26:21.73,0:26:24.53,Default,,0,0,0,,但是FOR-EACH不需要等待返回值\nDialogue: 0,0:26:24.84,0:26:26.66,Default,,0,0,0,,所以它变成了一个迭代的过程\nDialogue: 0,0:26:26.66,0:26:27.72,Default,,0,0,0,,这不是本质\nDialogue: 0,0:26:27.72,0:26:31.80,Default,,0,0,0,,我可以用迭代的方式定义MAP过程\nDialogue: 0,0:26:31.82,0:26:32.82,Default,,0,0,0,,只是我没那么做\nDialogue: 0,0:26:34.24,0:26:42.90,Default,,0,0,0,,学生：将FOR-EACH用在一个列表的列表上的话 我想这是可行的吧？\nDialogue: 0,0:26:42.90,0:26:48.10,Default,,0,0,0,,它会对这些内部列表的元素进行处理么？\nDialogue: 0,0:26:48.70,0:26:50.40,Default,,0,0,0,,教授：问题是 如果我调用\nDialogue: 0,0:26:50.40,0:26:52.28,Default,,0,0,0,,FOR-EACH或者MAP\nDialogue: 0,0:26:52.81,0:26:55.28,Default,,0,0,0,,参数是一个嵌套有一个表的表\nDialogue: 0,0:26:56.69,0:27:00.60,Default,,0,0,0,,虽然我们还没有讲过这个 但是那是可行的\nDialogue: 0,0:27:01.02,0:27:06.56,Default,,0,0,0,,答案是肯定的 不过我俩对“可行”的定义可能有些不同\nDialogue: 0,0:27:06.86,0:27:10.65,Default,,0,0,0,,来看一下 如果我给你一个表\nDialogue: 0,0:27:12.80,0:27:14.20,Default,,0,0,0,,而在个箭头所指的\nDialogue: 0,0:27:16.06,0:27:21.46,Default,,0,0,0,,不是一个数 而是一个表 或者序对 或者是其它东西\nDialogue: 0,0:27:21.96,0:27:24.54,Default,,0,0,0,,FOR-EACH对表中的每个元素做处理\nDialogue: 0,0:27:24.54,0:27:26.96,Default,,0,0,0,,它会不断地处理表CDR部分\nDialogue: 0,0:27:26.96,0:27:27.20,Default,,0,0,0,,学生：嗯\nDialogue: 0,0:27:27.20,0:27:31.06,Default,,0,0,0,,教授：对FOR-EACH来说 表中的第一个元素就是这个箭头所指的东西\nDialogue: 0,0:27:31.06,0:27:31.65,Default,,0,0,0,,学生：唔\nDialogue: 0,0:27:31.65,0:27:33.94,Default,,0,0,0,,教授：这对于你要完成的任务而言 也许是对的 也许不是\nDialogue: 0,0:27:33.94,0:27:35.57,Default,,0,0,0,,学生：所以不能进入子表中\nDialogue: 0,0:27:35.57,0:27:36.91,Default,,0,0,0,,教授：绝对不能\nDialogue: 0,0:27:36.91,0:27:38.51,Default,,0,0,0,,当然我也可以那样写程序\nDialogue: 0,0:27:38.51,0:27:42.97,Default,,0,0,0,,你所说的是另一种公共模式 叫做树递归\nDialogue: 0,0:27:43.01,0:27:47.94,Default,,0,0,0,,当你给它一个表 它会不断向深度递归 直到遇到所谓的“树叶”\nDialogue: 0,0:27:47.94,0:27:51.05,Default,,0,0,0,,你可以写出来这个过程 但是它既不是FOR-EACH也不是MAP\nDialogue: 0,0:27:52.42,0:27:55.05,Default,,0,0,0,,FOR-EACH和MAP都很简单\nDialogue: 0,0:27:55.77,0:27:56.89,Default,,0,0,0,,好 还有问题么？\nDialogue: 0,0:27:57.68,0:27:58.57,Default,,0,0,0,,好的 大家休息一下吧\nDialogue: 0,0:27:59.11,0:28:10.99,Default,,0,0,0,,[音乐]\nDialogue: 0,0:28:11.46,0:28:14.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:14.32,0:28:17.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:28:27.38,0:28:34.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:34.86,0:28:38.58,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson-Escher的例子\nDialogue: 0,0:28:41.94,0:28:48.65,Default,,0,0,0,,教授：我将在本节课余下的时间中 讨论一个实例\nDialogue: 0,0:28:50.04,0:28:53.92,Default,,0,0,0,,这个实例 可以充分地总结我们所学的所有东西\nDialogue: 0,0:28:54.74,0:28:56.29,Default,,0,0,0,,比如 表结构\nDialogue: 0,0:28:57.17,0:28:59.48,Default,,0,0,0,,以及抽象的技术\nDialogue: 0,0:28:59.54,0:29:00.82,Default,,0,0,0,,数据的表示\nDialogue: 0,0:29:01.60,0:29:04.60,Default,,0,0,0,,和用高阶过程描绘共性\nDialogue: 0,0:29:04.60,0:29:09.80,Default,,0,0,0,,也会介绍目前为止还没怎么谈论过的\nDialogue: 0,0:29:09.85,0:29:13.46,Default,,0,0,0,,也就是这门课的第三大主题\nDialogue: 0,0:29:13.96,0:29:15.53,Default,,0,0,0,,元语言抽象\nDialogue: 0,0:29:15.54,0:29:21.90,Default,,0,0,0,,这种在工程设计中控制复杂度的思想\nDialogue: 0,0:29:22.86,0:29:25.80,Default,,0,0,0,,也就是建立一个合适而强大的语言\nDialogue: 0,0:29:28.17,0:29:34.74,Default,,0,0,0,,你们或许记得 我说过在这门课程中 你们将要学到的最重要的事情是\nDialogue: 0,0:29:34.74,0:29:41.17,Default,,0,0,0,,当我们考察一门语言时 关心的是它的基本元素\nDialogue: 0,0:29:42.98,0:29:46.69,Default,,0,0,0,,关心它的组合方法\nDialogue: 0,0:29:49.72,0:29:52.80,Default,,0,0,0,,关心那些让你能够构建更大东西的东西\nDialogue: 0,0:29:53.61,0:29:55.24,Default,,0,0,0,,以及 抽象的方式\nDialogue: 0,0:30:00.97,0:30:05.16,Default,,0,0,0,,如何取用这些你构造出来的“大东西”\nDialogue: 0,0:30:05.56,0:30:07.97,Default,,0,0,0,,并将它们放入“黑盒”中\nDialogue: 0,0:30:08.45,0:30:11.71,Default,,0,0,0,,然后用它们来构建更复杂的东西\nDialogue: 0,0:30:13.53,0:30:18.72,Default,,0,0,0,,我将要介绍的一种语言 就是元语言抽象的一个例子\nDialogue: 0,0:30:18.73,0:30:22.70,Default,,0,0,0,,那是我朋友Peter Handerson发明的\nDialogue: 0,0:30:28.24,0:30:31.74,Default,,0,0,0,,他来自苏格兰的Stirling大学\nDialogue: 0,0:30:32.78,0:30:40.98,Default,,0,0,0,,这个语言是用来画这样的图\nDialogue: 0,0:30:41.86,0:30:46.66,Default,,0,0,0,,这是埃舍尔的木版画 《方形极限》\nDialogue: 0,0:30:49.33,0:30:57.94,Default,,0,0,0,,正如大家所见 这里面有着很复杂的...图像的递归\nDialogue: 0,0:30:58.84,0:31:01.46,Default,,0,0,0,,其中中间的鱼形图案以自相似的方式\nDialogue: 0,0:31:01.70,0:31:04.56,Default,,0,0,0,,不断地以更小的形式出现在原来的团案旁边\nDialogue: 0,0:31:08.49,0:31:12.80,Default,,0,0,0,,总之 Peter Hendersion的语言是用来表述这类图形\nDialogue: 0,0:31:13.37,0:31:18.28,Default,,0,0,0,,并且设计类似的图形 将它画在显示器上\nDialogue: 0,0:31:20.24,0:31:27.48,Default,,0,0,0,,这个例子还展示了另外一个主题\nDialogue: 0,0:31:28.09,0:31:32.02,Default,,0,0,0,,这也是我跟Gerry教授多次强调的\nDialogue: 0,0:31:32.02,0:31:36.17,Default,,0,0,0,,也就是过程跟数据之间没有本质的区别\nDialogue: 0,0:31:37.26,0:31:42.40,Default,,0,0,0,,不管如何 我希望今早课程结束后\nDialogue: 0,0:31:42.58,0:31:47.60,Default,,0,0,0,,你们能将过程和数据当作一回事儿\nDialogue: 0,0:31:47.96,0:31:49.58,Default,,0,0,0,,即使现在你们还将它们区别对待\nDialogue: 0,0:31:50.80,0:31:55.28,Default,,0,0,0,,那么 先让我们看一下Peter的语言\nDialogue: 0,0:31:55.28,0:31:57.26,Default,,0,0,0,,我先告诉你们基本元素是什么\nDialogue: 0,0:31:58.29,0:32:00.92,Default,,0,0,0,,这个语言非常简单 因为它的基本元素只有一个\nDialogue: 0,0:32:03.33,0:32:06.30,Default,,0,0,0,,这个基本元素不是大家想象的那样\nDialogue: 0,0:32:07.08,0:32:09.18,Default,,0,0,0,,它唯一的基本元素叫做\"图像\"\nDialogue: 0,0:32:09.70,0:32:12.11,Default,,0,0,0,,但此“图像”非彼“图像”\nDialogue: 0,0:32:12.11,0:32:14.17,Default,,0,0,0,,具体地来说\nDialogue: 0,0:32:14.17,0:32:15.17,Default,,0,0,0,,这是George的图像\nDialogue: 0,0:32:19.01,0:32:20.37,Default,,0,0,0,,我们的想法是\nDialogue: 0,0:32:22.33,0:32:24.57,Default,,0,0,0,,在这个语言中的图像是这样一个东西\nDialogue: 0,0:32:24.89,0:32:31.46,Default,,0,0,0,,它能在你指定的一个矩形里画出一个缩放好图像\nDialogue: 0,0:32:33.00,0:32:34.42,Default,,0,0,0,,这里大家看到的强调线\nDialogue: 0,0:32:34.42,0:32:37.70,Default,,0,0,0,,是这个矩形的轮廓 但不是图像的一部分\nDialogue: 0,0:32:40.49,0:32:47.17,Default,,0,0,0,,但是一旦指定一个矩形区域 图像会以以填充的方式绘制满区域\nDialogue: 0,0:32:47.17,0:32:52.16,Default,,0,0,0,,比如 这个是George 在这里 这个也是George\nDialogue: 0,0:32:53.21,0:32:56.65,Default,,0,0,0,,它是同一个图像 只是缩放程度不同\nDialogue: 0,0:32:57.40,0:32:59.28,Default,,0,0,0,,这是“胖”George的版本\nDialogue: 0,0:33:00.01,0:33:03.44,Default,,0,0,0,,这个也是George\nDialogue: 0,0:33:03.81,0:33:05.14,Default,,0,0,0,,这是同一个图形\nDialogue: 0,0:33:05.14,0:33:09.57,Default,,0,0,0,,这个语言中 这三个都是同一个图像\nDialogue: 0,0:33:09.58,0:33:13.04,Default,,0,0,0,,仅仅是给了不同的矩形区域让它来填充\nDialogue: 0,0:33:16.08,0:33:20.65,Default,,0,0,0,,这就是基本元素\nDialogue: 0,0:33:21.44,0:33:25.25,Default,,0,0,0,,现在 我们来讨论元素组合和操作\nDialogue: 0,0:33:25.90,0:33:30.17,Default,,0,0,0,,比如 这里有一个叫做旋转的操作\nDialogue: 0,0:33:31.09,0:33:33.66,Default,,0,0,0,,如果我有一个图像 “旋转”操作就是\nDialogue: 0,0:33:35.37,0:33:39.93,Default,,0,0,0,,先假定有一个里面有个“A”的矩形\nDialogue: 0,0:33:41.84,0:33:45.73,Default,,0,0,0,,而旋转90度的操作则会\nDialogue: 0,0:33:47.02,0:33:50.65,Default,,0,0,0,,在一个给定的矩形内 绘制同样的图像\nDialogue: 0,0:33:50.65,0:33:53.88,Default,,0,0,0,,但是 会缩放图像以适应矩形\nDialogue: 0,0:33:56.11,0:33:58.34,Default,,0,0,0,,这个就是旋转90度\nDialogue: 0,0:33:58.34,0:34:03.20,Default,,0,0,0,,另一个操作是“翻转” 可以水平翻转也可以竖直翻转\nDialogue: 0,0:34:04.77,0:34:06.00,Default,,0,0,0,,就是这些操作了\nDialogue: 0,0:34:06.01,0:34:10.40,Default,,0,0,0,,或者你可以把它们认为是组合一个元素的各种方式\nDialogue: 0,0:34:10.89,0:34:12.42,Default,,0,0,0,,我可以把它们混合起来\nDialogue: 0,0:34:13.44,0:34:15.54,Default,,0,0,0,,我们有一种叫BESIDE的操作\nDialogue: 0,0:34:16.46,0:34:24.78,Default,,0,0,0,,它做的事情是 给定两个图像A、B --\nDialogue: 0,0:34:29.02,0:34:33.25,Default,,0,0,0,,这里图像是指能在指定的矩形中画一个图案的东西 --\nDialogue: 0,0:34:34.05,0:34:36.51,Default,,0,0,0,,BESIDE将会做的事情\nDialogue: 0,0:34:37.85,0:34:44.08,Default,,0,0,0,,类似于调用(BESIDE A B S) 其中S是一个数\nDialogue: 0,0:34:45.34,0:34:48.08,Default,,0,0,0,,是一个在0到1之间的数\nDialogue: 0,0:34:50.51,0:34:52.57,Default,,0,0,0,,BESIDE绘制像这样的图像\nDialogue: 0,0:34:52.57,0:34:56.71,Default,,0,0,0,,以给定的矩形为基础 但会将基底缩放S\nDialogue: 0,0:34:56.71,0:34:58.71,Default,,0,0,0,,这里S是0.5\nDialogue: 0,0:35:00.18,0:35:07.17,Default,,0,0,0,,在这里 它会在这里画第一个图案\nDialogue: 0,0:35:07.81,0:35:12.65,Default,,0,0,0,,在这里画第二个图案\nDialogue: 0,0:35:13.82,0:35:16.44,Default,,0,0,0,,又比如说 我另设一个S的值\nDialogue: 0,0:35:16.81,0:35:23.02,Default,,0,0,0,,比如调用(BESIDE A B 0.25)\nDialogue: 0,0:35:25.94,0:35:29.09,Default,,0,0,0,,效果相同 只不过A更瘦了\nDialogue: 0,0:35:34.05,0:35:36.28,Default,,0,0,0,,而B是这样的\nDialogue: 0,0:35:37.82,0:35:40.29,Default,,0,0,0,,这就是组合方法之一：BESIDE\nDialogue: 0,0:35:40.68,0:35:46.05,Default,,0,0,0,,类似地 ABOVE方法在竖直方向上做这种操作\nDialogue: 0,0:35:47.84,0:35:48.89,Default,,0,0,0,,我们来看一下\nDialogue: 0,0:35:50.74,0:35:56.00,Default,,0,0,0,,这是George和他的\"弟弟\"\nDialogue: 0,0:35:56.72,0:36:07.05,Default,,0,0,0,,这是通过将George放在一旁\nDialogue: 0,0:36:10.36,0:36:14.42,Default,,0,0,0,,George与空图像的上下组合放在另一旁\nDialogue: 0,0:36:14.52,0:36:16.14,Default,,0,0,0,,这样做的意图很明显\nDialogue: 0,0:36:16.14,0:36:19.14,Default,,0,0,0,,空图像放在了另一个George的上面\nDialogue: 0,0:36:19.14,0:36:21.14,Default,,0,0,0,,合成的图像又放在了George的旁边\nDialogue: 0,0:36:28.96,0:36:30.34,Default,,0,0,0,,这个是图像P\nDialogue: 0,0:36:31.10,0:36:39.04,Default,,0,0,0,,像之前一样 是George和翻转后George的BESIDE组合\nDialogue: 0,0:36:40.53,0:36:42.08,Default,,0,0,0,,这里 我们做的是水平翻转\nDialogue: 0,0:36:42.37,0:36:44.80,Default,,0,0,0,,然后整体旋转180度\nDialogue: 0,0:36:45.80,0:36:50.82,Default,,0,0,0,,然后调用BESIDE让它们组合在一起 系数是0.5\nDialogue: 0,0:36:52.56,0:36:53.90,Default,,0,0,0,,这样 我创建了图像P\nDialogue: 0,0:36:55.90,0:36:57.88,Default,,0,0,0,,然后使用图像P\nDialogue: 0,0:36:59.21,0:37:04.96,Default,,0,0,0,,与它的翻转图像做ABOVE操作 形成图像Q\nDialogue: 0,0:37:09.20,0:37:13.26,Default,,0,0,0,,请注意 我们是如何快速地增加复杂度\nDialogue: 0,0:37:14.36,0:37:21.05,Default,,0,0,0,,转瞬之间 我们使用George组合得到了Q 这说明了什么？\nDialogue: 0,0:37:22.05,0:37:24.55,Default,,0,0,0,,为什么我们可以做得如此迅速呢?\nDialogue: 0,0:37:25.85,0:37:28.02,Default,,0,0,0,,答案是闭包性质\nDialogue: 0,0:37:28.69,0:37:32.98,Default,,0,0,0,,这是因为 当我将两个图像做BESIDE操作后\nDialogue: 0,0:37:34.30,0:37:35.29,Default,,0,0,0,,得到的也是图像\nDialogue: 0,0:37:35.33,0:37:37.78,Default,,0,0,0,,我可以继续执行 ROTATE FLIP 或者 ABOVE操作\nDialogue: 0,0:37:39.17,0:37:40.88,Default,,0,0,0,,而操作的结果P\nDialogue: 0,0:37:40.89,0:37:44.88,Default,,0,0,0,,BESIDE FLIP ROTATE操作的结果也是一个图像\nDialogue: 0,0:37:45.22,0:37:50.20,Default,,0,0,0,,在这种组合方法下 图像的世界是封闭的\nDialogue: 0,0:37:50.77,0:37:52.24,Default,,0,0,0,,所以 任何时候我都可以\nDialogue: 0,0:37:52.48,0:37:55.17,Default,,0,0,0,,以一个东西为基本元素 去构造别的东西\nDialogue: 0,0:37:56.33,0:37:58.52,Default,,0,0,0,,这个例子比表和线段更直观\nDialogue: 0,0:37:58.54,0:38:03.28,Default,,0,0,0,,它揭示了 我们如和用封闭的操作 快速增加复杂度\nDialogue: 0,0:38:07.48,0:38:12.02,Default,,0,0,0,,在构建更多东西之前\nDialogue: 0,0:38:12.04,0:38:14.77,Default,,0,0,0,,我们先来看看这个语言是如何实现的\nDialogue: 0,0:38:16.91,0:38:21.50,Default,,0,0,0,,其中基本的一个元素\nDialogue: 0,0:38:21.93,0:38:24.52,Default,,0,0,0,,是一个称作“矩形”的东西\nDialogue: 0,0:38:26.09,0:38:28.28,Default,,0,0,0,,所谓的矩形就是\nDialogue: 0,0:38:28.28,0:38:33.68,Default,,0,0,0,,它有一个原点\nDialogue: 0,0:38:36.45,0:38:40.18,Default,,0,0,0,,原点是一个向量 用以说明矩形是从哪开始\nDialogue: 0,0:38:40.18,0:38:42.29,Default,,0,0,0,,至于其它的向量\nDialogue: 0,0:38:43.66,0:38:46.33,Default,,0,0,0,,我们称其为矩形的水平分量\nDialogue: 0,0:38:55.76,0:38:59.25,Default,,0,0,0,,还有就是矩形的竖直分量\nDialogue: 0,0:39:00.49,0:39:02.68,Default,,0,0,0,,这就是构成矩形的三个基本元素\nDialogue: 0,0:39:02.68,0:39:04.51,Default,,0,0,0,,两个向量用作\nDialogue: 0,0:39:04.93,0:39:09.97,Default,,0,0,0,,计算左上角和右下角的顶点坐标\nDialogue: 0,0:39:09.97,0:39:12.37,Default,,0,0,0,,这三个向量确定了一个矩形\nDialogue: 0,0:39:16.00,0:39:18.93,Default,,0,0,0,,为了构建矩形 我们假设\nDialogue: 0,0:39:19.77,0:39:22.06,Default,,0,0,0,,假设有个“构建矩形”的构造函数\nDialogue: 0,0:39:23.01,0:39:24.26,Default,,0,0,0,,也就是MAKE-RECT\nDialogue: 0,0:39:27.56,0:39:35.17,Default,,0,0,0,,以及选择函数 HORIZ、VERT 和 ORIGIN\nDialogue: 0,0:39:37.58,0:39:39.65,Default,,0,0,0,,用于取得对应的矩形属性\nDialogue: 0,0:39:39.65,0:39:42.54,Default,,0,0,0,,我们知道有很多方法可以实现它\nDialogue: 0,0:39:42.54,0:39:47.62,Default,,0,0,0,,可以用序对或者表 或者其它东西\nDialogue: 0,0:39:47.62,0:39:51.40,Default,,0,0,0,,但是 这些东西的实现是George的事\nDialogue: 0,0:39:51.40,0:39:53.17,Default,,0,0,0,,这是一个数据表示的问题\nDialogue: 0,0:39:53.17,0:39:55.47,Default,,0,0,0,,现在我们假设已经有了这些矩形了\nDialogue: 0,0:39:59.05,0:40:05.08,Default,,0,0,0,,好的 现在来看我们接下来要做的事情\nDialogue: 0,0:40:05.08,0:40:08.22,Default,,0,0,0,,我们需要关心如何取用图像\nDialogue: 0,0:40:09.33,0:40:12.97,Default,,0,0,0,,将它缩放以适应你给定的矩形\nDialogue: 0,0:40:13.60,0:40:16.60,Default,,0,0,0,,我们要来安排这些事\nDialogue: 0,0:40:16.60,0:40:18.60,Default,,0,0,0,,来完成图像的缩放\nDialogue: 0,0:40:22.22,0:40:23.65,Default,,0,0,0,,有哪些思路呢？\nDialogue: 0,0:40:23.65,0:40:27.08,Default,,0,0,0,,一种想法是：无论何时给定一个矩形\nDialogue: 0,0:40:35.68,0:40:38.68,Default,,0,0,0,,无论何时给定一个矩形 也就是说\nDialogue: 0,0:40:39.25,0:40:45.77,Default,,0,0,0,,这在某种意义上是把正方形转换成矩形\nDialogue: 0,0:40:45.77,0:40:46.54,Default,,0,0,0,,也就是说\nDialogue: 0,0:40:46.54,0:40:48.53,Default,,0,0,0,,我所谓的正方形\nDialogue: 0,0:40:49.04,0:40:59.04,Default,,0,0,0,,它的坐标是(0,0)、(1,0)和(1,1)\nDialogue: 0,0:41:01.40,0:41:05.72,Default,,0,0,0,,我们有一些显而易见的缩放变换\nDialogue: 0,0:41:06.12,0:41:10.22,Default,,0,0,0,,可以把这个映射成这个 把这个映射成这个\nDialogue: 0,0:41:10.24,0:41:12.08,Default,,0,0,0,,并且 把所有的东西统一地拉伸\nDialogue: 0,0:41:12.17,0:41:18.25,Default,,0,0,0,,我们将这样的一条的线段\nDialogue: 0,0:41:19.73,0:41:24.20,Default,,0,0,0,,将它最终映射到像那样的一条线段\nDialogue: 0,0:41:26.20,0:41:32.68,Default,,0,0,0,,而点(X,Y)变成了这里的另外一个点\nDialogue: 0,0:41:32.68,0:41:39.37,Default,,0,0,0,,这个不紧要 会点向量运算 就能写出变换公式\nDialogue: 0,0:41:39.37,0:41:43.18,Default,,0,0,0,,初始点(X,Y)将会变换到的点的坐标是\nDialogue: 0,0:41:43.58,0:41:50.74,Default,,0,0,0,,以矩形原点为基础做向量加法\nDialogue: 0,0:41:51.16,0:41:55.48,Default,,0,0,0,,加上 初始点X坐标 一个介于0和1之间的值\nDialogue: 0,0:41:55.98,0:42:01.84,Default,,0,0,0,,并乘上矩形的水平向量\nDialogue: 0,0:42:07.62,0:42:11.00,Default,,0,0,0,,再加上初始点的Y坐标 也是一个介于0和1的值\nDialogue: 0,0:42:11.38,0:42:16.28,Default,,0,0,0,,并乘上矩形的竖直向量\nDialogue: 0,0:42:16.74,0:42:19.31,Default,,0,0,0,,这是简单的线性代数\nDialogue: 0,0:42:19.31,0:42:23.48,Default,,0,0,0,,这个就是正确的变换公式\nDialogue: 0,0:42:23.69,0:42:28.18,Default,,0,0,0,,它将方形中的物件转化到对应矩形中\nDialogue: 0,0:42:31.34,0:42:34.02,Default,,0,0,0,,现在 我们把它看作是一个过程\nDialogue: 0,0:42:35.16,0:42:36.29,Default,,0,0,0,,我们想要得到的是\nDialogue: 0,0:42:37.80,0:42:40.82,Default,,0,0,0,,由一个单位正方形到特定矩形的\nDialogue: 0,0:42:41.01,0:42:42.52,Default,,0,0,0,,特定变换过程\nDialogue: 0,0:42:43.80,0:42:45.22,Default,,0,0,0,,这个过程具体是这样的\nDialogue: 0,0:42:45.22,0:42:47.22,Default,,0,0,0,,我叫它COORD-MAP\nDialogue: 0,0:42:47.77,0:42:52.00,Default,,0,0,0,,COORD-MAP以一个矩形作为参数\nDialogue: 0,0:42:53.60,0:42:57.85,Default,,0,0,0,,它返回一个以点为参数的过程\nDialogue: 0,0:43:00.45,0:43:06.82,Default,,0,0,0,,每个矩形 都对应一个变换点(X, Y)坐标的过程\nDialogue: 0,0:43:06.82,0:43:08.02,Default,,0,0,0,,是怎么得到的呢？\nDialogue: 0,0:43:08.02,0:43:10.92,Default,,0,0,0,,就如黑板上的Lisp代码所示\nDialogue: 0,0:43:10.92,0:43:16.01,Default,,0,0,0,,我让矩形的原点加上--\nDialogue: 0,0:43:20.22,0:43:25.02,Default,,0,0,0,,首先是 矩形水平部分\nDialogue: 0,0:43:25.02,0:43:27.68,Default,,0,0,0,,按照点POINT的X坐标缩放\nDialogue: 0,0:43:29.65,0:43:32.62,Default,,0,0,0,,然后是 矩形竖直部分\nDialogue: 0,0:43:33.51,0:43:37.14,Default,,0,0,0,,按照点POINT的Y坐标缩放\nDialogue: 0,0:43:37.14,0:43:39.14,Default,,0,0,0,,然后把它们三个加到一起\nDialogue: 0,0:43:40.13,0:43:41.34,Default,,0,0,0,,这个过程就是这样\nDialogue: 0,0:43:41.34,0:43:44.54,Default,,0,0,0,,这就是我将要应用在点POINT上的过程\nDialogue: 0,0:43:46.54,0:43:52.17,Default,,0,0,0,,这个过程由每个矩形自己生成\nDialogue: 0,0:43:52.17,0:43:57.25,Default,,0,0,0,,每个矩形对应了一个定义在点集上的过程 COORD-MAP\nDialogue: 0,0:44:06.66,0:44:10.42,Default,,0,0,0,,比如说 这里的George\nDialogue: 0,0:44:11.36,0:44:16.34,Default,,0,0,0,,最初的George 可能是我在单位正方形中通过线段绘制的\nDialogue: 0,0:44:19.50,0:44:21.96,Default,,0,0,0,,而当我把它应用到一个新的矩形中\nDialogue: 0,0:44:24.14,0:44:28.17,Default,,0,0,0,,我将会在新矩形中画出组成George的那些线段来\nDialogue: 0,0:44:28.17,0:44:29.88,Default,,0,0,0,,我是怎么做的呢？\nDialogue: 0,0:44:30.68,0:44:36.94,Default,,0,0,0,,我枚举原始George中的每条线段\nDialogue: 0,0:44:38.64,0:44:40.58,Default,,0,0,0,,我对每条线段的终点\nDialogue: 0,0:44:40.88,0:44:44.45,Default,,0,0,0,,应用目标矩形对应的COORD-MAP过程\nDialogue: 0,0:44:44.45,0:44:46.06,Default,,0,0,0,,比如下面的这个矩形\nDialogue: 0,0:44:46.66,0:44:50.88,Default,,0,0,0,,这个胖George 有它对应的COORD-MAP\nDialogue: 0,0:44:51.25,0:44:53.69,Default,,0,0,0,,如果我要绘制这个图像\nDialogue: 0,0:44:55.38,0:44:57.92,Default,,0,0,0,,需要做的就是对这里的每条线段 比如这条\nDialogue: 0,0:44:59.29,0:45:05.34,Default,,0,0,0,,用COORD-MAP变换这个点 同时变换这个点\nDialogue: 0,0:45:05.34,0:45:07.09,Default,,0,0,0,,我就得到了这两个点\nDialogue: 0,0:45:07.38,0:45:08.94,Default,,0,0,0,,就可以将在两点之间画线\nDialogue: 0,0:45:09.71,0:45:11.52,Default,,0,0,0,,这就是核心思路\nDialogue: 0,0:45:12.66,0:45:14.78,Default,,0,0,0,,那么如果我给一个不同的矩形 比如这个\nDialogue: 0,0:45:14.80,0:45:15.76,Default,,0,0,0,,得到的是不同的COORD-MAP\nDialogue: 0,0:45:15.79,0:45:17.84,Default,,0,0,0,,因此我得到这些线段的不同图像\nDialogue: 0,0:45:19.28,0:45:22.14,Default,,0,0,0,,基本图像又该如何表示呢？\nDialogue: 0,0:45:22.14,0:45:26.52,Default,,0,0,0,,可以用线段组成的表来表示\nDialogue: 0,0:45:27.61,0:45:32.20,Default,,0,0,0,,这是用于构建我所谓的“基本图像”的过程\nDialogue: 0,0:45:33.48,0:45:37.17,Default,,0,0,0,,意思是 没有用BESIDE ROTATE等操作\nDialogue: 0,0:45:37.52,0:45:39.60,Default,,0,0,0,,它以由线段组成的表为参数\nDialogue: 0,0:45:42.94,0:45:44.04,Default,,0,0,0,,代码具体行为如下\nDialogue: 0,0:45:44.04,0:45:45.58,Default,,0,0,0,,图像会是什么样子呢？\nDialogue: 0,0:45:45.58,0:45:49.44,Default,,0,0,0,,首先 它是一个根据矩形定义的过程\nDialogue: 0,0:45:51.70,0:45:53.00,Default,,0,0,0,,这个过程做什么呢？\nDialogue: 0,0:45:53.00,0:45:56.56,Default,,0,0,0,,对于由线段组成的表中每个元素\nDialogue: 0,0:45:57.66,0:46:03.38,Default,,0,0,0,,表中的每条线段S\nDialogue: 0,0:46:05.89,0:46:07.30,Default,,0,0,0,,都绘制了一条线\nDialogue: 0,0:46:07.30,0:46:08.82,Default,,0,0,0,,它画什么样的线段呢？\nDialogue: 0,0:46:10.60,0:46:12.84,Default,,0,0,0,,先得到线段的起点\nDialogue: 0,0:46:15.22,0:46:17.94,Default,,0,0,0,,用对应的COORD-MAP对其做变换\nDialogue: 0,0:46:19.54,0:46:21.76,Default,,0,0,0,,这是我们想要的第一个点\nDialogue: 0,0:46:21.76,0:46:26.32,Default,,0,0,0,,然后对线段终点做COORD-MAP操作\nDialogue: 0,0:46:26.69,0:46:27.92,Default,,0,0,0,,并将两点连线\nDialogue: 0,0:46:27.92,0:46:30.84,Default,,0,0,0,,我们假设在屏幕上绘制线段是基本操作\nDialogue: 0,0:46:31.09,0:46:33.22,Default,,0,0,0,,已经在系统中实现了\nDialogue: 0,0:46:33.96,0:46:37.10,Default,,0,0,0,,通过COORD-MAP变换了线段终点\nDialogue: 0,0:46:37.13,0:46:38.20,Default,,0,0,0,,再把起点和终点连线\nDialogue: 0,0:46:39.61,0:46:44.12,Default,,0,0,0,,对表中每一条线段S都执行这样的操作\nDialogue: 0,0:46:45.96,0:46:51.40,Default,,0,0,0,,请注意 图像就是一个以矩形为参数的过程\nDialogue: 0,0:46:51.40,0:46:55.65,Default,,0,0,0,,所以当你给图像一个矩形时 它就像这样绘制线段\nDialogue: 0,0:46:57.17,0:47:01.10,Default,,0,0,0,,那好 我应该如何使用它呢？\nDialogue: 0,0:47:01.22,0:47:04.08,Default,,0,0,0,,我来说得具体一点\nDialogue: 0,0:47:05.60,0:47:24.22,Default,,0,0,0,,就比如说 (DEFINE R (MAKE-RECT ...))\nDialogue: 0,0:47:24.50,0:47:28.66,Default,,0,0,0,,这里需要用MAKE-VECTOR来构造一些向量\nDialogue: 0,0:47:29.84,0:47:46.18,Default,,0,0,0,,然后定义G为 (DEFINE G (MAKE-PICT ...))\nDialogue: 0,0:47:46.68,0:47:55.28,Default,,0,0,0,,我要在这里使用MAKE-SEGMENT来构建线段组成的表\nDialogue: 0,0:47:55.28,0:47:58.70,Default,,0,0,0,,MAKE-SEGMENT由向量构成 向量由点构成\nDialogue: 0,0:47:59.50,0:48:04.60,Default,,0,0,0,,如果我想在一个矩形中呈现图像G\nDialogue: 0,0:48:04.65,0:48:11.72,Default,,0,0,0,,注意 图像是一个过程 它接受一个矩形作为参数\nDialogue: 0,0:48:12.06,0:48:16.37,Default,,0,0,0,,所以 如果我调用(G R)\nDialogue: 0,0:48:17.96,0:48:23.25,Default,,0,0,0,,那么无论G是什么 都会在矩形R中绘制出来\nDialogue: 0,0:48:23.62,0:48:25.62,Default,,0,0,0,,这就是我们如何使用它\nDialogue: 0,0:48:26.86,0:48:36.29,Default,,0,0,0,,[音乐]\nDialogue: 0,0:48:36.29,0:48:39.78,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:39.82,0:48:43.54,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:48:51.28,0:48:55.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:55.50,0:48:58.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:48:59.34,0:49:03.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson-Escher的例子\nDialogue: 0,0:49:07.72,0:49:12.48,Default,,0,0,0,,教授：为什么我说这个例子很好呢？\nDialogue: 0,0:49:12.48,0:49:13.74,Default,,0,0,0,,也许你们不这么认为\nDialogue: 0,0:49:13.74,0:49:15.42,Default,,0,0,0,,你们可能觉得它很奇怪\nDialogue: 0,0:49:15.42,0:49:20.92,Default,,0,0,0,,用来矩形做复杂变换的过程来表示图像 确实奇怪\nDialogue: 0,0:49:20.92,0:49:22.72,Default,,0,0,0,,那么 它好在哪里呢？\nDialogue: 0,0:49:25.36,0:49:26.69,Default,,0,0,0,,原因就是\nDialogue: 0,0:49:27.22,0:49:30.40,Default,,0,0,0,,一旦你按这种方法实现了基本元素\nDialogue: 0,0:49:30.97,0:49:35.20,Default,,0,0,0,,组合的方法就是构造Lisp过程\nDialogue: 0,0:49:35.98,0:49:37.48,Default,,0,0,0,,我给你们演示一下\nDialogue: 0,0:49:37.48,0:49:39.02,Default,,0,0,0,,假设我想实现BESIDE\nDialogue: 0,0:49:41.56,0:49:47.36,Default,,0,0,0,,我要做的是 假设有个叫P1的图像\nDialogue: 0,0:49:47.36,0:49:50.62,Default,,0,0,0,,一定要记得：图像本质上是一个过程\nDialogue: 0,0:49:50.62,0:49:54.82,Default,,0,0,0,,当你传递给它一个矩形\nDialogue: 0,0:49:56.52,0:50:01.46,Default,,0,0,0,,它会在你给定的矩形中绘制图形\nDialogue: 0,0:50:03.46,0:50:09.26,Default,,0,0,0,,假设P2是另一个图像 你传递给它一个矩形\nDialogue: 0,0:50:09.74,0:50:12.44,Default,,0,0,0,,无论给它什么矩形 它都会绘制一些图案\nDialogue: 0,0:50:14.84,0:50:26.60,Default,,0,0,0,,现在 我想实现(BESIDE P1 P2 A) A是缩放因子\nDialogue: 0,0:50:27.04,0:50:28.38,Default,,0,0,0,,会得到什么呢？\nDialogue: 0,0:50:28.38,0:50:29.34,Default,,0,0,0,,我们会得到一个图像\nDialogue: 0,0:50:29.92,0:50:33.88,Default,,0,0,0,,也就是说你传给它一个矩形 它就会在其中绘图\nDialogue: 0,0:50:34.77,0:50:37.18,Default,,0,0,0,,如果我们在一个矩形中执行BESIDE操作\nDialogue: 0,0:50:38.58,0:50:40.12,Default,,0,0,0,,比如这个矩形\nDialogue: 0,0:50:41.50,0:50:42.74,Default,,0,0,0,,要做什么呢？\nDialogue: 0,0:50:42.76,0:50:46.36,Default,,0,0,0,,这将把矩形切分为两部分\nDialogue: 0,0:50:49.29,0:50:51.57,Default,,0,0,0,,一部分比例是A 另一部分是1-A\nDialogue: 0,0:50:52.65,0:50:55.12,Default,,0,0,0,,现在 我们就有了两个矩形\nDialogue: 0,0:51:02.34,0:51:06.54,Default,,0,0,0,,然后先让P1在这个矩形中绘制\nDialogue: 0,0:51:07.36,0:51:11.64,Default,,0,0,0,,然后让P2在这个矩形中绘制\nDialogue: 0,0:51:13.28,0:51:16.88,Default,,0,0,0,,BESIDE仅仅需要计算出这些矩形来\nDialogue: 0,0:51:17.36,0:51:23.97,Default,,0,0,0,,由于矩形是由原点、水平向量和竖直向量组成\nDialogue: 0,0:51:23.98,0:51:25.94,Default,,0,0,0,,BESIDE操作需要计算出这些要素\nDialogue: 0,0:51:27.37,0:51:32.29,Default,,0,0,0,,所以对第一个矩形来说 原点变成了矩形的原点\nDialogue: 0,0:51:33.64,0:51:37.80,Default,,0,0,0,,竖直向量与原矩形相同 不发生变化\nDialogue: 0,0:51:38.89,0:51:46.60,Default,,0,0,0,,水平向量是原始矩形的水平向量缩放A倍得到的\nDialogue: 0,0:51:47.49,0:51:48.90,Default,,0,0,0,,这就是第一个矩形\nDialogue: 0,0:51:49.46,0:51:52.69,Default,,0,0,0,,第二个矩形的原点是\nDialogue: 0,0:51:54.06,0:51:59.65,Default,,0,0,0,,原矩形的原点加上矩形的水平向量缩放A倍\nDialogue: 0,0:52:01.20,0:52:03.40,Default,,0,0,0,,第二个矩形的水平向量是\nDialogue: 0,0:52:03.77,0:52:06.04,Default,,0,0,0,,除去前一个矩形水平向量所余下的部分\nDialogue: 0,0:52:06.34,0:52:11.66,Default,,0,0,0,,也就是(1-A)*H H是原矩形的水平向量\nDialogue: 0,0:52:12.05,0:52:13.77,Default,,0,0,0,,它的竖直向量还是V\nDialogue: 0,0:52:15.48,0:52:17.98,Default,,0,0,0,,基本上 BESIDE就是构造这两个矩形\nDialogue: 0,0:52:18.00,0:52:20.57,Default,,0,0,0,,但重要的是 一旦构造好这些矩形\nDialogue: 0,0:52:20.93,0:52:24.58,Default,,0,0,0,,它就能让P1、P2在正确的位置绘制\nDialogue: 0,0:52:24.62,0:52:26.18,Default,,0,0,0,,这就是BESIDE需要做的全部工作\nDialogue: 0,0:52:27.80,0:52:29.30,Default,,0,0,0,,我们看一下代码\nDialogue: 0,0:52:34.33,0:52:35.13,Default,,0,0,0,,这是BESIDE\nDialogue: 0,0:52:39.64,0:52:46.44,Default,,0,0,0,,(BESIDE P1 P2 A) A是缩放比例\nDialogue: 0,0:52:47.84,0:52:53.64,Default,,0,0,0,,因为该过程返回图像 所以结果是一个以矩形为参数的过程\nDialogue: 0,0:52:55.49,0:52:56.56,Default,,0,0,0,,它做什么呢？\nDialogue: 0,0:52:56.76,0:53:02.32,Default,,0,0,0,,它让P1在某个矩形中绘制 P2在另一个矩形中绘制\nDialogue: 0,0:53:03.21,0:53:04.46,Default,,0,0,0,,现在这些矩形又是什么呢?\nDialogue: 0,0:53:04.46,0:53:05.48,Default,,0,0,0,,就在这里计算\nDialogue: 0,0:53:05.48,0:53:06.54,Default,,0,0,0,,它创建了一个矩形\nDialogue: 0,0:53:07.52,0:53:10.40,Default,,0,0,0,,用的是我刚才在黑板上写的几何公式 这是矩形的原点\nDialogue: 0,0:53:10.40,0:53:11.84,Default,,0,0,0,,矩形的水平向量\nDialogue: 0,0:53:11.84,0:53:13.44,Default,,0,0,0,,还有矩形的竖直向量\nDialogue: 0,0:53:13.97,0:53:14.81,Default,,0,0,0,,对于P2\nDialogue: 0,0:53:15.50,0:53:19.78,Default,,0,0,0,,矩形需要不同的原点 水平向量和竖直向量\nDialogue: 0,0:53:19.78,0:53:20.70,Default,,0,0,0,,但重要的是\nDialogue: 0,0:53:21.21,0:53:27.18,Default,,0,0,0,,BESIDE只是将这两个矩形分别传递给了P1和P2而已\nDialogue: 0,0:53:27.74,0:53:29.42,Default,,0,0,0,,这就是BESIDE所需要做的\nDialogue: 0,0:53:30.84,0:53:35.62,Default,,0,0,0,,好 ROTATE也很类似\nDialogue: 0,0:53:36.96,0:53:42.00,Default,,0,0,0,,假设我有一个图像A\nDialogue: 0,0:53:42.97,0:53:46.12,Default,,0,0,0,,我想让它旋转90度\nDialogue: 0,0:53:46.37,0:53:51.92,Default,,0,0,0,,这意味着 给定这个矩形\nDialogue: 0,0:53:53.94,0:53:58.44,Default,,0,0,0,,它有原点、水平向量和竖直向量\nDialogue: 0,0:53:58.78,0:54:03.18,Default,,0,0,0,,现在假设已经有了这样的矩形\nDialogue: 0,0:54:03.74,0:54:09.12,Default,,0,0,0,,这个矩形的原点、水平向量和竖直向量在这里\nDialogue: 0,0:54:09.60,0:54:12.46,Default,,0,0,0,,然后在矩形里各自绘制自己\nDialogue: 0,0:54:13.26,0:54:15.04,Default,,0,0,0,,我们来看看代码\nDialogue: 0,0:54:17.02,0:54:19.85,Default,,0,0,0,,那么 ROTATE90过程\nDialogue: 0,0:54:20.61,0:54:22.96,Default,,0,0,0,,返回的也是一个以矩形为参数的过程\nDialogue: 0,0:54:23.25,0:54:26.12,Default,,0,0,0,,它就是将图像绘制在一个特定矩形中\nDialogue: 0,0:54:27.21,0:54:30.66,Default,,0,0,0,,这个几何公式就是这个矩形的变换规则\nDialogue: 0,0:54:30.66,0:54:33.84,Default,,0,0,0,,这句代码让矩形看起来像向侧面的\nDialogue: 0,0:54:33.86,0:54:36.52,Default,,0,0,0,,原点在别的地方 竖直向量在别的地方\nDialogue: 0,0:54:37.13,0:54:39.74,Default,,0,0,0,,水平向量在别的地方 竖直向量在别的地方\nDialogue: 0,0:54:46.76,0:54:49.90,Default,,0,0,0,,再次注意 这里的关键是\nDialogue: 0,0:54:50.53,0:55:00.97,Default,,0,0,0,,关键是使用过程来表示图像 使其自动地具有闭包性质\nDialogue: 0,0:55:01.74,0:55:05.22,Default,,0,0,0,,这是因为 实际上 BESIDE只是接受并使用P1\nDialogue: 0,0:55:05.22,0:55:09.40,Default,,0,0,0,,BESIDE并不关心它是一个基本图像还是一些线段\nDialogue: 0,0:55:09.61,0:55:12.69,Default,,0,0,0,,或者P1还是ABOVE、BESIDE、ROTATE等操作的结果\nDialogue: 0,0:55:12.72,0:55:16.08,Default,,0,0,0,,关于P1 BESIDE需要知道的就是\nDialogue: 0,0:55:16.29,0:55:19.73,Default,,0,0,0,,给P1传递一个矩形 就会导致某物的绘制\nDialogue: 0,0:55:21.04,0:55:25.98,Default,,0,0,0,,在这个层面上 BESIDE并不关心P1是如何完成绘制\nDialogue: 0,0:55:27.73,0:55:32.25,Default,,0,0,0,,我们使用过程来表示图像 以保持它的闭包性质\nDialogue: 0,0:55:35.64,0:55:40.81,Default,,0,0,0,,将图像实现为过程 使得组合的方法变得\nDialogue: 0,0:55:41.18,0:55:43.93,Default,,0,0,0,,变得简单而优雅\nDialogue: 0,0:55:45.92,0:55:48.22,Default,,0,0,0,,但这并不是点睛之笔\nDialogue: 0,0:55:49.28,0:55:53.52,Default,,0,0,0,,点睛之笔来自于这门语言中抽象的方法\nDialogue: 0,0:55:54.70,0:55:56.24,Default,,0,0,0,,我们做了些什么？\nDialogue: 0,0:55:56.24,0:56:03.72,Default,,0,0,0,,我们把组合的方法实现为了过程\nDialogue: 0,0:56:05.85,0:56:09.38,Default,,0,0,0,,这也就意味着 当我们对这个语言进行抽象时\nDialogue: 0,0:56:10.17,0:56:15.69,Default,,0,0,0,,Lisp提供的 操作过程的一切方法\nDialogue: 0,0:56:16.33,0:56:21.45,Default,,0,0,0,,都可以自动地在这个图像语言中使用\nDialogue: 0,0:56:21.92,0:56:29.74,Default,,0,0,0,,与其用术语“这个语言以Lisp实现” — 虽然确实如此\nDialogue: 0,0:56:29.76,0:56:32.58,Default,,0,0,0,,我想描述为“这个语言嵌入于Lisp”\nDialogue: 0,0:56:37.64,0:56:42.08,Default,,0,0,0,,也就是说 通过像这样将语言嵌入\nDialogue: 0,0:56:42.90,0:56:48.86,Default,,0,0,0,,可以以扩展的形式 自动地获得Lisp的所有力量\nDialogue: 0,0:56:50.06,0:56:51.68,Default,,0,0,0,,这又是什么意思呢？\nDialogue: 0,0:56:51.97,0:57:02.94,Default,,0,0,0,,举个例子 假设我想用A B C D四副图像做东西\nDialogue: 0,0:57:03.76,0:57:07.06,Default,,0,0,0,,让它们呈现像这样的格局\nDialogue: 0,0:57:12.50,0:57:16.96,Default,,0,0,0,,可以将其称为FOUR-PICT格局\nDialogue: 0,0:57:16.96,0:57:17.70,Default,,0,0,0,,我该如何做呢？\nDialogue: 0,0:57:17.70,0:57:18.68,Default,,0,0,0,,我可以很容易的做到这些\nDialogue: 0,0:57:18.68,0:57:23.33,Default,,0,0,0,,写个过程 让B和D做ABOVE\nDialogue: 0,0:57:24.13,0:57:25.85,Default,,0,0,0,,A和C做ABOVE\nDialogue: 0,0:57:26.09,0:57:27.70,Default,,0,0,0,,得到的结果做BESIDE\nDialogue: 0,0:57:28.24,0:57:31.82,Default,,0,0,0,,我自然地拥有Lisp组合过程的能力\nDialogue: 0,0:57:32.92,0:57:35.82,Default,,0,0,0,,这不需要我为图像语言做些特殊处理\nDialogue: 0,0:57:35.82,0:57:39.92,Default,,0,0,0,,事实上 这些组合本身就是过程\nDialogue: 0,0:57:40.96,0:57:44.18,Default,,0,0,0,,假设我想做一些更复杂的事情\nDialogue: 0,0:57:44.18,0:57:46.50,Default,,0,0,0,,我想为这里的每一个传递一个参数\nDialogue: 0,0:57:46.52,0:57:50.08,Default,,0,0,0,,我可以独立地做旋转90度的操作\nDialogue: 0,0:57:50.41,0:57:52.64,Default,,0,0,0,,这只需要我在这个过程中加入一个参数\nDialogue: 0,0:57:53.17,0:57:54.56,Default,,0,0,0,,它自然而然就有了这样的功能\nDialogue: 0,0:57:54.80,0:57:57.84,Default,,0,0,0,,它自动地嵌入进去了\nDialogue: 0,0:57:58.16,0:58:05.36,Default,,0,0,0,,甚至 假设我想使用递归\nDialogue: 0,0:58:06.16,0:58:10.78,Default,,0,0,0,,我们看一下图像递归组合的方法\nDialogue: 0,0:58:10.78,0:58:14.64,Default,,0,0,0,,定义--看看你们能理解这个不\nDialogue: 0,0:58:14.69,0:58:18.97,Default,,0,0,0,,(DEFINE (RIGHT-PUSH PICT N A))\nDialogue: 0,0:58:22.84,0:58:29.80,Default,,0,0,0,,RIGHT-PUSH需要图片P 整数N和缩放因数A\nDialogue: 0,0:58:31.46,0:58:41.22,Default,,0,0,0,,定义是：如果N为0 那么返回图像P\nDialogue: 0,0:58:42.20,0:58:54.02,Default,,0,0,0,,否则 就-- 哦 这里是P\nDialogue: 0,0:58:55.88,0:59:00.21,Default,,0,0,0,,否则 我用图形P做BESIDE操作\nDialogue: 0,0:59:00.92,0:59:18.30,Default,,0,0,0,,BESIDE的另一个操作数是(RIGHT-PUSH P (- N 1) A)的结果\nDialogue: 0,0:59:24.72,0:59:31.12,Default,,0,0,0,,如果N为0 就返回P 否则就对P进行A倍缩放\nDialogue: 0,0:59:31.12,0:59:32.80,Default,,0,0,0,,抱歉 我这里代码没对齐\nDialogue: 0,0:59:33.66,0:59:38.50,Default,,0,0,0,,递归地调用(RIGHT-PUSH P (- N 1) A) 将结果用BESIDE连接\nDialogue: 0,0:59:38.50,0:59:42.00,Default,,0,0,0,,这就是一种递归组合方法\nDialogue: 0,0:59:43.78,0:59:44.76,Default,,0,0,0,,调用的结果会是怎样的？\nDialogue: 0,0:59:44.76,0:59:45.90,Default,,0,0,0,,我们来看看\nDialogue: 0,0:59:46.04,0:59:56.04,Default,,0,0,0,,这是(RIGHT-PUSH GEORGE 2 0.75)的结果\nDialogue: 0,0:59:59.26,1:00:00.72,Default,,0,0,0,,这个是从什么地方来的呢？\nDialogue: 0,1:00:00.72,1:00:02.34,Default,,0,0,0,,我是如何想象出这些递归来的呢？\nDialogue: 0,1:00:02.34,1:00:05.24,Default,,0,0,0,,答案是无意识的 绝对是无意识的\nDialogue: 0,1:00:05.24,1:00:09.80,Default,,0,0,0,,由于它们都是过程 而嵌入的目标系统中允许定义递归过程\nDialogue: 0,1:00:10.36,1:00:11.68,Default,,0,0,0,,我不必自己去做\nDialogue: 0,1:00:13.56,1:00:16.42,Default,,0,0,0,,当然 我们可以模仿这个方法做些更复杂的事\nDialogue: 0,1:00:16.42,1:00:18.21,Default,,0,0,0,,我可以定义做UP-PUSH的过程\nDialogue: 0,1:00:18.42,1:00:22.60,Default,,0,0,0,,对 它可以递归地把图片放在原来的上面\nDialogue: 0,1:00:22.60,1:00:26.54,Default,,0,0,0,,我也可以用这种策略来做些其它事\nDialogue: 0,1:00:26.56,1:00:28.85,Default,,0,0,0,,给定一个图像\nDialogue: 0,1:00:29.78,1:00:37.16,Default,,0,0,0,,然后递归地把它放在原图片的旁边和上面\nDialogue: 0,1:00:37.57,1:00:38.92,Default,,0,0,0,,这里再放一些别的\nDialogue: 0,1:00:39.52,1:00:41.82,Default,,0,0,0,,然后我把同样递归的图像放在这里\nDialogue: 0,1:00:42.36,1:00:44.20,Default,,0,0,0,,我可以用这个来终止\nDialogue: 0,1:00:45.40,1:00:52.50,Default,,0,0,0,,这个过程比RIGHT-PUSH复杂一点 但也不算太多\nDialogue: 0,1:00:53.64,1:00:58.14,Default,,0,0,0,,在BESIDE的基础上 我多加了一个ABOVE操作\nDialogue: 0,1:01:01.12,1:01:06.78,Default,,0,0,0,,如果我把它应用于四张放在一起的图像上\nDialogue: 0,1:01:07.53,1:01:08.65,Default,,0,0,0,,这样做当然没问题\nDialogue: 0,1:01:09.01,1:01:14.17,Default,,0,0,0,,我把它应用于我们之前定义的Q上\nDialogue: 0,1:01:15.97,1:01:18.73,Default,,0,0,0,,我得到的是这个玩意儿\nDialogue: 0,1:01:20.14,1:01:25.26,Default,,0,0,0,,\"图像Q的方形极限\" 做了两次\nDialogue: 0,1:01:28.18,1:01:32.25,Default,,0,0,0,,好 现在我们将其与Escher的\"方形极限\"对比一下\nDialogue: 0,1:01:32.88,1:01:34.53,Default,,0,0,0,,可以看到 这都是基于同样的思想\nDialogue: 0,1:01:34.74,1:01:36.94,Default,,0,0,0,,当然 Escher的图像更加漂亮一些\nDialogue: 0,1:01:36.94,1:01:44.04,Default,,0,0,0,,如果我们回过头审视George\nDialogue: 0,1:01:44.38,1:01:47.37,Default,,0,0,0,,我最开始用的是非常随意的设计\nDialogue: 0,1:01:47.42,1:01:49.26,Default,,0,0,0,,用了George的图像 做了一些操作\nDialogue: 0,1:01:51.22,1:01:53.14,Default,,0,0,0,,我们再看看Escher的图片\nDialogue: 0,1:01:54.08,1:01:56.14,Default,,0,0,0,,Escher的图片不是随意设计的\nDialogue: 0,1:01:56.14,1:01:57.66,Default,,0,0,0,,这个图案非常精妙\nDialogue: 0,1:01:57.89,1:02:00.20,Default,,0,0,0,,当我们把鱼身\nDialogue: 0,1:02:01.82,1:02:04.97,Default,,0,0,0,,把鱼身旋转并放缩 就会优美地变成下一条鱼\nDialogue: 0,1:02:07.40,1:02:11.48,Default,,0,0,0,,当然我没有刻意处理过George\nDialogue: 0,1:02:12.12,1:02:13.90,Default,,0,0,0,,就图像George来说\nDialogue: 0,1:02:15.41,1:02:18.64,Default,,0,0,0,,也有一些地方匹配 但不够好 比较随意\nDialogue: 0,1:02:18.64,1:02:21.53,Default,,0,0,0,,顺便说下 一个好的程序\nDialogue: 0,1:02:22.30,1:02:27.54,Default,,0,0,0,,应该有个过程 能接受像这里George一样的基本图像\nDialogue: 0,1:02:27.86,1:02:29.62,Default,,0,0,0,,然后调整其中的线段终点\nDialogue: 0,1:02:29.86,1:02:31.20,Default,,0,0,0,,这样可以得到一个好看的图像\nDialogue: 0,1:02:32.13,1:02:34.06,Default,,0,0,0,,在做“方形极限”应该注意这些\nDialogue: 0,1:02:34.68,1:02:36.30,Default,,0,0,0,,这是一个非常值得思考的事情\nDialogue: 0,1:02:38.08,1:02:39.72,Default,,0,0,0,,同时 我还可以进行组合\nDialogue: 0,1:02:39.72,1:02:41.04,Default,,0,0,0,,我们还可以使用递归过程\nDialogue: 0,1:02:41.04,1:02:43.48,Default,,0,0,0,,我们可以自然而然地做任何事情\nDialogue: 0,1:02:44.60,1:02:48.52,Default,,0,0,0,,重点在于 在语言中实际实现另一个语言\nDialogue: 0,1:02:48.69,1:02:50.44,Default,,0,0,0,,在语言中嵌入另一个语言的差异\nDialogue: 0,1:02:50.44,1:02:53.72,Default,,0,0,0,,这可以让你不丢失原有语言的能力 而Lisp强大之处在于\nDialogue: 0,1:02:54.76,1:02:57.62,Default,,0,0,0,,Lisp是一个强悍的语言 可以处理任何特定问题\nDialogue: 0,1:02:57.62,1:03:02.10,Default,,0,0,0,,把你想要的语言嵌入到Lisp中才是真的好\nDialogue: 0,1:03:02.10,1:03:05.44,Default,,0,0,0,,这才是这种设计方法的真正力量\nDialogue: 0,1:03:05.69,1:03:06.82,Default,,0,0,0,,我们可以深入一下\nDialogue: 0,1:03:06.82,1:03:08.81,Default,,0,0,0,,在Lisp中我们还可以做些其它的事\nDialogue: 0,1:03:09.21,1:03:17.52,Default,,0,0,0,,就是将通用方法抽象成高阶过程\nDialogue: 0,1:03:19.09,1:03:22.57,Default,,0,0,0,,在我画那些图像时 你们可能已经发现\nDialogue: 0,1:03:23.78,1:03:26.61,Default,,0,0,0,,RIGHT-PUSH和类似的过程 就是一直在上面放东西\nDialogue: 0,1:03:26.93,1:03:33.82,Default,,0,0,0,,而这个CORNER-PUSH则是一种一般性思想的泛化\nDialogue: 0,1:03:34.72,1:03:37.20,Default,,0,0,0,,为了演示并让大家熟悉\nDialogue: 0,1:03:37.98,1:03:40.65,Default,,0,0,0,,使用廊腰缦回的高阶过程\nDialogue: 0,1:03:41.12,1:03:47.24,Default,,0,0,0,,我给大家示范一下“递归地重复某种组合方法”的一般性思想\nDialogue: 0,1:03:48.30,1:03:50.70,Default,,0,0,0,,这个例子可以说明一切\nDialogue: 0,1:03:51.22,1:04:00.70,Default,,0,0,0,,我们可以定义一个依赖于具体组合方式的PUSH过程\nDialogue: 0,1:04:01.49,1:04:04.88,Default,,0,0,0,,COMB的取值可以是BESIDE或ABOVE等\nDialogue: 0,1:04:06.18,1:04:07.06,Default,,0,0,0,,过程的体是什么呢？\nDialogue: 0,1:04:07.06,1:04:12.06,Default,,0,0,0,,它返回一个过程 想一想BESIDE实际上是什么\nDialogue: 0,1:04:13.22,1:04:15.18,Default,,0,0,0,,它接受一个图像\nDialogue: 0,1:04:15.96,1:04:18.08,Default,,0,0,0,,哦  它接受两个图像和一个缩放因数\nDialogue: 0,1:04:18.62,1:04:24.28,Default,,0,0,0,,利用这个过程 定义一个接受层数、图像和缩放因数的过程\nDialogue: 0,1:04:24.28,1:04:25.45,Default,,0,0,0,,我称之为RIGHT-PUSH\nDialogue: 0,1:04:26.16,1:04:33.66,Default,,0,0,0,,这个过程接受 图像PICT 层数N和缩放因数A\nDialogue: 0,1:04:36.16,1:04:39.12,Default,,0,0,0,,我要做一些重复操作\nDialogue: 0,1:04:39.45,1:04:46.62,Default,,0,0,0,,我会重复应用一个接受一个图像P的过程\nDialogue: 0,1:04:48.40,1:04:50.69,Default,,0,0,0,,并把组合的方式应用在\nDialogue: 0,1:04:51.20,1:04:59.08,Default,,0,0,0,,应用在图像PICT和在这里接受的图像P以及缩放因数A\nDialogue: 0,1:05:02.26,1:05:07.28,Default,,0,0,0,,我要重复应用这个过程N次\nDialogue: 0,1:05:12.04,1:05:16.20,Default,,0,0,0,,我则是把这整个过程应用在原图片PICT上\nDialogue: 0,1:05:19.56,1:05:24.48,Default,,0,0,0,,虽然之前没提过 这里的REPEATED也是一个高阶过程\nDialogue: 0,1:05:24.53,1:05:28.34,Default,,0,0,0,,它接受一个过程P和一个数字N\nDialogue: 0,1:05:29.54,1:05:34.29,Default,,0,0,0,,它返回另一个过程：将给定的过程P重复应用N次的过程\nDialogue: 0,1:05:36.04,1:05:39.30,Default,,0,0,0,,可能有些人已经在练习中编写过REPEATED了\nDialogue: 0,1:05:39.70,1:05:43.01,Default,,0,0,0,,如果还没做的话 这是理解和练习高阶过程的好机会\nDialogue: 0,1:05:43.84,1:05:46.90,Default,,0,0,0,,无论如何 我将把REPEATED过程的结果应用到PICT上\nDialogue: 0,1:05:49.46,1:05:52.38,Default,,0,0,0,,定义好PUSH后 这就\nDialogue: 0,1:05:53.12,1:05:57.73,Default,,0,0,0,,这就是从BESIDE、RIGHT-PUSH中总结出来的一般性思想\nDialogue: 0,1:05:59.01,1:06:13.17,Default,,0,0,0,,现在 我就可以把RIGHT-PUSH定义为 用BESIDE来做PUSH操作\nDialogue: 0,1:06:17.65,1:06:20.32,Default,,0,0,0,,我也可以把UP-PUSH定义为 用ABOVE来做PUSH操作\nDialogue: 0,1:06:20.34,1:06:25.48,Default,,0,0,0,,类似地 CORNER-PUSH就是用BESIDE和ABOVE的适当组合做PUSH操作\nDialogue: 0,1:06:25.49,1:06:26.70,Default,,0,0,0,,我可以用任何东西做PUSH操作\nDialogue: 0,1:06:28.26,1:06:34.76,Default,,0,0,0,,嗯 如果你还不太理解LAMBDA的话 可以参考这个例子\nDialogue: 0,1:06:38.98,1:06:41.00,Default,,0,0,0,,我们可以从这个例子中学到很多东西\nDialogue: 0,1:06:42.18,1:06:49.80,Default,,0,0,0,,我主要想要介绍的是在一个语言中嵌入另一个语言\nDialogue: 0,1:06:50.66,1:06:55.62,Default,,0,0,0,,这样 母体语言--本例中是Lisp--的所有能力\nDialogue: 0,1:06:55.92,1:07:00.28,Default,,0,0,0,,可以作为你所构建语言的一种扩展而取得\nDialogue: 0,1:07:00.98,1:07:04.00,Default,,0,0,0,,这个例子很好地展示了这点\nDialogue: 0,1:07:08.14,1:07:10.94,Default,,0,0,0,,另外 当我们回过头去思考\nDialogue: 0,1:07:10.94,1:07:12.28,Default,,0,0,0,,什么是过程 什么是数据\nDialogue: 0,1:07:12.28,1:07:16.20,Default,,0,0,0,,在这里 天啊 发生了什么\nDialogue: 0,1:07:16.20,1:07:19.66,Default,,0,0,0,,在这里 这是一个过程 它接受一个图像和一个参数\nDialogue: 0,1:07:19.66,1:07:20.36,Default,,0,0,0,,但是 什么是图像呢？\nDialogue: 0,1:07:20.36,1:07:23.82,Default,,0,0,0,,请回想 图像本身 就是一个以矩形为参数的过程\nDialogue: 0,1:07:23.82,1:07:25.82,Default,,0,0,0,,这个矩形是某种抽象\nDialogue: 0,1:07:26.09,1:07:28.13,Default,,0,0,0,,我希望你们现在能彻底明白\nDialogue: 0,1:07:29.14,1:07:33.74,Default,,0,0,0,,系统中什么是过程 什么是数据\nDialogue: 0,1:07:33.74,1:07:34.78,Default,,0,0,0,,我们发现 它们没有任何区别\nDialogue: 0,1:07:35.49,1:07:36.44,Default,,0,0,0,,真的没有区别\nDialogue: 0,1:07:37.93,1:07:41.42,Default,,0,0,0,,你可以认为图像有时候是过程 有时候是数据\nDialogue: 0,1:07:41.84,1:07:44.90,Default,,0,0,0,,但是 这只是让你容易理解的一种方法\nDialogue: 0,1:07:44.90,1:07:47.30,Default,,0,0,0,,这有一定道理 也没有道理\nDialogue: 0,1:07:49.92,1:08:02.20,Default,,0,0,0,,关于系统的结构 一种更普遍的观点将其视作创建一种语言\nDialogue: 0,1:08:02.52,1:08:06.74,Default,,0,0,0,,将工程设计过程看作是创建一门语言\nDialogue: 0,1:08:07.84,1:08:13.97,Default,,0,0,0,,准确来说 是创建各种层次的语言\nDialogue: 0,1:08:14.77,1:08:20.01,Default,,0,0,0,,众所周知 有一种方法学 或者叫做“神话学”\nDialogue: 0,1:08:20.74,1:08:24.90,Default,,0,0,0,,姑且叫做软件“工程”\nDialogue: 0,1:08:25.21,1:08:28.04,Default,,0,0,0,,它声称 你要先计算出你的任务\nDialogue: 0,1:08:28.04,1:08:30.04,Default,,0,0,0,,精确且正确地计算出你的任务\nDialogue: 0,1:08:30.40,1:08:32.20,Default,,0,0,0,,一但你搞清楚要做的东西\nDialogue: 0,1:08:32.22,1:08:34.54,Default,,0,0,0,,你把它划分为三个子任务\nDialogue: 0,1:08:34.54,1:08:35.76,Default,,0,0,0,,然后你开始继续做--\nDialogue: 0,1:08:35.97,1:08:38.94,Default,,0,0,0,,你开始处理这个子任务 然后你明确它是什么\nDialogue: 0,1:08:38.94,1:08:43.04,Default,,0,0,0,,这个子问题就分裂成三个子任务 你把它们处理完\nDialogue: 0,1:08:43.04,1:08:47.32,Default,,0,0,0,,然后你先处理这两个任务\nDialogue: 0,1:08:47.32,1:08:51.10,Default,,0,0,0,,解决完子任务后 你后退到这里 处理第二个子任务\nDialogue: 0,1:08:51.10,1:08:53.40,Default,,0,0,0,,然后把它详细地实现出来\nDialogue: 0,1:08:53.40,1:08:57.64,Default,,0,0,0,,结束之后-- 你完成了这个美丽的大厦\nDialogue: 0,1:08:57.64,1:09:00.25,Default,,0,0,0,,你最后得到了一棵非凡的树\nDialogue: 0,1:09:00.89,1:09:08.24,Default,,0,0,0,,你把任务划分为子任务 子任务再划分为子任务\nDialogue: 0,1:09:09.88,1:09:15.02,Default,,0,0,0,,树中的每个结点都被严谨而准确地定义\nDialogue: 0,1:09:15.26,1:09:18.66,Default,,0,0,0,,为奇妙而精美的任务 以构建整栋大厦\nDialogue: 0,1:09:18.96,1:09:21.14,Default,,0,0,0,,这个就是所谓的“神话学”\nDialogue: 0,1:09:21.14,1:09:25.92,Default,,0,0,0,,只有计算机科学家才可能相信你构建的复杂系统像这个样子\nDialogue: 0,1:09:27.48,1:09:32.80,Default,,0,0,0,,好了 我们用Henderson的例子来做对比\nDialogue: 0,1:09:32.80,1:09:34.30,Default,,0,0,0,,它的结构不是那样\nDialogue: 0,1:09:35.26,1:09:39.33,Default,,0,0,0,,事实是：这里有一个语言的层次序列\nDialogue: 0,1:09:41.06,1:09:42.05,Default,,0,0,0,,它是什么？\nDialogue: 0,1:09:42.18,1:09:48.76,Default,,0,0,0,,这里有一层 允许我们构建基本图像\nDialogue: 0,1:09:51.69,1:09:56.24,Default,,0,0,0,,这个语言描述基本图像\nDialogue: 0,1:09:56.32,1:09:57.84,Default,,0,0,0,,我们并没有做过多地讨论\nDialogue: 0,1:09:58.22,1:09:59.58,Default,,0,0,0,,我们讨论了如何构造George\nDialogue: 0,1:09:59.61,1:10:04.88,Default,,0,0,0,,这个语言是在单位正方形中讨论点、线和向量\nDialogue: 0,1:10:06.42,1:10:11.29,Default,,0,0,0,,而在这之上\nDialogue: 0,1:10:11.97,1:10:14.10,Default,,0,0,0,,这是讨论基本图像的语言\nDialogue: 0,1:10:17.08,1:10:20.36,Default,,0,0,0,,讨论在特定单位正方形中线段的构造\nDialogue: 0,1:10:21.40,1:10:23.80,Default,,0,0,0,,在这个上面是另一个完整的语言\nDialogue: 0,1:10:24.05,1:10:30.86,Default,,0,0,0,,关于几何组合子的语言\nDialogue: 0,1:10:32.66,1:10:36.62,Default,,0,0,0,,关于几何物件的位置\nDialogue: 0,1:10:38.77,1:10:46.50,Default,,0,0,0,,讨论像ABOVE、BESIDE、RIGHT-PUSH和ROTATE这样的东西\nDialogue: 0,1:10:48.04,1:10:55.70,Default,,0,0,0,,这些事情恰巧与我们在这个语言中谈论的事情有关\nDialogue: 0,1:10:58.57,1:11:00.93,Default,,0,0,0,,再细化一点 我们发现在这之上\nDialogue: 0,1:11:02.61,1:11:15.10,Default,,0,0,0,,还有一门语言 描述组合的模式\nDialogue: 0,1:11:21.25,1:11:22.44,Default,,0,0,0,,比如说PUSH\nDialogue: 0,1:11:24.45,1:11:27.88,Default,,0,0,0,,也就是用一个放缩因子重复地做一件事儿\nDialogue: 0,1:11:28.38,1:11:31.28,Default,,0,0,0,,我们在那门语言中讨论的问题\nDialogue: 0,1:11:31.50,1:11:34.34,Default,,0,0,0,,正是我这里构建的东西\nDialogue: 0,1:11:36.30,1:11:42.76,Default,,0,0,0,,我们在每一层上所讨论的对象\nDialogue: 0,1:11:44.68,1:11:47.00,Default,,0,0,0,,都是前一个层次所建立的\nDialogue: 0,1:11:48.08,1:11:52.06,Default,,0,0,0,,这个和这个有什么区别呢？\nDialogue: 0,1:11:53.34,1:11:54.18,Default,,0,0,0,,这是因为\nDialogue: 0,1:11:56.14,1:12:01.73,Default,,0,0,0,,实际上在这里 树的每一个结点 每一次分解\nDialogue: 0,1:12:02.14,1:12:05.25,Default,,0,0,0,,都是旨在分成确定的任务\nDialogue: 0,1:12:07.50,1:12:08.88,Default,,0,0,0,,而在另一个方案中\nDialogue: 0,1:12:09.21,1:12:14.80,Default,,0,0,0,,你在每个层级上的完完全全的语言层面的能力\nDialogue: 0,1:12:16.00,1:12:18.08,Default,,0,0,0,,这里的每一个层次\nDialogue: 0,1:12:20.24,1:12:22.72,Default,,0,0,0,,都不是被设计为完成一个特定任务\nDialogue: 0,1:12:23.14,1:12:26.17,Default,,0,0,0,,它被设计为讨论整个事情\nDialogue: 0,1:12:27.62,1:12:30.78,Default,,0,0,0,,这样设计导致的结果是：\nDialogue: 0,1:12:31.14,1:12:35.58,Default,,0,0,0,,用这种设计方法更加健壮\nDialogue: 0,1:12:36.61,1:12:38.20,Default,,0,0,0,,我所谓的“健壮”是指\nDialogue: 0,1:12:38.44,1:12:41.24,Default,,0,0,0,,当你在描述中做一些改变\nDialogue: 0,1:12:42.70,1:12:48.04,Default,,0,0,0,,我们可以做出相应的改变\nDialogue: 0,1:12:49.22,1:12:52.60,Default,,0,0,0,,用上一层语言实现的方法改变即可\nDialogue: 0,1:12:54.29,1:12:56.58,Default,,0,0,0,,因为你让每个层次都是完全的\nDialogue: 0,1:12:56.62,1:12:59.66,Default,,0,0,0,,所以你不需要讨论像BESIDE这样的特定操作\nDialogue: 0,1:12:59.94,1:13:03.78,Default,,0,0,0,,你为表达这类事物创造了完备的词汇\nDialogue: 0,1:13:04.77,1:13:07.02,Default,,0,0,0,,所以当你轻微修改规格指标时\nDialogue: 0,1:13:07.02,1:13:11.38,Default,,0,0,0,,这种方法论可以捕捉并适应那些变化\nDialogue: 0,1:13:12.69,1:13:15.02,Default,,0,0,0,,然而这种设计却不够健壮\nDialogue: 0,1:13:15.02,1:13:17.08,Default,,0,0,0,,因为 如果我在这里改变一下\nDialogue: 0,1:13:17.53,1:13:21.69,Default,,0,0,0,,那可能会影响我划分这些东西的方式 严重地影响\nDialogue: 0,1:13:23.20,1:13:29.74,Default,,0,0,0,,分解观点的最大不同在于 按层次还是严格继承分解\nDialogue: 0,1:13:30.52,1:13:33.02,Default,,0,0,0,,不只是如此 当你有多个层次的语言时\nDialogue: 0,1:13:33.50,1:13:35.92,Default,,0,0,0,,你就有了不同的词汇储备\nDialogue: 0,1:13:36.45,1:13:38.74,Default,,0,0,0,,用于讨论不同层次上的设计\nDialogue: 0,1:13:38.74,1:13:40.92,Default,,0,0,0,,我们再回过头来看看George\nDialogue: 0,1:13:41.90,1:13:44.08,Default,,0,0,0,,如果我想改变图像George\nDialogue: 0,1:13:45.85,1:13:48.68,Default,,0,0,0,,我立马得到了一种不同的方式来描述变化\nDialogue: 0,1:13:48.68,1:13:56.08,Default,,0,0,0,,比如 我想在基本设计的层面上 移动某些向量的终点\nDialogue: 0,1:13:57.76,1:14:00.76,Default,,0,0,0,,我会在最底层讨论这个改变\nDialogue: 0,1:14:01.00,1:14:02.50,Default,,0,0,0,,我会另外指定终点位置\nDialogue: 0,1:14:03.34,1:14:07.98,Default,,0,0,0,,我也可以说 我想在这个小的重复元素上做文章\nDialogue: 0,1:14:09.10,1:14:10.94,Default,,0,0,0,,我可能想做些其它操作\nDialogue: 0,1:14:10.94,1:14:13.84,Default,,0,0,0,,我想在BESIDE中使用一个缩放因数\nDialogue: 0,1:14:13.84,1:14:19.34,Default,,0,0,0,,这个改变我会在更高的层次上讨论：在组合子的层次\nDialogue: 0,1:14:19.34,1:14:25.05,Default,,0,0,0,,我也可以改变图像的基本组合模式\nDialogue: 0,1:14:26.49,1:14:30.48,Default,,0,0,0,,做一些递归地分解 可能不会让它们填充满角落\nDialogue: 0,1:14:31.16,1:14:34.18,Default,,0,0,0,,而这样的一个变化 我会在最高层次讨论\nDialogue: 0,1:14:34.18,1:14:36.37,Default,,0,0,0,,正是因为我按这种结构组织系统\nDialogue: 0,1:14:36.52,1:14:39.62,Default,,0,0,0,,我有所有的词汇 可以用不同的方式描述变化\nDialogue: 0,1:14:39.65,1:14:42.48,Default,,0,0,0,,而且可以灵活地决定哪个更合适\nDialogue: 0,1:14:44.74,1:14:51.05,Default,,0,0,0,,这就是Lisp中不同于软件工程方法论的最大要点\nDialogue: 0,1:14:51.25,1:14:55.45,Default,,0,0,0,,它来自于这样一个观点：真正的设计过程\nDialogue: 0,1:14:56.12,1:14:59.62,Default,,0,0,0,,与其说是在设计程序 不如说是在设计语言\nDialogue: 0,1:14:59.62,1:15:01.09,Default,,0,0,0,,而这就是Lisp的力量\nDialogue: 0,1:15:02.21,1:15:03.61,Default,,0,0,0,,谢谢大家 下课\nDialogue: 0,1:15:05.69,1:15:23.37,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:15:05.69,1:15:23.37,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/FoOTOo/Learning-SICP\n"
  },
  {
    "path": "Ass/lec3a.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: SICP\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nLast Style Storage: Default\nAudio URI: G:\\untitled\\ref\\lec3a_480_muxed.mp4\nVideo Zoom Percent: 0.625\nScroll Position: 507\nActive Line: 512\nVideo File: G:\\untitled\\ref\\lec3a_480_muxed.mp4\nVideo Aspect Ratio: c1.33333\nVideo Position: 18119\nPlayResX: 640\nPlayResY: 480\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:03.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP Group\nDialogue: 0,0:00:04.40,0:00:08.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}Translation && Timeline: Dysprosium / Savior Michael\\NEncode && Effects: Dysprosium\nDialogue: 0,0:00:08.06,0:00:12.16,Declare,,0,0,0,,{\\an2\\fad(500,500)}Credit: Prof. Qiu Zongyan\nDialogue: 0,0:00:12.37,0:00:16.32,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson-Escher Example\nDialogue: 0,0:00:20.94,0:00:23.86,EN,,0,0,0,,PROFESSOR: Well, last time we talked about compound data,\nDialogue: 0,0:00:24.94,0:00:29.74,EN,,0,0,0,,and there were two main points to that business.\nDialogue: 0,0:00:29.74,0:00:32.48,EN,,0,0,0,,First of all, there was a methodology of data abstraction,\nDialogue: 0,0:00:32.94,0:00:39.10,EN,,0,0,0,,and the point of that was that you could isolate the way that data objects are used\nDialogue: 0,0:00:40.06,0:00:41.50,EN,,0,0,0,,from the way that they're represented:\nDialogue: 0,0:00:41.55,0:00:45.20,EN,,0,0,0,,this idea that there's this guy, George, and you go out make a contract with him;\nDialogue: 0,0:00:45.20,0:00:47.48,EN,,0,0,0,,and it's his business to represent the data objects;\nDialogue: 0,0:00:47.48,0:00:49.36,EN,,0,0,0,,and at the moment you are using them,\nDialogue: 0,0:00:49.36,0:00:51.36,EN,,0,0,0,,you don't think about George's problem.\nDialogue: 0,0:00:51.98,0:00:58.44,EN,,0,0,0,,And then secondly, there was this particular way that Lisp has of gluing together things\nDialogue: 0,0:00:58.94,0:01:00.52,EN,,0,0,0,,to form objects called pairs,\nDialogue: 0,0:01:00.52,0:01:03.54,EN,,0,0,0,,and that's done with cons, car and cdr.\nDialogue: 0,0:01:03.54,0:01:07.16,EN,,0,0,0,,And the way that cons, car and cdr are implemented is basically irrelevant.\nDialogue: 0,0:01:07.16,0:01:10.02,EN,,0,0,0,,That's sort of George's problem of how to build those things.\nDialogue: 0,0:01:10.02,0:01:11.16,EN,,0,0,0,,It could be done as primitives.\nDialogue: 0,0:01:11.16,0:01:13.80,EN,,0,0,0,,It could be done using procedures in some weird way,\nDialogue: 0,0:01:13.80,0:01:15.22,EN,,0,0,0,,but we're not going to worry about that.\nDialogue: 0,0:01:16.02,0:01:19.66,EN,,0,0,0,,And as an example, we looked at rational number arithmetic.\nDialogue: 0,0:01:19.66,0:01:21.50,EN,,0,0,0,,We looked at vectors,\nDialogue: 0,0:01:21.50,0:01:24.18,EN,,0,0,0,,and here's just a review of vectors.\nDialogue: 0,0:01:24.18,0:01:27.64,EN,,0,0,0,,Here's an operation that takes the sum of of two vectors,\nDialogue: 0,0:01:27.64,0:01:33.32,EN,,0,0,0,,so we want to add this vector, v1, and this vector, v2, and we get the sum.\nDialogue: 0,0:01:34.46,0:01:40.84,EN,,0,0,0,,And the sum is the vector whose coordinates are the sum of the coordinates of the pieces you're adding.\nDialogue: 0,0:01:41.28,0:01:45.66,EN,,0,0,0,,So I can say, to define make-vect, right, to add two vectors\nDialogue: 0,0:01:45.66,0:01:51.72,EN,,0,0,0,,I make a vector, whose x coordinate is the sum of the two x coordinates,\nDialogue: 0,0:01:52.10,0:01:54.82,EN,,0,0,0,,and whose y coordinate is the sum of the two y coordinates.\nDialogue: 0,0:01:56.06,0:02:04.10,EN,,0,0,0,,And then similarly, we could have an operation that scales vectors,\nDialogue: 0,0:02:04.94,0:02:12.66,EN,,0,0,0,,so here's a procedure scale that multiplies a vector, v, by some number, s.\nDialogue: 0,0:02:13.08,0:02:16.14,EN,,0,0,0,,So here's v, v goes from there to there\nDialogue: 0,0:02:16.32,0:02:20.22,EN,,0,0,0,,and I scale v, and I get a vector in the same direction that's longer.\nDialogue: 0,0:02:21.56,0:02:24.26,EN,,0,0,0,,And again, to scale a vector, I multiply the successive coordinates.\nDialogue: 0,0:02:24.26,0:02:30.22,EN,,0,0,0,,So I make a vector, whose x coordinate is the scale factor times the x coordinate\nDialogue: 0,0:02:30.56,0:02:33.54,EN,,0,0,0,,and whose y coordinate is the scale factor times the y coordinate.\nDialogue: 0,0:02:33.54,0:02:40.28,EN,,0,0,0,,So those are two operations that are implemented using the representation of vectors.\nDialogue: 0,0:02:40.28,0:02:45.02,EN,,0,0,0,,And the representation of vectors, for instance, is something that we can build in terms of pairs.\nDialogue: 0,0:02:45.34,0:02:51.28,EN,,0,0,0,,So George has gone out and implemented for us make-vector and x coordinate and y coordinate,\nDialogue: 0,0:02:53.02,0:02:57.98,EN,,0,0,0,,and this could be done, for instance, using cons,car and cdr;\nDialogue: 0,0:02:58.88,0:03:06.78,EN,,0,0,0,,and notice here, I wrote this in a slightly different way.\nDialogue: 0,0:03:08.04,0:03:11.00,EN,,0,0,0,,The procedures we've seen before, I've said something like\nDialogue: 0,0:03:11.14,0:03:16.22,EN,,0,0,0,,say, make-vector of x and y: cons of x and y.\nDialogue: 0,0:03:16.22,0:03:17.98,EN,,0,0,0,,And here I just wrote make-vector cons.\nDialogue: 0,0:03:17.98,0:03:20.48,EN,,0,0,0,,And that means something slightly different.\nDialogue: 0,0:03:20.48,0:03:26.22,EN,,0,0,0,,Previously we'd say, define make-vector to be a procedure that takes two arguments, x and y,\nDialogue: 0,0:03:26.22,0:03:28.04,EN,,0,0,0,,and does cons of x and y.\nDialogue: 0,0:03:28.04,0:03:34.12,EN,,0,0,0,,And here I am saying define make-vector to be the thing that cons is,\nDialogue: 0,0:03:35.18,0:03:39.66,EN,,0,0,0,,and that's almost the same as the other way we've been writing things.\nDialogue: 0,0:03:39.66,0:03:46.58,EN,,0,0,0,,And I just want you to get used to the idea that procedures can be objects, and that you can name them.\nDialogue: 0,0:03:48.70,0:03:51.80,EN,,0,0,0,,OK, well there's vector representation, and again,\nDialogue: 0,0:03:51.80,0:03:55.68,EN,,0,0,0,,if that was all there was to it,this would all be pretty boring.\nDialogue: 0,0:03:57.02,0:04:02.16,EN,,0,0,0,,And the point is, remember, that you can use cons to glue together not just numbers to form pairs,\nDialogue: 0,0:04:02.16,0:04:04.16,EN,,0,0,0,,but to glue together arbitrary things.\nDialogue: 0,0:04:05.20,0:04:11.60,EN,,0,0,0,,So for instance, if we'd like to represent a line segment,\nDialogue: 0,0:04:11.60,0:04:15.64,EN,,0,0,0,,say the line segment that goes from a certain vector:\nDialogue: 0,0:04:16.06,0:04:28.30,EN,,0,0,0,,say, the segment from the vector 2,3 to the point represented by the vector 5,1.\nDialogue: 0,0:04:28.30,0:04:31.82,EN,,0,0,0,,If we want to represent that line segment,\nDialogue: 0,0:04:33.26,0:04:36.20,EN,,0,0,0,,then we can build that as a pair of pairs.\nDialogue: 0,0:04:40.72,0:04:42.94,EN,,0,0,0,,So again, we can represent line segments.\nDialogue: 0,0:04:42.94,0:04:47.34,EN,,0,0,0,,We can make a constructor that makes a segment using cons,\nDialogue: 0,0:04:47.98,0:04:51.60,EN,,0,0,0,,selects out the start of a segment, selects out the end point of the segment;\nDialogue: 0,0:04:55.24,0:04:59.76,EN,,0,0,0,,and then if we actually look at that, if we peel away the abstraction layers,\nDialogue: 0,0:04:59.88,0:05:02.10,EN,,0,0,0,,and see what's that really is a pair of pairs,\nDialogue: 0,0:05:04.66,0:05:06.22,EN,,0,0,0,,we'd say well that's a pair.\nDialogue: 0,0:05:06.22,0:05:08.22,EN,,0,0,0,,Here's the segment.\nDialogue: 0,0:05:10.00,0:05:16.72,EN,,0,0,0,,It's car, right, it's car pointer is a pair, and it's cdr is also a pair,\nDialogue: 0,0:05:18.32,0:05:25.54,EN,,0,0,0,,and then what the car is--here's the car, that itself is a pair of 2 and 3.\nDialogue: 0,0:05:26.02,0:05:28.08,EN,,0,0,0,,And similarly the cdr is a pair of 2 and 3.\nDialogue: 0,0:05:28.16,0:05:29.24,EN,,0,0,0,,And let me remind you again\nDialogue: 0,0:05:29.32,0:05:33.46,EN,,0,0,0,,that a lot of people have some idea that if I'd taken this arrow and somehow\nDialogue: 0,0:05:33.80,0:05:36.90,EN,,0,0,0,,written it to point down, that would mean something else.\nDialogue: 0,0:05:36.98,0:05:38.28,EN,,0,0,0,,That's irrelevant.\nDialogue: 0,0:05:38.58,0:05:43.90,EN,,0,0,0,,It's only how these are connected and not whether this arrow happens to go vertically or horizontally.\nDialogue: 0,0:05:47.48,0:05:52.18,EN,,0,0,0,,And again just to remind you, there was this notion of closure.\nDialogue: 0,0:05:52.94,0:06:05.62,EN,,0,0,0,,See, closure was the thing that allowed us to start building up complexity, that didn't trap us in pairs.\nDialogue: 0,0:06:06.64,0:06:15.24,EN,,0,0,0,,Particularly what I mean is the things that we make, having combined things using cons to get a pair,\nDialogue: 0,0:06:16.44,0:06:22.64,EN,,0,0,0,,those things themselves can be combined using cons to make more complicated things.\nDialogue: 0,0:06:23.28,0:06:31.98,EN,,0,0,0,,Or as a mathematician might say, the set of data objects in Lisp is closed under the operation of forming pairs.\nDialogue: 0,0:06:33.82,0:06:36.34,EN,,0,0,0,,That's the thing that allows us to build complexity.\nDialogue: 0,0:06:36.34,0:06:38.04,EN,,0,0,0,,And that seems obvious, but remember\nDialogue: 0,0:06:39.06,0:06:42.46,EN,,0,0,0,,a lot of the things in the computer languages that people use are not closed.\nDialogue: 0,0:06:42.46,0:06:48.06,EN,,0,0,0,,So for example, forming arrays in Basic and Fortran is not a closed operation,\nDialogue: 0,0:06:48.08,0:06:51.94,EN,,0,0,0,,because you can make an array of numbers or character strings or something,\nDialogue: 0,0:06:52.04,0:06:54.18,EN,,0,0,0,,but you can't make an array of arrays.\nDialogue: 0,0:06:54.64,0:06:56.68,EN,,0,0,0,,And when you look at means of combination\nDialogue: 0,0:06:57.60,0:07:02.78,EN,,0,0,0,,you should be asking yourself whether things are closed under that means of combination.\nDialogue: 0,0:07:05.06,0:07:08.26,EN,,0,0,0,,Well in any case, because we can form pairs of pairs,\nDialogue: 0,0:07:08.86,0:07:12.78,EN,,0,0,0,,we can start using pairs to glue things together in all sorts of different ways.\nDialogue: 0,0:07:14.02,0:07:18.26,EN,,0,0,0,,So for instance if I'd like to glue together the four things, 1, 2, 3 and 4,\nDialogue: 0,0:07:18.26,0:07:19.82,EN,,0,0,0,,there are a lot of ways I can do it.\nDialogue: 0,0:07:20.74,0:07:26.12,EN,,0,0,0,,I could, for example, like we did with that line segment, i could make a pair\nDialogue: 0,0:07:29.02,0:07:36.88,EN,,0,0,0,,that had a 1 and a 2 and a 3 and a 4, right?\nDialogue: 0,0:07:36.88,0:07:40.06,EN,,0,0,0,,Or if I liked, I could do something like this.\nDialogue: 0,0:07:40.06,0:07:45.52,EN,,0,0,0,,I could make a pair, whose first thing is a pair,\nDialogue: 0,0:07:46.44,0:07:53.20,EN,,0,0,0,,whose car is 1, and his cdr is itself a pair that has the 2 and the 3\nDialogue: 0,0:07:53.26,0:07:55.08,EN,,0,0,0,,and then I could put the 4 up here.\nDialogue: 0,0:07:56.92,0:08:02.16,EN,,0,0,0,,So you see, there are a lot of different ways that I can start using pairs to glue things together,\nDialogue: 0,0:08:02.16,0:08:07.74,EN,,0,0,0,,and so it'll be a good idea to establish some kind of conventions,right,\nDialogue: 0,0:08:07.74,0:08:11.58,EN,,0,0,0,,that allow us to deal with this thing in some conventional way,\nDialogue: 0,0:08:11.58,0:08:14.00,EN,,0,0,0,,so we're not constantly making an ad hoc choice.\nDialogue: 0,0:08:15.94,0:08:19.04,EN,,0,0,0,,And Lisp has a particular convention\nDialogue: 0,0:08:20.74,0:08:25.82,EN,,0,0,0,,for representing a sequence of things as, essentially, a chain of pairs,\nDialogue: 0,0:08:26.78,0:08:28.18,EN,,0,0,0,,and that's called a List.\nDialogue: 0,0:08:34.72,0:08:40.50,EN,,0,0,0,,And what a list is is essentially just a convention for representing a sequence.\nDialogue: 0,0:08:40.70,0:08:47.38,EN,,0,0,0,,I would represent the sequence 1, 2, 3 and 4 by a sequence of pairs.\nDialogue: 0,0:08:48.26,0:08:54.68,EN,,0,0,0,,I'd put 1 here and then the cdr of this would point to another pair\nDialogue: 0,0:08:59.20,0:09:01.40,EN,,0,0,0,,whose car was the next thing in the sequence,\nDialogue: 0,0:09:01.52,0:09:03.42,EN,,0,0,0,,and the cdr would point to another pair\nDialogue: 0,0:09:05.44,0:09:07.30,EN,,0,0,0,,whose car was the next thing in the sequence--\nDialogue: 0,0:09:07.36,0:09:08.44,EN,,0,0,0,,so there's 3--\nDialogue: 0,0:09:08.44,0:09:09.74,EN,,0,0,0,,and then another one.\nDialogue: 0,0:09:09.74,0:09:13.22,EN,,0,0,0,,So for each item in the sequence, I'll get a pair.\nDialogue: 0,0:09:15.82,0:09:18.32,EN,,0,0,0,,And now there are no more, so I put a special marker\nDialogue: 0,0:09:20.72,0:09:22.74,EN,,0,0,0,,that means there's nothing more in the List.\nDialogue: 0,0:09:24.14,0:09:34.64,EN,,0,0,0,,OK, so that's a conventional way to glue things together if you want to represent a sequence, right.\nDialogue: 0,0:09:34.64,0:09:37.98,EN,,0,0,0,,And what it is is a bunch of pairs,\nDialogue: 0,0:09:39.40,0:09:44.80,EN,,0,0,0,,the successive cars of each pair are the items that you want to glue together,\nDialogue: 0,0:09:46.00,0:09:48.46,EN,,0,0,0,,and the cdr pointer points to the next pair.\nDialogue: 0,0:09:50.02,0:09:56.04,EN,,0,0,0,,Now if I actually wanted to construct that, what I would type into Lisp is this:\nDialogue: 0,0:09:56.62,0:09:58.76,EN,,0,0,0,,I'd actually construct that as saying, well this thing is\nDialogue: 0,0:09:59.22,0:10:15.28,EN,,0,0,0,,the cons of 1 onto the cons of 2 onto the cons of 3 onto the cons of 4 onto, well, this thing nil.\nDialogue: 0,0:10:15.28,0:10:20.00,EN,,0,0,0,,And what nil is is a name for the end of List marker.\nDialogue: 0,0:10:20.80,0:10:23.24,EN,,0,0,0,,It's a special name, which means this is the end of the List.\nDialogue: 0,0:10:26.24,0:10:30.26,EN,,0,0,0,,OK, so that's how I would actually construct that.\nDialogue: 0,0:10:37.54,0:10:41.40,EN,,0,0,0,,Of course, it's a terrible drag to constantly have to write something like\nDialogue: 0,0:10:41.45,0:10:45.18,EN,,0,0,0,,the cons of 1 onto the cons of 2 onto the cons of 3, whenever you want to make this thing.\nDialogue: 0,0:10:45.18,0:10:50.10,EN,,0,0,0,,So Lisp has an operation that's called LIST,\nDialogue: 0,0:10:53.70,0:10:57.72,EN,,0,0,0,,and List is just an abbreviation for this nest of conses.\nDialogue: 0,0:10:58.96,0:11:06.32,EN,,0,0,0,,So I could say, I could construct that by saying that is the List of 1, 2, 3 and 4.\nDialogue: 0,0:11:07.78,0:11:11.74,EN,,0,0,0,,And all this is is another way, a piece of syntactic sugar,\nDialogue: 0,0:11:11.94,0:11:14.76,EN,,0,0,0,,a more convenient way for writing that chain of conses--\nDialogue: 0,0:11:14.76,0:11:17.84,EN,,0,0,0,,cons of cons of cons of cons of cons of cons onto nil.\nDialogue: 0,0:11:18.48,0:11:39.78,EN,,0,0,0,,So for example, I could build this thing and say, I'll define 1-TO-4 to be the List of 1, 2, 3 and 4.\nDialogue: 0,0:11:47.96,0:11:53.02,EN,,0,0,0,,OK, well notice some of the consequences of using this convention.\nDialogue: 0,0:11:53.80,0:11:56.92,EN,,0,0,0,,First of all if I have this List, this 1, 2, 3 and 4,\nDialogue: 0,0:11:57.36,0:12:02.64,EN,,0,0,0,,the car of the whole thing is the first element in the List, right.\nDialogue: 0,0:12:04.06,0:12:05.28,EN,,0,0,0,,How do I get 2?\nDialogue: 0,0:12:05.28,0:12:23.94,EN,,0,0,0,,Well, 2 would be the car of the cdr of this thing 1-TO-4, it would be 2, right.\nDialogue: 0,0:12:23.98,0:12:29.48,EN,,0,0,0,,I take this thing, I take the cdr of it, which is this much,\nDialogue: 0,0:12:29.82,0:12:31.68,EN,,0,0,0,,and the car of that is 2,\nDialogue: 0,0:12:32.58,0:12:47.42,EN,,0,0,0,,and then similarly, the car of the cdr of the cdr of 1-TO-4, cdr, cdr, car--\nDialogue: 0,0:12:47.42,0:12:51.36,EN,,0,0,0,,would give me 3, and so on.\nDialogue: 0,0:12:52.68,0:12:55.84,EN,,0,0,0,,Let's take a look at that on the computer screen for a second.\nDialogue: 0,0:12:57.50,0:13:11.18,EN,,0,0,0,,I could come up to List, and I could type define 1-TO-4 to be the List of 1, 2, 3 and 4, right.\nDialogue: 0,0:13:13.78,0:13:21.28,EN,,0,0,0,,And I'll tell that to Lisp, and it says, fine, that's the definition of 1-TO-4.\nDialogue: 0,0:13:22.30,0:13:36.74,EN,,0,0,0,,And I could say, for instance, what's the car of the cdr of the cdr of 1-TO-4, close paren, close paren.\nDialogue: 0,0:13:38.34,0:13:42.42,EN,,0,0,0,,Right, so the car of the cdr of the cdr would be 3.\nDialogue: 0,0:13:44.08,0:13:50.08,EN,,0,0,0,,Right, or I could say, what's 1-TO-4 itself.\nDialogue: 0,0:13:51.26,0:13:57.22,EN,,0,0,0,,And you see what Lisp typed out is 1, 2, 3, 4, enclosed in parentheses,\nDialogue: 0,0:13:57.22,0:14:02.12,EN,,0,0,0,,and this notation, typing the elements of the List enclosed in parentheses\nDialogue: 0,0:14:02.12,0:14:08.90,EN,,0,0,0,,is Lisp's conventional way for printing back this chain of pairs that represents a sequence.\nDialogue: 0,0:14:08.90,0:14:17.14,EN,,0,0,0,,So for example, if I said, what's the cdr of 1-TO-4,\nDialogue: 0,0:14:19.30,0:14:21.12,EN,,0,0,0,,that's going to be the rest of the List.\nDialogue: 0,0:14:21.32,0:14:26.96,EN,,0,0,0,,That's the thing pointed to by the first pair, which is, again, a sequence that starts off with 2.\nDialogue: 0,0:14:28.52,0:14:37.74,EN,,0,0,0,,Or for example, I go off and say, what's the cdr of the cdr of 1-TO-4;\nDialogue: 0,0:14:43.24,0:14:44.68,EN,,0,0,0,,then that's 3,4.\nDialogue: 0,0:14:44.82,0:14:59.66,EN,,0,0,0,,Or if I say, what's the cdr of the cdr of the cdr of the cdr of 1-TO-4,\nDialogue: 0,0:15:04.74,0:15:10.46,EN,,0,0,0,,and I'm down there looking at the end of List pointer itself, and Lisp prints that as just open paren, close paren.\nDialogue: 0,0:15:10.96,0:15:13.48,EN,,0,0,0,,You can think of that as a List with nothing in there.\nDialogue: 0,0:15:14.12,0:15:21.38,EN,,0,0,0,,All right, see at the end what I did there was I looked at the cdr of the cdr of the cdr of 1-TO-4,\nDialogue: 0,0:15:21.42,0:15:25.20,EN,,0,0,0,,and I'm just left with the end of List pointer itself.\nDialogue: 0,0:15:25.20,0:15:27.20,EN,,0,0,0,,And that gets printed as open close.\nDialogue: 0,0:15:34.14,0:15:39.98,EN,,0,0,0,,All right, well that's a conventional way you can see for working down a List\nDialogue: 0,0:15:41.50,0:15:43.44,EN,,0,0,0,,by taking successive cdrs of things.\nDialogue: 0,0:15:43.44,0:15:45.00,EN,,0,0,0,,It's called cdring down a List.\nDialogue: 0,0:15:46.64,0:15:49.78,EN,,0,0,0,,And of course it's pretty much of a drag to type all those cdrs by hand.\nDialogue: 0,0:15:49.78,0:15:52.24,EN,,0,0,0,,You don't do that. You write procedures that do that.\nDialogue: 0,0:15:52.96,0:15:59.10,EN,,0,0,0,,And in fact one very, very common thing to do in Lisp is to write procedures that,\nDialogue: 0,0:15:59.85,0:16:06.54,EN,,0,0,0,,sort of, take a List of things and do something to every element in List, and return you a List of the results.\nDialogue: 0,0:16:07.42,0:16:11.92,EN,,0,0,0,,So what I mean for example, is I might write a procedure called Scale-List,\nDialogue: 0,0:16:16.80,0:16:25.24,EN,,0,0,0,,and Scale-List I might say I want to scale by 10 the entire List 1-TO-4,\nDialogue: 0,0:16:26.66,0:16:35.32,EN,,0,0,0,,and that would return for me the List 10, 20, 30, 40.\nDialogue: 0,0:16:38.25,0:16:40.25,EN,,0,0,0,,Right, it returns List, and\nDialogue: 0,0:16:44.49,0:16:49.30,EN,,0,0,0,,well you can see that there's going to be some kind of recursive strategy for doing it.\nDialogue: 0,0:16:49.30,0:16:51.30,EN,,0,0,0,,How would I actually write that procedure?\nDialogue: 0,0:16:52.52,0:16:59.80,EN,,0,0,0,,The idea would be, well if you'd like to build up a List where you've multiplied every element by 10,\nDialogue: 0,0:17:00.44,0:17:04.84,EN,,0,0,0,,what you'd say is well you imagine that you'd taken the rest of the List--\nDialogue: 0,0:17:05.86,0:17:08.42,EN,,0,0,0,,right, the thing represented by the cdr of the List,\nDialogue: 0,0:17:08.42,0:17:14.16,EN,,0,0,0,,and suppose I'd already built a List where each of these was multiplied by 10--\nDialogue: 0,0:17:16.06,0:17:19.68,EN,,0,0,0,,that would be Scale-List of the cdr of the List.\nDialogue: 0,0:17:20.12,0:17:23.82,EN,,0,0,0,,And then all I have to do is multiply the car of the List by 10,\nDialogue: 0,0:17:24.89,0:17:27.24,EN,,0,0,0,,and then cons that onto the rest, and I'll get a List.\nDialogue: 0,0:17:29.02,0:17:33.09,EN,,0,0,0,,Right and then similarly, to have scaled the cdr of the List, I'll scale the cdr of that\nDialogue: 0,0:17:33.30,0:17:36.20,EN,,0,0,0,,cons onto that 2 multiplied by 10.\nDialogue: 0,0:17:36.42,0:17:41.16,EN,,0,0,0,,And finally when I get all the way down to the end, and I only have this end of List pointer.\nDialogue: 0,0:17:41.72,0:17:45.28,EN,,0,0,0,,All right, this thing whose name is nil-- well I just returned an end of List pointer.\nDialogue: 0,0:17:45.54,0:17:47.68,EN,,0,0,0,,So there's a recursive strategy for doing that.\nDialogue: 0,0:17:47.68,0:17:50.52,EN,,0,0,0,,Here's the actual procedure that does that.\nDialogue: 0,0:17:50.96,0:17:55.04,EN,,0,0,0,,Right, this is an example of the general strategy of cdr-ing down a List and\nDialogue: 0,0:17:55.66,0:17:58.24,EN,,0,0,0,,so called cons-ing up the result, right.\nDialogue: 0,0:17:58.24,0:18:06.04,EN,,0,0,0,,So to Scale a List l by some scale factor s, what do I do?\nDialogue: 0,0:18:06.04,0:18:10.40,EN,,0,0,0,,Well there's a test, and Lisp has the predicate called null.\nDialogue: 0,0:18:10.40,0:18:13.22,EN,,0,0,0,,Null means is this thing the end of List pointer,\nDialogue: 0,0:18:13.90,0:18:17.16,EN,,0,0,0,,or another way to think of that is are there any elements in this List, right.\nDialogue: 0,0:18:18.17,0:18:23.00,EN,,0,0,0,,But in any case if I'm looking at the end of List pointer, then I just return the end of List pointer.\nDialogue: 0,0:18:23.65,0:18:24.60,EN,,0,0,0,,I just return nil,\nDialogue: 0,0:18:24.94,0:18:35.14,EN,,0,0,0,,otherwise I cons together the result of doing what I'm going to do to the first element in the List,\nDialogue: 0,0:18:35.54,0:18:39.29,EN,,0,0,0,,namely taking the car of l and multiplying it by s,\nDialogue: 0,0:18:40.36,0:18:46.34,EN,,0,0,0,,and I cons that onto recursively scaling the rest of the List.\nDialogue: 0,0:18:49.98,0:18:52.18,EN,,0,0,0,,OK, so again, the general idea is that you\nDialogue: 0,0:18:52.22,0:18:56.09,EN,,0,0,0,,you recursively do something to the rest of the List, to the cdr of the List,\nDialogue: 0,0:18:56.48,0:19:01.16,EN,,0,0,0,,and then you cons that onto actually doing something to the first element of the List.\nDialogue: 0,0:19:01.16,0:19:05.18,EN,,0,0,0,,When you get down to the end here, you return the end of List pointer,\nDialogue: 0,0:19:07.34,0:19:11.36,EN,,0,0,0,,and that's a general pattern for doing something to a list.\nDialogue: 0,0:19:14.05,0:19:19.52,EN,,0,0,0,,Well of course you should know by now that the very fact\nDialogue: 0,0:19:19.53,0:19:22.62,EN,,0,0,0,,that there's a general pattern there means I shouldn't be writing this procedure at all.\nDialogue: 0,0:19:22.62,0:19:24.90,EN,,0,0,0,,What I should do is write a procedure\nDialogue: 0,0:19:24.90,0:19:26.32,EN,,0,0,0,,that's the general pattern itself\nDialogue: 0,0:19:26.80,0:19:30.30,EN,,0,0,0,,that says, do something to everything in the List and define this thing in terms of that.\nDialogue: 0,0:19:30.68,0:19:32.30,EN,,0,0,0,,Right, make some higher order procedure,\nDialogue: 0,0:19:32.32,0:19:35.18,EN,,0,0,0,,and here's the higher order procedure that does that. It's called MAP,\nDialogue: 0,0:19:36.73,0:19:43.17,EN,,0,0,0,,and what MAP does is it takes a List, takes a List l, and it takes a procedure p,\nDialogue: 0,0:19:44.92,0:19:51.08,EN,,0,0,0,,and it returns the List of the elements gotten by applying p to each successive element in the List.\nDialogue: 0,0:19:51.81,0:19:55.40,EN,,0,0,0,,All right, so p of e1, p of e2, p of en.\nDialogue: 0,0:19:55.64,0:20:01.54,EN,,0,0,0,,Right, so I think of taking this List and transforming it by applying p to each element.\nDialogue: 0,0:20:02.52,0:20:07.08,EN,,0,0,0,,And you see all this procedure is is exactly the general strategy I said.\nDialogue: 0,0:20:07.08,0:20:09.08,EN,,0,0,0,,Instead of multiply by 10, it's do the procedure.\nDialogue: 0,0:20:09.08,0:20:11.64,EN,,0,0,0,,If the List is empty, return nil.\nDialogue: 0,0:20:11.86,0:20:16.60,EN,,0,0,0,,Otherwise, apply p to the first element of the List.\nDialogue: 0,0:20:17.14,0:20:18.74,EN,,0,0,0,,Right, apply p to car of l,\nDialogue: 0,0:20:19.30,0:20:25.40,EN,,0,0,0,,and cons that onto the result of applying p to everything in the cdr of the List,\nDialogue: 0,0:20:25.61,0:20:28.84,EN,,0,0,0,,so that's a general procedure called MAP.\nDialogue: 0,0:20:29.86,0:20:39.04,EN,,0,0,0,,And I could define Scale-List in terms of MAP.\nDialogue: 0,0:20:39.04,0:20:41.04,EN,,0,0,0,,Let me show you that first.\nDialogue: 0,0:20:43.46,0:20:52.50,EN,,0,0,0,,But I could say Scale-List is another way to define it is just MAP along the List by the procedure,\nDialogue: 0,0:20:52.50,0:20:55.54,EN,,0,0,0,,which takes an item and multiplies it by s.\nDialogue: 0,0:20:58.96,0:21:01.90,EN,,0,0,0,,Right, so this is really the way I should think about scaling the List,\nDialogue: 0,0:21:02.12,0:21:07.40,EN,,0,0,0,,build that actual recursion into the general strategy, not to every particular procedure I write.\nDialogue: 0,0:21:07.40,0:21:11.28,EN,,0,0,0,,And of course, one of the values of doing this is that you start to see commonality.\nDialogue: 0,0:21:12.16,0:21:15.02,EN,,0,0,0,,Right, again you're capturing general patterns of usage.\nDialogue: 0,0:21:15.96,0:21:31.18,EN,,0,0,0,,For instance, if I said MAP, the square procedure, down this List 1-TO-4, then I'd end up with 1, 4, 9 and 16.\nDialogue: 0,0:21:32.48,0:21:37.17,EN,,0,0,0,,Right, or if I said MAP down this List,\nDialogue: 0,0:21:37.57,0:21:46.32,EN,,0,0,0,,lambda of x plus x 10, if I MAP that down 1-TO-4,\nDialogue: 0,0:21:49.68,0:21:52.86,EN,,0,0,0,,then I'd get the List where everything had 10 added to it:\nDialogue: 0,0:21:53.34,0:21:58.17,EN,,0,0,0,,right, so I'd get 11,12, 13, 14.\nDialogue: 0,0:22:00.56,0:22:05.76,EN,,0,0,0,,And you can see that's going to be a very, very common idea: doing something to every element in the List.\nDialogue: 0,0:22:08.66,0:22:12.22,EN,,0,0,0,,One thing you might think about is writing MAP in an iterative style.\nDialogue: 0,0:22:12.22,0:22:16.04,EN,,0,0,0,,The one I wrote happens to evolve a recursive process,\nDialogue: 0,0:22:16.36,0:22:19.10,EN,,0,0,0,,but we could just as easily have made one that evolves an iterative process.\nDialogue: 0,0:22:19.10,0:22:23.16,EN,,0,0,0,,But see the interesting thing about it is that once you start thinking in terms of MAP--\nDialogue: 0,0:22:24.02,0:22:29.00,EN,,0,0,0,,see, once you say scale is just MAP, you stop thinking about whether it's iterative or recursive,\nDialogue: 0,0:22:29.00,0:22:31.82,EN,,0,0,0,,and you just say, well there's this aggregate, there's this List,\nDialogue: 0,0:22:32.22,0:22:34.52,EN,,0,0,0,,and what I do is transform every item in the List,\nDialogue: 0,0:22:34.56,0:22:38.36,EN,,0,0,0,,and I stop thinking about the particular control structure in order.\nDialogue: 0,0:22:38.88,0:22:41.09,EN,,0,0,0,,That's a very, very important idea,\nDialogue: 0,0:22:42.36,0:22:46.48,EN,,0,0,0,,and it, I guess it really comes out of APL.\nDialogue: 0,0:22:46.48,0:22:49.10,EN,,0,0,0,,It's, sort of, the really important idea in APL\nDialogue: 0,0:22:49.12,0:22:51.13,EN,,0,0,0,,that you stop thinking about control structures,\nDialogue: 0,0:22:51.41,0:22:53.92,EN,,0,0,0,,and you start thinking about operations on aggregates,\nDialogue: 0,0:22:55.01,0:23:00.01,EN,,0,0,0,,and then about halfway through this course,we'll see when we talk about something called stream processing,\nDialogue: 0,0:23:00.26,0:23:02.64,EN,,0,0,0,,how that view of the world really comes into its glory.\nDialogue: 0,0:23:02.64,0:23:05.30,EN,,0,0,0,,This is just us a, sort of, cute idea.\nDialogue: 0,0:23:05.30,0:23:08.70,EN,,0,0,0,,But we'll see much more applications of that later on.\nDialogue: 0,0:23:09.36,0:23:16.84,EN,,0,0,0,,Well let me mention that there's something that's very similar to MAP that's also a useful idea, and that's--\nDialogue: 0,0:23:17.56,0:23:22.54,EN,,0,0,0,,see, MAP says I take a List, I apply something to each item,\nDialogue: 0,0:23:22.98,0:23:25.62,EN,,0,0,0,,and I return a List of the successive values.\nDialogue: 0,0:23:25.98,0:23:28.69,EN,,0,0,0,,There's another thing I might do, which is very, very similar,\nDialogue: 0,0:23:29.32,0:23:35.86,EN,,0,0,0,,which is take a List and some action you want to do and then do it to each item in the List in sequence.\nDialogue: 0,0:23:36.29,0:23:39.40,EN,,0,0,0,,Don't make a List of the values, just do this particular action,\nDialogue: 0,0:23:40.02,0:23:45.10,EN,,0,0,0,,and that's something that's very much like MAP.\nDialogue: 0,0:23:45.10,0:23:46.02,EN,,0,0,0,,It's called for-each,\nDialogue: 0,0:23:46.74,0:23:49.48,EN,,0,0,0,,and for-each takes a procedure and a List,\nDialogue: 0,0:23:49.62,0:23:53.86,EN,,0,0,0,,and what it's going to do is do something to every item in the List.\nDialogue: 0,0:23:55.16,0:23:58.53,EN,,0,0,0,,So basically what it does: it says if the List is not empty,\nDialogue: 0,0:23:59.74,0:24:01.12,EN,,0,0,0,,if the List is not null,\nDialogue: 0,0:24:01.90,0:24:06.25,EN,,0,0,0,,then what I do is, I apply my procedure to the first item in the List,\nDialogue: 0,0:24:07.68,0:24:11.66,EN,,0,0,0,,and then I do this thing to the rest of the List.\nDialogue: 0,0:24:12.44,0:24:15.25,EN,,0,0,0,,I apply for-each to the cdr of the List.\nDialogue: 0,0:24:15.88,0:24:18.73,EN,,0,0,0,,All right, so I do it to the first of the List, do it to the rest of the List,\nDialogue: 0,0:24:19.32,0:24:23.92,EN,,0,0,0,,and of course, when I call it recursively, that's going to do it to the rest of the rest of the List and so on.\nDialogue: 0,0:24:23.92,0:24:28.12,EN,,0,0,0,,And finally, when I get done, I have to just do something to say I'm done,\nDialogue: 0,0:24:28.16,0:24:32.40,EN,,0,0,0,,so we'll return the message \"done.\" So that's very, very similar to MAP.\nDialogue: 0,0:24:32.80,0:24:35.12,EN,,0,0,0,,It's mostly different in what it returns.\nDialogue: 0,0:24:35.48,0:24:39.90,EN,,0,0,0,,And so for example, if I had some procedure that printed things on the screen,\nDialogue: 0,0:24:40.56,0:24:45.81,EN,,0,0,0,,if I wanted to print everything in the List, I could say for-each, print this List.\nDialogue: 0,0:24:46.78,0:24:51.33,EN,,0,0,0,,Or if I had a List of figures, and I wanted to draw them on the display,\nDialogue: 0,0:24:51.62,0:24:54.86,EN,,0,0,0,,I could say for-each, display on the screen this figure.\nDialogue: 0,0:24:58.18,0:24:59.32,EN,,0,0,0,,Take questions.\nDialogue: 0,0:25:00.62,0:25:04.26,EN,,0,0,0,,AUDIENCE: Does it create a new copy with something done to it,\nDialogue: 0,0:25:04.30,0:25:07.54,EN,,0,0,0,,unless you explicitly tell it to do that? Is that correct?\nDialogue: 0,0:25:07.54,0:25:09.18,EN,,0,0,0,,PROFESSOR: Right. Ah.\nDialogue: 0,0:25:09.93,0:25:10.94,EN,,0,0,0,,Yeah, that's right.\nDialogue: 0,0:25:10.94,0:25:15.14,EN,,0,0,0,,For-each does not create a List. It just sort of does something.\nDialogue: 0,0:25:15.14,0:25:17.29,EN,,0,0,0,,So if you have a bunch of things you want to do\nDialogue: 0,0:25:18.02,0:25:21.56,EN,,0,0,0,,and you're not worried about values like printing something, or drawing something on the screen,\nDialogue: 0,0:25:21.89,0:25:24.60,EN,,0,0,0,,or ringing the bell on the terminal,or for something,\nDialogue: 0,0:25:24.60,0:25:27.64,EN,,0,0,0,,you can say for-each, you know, do this for-each of those things in the List,\nDialogue: 0,0:25:28.21,0:25:32.42,EN,,0,0,0,,whereas MAP actually builds you this new collection of values that you might want to use.\nDialogue: 0,0:25:32.42,0:25:34.16,EN,,0,0,0,,It's just a subtle difference between them.\nDialogue: 0,0:25:34.16,0:25:36.30,EN,,0,0,0,,AUDIENCE: Could you write MAP using for-each,\nDialogue: 0,0:25:36.32,0:25:40.16,EN,,0,0,0,,so that you did some sort of cons or something to build the List back up?\nDialogue: 0,0:25:40.18,0:25:44.46,EN,,0,0,0,,PROFESSOR: Well, sort of. I mean, I probably could.\nDialogue: 0,0:25:44.46,0:25:49.98,EN,,0,0,0,,I can't think of how to do it right offhand, but yeah, I could arrange something.\nDialogue: 0,0:25:50.48,0:25:54.73,EN,,0,0,0,,AUDIENCE: The vital difference between MAP and for-each is one is recursive and the other is not\nDialogue: 0,0:25:54.73,0:26:00.62,EN,,0,0,0,,in the sense you defined early yesterday, I believe.\nDialogue: 0,0:26:01.24,0:26:03.86,EN,,0,0,0,,PROFESSOR: Yeah, about MAP and for-each and recursion.\nDialogue: 0,0:26:03.86,0:26:05.48,EN,,0,0,0,,Yeah, that's a good point.\nDialogue: 0,0:26:05.48,0:26:13.08,EN,,0,0,0,,For the MAP procedure I wrote, that happens to be a recursive process.\nDialogue: 0,0:26:13.82,0:26:17.06,EN,,0,0,0,,And the reason for that is that when you've done this thing to the rest of the List,\nDialogue: 0,0:26:17.08,0:26:20.96,EN,,0,0,0,,you're waiting for that value so that you can stick it on to the beginning of the List,\nDialogue: 0,0:26:21.73,0:26:24.53,EN,,0,0,0,,whereas for-each doesn't really have any values to wait for.\nDialogue: 0,0:26:24.84,0:26:26.66,EN,,0,0,0,,So that turns out to be an iterative process.\nDialogue: 0,0:26:26.66,0:26:27.72,EN,,0,0,0,,That's not fundamental.\nDialogue: 0,0:26:27.72,0:26:31.80,EN,,0,0,0,,I could have defined MAP so that it's evolved by an iterative process.\nDialogue: 0,0:26:31.82,0:26:32.82,EN,,0,0,0,,I just didn't happen to.\nDialogue: 0,0:26:34.24,0:26:42.90,EN,,0,0,0,,AUDIENCE: If you were to call for each with a List that had embedded Lists, I imagine it would work, right?\nDialogue: 0,0:26:42.90,0:26:48.10,EN,,0,0,0,,It would give you the internal elements of each of those internal Lists?\nDialogue: 0,0:26:48.70,0:26:50.40,EN,,0,0,0,,PROFESSOR: OK, the question is if I call\nDialogue: 0,0:26:50.40,0:26:52.28,EN,,0,0,0,,for-each or map, for that matter\nDialogue: 0,0:26:52.81,0:26:55.28,EN,,0,0,0,,with a List that had Lists in it\nDialogue: 0,0:26:56.69,0:27:00.60,EN,,0,0,0,,although we haven't really looked at that yet--would that work.\nDialogue: 0,0:27:01.02,0:27:06.56,EN,,0,0,0,,The answer is yes in the sense I mean work and no in the sense that you mean work,\nDialogue: 0,0:27:06.86,0:27:10.65,EN,,0,0,0,,because all that-- see if I give you a List,\nDialogue: 0,0:27:12.80,0:27:14.20,EN,,0,0,0,,where hanging off here is,\nDialogue: 0,0:27:16.06,0:27:21.46,EN,,0,0,0,,you know, is something that's not a number, maybe another List or you know, another cons or something,\nDialogue: 0,0:27:21.96,0:27:24.54,EN,,0,0,0,,for-each just says do something to each item in this List.\nDialogue: 0,0:27:24.54,0:27:26.96,EN,,0,0,0,,It goes down successively looking at the cdrs.\nDialogue: 0,0:27:26.96,0:27:27.20,EN,,0,0,0,,AUDIENCE: OK.\nDialogue: 0,0:27:27.20,0:27:31.06,EN,,0,0,0,,PROFESSOR: And as far as it's concerned, the first item in this List is whatever is hanging off here.\nDialogue: 0,0:27:31.06,0:27:31.65,EN,,0,0,0,,AUDIENCE: Mhm.\nDialogue: 0,0:27:31.65,0:27:33.94,EN,,0,0,0,,PROFESSOR: That might or might not be the right thing.\nDialogue: 0,0:27:33.94,0:27:35.57,EN,,0,0,0,,AUDIENCE: So it wouldn't go down into the--\nDialogue: 0,0:27:35.57,0:27:36.91,EN,,0,0,0,,PROFESSOR: Absolutely not.\nDialogue: 0,0:27:36.91,0:27:38.51,EN,,0,0,0,,I could certainly write something else.\nDialogue: 0,0:27:38.51,0:27:42.97,EN,,0,0,0,,There's another, what you're looking for is a common pattern of usage called tree recursion,\nDialogue: 0,0:27:43.01,0:27:47.94,EN,,0,0,0,,where you take a List, and you actually go all the way down to the what's called the leaves of the tree.\nDialogue: 0,0:27:47.94,0:27:51.05,EN,,0,0,0,,And you could write such a thing, but that's not for-each and it's not MAP.\nDialogue: 0,0:27:52.42,0:27:55.05,EN,,0,0,0,,Remember, these things are really being very simple minded.\nDialogue: 0,0:27:55.77,0:27:56.89,EN,,0,0,0,,OK, no more questions?\nDialogue: 0,0:27:57.68,0:27:58.57,EN,,0,0,0,,All right, let's break.\nDialogue: 0,0:27:59.11,0:28:10.99,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:28:11.46,0:28:14.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:28:14.32,0:28:17.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:28:27.38,0:28:34.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:28:34.86,0:28:38.58,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson Escher Example\nDialogue: 0,0:28:41.94,0:28:48.65,EN,,0,0,0,,PROFESSOR: What I'd like to do now is spend the rest of this time talking about one example,\nDialogue: 0,0:28:50.04,0:28:53.92,EN,,0,0,0,,and this example, I think, pretty much summarizes everything that we've done up until now:\nDialogue: 0,0:28:54.74,0:28:56.29,EN,,0,0,0,,all right, and that's List structure\nDialogue: 0,0:28:57.17,0:28:59.48,EN,,0,0,0,,and issues of abstraction,\nDialogue: 0,0:28:59.54,0:29:00.82,EN,,0,0,0,,and representation\nDialogue: 0,0:29:01.60,0:29:04.60,EN,,0,0,0,,and representation and capturing commonality with higher order procedures,\nDialogue: 0,0:29:04.60,0:29:09.80,EN,,0,0,0,,and also is going to introduce something we haven't really talked about a lot yet-- what I said is the major third theme in this course:\nDialogue: 0,0:29:09.85,0:29:13.46,EN,,0,0,0,,what I said is the major third theme in this course:\nDialogue: 0,0:29:13.96,0:29:15.53,EN,,0,0,0,,meta-linguistic abstraction,\nDialogue: 0,0:29:15.54,0:29:21.90,EN,,0,0,0,,which is the idea that one of the ways of tackling complexity in engineering design\nDialogue: 0,0:29:22.86,0:29:25.80,EN,,0,0,0,,is to build a suitable powerful language.\nDialogue: 0,0:29:28.17,0:29:34.74,EN,,0,0,0,,You might recall what I said was pretty much the very most important thing that we're going to tell you in this course is that\nDialogue: 0,0:29:34.74,0:29:41.17,EN,,0,0,0,,when you think about a language, you think about it in terms of what are the primitives;\nDialogue: 0,0:29:42.98,0:29:46.69,EN,,0,0,0,,what are the means of combination--\nDialogue: 0,0:29:49.72,0:29:52.80,EN,,0,0,0,,right, what are the things that allow you to build bigger things;\nDialogue: 0,0:29:53.61,0:29:55.24,EN,,0,0,0,,and then what are the means of abstraction.\nDialogue: 0,0:30:00.97,0:30:05.16,EN,,0,0,0,,How do you take those bigger things that you've built\nDialogue: 0,0:30:05.56,0:30:07.97,EN,,0,0,0,,put black boxes around them\nDialogue: 0,0:30:08.45,0:30:11.71,EN,,0,0,0,,and use them as elements in making something even more complicated?\nDialogue: 0,0:30:13.53,0:30:18.72,EN,,0,0,0,,Now the particular language I'm going to talk about is an example\nDialogue: 0,0:30:18.73,0:30:22.70,EN,,0,0,0,,that was made up by a friend of ours called Peter Henderson.\nDialogue: 0,0:30:28.24,0:30:31.74,EN,,0,0,0,,Peter Henderson is at the University of Stirling in Scotland.\nDialogue: 0,0:30:32.78,0:30:40.98,EN,,0,0,0,,And what this language is about is making figures that sort of look like this.\nDialogue: 0,0:30:41.86,0:30:46.66,EN,,0,0,0,,This is this is a woodcut by Escher called \"Square Limit.\"\nDialogue: 0,0:30:49.33,0:30:57.94,EN,,0,0,0,,You, sort of, see it has this complicated, kind of, recursive, sort of, recursive kind of figure,\nDialogue: 0,0:30:58.84,0:31:01.46,EN,,0,0,0,,where there's this fish pattern in the middle and things sort of\nDialogue: 0,0:31:01.70,0:31:04.56,EN,,0,0,0,,bleed out smaller and smaller in self similar ways.\nDialogue: 0,0:31:08.49,0:31:12.80,EN,,0,0,0,,Anyway, Peter Henderson's language was for describing figures that look like that\nDialogue: 0,0:31:13.37,0:31:18.28,EN,,0,0,0,,and designing new ones that look like that and drawing them on a display screen.\nDialogue: 0,0:31:20.24,0:31:27.48,EN,,0,0,0,,There's another theme that we'll see illustrated by this example,\nDialogue: 0,0:31:28.09,0:31:32.02,EN,,0,0,0,,and that's the issue of what Gerry and I have already mentioned a lot:\nDialogue: 0,0:31:32.02,0:31:36.17,EN,,0,0,0,,that there's no real difference, in some sense, between procedures and data.\nDialogue: 0,0:31:37.26,0:31:42.40,EN,,0,0,0,,And anyway I hope by the end of this morning, if you're not already,\nDialogue: 0,0:31:42.58,0:31:47.60,EN,,0,0,0,,you will be completely confused about what the difference between procedures and data are,\nDialogue: 0,0:31:47.96,0:31:49.58,EN,,0,0,0,,if you're not confused about that already.\nDialogue: 0,0:31:50.80,0:31:55.28,EN,,0,0,0,,Well in any case, let's start describing Peter's language.\nDialogue: 0,0:31:55.28,0:31:57.26,EN,,0,0,0,,I should start by telling you what the primitives are.\nDialogue: 0,0:31:58.29,0:32:00.92,EN,,0,0,0,,This language is very simple because there's only one primitive.\nDialogue: 0,0:32:03.33,0:32:06.30,EN,,0,0,0,,A primitive is not quite what you think it is.\nDialogue: 0,0:32:07.08,0:32:09.18,EN,,0,0,0,,There's only one primitive called a picture,\nDialogue: 0,0:32:09.70,0:32:12.11,EN,,0,0,0,,and a picture is not quite what you think it is.\nDialogue: 0,0:32:12.11,0:32:14.17,EN,,0,0,0,,Here's an example.\nDialogue: 0,0:32:14.17,0:32:15.17,EN,,0,0,0,,This is a picture of George.\nDialogue: 0,0:32:19.01,0:32:20.37,EN,,0,0,0,,The idea is that\nDialogue: 0,0:32:22.33,0:32:24.57,EN,,0,0,0,,a picture in this language is going to be something\nDialogue: 0,0:32:24.89,0:32:31.46,EN,,0,0,0,,that draws a figure scaled to fit a rectangle that you specify.\nDialogue: 0,0:32:33.00,0:32:34.42,EN,,0,0,0,,So here you see emphasis line\nDialogue: 0,0:32:34.42,0:32:37.70,EN,,0,0,0,,is outline of a rectangle, that's not really part of the picture,\nDialogue: 0,0:32:40.49,0:32:47.17,EN,,0,0,0,,but the picture-- you'll give it a rectangle, and it will draw this figure scaled to fit the rectangle.\nDialogue: 0,0:32:47.17,0:32:52.16,EN,,0,0,0,,So for example, there's George, and here, this is also George.\nDialogue: 0,0:32:53.21,0:32:56.65,EN,,0,0,0,,It's the same picture, right, just scaled to fit a different rectangle.\nDialogue: 0,0:32:57.40,0:32:59.28,EN,,0,0,0,,Here's George as a fat kid.\nDialogue: 0,0:33:00.01,0:33:03.44,EN,,0,0,0,,That's the same George.\nDialogue: 0,0:33:03.81,0:33:05.14,EN,,0,0,0,,It's all the same figure.\nDialogue: 0,0:33:05.14,0:33:09.57,EN,,0,0,0,,All of these three things are the same picture in this language.\nDialogue: 0,0:33:09.58,0:33:13.04,EN,,0,0,0,,I'm just giving it different rectangles to scale itself in.\nDialogue: 0,0:33:16.08,0:33:20.65,EN,,0,0,0,,OK, those are the primitives. That is the primitive.\nDialogue: 0,0:33:21.44,0:33:25.25,EN,,0,0,0,,Now let's start talking about the means of combination and the operations.\nDialogue: 0,0:33:25.90,0:33:30.17,EN,,0,0,0,,There is, for example, an operation called Rotate.\nDialogue: 0,0:33:31.09,0:33:33.66,EN,,0,0,0,,And what Rotate does is, if I have a picture,\nDialogue: 0,0:33:35.37,0:33:39.93,EN,,0,0,0,,say a picture that draws an \"A\" in some rectangle that I give it,\nDialogue: 0,0:33:41.84,0:33:45.73,EN,,0,0,0,,the Rotate of that--say the Rotate by 90 degrees would,\nDialogue: 0,0:33:47.02,0:33:50.65,EN,,0,0,0,,if I give it a rectangle, draw the same image,\nDialogue: 0,0:33:50.65,0:33:53.88,EN,,0,0,0,,but again, scaled to fit that rectangle.\nDialogue: 0,0:33:56.11,0:33:58.34,EN,,0,0,0,,So that's Rotate by 90 degrees.\nDialogue: 0,0:33:58.34,0:34:03.20,EN,,0,0,0,,There's another operation called Flip that can flip something, either horizontally or vertically.\nDialogue: 0,0:34:04.77,0:34:06.00,EN,,0,0,0,,All right, so those are, sort of, operations,\nDialogue: 0,0:34:06.01,0:34:10.40,EN,,0,0,0,,or you can think of those as means of combination of one element.\nDialogue: 0,0:34:10.89,0:34:12.42,EN,,0,0,0,,I can put things together.\nDialogue: 0,0:34:13.44,0:34:15.54,EN,,0,0,0,,There's a means of combination called Beside,\nDialogue: 0,0:34:16.46,0:34:24.78,EN,,0,0,0,,and what Beside does: it'll take two pictures, let's say A and B--\nDialogue: 0,0:34:29.02,0:34:33.25,EN,,0,0,0,,and by picture I mean something that's going to draw an image in a specified rectangle--\nDialogue: 0,0:34:34.05,0:34:36.51,EN,,0,0,0,,and what Beside will do--\nDialogue: 0,0:34:37.85,0:34:44.08,EN,,0,0,0,,I have to say, Beside of A and B, the side of two pictures and some number, s.\nDialogue: 0,0:34:45.34,0:34:48.08,EN,,0,0,0,,And s will be a number between zero and one.\nDialogue: 0,0:34:50.51,0:34:52.57,EN,,0,0,0,,And Beside will draw a picture that looks like this.\nDialogue: 0,0:34:52.57,0:34:56.71,EN,,0,0,0,,It will take the rectangle you give it and scale its base by s.\nDialogue: 0,0:34:56.71,0:34:58.71,EN,,0,0,0,,Say s is 0.5.\nDialogue: 0,0:35:00.18,0:35:07.17,EN,,0,0,0,,And then over here it will draw-- it'll put the first picture, and over here it'll put the second picture.\nDialogue: 0,0:35:07.81,0:35:12.65,EN,,0,0,0,,and over here it'll put the second picture.\nDialogue: 0,0:35:13.82,0:35:16.44,EN,,0,0,0,,Or for instance if I gave it a different value of s,\nDialogue: 0,0:35:16.81,0:35:23.02,EN,,0,0,0,,Or for instance if I gave it a different value of s, if I said Beside with a 0.25,\nDialogue: 0,0:35:25.94,0:35:29.09,EN,,0,0,0,,it would do the same thing, except the A would be much skinnier.\nDialogue: 0,0:35:34.05,0:35:36.28,EN,,0,0,0,,So it would draw something like that.\nDialogue: 0,0:35:37.82,0:35:40.29,EN,,0,0,0,,So there's a means of combination Beside,\nDialogue: 0,0:35:40.68,0:35:46.05,EN,,0,0,0,,and similarly there's an Above, which does the same thing except it puts them vertically instead of horizontally.\nDialogue: 0,0:35:47.84,0:35:48.89,EN,,0,0,0,,Well let's look at that.\nDialogue: 0,0:35:50.74,0:35:56.00,EN,,0,0,0,,All right, there's George and his kid brother,\nDialogue: 0,0:35:56.72,0:36:07.05,EN,,0,0,0,,which is, right, constructed by taking George and putting him Beside\nDialogue: 0,0:36:10.36,0:36:14.42,EN,,0,0,0,,The Above, taking the empty picture, and there's a thing called the empty picture,\nDialogue: 0,0:36:14.52,0:36:16.14,EN,,0,0,0,,which does the obvious thing--\nDialogue: 0,0:36:16.14,0:36:19.14,EN,,0,0,0,,putting the empty picture above a copy of George,\nDialogue: 0,0:36:19.14,0:36:21.14,EN,,0,0,0,,and then putting that whole thing Beside George.\nDialogue: 0,0:36:28.96,0:36:30.34,EN,,0,0,0,,Here's something called P which is,\nDialogue: 0,0:36:31.10,0:36:39.04,EN,,0,0,0,,which is, again, George Beside Flipping George,\nDialogue: 0,0:36:40.53,0:36:42.08,EN,,0,0,0,,I think, horizontally in this case,\nDialogue: 0,0:36:42.37,0:36:44.80,EN,,0,0,0,,Rotating the whole result 180 degrees\nDialogue: 0,0:36:45.80,0:36:50.82,EN,,0,0,0,,putting them Beside one another with the basic rectangle divided at 0.5,\nDialogue: 0,0:36:52.56,0:36:53.90,EN,,0,0,0,,right, and I can call that P.\nDialogue: 0,0:36:55.90,0:36:57.88,EN,,0,0,0,,And then I can take P,\nDialogue: 0,0:36:59.21,0:37:04.96,EN,,0,0,0,,And then I can take P, and put it above the Flipped copy of itself, and I can call that Q.\nDialogue: 0,0:37:09.20,0:37:13.26,EN,,0,0,0,,Notice how rapidly that we've built up complexity,\nDialogue: 0,0:37:14.36,0:37:21.05,EN,,0,0,0,,just in, you know, 15 seconds, you've gotten from George to that thing Q. Why is that?\nDialogue: 0,0:37:22.05,0:37:24.55,EN,,0,0,0,,How are how we able to do that so fast?\nDialogue: 0,0:37:25.85,0:37:28.02,EN,,0,0,0,,The answer is the closure property.\nDialogue: 0,0:37:28.69,0:37:32.98,EN,,0,0,0,,See, it's the fact that when I take a picture and put it Beside another picture,\nDialogue: 0,0:37:34.30,0:37:35.29,EN,,0,0,0,,that's then, again, a picture\nDialogue: 0,0:37:35.33,0:37:37.78,EN,,0,0,0,,that I can go and Rotate and Flip or put Above something else.\nDialogue: 0,0:37:39.17,0:37:40.88,EN,,0,0,0,,Right, and when I take that element P,\nDialogue: 0,0:37:40.89,0:37:44.88,EN,,0,0,0,,which is the Beside or the Flip or the Rotate of something, that's, again, a picture.\nDialogue: 0,0:37:45.22,0:37:50.20,EN,,0,0,0,,Right, the world of pictures is closed under those means of combination.\nDialogue: 0,0:37:50.77,0:37:52.24,EN,,0,0,0,,So whenever I have something,\nDialogue: 0,0:37:52.48,0:37:55.17,EN,,0,0,0,,I can turn right around and use that as an element in something else.\nDialogue: 0,0:37:56.33,0:37:58.52,EN,,0,0,0,,So maybe better than List and segments,\nDialogue: 0,0:37:58.54,0:38:03.28,EN,,0,0,0,,that just gives you an image for how fast you can build up complexity, because operations are closed.\nDialogue: 0,0:38:07.48,0:38:12.02,EN,,0,0,0,,OK, well before we go on with building more things,\nDialogue: 0,0:38:12.04,0:38:14.77,EN,,0,0,0,,let's talk about how this language is actually implemented.\nDialogue: 0,0:38:16.91,0:38:21.50,EN,,0,0,0,,The basic element that sits under the table here\nDialogue: 0,0:38:21.93,0:38:24.52,EN,,0,0,0,,is a thing called a rectangle,\nDialogue: 0,0:38:26.09,0:38:28.28,EN,,0,0,0,,and what a rectangle is going to be,\nDialogue: 0,0:38:28.28,0:38:33.68,EN,,0,0,0,,it's a thing that specified by an origin\nDialogue: 0,0:38:36.45,0:38:40.18,EN,,0,0,0,,that's going to be some vector that says where the rectangle starts.\nDialogue: 0,0:38:40.18,0:38:42.29,EN,,0,0,0,,And then there's going to be some other vector\nDialogue: 0,0:38:43.66,0:38:46.33,EN,,0,0,0,,that I'm going to call the horizontal part of the rectangle,\nDialogue: 0,0:38:55.76,0:38:59.25,EN,,0,0,0,,and another vector called the vertical part of the rectangle.\nDialogue: 0,0:39:00.49,0:39:02.68,EN,,0,0,0,,And those three pieces are the elements:\nDialogue: 0,0:39:02.68,0:39:04.51,EN,,0,0,0,,where the lower vertex is,\nDialogue: 0,0:39:04.93,0:39:09.97,EN,,0,0,0,,how you get to the next vertex over here, and how you get to the vertex over there.\nDialogue: 0,0:39:09.97,0:39:12.37,EN,,0,0,0,,The three vectors specify a rectangle.\nDialogue: 0,0:39:16.00,0:39:18.93,EN,,0,0,0,,Now to actually build rectangles, what I'll assume is\nDialogue: 0,0:39:19.77,0:39:22.06,EN,,0,0,0,,that we have a constructor called \"make rectangle,\"\nDialogue: 0,0:39:23.01,0:39:24.26,EN,,0,0,0,,or \"make-rect,\"\nDialogue: 0,0:39:27.56,0:39:35.17,EN,,0,0,0,,and selectors for horiz and vert and origin\nDialogue: 0,0:39:37.58,0:39:39.65,EN,,0,0,0,,that get out the pieces of that rectangle.\nDialogue: 0,0:39:39.65,0:39:42.54,EN,,0,0,0,,And well, you know a lot of ways you can do this now.\nDialogue: 0,0:39:42.54,0:39:47.62,EN,,0,0,0,,You can do it by using pairs in some way or other standard List or not.\nDialogue: 0,0:39:47.62,0:39:51.40,EN,,0,0,0,,But in any case, the implementation of these things, that's George's problem.\nDialogue: 0,0:39:51.40,0:39:53.17,EN,,0,0,0,,It's just a data representation problem.\nDialogue: 0,0:39:53.17,0:39:55.47,EN,,0,0,0,,So let's assume we have these rectangles to work with.\nDialogue: 0,0:39:59.05,0:40:05.08,EN,,0,0,0,,OK. Now the idea of this, remember what's got to happen.\nDialogue: 0,0:40:05.08,0:40:08.22,EN,,0,0,0,,Somehow we have to worry about taking the figure\nDialogue: 0,0:40:09.33,0:40:12.97,EN,,0,0,0,,and scaling it to fit some rectangle that you give it,\nDialogue: 0,0:40:13.60,0:40:16.60,EN,,0,0,0,,that's the basic thing you have to arrange,\nDialogue: 0,0:40:16.60,0:40:18.60,EN,,0,0,0,,that these pictures can do.\nDialogue: 0,0:40:22.22,0:40:23.65,EN,,0,0,0,,How do we think about that?\nDialogue: 0,0:40:23.65,0:40:27.08,EN,,0,0,0,,Well, one way to think about that is that any time I give you a rectangle,\nDialogue: 0,0:40:35.68,0:40:38.68,EN,,0,0,0,,Any time I gave you a rectangle, that defines,\nDialogue: 0,0:40:39.25,0:40:45.77,EN,,0,0,0,,that defines,in some sense, a transformation from the standard square into that rectangle.\nDialogue: 0,0:40:45.77,0:40:46.54,EN,,0,0,0,,Let me say what I mean.\nDialogue: 0,0:40:46.54,0:40:48.53,EN,,0,0,0,,By the standard square, I'll mean something,\nDialogue: 0,0:40:49.04,0:40:59.04,EN,,0,0,0,,which is a square whose coordinates are 0,0, and 1,0, and 0,1 and 1,1.\nDialogue: 0,0:41:01.40,0:41:05.72,EN,,0,0,0,,And there's some sort of the obvious scaling transformation,\nDialogue: 0,0:41:06.12,0:41:10.22,EN,,0,0,0,,which maps this to that and this to that,\nDialogue: 0,0:41:10.24,0:41:12.08,EN,,0,0,0,,and sort of, stretches everything uniformly.\nDialogue: 0,0:41:12.17,0:41:18.25,EN,,0,0,0,,So we take a line segment like this\nDialogue: 0,0:41:19.73,0:41:24.20,EN,,0,0,0,,and end up mapping it to a line segment like that,\nDialogue: 0,0:41:26.20,0:41:32.68,EN,,0,0,0,,so some point (x,y) goes to some other point up there.\nDialogue: 0,0:41:32.68,0:41:39.37,EN,,0,0,0,,And although it's not important, with a little vector algebra, you could write that formula.\nDialogue: 0,0:41:39.37,0:41:43.18,EN,,0,0,0,,The thing that (x,y) goes to, the point that (x,y) goes to is\nDialogue: 0,0:41:43.58,0:41:50.74,EN,,0,0,0,,gotten by taking the origin of the rectangle and then adding that as a vector to--\nDialogue: 0,0:41:51.16,0:41:55.48,EN,,0,0,0,,well, take x, the x coordinate, which is something between zero and one,\nDialogue: 0,0:41:55.98,0:42:01.84,EN,,0,0,0,,multiply that by the horizontal vector of the rectangle;\nDialogue: 0,0:42:07.62,0:42:11.00,EN,,0,0,0,,and take the y coordinate, which is also something between zero and one\nDialogue: 0,0:42:11.38,0:42:16.28,EN,,0,0,0,,and multiply that by the vertical vector of the rectangle.\nDialogue: 0,0:42:16.74,0:42:19.31,EN,,0,0,0,,That's just a little linear algebra.\nDialogue: 0,0:42:19.31,0:42:23.48,EN,,0,0,0,,Anyway, that's the formula, which is the right obvious transformation\nDialogue: 0,0:42:23.69,0:42:28.18,EN,,0,0,0,,that takes things into the unit square, into the interior of that rectangle.\nDialogue: 0,0:42:31.34,0:42:34.02,EN,,0,0,0,,OK well, let's actually look at that as a procedure.\nDialogue: 0,0:42:35.16,0:42:36.29,EN,,0,0,0,,So what we want is\nDialogue: 0,0:42:37.80,0:42:40.82,EN,,0,0,0,,the thing which tells us that particular transformation\nDialogue: 0,0:42:41.01,0:42:42.52,EN,,0,0,0,,that a rectangle defines.\nDialogue: 0,0:42:43.80,0:42:45.22,EN,,0,0,0,,So here's the procedure.\nDialogue: 0,0:42:45.22,0:42:47.22,EN,,0,0,0,,I'll call it coordinate-map.\nDialogue: 0,0:42:47.77,0:42:52.00,EN,,0,0,0,,Coordinate-map is the thing that takes as its argument a rectangle\nDialogue: 0,0:42:53.60,0:42:57.85,EN,,0,0,0,,and returns for you a procedure on points.\nDialogue: 0,0:43:00.45,0:43:06.82,EN,,0,0,0,,Right, so for each rectangle you get a way of transforming a point (x,y) into that rectangle.\nDialogue: 0,0:43:06.82,0:43:08.02,EN,,0,0,0,,And how do you get it?\nDialogue: 0,0:43:08.02,0:43:10.92,EN,,0,0,0,,Well I just--  writing in Lisp what I wrote there on the blackboard--\nDialogue: 0,0:43:10.92,0:43:16.01,EN,,0,0,0,,I add to the origin of the rectangle\nDialogue: 0,0:43:20.22,0:43:25.02,EN,,0,0,0,,the result of adding-- I take the horizontal part of the rectangle;\nDialogue: 0,0:43:25.02,0:43:27.68,EN,,0,0,0,,I scale that by the x coordinate of the point.\nDialogue: 0,0:43:29.65,0:43:32.62,EN,,0,0,0,,I take the vertical vector of the rectangle.\nDialogue: 0,0:43:33.51,0:43:37.14,EN,,0,0,0,,I scale that by the y coordinate of the point,\nDialogue: 0,0:43:37.14,0:43:39.14,EN,,0,0,0,,and then add all those three things up.\nDialogue: 0,0:43:40.13,0:43:41.34,EN,,0,0,0,,That's the procedure.\nDialogue: 0,0:43:41.34,0:43:44.54,EN,,0,0,0,,That is the procedure that I'm going to apply to a point.\nDialogue: 0,0:43:46.54,0:43:52.17,EN,,0,0,0,,And this whole thing is generated for each rectangle.\nDialogue: 0,0:43:52.17,0:43:57.25,EN,,0,0,0,,So any rectangle defines a Coordinate-MAP, which is a procedure on points.\nDialogue: 0,0:44:06.66,0:44:10.42,EN,,0,0,0,,All right, so for example, George here,\nDialogue: 0,0:44:11.36,0:44:16.34,EN,,0,0,0,,my original George, might have been something that I specified by segments in the unit square,\nDialogue: 0,0:44:19.50,0:44:21.96,EN,,0,0,0,,and then for each rectangle I give this thing,\nDialogue: 0,0:44:24.14,0:44:28.17,EN,,0,0,0,,I'm going to draw those segments inside that rectangle.\nDialogue: 0,0:44:28.17,0:44:29.88,EN,,0,0,0,,How actually do I do that?\nDialogue: 0,0:44:30.68,0:44:36.94,EN,,0,0,0,,Well I take each segment in my original reference George that was specified,\nDialogue: 0,0:44:38.64,0:44:40.58,EN,,0,0,0,,and to each of the end points of those segments,\nDialogue: 0,0:44:40.88,0:44:44.45,EN,,0,0,0,,I applied the COORDINATE-MAP of the particular rectangle I want to draw it in.\nDialogue: 0,0:44:44.45,0:44:46.06,EN,,0,0,0,,So for example, this lower rectangle,\nDialogue: 0,0:44:46.66,0:44:50.88,EN,,0,0,0,,this George as a fat kid rectangle, has its COORDINATE-MAP.\nDialogue: 0,0:44:51.25,0:44:53.69,EN,,0,0,0,,And if I want to draw this image,\nDialogue: 0,0:44:55.38,0:44:57.92,EN,,0,0,0,,And if I want to draw this image, what I do is for each segment here, say for this segment,\nDialogue: 0,0:44:59.29,0:45:05.34,EN,,0,0,0,,I transformed that point by the coordinate MAP, transform that point by the coordinate MAP.\nDialogue: 0,0:45:05.34,0:45:07.09,EN,,0,0,0,,That will give me this point and that point\nDialogue: 0,0:45:07.38,0:45:08.94,EN,,0,0,0,,and draw the segment between them.\nDialogue: 0,0:45:09.71,0:45:11.52,EN,,0,0,0,,Right, that's the idea.\nDialogue: 0,0:45:12.66,0:45:14.78,EN,,0,0,0,,Right, and if I give it a different rectangle like this one,\nDialogue: 0,0:45:14.80,0:45:15.76,EN,,0,0,0,,that's a different coordinate-MAP,\nDialogue: 0,0:45:15.79,0:45:17.84,EN,,0,0,0,,so I get a different image of those line segments.\nDialogue: 0,0:45:19.28,0:45:22.14,EN,,0,0,0,,Well how do we actually get a picture to start with?\nDialogue: 0,0:45:22.14,0:45:26.52,EN,,0,0,0,,I can build a picture to start with out of a List of line segments initially.\nDialogue: 0,0:45:27.61,0:45:32.20,EN,,0,0,0,,Here's a procedure that builds what I'll call a primitive picture,\nDialogue: 0,0:45:33.48,0:45:37.17,EN,,0,0,0,,meaning one I, sort of, got that didn't come out of Beside or Rotate or something.\nDialogue: 0,0:45:37.52,0:45:39.60,EN,,0,0,0,,It starts with a List of line segments,\nDialogue: 0,0:45:42.94,0:45:44.04,EN,,0,0,0,,And now it does what I said.\nDialogue: 0,0:45:44.04,0:45:45.58,EN,,0,0,0,,What's a picture have to be?\nDialogue: 0,0:45:45.58,0:45:49.44,EN,,0,0,0,,First of all it's a procedure that's defined on rectangles.\nDialogue: 0,0:45:51.70,0:45:53.00,EN,,0,0,0,,What does it do?\nDialogue: 0,0:45:53.00,0:45:56.56,EN,,0,0,0,,It says for each-- this is going to be a List of line segments--\nDialogue: 0,0:45:57.66,0:46:03.38,EN,,0,0,0,,for each segment, for each s, which is a segment in this List of segments,\nDialogue: 0,0:46:05.89,0:46:07.30,EN,,0,0,0,,well it draws a line.\nDialogue: 0,0:46:07.30,0:46:08.82,EN,,0,0,0,,What line does it draw?\nDialogue: 0,0:46:10.60,0:46:12.84,EN,,0,0,0,,It gets the start point of that segment,\nDialogue: 0,0:46:15.22,0:46:17.94,EN,,0,0,0,,transforms that by the coordinate MAP of the rectangle.\nDialogue: 0,0:46:19.54,0:46:21.76,EN,,0,0,0,,That's the first new point it wants to do.\nDialogue: 0,0:46:21.76,0:46:26.32,EN,,0,0,0,,Then it takes the endpoint of the segment, transforms that by the coordinate MAP of the rectangle,\nDialogue: 0,0:46:26.69,0:46:27.92,EN,,0,0,0,,and then draws a line between.\nDialogue: 0,0:46:27.92,0:46:30.84,EN,,0,0,0,,Let's assume drawline is some primitive that's built into the system\nDialogue: 0,0:46:31.09,0:46:33.22,EN,,0,0,0,,that actually draws a line on the display.\nDialogue: 0,0:46:33.96,0:46:37.10,EN,,0,0,0,,All right, so it transforms the endpoints by the coordinate MAP of the rectangle,\nDialogue: 0,0:46:37.13,0:46:38.20,EN,,0,0,0,,draws a line between them,\nDialogue: 0,0:46:39.61,0:46:44.12,EN,,0,0,0,,does that for each s in this List of segments.\nDialogue: 0,0:46:45.96,0:46:51.40,EN,,0,0,0,,And now remember again, a picture is a procedure that takes a rectangle as argument.\nDialogue: 0,0:46:51.40,0:46:55.65,EN,,0,0,0,,So when you hand it a rectangle, this is what it does: draws those lines.\nDialogue: 0,0:46:57.17,0:47:01.10,EN,,0,0,0,,All right, so there's-- how would I actually use this thing?\nDialogue: 0,0:47:01.22,0:47:04.08,EN,,0,0,0,,Let's make it a little bit more concrete.\nDialogue: 0,0:47:05.60,0:47:24.22,EN,,0,0,0,,Right, I would say for instance, define R to be make-rectangle of some stuff,\nDialogue: 0,0:47:24.50,0:47:28.66,EN,,0,0,0,,and I'd have to specify some vectors here using make-vector.\nDialogue: 0,0:47:29.84,0:47:46.18,EN,,0,0,0,,And then I could say, define say, G to be make-picture, and then some stuff.\nDialogue: 0,0:47:46.68,0:47:55.28,EN,,0,0,0,,And what I'd have to specify here is a List of line segments, right, using make segment.\nDialogue: 0,0:47:55.28,0:47:58.70,EN,,0,0,0,,Make-segment might be made out of vectors, and vectors might be made out of points.\nDialogue: 0,0:47:59.50,0:48:04.60,EN,,0,0,0,,And then if I actually wanted to see the image of G inside a rectangle,\nDialogue: 0,0:48:04.65,0:48:11.72,EN,,0,0,0,,well a picture is a procedure that takes a rectangle as argument.\nDialogue: 0,0:48:12.06,0:48:16.37,EN,,0,0,0,,So if I then called G with an input of R,\nDialogue: 0,0:48:17.96,0:48:23.25,EN,,0,0,0,,that would cause whatever image G is worrying about to be drawn inside the rectangle R.\nDialogue: 0,0:48:23.62,0:48:25.62,EN,,0,0,0,,Right, so that's how you'd use that.\nDialogue: 0,0:48:26.86,0:48:36.29,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:48:36.29,0:48:39.78,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:48:39.82,0:48:43.54,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:48:51.28,0:48:55.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:48:55.50,0:48:58.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:48:59.34,0:49:03.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}Henderson Escher Example\nDialogue: 0,0:49:07.72,0:49:12.48,EN,,0,0,0,,PROFESSOR: Well why is it that I say this example is nice?\nDialogue: 0,0:49:12.48,0:49:13.74,EN,,0,0,0,,You probably don't think it's nice.\nDialogue: 0,0:49:13.74,0:49:15.42,EN,,0,0,0,,You probably think it's more weird than nice.\nDialogue: 0,0:49:15.42,0:49:20.92,EN,,0,0,0,,Right, representing these pictures as procedures, which do complicated things with rectangles.\nDialogue: 0,0:49:20.92,0:49:22.72,EN,,0,0,0,,So why is it nice?\nDialogue: 0,0:49:25.36,0:49:26.69,EN,,0,0,0,,The reason it's nice\nDialogue: 0,0:49:27.22,0:49:30.40,EN,,0,0,0,,is that once you've implemented the primitives in this way,\nDialogue: 0,0:49:30.97,0:49:35.20,EN,,0,0,0,,the means of combination just fall out by implementing procedures.\nDialogue: 0,0:49:35.98,0:49:37.48,EN,,0,0,0,,Let me show you what I mean.\nDialogue: 0,0:49:37.48,0:49:39.02,EN,,0,0,0,,Suppose we want to implement Beside.\nDialogue: 0,0:49:41.56,0:49:47.36,EN,,0,0,0,,So I'd like to--  suppose I've got a picture. Let's call it P1.\nDialogue: 0,0:49:47.36,0:49:50.62,EN,,0,0,0,,P1 is going to be-- and now remember what a picture really is.\nDialogue: 0,0:49:50.62,0:49:54.82,EN,,0,0,0,,It's a thing that if you hand it some rectangle,\nDialogue: 0,0:49:56.52,0:50:01.46,EN,,0,0,0,,it will cause an image to be drawn in whatever rectangle you hand it.\nDialogue: 0,0:50:03.46,0:50:09.26,EN,,0,0,0,,And suppose P2 two is some other picture, and you hand that a rectangle.\nDialogue: 0,0:50:09.74,0:50:12.44,EN,,0,0,0,,And whatever rectangle you hand it, it draws some picture.\nDialogue: 0,0:50:14.84,0:50:26.60,EN,,0,0,0,,And now if I'd like to implement Beside of P1 and P2 with a scale factor A,\nDialogue: 0,0:50:27.04,0:50:28.38,EN,,0,0,0,,well what does that have to be?\nDialogue: 0,0:50:28.38,0:50:29.34,EN,,0,0,0,,That's gotta be a picture.\nDialogue: 0,0:50:29.92,0:50:33.88,EN,,0,0,0,,It's gotta be a thing that you handed a rectangle and draw something in that rectangle.\nDialogue: 0,0:50:34.77,0:50:37.18,EN,,0,0,0,,So if hand Beside this rectangle--\nDialogue: 0,0:50:38.58,0:50:40.12,EN,,0,0,0,,let's hand it a rectangle.\nDialogue: 0,0:50:41.50,0:50:42.74,EN,,0,0,0,,Well what's it going to do?\nDialogue: 0,0:50:42.76,0:50:46.36,EN,,0,0,0,,It's going to take this rectangle and split it into two\nDialogue: 0,0:50:49.29,0:50:51.57,EN,,0,0,0,,at a ratio of A and one minus A.\nDialogue: 0,0:50:52.65,0:50:55.12,EN,,0,0,0,,And it will say, oh sure, now I've got two rectangles.\nDialogue: 0,0:51:02.34,0:51:06.54,EN,,0,0,0,,And now it goes off to P1 and says P1, well draw yourself in this rectangle,\nDialogue: 0,0:51:07.36,0:51:11.64,EN,,0,0,0,,and goes off to P2, and says, P2, fine, draw yourself in this rectangle.\nDialogue: 0,0:51:13.28,0:51:16.88,EN,,0,0,0,,The only computation it has to do is figure out what these rectangles are.\nDialogue: 0,0:51:17.36,0:51:23.97,EN,,0,0,0,,Remember a rectangle is specified by an origin and a horizontal vector and a vertical vector.\nDialogue: 0,0:51:23.98,0:51:25.94,EN,,0,0,0,,so it's got to figure out what these things are.\nDialogue: 0,0:51:27.37,0:51:32.29,EN,,0,0,0,,So for this first rectangle, the origin turns out to be the origin of the original rectangle,\nDialogue: 0,0:51:33.64,0:51:37.80,EN,,0,0,0,,and the vertical vector is the same as the vertical vector of the original rectangle.\nDialogue: 0,0:51:38.89,0:51:46.60,EN,,0,0,0,,The horizontal vector is the horizontal vector of the original rectangle scaled by A.\nDialogue: 0,0:51:47.49,0:51:48.90,EN,,0,0,0,,And that's the first rectangle.\nDialogue: 0,0:51:49.46,0:51:52.69,EN,,0,0,0,,The second rectangle, the origin\nDialogue: 0,0:51:54.06,0:51:59.65,EN,,0,0,0,,The second rectangle, the origin is the original origin plus that horizontal vector scaled by A.\nDialogue: 0,0:52:01.20,0:52:03.40,EN,,0,0,0,,The horizontal vector of the second rectangle is\nDialogue: 0,0:52:03.77,0:52:06.04,EN,,0,0,0,,the rest of the horizontal vector of the first one,\nDialogue: 0,0:52:06.34,0:52:11.66,EN,,0,0,0,,which is 1 minus A times the original H,\nDialogue: 0,0:52:12.05,0:52:13.77,EN,,0,0,0,,and the vertical vector is still v.\nDialogue: 0,0:52:15.48,0:52:17.98,EN,,0,0,0,,But basically it goes and constructs these two rectangles,\nDialogue: 0,0:52:18.00,0:52:20.57,EN,,0,0,0,,and the important point is having constructed the rectangles,\nDialogue: 0,0:52:20.93,0:52:24.58,EN,,0,0,0,,it says OK, p1, you draw yourself in there, and p2, you draw yourself in there,\nDialogue: 0,0:52:24.62,0:52:26.18,EN,,0,0,0,,and that's all Beside has to do.\nDialogue: 0,0:52:27.80,0:52:29.30,EN,,0,0,0,,All right, let's look at that piece of code.\nDialogue: 0,0:52:34.33,0:52:35.13,EN,,0,0,0,,Beside\nDialogue: 0,0:52:39.64,0:52:46.44,EN,,0,0,0,,Beside of a picture and another picture with some scaling ratio\nDialogue: 0,0:52:47.84,0:52:53.64,EN,,0,0,0,,is first of all, since it's a picture, a procedure that's going to take a rectangle as argument.\nDialogue: 0,0:52:55.49,0:52:56.56,EN,,0,0,0,,What's it going to do?\nDialogue: 0,0:52:56.76,0:53:02.32,EN,,0,0,0,,It says, p1 draw yourself in some rectangle and p2 draw yourself in some other rectangle.\nDialogue: 0,0:53:03.21,0:53:04.46,EN,,0,0,0,,And now what are those rectangles?\nDialogue: 0,0:53:04.46,0:53:05.48,EN,,0,0,0,,Well here's the computation.\nDialogue: 0,0:53:05.48,0:53:06.54,EN,,0,0,0,,It makes a rectangle,\nDialogue: 0,0:53:07.52,0:53:10.40,EN,,0,0,0,,and this is the algebra I just did on the board: the origin, something;\nDialogue: 0,0:53:10.40,0:53:11.84,EN,,0,0,0,,the horizontal vector, something;\nDialogue: 0,0:53:11.84,0:53:13.44,EN,,0,0,0,,and the vertical vector, something.\nDialogue: 0,0:53:13.97,0:53:14.81,EN,,0,0,0,,For p2\nDialogue: 0,0:53:15.50,0:53:19.78,EN,,0,0,0,,And for p2, the rectangle it wants has some other origin and horizontal vector and vertical vector.\nDialogue: 0,0:53:19.78,0:53:20.70,EN,,0,0,0,,But the important point\nDialogue: 0,0:53:21.21,0:53:27.18,EN,,0,0,0,,is that all it's saying is, p1, go do your thing in one rectangle, and p2, go do your thing in another rectangle.\nDialogue: 0,0:53:27.74,0:53:29.42,EN,,0,0,0,,That's all the Beside has to do.\nDialogue: 0,0:53:30.84,0:53:35.62,EN,,0,0,0,,OK, similarly Rotate--\nDialogue: 0,0:53:36.96,0:53:42.00,EN,,0,0,0,,see if I have this picture A,\nDialogue: 0,0:53:42.97,0:53:46.12,EN,,0,0,0,,and I want to look at say rotating A by 90 degrees,\nDialogue: 0,0:53:46.37,0:53:51.92,EN,,0,0,0,,what that should mean is, well take this rectangle,\nDialogue: 0,0:53:53.94,0:53:58.44,EN,,0,0,0,,which is origin and horizontal vector and vertical vector,\nDialogue: 0,0:53:58.78,0:54:03.18,EN,,0,0,0,,and now pretend that it's really the rectangle that looks like this,\nDialogue: 0,0:54:03.74,0:54:09.12,EN,,0,0,0,,which has an origin and a horizontal vector up here, and a vertical vector there,\nDialogue: 0,0:54:09.60,0:54:12.46,EN,,0,0,0,,and now draw yourself with respect to that rectangle.\nDialogue: 0,0:54:13.26,0:54:15.04,EN,,0,0,0,,Let me show you that as a procedure.\nDialogue: 0,0:54:17.02,0:54:19.85,EN,,0,0,0,,All right, so we'll Rotate 90 of the picture,\nDialogue: 0,0:54:20.61,0:54:22.96,EN,,0,0,0,,because again, a procedure for rectangle,\nDialogue: 0,0:54:23.25,0:54:26.12,EN,,0,0,0,,which says, OK picture, draw yourself in some rectangle;\nDialogue: 0,0:54:27.21,0:54:30.66,EN,,0,0,0,,and then this algebra is the transformation on the rectangle.\nDialogue: 0,0:54:30.66,0:54:33.84,EN,,0,0,0,,It's the one which makes it look like the rectangle is sideways,\nDialogue: 0,0:54:33.86,0:54:36.52,EN,,0,0,0,,the origin is someplace else and the vertical vector is someplace else,\nDialogue: 0,0:54:37.13,0:54:39.74,EN,,0,0,0,,and the horizontal vector is someplace else, and vertical vector is someplace else.\nDialogue: 0,0:54:46.76,0:54:49.90,EN,,0,0,0,,OK, again notice, the crucial thing that's going on here\nDialogue: 0,0:54:50.53,0:55:00.97,EN,,0,0,0,,is you're using the representation of pictures as procedures to automatically get the closure property,\nDialogue: 0,0:55:01.74,0:55:05.22,EN,,0,0,0,,because what happens is, Beside just has this thing p1.\nDialogue: 0,0:55:05.22,0:55:09.40,EN,,0,0,0,,Beside doesn't care if that's a primitive picture or it's line segments\nDialogue: 0,0:55:09.61,0:55:12.69,EN,,0,0,0,,if p1 is, itself, the result of doing Aboves or Besides or Rotates.\nDialogue: 0,0:55:12.72,0:55:16.08,EN,,0,0,0,,All Beside has to know about, say, p1\nDialogue: 0,0:55:16.29,0:55:19.73,EN,,0,0,0,,p1 is that if you hand p1 a rectangle, it will cause something to be drawn.\nDialogue: 0,0:55:21.04,0:55:25.98,EN,,0,0,0,,And above that level, Beside just doesn't-- it's none of its business how p1 accomplishes that drawing.\nDialogue: 0,0:55:27.73,0:55:32.25,EN,,0,0,0,,All right, so you're using the procedural representation to ensure this closure.\nDialogue: 0,0:55:35.64,0:55:40.81,EN,,0,0,0,,So implementing pictures as procedures makes these means of combination,\nDialogue: 0,0:55:41.18,0:55:43.93,EN,,0,0,0,,both pretty simple and also, I think, elegant.\nDialogue: 0,0:55:45.92,0:55:48.22,EN,,0,0,0,,But that's not the real punchline.\nDialogue: 0,0:55:49.28,0:55:53.52,EN,,0,0,0,,The real punchline comes when you look at the means of abstraction in this language.\nDialogue: 0,0:55:54.70,0:55:56.24,EN,,0,0,0,,Because what have we done?\nDialogue: 0,0:55:56.24,0:56:03.72,EN,,0,0,0,,We've implemented the means of combination themselves as procedures.\nDialogue: 0,0:56:05.85,0:56:09.38,EN,,0,0,0,,And what that means is that when we go to abstract in this language,\nDialogue: 0,0:56:10.17,0:56:15.69,EN,,0,0,0,,everything that Lisp supplies us for manipulating procedures\nDialogue: 0,0:56:16.33,0:56:21.45,EN,,0,0,0,,automatically available to do things in this picture language.\nDialogue: 0,0:56:21.92,0:56:29.74,EN,,0,0,0,,The technical term I want to say is not only is this language implemented in Lisp, obviously it is,\nDialogue: 0,0:56:29.76,0:56:32.58,EN,,0,0,0,,but the language is nicely embedded in Lisp.\nDialogue: 0,0:56:37.64,0:56:42.08,EN,,0,0,0,,What I mean is by embedding the language in this way,\nDialogue: 0,0:56:42.90,0:56:48.86,EN,,0,0,0,,all the power of Lisp is automatically available as an extension to whatever you want to do.\nDialogue: 0,0:56:50.06,0:56:51.68,EN,,0,0,0,,And what do I mean by that?\nDialogue: 0,0:56:51.97,0:57:02.94,EN,,0,0,0,,Example: say, suppose I want to make a thing that takes four pictures A, B, C and D,\nDialogue: 0,0:57:03.76,0:57:07.06,EN,,0,0,0,,and makes a configuration that looks like this.\nDialogue: 0,0:57:12.50,0:57:16.96,EN,,0,0,0,,Well you might call that, you know, four pictures or something, four-pict configuration.\nDialogue: 0,0:57:16.96,0:57:17.70,EN,,0,0,0,,How do I do that?\nDialogue: 0,0:57:17.70,0:57:18.68,EN,,0,0,0,,Well I can obviously do that.\nDialogue: 0,0:57:18.68,0:57:23.33,EN,,0,0,0,,I just write a procedure that takes B above D\nDialogue: 0,0:57:24.13,0:57:25.85,EN,,0,0,0,,and A above C\nDialogue: 0,0:57:26.09,0:57:27.70,EN,,0,0,0,,and puts those things beside each other.\nDialogue: 0,0:57:28.24,0:57:31.82,EN,,0,0,0,,So I automatically have Lisp's ability to do procedure composition.\nDialogue: 0,0:57:32.92,0:57:35.82,EN,,0,0,0,,And I didn't have to make that specifically in the picture language.\nDialogue: 0,0:57:35.82,0:57:39.92,EN,,0,0,0,,It's automatic from the fact that the means of combination are themselves procedures.\nDialogue: 0,0:57:40.96,0:57:44.18,EN,,0,0,0,,Or suppose I wanted to do something a little bit more complicated.\nDialogue: 0,0:57:44.18,0:57:46.50,EN,,0,0,0,,I wanted to put in a parameter so that for each of these,\nDialogue: 0,0:57:46.52,0:57:50.08,EN,,0,0,0,,I could independently specify a rotation by 90 degrees.\nDialogue: 0,0:57:50.41,0:57:52.64,EN,,0,0,0,,That's just putting a parameter in the procedure.\nDialogue: 0,0:57:53.17,0:57:54.56,EN,,0,0,0,,It's automatically there.\nDialogue: 0,0:57:54.80,0:57:57.84,EN,,0,0,0,,Right, it automatically comes from the embedding.\nDialogue: 0,0:57:58.16,0:58:05.36,EN,,0,0,0,,Or even more, suppose I wanted to, you know, use recursion.\nDialogue: 0,0:58:06.16,0:58:10.78,EN,,0,0,0,,Let's look at a recursive means of combination on pictures.\nDialogue: 0,0:58:10.78,0:58:14.64,EN,,0,0,0,,I could say define-- let's see if you can figure out what this one is--\nDialogue: 0,0:58:14.69,0:58:18.97,EN,,0,0,0,,suppose I say define what it means to right-push a picture,\nDialogue: 0,0:58:22.84,0:58:29.80,EN,,0,0,0,,right-push a picture and some integer N and some scale factor A.\nDialogue: 0,0:58:31.46,0:58:41.22,EN,,0,0,0,,I'll define this to say if N equals 0, then the answer is the picture.\nDialogue: 0,0:58:42.20,0:58:54.02,EN,,0,0,0,,Otherwise I'm going to put-- oops, name change: P.\nDialogue: 0,0:58:55.88,0:59:00.21,EN,,0,0,0,,Otherwise, I'm going to take P and put it beside\nDialogue: 0,0:59:00.92,0:59:18.30,EN,,0,0,0,,the results of recursively right-pushing P with N minus 1 and A and use a scale factor of A. OK,\nDialogue: 0,0:59:24.72,0:59:31.12,EN,,0,0,0,,so if N 0 , it's P. Otherwise I put P with a scale factor of A--\nDialogue: 0,0:59:31.12,0:59:32.80,EN,,0,0,0,,I'm sorry I didn't align this right--\nDialogue: 0,0:59:33.66,0:59:38.50,EN,,0,0,0,,recursively beside the result of right-pushing P, N minus 1 times with a scale factor of A.\nDialogue: 0,0:59:38.50,0:59:42.00,EN,,0,0,0,,There's a recursive means of combination.\nDialogue: 0,0:59:43.78,0:59:44.76,EN,,0,0,0,,What's that look like?\nDialogue: 0,0:59:44.76,0:59:45.90,EN,,0,0,0,,Well, here's what it looks like.\nDialogue: 0,0:59:46.04,0:59:56.04,EN,,0,0,0,,There's George right-pushed against himself twice with a scale factor of 0.75.\nDialogue: 0,0:59:59.26,1:00:00.72,EN,,0,0,0,,Where'd that come from?\nDialogue: 0,1:00:00.72,1:00:02.34,EN,,0,0,0,,How did I get all this fancy recursion?\nDialogue: 0,1:00:02.34,1:00:05.24,EN,,0,0,0,,And the answer is just automatic, absolutely automatic.\nDialogue: 0,1:00:05.24,1:00:09.80,EN,,0,0,0,,Since these are procedures, the embedding says, well sure, I can define recursive procedures.\nDialogue: 0,1:00:10.36,1:00:11.68,EN,,0,0,0,,I didn't have to arrange that.\nDialogue: 0,1:00:13.56,1:00:16.42,EN,,0,0,0,,And of course, we can do more complicated things of the same sort.\nDialogue: 0,1:00:16.42,1:00:18.21,EN,,0,0,0,,I could make something that does an up-push.\nDialogue: 0,1:00:18.42,1:00:22.60,EN,,0,0,0,,Right, that sort of goes like this, by recursively putting something above.\nDialogue: 0,1:00:22.60,1:00:26.54,EN,,0,0,0,,Or I could make something that, sort of, was this scheme.\nDialogue: 0,1:00:26.56,1:00:28.85,EN,,0,0,0,,I might start out with a picture\nDialogue: 0,1:00:29.78,1:00:37.16,EN,,0,0,0,,and then, sort of, recursively both push it aside and above\nDialogue: 0,1:00:37.57,1:00:38.92,EN,,0,0,0,,and that might put something there.\nDialogue: 0,1:00:39.52,1:00:41.82,EN,,0,0,0,,And then up here I put the same recursive thing,\nDialogue: 0,1:00:42.36,1:00:44.20,EN,,0,0,0,,and I might end up with something like this.\nDialogue: 0,1:00:45.40,1:00:52.50,EN,,0,0,0,,Right, so there's a procedure that's a little bit more complicated than right-push but not much.\nDialogue: 0,1:00:53.64,1:00:58.14,EN,,0,0,0,,I just do an Above and a Beside, rather than just a Beside.\nDialogue: 0,1:01:01.12,1:01:06.78,EN,,0,0,0,,Now if I take that and apply that with the idea of putting four pictures together,\nDialogue: 0,1:01:07.53,1:01:08.65,EN,,0,0,0,,which I can surely do;\nDialogue: 0,1:01:09.01,1:01:14.17,EN,,0,0,0,,and I go and I apply that to Q, which we defined before, right,\nDialogue: 0,1:01:15.97,1:01:18.73,EN,,0,0,0,,what I end up with this is this thing,\nDialogue: 0,1:01:20.14,1:01:25.26,EN,,0,0,0,,which is, sort of, the square limit of Q, done twice.\nDialogue: 0,1:01:28.18,1:01:32.25,EN,,0,0,0,,Right, and then we can compare that with Escher's \"Square Limit.\"\nDialogue: 0,1:01:32.88,1:01:34.53,EN,,0,0,0,,And you see, it's sort of the same idea.\nDialogue: 0,1:01:34.74,1:01:36.94,EN,,0,0,0,,Escher's is, of course, much, much prettier.\nDialogue: 0,1:01:36.94,1:01:44.04,EN,,0,0,0,,If we go back and look at George, right, if we go look at George here--\nDialogue: 0,1:01:44.38,1:01:47.37,EN,,0,0,0,,see, I started with a fairly arbitrary design\nDialogue: 0,1:01:47.42,1:01:49.26,EN,,0,0,0,,this picture of George and did things with it.\nDialogue: 0,1:01:51.22,1:01:53.14,EN,,0,0,0,,Right, whereas if we go look at the Escher picture, right,\nDialogue: 0,1:01:54.08,1:01:56.14,EN,,0,0,0,,the Escher picture is not an arbitrary design.\nDialogue: 0,1:01:56.14,1:01:57.66,EN,,0,0,0,,It's this very, very clever thing,\nDialogue: 0,1:01:57.89,1:02:00.20,EN,,0,0,0,,so that when you take this fish body\nDialogue: 0,1:02:01.82,1:02:04.97,EN,,0,0,0,,and Rotate it and shrink it down, it bleeds into the next one really nicely.\nDialogue: 0,1:02:07.40,1:02:11.48,EN,,0,0,0,,And of course with George, I didn't really do anything like that.\nDialogue: 0,1:02:12.12,1:02:13.90,EN,,0,0,0,,So if we look at George,\nDialogue: 0,1:02:15.41,1:02:18.64,EN,,0,0,0,,right, there's a little bit of match up, but not very nice, and it's pretty arbitrary.\nDialogue: 0,1:02:18.64,1:02:21.53,EN,,0,0,0,,One very nice project, by the way,\nDialogue: 0,1:02:22.30,1:02:27.54,EN,,0,0,0,,would be to write a procedure that could take some basic figure like this George thing\nDialogue: 0,1:02:27.86,1:02:29.62,EN,,0,0,0,,and start moving the ends of the lines around,\nDialogue: 0,1:02:29.86,1:02:31.20,EN,,0,0,0,,so you got a really nice one\nDialogue: 0,1:02:32.13,1:02:34.06,EN,,0,0,0,,when you went and did that \"Square Limit\" process.\nDialogue: 0,1:02:34.68,1:02:36.30,EN,,0,0,0,,That'd be a really nice thing to think about.\nDialogue: 0,1:02:38.08,1:02:39.72,EN,,0,0,0,,Well so, we can combine things.\nDialogue: 0,1:02:39.72,1:02:41.04,EN,,0,0,0,,We can recursive procedures.\nDialogue: 0,1:02:41.04,1:02:43.48,EN,,0,0,0,,We can do all kinds of things, and that's all automatic.\nDialogue: 0,1:02:44.60,1:02:48.52,EN,,0,0,0,,Right, the important point, the difference between merely implementing something in a language\nDialogue: 0,1:02:48.69,1:02:50.44,EN,,0,0,0,,and embedding something in the language,\nDialogue: 0,1:02:50.44,1:02:53.72,EN,,0,0,0,,so that you don't lose the original power of the language, and what Lisp is great at,\nDialogue: 0,1:02:54.76,1:02:57.62,EN,,0,0,0,,see Lisp is a lousy language for doing any particular problem.\nDialogue: 0,1:02:57.62,1:03:02.10,EN,,0,0,0,,What it's good for is figuring out the right language that you want and embedding that in Lisp.\nDialogue: 0,1:03:02.10,1:03:05.44,EN,,0,0,0,,That's the real power of this approach to design.\nDialogue: 0,1:03:05.69,1:03:06.82,EN,,0,0,0,,Of course, we can go further.\nDialogue: 0,1:03:06.82,1:03:08.81,EN,,0,0,0,,See, you saw the other thing that we can do in Lisp\nDialogue: 0,1:03:09.21,1:03:17.52,EN,,0,0,0,,is capture general methods of doing things as higher order procedures.\nDialogue: 0,1:03:19.09,1:03:22.57,EN,,0,0,0,,And you probably just from me drawing it got the idea that right-push\nDialogue: 0,1:03:23.78,1:03:26.61,EN,,0,0,0,,and the analogous thing where you push something up and up and up and up\nDialogue: 0,1:03:26.93,1:03:33.82,EN,,0,0,0,,and this corner push thing are all generalizations of a common kind of idea.\nDialogue: 0,1:03:34.72,1:03:37.20,EN,,0,0,0,,So just to illustrate and give you practice in looking at a\nDialogue: 0,1:03:37.98,1:03:40.65,EN,,0,0,0,,at a fairly convoluted use of higher order procedures,\nDialogue: 0,1:03:41.12,1:03:47.24,EN,,0,0,0,,let me show you the general idea of pushing some means of combination to recursively repeat it.\nDialogue: 0,1:03:48.30,1:03:50.70,EN,,0,0,0,,So here's a good one to puzzle out.\nDialogue: 0,1:03:51.22,1:04:00.70,EN,,0,0,0,,We'll define it what it means to push using a means of combination.\nDialogue: 0,1:04:01.49,1:04:04.88,EN,,0,0,0,,Comb is going to be something like the Beside or Above.\nDialogue: 0,1:04:06.18,1:04:07.06,EN,,0,0,0,,Well what's that going to be.\nDialogue: 0,1:04:07.06,1:04:12.06,EN,,0,0,0,,That's going to be a procedure, remember what Beside actually was, right.\nDialogue: 0,1:04:13.22,1:04:15.18,EN,,0,0,0,,It took a picture,\nDialogue: 0,1:04:15.96,1:04:18.08,EN,,0,0,0,,took two pictures and a scale factor.\nDialogue: 0,1:04:18.62,1:04:24.28,EN,,0,0,0,,Using that I produced something that took a level number and a picture and a scale factor,\nDialogue: 0,1:04:24.28,1:04:25.45,EN,,0,0,0,,that I called right-push.\nDialogue: 0,1:04:26.16,1:04:33.66,EN,,0,0,0,,So this is going to be something that takes a picture, a level number and a scale factor, and it's going to say--\nDialogue: 0,1:04:36.16,1:04:39.12,EN,,0,0,0,,I'm going to do some repeated operation.\nDialogue: 0,1:04:39.45,1:04:46.62,EN,,0,0,0,,I'm going to repeatedly apply the procedure which takes a picture\nDialogue: 0,1:04:48.40,1:04:50.69,EN,,0,0,0,,and applies the means of combination\nDialogue: 0,1:04:51.20,1:04:59.08,EN,,0,0,0,,to the picture and the original picture and the one I took in here and the scale factor,\nDialogue: 0,1:05:02.26,1:05:07.28,EN,,0,0,0,,and I do the thing which repeats this procedure N times,\nDialogue: 0,1:05:12.04,1:05:16.20,EN,,0,0,0,,and I apply that whole thing to my original picture.\nDialogue: 0,1:05:19.56,1:05:24.48,EN,,0,0,0,,Repeated here, in case you haven't seen it, is another higher order procedure\nDialogue: 0,1:05:24.53,1:05:28.34,EN,,0,0,0,,that takes a procedure and a number\nDialogue: 0,1:05:29.54,1:05:34.29,EN,,0,0,0,,and returns for you another procedure that applies this procedure N times.\nDialogue: 0,1:05:36.04,1:05:39.30,EN,,0,0,0,,And I think some of you have already written repeated as an exercise,\nDialogue: 0,1:05:39.70,1:05:43.01,EN,,0,0,0,,but if you haven't, it's a very good exercise in thinking about higher order procedures.\nDialogue: 0,1:05:43.84,1:05:46.90,EN,,0,0,0,,But in any case, the result of this repeated is what I apply to picture.\nDialogue: 0,1:05:49.46,1:05:52.38,EN,,0,0,0,,And having done that, that's going to capture the --\nDialogue: 0,1:05:53.12,1:05:57.73,EN,,0,0,0,,that is the thing, the way I got from the idea of Beside to the idea of right-push\nDialogue: 0,1:05:59.01,1:06:13.17,EN,,0,0,0,,So having done that, I could say define right-push to be push of Beside.\nDialogue: 0,1:06:17.65,1:06:20.32,EN,,0,0,0,,Or if I say, define up-push to be push of Above\nDialogue: 0,1:06:20.34,1:06:25.48,EN,,0,0,0,,I'd get the analogous thing or define corner-push to be push of some appropriate thing that did both the Beside and Above,\nDialogue: 0,1:06:25.49,1:06:26.70,EN,,0,0,0,,or I could push anything.\nDialogue: 0,1:06:28.26,1:06:34.76,EN,,0,0,0,,Anyway this is, if you're having trouble with lambdas, this is an excellent exercise in figuring out what this means.\nDialogue: 0,1:06:38.98,1:06:41.00,EN,,0,0,0,,OK, well there's a lot to learn from this example.\nDialogue: 0,1:06:42.18,1:06:49.80,EN,,0,0,0,,The main point I've been welling on is the notion of nicely embedding a language inside another language.\nDialogue: 0,1:06:50.66,1:06:55.62,EN,,0,0,0,,Right, so that all the power of this language like Lisp of the surrounding language\nDialogue: 0,1:06:55.92,1:07:00.28,EN,,0,0,0,,is still accessible to you and appears as a natural extension of the language that you built.\nDialogue: 0,1:07:00.98,1:07:04.00,EN,,0,0,0,,That's one thing that this example shows very well.\nDialogue: 0,1:07:08.14,1:07:10.94,EN,,0,0,0,,Another thing is, if you go back and think about that,\nDialogue: 0,1:07:10.94,1:07:12.28,EN,,0,0,0,,what's procedures and what's data.\nDialogue: 0,1:07:12.28,1:07:16.20,EN,,0,0,0,,You know, by the time we get up to here, my God, what's going on.\nDialogue: 0,1:07:16.20,1:07:19.66,EN,,0,0,0,,I mean, this is some procedure, and it takes a picture and an argument,\nDialogue: 0,1:07:19.66,1:07:20.36,EN,,0,0,0,,and what's a picture.\nDialogue: 0,1:07:20.36,1:07:23.82,EN,,0,0,0,,Well, a picture itself, as you remember, was a procedure, and that took a rectangle.\nDialogue: 0,1:07:23.82,1:07:25.82,EN,,0,0,0,,And a rectangle is some abstraction.\nDialogue: 0,1:07:26.09,1:07:28.13,EN,,0,0,0,,And I hope now that by now you're completely lost\nDialogue: 0,1:07:29.14,1:07:33.74,EN,,0,0,0,,as to the question of what in the system is procedure and what's data.\nDialogue: 0,1:07:33.74,1:07:34.78,EN,,0,0,0,,You see, there isn't any difference.\nDialogue: 0,1:07:35.49,1:07:36.44,EN,,0,0,0,,There really isn't.\nDialogue: 0,1:07:37.93,1:07:41.42,EN,,0,0,0,,And you might think of a picture sometimes as a procedure and sometimes as data,\nDialogue: 0,1:07:41.84,1:07:44.90,EN,,0,0,0,,but that's just, sort of, you know, making you feel comfortable.\nDialogue: 0,1:07:44.90,1:07:47.30,EN,,0,0,0,,It's really both in some sense or neither in some sense.\nDialogue: 0,1:07:49.92,1:08:02.20,EN,,0,0,0,,OK, there's a more general point about the structure of the system as creating a language,\nDialogue: 0,1:08:02.52,1:08:06.74,EN,,0,0,0,,viewing the engineering design process as one of creating language or\nDialogue: 0,1:08:07.84,1:08:13.97,EN,,0,0,0,,or rather one of creating a sort of sequence of layers of language.\nDialogue: 0,1:08:14.77,1:08:20.01,EN,,0,0,0,,You see, there's this methodology, or maybe I should say mythology,\nDialogue: 0,1:08:20.74,1:08:24.90,EN,,0,0,0,,that's, sort of, charitably called software, quote, engineering.\nDialogue: 0,1:08:25.21,1:08:28.04,EN,,0,0,0,,All right, and what does it say, it's says well, you go and you figure out your task,\nDialogue: 0,1:08:28.04,1:08:30.04,EN,,0,0,0,,and you figure out exactly what you want to do.\nDialogue: 0,1:08:30.40,1:08:32.20,EN,,0,0,0,,And once you figure out exactly what you want to do,\nDialogue: 0,1:08:32.22,1:08:34.54,EN,,0,0,0,,you find out that it breaks out into three sub-tasks,\nDialogue: 0,1:08:34.54,1:08:35.76,EN,,0,0,0,,and you go and you start working on--\nDialogue: 0,1:08:35.97,1:08:38.94,EN,,0,0,0,,and you work on this sub-task, and you figure out exactly what that is.\nDialogue: 0,1:08:38.94,1:08:43.04,EN,,0,0,0,,And you find out that that breaks down into three sub-tasks, and you specify them completely,\nDialogue: 0,1:08:43.04,1:08:47.32,EN,,0,0,0,,and you go and you work on those two, and you work on this sub-one, and you specify that exactly.\nDialogue: 0,1:08:47.32,1:08:51.10,EN,,0,0,0,,And then finally when you're done, you come back way up here, and you work on your second sub-task,\nDialogue: 0,1:08:51.10,1:08:53.40,EN,,0,0,0,,and specify that out and work it out.\nDialogue: 0,1:08:53.40,1:08:57.64,EN,,0,0,0,,And then you end up with-- you end up at the end with this beautiful edifice.\nDialogue: 0,1:08:57.64,1:09:00.25,EN,,0,0,0,,Right, you end up with a marvelous tree,\nDialogue: 0,1:09:00.89,1:09:08.24,EN,,0,0,0,,that where you've broken your task into sub-tasks and broken each of these into sub-tasks and broken those into sub-tasks, right.\nDialogue: 0,1:09:09.88,1:09:15.02,EN,,0,0,0,,And each of these nodes is exactly and precisely defined\nDialogue: 0,1:09:15.26,1:09:18.66,EN,,0,0,0,,to do the wonderful, beautiful task to make it fit into the whole edifice\nDialogue: 0,1:09:18.96,1:09:21.14,EN,,0,0,0,,Right, that's this mythology.\nDialogue: 0,1:09:21.14,1:09:25.92,EN,,0,0,0,,See only a computer scientist could possibly believe that you build a complex system like that\nDialogue: 0,1:09:27.48,1:09:32.80,EN,,0,0,0,,Right. Contrast that with this Henderson example.\nDialogue: 0,1:09:32.80,1:09:34.30,EN,,0,0,0,,It didn't work like that.\nDialogue: 0,1:09:35.26,1:09:39.33,EN,,0,0,0,,What happened was that there was a sequence of layers of language.\nDialogue: 0,1:09:41.06,1:09:42.05,EN,,0,0,0,,What happened?\nDialogue: 0,1:09:42.18,1:09:48.76,EN,,0,0,0,,There was a layer of a thing that allowed us to build primitive pictures.\nDialogue: 0,1:09:51.69,1:09:56.24,EN,,0,0,0,,There's primitive pictures and that was a language.\nDialogue: 0,1:09:56.32,1:09:57.84,EN,,0,0,0,,I didn't say much about it.\nDialogue: 0,1:09:58.22,1:09:59.58,EN,,0,0,0,,We talked about how to construct George,\nDialogue: 0,1:09:59.61,1:10:04.88,EN,,0,0,0,,but that was a language where you talked about vectors and line segments and points and where they sat in the unit square.\nDialogue: 0,1:10:06.42,1:10:11.29,EN,,0,0,0,,And then on top of that, right, on top of that--\nDialogue: 0,1:10:11.97,1:10:14.10,EN,,0,0,0,,so this is the language of primitive pictures.\nDialogue: 0,1:10:17.08,1:10:20.36,EN,,0,0,0,,Right, talking about line segments in particular pictures in the unit square.\nDialogue: 0,1:10:21.40,1:10:23.80,EN,,0,0,0,,On top of that was a whole language.\nDialogue: 0,1:10:24.05,1:10:30.86,EN,,0,0,0,,There was a language of geometric combinators,\nDialogue: 0,1:10:32.66,1:10:36.62,EN,,0,0,0,,a language of geometric positions,\nDialogue: 0,1:10:38.77,1:10:46.50,EN,,0,0,0,,which talks about things like Above and Beside and right-push and Rotate.\nDialogue: 0,1:10:48.04,1:10:55.70,EN,,0,0,0,,And those things, sort of, happened with reference to the things that are talked about in this language.\nDialogue: 0,1:10:58.57,1:11:00.93,EN,,0,0,0,,And then if we like, we saw that above that\nDialogue: 0,1:11:02.61,1:11:15.10,EN,,0,0,0,,there was sort of a language of schemes of combination.\nDialogue: 0,1:11:21.25,1:11:22.44,EN,,0,0,0,,For example, push,\nDialogue: 0,1:11:24.45,1:11:27.88,EN,,0,0,0,,which talked about repeatedly doing something over with a scale factor.\nDialogue: 0,1:11:28.38,1:11:31.28,EN,,0,0,0,,And the things that were being discussed in that language\nDialogue: 0,1:11:31.50,1:11:34.34,EN,,0,0,0,,were, sort of, the things that happened down here.\nDialogue: 0,1:11:36.30,1:11:42.76,EN,,0,0,0,,So what you have is, at each level, the objects that are being talked about\nDialogue: 0,1:11:44.68,1:11:47.00,EN,,0,0,0,,are the things that were erected the previous level.\nDialogue: 0,1:11:48.08,1:11:52.06,EN,,0,0,0,,What's the difference between this thing and this thing?\nDialogue: 0,1:11:53.34,1:11:54.18,EN,,0,0,0,,The answer is\nDialogue: 0,1:11:56.14,1:12:01.73,EN,,0,0,0,,that over here in the tree, each node, and in fact, each decomposition down here,\nDialogue: 0,1:12:02.14,1:12:05.25,EN,,0,0,0,,is being designed to do a specific task,\nDialogue: 0,1:12:07.50,1:12:08.88,EN,,0,0,0,,whereas in the other scheme,\nDialogue: 0,1:12:09.21,1:12:14.80,EN,,0,0,0,,what you have is a full range of linguistic power at each level.\nDialogue: 0,1:12:16.00,1:12:18.08,EN,,0,0,0,,See what's happening there, at any level,\nDialogue: 0,1:12:20.24,1:12:22.72,EN,,0,0,0,,it's not being set up to do a particular task.\nDialogue: 0,1:12:23.14,1:12:26.17,EN,,0,0,0,,It's being set up to talk about a whole range of things.\nDialogue: 0,1:12:27.62,1:12:30.78,EN,,0,0,0,,The consequence of that for design\nDialogue: 0,1:12:31.14,1:12:35.58,EN,,0,0,0,,is that something that's designed in that method is likely to be more robust,\nDialogue: 0,1:12:36.61,1:12:38.20,EN,,0,0,0,,where by robust, I mean\nDialogue: 0,1:12:38.44,1:12:41.24,EN,,0,0,0,,that if you go and make some change in your description,\nDialogue: 0,1:12:42.70,1:12:48.04,EN,,0,0,0,,it's more likely to be captured by a corresponding change,\nDialogue: 0,1:12:49.22,1:12:52.60,EN,,0,0,0,,in the way that the language is implemented at the next level up,\nDialogue: 0,1:12:54.29,1:12:56.58,EN,,0,0,0,,right, because you've made these levels full.\nDialogue: 0,1:12:56.62,1:12:59.66,EN,,0,0,0,,So you're not talking about a particular thing like Beside.\nDialogue: 0,1:12:59.94,1:13:03.78,EN,,0,0,0,,You've given yourself a whole vocabulary to express things of that sort,\nDialogue: 0,1:13:04.77,1:13:07.02,EN,,0,0,0,,so if you go and change your specifications a little bit,\nDialogue: 0,1:13:07.02,1:13:11.38,EN,,0,0,0,,it's more likely that your methodology will able to adapt to capture that change,\nDialogue: 0,1:13:12.69,1:13:15.02,EN,,0,0,0,,whereas a design like this is not going to be robust,\nDialogue: 0,1:13:15.02,1:13:17.08,EN,,0,0,0,,because if I go and change something that's in here,\nDialogue: 0,1:13:17.53,1:13:21.69,EN,,0,0,0,,that might affect the entire way that I decomposed everything down, further down the tree.\nDialogue: 0,1:13:23.20,1:13:29.74,EN,,0,0,0,,Right, so very big difference in outlook in decomposition, levels of language rather than, sort of, a strict hierarchy.\nDialogue: 0,1:13:30.52,1:13:33.02,EN,,0,0,0,,Not only that, but when you have levels of language\nDialogue: 0,1:13:33.50,1:13:35.92,EN,,0,0,0,,you've given yourself a different vocabularies\nDialogue: 0,1:13:36.45,1:13:38.74,EN,,0,0,0,,for talking about the design at different levels.\nDialogue: 0,1:13:38.74,1:13:40.92,EN,,0,0,0,,So if we go back and look at George one last time,\nDialogue: 0,1:13:41.90,1:13:44.08,EN,,0,0,0,,if I wanted to change this picture George,\nDialogue: 0,1:13:45.85,1:13:48.68,EN,,0,0,0,,see suddenly I have a whole different ways of describing the change.\nDialogue: 0,1:13:48.68,1:13:56.08,EN,,0,0,0,,Like for example, I may want to go to the basic primitive design and move the endpoint of some vector.\nDialogue: 0,1:13:57.76,1:14:00.76,EN,,0,0,0,,That's a change that I would discuss at the lowest level.\nDialogue: 0,1:14:01.00,1:14:02.50,EN,,0,0,0,,I would say the endpoint is somewhere else.\nDialogue: 0,1:14:03.34,1:14:07.98,EN,,0,0,0,,Or I might come up and say, well the next thing I wanted to do, this little replicated element,\nDialogue: 0,1:14:09.10,1:14:10.94,EN,,0,0,0,,I might want to do by something else.\nDialogue: 0,1:14:10.94,1:14:13.84,EN,,0,0,0,,I might want to put a scale factor in that Beside.\nDialogue: 0,1:14:13.84,1:14:19.34,EN,,0,0,0,,That's a change that I would discuss at the next level of design, the level of combinators.\nDialogue: 0,1:14:19.34,1:14:25.05,EN,,0,0,0,,Or I might want to say, I might want to change the basic way that I took this pattern\nDialogue: 0,1:14:26.49,1:14:30.48,EN,,0,0,0,,and made some recursive decomposition, maybe not bleeding out toward the corners or something else.\nDialogue: 0,1:14:31.16,1:14:34.18,EN,,0,0,0,,That would be a change that I would discuss at the highest level.\nDialogue: 0,1:14:34.18,1:14:36.37,EN,,0,0,0,,And because I've structured the system to be this way,\nDialogue: 0,1:14:36.52,1:14:39.62,EN,,0,0,0,,I have all these vocabularies for talking about change in different ways\nDialogue: 0,1:14:39.65,1:14:42.48,EN,,0,0,0,,and a lot of flexibility to decide which one's appropriate.\nDialogue: 0,1:14:44.74,1:14:51.05,EN,,0,0,0,,OK, well that's sort of a big point about the difference in software methodology that comes out from Lisp,\nDialogue: 0,1:14:51.25,1:14:55.45,EN,,0,0,0,,and it all comes again, out of the notion that really, the design process\nDialogue: 0,1:14:56.12,1:14:59.62,EN,,0,0,0,,is not so much implementing programs as implementing languages.\nDialogue: 0,1:14:59.62,1:15:01.09,EN,,0,0,0,,And that's really the power of Lisp.\nDialogue: 0,1:15:02.21,1:15:03.61,EN,,0,0,0,,OK, thank you. Let's take a break.\nDialogue: 0,1:15:05.69,1:15:23.37,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:15:05.69,1:15:23.37,Declare,,0,0,0,,{\\an2\\fad(500,500)}Project Repo\\Nhttps://github.com/DeathKing/Learning-SICP\nDialogue: 0,1:15:23.37,1:15:25.37,Default,,0,0,0,,\n"
  },
  {
    "path": "Ass/lec3b.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nLast Style Storage: Default\nScroll Position: 1174\nActive Line: 1179\nVideo Zoom Percent: 0.625\nAudio URI: G:\\untitled\\ref\\lec3b_480_muxed2.mp4\nVideo File: G:\\untitled\\ref\\lec3b_480_muxed2.mp4\nVideo Aspect Ratio: c1.33333\nVideo Position: 78794\nPlayResX: 640\nPlayResY: 480\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:19.10,0:00:23.41,EN,,0,0,0,,PROFESSOR: Well, Hal just told us how you build robust systems.\nDialogue: 0,0:00:23.80,0:00:26.17,EN,,0,0,0,,The key idea was--\nDialogue: 0,0:00:26.81,0:00:30.20,EN,,0,0,0,,I'm sure that many of you don't really assimilate that yet--\nDialogue: 0,0:00:30.20,0:00:33.77,EN,,0,0,0,,but the key idea is that in order to make a system that's robust,\nDialogue: 0,0:00:33.93,0:00:36.48,EN,,0,0,0,,it has to be insensitive to small changes,\nDialogue: 0,0:00:36.60,0:00:37.37,EN,,0,0,0,,that is,\nDialogue: 0,0:00:37.37,0:00:40.90,EN,,0,0,0,,a small change in the problem should lead to only a small change in the solution.\nDialogue: 0,0:00:41.32,0:00:42.90,EN,,0,0,0,,There ought to be a continuity.\nDialogue: 0,0:00:42.90,0:00:45.94,EN,,0,0,0,,The space of solutions ought to be continuous in this space of problems.\nDialogue: 0,0:00:46.25,0:00:48.76,EN,,0,0,0,,The way he was explaining how to do that\nDialogue: 0,0:00:49.46,0:00:54.78,EN,,0,0,0,,was instead of solving a particular problem at every level of decomposition of the problem at the subproblems,\nDialogue: 0,0:00:55.08,0:00:56.78,EN,,0,0,0,,where you solve the class of problems,\nDialogue: 0,0:00:56.78,0:01:00.40,EN,,0,0,0,,which are a neighborhood of the particular problem that you're trying to solve.\nDialogue: 0,0:01:01.40,0:01:04.76,EN,,0,0,0,,The way you do that is by producing a language at that level of detail\nDialogue: 0,0:01:04.76,0:01:10.33,EN,,0,0,0,,in which the solutions to that class of problems is representable in that language.\nDialogue: 0,0:01:11.37,0:01:15.09,EN,,0,0,0,,Therefore when you change makes more changes to the problem you're trying to solve,\nDialogue: 0,0:01:15.09,0:01:19.29,EN,,0,0,0,,you generally have to make only small local changes to the solution you've constructed,\nDialogue: 0,0:01:19.29,0:01:22.26,EN,,0,0,0,,because at the level of detail you're working,\nDialogue: 0,0:01:22.26,0:01:24.26,EN,,0,0,0,,there's a language where you can express\nDialogue: 0,0:01:24.80,0:01:28.14,EN,,0,0,0,,the various solutions to alternate problems of the same type.\nDialogue: 0,0:01:30.04,0:01:33.74,EN,,0,0,0,,Well that's the beginning of a very important idea,\nDialogue: 0,0:01:34.40,0:01:38.61,EN,,0,0,0,,the most important perhaps idea that makes computer science more powerful\nDialogue: 0,0:01:38.61,0:01:42.37,EN,,0,0,0,,than most of the other kinds of engineering disciplines we know about.\nDialogue: 0,0:01:43.38,0:01:44.73,EN,,0,0,0,,What we've seen so far\nDialogue: 0,0:01:44.73,0:01:48.78,EN,,0,0,0,,is sort of how to use embedding of languages.\nDialogue: 0,0:01:49.26,0:01:53.36,EN,,0,0,0,,And, of course, the power of embedding languages partly comes from\nDialogue: 0,0:01:54.12,0:01:56.86,EN,,0,0,0,,procedures like this one that I showed you yesterday.\nDialogue: 0,0:01:57.37,0:02:02.13,EN,,0,0,0,,What you see here is the derivative program that we described yesterday.\nDialogue: 0,0:02:02.13,0:02:05.92,EN,,0,0,0,,It's a procedure that takes a procedure as an argument\nDialogue: 0,0:02:06.00,0:02:07.92,EN,,0,0,0,,and returns a procedure as a value.\nDialogue: 0,0:02:09.61,0:02:12.65,EN,,0,0,0,,And using such things is very nice.\nDialogue: 0,0:02:12.65,0:02:14.65,EN,,0,0,0,,You can make things like push combinators\nDialogue: 0,0:02:14.65,0:02:16.86,EN,,0,0,0,,and all that sort of wonderful thing that you saw last time.\nDialogue: 0,0:02:17.68,0:02:20.54,EN,,0,0,0,,However, now I'm going to really muddy the waters.\nDialogue: 0,0:02:21.56,0:02:25.90,EN,,0,0,0,,See this confuses the issue of what's the procedure and what is data,\nDialogue: 0,0:02:26.56,0:02:27.81,EN,,0,0,0,,but not very badly.\nDialogue: 0,0:02:28.42,0:02:30.90,EN,,0,0,0,,What we really want to do is confuse it very badly.\nDialogue: 0,0:02:31.18,0:02:32.44,EN,,0,0,0,,And the best way to do that\nDialogue: 0,0:02:32.44,0:02:37.62,EN,,0,0,0,,is to get involved with the manipulation of the algebraic expressions that the procedures themselves are expressed in.\nDialogue: 0,0:02:39.73,0:02:45.58,EN,,0,0,0,,So at this point, I want to talk about instead of things like on this slide,\nDialogue: 0,0:02:45.89,0:02:49.72,EN,,0,0,0,,the derivative procedure being a thing that manipulates a procedure--\nDialogue: 0,0:02:49.72,0:02:51.94,EN,,0,0,0,,this is a numerical method you see here.\nDialogue: 0,0:02:51.94,0:02:58.93,EN,,0,0,0,,And what you're seeing is a representation of the numerical approximationto the derivative.\nDialogue: 0,0:02:59.29,0:03:00.44,EN,,0,0,0,,That's what's here.\nDialogue: 0,0:03:00.86,0:03:04.93,EN,,0,0,0,,In fact what I'd like to talk about is instead things that look like this.\nDialogue: 0,0:03:06.05,0:03:11.33,EN,,0,0,0,,And what we have here are rules from a calculus book.\nDialogue: 0,0:03:12.09,0:03:16.17,EN,,0,0,0,,These are rules for finding the derivatives of the expressions\nDialogue: 0,0:03:16.70,0:03:20.58,EN,,0,0,0,,that one might write in some algebraic language.\nDialogue: 0,0:03:21.64,0:03:24.41,EN,,0,0,0,,It says things like a derivative of a constant is 0.\nDialogue: 0,0:03:25.13,0:03:29.09,EN,,0,0,0,,The derivative of the valuable with respect to which you are taking the derivative is 1.\nDialogue: 0,0:03:29.32,0:03:31.93,EN,,0,0,0,,The derivative of a constant times the function\nDialogue: 0,0:03:32.09,0:03:34.37,EN,,0,0,0,,is the constant times the derivative of the function,\nDialogue: 0,0:03:34.77,0:03:36.04,EN,,0,0,0,,and things like that.\nDialogue: 0,0:03:38.05,0:03:41.38,EN,,0,0,0,,These are exact expressions. These are not numerical approximations.\nDialogue: 0,0:03:42.96,0:03:44.52,EN,,0,0,0,,Can we make programs?\nDialogue: 0,0:03:44.52,0:03:52.24,EN,,0,0,0,,And, in fact, it's very easy to make programs that manipulate these expressions.\nDialogue: 0,0:03:56.38,0:03:59.52,EN,,0,0,0,,Well let's see. Let's look at these rules in some detail.\nDialogue: 0,0:04:01.08,0:04:05.22,EN,,0,0,0,,You all have seen these rules in your elementary calculus class at one time or another.\nDialogue: 0,0:04:05.98,0:04:12.12,EN,,0,0,0,,And you know from calculus that it's easy to produce derivatives of arbitrary expressions.\nDialogue: 0,0:04:12.53,0:04:16.05,EN,,0,0,0,,You also know from your elementary calculus that it's hard to produce integrals.\nDialogue: 0,0:04:16.98,0:04:19.37,EN,,0,0,0,,Yet integrals and derivatives are opposites of each other.\nDialogue: 0,0:04:19.52,0:04:21.28,EN,,0,0,0,,They're inverse operations.\nDialogue: 0,0:04:21.61,0:04:23.30,EN,,0,0,0,,And they have the same rules.\nDialogue: 0,0:04:24.16,0:04:29.68,EN,,0,0,0,,What is special about these rules that makes it possible for one\nDialogue: 0,0:04:29.68,0:04:33.65,EN,,0,0,0,,to produce derivatives easily and integrals why it's so hard?\nDialogue: 0,0:04:34.85,0:04:36.98,EN,,0,0,0,,Let's think about that very simply.\nDialogue: 0,0:04:37.40,0:04:38.38,EN,,0,0,0,,Look at these rules.\nDialogue: 0,0:04:39.36,0:04:43.06,EN,,0,0,0,,Every one of these rules, when used in the direction for taking derivatives,\nDialogue: 0,0:04:43.06,0:04:44.80,EN,,0,0,0,,which is in the direction of this arrow,\nDialogue: 0,0:04:46.68,0:04:49.16,EN,,0,0,0,,the left side is matched against your expression,\nDialogue: 0,0:04:49.16,0:04:53.05,EN,,0,0,0,,and the right side is the thing which is the derivative of that expression.\nDialogue: 0,0:04:54.02,0:04:55.65,EN,,0,0,0,,The arrow is going that way.\nDialogue: 0,0:04:57.37,0:05:00.45,EN,,0,0,0,,In each of these rules,\nDialogue: 0,0:05:01.24,0:05:03.72,EN,,0,0,0,,the expressions on the right-hand side of the rule\nDialogue: 0,0:05:03.72,0:05:06.56,EN,,0,0,0,,that are contained within derivatives are subexpressions,\nDialogue: 0,0:05:06.56,0:05:10.29,EN,,0,0,0,,are proper subexpressions, of the expression on the left-hand side.\nDialogue: 0,0:05:10.60,0:05:13.25,EN,,0,0,0,,So here we see the derivative of the sum,\nDialogue: 0,0:05:13.92,0:05:16.13,EN,,0,0,0,,witch is the expression on the left-hand side\nDialogue: 0,0:05:16.13,0:05:18.38,EN,,0,0,0,,is the sum of the derivatives of the pieces.\nDialogue: 0,0:05:20.08,0:05:24.49,EN,,0,0,0,,So the rule of moving to the right are reduction rules.\nDialogue: 0,0:05:25.02,0:05:26.61,EN,,0,0,0,,The problem becomes easier.\nDialogue: 0,0:05:27.56,0:05:31.48,EN,,0,0,0,,I make, I turn a big complicated problem it's lots of smaller problems\nDialogue: 0,0:05:32.44,0:05:35.76,EN,,0,0,0,,and then combine the results, a perfect place for recursion to work.\nDialogue: 0,0:05:36.58,0:05:40.85,EN,,0,0,0,,If I'm going in the other direction like this,\nDialogue: 0,0:05:41.81,0:05:45.13,EN,,0,0,0,,if I'm trying to produce integrals, well there are several problems you see here.\nDialogue: 0,0:05:45.24,0:05:49.09,EN,,0,0,0,,First of all, if I try to integrate an expression like a sum,\nDialogue: 0,0:05:49.21,0:05:50.81,EN,,0,0,0,,more than one rule matches.\nDialogue: 0,0:05:50.81,0:05:52.10,EN,,0,0,0,,Here's one that matches.\nDialogue: 0,0:05:52.48,0:05:53.65,EN,,0,0,0,,Here's one that matches.\nDialogue: 0,0:05:54.81,0:05:57.09,EN,,0,0,0,,I don't know which one to take. And they may be different.\nDialogue: 0,0:05:57.70,0:06:00.00,EN,,0,0,0,,I may get to explore different things.\nDialogue: 0,0:06:00.25,0:06:03.64,EN,,0,0,0,,Also, the expressions become larger in that direction.\nDialogue: 0,0:06:04.53,0:06:06.30,EN,,0,0,0,,And when the expressions become larger,\nDialogue: 0,0:06:06.30,0:06:10.56,EN,,0,0,0,,then there's no guarantee that any particular path I choose will terminate,\nDialogue: 0,0:06:10.94,0:06:13.46,EN,,0,0,0,,because we will only terminate by accidental cancellation.\nDialogue: 0,0:06:14.24,0:06:18.05,EN,,0,0,0,,So that's why integrals are complicated searches and hard to do.\nDialogue: 0,0:06:19.12,0:06:20.96,EN,,0,0,0,,Right now I don't want to do anything as hard as that.\nDialogue: 0,0:06:21.49,0:06:23.06,EN,,0,0,0,,Let's work on derivatives for a while.\nDialogue: 0,0:06:24.14,0:06:28.13,EN,,0,0,0,,Well, these rules are ones you know for the most part hopefully.\nDialogue: 0,0:06:28.78,0:06:31.88,EN,,0,0,0,,So let's see if we can write a program which is these rules.\nDialogue: 0,0:06:32.22,0:06:33.72,EN,,0,0,0,,And that should be very easy.\nDialogue: 0,0:06:34.89,0:06:36.21,EN,,0,0,0,,Just write the program.\nDialogue: 0,0:06:36.69,0:06:39.29,EN,,0,0,0,,See, because while I showed you is that it's a reduction rule,\nDialogue: 0,0:06:39.29,0:06:41.29,EN,,0,0,0,,it's something appropriate for a recursion.\nDialogue: 0,0:06:43.08,0:06:45.72,EN,,0,0,0,,And, of course, what we have for each of these rules is we have a case\nDialogue: 0,0:06:46.66,0:06:47.78,EN,,0,0,0,,in some case analysis.\nDialogue: 0,0:06:48.58,0:06:50.36,EN,,0,0,0,,So I'm just going to write this program down.\nDialogue: 0,0:06:52.88,0:06:57.69,EN,,0,0,0,,Now, of course, I'm going to be saying something you have to believe. Right?\nDialogue: 0,0:06:57.69,0:07:00.33,EN,,0,0,0,,What you have to believe is I can represent these algebraic expressions,\nDialogue: 0,0:07:00.68,0:07:03.88,EN,,0,0,0,,that I can grab their parts, that I can put them together.\nDialogue: 0,0:07:04.24,0:07:06.49,EN,,0,0,0,,We've invented list structures so that you can do that.\nDialogue: 0,0:07:07.52,0:07:09.14,EN,,0,0,0,,But you don't want to worry about that now.\nDialogue: 0,0:07:09.66,0:07:12.45,EN,,0,0,0,,Right now I'm going to write the program that encapsulates these rules\nDialogue: 0,0:07:12.76,0:07:15.85,EN,,0,0,0,,independent of the representation of the algebraic expressions.\nDialogue: 0,0:07:20.42,0:07:28.84,EN,,0,0,0,,You have a derivative of an expression with respect to a variable.\nDialogue: 0,0:07:30.50,0:07:33.08,EN,,0,0,0,,This is a different thing than the derivative of the function.\nDialogue: 0,0:07:34.82,0:07:38.61,EN,,0,0,0,,That's what we saw last time, that numerical approximation.\nDialogue: 0,0:07:39.00,0:07:40.82,EN,,0,0,0,,It's something you can't open up a function.\nDialogue: 0,0:07:40.82,0:07:41.89,EN,,0,0,0,,It's just the answers.\nDialogue: 0,0:07:43.09,0:07:45.18,EN,,0,0,0,,The derivative of an expression is the way it's written.\nDialogue: 0,0:07:45.74,0:07:47.85,EN,,0,0,0,,And therefore it's a syntactic phenomenon.\nDialogue: 0,0:07:48.29,0:07:51.62,EN,,0,0,0,,And so a lot of what we're going to be doing today is worrying about syntax,\nDialogue: 0,0:07:52.33,0:07:54.12,EN,,0,0,0,,syntax of expressions and things like that.\nDialogue: 0,0:07:54.70,0:07:55.93,EN,,0,0,0,,Well, there's a case analysis.\nDialogue: 0,0:07:57.50,0:08:01.08,EN,,0,0,0,,Anytime we do anything complicated thereby a recursion,\nDialogue: 0,0:08:01.08,0:08:02.64,EN,,0,0,0,,we presumably need a case analysis.\nDialogue: 0,0:08:03.62,0:08:05.16,EN,,0,0,0,,It's the essential way to begin.\nDialogue: 0,0:08:05.16,0:08:07.40,EN,,0,0,0,,And that's usually a conditional of some large kind.\nDialogue: 0,0:08:08.08,0:08:09.97,EN,,0,0,0,,Well, what are their possibilities?\nDialogue: 0,0:08:09.97,0:08:12.53,EN,,0,0,0,,the first rule that you saw is this something a constant?\nDialogue: 0,0:08:16.50,0:08:17.50,EN,,0,0,0,,And what I'm asking is,\nDialogue: 0,0:08:17.50,0:08:22.22,EN,,0,0,0,,is the expression a constant with respect to the variable given?\nDialogue: 0,0:08:24.90,0:08:27.08,EN,,0,0,0,,If so, the result is 0,\nDialogue: 0,0:08:27.50,0:08:30.10,EN,,0,0,0,,because the derivative represents the rate of change of something.\nDialogue: 0,0:08:31.76,0:08:32.65,EN,,0,0,0,,If, however,\nDialogue: 0,0:08:32.89,0:08:40.69,EN,,0,0,0,,the expression that I'm taking the derivative of is the variable I'm varying,\nDialogue: 0,0:08:41.72,0:08:50.42,EN,,0,0,0,,then this is the same variable, the expression var,\nDialogue: 0,0:08:51.14,0:08:54.52,EN,,0,0,0,,then the rate of change of the expression with respect to the variable is 1.\nDialogue: 0,0:08:55.50,0:08:56.54,EN,,0,0,0,,It's the same 1.\nDialogue: 0,0:08:58.90,0:09:00.77,EN,,0,0,0,,Well now there are a couple of other possibilities.\nDialogue: 0,0:09:01.33,0:09:03.14,EN,,0,0,0,,It could, for example, be a sum.\nDialogue: 0,0:09:03.86,0:09:05.88,EN,,0,0,0,,Well, I don't know how I'm going to express sums yet.\nDialogue: 0,0:09:06.09,0:09:08.25,EN,,0,0,0,,Actually I do. But I haven't told you yet.\nDialogue: 0,0:09:10.34,0:09:11.78,EN,,0,0,0,,But is it a sum?\nDialogue: 0,0:09:12.48,0:09:14.48,EN,,0,0,0,,I'm imagining that there's some way of telling.\nDialogue: 0,0:09:15.30,0:09:19.44,EN,,0,0,0,,I'm doing a dispatch on the type of the expression here,\nDialogue: 0,0:09:20.77,0:09:23.57,EN,,0,0,0,,absolutely essential in building languages.\nDialogue: 0,0:09:24.72,0:09:26.37,EN,,0,0,0,,Cause languages are made out of different expressions.\nDialogue: 0,0:09:26.48,0:09:27.54,EN,,0,0,0,,And soon we're going to see that\nDialogue: 0,0:09:27.84,0:09:31.02,EN,,0,0,0,,in our more powerful methods of building languages on languages.\nDialogue: 0,0:09:32.53,0:09:34.02,EN,,0,0,0,,Is an expression a sum?\nDialogue: 0,0:09:35.45,0:09:38.82,EN,,0,0,0,,If it's a sum, well, we know the rule for derivative of the sum\nDialogue: 0,0:09:38.82,0:09:41.33,EN,,0,0,0,,is the sum of the derivatives of the parts.\nDialogue: 0,0:09:42.13,0:09:44.32,EN,,0,0,0,,One of them is called the addend and the other is the augend.\nDialogue: 0,0:09:44.32,0:09:46.80,EN,,0,0,0,,But I don't have enough space on the blackboard to such long names.\nDialogue: 0,0:09:46.80,0:09:48.40,EN,,0,0,0,,So I'll call them A1 and A2.\nDialogue: 0,0:09:49.04,0:09:50.37,EN,,0,0,0,,I want to make a sum.\nDialogue: 0,0:09:53.53,0:09:55.68,EN,,0,0,0,,Do you remember which is the sub for head or the menu end?\nDialogue: 0,0:09:57.14,0:10:01.09,EN,,0,0,0,,Or was it the dividend and the divisor or something like that?\nDialogue: 0,0:10:01.65,0:10:08.48,EN,,0,0,0,,Make sum of the derivative of the A1, I'll call it.\nDialogue: 0,0:10:08.48,0:10:13.29,EN,,0,0,0,,It's the addend of the expression with respect to the variable,\nDialogue: 0,0:10:14.84,0:10:22.76,EN,,0,0,0,,and the derivative of the A2 of the expression,\nDialogue: 0,0:10:24.12,0:10:28.25,EN,,0,0,0,,those the two arguments, the addition. Respect to the variable.\nDialogue: 0,0:10:32.36,0:10:34.93,EN,,0,0,0,,And another rule that we know is product rule,\nDialogue: 0,0:10:35.20,0:10:37.44,EN,,0,0,0,,which is, if the expression is a product.\nDialogue: 0,0:10:43.21,0:10:46.10,EN,,0,0,0,,By the way, it's a good idea when you're defining things,\nDialogue: 0,0:10:46.96,0:10:48.32,EN,,0,0,0,,when you're defining predicates,\nDialogue: 0,0:10:48.85,0:10:50.96,EN,,0,0,0,,to give them a name that ends in a question mark.\nDialogue: 0,0:10:51.08,0:10:52.89,EN,,0,0,0,,This question mark doesn't mean anything.\nDialogue: 0,0:10:53.10,0:10:54.50,EN,,0,0,0,,It's for us as an agreement.\nDialogue: 0,0:10:54.61,0:10:58.94,EN,,0,0,0,,It's a conventional interface between humans so you can read my programs more easily.\nDialogue: 0,0:11:00.05,0:11:01.96,EN,,0,0,0,,So I want you to, when you write programs,\nDialogue: 0,0:11:01.96,0:11:03.73,EN,,0,0,0,,if you define a predicate procedure,\nDialogue: 0,0:11:04.01,0:11:05.77,EN,,0,0,0,,that's something that returns true of false,\nDialogue: 0,0:11:05.94,0:11:07.84,EN,,0,0,0,,it should have a name which ends in question mark.\nDialogue: 0,0:11:08.02,0:11:10.34,EN,,0,0,0,,The lisp doesn't care. I care.\nDialogue: 0,0:11:11.62,0:11:13.14,EN,,0,0,0,,I want to make a sum.\nDialogue: 0,0:11:13.14,0:11:17.49,EN,,0,0,0,,Because the product, the derivative of a product is the sum\nDialogue: 0,0:11:17.94,0:11:19.64,EN,,0,0,0,,of the first times the derivative of the second plus\nDialogue: 0,0:11:19.66,0:11:20.70,EN,,0,0,0,,the second times the derivative of the first.\nDialogue: 0,0:11:23.54,0:11:27.06,EN,,0,0,0,,Make a sum of two things,\nDialogue: 0,0:11:29.64,0:11:38.33,EN,,0,0,0,,a product of, well, I'm going to say the M1 of the expression,\nDialogue: 0,0:11:39.85,0:11:48.97,EN,,0,0,0,,and the derivative of the M2 of the expression with respect to the variable,\nDialogue: 0,0:11:51.90,0:12:06.28,EN,,0,0,0,,and the product of the derivative of M1,\nDialogue: 0,0:12:07.10,0:12:11.92,EN,,0,0,0,,the multiplier of the expression, with respect to the variable.\nDialogue: 0,0:12:13.32,0:12:18.05,EN,,0,0,0,,And the product of that and the multiplicand, M2, of the expression.\nDialogue: 0,0:12:20.64,0:12:24.89,EN,,0,0,0,,Make that product. Make the sum. Close that case.\nDialogue: 0,0:12:24.96,0:12:28.02,EN,,0,0,0,,And, of course, I could add as many cases as I like here\nDialogue: 0,0:12:28.32,0:12:30.82,EN,,0,0,0,,for a complete set of rules you might find in a calculus book.\nDialogue: 0,0:12:34.80,0:12:39.45,EN,,0,0,0,,So this is what it takes to encapsulate those rules.\nDialogue: 0,0:12:41.53,0:12:43.90,EN,,0,0,0,,And you see, you have to realize there's a lot of wishful thinking here.\nDialogue: 0,0:12:44.54,0:12:47.56,EN,,0,0,0,,I haven't told you anything about how I'm going to make these representations.\nDialogue: 0,0:12:48.46,0:12:51.92,EN,,0,0,0,,Now, once I've decided that this is my set of rules,\nDialogue: 0,0:12:52.52,0:12:55.20,EN,,0,0,0,,I think it's time to play with the representation.\nDialogue: 0,0:12:55.66,0:12:56.69,EN,,0,0,0,,Let's attack that.\nDialogue: 0,0:12:57.96,0:13:00.00,EN,,0,0,0,,Well, first of all, I'm going to play a pun.\nDialogue: 0,0:13:00.90,0:13:02.12,EN,,0,0,0,,It's an important pun.\nDialogue: 0,0:13:02.74,0:13:06.56,EN,,0,0,0,,It's a key to a sort of powerful idea.\nDialogue: 0,0:13:09.62,0:13:14.41,EN,,0,0,0,,If I want to represent sums, and products, and differences, and quotients, and things like that,\nDialogue: 0,0:13:15.22,0:13:18.62,EN,,0,0,0,,why not use the same language as I'm writing my program in?\nDialogue: 0,0:13:20.50,0:13:23.64,EN,,0,0,0,,I write my program it algebraic expressions that look like\nDialogue: 0,0:13:23.98,0:13:30.45,EN,,0,0,0,,the sum of the product on a and the product of x and x,\nDialogue: 0,0:13:32.60,0:13:33.80,EN,,0,0,0,,and things like that.\nDialogue: 0,0:13:34.28,0:13:38.50,EN,,0,0,0,,And the product of b and x and c, whatever,\nDialogue: 0,0:13:38.50,0:13:39.97,EN,,0,0,0,,make that a sum of the product.\nDialogue: 0,0:13:40.77,0:13:44.09,EN,,0,0,0,,Right now I don't want to have procedures with unknown numbers of arguments,\nDialogue: 0,0:13:44.93,0:13:48.46,EN,,0,0,0,,a product of b and x and c.\nDialogue: 0,0:13:51.42,0:13:52.44,EN,,0,0,0,,This is list structure.\nDialogue: 0,0:13:54.12,0:13:55.74,EN,,0,0,0,,And the reason why this is nice,\nDialogue: 0,0:13:55.90,0:13:58.33,EN,,0,0,0,,is because any one of these objects has a property.\nDialogue: 0,0:13:58.92,0:14:01.53,EN,,0,0,0,,I know where, know where the car is.\nDialogue: 0,0:14:01.96,0:14:03.21,EN,,0,0,0,,The car is the operator.\nDialogue: 0,0:14:03.92,0:14:06.38,EN,,0,0,0,,And the operands are the successive cdrs\nDialogue: 0,0:14:07.22,0:14:10.36,EN,,0,0,0,,the successive cars of the cdrs of the list that this is.\nDialogue: 0,0:14:12.48,0:14:13.88,EN,,0,0,0,,It makes it very convenient.\nDialogue: 0,0:14:14.01,0:14:16.40,EN,,0,0,0,,Ir have to parse it. It's been done for me.\nDialogue: 0,0:14:17.42,0:14:20.01,EN,,0,0,0,,I'm using the embedding in Lisp to advantage.\nDialogue: 0,0:14:22.66,0:14:23.77,EN,,0,0,0,,So, for example,\nDialogue: 0,0:14:25.08,0:14:33.97,EN,,0,0,0,,Let's start using list structure to write down the representation that I'm implicitly assuming here.\nDialogue: 0,0:14:35.25,0:14:38.34,EN,,0,0,0,,Well I have to define various things that are implied in this representation.\nDialogue: 0,0:14:38.54,0:14:40.90,EN,,0,0,0,,Like I have to find out how to do a constant,\nDialogue: 0,0:14:41.21,0:14:42.30,EN,,0,0,0,,how you do same variable.\nDialogue: 0,0:14:42.40,0:14:45.04,EN,,0,0,0,,Let's do those first. That's pretty easy enough.\nDialogue: 0,0:14:45.78,0:14:47.70,EN,,0,0,0,,Now I'm going to be introducing lots of primitives here,\nDialogue: 0,0:14:48.60,0:14:50.50,EN,,0,0,0,,because these are the primitives that come with list structure.\nDialogue: 0,0:14:51.98,0:14:53.46,EN,,0,0,0,,OK, you define a constant.\nDialogue: 0,0:15:02.25,0:15:04.29,EN,,0,0,0,,And what I mean by a constant,\nDialogue: 0,0:15:04.29,0:15:07.73,EN,,0,0,0,,an expression is constant with respect to a variable.\nDialogue: 0,0:15:09.05,0:15:11.60,EN,,0,0,0,,is that the expression is something simple.\nDialogue: 0,0:15:11.60,0:15:14.46,EN,,0,0,0,,I can't take it into pieces, and yet it isn't that variable.\nDialogue: 0,0:15:16.58,0:15:18.78,EN,,0,0,0,,I can't break it up, and yet it isn't that variable.\nDialogue: 0,0:15:18.90,0:15:25.12,EN,,0,0,0,,That does not mean that there may be other expressions that are more complicated that are constants.\nDialogue: 0,0:15:25.20,0:15:28.92,EN,,0,0,0,,It's just that I'm going to look at the primitive constants in this way.\nDialogue: 0,0:15:29.74,0:15:33.41,EN,,0,0,0,,So what this is, is it says that's it's the and.\nDialogue: 0,0:15:34.02,0:15:37.82,EN,,0,0,0,,I can combine predicate expressions which return true or false with and.\nDialogue: 0,0:15:38.62,0:15:46.82,EN,,0,0,0,,Something atomic, The expression is atomic, meaning it cannot be broken into parts.\nDialogue: 0,0:15:46.82,0:15:48.53,EN,,0,0,0,,It doesn't have a car and a cdr.\nDialogue: 0,0:15:49.45,0:15:50.21,EN,,0,0,0,,It's not a list.\nDialogue: 0,0:15:50.76,0:15:52.94,EN,,0,0,0,,And it's a special test built into the system.\nDialogue: 0,0:15:53.97,0:16:04.66,EN,,0,0,0,,And it's not identically equal to that variable.\nDialogue: 0,0:16:06.82,0:16:13.36,EN,,0,0,0,,I'm representing my variables by things that are symbols which cannot be broken into pieces,\nDialogue: 0,0:16:13.90,0:16:17.22,EN,,0,0,0,,things like x, and y, things like this.\nDialogue: 0,0:16:19.74,0:16:22.37,EN,,0,0,0,,Whereas, of course, something like this can be broken up into pieces.\nDialogue: 0,0:16:24.74,0:16:46.40,EN,,0,0,0,,And the same variable of an expression with respect to a variable is,\nDialogue: 0,0:16:46.40,0:16:48.40,EN,,0,0,0,,in fact, an atomic expression.\nDialogue: 0,0:16:48.77,0:16:59.61,EN,,0,0,0,,I want to have an atomic expression, which is identical.\nDialogue: 0,0:17:07.90,0:17:11.68,EN,,0,0,0,,I don't want to look inside this, this stuff anymore.\nDialogue: 0,0:17:12.52,0:17:15.56,EN,,0,0,0,,These are primitive maybe.\nDialogue: 0,0:17:15.77,0:17:17.08,EN,,0,0,0,,But it doesn't matter.\nDialogue: 0,0:17:17.78,0:17:21.74,EN,,0,0,0,,I'm defining... I'm using things that are given to me with a language.\nDialogue: 0,0:17:22.42,0:17:24.04,EN,,0,0,0,,I'm not terribly interest in them.\nDialogue: 0,0:17:24.42,0:17:26.04,EN,,0,0,0,,Now how do we deal with sums?\nDialogue: 0,0:17:26.60,0:17:28.80,EN,,0,0,0,,Ah, something very interesting will happen.\nDialogue: 0,0:17:28.98,0:17:33.12,EN,,0,0,0,,A sum is something which is not atomic and begins with the plus symbol.\nDialogue: 0,0:17:35.16,0:17:36.17,EN,,0,0,0,,That's what it means.\nDialogue: 0,0:17:36.65,0:17:39.77,EN,,0,0,0,,So here, I will define.\nDialogue: 0,0:17:45.46,0:17:57.77,EN,,0,0,0,,An expression is a sum if and it's not atomic\nDialogue: 0,0:18:04.57,0:18:15.45,EN,,0,0,0,,and it's head, it's beginning, its car of the expression is the symbol plus.\nDialogue: 0,0:18:19.74,0:18:24.04,EN,,0,0,0,,Now you're about to see something you haven't seen before, this quotation.\nDialogue: 0,0:18:25.89,0:18:28.22,EN,,0,0,0,,Why do I have that quotation there?\nDialogue: 0,0:18:29.48,0:18:30.52,EN,,0,0,0,,PROFESSOR: Say your name,\nDialogue: 0,0:18:30.68,0:18:31.41,EN,,0,0,0,,AUDIENCE: Susanna.\nDialogue: 0,0:18:31.41,0:18:32.01,EN,,0,0,0,,PROFESSOR: Louder.\nDialogue: 0,0:18:32.01,0:18:32.72,EN,,0,0,0,,AUDIENCE: Susanna\nDialogue: 0,0:18:33.25,0:18:34.21,EN,,0,0,0,,PROFESSOR: Say your name.\nDialogue: 0,0:18:34.21,0:18:34.85,EN,,0,0,0,,AUDIENCE: Your name.\nDialogue: 0,0:18:34.92,0:18:35.68,EN,,0,0,0,,PROFESSOR: Louder.\nDialogue: 0,0:18:35.77,0:18:36.61,EN,,0,0,0,,AUDIENCE: Your name.\nDialogue: 0,0:18:36.82,0:18:37.50,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:18:38.28,0:18:44.56,EN,,0,0,0,,What I'm showing you here is that the words of English are ambiguous.\nDialogue: 0,0:18:45.50,0:18:50.76,EN,,0,0,0,,I was saying, say your name.\nDialogue: 0,0:18:51.97,0:18:57.21,EN,,0,0,0,,I was also possibly saying say, your name.\nDialogue: 0,0:19:00.72,0:19:02.98,EN,,0,0,0,,But that cannot be distinguished in speech.\nDialogue: 0,0:19:03.89,0:19:08.01,EN,,0,0,0,,However, we do have a notation in writing,\nDialogue: 0,0:19:08.18,0:19:12.46,EN,,0,0,0,,which is quotation for distinguishing these two possible meanings.\nDialogue: 0,0:19:14.00,0:19:15.64,EN,,0,0,0,,In particular, over here,\nDialogue: 0,0:19:16.49,0:19:20.84,EN,,0,0,0,,in Lisp we have a notation for distinguishing these meanings.\nDialogue: 0,0:19:21.34,0:19:24.45,EN,,0,0,0,,If I were to just write a plus here, a plus symbol,\nDialogue: 0,0:19:24.64,0:19:28.52,EN,,0,0,0,,I would be asking, is the first element of the expression,\nDialogue: 0,0:19:29.06,0:19:33.61,EN,,0,0,0,,is the operator position of the expression, the addition operator?\nDialogue: 0,0:19:34.65,0:19:35.54,EN,,0,0,0,,I don't know.\nDialogue: 0,0:19:36.22,0:19:38.16,EN,,0,0,0,,I would have to have written the addition operator there,\nDialogue: 0,0:19:39.37,0:19:40.44,EN,,0,0,0,,which I can't write.\nDialogue: 0,0:19:41.34,0:19:45.88,EN,,0,0,0,,However, this way I'm asking, is this the symbolic object plus,\nDialogue: 0,0:19:45.98,0:19:48.14,EN,,0,0,0,,which normally stands for the addition operator?\nDialogue: 0,0:19:49.57,0:19:51.92,EN,,0,0,0,,That's what I want. That's the question I want to ask.\nDialogue: 0,0:19:52.92,0:19:54.45,EN,,0,0,0,,Now before I go any further,\nDialogue: 0,0:19:54.45,0:19:57.81,EN,,0,0,0,,I want to point out the quotation is a very complex concept,\nDialogue: 0,0:19:58.85,0:20:01.84,EN,,0,0,0,,and adding it to a language causes a great deal of troubles.\nDialogue: 0,0:20:03.57,0:20:05.04,EN,,0,0,0,,Consider the next slide.\nDialogue: 0,0:20:06.38,0:20:09.49,EN,,0,0,0,,Here's a deduction which we should all agree with.\nDialogue: 0,0:20:11.62,0:20:17.04,EN,,0,0,0,,We have, Alyssa is smart and Alyssa is George's mother.\nDialogue: 0,0:20:17.40,0:20:20.60,EN,,0,0,0,,This is an equality, is.\nDialogue: 0,0:20:22.13,0:20:26.30,EN,,0,0,0,,From those two, we can deduce that George's mother is smart.\nDialogue: 0,0:20:27.32,0:20:33.16,EN,,0,0,0,,Because we can always substitute equals for equals in expressions.\nDialogue: 0,0:20:34.09,0:20:35.16,EN,,0,0,0,,Or can we?\nDialogue: 0,0:20:36.52,0:20:40.37,EN,,0,0,0,,Here's a case where we have \"Chicago\" has seven letters.\nDialogue: 0,0:20:41.12,0:20:44.86,EN,,0,0,0,,The quotation means that I'm discussing the word Chicago,\nDialogue: 0,0:20:44.86,0:20:46.86,EN,,0,0,0,,not what the word represents.\nDialogue: 0,0:20:49.82,0:20:52.77,EN,,0,0,0,,Here I have that Chicago is the biggest city in Illinois.\nDialogue: 0,0:20:54.61,0:20:55.80,EN,,0,0,0,,As a consequence of this,\nDialogue: 0,0:20:55.80,0:20:59.09,EN,,0,0,0,,I would like to deduce that the biggest city in Illinois has seven letters.\nDialogue: 0,0:20:59.32,0:21:01.06,EN,,0,0,0,,But that's manifestly false.\nDialogue: 0,0:21:05.16,0:21:07.17,EN,,0,0,0,,Wow, it works.\nDialogue: 0,0:21:09.29,0:21:12.24,EN,,0,0,0,,OK, so once we have things like that,\nDialogue: 0,0:21:12.48,0:21:14.49,EN,,0,0,0,,our language gets much more complicated.\nDialogue: 0,0:21:14.49,0:21:18.34,EN,,0,0,0,,Because it's no longer true that things we tend to like to do with languages,\nDialogue: 0,0:21:18.34,0:21:20.76,EN,,0,0,0,,like substituting equals for equals and getting right answers,\nDialogue: 0,0:21:21.29,0:21:23.50,EN,,0,0,0,,are going to work without being very careful.\nDialogue: 0,0:21:24.49,0:21:27.34,EN,,0,0,0,,We can't substitute into what's called referentially opaque contexts,\nDialogue: 0,0:21:27.89,0:21:32.64,EN,,0,0,0,,of which a quotation is the prototypical type of referentially opaque context.\nDialogue: 0,0:21:33.17,0:21:35.28,EN,,0,0,0,,If you know what that means, you can consult a philosopher.\nDialogue: 0,0:21:35.42,0:21:37.02,EN,,0,0,0,,Presumably there is one in the room.\nDialogue: 0,0:21:37.53,0:21:41.32,EN,,0,0,0,,In any case, let's continue now,\nDialogue: 0,0:21:41.32,0:21:44.98,EN,,0,0,0,,now that we at least have an operational understanding of a 2000-year-old issue\nDialogue: 0,0:21:45.26,0:21:48.13,EN,,0,0,0,,that has to do with name, and mention, and all sorts of things like that.\nDialogue: 0,0:21:52.32,0:22:01.60,EN,,0,0,0,,I have to define what I mean, how to make a sum of two things, an a1 and a2.\nDialogue: 0,0:22:02.12,0:22:03.62,EN,,0,0,0,,And I'm going to do this very simply.\nDialogue: 0,0:22:03.62,0:22:11.96,EN,,0,0,0,,It's a list of the symbol plus, and a1, and a2.\nDialogue: 0,0:22:13.86,0:22:17.37,EN,,0,0,0,,And I can determine the first element.\nDialogue: 0,0:22:21.84,0:22:25.32,EN,,0,0,0,,Define a1 to be cadr.\nDialogue: 0,0:22:33.88,0:22:35.90,EN,,0,0,0,,I've just introduced another primitive.\nDialogue: 0,0:22:36.17,0:22:39.10,EN,,0,0,0,,This is the car of the cdr of something.\nDialogue: 0,0:22:39.80,0:22:44.53,EN,,0,0,0,,You might want to know why car and cdr are names of these primitives,\nDialogue: 0,0:22:44.66,0:22:48.42,EN,,0,0,0,,and why they've survived, even though they're much better ideas like left and right.\nDialogue: 0,0:22:48.76,0:22:50.44,EN,,0,0,0,,We could have called them things like that.\nDialogue: 0,0:22:51.28,0:22:56.25,EN,,0,0,0,,Well, first of all, the names come from the fact that in the great past, when Lisp was invented,\nDialogue: 0,0:22:56.36,0:23:00.80,EN,,0,0,0,,I suppose in '58 or something, it was on a 704 or something like that,\nDialogue: 0,0:23:00.80,0:23:05.41,EN,,0,0,0,,which had a machine. It was a machine that had an address register and a decrement register.\nDialogue: 0,0:23:05.41,0:23:08.17,EN,,0,0,0,,And these were the contents of the address register and the decrement register.\nDialogue: 0,0:23:08.17,0:23:09.37,EN,,0,0,0,,So it's an historical accident.\nDialogue: 0,0:23:09.64,0:23:11.28,EN,,0,0,0,,Now why have these names survived?\nDialogue: 0,0:23:11.74,0:23:14.76,EN,,0,0,0,,It's because Lisp programmers like to talk to each other over the phone.\nDialogue: 0,0:23:15.68,0:23:19.60,EN,,0,0,0,,And if you want to have a long sequence of cars and cdrs you might say, cdaddedr,\nDialogue: 0,0:23:21.01,0:23:22.32,EN,,0,0,0,,which can be understood.\nDialogue: 0,0:23:22.32,0:23:27.02,EN,,0,0,0,,But left of right or right of left is not so clear if you get good at it.\nDialogue: 0,0:23:27.60,0:23:30.02,EN,,0,0,0,,So that's why we have these words.\nDialogue: 0,0:23:30.54,0:23:34.14,EN,,0,0,0,,All of them up to four deep are defined typically in a Lisp system.\nDialogue: 0,0:23:38.66,0:23:47.05,EN,,0,0,0,,A2 to be-- and, of course, you can see that if I looked at one of these expressions\nDialogue: 0,0:23:47.36,0:23:52.14,EN,,0,0,0,,like the sum of 3 and 5,\nDialogue: 0,0:23:52.58,0:24:10.45,EN,,0,0,0,,what that is is a list containing the symbol plus, and a number 3, and a number 5.\nDialogue: 0,0:24:11.72,0:24:15.18,EN,,0,0,0,,Then the car is the symbol plus.\nDialogue: 0,0:24:16.13,0:24:18.21,EN,,0,0,0,,The car of the cdr.\nDialogue: 0,0:24:18.21,0:24:20.21,EN,,0,0,0,,Well I take the cdr and then I take the car.\nDialogue: 0,0:24:20.21,0:24:22.21,EN,,0,0,0,,And that's how I get to the 3. That's the first argument.\nDialogue: 0,0:24:22.52,0:24:25.69,EN,,0,0,0,,And the car of the cdr of the cdr gets me to this one, the 5.\nDialogue: 0,0:24:28.69,0:24:33.66,EN,,0,0,0,,And similarly, of course, I can define what's going on with products.\nDialogue: 0,0:24:35.22,0:24:36.56,EN,,0,0,0,,Let's do that very quickly.\nDialogue: 0,0:24:48.97,0:24:50.64,EN,,0,0,0,,Is the expression a product?\nDialogue: 0,0:24:51.05,0:24:54.69,EN,,0,0,0,,Yes if and if it's true, that's it's not atomic\nDialogue: 0,0:25:01.41,0:25:14.14,EN,,0,0,0,,and it's EQ quote, the asterisk symbol, which is the operator for multiplication.\nDialogue: 0,0:25:15.64,0:25:32.00,EN,,0,0,0,,Make product of an M1 and an M2 to be list,\nDialogue: 0,0:25:34.42,0:25:39.30,EN,,0,0,0,,quote, the asterisk operation and M1 and M2.\nDialogue: 0,0:25:40.82,0:25:56.81,EN,,0,0,0,,And I define M1 to be cadr and M2 to be caddr.\nDialogue: 0,0:26:00.09,0:26:02.38,EN,,0,0,0,,You get to be a good Lisp programmer because you start talking that way.\nDialogue: 0,0:26:02.53,0:26:05.53,EN,,0,0,0,,You can cdr thing down lists and cons them up and so on.\nDialogue: 0,0:26:06.29,0:26:10.10,EN,,0,0,0,,Now, now that we have essentially a complete program for finding derivatives,\nDialogue: 0,0:26:10.10,0:26:11.70,EN,,0,0,0,,you can add more rules if you like.\nDialogue: 0,0:26:12.21,0:26:13.93,EN,,0,0,0,,What kind of behavior do we get out of it?\nDialogue: 0,0:26:14.64,0:26:16.77,EN,,0,0,0,,I'll have to clear that x.\nDialogue: 0,0:26:17.80,0:26:20.82,EN,,0,0,0,,Well, supposing I define foo here\nDialogue: 0,0:26:22.16,0:26:30.38,EN,,0,0,0,,to be the sum of the product of ax square and bx plus c.\nDialogue: 0,0:26:30.54,0:26:32.08,EN,,0,0,0,,That's the same thing we see here\nDialogue: 0,0:26:32.08,0:26:36.36,EN,,0,0,0,,as the algebraic expression written in the more conventional notation over there.\nDialogue: 0,0:26:37.84,0:26:41.60,EN,,0,0,0,,Well, the derivative of foo with respect to x, which we can see over here,\nDialogue: 0,0:26:43.46,0:26:45.26,EN,,0,0,0,,is this horrible, horrendous mess.\nDialogue: 0,0:26:46.16,0:26:49.22,EN,,0,0,0,,I would like it to be 2ax plus b.\nDialogue: 0,0:26:50.68,0:26:53.44,EN,,0,0,0,,But it's not. It's equivalent to it.\nDialogue: 0,0:26:54.58,0:26:55.22,EN,,0,0,0,,What is it?\nDialogue: 0,0:26:55.97,0:26:59.96,EN,,0,0,0,,I have here, what do I have?\nDialogue: 0,0:27:00.50,0:27:04.30,EN,,0,0,0,,I have the derivative of the product of x and x.\nDialogue: 0,0:27:04.69,0:27:10.53,EN,,0,0,0,,Over here is, of course, the sum of x times 1 and 1 times x.\nDialogue: 0,0:27:12.73,0:27:15.66,EN,,0,0,0,,Now, well, it's the first times the derivative of the second plus the second times the derivative of the first. It's right.\nDialogue: 0,0:27:17.22,0:27:28.37,EN,,0,0,0,,That's 2x of course. a times 2x is 2ax plus 0X square doesn't count plus B over here plus a bunch of 0's.\nDialogue: 0,0:27:28.96,0:27:30.12,EN,,0,0,0,,Well the answer is right.\nDialogue: 0,0:27:30.12,0:27:35.14,EN,,0,0,0,,But I give people take off points on an exam for that, sadly enough.\nDialogue: 0,0:27:35.56,0:27:37.26,EN,,0,0,0,,Let's worry about that in the next segment.\nDialogue: 0,0:27:37.68,0:27:38.61,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:27:42.77,0:27:43.45,EN,,0,0,0,,Yes?\nDialogue: 0,0:27:43.89,0:27:46.69,EN,,0,0,0,,AUDIENCE: If you had left the quote when you put the plus,\nDialogue: 0,0:27:46.69,0:27:50.82,EN,,0,0,0,,then would that be referring to the procedure plus\nDialogue: 0,0:27:50.82,0:27:55.42,EN,,0,0,0,,and could you do a comparison between that procedure and some other procedure if you wanted to?\nDialogue: 0,0:27:56.16,0:27:57.08,EN,,0,0,0,,PROFESSOR: Yes. Good question.\nDialogue: 0,0:27:57.45,0:28:02.26,EN,,0,0,0,,If I had left this quotation off at this point,\nDialogue: 0,0:28:03.88,0:28:07.13,EN,,0,0,0,,Okay? If I had left that quotation off at that point,\nDialogue: 0,0:28:07.33,0:28:14.20,EN,,0,0,0,,then I would be referring here to the procedure which is the thing that plus is defined to be.\nDialogue: 0,0:28:15.38,0:28:24.88,EN,,0,0,0,,And indeed, I could compare some procedures with each other for identity.\nDialogue: 0,0:28:24.88,0:28:27.45,EN,,0,0,0,,Now what that means is not clear right now.\nDialogue: 0,0:28:27.85,0:28:29.37,EN,,0,0,0,,I don't like to think about it.\nDialogue: 0,0:28:29.89,0:28:32.40,EN,,0,0,0,,Because I don't know exactly what it would need to compare procedures.\nDialogue: 0,0:28:32.40,0:28:34.40,EN,,0,0,0,,There are reasons why that may make no sense at all.\nDialogue: 0,0:28:35.52,0:28:37.53,EN,,0,0,0,,However, the symbols, we understand.\nDialogue: 0,0:28:38.54,0:28:40.56,EN,,0,0,0,,And so that's why I put that quote in.\nDialogue: 0,0:28:41.16,0:28:43.70,EN,,0,0,0,,I want to talk about the symbol that's apparent on the page.\nDialogue: 0,0:28:46.16,0:28:46.92,EN,,0,0,0,,Any other questions?\nDialogue: 0,0:28:48.52,0:28:51.86,EN,,0,0,0,,OK. Thank you. Let's take a break.\nDialogue: 0,0:28:55.12,0:29:00.66,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:29:00.68,0:29:04.34,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:29:04.34,0:29:06.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:29:12.21,0:29:19.17,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:29:20.09,0:29:24.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}Symbolic Differentiation: Quotation\nDialogue: 0,0:29:29.86,0:29:30.92,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:29:31.46,0:29:37.76,EN,,0,0,0,,We've just developed a fairly plausible program for computing the derivatives of algebraic expressions.\nDialogue: 0,0:29:38.20,0:29:41.56,EN,,0,0,0,,It's an incomplete program, if you would like to add more rules.\nDialogue: 0,0:29:42.13,0:29:47.74,EN,,0,0,0,,And perhaps you might extend it to deal with uses of addition with any number of arguments\nDialogue: 0,0:29:47.76,0:29:49.70,EN,,0,0,0,,and multiplication with any of the number of arguments.\nDialogue: 0,0:29:49.89,0:29:51.38,EN,,0,0,0,,And that's all rather easy.\nDialogue: 0,0:29:52.73,0:29:56.93,EN,,0,0,0,,However, there was a little fly in that ointment.\nDialogue: 0,0:29:57.48,0:30:02.37,EN,,0,0,0,,We go back to this slide.\nDialogue: 0,0:30:02.94,0:30:08.60,EN,,0,0,0,,We see that the expressions that we get are rather bad.\nDialogue: 0,0:30:08.88,0:30:11.01,EN,,0,0,0,,This is a rather bad expression.\nDialogue: 0,0:30:11.46,0:30:13.10,EN,,0,0,0,,How do we get such an expression?\nDialogue: 0,0:30:13.84,0:30:15.50,EN,,0,0,0,,Why do we have that expression?\nDialogue: 0,0:30:16.84,0:30:18.74,EN,,0,0,0,,Let's look at this expression in some detail.\nDialogue: 0,0:30:18.92,0:30:20.76,EN,,0,0,0,,Let's find out where all the pieces come from.\nDialogue: 0,0:30:21.69,0:30:24.56,EN,,0,0,0,,As we see here, we have a sum--\nDialogue: 0,0:30:24.56,0:30:26.56,EN,,0,0,0,,just what I showed you at the end of the last time--\nDialogue: 0,0:30:27.12,0:30:29.09,EN,,0,0,0,,of X times 1 plus 1 time X.\nDialogue: 0,0:30:29.58,0:30:31.38,EN,,0,0,0,,That is a derivative of this product.\nDialogue: 0,0:30:32.52,0:30:36.41,EN,,0,0,0,,The product of a times that, where a does not depend upon x,\nDialogue: 0,0:30:36.41,0:30:38.41,EN,,0,0,0,,and therefore is constant with respect to x,\nDialogue: 0,0:30:39.04,0:30:44.53,EN,,0,0,0,,is this sum, which goes from here all the way through here and through here.\nDialogue: 0,0:30:44.80,0:30:48.89,EN,,0,0,0,,Because it is the first thing times the derivative of the second\nDialogue: 0,0:30:49.57,0:30:54.45,EN,,0,0,0,,plus the derivative of the first times the second\nDialogue: 0,0:30:54.66,0:30:59.06,EN,,0,0,0,,as the program we wrote on the blackboard indicated we should do.\nDialogue: 0,0:31:00.65,0:31:05.36,EN,,0,0,0,,And, of course, the product of bx over here\nDialogue: 0,0:31:05.49,0:31:09.81,EN,,0,0,0,,manifests itself as B times 1 plus 0 times X\nDialogue: 0,0:31:10.81,0:31:16.06,EN,,0,0,0,,because we see that B does not depend upon X.\nDialogue: 0,0:31:16.46,0:31:18.56,EN,,0,0,0,,And so the derivative of B is this 0,\nDialogue: 0,0:31:18.77,0:31:21.48,EN,,0,0,0,,and the derivative of X with respect itself is the 1.\nDialogue: 0,0:31:23.06,0:31:28.64,EN,,0,0,0,,And, of course, the derivative of the sums over here turn into these two sums of the derivatives of the parts.\nDialogue: 0,0:31:29.37,0:31:33.50,EN,,0,0,0,,So what we're seeing here is exactly the thing I was trying to tell you about\nDialogue: 0,0:31:33.66,0:31:35.89,EN,,0,0,0,,with Fibonacci numbers a while ago,\nDialogue: 0,0:31:37.77,0:31:39.49,EN,,0,0,0,,that the form of the process\nDialogue: 0,0:31:41.38,0:31:46.44,EN,,0,0,0,,is expanded as low as from the local rules that you see in the procedure,\nDialogue: 0,0:31:48.05,0:31:52.57,EN,,0,0,0,,that the procedure represents a set of local rules for the expansion of this process.\nDialogue: 0,0:31:53.36,0:32:00.09,EN,,0,0,0,,And here, the process left behind some stuff, which is the answer.\nDialogue: 0,0:32:00.25,0:32:06.26,EN,,0,0,0,,And it was constructed by the walk it takes of the tree structure, which is the expression.\nDialogue: 0,0:32:08.41,0:32:12.61,EN,,0,0,0,,So every part in the answer we see here derives from some part of the problem.\nDialogue: 0,0:32:14.46,0:32:17.78,EN,,0,0,0,,Now, we can look at, for example, the derivative of foo,\nDialogue: 0,0:32:17.78,0:32:19.65,EN,,0,0,0,,which is ax square plus bx plus c,\nDialogue: 0,0:32:19.84,0:32:23.05,EN,,0,0,0,,with respect to other things, like here, for example,\nDialogue: 0,0:32:24.14,0:32:27.48,EN,,0,0,0,,we can see that the derivative of foo with respect to a.\nDialogue: 0,0:32:28.10,0:32:31.77,EN,,0,0,0,,And it's very similar. It's, in fact, the identical algebraic expression,\nDialogue: 0,0:32:32.45,0:32:35.24,EN,,0,0,0,,except for the fact that theses 0's and 1's are in different places.\nDialogue: 0,0:32:36.06,0:32:38.60,EN,,0,0,0,,Because the only degree of freedom we have in this tree walk\nDialogue: 0,0:32:38.97,0:32:43.85,EN,,0,0,0,,is what's constant with respect to the variable we're taking the derivative with respect to\nDialogue: 0,0:32:44.28,0:32:45.81,EN,,0,0,0,,and what's the same variable.\nDialogue: 0,0:32:48.26,0:32:52.09,EN,,0,0,0,,In other words, if we go back to this blackboard and we look,\nDialogue: 0,0:32:52.65,0:32:57.49,EN,,0,0,0,,we have no choice what to do when we take the derivative of the sum or a product.\nDialogue: 0,0:32:58.08,0:33:04.48,EN,,0,0,0,,The only interesting place here is, is the expression the variable,\nDialogue: 0,0:33:04.80,0:33:10.10,EN,,0,0,0,,or is the expression a constant with respect to that variable for very, very small expressions?\nDialogue: 0,0:33:10.36,0:33:12.41,EN,,0,0,0,,In which case we get various 1's and 0's,\nDialogue: 0,0:33:12.69,0:33:14.49,EN,,0,0,0,,which if we go back to this slide,\nDialogue: 0,0:33:15.12,0:33:18.16,EN,,0,0,0,,we can see that the 0's that appear here, for example,\nDialogue: 0,0:33:18.37,0:33:22.74,EN,,0,0,0,,this 1 over here in derivative of foo with respect to A,\nDialogue: 0,0:33:22.96,0:33:24.86,EN,,0,0,0,,which gets us an X square,\nDialogue: 0,0:33:24.96,0:33:32.53,EN,,0,0,0,,because that 1 gets the multiply of X and X into the answer, that 1 is 0.\nDialogue: 0,0:33:32.64,0:33:34.89,EN,,0,0,0,,Over here, we're not taking the derivative of foo with respect to c.\nDialogue: 0,0:33:36.78,0:33:39.30,EN,,0,0,0,,But the shapes of these expressions are the same.\nDialogue: 0,0:33:40.54,0:33:43.96,EN,,0,0,0,,See all those shapes. They're the same.\nDialogue: 0,0:33:50.37,0:33:52.28,EN,,0,0,0,,Well is there anything wrong with our rules?\nDialogue: 0,0:33:53.58,0:33:55.02,EN,,0,0,0,,No. They're the right rules.\nDialogue: 0,0:33:56.12,0:33:57.77,EN,,0,0,0,,We've been through this one before.\nDialogue: 0,0:33:58.06,0:34:03.53,EN,,0,0,0,,One of the things you're going to begin to discover is that there aren't too many good ideas.\nDialogue: 0,0:34:06.32,0:34:09.74,EN,,0,0,0,,When we were looking at rational numbers yesterday,\nDialogue: 0,0:34:12.12,0:34:14.48,EN,,0,0,0,,the problem was that we got 6/8 rather then 3/4.\nDialogue: 0,0:34:14.97,0:34:16.49,EN,,0,0,0,,The answer was unsimplified.\nDialogue: 0,0:34:18.09,0:34:20.90,EN,,0,0,0,,The problem, of course, is very similar.\nDialogue: 0,0:34:21.18,0:34:25.41,EN,,0,0,0,,There are things I'd like to be identical by simplification that don't become identical.\nDialogue: 0,0:34:27.57,0:34:31.89,EN,,0,0,0,,And yet the rules for doing addition a multiplication of rational numbers were correct.\nDialogue: 0,0:34:33.97,0:34:37.41,EN,,0,0,0,,So the way we might solve this problem is do the thing we did last time, which always works.\nDialogue: 0,0:34:37.78,0:34:39.89,EN,,0,0,0,,If something worked last time it ought to work again.\nDialogue: 0,0:34:40.53,0:34:42.05,EN,,0,0,0,,It's changed representation.\nDialogue: 0,0:34:43.13,0:34:46.44,EN,,0,0,0,,Perhaps in the representation we could put in a simplification step\nDialogue: 0,0:34:47.88,0:34:49.78,EN,,0,0,0,,that produces a simplified representation.\nDialogue: 0,0:34:50.17,0:34:51.73,EN,,0,0,0,,This may not always work, of course.\nDialogue: 0,0:34:52.49,0:34:54.14,EN,,0,0,0,,I'm not trying to say that it always works.\nDialogue: 0,0:34:55.12,0:35:00.44,EN,,0,0,0,,But it's one of the pieces of artillery we have in our war against complexity.\nDialogue: 0,0:35:01.46,0:35:03.85,EN,,0,0,0,,You see, because we solved our problem very carefully.\nDialogue: 0,0:35:04.30,0:35:07.20,EN,,0,0,0,,What we've done, is we've divided the world in several parts.\nDialogue: 0,0:35:07.57,0:35:08.73,EN,,0,0,0,,There are derivatives rules\nDialogue: 0,0:35:11.32,0:35:15.80,EN,,0,0,0,,and general rules for algebra of some sort at this level of detail.\nDialogue: 0,0:35:16.38,0:35:21.22,EN,,0,0,0,,and i have an abstraction barrier.\nDialogue: 0,0:35:22.48,0:35:33.49,EN,,0,0,0,,And i have the representation of the algebraic expressions, list structure.\nDialogue: 0,0:35:37.33,0:35:42.56,EN,,0,0,0,,And in this barrier, I have the interface procedures.\nDialogue: 0,0:35:43.25,0:35:49.82,EN,,0,0,0,,I have constant, and things like same-var.\nDialogue: 0,0:35:54.60,0:35:58.72,EN,,0,0,0,,I have things like sum, make-sum.\nDialogue: 0,0:36:02.22,0:36:05.57,EN,,0,0,0,,I have A1, A2.\nDialogue: 0,0:36:06.60,0:36:08.58,EN,,0,0,0,,I have products and things like that,\nDialogue: 0,0:36:08.74,0:36:11.90,EN,,0,0,0,,all the other things I might need for various kinds of algebraic expressions.\nDialogue: 0,0:36:12.94,0:36:19.14,EN,,0,0,0,,Making this barrier allows me to arbitrarily change the representation\nDialogue: 0,0:36:20.14,0:36:23.20,EN,,0,0,0,,without changing the rules that are written in terms of that representation.\nDialogue: 0,0:36:25.04,0:36:29.08,EN,,0,0,0,,So if I can make the problem go away by changing representation,\nDialogue: 0,0:36:30.38,0:36:34.52,EN,,0,0,0,,the composition of the problem into these two parts has helped me a great deal.\nDialogue: 0,0:36:35.65,0:36:37.54,EN,,0,0,0,,So let's take a very simple case of this.\nDialogue: 0,0:36:38.82,0:36:40.08,EN,,0,0,0,,What was one of the problems?\nDialogue: 0,0:36:40.26,0:36:43.61,EN,,0,0,0,,Let's go back to this transparency again.\nDialogue: 0,0:36:44.50,0:36:47.34,EN,,0,0,0,,And we see here, oh yes, there's horrible things\nDialogue: 0,0:36:47.62,0:36:51.86,EN,,0,0,0,,like here is the sum of an expression and 0.\nDialogue: 0,0:36:53.14,0:36:56.66,EN,,0,0,0,,Well that's no reason to think of it as anything other than the expression itself.\nDialogue: 0,0:36:57.21,0:37:01.90,EN,,0,0,0,,Why should the summation operation have made up this edition?\nDialogue: 0,0:37:03.38,0:37:04.57,EN,,0,0,0,,It can be smarter than that.\nDialogue: 0,0:37:05.56,0:37:10.08,EN,,0,0,0,,Or here, for example, is a multiplication of something by 1.\nDialogue: 0,0:37:11.16,0:37:12.29,EN,,0,0,0,,It's another thing like that.\nDialogue: 0,0:37:12.86,0:37:15.68,EN,,0,0,0,,Or here is a product of something with 0, which is certainly 0.\nDialogue: 0,0:37:17.86,0:37:19.52,EN,,0,0,0,,So we won't have to make this construction.\nDialogue: 0,0:37:21.44,0:37:22.62,EN,,0,0,0,,So why don't we just do that?\nDialogue: 0,0:37:23.66,0:37:27.96,EN,,0,0,0,,We need to change the way the representation works, almost here.\nDialogue: 0,0:37:37.40,0:37:41.84,EN,,0,0,0,,Make-sum to be.\nDialogue: 0,0:37:42.05,0:37:43.76,EN,,0,0,0,,Well, now it's not something so simple.\nDialogue: 0,0:37:44.00,0:37:50.40,EN,,0,0,0,,I'm not going to make a list containing the symbol plus and things unless I need to.\nDialogue: 0,0:37:51.72,0:37:53.05,EN,,0,0,0,,Well, what are the possibilities?\nDialogue: 0,0:37:54.56,0:37:58.53,EN,,0,0,0,,If...I have some sort of cases here.\nDialogue: 0,0:37:59.38,0:38:08.20,EN,,0,0,0,,If I have numbers, if a1 is a number--\nDialogue: 0,0:38:09.05,0:38:10.93,EN,,0,0,0,,and here's another primitive I've just introduced,\nDialogue: 0,0:38:10.93,0:38:13.18,EN,,0,0,0,,it's possible to tell whether something's number--\nDialogue: 0,0:38:15.38,0:38:23.82,EN,,0,0,0,,and if number A2, meaning they're not symbolic expressions,\nDialogue: 0,0:38:24.45,0:38:26.20,EN,,0,0,0,,then why not do the addition now?\nDialogue: 0,0:38:26.45,0:38:29.92,EN,,0,0,0,,The result is just a plus of A1 and A2.\nDialogue: 0,0:38:32.32,0:38:33.98,EN,,0,0,0,,I'm not asking if these represent numbers.\nDialogue: 0,0:38:33.98,0:38:35.98,EN,,0,0,0,,Of course all of these symbols represent numbers.\nDialogue: 0,0:38:37.33,0:38:41.22,EN,,0,0,0,,I'm talking about whether the one I've got is the number 3 right now.\nDialogue: 0,0:38:43.40,0:38:44.40,EN,,0,0,0,,And, for example,\nDialogue: 0,0:38:48.77,0:38:59.61,EN,,0,0,0,,supposing A1 is a number, and it's equal to 0,\nDialogue: 0,0:39:04.20,0:39:06.38,EN,,0,0,0,,well then the answer is just A2.\nDialogue: 0,0:39:06.93,0:39:08.68,EN,,0,0,0,,There is no reason to make anything up.\nDialogue: 0,0:39:10.98,0:39:23.41,EN,,0,0,0,,And if A2 is a number, and equal A2 0,\nDialogue: 0,0:39:27.16,0:39:28.90,EN,,0,0,0,,then the result is A1.\nDialogue: 0,0:39:30.04,0:39:33.65,EN,,0,0,0,,And only if I can't figure out something better to do with this situation,\nDialogue: 0,0:39:34.13,0:39:35.61,EN,,0,0,0,,well, I can construct a list.\nDialogue: 0,0:39:37.86,0:39:42.86,EN,,0,0,0,,Otherwise I want the representation to be the list\nDialogue: 0,0:39:44.13,0:39:52.33,EN,,0,0,0,,containing the quoted symbol plus, and A1, and A2.\nDialogue: 0,0:39:58.66,0:40:01.65,EN,,0,0,0,,And, of course, a very similar thing can be done for products.\nDialogue: 0,0:40:03.01,0:40:05.04,EN,,0,0,0,,And I think I'll avoid boring you with them.\nDialogue: 0,0:40:05.44,0:40:07.24,EN,,0,0,0,,I was going to write it on the blackboard.\nDialogue: 0,0:40:07.65,0:40:09.80,EN,,0,0,0,,I don't think it's necessary. You know what to do.\nDialogue: 0,0:40:10.76,0:40:11.61,EN,,0,0,0,,It's very simple.\nDialogue: 0,0:40:12.86,0:40:19.89,EN,,0,0,0,,But now, let's just see the kind of results we get out of changing our program in this way.\nDialogue: 0,0:40:21.68,0:40:27.88,EN,,0,0,0,,Well, here's the derivatives after having just changed the constructors for expressions.\nDialogue: 0,0:40:28.98,0:40:32.21,EN,,0,0,0,,The same foo, aX square plus bX plus c,\nDialogue: 0,0:40:33.28,0:40:40.70,EN,,0,0,0,,and what I get is nothing more than the derivative of that is 2aX plus B.\nDialogue: 0,0:40:40.70,0:40:42.10,EN,,0,0,0,,Well, it's not completely simplified.\nDialogue: 0,0:40:42.60,0:40:44.53,EN,,0,0,0,,I would like to collect common terms and sums.\nDialogue: 0,0:40:45.06,0:40:46.08,EN,,0,0,0,,Well, that's more work.\nDialogue: 0,0:40:47.12,0:40:51.86,EN,,0,0,0,,And, of course, programs to do this sort of thing are huge and complicated.\nDialogue: 0,0:40:52.28,0:40:55.28,EN,,0,0,0,,Algebraic simplification, it's a very complicated mess.\nDialogue: 0,0:40:56.37,0:41:00.13,EN,,0,0,0,,There's a very famous program you may have heard of called Maxima developed at MIT in the past,\nDialogue: 0,0:41:00.42,0:41:03.14,EN,,0,0,0,,which is 5,000 pages of Lisp code,\nDialogue: 0,0:41:03.92,0:41:06.50,EN,,0,0,0,,mostly the algebraic simplification operations.\nDialogue: 0,0:41:08.08,0:41:12.21,EN,,0,0,0,,There we see the derivative of foo.\nDialogue: 0,0:41:12.21,0:41:16.86,EN,,0,0,0,,In fact, alias is something I wouldn't take off more than 1 point for on an elementary calculus class.\nDialogue: 0,0:41:18.38,0:41:22.49,EN,,0,0,0,,And the derivative of foo with respect to a, well it's gone down to X times X,\nDialogue: 0,0:41:22.80,0:41:23.80,EN,,0,0,0,,which isn't so bad.\nDialogue: 0,0:41:24.74,0:41:27.53,EN,,0,0,0,,And the derivative of foo with respect to b is just X itself.\nDialogue: 0,0:41:28.06,0:41:30.12,EN,,0,0,0,,And the derivative of foo with respect to c comes out 1.\nDialogue: 0,0:41:30.70,0:41:32.04,EN,,0,0,0,,So I'm pretty pleased with this.\nDialogue: 0,0:41:34.10,0:41:39.01,EN,,0,0,0,,What you've seen is, of course, a little bit contrived, carefully organized example\nDialogue: 0,0:41:39.56,0:41:42.60,EN,,0,0,0,,to show you how we can manipulate algebraic expressions,\nDialogue: 0,0:41:42.96,0:41:47.93,EN,,0,0,0,,how we do that abstractly in terms of abstract syntax rather than concrete syntax\nDialogue: 0,0:41:49.21,0:41:56.29,EN,,0,0,0,,and how we can use the abstraction to control what goes on in building these expressions.\nDialogue: 0,0:41:57.80,0:42:00.41,EN,,0,0,0,,But the real story isn't just such a simple thing as that.\nDialogue: 0,0:42:01.00,0:42:04.45,EN,,0,0,0,,The real story is, in fact, that I'm manipulating these expressions.\nDialogue: 0,0:42:04.45,0:42:06.72,EN,,0,0,0,,And the expressions are the same expressions--\nDialogue: 0,0:42:06.72,0:42:07.97,EN,,0,0,0,,going back to the slide--\nDialogue: 0,0:42:08.08,0:42:10.52,EN,,0,0,0,,as the ones that are Lisp expressions.\nDialogue: 0,0:42:12.02,0:42:12.97,EN,,0,0,0,,There's a pun here.\nDialogue: 0,0:42:13.82,0:42:21.49,EN,,0,0,0,,I've chosen my representation to be the same as the representation in my language of similar things.\nDialogue: 0,0:42:22.89,0:42:26.52,EN,,0,0,0,,By doing so, I've invoked a necessity.\nDialogue: 0,0:42:26.90,0:42:30.34,EN,,0,0,0,,I created the necessity to have things like quotation\nDialogue: 0,0:42:30.97,0:42:38.17,EN,,0,0,0,,because of the fact that my language is capable of writing expressions that talk about expressions of the language.\nDialogue: 0,0:42:39.76,0:42:43.22,EN,,0,0,0,,I need to have something that says, this is an expression I'm talking about\nDialogue: 0,0:42:43.76,0:42:46.13,EN,,0,0,0,,rather than this expression is talking about something,\nDialogue: 0,0:42:47.20,0:42:48.44,EN,,0,0,0,,and I want to talk about that.\nDialogue: 0,0:42:51.34,0:42:55.36,EN,,0,0,0,,So quotation stops and says, I'm talking about this expression itself.\nDialogue: 0,0:42:57.97,0:43:00.85,EN,,0,0,0,,Now, given that power,\nDialogue: 0,0:43:01.58,0:43:03.82,EN,,0,0,0,,if I can manipulate expressions of the language,\nDialogue: 0,0:43:04.80,0:43:09.00,EN,,0,0,0,,I can begin to build even much more powerful layers upon layers of languages.\nDialogue: 0,0:43:09.77,0:43:12.64,EN,,0,0,0,,Because I can write languages that not only are embedded in Lisp\nDialogue: 0,0:43:13.46,0:43:14.80,EN,,0,0,0,,or whatever language you start with,\nDialogue: 0,0:43:15.26,0:43:17.76,EN,,0,0,0,,but languages that are completely different,\nDialogue: 0,0:43:18.58,0:43:22.24,EN,,0,0,0,,that are just, if we say, interpreted in Lisp or something like that.\nDialogue: 0,0:43:23.17,0:43:25.46,EN,,0,0,0,,We'll get to understand those words more in the future.\nDialogue: 0,0:43:26.56,0:43:32.09,EN,,0,0,0,,But right now I just want to leave you with the fact that we've hit a line\nDialogue: 0,0:43:32.36,0:43:34.98,EN,,0,0,0,,which gives us tremendous power.\nDialogue: 0,0:43:36.00,0:43:37.82,EN,,0,0,0,,And this point we've bought a sledgehammer.\nDialogue: 0,0:43:38.17,0:43:40.92,EN,,0,0,0,,We have to be careful to what flies when we apply it.\nDialogue: 0,0:43:42.17,0:43:43.00,EN,,0,0,0,,Thank you.\nDialogue: 0,0:00:00.00,0:00:02.32,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.57,0:00:11.10,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:02.57,0:00:11.10,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}字幕&时间轴\\N邓雄飞\\N(Dysprosium)\nDialogue: 0,0:00:02.57,0:00:11.10,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}后期&特效\\N邓雄飞\\N(Dysprosium)\nDialogue: 0,0:00:02.57,0:00:11.10,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.57,0:00:11.10,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:11.24,0:00:14.46,Declare,,0,0,0,,{\\an2\\fad(500,500)}符号化求导系统，引用\nDialogue: 0,0:00:19.10,0:00:23.41,Default,,0,0,0,,教授：嗯 Harold教授讲解了如何构造健壮的系统\nDialogue: 0,0:00:23.80,0:00:26.17,Default,,0,0,0,,关键点就是\nDialogue: 0,0:00:26.81,0:00:30.20,Default,,0,0,0,,我想你们大多还没吃透其中的要点\nDialogue: 0,0:00:30.20,0:00:33.77,Default,,0,0,0,,要点就是 为了让系统具有健壮性\nDialogue: 0,0:00:33.93,0:00:36.48,Default,,0,0,0,,应该让它对小变化不敏感\nDialogue: 0,0:00:36.60,0:00:37.37,Default,,0,0,0,,也就是说\nDialogue: 0,0:00:37.37,0:00:40.90,Default,,0,0,0,,问题中的小改变只会导致解决方案的小改动\nDialogue: 0,0:00:41.32,0:00:42.90,Default,,0,0,0,,系统应该是连续的\nDialogue: 0,0:00:42.90,0:00:45.94,Default,,0,0,0,,在问题空间中 解的空间是连续的\nDialogue: 0,0:00:46.25,0:00:48.76,Default,,0,0,0,,Harold教授给你们解释过\nDialogue: 0,0:00:49.46,0:00:54.78,Default,,0,0,0,,与其在问题分解出的子问题上 求解具体问题\nDialogue: 0,0:00:55.08,0:00:56.78,Default,,0,0,0,,你不如解决一类问题\nDialogue: 0,0:00:56.78,0:01:00.40,Default,,0,0,0,,也就是你想要解决的具体问题的“邻居”\nDialogue: 0,0:01:01.40,0:01:04.76,Default,,0,0,0,,解决之道便是在该层次上构造一门语言\nDialogue: 0,0:01:04.76,0:01:10.33,Default,,0,0,0,,使得我们可以用这门语言来表述这类问题\nDialogue: 0,0:01:11.37,0:01:15.09,Default,,0,0,0,,因此 当着手解决的问题再发生变动时\nDialogue: 0,0:01:15.09,0:01:19.29,Default,,0,0,0,,通常 你只需要在已构造好的解决方案上做出微小改动\nDialogue: 0,0:01:19.29,0:01:22.26,Default,,0,0,0,,因为在你所考虑的层次上\nDialogue: 0,0:01:22.26,0:01:24.26,Default,,0,0,0,,有一门语言可以表达\nDialogue: 0,0:01:24.80,0:01:28.14,Default,,0,0,0,,类似问题的各种解法\nDialogue: 0,0:01:30.04,0:01:33.74,Default,,0,0,0,,呃... 这是一个重要思想的萌芽\nDialogue: 0,0:01:34.40,0:01:38.61,Default,,0,0,0,,该思想的重要性也使得计算机科学比\nDialogue: 0,0:01:38.61,0:01:42.37,Default,,0,0,0,,其它大多数工程学科还要强大\nDialogue: 0,0:01:43.38,0:01:44.73,Default,,0,0,0,,目前为止 我们学习的是\nDialogue: 0,0:01:44.73,0:01:48.78,Default,,0,0,0,,类似于 如何使用语言内置元素\nDialogue: 0,0:01:49.26,0:01:53.36,Default,,0,0,0,,当然 内置元素的力量一部分来源于\nDialogue: 0,0:01:54.12,0:01:56.86,Default,,0,0,0,,像这个一样的过程 我昨天给你们展示过了\nDialogue: 0,0:01:57.37,0:02:02.13,Default,,0,0,0,,这里 是一份求导程序 昨天给你们描述过了\nDialogue: 0,0:02:02.13,0:02:05.92,Default,,0,0,0,,这个过程以一个过程为参数\nDialogue: 0,0:02:06.00,0:02:07.92,Default,,0,0,0,,并返回一个过程\nDialogue: 0,0:02:09.61,0:02:12.65,Default,,0,0,0,,用这样的东西棒极了\nDialogue: 0,0:02:12.65,0:02:14.65,Default,,0,0,0,,你可以像创建PUSH组合子那样构造\nDialogue: 0,0:02:14.65,0:02:16.86,Default,,0,0,0,,可以像上节课看到的哪些奇妙东西那样\nDialogue: 0,0:02:17.68,0:02:20.54,Default,,0,0,0,,现在 我要来打个太极\nDialogue: 0,0:02:21.56,0:02:25.90,Default,,0,0,0,,这个程序混淆了过程和数据\nDialogue: 0,0:02:26.56,0:02:27.81,Default,,0,0,0,,虽然程度不算太重\nDialogue: 0,0:02:28.42,0:02:30.90,Default,,0,0,0,,而我们将要严重地混淆两者\nDialogue: 0,0:02:31.18,0:02:32.44,Default,,0,0,0,,最好的做法就是\nDialogue: 0,0:02:32.44,0:02:37.62,Default,,0,0,0,,参与到过程自身所描述的代数表达式的操作中\nDialogue: 0,0:02:39.73,0:02:45.58,Default,,0,0,0,,所以 这里我不会讨论这张幻灯片上的东西\nDialogue: 0,0:02:45.89,0:02:49.72,Default,,0,0,0,,一个通过操作过程的求导程序\nDialogue: 0,0:02:49.72,0:02:51.94,Default,,0,0,0,,这只是一个数值化方法而已\nDialogue: 0,0:02:51.94,0:02:58.93,Default,,0,0,0,,你们所看到的是 通过数值方法来近似的求导程序\nDialogue: 0,0:02:59.29,0:03:00.44,Default,,0,0,0,,也就是这里的东西了\nDialogue: 0,0:03:00.86,0:03:04.93,Default,,0,0,0,,事实上 我想讨论的是这些东西\nDialogue: 0,0:03:06.05,0:03:11.33,Default,,0,0,0,,这是一份从微积分书中摘录的法则\nDialogue: 0,0:03:12.09,0:03:16.17,Default,,0,0,0,,这对表达式求导的法则\nDialogue: 0,0:03:16.70,0:03:20.58,Default,,0,0,0,,只不过是用代数语言书写的\nDialogue: 0,0:03:21.64,0:03:24.41,Default,,0,0,0,,法则说 常数的导数是0\nDialogue: 0,0:03:25.13,0:03:29.09,Default,,0,0,0,,而代表你所讨论的那个数的变量导数为1\nDialogue: 0,0:03:29.32,0:03:31.93,Default,,0,0,0,,常数乘以函数的导数\nDialogue: 0,0:03:32.09,0:03:34.37,Default,,0,0,0,,其值是常数的值乘以函数导数的值\nDialogue: 0,0:03:34.77,0:03:36.04,Default,,0,0,0,,就是这个意思\nDialogue: 0,0:03:38.05,0:03:41.38,Default,,0,0,0,,这些都是精确的表达式 而非数值近似\nDialogue: 0,0:03:42.96,0:03:44.52,Default,,0,0,0,,我们还能编写程序吗？\nDialogue: 0,0:03:44.52,0:03:52.24,Default,,0,0,0,,事实上 编写处理这些表达式的程序非常容易\nDialogue: 0,0:03:56.38,0:03:59.52,Default,,0,0,0,,让我们仔细地看看这些法则\nDialogue: 0,0:04:01.08,0:04:05.22,Default,,0,0,0,,你们曾经在初等微积分课上学过这些法则了\nDialogue: 0,0:04:05.98,0:04:12.12,Default,,0,0,0,,你们知道 微积分中对多元表达式求导很容易\nDialogue: 0,0:04:12.53,0:04:16.05,Default,,0,0,0,,在微积分课上 你们也知道计算积分不容易\nDialogue: 0,0:04:16.98,0:04:19.37,Default,,0,0,0,,虽然积分和求导相对\nDialogue: 0,0:04:19.52,0:04:21.28,Default,,0,0,0,,它俩互为逆运算\nDialogue: 0,0:04:21.61,0:04:23.30,Default,,0,0,0,,但它们有同样的法则\nDialogue: 0,0:04:24.16,0:04:29.68,Default,,0,0,0,,但这些法则中又有什么特殊的东西\nDialogue: 0,0:04:29.68,0:04:33.65,Default,,0,0,0,,使得求导容易 求积分就困难呢？\nDialogue: 0,0:04:34.85,0:04:36.98,Default,,0,0,0,,我们浅显地想一想\nDialogue: 0,0:04:37.40,0:04:38.38,Default,,0,0,0,,仔细考察法则\nDialogue: 0,0:04:39.36,0:04:43.06,Default,,0,0,0,,对于每条法则来说 你求导数时的方向\nDialogue: 0,0:04:43.06,0:04:44.80,Default,,0,0,0,,这个箭头的方向\nDialogue: 0,0:04:46.68,0:04:49.16,Default,,0,0,0,,法则的左边与你的表达式相匹配\nDialogue: 0,0:04:49.16,0:04:53.05,Default,,0,0,0,,法则的右边就是表达式的导数\nDialogue: 0,0:04:54.02,0:04:55.65,Default,,0,0,0,,箭头是这个方向的\nDialogue: 0,0:04:57.37,0:05:00.45,Default,,0,0,0,,每条法则中\nDialogue: 0,0:05:01.24,0:05:03.72,Default,,0,0,0,,法则右边的表达式\nDialogue: 0,0:05:03.72,0:05:06.56,Default,,0,0,0,,都是求导过程中的子表达式\nDialogue: 0,0:05:06.56,0:05:10.29,Default,,0,0,0,,都是左边式子的合法子表达式\nDialogue: 0,0:05:10.60,0:05:13.25,Default,,0,0,0,,这里 我们发现 和的导数\nDialogue: 0,0:05:13.92,0:05:16.13,Default,,0,0,0,,也就是左边式子的导数\nDialogue: 0,0:05:16.13,0:05:18.38,Default,,0,0,0,,就是两部分导数之和\nDialogue: 0,0:05:20.08,0:05:24.49,Default,,0,0,0,,法则从左至右的方向是“归约规则”\nDialogue: 0,0:05:25.02,0:05:26.61,Default,,0,0,0,,问题变简单了\nDialogue: 0,0:05:27.56,0:05:31.48,Default,,0,0,0,,我把一个复杂的问题 转化成了许多小点儿的问题\nDialogue: 0,0:05:32.44,0:05:35.76,Default,,0,0,0,,然后把结果组合起来 这里用递归可以完美地解决\nDialogue: 0,0:05:36.58,0:05:40.85,Default,,0,0,0,,但如果我从另外的方向来思考\nDialogue: 0,0:05:41.81,0:05:45.13,Default,,0,0,0,,如果我想求积分的话 你会发现有很多问题\nDialogue: 0,0:05:45.24,0:05:49.09,Default,,0,0,0,,就比如 如果我想求一个和的积分\nDialogue: 0,0:05:49.21,0:05:50.81,Default,,0,0,0,,就会匹配多条法则\nDialogue: 0,0:05:50.81,0:05:52.10,Default,,0,0,0,,这条匹配\nDialogue: 0,0:05:52.48,0:05:53.65,Default,,0,0,0,,这条也匹配\nDialogue: 0,0:05:54.81,0:05:57.09,Default,,0,0,0,,我不知道该用哪个——它们之间可能不一样\nDialogue: 0,0:05:57.70,0:06:00.00,Default,,0,0,0,,我得考察两者的不同之处\nDialogue: 0,0:06:00.25,0:06:03.64,Default,,0,0,0,,所以 在这个方向上 表达式变复杂了\nDialogue: 0,0:06:04.53,0:06:06.30,Default,,0,0,0,,当表达式变复杂时\nDialogue: 0,0:06:06.30,0:06:10.56,Default,,0,0,0,,就没法保证我所选的路径一定能终止了\nDialogue: 0,0:06:10.94,0:06:13.46,Default,,0,0,0,,因为唯一的可能是偶然的约分\nDialogue: 0,0:06:14.24,0:06:18.05,Default,,0,0,0,,这也就是为什么 积分是一种复杂的搜索 而难以完成\nDialogue: 0,0:06:19.12,0:06:20.96,Default,,0,0,0,,现在我不想处理这么复杂的东西\nDialogue: 0,0:06:21.49,0:06:23.06,Default,,0,0,0,,我们先来讨论求导数\nDialogue: 0,0:06:24.14,0:06:28.13,Default,,0,0,0,,好吧 我就假设你们都大致了解这些法则了\nDialogue: 0,0:06:28.78,0:06:31.88,Default,,0,0,0,,让我们来看看能不能用程序表达这些法则\nDialogue: 0,0:06:32.22,0:06:33.72,Default,,0,0,0,,这应该很容易\nDialogue: 0,0:06:34.89,0:06:36.21,Default,,0,0,0,,信手拈来\nDialogue: 0,0:06:36.69,0:06:39.29,Default,,0,0,0,,因为 我给你们展示的是“归约规则”\nDialogue: 0,0:06:39.29,0:06:41.29,Default,,0,0,0,,这样用递归来编写会比较合适\nDialogue: 0,0:06:43.08,0:06:45.72,Default,,0,0,0,,当然 对每条法则来说就是一种情况\nDialogue: 0,0:06:46.66,0:06:47.78,Default,,0,0,0,,我们做“分情况分析”\nDialogue: 0,0:06:48.58,0:06:50.36,Default,,0,0,0,,我就这么写了\nDialogue: 0,0:06:52.88,0:06:57.69,Default,,0,0,0,,当然 我得先让大家达成共识 对吧？\nDialogue: 0,0:06:57.69,0:07:00.33,Default,,0,0,0,,你们应该意识到到我可以表示这些代数式\nDialogue: 0,0:07:00.68,0:07:03.88,Default,,0,0,0,,我可以从中抽取式子 也可以将它们组合起来\nDialogue: 0,0:07:04.24,0:07:06.49,Default,,0,0,0,,我们发明了表结构来解决这个问题\nDialogue: 0,0:07:07.52,0:07:09.14,Default,,0,0,0,,但现在我们不必关心\nDialogue: 0,0:07:09.66,0:07:12.45,Default,,0,0,0,,现在 我要编写一个程序来封装这些法则\nDialogue: 0,0:07:12.76,0:07:15.85,Default,,0,0,0,,但它不依赖于代数表达式的表示法\nDialogue: 0,0:07:20.42,0:07:28.84,Default,,0,0,0,,(DERIV EXP VAR)表示表达式EXP关于变量VAR的导数\nDialogue: 0,0:07:30.50,0:07:33.08,Default,,0,0,0,,这和函数的导数是不一样的\nDialogue: 0,0:07:34.82,0:07:38.61,Default,,0,0,0,,那个是我们上节课看到的数值近似\nDialogue: 0,0:07:39.00,0:07:40.82,Default,,0,0,0,,并不能看到函数内部\nDialogue: 0,0:07:40.82,0:07:41.89,Default,,0,0,0,,它只是一个数值\nDialogue: 0,0:07:43.09,0:07:45.18,Default,,0,0,0,,表达式的导数也是一个表达式\nDialogue: 0,0:07:45.74,0:07:47.85,Default,,0,0,0,,因此 这只是一个语法问题\nDialogue: 0,0:07:48.29,0:07:51.62,Default,,0,0,0,,我们今天要做的大多数工作 就是讨论语法\nDialogue: 0,0:07:52.33,0:07:54.12,Default,,0,0,0,,表达式的语法或类似\nDialogue: 0,0:07:54.70,0:07:55.93,Default,,0,0,0,,首先要做“分情况分析”\nDialogue: 0,0:07:57.50,0:08:01.08,Default,,0,0,0,,任何时候我们处理复杂事物 需要递归求解时\nDialogue: 0,0:08:01.08,0:08:02.64,Default,,0,0,0,,我们很可能需要“按情况分析”\nDialogue: 0,0:08:03.62,0:08:05.16,Default,,0,0,0,,通常都是这样开始的\nDialogue: 0,0:08:05.16,0:08:07.40,Default,,0,0,0,,复杂的问题都是用“按情况分析”\nDialogue: 0,0:08:08.08,0:08:09.97,Default,,0,0,0,,那么 有哪些可能（的情况）呢？\nDialogue: 0,0:08:09.97,0:08:12.53,Default,,0,0,0,,第一条法则说 如果你遇到一个常数\nDialogue: 0,0:08:16.50,0:08:17.50,Default,,0,0,0,,这里 我就是在判断\nDialogue: 0,0:08:17.50,0:08:22.22,Default,,0,0,0,,表达式EXP是否为给定变量VAR的常数（常量表达式）\nDialogue: 0,0:08:24.90,0:08:27.08,Default,,0,0,0,,是的话 结果就是0\nDialogue: 0,0:08:27.50,0:08:30.10,Default,,0,0,0,,因为导数表征的是某物的变化率\nDialogue: 0,0:08:31.76,0:08:32.65,Default,,0,0,0,,然而\nDialogue: 0,0:08:32.89,0:08:40.69,Default,,0,0,0,,如果我求导的表达式 与我关心的变量有关\nDialogue: 0,0:08:41.72,0:08:50.42,Default,,0,0,0,,如果判定表达式和变量相同\nDialogue: 0,0:08:51.14,0:08:54.52,Default,,0,0,0,,那么关于变量VAR的表达式EXP的变化率就是1\nDialogue: 0,0:08:55.50,0:08:56.54,Default,,0,0,0,,它俩相同 结果是1\nDialogue: 0,0:08:58.90,0:09:00.77,Default,,0,0,0,,当然 还可能有其它的可能性\nDialogue: 0,0:09:01.33,0:09:03.14,Default,,0,0,0,,比如说 它可能是一个和式\nDialogue: 0,0:09:03.86,0:09:05.88,Default,,0,0,0,,呃 我现在还完全知道该如何表示和式\nDialogue: 0,0:09:06.09,0:09:08.25,Default,,0,0,0,,事实上我可以 只是我还没有告诉你们\nDialogue: 0,0:09:10.34,0:09:11.78,Default,,0,0,0,,如果表达式是和式\nDialogue: 0,0:09:12.48,0:09:14.48,Default,,0,0,0,,我就假想有一种方式可以判别（和式）\nDialogue: 0,0:09:15.30,0:09:19.44,Default,,0,0,0,,这里 我要做一个表达式的类型分派\nDialogue: 0,0:09:20.77,0:09:23.57,Default,,0,0,0,,这是在构建语言时绝对必要的\nDialogue: 0,0:09:24.72,0:09:26.37,Default,,0,0,0,,因为语言由不同的表达式构成\nDialogue: 0,0:09:26.48,0:09:27.54,Default,,0,0,0,,我们马上就将看到\nDialogue: 0,0:09:27.84,0:09:31.02,Default,,0,0,0,,如何用更强大的方法 用语言去构建语言\nDialogue: 0,0:09:32.53,0:09:34.02,Default,,0,0,0,,表达式是和式吗？\nDialogue: 0,0:09:35.45,0:09:38.82,Default,,0,0,0,,如果是的话 很好 我们已经知道和式的求导法则了\nDialogue: 0,0:09:38.82,0:09:41.33,Default,,0,0,0,,即是各部分导数之和\nDialogue: 0,0:09:42.13,0:09:44.32,Default,,0,0,0,,其中一个叫做加数 另一个叫做被加数\nDialogue: 0,0:09:44.32,0:09:46.80,Default,,0,0,0,,黑板上没那么多空间写这么长的名字了\nDialogue: 0,0:09:46.80,0:09:48.40,Default,,0,0,0,,我就姑且把它们叫做 A1和A2\nDialogue: 0,0:09:49.04,0:09:50.37,Default,,0,0,0,,把它们求和\nDialogue: 0,0:09:53.53,0:09:55.68,Default,,0,0,0,,（意义不明）\nDialogue: 0,0:09:57.14,0:10:01.09,Default,,0,0,0,,是叫做被除数和除数一类的么？\nDialogue: 0,0:10:01.65,0:10:08.48,Default,,0,0,0,,将A1的导数...加上\nDialogue: 0,0:10:08.48,0:10:13.29,Default,,0,0,0,,这是关于变量VAR的表达式的加数\nDialogue: 0,0:10:14.84,0:10:22.76,Default,,0,0,0,,与A2的导数相加\nDialogue: 0,0:10:24.12,0:10:28.25,Default,,0,0,0,,这两个参数的和 变量是VAR\nDialogue: 0,0:10:32.36,0:10:34.93,Default,,0,0,0,,我们知道还有一条乘法的求导法则\nDialogue: 0,0:10:35.20,0:10:37.44,Default,,0,0,0,,也就是说 如果表达式是乘式\nDialogue: 0,0:10:43.21,0:10:46.10,Default,,0,0,0,,顺便说下 当你定义过程时 有个好习惯\nDialogue: 0,0:10:46.96,0:10:48.32,Default,,0,0,0,,就是在定义谓词时\nDialogue: 0,0:10:48.85,0:10:50.96,Default,,0,0,0,,将谓词名以问号结尾\nDialogue: 0,0:10:51.08,0:10:52.89,Default,,0,0,0,,问号本身不代表什么\nDialogue: 0,0:10:53.10,0:10:54.50,Default,,0,0,0,,但这是俗成的约定\nDialogue: 0,0:10:54.61,0:10:58.94,Default,,0,0,0,,这是人们之间约定的接口 以方便他人阅读你的脚本\nDialogue: 0,0:11:00.05,0:11:01.96,Default,,0,0,0,,我希望你在写程序的时候\nDialogue: 0,0:11:01.96,0:11:03.73,Default,,0,0,0,,当你定义谓词的时候\nDialogue: 0,0:11:04.01,0:11:05.77,Default,,0,0,0,,就是那些返回TRUE或FALSE的过程\nDialogue: 0,0:11:05.94,0:11:07.84,Default,,0,0,0,,你应该使它们的名字以问号结尾\nDialogue: 0,0:11:08.02,0:11:10.34,Default,,0,0,0,,这对Lisp无异 但对人类友好\nDialogue: 0,0:11:11.62,0:11:13.14,Default,,0,0,0,,我需要求和\nDialogue: 0,0:11:13.14,0:11:17.49,Default,,0,0,0,,因为积的导数就是...\nDialogue: 0,0:11:17.94,0:11:19.64,Default,,0,0,0,,M1*DERIV(M2)\nDialogue: 0,0:11:19.66,0:11:20.70,Default,,0,0,0,,+DERIV(M1)*M2\nDialogue: 0,0:11:23.54,0:11:27.06,Default,,0,0,0,,两者加起来\nDialogue: 0,0:11:29.64,0:11:38.33,Default,,0,0,0,,求积... 呃 就用表达式中的M1来表示（被乘数）好了\nDialogue: 0,0:11:39.85,0:11:48.97,Default,,0,0,0,,表达式中M2关于变量VAR的导数\nDialogue: 0,0:11:51.90,0:12:06.28,Default,,0,0,0,,以及 M1关于变量VAR的导数乘以\nDialogue: 0,0:12:07.10,0:12:11.92,Default,,0,0,0,,M1是这里的被乘数\nDialogue: 0,0:12:13.32,0:12:18.05,Default,,0,0,0,,乘数是表达式中的M2\nDialogue: 0,0:12:20.64,0:12:24.89,Default,,0,0,0,,求积完毕、求和完毕、乘式分析完毕\nDialogue: 0,0:12:24.96,0:12:28.02,Default,,0,0,0,,当然 在这里我可以添加更多的情况\nDialogue: 0,0:12:28.32,0:12:30.82,Default,,0,0,0,,微积分书中的完整法则\nDialogue: 0,0:12:34.80,0:12:39.45,Default,,0,0,0,,我们就是这么来封装这些法则的\nDialogue: 0,0:12:41.53,0:12:43.90,Default,,0,0,0,,如你所见 我们这里用到了大量的“按愿望思维”\nDialogue: 0,0:12:44.54,0:12:47.56,Default,,0,0,0,,我们还没有说这些（表达式）是如何表示的\nDialogue: 0,0:12:48.46,0:12:51.92,Default,,0,0,0,,现在 一旦我将其定为我的一套法则\nDialogue: 0,0:12:52.52,0:12:55.20,Default,,0,0,0,,我想是时候考虑表示法了\nDialogue: 0,0:12:55.66,0:12:56.69,Default,,0,0,0,,我们来拿捏拿捏\nDialogue: 0,0:12:57.96,0:13:00.00,Default,,0,0,0,,首先 我要用到一种“双关”思想\nDialogue: 0,0:13:00.90,0:13:02.12,Default,,0,0,0,,这种“双关”思想非常重要\nDialogue: 0,0:13:02.74,0:13:06.56,Default,,0,0,0,,它是一种强有力思想的关键\nDialogue: 0,0:13:09.62,0:13:14.41,Default,,0,0,0,,如果我想表达诸如和、积、差、商的东西\nDialogue: 0,0:13:15.22,0:13:18.62,Default,,0,0,0,,为什么不用和我程序一样的语言呢？\nDialogue: 0,0:13:20.50,0:13:23.64,Default,,0,0,0,,我程序中 代数表达式是形如\nDialogue: 0,0:13:23.98,0:13:30.45,Default,,0,0,0,,(+ (* A (* X X))\nDialogue: 0,0:13:32.60,0:13:33.80,Default,,0,0,0,,和与之类似的\nDialogue: 0,0:13:34.28,0:13:38.50,Default,,0,0,0,,(* B X)以及C\nDialogue: 0,0:13:38.50,0:13:39.97,Default,,0,0,0,,把它们加起来\nDialogue: 0,0:13:40.77,0:13:44.09,Default,,0,0,0,,现在 我的过程还不能处理多元参数\nDialogue: 0,0:13:44.93,0:13:48.46,Default,,0,0,0,,(+ (* B X) C)\nDialogue: 0,0:13:51.42,0:13:52.44,Default,,0,0,0,,这是表结构\nDialogue: 0,0:13:54.12,0:13:55.74,Default,,0,0,0,,这么做很棒 是因为\nDialogue: 0,0:13:55.90,0:13:58.33,Default,,0,0,0,,是因为这些对象都有一种性质\nDialogue: 0,0:13:58.92,0:14:01.53,Default,,0,0,0,,我知道它们的CAR部分是什么\nDialogue: 0,0:14:01.96,0:14:03.21,Default,,0,0,0,,CAR部分就是运算符\nDialogue: 0,0:14:03.92,0:14:06.38,Default,,0,0,0,,运算数是相继的CDR部分\nDialogue: 0,0:14:07.22,0:14:10.36,Default,,0,0,0,,也就是不断取表CDR部分的CAR部分\nDialogue: 0,0:14:12.48,0:14:13.88,Default,,0,0,0,,这样就使它很方便了\nDialogue: 0,0:14:14.01,0:14:16.40,Default,,0,0,0,,我需要去解析它 但它已经帮我完成了\nDialogue: 0,0:14:17.42,0:14:20.01,Default,,0,0,0,,我利用了Lisp中的内建元素\nDialogue: 0,0:14:22.66,0:14:23.77,Default,,0,0,0,,举个例子\nDialogue: 0,0:14:25.08,0:14:33.97,Default,,0,0,0,,我们用表结构来表示我所暗示的表示法吧！\nDialogue: 0,0:14:35.25,0:14:38.34,Default,,0,0,0,,我需要定义一些东西 这都暗含在这种表示法中\nDialogue: 0,0:14:38.54,0:14:40.90,Default,,0,0,0,,比如如何判定是否为常量\nDialogue: 0,0:14:41.21,0:14:42.30,Default,,0,0,0,,又怎么判断是同一个变量\nDialogue: 0,0:14:42.40,0:14:45.04,Default,,0,0,0,,我们先完成这些吧 都相当简单\nDialogue: 0,0:14:45.78,0:14:47.70,Default,,0,0,0,,这里 我要介绍一些基本过程\nDialogue: 0,0:14:48.60,0:14:50.50,Default,,0,0,0,,因为它们都是与表结构相关的\nDialogue: 0,0:14:51.98,0:14:53.46,Default,,0,0,0,,CONSTANT?谓词定义为\nDialogue: 0,0:15:02.25,0:15:04.29,Default,,0,0,0,,我所谓的常量\nDialogue: 0,0:15:04.29,0:15:07.73,Default,,0,0,0,,表达式关于变量VAR是一个常量\nDialogue: 0,0:15:09.05,0:15:11.60,Default,,0,0,0,,是一些简单的表达式\nDialogue: 0,0:15:11.60,0:15:14.46,Default,,0,0,0,,我无法再细化它 但它也不是我们关心的变量\nDialogue: 0,0:15:16.58,0:15:18.78,Default,,0,0,0,,我无法分解它 但它也不是我们关心的变量\nDialogue: 0,0:15:18.90,0:15:25.12,Default,,0,0,0,,这也并不是说 一些复杂的表达式就不是常量表达式\nDialogue: 0,0:15:25.20,0:15:28.92,Default,,0,0,0,,我只是想用这种方式考察基本常量\nDialogue: 0,0:15:29.74,0:15:33.41,Default,,0,0,0,,因此 这个谓词是几个条件的合取\nDialogue: 0,0:15:34.02,0:15:37.82,Default,,0,0,0,,AND语句允许用户组合返回TRUE或者FALSE的谓词\nDialogue: 0,0:15:38.62,0:15:46.82,Default,,0,0,0,,表达式是原子的么？--原子表达式不可以再被细分\nDialogue: 0,0:15:46.82,0:15:48.53,Default,,0,0,0,,它没有CAR部分和CDR部分\nDialogue: 0,0:15:49.45,0:15:50.21,Default,,0,0,0,,它不是表\nDialogue: 0,0:15:50.76,0:15:52.94,Default,,0,0,0,,系统中内建有特殊测试\nDialogue: 0,0:15:53.97,0:16:04.66,Default,,0,0,0,,并且表达式EXP和变量VAR在EQ?的语义下不相等\nDialogue: 0,0:16:06.82,0:16:13.36,Default,,0,0,0,,我用不能被分解的符号来表示变量\nDialogue: 0,0:16:13.90,0:16:17.22,Default,,0,0,0,,比如'X 'Y 和像这样的\nDialogue: 0,0:16:19.74,0:16:22.37,Default,,0,0,0,,当然 像这样的组合式就可以再被细分\nDialogue: 0,0:16:24.74,0:16:46.40,Default,,0,0,0,,(SAME-VAR? EXP VAR)定义为\nDialogue: 0,0:16:46.40,0:16:48.40,Default,,0,0,0,,实际上 一条原子表达式……\nDialogue: 0,0:16:48.77,0:16:59.61,Default,,0,0,0,,该表达式与讨论变量相同\nDialogue: 0,0:17:07.90,0:17:11.68,Default,,0,0,0,,我不想深入讨论这些过程内部\nDialogue: 0,0:17:12.52,0:17:15.56,Default,,0,0,0,,把这些当作基本过程\nDialogue: 0,0:17:15.77,0:17:17.08,Default,,0,0,0,,这无关紧要\nDialogue: 0,0:17:17.78,0:17:21.74,Default,,0,0,0,,我用的是语言内置的功能\nDialogue: 0,0:17:22.42,0:17:24.04,Default,,0,0,0,,我并不关心这些（具体实现）\nDialogue: 0,0:17:24.42,0:17:26.04,Default,,0,0,0,,现在 我们要如何处理和式呢？\nDialogue: 0,0:17:26.60,0:17:28.80,Default,,0,0,0,,啊哈 好戏就要上演了\nDialogue: 0,0:17:28.98,0:17:33.12,Default,,0,0,0,,和式不是原子的 它以‘+’号打头\nDialogue: 0,0:17:35.16,0:17:36.17,Default,,0,0,0,,就是这个意思\nDialogue: 0,0:17:36.65,0:17:39.77,Default,,0,0,0,,这里 我定义\nDialogue: 0,0:17:45.46,0:17:57.77,Default,,0,0,0,,表达式为和式 当它不是原子表达式\nDialogue: 0,0:18:04.57,0:18:15.45,Default,,0,0,0,,并且它的开头 表达式的CAR部分是个‘+’号\nDialogue: 0,0:18:19.74,0:18:24.04,Default,,0,0,0,,我将要引入一个你们从未见过的东西--这个引号\nDialogue: 0,0:18:25.89,0:18:28.22,Default,,0,0,0,,我这里为什么要用引号呢？\nDialogue: 0,0:18:29.48,0:18:30.52,Default,,0,0,0,,教授：说你的名字\nDialogue: 0,0:18:30.68,0:18:31.41,Default,,0,0,0,,观众：Susanna\nDialogue: 0,0:18:31.41,0:18:32.01,Default,,0,0,0,,教授：大点声儿\nDialogue: 0,0:18:32.01,0:18:32.72,Default,,0,0,0,,观众：Susanna\nDialogue: 0,0:18:33.25,0:18:34.21,Default,,0,0,0,,教授：说“你的名字”\nDialogue: 0,0:18:34.21,0:18:34.85,Default,,0,0,0,,观众：“你的名字”\nDialogue: 0,0:18:34.92,0:18:35.68,Default,,0,0,0,,教授：大点声儿\nDialogue: 0,0:18:35.77,0:18:36.61,Default,,0,0,0,,观众：“你的名字”\nDialogue: 0,0:18:36.82,0:18:37.50,Default,,0,0,0,,教授：对了\nDialogue: 0,0:18:38.28,0:18:44.56,Default,,0,0,0,,在这里我想告诉大家 英语词汇是有歧义的\nDialogue: 0,0:18:45.50,0:18:50.76,Default,,0,0,0,,我可能说 “说你的名字”\nDialogue: 0,0:18:51.97,0:18:57.21,Default,,0,0,0,,我也可能说 “说‘你的名字’”\nDialogue: 0,0:19:00.72,0:19:02.98,Default,,0,0,0,,光从说话上还无法分辨\nDialogue: 0,0:19:03.89,0:19:08.01,Default,,0,0,0,,然而书面上 我们有专门的记号--引号\nDialogue: 0,0:19:08.18,0:19:12.46,Default,,0,0,0,,用来区别这两种可能的意思\nDialogue: 0,0:19:14.00,0:19:15.64,Default,,0,0,0,,具体来说 这里\nDialogue: 0,0:19:16.49,0:19:20.84,Default,,0,0,0,,在Lisp中有用于区别这些语义的记号\nDialogue: 0,0:19:21.34,0:19:24.45,Default,,0,0,0,,如果我只是写下一个加号\nDialogue: 0,0:19:24.64,0:19:28.52,Default,,0,0,0,,我会问系统 表达式的首元素\nDialogue: 0,0:19:29.06,0:19:33.61,Default,,0,0,0,,也就是表达式的运算符 是加运算符（一个过程）么？\nDialogue: 0,0:19:34.65,0:19:35.54,Default,,0,0,0,,我并不知道\nDialogue: 0,0:19:36.22,0:19:38.16,Default,,0,0,0,,我本应该在那里写一个加运算符的\nDialogue: 0,0:19:39.37,0:19:40.44,Default,,0,0,0,,但我无法那样做\nDialogue: 0,0:19:41.34,0:19:45.88,Default,,0,0,0,,而这种方式则是问 这个符号对象是否为\nDialogue: 0,0:19:45.98,0:19:48.14,Default,,0,0,0,,代表加运算符的符号\nDialogue: 0,0:19:49.57,0:19:51.92,Default,,0,0,0,,这才是我想要问和知道的问题\nDialogue: 0,0:19:52.92,0:19:54.45,Default,,0,0,0,,在我们深入讨论之前\nDialogue: 0,0:19:54.45,0:19:57.81,Default,,0,0,0,,我想要指出 “引用”是一个复杂的概念\nDialogue: 0,0:19:58.85,0:20:01.84,Default,,0,0,0,,语言中引入这个概念将会造成许多麻烦\nDialogue: 0,0:20:03.57,0:20:05.04,Default,,0,0,0,,请看下面这张幻灯片\nDialogue: 0,0:20:06.38,0:20:09.49,Default,,0,0,0,,这里这个推论没有问题\nDialogue: 0,0:20:11.62,0:20:17.04,Default,,0,0,0,,这是说 Alyssa聪明而Alyssa是George的妈妈\nDialogue: 0,0:20:17.40,0:20:20.60,Default,,0,0,0,,通过IS建立了一个等式\nDialogue: 0,0:20:22.13,0:20:26.30,Default,,0,0,0,,我们可以从这两个陈述推论出 George妈妈很聪明\nDialogue: 0,0:20:27.32,0:20:33.16,Default,,0,0,0,,这是因为我们总可以在表达式中等价替换\nDialogue: 0,0:20:34.09,0:20:35.16,Default,,0,0,0,,真是这样吗？\nDialogue: 0,0:20:36.52,0:20:40.37,Default,,0,0,0,,这个例子说 “Chicago”有七个字母\nDialogue: 0,0:20:41.12,0:20:44.86,Default,,0,0,0,,引用则是强调我讨论的是单词“Chicago”\nDialogue: 0,0:20:44.86,0:20:46.86,Default,,0,0,0,,而不是单词所代表的意思\nDialogue: 0,0:20:49.82,0:20:52.77,Default,,0,0,0,,这里说 Chicago是Illinois州最大的城市\nDialogue: 0,0:20:54.61,0:20:55.80,Default,,0,0,0,,而（代换的）结果是……\nDialogue: 0,0:20:55.80,0:20:59.09,Default,,0,0,0,,我可能会得到 Illinois州最大的城市有七个字母\nDialogue: 0,0:20:59.32,0:21:01.06,Default,,0,0,0,,这显然是错的\nDialogue: 0,0:21:05.16,0:21:07.17,Default,,0,0,0,,喔！手写笔好使了\nDialogue: 0,0:21:09.29,0:21:12.24,Default,,0,0,0,,所以 一旦我们有了（引用）这样的东西\nDialogue: 0,0:21:12.48,0:21:14.49,Default,,0,0,0,,我们的语言就会变得复杂\nDialogue: 0,0:21:14.49,0:21:18.34,Default,,0,0,0,,因为我们对于语言的一些操作就不再正确\nDialogue: 0,0:21:18.34,0:21:20.76,Default,,0,0,0,,比如通过等价代换来得到正确答案\nDialogue: 0,0:21:21.29,0:21:23.50,Default,,0,0,0,,如果不小心地操作就会出错\nDialogue: 0,0:21:24.49,0:21:27.34,Default,,0,0,0,,在一个引用不透明的上下文中 我们无法进行代换\nDialogue: 0,0:21:27.89,0:21:32.64,Default,,0,0,0,,引用就是引用不透明上下文的典型\nDialogue: 0,0:21:33.17,0:21:35.28,Default,,0,0,0,,如果你知道那是什么意思……你可以成为一位哲学家\nDialogue: 0,0:21:35.42,0:21:37.02,Default,,0,0,0,,或许我们之中就有一位\nDialogue: 0,0:21:37.53,0:21:41.32,Default,,0,0,0,,言归正传 我们继续\nDialogue: 0,0:21:41.32,0:21:44.98,Default,,0,0,0,,现在我们对一个有2000年历史的问题至少有了操作上的理解\nDialogue: 0,0:21:45.26,0:21:48.13,Default,,0,0,0,,关于名称、提及和等等类似的问题\nDialogue: 0,0:21:52.32,0:22:01.60,Default,,0,0,0,,我得定义如何把两个数加起来 (DEFINE (MAKE-SUM A1 A2))\nDialogue: 0,0:22:02.12,0:22:03.62,Default,,0,0,0,,我简单实现一下\nDialogue: 0,0:22:03.62,0:22:11.96,Default,,0,0,0,,'+、A1、A2构成列表\nDialogue: 0,0:22:13.86,0:22:17.37,Default,,0,0,0,,我可以决定如何取出第一个元素\nDialogue: 0,0:22:21.84,0:22:25.32,Default,,0,0,0,,(DEFINE A1 CADR)\nDialogue: 0,0:22:33.88,0:22:35.90,Default,,0,0,0,,这里又给大家介绍了一个基本过程\nDialogue: 0,0:22:36.17,0:22:39.10,Default,,0,0,0,,这个是取出某物CDR部分的CAR部分\nDialogue: 0,0:22:39.80,0:22:44.53,Default,,0,0,0,,大家或许会好奇 这些基本过程为什么叫做CAR和CDR\nDialogue: 0,0:22:44.66,0:22:48.42,Default,,0,0,0,,而且传承了下来 尽管叫做LEFT和RIGHT会好一点\nDialogue: 0,0:22:48.76,0:22:50.44,Default,,0,0,0,,我们本可以那样叫的\nDialogue: 0,0:22:51.28,0:22:56.25,Default,,0,0,0,,呃 其实 这个名字来自于很久以前 当发明Lisp时\nDialogue: 0,0:22:56.36,0:23:00.80,Default,,0,0,0,,我想大概是58年的样子 是在类似于704之类的机子上实现的\nDialogue: 0,0:23:00.80,0:23:05.41,Default,,0,0,0,,这个机器有个地址寄存器和减量寄存器\nDialogue: 0,0:23:05.41,0:23:08.17,Default,,0,0,0,,而这些就是地址寄存器和减量寄存器的值\nDialogue: 0,0:23:08.17,0:23:09.37,Default,,0,0,0,,所以这是历史遗留问题\nDialogue: 0,0:23:09.64,0:23:11.28,Default,,0,0,0,,但是这些名字为什么又延续下来了呢？\nDialogue: 0,0:23:11.74,0:23:14.76,Default,,0,0,0,,这是因为Lisp程序员喜欢用电话交流\nDialogue: 0,0:23:15.68,0:23:19.60,Default,,0,0,0,,要是你有一长串的CAR和CDR序列 你就可能说“CDADDEDR”\nDialogue: 0,0:23:21.01,0:23:22.32,Default,,0,0,0,,这是可以理解的\nDialogue: 0,0:23:22.32,0:23:27.02,Default,,0,0,0,,但是左边的右边的右边的左边就不是那么清楚了\nDialogue: 0,0:23:27.60,0:23:30.02,Default,,0,0,0,,这就是我们为什么有这些黑话\nDialogue: 0,0:23:30.54,0:23:34.14,Default,,0,0,0,,典型的Lisp系统 默认定义到第四层\nDialogue: 0,0:23:38.66,0:23:47.05,Default,,0,0,0,,而定义A2为……当然 如果我们考察这些表达式中的一个\nDialogue: 0,0:23:47.36,0:23:52.14,Default,,0,0,0,,比如(+ 3 5)\nDialogue: 0,0:23:52.58,0:24:10.45,Default,,0,0,0,,这个实际上是一个包含有'+、数3和数5的表\nDialogue: 0,0:24:11.72,0:24:15.18,Default,,0,0,0,,表的CAR部分是'+\nDialogue: 0,0:24:16.13,0:24:18.21,Default,,0,0,0,,CDR部分的CAR部分\nDialogue: 0,0:24:18.21,0:24:20.21,Default,,0,0,0,,也就是先取CDR部分 然后再取CAR部分\nDialogue: 0,0:24:20.21,0:24:22.21,Default,,0,0,0,,这就是我如何取得3的 也就是第一个参数\nDialogue: 0,0:24:22.52,0:24:25.69,Default,,0,0,0,,CDR的CDR部分的CAR部分 就是这个……数5\nDialogue: 0,0:24:28.69,0:24:33.66,Default,,0,0,0,,当然类似地 对于乘式我可以这样定义\nDialogue: 0,0:24:35.22,0:24:36.56,Default,,0,0,0,,我快速地演示一下\nDialogue: 0,0:24:48.97,0:24:50.64,Default,,0,0,0,,(DEFINE (PRODUCT? EXP))\nDialogue: 0,0:24:51.05,0:24:54.69,Default,,0,0,0,,如果它不是原子的 而且\nDialogue: 0,0:25:01.41,0:25:14.14,Default,,0,0,0,,EXP的CAR部分与用于表示乘法的符号'*在 EQ?的语义下相等\nDialogue: 0,0:25:15.64,0:25:32.00,Default,,0,0,0,,(DEFINE (MAKE-PRODUCT M1 M2))\nDialogue: 0,0:25:34.42,0:25:39.30,Default,,0,0,0,,(LIST '* M1 M2)\nDialogue: 0,0:25:40.82,0:25:56.81,Default,,0,0,0,,并定义M1为CADR M2为CADDR\nDialogue: 0,0:26:00.09,0:26:02.38,Default,,0,0,0,,当你说行话的时候 你就上道了\nDialogue: 0,0:26:02.53,0:26:05.53,Default,,0,0,0,,你可以取表的CDR 也可以把它们组合起来\nDialogue: 0,0:26:06.29,0:26:10.10,Default,,0,0,0,,现在 我们有了原理上完整的求导程序了\nDialogue: 0,0:26:10.10,0:26:11.70,Default,,0,0,0,,如果需要的话 你也可以添加更多的规则\nDialogue: 0,0:26:12.21,0:26:13.93,Default,,0,0,0,,它又要怎么用呢？\nDialogue: 0,0:26:14.64,0:26:16.77,Default,,0,0,0,,我先把这个笔迹清了\nDialogue: 0,0:26:17.80,0:26:20.82,Default,,0,0,0,,恩 假设我在这里定义FOO为\nDialogue: 0,0:26:22.16,0:26:30.38,Default,,0,0,0,,定义FOO为A*X^2+B*X+C\nDialogue: 0,0:26:30.54,0:26:32.08,Default,,0,0,0,,跟我们这里看到的是一样的\nDialogue: 0,0:26:32.08,0:26:36.36,Default,,0,0,0,,这里是用更习见的记号书写的代数表达式\nDialogue: 0,0:26:37.84,0:26:41.60,Default,,0,0,0,,那么 表达式FOO关于X的导数 结果在这里\nDialogue: 0,0:26:43.46,0:26:45.26,Default,,0,0,0,,真是乱得一团糟\nDialogue: 0,0:26:46.16,0:26:49.22,Default,,0,0,0,,我期望答案是2*A*X+B\nDialogue: 0,0:26:50.68,0:26:53.44,Default,,0,0,0,,虽然与结果等价 但它并不是我们希望的结果\nDialogue: 0,0:26:54.58,0:26:55.22,Default,,0,0,0,,这是什么呢？\nDialogue: 0,0:26:55.97,0:26:59.96,Default,,0,0,0,,我们最初有什么？\nDialogue: 0,0:27:00.50,0:27:04.30,Default,,0,0,0,,我求X*X的导数\nDialogue: 0,0:27:04.69,0:27:10.53,Default,,0,0,0,,答案是X*1+1*X 这当然没错\nDialogue: 0,0:27:12.73,0:27:15.66,Default,,0,0,0,,这就是乘数的导数乘以被乘数加上乘数乘以被乘数的导数\nDialogue: 0,0:27:17.22,0:27:28.37,Default,,0,0,0,,那就是2X、A*2X就是2AX、0X^2省去 再加上0和这里的一大堆0\nDialogue: 0,0:27:28.96,0:27:30.12,Default,,0,0,0,,答案是对的\nDialogue: 0,0:27:30.12,0:27:35.14,Default,,0,0,0,,当我们还需要用户额外检验一下 真是糟糕投了\nDialogue: 0,0:27:35.56,0:27:37.26,Default,,0,0,0,,我们下一节再考虑这个内容\nDialogue: 0,0:27:37.68,0:27:38.61,Default,,0,0,0,,有疑问吗？\nDialogue: 0,0:27:42.77,0:27:43.45,Default,,0,0,0,,请说\nDialogue: 0,0:27:43.89,0:27:46.69,Default,,0,0,0,,观众：写加号时不加引号\nDialogue: 0,0:27:46.69,0:27:50.82,Default,,0,0,0,,是表示引用加那个过程么？\nDialogue: 0,0:27:50.82,0:27:55.42,Default,,0,0,0,,如果有需要的话 是否能在两个过程之间进行比较\nDialogue: 0,0:27:56.16,0:27:57.08,Default,,0,0,0,,教授：问得好！\nDialogue: 0,0:27:57.45,0:28:02.26,Default,,0,0,0,,如果我这里不用左引号将这个引住\nDialogue: 0,0:28:03.88,0:28:07.13,Default,,0,0,0,,如果我这里不用引号\nDialogue: 0,0:28:07.33,0:28:14.20,Default,,0,0,0,,那么这里我就会引用定义好的加法过程\nDialogue: 0,0:28:15.38,0:28:24.88,Default,,0,0,0,,实际上 我可以比较两个过程是否同一\nDialogue: 0,0:28:24.88,0:28:27.45,Default,,0,0,0,,现在很难从语义上解释\nDialogue: 0,0:28:27.85,0:28:29.37,Default,,0,0,0,,我现在不想考虑这个问题\nDialogue: 0,0:28:29.89,0:28:32.40,Default,,0,0,0,,因为我不知道比较过程需要什么\nDialogue: 0,0:28:32.40,0:28:34.40,Default,,0,0,0,,这样做没有意义是有很多原因的\nDialogue: 0,0:28:35.52,0:28:37.53,Default,,0,0,0,,然而 这些符号我们是可以理解的\nDialogue: 0,0:28:38.54,0:28:40.56,Default,,0,0,0,,这也是我为什么我要将它们引住\nDialogue: 0,0:28:41.16,0:28:43.70,Default,,0,0,0,,我想讨论出现在这些代码中的符号\nDialogue: 0,0:28:46.16,0:28:46.92,Default,,0,0,0,,还有什么问题么？\nDialogue: 0,0:28:48.52,0:28:51.86,Default,,0,0,0,,好吧 休息一下 谢谢大家\nDialogue: 0,0:28:55.12,0:29:00.66,Default,,0,0,0,,[音乐]\nDialogue: 0,0:29:00.68,0:29:04.34,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:29:04.34,0:29:06.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:29:12.21,0:29:19.17,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:29:20.09,0:29:24.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}符号化导数系统、引用\nDialogue: 0,0:29:29.86,0:29:30.92,Default,,0,0,0,,教授：好 我们继续\nDialogue: 0,0:29:31.46,0:29:37.76,Default,,0,0,0,,我们编写了一个貌似可行的代数表达式求导程序\nDialogue: 0,0:29:38.20,0:29:41.56,Default,,0,0,0,,这个程序是不完整的 你需要添加一些规则\nDialogue: 0,0:29:42.13,0:29:47.74,Default,,0,0,0,,你可能需要加强这个系统 使得它能够处理\nDialogue: 0,0:29:47.76,0:29:49.70,Default,,0,0,0,,多元加法和多元乘法\nDialogue: 0,0:29:49.89,0:29:51.38,Default,,0,0,0,,这些都相当简单\nDialogue: 0,0:29:52.73,0:29:56.93,Default,,0,0,0,,但这里面也有一些瑕疵\nDialogue: 0,0:29:57.48,0:30:02.37,Default,,0,0,0,,回到这张幻灯片来\nDialogue: 0,0:30:02.94,0:30:08.60,Default,,0,0,0,,我们发现 得到的表达式相当乱\nDialogue: 0,0:30:08.88,0:30:11.01,Default,,0,0,0,,这个表达式非常糟糕\nDialogue: 0,0:30:11.46,0:30:13.10,Default,,0,0,0,,我们是怎么得到这样的表达式的？\nDialogue: 0,0:30:13.84,0:30:15.50,Default,,0,0,0,,为什么是这样呢？\nDialogue: 0,0:30:16.84,0:30:18.74,Default,,0,0,0,,我们详细地分析一下这个表达式\nDialogue: 0,0:30:18.92,0:30:20.76,Default,,0,0,0,,找出这些片段都是出自哪里\nDialogue: 0,0:30:21.69,0:30:24.56,Default,,0,0,0,,如我们所见 这里的和式\nDialogue: 0,0:30:24.56,0:30:26.56,Default,,0,0,0,,也就是上一小节中给你们提到的\nDialogue: 0,0:30:27.12,0:30:29.09,Default,,0,0,0,,(+ (* X 1) (* 1 X))\nDialogue: 0,0:30:29.58,0:30:31.38,Default,,0,0,0,,是这个乘式的导数\nDialogue: 0,0:30:32.52,0:30:36.41,Default,,0,0,0,,也就是A乘上这个的积 这里A不是X的函数\nDialogue: 0,0:30:36.41,0:30:38.41,Default,,0,0,0,,因此A关于X是一个常数\nDialogue: 0,0:30:39.04,0:30:44.53,Default,,0,0,0,,导数为这个和式 从这里到这里 再到这里\nDialogue: 0,0:30:44.80,0:30:48.89,Default,,0,0,0,,因为这个是乘数乘以被乘数的导数\nDialogue: 0,0:30:49.57,0:30:54.45,Default,,0,0,0,,加上被乘数乘以乘数的导数\nDialogue: 0,0:30:54.66,0:30:59.06,Default,,0,0,0,,我们在黑板上的程序告诉我们确实是这样的\nDialogue: 0,0:31:00.65,0:31:05.36,Default,,0,0,0,,当然 这里B乘以X的积\nDialogue: 0,0:31:05.49,0:31:09.81,Default,,0,0,0,,被化成了 B*1+0*X\nDialogue: 0,0:31:10.81,0:31:16.06,Default,,0,0,0,,因为B不是X的函数\nDialogue: 0,0:31:16.46,0:31:18.56,Default,,0,0,0,,因此B的导数为0\nDialogue: 0,0:31:18.77,0:31:21.48,Default,,0,0,0,,而X对自己求导则为1\nDialogue: 0,0:31:23.06,0:31:28.64,Default,,0,0,0,,这里的加法化成了 这两个导数的和\nDialogue: 0,0:31:29.37,0:31:33.50,Default,,0,0,0,,所以这里 我想告诉你和之前一样的东西\nDialogue: 0,0:31:33.66,0:31:35.89,Default,,0,0,0,,也就是在讲斐波那契数那时候\nDialogue: 0,0:31:37.77,0:31:39.49,Default,,0,0,0,,所谓的 “过程的形状”\nDialogue: 0,0:31:41.38,0:31:46.44,Default,,0,0,0,,就是通过局部的规则向低层次展开\nDialogue: 0,0:31:48.05,0:31:52.57,Default,,0,0,0,,也就是过程代表了一系列用于演进过程局部规则\nDialogue: 0,0:31:53.36,0:32:00.09,Default,,0,0,0,,这里 过程还遗留了一些东西--也就是答案\nDialogue: 0,0:32:00.25,0:32:06.26,Default,,0,0,0,,这是通过遍历表达式的树结构构造出来的\nDialogue: 0,0:32:08.41,0:32:12.61,Default,,0,0,0,,答案中的每个部分对应问题中的某个部分\nDialogue: 0,0:32:14.46,0:32:17.78,Default,,0,0,0,,比如说 现在我们考察FOO的导数\nDialogue: 0,0:32:17.78,0:32:19.65,Default,,0,0,0,,也就是AX^2+BX+C\nDialogue: 0,0:32:19.84,0:32:23.05,Default,,0,0,0,,并另令自变量 比如像这里\nDialogue: 0,0:32:24.14,0:32:27.48,Default,,0,0,0,,我们令A为自变量 求FOO的导数\nDialogue: 0,0:32:28.10,0:32:31.77,Default,,0,0,0,,这都非常相似 实际上 它们是同样的代数表达式\nDialogue: 0,0:32:32.45,0:32:35.24,Default,,0,0,0,,只是它们之中0和1的位置不一样罢了\nDialogue: 0,0:32:36.06,0:32:38.60,Default,,0,0,0,,这是因为在这个树结构的遍历中\nDialogue: 0,0:32:38.97,0:32:43.85,Default,,0,0,0,,只可能是CONSTANT?和SAME-VAR?会因变量的不同\nDialogue: 0,0:32:44.28,0:32:45.81,Default,,0,0,0,,而造成不同结果\nDialogue: 0,0:32:48.26,0:32:52.09,Default,,0,0,0,,回到黑板上来再看看\nDialogue: 0,0:32:52.65,0:32:57.49,Default,,0,0,0,,我们在求和式或乘式的导数时根本没有发挥的余地\nDialogue: 0,0:32:58.08,0:33:04.48,Default,,0,0,0,,真正可以做文章的地方 则是表达式和自变量\nDialogue: 0,0:33:04.80,0:33:10.10,Default,,0,0,0,,以及对于那些短小的表达式 是否为关于自变量的常量\nDialogue: 0,0:33:10.36,0:33:12.41,Default,,0,0,0,,就是这些地方导致了不同的0和1的产生\nDialogue: 0,0:33:12.69,0:33:14.49,Default,,0,0,0,,回过头来看这张幻灯\nDialogue: 0,0:33:15.12,0:33:18.16,Default,,0,0,0,,这里就出现了“0”\nDialogue: 0,0:33:18.37,0:33:22.74,Default,,0,0,0,,这里是求FOO(A)的导数时得到的“1”\nDialogue: 0,0:33:22.96,0:33:24.86,Default,,0,0,0,,我们得到了X^2\nDialogue: 0,0:33:24.96,0:33:32.53,Default,,0,0,0,,这个1是X*X关于X的导数 关于B求导时1变成了0\nDialogue: 0,0:33:32.64,0:33:34.89,Default,,0,0,0,,这里 我们求FOO关于C的导数\nDialogue: 0,0:33:36.78,0:33:39.30,Default,,0,0,0,,但是这些表达式的轮廓是一致的\nDialogue: 0,0:33:40.54,0:33:43.96,Default,,0,0,0,,看看这些轮廓 都是相同的\nDialogue: 0,0:33:50.37,0:33:52.28,Default,,0,0,0,,那么 难道是我们的规则出了问题？\nDialogue: 0,0:33:53.58,0:33:55.02,Default,,0,0,0,,不 这些规则都对\nDialogue: 0,0:33:56.12,0:33:57.77,Default,,0,0,0,,我们曾经遇到过这种问题\nDialogue: 0,0:33:58.06,0:34:03.53,Default,,0,0,0,,你将会发现 这其中缺乏一些非常好的思想\nDialogue: 0,0:34:06.32,0:34:09.74,Default,,0,0,0,,昨天 我们在考察有理数时\nDialogue: 0,0:34:12.12,0:34:14.48,Default,,0,0,0,,想要得到3/4却得到6/8\nDialogue: 0,0:34:14.97,0:34:16.49,Default,,0,0,0,,答案没有化简\nDialogue: 0,0:34:18.09,0:34:20.90,Default,,0,0,0,,当然 当下的问题也非常类似\nDialogue: 0,0:34:21.18,0:34:25.41,Default,,0,0,0,,我想把不相同的表达式通过化简来使相同\nDialogue: 0,0:34:27.57,0:34:31.89,Default,,0,0,0,,当然 有理数加法和乘法的规则依然正确\nDialogue: 0,0:34:33.97,0:34:37.41,Default,,0,0,0,,因此这里 我们依葫芦画瓢\nDialogue: 0,0:34:37.78,0:34:39.89,Default,,0,0,0,,上次能行的办法 这次也没问题\nDialogue: 0,0:34:40.53,0:34:42.05,Default,,0,0,0,,也就是改换一下它的表示\nDialogue: 0,0:34:43.13,0:34:46.44,Default,,0,0,0,,或许在将其表示出来时我们可以进行\nDialogue: 0,0:34:47.88,0:34:49.78,Default,,0,0,0,,一步产生简化表示的步骤\nDialogue: 0,0:34:50.17,0:34:51.73,Default,,0,0,0,,当然啦 这也不是万用万灵\nDialogue: 0,0:34:52.49,0:34:54.14,Default,,0,0,0,,我也不想证明它是万能的\nDialogue: 0,0:34:55.12,0:35:00.44,Default,,0,0,0,,但这也是控制复杂度的一招妙计\nDialogue: 0,0:35:01.46,0:35:03.85,Default,,0,0,0,,我们小心翼翼地解决这些问题\nDialogue: 0,0:35:04.30,0:35:07.20,Default,,0,0,0,,我们所做的 就是把问题划分为几个部分\nDialogue: 0,0:35:07.57,0:35:08.73,Default,,0,0,0,,分别是求导规则\nDialogue: 0,0:35:11.32,0:35:15.80,Default,,0,0,0,,和在这种层面上的一般代数规则\nDialogue: 0,0:35:16.38,0:35:21.22,Default,,0,0,0,,然后就有一道抽象屏障\nDialogue: 0,0:35:22.48,0:35:33.49,Default,,0,0,0,,这里是代数表达式的表示--表结构\nDialogue: 0,0:35:37.33,0:35:42.56,Default,,0,0,0,,在这道屏障中 我定义了接口过程\nDialogue: 0,0:35:43.25,0:35:49.82,Default,,0,0,0,,比如 CONSTANT? SAME-VAR?\nDialogue: 0,0:35:54.60,0:35:58.72,Default,,0,0,0,,又比如 SUM? MAKE-SUM\nDialogue: 0,0:36:02.22,0:36:05.57,Default,,0,0,0,,还有 A1 A2\nDialogue: 0,0:36:06.60,0:36:08.58,Default,,0,0,0,,还有 PRODUCT? 之类的东西\nDialogue: 0,0:36:08.74,0:36:11.90,Default,,0,0,0,,我所需要的、针对各式代数表达式的东西\nDialogue: 0,0:36:12.94,0:36:19.14,Default,,0,0,0,,构筑这些屏障我可以随意地改换表示法\nDialogue: 0,0:36:20.14,0:36:23.20,Default,,0,0,0,,而不用改变在某种表示法下编写的规则\nDialogue: 0,0:36:25.04,0:36:29.08,Default,,0,0,0,,如果我能通过改变表示法来解决问题\nDialogue: 0,0:36:30.38,0:36:34.52,Default,,0,0,0,,那么把问题分解为两个部分则帮了我大忙\nDialogue: 0,0:36:35.65,0:36:37.54,Default,,0,0,0,,好吧 举一个非常简单的例子\nDialogue: 0,0:36:38.82,0:36:40.08,Default,,0,0,0,,我们的问题是什么？\nDialogue: 0,0:36:40.26,0:36:43.61,Default,,0,0,0,,回到这张幻灯片来\nDialogue: 0,0:36:44.50,0:36:47.34,Default,,0,0,0,,看这里 哦 这相当糟糕\nDialogue: 0,0:36:47.62,0:36:51.86,Default,,0,0,0,,这里是一个表达式与“0”的和\nDialogue: 0,0:36:53.14,0:36:56.66,Default,,0,0,0,,毋庸置疑这应该是该表达式本身\nDialogue: 0,0:36:57.21,0:37:01.90,Default,,0,0,0,,为什么这里还会有加号？\nDialogue: 0,0:37:03.38,0:37:04.57,Default,,0,0,0,,这其实可以更智能点\nDialogue: 0,0:37:05.56,0:37:10.08,Default,,0,0,0,,又比如说这里 是某表达式与“1”的积\nDialogue: 0,0:37:11.16,0:37:12.29,Default,,0,0,0,,这和之前一个道理\nDialogue: 0,0:37:12.86,0:37:15.68,Default,,0,0,0,,又像这里 与“0”相乘显然是“0”\nDialogue: 0,0:37:17.86,0:37:19.52,Default,,0,0,0,,因此我们也不用去构造这些式子了\nDialogue: 0,0:37:21.44,0:37:22.62,Default,,0,0,0,,我们为什么不这么做呢？\nDialogue: 0,0:37:23.66,0:37:27.96,Default,,0,0,0,,我们需要去修改表示法 基本上就是那里了\nDialogue: 0,0:37:37.40,0:37:41.84,Default,,0,0,0,,定义 MAKE-SUM 为\nDialogue: 0,0:37:42.05,0:37:43.76,Default,,0,0,0,,呃 现在就不是那么简单了\nDialogue: 0,0:37:44.00,0:37:50.40,Default,,0,0,0,,除非是有必要 否则我不会简单地把加号和式子组合成表\nDialogue: 0,0:37:51.72,0:37:53.05,Default,,0,0,0,,那么 还有哪些可能呢？\nDialogue: 0,0:37:54.56,0:37:58.53,Default,,0,0,0,,如果……这里有一些可能的情况\nDialogue: 0,0:37:59.38,0:38:08.20,Default,,0,0,0,,如果都是数值的话 如果A1是数值的话\nDialogue: 0,0:38:09.05,0:38:10.93,Default,,0,0,0,,这个基本过程我刚刚提到过\nDialogue: 0,0:38:10.93,0:38:13.18,Default,,0,0,0,,也就是用来检测参数是否为数值\nDialogue: 0,0:38:15.38,0:38:23.82,Default,,0,0,0,,并且A2也是数值的话 也就是A2不是符号表达式\nDialogue: 0,0:38:24.45,0:38:26.20,Default,,0,0,0,,那么我们就直接把它们加起来\nDialogue: 0,0:38:26.45,0:38:29.92,Default,,0,0,0,,结果就是A1加上A2的和\nDialogue: 0,0:38:32.32,0:38:33.98,Default,,0,0,0,,我并不是检查它们代表数值\nDialogue: 0,0:38:33.98,0:38:35.98,Default,,0,0,0,,这里所有的符号都代表数值\nDialogue: 0,0:38:37.33,0:38:41.22,Default,,0,0,0,,就比如 我想要考察的是这个东西是否为数值3\nDialogue: 0,0:38:43.40,0:38:44.40,Default,,0,0,0,,另一种情况\nDialogue: 0,0:38:48.77,0:38:59.61,Default,,0,0,0,,假设A1是数值 并且为0\nDialogue: 0,0:39:04.20,0:39:06.38,Default,,0,0,0,,那么答案就是A2\nDialogue: 0,0:39:06.93,0:39:08.68,Default,,0,0,0,,不用再构造什么\nDialogue: 0,0:39:10.98,0:39:23.41,Default,,0,0,0,,如果A2是数值 并且为0\nDialogue: 0,0:39:27.16,0:39:28.90,Default,,0,0,0,,那么答案就是A1\nDialogue: 0,0:39:30.04,0:39:33.65,Default,,0,0,0,,如果没有比这些更好的情况\nDialogue: 0,0:39:34.13,0:39:35.61,Default,,0,0,0,,我就需要构造一个表\nDialogue: 0,0:39:37.86,0:39:42.86,Default,,0,0,0,,构造一个用于表示答案的表\nDialogue: 0,0:39:44.13,0:39:52.33,Default,,0,0,0,,其中有 '+、A1和A2\nDialogue: 0,0:39:58.66,0:40:01.65,Default,,0,0,0,,当然 积的导数也可以类比此法\nDialogue: 0,0:40:03.01,0:40:05.04,Default,,0,0,0,,这里 我就不细讲了\nDialogue: 0,0:40:05.44,0:40:07.24,Default,,0,0,0,,我就直接在黑板上写出结果\nDialogue: 0,0:40:07.65,0:40:09.80,Default,,0,0,0,,这并不是很重要 你们已经了解它的思想了\nDialogue: 0,0:40:10.76,0:40:11.61,Default,,0,0,0,,非常简明\nDialogue: 0,0:40:12.86,0:40:19.89,Default,,0,0,0,,现在 我们来看看用这种方式改造程序后 效果如何\nDialogue: 0,0:40:21.68,0:40:27.88,Default,,0,0,0,,哦 这是修改表达式构造函数后的求导结果\nDialogue: 0,0:40:28.98,0:40:32.21,Default,,0,0,0,,对同样地FOO求导：AX^2+BX+C\nDialogue: 0,0:40:33.28,0:40:40.70,Default,,0,0,0,,我得到了 2AX+B\nDialogue: 0,0:40:40.70,0:40:42.10,Default,,0,0,0,,虽然它并没有化到最简\nDialogue: 0,0:40:42.60,0:40:44.53,Default,,0,0,0,,我应该合并同类项和求和\nDialogue: 0,0:40:45.06,0:40:46.08,Default,,0,0,0,,但这又是另外一回事了\nDialogue: 0,0:40:47.12,0:40:51.86,Default,,0,0,0,,当然啦 完成这个功能的代码就大而复杂了\nDialogue: 0,0:40:52.28,0:40:55.28,Default,,0,0,0,,代数化简 是一项繁复的工作\nDialogue: 0,0:40:56.37,0:41:00.13,Default,,0,0,0,,你们可能听过MIT以前开发的一个非常出名的程序 MAXIMA\nDialogue: 0,0:41:00.42,0:41:03.14,Default,,0,0,0,,它有5000页的LISP代码\nDialogue: 0,0:41:03.92,0:41:06.50,Default,,0,0,0,,大部分是代数化简的操作\nDialogue: 0,0:41:08.08,0:41:12.21,Default,,0,0,0,,这里是FOO的导数\nDialogue: 0,0:41:12.21,0:41:16.86,Default,,0,0,0,,要是我的话 我会在初等微积分课上讲讲“改换主变量”这个东西\nDialogue: 0,0:41:18.38,0:41:22.49,Default,,0,0,0,,以A为自变量 FOO的导数则是X*X\nDialogue: 0,0:41:22.80,0:41:23.80,Default,,0,0,0,,看起来还不差\nDialogue: 0,0:41:24.74,0:41:27.53,Default,,0,0,0,,以B为自变量 FOO的导数则是X本身\nDialogue: 0,0:41:28.06,0:41:30.12,Default,,0,0,0,,以C为自变量 FOO的导数则为“1”\nDialogue: 0,0:41:30.70,0:41:32.04,Default,,0,0,0,,我对这些结果很满意\nDialogue: 0,0:41:34.10,0:41:39.01,Default,,0,0,0,,你所看到的 都是精心设计、仔细规划的例子\nDialogue: 0,0:41:39.56,0:41:42.60,Default,,0,0,0,,用以展示如何操作代数表达式\nDialogue: 0,0:41:42.96,0:41:47.93,Default,,0,0,0,,我们如何不用具体的语法 而用抽象的语法抽象地进行\nDialogue: 0,0:41:49.21,0:41:56.29,Default,,0,0,0,,以及我们如何使用抽象屏障控制构造这些表达式\nDialogue: 0,0:41:57.80,0:42:00.41,Default,,0,0,0,,真正的奥义并不是如此的简单\nDialogue: 0,0:42:01.00,0:42:04.45,Default,,0,0,0,,实际上 真正的奥义在于我在操作这些表达式时\nDialogue: 0,0:42:04.45,0:42:06.72,Default,,0,0,0,,代数表达式和代码表达式--\nDialogue: 0,0:42:06.72,0:42:07.97,Default,,0,0,0,,回过头来看看幻灯片\nDialogue: 0,0:42:08.08,0:42:10.52,Default,,0,0,0,,都是同一种Lisp表达式\nDialogue: 0,0:42:12.02,0:42:12.97,Default,,0,0,0,,这样一语双关 一石二鸟\nDialogue: 0,0:42:13.82,0:42:21.49,Default,,0,0,0,,我用表示代码相同的方法来作为我的表示法\nDialogue: 0,0:42:22.89,0:42:26.52,Default,,0,0,0,,为了要这样做 我得付出点代价\nDialogue: 0,0:42:26.90,0:42:30.34,Default,,0,0,0,,我需要使用类似于“引用”的东西\nDialogue: 0,0:42:30.97,0:42:38.17,Default,,0,0,0,,这是因为 我的语言可以编写讨论语言表达式的表达式\nDialogue: 0,0:42:39.76,0:42:43.22,Default,,0,0,0,,我需要有某种东西指出 这个是我需要讨论的表达式\nDialogue: 0,0:42:43.76,0:42:46.13,Default,,0,0,0,,而不是说 （去求）这个表达式的值\nDialogue: 0,0:42:47.20,0:42:48.44,Default,,0,0,0,,我想要的是前者\nDialogue: 0,0:42:51.34,0:42:55.36,Default,,0,0,0,,引用阻止表达式被求值 其语义为“就是表达式本身”\nDialogue: 0,0:42:57.97,0:43:00.85,Default,,0,0,0,,有了这种能力以后\nDialogue: 0,0:43:01.58,0:43:03.82,Default,,0,0,0,,如果我可以操作语言的表达式\nDialogue: 0,0:43:04.80,0:43:09.00,Default,,0,0,0,,我可以在语言层之上构建更加有力的层次\nDialogue: 0,0:43:09.77,0:43:12.64,Default,,0,0,0,,因为我可以编写不仅仅是内嵌于Lisp的语言\nDialogue: 0,0:43:13.46,0:43:14.80,Default,,0,0,0,,或者是其它的语言\nDialogue: 0,0:43:15.26,0:43:17.76,Default,,0,0,0,,我可以编写一种完全不同的语言\nDialogue: 0,0:43:18.58,0:43:22.24,Default,,0,0,0,,而其实质上则是被Lisp或其它语言所解释\nDialogue: 0,0:43:23.17,0:43:25.46,Default,,0,0,0,,我们以后还会对此有更深入的理解\nDialogue: 0,0:43:26.56,0:43:32.09,Default,,0,0,0,,我现在只是想让你们意识到\nDialogue: 0,0:43:32.36,0:43:34.98,Default,,0,0,0,,我们已经感触到了一种惊人的力量\nDialogue: 0,0:43:36.00,0:43:37.82,Default,,0,0,0,,现在我们有了方天画戟\nDialogue: 0,0:43:38.17,0:43:40.92,Default,,0,0,0,,当我们使用它时 也得万分小心\nDialogue: 0,0:43:42.17,0:43:43.00,Default,,0,0,0,,谢谢大家\nDialogue: 0,0:43:44.10,0:44:00.54,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:43:44.10,0:44:00.54,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec3b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nLast Style Storage: Default\nScroll Position: 583\nActive Line: 593\nVideo Zoom Percent: 0.625\nAudio URI: G:\\untitled\\ref\\lec3b_480_muxed2.mp4\nVideo File: G:\\untitled\\ref\\lec3b_480_muxed2.mp4\nVideo Aspect Ratio: c1.33333\nVideo Position: 79137\nPlayResX: 640\nPlayResY: 480\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:02.32,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.57,0:00:06.01,Declare,,0,0,0,,{\\an2\\fad(500,500)}翻译&&时间轴：邓雄飞（Dysprosium）\\N压制&&特效：邓雄飞（Dysprosium）\\N校对：邓雄飞（Dysprosium）\nDialogue: 0,0:00:06.06,0:00:08.97,Declare,,0,0,0,,{\\an2\\fad(500,500)}特别感谢：裘宗燕教授\nDialogue: 0,0:00:11.24,0:00:14.46,Declare,,0,0,0,,{\\an2\\fad(500,500)}符号化求导系统，引用\nDialogue: 0,0:00:19.10,0:00:23.41,Default,,0,0,0,,教授：嗯 Harold教授讲解了如何构造健壮的系统\nDialogue: 0,0:00:23.80,0:00:26.17,Default,,0,0,0,,关键点就是\nDialogue: 0,0:00:26.81,0:00:30.20,Default,,0,0,0,,我想你们大多还没吃透其中的要点\nDialogue: 0,0:00:30.20,0:00:33.77,Default,,0,0,0,,要点就是 为了让系统具有健壮性\nDialogue: 0,0:00:33.93,0:00:36.48,Default,,0,0,0,,应该让它对小变化不敏感\nDialogue: 0,0:00:36.60,0:00:37.37,Default,,0,0,0,,也就是说\nDialogue: 0,0:00:37.37,0:00:40.90,Default,,0,0,0,,问题中的小改变只会导致解决方案的小改动\nDialogue: 0,0:00:41.32,0:00:42.90,Default,,0,0,0,,系统应该是连续的\nDialogue: 0,0:00:42.90,0:00:45.94,Default,,0,0,0,,在问题空间中 解的空间是连续的\nDialogue: 0,0:00:46.25,0:00:48.76,Default,,0,0,0,,Harold教授给你们解释过\nDialogue: 0,0:00:49.46,0:00:54.78,Default,,0,0,0,,与其在问题分解出的子问题上 求解具体问题\nDialogue: 0,0:00:55.08,0:00:56.78,Default,,0,0,0,,你不如解决一类问题\nDialogue: 0,0:00:56.78,0:01:00.40,Default,,0,0,0,,也就是你想要解决的具体问题的“邻居”\nDialogue: 0,0:01:01.40,0:01:04.76,Default,,0,0,0,,解决之道便是在该层次上构造一门语言\nDialogue: 0,0:01:04.76,0:01:10.33,Default,,0,0,0,,使得我们可以用这门语言来表述这类问题\nDialogue: 0,0:01:11.37,0:01:15.09,Default,,0,0,0,,因此 当着手解决的问题再发生变动时\nDialogue: 0,0:01:15.09,0:01:19.29,Default,,0,0,0,,通常 你只需要在已构造好的解决方案上做出微小改动\nDialogue: 0,0:01:19.29,0:01:22.26,Default,,0,0,0,,因为在你所考虑的层次上\nDialogue: 0,0:01:22.26,0:01:24.26,Default,,0,0,0,,有一门语言可以表达\nDialogue: 0,0:01:24.80,0:01:28.14,Default,,0,0,0,,类似问题的各种解法\nDialogue: 0,0:01:30.04,0:01:33.74,Default,,0,0,0,,呃... 这是一个重要思想的萌芽\nDialogue: 0,0:01:34.40,0:01:38.61,Default,,0,0,0,,该思想的重要性也使得计算机科学比\nDialogue: 0,0:01:38.61,0:01:42.37,Default,,0,0,0,,其它大多数工程学科还要强大\nDialogue: 0,0:01:43.38,0:01:44.73,Default,,0,0,0,,目前为止 我们学习的是\nDialogue: 0,0:01:44.73,0:01:48.78,Default,,0,0,0,,类似于 如何使用语言内置元素\nDialogue: 0,0:01:49.26,0:01:53.36,Default,,0,0,0,,当然 内置元素的力量一部分来源于\nDialogue: 0,0:01:54.12,0:01:56.86,Default,,0,0,0,,像这个一样的过程 我昨天给你们展示过了\nDialogue: 0,0:01:57.37,0:02:02.13,Default,,0,0,0,,这里 是一份求导程序 昨天给你们描述过了\nDialogue: 0,0:02:02.13,0:02:05.92,Default,,0,0,0,,这个过程以一个过程为参数\nDialogue: 0,0:02:06.00,0:02:07.92,Default,,0,0,0,,并返回一个过程\nDialogue: 0,0:02:09.61,0:02:12.65,Default,,0,0,0,,用这样的东西棒极了\nDialogue: 0,0:02:12.65,0:02:14.65,Default,,0,0,0,,你可以像创建PUSH组合子那样构造\nDialogue: 0,0:02:14.65,0:02:16.86,Default,,0,0,0,,可以像上节课看到的哪些奇妙东西那样\nDialogue: 0,0:02:17.68,0:02:20.54,Default,,0,0,0,,现在 我要来打个太极\nDialogue: 0,0:02:21.56,0:02:25.90,Default,,0,0,0,,这个程序混淆了过程和数据\nDialogue: 0,0:02:26.56,0:02:27.81,Default,,0,0,0,,虽然程度不算太重\nDialogue: 0,0:02:28.42,0:02:30.90,Default,,0,0,0,,而我们将要严重地混淆两者\nDialogue: 0,0:02:31.18,0:02:32.44,Default,,0,0,0,,最好的做法就是\nDialogue: 0,0:02:32.44,0:02:37.62,Default,,0,0,0,,参与到过程自身所描述的代数表达式的操作中\nDialogue: 0,0:02:39.73,0:02:45.58,Default,,0,0,0,,所以 这里我不会讨论这张幻灯片上的东西\nDialogue: 0,0:02:45.89,0:02:49.72,Default,,0,0,0,,一个通过操作过程的求导程序\nDialogue: 0,0:02:49.72,0:02:51.94,Default,,0,0,0,,这只是一个数值化方法而已\nDialogue: 0,0:02:51.94,0:02:58.93,Default,,0,0,0,,你们所看到的是 通过数值方法来近似的求导程序\nDialogue: 0,0:02:59.29,0:03:00.44,Default,,0,0,0,,也就是这里的东西了\nDialogue: 0,0:03:00.86,0:03:04.93,Default,,0,0,0,,事实上 我想讨论的是这些东西\nDialogue: 0,0:03:06.05,0:03:11.33,Default,,0,0,0,,这是一份从微积分书中摘录的法则\nDialogue: 0,0:03:12.09,0:03:16.17,Default,,0,0,0,,这对表达式求导的法则\nDialogue: 0,0:03:16.70,0:03:20.58,Default,,0,0,0,,只不过是用代数语言书写的\nDialogue: 0,0:03:21.64,0:03:24.41,Default,,0,0,0,,法则说 常数的导数是0\nDialogue: 0,0:03:25.13,0:03:29.09,Default,,0,0,0,,而代表你所讨论的那个数的变量导数为1\nDialogue: 0,0:03:29.32,0:03:31.93,Default,,0,0,0,,常数乘以函数的导数\nDialogue: 0,0:03:32.09,0:03:34.37,Default,,0,0,0,,其值是常数的值乘以函数导数的值\nDialogue: 0,0:03:34.77,0:03:36.04,Default,,0,0,0,,就是这个意思\nDialogue: 0,0:03:38.05,0:03:41.38,Default,,0,0,0,,这些都是精确的表达式 而非数值近似\nDialogue: 0,0:03:42.96,0:03:44.52,Default,,0,0,0,,我们还能编写程序吗？\nDialogue: 0,0:03:44.52,0:03:52.24,Default,,0,0,0,,事实上 编写处理这些表达式的程序非常容易\nDialogue: 0,0:03:56.38,0:03:59.52,Default,,0,0,0,,让我们仔细地看看这些法则\nDialogue: 0,0:04:01.08,0:04:05.22,Default,,0,0,0,,你们曾经在初等微积分课上学过这些法则了\nDialogue: 0,0:04:05.98,0:04:12.12,Default,,0,0,0,,你们知道 微积分中对多元表达式求导很容易\nDialogue: 0,0:04:12.53,0:04:16.05,Default,,0,0,0,,在微积分课上 你们也知道计算积分不容易\nDialogue: 0,0:04:16.98,0:04:19.37,Default,,0,0,0,,虽然积分和求导相对\nDialogue: 0,0:04:19.52,0:04:21.28,Default,,0,0,0,,它俩互为逆运算\nDialogue: 0,0:04:21.61,0:04:23.30,Default,,0,0,0,,但它们有同样的法则\nDialogue: 0,0:04:24.16,0:04:29.68,Default,,0,0,0,,但这些法则中又有什么特殊的东西\nDialogue: 0,0:04:29.68,0:04:33.65,Default,,0,0,0,,使得求导容易 求积分就困难呢？\nDialogue: 0,0:04:34.85,0:04:36.98,Default,,0,0,0,,我们浅显地想一想\nDialogue: 0,0:04:37.40,0:04:38.38,Default,,0,0,0,,仔细考察法则\nDialogue: 0,0:04:39.36,0:04:43.06,Default,,0,0,0,,对于每条法则来说 你求导数时的方向\nDialogue: 0,0:04:43.06,0:04:44.80,Default,,0,0,0,,这个箭头的方向\nDialogue: 0,0:04:46.68,0:04:49.16,Default,,0,0,0,,法则的左边与你的表达式相匹配\nDialogue: 0,0:04:49.16,0:04:53.05,Default,,0,0,0,,法则的右边就是表达式的导数\nDialogue: 0,0:04:54.02,0:04:55.65,Default,,0,0,0,,箭头是这个方向的\nDialogue: 0,0:04:57.37,0:05:00.45,Default,,0,0,0,,每条法则中\nDialogue: 0,0:05:01.24,0:05:03.72,Default,,0,0,0,,法则右边的表达式\nDialogue: 0,0:05:03.72,0:05:06.56,Default,,0,0,0,,都是求导过程中的子表达式\nDialogue: 0,0:05:06.56,0:05:10.29,Default,,0,0,0,,都是左边式子的合法子表达式\nDialogue: 0,0:05:10.60,0:05:13.25,Default,,0,0,0,,这里 我们发现 和的导数\nDialogue: 0,0:05:13.92,0:05:16.13,Default,,0,0,0,,也就是左边式子的导数\nDialogue: 0,0:05:16.13,0:05:18.38,Default,,0,0,0,,就是两部分导数之和\nDialogue: 0,0:05:20.08,0:05:24.49,Default,,0,0,0,,法则从左至右的方向是“归约规则”\nDialogue: 0,0:05:25.02,0:05:26.61,Default,,0,0,0,,问题变简单了\nDialogue: 0,0:05:27.56,0:05:31.48,Default,,0,0,0,,我把一个复杂的问题 转化成了许多小点儿的问题\nDialogue: 0,0:05:32.44,0:05:35.76,Default,,0,0,0,,然后把结果组合起来 这里用递归可以完美地解决\nDialogue: 0,0:05:36.58,0:05:40.85,Default,,0,0,0,,但如果我从另外的方向来思考\nDialogue: 0,0:05:41.81,0:05:45.13,Default,,0,0,0,,如果我想求积分的话 你会发现有很多问题\nDialogue: 0,0:05:45.24,0:05:49.09,Default,,0,0,0,,就比如 如果我想求一个和的积分\nDialogue: 0,0:05:49.21,0:05:50.81,Default,,0,0,0,,就会匹配多条法则\nDialogue: 0,0:05:50.81,0:05:52.10,Default,,0,0,0,,这条匹配\nDialogue: 0,0:05:52.48,0:05:53.65,Default,,0,0,0,,这条也匹配\nDialogue: 0,0:05:54.81,0:05:57.09,Default,,0,0,0,,我不知道该用哪个——它们之间可能不一样\nDialogue: 0,0:05:57.70,0:06:00.00,Default,,0,0,0,,我得考察两者的不同之处\nDialogue: 0,0:06:00.25,0:06:03.64,Default,,0,0,0,,所以 在这个方向上 表达式变复杂了\nDialogue: 0,0:06:04.53,0:06:06.30,Default,,0,0,0,,当表达式变复杂时\nDialogue: 0,0:06:06.30,0:06:10.56,Default,,0,0,0,,就没法保证我所选的路径一定能终止了\nDialogue: 0,0:06:10.94,0:06:13.46,Default,,0,0,0,,因为唯一的可能是偶然的约分\nDialogue: 0,0:06:14.24,0:06:18.05,Default,,0,0,0,,这也就是为什么 积分是一种复杂的搜索 而难以完成\nDialogue: 0,0:06:19.12,0:06:20.96,Default,,0,0,0,,现在我不想处理这么复杂的东西\nDialogue: 0,0:06:21.49,0:06:23.06,Default,,0,0,0,,我们先来讨论求导数\nDialogue: 0,0:06:24.14,0:06:28.13,Default,,0,0,0,,好吧 我就假设你们都大致了解这些法则了\nDialogue: 0,0:06:28.78,0:06:31.88,Default,,0,0,0,,让我们来看看能不能用程序表达这些法则\nDialogue: 0,0:06:32.22,0:06:33.72,Default,,0,0,0,,这应该很容易\nDialogue: 0,0:06:34.89,0:06:36.21,Default,,0,0,0,,信手拈来\nDialogue: 0,0:06:36.69,0:06:39.29,Default,,0,0,0,,因为 我给你们展示的是“归约规则”\nDialogue: 0,0:06:39.29,0:06:41.29,Default,,0,0,0,,这样用递归来编写会比较合适\nDialogue: 0,0:06:43.08,0:06:45.72,Default,,0,0,0,,当然 对每条法则来说就是一种情况\nDialogue: 0,0:06:46.66,0:06:47.78,Default,,0,0,0,,我们做“分情况分析”\nDialogue: 0,0:06:48.58,0:06:50.36,Default,,0,0,0,,我就这么写了\nDialogue: 0,0:06:52.88,0:06:57.69,Default,,0,0,0,,当然 我得先让大家达成共识 对吧？\nDialogue: 0,0:06:57.69,0:07:00.33,Default,,0,0,0,,你们应该意识到到我可以表示这些代数式\nDialogue: 0,0:07:00.68,0:07:03.88,Default,,0,0,0,,我可以从中抽取式子 也可以将它们组合起来\nDialogue: 0,0:07:04.24,0:07:06.49,Default,,0,0,0,,我们发明了表结构来解决这个问题\nDialogue: 0,0:07:07.52,0:07:09.14,Default,,0,0,0,,但现在我们不必关心\nDialogue: 0,0:07:09.66,0:07:12.45,Default,,0,0,0,,现在 我要编写一个程序来封装这些法则\nDialogue: 0,0:07:12.76,0:07:15.85,Default,,0,0,0,,但它不依赖于代数表达式的表示法\nDialogue: 0,0:07:20.42,0:07:28.84,Default,,0,0,0,,(DERIV EXP VAR)表示表达式EXP关于变量VAR的导数\nDialogue: 0,0:07:30.50,0:07:33.08,Default,,0,0,0,,这和函数的导数是不一样的\nDialogue: 0,0:07:34.82,0:07:38.61,Default,,0,0,0,,那个是我们上节课看到的数值近似\nDialogue: 0,0:07:39.00,0:07:40.82,Default,,0,0,0,,并不能看到函数内部\nDialogue: 0,0:07:40.82,0:07:41.89,Default,,0,0,0,,它只是一个数值\nDialogue: 0,0:07:43.09,0:07:45.18,Default,,0,0,0,,表达式的导数也是一个表达式\nDialogue: 0,0:07:45.74,0:07:47.85,Default,,0,0,0,,因此 这只是一个语法问题\nDialogue: 0,0:07:48.29,0:07:51.62,Default,,0,0,0,,我们今天要做的大多数工作 就是讨论语法\nDialogue: 0,0:07:52.33,0:07:54.12,Default,,0,0,0,,表达式的语法或类似\nDialogue: 0,0:07:54.70,0:07:55.93,Default,,0,0,0,,首先要做“分情况分析”\nDialogue: 0,0:07:57.50,0:08:01.08,Default,,0,0,0,,任何时候我们处理复杂事物 需要递归求解时\nDialogue: 0,0:08:01.08,0:08:02.64,Default,,0,0,0,,我们很可能需要“按情况分析”\nDialogue: 0,0:08:03.62,0:08:05.16,Default,,0,0,0,,通常都是这样开始的\nDialogue: 0,0:08:05.16,0:08:07.40,Default,,0,0,0,,复杂的问题都是用“按情况分析”\nDialogue: 0,0:08:08.08,0:08:09.97,Default,,0,0,0,,那么 有哪些可能（的情况）呢？\nDialogue: 0,0:08:09.97,0:08:12.53,Default,,0,0,0,,第一条法则说 如果你遇到一个常数\nDialogue: 0,0:08:16.50,0:08:17.50,Default,,0,0,0,,这里 我就是在判断\nDialogue: 0,0:08:17.50,0:08:22.22,Default,,0,0,0,,表达式EXP是否为给定变量VAR的常数（常量表达式）\nDialogue: 0,0:08:24.90,0:08:27.08,Default,,0,0,0,,是的话 结果就是0\nDialogue: 0,0:08:27.50,0:08:30.10,Default,,0,0,0,,因为导数表征的是某物的变化率\nDialogue: 0,0:08:31.76,0:08:32.65,Default,,0,0,0,,然而\nDialogue: 0,0:08:32.89,0:08:40.69,Default,,0,0,0,,如果我求导的表达式 与我关心的变量有关\nDialogue: 0,0:08:41.72,0:08:50.42,Default,,0,0,0,,如果判定表达式和变量相同\nDialogue: 0,0:08:51.14,0:08:54.52,Default,,0,0,0,,那么关于变量VAR的表达式EXP的变化率就是1\nDialogue: 0,0:08:55.50,0:08:56.54,Default,,0,0,0,,它俩相同 结果是1\nDialogue: 0,0:08:58.90,0:09:00.77,Default,,0,0,0,,当然 还可能有其它的可能性\nDialogue: 0,0:09:01.33,0:09:03.14,Default,,0,0,0,,比如说 它可能是一个和式\nDialogue: 0,0:09:03.86,0:09:05.88,Default,,0,0,0,,呃 我现在还完全知道该如何表示和式\nDialogue: 0,0:09:06.09,0:09:08.25,Default,,0,0,0,,事实上我可以 只是我还没有告诉你们\nDialogue: 0,0:09:10.34,0:09:11.78,Default,,0,0,0,,如果表达式是和式\nDialogue: 0,0:09:12.48,0:09:14.48,Default,,0,0,0,,我就假想有一种方式可以判别（和式）\nDialogue: 0,0:09:15.30,0:09:19.44,Default,,0,0,0,,这里 我要做一个表达式的类型分派\nDialogue: 0,0:09:20.77,0:09:23.57,Default,,0,0,0,,这是在构建语言时绝对必要的\nDialogue: 0,0:09:24.72,0:09:26.37,Default,,0,0,0,,因为语言由不同的表达式构成\nDialogue: 0,0:09:26.48,0:09:27.54,Default,,0,0,0,,我们马上就将看到\nDialogue: 0,0:09:27.84,0:09:31.02,Default,,0,0,0,,如何用更强大的方法 用语言去构建语言\nDialogue: 0,0:09:32.53,0:09:34.02,Default,,0,0,0,,表达式是和式吗？\nDialogue: 0,0:09:35.45,0:09:38.82,Default,,0,0,0,,如果是的话 很好 我们已经知道和式的求导法则了\nDialogue: 0,0:09:38.82,0:09:41.33,Default,,0,0,0,,即是各部分导数之和\nDialogue: 0,0:09:42.13,0:09:44.32,Default,,0,0,0,,其中一个叫做加数 另一个叫做被加数\nDialogue: 0,0:09:44.32,0:09:46.80,Default,,0,0,0,,黑板上没那么多空间写这么长的名字了\nDialogue: 0,0:09:46.80,0:09:48.40,Default,,0,0,0,,我就姑且把它们叫做 A1和A2\nDialogue: 0,0:09:49.04,0:09:50.37,Default,,0,0,0,,把它们求和\nDialogue: 0,0:09:53.53,0:09:55.68,Default,,0,0,0,,（意义不明）\nDialogue: 0,0:09:57.14,0:10:01.09,Default,,0,0,0,,是叫做被除数和除数一类的么？\nDialogue: 0,0:10:01.65,0:10:08.48,Default,,0,0,0,,将A1的导数...加上\nDialogue: 0,0:10:08.48,0:10:13.29,Default,,0,0,0,,这是关于变量VAR的表达式的加数\nDialogue: 0,0:10:14.84,0:10:22.76,Default,,0,0,0,,与A2的导数相加\nDialogue: 0,0:10:24.12,0:10:28.25,Default,,0,0,0,,这两个参数的和 变量是VAR\nDialogue: 0,0:10:32.36,0:10:34.93,Default,,0,0,0,,我们知道还有一条乘法的求导法则\nDialogue: 0,0:10:35.20,0:10:37.44,Default,,0,0,0,,也就是说 如果表达式是乘式\nDialogue: 0,0:10:43.21,0:10:46.10,Default,,0,0,0,,顺便说下 当你定义过程时 有个好习惯\nDialogue: 0,0:10:46.96,0:10:48.32,Default,,0,0,0,,就是在定义谓词时\nDialogue: 0,0:10:48.85,0:10:50.96,Default,,0,0,0,,将谓词名以问号结尾\nDialogue: 0,0:10:51.08,0:10:52.89,Default,,0,0,0,,问号本身不代表什么\nDialogue: 0,0:10:53.10,0:10:54.50,Default,,0,0,0,,但这是俗成的约定\nDialogue: 0,0:10:54.61,0:10:58.94,Default,,0,0,0,,这是人们之间约定的接口 以方便他人阅读你的脚本\nDialogue: 0,0:11:00.05,0:11:01.96,Default,,0,0,0,,我希望你在写程序的时候\nDialogue: 0,0:11:01.96,0:11:03.73,Default,,0,0,0,,当你定义谓词的时候\nDialogue: 0,0:11:04.01,0:11:05.77,Default,,0,0,0,,就是那些返回TRUE或FALSE的过程\nDialogue: 0,0:11:05.94,0:11:07.84,Default,,0,0,0,,你应该使它们的名字以问号结尾\nDialogue: 0,0:11:08.02,0:11:10.34,Default,,0,0,0,,这对Lisp无异 但对人类友好\nDialogue: 0,0:11:11.62,0:11:13.14,Default,,0,0,0,,我需要求和\nDialogue: 0,0:11:13.14,0:11:17.49,Default,,0,0,0,,因为积的导数就是...\nDialogue: 0,0:11:17.94,0:11:19.64,Default,,0,0,0,,M1*DERIV(M2)\nDialogue: 0,0:11:19.66,0:11:20.70,Default,,0,0,0,,+DERIV(M1)*M2\nDialogue: 0,0:11:23.54,0:11:27.06,Default,,0,0,0,,两者加起来\nDialogue: 0,0:11:29.64,0:11:38.33,Default,,0,0,0,,求积... 呃 就用表达式中的M1来表示（被乘数）好了\nDialogue: 0,0:11:39.85,0:11:48.97,Default,,0,0,0,,表达式中M2关于变量VAR的导数\nDialogue: 0,0:11:51.90,0:12:06.28,Default,,0,0,0,,以及 M1关于变量VAR的导数乘以\nDialogue: 0,0:12:07.10,0:12:11.92,Default,,0,0,0,,M1是这里的被乘数\nDialogue: 0,0:12:13.32,0:12:18.05,Default,,0,0,0,,乘数是表达式中的M2\nDialogue: 0,0:12:20.64,0:12:24.89,Default,,0,0,0,,求积完毕、求和完毕、乘式分析完毕\nDialogue: 0,0:12:24.96,0:12:28.02,Default,,0,0,0,,当然 在这里我可以添加更多的情况\nDialogue: 0,0:12:28.32,0:12:30.82,Default,,0,0,0,,微积分书中的完整法则\nDialogue: 0,0:12:34.80,0:12:39.45,Default,,0,0,0,,我们就是这么来封装这些法则的\nDialogue: 0,0:12:41.53,0:12:43.90,Default,,0,0,0,,如你所见 我们这里用到了大量的“按愿望思维”\nDialogue: 0,0:12:44.54,0:12:47.56,Default,,0,0,0,,我们还没有说这些（表达式）是如何表示的\nDialogue: 0,0:12:48.46,0:12:51.92,Default,,0,0,0,,现在 一旦我将其定为我的一套法则\nDialogue: 0,0:12:52.52,0:12:55.20,Default,,0,0,0,,我想是时候考虑表示法了\nDialogue: 0,0:12:55.66,0:12:56.69,Default,,0,0,0,,我们来拿捏拿捏\nDialogue: 0,0:12:57.96,0:13:00.00,Default,,0,0,0,,首先 我要用到一种“双关”思想\nDialogue: 0,0:13:00.90,0:13:02.12,Default,,0,0,0,,这种“双关”思想非常重要\nDialogue: 0,0:13:02.74,0:13:06.56,Default,,0,0,0,,它是一种强有力思想的关键\nDialogue: 0,0:13:09.62,0:13:14.41,Default,,0,0,0,,如果我想表达诸如和、积、差、商的东西\nDialogue: 0,0:13:15.22,0:13:18.62,Default,,0,0,0,,为什么不用和我程序一样的语言呢？\nDialogue: 0,0:13:20.50,0:13:23.64,Default,,0,0,0,,我程序中 代数表达式是形如\nDialogue: 0,0:13:23.98,0:13:30.45,Default,,0,0,0,,(+ (* A (* X X))\nDialogue: 0,0:13:32.60,0:13:33.80,Default,,0,0,0,,和与之类似的\nDialogue: 0,0:13:34.28,0:13:38.50,Default,,0,0,0,,(* B X)以及C\nDialogue: 0,0:13:38.50,0:13:39.97,Default,,0,0,0,,把它们加起来\nDialogue: 0,0:13:40.77,0:13:44.09,Default,,0,0,0,,现在 我的过程还不能处理多元参数\nDialogue: 0,0:13:44.93,0:13:48.46,Default,,0,0,0,,(+ (* B X) C)\nDialogue: 0,0:13:51.42,0:13:52.44,Default,,0,0,0,,这是表结构\nDialogue: 0,0:13:54.12,0:13:55.74,Default,,0,0,0,,这么做很棒 是因为\nDialogue: 0,0:13:55.90,0:13:58.33,Default,,0,0,0,,是因为这些对象都有一种性质\nDialogue: 0,0:13:58.92,0:14:01.53,Default,,0,0,0,,我知道它们的CAR部分是什么\nDialogue: 0,0:14:01.96,0:14:03.21,Default,,0,0,0,,CAR部分就是运算符\nDialogue: 0,0:14:03.92,0:14:06.38,Default,,0,0,0,,运算数是相继的CDR部分\nDialogue: 0,0:14:07.22,0:14:10.36,Default,,0,0,0,,也就是不断取表CDR部分的CAR部分\nDialogue: 0,0:14:12.48,0:14:13.88,Default,,0,0,0,,这样就使它很方便了\nDialogue: 0,0:14:14.01,0:14:16.40,Default,,0,0,0,,我需要去解析它 但它已经帮我完成了\nDialogue: 0,0:14:17.42,0:14:20.01,Default,,0,0,0,,我利用了Lisp中的内建元素\nDialogue: 0,0:14:22.66,0:14:23.77,Default,,0,0,0,,举个例子\nDialogue: 0,0:14:25.08,0:14:33.97,Default,,0,0,0,,我们用表结构来表示我所暗示的表示法吧！\nDialogue: 0,0:14:35.25,0:14:38.34,Default,,0,0,0,,我需要定义一些东西 这都暗含在这种表示法中\nDialogue: 0,0:14:38.54,0:14:40.90,Default,,0,0,0,,比如如何判定是否为常量\nDialogue: 0,0:14:41.21,0:14:42.30,Default,,0,0,0,,又怎么判断是同一个变量\nDialogue: 0,0:14:42.40,0:14:45.04,Default,,0,0,0,,我们先完成这些吧 都相当简单\nDialogue: 0,0:14:45.78,0:14:47.70,Default,,0,0,0,,这里 我要介绍一些基本过程\nDialogue: 0,0:14:48.60,0:14:50.50,Default,,0,0,0,,因为它们都是与表结构相关的\nDialogue: 0,0:14:51.98,0:14:53.46,Default,,0,0,0,,CONSTANT?谓词定义为\nDialogue: 0,0:15:02.25,0:15:04.29,Default,,0,0,0,,我所谓的常量\nDialogue: 0,0:15:04.29,0:15:07.73,Default,,0,0,0,,表达式关于变量VAR是一个常量\nDialogue: 0,0:15:09.05,0:15:11.60,Default,,0,0,0,,是一些简单的表达式\nDialogue: 0,0:15:11.60,0:15:14.46,Default,,0,0,0,,我无法再细化它 但它也不是我们关心的变量\nDialogue: 0,0:15:16.58,0:15:18.78,Default,,0,0,0,,我无法分解它 但它也不是我们关心的变量\nDialogue: 0,0:15:18.90,0:15:25.12,Default,,0,0,0,,这也并不是说 一些复杂的表达式就不是常量表达式\nDialogue: 0,0:15:25.20,0:15:28.92,Default,,0,0,0,,我只是想用这种方式考察基本常量\nDialogue: 0,0:15:29.74,0:15:33.41,Default,,0,0,0,,因此 这个谓词是几个条件的合取\nDialogue: 0,0:15:34.02,0:15:37.82,Default,,0,0,0,,AND语句允许用户组合返回TRUE或者FALSE的谓词\nDialogue: 0,0:15:38.62,0:15:46.82,Default,,0,0,0,,表达式是原子的么？--原子表达式不可以再被细分\nDialogue: 0,0:15:46.82,0:15:48.53,Default,,0,0,0,,它没有CAR部分和CDR部分\nDialogue: 0,0:15:49.45,0:15:50.21,Default,,0,0,0,,它不是表\nDialogue: 0,0:15:50.76,0:15:52.94,Default,,0,0,0,,系统中内建有特殊测试\nDialogue: 0,0:15:53.97,0:16:04.66,Default,,0,0,0,,并且表达式EXP和变量VAR在EQ?的语义下不相等\nDialogue: 0,0:16:06.82,0:16:13.36,Default,,0,0,0,,我用不能被分解的符号来表示变量\nDialogue: 0,0:16:13.90,0:16:17.22,Default,,0,0,0,,比如'X 'Y 和像这样的\nDialogue: 0,0:16:19.74,0:16:22.37,Default,,0,0,0,,当然 像这样的组合式就可以再被细分\nDialogue: 0,0:16:24.74,0:16:46.40,Default,,0,0,0,,(SAME-VAR? EXP VAR)定义为\nDialogue: 0,0:16:46.40,0:16:48.40,Default,,0,0,0,,实际上 一条原子表达式……\nDialogue: 0,0:16:48.77,0:16:59.61,Default,,0,0,0,,该表达式与讨论变量相同\nDialogue: 0,0:17:07.90,0:17:11.68,Default,,0,0,0,,我不想深入讨论这些过程内部\nDialogue: 0,0:17:12.52,0:17:15.56,Default,,0,0,0,,把这些当作基本过程\nDialogue: 0,0:17:15.77,0:17:17.08,Default,,0,0,0,,这无关紧要\nDialogue: 0,0:17:17.78,0:17:21.74,Default,,0,0,0,,我用的是语言内置的功能\nDialogue: 0,0:17:22.42,0:17:24.04,Default,,0,0,0,,我并不关心这些（具体实现）\nDialogue: 0,0:17:24.42,0:17:26.04,Default,,0,0,0,,现在 我们要如何处理和式呢？\nDialogue: 0,0:17:26.60,0:17:28.80,Default,,0,0,0,,啊哈 好戏就要上演了\nDialogue: 0,0:17:28.98,0:17:33.12,Default,,0,0,0,,和式不是原子的 它以‘+’号打头\nDialogue: 0,0:17:35.16,0:17:36.17,Default,,0,0,0,,就是这个意思\nDialogue: 0,0:17:36.65,0:17:39.77,Default,,0,0,0,,这里 我定义\nDialogue: 0,0:17:45.46,0:17:57.77,Default,,0,0,0,,表达式为和式 当它不是原子表达式\nDialogue: 0,0:18:04.57,0:18:15.45,Default,,0,0,0,,并且它的开头 表达式的CAR部分是个‘+’号\nDialogue: 0,0:18:19.74,0:18:24.04,Default,,0,0,0,,我将要引入一个你们从未见过的东西--这个引号\nDialogue: 0,0:18:25.89,0:18:28.22,Default,,0,0,0,,我这里为什么要用引号呢？\nDialogue: 0,0:18:29.48,0:18:30.52,Default,,0,0,0,,教授：说你的名字\nDialogue: 0,0:18:30.68,0:18:31.41,Default,,0,0,0,,观众：Susanna\nDialogue: 0,0:18:31.41,0:18:32.01,Default,,0,0,0,,教授：大点声儿\nDialogue: 0,0:18:32.01,0:18:32.72,Default,,0,0,0,,观众：Susanna\nDialogue: 0,0:18:33.25,0:18:34.21,Default,,0,0,0,,教授：说“你的名字”\nDialogue: 0,0:18:34.21,0:18:34.85,Default,,0,0,0,,观众：“你的名字”\nDialogue: 0,0:18:34.92,0:18:35.68,Default,,0,0,0,,教授：大点声儿\nDialogue: 0,0:18:35.77,0:18:36.61,Default,,0,0,0,,观众：“你的名字”\nDialogue: 0,0:18:36.82,0:18:37.50,Default,,0,0,0,,教授：对了\nDialogue: 0,0:18:38.28,0:18:44.56,Default,,0,0,0,,在这里我想告诉大家 英语词汇是有歧义的\nDialogue: 0,0:18:45.50,0:18:50.76,Default,,0,0,0,,我可能说 “说你的名字”\nDialogue: 0,0:18:51.97,0:18:57.21,Default,,0,0,0,,我也可能说 “说‘你的名字’”\nDialogue: 0,0:19:00.72,0:19:02.98,Default,,0,0,0,,光从说话上还无法分辨\nDialogue: 0,0:19:03.89,0:19:08.01,Default,,0,0,0,,然而书面上 我们有专门的记号--引号\nDialogue: 0,0:19:08.18,0:19:12.46,Default,,0,0,0,,用来区别这两种可能的意思\nDialogue: 0,0:19:14.00,0:19:15.64,Default,,0,0,0,,具体来说 这里\nDialogue: 0,0:19:16.49,0:19:20.84,Default,,0,0,0,,在Lisp中有用于区别这些语义的记号\nDialogue: 0,0:19:21.34,0:19:24.45,Default,,0,0,0,,如果我只是写下一个加号\nDialogue: 0,0:19:24.64,0:19:28.52,Default,,0,0,0,,我会问系统 表达式的首元素\nDialogue: 0,0:19:29.06,0:19:33.61,Default,,0,0,0,,也就是表达式的运算符 是加运算符（一个过程）么？\nDialogue: 0,0:19:34.65,0:19:35.54,Default,,0,0,0,,我并不知道\nDialogue: 0,0:19:36.22,0:19:38.16,Default,,0,0,0,,我本应该在那里写一个加运算符的\nDialogue: 0,0:19:39.37,0:19:40.44,Default,,0,0,0,,但我无法那样做\nDialogue: 0,0:19:41.34,0:19:45.88,Default,,0,0,0,,而这种方式则是问 这个符号对象是否为\nDialogue: 0,0:19:45.98,0:19:48.14,Default,,0,0,0,,代表加运算符的符号\nDialogue: 0,0:19:49.57,0:19:51.92,Default,,0,0,0,,这才是我想要问和知道的问题\nDialogue: 0,0:19:52.92,0:19:54.45,Default,,0,0,0,,在我们深入讨论之前\nDialogue: 0,0:19:54.45,0:19:57.81,Default,,0,0,0,,我想要指出 “引用”是一个复杂的概念\nDialogue: 0,0:19:58.85,0:20:01.84,Default,,0,0,0,,语言中引入这个概念将会造成许多麻烦\nDialogue: 0,0:20:03.57,0:20:05.04,Default,,0,0,0,,请看下面这张幻灯片\nDialogue: 0,0:20:06.38,0:20:09.49,Default,,0,0,0,,这里这个推论没有问题\nDialogue: 0,0:20:11.62,0:20:17.04,Default,,0,0,0,,这是说 Alyssa聪明而Alyssa是George的妈妈\nDialogue: 0,0:20:17.40,0:20:20.60,Default,,0,0,0,,通过IS建立了一个等式\nDialogue: 0,0:20:22.13,0:20:26.30,Default,,0,0,0,,我们可以从这两个陈述推论出 George妈妈很聪明\nDialogue: 0,0:20:27.32,0:20:33.16,Default,,0,0,0,,这是因为我们总可以在表达式中等价替换\nDialogue: 0,0:20:34.09,0:20:35.16,Default,,0,0,0,,真是这样吗？\nDialogue: 0,0:20:36.52,0:20:40.37,Default,,0,0,0,,这个例子说 “Chicago”有七个字母\nDialogue: 0,0:20:41.12,0:20:44.86,Default,,0,0,0,,引用则是强调我讨论的是单词“Chicago”\nDialogue: 0,0:20:44.86,0:20:46.86,Default,,0,0,0,,而不是单词所代表的意思\nDialogue: 0,0:20:49.82,0:20:52.77,Default,,0,0,0,,这里说 Chicago是Illinois州最大的城市\nDialogue: 0,0:20:54.61,0:20:55.80,Default,,0,0,0,,而（代换的）结果是……\nDialogue: 0,0:20:55.80,0:20:59.09,Default,,0,0,0,,我可能会得到 Illinois州最大的城市有七个字母\nDialogue: 0,0:20:59.32,0:21:01.06,Default,,0,0,0,,这显然是错的\nDialogue: 0,0:21:05.16,0:21:07.17,Default,,0,0,0,,喔！手写笔好使了\nDialogue: 0,0:21:09.29,0:21:12.24,Default,,0,0,0,,所以 一旦我们有了（引用）这样的东西\nDialogue: 0,0:21:12.48,0:21:14.49,Default,,0,0,0,,我们的语言就会变得复杂\nDialogue: 0,0:21:14.49,0:21:18.34,Default,,0,0,0,,因为我们对于语言的一些操作就不再正确\nDialogue: 0,0:21:18.34,0:21:20.76,Default,,0,0,0,,比如通过等价代换来得到正确答案\nDialogue: 0,0:21:21.29,0:21:23.50,Default,,0,0,0,,如果不小心地操作就会出错\nDialogue: 0,0:21:24.49,0:21:27.34,Default,,0,0,0,,在一个引用不透明的上下文中 我们无法进行代换\nDialogue: 0,0:21:27.89,0:21:32.64,Default,,0,0,0,,引用就是引用不透明上下文的典型\nDialogue: 0,0:21:33.17,0:21:35.28,Default,,0,0,0,,如果你知道那是什么意思……你可以成为一位哲学家\nDialogue: 0,0:21:35.42,0:21:37.02,Default,,0,0,0,,或许我们之中就有一位\nDialogue: 0,0:21:37.53,0:21:41.32,Default,,0,0,0,,言归正传 我们继续\nDialogue: 0,0:21:41.32,0:21:44.98,Default,,0,0,0,,现在我们对一个有2000年历史的问题至少有了操作上的理解\nDialogue: 0,0:21:45.26,0:21:48.13,Default,,0,0,0,,关于名称、提及和等等类似的问题\nDialogue: 0,0:21:52.32,0:22:01.60,Default,,0,0,0,,我得定义如何把两个数加起来 (DEFINE (MAKE-SUM A1 A2))\nDialogue: 0,0:22:02.12,0:22:03.62,Default,,0,0,0,,我简单实现一下\nDialogue: 0,0:22:03.62,0:22:11.96,Default,,0,0,0,,'+、A1、A2构成列表\nDialogue: 0,0:22:13.86,0:22:17.37,Default,,0,0,0,,我可以决定如何取出第一个元素\nDialogue: 0,0:22:21.84,0:22:25.32,Default,,0,0,0,,(DEFINE A1 CADR)\nDialogue: 0,0:22:33.88,0:22:35.90,Default,,0,0,0,,这里又给大家介绍了一个基本过程\nDialogue: 0,0:22:36.17,0:22:39.10,Default,,0,0,0,,这个是取出某物CDR部分的CAR部分\nDialogue: 0,0:22:39.80,0:22:44.53,Default,,0,0,0,,大家或许会好奇 这些基本过程为什么叫做CAR和CDR\nDialogue: 0,0:22:44.66,0:22:48.42,Default,,0,0,0,,而且传承了下来 尽管叫做LEFT和RIGHT会好一点\nDialogue: 0,0:22:48.76,0:22:50.44,Default,,0,0,0,,我们本可以那样叫的\nDialogue: 0,0:22:51.28,0:22:56.25,Default,,0,0,0,,呃 其实 这个名字来自于很久以前 当发明Lisp时\nDialogue: 0,0:22:56.36,0:23:00.80,Default,,0,0,0,,我想大概是58年的样子 是在类似于704之类的机子上实现的\nDialogue: 0,0:23:00.80,0:23:05.41,Default,,0,0,0,,这个机器有个地址寄存器和减量寄存器\nDialogue: 0,0:23:05.41,0:23:08.17,Default,,0,0,0,,而这些就是地址寄存器和减量寄存器的值\nDialogue: 0,0:23:08.17,0:23:09.37,Default,,0,0,0,,所以这是历史遗留问题\nDialogue: 0,0:23:09.64,0:23:11.28,Default,,0,0,0,,但是这些名字为什么又延续下来了呢？\nDialogue: 0,0:23:11.74,0:23:14.76,Default,,0,0,0,,这是因为Lisp程序员喜欢用电话交流\nDialogue: 0,0:23:15.68,0:23:19.60,Default,,0,0,0,,要是你有一长串的CAR和CDR序列 你就可能说“CDADDEDR”\nDialogue: 0,0:23:21.01,0:23:22.32,Default,,0,0,0,,这是可以理解的\nDialogue: 0,0:23:22.32,0:23:27.02,Default,,0,0,0,,但是左边的右边的右边的左边就不是那么清楚了\nDialogue: 0,0:23:27.60,0:23:30.02,Default,,0,0,0,,这就是我们为什么有这些黑话\nDialogue: 0,0:23:30.54,0:23:34.14,Default,,0,0,0,,典型的Lisp系统 默认定义到第四层\nDialogue: 0,0:23:38.66,0:23:47.05,Default,,0,0,0,,而定义A2为……当然 如果我们考察这些表达式中的一个\nDialogue: 0,0:23:47.36,0:23:52.14,Default,,0,0,0,,比如(+ 3 5)\nDialogue: 0,0:23:52.58,0:24:10.45,Default,,0,0,0,,这个实际上是一个包含有'+、数3和数5的表\nDialogue: 0,0:24:11.72,0:24:15.18,Default,,0,0,0,,表的CAR部分是'+\nDialogue: 0,0:24:16.13,0:24:18.21,Default,,0,0,0,,CDR部分的CAR部分\nDialogue: 0,0:24:18.21,0:24:20.21,Default,,0,0,0,,也就是先取CDR部分 然后再取CAR部分\nDialogue: 0,0:24:20.21,0:24:22.21,Default,,0,0,0,,这就是我如何取得3的 也就是第一个参数\nDialogue: 0,0:24:22.52,0:24:25.69,Default,,0,0,0,,CDR的CDR部分的CAR部分 就是这个……数5\nDialogue: 0,0:24:28.69,0:24:33.66,Default,,0,0,0,,当然类似地 对于乘式我可以这样定义\nDialogue: 0,0:24:35.22,0:24:36.56,Default,,0,0,0,,我快速地演示一下\nDialogue: 0,0:24:48.97,0:24:50.64,Default,,0,0,0,,(DEFINE (PRODUCT? EXP))\nDialogue: 0,0:24:51.05,0:24:54.69,Default,,0,0,0,,如果它不是原子的 而且\nDialogue: 0,0:25:01.41,0:25:14.14,Default,,0,0,0,,EXP的CAR部分与用于表示乘法的符号'*在 EQ?的语义下相等\nDialogue: 0,0:25:15.64,0:25:32.00,Default,,0,0,0,,(DEFINE (MAKE-PRODUCT M1 M2))\nDialogue: 0,0:25:34.42,0:25:39.30,Default,,0,0,0,,(LIST '* M1 M2)\nDialogue: 0,0:25:40.82,0:25:56.81,Default,,0,0,0,,并定义M1为CADR M2为CADDR\nDialogue: 0,0:26:00.09,0:26:02.38,Default,,0,0,0,,当你说行话的时候 你就上道了\nDialogue: 0,0:26:02.53,0:26:05.53,Default,,0,0,0,,你可以取表的CDR 也可以把它们组合起来\nDialogue: 0,0:26:06.29,0:26:10.10,Default,,0,0,0,,现在 我们有了原理上完整的求导程序了\nDialogue: 0,0:26:10.10,0:26:11.70,Default,,0,0,0,,如果需要的话 你也可以添加更多的规则\nDialogue: 0,0:26:12.21,0:26:13.93,Default,,0,0,0,,它又要怎么用呢？\nDialogue: 0,0:26:14.64,0:26:16.77,Default,,0,0,0,,我先把这个笔迹清了\nDialogue: 0,0:26:17.80,0:26:20.82,Default,,0,0,0,,恩 假设我在这里定义FOO为\nDialogue: 0,0:26:22.16,0:26:30.38,Default,,0,0,0,,定义FOO为A*X^2+B*X+C\nDialogue: 0,0:26:30.54,0:26:32.08,Default,,0,0,0,,跟我们这里看到的是一样的\nDialogue: 0,0:26:32.08,0:26:36.36,Default,,0,0,0,,这里是用更习见的记号书写的代数表达式\nDialogue: 0,0:26:37.84,0:26:41.60,Default,,0,0,0,,那么 表达式FOO关于X的导数 结果在这里\nDialogue: 0,0:26:43.46,0:26:45.26,Default,,0,0,0,,真是乱得一团糟\nDialogue: 0,0:26:46.16,0:26:49.22,Default,,0,0,0,,我期望答案是2*A*X+B\nDialogue: 0,0:26:50.68,0:26:53.44,Default,,0,0,0,,虽然与结果等价 但它并不是我们希望的结果\nDialogue: 0,0:26:54.58,0:26:55.22,Default,,0,0,0,,这是什么呢？\nDialogue: 0,0:26:55.97,0:26:59.96,Default,,0,0,0,,我们最初有什么？\nDialogue: 0,0:27:00.50,0:27:04.30,Default,,0,0,0,,我求X*X的导数\nDialogue: 0,0:27:04.69,0:27:10.53,Default,,0,0,0,,答案是X*1+1*X 这当然没错\nDialogue: 0,0:27:12.73,0:27:15.66,Default,,0,0,0,,这就是乘数的导数乘以被乘数加上乘数乘以被乘数的导数\nDialogue: 0,0:27:17.22,0:27:28.37,Default,,0,0,0,,那就是2X、A*2X就是2AX、0X^2省去 再加上0和这里的一大堆0\nDialogue: 0,0:27:28.96,0:27:30.12,Default,,0,0,0,,答案是对的\nDialogue: 0,0:27:30.12,0:27:35.14,Default,,0,0,0,,当我们还需要用户额外检验一下 真是糟糕投了\nDialogue: 0,0:27:35.56,0:27:37.26,Default,,0,0,0,,我们下一节再考虑这个内容\nDialogue: 0,0:27:37.68,0:27:38.61,Default,,0,0,0,,有疑问吗？\nDialogue: 0,0:27:42.77,0:27:43.45,Default,,0,0,0,,请说\nDialogue: 0,0:27:43.89,0:27:46.69,Default,,0,0,0,,观众：写加号时不加引号\nDialogue: 0,0:27:46.69,0:27:50.82,Default,,0,0,0,,是表示引用加那个过程么？\nDialogue: 0,0:27:50.82,0:27:55.42,Default,,0,0,0,,如果有需要的话 是否能在两个过程之间进行比较\nDialogue: 0,0:27:56.16,0:27:57.08,Default,,0,0,0,,教授：问得好！\nDialogue: 0,0:27:57.45,0:28:02.26,Default,,0,0,0,,如果我这里不用左引号将这个引住\nDialogue: 0,0:28:03.88,0:28:07.13,Default,,0,0,0,,如果我这里不用引号\nDialogue: 0,0:28:07.33,0:28:14.20,Default,,0,0,0,,那么这里我就会引用定义好的加法过程\nDialogue: 0,0:28:15.38,0:28:24.88,Default,,0,0,0,,实际上 我可以比较两个过程是否同一\nDialogue: 0,0:28:24.88,0:28:27.45,Default,,0,0,0,,现在很难从语义上解释\nDialogue: 0,0:28:27.85,0:28:29.37,Default,,0,0,0,,我现在不想考虑这个问题\nDialogue: 0,0:28:29.89,0:28:32.40,Default,,0,0,0,,因为我不知道比较过程需要什么\nDialogue: 0,0:28:32.40,0:28:34.40,Default,,0,0,0,,这样做没有意义是有很多原因的\nDialogue: 0,0:28:35.52,0:28:37.53,Default,,0,0,0,,然而 这些符号我们是可以理解的\nDialogue: 0,0:28:38.54,0:28:40.56,Default,,0,0,0,,这也是我为什么我要将它们引住\nDialogue: 0,0:28:41.16,0:28:43.70,Default,,0,0,0,,我想讨论出现在这些代码中的符号\nDialogue: 0,0:28:46.16,0:28:46.92,Default,,0,0,0,,还有什么问题么？\nDialogue: 0,0:28:48.52,0:28:51.86,Default,,0,0,0,,好吧 休息一下 谢谢大家\nDialogue: 0,0:28:55.12,0:29:00.66,Default,,0,0,0,,[音乐]\nDialogue: 0,0:29:00.68,0:29:04.34,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:29:04.34,0:29:06.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:29:12.21,0:29:19.17,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:29:20.09,0:29:24.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}符号化导数系统、引用\nDialogue: 0,0:29:29.86,0:29:30.92,Default,,0,0,0,,教授：好 我们继续\nDialogue: 0,0:29:31.46,0:29:37.76,Default,,0,0,0,,我们编写了一个貌似可行的代数表达式求导程序\nDialogue: 0,0:29:38.20,0:29:41.56,Default,,0,0,0,,这个程序是不完整的 你需要添加一些规则\nDialogue: 0,0:29:42.13,0:29:47.74,Default,,0,0,0,,你可能需要加强这个系统 使得它能够处理\nDialogue: 0,0:29:47.76,0:29:49.70,Default,,0,0,0,,多元加法和多元乘法\nDialogue: 0,0:29:49.89,0:29:51.38,Default,,0,0,0,,这些都相当简单\nDialogue: 0,0:29:52.73,0:29:56.93,Default,,0,0,0,,但这里面也有一些瑕疵\nDialogue: 0,0:29:57.48,0:30:02.37,Default,,0,0,0,,回到这张幻灯片来\nDialogue: 0,0:30:02.94,0:30:08.60,Default,,0,0,0,,我们发现 得到的表达式相当乱\nDialogue: 0,0:30:08.88,0:30:11.01,Default,,0,0,0,,这个表达式非常糟糕\nDialogue: 0,0:30:11.46,0:30:13.10,Default,,0,0,0,,我们是怎么得到这样的表达式的？\nDialogue: 0,0:30:13.84,0:30:15.50,Default,,0,0,0,,为什么是这样呢？\nDialogue: 0,0:30:16.84,0:30:18.74,Default,,0,0,0,,我们详细地分析一下这个表达式\nDialogue: 0,0:30:18.92,0:30:20.76,Default,,0,0,0,,找出这些片段都是出自哪里\nDialogue: 0,0:30:21.69,0:30:24.56,Default,,0,0,0,,如我们所见 这里的和式\nDialogue: 0,0:30:24.56,0:30:26.56,Default,,0,0,0,,也就是上一小节中给你们提到的\nDialogue: 0,0:30:27.12,0:30:29.09,Default,,0,0,0,,(+ (* X 1) (* 1 X))\nDialogue: 0,0:30:29.58,0:30:31.38,Default,,0,0,0,,是这个乘式的导数\nDialogue: 0,0:30:32.52,0:30:36.41,Default,,0,0,0,,也就是A乘上这个的积 这里A不是X的函数\nDialogue: 0,0:30:36.41,0:30:38.41,Default,,0,0,0,,因此A关于X是一个常数\nDialogue: 0,0:30:39.04,0:30:44.53,Default,,0,0,0,,导数为这个和式 从这里到这里 再到这里\nDialogue: 0,0:30:44.80,0:30:48.89,Default,,0,0,0,,因为这个是乘数乘以被乘数的导数\nDialogue: 0,0:30:49.57,0:30:54.45,Default,,0,0,0,,加上被乘数乘以乘数的导数\nDialogue: 0,0:30:54.66,0:30:59.06,Default,,0,0,0,,我们在黑板上的程序告诉我们确实是这样的\nDialogue: 0,0:31:00.65,0:31:05.36,Default,,0,0,0,,当然 这里B乘以X的积\nDialogue: 0,0:31:05.49,0:31:09.81,Default,,0,0,0,,被化成了 B*1+0*X\nDialogue: 0,0:31:10.81,0:31:16.06,Default,,0,0,0,,因为B不是X的函数\nDialogue: 0,0:31:16.46,0:31:18.56,Default,,0,0,0,,因此B的导数为0\nDialogue: 0,0:31:18.77,0:31:21.48,Default,,0,0,0,,而X对自己求导则为1\nDialogue: 0,0:31:23.06,0:31:28.64,Default,,0,0,0,,这里的加法化成了 这两个导数的和\nDialogue: 0,0:31:29.37,0:31:33.50,Default,,0,0,0,,所以这里 我想告诉你和之前一样的东西\nDialogue: 0,0:31:33.66,0:31:35.89,Default,,0,0,0,,也就是在讲斐波那契数那时候\nDialogue: 0,0:31:37.77,0:31:39.49,Default,,0,0,0,,所谓的 “过程的形状”\nDialogue: 0,0:31:41.38,0:31:46.44,Default,,0,0,0,,就是通过局部的规则向低层次展开\nDialogue: 0,0:31:48.05,0:31:52.57,Default,,0,0,0,,也就是过程代表了一系列用于演进过程局部规则\nDialogue: 0,0:31:53.36,0:32:00.09,Default,,0,0,0,,这里 过程还遗留了一些东西--也就是答案\nDialogue: 0,0:32:00.25,0:32:06.26,Default,,0,0,0,,这是通过遍历表达式的树结构构造出来的\nDialogue: 0,0:32:08.41,0:32:12.61,Default,,0,0,0,,答案中的每个部分对应问题中的某个部分\nDialogue: 0,0:32:14.46,0:32:17.78,Default,,0,0,0,,比如说 现在我们考察FOO的导数\nDialogue: 0,0:32:17.78,0:32:19.65,Default,,0,0,0,,也就是AX^2+BX+C\nDialogue: 0,0:32:19.84,0:32:23.05,Default,,0,0,0,,并另令自变量 比如像这里\nDialogue: 0,0:32:24.14,0:32:27.48,Default,,0,0,0,,我们令A为自变量 求FOO的导数\nDialogue: 0,0:32:28.10,0:32:31.77,Default,,0,0,0,,这都非常相似 实际上 它们是同样的代数表达式\nDialogue: 0,0:32:32.45,0:32:35.24,Default,,0,0,0,,只是它们之中0和1的位置不一样罢了\nDialogue: 0,0:32:36.06,0:32:38.60,Default,,0,0,0,,这是因为在这个树结构的遍历中\nDialogue: 0,0:32:38.97,0:32:43.85,Default,,0,0,0,,只可能是CONSTANT?和SAME-VAR?会因变量的不同\nDialogue: 0,0:32:44.28,0:32:45.81,Default,,0,0,0,,而造成不同结果\nDialogue: 0,0:32:48.26,0:32:52.09,Default,,0,0,0,,回到黑板上来再看看\nDialogue: 0,0:32:52.65,0:32:57.49,Default,,0,0,0,,我们在求和式或乘式的导数时根本没有发挥的余地\nDialogue: 0,0:32:58.08,0:33:04.48,Default,,0,0,0,,真正可以做文章的地方 则是表达式和自变量\nDialogue: 0,0:33:04.80,0:33:10.10,Default,,0,0,0,,以及对于那些短小的表达式 是否为关于自变量的常量\nDialogue: 0,0:33:10.36,0:33:12.41,Default,,0,0,0,,就是这些地方导致了不同的0和1的产生\nDialogue: 0,0:33:12.69,0:33:14.49,Default,,0,0,0,,回过头来看这张幻灯\nDialogue: 0,0:33:15.12,0:33:18.16,Default,,0,0,0,,这里就出现了“0”\nDialogue: 0,0:33:18.37,0:33:22.74,Default,,0,0,0,,这里是求FOO(A)的导数时得到的“1”\nDialogue: 0,0:33:22.96,0:33:24.86,Default,,0,0,0,,我们得到了X^2\nDialogue: 0,0:33:24.96,0:33:32.53,Default,,0,0,0,,这个1是X*X关于X的导数 关于B求导时1变成了0\nDialogue: 0,0:33:32.64,0:33:34.89,Default,,0,0,0,,这里 我们求FOO关于C的导数\nDialogue: 0,0:33:36.78,0:33:39.30,Default,,0,0,0,,但是这些表达式的轮廓是一致的\nDialogue: 0,0:33:40.54,0:33:43.96,Default,,0,0,0,,看看这些轮廓 都是相同的\nDialogue: 0,0:33:50.37,0:33:52.28,Default,,0,0,0,,那么 难道是我们的规则出了问题？\nDialogue: 0,0:33:53.58,0:33:55.02,Default,,0,0,0,,不 这些规则都对\nDialogue: 0,0:33:56.12,0:33:57.77,Default,,0,0,0,,我们曾经遇到过这种问题\nDialogue: 0,0:33:58.06,0:34:03.53,Default,,0,0,0,,你将会发现 这其中缺乏一些非常好的思想\nDialogue: 0,0:34:06.32,0:34:09.74,Default,,0,0,0,,昨天 我们在考察有理数时\nDialogue: 0,0:34:12.12,0:34:14.48,Default,,0,0,0,,想要得到3/4却得到6/8\nDialogue: 0,0:34:14.97,0:34:16.49,Default,,0,0,0,,答案没有化简\nDialogue: 0,0:34:18.09,0:34:20.90,Default,,0,0,0,,当然 当下的问题也非常类似\nDialogue: 0,0:34:21.18,0:34:25.41,Default,,0,0,0,,我想把不相同的表达式通过化简来使相同\nDialogue: 0,0:34:27.57,0:34:31.89,Default,,0,0,0,,当然 有理数加法和乘法的规则依然正确\nDialogue: 0,0:34:33.97,0:34:37.41,Default,,0,0,0,,因此这里 我们依葫芦画瓢\nDialogue: 0,0:34:37.78,0:34:39.89,Default,,0,0,0,,上次能行的办法 这次也没问题\nDialogue: 0,0:34:40.53,0:34:42.05,Default,,0,0,0,,也就是改换一下它的表示\nDialogue: 0,0:34:43.13,0:34:46.44,Default,,0,0,0,,或许在将其表示出来时我们可以进行\nDialogue: 0,0:34:47.88,0:34:49.78,Default,,0,0,0,,一步产生简化表示的步骤\nDialogue: 0,0:34:50.17,0:34:51.73,Default,,0,0,0,,当然啦 这也不是万用万灵\nDialogue: 0,0:34:52.49,0:34:54.14,Default,,0,0,0,,我也不想证明它是万能的\nDialogue: 0,0:34:55.12,0:35:00.44,Default,,0,0,0,,但这也是控制复杂度的一招妙计\nDialogue: 0,0:35:01.46,0:35:03.85,Default,,0,0,0,,我们小心翼翼地解决这些问题\nDialogue: 0,0:35:04.30,0:35:07.20,Default,,0,0,0,,我们所做的 就是把问题划分为几个部分\nDialogue: 0,0:35:07.57,0:35:08.73,Default,,0,0,0,,分别是求导规则\nDialogue: 0,0:35:11.32,0:35:15.80,Default,,0,0,0,,和在这种层面上的一般代数规则\nDialogue: 0,0:35:16.38,0:35:21.22,Default,,0,0,0,,然后就有一道抽象屏障\nDialogue: 0,0:35:22.48,0:35:33.49,Default,,0,0,0,,这里是代数表达式的表示--表结构\nDialogue: 0,0:35:37.33,0:35:42.56,Default,,0,0,0,,在这道屏障中 我定义了接口过程\nDialogue: 0,0:35:43.25,0:35:49.82,Default,,0,0,0,,比如 CONSTANT? SAME-VAR?\nDialogue: 0,0:35:54.60,0:35:58.72,Default,,0,0,0,,又比如 SUM? MAKE-SUM\nDialogue: 0,0:36:02.22,0:36:05.57,Default,,0,0,0,,还有 A1 A2\nDialogue: 0,0:36:06.60,0:36:08.58,Default,,0,0,0,,还有 PRODUCT? 之类的东西\nDialogue: 0,0:36:08.74,0:36:11.90,Default,,0,0,0,,我所需要的、针对各式代数表达式的东西\nDialogue: 0,0:36:12.94,0:36:19.14,Default,,0,0,0,,构筑这些屏障我可以随意地改换表示法\nDialogue: 0,0:36:20.14,0:36:23.20,Default,,0,0,0,,而不用改变在某种表示法下编写的规则\nDialogue: 0,0:36:25.04,0:36:29.08,Default,,0,0,0,,如果我能通过改变表示法来解决问题\nDialogue: 0,0:36:30.38,0:36:34.52,Default,,0,0,0,,那么把问题分解为两个部分则帮了我大忙\nDialogue: 0,0:36:35.65,0:36:37.54,Default,,0,0,0,,好吧 举一个非常简单的例子\nDialogue: 0,0:36:38.82,0:36:40.08,Default,,0,0,0,,我们的问题是什么？\nDialogue: 0,0:36:40.26,0:36:43.61,Default,,0,0,0,,回到这张幻灯片来\nDialogue: 0,0:36:44.50,0:36:47.34,Default,,0,0,0,,看这里 哦 这相当糟糕\nDialogue: 0,0:36:47.62,0:36:51.86,Default,,0,0,0,,这里是一个表达式与“0”的和\nDialogue: 0,0:36:53.14,0:36:56.66,Default,,0,0,0,,毋庸置疑这应该是该表达式本身\nDialogue: 0,0:36:57.21,0:37:01.90,Default,,0,0,0,,为什么这里还会有加号？\nDialogue: 0,0:37:03.38,0:37:04.57,Default,,0,0,0,,这其实可以更智能点\nDialogue: 0,0:37:05.56,0:37:10.08,Default,,0,0,0,,又比如说这里 是某表达式与“1”的积\nDialogue: 0,0:37:11.16,0:37:12.29,Default,,0,0,0,,这和之前一个道理\nDialogue: 0,0:37:12.86,0:37:15.68,Default,,0,0,0,,又像这里 与“0”相乘显然是“0”\nDialogue: 0,0:37:17.86,0:37:19.52,Default,,0,0,0,,因此我们也不用去构造这些式子了\nDialogue: 0,0:37:21.44,0:37:22.62,Default,,0,0,0,,我们为什么不这么做呢？\nDialogue: 0,0:37:23.66,0:37:27.96,Default,,0,0,0,,我们需要去修改表示法 基本上就是那里了\nDialogue: 0,0:37:37.40,0:37:41.84,Default,,0,0,0,,定义 MAKE-SUM 为\nDialogue: 0,0:37:42.05,0:37:43.76,Default,,0,0,0,,呃 现在就不是那么简单了\nDialogue: 0,0:37:44.00,0:37:50.40,Default,,0,0,0,,除非是有必要 否则我不会简单地把加号和式子组合成表\nDialogue: 0,0:37:51.72,0:37:53.05,Default,,0,0,0,,那么 还有哪些可能呢？\nDialogue: 0,0:37:54.56,0:37:58.53,Default,,0,0,0,,如果……这里有一些可能的情况\nDialogue: 0,0:37:59.38,0:38:08.20,Default,,0,0,0,,如果都是数值的话 如果A1是数值的话\nDialogue: 0,0:38:09.05,0:38:10.93,Default,,0,0,0,,这个基本过程我刚刚提到过\nDialogue: 0,0:38:10.93,0:38:13.18,Default,,0,0,0,,也就是用来检测参数是否为数值\nDialogue: 0,0:38:15.38,0:38:23.82,Default,,0,0,0,,并且A2也是数值的话 也就是A2不是符号表达式\nDialogue: 0,0:38:24.45,0:38:26.20,Default,,0,0,0,,那么我们就直接把它们加起来\nDialogue: 0,0:38:26.45,0:38:29.92,Default,,0,0,0,,结果就是A1加上A2的和\nDialogue: 0,0:38:32.32,0:38:33.98,Default,,0,0,0,,我并不是检查它们代表数值\nDialogue: 0,0:38:33.98,0:38:35.98,Default,,0,0,0,,这里所有的符号都代表数值\nDialogue: 0,0:38:37.33,0:38:41.22,Default,,0,0,0,,就比如 我想要考察的是这个东西是否为数值3\nDialogue: 0,0:38:43.40,0:38:44.40,Default,,0,0,0,,另一种情况\nDialogue: 0,0:38:48.77,0:38:59.61,Default,,0,0,0,,假设A1是数值 并且为0\nDialogue: 0,0:39:04.20,0:39:06.38,Default,,0,0,0,,那么答案就是A2\nDialogue: 0,0:39:06.93,0:39:08.68,Default,,0,0,0,,不用再构造什么\nDialogue: 0,0:39:10.98,0:39:23.41,Default,,0,0,0,,如果A2是数值 并且为0\nDialogue: 0,0:39:27.16,0:39:28.90,Default,,0,0,0,,那么答案就是A1\nDialogue: 0,0:39:30.04,0:39:33.65,Default,,0,0,0,,如果没有比这些更好的情况\nDialogue: 0,0:39:34.13,0:39:35.61,Default,,0,0,0,,我就需要构造一个表\nDialogue: 0,0:39:37.86,0:39:42.86,Default,,0,0,0,,构造一个用于表示答案的表\nDialogue: 0,0:39:44.13,0:39:52.33,Default,,0,0,0,,其中有 '+、A1和A2\nDialogue: 0,0:39:58.66,0:40:01.65,Default,,0,0,0,,当然 积的导数也可以类比此法\nDialogue: 0,0:40:03.01,0:40:05.04,Default,,0,0,0,,这里 我就不细讲了\nDialogue: 0,0:40:05.44,0:40:07.24,Default,,0,0,0,,我就直接在黑板上写出结果\nDialogue: 0,0:40:07.65,0:40:09.80,Default,,0,0,0,,这并不是很重要 你们已经了解它的思想了\nDialogue: 0,0:40:10.76,0:40:11.61,Default,,0,0,0,,非常简明\nDialogue: 0,0:40:12.86,0:40:19.89,Default,,0,0,0,,现在 我们来看看用这种方式改造程序后 效果如何\nDialogue: 0,0:40:21.68,0:40:27.88,Default,,0,0,0,,哦 这是修改表达式构造函数后的求导结果\nDialogue: 0,0:40:28.98,0:40:32.21,Default,,0,0,0,,对同样地FOO求导：AX^2+BX+C\nDialogue: 0,0:40:33.28,0:40:40.70,Default,,0,0,0,,我得到了 2AX+B\nDialogue: 0,0:40:40.70,0:40:42.10,Default,,0,0,0,,虽然它并没有化到最简\nDialogue: 0,0:40:42.60,0:40:44.53,Default,,0,0,0,,我应该合并同类项和求和\nDialogue: 0,0:40:45.06,0:40:46.08,Default,,0,0,0,,但这又是另外一回事了\nDialogue: 0,0:40:47.12,0:40:51.86,Default,,0,0,0,,当然啦 完成这个功能的代码就大而复杂了\nDialogue: 0,0:40:52.28,0:40:55.28,Default,,0,0,0,,代数化简 是一项繁复的工作\nDialogue: 0,0:40:56.37,0:41:00.13,Default,,0,0,0,,你们可能听过MIT以前开发的一个非常出名的程序 MAXIMA\nDialogue: 0,0:41:00.42,0:41:03.14,Default,,0,0,0,,它有5000页的LISP代码\nDialogue: 0,0:41:03.92,0:41:06.50,Default,,0,0,0,,大部分是代数化简的操作\nDialogue: 0,0:41:08.08,0:41:12.21,Default,,0,0,0,,这里是FOO的导数\nDialogue: 0,0:41:12.21,0:41:16.86,Default,,0,0,0,,要是我的话 我会在初等微积分课上讲讲“改换主变量”这个东西\nDialogue: 0,0:41:18.38,0:41:22.49,Default,,0,0,0,,以A为自变量 FOO的导数则是X*X\nDialogue: 0,0:41:22.80,0:41:23.80,Default,,0,0,0,,看起来还不差\nDialogue: 0,0:41:24.74,0:41:27.53,Default,,0,0,0,,以B为自变量 FOO的导数则是X本身\nDialogue: 0,0:41:28.06,0:41:30.12,Default,,0,0,0,,以C为自变量 FOO的导数则为“1”\nDialogue: 0,0:41:30.70,0:41:32.04,Default,,0,0,0,,我对这些结果很满意\nDialogue: 0,0:41:34.10,0:41:39.01,Default,,0,0,0,,你所看到的 都是精心设计、仔细规划的例子\nDialogue: 0,0:41:39.56,0:41:42.60,Default,,0,0,0,,用以展示如何操作代数表达式\nDialogue: 0,0:41:42.96,0:41:47.93,Default,,0,0,0,,我们如何不用具体的语法 而用抽象的语法抽象地进行\nDialogue: 0,0:41:49.21,0:41:56.29,Default,,0,0,0,,以及我们如何使用抽象屏障控制构造这些表达式\nDialogue: 0,0:41:57.80,0:42:00.41,Default,,0,0,0,,真正的奥义并不是如此的简单\nDialogue: 0,0:42:01.00,0:42:04.45,Default,,0,0,0,,实际上 真正的奥义在于我在操作这些表达式时\nDialogue: 0,0:42:04.45,0:42:06.72,Default,,0,0,0,,代数表达式和代码表达式--\nDialogue: 0,0:42:06.72,0:42:07.97,Default,,0,0,0,,回过头来看看幻灯片\nDialogue: 0,0:42:08.08,0:42:10.52,Default,,0,0,0,,都是同一种Lisp表达式\nDialogue: 0,0:42:12.02,0:42:12.97,Default,,0,0,0,,这样一语双关 一石二鸟\nDialogue: 0,0:42:13.82,0:42:21.49,Default,,0,0,0,,我用表示代码相同的方法来作为我的表示法\nDialogue: 0,0:42:22.89,0:42:26.52,Default,,0,0,0,,为了要这样做 我得付出点代价\nDialogue: 0,0:42:26.90,0:42:30.34,Default,,0,0,0,,我需要使用类似于“引用”的东西\nDialogue: 0,0:42:30.97,0:42:38.17,Default,,0,0,0,,这是因为 我的语言可以编写讨论语言表达式的表达式\nDialogue: 0,0:42:39.76,0:42:43.22,Default,,0,0,0,,我需要有某种东西指出 这个是我需要讨论的表达式\nDialogue: 0,0:42:43.76,0:42:46.13,Default,,0,0,0,,而不是说 （去求）这个表达式的值\nDialogue: 0,0:42:47.20,0:42:48.44,Default,,0,0,0,,我想要的是前者\nDialogue: 0,0:42:51.34,0:42:55.36,Default,,0,0,0,,引用阻止表达式被求值 其语义为“就是表达式本身”\nDialogue: 0,0:42:57.97,0:43:00.85,Default,,0,0,0,,有了这种能力以后\nDialogue: 0,0:43:01.58,0:43:03.82,Default,,0,0,0,,如果我可以操作语言的表达式\nDialogue: 0,0:43:04.80,0:43:09.00,Default,,0,0,0,,我可以在语言层之上构建更加有力的层次\nDialogue: 0,0:43:09.77,0:43:12.64,Default,,0,0,0,,因为我可以编写不仅仅是内嵌于Lisp的语言\nDialogue: 0,0:43:13.46,0:43:14.80,Default,,0,0,0,,或者是其它的语言\nDialogue: 0,0:43:15.26,0:43:17.76,Default,,0,0,0,,我可以编写一种完全不同的语言\nDialogue: 0,0:43:18.58,0:43:22.24,Default,,0,0,0,,而其实质上则是被Lisp或其它语言所解释\nDialogue: 0,0:43:23.17,0:43:25.46,Default,,0,0,0,,我们以后还会对此有更深入的理解\nDialogue: 0,0:43:26.56,0:43:32.09,Default,,0,0,0,,我现在只是想让你们意识到\nDialogue: 0,0:43:32.36,0:43:34.98,Default,,0,0,0,,我们已经感触到了一种惊人的力量\nDialogue: 0,0:43:36.00,0:43:37.82,Default,,0,0,0,,现在我们有了方天画戟\nDialogue: 0,0:43:38.17,0:43:40.92,Default,,0,0,0,,当我们使用它时 也得万分小心\nDialogue: 0,0:43:42.17,0:43:43.00,Default,,0,0,0,,谢谢大家\nDialogue: 0,0:43:44.10,0:44:00.54,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:43:44.10,0:44:00.54,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec3b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nLast Style Storage: Default\nScroll Position: 581\nActive Line: 593\nVideo Zoom Percent: 0.625\nAudio URI: G:\\untitled\\ref\\lec3b_480_muxed2.mp4\nVideo File: G:\\untitled\\ref\\lec3b_480_muxed2.mp4\nVideo Aspect Ratio: c1.33333\nVideo Position: 79137\nPlayResX: 640\nPlayResY: 480\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:02.32,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP Group\nDialogue: 0,0:00:02.57,0:00:06.01,Declare,,0,0,0,,{\\an2\\fad(500,500)}Translation && Timeline: Dysprosium\\NEncode && Effects: Dysprosium\nDialogue: 0,0:00:06.06,0:00:08.97,Declare,,0,0,0,,{\\an2\\fad(500,500)}Credit: Prof. Qiu Zonyan\nDialogue: 0,0:00:11.24,0:00:14.46,Declare,,0,0,0,,{\\an2\\fad(500,500)}Symbolic Differentiation: Quotation\nDialogue: 0,0:00:19.10,0:00:23.41,EN,,0,0,0,,PROFESSOR: Well, Hal just told us how you build robust systems.\nDialogue: 0,0:00:23.80,0:00:26.17,EN,,0,0,0,,The key idea was--\nDialogue: 0,0:00:26.81,0:00:30.20,EN,,0,0,0,,I'm sure that many of you don't really assimilate that yet--\nDialogue: 0,0:00:30.20,0:00:33.77,EN,,0,0,0,,but the key idea is that in order to make a system that's robust,\nDialogue: 0,0:00:33.93,0:00:36.48,EN,,0,0,0,,it has to be insensitive to small changes,\nDialogue: 0,0:00:36.60,0:00:37.37,EN,,0,0,0,,that is,\nDialogue: 0,0:00:37.37,0:00:40.90,EN,,0,0,0,,a small change in the problem should lead to only a small change in the solution.\nDialogue: 0,0:00:41.32,0:00:42.90,EN,,0,0,0,,There ought to be a continuity.\nDialogue: 0,0:00:42.90,0:00:45.94,EN,,0,0,0,,The space of solutions ought to be continuous in this space of problems.\nDialogue: 0,0:00:46.25,0:00:48.76,EN,,0,0,0,,The way he was explaining how to do that\nDialogue: 0,0:00:49.46,0:00:54.78,EN,,0,0,0,,was instead of solving a particular problem at every level of decomposition of the problem at the subproblems,\nDialogue: 0,0:00:55.08,0:00:56.78,EN,,0,0,0,,where you solve the class of problems,\nDialogue: 0,0:00:56.78,0:01:00.40,EN,,0,0,0,,which are a neighborhood of the particular problem that you're trying to solve.\nDialogue: 0,0:01:01.40,0:01:04.76,EN,,0,0,0,,The way you do that is by producing a language at that level of detail\nDialogue: 0,0:01:04.76,0:01:10.33,EN,,0,0,0,,in which the solutions to that class of problems is representable in that language.\nDialogue: 0,0:01:11.37,0:01:15.09,EN,,0,0,0,,Therefore when you change makes more changes to the problem you're trying to solve,\nDialogue: 0,0:01:15.09,0:01:19.29,EN,,0,0,0,,you generally have to make only small local changes to the solution you've constructed,\nDialogue: 0,0:01:19.29,0:01:22.26,EN,,0,0,0,,because at the level of detail you're working,\nDialogue: 0,0:01:22.26,0:01:24.26,EN,,0,0,0,,there's a language where you can express\nDialogue: 0,0:01:24.80,0:01:28.14,EN,,0,0,0,,the various solutions to alternate problems of the same type.\nDialogue: 0,0:01:30.04,0:01:33.74,EN,,0,0,0,,Well that's the beginning of a very important idea,\nDialogue: 0,0:01:34.40,0:01:38.61,EN,,0,0,0,,the most important perhaps idea that makes computer science more powerful\nDialogue: 0,0:01:38.61,0:01:42.37,EN,,0,0,0,,than most of the other kinds of engineering disciplines we know about.\nDialogue: 0,0:01:43.38,0:01:44.73,EN,,0,0,0,,What we've seen so far\nDialogue: 0,0:01:44.73,0:01:48.78,EN,,0,0,0,,is sort of how to use embedding of languages.\nDialogue: 0,0:01:49.26,0:01:53.36,EN,,0,0,0,,And, of course, the power of embedding languages partly comes from\nDialogue: 0,0:01:54.12,0:01:56.86,EN,,0,0,0,,procedures like this one that I showed you yesterday.\nDialogue: 0,0:01:57.37,0:02:02.13,EN,,0,0,0,,What you see here is the derivative program that we described yesterday.\nDialogue: 0,0:02:02.13,0:02:05.92,EN,,0,0,0,,It's a procedure that takes a procedure as an argument\nDialogue: 0,0:02:06.00,0:02:07.92,EN,,0,0,0,,and returns a procedure as a value.\nDialogue: 0,0:02:09.61,0:02:12.65,EN,,0,0,0,,And using such things is very nice.\nDialogue: 0,0:02:12.65,0:02:14.65,EN,,0,0,0,,You can make things like push combinators\nDialogue: 0,0:02:14.65,0:02:16.86,EN,,0,0,0,,and all that sort of wonderful thing that you saw last time.\nDialogue: 0,0:02:17.68,0:02:20.54,EN,,0,0,0,,However, now I'm going to really muddy the waters.\nDialogue: 0,0:02:21.56,0:02:25.90,EN,,0,0,0,,See this confuses the issue of what's the procedure and what is data,\nDialogue: 0,0:02:26.56,0:02:27.81,EN,,0,0,0,,but not very badly.\nDialogue: 0,0:02:28.42,0:02:30.90,EN,,0,0,0,,What we really want to do is confuse it very badly.\nDialogue: 0,0:02:31.18,0:02:32.44,EN,,0,0,0,,And the best way to do that\nDialogue: 0,0:02:32.44,0:02:37.62,EN,,0,0,0,,is to get involved with the manipulation of the algebraic expressions that the procedures themselves are expressed in.\nDialogue: 0,0:02:39.73,0:02:45.58,EN,,0,0,0,,So at this point, I want to talk about instead of things like on this slide,\nDialogue: 0,0:02:45.89,0:02:49.72,EN,,0,0,0,,the derivative procedure being a thing that manipulates a procedure--\nDialogue: 0,0:02:49.72,0:02:51.94,EN,,0,0,0,,this is a numerical method you see here.\nDialogue: 0,0:02:51.94,0:02:58.93,EN,,0,0,0,,And what you're seeing is a representation of the numerical approximationto the derivative.\nDialogue: 0,0:02:59.29,0:03:00.44,EN,,0,0,0,,That's what's here.\nDialogue: 0,0:03:00.86,0:03:04.93,EN,,0,0,0,,In fact what I'd like to talk about is instead things that look like this.\nDialogue: 0,0:03:06.05,0:03:11.33,EN,,0,0,0,,And what we have here are rules from a calculus book.\nDialogue: 0,0:03:12.09,0:03:16.17,EN,,0,0,0,,These are rules for finding the derivatives of the expressions\nDialogue: 0,0:03:16.70,0:03:20.58,EN,,0,0,0,,that one might write in some algebraic language.\nDialogue: 0,0:03:21.64,0:03:24.41,EN,,0,0,0,,It says things like a derivative of a constant is 0.\nDialogue: 0,0:03:25.13,0:03:29.09,EN,,0,0,0,,The derivative of the valuable with respect to which you are taking the derivative is 1.\nDialogue: 0,0:03:29.32,0:03:31.93,EN,,0,0,0,,The derivative of a constant times the function\nDialogue: 0,0:03:32.09,0:03:34.37,EN,,0,0,0,,is the constant times the derivative of the function,\nDialogue: 0,0:03:34.77,0:03:36.04,EN,,0,0,0,,and things like that.\nDialogue: 0,0:03:38.05,0:03:41.38,EN,,0,0,0,,These are exact expressions. These are not numerical approximations.\nDialogue: 0,0:03:42.96,0:03:44.52,EN,,0,0,0,,Can we make programs?\nDialogue: 0,0:03:44.52,0:03:52.24,EN,,0,0,0,,And, in fact, it's very easy to make programs that manipulate these expressions.\nDialogue: 0,0:03:56.38,0:03:59.52,EN,,0,0,0,,Well let's see. Let's look at these rules in some detail.\nDialogue: 0,0:04:01.08,0:04:05.22,EN,,0,0,0,,You all have seen these rules in your elementary calculus class at one time or another.\nDialogue: 0,0:04:05.98,0:04:12.12,EN,,0,0,0,,And you know from calculus that it's easy to produce derivatives of arbitrary expressions.\nDialogue: 0,0:04:12.53,0:04:16.05,EN,,0,0,0,,You also know from your elementary calculus that it's hard to produce integrals.\nDialogue: 0,0:04:16.98,0:04:19.37,EN,,0,0,0,,Yet integrals and derivatives are opposites of each other.\nDialogue: 0,0:04:19.52,0:04:21.28,EN,,0,0,0,,They're inverse operations.\nDialogue: 0,0:04:21.61,0:04:23.30,EN,,0,0,0,,And they have the same rules.\nDialogue: 0,0:04:24.16,0:04:29.68,EN,,0,0,0,,What is special about these rules that makes it possible for one\nDialogue: 0,0:04:29.68,0:04:33.65,EN,,0,0,0,,to produce derivatives easily and integrals why it's so hard?\nDialogue: 0,0:04:34.85,0:04:36.98,EN,,0,0,0,,Let's think about that very simply.\nDialogue: 0,0:04:37.40,0:04:38.38,EN,,0,0,0,,Look at these rules.\nDialogue: 0,0:04:39.36,0:04:43.06,EN,,0,0,0,,Every one of these rules, when used in the direction for taking derivatives,\nDialogue: 0,0:04:43.06,0:04:44.80,EN,,0,0,0,,which is in the direction of this arrow,\nDialogue: 0,0:04:46.68,0:04:49.16,EN,,0,0,0,,the left side is matched against your expression,\nDialogue: 0,0:04:49.16,0:04:53.05,EN,,0,0,0,,and the right side is the thing which is the derivative of that expression.\nDialogue: 0,0:04:54.02,0:04:55.65,EN,,0,0,0,,The arrow is going that way.\nDialogue: 0,0:04:57.37,0:05:00.45,EN,,0,0,0,,In each of these rules,\nDialogue: 0,0:05:01.24,0:05:03.72,EN,,0,0,0,,the expressions on the right-hand side of the rule\nDialogue: 0,0:05:03.72,0:05:06.56,EN,,0,0,0,,that are contained within derivatives are subexpressions,\nDialogue: 0,0:05:06.56,0:05:10.29,EN,,0,0,0,,are proper subexpressions, of the expression on the left-hand side.\nDialogue: 0,0:05:10.60,0:05:13.25,EN,,0,0,0,,So here we see the derivative of the sum,\nDialogue: 0,0:05:13.92,0:05:16.13,EN,,0,0,0,,witch is the expression on the left-hand side\nDialogue: 0,0:05:16.13,0:05:18.38,EN,,0,0,0,,is the sum of the derivatives of the pieces.\nDialogue: 0,0:05:20.08,0:05:24.49,EN,,0,0,0,,So the rule of moving to the right are reduction rules.\nDialogue: 0,0:05:25.02,0:05:26.61,EN,,0,0,0,,The problem becomes easier.\nDialogue: 0,0:05:27.56,0:05:31.48,EN,,0,0,0,,I make, I turn a big complicated problem it's lots of smaller problems\nDialogue: 0,0:05:32.44,0:05:35.76,EN,,0,0,0,,and then combine the results, a perfect place for recursion to work.\nDialogue: 0,0:05:36.58,0:05:40.85,EN,,0,0,0,,If I'm going in the other direction like this,\nDialogue: 0,0:05:41.81,0:05:45.13,EN,,0,0,0,,if I'm trying to produce integrals, well there are several problems you see here.\nDialogue: 0,0:05:45.24,0:05:49.09,EN,,0,0,0,,First of all, if I try to integrate an expression like a sum,\nDialogue: 0,0:05:49.21,0:05:50.81,EN,,0,0,0,,more than one rule matches.\nDialogue: 0,0:05:50.81,0:05:52.10,EN,,0,0,0,,Here's one that matches.\nDialogue: 0,0:05:52.48,0:05:53.65,EN,,0,0,0,,Here's one that matches.\nDialogue: 0,0:05:54.81,0:05:57.09,EN,,0,0,0,,I don't know which one to take. And they may be different.\nDialogue: 0,0:05:57.70,0:06:00.00,EN,,0,0,0,,I may get to explore different things.\nDialogue: 0,0:06:00.25,0:06:03.64,EN,,0,0,0,,Also, the expressions become larger in that direction.\nDialogue: 0,0:06:04.53,0:06:06.30,EN,,0,0,0,,And when the expressions become larger,\nDialogue: 0,0:06:06.30,0:06:10.56,EN,,0,0,0,,then there's no guarantee that any particular path I choose will terminate,\nDialogue: 0,0:06:10.94,0:06:13.46,EN,,0,0,0,,because we will only terminate by accidental cancellation.\nDialogue: 0,0:06:14.24,0:06:18.05,EN,,0,0,0,,So that's why integrals are complicated searches and hard to do.\nDialogue: 0,0:06:19.12,0:06:20.96,EN,,0,0,0,,Right now I don't want to do anything as hard as that.\nDialogue: 0,0:06:21.49,0:06:23.06,EN,,0,0,0,,Let's work on derivatives for a while.\nDialogue: 0,0:06:24.14,0:06:28.13,EN,,0,0,0,,Well, these rules are ones you know for the most part hopefully.\nDialogue: 0,0:06:28.78,0:06:31.88,EN,,0,0,0,,So let's see if we can write a program which is these rules.\nDialogue: 0,0:06:32.22,0:06:33.72,EN,,0,0,0,,And that should be very easy.\nDialogue: 0,0:06:34.89,0:06:36.21,EN,,0,0,0,,Just write the program.\nDialogue: 0,0:06:36.69,0:06:39.29,EN,,0,0,0,,See, because while I showed you is that it's a reduction rule,\nDialogue: 0,0:06:39.29,0:06:41.29,EN,,0,0,0,,it's something appropriate for a recursion.\nDialogue: 0,0:06:43.08,0:06:45.72,EN,,0,0,0,,And, of course, what we have for each of these rules is we have a case\nDialogue: 0,0:06:46.66,0:06:47.78,EN,,0,0,0,,in some case analysis.\nDialogue: 0,0:06:48.58,0:06:50.36,EN,,0,0,0,,So I'm just going to write this program down.\nDialogue: 0,0:06:52.88,0:06:57.69,EN,,0,0,0,,Now, of course, I'm going to be saying something you have to believe. Right?\nDialogue: 0,0:06:57.69,0:07:00.33,EN,,0,0,0,,What you have to believe is I can represent these algebraic expressions,\nDialogue: 0,0:07:00.68,0:07:03.88,EN,,0,0,0,,that I can grab their parts, that I can put them together.\nDialogue: 0,0:07:04.24,0:07:06.49,EN,,0,0,0,,We've invented list structures so that you can do that.\nDialogue: 0,0:07:07.52,0:07:09.14,EN,,0,0,0,,But you don't want to worry about that now.\nDialogue: 0,0:07:09.66,0:07:12.45,EN,,0,0,0,,Right now I'm going to write the program that encapsulates these rules\nDialogue: 0,0:07:12.76,0:07:15.85,EN,,0,0,0,,independent of the representation of the algebraic expressions.\nDialogue: 0,0:07:20.42,0:07:28.84,EN,,0,0,0,,You have a derivative of an expression with respect to a variable.\nDialogue: 0,0:07:30.50,0:07:33.08,EN,,0,0,0,,This is a different thing than the derivative of the function.\nDialogue: 0,0:07:34.82,0:07:38.61,EN,,0,0,0,,That's what we saw last time, that numerical approximation.\nDialogue: 0,0:07:39.00,0:07:40.82,EN,,0,0,0,,It's something you can't open up a function.\nDialogue: 0,0:07:40.82,0:07:41.89,EN,,0,0,0,,It's just the answers.\nDialogue: 0,0:07:43.09,0:07:45.18,EN,,0,0,0,,The derivative of an expression is the way it's written.\nDialogue: 0,0:07:45.74,0:07:47.85,EN,,0,0,0,,And therefore it's a syntactic phenomenon.\nDialogue: 0,0:07:48.29,0:07:51.62,EN,,0,0,0,,And so a lot of what we're going to be doing today is worrying about syntax,\nDialogue: 0,0:07:52.33,0:07:54.12,EN,,0,0,0,,syntax of expressions and things like that.\nDialogue: 0,0:07:54.70,0:07:55.93,EN,,0,0,0,,Well, there's a case analysis.\nDialogue: 0,0:07:57.50,0:08:01.08,EN,,0,0,0,,Anytime we do anything complicated thereby a recursion,\nDialogue: 0,0:08:01.08,0:08:02.64,EN,,0,0,0,,we presumably need a case analysis.\nDialogue: 0,0:08:03.62,0:08:05.16,EN,,0,0,0,,It's the essential way to begin.\nDialogue: 0,0:08:05.16,0:08:07.40,EN,,0,0,0,,And that's usually a conditional of some large kind.\nDialogue: 0,0:08:08.08,0:08:09.97,EN,,0,0,0,,Well, what are their possibilities?\nDialogue: 0,0:08:09.97,0:08:12.53,EN,,0,0,0,,the first rule that you saw is this something a constant?\nDialogue: 0,0:08:16.50,0:08:17.50,EN,,0,0,0,,And what I'm asking is,\nDialogue: 0,0:08:17.50,0:08:22.22,EN,,0,0,0,,is the expression a constant with respect to the variable given?\nDialogue: 0,0:08:24.90,0:08:27.08,EN,,0,0,0,,If so, the result is 0,\nDialogue: 0,0:08:27.50,0:08:30.10,EN,,0,0,0,,because the derivative represents the rate of change of something.\nDialogue: 0,0:08:31.76,0:08:32.65,EN,,0,0,0,,If, however,\nDialogue: 0,0:08:32.89,0:08:40.69,EN,,0,0,0,,the expression that I'm taking the derivative of is the variable I'm varying,\nDialogue: 0,0:08:41.72,0:08:50.42,EN,,0,0,0,,then this is the same variable, the expression var,\nDialogue: 0,0:08:51.14,0:08:54.52,EN,,0,0,0,,then the rate of change of the expression with respect to the variable is 1.\nDialogue: 0,0:08:55.50,0:08:56.54,EN,,0,0,0,,It's the same 1.\nDialogue: 0,0:08:58.90,0:09:00.77,EN,,0,0,0,,Well now there are a couple of other possibilities.\nDialogue: 0,0:09:01.33,0:09:03.14,EN,,0,0,0,,It could, for example, be a sum.\nDialogue: 0,0:09:03.86,0:09:05.88,EN,,0,0,0,,Well, I don't know how I'm going to express sums yet.\nDialogue: 0,0:09:06.09,0:09:08.25,EN,,0,0,0,,Actually I do. But I haven't told you yet.\nDialogue: 0,0:09:10.34,0:09:11.78,EN,,0,0,0,,But is it a sum?\nDialogue: 0,0:09:12.48,0:09:14.48,EN,,0,0,0,,I'm imagining that there's some way of telling.\nDialogue: 0,0:09:15.30,0:09:19.44,EN,,0,0,0,,I'm doing a dispatch on the type of the expression here,\nDialogue: 0,0:09:20.77,0:09:23.57,EN,,0,0,0,,absolutely essential in building languages.\nDialogue: 0,0:09:24.72,0:09:26.37,EN,,0,0,0,,Cause languages are made out of different expressions.\nDialogue: 0,0:09:26.48,0:09:27.54,EN,,0,0,0,,And soon we're going to see that\nDialogue: 0,0:09:27.84,0:09:31.02,EN,,0,0,0,,in our more powerful methods of building languages on languages.\nDialogue: 0,0:09:32.53,0:09:34.02,EN,,0,0,0,,Is an expression a sum?\nDialogue: 0,0:09:35.45,0:09:38.82,EN,,0,0,0,,If it's a sum, well, we know the rule for derivative of the sum\nDialogue: 0,0:09:38.82,0:09:41.33,EN,,0,0,0,,is the sum of the derivatives of the parts.\nDialogue: 0,0:09:42.13,0:09:44.32,EN,,0,0,0,,One of them is called the addend and the other is the augend.\nDialogue: 0,0:09:44.32,0:09:46.80,EN,,0,0,0,,But I don't have enough space on the blackboard to such long names.\nDialogue: 0,0:09:46.80,0:09:48.40,EN,,0,0,0,,So I'll call them A1 and A2.\nDialogue: 0,0:09:49.04,0:09:50.37,EN,,0,0,0,,I want to make a sum.\nDialogue: 0,0:09:53.53,0:09:55.68,EN,,0,0,0,,Do you remember which is the sub for head or the menu end?\nDialogue: 0,0:09:57.14,0:10:01.09,EN,,0,0,0,,Or was it the dividend and the divisor or something like that?\nDialogue: 0,0:10:01.65,0:10:08.48,EN,,0,0,0,,Make sum of the derivative of the A1, I'll call it.\nDialogue: 0,0:10:08.48,0:10:13.29,EN,,0,0,0,,It's the addend of the expression with respect to the variable,\nDialogue: 0,0:10:14.84,0:10:22.76,EN,,0,0,0,,and the derivative of the A2 of the expression,\nDialogue: 0,0:10:24.12,0:10:28.25,EN,,0,0,0,,those the two arguments, the addition. Respect to the variable.\nDialogue: 0,0:10:32.36,0:10:34.93,EN,,0,0,0,,And another rule that we know is product rule,\nDialogue: 0,0:10:35.20,0:10:37.44,EN,,0,0,0,,which is, if the expression is a product.\nDialogue: 0,0:10:43.21,0:10:46.10,EN,,0,0,0,,By the way, it's a good idea when you're defining things,\nDialogue: 0,0:10:46.96,0:10:48.32,EN,,0,0,0,,when you're defining predicates,\nDialogue: 0,0:10:48.85,0:10:50.96,EN,,0,0,0,,to give them a name that ends in a question mark.\nDialogue: 0,0:10:51.08,0:10:52.89,EN,,0,0,0,,This question mark doesn't mean anything.\nDialogue: 0,0:10:53.10,0:10:54.50,EN,,0,0,0,,It's for us as an agreement.\nDialogue: 0,0:10:54.61,0:10:58.94,EN,,0,0,0,,It's a conventional interface between humans so you can read my programs more easily.\nDialogue: 0,0:11:00.05,0:11:01.96,EN,,0,0,0,,So I want you to, when you write programs,\nDialogue: 0,0:11:01.96,0:11:03.73,EN,,0,0,0,,if you define a predicate procedure,\nDialogue: 0,0:11:04.01,0:11:05.77,EN,,0,0,0,,that's something that returns true of false,\nDialogue: 0,0:11:05.94,0:11:07.84,EN,,0,0,0,,it should have a name which ends in question mark.\nDialogue: 0,0:11:08.02,0:11:10.34,EN,,0,0,0,,The lisp doesn't care. I care.\nDialogue: 0,0:11:11.62,0:11:13.14,EN,,0,0,0,,I want to make a sum.\nDialogue: 0,0:11:13.14,0:11:17.49,EN,,0,0,0,,Because the product, the derivative of a product is the sum\nDialogue: 0,0:11:17.94,0:11:19.64,EN,,0,0,0,,of the first times the derivative of the second plus\nDialogue: 0,0:11:19.66,0:11:20.70,EN,,0,0,0,,the second times the derivative of the first.\nDialogue: 0,0:11:23.54,0:11:27.06,EN,,0,0,0,,Make a sum of two things,\nDialogue: 0,0:11:29.64,0:11:38.33,EN,,0,0,0,,a product of, well, I'm going to say the M1 of the expression,\nDialogue: 0,0:11:39.85,0:11:48.97,EN,,0,0,0,,and the derivative of the M2 of the expression with respect to the variable,\nDialogue: 0,0:11:51.90,0:12:06.28,EN,,0,0,0,,and the product of the derivative of M1,\nDialogue: 0,0:12:07.10,0:12:11.92,EN,,0,0,0,,the multiplier of the expression, with respect to the variable.\nDialogue: 0,0:12:13.32,0:12:18.05,EN,,0,0,0,,And the product of that and the multiplicand, M2, of the expression.\nDialogue: 0,0:12:20.64,0:12:24.89,EN,,0,0,0,,Make that product. Make the sum. Close that case.\nDialogue: 0,0:12:24.96,0:12:28.02,EN,,0,0,0,,And, of course, I could add as many cases as I like here\nDialogue: 0,0:12:28.32,0:12:30.82,EN,,0,0,0,,for a complete set of rules you might find in a calculus book.\nDialogue: 0,0:12:34.80,0:12:39.45,EN,,0,0,0,,So this is what it takes to encapsulate those rules.\nDialogue: 0,0:12:41.53,0:12:43.90,EN,,0,0,0,,And you see, you have to realize there's a lot of wishful thinking here.\nDialogue: 0,0:12:44.54,0:12:47.56,EN,,0,0,0,,I haven't told you anything about how I'm going to make these representations.\nDialogue: 0,0:12:48.46,0:12:51.92,EN,,0,0,0,,Now, once I've decided that this is my set of rules,\nDialogue: 0,0:12:52.52,0:12:55.20,EN,,0,0,0,,I think it's time to play with the representation.\nDialogue: 0,0:12:55.66,0:12:56.69,EN,,0,0,0,,Let's attack that.\nDialogue: 0,0:12:57.96,0:13:00.00,EN,,0,0,0,,Well, first of all, I'm going to play a pun.\nDialogue: 0,0:13:00.90,0:13:02.12,EN,,0,0,0,,It's an important pun.\nDialogue: 0,0:13:02.74,0:13:06.56,EN,,0,0,0,,It's a key to a sort of powerful idea.\nDialogue: 0,0:13:09.62,0:13:14.41,EN,,0,0,0,,If I want to represent sums, and products, and differences, and quotients, and things like that,\nDialogue: 0,0:13:15.22,0:13:18.62,EN,,0,0,0,,why not use the same language as I'm writing my program in?\nDialogue: 0,0:13:20.50,0:13:23.64,EN,,0,0,0,,I write my program it algebraic expressions that look like\nDialogue: 0,0:13:23.98,0:13:30.45,EN,,0,0,0,,the sum of the product on a and the product of x and x,\nDialogue: 0,0:13:32.60,0:13:33.80,EN,,0,0,0,,and things like that.\nDialogue: 0,0:13:34.28,0:13:38.50,EN,,0,0,0,,And the product of b and x and c, whatever,\nDialogue: 0,0:13:38.50,0:13:39.97,EN,,0,0,0,,make that a sum of the product.\nDialogue: 0,0:13:40.77,0:13:44.09,EN,,0,0,0,,Right now I don't want to have procedures with unknown numbers of arguments,\nDialogue: 0,0:13:44.93,0:13:48.46,EN,,0,0,0,,a product of b and x and c.\nDialogue: 0,0:13:51.42,0:13:52.44,EN,,0,0,0,,This is list structure.\nDialogue: 0,0:13:54.12,0:13:55.74,EN,,0,0,0,,And the reason why this is nice,\nDialogue: 0,0:13:55.90,0:13:58.33,EN,,0,0,0,,is because any one of these objects has a property.\nDialogue: 0,0:13:58.92,0:14:01.53,EN,,0,0,0,,I know where, know where the car is.\nDialogue: 0,0:14:01.96,0:14:03.21,EN,,0,0,0,,The car is the operator.\nDialogue: 0,0:14:03.92,0:14:06.38,EN,,0,0,0,,And the operands are the successive cdrs\nDialogue: 0,0:14:07.22,0:14:10.36,EN,,0,0,0,,the successive cars of the cdrs of the list that this is.\nDialogue: 0,0:14:12.48,0:14:13.88,EN,,0,0,0,,It makes it very convenient.\nDialogue: 0,0:14:14.01,0:14:16.40,EN,,0,0,0,,Ir have to parse it. It's been done for me.\nDialogue: 0,0:14:17.42,0:14:20.01,EN,,0,0,0,,I'm using the embedding in Lisp to advantage.\nDialogue: 0,0:14:22.66,0:14:23.77,EN,,0,0,0,,So, for example,\nDialogue: 0,0:14:25.08,0:14:33.97,EN,,0,0,0,,Let's start using list structure to write down the representation that I'm implicitly assuming here.\nDialogue: 0,0:14:35.25,0:14:38.34,EN,,0,0,0,,Well I have to define various things that are implied in this representation.\nDialogue: 0,0:14:38.54,0:14:40.90,EN,,0,0,0,,Like I have to find out how to do a constant,\nDialogue: 0,0:14:41.21,0:14:42.30,EN,,0,0,0,,how you do same variable.\nDialogue: 0,0:14:42.40,0:14:45.04,EN,,0,0,0,,Let's do those first. That's pretty easy enough.\nDialogue: 0,0:14:45.78,0:14:47.70,EN,,0,0,0,,Now I'm going to be introducing lots of primitives here,\nDialogue: 0,0:14:48.60,0:14:50.50,EN,,0,0,0,,because these are the primitives that come with list structure.\nDialogue: 0,0:14:51.98,0:14:53.46,EN,,0,0,0,,OK, you define a constant.\nDialogue: 0,0:15:02.25,0:15:04.29,EN,,0,0,0,,And what I mean by a constant,\nDialogue: 0,0:15:04.29,0:15:07.73,EN,,0,0,0,,an expression is constant with respect to a variable.\nDialogue: 0,0:15:09.05,0:15:11.60,EN,,0,0,0,,is that the expression is something simple.\nDialogue: 0,0:15:11.60,0:15:14.46,EN,,0,0,0,,I can't take it into pieces, and yet it isn't that variable.\nDialogue: 0,0:15:16.58,0:15:18.78,EN,,0,0,0,,I can't break it up, and yet it isn't that variable.\nDialogue: 0,0:15:18.90,0:15:25.12,EN,,0,0,0,,That does not mean that there may be other expressions that are more complicated that are constants.\nDialogue: 0,0:15:25.20,0:15:28.92,EN,,0,0,0,,It's just that I'm going to look at the primitive constants in this way.\nDialogue: 0,0:15:29.74,0:15:33.41,EN,,0,0,0,,So what this is, is it says that's it's the and.\nDialogue: 0,0:15:34.02,0:15:37.82,EN,,0,0,0,,I can combine predicate expressions which return true or false with and.\nDialogue: 0,0:15:38.62,0:15:46.82,EN,,0,0,0,,Something atomic, The expression is atomic, meaning it cannot be broken into parts.\nDialogue: 0,0:15:46.82,0:15:48.53,EN,,0,0,0,,It doesn't have a car and a cdr.\nDialogue: 0,0:15:49.45,0:15:50.21,EN,,0,0,0,,It's not a list.\nDialogue: 0,0:15:50.76,0:15:52.94,EN,,0,0,0,,And it's a special test built into the system.\nDialogue: 0,0:15:53.97,0:16:04.66,EN,,0,0,0,,And it's not identically equal to that variable.\nDialogue: 0,0:16:06.82,0:16:13.36,EN,,0,0,0,,I'm representing my variables by things that are symbols which cannot be broken into pieces,\nDialogue: 0,0:16:13.90,0:16:17.22,EN,,0,0,0,,things like x, and y, things like this.\nDialogue: 0,0:16:19.74,0:16:22.37,EN,,0,0,0,,Whereas, of course, something like this can be broken up into pieces.\nDialogue: 0,0:16:24.74,0:16:46.40,EN,,0,0,0,,And the same variable of an expression with respect to a variable is,\nDialogue: 0,0:16:46.40,0:16:48.40,EN,,0,0,0,,in fact, an atomic expression.\nDialogue: 0,0:16:48.77,0:16:59.61,EN,,0,0,0,,I want to have an atomic expression, which is identical.\nDialogue: 0,0:17:07.90,0:17:11.68,EN,,0,0,0,,I don't want to look inside this, this stuff anymore.\nDialogue: 0,0:17:12.52,0:17:15.56,EN,,0,0,0,,These are primitive maybe.\nDialogue: 0,0:17:15.77,0:17:17.08,EN,,0,0,0,,But it doesn't matter.\nDialogue: 0,0:17:17.78,0:17:21.74,EN,,0,0,0,,I'm defining... I'm using things that are given to me with a language.\nDialogue: 0,0:17:22.42,0:17:24.04,EN,,0,0,0,,I'm not terribly interest in them.\nDialogue: 0,0:17:24.42,0:17:26.04,EN,,0,0,0,,Now how do we deal with sums?\nDialogue: 0,0:17:26.60,0:17:28.80,EN,,0,0,0,,Ah, something very interesting will happen.\nDialogue: 0,0:17:28.98,0:17:33.12,EN,,0,0,0,,A sum is something which is not atomic and begins with the plus symbol.\nDialogue: 0,0:17:35.16,0:17:36.17,EN,,0,0,0,,That's what it means.\nDialogue: 0,0:17:36.65,0:17:39.77,EN,,0,0,0,,So here, I will define.\nDialogue: 0,0:17:45.46,0:17:57.77,EN,,0,0,0,,An expression is a sum if and it's not atomic\nDialogue: 0,0:18:04.57,0:18:15.45,EN,,0,0,0,,and it's head, it's beginning, its car of the expression is the symbol plus.\nDialogue: 0,0:18:19.74,0:18:24.04,EN,,0,0,0,,Now you're about to see something you haven't seen before, this quotation.\nDialogue: 0,0:18:25.89,0:18:28.22,EN,,0,0,0,,Why do I have that quotation there?\nDialogue: 0,0:18:29.48,0:18:30.52,EN,,0,0,0,,PROFESSOR: Say your name,\nDialogue: 0,0:18:30.68,0:18:31.41,EN,,0,0,0,,AUDIENCE: Susanna.\nDialogue: 0,0:18:31.41,0:18:32.01,EN,,0,0,0,,PROFESSOR: Louder.\nDialogue: 0,0:18:32.01,0:18:32.72,EN,,0,0,0,,AUDIENCE: Susanna\nDialogue: 0,0:18:33.25,0:18:34.21,EN,,0,0,0,,PROFESSOR: Say your name.\nDialogue: 0,0:18:34.21,0:18:34.85,EN,,0,0,0,,AUDIENCE: Your name.\nDialogue: 0,0:18:34.92,0:18:35.68,EN,,0,0,0,,PROFESSOR: Louder.\nDialogue: 0,0:18:35.77,0:18:36.61,EN,,0,0,0,,AUDIENCE: Your name.\nDialogue: 0,0:18:36.82,0:18:37.50,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:18:38.28,0:18:44.56,EN,,0,0,0,,What I'm showing you here is that the words of English are ambiguous.\nDialogue: 0,0:18:45.50,0:18:50.76,EN,,0,0,0,,I was saying, say your name.\nDialogue: 0,0:18:51.97,0:18:57.21,EN,,0,0,0,,I was also possibly saying say, your name.\nDialogue: 0,0:19:00.72,0:19:02.98,EN,,0,0,0,,But that cannot be distinguished in speech.\nDialogue: 0,0:19:03.89,0:19:08.01,EN,,0,0,0,,However, we do have a notation in writing,\nDialogue: 0,0:19:08.18,0:19:12.46,EN,,0,0,0,,which is quotation for distinguishing these two possible meanings.\nDialogue: 0,0:19:14.00,0:19:15.64,EN,,0,0,0,,In particular, over here,\nDialogue: 0,0:19:16.49,0:19:20.84,EN,,0,0,0,,in Lisp we have a notation for distinguishing these meanings.\nDialogue: 0,0:19:21.34,0:19:24.45,EN,,0,0,0,,If I were to just write a plus here, a plus symbol,\nDialogue: 0,0:19:24.64,0:19:28.52,EN,,0,0,0,,I would be asking, is the first element of the expression,\nDialogue: 0,0:19:29.06,0:19:33.61,EN,,0,0,0,,is the operator position of the expression, the addition operator?\nDialogue: 0,0:19:34.65,0:19:35.54,EN,,0,0,0,,I don't know.\nDialogue: 0,0:19:36.22,0:19:38.16,EN,,0,0,0,,I would have to have written the addition operator there,\nDialogue: 0,0:19:39.37,0:19:40.44,EN,,0,0,0,,which I can't write.\nDialogue: 0,0:19:41.34,0:19:45.88,EN,,0,0,0,,However, this way I'm asking, is this the symbolic object plus,\nDialogue: 0,0:19:45.98,0:19:48.14,EN,,0,0,0,,which normally stands for the addition operator?\nDialogue: 0,0:19:49.57,0:19:51.92,EN,,0,0,0,,That's what I want. That's the question I want to ask.\nDialogue: 0,0:19:52.92,0:19:54.45,EN,,0,0,0,,Now before I go any further,\nDialogue: 0,0:19:54.45,0:19:57.81,EN,,0,0,0,,I want to point out the quotation is a very complex concept,\nDialogue: 0,0:19:58.85,0:20:01.84,EN,,0,0,0,,and adding it to a language causes a great deal of troubles.\nDialogue: 0,0:20:03.57,0:20:05.04,EN,,0,0,0,,Consider the next slide.\nDialogue: 0,0:20:06.38,0:20:09.49,EN,,0,0,0,,Here's a deduction which we should all agree with.\nDialogue: 0,0:20:11.62,0:20:17.04,EN,,0,0,0,,We have, Alyssa is smart and Alyssa is George's mother.\nDialogue: 0,0:20:17.40,0:20:20.60,EN,,0,0,0,,This is an equality, is.\nDialogue: 0,0:20:22.13,0:20:26.30,EN,,0,0,0,,From those two, we can deduce that George's mother is smart.\nDialogue: 0,0:20:27.32,0:20:33.16,EN,,0,0,0,,Because we can always substitute equals for equals in expressions.\nDialogue: 0,0:20:34.09,0:20:35.16,EN,,0,0,0,,Or can we?\nDialogue: 0,0:20:36.52,0:20:40.37,EN,,0,0,0,,Here's a case where we have \"Chicago\" has seven letters.\nDialogue: 0,0:20:41.12,0:20:44.86,EN,,0,0,0,,The quotation means that I'm discussing the word Chicago,\nDialogue: 0,0:20:44.86,0:20:46.86,EN,,0,0,0,,not what the word represents.\nDialogue: 0,0:20:49.82,0:20:52.77,EN,,0,0,0,,Here I have that Chicago is the biggest city in Illinois.\nDialogue: 0,0:20:54.61,0:20:55.80,EN,,0,0,0,,As a consequence of this,\nDialogue: 0,0:20:55.80,0:20:59.09,EN,,0,0,0,,I would like to deduce that the biggest city in Illinois has seven letters.\nDialogue: 0,0:20:59.32,0:21:01.06,EN,,0,0,0,,But that's manifestly false.\nDialogue: 0,0:21:05.16,0:21:07.17,EN,,0,0,0,,Wow, it works.\nDialogue: 0,0:21:09.29,0:21:12.24,EN,,0,0,0,,OK, so once we have things like that,\nDialogue: 0,0:21:12.48,0:21:14.49,EN,,0,0,0,,our language gets much more complicated.\nDialogue: 0,0:21:14.49,0:21:18.34,EN,,0,0,0,,Because it's no longer true that things we tend to like to do with languages,\nDialogue: 0,0:21:18.34,0:21:20.76,EN,,0,0,0,,like substituting equals for equals and getting right answers,\nDialogue: 0,0:21:21.29,0:21:23.50,EN,,0,0,0,,are going to work without being very careful.\nDialogue: 0,0:21:24.49,0:21:27.34,EN,,0,0,0,,We can't substitute into what's called referentially opaque contexts,\nDialogue: 0,0:21:27.89,0:21:32.64,EN,,0,0,0,,of which a quotation is the prototypical type of referentially opaque context.\nDialogue: 0,0:21:33.17,0:21:35.28,EN,,0,0,0,,If you know what that means, you can consult a philosopher.\nDialogue: 0,0:21:35.42,0:21:37.02,EN,,0,0,0,,Presumably there is one in the room.\nDialogue: 0,0:21:37.53,0:21:41.32,EN,,0,0,0,,In any case, let's continue now,\nDialogue: 0,0:21:41.32,0:21:44.98,EN,,0,0,0,,now that we at least have an operational understanding of a 2000-year-old issue\nDialogue: 0,0:21:45.26,0:21:48.13,EN,,0,0,0,,that has to do with name, and mention, and all sorts of things like that.\nDialogue: 0,0:21:52.32,0:22:01.60,EN,,0,0,0,,I have to define what I mean, how to make a sum of two things, an a1 and a2.\nDialogue: 0,0:22:02.12,0:22:03.62,EN,,0,0,0,,And I'm going to do this very simply.\nDialogue: 0,0:22:03.62,0:22:11.96,EN,,0,0,0,,It's a list of the symbol plus, and a1, and a2.\nDialogue: 0,0:22:13.86,0:22:17.37,EN,,0,0,0,,And I can determine the first element.\nDialogue: 0,0:22:21.84,0:22:25.32,EN,,0,0,0,,Define a1 to be cadr.\nDialogue: 0,0:22:33.88,0:22:35.90,EN,,0,0,0,,I've just introduced another primitive.\nDialogue: 0,0:22:36.17,0:22:39.10,EN,,0,0,0,,This is the car of the cdr of something.\nDialogue: 0,0:22:39.80,0:22:44.53,EN,,0,0,0,,You might want to know why car and cdr are names of these primitives,\nDialogue: 0,0:22:44.66,0:22:48.42,EN,,0,0,0,,and why they've survived, even though they're much better ideas like left and right.\nDialogue: 0,0:22:48.76,0:22:50.44,EN,,0,0,0,,We could have called them things like that.\nDialogue: 0,0:22:51.28,0:22:56.25,EN,,0,0,0,,Well, first of all, the names come from the fact that in the great past, when Lisp was invented,\nDialogue: 0,0:22:56.36,0:23:00.80,EN,,0,0,0,,I suppose in '58 or something, it was on a 704 or something like that,\nDialogue: 0,0:23:00.80,0:23:05.41,EN,,0,0,0,,which had a machine. It was a machine that had an address register and a decrement register.\nDialogue: 0,0:23:05.41,0:23:08.17,EN,,0,0,0,,And these were the contents of the address register and the decrement register.\nDialogue: 0,0:23:08.17,0:23:09.37,EN,,0,0,0,,So it's an historical accident.\nDialogue: 0,0:23:09.64,0:23:11.28,EN,,0,0,0,,Now why have these names survived?\nDialogue: 0,0:23:11.74,0:23:14.76,EN,,0,0,0,,It's because Lisp programmers like to talk to each other over the phone.\nDialogue: 0,0:23:15.68,0:23:19.60,EN,,0,0,0,,And if you want to have a long sequence of cars and cdrs you might say, cdaddedr,\nDialogue: 0,0:23:21.01,0:23:22.32,EN,,0,0,0,,which can be understood.\nDialogue: 0,0:23:22.32,0:23:27.02,EN,,0,0,0,,But left of right or right of left is not so clear if you get good at it.\nDialogue: 0,0:23:27.60,0:23:30.02,EN,,0,0,0,,So that's why we have these words.\nDialogue: 0,0:23:30.54,0:23:34.14,EN,,0,0,0,,All of them up to four deep are defined typically in a Lisp system.\nDialogue: 0,0:23:38.66,0:23:47.05,EN,,0,0,0,,A2 to be-- and, of course, you can see that if I looked at one of these expressions\nDialogue: 0,0:23:47.36,0:23:52.14,EN,,0,0,0,,like the sum of 3 and 5,\nDialogue: 0,0:23:52.58,0:24:10.45,EN,,0,0,0,,what that is is a list containing the symbol plus, and a number 3, and a number 5.\nDialogue: 0,0:24:11.72,0:24:15.18,EN,,0,0,0,,Then the car is the symbol plus.\nDialogue: 0,0:24:16.13,0:24:18.21,EN,,0,0,0,,The car of the cdr.\nDialogue: 0,0:24:18.21,0:24:20.21,EN,,0,0,0,,Well I take the cdr and then I take the car.\nDialogue: 0,0:24:20.21,0:24:22.21,EN,,0,0,0,,And that's how I get to the 3. That's the first argument.\nDialogue: 0,0:24:22.52,0:24:25.69,EN,,0,0,0,,And the car of the cdr of the cdr gets me to this one, the 5.\nDialogue: 0,0:24:28.69,0:24:33.66,EN,,0,0,0,,And similarly, of course, I can define what's going on with products.\nDialogue: 0,0:24:35.22,0:24:36.56,EN,,0,0,0,,Let's do that very quickly.\nDialogue: 0,0:24:48.97,0:24:50.64,EN,,0,0,0,,Is the expression a product?\nDialogue: 0,0:24:51.05,0:24:54.69,EN,,0,0,0,,Yes if and if it's true, that's it's not atomic\nDialogue: 0,0:25:01.41,0:25:14.14,EN,,0,0,0,,and it's EQ quote, the asterisk symbol, which is the operator for multiplication.\nDialogue: 0,0:25:15.64,0:25:32.00,EN,,0,0,0,,Make product of an M1 and an M2 to be list,\nDialogue: 0,0:25:34.42,0:25:39.30,EN,,0,0,0,,quote, the asterisk operation and M1 and M2.\nDialogue: 0,0:25:40.82,0:25:56.81,EN,,0,0,0,,And I define M1 to be cadr and M2 to be caddr.\nDialogue: 0,0:26:00.09,0:26:02.38,EN,,0,0,0,,You get to be a good Lisp programmer because you start talking that way.\nDialogue: 0,0:26:02.53,0:26:05.53,EN,,0,0,0,,You can cdr thing down lists and cons them up and so on.\nDialogue: 0,0:26:06.29,0:26:10.10,EN,,0,0,0,,Now, now that we have essentially a complete program for finding derivatives,\nDialogue: 0,0:26:10.10,0:26:11.70,EN,,0,0,0,,you can add more rules if you like.\nDialogue: 0,0:26:12.21,0:26:13.93,EN,,0,0,0,,What kind of behavior do we get out of it?\nDialogue: 0,0:26:14.64,0:26:16.77,EN,,0,0,0,,I'll have to clear that x.\nDialogue: 0,0:26:17.80,0:26:20.82,EN,,0,0,0,,Well, supposing I define foo here\nDialogue: 0,0:26:22.16,0:26:30.38,EN,,0,0,0,,to be the sum of the product of ax square and bx plus c.\nDialogue: 0,0:26:30.54,0:26:32.08,EN,,0,0,0,,That's the same thing we see here\nDialogue: 0,0:26:32.08,0:26:36.36,EN,,0,0,0,,as the algebraic expression written in the more conventional notation over there.\nDialogue: 0,0:26:37.84,0:26:41.60,EN,,0,0,0,,Well, the derivative of foo with respect to x, which we can see over here,\nDialogue: 0,0:26:43.46,0:26:45.26,EN,,0,0,0,,is this horrible, horrendous mess.\nDialogue: 0,0:26:46.16,0:26:49.22,EN,,0,0,0,,I would like it to be 2ax plus b.\nDialogue: 0,0:26:50.68,0:26:53.44,EN,,0,0,0,,But it's not. It's equivalent to it.\nDialogue: 0,0:26:54.58,0:26:55.22,EN,,0,0,0,,What is it?\nDialogue: 0,0:26:55.97,0:26:59.96,EN,,0,0,0,,I have here, what do I have?\nDialogue: 0,0:27:00.50,0:27:04.30,EN,,0,0,0,,I have the derivative of the product of x and x.\nDialogue: 0,0:27:04.69,0:27:10.53,EN,,0,0,0,,Over here is, of course, the sum of x times 1 and 1 times x.\nDialogue: 0,0:27:12.73,0:27:15.66,EN,,0,0,0,,Now, well, it's the first times the derivative of the second plus the second times the derivative of the first. It's right.\nDialogue: 0,0:27:17.22,0:27:28.37,EN,,0,0,0,,That's 2x of course. a times 2x is 2ax plus 0X square doesn't count plus B over here plus a bunch of 0's.\nDialogue: 0,0:27:28.96,0:27:30.12,EN,,0,0,0,,Well the answer is right.\nDialogue: 0,0:27:30.12,0:27:35.14,EN,,0,0,0,,But I give people take off points on an exam for that, sadly enough.\nDialogue: 0,0:27:35.56,0:27:37.26,EN,,0,0,0,,Let's worry about that in the next segment.\nDialogue: 0,0:27:37.68,0:27:38.61,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:27:42.77,0:27:43.45,EN,,0,0,0,,Yes?\nDialogue: 0,0:27:43.89,0:27:46.69,EN,,0,0,0,,AUDIENCE: If you had left the quote when you put the plus,\nDialogue: 0,0:27:46.69,0:27:50.82,EN,,0,0,0,,then would that be referring to the procedure plus\nDialogue: 0,0:27:50.82,0:27:55.42,EN,,0,0,0,,and could you do a comparison between that procedure and some other procedure if you wanted to?\nDialogue: 0,0:27:56.16,0:27:57.08,EN,,0,0,0,,PROFESSOR: Yes. Good question.\nDialogue: 0,0:27:57.45,0:28:02.26,EN,,0,0,0,,If I had left this quotation off at this point,\nDialogue: 0,0:28:03.88,0:28:07.13,EN,,0,0,0,,Okay? If I had left that quotation off at that point,\nDialogue: 0,0:28:07.33,0:28:14.20,EN,,0,0,0,,then I would be referring here to the procedure which is the thing that plus is defined to be.\nDialogue: 0,0:28:15.38,0:28:24.88,EN,,0,0,0,,And indeed, I could compare some procedures with each other for identity.\nDialogue: 0,0:28:24.88,0:28:27.45,EN,,0,0,0,,Now what that means is not clear right now.\nDialogue: 0,0:28:27.85,0:28:29.37,EN,,0,0,0,,I don't like to think about it.\nDialogue: 0,0:28:29.89,0:28:32.40,EN,,0,0,0,,Because I don't know exactly what it would need to compare procedures.\nDialogue: 0,0:28:32.40,0:28:34.40,EN,,0,0,0,,There are reasons why that may make no sense at all.\nDialogue: 0,0:28:35.52,0:28:37.53,EN,,0,0,0,,However, the symbols, we understand.\nDialogue: 0,0:28:38.54,0:28:40.56,EN,,0,0,0,,And so that's why I put that quote in.\nDialogue: 0,0:28:41.16,0:28:43.70,EN,,0,0,0,,I want to talk about the symbol that's apparent on the page.\nDialogue: 0,0:28:46.16,0:28:46.92,EN,,0,0,0,,Any other questions?\nDialogue: 0,0:28:48.52,0:28:51.86,EN,,0,0,0,,OK. Thank you. Let's take a break.\nDialogue: 0,0:28:55.12,0:29:00.66,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:29:00.68,0:29:04.34,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:29:04.34,0:29:06.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:29:12.21,0:29:19.17,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:29:20.09,0:29:24.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}Symbolic Differentiation: Quotation\nDialogue: 0,0:29:29.86,0:29:30.92,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:29:31.46,0:29:37.76,EN,,0,0,0,,We've just developed a fairly plausible program for computing the derivatives of algebraic expressions.\nDialogue: 0,0:29:38.20,0:29:41.56,EN,,0,0,0,,It's an incomplete program, if you would like to add more rules.\nDialogue: 0,0:29:42.13,0:29:47.74,EN,,0,0,0,,And perhaps you might extend it to deal with uses of addition with any number of arguments\nDialogue: 0,0:29:47.76,0:29:49.70,EN,,0,0,0,,and multiplication with any of the number of arguments.\nDialogue: 0,0:29:49.89,0:29:51.38,EN,,0,0,0,,And that's all rather easy.\nDialogue: 0,0:29:52.73,0:29:56.93,EN,,0,0,0,,However, there was a little fly in that ointment.\nDialogue: 0,0:29:57.48,0:30:02.37,EN,,0,0,0,,We go back to this slide.\nDialogue: 0,0:30:02.94,0:30:08.60,EN,,0,0,0,,We see that the expressions that we get are rather bad.\nDialogue: 0,0:30:08.88,0:30:11.01,EN,,0,0,0,,This is a rather bad expression.\nDialogue: 0,0:30:11.46,0:30:13.10,EN,,0,0,0,,How do we get such an expression?\nDialogue: 0,0:30:13.84,0:30:15.50,EN,,0,0,0,,Why do we have that expression?\nDialogue: 0,0:30:16.84,0:30:18.74,EN,,0,0,0,,Let's look at this expression in some detail.\nDialogue: 0,0:30:18.92,0:30:20.76,EN,,0,0,0,,Let's find out where all the pieces come from.\nDialogue: 0,0:30:21.69,0:30:24.56,EN,,0,0,0,,As we see here, we have a sum--\nDialogue: 0,0:30:24.56,0:30:26.56,EN,,0,0,0,,just what I showed you at the end of the last time--\nDialogue: 0,0:30:27.12,0:30:29.09,EN,,0,0,0,,of X times 1 plus 1 time X.\nDialogue: 0,0:30:29.58,0:30:31.38,EN,,0,0,0,,That is a derivative of this product.\nDialogue: 0,0:30:32.52,0:30:36.41,EN,,0,0,0,,The product of a times that, where a does not depend upon x,\nDialogue: 0,0:30:36.41,0:30:38.41,EN,,0,0,0,,and therefore is constant with respect to x,\nDialogue: 0,0:30:39.04,0:30:44.53,EN,,0,0,0,,is this sum, which goes from here all the way through here and through here.\nDialogue: 0,0:30:44.80,0:30:48.89,EN,,0,0,0,,Because it is the first thing times the derivative of the second\nDialogue: 0,0:30:49.57,0:30:54.45,EN,,0,0,0,,plus the derivative of the first times the second\nDialogue: 0,0:30:54.66,0:30:59.06,EN,,0,0,0,,as the program we wrote on the blackboard indicated we should do.\nDialogue: 0,0:31:00.65,0:31:05.36,EN,,0,0,0,,And, of course, the product of bx over here\nDialogue: 0,0:31:05.49,0:31:09.81,EN,,0,0,0,,manifests itself as B times 1 plus 0 times X\nDialogue: 0,0:31:10.81,0:31:16.06,EN,,0,0,0,,because we see that B does not depend upon X.\nDialogue: 0,0:31:16.46,0:31:18.56,EN,,0,0,0,,And so the derivative of B is this 0,\nDialogue: 0,0:31:18.77,0:31:21.48,EN,,0,0,0,,and the derivative of X with respect itself is the 1.\nDialogue: 0,0:31:23.06,0:31:28.64,EN,,0,0,0,,And, of course, the derivative of the sums over here turn into these two sums of the derivatives of the parts.\nDialogue: 0,0:31:29.37,0:31:33.50,EN,,0,0,0,,So what we're seeing here is exactly the thing I was trying to tell you about\nDialogue: 0,0:31:33.66,0:31:35.89,EN,,0,0,0,,with Fibonacci numbers a while ago,\nDialogue: 0,0:31:37.77,0:31:39.49,EN,,0,0,0,,that the form of the process\nDialogue: 0,0:31:41.38,0:31:46.44,EN,,0,0,0,,is expanded as low as from the local rules that you see in the procedure,\nDialogue: 0,0:31:48.05,0:31:52.57,EN,,0,0,0,,that the procedure represents a set of local rules for the expansion of this process.\nDialogue: 0,0:31:53.36,0:32:00.09,EN,,0,0,0,,And here, the process left behind some stuff, which is the answer.\nDialogue: 0,0:32:00.25,0:32:06.26,EN,,0,0,0,,And it was constructed by the walk it takes of the tree structure, which is the expression.\nDialogue: 0,0:32:08.41,0:32:12.61,EN,,0,0,0,,So every part in the answer we see here derives from some part of the problem.\nDialogue: 0,0:32:14.46,0:32:17.78,EN,,0,0,0,,Now, we can look at, for example, the derivative of foo,\nDialogue: 0,0:32:17.78,0:32:19.65,EN,,0,0,0,,which is ax square plus bx plus c,\nDialogue: 0,0:32:19.84,0:32:23.05,EN,,0,0,0,,with respect to other things, like here, for example,\nDialogue: 0,0:32:24.14,0:32:27.48,EN,,0,0,0,,we can see that the derivative of foo with respect to a.\nDialogue: 0,0:32:28.10,0:32:31.77,EN,,0,0,0,,And it's very similar. It's, in fact, the identical algebraic expression,\nDialogue: 0,0:32:32.45,0:32:35.24,EN,,0,0,0,,except for the fact that theses 0's and 1's are in different places.\nDialogue: 0,0:32:36.06,0:32:38.60,EN,,0,0,0,,Because the only degree of freedom we have in this tree walk\nDialogue: 0,0:32:38.97,0:32:43.85,EN,,0,0,0,,is what's constant with respect to the variable we're taking the derivative with respect to\nDialogue: 0,0:32:44.28,0:32:45.81,EN,,0,0,0,,and what's the same variable.\nDialogue: 0,0:32:48.26,0:32:52.09,EN,,0,0,0,,In other words, if we go back to this blackboard and we look,\nDialogue: 0,0:32:52.65,0:32:57.49,EN,,0,0,0,,we have no choice what to do when we take the derivative of the sum or a product.\nDialogue: 0,0:32:58.08,0:33:04.48,EN,,0,0,0,,The only interesting place here is, is the expression the variable,\nDialogue: 0,0:33:04.80,0:33:10.10,EN,,0,0,0,,or is the expression a constant with respect to that variable for very, very small expressions?\nDialogue: 0,0:33:10.36,0:33:12.41,EN,,0,0,0,,In which case we get various 1's and 0's,\nDialogue: 0,0:33:12.69,0:33:14.49,EN,,0,0,0,,which if we go back to this slide,\nDialogue: 0,0:33:15.12,0:33:18.16,EN,,0,0,0,,we can see that the 0's that appear here, for example,\nDialogue: 0,0:33:18.37,0:33:22.74,EN,,0,0,0,,this 1 over here in derivative of foo with respect to A,\nDialogue: 0,0:33:22.96,0:33:24.86,EN,,0,0,0,,which gets us an X square,\nDialogue: 0,0:33:24.96,0:33:32.53,EN,,0,0,0,,because that 1 gets the multiply of X and X into the answer, that 1 is 0.\nDialogue: 0,0:33:32.64,0:33:34.89,EN,,0,0,0,,Over here, we're not taking the derivative of foo with respect to c.\nDialogue: 0,0:33:36.78,0:33:39.30,EN,,0,0,0,,But the shapes of these expressions are the same.\nDialogue: 0,0:33:40.54,0:33:43.96,EN,,0,0,0,,See all those shapes. They're the same.\nDialogue: 0,0:33:50.37,0:33:52.28,EN,,0,0,0,,Well is there anything wrong with our rules?\nDialogue: 0,0:33:53.58,0:33:55.02,EN,,0,0,0,,No. They're the right rules.\nDialogue: 0,0:33:56.12,0:33:57.77,EN,,0,0,0,,We've been through this one before.\nDialogue: 0,0:33:58.06,0:34:03.53,EN,,0,0,0,,One of the things you're going to begin to discover is that there aren't too many good ideas.\nDialogue: 0,0:34:06.32,0:34:09.74,EN,,0,0,0,,When we were looking at rational numbers yesterday,\nDialogue: 0,0:34:12.12,0:34:14.48,EN,,0,0,0,,the problem was that we got 6/8 rather then 3/4.\nDialogue: 0,0:34:14.97,0:34:16.49,EN,,0,0,0,,The answer was unsimplified.\nDialogue: 0,0:34:18.09,0:34:20.90,EN,,0,0,0,,The problem, of course, is very similar.\nDialogue: 0,0:34:21.18,0:34:25.41,EN,,0,0,0,,There are things I'd like to be identical by simplification that don't become identical.\nDialogue: 0,0:34:27.57,0:34:31.89,EN,,0,0,0,,And yet the rules for doing addition a multiplication of rational numbers were correct.\nDialogue: 0,0:34:33.97,0:34:37.41,EN,,0,0,0,,So the way we might solve this problem is do the thing we did last time, which always works.\nDialogue: 0,0:34:37.78,0:34:39.89,EN,,0,0,0,,If something worked last time it ought to work again.\nDialogue: 0,0:34:40.53,0:34:42.05,EN,,0,0,0,,It's changed representation.\nDialogue: 0,0:34:43.13,0:34:46.44,EN,,0,0,0,,Perhaps in the representation we could put in a simplification step\nDialogue: 0,0:34:47.88,0:34:49.78,EN,,0,0,0,,that produces a simplified representation.\nDialogue: 0,0:34:50.17,0:34:51.73,EN,,0,0,0,,This may not always work, of course.\nDialogue: 0,0:34:52.49,0:34:54.14,EN,,0,0,0,,I'm not trying to say that it always works.\nDialogue: 0,0:34:55.12,0:35:00.44,EN,,0,0,0,,But it's one of the pieces of artillery we have in our war against complexity.\nDialogue: 0,0:35:01.46,0:35:03.85,EN,,0,0,0,,You see, because we solved our problem very carefully.\nDialogue: 0,0:35:04.30,0:35:07.20,EN,,0,0,0,,What we've done, is we've divided the world in several parts.\nDialogue: 0,0:35:07.57,0:35:08.73,EN,,0,0,0,,There are derivatives rules\nDialogue: 0,0:35:11.32,0:35:15.80,EN,,0,0,0,,and general rules for algebra of some sort at this level of detail.\nDialogue: 0,0:35:16.38,0:35:21.22,EN,,0,0,0,,and i have an abstraction barrier.\nDialogue: 0,0:35:22.48,0:35:33.49,EN,,0,0,0,,And i have the representation of the algebraic expressions, list structure.\nDialogue: 0,0:35:37.33,0:35:42.56,EN,,0,0,0,,And in this barrier, I have the interface procedures.\nDialogue: 0,0:35:43.25,0:35:49.82,EN,,0,0,0,,I have constant, and things like same-var.\nDialogue: 0,0:35:54.60,0:35:58.72,EN,,0,0,0,,I have things like sum, make-sum.\nDialogue: 0,0:36:02.22,0:36:05.57,EN,,0,0,0,,I have A1, A2.\nDialogue: 0,0:36:06.60,0:36:08.58,EN,,0,0,0,,I have products and things like that,\nDialogue: 0,0:36:08.74,0:36:11.90,EN,,0,0,0,,all the other things I might need for various kinds of algebraic expressions.\nDialogue: 0,0:36:12.94,0:36:19.14,EN,,0,0,0,,Making this barrier allows me to arbitrarily change the representation\nDialogue: 0,0:36:20.14,0:36:23.20,EN,,0,0,0,,without changing the rules that are written in terms of that representation.\nDialogue: 0,0:36:25.04,0:36:29.08,EN,,0,0,0,,So if I can make the problem go away by changing representation,\nDialogue: 0,0:36:30.38,0:36:34.52,EN,,0,0,0,,the composition of the problem into these two parts has helped me a great deal.\nDialogue: 0,0:36:35.65,0:36:37.54,EN,,0,0,0,,So let's take a very simple case of this.\nDialogue: 0,0:36:38.82,0:36:40.08,EN,,0,0,0,,What was one of the problems?\nDialogue: 0,0:36:40.26,0:36:43.61,EN,,0,0,0,,Let's go back to this transparency again.\nDialogue: 0,0:36:44.50,0:36:47.34,EN,,0,0,0,,And we see here, oh yes, there's horrible things\nDialogue: 0,0:36:47.62,0:36:51.86,EN,,0,0,0,,like here is the sum of an expression and 0.\nDialogue: 0,0:36:53.14,0:36:56.66,EN,,0,0,0,,Well that's no reason to think of it as anything other than the expression itself.\nDialogue: 0,0:36:57.21,0:37:01.90,EN,,0,0,0,,Why should the summation operation have made up this edition?\nDialogue: 0,0:37:03.38,0:37:04.57,EN,,0,0,0,,It can be smarter than that.\nDialogue: 0,0:37:05.56,0:37:10.08,EN,,0,0,0,,Or here, for example, is a multiplication of something by 1.\nDialogue: 0,0:37:11.16,0:37:12.29,EN,,0,0,0,,It's another thing like that.\nDialogue: 0,0:37:12.86,0:37:15.68,EN,,0,0,0,,Or here is a product of something with 0, which is certainly 0.\nDialogue: 0,0:37:17.86,0:37:19.52,EN,,0,0,0,,So we won't have to make this construction.\nDialogue: 0,0:37:21.44,0:37:22.62,EN,,0,0,0,,So why don't we just do that?\nDialogue: 0,0:37:23.66,0:37:27.96,EN,,0,0,0,,We need to change the way the representation works, almost here.\nDialogue: 0,0:37:37.40,0:37:41.84,EN,,0,0,0,,Make-sum to be.\nDialogue: 0,0:37:42.05,0:37:43.76,EN,,0,0,0,,Well, now it's not something so simple.\nDialogue: 0,0:37:44.00,0:37:50.40,EN,,0,0,0,,I'm not going to make a list containing the symbol plus and things unless I need to.\nDialogue: 0,0:37:51.72,0:37:53.05,EN,,0,0,0,,Well, what are the possibilities?\nDialogue: 0,0:37:54.56,0:37:58.53,EN,,0,0,0,,If...I have some sort of cases here.\nDialogue: 0,0:37:59.38,0:38:08.20,EN,,0,0,0,,If I have numbers, if a1 is a number--\nDialogue: 0,0:38:09.05,0:38:10.93,EN,,0,0,0,,and here's another primitive I've just introduced,\nDialogue: 0,0:38:10.93,0:38:13.18,EN,,0,0,0,,it's possible to tell whether something's number--\nDialogue: 0,0:38:15.38,0:38:23.82,EN,,0,0,0,,and if number A2, meaning they're not symbolic expressions,\nDialogue: 0,0:38:24.45,0:38:26.20,EN,,0,0,0,,then why not do the addition now?\nDialogue: 0,0:38:26.45,0:38:29.92,EN,,0,0,0,,The result is just a plus of A1 and A2.\nDialogue: 0,0:38:32.32,0:38:33.98,EN,,0,0,0,,I'm not asking if these represent numbers.\nDialogue: 0,0:38:33.98,0:38:35.98,EN,,0,0,0,,Of course all of these symbols represent numbers.\nDialogue: 0,0:38:37.33,0:38:41.22,EN,,0,0,0,,I'm talking about whether the one I've got is the number 3 right now.\nDialogue: 0,0:38:43.40,0:38:44.40,EN,,0,0,0,,And, for example,\nDialogue: 0,0:38:48.77,0:38:59.61,EN,,0,0,0,,supposing A1 is a number, and it's equal to 0,\nDialogue: 0,0:39:04.20,0:39:06.38,EN,,0,0,0,,well then the answer is just A2.\nDialogue: 0,0:39:06.93,0:39:08.68,EN,,0,0,0,,There is no reason to make anything up.\nDialogue: 0,0:39:10.98,0:39:23.41,EN,,0,0,0,,And if A2 is a number, and equal A2 0,\nDialogue: 0,0:39:27.16,0:39:28.90,EN,,0,0,0,,then the result is A1.\nDialogue: 0,0:39:30.04,0:39:33.65,EN,,0,0,0,,And only if I can't figure out something better to do with this situation,\nDialogue: 0,0:39:34.13,0:39:35.61,EN,,0,0,0,,well, I can construct a list.\nDialogue: 0,0:39:37.86,0:39:42.86,EN,,0,0,0,,Otherwise I want the representation to be the list\nDialogue: 0,0:39:44.13,0:39:52.33,EN,,0,0,0,,containing the quoted symbol plus, and A1, and A2.\nDialogue: 0,0:39:58.66,0:40:01.65,EN,,0,0,0,,And, of course, a very similar thing can be done for products.\nDialogue: 0,0:40:03.01,0:40:05.04,EN,,0,0,0,,And I think I'll avoid boring you with them.\nDialogue: 0,0:40:05.44,0:40:07.24,EN,,0,0,0,,I was going to write it on the blackboard.\nDialogue: 0,0:40:07.65,0:40:09.80,EN,,0,0,0,,I don't think it's necessary. You know what to do.\nDialogue: 0,0:40:10.76,0:40:11.61,EN,,0,0,0,,It's very simple.\nDialogue: 0,0:40:12.86,0:40:19.89,EN,,0,0,0,,But now, let's just see the kind of results we get out of changing our program in this way.\nDialogue: 0,0:40:21.68,0:40:27.88,EN,,0,0,0,,Well, here's the derivatives after having just changed the constructors for expressions.\nDialogue: 0,0:40:28.98,0:40:32.21,EN,,0,0,0,,The same foo, aX square plus bX plus c,\nDialogue: 0,0:40:33.28,0:40:40.70,EN,,0,0,0,,and what I get is nothing more than the derivative of that is 2aX plus B.\nDialogue: 0,0:40:40.70,0:40:42.10,EN,,0,0,0,,Well, it's not completely simplified.\nDialogue: 0,0:40:42.60,0:40:44.53,EN,,0,0,0,,I would like to collect common terms and sums.\nDialogue: 0,0:40:45.06,0:40:46.08,EN,,0,0,0,,Well, that's more work.\nDialogue: 0,0:40:47.12,0:40:51.86,EN,,0,0,0,,And, of course, programs to do this sort of thing are huge and complicated.\nDialogue: 0,0:40:52.28,0:40:55.28,EN,,0,0,0,,Algebraic simplification, it's a very complicated mess.\nDialogue: 0,0:40:56.37,0:41:00.13,EN,,0,0,0,,There's a very famous program you may have heard of called Maxima developed at MIT in the past,\nDialogue: 0,0:41:00.42,0:41:03.14,EN,,0,0,0,,which is 5,000 pages of Lisp code,\nDialogue: 0,0:41:03.92,0:41:06.50,EN,,0,0,0,,mostly the algebraic simplification operations.\nDialogue: 0,0:41:08.08,0:41:12.21,EN,,0,0,0,,There we see the derivative of foo.\nDialogue: 0,0:41:12.21,0:41:16.86,EN,,0,0,0,,In fact, alias is something I wouldn't take off more than 1 point for on an elementary calculus class.\nDialogue: 0,0:41:18.38,0:41:22.49,EN,,0,0,0,,And the derivative of foo with respect to a, well it's gone down to X times X,\nDialogue: 0,0:41:22.80,0:41:23.80,EN,,0,0,0,,which isn't so bad.\nDialogue: 0,0:41:24.74,0:41:27.53,EN,,0,0,0,,And the derivative of foo with respect to b is just X itself.\nDialogue: 0,0:41:28.06,0:41:30.12,EN,,0,0,0,,And the derivative of foo with respect to c comes out 1.\nDialogue: 0,0:41:30.70,0:41:32.04,EN,,0,0,0,,So I'm pretty pleased with this.\nDialogue: 0,0:41:34.10,0:41:39.01,EN,,0,0,0,,What you've seen is, of course, a little bit contrived, carefully organized example\nDialogue: 0,0:41:39.56,0:41:42.60,EN,,0,0,0,,to show you how we can manipulate algebraic expressions,\nDialogue: 0,0:41:42.96,0:41:47.93,EN,,0,0,0,,how we do that abstractly in terms of abstract syntax rather than concrete syntax\nDialogue: 0,0:41:49.21,0:41:56.29,EN,,0,0,0,,and how we can use the abstraction to control what goes on in building these expressions.\nDialogue: 0,0:41:57.80,0:42:00.41,EN,,0,0,0,,But the real story isn't just such a simple thing as that.\nDialogue: 0,0:42:01.00,0:42:04.45,EN,,0,0,0,,The real story is, in fact, that I'm manipulating these expressions.\nDialogue: 0,0:42:04.45,0:42:06.72,EN,,0,0,0,,And the expressions are the same expressions--\nDialogue: 0,0:42:06.72,0:42:07.97,EN,,0,0,0,,going back to the slide--\nDialogue: 0,0:42:08.08,0:42:10.52,EN,,0,0,0,,as the ones that are Lisp expressions.\nDialogue: 0,0:42:12.02,0:42:12.97,EN,,0,0,0,,There's a pun here.\nDialogue: 0,0:42:13.82,0:42:21.49,EN,,0,0,0,,I've chosen my representation to be the same as the representation in my language of similar things.\nDialogue: 0,0:42:22.89,0:42:26.52,EN,,0,0,0,,By doing so, I've invoked a necessity.\nDialogue: 0,0:42:26.90,0:42:30.34,EN,,0,0,0,,I created the necessity to have things like quotation\nDialogue: 0,0:42:30.97,0:42:38.17,EN,,0,0,0,,because of the fact that my language is capable of writing expressions that talk about expressions of the language.\nDialogue: 0,0:42:39.76,0:42:43.22,EN,,0,0,0,,I need to have something that says, this is an expression I'm talking about\nDialogue: 0,0:42:43.76,0:42:46.13,EN,,0,0,0,,rather than this expression is talking about something,\nDialogue: 0,0:42:47.20,0:42:48.44,EN,,0,0,0,,and I want to talk about that.\nDialogue: 0,0:42:51.34,0:42:55.36,EN,,0,0,0,,So quotation stops and says, I'm talking about this expression itself.\nDialogue: 0,0:42:57.97,0:43:00.85,EN,,0,0,0,,Now, given that power,\nDialogue: 0,0:43:01.58,0:43:03.82,EN,,0,0,0,,if I can manipulate expressions of the language,\nDialogue: 0,0:43:04.80,0:43:09.00,EN,,0,0,0,,I can begin to build even much more powerful layers upon layers of languages.\nDialogue: 0,0:43:09.77,0:43:12.64,EN,,0,0,0,,Because I can write languages that not only are embedded in Lisp\nDialogue: 0,0:43:13.46,0:43:14.80,EN,,0,0,0,,or whatever language you start with,\nDialogue: 0,0:43:15.26,0:43:17.76,EN,,0,0,0,,but languages that are completely different,\nDialogue: 0,0:43:18.58,0:43:22.24,EN,,0,0,0,,that are just, if we say, interpreted in Lisp or something like that.\nDialogue: 0,0:43:23.17,0:43:25.46,EN,,0,0,0,,We'll get to understand those words more in the future.\nDialogue: 0,0:43:26.56,0:43:32.09,EN,,0,0,0,,But right now I just want to leave you with the fact that we've hit a line\nDialogue: 0,0:43:32.36,0:43:34.98,EN,,0,0,0,,which gives us tremendous power.\nDialogue: 0,0:43:36.00,0:43:37.82,EN,,0,0,0,,And this point we've bought a sledgehammer.\nDialogue: 0,0:43:38.17,0:43:40.92,EN,,0,0,0,,We have to be careful to what flies when we apply it.\nDialogue: 0,0:43:42.17,0:43:43.00,EN,,0,0,0,,Thank you.\nDialogue: 0,0:43:44.10,0:44:00.54,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:43:44.10,0:44:00.54,Declare,,0,0,0,,{\\an2\\fad(500,500)}Project Repo\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec4a.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: CHNENG Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nVideo Zoom Percent: 0.65\nPlayResX: 640\nPlayResY: 480\nScroll Position: 75\nActive Line: 0\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:24.34,0:00:29.34,EN,,0,0,0,,PROFESSOR: Well, yesterday we learned a bit about symbolic manipulation,\nDialogue: 0,0:00:29.92,0:00:35.12,EN,,0,0,0,,and we wrote a rather stylized program\nDialogue: 0,0:00:35.15,0:00:38.97,EN,,0,0,0,,to implement a pile of calculus rule from the calculus book.\nDialogue: 0,0:00:39.61,0:00:44.59,EN,,0,0,0,,Here on the transparencies,\nDialogue: 0,0:00:44.96,0:00:48.81,EN,,0,0,0,,we see a bunch of calculus rules from such a book.\nDialogue: 0,0:00:49.47,0:00:54.62,EN,,0,0,0,,And, of course, what we did is sort of translate these rules into the language of the computer.\nDialogue: 0,0:00:55.14,0:00:58.85,EN,,0,0,0,,But, of course, that's a sort of funny strategy.\nDialogue: 0,0:00:59.36,0:01:04.80,EN,,0,0,0,,Why should we have to translate these rules into the language of the computer?\nDialogue: 0,0:01:05.00,0:01:06.27,EN,,0,0,0,,And what do I really mean by that?\nDialogue: 0,0:01:06.62,0:01:11.02,EN,,0,0,0,,These are--the program we wrote yesterday was very stylized.\nDialogue: 0,0:01:11.21,0:01:15.98,EN,,0,0,0,,It was a conditional, a dispatch on the type of the expression\nDialogue: 0,0:01:16.38,0:01:18.48,EN,,0,0,0,,as observed by the rules.\nDialogue: 0,0:01:19.68,0:01:21.55,EN,,0,0,0,,What we see here are rules that say\nDialogue: 0,0:01:21.74,0:01:25.48,EN,,0,0,0,,if the object being the derivative is being taken of,\nDialogue: 0,0:01:25.48,0:01:29.42,EN,,0,0,0,,if that expression is a constant, then do one thing.\nDialogue: 0,0:01:29.42,0:01:31.37,EN,,0,0,0,,If it's a variable, do another thing.\nDialogue: 0,0:01:31.60,0:01:35.56,EN,,0,0,0,,If it's a product of a constant times a variable, do something and so on.\nDialogue: 0,0:01:36.00,0:01:38.96,EN,,0,0,0,,There's sort of a dispatch there on a type.\nDialogue: 0,0:01:41.40,0:01:45.16,EN,,0,0,0,,Well, since it has such a stylized behavior and structure,\nDialogue: 0,0:01:45.95,0:01:49.53,EN,,0,0,0,,is there some other way of writing this program that's more clear?\nDialogue: 0,0:01:50.83,0:01:53.45,EN,,0,0,0,,Well, what's a rule, first of all, What are these rules?\nDialogue: 0,0:01:55.56,0:01:58.50,EN,,0,0,0,,Let's think about that. Rules have parts.\nDialogue: 0,0:01:58.94,0:02:02.35,EN,,0,0,0,,If you look at these rules in detail,\nDialogue: 0,0:02:03.71,0:02:04.99,EN,,0,0,0,,what you see, for example,\nDialogue: 0,0:02:05.12,0:02:09.69,EN,,0,0,0,,is the rule has a left-hand side and a right-hand side.\nDialogue: 0,0:02:10.36,0:02:14.36,EN,,0,0,0,,Each of these rules has a left-hand side and the right-hand side.\nDialogue: 0,0:02:15.15,0:02:20.30,EN,,0,0,0,,The left-hand side is somehow compared with the expression you're trying to take the derivative of.\nDialogue: 0,0:02:21.52,0:02:25.10,EN,,0,0,0,,The right-hand side is the replacement for that expression.\nDialogue: 0,0:02:28.49,0:02:33.10,EN,,0,0,0,,So all rules on this page are something like this.\nDialogue: 0,0:02:36.51,0:02:38.06,EN,,0,0,0,,I have patterns,\nDialogue: 0,0:02:41.48,0:02:48.30,EN,,0,0,0,,and somehow, I have to produce, given a pattern, a skeleton.\nDialogue: 0,0:02:51.88,0:02:52.81,EN,,0,0,0,,This is a rule.\nDialogue: 0,0:02:55.42,0:02:57.13,EN,,0,0,0,,A pattern is something that matches,\nDialogue: 0,0:02:57.88,0:03:03.26,EN,,0,0,0,,and a skeleton is something you substitute into in order to get a new expression.\nDialogue: 0,0:03:06.46,0:03:16.32,EN,,0,0,0,,So what that means is that the pattern is matched against the expression, which is the source expression.\nDialogue: 0,0:03:23.72,0:03:28.51,EN,,0,0,0,,And the result of the application of the rule is to produce a new expression,\nDialogue: 0,0:03:33.61,0:03:34.91,EN,,0,0,0,,which I'll call a target,\nDialogue: 0,0:03:38.12,0:03:39.88,EN,,0,0,0,,by instantiation of a skeleton.\nDialogue: 0,0:03:41.63,0:03:43.02,EN,,0,0,0,,That's called instantiation.\nDialogue: 0,0:03:50.72,0:03:54.73,EN,,0,0,0,,So that is the process by which these rules are described.\nDialogue: 0,0:03:55.69,0:03:57.26,EN,,0,0,0,,What I'd like to do today\nDialogue: 0,0:03:58.73,0:04:01.08,EN,,0,0,0,,is build a language\nDialogue: 0,0:04:02.20,0:04:05.48,EN,,0,0,0,,and a means of interpreting that language, a means of executing that language,\nDialogue: 0,0:04:05.74,0:04:08.43,EN,,0,0,0,,where that language allows us to directly express these rules.\nDialogue: 0,0:04:10.59,0:04:11.58,EN,,0,0,0,,And what we're going to do\nDialogue: 0,0:04:11.58,0:04:17.56,EN,,0,0,0,,instead of bringing the rules to the level of the computer by writing a program that is those rules\nDialogue: 0,0:04:18.38,0:04:21.56,EN,,0,0,0,,in the computer's language--at the moment, in a Lisp--\nDialogue: 0,0:04:22.16,0:04:24.49,EN,,0,0,0,,we're going to bring the computer to the level of us\nDialogue: 0,0:04:25.48,0:04:29.15,EN,,0,0,0,,by writing a way by which the computer can understand rules of this sort.\nDialogue: 0,0:04:30.91,0:04:34.76,EN,,0,0,0,,This is slightly emphasizing the idea that we had last time\nDialogue: 0,0:04:35.44,0:04:39.36,EN,,0,0,0,,that we're trying to make a solution to a class of problems rather than a particular one.\nDialogue: 0,0:04:39.77,0:04:46.72,EN,,0,0,0,,The problem is if I want to write rules for a different piece of mathematics,\nDialogue: 0,0:04:48.24,0:04:51.39,EN,,0,0,0,,say, to simple algebraic simplification or something like that,\nDialogue: 0,0:04:51.98,0:04:55.48,EN,,0,0,0,,or manipulation of trigonometric functions,\nDialogue: 0,0:04:56.09,0:05:01.16,EN,,0,0,0,,I would have to write a different program in using yesterday's method.\nDialogue: 0,0:05:01.16,0:05:05.42,EN,,0,0,0,,Whereas I would like to encapsulate all of the things that are common to both of those programs,\nDialogue: 0,0:05:06.12,0:05:10.17,EN,,0,0,0,,meaning the idea of matching, instantiation, the control structure,\nDialogue: 0,0:05:10.17,0:05:12.46,EN,,0,0,0,,which turns out to be very complicated for such a thing,\nDialogue: 0,0:05:13.16,0:05:18.46,EN,,0,0,0,,I'd like to encapsulate that separately from the rules themselves.\nDialogue: 0,0:05:20.06,0:05:22.60,EN,,0,0,0,,So let's look at, first of all, a representation.\nDialogue: 0,0:05:22.62,0:05:24.09,EN,,0,0,0,,I'd like to use the overhead here.\nDialogue: 0,0:05:24.67,0:05:25.60,EN,,0,0,0,,I'd like-- there it is.\nDialogue: 0,0:05:26.25,0:05:32.27,EN,,0,0,0,,I'd like to look at a representation of the rules of calculus for derivatives\nDialogue: 0,0:05:33.71,0:05:37.15,EN,,0,0,0,,in a sort of simple language that I'm writing right here.\nDialogue: 0,0:05:38.11,0:05:43.29,EN,,0,0,0,,Now, I'm going to avoid--I'm going to avoid worrying about syntax.\nDialogue: 0,0:05:44.28,0:05:49.28,EN,,0,0,0,,We can easily pretty this, and I'm not interested in making-- this is indeed ugly.\nDialogue: 0,0:05:49.30,0:05:56.41,EN,,0,0,0,,This doesn't look like the beautiful text set dx by dt or something that I'd like to write,\nDialogue: 0,0:05:56.76,0:05:58.12,EN,,0,0,0,,but that's not essential.\nDialogue: 0,0:05:58.88,0:06:00.62,EN,,0,0,0,,That's sort of an accidental phenomenon.\nDialogue: 0,0:06:01.00,0:06:04.44,EN,,0,0,0,,Here, we're just worrying about the fact that the structure of the rules\nDialogue: 0,0:06:04.83,0:06:11.70,EN,,0,0,0,,is that there is a left-hand side here, represents the thing I want to match against the derivative expression.\nDialogue: 0,0:06:11.80,0:06:13.56,EN,,0,0,0,,This is the representation I'm going to say\nDialogue: 0,0:06:13.60,0:06:18.32,EN,,0,0,0,,for the derivative of a constant, which we will call c\nDialogue: 0,0:06:18.84,0:06:21.20,EN,,0,0,0,,respect to the variable we will call v.\nDialogue: 0,0:06:23.08,0:06:25.55,EN,,0,0,0,,And what we will get on the right-hand side is 0.\nDialogue: 0,0:06:26.00,0:06:28.06,EN,,0,0,0,,So this represents a rule.\nDialogue: 0,0:06:29.26,0:06:34.04,EN,,0,0,0,,The next rule will be the derivative of a variable, which we will call v\nDialogue: 0,0:06:34.22,0:06:37.74,EN,,0,0,0,,respect to the same variable v, and we get a 1.\nDialogue: 0,0:06:38.60,0:06:42.17,EN,,0,0,0,,However, if we have the derivative of a variable called u\nDialogue: 0,0:06:42.41,0:06:44.84,EN,,0,0,0,,respect to a different variables v,\nDialogue: 0,0:06:45.39,0:06:47.05,EN,,0,0,0,,we will get 0.\nDialogue: 0,0:06:47.84,0:06:52.17,EN,,0,0,0,,I just want you look at these rules a little bit and see how they fit together.\nDialogue: 0,0:06:52.51,0:06:54.30,EN,,0,0,0,,For example, over here,\nDialogue: 0,0:06:54.73,0:07:01.90,EN,,0,0,0,,we're going to have the derivative of the sum of an expression called x1 and an expression called x2.\nDialogue: 0,0:07:01.90,0:07:05.85,EN,,0,0,0,,These things that begin with question marks are called pattern variables\nDialogue: 0,0:07:06.88,0:07:08.62,EN,,0,0,0,,in the language that we're inventing,\nDialogue: 0,0:07:08.93,0:07:14.93,EN,,0,0,0,,and you see we're just making it up, so pattern variables for matching.\nDialogue: 0,0:07:14.93,0:07:20.33,EN,,0,0,0,,And so in this-- here we have the derivative of the sum of the expression which we will call x1.\nDialogue: 0,0:07:20.33,0:07:26.70,EN,,0,0,0,,And the expression we will call x2 with respect to the variable we call v will be-- here is the right-hand side:\nDialogue: 0,0:07:26.70,0:07:32.76,EN,,0,0,0,,the sum of the derivative of  that expression x1 with respect to v-- the right-hand side is the skeleton--\nDialogue: 0,0:07:33.82,0:07:37.10,EN,,0,0,0,,and the derivative of x2 with respect to v.\nDialogue: 0,0:07:37.60,0:07:42.38,EN,,0,0,0,,Colons here will stand for substitution objects.\nDialogue: 0,0:07:43.63,0:07:47.23,EN,,0,0,0,,They're--we'll call them skeleton evaluations.\nDialogue: 0,0:07:48.51,0:07:53.07,EN,,0,0,0,,So let me put up here on the blackboard for a second some syntax\nDialogue: 0,0:07:53.23,0:07:55.56,EN,,0,0,0,,so we'll know what's going on for this rule language.\nDialogue: 0,0:07:56.68,0:07:59.88,EN,,0,0,0,,First of all, we're going to have to worry about the pattern matching.\nDialogue: 0,0:08:06.04,0:08:13.12,EN,,0,0,0,,We're going to have things like a symbol like foo matches exactly itself.\nDialogue: 0,0:08:23.52,0:08:31.34,EN,,0,0,0,,The expression f of a and b will be used to match any list\nDialogue: 0,0:08:36.30,0:08:57.02,EN,,0,0,0,,whose first element is f, whose second element is a, and whose third element is b.\nDialogue: 0,0:08:58.62,0:09:06.99,EN,,0,0,0,,Also, another thing we might have in a pattern is that--a question mark with some variable like x.\nDialogue: 0,0:09:08.57,0:09:18.67,EN,,0,0,0,,And what that means, it says matches anything, which we will call x.\nDialogue: 0,0:09:25.45,0:09:29.98,EN,,0,0,0,,Question mark c x will match only constants.\nDialogue: 0,0:09:31.50,0:09:40.96,EN,,0,0,0,,So this is something which matches a constant called x.\nDialogue: 0,0:09:44.56,0:09:57.07,EN,,0,0,0,,And question mark v x will match a variable, which we call x.\nDialogue: 0,0:10:01.66,0:10:03.80,EN,,0,0,0,,This is sort of the language we're making up now.\nDialogue: 0,0:10:04.19,0:10:09.40,EN,,0,0,0,,If I match two things against each other, then they are compared element by element\nDialogue: 0,0:10:10.25,0:10:15.85,EN,,0,0,0,,But elements in the pattern may contain these syntactic variables,\nDialogue: 0,0:10:17.07,0:10:20.43,EN,,0,0,0,,which will be used to match arbitrary objects.\nDialogue: 0,0:10:22.12,0:10:29.28,EN,,0,0,0,,And we'll get that object as the value in the name x here, for example.\nDialogue: 0,0:10:31.05,0:10:37.55,EN,,0,0,0,,Now, when we make skeletons for instantiation.\nDialogue: 0,0:10:39.50,0:10:41.40,EN,,0,0,0,,Well, then we have things like this.\nDialogue: 0,0:10:42.27,0:10:46.33,EN,,0,0,0,,foo, a symbol, instantiates to itself.\nDialogue: 0,0:10:55.08,0:11:05.92,EN,,0,0,0,,Something which is a list like f of a and b, instantiates to--\nDialogue: 0,0:11:06.36,0:11:14.75,EN,,0,0,0,,well, f instantiates to a  3-list, a list of three elements,\nDialogue: 0,0:11:15.55,0:11:33.37,EN,,0,0,0,,okay, which are the results of instantiating each of f, a, and b.\nDialogue: 0,0:11:36.35,0:11:54.27,EN,,0,0,0,,And x well--we instantiate to the value of x as in the matched pattern.\nDialogue: 0,0:12:03.05,0:12:10.08,EN,,0,0,0,,So going back to the overhead here, we see -- we see that all of those kinds of objects\nDialogue: 0,0:12:10.78,0:12:16.06,EN,,0,0,0,,we see here a pattern variable which matches a constant,\nDialogue: 0,0:12:16.56,0:12:19.02,EN,,0,0,0,,a pattern variable which matches a variable,\nDialogue: 0,0:12:19.39,0:12:21.74,EN,,0,0,0,,a pattern variable which will match anything.\nDialogue: 0,0:12:22.72,0:12:24.92,EN,,0,0,0,,And if we have two instances of the same name,\nDialogue: 0,0:12:25.08,0:12:31.77,EN,,0,0,0,,like this is the derivative of the expression which is a variable only whose name will be v\nDialogue: 0,0:12:32.86,0:12:36.30,EN,,0,0,0,,with respect to some arbitrary expression which we will call v,\nDialogue: 0,0:12:36.41,0:12:38.01,EN,,0,0,0,,since this v appears twice,\nDialogue: 0,0:12:38.65,0:12:41.07,EN,,0,0,0,,we're going to want that to mean they have to be the same.\nDialogue: 0,0:12:42.68,0:12:45.00,EN,,0,0,0,,The only consistent match is that those are the same.\nDialogue: 0,0:12:45.23,0:12:47.23,EN,,0,0,0,,So here, we're making up a language.\nDialogue: 0,0:12:47.60,0:12:50.66,EN,,0,0,0,,And in fact, that's a very nice thing to be doing.\nDialogue: 0,0:12:50.66,0:12:52.60,EN,,0,0,0,,It's so much fun to make up a language.\nDialogue: 0,0:12:52.60,0:12:54.33,EN,,0,0,0,,And you do this all the time.\nDialogue: 0,0:12:54.33,0:12:56.89,EN,,0,0,0,,And the really most powerful design things you ever do\nDialogue: 0,0:12:57.23,0:13:00.20,EN,,0,0,0,,are sort of making up a language to solve problems like this.\nDialogue: 0,0:13:02.06,0:13:05.34,EN,,0,0,0,,Now, here we go back here and look at some of these rules.\nDialogue: 0,0:13:05.80,0:13:07.10,EN,,0,0,0,,Well, there's a whole set of them.\nDialogue: 0,0:13:07.10,0:13:12.43,EN,,0,0,0,,I mean, there's one for addition and one for multiplication, just like we had before.\nDialogue: 0,0:13:12.43,0:13:17.37,EN,,0,0,0,,The derivative of the product of x1 and x2 with respect to v is\nDialogue: 0,0:13:17.68,0:13:26.52,EN,,0,0,0,,the sum of the product of x1 and the derivative x2 with respect to v and the product of the derivative of x1 and x2.\nDialogue: 0,0:13:27.26,0:13:29.10,EN,,0,0,0,,And here we have exponentiation.\nDialogue: 0,0:13:29.24,0:13:32.11,EN,,0,0,0,,And, of course, we run off the end down here. We get as many as we like.\nDialogue: 0,0:13:32.70,0:13:39.10,EN,,0,0,0,,But the whole thing over here, I'm giving this--this list of rules the name \"derivative rules.\"\nDialogue: 0,0:13:40.40,0:13:44.33,EN,,0,0,0,,What would we do with such a thing once we have it?\nDialogue: 0,0:13:45.40,0:13:47.84,EN,,0,0,0,,Well, one of the nicest ideas, first of all,\nDialogue: 0,0:13:48.44,0:13:51.68,EN,,0,0,0,,is I'm going to write for you, and we're going to play with it all day.\nDialogue: 0,0:13:52.28,0:13:57.37,EN,,0,0,0,,What I'm going to write for you is a program called simplifier,\nDialogue: 0,0:13:57.82,0:13:59.47,EN,,0,0,0,,the general-purpose simplifier.\nDialogue: 0,0:14:00.09,0:14:17.10,EN,,0,0,0,,And we're going to say something like define dsimp to be a simplifier of the derivative rules.\nDialogue: 0,0:14:23.74,0:14:28.75,EN,,0,0,0,,And what simplifier is going to do is, given a set of rules, it will produce for me a procedure\nDialogue: 0,0:14:29.32,0:14:34.59,EN,,0,0,0,,which will simplify expressions containing the things that are referred to by these rules.\nDialogue: 0,0:14:37.39,0:14:43.93,EN,,0,0,0,,So here will be a procedure constructed for your purposes to simplify things with derivatives in them\nDialogue: 0,0:14:44.59,0:14:49.56,EN,,0,0,0,,such that, after that, if we're typing at some Lisp system, and we get a prompt,\nDialogue: 0,0:14:49.88,0:15:03.93,EN,,0,0,0,,and we say dsimp, for example, of the derivative of the sum of x and y with respect to x--\nDialogue: 0,0:15:06.99,0:15:10.97,EN,,0,0,0,,note the quote here because I'm talking about the expression which is the derivative--\nDialogue: 0,0:15:13.29,0:15:17.76,EN,,0,0,0,,then I will get back as a result plus 1 0.\nDialogue: 0,0:15:19.96,0:15:24.60,EN,,0,0,0,,Because the derivative of x plus y is the derivative of x plus derivative y.\nDialogue: 0,0:15:24.60,0:15:26.22,EN,,0,0,0,,The derivative of x with respect to x is 1.\nDialogue: 0,0:15:26.38,0:15:27.82,EN,,0,0,0,,The derivative of y with respect to x is 0.\nDialogue: 0,0:15:29.42,0:15:30.46,EN,,0,0,0,,It's not what we're going to get.\nDialogue: 0,0:15:31.18,0:15:34.65,EN,,0,0,0,,I haven't put any simplification at that level-- algebraic simplification--yet.\nDialogue: 0,0:15:36.16,0:15:41.53,EN,,0,0,0,,Of course, once we have such a thing, then we can--then we can look at other rules.\nDialogue: 0,0:15:41.96,0:15:49.36,EN,,0,0,0,,So, for example, we can, if we go to the slide, OK?\nDialogue: 0,0:15:49.36,0:15:54.12,EN,,0,0,0,,Here, for example, are other rules that we might have, algebraic manipulation rules,\nDialogue: 0,0:15:56.00,0:15:58.38,EN,,0,0,0,,ones that would be used for simplifying algebraic expressions.\nDialogue: 0,0:15:59.00,0:16:02.06,EN,,0,0,0,,For example, just looking at some of these,\nDialogue: 0,0:16:03.04,0:16:09.20,EN,,0,0,0,,the left-hand side says any operator applied to a constant e1 and a constant e2\nDialogue: 0,0:16:09.32,0:16:14.51,EN,,0,0,0,,is the result of evaluating that operator on the constants e1 and e2.\nDialogue: 0,0:16:15.88,0:16:21.56,EN,,0,0,0,,Or an operator, applied to e1, any expression e1 and a constant e2,\nDialogue: 0,0:16:21.69,0:16:23.87,EN,,0,0,0,,is going to move the constant forward.\nDialogue: 0,0:16:24.52,0:16:27.68,EN,,0,0,0,,So that'll turn into the operator with e2 followed by e1.\nDialogue: 0,0:16:28.59,0:16:30.11,EN,,0,0,0,,Why I did that, I don't know.\nDialogue: 0,0:16:30.22,0:16:33.16,EN,,0,0,0,,It wouldn't work if I had division, for example.\nDialogue: 0,0:16:33.53,0:16:35.31,EN,,0,0,0,,So there's a bug in the rules, if you like.\nDialogue: 0,0:16:36.67,0:16:40.86,EN,,0,0,0,,So the sum of 0 and e is e.\nDialogue: 0,0:16:42.17,0:16:45.31,EN,,0,0,0,,The product of 1 and any expression e is e.\nDialogue: 0,0:16:46.12,0:16:49.13,EN,,0,0,0,,The product of 0 and any expression e is 0.\nDialogue: 0,0:16:49.33,0:16:52.72,EN,,0,0,0,,Just looking at some more of these rules, we could have arbitrarily complicated ones.\nDialogue: 0,0:16:53.69,0:16:54.81,EN,,0,0,0,,We could have things like\nDialogue: 0,0:16:55.36,0:17:01.69,EN,,0,0,0,,the product of the constant e1 and any constant e2 with e3\nDialogue: 0,0:17:02.35,0:17:11.96,EN,,0,0,0,,is the result of multiplying the result of multiplying now the constants e1 and e2 together and putting e3 there.\nDialogue: 0,0:17:13.36,0:17:16.76,EN,,0,0,0,,So it says combine the constants that I had,\nDialogue: 0,0:17:16.76,0:17:22.70,EN,,0,0,0,,which was if I had a product of e1 and e2 and e3 just multiply--I mean and e1 and e2 are both constants, multiply them.\nDialogue: 0,0:17:23.84,0:17:25.48,EN,,0,0,0,,And you can make up the rules as you like.\nDialogue: 0,0:17:25.79,0:17:26.94,EN,,0,0,0,,There are lots of them here.\nDialogue: 0,0:17:27.42,0:17:31.04,EN,,0,0,0,,There are things as complicated, for example, as--\nDialogue: 0,0:17:31.26,0:17:33.93,EN,,0,0,0,,oh, I suppose down here some distributive law, you see.\nDialogue: 0,0:17:33.93,0:17:38.57,EN,,0,0,0,,The product of any object c and the sum of d and e\nDialogue: 0,0:17:39.02,0:17:43.66,EN,,0,0,0,,gives the result as the same as the sum of the product of c and d and the product of c and e.\nDialogue: 0,0:17:45.31,0:17:48.67,EN,,0,0,0,,Now, what exactly these rules are doesn't very much interest me.\nDialogue: 0,0:17:49.16,0:17:52.97,EN,,0,0,0,,We're going to be writing the language that will allow us to interpret these rules\nDialogue: 0,0:17:55.50,0:17:57.48,EN,,0,0,0,,so that we can, in fact, make up whatever rules we like,\nDialogue: 0,0:17:58.35,0:18:00.14,EN,,0,0,0,,another whole language of programming.\nDialogue: 0,0:18:03.39,0:18:04.04,EN,,0,0,0,,Well, let's see.\nDialogue: 0,0:18:05.18,0:18:06.96,EN,,0,0,0,,I haven't told you how we're going to do this.\nDialogue: 0,0:18:07.53,0:18:10.06,EN,,0,0,0,,And, of course, for a while, we're going to work on that.\nDialogue: 0,0:18:10.89,0:18:15.40,EN,,0,0,0,,But there's a real question of what is--what am I going to do at all at a large scale?\nDialogue: 0,0:18:17.08,0:18:18.22,EN,,0,0,0,,How do these rules work?\nDialogue: 0,0:18:19.00,0:18:25.45,EN,,0,0,0,,How is the simplifier program going to manipulate these rules with your expression to produce a reasonable answer?\nDialogue: 0,0:18:26.22,0:18:29.85,EN,,0,0,0,,Well, first, I'd like to think about these rules as being some sort of deck of them.\nDialogue: 0,0:18:32.52,0:18:34.22,EN,,0,0,0,,So here I have a whole bunch of rules,\nDialogue: 0,0:18:42.09,0:18:44.49,EN,,0,0,0,,Each rule-- here's a rule--\nDialogue: 0,0:18:46.97,0:18:49.24,EN,,0,0,0,,has a pattern and a skeleton.\nDialogue: 0,0:18:49.72,0:18:51.36,EN,,0,0,0,,I'm trying to make up a control structure for this.\nDialogue: 0,0:18:53.37,0:18:56.56,EN,,0,0,0,,Now, what I have is a matcher,\nDialogue: 0,0:19:00.99,0:19:03.76,EN,,0,0,0,,and I have something which is an instantiater.\nDialogue: 0,0:19:09.66,0:19:12.94,EN,,0,0,0,,And I'm going to pass from the matcher to the instantiater\nDialogue: 0,0:19:14.03,0:19:17.47,EN,,0,0,0,,some set of meaning for the pattern variables,\nDialogue: 0,0:19:18.06,0:19:19.42,EN,,0,0,0,,a dictionary, I'll call it.\nDialogue: 0,0:19:20.59,0:19:21.52,EN,,0,0,0,,A dictionary,\nDialogue: 0,0:19:24.92,0:19:27.82,EN,,0,0,0,,which will say x was matched against the following subexpression\nDialogue: 0,0:19:29.04,0:19:31.31,EN,,0,0,0,,and y was matched against another following subexpression.\nDialogue: 0,0:19:32.25,0:19:36.35,EN,,0,0,0,,And from the instantiater, I will be making expressions,and they will go into the matcher.\nDialogue: 0,0:19:37.16,0:19:38.36,EN,,0,0,0,,They will be expressions.\nDialogue: 0,0:19:45.00,0:19:48.41,EN,,0,0,0,,And the patterns of the rules will be fed into the matcher,\nDialogue: 0,0:19:49.24,0:19:54.40,EN,,0,0,0,,and the skeletons from the same rule will be fed into the instantiater.\nDialogue: 0,0:19:55.21,0:19:56.62,EN,,0,0,0,,Now, this is a little complicated\nDialogue: 0,0:19:57.12,0:19:59.53,EN,,0,0,0,,because when you have something like an algebraic expression,\nDialogue: 0,0:20:00.44,0:20:03.60,EN,,0,0,0,,where  some of the rules are intended to be able to allow you to substitute equal for equal.\nDialogue: 0,0:20:04.24,0:20:05.87,EN,,0,0,0,,These are equal transformation rules.\nDialogue: 0,0:20:06.88,0:20:09.29,EN,,0,0,0,,So all subexpressions of the expression should be looked at.\nDialogue: 0,0:20:11.13,0:20:15.82,EN,,0,0,0,,You give it an expression, this thing, and the rules should be cycled around.\nDialogue: 0,0:20:16.03,0:20:19.71,EN,,0,0,0,,First of all, for every subexpression of the expression you feed in,\nDialogue: 0,0:20:20.22,0:20:22.83,EN,,0,0,0,,all of the rules must be tried and looked at.\nDialogue: 0,0:20:24.33,0:20:27.07,EN,,0,0,0,,And if any rule matches, then this process occurs.\nDialogue: 0,0:20:27.30,0:20:30.63,EN,,0,0,0,,The dictionary--the dictionary is to have some values in it.\nDialogue: 0,0:20:30.63,0:20:33.39,EN,,0,0,0,,The instantiater makes a new expression,\nDialogue: 0,0:20:33.90,0:20:39.10,EN,,0,0,0,,which is basically replaces that part of the expression that was matched in your original expression.\nDialogue: 0,0:20:40.84,0:20:44.46,EN,,0,0,0,,And then, then, of course, we're going to recheck that,\nDialogue: 0,0:20:44.75,0:20:48.11,EN,,0,0,0,,going to go around these rules again, seeing if that could be simplified further.\nDialogue: 0,0:20:49.53,0:20:53.71,EN,,0,0,0,,And then, then we're going to do that for every subexpression until the thing no longer changes.\nDialogue: 0,0:20:54.96,0:20:57.50,EN,,0,0,0,,You can think of this as sort of an organic process.\nDialogue: 0,0:20:57.83,0:21:00.20,EN,,0,0,0,,You've got some sort of stew, right?\nDialogue: 0,0:21:00.24,0:21:04.32,EN,,0,0,0,,You've got bacteria or something, or enzymes in some, in some gooey mess.\nDialogue: 0,0:21:05.63,0:21:10.50,EN,,0,0,0,,And there's these--and these enzymes change things.\nDialogue: 0,0:21:10.50,0:21:14.38,EN,,0,0,0,,They attach to your expression, change it, and then they go away.\nDialogue: 0,0:21:15.28,0:21:17.83,EN,,0,0,0,,And they have to match. The key-in-lock phenomenon.\nDialogue: 0,0:21:18.00,0:21:19.73,EN,,0,0,0,,They match, they change it, they go away.\nDialogue: 0,0:21:19.73,0:21:21.68,EN,,0,0,0,,You can imagine it as a parallel process of some sort.\nDialogue: 0,0:21:22.70,0:21:24.97,EN,,0,0,0,,So you stick an expression into this mess,\nDialogue: 0,0:21:25.80,0:21:28.00,EN,,0,0,0,,and after a while, you take it out, and it's been simplified.\nDialogue: 0,0:21:30.44,0:21:32.64,EN,,0,0,0,,And it just keeps changing until it no longer can be changed.\nDialogue: 0,0:21:33.36,0:21:38.33,EN,,0,0,0,,But these enzymes can attach to any part of the, of the expression.\nDialogue: 0,0:21:39.21,0:21:43.76,EN,,0,0,0,,OK, at this point, I'd like to stop and ask for questions.\nDialogue: 0,0:21:44.92,0:21:45.36,EN,,0,0,0,,Yes.\nDialogue: 0,0:21:45.43,0:21:52.76,EN,,0,0,0,,AUDIENCE: This implies that the matching program and the instantiation program are separate programs; is that right? Or is that-- they are.\nDialogue: 0,0:21:52.76,0:21:53.85,EN,,0,0,0,,PROFESSOR: They're separate little pieces.\nDialogue: 0,0:21:54.14,0:21:56.60,EN,,0,0,0,,They fit together in a larger structure.\nDialogue: 0,0:21:57.26,0:21:59.13,EN,,0,0,0,,AUDIENCE: So I'm going through and matching\nDialogue: 0,0:21:59.61,0:22:03.21,EN,,0,0,0,,and passing the information about what I matched to an instantiater,\nDialogue: 0,0:22:03.39,0:22:06.03,EN,,0,0,0,,which makes the changes. And then I pass that back to the matcher?\nDialogue: 0,0:22:06.11,0:22:08.49,EN,,0,0,0,,PROFESSOR: It won't make a change. It will make a new expression,\nDialogue: 0,0:22:09.61,0:22:18.43,EN,,0,0,0,,which has, which has substituted the values of the pattern variable that were matched on the left-hand side for the variables that are mentioned,\nDialogue: 0,0:22:18.99,0:22:23.80,EN,,0,0,0,,the skeleton variables or evaluation variables or whatever I called them, on the right-hand side.\nDialogue: 0,0:22:25.20,0:22:27.08,EN,,0,0,0,,AUDIENCE: And then that's passed back into the matcher?\nDialogue: 0,0:22:27.20,0:22:32.32,EN,,0,0,0,,PROFESSOR: Then this is going to go around again. This is going to go through this mess until it no longer changes.\nDialogue: 0,0:22:33.31,0:22:37.00,EN,,0,0,0,,AUDIENCE: And it seems that there would be a danger of getting into a recursive loop.\nDialogue: 0,0:22:37.20,0:22:42.00,EN,,0,0,0,,Yes, if you do not write your rules nicely, you are-- indeed,\nDialogue: 0,0:22:42.00,0:22:45.53,EN,,0,0,0,,in any programming language you invent, if it's sufficiently powerful to do anything,\nDialogue: 0,0:22:45.72,0:22:48.40,EN,,0,0,0,,you can write programs that will go into infinite loops.\nDialogue: 0,0:22:49.37,0:22:55.07,EN,,0,0,0,,And indeed, writing a program for doing algebraic manipulation so on will produce infinite loops.\nDialogue: 0,0:23:01.05,0:23:01.52,EN,,0,0,0,,Go ahead.\nDialogue: 0,0:23:01.79,0:23:05.90,EN,,0,0,0,,AUDIENCE: Some language designers feel that this feature is so important\nDialogue: 0,0:23:05.93,0:23:12.03,EN,,0,0,0,,that it should become part of the basic language, for example, scheme in this case.\nDialogue: 0,0:23:12.03,0:23:13.96,EN,,0,0,0,,What are your thoughts on--\nDialogue: 0,0:23:13.96,0:23:15.08,EN,,0,0,0,,PROFESSOR: Which language feature?\nDialogue: 0,0:23:15.79,0:23:17.26,EN,,0,0,0,,AUDIENCE: The pattern matching.\nDialogue: 0,0:23:17.26,0:23:22.03,EN,,0,0,0,,It's all application of such rules should be--\nDialogue: 0,0:23:22.03,0:23:23.70,EN,,0,0,0,,PROFESSOR: Oh, you mean like Prolog?\nDialogue: 0,0:23:23.70,0:23:26.60,EN,,0,0,0,,AUDIENCE: Like Prolog, but it becomes a more general--\nDialogue: 0,0:23:26.60,0:23:27.64,EN,,0,0,0,,PROFESSOR: It's possible.\nDialogue: 0,0:23:28.46,0:23:32.30,EN,,0,0,0,,OK, I think my feeling about that is that\nDialogue: 0,0:23:33.16,0:23:36.49,EN,,0,0,0,,I would like to teach you how to do it so you don't depend upon some language designer.\nDialogue: 0,0:23:40.92,0:23:42.75,EN,,0,0,0,,PROFESSOR: You make it yourself. You can roll your own.\nDialogue: 0,0:23:45.28,0:23:45.63,EN,,0,0,0,,Thank you.\nDialogue: 0,0:23:45.63,0:23:50.63,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:23:50.63,0:23:53.13,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:23:53.13,0:23:55.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:24:00.32,0:24:06.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:24:07.07,0:24:10.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}Pattern-matching: Rule-based Substitution\nDialogue: 0,0:24:14.08,0:24:15.80,EN,,0,0,0,,Well, let's see.\nDialogue: 0,0:24:15.80,0:24:17.21,EN,,0,0,0,,Now we have to tell you how it works.\nDialogue: 0,0:24:20.00,0:24:24.11,EN,,0,0,0,,It conveniently breaks up into various pieces.\nDialogue: 0,0:24:24.80,0:24:26.54,EN,,0,0,0,,I'd like to look now at the matcher.\nDialogue: 0,0:24:28.72,0:24:31.42,EN,,0,0,0,,The matcher has the following basic structure.\nDialogue: 0,0:24:32.86,0:24:45.12,EN,,0,0,0,,It's a box that takes as its input an expression and a pattern,\nDialogue: 0,0:24:52.09,0:24:53.95,EN,,0,0,0,,and it turns out a dictionary.\nDialogue: 0,0:25:01.71,0:25:08.67,EN,,0,0,0,,A dictionary, remember, is a mapping of pattern variables to the values that were found by matching,\nDialogue: 0,0:25:09.15,0:25:11.05,EN,,0,0,0,,and it puts out another dictionary,\nDialogue: 0,0:25:18.24,0:25:25.53,EN,,0,0,0,,which is the result of augmenting this dictionary by what was found in matching this expression against this pattern.\nDialogue: 0,0:25:28.00,0:25:28.83,EN,,0,0,0,,So that's the matcher.\nDialogue: 0,0:25:33.87,0:25:36.54,EN,,0,0,0,,Now, this is a rather complicated program,\nDialogue: 0,0:25:37.20,0:25:41.58,EN,,0,0,0,,and we can look at it on the overhead over here and see,\nDialogue: 0,0:25:41.98,0:25:43.87,EN,,0,0,0,,ha ha, it's very complicated.\nDialogue: 0,0:25:44.43,0:25:45.87,EN,,0,0,0,,I just want you to look at the shape of it.\nDialogue: 0,0:25:46.78,0:25:49.85,EN,,0,0,0,,It's too complicated to look at except in pieces.\nDialogue: 0,0:25:51.72,0:25:59.24,EN,,0,0,0,,However, it's a fairly large, complicated program with a lot of sort of indented structure.\nDialogue: 0,0:26:00.09,0:26:05.28,EN,,0,0,0,,At the largest scale-- you don't try to read those characters, but at the largest scale,\nDialogue: 0,0:26:05.43,0:26:10.36,EN,,0,0,0,,you see that there is a case analysis, which is all these cases lined up.\nDialogue: 0,0:26:12.09,0:26:16.19,EN,,0,0,0,,What we're now going to do is look at this in a bit more detail,\nDialogue: 0,0:26:16.67,0:26:18.60,EN,,0,0,0,,attempting to understand how it works.\nDialogue: 0,0:26:20.08,0:26:22.35,EN,,0,0,0,,Let's go now to the first slide,\nDialogue: 0,0:26:23.55,0:26:27.93,EN,,0,0,0,,showing some of the structure of the matcher at a large scale.\nDialogue: 0,0:26:28.81,0:26:36.33,EN,,0,0,0,,And we see that the matcher, the matcher takes as its input a pattern, an expression, and a dictionary.\nDialogue: 0,0:26:38.57,0:26:40.40,EN,,0,0,0,,And there is a case analysis here,\nDialogue: 0,0:26:41.24,0:26:45.61,EN,,0,0,0,,which is made out of several cases, some of which have been left out over here,\nDialogue: 0,0:26:46.62,0:26:48.62,EN,,0,0,0,,and the general case, which I'd like you to see.\nDialogue: 0,0:26:50.52,0:26:53.28,EN,,0,0,0,,Let's consider this general case. It's a very important pattern.\nDialogue: 0,0:26:56.32,0:27:01.61,EN,,0,0,0,,The problem is that we have to examine two trees simultaneously.\nDialogue: 0,0:27:02.50,0:27:08.03,EN,,0,0,0,,One of the trees is the tree of the expression, and the other is the tree of the pattern.\nDialogue: 0,0:27:08.59,0:27:10.11,EN,,0,0,0,,We have to compare them with each other\nDialogue: 0,0:27:11.37,0:27:16.38,EN,,0,0,0,,so that the subexpressions of the expression are matched against subexpressions of the pattern.\nDialogue: 0,0:27:18.38,0:27:23.44,EN,,0,0,0,,Looking at that in a bit more detail, suppose I had a pattern, a pattern,\nDialogue: 0,0:27:23.93,0:27:31.24,EN,,0,0,0,,which was the sum of the product of a thing which we will call x\nDialogue: 0,0:27:32.44,0:27:35.53,EN,,0,0,0,,and a thing which we will call y,\nDialogue: 0,0:27:39.12,0:27:42.04,EN,,0,0,0,,and the sum of that, and the same thing we call y.\nDialogue: 0,0:27:45.21,0:27:47.53,EN,,0,0,0,,So we're looking for a sum of a product\nDialogue: 0,0:27:48.99,0:27:54.78,EN,,0,0,0,,whose second--whose second argument is the same as the second argument of the sum.\nDialogue: 0,0:27:57.02,0:27:58.84,EN,,0,0,0,,That's a thing you might be looking for.\nDialogue: 0,0:27:59.60,0:28:02.04,EN,,0,0,0,,Well, that, as a pattern, looks like this.\nDialogue: 0,0:28:03.02,0:28:04.01,EN,,0,0,0,,There is a tree,\nDialogue: 0,0:28:04.94,0:28:06.25,EN,,0,0,0,,which consists of a sum,\nDialogue: 0,0:28:08.08,0:28:20.25,EN,,0,0,0,,and a product with a pattern variable question mark x and question mark y,\nDialogue: 0,0:28:21.36,0:28:22.73,EN,,0,0,0,,and question mark y,\nDialogue: 0,0:28:24.92,0:28:26.94,EN,,0,0,0,,just looking at the same, just writing down the list structure in a different way.\nDialogue: 0,0:28:28.75,0:28:31.76,EN,,0,0,0,,Now, suppose we were matching that against an expression which matches it,\nDialogue: 0,0:28:32.49,0:28:39.85,EN,,0,0,0,,the product of 3 and x and, say, x.\nDialogue: 0,0:28:42.41,0:28:43.36,EN,,0,0,0,,That's another tree.\nDialogue: 0,0:28:44.33,0:28:56.06,EN,,0,0,0,,It's the sum of the product of 3 and x and of x.\nDialogue: 0,0:28:59.44,0:29:03.02,EN,,0,0,0,,So what I want to do is traverse these two trees simultaneously.\nDialogue: 0,0:29:04.41,0:29:07.82,EN,,0,0,0,,And what I'd like to do is walk them like this.\nDialogue: 0,0:29:08.67,0:29:12.96,EN,,0,0,0,,I'm going to say are these the same?\nDialogue: 0,0:29:12.96,0:29:14.32,EN,,0,0,0,,This is a complicated object.\nDialogue: 0,0:29:15.21,0:29:17.26,EN,,0,0,0,,Let's look at the left branches.\nDialogue: 0,0:29:17.26,0:29:18.14,EN,,0,0,0,,Well, that could be the car.\nDialogue: 0,0:29:18.56,0:29:21.21,EN,,0,0,0,,How does that look? Oh yes, the plus looks just fine.\nDialogue: 0,0:29:21.68,0:29:24.20,EN,,0,0,0,,But the next thing here is a complicated thing.\nDialogue: 0,0:29:24.20,0:29:24.84,EN,,0,0,0,,Let's look at that.\nDialogue: 0,0:29:25.20,0:29:26.80,EN,,0,0,0,,Oh yes, that's pretty fine, too.\nDialogue: 0,0:29:26.80,0:29:27.79,EN,,0,0,0,,They're both asterisks.\nDialogue: 0,0:29:28.51,0:29:30.24,EN,,0,0,0,,Now, whoops!\nDialogue: 0,0:29:30.40,0:29:33.60,EN,,0,0,0,,My pattern variable, it matches against the 3.\nDialogue: 0,0:29:34.27,0:29:35.92,EN,,0,0,0,,Remember, x equals 3 now.\nDialogue: 0,0:29:36.36,0:29:37.37,EN,,0,0,0,,That's in my dictionary,\nDialogue: 0,0:29:37.56,0:29:40.73,EN,,0,0,0,,and the dictionary's going to follow along with me: x equals three.\nDialogue: 0,0:29:41.45,0:29:45.87,EN,,0,0,0,,Ah yes, x equals 3 and y equals x, different x.\nDialogue: 0,0:29:46.83,0:29:51.20,EN,,0,0,0,,The pattern x is the expression x, the pattern y.\nDialogue: 0,0:29:53.61,0:29:57.76,EN,,0,0,0,,Oh yes, the pattern variable y, I've already got a value for it. It's x.\nDialogue: 0,0:29:58.36,0:30:00.06,EN,,0,0,0,,Is this an x? Oh yeah, sure it is.\nDialogue: 0,0:30:00.06,0:30:00.75,EN,,0,0,0,,That's fine.\nDialogue: 0,0:30:02.03,0:30:02.78,EN,,0,0,0,,Yep, done.\nDialogue: 0,0:30:03.39,0:30:08.09,EN,,0,0,0,,I now have a dictionary, which I've accumulated by making this walk.\nDialogue: 0,0:30:11.42,0:30:14.51,EN,,0,0,0,,Well, now let's look at this general case here and see how that works.\nDialogue: 0,0:30:15.88,0:30:16.51,EN,,0,0,0,,Here we have it.\nDialogue: 0,0:30:17.20,0:30:21.66,EN,,0,0,0,,I take in a pattern variable -- sorry -- a pattern, an expression, and a dictionary.\nDialogue: 0,0:30:22.38,0:30:27.50,EN,,0,0,0,,And now I'm going to do a complicated thing here, which is the general case.\nDialogue: 0,0:30:29.98,0:30:34.80,EN,,0,0,0,,The expression is made out of two parts: a left and a right half, in general.\nDialogue: 0,0:30:35.45,0:30:38.81,EN,,0,0,0,,Anything that's complicated is made out of two pieces in a Lisp system.\nDialogue: 0,0:30:40.03,0:30:41.23,EN,,0,0,0,,Well, now what do we have here?\nDialogue: 0,0:30:41.88,0:30:48.84,EN,,0,0,0,,I'm going to match the car's of the two expressions against each other with respect to the dictionary I already have,\nDialogue: 0,0:30:50.30,0:30:53.12,EN,,0,0,0,,producing a dictionary as its value,\nDialogue: 0,0:30:54.14,0:30:57.26,EN,,0,0,0,,which I will then use for matching the cdr's against each other.\nDialogue: 0,0:30:58.51,0:31:02.09,EN,,0,0,0,,So that's how the dictionary travels, threads the entire structure.\nDialogue: 0,0:31:03.66,0:31:07.53,EN,,0,0,0,,And then the result of that is the dictionary for the match of the car and the cdr,\nDialogue: 0,0:31:10.12,0:31:12.41,EN,,0,0,0,,and that's what's going to be returned as a value.\nDialogue: 0,0:31:13.61,0:31:15.84,EN,,0,0,0,,Now, at any point, a match might fail.\nDialogue: 0,0:31:16.62,0:31:18.20,EN,,0,0,0,,It may be the case, for example,\nDialogue: 0,0:31:18.36,0:31:27.18,EN,,0,0,0,,if we go back and look at an expression that doesn't quite match, like supposing this was a 4.\nDialogue: 0,0:31:29.13,0:31:34.81,EN,,0,0,0,,Well, now these two don't match any more, because the x that had to be  --\nDialogue: 0,0:31:34.93,0:31:37.34,EN,,0,0,0,,sorry, the y that had to be x here\nDialogue: 0,0:31:37.82,0:31:40.12,EN,,0,0,0,,and this y has to be 4.\nDialogue: 0,0:31:40.53,0:31:43.52,EN,,0,0,0,,But x and 4 were not the same object syntactically.\nDialogue: 0,0:31:44.59,0:31:48.81,EN,,0,0,0,,So this wouldn't match, and that would be rejected sometimes, so matches may fail.\nDialogue: 0,0:31:50.19,0:31:56.08,EN,,0,0,0,,Now, of course, because this matcher takes the dictionary from the previous match as input,\nDialogue: 0,0:31:56.52,0:31:58.28,EN,,0,0,0,,it must be able to propagate the failures.\nDialogue: 0,0:31:58.57,0:32:01.04,EN,,0,0,0,,And so that's what the first clause of this conditional does.\nDialogue: 0,0:32:03.61,0:32:08.19,EN,,0,0,0,,It's also true that if it turned out that the pattern was not atomic--\nDialogue: 0,0:32:08.50,0:32:11.45,EN,,0,0,0,,see, if the pattern was atomic, I'd go into this stuff, which we haven't looked at yet.\nDialogue: 0,0:32:12.17,0:32:13.56,EN,,0,0,0,,But if the pattern is not atomic\nDialogue: 0,0:32:15.05,0:32:19.23,EN,,0,0,0,,and the expression is atomic-- it's not made out of pieces--\nDialogue: 0,0:32:20.14,0:32:22.65,EN,,0,0,0,,then that must be a failure, and so we go over here.\nDialogue: 0,0:32:23.64,0:32:30.78,EN,,0,0,0,,If the pattern is not atomic and the pattern is not a pattern variable--I have to remind myself of that-- then we go over here.\nDialogue: 0,0:32:30.96,0:32:32.51,EN,,0,0,0,,So that's way, failures may occur.\nDialogue: 0,0:32:35.26,0:32:39.12,EN,,0,0,0,,OK, so now let's look at the insides of this thing.\nDialogue: 0,0:32:39.84,0:32:42.93,EN,,0,0,0,,Well, the first place to look is what happens if I have an atomic pattern?\nDialogue: 0,0:32:42.93,0:32:43.90,EN,,0,0,0,,That's very simple.\nDialogue: 0,0:32:43.90,0:32:46.50,EN,,0,0,0,,A pattern that's not made out of any pieces: foo.\nDialogue: 0,0:32:47.37,0:32:48.54,EN,,0,0,0,,That's a nice atomic pattern.\nDialogue: 0,0:32:49.16,0:32:51.24,EN,,0,0,0,,Well, here's what we see.\nDialogue: 0,0:32:52.08,0:32:55.82,EN,,0,0,0,,If the pattern is atomic, then if the expression is atomic,\nDialogue: 0,0:32:56.80,0:33:01.85,EN,,0,0,0,,then if they are the same thing, then the dictionary I get is the same one as I had before.\nDialogue: 0,0:33:03.08,0:33:04.00,EN,,0,0,0,,Nothing's changed.\nDialogue: 0,0:33:04.60,0:33:10.33,EN,,0,0,0,,It's just that I matched plus against plus, asterisk against asterisk, x against x.\nDialogue: 0,0:33:11.42,0:33:12.33,EN,,0,0,0,,That's all fine.\nDialogue: 0,0:33:13.07,0:33:16.81,EN,,0,0,0,,However, if the pattern is not the one which is the expression,\nDialogue: 0,0:33:17.32,0:33:21.36,EN,,0,0,0,,if I have two separate atomic objects, then it was matching plus against asterisk,\nDialogue: 0,0:33:22.44,0:33:23.40,EN,,0,0,0,,which case I fail.\nDialogue: 0,0:33:25.60,0:33:34.56,EN,,0,0,0,,Or if it turns out that the pattern is atomic but the expression is complicated, it's not atomic, then I get a failure.\nDialogue: 0,0:33:37.40,0:33:38.24,EN,,0,0,0,,That's very simple.\nDialogue: 0,0:33:38.81,0:33:43.61,EN,,0,0,0,,Now, what about the various kinds of pattern variables?\nDialogue: 0,0:33:44.09,0:33:46.54,EN,,0,0,0,,We had three kinds. I give them the names.\nDialogue: 0,0:33:47.39,0:33:52.03,EN,,0,0,0,,They're arbitrary constants, arbitrary variables, and arbitrary expressions.\nDialogue: 0,0:33:53.82,0:34:00.14,EN,,0,0,0,,A question mark x is an arbitrary expression.\nDialogue: 0,0:34:01.18,0:34:04.54,EN,,0,0,0,,A question mark cx is an arbitrary constant,\nDialogue: 0,0:34:04.73,0:34:07.29,EN,,0,0,0,,and a question mark vx is an arbitrary variable.\nDialogue: 0,0:34:08.96,0:34:09.79,EN,,0,0,0,,Well, what do we do here?\nDialogue: 0,0:34:10.51,0:34:16.94,EN,,0,0,0,,Looking at this, we see that if I have an arbitrary constant, if the pattern is an arbitrary constant,\nDialogue: 0,0:34:17.53,0:34:20.57,EN,,0,0,0,,then it had better be the case that the expression had better be a constant.\nDialogue: 0,0:34:21.48,0:34:23.53,EN,,0,0,0,,If the expression is not a constant, then that match fails.\nDialogue: 0,0:34:23.83,0:34:27.50,EN,,0,0,0,,If it is a constant, however, then I wish to extend the dictionary.\nDialogue: 0,0:34:27.50,0:34:29.69,EN,,0,0,0,,I wish to extend the dictionary\nDialogue: 0,0:34:30.70,0:34:37.76,EN,,0,0,0,,with that pattern being remembered to be that expression using the old dictionary as a starting point.\nDialogue: 0,0:34:41.16,0:34:42.75,EN,,0,0,0,,So really, for arbitrary variables,\nDialogue: 0,0:34:43.72,0:34:47.46,EN,,0,0,0,,I have to check first if the expression is a variable by matching against.\nDialogue: 0,0:34:47.46,0:34:50.09,EN,,0,0,0,,If so, it's worth extending the dictionary\nDialogue: 0,0:34:50.38,0:34:54.65,EN,,0,0,0,,so the pattern is remembered to be matched against that expression, given the original dictionary,\nDialogue: 0,0:34:55.28,0:34:56.70,EN,,0,0,0,,and this makes a new dictionary.\nDialogue: 0,0:34:58.88,0:35:04.16,EN,,0,0,0,,Now, it has to check. There's a sorts of failure inside extend dictionary, which is that--\nDialogue: 0,0:35:04.16,0:35:07.50,EN,,0,0,0,,if one of these pattern variables already has a value\nDialogue: 0,0:35:09.23,0:35:16.17,EN,,0,0,0,,and I'm trying to match the thing against something else which is not equivalent to the one that I've already matched it against once,\nDialogue: 0,0:35:16.43,0:35:18.36,EN,,0,0,0,,then a failure will come flying out of here, too.\nDialogue: 0,0:35:20.16,0:35:21.56,EN,,0,0,0,,And I will see that some time.\nDialogue: 0,0:35:22.91,0:35:29.36,EN,,0,0,0,,And finally, an expression does not have to check anything syntactic about the expression that's being matched,\nDialogue: 0,0:35:30.11,0:35:32.20,EN,,0,0,0,,so all it does is it's an extension of the dictionary.\nDialogue: 0,0:35:34.76,0:35:38.32,EN,,0,0,0,,So you've just seen a complete, very simple matcher.\nDialogue: 0,0:35:39.28,0:35:41.37,EN,,0,0,0,,Now, one of the things that's rather remarkable about this\nDialogue: 0,0:35:41.66,0:35:45.12,EN,,0,0,0,,is people pay an awful lot of money these days for someone to make\nDialogue: 0,0:35:45.46,0:35:47.52,EN,,0,0,0,,a, quote, AI expert system\nDialogue: 0,0:35:48.40,0:35:52.03,EN,,0,0,0,,that has nothing more in it than a matcher and maybe an instantiater like this.\nDialogue: 0,0:35:53.56,0:35:56.94,EN,,0,0,0,,But it's very easy to do, and now, of course, you can start up a little start-up company\nDialogue: 0,0:35:57.42,0:36:01.72,EN,,0,0,0,,and make a couple of megabucks in the next week taking some people for a ride.\nDialogue: 0,0:36:03.79,0:36:08.57,EN,,0,0,0,,I mean, 20 years ago, this was remarkable, this kind of program.\nDialogue: 0,0:36:09.74,0:36:12.81,EN,,0,0,0,,But now, this is sort of easy. You can teach it to freshmen.\nDialogue: 0,0:36:13.63,0:36:15.47,EN,,0,0,0,,Well, now there's an instantiater as well.\nDialogue: 0,0:36:20.22,0:36:23.07,EN,,0,0,0,,The problem is they're all going off and making more money than I do. Alright?\nDialogue: 0,0:36:24.97,0:36:26.59,EN,,0,0,0,,But that's always been true of universities.\nDialogue: 0,0:36:27.10,0:36:39.42,EN,,0,0,0,,As expression, the purpose of the instantiater is to make expressions given a dictionary and a skeleton.\nDialogue: 0,0:36:44.35,0:36:45.69,EN,,0,0,0,,And that's not very hard at all.\nDialogue: 0,0:36:46.60,0:36:53.36,EN,,0,0,0,,We'll see that very simply in the next, the next slide here.\nDialogue: 0,0:36:53.88,0:36:59.29,EN,,0,0,0,,To instantiate a skeleton, given a particular dictionary-- oh, this is easy.\nDialogue: 0,0:36:59.68,0:37:03.29,EN,,0,0,0,,We're going to do a recursive tree walk over the skeleton.\nDialogue: 0,0:37:04.08,0:37:08.33,EN,,0,0,0,,And for everything which is a skeleton variable-- I don't know, call it a skeleton evaluation.\nDialogue: 0,0:37:08.41,0:37:11.42,EN,,0,0,0,,That's the name and the abstract syntax that I give it in this program:\nDialogue: 0,0:37:11.60,0:37:16.46,EN,,0,0,0,,a skeleton evaluation, a thing beginning with a colon in the rules.\nDialogue: 0,0:37:18.25,0:37:24.30,EN,,0,0,0,,For anything of that case, I'm going to look up the answer in the dictionary, and we'll worry about that in a second.\nDialogue: 0,0:37:24.30,0:37:25.61,EN,,0,0,0,,Let's look at this as a whole.\nDialogue: 0,0:37:27.77,0:37:31.80,EN,,0,0,0,,Here, I have-- I'm going to instantiate a skeleton, given a dictionary.\nDialogue: 0,0:37:32.75,0:37:37.15,EN,,0,0,0,,Well, I'm going to define some internal loop right there,\nDialogue: 0,0:37:38.14,0:37:39.85,EN,,0,0,0,,and it's going to do something very simple.\nDialogue: 0,0:37:40.17,0:37:43.50,EN,,0,0,0,,Even if a skeleton--even if a skeleton is simple and atomic,\nDialogue: 0,0:37:44.60,0:37:47.45,EN,,0,0,0,,in which case it's nothing more than giving the skeleton back as an answer,\nDialogue: 0,0:37:48.84,0:37:51.87,EN,,0,0,0,,or in the general case, it's complicated,\nDialogue: 0,0:37:52.60,0:37:59.40,EN,,0,0,0,,in which case I'm going to make up the expression which is the result of instantiating--\nDialogue: 0,0:37:59.40,0:38:04.25,EN,,0,0,0,,calling this loop recursively-- instantiating the car of the skeleton and the cdr.\nDialogue: 0,0:38:04.89,0:38:06.24,EN,,0,0,0,,So here is a recursive tree walk.\nDialogue: 0,0:38:08.41,0:38:14.36,EN,,0,0,0,,However, if it turns out to be a skeleton evaluation, a colon expression in the skeleton,\nDialogue: 0,0:38:14.96,0:38:22.64,EN,,0,0,0,,then what I'm going to do is find the expression that's in the colon-- the CADR in this case.\nDialogue: 0,0:38:22.81,0:38:26.25,EN,,0,0,0,,It's a piece of abstract syntax here, so I can change my representation of rules.\nDialogue: 0,0:38:27.52,0:38:32.73,EN,,0,0,0,,I'm going to evaluate that relative to this dictionary, whatever evaluation means.\nDialogue: 0,0:38:32.90,0:38:34.65,EN,,0,0,0,,We'll find out a lot about that sometime.\nDialogue: 0,0:38:36.12,0:38:38.35,EN,,0,0,0,,And the result of that is my answer.\nDialogue: 0,0:38:39.68,0:38:43.66,EN,,0,0,0,,so. I start up this loop-- here's my initialization-- by calling it with the whole skeleton,\nDialogue: 0,0:38:44.44,0:38:47.04,EN,,0,0,0,,and this will just do a recursive decomposition into pieces.\nDialogue: 0,0:38:49.63,0:38:56.48,EN,,0,0,0,,Now, one more little bit of detail is what happens inside evaluate?\nDialogue: 0,0:38:57.18,0:38:59.07,EN,,0,0,0,,I can't tell you that in great detail.\nDialogue: 0,0:38:59.98,0:39:01.34,EN,,0,0,0,,I'll tell you a little bit of it.\nDialogue: 0,0:39:01.56,0:39:03.74,EN,,0,0,0,,Later, we're going to see--look into this in much more detail.\nDialogue: 0,0:39:05.29,0:39:10.81,EN,,0,0,0,,To evaluate some form, some expression with respect to a dictionary,\nDialogue: 0,0:39:11.90,0:39:14.17,EN,,0,0,0,,if the expression is an atomic object, well,\nDialogue: 0,0:39:15.04,0:39:16.22,EN,,0,0,0,,I'm going to go look it up.\nDialogue: 0,0:39:18.60,0:39:19.87,EN,,0,0,0,,Nothing very exciting there.\nDialogue: 0,0:39:20.57,0:39:23.66,EN,,0,0,0,,Otherwise, I'm going to do something complicated here,\nDialogue: 0,0:39:23.83,0:39:28.28,EN,,0,0,0,,which is I'm going to apply a procedure which is the result of looking up the operator part\nDialogue: 0,0:39:29.44,0:39:31.68,EN,,0,0,0,,in something that we're going to find out about someday.\nDialogue: 0,0:39:32.14,0:39:34.20,EN,,0,0,0,,I want you realize you're seeing magic now.\nDialogue: 0,0:39:34.67,0:39:38.72,EN,,0,0,0,,This magic will become clear very soon, but not today.\nDialogue: 0,0:39:40.00,0:39:46.51,EN,,0,0,0,,Then I'm looking at--looking up all the pieces, all the arguments to that in the dictionary.\nDialogue: 0,0:39:48.56,0:39:50.88,EN,,0,0,0,,So I don't want you to look at this in detail.\nDialogue: 0,0:39:51.44,0:39:53.44,EN,,0,0,0,,I want you to see that there's more going on here,\nDialogue: 0,0:39:54.17,0:39:56.75,EN,,0,0,0,,and we're going to see more about this.\nDialogue: 0,0:39:59.04,0:40:00.88,EN,,0,0,0,,But it's-- the magic is going to stop.\nDialogue: 0,0:40:02.57,0:40:06.96,EN,,0,0,0,,This part has to do with Lisp, and it's the end of that.\nDialogue: 0,0:40:10.25,0:40:13.56,EN,,0,0,0,,OK, so now we know about matching and instantiation.\nDialogue: 0,0:40:15.05,0:40:16.60,EN,,0,0,0,,Are there any questions for this segment?\nDialogue: 0,0:40:28.10,0:40:29.80,EN,,0,0,0,,AUDIENCE: I have a question.\nDialogue: 0,0:40:29.80,0:40:30.43,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:40:30.43,0:40:32.56,EN,,0,0,0,,AUDIENCE: Is it possible to bring up a previous slide?\nDialogue: 0,0:40:33.60,0:40:35.56,EN,,0,0,0,,It's about this define match pattern.\nDialogue: 0,0:40:36.16,0:40:40.76,EN,,0,0,0,,PROFESSOR: Yes. You'd like to see the overall slide define match pattern.\nDialogue: 0,0:40:40.76,0:40:43.06,EN,,0,0,0,,Can somebody put up the -- no, the overhead.\nDialogue: 0,0:40:43.06,0:40:45.16,EN,,0,0,0,,That's the biggest scale one.\nDialogue: 0,0:40:45.31,0:40:46.40,EN,,0,0,0,,What part would you like to see?\nDialogue: 0,0:40:46.76,0:40:49.96,EN,,0,0,0,,AUDIENCE: Well, the top would be fine.\nDialogue: 0,0:40:49.96,0:40:53.76,EN,,0,0,0,,Any of the parts where you're passing failed.\nDialogue: 0,0:40:54.52,0:40:55.21,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:40:55.64,0:40:59.33,EN,,0,0,0,,AUDIENCE: The idea is to pass failed back to the dictionary; is that right?\nDialogue: 0,0:40:59.33,0:41:04.25,EN,,0,0,0,,PROFESSOR: The dictionary is the answer to a match, right?\nDialogue: 0,0:41:05.16,0:41:09.80,EN,,0,0,0,,And it is either some mapping\nDialogue: 0,0:41:11.07,0:41:14.03,EN,,0,0,0,,or there's no match. It doesn't match.\nDialogue: 0,0:41:14.46,0:41:14.97,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:41:15.26,0:41:17.83,EN,,0,0,0,,PROFESSOR: So what you're seeing over here is, in fact,\nDialogue: 0,0:41:17.83,0:41:22.60,EN,,0,0,0,,because the fact that a match may have another match pass in the dictionary,\nDialogue: 0,0:41:22.80,0:41:24.65,EN,,0,0,0,,as you see in the general case down here.\nDialogue: 0,0:41:25.12,0:41:27.93,EN,,0,0,0,,Here's the general case where a match passes another match to the dictionary.\nDialogue: 0,0:41:28.14,0:41:34.16,EN,,0,0,0,,When I match the cdr's, I match them in the dictionary that is resulting from matching the car's.\nDialogue: 0,0:41:36.06,0:41:37.08,EN,,0,0,0,,OK, that's what I have here.\nDialogue: 0,0:41:37.29,0:41:40.30,EN,,0,0,0,,So because of that, if the match of the car's fails,\nDialogue: 0,0:41:41.23,0:41:45.44,EN,,0,0,0,,then it may be necessary that the match of the cdr's propagates that failure,\nDialogue: 0,0:41:45.95,0:41:46.96,EN,,0,0,0,,and that's what the first line is.\nDialogue: 0,0:41:48.26,0:41:51.73,EN,,0,0,0,,AUDIENCE: OK, well, I'm still unclear what matches--\nDialogue: 0,0:41:51.73,0:41:54.24,EN,,0,0,0,,what comes out of one instance of the match?\nDialogue: 0,0:41:54.73,0:41:56.00,EN,,0,0,0,,PROFESSOR: One of two possibilities.\nDialogue: 0,0:41:56.33,0:41:59.15,EN,,0,0,0,,Either the symbol failed, which means there is no match.\nDialogue: 0,0:41:59.53,0:41:59.93,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:41:59.93,0:42:03.87,EN,,0,0,0,,PROFESSOR: Or some mapping, which is an abstract thing right now,\nDialogue: 0,0:42:04.16,0:42:05.68,EN,,0,0,0,,and you should know about the structure of it,\nDialogue: 0,0:42:06.49,0:42:13.96,EN,,0,0,0,,which relates the pattern variables to their values as picked up in the match.\nDialogue: 0,0:42:14.68,0:42:16.70,EN,,0,0,0,,AUDIENCE: OK, so it is--\nDialogue: 0,0:42:16.80,0:42:18.57,EN,,0,0,0,,PROFESSOR: That's constructed by extend dictionary.\nDialogue: 0,0:42:18.80,0:42:28.54,EN,,0,0,0,,AUDIENCE: So the recursive nature brings about the fact that if ever a failed gets passed out of any calling of match,\nDialogue: 0,0:42:28.68,0:42:30.30,EN,,0,0,0,,then the first condition will pick it up--\nDialogue: 0,0:42:30.40,0:42:33.56,EN,,0,0,0,,PROFESSOR: And just propagate it along without any further ado, right.\nDialogue: 0,0:42:33.56,0:42:34.83,EN,,0,0,0,,AUDIENCE: Oh, right.\nDialogue: 0,0:42:35.50,0:42:37.36,EN,,0,0,0,,PROFESSOR: That's just the fastest way to get that failure out of there.\nDialogue: 0,0:42:42.86,0:42:43.60,EN,,0,0,0,,Yes.\nDialogue: 0,0:42:43.84,0:42:47.23,EN,,0,0,0,,AUDIENCE: If I don't fail, that means that I've matched a pattern,\nDialogue: 0,0:42:47.84,0:42:53.00,EN,,0,0,0,,and I run the procedure extend dict and then pass in the pattern in the expression.\nDialogue: 0,0:42:55.21,0:42:58.43,EN,,0,0,0,,But the substitution will not be made at that point; is that right?\nDialogue: 0,0:42:58.43,0:42:59.03,EN,,0,0,0,,I'm just--\nDialogue: 0,0:42:59.03,0:42:59.46,EN,,0,0,0,,PROFESSOR: No, no.\nDialogue: 0,0:42:59.46,0:43:02.40,EN,,0,0,0,,There's no substitution being there because there's no skeleton to be substituted in.\nDialogue: 0,0:43:02.40,0:43:03.06,EN,,0,0,0,,AUDIENCE: Right. So\nDialogue: 0,0:43:03.06,0:43:07.16,EN,,0,0,0,,PROFESSOR: All you've got there is we're making up the dictionary for later substitution.\nDialogue: 0,0:43:08.25,0:43:12.43,EN,,0,0,0,,AUDIENCE: And what would the dictionary look like? Is it ordered pairs?\nDialogue: 0,0:43:12.72,0:43:15.96,EN,,0,0,0,,PROFESSOR: Ahhhhh, That's--that's not told to you.\nDialogue: 0,0:43:15.96,0:43:16.89,EN,,0,0,0,,We're being abstract.\nDialogue: 0,0:43:17.06,0:43:17.56,EN,,0,0,0,,AUDIENCE: OK.\nDialogue: 0,0:43:17.56,0:43:18.90,EN,,0,0,0,,PROFESSOR: Why do you want to know?\nDialogue: 0,0:43:18.90,0:43:21.64,EN,,0,0,0,,What it is, it's a function. It's a function.\nDialogue: 0,0:43:21.69,0:43:22.33,EN,,0,0,0,,AUDIENCE: Well, the reason I want to know is--\nDialogue: 0,0:43:22.33,0:43:24.17,EN,,0,0,0,,PROFESSOR: A function abstractly is a set of ordered pairs.\nDialogue: 0,0:43:25.12,0:43:28.44,EN,,0,0,0,,It could be implemented as a set of list pairs.\nDialogue: 0,0:43:29.06,0:43:32.43,EN,,0,0,0,,It could be implemented as some fancy table mechanism.\nDialogue: 0,0:43:32.56,0:43:34.16,EN,,0,0,0,,It could be implemented as a function.\nDialogue: 0,0:43:35.80,0:43:37.40,EN,,0,0,0,,And somehow, I'm building up a function.\nDialogue: 0,0:43:39.02,0:43:39.87,EN,,0,0,0,,But I'm not telling you.\nDialogue: 0,0:43:40.84,0:43:43.08,EN,,0,0,0,,That's up to George, who's going to build that later.\nDialogue: 0,0:43:49.56,0:43:52.06,EN,,0,0,0,,I know you really badly want to write concrete things.\nDialogue: 0,0:43:52.36,0:43:54.19,EN,,0,0,0,,I'm not going to let you do that.\nDialogue: 0,0:43:54.43,0:43:59.23,EN,,0,0,0,,AUDIENCE: Well, let me at least ask, what is the important information there that's being passed to extend dict?\nDialogue: 0,0:43:59.74,0:44:02.08,EN,,0,0,0,,I want to pass the pattern I found--\nDialogue: 0,0:44:02.73,0:44:04.83,EN,,0,0,0,,PROFESSOR: Yes. The pattern that's matched against the expression.\nDialogue: 0,0:44:04.83,0:44:09.30,EN,,0,0,0,,You want to have the pattern, which happens to be in those cases pattern variables, right?\nDialogue: 0,0:44:09.85,0:44:12.89,EN,,0,0,0,,All of those three cases for extend dict are pattern variables.\nDialogue: 0,0:44:13.20,0:44:13.50,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:44:14.48,0:44:18.75,EN,,0,0,0,,PROFESSOR: So you have a pattern variable that is to be given a value in a dictionary.\nDialogue: 0,0:44:19.45,0:44:22.11,EN,,0,0,0,,PROFESSOR: The value is the expression that it matched against.\nDialogue: 0,0:44:23.31,0:44:29.63,EN,,0,0,0,,The dictionary is the set of things I've already figured out that I have memorized or learned.\nDialogue: 0,0:44:30.54,0:44:34.41,EN,,0,0,0,,And I am going to make a new dictionary, which is extended from the original one\nDialogue: 0,0:44:35.12,0:44:38.35,EN,,0,0,0,,by having that pattern variable have a value with the new dictionary.\nDialogue: 0,0:44:39.98,0:44:43.73,EN,,0,0,0,,AUDIENCE: I guess what I don't understand is why can't the substitution be made right as soon as you find--\nDialogue: 0,0:44:43.73,0:44:44.80,EN,,0,0,0,,PROFESSOR: How do I know what I'm going to substitute?\nDialogue: 0,0:44:44.81,0:44:46.62,EN,,0,0,0,,I don't know anything about this skeleton.\nDialogue: 0,0:44:47.58,0:44:49.66,EN,,0,0,0,,This pattern, this matcher is an independent unit.\nDialogue: 0,0:44:49.66,0:44:51.00,EN,,0,0,0,,AUDIENCE: Oh, I see. OK.\nDialogue: 0,0:44:51.00,0:44:51.50,EN,,0,0,0,,PROFESSOR: Right?\nDialogue: 0,0:44:51.50,0:44:51.90,EN,,0,0,0,,AUDIENCE: Yeah.\nDialogue: 0,0:44:51.90,0:44:57.23,EN,,0,0,0,,PROFESSOR: I take the matcher. I apply the matcher. If it matches, then it was worth doing instantiation.\nDialogue: 0,0:44:58.20,0:44:59.50,EN,,0,0,0,,AUDIENCE: OK, good.\nDialogue: 0,0:45:00.54,0:45:03.88,EN,,0,0,0,,AUDIENCE: Can you just do that answer again using that example on the board?\nDialogue: 0,0:45:04.89,0:45:06.93,EN,,0,0,0,,You know, what you just passed back to the matcher.\nDialogue: 0,0:45:06.93,0:45:08.00,EN,,0,0,0,,PROFESSOR: Oh yes. OK, yes.\nDialogue: 0,0:45:08.26,0:45:09.74,EN,,0,0,0,,You're looking at this example.\nDialogue: 0,0:45:10.67,0:45:15.45,EN,,0,0,0,,At this point when I'm traversing this structure, I get to here: x.\nDialogue: 0,0:45:16.67,0:45:20.54,EN,,0,0,0,,I have some dictionary, presumably an empty dictionary at this point if this is the whole expression.\nDialogue: 0,0:45:21.56,0:45:25.36,EN,,0,0,0,,So I have an empty dictionary, and I've matched x against 3.\nDialogue: 0,0:45:26.62,0:45:33.60,EN,,0,0,0,,So now, after this point,the dictionary contains x is 3, OK?\nDialogue: 0,0:45:33.64,0:45:36.09,EN,,0,0,0,,Now, I continue walking along here. I see y.\nDialogue: 0,0:45:36.89,0:45:39.20,EN,,0,0,0,,Now, this is a particular x, a pattern x.\nDialogue: 0,0:45:39.79,0:45:41.37,EN,,0,0,0,,I see y, a pattern y.\nDialogue: 0,0:45:42.17,0:45:47.74,EN,,0,0,0,,The dictionary says, oh yes, the pattern y is the symbol x\nDialogue: 0,0:45:48.99,0:45:51.20,EN,,0,0,0,,because I've gota match there.\nDialogue: 0,0:45:52.43,0:45:54.52,EN,,0,0,0,,So the dictionary now contains at this point two entries.\nDialogue: 0,0:45:55.45,0:45:59.90,EN,,0,0,0,,The pattern x is 3, and the pattern y is the expression x.\nDialogue: 0,0:46:01.95,0:46:04.11,EN,,0,0,0,,Now, I get that, I can walk along further.\nDialogue: 0,0:46:04.23,0:46:07.45,EN,,0,0,0,,I say, oh, pattern y also wants to be 4.\nDialogue: 0,0:46:08.06,0:46:10.65,EN,,0,0,0,,But that isn't possible, producing a failure.\nDialogue: 0,0:46:14.30,0:46:15.48,EN,,0,0,0,,Thank you. Let's take a break.\nDialogue: 0,0:46:16.76,0:46:25.02,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:46:25.07,0:46:27.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:46:27.47,0:46:30.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:46:48.19,0:46:54.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:46:55.20,0:46:58.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}Pattern-matching: Rule-based Substitution\nDialogue: 0,0:47:02.38,0:47:05.68,EN,,0,0,0,,OK, you're seeing your first very big and hairy program.\nDialogue: 0,0:47:07.34,0:47:09.90,EN,,0,0,0,,Now, of course, one of the goals of this subject\nDialogue: 0,0:47:09.90,0:47:12.97,EN,,0,0,0,,is to get you to be able to read something like this and not be afraid of it.\nDialogue: 0,0:47:13.76,0:47:16.33,EN,,0,0,0,,This one's only about four pages of code.\nDialogue: 0,0:47:17.08,0:47:19.23,EN,,0,0,0,,By the end of the subject, I hope a 50-page program\nDialogue: 0,0:47:20.27,0:47:21.80,EN,,0,0,0,,will not look particularly frightening.\nDialogue: 0,0:47:22.97,0:47:28.20,EN,,0,0,0,,But I don't expect-- and I don't want you to think that I expect you to be getting it as it's coming out.\nDialogue: 0,0:47:29.20,0:47:31.70,EN,,0,0,0,,You're supposed to feel the flavor of this, OK?\nDialogue: 0,0:47:31.70,0:47:34.83,EN,,0,0,0,,And then you're supposed to think about it because it is a big program.\nDialogue: 0,0:47:35.32,0:47:38.92,EN,,0,0,0,,There's a lot of stuff inside this program.\nDialogue: 0,0:47:41.24,0:47:46.03,EN,,0,0,0,,Now, I've told you about the language we're implementing, the pattern match substitution language.\nDialogue: 0,0:47:46.81,0:47:47.64,EN,,0,0,0,,I showed you some rules.\nDialogue: 0,0:47:48.36,0:47:51.24,EN,,0,0,0,,And I've told you about matching and instantiation,\nDialogue: 0,0:47:51.55,0:47:53.32,EN,,0,0,0,,which are the two halves of how a rule works.\nDialogue: 0,0:47:54.24,0:47:56.35,EN,,0,0,0,,Now we have to understand the control structure\nDialogue: 0,0:47:56.86,0:48:00.32,EN,,0,0,0,,by which the rules are applied to the expressions\nDialogue: 0,0:48:01.08,0:48:03.84,EN,,0,0,0,,so as to do algebraic simplification.\nDialogue: 0,0:48:06.92,0:48:09.58,EN,,0,0,0,,Now, that's also a big complicated mess.\nDialogue: 0,0:48:12.09,0:48:19.48,EN,,0,0,0,,The problem is that there is a variety of interlocking, interwoven loops, if you will, involved in this.\nDialogue: 0,0:48:20.24,0:48:26.99,EN,,0,0,0,,For one thing, I have to apply-- I have to examine every subexpression of my expression that I'm trying to simplify.\nDialogue: 0,0:48:29.00,0:48:29.93,EN,,0,0,0,,That we know how to do.\nDialogue: 0,0:48:29.93,0:48:36.24,EN,,0,0,0,,It's a car cdr recursion of some sort, or something like that, and some sort of tree walk.\nDialogue: 0,0:48:37.44,0:48:38.59,EN,,0,0,0,,And that's going to be happening.\nDialogue: 0,0:48:38.84,0:48:42.46,EN,,0,0,0,,Now, for every such place, every node that I get to\nDialogue: 0,0:48:43.47,0:48:48.76,EN,,0,0,0,,in doing my traversal of the expression I'm trying to simplify,\nDialogue: 0,0:48:49.20,0:48:51.07,EN,,0,0,0,,I want to apply all of the rules.\nDialogue: 0,0:48:53.42,0:48:55.08,EN,,0,0,0,,Every rule is going to look at every node.\nDialogue: 0,0:48:56.00,0:48:57.92,EN,,0,0,0,,I'm going to rotate the rules around.\nDialogue: 0,0:49:01.66,0:49:05.48,EN,,0,0,0,,Now, either a rule will or will not match.\nDialogue: 0,0:49:07.50,0:49:10.62,EN,,0,0,0,,If the rule does not match, then it's not very interesting.\nDialogue: 0,0:49:12.28,0:49:19.34,EN,,0,0,0,,If the rule does match, then I'm going to replace that node in the expression by an alternate expression.\nDialogue: 0,0:49:20.08,0:49:22.89,EN,,0,0,0,,I'm actually going to make a new expression, which contains--\nDialogue: 0,0:49:23.55,0:49:28.65,EN,,0,0,0,,everything contains that new value, the result of substituting into the skeleton,\nDialogue: 0,0:49:29.21,0:49:31.92,EN,,0,0,0,,instantiating the skeleton for that rule at this level.\nDialogue: 0,0:49:32.72,0:49:37.37,EN,,0,0,0,,But no one knows whether that thing that I instantiated there is in simplified form.\nDialogue: 0,0:49:38.75,0:49:43.82,EN,,0,0,0,,So we're going to have to simplify that, somehow to call the simplifier on the thing that I just constructed.\nDialogue: 0,0:49:46.12,0:49:50.36,EN,,0,0,0,,And then when that's done, then I sort of can build that into the expression I want as my answer.\nDialogue: 0,0:49:51.80,0:49:57.45,EN,,0,0,0,,Now, there is a basic idea here, which I will call a garbage- in, garbage-out simplifier.\nDialogue: 0,0:50:01.47,0:50:02.75,EN,,0,0,0,,It's a kind of recursive simplifier.\nDialogue: 0,0:50:03.58,0:50:08.84,EN,,0,0,0,,And what happens is the way simplify something is that simple objects like variables are simple.\nDialogue: 0,0:50:10.78,0:50:13.28,EN,,0,0,0,,Compound objects, well, I don't know.\nDialogue: 0,0:50:14.09,0:50:16.56,EN,,0,0,0,,What I'm going to do is I'm going to build up from simple objects,\nDialogue: 0,0:50:16.86,0:50:21.23,EN,,0,0,0,,trying to make simple things by assuming that the pieces they're made out of are simple.\nDialogue: 0,0:50:24.60,0:50:25.61,EN,,0,0,0,,That's what's happening here.\nDialogue: 0,0:50:27.82,0:50:33.12,EN,,0,0,0,,Well, now, if we look at the first slide-- no, overhead, overhead.\nDialogue: 0,0:50:33.88,0:50:37.13,EN,,0,0,0,,If we look at the overhead, we see a very complicated program like we saw before for the matcher,\nDialogue: 0,0:50:37.53,0:50:39.95,EN,,0,0,0,,so complicated that you can't read it like that.\nDialogue: 0,0:50:41.92,0:50:43.61,EN,,0,0,0,,I just want you to get the feel of the shape of it,\nDialogue: 0,0:50:44.44,0:50:50.01,EN,,0,0,0,,and the shape of it is that this program has various subprograms in it.\nDialogue: 0,0:50:52.11,0:50:57.56,EN,,0,0,0,,One of them--this part is the part for traversing the expression,\nDialogue: 0,0:50:58.97,0:51:01.36,EN,,0,0,0,,and this part is the part for trying rules.\nDialogue: 0,0:51:02.52,0:51:05.60,EN,,0,0,0,,Now, of course, we can look at that in some more detail.\nDialogue: 0,0:51:06.89,0:51:11.80,EN,,0,0,0,,Let's look at--let's look at the first transparency, right?\nDialogue: 0,0:51:13.40,0:51:17.36,EN,,0,0,0,,The simplifier is made out of several parts.\nDialogue: 0,0:51:17.96,0:51:22.92,EN,,0,0,0,,Now, remember at the very beginning, the simplifier is the thing which takes a rules-- a set of rules\nDialogue: 0,0:51:23.92,0:51:27.20,EN,,0,0,0,,and produces a program which will simplify it relative to them.\nDialogue: 0,0:51:30.04,0:51:32.60,EN,,0,0,0,,So here we have our simplifier.\nDialogue: 0,0:51:33.48,0:51:34.81,EN,,0,0,0,,It takes a rule set.\nDialogue: 0,0:51:36.16,0:51:38.68,EN,,0,0,0,,And in the context where that rule set is defined,\nDialogue: 0,0:51:39.24,0:51:41.48,EN,,0,0,0,,there are various other definitions that are done here.\nDialogue: 0,0:51:42.33,0:51:46.20,EN,,0,0,0,,And then the result of this simplifier procedure is,\nDialogue: 0,0:51:46.41,0:51:50.80,EN,,0,0,0,,in fact, one of the procedures that was defined. Simplify-exp.\nDialogue: 0,0:51:52.46,0:51:57.71,EN,,0,0,0,,What I'm returning as the value of calling the simplifier on a set of rules\nDialogue: 0,0:51:58.17,0:52:03.21,EN,,0,0,0,,is a procedure the simplify exp procedure, which is defined in that context,\nDialogue: 0,0:52:05.23,0:52:08.83,EN,,0,0,0,,which is a simplification procedure appropriate for using those set of rules.\nDialogue: 0,0:52:15.04,0:52:15.96,EN,,0,0,0,,That's what I have there.\nDialogue: 0,0:52:17.45,0:52:21.79,EN,,0,0,0,,Now, the first two of these procedures, this one and this one,\nDialogue: 0,0:52:22.48,0:52:25.74,EN,,0,0,0,,are together going to be the recursive traversal of an expression.\nDialogue: 0,0:52:26.97,0:52:30.20,EN,,0,0,0,,This one is the general simplification for any expression,\nDialogue: 0,0:52:30.94,0:52:33.23,EN,,0,0,0,,and this is the thing which simplifies a list of parts of an expression.\nDialogue: 0,0:52:35.53,0:52:36.08,EN,,0,0,0,,Nothing more.\nDialogue: 0,0:52:37.04,0:52:39.90,EN,,0,0,0,,For each of those, we're going to do something complicated, which involves trying the rules.\nDialogue: 0,0:52:40.32,0:52:41.71,EN,,0,0,0,,Now, we should look at the various parts.\nDialogue: 0,0:52:45.76,0:52:48.08,EN,,0,0,0,,Well let's look first at the recursive traversal of an expression.\nDialogue: 0,0:52:48.57,0:52:51.68,EN,,0,0,0,,And this is done in a sort of simple way.\nDialogue: 0,0:52:54.28,0:52:57.93,EN,,0,0,0,,This is a little nest of recursive procedures.\nDialogue: 0,0:52:59.42,0:53:01.77,EN,,0,0,0,,And what we have here are two procedures--\nDialogue: 0,0:53:02.59,0:53:05.20,EN,,0,0,0,,one for simplifying an expression,\nDialogue: 0,0:53:06.11,0:53:08.16,EN,,0,0,0,,and one for simplifying parts of an expression.\nDialogue: 0,0:53:09.44,0:53:10.97,EN,,0,0,0,,And the way this works is very simple.\nDialogue: 0,0:53:12.12,0:53:16.86,EN,,0,0,0,,If the expression I'm trying to simplify is a compound expression,\nDialogue: 0,0:53:17.04,0:53:18.32,EN,,0,0,0,,I'm going to simplify all the parts of it.\nDialogue: 0,0:53:19.95,0:53:22.32,EN,,0,0,0,,And that's calling--that procedure, simplify parts,\nDialogue: 0,0:53:22.33,0:53:25.74,EN,,0,0,0,,is going to make up a new expression with all the parts simplified,\nDialogue: 0,0:53:26.00,0:53:28.64,EN,,0,0,0,,which I'm then going to try the rules on over here.\nDialogue: 0,0:53:30.86,0:53:34.22,EN,,0,0,0,,If it turns out that the expression is not compound, if it's simple,\nDialogue: 0,0:53:34.76,0:53:37.13,EN,,0,0,0,,like just a symbol or something like pi,\nDialogue: 0,0:53:38.16,0:53:39.79,EN,,0,0,0,,then in any case, I'm going to try the rules on it\nDialogue: 0,0:53:40.03,0:53:47.56,EN,,0,0,0,,because it might be that I want in my set of rules to expand pi to 3.14159265358979,dot, dot, dot.\nDialogue: 0,0:53:48.46,0:53:49.08,EN,,0,0,0,,But I may not.\nDialogue: 0,0:53:50.11,0:53:51.52,EN,,0,0,0,,But there is no reason not to do it.\nDialogue: 0,0:53:52.75,0:53:57.53,EN,,0,0,0,,Now, if I want to simplify the parts, well, that's easy too.\nDialogue: 0,0:53:58.99,0:54:02.88,EN,,0,0,0,,Either the expression is an empty one, there's no more parts,\nDialogue: 0,0:54:03.71,0:54:05.08,EN,,0,0,0,,in which case I have the empty expression.\nDialogue: 0,0:54:05.72,0:54:10.52,EN,,0,0,0,,Otherwise, I'm going to make a new expression by cons,\nDialogue: 0,0:54:11.21,0:54:14.27,EN,,0,0,0,,which is the result of simplifying the first part of the expression, the car,\nDialogue: 0,0:54:15.42,0:54:17.39,EN,,0,0,0,,and simplifying the rest of the expression, which is the cdr.\nDialogue: 0,0:54:21.08,0:54:23.88,EN,,0,0,0,,Now, the reason why I'm showing you this sort of stuff this way\nDialogue: 0,0:54:24.88,0:54:30.12,EN,,0,0,0,,is because I want you get the feeling for the various patterns that are very important when writing programs.\nDialogue: 0,0:54:32.20,0:54:34.00,EN,,0,0,0,,And this could be written a different way.\nDialogue: 0,0:54:34.00,0:54:36.99,EN,,0,0,0,,There's another way to write simplified expressions so there would be only one of them.\nDialogue: 0,0:54:37.72,0:54:39.63,EN,,0,0,0,,There would only be one little procedure here.\nDialogue: 0,0:54:39.63,0:54:42.36,EN,,0,0,0,,Let me just write that on the blackboard to give you a feeling for that.\nDialogue: 0,0:54:49.71,0:54:51.90,EN,,0,0,0,,This is in another idiom, if you will.\nDialogue: 0,0:54:59.30,0:55:03.13,EN,,0,0,0,,To simplify an expression called exp, what am I going to do?\nDialogue: 0,0:55:03.21,0:55:10.14,EN,,0,0,0,,I'm going to try the rules on the following situation.\nDialogue: 0,0:55:11.12,0:55:15.72,EN,,0,0,0,,If-- on the following expression-- compound, just like we had before.\nDialogue: 0,0:55:21.52,0:55:24.27,EN,,0,0,0,,If the expression is compound, well, what am I going to do?\nDialogue: 0,0:55:24.53,0:55:25.40,EN,,0,0,0,,I'm going to simplify all the parts.\nDialogue: 0,0:55:26.01,0:55:27.80,EN,,0,0,0,,But I already have a cdr recursion,\nDialogue: 0,0:55:30.25,0:55:33.18,EN,,0,0,0,,common pattern of usage, which has been captured as a high-order procedure.\nDialogue: 0,0:55:34.09,0:55:34.46,EN,,0,0,0,,It's called map.\nDialogue: 0,0:55:36.08,0:55:36.88,EN,,0,0,0,,So I'll just write that here.\nDialogue: 0,0:55:37.16,0:55:48.03,EN,,0,0,0,,Map simplify the expression, all the parts of the expression.\nDialogue: 0,0:55:49.00,0:55:54.59,EN,,0,0,0,,This says apply the simplification operation, which is this one, every part of the expression,\nDialogue: 0,0:55:55.34,0:55:57.34,EN,,0,0,0,,and then that cons those up into a list.\nDialogue: 0,0:56:00.92,0:56:04.38,EN,,0,0,0,,It's every element of the list which the expression is assumed to be made out of,\nDialogue: 0,0:56:05.45,0:56:08.23,EN,,0,0,0,,and otherwise, I have the expression.\nDialogue: 0,0:56:09.05,0:56:12.36,EN,,0,0,0,,So I don't need the helper procedure, simplify parts,\nDialogue: 0,0:56:12.64,0:56:13.48,EN,,0,0,0,,because that's really this.\nDialogue: 0,0:56:15.47,0:56:17.05,EN,,0,0,0,,So sometimes, you just write it this way.\nDialogue: 0,0:56:17.84,0:56:18.70,EN,,0,0,0,,It doesn't matter very much.\nDialogue: 0,0:56:21.16,0:56:26.27,EN,,0,0,0,,Well, now let's take a look at-- let's just look at how you try rules.\nDialogue: 0,0:56:27.70,0:56:31.60,EN,,0,0,0,,If you look at this slide, we see this is a complicated mess also.\nDialogue: 0,0:56:33.68,0:56:35.28,EN,,0,0,0,,I'm trying rules on an expression.\nDialogue: 0,0:56:36.36,0:56:39.96,EN,,0,0,0,,It turns out the expression I'm trying it on is some subexpression now of the expression I started with.\nDialogue: 0,0:56:40.43,0:56:43.88,EN,,0,0,0,,Because the thing I just arranged allowed us to try every subexpression.\nDialogue: 0,0:56:46.11,0:56:51.90,EN,,0,0,0,,So now here we're taking in a subexpression of the expression we started with. That's what this is.\nDialogue: 0,0:56:52.49,0:56:57.71,EN,,0,0,0,,And what we're going to define here is a procedure called scan, which is going to try every rule.\nDialogue: 0,0:56:58.72,0:57:00.33,EN,,0,0,0,,And we're going to start it up on the whole set of rules.\nDialogue: 0,0:57:01.92,0:57:07.77,EN,,0,0,0,,This is going to go cdr-ing down the rules, if you will, looking for a rule to apply.\nDialogue: 0,0:57:09.37,0:57:11.96,EN,,0,0,0,,And when it finds one, it'll do the job.\nDialogue: 0,0:57:14.09,0:57:16.41,EN,,0,0,0,,Well, let's take a look at how try rules works.\nDialogue: 0,0:57:17.74,0:57:21.02,EN,,0,0,0,,It's very simple: the scan rules. Scan rules, the way of scanning.\nDialogue: 0,0:57:21.96,0:57:23.26,EN,,0,0,0,,Well, is it so simple?\nDialogue: 0,0:57:23.26,0:57:24.51,EN,,0,0,0,,It's a big program, of course.\nDialogue: 0,0:57:25.55,0:57:28.57,EN,,0,0,0,,We take a bunch of rules, which is a sublist of the list of rules.\nDialogue: 0,0:57:30.75,0:57:35.13,EN,,0,0,0,,We've tried some of them already, and they've not been appropriate, so we get to some here.\nDialogue: 0,0:57:35.87,0:57:36.30,EN,,0,0,0,,next one.\nDialogue: 0,0:57:36.40,0:57:37.63,EN,,0,0,0,,If there are no more rules,\nDialogue: 0,0:57:37.90,0:57:40.84,EN,,0,0,0,,well then, there's nothing I can do with this expression, and it's simplified.\nDialogue: 0,0:57:42.35,0:57:47.26,EN,,0,0,0,,However, if it turns out that there are still rules to be done,\nDialogue: 0,0:57:48.01,0:57:51.58,EN,,0,0,0,,then let's match the pattern of the first rule\nDialogue: 0,0:57:52.20,0:57:55.40,EN,,0,0,0,,against the expression using the empty dictionary to start with\nDialogue: 0,0:57:57.07,0:57:58.84,EN,,0,0,0,,and use that as the dictionary.\nDialogue: 0,0:58:00.32,0:58:03.74,EN,,0,0,0,,If that happens to be a failure, try the rest of the rules.\nDialogue: 0,0:58:06.68,0:58:07.52,EN,,0,0,0,,That's all it says here.\nDialogue: 0,0:58:08.52,0:58:10.33,EN,,0,0,0,,How it says, it says discard that rule.\nDialogue: 0,0:58:11.10,0:58:15.05,EN,,0,0,0,,Otherwise, well, I'm going to get the skeleton of the first rule,\nDialogue: 0,0:58:15.34,0:58:17.40,EN,,0,0,0,,instantiate that relative to the dictionary,\nDialogue: 0,0:58:17.93,0:58:20.80,EN,,0,0,0,,and simplify the result, and that's the expression I want.\nDialogue: 0,0:58:24.20,0:58:25.96,EN,,0,0,0,,So although that was a complicated program,\nDialogue: 0,0:58:26.25,0:58:28.72,EN,,0,0,0,,every complicated program is made out of a lot of simple pieces.\nDialogue: 0,0:58:29.77,0:58:33.12,EN,,0,0,0,,Now, the pattern of recursions here is very complicated.\nDialogue: 0,0:58:34.78,0:58:36.52,EN,,0,0,0,,And one of the most important things is not to think about that.\nDialogue: 0,0:58:38.67,0:58:41.80,EN,,0,0,0,,If you try to think about the actual pattern by which this does something,\nDialogue: 0,0:58:42.06,0:58:42.97,EN,,0,0,0,,you're going to get very confused.\nDialogue: 0,0:58:45.31,0:58:45.71,EN,,0,0,0,,I would.\nDialogue: 0,0:58:47.04,0:58:50.17,EN,,0,0,0,,This is not a matter. you can do this with practice.\nDialogue: 0,0:58:51.52,0:58:52.46,EN,,0,0,0,,These patterns are hard.\nDialogue: 0,0:58:54.17,0:58:55.42,EN,,0,0,0,,But you don't have to think about it.\nDialogue: 0,0:58:55.83,0:58:59.72,EN,,0,0,0,,The key to this-- it's very good programming and very good design--\nDialogue: 0,0:58:59.74,0:59:00.97,EN,,0,0,0,,is to know what not to think about.\nDialogue: 0,0:59:03.05,0:59:06.06,EN,,0,0,0,,The fact is, going back to this slide,\nDialogue: 0,0:59:06.92,0:59:08.01,EN,,0,0,0,,I don't have to think about it\nDialogue: 0,0:59:08.54,0:59:13.83,EN,,0,0,0,,because I have specifications in my mind for what simplify x does.\nDialogue: 0,0:59:14.00,0:59:15.24,EN,,0,0,0,,I don't have to know how it does it.\nDialogue: 0,0:59:17.08,0:59:21.24,EN,,0,0,0,,And it may, in fact, call scan somehow through try rules, which it does.\nDialogue: 0,0:59:22.24,0:59:24.09,EN,,0,0,0,,And somehow, I've got another recursion going on here.\nDialogue: 0,0:59:24.33,0:59:25.69,EN,,0,0,0,,But since I know that simplify exp\nDialogue: 0,0:59:26.84,0:59:30.40,EN,,0,0,0,,is assumed by wishful thinking to produce the simplified result,\nDialogue: 0,0:59:31.61,0:59:32.99,EN,,0,0,0,,then I don't have to think about it anymore.\nDialogue: 0,0:59:33.43,0:59:34.83,EN,,0,0,0,,I've used it.\nDialogue: 0,0:59:35.07,0:59:36.43,EN,,0,0,0,,I've used it in a reasonable way.\nDialogue: 0,0:59:36.43,0:59:37.45,EN,,0,0,0,,I will get a reasonable answer.\nDialogue: 0,0:59:39.95,0:59:42.57,EN,,0,0,0,,And you have to learn how to program that way-- with abandon.\nDialogue: 0,0:59:47.56,0:59:49.05,EN,,0,0,0,,Well, there's very little left of this thing.\nDialogue: 0,0:59:50.40,0:59:54.46,EN,,0,0,0,,All there is left is a few details associated with what a dictionary is.\nDialogue: 0,0:59:55.08,0:59:58.32,EN,,0,0,0,,And those of you who've been itching to know what a dictionary is,\nDialogue: 0,0:59:58.70,1:00:01.82,EN,,0,0,0,,well, I will flip it up and not tell you anything about it.\nDialogue: 0,1:00:04.14,1:00:05.20,EN,,0,0,0,,Dictionaries are easy.\nDialogue: 0,1:00:06.01,1:00:09.84,EN,,0,0,0,,It's represented in terms of something else called an A list,\nDialogue: 0,1:00:10.65,1:00:16.04,EN,,0,0,0,,which is a particular pattern of usage for making tables in lists.\nDialogue: 0,1:00:16.50,1:00:20.17,EN,,0,0,0,,They're easy. They're made out of pairs, as was asked a bit ago.\nDialogue: 0,1:00:21.21,1:00:24.62,EN,,0,0,0,,And there are special procedures for dealing with such things called assq,\nDialogue: 0,1:00:24.94,1:00:26.36,EN,,0,0,0,,and you can find them in manuals.\nDialogue: 0,1:00:27.04,1:00:28.59,EN,,0,0,0,,I'm not terribly excited about it.\nDialogue: 0,1:00:28.83,1:00:31.21,EN,,0,0,0,,The only interesting thing here in extend dictionary\nDialogue: 0,1:00:31.48,1:00:36.94,EN,,0,0,0,,is I have to extend the dictionary with a pattern, a datum, and a dictionary.\nDialogue: 0,1:00:37.42,1:00:42.38,EN,,0,0,0,,I wish that, this pattern is, in fact, at this point a pattern variable.\nDialogue: 0,1:00:43.74,1:00:47.53,EN,,0,0,0,,And what do I want to do? I want to pull out the name of that pattern variable\nDialogue: 0,1:00:48.16,1:00:49.42,EN,,0,0,0,,the pattern variable name,\nDialogue: 0,1:00:50.44,1:00:53.71,EN,,0,0,0,,and I'm going to look up in the dictionary and see if it already has a value.\nDialogue: 0,1:00:53.79,1:00:56.41,EN,,0,0,0,,If not, I'm going to add a new one in.\nDialogue: 0,1:00:56.92,1:00:59.23,EN,,0,0,0,,If it does have one, if it has a value,\nDialogue: 0,1:00:59.60,1:01:03.18,EN,,0,0,0,,then it had better be equal to the one that was already stored away.\nDialogue: 0,1:01:03.88,1:01:06.54,EN,,0,0,0,,And if that's the case, the dictionary is what I expected it to be.\nDialogue: 0,1:01:06.89,1:01:09.15,EN,,0,0,0,,Otherwise, I fail.\nDialogue: 0,1:01:12.08,1:01:12.89,EN,,0,0,0,,So that's easy, too.\nDialogue: 0,1:01:13.66,1:01:16.68,EN,,0,0,0,,If you open up any program, you're going to find inside of it lots of little pieces,\nDialogue: 0,1:01:17.18,1:01:18.30,EN,,0,0,0,,all of which are easy.\nDialogue: 0,1:01:20.04,1:01:21.29,EN,,0,0,0,,So at this point, I suppose,\nDialogue: 0,1:01:21.60,1:01:25.68,EN,,0,0,0,,I've just told you some million-dollar valuable information.\nDialogue: 0,1:01:28.41,1:01:30.96,EN,,0,0,0,,And I suppose at this point we're pretty much done with this program.\nDialogue: 0,1:01:31.85,1:01:32.72,EN,,0,0,0,,I'd like to ask about questions.\nDialogue: 0,1:01:34.27,1:01:38.16,EN,,0,0,0,,AUDIENCE: Yes, can you give me the words that describe the specification for a simplified expression?\nDialogue: 0,1:01:38.72,1:01:39.02,EN,,0,0,0,,PROFESSOR: Sure.\nDialogue: 0,1:01:39.85,1:01:44.33,EN,,0,0,0,,A simplified expression takes an expression and produces a simplified expression.\nDialogue: 0,1:01:45.28,1:01:45.77,EN,,0,0,0,,That's it, OK?\nDialogue: 0,1:01:48.11,1:01:50.27,EN,,0,0,0,,How it does it is very easy.\nDialogue: 0,1:01:51.60,1:01:56.09,EN,,0,0,0,,In compound expressions, all the pieces are simplified, and then the rules are tried on the result.\nDialogue: 0,1:01:56.89,1:01:58.49,EN,,0,0,0,,And for simple expressions, you just try all the rules.\nDialogue: 0,1:01:59.52,1:02:02.11,EN,,0,0,0,,AUDIENCE: So an expression is simplified by virtue of the rules?\nDialogue: 0,1:02:02.76,1:02:03.58,EN,,0,0,0,,PROFESSOR: That's, of course, true.\nDialogue: 0,1:02:03.76,1:02:03.90,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,1:02:04.06,1:02:07.13,EN,,0,0,0,,PROFESSOR: And the way this works is that simplified expression, as you see here,\nDialogue: 0,1:02:08.35,1:02:11.64,EN,,0,0,0,,what it does is it breaks the expression down into the smallest pieces,\nDialogue: 0,1:02:12.60,1:02:17.29,EN,,0,0,0,,simplifies building up from the bottom using the rules to be the simplifier,\nDialogue: 0,1:02:18.30,1:02:22.48,EN,,0,0,0,,to do the manipulations, and constructs a new expression as the result.\nDialogue: 0,1:02:24.28,1:02:29.44,EN,,0,0,0,,Eventually, one of things you see is that the rules themselves, the try rules,\nDialogue: 0,1:02:29.70,1:02:35.50,EN,,0,0,0,,call a simplified expression on the results when it changes something, the results of a match.\nDialogue: 0,1:02:35.80,1:02:40.64,EN,,0,0,0,,I'm sorry, the results of instantiation of a skeleton for a rule that has matched.\nDialogue: 0,1:02:42.00,1:02:47.36,EN,,0,0,0,,So the spec of a simplified expression is that any expression you put into it comes out simplified according to those rules.\nDialogue: 0,1:02:49.84,1:02:50.76,EN,,0,0,0,,Thank you. Let's take a break.\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:06.19,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:06.45,0:00:14.22,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}字幕&时间轴\\N邓雄飞 & S.Michael\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}后期&特效\\N邓雄飞\\N(Dysprosium)\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:14.83,0:00:18.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}模式匹配：基于规则的代换\\N Pattern Matching: Rule-based Substitution\nDialogue: 0,0:00:24.34,0:00:29.34,Default,,0,0,0,,教授：昨天 我们学习了一些符号操作\nDialogue: 0,0:00:29.92,0:00:35.12,Default,,0,0,0,,编写了一个非常典型的程序\nDialogue: 0,0:00:35.15,0:00:38.97,Default,,0,0,0,,来实现教材中的微积分规则\nDialogue: 0,0:00:39.61,0:00:44.59,Default,,0,0,0,,在这张幻灯片上\nDialogue: 0,0:00:44.96,0:00:48.81,Default,,0,0,0,,有一些从书中摘录的微积分规则\nDialogue: 0,0:00:49.47,0:00:54.62,Default,,0,0,0,,我们要把这些规则转化成计算机语言\nDialogue: 0,0:00:55.14,0:00:58.85,Default,,0,0,0,,当然 这种策略很有趣\nDialogue: 0,0:00:59.36,0:01:04.80,Default,,0,0,0,,但是我们为什么要把它们翻译成计算机语言呢？\nDialogue: 0,0:01:05.00,0:01:06.27,Default,,0,0,0,,我的意思是---\nDialogue: 0,0:01:06.62,0:01:11.02,Default,,0,0,0,,我们昨天写的程序非常典型\nDialogue: 0,0:01:11.21,0:01:15.98,Default,,0,0,0,,它是一个按表达式类型做分派的分情况分析语句\nDialogue: 0,0:01:16.38,0:01:18.48,Default,,0,0,0,,规则就是这样的\nDialogue: 0,0:01:19.68,0:01:21.55,Default,,0,0,0,,这里的规则是说:\nDialogue: 0,0:01:21.74,0:01:25.48,Default,,0,0,0,,我们考察的表达式如果是---\nDialogue: 0,0:01:25.48,0:01:29.42,Default,,0,0,0,,如果是常量 就做一些事情\nDialogue: 0,0:01:29.42,0:01:31.37,Default,,0,0,0,,如果是变量 就做另一件事情\nDialogue: 0,0:01:31.60,0:01:35.56,Default,,0,0,0,,如果它是常量乘以变量 就做另外的事 等等\nDialogue: 0,0:01:36.00,0:01:38.96,Default,,0,0,0,,这是一种按类型的分派\nDialogue: 0,0:01:41.40,0:01:45.16,Default,,0,0,0,,那么 既然它有如此典型的行为和结构\nDialogue: 0,0:01:45.95,0:01:49.53,Default,,0,0,0,,有没有其它方式把这个过程写得更加清晰？\nDialogue: 0,0:01:50.83,0:01:53.45,Default,,0,0,0,,首先要解决的是 这些规则是什么?\nDialogue: 0,0:01:55.56,0:01:58.50,Default,,0,0,0,,我们来好好想一下 规则有好几个部分\nDialogue: 0,0:01:58.94,0:02:02.35,Default,,0,0,0,,如果仔细观察这些规则\nDialogue: 0,0:02:03.71,0:02:04.99,Default,,0,0,0,,你就会发现\nDialogue: 0,0:02:05.12,0:02:09.69,Default,,0,0,0,,这些规则都有左右两部分\nDialogue: 0,0:02:10.36,0:02:14.36,Default,,0,0,0,,每一个规则都有左边部分和右边部分\nDialogue: 0,0:02:15.15,0:02:20.30,Default,,0,0,0,,左边部分用来与对被求导表达式做比较\nDialogue: 0,0:02:21.52,0:02:25.10,Default,,0,0,0,,右边部分用于替换原表达式\nDialogue: 0,0:02:28.49,0:02:33.10,Default,,0,0,0,,这张纸上的所有规则都可以描述成这样——\nDialogue: 0,0:02:36.51,0:02:38.06,Default,,0,0,0,,我们有许多模式\nDialogue: 0,0:02:41.48,0:02:48.30,Default,,0,0,0,,有时候 给定一个模式 我们需要为其生成一个骨架\nDialogue: 0,0:02:51.88,0:02:52.81,Default,,0,0,0,,这就是一个规则\nDialogue: 0,0:02:55.42,0:02:57.13,Default,,0,0,0,,模式是用于匹配的部分\nDialogue: 0,0:02:57.88,0:03:03.26,Default,,0,0,0,,将成功匹配的值代换到骨架里 就得到一个新的表达式\nDialogue: 0,0:03:06.46,0:03:16.32,Default,,0,0,0,,我的意思是：模式是用来匹配原表达式的\nDialogue: 0,0:03:23.72,0:03:28.51,Default,,0,0,0,,应用规则会产生一个新的表达式\nDialogue: 0,0:03:33.61,0:03:34.91,Default,,0,0,0,,我们称之为目标\nDialogue: 0,0:03:38.12,0:03:39.88,Default,,0,0,0,,这是通过骨架的实例化实现的\nDialogue: 0,0:03:41.63,0:03:43.02,Default,,0,0,0,,这个叫做实例化\nDialogue: 0,0:03:50.72,0:03:54.73,Default,,0,0,0,,这就是这些规则所描述的过程\nDialogue: 0,0:03:55.69,0:03:57.26,Default,,0,0,0,,今天我想要做的是\nDialogue: 0,0:03:58.73,0:04:01.08,Default,,0,0,0,,构建一种语言\nDialogue: 0,0:04:02.20,0:04:05.48,Default,,0,0,0,,以及它的解释与执行方法\nDialogue: 0,0:04:05.74,0:04:08.43,Default,,0,0,0,,使得这种语言可以直接表述这些规则\nDialogue: 0,0:04:10.59,0:04:11.58,Default,,0,0,0,,我们将要做的是\nDialogue: 0,0:04:11.58,0:04:17.56,Default,,0,0,0,,与其通过将规则翻译为程序 让计算机理解并执行\nDialogue: 0,0:04:18.38,0:04:21.56,Default,,0,0,0,,这里主要指 Lisp 程序\nDialogue: 0,0:04:22.16,0:04:24.49,Default,,0,0,0,,我们不如让计算机理解我们\nDialogue: 0,0:04:25.48,0:04:29.15,Default,,0,0,0,,我们可以写一些程序让计算机理解这些规则\nDialogue: 0,0:04:30.91,0:04:34.76,Default,,0,0,0,,这又稍微强调了上次的主旨\nDialogue: 0,0:04:35.44,0:04:39.36,Default,,0,0,0,,与其解决一个特定问题 不如解决一类问题\nDialogue: 0,0:04:39.77,0:04:46.72,Default,,0,0,0,,如果我为不同的数学运算写规则\nDialogue: 0,0:04:48.24,0:04:51.39,Default,,0,0,0,,比如简单代数的化简\nDialogue: 0,0:04:51.98,0:04:55.48,Default,,0,0,0,,或者三角函数运算\nDialogue: 0,0:04:56.09,0:05:01.16,Default,,0,0,0,,如果按照昨天的方法 我就得重新写个不同的程序\nDialogue: 0,0:05:01.16,0:05:05.42,Default,,0,0,0,,与之相反 我把程序中的共有逻辑给封装起来\nDialogue: 0,0:05:06.12,0:05:10.17,Default,,0,0,0,,也就是匹配、实例化等概念 还有控制结构\nDialogue: 0,0:05:10.17,0:05:12.46,Default,,0,0,0,,这都是非常复杂的事情\nDialogue: 0,0:05:13.16,0:05:18.46,Default,,0,0,0,,我想把它们从规则中分开 并封装\nDialogue: 0,0:05:20.06,0:05:22.60,Default,,0,0,0,,首先让我们看一下表示法\nDialogue: 0,0:05:22.62,0:05:24.09,Default,,0,0,0,,请大家看投影仪上的幻灯片\nDialogue: 0,0:05:24.67,0:05:25.60,Default,,0,0,0,,已经在这里了\nDialogue: 0,0:05:26.25,0:05:32.27,Default,,0,0,0,,我想要把求导的计算规则\nDialogue: 0,0:05:33.71,0:05:37.15,Default,,0,0,0,,表示为我这里写的一种简单语言\nDialogue: 0,0:05:38.11,0:05:43.29,Default,,0,0,0,,我会尽量避免去考虑语法\nDialogue: 0,0:05:44.28,0:05:49.28,Default,,0,0,0,,美化它很容易 虽然这个确实挺丑 但我并不关心\nDialogue: 0,0:05:49.30,0:05:56.41,Default,,0,0,0,,这确实不能像dx/dt那样表示\nDialogue: 0,0:05:56.76,0:05:58.12,Default,,0,0,0,,但这并不重要\nDialogue: 0,0:05:58.88,0:06:00.62,Default,,0,0,0,,这是一个偶然现象\nDialogue: 0,0:06:01.00,0:06:04.44,Default,,0,0,0,,这里 我只关心规则的结构\nDialogue: 0,0:06:04.83,0:06:11.70,Default,,0,0,0,,规则的左边部分代表了我想要匹配的求导表达式\nDialogue: 0,0:06:11.80,0:06:13.56,Default,,0,0,0,,这个表示是说\nDialogue: 0,0:06:13.60,0:06:18.32,Default,,0,0,0,,一个匹配常量的模式变量c\nDialogue: 0,0:06:18.84,0:06:21.20,Default,,0,0,0,,关于匹配任意表达式的模式变量v求导\nDialogue: 0,0:06:23.08,0:06:25.55,Default,,0,0,0,,我们在右边部分得到的是0\nDialogue: 0,0:06:26.00,0:06:28.06,Default,,0,0,0,,这就代表了一个规则\nDialogue: 0,0:06:29.26,0:06:34.04,Default,,0,0,0,,下一条规则是 匹配变量的模式变量v\nDialogue: 0,0:06:34.22,0:06:37.74,Default,,0,0,0,,对同一个模式变量求导 得到的结果是1\nDialogue: 0,0:06:38.60,0:06:42.17,Default,,0,0,0,,然而 如果一个匹配变量的模式变量u\nDialogue: 0,0:06:42.41,0:06:44.84,Default,,0,0,0,,关于另一个模式变量v求导\nDialogue: 0,0:06:45.39,0:06:47.05,Default,,0,0,0,,那么 结果就是0\nDialogue: 0,0:06:47.84,0:06:52.17,Default,,0,0,0,,我想让大家看一下 这些规则是如何组织在一起的\nDialogue: 0,0:06:52.51,0:06:54.30,Default,,0,0,0,,比如说 在这里\nDialogue: 0,0:06:54.73,0:07:01.90,Default,,0,0,0,,我们要求表达式x1、x2之和的导数\nDialogue: 0,0:07:01.90,0:07:05.85,Default,,0,0,0,,在我们创造的这个语言中\nDialogue: 0,0:07:06.88,0:07:08.62,Default,,0,0,0,,以问号开头的叫模式变量\nDialogue: 0,0:07:08.93,0:07:14.93,Default,,0,0,0,,我们就像这样来构建这些用来匹配的模式变量\nDialogue: 0,0:07:14.93,0:07:20.33,Default,,0,0,0,,这里 表达式x1加上表达式x2\nDialogue: 0,0:07:20.33,0:07:26.70,Default,,0,0,0,,对变量v求导的结果等于右边这里的式子\nDialogue: 0,0:07:26.70,0:07:32.76,Default,,0,0,0,,右边的式子是一个骨架 表示表达式X1关于变量v求导\nDialogue: 0,0:07:33.82,0:07:37.10,Default,,0,0,0,,加上表达式X2对变量v求导的和\nDialogue: 0,0:07:37.60,0:07:42.38,Default,,0,0,0,,这里的冒号表示要代换的对象\nDialogue: 0,0:07:43.63,0:07:47.23,Default,,0,0,0,,我们将它们称作“骨架求值”\nDialogue: 0,0:07:48.51,0:07:53.07,Default,,0,0,0,,让我在黑板上写一些语法\nDialogue: 0,0:07:53.23,0:07:55.56,Default,,0,0,0,,这样就能知道 在我们这门规则语言中会发生什么\nDialogue: 0,0:07:56.68,0:07:59.88,Default,,0,0,0,,首先我们要处理模式匹配问题\nDialogue: 0,0:08:06.04,0:08:13.12,Default,,0,0,0,,第一条规则是 形如foo这样的符号与其自身匹配\nDialogue: 0,0:08:23.52,0:08:31.34,Default,,0,0,0,,形如(f a b)的表达式 可以匹配这样的表\nDialogue: 0,0:08:36.30,0:08:57.02,Default,,0,0,0,,表的首元素是f、第二个元素是a、第三个元素是b\nDialogue: 0,0:08:58.62,0:09:06.99,Default,,0,0,0,,另外 模式中可能还有形如(? x)这样的规则\nDialogue: 0,0:09:08.57,0:09:18.67,Default,,0,0,0,,这个规则可以匹配任意表达式 并将其称为x\nDialogue: 0,0:09:25.45,0:09:29.98,Default,,0,0,0,,(?c x) 只匹配常量\nDialogue: 0,0:09:31.50,0:09:40.96,Default,,0,0,0,,并将匹配的常量记作x\nDialogue: 0,0:09:44.56,0:09:57.07,Default,,0,0,0,,(?v x)匹配变量 并将匹配的变量记作x\nDialogue: 0,0:10:01.66,0:10:03.80,Default,,0,0,0,,这就是我们正在构建的语言\nDialogue: 0,0:10:04.19,0:10:09.40,Default,,0,0,0,,两个对象的比较是基于元素与元素间的比较\nDialogue: 0,0:10:10.25,0:10:15.85,Default,,0,0,0,,模式中的元素可以包含这些语法变量、模式变量\nDialogue: 0,0:10:17.07,0:10:20.43,Default,,0,0,0,,它们可以用来匹配任意对象\nDialogue: 0,0:10:22.12,0:10:29.28,Default,,0,0,0,,这样 我就可以用x作为名字取得被匹配对象的值\nDialogue: 0,0:10:31.05,0:10:37.55,Default,,0,0,0,,现在 当我们为实例化准备骨架的时候\nDialogue: 0,0:10:39.50,0:10:41.40,Default,,0,0,0,,我们可能有这样的东西\nDialogue: 0,0:10:42.27,0:10:46.33,Default,,0,0,0,,符号foo实例化为它本身\nDialogue: 0,0:10:55.08,0:11:05.92,Default,,0,0,0,,形如(f a b)这样的表 实例化为\nDialogue: 0,0:11:06.36,0:11:14.75,Default,,0,0,0,,实例化为一个三元素表\nDialogue: 0,0:11:15.55,0:11:33.37,Default,,0,0,0,,其元素分别为f、a、b各自实例化后的结果\nDialogue: 0,0:11:36.35,0:11:54.27,Default,,0,0,0,,(: x) 会被实例化为x的值--也就是被匹配的模式\nDialogue: 0,0:12:03.05,0:12:10.08,Default,,0,0,0,,回头看看这里的幻灯片 我们发现这些都是对象\nDialogue: 0,0:12:10.78,0:12:16.06,Default,,0,0,0,,我们看到 这是一个用来匹配常量的模式变量\nDialogue: 0,0:12:16.56,0:12:19.02,Default,,0,0,0,,这是匹配变量的模式变量\nDialogue: 0,0:12:19.39,0:12:21.74,Default,,0,0,0,,这是匹配任意表达式的模式变量\nDialogue: 0,0:12:22.72,0:12:24.92,Default,,0,0,0,,如果我们有了名字一样的两个实例\nDialogue: 0,0:12:25.08,0:12:31.77,Default,,0,0,0,,想这个是被称作v的单变量表达式\nDialogue: 0,0:12:32.86,0:12:36.30,Default,,0,0,0,,关于一个称作v的任意表达式求导\nDialogue: 0,0:12:36.41,0:12:38.01,Default,,0,0,0,,因为这个v出现了两次\nDialogue: 0,0:12:38.65,0:12:41.07,Default,,0,0,0,,我们想约束它们相同\nDialogue: 0,0:12:42.68,0:12:45.00,Default,,0,0,0,,只有它俩完全一致才算是匹配\nDialogue: 0,0:12:45.23,0:12:47.23,Default,,0,0,0,,所以在这里我们在构建一个语言\nDialogue: 0,0:12:47.60,0:12:50.66,Default,,0,0,0,,事实上 这是一件非常好的事情\nDialogue: 0,0:12:50.66,0:12:52.60,Default,,0,0,0,,构建一个语言非常有趣\nDialogue: 0,0:12:52.60,0:12:54.33,Default,,0,0,0,,并且大家一直在做这些\nDialogue: 0,0:12:54.33,0:12:56.89,Default,,0,0,0,,大家做过的真正强大的设计\nDialogue: 0,0:12:57.23,0:13:00.20,Default,,0,0,0,,是构建一个语言来解决这样的问题\nDialogue: 0,0:13:02.06,0:13:05.34,Default,,0,0,0,,我们回头看看这些规则\nDialogue: 0,0:13:05.80,0:13:07.10,Default,,0,0,0,,这就是它们的全部\nDialogue: 0,0:13:07.10,0:13:12.43,Default,,0,0,0,,我们有加法、乘法 就像我们之前看到的一样\nDialogue: 0,0:13:12.43,0:13:17.37,Default,,0,0,0,,x1+x2 关于变量v的导数等于\nDialogue: 0,0:13:17.68,0:13:26.52,Default,,0,0,0,,x2对v求导乘以x1 加上 x1对v求导乘以x2\nDialogue: 0,0:13:27.26,0:13:29.10,Default,,0,0,0,,这是指数运算的求导规则\nDialogue: 0,0:13:29.24,0:13:32.11,Default,,0,0,0,,虽然这里展示完了所有的规则 但还可以按照我们意愿添加\nDialogue: 0,0:13:32.70,0:13:39.10,Default,,0,0,0,,我们在这里 建立了关于求导的规则列表\nDialogue: 0,0:13:40.40,0:13:44.33,Default,,0,0,0,,一旦我们有了这些 我们应该做什么呢？\nDialogue: 0,0:13:45.40,0:13:47.84,Default,,0,0,0,,恩 我将给你们展示最好的思想之一\nDialogue: 0,0:13:48.44,0:13:51.68,Default,,0,0,0,,然后我们将花一整天来鼓捣它\nDialogue: 0,0:13:52.28,0:13:57.37,Default,,0,0,0,,我将向大家展示一个叫做simplifier的程序\nDialogue: 0,0:13:57.82,0:13:59.47,Default,,0,0,0,,一个通用的化简器\nDialogue: 0,0:14:00.09,0:14:17.10,Default,,0,0,0,,我们将求导规则deriv-rules送入simplifier从而产生dsimp\nDialogue: 0,0:14:23.74,0:14:28.75,Default,,0,0,0,,传给simplifier过程一套规则 它会返回给我们一个过程\nDialogue: 0,0:14:29.32,0:14:34.59,Default,,0,0,0,,它根据这些规则对表达式进行化简\nDialogue: 0,0:14:37.39,0:14:43.93,Default,,0,0,0,,因此 这里会返回一个按照你制定的规则所构造的过程\nDialogue: 0,0:14:44.59,0:14:49.56,Default,,0,0,0,,使得在我们进入 Lisp 系统后 在命令提示符后面\nDialogue: 0,0:14:49.88,0:15:03.93,Default,,0,0,0,,输入 (DSIMP '(dd (+ x y) x))\nDialogue: 0,0:15:06.99,0:15:10.97,Default,,0,0,0,,注意这里的引号 因为我们讨论的是表达式的求导\nDialogue: 0,0:15:13.29,0:15:17.76,Default,,0,0,0,,然后我将得到结果 (+ 1 0)\nDialogue: 0,0:15:19.96,0:15:24.60,Default,,0,0,0,,因为 (x+y)' = x' + y'\nDialogue: 0,0:15:24.60,0:15:26.22,Default,,0,0,0,,x'=1\nDialogue: 0,0:15:26.38,0:15:27.82,Default,,0,0,0,,y'=0（关于x求导）\nDialogue: 0,0:15:29.42,0:15:30.46,Default,,0,0,0,,这不是我想要的\nDialogue: 0,0:15:31.18,0:15:34.65,Default,,0,0,0,,我还没有在这里做代数化简\nDialogue: 0,0:15:36.16,0:15:41.53,Default,,0,0,0,,当然一旦我有了这个东西那么我们可以 -- 我们可以看看其它的规则\nDialogue: 0,0:15:41.96,0:15:49.36,Default,,0,0,0,,比如 我们看这张幻灯片\nDialogue: 0,0:15:49.36,0:15:54.12,Default,,0,0,0,,这里是其它的规则 代数操作规则\nDialogue: 0,0:15:56.00,0:15:58.38,Default,,0,0,0,,它们可以用来化简代数表达式\nDialogue: 0,0:15:59.00,0:16:02.06,Default,,0,0,0,,考察一下这些规则\nDialogue: 0,0:16:03.04,0:16:09.20,Default,,0,0,0,,这条规则的左部分是说 某个运算符应用到常量e1和常量e2上\nDialogue: 0,0:16:09.32,0:16:14.51,Default,,0,0,0,,其结果就是求(op e1 e2)的值\nDialogue: 0,0:16:15.88,0:16:21.56,Default,,0,0,0,,或者 当一个运算符应用在任意表达式e1和常量e2上\nDialogue: 0,0:16:21.69,0:16:23.87,Default,,0,0,0,,化简结果会把常量前置\nDialogue: 0,0:16:24.52,0:16:27.68,Default,,0,0,0,,这就变成了((: op) (: e2) (: e1))\nDialogue: 0,0:16:28.59,0:16:30.11,Default,,0,0,0,,为什么要这么做？我不知道\nDialogue: 0,0:16:30.22,0:16:33.16,Default,,0,0,0,,比如说 如果系统中有除法的话 这就不对\nDialogue: 0,0:16:33.53,0:16:35.31,Default,,0,0,0,,换句话说 规则有漏洞\nDialogue: 0,0:16:36.67,0:16:40.86,Default,,0,0,0,,所以0与任何表达式e的和 等于表达式e\nDialogue: 0,0:16:42.17,0:16:45.31,Default,,0,0,0,,1乘以任何表达式e的结果是表达式e\nDialogue: 0,0:16:46.12,0:16:49.13,Default,,0,0,0,,0乘以任何表达式e的结果是0\nDialogue: 0,0:16:49.33,0:16:52.72,Default,,0,0,0,,我们可以有任意复杂的规则\nDialogue: 0,0:16:53.69,0:16:54.81,Default,,0,0,0,,比如说\nDialogue: 0,0:16:55.36,0:17:01.69,Default,,0,0,0,,常量e1*(常量e2*任意表达式e3)\nDialogue: 0,0:17:02.35,0:17:11.96,Default,,0,0,0,,可以化简为 (e1*e2)*e3\nDialogue: 0,0:17:13.36,0:17:16.76,Default,,0,0,0,,这个规则是说 先把常量组合起来\nDialogue: 0,0:17:16.76,0:17:22.70,Default,,0,0,0,,如果有形如 e1*(e2*e3) 的式子 而且e1 e2都是常量 就先把常量乘起来\nDialogue: 0,0:17:23.84,0:17:25.48,Default,,0,0,0,,你可以根据意愿来构建这些规则\nDialogue: 0,0:17:25.79,0:17:26.94,Default,,0,0,0,,这里还有很多规则\nDialogue: 0,0:17:27.42,0:17:31.04,Default,,0,0,0,,这些规则是很复杂的 比如--\nDialogue: 0,0:17:31.26,0:17:33.93,Default,,0,0,0,,请看 这条规则是分配律\nDialogue: 0,0:17:33.93,0:17:38.57,Default,,0,0,0,,任何表达式c乘以d和e\nDialogue: 0,0:17:39.02,0:17:43.66,Default,,0,0,0,,等于 c与d的积加上c与e的积\nDialogue: 0,0:17:45.31,0:17:48.67,Default,,0,0,0,,我并不关心这些规则具体描述的什么\nDialogue: 0,0:17:49.16,0:17:52.97,Default,,0,0,0,,我们将要构建一种语言 用来解释这些规则\nDialogue: 0,0:17:55.50,0:17:57.48,Default,,0,0,0,,这样我们就可以按我们的意愿编写规则\nDialogue: 0,0:17:58.35,0:18:00.14,Default,,0,0,0,,这是另外一种程序设计语言\nDialogue: 0,0:18:03.39,0:18:04.04,Default,,0,0,0,,来看看\nDialogue: 0,0:18:05.18,0:18:06.96,Default,,0,0,0,,我还没告诉你我们要怎么做\nDialogue: 0,0:18:07.53,0:18:10.06,Default,,0,0,0,,当然我们马上就要讲了\nDialogue: 0,0:18:10.89,0:18:15.40,Default,,0,0,0,,但真正的问题是：宏观地看 我要做什么？\nDialogue: 0,0:18:17.08,0:18:18.22,Default,,0,0,0,,这些规则是如何运作的？\nDialogue: 0,0:18:19.00,0:18:25.45,Default,,0,0,0,,化简程序是如何用这些规则来输入的表达式 并返回一个合理的答案？\nDialogue: 0,0:18:26.22,0:18:29.85,Default,,0,0,0,,首先 我认为我们有一大堆的规则\nDialogue: 0,0:18:32.52,0:18:34.22,Default,,0,0,0,,这里有全部的规则\nDialogue: 0,0:18:42.09,0:18:44.49,Default,,0,0,0,,这里的每一个规则 ---\nDialogue: 0,0:18:46.97,0:18:49.24,Default,,0,0,0,,都有一个模式和一个骨架\nDialogue: 0,0:18:49.72,0:18:51.36,Default,,0,0,0,,我正在努力为它作一个控制结构\nDialogue: 0,0:18:53.37,0:18:56.56,Default,,0,0,0,,我有一个匹配器\nDialogue: 0,0:19:00.99,0:19:03.76,Default,,0,0,0,,还有一个实例化器\nDialogue: 0,0:19:09.66,0:19:12.94,Default,,0,0,0,,我将把一系列模式变量的值\nDialogue: 0,0:19:14.03,0:19:17.47,Default,,0,0,0,,从匹配器中传递到实例化器中\nDialogue: 0,0:19:18.06,0:19:19.42,Default,,0,0,0,,我把传递的东西叫做词典\nDialogue: 0,0:19:20.59,0:19:21.52,Default,,0,0,0,,传递一本词典\nDialogue: 0,0:19:24.92,0:19:27.82,Default,,0,0,0,,里面记载了：x匹配下列子表达式\nDialogue: 0,0:19:29.04,0:19:31.31,Default,,0,0,0,,而y匹配另一个子表达式\nDialogue: 0,0:19:32.25,0:19:36.35,Default,,0,0,0,,我会从实例化器中构造表达式 并送入匹配器\nDialogue: 0,0:19:37.16,0:19:38.36,Default,,0,0,0,,这些是表达式\nDialogue: 0,0:19:45.00,0:19:48.41,Default,,0,0,0,,这些规则的模式将要送进匹配器中\nDialogue: 0,0:19:49.24,0:19:54.40,Default,,0,0,0,,规则对应的骨架将要送进实例化器中\nDialogue: 0,0:19:55.21,0:19:56.62,Default,,0,0,0,,现在变得有点复杂了\nDialogue: 0,0:19:57.12,0:19:59.53,Default,,0,0,0,,因为当我们处理代数表达式时\nDialogue: 0,0:20:00.44,0:20:03.60,Default,,0,0,0,,有一些规则使你能够做等价代换\nDialogue: 0,0:20:04.24,0:20:05.87,Default,,0,0,0,,这些是等价代换规则\nDialogue: 0,0:20:06.88,0:20:09.29,Default,,0,0,0,,所以需要考察表达式的所有子表达式\nDialogue: 0,0:20:11.13,0:20:15.82,Default,,0,0,0,,给定一个表达式 这些规则应该被不断应用\nDialogue: 0,0:20:16.03,0:20:19.71,Default,,0,0,0,,首先 对于传入的表达式的每个子表达式\nDialogue: 0,0:20:20.22,0:20:22.83,Default,,0,0,0,,所有的规则都需要考察一次\nDialogue: 0,0:20:24.33,0:20:27.07,Default,,0,0,0,,如果有规则匹配成功 那么就会执行这个过程\nDialogue: 0,0:20:27.30,0:20:30.63,Default,,0,0,0,,传递一本存储值的词典\nDialogue: 0,0:20:30.63,0:20:33.39,Default,,0,0,0,,实例化器产生一个新的表达式\nDialogue: 0,0:20:33.90,0:20:39.10,Default,,0,0,0,,该表达式基本上只是替换了原表达式中匹配的部分\nDialogue: 0,0:20:40.84,0:20:44.46,Default,,0,0,0,,然后 我们要对它重新检查\nDialogue: 0,0:20:44.75,0:20:48.11,Default,,0,0,0,,重新考察这些规则 看看表达式是否可以更进一步化简\nDialogue: 0,0:20:49.53,0:20:53.71,Default,,0,0,0,,然后每一个子表达式这样做 直到没有任何变化为止\nDialogue: 0,0:20:54.96,0:20:57.50,Default,,0,0,0,,你可以把它想像成一个有机过程\nDialogue: 0,0:20:57.83,0:21:00.20,Default,,0,0,0,,我们有一锅炖汤\nDialogue: 0,0:21:00.24,0:21:04.32,Default,,0,0,0,,粘乎乎的汤里面有细菌 有酶\nDialogue: 0,0:21:05.63,0:21:10.50,Default,,0,0,0,,这些酶改变了汤\nDialogue: 0,0:21:10.50,0:21:14.38,Default,,0,0,0,,它们附着在你的表达式上 改变了它 然后就走了\nDialogue: 0,0:21:15.28,0:21:17.83,Default,,0,0,0,,就像钥匙和锁一样 它们需要配对\nDialogue: 0,0:21:18.00,0:21:19.73,Default,,0,0,0,,匹配 -- 改变 -- 然后离开\nDialogue: 0,0:21:19.73,0:21:21.68,Default,,0,0,0,,你可以将其想像成一种并行过程\nDialogue: 0,0:21:22.70,0:21:24.97,Default,,0,0,0,,所以你把一个表达式放到这锅“浓汤”中\nDialogue: 0,0:21:25.80,0:21:28.00,Default,,0,0,0,,过了会儿把它拿出来 它就被简化了\nDialogue: 0,0:21:30.44,0:21:32.64,Default,,0,0,0,,它会一直变化 直到不能再变化为止\nDialogue: 0,0:21:33.36,0:21:38.33,Default,,0,0,0,,但这些酶可以附着在表达式的任何部分\nDialogue: 0,0:21:39.21,0:21:43.76,Default,,0,0,0,,课先上到这里 有问题么？\nDialogue: 0,0:21:44.92,0:21:45.36,Default,,0,0,0,,请讲\nDialogue: 0,0:21:45.43,0:21:52.76,Default,,0,0,0,,学生：匹配器和实例化器是两个独立的程序 是么?\nDialogue: 0,0:21:52.76,0:21:53.85,Default,,0,0,0,,教授：他们被拆分成很多小片\nDialogue: 0,0:21:54.14,0:21:56.60,Default,,0,0,0,,然后在一个更大的结构中组合起来\nDialogue: 0,0:21:57.26,0:21:59.13,Default,,0,0,0,,学生：先扫描并匹配\nDialogue: 0,0:21:59.61,0:22:03.21,Default,,0,0,0,,并把匹配结果传递给实例化器\nDialogue: 0,0:22:03.39,0:22:06.03,Default,,0,0,0,,实例化器做出更改 并将其返回给匹配器\nDialogue: 0,0:22:06.11,0:22:08.49,Default,,0,0,0,,教授：不是直接更改 而是生成新的表达式\nDialogue: 0,0:22:09.61,0:22:18.43,Default,,0,0,0,,新表达式中的模式变量都被左边式子中所匹配的值所替换\nDialogue: 0,0:22:18.99,0:22:23.80,Default,,0,0,0,,也就是右边式子中的那些骨架变量 或者说求值变量\nDialogue: 0,0:22:25.20,0:22:27.08,Default,,0,0,0,,学生：然后它要回传给匹配器么?\nDialogue: 0,0:22:27.20,0:22:32.32,Default,,0,0,0,,教授：然后要再进行一轮 直到表达式不再变化\nDialogue: 0,0:22:33.31,0:22:37.00,Default,,0,0,0,,学生：感觉这样递归循环似乎有些危险\nDialogue: 0,0:22:37.20,0:22:42.00,Default,,0,0,0,,教授：你说得很对 如果你定义的规则不好--\nDialogue: 0,0:22:42.00,0:22:45.53,Default,,0,0,0,,你发明的任何语言 如果它可以做任何事情\nDialogue: 0,0:22:45.72,0:22:48.40,Default,,0,0,0,,你就可能写出无限循环的程序\nDialogue: 0,0:22:49.37,0:22:55.07,Default,,0,0,0,,确实 诸如代数处理 这样的过程可能会产生无限循环\nDialogue: 0,0:23:01.05,0:23:01.52,Default,,0,0,0,,教授：请讲\nDialogue: 0,0:23:01.79,0:23:05.90,Default,,0,0,0,,学生：一些语言的设计者觉得这个特性非常重要\nDialogue: 0,0:23:05.93,0:23:12.03,Default,,0,0,0,,以至于它应该是语言的一部分 比如Scheme\nDialogue: 0,0:23:12.03,0:23:13.96,Default,,0,0,0,,你的观点是--\nDialogue: 0,0:23:13.96,0:23:15.08,Default,,0,0,0,,老师：语言的什么特性?\nDialogue: 0,0:23:15.79,0:23:17.26,Default,,0,0,0,,学生：模式匹配\nDialogue: 0,0:23:17.26,0:23:22.03,Default,,0,0,0,,所有应用的这些规则应该 ---\nDialogue: 0,0:23:22.03,0:23:23.70,Default,,0,0,0,,教授：你是说像 Prolog 那样？\nDialogue: 0,0:23:23.70,0:23:26.60,Default,,0,0,0,,学生：类似 Prolog 但更加通用的--\nDialogue: 0,0:23:26.60,0:23:27.64,Default,,0,0,0,,教授：这是可行的\nDialogue: 0,0:23:28.46,0:23:32.30,Default,,0,0,0,,好了 我是觉得吧…… 恩……\nDialogue: 0,0:23:33.16,0:23:36.49,Default,,0,0,0,,我可以教你怎么做 这样你就不用依靠语言的设计者\nDialogue: 0,0:23:40.92,0:23:42.75,Default,,0,0,0,,教授：我们可以自己来实现\nDialogue: 0,0:23:45.28,0:23:45.63,Default,,0,0,0,,下课\nDialogue: 0,0:23:45.63,0:23:50.63,Default,,0,0,0,,[音乐]\nDialogue: 0,0:23:50.63,0:23:53.13,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:23:53.13,0:23:55.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:24:00.32,0:24:06.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:24:07.07,0:24:10.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}模式匹配：基于规则的代换\nDialogue: 0,0:24:14.08,0:24:15.80,Default,,0,0,0,,好 上课\nDialogue: 0,0:24:15.80,0:24:17.21,Default,,0,0,0,,现在 我得告诉你们它是如何运作的\nDialogue: 0,0:24:20.00,0:24:24.11,Default,,0,0,0,,它很容易分成很多小份\nDialogue: 0,0:24:24.80,0:24:26.54,Default,,0,0,0,,现在 我们先看一下匹配器\nDialogue: 0,0:24:28.72,0:24:31.42,Default,,0,0,0,,匹配器的结构是像下面这样的\nDialogue: 0,0:24:32.86,0:24:45.12,Default,,0,0,0,,它是一个盒子 它的输入是一个表达式和一个模式\nDialogue: 0,0:24:52.09,0:24:53.95,Default,,0,0,0,,还有个输入是一本词典\nDialogue: 0,0:25:01.71,0:25:08.67,Default,,0,0,0,,要记住 词典把模式变量映射到匹配的值上\nDialogue: 0,0:25:09.15,0:25:11.05,Default,,0,0,0,,它的输出是另一本词典\nDialogue: 0,0:25:18.24,0:25:25.53,Default,,0,0,0,,除了旧词典中已有的内容 新词典中还产生的新的匹配\nDialogue: 0,0:25:28.00,0:25:28.83,Default,,0,0,0,,这就是匹配器\nDialogue: 0,0:25:33.87,0:25:36.54,Default,,0,0,0,,这是一个相当复杂的程序\nDialogue: 0,0:25:37.20,0:25:41.58,Default,,0,0,0,,请大家看看这里的投影 请看\nDialogue: 0,0:25:41.98,0:25:43.87,Default,,0,0,0,,哈哈 真是相当复杂\nDialogue: 0,0:25:44.43,0:25:45.87,Default,,0,0,0,,我只想让大家看一下它的轮廓\nDialogue: 0,0:25:46.78,0:25:49.85,Default,,0,0,0,,其实现细节太复杂了\nDialogue: 0,0:25:51.72,0:25:59.24,Default,,0,0,0,,然而 这是一个庞大的程序 它有很多这样的缩进的结构\nDialogue: 0,0:26:00.09,0:26:05.28,Default,,0,0,0,,在最外层 -- 不要去读这些代码  宏观地看\nDialogue: 0,0:26:05.43,0:26:10.36,Default,,0,0,0,,这里有一个分情况分析 而这些就是不同的情况\nDialogue: 0,0:26:12.09,0:26:16.19,Default,,0,0,0,,现在 我们将要深入细节\nDialogue: 0,0:26:16.67,0:26:18.60,Default,,0,0,0,,试图理解它是如何工作的\nDialogue: 0,0:26:20.08,0:26:22.35,Default,,0,0,0,,我们来看第一张幻灯片\nDialogue: 0,0:26:23.55,0:26:27.93,Default,,0,0,0,,它展示了匹配器的宏观结构\nDialogue: 0,0:26:28.81,0:26:36.33,Default,,0,0,0,,我们看到匹配器 它需要的参数有：模式、表达式和词典\nDialogue: 0,0:26:38.57,0:26:40.40,Default,,0,0,0,,这里是一个cond语句\nDialogue: 0,0:26:41.24,0:26:45.61,Default,,0,0,0,,它有许多不同情况 我们省略了一些代码\nDialogue: 0,0:26:46.62,0:26:48.62,Default,,0,0,0,,这个是我想让大家注意的 通用情况\nDialogue: 0,0:26:50.52,0:26:53.28,Default,,0,0,0,,考虑这个通用模式 它是个非常重要的模式\nDialogue: 0,0:26:56.32,0:27:01.61,Default,,0,0,0,,问题是我们需要同时地检查这两棵树\nDialogue: 0,0:27:02.50,0:27:08.03,Default,,0,0,0,,一棵树是表达式 另一棵树是模式\nDialogue: 0,0:27:08.59,0:27:10.11,Default,,0,0,0,,我们需要在它们之间进行匹配\nDialogue: 0,0:27:11.37,0:27:16.38,Default,,0,0,0,,使得表达式的子表达式会与模式的子表达式相匹配\nDialogue: 0,0:27:18.38,0:27:23.44,Default,,0,0,0,,我们深入研究一下 假设我有一个模式\nDialogue: 0,0:27:23.93,0:27:31.24,Default,,0,0,0,,这个是模式是 一个叫做x的表达式 乘以\nDialogue: 0,0:27:32.44,0:27:35.53,Default,,0,0,0,,乘以一个我们叫做y的表达式\nDialogue: 0,0:27:39.12,0:27:42.04,Default,,0,0,0,,再加上 刚才的表达式y 两个y必须是相同的表达式\nDialogue: 0,0:27:45.21,0:27:47.53,Default,,0,0,0,,我们在考察 乘式的和\nDialogue: 0,0:27:48.99,0:27:54.78,Default,,0,0,0,,其中 乘法和加法的第二个参数都是相同的\nDialogue: 0,0:27:57.02,0:27:58.84,Default,,0,0,0,,这是我们想要匹配像这样的表达式\nDialogue: 0,0:27:59.60,0:28:02.04,Default,,0,0,0,,它作为一个模式看起来像这个样子\nDialogue: 0,0:28:03.02,0:28:04.01,Default,,0,0,0,,这是一课树\nDialogue: 0,0:28:04.94,0:28:06.25,Default,,0,0,0,,它包含了一个加号\nDialogue: 0,0:28:08.08,0:28:20.25,Default,,0,0,0,,还有乘号 以及模式变量(? x)和(? y)\nDialogue: 0,0:28:21.36,0:28:22.73,Default,,0,0,0,,还有模式变量(? y)\nDialogue: 0,0:28:24.92,0:28:26.94,Default,,0,0,0,,这只是把表结构换了种写法 两者其实是一样的\nDialogue: 0,0:28:28.75,0:28:31.76,Default,,0,0,0,,我们先演示一个成功的匹配是如何运行的\nDialogue: 0,0:28:32.49,0:28:39.85,Default,,0,0,0,,这个模式匹配表达式 (+ (* 3 x) x)\nDialogue: 0,0:28:42.41,0:28:43.36,Default,,0,0,0,,这是另一棵个树\nDialogue: 0,0:28:44.33,0:28:56.06,Default,,0,0,0,,它是3乘以x的积加上x\nDialogue: 0,0:28:59.44,0:29:03.02,Default,,0,0,0,,所以我要做的是 同时遍历这两棵树\nDialogue: 0,0:29:04.41,0:29:07.82,Default,,0,0,0,,我想这样遍历它们\nDialogue: 0,0:29:08.67,0:29:12.96,Default,,0,0,0,,我会比较它们是否一样\nDialogue: 0,0:29:12.96,0:29:14.32,Default,,0,0,0,,这是一个复合对象\nDialogue: 0,0:29:15.21,0:29:17.26,Default,,0,0,0,,我们先看它的左分支\nDialogue: 0,0:29:17.26,0:29:18.14,Default,,0,0,0,,这可能是car部分\nDialogue: 0,0:29:18.56,0:29:21.21,Default,,0,0,0,,它们匹配吗？恩 两个加号成功匹配\nDialogue: 0,0:29:21.68,0:29:24.20,Default,,0,0,0,,但是下一个对象是复合的\nDialogue: 0,0:29:24.20,0:29:24.84,Default,,0,0,0,,我们看一下它\nDialogue: 0,0:29:25.20,0:29:26.80,Default,,0,0,0,,这个也匹配了\nDialogue: 0,0:29:26.80,0:29:27.79,Default,,0,0,0,,它们都是星号\nDialogue: 0,0:29:28.51,0:29:30.24,Default,,0,0,0,,现在……哦！\nDialogue: 0,0:29:30.40,0:29:33.60,Default,,0,0,0,,这是模式变量 它和3相匹配\nDialogue: 0,0:29:34.27,0:29:35.92,Default,,0,0,0,,记住 现在x等于3\nDialogue: 0,0:29:36.36,0:29:37.37,Default,,0,0,0,,把它记录在词典中\nDialogue: 0,0:29:37.56,0:29:40.73,Default,,0,0,0,,遍历过程中 词典紧随着我们 并告诉我们：x等于3\nDialogue: 0,0:29:41.45,0:29:45.87,Default,,0,0,0,,x等于3 y等于x 但这两个是不同意义上的x\nDialogue: 0,0:29:46.83,0:29:51.20,Default,,0,0,0,,那个是模式变量x 而这个是模式变量y匹配表达式x\nDialogue: 0,0:29:53.61,0:29:57.76,Default,,0,0,0,,这是模式变量y 它已经有值了 并且值是x\nDialogue: 0,0:29:58.36,0:30:00.06,Default,,0,0,0,,这是x么? 当然是\nDialogue: 0,0:30:00.06,0:30:00.75,Default,,0,0,0,,好的\nDialogue: 0,0:30:02.03,0:30:02.78,Default,,0,0,0,,完事儿了\nDialogue: 0,0:30:03.39,0:30:08.09,Default,,0,0,0,,现在 我有一本词典 它在遍历过程中不断积累\nDialogue: 0,0:30:11.42,0:30:14.51,Default,,0,0,0,,现在让我们看看这个一般情况 然后看看它如何工作\nDialogue: 0,0:30:15.88,0:30:16.51,Default,,0,0,0,,这里..\nDialogue: 0,0:30:17.20,0:30:21.66,Default,,0,0,0,,我传入一个模式 一个表达式 和一本词典\nDialogue: 0,0:30:22.38,0:30:27.50,Default,,0,0,0,,这里的情况比较复杂 -- 它是通用情况\nDialogue: 0,0:30:29.98,0:30:34.80,Default,,0,0,0,,一般来说 表达式由两部分组成：左部分和右部分\nDialogue: 0,0:30:35.45,0:30:38.81,Default,,0,0,0,,在Lisp系统中 复合对象都是由两部分组成的\nDialogue: 0,0:30:40.03,0:30:41.23,Default,,0,0,0,,现在我们有什么呢？\nDialogue: 0,0:30:41.88,0:30:48.84,Default,,0,0,0,,我将会用已有的这本词典 继续匹配模式和表达式的car部分\nDialogue: 0,0:30:50.30,0:30:53.12,Default,,0,0,0,,这个匹配过程会产生一本新词典\nDialogue: 0,0:30:54.14,0:30:57.26,Default,,0,0,0,,我将用它来匹配它们的cdr部分\nDialogue: 0,0:30:58.51,0:31:02.09,Default,,0,0,0,,这就是词典是如何在整个结构中遍历、线索的\nDialogue: 0,0:31:03.66,0:31:07.53,Default,,0,0,0,,匹配完car和cdr部分后得到的词典\nDialogue: 0,0:31:10.12,0:31:12.41,Default,,0,0,0,,会作为值返回给上级\nDialogue: 0,0:31:13.61,0:31:15.84,Default,,0,0,0,,匹配可能会在任何一个地方失败\nDialogue: 0,0:31:16.62,0:31:18.20,Default,,0,0,0,,比如说 可能会有这种情况\nDialogue: 0,0:31:18.36,0:31:27.18,Default,,0,0,0,,我们回过头来把这里改成4 这样就不会完全匹配\nDialogue: 0,0:31:29.13,0:31:34.81,Default,,0,0,0,,现在这两个不再匹配了 因为x应该\nDialogue: 0,0:31:34.93,0:31:37.34,Default,,0,0,0,,不好意思 这个y是x\nDialogue: 0,0:31:37.82,0:31:40.12,Default,,0,0,0,,但是这里的y却又是4\nDialogue: 0,0:31:40.53,0:31:43.52,Default,,0,0,0,,语法上来说 x和4显然不相同\nDialogue: 0,0:31:44.59,0:31:48.81,Default,,0,0,0,,所以这个不会匹配成功 它会拒绝 匹配会失败\nDialogue: 0,0:31:50.19,0:31:56.08,Default,,0,0,0,,那么 因为先前产生的词典会作为输入送入匹配器\nDialogue: 0,0:31:56.52,0:31:58.28,Default,,0,0,0,,所以它必须能够传播失败\nDialogue: 0,0:31:58.57,0:32:01.04,Default,,0,0,0,,第一条语句就是用来判断失败的\nDialogue: 0,0:32:03.61,0:32:08.19,Default,,0,0,0,,如果证实出来这个模式不是原子的---\nDialogue: 0,0:32:08.50,0:32:11.45,Default,,0,0,0,,如果模式是原子的 将进入这里 这里我们还没有讨论过\nDialogue: 0,0:32:12.17,0:32:13.56,Default,,0,0,0,,如果模式不是原子的\nDialogue: 0,0:32:15.05,0:32:19.23,Default,,0,0,0,,但表达式是原子--也就是它不由小部分组成\nDialogue: 0,0:32:20.14,0:32:22.65,Default,,0,0,0,,那么匹配必然失败 因此我们返回'failed\nDialogue: 0,0:32:23.64,0:32:30.78,Default,,0,0,0,,整理下思路 如果这个模式既不是原子的又不是模式变量的话 程序会来到这里\nDialogue: 0,0:32:30.96,0:32:32.51,Default,,0,0,0,,这是会使匹配失败的情况\nDialogue: 0,0:32:35.26,0:32:39.12,Default,,0,0,0,,好 让我们看这个里面的东西\nDialogue: 0,0:32:39.84,0:32:42.93,Default,,0,0,0,,首先需要知道 如果用原子模式来进行匹配会发生什么？\nDialogue: 0,0:32:42.93,0:32:43.90,Default,,0,0,0,,这简单\nDialogue: 0,0:32:43.90,0:32:46.50,Default,,0,0,0,,不是由其它模式构成的模式 比如：foo\nDialogue: 0,0:32:47.37,0:32:48.54,Default,,0,0,0,,这是个非常好的原子模式\nDialogue: 0,0:32:49.16,0:32:51.24,Default,,0,0,0,,让我们来看看\nDialogue: 0,0:32:52.08,0:32:55.82,Default,,0,0,0,,如果模式是原子的 而且表达式也原子的话\nDialogue: 0,0:32:56.80,0:33:01.85,Default,,0,0,0,,并且如果它俩是同一个东西 那么词典就跟之前一样\nDialogue: 0,0:33:03.08,0:33:04.00,Default,,0,0,0,,没有变化\nDialogue: 0,0:33:04.60,0:33:10.33,Default,,0,0,0,,就像刚才 +匹配+ *匹配* x匹配x\nDialogue: 0,0:33:11.42,0:33:12.33,Default,,0,0,0,,就是那样\nDialogue: 0,0:33:13.07,0:33:16.81,Default,,0,0,0,,然而 如何模式和表达式并不相同的话\nDialogue: 0,0:33:17.32,0:33:21.36,Default,,0,0,0,,如果这是两个不同的原子对象 比如+和*相匹配\nDialogue: 0,0:33:22.44,0:33:23.40,Default,,0,0,0,,这样就失败了\nDialogue: 0,0:33:25.60,0:33:34.56,Default,,0,0,0,,或者说 如果模式是原子 但表达式是复合 那么匹配失败\nDialogue: 0,0:33:37.40,0:33:38.24,Default,,0,0,0,,这很简单\nDialogue: 0,0:33:38.81,0:33:43.61,Default,,0,0,0,,那么 那些各种各样的模式变量又是怎么处理的呢？\nDialogue: 0,0:33:44.09,0:33:46.54,Default,,0,0,0,,我们有三类被命名了的模式变量\nDialogue: 0,0:33:47.39,0:33:52.03,Default,,0,0,0,,它们分别用于匹配：任意常量 任意变量 任意表达式\nDialogue: 0,0:33:53.82,0:34:00.14,Default,,0,0,0,,(? x) 表示匹配任意表达式\nDialogue: 0,0:34:01.18,0:34:04.54,Default,,0,0,0,,(?c x) 表示匹配任意常量\nDialogue: 0,0:34:04.73,0:34:07.29,Default,,0,0,0,,(?v x) 表示匹配任意变量\nDialogue: 0,0:34:08.96,0:34:09.79,Default,,0,0,0,,好的 我们要做什么呢?\nDialogue: 0,0:34:10.51,0:34:16.94,Default,,0,0,0,,看这里 如果模式表示的是匹配任意常量\nDialogue: 0,0:34:17.53,0:34:20.57,Default,,0,0,0,,那么待匹配的表达式最好是一个常量\nDialogue: 0,0:34:21.48,0:34:23.53,Default,,0,0,0,,不然的话 匹配就会失败\nDialogue: 0,0:34:23.83,0:34:27.50,Default,,0,0,0,,如果是一个常量 那么我就需要扩充词典\nDialogue: 0,0:34:27.50,0:34:29.69,Default,,0,0,0,,扩充词典的方法则是：\nDialogue: 0,0:34:30.70,0:34:37.76,Default,,0,0,0,,在旧词典后 附加一对模式与表达式的配对\nDialogue: 0,0:34:41.16,0:34:42.75,Default,,0,0,0,,因此 如果是匹配任意变量\nDialogue: 0,0:34:43.72,0:34:47.46,Default,,0,0,0,,我得通过匹配来核查表达式是否是变量\nDialogue: 0,0:34:47.46,0:34:50.09,Default,,0,0,0,,如果是的话 我就扩充词典\nDialogue: 0,0:34:50.38,0:34:54.65,Default,,0,0,0,,现在在原有词典基础上 我们又多了一项模式与表达式的匹配\nDialogue: 0,0:34:55.28,0:34:56.70,Default,,0,0,0,,这个过程返回一本新的词典\nDialogue: 0,0:34:58.88,0:35:04.16,Default,,0,0,0,,在这个词典中也有很多失败 因此需要检查\nDialogue: 0,0:35:04.16,0:35:07.50,Default,,0,0,0,,就比如 模式变量已经有一个值了\nDialogue: 0,0:35:09.23,0:35:16.17,Default,,0,0,0,,但我又用它匹配一个跟之前匹配的表达式不相同的表达式的话\nDialogue: 0,0:35:16.43,0:35:18.36,Default,,0,0,0,,那么在这里也会立即产生失败\nDialogue: 0,0:35:20.16,0:35:21.56,Default,,0,0,0,,我们后面再讨论\nDialogue: 0,0:35:22.91,0:35:29.36,Default,,0,0,0,,最后 匹配任意的表达式不需要在语法范畴做什么检查\nDialogue: 0,0:35:30.11,0:35:32.20,Default,,0,0,0,,只用扩充词典就行了\nDialogue: 0,0:35:34.76,0:35:38.32,Default,,0,0,0,,这就是一个完整的简单的匹配器\nDialogue: 0,0:35:39.28,0:35:41.37,Default,,0,0,0,,非常具有讽刺意味的一点是\nDialogue: 0,0:35:41.66,0:35:45.12,Default,,0,0,0,,现在 人们花了大价钱来请一些人编写\nDialogue: 0,0:35:45.46,0:35:47.52,Default,,0,0,0,,所谓的 “人工智能专家系统”\nDialogue: 0,0:35:48.40,0:35:52.03,Default,,0,0,0,,也不过是像这样的一个匹配器和实例化器罢了\nDialogue: 0,0:35:53.56,0:35:56.94,Default,,0,0,0,,这很容易做 现在你也可以创业开个小公司了\nDialogue: 0,0:35:57.42,0:36:01.72,Default,,0,0,0,,然后 第二周忽悠风投给你投个几百万\nDialogue: 0,0:36:03.79,0:36:08.57,Default,,0,0,0,,我是想说 这种程序放在20年前是非凡的\nDialogue: 0,0:36:09.74,0:36:12.81,Default,,0,0,0,,但放到现在 它就是小菜一碟了 大一新生也可以学\nDialogue: 0,0:36:13.63,0:36:15.47,Default,,0,0,0,,这里是一个实例化器\nDialogue: 0,0:36:20.22,0:36:23.07,Default,,0,0,0,,可问题是 他们都去了赚钱了 而且比我的还多\nDialogue: 0,0:36:24.97,0:36:26.59,Default,,0,0,0,,在大学中确实是这样\nDialogue: 0,0:36:27.10,0:36:39.42,Default,,0,0,0,,实例化是用来将给定的表达式、词典和骨架生成新的表达式的\nDialogue: 0,0:36:44.35,0:36:45.69,Default,,0,0,0,,这个不是很难\nDialogue: 0,0:36:46.60,0:36:53.36,Default,,0,0,0,,我们在下一张幻灯片中简单地看下\nDialogue: 0,0:36:53.88,0:36:59.29,Default,,0,0,0,,用一本给定的词典去实例化一个骨架 这很简单\nDialogue: 0,0:36:59.68,0:37:03.29,Default,,0,0,0,,我们要做的 就是对骨架递归地做树遍历\nDialogue: 0,0:37:04.08,0:37:08.33,Default,,0,0,0,,所有的骨架变量---我叫它“骨架求值”\nDialogue: 0,0:37:08.41,0:37:11.42,Default,,0,0,0,,这是我在这个程序中定义的抽象语法\nDialogue: 0,0:37:11.60,0:37:16.46,Default,,0,0,0,,在规则中 以冒号打头的就是骨架求值\nDialogue: 0,0:37:18.25,0:37:24.30,Default,,0,0,0,,在那种情况下 我要在词典中找答案 我们待会儿再讨论\nDialogue: 0,0:37:24.30,0:37:25.61,Default,,0,0,0,,我们看整体\nDialogue: 0,0:37:27.77,0:37:31.80,Default,,0,0,0,,这个过程是用一本字典来实例化一个骨架\nDialogue: 0,0:37:32.75,0:37:37.15,Default,,0,0,0,,我在这里定义一个内部循环\nDialogue: 0,0:37:38.14,0:37:39.85,Default,,0,0,0,,它要做的事情很简单\nDialogue: 0,0:37:40.17,0:37:43.50,Default,,0,0,0,,如果这个骨架是原子的\nDialogue: 0,0:37:44.60,0:37:47.45,Default,,0,0,0,,这种情况 它直接返回一个骨架作为结果\nDialogue: 0,0:37:48.84,0:37:51.87,Default,,0,0,0,,或者在通常情况下它是复合的\nDialogue: 0,0:37:52.60,0:37:59.40,Default,,0,0,0,,这种情况下 我通过一些实例化的结果构造表达式\nDialogue: 0,0:37:59.40,0:38:04.25,Default,,0,0,0,,递归调用这个循环 不断实例化骨架的car和cdr部分\nDialogue: 0,0:38:04.89,0:38:06.24,Default,,0,0,0,,这就是树的递归遍历\nDialogue: 0,0:38:08.41,0:38:14.36,Default,,0,0,0,,如果在骨架中有冒号表达式 那么这就是一个骨架求值\nDialogue: 0,0:38:14.96,0:38:22.64,Default,,0,0,0,,那么要做的事情是：找到冒号引导的表达式 -- 本例中 也就是CADR部分\nDialogue: 0,0:38:22.81,0:38:26.25,Default,,0,0,0,,这些是抽象语法 因此我能改变规则的表示\nDialogue: 0,0:38:27.52,0:38:32.73,Default,,0,0,0,,先不管求值过程如何实现 总之我要用这本词典对表达式求值\nDialogue: 0,0:38:32.90,0:38:34.65,Default,,0,0,0,,我们以后再仔细讨论\nDialogue: 0,0:38:36.12,0:38:38.35,Default,,0,0,0,,求值的结果就是答案\nDialogue: 0,0:38:39.68,0:38:43.66,Default,,0,0,0,,这条初始化语句 通过给它传递整个骨架循环来启动它\nDialogue: 0,0:38:44.44,0:38:47.04,Default,,0,0,0,,这些调用又会被分成小块的递归调用\nDialogue: 0,0:38:49.63,0:38:56.48,Default,,0,0,0,,那么 求值过程里面发生了些什么\nDialogue: 0,0:38:57.18,0:38:59.07,Default,,0,0,0,,我无法详尽地给你们解释\nDialogue: 0,0:38:59.98,0:39:01.34,Default,,0,0,0,,我就大致说一下\nDialogue: 0,0:39:01.56,0:39:03.74,Default,,0,0,0,,之后 我们再深入地讨论\nDialogue: 0,0:39:05.29,0:39:10.81,Default,,0,0,0,,在一本词典的环境下 求值一个表达式\nDialogue: 0,0:39:11.90,0:39:14.17,Default,,0,0,0,,如果表达式是原子的\nDialogue: 0,0:39:15.04,0:39:16.22,Default,,0,0,0,,就在词典中进行查找\nDialogue: 0,0:39:18.60,0:39:19.87,Default,,0,0,0,,这没啥\nDialogue: 0,0:39:20.57,0:39:23.66,Default,,0,0,0,,难点在这里\nDialogue: 0,0:39:23.83,0:39:28.28,Default,,0,0,0,,我将要应用表达式的car部分对应的一个过程\nDialogue: 0,0:39:29.44,0:39:31.68,Default,,0,0,0,,这个过程是在“某个地方”查找得到的--我们以后讨论\nDialogue: 0,0:39:32.14,0:39:34.20,Default,,0,0,0,,我想请大家注意一下 这之中有一些“魔法”\nDialogue: 0,0:39:34.67,0:39:38.72,Default,,0,0,0,,这个魔法将在不久后“施展”出来 但不是在今天\nDialogue: 0,0:39:40.00,0:39:46.51,Default,,0,0,0,,我们在词典中查找表达式剩余部分对应的值\nDialogue: 0,0:39:48.56,0:39:50.88,Default,,0,0,0,,我还不想让你们关注细节\nDialogue: 0,0:39:51.44,0:39:53.44,Default,,0,0,0,,我想让大家意识到这里还有很多代码\nDialogue: 0,0:39:54.17,0:39:56.75,Default,,0,0,0,,我们以后再详细讨论\nDialogue: 0,0:39:59.04,0:40:00.88,Default,,0,0,0,,但是 魔法就到此结束了\nDialogue: 0,0:40:02.57,0:40:06.96,Default,,0,0,0,,这部分利用Lisp的神奇力量 不过也就到此为止了\nDialogue: 0,0:40:10.25,0:40:13.56,Default,,0,0,0,,我们介绍了匹配和实例化\nDialogue: 0,0:40:15.05,0:40:16.60,Default,,0,0,0,,这一节有疑问么?\nDialogue: 0,0:40:28.10,0:40:29.80,Default,,0,0,0,,学生：我有一个问题\nDialogue: 0,0:40:29.80,0:40:30.43,Default,,0,0,0,,教授：请讲\nDialogue: 0,0:40:30.43,0:40:32.56,Default,,0,0,0,,学生：您能切到前张幻灯片上吗？\nDialogue: 0,0:40:33.60,0:40:35.56,Default,,0,0,0,,是关于定义匹配模式的\nDialogue: 0,0:40:36.16,0:40:40.76,Default,,0,0,0,,教授：好的 你想看定义匹配模式的全部的幻灯片\nDialogue: 0,0:40:40.76,0:40:43.06,Default,,0,0,0,,有人能帮我把投影仪---\nDialogue: 0,0:40:43.06,0:40:45.16,Default,,0,0,0,,这是最大的规模\nDialogue: 0,0:40:45.31,0:40:46.40,Default,,0,0,0,,你想看哪一部分？\nDialogue: 0,0:40:46.76,0:40:49.96,Default,,0,0,0,,学生：呃 最上面吧\nDialogue: 0,0:40:49.96,0:40:53.76,Default,,0,0,0,,就是传递失败的那一部分\nDialogue: 0,0:40:54.52,0:40:55.21,Default,,0,0,0,,教授：恩\nDialogue: 0,0:40:55.64,0:40:59.33,Default,,0,0,0,,学生：基本的想法是把错误返回给词典 是么?\nDialogue: 0,0:40:59.33,0:41:04.25,Default,,0,0,0,,教授：所谓的词典 就是所是匹配的答案 对吧？\nDialogue: 0,0:41:05.16,0:41:09.80,Default,,0,0,0,,要么它是一些配对\nDialogue: 0,0:41:11.07,0:41:14.03,Default,,0,0,0,,要么根本就没有配对\nDialogue: 0,0:41:14.46,0:41:14.97,Default,,0,0,0,,学生：对\nDialogue: 0,0:41:15.26,0:41:17.83,Default,,0,0,0,,教授：这里 事实上\nDialogue: 0,0:41:17.83,0:41:22.60,Default,,0,0,0,,因为一个匹配过程会向另一个匹配过程传递词典\nDialogue: 0,0:41:22.80,0:41:24.65,Default,,0,0,0,,可以在这里的一般情况中看到\nDialogue: 0,0:41:25.12,0:41:27.93,Default,,0,0,0,,这是一个匹配过程传递词典到另一个匹配过程\nDialogue: 0,0:41:28.14,0:41:34.16,Default,,0,0,0,,我是用匹配car部分得到的词典来匹配cdr部分的\nDialogue: 0,0:41:36.06,0:41:37.08,Default,,0,0,0,,这里的代码就是这个意思\nDialogue: 0,0:41:37.29,0:41:40.30,Default,,0,0,0,,正因为如此 如果对car部分的匹配失败了\nDialogue: 0,0:41:41.23,0:41:45.44,Default,,0,0,0,,匹配cdr部分的时候就有必要传播失败\nDialogue: 0,0:41:45.95,0:41:46.96,Default,,0,0,0,,第一行就是用于传播失败\nDialogue: 0,0:41:48.26,0:41:51.73,Default,,0,0,0,,学生：好 但我还是不明白匹配 --\nDialogue: 0,0:41:51.73,0:41:54.24,Default,,0,0,0,,从匹配的实例出来的是什么?\nDialogue: 0,0:41:54.73,0:41:56.00,Default,,0,0,0,,教授：有两种可能的情况\nDialogue: 0,0:41:56.33,0:41:59.15,Default,,0,0,0,,一种是符号'failed 意味匹配失败\nDialogue: 0,0:41:59.53,0:41:59.93,Default,,0,0,0,,学生：对\nDialogue: 0,0:41:59.93,0:42:03.87,Default,,0,0,0,,教授：或者是某种映射 -- 现在这还是一个抽象的东西\nDialogue: 0,0:42:04.16,0:42:05.68,Default,,0,0,0,,你需要知道它的结构\nDialogue: 0,0:42:06.49,0:42:13.96,Default,,0,0,0,,它们把匹配过程中 匹配成功的模式变量和值关联起来\nDialogue: 0,0:42:14.68,0:42:16.70,Default,,0,0,0,,学生：好 那么\nDialogue: 0,0:42:16.80,0:42:18.57,Default,,0,0,0,,教授：那是通过扩充词典实现的\nDialogue: 0,0:42:18.80,0:42:28.54,Default,,0,0,0,,学生：所以根据递归性质 如果匹配过程产生并传递了失败\nDialogue: 0,0:42:28.68,0:42:30.30,Default,,0,0,0,,那么第一种情况将捕获它\nDialogue: 0,0:42:30.40,0:42:33.56,Default,,0,0,0,,教授：并且传播它 不做任何其它处理\nDialogue: 0,0:42:33.56,0:42:34.83,Default,,0,0,0,,学生：哦 懂了\nDialogue: 0,0:42:35.50,0:42:37.36,Default,,0,0,0,,教授：这是传出失败最快的方法\nDialogue: 0,0:42:42.86,0:42:43.60,Default,,0,0,0,,请讲\nDialogue: 0,0:42:43.84,0:42:47.23,Default,,0,0,0,,学生：如果没有失败 那意味着我匹配了一个模式\nDialogue: 0,0:42:47.84,0:42:53.00,Default,,0,0,0,,我会扩充词典并且传递表达式中的模式\nDialogue: 0,0:42:55.21,0:42:58.43,Default,,0,0,0,,但是 代换并不是发生在这 对吧？\nDialogue: 0,0:42:58.43,0:42:59.03,Default,,0,0,0,,是吧？\nDialogue: 0,0:42:59.03,0:42:59.46,Default,,0,0,0,,教授：你是对的\nDialogue: 0,0:42:59.46,0:43:02.40,Default,,0,0,0,,这里没有可供代换的骨架 因此不会发生代换\nDialogue: 0,0:43:02.40,0:43:03.06,Default,,0,0,0,,学生：好 那么\nDialogue: 0,0:43:03.06,0:43:07.16,Default,,0,0,0,,教授：我们这里所做的 是为后面的代换准备词典\nDialogue: 0,0:43:08.25,0:43:12.43,Default,,0,0,0,,学生：词典的数据结构是什么呢？是有序对么？\nDialogue: 0,0:43:12.72,0:43:15.96,Default,,0,0,0,,教授：那个 那个还没有告诉你\nDialogue: 0,0:43:15.96,0:43:16.89,Default,,0,0,0,,它还是一个抽象的东西\nDialogue: 0,0:43:17.06,0:43:17.56,Default,,0,0,0,,学生：哦\nDialogue: 0,0:43:17.56,0:43:18.90,Default,,0,0,0,,教授：你为什么要知道呢?\nDialogue: 0,0:43:18.90,0:43:21.64,Default,,0,0,0,,它是一个函数 仅仅是一个函数\nDialogue: 0,0:43:21.69,0:43:22.33,Default,,0,0,0,,学生：我想知道它的原因是--\nDialogue: 0,0:43:22.33,0:43:24.17,Default,,0,0,0,,教授：这个抽象函数表现地像有序对\nDialogue: 0,0:43:25.12,0:43:28.44,Default,,0,0,0,,它可以用一系列的表通过链接来实现\nDialogue: 0,0:43:29.06,0:43:32.43,Default,,0,0,0,,它也可以用一些酷炫的表机制来实现\nDialogue: 0,0:43:32.56,0:43:34.16,Default,,0,0,0,,它也可以实现为一个函数\nDialogue: 0,0:43:35.80,0:43:37.40,Default,,0,0,0,,我可以把它写成一个函数\nDialogue: 0,0:43:39.02,0:43:39.87,Default,,0,0,0,,但我不会告诉你具体细节\nDialogue: 0,0:43:40.84,0:43:43.08,Default,,0,0,0,,这是George的事情 由他来构建这个结构\nDialogue: 0,0:43:49.56,0:43:52.06,Default,,0,0,0,,我知道 你特别想知道它的具体结构\nDialogue: 0,0:43:52.36,0:43:54.19,Default,,0,0,0,,但我不打算让你那么做\nDialogue: 0,0:43:54.43,0:43:59.23,Default,,0,0,0,,学生：恩 最后一个问题 扩充到词典中的重要信息是什么?\nDialogue: 0,0:43:59.74,0:44:02.08,Default,,0,0,0,,我想 可能是匹配发现的模式\nDialogue: 0,0:44:02.73,0:44:04.83,Default,,0,0,0,,教授：是的 那些与表达式相匹配的模式\nDialogue: 0,0:44:04.83,0:44:09.30,Default,,0,0,0,,我们想要得到模式 只不过在本例中这些都是模式变量 对吧？\nDialogue: 0,0:44:09.85,0:44:12.89,Default,,0,0,0,,这三种扩充词典的情况都是模式变量\nDialogue: 0,0:44:13.20,0:44:13.50,Default,,0,0,0,,学生：恩\nDialogue: 0,0:44:14.48,0:44:18.75,Default,,0,0,0,,教授：所以 在词典就有一个模式变量与一个值对应\nDialogue: 0,0:44:19.45,0:44:22.11,Default,,0,0,0,,这个值是所匹配的表达式\nDialogue: 0,0:44:23.31,0:44:29.63,Default,,0,0,0,,词典就是遍历过程中记录下来的所有匹配\nDialogue: 0,0:44:30.54,0:44:34.41,Default,,0,0,0,,我会以原有词典为基础 创建一本新词典\nDialogue: 0,0:44:35.12,0:44:38.35,Default,,0,0,0,,新增的内容就是新发现的匹配\nDialogue: 0,0:44:39.98,0:44:43.73,Default,,0,0,0,,学生：我不理解为什么不能在发现匹配后立即进行代换\nDialogue: 0,0:44:43.73,0:44:44.80,Default,,0,0,0,,教授：哦 那时候还不能代换\nDialogue: 0,0:44:44.81,0:44:46.62,Default,,0,0,0,,因为我不知道骨架啊！\nDialogue: 0,0:44:47.58,0:44:49.66,Default,,0,0,0,,模式和匹配器都是独立的单元\nDialogue: 0,0:44:49.66,0:44:51.00,Default,,0,0,0,,学生：哦 我明白了\nDialogue: 0,0:44:51.00,0:44:51.50,Default,,0,0,0,,教授：懂了吧？\nDialogue: 0,0:44:51.50,0:44:51.90,Default,,0,0,0,,学生：恩\nDialogue: 0,0:44:51.90,0:44:57.23,Default,,0,0,0,,教授：我用这个匹配器进行匹配 如果匹配了就可以实例化\nDialogue: 0,0:44:58.20,0:44:59.50,Default,,0,0,0,,学生：知道了\nDialogue: 0,0:45:00.54,0:45:03.88,Default,,0,0,0,,学生：您可以再求解一次黑板上的例子么\nDialogue: 0,0:45:04.89,0:45:06.93,Default,,0,0,0,,什么东西返回给了匹配器\nDialogue: 0,0:45:06.93,0:45:08.00,Default,,0,0,0,,教授：当然可以\nDialogue: 0,0:45:08.26,0:45:09.74,Default,,0,0,0,,来看这个例子\nDialogue: 0,0:45:10.67,0:45:15.45,Default,,0,0,0,,在这里当我遍历这个结构的时候 我遇到了(? x)\nDialogue: 0,0:45:16.67,0:45:20.54,Default,,0,0,0,,我有一本词典 不过此时假设它是空的\nDialogue: 0,0:45:21.56,0:45:25.36,Default,,0,0,0,,一本空词典 然后我匹配到了x为3\nDialogue: 0,0:45:26.62,0:45:33.60,Default,,0,0,0,,从此以后 词典中就记录了 x与3匹配 对吧\nDialogue: 0,0:45:33.64,0:45:36.09,Default,,0,0,0,,继续遍历 然后遇到(? y)\nDialogue: 0,0:45:36.89,0:45:39.20,Default,,0,0,0,,它是一个特殊的x 这是模式变量x\nDialogue: 0,0:45:39.79,0:45:41.37,Default,,0,0,0,,我看到(? y) 模式变量y\nDialogue: 0,0:45:42.17,0:45:47.74,Default,,0,0,0,,词典说 模式变量y的值是符号x\nDialogue: 0,0:45:48.99,0:45:51.20,Default,,0,0,0,,因为这里已经匹配过了\nDialogue: 0,0:45:52.43,0:45:54.52,Default,,0,0,0,,所以此时 词典中包含两个条目\nDialogue: 0,0:45:55.45,0:45:59.90,Default,,0,0,0,,模式变量x是数字3 模式变量y是表达式x\nDialogue: 0,0:46:01.95,0:46:04.11,Default,,0,0,0,,现在继续进行遍历\nDialogue: 0,0:46:04.23,0:46:07.45,Default,,0,0,0,,这里 模式变量y想要和4匹配\nDialogue: 0,0:46:08.06,0:46:10.65,Default,,0,0,0,,但是这个不可能 产生失败\nDialogue: 0,0:46:14.30,0:46:15.48,Default,,0,0,0,,谢谢 下课\nDialogue: 0,0:46:16.76,0:46:25.02,Default,,0,0,0,,[音乐]\nDialogue: 0,0:46:25.07,0:46:27.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:27.47,0:46:30.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教\nDialogue: 0,0:46:48.19,0:46:54.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:55.20,0:46:58.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}模式匹配：基于规则的代换\nDialogue: 0,0:47:02.38,0:47:05.68,Default,,0,0,0,,这是大家首次看到如此庞大而复杂的程序\nDialogue: 0,0:47:07.34,0:47:09.90,Default,,0,0,0,,当然 本项课程的目的之一就在于\nDialogue: 0,0:47:09.90,0:47:12.97,Default,,0,0,0,,是让大家可以读懂这么庞大的程序 而完全不用害怕它\nDialogue: 0,0:47:13.76,0:47:16.33,Default,,0,0,0,,这个程序仅仅只有4页代码而已\nDialogue: 0,0:47:17.08,0:47:19.23,Default,,0,0,0,,课程结业后 我希望就算是50页长的程序\nDialogue: 0,0:47:20.27,0:47:21.80,Default,,0,0,0,,也吓不倒你们\nDialogue: 0,0:47:22.97,0:47:28.20,Default,,0,0,0,,我不是说让你们“左耳朵进 右耳朵出”地读程序\nDialogue: 0,0:47:29.20,0:47:31.70,Default,,0,0,0,,你应该体会这个程序\nDialogue: 0,0:47:31.70,0:47:34.83,Default,,0,0,0,,然后好好思考 因为它是一个很大的程序\nDialogue: 0,0:47:35.32,0:47:38.92,Default,,0,0,0,,在这个程序中有很多东西\nDialogue: 0,0:47:41.24,0:47:46.03,Default,,0,0,0,,我已经介绍了我们正在实现的 -- 基于规则代换的模式匹配语言\nDialogue: 0,0:47:46.81,0:47:47.64,Default,,0,0,0,,给你们看了一些规则\nDialogue: 0,0:47:48.36,0:47:51.24,Default,,0,0,0,,我已经告诉大家匹配和实例化\nDialogue: 0,0:47:51.55,0:47:53.32,Default,,0,0,0,,它们是使规则生效的“阴阳两极”\nDialogue: 0,0:47:54.24,0:47:56.35,Default,,0,0,0,,现在我们需要理解控制结构\nDialogue: 0,0:47:56.86,0:48:00.32,Default,,0,0,0,,就是这些规则是如何被用在表达式上\nDialogue: 0,0:48:01.08,0:48:03.84,Default,,0,0,0,,来指导代数化简的\nDialogue: 0,0:48:06.92,0:48:09.58,Default,,0,0,0,,这也是非常复杂的\nDialogue: 0,0:48:12.09,0:48:19.48,Default,,0,0,0,,其中有很多循环 相互交织 错综复杂\nDialogue: 0,0:48:20.24,0:48:26.99,Default,,0,0,0,,一方面 我不得不检查 待化简表达式的每个子表达式\nDialogue: 0,0:48:29.00,0:48:29.93,Default,,0,0,0,,我们已经讲过了\nDialogue: 0,0:48:29.93,0:48:36.24,Default,,0,0,0,,这是在car、cdr部分做某种树形递归\nDialogue: 0,0:48:37.44,0:48:38.59,Default,,0,0,0,,就是那样\nDialogue: 0,0:48:38.84,0:48:42.46,Default,,0,0,0,,现在 在我每个遍历到的结点上\nDialogue: 0,0:48:43.47,0:48:48.76,Default,,0,0,0,,也就是我想要化简的（子）表达式\nDialogue: 0,0:48:49.20,0:48:51.07,Default,,0,0,0,,我需要应用所有的规则\nDialogue: 0,0:48:53.42,0:48:55.08,Default,,0,0,0,,每个规则都需要检查每个节点\nDialogue: 0,0:48:56.00,0:48:57.92,Default,,0,0,0,,我一直在这些规则中打转（循环）\nDialogue: 0,0:49:01.66,0:49:05.48,Default,,0,0,0,,一个规则可能匹配 也可能不匹配\nDialogue: 0,0:49:07.50,0:49:10.62,Default,,0,0,0,,如果规则不匹配 那我就不关心了\nDialogue: 0,0:49:12.28,0:49:19.34,Default,,0,0,0,,如果规则匹配了 我就在那个结点用另一个表达式替换这个表达式\nDialogue: 0,0:49:20.08,0:49:22.89,Default,,0,0,0,,实际上 我创建了一个新表达式 它包含\nDialogue: 0,0:49:23.55,0:49:28.65,Default,,0,0,0,,它包含了所有的东西 新的值代换入骨架后的结果\nDialogue: 0,0:49:29.21,0:49:31.92,Default,,0,0,0,,也就是 在该层次上 把规则所对应的骨架实例化的结果\nDialogue: 0,0:49:32.72,0:49:37.37,Default,,0,0,0,,但我并不知道我所实例化出来的东西 是否是简化形式\nDialogue: 0,0:49:38.75,0:49:43.82,Default,,0,0,0,,所以我要对我刚刚构建好的东西调用化简器来简化它\nDialogue: 0,0:49:46.12,0:49:50.36,Default,,0,0,0,,完成后 我就可以将其构建进我想要的表达式中作为答案\nDialogue: 0,0:49:51.80,0:49:57.45,Default,,0,0,0,,这里的基本思想是 我们定义一个 “废料进-废料出”的化简器\nDialogue: 0,0:50:01.47,0:50:02.75,Default,,0,0,0,,它是一种递归调用的化简器\nDialogue: 0,0:50:03.58,0:50:08.84,Default,,0,0,0,,化简方法是：基本对象 比如变量就是最简形式的了\nDialogue: 0,0:50:10.78,0:50:13.28,Default,,0,0,0,,复合对象 -- 呃 我也不知道\nDialogue: 0,0:50:14.09,0:50:16.56,Default,,0,0,0,,而我要从简单的对象入手\nDialogue: 0,0:50:16.86,0:50:21.23,Default,,0,0,0,,通过假设它们都是由小块的基本对象组成的\nDialogue: 0,0:50:24.60,0:50:25.61,Default,,0,0,0,,这就是思路\nDialogue: 0,0:50:27.82,0:50:33.12,Default,,0,0,0,,现在如果我们看第一张投影\nDialogue: 0,0:50:33.88,0:50:37.13,Default,,0,0,0,,我们看到一个非常复杂的程序 就像我们之前看到的匹配器一样\nDialogue: 0,0:50:37.53,0:50:39.95,Default,,0,0,0,,它太复杂了 没有必要仔细阅读它\nDialogue: 0,0:50:41.92,0:50:43.61,Default,,0,0,0,,我只想让大家感受一下它的轮廓\nDialogue: 0,0:50:44.44,0:50:50.01,Default,,0,0,0,,也就是这个程序里面有很多子程序\nDialogue: 0,0:50:52.11,0:50:57.56,Default,,0,0,0,,这部分用于遍历表达式\nDialogue: 0,0:50:58.97,0:51:01.36,Default,,0,0,0,,这部分用于尝试规则\nDialogue: 0,0:51:02.52,0:51:05.60,Default,,0,0,0,,当然 我们也可以看看细节\nDialogue: 0,0:51:06.89,0:51:11.80,Default,,0,0,0,,来看第一张幻灯片\nDialogue: 0,0:51:13.40,0:51:17.36,Default,,0,0,0,,化简器由数个部分组成\nDialogue: 0,0:51:17.96,0:51:22.92,Default,,0,0,0,,回想一下 化简器接收一系列的规则\nDialogue: 0,0:51:23.92,0:51:27.20,Default,,0,0,0,,并生成一个使用该规则进行化简的程序\nDialogue: 0,0:51:30.04,0:51:32.60,Default,,0,0,0,,化简器在这里定义\nDialogue: 0,0:51:33.48,0:51:34.81,Default,,0,0,0,,接受一个规则集合\nDialogue: 0,0:51:36.16,0:51:38.68,Default,,0,0,0,,在the-rules被定义的上下文中\nDialogue: 0,0:51:39.24,0:51:41.48,Default,,0,0,0,,还定义了很多其它东西\nDialogue: 0,0:51:42.33,0:51:46.20,Default,,0,0,0,,而simplifier过程的返回结果则是\nDialogue: 0,0:51:46.41,0:51:50.80,Default,,0,0,0,,是一个已经定义好的过程 -- simplify-exp\nDialogue: 0,0:51:52.46,0:51:57.71,Default,,0,0,0,,调用 (simplifier the-rules) 的返回值是\nDialogue: 0,0:51:58.17,0:52:03.21,Default,,0,0,0,,返回值是一个过程 是在该上下文中定义的simplify-exp过程\nDialogue: 0,0:52:05.23,0:52:08.83,Default,,0,0,0,,这是一个利用这些给定规则进行化简的过程\nDialogue: 0,0:52:15.04,0:52:15.96,Default,,0,0,0,,定义就是这样的\nDialogue: 0,0:52:17.45,0:52:21.79,Default,,0,0,0,,这些过程的前两个 这个和这个\nDialogue: 0,0:52:22.48,0:52:25.74,Default,,0,0,0,,它们一起 递归地遍历一个表达式\nDialogue: 0,0:52:26.97,0:52:30.20,Default,,0,0,0,,这个是任何表达式的通用化简方法\nDialogue: 0,0:52:30.94,0:52:33.23,Default,,0,0,0,,而这个过程用于化简表达式的子部分\nDialogue: 0,0:52:35.53,0:52:36.08,Default,,0,0,0,,没别的了\nDialogue: 0,0:52:37.04,0:52:39.90,Default,,0,0,0,,每个过程中 我们会做些复杂操作 包括尝试这些规则\nDialogue: 0,0:52:40.32,0:52:41.71,Default,,0,0,0,,现在 我们看看这些过程\nDialogue: 0,0:52:45.76,0:52:48.08,Default,,0,0,0,,我们先来讨论一下表达式的递归遍历\nDialogue: 0,0:52:48.57,0:52:51.68,Default,,0,0,0,,这是用一种很简单的方法完成的\nDialogue: 0,0:52:54.28,0:52:57.93,Default,,0,0,0,,这是一个小型的、嵌套的递归过程\nDialogue: 0,0:52:59.42,0:53:01.77,Default,,0,0,0,,这里有两个过程 ---\nDialogue: 0,0:53:02.59,0:53:05.20,Default,,0,0,0,,一个是对整个表达式化简\nDialogue: 0,0:53:06.11,0:53:08.16,Default,,0,0,0,,另一个是对表达式的某部分化简\nDialogue: 0,0:53:09.44,0:53:10.97,Default,,0,0,0,,它们的原理都很简单\nDialogue: 0,0:53:12.12,0:53:16.86,Default,,0,0,0,,如果我想要化简的表达式是复合表达式\nDialogue: 0,0:53:17.04,0:53:18.32,Default,,0,0,0,,那么就对每一个部分进行化简\nDialogue: 0,0:53:19.95,0:53:22.32,Default,,0,0,0,,调用simplify-parts这个过程\nDialogue: 0,0:53:22.33,0:53:25.74,Default,,0,0,0,,会构造一个新的表达式 其中各个部分都是化简过的\nDialogue: 0,0:53:26.00,0:53:28.64,Default,,0,0,0,,我会在这里尝试那些应用规则\nDialogue: 0,0:53:30.86,0:53:34.22,Default,,0,0,0,,如果表达式不是复合的 而是一些简单的表达式\nDialogue: 0,0:53:34.76,0:53:37.13,Default,,0,0,0,,比如说是符号 或者'pi\nDialogue: 0,0:53:38.16,0:53:39.79,Default,,0,0,0,,无论如何 我都需要尝试应用这些规则\nDialogue: 0,0:53:40.03,0:53:47.56,Default,,0,0,0,,因为 因为可能有将pi扩展成3.14159265358979....这样的规则\nDialogue: 0,0:53:48.46,0:53:49.08,Default,,0,0,0,,也许我不会这样做\nDialogue: 0,0:53:50.11,0:53:51.52,Default,,0,0,0,,但是没有理由不这样做\nDialogue: 0,0:53:52.75,0:53:57.53,Default,,0,0,0,,现在如果我对表达式的各部分化简 那就很简单了\nDialogue: 0,0:53:58.99,0:54:02.88,Default,,0,0,0,,要么表达式是空的 它没有更多的部分了\nDialogue: 0,0:54:03.71,0:54:05.08,Default,,0,0,0,,这种情况我返回一个空表达式\nDialogue: 0,0:54:05.72,0:54:10.52,Default,,0,0,0,,否则 我用cons构建一个新的表达式\nDialogue: 0,0:54:11.21,0:54:14.27,Default,,0,0,0,,新表达式的car部分是原表达式car的化简结果\nDialogue: 0,0:54:15.42,0:54:17.39,Default,,0,0,0,,然后化简表达式的其它其他部分作为新表达式的cdr部分\nDialogue: 0,0:54:21.08,0:54:23.88,Default,,0,0,0,,我用这种方式向大家展示这些的原因是\nDialogue: 0,0:54:24.88,0:54:30.12,Default,,0,0,0,,我想让大家感受到 这些不同模式在编程时非常重要\nDialogue: 0,0:54:32.20,0:54:34.00,Default,,0,0,0,,这段程序我可以换种写法\nDialogue: 0,0:54:34.00,0:54:36.99,Default,,0,0,0,,还有一种化简表达式的方法\nDialogue: 0,0:54:37.72,0:54:39.63,Default,,0,0,0,,这仅仅是一个小程序\nDialogue: 0,0:54:39.63,0:54:42.36,Default,,0,0,0,,我把它写到黑板上 让大家感受一下\nDialogue: 0,0:54:49.71,0:54:51.90,Default,,0,0,0,,你可以用这种惯用法来写程序\nDialogue: 0,0:54:59.30,0:55:03.13,Default,,0,0,0,,那么 如何化简表达式exp呢？\nDialogue: 0,0:55:03.21,0:55:10.14,Default,,0,0,0,,在以下几种情况下 调用try-rules\nDialogue: 0,0:55:11.12,0:55:15.72,Default,,0,0,0,,就像之前一样 如果表达式是复合的\nDialogue: 0,0:55:21.52,0:55:24.27,Default,,0,0,0,,如果是复合的 我要怎么做呢?\nDialogue: 0,0:55:24.53,0:55:25.40,Default,,0,0,0,,我要化简它的每个部分\nDialogue: 0,0:55:26.01,0:55:27.80,Default,,0,0,0,,但是我已经有对cdr部分递归的过程了\nDialogue: 0,0:55:30.25,0:55:33.18,Default,,0,0,0,,一个被封装成高阶过程的通用模式\nDialogue: 0,0:55:34.09,0:55:34.46,Default,,0,0,0,,也就是map过程\nDialogue: 0,0:55:36.08,0:55:36.88,Default,,0,0,0,,我在这里写出来\nDialogue: 0,0:55:37.16,0:55:48.03,Default,,0,0,0,,(map simplify-exp exp)\nDialogue: 0,0:55:49.00,0:55:54.59,Default,,0,0,0,,这是说 把simplify-exp这个过程应用在表达式的每个部分\nDialogue: 0,0:55:55.34,0:55:57.34,Default,,0,0,0,,然后把结果用cons组合成表\nDialogue: 0,0:56:00.92,0:56:04.38,Default,,0,0,0,,所以表中的每个元素都是化简过的\nDialogue: 0,0:56:05.45,0:56:08.23,Default,,0,0,0,,不是复合表达式的话 就不用化简了\nDialogue: 0,0:56:09.05,0:56:12.36,Default,,0,0,0,,所以不需要再写一个辅助函数来化简各个部分\nDialogue: 0,0:56:12.64,0:56:13.48,Default,,0,0,0,,这句代码就够了\nDialogue: 0,0:56:15.47,0:56:17.05,Default,,0,0,0,,所以有时候可以这样写\nDialogue: 0,0:56:17.84,0:56:18.70,Default,,0,0,0,,这个无关紧要\nDialogue: 0,0:56:21.16,0:56:26.27,Default,,0,0,0,,好现在看一下 -- 如何尝试规则\nDialogue: 0,0:56:27.70,0:56:31.60,Default,,0,0,0,,这里 幻灯片上有一堆复杂的东西\nDialogue: 0,0:56:33.68,0:56:35.28,Default,,0,0,0,,我要尝试对一个表达式施用规则\nDialogue: 0,0:56:36.36,0:56:39.96,Default,,0,0,0,,我现在尝试的表达式是最初表达式的子表达式\nDialogue: 0,0:56:40.43,0:56:43.88,Default,,0,0,0,,这是因为我之前特意安排要求遍历所有子表达式\nDialogue: 0,0:56:46.11,0:56:51.90,Default,,0,0,0,,所以这里的exp 就是最初表达式的子表达式\nDialogue: 0,0:56:52.49,0:56:57.71,Default,,0,0,0,,这里我们定义一个scan的过程 它用来尝试每一个规则\nDialogue: 0,0:56:58.72,0:57:00.33,Default,,0,0,0,,我们会在整个规则中扫描\nDialogue: 0,0:57:01.92,0:57:07.77,Default,,0,0,0,,它会通过不断取cdr部分来遍历整个规则 查找一条规则来施用\nDialogue: 0,0:57:09.37,0:57:11.96,Default,,0,0,0,,当找到一条规则 它的任务就完成了\nDialogue: 0,0:57:14.09,0:57:16.41,Default,,0,0,0,,我们来看一下try-rules是如何工作的\nDialogue: 0,0:57:17.74,0:57:21.02,Default,,0,0,0,,非常简单：就是顺序地扫描规则表\nDialogue: 0,0:57:21.96,0:57:23.26,Default,,0,0,0,,它 真的简单吗？\nDialogue: 0,0:57:23.26,0:57:24.51,Default,,0,0,0,,不 这是个很庞大的程序\nDialogue: 0,0:57:25.55,0:57:28.57,Default,,0,0,0,,接收的参数是一系列的规则--它们是整个规则表的子表\nDialogue: 0,0:57:30.75,0:57:35.13,Default,,0,0,0,,我们已经查找了其中的一些 但它们都不符合 所以试试剩下的\nDialogue: 0,0:57:35.87,0:57:36.30,Default,,0,0,0,,尝试下一条\nDialogue: 0,0:57:36.40,0:57:37.63,Default,,0,0,0,,如果所有规则都尝试完了\nDialogue: 0,0:57:37.90,0:57:40.84,Default,,0,0,0,,那么 我就不能再对这个表达式做什么了 它已经是最简了\nDialogue: 0,0:57:42.35,0:57:47.26,Default,,0,0,0,,然而 如果还有规则需要扫描\nDialogue: 0,0:57:48.01,0:57:51.58,Default,,0,0,0,,那么从一个空的词典开始\nDialogue: 0,0:57:52.20,0:57:55.40,Default,,0,0,0,,用规则表中的第一条规则对表达式进行模式匹配\nDialogue: 0,0:57:57.07,0:57:58.84,Default,,0,0,0,,将得到的结果作为新的词典\nDialogue: 0,0:58:00.32,0:58:03.74,Default,,0,0,0,,如果失败了 就尝试剩余规则\nDialogue: 0,0:58:06.68,0:58:07.52,Default,,0,0,0,,这句代码就是这个意思\nDialogue: 0,0:58:08.52,0:58:10.33,Default,,0,0,0,,也就是说 丢弃那条规则\nDialogue: 0,0:58:11.10,0:58:15.05,Default,,0,0,0,,成功的话 我将取出第一条规则对应的骨架\nDialogue: 0,0:58:15.34,0:58:17.40,Default,,0,0,0,,利用得到的词典 来将其实例化\nDialogue: 0,0:58:17.93,0:58:20.80,Default,,0,0,0,,然后对结果化简 就得到了我想要的表达式\nDialogue: 0,0:58:24.20,0:58:25.96,Default,,0,0,0,,虽然这是一个复杂的程序\nDialogue: 0,0:58:26.25,0:58:28.72,Default,,0,0,0,,但是每个复杂程序都是由许多简单部分组成的\nDialogue: 0,0:58:29.77,0:58:33.12,Default,,0,0,0,,这里的递归模式非常复杂\nDialogue: 0,0:58:34.78,0:58:36.52,Default,,0,0,0,,最重要的事情就是：不要去思考它\nDialogue: 0,0:58:38.67,0:58:41.80,Default,,0,0,0,,如果去思考它的实际行为\nDialogue: 0,0:58:42.06,0:58:42.97,Default,,0,0,0,,大家就会迷惑\nDialogue: 0,0:58:45.31,0:58:45.71,Default,,0,0,0,,就算是我也会\nDialogue: 0,0:58:47.04,0:58:50.17,Default,,0,0,0,,没关系 可以多加练习\nDialogue: 0,0:58:51.52,0:58:52.46,Default,,0,0,0,,这些模式非常难\nDialogue: 0,0:58:54.17,0:58:55.42,Default,,0,0,0,,但是大家不用考虑它\nDialogue: 0,0:58:55.83,0:58:59.72,Default,,0,0,0,,关键点就是 好的编程或设计方法需要\nDialogue: 0,0:58:59.74,0:59:00.97,Default,,0,0,0,,知道什么是不需要考虑的\nDialogue: 0,0:59:03.05,0:59:06.06,Default,,0,0,0,,回到这张幻灯片上\nDialogue: 0,0:59:06.92,0:59:08.01,Default,,0,0,0,,我不需要考虑它\nDialogue: 0,0:59:08.54,0:59:13.83,Default,,0,0,0,,是因为我规定了exp化简后的结果是什么样子\nDialogue: 0,0:59:14.00,0:59:15.24,Default,,0,0,0,,我不需要知道它是如何做的\nDialogue: 0,0:59:17.08,0:59:21.24,Default,,0,0,0,,它也许是像我们这里 又是scan 又是try-rule\nDialogue: 0,0:59:22.24,0:59:24.09,Default,,0,0,0,,又或者在这里调用另一个递归程序\nDialogue: 0,0:59:24.33,0:59:25.69,Default,,0,0,0,,根据“按愿望思维” 因为我知道simplify-exp\nDialogue: 0,0:59:26.84,0:59:30.40,Default,,0,0,0,,它会返回exp化简后的结果\nDialogue: 0,0:59:31.61,0:59:32.99,Default,,0,0,0,,那么我就不需要再考虑它的具体实现了\nDialogue: 0,0:59:33.43,0:59:34.83,Default,,0,0,0,,我直接使用它\nDialogue: 0,0:59:35.07,0:59:36.43,Default,,0,0,0,,我合情合理地使用它\nDialogue: 0,0:59:36.43,0:59:37.45,Default,,0,0,0,,就会得到正确的结果\nDialogue: 0,0:59:39.95,0:59:42.57,Default,,0,0,0,,我们必须学会这种程序设计方法 -- 学会放弃\nDialogue: 0,0:59:47.56,0:59:49.05,Default,,0,0,0,,这里还有一点剩余\nDialogue: 0,0:59:50.40,0:59:54.46,Default,,0,0,0,,这里还有一些词典方面的细节\nDialogue: 0,0:59:55.08,0:59:58.32,Default,,0,0,0,,你们想知道到底词典是什么\nDialogue: 0,0:59:58.70,1:00:01.82,Default,,0,0,0,,但是我会跳过它 无可奉告\nDialogue: 0,1:00:04.14,1:00:05.20,Default,,0,0,0,,词典很简单\nDialogue: 0,1:00:06.01,1:00:09.84,Default,,0,0,0,,它是用一种被称为关联表的东西来表示的\nDialogue: 0,1:00:10.65,1:00:16.04,Default,,0,0,0,,这是一种特殊使用模式 用来在线性表中存放二维表\nDialogue: 0,1:00:16.50,1:00:20.17,Default,,0,0,0,,它们很简单 由序对构成 之前已经有同学问过了\nDialogue: 0,1:00:21.21,1:00:24.62,Default,,0,0,0,,有个特殊的过程叫做assq 用来处理这些东西\nDialogue: 0,1:00:24.94,1:00:26.36,Default,,0,0,0,,手册里面有\nDialogue: 0,1:00:27.04,1:00:28.59,Default,,0,0,0,,这个都无关紧要\nDialogue: 0,1:00:28.83,1:00:31.21,Default,,0,0,0,,重要的是如何扩充词典\nDialogue: 0,1:00:31.48,1:00:36.94,Default,,0,0,0,,要用一个模式、模式对应的数据、一本旧词典来扩充\nDialogue: 0,1:00:37.42,1:00:42.38,Default,,0,0,0,,这个模式pat 实际上是一个模式变量\nDialogue: 0,1:00:43.74,1:00:47.53,Default,,0,0,0,,我要做什么呢？我先从模式中取出模式变量的名字\nDialogue: 0,1:00:48.16,1:00:49.42,Default,,0,0,0,,把它赋给变量name\nDialogue: 0,1:00:50.44,1:00:53.71,Default,,0,0,0,,然后我按照这个名字在词典中查找是否有对应的值\nDialogue: 0,1:00:53.79,1:00:56.41,Default,,0,0,0,,如果没有 就将这对新的模式-值加入到词典中\nDialogue: 0,1:00:56.92,1:00:59.23,Default,,0,0,0,,如果已经存在一个这样名字的词条 并且有值\nDialogue: 0,1:00:59.60,1:01:03.18,Default,,0,0,0,,那dat的值最好跟已经存储的值相等\nDialogue: 0,1:01:03.88,1:01:06.54,Default,,0,0,0,,这是我心目中期待的情况\nDialogue: 0,1:01:06.89,1:01:09.15,Default,,0,0,0,,否则 置失败\nDialogue: 0,1:01:12.08,1:01:12.89,Default,,0,0,0,,所以它也很简单\nDialogue: 0,1:01:13.66,1:01:16.68,Default,,0,0,0,,打开任何一个程序 你会发现它们都是由数个个小部分组成\nDialogue: 0,1:01:17.18,1:01:18.30,Default,,0,0,0,,许多简单的小部分\nDialogue: 0,1:01:20.04,1:01:21.29,Default,,0,0,0,,我想 到目前为止\nDialogue: 0,1:01:21.60,1:01:25.68,Default,,0,0,0,,我已经告诉给你们价值百万的信息了\nDialogue: 0,1:01:28.41,1:01:30.96,Default,,0,0,0,,我想这个程序几乎已经讲完了\nDialogue: 0,1:01:31.85,1:01:32.72,Default,,0,0,0,,有什么问题么？\nDialogue: 0,1:01:34.27,1:01:38.16,Default,,0,0,0,,学生：你描述一下 化简后的表达式的规范么？\nDialogue: 0,1:01:38.72,1:01:39.02,Default,,0,0,0,,教授：好的\nDialogue: 0,1:01:39.85,1:01:44.33,Default,,0,0,0,,simplify-exp接收一个表达式 返回一个化简后的表达式\nDialogue: 0,1:01:45.28,1:01:45.77,Default,,0,0,0,,就是这样了\nDialogue: 0,1:01:48.11,1:01:50.27,Default,,0,0,0,,它的工作方式很简单\nDialogue: 0,1:01:51.60,1:01:56.09,Default,,0,0,0,,对于复合表达式 先化简各部分后 再尝试化简整体\nDialogue: 0,1:01:56.89,1:01:58.49,Default,,0,0,0,,原子表达式 就直接代规则化简\nDialogue: 0,1:01:59.52,1:02:02.11,Default,,0,0,0,,学生：是这些规则把表达式化简了么?\nDialogue: 0,1:02:02.76,1:02:03.58,Default,,0,0,0,,教授：当然\nDialogue: 0,1:02:03.76,1:02:03.90,Default,,0,0,0,,学生：好\nDialogue: 0,1:02:04.06,1:02:07.13,Default,,0,0,0,,教授：它们像你在这里看到的一样化简表达式\nDialogue: 0,1:02:08.35,1:02:11.64,Default,,0,0,0,,它先把表达式划分为小块\nDialogue: 0,1:02:12.60,1:02:17.29,Default,,0,0,0,,在化简器中使用这些规则 自下而上化简并构造表达式\nDialogue: 0,1:02:18.30,1:02:22.48,Default,,0,0,0,,处理它们 构造一个新的表达式作为结果\nDialogue: 0,1:02:24.28,1:02:29.44,Default,,0,0,0,,最后再尝试调用这些规则化简\nDialogue: 0,1:02:29.70,1:02:35.50,Default,,0,0,0,,当匹配的结果发生变化时 -- 就调用simplify-exp化简它\nDialogue: 0,1:02:35.80,1:02:40.64,Default,,0,0,0,,哦 不对是 骨架的实例化结果发生改变时\nDialogue: 0,1:02:42.00,1:02:47.36,Default,,0,0,0,,所以 规范就是 任何传入的表达式通过这些规则生成化简后的表达式\nDialogue: 0,1:02:49.84,1:02:50.76,Default,,0,0,0,,谢谢大家 下课\nDialogue: 0,1:02:53.64,1:03:06.96,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:02:53.64,1:03:06.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec4a.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: CHN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nVideo Zoom Percent: 1\nPlayResX: 640\nPlayResY: 480\nScroll Position: 0\nActive Line: 6\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:06.19,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:06.45,0:00:14.22,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}字幕&时间轴\\N邓雄飞 & S.Michael\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}后期&特效\\N邓雄飞\\N(Dysprosium)\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:06.45,0:00:14.22,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:14.83,0:00:18.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}模式匹配：基于规则的代换\nDialogue: 0,0:00:24.34,0:00:29.34,Default,,0,0,0,,教授：昨天 我们学习了一些符号操作\nDialogue: 0,0:00:29.92,0:00:35.12,Default,,0,0,0,,编写了一个非常典型的程序\nDialogue: 0,0:00:35.15,0:00:38.97,Default,,0,0,0,,来实现教材中的微积分规则\nDialogue: 0,0:00:39.61,0:00:44.59,Default,,0,0,0,,在这张幻灯片上\nDialogue: 0,0:00:44.96,0:00:48.81,Default,,0,0,0,,有一些从书中摘录的微积分规则\nDialogue: 0,0:00:49.47,0:00:54.62,Default,,0,0,0,,我们要把这些规则转化成计算机语言\nDialogue: 0,0:00:55.14,0:00:58.85,Default,,0,0,0,,当然 这种策略很有趣\nDialogue: 0,0:00:59.36,0:01:04.80,Default,,0,0,0,,但是我们为什么要把它们翻译成计算机语言呢？\nDialogue: 0,0:01:05.00,0:01:06.27,Default,,0,0,0,,我的意思是---\nDialogue: 0,0:01:06.62,0:01:11.02,Default,,0,0,0,,我们昨天写的程序非常典型\nDialogue: 0,0:01:11.21,0:01:15.98,Default,,0,0,0,,它是一个按表达式类型做分派的分情况分析语句\nDialogue: 0,0:01:16.38,0:01:18.48,Default,,0,0,0,,规则就是这样的\nDialogue: 0,0:01:19.68,0:01:21.55,Default,,0,0,0,,这里的规则是说:\nDialogue: 0,0:01:21.74,0:01:25.48,Default,,0,0,0,,我们考察的表达式如果是---\nDialogue: 0,0:01:25.48,0:01:29.42,Default,,0,0,0,,如果是常量 就做一些事情\nDialogue: 0,0:01:29.42,0:01:31.37,Default,,0,0,0,,如果是变量 就做另一件事情\nDialogue: 0,0:01:31.60,0:01:35.56,Default,,0,0,0,,如果它是常量乘以变量 就做另外的事 等等\nDialogue: 0,0:01:36.00,0:01:38.96,Default,,0,0,0,,这是一种按类型的分派\nDialogue: 0,0:01:41.40,0:01:45.16,Default,,0,0,0,,那么 既然它有如此典型的行为和结构\nDialogue: 0,0:01:45.95,0:01:49.53,Default,,0,0,0,,有没有其它方式把这个过程写得更加清晰？\nDialogue: 0,0:01:50.83,0:01:53.45,Default,,0,0,0,,首先要解决的是 这些规则是什么?\nDialogue: 0,0:01:55.56,0:01:58.50,Default,,0,0,0,,我们来好好想一下 规则有好几个部分\nDialogue: 0,0:01:58.94,0:02:02.35,Default,,0,0,0,,如果仔细观察这些规则\nDialogue: 0,0:02:03.71,0:02:04.99,Default,,0,0,0,,你就会发现\nDialogue: 0,0:02:05.12,0:02:09.69,Default,,0,0,0,,这些规则都有左右两部分\nDialogue: 0,0:02:10.36,0:02:14.36,Default,,0,0,0,,每一个规则都有左边部分和右边部分\nDialogue: 0,0:02:15.15,0:02:20.30,Default,,0,0,0,,左边部分用来与对被求导表达式做比较\nDialogue: 0,0:02:21.52,0:02:25.10,Default,,0,0,0,,右边部分用于替换原表达式\nDialogue: 0,0:02:28.49,0:02:33.10,Default,,0,0,0,,这张纸上的所有规则都可以描述成这样——\nDialogue: 0,0:02:36.51,0:02:38.06,Default,,0,0,0,,我们有许多模式\nDialogue: 0,0:02:41.48,0:02:48.30,Default,,0,0,0,,有时候 给定一个模式 我们需要为其生成一个骨架\nDialogue: 0,0:02:51.88,0:02:52.81,Default,,0,0,0,,这就是一个规则\nDialogue: 0,0:02:55.42,0:02:57.13,Default,,0,0,0,,模式是用于匹配的部分\nDialogue: 0,0:02:57.88,0:03:03.26,Default,,0,0,0,,将成功匹配的值代换到骨架里 就得到一个新的表达式\nDialogue: 0,0:03:06.46,0:03:16.32,Default,,0,0,0,,我的意思是：模式是用来匹配原表达式的\nDialogue: 0,0:03:23.72,0:03:28.51,Default,,0,0,0,,应用规则会产生一个新的表达式\nDialogue: 0,0:03:33.61,0:03:34.91,Default,,0,0,0,,我们称之为目标\nDialogue: 0,0:03:38.12,0:03:39.88,Default,,0,0,0,,这是通过骨架的实例化实现的\nDialogue: 0,0:03:41.63,0:03:43.02,Default,,0,0,0,,这个叫做实例化\nDialogue: 0,0:03:50.72,0:03:54.73,Default,,0,0,0,,这就是这些规则所描述的过程\nDialogue: 0,0:03:55.69,0:03:57.26,Default,,0,0,0,,今天我想要做的是\nDialogue: 0,0:03:58.73,0:04:01.08,Default,,0,0,0,,构建一种语言\nDialogue: 0,0:04:02.20,0:04:05.48,Default,,0,0,0,,以及它的解释与执行方法\nDialogue: 0,0:04:05.74,0:04:08.43,Default,,0,0,0,,使得这种语言可以直接表述这些规则\nDialogue: 0,0:04:10.59,0:04:11.58,Default,,0,0,0,,我们将要做的是\nDialogue: 0,0:04:11.58,0:04:17.56,Default,,0,0,0,,与其通过将规则翻译为程序 让计算机理解并执行\nDialogue: 0,0:04:18.38,0:04:21.56,Default,,0,0,0,,这里主要指 Lisp 程序\nDialogue: 0,0:04:22.16,0:04:24.49,Default,,0,0,0,,我们不如让计算机理解我们\nDialogue: 0,0:04:25.48,0:04:29.15,Default,,0,0,0,,我们可以写一些程序让计算机理解这些规则\nDialogue: 0,0:04:30.91,0:04:34.76,Default,,0,0,0,,这又稍微强调了上次的主旨\nDialogue: 0,0:04:35.44,0:04:39.36,Default,,0,0,0,,与其解决一个特定问题 不如解决一类问题\nDialogue: 0,0:04:39.77,0:04:46.72,Default,,0,0,0,,如果我为不同的数学运算写规则\nDialogue: 0,0:04:48.24,0:04:51.39,Default,,0,0,0,,比如简单代数的化简\nDialogue: 0,0:04:51.98,0:04:55.48,Default,,0,0,0,,或者三角函数运算\nDialogue: 0,0:04:56.09,0:05:01.16,Default,,0,0,0,,如果按照昨天的方法 我就得重新写个不同的程序\nDialogue: 0,0:05:01.16,0:05:05.42,Default,,0,0,0,,与之相反 我把程序中的共有逻辑给封装起来\nDialogue: 0,0:05:06.12,0:05:10.17,Default,,0,0,0,,也就是匹配、实例化等概念 还有控制结构\nDialogue: 0,0:05:10.17,0:05:12.46,Default,,0,0,0,,这都是非常复杂的事情\nDialogue: 0,0:05:13.16,0:05:18.46,Default,,0,0,0,,我想把它们从规则中分开 并封装\nDialogue: 0,0:05:20.06,0:05:22.60,Default,,0,0,0,,首先让我们看一下表示法\nDialogue: 0,0:05:22.62,0:05:24.09,Default,,0,0,0,,请大家看投影仪上的幻灯片\nDialogue: 0,0:05:24.67,0:05:25.60,Default,,0,0,0,,已经在这里了\nDialogue: 0,0:05:26.25,0:05:32.27,Default,,0,0,0,,我想要把求导的计算规则\nDialogue: 0,0:05:33.71,0:05:37.15,Default,,0,0,0,,表示为我这里写的一种简单语言\nDialogue: 0,0:05:38.11,0:05:43.29,Default,,0,0,0,,我会尽量避免去考虑语法\nDialogue: 0,0:05:44.28,0:05:49.28,Default,,0,0,0,,美化它很容易 虽然这个确实挺丑 但我并不关心\nDialogue: 0,0:05:49.30,0:05:56.41,Default,,0,0,0,,这确实不能像dx/dt那样表示\nDialogue: 0,0:05:56.76,0:05:58.12,Default,,0,0,0,,但这并不重要\nDialogue: 0,0:05:58.88,0:06:00.62,Default,,0,0,0,,这是一个偶然现象\nDialogue: 0,0:06:01.00,0:06:04.44,Default,,0,0,0,,这里 我只关心规则的结构\nDialogue: 0,0:06:04.83,0:06:11.70,Default,,0,0,0,,规则的左边部分代表了我想要匹配的求导表达式\nDialogue: 0,0:06:11.80,0:06:13.56,Default,,0,0,0,,这个表示是说\nDialogue: 0,0:06:13.60,0:06:18.32,Default,,0,0,0,,一个匹配常量的模式变量c\nDialogue: 0,0:06:18.84,0:06:21.20,Default,,0,0,0,,关于匹配任意表达式的模式变量v求导\nDialogue: 0,0:06:23.08,0:06:25.55,Default,,0,0,0,,我们在右边部分得到的是0\nDialogue: 0,0:06:26.00,0:06:28.06,Default,,0,0,0,,这就代表了一个规则\nDialogue: 0,0:06:29.26,0:06:34.04,Default,,0,0,0,,下一条规则是 匹配变量的模式变量v\nDialogue: 0,0:06:34.22,0:06:37.74,Default,,0,0,0,,对同一个模式变量求导 得到的结果是1\nDialogue: 0,0:06:38.60,0:06:42.17,Default,,0,0,0,,然而 如果一个匹配变量的模式变量u\nDialogue: 0,0:06:42.41,0:06:44.84,Default,,0,0,0,,关于另一个模式变量v求导\nDialogue: 0,0:06:45.39,0:06:47.05,Default,,0,0,0,,那么 结果就是0\nDialogue: 0,0:06:47.84,0:06:52.17,Default,,0,0,0,,我想让大家看一下 这些规则是如何组织在一起的\nDialogue: 0,0:06:52.51,0:06:54.30,Default,,0,0,0,,比如说 在这里\nDialogue: 0,0:06:54.73,0:07:01.90,Default,,0,0,0,,我们要求表达式x1、x2之和的导数\nDialogue: 0,0:07:01.90,0:07:05.85,Default,,0,0,0,,在我们创造的这个语言中\nDialogue: 0,0:07:06.88,0:07:08.62,Default,,0,0,0,,以问号开头的叫模式变量\nDialogue: 0,0:07:08.93,0:07:14.93,Default,,0,0,0,,我们就像这样来构建这些用来匹配的模式变量\nDialogue: 0,0:07:14.93,0:07:20.33,Default,,0,0,0,,这里 表达式x1加上表达式x2\nDialogue: 0,0:07:20.33,0:07:26.70,Default,,0,0,0,,对变量v求导的结果等于右边这里的式子\nDialogue: 0,0:07:26.70,0:07:32.76,Default,,0,0,0,,右边的式子是一个骨架 表示表达式X1关于变量v求导\nDialogue: 0,0:07:33.82,0:07:37.10,Default,,0,0,0,,加上表达式X2对变量v求导的和\nDialogue: 0,0:07:37.60,0:07:42.38,Default,,0,0,0,,这里的冒号表示要代换的对象\nDialogue: 0,0:07:43.63,0:07:47.23,Default,,0,0,0,,我们将它们称作“骨架求值”\nDialogue: 0,0:07:48.51,0:07:53.07,Default,,0,0,0,,让我在黑板上写一些语法\nDialogue: 0,0:07:53.23,0:07:55.56,Default,,0,0,0,,这样就能知道 在我们这门规则语言中会发生什么\nDialogue: 0,0:07:56.68,0:07:59.88,Default,,0,0,0,,首先我们要处理模式匹配问题\nDialogue: 0,0:08:06.04,0:08:13.12,Default,,0,0,0,,第一条规则是 形如foo这样的符号与其自身匹配\nDialogue: 0,0:08:23.52,0:08:31.34,Default,,0,0,0,,形如(f a b)的表达式 可以匹配这样的表\nDialogue: 0,0:08:36.30,0:08:57.02,Default,,0,0,0,,表的首元素是f、第二个元素是a、第三个元素是b\nDialogue: 0,0:08:58.62,0:09:06.99,Default,,0,0,0,,另外 模式中可能还有形如(? x)这样的规则\nDialogue: 0,0:09:08.57,0:09:18.67,Default,,0,0,0,,这个规则可以匹配任意表达式 并将其称为x\nDialogue: 0,0:09:25.45,0:09:29.98,Default,,0,0,0,,(?c x) 只匹配常量\nDialogue: 0,0:09:31.50,0:09:40.96,Default,,0,0,0,,并将匹配的常量记作x\nDialogue: 0,0:09:44.56,0:09:57.07,Default,,0,0,0,,(?v x)匹配变量 并将匹配的变量记作x\nDialogue: 0,0:10:01.66,0:10:03.80,Default,,0,0,0,,这就是我们正在构建的语言\nDialogue: 0,0:10:04.19,0:10:09.40,Default,,0,0,0,,两个对象的比较是基于元素与元素间的比较\nDialogue: 0,0:10:10.25,0:10:15.85,Default,,0,0,0,,模式中的元素可以包含这些语法变量、模式变量\nDialogue: 0,0:10:17.07,0:10:20.43,Default,,0,0,0,,它们可以用来匹配任意对象\nDialogue: 0,0:10:22.12,0:10:29.28,Default,,0,0,0,,这样 我就可以用x作为名字取得被匹配对象的值\nDialogue: 0,0:10:31.05,0:10:37.55,Default,,0,0,0,,现在 当我们为实例化准备骨架的时候\nDialogue: 0,0:10:39.50,0:10:41.40,Default,,0,0,0,,我们可能有这样的东西\nDialogue: 0,0:10:42.27,0:10:46.33,Default,,0,0,0,,符号foo实例化为它本身\nDialogue: 0,0:10:55.08,0:11:05.92,Default,,0,0,0,,形如(f a b)这样的表 实例化为\nDialogue: 0,0:11:06.36,0:11:14.75,Default,,0,0,0,,实例化为一个三元素表\nDialogue: 0,0:11:15.55,0:11:33.37,Default,,0,0,0,,其元素分别为f、a、b各自实例化后的结果\nDialogue: 0,0:11:36.35,0:11:54.27,Default,,0,0,0,,(: x) 会被实例化为x的值--也就是被匹配的模式\nDialogue: 0,0:12:03.05,0:12:10.08,Default,,0,0,0,,回头看看这里的幻灯片 我们发现这些都是对象\nDialogue: 0,0:12:10.78,0:12:16.06,Default,,0,0,0,,我们看到 这是一个用来匹配常量的模式变量\nDialogue: 0,0:12:16.56,0:12:19.02,Default,,0,0,0,,这是匹配变量的模式变量\nDialogue: 0,0:12:19.39,0:12:21.74,Default,,0,0,0,,这是匹配任意表达式的模式变量\nDialogue: 0,0:12:22.72,0:12:24.92,Default,,0,0,0,,如果我们有了名字一样的两个实例\nDialogue: 0,0:12:25.08,0:12:31.77,Default,,0,0,0,,想这个是被称作v的单变量表达式\nDialogue: 0,0:12:32.86,0:12:36.30,Default,,0,0,0,,关于一个称作v的任意表达式求导\nDialogue: 0,0:12:36.41,0:12:38.01,Default,,0,0,0,,因为这个v出现了两次\nDialogue: 0,0:12:38.65,0:12:41.07,Default,,0,0,0,,我们想约束它们相同\nDialogue: 0,0:12:42.68,0:12:45.00,Default,,0,0,0,,只有它俩完全一致才算是匹配\nDialogue: 0,0:12:45.23,0:12:47.23,Default,,0,0,0,,所以在这里我们在构建一个语言\nDialogue: 0,0:12:47.60,0:12:50.66,Default,,0,0,0,,事实上 这是一件非常好的事情\nDialogue: 0,0:12:50.66,0:12:52.60,Default,,0,0,0,,构建一个语言非常有趣\nDialogue: 0,0:12:52.60,0:12:54.33,Default,,0,0,0,,并且大家一直在做这些\nDialogue: 0,0:12:54.33,0:12:56.89,Default,,0,0,0,,大家做过的真正强大的设计\nDialogue: 0,0:12:57.23,0:13:00.20,Default,,0,0,0,,是构建一个语言来解决这样的问题\nDialogue: 0,0:13:02.06,0:13:05.34,Default,,0,0,0,,我们回头看看这些规则\nDialogue: 0,0:13:05.80,0:13:07.10,Default,,0,0,0,,这就是它们的全部\nDialogue: 0,0:13:07.10,0:13:12.43,Default,,0,0,0,,我们有加法、乘法 就像我们之前看到的一样\nDialogue: 0,0:13:12.43,0:13:17.37,Default,,0,0,0,,x1+x2 关于变量v的导数等于\nDialogue: 0,0:13:17.68,0:13:26.52,Default,,0,0,0,,x2对v求导乘以x1 加上 x1对v求导乘以x2\nDialogue: 0,0:13:27.26,0:13:29.10,Default,,0,0,0,,这是指数运算的求导规则\nDialogue: 0,0:13:29.24,0:13:32.11,Default,,0,0,0,,虽然这里展示完了所有的规则 但还可以按照我们意愿添加\nDialogue: 0,0:13:32.70,0:13:39.10,Default,,0,0,0,,我们在这里 建立了关于求导的规则列表\nDialogue: 0,0:13:40.40,0:13:44.33,Default,,0,0,0,,一旦我们有了这些 我们应该做什么呢？\nDialogue: 0,0:13:45.40,0:13:47.84,Default,,0,0,0,,恩 我将给你们展示最好的思想之一\nDialogue: 0,0:13:48.44,0:13:51.68,Default,,0,0,0,,然后我们将花一整天来鼓捣它\nDialogue: 0,0:13:52.28,0:13:57.37,Default,,0,0,0,,我将向大家展示一个叫做simplifier的程序\nDialogue: 0,0:13:57.82,0:13:59.47,Default,,0,0,0,,一个通用的化简器\nDialogue: 0,0:14:00.09,0:14:17.10,Default,,0,0,0,,我们将求导规则deriv-rules送入simplifier从而产生dsimp\nDialogue: 0,0:14:23.74,0:14:28.75,Default,,0,0,0,,传给simplifier过程一套规则 它会返回给我们一个过程\nDialogue: 0,0:14:29.32,0:14:34.59,Default,,0,0,0,,它根据这些规则对表达式进行化简\nDialogue: 0,0:14:37.39,0:14:43.93,Default,,0,0,0,,因此 这里会返回一个按照你制定的规则所构造的过程\nDialogue: 0,0:14:44.59,0:14:49.56,Default,,0,0,0,,使得在我们进入 Lisp 系统后 在命令提示符后面\nDialogue: 0,0:14:49.88,0:15:03.93,Default,,0,0,0,,输入 (DSIMP '(dd (+ x y) x))\nDialogue: 0,0:15:06.99,0:15:10.97,Default,,0,0,0,,注意这里的引号 因为我们讨论的是表达式的求导\nDialogue: 0,0:15:13.29,0:15:17.76,Default,,0,0,0,,然后我将得到结果 (+ 1 0)\nDialogue: 0,0:15:19.96,0:15:24.60,Default,,0,0,0,,因为 (x+y)' = x' + y'\nDialogue: 0,0:15:24.60,0:15:26.22,Default,,0,0,0,,x'=1\nDialogue: 0,0:15:26.38,0:15:27.82,Default,,0,0,0,,y'=0（关于x求导）\nDialogue: 0,0:15:29.42,0:15:30.46,Default,,0,0,0,,这不是我想要的\nDialogue: 0,0:15:31.18,0:15:34.65,Default,,0,0,0,,我还没有在这里做代数化简\nDialogue: 0,0:15:36.16,0:15:41.53,Default,,0,0,0,,当然一旦我有了这个东西那么我们可以 -- 我们可以看看其它的规则\nDialogue: 0,0:15:41.96,0:15:49.36,Default,,0,0,0,,比如 我们看这张幻灯片\nDialogue: 0,0:15:49.36,0:15:54.12,Default,,0,0,0,,这里是其它的规则 代数操作规则\nDialogue: 0,0:15:56.00,0:15:58.38,Default,,0,0,0,,它们可以用来化简代数表达式\nDialogue: 0,0:15:59.00,0:16:02.06,Default,,0,0,0,,考察一下这些规则\nDialogue: 0,0:16:03.04,0:16:09.20,Default,,0,0,0,,这条规则的左部分是说 某个运算符应用到常量e1和常量e2上\nDialogue: 0,0:16:09.32,0:16:14.51,Default,,0,0,0,,其结果就是求(op e1 e2)的值\nDialogue: 0,0:16:15.88,0:16:21.56,Default,,0,0,0,,或者 当一个运算符应用在任意表达式e1和常量e2上\nDialogue: 0,0:16:21.69,0:16:23.87,Default,,0,0,0,,化简结果会把常量前置\nDialogue: 0,0:16:24.52,0:16:27.68,Default,,0,0,0,,这就变成了((: op) (: e2) (: e1))\nDialogue: 0,0:16:28.59,0:16:30.11,Default,,0,0,0,,为什么要这么做？我不知道\nDialogue: 0,0:16:30.22,0:16:33.16,Default,,0,0,0,,比如说 如果系统中有除法的话 这就不对\nDialogue: 0,0:16:33.53,0:16:35.31,Default,,0,0,0,,换句话说 规则有漏洞\nDialogue: 0,0:16:36.67,0:16:40.86,Default,,0,0,0,,所以0与任何表达式e的和 等于表达式e\nDialogue: 0,0:16:42.17,0:16:45.31,Default,,0,0,0,,1乘以任何表达式e的结果是表达式e\nDialogue: 0,0:16:46.12,0:16:49.13,Default,,0,0,0,,0乘以任何表达式e的结果是0\nDialogue: 0,0:16:49.33,0:16:52.72,Default,,0,0,0,,我们可以有任意复杂的规则\nDialogue: 0,0:16:53.69,0:16:54.81,Default,,0,0,0,,比如说\nDialogue: 0,0:16:55.36,0:17:01.69,Default,,0,0,0,,常量e1*(常量e2*任意表达式e3)\nDialogue: 0,0:17:02.35,0:17:11.96,Default,,0,0,0,,可以化简为 (e1*e2)*e3\nDialogue: 0,0:17:13.36,0:17:16.76,Default,,0,0,0,,这个规则是说 先把常量组合起来\nDialogue: 0,0:17:16.76,0:17:22.70,Default,,0,0,0,,如果有形如 e1*(e2*e3) 的式子 而且e1 e2都是常量 就先把常量乘起来\nDialogue: 0,0:17:23.84,0:17:25.48,Default,,0,0,0,,你可以根据意愿来构建这些规则\nDialogue: 0,0:17:25.79,0:17:26.94,Default,,0,0,0,,这里还有很多规则\nDialogue: 0,0:17:27.42,0:17:31.04,Default,,0,0,0,,这些规则是很复杂的 比如--\nDialogue: 0,0:17:31.26,0:17:33.93,Default,,0,0,0,,请看 这条规则是分配律\nDialogue: 0,0:17:33.93,0:17:38.57,Default,,0,0,0,,任何表达式c乘以d和e\nDialogue: 0,0:17:39.02,0:17:43.66,Default,,0,0,0,,等于 c与d的积加上c与e的积\nDialogue: 0,0:17:45.31,0:17:48.67,Default,,0,0,0,,我并不关心这些规则具体描述的什么\nDialogue: 0,0:17:49.16,0:17:52.97,Default,,0,0,0,,我们将要构建一种语言 用来解释这些规则\nDialogue: 0,0:17:55.50,0:17:57.48,Default,,0,0,0,,这样我们就可以按我们的意愿编写规则\nDialogue: 0,0:17:58.35,0:18:00.14,Default,,0,0,0,,这是另外一种程序设计语言\nDialogue: 0,0:18:03.39,0:18:04.04,Default,,0,0,0,,来看看\nDialogue: 0,0:18:05.18,0:18:06.96,Default,,0,0,0,,我还没告诉你我们要怎么做\nDialogue: 0,0:18:07.53,0:18:10.06,Default,,0,0,0,,当然我们马上就要讲了\nDialogue: 0,0:18:10.89,0:18:15.40,Default,,0,0,0,,但真正的问题是：宏观地看 我要做什么？\nDialogue: 0,0:18:17.08,0:18:18.22,Default,,0,0,0,,这些规则是如何运作的？\nDialogue: 0,0:18:19.00,0:18:25.45,Default,,0,0,0,,化简程序是如何用这些规则来输入的表达式 并返回一个合理的答案？\nDialogue: 0,0:18:26.22,0:18:29.85,Default,,0,0,0,,首先 我认为我们有一大堆的规则\nDialogue: 0,0:18:32.52,0:18:34.22,Default,,0,0,0,,这里有全部的规则\nDialogue: 0,0:18:42.09,0:18:44.49,Default,,0,0,0,,这里的每一个规则 ---\nDialogue: 0,0:18:46.97,0:18:49.24,Default,,0,0,0,,都有一个模式和一个骨架\nDialogue: 0,0:18:49.72,0:18:51.36,Default,,0,0,0,,我正在努力为它作一个控制结构\nDialogue: 0,0:18:53.37,0:18:56.56,Default,,0,0,0,,我有一个匹配器\nDialogue: 0,0:19:00.99,0:19:03.76,Default,,0,0,0,,还有一个实例化器\nDialogue: 0,0:19:09.66,0:19:12.94,Default,,0,0,0,,我将把一系列模式变量的值\nDialogue: 0,0:19:14.03,0:19:17.47,Default,,0,0,0,,从匹配器中传递到实例化器中\nDialogue: 0,0:19:18.06,0:19:19.42,Default,,0,0,0,,我把传递的东西叫做词典\nDialogue: 0,0:19:20.59,0:19:21.52,Default,,0,0,0,,传递一本词典\nDialogue: 0,0:19:24.92,0:19:27.82,Default,,0,0,0,,里面记载了：x匹配下列子表达式\nDialogue: 0,0:19:29.04,0:19:31.31,Default,,0,0,0,,而y匹配另一个子表达式\nDialogue: 0,0:19:32.25,0:19:36.35,Default,,0,0,0,,我会从实例化器中构造表达式 并送入匹配器\nDialogue: 0,0:19:37.16,0:19:38.36,Default,,0,0,0,,这些是表达式\nDialogue: 0,0:19:45.00,0:19:48.41,Default,,0,0,0,,这些规则的模式将要送进匹配器中\nDialogue: 0,0:19:49.24,0:19:54.40,Default,,0,0,0,,规则对应的骨架将要送进实例化器中\nDialogue: 0,0:19:55.21,0:19:56.62,Default,,0,0,0,,现在变得有点复杂了\nDialogue: 0,0:19:57.12,0:19:59.53,Default,,0,0,0,,因为当我们处理代数表达式时\nDialogue: 0,0:20:00.44,0:20:03.60,Default,,0,0,0,,有一些规则使你能够做等价代换\nDialogue: 0,0:20:04.24,0:20:05.87,Default,,0,0,0,,这些是等价代换规则\nDialogue: 0,0:20:06.88,0:20:09.29,Default,,0,0,0,,所以需要考察表达式的所有子表达式\nDialogue: 0,0:20:11.13,0:20:15.82,Default,,0,0,0,,给定一个表达式 这些规则应该被不断应用\nDialogue: 0,0:20:16.03,0:20:19.71,Default,,0,0,0,,首先 对于传入的表达式的每个子表达式\nDialogue: 0,0:20:20.22,0:20:22.83,Default,,0,0,0,,所有的规则都需要考察一次\nDialogue: 0,0:20:24.33,0:20:27.07,Default,,0,0,0,,如果有规则匹配成功 那么就会执行这个过程\nDialogue: 0,0:20:27.30,0:20:30.63,Default,,0,0,0,,传递一本存储值的词典\nDialogue: 0,0:20:30.63,0:20:33.39,Default,,0,0,0,,实例化器产生一个新的表达式\nDialogue: 0,0:20:33.90,0:20:39.10,Default,,0,0,0,,该表达式基本上只是替换了原表达式中匹配的部分\nDialogue: 0,0:20:40.84,0:20:44.46,Default,,0,0,0,,然后 我们要对它重新检查\nDialogue: 0,0:20:44.75,0:20:48.11,Default,,0,0,0,,重新考察这些规则 看看表达式是否可以更进一步化简\nDialogue: 0,0:20:49.53,0:20:53.71,Default,,0,0,0,,然后每一个子表达式这样做 直到没有任何变化为止\nDialogue: 0,0:20:54.96,0:20:57.50,Default,,0,0,0,,你可以把它想像成一个有机过程\nDialogue: 0,0:20:57.83,0:21:00.20,Default,,0,0,0,,我们有一锅炖汤\nDialogue: 0,0:21:00.24,0:21:04.32,Default,,0,0,0,,粘乎乎的汤里面有细菌 有酶\nDialogue: 0,0:21:05.63,0:21:10.50,Default,,0,0,0,,这些酶改变了汤\nDialogue: 0,0:21:10.50,0:21:14.38,Default,,0,0,0,,它们附着在你的表达式上 改变了它 然后就走了\nDialogue: 0,0:21:15.28,0:21:17.83,Default,,0,0,0,,就像钥匙和锁一样 它们需要配对\nDialogue: 0,0:21:18.00,0:21:19.73,Default,,0,0,0,,匹配 -- 改变 -- 然后离开\nDialogue: 0,0:21:19.73,0:21:21.68,Default,,0,0,0,,你可以将其想像成一种并行过程\nDialogue: 0,0:21:22.70,0:21:24.97,Default,,0,0,0,,所以你把一个表达式放到这锅“浓汤”中\nDialogue: 0,0:21:25.80,0:21:28.00,Default,,0,0,0,,过了会儿把它拿出来 它就被简化了\nDialogue: 0,0:21:30.44,0:21:32.64,Default,,0,0,0,,它会一直变化 直到不能再变化为止\nDialogue: 0,0:21:33.36,0:21:38.33,Default,,0,0,0,,但这些酶可以附着在表达式的任何部分\nDialogue: 0,0:21:39.21,0:21:43.76,Default,,0,0,0,,课先上到这里 有问题么？\nDialogue: 0,0:21:44.92,0:21:45.36,Default,,0,0,0,,请讲\nDialogue: 0,0:21:45.43,0:21:52.76,Default,,0,0,0,,学生：匹配器和实例化器是两个独立的程序 是么?\nDialogue: 0,0:21:52.76,0:21:53.85,Default,,0,0,0,,教授：他们被拆分成很多小片\nDialogue: 0,0:21:54.14,0:21:56.60,Default,,0,0,0,,然后在一个更大的结构中组合起来\nDialogue: 0,0:21:57.26,0:21:59.13,Default,,0,0,0,,学生：先扫描并匹配\nDialogue: 0,0:21:59.61,0:22:03.21,Default,,0,0,0,,并把匹配结果传递给实例化器\nDialogue: 0,0:22:03.39,0:22:06.03,Default,,0,0,0,,实例化器做出更改 并将其返回给匹配器\nDialogue: 0,0:22:06.11,0:22:08.49,Default,,0,0,0,,教授：不是直接更改 而是生成新的表达式\nDialogue: 0,0:22:09.61,0:22:18.43,Default,,0,0,0,,新表达式中的模式变量都被左边式子中所匹配的值所替换\nDialogue: 0,0:22:18.99,0:22:23.80,Default,,0,0,0,,也就是右边式子中的那些骨架变量 或者说求值变量\nDialogue: 0,0:22:25.20,0:22:27.08,Default,,0,0,0,,学生：然后它要回传给匹配器么?\nDialogue: 0,0:22:27.20,0:22:32.32,Default,,0,0,0,,教授：然后要再进行一轮 直到表达式不再变化\nDialogue: 0,0:22:33.31,0:22:37.00,Default,,0,0,0,,学生：感觉这样递归循环似乎有些危险\nDialogue: 0,0:22:37.20,0:22:42.00,Default,,0,0,0,,教授：你说得很对 如果你定义的规则不好--\nDialogue: 0,0:22:42.00,0:22:45.53,Default,,0,0,0,,你发明的任何语言 如果它可以做任何事情\nDialogue: 0,0:22:45.72,0:22:48.40,Default,,0,0,0,,你就可能写出无限循环的程序\nDialogue: 0,0:22:49.37,0:22:55.07,Default,,0,0,0,,确实 诸如代数处理 这样的过程可能会产生无限循环\nDialogue: 0,0:23:01.05,0:23:01.52,Default,,0,0,0,,教授：请讲\nDialogue: 0,0:23:01.79,0:23:05.90,Default,,0,0,0,,学生：一些语言的设计者觉得这个特性非常重要\nDialogue: 0,0:23:05.93,0:23:12.03,Default,,0,0,0,,以至于它应该是语言的一部分 比如Scheme\nDialogue: 0,0:23:12.03,0:23:13.96,Default,,0,0,0,,你的观点是--\nDialogue: 0,0:23:13.96,0:23:15.08,Default,,0,0,0,,老师：语言的什么特性?\nDialogue: 0,0:23:15.79,0:23:17.26,Default,,0,0,0,,学生：模式匹配\nDialogue: 0,0:23:17.26,0:23:22.03,Default,,0,0,0,,所有应用的这些规则应该 ---\nDialogue: 0,0:23:22.03,0:23:23.70,Default,,0,0,0,,教授：你是说像 Prolog 那样？\nDialogue: 0,0:23:23.70,0:23:26.60,Default,,0,0,0,,学生：类似 Prolog 但更加通用的--\nDialogue: 0,0:23:26.60,0:23:27.64,Default,,0,0,0,,教授：这是可行的\nDialogue: 0,0:23:28.46,0:23:32.30,Default,,0,0,0,,好了 我是觉得吧…… 恩……\nDialogue: 0,0:23:33.16,0:23:36.49,Default,,0,0,0,,我可以教你怎么做 这样你就不用依靠语言的设计者\nDialogue: 0,0:23:40.92,0:23:42.75,Default,,0,0,0,,教授：我们可以自己来实现\nDialogue: 0,0:23:45.28,0:23:45.63,Default,,0,0,0,,下课\nDialogue: 0,0:23:45.63,0:23:50.63,Default,,0,0,0,,[音乐]\nDialogue: 0,0:23:50.63,0:23:53.13,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:23:53.13,0:23:55.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:24:00.32,0:24:06.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:24:07.07,0:24:10.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}模式匹配：基于规则的代换\nDialogue: 0,0:24:14.08,0:24:15.80,Default,,0,0,0,,好 上课\nDialogue: 0,0:24:15.80,0:24:17.21,Default,,0,0,0,,现在 我得告诉你们它是如何运作的\nDialogue: 0,0:24:20.00,0:24:24.11,Default,,0,0,0,,它很容易分成很多小份\nDialogue: 0,0:24:24.80,0:24:26.54,Default,,0,0,0,,现在 我们先看一下匹配器\nDialogue: 0,0:24:28.72,0:24:31.42,Default,,0,0,0,,匹配器的结构是像下面这样的\nDialogue: 0,0:24:32.86,0:24:45.12,Default,,0,0,0,,它是一个盒子 它的输入是一个表达式和一个模式\nDialogue: 0,0:24:52.09,0:24:53.95,Default,,0,0,0,,还有个输入是一本词典\nDialogue: 0,0:25:01.71,0:25:08.67,Default,,0,0,0,,要记住 词典把模式变量映射到匹配的值上\nDialogue: 0,0:25:09.15,0:25:11.05,Default,,0,0,0,,它的输出是另一本词典\nDialogue: 0,0:25:18.24,0:25:25.53,Default,,0,0,0,,除了旧词典中已有的内容 新词典中还产生的新的匹配\nDialogue: 0,0:25:28.00,0:25:28.83,Default,,0,0,0,,这就是匹配器\nDialogue: 0,0:25:33.87,0:25:36.54,Default,,0,0,0,,这是一个相当复杂的程序\nDialogue: 0,0:25:37.20,0:25:41.58,Default,,0,0,0,,请大家看看这里的投影 请看\nDialogue: 0,0:25:41.98,0:25:43.87,Default,,0,0,0,,哈哈 真是相当复杂\nDialogue: 0,0:25:44.43,0:25:45.87,Default,,0,0,0,,我只想让大家看一下它的轮廓\nDialogue: 0,0:25:46.78,0:25:49.85,Default,,0,0,0,,其实现细节太复杂了\nDialogue: 0,0:25:51.72,0:25:59.24,Default,,0,0,0,,然而 这是一个庞大的程序 它有很多这样的缩进的结构\nDialogue: 0,0:26:00.09,0:26:05.28,Default,,0,0,0,,在最外层 -- 不要去读这些代码  宏观地看\nDialogue: 0,0:26:05.43,0:26:10.36,Default,,0,0,0,,这里有一个分情况分析 而这些就是不同的情况\nDialogue: 0,0:26:12.09,0:26:16.19,Default,,0,0,0,,现在 我们将要深入细节\nDialogue: 0,0:26:16.67,0:26:18.60,Default,,0,0,0,,试图理解它是如何工作的\nDialogue: 0,0:26:20.08,0:26:22.35,Default,,0,0,0,,我们来看第一张幻灯片\nDialogue: 0,0:26:23.55,0:26:27.93,Default,,0,0,0,,它展示了匹配器的宏观结构\nDialogue: 0,0:26:28.81,0:26:36.33,Default,,0,0,0,,我们看到匹配器 它需要的参数有：模式、表达式和词典\nDialogue: 0,0:26:38.57,0:26:40.40,Default,,0,0,0,,这里是一个cond语句\nDialogue: 0,0:26:41.24,0:26:45.61,Default,,0,0,0,,它有许多不同情况 我们省略了一些代码\nDialogue: 0,0:26:46.62,0:26:48.62,Default,,0,0,0,,这个是我想让大家注意的 通用情况\nDialogue: 0,0:26:50.52,0:26:53.28,Default,,0,0,0,,考虑这个通用模式 它是个非常重要的模式\nDialogue: 0,0:26:56.32,0:27:01.61,Default,,0,0,0,,问题是我们需要同时地检查这两棵树\nDialogue: 0,0:27:02.50,0:27:08.03,Default,,0,0,0,,一棵树是表达式 另一棵树是模式\nDialogue: 0,0:27:08.59,0:27:10.11,Default,,0,0,0,,我们需要在它们之间进行匹配\nDialogue: 0,0:27:11.37,0:27:16.38,Default,,0,0,0,,使得表达式的子表达式会与模式的子表达式相匹配\nDialogue: 0,0:27:18.38,0:27:23.44,Default,,0,0,0,,我们深入研究一下 假设我有一个模式\nDialogue: 0,0:27:23.93,0:27:31.24,Default,,0,0,0,,这个是模式是 一个叫做x的表达式 乘以\nDialogue: 0,0:27:32.44,0:27:35.53,Default,,0,0,0,,乘以一个我们叫做y的表达式\nDialogue: 0,0:27:39.12,0:27:42.04,Default,,0,0,0,,再加上 刚才的表达式y 两个y必须是相同的表达式\nDialogue: 0,0:27:45.21,0:27:47.53,Default,,0,0,0,,我们在考察 乘式的和\nDialogue: 0,0:27:48.99,0:27:54.78,Default,,0,0,0,,其中 乘法和加法的第二个参数都是相同的\nDialogue: 0,0:27:57.02,0:27:58.84,Default,,0,0,0,,这是我们想要匹配像这样的表达式\nDialogue: 0,0:27:59.60,0:28:02.04,Default,,0,0,0,,它作为一个模式看起来像这个样子\nDialogue: 0,0:28:03.02,0:28:04.01,Default,,0,0,0,,这是一课树\nDialogue: 0,0:28:04.94,0:28:06.25,Default,,0,0,0,,它包含了一个加号\nDialogue: 0,0:28:08.08,0:28:20.25,Default,,0,0,0,,还有乘号 以及模式变量(? x)和(? y)\nDialogue: 0,0:28:21.36,0:28:22.73,Default,,0,0,0,,还有模式变量(? y)\nDialogue: 0,0:28:24.92,0:28:26.94,Default,,0,0,0,,这只是把表结构换了种写法 两者其实是一样的\nDialogue: 0,0:28:28.75,0:28:31.76,Default,,0,0,0,,我们先演示一个成功的匹配是如何运行的\nDialogue: 0,0:28:32.49,0:28:39.85,Default,,0,0,0,,这个模式匹配表达式 (+ (* 3 x) x)\nDialogue: 0,0:28:42.41,0:28:43.36,Default,,0,0,0,,这是另一棵个树\nDialogue: 0,0:28:44.33,0:28:56.06,Default,,0,0,0,,它是3乘以x的积加上x\nDialogue: 0,0:28:59.44,0:29:03.02,Default,,0,0,0,,所以我要做的是 同时遍历这两棵树\nDialogue: 0,0:29:04.41,0:29:07.82,Default,,0,0,0,,我想这样遍历它们\nDialogue: 0,0:29:08.67,0:29:12.96,Default,,0,0,0,,我会比较它们是否一样\nDialogue: 0,0:29:12.96,0:29:14.32,Default,,0,0,0,,这是一个复合对象\nDialogue: 0,0:29:15.21,0:29:17.26,Default,,0,0,0,,我们先看它的左分支\nDialogue: 0,0:29:17.26,0:29:18.14,Default,,0,0,0,,这可能是car部分\nDialogue: 0,0:29:18.56,0:29:21.21,Default,,0,0,0,,它们匹配吗？恩 两个加号成功匹配\nDialogue: 0,0:29:21.68,0:29:24.20,Default,,0,0,0,,但是下一个对象是复合的\nDialogue: 0,0:29:24.20,0:29:24.84,Default,,0,0,0,,我们看一下它\nDialogue: 0,0:29:25.20,0:29:26.80,Default,,0,0,0,,这个也匹配了\nDialogue: 0,0:29:26.80,0:29:27.79,Default,,0,0,0,,它们都是星号\nDialogue: 0,0:29:28.51,0:29:30.24,Default,,0,0,0,,现在……哦！\nDialogue: 0,0:29:30.40,0:29:33.60,Default,,0,0,0,,这是模式变量 它和3相匹配\nDialogue: 0,0:29:34.27,0:29:35.92,Default,,0,0,0,,记住 现在x等于3\nDialogue: 0,0:29:36.36,0:29:37.37,Default,,0,0,0,,把它记录在词典中\nDialogue: 0,0:29:37.56,0:29:40.73,Default,,0,0,0,,遍历过程中 词典紧随着我们 并告诉我们：x等于3\nDialogue: 0,0:29:41.45,0:29:45.87,Default,,0,0,0,,x等于3 y等于x 但这两个是不同意义上的x\nDialogue: 0,0:29:46.83,0:29:51.20,Default,,0,0,0,,那个是模式变量x 而这个是模式变量y匹配表达式x\nDialogue: 0,0:29:53.61,0:29:57.76,Default,,0,0,0,,这是模式变量y 它已经有值了 并且值是x\nDialogue: 0,0:29:58.36,0:30:00.06,Default,,0,0,0,,这是x么? 当然是\nDialogue: 0,0:30:00.06,0:30:00.75,Default,,0,0,0,,好的\nDialogue: 0,0:30:02.03,0:30:02.78,Default,,0,0,0,,完事儿了\nDialogue: 0,0:30:03.39,0:30:08.09,Default,,0,0,0,,现在 我有一本词典 它在遍历过程中不断积累\nDialogue: 0,0:30:11.42,0:30:14.51,Default,,0,0,0,,现在让我们看看这个一般情况 然后看看它如何工作\nDialogue: 0,0:30:15.88,0:30:16.51,Default,,0,0,0,,这里..\nDialogue: 0,0:30:17.20,0:30:21.66,Default,,0,0,0,,我传入一个模式 一个表达式 和一本词典\nDialogue: 0,0:30:22.38,0:30:27.50,Default,,0,0,0,,这里的情况比较复杂 -- 它是通用情况\nDialogue: 0,0:30:29.98,0:30:34.80,Default,,0,0,0,,一般来说 表达式由两部分组成：左部分和右部分\nDialogue: 0,0:30:35.45,0:30:38.81,Default,,0,0,0,,在Lisp系统中 复合对象都是由两部分组成的\nDialogue: 0,0:30:40.03,0:30:41.23,Default,,0,0,0,,现在我们有什么呢？\nDialogue: 0,0:30:41.88,0:30:48.84,Default,,0,0,0,,我将会用已有的这本词典 继续匹配模式和表达式的car部分\nDialogue: 0,0:30:50.30,0:30:53.12,Default,,0,0,0,,这个匹配过程会产生一本新词典\nDialogue: 0,0:30:54.14,0:30:57.26,Default,,0,0,0,,我将用它来匹配它们的cdr部分\nDialogue: 0,0:30:58.51,0:31:02.09,Default,,0,0,0,,这就是词典是如何在整个结构中遍历、线索的\nDialogue: 0,0:31:03.66,0:31:07.53,Default,,0,0,0,,匹配完car和cdr部分后得到的词典\nDialogue: 0,0:31:10.12,0:31:12.41,Default,,0,0,0,,会作为值返回给上级\nDialogue: 0,0:31:13.61,0:31:15.84,Default,,0,0,0,,匹配可能会在任何一个地方失败\nDialogue: 0,0:31:16.62,0:31:18.20,Default,,0,0,0,,比如说 可能会有这种情况\nDialogue: 0,0:31:18.36,0:31:27.18,Default,,0,0,0,,我们回过头来把这里改成4 这样就不会完全匹配\nDialogue: 0,0:31:29.13,0:31:34.81,Default,,0,0,0,,现在这两个不再匹配了 因为x应该\nDialogue: 0,0:31:34.93,0:31:37.34,Default,,0,0,0,,不好意思 这个y是x\nDialogue: 0,0:31:37.82,0:31:40.12,Default,,0,0,0,,但是这里的y却又是4\nDialogue: 0,0:31:40.53,0:31:43.52,Default,,0,0,0,,语法上来说 x和4显然不相同\nDialogue: 0,0:31:44.59,0:31:48.81,Default,,0,0,0,,所以这个不会匹配成功 它会拒绝 匹配会失败\nDialogue: 0,0:31:50.19,0:31:56.08,Default,,0,0,0,,那么 因为先前产生的词典会作为输入送入匹配器\nDialogue: 0,0:31:56.52,0:31:58.28,Default,,0,0,0,,所以它必须能够传播失败\nDialogue: 0,0:31:58.57,0:32:01.04,Default,,0,0,0,,第一条语句就是用来判断失败的\nDialogue: 0,0:32:03.61,0:32:08.19,Default,,0,0,0,,如果证实出来这个模式不是原子的---\nDialogue: 0,0:32:08.50,0:32:11.45,Default,,0,0,0,,如果模式是原子的 将进入这里 这里我们还没有讨论过\nDialogue: 0,0:32:12.17,0:32:13.56,Default,,0,0,0,,如果模式不是原子的\nDialogue: 0,0:32:15.05,0:32:19.23,Default,,0,0,0,,但表达式是原子--也就是它不由小部分组成\nDialogue: 0,0:32:20.14,0:32:22.65,Default,,0,0,0,,那么匹配必然失败 因此我们返回'failed\nDialogue: 0,0:32:23.64,0:32:30.78,Default,,0,0,0,,整理下思路 如果这个模式既不是原子的又不是模式变量的话 程序会来到这里\nDialogue: 0,0:32:30.96,0:32:32.51,Default,,0,0,0,,这是会使匹配失败的情况\nDialogue: 0,0:32:35.26,0:32:39.12,Default,,0,0,0,,好 让我们看这个里面的东西\nDialogue: 0,0:32:39.84,0:32:42.93,Default,,0,0,0,,首先需要知道 如果用原子模式来进行匹配会发生什么？\nDialogue: 0,0:32:42.93,0:32:43.90,Default,,0,0,0,,这简单\nDialogue: 0,0:32:43.90,0:32:46.50,Default,,0,0,0,,不是由其它模式构成的模式 比如：foo\nDialogue: 0,0:32:47.37,0:32:48.54,Default,,0,0,0,,这是个非常好的原子模式\nDialogue: 0,0:32:49.16,0:32:51.24,Default,,0,0,0,,让我们来看看\nDialogue: 0,0:32:52.08,0:32:55.82,Default,,0,0,0,,如果模式是原子的 而且表达式也原子的话\nDialogue: 0,0:32:56.80,0:33:01.85,Default,,0,0,0,,并且如果它俩是同一个东西 那么词典就跟之前一样\nDialogue: 0,0:33:03.08,0:33:04.00,Default,,0,0,0,,没有变化\nDialogue: 0,0:33:04.60,0:33:10.33,Default,,0,0,0,,就像刚才 +匹配+ *匹配* x匹配x\nDialogue: 0,0:33:11.42,0:33:12.33,Default,,0,0,0,,就是那样\nDialogue: 0,0:33:13.07,0:33:16.81,Default,,0,0,0,,然而 如何模式和表达式并不相同的话\nDialogue: 0,0:33:17.32,0:33:21.36,Default,,0,0,0,,如果这是两个不同的原子对象 比如+和*相匹配\nDialogue: 0,0:33:22.44,0:33:23.40,Default,,0,0,0,,这样就失败了\nDialogue: 0,0:33:25.60,0:33:34.56,Default,,0,0,0,,或者说 如果模式是原子 但表达式是复合 那么匹配失败\nDialogue: 0,0:33:37.40,0:33:38.24,Default,,0,0,0,,这很简单\nDialogue: 0,0:33:38.81,0:33:43.61,Default,,0,0,0,,那么 那些各种各样的模式变量又是怎么处理的呢？\nDialogue: 0,0:33:44.09,0:33:46.54,Default,,0,0,0,,我们有三类被命名了的模式变量\nDialogue: 0,0:33:47.39,0:33:52.03,Default,,0,0,0,,它们分别用于匹配：任意常量 任意变量 任意表达式\nDialogue: 0,0:33:53.82,0:34:00.14,Default,,0,0,0,,(? x) 表示匹配任意表达式\nDialogue: 0,0:34:01.18,0:34:04.54,Default,,0,0,0,,(?c x) 表示匹配任意常量\nDialogue: 0,0:34:04.73,0:34:07.29,Default,,0,0,0,,(?v x) 表示匹配任意变量\nDialogue: 0,0:34:08.96,0:34:09.79,Default,,0,0,0,,好的 我们要做什么呢?\nDialogue: 0,0:34:10.51,0:34:16.94,Default,,0,0,0,,看这里 如果模式表示的是匹配任意常量\nDialogue: 0,0:34:17.53,0:34:20.57,Default,,0,0,0,,那么待匹配的表达式最好是一个常量\nDialogue: 0,0:34:21.48,0:34:23.53,Default,,0,0,0,,不然的话 匹配就会失败\nDialogue: 0,0:34:23.83,0:34:27.50,Default,,0,0,0,,如果是一个常量 那么我就需要扩充词典\nDialogue: 0,0:34:27.50,0:34:29.69,Default,,0,0,0,,扩充词典的方法则是：\nDialogue: 0,0:34:30.70,0:34:37.76,Default,,0,0,0,,在旧词典后 附加一对模式与表达式的配对\nDialogue: 0,0:34:41.16,0:34:42.75,Default,,0,0,0,,因此 如果是匹配任意变量\nDialogue: 0,0:34:43.72,0:34:47.46,Default,,0,0,0,,我得通过匹配来核查表达式是否是变量\nDialogue: 0,0:34:47.46,0:34:50.09,Default,,0,0,0,,如果是的话 我就扩充词典\nDialogue: 0,0:34:50.38,0:34:54.65,Default,,0,0,0,,现在在原有词典基础上 我们又多了一项模式与表达式的匹配\nDialogue: 0,0:34:55.28,0:34:56.70,Default,,0,0,0,,这个过程返回一本新的词典\nDialogue: 0,0:34:58.88,0:35:04.16,Default,,0,0,0,,在这个词典中也有很多失败 因此需要检查\nDialogue: 0,0:35:04.16,0:35:07.50,Default,,0,0,0,,就比如 模式变量已经有一个值了\nDialogue: 0,0:35:09.23,0:35:16.17,Default,,0,0,0,,但我又用它匹配一个跟之前匹配的表达式不相同的表达式的话\nDialogue: 0,0:35:16.43,0:35:18.36,Default,,0,0,0,,那么在这里也会立即产生失败\nDialogue: 0,0:35:20.16,0:35:21.56,Default,,0,0,0,,我们后面再讨论\nDialogue: 0,0:35:22.91,0:35:29.36,Default,,0,0,0,,最后 匹配任意的表达式不需要在语法范畴做什么检查\nDialogue: 0,0:35:30.11,0:35:32.20,Default,,0,0,0,,只用扩充词典就行了\nDialogue: 0,0:35:34.76,0:35:38.32,Default,,0,0,0,,这就是一个完整的简单的匹配器\nDialogue: 0,0:35:39.28,0:35:41.37,Default,,0,0,0,,非常具有讽刺意味的一点是\nDialogue: 0,0:35:41.66,0:35:45.12,Default,,0,0,0,,现在 人们花了大价钱来请一些人编写\nDialogue: 0,0:35:45.46,0:35:47.52,Default,,0,0,0,,所谓的 “人工智能专家系统”\nDialogue: 0,0:35:48.40,0:35:52.03,Default,,0,0,0,,也不过是像这样的一个匹配器和实例化器罢了\nDialogue: 0,0:35:53.56,0:35:56.94,Default,,0,0,0,,这很容易做 现在你也可以创业开个小公司了\nDialogue: 0,0:35:57.42,0:36:01.72,Default,,0,0,0,,然后 第二周忽悠风投给你投个几百万\nDialogue: 0,0:36:03.79,0:36:08.57,Default,,0,0,0,,我是想说 这种程序放在20年前是非凡的\nDialogue: 0,0:36:09.74,0:36:12.81,Default,,0,0,0,,但放到现在 它就是小菜一碟了 大一新生也可以学\nDialogue: 0,0:36:13.63,0:36:15.47,Default,,0,0,0,,这里是一个实例化器\nDialogue: 0,0:36:20.22,0:36:23.07,Default,,0,0,0,,可问题是 他们都去了赚钱了 而且比我的还多\nDialogue: 0,0:36:24.97,0:36:26.59,Default,,0,0,0,,在大学中确实是这样\nDialogue: 0,0:36:27.10,0:36:39.42,Default,,0,0,0,,实例化是用来将给定的表达式、词典和骨架生成新的表达式的\nDialogue: 0,0:36:44.35,0:36:45.69,Default,,0,0,0,,这个不是很难\nDialogue: 0,0:36:46.60,0:36:53.36,Default,,0,0,0,,我们在下一张幻灯片中简单地看下\nDialogue: 0,0:36:53.88,0:36:59.29,Default,,0,0,0,,用一本给定的词典去实例化一个骨架 这很简单\nDialogue: 0,0:36:59.68,0:37:03.29,Default,,0,0,0,,我们要做的 就是对骨架递归地做树遍历\nDialogue: 0,0:37:04.08,0:37:08.33,Default,,0,0,0,,所有的骨架变量---我叫它“骨架求值”\nDialogue: 0,0:37:08.41,0:37:11.42,Default,,0,0,0,,这是我在这个程序中定义的抽象语法\nDialogue: 0,0:37:11.60,0:37:16.46,Default,,0,0,0,,在规则中 以冒号打头的就是骨架求值\nDialogue: 0,0:37:18.25,0:37:24.30,Default,,0,0,0,,在那种情况下 我要在词典中找答案 我们待会儿再讨论\nDialogue: 0,0:37:24.30,0:37:25.61,Default,,0,0,0,,我们看整体\nDialogue: 0,0:37:27.77,0:37:31.80,Default,,0,0,0,,这个过程是用一本字典来实例化一个骨架\nDialogue: 0,0:37:32.75,0:37:37.15,Default,,0,0,0,,我在这里定义一个内部循环\nDialogue: 0,0:37:38.14,0:37:39.85,Default,,0,0,0,,它要做的事情很简单\nDialogue: 0,0:37:40.17,0:37:43.50,Default,,0,0,0,,如果这个骨架是原子的\nDialogue: 0,0:37:44.60,0:37:47.45,Default,,0,0,0,,这种情况 它直接返回一个骨架作为结果\nDialogue: 0,0:37:48.84,0:37:51.87,Default,,0,0,0,,或者在通常情况下它是复合的\nDialogue: 0,0:37:52.60,0:37:59.40,Default,,0,0,0,,这种情况下 我通过一些实例化的结果构造表达式\nDialogue: 0,0:37:59.40,0:38:04.25,Default,,0,0,0,,递归调用这个循环 不断实例化骨架的car和cdr部分\nDialogue: 0,0:38:04.89,0:38:06.24,Default,,0,0,0,,这就是树的递归遍历\nDialogue: 0,0:38:08.41,0:38:14.36,Default,,0,0,0,,如果在骨架中有冒号表达式 那么这就是一个骨架求值\nDialogue: 0,0:38:14.96,0:38:22.64,Default,,0,0,0,,那么要做的事情是：找到冒号引导的表达式 -- 本例中 也就是CADR部分\nDialogue: 0,0:38:22.81,0:38:26.25,Default,,0,0,0,,这些是抽象语法 因此我能改变规则的表示\nDialogue: 0,0:38:27.52,0:38:32.73,Default,,0,0,0,,先不管求值过程如何实现 总之我要用这本词典对表达式求值\nDialogue: 0,0:38:32.90,0:38:34.65,Default,,0,0,0,,我们以后再仔细讨论\nDialogue: 0,0:38:36.12,0:38:38.35,Default,,0,0,0,,求值的结果就是答案\nDialogue: 0,0:38:39.68,0:38:43.66,Default,,0,0,0,,这条初始化语句 通过给它传递整个骨架循环来启动它\nDialogue: 0,0:38:44.44,0:38:47.04,Default,,0,0,0,,这些调用又会被分成小块的递归调用\nDialogue: 0,0:38:49.63,0:38:56.48,Default,,0,0,0,,那么 求值过程里面发生了些什么\nDialogue: 0,0:38:57.18,0:38:59.07,Default,,0,0,0,,我无法详尽地给你们解释\nDialogue: 0,0:38:59.98,0:39:01.34,Default,,0,0,0,,我就大致说一下\nDialogue: 0,0:39:01.56,0:39:03.74,Default,,0,0,0,,之后 我们再深入地讨论\nDialogue: 0,0:39:05.29,0:39:10.81,Default,,0,0,0,,在一本词典的环境下 求值一个表达式\nDialogue: 0,0:39:11.90,0:39:14.17,Default,,0,0,0,,如果表达式是原子的\nDialogue: 0,0:39:15.04,0:39:16.22,Default,,0,0,0,,就在词典中进行查找\nDialogue: 0,0:39:18.60,0:39:19.87,Default,,0,0,0,,这没啥\nDialogue: 0,0:39:20.57,0:39:23.66,Default,,0,0,0,,难点在这里\nDialogue: 0,0:39:23.83,0:39:28.28,Default,,0,0,0,,我将要应用表达式的car部分对应的一个过程\nDialogue: 0,0:39:29.44,0:39:31.68,Default,,0,0,0,,这个过程是在“某个地方”查找得到的--我们以后讨论\nDialogue: 0,0:39:32.14,0:39:34.20,Default,,0,0,0,,我想请大家注意一下 这之中有一些“魔法”\nDialogue: 0,0:39:34.67,0:39:38.72,Default,,0,0,0,,这个魔法将在不久后“施展”出来 但不是在今天\nDialogue: 0,0:39:40.00,0:39:46.51,Default,,0,0,0,,我们在词典中查找表达式剩余部分对应的值\nDialogue: 0,0:39:48.56,0:39:50.88,Default,,0,0,0,,我还不想让你们关注细节\nDialogue: 0,0:39:51.44,0:39:53.44,Default,,0,0,0,,我想让大家意识到这里还有很多代码\nDialogue: 0,0:39:54.17,0:39:56.75,Default,,0,0,0,,我们以后再详细讨论\nDialogue: 0,0:39:59.04,0:40:00.88,Default,,0,0,0,,但是 魔法就到此结束了\nDialogue: 0,0:40:02.57,0:40:06.96,Default,,0,0,0,,这部分利用Lisp的神奇力量 不过也就到此为止了\nDialogue: 0,0:40:10.25,0:40:13.56,Default,,0,0,0,,我们介绍了匹配和实例化\nDialogue: 0,0:40:15.05,0:40:16.60,Default,,0,0,0,,这一节有疑问么?\nDialogue: 0,0:40:28.10,0:40:29.80,Default,,0,0,0,,学生：我有一个问题\nDialogue: 0,0:40:29.80,0:40:30.43,Default,,0,0,0,,教授：请讲\nDialogue: 0,0:40:30.43,0:40:32.56,Default,,0,0,0,,学生：您能切到前张幻灯片上吗？\nDialogue: 0,0:40:33.60,0:40:35.56,Default,,0,0,0,,是关于定义匹配模式的\nDialogue: 0,0:40:36.16,0:40:40.76,Default,,0,0,0,,教授：好的 你想看定义匹配模式的全部的幻灯片\nDialogue: 0,0:40:40.76,0:40:43.06,Default,,0,0,0,,有人能帮我把投影仪---\nDialogue: 0,0:40:43.06,0:40:45.16,Default,,0,0,0,,这是最大的规模\nDialogue: 0,0:40:45.31,0:40:46.40,Default,,0,0,0,,你想看哪一部分？\nDialogue: 0,0:40:46.76,0:40:49.96,Default,,0,0,0,,学生：呃 最上面吧\nDialogue: 0,0:40:49.96,0:40:53.76,Default,,0,0,0,,就是传递失败的那一部分\nDialogue: 0,0:40:54.52,0:40:55.21,Default,,0,0,0,,教授：恩\nDialogue: 0,0:40:55.64,0:40:59.33,Default,,0,0,0,,学生：基本的想法是把错误返回给词典 是么?\nDialogue: 0,0:40:59.33,0:41:04.25,Default,,0,0,0,,教授：所谓的词典 就是所是匹配的答案 对吧？\nDialogue: 0,0:41:05.16,0:41:09.80,Default,,0,0,0,,要么它是一些配对\nDialogue: 0,0:41:11.07,0:41:14.03,Default,,0,0,0,,要么根本就没有配对\nDialogue: 0,0:41:14.46,0:41:14.97,Default,,0,0,0,,学生：对\nDialogue: 0,0:41:15.26,0:41:17.83,Default,,0,0,0,,教授：这里 事实上\nDialogue: 0,0:41:17.83,0:41:22.60,Default,,0,0,0,,因为一个匹配过程会向另一个匹配过程传递词典\nDialogue: 0,0:41:22.80,0:41:24.65,Default,,0,0,0,,可以在这里的一般情况中看到\nDialogue: 0,0:41:25.12,0:41:27.93,Default,,0,0,0,,这是一个匹配过程传递词典到另一个匹配过程\nDialogue: 0,0:41:28.14,0:41:34.16,Default,,0,0,0,,我是用匹配car部分得到的词典来匹配cdr部分的\nDialogue: 0,0:41:36.06,0:41:37.08,Default,,0,0,0,,这里的代码就是这个意思\nDialogue: 0,0:41:37.29,0:41:40.30,Default,,0,0,0,,正因为如此 如果对car部分的匹配失败了\nDialogue: 0,0:41:41.23,0:41:45.44,Default,,0,0,0,,匹配cdr部分的时候就有必要传播失败\nDialogue: 0,0:41:45.95,0:41:46.96,Default,,0,0,0,,第一行就是用于传播失败\nDialogue: 0,0:41:48.26,0:41:51.73,Default,,0,0,0,,学生：好 但我还是不明白匹配 --\nDialogue: 0,0:41:51.73,0:41:54.24,Default,,0,0,0,,从匹配的实例出来的是什么?\nDialogue: 0,0:41:54.73,0:41:56.00,Default,,0,0,0,,教授：有两种可能的情况\nDialogue: 0,0:41:56.33,0:41:59.15,Default,,0,0,0,,一种是符号'failed 意味匹配失败\nDialogue: 0,0:41:59.53,0:41:59.93,Default,,0,0,0,,学生：对\nDialogue: 0,0:41:59.93,0:42:03.87,Default,,0,0,0,,教授：或者是某种映射 -- 现在这还是一个抽象的东西\nDialogue: 0,0:42:04.16,0:42:05.68,Default,,0,0,0,,你需要知道它的结构\nDialogue: 0,0:42:06.49,0:42:13.96,Default,,0,0,0,,它们把匹配过程中 匹配成功的模式变量和值关联起来\nDialogue: 0,0:42:14.68,0:42:16.70,Default,,0,0,0,,学生：好 那么\nDialogue: 0,0:42:16.80,0:42:18.57,Default,,0,0,0,,教授：那是通过扩充词典实现的\nDialogue: 0,0:42:18.80,0:42:28.54,Default,,0,0,0,,学生：所以根据递归性质 如果匹配过程产生并传递了失败\nDialogue: 0,0:42:28.68,0:42:30.30,Default,,0,0,0,,那么第一种情况将捕获它\nDialogue: 0,0:42:30.40,0:42:33.56,Default,,0,0,0,,教授：并且传播它 不做任何其它处理\nDialogue: 0,0:42:33.56,0:42:34.83,Default,,0,0,0,,学生：哦 懂了\nDialogue: 0,0:42:35.50,0:42:37.36,Default,,0,0,0,,教授：这是传出失败最快的方法\nDialogue: 0,0:42:42.86,0:42:43.60,Default,,0,0,0,,请讲\nDialogue: 0,0:42:43.84,0:42:47.23,Default,,0,0,0,,学生：如果没有失败 那意味着我匹配了一个模式\nDialogue: 0,0:42:47.84,0:42:53.00,Default,,0,0,0,,我会扩充词典并且传递表达式中的模式\nDialogue: 0,0:42:55.21,0:42:58.43,Default,,0,0,0,,但是 代换并不是发生在这 对吧？\nDialogue: 0,0:42:58.43,0:42:59.03,Default,,0,0,0,,是吧？\nDialogue: 0,0:42:59.03,0:42:59.46,Default,,0,0,0,,教授：你是对的\nDialogue: 0,0:42:59.46,0:43:02.40,Default,,0,0,0,,这里没有可供代换的骨架 因此不会发生代换\nDialogue: 0,0:43:02.40,0:43:03.06,Default,,0,0,0,,学生：好 那么\nDialogue: 0,0:43:03.06,0:43:07.16,Default,,0,0,0,,教授：我们这里所做的 是为后面的代换准备词典\nDialogue: 0,0:43:08.25,0:43:12.43,Default,,0,0,0,,学生：词典的数据结构是什么呢？是有序对么？\nDialogue: 0,0:43:12.72,0:43:15.96,Default,,0,0,0,,教授：那个 那个还没有告诉你\nDialogue: 0,0:43:15.96,0:43:16.89,Default,,0,0,0,,它还是一个抽象的东西\nDialogue: 0,0:43:17.06,0:43:17.56,Default,,0,0,0,,学生：哦\nDialogue: 0,0:43:17.56,0:43:18.90,Default,,0,0,0,,教授：你为什么要知道呢?\nDialogue: 0,0:43:18.90,0:43:21.64,Default,,0,0,0,,它是一个函数 仅仅是一个函数\nDialogue: 0,0:43:21.69,0:43:22.33,Default,,0,0,0,,学生：我想知道它的原因是--\nDialogue: 0,0:43:22.33,0:43:24.17,Default,,0,0,0,,教授：这个抽象函数表现地像有序对\nDialogue: 0,0:43:25.12,0:43:28.44,Default,,0,0,0,,它可以用一系列的表通过链接来实现\nDialogue: 0,0:43:29.06,0:43:32.43,Default,,0,0,0,,它也可以用一些酷炫的表机制来实现\nDialogue: 0,0:43:32.56,0:43:34.16,Default,,0,0,0,,它也可以实现为一个函数\nDialogue: 0,0:43:35.80,0:43:37.40,Default,,0,0,0,,我可以把它写成一个函数\nDialogue: 0,0:43:39.02,0:43:39.87,Default,,0,0,0,,但我不会告诉你具体细节\nDialogue: 0,0:43:40.84,0:43:43.08,Default,,0,0,0,,这是George的事情 由他来构建这个结构\nDialogue: 0,0:43:49.56,0:43:52.06,Default,,0,0,0,,我知道 你特别想知道它的具体结构\nDialogue: 0,0:43:52.36,0:43:54.19,Default,,0,0,0,,但我不打算让你那么做\nDialogue: 0,0:43:54.43,0:43:59.23,Default,,0,0,0,,学生：恩 最后一个问题 扩充到词典中的重要信息是什么?\nDialogue: 0,0:43:59.74,0:44:02.08,Default,,0,0,0,,我想 可能是匹配发现的模式\nDialogue: 0,0:44:02.73,0:44:04.83,Default,,0,0,0,,教授：是的 那些与表达式相匹配的模式\nDialogue: 0,0:44:04.83,0:44:09.30,Default,,0,0,0,,我们想要得到模式 只不过在本例中这些都是模式变量 对吧？\nDialogue: 0,0:44:09.85,0:44:12.89,Default,,0,0,0,,这三种扩充词典的情况都是模式变量\nDialogue: 0,0:44:13.20,0:44:13.50,Default,,0,0,0,,学生：恩\nDialogue: 0,0:44:14.48,0:44:18.75,Default,,0,0,0,,教授：所以 在词典就有一个模式变量与一个值对应\nDialogue: 0,0:44:19.45,0:44:22.11,Default,,0,0,0,,这个值是所匹配的表达式\nDialogue: 0,0:44:23.31,0:44:29.63,Default,,0,0,0,,词典就是遍历过程中记录下来的所有匹配\nDialogue: 0,0:44:30.54,0:44:34.41,Default,,0,0,0,,我会以原有词典为基础 创建一本新词典\nDialogue: 0,0:44:35.12,0:44:38.35,Default,,0,0,0,,新增的内容就是新发现的匹配\nDialogue: 0,0:44:39.98,0:44:43.73,Default,,0,0,0,,学生：我不理解为什么不能在发现匹配后立即进行代换\nDialogue: 0,0:44:43.73,0:44:44.80,Default,,0,0,0,,教授：哦 那时候还不能代换\nDialogue: 0,0:44:44.81,0:44:46.62,Default,,0,0,0,,因为我不知道骨架啊！\nDialogue: 0,0:44:47.58,0:44:49.66,Default,,0,0,0,,模式和匹配器都是独立的单元\nDialogue: 0,0:44:49.66,0:44:51.00,Default,,0,0,0,,学生：哦 我明白了\nDialogue: 0,0:44:51.00,0:44:51.50,Default,,0,0,0,,教授：懂了吧？\nDialogue: 0,0:44:51.50,0:44:51.90,Default,,0,0,0,,学生：恩\nDialogue: 0,0:44:51.90,0:44:57.23,Default,,0,0,0,,教授：我用这个匹配器进行匹配 如果匹配了就可以实例化\nDialogue: 0,0:44:58.20,0:44:59.50,Default,,0,0,0,,学生：知道了\nDialogue: 0,0:45:00.54,0:45:03.88,Default,,0,0,0,,学生：您可以再求解一次黑板上的例子么\nDialogue: 0,0:45:04.89,0:45:06.93,Default,,0,0,0,,什么东西返回给了匹配器\nDialogue: 0,0:45:06.93,0:45:08.00,Default,,0,0,0,,教授：当然可以\nDialogue: 0,0:45:08.26,0:45:09.74,Default,,0,0,0,,来看这个例子\nDialogue: 0,0:45:10.67,0:45:15.45,Default,,0,0,0,,在这里当我遍历这个结构的时候 我遇到了(? x)\nDialogue: 0,0:45:16.67,0:45:20.54,Default,,0,0,0,,我有一本词典 不过此时假设它是空的\nDialogue: 0,0:45:21.56,0:45:25.36,Default,,0,0,0,,一本空词典 然后我匹配到了x为3\nDialogue: 0,0:45:26.62,0:45:33.60,Default,,0,0,0,,从此以后 词典中就记录了 x与3匹配 对吧\nDialogue: 0,0:45:33.64,0:45:36.09,Default,,0,0,0,,继续遍历 然后遇到(? y)\nDialogue: 0,0:45:36.89,0:45:39.20,Default,,0,0,0,,它是一个特殊的x 这是模式变量x\nDialogue: 0,0:45:39.79,0:45:41.37,Default,,0,0,0,,我看到(? y) 模式变量y\nDialogue: 0,0:45:42.17,0:45:47.74,Default,,0,0,0,,词典说 模式变量y的值是符号x\nDialogue: 0,0:45:48.99,0:45:51.20,Default,,0,0,0,,因为这里已经匹配过了\nDialogue: 0,0:45:52.43,0:45:54.52,Default,,0,0,0,,所以此时 词典中包含两个条目\nDialogue: 0,0:45:55.45,0:45:59.90,Default,,0,0,0,,模式变量x是数字3 模式变量y是表达式x\nDialogue: 0,0:46:01.95,0:46:04.11,Default,,0,0,0,,现在继续进行遍历\nDialogue: 0,0:46:04.23,0:46:07.45,Default,,0,0,0,,这里 模式变量y想要和4匹配\nDialogue: 0,0:46:08.06,0:46:10.65,Default,,0,0,0,,但是这个不可能 产生失败\nDialogue: 0,0:46:14.30,0:46:15.48,Default,,0,0,0,,谢谢 下课\nDialogue: 0,0:46:16.76,0:46:25.02,Default,,0,0,0,,[音乐]\nDialogue: 0,0:46:25.07,0:46:27.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:27.47,0:46:30.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教\nDialogue: 0,0:46:48.19,0:46:54.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:55.20,0:46:58.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}模式匹配：基于规则的代换\nDialogue: 0,0:47:02.38,0:47:05.68,Default,,0,0,0,,这是大家首次看到如此庞大而复杂的程序\nDialogue: 0,0:47:07.34,0:47:09.90,Default,,0,0,0,,当然 本项课程的目的之一就在于\nDialogue: 0,0:47:09.90,0:47:12.97,Default,,0,0,0,,是让大家可以读懂这么庞大的程序 而完全不用害怕它\nDialogue: 0,0:47:13.76,0:47:16.33,Default,,0,0,0,,这个程序仅仅只有4页代码而已\nDialogue: 0,0:47:17.08,0:47:19.23,Default,,0,0,0,,课程结业后 我希望就算是50页长的程序\nDialogue: 0,0:47:20.27,0:47:21.80,Default,,0,0,0,,也吓不倒你们\nDialogue: 0,0:47:22.97,0:47:28.20,Default,,0,0,0,,我不是说让你们“左耳朵进 右耳朵出”地读程序\nDialogue: 0,0:47:29.20,0:47:31.70,Default,,0,0,0,,你应该体会这个程序\nDialogue: 0,0:47:31.70,0:47:34.83,Default,,0,0,0,,然后好好思考 因为它是一个很大的程序\nDialogue: 0,0:47:35.32,0:47:38.92,Default,,0,0,0,,在这个程序中有很多东西\nDialogue: 0,0:47:41.24,0:47:46.03,Default,,0,0,0,,我已经介绍了我们正在实现的 -- 基于规则代换的模式匹配语言\nDialogue: 0,0:47:46.81,0:47:47.64,Default,,0,0,0,,给你们看了一些规则\nDialogue: 0,0:47:48.36,0:47:51.24,Default,,0,0,0,,我已经告诉大家匹配和实例化\nDialogue: 0,0:47:51.55,0:47:53.32,Default,,0,0,0,,它们是使规则生效的“阴阳两极”\nDialogue: 0,0:47:54.24,0:47:56.35,Default,,0,0,0,,现在我们需要理解控制结构\nDialogue: 0,0:47:56.86,0:48:00.32,Default,,0,0,0,,就是这些规则是如何被用在表达式上\nDialogue: 0,0:48:01.08,0:48:03.84,Default,,0,0,0,,来指导代数化简的\nDialogue: 0,0:48:06.92,0:48:09.58,Default,,0,0,0,,这也是非常复杂的\nDialogue: 0,0:48:12.09,0:48:19.48,Default,,0,0,0,,其中有很多循环 相互交织 错综复杂\nDialogue: 0,0:48:20.24,0:48:26.99,Default,,0,0,0,,一方面 我不得不检查 待化简表达式的每个子表达式\nDialogue: 0,0:48:29.00,0:48:29.93,Default,,0,0,0,,我们已经讲过了\nDialogue: 0,0:48:29.93,0:48:36.24,Default,,0,0,0,,这是在car、cdr部分做某种树形递归\nDialogue: 0,0:48:37.44,0:48:38.59,Default,,0,0,0,,就是那样\nDialogue: 0,0:48:38.84,0:48:42.46,Default,,0,0,0,,现在 在我每个遍历到的结点上\nDialogue: 0,0:48:43.47,0:48:48.76,Default,,0,0,0,,也就是我想要化简的（子）表达式\nDialogue: 0,0:48:49.20,0:48:51.07,Default,,0,0,0,,我需要应用所有的规则\nDialogue: 0,0:48:53.42,0:48:55.08,Default,,0,0,0,,每个规则都需要检查每个节点\nDialogue: 0,0:48:56.00,0:48:57.92,Default,,0,0,0,,我一直在这些规则中打转（循环）\nDialogue: 0,0:49:01.66,0:49:05.48,Default,,0,0,0,,一个规则可能匹配 也可能不匹配\nDialogue: 0,0:49:07.50,0:49:10.62,Default,,0,0,0,,如果规则不匹配 那我就不关心了\nDialogue: 0,0:49:12.28,0:49:19.34,Default,,0,0,0,,如果规则匹配了 我就在那个结点用另一个表达式替换这个表达式\nDialogue: 0,0:49:20.08,0:49:22.89,Default,,0,0,0,,实际上 我创建了一个新表达式 它包含\nDialogue: 0,0:49:23.55,0:49:28.65,Default,,0,0,0,,它包含了所有的东西 新的值代换入骨架后的结果\nDialogue: 0,0:49:29.21,0:49:31.92,Default,,0,0,0,,也就是 在该层次上 把规则所对应的骨架实例化的结果\nDialogue: 0,0:49:32.72,0:49:37.37,Default,,0,0,0,,但我并不知道我所实例化出来的东西 是否是简化形式\nDialogue: 0,0:49:38.75,0:49:43.82,Default,,0,0,0,,所以我要对我刚刚构建好的东西调用化简器来简化它\nDialogue: 0,0:49:46.12,0:49:50.36,Default,,0,0,0,,完成后 我就可以将其构建进我想要的表达式中作为答案\nDialogue: 0,0:49:51.80,0:49:57.45,Default,,0,0,0,,这里的基本思想是 我们定义一个 “废料进-废料出”的化简器\nDialogue: 0,0:50:01.47,0:50:02.75,Default,,0,0,0,,它是一种递归调用的化简器\nDialogue: 0,0:50:03.58,0:50:08.84,Default,,0,0,0,,化简方法是：基本对象 比如变量就是最简形式的了\nDialogue: 0,0:50:10.78,0:50:13.28,Default,,0,0,0,,复合对象 -- 呃 我也不知道\nDialogue: 0,0:50:14.09,0:50:16.56,Default,,0,0,0,,而我要从简单的对象入手\nDialogue: 0,0:50:16.86,0:50:21.23,Default,,0,0,0,,通过假设它们都是由小块的基本对象组成的\nDialogue: 0,0:50:24.60,0:50:25.61,Default,,0,0,0,,这就是思路\nDialogue: 0,0:50:27.82,0:50:33.12,Default,,0,0,0,,现在如果我们看第一张投影\nDialogue: 0,0:50:33.88,0:50:37.13,Default,,0,0,0,,我们看到一个非常复杂的程序 就像我们之前看到的匹配器一样\nDialogue: 0,0:50:37.53,0:50:39.95,Default,,0,0,0,,它太复杂了 没有必要仔细阅读它\nDialogue: 0,0:50:41.92,0:50:43.61,Default,,0,0,0,,我只想让大家感受一下它的轮廓\nDialogue: 0,0:50:44.44,0:50:50.01,Default,,0,0,0,,也就是这个程序里面有很多子程序\nDialogue: 0,0:50:52.11,0:50:57.56,Default,,0,0,0,,这部分用于遍历表达式\nDialogue: 0,0:50:58.97,0:51:01.36,Default,,0,0,0,,这部分用于尝试规则\nDialogue: 0,0:51:02.52,0:51:05.60,Default,,0,0,0,,当然 我们也可以看看细节\nDialogue: 0,0:51:06.89,0:51:11.80,Default,,0,0,0,,来看第一张幻灯片\nDialogue: 0,0:51:13.40,0:51:17.36,Default,,0,0,0,,化简器由数个部分组成\nDialogue: 0,0:51:17.96,0:51:22.92,Default,,0,0,0,,回想一下 化简器接收一系列的规则\nDialogue: 0,0:51:23.92,0:51:27.20,Default,,0,0,0,,并生成一个使用该规则进行化简的程序\nDialogue: 0,0:51:30.04,0:51:32.60,Default,,0,0,0,,化简器在这里定义\nDialogue: 0,0:51:33.48,0:51:34.81,Default,,0,0,0,,接受一个规则集合\nDialogue: 0,0:51:36.16,0:51:38.68,Default,,0,0,0,,在the-rules被定义的上下文中\nDialogue: 0,0:51:39.24,0:51:41.48,Default,,0,0,0,,还定义了很多其它东西\nDialogue: 0,0:51:42.33,0:51:46.20,Default,,0,0,0,,而simplifier过程的返回结果则是\nDialogue: 0,0:51:46.41,0:51:50.80,Default,,0,0,0,,是一个已经定义好的过程 -- simplify-exp\nDialogue: 0,0:51:52.46,0:51:57.71,Default,,0,0,0,,调用 (simplifier the-rules) 的返回值是\nDialogue: 0,0:51:58.17,0:52:03.21,Default,,0,0,0,,返回值是一个过程 是在该上下文中定义的simplify-exp过程\nDialogue: 0,0:52:05.23,0:52:08.83,Default,,0,0,0,,这是一个利用这些给定规则进行化简的过程\nDialogue: 0,0:52:15.04,0:52:15.96,Default,,0,0,0,,定义就是这样的\nDialogue: 0,0:52:17.45,0:52:21.79,Default,,0,0,0,,这些过程的前两个 这个和这个\nDialogue: 0,0:52:22.48,0:52:25.74,Default,,0,0,0,,它们一起 递归地遍历一个表达式\nDialogue: 0,0:52:26.97,0:52:30.20,Default,,0,0,0,,这个是任何表达式的通用化简方法\nDialogue: 0,0:52:30.94,0:52:33.23,Default,,0,0,0,,而这个过程用于化简表达式的子部分\nDialogue: 0,0:52:35.53,0:52:36.08,Default,,0,0,0,,没别的了\nDialogue: 0,0:52:37.04,0:52:39.90,Default,,0,0,0,,每个过程中 我们会做些复杂操作 包括尝试这些规则\nDialogue: 0,0:52:40.32,0:52:41.71,Default,,0,0,0,,现在 我们看看这些过程\nDialogue: 0,0:52:45.76,0:52:48.08,Default,,0,0,0,,我们先来讨论一下表达式的递归遍历\nDialogue: 0,0:52:48.57,0:52:51.68,Default,,0,0,0,,这是用一种很简单的方法完成的\nDialogue: 0,0:52:54.28,0:52:57.93,Default,,0,0,0,,这是一个小型的、嵌套的递归过程\nDialogue: 0,0:52:59.42,0:53:01.77,Default,,0,0,0,,这里有两个过程 ---\nDialogue: 0,0:53:02.59,0:53:05.20,Default,,0,0,0,,一个是对整个表达式化简\nDialogue: 0,0:53:06.11,0:53:08.16,Default,,0,0,0,,另一个是对表达式的某部分化简\nDialogue: 0,0:53:09.44,0:53:10.97,Default,,0,0,0,,它们的原理都很简单\nDialogue: 0,0:53:12.12,0:53:16.86,Default,,0,0,0,,如果我想要化简的表达式是复合表达式\nDialogue: 0,0:53:17.04,0:53:18.32,Default,,0,0,0,,那么就对每一个部分进行化简\nDialogue: 0,0:53:19.95,0:53:22.32,Default,,0,0,0,,调用simplify-parts这个过程\nDialogue: 0,0:53:22.33,0:53:25.74,Default,,0,0,0,,会构造一个新的表达式 其中各个部分都是化简过的\nDialogue: 0,0:53:26.00,0:53:28.64,Default,,0,0,0,,我会在这里尝试那些应用规则\nDialogue: 0,0:53:30.86,0:53:34.22,Default,,0,0,0,,如果表达式不是复合的 而是一些简单的表达式\nDialogue: 0,0:53:34.76,0:53:37.13,Default,,0,0,0,,比如说是符号 或者'pi\nDialogue: 0,0:53:38.16,0:53:39.79,Default,,0,0,0,,无论如何 我都需要尝试应用这些规则\nDialogue: 0,0:53:40.03,0:53:47.56,Default,,0,0,0,,因为 因为可能有将pi扩展成3.14159265358979....这样的规则\nDialogue: 0,0:53:48.46,0:53:49.08,Default,,0,0,0,,也许我不会这样做\nDialogue: 0,0:53:50.11,0:53:51.52,Default,,0,0,0,,但是没有理由不这样做\nDialogue: 0,0:53:52.75,0:53:57.53,Default,,0,0,0,,现在如果我对表达式的各部分化简 那就很简单了\nDialogue: 0,0:53:58.99,0:54:02.88,Default,,0,0,0,,要么表达式是空的 它没有更多的部分了\nDialogue: 0,0:54:03.71,0:54:05.08,Default,,0,0,0,,这种情况我返回一个空表达式\nDialogue: 0,0:54:05.72,0:54:10.52,Default,,0,0,0,,否则 我用cons构建一个新的表达式\nDialogue: 0,0:54:11.21,0:54:14.27,Default,,0,0,0,,新表达式的car部分是原表达式car的化简结果\nDialogue: 0,0:54:15.42,0:54:17.39,Default,,0,0,0,,然后化简表达式的其它其他部分作为新表达式的cdr部分\nDialogue: 0,0:54:21.08,0:54:23.88,Default,,0,0,0,,我用这种方式向大家展示这些的原因是\nDialogue: 0,0:54:24.88,0:54:30.12,Default,,0,0,0,,我想让大家感受到 这些不同模式在编程时非常重要\nDialogue: 0,0:54:32.20,0:54:34.00,Default,,0,0,0,,这段程序我可以换种写法\nDialogue: 0,0:54:34.00,0:54:36.99,Default,,0,0,0,,还有一种化简表达式的方法\nDialogue: 0,0:54:37.72,0:54:39.63,Default,,0,0,0,,这仅仅是一个小程序\nDialogue: 0,0:54:39.63,0:54:42.36,Default,,0,0,0,,我把它写到黑板上 让大家感受一下\nDialogue: 0,0:54:49.71,0:54:51.90,Default,,0,0,0,,你可以用这种惯用法来写程序\nDialogue: 0,0:54:59.30,0:55:03.13,Default,,0,0,0,,那么 如何化简表达式exp呢？\nDialogue: 0,0:55:03.21,0:55:10.14,Default,,0,0,0,,在以下几种情况下 调用try-rules\nDialogue: 0,0:55:11.12,0:55:15.72,Default,,0,0,0,,就像之前一样 如果表达式是复合的\nDialogue: 0,0:55:21.52,0:55:24.27,Default,,0,0,0,,如果是复合的 我要怎么做呢?\nDialogue: 0,0:55:24.53,0:55:25.40,Default,,0,0,0,,我要化简它的每个部分\nDialogue: 0,0:55:26.01,0:55:27.80,Default,,0,0,0,,但是我已经有对cdr部分递归的过程了\nDialogue: 0,0:55:30.25,0:55:33.18,Default,,0,0,0,,一个被封装成高阶过程的通用模式\nDialogue: 0,0:55:34.09,0:55:34.46,Default,,0,0,0,,也就是map过程\nDialogue: 0,0:55:36.08,0:55:36.88,Default,,0,0,0,,我在这里写出来\nDialogue: 0,0:55:37.16,0:55:48.03,Default,,0,0,0,,(map simplify-exp exp)\nDialogue: 0,0:55:49.00,0:55:54.59,Default,,0,0,0,,这是说 把simplify-exp这个过程应用在表达式的每个部分\nDialogue: 0,0:55:55.34,0:55:57.34,Default,,0,0,0,,然后把结果用cons组合成表\nDialogue: 0,0:56:00.92,0:56:04.38,Default,,0,0,0,,所以表中的每个元素都是化简过的\nDialogue: 0,0:56:05.45,0:56:08.23,Default,,0,0,0,,不是复合表达式的话 就不用化简了\nDialogue: 0,0:56:09.05,0:56:12.36,Default,,0,0,0,,所以不需要再写一个辅助函数来化简各个部分\nDialogue: 0,0:56:12.64,0:56:13.48,Default,,0,0,0,,这句代码就够了\nDialogue: 0,0:56:15.47,0:56:17.05,Default,,0,0,0,,所以有时候可以这样写\nDialogue: 0,0:56:17.84,0:56:18.70,Default,,0,0,0,,这个无关紧要\nDialogue: 0,0:56:21.16,0:56:26.27,Default,,0,0,0,,好现在看一下 -- 如何尝试规则\nDialogue: 0,0:56:27.70,0:56:31.60,Default,,0,0,0,,这里 幻灯片上有一堆复杂的东西\nDialogue: 0,0:56:33.68,0:56:35.28,Default,,0,0,0,,我要尝试对一个表达式施用规则\nDialogue: 0,0:56:36.36,0:56:39.96,Default,,0,0,0,,我现在尝试的表达式是最初表达式的子表达式\nDialogue: 0,0:56:40.43,0:56:43.88,Default,,0,0,0,,这是因为我之前特意安排要求遍历所有子表达式\nDialogue: 0,0:56:46.11,0:56:51.90,Default,,0,0,0,,所以这里的exp 就是最初表达式的子表达式\nDialogue: 0,0:56:52.49,0:56:57.71,Default,,0,0,0,,这里我们定义一个scan的过程 它用来尝试每一个规则\nDialogue: 0,0:56:58.72,0:57:00.33,Default,,0,0,0,,我们会在整个规则中扫描\nDialogue: 0,0:57:01.92,0:57:07.77,Default,,0,0,0,,它会通过不断取cdr部分来遍历整个规则 查找一条规则来施用\nDialogue: 0,0:57:09.37,0:57:11.96,Default,,0,0,0,,当找到一条规则 它的任务就完成了\nDialogue: 0,0:57:14.09,0:57:16.41,Default,,0,0,0,,我们来看一下try-rules是如何工作的\nDialogue: 0,0:57:17.74,0:57:21.02,Default,,0,0,0,,非常简单：就是顺序地扫描规则表\nDialogue: 0,0:57:21.96,0:57:23.26,Default,,0,0,0,,它 真的简单吗？\nDialogue: 0,0:57:23.26,0:57:24.51,Default,,0,0,0,,不 这是个很庞大的程序\nDialogue: 0,0:57:25.55,0:57:28.57,Default,,0,0,0,,接收的参数是一系列的规则--它们是整个规则表的子表\nDialogue: 0,0:57:30.75,0:57:35.13,Default,,0,0,0,,我们已经查找了其中的一些 但它们都不符合 所以试试剩下的\nDialogue: 0,0:57:35.87,0:57:36.30,Default,,0,0,0,,尝试下一条\nDialogue: 0,0:57:36.40,0:57:37.63,Default,,0,0,0,,如果所有规则都尝试完了\nDialogue: 0,0:57:37.90,0:57:40.84,Default,,0,0,0,,那么 我就不能再对这个表达式做什么了 它已经是最简了\nDialogue: 0,0:57:42.35,0:57:47.26,Default,,0,0,0,,然而 如果还有规则需要扫描\nDialogue: 0,0:57:48.01,0:57:51.58,Default,,0,0,0,,那么从一个空的词典开始\nDialogue: 0,0:57:52.20,0:57:55.40,Default,,0,0,0,,用规则表中的第一条规则对表达式进行模式匹配\nDialogue: 0,0:57:57.07,0:57:58.84,Default,,0,0,0,,将得到的结果作为新的词典\nDialogue: 0,0:58:00.32,0:58:03.74,Default,,0,0,0,,如果失败了 就尝试剩余规则\nDialogue: 0,0:58:06.68,0:58:07.52,Default,,0,0,0,,这句代码就是这个意思\nDialogue: 0,0:58:08.52,0:58:10.33,Default,,0,0,0,,也就是说 丢弃那条规则\nDialogue: 0,0:58:11.10,0:58:15.05,Default,,0,0,0,,成功的话 我将取出第一条规则对应的骨架\nDialogue: 0,0:58:15.34,0:58:17.40,Default,,0,0,0,,利用得到的词典 来将其实例化\nDialogue: 0,0:58:17.93,0:58:20.80,Default,,0,0,0,,然后对结果化简 就得到了我想要的表达式\nDialogue: 0,0:58:24.20,0:58:25.96,Default,,0,0,0,,虽然这是一个复杂的程序\nDialogue: 0,0:58:26.25,0:58:28.72,Default,,0,0,0,,但是每个复杂程序都是由许多简单部分组成的\nDialogue: 0,0:58:29.77,0:58:33.12,Default,,0,0,0,,这里的递归模式非常复杂\nDialogue: 0,0:58:34.78,0:58:36.52,Default,,0,0,0,,最重要的事情就是：不要去思考它\nDialogue: 0,0:58:38.67,0:58:41.80,Default,,0,0,0,,如果去思考它的实际行为\nDialogue: 0,0:58:42.06,0:58:42.97,Default,,0,0,0,,大家就会迷惑\nDialogue: 0,0:58:45.31,0:58:45.71,Default,,0,0,0,,就算是我也会\nDialogue: 0,0:58:47.04,0:58:50.17,Default,,0,0,0,,没关系 可以多加练习\nDialogue: 0,0:58:51.52,0:58:52.46,Default,,0,0,0,,这些模式非常难\nDialogue: 0,0:58:54.17,0:58:55.42,Default,,0,0,0,,但是大家不用考虑它\nDialogue: 0,0:58:55.83,0:58:59.72,Default,,0,0,0,,关键点就是 好的编程或设计方法需要\nDialogue: 0,0:58:59.74,0:59:00.97,Default,,0,0,0,,知道什么是不需要考虑的\nDialogue: 0,0:59:03.05,0:59:06.06,Default,,0,0,0,,回到这张幻灯片上\nDialogue: 0,0:59:06.92,0:59:08.01,Default,,0,0,0,,我不需要考虑它\nDialogue: 0,0:59:08.54,0:59:13.83,Default,,0,0,0,,是因为我规定了exp化简后的结果是什么样子\nDialogue: 0,0:59:14.00,0:59:15.24,Default,,0,0,0,,我不需要知道它是如何做的\nDialogue: 0,0:59:17.08,0:59:21.24,Default,,0,0,0,,它也许是像我们这里 又是scan 又是try-rule\nDialogue: 0,0:59:22.24,0:59:24.09,Default,,0,0,0,,又或者在这里调用另一个递归程序\nDialogue: 0,0:59:24.33,0:59:25.69,Default,,0,0,0,,根据“按愿望思维” 因为我知道simplify-exp\nDialogue: 0,0:59:26.84,0:59:30.40,Default,,0,0,0,,它会返回exp化简后的结果\nDialogue: 0,0:59:31.61,0:59:32.99,Default,,0,0,0,,那么我就不需要再考虑它的具体实现了\nDialogue: 0,0:59:33.43,0:59:34.83,Default,,0,0,0,,我直接使用它\nDialogue: 0,0:59:35.07,0:59:36.43,Default,,0,0,0,,我合情合理地使用它\nDialogue: 0,0:59:36.43,0:59:37.45,Default,,0,0,0,,就会得到正确的结果\nDialogue: 0,0:59:39.95,0:59:42.57,Default,,0,0,0,,我们必须学会这种程序设计方法 -- 学会放弃\nDialogue: 0,0:59:47.56,0:59:49.05,Default,,0,0,0,,这里还有一点剩余\nDialogue: 0,0:59:50.40,0:59:54.46,Default,,0,0,0,,这里还有一些词典方面的细节\nDialogue: 0,0:59:55.08,0:59:58.32,Default,,0,0,0,,你们想知道到底词典是什么\nDialogue: 0,0:59:58.70,1:00:01.82,Default,,0,0,0,,但是我会跳过它 无可奉告\nDialogue: 0,1:00:04.14,1:00:05.20,Default,,0,0,0,,词典很简单\nDialogue: 0,1:00:06.01,1:00:09.84,Default,,0,0,0,,它是用一种被称为关联表的东西来表示的\nDialogue: 0,1:00:10.65,1:00:16.04,Default,,0,0,0,,这是一种特殊使用模式 用来在线性表中存放二维表\nDialogue: 0,1:00:16.50,1:00:20.17,Default,,0,0,0,,它们很简单 由序对构成 之前已经有同学问过了\nDialogue: 0,1:00:21.21,1:00:24.62,Default,,0,0,0,,有个特殊的过程叫做assq 用来处理这些东西\nDialogue: 0,1:00:24.94,1:00:26.36,Default,,0,0,0,,手册里面有\nDialogue: 0,1:00:27.04,1:00:28.59,Default,,0,0,0,,这个都无关紧要\nDialogue: 0,1:00:28.83,1:00:31.21,Default,,0,0,0,,重要的是如何扩充词典\nDialogue: 0,1:00:31.48,1:00:36.94,Default,,0,0,0,,要用一个模式、模式对应的数据、一本旧词典来扩充\nDialogue: 0,1:00:37.42,1:00:42.38,Default,,0,0,0,,这个模式pat 实际上是一个模式变量\nDialogue: 0,1:00:43.74,1:00:47.53,Default,,0,0,0,,我要做什么呢？我先从模式中取出模式变量的名字\nDialogue: 0,1:00:48.16,1:00:49.42,Default,,0,0,0,,把它赋给变量name\nDialogue: 0,1:00:50.44,1:00:53.71,Default,,0,0,0,,然后我按照这个名字在词典中查找是否有对应的值\nDialogue: 0,1:00:53.79,1:00:56.41,Default,,0,0,0,,如果没有 就将这对新的模式-值加入到词典中\nDialogue: 0,1:00:56.92,1:00:59.23,Default,,0,0,0,,如果已经存在一个这样名字的词条 并且有值\nDialogue: 0,1:00:59.60,1:01:03.18,Default,,0,0,0,,那dat的值最好跟已经存储的值相等\nDialogue: 0,1:01:03.88,1:01:06.54,Default,,0,0,0,,这是我心目中期待的情况\nDialogue: 0,1:01:06.89,1:01:09.15,Default,,0,0,0,,否则 置失败\nDialogue: 0,1:01:12.08,1:01:12.89,Default,,0,0,0,,所以它也很简单\nDialogue: 0,1:01:13.66,1:01:16.68,Default,,0,0,0,,打开任何一个程序 你会发现它们都是由数个个小部分组成\nDialogue: 0,1:01:17.18,1:01:18.30,Default,,0,0,0,,许多简单的小部分\nDialogue: 0,1:01:20.04,1:01:21.29,Default,,0,0,0,,我想 到目前为止\nDialogue: 0,1:01:21.60,1:01:25.68,Default,,0,0,0,,我已经告诉给你们价值百万的信息了\nDialogue: 0,1:01:28.41,1:01:30.96,Default,,0,0,0,,我想这个程序几乎已经讲完了\nDialogue: 0,1:01:31.85,1:01:32.72,Default,,0,0,0,,有什么问题么？\nDialogue: 0,1:01:34.27,1:01:38.16,Default,,0,0,0,,学生：你描述一下 化简后的表达式的规范么？\nDialogue: 0,1:01:38.72,1:01:39.02,Default,,0,0,0,,教授：好的\nDialogue: 0,1:01:39.85,1:01:44.33,Default,,0,0,0,,simplify-exp接收一个表达式 返回一个化简后的表达式\nDialogue: 0,1:01:45.28,1:01:45.77,Default,,0,0,0,,就是这样了\nDialogue: 0,1:01:48.11,1:01:50.27,Default,,0,0,0,,它的工作方式很简单\nDialogue: 0,1:01:51.60,1:01:56.09,Default,,0,0,0,,对于复合表达式 先化简各部分后 再尝试化简整体\nDialogue: 0,1:01:56.89,1:01:58.49,Default,,0,0,0,,原子表达式 就直接代规则化简\nDialogue: 0,1:01:59.52,1:02:02.11,Default,,0,0,0,,学生：是这些规则把表达式化简了么?\nDialogue: 0,1:02:02.76,1:02:03.58,Default,,0,0,0,,教授：当然\nDialogue: 0,1:02:03.76,1:02:03.90,Default,,0,0,0,,学生：好\nDialogue: 0,1:02:04.06,1:02:07.13,Default,,0,0,0,,教授：它们像你在这里看到的一样化简表达式\nDialogue: 0,1:02:08.35,1:02:11.64,Default,,0,0,0,,它先把表达式划分为小块\nDialogue: 0,1:02:12.60,1:02:17.29,Default,,0,0,0,,在化简器中使用这些规则 自下而上化简并构造表达式\nDialogue: 0,1:02:18.30,1:02:22.48,Default,,0,0,0,,处理它们 构造一个新的表达式作为结果\nDialogue: 0,1:02:24.28,1:02:29.44,Default,,0,0,0,,最后再尝试调用这些规则化简\nDialogue: 0,1:02:29.70,1:02:35.50,Default,,0,0,0,,当匹配的结果发生变化时 -- 就调用simplify-exp化简它\nDialogue: 0,1:02:35.80,1:02:40.64,Default,,0,0,0,,哦 不对是 骨架的实例化结果发生改变时\nDialogue: 0,1:02:42.00,1:02:47.36,Default,,0,0,0,,所以 规范就是 任何传入的表达式通过这些规则生成化简后的表达式\nDialogue: 0,1:02:49.84,1:02:50.76,Default,,0,0,0,,谢谢大家 下课\nDialogue: 0,1:02:53.64,1:03:06.96,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:02:53.64,1:03:06.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec4a.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.0.4\n; http://www.aegisub.org/\nTitle: EN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nCollisions: Normal\nVideo Zoom Percent: 1\nScroll Position: 0\nActive Line: 0\nVideo Zoom Percent: 0.65\nPlayResX: 640\nPlayResY: 480\nYCbCr Matrix: TV.601\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:22.34,EN,,0,0,0,,\nDialogue: 0,0:00:22.34,0:00:24.34,EN,,0,0,0,,Pattern-matching: Rule-based Substitution\nDialogue: 0,0:00:24.34,0:00:29.34,EN,,0,0,0,,PROFESSOR: Well, yesterday we learned a bit about symbolic manipulation,\nDialogue: 0,0:00:29.92,0:00:35.12,EN,,0,0,0,,and we wrote a rather stylized program\nDialogue: 0,0:00:35.15,0:00:38.97,EN,,0,0,0,,to implement a pile of calculus rule from the calculus book.\nDialogue: 0,0:00:39.61,0:00:44.59,EN,,0,0,0,,Here on the transparencies,\nDialogue: 0,0:00:44.96,0:00:48.81,EN,,0,0,0,,we see a bunch of calculus rules from such a book.\nDialogue: 0,0:00:49.47,0:00:54.62,EN,,0,0,0,,And, of course, what we did is sort of translate these rules into the language of the computer.\nDialogue: 0,0:00:55.14,0:00:58.85,EN,,0,0,0,,But, of course, that's a sort of funny strategy.\nDialogue: 0,0:00:59.36,0:01:04.80,EN,,0,0,0,,Why should we have to translate these rules into the language of the computer?\nDialogue: 0,0:01:05.00,0:01:06.27,EN,,0,0,0,,And what do I really mean by that?\nDialogue: 0,0:01:06.62,0:01:11.02,EN,,0,0,0,,These are--the program we wrote yesterday was very stylized.\nDialogue: 0,0:01:11.21,0:01:15.98,EN,,0,0,0,,It was a conditional, a dispatch on the type of the expression\nDialogue: 0,0:01:16.38,0:01:18.48,EN,,0,0,0,,as observed by the rules.\nDialogue: 0,0:01:19.68,0:01:21.55,EN,,0,0,0,,What we see here are rules that say\nDialogue: 0,0:01:21.74,0:01:25.48,EN,,0,0,0,,if the object being the derivative is being taken of,\nDialogue: 0,0:01:25.48,0:01:29.42,EN,,0,0,0,,if that expression is a constant, then do one thing.\nDialogue: 0,0:01:29.42,0:01:31.37,EN,,0,0,0,,If it's a variable, do another thing.\nDialogue: 0,0:01:31.60,0:01:35.56,EN,,0,0,0,,If it's a product of a constant times a variable, do something and so on.\nDialogue: 0,0:01:36.00,0:01:38.96,EN,,0,0,0,,There's sort of a dispatch there on a type.\nDialogue: 0,0:01:41.40,0:01:45.16,EN,,0,0,0,,Well, since it has such a stylized behavior and structure,\nDialogue: 0,0:01:45.95,0:01:49.53,EN,,0,0,0,,is there some other way of writing this program that's more clear?\nDialogue: 0,0:01:50.83,0:01:53.45,EN,,0,0,0,,Well, what's a rule, first of all, What are these rules?\nDialogue: 0,0:01:55.56,0:01:58.50,EN,,0,0,0,,Let's think about that. Rules have parts.\nDialogue: 0,0:01:58.94,0:02:02.35,EN,,0,0,0,,If you look at these rules in detail,\nDialogue: 0,0:02:03.71,0:02:04.99,EN,,0,0,0,,what you see, for example,\nDialogue: 0,0:02:05.12,0:02:09.69,EN,,0,0,0,,is the rule has a left-hand side and a right-hand side.\nDialogue: 0,0:02:10.36,0:02:14.36,EN,,0,0,0,,Each of these rules has a left-hand side and the right-hand side.\nDialogue: 0,0:02:15.15,0:02:20.30,EN,,0,0,0,,The left-hand side is somehow compared with the expression you're trying to take the derivative of.\nDialogue: 0,0:02:21.52,0:02:25.10,EN,,0,0,0,,The right-hand side is the replacement for that expression.\nDialogue: 0,0:02:28.49,0:02:33.10,EN,,0,0,0,,So all rules on this page are something like this.\nDialogue: 0,0:02:36.51,0:02:38.06,EN,,0,0,0,,I have patterns,\nDialogue: 0,0:02:41.48,0:02:48.30,EN,,0,0,0,,and somehow, I have to produce, given a pattern, a skeleton.\nDialogue: 0,0:02:51.88,0:02:52.81,EN,,0,0,0,,This is a rule.\nDialogue: 0,0:02:55.42,0:02:57.13,EN,,0,0,0,,A pattern is something that matches,\nDialogue: 0,0:02:57.88,0:03:03.26,EN,,0,0,0,,and a skeleton is something you substitute into in order to get a new expression.\nDialogue: 0,0:03:06.46,0:03:16.32,EN,,0,0,0,,So what that means is that the pattern is matched against the expression, which is the source expression.\nDialogue: 0,0:03:23.72,0:03:28.51,EN,,0,0,0,,And the result of the application of the rule is to produce a new expression,\nDialogue: 0,0:03:33.61,0:03:34.91,EN,,0,0,0,,which I'll call a target,\nDialogue: 0,0:03:38.12,0:03:39.88,EN,,0,0,0,,by instantiation of a skeleton.\nDialogue: 0,0:03:41.63,0:03:43.02,EN,,0,0,0,,That's called instantiation.\nDialogue: 0,0:03:50.72,0:03:54.73,EN,,0,0,0,,So that is the process by which these rules are described.\nDialogue: 0,0:03:55.69,0:03:57.26,EN,,0,0,0,,What I'd like to do today\nDialogue: 0,0:03:58.73,0:04:01.08,EN,,0,0,0,,is build a language\nDialogue: 0,0:04:02.20,0:04:05.48,EN,,0,0,0,,and a means of interpreting that language, a means of executing that language,\nDialogue: 0,0:04:05.74,0:04:08.43,EN,,0,0,0,,where that language allows us to directly express these rules.\nDialogue: 0,0:04:10.59,0:04:11.58,EN,,0,0,0,,And what we're going to do\nDialogue: 0,0:04:11.58,0:04:17.56,EN,,0,0,0,,instead of bringing the rules to the level of the computer by writing a program that is those rules\nDialogue: 0,0:04:18.38,0:04:21.56,EN,,0,0,0,,in the computer's language--at the moment, in a Lisp--\nDialogue: 0,0:04:22.16,0:04:24.49,EN,,0,0,0,,we're going to bring the computer to the level of us\nDialogue: 0,0:04:25.48,0:04:29.15,EN,,0,0,0,,by writing a way by which the computer can understand rules of this sort.\nDialogue: 0,0:04:30.91,0:04:34.76,EN,,0,0,0,,This is slightly emphasizing the idea that we had last time\nDialogue: 0,0:04:35.44,0:04:39.36,EN,,0,0,0,,that we're trying to make a solution to a class of problems rather than a particular one.\nDialogue: 0,0:04:39.77,0:04:46.72,EN,,0,0,0,,The problem is if I want to write rules for a different piece of mathematics,\nDialogue: 0,0:04:48.24,0:04:51.39,EN,,0,0,0,,say, to simple algebraic simplification or something like that,\nDialogue: 0,0:04:51.98,0:04:55.48,EN,,0,0,0,,or manipulation of trigonometric functions,\nDialogue: 0,0:04:56.09,0:05:01.16,EN,,0,0,0,,I would have to write a different program in using yesterday's method.\nDialogue: 0,0:05:01.16,0:05:05.42,EN,,0,0,0,,Whereas I would like to encapsulate all of the things that are common to both of those programs,\nDialogue: 0,0:05:06.12,0:05:10.17,EN,,0,0,0,,meaning the idea of matching, instantiation, the control structure,\nDialogue: 0,0:05:10.17,0:05:12.46,EN,,0,0,0,,which turns out to be very complicated for such a thing,\nDialogue: 0,0:05:13.16,0:05:18.46,EN,,0,0,0,,I'd like to encapsulate that separately from the rules themselves.\nDialogue: 0,0:05:20.06,0:05:22.60,EN,,0,0,0,,So let's look at, first of all, a representation.\nDialogue: 0,0:05:22.62,0:05:24.09,EN,,0,0,0,,I'd like to use the overhead here.\nDialogue: 0,0:05:24.67,0:05:25.60,EN,,0,0,0,,I'd like-- there it is.\nDialogue: 0,0:05:26.25,0:05:32.27,EN,,0,0,0,,I'd like to look at a representation of the rules of calculus for derivatives\nDialogue: 0,0:05:33.71,0:05:37.15,EN,,0,0,0,,in a sort of simple language that I'm writing right here.\nDialogue: 0,0:05:38.11,0:05:43.29,EN,,0,0,0,,Now, I'm going to avoid--I'm going to avoid worrying about syntax.\nDialogue: 0,0:05:44.28,0:05:49.28,EN,,0,0,0,,We can easily pretty this, and I'm not interested in making-- this is indeed ugly.\nDialogue: 0,0:05:49.30,0:05:56.41,EN,,0,0,0,,This doesn't look like the beautiful text set dx by dt or something that I'd like to write,\nDialogue: 0,0:05:56.76,0:05:58.12,EN,,0,0,0,,but that's not essential.\nDialogue: 0,0:05:58.88,0:06:00.62,EN,,0,0,0,,That's sort of an accidental phenomenon.\nDialogue: 0,0:06:01.00,0:06:04.44,EN,,0,0,0,,Here, we're just worrying about the fact that the structure of the rules\nDialogue: 0,0:06:04.83,0:06:11.70,EN,,0,0,0,,is that there is a left-hand side here, represents the thing I want to match against the derivative expression.\nDialogue: 0,0:06:11.80,0:06:13.56,EN,,0,0,0,,This is the representation I'm going to say\nDialogue: 0,0:06:13.60,0:06:18.32,EN,,0,0,0,,for the derivative of a constant, which we will call c\nDialogue: 0,0:06:18.84,0:06:21.20,EN,,0,0,0,,respect to the variable we will call v.\nDialogue: 0,0:06:23.08,0:06:25.55,EN,,0,0,0,,And what we will get on the right-hand side is 0.\nDialogue: 0,0:06:26.00,0:06:28.06,EN,,0,0,0,,So this represents a rule.\nDialogue: 0,0:06:29.26,0:06:34.04,EN,,0,0,0,,The next rule will be the derivative of a variable, which we will call v\nDialogue: 0,0:06:34.22,0:06:37.74,EN,,0,0,0,,respect to the same variable v, and we get a 1.\nDialogue: 0,0:06:38.60,0:06:42.17,EN,,0,0,0,,However, if we have the derivative of a variable called u\nDialogue: 0,0:06:42.41,0:06:44.84,EN,,0,0,0,,respect to a different variables v,\nDialogue: 0,0:06:45.39,0:06:47.05,EN,,0,0,0,,we will get 0.\nDialogue: 0,0:06:47.84,0:06:52.17,EN,,0,0,0,,I just want you look at these rules a little bit and see how they fit together.\nDialogue: 0,0:06:52.51,0:06:54.30,EN,,0,0,0,,For example, over here,\nDialogue: 0,0:06:54.73,0:07:01.90,EN,,0,0,0,,we're going to have the derivative of the sum of an expression called x1 and an expression called x2.\nDialogue: 0,0:07:01.90,0:07:05.85,EN,,0,0,0,,These things that begin with question marks are called pattern variables\nDialogue: 0,0:07:06.88,0:07:08.62,EN,,0,0,0,,in the language that we're inventing,\nDialogue: 0,0:07:08.93,0:07:14.93,EN,,0,0,0,,and you see we're just making it up, so pattern variables for matching.\nDialogue: 0,0:07:14.93,0:07:20.33,EN,,0,0,0,,And so in this-- here we have the derivative of the sum of the expression which we will call x1.\nDialogue: 0,0:07:20.33,0:07:26.70,EN,,0,0,0,,And the expression we will call x2 with respect to the variable we call v will be-- here is the right-hand side:\nDialogue: 0,0:07:26.70,0:07:32.76,EN,,0,0,0,,the sum of the derivative of  that expression x1 with respect to v-- the right-hand side is the skeleton--\nDialogue: 0,0:07:33.82,0:07:37.10,EN,,0,0,0,,and the derivative of x2 with respect to v.\nDialogue: 0,0:07:37.60,0:07:42.38,EN,,0,0,0,,Colons here will stand for substitution objects.\nDialogue: 0,0:07:43.63,0:07:47.23,EN,,0,0,0,,They're--we'll call them skeleton evaluations.\nDialogue: 0,0:07:48.51,0:07:53.07,EN,,0,0,0,,So let me put up here on the blackboard for a second some syntax\nDialogue: 0,0:07:53.23,0:07:55.56,EN,,0,0,0,,so we'll know what's going on for this rule language.\nDialogue: 0,0:07:56.68,0:07:59.88,EN,,0,0,0,,First of all, we're going to have to worry about the pattern matching.\nDialogue: 0,0:08:06.04,0:08:13.12,EN,,0,0,0,,We're going to have things like a symbol like foo matches exactly itself.\nDialogue: 0,0:08:23.52,0:08:31.34,EN,,0,0,0,,The expression f of a and b will be used to match any list\nDialogue: 0,0:08:36.30,0:08:57.02,EN,,0,0,0,,whose first element is f, whose second element is a, and whose third element is b.\nDialogue: 0,0:08:58.62,0:09:06.99,EN,,0,0,0,,Also, another thing we might have in a pattern is that--a question mark with some variable like x.\nDialogue: 0,0:09:08.57,0:09:18.67,EN,,0,0,0,,And what that means, it says matches anything, which we will call x.\nDialogue: 0,0:09:25.45,0:09:29.98,EN,,0,0,0,,Question mark c x will match only constants.\nDialogue: 0,0:09:31.50,0:09:40.96,EN,,0,0,0,,So this is something which matches a constant called x.\nDialogue: 0,0:09:44.56,0:09:57.07,EN,,0,0,0,,And question mark v x will match a variable, which we call x.\nDialogue: 0,0:10:01.66,0:10:03.80,EN,,0,0,0,,This is sort of the language we're making up now.\nDialogue: 0,0:10:04.19,0:10:09.40,EN,,0,0,0,,If I match two things against each other, then they are compared element by element\nDialogue: 0,0:10:10.25,0:10:15.85,EN,,0,0,0,,But elements in the pattern may contain these syntactic variables,\nDialogue: 0,0:10:17.07,0:10:20.43,EN,,0,0,0,,which will be used to match arbitrary objects.\nDialogue: 0,0:10:22.12,0:10:29.28,EN,,0,0,0,,And we'll get that object as the value in the name x here, for example.\nDialogue: 0,0:10:31.05,0:10:37.55,EN,,0,0,0,,Now, when we make skeletons for instantiation.\nDialogue: 0,0:10:39.50,0:10:41.40,EN,,0,0,0,,Well, then we have things like this.\nDialogue: 0,0:10:42.27,0:10:46.33,EN,,0,0,0,,foo, a symbol, instantiates to itself.\nDialogue: 0,0:10:55.08,0:11:05.92,EN,,0,0,0,,Something which is a list like f of a and b, instantiates to--\nDialogue: 0,0:11:06.36,0:11:14.75,EN,,0,0,0,,well, f instantiates to a  3-list, a list of three elements,\nDialogue: 0,0:11:15.55,0:11:33.37,EN,,0,0,0,,okay, which are the results of instantiating each of f, a, and b.\nDialogue: 0,0:11:36.35,0:11:54.27,EN,,0,0,0,,And x well--we instantiate to the value of x as in the matched pattern.\nDialogue: 0,0:12:03.05,0:12:10.08,EN,,0,0,0,,So going back to the overhead here, we see -- we see that all of those kinds of objects\nDialogue: 0,0:12:10.78,0:12:16.06,EN,,0,0,0,,we see here a pattern variable which matches a constant,\nDialogue: 0,0:12:16.56,0:12:19.02,EN,,0,0,0,,a pattern variable which matches a variable,\nDialogue: 0,0:12:19.39,0:12:21.74,EN,,0,0,0,,a pattern variable which will match anything.\nDialogue: 0,0:12:22.72,0:12:24.92,EN,,0,0,0,,And if we have two instances of the same name,\nDialogue: 0,0:12:25.08,0:12:31.77,EN,,0,0,0,,like this is the derivative of the expression which is a variable only whose name will be v\nDialogue: 0,0:12:32.86,0:12:36.30,EN,,0,0,0,,with respect to some arbitrary expression which we will call v,\nDialogue: 0,0:12:36.41,0:12:38.01,EN,,0,0,0,,since this v appears twice,\nDialogue: 0,0:12:38.65,0:12:41.07,EN,,0,0,0,,we're going to want that to mean they have to be the same.\nDialogue: 0,0:12:42.68,0:12:45.00,EN,,0,0,0,,The only consistent match is that those are the same.\nDialogue: 0,0:12:45.23,0:12:47.23,EN,,0,0,0,,So here, we're making up a language.\nDialogue: 0,0:12:47.60,0:12:50.66,EN,,0,0,0,,And in fact, that's a very nice thing to be doing.\nDialogue: 0,0:12:50.66,0:12:52.60,EN,,0,0,0,,It's so much fun to make up a language.\nDialogue: 0,0:12:52.60,0:12:54.33,EN,,0,0,0,,And you do this all the time.\nDialogue: 0,0:12:54.33,0:12:56.89,EN,,0,0,0,,And the really most powerful design things you ever do\nDialogue: 0,0:12:57.23,0:13:00.20,EN,,0,0,0,,are sort of making up a language to solve problems like this.\nDialogue: 0,0:13:02.06,0:13:05.34,EN,,0,0,0,,Now, here we go back here and look at some of these rules.\nDialogue: 0,0:13:05.80,0:13:07.10,EN,,0,0,0,,Well, there's a whole set of them.\nDialogue: 0,0:13:07.10,0:13:12.43,EN,,0,0,0,,I mean, there's one for addition and one for multiplication, just like we had before.\nDialogue: 0,0:13:12.43,0:13:17.37,EN,,0,0,0,,The derivative of the product of x1 and x2 with respect to v is\nDialogue: 0,0:13:17.68,0:13:26.52,EN,,0,0,0,,the sum of the product of x1 and the derivative x2 with respect to v and the product of the derivative of x1 and x2.\nDialogue: 0,0:13:27.26,0:13:29.10,EN,,0,0,0,,And here we have exponentiation.\nDialogue: 0,0:13:29.24,0:13:32.11,EN,,0,0,0,,And, of course, we run off the end down here. We get as many as we like.\nDialogue: 0,0:13:32.70,0:13:39.10,EN,,0,0,0,,But the whole thing over here, I'm giving this--this list of rules the name \"derivative rules.\"\nDialogue: 0,0:13:40.40,0:13:44.33,EN,,0,0,0,,What would we do with such a thing once we have it?\nDialogue: 0,0:13:45.40,0:13:47.84,EN,,0,0,0,,Well, one of the nicest ideas, first of all,\nDialogue: 0,0:13:48.44,0:13:51.68,EN,,0,0,0,,is I'm going to write for you, and we're going to play with it all day.\nDialogue: 0,0:13:52.28,0:13:57.37,EN,,0,0,0,,What I'm going to write for you is a program called simplifier,\nDialogue: 0,0:13:57.82,0:13:59.47,EN,,0,0,0,,the general-purpose simplifier.\nDialogue: 0,0:14:00.09,0:14:17.10,EN,,0,0,0,,And we're going to say something like define dsimp to be a simplifier of the derivative rules.\nDialogue: 0,0:14:23.74,0:14:28.75,EN,,0,0,0,,And what simplifier is going to do is, given a set of rules, it will produce for me a procedure\nDialogue: 0,0:14:29.32,0:14:34.59,EN,,0,0,0,,which will simplify expressions containing the things that are referred to by these rules.\nDialogue: 0,0:14:37.39,0:14:43.93,EN,,0,0,0,,So here will be a procedure constructed for your purposes to simplify things with derivatives in them\nDialogue: 0,0:14:44.59,0:14:49.56,EN,,0,0,0,,such that, after that, if we're typing at some Lisp system, and we get a prompt,\nDialogue: 0,0:14:49.88,0:15:03.93,EN,,0,0,0,,and we say dsimp, for example, of the derivative of the sum of x and y with respect to x--\nDialogue: 0,0:15:06.99,0:15:10.97,EN,,0,0,0,,note the quote here because I'm talking about the expression which is the derivative--\nDialogue: 0,0:15:13.29,0:15:17.76,EN,,0,0,0,,then I will get back as a result plus 1 0.\nDialogue: 0,0:15:19.96,0:15:24.60,EN,,0,0,0,,Because the derivative of x plus y is the derivative of x plus derivative y.\nDialogue: 0,0:15:24.60,0:15:26.22,EN,,0,0,0,,The derivative of x with respect to x is 1.\nDialogue: 0,0:15:26.38,0:15:27.82,EN,,0,0,0,,The derivative of y with respect to x is 0.\nDialogue: 0,0:15:29.42,0:15:30.46,EN,,0,0,0,,It's not what we're going to get.\nDialogue: 0,0:15:31.18,0:15:34.65,EN,,0,0,0,,I haven't put any simplification at that level-- algebraic simplification--yet.\nDialogue: 0,0:15:36.16,0:15:41.53,EN,,0,0,0,,Of course, once we have such a thing, then we can--then we can look at other rules.\nDialogue: 0,0:15:41.96,0:15:49.36,EN,,0,0,0,,So, for example, we can, if we go to the slide, OK?\nDialogue: 0,0:15:49.36,0:15:54.12,EN,,0,0,0,,Here, for example, are other rules that we might have, algebraic manipulation rules,\nDialogue: 0,0:15:56.00,0:15:58.38,EN,,0,0,0,,ones that would be used for simplifying algebraic expressions.\nDialogue: 0,0:15:59.00,0:16:02.06,EN,,0,0,0,,For example, just looking at some of these,\nDialogue: 0,0:16:03.04,0:16:09.20,EN,,0,0,0,,the left-hand side says any operator applied to a constant e1 and a constant e2\nDialogue: 0,0:16:09.32,0:16:14.51,EN,,0,0,0,,is the result of evaluating that operator on the constants e1 and e2.\nDialogue: 0,0:16:15.88,0:16:21.56,EN,,0,0,0,,Or an operator, applied to e1, any expression e1 and a constant e2,\nDialogue: 0,0:16:21.69,0:16:23.87,EN,,0,0,0,,is going to move the constant forward.\nDialogue: 0,0:16:24.52,0:16:27.68,EN,,0,0,0,,So that'll turn into the operator with e2 followed by e1.\nDialogue: 0,0:16:28.59,0:16:30.11,EN,,0,0,0,,Why I did that, I don't know.\nDialogue: 0,0:16:30.22,0:16:33.16,EN,,0,0,0,,It wouldn't work if I had division, for example.\nDialogue: 0,0:16:33.53,0:16:35.31,EN,,0,0,0,,So there's a bug in the rules, if you like.\nDialogue: 0,0:16:36.67,0:16:40.86,EN,,0,0,0,,So the sum of 0 and e is e.\nDialogue: 0,0:16:42.17,0:16:45.31,EN,,0,0,0,,The product of 1 and any expression e is e.\nDialogue: 0,0:16:46.12,0:16:49.13,EN,,0,0,0,,The product of 0 and any expression e is 0.\nDialogue: 0,0:16:49.33,0:16:52.72,EN,,0,0,0,,Just looking at some more of these rules, we could have arbitrarily complicated ones.\nDialogue: 0,0:16:53.69,0:16:54.81,EN,,0,0,0,,We could have things like\nDialogue: 0,0:16:55.36,0:17:01.69,EN,,0,0,0,,the product of the constant e1 and any constant e2 with e3\nDialogue: 0,0:17:02.35,0:17:11.96,EN,,0,0,0,,is the result of multiplying the result of multiplying now the constants e1 and e2 together and putting e3 there.\nDialogue: 0,0:17:13.36,0:17:16.76,EN,,0,0,0,,So it says combine the constants that I had,\nDialogue: 0,0:17:16.76,0:17:22.70,EN,,0,0,0,,which was if I had a product of e1 and e2 and e3 just multiply--I mean and e1 and e2 are both constants, multiply them.\nDialogue: 0,0:17:23.84,0:17:25.48,EN,,0,0,0,,And you can make up the rules as you like.\nDialogue: 0,0:17:25.79,0:17:26.94,EN,,0,0,0,,There are lots of them here.\nDialogue: 0,0:17:27.42,0:17:31.04,EN,,0,0,0,,There are things as complicated, for example, as--\nDialogue: 0,0:17:31.26,0:17:33.93,EN,,0,0,0,,oh, I suppose down here some distributive law, you see.\nDialogue: 0,0:17:33.93,0:17:38.57,EN,,0,0,0,,The product of any object c and the sum of d and e\nDialogue: 0,0:17:39.02,0:17:43.66,EN,,0,0,0,,gives the result as the same as the sum of the product of c and d and the product of c and e.\nDialogue: 0,0:17:45.31,0:17:48.67,EN,,0,0,0,,Now, what exactly these rules are doesn't very much interest me.\nDialogue: 0,0:17:49.16,0:17:52.97,EN,,0,0,0,,We're going to be writing the language that will allow us to interpret these rules\nDialogue: 0,0:17:55.50,0:17:57.48,EN,,0,0,0,,so that we can, in fact, make up whatever rules we like,\nDialogue: 0,0:17:58.35,0:18:00.14,EN,,0,0,0,,another whole language of programming.\nDialogue: 0,0:18:03.39,0:18:04.04,EN,,0,0,0,,Well, let's see.\nDialogue: 0,0:18:05.18,0:18:06.96,EN,,0,0,0,,I haven't told you how we're going to do this.\nDialogue: 0,0:18:07.53,0:18:10.06,EN,,0,0,0,,And, of course, for a while, we're going to work on that.\nDialogue: 0,0:18:10.89,0:18:15.40,EN,,0,0,0,,But there's a real question of what is--what am I going to do at all at a large scale?\nDialogue: 0,0:18:17.08,0:18:18.22,EN,,0,0,0,,How do these rules work?\nDialogue: 0,0:18:19.00,0:18:25.45,EN,,0,0,0,,How is the simplifier program going to manipulate these rules with your expression to produce a reasonable answer?\nDialogue: 0,0:18:26.22,0:18:29.85,EN,,0,0,0,,Well, first, I'd like to think about these rules as being some sort of deck of them.\nDialogue: 0,0:18:32.52,0:18:34.22,EN,,0,0,0,,So here I have a whole bunch of rules,\nDialogue: 0,0:18:42.09,0:18:44.49,EN,,0,0,0,,Each rule-- here's a rule--\nDialogue: 0,0:18:46.97,0:18:49.24,EN,,0,0,0,,has a pattern and a skeleton.\nDialogue: 0,0:18:49.72,0:18:51.36,EN,,0,0,0,,I'm trying to make up a control structure for this.\nDialogue: 0,0:18:53.37,0:18:56.56,EN,,0,0,0,,Now, what I have is a matcher,\nDialogue: 0,0:19:00.99,0:19:03.76,EN,,0,0,0,,and I have something which is an instantiater.\nDialogue: 0,0:19:09.66,0:19:12.94,EN,,0,0,0,,And I'm going to pass from the matcher to the instantiater\nDialogue: 0,0:19:14.03,0:19:17.47,EN,,0,0,0,,some set of meaning for the pattern variables,\nDialogue: 0,0:19:18.06,0:19:19.42,EN,,0,0,0,,a dictionary, I'll call it.\nDialogue: 0,0:19:20.59,0:19:21.52,EN,,0,0,0,,A dictionary,\nDialogue: 0,0:19:24.92,0:19:27.82,EN,,0,0,0,,which will say x was matched against the following subexpression\nDialogue: 0,0:19:29.04,0:19:31.31,EN,,0,0,0,,and y was matched against another following subexpression.\nDialogue: 0,0:19:32.25,0:19:36.35,EN,,0,0,0,,And from the instantiater, I will be making expressions,and they will go into the matcher.\nDialogue: 0,0:19:37.16,0:19:38.36,EN,,0,0,0,,They will be expressions.\nDialogue: 0,0:19:45.00,0:19:48.41,EN,,0,0,0,,And the patterns of the rules will be fed into the matcher,\nDialogue: 0,0:19:49.24,0:19:54.40,EN,,0,0,0,,and the skeletons from the same rule will be fed into the instantiater.\nDialogue: 0,0:19:55.21,0:19:56.62,EN,,0,0,0,,Now, this is a little complicated\nDialogue: 0,0:19:57.12,0:19:59.53,EN,,0,0,0,,because when you have something like an algebraic expression,\nDialogue: 0,0:20:00.44,0:20:03.60,EN,,0,0,0,,where  some of the rules are intended to be able to allow you to substitute equal for equal.\nDialogue: 0,0:20:04.24,0:20:05.87,EN,,0,0,0,,These are equal transformation rules.\nDialogue: 0,0:20:06.88,0:20:09.29,EN,,0,0,0,,So all subexpressions of the expression should be looked at.\nDialogue: 0,0:20:11.13,0:20:15.82,EN,,0,0,0,,You give it an expression, this thing, and the rules should be cycled around.\nDialogue: 0,0:20:16.03,0:20:19.71,EN,,0,0,0,,First of all, for every subexpression of the expression you feed in,\nDialogue: 0,0:20:20.22,0:20:22.83,EN,,0,0,0,,all of the rules must be tried and looked at.\nDialogue: 0,0:20:24.33,0:20:27.07,EN,,0,0,0,,And if any rule matches, then this process occurs.\nDialogue: 0,0:20:27.30,0:20:30.63,EN,,0,0,0,,The dictionary--the dictionary is to have some values in it.\nDialogue: 0,0:20:30.63,0:20:33.39,EN,,0,0,0,,The instantiater makes a new expression,\nDialogue: 0,0:20:33.90,0:20:39.10,EN,,0,0,0,,which is basically replaces that part of the expression that was matched in your original expression.\nDialogue: 0,0:20:40.84,0:20:44.46,EN,,0,0,0,,And then, then, of course, we're going to recheck that,\nDialogue: 0,0:20:44.75,0:20:48.11,EN,,0,0,0,,going to go around these rules again, seeing if that could be simplified further.\nDialogue: 0,0:20:49.53,0:20:53.71,EN,,0,0,0,,And then, then we're going to do that for every subexpression until the thing no longer changes.\nDialogue: 0,0:20:54.96,0:20:57.50,EN,,0,0,0,,You can think of this as sort of an organic process.\nDialogue: 0,0:20:57.83,0:21:00.20,EN,,0,0,0,,You've got some sort of stew, right?\nDialogue: 0,0:21:00.24,0:21:04.32,EN,,0,0,0,,You've got bacteria or something, or enzymes in some, in some gooey mess.\nDialogue: 0,0:21:05.63,0:21:10.50,EN,,0,0,0,,And there's these--and these enzymes change things.\nDialogue: 0,0:21:10.50,0:21:14.38,EN,,0,0,0,,They attach to your expression, change it, and then they go away.\nDialogue: 0,0:21:15.28,0:21:17.83,EN,,0,0,0,,And they have to match. The key-in-lock phenomenon.\nDialogue: 0,0:21:18.00,0:21:19.73,EN,,0,0,0,,They match, they change it, they go away.\nDialogue: 0,0:21:19.73,0:21:21.68,EN,,0,0,0,,You can imagine it as a parallel process of some sort.\nDialogue: 0,0:21:22.70,0:21:24.97,EN,,0,0,0,,So you stick an expression into this mess,\nDialogue: 0,0:21:25.80,0:21:28.00,EN,,0,0,0,,and after a while, you take it out, and it's been simplified.\nDialogue: 0,0:21:30.44,0:21:32.64,EN,,0,0,0,,And it just keeps changing until it no longer can be changed.\nDialogue: 0,0:21:33.36,0:21:38.33,EN,,0,0,0,,But these enzymes can attach to any part of the, of the expression.\nDialogue: 0,0:21:39.21,0:21:43.76,EN,,0,0,0,,OK, at this point, I'd like to stop and ask for questions.\nDialogue: 0,0:21:44.92,0:21:45.36,EN,,0,0,0,,Yes.\nDialogue: 0,0:21:45.43,0:21:52.76,EN,,0,0,0,,AUDIENCE: This implies that the matching program and the instantiation program are separate programs; is that right? Or is that-- they are.\nDialogue: 0,0:21:52.76,0:21:53.85,EN,,0,0,0,,PROFESSOR: They're separate little pieces.\nDialogue: 0,0:21:54.14,0:21:56.60,EN,,0,0,0,,They fit together in a larger structure.\nDialogue: 0,0:21:57.26,0:21:59.13,EN,,0,0,0,,AUDIENCE: So I'm going through and matching\nDialogue: 0,0:21:59.61,0:22:03.21,EN,,0,0,0,,and passing the information about what I matched to an instantiater,\nDialogue: 0,0:22:03.39,0:22:06.03,EN,,0,0,0,,which makes the changes. And then I pass that back to the matcher?\nDialogue: 0,0:22:06.11,0:22:08.49,EN,,0,0,0,,PROFESSOR: It won't make a change. It will make a new expression,\nDialogue: 0,0:22:09.61,0:22:18.43,EN,,0,0,0,,which has, which has substituted the values of the pattern variable that were matched on the left-hand side for the variables that are mentioned,\nDialogue: 0,0:22:18.99,0:22:23.80,EN,,0,0,0,,the skeleton variables or evaluation variables or whatever I called them, on the right-hand side.\nDialogue: 0,0:22:25.20,0:22:27.08,EN,,0,0,0,,AUDIENCE: And then that's passed back into the matcher?\nDialogue: 0,0:22:27.20,0:22:32.32,EN,,0,0,0,,PROFESSOR: Then this is going to go around again. This is going to go through this mess until it no longer changes.\nDialogue: 0,0:22:33.31,0:22:37.00,EN,,0,0,0,,AUDIENCE: And it seems that there would be a danger of getting into a recursive loop.\nDialogue: 0,0:22:37.20,0:22:42.00,EN,,0,0,0,,Yes, if you do not write your rules nicely, you are-- indeed,\nDialogue: 0,0:22:42.00,0:22:45.53,EN,,0,0,0,,in any programming language you invent, if it's sufficiently powerful to do anything,\nDialogue: 0,0:22:45.72,0:22:48.40,EN,,0,0,0,,you can write programs that will go into infinite loops.\nDialogue: 0,0:22:49.37,0:22:55.07,EN,,0,0,0,,And indeed, writing a program for doing algebraic manipulation so on will produce infinite loops.\nDialogue: 0,0:23:01.05,0:23:01.52,EN,,0,0,0,,Go ahead.\nDialogue: 0,0:23:01.79,0:23:05.90,EN,,0,0,0,,AUDIENCE: Some language designers feel that this feature is so important\nDialogue: 0,0:23:05.93,0:23:12.03,EN,,0,0,0,,that it should become part of the basic language, for example, scheme in this case.\nDialogue: 0,0:23:12.03,0:23:13.96,EN,,0,0,0,,What are your thoughts on--\nDialogue: 0,0:23:13.96,0:23:15.08,EN,,0,0,0,,PROFESSOR: Which language feature?\nDialogue: 0,0:23:15.79,0:23:17.26,EN,,0,0,0,,AUDIENCE: The pattern matching.\nDialogue: 0,0:23:17.26,0:23:22.03,EN,,0,0,0,,It's all application of such rules should be--\nDialogue: 0,0:23:22.03,0:23:23.70,EN,,0,0,0,,PROFESSOR: Oh, you mean like Prolog?\nDialogue: 0,0:23:23.70,0:23:26.60,EN,,0,0,0,,AUDIENCE: Like Prolog, but it becomes a more general--\nDialogue: 0,0:23:26.60,0:23:27.64,EN,,0,0,0,,PROFESSOR: It's possible.\nDialogue: 0,0:23:28.46,0:23:32.30,EN,,0,0,0,,OK, I think my feeling about that is that\nDialogue: 0,0:23:33.16,0:23:36.49,EN,,0,0,0,,I would like to teach you how to do it so you don't depend upon some language designer.\nDialogue: 0,0:23:40.92,0:23:42.75,EN,,0,0,0,,PROFESSOR: You make it yourself. You can roll your own.\nDialogue: 0,0:23:45.28,0:23:45.63,EN,,0,0,0,,Thank you.\nDialogue: 0,0:23:45.63,0:23:50.63,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:23:50.63,0:23:53.13,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:23:53.13,0:23:55.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:24:00.32,0:24:06.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:24:07.07,0:24:10.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}Pattern-matching: Rule-based Substitution\nDialogue: 0,0:24:14.08,0:24:15.80,EN,,0,0,0,,Well, let's see.\nDialogue: 0,0:24:15.80,0:24:17.21,EN,,0,0,0,,Now we have to tell you how it works.\nDialogue: 0,0:24:20.00,0:24:24.11,EN,,0,0,0,,It conveniently breaks up into various pieces.\nDialogue: 0,0:24:24.80,0:24:26.54,EN,,0,0,0,,I'd like to look now at the matcher.\nDialogue: 0,0:24:28.72,0:24:31.42,EN,,0,0,0,,The matcher has the following basic structure.\nDialogue: 0,0:24:32.86,0:24:45.12,EN,,0,0,0,,It's a box that takes as its input an expression and a pattern,\nDialogue: 0,0:24:52.09,0:24:53.95,EN,,0,0,0,,and it turns out a dictionary.\nDialogue: 0,0:25:01.71,0:25:08.67,EN,,0,0,0,,A dictionary, remember, is a mapping of pattern variables to the values that were found by matching,\nDialogue: 0,0:25:09.15,0:25:11.05,EN,,0,0,0,,and it puts out another dictionary,\nDialogue: 0,0:25:18.24,0:25:25.53,EN,,0,0,0,,which is the result of augmenting this dictionary by what was found in matching this expression against this pattern.\nDialogue: 0,0:25:28.00,0:25:28.83,EN,,0,0,0,,So that's the matcher.\nDialogue: 0,0:25:33.87,0:25:36.54,EN,,0,0,0,,Now, this is a rather complicated program,\nDialogue: 0,0:25:37.20,0:25:41.58,EN,,0,0,0,,and we can look at it on the overhead over here and see,\nDialogue: 0,0:25:41.98,0:25:43.87,EN,,0,0,0,,ha ha, it's very complicated.\nDialogue: 0,0:25:44.43,0:25:45.87,EN,,0,0,0,,I just want you to look at the shape of it.\nDialogue: 0,0:25:46.78,0:25:49.85,EN,,0,0,0,,It's too complicated to look at except in pieces.\nDialogue: 0,0:25:51.72,0:25:59.24,EN,,0,0,0,,However, it's a fairly large, complicated program with a lot of sort of indented structure.\nDialogue: 0,0:26:00.09,0:26:05.28,EN,,0,0,0,,At the largest scale-- you don't try to read those characters, but at the largest scale,\nDialogue: 0,0:26:05.43,0:26:10.36,EN,,0,0,0,,you see that there is a case analysis, which is all these cases lined up.\nDialogue: 0,0:26:12.09,0:26:16.19,EN,,0,0,0,,What we're now going to do is look at this in a bit more detail,\nDialogue: 0,0:26:16.67,0:26:18.60,EN,,0,0,0,,attempting to understand how it works.\nDialogue: 0,0:26:20.08,0:26:22.35,EN,,0,0,0,,Let's go now to the first slide,\nDialogue: 0,0:26:23.55,0:26:27.93,EN,,0,0,0,,showing some of the structure of the matcher at a large scale.\nDialogue: 0,0:26:28.81,0:26:36.33,EN,,0,0,0,,And we see that the matcher, the matcher takes as its input a pattern, an expression, and a dictionary.\nDialogue: 0,0:26:38.57,0:26:40.40,EN,,0,0,0,,And there is a case analysis here,\nDialogue: 0,0:26:41.24,0:26:45.61,EN,,0,0,0,,which is made out of several cases, some of which have been left out over here,\nDialogue: 0,0:26:46.62,0:26:48.62,EN,,0,0,0,,and the general case, which I'd like you to see.\nDialogue: 0,0:26:50.52,0:26:53.28,EN,,0,0,0,,Let's consider this general case. It's a very important pattern.\nDialogue: 0,0:26:56.32,0:27:01.61,EN,,0,0,0,,The problem is that we have to examine two trees simultaneously.\nDialogue: 0,0:27:02.50,0:27:08.03,EN,,0,0,0,,One of the trees is the tree of the expression, and the other is the tree of the pattern.\nDialogue: 0,0:27:08.59,0:27:10.11,EN,,0,0,0,,We have to compare them with each other\nDialogue: 0,0:27:11.37,0:27:16.38,EN,,0,0,0,,so that the subexpressions of the expression are matched against subexpressions of the pattern.\nDialogue: 0,0:27:18.38,0:27:23.44,EN,,0,0,0,,Looking at that in a bit more detail, suppose I had a pattern, a pattern,\nDialogue: 0,0:27:23.93,0:27:31.24,EN,,0,0,0,,which was the sum of the product of a thing which we will call x\nDialogue: 0,0:27:32.44,0:27:35.53,EN,,0,0,0,,and a thing which we will call y,\nDialogue: 0,0:27:39.12,0:27:42.04,EN,,0,0,0,,and the sum of that, and the same thing we call y.\nDialogue: 0,0:27:45.21,0:27:47.53,EN,,0,0,0,,So we're looking for a sum of a product\nDialogue: 0,0:27:48.99,0:27:54.78,EN,,0,0,0,,whose second--whose second argument is the same as the second argument of the sum.\nDialogue: 0,0:27:57.02,0:27:58.84,EN,,0,0,0,,That's a thing you might be looking for.\nDialogue: 0,0:27:59.60,0:28:02.04,EN,,0,0,0,,Well, that, as a pattern, looks like this.\nDialogue: 0,0:28:03.02,0:28:04.01,EN,,0,0,0,,There is a tree,\nDialogue: 0,0:28:04.94,0:28:06.25,EN,,0,0,0,,which consists of a sum,\nDialogue: 0,0:28:08.08,0:28:20.25,EN,,0,0,0,,and a product with a pattern variable question mark x and question mark y,\nDialogue: 0,0:28:21.36,0:28:22.73,EN,,0,0,0,,and question mark y,\nDialogue: 0,0:28:24.92,0:28:26.94,EN,,0,0,0,,just looking at the same, just writing down the list structure in a different way.\nDialogue: 0,0:28:28.75,0:28:31.76,EN,,0,0,0,,Now, suppose we were matching that against an expression which matches it,\nDialogue: 0,0:28:32.49,0:28:39.85,EN,,0,0,0,,the product of 3 and x and, say, x.\nDialogue: 0,0:28:42.41,0:28:43.36,EN,,0,0,0,,That's another tree.\nDialogue: 0,0:28:44.33,0:28:56.06,EN,,0,0,0,,It's the sum of the product of 3 and x and of x.\nDialogue: 0,0:28:59.44,0:29:03.02,EN,,0,0,0,,So what I want to do is traverse these two trees simultaneously.\nDialogue: 0,0:29:04.41,0:29:07.82,EN,,0,0,0,,And what I'd like to do is walk them like this.\nDialogue: 0,0:29:08.67,0:29:12.96,EN,,0,0,0,,I'm going to say are these the same?\nDialogue: 0,0:29:12.96,0:29:14.32,EN,,0,0,0,,This is a complicated object.\nDialogue: 0,0:29:15.21,0:29:17.26,EN,,0,0,0,,Let's look at the left branches.\nDialogue: 0,0:29:17.26,0:29:18.14,EN,,0,0,0,,Well, that could be the car.\nDialogue: 0,0:29:18.56,0:29:21.21,EN,,0,0,0,,How does that look? Oh yes, the plus looks just fine.\nDialogue: 0,0:29:21.68,0:29:24.20,EN,,0,0,0,,But the next thing here is a complicated thing.\nDialogue: 0,0:29:24.20,0:29:24.84,EN,,0,0,0,,Let's look at that.\nDialogue: 0,0:29:25.20,0:29:26.80,EN,,0,0,0,,Oh yes, that's pretty fine, too.\nDialogue: 0,0:29:26.80,0:29:27.79,EN,,0,0,0,,They're both asterisks.\nDialogue: 0,0:29:28.51,0:29:30.24,EN,,0,0,0,,Now, whoops!\nDialogue: 0,0:29:30.40,0:29:33.60,EN,,0,0,0,,My pattern variable, it matches against the 3.\nDialogue: 0,0:29:34.27,0:29:35.92,EN,,0,0,0,,Remember, x equals 3 now.\nDialogue: 0,0:29:36.36,0:29:37.37,EN,,0,0,0,,That's in my dictionary,\nDialogue: 0,0:29:37.56,0:29:40.73,EN,,0,0,0,,and the dictionary's going to follow along with me: x equals three.\nDialogue: 0,0:29:41.45,0:29:45.87,EN,,0,0,0,,Ah yes, x equals 3 and y equals x, different x.\nDialogue: 0,0:29:46.83,0:29:51.20,EN,,0,0,0,,The pattern x is the expression x, the pattern y.\nDialogue: 0,0:29:53.61,0:29:57.76,EN,,0,0,0,,Oh yes, the pattern variable y, I've already got a value for it. It's x.\nDialogue: 0,0:29:58.36,0:30:00.06,EN,,0,0,0,,Is this an x? Oh yeah, sure it is.\nDialogue: 0,0:30:00.06,0:30:00.75,EN,,0,0,0,,That's fine.\nDialogue: 0,0:30:02.03,0:30:02.78,EN,,0,0,0,,Yep, done.\nDialogue: 0,0:30:03.39,0:30:08.09,EN,,0,0,0,,I now have a dictionary, which I've accumulated by making this walk.\nDialogue: 0,0:30:11.42,0:30:14.51,EN,,0,0,0,,Well, now let's look at this general case here and see how that works.\nDialogue: 0,0:30:15.88,0:30:16.51,EN,,0,0,0,,Here we have it.\nDialogue: 0,0:30:17.20,0:30:21.66,EN,,0,0,0,,I take in a pattern variable -- sorry -- a pattern, an expression, and a dictionary.\nDialogue: 0,0:30:22.38,0:30:27.50,EN,,0,0,0,,And now I'm going to do a complicated thing here, which is the general case.\nDialogue: 0,0:30:29.98,0:30:34.80,EN,,0,0,0,,The expression is made out of two parts: a left and a right half, in general.\nDialogue: 0,0:30:35.45,0:30:38.81,EN,,0,0,0,,Anything that's complicated is made out of two pieces in a Lisp system.\nDialogue: 0,0:30:40.03,0:30:41.23,EN,,0,0,0,,Well, now what do we have here?\nDialogue: 0,0:30:41.88,0:30:48.84,EN,,0,0,0,,I'm going to match the car's of the two expressions against each other with respect to the dictionary I already have,\nDialogue: 0,0:30:50.30,0:30:53.12,EN,,0,0,0,,producing a dictionary as its value,\nDialogue: 0,0:30:54.14,0:30:57.26,EN,,0,0,0,,which I will then use for matching the cdr's against each other.\nDialogue: 0,0:30:58.51,0:31:02.09,EN,,0,0,0,,So that's how the dictionary travels, threads the entire structure.\nDialogue: 0,0:31:03.66,0:31:07.53,EN,,0,0,0,,And then the result of that is the dictionary for the match of the car and the cdr,\nDialogue: 0,0:31:10.12,0:31:12.41,EN,,0,0,0,,and that's what's going to be returned as a value.\nDialogue: 0,0:31:13.61,0:31:15.84,EN,,0,0,0,,Now, at any point, a match might fail.\nDialogue: 0,0:31:16.62,0:31:18.20,EN,,0,0,0,,It may be the case, for example,\nDialogue: 0,0:31:18.36,0:31:27.18,EN,,0,0,0,,if we go back and look at an expression that doesn't quite match, like supposing this was a 4.\nDialogue: 0,0:31:29.13,0:31:34.81,EN,,0,0,0,,Well, now these two don't match any more, because the x that had to be  --\nDialogue: 0,0:31:34.93,0:31:37.34,EN,,0,0,0,,sorry, the y that had to be x here\nDialogue: 0,0:31:37.82,0:31:40.12,EN,,0,0,0,,and this y has to be 4.\nDialogue: 0,0:31:40.53,0:31:43.52,EN,,0,0,0,,But x and 4 were not the same object syntactically.\nDialogue: 0,0:31:44.59,0:31:48.81,EN,,0,0,0,,So this wouldn't match, and that would be rejected sometimes, so matches may fail.\nDialogue: 0,0:31:50.19,0:31:56.08,EN,,0,0,0,,Now, of course, because this matcher takes the dictionary from the previous match as input,\nDialogue: 0,0:31:56.52,0:31:58.28,EN,,0,0,0,,it must be able to propagate the failures.\nDialogue: 0,0:31:58.57,0:32:01.04,EN,,0,0,0,,And so that's what the first clause of this conditional does.\nDialogue: 0,0:32:03.61,0:32:08.19,EN,,0,0,0,,It's also true that if it turned out that the pattern was not atomic--\nDialogue: 0,0:32:08.50,0:32:11.45,EN,,0,0,0,,see, if the pattern was atomic, I'd go into this stuff, which we haven't looked at yet.\nDialogue: 0,0:32:12.17,0:32:13.56,EN,,0,0,0,,But if the pattern is not atomic\nDialogue: 0,0:32:15.05,0:32:19.23,EN,,0,0,0,,and the expression is atomic-- it's not made out of pieces--\nDialogue: 0,0:32:20.14,0:32:22.65,EN,,0,0,0,,then that must be a failure, and so we go over here.\nDialogue: 0,0:32:23.64,0:32:30.78,EN,,0,0,0,,If the pattern is not atomic and the pattern is not a pattern variable--I have to remind myself of that-- then we go over here.\nDialogue: 0,0:32:30.96,0:32:32.51,EN,,0,0,0,,So that's way, failures may occur.\nDialogue: 0,0:32:35.26,0:32:39.12,EN,,0,0,0,,OK, so now let's look at the insides of this thing.\nDialogue: 0,0:32:39.84,0:32:42.93,EN,,0,0,0,,Well, the first place to look is what happens if I have an atomic pattern?\nDialogue: 0,0:32:42.93,0:32:43.90,EN,,0,0,0,,That's very simple.\nDialogue: 0,0:32:43.90,0:32:46.50,EN,,0,0,0,,A pattern that's not made out of any pieces: foo.\nDialogue: 0,0:32:47.37,0:32:48.54,EN,,0,0,0,,That's a nice atomic pattern.\nDialogue: 0,0:32:49.16,0:32:51.24,EN,,0,0,0,,Well, here's what we see.\nDialogue: 0,0:32:52.08,0:32:55.82,EN,,0,0,0,,If the pattern is atomic, then if the expression is atomic,\nDialogue: 0,0:32:56.80,0:33:01.85,EN,,0,0,0,,then if they are the same thing, then the dictionary I get is the same one as I had before.\nDialogue: 0,0:33:03.08,0:33:04.00,EN,,0,0,0,,Nothing's changed.\nDialogue: 0,0:33:04.60,0:33:10.33,EN,,0,0,0,,It's just that I matched plus against plus, asterisk against asterisk, x against x.\nDialogue: 0,0:33:11.42,0:33:12.33,EN,,0,0,0,,That's all fine.\nDialogue: 0,0:33:13.07,0:33:16.81,EN,,0,0,0,,However, if the pattern is not the one which is the expression,\nDialogue: 0,0:33:17.32,0:33:21.36,EN,,0,0,0,,if I have two separate atomic objects, then it was matching plus against asterisk,\nDialogue: 0,0:33:22.44,0:33:23.40,EN,,0,0,0,,which case I fail.\nDialogue: 0,0:33:25.60,0:33:34.56,EN,,0,0,0,,Or if it turns out that the pattern is atomic but the expression is complicated, it's not atomic, then I get a failure.\nDialogue: 0,0:33:37.40,0:33:38.24,EN,,0,0,0,,That's very simple.\nDialogue: 0,0:33:38.81,0:33:43.61,EN,,0,0,0,,Now, what about the various kinds of pattern variables?\nDialogue: 0,0:33:44.09,0:33:46.54,EN,,0,0,0,,We had three kinds. I give them the names.\nDialogue: 0,0:33:47.39,0:33:52.03,EN,,0,0,0,,They're arbitrary constants, arbitrary variables, and arbitrary expressions.\nDialogue: 0,0:33:53.82,0:34:00.14,EN,,0,0,0,,A question mark x is an arbitrary expression.\nDialogue: 0,0:34:01.18,0:34:04.54,EN,,0,0,0,,A question mark cx is an arbitrary constant,\nDialogue: 0,0:34:04.73,0:34:07.29,EN,,0,0,0,,and a question mark vx is an arbitrary variable.\nDialogue: 0,0:34:08.96,0:34:09.79,EN,,0,0,0,,Well, what do we do here?\nDialogue: 0,0:34:10.51,0:34:16.94,EN,,0,0,0,,Looking at this, we see that if I have an arbitrary constant, if the pattern is an arbitrary constant,\nDialogue: 0,0:34:17.53,0:34:20.57,EN,,0,0,0,,then it had better be the case that the expression had better be a constant.\nDialogue: 0,0:34:21.48,0:34:23.53,EN,,0,0,0,,If the expression is not a constant, then that match fails.\nDialogue: 0,0:34:23.83,0:34:27.50,EN,,0,0,0,,If it is a constant, however, then I wish to extend the dictionary.\nDialogue: 0,0:34:27.50,0:34:29.69,EN,,0,0,0,,I wish to extend the dictionary\nDialogue: 0,0:34:30.70,0:34:37.76,EN,,0,0,0,,with that pattern being remembered to be that expression using the old dictionary as a starting point.\nDialogue: 0,0:34:41.16,0:34:42.75,EN,,0,0,0,,So really, for arbitrary variables,\nDialogue: 0,0:34:43.72,0:34:47.46,EN,,0,0,0,,I have to check first if the expression is a variable by matching against.\nDialogue: 0,0:34:47.46,0:34:50.09,EN,,0,0,0,,If so, it's worth extending the dictionary\nDialogue: 0,0:34:50.38,0:34:54.65,EN,,0,0,0,,so the pattern is remembered to be matched against that expression, given the original dictionary,\nDialogue: 0,0:34:55.28,0:34:56.70,EN,,0,0,0,,and this makes a new dictionary.\nDialogue: 0,0:34:58.88,0:35:04.16,EN,,0,0,0,,Now, it has to check. There's a sorts of failure inside extend dictionary, which is that--\nDialogue: 0,0:35:04.16,0:35:07.50,EN,,0,0,0,,if one of these pattern variables already has a value\nDialogue: 0,0:35:09.23,0:35:16.17,EN,,0,0,0,,and I'm trying to match the thing against something else which is not equivalent to the one that I've already matched it against once,\nDialogue: 0,0:35:16.43,0:35:18.36,EN,,0,0,0,,then a failure will come flying out of here, too.\nDialogue: 0,0:35:20.16,0:35:21.56,EN,,0,0,0,,And I will see that some time.\nDialogue: 0,0:35:22.91,0:35:29.36,EN,,0,0,0,,And finally, an expression does not have to check anything syntactic about the expression that's being matched,\nDialogue: 0,0:35:30.11,0:35:32.20,EN,,0,0,0,,so all it does is it's an extension of the dictionary.\nDialogue: 0,0:35:34.76,0:35:38.32,EN,,0,0,0,,So you've just seen a complete, very simple matcher.\nDialogue: 0,0:35:39.28,0:35:41.37,EN,,0,0,0,,Now, one of the things that's rather remarkable about this\nDialogue: 0,0:35:41.66,0:35:45.12,EN,,0,0,0,,is people pay an awful lot of money these days for someone to make\nDialogue: 0,0:35:45.46,0:35:47.52,EN,,0,0,0,,a, quote, AI expert system\nDialogue: 0,0:35:48.40,0:35:52.03,EN,,0,0,0,,that has nothing more in it than a matcher and maybe an instantiater like this.\nDialogue: 0,0:35:53.56,0:35:56.94,EN,,0,0,0,,But it's very easy to do, and now, of course, you can start up a little start-up company\nDialogue: 0,0:35:57.42,0:36:01.72,EN,,0,0,0,,and make a couple of megabucks in the next week taking some people for a ride.\nDialogue: 0,0:36:03.79,0:36:08.57,EN,,0,0,0,,I mean, 20 years ago, this was remarkable, this kind of program.\nDialogue: 0,0:36:09.74,0:36:12.81,EN,,0,0,0,,But now, this is sort of easy. You can teach it to freshmen.\nDialogue: 0,0:36:13.63,0:36:15.47,EN,,0,0,0,,Well, now there's an instantiater as well.\nDialogue: 0,0:36:20.22,0:36:23.07,EN,,0,0,0,,The problem is they're all going off and making more money than I do. Alright?\nDialogue: 0,0:36:24.97,0:36:26.59,EN,,0,0,0,,But that's always been true of universities.\nDialogue: 0,0:36:27.10,0:36:39.42,EN,,0,0,0,,As expression, the purpose of the instantiater is to make expressions given a dictionary and a skeleton.\nDialogue: 0,0:36:44.35,0:36:45.69,EN,,0,0,0,,And that's not very hard at all.\nDialogue: 0,0:36:46.60,0:36:53.36,EN,,0,0,0,,We'll see that very simply in the next, the next slide here.\nDialogue: 0,0:36:53.88,0:36:59.29,EN,,0,0,0,,To instantiate a skeleton, given a particular dictionary-- oh, this is easy.\nDialogue: 0,0:36:59.68,0:37:03.29,EN,,0,0,0,,We're going to do a recursive tree walk over the skeleton.\nDialogue: 0,0:37:04.08,0:37:08.33,EN,,0,0,0,,And for everything which is a skeleton variable-- I don't know, call it a skeleton evaluation.\nDialogue: 0,0:37:08.41,0:37:11.42,EN,,0,0,0,,That's the name and the abstract syntax that I give it in this program:\nDialogue: 0,0:37:11.60,0:37:16.46,EN,,0,0,0,,a skeleton evaluation, a thing beginning with a colon in the rules.\nDialogue: 0,0:37:18.25,0:37:24.30,EN,,0,0,0,,For anything of that case, I'm going to look up the answer in the dictionary, and we'll worry about that in a second.\nDialogue: 0,0:37:24.30,0:37:25.61,EN,,0,0,0,,Let's look at this as a whole.\nDialogue: 0,0:37:27.77,0:37:31.80,EN,,0,0,0,,Here, I have-- I'm going to instantiate a skeleton, given a dictionary.\nDialogue: 0,0:37:32.75,0:37:37.15,EN,,0,0,0,,Well, I'm going to define some internal loop right there,\nDialogue: 0,0:37:38.14,0:37:39.85,EN,,0,0,0,,and it's going to do something very simple.\nDialogue: 0,0:37:40.17,0:37:43.50,EN,,0,0,0,,Even if a skeleton--even if a skeleton is simple and atomic,\nDialogue: 0,0:37:44.60,0:37:47.45,EN,,0,0,0,,in which case it's nothing more than giving the skeleton back as an answer,\nDialogue: 0,0:37:48.84,0:37:51.87,EN,,0,0,0,,or in the general case, it's complicated,\nDialogue: 0,0:37:52.60,0:37:59.40,EN,,0,0,0,,in which case I'm going to make up the expression which is the result of instantiating--\nDialogue: 0,0:37:59.40,0:38:04.25,EN,,0,0,0,,calling this loop recursively-- instantiating the car of the skeleton and the cdr.\nDialogue: 0,0:38:04.89,0:38:06.24,EN,,0,0,0,,So here is a recursive tree walk.\nDialogue: 0,0:38:08.41,0:38:14.36,EN,,0,0,0,,However, if it turns out to be a skeleton evaluation, a colon expression in the skeleton,\nDialogue: 0,0:38:14.96,0:38:22.64,EN,,0,0,0,,then what I'm going to do is find the expression that's in the colon-- the CADR in this case.\nDialogue: 0,0:38:22.81,0:38:26.25,EN,,0,0,0,,It's a piece of abstract syntax here, so I can change my representation of rules.\nDialogue: 0,0:38:27.52,0:38:32.73,EN,,0,0,0,,I'm going to evaluate that relative to this dictionary, whatever evaluation means.\nDialogue: 0,0:38:32.90,0:38:34.65,EN,,0,0,0,,We'll find out a lot about that sometime.\nDialogue: 0,0:38:36.12,0:38:38.35,EN,,0,0,0,,And the result of that is my answer.\nDialogue: 0,0:38:39.68,0:38:43.66,EN,,0,0,0,,so. I start up this loop-- here's my initialization-- by calling it with the whole skeleton,\nDialogue: 0,0:38:44.44,0:38:47.04,EN,,0,0,0,,and this will just do a recursive decomposition into pieces.\nDialogue: 0,0:38:49.63,0:38:56.48,EN,,0,0,0,,Now, one more little bit of detail is what happens inside evaluate?\nDialogue: 0,0:38:57.18,0:38:59.07,EN,,0,0,0,,I can't tell you that in great detail.\nDialogue: 0,0:38:59.98,0:39:01.34,EN,,0,0,0,,I'll tell you a little bit of it.\nDialogue: 0,0:39:01.56,0:39:03.74,EN,,0,0,0,,Later, we're going to see--look into this in much more detail.\nDialogue: 0,0:39:05.29,0:39:10.81,EN,,0,0,0,,To evaluate some form, some expression with respect to a dictionary,\nDialogue: 0,0:39:11.90,0:39:14.17,EN,,0,0,0,,if the expression is an atomic object, well,\nDialogue: 0,0:39:15.04,0:39:16.22,EN,,0,0,0,,I'm going to go look it up.\nDialogue: 0,0:39:18.60,0:39:19.87,EN,,0,0,0,,Nothing very exciting there.\nDialogue: 0,0:39:20.57,0:39:23.66,EN,,0,0,0,,Otherwise, I'm going to do something complicated here,\nDialogue: 0,0:39:23.83,0:39:28.28,EN,,0,0,0,,which is I'm going to apply a procedure which is the result of looking up the operator part\nDialogue: 0,0:39:29.44,0:39:31.68,EN,,0,0,0,,in something that we're going to find out about someday.\nDialogue: 0,0:39:32.14,0:39:34.20,EN,,0,0,0,,I want you realize you're seeing magic now.\nDialogue: 0,0:39:34.67,0:39:38.72,EN,,0,0,0,,This magic will become clear very soon, but not today.\nDialogue: 0,0:39:40.00,0:39:46.51,EN,,0,0,0,,Then I'm looking at--looking up all the pieces, all the arguments to that in the dictionary.\nDialogue: 0,0:39:48.56,0:39:50.88,EN,,0,0,0,,So I don't want you to look at this in detail.\nDialogue: 0,0:39:51.44,0:39:53.44,EN,,0,0,0,,I want you to see that there's more going on here,\nDialogue: 0,0:39:54.17,0:39:56.75,EN,,0,0,0,,and we're going to see more about this.\nDialogue: 0,0:39:59.04,0:40:00.88,EN,,0,0,0,,But it's-- the magic is going to stop.\nDialogue: 0,0:40:02.57,0:40:06.96,EN,,0,0,0,,This part has to do with Lisp, and it's the end of that.\nDialogue: 0,0:40:10.25,0:40:13.56,EN,,0,0,0,,OK, so now we know about matching and instantiation.\nDialogue: 0,0:40:15.05,0:40:16.60,EN,,0,0,0,,Are there any questions for this segment?\nDialogue: 0,0:40:28.10,0:40:29.80,EN,,0,0,0,,AUDIENCE: I have a question.\nDialogue: 0,0:40:29.80,0:40:30.43,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:40:30.43,0:40:32.56,EN,,0,0,0,,AUDIENCE: Is it possible to bring up a previous slide?\nDialogue: 0,0:40:33.60,0:40:35.56,EN,,0,0,0,,It's about this define match pattern.\nDialogue: 0,0:40:36.16,0:40:40.76,EN,,0,0,0,,PROFESSOR: Yes. You'd like to see the overall slide define match pattern.\nDialogue: 0,0:40:40.76,0:40:43.06,EN,,0,0,0,,Can somebody put up the -- no, the overhead.\nDialogue: 0,0:40:43.06,0:40:45.16,EN,,0,0,0,,That's the biggest scale one.\nDialogue: 0,0:40:45.31,0:40:46.40,EN,,0,0,0,,What part would you like to see?\nDialogue: 0,0:40:46.76,0:40:49.96,EN,,0,0,0,,AUDIENCE: Well, the top would be fine.\nDialogue: 0,0:40:49.96,0:40:53.76,EN,,0,0,0,,Any of the parts where you're passing failed.\nDialogue: 0,0:40:54.52,0:40:55.21,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:40:55.64,0:40:59.33,EN,,0,0,0,,AUDIENCE: The idea is to pass failed back to the dictionary; is that right?\nDialogue: 0,0:40:59.33,0:41:04.25,EN,,0,0,0,,PROFESSOR: The dictionary is the answer to a match, right?\nDialogue: 0,0:41:05.16,0:41:09.80,EN,,0,0,0,,And it is either some mapping\nDialogue: 0,0:41:11.07,0:41:14.03,EN,,0,0,0,,or there's no match. It doesn't match.\nDialogue: 0,0:41:14.46,0:41:14.97,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:41:15.26,0:41:17.83,EN,,0,0,0,,PROFESSOR: So what you're seeing over here is, in fact,\nDialogue: 0,0:41:17.83,0:41:22.60,EN,,0,0,0,,because the fact that a match may have another match pass in the dictionary,\nDialogue: 0,0:41:22.80,0:41:24.65,EN,,0,0,0,,as you see in the general case down here.\nDialogue: 0,0:41:25.12,0:41:27.93,EN,,0,0,0,,Here's the general case where a match passes another match to the dictionary.\nDialogue: 0,0:41:28.14,0:41:34.16,EN,,0,0,0,,When I match the cdr's, I match them in the dictionary that is resulting from matching the car's.\nDialogue: 0,0:41:36.06,0:41:37.08,EN,,0,0,0,,OK, that's what I have here.\nDialogue: 0,0:41:37.29,0:41:40.30,EN,,0,0,0,,So because of that, if the match of the car's fails,\nDialogue: 0,0:41:41.23,0:41:45.44,EN,,0,0,0,,then it may be necessary that the match of the cdr's propagates that failure,\nDialogue: 0,0:41:45.95,0:41:46.96,EN,,0,0,0,,and that's what the first line is.\nDialogue: 0,0:41:48.26,0:41:51.73,EN,,0,0,0,,AUDIENCE: OK, well, I'm still unclear what matches--\nDialogue: 0,0:41:51.73,0:41:54.24,EN,,0,0,0,,what comes out of one instance of the match?\nDialogue: 0,0:41:54.73,0:41:56.00,EN,,0,0,0,,PROFESSOR: One of two possibilities.\nDialogue: 0,0:41:56.33,0:41:59.15,EN,,0,0,0,,Either the symbol failed, which means there is no match.\nDialogue: 0,0:41:59.53,0:41:59.93,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:41:59.93,0:42:03.87,EN,,0,0,0,,PROFESSOR: Or some mapping, which is an abstract thing right now,\nDialogue: 0,0:42:04.16,0:42:05.68,EN,,0,0,0,,and you should know about the structure of it,\nDialogue: 0,0:42:06.49,0:42:13.96,EN,,0,0,0,,which relates the pattern variables to their values as picked up in the match.\nDialogue: 0,0:42:14.68,0:42:16.70,EN,,0,0,0,,AUDIENCE: OK, so it is--\nDialogue: 0,0:42:16.80,0:42:18.57,EN,,0,0,0,,PROFESSOR: That's constructed by extend dictionary.\nDialogue: 0,0:42:18.80,0:42:28.54,EN,,0,0,0,,AUDIENCE: So the recursive nature brings about the fact that if ever a failed gets passed out of any calling of match,\nDialogue: 0,0:42:28.68,0:42:30.30,EN,,0,0,0,,then the first condition will pick it up--\nDialogue: 0,0:42:30.40,0:42:33.56,EN,,0,0,0,,PROFESSOR: And just propagate it along without any further ado, right.\nDialogue: 0,0:42:33.56,0:42:34.83,EN,,0,0,0,,AUDIENCE: Oh, right.\nDialogue: 0,0:42:35.50,0:42:37.36,EN,,0,0,0,,PROFESSOR: That's just the fastest way to get that failure out of there.\nDialogue: 0,0:42:42.86,0:42:43.60,EN,,0,0,0,,Yes.\nDialogue: 0,0:42:43.84,0:42:47.23,EN,,0,0,0,,AUDIENCE: If I don't fail, that means that I've matched a pattern,\nDialogue: 0,0:42:47.84,0:42:53.00,EN,,0,0,0,,and I run the procedure extend dict and then pass in the pattern in the expression.\nDialogue: 0,0:42:55.21,0:42:58.43,EN,,0,0,0,,But the substitution will not be made at that point; is that right?\nDialogue: 0,0:42:58.43,0:42:59.03,EN,,0,0,0,,I'm just--\nDialogue: 0,0:42:59.03,0:42:59.46,EN,,0,0,0,,PROFESSOR: No, no.\nDialogue: 0,0:42:59.46,0:43:02.40,EN,,0,0,0,,There's no substitution being there because there's no skeleton to be substituted in.\nDialogue: 0,0:43:02.40,0:43:03.06,EN,,0,0,0,,AUDIENCE: Right. So\nDialogue: 0,0:43:03.06,0:43:07.16,EN,,0,0,0,,PROFESSOR: All you've got there is we're making up the dictionary for later substitution.\nDialogue: 0,0:43:08.25,0:43:12.43,EN,,0,0,0,,AUDIENCE: And what would the dictionary look like? Is it ordered pairs?\nDialogue: 0,0:43:12.72,0:43:15.96,EN,,0,0,0,,PROFESSOR: Ahhhhh, That's--that's not told to you.\nDialogue: 0,0:43:15.96,0:43:16.89,EN,,0,0,0,,We're being abstract.\nDialogue: 0,0:43:17.06,0:43:17.56,EN,,0,0,0,,AUDIENCE: OK.\nDialogue: 0,0:43:17.56,0:43:18.90,EN,,0,0,0,,PROFESSOR: Why do you want to know?\nDialogue: 0,0:43:18.90,0:43:21.64,EN,,0,0,0,,What it is, it's a function. It's a function.\nDialogue: 0,0:43:21.69,0:43:22.33,EN,,0,0,0,,AUDIENCE: Well, the reason I want to know is--\nDialogue: 0,0:43:22.33,0:43:24.17,EN,,0,0,0,,PROFESSOR: A function abstractly is a set of ordered pairs.\nDialogue: 0,0:43:25.12,0:43:28.44,EN,,0,0,0,,It could be implemented as a set of list pairs.\nDialogue: 0,0:43:29.06,0:43:32.43,EN,,0,0,0,,It could be implemented as some fancy table mechanism.\nDialogue: 0,0:43:32.56,0:43:34.16,EN,,0,0,0,,It could be implemented as a function.\nDialogue: 0,0:43:35.80,0:43:37.40,EN,,0,0,0,,And somehow, I'm building up a function.\nDialogue: 0,0:43:39.02,0:43:39.87,EN,,0,0,0,,But I'm not telling you.\nDialogue: 0,0:43:40.84,0:43:43.08,EN,,0,0,0,,That's up to George, who's going to build that later.\nDialogue: 0,0:43:49.56,0:43:52.06,EN,,0,0,0,,I know you really badly want to write concrete things.\nDialogue: 0,0:43:52.36,0:43:54.19,EN,,0,0,0,,I'm not going to let you do that.\nDialogue: 0,0:43:54.43,0:43:59.23,EN,,0,0,0,,AUDIENCE: Well, let me at least ask, what is the important information there that's being passed to extend dict?\nDialogue: 0,0:43:59.74,0:44:02.08,EN,,0,0,0,,I want to pass the pattern I found--\nDialogue: 0,0:44:02.73,0:44:04.83,EN,,0,0,0,,PROFESSOR: Yes. The pattern that's matched against the expression.\nDialogue: 0,0:44:04.83,0:44:09.30,EN,,0,0,0,,You want to have the pattern, which happens to be in those cases pattern variables, right?\nDialogue: 0,0:44:09.85,0:44:12.89,EN,,0,0,0,,All of those three cases for extend dict are pattern variables.\nDialogue: 0,0:44:13.20,0:44:13.50,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:44:14.48,0:44:18.75,EN,,0,0,0,,PROFESSOR: So you have a pattern variable that is to be given a value in a dictionary.\nDialogue: 0,0:44:19.45,0:44:22.11,EN,,0,0,0,,PROFESSOR: The value is the expression that it matched against.\nDialogue: 0,0:44:23.31,0:44:29.63,EN,,0,0,0,,The dictionary is the set of things I've already figured out that I have memorized or learned.\nDialogue: 0,0:44:30.54,0:44:34.41,EN,,0,0,0,,And I am going to make a new dictionary, which is extended from the original one\nDialogue: 0,0:44:35.12,0:44:38.35,EN,,0,0,0,,by having that pattern variable have a value with the new dictionary.\nDialogue: 0,0:44:39.98,0:44:43.73,EN,,0,0,0,,AUDIENCE: I guess what I don't understand is why can't the substitution be made right as soon as you find--\nDialogue: 0,0:44:43.73,0:44:44.80,EN,,0,0,0,,PROFESSOR: How do I know what I'm going to substitute?\nDialogue: 0,0:44:44.81,0:44:46.62,EN,,0,0,0,,I don't know anything about this skeleton.\nDialogue: 0,0:44:47.58,0:44:49.66,EN,,0,0,0,,This pattern, this matcher is an independent unit.\nDialogue: 0,0:44:49.66,0:44:51.00,EN,,0,0,0,,AUDIENCE: Oh, I see. OK.\nDialogue: 0,0:44:51.00,0:44:51.50,EN,,0,0,0,,PROFESSOR: Right?\nDialogue: 0,0:44:51.50,0:44:51.90,EN,,0,0,0,,AUDIENCE: Yeah.\nDialogue: 0,0:44:51.90,0:44:57.23,EN,,0,0,0,,PROFESSOR: I take the matcher. I apply the matcher. If it matches, then it was worth doing instantiation.\nDialogue: 0,0:44:58.20,0:44:59.50,EN,,0,0,0,,AUDIENCE: OK, good.\nDialogue: 0,0:45:00.54,0:45:03.88,EN,,0,0,0,,AUDIENCE: Can you just do that answer again using that example on the board?\nDialogue: 0,0:45:04.89,0:45:06.93,EN,,0,0,0,,You know, what you just passed back to the matcher.\nDialogue: 0,0:45:06.93,0:45:08.00,EN,,0,0,0,,PROFESSOR: Oh yes. OK, yes.\nDialogue: 0,0:45:08.26,0:45:09.74,EN,,0,0,0,,You're looking at this example.\nDialogue: 0,0:45:10.67,0:45:15.45,EN,,0,0,0,,At this point when I'm traversing this structure, I get to here: x.\nDialogue: 0,0:45:16.67,0:45:20.54,EN,,0,0,0,,I have some dictionary, presumably an empty dictionary at this point if this is the whole expression.\nDialogue: 0,0:45:21.56,0:45:25.36,EN,,0,0,0,,So I have an empty dictionary, and I've matched x against 3.\nDialogue: 0,0:45:26.62,0:45:33.60,EN,,0,0,0,,So now, after this point,the dictionary contains x is 3, OK?\nDialogue: 0,0:45:33.64,0:45:36.09,EN,,0,0,0,,Now, I continue walking along here. I see y.\nDialogue: 0,0:45:36.89,0:45:39.20,EN,,0,0,0,,Now, this is a particular x, a pattern x.\nDialogue: 0,0:45:39.79,0:45:41.37,EN,,0,0,0,,I see y, a pattern y.\nDialogue: 0,0:45:42.17,0:45:47.74,EN,,0,0,0,,The dictionary says, oh yes, the pattern y is the symbol x\nDialogue: 0,0:45:48.99,0:45:51.20,EN,,0,0,0,,because I've gota match there.\nDialogue: 0,0:45:52.43,0:45:54.52,EN,,0,0,0,,So the dictionary now contains at this point two entries.\nDialogue: 0,0:45:55.45,0:45:59.90,EN,,0,0,0,,The pattern x is 3, and the pattern y is the expression x.\nDialogue: 0,0:46:01.95,0:46:04.11,EN,,0,0,0,,Now, I get that, I can walk along further.\nDialogue: 0,0:46:04.23,0:46:07.45,EN,,0,0,0,,I say, oh, pattern y also wants to be 4.\nDialogue: 0,0:46:08.06,0:46:10.65,EN,,0,0,0,,But that isn't possible, producing a failure.\nDialogue: 0,0:46:14.30,0:46:15.48,EN,,0,0,0,,Thank you. Let's take a break.\nDialogue: 0,0:46:16.76,0:46:25.02,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:46:25.07,0:46:27.45,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:46:27.47,0:46:30.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:46:48.19,0:46:54.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}The Structure And Interpretation of Computer Programs\nDialogue: 0,0:46:55.20,0:46:58.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}Pattern-matching: Rule-based Substitution\nDialogue: 0,0:47:02.38,0:47:05.68,EN,,0,0,0,,OK, you're seeing your first very big and hairy program.\nDialogue: 0,0:47:07.34,0:47:09.90,EN,,0,0,0,,Now, of course, one of the goals of this subject\nDialogue: 0,0:47:09.90,0:47:12.97,EN,,0,0,0,,is to get you to be able to read something like this and not be afraid of it.\nDialogue: 0,0:47:13.76,0:47:16.33,EN,,0,0,0,,This one's only about four pages of code.\nDialogue: 0,0:47:17.08,0:47:19.23,EN,,0,0,0,,By the end of the subject, I hope a 50-page program\nDialogue: 0,0:47:20.27,0:47:21.80,EN,,0,0,0,,will not look particularly frightening.\nDialogue: 0,0:47:22.97,0:47:28.20,EN,,0,0,0,,But I don't expect-- and I don't want you to think that I expect you to be getting it as it's coming out.\nDialogue: 0,0:47:29.20,0:47:31.70,EN,,0,0,0,,You're supposed to feel the flavor of this, OK?\nDialogue: 0,0:47:31.70,0:47:34.83,EN,,0,0,0,,And then you're supposed to think about it because it is a big program.\nDialogue: 0,0:47:35.32,0:47:38.92,EN,,0,0,0,,There's a lot of stuff inside this program.\nDialogue: 0,0:47:41.24,0:47:46.03,EN,,0,0,0,,Now, I've told you about the language we're implementing, the pattern match substitution language.\nDialogue: 0,0:47:46.81,0:47:47.64,EN,,0,0,0,,I showed you some rules.\nDialogue: 0,0:47:48.36,0:47:51.24,EN,,0,0,0,,And I've told you about matching and instantiation,\nDialogue: 0,0:47:51.55,0:47:53.32,EN,,0,0,0,,which are the two halves of how a rule works.\nDialogue: 0,0:47:54.24,0:47:56.35,EN,,0,0,0,,Now we have to understand the control structure\nDialogue: 0,0:47:56.86,0:48:00.32,EN,,0,0,0,,by which the rules are applied to the expressions\nDialogue: 0,0:48:01.08,0:48:03.84,EN,,0,0,0,,so as to do algebraic simplification.\nDialogue: 0,0:48:06.92,0:48:09.58,EN,,0,0,0,,Now, that's also a big complicated mess.\nDialogue: 0,0:48:12.09,0:48:19.48,EN,,0,0,0,,The problem is that there is a variety of interlocking, interwoven loops, if you will, involved in this.\nDialogue: 0,0:48:20.24,0:48:26.99,EN,,0,0,0,,For one thing, I have to apply-- I have to examine every subexpression of my expression that I'm trying to simplify.\nDialogue: 0,0:48:29.00,0:48:29.93,EN,,0,0,0,,That we know how to do.\nDialogue: 0,0:48:29.93,0:48:36.24,EN,,0,0,0,,It's a car cdr recursion of some sort, or something like that, and some sort of tree walk.\nDialogue: 0,0:48:37.44,0:48:38.59,EN,,0,0,0,,And that's going to be happening.\nDialogue: 0,0:48:38.84,0:48:42.46,EN,,0,0,0,,Now, for every such place, every node that I get to\nDialogue: 0,0:48:43.47,0:48:48.76,EN,,0,0,0,,in doing my traversal of the expression I'm trying to simplify,\nDialogue: 0,0:48:49.20,0:48:51.07,EN,,0,0,0,,I want to apply all of the rules.\nDialogue: 0,0:48:53.42,0:48:55.08,EN,,0,0,0,,Every rule is going to look at every node.\nDialogue: 0,0:48:56.00,0:48:57.92,EN,,0,0,0,,I'm going to rotate the rules around.\nDialogue: 0,0:49:01.66,0:49:05.48,EN,,0,0,0,,Now, either a rule will or will not match.\nDialogue: 0,0:49:07.50,0:49:10.62,EN,,0,0,0,,If the rule does not match, then it's not very interesting.\nDialogue: 0,0:49:12.28,0:49:19.34,EN,,0,0,0,,If the rule does match, then I'm going to replace that node in the expression by an alternate expression.\nDialogue: 0,0:49:20.08,0:49:22.89,EN,,0,0,0,,I'm actually going to make a new expression, which contains--\nDialogue: 0,0:49:23.55,0:49:28.65,EN,,0,0,0,,everything contains that new value, the result of substituting into the skeleton,\nDialogue: 0,0:49:29.21,0:49:31.92,EN,,0,0,0,,instantiating the skeleton for that rule at this level.\nDialogue: 0,0:49:32.72,0:49:37.37,EN,,0,0,0,,But no one knows whether that thing that I instantiated there is in simplified form.\nDialogue: 0,0:49:38.75,0:49:43.82,EN,,0,0,0,,So we're going to have to simplify that, somehow to call the simplifier on the thing that I just constructed.\nDialogue: 0,0:49:46.12,0:49:50.36,EN,,0,0,0,,And then when that's done, then I sort of can build that into the expression I want as my answer.\nDialogue: 0,0:49:51.80,0:49:57.45,EN,,0,0,0,,Now, there is a basic idea here, which I will call a garbage- in, garbage-out simplifier.\nDialogue: 0,0:50:01.47,0:50:02.75,EN,,0,0,0,,It's a kind of recursive simplifier.\nDialogue: 0,0:50:03.58,0:50:08.84,EN,,0,0,0,,And what happens is the way simplify something is that simple objects like variables are simple.\nDialogue: 0,0:50:10.78,0:50:13.28,EN,,0,0,0,,Compound objects, well, I don't know.\nDialogue: 0,0:50:14.09,0:50:16.56,EN,,0,0,0,,What I'm going to do is I'm going to build up from simple objects,\nDialogue: 0,0:50:16.86,0:50:21.23,EN,,0,0,0,,trying to make simple things by assuming that the pieces they're made out of are simple.\nDialogue: 0,0:50:24.60,0:50:25.61,EN,,0,0,0,,That's what's happening here.\nDialogue: 0,0:50:27.82,0:50:33.12,EN,,0,0,0,,Well, now, if we look at the first slide-- no, overhead, overhead.\nDialogue: 0,0:50:33.88,0:50:37.13,EN,,0,0,0,,If we look at the overhead, we see a very complicated program like we saw before for the matcher,\nDialogue: 0,0:50:37.53,0:50:39.95,EN,,0,0,0,,so complicated that you can't read it like that.\nDialogue: 0,0:50:41.92,0:50:43.61,EN,,0,0,0,,I just want you to get the feel of the shape of it,\nDialogue: 0,0:50:44.44,0:50:50.01,EN,,0,0,0,,and the shape of it is that this program has various subprograms in it.\nDialogue: 0,0:50:52.11,0:50:57.56,EN,,0,0,0,,One of them--this part is the part for traversing the expression,\nDialogue: 0,0:50:58.97,0:51:01.36,EN,,0,0,0,,and this part is the part for trying rules.\nDialogue: 0,0:51:02.52,0:51:05.60,EN,,0,0,0,,Now, of course, we can look at that in some more detail.\nDialogue: 0,0:51:06.89,0:51:11.80,EN,,0,0,0,,Let's look at--let's look at the first transparency, right?\nDialogue: 0,0:51:13.40,0:51:17.36,EN,,0,0,0,,The simplifier is made out of several parts.\nDialogue: 0,0:51:17.96,0:51:22.92,EN,,0,0,0,,Now, remember at the very beginning, the simplifier is the thing which takes a rules-- a set of rules\nDialogue: 0,0:51:23.92,0:51:27.20,EN,,0,0,0,,and produces a program which will simplify it relative to them.\nDialogue: 0,0:51:30.04,0:51:32.60,EN,,0,0,0,,So here we have our simplifier.\nDialogue: 0,0:51:33.48,0:51:34.81,EN,,0,0,0,,It takes a rule set.\nDialogue: 0,0:51:36.16,0:51:38.68,EN,,0,0,0,,And in the context where that rule set is defined,\nDialogue: 0,0:51:39.24,0:51:41.48,EN,,0,0,0,,there are various other definitions that are done here.\nDialogue: 0,0:51:42.33,0:51:46.20,EN,,0,0,0,,And then the result of this simplifier procedure is,\nDialogue: 0,0:51:46.41,0:51:50.80,EN,,0,0,0,,in fact, one of the procedures that was defined. Simplify-exp.\nDialogue: 0,0:51:52.46,0:51:57.71,EN,,0,0,0,,What I'm returning as the value of calling the simplifier on a set of rules\nDialogue: 0,0:51:58.17,0:52:03.21,EN,,0,0,0,,is a procedure the simplify exp procedure, which is defined in that context,\nDialogue: 0,0:52:05.23,0:52:08.83,EN,,0,0,0,,which is a simplification procedure appropriate for using those set of rules.\nDialogue: 0,0:52:15.04,0:52:15.96,EN,,0,0,0,,That's what I have there.\nDialogue: 0,0:52:17.45,0:52:21.79,EN,,0,0,0,,Now, the first two of these procedures, this one and this one,\nDialogue: 0,0:52:22.48,0:52:25.74,EN,,0,0,0,,are together going to be the recursive traversal of an expression.\nDialogue: 0,0:52:26.97,0:52:30.20,EN,,0,0,0,,This one is the general simplification for any expression,\nDialogue: 0,0:52:30.94,0:52:33.23,EN,,0,0,0,,and this is the thing which simplifies a list of parts of an expression.\nDialogue: 0,0:52:35.53,0:52:36.08,EN,,0,0,0,,Nothing more.\nDialogue: 0,0:52:37.04,0:52:39.90,EN,,0,0,0,,For each of those, we're going to do something complicated, which involves trying the rules.\nDialogue: 0,0:52:40.32,0:52:41.71,EN,,0,0,0,,Now, we should look at the various parts.\nDialogue: 0,0:52:45.76,0:52:48.08,EN,,0,0,0,,Well let's look first at the recursive traversal of an expression.\nDialogue: 0,0:52:48.57,0:52:51.68,EN,,0,0,0,,And this is done in a sort of simple way.\nDialogue: 0,0:52:54.28,0:52:57.93,EN,,0,0,0,,This is a little nest of recursive procedures.\nDialogue: 0,0:52:59.42,0:53:01.77,EN,,0,0,0,,And what we have here are two procedures--\nDialogue: 0,0:53:02.59,0:53:05.20,EN,,0,0,0,,one for simplifying an expression,\nDialogue: 0,0:53:06.11,0:53:08.16,EN,,0,0,0,,and one for simplifying parts of an expression.\nDialogue: 0,0:53:09.44,0:53:10.97,EN,,0,0,0,,And the way this works is very simple.\nDialogue: 0,0:53:12.12,0:53:16.86,EN,,0,0,0,,If the expression I'm trying to simplify is a compound expression,\nDialogue: 0,0:53:17.04,0:53:18.32,EN,,0,0,0,,I'm going to simplify all the parts of it.\nDialogue: 0,0:53:19.95,0:53:22.32,EN,,0,0,0,,And that's calling--that procedure, simplify parts,\nDialogue: 0,0:53:22.33,0:53:25.74,EN,,0,0,0,,is going to make up a new expression with all the parts simplified,\nDialogue: 0,0:53:26.00,0:53:28.64,EN,,0,0,0,,which I'm then going to try the rules on over here.\nDialogue: 0,0:53:30.86,0:53:34.22,EN,,0,0,0,,If it turns out that the expression is not compound, if it's simple,\nDialogue: 0,0:53:34.76,0:53:37.13,EN,,0,0,0,,like just a symbol or something like pi,\nDialogue: 0,0:53:38.16,0:53:39.79,EN,,0,0,0,,then in any case, I'm going to try the rules on it\nDialogue: 0,0:53:40.03,0:53:47.56,EN,,0,0,0,,because it might be that I want in my set of rules to expand pi to 3.14159265358979,dot, dot, dot.\nDialogue: 0,0:53:48.46,0:53:49.08,EN,,0,0,0,,But I may not.\nDialogue: 0,0:53:50.11,0:53:51.52,EN,,0,0,0,,But there is no reason not to do it.\nDialogue: 0,0:53:52.75,0:53:57.53,EN,,0,0,0,,Now, if I want to simplify the parts, well, that's easy too.\nDialogue: 0,0:53:58.99,0:54:02.88,EN,,0,0,0,,Either the expression is an empty one, there's no more parts,\nDialogue: 0,0:54:03.71,0:54:05.08,EN,,0,0,0,,in which case I have the empty expression.\nDialogue: 0,0:54:05.72,0:54:10.52,EN,,0,0,0,,Otherwise, I'm going to make a new expression by cons,\nDialogue: 0,0:54:11.21,0:54:14.27,EN,,0,0,0,,which is the result of simplifying the first part of the expression, the car,\nDialogue: 0,0:54:15.42,0:54:17.39,EN,,0,0,0,,and simplifying the rest of the expression, which is the cdr.\nDialogue: 0,0:54:21.08,0:54:23.88,EN,,0,0,0,,Now, the reason why I'm showing you this sort of stuff this way\nDialogue: 0,0:54:24.88,0:54:30.12,EN,,0,0,0,,is because I want you get the feeling for the various patterns that are very important when writing programs.\nDialogue: 0,0:54:32.20,0:54:34.00,EN,,0,0,0,,And this could be written a different way.\nDialogue: 0,0:54:34.00,0:54:36.99,EN,,0,0,0,,There's another way to write simplified expressions so there would be only one of them.\nDialogue: 0,0:54:37.72,0:54:39.63,EN,,0,0,0,,There would only be one little procedure here.\nDialogue: 0,0:54:39.63,0:54:42.36,EN,,0,0,0,,Let me just write that on the blackboard to give you a feeling for that.\nDialogue: 0,0:54:49.71,0:54:51.90,EN,,0,0,0,,This is in another idiom, if you will.\nDialogue: 0,0:54:59.30,0:55:03.13,EN,,0,0,0,,To simplify an expression called exp, what am I going to do?\nDialogue: 0,0:55:03.21,0:55:10.14,EN,,0,0,0,,I'm going to try the rules on the following situation.\nDialogue: 0,0:55:11.12,0:55:15.72,EN,,0,0,0,,If-- on the following expression-- compound, just like we had before.\nDialogue: 0,0:55:21.52,0:55:24.27,EN,,0,0,0,,If the expression is compound, well, what am I going to do?\nDialogue: 0,0:55:24.53,0:55:25.40,EN,,0,0,0,,I'm going to simplify all the parts.\nDialogue: 0,0:55:26.01,0:55:27.80,EN,,0,0,0,,But I already have a cdr recursion,\nDialogue: 0,0:55:30.25,0:55:33.18,EN,,0,0,0,,common pattern of usage, which has been captured as a high-order procedure.\nDialogue: 0,0:55:34.09,0:55:34.46,EN,,0,0,0,,It's called map.\nDialogue: 0,0:55:36.08,0:55:36.88,EN,,0,0,0,,So I'll just write that here.\nDialogue: 0,0:55:37.16,0:55:48.03,EN,,0,0,0,,Map simplify the expression, all the parts of the expression.\nDialogue: 0,0:55:49.00,0:55:54.59,EN,,0,0,0,,This says apply the simplification operation, which is this one, every part of the expression,\nDialogue: 0,0:55:55.34,0:55:57.34,EN,,0,0,0,,and then that cons those up into a list.\nDialogue: 0,0:56:00.92,0:56:04.38,EN,,0,0,0,,It's every element of the list which the expression is assumed to be made out of,\nDialogue: 0,0:56:05.45,0:56:08.23,EN,,0,0,0,,and otherwise, I have the expression.\nDialogue: 0,0:56:09.05,0:56:12.36,EN,,0,0,0,,So I don't need the helper procedure, simplify parts,\nDialogue: 0,0:56:12.64,0:56:13.48,EN,,0,0,0,,because that's really this.\nDialogue: 0,0:56:15.47,0:56:17.05,EN,,0,0,0,,So sometimes, you just write it this way.\nDialogue: 0,0:56:17.84,0:56:18.70,EN,,0,0,0,,It doesn't matter very much.\nDialogue: 0,0:56:21.16,0:56:26.27,EN,,0,0,0,,Well, now let's take a look at-- let's just look at how you try rules.\nDialogue: 0,0:56:27.70,0:56:31.60,EN,,0,0,0,,If you look at this slide, we see this is a complicated mess also.\nDialogue: 0,0:56:33.68,0:56:35.28,EN,,0,0,0,,I'm trying rules on an expression.\nDialogue: 0,0:56:36.36,0:56:39.96,EN,,0,0,0,,It turns out the expression I'm trying it on is some subexpression now of the expression I started with.\nDialogue: 0,0:56:40.43,0:56:43.88,EN,,0,0,0,,Because the thing I just arranged allowed us to try every subexpression.\nDialogue: 0,0:56:46.11,0:56:51.90,EN,,0,0,0,,So now here we're taking in a subexpression of the expression we started with. That's what this is.\nDialogue: 0,0:56:52.49,0:56:57.71,EN,,0,0,0,,And what we're going to define here is a procedure called scan, which is going to try every rule.\nDialogue: 0,0:56:58.72,0:57:00.33,EN,,0,0,0,,And we're going to start it up on the whole set of rules.\nDialogue: 0,0:57:01.92,0:57:07.77,EN,,0,0,0,,This is going to go cdr-ing down the rules, if you will, looking for a rule to apply.\nDialogue: 0,0:57:09.37,0:57:11.96,EN,,0,0,0,,And when it finds one, it'll do the job.\nDialogue: 0,0:57:14.09,0:57:16.41,EN,,0,0,0,,Well, let's take a look at how try rules works.\nDialogue: 0,0:57:17.74,0:57:21.02,EN,,0,0,0,,It's very simple: the scan rules. Scan rules, the way of scanning.\nDialogue: 0,0:57:21.96,0:57:23.26,EN,,0,0,0,,Well, is it so simple?\nDialogue: 0,0:57:23.26,0:57:24.51,EN,,0,0,0,,It's a big program, of course.\nDialogue: 0,0:57:25.55,0:57:28.57,EN,,0,0,0,,We take a bunch of rules, which is a sublist of the list of rules.\nDialogue: 0,0:57:30.75,0:57:35.13,EN,,0,0,0,,We've tried some of them already, and they've not been appropriate, so we get to some here.\nDialogue: 0,0:57:35.87,0:57:36.30,EN,,0,0,0,,next one.\nDialogue: 0,0:57:36.40,0:57:37.63,EN,,0,0,0,,If there are no more rules,\nDialogue: 0,0:57:37.90,0:57:40.84,EN,,0,0,0,,well then, there's nothing I can do with this expression, and it's simplified.\nDialogue: 0,0:57:42.35,0:57:47.26,EN,,0,0,0,,However, if it turns out that there are still rules to be done,\nDialogue: 0,0:57:48.01,0:57:51.58,EN,,0,0,0,,then let's match the pattern of the first rule\nDialogue: 0,0:57:52.20,0:57:55.40,EN,,0,0,0,,against the expression using the empty dictionary to start with\nDialogue: 0,0:57:57.07,0:57:58.84,EN,,0,0,0,,and use that as the dictionary.\nDialogue: 0,0:58:00.32,0:58:03.74,EN,,0,0,0,,If that happens to be a failure, try the rest of the rules.\nDialogue: 0,0:58:06.68,0:58:07.52,EN,,0,0,0,,That's all it says here.\nDialogue: 0,0:58:08.52,0:58:10.33,EN,,0,0,0,,How it says, it says discard that rule.\nDialogue: 0,0:58:11.10,0:58:15.05,EN,,0,0,0,,Otherwise, well, I'm going to get the skeleton of the first rule,\nDialogue: 0,0:58:15.34,0:58:17.40,EN,,0,0,0,,instantiate that relative to the dictionary,\nDialogue: 0,0:58:17.93,0:58:20.80,EN,,0,0,0,,and simplify the result, and that's the expression I want.\nDialogue: 0,0:58:24.20,0:58:25.96,EN,,0,0,0,,So although that was a complicated program,\nDialogue: 0,0:58:26.25,0:58:28.72,EN,,0,0,0,,every complicated program is made out of a lot of simple pieces.\nDialogue: 0,0:58:29.77,0:58:33.12,EN,,0,0,0,,Now, the pattern of recursions here is very complicated.\nDialogue: 0,0:58:34.78,0:58:36.52,EN,,0,0,0,,And one of the most important things is not to think about that.\nDialogue: 0,0:58:38.67,0:58:41.80,EN,,0,0,0,,If you try to think about the actual pattern by which this does something,\nDialogue: 0,0:58:42.06,0:58:42.97,EN,,0,0,0,,you're going to get very confused.\nDialogue: 0,0:58:45.31,0:58:45.71,EN,,0,0,0,,I would.\nDialogue: 0,0:58:47.04,0:58:50.17,EN,,0,0,0,,This is not a matter. you can do this with practice.\nDialogue: 0,0:58:51.52,0:58:52.46,EN,,0,0,0,,These patterns are hard.\nDialogue: 0,0:58:54.17,0:58:55.42,EN,,0,0,0,,But you don't have to think about it.\nDialogue: 0,0:58:55.83,0:58:59.72,EN,,0,0,0,,The key to this-- it's very good programming and very good design--\nDialogue: 0,0:58:59.74,0:59:00.97,EN,,0,0,0,,is to know what not to think about.\nDialogue: 0,0:59:03.05,0:59:06.06,EN,,0,0,0,,The fact is, going back to this slide,\nDialogue: 0,0:59:06.92,0:59:08.01,EN,,0,0,0,,I don't have to think about it\nDialogue: 0,0:59:08.54,0:59:13.83,EN,,0,0,0,,because I have specifications in my mind for what simplify x does.\nDialogue: 0,0:59:14.00,0:59:15.24,EN,,0,0,0,,I don't have to know how it does it.\nDialogue: 0,0:59:17.08,0:59:21.24,EN,,0,0,0,,And it may, in fact, call scan somehow through try rules, which it does.\nDialogue: 0,0:59:22.24,0:59:24.09,EN,,0,0,0,,And somehow, I've got another recursion going on here.\nDialogue: 0,0:59:24.33,0:59:25.69,EN,,0,0,0,,But since I know that simplify exp\nDialogue: 0,0:59:26.84,0:59:30.40,EN,,0,0,0,,is assumed by wishful thinking to produce the simplified result,\nDialogue: 0,0:59:31.61,0:59:32.99,EN,,0,0,0,,then I don't have to think about it anymore.\nDialogue: 0,0:59:33.43,0:59:34.83,EN,,0,0,0,,I've used it.\nDialogue: 0,0:59:35.07,0:59:36.43,EN,,0,0,0,,I've used it in a reasonable way.\nDialogue: 0,0:59:36.43,0:59:37.45,EN,,0,0,0,,I will get a reasonable answer.\nDialogue: 0,0:59:39.95,0:59:42.57,EN,,0,0,0,,And you have to learn how to program that way-- with abandon.\nDialogue: 0,0:59:47.56,0:59:49.05,EN,,0,0,0,,Well, there's very little left of this thing.\nDialogue: 0,0:59:50.40,0:59:54.46,EN,,0,0,0,,All there is left is a few details associated with what a dictionary is.\nDialogue: 0,0:59:55.08,0:59:58.32,EN,,0,0,0,,And those of you who've been itching to know what a dictionary is,\nDialogue: 0,0:59:58.70,1:00:01.82,EN,,0,0,0,,well, I will flip it up and not tell you anything about it.\nDialogue: 0,1:00:04.14,1:00:05.20,EN,,0,0,0,,Dictionaries are easy.\nDialogue: 0,1:00:06.01,1:00:09.84,EN,,0,0,0,,It's represented in terms of something else called an A list,\nDialogue: 0,1:00:10.65,1:00:16.04,EN,,0,0,0,,which is a particular pattern of usage for making tables in lists.\nDialogue: 0,1:00:16.50,1:00:20.17,EN,,0,0,0,,They're easy. They're made out of pairs, as was asked a bit ago.\nDialogue: 0,1:00:21.21,1:00:24.62,EN,,0,0,0,,And there are special procedures for dealing with such things called assq,\nDialogue: 0,1:00:24.94,1:00:26.36,EN,,0,0,0,,and you can find them in manuals.\nDialogue: 0,1:00:27.04,1:00:28.59,EN,,0,0,0,,I'm not terribly excited about it.\nDialogue: 0,1:00:28.83,1:00:31.21,EN,,0,0,0,,The only interesting thing here in extend dictionary\nDialogue: 0,1:00:31.48,1:00:36.94,EN,,0,0,0,,is I have to extend the dictionary with a pattern, a datum, and a dictionary.\nDialogue: 0,1:00:37.42,1:00:42.38,EN,,0,0,0,,I wish that, this pattern is, in fact, at this point a pattern variable.\nDialogue: 0,1:00:43.74,1:00:47.53,EN,,0,0,0,,And what do I want to do? I want to pull out the name of that pattern variable\nDialogue: 0,1:00:48.16,1:00:49.42,EN,,0,0,0,,the pattern variable name,\nDialogue: 0,1:00:50.44,1:00:53.71,EN,,0,0,0,,and I'm going to look up in the dictionary and see if it already has a value.\nDialogue: 0,1:00:53.79,1:00:56.41,EN,,0,0,0,,If not, I'm going to add a new one in.\nDialogue: 0,1:00:56.92,1:00:59.23,EN,,0,0,0,,If it does have one, if it has a value,\nDialogue: 0,1:00:59.60,1:01:03.18,EN,,0,0,0,,then it had better be equal to the one that was already stored away.\nDialogue: 0,1:01:03.88,1:01:06.54,EN,,0,0,0,,And if that's the case, the dictionary is what I expected it to be.\nDialogue: 0,1:01:06.89,1:01:09.15,EN,,0,0,0,,Otherwise, I fail.\nDialogue: 0,1:01:12.08,1:01:12.89,EN,,0,0,0,,So that's easy, too.\nDialogue: 0,1:01:13.66,1:01:16.68,EN,,0,0,0,,If you open up any program, you're going to find inside of it lots of little pieces,\nDialogue: 0,1:01:17.18,1:01:18.30,EN,,0,0,0,,all of which are easy.\nDialogue: 0,1:01:20.04,1:01:21.29,EN,,0,0,0,,So at this point, I suppose,\nDialogue: 0,1:01:21.60,1:01:25.68,EN,,0,0,0,,I've just told you some million-dollar valuable information.\nDialogue: 0,1:01:28.41,1:01:30.96,EN,,0,0,0,,And I suppose at this point we're pretty much done with this program.\nDialogue: 0,1:01:31.85,1:01:32.72,EN,,0,0,0,,I'd like to ask about questions.\nDialogue: 0,1:01:34.27,1:01:38.16,EN,,0,0,0,,AUDIENCE: Yes, can you give me the words that describe the specification for a simplified expression?\nDialogue: 0,1:01:38.72,1:01:39.02,EN,,0,0,0,,PROFESSOR: Sure.\nDialogue: 0,1:01:39.85,1:01:44.33,EN,,0,0,0,,A simplified expression takes an expression and produces a simplified expression.\nDialogue: 0,1:01:45.28,1:01:45.77,EN,,0,0,0,,That's it, OK?\nDialogue: 0,1:01:48.11,1:01:50.27,EN,,0,0,0,,How it does it is very easy.\nDialogue: 0,1:01:51.60,1:01:56.09,EN,,0,0,0,,In compound expressions, all the pieces are simplified, and then the rules are tried on the result.\nDialogue: 0,1:01:56.89,1:01:58.49,EN,,0,0,0,,And for simple expressions, you just try all the rules.\nDialogue: 0,1:01:59.52,1:02:02.11,EN,,0,0,0,,AUDIENCE: So an expression is simplified by virtue of the rules?\nDialogue: 0,1:02:02.76,1:02:03.58,EN,,0,0,0,,PROFESSOR: That's, of course, true.\nDialogue: 0,1:02:03.76,1:02:03.90,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,1:02:04.06,1:02:07.13,EN,,0,0,0,,PROFESSOR: And the way this works is that simplified expression, as you see here,\nDialogue: 0,1:02:08.35,1:02:11.64,EN,,0,0,0,,what it does is it breaks the expression down into the smallest pieces,\nDialogue: 0,1:02:12.60,1:02:17.29,EN,,0,0,0,,simplifies building up from the bottom using the rules to be the simplifier,\nDialogue: 0,1:02:18.30,1:02:22.48,EN,,0,0,0,,to do the manipulations, and constructs a new expression as the result.\nDialogue: 0,1:02:24.28,1:02:29.44,EN,,0,0,0,,Eventually, one of things you see is that the rules themselves, the try rules,\nDialogue: 0,1:02:29.70,1:02:35.50,EN,,0,0,0,,call a simplified expression on the results when it changes something, the results of a match.\nDialogue: 0,1:02:35.80,1:02:40.64,EN,,0,0,0,,I'm sorry, the results of instantiation of a skeleton for a rule that has matched.\nDialogue: 0,1:02:42.00,1:02:47.36,EN,,0,0,0,,So the spec of a simplified expression is that any expression you put into it comes out simplified according to those rules.\nDialogue: 0,1:02:49.84,1:02:50.76,EN,,0,0,0,,Thank you. Let's take a break.\n"
  },
  {
    "path": "Ass/lec4b.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 2664\nActive Line: 2669\nVideo Position: 149956\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:11.40,0:00:16.50,EN,,0,0,0,,Generic Operators\nDialogue: 0,0:00:20.18,0:00:21.84,EN,,0,0,0,,PROFESSOR: So far in this course we've been talking\nDialogue: 0,0:00:21.84,0:00:23.78,EN,,0,0,0,,a lot about data abstraction.\nDialogue: 0,0:00:23.78,0:00:27.15,EN,,0,0,0,,And remember the idea is that we build systems\nDialogue: 0,0:00:27.74,0:00:32.56,EN,,0,0,0,,that have these horizontal barriers in them, these abstraction barriers\nDialogue: 0,0:00:33.42,0:00:39.21,EN,,0,0,0,,that separate use, the way you might use some data object,\nDialogue: 0,0:00:39.93,0:00:41.18,EN,,0,0,0,,from the way you might represent it.\nDialogue: 0,0:00:49.40,0:00:52.03,EN,,0,0,0,,Or another way to think of that is up here you have the boss\nDialogue: 0,0:00:52.11,0:00:55.50,EN,,0,0,0,,who's going to be using some sort of data object.\nDialogue: 0,0:00:57.11,0:01:02.31,EN,,0,0,0,,And down here is George who's implemented it.\nDialogue: 0,0:01:02.31,0:01:05.42,EN,,0,0,0,,Now this notion of separating use from representation\nDialogue: 0,0:01:05.44,0:01:09.76,EN,,0,0,0,,so you can think about these two problems separately\nDialogue: 0,0:01:10.60,0:01:14.76,EN,,0,0,0,,is a very,very powerful programming methodology, data abstraction.\nDialogue: 0,0:01:15.93,0:01:18.81,EN,,0,0,0,,On the other hand, it's not really sufficient\nDialogue: 0,0:01:19.56,0:01:21.84,EN,,0,0,0,,for really complex systems.\nDialogue: 0,0:01:22.96,0:01:27.64,EN,,0,0,0,,And the problem with this is George.\nDialogue: 0,0:01:28.64,0:01:32.09,EN,,0,0,0,,Or actually, the problem is that\nDialogue: 0,0:01:32.09,0:01:32.78,EN,,0,0,0,,there are a lot of Georges.\nDialogue: 0,0:01:34.63,0:01:35.39,EN,,0,0,0,,Let's be concrete.\nDialogue: 0,0:01:35.39,0:01:39.18,EN,,0,0,0,,Let's suppose there is George,and there's also Martha.\nDialogue: 0,0:01:41.19,0:01:44.22,EN,,0,0,0,,OK, now George and Martha are both working on this system,\nDialogue: 0,0:01:46.04,0:01:47.29,EN,,0,0,0,,both designing representations,\nDialogue: 0,0:01:48.41,0:01:50.67,EN,,0,0,0,,and absolutely are incompatible.\nDialogue: 0,0:01:51.75,0:01:53.62,EN,,0,0,0,,They wouldn't cooperate on a representation\nDialogue: 0,0:01:54.01,0:01:55.34,EN,,0,0,0,,under any circumstances.\nDialogue: 0,0:01:57.48,0:01:59.72,EN,,0,0,0,,And the problem is you would like to have some system\nDialogue: 0,0:02:00.06,0:02:02.60,EN,,0,0,0,,where both George and Martha are designing representations,\nDialogue: 0,0:02:03.82,0:02:08.08,EN,,0,0,0,,and, yet, if you're above this abstraction barrier\nDialogue: 0,0:02:09.40,0:02:11.04,EN,,0,0,0,,you don't want to have to worry about that,\nDialogue: 0,0:02:11.66,0:02:14.18,EN,,0,0,0,,whether something is done by George or by Martha.\nDialogue: 0,0:02:14.18,0:02:15.43,EN,,0,0,0,,And you don't want George and Martha to\nDialogue: 0,0:02:15.43,0:02:16.48,EN,,0,0,0,,interfere with each other.\nDialogue: 0,0:02:16.63,0:02:20.31,EN,,0,0,0,,Somehow in designing a system, you not only want these\nDialogue: 0,0:02:20.31,0:02:23.84,EN,,0,0,0,,horizontal barriers, but you also want some kind of\nDialogue: 0,0:02:25.82,0:02:30.64,EN,,0,0,0,,some kind of vertical barrier to keep George and Martha separate.\nDialogue: 0,0:02:32.98,0:02:35.40,EN,,0,0,0,,Let me be a little bit more concrete.\nDialogue: 0,0:02:36.56,0:02:40.54,EN,,0,0,0,,Imagine that you're thinking about personnel records\nDialogue: 0,0:02:41.18,0:02:46.11,EN,,0,0,0,,for a large company with a lot of loosely linked divisions\nDialogue: 0,0:02:47.90,0:02:49.71,EN,,0,0,0,,that don't cooperate very well either.\nDialogue: 0,0:02:50.43,0:02:57.04,EN,,0,0,0,,And imagine even that this company is formed by merging a\nDialogue: 0,0:02:57.04,0:02:59.45,EN,,0,0,0,,whole bunch of companies that already have their personnel\nDialogue: 0,0:02:59.45,0:03:00.70,EN,,0,0,0,,record system set up.\nDialogue: 0,0:03:03.25,0:03:06.57,EN,,0,0,0,,And imagine that once these divisions are all linked in\nDialogue: 0,0:03:06.57,0:03:08.53,EN,,0,0,0,,some kind of very sophisticated satellite\nDialogue: 0,0:03:08.53,0:03:10.52,EN,,0,0,0,,network, and all these databases are put together.\nDialogue: 0,0:03:12.24,0:03:13.85,EN,,0,0,0,,And what you'd like to do\nDialogue: 0,0:03:14.84,0:03:16.33,EN,,0,0,0,,is from any place in the company,\nDialogue: 0,0:03:17.26,0:03:23.13,EN,,0,0,0,,to be able to say things like,oh, what's the name in a\nDialogue: 0,0:03:23.13,0:03:23.87,EN,,0,0,0,,personnel record?\nDialogue: 0,0:03:26.30,0:03:29.15,EN,,0,0,0,,Or, what's the job description in a personnel record?\nDialogue: 0,0:03:30.54,0:03:34.40,EN,,0,0,0,,And not have to worry about the fact that each division\nDialogue: 0,0:03:34.84,0:03:36.76,EN,,0,0,0,,obviously is going to have completely separate\nDialogue: 0,0:03:36.76,0:03:39.37,EN,,0,0,0,,conventions for how you might implement these records.\nDialogue: 0,0:03:41.58,0:03:43.26,EN,,0,0,0,,From this point you don't want to know about that.\nDialogue: 0,0:03:44.96,0:03:47.92,EN,,0,0,0,,Well how could you possibly do that?\nDialogue: 0,0:03:48.43,0:03:52.41,EN,,0,0,0,,One way, of course, is to send down an edict from somewhere\nDialogue: 0,0:03:52.64,0:03:56.29,EN,,0,0,0,,that everybody has to change their format to some fixed\nDialogue: 0,0:03:56.29,0:03:57.24,EN,,0,0,0,,compatible thing.\nDialogue: 0,0:03:58.07,0:04:00.12,EN,,0,0,0,,That's what people often try, and of course it never works.\nDialogue: 0,0:04:01.82,0:04:07.34,EN,,0,0,0,,Another thing that you might want to do is somehow arrange\nDialogue: 0,0:04:08.33,0:04:09.90,EN,,0,0,0,,it so you can have these vertical barriers.\nDialogue: 0,0:04:11.25,0:04:14.40,EN,,0,0,0,,So that when you ask for the name of a personnel record,\nDialogue: 0,0:04:14.43,0:04:17.97,EN,,0,0,0,,somehow, whatever format it happens to be, name will\nDialogue: 0,0:04:17.97,0:04:19.42,EN,,0,0,0,,figure out how to do the right thing.\nDialogue: 0,0:04:22.73,0:04:25.53,EN,,0,0,0,,We want name to be, so-called, a generic operator.\nDialogue: 0,0:04:26.26,0:04:30.06,EN,,0,0,0,,Generic operator means what it sort of precisely does depends\nDialogue: 0,0:04:30.06,0:04:31.69,EN,,0,0,0,,on the kind of data that it's looking at.\nDialogue: 0,0:04:33.65,0:04:36.62,EN,,0,0,0,,More than that, you'd like to design the system so that the\nDialogue: 0,0:04:36.92,0:04:39.79,EN,,0,0,0,,next time a new division comes into the company\nDialogue: 0,0:04:42.51,0:04:45.64,EN,,0,0,0,,they don't have to make any big changes in what they're already doing\nDialogue: 0,0:04:45.64,0:04:50.11,EN,,0,0,0,,to link into this system, and the rest of the company\nDialogue: 0,0:04:50.11,0:04:52.01,EN,,0,0,0,,doesn't have to make any big changes\nDialogue: 0,0:04:52.27,0:04:53.93,EN,,0,0,0,,to admit their stuff to the system.\nDialogue: 0,0:04:55.52,0:04:57.52,EN,,0,0,0,,So that's the problem you should be thinking about.\nDialogue: 0,0:04:58.70,0:05:00.77,EN,,0,0,0,,Like it's sort of just your work.\nDialogue: 0,0:05:00.77,0:05:03.77,EN,,0,0,0,,You want to be able to include new things by making minimal changes.\nDialogue: 0,0:05:05.98,0:05:08.12,EN,,0,0,0,,OK, well that's the problem that we'll be talking about today.\nDialogue: 0,0:05:09.44,0:05:14.22,EN,,0,0,0,,And you should have this sort of distributed personnel record system in your mind.\nDialogue: 0,0:05:14.24,0:05:16.62,EN,,0,0,0,,But actually the one I'll be talking about is a problem\nDialogue: 0,0:05:16.62,0:05:18.48,EN,,0,0,0,,that's a little bit more self-contained than that.\nDialogue: 0,0:05:19.29,0:05:21.76,EN,,0,0,0,,that'll bring up the issues, I think, more clearly.\nDialogue: 0,0:05:21.87,0:05:26.01,EN,,0,0,0,,That's the problem of doing a system that does arithmetic on complex numbers.\nDialogue: 0,0:05:27.77,0:05:28.92,EN,,0,0,0,,So let's take a look here.\nDialogue: 0,0:05:30.69,0:05:31.74,EN,,0,0,0,,Just as a little review,\nDialogue: 0,0:05:32.04,0:05:33.53,EN,,0,0,0,,there are things called complex numbers.\nDialogue: 0,0:05:35.25,0:05:38.22,EN,,0,0,0,,Complex number you can think of as a point in the plane, or z.\nDialogue: 0,0:05:39.37,0:05:47.19,EN,,0,0,0,,And you can represent a point either by its real-part and its imaginary-part.\nDialogue: 0,0:05:47.19,0:05:50.83,EN,,0,0,0,,So if this is z and its real-part is this much,\nDialogue: 0,0:05:51.50,0:05:53.24,EN,,0,0,0,,and its imaginary-part is that much,\nDialogue: 0,0:05:54.33,0:05:56.44,EN,,0,0,0,,and you write z equals x plus iy.\nDialogue: 0,0:05:59.11,0:06:03.21,EN,,0,0,0,,Or another way to represent a complex number is by saying,\nDialogue: 0,0:06:03.21,0:06:09.00,EN,,0,0,0,,what's the distance from the origin, and what's the angle?\nDialogue: 0,0:06:11.32,0:06:16.67,EN,,0,0,0,,So that represents a complex number as its radius times an angle.\nDialogue: 0,0:06:19.52,0:06:21.92,EN,,0,0,0,,This one's called -- the original one's called rectangular form,\nDialogue: 0,0:06:22.59,0:06:25.45,EN,,0,0,0,,rectangular representation, real- and imaginary-part\nDialogue: 0,0:06:26.20,0:06:30.04,EN,,0,0,0,,or polar representation magnitude and angle--\nDialogue: 0,0:06:30.04,0:06:31.48,EN,,0,0,0,,and if you know the real- and imaginary-part,\nDialogue: 0,0:06:31.53,0:06:33.36,EN,,0,0,0,,you can figure out the magnitude and angle.\nDialogue: 0,0:06:33.72,0:06:36.97,EN,,0,0,0,,If you know x and y, you can get r by this formula.\nDialogue: 0,0:06:37.19,0:06:39.48,EN,,0,0,0,,Square root of sum of the squares, and you can get the\nDialogue: 0,0:06:39.48,0:06:40.76,EN,,0,0,0,,angle as an arctangent.\nDialogue: 0,0:06:41.42,0:06:44.42,EN,,0,0,0,,Or conversely, if you knew r and A you could\nDialogue: 0,0:06:44.42,0:06:45.31,EN,,0,0,0,,figure out x and y.\nDialogue: 0,0:06:45.80,0:06:49.43,EN,,0,0,0,,x is r times the cosine of A, and y is r times the sine of A.\nDialogue: 0,0:06:51.34,0:06:53.66,EN,,0,0,0,,All right, so there's these two. They're complex numbers.\nDialogue: 0,0:06:54.13,0:06:57.15,EN,,0,0,0,,You can think of them either in polar form or rectangular form.\nDialogue: 0,0:06:57.15,0:06:58.12,EN,,0,0,0,,What we would like to do\nDialogue: 0,0:06:58.32,0:07:01.32,EN,,0,0,0,,is make a system that does arithmetic on complex numbers.\nDialogue: 0,0:07:03.95,0:07:05.12,EN,,0,0,0,,In other words, what we'd like--\nDialogue: 0,0:07:05.58,0:07:06.99,EN,,0,0,0,,just like the rational number example--\nDialogue: 0,0:07:07.38,0:07:10.20,EN,,0,0,0,,is to have some operations plus c,\nDialogue: 0,0:07:10.73,0:07:13.90,EN,,0,0,0,,which is going to take two complex numbers and add them, subtract them,\nDialogue: 0,0:07:14.35,0:07:16.94,EN,,0,0,0,,and multiply them, and divide them.\nDialogue: 0,0:07:20.73,0:07:25.28,EN,,0,0,0,,OK, well there's little bit of mathematics behind it.\nDialogue: 0,0:07:25.28,0:07:28.36,EN,,0,0,0,,What are the actual formulas for manipulating such things?\nDialogue: 0,0:07:30.41,0:07:31.92,EN,,0,0,0,,And it's sort of not important where they come from,\nDialogue: 0,0:07:34.00,0:07:35.79,EN,,0,0,0,,but just as an implementer let's see--\nDialogue: 0,0:07:35.80,0:07:37.95,EN,,0,0,0,,if you want to add two complex numbers it's pretty easy to\nDialogue: 0,0:07:39.13,0:07:42.66,EN,,0,0,0,,it's pretty easy to get its real-part and its imaginary-part.\nDialogue: 0,0:07:42.66,0:07:45.93,EN,,0,0,0,,The real-part of the sum of two complex numbers\nDialogue: 0,0:07:47.72,0:07:49.72,EN,,0,0,0,,real-part of the z1 plus z2\nDialogue: 0,0:07:50.06,0:07:54.64,EN,,0,0,0,,is the real-part of z1 plus the real-part of z2.\nDialogue: 0,0:07:57.82,0:08:01.60,EN,,0,0,0,,And the imaginary-part of z1 plus z2\nDialogue: 0,0:08:01.74,0:08:05.66,EN,,0,0,0,,is the imaginary part of z1 plus the imaginary part of z2.\nDialogue: 0,0:08:07.41,0:08:09.48,EN,,0,0,0,,So it's pretty easy to add complex numbers.\nDialogue: 0,0:08:09.48,0:08:10.99,EN,,0,0,0,,You just add the corresponding parts\nDialogue: 0,0:08:11.31,0:08:13.18,EN,,0,0,0,,and make a new complex number with those parts.\nDialogue: 0,0:08:13.37,0:08:14.73,EN,,0,0,0,,If you want to multiply them,\nDialogue: 0,0:08:15.53,0:08:17.82,EN,,0,0,0,,it's kind of nice to do it in polar form.\nDialogue: 0,0:08:17.82,0:08:20.38,EN,,0,0,0,,Because if you have two complex numbers,\nDialogue: 0,0:08:20.40,0:08:26.54,EN,,0,0,0,,the magnitude of their product is here, the product of the magnitudes.\nDialogue: 0,0:08:28.85,0:08:33.88,EN,,0,0,0,,And the angle of the product is the sum of the angles.\nDialogue: 0,0:08:35.80,0:08:40.54,EN,,0,0,0,,So that's sort of mathematics that allows you to do arithmetic on complex numbers.\nDialogue: 0,0:08:40.54,0:08:42.38,EN,,0,0,0,,Let's actually think about the implementation.\nDialogue: 0,0:08:43.72,0:08:47.39,EN,,0,0,0,,Well we do it just like rational numbers.\nDialogue: 0,0:08:49.84,0:08:53.47,EN,,0,0,0,,We come down, we assume we have some constructors and selectors.\nDialogue: 0,0:08:53.76,0:08:54.52,EN,,0,0,0,,What would we like?\nDialogue: 0,0:08:55.33,0:08:58.16,EN,,0,0,0,,Well let's assume that we make a data object cloud,\nDialogue: 0,0:08:58.54,0:09:00.78,EN,,0,0,0,,which is a complex number that has some stuff in it,\nDialogue: 0,0:09:01.79,0:09:04.67,EN,,0,0,0,,and that we can get out from a complex number the real-part,\nDialogue: 0,0:09:05.52,0:09:09.64,EN,,0,0,0,,or the imaginary-part, or the magnitude, or the angle.\nDialogue: 0,0:09:12.15,0:09:14.01,EN,,0,0,0,,We want some ways of making complex numbers--\nDialogue: 0,0:09:14.03,0:09:15.64,EN,,0,0,0,,not only selectors, but constructors.\nDialogue: 0,0:09:16.80,0:09:19.52,EN,,0,0,0,,So we'll assume we have a thing called make-rectangular.\nDialogue: 0,0:09:19.53,0:09:24.27,EN,,0,0,0,,What make-rectangular is going to do is take a real-part and\nDialogue: 0,0:09:24.51,0:09:29.36,EN,,0,0,0,,an imaginary-part and construct a complex number with those parts.\nDialogue: 0,0:09:31.92,0:09:35.01,EN,,0,0,0,,Similarly, we can have make-polar which will taking\nDialogue: 0,0:09:35.01,0:09:37.85,EN,,0,0,0,,a magnitude and an angle,\nDialogue: 0,0:09:40.83,0:09:43.90,EN,,0,0,0,,and construct a complex number which has that magnitude and angle.\nDialogue: 0,0:09:44.68,0:09:45.46,EN,,0,0,0,,So here's a system.\nDialogue: 0,0:09:45.46,0:09:47.77,EN,,0,0,0,,We'll have two constructors and four selectors.\nDialogue: 0,0:09:48.91,0:09:55.15,EN,,0,0,0,,And now, just like before, in terms of that abstract data\nDialogue: 0,0:09:55.15,0:09:59.22,EN,,0,0,0,,we'll go ahead and implement our complex number operations.\nDialogue: 0,0:09:59.22,0:10:02.30,EN,,0,0,0,,And here you can see translated into Lisp code\nDialogue: 0,0:10:03.23,0:10:07.47,EN,,0,0,0,,just the arithmetic formulas I put down before.\nDialogue: 0,0:10:08.06,0:10:09.98,EN,,0,0,0,,If I want to add two complex numbers\nDialogue: 0,0:10:11.76,0:10:15.56,EN,,0,0,0,,I will make a complex number out of its real- and imaginary-parts.\nDialogue: 0,0:10:16.72,0:10:19.02,EN,,0,0,0,,The real part of the complex number I'm going to make\nDialogue: 0,0:10:19.40,0:10:21.80,EN,,0,0,0,,is the sum of the real-parts.\nDialogue: 0,0:10:23.31,0:10:25.37,EN,,0,0,0,,The imaginary part of the complex number I'm going to make\nDialogue: 0,0:10:25.40,0:10:27.52,EN,,0,0,0,,is the sum of the imaginary-parts.\nDialogue: 0,0:10:30.31,0:10:32.09,EN,,0,0,0,,I put those together, make a complex number.\nDialogue: 0,0:10:32.16,0:10:34.44,EN,,0,0,0,,That's how I implement complex number addition.\nDialogue: 0,0:10:35.78,0:10:38.49,EN,,0,0,0,,Subtraction is essentially the same.\nDialogue: 0,0:10:39.65,0:10:42.97,EN,,0,0,0,,All I do is subtract the parts rather than add them.\nDialogue: 0,0:10:45.14,0:10:47.07,EN,,0,0,0,,To multiply two complex numbers,\nDialogue: 0,0:10:47.74,0:10:49.02,EN,,0,0,0,,I use the other formula.\nDialogue: 0,0:10:49.27,0:10:53.84,EN,,0,0,0,,I'll make a complex number out of a magnitude and angle.\nDialogue: 0,0:10:55.35,0:10:56.44,EN,,0,0,0,,The magnitude\nDialogue: 0,0:10:56.65,0:11:00.97,EN,,0,0,0,,is going to be the product of the magnitudesof the two complex numbers I'm multiplying.\nDialogue: 0,0:11:03.71,0:11:05.93,EN,,0,0,0,,And the angle is going to be the sum\nDialogue: 0,0:11:06.16,0:11:08.51,EN,,0,0,0,,of the angles of the z1two complex numbers I'm multiplying.\nDialogue: 0,0:11:09.62,0:11:10.96,EN,,0,0,0,,So there's multiplication.\nDialogue: 0,0:11:11.23,0:11:12.25,EN,,0,0,0,,And then division,\nDialogue: 0,0:11:14.27,0:11:15.90,EN,,0,0,0,,division is almost the same.\nDialogue: 0,0:11:17.37,0:11:19.58,EN,,0,0,0,,Here I divide the magnitudes and subtract the angles.\nDialogue: 0,0:11:28.36,0:11:30.46,EN,,0,0,0,,Now I've implemented the operations.\nDialogue: 0,0:11:31.87,0:11:33.64,EN,,0,0,0,,And what do we do?\nDialogue: 0,0:11:33.64,0:11:34.52,EN,,0,0,0,,We call on George.\nDialogue: 0,0:11:36.06,0:11:38.79,EN,,0,0,0,,We've done the use, let's worry about the representation.\nDialogue: 0,0:11:38.80,0:11:40.94,EN,,0,0,0,,We'll call on George and say to George,\nDialogue: 0,0:11:40.97,0:11:43.61,EN,,0,0,0,,go ahead and build us a complex number representation.\nDialogue: 0,0:11:45.25,0:11:47.44,EN,,0,0,0,,Well that's fine...ahhh\nDialogue: 0,0:11:47.77,0:11:52.66,EN,,0,0,0,,George can say, we'll implement a complex number\nDialogue: 0,0:11:52.66,0:11:57.15,EN,,0,0,0,,simply as a pair that has the real-part and the imaginary-part.\nDialogue: 0,0:11:57.20,0:12:02.62,EN,,0,0,0,,So if I want to make a complex number with a certain real-part and an imaginary-part,\nDialogue: 0,0:12:03.36,0:12:05.55,EN,,0,0,0,,I'll just use cons to form a pair, and that will--\nDialogue: 0,0:12:06.03,0:12:08.11,EN,,0,0,0,,that's George's representation of a complex number.\nDialogue: 0,0:12:09.78,0:12:12.42,EN,,0,0,0,,So if I want to get out the real-part of something, I just\nDialogue: 0,0:12:12.42,0:12:14.12,EN,,0,0,0,,extract the car, the first part.\nDialogue: 0,0:12:14.35,0:12:16.67,EN,,0,0,0,,If I want to get the imaginary-part, I extract the cdr\nDialogue: 0,0:12:19.64,0:12:21.77,EN,,0,0,0,,How do I deal with the magnitude and angle?\nDialogue: 0,0:12:22.22,0:12:25.75,EN,,0,0,0,,Well if I want to extract the magnitude of one of these things\nDialogue: 0,0:12:25.75,0:12:32.30,EN,,0,0,0,,I get the square root of the sum of the square of the car plus the square of the cdr.\nDialogue: 0,0:12:33.79,0:12:39.26,EN,,0,0,0,,If I want to get the angle, I compute the arctangent of the cdr in the car.\nDialogue: 0,0:12:39.53,0:12:42.86,EN,,0,0,0,,This is a lisp procedure for computing arctangent.\nDialogue: 0,0:12:44.97,0:12:48.59,EN,,0,0,0,,And if somebody hands me a magnitude and an angle\nDialogue: 0,0:12:48.94,0:12:50.56,EN,,0,0,0,,and says, make me a complex number,well I compute the\nDialogue: 0,0:12:50.89,0:12:56.24,EN,,0,0,0,,well I compute the real-part and the imaginary-part, r * cosine of a and r * sine of a,\nDialogue: 0,0:12:57.77,0:12:59.05,EN,,0,0,0,,and stick them together into a pair.\nDialogue: 0,0:13:01.46,0:13:02.26,EN,,0,0,0,,OK so we're done.\nDialogue: 0,0:13:02.26,0:13:04.75,EN,,0,0,0,,In fact, what I just did, conceptually,\nDialogue: 0,0:13:06.89,0:13:09.37,EN,,0,0,0,,is absolutely no different from the rational number\nDialogue: 0,0:13:10.60,0:13:12.44,EN,,0,0,0,,representation that we looked at last time.\nDialogue: 0,0:13:12.75,0:13:13.91,EN,,0,0,0,,It's the same sort of idea.\nDialogue: 0,0:13:13.91,0:13:16.28,EN,,0,0,0,,You implement the operators, you pick a representation.\nDialogue: 0,0:13:18.07,0:13:18.65,EN,,0,0,0,,Nothing different.\nDialogue: 0,0:13:20.07,0:13:21.56,EN,,0,0,0,,Now let's worry about Martha.\nDialogue: 0,0:13:23.21,0:13:24.52,EN,,0,0,0,,See, Martha has a different idea.\nDialogue: 0,0:13:26.67,0:13:28.57,EN,,0,0,0,,She doesn't want to represent a complex number\nDialogue: 0,0:13:28.59,0:13:30.90,EN,,0,0,0,,as a pair of a real-part and an imaginary-part.\nDialogue: 0,0:13:30.90,0:13:34.17,EN,,0,0,0,,What she would like to do is represent a complex number as\nDialogue: 0,0:13:34.17,0:13:37.69,EN,,0,0,0,,a pair of a magnitude and an angle.\nDialogue: 0,0:13:39.55,0:13:42.13,EN,,0,0,0,,So if instead of calling up George we ask Martha to design\nDialogue: 0,0:13:42.13,0:13:43.74,EN,,0,0,0,,our representation, we get something like this.\nDialogue: 0,0:13:44.57,0:13:47.16,EN,,0,0,0,,We get make-polar.\nDialogue: 0,0:13:47.16,0:13:50.22,EN,,0,0,0,,Sure, if I give you a magnitude and an angle we're\nDialogue: 0,0:13:50.22,0:13:53.07,EN,,0,0,0,,just going to form a pair that has magnitude and angle.\nDialogue: 0,0:13:55.43,0:13:57.68,EN,,0,0,0,,If you want to extract the magnitude, that's easy.\nDialogue: 0,0:13:58.24,0:13:59.37,EN,,0,0,0,,You just pull out the car or the pair.\nDialogue: 0,0:13:59.78,0:14:02.67,EN,,0,0,0,,If you want to extract the angle, sure, that's easy.\nDialogue: 0,0:14:02.67,0:14:03.63,EN,,0,0,0,,You just pull out the cdr.\nDialogue: 0,0:14:04.81,0:14:07.02,EN,,0,0,0,,If you want to look for real-parts and imaginary-parts,\nDialogue: 0,0:14:07.42,0:14:08.49,EN,,0,0,0,,well then you have to do some work.\nDialogue: 0,0:14:08.88,0:14:14.58,EN,,0,0,0,,If you want the real-part, you have to get r cosine a.\nDialogue: 0,0:14:14.58,0:14:19.99,EN,,0,0,0,,In other words, r, the car of the pair, times the cosine of\nDialogue: 0,0:14:19.99,0:14:20.95,EN,,0,0,0,,the cdr of the pair.\nDialogue: 0,0:14:20.95,0:14:26.23,EN,,0,0,0,,So this is r times the cosine of a,\nDialogue: 0,0:14:26.54,0:14:27.48,EN,,0,0,0,,and that's the real-part.\nDialogue: 0,0:14:28.33,0:14:31.40,EN,,0,0,0,,If you want to get the imaginary-part, it's r times the sine of a.\nDialogue: 0,0:14:32.66,0:14:37.93,EN,,0,0,0,,And if I hand you a real-part and an imaginary-part and say,\nDialogue: 0,0:14:37.93,0:14:42.03,EN,,0,0,0,,make me a complex number with that real-part and\nDialogue: 0,0:14:42.03,0:14:44.17,EN,,0,0,0,,imaginary-part, well I figure out what the magnitude and\nDialogue: 0,0:14:44.17,0:14:45.54,EN,,0,0,0,,angle should be.\nDialogue: 0,0:14:45.54,0:14:47.85,EN,,0,0,0,,The magnitude's the square root of the sum of the squares\nDialogue: 0,0:14:48.09,0:14:49.23,EN,,0,0,0,,and the angle's the arctangent.\nDialogue: 0,0:14:49.23,0:14:50.22,EN,,0,0,0,,I put those together to make a pair.\nDialogue: 0,0:14:52.09,0:14:54.17,EN,,0,0,0,,So there's Martha's idea.\nDialogue: 0,0:14:56.69,0:14:57.37,EN,,0,0,0,,Well which is better?\nDialogue: 0,0:14:59.68,0:15:03.15,EN,,0,0,0,,Well if you're doing a lot of additions, probably George's is better\nDialogue: 0,0:15:03.16,0:15:05.61,EN,,0,0,0,,is better, because you're doing a lot of real-parts and imaginary-parts.\nDialogue: 0,0:15:05.85,0:15:08.40,EN,,0,0,0,,If mostly you're going to be doing multiplications and divisions,\nDialogue: 0,0:15:09.48,0:15:11.14,EN,,0,0,0,,then maybe Martha's idea is better.\nDialogue: 0,0:15:11.14,0:15:14.84,EN,,0,0,0,,Or maybe, and this is the real point, you can't decide.\nDialogue: 0,0:15:16.59,0:15:22.32,EN,,0,0,0,,Or maybe you just have to let them both hang around, for personality reasons.\nDialogue: 0,0:15:23.48,0:15:26.76,EN,,0,0,0,,Maybe you just really can't ever decide what you would like.\nDialogue: 0,0:15:28.56,0:15:32.32,EN,,0,0,0,,And again, what we would really like is a system that looks like this.\nDialogue: 0,0:15:32.65,0:15:36.17,EN,,0,0,0,,That somehow there's George over here, who has built\nDialogue: 0,0:15:36.83,0:15:39.64,EN,,0,0,0,,rectangular complex numbers.\nDialogue: 0,0:15:41.47,0:15:44.25,EN,,0,0,0,,And Martha, who has polar complex numbers.\nDialogue: 0,0:15:46.12,0:15:49.69,EN,,0,0,0,,And somehow we have operations\nDialogue: 0,0:15:50.28,0:15:56.89,EN,,0,0,0,,that can add, and subtract, and multiply, and divide\nDialogue: 0,0:15:57.56,0:15:58.76,EN,,0,0,0,,and it shouldn't matter\nDialogue: 0,0:15:59.34,0:16:02.79,EN,,0,0,0,,that there are two incompatible representations of complex\nDialogue: 0,0:16:02.79,0:16:03.98,EN,,0,0,0,,numbers floating around this system.\nDialogue: 0,0:16:04.41,0:16:08.33,EN,,0,0,0,,In other words, not only like an abstraction barrier here\nDialogue: 0,0:16:09.64,0:16:11.84,EN,,0,0,0,,that has things in it like a real-part,\nDialogue: 0,0:16:15.77,0:16:21.71,EN,,0,0,0,,and an imaginary-part, and magnitude,and angle.\nDialogue: 0,0:16:23.83,0:16:25.36,EN,,0,0,0,,So not only is there an abstraction barrier\nDialogue: 0,0:16:25.39,0:16:28.38,EN,,0,0,0,,that hides the actual representation from us,\nDialogue: 0,0:16:29.10,0:16:31.52,EN,,0,0,0,,but also there's some kind of vertical barrier here\nDialogue: 0,0:16:32.19,0:16:35.02,EN,,0,0,0,,that allows both of these representations to exist\nDialogue: 0,0:16:35.87,0:16:37.40,EN,,0,0,0,,without interfering with each other.\nDialogue: 0,0:16:38.57,0:16:41.07,EN,,0,0,0,,The idea is that the things in here--\nDialogue: 0,0:16:41.90,0:16:44.12,EN,,0,0,0,,real-part, imaginary-part,magnitude, and angle--\nDialogue: 0,0:16:44.12,0:16:46.49,EN,,0,0,0,,will be generic operators.\nDialogue: 0,0:16:47.31,0:16:49.45,EN,,0,0,0,,If you ask for the real-part, it will worry about\nDialogue: 0,0:16:49.98,0:16:51.31,EN,,0,0,0,,what representation it's looking at.\nDialogue: 0,0:16:53.88,0:16:55.10,EN,,0,0,0,,OK, well how can we do that?\nDialogue: 0,0:16:56.84,0:16:59.23,EN,,0,0,0,,There's actually a really obvious idea,\nDialogue: 0,0:16:59.84,0:17:01.68,EN,,0,0,0,,if you're used to thinking about complex numbers.\nDialogue: 0,0:17:02.52,0:17:04.44,EN,,0,0,0,,If you're used to thinking about compound data.\nDialogue: 0,0:17:06.33,0:17:10.99,EN,,0,0,0,,See, suppose you could just tell by looking at a complex number\nDialogue: 0,0:17:12.17,0:17:13.95,EN,,0,0,0,,whether it was constructed by George or Martha.\nDialogue: 0,0:17:15.79,0:17:18.90,EN,,0,0,0,,In other words, so it's not that what's floating around\nDialogue: 0,0:17:18.90,0:17:20.91,EN,,0,0,0,,here are ordinary, just complex numbers, right?\nDialogue: 0,0:17:20.91,0:17:22.94,EN,,0,0,0,,They're fancy, designer complex numbers.\nDialogue: 0,0:17:24.39,0:17:28.04,EN,,0,0,0,,So you look at a complex numbers as it's not just a complex number\nDialogue: 0,0:17:28.04,0:17:29.16,EN,,0,0,0,,it's got a label on it that says,\nDialogue: 0,0:17:29.19,0:17:30.75,EN,,0,0,0,,that one is by Martha.\nDialogue: 0,0:17:31.45,0:17:34.22,EN,,0,0,0,,Or this is a complex number by George.\nDialogue: 0,0:17:34.48,0:17:35.39,EN,,0,0,0,,Right? They're signed.\nDialogue: 0,0:17:36.86,0:17:40.15,EN,,0,0,0,,See, and then whenever we looked at a complex number we\nDialogue: 0,0:17:40.15,0:17:45.48,EN,,0,0,0,,could just read the label, and then we'd know how you expect\nDialogue: 0,0:17:45.80,0:17:46.72,EN,,0,0,0,,to operate on that.\nDialogue: 0,0:17:48.03,0:17:51.19,EN,,0,0,0,,In other words, what we want is not just ordinary data objects.\nDialogue: 0,0:17:51.19,0:17:54.37,EN,,0,0,0,,We want to introduce the notion of what's called typed data.\nDialogue: 0,0:17:59.76,0:18:02.81,EN,,0,0,0,,Typed data means, again, there's some sort of cloud.\nDialogue: 0,0:18:03.94,0:18:08.93,EN,,0,0,0,,And what it's got in it is an ordinary data object like\nDialogue: 0,0:18:08.93,0:18:09.90,EN,,0,0,0,,we've been thinking about.\nDialogue: 0,0:18:13.18,0:18:16.54,EN,,0,0,0,,Pulled out the contents, sort of the actual data.\nDialogue: 0,0:18:19.32,0:18:21.56,EN,,0,0,0,,But also a thing called a type,\nDialogue: 0,0:18:22.56,0:18:25.24,EN,,0,0,0,,but it's signed by either George or Martha.\nDialogue: 0,0:18:25.99,0:18:28.27,EN,,0,0,0,,So we're going to go from regular data to type data.\nDialogue: 0,0:18:31.95,0:18:32.71,EN,,0,0,0,,How do we build that?\nDialogue: 0,0:18:32.71,0:18:33.50,EN,,0,0,0,,Well that's easy.\nDialogue: 0,0:18:33.84,0:18:35.32,EN,,0,0,0,,We know how to build clouds.\nDialogue: 0,0:18:35.80,0:18:36.88,EN,,0,0,0,,We can build them out of pairs.\nDialogue: 0,0:18:37.92,0:18:41.82,EN,,0,0,0,,So here's a little representation that supports typed data.\nDialogue: 0,0:18:43.51,0:18:49.64,EN,,0,0,0,,There's a thing called take a type and attach it to a piece of contents,\nDialogue: 0,0:18:49.69,0:18:50.64,EN,,0,0,0,,and we just use cons.\nDialogue: 0,0:18:51.64,0:18:54.11,EN,,0,0,0,,And if we have a piece of typed data, we can look at the type\nDialogue: 0,0:18:55.21,0:18:56.00,EN,,0,0,0,,which is the car.\nDialogue: 0,0:18:56.29,0:18:58.30,EN,,0,0,0,,We can look at the contents,which is the cdr.\nDialogue: 0,0:18:59.96,0:19:04.28,EN,,0,0,0,,Now along with that, the way we use our type data will test,\nDialogue: 0,0:19:05.29,0:19:07.26,EN,,0,0,0,,when we're given a piece of data, what type it is.\nDialogue: 0,0:19:07.52,0:19:09.26,EN,,0,0,0,,So we have some type predicates with us.\nDialogue: 0,0:19:10.51,0:19:13.73,EN,,0,0,0,,For example, to see whether a complex number is one of\nDialogue: 0,0:19:13.73,0:19:16.86,EN,,0,0,0,,George's, whether it's rectangular, we just check to\nDialogue: 0,0:19:16.86,0:19:21.85,EN,,0,0,0,,see if the type of that is the symbol rectangular,\nDialogue: 0,0:19:23.68,0:19:25.05,EN,,0,0,0,,right? The symbol rectangular.\nDialogue: 0,0:19:27.20,0:19:30.33,EN,,0,0,0,,And to check whether a complex number is one of Martha's,\nDialogue: 0,0:19:30.33,0:19:33.42,EN,,0,0,0,,we check to see whether the type is the symbol polar.\nDialogue: 0,0:19:36.46,0:19:39.21,EN,,0,0,0,,So that's a way to test what kind of number we're looking at.\nDialogue: 0,0:19:40.75,0:19:42.81,EN,,0,0,0,,Now let's think about how we can use that to build the system.\nDialogue: 0,0:19:43.87,0:19:46.73,EN,,0,0,0,,So let's suppose that George and Martha were off working separately,\nDialogue: 0,0:19:47.36,0:19:52.64,EN,,0,0,0,,and each of them had designed their complex number representation packages.\nDialogue: 0,0:19:52.64,0:19:58.52,EN,,0,0,0,,What do they have to do to become part of the system,\nDialogue: 0,0:19:58.73,0:20:00.14,EN,,0,0,0,,to exist compatibly?\nDialogue: 0,0:20:00.14,0:20:02.11,EN,,0,0,0,,Well it's really pretty easy.\nDialogue: 0,0:20:02.72,0:20:04.51,EN,,0,0,0,,Remember, George had this package.\nDialogue: 0,0:20:05.97,0:20:08.48,EN,,0,0,0,,Here's George's original package, or half of it.\nDialogue: 0,0:20:08.98,0:20:11.15,EN,,0,0,0,,And underlined in red are the changes he has to make.\nDialogue: 0,0:20:12.09,0:20:16.43,EN,,0,0,0,,So before, when George made a complex number out of an x and y\nDialogue: 0,0:20:17.52,0:20:19.85,EN,,0,0,0,,he just put them together to make a pair.\nDialogue: 0,0:20:20.93,0:20:23.39,EN,,0,0,0,,And the only difference is that now he signs them.\nDialogue: 0,0:20:24.09,0:20:28.08,EN,,0,0,0,,He attaches the type, which is the symbol rectangular to that pair.\nDialogue: 0,0:20:30.60,0:20:33.26,EN,,0,0,0,,Everything else George does is the same, except that--\nDialogue: 0,0:20:33.92,0:20:38.06,EN,,0,0,0,,see, George and Martha both have procedures named real-part and imaginary-part.\nDialogue: 0,0:20:38.70,0:20:42.96,EN,,0,0,0,,So to allow them both to exist in the same Lisp environment,\nDialogue: 0,0:20:44.22,0:20:45.92,EN,,0,0,0,,George had changed the names of his procedures.\nDialogue: 0,0:20:45.92,0:20:49.14,EN,,0,0,0,,So we'll say, this is George's real-part procedure.\nDialogue: 0,0:20:49.14,0:20:51.16,EN,,0,0,0,,It's the real-part-rectangular procedure,\nDialogue: 0,0:20:51.48,0:20:54.06,EN,,0,0,0,,the imaginary-part-rectangular procedure.\nDialogue: 0,0:20:55.42,0:20:57.24,EN,,0,0,0,,And then here's the rest of George's package.\nDialogue: 0,0:20:59.13,0:21:02.06,EN,,0,0,0,,He'd had magnitude and angle, just renames them magnitude\nDialogue: 0,0:21:02.06,0:21:04.16,EN,,0,0,0,,rectangular and angle rectangular.\nDialogue: 0,0:21:06.08,0:21:07.96,EN,,0,0,0,,And Martha has to do basically the same thing.\nDialogue: 0,0:21:09.86,0:21:16.22,EN,,0,0,0,,Martha previously, when she made a complex number out of a magnitude and angle,\nDialogue: 0,0:21:18.14,0:21:19.27,EN,,0,0,0,,she just cons them.\nDialogue: 0,0:21:19.27,0:21:20.86,EN,,0,0,0,,Now she attaches the type polar,\nDialogue: 0,0:21:23.95,0:21:25.61,EN,,0,0,0,,and she changes the name\nDialogue: 0,0:21:25.66,0:21:29.85,EN,,0,0,0,,so her real-part procedure won't conflict in name with George's.\nDialogue: 0,0:21:30.71,0:21:32.99,EN,,0,0,0,,It's a real-part-polar,imaginary-part-polar,\nDialogue: 0,0:21:34.54,0:21:38.06,EN,,0,0,0,,magnitude polar, and angle polar.\nDialogue: 0,0:21:45.00,0:21:46.13,EN,,0,0,0,,Now we have the system.\nDialogue: 0,0:21:46.13,0:21:47.92,EN,,0,0,0,,Right there's George and Martha.\nDialogue: 0,0:21:49.16,0:21:51.68,EN,,0,0,0,,And now we've got to get some kind of manager to look at these types.\nDialogue: 0,0:21:52.83,0:21:56.48,EN,,0,0,0,,How are these things actually going to work now\nDialogue: 0,0:21:57.05,0:21:59.40,EN,,0,0,0,,that George and Martha have supplied us with typed data?\nDialogue: 0,0:22:00.53,0:22:04.30,EN,,0,0,0,,Well what we have are a bunch of generic selectors.\nDialogue: 0,0:22:05.26,0:22:10.63,EN,,0,0,0,,Generic selectors for complex numbers real-part,imaginary-part, magnitude, and angle.\nDialogue: 0,0:22:14.14,0:22:15.40,EN,,0,0,0,,Let's look at them more closely.\nDialogue: 0,0:22:17.93,0:22:19.00,EN,,0,0,0,,What does a real-part do?\nDialogue: 0,0:22:19.31,0:22:22.76,EN,,0,0,0,,If I ask for the real part of a complex number,\nDialogue: 0,0:22:24.07,0:22:24.91,EN,,0,0,0,,well I look at it.\nDialogue: 0,0:22:25.80,0:22:26.69,EN,,0,0,0,,I look at its type.\nDialogue: 0,0:22:26.69,0:22:28.12,EN,,0,0,0,,I say, is it rectangular?\nDialogue: 0,0:22:31.02,0:22:35.36,EN,,0,0,0,,If so, I apply George's real part procedure\nDialogue: 0,0:22:36.06,0:22:37.92,EN,,0,0,0,,to the contents of that complex number.\nDialogue: 0,0:22:41.07,0:22:42.94,EN,,0,0,0,,This is a number that has a type on it.\nDialogue: 0,0:22:43.72,0:22:47.66,EN,,0,0,0,,I strip off the type using contents and apply George's procedure.\nDialogue: 0,0:22:50.70,0:22:52.86,EN,,0,0,0,,Or is this a polar complex number?\nDialogue: 0,0:22:53.95,0:22:54.97,EN,,0,0,0,,If I want the real part,\nDialogue: 0,0:22:55.45,0:22:58.78,EN,,0,0,0,,I apply Martha's real-part procedure to the contents of that number.\nDialogue: 0,0:22:59.85,0:23:01.15,EN,,0,0,0,,So that's how real part works.\nDialogue: 0,0:23:02.26,0:23:05.66,EN,,0,0,0,,And then similarly there's imaginary-part, which is almost the same.\nDialogue: 0,0:23:06.51,0:23:09.60,EN,,0,0,0,,Right? It looks at the number and if it's rectangular, uses\nDialogue: 0,0:23:09.60,0:23:11.13,EN,,0,0,0,,George's imaginary-part procedure.\nDialogue: 0,0:23:11.13,0:23:12.83,EN,,0,0,0,,If it's polar, uses Martha's.\nDialogue: 0,0:23:13.38,0:23:17.40,EN,,0,0,0,,And then there's a magnitude and an angle.\nDialogue: 0,0:23:19.71,0:23:21.02,EN,,0,0,0,,So there's a system.\nDialogue: 0,0:23:23.00,0:23:24.26,EN,,0,0,0,,Has three parts.\nDialogue: 0,0:23:24.26,0:23:26.59,EN,,0,0,0,,There's sort of George, and Martha, and the manager.\nDialogue: 0,0:23:26.76,0:23:28.97,EN,,0,0,0,,And that's how you get generic operators implemented.\nDialogue: 0,0:23:28.97,0:23:32.92,EN,,0,0,0,,Let's look at just a simple example, just to pin it down.\nDialogue: 0,0:23:33.50,0:23:35.12,EN,,0,0,0,,But exactly how this is going to work,\nDialogue: 0,0:23:36.54,0:23:43.98,EN,,0,0,0,,suppose you're going to be looking at the complex number who's real-part is one,\nDialogue: 0,0:23:44.52,0:23:46.09,EN,,0,0,0,,and who's imaginary-part is two.\nDialogue: 0,0:23:46.09,0:23:48.44,EN,,0,0,0,,So that would be one plus 2i.\nDialogue: 0,0:23:50.31,0:23:52.64,EN,,0,0,0,,What would happen is up here,\nDialogue: 0,0:23:55.28,0:23:57.53,EN,,0,0,0,,up here above where the operations have to happen,\nDialogue: 0,0:23:57.63,0:24:08.27,EN,,0,0,0,,that number would be represented as a pair of 1 and 2 together with type data.\nDialogue: 0,0:24:10.48,0:24:11.39,EN,,0,0,0,,That would be the contents.\nDialogue: 0,0:24:11.87,0:24:17.96,EN,,0,0,0,,And the whole data would be that thing with the symbol rectangular added onto that.\nDialogue: 0,0:24:18.14,0:24:21.53,EN,,0,0,0,,And that's the way that complex number would exist in the system.\nDialogue: 0,0:24:22.33,0:24:24.92,EN,,0,0,0,,When you went to take the real-part,\nDialogue: 0,0:24:25.84,0:24:28.89,EN,,0,0,0,,the manager will look at this and say, oh it's one of George's.\nDialogue: 0,0:24:30.27,0:24:31.53,EN,,0,0,0,,He'll strip off the type\nDialogue: 0,0:24:33.34,0:24:36.91,EN,,0,0,0,,and hand down to George the pair 1, 2.\nDialogue: 0,0:24:38.00,0:24:42.27,EN,,0,0,0,,And that's the kind of data that George developed his system to use.\nDialogue: 0,0:24:44.36,0:24:45.92,EN,,0,0,0,,So it gets stripped down.\nDialogue: 0,0:24:46.52,0:24:49.76,EN,,0,0,0,,Later on, if you ask George to construct a complex number,\nDialogue: 0,0:24:51.24,0:24:54.56,EN,,0,0,0,,George would construct some complex number as a pair,\nDialogue: 0,0:24:55.07,0:24:58.24,EN,,0,0,0,,and before he passes it back up through the manager would\nDialogue: 0,0:24:59.42,0:25:01.13,EN,,0,0,0,,attach the type rectangular.\nDialogue: 0,0:25:03.92,0:25:04.65,EN,,0,0,0,,So you see what happens.\nDialogue: 0,0:25:04.65,0:25:05.85,EN,,0,0,0,,There's no confusion in this system.\nDialogue: 0,0:25:05.85,0:25:10.84,EN,,0,0,0,,It doesn't matter in the least that the pair 1, 2\nDialogue: 0,0:25:13.50,0:25:15.75,EN,,0,0,0,,means something completely different in Martha's world.\nDialogue: 0,0:25:15.75,0:25:18.44,EN,,0,0,0,,In Martha's world this pair means the complex number whose\nDialogue: 0,0:25:18.44,0:25:20.78,EN,,0,0,0,,magnitude is 1 and whose angle is 2.\nDialogue: 0,0:25:21.19,0:25:22.19,EN,,0,0,0,,And there's no confusion,\nDialogue: 0,0:25:22.22,0:25:27.25,EN,,0,0,0,,because by the time any pair like this gets handed back through the manager to the\nDialogue: 0,0:25:27.25,0:25:29.61,EN,,0,0,0,,main system it's going to have the type polar attached.\nDialogue: 0,0:25:31.21,0:25:33.67,EN,,0,0,0,,Whereas this one would have the type rectangular attached.\nDialogue: 0,0:25:36.93,0:25:37.90,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:25:40.77,0:25:55.55,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:25:55.69,0:25:57.77,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:25:57.77,0:25:59.76,EN,,0,0,0,,By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:26:05.21,0:26:11.95,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:26:12.84,0:26:16.75,EN,,0,0,0,,Generic Operators\nDialogue: 0,0:26:20.21,0:26:24.15,EN,,0,0,0,,We just looked at a strategy for implementing generic operators.\nDialogue: 0,0:26:24.15,0:26:31.40,EN,,0,0,0,,That strategy has a name: it's called dispatch on type.\nDialogue: 0,0:26:34.31,0:26:39.36,EN,,0,0,0,,And the idea is that you break your system into a bunch of pieces.\nDialogue: 0,0:26:39.36,0:26:42.67,EN,,0,0,0,,There's George and Martha, who are making representations,\nDialogue: 0,0:26:43.37,0:26:44.38,EN,,0,0,0,,and then there's the manager.\nDialogue: 0,0:26:46.12,0:26:48.06,EN,,0,0,0,,Looks at the types on the data\nDialogue: 0,0:26:48.51,0:26:50.59,EN,,0,0,0,,and then dispatches them to the right person.\nDialogue: 0,0:26:51.99,0:26:56.01,EN,,0,0,0,,Well what criticisms can we make of that as a system organization?\nDialogue: 0,0:26:58.15,0:27:00.40,EN,,0,0,0,,Well first of all there was this little, annoying problem\nDialogue: 0,0:27:00.40,0:27:03.05,EN,,0,0,0,,that George and Martha had to change the names of their procedures\nDialogue: 0,0:27:04.00,0:27:05.95,EN,,0,0,0,,George originally had a real-part procedure,\nDialogue: 0,0:27:05.98,0:27:08.28,EN,,0,0,0,,and he had to go name it real-part rectangular\nDialogue: 0,0:27:08.30,0:27:10.83,EN,,0,0,0,,so it wouldn't interfere with Martha's real-part procedure,\nDialogue: 0,0:27:10.84,0:27:12.76,EN,,0,0,0,,which is now named real-part-polar,\nDialogue: 0,0:27:13.64,0:27:16.68,EN,,0,0,0,,so it wouldn't interfere with the manager's real-part procedure, who's now named real-part.\nDialogue: 0,0:27:17.31,0:27:18.94,EN,,0,0,0,,That's kind of an annoying problem.\nDialogue: 0,0:27:19.46,0:27:21.13,EN,,0,0,0,,But I'm not going to talk about that one now.\nDialogue: 0,0:27:21.27,0:27:22.35,EN,,0,0,0,,We'll see later on\nDialogue: 0,0:27:23.26,0:27:26.12,EN,,0,0,0,,when we think about the structure of Lisp names and environments\nDialogue: 0,0:27:26.12,0:27:30.39,EN,,0,0,0,,that there really are ways to package all those so-called name spaces separately so they\nDialogue: 0,0:27:30.39,0:27:31.56,EN,,0,0,0,,don't interfere with each other.\nDialogue: 0,0:27:32.50,0:27:34.01,EN,,0,0,0,,Not going to think about that problem now.\nDialogue: 0,0:27:35.72,0:27:38.19,EN,,0,0,0,,The problem that I actually want to focus on is\nDialogue: 0,0:27:38.36,0:27:43.24,EN,,0,0,0,,what happens when you bring somebody new into the system.\nDialogue: 0,0:27:44.51,0:27:45.32,EN,,0,0,0,,What has to happen?\nDialogue: 0,0:27:45.32,0:27:46.81,EN,,0,0,0,,Well George and Martha don't care.\nDialogue: 0,0:27:47.42,0:27:50.73,EN,,0,0,0,,George is sitting there in his rectangular world,\nDialogue: 0,0:27:52.20,0:27:53.84,EN,,0,0,0,,has his procedures and his types.\nDialogue: 0,0:27:54.09,0:27:55.74,EN,,0,0,0,,Martha sits in her polar world.\nDialogue: 0,0:27:55.93,0:27:57.02,EN,,0,0,0,,She doesn't care.\nDialogue: 0,0:27:59.38,0:28:00.54,EN,,0,0,0,,But let's look at the manager.\nDialogue: 0,0:28:00.62,0:28:02.84,EN,,0,0,0,,What's the manager have to do?\nDialogue: 0,0:28:03.18,0:28:06.20,EN,,0,0,0,,The manager comes through and had these operations.\nDialogue: 0,0:28:07.36,0:28:09.04,EN,,0,0,0,,There was a test for rectangular\nDialogue: 0,0:28:09.04,0:28:10.14,EN,,0,0,0,,and a test for polar.\nDialogue: 0,0:28:10.14,0:28:14.91,EN,,0,0,0,,If Harry comes in with some new kind of complex number,\nDialogue: 0,0:28:17.21,0:28:19.96,EN,,0,0,0,,and Harry has a new type, Harry type complex number, the\nDialogue: 0,0:28:20.27,0:28:23.28,EN,,0,0,0,,manager has to go in and change all those procedures.\nDialogue: 0,0:28:25.24,0:28:26.94,EN,,0,0,0,,So the inflexibility in the system,\nDialogue: 0,0:28:26.96,0:28:32.41,EN,,0,0,0,,the place where work has to happen to accommodate change, is in the manager.\nDialogue: 0,0:28:34.89,0:28:35.99,EN,,0,0,0,,That's pretty annoying.\nDialogue: 0,0:28:35.99,0:28:37.21,EN,,0,0,0,,It's even more annoying\nDialogue: 0,0:28:39.05,0:28:41.21,EN,,0,0,0,,It's even more annoying when you realize the manager's not doing anything\nDialogue: 0,0:28:42.59,0:28:44.67,EN,,0,0,0,,The manager is just being a paper pusher.\nDialogue: 0,0:28:45.84,0:28:51.13,EN,,0,0,0,,Let's look again at these programs. What are they doing?\nDialogue: 0,0:28:51.76,0:28:52.72,EN,,0,0,0,,What does real-part do?\nDialogue: 0,0:28:52.88,0:28:56.17,EN,,0,0,0,,Real-part says, oh, is it the kind of complex number that\nDialogue: 0,0:28:56.17,0:28:57.00,EN,,0,0,0,,George can handle?\nDialogue: 0,0:28:57.00,0:28:58.27,EN,,0,0,0,,If so, send it off to George.\nDialogue: 0,0:28:59.41,0:29:01.76,EN,,0,0,0,,Is it the kind of complex number that Martha can handle?\nDialogue: 0,0:29:01.82,0:29:04.06,EN,,0,0,0,,If so, send it off to Martha.\nDialogue: 0,0:29:05.04,0:29:08.72,EN,,0,0,0,,So it's really annoying that the bottleneck in this system,\nDialogue: 0,0:29:08.72,0:29:11.66,EN,,0,0,0,,the thing that's preventing flexibility and change,\nDialogue: 0,0:29:12.09,0:29:14.36,EN,,0,0,0,,is completely in the bureaucracy.\nDialogue: 0,0:29:15.00,0:29:17.02,EN,,0,0,0,,It's not in anybody who's doing any of the work.\nDialogue: 0,0:29:19.70,0:29:21.80,EN,,0,0,0,,Not an uncommon situation, unfortunately.\nDialogue: 0,0:29:23.18,0:29:24.41,EN,,0,0,0,,See, what's really going on--\nDialogue: 0,0:29:24.48,0:29:26.97,EN,,0,0,0,,abstractly in the system, there's a table.\nDialogue: 0,0:29:28.10,0:29:30.08,EN,,0,0,0,,So what's really happening is somewhere there's a table.\nDialogue: 0,0:29:30.84,0:29:33.64,EN,,0,0,0,,There're types.\nDialogue: 0,0:29:34.40,0:29:38.96,EN,,0,0,0,,There's polar and rectangular.\nDialogue: 0,0:29:41.55,0:29:43.02,EN,,0,0,0,,And Harry's may be over here.\nDialogue: 0,0:29:44.38,0:29:46.56,EN,,0,0,0,,And there are operators.\nDialogue: 0,0:29:48.05,0:29:58.24,EN,,0,0,0,,There's an operator like real-part. Or imaginary-part.\nDialogue: 0,0:30:00.01,0:30:04.22,EN,,0,0,0,,Or a magnitude and angle.\nDialogue: 0,0:30:05.83,0:30:18.97,EN,,0,0,0,,And sitting in this table are the right procedures.\nDialogue: 0,0:30:19.28,0:30:21.99,EN,,0,0,0,,So sitting here for the type polar and real-part is\nDialogue: 0,0:30:21.99,0:30:27.56,EN,,0,0,0,,Martha's procedure real-part-polar.\nDialogue: 0,0:30:30.57,0:30:36.62,EN,,0,0,0,,And over here in the table is George's procedure real-part-rectangular.\nDialogue: 0,0:30:37.74,0:30:43.07,EN,,0,0,0,,And over here would be, say, Martha's procedure magnitude-polar,\nDialogue: 0,0:30:44.46,0:30:49.76,EN,,0,0,0,,and George's procedure magnitude-rectangular, right, and so on.\nDialogue: 0,0:30:49.76,0:30:51.24,EN,,0,0,0,,The rest of this table's filled in.\nDialogue: 0,0:30:52.39,0:30:54.26,EN,,0,0,0,,And that's really what's going on.\nDialogue: 0,0:30:57.63,0:31:01.74,EN,,0,0,0,,So in some sense, all the manager is doing\nDialogue: 0,0:31:02.11,0:31:04.11,EN,,0,0,0,,is acting as this table.\nDialogue: 0,0:31:06.86,0:31:08.70,EN,,0,0,0,,Well how do we fix our system?\nDialogue: 0,0:31:11.74,0:31:13.77,EN,,0,0,0,,Well, how do you fix bureaucracies a lot of the time?\nDialogue: 0,0:31:13.77,0:31:15.44,EN,,0,0,0,,What you do is you get rid of the manager.\nDialogue: 0,0:31:16.01,0:31:19.55,EN,,0,0,0,,We just take the manager and replace him by a computer.\nDialogue: 0,0:31:20.17,0:31:21.76,EN,,0,0,0,,We're going to automate him out of existence.\nDialogue: 0,0:31:23.32,0:31:26.57,EN,,0,0,0,,Namely, instead of having the manager who basically consults this table,\nDialogue: 0,0:31:27.45,0:31:29.32,EN,,0,0,0,,we'll have our system use the table directly.\nDialogue: 0,0:31:31.02,0:31:32.11,EN,,0,0,0,,What do I mean by that?\nDialogue: 0,0:31:32.11,0:31:36.19,EN,,0,0,0,,Let's assume, again using data abstraction,\nDialogue: 0,0:31:37.71,0:31:40.40,EN,,0,0,0,,that we have some kind of data structure that's a table.\nDialogue: 0,0:31:40.88,0:31:43.61,EN,,0,0,0,,And we have ways of sticking things in and ways of getting things out.\nDialogue: 0,0:31:44.35,0:31:49.04,EN,,0,0,0,,And to be explicit, let me assume that there's an operation called \"put.\"\nDialogue: 0,0:31:50.30,0:31:58.32,EN,,0,0,0,,And put is going to take, case two things I'll call \"keys.\" key1 and key2.\nDialogue: 0,0:32:00.13,0:32:00.99,EN,,0,0,0,,And a value.\nDialogue: 0,0:32:06.20,0:32:11.12,EN,,0,0,0,,And that stores the value in the table under key1 and key2.\nDialogue: 0,0:32:11.49,0:32:13.16,EN,,0,0,0,,And then we'll assume there's a thing called \"get,\"\nDialogue: 0,0:32:15.23,0:32:18.72,EN,,0,0,0,,such that if later on I say, get me what's in the table\nDialogue: 0,0:32:19.40,0:32:22.76,EN,,0,0,0,,stored under key1 and key2,\nDialogue: 0,0:32:23.40,0:32:25.39,EN,,0,0,0,,it'll retrieve whatever value was stored there.\nDialogue: 0,0:32:26.73,0:32:29.44,EN,,0,0,0,,And let's not worry about how tables are implemented.\nDialogue: 0,0:32:30.00,0:32:32.52,EN,,0,0,0,,That's yet another data abstraction, George's problem.\nDialogue: 0,0:32:33.06,0:32:34.36,EN,,0,0,0,,And maybe we'll see later--\nDialogue: 0,0:32:34.70,0:32:36.97,EN,,0,0,0,,talk about how you might actually build tables in Lisp.\nDialogue: 0,0:32:40.71,0:32:45.50,EN,,0,0,0,,Well given this organization,what did George and Martha have to do?\nDialogue: 0,0:32:47.38,0:32:49.07,EN,,0,0,0,,Well when they build their system,\nDialogue: 0,0:32:49.13,0:32:51.08,EN,,0,0,0,,they each have the responsibility\nDialogue: 0,0:32:51.44,0:32:53.82,EN,,0,0,0,,to set up their appropriate column in the table.\nDialogue: 0,0:32:55.21,0:32:57.47,EN,,0,0,0,,So what George does, for example,\nDialogue: 0,0:32:59.79,0:33:02.06,EN,,0,0,0,,when he defines his procedures all he has to do\nDialogue: 0,0:33:02.27,0:33:07.99,EN,,0,0,0,,is go off and put into the table under the type-rectangular.\nDialogue: 0,0:33:09.82,0:33:12.12,EN,,0,0,0,,And the name of the operation is real-part,\nDialogue: 0,0:33:13.31,0:33:15.26,EN,,0,0,0,,his procedure real-part-rectangular.\nDialogue: 0,0:33:16.25,0:33:17.78,EN,,0,0,0,,So notice what's going into this table.\nDialogue: 0,0:33:17.78,0:33:22.10,EN,,0,0,0,,The two keys here are symbols, rectangular and real-part.\nDialogue: 0,0:33:22.10,0:33:22.75,EN,,0,0,0,,That's the quote.\nDialogue: 0,0:33:24.40,0:33:26.75,EN,,0,0,0,,And what's going into the table is the actual\nDialogue: 0,0:33:26.84,0:33:29.21,EN,,0,0,0,,procedure that he wrote, real-part rectangular.\nDialogue: 0,0:33:31.85,0:33:34.30,EN,,0,0,0,,And then puts an imaginary part into the table,\nDialogue: 0,0:33:34.59,0:33:37.80,EN,,0,0,0,,filed under the keys rectangular and imaginary-part,\nDialogue: 0,0:33:38.62,0:33:42.88,EN,,0,0,0,,and magnitude under the keys rectangular magnitude,\nDialogue: 0,0:33:43.61,0:33:45.20,EN,,0,0,0,,angle under rectangular-angle.\nDialogue: 0,0:33:47.04,0:33:50.84,EN,,0,0,0,,Okay? So that's what George has to do to be part of this system.\nDialogue: 0,0:33:54.42,0:33:58.86,EN,,0,0,0,,Martha similarly sets up the column and the table under polar.\nDialogue: 0,0:33:59.43,0:34:00.65,EN,,0,0,0,,Polar and real-part.\nDialogue: 0,0:34:01.69,0:34:03.58,EN,,0,0,0,,Right? Is the procedure real-part-polar?\nDialogue: 0,0:34:04.34,0:34:07.29,EN,,0,0,0,,And imaginary-part, and magnitude, and angle.\nDialogue: 0,0:34:08.91,0:34:11.40,EN,,0,0,0,,So this is what Martha has to do to be part of the system.\nDialogue: 0,0:34:11.40,0:34:13.55,EN,,0,0,0,,Everyone who makes a representation has the\nDialogue: 0,0:34:13.55,0:34:17.63,EN,,0,0,0,,responsibility for setting up a column in the table.\nDialogue: 0,0:34:17.76,0:34:19.90,EN,,0,0,0,,And what does Harry do when Harry comes in with his\nDialogue: 0,0:34:19.90,0:34:21.80,EN,,0,0,0,,brilliant idea for implementing complex numbers?\nDialogue: 0,0:34:21.80,0:34:23.96,EN,,0,0,0,,Well he makes whatever procedure he wants and\nDialogue: 0,0:34:24.04,0:34:26.52,EN,,0,0,0,,builds a new column in this table.\nDialogue: 0,0:34:28.55,0:34:30.04,EN,,0,0,0,,OK, well what happened to the manager?\nDialogue: 0,0:34:31.33,0:34:34.61,EN,,0,0,0,,The manager has been automated out of existence and is\nDialogue: 0,0:34:34.61,0:34:37.11,EN,,0,0,0,,replaced by a procedure called operate.\nDialogue: 0,0:34:37.11,0:34:39.55,EN,,0,0,0,,And this is the key procedure in the whole system.\nDialogue: 0,0:34:40.38,0:34:45.92,EN,,0,0,0,,Let's say define operate.\nDialogue: 0,0:34:51.06,0:34:56.09,EN,,0,0,0,,Operate is going to take an operation that you want to do,\nDialogue: 0,0:34:57.75,0:34:58.88,EN,,0,0,0,,the name of an operation,\nDialogue: 0,0:34:59.20,0:35:03.28,EN,,0,0,0,,and an object that you would like to apply that operation to.\nDialogue: 0,0:35:04.21,0:35:09.76,EN,,0,0,0,,So for example, the real-part of some particular complex number, what does it do?\nDialogue: 0,0:35:09.95,0:35:11.90,EN,,0,0,0,,Well the first thing it does, it looks in the table.\nDialogue: 0,0:35:12.64,0:35:13.87,EN,,0,0,0,,Goes into the table\nDialogue: 0,0:35:14.80,0:35:22.56,EN,,0,0,0,,and tries to find a procedure that's stored in the table.\nDialogue: 0,0:35:23.15,0:35:24.80,EN,,0,0,0,,So it gets from the table,\nDialogue: 0,0:35:25.50,0:35:33.92,EN,,0,0,0,,using as keys the type of the object and the operator,\nDialogue: 0,0:35:38.92,0:35:40.14,EN,,0,0,0,,but looks on the table and sees\nDialogue: 0,0:35:40.38,0:35:42.72,EN,,0,0,0,,what's stored under the type of the object and the operator\nDialogue: 0,0:35:42.89,0:35:44.35,EN,,0,0,0,,sees if anything's stored.\nDialogue: 0,0:35:44.44,0:35:45.93,EN,,0,0,0,,Let's assume that get is implemented.\nDialogue: 0,0:35:45.93,0:35:47.72,EN,,0,0,0,,So if nothing is stored there,\nDialogue: 0,0:35:48.11,0:35:51.79,EN,,0,0,0,,it'll return a nil, return the empty list.\nDialogue: 0,0:35:52.67,0:35:55.39,EN,,0,0,0,,So it says, if there's actually something stored there,\nDialogue: 0,0:35:56.62,0:36:00.43,EN,,0,0,0,,if the procedure here is not no,\nDialogue: 0,0:36:03.15,0:36:07.12,EN,,0,0,0,,then it'll take the procedure that it found in the table\nDialogue: 0,0:36:09.79,0:36:15.00,EN,,0,0,0,,procedure that it found in the table and apply it to the contents of the object.\nDialogue: 0,0:36:18.25,0:36:20.40,EN,,0,0,0,,And otherwise if there was nothing stored there,\nDialogue: 0,0:36:20.67,0:36:22.51,EN,,0,0,0,,it'll-- well we can decide.\nDialogue: 0,0:36:22.81,0:36:27.12,EN,,0,0,0,,In this case let's have it put out an error message saying, undefined operator.\nDialogue: 0,0:36:28.48,0:36:30.24,EN,,0,0,0,,No operator for this type.\nDialogue: 0,0:36:33.07,0:36:34.72,EN,,0,0,0,,Or some appropriate error message.\nDialogue: 0,0:36:39.07,0:36:39.48,EN,,0,0,0,,OK?\nDialogue: 0,0:36:39.72,0:36:41.04,EN,,0,0,0,,And that replaces the manager.\nDialogue: 0,0:36:41.89,0:36:42.91,EN,,0,0,0,,How do we really use it?\nDialogue: 0,0:36:43.96,0:36:49.80,EN,,0,0,0,,Well what we say is we'll go off and define our generic selectors using operate.\nDialogue: 0,0:36:50.04,0:36:56.75,EN,,0,0,0,,We'll say that the real-part of an object is found by\nDialogue: 0,0:36:57.14,0:37:05.66,EN,,0,0,0,,operating on the object with the name of the operation being real-part.\nDialogue: 0,0:37:08.07,0:37:12.22,EN,,0,0,0,,And then similarly, imaginary-part is operate using the name imaginary-part\nDialogue: 0,0:37:12.22,0:37:13.98,EN,,0,0,0,,and magnitude and angle.\nDialogue: 0,0:37:15.36,0:37:17.43,EN,,0,0,0,,That's our implementation.\nDialogue: 0,0:37:17.43,0:37:20.48,EN,,0,0,0,,That plus the type plus the operate procedure.\nDialogue: 0,0:37:21.33,0:37:24.00,EN,,0,0,0,,And the table effectively replaces what the  manager used to do.\nDialogue: 0,0:37:24.06,0:37:27.69,EN,,0,0,0,,Let's just go through that slowly to show you what's going on.\nDialogue: 0,0:37:27.90,0:37:33.00,EN,,0,0,0,,Suppose I have one of Martha's complex numbers.\nDialogue: 0,0:37:33.53,0:37:38.80,EN,,0,0,0,,It's got magnitude 1 and angle 2.\nDialogue: 0,0:37:39.10,0:37:40.22,EN,,0,0,0,,And it's one of Martha's.\nDialogue: 0,0:37:40.22,0:37:45.45,EN,,0,0,0,,So it's labeled here, polar.\nDialogue: 0,0:37:47.24,0:37:48.00,EN,,0,0,0,,Let's call that z.\nDialogue: 0,0:37:48.00,0:37:48.91,EN,,0,0,0,,Suppose that's z.\nDialogue: 0,0:37:51.77,0:37:54.46,EN,,0,0,0,,And suppose with this implementation someone comes up\nDialogue: 0,0:37:54.80,0:37:57.92,EN,,0,0,0,,asks for the real-part of z.\nDialogue: 0,0:38:04.87,0:38:07.96,EN,,0,0,0,,Well real-part now is defined in terms of operate.\nDialogue: 0,0:38:09.16,0:38:10.57,EN,,0,0,0,,So that's equivalent to saying\nDialogue: 0,0:38:12.09,0:38:24.81,EN,,0,0,0,,operate with the name of the operator being real-part, the symbol real-part on z.\nDialogue: 0,0:38:27.06,0:38:28.09,EN,,0,0,0,,And now operate comes.\nDialogue: 0,0:38:28.09,0:38:29.24,EN,,0,0,0,,It's going to look in the table,\nDialogue: 0,0:38:31.04,0:38:34.36,EN,,0,0,0,,and it's going to try and find something stored under--\nDialogue: 0,0:38:39.00,0:38:46.22,EN,,0,0,0,,the operation is going to apply by looking in the table under the type of the object.\nDialogue: 0,0:38:46.72,0:38:48.22,EN,,0,0,0,,And the type of z is polar.\nDialogue: 0,0:38:48.79,0:38:51.37,EN,,0,0,0,,So it's going to look and say, can I get using polar?\nDialogue: 0,0:38:52.99,0:38:58.57,EN,,0,0,0,,And the operation name, which was real-part.\nDialogue: 0,0:39:05.96,0:39:13.63,EN,,0,0,0,,It's going to look in there and apply that to the contents of z.\nDialogue: 0,0:39:14.83,0:39:17.13,EN,,0,0,0,,What's that is if everything was set up correctly,\nDialogue: 0,0:39:17.74,0:39:21.70,EN,,0,0,0,,this thing is the procedure that Martha put there.\nDialogue: 0,0:39:21.70,0:39:22.95,EN,,0,0,0,,This is real-part-polar.\nDialogue: 0,0:39:31.05,0:39:35.13,EN,,0,0,0,,And this is z without its type.\nDialogue: 0,0:39:35.44,0:39:38.94,EN,,0,0,0,,The thing that Martha originally designed those procedures to work on,\nDialogue: 0,0:39:39.40,0:39:40.43,EN,,0,0,0,,which is 1, 2.\nDialogue: 0,0:39:43.71,0:39:45.87,EN,,0,0,0,,And so operate sort of does uniformly\nDialogue: 0,0:39:46.46,0:39:48.89,EN,,0,0,0,,what the manager used to do sort of all over the system.\nDialogue: 0,0:39:49.45,0:39:52.59,EN,,0,0,0,,It finds the right thing, looks in the table, strips off the type,\nDialogue: 0,0:39:53.58,0:39:57.52,EN,,0,0,0,,and passes it down into the person who handles it.\nDialogue: 0,0:39:58.88,0:40:05.48,EN,,0,0,0,,This is another, and, you can see, more flexible for most purposes,\nDialogue: 0,0:40:06.22,0:40:08.04,EN,,0,0,0,,way of implementing generic operators.\nDialogue: 0,0:40:08.08,0:40:15.69,EN,,0,0,0,,And it's called data-directed programming.\nDialogue: 0,0:40:20.35,0:40:21.96,EN,,0,0,0,,And the idea of that is\nDialogue: 0,0:40:23.42,0:40:25.55,EN,,0,0,0,,And the idea of that is in some sense the data objects themselves,\nDialogue: 0,0:40:26.04,0:40:28.35,EN,,0,0,0,,those little complex numbers that are floating around the system,\nDialogue: 0,0:40:28.73,0:40:33.16,EN,,0,0,0,,are carrying with them the information about how you should operate on them.\nDialogue: 0,0:40:35.74,0:40:36.78,EN,,0,0,0,,Let's break for questions.\nDialogue: 0,0:40:41.00,0:40:41.24,EN,,0,0,0,,Yes.\nDialogue: 0,0:40:41.24,0:40:43.39,EN,,0,0,0,,AUDIENCE: What do you have stored in that data object?\nDialogue: 0,0:40:43.39,0:40:47.10,EN,,0,0,0,,You have the data itself, you have its type,\nDialogue: 0,0:40:47.10,0:40:49.60,EN,,0,0,0,,the operations for that type?\nDialogue: 0,0:40:49.69,0:40:53.08,EN,,0,0,0,,Or where are the operations that you found?\nDialogue: 0,0:40:53.60,0:40:54.17,EN,,0,0,0,,PROFESSOR: OK, let me--\nDialogue: 0,0:40:54.98,0:40:56.50,EN,,0,0,0,,yeah, that's a good question.\nDialogue: 0,0:40:56.50,0:41:00.46,EN,,0,0,0,,Because it raises other possibilities of how you might do it.\nDialogue: 0,0:41:00.75,0:41:02.48,EN,,0,0,0,,And of course there are a lot of possibilities.\nDialogue: 0,0:41:04.20,0:41:06.14,EN,,0,0,0,,In this particular implementation,\nDialogue: 0,0:41:06.24,0:41:09.72,EN,,0,0,0,,what's sitting in this data object, for example,\nDialogue: 0,0:41:10.44,0:41:13.45,EN,,0,0,0,,is the data itself-- which in this case is a pair of 1 and 2--\nDialogue: 0,0:41:14.98,0:41:16.55,EN,,0,0,0,,and also a symbol.\nDialogue: 0,0:41:16.55,0:41:19.07,EN,,0,0,0,,This is the symbol, the word P-O-L-A-R,\nDialogue: 0,0:41:20.60,0:41:22.33,EN,,0,0,0,,And that what's sitting in this data object.\nDialogue: 0,0:41:24.24,0:41:26.69,EN,,0,0,0,,OK, where are the operations themselves?\nDialogue: 0,0:41:26.69,0:41:29.00,EN,,0,0,0,,The operations are sitting in the table.\nDialogue: 0,0:41:29.85,0:41:31.07,EN,,0,0,0,,So in this table,\nDialogue: 0,0:41:32.30,0:41:36.46,EN,,0,0,0,,the rows and columns of the table are labeled by symbols.\nDialogue: 0,0:41:38.23,0:41:40.08,EN,,0,0,0,,So when I store something in this table,\nDialogue: 0,0:41:40.09,0:41:47.02,EN,,0,0,0,,the key might be the symbol polar and the symbol magnitude.\nDialogue: 0,0:41:48.24,0:41:51.31,EN,,0,0,0,,And I think by writing it this way I've been very confusing.\nDialogue: 0,0:41:51.31,0:41:52.70,EN,,0,0,0,,Because what's really sitting here isn't--\nDialogue: 0,0:41:53.16,0:41:54.57,EN,,0,0,0,,when I wrote magnitude polar,\nDialogue: 0,0:41:57.04,0:41:59.23,EN,,0,0,0,,what I mean is the procedure magnitude polar.\nDialogue: 0,0:41:59.85,0:42:01.85,EN,,0,0,0,,And probably what I really should have written--\nDialogue: 0,0:42:02.58,0:42:04.20,EN,,0,0,0,,except it's too small for me to write\nDialogue: 0,0:42:04.20,0:42:05.07,EN,,0,0,0,,in this little space--\nDialogue: 0,0:42:05.58,0:42:08.92,EN,,0,0,0,,is something like lambda of z,\nDialogue: 0,0:42:10.60,0:42:12.75,EN,,0,0,0,,the thing that Martha wrote to implement.\nDialogue: 0,0:42:14.71,0:42:15.72,EN,,0,0,0,,And then you can see from that,\nDialogue: 0,0:42:15.74,0:42:17.44,EN,,0,0,0,,there's another way that I alluded to\nDialogue: 0,0:42:17.71,0:42:19.82,EN,,0,0,0,,of solving this name conflict problem\nDialogue: 0,0:42:20.04,0:42:23.15,EN,,0,0,0,,which is that George and Martha never have to name their procedures at all.\nDialogue: 0,0:42:23.15,0:42:25.37,EN,,0,0,0,,They can just stick the lambda, the lambda...\nDialogue: 0,0:42:25.39,0:42:28.12,EN,,0,0,0,,the anonymous things generated by lambda directly into the table.\nDialogue: 0,0:42:28.66,0:42:31.76,EN,,0,0,0,,There's also another thing that your question raises,\nDialogue: 0,0:42:32.35,0:42:34.06,EN,,0,0,0,,is the possibility that maybe\nDialogue: 0,0:42:34.83,0:42:37.92,EN,,0,0,0,,what I would like somehow is to store in this data object\nDialogue: 0,0:42:37.95,0:42:39.48,EN,,0,0,0,,not the symbol P-O-L-A-R but\nDialogue: 0,0:42:39.93,0:42:42.35,EN,,0,0,0,,maybe actually all the operations themselves.\nDialogue: 0,0:42:43.90,0:42:45.63,EN,,0,0,0,,And that's another way to organize the system,\nDialogue: 0,0:42:45.66,0:42:46.60,EN,,0,0,0,,called message passing.\nDialogue: 0,0:42:48.65,0:42:49.92,EN,,0,0,0,,So there are a lot of ways you can do it.\nDialogue: 0,0:42:54.64,0:42:58.04,EN,,0,0,0,,AUDIENCE: Therefore if Martha and George had used the same\nDialogue: 0,0:42:58.04,0:43:01.23,EN,,0,0,0,,procedure names, it would be OK because it wouldn't look\nDialogue: 0,0:43:01.23,0:43:02.56,EN,,0,0,0,,it wouldn't look into it\nDialogue: 0,0:43:02.56,0:43:04.68,EN,,0,0,0,,PROFESSOR: That's right.That's right.\nDialogue: 0,0:43:04.80,0:43:07.85,EN,,0,0,0,,See, they wouldn't even have to name their procedures at all.\nDialogue: 0,0:43:08.04,0:43:09.36,EN,,0,0,0,,What George and Martha could writ --,\nDialogue: 0,0:43:09.50,0:43:10.62,EN,,0,0,0,,what George could have written\nDialogue: 0,0:43:10.83,0:43:15.28,EN,,0,0,0,,instead of saying put in the table under rectangular- and real-part,\nDialogue: 0,0:43:16.22,0:43:17.98,EN,,0,0,0,,the procedure real-part rectangular,\nDialogue: 0,0:43:18.03,0:43:21.15,EN,,0,0,0,,George could have written put under rectangular real-part,\nDialogue: 0,0:43:21.24,0:43:23.69,EN,,0,0,0,,lambda of z, such and such, such and such,\nDialogue: 0,0:43:24.54,0:43:26.84,EN,,0,0,0,,And the system would work completely the same.\nDialogue: 0,0:43:27.33,0:43:29.24,EN,,0,0,0,,AUDIENCE: My question is, Martha could put\nDialogue: 0,0:43:29.84,0:43:33.60,EN,,0,0,0,,could have put key1 key2 real-part,\nDialogue: 0,0:43:33.95,0:43:37.64,EN,,0,0,0,,and George could have put key1 key2 real-part,\nDialogue: 0,0:43:37.96,0:43:39.60,EN,,0,0,0,,and as long as they defined them differently\nDialogue: 0,0:43:39.80,0:43:41.26,EN,,0,0,0,,they wouldn't have had any conflicts, right?\nDialogue: 0,0:43:41.29,0:43:43.80,EN,,0,0,0,,PROFESSOR: Yes, that would all be OK except for the fact\nDialogue: 0,0:43:44.97,0:43:47.13,EN,,0,0,0,,that if you imagine George and Martha typing at the same\nDialogue: 0,0:43:47.13,0:43:49.20,EN,,0,0,0,,console with the same meanings for all their names,\nDialogue: 0,0:43:49.82,0:43:51.23,EN,,0,0,0,,and it would get confused by real-part,\nDialogue: 0,0:43:51.24,0:43:52.80,EN,,0,0,0,,but there are ways to arrange that, too.\nDialogue: 0,0:43:52.80,0:43:54.80,EN,,0,0,0,,And in principle you're absolutely right.\nDialogue: 0,0:43:54.98,0:43:56.29,EN,,0,0,0,,If their names didn't conflict--\nDialogue: 0,0:43:56.29,0:43:58.19,EN,,0,0,0,,it's the objects that go in the table, not the names.\nDialogue: 0,0:44:08.20,0:44:09.05,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:44:12.91,0:44:20.48,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:44:20.96,0:44:23.29,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:44:23.45,0:44:25.29,EN,,0,0,0,,By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:44:57.42,0:45:05.07,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:45:05.47,0:45:09.24,EN,,0,0,0,,Generic Operators\nDialogue: 0,0:45:12.88,0:45:16.88,EN,,0,0,0,,RPOFESSOR: All right, well we just looked at data-directed programming\nDialogue: 0,0:45:17.68,0:45:22.84,EN,,0,0,0,,as a way of implementing a system that does arithmetic on complex numbers.\nDialogue: 0,0:45:27.60,0:45:32.48,EN,,0,0,0,,So I had these operations in it called plus C and minus C,\nDialogue: 0,0:45:32.88,0:45:37.24,EN,,0,0,0,,and multiply, and divide,and maybe some others.\nDialogue: 0,0:45:38.23,0:45:45.72,EN,,0,0,0,,And that sat on top of-- and this is the key point--\nDialogue: 0,0:45:45.74,0:45:49.60,EN,,0,0,0,,sat on top of two different representations.\nDialogue: 0,0:45:50.34,0:45:55.44,EN,,0,0,0,,A rectangular package here, and a polar package.\nDialogue: 0,0:45:58.14,0:45:59.15,EN,,0,0,0,,And maybe some more.\nDialogue: 0,0:45:59.15,0:46:02.80,EN,,0,0,0,,And we saw that the whole idea is that maybe some more are now very easy to add.\nDialogue: 0,0:46:04.67,0:46:08.35,EN,,0,0,0,,But that doesn't really show the power of this methodology.\nDialogue: 0,0:46:08.90,0:46:10.15,EN,,0,0,0,,Shows you what's going on.\nDialogue: 0,0:46:10.15,0:46:12.33,EN,,0,0,0,,The power of the methodology only becomes apparent\nDialogue: 0,0:46:12.94,0:46:15.79,EN,,0,0,0,,when you start embedding this in some more complex system.\nDialogue: 0,0:46:16.17,0:46:17.74,EN,,0,0,0,,So let... What I'm going to do now\nDialogue: 0,0:46:17.87,0:46:20.01,EN,,0,0,0,,is embed this in some more complex system.\nDialogue: 0,0:46:20.25,0:46:25.28,EN,,0,0,0,,Let's assume that what we really have is a general kind of arithmetic system.\nDialogue: 0,0:46:25.28,0:46:27.24,EN,,0,0,0,,So called generic arithmetic system.\nDialogue: 0,0:46:27.24,0:46:28.54,EN,,0,0,0,,And at the top level here,\nDialogue: 0,0:46:30.76,0:46:35.92,EN,,0,0,0,,somebody can say add twothings, or subtract two things,\nDialogue: 0,0:46:37.45,0:46:41.05,EN,,0,0,0,,or multiply two  things, or divide two things.\nDialogue: 0,0:46:44.14,0:46:46.52,EN,,0,0,0,,And underneath that there's an abstraction barrier.\nDialogue: 0,0:46:47.93,0:46:49.15,EN,,0,0,0,,And underneath this barrier,\nDialogue: 0,0:46:49.50,0:46:52.48,EN,,0,0,0,,is, say, a complex arithmetic package.\nDialogue: 0,0:46:53.02,0:46:54.96,EN,,0,0,0,,And you can say, add two complex numbers.\nDialogue: 0,0:46:55.04,0:46:58.83,EN,,0,0,0,,Or you might also have--remember we did a rational number package\nDialogue: 0,0:46:58.88,0:46:59.93,EN,,0,0,0,,you might have that sitting there.\nDialogue: 0,0:47:00.19,0:47:01.72,EN,,0,0,0,,And there might be a rational thing.\nDialogue: 0,0:47:04.76,0:47:06.22,EN,,0,0,0,,And the rational number package,\nDialogue: 0,0:47:07.16,0:47:14.75,EN,,0,0,0,,well, has the things we implemented. Plus rat, and times rat, and so on.\nDialogue: 0,0:47:15.39,0:47:17.01,EN,,0,0,0,,Or you might have ordinary Lisp numbers.\nDialogue: 0,0:47:17.01,0:47:18.99,EN,,0,0,0,,You might say add three and four.\nDialogue: 0,0:47:19.42,0:47:20.94,EN,,0,0,0,,So we might have ordinary numbers,\nDialogue: 0,0:47:28.28,0:47:34.67,EN,,0,0,0,,in which case we have the Lisp supplied plus, and minus, and times, and slash.\nDialogue: 0,0:47:36.67,0:47:39.12,EN,,0,0,0,,OK, so we might imagine this complex number system\nDialogue: 0,0:47:39.44,0:47:44.44,EN,,0,0,0,,sitting in a more complicated generic operator structure at the next level up.\nDialogue: 0,0:47:47.73,0:47:48.73,EN,,0,0,0,,Well how can we make that?\nDialogue: 0,0:47:49.05,0:47:52.32,EN,,0,0,0,,We already have the idea, we're just going to do it again.\nDialogue: 0,0:47:52.78,0:47:54.72,EN,,0,0,0,,We've implemented a rational number package.\nDialogue: 0,0:47:54.72,0:47:56.89,EN,,0,0,0,,Let's look at how it has to be changed.\nDialogue: 0,0:48:01.48,0:48:03.40,EN,,0,0,0,,In fact, at this level it doesn't have to be changed at all.\nDialogue: 0,0:48:03.73,0:48:05.88,EN,,0,0,0,,This is exactly the code that we wrote last time.\nDialogue: 0,0:48:07.18,0:48:08.97,EN,,0,0,0,,To add two rational numbers,\nDialogue: 0,0:48:09.85,0:48:10.91,EN,,0,0,0,,remember there was this formula.\nDialogue: 0,0:48:11.14,0:48:13.37,EN,,0,0,0,,You make a rational number whose numerator--\nDialogue: 0,0:48:13.98,0:48:17.56,EN,,0,0,0,,is the numerator of the first times the denominator of the second\nDialogue: 0,0:48:17.93,0:48:21.52,EN,,0,0,0,,plus the denominator of the first times the numerator of the second.\nDialogue: 0,0:48:21.52,0:48:23.79,EN,,0,0,0,,And who's denominator is the product of the denominators.\nDialogue: 0,0:48:25.76,0:48:29.07,EN,,0,0,0,,And minus rat, and star rat, and slash rat.\nDialogue: 0,0:48:30.36,0:48:35.12,EN,,0,0,0,,And this is exactly the rational number package that we made before.\nDialogue: 0,0:48:36.31,0:48:38.89,EN,,0,0,0,,We're ignoring the GCD problem,but let's not worry about that.\nDialogue: 0,0:48:39.08,0:48:42.59,EN,,0,0,0,,How do we install... As implementers of this rational number package,\nDialogue: 0,0:48:42.80,0:48:45.10,EN,,0,0,0,,how do we install it in the generic arithmetic system?\nDialogue: 0,0:48:45.57,0:48:46.22,EN,,0,0,0,,Well that's easy.\nDialogue: 0,0:48:47.29,0:48:51.56,EN,,0,0,0,,Go off... There's only one thing we have to do differently.\nDialogue: 0,0:48:51.84,0:48:55.71,EN,,0,0,0,,Whereas previously we said that to make a rational number\nDialogue: 0,0:48:56.27,0:48:59.98,EN,,0,0,0,,you built a pair of the numerator and denominator,\nDialogue: 0,0:49:00.96,0:49:03.20,EN,,0,0,0,,here we'll not only build the pair, but we'll sign it.\nDialogue: 0,0:49:03.30,0:49:04.56,EN,,0,0,0,,We'll attach the type rational.\nDialogue: 0,0:49:06.36,0:49:08.09,EN,,0,0,0,,That's the only thing we have to do different,\nDialogue: 0,0:49:08.56,0:49:10.09,EN,,0,0,0,,make it a typed data object.\nDialogue: 0,0:49:12.38,0:49:14.08,EN,,0,0,0,,And now we'll stick our operations in the table.\nDialogue: 0,0:49:14.36,0:49:18.20,EN,,0,0,0,,We'll put under the symbol rational and the operation add\nDialogue: 0,0:49:18.92,0:49:20.25,EN,,0,0,0,,our procedure -- +rat.\nDialogue: 0,0:49:21.82,0:49:23.24,EN,,0,0,0,,And, again, note this is a symbol.\nDialogue: 0,0:49:23.74,0:49:23.93,EN,,0,0,0,,Right?\nDialogue: 0,0:49:24.03,0:49:25.29,EN,,0,0,0,,Quote, and quote,\nDialogue: 0,0:49:25.31,0:49:28.01,EN,,0,0,0,,but the actual thing we're putting in the table is the procedure.\nDialogue: 0,0:49:29.82,0:49:31.77,EN,,0,0,0,,And for how to subtract,\nDialogue: 0,0:49:31.79,0:49:36.81,EN,,0,0,0,,well you subtract rationals with minus rat.\nDialogue: 0,0:49:38.27,0:49:40.24,EN,,0,0,0,,And multiply, and divide.\nDialogue: 0,0:49:41.09,0:49:43.64,EN,,0,0,0,,And that is exactly and precisely what we have to do\nDialogue: 0,0:49:44.14,0:49:46.97,EN,,0,0,0,,to fit inside this generic arithmetic system.\nDialogue: 0,0:49:48.51,0:49:49.88,EN,,0,0,0,,Well how does the whole thing work?\nDialogue: 0,0:49:51.56,0:49:58.40,EN,,0,0,0,,See, what we want to do is have some generic operators.\nDialogue: 0,0:49:59.34,0:50:02.80,EN,,0,0,0,,Right? Have add and sub and mul and div be generic operators.\nDialogue: 0,0:50:03.99,0:50:17.36,EN,,0,0,0,,So we're going to define add and say, to add x and y,\nDialogue: 0,0:50:18.62,0:50:22.12,EN,,0,0,0,,that will be operate--\nDialogue: 0,0:50:26.08,0:50:27.49,EN,,0,0,0,,we were going to call it operate-2.\nDialogue: 0,0:50:27.49,0:50:30.78,EN,,0,0,0,,This is our operator procedure, but set up for two arguments\nDialogue: 0,0:50:31.60,0:50:35.84,EN,,0,0,0,,using add on x and y.\nDialogue: 0,0:50:37.60,0:50:39.76,EN,,0,0,0,,And so this is the analog to operate.\nDialogue: 0,0:50:40.42,0:50:41.68,EN,,0,0,0,,Let's look at the code for a second.\nDialogue: 0,0:50:41.68,0:50:42.93,EN,,0,0,0,,It's almost like operate.\nDialogue: 0,0:50:45.79,0:50:52.49,EN,,0,0,0,,Right? To operate with some operator on an argument1 and an argument2\nDialogue: 0,0:50:55.04,0:50:56.65,EN,,0,0,0,,well the first thing we're going to do is check\nDialogue: 0,0:50:56.83,0:51:00.73,EN,,0,0,0,,and see if the two arguments have the same type.\nDialogue: 0,0:51:01.90,0:51:02.96,EN,,0,0,0,,So we'll say,\nDialogue: 0,0:51:02.99,0:51:07.77,EN,,0,0,0,,is the type of the first argument the same as the type of the second argument?\nDialogue: 0,0:51:10.35,0:51:13.36,EN,,0,0,0,,And if they're not, if they're not\nDialogue: 0,0:51:13.58,0:51:15.63,EN,,0,0,0,,we'll go off and complain, and say, that's an error.\nDialogue: 0,0:51:15.67,0:51:16.67,EN,,0,0,0,,We don't know how to do that.\nDialogue: 0,0:51:19.14,0:51:20.49,EN,,0,0,0,,If they do have the same type,\nDialogue: 0,0:51:20.51,0:51:22.08,EN,,0,0,0,,we'll do exactly what we did before.\nDialogue: 0,0:51:22.08,0:51:26.46,EN,,0,0,0,,We'll go look and filed under the type of the argument--\nDialogue: 0,0:51:26.76,0:51:29.61,EN,,0,0,0,,arg 1 and arg 2 have the same type, so it doesn't matter.\nDialogue: 0,0:51:30.42,0:51:32.59,EN,,0,0,0,,So we'll look in the table, find the procedure.\nDialogue: 0,0:51:33.64,0:51:35.87,EN,,0,0,0,,If there is a procedure there,\nDialogue: 0,0:51:37.53,0:51:41.74,EN,,0,0,0,,then we'll apply it to the contents of the arg1 and the contents of arg2.\nDialogue: 0,0:51:43.03,0:51:44.76,EN,,0,0,0,,And otherwise we'll say, error.\nDialogue: 0,0:51:44.76,0:51:45.72,EN,,0,0,0,,Undefined operator.\nDialogue: 0,0:51:46.89,0:51:48.16,EN,,0,0,0,,And so there's operate-2.\nDialogue: 0,0:51:51.72,0:51:54.03,EN,,0,0,0,,And that's all we have to do.\nDialogue: 0,0:51:55.16,0:51:57.45,EN,,0,0,0,,We just built the complex number package before.\nDialogue: 0,0:51:57.64,0:52:01.00,EN,,0,0,0,,How do we embed that complex number package in this generic system?\nDialogue: 0,0:52:02.14,0:52:02.91,EN,,0,0,0,,Almost the same.\nDialogue: 0,0:52:06.41,0:52:08.59,EN,,0,0,0,,We make a procedure called make-complex\nDialogue: 0,0:52:09.95,0:52:12.81,EN,,0,0,0,,that takes whatever George and Martha hand to us\nDialogue: 0,0:52:13.64,0:52:15.00,EN,,0,0,0,,and add the type complex.\nDialogue: 0,0:52:18.17,0:52:23.87,EN,,0,0,0,,And then we say, to add complex numbers, plus complex,\nDialogue: 0,0:52:25.84,0:52:28.78,EN,,0,0,0,,we use our internal procedure, plus c,\nDialogue: 0,0:52:30.78,0:52:32.24,EN,,0,0,0,,and attach a type,\nDialogue: 0,0:52:32.24,0:52:33.42,EN,,0,0,0,,make that a complex number.\nDialogue: 0,0:52:37.68,0:52:42.52,EN,,0,0,0,,So our original package had names plus c and minus c\nDialogue: 0,0:52:42.68,0:52:44.75,EN,,0,0,0,,that we're using to communicate with George and Martha.\nDialogue: 0,0:52:45.25,0:52:47.39,EN,,0,0,0,,And then to communicate with the outside world,\nDialogue: 0,0:52:47.40,0:52:53.04,EN,,0,0,0,,we have a thing called plus-complex and minus-complex.\nDialogue: 0,0:52:55.92,0:52:56.53,EN,,0,0,0,,And so on.\nDialogue: 0,0:52:56.53,0:52:59.98,EN,,0,0,0,,And the only difference is that these return values that are typed\nDialogue: 0,0:53:01.12,0:53:02.41,EN,,0,0,0,,So they can be looked at up here.\nDialogue: 0,0:53:02.85,0:53:05.02,EN,,0,0,0,,And these are internal operations.\nDialogue: 0,0:53:09.25,0:53:10.68,EN,,0,0,0,,Let's go look at that slide again.\nDialogue: 0,0:53:10.68,0:53:13.04,EN,,0,0,0,,There's one more thing we do.\nDialogue: 0,0:53:13.74,0:53:15.61,EN,,0,0,0,,After defining plus-complex,\nDialogue: 0,0:53:15.68,0:53:20.52,EN,,0,0,0,,we put under the type complex and the symbol add,\nDialogue: 0,0:53:21.31,0:53:22.75,EN,,0,0,0,,that procedure plus complex.\nDialogue: 0,0:53:23.20,0:53:26.75,EN,,0,0,0,,And then similarly for subtracting complex numbers,\nDialogue: 0,0:53:27.13,0:53:29.13,EN,,0,0,0,,and multiplying them, and dividing them.\nDialogue: 0,0:53:31.70,0:53:33.48,EN,,0,0,0,,OK, how do we install ordinary numbers?\nDialogue: 0,0:53:35.25,0:53:36.12,EN,,0,0,0,,Exactly the same way.\nDialogue: 0,0:53:38.16,0:53:41.36,EN,,0,0,0,,Come off and say, well we'll make a thing called make-number\nDialogue: 0,0:53:44.34,0:53:48.11,EN,,0,0,0,,Make-number takes a number and attaches a type,\nDialogue: 0,0:53:48.14,0:53:49.29,EN,,0,0,0,,which is the symbol number.\nDialogue: 0,0:53:50.26,0:53:52.11,EN,,0,0,0,,We build a procedure called plus-number,\nDialogue: 0,0:53:52.92,0:53:58.75,EN,,0,0,0,,which is simply, add the two things using the ordinary addition,\nDialogue: 0,0:53:58.92,0:54:00.78,EN,,0,0,0,,because in this case we're talking about ordinary numbers,\nDialogue: 0,0:54:01.31,0:54:03.10,EN,,0,0,0,,and attach a type to it and make that a number.\nDialogue: 0,0:54:04.51,0:54:08.09,EN,,0,0,0,,And then we put into the table under the symbol number\nDialogue: 0,0:54:08.59,0:54:11.00,EN,,0,0,0,,and the operation add, this procedure plus-number,\nDialogue: 0,0:54:12.30,0:54:16.16,EN,,0,0,0,,and then the same thing for subtracting, and multiplying, and dividing.\nDialogue: 0,0:54:22.67,0:54:26.06,EN,,0,0,0,,Let's look at an example, just to make it clear.\nDialogue: 0,0:54:26.06,0:54:28.75,EN,,0,0,0,,Suppose, for instance,\nDialogue: 0,0:54:32.28,0:54:34.15,EN,,0,0,0,,I'm going to perform the operation.\nDialogue: 0,0:54:34.15,0:54:38.22,EN,,0,0,0,,So I sit up here and I'm going to perform the operation,\nDialogue: 0,0:54:38.22,0:54:40.46,EN,,0,0,0,,which looks like multiplying two complex numbers.\nDialogue: 0,0:54:40.93,0:54:48.64,EN,,0,0,0,,So I would multiply, say, 3 plus 4i and 2 plus 6i.\nDialogue: 0,0:54:50.17,0:54:52.60,EN,,0,0,0,,And that's something that I might want to take hand that to mul.\nDialogue: 0,0:54:52.84,0:54:55.76,EN,,0,0,0,,I'll write mul as my generic operator here.\nDialogue: 0,0:54:57.17,0:54:57.98,EN,,0,0,0,,How's that going to work?\nDialogue: 0,0:54:58.28,0:55:04.60,EN,,0,0,0,,Well 3 plus 4i, say, sits in the system at this level\nDialogue: 0,0:55:04.83,0:55:06.11,EN,,0,0,0,,as something that looks like this.\nDialogue: 0,0:55:06.25,0:55:07.52,EN,,0,0,0,,Let's say it was one of George's.\nDialogue: 0,0:55:08.28,0:55:14.97,EN,,0,0,0,,So it would have a 3 and a 4.\nDialogue: 0,0:55:18.49,0:55:20.97,EN,,0,0,0,,And attached to that would be George's type,\nDialogue: 0,0:55:24.33,0:55:28.32,EN,,0,0,0,,which says rectangular, it came from George.\nDialogue: 0,0:55:29.51,0:55:30.57,EN,,0,0,0,,And attached to that--\nDialogue: 0,0:55:31.23,0:55:35.79,EN,,0,0,0,,and this itself would be the data view from the next level up\nDialogue: 0,0:55:36.19,0:55:36.78,EN,,0,0,0,,which it is--\nDialogue: 0,0:55:37.93,0:55:39.96,EN,,0,0,0,,so that itself would be a type-data object\nDialogue: 0,0:55:40.60,0:55:41.80,EN,,0,0,0,,which would say complex.\nDialogue: 0,0:55:44.82,0:55:47.31,EN,,0,0,0,,So that's what this object would look like\nDialogue: 0,0:55:48.64,0:55:50.24,EN,,0,0,0,,up here at the very highest level,\nDialogue: 0,0:55:50.68,0:55:53.56,EN,,0,0,0,,where the really super-generic operations are looking at it.\nDialogue: 0,0:55:55.56,0:55:58.72,EN,,0,0,0,,Now what happens, mul eventually's going to come along\nDialogue: 0,0:55:58.84,0:56:00.40,EN,,0,0,0,,and say, oh,what's it's type?\nDialogue: 0,0:56:00.48,0:56:01.48,EN,,0,0,0,,It's type is complex.\nDialogue: 0,0:56:04.27,0:56:06.46,EN,,0,0,0,,Go through to operate-2 and say,\nDialogue: 0,0:56:06.46,0:56:09.72,EN,,0,0,0,,oh, what I want to do is apply what's in the table,\nDialogue: 0,0:56:09.72,0:56:13.04,EN,,0,0,0,,which is going to be the procedure star complex,\nDialogue: 0,0:56:15.08,0:56:17.76,EN,,0,0,0,,on this thing with the type stripped off.\nDialogue: 0,0:56:17.95,0:56:19.28,EN,,0,0,0,,So it's going to strip off the type,\nDialogue: 0,0:56:19.93,0:56:24.24,EN,,0,0,0,,take that much, and send that down into the complex world.\nDialogue: 0,0:56:26.70,0:56:28.73,EN,,0,0,0,,The complex world looks at its operations and says,\nDialogue: 0,0:56:28.76,0:56:30.56,EN,,0,0,0,,oh, I have to apply star c.\nDialogue: 0,0:56:31.28,0:56:32.14,EN,,0,0,0,,Star c might say,\nDialogue: 0,0:56:32.22,0:56:37.20,EN,,0,0,0,,at some point I want to look at the magnitude of this object that it's in, that it's got.\nDialogue: 0,0:56:39.42,0:56:40.16,EN,,0,0,0,,And they'll say, oh, it's\nDialogue: 0,0:56:40.16,0:56:41.71,EN,,0,0,0,,rectangular, it's one of George's.\nDialogue: 0,0:56:41.87,0:56:44.41,EN,,0,0,0,,So it'll then strip off the next version of type,\nDialogue: 0,0:56:46.91,0:56:49.80,EN,,0,0,0,,and hand that down to George to take the magnitude of.\nDialogue: 0,0:56:52.16,0:56:53.13,EN,,0,0,0,,So you see what's going on\nDialogue: 0,0:56:53.44,0:56:56.99,EN,,0,0,0,,is that there are these chains of types.\nDialogue: 0,0:56:59.32,0:57:01.50,EN,,0,0,0,,And the length of the chain is sort of the number of levels\nDialogue: 0,0:57:01.53,0:57:03.13,EN,,0,0,0,,that you're going to be going up in this table.\nDialogue: 0,0:57:05.09,0:57:05.96,EN,,0,0,0,,And what a type tells you,\nDialogue: 0,0:57:05.96,0:57:10.84,EN,,0,0,0,,every time you have a vertical barrier in this table,\nDialogue: 0,0:57:11.05,0:57:14.06,EN,,0,0,0,,where there's some ambiguity about where you should go down to the next level,\nDialogue: 0,0:57:14.41,0:57:15.85,EN,,0,0,0,,the type is telling you where to go.\nDialogue: 0,0:57:17.44,0:57:18.83,EN,,0,0,0,,And then everybody at the bottom,\nDialogue: 0,0:57:18.97,0:57:20.67,EN,,0,0,0,,as they construct data and filter it up,\nDialogue: 0,0:57:21.12,0:57:22.81,EN,,0,0,0,,they stick their type back on.\nDialogue: 0,0:57:25.35,0:57:30.75,EN,,0,0,0,,So that's the general structure of the system.\nDialogue: 0,0:57:33.41,0:57:33.77,EN,,0,0,0,,OK.\nDialogue: 0,0:57:34.82,0:57:35.68,EN,,0,0,0,,Now that we've got this,\nDialogue: 0,0:57:37.56,0:57:39.44,EN,,0,0,0,,let's go and make this thing even more complex.\nDialogue: 0,0:57:41.89,0:57:46.54,EN,,0,0,0,,Let's talk about adding to the system not only these kinds of numbers\nDialogue: 0,0:57:46.60,0:57:51.15,EN,,0,0,0,,numbers, but it's also meaningful to start talking about adding polynomials.\nDialogue: 0,0:57:51.51,0:57:52.97,EN,,0,0,0,,Might do arithmetic on polynomials.\nDialogue: 0,0:57:53.36,0:58:03.71,EN,,0,0,0,,Like we could have x to the fifteenth plus 2x to the seventh plus 5.\nDialogue: 0,0:58:04.48,0:58:05.84,EN,,0,0,0,,That might be some polynomial.\nDialogue: 0,0:58:06.38,0:58:07.93,EN,,0,0,0,,And if we have two such gadgets\nDialogue: 0,0:58:07.93,0:58:09.48,EN,,0,0,0,,we can add them or multiply them.\nDialogue: 0,0:58:10.53,0:58:11.79,EN,,0,0,0,,Let's not worry about dividing them.\nDialogue: 0,0:58:12.14,0:58:14.67,EN,,0,0,0,,Just add them, multiply them, then we'll subtract them.\nDialogue: 0,0:58:15.55,0:58:17.16,EN,,0,0,0,,Auhhh...What do we have to do? Well\nDialogue: 0,0:58:18.52,0:58:20.76,EN,,0,0,0,,let's think about how we might represent a polynomial.\nDialogue: 0,0:58:21.83,0:58:23.55,EN,,0,0,0,,It's going to be some typed data object.\nDialogue: 0,0:58:24.73,0:58:27.55,EN,,0,0,0,,So let's say a polynomial to this system\nDialogue: 0,0:58:28.54,0:58:31.68,EN,,0,0,0,,might look like a thing that starts with the type polynomial.\nDialogue: 0,0:58:32.00,0:58:34.55,EN,,0,0,0,,And then maybe it says the next thing is what variable its in.\nDialogue: 0,0:58:34.55,0:58:37.69,EN,,0,0,0,,So I might say I'm a polynomial in the variable x.\nDialogue: 0,0:58:38.96,0:58:41.39,EN,,0,0,0,,And then it'll have some information about what the terms are.\nDialogue: 0,0:58:42.25,0:58:44.16,EN,,0,0,0,,And there're just tons of ways to do this,\nDialogue: 0,0:58:44.25,0:58:47.63,EN,,0,0,0,,but one way is to say we're going to have a thing called a term-list.\nDialogue: 0,0:58:51.52,0:58:52.24,EN,,0,0,0,,And a term-list--\nDialogue: 0,0:58:53.70,0:58:55.61,EN,,0,0,0,,well, in our case we'll use something that looks like this.\nDialogue: 0,0:58:56.36,0:58:59.68,EN,,0,0,0,,We'll make it a bunch of pairs which have an order in a coefficient\nDialogue: 0,0:58:59.69,0:59:05.80,EN,,0,0,0,,So this polynomial would be represented by this term-list.\nDialogue: 0,0:59:09.42,0:59:10.68,EN,,0,0,0,,And what that means is that\nDialogue: 0,0:59:11.48,0:59:19.71,EN,,0,0,0,,this polynomial starts off with a term of order 15 and coefficient 1.\nDialogue: 0,0:59:23.82,0:59:27.50,EN,,0,0,0,,And the next thing in it is a term of order 7 and coefficient 2,\nDialogue: 0,0:59:27.53,0:59:30.49,EN,,0,0,0,,a term of order 0, which is constant in coefficient 5\nDialogue: 0,0:59:31.45,0:59:34.16,EN,,0,0,0,,And there are lots and lots of ways,\nDialogue: 0,0:59:34.25,0:59:35.96,EN,,0,0,0,,and lots and lots of trade-offs\nDialogue: 0,0:59:36.01,0:59:39.10,EN,,0,0,0,,when you really think about making algebraic manipulation packages\nDialogue: 0,0:59:39.44,0:59:41.73,EN,,0,0,0,,that exactly how you should represent these things.\nDialogue: 0,0:59:42.01,0:59:43.68,EN,,0,0,0,,But this is a fairly standard one.\nDialogue: 0,0:59:44.18,0:59:45.55,EN,,0,0,0,,It's useful in a lot of contexts.\nDialogue: 0,0:59:47.77,0:59:50.99,EN,,0,0,0,,OK, well how do we implement our polynomial arithmetic?\nDialogue: 0,0:59:53.47,0:59:54.96,EN,,0,0,0,,Let's start out.\nDialogue: 0,0:59:57.95,1:00:00.28,EN,,0,0,0,,What we'll do to make a polynomial--\nDialogue: 0,1:00:00.76,1:00:04.12,EN,,0,0,0,,we'll first have a way to make polynomials.\nDialogue: 0,1:00:05.69,1:00:10.28,EN,,0,0,0,,We're going to make a polynomial out of variable like x and term-list.\nDialogue: 0,1:00:11.24,1:00:14.09,EN,,0,0,0,,And all that does is we'll package them together someway.\nDialogue: 0,1:00:14.30,1:00:19.40,EN,,0,0,0,,We'll put the variable together with the term list using cons\nDialogue: 0,1:00:19.82,1:00:21.74,EN,,0,0,0,,and then attached to that the type polynomial.\nDialogue: 0,1:00:26.27,1:00:27.77,EN,,0,0,0,,OK, how do we add two polynomials?\nDialogue: 0,1:00:29.28,1:00:31.85,EN,,0,0,0,,To add a polynomial, p1 and p2,\nDialogue: 0,1:00:32.68,1:00:35.18,EN,,0,0,0,,and then just for simplicity let's say we\nDialogue: 0,1:00:35.37,1:00:37.15,EN,,0,0,0,,we will only add things in the same variable.\nDialogue: 0,1:00:37.38,1:00:39.28,EN,,0,0,0,,So if they have the same variable,\nDialogue: 0,1:00:39.69,1:00:42.57,EN,,0,0,0,,and same variable here is going to be some selector we write,\nDialogue: 0,1:00:42.96,1:00:44.38,EN,,0,0,0,,whose details we don't care about.\nDialogue: 0,1:00:45.15,1:00:47.04,EN,,0,0,0,,If the two polynomials have the same variable,\nDialogue: 0,1:00:48.03,1:00:48.81,EN,,0,0,0,,then we'll do something.\nDialogue: 0,1:00:48.81,1:00:51.26,EN,,0,0,0,,If they don't have the same variable, we'll give an error,\nDialogue: 0,1:00:52.35,1:00:54.01,EN,,0,0,0,,polynomials not in the same variable.\nDialogue: 0,1:00:55.48,1:00:57.37,EN,,0,0,0,,And if they do have the same variable,\nDialogue: 0,1:00:57.60,1:00:59.18,EN,,0,0,0,,what we'll do is we'll make a polynomial\nDialogue: 0,1:00:59.80,1:01:01.85,EN,,0,0,0,,whose variable is whatever that variable is,\nDialogue: 0,1:01:03.15,1:01:06.56,EN,,0,0,0,,and whose term-list is something we'll call sum-terms.\nDialogue: 0,1:01:07.48,1:01:09.80,EN,,0,0,0,,Plus terms will add the two term lists.\nDialogue: 0,1:01:10.17,1:01:12.01,EN,,0,0,0,,So we'll add the two term lists to the polynomial.\nDialogue: 0,1:01:13.50,1:01:14.51,EN,,0,0,0,,That'll give us a term-list.\nDialogue: 0,1:01:15.00,1:01:20.01,EN,,0,0,0,,We'll add on, we'll say it's a polynomial in the variable with that term-list.\nDialogue: 0,1:01:20.68,1:01:21.79,EN,,0,0,0,,That's plus poly.\nDialogue: 0,1:01:22.55,1:01:27.00,EN,,0,0,0,,And then we're going to put in our table under the type polynomial\nDialogue: 0,1:01:28.24,1:01:30.14,EN,,0,0,0,,add them using plus poly.\nDialogue: 0,1:01:30.52,1:01:31.75,EN,,0,0,0,,And of course we really haven't done much.\nDialogue: 0,1:01:31.75,1:01:35.31,EN,,0,0,0,,What we've really done is pushed all the work onto this thing, +terms\nDialogue: 0,1:01:35.79,1:01:37.02,EN,,0,0,0,,which is supposed to add term-lists.\nDialogue: 0,1:01:37.74,1:01:39.16,EN,,0,0,0,,Let's look at that.\nDialogue: 0,1:01:39.18,1:01:48.03,EN,,0,0,0,,Here's an overview of how we might add two term-lists.\nDialogue: 0,1:01:48.90,1:01:51.74,EN,,0,0,0,,So L1 and L2 were going to be two term-lists.\nDialogue: 0,1:01:52.00,1:01:54.81,EN,,0,0,0,,And a term-list is a bunch of pairs, coefficient in order.\nDialogue: 0,1:01:55.70,1:01:56.95,EN,,0,0,0,,And it's a big case analysis.\nDialogue: 0,1:01:59.86,1:02:04.14,EN,,0,0,0,,And the first thing we'll check for and see if there are any terms\nDialogue: 0,1:02:05.39,1:02:07.55,EN,,0,0,0,,We're going to recursively work down these term-lists\nDialogue: 0,1:02:08.16,1:02:11.74,EN,,0,0,0,,so eventually we'll get to a place where either L1 or L2 might be empty.\nDialogue: 0,1:02:12.27,1:02:14.35,EN,,0,0,0,,And if either one is empty,\nDialogue: 0,1:02:14.52,1:02:15.85,EN,,0,0,0,,our answer will be the other one.\nDialogue: 0,1:02:15.85,1:02:19.55,EN,,0,0,0,,So if L1 is empty we'll return L2,\nDialogue: 0,1:02:19.63,1:02:21.71,EN,,0,0,0,,and if L2 is empty we'll return L1.\nDialogue: 0,1:02:23.26,1:02:25.76,EN,,0,0,0,,Otherwise there are sort of three interesting cases.\nDialogue: 0,1:02:27.22,1:02:27.98,EN,,0,0,0,,What we're going to do is\nDialogue: 0,1:02:29.08,1:02:31.05,EN,,0,0,0,,grab the first term in each of those lists,\nDialogue: 0,1:02:33.50,1:02:36.04,EN,,0,0,0,,Right? Called t1 and t2.\nDialogue: 0,1:02:37.66,1:02:39.05,EN,,0,0,0,,And we're going to look at three cases,\nDialogue: 0,1:02:39.60,1:02:45.68,EN,,0,0,0,,depending on whether the order of t1 is greater than the order of t2,\nDialogue: 0,1:02:47.23,1:02:50.59,EN,,0,0,0,,or less than t2, or the same.\nDialogue: 0,1:02:53.28,1:02:54.91,EN,,0,0,0,,Those are the three cases we're going to look at.\nDialogue: 0,1:02:54.91,1:02:55.84,EN,,0,0,0,,Let's look at this case.\nDialogue: 0,1:02:58.64,1:03:01.31,EN,,0,0,0,,If the order of t1 is greater than the order of t2,\nDialogue: 0,1:03:03.40,1:03:04.70,EN,,0,0,0,,then what that means is that\nDialogue: 0,1:03:06.06,1:03:09.96,EN,,0,0,0,,then what that means is that our answer is going to start with this term of the order of t1.\nDialogue: 0,1:03:11.56,1:03:13.80,EN,,0,0,0,,Because it won't combine with any lower order terms.\nDialogue: 0,1:03:14.17,1:03:16.19,EN,,0,0,0,,So what we do is add the lower order terms.\nDialogue: 0,1:03:16.76,1:03:18.25,EN,,0,0,0,,We recursively add\nDialogue: 0,1:03:19.71,1:03:25.07,EN,,0,0,0,,together all the terms in the rest of the term-list in L1 and L2.\nDialogue: 0,1:03:27.13,1:03:29.32,EN,,0,0,0,,That's going to be the lower order terms of the answer.\nDialogue: 0,1:03:30.12,1:03:32.48,EN,,0,0,0,,And then we're going to adjoin to that the highest order term.\nDialogue: 0,1:03:33.18,1:03:35.45,EN,,0,0,0,,And I'm using here a whole bunch of procedures I haven't defined\nDialogue: 0,1:03:35.47,1:03:37.55,EN,,0,0,0,,like a adjoin-term, and rest-terms,\nDialogue: 0,1:03:38.48,1:03:40.17,EN,,0,0,0,,and selectors that get order.\nDialogue: 0,1:03:41.15,1:03:42.78,EN,,0,0,0,,But you can imagine what those are.\nDialogue: 0,1:03:44.44,1:03:48.76,EN,,0,0,0,,Right? So if the first term-list has a higher order than the second\nDialogue: 0,1:03:48.78,1:03:51.08,EN,,0,0,0,,we recursively add all the lower terms\nDialogue: 0,1:03:51.28,1:03:53.42,EN,,0,0,0,,and then stick on that last term.\nDialogue: 0,1:03:55.54,1:03:56.75,EN,,0,0,0,,The other case, the same way.\nDialogue: 0,1:03:56.89,1:04:00.28,EN,,0,0,0,,If the first term has a smaller order,\nDialogue: 0,1:04:00.54,1:04:08.36,EN,,0,0,0,,well then we add we add the first term-list and the rest of the terms in the second one\nDialogue: 0,1:04:08.62,1:04:12.65,EN,,0,0,0,,and adjoin on this highest order term.\nDialogue: 0,1:04:14.57,1:04:15.96,EN,,0,0,0,,So so far nothing's much happened,\nDialogue: 0,1:04:15.96,1:04:19.40,EN,,0,0,0,,we've just sort of pushed this thing off into adding lower order terms.\nDialogue: 0,1:04:19.47,1:04:21.96,EN,,0,0,0,,The last case where you actually get to a coefficients\nDialogue: 0,1:04:22.57,1:04:25.18,EN,,0,0,0,,that you have to add, this will be the case where the orders are equal.\nDialogue: 0,1:04:27.24,1:04:30.99,EN,,0,0,0,,What we do is, well again recursively add the lower order terms.\nDialogue: 0,1:04:31.00,1:04:32.83,EN,,0,0,0,,But now we have to really combine something.\nDialogue: 0,1:04:33.46,1:04:36.35,EN,,0,0,0,,What we do is we make a term\nDialogue: 0,1:04:37.31,1:04:39.93,EN,,0,0,0,,whose order is the order of the term we're looking at.\nDialogue: 0,1:04:40.82,1:04:42.72,EN,,0,0,0,,By now t1 and t2 have the same order.\nDialogue: 0,1:04:44.32,1:04:44.99,EN,,0,0,0,,That's its order.\nDialogue: 0,1:04:45.09,1:04:52.33,EN,,0,0,0,,And its coefficient is gotten by adding the coefficient of t1 and the coefficient of t2.\nDialogue: 0,1:04:55.79,1:04:59.64,EN,,0,0,0,,There's... This is a big recursive working down of terms,\nDialogue: 0,1:04:59.68,1:05:03.61,EN,,0,0,0,,but really there's only one interesting symbol in this procedure,\nDialogue: 0,1:05:04.25,1:05:05.69,EN,,0,0,0,,only one interesting idea.\nDialogue: 0,1:05:05.90,1:05:08.50,EN,,0,0,0,,The interesting idea is this add.\nDialogue: 0,1:05:12.39,1:05:14.80,EN,,0,0,0,,And the reason that's interesting is because\nDialogue: 0,1:05:15.42,1:05:17.37,EN,,0,0,0,,something completely wonderful just happened.\nDialogue: 0,1:05:18.22,1:05:21.37,EN,,0,0,0,,We reduced adding polynomials,\nDialogue: 0,1:05:22.56,1:05:26.46,EN,,0,0,0,,not to sort of plus, but to the generic add.\nDialogue: 0,1:05:28.82,1:05:32.28,EN,,0,0,0,,In other words, by implementing it that way,\nDialogue: 0,1:05:32.89,1:05:34.68,EN,,0,0,0,,not only do we have our system\nDialogue: 0,1:05:35.92,1:05:41.66,EN,,0,0,0,,where we can have rational numbers, or complex numbers, or ordinary numbers,\nDialogue: 0,1:05:41.85,1:05:43.82,EN,,0,0,0,,we've just added on polynomials.\nDialogue: 0,1:05:48.52,1:05:51.13,EN,,0,0,0,,But the coefficients of the polynomials\nDialogue: 0,1:05:51.24,1:05:52.86,EN,,0,0,0,,can be anything that the system can add.\nDialogue: 0,1:05:53.59,1:05:56.73,EN,,0,0,0,,So these could be polynomials whose coefficient\nDialogue: 0,1:05:57.20,1:06:01.20,EN,,0,0,0,,are rational numbers or complex numbers,\nDialogue: 0,1:06:02.76,1:06:06.99,EN,,0,0,0,,which in turn could be either rectangular, or polar,\nDialogue: 0,1:06:09.12,1:06:11.39,EN,,0,0,0,,or ordinary numbers.\nDialogue: 0,1:06:18.97,1:06:21.21,EN,,0,0,0,,Rignt? So what I mean precisely is\nDialogue: 0,1:06:22.06,1:06:24.35,EN,,0,0,0,,our system right now automatically\nDialogue: 0,1:06:26.60,1:06:31.50,EN,,0,0,0,,can handle things like adding together polynomials that have this form\nDialogue: 0,1:06:31.53,1:06:39.69,EN,,0,0,0,,2/3 of x squared plus 5/17 x plus 11/4.\nDialogue: 0,1:06:40.94,1:06:43.48,EN,,0,0,0,,Or automatically handle polynomials that look like\nDialogue: 0,1:06:43.82,1:06:52.57,EN,,0,0,0,,3 plus 2i times x to the fifth plus 4 plus 7i, or something.\nDialogue: 0,1:06:53.88,1:06:56.21,EN,,0,0,0,,Right? You can automatically handle those things.\nDialogue: 0,1:06:56.21,1:06:57.07,EN,,0,0,0,,Why is that?\nDialogue: 0,1:06:57.82,1:07:01.50,EN,,0,0,0,,That's merely because, or profoundly because\nDialogue: 0,1:07:02.17,1:07:05.93,EN,,0,0,0,,we reduced adding polynomials to adding their coefficients.\nDialogue: 0,1:07:06.79,1:07:10.22,EN,,0,0,0,,And adding coefficients was done by the generic add operator\nDialogue: 0,1:07:11.08,1:07:12.94,EN,,0,0,0,,which said, I don't care what your types are\nDialogue: 0,1:07:12.96,1:07:14.08,EN,,0,0,0,,as long as I know how to add you.\nDialogue: 0,1:07:15.23,1:07:18.86,EN,,0,0,0,,So automatically for free we get the ability to handle that.\nDialogue: 0,1:07:20.65,1:07:22.04,EN,,0,0,0,,What's even better than that,\nDialogue: 0,1:07:24.51,1:07:26.52,EN,,0,0,0,,one of the things we did\nDialogue: 0,1:07:27.20,1:07:30.52,EN,,0,0,0,,we put into the table that the way you add polynomials\nDialogue: 0,1:07:31.28,1:07:32.52,EN,,0,0,0,,is using plus poly.\nDialogue: 0,1:07:34.66,1:07:38.65,EN,,0,0,0,,That means that polynomials themselves are things that can be added.\nDialogue: 0,1:07:39.42,1:07:42.11,EN,,0,0,0,,So for instance let me write one here.\nDialogue: 0,1:07:43.18,1:07:46.19,EN,,0,0,0,,Here is... Here's a polynomial.\nDialogue: 0,1:07:50.56,1:07:52.41,EN,,0,0,0,,So this gadget here I'm writing up,\nDialogue: 0,1:07:54.12,1:07:58.46,EN,,0,0,0,,this is a polynomial in y\nDialogue: 0,1:08:01.07,1:08:04.69,EN,,0,0,0,,whose coefficients are polynomials in x.\nDialogue: 0,1:08:08.61,1:08:11.12,EN,,0,0,0,,So you see, simply by saying,\nDialogue: 0,1:08:11.76,1:08:14.06,EN,,0,0,0,,polynomials are themselves things that can be added,\nDialogue: 0,1:08:14.41,1:08:17.90,EN,,0,0,0,,we can go off and say, well not only can we deal with rationals,\nDialogue: 0,1:08:18.27,1:08:20.33,EN,,0,0,0,,or complex, or ordinary numbers,\nDialogue: 0,1:08:20.35,1:08:21.77,EN,,0,0,0,,but we can deal with polynomials\nDialogue: 0,1:08:22.09,1:08:25.39,EN,,0,0,0,,whose coefficients are rationals, or complex, or ordinary numbers,\nDialogue: 0,1:08:25.50,1:08:27.52,EN,,0,0,0,,or polynomials\nDialogue: 0,1:08:29.15,1:08:30.96,EN,,0,0,0,,whose coefficients are rationals,\nDialogue: 0,1:08:31.69,1:08:36.76,EN,,0,0,0,,or complex, rectangular, polar, or ordinary numbers,\nDialogue: 0,1:08:36.94,1:08:41.13,EN,,0,0,0,,or ordinary numbers, or polynomials whose coefficients are rationals,\nDialogue: 0,1:08:41.80,1:08:43.32,EN,,0,0,0,,complex, or ordinary numbers.\nDialogue: 0,1:08:43.67,1:08:45.21,EN,,0,0,0,,And so on, and so on, and so on.\nDialogue: 0,1:08:45.95,1:08:47.55,EN,,0,0,0,,So this is sort of an infinite\nDialogue: 0,1:08:48.49,1:08:52.88,EN,,0,0,0,,or maybe a recursive tower of types that we've built up.\nDialogue: 0,1:08:53.88,1:08:57.12,EN,,0,0,0,,And it's all exactly from that one little symbol, A-D-D.\nDialogue: 0,1:08:57.61,1:09:00.49,EN,,0,0,0,,Writing \"add\" instead of \"plus\" in the polynomial thing.\nDialogue: 0,1:09:02.27,1:09:03.77,EN,,0,0,0,,Slightly different way to think about it\nDialogue: 0,1:09:03.95,1:09:07.74,EN,,0,0,0,,is that polynomials are a constructor for types.\nDialogue: 0,1:09:08.74,1:09:11.20,EN,,0,0,0,,Namely you give it a type, like integer,\nDialogue: 0,1:09:11.48,1:09:15.74,EN,,0,0,0,,and it returns for you polynomials in x whose coefficients are integers.\nDialogue: 0,1:09:16.27,1:09:17.72,EN,,0,0,0,,And the important thing about\nDialogue: 0,1:09:18.65,1:09:20.73,EN,,0,0,0,,is that is that the operations on polynomials\nDialogue: 0,1:09:21.28,1:09:23.37,EN,,0,0,0,,reduce to the operations on the coefficients.\nDialogue: 0,1:09:23.39,1:09:24.96,EN,,0,0,0,,And there are a lot of things like that.\nDialogue: 0,1:09:25.84,1:09:27.92,EN,,0,0,0,,So for example, let's go back and rational numbers.\nDialogue: 0,1:09:28.87,1:09:32.65,EN,,0,0,0,,We thought about rational numbers as an integer over an integer\nDialogue: 0,1:09:32.67,1:09:35.66,EN,,0,0,0,,but there's the general notion of a rational object.\nDialogue: 0,1:09:36.24,1:09:42.03,EN,,0,0,0,,Like we might think about 3x plus 7 over x squared plus 1.\nDialogue: 0,1:09:43.07,1:09:48.86,EN,,0,0,0,,That's general rational object whose numerator and denominator are polynomials.\nDialogue: 0,1:09:50.31,1:09:52.41,EN,,0,0,0,,And to add two of them we use the same formula,\nDialogue: 0,1:09:52.44,1:09:55.40,EN,,0,0,0,,numerator times denominator plus denominator times numerator\nDialogue: 0,1:09:55.72,1:09:56.99,EN,,0,0,0,,over product of denominators.\nDialogue: 0,1:09:57.29,1:09:59.37,EN,,0,0,0,,How could we install that in our system?\nDialogue: 0,1:09:59.39,1:10:02.97,EN,,0,0,0,,Well here's our original rational number arithmetic package.\nDialogue: 0,1:10:04.25,1:10:08.24,EN,,0,0,0,,And all we have to do in order to make the entire system\nDialogue: 0,1:10:08.28,1:10:11.58,EN,,0,0,0,,continue working with general rational objects,\nDialogue: 0,1:10:11.85,1:10:16.44,EN,,0,0,0,,is replace these particular pluses and stars by the generic operator.\nDialogue: 0,1:10:16.48,1:10:19.18,EN,,0,0,0,,So if we simply change that procedure to this one,\nDialogue: 0,1:10:19.71,1:10:22.04,EN,,0,0,0,,here we've changed plus and star to add a mul,\nDialogue: 0,1:10:22.88,1:10:24.48,EN,,0,0,0,,those are absolutely the only change,\nDialogue: 0,1:10:24.84,1:10:26.03,EN,,0,0,0,,then suddenly\nDialogue: 0,1:10:27.52,1:10:31.40,EN,,0,0,0,,our entire system can start talking about objects that look like this.\nDialogue: 0,1:10:33.72,1:10:38.27,EN,,0,0,0,,So for example, here is a rational object\nDialogue: 0,1:10:39.18,1:10:44.86,EN,,0,0,0,,whose numerator is a polynomial in x whose coefficients are rational numbers.\nDialogue: 0,1:10:47.02,1:10:49.56,EN,,0,0,0,,Or here is a rational object\nDialogue: 0,1:10:51.10,1:10:54.43,EN,,0,0,0,,whose numerator is polynomials in x\nDialogue: 0,1:10:55.15,1:10:58.19,EN,,0,0,0,,whose coefficients are rational objects\nDialogue: 0,1:10:59.77,1:11:01.53,EN,,0,0,0,,constructed out of complex numbers.\nDialogue: 0,1:11:03.39,1:11:04.85,EN,,0,0,0,,And then there are a lot of other things like that.\nDialogue: 0,1:11:04.85,1:11:08.68,EN,,0,0,0,,See, whenever you have a thing where the operations reduce to operations on the pieces,\nDialogue: 0,1:11:08.89,1:11:10.00,EN,,0,0,0,,another example would be\nDialogue: 0,1:11:10.28,1:11:11.42,EN,,0,0,0,,two by two matrices.\nDialogue: 0,1:11:12.31,1:11:15.44,EN,,0,0,0,,I have the idea, there might be a matrix here\nDialogue: 0,1:11:16.43,1:11:18.33,EN,,0,0,0,,of general things that I don't care about.\nDialogue: 0,1:11:18.72,1:11:20.14,EN,,0,0,0,,But if I add two of them,\nDialogue: 0,1:11:22.33,1:11:25.18,EN,,0,0,0,,the answer over here is gotten by\nDialogue: 0,1:11:25.18,1:11:28.14,EN,,0,0,0,,adding this one and that one,however they like to add.\nDialogue: 0,1:11:29.03,1:11:31.11,EN,,0,0,0,,So I can implement that the same way.\nDialogue: 0,1:11:31.11,1:11:31.71,EN,,0,0,0,,And if I do that,\nDialogue: 0,1:11:31.96,1:11:34.60,EN,,0,0,0,,then again suddenly my system can start handling things like this.\nDialogue: 0,1:11:35.29,1:11:39.18,EN,,0,0,0,,So here's a matrix whose elements happen to be--\nDialogue: 0,1:11:39.46,1:11:42.16,EN,,0,0,0,,we'll say this element here is a rational object\nDialogue: 0,1:11:43.10,1:11:45.15,EN,,0,0,0,,whose numerator and denominators are polynomials.\nDialogue: 0,1:11:47.02,1:11:49.56,EN,,0,0,0,,Right? And all that comes for free.\nDialogue: 0,1:11:51.28,1:11:53.82,EN,,0,0,0,,Right? What's really going on here?\nDialogue: 0,1:11:53.92,1:11:56.17,EN,,0,0,0,,What's really going on is\nDialogue: 0,1:11:57.68,1:12:02.44,EN,,0,0,0,,getting rid of who's sitting there poking his nose into who everybody's business is.\nDialogue: 0,1:12:03.12,1:12:06.19,EN,,0,0,0,,We built a system that has decentralized control.\nDialogue: 0,1:12:14.78,1:12:18.34,EN,,0,0,0,,So when you come into and no one's poking around saying,\nDialogue: 0,1:12:18.35,1:12:22.30,EN,,0,0,0,,gee, are you in the official list of people who can be added?\nDialogue: 0,1:12:22.44,1:12:26.22,EN,,0,0,0,,Rather you say, well go off and add yourself how your parts like to be added.\nDialogue: 0,1:12:27.81,1:12:31.03,EN,,0,0,0,,And the result of that is you can get this very, very, very\nDialogue: 0,1:12:31.03,1:12:33.87,EN,,0,0,0,,complex hierarchy where a lot of things just get done and\nDialogue: 0,1:12:33.87,1:12:35.55,EN,,0,0,0,,rooted to the right place automatically.\nDialogue: 0,1:12:37.00,1:12:37.79,EN,,0,0,0,,Let's stop for questions.\nDialogue: 0,1:12:40.38,1:12:42.32,EN,,0,0,0,,AUDIENCE: You say you get this for free.\nDialogue: 0,1:12:42.35,1:12:45.82,EN,,0,0,0,,Um..... One thing that strikes me is that now you've lost\nDialogue: 0,1:12:46.48,1:12:50.91,EN,,0,0,0,,kind of the cleanness of the break between what's on top and what's underneath.\nDialogue: 0,1:12:50.91,1:12:52.77,EN,,0,0,0,,In other words, now you're defining some of the\nDialogue: 0,1:12:52.77,1:12:56.08,EN,,0,0,0,,lower-level procedures in terms of things above their own line.\nDialogue: 0,1:12:56.61,1:12:59.45,EN,,0,0,0,,Isn't that dangerous?\nDialogue: 0,1:13:00.35,1:13:04.49,EN,,0,0,0,,Or, if nothing more, a little less structured?\nDialogue: 0,1:13:05.44,1:13:05.95,EN,,0,0,0,,PROFESSOR: No, I--\nDialogue: 0,1:13:06.41,1:13:07.77,EN,,0,0,0,,the question is whether that's less structured.\nDialogue: 0,1:13:07.77,1:13:08.69,EN,,0,0,0,,Depends on what you mean by structure.\nDialogue: 0,1:13:08.69,1:13:10.17,EN,,0,0,0,,All this is doing is recursion.\nDialogue: 0,1:13:11.05,1:13:18.80,EN,,0,0,0,,See, it's saying that the way you add these guys is to use that.\nDialogue: 0,1:13:19.15,1:13:21.37,EN,,0,0,0,,And that's not less structured, it's just a recursive structure.\nDialogue: 0,1:13:22.70,1:13:24.99,EN,,0,0,0,,So I don't think it's particularly any less clean.\nDialogue: 0,1:13:24.99,1:13:28.16,EN,,0,0,0,,AUDIENCE: Now when you want to change the multiplier or the add operator\nDialogue: 0,1:13:29.34,1:13:31.38,EN,,0,0,0,,suddenly you've got tremendous consequences\nDialogue: 0,1:13:31.38,1:13:34.27,EN,,0,0,0,,underneath that you're not even sure the extent of.\nDialogue: 0,1:13:34.48,1:13:36.44,EN,,0,0,0,,PROFESSOR: That's right, but it depends what you mean.\nDialogue: 0,1:13:37.08,1:13:38.47,EN,,0,0,0,,See, this goes both ways.\nDialogue: 0,1:13:39.10,1:13:43.24,EN,,0,0,0,,Um....What would be a good example?\nDialogue: 0,1:13:44.69,1:13:47.50,EN,,0,0,0,,I ignored greatest common divisor, for instance.\nDialogue: 0,1:13:47.77,1:13:50.08,EN,,0,0,0,,I ignored that problem just to keep the example simple.\nDialogue: 0,1:13:50.28,1:13:56.92,EN,,0,0,0,,But if I suddenly decided that plus rat here\nDialogue: 0,1:13:57.82,1:14:01.69,EN,,0,0,0,,should do a GCD computation and install that,\nDialogue: 0,1:14:03.34,1:14:07.87,EN,,0,0,0,,then that immediately becomes available to all of these, to that guy, and that guy,\nDialogue: 0,1:14:08.03,1:14:10.08,EN,,0,0,0,,and that guy, and all the way down.\nDialogue: 0,1:14:11.56,1:14:13.89,EN,,0,0,0,,So it depends what you mean by the coherence of your system.\nDialogue: 0,1:14:13.89,1:14:17.03,EN,,0,0,0,,It's certainly true that you might want to have a special\nDialogue: 0,1:14:17.03,1:14:19.56,EN,,0,0,0,,different one that didn't filter down through the coefficients\nDialogue: 0,1:14:19.61,1:14:22.97,EN,,0,0,0,,but the nice thing about this particular example is that mostly you do.\nDialogue: 0,1:14:25.44,1:14:27.63,EN,,0,0,0,,AUDIENCE: Isn't that the problem, I think, that you're\nDialogue: 0,1:14:27.63,1:14:32.95,EN,,0,0,0,,getting to tied in with the fact that the structuring, the\nDialogue: 0,1:14:32.95,1:14:36.33,EN,,0,0,0,,recursiveness of that structuring there is actually\nDialogue: 0,1:14:36.33,1:14:40.34,EN,,0,0,0,,in execution as opposed to just definition of the actual\nDialogue: 0,1:14:40.34,1:14:41.16,EN,,0,0,0,,types themselves?\nDialogue: 0,1:14:44.68,1:14:46.12,EN,,0,0,0,,PROFESSOR: I think I understand the question.\nDialogue: 0,1:14:46.12,1:14:47.80,EN,,0,0,0,,The point is that these types evolve\nDialogue: 0,1:14:47.82,1:14:50.40,EN,,0,0,0,,and get more and more complex as the thing's actually running.\nDialogue: 0,1:14:50.40,1:14:50.73,EN,,0,0,0,,Is that what--\nDialogue: 0,1:14:50.73,1:14:50.99,EN,,0,0,0,,AUDIENCE: Yap.\nDialogue: 0,1:14:50.99,1:14:51.79,EN,,0,0,0,,As it's running.\nDialogue: 0,1:14:52.09,1:14:54.18,EN,,0,0,0,,AUDIENCE: As opposed to the basic definitions.\nDialogue: 0,1:14:54.18,1:14:54.83,EN,,0,0,0,,PROFESSOR: Right. There's...\nDialogue: 0,1:14:54.83,1:14:56.70,EN,,0,0,0,,The type structure is sort of recursive.\nDialogue: 0,1:14:57.21,1:15:00.22,EN,,0,0,0,,It's not that you can make this finite list of the\nDialogue: 0,1:15:01.58,1:15:04.85,EN,,0,0,0,,actual things they might look like before the system runs.\nDialogue: 0,1:15:04.85,1:15:05.79,EN,,0,0,0,,It's something that evolves.\nDialogue: 0,1:15:06.78,1:15:08.64,EN,,0,0,0,,So if you want to specify that system,\nDialogue: 0,1:15:08.67,1:15:10.96,EN,,0,0,0,,you have to do in some other way than by this finite list.\nDialogue: 0,1:15:11.00,1:15:13.18,EN,,0,0,0,,You have to do it by a recursive structure.\nDialogue: 0,1:15:13.67,1:15:17.90,EN,,0,0,0,,AUDIENCE: Because the basic structure of the types is pretty clean and simple.\nDialogue: 0,1:15:17.90,1:15:18.19,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:15:20.40,1:15:20.75,EN,,0,0,0,,Yes?\nDialogue: 0,1:15:21.46,1:15:22.87,EN,,0,0,0,,AUDIENCE: I have a question.\nDialogue: 0,1:15:22.87,1:15:25.68,EN,,0,0,0,,I understand once you have your data structure set up,\nDialogue: 0,1:15:25.71,1:15:28.73,EN,,0,0,0,,how it pulls off complex and passes that down,\nDialogue: 0,1:15:28.73,1:15:30.64,EN,,0,0,0,,and then pulls off rect, passes that down.\nDialogue: 0,1:15:30.64,1:15:33.95,EN,,0,0,0,,But if you're just a user and you don't know anything about rect or polar or whatever,\nDialogue: 0,1:15:34.25,1:15:36.04,EN,,0,0,0,,how do you initially set up that data structure\nDialogue: 0,1:15:36.09,1:15:38.08,EN,,0,0,0,,so that everything goes to the right spot?\nDialogue: 0,1:15:38.09,1:15:41.00,EN,,0,0,0,,If I just have the equation over there on the left\nDialogue: 0,1:15:41.02,1:15:42.50,EN,,0,0,0,,And I just want to add, multiply complex numbers--\nDialogue: 0,1:15:42.50,1:15:43.64,EN,,0,0,0,,PROFESSOR: Well that's the wonderful thing.\nDialogue: 0,1:15:43.64,1:15:45.26,EN,,0,0,0,,If you're just a user you say \"mul.\"\nDialogue: 0,1:15:47.73,1:15:49.95,EN,,0,0,0,,AUDIENCE: And it figures out that I mean complex numbers?\nDialogue: 0,1:15:49.96,1:15:51.23,EN,,0,0,0,,Or how do I tell it that I want--\nDialogue: 0,1:15:51.26,1:15:53.05,EN,,0,0,0,,PROFESSOR: Well you're going to have in your hands complex numbers.\nDialogue: 0,1:15:53.05,1:15:56.30,EN,,0,0,0,,See what you would have at some level, as a real user,\nDialogue: 0,1:15:56.32,1:15:58.14,EN,,0,0,0,,is a constructor for complex numbers.\nDialogue: 0,1:15:58.37,1:15:59.55,EN,,0,0,0,,AUDIENCE: So then I have to make complex numbers?\nDialogue: 0,1:15:59.56,1:16:00.35,EN,,0,0,0,,PROFESSOR: So you have to make them.\nDialogue: 0,1:16:00.35,1:16:04.01,EN,,0,0,0,,What you would probably have as a user is some little thing in the reader loop,\nDialogue: 0,1:16:04.65,1:16:07.56,EN,,0,0,0,,which would give you some plausible way\nDialogue: 0,1:16:07.56,1:16:08.86,EN,,0,0,0,,to type in a complex number,\nDialogue: 0,1:16:09.31,1:16:11.00,EN,,0,0,0,,in however whatever format you like.\nDialogue: 0,1:16:11.59,1:16:14.36,EN,,0,0,0,,Or it might be that you're never typing them in.\nDialogue: 0,1:16:14.36,1:16:16.17,EN,,0,0,0,,Someone's just handing you a complex number.\nDialogue: 0,1:16:16.78,1:16:19.82,EN,,0,0,0,,AUDIENCE: OK, so if I had a complex number that had a polynomial in it,\nDialogue: 0,1:16:19.82,1:16:21.96,EN,,0,0,0,,I'd have to make my polynomial and then make my complex number.\nDialogue: 0,1:16:21.96,1:16:23.96,EN,,0,0,0,,PROFESSOR: Right if you wanted it constructed from scratch.\nDialogue: 0,1:16:24.28,1:16:25.71,EN,,0,0,0,,At some point you construct them from scratch.\nDialogue: 0,1:16:25.71,1:16:27.05,EN,,0,0,0,,But what you don't have to know of that\nDialogue: 0,1:16:27.28,1:16:30.32,EN,,0,0,0,,is when you have the object you can just say \"mul.\" And it'll multiply.\nDialogue: 0,1:16:32.78,1:16:32.99,EN,,0,0,0,,Yeah?\nDialogue: 0,1:16:33.27,1:16:35.76,EN,,0,0,0,,AUDIENCE: I think the question that was being posed here is,\nDialogue: 0,1:16:36.45,1:16:40.01,EN,,0,0,0,,say if I want to change my presentation of complexes,\nDialogue: 0,1:16:40.03,1:16:41.44,EN,,0,0,0,,or some operation of complex,\nDialogue: 0,1:16:41.52,1:16:47.10,EN,,0,0,0,,how much real code I will have to gets around with,\nDialogue: 0,1:16:47.15,1:16:51.26,EN,,0,0,0,,or change to change it in one specific operation?\nDialogue: 0,1:16:52.27,1:16:53.49,EN,,0,0,0,,PROFESSOR: [UNINTELLIGIBLE] what you have to change.\nDialogue: 0,1:16:53.49,1:16:54.99,EN,,0,0,0,,And the point is that you only have to change\nDialogue: 0,1:16:55.39,1:16:56.07,EN,,0,0,0,,what you're changing.\nDialogue: 0,1:16:56.07,1:17:00.04,EN,,0,0,0,,See if Martha decides that she would rather--\nDialogue: 0,1:17:00.32,1:17:01.23,EN,,0,0,0,,let's see something silly--\nDialogue: 0,1:17:01.44,1:17:02.91,EN,,0,0,0,,like change the order in the pair.\nDialogue: 0,1:17:04.04,1:17:08.72,EN,,0,0,0,,Like angle and magnitude in the other order,\nDialogue: 0,1:17:09.39,1:17:10.80,EN,,0,0,0,,she just makes that change locally.\nDialogue: 0,1:17:10.97,1:17:13.29,EN,,0,0,0,,And the whole thing will propagate through the system in the right way.\nDialogue: 0,1:17:14.79,1:17:18.76,EN,,0,0,0,,Or if suddenly you said, gee, I have another representation for rationals.\nDialogue: 0,1:17:19.70,1:17:23.90,EN,,0,0,0,,And I'm going to stick it here, by filing those operations in the table.\nDialogue: 0,1:17:24.82,1:17:27.22,EN,,0,0,0,,Then suddenly all of these polynomials whose coefficients\nDialogue: 0,1:17:27.22,1:17:29.10,EN,,0,0,0,,are coefficients of coefficients, or whatever,\nDialogue: 0,1:17:29.24,1:17:32.40,EN,,0,0,0,,also can automatically have available that representation.\nDialogue: 0,1:17:32.70,1:17:34.67,EN,,0,0,0,,That's the power of this particular one.\nDialogue: 0,1:17:36.11,1:17:38.70,EN,,0,0,0,,AUDIENCE: I'm not sure if I can even pose an intelligent sounding question.\nDialogue: 0,1:17:38.70,1:17:42.38,EN,,0,0,0,,But somehow this whole thing went really nicely\nDialogue: 0,1:17:42.54,1:17:45.88,EN,,0,0,0,,to this beautiful finish where all the things seemed to fall into place.\nDialogue: 0,1:17:46.72,1:17:48.67,EN,,0,0,0,,And sort of seemed a little contrived.\nDialogue: 0,1:17:50.93,1:17:52.52,EN,,0,0,0,,That's all for the sake, I'm sure, of teaching.\nDialogue: 0,1:17:52.56,1:17:54.65,EN,,0,0,0,,I doubt that the guys who first did this--\nDialogue: 0,1:17:55.10,1:17:55.85,EN,,0,0,0,,and I could be wrong--\nDialogue: 0,1:17:56.60,1:17:59.72,EN,,0,0,0,,figured it all out so that when they just all put it all together,\nDialogue: 0,1:17:59.77,1:18:03.93,EN,,0,0,0,,you could all of the sudden, blam, do any kind of arithmetic on any kind of object.\nDialogue: 0,1:18:04.86,1:18:07.20,EN,,0,0,0,,It seems like maybe they had to play with it for a while\nDialogue: 0,1:18:07.93,1:18:10.62,EN,,0,0,0,,and had to bash it and rework it.\nDialogue: 0,1:18:11.80,1:18:14.12,EN,,0,0,0,,And it seems like that's the kind of problem we're really\nDialogue: 0,1:18:14.12,1:18:16.94,EN,,0,0,0,,faced with we start trying to design a really complex system\nDialogue: 0,1:18:17.31,1:18:20.35,EN,,0,0,0,,is having lots of different kinds of parts and not even knowing\nDialogue: 0,1:18:21.08,1:18:24.62,EN,,0,0,0,,what kinds of operations we're going to want to do on those parts.\nDialogue: 0,1:18:24.62,1:18:26.54,EN,,0,0,0,,How to organize the operations in this nice way\nDialogue: 0,1:18:26.56,1:18:29.63,EN,,0,0,0,,so that no matter what you do, when you start putting them together\nDialogue: 0,1:18:29.63,1:18:31.39,EN,,0,0,0,,everything starts falling out for free.\nDialogue: 0,1:18:31.70,1:18:34.34,EN,,0,0,0,,PROFESSOR: OK, well that's certainly a very intelligent question... Um\nDialogue: 0,1:18:35.10,1:18:39.52,EN,,0,0,0,,Um....One part is this is a very good methodology\nDialogue: 0,1:18:39.87,1:18:43.88,EN,,0,0,0,,that people have discovered a lot coming from symbolic algebra.\nDialogue: 0,1:18:44.59,1:18:45.90,EN,,0,0,0,,Because there are a lot of complications.\nDialogue: 0,1:18:47.59,1:18:50.71,EN,,0,0,0,,To allow you to implement these things before you decide\nDialogue: 0,1:18:50.71,1:18:52.89,EN,,0,0,0,,what you want all the operations to be, and all of that.\nDialogue: 0,1:18:53.31,1:18:57.72,EN,,0,0,0,,So in some sense it's an answer that people have discovered by wading through this stuff.\nDialogue: 0,1:18:58.56,1:19:00.75,EN,,0,0,0,,In another sense, it is a very contrived example.\nDialogue: 0,1:19:02.16,1:19:06.24,EN,,0,0,0,,AUDIENCE: It seems like to be able to do this you do have to\nDialogue: 0,1:19:06.24,1:19:09.01,EN,,0,0,0,,wade through it for a certain amount of time before you can become good at it.\nDialogue: 0,1:19:09.01,1:19:11.88,EN,,0,0,0,,PROFESSOR: Let me show you how terribly contrived this is.\nDialogue: 0,1:19:12.22,1:19:14.13,EN,,0,0,0,,So you can write all these wonderful things.\nDialogue: 0,1:19:14.13,1:19:16.25,EN,,0,0,0,,But the system that I wrote here,\nDialogue: 0,1:19:17.02,1:19:18.96,EN,,0,0,0,,and if we had another half an hour to give this lecture\nDialogue: 0,1:19:19.31,1:19:20.46,EN,,0,0,0,,I would have given this part of it,\nDialogue: 0,1:19:20.81,1:19:23.02,EN,,0,0,0,,which says, notice that it breaks down\nDialogue: 0,1:19:23.20,1:19:29.31,EN,,0,0,0,,if I tell it to do something as foolish as add 3 plus 7/2.\nDialogue: 0,1:19:30.88,1:19:33.42,EN,,0,0,0,,Because what will happen is you'll get to operate-2,\nDialogue: 0,1:19:33.80,1:19:35.95,EN,,0,0,0,,and operate-2 will say, oh this is type number,\nDialogue: 0,1:19:36.18,1:19:37.37,EN,,0,0,0,,and that's type rational.\nDialogue: 0,1:19:37.56,1:19:38.81,EN,,0,0,0,,I don't know how to add them.\nDialogue: 0,1:19:41.53,1:19:44.30,EN,,0,0,0,,So you'd like the system at least to be able to say something like,\nDialogue: 0,1:19:45.88,1:19:47.34,EN,,0,0,0,,gee,before you do that\nDialogue: 0,1:19:48.59,1:19:50.24,EN,,0,0,0,,change that to 3/1.\nDialogue: 0,1:19:50.48,1:19:53.21,EN,,0,0,0,,Turn it into a rational number, hand that to the rational package.\nDialogue: 0,1:19:54.86,1:19:58.70,EN,,0,0,0,,That's the thing I didn't talk about in this lecture.\nDialogue: 0,1:19:58.73,1:20:00.88,EN,,0,0,0,,It's a little bit in the book,which talks about the problem\nDialogue: 0,1:20:00.88,1:20:01.95,EN,,0,0,0,,of what's called coercion.\nDialogue: 0,1:20:03.39,1:20:05.15,EN,,0,0,0,,Where you wanted--\nDialogue: 0,1:20:05.31,1:20:08.89,EN,,0,0,0,,see, having so carefully set up all of these types as distinct objects\nDialogue: 0,1:20:08.91,1:20:12.17,EN,,0,0,0,,a lot of times you want to also put in knowledge\nDialogue: 0,1:20:12.40,1:20:17.98,EN,,0,0,0,,about how to view an ordinary number as a kind of rational.\nDialogue: 0,1:20:19.11,1:20:21.29,EN,,0,0,0,,Or view an ordinary number as a kind of complex.\nDialogue: 0,1:20:21.62,1:20:25.16,EN,,0,0,0,,That's where the complexity in the system really starts happening\nDialogue: 0,1:20:25.76,1:20:28.12,EN,,0,0,0,,where you talk about, see where do I put that knowledge?\nDialogue: 0,1:20:28.42,1:20:32.19,EN,,0,0,0,,Is it rational to know that ordinary numbers might be pieces of cons of them?\nDialogue: 0,1:20:33.13,1:20:36.38,EN,,0,0,0,,Or they're terrible, terrible examples, like\nDialogue: 0,1:20:38.14,1:20:47.48,EN,,0,0,0,,if I might want to add a complex number to a rational number.\nDialogue: 0,1:20:49.87,1:20:50.76,EN,,0,0,0,,Bad example.\nDialogue: 0,1:20:50.76,1:20:51.58,EN,,0,0,0,,5/7.\nDialogue: 0,1:20:53.86,1:20:55.72,EN,,0,0,0,,Then somebody's got to know that\nDialogue: 0,1:20:56.06,1:20:58.16,EN,,0,0,0,,I have to convert these to another type,\nDialogue: 0,1:20:58.20,1:21:00.65,EN,,0,0,0,,which is complex numbers whose parts might be rationals.\nDialogue: 0,1:21:01.54,1:21:02.68,EN,,0,0,0,,And who worries about that?\nDialogue: 0,1:21:02.68,1:21:03.95,EN,,0,0,0,,Does complex worry about that?\nDialogue: 0,1:21:03.95,1:21:05.03,EN,,0,0,0,,Does rational worry about that?\nDialogue: 0,1:21:05.24,1:21:06.22,EN,,0,0,0,,Does plus worry about that?\nDialogue: 0,1:21:06.90,1:21:08.52,EN,,0,0,0,,That's where the real complexity comes in.\nDialogue: 0,1:21:08.52,1:21:11.38,EN,,0,0,0,,And that's where it's pretty well sorted out.\nDialogue: 0,1:21:11.38,1:21:14.12,EN,,0,0,0,,And a lot of, in fact, all of this message passing stuff\nDialogue: 0,1:21:14.64,1:21:16.54,EN,,0,0,0,,was motivated by problems like this.\nDialogue: 0,1:21:18.46,1:21:20.89,EN,,0,0,0,,And when you really push it, people are--\nDialogue: 0,1:21:20.91,1:21:24.76,EN,,0,0,0,,somehow the algebraic manipulation problem seems to be so complex\nDialogue: 0,1:21:25.18,1:21:27.41,EN,,0,0,0,,that the people who are always at the edge of it are exactly in\nDialogue: 0,1:21:27.41,1:21:28.05,EN,,0,0,0,,the state you said.\nDialogue: 0,1:21:28.05,1:21:29.71,EN,,0,0,0,,They're wading through this thing, mucking around,\nDialogue: 0,1:21:29.72,1:21:31.37,EN,,0,0,0,,seeing what they use, trying to distill stuff.\nDialogue: 0,1:21:34.20,1:21:37.76,EN,,0,0,0,,AUDIENCE: I just want to come back to this issue of complexity once more.\nDialogue: 0,1:21:38.41,1:21:44.55,EN,,0,0,0,,Um... It certainly seems to be true that you have a great deal of\nDialogue: 0,1:21:44.55,1:21:48.32,EN,,0,0,0,,flexibility in altering the lower level kinds of things.\nDialogue: 0,1:21:49.71,1:21:53.40,EN,,0,0,0,,But it is true that you are, in a sense,\nDialogue: 0,1:21:53.44,1:21:55.26,EN,,0,0,0,,freezing higher level operations.\nDialogue: 0,1:21:55.45,1:21:58.51,EN,,0,0,0,,Or at least if you change them you don't know where all of\nDialogue: 0,1:21:58.51,1:22:02.06,EN,,0,0,0,,the changes are going to show up, or how they are.\nDialogue: 0,1:22:02.20,1:22:04.22,EN,,0,0,0,,PROFESSOR: OK, that's an extremely good question.\nDialogue: 0,1:22:04.68,1:22:05.87,EN,,0,0,0,,What I have to do is,\nDialogue: 0,1:22:08.68,1:22:10.84,EN,,0,0,0,,if I decide there's a new general operation\nDialogue: 0,1:22:11.45,1:22:13.07,EN,,0,0,0,,called equality test,\nDialogue: 0,1:22:14.96,1:22:17.15,EN,,0,0,0,,then all of these people have to decide\nDialogue: 0,1:22:18.22,1:22:22.54,EN,,0,0,0,,whether or not they would like to have an equality test by looking in the table.\nDialogue: 0,1:22:24.65,1:22:26.84,EN,,0,0,0,,There're ways to decentralize it even more.\nDialogue: 0,1:22:27.87,1:22:30.70,EN,,0,0,0,,That's what I sort of hinted at last time, where I said\nDialogue: 0,1:22:31.08,1:22:33.26,EN,,0,0,0,,you could not only have this type as a symbol,\nDialogue: 0,1:22:33.40,1:22:38.70,EN,,0,0,0,,but you actually might store in each object the operations that it knows of that.\nDialogue: 0,1:22:40.45,1:22:43.90,EN,,0,0,0,,So you might have things like greatest common divisor,\nDialogue: 0,1:22:44.43,1:22:46.81,EN,,0,0,0,,which is a thing here which is defined only for integers,\nDialogue: 0,1:22:47.40,1:22:49.21,EN,,0,0,0,,and not in general for rational numbers.\nDialogue: 0,1:22:51.03,1:22:53.11,EN,,0,0,0,,So it might be a very, very fragmented system.\nDialogue: 0,1:22:53.11,1:22:55.66,EN,,0,0,0,,And then depending on where you want your flexibility,\nDialogue: 0,1:22:56.22,1:22:59.02,EN,,0,0,0,,You...there's a whole spectrum of places that you  can build that in.\nDialogue: 0,1:22:59.96,1:23:02.56,EN,,0,0,0,,But you're pointing at the place where this starts being weak,\nDialogue: 0,1:23:02.60,1:23:06.37,EN,,0,0,0,,that there has to be some agreement on top here about these general operations.\nDialogue: 0,1:23:06.37,1:23:07.82,EN,,0,0,0,,Or at least people have to think about them.\nDialogue: 0,1:23:08.39,1:23:10.72,EN,,0,0,0,,Or you might decide, you might have a table that's very sparse\nDialogue: 0,1:23:10.75,1:23:11.96,EN,,0,0,0,,that only has a few things in it.\nDialogue: 0,1:23:14.01,1:23:15.49,EN,,0,0,0,,But there are lot of ways to play that game.\nDialogue: 0,1:23:19.78,1:23:20.43,EN,,0,0,0,,OK, thank you.\nDialogue: 0,0:00:00.00,0:00:02.25,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:04.33,0:00:10.35,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N刘殊君（rtmagic）\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:11.40,0:00:16.50,Declare,,0,0,0,,{\\an2\\fad(500,500)}通用运算符\nDialogue: 0,0:00:20.18,0:00:21.84,Default,,0,0,0,,教授：到目前为止 我们已经进行了很多\nDialogue: 0,0:00:21.84,0:00:23.78,Default,,0,0,0,,关于数据抽象的讨论\nDialogue: 0,0:00:23.78,0:00:27.15,Default,,0,0,0,,关键理念就是在构造系统的时候\nDialogue: 0,0:00:27.74,0:00:32.56,Default,,0,0,0,,在其中加入水平的抽象屏障 这些抽象屏障\nDialogue: 0,0:00:33.42,0:00:39.21,Default,,0,0,0,,把你使用一个数据对象的方式\nDialogue: 0,0:00:39.93,0:00:41.18,Default,,0,0,0,,和表示它的方式区分开来\nDialogue: 0,0:00:49.40,0:00:52.03,Default,,0,0,0,,或者可以这样理解它 在上层有一个老板\nDialogue: 0,0:00:52.11,0:00:55.50,Default,,0,0,0,,想要调用某种数据对象\nDialogue: 0,0:00:57.11,0:01:02.31,Default,,0,0,0,,而在下层 George负责它的具体实现\nDialogue: 0,0:01:02.31,0:01:05.42,Default,,0,0,0,,这种把使用与表示分离的想法\nDialogue: 0,0:01:05.44,0:01:09.76,Default,,0,0,0,,可以让你分开考虑这两个问题\nDialogue: 0,0:01:10.60,0:01:14.76,Default,,0,0,0,,这是一种非常强大的编程的方法论 -- 数据抽象\nDialogue: 0,0:01:15.93,0:01:18.81,Default,,0,0,0,,但另一方面 数据抽象在那些真正复杂的系统上\nDialogue: 0,0:01:19.56,0:01:21.84,Default,,0,0,0,,并不是很有效\nDialogue: 0,0:01:22.96,0:01:27.64,Default,,0,0,0,,这个问题就出在George这里\nDialogue: 0,0:01:28.64,0:01:32.09,Default,,0,0,0,,或者说 实际上 问题就在于\nDialogue: 0,0:01:32.09,0:01:32.78,Default,,0,0,0,,现在有太多的George\nDialogue: 0,0:01:34.63,0:01:35.39,Default,,0,0,0,,具体地说\nDialogue: 0,0:01:35.39,0:01:39.18,Default,,0,0,0,,假设现在有George和Martha两个人\nDialogue: 0,0:01:41.19,0:01:44.22,Default,,0,0,0,,他们都是这个系统的开发人员\nDialogue: 0,0:01:46.04,0:01:47.29,Default,,0,0,0,,都在设计数据的表示方法\nDialogue: 0,0:01:48.41,0:01:50.67,Default,,0,0,0,,而且他们完全合不来\nDialogue: 0,0:01:51.75,0:01:53.62,Default,,0,0,0,,他们不会合作开发同一种表示方法\nDialogue: 0,0:01:54.01,0:01:55.34,Default,,0,0,0,,永远也不会\nDialogue: 0,0:01:57.48,0:01:59.72,Default,,0,0,0,,现在的问题是 假设你想要这样一个系统\nDialogue: 0,0:02:00.06,0:02:02.60,Default,,0,0,0,,在这个系统中George和Martha都为它设计了数据表示方法\nDialogue: 0,0:02:03.82,0:02:08.08,Default,,0,0,0,,但是如果你在高于这个抽象屏障的层面思考\nDialogue: 0,0:02:09.40,0:02:11.04,Default,,0,0,0,,你就不用去操心这些事情\nDialogue: 0,0:02:11.66,0:02:14.18,Default,,0,0,0,,不用操心 某个东西是到底是George做的还是Martha做的\nDialogue: 0,0:02:14.18,0:02:15.43,Default,,0,0,0,,同时你也不想让George和Martha\nDialogue: 0,0:02:15.43,0:02:16.48,Default,,0,0,0,,妨碍彼此的工作\nDialogue: 0,0:02:16.63,0:02:20.31,Default,,0,0,0,,你在设计系统的时候 不仅仅需要这些\nDialogue: 0,0:02:20.31,0:02:23.84,Default,,0,0,0,,水平的抽象屏障 同时也想设置一道\nDialogue: 0,0:02:25.82,0:02:30.64,Default,,0,0,0,,垂直的屏障 -- 来把George和Martha分离开\nDialogue: 0,0:02:32.98,0:02:35.40,Default,,0,0,0,,我们来说得再具体一点\nDialogue: 0,0:02:36.56,0:02:40.54,Default,,0,0,0,,想象一个很大的公司的人事记录\nDialogue: 0,0:02:41.18,0:02:46.11,Default,,0,0,0,,这个公司里有很多部门没什么联系\nDialogue: 0,0:02:47.90,0:02:49.71,Default,,0,0,0,,并且部门之间合作得也不太好\nDialogue: 0,0:02:50.43,0:02:57.04,Default,,0,0,0,,甚至还可以想象这个大公司就是由\nDialogue: 0,0:02:57.04,0:02:59.45,Default,,0,0,0,,很多公司组成的 而且每个公司\nDialogue: 0,0:02:59.45,0:03:00.70,Default,,0,0,0,,都有自己的一套人事记录\nDialogue: 0,0:03:03.25,0:03:06.57,Default,,0,0,0,,想象一下突然有一天 这些部门\nDialogue: 0,0:03:06.57,0:03:08.53,Default,,0,0,0,,被一种神奇的卫星网络连接起来\nDialogue: 0,0:03:08.53,0:03:10.52,Default,,0,0,0,,它们各自的数据库都被放到了一起\nDialogue: 0,0:03:12.24,0:03:13.85,Default,,0,0,0,,现在你想要\nDialogue: 0,0:03:14.84,0:03:16.33,Default,,0,0,0,,在公司的任何地方\nDialogue: 0,0:03:17.26,0:03:23.13,Default,,0,0,0,,都能够知道 哦 某一条人事记录里的\nDialogue: 0,0:03:23.13,0:03:23.87,Default,,0,0,0,,“姓名”是什么\nDialogue: 0,0:03:26.30,0:03:29.15,Default,,0,0,0,,或者一条记录里的“工作”是什么\nDialogue: 0,0:03:30.54,0:03:34.40,Default,,0,0,0,,同时又不需要担心每一个部门\nDialogue: 0,0:03:34.84,0:03:36.76,Default,,0,0,0,,对于人事记录的格式\nDialogue: 0,0:03:36.76,0:03:39.37,Default,,0,0,0,,有着完全不同的习惯\nDialogue: 0,0:03:41.58,0:03:43.26,Default,,0,0,0,,从你的视角上你不想去了解这些东西\nDialogue: 0,0:03:44.96,0:03:47.92,Default,,0,0,0,,那么怎么才能做到这样呢？\nDialogue: 0,0:03:48.43,0:03:52.41,Default,,0,0,0,,当然 一种方法是下发一个告示\nDialogue: 0,0:03:52.64,0:03:56.29,Default,,0,0,0,,来通知所有人把他们的记录格式\nDialogue: 0,0:03:56.29,0:03:57.24,Default,,0,0,0,,都改成某种标准的格式\nDialogue: 0,0:03:58.07,0:04:00.12,Default,,0,0,0,,人们经常这样做 但都没有成功\nDialogue: 0,0:04:01.82,0:04:07.34,Default,,0,0,0,,另一个办法则是重新安排这些记录\nDialogue: 0,0:04:08.33,0:04:09.90,Default,,0,0,0,,让它们中间有这种垂直的抽象屏障\nDialogue: 0,0:04:11.25,0:04:14.40,Default,,0,0,0,,当你查询一份人事档案里的姓名的时候\nDialogue: 0,0:04:14.43,0:04:17.97,Default,,0,0,0,,不管它是什么格式 name这个过程都能设法\nDialogue: 0,0:04:17.97,0:04:19.42,Default,,0,0,0,,搞清楚怎么正确地完成这件事\nDialogue: 0,0:04:22.73,0:04:25.53,Default,,0,0,0,,我们把name叫做一个 所谓的“通用运算符”\nDialogue: 0,0:04:26.26,0:04:30.06,Default,,0,0,0,,通用运算符意味着它会根据数据的种类\nDialogue: 0,0:04:30.06,0:04:31.69,Default,,0,0,0,,准确地做出对应的操作\nDialogue: 0,0:04:33.65,0:04:36.62,Default,,0,0,0,,更进一步讲 你想让这个系统在\nDialogue: 0,0:04:36.92,0:04:39.79,Default,,0,0,0,,下次公司里多了一个新的人员划分的时候\nDialogue: 0,0:04:42.51,0:04:45.64,Default,,0,0,0,,人们连接系统的方法不会有很大的变化\nDialogue: 0,0:04:45.64,0:04:50.11,Default,,0,0,0,,并且公司里剩下的部门\nDialogue: 0,0:04:50.11,0:04:52.01,Default,,0,0,0,,要把它们的人员记录添加到这个系统\nDialogue: 0,0:04:52.27,0:04:53.93,Default,,0,0,0,,也不需要做什么大的修改\nDialogue: 0,0:04:55.52,0:04:57.52,Default,,0,0,0,,那么这就是你应该考虑的问题\nDialogue: 0,0:04:58.70,0:05:00.77,Default,,0,0,0,,或者这就是你的工作\nDialogue: 0,0:05:00.77,0:05:03.77,Default,,0,0,0,,要让系统可以用最少的改动来拥抱变化\nDialogue: 0,0:05:05.98,0:05:08.12,Default,,0,0,0,,这就是我们今天要讨论的问题\nDialogue: 0,0:05:09.44,0:05:14.22,Default,,0,0,0,,你脑子里应该有这个分布式的人事档案系统\nDialogue: 0,0:05:14.24,0:05:16.62,Default,,0,0,0,,但是实际上 我今天要讨论的是一个\nDialogue: 0,0:05:16.62,0:05:18.48,Default,,0,0,0,,比那要更加自成体系的问题\nDialogue: 0,0:05:19.29,0:05:21.76,Default,,0,0,0,,我觉得用它可以把事情说得更清楚一点\nDialogue: 0,0:05:21.87,0:05:26.01,Default,,0,0,0,,我们要讨论的是 复数域上的算术系统\nDialogue: 0,0:05:27.77,0:05:28.92,Default,,0,0,0,,我们来看看这个系统\nDialogue: 0,0:05:30.69,0:05:31.74,Default,,0,0,0,,来复习一下\nDialogue: 0,0:05:32.04,0:05:33.53,Default,,0,0,0,,什么是“复数”\nDialogue: 0,0:05:35.25,0:05:38.22,Default,,0,0,0,,复数z可以看做复平面上的一点\nDialogue: 0,0:05:39.37,0:05:47.19,Default,,0,0,0,,我们将复数表示为实数部分和虚数部分\nDialogue: 0,0:05:47.19,0:05:50.83,Default,,0,0,0,,所以如果这个是复数z 它的实部是这么多\nDialogue: 0,0:05:51.50,0:05:53.24,Default,,0,0,0,,它的虚部是那么多\nDialogue: 0,0:05:54.33,0:05:56.44,Default,,0,0,0,,我们就可以记z=x+iy\nDialogue: 0,0:05:59.11,0:06:03.21,Default,,0,0,0,,还有另一种方法来表示一个复数 比如说\nDialogue: 0,0:06:03.21,0:06:09.00,Default,,0,0,0,,这个点与原点的距离是多少 在原点的什么角度上\nDialogue: 0,0:06:11.32,0:06:16.67,Default,,0,0,0,,像这样 复数也可以表示为半径乘以一个角度\nDialogue: 0,0:06:19.52,0:06:21.92,Default,,0,0,0,,第一种表示法称为 直角坐标系表示\nDialogue: 0,0:06:22.59,0:06:25.45,Default,,0,0,0,,或者说实部-虚部表示\nDialogue: 0,0:06:26.20,0:06:30.04,Default,,0,0,0,,而后一种是用模和辐角两部分的极坐标表示\nDialogue: 0,0:06:30.04,0:06:31.48,Default,,0,0,0,,并且如果你知道了一个复数的实部和虚部\nDialogue: 0,0:06:31.53,0:06:33.36,Default,,0,0,0,,你就能计算出它的模和辐角\nDialogue: 0,0:06:33.72,0:06:36.97,Default,,0,0,0,,如果知道了x和y 就能用这个式子算出r\nDialogue: 0,0:06:37.19,0:06:39.48,Default,,0,0,0,,等于两个数平方和的平方根 然后就可以\nDialogue: 0,0:06:39.48,0:06:40.76,Default,,0,0,0,,用反三角函数算出辐角的值\nDialogue: 0,0:06:41.42,0:06:44.42,Default,,0,0,0,,或者反过来 如果你知道了r和A\nDialogue: 0,0:06:44.42,0:06:45.31,Default,,0,0,0,,你也能计算出x和y\nDialogue: 0,0:06:45.80,0:06:49.43,Default,,0,0,0,,x=r·cos(A) y=r·sin(A)\nDialogue: 0,0:06:51.34,0:06:53.66,Default,,0,0,0,,这是表示复数的两种不同方法\nDialogue: 0,0:06:54.13,0:06:57.15,Default,,0,0,0,,分别是极坐标形式和直角坐标形式\nDialogue: 0,0:06:57.15,0:06:58.12,Default,,0,0,0,,我们要设计的是\nDialogue: 0,0:06:58.32,0:07:01.32,Default,,0,0,0,,一个复数域上的算术系统\nDialogue: 0,0:07:03.95,0:07:05.12,Default,,0,0,0,,换句话讲 我们要\nDialogue: 0,0:07:05.58,0:07:06.99,Default,,0,0,0,,就像之前课上有理数运算的例子一样\nDialogue: 0,0:07:07.38,0:07:10.20,Default,,0,0,0,,是构造一个叫做+c的操作\nDialogue: 0,0:07:10.73,0:07:13.90,Default,,0,0,0,,它将两个复数然后把它们相加、相减\nDialogue: 0,0:07:14.35,0:07:16.94,Default,,0,0,0,,相乘或者相除\nDialogue: 0,0:07:20.73,0:07:25.28,Default,,0,0,0,,那么我们要用到一点点数学\nDialogue: 0,0:07:25.28,0:07:28.36,Default,,0,0,0,,对它们进行操作的具体的算式是什么\nDialogue: 0,0:07:30.41,0:07:31.92,Default,,0,0,0,,它们是怎么得出来的 并不重要\nDialogue: 0,0:07:34.00,0:07:35.79,Default,,0,0,0,,我们只是用它们实现运算\nDialogue: 0,0:07:35.80,0:07:37.95,Default,,0,0,0,,如果想要把两个复数相加\nDialogue: 0,0:07:39.13,0:07:42.66,Default,,0,0,0,,可以很容易地获取它们的实部和虚部\nDialogue: 0,0:07:42.66,0:07:45.93,Default,,0,0,0,,两个复数的和的实部\nDialogue: 0,0:07:47.72,0:07:49.72,Default,,0,0,0,,z1+z2的实部\nDialogue: 0,0:07:50.06,0:07:54.64,Default,,0,0,0,,就是z1的实部加上z2的实部\nDialogue: 0,0:07:57.82,0:08:01.60,Default,,0,0,0,,然后z1+z2的虚部也就是\nDialogue: 0,0:08:01.74,0:08:05.66,Default,,0,0,0,,z1的虚部加上z2的虚部\nDialogue: 0,0:08:07.41,0:08:09.48,Default,,0,0,0,,所以复数相加是非常简单的事情\nDialogue: 0,0:08:09.48,0:08:10.99,Default,,0,0,0,,你只要把各个部分分别加起来\nDialogue: 0,0:08:11.31,0:08:13.18,Default,,0,0,0,,然后用结果构建一个新的复数\nDialogue: 0,0:08:13.37,0:08:14.73,Default,,0,0,0,,如果你想要让复数相乘\nDialogue: 0,0:08:15.53,0:08:17.82,Default,,0,0,0,,那么在极坐标下运算会方便很多\nDialogue: 0,0:08:17.82,0:08:20.38,Default,,0,0,0,,因为对于两个复数\nDialogue: 0,0:08:20.40,0:08:26.54,Default,,0,0,0,,两复数积之模 就是它们各自的模的乘积\nDialogue: 0,0:08:28.85,0:08:33.88,Default,,0,0,0,,它们的积的辐角 就是两个辐角的和\nDialogue: 0,0:08:35.80,0:08:40.54,Default,,0,0,0,,这就是复数域上的运算所需的数学知识\nDialogue: 0,0:08:40.54,0:08:42.38,Default,,0,0,0,,我们来想一想具体的实现\nDialogue: 0,0:08:43.72,0:08:47.39,Default,,0,0,0,,我们就像之前运算有理数那样做\nDialogue: 0,0:08:49.84,0:08:53.47,Default,,0,0,0,,来到底层 假设有一些构造函数和选择函数\nDialogue: 0,0:08:53.76,0:08:54.52,Default,,0,0,0,,它们应该是什么样子呢\nDialogue: 0,0:08:55.33,0:08:58.16,Default,,0,0,0,,假设我们制造了一些表示数据对象的“云彩”\nDialogue: 0,0:08:58.54,0:09:00.78,Default,,0,0,0,,也就是用某种形式表示的复数\nDialogue: 0,0:09:01.79,0:09:04.67,Default,,0,0,0,,我们能从这个复数中得到它的实部\nDialogue: 0,0:09:05.52,0:09:09.64,Default,,0,0,0,,可以获得 虚部、模、或者辐角\nDialogue: 0,0:09:12.15,0:09:14.01,Default,,0,0,0,,然后我们需要一种方法来构造复数\nDialogue: 0,0:09:14.03,0:09:15.64,Default,,0,0,0,,不仅要有选择函数 还要有构造函数\nDialogue: 0,0:09:16.80,0:09:19.52,Default,,0,0,0,,那么假设我们有一个叫做make-rectangular的过程\nDialogue: 0,0:09:19.53,0:09:24.27,Default,,0,0,0,,这个过程的功能是接受一个实部\nDialogue: 0,0:09:24.51,0:09:29.36,Default,,0,0,0,,和一个虚部 然后把这两个部分组合成一个复数\nDialogue: 0,0:09:31.92,0:09:35.01,Default,,0,0,0,,同样我们也可以构造一个make-polar过程\nDialogue: 0,0:09:35.01,0:09:37.85,Default,,0,0,0,,它接受一个模和一个辐角\nDialogue: 0,0:09:40.83,0:09:43.90,Default,,0,0,0,,然后用这两个值 组成一个复数\nDialogue: 0,0:09:44.68,0:09:45.46,Default,,0,0,0,,那么这个系统\nDialogue: 0,0:09:45.46,0:09:47.77,Default,,0,0,0,,里面会有两个构造函数和四个选择函数\nDialogue: 0,0:09:48.91,0:09:55.15,Default,,0,0,0,,现在 就像之前课程中那样 我们基于这个抽象的数据结构\nDialogue: 0,0:09:55.15,0:09:59.22,Default,,0,0,0,,继续实现复数的各种运算\nDialogue: 0,0:09:59.22,0:10:02.30,Default,,0,0,0,,而这些Lisp代码\nDialogue: 0,0:10:03.23,0:10:07.47,Default,,0,0,0,,是从我之前写的算术公式“翻译”而来的\nDialogue: 0,0:10:08.06,0:10:09.98,Default,,0,0,0,,如果我想把两个复数相加\nDialogue: 0,0:10:11.76,0:10:15.56,Default,,0,0,0,,我就要用一个实部和一个虚部构造一个复数\nDialogue: 0,0:10:16.72,0:10:19.02,Default,,0,0,0,,这个新的复数的实部是\nDialogue: 0,0:10:19.40,0:10:21.80,Default,,0,0,0,,两个复数的实部的和\nDialogue: 0,0:10:23.31,0:10:25.37,Default,,0,0,0,,它的虚数部分是\nDialogue: 0,0:10:25.40,0:10:27.52,Default,,0,0,0,,两个复数的虚部的和\nDialogue: 0,0:10:30.31,0:10:32.09,Default,,0,0,0,,我把它们放到一起 构造出一个复数\nDialogue: 0,0:10:32.16,0:10:34.44,Default,,0,0,0,,这就是实现复数加法的方法\nDialogue: 0,0:10:35.78,0:10:38.49,Default,,0,0,0,,减法实际上是一样的\nDialogue: 0,0:10:39.65,0:10:42.97,Default,,0,0,0,,只需要把各个部分相加变成把它们相减\nDialogue: 0,0:10:45.14,0:10:47.07,Default,,0,0,0,,要把两个复数相乘\nDialogue: 0,0:10:47.74,0:10:49.02,Default,,0,0,0,,要用另外一个式子\nDialogue: 0,0:10:49.27,0:10:53.84,Default,,0,0,0,,我会用一个模和一个辐角来构造一个复数\nDialogue: 0,0:10:55.35,0:10:56.44,Default,,0,0,0,,z1*z2的模\nDialogue: 0,0:10:56.65,0:11:00.97,Default,,0,0,0,,就是z1的模乘以z2的模\nDialogue: 0,0:11:03.71,0:11:05.93,Default,,0,0,0,,而z1*z2的辐角则是\nDialogue: 0,0:11:06.16,0:11:08.51,Default,,0,0,0,,z1的辐角加上z2的辐角\nDialogue: 0,0:11:09.62,0:11:10.96,Default,,0,0,0,,那么这就是乘法的实现\nDialogue: 0,0:11:11.23,0:11:12.25,Default,,0,0,0,,然后是除法\nDialogue: 0,0:11:14.27,0:11:15.90,Default,,0,0,0,,除法和乘法几乎是一样的\nDialogue: 0,0:11:17.37,0:11:19.58,Default,,0,0,0,,我只要把两个模相除 把辐角相减就可以了\nDialogue: 0,0:11:28.36,0:11:30.46,Default,,0,0,0,,现在我已经实现了各种运算\nDialogue: 0,0:11:31.87,0:11:33.64,Default,,0,0,0,,然后我们做什么\nDialogue: 0,0:11:33.64,0:11:34.52,Default,,0,0,0,,我们把George叫来\nDialogue: 0,0:11:36.06,0:11:38.79,Default,,0,0,0,,我们完成了“使用”的部分 现在应该考虑“表示”了\nDialogue: 0,0:11:38.80,0:11:40.94,Default,,0,0,0,,我们叫来George然后对他说\nDialogue: 0,0:11:40.97,0:11:43.61,Default,,0,0,0,,“为我们设计一个一套复数的表示方法”\nDialogue: 0,0:11:45.25,0:11:47.44,Default,,0,0,0,,很好\nDialogue: 0,0:11:47.77,0:11:52.66,Default,,0,0,0,,George可能会说 我们把一个复数\nDialogue: 0,0:11:52.66,0:11:57.15,Default,,0,0,0,,实现为 一个由实部和虚部组成的序对\nDialogue: 0,0:11:57.20,0:12:02.62,Default,,0,0,0,,那么如果我想用某个实部和虚部来构造复数\nDialogue: 0,0:12:03.36,0:12:05.55,Default,,0,0,0,,我只需要把它们cons起来即可 这样可以--\nDialogue: 0,0:12:06.03,0:12:08.11,Default,,0,0,0,,这就是George表示复数的方法\nDialogue: 0,0:12:09.78,0:12:12.42,Default,,0,0,0,,那么如果我想获得它的实部 我只需要\nDialogue: 0,0:12:12.42,0:12:14.12,Default,,0,0,0,,提取出序对的car部分 -- 它的首部分\nDialogue: 0,0:12:14.35,0:12:16.67,Default,,0,0,0,,如果我想要得到虚部 我就提取出它的cdr部分\nDialogue: 0,0:12:19.64,0:12:21.77,Default,,0,0,0,,那对于模和辐角 又该如何取得呢？\nDialogue: 0,0:12:22.22,0:12:25.75,Default,,0,0,0,,如果我想取得某个复数的模\nDialogue: 0,0:12:25.75,0:12:32.30,Default,,0,0,0,,我需要计算该复数car与cdr的平方和的算术平方根\nDialogue: 0,0:12:33.79,0:12:39.26,Default,,0,0,0,,如果我想得到辐角 我就计算它的cdr与car比值的反正切\nDialogue: 0,0:12:39.53,0:12:42.86,Default,,0,0,0,,这个Lisp过程用于计算反正切\nDialogue: 0,0:12:44.97,0:12:48.59,Default,,0,0,0,,要是有人给我一个模和辐角\nDialogue: 0,0:12:48.94,0:12:50.56,Default,,0,0,0,,并说：“给我构造一个复数”\nDialogue: 0,0:12:50.89,0:12:56.24,Default,,0,0,0,,用它们计算出实部 r*cos(a) 和虚部 r*sin(a)\nDialogue: 0,0:12:57.77,0:12:59.05,Default,,0,0,0,,连接成一个序对就行了\nDialogue: 0,0:13:01.46,0:13:02.26,Default,,0,0,0,,完成了\nDialogue: 0,0:13:02.26,0:13:04.75,Default,,0,0,0,,实际上我做的事情 在概念上讲\nDialogue: 0,0:13:06.89,0:13:09.37,Default,,0,0,0,,和我们之前提过的有理数的表示\nDialogue: 0,0:13:10.60,0:13:12.44,Default,,0,0,0,,是完全没有区别的\nDialogue: 0,0:13:12.75,0:13:13.91,Default,,0,0,0,,它们的思想相同\nDialogue: 0,0:13:13.91,0:13:16.28,Default,,0,0,0,,实现具体过程 选择一种表示方法\nDialogue: 0,0:13:18.07,0:13:18.65,Default,,0,0,0,,没有什么不同\nDialogue: 0,0:13:20.07,0:13:21.56,Default,,0,0,0,,现在我们来关心一下Martha\nDialogue: 0,0:13:23.21,0:13:24.52,Default,,0,0,0,,嗯 Martha的想法不太一样\nDialogue: 0,0:13:26.67,0:13:28.57,Default,,0,0,0,,她不想把复数表示成\nDialogue: 0,0:13:28.59,0:13:30.90,Default,,0,0,0,,由实部和虚部组成的序对\nDialogue: 0,0:13:30.90,0:13:34.17,Default,,0,0,0,,她比较喜欢把它们表示成\nDialogue: 0,0:13:34.17,0:13:37.69,Default,,0,0,0,,由模和辐角组成的序对\nDialogue: 0,0:13:39.55,0:13:42.13,Default,,0,0,0,,那么如果我们没有让George而是让Martha\nDialogue: 0,0:13:42.13,0:13:43.74,Default,,0,0,0,,来设计复数的表示方法 我们就会得到这样的东西\nDialogue: 0,0:13:44.57,0:13:47.16,Default,,0,0,0,,有一个make-polar过程\nDialogue: 0,0:13:47.16,0:13:50.22,Default,,0,0,0,,当然了 有了一个模和一个辐角之后\nDialogue: 0,0:13:50.22,0:13:53.07,Default,,0,0,0,,我们只要把它们组合成一个序对就行了\nDialogue: 0,0:13:55.43,0:13:57.68,Default,,0,0,0,,如果你想取得复数的模 那很简单\nDialogue: 0,0:13:58.24,0:13:59.37,Default,,0,0,0,,你只需要取序对的car部分即可\nDialogue: 0,0:13:59.78,0:14:02.67,Default,,0,0,0,,当然 想取得复数的辐角 那也很简单\nDialogue: 0,0:14:02.67,0:14:03.63,Default,,0,0,0,,只需取cdr部分即可\nDialogue: 0,0:14:04.81,0:14:07.02,Default,,0,0,0,,但是如果你想要获得实部和虚部\nDialogue: 0,0:14:07.42,0:14:08.49,Default,,0,0,0,,那就得费点力气\nDialogue: 0,0:14:08.88,0:14:14.58,Default,,0,0,0,,想得到实部 你就得计算r*cos(a)\nDialogue: 0,0:14:14.58,0:14:19.99,Default,,0,0,0,,换句话讲 用序对的car部分去乘以\nDialogue: 0,0:14:19.99,0:14:20.95,Default,,0,0,0,,cdr部分的余弦值\nDialogue: 0,0:14:20.95,0:14:26.23,Default,,0,0,0,,然后你就算出了r*cos(a)\nDialogue: 0,0:14:26.54,0:14:27.48,Default,,0,0,0,,这就是这个复数的实部\nDialogue: 0,0:14:28.33,0:14:31.40,Default,,0,0,0,,要是想算出它的虚部 用r乘以sin(a)就可以了\nDialogue: 0,0:14:32.66,0:14:37.93,Default,,0,0,0,,现在如果我给你一个实部和虚部 然后说\nDialogue: 0,0:14:37.93,0:14:42.03,Default,,0,0,0,,用它们给我构造一个复数\nDialogue: 0,0:14:42.03,0:14:44.17,Default,,0,0,0,,那就要先算出\nDialogue: 0,0:14:44.17,0:14:45.54,Default,,0,0,0,,模和辐角是多少\nDialogue: 0,0:14:45.54,0:14:47.85,Default,,0,0,0,,模是实部和虚部的平方和的算术平方根\nDialogue: 0,0:14:48.09,0:14:49.23,Default,,0,0,0,,辐角是这个反正切\nDialogue: 0,0:14:49.23,0:14:50.22,Default,,0,0,0,,我用这两个数构造一个序对\nDialogue: 0,0:14:52.09,0:14:54.17,Default,,0,0,0,,以上就是Martha的想法\nDialogue: 0,0:14:56.69,0:14:57.37,Default,,0,0,0,,那么哪种比较好呢？\nDialogue: 0,0:14:59.68,0:15:03.15,Default,,0,0,0,,如果你需要做很多加法 那么George的比较好\nDialogue: 0,0:15:03.16,0:15:05.61,Default,,0,0,0,,因为你总是要用到复数的实部和虚部\nDialogue: 0,0:15:05.85,0:15:08.40,Default,,0,0,0,,如果你大多数时间都是在做乘法\nDialogue: 0,0:15:09.48,0:15:11.14,Default,,0,0,0,,那可能Martha的办法就要好一些\nDialogue: 0,0:15:11.14,0:15:14.84,Default,,0,0,0,,又或者 -- 这就是问题所在了 -- 你决定不了\nDialogue: 0,0:15:16.59,0:15:22.32,Default,,0,0,0,,或者出于某些个人原因 你想让它们同时存在\nDialogue: 0,0:15:23.48,0:15:26.76,Default,,0,0,0,,也可能你是真的无法决定你更喜欢哪种表示法\nDialogue: 0,0:15:28.56,0:15:32.32,Default,,0,0,0,,回到这个话题 我们真正想要的是这样一个系统\nDialogue: 0,0:15:32.65,0:15:36.17,Default,,0,0,0,,这里面 既有George 他实现了\nDialogue: 0,0:15:36.83,0:15:39.64,Default,,0,0,0,,复数的直角坐标表示\nDialogue: 0,0:15:41.47,0:15:44.25,Default,,0,0,0,,又有Martha 她实现了复数的极坐标表示\nDialogue: 0,0:15:46.12,0:15:49.69,Default,,0,0,0,,然后我们有各种运算\nDialogue: 0,0:15:50.28,0:15:56.89,Default,,0,0,0,,用来对复数进行加减乘除\nDialogue: 0,0:15:57.56,0:15:58.76,Default,,0,0,0,,那么这些运算\nDialogue: 0,0:15:59.34,0:16:02.79,Default,,0,0,0,,不应该被系统中同时存在的两种\nDialogue: 0,0:16:02.79,0:16:03.98,Default,,0,0,0,,互不兼容的复数表示方法影响\nDialogue: 0,0:16:04.41,0:16:08.33,Default,,0,0,0,,或者说 我们不光有像这样的一个抽象屏障\nDialogue: 0,0:16:09.64,0:16:11.84,Default,,0,0,0,,它里面有real-part\nDialogue: 0,0:16:15.77,0:16:21.71,Default,,0,0,0,,还有 IMAG-PART、MAG 和 ANG 等几个过程\nDialogue: 0,0:16:23.83,0:16:25.36,Default,,0,0,0,,不光有一层抽象屏障\nDialogue: 0,0:16:25.39,0:16:28.38,Default,,0,0,0,,把实际的数据表示隐藏起来\nDialogue: 0,0:16:29.10,0:16:31.52,Default,,0,0,0,,还有一层垂直的屏障\nDialogue: 0,0:16:32.19,0:16:35.02,Default,,0,0,0,,容许不同的表示方法彼此共存\nDialogue: 0,0:16:35.87,0:16:37.40,Default,,0,0,0,,而不互相干预\nDialogue: 0,0:16:38.57,0:16:41.07,Default,,0,0,0,,我们的想法是把这些东西\nDialogue: 0,0:16:41.90,0:16:44.12,Default,,0,0,0,,REAL-PART、IMAG-PART、MAG、ANG 这些过程\nDialogue: 0,0:16:44.12,0:16:46.49,Default,,0,0,0,,设计成通用运算符\nDialogue: 0,0:16:47.31,0:16:49.45,Default,,0,0,0,,如果你调用real-part过程 它就会判断\nDialogue: 0,0:16:49.98,0:16:51.31,Default,,0,0,0,,要在哪一种表示方法中寻找它\nDialogue: 0,0:16:53.88,0:16:55.10,Default,,0,0,0,,那么我们怎么做到这一点呢\nDialogue: 0,0:16:56.84,0:16:59.23,Default,,0,0,0,,实际上有一个很容易想到的办法\nDialogue: 0,0:16:59.84,0:17:01.68,Default,,0,0,0,,如果你习惯了思考复数的模式\nDialogue: 0,0:17:02.52,0:17:04.44,Default,,0,0,0,,如果你已经习惯了复合数据的思想\nDialogue: 0,0:17:06.33,0:17:10.99,Default,,0,0,0,,假设你只要观察一个复数\nDialogue: 0,0:17:12.17,0:17:13.95,Default,,0,0,0,,就能看出它是被George还是Martha构造出来的\nDialogue: 0,0:17:15.79,0:17:18.90,Default,,0,0,0,,换句话说 在你眼前漂浮的这些东西\nDialogue: 0,0:17:18.90,0:17:20.91,Default,,0,0,0,,不是普通的复数 对吗？\nDialogue: 0,0:17:20.91,0:17:22.94,Default,,0,0,0,,它们是被某个设计者“构想”出来的\nDialogue: 0,0:17:24.39,0:17:28.04,Default,,0,0,0,,当考察一个复数 我们会发现它“不仅仅”是个复数\nDialogue: 0,0:17:28.04,0:17:29.16,Default,,0,0,0,,它上面有一个标签\nDialogue: 0,0:17:29.19,0:17:30.75,Default,,0,0,0,,写着这个是由Martha制造的\nDialogue: 0,0:17:31.45,0:17:34.22,Default,,0,0,0,,或者这个是由George制造的\nDialogue: 0,0:17:34.48,0:17:35.39,Default,,0,0,0,,对吧？它们被签了名字\nDialogue: 0,0:17:36.86,0:17:40.15,Default,,0,0,0,,在这之后 无论何时我们看见一个复数\nDialogue: 0,0:17:40.15,0:17:45.48,Default,,0,0,0,,我们只要看它的标签  然后我们就能知道\nDialogue: 0,0:17:45.80,0:17:46.72,Default,,0,0,0,,应该怎么对它进行运算\nDialogue: 0,0:17:48.03,0:17:51.19,Default,,0,0,0,,或者说 我们想要的不只是普通的数据对象\nDialogue: 0,0:17:51.19,0:17:54.37,Default,,0,0,0,,我们引入一个概念：带类型的数据\nDialogue: 0,0:17:59.76,0:18:02.81,Default,,0,0,0,,带类型的数据就意味着 这里有一朵“云彩”\nDialogue: 0,0:18:03.94,0:18:08.93,Default,,0,0,0,,它里面有我们之前所说的那种\nDialogue: 0,0:18:08.93,0:18:09.90,Default,,0,0,0,,普通的数据对象\nDialogue: 0,0:18:13.18,0:18:16.54,Default,,0,0,0,,这是它的内容 就是实际的数据\nDialogue: 0,0:18:19.32,0:18:21.56,Default,,0,0,0,,它里面还有一个叫做类型的东西\nDialogue: 0,0:18:22.56,0:18:25.24,Default,,0,0,0,,被George或者Martha签了名\nDialogue: 0,0:18:25.99,0:18:28.27,Default,,0,0,0,,那么我们现在就要从无类型的数据进入带类型数据的领域\nDialogue: 0,0:18:31.95,0:18:32.71,Default,,0,0,0,,我们怎么构造它\nDialogue: 0,0:18:32.71,0:18:33.50,Default,,0,0,0,,那很简单\nDialogue: 0,0:18:33.84,0:18:35.32,Default,,0,0,0,,我们知道怎么构造“云彩”\nDialogue: 0,0:18:35.80,0:18:36.88,Default,,0,0,0,,我们用序对来组成它们\nDialogue: 0,0:18:37.92,0:18:41.82,Default,,0,0,0,,那么我们就有了一种方法来表示带类型的数据\nDialogue: 0,0:18:43.51,0:18:49.64,Default,,0,0,0,,这种方法叫做 把类型附加到内容上\nDialogue: 0,0:18:49.69,0:18:50.64,Default,,0,0,0,,用cons就可以做到\nDialogue: 0,0:18:51.64,0:18:54.11,Default,,0,0,0,,然后面对一个带类型的数据 我们就可以知道它的类型\nDialogue: 0,0:18:55.21,0:18:56.00,Default,,0,0,0,,也就是序对的car部分\nDialogue: 0,0:18:56.29,0:18:58.30,Default,,0,0,0,,我们也可以知道它的具体内容 就是它的cdr部分\nDialogue: 0,0:18:59.96,0:19:04.28,Default,,0,0,0,,我们用这种方法使用带类型的数据\nDialogue: 0,0:19:05.29,0:19:07.26,Default,,0,0,0,,面对一段类型数据就能知道它是什么类型\nDialogue: 0,0:19:07.52,0:19:09.26,Default,,0,0,0,,那么我们现在有了几种判断类型的谓词\nDialogue: 0,0:19:10.51,0:19:13.73,Default,,0,0,0,,举例来讲 想要知道一个复数\nDialogue: 0,0:19:13.73,0:19:16.86,Default,,0,0,0,,是不是George构造的 是不是直角坐标表示的 我们只需要看\nDialogue: 0,0:19:16.86,0:19:21.85,Default,,0,0,0,,它的“类型”是不是rectangular这个符号\nDialogue: 0,0:19:23.68,0:19:25.05,Default,,0,0,0,,对吧？检查 rectangular 符号\nDialogue: 0,0:19:27.20,0:19:30.33,Default,,0,0,0,,同理 想要知道一个复数是不是Martha构造的\nDialogue: 0,0:19:30.33,0:19:33.42,Default,,0,0,0,,我们就看它的“类型”是不是polar这个符号\nDialogue: 0,0:19:36.46,0:19:39.21,Default,,0,0,0,,那么这就是一种识别数字的类型的方法\nDialogue: 0,0:19:40.75,0:19:42.81,Default,,0,0,0,,现在来想想 怎么用这种方法来构建系统\nDialogue: 0,0:19:43.87,0:19:46.73,Default,,0,0,0,,我们假设George和Martha分别在做各自的工作\nDialogue: 0,0:19:47.36,0:19:52.64,Default,,0,0,0,,每一个人都设计了他们的复数表示程序包\nDialogue: 0,0:19:52.64,0:19:58.52,Default,,0,0,0,,他们怎么让自己的东西成为系统的一部分\nDialogue: 0,0:19:58.73,0:20:00.14,Default,,0,0,0,,和对方友好共存呢\nDialogue: 0,0:20:00.14,0:20:02.11,Default,,0,0,0,,那其实非常简单\nDialogue: 0,0:20:02.72,0:20:04.51,Default,,0,0,0,,回忆一下 George做了这个程序包\nDialogue: 0,0:20:05.97,0:20:08.48,Default,,0,0,0,,这就是George的程序包 或者说它的一部分\nDialogue: 0,0:20:08.98,0:20:11.15,Default,,0,0,0,,然后红色下划线标出的部分是他需要做的修改\nDialogue: 0,0:20:12.09,0:20:16.43,Default,,0,0,0,,之前 当George用x和y构建了一个复数的时候\nDialogue: 0,0:20:17.52,0:20:19.85,Default,,0,0,0,,他只是把它们组合成一个序对\nDialogue: 0,0:20:20.93,0:20:23.39,Default,,0,0,0,,现在唯一不同的地方是 他给它们打了标签\nDialogue: 0,0:20:24.09,0:20:28.08,Default,,0,0,0,,他把类型 -- 也就是 rectangular符号 -- 附加到这个序对上面\nDialogue: 0,0:20:30.60,0:20:33.26,Default,,0,0,0,,剩下的事情都和之前一样 除了一点\nDialogue: 0,0:20:33.92,0:20:38.06,Default,,0,0,0,,就是George和Martha的程序都有叫做real-part和imaginary-part的过程\nDialogue: 0,0:20:38.70,0:20:42.96,Default,,0,0,0,,为了这些过程存在于在同一个Lisp环境中\nDialogue: 0,0:20:44.22,0:20:45.92,Default,,0,0,0,,George就要修改他的过程名字\nDialogue: 0,0:20:45.92,0:20:49.14,Default,,0,0,0,,那么我们说 这是George的real-part过程\nDialogue: 0,0:20:49.14,0:20:51.16,Default,,0,0,0,,叫做real-part-rectangular过程\nDialogue: 0,0:20:51.48,0:20:54.06,Default,,0,0,0,,还有 imag-part-rectangular过程\nDialogue: 0,0:20:55.42,0:20:57.24,Default,,0,0,0,,那么这里是George的程序包剩下的部分\nDialogue: 0,0:20:59.13,0:21:02.06,Default,,0,0,0,,他已经有了magnitude和angle过程 只要把它们改名\nDialogue: 0,0:21:02.06,0:21:04.16,Default,,0,0,0,,叫magnitude-rectangular和angle-rectangular就好了\nDialogue: 0,0:21:06.08,0:21:07.96,Default,,0,0,0,,Martha要做的事情基本相同\nDialogue: 0,0:21:09.86,0:21:16.22,Default,,0,0,0,,在这之前 当她用模和辐角构造复数的时候\nDialogue: 0,0:21:18.14,0:21:19.27,Default,,0,0,0,,她只是把这两个东西cons起来\nDialogue: 0,0:21:19.27,0:21:20.86,Default,,0,0,0,,现在她额外附加类型 polar\nDialogue: 0,0:21:23.95,0:21:25.61,Default,,0,0,0,,然后修改过程的名字\nDialogue: 0,0:21:25.66,0:21:29.85,Default,,0,0,0,,来避免保证她的real-part过程和George的产生冲突\nDialogue: 0,0:21:30.71,0:21:32.99,Default,,0,0,0,,分别改为real-part-polar和imaginary-part-polar\nDialogue: 0,0:21:34.54,0:21:38.06,Default,,0,0,0,,magnitude-polar和angle-polar这四个过程\nDialogue: 0,0:21:45.00,0:21:46.13,Default,,0,0,0,,现在我们的系统\nDialogue: 0,0:21:46.13,0:21:47.92,Default,,0,0,0,,在它里面既有George又有Martha\nDialogue: 0,0:21:49.16,0:21:51.68,Default,,0,0,0,,然后现在我们需要一个经理来对类型进行判断\nDialogue: 0,0:21:52.83,0:21:56.48,Default,,0,0,0,,那么在George和Martha给我们提供了类型数据之后\nDialogue: 0,0:21:57.05,0:21:59.40,Default,,0,0,0,,这个系统现在怎么工作呢？\nDialogue: 0,0:22:00.53,0:22:04.30,Default,,0,0,0,,我们手里有的 是一堆通用选择函数\nDialogue: 0,0:22:05.26,0:22:10.63,Default,,0,0,0,,用于复数的通用选择函数比如 real-part、imag-part、magnitude和angle等\nDialogue: 0,0:22:14.14,0:22:15.40,Default,,0,0,0,,让我们更进一步观察它们\nDialogue: 0,0:22:17.93,0:22:19.00,Default,,0,0,0,,real-part过程应该做什么\nDialogue: 0,0:22:19.31,0:22:22.76,Default,,0,0,0,,如果我想得到一个复数的实部\nDialogue: 0,0:22:24.07,0:22:24.91,Default,,0,0,0,,那么我先要观察它\nDialogue: 0,0:22:25.80,0:22:26.69,Default,,0,0,0,,我观察它的类型\nDialogue: 0,0:22:26.69,0:22:28.12,Default,,0,0,0,,考虑它是用直角坐标表示的吗\nDialogue: 0,0:22:31.02,0:22:35.36,Default,,0,0,0,,如果是的话 我就对这个复数的\"内容\"部分\nDialogue: 0,0:22:36.06,0:22:37.92,Default,,0,0,0,,调用George的real-part过程\nDialogue: 0,0:22:41.07,0:22:42.94,Default,,0,0,0,,这是一个带有类型的数字\nDialogue: 0,0:22:43.72,0:22:47.66,Default,,0,0,0,,我用contents过程剥掉类型 并且对它应用George的过程\nDialogue: 0,0:22:50.70,0:22:52.86,Default,,0,0,0,,那如果是一个用极坐标表示的复数呢？\nDialogue: 0,0:22:53.95,0:22:54.97,Default,,0,0,0,,如果我想要得到它的实部\nDialogue: 0,0:22:55.45,0:22:58.78,Default,,0,0,0,,我就把Martha的real-part过程应用在这个数的内容上\nDialogue: 0,0:22:59.85,0:23:01.15,Default,,0,0,0,,这就是real-part工作的方式\nDialogue: 0,0:23:02.26,0:23:05.66,Default,,0,0,0,,还有类似的imag-part过程 几乎是一样的\nDialogue: 0,0:23:06.51,0:23:09.60,Default,,0,0,0,,它先观察这个数字 它是直角坐标表示的\nDialogue: 0,0:23:09.60,0:23:11.13,Default,,0,0,0,,就调用George的imaginary-part过程\nDialogue: 0,0:23:11.13,0:23:12.83,Default,,0,0,0,,是极坐标表示的 就用Martha的过程\nDialogue: 0,0:23:13.38,0:23:17.40,Default,,0,0,0,,同理也可以构造出magnitude和angle两个过程\nDialogue: 0,0:23:19.71,0:23:21.02,Default,,0,0,0,,我们的系统是这个样子\nDialogue: 0,0:23:23.00,0:23:24.26,Default,,0,0,0,,它里面有三个部分\nDialogue: 0,0:23:24.26,0:23:26.59,Default,,0,0,0,,有George、Martha和一个经理\nDialogue: 0,0:23:26.76,0:23:28.97,Default,,0,0,0,,这就是实现通用操作符的方法\nDialogue: 0,0:23:28.97,0:23:32.92,Default,,0,0,0,,为了把它说清楚 我们举一个简单的实例\nDialogue: 0,0:23:33.50,0:23:35.12,Default,,0,0,0,,但是准确描述了它工作的方式\nDialogue: 0,0:23:36.54,0:23:43.98,Default,,0,0,0,,假设你现在 面对一个实部是1\nDialogue: 0,0:23:44.52,0:23:46.09,Default,,0,0,0,,虚部是2的复数\nDialogue: 0,0:23:46.09,0:23:48.44,Default,,0,0,0,,也就是1+2i\nDialogue: 0,0:23:50.31,0:23:52.64,Default,,0,0,0,,现在在这里\nDialogue: 0,0:23:55.28,0:23:57.53,Default,,0,0,0,,在操作发生的上层\nDialogue: 0,0:23:57.63,0:24:08.27,Default,,0,0,0,,复数被表示成一个由1和2组成的序对加上类型信息\nDialogue: 0,0:24:10.48,0:24:11.39,Default,,0,0,0,,（1和2）是内容\nDialogue: 0,0:24:11.87,0:24:17.96,Default,,0,0,0,,整个的数据就是在那之上加上一个rectangular符号\nDialogue: 0,0:24:18.14,0:24:21.53,Default,,0,0,0,,这就是复数在这个系统里存在的形式\nDialogue: 0,0:24:22.33,0:24:24.92,Default,,0,0,0,,你要调取real-part的时候\nDialogue: 0,0:24:25.84,0:24:28.89,Default,,0,0,0,,经理会检查这个数然后说 这是George构造的数字\nDialogue: 0,0:24:30.27,0:24:31.53,Default,,0,0,0,,他会先把类型拿掉\nDialogue: 0,0:24:33.34,0:24:36.91,Default,,0,0,0,,然后把 (1,2) 这个序对传递给George\nDialogue: 0,0:24:38.00,0:24:42.27,Default,,0,0,0,,这是George的系统可以直接处理的数据\nDialogue: 0,0:24:44.36,0:24:45.92,Default,,0,0,0,,那么它被拆了出来\nDialogue: 0,0:24:46.52,0:24:49.76,Default,,0,0,0,,之后 如果你让George构造一个复数\nDialogue: 0,0:24:51.24,0:24:54.56,Default,,0,0,0,,George就会把它构造成序对\nDialogue: 0,0:24:55.07,0:24:58.24,Default,,0,0,0,,在数据被传递到上层之前\nDialogue: 0,0:24:59.42,0:25:01.13,Default,,0,0,0,,经理会再给它加上rectangular类型\nDialogue: 0,0:25:03.92,0:25:04.65,Default,,0,0,0,,看这个过程\nDialogue: 0,0:25:04.65,0:25:05.85,Default,,0,0,0,,这个系统不会发生混乱\nDialogue: 0,0:25:05.85,0:25:10.84,Default,,0,0,0,,就算在Martha的世界里 序对(1 2)的含义完全不同\nDialogue: 0,0:25:13.50,0:25:15.75,Default,,0,0,0,,也并没有什么影响\nDialogue: 0,0:25:15.75,0:25:18.44,Default,,0,0,0,,在Martha的世界里这个序对代表了\nDialogue: 0,0:25:18.44,0:25:20.78,Default,,0,0,0,,一个模为1 辐角为2的复数\nDialogue: 0,0:25:21.19,0:25:22.19,Default,,0,0,0,,但是这并不会造成混乱\nDialogue: 0,0:25:22.22,0:25:27.25,Default,,0,0,0,,因为每当有一个这样的序对经由经理之手\nDialogue: 0,0:25:27.25,0:25:29.61,Default,,0,0,0,,被交给主系统的时候 它都会被附加上polar的类型标志\nDialogue: 0,0:25:31.21,0:25:33.67,Default,,0,0,0,,而这个就会被贴上rectangular类型的标签\nDialogue: 0,0:25:36.93,0:25:37.90,Default,,0,0,0,,好 我们休息一下\nDialogue: 0,0:25:40.77,0:25:55.55,Default,,0,0,0,,[音乐]\nDialogue: 0,0:25:55.69,0:25:57.77,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:25:57.77,0:25:59.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:26:05.21,0:26:11.95,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:26:12.84,0:26:16.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}通用运算符\nDialogue: 0,0:26:20.21,0:26:24.15,Default,,0,0,0,,我们刚刚提出了一种实现通用运算符的策略\nDialogue: 0,0:26:24.15,0:26:31.40,Default,,0,0,0,,这种策略有一个名字 叫做“基于类型的分派”\nDialogue: 0,0:26:34.31,0:26:39.36,Default,,0,0,0,,它的想法就是你要把你的系统分成很多小块\nDialogue: 0,0:26:39.36,0:26:42.67,Default,,0,0,0,,里面有George和Martha在设计表示方法\nDialogue: 0,0:26:43.37,0:26:44.38,Default,,0,0,0,,还有一个经理\nDialogue: 0,0:26:46.12,0:26:48.06,Default,,0,0,0,,负责去看数据上的类型是什么\nDialogue: 0,0:26:48.51,0:26:50.59,Default,,0,0,0,,然后分派给正确的人去处理\nDialogue: 0,0:26:51.99,0:26:56.01,Default,,0,0,0,,这种组织系统的方法有什么缺点呢？\nDialogue: 0,0:26:58.15,0:27:00.40,Default,,0,0,0,,首先 有个小小的烦人的问题\nDialogue: 0,0:27:00.40,0:27:03.05,Default,,0,0,0,,George和Martha需要修改他们的过程的名字\nDialogue: 0,0:27:04.00,0:27:05.95,Default,,0,0,0,,George一开始写了一个real-part过程\nDialogue: 0,0:27:05.98,0:27:08.28,Default,,0,0,0,,现在他必须把它的名字改成real-part-rectangular\nDialogue: 0,0:27:08.30,0:27:10.83,Default,,0,0,0,,才能让它不与Martha的real-part过程相互冲突\nDialogue: 0,0:27:10.84,0:27:12.76,Default,,0,0,0,,而Martha的过程现在改叫real-part-polar\nDialogue: 0,0:27:13.64,0:27:16.68,Default,,0,0,0,,这是为了不和经理的那个叫做real-part的过程发生冲突\nDialogue: 0,0:27:17.31,0:27:18.94,Default,,0,0,0,,这个问题确实很恼人\nDialogue: 0,0:27:19.46,0:27:21.13,Default,,0,0,0,,但是我现在暂时不讨论这个问题\nDialogue: 0,0:27:21.27,0:27:22.35,Default,,0,0,0,,我们稍后将会看到\nDialogue: 0,0:27:23.26,0:27:26.12,Default,,0,0,0,,在讨论到Lisp名称与环境的结构的时候\nDialogue: 0,0:27:26.12,0:27:30.39,Default,,0,0,0,,我们会有方法把这些所谓的命名空间分开来封装\nDialogue: 0,0:27:30.39,0:27:31.56,Default,,0,0,0,,然后它们就不会互相影响了\nDialogue: 0,0:27:32.50,0:27:34.01,Default,,0,0,0,,现在我们暂时不去考虑这个问题\nDialogue: 0,0:27:35.72,0:27:38.19,Default,,0,0,0,,我现在想关注的问题是\nDialogue: 0,0:27:38.36,0:27:43.24,Default,,0,0,0,,你把一个新人招纳进系统之中会发生什么\nDialogue: 0,0:27:44.51,0:27:45.32,Default,,0,0,0,,会发生什么？\nDialogue: 0,0:27:45.32,0:27:46.81,Default,,0,0,0,,George和Martha并不关心\nDialogue: 0,0:27:47.42,0:27:50.73,Default,,0,0,0,,George在他的直角坐标世界里\nDialogue: 0,0:27:52.20,0:27:53.84,Default,,0,0,0,,坐拥着他的过程和数据类型\nDialogue: 0,0:27:54.09,0:27:55.74,Default,,0,0,0,,而Martha待在她的极坐标世界中\nDialogue: 0,0:27:55.93,0:27:57.02,Default,,0,0,0,,不问世事\nDialogue: 0,0:27:59.38,0:28:00.54,Default,,0,0,0,,但是经理呢？\nDialogue: 0,0:28:00.62,0:28:02.84,Default,,0,0,0,,经理需要做什么？\nDialogue: 0,0:28:03.18,0:28:06.20,Default,,0,0,0,,现在经理带着他的运算来了\nDialogue: 0,0:28:07.36,0:28:09.04,Default,,0,0,0,,有直角坐标的判断\nDialogue: 0,0:28:09.04,0:28:10.14,Default,,0,0,0,,和极坐标的判断过程\nDialogue: 0,0:28:10.14,0:28:14.91,Default,,0,0,0,,如果Harry带着某种新型的复数表示方法 进入这个系统\nDialogue: 0,0:28:17.21,0:28:19.96,Default,,0,0,0,,同时带来了一个新的类型--Harry型复数\nDialogue: 0,0:28:20.27,0:28:23.28,Default,,0,0,0,,经理就需要修改他所有的过程\nDialogue: 0,0:28:25.24,0:28:26.94,Default,,0,0,0,,所以这个系统的不灵活之处\nDialogue: 0,0:28:26.96,0:28:32.41,Default,,0,0,0,,也就是需要大量工作才能适应变化的地方 就在这个经理身上\nDialogue: 0,0:28:34.89,0:28:35.99,Default,,0,0,0,,那是非常恼人的事情\nDialogue: 0,0:28:35.99,0:28:37.21,Default,,0,0,0,,更恼人的是\nDialogue: 0,0:28:39.05,0:28:41.21,Default,,0,0,0,,你意识到这个经理实际上什么也不做\nDialogue: 0,0:28:42.59,0:28:44.67,Default,,0,0,0,,这个经理只负责“传递公文”而已\nDialogue: 0,0:28:45.84,0:28:51.13,Default,,0,0,0,,我们再来看看这些程序 它们在做什么\nDialogue: 0,0:28:51.76,0:28:52.72,Default,,0,0,0,,real-part过程在做什么\nDialogue: 0,0:28:52.88,0:28:56.17,Default,,0,0,0,,这个过程说 哦 这个复数是\nDialogue: 0,0:28:56.17,0:28:57.00,Default,,0,0,0,,George会处理的那一种吗\nDialogue: 0,0:28:57.00,0:28:58.27,Default,,0,0,0,,如果是的话 好 把它交给George处理\nDialogue: 0,0:28:59.41,0:29:01.76,Default,,0,0,0,,它是Martha能操作的那一种吗\nDialogue: 0,0:29:01.82,0:29:04.06,Default,,0,0,0,,是的话 把它交给Martha处理\nDialogue: 0,0:29:05.04,0:29:08.72,Default,,0,0,0,,这个系统真正恼人之处 也就是这个系统的瓶颈\nDialogue: 0,0:29:08.72,0:29:11.66,Default,,0,0,0,,它降低灵活性 阻碍变化\nDialogue: 0,0:29:12.09,0:29:14.36,Default,,0,0,0,,完全是一种的官僚主义\nDialogue: 0,0:29:15.00,0:29:17.02,Default,,0,0,0,,而不是任何做实事的人\nDialogue: 0,0:29:19.70,0:29:21.80,Default,,0,0,0,,很可惜这种情况经常发生\nDialogue: 0,0:29:23.18,0:29:24.41,Default,,0,0,0,,实际上发生的事情是\nDialogue: 0,0:29:24.48,0:29:26.97,Default,,0,0,0,,在系统中 有一张抽象的表格\nDialogue: 0,0:29:28.10,0:29:30.08,Default,,0,0,0,,实际发生的事情是 有这样一张表格\nDialogue: 0,0:29:30.84,0:29:33.64,Default,,0,0,0,,其中有各种类型\nDialogue: 0,0:29:34.40,0:29:38.96,Default,,0,0,0,,有polar和rectangular\nDialogue: 0,0:29:41.55,0:29:43.02,Default,,0,0,0,,可能Harry也在这里\nDialogue: 0,0:29:44.38,0:29:46.56,Default,,0,0,0,,然后这里是各种运算符\nDialogue: 0,0:29:48.05,0:29:58.24,Default,,0,0,0,,各种运算符 比如real-part和imag-part\nDialogue: 0,0:30:00.01,0:30:04.22,Default,,0,0,0,,还有magnitude、angle这些运算符\nDialogue: 0,0:30:05.83,0:30:18.97,Default,,0,0,0,,单元格中对应的是相应过程\nDialogue: 0,0:30:19.28,0:30:21.99,Default,,0,0,0,,那么填在这里 负责polar类型的real-part过程的是\nDialogue: 0,0:30:21.99,0:30:27.56,Default,,0,0,0,,Martha的real-part-polar过程\nDialogue: 0,0:30:30.57,0:30:36.62,Default,,0,0,0,,然后在这里是George的real-part-rectangular过程\nDialogue: 0,0:30:37.74,0:30:43.07,Default,,0,0,0,,然后这里是Martha的magnitude-polar过程\nDialogue: 0,0:30:44.46,0:30:49.76,Default,,0,0,0,,然后是George的magnitude-rectangular过程 等等等等\nDialogue: 0,0:30:49.76,0:30:51.24,Default,,0,0,0,,剩下的单元格也像这样填好\nDialogue: 0,0:30:52.39,0:30:54.26,Default,,0,0,0,,这就是实际上发生的事情\nDialogue: 0,0:30:57.63,0:31:01.74,Default,,0,0,0,,从某种意义上讲 经理做的事情就是\nDialogue: 0,0:31:02.11,0:31:04.11,Default,,0,0,0,,去扮演这张表格\nDialogue: 0,0:31:06.86,0:31:08.70,Default,,0,0,0,,那我们怎么去修补这个系统呢\nDialogue: 0,0:31:11.74,0:31:13.77,Default,,0,0,0,,怎么去消灭这种官僚主义？\nDialogue: 0,0:31:13.77,0:31:15.44,Default,,0,0,0,,你要做的就是让这个经理走人\nDialogue: 0,0:31:16.01,0:31:19.55,Default,,0,0,0,,我们用一台计算机来代替他\nDialogue: 0,0:31:20.17,0:31:21.76,Default,,0,0,0,,我们要让自动操作抹掉他存在的意义\nDialogue: 0,0:31:23.32,0:31:26.57,Default,,0,0,0,,也就是说 我们不用这个经理去查阅这个表格\nDialogue: 0,0:31:27.45,0:31:29.32,Default,,0,0,0,,而是让我们的系统直接去查阅它\nDialogue: 0,0:31:31.02,0:31:32.11,Default,,0,0,0,,这是什么意思呢？\nDialogue: 0,0:31:32.11,0:31:36.19,Default,,0,0,0,,我们来假设 还是用数据抽象的观点\nDialogue: 0,0:31:37.71,0:31:40.40,Default,,0,0,0,,我们有这样一种表格数据结构\nDialogue: 0,0:31:40.88,0:31:43.61,Default,,0,0,0,,而且我们还有把东西填进去和从中删除的方法\nDialogue: 0,0:31:44.35,0:31:49.04,Default,,0,0,0,,为了把话说清楚 我们假设现在有一个叫put的方法\nDialogue: 0,0:31:50.30,0:31:58.32,Default,,0,0,0,,本例中put方法接受两个参数 -- 我们称其为“关键字” -- key1和key2\nDialogue: 0,0:32:00.13,0:32:00.99,Default,,0,0,0,,还有接受一个值\nDialogue: 0,0:32:06.20,0:32:11.12,Default,,0,0,0,,put过程把value存放在表格key1和key2对应的格子里\nDialogue: 0,0:32:11.49,0:32:13.16,Default,,0,0,0,,然后我们假设有另一个叫get的过程\nDialogue: 0,0:32:15.23,0:32:18.72,Default,,0,0,0,,它是这样的一个东西 如果我说把表格里\nDialogue: 0,0:32:19.40,0:32:22.76,Default,,0,0,0,,存储在key1和key2对应的格子中的数据给我\nDialogue: 0,0:32:23.40,0:32:25.39,Default,,0,0,0,,它会把存储在那里的东西返回给我\nDialogue: 0,0:32:26.73,0:32:29.44,Default,,0,0,0,,我们先不要担心这个表格怎么实现\nDialogue: 0,0:32:30.00,0:32:32.52,Default,,0,0,0,,那又是另一个数据抽象了 是George需要考虑的问题\nDialogue: 0,0:32:33.06,0:32:34.36,Default,,0,0,0,,也许稍后我们还会看到\nDialogue: 0,0:32:34.70,0:32:36.97,Default,,0,0,0,,我们还会讨论怎么用Lisp建立这个表格\nDialogue: 0,0:32:40.71,0:32:45.50,Default,,0,0,0,,我们有了这个组织结构 George和Martha需要做什么呢？\nDialogue: 0,0:32:47.38,0:32:49.07,Default,,0,0,0,,当他们构建自己的系统的时候\nDialogue: 0,0:32:49.13,0:32:51.08,Default,,0,0,0,,都有责任在表格里\nDialogue: 0,0:32:51.44,0:32:53.82,Default,,0,0,0,,正确地添加上自己的那一列\nDialogue: 0,0:32:55.21,0:32:57.47,Default,,0,0,0,,比如说 对于George\nDialogue: 0,0:32:59.79,0:33:02.06,Default,,0,0,0,,当他定义过程的时候 他需要做的就是\nDialogue: 0,0:33:02.27,0:33:07.99,Default,,0,0,0,,把它们放进表格中的rectangular类型的那一列下面\nDialogue: 0,0:33:09.82,0:33:12.12,Default,,0,0,0,,然后操作的名字是real-part\nDialogue: 0,0:33:13.31,0:33:15.26,Default,,0,0,0,,放入他的real-part-rectangular过程\nDialogue: 0,0:33:16.25,0:33:17.78,Default,,0,0,0,,注意有什么被放到了表格里\nDialogue: 0,0:33:17.78,0:33:22.10,Default,,0,0,0,,这里的两个key是这两个符号：rectangular和real-part\nDialogue: 0,0:33:22.10,0:33:22.75,Default,,0,0,0,,这是引用\nDialogue: 0,0:33:24.40,0:33:26.75,Default,,0,0,0,,要被填到表里的东西\nDialogue: 0,0:33:26.84,0:33:29.21,Default,,0,0,0,,是他编写的real-part-rectangular过程\nDialogue: 0,0:33:31.85,0:33:34.30,Default,,0,0,0,,然后把这个获取虚部的过程也放进表里\nDialogue: 0,0:33:34.59,0:33:37.80,Default,,0,0,0,,分类到rectangular和imag-part两个关键字之下\nDialogue: 0,0:33:38.62,0:33:42.88,Default,,0,0,0,,获取模值的过程放到rectangular和magnitude下面\nDialogue: 0,0:33:43.61,0:33:45.20,Default,,0,0,0,,获取辐角的过程放到rectangular和angle下面\nDialogue: 0,0:33:47.04,0:33:50.84,Default,,0,0,0,,George作为系统的一部分 就要做以上这些事情\nDialogue: 0,0:33:54.42,0:33:58.86,Default,,0,0,0,,Martha用同样的方法填好表格中关于polar的这一列\nDialogue: 0,0:33:59.43,0:34:00.65,Default,,0,0,0,,在polar和real-part对应的这一栏\nDialogue: 0,0:34:01.69,0:34:03.58,Default,,0,0,0,,应该填的过程是real-part-polar是吧？\nDialogue: 0,0:34:04.34,0:34:07.29,Default,,0,0,0,,然后分别是imag-part、magnitude和angle过程\nDialogue: 0,0:34:08.91,0:34:11.40,Default,,0,0,0,,Martha想要加入系统当中就要做这些事情\nDialogue: 0,0:34:11.40,0:34:13.55,Default,,0,0,0,,每个设计了数据表示的人\nDialogue: 0,0:34:13.55,0:34:17.63,Default,,0,0,0,,都必须在表格里设置自己的一列\nDialogue: 0,0:34:17.76,0:34:19.90,Default,,0,0,0,,那么Harry带着他的绝妙的复数实现方法\nDialogue: 0,0:34:19.90,0:34:21.80,Default,,0,0,0,,过来的时候 他需要做什么呢\nDialogue: 0,0:34:21.80,0:34:23.96,Default,,0,0,0,,他先把过程写好\nDialogue: 0,0:34:24.04,0:34:26.52,Default,,0,0,0,,然后在表格里再建立一列\nDialogue: 0,0:34:28.55,0:34:30.04,Default,,0,0,0,,那么现在经理怎么样了呢\nDialogue: 0,0:34:31.33,0:34:34.61,Default,,0,0,0,,经理的存在被自动操作所取代\nDialogue: 0,0:34:34.61,0:34:37.11,Default,,0,0,0,,被一个叫做operate的过程代替\nDialogue: 0,0:34:37.11,0:34:39.55,Default,,0,0,0,,这是这个系统最关键的一个过程\nDialogue: 0,0:34:40.38,0:34:45.92,Default,,0,0,0,,(define operate\nDialogue: 0,0:34:51.06,0:34:56.09,Default,,0,0,0,,Operate过程接收你想要采取的运算\nDialogue: 0,0:34:57.75,0:34:58.88,Default,,0,0,0,,应该说是这个运算的名字\nDialogue: 0,0:34:59.20,0:35:03.28,Default,,0,0,0,,和被运算的对象\nDialogue: 0,0:35:04.21,0:35:09.76,Default,,0,0,0,,那么举例来说 对一个复数调用real-part operate过程会做什么呢\nDialogue: 0,0:35:09.95,0:35:11.90,Default,,0,0,0,,它要做的第一件事就是去查表\nDialogue: 0,0:35:12.64,0:35:13.87,Default,,0,0,0,,它查询这个表格\nDialogue: 0,0:35:14.80,0:35:22.56,Default,,0,0,0,,试图去找到存储在表格里的一个过程\nDialogue: 0,0:35:23.15,0:35:24.80,Default,,0,0,0,,所以它要对表格调用get过程\nDialogue: 0,0:35:25.50,0:35:33.92,Default,,0,0,0,,用对象的类型和运算的名称作为关键字进行检索\nDialogue: 0,0:35:38.92,0:35:40.14,Default,,0,0,0,,这样就可以知道在表格中\nDialogue: 0,0:35:40.38,0:35:42.72,Default,,0,0,0,,与数据的类型和要进行的运算相对应的是什么了\nDialogue: 0,0:35:42.89,0:35:44.35,Default,,0,0,0,,对应的这一格里填了什么东西\nDialogue: 0,0:35:44.44,0:35:45.93,Default,,0,0,0,,我们假设get过程已经被实现好了\nDialogue: 0,0:35:45.93,0:35:47.72,Default,,0,0,0,,所以如果在那一格什么也没有\nDialogue: 0,0:35:48.11,0:35:51.79,Default,,0,0,0,,它就会返回一个空表\nDialogue: 0,0:35:52.67,0:35:55.39,Default,,0,0,0,,如果那里确实有什么东西\nDialogue: 0,0:35:56.62,0:36:00.43,Default,,0,0,0,,如果存储有这样的一个过程\nDialogue: 0,0:36:03.15,0:36:07.12,Default,,0,0,0,,那么就会把在表格里找到的这个过程\nDialogue: 0,0:36:09.79,0:36:15.00,Default,,0,0,0,,应用到对象的具体内容上去\nDialogue: 0,0:36:18.25,0:36:20.40,Default,,0,0,0,,如果那里没有东西的话\nDialogue: 0,0:36:20.67,0:36:22.51,Default,,0,0,0,,它就会 -- 我们可以决定\nDialogue: 0,0:36:22.81,0:36:27.12,Default,,0,0,0,,本例中 我们让它输出一个错误消息：“未定义的运算符”\nDialogue: 0,0:36:28.48,0:36:30.24,Default,,0,0,0,,没有支持这种类型的运算符\nDialogue: 0,0:36:33.07,0:36:34.72,Default,,0,0,0,,或者其它合适的错误信息\nDialogue: 0,0:36:39.07,0:36:39.48,Default,,0,0,0,,对吧？\nDialogue: 0,0:36:39.72,0:36:41.04,Default,,0,0,0,,这个东西替代了经理\nDialogue: 0,0:36:41.89,0:36:42.91,Default,,0,0,0,,我们怎么去使用它呢\nDialogue: 0,0:36:43.96,0:36:49.80,Default,,0,0,0,,我们的想法是用operate过程来定义通用选择函数\nDialogue: 0,0:36:50.04,0:36:56.75,Default,,0,0,0,,我们可以说一个对象的real-part\nDialogue: 0,0:36:57.14,0:37:05.66,Default,,0,0,0,,是这个对象被operate应用了叫做real-part的运算后得到的结果\nDialogue: 0,0:37:08.07,0:37:12.22,Default,,0,0,0,,那么类似地 imag-part是operate对obj应用imag-part运算\nDialogue: 0,0:37:12.22,0:37:13.98,Default,,0,0,0,,magnitude和angle同理\nDialogue: 0,0:37:15.36,0:37:17.43,Default,,0,0,0,,这就是我们的实现方法\nDialogue: 0,0:37:17.43,0:37:20.48,Default,,0,0,0,,由它们加上类型再加上operate过程组成\nDialogue: 0,0:37:21.33,0:37:24.00,Default,,0,0,0,,这个表格现在就有效地完成了之前经理的工作\nDialogue: 0,0:37:24.06,0:37:27.69,Default,,0,0,0,,我们来梳理一下在这个过程中发生的事情\nDialogue: 0,0:37:27.90,0:37:33.00,Default,,0,0,0,,假设我有一个由Martha构造的复数\nDialogue: 0,0:37:33.53,0:37:38.80,Default,,0,0,0,,它的模值是1 辐角是2\nDialogue: 0,0:37:39.10,0:37:40.22,Default,,0,0,0,,它是由Martha构造的\nDialogue: 0,0:37:40.22,0:37:45.45,Default,,0,0,0,,所以它被贴上了polar的标签\nDialogue: 0,0:37:47.24,0:37:48.00,Default,,0,0,0,,我们叫它z\nDialogue: 0,0:37:48.00,0:37:48.91,Default,,0,0,0,,假设这就是z\nDialogue: 0,0:37:51.77,0:37:54.46,Default,,0,0,0,,然后假设在这种实现方法下\nDialogue: 0,0:37:54.80,0:37:57.92,Default,,0,0,0,,有人想要取z的实部\nDialogue: 0,0:38:04.87,0:38:07.96,Default,,0,0,0,,由于real-part现在是用operate来定义的\nDialogue: 0,0:38:09.16,0:38:10.57,Default,,0,0,0,,这就等同于说\nDialogue: 0,0:38:12.09,0:38:24.81,Default,,0,0,0,,调用 (operate 'real-part z)\nDialogue: 0,0:38:27.06,0:38:28.09,Default,,0,0,0,,然后operate过程\nDialogue: 0,0:38:28.09,0:38:29.24,Default,,0,0,0,,就会去查询表格\nDialogue: 0,0:38:31.04,0:38:34.36,Default,,0,0,0,,然后试图去寻找在表格里存放的\nDialogue: 0,0:38:39.00,0:38:46.22,Default,,0,0,0,,查询表格中与对象的类型相对应的一列\nDialogue: 0,0:38:46.72,0:38:48.22,Default,,0,0,0,,那么z的类型是polar\nDialogue: 0,0:38:48.79,0:38:51.37,Default,,0,0,0,,所以它就要说 我用polar作为关键字查表\nDialogue: 0,0:38:52.99,0:38:58.57,Default,,0,0,0,,然后运算的名称是real-part\nDialogue: 0,0:39:05.96,0:39:13.63,Default,,0,0,0,,它查询对应的过程 然后应用到z的内容上去\nDialogue: 0,0:39:14.83,0:39:17.13,Default,,0,0,0,,如果所有东西都安排妥当的话\nDialogue: 0,0:39:17.74,0:39:21.70,Default,,0,0,0,,如果它找到的过程就是Martha编写的过程\nDialogue: 0,0:39:21.70,0:39:22.95,Default,,0,0,0,,也就是real-part-polar\nDialogue: 0,0:39:31.05,0:39:35.13,Default,,0,0,0,,然后这就是z去掉类型之后的东西\nDialogue: 0,0:39:35.44,0:39:38.94,Default,,0,0,0,,是Martha最初设计的数据表示\nDialogue: 0,0:39:39.40,0:39:40.43,Default,,0,0,0,,也就是这里的(1 2)\nDialogue: 0,0:39:43.71,0:39:45.87,Default,,0,0,0,,所以说在整个系统中 operate过程\nDialogue: 0,0:39:46.46,0:39:48.89,Default,,0,0,0,,和之前的经理做的事情没什么区别\nDialogue: 0,0:39:49.45,0:39:52.59,Default,,0,0,0,,它通过查询表格找到正确的东西  然后剥离类型\nDialogue: 0,0:39:53.58,0:39:57.52,Default,,0,0,0,,然后把它传递给能够处理它的人\nDialogue: 0,0:39:58.88,0:40:05.48,Default,,0,0,0,,你会发现 这是另一种 在大多数情况下\nDialogue: 0,0:40:06.22,0:40:08.04,Default,,0,0,0,,更灵活地实现通用运算符的方法\nDialogue: 0,0:40:08.08,0:40:15.69,Default,,0,0,0,,我们把它叫做“数据导向编程”\nDialogue: 0,0:40:20.35,0:40:21.96,Default,,0,0,0,,其理念是\nDialogue: 0,0:40:23.42,0:40:25.55,Default,,0,0,0,,在某种意义上 这些数据对象本身\nDialogue: 0,0:40:26.04,0:40:28.35,Default,,0,0,0,,这些充斥在系统中的复数\nDialogue: 0,0:40:28.73,0:40:33.16,Default,,0,0,0,,它们自身就携带着 关于应该怎么去操作它们的信息\nDialogue: 0,0:40:35.74,0:40:36.78,Default,,0,0,0,,有什么疑问吗？\nDialogue: 0,0:40:41.00,0:40:41.24,Default,,0,0,0,,请说\nDialogue: 0,0:40:41.24,0:40:43.39,Default,,0,0,0,,学生：你在那个数据对象里存储的是什么呢\nDialogue: 0,0:40:43.39,0:40:47.10,Default,,0,0,0,,这里面有这个数据本身 还有它的类型\nDialogue: 0,0:40:47.10,0:40:49.60,Default,,0,0,0,,还有该与该类型对应的运算\nDialogue: 0,0:40:49.69,0:40:53.08,Default,,0,0,0,,或者说那些运算是存储在哪里呢？\nDialogue: 0,0:40:53.60,0:40:54.17,Default,,0,0,0,,教授：好 让我--\nDialogue: 0,0:40:54.98,0:40:56.50,Default,,0,0,0,,恩 这是一个好问题\nDialogue: 0,0:40:56.50,0:41:00.46,Default,,0,0,0,,通过它暗示了实现我们目标的 其它可行方法\nDialogue: 0,0:41:00.75,0:41:02.48,Default,,0,0,0,,当然可能的方法有很多\nDialogue: 0,0:41:04.20,0:41:06.14,Default,,0,0,0,,在这个特定的实现当中\nDialogue: 0,0:41:06.24,0:41:09.72,Default,,0,0,0,,在这个数据对象里放着\nDialogue: 0,0:41:10.44,0:41:13.45,Default,,0,0,0,,就是数据本身 本例中是序对(1, 2)\nDialogue: 0,0:41:14.98,0:41:16.55,Default,,0,0,0,,和一个符号\nDialogue: 0,0:41:16.55,0:41:19.07,Default,,0,0,0,,就是这个符号 单词P-O-L-A-R\nDialogue: 0,0:41:20.60,0:41:22.33,Default,,0,0,0,,这些就是这个数据对象里面的东西\nDialogue: 0,0:41:24.24,0:41:26.69,Default,,0,0,0,,那么这些运算又是存放在哪里的呢？\nDialogue: 0,0:41:26.69,0:41:29.00,Default,,0,0,0,,那些运算在表格里\nDialogue: 0,0:41:29.85,0:41:31.07,Default,,0,0,0,,在这个表格里\nDialogue: 0,0:41:32.30,0:41:36.46,Default,,0,0,0,,所有行和列的名字都是符号\nDialogue: 0,0:41:38.23,0:41:40.08,Default,,0,0,0,,所以当我往里面存什么东西的时候\nDialogue: 0,0:41:40.09,0:41:47.02,Default,,0,0,0,,可以以符号polar或符号magnitude作为关键字\nDialogue: 0,0:41:48.24,0:41:51.31,Default,,0,0,0,,我这样写 可能让你们感到困惑了\nDialogue: 0,0:41:51.31,0:41:52.70,Default,,0,0,0,,因为在这里面放的并不是\nDialogue: 0,0:41:53.16,0:41:54.57,Default,,0,0,0,,当我写下mag-polar的时候\nDialogue: 0,0:41:57.04,0:41:59.23,Default,,0,0,0,,我指的是那个叫mag-polar的过程\nDialogue: 0,0:41:59.85,0:42:01.85,Default,,0,0,0,,可能 我本来应该在这里写上\nDialogue: 0,0:42:02.58,0:42:04.20,Default,,0,0,0,,但是这里空间太小了\nDialogue: 0,0:42:04.20,0:42:05.07,Default,,0,0,0,,我写不下\nDialogue: 0,0:42:05.58,0:42:08.92,Default,,0,0,0,,应该写成lambda(z)\nDialogue: 0,0:42:10.60,0:42:12.75,Default,,0,0,0,,然后调用Martha实现的过程\nDialogue: 0,0:42:14.71,0:42:15.72,Default,,0,0,0,,你也可以从这里看出\nDialogue: 0,0:42:15.74,0:42:17.44,Default,,0,0,0,,我已经暗示了另一种方法\nDialogue: 0,0:42:17.71,0:42:19.82,Default,,0,0,0,,来解决名字冲突的问题\nDialogue: 0,0:42:20.04,0:42:23.15,Default,,0,0,0,,那就是George和Martha根本不用给他们的过程起名字\nDialogue: 0,0:42:23.15,0:42:25.37,Default,,0,0,0,,可以直接把由lambda定义的\nDialogue: 0,0:42:25.39,0:42:28.12,Default,,0,0,0,,由lambda定义的匿名函数放进表格里\nDialogue: 0,0:42:28.66,0:42:31.76,Default,,0,0,0,,你的问题还引出了另一种可能性\nDialogue: 0,0:42:32.35,0:42:34.06,Default,,0,0,0,,也就是\nDialogue: 0,0:42:34.83,0:42:37.92,Default,,0,0,0,,可能我在这个数据对象里存储的\nDialogue: 0,0:42:37.95,0:42:39.48,Default,,0,0,0,,不是符号POLAR\nDialogue: 0,0:42:39.93,0:42:42.35,Default,,0,0,0,,也许是这些运算本身\nDialogue: 0,0:42:43.90,0:42:45.63,Default,,0,0,0,,这是组织系统的另一种方法\nDialogue: 0,0:42:45.66,0:42:46.60,Default,,0,0,0,,叫做“消息传递”\nDialogue: 0,0:42:48.65,0:42:49.92,Default,,0,0,0,,它们都殊途同归\nDialogue: 0,0:42:54.64,0:42:58.04,Default,,0,0,0,,学生：所以说如果Martha和George\nDialogue: 0,0:42:58.04,0:43:01.23,Default,,0,0,0,,用了相同的过程名字也没什么问题\nDialogue: 0,0:43:01.23,0:43:02.56,Default,,0,0,0,,[听不清]\nDialogue: 0,0:43:02.56,0:43:04.68,Default,,0,0,0,,教授：对 你说得很对\nDialogue: 0,0:43:04.80,0:43:07.85,Default,,0,0,0,,看 他们甚至根本不需要给他们的过程命名\nDialogue: 0,0:43:08.04,0:43:09.36,Default,,0,0,0,,George和Martha可以 --\nDialogue: 0,0:43:09.50,0:43:10.62,Default,,0,0,0,,George可以这么来做\nDialogue: 0,0:43:10.83,0:43:15.28,Default,,0,0,0,,与其在rectangular和real-part对应的格子里放\nDialogue: 0,0:43:16.22,0:43:17.98,Default,,0,0,0,,存放real-part-rectangular这个过程\nDialogue: 0,0:43:18.03,0:43:21.15,Default,,0,0,0,,George可以在rectangular和real-part对应的格子里放\nDialogue: 0,0:43:21.24,0:43:23.69,Default,,0,0,0,,放一个lambda(z) 然后什么什么\nDialogue: 0,0:43:24.54,0:43:26.84,Default,,0,0,0,,整个系统会以完全相同的方式工作\nDialogue: 0,0:43:27.33,0:43:29.24,Default,,0,0,0,,学生：我的问题是 就算Martha在\nDialogue: 0,0:43:29.84,0:43:33.60,Default,,0,0,0,,Martha在key1和key2对应的格子里放了real-part过程\nDialogue: 0,0:43:33.95,0:43:37.64,Default,,0,0,0,,George也在key1和key2下放了一个real-part过程\nDialogue: 0,0:43:37.96,0:43:39.60,Default,,0,0,0,,只要两个过程的定义不一样\nDialogue: 0,0:43:39.80,0:43:41.26,Default,,0,0,0,,它们就不会发生任何冲突 对吗？\nDialogue: 0,0:43:41.29,0:43:43.80,Default,,0,0,0,,教授：对的 这完全没有问题\nDialogue: 0,0:43:44.97,0:43:47.13,Default,,0,0,0,,除非你说的是George和Martha在同一个终端上工作\nDialogue: 0,0:43:47.13,0:43:49.20,Default,,0,0,0,,并且他们两个人起的所有名字的含义全部相同\nDialogue: 0,0:43:49.82,0:43:51.23,Default,,0,0,0,,那么同样的real-part就会造成困扰\nDialogue: 0,0:43:51.24,0:43:52.80,Default,,0,0,0,,但是就算是这种情况也有办法解决\nDialogue: 0,0:43:52.80,0:43:54.80,Default,,0,0,0,,从原则上讲你说的完全正确\nDialogue: 0,0:43:54.98,0:43:56.29,Default,,0,0,0,,如果它们的名字不互相冲突的话\nDialogue: 0,0:43:56.29,0:43:58.19,Default,,0,0,0,,被填到表里的是对象本身 而不是它们的名字\nDialogue: 0,0:44:08.20,0:44:09.05,Default,,0,0,0,,好 我们休息一下\nDialogue: 0,0:44:12.91,0:44:20.48,Default,,0,0,0,,[音乐]\nDialogue: 0,0:44:20.96,0:44:23.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:44:23.45,0:44:25.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:44:57.42,0:45:05.07,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:45:05.47,0:45:09.24,Declare,,0,0,0,,{\\an2\\fad(500,500)}通用运算符\nDialogue: 0,0:45:12.88,0:45:16.88,Default,,0,0,0,,教授：好的 我们刚刚讲了一个数据导向编程的例子\nDialogue: 0,0:45:17.68,0:45:22.84,Default,,0,0,0,,我们将其用于实现一个复数域上的算术系统\nDialogue: 0,0:45:27.60,0:45:32.48,Default,,0,0,0,,我已经在里面实现了 +c -c 这些运算\nDialogue: 0,0:45:32.88,0:45:37.24,Default,,0,0,0,,*c \\c 还有其它的一些过程\nDialogue: 0,0:45:38.23,0:45:45.72,Default,,0,0,0,,这些过程存在于上层 -- 这是关键之处\nDialogue: 0,0:45:45.74,0:45:49.60,Default,,0,0,0,,它们存在于两种不同表示方式的上层\nDialogue: 0,0:45:50.34,0:45:55.44,Default,,0,0,0,,这是一个直角坐标程序包 这里一个极坐标程序包\nDialogue: 0,0:45:58.14,0:45:59.15,Default,,0,0,0,,可能还有其它的东西\nDialogue: 0,0:45:59.15,0:46:02.80,Default,,0,0,0,,关键理念就是 “其它的东西”可以很容易地添加上去\nDialogue: 0,0:46:04.67,0:46:08.35,Default,,0,0,0,,但是这并没有真正体现出这种方法学的威力\nDialogue: 0,0:46:08.90,0:46:10.15,Default,,0,0,0,,我们看看发生了什么\nDialogue: 0,0:46:10.15,0:46:12.33,Default,,0,0,0,,这个方法的威力 只有当你\nDialogue: 0,0:46:12.94,0:46:15.79,Default,,0,0,0,,当你把它嵌入于一些更复杂的系统中时才会显现\nDialogue: 0,0:46:16.17,0:46:17.74,Default,,0,0,0,,我现在要做的就是\nDialogue: 0,0:46:17.87,0:46:20.01,Default,,0,0,0,,把它嵌入一个更复杂的系统中\nDialogue: 0,0:46:20.25,0:46:25.28,Default,,0,0,0,,假设我们已经有了一个通用算术系统\nDialogue: 0,0:46:25.28,0:46:27.24,Default,,0,0,0,,所谓的“通用算术系统”\nDialogue: 0,0:46:27.24,0:46:28.54,Default,,0,0,0,,然后在系统的最顶层\nDialogue: 0,0:46:30.76,0:46:35.92,Default,,0,0,0,,用户可以命令它把两个东西相加 或者相减\nDialogue: 0,0:46:37.45,0:46:41.05,Default,,0,0,0,,或者让两数相乘、相除\nDialogue: 0,0:46:44.14,0:46:46.52,Default,,0,0,0,,然后在它们下面是一个抽象屏障\nDialogue: 0,0:46:47.93,0:46:49.15,Default,,0,0,0,,抽象屏障的下层\nDialogue: 0,0:46:49.50,0:46:52.48,Default,,0,0,0,,是一个复数域算术程序包\nDialogue: 0,0:46:53.02,0:46:54.96,Default,,0,0,0,,然后你可以让它把两个复数相加\nDialogue: 0,0:46:55.04,0:46:58.83,Default,,0,0,0,,或者你还可以把 有理数域算术程序包\nDialogue: 0,0:46:58.88,0:46:59.93,Default,,0,0,0,,给安装进来\nDialogue: 0,0:47:00.19,0:47:01.72,Default,,0,0,0,,可以放进去有理数\nDialogue: 0,0:47:04.76,0:47:06.22,Default,,0,0,0,,然后有理数程序包里面\nDialogue: 0,0:47:07.16,0:47:14.75,Default,,0,0,0,,有我们实现的 +rat、*rat等等的这些过程\nDialogue: 0,0:47:15.39,0:47:17.01,Default,,0,0,0,,或者你还可以加上通常的Lisp算术系统\nDialogue: 0,0:47:17.01,0:47:18.99,Default,,0,0,0,,你可以让它把3和4加起来\nDialogue: 0,0:47:19.42,0:47:20.94,Default,,0,0,0,,那么我们在这个系统里加入通常的算术系统\nDialogue: 0,0:47:28.28,0:47:34.67,Default,,0,0,0,,其中有Lisp自带的 + - * /\nDialogue: 0,0:47:36.67,0:47:39.12,Default,,0,0,0,,总而言之 我们可以想象这个复数系统\nDialogue: 0,0:47:39.44,0:47:44.44,Default,,0,0,0,,存在于一个更加复杂的通用运算系统里面\nDialogue: 0,0:47:47.73,0:47:48.73,Default,,0,0,0,,我们怎么才能做到呢\nDialogue: 0,0:47:49.05,0:47:52.32,Default,,0,0,0,,我们已经有了想法 只要再一次应用它就可以了\nDialogue: 0,0:47:52.78,0:47:54.72,Default,,0,0,0,,我们已经实现了一个有理数程序包\nDialogue: 0,0:47:54.72,0:47:56.89,Default,,0,0,0,,那么我们来看看应该怎么修改它\nDialogue: 0,0:48:01.48,0:48:03.40,Default,,0,0,0,,实际上 在这个层面 它根本就不需要修改\nDialogue: 0,0:48:03.73,0:48:05.88,Default,,0,0,0,,这完全就是我们上次写的那些代码\nDialogue: 0,0:48:07.18,0:48:08.97,Default,,0,0,0,,要把两个有理数相加\nDialogue: 0,0:48:09.85,0:48:10.91,Default,,0,0,0,,回忆一下 我们要用到这个公式\nDialogue: 0,0:48:11.14,0:48:13.37,Default,,0,0,0,,构造一个有理数 它的分子是\nDialogue: 0,0:48:13.98,0:48:17.56,Default,,0,0,0,,x的分子乘以y的分母\nDialogue: 0,0:48:17.93,0:48:21.52,Default,,0,0,0,,加上 x的分母乘以y的分子\nDialogue: 0,0:48:21.52,0:48:23.79,Default,,0,0,0,,而结果的分母是 x的分母乘y的分母\nDialogue: 0,0:48:25.76,0:48:29.07,Default,,0,0,0,,然后是-rat、*rat、/rat这些过程\nDialogue: 0,0:48:30.36,0:48:35.12,Default,,0,0,0,,这就是我们之前写的那个有理数程序包\nDialogue: 0,0:48:36.31,0:48:38.89,Default,,0,0,0,,我们忽略最大公约数的问题 先不去考虑那个\nDialogue: 0,0:48:39.08,0:48:42.59,Default,,0,0,0,,作为这个有理数包的实现人员\nDialogue: 0,0:48:42.80,0:48:45.10,Default,,0,0,0,,怎么把它安装到我们的通用运算系统中呢？\nDialogue: 0,0:48:45.57,0:48:46.22,Default,,0,0,0,,那很简单\nDialogue: 0,0:48:47.29,0:48:51.56,Default,,0,0,0,,我们要做的事只有一件和之前不同\nDialogue: 0,0:48:51.84,0:48:55.71,Default,,0,0,0,,在之前我们说构造一个有理数\nDialogue: 0,0:48:56.27,0:48:59.98,Default,,0,0,0,,就是构造一个由分子分母组成的序对\nDialogue: 0,0:49:00.96,0:49:03.20,Default,,0,0,0,,现在我们不光构造这个序对 还要给它贴上标签\nDialogue: 0,0:49:03.30,0:49:04.56,Default,,0,0,0,,给它加上rational类型\nDialogue: 0,0:49:06.36,0:49:08.09,Default,,0,0,0,,这就是唯一的不同之处\nDialogue: 0,0:49:08.56,0:49:10.09,Default,,0,0,0,,把它变成带类型的数据\nDialogue: 0,0:49:12.38,0:49:14.08,Default,,0,0,0,,现在 我们要把运算放进表格里\nDialogue: 0,0:49:14.36,0:49:18.20,Default,,0,0,0,,我们在rational符号和add运算对应的格子里\nDialogue: 0,0:49:18.92,0:49:20.25,Default,,0,0,0,,放进我们的+rat过程\nDialogue: 0,0:49:21.82,0:49:23.24,Default,,0,0,0,,再次强调 这是一个符号\nDialogue: 0,0:49:23.74,0:49:23.93,Default,,0,0,0,,看到了么？\nDialogue: 0,0:49:24.03,0:49:25.29,Default,,0,0,0,,这是引用 这也是引用\nDialogue: 0,0:49:25.31,0:49:28.01,Default,,0,0,0,,但是实际上放进表里的是+rat过程本身\nDialogue: 0,0:49:29.82,0:49:31.77,Default,,0,0,0,,然后怎么做减法\nDialogue: 0,0:49:31.79,0:49:36.81,Default,,0,0,0,,我们用-rat过程做减法\nDialogue: 0,0:49:38.27,0:49:40.24,Default,,0,0,0,,然后是乘法和除法\nDialogue: 0,0:49:41.09,0:49:43.64,Default,,0,0,0,,这些步骤精准地描述了 我们该怎么做\nDialogue: 0,0:49:44.14,0:49:46.97,Default,,0,0,0,,来兼容这个通用算术系统\nDialogue: 0,0:49:48.51,0:49:49.88,Default,,0,0,0,,那么整个系统怎么工作呢\nDialogue: 0,0:49:51.56,0:49:58.40,Default,,0,0,0,,我们想实现的是通用运算符\nDialogue: 0,0:49:59.34,0:50:02.80,Default,,0,0,0,,为了让add、sub、mul和div变成通用运算符\nDialogue: 0,0:50:03.99,0:50:17.36,Default,,0,0,0,,所以我们要把add过程定义为 (ADD X Y)就是\nDialogue: 0,0:50:18.62,0:50:22.12,Default,,0,0,0,,就是调用operate过程\nDialogue: 0,0:50:26.08,0:50:27.49,Default,,0,0,0,,我们把这个叫做operate-2\nDialogue: 0,0:50:27.49,0:50:30.78,Default,,0,0,0,,这是我们的操作过程 但是要接收两个参数\nDialogue: 0,0:50:31.60,0:50:35.84,Default,,0,0,0,,对它们应用add 把它们加起来\nDialogue: 0,0:50:37.60,0:50:39.76,Default,,0,0,0,,这是和operate类似的一个东西\nDialogue: 0,0:50:40.42,0:50:41.68,Default,,0,0,0,,我们再看看这个代码\nDialogue: 0,0:50:41.68,0:50:42.93,Default,,0,0,0,,它和operate很相似\nDialogue: 0,0:50:45.79,0:50:52.49,Default,,0,0,0,,为了将运算符运用在两个参数arg1和arg2上\nDialogue: 0,0:50:55.04,0:50:56.65,Default,,0,0,0,,首要任务是\nDialogue: 0,0:50:56.83,0:51:00.73,Default,,0,0,0,,检查这两个参数的类型是否相同\nDialogue: 0,0:51:01.90,0:51:02.96,Default,,0,0,0,,所以我们要问\nDialogue: 0,0:51:02.99,0:51:07.77,Default,,0,0,0,,第一个参数的类型和第二个的类型一样吗？\nDialogue: 0,0:51:10.35,0:51:13.36,Default,,0,0,0,,如果不一样\nDialogue: 0,0:51:13.58,0:51:15.63,Default,,0,0,0,,我们就停止运行 然后抛出错误\nDialogue: 0,0:51:15.67,0:51:16.67,Default,,0,0,0,,我们不知道怎么对它们进行运算\nDialogue: 0,0:51:19.14,0:51:20.49,Default,,0,0,0,,如果它们的类型确实是相同的\nDialogue: 0,0:51:20.51,0:51:22.08,Default,,0,0,0,,那就和之前一样了\nDialogue: 0,0:51:22.08,0:51:26.46,Default,,0,0,0,,我们会查询在参数的类型对应的\nDialogue: 0,0:51:26.76,0:51:29.61,Default,,0,0,0,,参数1和参数2是同样的类型 知道一个就可以\nDialogue: 0,0:51:30.42,0:51:32.59,Default,,0,0,0,,我们到表格里去查找对应的过程\nDialogue: 0,0:51:33.64,0:51:35.87,Default,,0,0,0,,如果找到这样一个过程\nDialogue: 0,0:51:37.53,0:51:41.74,Default,,0,0,0,,我们就将其应用在参数1和参数2的内容上\nDialogue: 0,0:51:43.03,0:51:44.76,Default,,0,0,0,,如果是其它情况 就报错\nDialogue: 0,0:51:44.76,0:51:45.72,Default,,0,0,0,,“未定义运算符”\nDialogue: 0,0:51:46.89,0:51:48.16,Default,,0,0,0,,这就是operate-2过程\nDialogue: 0,0:51:51.72,0:51:54.03,Default,,0,0,0,,这就是我们要做的全部事情\nDialogue: 0,0:51:55.16,0:51:57.45,Default,,0,0,0,,我们刚刚才写好了一个复数运算包\nDialogue: 0,0:51:57.64,0:52:01.00,Default,,0,0,0,,那么怎么把它放进这个通用系统里面呢？\nDialogue: 0,0:52:02.14,0:52:02.91,Default,,0,0,0,,方法几乎是一样的\nDialogue: 0,0:52:06.41,0:52:08.59,Default,,0,0,0,,我们构造一个叫做make-complex的过程\nDialogue: 0,0:52:09.95,0:52:12.81,Default,,0,0,0,,它把George和Martha给我们的东西\nDialogue: 0,0:52:13.64,0:52:15.00,Default,,0,0,0,,贴上complex的类型标志\nDialogue: 0,0:52:18.17,0:52:23.87,Default,,0,0,0,,然后我们说 要把复数相加 这个+complex过程\nDialogue: 0,0:52:25.84,0:52:28.78,Default,,0,0,0,,用我们的内部过程 +c\nDialogue: 0,0:52:30.78,0:52:32.24,Default,,0,0,0,,把结果加上类型\nDialogue: 0,0:52:32.24,0:52:33.42,Default,,0,0,0,,让它变成复数类型\nDialogue: 0,0:52:37.68,0:52:42.52,Default,,0,0,0,,那么我们的包里原来有+c和-c这两个过程\nDialogue: 0,0:52:42.68,0:52:44.75,Default,,0,0,0,,用来和George和Martha通信\nDialogue: 0,0:52:45.25,0:52:47.39,Default,,0,0,0,,然后为了与外部通信\nDialogue: 0,0:52:47.40,0:52:53.04,Default,,0,0,0,,我们还有+complex和-complex\nDialogue: 0,0:52:55.92,0:52:56.53,Default,,0,0,0,,等等\nDialogue: 0,0:52:56.53,0:52:59.98,Default,,0,0,0,,它们唯一的不同就在于：后者的返回的是带类型的值\nDialogue: 0,0:53:01.12,0:53:02.41,Default,,0,0,0,,它们可以在这里被查询\nDialogue: 0,0:53:02.85,0:53:05.02,Default,,0,0,0,,而这些是内部过程\nDialogue: 0,0:53:09.25,0:53:10.68,Default,,0,0,0,,我们再来看那个幻灯片\nDialogue: 0,0:53:10.68,0:53:13.04,Default,,0,0,0,,我们还有一件事要做\nDialogue: 0,0:53:13.74,0:53:15.61,Default,,0,0,0,,在定义了+complex之后\nDialogue: 0,0:53:15.68,0:53:20.52,Default,,0,0,0,,我们在complex类型和add符号对应的格子中\nDialogue: 0,0:53:21.31,0:53:22.75,Default,,0,0,0,,填上过程+complex\nDialogue: 0,0:53:23.20,0:53:26.75,Default,,0,0,0,,对于-complex也类似\nDialogue: 0,0:53:27.13,0:53:29.13,Default,,0,0,0,,*complex和/complex亦如此\nDialogue: 0,0:53:31.70,0:53:33.48,Default,,0,0,0,,那我们怎么安装寻常算术呢？\nDialogue: 0,0:53:35.25,0:53:36.12,Default,,0,0,0,,方法还是一样的\nDialogue: 0,0:53:38.16,0:53:41.36,Default,,0,0,0,,我们会写一个叫做make-number的过程\nDialogue: 0,0:53:44.34,0:53:48.11,Default,,0,0,0,,make-number接收一个数 然后给它加上类型\nDialogue: 0,0:53:48.14,0:53:49.29,Default,,0,0,0,,也就是符号number\nDialogue: 0,0:53:50.26,0:53:52.11,Default,,0,0,0,,我们构造一个过程叫做+number\nDialogue: 0,0:53:52.92,0:53:58.75,Default,,0,0,0,,用Lisp自带的加法把两个数加起来\nDialogue: 0,0:53:58.92,0:54:00.78,Default,,0,0,0,,因为我们现在讨论的是寻常算术\nDialogue: 0,0:54:01.31,0:54:03.10,Default,,0,0,0,,给它加上类型 让它变成number类型\nDialogue: 0,0:54:04.51,0:54:08.09,Default,,0,0,0,,然后我们把+number过程放到\nDialogue: 0,0:54:08.59,0:54:11.00,Default,,0,0,0,,表格里number和add对应的的格子中\nDialogue: 0,0:54:12.30,0:54:16.16,Default,,0,0,0,,再用相同的方法把减法 乘法 除法也放进去\nDialogue: 0,0:54:22.67,0:54:26.06,Default,,0,0,0,,我们举一个例子 就看得清楚一点\nDialogue: 0,0:54:26.06,0:54:28.75,Default,,0,0,0,,假设 比如说\nDialogue: 0,0:54:32.28,0:54:34.15,Default,,0,0,0,,我要执行这个运算\nDialogue: 0,0:54:34.15,0:54:38.22,Default,,0,0,0,,好 现在我要执行一个运算\nDialogue: 0,0:54:38.22,0:54:40.46,Default,,0,0,0,,比如说我把两个复数乘起来\nDialogue: 0,0:54:40.93,0:54:48.64,Default,,0,0,0,,把3+4i和2+6i乘起来\nDialogue: 0,0:54:50.17,0:54:52.60,Default,,0,0,0,,这就是我调用mul过程要传入的参数\nDialogue: 0,0:54:52.84,0:54:55.76,Default,,0,0,0,,这里就代表通用运算符mul\nDialogue: 0,0:54:57.17,0:54:57.98,Default,,0,0,0,,那么它怎么工作呢\nDialogue: 0,0:54:58.28,0:55:04.60,Default,,0,0,0,,我们讲3+4i 在整个系统里\nDialogue: 0,0:55:04.83,0:55:06.11,Default,,0,0,0,,处于这样的一个位置\nDialogue: 0,0:55:06.25,0:55:07.52,Default,,0,0,0,,假设它是George那种方法表示的\nDialogue: 0,0:55:08.28,0:55:14.97,Default,,0,0,0,,所以它的内部有一个3和一个4\nDialogue: 0,0:55:18.49,0:55:20.97,Default,,0,0,0,,这上面还贴着George的类型标志\nDialogue: 0,0:55:24.33,0:55:28.32,Default,,0,0,0,,是他构造的rectangular类型\nDialogue: 0,0:55:29.51,0:55:30.57,Default,,0,0,0,,又附加在那上面的\nDialogue: 0,0:55:31.23,0:55:35.79,Default,,0,0,0,,从更上一层的视角来看这一段数据\nDialogue: 0,0:55:36.19,0:55:36.78,Default,,0,0,0,,它又是一个\nDialogue: 0,0:55:37.93,0:55:39.96,Default,,0,0,0,,这整个又是一个带类型的数据\nDialogue: 0,0:55:40.60,0:55:41.80,Default,,0,0,0,,它的类型是complex\nDialogue: 0,0:55:44.82,0:55:47.31,Default,,0,0,0,,那么这就是这个对象\nDialogue: 0,0:55:48.64,0:55:50.24,Default,,0,0,0,,在最高层视角中的样子\nDialogue: 0,0:55:50.68,0:55:53.56,Default,,0,0,0,,那些通用运算符看到的对象 就是这样的\nDialogue: 0,0:55:55.56,0:55:58.72,Default,,0,0,0,,现在 mul过程会过来问\nDialogue: 0,0:55:58.84,0:56:00.40,Default,,0,0,0,,它的类型是什么？\nDialogue: 0,0:56:00.48,0:56:01.48,Default,,0,0,0,,它的类型是complex\nDialogue: 0,0:56:04.27,0:56:06.46,Default,,0,0,0,,然后运行到operate-2 然后说\nDialogue: 0,0:56:06.46,0:56:09.72,Default,,0,0,0,,啊 我想要把表格里的过程\nDialogue: 0,0:56:09.72,0:56:13.04,Default,,0,0,0,,也就是*complex这个过程\nDialogue: 0,0:56:15.08,0:56:17.76,Default,,0,0,0,,应用到 将其类型剥离之后的结果上去\nDialogue: 0,0:56:17.95,0:56:19.28,Default,,0,0,0,,所以它会把类型剥下来\nDialogue: 0,0:56:19.93,0:56:24.24,Default,,0,0,0,,把剩下的东西传递给复数的世界\nDialogue: 0,0:56:26.70,0:56:28.73,Default,,0,0,0,,复数的世界看了看它有的运算操作 然后说\nDialogue: 0,0:56:28.76,0:56:30.56,Default,,0,0,0,,“我得调用*c这个过程”\nDialogue: 0,0:56:31.28,0:56:32.14,Default,,0,0,0,,然后*c过程说\nDialogue: 0,0:56:32.22,0:56:37.20,Default,,0,0,0,,我想知道这个东西的模值是多少\nDialogue: 0,0:56:39.42,0:56:40.16,Default,,0,0,0,,然后它们会说 啊\nDialogue: 0,0:56:40.16,0:56:41.71,Default,,0,0,0,,它是直角坐标表示的 是George的东西\nDialogue: 0,0:56:41.87,0:56:44.41,Default,,0,0,0,,所以它们又剥掉了一个类型\nDialogue: 0,0:56:46.91,0:56:49.80,Default,,0,0,0,,然后把内容交给George 让他提取出它的模值\nDialogue: 0,0:56:52.16,0:56:53.13,Default,,0,0,0,,那么我们看到\nDialogue: 0,0:56:53.44,0:56:56.99,Default,,0,0,0,,这其中有一条由类型构成的链条\nDialogue: 0,0:56:59.32,0:57:01.50,Default,,0,0,0,,这个链条的长度就是你要\nDialogue: 0,0:57:01.53,0:57:03.13,Default,,0,0,0,,在这个表格里上升的层数\nDialogue: 0,0:57:05.09,0:57:05.96,Default,,0,0,0,,类型的作用则是\nDialogue: 0,0:57:05.96,0:57:10.84,Default,,0,0,0,,每当我们在表格中遇到一道垂直屏障时\nDialogue: 0,0:57:11.05,0:57:14.06,Default,,0,0,0,,你不知道该如何抉择时\nDialogue: 0,0:57:14.41,0:57:15.85,Default,,0,0,0,,类型就会给你指路\nDialogue: 0,0:57:17.44,0:57:18.83,Default,,0,0,0,,然后最底层的过程\nDialogue: 0,0:57:18.97,0:57:20.67,Default,,0,0,0,,它们构造数据结构 对数据进行筛选之后\nDialogue: 0,0:57:21.12,0:57:22.81,Default,,0,0,0,,再把类型贴回去\nDialogue: 0,0:57:25.35,0:57:30.75,Default,,0,0,0,,这就是整个系统的总体结构\nDialogue: 0,0:57:33.41,0:57:33.77,Default,,0,0,0,,好\nDialogue: 0,0:57:34.82,0:57:35.68,Default,,0,0,0,,明白了这个之后\nDialogue: 0,0:57:37.56,0:57:39.44,Default,,0,0,0,,我们再让这个系统变得更加复杂\nDialogue: 0,0:57:41.89,0:57:46.54,Default,,0,0,0,,我们这次不光要在系统里添加新的数域\nDialogue: 0,0:57:46.60,0:57:51.15,Default,,0,0,0,,我们也来讨论一下怎么把多项式也加进去\nDialogue: 0,0:57:51.51,0:57:52.97,Default,,0,0,0,,让它能做多项式算术\nDialogue: 0,0:57:53.36,0:58:03.71,Default,,0,0,0,,比如我们可以计算x^15+2x^7+5\nDialogue: 0,0:58:04.48,0:58:05.84,Default,,0,0,0,,像这样的多项式\nDialogue: 0,0:58:06.38,0:58:07.93,Default,,0,0,0,,如果有两个这样的东西\nDialogue: 0,0:58:07.93,0:58:09.48,Default,,0,0,0,,我们可以把它们相加或者相乘\nDialogue: 0,0:58:10.53,0:58:11.79,Default,,0,0,0,,先不管相除的问题\nDialogue: 0,0:58:12.14,0:58:14.67,Default,,0,0,0,,只考虑相加相乘和相减\nDialogue: 0,0:58:15.55,0:58:17.16,Default,,0,0,0,,我们需要做什么\nDialogue: 0,0:58:18.52,0:58:20.76,Default,,0,0,0,,我们先来想想怎么表示一个多项式\nDialogue: 0,0:58:21.83,0:58:23.55,Default,,0,0,0,,它也是一种带类型的数据\nDialogue: 0,0:58:24.73,0:58:27.55,Default,,0,0,0,,这个系统里的一个多项式\nDialogue: 0,0:58:28.54,0:58:31.68,Default,,0,0,0,,应该是带有polynomial类型的对象\nDialogue: 0,0:58:32.00,0:58:34.55,Default,,0,0,0,,接下来它可能要问这个多项式的变量是哪个\nDialogue: 0,0:58:34.55,0:58:37.69,Default,,0,0,0,,比如这是一个以x为变量的多项式\nDialogue: 0,0:58:38.96,0:58:41.39,Default,,0,0,0,,然后 多项式内还有各项的信息\nDialogue: 0,0:58:42.25,0:58:44.16,Default,,0,0,0,,有很多种方法来实现\nDialogue: 0,0:58:44.25,0:58:47.63,Default,,0,0,0,,我们采用的方法是构造一个“项表”\nDialogue: 0,0:58:51.52,0:58:52.24,Default,,0,0,0,,所谓的“项表”\nDialogue: 0,0:58:53.70,0:58:55.61,Default,,0,0,0,,本例中 我们用的是类似这样的东西\nDialogue: 0,0:58:56.36,0:58:59.68,Default,,0,0,0,,我们把它写成一系列 按次数排列的序对\nDialogue: 0,0:58:59.69,0:59:05.80,Default,,0,0,0,,那么这个项表就能表示这个多项式了\nDialogue: 0,0:59:09.42,0:59:10.68,Default,,0,0,0,,它的意义是\nDialogue: 0,0:59:11.48,0:59:19.71,Default,,0,0,0,,这个多项式第一项的次数是15 系数是1\nDialogue: 0,0:59:23.82,0:59:27.50,Default,,0,0,0,,然后下一项的次数是7 系数是2\nDialogue: 0,0:59:27.53,0:59:30.49,Default,,0,0,0,,再下一项是一个常数 它次数是0 系数是5\nDialogue: 0,0:59:31.45,0:59:34.16,Default,,0,0,0,,实际上有很多很多种方法\nDialogue: 0,0:59:34.25,0:59:35.96,Default,,0,0,0,,也有很多很多的取舍\nDialogue: 0,0:59:36.01,0:59:39.10,Default,,0,0,0,,在你认真思考如何实现代数操作程序包时\nDialogue: 0,0:59:39.44,0:59:41.73,Default,,0,0,0,,你该如何表示这些东西\nDialogue: 0,0:59:42.01,0:59:43.68,Default,,0,0,0,,但是我们这种是比较标准的一种\nDialogue: 0,0:59:44.18,0:59:45.55,Default,,0,0,0,,它适用于很多情况\nDialogue: 0,0:59:47.77,0:59:50.99,Default,,0,0,0,,好 那么我们怎么实现我们的多项式算术呢\nDialogue: 0,0:59:53.47,0:59:54.96,Default,,0,0,0,,现在开始着手做这个事情\nDialogue: 0,0:59:57.95,1:00:00.28,Default,,0,0,0,,构造一个多项式 首先要\nDialogue: 0,1:00:00.76,1:00:04.12,Default,,0,0,0,,首先我们得找一个办法来构造多项式\nDialogue: 0,1:00:05.69,1:00:10.28,Default,,0,0,0,,我们可以用一个变量 比如x和一个项表来构造它们\nDialogue: 0,1:00:11.24,1:00:14.09,Default,,0,0,0,,我们要用某种方法把它们包装起来\nDialogue: 0,1:00:14.30,1:00:19.40,Default,,0,0,0,,我们可以用cons把变量和项表组合起来\nDialogue: 0,1:00:19.82,1:00:21.74,Default,,0,0,0,,然后把这个序对加上polynomial的类型标志\nDialogue: 0,1:00:26.27,1:00:27.77,Default,,0,0,0,,那我们怎么处理多项式相加呢？\nDialogue: 0,1:00:29.28,1:00:31.85,Default,,0,0,0,,要相加两个多项式 p1和p2\nDialogue: 0,1:00:32.68,1:00:35.18,Default,,0,0,0,,为了简化问题 假设我们\nDialogue: 0,1:00:35.37,1:00:37.15,Default,,0,0,0,,我们只相加变量相同的两个式子\nDialogue: 0,1:00:37.38,1:00:39.28,Default,,0,0,0,,那么如果它们的变量相同\nDialogue: 0,1:00:39.69,1:00:42.57,Default,,0,0,0,,是否相同交由我们编写的选择函数判断\nDialogue: 0,1:00:42.96,1:00:44.38,Default,,0,0,0,,我们不必在意它的细节\nDialogue: 0,1:00:45.15,1:00:47.04,Default,,0,0,0,,如果两个多项式的变量相同\nDialogue: 0,1:00:48.03,1:00:48.81,Default,,0,0,0,,我们就继续运算\nDialogue: 0,1:00:48.81,1:00:51.26,Default,,0,0,0,,如果它们的变量不相同 我们返回一个错误\nDialogue: 0,1:00:52.35,1:00:54.01,Default,,0,0,0,,“两个多项式的变量不相同”\nDialogue: 0,1:00:55.48,1:00:57.37,Default,,0,0,0,,如果它们的变量确实是相同\nDialogue: 0,1:00:57.60,1:00:59.18,Default,,0,0,0,,我们就要构造一个新的多项式\nDialogue: 0,1:00:59.80,1:01:01.85,Default,,0,0,0,,它的变量即是原式的变量\nDialogue: 0,1:01:03.15,1:01:06.56,Default,,0,0,0,,它的项表则由过程+terms产生\nDialogue: 0,1:01:07.48,1:01:09.80,Default,,0,0,0,,+terms过程会把两个项表加起来\nDialogue: 0,1:01:10.17,1:01:12.01,Default,,0,0,0,,所以我们要把两个多项式的项表合起来\nDialogue: 0,1:01:13.50,1:01:14.51,Default,,0,0,0,,该过程即可返回一个项表\nDialogue: 0,1:01:15.00,1:01:20.01,Default,,0,0,0,,我们将变量和得到的项表构造成新的多项式\nDialogue: 0,1:01:20.68,1:01:21.79,Default,,0,0,0,,这就是+poly过程\nDialogue: 0,1:01:22.55,1:01:27.00,Default,,0,0,0,,然后我们要把这个过程放进表格中polynomial那一栏\nDialogue: 0,1:01:28.24,1:01:30.14,Default,,0,0,0,,用+poly实现add操作\nDialogue: 0,1:01:30.52,1:01:31.75,Default,,0,0,0,,当然实际上没做多少事情\nDialogue: 0,1:01:31.75,1:01:35.31,Default,,0,0,0,,我们只是把所有的工作压到+terms的头上\nDialogue: 0,1:01:35.79,1:01:37.02,Default,,0,0,0,,它会负责把项表相加起来\nDialogue: 0,1:01:37.74,1:01:39.16,Default,,0,0,0,,我们看看这个过程\nDialogue: 0,1:01:39.18,1:01:48.03,Default,,0,0,0,,这是+terms过程的大概结构\nDialogue: 0,1:01:48.90,1:01:51.74,Default,,0,0,0,,L1和L2是两个项表\nDialogue: 0,1:01:52.00,1:01:54.81,Default,,0,0,0,,所谓“项表”即是按每项次数排序的序对\nDialogue: 0,1:01:55.70,1:01:56.95,Default,,0,0,0,,这里有一个大的分情况分析\nDialogue: 0,1:01:59.86,1:02:04.14,Default,,0,0,0,,首先 我们要检查项表是否为空\nDialogue: 0,1:02:05.39,1:02:07.55,Default,,0,0,0,,我们对项表做递归下降处理\nDialogue: 0,1:02:08.16,1:02:11.74,Default,,0,0,0,,最终下降到 L1或L2为空\nDialogue: 0,1:02:12.27,1:02:14.35,Default,,0,0,0,,只要其中有一个为空\nDialogue: 0,1:02:14.52,1:02:15.85,Default,,0,0,0,,我们的答案就是剩下的另一个\nDialogue: 0,1:02:15.85,1:02:19.55,Default,,0,0,0,,就是说如果L1是空表 我们就返回L2\nDialogue: 0,1:02:19.63,1:02:21.71,Default,,0,0,0,,L2是空表的话就返回L1\nDialogue: 0,1:02:23.26,1:02:25.76,Default,,0,0,0,,除此之外还有三种情况\nDialogue: 0,1:02:27.22,1:02:27.98,Default,,0,0,0,,我们要做的是\nDialogue: 0,1:02:29.08,1:02:31.05,Default,,0,0,0,,取表中的第一项\nDialogue: 0,1:02:33.50,1:02:36.04,Default,,0,0,0,,记为t1和t2\nDialogue: 0,1:02:37.66,1:02:39.05,Default,,0,0,0,,我们来分析一下这三种情况\nDialogue: 0,1:02:39.60,1:02:45.68,Default,,0,0,0,,分别是t1的次数大于t2的\nDialogue: 0,1:02:47.23,1:02:50.59,Default,,0,0,0,,小于t2的 或者等于t2的\nDialogue: 0,1:02:53.28,1:02:54.91,Default,,0,0,0,,这就是我们要判断的三种情况\nDialogue: 0,1:02:54.91,1:02:55.84,Default,,0,0,0,,先看看这一种\nDialogue: 0,1:02:58.64,1:03:01.31,Default,,0,0,0,,如果t1的次数比t2的次数要高\nDialogue: 0,1:03:03.40,1:03:04.70,Default,,0,0,0,,就意味着\nDialogue: 0,1:03:06.06,1:03:09.96,Default,,0,0,0,,答案的第一项的次数就是t1的次数\nDialogue: 0,1:03:11.56,1:03:13.80,Default,,0,0,0,,因为高次项不会和任何低次项相加\nDialogue: 0,1:03:14.17,1:03:16.19,Default,,0,0,0,,那么我们只需要把低次的项加起来\nDialogue: 0,1:03:16.76,1:03:18.25,Default,,0,0,0,,我们递归地把\nDialogue: 0,1:03:19.71,1:03:25.07,Default,,0,0,0,,把L1和L2两个项表里剩下的项相加\nDialogue: 0,1:03:27.13,1:03:29.32,Default,,0,0,0,,作为我们的答案中低次项\nDialogue: 0,1:03:30.12,1:03:32.48,Default,,0,0,0,,然后我们把它们和最高次的项连接起来\nDialogue: 0,1:03:33.18,1:03:35.45,Default,,0,0,0,,这里 我用了一对还未定义的过程\nDialogue: 0,1:03:35.47,1:03:37.55,Default,,0,0,0,,比如adjoin-term、rest-terms\nDialogue: 0,1:03:38.48,1:03:40.17,Default,,0,0,0,,还有获取次数的选择函数\nDialogue: 0,1:03:41.15,1:03:42.78,Default,,0,0,0,,但是你可以想象它们是什么样子的\nDialogue: 0,1:03:44.44,1:03:48.76,Default,,0,0,0,,那么如果第一个项表的次数比第二个要高\nDialogue: 0,1:03:48.78,1:03:51.08,Default,,0,0,0,,我们就递归地把所有的低次的项相加\nDialogue: 0,1:03:51.28,1:03:53.42,Default,,0,0,0,,再和最高次项连接起来\nDialogue: 0,1:03:55.54,1:03:56.75,Default,,0,0,0,,其它情况也是一样的\nDialogue: 0,1:03:56.89,1:04:00.28,Default,,0,0,0,,如果第一个多项式次数比较低\nDialogue: 0,1:04:00.54,1:04:08.36,Default,,0,0,0,,我们就把整个第一个多项式和第二个多项式低次的项相加\nDialogue: 0,1:04:08.62,1:04:12.65,Default,,0,0,0,,然后把结果再和最高次项连起来\nDialogue: 0,1:04:14.57,1:04:15.96,Default,,0,0,0,,到现在也没多少复杂的事情\nDialogue: 0,1:04:15.96,1:04:19.40,Default,,0,0,0,,把问题变成 让低次数的项相加\nDialogue: 0,1:04:19.47,1:04:21.96,Default,,0,0,0,,还有最后一种情况是 两个多项式的次数一样\nDialogue: 0,1:04:22.57,1:04:25.18,Default,,0,0,0,,你必须要把它们的系数加起来 因为它们是同类项\nDialogue: 0,1:04:27.24,1:04:30.99,Default,,0,0,0,,我们的应对方法仍然是 递归地把低次项相加\nDialogue: 0,1:04:31.00,1:04:32.83,Default,,0,0,0,,但现在我们需要合并一些项了\nDialogue: 0,1:04:33.46,1:04:36.35,Default,,0,0,0,,我们构造一个项\nDialogue: 0,1:04:37.31,1:04:39.93,Default,,0,0,0,,其次数为我们正在处理的那一项的次数\nDialogue: 0,1:04:40.82,1:04:42.72,Default,,0,0,0,,因为现在t1和t2的次数是相同的\nDialogue: 0,1:04:44.32,1:04:44.99,Default,,0,0,0,,确定好次数了\nDialogue: 0,1:04:45.09,1:04:52.33,Default,,0,0,0,,而它的系数是t1和t2系数之和\nDialogue: 0,1:04:55.79,1:04:59.64,Default,,0,0,0,,这是一个庞大的递归过程\nDialogue: 0,1:04:59.68,1:05:03.61,Default,,0,0,0,,但其中只有一个符号值得玩味\nDialogue: 0,1:05:04.25,1:05:05.69,Default,,0,0,0,,它蕴含了重要的思想\nDialogue: 0,1:05:05.90,1:05:08.50,Default,,0,0,0,,那就是这个ADD过程\nDialogue: 0,1:05:12.39,1:05:14.80,Default,,0,0,0,,说它有趣是因为\nDialogue: 0,1:05:15.42,1:05:17.37,Default,,0,0,0,,有一件好事发生\nDialogue: 0,1:05:18.22,1:05:21.37,Default,,0,0,0,,我们没有把多项式加法\nDialogue: 0,1:05:22.56,1:05:26.46,Default,,0,0,0,,归约为某种加法 而是归约为通用运算符ADD\nDialogue: 0,1:05:28.82,1:05:32.28,Default,,0,0,0,,换句话说 用这种方法实现它之后\nDialogue: 0,1:05:32.89,1:05:34.68,Default,,0,0,0,,我们的系统就不光有\nDialogue: 0,1:05:35.92,1:05:41.66,Default,,0,0,0,,有理数、复数还有寻常算术\nDialogue: 0,1:05:41.85,1:05:43.82,Default,,0,0,0,,我们同时也让它支持多项式运算了\nDialogue: 0,1:05:48.52,1:05:51.13,Default,,0,0,0,,而多项式的系数可以是\nDialogue: 0,1:05:51.24,1:05:52.86,Default,,0,0,0,,这个系统能够相加的任何东西\nDialogue: 0,1:05:53.59,1:05:56.73,Default,,0,0,0,,也就是说多项式的系数\nDialogue: 0,1:05:57.20,1:06:01.20,Default,,0,0,0,,有理数或者复数\nDialogue: 0,1:06:02.76,1:06:06.99,Default,,0,0,0,,复数同时可支持直角坐标形式和极坐标形式\nDialogue: 0,1:06:09.12,1:06:11.39,Default,,0,0,0,,系数还可以是寻常的数字\nDialogue: 0,1:06:18.97,1:06:21.21,Default,,0,0,0,,我想说的是\nDialogue: 0,1:06:22.06,1:06:24.35,Default,,0,0,0,,我们的系统现在可以自动地\nDialogue: 0,1:06:26.60,1:06:31.50,Default,,0,0,0,,处理像这样的式子\nDialogue: 0,1:06:31.53,1:06:39.69,Default,,0,0,0,,比如2/3x^2+5/17x+11/4这样的式子\nDialogue: 0,1:06:40.94,1:06:43.48,Default,,0,0,0,,也可以自动处理像是\nDialogue: 0,1:06:43.82,1:06:52.57,Default,,0,0,0,,(3+2i)x^5+(4+7i)这样的式子\nDialogue: 0,1:06:53.88,1:06:56.21,Default,,0,0,0,,系统可以自动处理这些运算\nDialogue: 0,1:06:56.21,1:06:57.07,Default,,0,0,0,,为什么呢？\nDialogue: 0,1:06:57.82,1:07:01.50,Default,,0,0,0,,仅仅是因为 或者说深层次的原因是\nDialogue: 0,1:07:02.17,1:07:05.93,Default,,0,0,0,,我们把多项式相加归约成了把它们的系数相加\nDialogue: 0,1:07:06.79,1:07:10.22,Default,,0,0,0,,而系数的相加是由通用运算符ADD完成的\nDialogue: 0,1:07:11.08,1:07:12.94,Default,,0,0,0,,它说：“我不管你的数据类型是什么”\nDialogue: 0,1:07:12.96,1:07:14.08,Default,,0,0,0,,“只要我能够处理就行”\nDialogue: 0,1:07:15.23,1:07:18.86,Default,,0,0,0,,于是我们就“免费”获得了处理这些东西的功能\nDialogue: 0,1:07:20.65,1:07:22.04,Default,,0,0,0,,更神奇的是\nDialogue: 0,1:07:24.51,1:07:26.52,Default,,0,0,0,,我们曾把\nDialogue: 0,1:07:27.20,1:07:30.52,Default,,0,0,0,,我们放入表格中 用于处理多项式加法\nDialogue: 0,1:07:31.28,1:07:32.52,Default,,0,0,0,,是用的+poly过程\nDialogue: 0,1:07:34.66,1:07:38.65,Default,,0,0,0,,这就意味着ADD过程也可以处理多项式了\nDialogue: 0,1:07:39.42,1:07:42.11,Default,,0,0,0,,我举个例子\nDialogue: 0,1:07:43.18,1:07:46.19,Default,,0,0,0,,这是一个多项式\nDialogue: 0,1:07:50.56,1:07:52.41,Default,,0,0,0,,我正在写的这个东西\nDialogue: 0,1:07:54.12,1:07:58.46,Default,,0,0,0,,它是一个以y作为变量的多项式\nDialogue: 0,1:08:01.07,1:08:04.69,Default,,0,0,0,,每项的系数是以x作为变量的多项式\nDialogue: 0,1:08:08.61,1:08:11.12,Default,,0,0,0,,你将看到\nDialogue: 0,1:08:11.76,1:08:14.06,Default,,0,0,0,,由于 “ADD过程能够处理多项式”\nDialogue: 0,1:08:14.41,1:08:17.90,Default,,0,0,0,,我们可以说 我们的系统现在不光能运算有理数\nDialogue: 0,1:08:18.27,1:08:20.33,Default,,0,0,0,,复数和一般数字\nDialogue: 0,1:08:20.35,1:08:21.77,Default,,0,0,0,,我们还可以处理多项式\nDialogue: 0,1:08:22.09,1:08:25.39,Default,,0,0,0,,多项式的系数可以是有理数、复数、一般数字\nDialogue: 0,1:08:25.50,1:08:27.52,Default,,0,0,0,,甚至是多项式\nDialogue: 0,1:08:29.15,1:08:30.96,Default,,0,0,0,,作为系数的多项式 其系数还可以是有理数\nDialogue: 0,1:08:31.69,1:08:36.76,Default,,0,0,0,,复数（直角或极坐标形式）或一般数字\nDialogue: 0,1:08:36.94,1:08:41.13,Default,,0,0,0,,甚至还可以是系数为有理数的多项式\nDialogue: 0,1:08:41.80,1:08:43.32,Default,,0,0,0,,系数为复数、一般数字的多项式\nDialogue: 0,1:08:43.67,1:08:45.21,Default,,0,0,0,,以此类推\nDialogue: 0,1:08:45.95,1:08:47.55,Default,,0,0,0,,我们构造出了一座无限延伸的\nDialogue: 0,1:08:48.49,1:08:52.88,Default,,0,0,0,,或者说是递归的类型高塔\nDialogue: 0,1:08:53.88,1:08:57.12,Default,,0,0,0,,这一切都来源于那个小小的符号：A-D-D\nDialogue: 0,1:08:57.61,1:09:00.49,Default,,0,0,0,,来源于在多项式程序里 用“ADD”来代替“+”\nDialogue: 0,1:09:02.27,1:09:03.77,Default,,0,0,0,,换一种方式来理解它就是\nDialogue: 0,1:09:03.95,1:09:07.74,Default,,0,0,0,,多项式也是一种类型的构造函数\nDialogue: 0,1:09:08.74,1:09:11.20,Default,,0,0,0,,也就是说你传递给它一个类型 比如整型\nDialogue: 0,1:09:11.48,1:09:15.74,Default,,0,0,0,,然后它就返回一个以整数作为系数的多项式\nDialogue: 0,1:09:16.27,1:09:17.72,Default,,0,0,0,,过程中很重要的一点是\nDialogue: 0,1:09:18.65,1:09:20.73,Default,,0,0,0,,就是多项式上的运算\nDialogue: 0,1:09:21.28,1:09:23.37,Default,,0,0,0,,归约成了关于系数的运算\nDialogue: 0,1:09:23.39,1:09:24.96,Default,,0,0,0,,很多地方都与这里类似\nDialogue: 0,1:09:25.84,1:09:27.92,Default,,0,0,0,,比如 我们再回头看看有理数\nDialogue: 0,1:09:28.87,1:09:32.65,Default,,0,0,0,,我们之前把有理数看做 一个整数在另一个上面\nDialogue: 0,1:09:32.67,1:09:35.66,Default,,0,0,0,,但这并不是关于有理式的一般性记号\nDialogue: 0,1:09:36.24,1:09:42.03,Default,,0,0,0,,比如我们也可以把3x+7放在上面 x^2+1放在下面\nDialogue: 0,1:09:43.07,1:09:48.86,Default,,0,0,0,,这是一个分子分母都是多项式的广义有理式\nDialogue: 0,1:09:50.31,1:09:52.41,Default,,0,0,0,,有理式相加 和有理数相加一样\nDialogue: 0,1:09:52.44,1:09:55.40,Default,,0,0,0,,分子乘分母 加 分母乘分子 结果作为分子\nDialogue: 0,1:09:55.72,1:09:56.99,Default,,0,0,0,,两个分母相乘 结果作为分母\nDialogue: 0,1:09:57.29,1:09:59.37,Default,,0,0,0,,怎么把它安装到我们的系统中呢？\nDialogue: 0,1:09:59.39,1:10:02.97,Default,,0,0,0,,这是我们原来的有理数算术程序包\nDialogue: 0,1:10:04.25,1:10:08.24,Default,,0,0,0,,为了让这个系统能够\nDialogue: 0,1:10:08.28,1:10:11.58,Default,,0,0,0,,支持广义有理式的运算\nDialogue: 0,1:10:11.85,1:10:16.44,Default,,0,0,0,,我们把特定的加法和乘法过程 都改成通用运算符\nDialogue: 0,1:10:16.48,1:10:19.18,Default,,0,0,0,,所以如果我们把原来那个过程变成这个过程\nDialogue: 0,1:10:19.71,1:10:22.04,Default,,0,0,0,,把+和*换成ADD和MUL\nDialogue: 0,1:10:22.88,1:10:24.48,Default,,0,0,0,,这些是唯一的改动\nDialogue: 0,1:10:24.84,1:10:26.03,Default,,0,0,0,,然后霎时间\nDialogue: 0,1:10:27.52,1:10:31.40,Default,,0,0,0,,我们的整个系统 就知道怎么运算这样的东西了\nDialogue: 0,1:10:33.72,1:10:38.27,Default,,0,0,0,,比如说 这里的这个有理式\nDialogue: 0,1:10:39.18,1:10:44.86,Default,,0,0,0,,它的分子是一个系数是有理数的、关于x的多项式\nDialogue: 0,1:10:47.02,1:10:49.56,Default,,0,0,0,,而这个有理式\nDialogue: 0,1:10:51.10,1:10:54.43,Default,,0,0,0,,它的分子是关于x的多项式\nDialogue: 0,1:10:55.15,1:10:58.19,Default,,0,0,0,,多项式的系数又是有理式\nDialogue: 0,1:10:59.77,1:11:01.53,Default,,0,0,0,,有理式又由复数组成\nDialogue: 0,1:11:03.39,1:11:04.85,Default,,0,0,0,,或者别的像这样的东西\nDialogue: 0,1:11:04.85,1:11:08.68,Default,,0,0,0,,看 只要能够归约成针对各部分的运算\nDialogue: 0,1:11:08.89,1:11:10.00,Default,,0,0,0,,另一个例子是\nDialogue: 0,1:11:10.28,1:11:11.42,Default,,0,0,0,,2*2的矩阵\nDialogue: 0,1:11:12.31,1:11:15.44,Default,,0,0,0,,假如有这样一个矩阵形式的东西\nDialogue: 0,1:11:16.43,1:11:18.33,Default,,0,0,0,,不管它里面是什么\nDialogue: 0,1:11:18.72,1:11:20.14,Default,,0,0,0,,但是如果我对两个这种东西调用ADD\nDialogue: 0,1:11:22.33,1:11:25.18,Default,,0,0,0,,答案就是\nDialogue: 0,1:11:25.18,1:11:28.14,Default,,0,0,0,,把这个和这个相加 而矩阵是怎么相加的\nDialogue: 0,1:11:29.03,1:11:31.11,Default,,0,0,0,,那么我可以用同样的方法实现\nDialogue: 0,1:11:31.11,1:11:31.71,Default,,0,0,0,,如果我这么做了\nDialogue: 0,1:11:31.96,1:11:34.60,Default,,0,0,0,,整个系统就马上可以处理像这样的东西了\nDialogue: 0,1:11:35.29,1:11:39.18,Default,,0,0,0,,比如说一个矩阵 它的元素都是\nDialogue: 0,1:11:39.46,1:11:42.16,Default,,0,0,0,,它的元素是一个有理式\nDialogue: 0,1:11:43.10,1:11:45.15,Default,,0,0,0,,这个有理式的分子分母都是多项式\nDialogue: 0,1:11:47.02,1:11:49.56,Default,,0,0,0,,我们自然而然地获得了这些功能\nDialogue: 0,1:11:51.28,1:11:53.82,Default,,0,0,0,,整个过程中发生了什么？\nDialogue: 0,1:11:53.92,1:11:56.17,Default,,0,0,0,,真正发生的是\nDialogue: 0,1:11:57.68,1:12:02.44,Default,,0,0,0,,我们摆脱了凡事都想插一手的经理\nDialogue: 0,1:12:03.12,1:12:06.19,Default,,0,0,0,,我们构造了一个“控制去中心化”的系统\nDialogue: 0,1:12:14.78,1:12:18.34,Default,,0,0,0,,你进入这个系统的时候 不会有人一边闲逛一边说\nDialogue: 0,1:12:18.35,1:12:22.30,Default,,0,0,0,,我看看官方列表中ADD是否能够处理你\nDialogue: 0,1:12:22.44,1:12:26.22,Default,,0,0,0,,你直接就可以用正确的方法 把你和别的东西加起来\nDialogue: 0,1:12:27.81,1:12:31.03,Default,,0,0,0,,这么做的好处就是 就连这种非常非常\nDialogue: 0,1:12:31.03,1:12:33.87,Default,,0,0,0,,复杂的分层对象也可以被分解后\nDialogue: 0,1:12:33.87,1:12:35.55,Default,,0,0,0,,自动放到正确的地方去处理\nDialogue: 0,1:12:37.00,1:12:37.79,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:12:40.38,1:12:42.32,Default,,0,0,0,,学生：你说你“免费”获得了这些功能\nDialogue: 0,1:12:42.35,1:12:45.82,Default,,0,0,0,,但是我在意的是你现在丢掉了\nDialogue: 0,1:12:46.48,1:12:50.91,Default,,0,0,0,,某种上下层之间的清楚界限\nDialogue: 0,1:12:50.91,1:12:52.77,Default,,0,0,0,,或者说 现在你是在用\nDialogue: 0,1:12:52.77,1:12:56.08,Default,,0,0,0,,上层的东西来定义下层的过程\nDialogue: 0,1:12:56.61,1:12:59.45,Default,,0,0,0,,这不是很危险吗？\nDialogue: 0,1:13:00.35,1:13:04.49,Default,,0,0,0,,或者说 结构会变得混乱？\nDialogue: 0,1:13:05.44,1:13:05.95,Default,,0,0,0,,教授：不 我--\nDialogue: 0,1:13:06.41,1:13:07.77,Default,,0,0,0,,你问它的结构是否混乱\nDialogue: 0,1:13:07.77,1:13:08.69,Default,,0,0,0,,这得要看你说的“结构”是指什么\nDialogue: 0,1:13:08.69,1:13:10.17,Default,,0,0,0,,整个过程里我们都在做递归\nDialogue: 0,1:13:11.05,1:13:18.80,Default,,0,0,0,,看 就是说要把这些东西相加就要用到这个过程\nDialogue: 0,1:13:19.15,1:13:21.37,Default,,0,0,0,,它是一种递归结构 并不混乱\nDialogue: 0,1:13:22.70,1:13:24.99,Default,,0,0,0,,所以我不认为它不清楚\nDialogue: 0,1:13:24.99,1:13:28.16,Default,,0,0,0,,学生：那么当你修改乘法或加法运算时\nDialogue: 0,1:13:29.34,1:13:31.38,Default,,0,0,0,,可能会导致\nDialogue: 0,1:13:31.38,1:13:34.27,Default,,0,0,0,,无法预测的灾难性后果\nDialogue: 0,1:13:34.48,1:13:36.44,Default,,0,0,0,,教授：你说得对 但是那要看你的意思是什么\nDialogue: 0,1:13:37.08,1:13:38.47,Default,,0,0,0,,从两个角度来讨论\nDialogue: 0,1:13:39.10,1:13:43.24,Default,,0,0,0,,举个什么例子好呢？\nDialogue: 0,1:13:44.69,1:13:47.50,Default,,0,0,0,,比如说 之前我忽略了GCD运算\nDialogue: 0,1:13:47.77,1:13:50.08,Default,,0,0,0,,我们忽略了它 是为了简化我们的例子\nDialogue: 0,1:13:50.28,1:13:56.92,Default,,0,0,0,,但是如果突然我觉得 这里的+rat\nDialogue: 0,1:13:57.82,1:14:01.69,Default,,0,0,0,,应该把结果约分 然后把这个功能安装到程序里\nDialogue: 0,1:14:03.34,1:14:07.87,Default,,0,0,0,,那么这个功能一旦安装 就立刻可以被所有过程调用\nDialogue: 0,1:14:08.03,1:14:10.08,Default,,0,0,0,,被这个或者那个 所有的这些\nDialogue: 0,1:14:11.56,1:14:13.89,Default,,0,0,0,,这取决于你系统的相干性（耦合度）\nDialogue: 0,1:14:13.89,1:14:17.03,Default,,0,0,0,,确实你可能想设计一个\nDialogue: 0,1:14:17.03,1:14:19.56,Default,,0,0,0,,不这样递归下降的程序\nDialogue: 0,1:14:19.61,1:14:22.97,Default,,0,0,0,,但是我举这个例子的好处 就在于我们通常都是这么做的\nDialogue: 0,1:14:25.44,1:14:27.63,Default,,0,0,0,,学生：是不是有一个问题 我想\nDialogue: 0,1:14:27.63,1:14:32.95,Default,,0,0,0,,就是你会被这个结构捆绑起来\nDialogue: 0,1:14:32.95,1:14:36.33,Default,,0,0,0,,这个递归的结构是实际上被执行了的\nDialogue: 0,1:14:36.33,1:14:40.34,Default,,0,0,0,,而不是仅仅是为了定义类型的需要\nDialogue: 0,1:14:40.34,1:14:41.16,Default,,0,0,0,,被这个事实所束缚\nDialogue: 0,1:14:44.68,1:14:46.12,Default,,0,0,0,,教授：我大概明白你的意思\nDialogue: 0,1:14:46.12,1:14:47.80,Default,,0,0,0,,你是想说在这个系统投入运行之后\nDialogue: 0,1:14:47.82,1:14:50.40,Default,,0,0,0,,这些类型还会变得越来越复杂\nDialogue: 0,1:14:50.40,1:14:50.73,Default,,0,0,0,,你是不是想……\nDialogue: 0,1:14:50.73,1:14:50.99,Default,,0,0,0,,学生：对\nDialogue: 0,1:14:50.99,1:14:51.79,Default,,0,0,0,,在它投入运行之后\nDialogue: 0,1:14:52.09,1:14:54.18,Default,,0,0,0,,学生：而不是作为基本的定义\nDialogue: 0,1:14:54.18,1:14:54.83,Default,,0,0,0,,教授：对\nDialogue: 0,1:14:54.83,1:14:56.70,Default,,0,0,0,,我们的类型结构可以说就是递归的\nDialogue: 0,1:14:57.21,1:15:00.22,Default,,0,0,0,,它并不是一个 可以在系统投入运行之前\nDialogue: 0,1:15:01.58,1:15:04.85,Default,,0,0,0,,就能把要用到的东西全部包括的列表\nDialogue: 0,1:15:04.85,1:15:05.79,Default,,0,0,0,,它是一个不断演进的东西\nDialogue: 0,1:15:06.78,1:15:08.64,Default,,0,0,0,,所以如果你想要定制这个系统\nDialogue: 0,1:15:08.67,1:15:10.96,Default,,0,0,0,,你就不能通过有限的表\nDialogue: 0,1:15:11.00,1:15:13.18,Default,,0,0,0,,你需要用一个递归结构实现它\nDialogue: 0,1:15:13.67,1:15:17.90,Default,,0,0,0,,学生：因为类型的基本结构是相当简单而明了的\nDialogue: 0,1:15:17.90,1:15:18.19,Default,,0,0,0,,教授：对\nDialogue: 0,1:15:20.40,1:15:20.75,Default,,0,0,0,,嗯？\nDialogue: 0,1:15:21.46,1:15:22.87,Default,,0,0,0,,学生：我有一个问题\nDialogue: 0,1:15:22.87,1:15:25.68,Default,,0,0,0,,我明白一旦你的数据结构被设计好之后\nDialogue: 0,1:15:25.71,1:15:28.73,Default,,0,0,0,,它是怎么把complex标志拿掉 把它传递给下层\nDialogue: 0,1:15:28.73,1:15:30.64,Default,,0,0,0,,然后把rect类型拿掉 再传递给下层\nDialogue: 0,1:15:30.64,1:15:33.95,Default,,0,0,0,,但是如果你只是一个用户 并不知道什么rect或者polar类型\nDialogue: 0,1:15:34.25,1:15:36.04,Default,,0,0,0,,你怎么知道如何去设置这个数据结构\nDialogue: 0,1:15:36.09,1:15:38.08,Default,,0,0,0,,让所有东西正常运转呢\nDialogue: 0,1:15:38.09,1:15:41.00,Default,,0,0,0,,如果我只知道左边的这个算式\nDialogue: 0,1:15:41.02,1:15:42.50,Default,,0,0,0,,我只是想把复数加起来或者乘起来\nDialogue: 0,1:15:42.50,1:15:43.64,Default,,0,0,0,,教授：这就是它神奇的地方\nDialogue: 0,1:15:43.64,1:15:45.26,Default,,0,0,0,,如果你是一个用户 直接调用mul就可以了\nDialogue: 0,1:15:47.73,1:15:49.95,Default,,0,0,0,,学生：然后它就能明白我要计算的是复数？\nDialogue: 0,1:15:49.96,1:15:51.23,Default,,0,0,0,,或者我怎么告诉它我想——\nDialogue: 0,1:15:51.26,1:15:53.05,Default,,0,0,0,,教授：只要你给它的是复数它就能明白\nDialogue: 0,1:15:53.05,1:15:56.30,Default,,0,0,0,,作为这个系统的用户\nDialogue: 0,1:15:56.32,1:15:58.14,Default,,0,0,0,,你能使用的是复数的构造函数\nDialogue: 0,1:15:58.37,1:15:59.55,Default,,0,0,0,,学生：那么我需要自己构造复数了？\nDialogue: 0,1:15:59.56,1:16:00.35,Default,,0,0,0,,教授：那么你需要自己构造它们\nDialogue: 0,1:16:00.35,1:16:04.01,Default,,0,0,0,,作为用户 你可能只能够操作命令行\nDialogue: 0,1:16:04.65,1:16:07.56,Default,,0,0,0,,它会给你提供一些合理的方法\nDialogue: 0,1:16:07.56,1:16:08.86,Default,,0,0,0,,来输入复数\nDialogue: 0,1:16:09.31,1:16:11.00,Default,,0,0,0,,让你用你喜欢的格式输入\nDialogue: 0,1:16:11.59,1:16:14.36,Default,,0,0,0,,也可能你根本就不用输入它们\nDialogue: 0,1:16:14.36,1:16:16.17,Default,,0,0,0,,只是别人给你一个复数让你计算\nDialogue: 0,1:16:16.78,1:16:19.82,Default,,0,0,0,,学生：好 那么如果我有一个含有多项式的复数\nDialogue: 0,1:16:19.82,1:16:21.96,Default,,0,0,0,,我就要先构造这个多项式 然后再构造我的复数\nDialogue: 0,1:16:21.96,1:16:23.96,Default,,0,0,0,,教授：如果你是从零开始构造它的话 是这样的\nDialogue: 0,1:16:24.28,1:16:25.71,Default,,0,0,0,,可以说你是在从零开始构造\nDialogue: 0,1:16:25.71,1:16:27.05,Default,,0,0,0,,而你只要有了要计算的东西\nDialogue: 0,1:16:27.28,1:16:30.32,Default,,0,0,0,,可以直接调用mul运算 然后它们就会被乘起来\nDialogue: 0,1:16:32.78,1:16:32.99,Default,,0,0,0,,说吧\nDialogue: 0,1:16:33.27,1:16:35.76,Default,,0,0,0,,学生：我想提一个问题 就是……\nDialogue: 0,1:16:36.45,1:16:40.01,Default,,0,0,0,,比如说我想修改我的复数表示方法\nDialogue: 0,1:16:40.03,1:16:41.44,Default,,0,0,0,,或者复数的某些运算\nDialogue: 0,1:16:41.52,1:16:47.10,Default,,0,0,0,,为了修改一个特定的运算\nDialogue: 0,1:16:47.15,1:16:51.26,Default,,0,0,0,,我得考虑多少代码？\nDialogue: 0,1:16:52.27,1:16:53.49,Default,,0,0,0,,教授：得看你想要修改什么\nDialogue: 0,1:16:53.49,1:16:54.99,Default,,0,0,0,,重点在于你只需要改\nDialogue: 0,1:16:55.39,1:16:56.07,Default,,0,0,0,,你想改的那一部分\nDialogue: 0,1:16:56.07,1:17:00.04,Default,,0,0,0,,想象一下如果Martha决定她\nDialogue: 0,1:17:00.32,1:17:01.23,Default,,0,0,0,,举个不太好的例子\nDialogue: 0,1:17:01.44,1:17:02.91,Default,,0,0,0,,比如把序对中两个数的顺序调换\nDialogue: 0,1:17:04.04,1:17:08.72,Default,,0,0,0,,把模和辐角的顺序反过来\nDialogue: 0,1:17:09.39,1:17:10.80,Default,,0,0,0,,她只做了局部的修改\nDialogue: 0,1:17:10.97,1:17:13.29,Default,,0,0,0,,那么这个改动会准确无误地扩散到整个系统里\nDialogue: 0,1:17:14.79,1:17:18.76,Default,,0,0,0,,或者突然你说 我有另一种方法来表示有理数\nDialogue: 0,1:17:19.70,1:17:23.90,Default,,0,0,0,,我就得不断地在表格中添加运算\nDialogue: 0,1:17:24.82,1:17:27.22,Default,,0,0,0,,那么突然之间所有的多项式\nDialogue: 0,1:17:27.22,1:17:29.10,Default,,0,0,0,,它们的系数和系数的系数 或者什么东西\nDialogue: 0,1:17:29.24,1:17:32.40,Default,,0,0,0,,都自动支持用这种表示方法来表示了\nDialogue: 0,1:17:32.70,1:17:34.67,Default,,0,0,0,,这就是我们这种设计的威力\nDialogue: 0,1:17:36.11,1:17:38.70,Default,,0,0,0,,学生：我提的这个问题可能听起来比较蠢\nDialogue: 0,1:17:38.70,1:17:42.38,Default,,0,0,0,,整个这个系统看起来\nDialogue: 0,1:17:42.54,1:17:45.88,Default,,0,0,0,,非常完美 所有的东西都各就各位\nDialogue: 0,1:17:46.72,1:17:48.67,Default,,0,0,0,,完美得有点出乎意料\nDialogue: 0,1:17:50.93,1:17:52.52,Default,,0,0,0,,我相信 这都是为了教学方便\nDialogue: 0,1:17:52.56,1:17:54.65,Default,,0,0,0,,我怀疑的是首先发明了这种做法的人\nDialogue: 0,1:17:55.10,1:17:55.85,Default,,0,0,0,,我可能说得不对\nDialogue: 0,1:17:56.60,1:17:59.72,Default,,0,0,0,,难道一下子就搞清楚了所有这些东西一起\nDialogue: 0,1:17:59.77,1:18:03.93,Default,,0,0,0,,只要把这些放在一起 你就突然可以对各种对象做各种运算\nDialogue: 0,1:18:04.86,1:18:07.20,Default,,0,0,0,,我觉得他们应该研究了很长时间\nDialogue: 0,1:18:07.93,1:18:10.62,Default,,0,0,0,,不断地推倒重来\nDialogue: 0,1:18:11.80,1:18:14.12,Default,,0,0,0,,然后我觉得 当我们设计一个非常复杂的系统\nDialogue: 0,1:18:14.12,1:18:16.94,Default,,0,0,0,,我们也要面对这样的问题\nDialogue: 0,1:18:17.31,1:18:20.35,Default,,0,0,0,,就是有太多各种各样的部件 我们甚至不知道\nDialogue: 0,1:18:21.08,1:18:24.62,Default,,0,0,0,,我们甚至不知道要对这些部件做什么样的操作\nDialogue: 0,1:18:24.62,1:18:26.54,Default,,0,0,0,,在这种时候我怎么用这种良好的方法组织操作\nDialogue: 0,1:18:26.56,1:18:29.63,Default,,0,0,0,,才能获得这种 不管怎样只要把它们放在一起\nDialogue: 0,1:18:29.63,1:18:31.39,Default,,0,0,0,,所有事情就正常运转 这样的效果呢\nDialogue: 0,1:18:31.70,1:18:34.34,Default,,0,0,0,,教授：很好 这确实是一个非常聪明的问题\nDialogue: 0,1:18:35.10,1:18:39.52,Default,,0,0,0,,要说的一点是我们这种方法论\nDialogue: 0,1:18:39.87,1:18:43.88,Default,,0,0,0,,受到了符号代数的很多启发\nDialogue: 0,1:18:44.59,1:18:45.90,Default,,0,0,0,,符号代数相当繁复\nDialogue: 0,1:18:47.59,1:18:50.71,Default,,0,0,0,,允许你在决定各种运算是什么样子之前\nDialogue: 0,1:18:50.71,1:18:52.89,Default,,0,0,0,,来实现这个系统\nDialogue: 0,1:18:53.31,1:18:57.72,Default,,0,0,0,,所以从某种意义上讲 这是人们在这方面长期探索之后得出的答案\nDialogue: 0,1:18:58.56,1:19:00.75,Default,,0,0,0,,从另一个角度来说 这确实是精心设计的例子\nDialogue: 0,1:19:02.16,1:19:06.24,Default,,0,0,0,,学生：看上去想要设计出这样的系统\nDialogue: 0,1:19:06.24,1:19:09.01,Default,,0,0,0,,一开始先要研究一段时间然后才能变熟练\nDialogue: 0,1:19:09.01,1:19:11.88,Default,,0,0,0,,教授：我给你看看这个东西是多么的勉强\nDialogue: 0,1:19:12.22,1:19:14.13,Default,,0,0,0,,你现在可以写下所有的这些程序\nDialogue: 0,1:19:14.13,1:19:16.25,Default,,0,0,0,,但是我写在这里的这个系统\nDialogue: 0,1:19:17.02,1:19:18.96,Default,,0,0,0,,如果允许我拖堂半小时的话\nDialogue: 0,1:19:19.31,1:19:20.46,Default,,0,0,0,,我会给大家讲\nDialogue: 0,1:19:20.81,1:19:23.02,Default,,0,0,0,,如果我让它做一个错误操作\nDialogue: 0,1:19:23.20,1:19:29.31,Default,,0,0,0,,比如一个愚蠢的命令 用3加上7/2 它就会崩溃\nDialogue: 0,1:19:30.88,1:19:33.42,Default,,0,0,0,,因为程序首先会调用operate-2这个过程\nDialogue: 0,1:19:33.80,1:19:35.95,Default,,0,0,0,,然后operate-2会说 这个是数字类型\nDialogue: 0,1:19:36.18,1:19:37.37,Default,,0,0,0,,那个是有理数类型\nDialogue: 0,1:19:37.56,1:19:38.81,Default,,0,0,0,,我不知道怎么把它们加起来\nDialogue: 0,1:19:41.53,1:19:44.30,Default,,0,0,0,,那么你想让这个系统至少能够\nDialogue: 0,1:19:45.88,1:19:47.34,Default,,0,0,0,,比如说 在做这个操作之前\nDialogue: 0,1:19:48.59,1:19:50.24,Default,,0,0,0,,把3提升为3/1\nDialogue: 0,1:19:50.48,1:19:53.21,Default,,0,0,0,,把它变成一个有理数 然后交给有理数程序包来处理\nDialogue: 0,1:19:54.86,1:19:58.70,Default,,0,0,0,,课堂上我们来不及讲这个问题了\nDialogue: 0,1:19:58.73,1:20:00.88,Default,,0,0,0,,书里面讨论了这个问题\nDialogue: 0,1:20:00.88,1:20:01.95,Default,,0,0,0,,叫做“类型转换”\nDialogue: 0,1:20:03.39,1:20:05.15,Default,,0,0,0,,你想要的是\nDialogue: 0,1:20:05.31,1:20:08.89,Default,,0,0,0,,看 我们小心翼翼地把对象按类型分好类\nDialogue: 0,1:20:08.91,1:20:12.17,Default,,0,0,0,,但是有时你也想让它\nDialogue: 0,1:20:12.40,1:20:17.98,Default,,0,0,0,,知道怎么把一个普通的数字当成有理数\nDialogue: 0,1:20:19.11,1:20:21.29,Default,,0,0,0,,或者把普通的数字当成复数\nDialogue: 0,1:20:21.62,1:20:25.16,Default,,0,0,0,,到那个时候系统就开始变得复杂了\nDialogue: 0,1:20:25.76,1:20:28.12,Default,,0,0,0,,就是你去思考 我应该把这些知识放在哪里的时候\nDialogue: 0,1:20:28.42,1:20:32.19,Default,,0,0,0,,是应该让有理数知道它们是由普通的数字构成的吗？\nDialogue: 0,1:20:33.13,1:20:36.38,Default,,0,0,0,,或者我们举一个更加糟糕的例子\nDialogue: 0,1:20:38.14,1:20:47.48,Default,,0,0,0,,比如说我想要把一个复数加到有理数上去\nDialogue: 0,1:20:49.87,1:20:50.76,Default,,0,0,0,,这个不好\nDialogue: 0,1:20:50.76,1:20:51.58,Default,,0,0,0,,5/7\nDialogue: 0,1:20:53.86,1:20:55.72,Default,,0,0,0,,然后整个系统里必须有人知道\nDialogue: 0,1:20:56.06,1:20:58.16,Default,,0,0,0,,他需要把这个东西变成另一种类型\nDialogue: 0,1:20:58.20,1:21:00.65,Default,,0,0,0,,要把它变成一部分是有理数的复数\nDialogue: 0,1:21:01.54,1:21:02.68,Default,,0,0,0,,那么谁应该去操心这个事情呢\nDialogue: 0,1:21:02.68,1:21:03.95,Default,,0,0,0,,是complex程序包吗？\nDialogue: 0,1:21:03.95,1:21:05.03,Default,,0,0,0,,是rational程序包吗？\nDialogue: 0,1:21:05.24,1:21:06.22,Default,,0,0,0,,还是plus过程要考虑这个问题？\nDialogue: 0,1:21:06.90,1:21:08.52,Default,,0,0,0,,这就是体现复杂性的地方\nDialogue: 0,1:21:08.52,1:21:11.38,Default,,0,0,0,,也是这个问题的特别之处\nDialogue: 0,1:21:11.38,1:21:14.12,Default,,0,0,0,,同时很多的 实际上是所有的这样的“消息传递”的想法\nDialogue: 0,1:21:14.64,1:21:16.54,Default,,0,0,0,,都是被这样的问题启发的\nDialogue: 0,1:21:18.46,1:21:20.89,Default,,0,0,0,,当你真正深入进去\nDialogue: 0,1:21:20.91,1:21:24.76,Default,,0,0,0,,人们发现 代数操作的问题是如此复杂\nDialogue: 0,1:21:25.18,1:21:27.41,Default,,0,0,0,,而那些一直围绕它们工作的人们 确实就处在\nDialogue: 0,1:21:27.41,1:21:28.05,Default,,0,0,0,,你说的那种状态\nDialogue: 0,1:21:28.05,1:21:29.71,Default,,0,0,0,,他们在这些问题里艰难跋涉 时不时陷进泥里\nDialogue: 0,1:21:29.72,1:21:31.37,Default,,0,0,0,,寻找好用的工具 并试着提炼一种通用方法\nDialogue: 0,1:21:34.20,1:21:37.76,Default,,0,0,0,,学生：我想再一次回到这个复杂度的问题上来\nDialogue: 0,1:21:38.41,1:21:44.55,Default,,0,0,0,,在修改底层过程的时候 这个系统\nDialogue: 0,1:21:44.55,1:21:48.32,Default,,0,0,0,,毫无疑问 体现了非常大的灵活性\nDialogue: 0,1:21:49.71,1:21:53.40,Default,,0,0,0,,但是确实 在某种意义上讲\nDialogue: 0,1:21:53.44,1:21:55.26,Default,,0,0,0,,冻结了高层运算\nDialogue: 0,1:21:55.45,1:21:58.51,Default,,0,0,0,,或者至少如果你修改它们 你不知道\nDialogue: 0,1:21:58.51,1:22:02.06,Default,,0,0,0,,改动会体现在哪里 会怎么体现出来\nDialogue: 0,1:22:02.20,1:22:04.22,Default,,0,0,0,,教授：这个问题真是不能再好了\nDialogue: 0,1:22:04.68,1:22:05.87,Default,,0,0,0,,我要做的事情就是\nDialogue: 0,1:22:08.68,1:22:10.84,Default,,0,0,0,,如果我决定添加一个通用操作\nDialogue: 0,1:22:11.45,1:22:13.07,Default,,0,0,0,,比如equality-test\nDialogue: 0,1:22:14.96,1:22:17.15,Default,,0,0,0,,那么系统中的其它人就要查表格\nDialogue: 0,1:22:18.22,1:22:22.54,Default,,0,0,0,,来看他们需不需要支持equality-test\nDialogue: 0,1:22:24.65,1:22:26.84,Default,,0,0,0,,我们可以让它变得更加去中心化\nDialogue: 0,1:22:27.87,1:22:30.70,Default,,0,0,0,,这就是之前我提示了很多次的事情\nDialogue: 0,1:22:31.08,1:22:33.26,Default,,0,0,0,,你不但可以通过给对象添加符号标签来体现类型\nDialogue: 0,1:22:33.40,1:22:38.70,Default,,0,0,0,,而是把每一类对象接受的运算也保存在里面\nDialogue: 0,1:22:40.45,1:22:43.90,Default,,0,0,0,,那么你可以添加一个 比如说最大公约数过程\nDialogue: 0,1:22:44.43,1:22:46.81,Default,,0,0,0,,它只能计算整数\nDialogue: 0,1:22:47.40,1:22:49.21,Default,,0,0,0,,而不是对所有有理数都通用\nDialogue: 0,1:22:51.03,1:22:53.11,Default,,0,0,0,,所以这个系统可能是非常非常碎片化的\nDialogue: 0,1:22:53.11,1:22:55.66,Default,,0,0,0,,取决于你想让哪一部分比较灵活\nDialogue: 0,1:22:56.22,1:22:59.02,Default,,0,0,0,,有一系列的地方让你把这个东西放进去\nDialogue: 0,1:22:59.96,1:23:02.56,Default,,0,0,0,,但是你也指出了这种设计的弱点\nDialogue: 0,1:23:02.60,1:23:06.37,Default,,0,0,0,,就是必须在顶层 对于这些通用运算符有一些约定\nDialogue: 0,1:23:06.37,1:23:07.82,Default,,0,0,0,,或者至少人们要考虑这件事情\nDialogue: 0,1:23:08.39,1:23:10.72,Default,,0,0,0,,或者你可以决定 把这个表格设计得非常稀疏\nDialogue: 0,1:23:10.75,1:23:11.96,Default,,0,0,0,,里面只放很少的一点东西\nDialogue: 0,1:23:14.01,1:23:15.49,Default,,0,0,0,,这个游戏有很多种玩法\nDialogue: 0,1:23:19.78,1:23:20.43,Default,,0,0,0,,谢谢大家\nDialogue: 0,1:23:23.53,1:23:36.56,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:23:23.53,1:23:36.56,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec4b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nLast Style Storage: Default\nAudio File: ../../../../Movies/SICP480p/lec4b_480_muxed.mp4\nVideo File: ../../../../Movies/SICP480p/lec4b_480_muxed.mp4\nVideo AR Mode: 4\nVideo AR Value: 1.333333\nVideo Zoom Percent: 2.000000\nActive Line: 6\nVideo Position: 690\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:02.25,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:04.33,0:00:10.35,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N刘殊君（rtmagic）\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:04.33,0:00:10.35,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:11.40,0:00:16.50,Declare,,0,0,0,,{\\an2\\fad(500,500)}通用运算符\nDialogue: 0,0:00:20.18,0:00:21.84,Default,,0,0,0,,教授：到目前为止 我们已经进行了很多\nDialogue: 0,0:00:21.84,0:00:23.78,Default,,0,0,0,,关于数据抽象的讨论\nDialogue: 0,0:00:23.78,0:00:27.15,Default,,0,0,0,,关键理念就是在构造系统的时候\nDialogue: 0,0:00:27.74,0:00:32.56,Default,,0,0,0,,在其中加入水平的抽象屏障 这些抽象屏障\nDialogue: 0,0:00:33.42,0:00:39.21,Default,,0,0,0,,把你使用一个数据对象的方式\nDialogue: 0,0:00:39.93,0:00:41.18,Default,,0,0,0,,和表示它的方式区分开来\nDialogue: 0,0:00:49.40,0:00:52.03,Default,,0,0,0,,或者可以这样理解它 在上层有一个老板\nDialogue: 0,0:00:52.11,0:00:55.50,Default,,0,0,0,,想要调用某种数据对象\nDialogue: 0,0:00:57.11,0:01:02.31,Default,,0,0,0,,而在下层 George负责它的具体实现\nDialogue: 0,0:01:02.31,0:01:05.42,Default,,0,0,0,,这种把使用与表示分离的想法\nDialogue: 0,0:01:05.44,0:01:09.76,Default,,0,0,0,,可以让你分开考虑这两个问题\nDialogue: 0,0:01:10.60,0:01:14.76,Default,,0,0,0,,这是一种非常强大的编程的方法论 -- 数据抽象\nDialogue: 0,0:01:15.93,0:01:18.81,Default,,0,0,0,,但另一方面 数据抽象在那些真正复杂的系统上\nDialogue: 0,0:01:19.56,0:01:21.84,Default,,0,0,0,,并不是很有效\nDialogue: 0,0:01:22.96,0:01:27.64,Default,,0,0,0,,这个问题就出在George这里\nDialogue: 0,0:01:28.64,0:01:32.09,Default,,0,0,0,,或者说 实际上 问题就在于\nDialogue: 0,0:01:32.09,0:01:32.78,Default,,0,0,0,,现在有太多的George\nDialogue: 0,0:01:34.63,0:01:35.39,Default,,0,0,0,,具体地说\nDialogue: 0,0:01:35.39,0:01:39.18,Default,,0,0,0,,假设现在有George和Martha两个人\nDialogue: 0,0:01:41.19,0:01:44.22,Default,,0,0,0,,他们都是这个系统的开发人员\nDialogue: 0,0:01:46.04,0:01:47.29,Default,,0,0,0,,都在设计数据的表示方法\nDialogue: 0,0:01:48.41,0:01:50.67,Default,,0,0,0,,而且他们完全合不来\nDialogue: 0,0:01:51.75,0:01:53.62,Default,,0,0,0,,他们不会合作开发同一种表示方法\nDialogue: 0,0:01:54.01,0:01:55.34,Default,,0,0,0,,永远也不会\nDialogue: 0,0:01:57.48,0:01:59.72,Default,,0,0,0,,现在的问题是 假设你想要这样一个系统\nDialogue: 0,0:02:00.06,0:02:02.60,Default,,0,0,0,,在这个系统中George和Martha都为它设计了数据表示方法\nDialogue: 0,0:02:03.82,0:02:08.08,Default,,0,0,0,,但是如果你在高于这个抽象屏障的层面思考\nDialogue: 0,0:02:09.40,0:02:11.04,Default,,0,0,0,,你就不用去操心这些事情\nDialogue: 0,0:02:11.66,0:02:14.18,Default,,0,0,0,,不用操心 某个东西是到底是George做的还是Martha做的\nDialogue: 0,0:02:14.18,0:02:15.43,Default,,0,0,0,,同时你也不想让George和Martha\nDialogue: 0,0:02:15.43,0:02:16.48,Default,,0,0,0,,妨碍彼此的工作\nDialogue: 0,0:02:16.63,0:02:20.31,Default,,0,0,0,,你在设计系统的时候 不仅仅需要这些\nDialogue: 0,0:02:20.31,0:02:23.84,Default,,0,0,0,,水平的抽象屏障 同时也想设置一道\nDialogue: 0,0:02:25.82,0:02:30.64,Default,,0,0,0,,垂直的屏障 -- 来把George和Martha分离开\nDialogue: 0,0:02:32.98,0:02:35.40,Default,,0,0,0,,我们来说得再具体一点\nDialogue: 0,0:02:36.56,0:02:40.54,Default,,0,0,0,,想象一个很大的公司的人事记录\nDialogue: 0,0:02:41.18,0:02:46.11,Default,,0,0,0,,这个公司里有很多部门没什么联系\nDialogue: 0,0:02:47.90,0:02:49.71,Default,,0,0,0,,并且部门之间合作得也不太好\nDialogue: 0,0:02:50.43,0:02:57.04,Default,,0,0,0,,甚至还可以想象这个大公司就是由\nDialogue: 0,0:02:57.04,0:02:59.45,Default,,0,0,0,,很多公司组成的 而且每个公司\nDialogue: 0,0:02:59.45,0:03:00.70,Default,,0,0,0,,都有自己的一套人事记录\nDialogue: 0,0:03:03.25,0:03:06.57,Default,,0,0,0,,想象一下突然有一天 这些部门\nDialogue: 0,0:03:06.57,0:03:08.53,Default,,0,0,0,,被一种神奇的卫星网络连接起来\nDialogue: 0,0:03:08.53,0:03:10.52,Default,,0,0,0,,它们各自的数据库都被放到了一起\nDialogue: 0,0:03:12.24,0:03:13.85,Default,,0,0,0,,现在你想要\nDialogue: 0,0:03:14.84,0:03:16.33,Default,,0,0,0,,在公司的任何地方\nDialogue: 0,0:03:17.26,0:03:23.13,Default,,0,0,0,,都能够知道 哦 某一条人事记录里的\nDialogue: 0,0:03:23.13,0:03:23.87,Default,,0,0,0,,“姓名”是什么\nDialogue: 0,0:03:26.30,0:03:29.15,Default,,0,0,0,,或者一条记录里的“工作”是什么\nDialogue: 0,0:03:30.54,0:03:34.40,Default,,0,0,0,,同时又不需要担心每一个部门\nDialogue: 0,0:03:34.84,0:03:36.76,Default,,0,0,0,,对于人事记录的格式\nDialogue: 0,0:03:36.76,0:03:39.37,Default,,0,0,0,,有着完全不同的习惯\nDialogue: 0,0:03:41.58,0:03:43.26,Default,,0,0,0,,从你的视角上你不想去了解这些东西\nDialogue: 0,0:03:44.96,0:03:47.92,Default,,0,0,0,,那么怎么才能做到这样呢？\nDialogue: 0,0:03:48.43,0:03:52.41,Default,,0,0,0,,当然 一种方法是下发一个告示\nDialogue: 0,0:03:52.64,0:03:56.29,Default,,0,0,0,,来通知所有人把他们的记录格式\nDialogue: 0,0:03:56.29,0:03:57.24,Default,,0,0,0,,都改成某种标准的格式\nDialogue: 0,0:03:58.07,0:04:00.12,Default,,0,0,0,,人们经常这样做 但都没有成功\nDialogue: 0,0:04:01.82,0:04:07.34,Default,,0,0,0,,另一个办法则是重新安排这些记录\nDialogue: 0,0:04:08.33,0:04:09.90,Default,,0,0,0,,让它们中间有这种垂直的抽象屏障\nDialogue: 0,0:04:11.25,0:04:14.40,Default,,0,0,0,,当你查询一份人事档案里的姓名的时候\nDialogue: 0,0:04:14.43,0:04:17.97,Default,,0,0,0,,不管它是什么格式 name这个过程都能设法\nDialogue: 0,0:04:17.97,0:04:19.42,Default,,0,0,0,,搞清楚怎么正确地完成这件事\nDialogue: 0,0:04:22.73,0:04:25.53,Default,,0,0,0,,我们把name叫做一个 所谓的“通用运算符”\nDialogue: 0,0:04:26.26,0:04:30.06,Default,,0,0,0,,通用运算符意味着它会根据数据的种类\nDialogue: 0,0:04:30.06,0:04:31.69,Default,,0,0,0,,准确地做出对应的操作\nDialogue: 0,0:04:33.65,0:04:36.62,Default,,0,0,0,,更进一步讲 你想让这个系统在\nDialogue: 0,0:04:36.92,0:04:39.79,Default,,0,0,0,,下次公司里多了一个新的人员划分的时候\nDialogue: 0,0:04:42.51,0:04:45.64,Default,,0,0,0,,人们连接系统的方法不会有很大的变化\nDialogue: 0,0:04:45.64,0:04:50.11,Default,,0,0,0,,并且公司里剩下的部门\nDialogue: 0,0:04:50.11,0:04:52.01,Default,,0,0,0,,要把它们的人员记录添加到这个系统\nDialogue: 0,0:04:52.27,0:04:53.93,Default,,0,0,0,,也不需要做什么大的修改\nDialogue: 0,0:04:55.52,0:04:57.52,Default,,0,0,0,,那么这就是你应该考虑的问题\nDialogue: 0,0:04:58.70,0:05:00.77,Default,,0,0,0,,或者这就是你的工作\nDialogue: 0,0:05:00.77,0:05:03.77,Default,,0,0,0,,要让系统可以用最少的改动来拥抱变化\nDialogue: 0,0:05:05.98,0:05:08.12,Default,,0,0,0,,这就是我们今天要讨论的问题\nDialogue: 0,0:05:09.44,0:05:14.22,Default,,0,0,0,,你脑子里应该有这个分布式的人事档案系统\nDialogue: 0,0:05:14.24,0:05:16.62,Default,,0,0,0,,但是实际上 我今天要讨论的是一个\nDialogue: 0,0:05:16.62,0:05:18.48,Default,,0,0,0,,比那要更加自成体系的问题\nDialogue: 0,0:05:19.29,0:05:21.76,Default,,0,0,0,,我觉得用它可以把事情说得更清楚一点\nDialogue: 0,0:05:21.87,0:05:26.01,Default,,0,0,0,,我们要讨论的是 复数域上的算术系统\nDialogue: 0,0:05:27.77,0:05:28.92,Default,,0,0,0,,我们来看看这个系统\nDialogue: 0,0:05:30.69,0:05:31.74,Default,,0,0,0,,来复习一下\nDialogue: 0,0:05:32.04,0:05:33.53,Default,,0,0,0,,什么是“复数”\nDialogue: 0,0:05:35.25,0:05:38.22,Default,,0,0,0,,复数z可以看做复平面上的一点\nDialogue: 0,0:05:39.37,0:05:47.19,Default,,0,0,0,,我们将复数表示为实数部分和虚数部分\nDialogue: 0,0:05:47.19,0:05:50.83,Default,,0,0,0,,所以如果这个是复数z 它的实部是这么多\nDialogue: 0,0:05:51.50,0:05:53.24,Default,,0,0,0,,它的虚部是那么多\nDialogue: 0,0:05:54.33,0:05:56.44,Default,,0,0,0,,我们就可以记z=x+iy\nDialogue: 0,0:05:59.11,0:06:03.21,Default,,0,0,0,,还有另一种方法来表示一个复数 比如说\nDialogue: 0,0:06:03.21,0:06:09.00,Default,,0,0,0,,这个点与原点的距离是多少 在原点的什么角度上\nDialogue: 0,0:06:11.32,0:06:16.67,Default,,0,0,0,,像这样 复数也可以表示为半径乘以一个角度\nDialogue: 0,0:06:19.52,0:06:21.92,Default,,0,0,0,,第一种表示法称为 直角坐标系表示\nDialogue: 0,0:06:22.59,0:06:25.45,Default,,0,0,0,,或者说实部-虚部表示\nDialogue: 0,0:06:26.20,0:06:30.04,Default,,0,0,0,,而后一种是用模和辐角两部分的极坐标表示\nDialogue: 0,0:06:30.04,0:06:31.48,Default,,0,0,0,,并且如果你知道了一个复数的实部和虚部\nDialogue: 0,0:06:31.53,0:06:33.36,Default,,0,0,0,,你就能计算出它的模和辐角\nDialogue: 0,0:06:33.72,0:06:36.97,Default,,0,0,0,,如果知道了x和y 就能用这个式子算出r\nDialogue: 0,0:06:37.19,0:06:39.48,Default,,0,0,0,,等于两个数平方和的平方根 然后就可以\nDialogue: 0,0:06:39.48,0:06:40.76,Default,,0,0,0,,用反三角函数算出辐角的值\nDialogue: 0,0:06:41.42,0:06:44.42,Default,,0,0,0,,或者反过来 如果你知道了r和A\nDialogue: 0,0:06:44.42,0:06:45.31,Default,,0,0,0,,你也能计算出x和y\nDialogue: 0,0:06:45.80,0:06:49.43,Default,,0,0,0,,x=r·cos(A) y=r·sin(A)\nDialogue: 0,0:06:51.34,0:06:53.66,Default,,0,0,0,,这是表示复数的两种不同方法\nDialogue: 0,0:06:54.13,0:06:57.15,Default,,0,0,0,,分别是极坐标形式和直角坐标形式\nDialogue: 0,0:06:57.15,0:06:58.12,Default,,0,0,0,,我们要设计的是\nDialogue: 0,0:06:58.32,0:07:01.32,Default,,0,0,0,,一个复数域上的算术系统\nDialogue: 0,0:07:03.95,0:07:05.12,Default,,0,0,0,,换句话讲 我们要\nDialogue: 0,0:07:05.58,0:07:06.99,Default,,0,0,0,,就像之前课上有理数运算的例子一样\nDialogue: 0,0:07:07.38,0:07:10.20,Default,,0,0,0,,是构造一个叫做+c的操作\nDialogue: 0,0:07:10.73,0:07:13.90,Default,,0,0,0,,它将两个复数然后把它们相加、相减\nDialogue: 0,0:07:14.35,0:07:16.94,Default,,0,0,0,,相乘或者相除\nDialogue: 0,0:07:20.73,0:07:25.28,Default,,0,0,0,,那么我们要用到一点点数学\nDialogue: 0,0:07:25.28,0:07:28.36,Default,,0,0,0,,对它们进行操作的具体的算式是什么\nDialogue: 0,0:07:30.41,0:07:31.92,Default,,0,0,0,,它们是怎么得出来的 并不重要\nDialogue: 0,0:07:34.00,0:07:35.79,Default,,0,0,0,,我们只是用它们实现运算\nDialogue: 0,0:07:35.80,0:07:37.95,Default,,0,0,0,,如果想要把两个复数相加\nDialogue: 0,0:07:39.13,0:07:42.66,Default,,0,0,0,,可以很容易地获取它们的实部和虚部\nDialogue: 0,0:07:42.66,0:07:45.93,Default,,0,0,0,,两个复数的和的实部\nDialogue: 0,0:07:47.72,0:07:49.72,Default,,0,0,0,,z1+z2的实部\nDialogue: 0,0:07:50.06,0:07:54.64,Default,,0,0,0,,就是z1的实部加上z2的实部\nDialogue: 0,0:07:57.82,0:08:01.60,Default,,0,0,0,,然后z1+z2的虚部也就是\nDialogue: 0,0:08:01.74,0:08:05.66,Default,,0,0,0,,z1的虚部加上z2的虚部\nDialogue: 0,0:08:07.41,0:08:09.48,Default,,0,0,0,,所以复数相加是非常简单的事情\nDialogue: 0,0:08:09.48,0:08:10.99,Default,,0,0,0,,你只要把各个部分分别加起来\nDialogue: 0,0:08:11.31,0:08:13.18,Default,,0,0,0,,然后用结果构建一个新的复数\nDialogue: 0,0:08:13.37,0:08:14.73,Default,,0,0,0,,如果你想要让复数相乘\nDialogue: 0,0:08:15.53,0:08:17.82,Default,,0,0,0,,那么在极坐标下运算会方便很多\nDialogue: 0,0:08:17.82,0:08:20.38,Default,,0,0,0,,因为对于两个复数\nDialogue: 0,0:08:20.40,0:08:26.54,Default,,0,0,0,,两复数积之模 就是它们各自的模的乘积\nDialogue: 0,0:08:28.85,0:08:33.88,Default,,0,0,0,,它们的积的辐角 就是两个辐角的和\nDialogue: 0,0:08:35.80,0:08:40.54,Default,,0,0,0,,这就是复数域上的运算所需的数学知识\nDialogue: 0,0:08:40.54,0:08:42.38,Default,,0,0,0,,我们来想一想具体的实现\nDialogue: 0,0:08:43.72,0:08:47.39,Default,,0,0,0,,我们就像之前运算有理数那样做\nDialogue: 0,0:08:49.84,0:08:53.47,Default,,0,0,0,,来到底层 假设有一些构造函数和选择函数\nDialogue: 0,0:08:53.76,0:08:54.52,Default,,0,0,0,,它们应该是什么样子呢\nDialogue: 0,0:08:55.33,0:08:58.16,Default,,0,0,0,,假设我们制造了一些表示数据对象的“云彩”\nDialogue: 0,0:08:58.54,0:09:00.78,Default,,0,0,0,,也就是用某种形式表示的复数\nDialogue: 0,0:09:01.79,0:09:04.67,Default,,0,0,0,,我们能从这个复数中得到它的实部\nDialogue: 0,0:09:05.52,0:09:09.64,Default,,0,0,0,,可以获得 虚部、模、或者辐角\nDialogue: 0,0:09:12.15,0:09:14.01,Default,,0,0,0,,然后我们需要一种方法来构造复数\nDialogue: 0,0:09:14.03,0:09:15.64,Default,,0,0,0,,不仅要有选择函数 还要有构造函数\nDialogue: 0,0:09:16.80,0:09:19.52,Default,,0,0,0,,那么假设我们有一个叫做make-rectangular的过程\nDialogue: 0,0:09:19.53,0:09:24.27,Default,,0,0,0,,这个过程的功能是接受一个实部\nDialogue: 0,0:09:24.51,0:09:29.36,Default,,0,0,0,,和一个虚部 然后把这两个部分组合成一个复数\nDialogue: 0,0:09:31.92,0:09:35.01,Default,,0,0,0,,同样我们也可以构造一个make-polar过程\nDialogue: 0,0:09:35.01,0:09:37.85,Default,,0,0,0,,它接受一个模和一个辐角\nDialogue: 0,0:09:40.83,0:09:43.90,Default,,0,0,0,,然后用这两个值 组成一个复数\nDialogue: 0,0:09:44.68,0:09:45.46,Default,,0,0,0,,那么这个系统\nDialogue: 0,0:09:45.46,0:09:47.77,Default,,0,0,0,,里面会有两个构造函数和四个选择函数\nDialogue: 0,0:09:48.91,0:09:55.15,Default,,0,0,0,,现在 就像之前课程中那样 我们基于这个抽象的数据结构\nDialogue: 0,0:09:55.15,0:09:59.22,Default,,0,0,0,,继续实现复数的各种运算\nDialogue: 0,0:09:59.22,0:10:02.30,Default,,0,0,0,,而这些Lisp代码\nDialogue: 0,0:10:03.23,0:10:07.47,Default,,0,0,0,,是从我之前写的算术公式“翻译”而来的\nDialogue: 0,0:10:08.06,0:10:09.98,Default,,0,0,0,,如果我想把两个复数相加\nDialogue: 0,0:10:11.76,0:10:15.56,Default,,0,0,0,,我就要用一个实部和一个虚部构造一个复数\nDialogue: 0,0:10:16.72,0:10:19.02,Default,,0,0,0,,这个新的复数的实部是\nDialogue: 0,0:10:19.40,0:10:21.80,Default,,0,0,0,,两个复数的实部的和\nDialogue: 0,0:10:23.31,0:10:25.37,Default,,0,0,0,,它的虚数部分是\nDialogue: 0,0:10:25.40,0:10:27.52,Default,,0,0,0,,两个复数的虚部的和\nDialogue: 0,0:10:30.31,0:10:32.09,Default,,0,0,0,,我把它们放到一起 构造出一个复数\nDialogue: 0,0:10:32.16,0:10:34.44,Default,,0,0,0,,这就是实现复数加法的方法\nDialogue: 0,0:10:35.78,0:10:38.49,Default,,0,0,0,,减法实际上是一样的\nDialogue: 0,0:10:39.65,0:10:42.97,Default,,0,0,0,,只需要把各个部分相加变成把它们相减\nDialogue: 0,0:10:45.14,0:10:47.07,Default,,0,0,0,,要把两个复数相乘\nDialogue: 0,0:10:47.74,0:10:49.02,Default,,0,0,0,,要用另外一个式子\nDialogue: 0,0:10:49.27,0:10:53.84,Default,,0,0,0,,我会用一个模和一个辐角来构造一个复数\nDialogue: 0,0:10:55.35,0:10:56.44,Default,,0,0,0,,z1*z2的模\nDialogue: 0,0:10:56.65,0:11:00.97,Default,,0,0,0,,就是z1的模乘以z2的模\nDialogue: 0,0:11:03.71,0:11:05.93,Default,,0,0,0,,而z1*z2的辐角则是\nDialogue: 0,0:11:06.16,0:11:08.51,Default,,0,0,0,,z1的辐角加上z2的辐角\nDialogue: 0,0:11:09.62,0:11:10.96,Default,,0,0,0,,那么这就是乘法的实现\nDialogue: 0,0:11:11.23,0:11:12.25,Default,,0,0,0,,然后是除法\nDialogue: 0,0:11:14.27,0:11:15.90,Default,,0,0,0,,除法和乘法几乎是一样的\nDialogue: 0,0:11:17.37,0:11:19.58,Default,,0,0,0,,我只要把两个模相除 把辐角相减就可以了\nDialogue: 0,0:11:28.36,0:11:30.46,Default,,0,0,0,,现在我已经实现了各种运算\nDialogue: 0,0:11:31.87,0:11:33.64,Default,,0,0,0,,然后我们做什么\nDialogue: 0,0:11:33.64,0:11:34.52,Default,,0,0,0,,我们把George叫来\nDialogue: 0,0:11:36.06,0:11:38.79,Default,,0,0,0,,我们完成了“使用”的部分 现在应该考虑“表示”了\nDialogue: 0,0:11:38.80,0:11:40.94,Default,,0,0,0,,我们叫来George然后对他说\nDialogue: 0,0:11:40.97,0:11:43.61,Default,,0,0,0,,“为我们设计一个一套复数的表示方法”\nDialogue: 0,0:11:45.25,0:11:47.44,Default,,0,0,0,,很好\nDialogue: 0,0:11:47.77,0:11:52.66,Default,,0,0,0,,George可能会说 我们把一个复数\nDialogue: 0,0:11:52.66,0:11:57.15,Default,,0,0,0,,实现为 一个由实部和虚部组成的序对\nDialogue: 0,0:11:57.20,0:12:02.62,Default,,0,0,0,,那么如果我想用某个实部和虚部来构造复数\nDialogue: 0,0:12:03.36,0:12:05.55,Default,,0,0,0,,我只需要把它们cons起来即可 这样可以--\nDialogue: 0,0:12:06.03,0:12:08.11,Default,,0,0,0,,这就是George表示复数的方法\nDialogue: 0,0:12:09.78,0:12:12.42,Default,,0,0,0,,那么如果我想获得它的实部 我只需要\nDialogue: 0,0:12:12.42,0:12:14.12,Default,,0,0,0,,提取出序对的car部分 -- 它的首部分\nDialogue: 0,0:12:14.35,0:12:16.67,Default,,0,0,0,,如果我想要得到虚部 我就提取出它的cdr部分\nDialogue: 0,0:12:19.64,0:12:21.77,Default,,0,0,0,,那对于模和辐角 又该如何取得呢？\nDialogue: 0,0:12:22.22,0:12:25.75,Default,,0,0,0,,如果我想取得某个复数的模\nDialogue: 0,0:12:25.75,0:12:32.30,Default,,0,0,0,,我需要计算该复数car与cdr的平方和的算术平方根\nDialogue: 0,0:12:33.79,0:12:39.26,Default,,0,0,0,,如果我想得到辐角 我就计算它的cdr与car比值的反正切\nDialogue: 0,0:12:39.53,0:12:42.86,Default,,0,0,0,,这个Lisp过程用于计算反正切\nDialogue: 0,0:12:44.97,0:12:48.59,Default,,0,0,0,,要是有人给我一个模和辐角\nDialogue: 0,0:12:48.94,0:12:50.56,Default,,0,0,0,,并说：“给我构造一个复数”\nDialogue: 0,0:12:50.89,0:12:56.24,Default,,0,0,0,,用它们计算出实部 r*cos(a) 和虚部 r*sin(a)\nDialogue: 0,0:12:57.77,0:12:59.05,Default,,0,0,0,,连接成一个序对就行了\nDialogue: 0,0:13:01.46,0:13:02.26,Default,,0,0,0,,完成了\nDialogue: 0,0:13:02.26,0:13:04.75,Default,,0,0,0,,实际上我做的事情 在概念上讲\nDialogue: 0,0:13:06.89,0:13:09.37,Default,,0,0,0,,和我们之前提过的有理数的表示\nDialogue: 0,0:13:10.60,0:13:12.44,Default,,0,0,0,,是完全没有区别的\nDialogue: 0,0:13:12.75,0:13:13.91,Default,,0,0,0,,它们的思想相同\nDialogue: 0,0:13:13.91,0:13:16.28,Default,,0,0,0,,实现具体过程 选择一种表示方法\nDialogue: 0,0:13:18.07,0:13:18.65,Default,,0,0,0,,没有什么不同\nDialogue: 0,0:13:20.07,0:13:21.56,Default,,0,0,0,,现在我们来关心一下Martha\nDialogue: 0,0:13:23.21,0:13:24.52,Default,,0,0,0,,嗯 Martha的想法不太一样\nDialogue: 0,0:13:26.67,0:13:28.57,Default,,0,0,0,,她不想把复数表示成\nDialogue: 0,0:13:28.59,0:13:30.90,Default,,0,0,0,,由实部和虚部组成的序对\nDialogue: 0,0:13:30.90,0:13:34.17,Default,,0,0,0,,她比较喜欢把它们表示成\nDialogue: 0,0:13:34.17,0:13:37.69,Default,,0,0,0,,由模和辐角组成的序对\nDialogue: 0,0:13:39.55,0:13:42.13,Default,,0,0,0,,那么如果我们没有让George而是让Martha\nDialogue: 0,0:13:42.13,0:13:43.74,Default,,0,0,0,,来设计复数的表示方法 我们就会得到这样的东西\nDialogue: 0,0:13:44.57,0:13:47.16,Default,,0,0,0,,有一个make-polar过程\nDialogue: 0,0:13:47.16,0:13:50.22,Default,,0,0,0,,当然了 有了一个模和一个辐角之后\nDialogue: 0,0:13:50.22,0:13:53.07,Default,,0,0,0,,我们只要把它们组合成一个序对就行了\nDialogue: 0,0:13:55.43,0:13:57.68,Default,,0,0,0,,如果你想取得复数的模 那很简单\nDialogue: 0,0:13:58.24,0:13:59.37,Default,,0,0,0,,你只需要取序对的car部分即可\nDialogue: 0,0:13:59.78,0:14:02.67,Default,,0,0,0,,当然 想取得复数的辐角 那也很简单\nDialogue: 0,0:14:02.67,0:14:03.63,Default,,0,0,0,,只需取cdr部分即可\nDialogue: 0,0:14:04.81,0:14:07.02,Default,,0,0,0,,但是如果你想要获得实部和虚部\nDialogue: 0,0:14:07.42,0:14:08.49,Default,,0,0,0,,那就得费点力气\nDialogue: 0,0:14:08.88,0:14:14.58,Default,,0,0,0,,想得到实部 你就得计算r*cos(a)\nDialogue: 0,0:14:14.58,0:14:19.99,Default,,0,0,0,,换句话讲 用序对的car部分去乘以\nDialogue: 0,0:14:19.99,0:14:20.95,Default,,0,0,0,,cdr部分的余弦值\nDialogue: 0,0:14:20.95,0:14:26.23,Default,,0,0,0,,然后你就算出了r*cos(a)\nDialogue: 0,0:14:26.54,0:14:27.48,Default,,0,0,0,,这就是这个复数的实部\nDialogue: 0,0:14:28.33,0:14:31.40,Default,,0,0,0,,要是想算出它的虚部 用r乘以sin(a)就可以了\nDialogue: 0,0:14:32.66,0:14:37.93,Default,,0,0,0,,现在如果我给你一个实部和虚部 然后说\nDialogue: 0,0:14:37.93,0:14:42.03,Default,,0,0,0,,用它们给我构造一个复数\nDialogue: 0,0:14:42.03,0:14:44.17,Default,,0,0,0,,那就要先算出\nDialogue: 0,0:14:44.17,0:14:45.54,Default,,0,0,0,,模和辐角是多少\nDialogue: 0,0:14:45.54,0:14:47.85,Default,,0,0,0,,模是实部和虚部的平方和的算术平方根\nDialogue: 0,0:14:48.09,0:14:49.23,Default,,0,0,0,,辐角是这个反正切\nDialogue: 0,0:14:49.23,0:14:50.22,Default,,0,0,0,,我用这两个数构造一个序对\nDialogue: 0,0:14:52.09,0:14:54.17,Default,,0,0,0,,以上就是Martha的想法\nDialogue: 0,0:14:56.69,0:14:57.37,Default,,0,0,0,,那么哪种比较好呢？\nDialogue: 0,0:14:59.68,0:15:03.15,Default,,0,0,0,,如果你需要做很多加法 那么George的比较好\nDialogue: 0,0:15:03.16,0:15:05.61,Default,,0,0,0,,因为你总是要用到复数的实部和虚部\nDialogue: 0,0:15:05.85,0:15:08.40,Default,,0,0,0,,如果你大多数时间都是在做乘法\nDialogue: 0,0:15:09.48,0:15:11.14,Default,,0,0,0,,那可能Martha的办法就要好一些\nDialogue: 0,0:15:11.14,0:15:14.84,Default,,0,0,0,,又或者 -- 这就是问题所在了 -- 你决定不了\nDialogue: 0,0:15:16.59,0:15:22.32,Default,,0,0,0,,或者出于某些个人原因 你想让它们同时存在\nDialogue: 0,0:15:23.48,0:15:26.76,Default,,0,0,0,,也可能你是真的无法决定你更喜欢哪种表示法\nDialogue: 0,0:15:28.56,0:15:32.32,Default,,0,0,0,,回到这个话题 我们真正想要的是这样一个系统\nDialogue: 0,0:15:32.65,0:15:36.17,Default,,0,0,0,,这里面 既有George 他实现了\nDialogue: 0,0:15:36.83,0:15:39.64,Default,,0,0,0,,复数的直角坐标表示\nDialogue: 0,0:15:41.47,0:15:44.25,Default,,0,0,0,,又有Martha 她实现了复数的极坐标表示\nDialogue: 0,0:15:46.12,0:15:49.69,Default,,0,0,0,,然后我们有各种运算\nDialogue: 0,0:15:50.28,0:15:56.89,Default,,0,0,0,,用来对复数进行加减乘除\nDialogue: 0,0:15:57.56,0:15:58.76,Default,,0,0,0,,那么这些运算\nDialogue: 0,0:15:59.34,0:16:02.79,Default,,0,0,0,,不应该被系统中同时存在的两种\nDialogue: 0,0:16:02.79,0:16:03.98,Default,,0,0,0,,互不兼容的复数表示方法影响\nDialogue: 0,0:16:04.41,0:16:08.33,Default,,0,0,0,,或者说 我们不光有像这样的一个抽象屏障\nDialogue: 0,0:16:09.64,0:16:11.84,Default,,0,0,0,,它里面有real-part\nDialogue: 0,0:16:15.77,0:16:21.71,Default,,0,0,0,,还有 IMAG-PART、MAG 和 ANG 等几个过程\nDialogue: 0,0:16:23.83,0:16:25.36,Default,,0,0,0,,不光有一层抽象屏障\nDialogue: 0,0:16:25.39,0:16:28.38,Default,,0,0,0,,把实际的数据表示隐藏起来\nDialogue: 0,0:16:29.10,0:16:31.52,Default,,0,0,0,,还有一层垂直的屏障\nDialogue: 0,0:16:32.19,0:16:35.02,Default,,0,0,0,,容许不同的表示方法彼此共存\nDialogue: 0,0:16:35.87,0:16:37.40,Default,,0,0,0,,而不互相干预\nDialogue: 0,0:16:38.57,0:16:41.07,Default,,0,0,0,,我们的想法是把这些东西\nDialogue: 0,0:16:41.90,0:16:44.12,Default,,0,0,0,,REAL-PART、IMAG-PART、MAG、ANG 这些过程\nDialogue: 0,0:16:44.12,0:16:46.49,Default,,0,0,0,,设计成通用运算符\nDialogue: 0,0:16:47.31,0:16:49.45,Default,,0,0,0,,如果你调用real-part过程 它就会判断\nDialogue: 0,0:16:49.98,0:16:51.31,Default,,0,0,0,,要在哪一种表示方法中寻找它\nDialogue: 0,0:16:53.88,0:16:55.10,Default,,0,0,0,,那么我们怎么做到这一点呢\nDialogue: 0,0:16:56.84,0:16:59.23,Default,,0,0,0,,实际上有一个很容易想到的办法\nDialogue: 0,0:16:59.84,0:17:01.68,Default,,0,0,0,,如果你习惯了思考复数的模式\nDialogue: 0,0:17:02.52,0:17:04.44,Default,,0,0,0,,如果你已经习惯了复合数据的思想\nDialogue: 0,0:17:06.33,0:17:10.99,Default,,0,0,0,,假设你只要观察一个复数\nDialogue: 0,0:17:12.17,0:17:13.95,Default,,0,0,0,,就能看出它是被George还是Martha构造出来的\nDialogue: 0,0:17:15.79,0:17:18.90,Default,,0,0,0,,换句话说 在你眼前漂浮的这些东西\nDialogue: 0,0:17:18.90,0:17:20.91,Default,,0,0,0,,不是普通的复数 对吗？\nDialogue: 0,0:17:20.91,0:17:22.94,Default,,0,0,0,,它们是被某个设计者“构想”出来的\nDialogue: 0,0:17:24.39,0:17:28.04,Default,,0,0,0,,当考察一个复数 我们会发现它“不仅仅”是个复数\nDialogue: 0,0:17:28.04,0:17:29.16,Default,,0,0,0,,它上面有一个标签\nDialogue: 0,0:17:29.19,0:17:30.75,Default,,0,0,0,,写着这个是由Martha制造的\nDialogue: 0,0:17:31.45,0:17:34.22,Default,,0,0,0,,或者这个是由George制造的\nDialogue: 0,0:17:34.48,0:17:35.39,Default,,0,0,0,,对吧？它们被签了名字\nDialogue: 0,0:17:36.86,0:17:40.15,Default,,0,0,0,,在这之后 无论何时我们看见一个复数\nDialogue: 0,0:17:40.15,0:17:45.48,Default,,0,0,0,,我们只要看它的标签  然后我们就能知道\nDialogue: 0,0:17:45.80,0:17:46.72,Default,,0,0,0,,应该怎么对它进行运算\nDialogue: 0,0:17:48.03,0:17:51.19,Default,,0,0,0,,或者说 我们想要的不只是普通的数据对象\nDialogue: 0,0:17:51.19,0:17:54.37,Default,,0,0,0,,我们引入一个概念：带类型的数据\nDialogue: 0,0:17:59.76,0:18:02.81,Default,,0,0,0,,带类型的数据就意味着 这里有一朵“云彩”\nDialogue: 0,0:18:03.94,0:18:08.93,Default,,0,0,0,,它里面有我们之前所说的那种\nDialogue: 0,0:18:08.93,0:18:09.90,Default,,0,0,0,,普通的数据对象\nDialogue: 0,0:18:13.18,0:18:16.54,Default,,0,0,0,,这是它的内容 就是实际的数据\nDialogue: 0,0:18:19.32,0:18:21.56,Default,,0,0,0,,它里面还有一个叫做类型的东西\nDialogue: 0,0:18:22.56,0:18:25.24,Default,,0,0,0,,被George或者Martha签了名\nDialogue: 0,0:18:25.99,0:18:28.27,Default,,0,0,0,,那么我们现在就要从无类型的数据进入带类型数据的领域\nDialogue: 0,0:18:31.95,0:18:32.71,Default,,0,0,0,,我们怎么构造它\nDialogue: 0,0:18:32.71,0:18:33.50,Default,,0,0,0,,那很简单\nDialogue: 0,0:18:33.84,0:18:35.32,Default,,0,0,0,,我们知道怎么构造“云彩”\nDialogue: 0,0:18:35.80,0:18:36.88,Default,,0,0,0,,我们用序对来组成它们\nDialogue: 0,0:18:37.92,0:18:41.82,Default,,0,0,0,,那么我们就有了一种方法来表示带类型的数据\nDialogue: 0,0:18:43.51,0:18:49.64,Default,,0,0,0,,这种方法叫做 把类型附加到内容上\nDialogue: 0,0:18:49.69,0:18:50.64,Default,,0,0,0,,用cons就可以做到\nDialogue: 0,0:18:51.64,0:18:54.11,Default,,0,0,0,,然后面对一个带类型的数据 我们就可以知道它的类型\nDialogue: 0,0:18:55.21,0:18:56.00,Default,,0,0,0,,也就是序对的car部分\nDialogue: 0,0:18:56.29,0:18:58.30,Default,,0,0,0,,我们也可以知道它的具体内容 就是它的cdr部分\nDialogue: 0,0:18:59.96,0:19:04.28,Default,,0,0,0,,我们用这种方法使用带类型的数据\nDialogue: 0,0:19:05.29,0:19:07.26,Default,,0,0,0,,面对一段类型数据就能知道它是什么类型\nDialogue: 0,0:19:07.52,0:19:09.26,Default,,0,0,0,,那么我们现在有了几种判断类型的谓词\nDialogue: 0,0:19:10.51,0:19:13.73,Default,,0,0,0,,举例来讲 想要知道一个复数\nDialogue: 0,0:19:13.73,0:19:16.86,Default,,0,0,0,,是不是George构造的 是不是直角坐标表示的 我们只需要看\nDialogue: 0,0:19:16.86,0:19:21.85,Default,,0,0,0,,它的“类型”是不是rectangular这个符号\nDialogue: 0,0:19:23.68,0:19:25.05,Default,,0,0,0,,对吧？检查 rectangular 符号\nDialogue: 0,0:19:27.20,0:19:30.33,Default,,0,0,0,,同理 想要知道一个复数是不是Martha构造的\nDialogue: 0,0:19:30.33,0:19:33.42,Default,,0,0,0,,我们就看它的“类型”是不是polar这个符号\nDialogue: 0,0:19:36.46,0:19:39.21,Default,,0,0,0,,那么这就是一种识别数字的类型的方法\nDialogue: 0,0:19:40.75,0:19:42.81,Default,,0,0,0,,现在来想想 怎么用这种方法来构建系统\nDialogue: 0,0:19:43.87,0:19:46.73,Default,,0,0,0,,我们假设George和Martha分别在做各自的工作\nDialogue: 0,0:19:47.36,0:19:52.64,Default,,0,0,0,,每一个人都设计了他们的复数表示程序包\nDialogue: 0,0:19:52.64,0:19:58.52,Default,,0,0,0,,他们怎么让自己的东西成为系统的一部分\nDialogue: 0,0:19:58.73,0:20:00.14,Default,,0,0,0,,和对方友好共存呢\nDialogue: 0,0:20:00.14,0:20:02.11,Default,,0,0,0,,那其实非常简单\nDialogue: 0,0:20:02.72,0:20:04.51,Default,,0,0,0,,回忆一下 George做了这个程序包\nDialogue: 0,0:20:05.97,0:20:08.48,Default,,0,0,0,,这就是George的程序包 或者说它的一部分\nDialogue: 0,0:20:08.98,0:20:11.15,Default,,0,0,0,,然后红色下划线标出的部分是他需要做的修改\nDialogue: 0,0:20:12.09,0:20:16.43,Default,,0,0,0,,之前 当George用x和y构建了一个复数的时候\nDialogue: 0,0:20:17.52,0:20:19.85,Default,,0,0,0,,他只是把它们组合成一个序对\nDialogue: 0,0:20:20.93,0:20:23.39,Default,,0,0,0,,现在唯一不同的地方是 他给它们打了标签\nDialogue: 0,0:20:24.09,0:20:28.08,Default,,0,0,0,,他把类型 -- 也就是 rectangular符号 -- 附加到这个序对上面\nDialogue: 0,0:20:30.60,0:20:33.26,Default,,0,0,0,,剩下的事情都和之前一样 除了一点\nDialogue: 0,0:20:33.92,0:20:38.06,Default,,0,0,0,,就是George和Martha的程序都有叫做real-part和imaginary-part的过程\nDialogue: 0,0:20:38.70,0:20:42.96,Default,,0,0,0,,为了这些过程存在于在同一个Lisp环境中\nDialogue: 0,0:20:44.22,0:20:45.92,Default,,0,0,0,,George就要修改他的过程名字\nDialogue: 0,0:20:45.92,0:20:49.14,Default,,0,0,0,,那么我们说 这是George的real-part过程\nDialogue: 0,0:20:49.14,0:20:51.16,Default,,0,0,0,,叫做real-part-rectangular过程\nDialogue: 0,0:20:51.48,0:20:54.06,Default,,0,0,0,,还有 imag-part-rectangular过程\nDialogue: 0,0:20:55.42,0:20:57.24,Default,,0,0,0,,那么这里是George的程序包剩下的部分\nDialogue: 0,0:20:59.13,0:21:02.06,Default,,0,0,0,,他已经有了magnitude和angle过程 只要把它们改名\nDialogue: 0,0:21:02.06,0:21:04.16,Default,,0,0,0,,叫magnitude-rectangular和angle-rectangular就好了\nDialogue: 0,0:21:06.08,0:21:07.96,Default,,0,0,0,,Martha要做的事情基本相同\nDialogue: 0,0:21:09.86,0:21:16.22,Default,,0,0,0,,在这之前 当她用模和辐角构造复数的时候\nDialogue: 0,0:21:18.14,0:21:19.27,Default,,0,0,0,,她只是把这两个东西cons起来\nDialogue: 0,0:21:19.27,0:21:20.86,Default,,0,0,0,,现在她额外附加类型 polar\nDialogue: 0,0:21:23.95,0:21:25.61,Default,,0,0,0,,然后修改过程的名字\nDialogue: 0,0:21:25.66,0:21:29.85,Default,,0,0,0,,来避免保证她的real-part过程和George的产生冲突\nDialogue: 0,0:21:30.71,0:21:32.99,Default,,0,0,0,,分别改为real-part-polar和imaginary-part-polar\nDialogue: 0,0:21:34.54,0:21:38.06,Default,,0,0,0,,magnitude-polar和angle-polar这四个过程\nDialogue: 0,0:21:45.00,0:21:46.13,Default,,0,0,0,,现在我们的系统\nDialogue: 0,0:21:46.13,0:21:47.92,Default,,0,0,0,,在它里面既有George又有Martha\nDialogue: 0,0:21:49.16,0:21:51.68,Default,,0,0,0,,然后现在我们需要一个经理来对类型进行判断\nDialogue: 0,0:21:52.83,0:21:56.48,Default,,0,0,0,,那么在George和Martha给我们提供了类型数据之后\nDialogue: 0,0:21:57.05,0:21:59.40,Default,,0,0,0,,这个系统现在怎么工作呢？\nDialogue: 0,0:22:00.53,0:22:04.30,Default,,0,0,0,,我们手里有的 是一堆通用选择函数\nDialogue: 0,0:22:05.26,0:22:10.63,Default,,0,0,0,,用于复数的通用选择函数比如 real-part、imag-part、magnitude和angle等\nDialogue: 0,0:22:14.14,0:22:15.40,Default,,0,0,0,,让我们更进一步观察它们\nDialogue: 0,0:22:17.93,0:22:19.00,Default,,0,0,0,,real-part过程应该做什么\nDialogue: 0,0:22:19.31,0:22:22.76,Default,,0,0,0,,如果我想得到一个复数的实部\nDialogue: 0,0:22:24.07,0:22:24.91,Default,,0,0,0,,那么我先要观察它\nDialogue: 0,0:22:25.80,0:22:26.69,Default,,0,0,0,,我观察它的类型\nDialogue: 0,0:22:26.69,0:22:28.12,Default,,0,0,0,,考虑它是用直角坐标表示的吗\nDialogue: 0,0:22:31.02,0:22:35.36,Default,,0,0,0,,如果是的话 我就对这个复数的\"内容\"部分\nDialogue: 0,0:22:36.06,0:22:37.92,Default,,0,0,0,,调用George的real-part过程\nDialogue: 0,0:22:41.07,0:22:42.94,Default,,0,0,0,,这是一个带有类型的数字\nDialogue: 0,0:22:43.72,0:22:47.66,Default,,0,0,0,,我用contents过程剥掉类型 并且对它应用George的过程\nDialogue: 0,0:22:50.70,0:22:52.86,Default,,0,0,0,,那如果是一个用极坐标表示的复数呢？\nDialogue: 0,0:22:53.95,0:22:54.97,Default,,0,0,0,,如果我想要得到它的实部\nDialogue: 0,0:22:55.45,0:22:58.78,Default,,0,0,0,,我就把Martha的real-part过程应用在这个数的内容上\nDialogue: 0,0:22:59.85,0:23:01.15,Default,,0,0,0,,这就是real-part工作的方式\nDialogue: 0,0:23:02.26,0:23:05.66,Default,,0,0,0,,还有类似的imag-part过程 几乎是一样的\nDialogue: 0,0:23:06.51,0:23:09.60,Default,,0,0,0,,它先观察这个数字 它是直角坐标表示的\nDialogue: 0,0:23:09.60,0:23:11.13,Default,,0,0,0,,就调用George的imaginary-part过程\nDialogue: 0,0:23:11.13,0:23:12.83,Default,,0,0,0,,是极坐标表示的 就用Martha的过程\nDialogue: 0,0:23:13.38,0:23:17.40,Default,,0,0,0,,同理也可以构造出magnitude和angle两个过程\nDialogue: 0,0:23:19.71,0:23:21.02,Default,,0,0,0,,我们的系统是这个样子\nDialogue: 0,0:23:23.00,0:23:24.26,Default,,0,0,0,,它里面有三个部分\nDialogue: 0,0:23:24.26,0:23:26.59,Default,,0,0,0,,有George、Martha和一个经理\nDialogue: 0,0:23:26.76,0:23:28.97,Default,,0,0,0,,这就是实现通用操作符的方法\nDialogue: 0,0:23:28.97,0:23:32.92,Default,,0,0,0,,为了把它说清楚 我们举一个简单的实例\nDialogue: 0,0:23:33.50,0:23:35.12,Default,,0,0,0,,但是准确描述了它工作的方式\nDialogue: 0,0:23:36.54,0:23:43.98,Default,,0,0,0,,假设你现在 面对一个实部是1\nDialogue: 0,0:23:44.52,0:23:46.09,Default,,0,0,0,,虚部是2的复数\nDialogue: 0,0:23:46.09,0:23:48.44,Default,,0,0,0,,也就是1+2i\nDialogue: 0,0:23:50.31,0:23:52.64,Default,,0,0,0,,现在在这里\nDialogue: 0,0:23:55.28,0:23:57.53,Default,,0,0,0,,在操作发生的上层\nDialogue: 0,0:23:57.63,0:24:08.27,Default,,0,0,0,,复数被表示成一个由1和2组成的序对加上类型信息\nDialogue: 0,0:24:10.48,0:24:11.39,Default,,0,0,0,,（1和2）是内容\nDialogue: 0,0:24:11.87,0:24:17.96,Default,,0,0,0,,整个的数据就是在那之上加上一个rectangular符号\nDialogue: 0,0:24:18.14,0:24:21.53,Default,,0,0,0,,这就是复数在这个系统里存在的形式\nDialogue: 0,0:24:22.33,0:24:24.92,Default,,0,0,0,,你要调取real-part的时候\nDialogue: 0,0:24:25.84,0:24:28.89,Default,,0,0,0,,经理会检查这个数然后说 这是George构造的数字\nDialogue: 0,0:24:30.27,0:24:31.53,Default,,0,0,0,,他会先把类型拿掉\nDialogue: 0,0:24:33.34,0:24:36.91,Default,,0,0,0,,然后把 (1,2) 这个序对传递给George\nDialogue: 0,0:24:38.00,0:24:42.27,Default,,0,0,0,,这是George的系统可以直接处理的数据\nDialogue: 0,0:24:44.36,0:24:45.92,Default,,0,0,0,,那么它被拆了出来\nDialogue: 0,0:24:46.52,0:24:49.76,Default,,0,0,0,,之后 如果你让George构造一个复数\nDialogue: 0,0:24:51.24,0:24:54.56,Default,,0,0,0,,George就会把它构造成序对\nDialogue: 0,0:24:55.07,0:24:58.24,Default,,0,0,0,,在数据被传递到上层之前\nDialogue: 0,0:24:59.42,0:25:01.13,Default,,0,0,0,,经理会再给它加上rectangular类型\nDialogue: 0,0:25:03.92,0:25:04.65,Default,,0,0,0,,看这个过程\nDialogue: 0,0:25:04.65,0:25:05.85,Default,,0,0,0,,这个系统不会发生混乱\nDialogue: 0,0:25:05.85,0:25:10.84,Default,,0,0,0,,就算在Martha的世界里 序对(1 2)的含义完全不同\nDialogue: 0,0:25:13.50,0:25:15.75,Default,,0,0,0,,也并没有什么影响\nDialogue: 0,0:25:15.75,0:25:18.44,Default,,0,0,0,,在Martha的世界里这个序对代表了\nDialogue: 0,0:25:18.44,0:25:20.78,Default,,0,0,0,,一个模为1 辐角为2的复数\nDialogue: 0,0:25:21.19,0:25:22.19,Default,,0,0,0,,但是这并不会造成混乱\nDialogue: 0,0:25:22.22,0:25:27.25,Default,,0,0,0,,因为每当有一个这样的序对经由经理之手\nDialogue: 0,0:25:27.25,0:25:29.61,Default,,0,0,0,,被交给主系统的时候 它都会被附加上polar的类型标志\nDialogue: 0,0:25:31.21,0:25:33.67,Default,,0,0,0,,而这个就会被贴上rectangular类型的标签\nDialogue: 0,0:25:36.93,0:25:37.90,Default,,0,0,0,,好 我们休息一下\nDialogue: 0,0:25:40.77,0:25:55.55,Default,,0,0,0,,[音乐]\nDialogue: 0,0:25:55.69,0:25:57.77,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:25:57.77,0:25:59.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:26:05.21,0:26:11.95,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:26:12.84,0:26:16.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}通用运算符\nDialogue: 0,0:26:20.21,0:26:24.15,Default,,0,0,0,,我们刚刚提出了一种实现通用运算符的策略\nDialogue: 0,0:26:24.15,0:26:31.40,Default,,0,0,0,,这种策略有一个名字 叫做“基于类型的分派”\nDialogue: 0,0:26:34.31,0:26:39.36,Default,,0,0,0,,它的想法就是你要把你的系统分成很多小块\nDialogue: 0,0:26:39.36,0:26:42.67,Default,,0,0,0,,里面有George和Martha在设计表示方法\nDialogue: 0,0:26:43.37,0:26:44.38,Default,,0,0,0,,还有一个经理\nDialogue: 0,0:26:46.12,0:26:48.06,Default,,0,0,0,,负责去看数据上的类型是什么\nDialogue: 0,0:26:48.51,0:26:50.59,Default,,0,0,0,,然后分派给正确的人去处理\nDialogue: 0,0:26:51.99,0:26:56.01,Default,,0,0,0,,这种组织系统的方法有什么缺点呢？\nDialogue: 0,0:26:58.15,0:27:00.40,Default,,0,0,0,,首先 有个小小的烦人的问题\nDialogue: 0,0:27:00.40,0:27:03.05,Default,,0,0,0,,George和Martha需要修改他们的过程的名字\nDialogue: 0,0:27:04.00,0:27:05.95,Default,,0,0,0,,George一开始写了一个real-part过程\nDialogue: 0,0:27:05.98,0:27:08.28,Default,,0,0,0,,现在他必须把它的名字改成real-part-rectangular\nDialogue: 0,0:27:08.30,0:27:10.83,Default,,0,0,0,,才能让它不与Martha的real-part过程相互冲突\nDialogue: 0,0:27:10.84,0:27:12.76,Default,,0,0,0,,而Martha的过程现在改叫real-part-polar\nDialogue: 0,0:27:13.64,0:27:16.68,Default,,0,0,0,,这是为了不和经理的那个叫做real-part的过程发生冲突\nDialogue: 0,0:27:17.31,0:27:18.94,Default,,0,0,0,,这个问题确实很恼人\nDialogue: 0,0:27:19.46,0:27:21.13,Default,,0,0,0,,但是我现在暂时不讨论这个问题\nDialogue: 0,0:27:21.27,0:27:22.35,Default,,0,0,0,,我们稍后将会看到\nDialogue: 0,0:27:23.26,0:27:26.12,Default,,0,0,0,,在讨论到Lisp名称与环境的结构的时候\nDialogue: 0,0:27:26.12,0:27:30.39,Default,,0,0,0,,我们会有方法把这些所谓的命名空间分开来封装\nDialogue: 0,0:27:30.39,0:27:31.56,Default,,0,0,0,,然后它们就不会互相影响了\nDialogue: 0,0:27:32.50,0:27:34.01,Default,,0,0,0,,现在我们暂时不去考虑这个问题\nDialogue: 0,0:27:35.72,0:27:38.19,Default,,0,0,0,,我现在想关注的问题是\nDialogue: 0,0:27:38.36,0:27:43.24,Default,,0,0,0,,你把一个新人招纳进系统之中会发生什么\nDialogue: 0,0:27:44.51,0:27:45.32,Default,,0,0,0,,会发生什么？\nDialogue: 0,0:27:45.32,0:27:46.81,Default,,0,0,0,,George和Martha并不关心\nDialogue: 0,0:27:47.42,0:27:50.73,Default,,0,0,0,,George在他的直角坐标世界里\nDialogue: 0,0:27:52.20,0:27:53.84,Default,,0,0,0,,坐拥着他的过程和数据类型\nDialogue: 0,0:27:54.09,0:27:55.74,Default,,0,0,0,,而Martha待在她的极坐标世界中\nDialogue: 0,0:27:55.93,0:27:57.02,Default,,0,0,0,,不问世事\nDialogue: 0,0:27:59.38,0:28:00.54,Default,,0,0,0,,但是经理呢？\nDialogue: 0,0:28:00.62,0:28:02.84,Default,,0,0,0,,经理需要做什么？\nDialogue: 0,0:28:03.18,0:28:06.20,Default,,0,0,0,,现在经理带着他的运算来了\nDialogue: 0,0:28:07.36,0:28:09.04,Default,,0,0,0,,有直角坐标的判断\nDialogue: 0,0:28:09.04,0:28:10.14,Default,,0,0,0,,和极坐标的判断过程\nDialogue: 0,0:28:10.14,0:28:14.91,Default,,0,0,0,,如果Harry带着某种新型的复数表示方法 进入这个系统\nDialogue: 0,0:28:17.21,0:28:19.96,Default,,0,0,0,,同时带来了一个新的类型--Harry型复数\nDialogue: 0,0:28:20.27,0:28:23.28,Default,,0,0,0,,经理就需要修改他所有的过程\nDialogue: 0,0:28:25.24,0:28:26.94,Default,,0,0,0,,所以这个系统的不灵活之处\nDialogue: 0,0:28:26.96,0:28:32.41,Default,,0,0,0,,也就是需要大量工作才能适应变化的地方 就在这个经理身上\nDialogue: 0,0:28:34.89,0:28:35.99,Default,,0,0,0,,那是非常恼人的事情\nDialogue: 0,0:28:35.99,0:28:37.21,Default,,0,0,0,,更恼人的是\nDialogue: 0,0:28:39.05,0:28:41.21,Default,,0,0,0,,你意识到这个经理实际上什么也不做\nDialogue: 0,0:28:42.59,0:28:44.67,Default,,0,0,0,,这个经理只负责“传递公文”而已\nDialogue: 0,0:28:45.84,0:28:51.13,Default,,0,0,0,,我们再来看看这些程序 它们在做什么\nDialogue: 0,0:28:51.76,0:28:52.72,Default,,0,0,0,,real-part过程在做什么\nDialogue: 0,0:28:52.88,0:28:56.17,Default,,0,0,0,,这个过程说 哦 这个复数是\nDialogue: 0,0:28:56.17,0:28:57.00,Default,,0,0,0,,George会处理的那一种吗\nDialogue: 0,0:28:57.00,0:28:58.27,Default,,0,0,0,,如果是的话 好 把它交给George处理\nDialogue: 0,0:28:59.41,0:29:01.76,Default,,0,0,0,,它是Martha能操作的那一种吗\nDialogue: 0,0:29:01.82,0:29:04.06,Default,,0,0,0,,是的话 把它交给Martha处理\nDialogue: 0,0:29:05.04,0:29:08.72,Default,,0,0,0,,这个系统真正恼人之处 也就是这个系统的瓶颈\nDialogue: 0,0:29:08.72,0:29:11.66,Default,,0,0,0,,它降低灵活性 阻碍变化\nDialogue: 0,0:29:12.09,0:29:14.36,Default,,0,0,0,,完全是一种的官僚主义\nDialogue: 0,0:29:15.00,0:29:17.02,Default,,0,0,0,,而不是任何做实事的人\nDialogue: 0,0:29:19.70,0:29:21.80,Default,,0,0,0,,很可惜这种情况经常发生\nDialogue: 0,0:29:23.18,0:29:24.41,Default,,0,0,0,,实际上发生的事情是\nDialogue: 0,0:29:24.48,0:29:26.97,Default,,0,0,0,,在系统中 有一张抽象的表格\nDialogue: 0,0:29:28.10,0:29:30.08,Default,,0,0,0,,实际发生的事情是 有这样一张表格\nDialogue: 0,0:29:30.84,0:29:33.64,Default,,0,0,0,,其中有各种类型\nDialogue: 0,0:29:34.40,0:29:38.96,Default,,0,0,0,,有polar和rectangular\nDialogue: 0,0:29:41.55,0:29:43.02,Default,,0,0,0,,可能Harry也在这里\nDialogue: 0,0:29:44.38,0:29:46.56,Default,,0,0,0,,然后这里是各种运算符\nDialogue: 0,0:29:48.05,0:29:58.24,Default,,0,0,0,,各种运算符 比如real-part和imag-part\nDialogue: 0,0:30:00.01,0:30:04.22,Default,,0,0,0,,还有magnitude、angle这些运算符\nDialogue: 0,0:30:05.83,0:30:18.97,Default,,0,0,0,,单元格中对应的是相应过程\nDialogue: 0,0:30:19.28,0:30:21.99,Default,,0,0,0,,那么填在这里 负责polar类型的real-part过程的是\nDialogue: 0,0:30:21.99,0:30:27.56,Default,,0,0,0,,Martha的real-part-polar过程\nDialogue: 0,0:30:30.57,0:30:36.62,Default,,0,0,0,,然后在这里是George的real-part-rectangular过程\nDialogue: 0,0:30:37.74,0:30:43.07,Default,,0,0,0,,然后这里是Martha的magnitude-polar过程\nDialogue: 0,0:30:44.46,0:30:49.76,Default,,0,0,0,,然后是George的magnitude-rectangular过程 等等等等\nDialogue: 0,0:30:49.76,0:30:51.24,Default,,0,0,0,,剩下的单元格也像这样填好\nDialogue: 0,0:30:52.39,0:30:54.26,Default,,0,0,0,,这就是实际上发生的事情\nDialogue: 0,0:30:57.63,0:31:01.74,Default,,0,0,0,,从某种意义上讲 经理做的事情就是\nDialogue: 0,0:31:02.11,0:31:04.11,Default,,0,0,0,,去扮演这张表格\nDialogue: 0,0:31:06.86,0:31:08.70,Default,,0,0,0,,那我们怎么去修补这个系统呢\nDialogue: 0,0:31:11.74,0:31:13.77,Default,,0,0,0,,怎么去消灭这种官僚主义？\nDialogue: 0,0:31:13.77,0:31:15.44,Default,,0,0,0,,你要做的就是让这个经理走人\nDialogue: 0,0:31:16.01,0:31:19.55,Default,,0,0,0,,我们用一台计算机来代替他\nDialogue: 0,0:31:20.17,0:31:21.76,Default,,0,0,0,,我们要让自动操作抹掉他存在的意义\nDialogue: 0,0:31:23.32,0:31:26.57,Default,,0,0,0,,也就是说 我们不用这个经理去查阅这个表格\nDialogue: 0,0:31:27.45,0:31:29.32,Default,,0,0,0,,而是让我们的系统直接去查阅它\nDialogue: 0,0:31:31.02,0:31:32.11,Default,,0,0,0,,这是什么意思呢？\nDialogue: 0,0:31:32.11,0:31:36.19,Default,,0,0,0,,我们来假设 还是用数据抽象的观点\nDialogue: 0,0:31:37.71,0:31:40.40,Default,,0,0,0,,我们有这样一种表格数据结构\nDialogue: 0,0:31:40.88,0:31:43.61,Default,,0,0,0,,而且我们还有把东西填进去和从中删除的方法\nDialogue: 0,0:31:44.35,0:31:49.04,Default,,0,0,0,,为了把话说清楚 我们假设现在有一个叫put的方法\nDialogue: 0,0:31:50.30,0:31:58.32,Default,,0,0,0,,本例中put方法接受两个参数 -- 我们称其为“关键字” -- key1和key2\nDialogue: 0,0:32:00.13,0:32:00.99,Default,,0,0,0,,还有接受一个值\nDialogue: 0,0:32:06.20,0:32:11.12,Default,,0,0,0,,put过程把value存放在表格key1和key2对应的格子里\nDialogue: 0,0:32:11.49,0:32:13.16,Default,,0,0,0,,然后我们假设有另一个叫get的过程\nDialogue: 0,0:32:15.23,0:32:18.72,Default,,0,0,0,,它是这样的一个东西 如果我说把表格里\nDialogue: 0,0:32:19.40,0:32:22.76,Default,,0,0,0,,存储在key1和key2对应的格子中的数据给我\nDialogue: 0,0:32:23.40,0:32:25.39,Default,,0,0,0,,它会把存储在那里的东西返回给我\nDialogue: 0,0:32:26.73,0:32:29.44,Default,,0,0,0,,我们先不要担心这个表格怎么实现\nDialogue: 0,0:32:30.00,0:32:32.52,Default,,0,0,0,,那又是另一个数据抽象了 是George需要考虑的问题\nDialogue: 0,0:32:33.06,0:32:34.36,Default,,0,0,0,,也许稍后我们还会看到\nDialogue: 0,0:32:34.70,0:32:36.97,Default,,0,0,0,,我们还会讨论怎么用Lisp建立这个表格\nDialogue: 0,0:32:40.71,0:32:45.50,Default,,0,0,0,,我们有了这个组织结构 George和Martha需要做什么呢？\nDialogue: 0,0:32:47.38,0:32:49.07,Default,,0,0,0,,当他们构建自己的系统的时候\nDialogue: 0,0:32:49.13,0:32:51.08,Default,,0,0,0,,都有责任在表格里\nDialogue: 0,0:32:51.44,0:32:53.82,Default,,0,0,0,,正确地添加上自己的那一列\nDialogue: 0,0:32:55.21,0:32:57.47,Default,,0,0,0,,比如说 对于George\nDialogue: 0,0:32:59.79,0:33:02.06,Default,,0,0,0,,当他定义过程的时候 他需要做的就是\nDialogue: 0,0:33:02.27,0:33:07.99,Default,,0,0,0,,把它们放进表格中的rectangular类型的那一列下面\nDialogue: 0,0:33:09.82,0:33:12.12,Default,,0,0,0,,然后操作的名字是real-part\nDialogue: 0,0:33:13.31,0:33:15.26,Default,,0,0,0,,放入他的real-part-rectangular过程\nDialogue: 0,0:33:16.25,0:33:17.78,Default,,0,0,0,,注意有什么被放到了表格里\nDialogue: 0,0:33:17.78,0:33:22.10,Default,,0,0,0,,这里的两个key是这两个符号：rectangular和real-part\nDialogue: 0,0:33:22.10,0:33:22.75,Default,,0,0,0,,这是引用\nDialogue: 0,0:33:24.40,0:33:26.75,Default,,0,0,0,,要被填到表里的东西\nDialogue: 0,0:33:26.84,0:33:29.21,Default,,0,0,0,,是他编写的real-part-rectangular过程\nDialogue: 0,0:33:31.85,0:33:34.30,Default,,0,0,0,,然后把这个获取虚部的过程也放进表里\nDialogue: 0,0:33:34.59,0:33:37.80,Default,,0,0,0,,分类到rectangular和imag-part两个关键字之下\nDialogue: 0,0:33:38.62,0:33:42.88,Default,,0,0,0,,获取模值的过程放到rectangular和magnitude下面\nDialogue: 0,0:33:43.61,0:33:45.20,Default,,0,0,0,,获取辐角的过程放到rectangular和angle下面\nDialogue: 0,0:33:47.04,0:33:50.84,Default,,0,0,0,,George作为系统的一部分 就要做以上这些事情\nDialogue: 0,0:33:54.42,0:33:58.86,Default,,0,0,0,,Martha用同样的方法填好表格中关于polar的这一列\nDialogue: 0,0:33:59.43,0:34:00.65,Default,,0,0,0,,在polar和real-part对应的这一栏\nDialogue: 0,0:34:01.69,0:34:03.58,Default,,0,0,0,,应该填的过程是real-part-polar是吧？\nDialogue: 0,0:34:04.34,0:34:07.29,Default,,0,0,0,,然后分别是imag-part、magnitude和angle过程\nDialogue: 0,0:34:08.91,0:34:11.40,Default,,0,0,0,,Martha想要加入系统当中就要做这些事情\nDialogue: 0,0:34:11.40,0:34:13.55,Default,,0,0,0,,每个设计了数据表示的人\nDialogue: 0,0:34:13.55,0:34:17.63,Default,,0,0,0,,都必须在表格里设置自己的一列\nDialogue: 0,0:34:17.76,0:34:19.90,Default,,0,0,0,,那么Harry带着他的绝妙的复数实现方法\nDialogue: 0,0:34:19.90,0:34:21.80,Default,,0,0,0,,过来的时候 他需要做什么呢\nDialogue: 0,0:34:21.80,0:34:23.96,Default,,0,0,0,,他先把过程写好\nDialogue: 0,0:34:24.04,0:34:26.52,Default,,0,0,0,,然后在表格里再建立一列\nDialogue: 0,0:34:28.55,0:34:30.04,Default,,0,0,0,,那么现在经理怎么样了呢\nDialogue: 0,0:34:31.33,0:34:34.61,Default,,0,0,0,,经理的存在被自动操作所取代\nDialogue: 0,0:34:34.61,0:34:37.11,Default,,0,0,0,,被一个叫做operate的过程代替\nDialogue: 0,0:34:37.11,0:34:39.55,Default,,0,0,0,,这是这个系统最关键的一个过程\nDialogue: 0,0:34:40.38,0:34:45.92,Default,,0,0,0,,(define operate\nDialogue: 0,0:34:51.06,0:34:56.09,Default,,0,0,0,,Operate过程接收你想要采取的运算\nDialogue: 0,0:34:57.75,0:34:58.88,Default,,0,0,0,,应该说是这个运算的名字\nDialogue: 0,0:34:59.20,0:35:03.28,Default,,0,0,0,,和被运算的对象\nDialogue: 0,0:35:04.21,0:35:09.76,Default,,0,0,0,,那么举例来说 对一个复数调用real-part operate过程会做什么呢\nDialogue: 0,0:35:09.95,0:35:11.90,Default,,0,0,0,,它要做的第一件事就是去查表\nDialogue: 0,0:35:12.64,0:35:13.87,Default,,0,0,0,,它查询这个表格\nDialogue: 0,0:35:14.80,0:35:22.56,Default,,0,0,0,,试图去找到存储在表格里的一个过程\nDialogue: 0,0:35:23.15,0:35:24.80,Default,,0,0,0,,所以它要对表格调用get过程\nDialogue: 0,0:35:25.50,0:35:33.92,Default,,0,0,0,,用对象的类型和运算的名称作为关键字进行检索\nDialogue: 0,0:35:38.92,0:35:40.14,Default,,0,0,0,,这样就可以知道在表格中\nDialogue: 0,0:35:40.38,0:35:42.72,Default,,0,0,0,,与数据的类型和要进行的运算相对应的是什么了\nDialogue: 0,0:35:42.89,0:35:44.35,Default,,0,0,0,,对应的这一格里填了什么东西\nDialogue: 0,0:35:44.44,0:35:45.93,Default,,0,0,0,,我们假设get过程已经被实现好了\nDialogue: 0,0:35:45.93,0:35:47.72,Default,,0,0,0,,所以如果在那一格什么也没有\nDialogue: 0,0:35:48.11,0:35:51.79,Default,,0,0,0,,它就会返回一个空表\nDialogue: 0,0:35:52.67,0:35:55.39,Default,,0,0,0,,如果那里确实有什么东西\nDialogue: 0,0:35:56.62,0:36:00.43,Default,,0,0,0,,如果存储有这样的一个过程\nDialogue: 0,0:36:03.15,0:36:07.12,Default,,0,0,0,,那么就会把在表格里找到的这个过程\nDialogue: 0,0:36:09.79,0:36:15.00,Default,,0,0,0,,应用到对象的具体内容上去\nDialogue: 0,0:36:18.25,0:36:20.40,Default,,0,0,0,,如果那里没有东西的话\nDialogue: 0,0:36:20.67,0:36:22.51,Default,,0,0,0,,它就会 -- 我们可以决定\nDialogue: 0,0:36:22.81,0:36:27.12,Default,,0,0,0,,本例中 我们让它输出一个错误消息：“未定义的运算符”\nDialogue: 0,0:36:28.48,0:36:30.24,Default,,0,0,0,,没有支持这种类型的运算符\nDialogue: 0,0:36:33.07,0:36:34.72,Default,,0,0,0,,或者其它合适的错误信息\nDialogue: 0,0:36:39.07,0:36:39.48,Default,,0,0,0,,对吧？\nDialogue: 0,0:36:39.72,0:36:41.04,Default,,0,0,0,,这个东西替代了经理\nDialogue: 0,0:36:41.89,0:36:42.91,Default,,0,0,0,,我们怎么去使用它呢\nDialogue: 0,0:36:43.96,0:36:49.80,Default,,0,0,0,,我们的想法是用operate过程来定义通用选择函数\nDialogue: 0,0:36:50.04,0:36:56.75,Default,,0,0,0,,我们可以说一个对象的real-part\nDialogue: 0,0:36:57.14,0:37:05.66,Default,,0,0,0,,是这个对象被operate应用了叫做real-part的运算后得到的结果\nDialogue: 0,0:37:08.07,0:37:12.22,Default,,0,0,0,,那么类似地 imag-part是operate对obj应用imag-part运算\nDialogue: 0,0:37:12.22,0:37:13.98,Default,,0,0,0,,magnitude和angle同理\nDialogue: 0,0:37:15.36,0:37:17.43,Default,,0,0,0,,这就是我们的实现方法\nDialogue: 0,0:37:17.43,0:37:20.48,Default,,0,0,0,,由它们加上类型再加上operate过程组成\nDialogue: 0,0:37:21.33,0:37:24.00,Default,,0,0,0,,这个表格现在就有效地完成了之前经理的工作\nDialogue: 0,0:37:24.06,0:37:27.69,Default,,0,0,0,,我们来梳理一下在这个过程中发生的事情\nDialogue: 0,0:37:27.90,0:37:33.00,Default,,0,0,0,,假设我有一个由Martha构造的复数\nDialogue: 0,0:37:33.53,0:37:38.80,Default,,0,0,0,,它的模值是1 辐角是2\nDialogue: 0,0:37:39.10,0:37:40.22,Default,,0,0,0,,它是由Martha构造的\nDialogue: 0,0:37:40.22,0:37:45.45,Default,,0,0,0,,所以它被贴上了polar的标签\nDialogue: 0,0:37:47.24,0:37:48.00,Default,,0,0,0,,我们叫它z\nDialogue: 0,0:37:48.00,0:37:48.91,Default,,0,0,0,,假设这就是z\nDialogue: 0,0:37:51.77,0:37:54.46,Default,,0,0,0,,然后假设在这种实现方法下\nDialogue: 0,0:37:54.80,0:37:57.92,Default,,0,0,0,,有人想要取z的实部\nDialogue: 0,0:38:04.87,0:38:07.96,Default,,0,0,0,,由于real-part现在是用operate来定义的\nDialogue: 0,0:38:09.16,0:38:10.57,Default,,0,0,0,,这就等同于说\nDialogue: 0,0:38:12.09,0:38:24.81,Default,,0,0,0,,调用 (operate 'real-part z)\nDialogue: 0,0:38:27.06,0:38:28.09,Default,,0,0,0,,然后operate过程\nDialogue: 0,0:38:28.09,0:38:29.24,Default,,0,0,0,,就会去查询表格\nDialogue: 0,0:38:31.04,0:38:34.36,Default,,0,0,0,,然后试图去寻找在表格里存放的\nDialogue: 0,0:38:39.00,0:38:46.22,Default,,0,0,0,,查询表格中与对象的类型相对应的一列\nDialogue: 0,0:38:46.72,0:38:48.22,Default,,0,0,0,,那么z的类型是polar\nDialogue: 0,0:38:48.79,0:38:51.37,Default,,0,0,0,,所以它就要说 我用polar作为关键字查表\nDialogue: 0,0:38:52.99,0:38:58.57,Default,,0,0,0,,然后运算的名称是real-part\nDialogue: 0,0:39:05.96,0:39:13.63,Default,,0,0,0,,它查询对应的过程 然后应用到z的内容上去\nDialogue: 0,0:39:14.83,0:39:17.13,Default,,0,0,0,,如果所有东西都安排妥当的话\nDialogue: 0,0:39:17.74,0:39:21.70,Default,,0,0,0,,如果它找到的过程就是Martha编写的过程\nDialogue: 0,0:39:21.70,0:39:22.95,Default,,0,0,0,,也就是real-part-polar\nDialogue: 0,0:39:31.05,0:39:35.13,Default,,0,0,0,,然后这就是z去掉类型之后的东西\nDialogue: 0,0:39:35.44,0:39:38.94,Default,,0,0,0,,是Martha最初设计的数据表示\nDialogue: 0,0:39:39.40,0:39:40.43,Default,,0,0,0,,也就是这里的(1 2)\nDialogue: 0,0:39:43.71,0:39:45.87,Default,,0,0,0,,所以说在整个系统中 operate过程\nDialogue: 0,0:39:46.46,0:39:48.89,Default,,0,0,0,,和之前的经理做的事情没什么区别\nDialogue: 0,0:39:49.45,0:39:52.59,Default,,0,0,0,,它通过查询表格找到正确的东西  然后剥离类型\nDialogue: 0,0:39:53.58,0:39:57.52,Default,,0,0,0,,然后把它传递给能够处理它的人\nDialogue: 0,0:39:58.88,0:40:05.48,Default,,0,0,0,,你会发现 这是另一种 在大多数情况下\nDialogue: 0,0:40:06.22,0:40:08.04,Default,,0,0,0,,更灵活地实现通用运算符的方法\nDialogue: 0,0:40:08.08,0:40:15.69,Default,,0,0,0,,我们把它叫做“数据导向编程”\nDialogue: 0,0:40:20.35,0:40:21.96,Default,,0,0,0,,其理念是\nDialogue: 0,0:40:23.42,0:40:25.55,Default,,0,0,0,,在某种意义上 这些数据对象本身\nDialogue: 0,0:40:26.04,0:40:28.35,Default,,0,0,0,,这些充斥在系统中的复数\nDialogue: 0,0:40:28.73,0:40:33.16,Default,,0,0,0,,它们自身就携带着 关于应该怎么去操作它们的信息\nDialogue: 0,0:40:35.74,0:40:36.78,Default,,0,0,0,,有什么疑问吗？\nDialogue: 0,0:40:41.00,0:40:41.24,Default,,0,0,0,,请说\nDialogue: 0,0:40:41.24,0:40:43.39,Default,,0,0,0,,学生：你在那个数据对象里存储的是什么呢\nDialogue: 0,0:40:43.39,0:40:47.10,Default,,0,0,0,,这里面有这个数据本身 还有它的类型\nDialogue: 0,0:40:47.10,0:40:49.60,Default,,0,0,0,,还有该与该类型对应的运算\nDialogue: 0,0:40:49.69,0:40:53.08,Default,,0,0,0,,或者说那些运算是存储在哪里呢？\nDialogue: 0,0:40:53.60,0:40:54.17,Default,,0,0,0,,教授：好 让我--\nDialogue: 0,0:40:54.98,0:40:56.50,Default,,0,0,0,,恩 这是一个好问题\nDialogue: 0,0:40:56.50,0:41:00.46,Default,,0,0,0,,通过它暗示了实现我们目标的 其它可行方法\nDialogue: 0,0:41:00.75,0:41:02.48,Default,,0,0,0,,当然可能的方法有很多\nDialogue: 0,0:41:04.20,0:41:06.14,Default,,0,0,0,,在这个特定的实现当中\nDialogue: 0,0:41:06.24,0:41:09.72,Default,,0,0,0,,在这个数据对象里放着\nDialogue: 0,0:41:10.44,0:41:13.45,Default,,0,0,0,,就是数据本身 本例中是序对(1, 2)\nDialogue: 0,0:41:14.98,0:41:16.55,Default,,0,0,0,,和一个符号\nDialogue: 0,0:41:16.55,0:41:19.07,Default,,0,0,0,,就是这个符号 单词P-O-L-A-R\nDialogue: 0,0:41:20.60,0:41:22.33,Default,,0,0,0,,这些就是这个数据对象里面的东西\nDialogue: 0,0:41:24.24,0:41:26.69,Default,,0,0,0,,那么这些运算又是存放在哪里的呢？\nDialogue: 0,0:41:26.69,0:41:29.00,Default,,0,0,0,,那些运算在表格里\nDialogue: 0,0:41:29.85,0:41:31.07,Default,,0,0,0,,在这个表格里\nDialogue: 0,0:41:32.30,0:41:36.46,Default,,0,0,0,,所有行和列的名字都是符号\nDialogue: 0,0:41:38.23,0:41:40.08,Default,,0,0,0,,所以当我往里面存什么东西的时候\nDialogue: 0,0:41:40.09,0:41:47.02,Default,,0,0,0,,可以以符号polar或符号magnitude作为关键字\nDialogue: 0,0:41:48.24,0:41:51.31,Default,,0,0,0,,我这样写 可能让你们感到困惑了\nDialogue: 0,0:41:51.31,0:41:52.70,Default,,0,0,0,,因为在这里面放的并不是\nDialogue: 0,0:41:53.16,0:41:54.57,Default,,0,0,0,,当我写下mag-polar的时候\nDialogue: 0,0:41:57.04,0:41:59.23,Default,,0,0,0,,我指的是那个叫mag-polar的过程\nDialogue: 0,0:41:59.85,0:42:01.85,Default,,0,0,0,,可能 我本来应该在这里写上\nDialogue: 0,0:42:02.58,0:42:04.20,Default,,0,0,0,,但是这里空间太小了\nDialogue: 0,0:42:04.20,0:42:05.07,Default,,0,0,0,,我写不下\nDialogue: 0,0:42:05.58,0:42:08.92,Default,,0,0,0,,应该写成lambda(z)\nDialogue: 0,0:42:10.60,0:42:12.75,Default,,0,0,0,,然后调用Martha实现的过程\nDialogue: 0,0:42:14.71,0:42:15.72,Default,,0,0,0,,你也可以从这里看出\nDialogue: 0,0:42:15.74,0:42:17.44,Default,,0,0,0,,我已经暗示了另一种方法\nDialogue: 0,0:42:17.71,0:42:19.82,Default,,0,0,0,,来解决名字冲突的问题\nDialogue: 0,0:42:20.04,0:42:23.15,Default,,0,0,0,,那就是George和Martha根本不用给他们的过程起名字\nDialogue: 0,0:42:23.15,0:42:25.37,Default,,0,0,0,,可以直接把由lambda定义的\nDialogue: 0,0:42:25.39,0:42:28.12,Default,,0,0,0,,由lambda定义的匿名函数放进表格里\nDialogue: 0,0:42:28.66,0:42:31.76,Default,,0,0,0,,你的问题还引出了另一种可能性\nDialogue: 0,0:42:32.35,0:42:34.06,Default,,0,0,0,,也就是\nDialogue: 0,0:42:34.83,0:42:37.92,Default,,0,0,0,,可能我在这个数据对象里存储的\nDialogue: 0,0:42:37.95,0:42:39.48,Default,,0,0,0,,不是符号POLAR\nDialogue: 0,0:42:39.93,0:42:42.35,Default,,0,0,0,,也许是这些运算本身\nDialogue: 0,0:42:43.90,0:42:45.63,Default,,0,0,0,,这是组织系统的另一种方法\nDialogue: 0,0:42:45.66,0:42:46.60,Default,,0,0,0,,叫做“消息传递”\nDialogue: 0,0:42:48.65,0:42:49.92,Default,,0,0,0,,它们都殊途同归\nDialogue: 0,0:42:54.64,0:42:58.04,Default,,0,0,0,,学生：所以说如果Martha和George\nDialogue: 0,0:42:58.04,0:43:01.23,Default,,0,0,0,,用了相同的过程名字也没什么问题\nDialogue: 0,0:43:01.23,0:43:02.56,Default,,0,0,0,,[听不清]\nDialogue: 0,0:43:02.56,0:43:04.68,Default,,0,0,0,,教授：对 你说得很对\nDialogue: 0,0:43:04.80,0:43:07.85,Default,,0,0,0,,看 他们甚至根本不需要给他们的过程命名\nDialogue: 0,0:43:08.04,0:43:09.36,Default,,0,0,0,,George和Martha可以 --\nDialogue: 0,0:43:09.50,0:43:10.62,Default,,0,0,0,,George可以这么来做\nDialogue: 0,0:43:10.83,0:43:15.28,Default,,0,0,0,,与其在rectangular和real-part对应的格子里放\nDialogue: 0,0:43:16.22,0:43:17.98,Default,,0,0,0,,存放real-part-rectangular这个过程\nDialogue: 0,0:43:18.03,0:43:21.15,Default,,0,0,0,,George可以在rectangular和real-part对应的格子里放\nDialogue: 0,0:43:21.24,0:43:23.69,Default,,0,0,0,,放一个lambda(z) 然后什么什么\nDialogue: 0,0:43:24.54,0:43:26.84,Default,,0,0,0,,整个系统会以完全相同的方式工作\nDialogue: 0,0:43:27.33,0:43:29.24,Default,,0,0,0,,学生：我的问题是 就算Martha在\nDialogue: 0,0:43:29.84,0:43:33.60,Default,,0,0,0,,Martha在key1和key2对应的格子里放了real-part过程\nDialogue: 0,0:43:33.95,0:43:37.64,Default,,0,0,0,,George也在key1和key2下放了一个real-part过程\nDialogue: 0,0:43:37.96,0:43:39.60,Default,,0,0,0,,只要两个过程的定义不一样\nDialogue: 0,0:43:39.80,0:43:41.26,Default,,0,0,0,,它们就不会发生任何冲突 对吗？\nDialogue: 0,0:43:41.29,0:43:43.80,Default,,0,0,0,,教授：对的 这完全没有问题\nDialogue: 0,0:43:44.97,0:43:47.13,Default,,0,0,0,,除非你说的是George和Martha在同一个终端上工作\nDialogue: 0,0:43:47.13,0:43:49.20,Default,,0,0,0,,并且他们两个人起的所有名字的含义全部相同\nDialogue: 0,0:43:49.82,0:43:51.23,Default,,0,0,0,,那么同样的real-part就会造成困扰\nDialogue: 0,0:43:51.24,0:43:52.80,Default,,0,0,0,,但是就算是这种情况也有办法解决\nDialogue: 0,0:43:52.80,0:43:54.80,Default,,0,0,0,,从原则上讲你说的完全正确\nDialogue: 0,0:43:54.98,0:43:56.29,Default,,0,0,0,,如果它们的名字不互相冲突的话\nDialogue: 0,0:43:56.29,0:43:58.19,Default,,0,0,0,,被填到表里的是对象本身 而不是它们的名字\nDialogue: 0,0:44:08.20,0:44:09.05,Default,,0,0,0,,好 我们休息一下\nDialogue: 0,0:44:12.91,0:44:20.48,Default,,0,0,0,,[音乐]\nDialogue: 0,0:44:20.96,0:44:23.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:44:23.45,0:44:25.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:44:57.42,0:45:05.07,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:45:05.47,0:45:09.24,Declare,,0,0,0,,{\\an2\\fad(500,500)}通用运算符\nDialogue: 0,0:45:12.88,0:45:16.88,Default,,0,0,0,,教授：好的 我们刚刚讲了一个数据导向编程的例子\nDialogue: 0,0:45:17.68,0:45:22.84,Default,,0,0,0,,我们将其用于实现一个复数域上的算术系统\nDialogue: 0,0:45:27.60,0:45:32.48,Default,,0,0,0,,我已经在里面实现了 +c -c 这些运算\nDialogue: 0,0:45:32.88,0:45:37.24,Default,,0,0,0,,*c \\c 还有其它的一些过程\nDialogue: 0,0:45:38.23,0:45:45.72,Default,,0,0,0,,这些过程存在于上层 -- 这是关键之处\nDialogue: 0,0:45:45.74,0:45:49.60,Default,,0,0,0,,它们存在于两种不同表示方式的上层\nDialogue: 0,0:45:50.34,0:45:55.44,Default,,0,0,0,,这是一个直角坐标程序包 这里一个极坐标程序包\nDialogue: 0,0:45:58.14,0:45:59.15,Default,,0,0,0,,可能还有其它的东西\nDialogue: 0,0:45:59.15,0:46:02.80,Default,,0,0,0,,关键理念就是 “其它的东西”可以很容易地添加上去\nDialogue: 0,0:46:04.67,0:46:08.35,Default,,0,0,0,,但是这并没有真正体现出这种方法学的威力\nDialogue: 0,0:46:08.90,0:46:10.15,Default,,0,0,0,,我们看看发生了什么\nDialogue: 0,0:46:10.15,0:46:12.33,Default,,0,0,0,,这个方法的威力 只有当你\nDialogue: 0,0:46:12.94,0:46:15.79,Default,,0,0,0,,当你把它嵌入于一些更复杂的系统中时才会显现\nDialogue: 0,0:46:16.17,0:46:17.74,Default,,0,0,0,,我现在要做的就是\nDialogue: 0,0:46:17.87,0:46:20.01,Default,,0,0,0,,把它嵌入一个更复杂的系统中\nDialogue: 0,0:46:20.25,0:46:25.28,Default,,0,0,0,,假设我们已经有了一个通用算术系统\nDialogue: 0,0:46:25.28,0:46:27.24,Default,,0,0,0,,所谓的“通用算术系统”\nDialogue: 0,0:46:27.24,0:46:28.54,Default,,0,0,0,,然后在系统的最顶层\nDialogue: 0,0:46:30.76,0:46:35.92,Default,,0,0,0,,用户可以命令它把两个东西相加 或者相减\nDialogue: 0,0:46:37.45,0:46:41.05,Default,,0,0,0,,或者让两数相乘、相除\nDialogue: 0,0:46:44.14,0:46:46.52,Default,,0,0,0,,然后在它们下面是一个抽象屏障\nDialogue: 0,0:46:47.93,0:46:49.15,Default,,0,0,0,,抽象屏障的下层\nDialogue: 0,0:46:49.50,0:46:52.48,Default,,0,0,0,,是一个复数域算术程序包\nDialogue: 0,0:46:53.02,0:46:54.96,Default,,0,0,0,,然后你可以让它把两个复数相加\nDialogue: 0,0:46:55.04,0:46:58.83,Default,,0,0,0,,或者你还可以把 有理数域算术程序包\nDialogue: 0,0:46:58.88,0:46:59.93,Default,,0,0,0,,给安装进来\nDialogue: 0,0:47:00.19,0:47:01.72,Default,,0,0,0,,可以放进去有理数\nDialogue: 0,0:47:04.76,0:47:06.22,Default,,0,0,0,,然后有理数程序包里面\nDialogue: 0,0:47:07.16,0:47:14.75,Default,,0,0,0,,有我们实现的 +rat、*rat等等的这些过程\nDialogue: 0,0:47:15.39,0:47:17.01,Default,,0,0,0,,或者你还可以加上通常的Lisp算术系统\nDialogue: 0,0:47:17.01,0:47:18.99,Default,,0,0,0,,你可以让它把3和4加起来\nDialogue: 0,0:47:19.42,0:47:20.94,Default,,0,0,0,,那么我们在这个系统里加入通常的算术系统\nDialogue: 0,0:47:28.28,0:47:34.67,Default,,0,0,0,,其中有Lisp自带的 + - * /\nDialogue: 0,0:47:36.67,0:47:39.12,Default,,0,0,0,,总而言之 我们可以想象这个复数系统\nDialogue: 0,0:47:39.44,0:47:44.44,Default,,0,0,0,,存在于一个更加复杂的通用运算系统里面\nDialogue: 0,0:47:47.73,0:47:48.73,Default,,0,0,0,,我们怎么才能做到呢\nDialogue: 0,0:47:49.05,0:47:52.32,Default,,0,0,0,,我们已经有了想法 只要再一次应用它就可以了\nDialogue: 0,0:47:52.78,0:47:54.72,Default,,0,0,0,,我们已经实现了一个有理数程序包\nDialogue: 0,0:47:54.72,0:47:56.89,Default,,0,0,0,,那么我们来看看应该怎么修改它\nDialogue: 0,0:48:01.48,0:48:03.40,Default,,0,0,0,,实际上 在这个层面 它根本就不需要修改\nDialogue: 0,0:48:03.73,0:48:05.88,Default,,0,0,0,,这完全就是我们上次写的那些代码\nDialogue: 0,0:48:07.18,0:48:08.97,Default,,0,0,0,,要把两个有理数相加\nDialogue: 0,0:48:09.85,0:48:10.91,Default,,0,0,0,,回忆一下 我们要用到这个公式\nDialogue: 0,0:48:11.14,0:48:13.37,Default,,0,0,0,,构造一个有理数 它的分子是\nDialogue: 0,0:48:13.98,0:48:17.56,Default,,0,0,0,,x的分子乘以y的分母\nDialogue: 0,0:48:17.93,0:48:21.52,Default,,0,0,0,,加上 x的分母乘以y的分子\nDialogue: 0,0:48:21.52,0:48:23.79,Default,,0,0,0,,而结果的分母是 x的分母乘y的分母\nDialogue: 0,0:48:25.76,0:48:29.07,Default,,0,0,0,,然后是-rat、*rat、/rat这些过程\nDialogue: 0,0:48:30.36,0:48:35.12,Default,,0,0,0,,这就是我们之前写的那个有理数程序包\nDialogue: 0,0:48:36.31,0:48:38.89,Default,,0,0,0,,我们忽略最大公约数的问题 先不去考虑那个\nDialogue: 0,0:48:39.08,0:48:42.59,Default,,0,0,0,,作为这个有理数包的实现人员\nDialogue: 0,0:48:42.80,0:48:45.10,Default,,0,0,0,,怎么把它安装到我们的通用运算系统中呢？\nDialogue: 0,0:48:45.57,0:48:46.22,Default,,0,0,0,,那很简单\nDialogue: 0,0:48:47.29,0:48:51.56,Default,,0,0,0,,我们要做的事只有一件和之前不同\nDialogue: 0,0:48:51.84,0:48:55.71,Default,,0,0,0,,在之前我们说构造一个有理数\nDialogue: 0,0:48:56.27,0:48:59.98,Default,,0,0,0,,就是构造一个由分子分母组成的序对\nDialogue: 0,0:49:00.96,0:49:03.20,Default,,0,0,0,,现在我们不光构造这个序对 还要给它贴上标签\nDialogue: 0,0:49:03.30,0:49:04.56,Default,,0,0,0,,给它加上rational类型\nDialogue: 0,0:49:06.36,0:49:08.09,Default,,0,0,0,,这就是唯一的不同之处\nDialogue: 0,0:49:08.56,0:49:10.09,Default,,0,0,0,,把它变成带类型的数据\nDialogue: 0,0:49:12.38,0:49:14.08,Default,,0,0,0,,现在 我们要把运算放进表格里\nDialogue: 0,0:49:14.36,0:49:18.20,Default,,0,0,0,,我们在rational符号和add运算对应的格子里\nDialogue: 0,0:49:18.92,0:49:20.25,Default,,0,0,0,,放进我们的+rat过程\nDialogue: 0,0:49:21.82,0:49:23.24,Default,,0,0,0,,再次强调 这是一个符号\nDialogue: 0,0:49:23.74,0:49:23.93,Default,,0,0,0,,看到了么？\nDialogue: 0,0:49:24.03,0:49:25.29,Default,,0,0,0,,这是引用 这也是引用\nDialogue: 0,0:49:25.31,0:49:28.01,Default,,0,0,0,,但是实际上放进表里的是+rat过程本身\nDialogue: 0,0:49:29.82,0:49:31.77,Default,,0,0,0,,然后怎么做减法\nDialogue: 0,0:49:31.79,0:49:36.81,Default,,0,0,0,,我们用-rat过程做减法\nDialogue: 0,0:49:38.27,0:49:40.24,Default,,0,0,0,,然后是乘法和除法\nDialogue: 0,0:49:41.09,0:49:43.64,Default,,0,0,0,,这些步骤精准地描述了 我们该怎么做\nDialogue: 0,0:49:44.14,0:49:46.97,Default,,0,0,0,,来兼容这个通用算术系统\nDialogue: 0,0:49:48.51,0:49:49.88,Default,,0,0,0,,那么整个系统怎么工作呢\nDialogue: 0,0:49:51.56,0:49:58.40,Default,,0,0,0,,我们想实现的是通用运算符\nDialogue: 0,0:49:59.34,0:50:02.80,Default,,0,0,0,,为了让add、sub、mul和div变成通用运算符\nDialogue: 0,0:50:03.99,0:50:17.36,Default,,0,0,0,,所以我们要把add过程定义为 (ADD X Y)就是\nDialogue: 0,0:50:18.62,0:50:22.12,Default,,0,0,0,,就是调用operate过程\nDialogue: 0,0:50:26.08,0:50:27.49,Default,,0,0,0,,我们把这个叫做operate-2\nDialogue: 0,0:50:27.49,0:50:30.78,Default,,0,0,0,,这是我们的操作过程 但是要接收两个参数\nDialogue: 0,0:50:31.60,0:50:35.84,Default,,0,0,0,,对它们应用add 把它们加起来\nDialogue: 0,0:50:37.60,0:50:39.76,Default,,0,0,0,,这是和operate类似的一个东西\nDialogue: 0,0:50:40.42,0:50:41.68,Default,,0,0,0,,我们再看看这个代码\nDialogue: 0,0:50:41.68,0:50:42.93,Default,,0,0,0,,它和operate很相似\nDialogue: 0,0:50:45.79,0:50:52.49,Default,,0,0,0,,为了将运算符运用在两个参数arg1和arg2上\nDialogue: 0,0:50:55.04,0:50:56.65,Default,,0,0,0,,首要任务是\nDialogue: 0,0:50:56.83,0:51:00.73,Default,,0,0,0,,检查这两个参数的类型是否相同\nDialogue: 0,0:51:01.90,0:51:02.96,Default,,0,0,0,,所以我们要问\nDialogue: 0,0:51:02.99,0:51:07.77,Default,,0,0,0,,第一个参数的类型和第二个的类型一样吗？\nDialogue: 0,0:51:10.35,0:51:13.36,Default,,0,0,0,,如果不一样\nDialogue: 0,0:51:13.58,0:51:15.63,Default,,0,0,0,,我们就停止运行 然后抛出错误\nDialogue: 0,0:51:15.67,0:51:16.67,Default,,0,0,0,,我们不知道怎么对它们进行运算\nDialogue: 0,0:51:19.14,0:51:20.49,Default,,0,0,0,,如果它们的类型确实是相同的\nDialogue: 0,0:51:20.51,0:51:22.08,Default,,0,0,0,,那就和之前一样了\nDialogue: 0,0:51:22.08,0:51:26.46,Default,,0,0,0,,我们会查询在参数的类型对应的\nDialogue: 0,0:51:26.76,0:51:29.61,Default,,0,0,0,,参数1和参数2是同样的类型 知道一个就可以\nDialogue: 0,0:51:30.42,0:51:32.59,Default,,0,0,0,,我们到表格里去查找对应的过程\nDialogue: 0,0:51:33.64,0:51:35.87,Default,,0,0,0,,如果找到这样一个过程\nDialogue: 0,0:51:37.53,0:51:41.74,Default,,0,0,0,,我们就将其应用在参数1和参数2的内容上\nDialogue: 0,0:51:43.03,0:51:44.76,Default,,0,0,0,,如果是其它情况 就报错\nDialogue: 0,0:51:44.76,0:51:45.72,Default,,0,0,0,,“未定义运算符”\nDialogue: 0,0:51:46.89,0:51:48.16,Default,,0,0,0,,这就是operate-2过程\nDialogue: 0,0:51:51.72,0:51:54.03,Default,,0,0,0,,这就是我们要做的全部事情\nDialogue: 0,0:51:55.16,0:51:57.45,Default,,0,0,0,,我们刚刚才写好了一个复数运算包\nDialogue: 0,0:51:57.64,0:52:01.00,Default,,0,0,0,,那么怎么把它放进这个通用系统里面呢？\nDialogue: 0,0:52:02.14,0:52:02.91,Default,,0,0,0,,方法几乎是一样的\nDialogue: 0,0:52:06.41,0:52:08.59,Default,,0,0,0,,我们构造一个叫做make-complex的过程\nDialogue: 0,0:52:09.95,0:52:12.81,Default,,0,0,0,,它把George和Martha给我们的东西\nDialogue: 0,0:52:13.64,0:52:15.00,Default,,0,0,0,,贴上complex的类型标志\nDialogue: 0,0:52:18.17,0:52:23.87,Default,,0,0,0,,然后我们说 要把复数相加 这个+complex过程\nDialogue: 0,0:52:25.84,0:52:28.78,Default,,0,0,0,,用我们的内部过程 +c\nDialogue: 0,0:52:30.78,0:52:32.24,Default,,0,0,0,,把结果加上类型\nDialogue: 0,0:52:32.24,0:52:33.42,Default,,0,0,0,,让它变成复数类型\nDialogue: 0,0:52:37.68,0:52:42.52,Default,,0,0,0,,那么我们的包里原来有+c和-c这两个过程\nDialogue: 0,0:52:42.68,0:52:44.75,Default,,0,0,0,,用来和George和Martha通信\nDialogue: 0,0:52:45.25,0:52:47.39,Default,,0,0,0,,然后为了与外部通信\nDialogue: 0,0:52:47.40,0:52:53.04,Default,,0,0,0,,我们还有+complex和-complex\nDialogue: 0,0:52:55.92,0:52:56.53,Default,,0,0,0,,等等\nDialogue: 0,0:52:56.53,0:52:59.98,Default,,0,0,0,,它们唯一的不同就在于：后者的返回的是带类型的值\nDialogue: 0,0:53:01.12,0:53:02.41,Default,,0,0,0,,它们可以在这里被查询\nDialogue: 0,0:53:02.85,0:53:05.02,Default,,0,0,0,,而这些是内部过程\nDialogue: 0,0:53:09.25,0:53:10.68,Default,,0,0,0,,我们再来看那个幻灯片\nDialogue: 0,0:53:10.68,0:53:13.04,Default,,0,0,0,,我们还有一件事要做\nDialogue: 0,0:53:13.74,0:53:15.61,Default,,0,0,0,,在定义了+complex之后\nDialogue: 0,0:53:15.68,0:53:20.52,Default,,0,0,0,,我们在complex类型和add符号对应的格子中\nDialogue: 0,0:53:21.31,0:53:22.75,Default,,0,0,0,,填上过程+complex\nDialogue: 0,0:53:23.20,0:53:26.75,Default,,0,0,0,,对于-complex也类似\nDialogue: 0,0:53:27.13,0:53:29.13,Default,,0,0,0,,*complex和/complex亦如此\nDialogue: 0,0:53:31.70,0:53:33.48,Default,,0,0,0,,那我们怎么安装寻常算术呢？\nDialogue: 0,0:53:35.25,0:53:36.12,Default,,0,0,0,,方法还是一样的\nDialogue: 0,0:53:38.16,0:53:41.36,Default,,0,0,0,,我们会写一个叫做make-number的过程\nDialogue: 0,0:53:44.34,0:53:48.11,Default,,0,0,0,,make-number接收一个数 然后给它加上类型\nDialogue: 0,0:53:48.14,0:53:49.29,Default,,0,0,0,,也就是符号number\nDialogue: 0,0:53:50.26,0:53:52.11,Default,,0,0,0,,我们构造一个过程叫做+number\nDialogue: 0,0:53:52.92,0:53:58.75,Default,,0,0,0,,用Lisp自带的加法把两个数加起来\nDialogue: 0,0:53:58.92,0:54:00.78,Default,,0,0,0,,因为我们现在讨论的是寻常算术\nDialogue: 0,0:54:01.31,0:54:03.10,Default,,0,0,0,,给它加上类型 让它变成number类型\nDialogue: 0,0:54:04.51,0:54:08.09,Default,,0,0,0,,然后我们把+number过程放到\nDialogue: 0,0:54:08.59,0:54:11.00,Default,,0,0,0,,表格里number和add对应的的格子中\nDialogue: 0,0:54:12.30,0:54:16.16,Default,,0,0,0,,再用相同的方法把减法 乘法 除法也放进去\nDialogue: 0,0:54:22.67,0:54:26.06,Default,,0,0,0,,我们举一个例子 就看得清楚一点\nDialogue: 0,0:54:26.06,0:54:28.75,Default,,0,0,0,,假设 比如说\nDialogue: 0,0:54:32.28,0:54:34.15,Default,,0,0,0,,我要执行这个运算\nDialogue: 0,0:54:34.15,0:54:38.22,Default,,0,0,0,,好 现在我要执行一个运算\nDialogue: 0,0:54:38.22,0:54:40.46,Default,,0,0,0,,比如说我把两个复数乘起来\nDialogue: 0,0:54:40.93,0:54:48.64,Default,,0,0,0,,把3+4i和2+6i乘起来\nDialogue: 0,0:54:50.17,0:54:52.60,Default,,0,0,0,,这就是我调用mul过程要传入的参数\nDialogue: 0,0:54:52.84,0:54:55.76,Default,,0,0,0,,这里就代表通用运算符mul\nDialogue: 0,0:54:57.17,0:54:57.98,Default,,0,0,0,,那么它怎么工作呢\nDialogue: 0,0:54:58.28,0:55:04.60,Default,,0,0,0,,我们讲3+4i 在整个系统里\nDialogue: 0,0:55:04.83,0:55:06.11,Default,,0,0,0,,处于这样的一个位置\nDialogue: 0,0:55:06.25,0:55:07.52,Default,,0,0,0,,假设它是George那种方法表示的\nDialogue: 0,0:55:08.28,0:55:14.97,Default,,0,0,0,,所以它的内部有一个3和一个4\nDialogue: 0,0:55:18.49,0:55:20.97,Default,,0,0,0,,这上面还贴着George的类型标志\nDialogue: 0,0:55:24.33,0:55:28.32,Default,,0,0,0,,是他构造的rectangular类型\nDialogue: 0,0:55:29.51,0:55:30.57,Default,,0,0,0,,又附加在那上面的\nDialogue: 0,0:55:31.23,0:55:35.79,Default,,0,0,0,,从更上一层的视角来看这一段数据\nDialogue: 0,0:55:36.19,0:55:36.78,Default,,0,0,0,,它又是一个\nDialogue: 0,0:55:37.93,0:55:39.96,Default,,0,0,0,,这整个又是一个带类型的数据\nDialogue: 0,0:55:40.60,0:55:41.80,Default,,0,0,0,,它的类型是complex\nDialogue: 0,0:55:44.82,0:55:47.31,Default,,0,0,0,,那么这就是这个对象\nDialogue: 0,0:55:48.64,0:55:50.24,Default,,0,0,0,,在最高层视角中的样子\nDialogue: 0,0:55:50.68,0:55:53.56,Default,,0,0,0,,那些通用运算符看到的对象 就是这样的\nDialogue: 0,0:55:55.56,0:55:58.72,Default,,0,0,0,,现在 mul过程会过来问\nDialogue: 0,0:55:58.84,0:56:00.40,Default,,0,0,0,,它的类型是什么？\nDialogue: 0,0:56:00.48,0:56:01.48,Default,,0,0,0,,它的类型是complex\nDialogue: 0,0:56:04.27,0:56:06.46,Default,,0,0,0,,然后运行到operate-2 然后说\nDialogue: 0,0:56:06.46,0:56:09.72,Default,,0,0,0,,啊 我想要把表格里的过程\nDialogue: 0,0:56:09.72,0:56:13.04,Default,,0,0,0,,也就是*complex这个过程\nDialogue: 0,0:56:15.08,0:56:17.76,Default,,0,0,0,,应用到 将其类型剥离之后的结果上去\nDialogue: 0,0:56:17.95,0:56:19.28,Default,,0,0,0,,所以它会把类型剥下来\nDialogue: 0,0:56:19.93,0:56:24.24,Default,,0,0,0,,把剩下的东西传递给复数的世界\nDialogue: 0,0:56:26.70,0:56:28.73,Default,,0,0,0,,复数的世界看了看它有的运算操作 然后说\nDialogue: 0,0:56:28.76,0:56:30.56,Default,,0,0,0,,“我得调用*c这个过程”\nDialogue: 0,0:56:31.28,0:56:32.14,Default,,0,0,0,,然后*c过程说\nDialogue: 0,0:56:32.22,0:56:37.20,Default,,0,0,0,,我想知道这个东西的模值是多少\nDialogue: 0,0:56:39.42,0:56:40.16,Default,,0,0,0,,然后它们会说 啊\nDialogue: 0,0:56:40.16,0:56:41.71,Default,,0,0,0,,它是直角坐标表示的 是George的东西\nDialogue: 0,0:56:41.87,0:56:44.41,Default,,0,0,0,,所以它们又剥掉了一个类型\nDialogue: 0,0:56:46.91,0:56:49.80,Default,,0,0,0,,然后把内容交给George 让他提取出它的模值\nDialogue: 0,0:56:52.16,0:56:53.13,Default,,0,0,0,,那么我们看到\nDialogue: 0,0:56:53.44,0:56:56.99,Default,,0,0,0,,这其中有一条由类型构成的链条\nDialogue: 0,0:56:59.32,0:57:01.50,Default,,0,0,0,,这个链条的长度就是你要\nDialogue: 0,0:57:01.53,0:57:03.13,Default,,0,0,0,,在这个表格里上升的层数\nDialogue: 0,0:57:05.09,0:57:05.96,Default,,0,0,0,,类型的作用则是\nDialogue: 0,0:57:05.96,0:57:10.84,Default,,0,0,0,,每当我们在表格中遇到一道垂直屏障时\nDialogue: 0,0:57:11.05,0:57:14.06,Default,,0,0,0,,你不知道该如何抉择时\nDialogue: 0,0:57:14.41,0:57:15.85,Default,,0,0,0,,类型就会给你指路\nDialogue: 0,0:57:17.44,0:57:18.83,Default,,0,0,0,,然后最底层的过程\nDialogue: 0,0:57:18.97,0:57:20.67,Default,,0,0,0,,它们构造数据结构 对数据进行筛选之后\nDialogue: 0,0:57:21.12,0:57:22.81,Default,,0,0,0,,再把类型贴回去\nDialogue: 0,0:57:25.35,0:57:30.75,Default,,0,0,0,,这就是整个系统的总体结构\nDialogue: 0,0:57:33.41,0:57:33.77,Default,,0,0,0,,好\nDialogue: 0,0:57:34.82,0:57:35.68,Default,,0,0,0,,明白了这个之后\nDialogue: 0,0:57:37.56,0:57:39.44,Default,,0,0,0,,我们再让这个系统变得更加复杂\nDialogue: 0,0:57:41.89,0:57:46.54,Default,,0,0,0,,我们这次不光要在系统里添加新的数域\nDialogue: 0,0:57:46.60,0:57:51.15,Default,,0,0,0,,我们也来讨论一下怎么把多项式也加进去\nDialogue: 0,0:57:51.51,0:57:52.97,Default,,0,0,0,,让它能做多项式算术\nDialogue: 0,0:57:53.36,0:58:03.71,Default,,0,0,0,,比如我们可以计算x^15+2x^7+5\nDialogue: 0,0:58:04.48,0:58:05.84,Default,,0,0,0,,像这样的多项式\nDialogue: 0,0:58:06.38,0:58:07.93,Default,,0,0,0,,如果有两个这样的东西\nDialogue: 0,0:58:07.93,0:58:09.48,Default,,0,0,0,,我们可以把它们相加或者相乘\nDialogue: 0,0:58:10.53,0:58:11.79,Default,,0,0,0,,先不管相除的问题\nDialogue: 0,0:58:12.14,0:58:14.67,Default,,0,0,0,,只考虑相加相乘和相减\nDialogue: 0,0:58:15.55,0:58:17.16,Default,,0,0,0,,我们需要做什么\nDialogue: 0,0:58:18.52,0:58:20.76,Default,,0,0,0,,我们先来想想怎么表示一个多项式\nDialogue: 0,0:58:21.83,0:58:23.55,Default,,0,0,0,,它也是一种带类型的数据\nDialogue: 0,0:58:24.73,0:58:27.55,Default,,0,0,0,,这个系统里的一个多项式\nDialogue: 0,0:58:28.54,0:58:31.68,Default,,0,0,0,,应该是带有polynomial类型的对象\nDialogue: 0,0:58:32.00,0:58:34.55,Default,,0,0,0,,接下来它可能要问这个多项式的变量是哪个\nDialogue: 0,0:58:34.55,0:58:37.69,Default,,0,0,0,,比如这是一个以x为变量的多项式\nDialogue: 0,0:58:38.96,0:58:41.39,Default,,0,0,0,,然后 多项式内还有各项的信息\nDialogue: 0,0:58:42.25,0:58:44.16,Default,,0,0,0,,有很多种方法来实现\nDialogue: 0,0:58:44.25,0:58:47.63,Default,,0,0,0,,我们采用的方法是构造一个“项表”\nDialogue: 0,0:58:51.52,0:58:52.24,Default,,0,0,0,,所谓的“项表”\nDialogue: 0,0:58:53.70,0:58:55.61,Default,,0,0,0,,本例中 我们用的是类似这样的东西\nDialogue: 0,0:58:56.36,0:58:59.68,Default,,0,0,0,,我们把它写成一系列 按次数排列的序对\nDialogue: 0,0:58:59.69,0:59:05.80,Default,,0,0,0,,那么这个项表就能表示这个多项式了\nDialogue: 0,0:59:09.42,0:59:10.68,Default,,0,0,0,,它的意义是\nDialogue: 0,0:59:11.48,0:59:19.71,Default,,0,0,0,,这个多项式第一项的次数是15 系数是1\nDialogue: 0,0:59:23.82,0:59:27.50,Default,,0,0,0,,然后下一项的次数是7 系数是2\nDialogue: 0,0:59:27.53,0:59:30.49,Default,,0,0,0,,再下一项是一个常数 它次数是0 系数是5\nDialogue: 0,0:59:31.45,0:59:34.16,Default,,0,0,0,,实际上有很多很多种方法\nDialogue: 0,0:59:34.25,0:59:35.96,Default,,0,0,0,,也有很多很多的取舍\nDialogue: 0,0:59:36.01,0:59:39.10,Default,,0,0,0,,在你认真思考如何实现代数操作程序包时\nDialogue: 0,0:59:39.44,0:59:41.73,Default,,0,0,0,,你该如何表示这些东西\nDialogue: 0,0:59:42.01,0:59:43.68,Default,,0,0,0,,但是我们这种是比较标准的一种\nDialogue: 0,0:59:44.18,0:59:45.55,Default,,0,0,0,,它适用于很多情况\nDialogue: 0,0:59:47.77,0:59:50.99,Default,,0,0,0,,好 那么我们怎么实现我们的多项式算术呢\nDialogue: 0,0:59:53.47,0:59:54.96,Default,,0,0,0,,现在开始着手做这个事情\nDialogue: 0,0:59:57.95,1:00:00.28,Default,,0,0,0,,构造一个多项式 首先要\nDialogue: 0,1:00:00.76,1:00:04.12,Default,,0,0,0,,首先我们得找一个办法来构造多项式\nDialogue: 0,1:00:05.69,1:00:10.28,Default,,0,0,0,,我们可以用一个变量 比如x和一个项表来构造它们\nDialogue: 0,1:00:11.24,1:00:14.09,Default,,0,0,0,,我们要用某种方法把它们包装起来\nDialogue: 0,1:00:14.30,1:00:19.40,Default,,0,0,0,,我们可以用cons把变量和项表组合起来\nDialogue: 0,1:00:19.82,1:00:21.74,Default,,0,0,0,,然后把这个序对加上polynomial的类型标志\nDialogue: 0,1:00:26.27,1:00:27.77,Default,,0,0,0,,那我们怎么处理多项式相加呢？\nDialogue: 0,1:00:29.28,1:00:31.85,Default,,0,0,0,,要相加两个多项式 p1和p2\nDialogue: 0,1:00:32.68,1:00:35.18,Default,,0,0,0,,为了简化问题 假设我们\nDialogue: 0,1:00:35.37,1:00:37.15,Default,,0,0,0,,我们只相加变量相同的两个式子\nDialogue: 0,1:00:37.38,1:00:39.28,Default,,0,0,0,,那么如果它们的变量相同\nDialogue: 0,1:00:39.69,1:00:42.57,Default,,0,0,0,,是否相同交由我们编写的选择函数判断\nDialogue: 0,1:00:42.96,1:00:44.38,Default,,0,0,0,,我们不必在意它的细节\nDialogue: 0,1:00:45.15,1:00:47.04,Default,,0,0,0,,如果两个多项式的变量相同\nDialogue: 0,1:00:48.03,1:00:48.81,Default,,0,0,0,,我们就继续运算\nDialogue: 0,1:00:48.81,1:00:51.26,Default,,0,0,0,,如果它们的变量不相同 我们返回一个错误\nDialogue: 0,1:00:52.35,1:00:54.01,Default,,0,0,0,,“两个多项式的变量不相同”\nDialogue: 0,1:00:55.48,1:00:57.37,Default,,0,0,0,,如果它们的变量确实是相同\nDialogue: 0,1:00:57.60,1:00:59.18,Default,,0,0,0,,我们就要构造一个新的多项式\nDialogue: 0,1:00:59.80,1:01:01.85,Default,,0,0,0,,它的变量即是原式的变量\nDialogue: 0,1:01:03.15,1:01:06.56,Default,,0,0,0,,它的项表则由过程+terms产生\nDialogue: 0,1:01:07.48,1:01:09.80,Default,,0,0,0,,+terms过程会把两个项表加起来\nDialogue: 0,1:01:10.17,1:01:12.01,Default,,0,0,0,,所以我们要把两个多项式的项表合起来\nDialogue: 0,1:01:13.50,1:01:14.51,Default,,0,0,0,,该过程即可返回一个项表\nDialogue: 0,1:01:15.00,1:01:20.01,Default,,0,0,0,,我们将变量和得到的项表构造成新的多项式\nDialogue: 0,1:01:20.68,1:01:21.79,Default,,0,0,0,,这就是+poly过程\nDialogue: 0,1:01:22.55,1:01:27.00,Default,,0,0,0,,然后我们要把这个过程放进表格中polynomial那一栏\nDialogue: 0,1:01:28.24,1:01:30.14,Default,,0,0,0,,用+poly实现add操作\nDialogue: 0,1:01:30.52,1:01:31.75,Default,,0,0,0,,当然实际上没做多少事情\nDialogue: 0,1:01:31.75,1:01:35.31,Default,,0,0,0,,我们只是把所有的工作压到+terms的头上\nDialogue: 0,1:01:35.79,1:01:37.02,Default,,0,0,0,,它会负责把项表相加起来\nDialogue: 0,1:01:37.74,1:01:39.16,Default,,0,0,0,,我们看看这个过程\nDialogue: 0,1:01:39.18,1:01:48.03,Default,,0,0,0,,这是+terms过程的大概结构\nDialogue: 0,1:01:48.90,1:01:51.74,Default,,0,0,0,,L1和L2是两个项表\nDialogue: 0,1:01:52.00,1:01:54.81,Default,,0,0,0,,所谓“项表”即是按每项次数排序的序对\nDialogue: 0,1:01:55.70,1:01:56.95,Default,,0,0,0,,这里有一个大的分情况分析\nDialogue: 0,1:01:59.86,1:02:04.14,Default,,0,0,0,,首先 我们要检查项表是否为空\nDialogue: 0,1:02:05.39,1:02:07.55,Default,,0,0,0,,我们对项表做递归下降处理\nDialogue: 0,1:02:08.16,1:02:11.74,Default,,0,0,0,,最终下降到 L1或L2为空\nDialogue: 0,1:02:12.27,1:02:14.35,Default,,0,0,0,,只要其中有一个为空\nDialogue: 0,1:02:14.52,1:02:15.85,Default,,0,0,0,,我们的答案就是剩下的另一个\nDialogue: 0,1:02:15.85,1:02:19.55,Default,,0,0,0,,就是说如果L1是空表 我们就返回L2\nDialogue: 0,1:02:19.63,1:02:21.71,Default,,0,0,0,,L2是空表的话就返回L1\nDialogue: 0,1:02:23.26,1:02:25.76,Default,,0,0,0,,除此之外还有三种情况\nDialogue: 0,1:02:27.22,1:02:27.98,Default,,0,0,0,,我们要做的是\nDialogue: 0,1:02:29.08,1:02:31.05,Default,,0,0,0,,取表中的第一项\nDialogue: 0,1:02:33.50,1:02:36.04,Default,,0,0,0,,记为t1和t2\nDialogue: 0,1:02:37.66,1:02:39.05,Default,,0,0,0,,我们来分析一下这三种情况\nDialogue: 0,1:02:39.60,1:02:45.68,Default,,0,0,0,,分别是t1的次数大于t2的\nDialogue: 0,1:02:47.23,1:02:50.59,Default,,0,0,0,,小于t2的 或者等于t2的\nDialogue: 0,1:02:53.28,1:02:54.91,Default,,0,0,0,,这就是我们要判断的三种情况\nDialogue: 0,1:02:54.91,1:02:55.84,Default,,0,0,0,,先看看这一种\nDialogue: 0,1:02:58.64,1:03:01.31,Default,,0,0,0,,如果t1的次数比t2的次数要高\nDialogue: 0,1:03:03.40,1:03:04.70,Default,,0,0,0,,就意味着\nDialogue: 0,1:03:06.06,1:03:09.96,Default,,0,0,0,,答案的第一项的次数就是t1的次数\nDialogue: 0,1:03:11.56,1:03:13.80,Default,,0,0,0,,因为高次项不会和任何低次项相加\nDialogue: 0,1:03:14.17,1:03:16.19,Default,,0,0,0,,那么我们只需要把低次的项加起来\nDialogue: 0,1:03:16.76,1:03:18.25,Default,,0,0,0,,我们递归地把\nDialogue: 0,1:03:19.71,1:03:25.07,Default,,0,0,0,,把L1和L2两个项表里剩下的项相加\nDialogue: 0,1:03:27.13,1:03:29.32,Default,,0,0,0,,作为我们的答案中低次项\nDialogue: 0,1:03:30.12,1:03:32.48,Default,,0,0,0,,然后我们把它们和最高次的项连接起来\nDialogue: 0,1:03:33.18,1:03:35.45,Default,,0,0,0,,这里 我用了一对还未定义的过程\nDialogue: 0,1:03:35.47,1:03:37.55,Default,,0,0,0,,比如adjoin-term、rest-terms\nDialogue: 0,1:03:38.48,1:03:40.17,Default,,0,0,0,,还有获取次数的选择函数\nDialogue: 0,1:03:41.15,1:03:42.78,Default,,0,0,0,,但是你可以想象它们是什么样子的\nDialogue: 0,1:03:44.44,1:03:48.76,Default,,0,0,0,,那么如果第一个项表的次数比第二个要高\nDialogue: 0,1:03:48.78,1:03:51.08,Default,,0,0,0,,我们就递归地把所有的低次的项相加\nDialogue: 0,1:03:51.28,1:03:53.42,Default,,0,0,0,,再和最高次项连接起来\nDialogue: 0,1:03:55.54,1:03:56.75,Default,,0,0,0,,其它情况也是一样的\nDialogue: 0,1:03:56.89,1:04:00.28,Default,,0,0,0,,如果第一个多项式次数比较低\nDialogue: 0,1:04:00.54,1:04:08.36,Default,,0,0,0,,我们就把整个第一个多项式和第二个多项式低次的项相加\nDialogue: 0,1:04:08.62,1:04:12.65,Default,,0,0,0,,然后把结果再和最高次项连起来\nDialogue: 0,1:04:14.57,1:04:15.96,Default,,0,0,0,,到现在也没多少复杂的事情\nDialogue: 0,1:04:15.96,1:04:19.40,Default,,0,0,0,,把问题变成 让低次数的项相加\nDialogue: 0,1:04:19.47,1:04:21.96,Default,,0,0,0,,还有最后一种情况是 两个多项式的次数一样\nDialogue: 0,1:04:22.57,1:04:25.18,Default,,0,0,0,,你必须要把它们的系数加起来 因为它们是同类项\nDialogue: 0,1:04:27.24,1:04:30.99,Default,,0,0,0,,我们的应对方法仍然是 递归地把低次项相加\nDialogue: 0,1:04:31.00,1:04:32.83,Default,,0,0,0,,但现在我们需要合并一些项了\nDialogue: 0,1:04:33.46,1:04:36.35,Default,,0,0,0,,我们构造一个项\nDialogue: 0,1:04:37.31,1:04:39.93,Default,,0,0,0,,其次数为我们正在处理的那一项的次数\nDialogue: 0,1:04:40.82,1:04:42.72,Default,,0,0,0,,因为现在t1和t2的次数是相同的\nDialogue: 0,1:04:44.32,1:04:44.99,Default,,0,0,0,,确定好次数了\nDialogue: 0,1:04:45.09,1:04:52.33,Default,,0,0,0,,而它的系数是t1和t2系数之和\nDialogue: 0,1:04:55.79,1:04:59.64,Default,,0,0,0,,这是一个庞大的递归过程\nDialogue: 0,1:04:59.68,1:05:03.61,Default,,0,0,0,,但其中只有一个符号值得玩味\nDialogue: 0,1:05:04.25,1:05:05.69,Default,,0,0,0,,它蕴含了重要的思想\nDialogue: 0,1:05:05.90,1:05:08.50,Default,,0,0,0,,那就是这个ADD过程\nDialogue: 0,1:05:12.39,1:05:14.80,Default,,0,0,0,,说它有趣是因为\nDialogue: 0,1:05:15.42,1:05:17.37,Default,,0,0,0,,有一件好事发生\nDialogue: 0,1:05:18.22,1:05:21.37,Default,,0,0,0,,我们没有把多项式加法\nDialogue: 0,1:05:22.56,1:05:26.46,Default,,0,0,0,,归约为某种加法 而是归约为通用运算符ADD\nDialogue: 0,1:05:28.82,1:05:32.28,Default,,0,0,0,,换句话说 用这种方法实现它之后\nDialogue: 0,1:05:32.89,1:05:34.68,Default,,0,0,0,,我们的系统就不光有\nDialogue: 0,1:05:35.92,1:05:41.66,Default,,0,0,0,,有理数、复数还有寻常算术\nDialogue: 0,1:05:41.85,1:05:43.82,Default,,0,0,0,,我们同时也让它支持多项式运算了\nDialogue: 0,1:05:48.52,1:05:51.13,Default,,0,0,0,,而多项式的系数可以是\nDialogue: 0,1:05:51.24,1:05:52.86,Default,,0,0,0,,这个系统能够相加的任何东西\nDialogue: 0,1:05:53.59,1:05:56.73,Default,,0,0,0,,也就是说多项式的系数\nDialogue: 0,1:05:57.20,1:06:01.20,Default,,0,0,0,,有理数或者复数\nDialogue: 0,1:06:02.76,1:06:06.99,Default,,0,0,0,,复数同时可支持直角坐标形式和极坐标形式\nDialogue: 0,1:06:09.12,1:06:11.39,Default,,0,0,0,,系数还可以是寻常的数字\nDialogue: 0,1:06:18.97,1:06:21.21,Default,,0,0,0,,我想说的是\nDialogue: 0,1:06:22.06,1:06:24.35,Default,,0,0,0,,我们的系统现在可以自动地\nDialogue: 0,1:06:26.60,1:06:31.50,Default,,0,0,0,,处理像这样的式子\nDialogue: 0,1:06:31.53,1:06:39.69,Default,,0,0,0,,比如2/3x^2+5/17x+11/4这样的式子\nDialogue: 0,1:06:40.94,1:06:43.48,Default,,0,0,0,,也可以自动处理像是\nDialogue: 0,1:06:43.82,1:06:52.57,Default,,0,0,0,,(3+2i)x^5+(4+7i)这样的式子\nDialogue: 0,1:06:53.88,1:06:56.21,Default,,0,0,0,,系统可以自动处理这些运算\nDialogue: 0,1:06:56.21,1:06:57.07,Default,,0,0,0,,为什么呢？\nDialogue: 0,1:06:57.82,1:07:01.50,Default,,0,0,0,,仅仅是因为 或者说深层次的原因是\nDialogue: 0,1:07:02.17,1:07:05.93,Default,,0,0,0,,我们把多项式相加归约成了把它们的系数相加\nDialogue: 0,1:07:06.79,1:07:10.22,Default,,0,0,0,,而系数的相加是由通用运算符ADD完成的\nDialogue: 0,1:07:11.08,1:07:12.94,Default,,0,0,0,,它说：“我不管你的数据类型是什么”\nDialogue: 0,1:07:12.96,1:07:14.08,Default,,0,0,0,,“只要我能够处理就行”\nDialogue: 0,1:07:15.23,1:07:18.86,Default,,0,0,0,,于是我们就“免费”获得了处理这些东西的功能\nDialogue: 0,1:07:20.65,1:07:22.04,Default,,0,0,0,,更神奇的是\nDialogue: 0,1:07:24.51,1:07:26.52,Default,,0,0,0,,我们曾把\nDialogue: 0,1:07:27.20,1:07:30.52,Default,,0,0,0,,我们放入表格中 用于处理多项式加法\nDialogue: 0,1:07:31.28,1:07:32.52,Default,,0,0,0,,是用的+poly过程\nDialogue: 0,1:07:34.66,1:07:38.65,Default,,0,0,0,,这就意味着ADD过程也可以处理多项式了\nDialogue: 0,1:07:39.42,1:07:42.11,Default,,0,0,0,,我举个例子\nDialogue: 0,1:07:43.18,1:07:46.19,Default,,0,0,0,,这是一个多项式\nDialogue: 0,1:07:50.56,1:07:52.41,Default,,0,0,0,,我正在写的这个东西\nDialogue: 0,1:07:54.12,1:07:58.46,Default,,0,0,0,,它是一个以y作为变量的多项式\nDialogue: 0,1:08:01.07,1:08:04.69,Default,,0,0,0,,每项的系数是以x作为变量的多项式\nDialogue: 0,1:08:08.61,1:08:11.12,Default,,0,0,0,,你将看到\nDialogue: 0,1:08:11.76,1:08:14.06,Default,,0,0,0,,由于 “ADD过程能够处理多项式”\nDialogue: 0,1:08:14.41,1:08:17.90,Default,,0,0,0,,我们可以说 我们的系统现在不光能运算有理数\nDialogue: 0,1:08:18.27,1:08:20.33,Default,,0,0,0,,复数和一般数字\nDialogue: 0,1:08:20.35,1:08:21.77,Default,,0,0,0,,我们还可以处理多项式\nDialogue: 0,1:08:22.09,1:08:25.39,Default,,0,0,0,,多项式的系数可以是有理数、复数、一般数字\nDialogue: 0,1:08:25.50,1:08:27.52,Default,,0,0,0,,甚至是多项式\nDialogue: 0,1:08:29.15,1:08:30.96,Default,,0,0,0,,作为系数的多项式 其系数还可以是有理数\nDialogue: 0,1:08:31.69,1:08:36.76,Default,,0,0,0,,复数（直角或极坐标形式）或一般数字\nDialogue: 0,1:08:36.94,1:08:41.13,Default,,0,0,0,,甚至还可以是系数为有理数的多项式\nDialogue: 0,1:08:41.80,1:08:43.32,Default,,0,0,0,,系数为复数、一般数字的多项式\nDialogue: 0,1:08:43.67,1:08:45.21,Default,,0,0,0,,以此类推\nDialogue: 0,1:08:45.95,1:08:47.55,Default,,0,0,0,,我们构造出了一座无限延伸的\nDialogue: 0,1:08:48.49,1:08:52.88,Default,,0,0,0,,或者说是递归的类型高塔\nDialogue: 0,1:08:53.88,1:08:57.12,Default,,0,0,0,,这一切都来源于那个小小的符号：A-D-D\nDialogue: 0,1:08:57.61,1:09:00.49,Default,,0,0,0,,来源于在多项式程序里 用“ADD”来代替“+”\nDialogue: 0,1:09:02.27,1:09:03.77,Default,,0,0,0,,换一种方式来理解它就是\nDialogue: 0,1:09:03.95,1:09:07.74,Default,,0,0,0,,多项式也是一种类型的构造函数\nDialogue: 0,1:09:08.74,1:09:11.20,Default,,0,0,0,,也就是说你传递给它一个类型 比如整型\nDialogue: 0,1:09:11.48,1:09:15.74,Default,,0,0,0,,然后它就返回一个以整数作为系数的多项式\nDialogue: 0,1:09:16.27,1:09:17.72,Default,,0,0,0,,过程中很重要的一点是\nDialogue: 0,1:09:18.65,1:09:20.73,Default,,0,0,0,,就是多项式上的运算\nDialogue: 0,1:09:21.28,1:09:23.37,Default,,0,0,0,,归约成了关于系数的运算\nDialogue: 0,1:09:23.39,1:09:24.96,Default,,0,0,0,,很多地方都与这里类似\nDialogue: 0,1:09:25.84,1:09:27.92,Default,,0,0,0,,比如 我们再回头看看有理数\nDialogue: 0,1:09:28.87,1:09:32.65,Default,,0,0,0,,我们之前把有理数看做 一个整数在另一个上面\nDialogue: 0,1:09:32.67,1:09:35.66,Default,,0,0,0,,但这并不是关于有理式的一般性记号\nDialogue: 0,1:09:36.24,1:09:42.03,Default,,0,0,0,,比如我们也可以把3x+7放在上面 x^2+1放在下面\nDialogue: 0,1:09:43.07,1:09:48.86,Default,,0,0,0,,这是一个分子分母都是多项式的广义有理式\nDialogue: 0,1:09:50.31,1:09:52.41,Default,,0,0,0,,有理式相加 和有理数相加一样\nDialogue: 0,1:09:52.44,1:09:55.40,Default,,0,0,0,,分子乘分母 加 分母乘分子 结果作为分子\nDialogue: 0,1:09:55.72,1:09:56.99,Default,,0,0,0,,两个分母相乘 结果作为分母\nDialogue: 0,1:09:57.29,1:09:59.37,Default,,0,0,0,,怎么把它安装到我们的系统中呢？\nDialogue: 0,1:09:59.39,1:10:02.97,Default,,0,0,0,,这是我们原来的有理数算术程序包\nDialogue: 0,1:10:04.25,1:10:08.24,Default,,0,0,0,,为了让这个系统能够\nDialogue: 0,1:10:08.28,1:10:11.58,Default,,0,0,0,,支持广义有理式的运算\nDialogue: 0,1:10:11.85,1:10:16.44,Default,,0,0,0,,我们把特定的加法和乘法过程 都改成通用运算符\nDialogue: 0,1:10:16.48,1:10:19.18,Default,,0,0,0,,所以如果我们把原来那个过程变成这个过程\nDialogue: 0,1:10:19.71,1:10:22.04,Default,,0,0,0,,把+和*换成ADD和MUL\nDialogue: 0,1:10:22.88,1:10:24.48,Default,,0,0,0,,这些是唯一的改动\nDialogue: 0,1:10:24.84,1:10:26.03,Default,,0,0,0,,然后霎时间\nDialogue: 0,1:10:27.52,1:10:31.40,Default,,0,0,0,,我们的整个系统 就知道怎么运算这样的东西了\nDialogue: 0,1:10:33.72,1:10:38.27,Default,,0,0,0,,比如说 这里的这个有理式\nDialogue: 0,1:10:39.18,1:10:44.86,Default,,0,0,0,,它的分子是一个系数是有理数的、关于x的多项式\nDialogue: 0,1:10:47.02,1:10:49.56,Default,,0,0,0,,而这个有理式\nDialogue: 0,1:10:51.10,1:10:54.43,Default,,0,0,0,,它的分子是关于x的多项式\nDialogue: 0,1:10:55.15,1:10:58.19,Default,,0,0,0,,多项式的系数又是有理式\nDialogue: 0,1:10:59.77,1:11:01.53,Default,,0,0,0,,有理式又由复数组成\nDialogue: 0,1:11:03.39,1:11:04.85,Default,,0,0,0,,或者别的像这样的东西\nDialogue: 0,1:11:04.85,1:11:08.68,Default,,0,0,0,,看 只要能够归约成针对各部分的运算\nDialogue: 0,1:11:08.89,1:11:10.00,Default,,0,0,0,,另一个例子是\nDialogue: 0,1:11:10.28,1:11:11.42,Default,,0,0,0,,2*2的矩阵\nDialogue: 0,1:11:12.31,1:11:15.44,Default,,0,0,0,,假如有这样一个矩阵形式的东西\nDialogue: 0,1:11:16.43,1:11:18.33,Default,,0,0,0,,不管它里面是什么\nDialogue: 0,1:11:18.72,1:11:20.14,Default,,0,0,0,,但是如果我对两个这种东西调用ADD\nDialogue: 0,1:11:22.33,1:11:25.18,Default,,0,0,0,,答案就是\nDialogue: 0,1:11:25.18,1:11:28.14,Default,,0,0,0,,把这个和这个相加 而矩阵是怎么相加的\nDialogue: 0,1:11:29.03,1:11:31.11,Default,,0,0,0,,那么我可以用同样的方法实现\nDialogue: 0,1:11:31.11,1:11:31.71,Default,,0,0,0,,如果我这么做了\nDialogue: 0,1:11:31.96,1:11:34.60,Default,,0,0,0,,整个系统就马上可以处理像这样的东西了\nDialogue: 0,1:11:35.29,1:11:39.18,Default,,0,0,0,,比如说一个矩阵 它的元素都是\nDialogue: 0,1:11:39.46,1:11:42.16,Default,,0,0,0,,它的元素是一个有理式\nDialogue: 0,1:11:43.10,1:11:45.15,Default,,0,0,0,,这个有理式的分子分母都是多项式\nDialogue: 0,1:11:47.02,1:11:49.56,Default,,0,0,0,,我们自然而然地获得了这些功能\nDialogue: 0,1:11:51.28,1:11:53.82,Default,,0,0,0,,整个过程中发生了什么？\nDialogue: 0,1:11:53.92,1:11:56.17,Default,,0,0,0,,真正发生的是\nDialogue: 0,1:11:57.68,1:12:02.44,Default,,0,0,0,,我们摆脱了凡事都想插一手的经理\nDialogue: 0,1:12:03.12,1:12:06.19,Default,,0,0,0,,我们构造了一个“控制去中心化”的系统\nDialogue: 0,1:12:14.78,1:12:18.34,Default,,0,0,0,,你进入这个系统的时候 不会有人一边闲逛一边说\nDialogue: 0,1:12:18.35,1:12:22.30,Default,,0,0,0,,我看看官方列表中ADD是否能够处理你\nDialogue: 0,1:12:22.44,1:12:26.22,Default,,0,0,0,,你直接就可以用正确的方法 把你和别的东西加起来\nDialogue: 0,1:12:27.81,1:12:31.03,Default,,0,0,0,,这么做的好处就是 就连这种非常非常\nDialogue: 0,1:12:31.03,1:12:33.87,Default,,0,0,0,,复杂的分层对象也可以被分解后\nDialogue: 0,1:12:33.87,1:12:35.55,Default,,0,0,0,,自动放到正确的地方去处理\nDialogue: 0,1:12:37.00,1:12:37.79,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:12:40.38,1:12:42.32,Default,,0,0,0,,学生：你说你“免费”获得了这些功能\nDialogue: 0,1:12:42.35,1:12:45.82,Default,,0,0,0,,但是我在意的是你现在丢掉了\nDialogue: 0,1:12:46.48,1:12:50.91,Default,,0,0,0,,某种上下层之间的清楚界限\nDialogue: 0,1:12:50.91,1:12:52.77,Default,,0,0,0,,或者说 现在你是在用\nDialogue: 0,1:12:52.77,1:12:56.08,Default,,0,0,0,,上层的东西来定义下层的过程\nDialogue: 0,1:12:56.61,1:12:59.45,Default,,0,0,0,,这不是很危险吗？\nDialogue: 0,1:13:00.35,1:13:04.49,Default,,0,0,0,,或者说 结构会变得混乱？\nDialogue: 0,1:13:05.44,1:13:05.95,Default,,0,0,0,,教授：不 我--\nDialogue: 0,1:13:06.41,1:13:07.77,Default,,0,0,0,,你问它的结构是否混乱\nDialogue: 0,1:13:07.77,1:13:08.69,Default,,0,0,0,,这得要看你说的“结构”是指什么\nDialogue: 0,1:13:08.69,1:13:10.17,Default,,0,0,0,,整个过程里我们都在做递归\nDialogue: 0,1:13:11.05,1:13:18.80,Default,,0,0,0,,看 就是说要把这些东西相加就要用到这个过程\nDialogue: 0,1:13:19.15,1:13:21.37,Default,,0,0,0,,它是一种递归结构 并不混乱\nDialogue: 0,1:13:22.70,1:13:24.99,Default,,0,0,0,,所以我不认为它不清楚\nDialogue: 0,1:13:24.99,1:13:28.16,Default,,0,0,0,,学生：那么当你修改乘法或加法运算时\nDialogue: 0,1:13:29.34,1:13:31.38,Default,,0,0,0,,可能会导致\nDialogue: 0,1:13:31.38,1:13:34.27,Default,,0,0,0,,无法预测的灾难性后果\nDialogue: 0,1:13:34.48,1:13:36.44,Default,,0,0,0,,教授：你说得对 但是那要看你的意思是什么\nDialogue: 0,1:13:37.08,1:13:38.47,Default,,0,0,0,,从两个角度来讨论\nDialogue: 0,1:13:39.10,1:13:43.24,Default,,0,0,0,,举个什么例子好呢？\nDialogue: 0,1:13:44.69,1:13:47.50,Default,,0,0,0,,比如说 之前我忽略了GCD运算\nDialogue: 0,1:13:47.77,1:13:50.08,Default,,0,0,0,,我们忽略了它 是为了简化我们的例子\nDialogue: 0,1:13:50.28,1:13:56.92,Default,,0,0,0,,但是如果突然我觉得 这里的+rat\nDialogue: 0,1:13:57.82,1:14:01.69,Default,,0,0,0,,应该把结果约分 然后把这个功能安装到程序里\nDialogue: 0,1:14:03.34,1:14:07.87,Default,,0,0,0,,那么这个功能一旦安装 就立刻可以被所有过程调用\nDialogue: 0,1:14:08.03,1:14:10.08,Default,,0,0,0,,被这个或者那个 所有的这些\nDialogue: 0,1:14:11.56,1:14:13.89,Default,,0,0,0,,这取决于你系统的相干性（耦合度）\nDialogue: 0,1:14:13.89,1:14:17.03,Default,,0,0,0,,确实你可能想设计一个\nDialogue: 0,1:14:17.03,1:14:19.56,Default,,0,0,0,,不这样递归下降的程序\nDialogue: 0,1:14:19.61,1:14:22.97,Default,,0,0,0,,但是我举这个例子的好处 就在于我们通常都是这么做的\nDialogue: 0,1:14:25.44,1:14:27.63,Default,,0,0,0,,学生：是不是有一个问题 我想\nDialogue: 0,1:14:27.63,1:14:32.95,Default,,0,0,0,,就是你会被这个结构捆绑起来\nDialogue: 0,1:14:32.95,1:14:36.33,Default,,0,0,0,,这个递归的结构是实际上被执行了的\nDialogue: 0,1:14:36.33,1:14:40.34,Default,,0,0,0,,而不是仅仅是为了定义类型的需要\nDialogue: 0,1:14:40.34,1:14:41.16,Default,,0,0,0,,被这个事实所束缚\nDialogue: 0,1:14:44.68,1:14:46.12,Default,,0,0,0,,教授：我大概明白你的意思\nDialogue: 0,1:14:46.12,1:14:47.80,Default,,0,0,0,,你是想说在这个系统投入运行之后\nDialogue: 0,1:14:47.82,1:14:50.40,Default,,0,0,0,,这些类型还会变得越来越复杂\nDialogue: 0,1:14:50.40,1:14:50.73,Default,,0,0,0,,你是不是想……\nDialogue: 0,1:14:50.73,1:14:50.99,Default,,0,0,0,,学生：对\nDialogue: 0,1:14:50.99,1:14:51.79,Default,,0,0,0,,在它投入运行之后\nDialogue: 0,1:14:52.09,1:14:54.18,Default,,0,0,0,,学生：而不是作为基本的定义\nDialogue: 0,1:14:54.18,1:14:54.83,Default,,0,0,0,,教授：对\nDialogue: 0,1:14:54.83,1:14:56.70,Default,,0,0,0,,我们的类型结构可以说就是递归的\nDialogue: 0,1:14:57.21,1:15:00.22,Default,,0,0,0,,它并不是一个 可以在系统投入运行之前\nDialogue: 0,1:15:01.58,1:15:04.85,Default,,0,0,0,,就能把要用到的东西全部包括的列表\nDialogue: 0,1:15:04.85,1:15:05.79,Default,,0,0,0,,它是一个不断演进的东西\nDialogue: 0,1:15:06.78,1:15:08.64,Default,,0,0,0,,所以如果你想要定制这个系统\nDialogue: 0,1:15:08.67,1:15:10.96,Default,,0,0,0,,你就不能通过有限的表\nDialogue: 0,1:15:11.00,1:15:13.18,Default,,0,0,0,,你需要用一个递归结构实现它\nDialogue: 0,1:15:13.67,1:15:17.90,Default,,0,0,0,,学生：因为类型的基本结构是相当简单而明了的\nDialogue: 0,1:15:17.90,1:15:18.19,Default,,0,0,0,,教授：对\nDialogue: 0,1:15:20.40,1:15:20.75,Default,,0,0,0,,嗯？\nDialogue: 0,1:15:21.46,1:15:22.87,Default,,0,0,0,,学生：我有一个问题\nDialogue: 0,1:15:22.87,1:15:25.68,Default,,0,0,0,,我明白一旦你的数据结构被设计好之后\nDialogue: 0,1:15:25.71,1:15:28.73,Default,,0,0,0,,它是怎么把complex标志拿掉 把它传递给下层\nDialogue: 0,1:15:28.73,1:15:30.64,Default,,0,0,0,,然后把rect类型拿掉 再传递给下层\nDialogue: 0,1:15:30.64,1:15:33.95,Default,,0,0,0,,但是如果你只是一个用户 并不知道什么rect或者polar类型\nDialogue: 0,1:15:34.25,1:15:36.04,Default,,0,0,0,,你怎么知道如何去设置这个数据结构\nDialogue: 0,1:15:36.09,1:15:38.08,Default,,0,0,0,,让所有东西正常运转呢\nDialogue: 0,1:15:38.09,1:15:41.00,Default,,0,0,0,,如果我只知道左边的这个算式\nDialogue: 0,1:15:41.02,1:15:42.50,Default,,0,0,0,,我只是想把复数加起来或者乘起来\nDialogue: 0,1:15:42.50,1:15:43.64,Default,,0,0,0,,教授：这就是它神奇的地方\nDialogue: 0,1:15:43.64,1:15:45.26,Default,,0,0,0,,如果你是一个用户 直接调用mul就可以了\nDialogue: 0,1:15:47.73,1:15:49.95,Default,,0,0,0,,学生：然后它就能明白我要计算的是复数？\nDialogue: 0,1:15:49.96,1:15:51.23,Default,,0,0,0,,或者我怎么告诉它我想——\nDialogue: 0,1:15:51.26,1:15:53.05,Default,,0,0,0,,教授：只要你给它的是复数它就能明白\nDialogue: 0,1:15:53.05,1:15:56.30,Default,,0,0,0,,作为这个系统的用户\nDialogue: 0,1:15:56.32,1:15:58.14,Default,,0,0,0,,你能使用的是复数的构造函数\nDialogue: 0,1:15:58.37,1:15:59.55,Default,,0,0,0,,学生：那么我需要自己构造复数了？\nDialogue: 0,1:15:59.56,1:16:00.35,Default,,0,0,0,,教授：那么你需要自己构造它们\nDialogue: 0,1:16:00.35,1:16:04.01,Default,,0,0,0,,作为用户 你可能只能够操作命令行\nDialogue: 0,1:16:04.65,1:16:07.56,Default,,0,0,0,,它会给你提供一些合理的方法\nDialogue: 0,1:16:07.56,1:16:08.86,Default,,0,0,0,,来输入复数\nDialogue: 0,1:16:09.31,1:16:11.00,Default,,0,0,0,,让你用你喜欢的格式输入\nDialogue: 0,1:16:11.59,1:16:14.36,Default,,0,0,0,,也可能你根本就不用输入它们\nDialogue: 0,1:16:14.36,1:16:16.17,Default,,0,0,0,,只是别人给你一个复数让你计算\nDialogue: 0,1:16:16.78,1:16:19.82,Default,,0,0,0,,学生：好 那么如果我有一个含有多项式的复数\nDialogue: 0,1:16:19.82,1:16:21.96,Default,,0,0,0,,我就要先构造这个多项式 然后再构造我的复数\nDialogue: 0,1:16:21.96,1:16:23.96,Default,,0,0,0,,教授：如果你是从零开始构造它的话 是这样的\nDialogue: 0,1:16:24.28,1:16:25.71,Default,,0,0,0,,可以说你是在从零开始构造\nDialogue: 0,1:16:25.71,1:16:27.05,Default,,0,0,0,,而你只要有了要计算的东西\nDialogue: 0,1:16:27.28,1:16:30.32,Default,,0,0,0,,可以直接调用mul运算 然后它们就会被乘起来\nDialogue: 0,1:16:32.78,1:16:32.99,Default,,0,0,0,,说吧\nDialogue: 0,1:16:33.27,1:16:35.76,Default,,0,0,0,,学生：我想提一个问题 就是……\nDialogue: 0,1:16:36.45,1:16:40.01,Default,,0,0,0,,比如说我想修改我的复数表示方法\nDialogue: 0,1:16:40.03,1:16:41.44,Default,,0,0,0,,或者复数的某些运算\nDialogue: 0,1:16:41.52,1:16:47.10,Default,,0,0,0,,为了修改一个特定的运算\nDialogue: 0,1:16:47.15,1:16:51.26,Default,,0,0,0,,我得考虑多少代码？\nDialogue: 0,1:16:52.27,1:16:53.49,Default,,0,0,0,,教授：得看你想要修改什么\nDialogue: 0,1:16:53.49,1:16:54.99,Default,,0,0,0,,重点在于你只需要改\nDialogue: 0,1:16:55.39,1:16:56.07,Default,,0,0,0,,你想改的那一部分\nDialogue: 0,1:16:56.07,1:17:00.04,Default,,0,0,0,,想象一下如果Martha决定她\nDialogue: 0,1:17:00.32,1:17:01.23,Default,,0,0,0,,举个不太好的例子\nDialogue: 0,1:17:01.44,1:17:02.91,Default,,0,0,0,,比如把序对中两个数的顺序调换\nDialogue: 0,1:17:04.04,1:17:08.72,Default,,0,0,0,,把模和辐角的顺序反过来\nDialogue: 0,1:17:09.39,1:17:10.80,Default,,0,0,0,,她只做了局部的修改\nDialogue: 0,1:17:10.97,1:17:13.29,Default,,0,0,0,,那么这个改动会准确无误地扩散到整个系统里\nDialogue: 0,1:17:14.79,1:17:18.76,Default,,0,0,0,,或者突然你说 我有另一种方法来表示有理数\nDialogue: 0,1:17:19.70,1:17:23.90,Default,,0,0,0,,我就得不断地在表格中添加运算\nDialogue: 0,1:17:24.82,1:17:27.22,Default,,0,0,0,,那么突然之间所有的多项式\nDialogue: 0,1:17:27.22,1:17:29.10,Default,,0,0,0,,它们的系数和系数的系数 或者什么东西\nDialogue: 0,1:17:29.24,1:17:32.40,Default,,0,0,0,,都自动支持用这种表示方法来表示了\nDialogue: 0,1:17:32.70,1:17:34.67,Default,,0,0,0,,这就是我们这种设计的威力\nDialogue: 0,1:17:36.11,1:17:38.70,Default,,0,0,0,,学生：我提的这个问题可能听起来比较蠢\nDialogue: 0,1:17:38.70,1:17:42.38,Default,,0,0,0,,整个这个系统看起来\nDialogue: 0,1:17:42.54,1:17:45.88,Default,,0,0,0,,非常完美 所有的东西都各就各位\nDialogue: 0,1:17:46.72,1:17:48.67,Default,,0,0,0,,完美得有点出乎意料\nDialogue: 0,1:17:50.93,1:17:52.52,Default,,0,0,0,,我相信 这都是为了教学方便\nDialogue: 0,1:17:52.56,1:17:54.65,Default,,0,0,0,,我怀疑的是首先发明了这种做法的人\nDialogue: 0,1:17:55.10,1:17:55.85,Default,,0,0,0,,我可能说得不对\nDialogue: 0,1:17:56.60,1:17:59.72,Default,,0,0,0,,难道一下子就搞清楚了所有这些东西一起\nDialogue: 0,1:17:59.77,1:18:03.93,Default,,0,0,0,,只要把这些放在一起 你就突然可以对各种对象做各种运算\nDialogue: 0,1:18:04.86,1:18:07.20,Default,,0,0,0,,我觉得他们应该研究了很长时间\nDialogue: 0,1:18:07.93,1:18:10.62,Default,,0,0,0,,不断地推倒重来\nDialogue: 0,1:18:11.80,1:18:14.12,Default,,0,0,0,,然后我觉得 当我们设计一个非常复杂的系统\nDialogue: 0,1:18:14.12,1:18:16.94,Default,,0,0,0,,我们也要面对这样的问题\nDialogue: 0,1:18:17.31,1:18:20.35,Default,,0,0,0,,就是有太多各种各样的部件 我们甚至不知道\nDialogue: 0,1:18:21.08,1:18:24.62,Default,,0,0,0,,我们甚至不知道要对这些部件做什么样的操作\nDialogue: 0,1:18:24.62,1:18:26.54,Default,,0,0,0,,在这种时候我怎么用这种良好的方法组织操作\nDialogue: 0,1:18:26.56,1:18:29.63,Default,,0,0,0,,才能获得这种 不管怎样只要把它们放在一起\nDialogue: 0,1:18:29.63,1:18:31.39,Default,,0,0,0,,所有事情就正常运转 这样的效果呢\nDialogue: 0,1:18:31.70,1:18:34.34,Default,,0,0,0,,教授：很好 这确实是一个非常聪明的问题\nDialogue: 0,1:18:35.10,1:18:39.52,Default,,0,0,0,,要说的一点是我们这种方法论\nDialogue: 0,1:18:39.87,1:18:43.88,Default,,0,0,0,,受到了符号代数的很多启发\nDialogue: 0,1:18:44.59,1:18:45.90,Default,,0,0,0,,符号代数相当繁复\nDialogue: 0,1:18:47.59,1:18:50.71,Default,,0,0,0,,允许你在决定各种运算是什么样子之前\nDialogue: 0,1:18:50.71,1:18:52.89,Default,,0,0,0,,来实现这个系统\nDialogue: 0,1:18:53.31,1:18:57.72,Default,,0,0,0,,所以从某种意义上讲 这是人们在这方面长期探索之后得出的答案\nDialogue: 0,1:18:58.56,1:19:00.75,Default,,0,0,0,,从另一个角度来说 这确实是精心设计的例子\nDialogue: 0,1:19:02.16,1:19:06.24,Default,,0,0,0,,学生：看上去想要设计出这样的系统\nDialogue: 0,1:19:06.24,1:19:09.01,Default,,0,0,0,,一开始先要研究一段时间然后才能变熟练\nDialogue: 0,1:19:09.01,1:19:11.88,Default,,0,0,0,,教授：我给你看看这个东西是多么的勉强\nDialogue: 0,1:19:12.22,1:19:14.13,Default,,0,0,0,,你现在可以写下所有的这些程序\nDialogue: 0,1:19:14.13,1:19:16.25,Default,,0,0,0,,但是我写在这里的这个系统\nDialogue: 0,1:19:17.02,1:19:18.96,Default,,0,0,0,,如果允许我拖堂半小时的话\nDialogue: 0,1:19:19.31,1:19:20.46,Default,,0,0,0,,我会给大家讲\nDialogue: 0,1:19:20.81,1:19:23.02,Default,,0,0,0,,如果我让它做一个错误操作\nDialogue: 0,1:19:23.20,1:19:29.31,Default,,0,0,0,,比如一个愚蠢的命令 用3加上7/2 它就会崩溃\nDialogue: 0,1:19:30.88,1:19:33.42,Default,,0,0,0,,因为程序首先会调用operate-2这个过程\nDialogue: 0,1:19:33.80,1:19:35.95,Default,,0,0,0,,然后operate-2会说 这个是数字类型\nDialogue: 0,1:19:36.18,1:19:37.37,Default,,0,0,0,,那个是有理数类型\nDialogue: 0,1:19:37.56,1:19:38.81,Default,,0,0,0,,我不知道怎么把它们加起来\nDialogue: 0,1:19:41.53,1:19:44.30,Default,,0,0,0,,那么你想让这个系统至少能够\nDialogue: 0,1:19:45.88,1:19:47.34,Default,,0,0,0,,比如说 在做这个操作之前\nDialogue: 0,1:19:48.59,1:19:50.24,Default,,0,0,0,,把3提升为3/1\nDialogue: 0,1:19:50.48,1:19:53.21,Default,,0,0,0,,把它变成一个有理数 然后交给有理数程序包来处理\nDialogue: 0,1:19:54.86,1:19:58.70,Default,,0,0,0,,课堂上我们来不及讲这个问题了\nDialogue: 0,1:19:58.73,1:20:00.88,Default,,0,0,0,,书里面讨论了这个问题\nDialogue: 0,1:20:00.88,1:20:01.95,Default,,0,0,0,,叫做“类型转换”\nDialogue: 0,1:20:03.39,1:20:05.15,Default,,0,0,0,,你想要的是\nDialogue: 0,1:20:05.31,1:20:08.89,Default,,0,0,0,,看 我们小心翼翼地把对象按类型分好类\nDialogue: 0,1:20:08.91,1:20:12.17,Default,,0,0,0,,但是有时你也想让它\nDialogue: 0,1:20:12.40,1:20:17.98,Default,,0,0,0,,知道怎么把一个普通的数字当成有理数\nDialogue: 0,1:20:19.11,1:20:21.29,Default,,0,0,0,,或者把普通的数字当成复数\nDialogue: 0,1:20:21.62,1:20:25.16,Default,,0,0,0,,到那个时候系统就开始变得复杂了\nDialogue: 0,1:20:25.76,1:20:28.12,Default,,0,0,0,,就是你去思考 我应该把这些知识放在哪里的时候\nDialogue: 0,1:20:28.42,1:20:32.19,Default,,0,0,0,,是应该让有理数知道它们是由普通的数字构成的吗？\nDialogue: 0,1:20:33.13,1:20:36.38,Default,,0,0,0,,或者我们举一个更加糟糕的例子\nDialogue: 0,1:20:38.14,1:20:47.48,Default,,0,0,0,,比如说我想要把一个复数加到有理数上去\nDialogue: 0,1:20:49.87,1:20:50.76,Default,,0,0,0,,这个不好\nDialogue: 0,1:20:50.76,1:20:51.58,Default,,0,0,0,,5/7\nDialogue: 0,1:20:53.86,1:20:55.72,Default,,0,0,0,,然后整个系统里必须有人知道\nDialogue: 0,1:20:56.06,1:20:58.16,Default,,0,0,0,,他需要把这个东西变成另一种类型\nDialogue: 0,1:20:58.20,1:21:00.65,Default,,0,0,0,,要把它变成一部分是有理数的复数\nDialogue: 0,1:21:01.54,1:21:02.68,Default,,0,0,0,,那么谁应该去操心这个事情呢\nDialogue: 0,1:21:02.68,1:21:03.95,Default,,0,0,0,,是complex程序包吗？\nDialogue: 0,1:21:03.95,1:21:05.03,Default,,0,0,0,,是rational程序包吗？\nDialogue: 0,1:21:05.24,1:21:06.22,Default,,0,0,0,,还是plus过程要考虑这个问题？\nDialogue: 0,1:21:06.90,1:21:08.52,Default,,0,0,0,,这就是体现复杂性的地方\nDialogue: 0,1:21:08.52,1:21:11.38,Default,,0,0,0,,也是这个问题的特别之处\nDialogue: 0,1:21:11.38,1:21:14.12,Default,,0,0,0,,同时很多的 实际上是所有的这样的“消息传递”的想法\nDialogue: 0,1:21:14.64,1:21:16.54,Default,,0,0,0,,都是被这样的问题启发的\nDialogue: 0,1:21:18.46,1:21:20.89,Default,,0,0,0,,当你真正深入进去\nDialogue: 0,1:21:20.91,1:21:24.76,Default,,0,0,0,,人们发现 代数操作的问题是如此复杂\nDialogue: 0,1:21:25.18,1:21:27.41,Default,,0,0,0,,而那些一直围绕它们工作的人们 确实就处在\nDialogue: 0,1:21:27.41,1:21:28.05,Default,,0,0,0,,你说的那种状态\nDialogue: 0,1:21:28.05,1:21:29.71,Default,,0,0,0,,他们在这些问题里艰难跋涉 时不时陷进泥里\nDialogue: 0,1:21:29.72,1:21:31.37,Default,,0,0,0,,寻找好用的工具 并试着提炼一种通用方法\nDialogue: 0,1:21:34.20,1:21:37.76,Default,,0,0,0,,学生：我想再一次回到这个复杂度的问题上来\nDialogue: 0,1:21:38.41,1:21:44.55,Default,,0,0,0,,在修改底层过程的时候 这个系统\nDialogue: 0,1:21:44.55,1:21:48.32,Default,,0,0,0,,毫无疑问 体现了非常大的灵活性\nDialogue: 0,1:21:49.71,1:21:53.40,Default,,0,0,0,,但是确实 在某种意义上讲\nDialogue: 0,1:21:53.44,1:21:55.26,Default,,0,0,0,,冻结了高层运算\nDialogue: 0,1:21:55.45,1:21:58.51,Default,,0,0,0,,或者至少如果你修改它们 你不知道\nDialogue: 0,1:21:58.51,1:22:02.06,Default,,0,0,0,,改动会体现在哪里 会怎么体现出来\nDialogue: 0,1:22:02.20,1:22:04.22,Default,,0,0,0,,教授：这个问题真是不能再好了\nDialogue: 0,1:22:04.68,1:22:05.87,Default,,0,0,0,,我要做的事情就是\nDialogue: 0,1:22:08.68,1:22:10.84,Default,,0,0,0,,如果我决定添加一个通用操作\nDialogue: 0,1:22:11.45,1:22:13.07,Default,,0,0,0,,比如equality-test\nDialogue: 0,1:22:14.96,1:22:17.15,Default,,0,0,0,,那么系统中的其它人就要查表格\nDialogue: 0,1:22:18.22,1:22:22.54,Default,,0,0,0,,来看他们需不需要支持equality-test\nDialogue: 0,1:22:24.65,1:22:26.84,Default,,0,0,0,,我们可以让它变得更加去中心化\nDialogue: 0,1:22:27.87,1:22:30.70,Default,,0,0,0,,这就是之前我提示了很多次的事情\nDialogue: 0,1:22:31.08,1:22:33.26,Default,,0,0,0,,你不但可以通过给对象添加符号标签来体现类型\nDialogue: 0,1:22:33.40,1:22:38.70,Default,,0,0,0,,而是把每一类对象接受的运算也保存在里面\nDialogue: 0,1:22:40.45,1:22:43.90,Default,,0,0,0,,那么你可以添加一个 比如说最大公约数过程\nDialogue: 0,1:22:44.43,1:22:46.81,Default,,0,0,0,,它只能计算整数\nDialogue: 0,1:22:47.40,1:22:49.21,Default,,0,0,0,,而不是对所有有理数都通用\nDialogue: 0,1:22:51.03,1:22:53.11,Default,,0,0,0,,所以这个系统可能是非常非常碎片化的\nDialogue: 0,1:22:53.11,1:22:55.66,Default,,0,0,0,,取决于你想让哪一部分比较灵活\nDialogue: 0,1:22:56.22,1:22:59.02,Default,,0,0,0,,有一系列的地方让你把这个东西放进去\nDialogue: 0,1:22:59.96,1:23:02.56,Default,,0,0,0,,但是你也指出了这种设计的弱点\nDialogue: 0,1:23:02.60,1:23:06.37,Default,,0,0,0,,就是必须在顶层 对于这些通用运算符有一些约定\nDialogue: 0,1:23:06.37,1:23:07.82,Default,,0,0,0,,或者至少人们要考虑这件事情\nDialogue: 0,1:23:08.39,1:23:10.72,Default,,0,0,0,,或者你可以决定 把这个表格设计得非常稀疏\nDialogue: 0,1:23:10.75,1:23:11.96,Default,,0,0,0,,里面只放很少的一点东西\nDialogue: 0,1:23:14.01,1:23:15.49,Default,,0,0,0,,这个游戏有很多种玩法\nDialogue: 0,1:23:19.78,1:23:20.43,Default,,0,0,0,,谢谢大家\nDialogue: 0,1:23:23.53,1:23:36.56,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:23:23.53,1:23:36.56,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec4b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:11.40,0:00:16.50,EN,,0,0,0,,Generic Operators\nDialogue: 0,0:00:20.18,0:00:21.84,EN,,0,0,0,,PROFESSOR: So far in this course we've been talking\nDialogue: 0,0:00:21.84,0:00:23.78,EN,,0,0,0,,a lot about data abstraction.\nDialogue: 0,0:00:23.78,0:00:27.15,EN,,0,0,0,,And remember the idea is that we build systems\nDialogue: 0,0:00:27.74,0:00:32.56,EN,,0,0,0,,that have these horizontal barriers in them, these abstraction barriers\nDialogue: 0,0:00:33.42,0:00:39.21,EN,,0,0,0,,that separate use, the way you might use some data object,\nDialogue: 0,0:00:39.93,0:00:41.18,EN,,0,0,0,,from the way you might represent it.\nDialogue: 0,0:00:49.40,0:00:52.03,EN,,0,0,0,,Or another way to think of that is up here you have the boss\nDialogue: 0,0:00:52.11,0:00:55.50,EN,,0,0,0,,who's going to be using some sort of data object.\nDialogue: 0,0:00:57.11,0:01:02.31,EN,,0,0,0,,And down here is George who's implemented it.\nDialogue: 0,0:01:02.31,0:01:05.42,EN,,0,0,0,,Now this notion of separating use from representation\nDialogue: 0,0:01:05.44,0:01:09.76,EN,,0,0,0,,so you can think about these two problems separately\nDialogue: 0,0:01:10.60,0:01:14.76,EN,,0,0,0,,is a very,very powerful programming methodology, data abstraction.\nDialogue: 0,0:01:15.93,0:01:18.81,EN,,0,0,0,,On the other hand, it's not really sufficient\nDialogue: 0,0:01:19.56,0:01:21.84,EN,,0,0,0,,for really complex systems.\nDialogue: 0,0:01:22.96,0:01:27.64,EN,,0,0,0,,And the problem with this is George.\nDialogue: 0,0:01:28.64,0:01:32.09,EN,,0,0,0,,Or actually, the problem is that\nDialogue: 0,0:01:32.09,0:01:32.78,EN,,0,0,0,,there are a lot of Georges.\nDialogue: 0,0:01:34.63,0:01:35.39,EN,,0,0,0,,Let's be concrete.\nDialogue: 0,0:01:35.39,0:01:39.18,EN,,0,0,0,,Let's suppose there is George,and there's also Martha.\nDialogue: 0,0:01:41.19,0:01:44.22,EN,,0,0,0,,OK, now George and Martha are both working on this system,\nDialogue: 0,0:01:46.04,0:01:47.29,EN,,0,0,0,,both designing representations,\nDialogue: 0,0:01:48.41,0:01:50.67,EN,,0,0,0,,and absolutely are incompatible.\nDialogue: 0,0:01:51.75,0:01:53.62,EN,,0,0,0,,They wouldn't cooperate on a representation\nDialogue: 0,0:01:54.01,0:01:55.34,EN,,0,0,0,,under any circumstances.\nDialogue: 0,0:01:57.48,0:01:59.72,EN,,0,0,0,,And the problem is you would like to have some system\nDialogue: 0,0:02:00.06,0:02:02.60,EN,,0,0,0,,where both George and Martha are designing representations,\nDialogue: 0,0:02:03.82,0:02:08.08,EN,,0,0,0,,and, yet, if you're above this abstraction barrier\nDialogue: 0,0:02:09.40,0:02:11.04,EN,,0,0,0,,you don't want to have to worry about that,\nDialogue: 0,0:02:11.66,0:02:14.18,EN,,0,0,0,,whether something is done by George or by Martha.\nDialogue: 0,0:02:14.18,0:02:15.43,EN,,0,0,0,,And you don't want George and Martha to\nDialogue: 0,0:02:15.43,0:02:16.48,EN,,0,0,0,,interfere with each other.\nDialogue: 0,0:02:16.63,0:02:20.31,EN,,0,0,0,,Somehow in designing a system, you not only want these\nDialogue: 0,0:02:20.31,0:02:23.84,EN,,0,0,0,,horizontal barriers, but you also want some kind of\nDialogue: 0,0:02:25.82,0:02:30.64,EN,,0,0,0,,some kind of vertical barrier to keep George and Martha separate.\nDialogue: 0,0:02:32.98,0:02:35.40,EN,,0,0,0,,Let me be a little bit more concrete.\nDialogue: 0,0:02:36.56,0:02:40.54,EN,,0,0,0,,Imagine that you're thinking about personnel records\nDialogue: 0,0:02:41.18,0:02:46.11,EN,,0,0,0,,for a large company with a lot of loosely linked divisions\nDialogue: 0,0:02:47.90,0:02:49.71,EN,,0,0,0,,that don't cooperate very well either.\nDialogue: 0,0:02:50.43,0:02:57.04,EN,,0,0,0,,And imagine even that this company is formed by merging a\nDialogue: 0,0:02:57.04,0:02:59.45,EN,,0,0,0,,whole bunch of companies that already have their personnel\nDialogue: 0,0:02:59.45,0:03:00.70,EN,,0,0,0,,record system set up.\nDialogue: 0,0:03:03.25,0:03:06.57,EN,,0,0,0,,And imagine that once these divisions are all linked in\nDialogue: 0,0:03:06.57,0:03:08.53,EN,,0,0,0,,some kind of very sophisticated satellite\nDialogue: 0,0:03:08.53,0:03:10.52,EN,,0,0,0,,network, and all these databases are put together.\nDialogue: 0,0:03:12.24,0:03:13.85,EN,,0,0,0,,And what you'd like to do\nDialogue: 0,0:03:14.84,0:03:16.33,EN,,0,0,0,,is from any place in the company,\nDialogue: 0,0:03:17.26,0:03:23.13,EN,,0,0,0,,to be able to say things like,oh, what's the name in a\nDialogue: 0,0:03:23.13,0:03:23.87,EN,,0,0,0,,personnel record?\nDialogue: 0,0:03:26.30,0:03:29.15,EN,,0,0,0,,Or, what's the job description in a personnel record?\nDialogue: 0,0:03:30.54,0:03:34.40,EN,,0,0,0,,And not have to worry about the fact that each division\nDialogue: 0,0:03:34.84,0:03:36.76,EN,,0,0,0,,obviously is going to have completely separate\nDialogue: 0,0:03:36.76,0:03:39.37,EN,,0,0,0,,conventions for how you might implement these records.\nDialogue: 0,0:03:41.58,0:03:43.26,EN,,0,0,0,,From this point you don't want to know about that.\nDialogue: 0,0:03:44.96,0:03:47.92,EN,,0,0,0,,Well how could you possibly do that?\nDialogue: 0,0:03:48.43,0:03:52.41,EN,,0,0,0,,One way, of course, is to send down an edict from somewhere\nDialogue: 0,0:03:52.64,0:03:56.29,EN,,0,0,0,,that everybody has to change their format to some fixed\nDialogue: 0,0:03:56.29,0:03:57.24,EN,,0,0,0,,compatible thing.\nDialogue: 0,0:03:58.07,0:04:00.12,EN,,0,0,0,,That's what people often try, and of course it never works.\nDialogue: 0,0:04:01.82,0:04:07.34,EN,,0,0,0,,Another thing that you might want to do is somehow arrange\nDialogue: 0,0:04:08.33,0:04:09.90,EN,,0,0,0,,it so you can have these vertical barriers.\nDialogue: 0,0:04:11.25,0:04:14.40,EN,,0,0,0,,So that when you ask for the name of a personnel record,\nDialogue: 0,0:04:14.43,0:04:17.97,EN,,0,0,0,,somehow, whatever format it happens to be, name will\nDialogue: 0,0:04:17.97,0:04:19.42,EN,,0,0,0,,figure out how to do the right thing.\nDialogue: 0,0:04:22.73,0:04:25.53,EN,,0,0,0,,We want name to be, so-called, a generic operator.\nDialogue: 0,0:04:26.26,0:04:30.06,EN,,0,0,0,,Generic operator means what it sort of precisely does depends\nDialogue: 0,0:04:30.06,0:04:31.69,EN,,0,0,0,,on the kind of data that it's looking at.\nDialogue: 0,0:04:33.65,0:04:36.62,EN,,0,0,0,,More than that, you'd like to design the system so that the\nDialogue: 0,0:04:36.92,0:04:39.79,EN,,0,0,0,,next time a new division comes into the company\nDialogue: 0,0:04:42.51,0:04:45.64,EN,,0,0,0,,they don't have to make any big changes in what they're already doing\nDialogue: 0,0:04:45.64,0:04:50.11,EN,,0,0,0,,to link into this system, and the rest of the company\nDialogue: 0,0:04:50.11,0:04:52.01,EN,,0,0,0,,doesn't have to make any big changes\nDialogue: 0,0:04:52.27,0:04:53.93,EN,,0,0,0,,to admit their stuff to the system.\nDialogue: 0,0:04:55.52,0:04:57.52,EN,,0,0,0,,So that's the problem you should be thinking about.\nDialogue: 0,0:04:58.70,0:05:00.77,EN,,0,0,0,,Like it's sort of just your work.\nDialogue: 0,0:05:00.77,0:05:03.77,EN,,0,0,0,,You want to be able to include new things by making minimal changes.\nDialogue: 0,0:05:05.98,0:05:08.12,EN,,0,0,0,,OK, well that's the problem that we'll be talking about today.\nDialogue: 0,0:05:09.44,0:05:14.22,EN,,0,0,0,,And you should have this sort of distributed personnel record system in your mind.\nDialogue: 0,0:05:14.24,0:05:16.62,EN,,0,0,0,,But actually the one I'll be talking about is a problem\nDialogue: 0,0:05:16.62,0:05:18.48,EN,,0,0,0,,that's a little bit more self-contained than that.\nDialogue: 0,0:05:19.29,0:05:21.76,EN,,0,0,0,,that'll bring up the issues, I think, more clearly.\nDialogue: 0,0:05:21.87,0:05:26.01,EN,,0,0,0,,That's the problem of doing a system that does arithmetic on complex numbers.\nDialogue: 0,0:05:27.77,0:05:28.92,EN,,0,0,0,,So let's take a look here.\nDialogue: 0,0:05:30.69,0:05:31.74,EN,,0,0,0,,Just as a little review,\nDialogue: 0,0:05:32.04,0:05:33.53,EN,,0,0,0,,there are things called complex numbers.\nDialogue: 0,0:05:35.25,0:05:38.22,EN,,0,0,0,,Complex number you can think of as a point in the plane, or z.\nDialogue: 0,0:05:39.37,0:05:47.19,EN,,0,0,0,,And you can represent a point either by its real-part and its imaginary-part.\nDialogue: 0,0:05:47.19,0:05:50.83,EN,,0,0,0,,So if this is z and its real-part is this much,\nDialogue: 0,0:05:51.50,0:05:53.24,EN,,0,0,0,,and its imaginary-part is that much,\nDialogue: 0,0:05:54.33,0:05:56.44,EN,,0,0,0,,and you write z equals x plus iy.\nDialogue: 0,0:05:59.11,0:06:03.21,EN,,0,0,0,,Or another way to represent a complex number is by saying,\nDialogue: 0,0:06:03.21,0:06:09.00,EN,,0,0,0,,what's the distance from the origin, and what's the angle?\nDialogue: 0,0:06:11.32,0:06:16.67,EN,,0,0,0,,So that represents a complex number as its radius times an angle.\nDialogue: 0,0:06:19.52,0:06:21.92,EN,,0,0,0,,This one's called -- the original one's called rectangular form,\nDialogue: 0,0:06:22.59,0:06:25.45,EN,,0,0,0,,rectangular representation, real- and imaginary-part\nDialogue: 0,0:06:26.20,0:06:30.04,EN,,0,0,0,,or polar representation magnitude and angle--\nDialogue: 0,0:06:30.04,0:06:31.48,EN,,0,0,0,,and if you know the real- and imaginary-part,\nDialogue: 0,0:06:31.53,0:06:33.36,EN,,0,0,0,,you can figure out the magnitude and angle.\nDialogue: 0,0:06:33.72,0:06:36.97,EN,,0,0,0,,If you know x and y, you can get r by this formula.\nDialogue: 0,0:06:37.19,0:06:39.48,EN,,0,0,0,,Square root of sum of the squares, and you can get the\nDialogue: 0,0:06:39.48,0:06:40.76,EN,,0,0,0,,angle as an arctangent.\nDialogue: 0,0:06:41.42,0:06:44.42,EN,,0,0,0,,Or conversely, if you knew r and A you could\nDialogue: 0,0:06:44.42,0:06:45.31,EN,,0,0,0,,figure out x and y.\nDialogue: 0,0:06:45.80,0:06:49.43,EN,,0,0,0,,x is r times the cosine of A, and y is r times the sine of A.\nDialogue: 0,0:06:51.34,0:06:53.66,EN,,0,0,0,,All right, so there's these two. They're complex numbers.\nDialogue: 0,0:06:54.13,0:06:57.15,EN,,0,0,0,,You can think of them either in polar form or rectangular form.\nDialogue: 0,0:06:57.15,0:06:58.12,EN,,0,0,0,,What we would like to do\nDialogue: 0,0:06:58.32,0:07:01.32,EN,,0,0,0,,is make a system that does arithmetic on complex numbers.\nDialogue: 0,0:07:03.95,0:07:05.12,EN,,0,0,0,,In other words, what we'd like--\nDialogue: 0,0:07:05.58,0:07:06.99,EN,,0,0,0,,just like the rational number example--\nDialogue: 0,0:07:07.38,0:07:10.20,EN,,0,0,0,,is to have some operations plus c,\nDialogue: 0,0:07:10.73,0:07:13.90,EN,,0,0,0,,which is going to take two complex numbers and add them, subtract them,\nDialogue: 0,0:07:14.35,0:07:16.94,EN,,0,0,0,,and multiply them, and divide them.\nDialogue: 0,0:07:20.73,0:07:25.28,EN,,0,0,0,,OK, well there's little bit of mathematics behind it.\nDialogue: 0,0:07:25.28,0:07:28.36,EN,,0,0,0,,What are the actual formulas for manipulating such things?\nDialogue: 0,0:07:30.41,0:07:31.92,EN,,0,0,0,,And it's sort of not important where they come from,\nDialogue: 0,0:07:34.00,0:07:35.79,EN,,0,0,0,,but just as an implementer let's see--\nDialogue: 0,0:07:35.80,0:07:37.95,EN,,0,0,0,,if you want to add two complex numbers it's pretty easy to\nDialogue: 0,0:07:39.13,0:07:42.66,EN,,0,0,0,,it's pretty easy to get its real-part and its imaginary-part.\nDialogue: 0,0:07:42.66,0:07:45.93,EN,,0,0,0,,The real-part of the sum of two complex numbers\nDialogue: 0,0:07:47.72,0:07:49.72,EN,,0,0,0,,real-part of the z1 plus z2\nDialogue: 0,0:07:50.06,0:07:54.64,EN,,0,0,0,,is the real-part of z1 plus the real-part of z2.\nDialogue: 0,0:07:57.82,0:08:01.60,EN,,0,0,0,,And the imaginary-part of z1 plus z2\nDialogue: 0,0:08:01.74,0:08:05.66,EN,,0,0,0,,is the imaginary part of z1 plus the imaginary part of z2.\nDialogue: 0,0:08:07.41,0:08:09.48,EN,,0,0,0,,So it's pretty easy to add complex numbers.\nDialogue: 0,0:08:09.48,0:08:10.99,EN,,0,0,0,,You just add the corresponding parts\nDialogue: 0,0:08:11.31,0:08:13.18,EN,,0,0,0,,and make a new complex number with those parts.\nDialogue: 0,0:08:13.37,0:08:14.73,EN,,0,0,0,,If you want to multiply them,\nDialogue: 0,0:08:15.53,0:08:17.82,EN,,0,0,0,,it's kind of nice to do it in polar form.\nDialogue: 0,0:08:17.82,0:08:20.38,EN,,0,0,0,,Because if you have two complex numbers,\nDialogue: 0,0:08:20.40,0:08:26.54,EN,,0,0,0,,the magnitude of their product is here, the product of the magnitudes.\nDialogue: 0,0:08:28.85,0:08:33.88,EN,,0,0,0,,And the angle of the product is the sum of the angles.\nDialogue: 0,0:08:35.80,0:08:40.54,EN,,0,0,0,,So that's sort of mathematics that allows you to do arithmetic on complex numbers.\nDialogue: 0,0:08:40.54,0:08:42.38,EN,,0,0,0,,Let's actually think about the implementation.\nDialogue: 0,0:08:43.72,0:08:47.39,EN,,0,0,0,,Well we do it just like rational numbers.\nDialogue: 0,0:08:49.84,0:08:53.47,EN,,0,0,0,,We come down, we assume we have some constructors and selectors.\nDialogue: 0,0:08:53.76,0:08:54.52,EN,,0,0,0,,What would we like?\nDialogue: 0,0:08:55.33,0:08:58.16,EN,,0,0,0,,Well let's assume that we make a data object cloud,\nDialogue: 0,0:08:58.54,0:09:00.78,EN,,0,0,0,,which is a complex number that has some stuff in it,\nDialogue: 0,0:09:01.79,0:09:04.67,EN,,0,0,0,,and that we can get out from a complex number the real-part,\nDialogue: 0,0:09:05.52,0:09:09.64,EN,,0,0,0,,or the imaginary-part, or the magnitude, or the angle.\nDialogue: 0,0:09:12.15,0:09:14.01,EN,,0,0,0,,We want some ways of making complex numbers--\nDialogue: 0,0:09:14.03,0:09:15.64,EN,,0,0,0,,not only selectors, but constructors.\nDialogue: 0,0:09:16.80,0:09:19.52,EN,,0,0,0,,So we'll assume we have a thing called make-rectangular.\nDialogue: 0,0:09:19.53,0:09:24.27,EN,,0,0,0,,What make-rectangular is going to do is take a real-part and\nDialogue: 0,0:09:24.51,0:09:29.36,EN,,0,0,0,,an imaginary-part and construct a complex number with those parts.\nDialogue: 0,0:09:31.92,0:09:35.01,EN,,0,0,0,,Similarly, we can have make-polar which will taking\nDialogue: 0,0:09:35.01,0:09:37.85,EN,,0,0,0,,a magnitude and an angle,\nDialogue: 0,0:09:40.83,0:09:43.90,EN,,0,0,0,,and construct a complex number which has that magnitude and angle.\nDialogue: 0,0:09:44.68,0:09:45.46,EN,,0,0,0,,So here's a system.\nDialogue: 0,0:09:45.46,0:09:47.77,EN,,0,0,0,,We'll have two constructors and four selectors.\nDialogue: 0,0:09:48.91,0:09:55.15,EN,,0,0,0,,And now, just like before, in terms of that abstract data\nDialogue: 0,0:09:55.15,0:09:59.22,EN,,0,0,0,,we'll go ahead and implement our complex number operations.\nDialogue: 0,0:09:59.22,0:10:02.30,EN,,0,0,0,,And here you can see translated into Lisp code\nDialogue: 0,0:10:03.23,0:10:07.47,EN,,0,0,0,,just the arithmetic formulas I put down before.\nDialogue: 0,0:10:08.06,0:10:09.98,EN,,0,0,0,,If I want to add two complex numbers\nDialogue: 0,0:10:11.76,0:10:15.56,EN,,0,0,0,,I will make a complex number out of its real- and imaginary-parts.\nDialogue: 0,0:10:16.72,0:10:19.02,EN,,0,0,0,,The real part of the complex number I'm going to make\nDialogue: 0,0:10:19.40,0:10:21.80,EN,,0,0,0,,is the sum of the real-parts.\nDialogue: 0,0:10:23.31,0:10:25.37,EN,,0,0,0,,The imaginary part of the complex number I'm going to make\nDialogue: 0,0:10:25.40,0:10:27.52,EN,,0,0,0,,is the sum of the imaginary-parts.\nDialogue: 0,0:10:30.31,0:10:32.09,EN,,0,0,0,,I put those together, make a complex number.\nDialogue: 0,0:10:32.16,0:10:34.44,EN,,0,0,0,,That's how I implement complex number addition.\nDialogue: 0,0:10:35.78,0:10:38.49,EN,,0,0,0,,Subtraction is essentially the same.\nDialogue: 0,0:10:39.65,0:10:42.97,EN,,0,0,0,,All I do is subtract the parts rather than add them.\nDialogue: 0,0:10:45.14,0:10:47.07,EN,,0,0,0,,To multiply two complex numbers,\nDialogue: 0,0:10:47.74,0:10:49.02,EN,,0,0,0,,I use the other formula.\nDialogue: 0,0:10:49.27,0:10:53.84,EN,,0,0,0,,I'll make a complex number out of a magnitude and angle.\nDialogue: 0,0:10:55.35,0:10:56.44,EN,,0,0,0,,The magnitude\nDialogue: 0,0:10:56.65,0:11:00.97,EN,,0,0,0,,is going to be the product of the magnitudesof the two complex numbers I'm multiplying.\nDialogue: 0,0:11:03.71,0:11:05.93,EN,,0,0,0,,And the angle is going to be the sum\nDialogue: 0,0:11:06.16,0:11:08.51,EN,,0,0,0,,of the angles of the z1two complex numbers I'm multiplying.\nDialogue: 0,0:11:09.62,0:11:10.96,EN,,0,0,0,,So there's multiplication.\nDialogue: 0,0:11:11.23,0:11:12.25,EN,,0,0,0,,And then division,\nDialogue: 0,0:11:14.27,0:11:15.90,EN,,0,0,0,,division is almost the same.\nDialogue: 0,0:11:17.37,0:11:19.58,EN,,0,0,0,,Here I divide the magnitudes and subtract the angles.\nDialogue: 0,0:11:28.36,0:11:30.46,EN,,0,0,0,,Now I've implemented the operations.\nDialogue: 0,0:11:31.87,0:11:33.64,EN,,0,0,0,,And what do we do?\nDialogue: 0,0:11:33.64,0:11:34.52,EN,,0,0,0,,We call on George.\nDialogue: 0,0:11:36.06,0:11:38.79,EN,,0,0,0,,We've done the use, let's worry about the representation.\nDialogue: 0,0:11:38.80,0:11:40.94,EN,,0,0,0,,We'll call on George and say to George,\nDialogue: 0,0:11:40.97,0:11:43.61,EN,,0,0,0,,go ahead and build us a complex number representation.\nDialogue: 0,0:11:45.25,0:11:47.44,EN,,0,0,0,,Well that's fine...ahhh\nDialogue: 0,0:11:47.77,0:11:52.66,EN,,0,0,0,,George can say, we'll implement a complex number\nDialogue: 0,0:11:52.66,0:11:57.15,EN,,0,0,0,,simply as a pair that has the real-part and the imaginary-part.\nDialogue: 0,0:11:57.20,0:12:02.62,EN,,0,0,0,,So if I want to make a complex number with a certain real-part and an imaginary-part,\nDialogue: 0,0:12:03.36,0:12:05.55,EN,,0,0,0,,I'll just use cons to form a pair, and that will--\nDialogue: 0,0:12:06.03,0:12:08.11,EN,,0,0,0,,that's George's representation of a complex number.\nDialogue: 0,0:12:09.78,0:12:12.42,EN,,0,0,0,,So if I want to get out the real-part of something, I just\nDialogue: 0,0:12:12.42,0:12:14.12,EN,,0,0,0,,extract the car, the first part.\nDialogue: 0,0:12:14.35,0:12:16.67,EN,,0,0,0,,If I want to get the imaginary-part, I extract the cdr\nDialogue: 0,0:12:19.64,0:12:21.77,EN,,0,0,0,,How do I deal with the magnitude and angle?\nDialogue: 0,0:12:22.22,0:12:25.75,EN,,0,0,0,,Well if I want to extract the magnitude of one of these things\nDialogue: 0,0:12:25.75,0:12:32.30,EN,,0,0,0,,I get the square root of the sum of the square of the car plus the square of the cdr.\nDialogue: 0,0:12:33.79,0:12:39.26,EN,,0,0,0,,If I want to get the angle, I compute the arctangent of the cdr in the car.\nDialogue: 0,0:12:39.53,0:12:42.86,EN,,0,0,0,,This is a lisp procedure for computing arctangent.\nDialogue: 0,0:12:44.97,0:12:48.59,EN,,0,0,0,,And if somebody hands me a magnitude and an angle\nDialogue: 0,0:12:48.94,0:12:50.56,EN,,0,0,0,,and says, make me a complex number,well I compute the\nDialogue: 0,0:12:50.89,0:12:56.24,EN,,0,0,0,,well I compute the real-part and the imaginary-part, r * cosine of a and r * sine of a,\nDialogue: 0,0:12:57.77,0:12:59.05,EN,,0,0,0,,and stick them together into a pair.\nDialogue: 0,0:13:01.46,0:13:02.26,EN,,0,0,0,,OK so we're done.\nDialogue: 0,0:13:02.26,0:13:04.75,EN,,0,0,0,,In fact, what I just did, conceptually,\nDialogue: 0,0:13:06.89,0:13:09.37,EN,,0,0,0,,is absolutely no different from the rational number\nDialogue: 0,0:13:10.60,0:13:12.44,EN,,0,0,0,,representation that we looked at last time.\nDialogue: 0,0:13:12.75,0:13:13.91,EN,,0,0,0,,It's the same sort of idea.\nDialogue: 0,0:13:13.91,0:13:16.28,EN,,0,0,0,,You implement the operators, you pick a representation.\nDialogue: 0,0:13:18.07,0:13:18.65,EN,,0,0,0,,Nothing different.\nDialogue: 0,0:13:20.07,0:13:21.56,EN,,0,0,0,,Now let's worry about Martha.\nDialogue: 0,0:13:23.21,0:13:24.52,EN,,0,0,0,,See, Martha has a different idea.\nDialogue: 0,0:13:26.67,0:13:28.57,EN,,0,0,0,,She doesn't want to represent a complex number\nDialogue: 0,0:13:28.59,0:13:30.90,EN,,0,0,0,,as a pair of a real-part and an imaginary-part.\nDialogue: 0,0:13:30.90,0:13:34.17,EN,,0,0,0,,What she would like to do is represent a complex number as\nDialogue: 0,0:13:34.17,0:13:37.69,EN,,0,0,0,,a pair of a magnitude and an angle.\nDialogue: 0,0:13:39.55,0:13:42.13,EN,,0,0,0,,So if instead of calling up George we ask Martha to design\nDialogue: 0,0:13:42.13,0:13:43.74,EN,,0,0,0,,our representation, we get something like this.\nDialogue: 0,0:13:44.57,0:13:47.16,EN,,0,0,0,,We get make-polar.\nDialogue: 0,0:13:47.16,0:13:50.22,EN,,0,0,0,,Sure, if I give you a magnitude and an angle we're\nDialogue: 0,0:13:50.22,0:13:53.07,EN,,0,0,0,,just going to form a pair that has magnitude and angle.\nDialogue: 0,0:13:55.43,0:13:57.68,EN,,0,0,0,,If you want to extract the magnitude, that's easy.\nDialogue: 0,0:13:58.24,0:13:59.37,EN,,0,0,0,,You just pull out the car or the pair.\nDialogue: 0,0:13:59.78,0:14:02.67,EN,,0,0,0,,If you want to extract the angle, sure, that's easy.\nDialogue: 0,0:14:02.67,0:14:03.63,EN,,0,0,0,,You just pull out the cdr.\nDialogue: 0,0:14:04.81,0:14:07.02,EN,,0,0,0,,If you want to look for real-parts and imaginary-parts,\nDialogue: 0,0:14:07.42,0:14:08.49,EN,,0,0,0,,well then you have to do some work.\nDialogue: 0,0:14:08.88,0:14:14.58,EN,,0,0,0,,If you want the real-part, you have to get r cosine a.\nDialogue: 0,0:14:14.58,0:14:19.99,EN,,0,0,0,,In other words, r, the car of the pair, times the cosine of\nDialogue: 0,0:14:19.99,0:14:20.95,EN,,0,0,0,,the cdr of the pair.\nDialogue: 0,0:14:20.95,0:14:26.23,EN,,0,0,0,,So this is r times the cosine of a,\nDialogue: 0,0:14:26.54,0:14:27.48,EN,,0,0,0,,and that's the real-part.\nDialogue: 0,0:14:28.33,0:14:31.40,EN,,0,0,0,,If you want to get the imaginary-part, it's r times the sine of a.\nDialogue: 0,0:14:32.66,0:14:37.93,EN,,0,0,0,,And if I hand you a real-part and an imaginary-part and say,\nDialogue: 0,0:14:37.93,0:14:42.03,EN,,0,0,0,,make me a complex number with that real-part and\nDialogue: 0,0:14:42.03,0:14:44.17,EN,,0,0,0,,imaginary-part, well I figure out what the magnitude and\nDialogue: 0,0:14:44.17,0:14:45.54,EN,,0,0,0,,angle should be.\nDialogue: 0,0:14:45.54,0:14:47.85,EN,,0,0,0,,The magnitude's the square root of the sum of the squares\nDialogue: 0,0:14:48.09,0:14:49.23,EN,,0,0,0,,and the angle's the arctangent.\nDialogue: 0,0:14:49.23,0:14:50.22,EN,,0,0,0,,I put those together to make a pair.\nDialogue: 0,0:14:52.09,0:14:54.17,EN,,0,0,0,,So there's Martha's idea.\nDialogue: 0,0:14:56.69,0:14:57.37,EN,,0,0,0,,Well which is better?\nDialogue: 0,0:14:59.68,0:15:03.15,EN,,0,0,0,,Well if you're doing a lot of additions, probably George's is better\nDialogue: 0,0:15:03.16,0:15:05.61,EN,,0,0,0,,is better, because you're doing a lot of real-parts and imaginary-parts.\nDialogue: 0,0:15:05.85,0:15:08.40,EN,,0,0,0,,If mostly you're going to be doing multiplications and divisions,\nDialogue: 0,0:15:09.48,0:15:11.14,EN,,0,0,0,,then maybe Martha's idea is better.\nDialogue: 0,0:15:11.14,0:15:14.84,EN,,0,0,0,,Or maybe, and this is the real point, you can't decide.\nDialogue: 0,0:15:16.59,0:15:22.32,EN,,0,0,0,,Or maybe you just have to let them both hang around, for personality reasons.\nDialogue: 0,0:15:23.48,0:15:26.76,EN,,0,0,0,,Maybe you just really can't ever decide what you would like.\nDialogue: 0,0:15:28.56,0:15:32.32,EN,,0,0,0,,And again, what we would really like is a system that looks like this.\nDialogue: 0,0:15:32.65,0:15:36.17,EN,,0,0,0,,That somehow there's George over here, who has built\nDialogue: 0,0:15:36.83,0:15:39.64,EN,,0,0,0,,rectangular complex numbers.\nDialogue: 0,0:15:41.47,0:15:44.25,EN,,0,0,0,,And Martha, who has polar complex numbers.\nDialogue: 0,0:15:46.12,0:15:49.69,EN,,0,0,0,,And somehow we have operations\nDialogue: 0,0:15:50.28,0:15:56.89,EN,,0,0,0,,that can add, and subtract, and multiply, and divide\nDialogue: 0,0:15:57.56,0:15:58.76,EN,,0,0,0,,and it shouldn't matter\nDialogue: 0,0:15:59.34,0:16:02.79,EN,,0,0,0,,that there are two incompatible representations of complex\nDialogue: 0,0:16:02.79,0:16:03.98,EN,,0,0,0,,numbers floating around this system.\nDialogue: 0,0:16:04.41,0:16:08.33,EN,,0,0,0,,In other words, not only like an abstraction barrier here\nDialogue: 0,0:16:09.64,0:16:11.84,EN,,0,0,0,,that has things in it like a real-part,\nDialogue: 0,0:16:15.77,0:16:21.71,EN,,0,0,0,,and an imaginary-part, and magnitude,and angle.\nDialogue: 0,0:16:23.83,0:16:25.36,EN,,0,0,0,,So not only is there an abstraction barrier\nDialogue: 0,0:16:25.39,0:16:28.38,EN,,0,0,0,,that hides the actual representation from us,\nDialogue: 0,0:16:29.10,0:16:31.52,EN,,0,0,0,,but also there's some kind of vertical barrier here\nDialogue: 0,0:16:32.19,0:16:35.02,EN,,0,0,0,,that allows both of these representations to exist\nDialogue: 0,0:16:35.87,0:16:37.40,EN,,0,0,0,,without interfering with each other.\nDialogue: 0,0:16:38.57,0:16:41.07,EN,,0,0,0,,The idea is that the things in here--\nDialogue: 0,0:16:41.90,0:16:44.12,EN,,0,0,0,,real-part, imaginary-part,magnitude, and angle--\nDialogue: 0,0:16:44.12,0:16:46.49,EN,,0,0,0,,will be generic operators.\nDialogue: 0,0:16:47.31,0:16:49.45,EN,,0,0,0,,If you ask for the real-part, it will worry about\nDialogue: 0,0:16:49.98,0:16:51.31,EN,,0,0,0,,what representation it's looking at.\nDialogue: 0,0:16:53.88,0:16:55.10,EN,,0,0,0,,OK, well how can we do that?\nDialogue: 0,0:16:56.84,0:16:59.23,EN,,0,0,0,,There's actually a really obvious idea,\nDialogue: 0,0:16:59.84,0:17:01.68,EN,,0,0,0,,if you're used to thinking about complex numbers.\nDialogue: 0,0:17:02.52,0:17:04.44,EN,,0,0,0,,If you're used to thinking about compound data.\nDialogue: 0,0:17:06.33,0:17:10.99,EN,,0,0,0,,See, suppose you could just tell by looking at a complex number\nDialogue: 0,0:17:12.17,0:17:13.95,EN,,0,0,0,,whether it was constructed by George or Martha.\nDialogue: 0,0:17:15.79,0:17:18.90,EN,,0,0,0,,In other words, so it's not that what's floating around\nDialogue: 0,0:17:18.90,0:17:20.91,EN,,0,0,0,,here are ordinary, just complex numbers, right?\nDialogue: 0,0:17:20.91,0:17:22.94,EN,,0,0,0,,They're fancy, designer complex numbers.\nDialogue: 0,0:17:24.39,0:17:28.04,EN,,0,0,0,,So you look at a complex numbers as it's not just a complex number\nDialogue: 0,0:17:28.04,0:17:29.16,EN,,0,0,0,,it's got a label on it that says,\nDialogue: 0,0:17:29.19,0:17:30.75,EN,,0,0,0,,that one is by Martha.\nDialogue: 0,0:17:31.45,0:17:34.22,EN,,0,0,0,,Or this is a complex number by George.\nDialogue: 0,0:17:34.48,0:17:35.39,EN,,0,0,0,,Right? They're signed.\nDialogue: 0,0:17:36.86,0:17:40.15,EN,,0,0,0,,See, and then whenever we looked at a complex number we\nDialogue: 0,0:17:40.15,0:17:45.48,EN,,0,0,0,,could just read the label, and then we'd know how you expect\nDialogue: 0,0:17:45.80,0:17:46.72,EN,,0,0,0,,to operate on that.\nDialogue: 0,0:17:48.03,0:17:51.19,EN,,0,0,0,,In other words, what we want is not just ordinary data objects.\nDialogue: 0,0:17:51.19,0:17:54.37,EN,,0,0,0,,We want to introduce the notion of what's called typed data.\nDialogue: 0,0:17:59.76,0:18:02.81,EN,,0,0,0,,Typed data means, again, there's some sort of cloud.\nDialogue: 0,0:18:03.94,0:18:08.93,EN,,0,0,0,,And what it's got in it is an ordinary data object like\nDialogue: 0,0:18:08.93,0:18:09.90,EN,,0,0,0,,we've been thinking about.\nDialogue: 0,0:18:13.18,0:18:16.54,EN,,0,0,0,,Pulled out the contents, sort of the actual data.\nDialogue: 0,0:18:19.32,0:18:21.56,EN,,0,0,0,,But also a thing called a type,\nDialogue: 0,0:18:22.56,0:18:25.24,EN,,0,0,0,,but it's signed by either George or Martha.\nDialogue: 0,0:18:25.99,0:18:28.27,EN,,0,0,0,,So we're going to go from regular data to type data.\nDialogue: 0,0:18:31.95,0:18:32.71,EN,,0,0,0,,How do we build that?\nDialogue: 0,0:18:32.71,0:18:33.50,EN,,0,0,0,,Well that's easy.\nDialogue: 0,0:18:33.84,0:18:35.32,EN,,0,0,0,,We know how to build clouds.\nDialogue: 0,0:18:35.80,0:18:36.88,EN,,0,0,0,,We can build them out of pairs.\nDialogue: 0,0:18:37.92,0:18:41.82,EN,,0,0,0,,So here's a little representation that supports typed data.\nDialogue: 0,0:18:43.51,0:18:49.64,EN,,0,0,0,,There's a thing called take a type and attach it to a piece of contents,\nDialogue: 0,0:18:49.69,0:18:50.64,EN,,0,0,0,,and we just use cons.\nDialogue: 0,0:18:51.64,0:18:54.11,EN,,0,0,0,,And if we have a piece of typed data, we can look at the type\nDialogue: 0,0:18:55.21,0:18:56.00,EN,,0,0,0,,which is the car.\nDialogue: 0,0:18:56.29,0:18:58.30,EN,,0,0,0,,We can look at the contents,which is the cdr.\nDialogue: 0,0:18:59.96,0:19:04.28,EN,,0,0,0,,Now along with that, the way we use our type data will test,\nDialogue: 0,0:19:05.29,0:19:07.26,EN,,0,0,0,,when we're given a piece of data, what type it is.\nDialogue: 0,0:19:07.52,0:19:09.26,EN,,0,0,0,,So we have some type predicates with us.\nDialogue: 0,0:19:10.51,0:19:13.73,EN,,0,0,0,,For example, to see whether a complex number is one of\nDialogue: 0,0:19:13.73,0:19:16.86,EN,,0,0,0,,George's, whether it's rectangular, we just check to\nDialogue: 0,0:19:16.86,0:19:21.85,EN,,0,0,0,,see if the type of that is the symbol rectangular,\nDialogue: 0,0:19:23.68,0:19:25.05,EN,,0,0,0,,right? The symbol rectangular.\nDialogue: 0,0:19:27.20,0:19:30.33,EN,,0,0,0,,And to check whether a complex number is one of Martha's,\nDialogue: 0,0:19:30.33,0:19:33.42,EN,,0,0,0,,we check to see whether the type is the symbol polar.\nDialogue: 0,0:19:36.46,0:19:39.21,EN,,0,0,0,,So that's a way to test what kind of number we're looking at.\nDialogue: 0,0:19:40.75,0:19:42.81,EN,,0,0,0,,Now let's think about how we can use that to build the system.\nDialogue: 0,0:19:43.87,0:19:46.73,EN,,0,0,0,,So let's suppose that George and Martha were off working separately,\nDialogue: 0,0:19:47.36,0:19:52.64,EN,,0,0,0,,and each of them had designed their complex number representation packages.\nDialogue: 0,0:19:52.64,0:19:58.52,EN,,0,0,0,,What do they have to do to become part of the system,\nDialogue: 0,0:19:58.73,0:20:00.14,EN,,0,0,0,,to exist compatibly?\nDialogue: 0,0:20:00.14,0:20:02.11,EN,,0,0,0,,Well it's really pretty easy.\nDialogue: 0,0:20:02.72,0:20:04.51,EN,,0,0,0,,Remember, George had this package.\nDialogue: 0,0:20:05.97,0:20:08.48,EN,,0,0,0,,Here's George's original package, or half of it.\nDialogue: 0,0:20:08.98,0:20:11.15,EN,,0,0,0,,And underlined in red are the changes he has to make.\nDialogue: 0,0:20:12.09,0:20:16.43,EN,,0,0,0,,So before, when George made a complex number out of an x and y\nDialogue: 0,0:20:17.52,0:20:19.85,EN,,0,0,0,,he just put them together to make a pair.\nDialogue: 0,0:20:20.93,0:20:23.39,EN,,0,0,0,,And the only difference is that now he signs them.\nDialogue: 0,0:20:24.09,0:20:28.08,EN,,0,0,0,,He attaches the type, which is the symbol rectangular to that pair.\nDialogue: 0,0:20:30.60,0:20:33.26,EN,,0,0,0,,Everything else George does is the same, except that--\nDialogue: 0,0:20:33.92,0:20:38.06,EN,,0,0,0,,see, George and Martha both have procedures named real-part and imaginary-part.\nDialogue: 0,0:20:38.70,0:20:42.96,EN,,0,0,0,,So to allow them both to exist in the same Lisp environment,\nDialogue: 0,0:20:44.22,0:20:45.92,EN,,0,0,0,,George had changed the names of his procedures.\nDialogue: 0,0:20:45.92,0:20:49.14,EN,,0,0,0,,So we'll say, this is George's real-part procedure.\nDialogue: 0,0:20:49.14,0:20:51.16,EN,,0,0,0,,It's the real-part-rectangular procedure,\nDialogue: 0,0:20:51.48,0:20:54.06,EN,,0,0,0,,the imaginary-part-rectangular procedure.\nDialogue: 0,0:20:55.42,0:20:57.24,EN,,0,0,0,,And then here's the rest of George's package.\nDialogue: 0,0:20:59.13,0:21:02.06,EN,,0,0,0,,He'd had magnitude and angle, just renames them magnitude\nDialogue: 0,0:21:02.06,0:21:04.16,EN,,0,0,0,,rectangular and angle rectangular.\nDialogue: 0,0:21:06.08,0:21:07.96,EN,,0,0,0,,And Martha has to do basically the same thing.\nDialogue: 0,0:21:09.86,0:21:16.22,EN,,0,0,0,,Martha previously, when she made a complex number out of a magnitude and angle,\nDialogue: 0,0:21:18.14,0:21:19.27,EN,,0,0,0,,she just cons them.\nDialogue: 0,0:21:19.27,0:21:20.86,EN,,0,0,0,,Now she attaches the type polar,\nDialogue: 0,0:21:23.95,0:21:25.61,EN,,0,0,0,,and she changes the name\nDialogue: 0,0:21:25.66,0:21:29.85,EN,,0,0,0,,so her real-part procedure won't conflict in name with George's.\nDialogue: 0,0:21:30.71,0:21:32.99,EN,,0,0,0,,It's a real-part-polar,imaginary-part-polar,\nDialogue: 0,0:21:34.54,0:21:38.06,EN,,0,0,0,,magnitude polar, and angle polar.\nDialogue: 0,0:21:45.00,0:21:46.13,EN,,0,0,0,,Now we have the system.\nDialogue: 0,0:21:46.13,0:21:47.92,EN,,0,0,0,,Right there's George and Martha.\nDialogue: 0,0:21:49.16,0:21:51.68,EN,,0,0,0,,And now we've got to get some kind of manager to look at these types.\nDialogue: 0,0:21:52.83,0:21:56.48,EN,,0,0,0,,How are these things actually going to work now\nDialogue: 0,0:21:57.05,0:21:59.40,EN,,0,0,0,,that George and Martha have supplied us with typed data?\nDialogue: 0,0:22:00.53,0:22:04.30,EN,,0,0,0,,Well what we have are a bunch of generic selectors.\nDialogue: 0,0:22:05.26,0:22:10.63,EN,,0,0,0,,Generic selectors for complex numbers real-part,imaginary-part, magnitude, and angle.\nDialogue: 0,0:22:14.14,0:22:15.40,EN,,0,0,0,,Let's look at them more closely.\nDialogue: 0,0:22:17.93,0:22:19.00,EN,,0,0,0,,What does a real-part do?\nDialogue: 0,0:22:19.31,0:22:22.76,EN,,0,0,0,,If I ask for the real part of a complex number,\nDialogue: 0,0:22:24.07,0:22:24.91,EN,,0,0,0,,well I look at it.\nDialogue: 0,0:22:25.80,0:22:26.69,EN,,0,0,0,,I look at its type.\nDialogue: 0,0:22:26.69,0:22:28.12,EN,,0,0,0,,I say, is it rectangular?\nDialogue: 0,0:22:31.02,0:22:35.36,EN,,0,0,0,,If so, I apply George's real part procedure\nDialogue: 0,0:22:36.06,0:22:37.92,EN,,0,0,0,,to the contents of that complex number.\nDialogue: 0,0:22:41.07,0:22:42.94,EN,,0,0,0,,This is a number that has a type on it.\nDialogue: 0,0:22:43.72,0:22:47.66,EN,,0,0,0,,I strip off the type using contents and apply George's procedure.\nDialogue: 0,0:22:50.70,0:22:52.86,EN,,0,0,0,,Or is this a polar complex number?\nDialogue: 0,0:22:53.95,0:22:54.97,EN,,0,0,0,,If I want the real part,\nDialogue: 0,0:22:55.45,0:22:58.78,EN,,0,0,0,,I apply Martha's real-part procedure to the contents of that number.\nDialogue: 0,0:22:59.85,0:23:01.15,EN,,0,0,0,,So that's how real part works.\nDialogue: 0,0:23:02.26,0:23:05.66,EN,,0,0,0,,And then similarly there's imaginary-part, which is almost the same.\nDialogue: 0,0:23:06.51,0:23:09.60,EN,,0,0,0,,Right? It looks at the number and if it's rectangular, uses\nDialogue: 0,0:23:09.60,0:23:11.13,EN,,0,0,0,,George's imaginary-part procedure.\nDialogue: 0,0:23:11.13,0:23:12.83,EN,,0,0,0,,If it's polar, uses Martha's.\nDialogue: 0,0:23:13.38,0:23:17.40,EN,,0,0,0,,And then there's a magnitude and an angle.\nDialogue: 0,0:23:19.71,0:23:21.02,EN,,0,0,0,,So there's a system.\nDialogue: 0,0:23:23.00,0:23:24.26,EN,,0,0,0,,Has three parts.\nDialogue: 0,0:23:24.26,0:23:26.59,EN,,0,0,0,,There's sort of George, and Martha, and the manager.\nDialogue: 0,0:23:26.76,0:23:28.97,EN,,0,0,0,,And that's how you get generic operators implemented.\nDialogue: 0,0:23:28.97,0:23:32.92,EN,,0,0,0,,Let's look at just a simple example, just to pin it down.\nDialogue: 0,0:23:33.50,0:23:35.12,EN,,0,0,0,,But exactly how this is going to work,\nDialogue: 0,0:23:36.54,0:23:43.98,EN,,0,0,0,,suppose you're going to be looking at the complex number who's real-part is one,\nDialogue: 0,0:23:44.52,0:23:46.09,EN,,0,0,0,,and who's imaginary-part is two.\nDialogue: 0,0:23:46.09,0:23:48.44,EN,,0,0,0,,So that would be one plus 2i.\nDialogue: 0,0:23:50.31,0:23:52.64,EN,,0,0,0,,What would happen is up here,\nDialogue: 0,0:23:55.28,0:23:57.53,EN,,0,0,0,,up here above where the operations have to happen,\nDialogue: 0,0:23:57.63,0:24:08.27,EN,,0,0,0,,that number would be represented as a pair of 1 and 2 together with type data.\nDialogue: 0,0:24:10.48,0:24:11.39,EN,,0,0,0,,That would be the contents.\nDialogue: 0,0:24:11.87,0:24:17.96,EN,,0,0,0,,And the whole data would be that thing with the symbol rectangular added onto that.\nDialogue: 0,0:24:18.14,0:24:21.53,EN,,0,0,0,,And that's the way that complex number would exist in the system.\nDialogue: 0,0:24:22.33,0:24:24.92,EN,,0,0,0,,When you went to take the real-part,\nDialogue: 0,0:24:25.84,0:24:28.89,EN,,0,0,0,,the manager will look at this and say, oh it's one of George's.\nDialogue: 0,0:24:30.27,0:24:31.53,EN,,0,0,0,,He'll strip off the type\nDialogue: 0,0:24:33.34,0:24:36.91,EN,,0,0,0,,and hand down to George the pair 1, 2.\nDialogue: 0,0:24:38.00,0:24:42.27,EN,,0,0,0,,And that's the kind of data that George developed his system to use.\nDialogue: 0,0:24:44.36,0:24:45.92,EN,,0,0,0,,So it gets stripped down.\nDialogue: 0,0:24:46.52,0:24:49.76,EN,,0,0,0,,Later on, if you ask George to construct a complex number,\nDialogue: 0,0:24:51.24,0:24:54.56,EN,,0,0,0,,George would construct some complex number as a pair,\nDialogue: 0,0:24:55.07,0:24:58.24,EN,,0,0,0,,and before he passes it back up through the manager would\nDialogue: 0,0:24:59.42,0:25:01.13,EN,,0,0,0,,attach the type rectangular.\nDialogue: 0,0:25:03.92,0:25:04.65,EN,,0,0,0,,So you see what happens.\nDialogue: 0,0:25:04.65,0:25:05.85,EN,,0,0,0,,There's no confusion in this system.\nDialogue: 0,0:25:05.85,0:25:10.84,EN,,0,0,0,,It doesn't matter in the least that the pair 1, 2\nDialogue: 0,0:25:13.50,0:25:15.75,EN,,0,0,0,,means something completely different in Martha's world.\nDialogue: 0,0:25:15.75,0:25:18.44,EN,,0,0,0,,In Martha's world this pair means the complex number whose\nDialogue: 0,0:25:18.44,0:25:20.78,EN,,0,0,0,,magnitude is 1 and whose angle is 2.\nDialogue: 0,0:25:21.19,0:25:22.19,EN,,0,0,0,,And there's no confusion,\nDialogue: 0,0:25:22.22,0:25:27.25,EN,,0,0,0,,because by the time any pair like this gets handed back through the manager to the\nDialogue: 0,0:25:27.25,0:25:29.61,EN,,0,0,0,,main system it's going to have the type polar attached.\nDialogue: 0,0:25:31.21,0:25:33.67,EN,,0,0,0,,Whereas this one would have the type rectangular attached.\nDialogue: 0,0:25:36.93,0:25:37.90,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:25:40.77,0:25:55.55,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:25:55.69,0:25:57.77,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:25:57.77,0:25:59.76,EN,,0,0,0,,By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:26:05.21,0:26:11.95,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:26:12.84,0:26:16.75,EN,,0,0,0,,Generic Operators\nDialogue: 0,0:26:20.21,0:26:24.15,EN,,0,0,0,,We just looked at a strategy for implementing generic operators.\nDialogue: 0,0:26:24.15,0:26:31.40,EN,,0,0,0,,That strategy has a name: it's called dispatch on type.\nDialogue: 0,0:26:34.31,0:26:39.36,EN,,0,0,0,,And the idea is that you break your system into a bunch of pieces.\nDialogue: 0,0:26:39.36,0:26:42.67,EN,,0,0,0,,There's George and Martha, who are making representations,\nDialogue: 0,0:26:43.37,0:26:44.38,EN,,0,0,0,,and then there's the manager.\nDialogue: 0,0:26:46.12,0:26:48.06,EN,,0,0,0,,Looks at the types on the data\nDialogue: 0,0:26:48.51,0:26:50.59,EN,,0,0,0,,and then dispatches them to the right person.\nDialogue: 0,0:26:51.99,0:26:56.01,EN,,0,0,0,,Well what criticisms can we make of that as a system organization?\nDialogue: 0,0:26:58.15,0:27:00.40,EN,,0,0,0,,Well first of all there was this little, annoying problem\nDialogue: 0,0:27:00.40,0:27:03.05,EN,,0,0,0,,that George and Martha had to change the names of their procedures\nDialogue: 0,0:27:04.00,0:27:05.95,EN,,0,0,0,,George originally had a real-part procedure,\nDialogue: 0,0:27:05.98,0:27:08.28,EN,,0,0,0,,and he had to go name it real-part rectangular\nDialogue: 0,0:27:08.30,0:27:10.83,EN,,0,0,0,,so it wouldn't interfere with Martha's real-part procedure,\nDialogue: 0,0:27:10.84,0:27:12.76,EN,,0,0,0,,which is now named real-part-polar,\nDialogue: 0,0:27:13.64,0:27:16.68,EN,,0,0,0,,so it wouldn't interfere with the manager's real-part procedure, who's now named real-part.\nDialogue: 0,0:27:17.31,0:27:18.94,EN,,0,0,0,,That's kind of an annoying problem.\nDialogue: 0,0:27:19.46,0:27:21.13,EN,,0,0,0,,But I'm not going to talk about that one now.\nDialogue: 0,0:27:21.27,0:27:22.35,EN,,0,0,0,,We'll see later on\nDialogue: 0,0:27:23.26,0:27:26.12,EN,,0,0,0,,when we think about the structure of Lisp names and environments\nDialogue: 0,0:27:26.12,0:27:30.39,EN,,0,0,0,,that there really are ways to package all those so-called name spaces separately so they\nDialogue: 0,0:27:30.39,0:27:31.56,EN,,0,0,0,,don't interfere with each other.\nDialogue: 0,0:27:32.50,0:27:34.01,EN,,0,0,0,,Not going to think about that problem now.\nDialogue: 0,0:27:35.72,0:27:38.19,EN,,0,0,0,,The problem that I actually want to focus on is\nDialogue: 0,0:27:38.36,0:27:43.24,EN,,0,0,0,,what happens when you bring somebody new into the system.\nDialogue: 0,0:27:44.51,0:27:45.32,EN,,0,0,0,,What has to happen?\nDialogue: 0,0:27:45.32,0:27:46.81,EN,,0,0,0,,Well George and Martha don't care.\nDialogue: 0,0:27:47.42,0:27:50.73,EN,,0,0,0,,George is sitting there in his rectangular world,\nDialogue: 0,0:27:52.20,0:27:53.84,EN,,0,0,0,,has his procedures and his types.\nDialogue: 0,0:27:54.09,0:27:55.74,EN,,0,0,0,,Martha sits in her polar world.\nDialogue: 0,0:27:55.93,0:27:57.02,EN,,0,0,0,,She doesn't care.\nDialogue: 0,0:27:59.38,0:28:00.54,EN,,0,0,0,,But let's look at the manager.\nDialogue: 0,0:28:00.62,0:28:02.84,EN,,0,0,0,,What's the manager have to do?\nDialogue: 0,0:28:03.18,0:28:06.20,EN,,0,0,0,,The manager comes through and had these operations.\nDialogue: 0,0:28:07.36,0:28:09.04,EN,,0,0,0,,There was a test for rectangular\nDialogue: 0,0:28:09.04,0:28:10.14,EN,,0,0,0,,and a test for polar.\nDialogue: 0,0:28:10.14,0:28:14.91,EN,,0,0,0,,If Harry comes in with some new kind of complex number,\nDialogue: 0,0:28:17.21,0:28:19.96,EN,,0,0,0,,and Harry has a new type, Harry type complex number, the\nDialogue: 0,0:28:20.27,0:28:23.28,EN,,0,0,0,,manager has to go in and change all those procedures.\nDialogue: 0,0:28:25.24,0:28:26.94,EN,,0,0,0,,So the inflexibility in the system,\nDialogue: 0,0:28:26.96,0:28:32.41,EN,,0,0,0,,the place where work has to happen to accommodate change, is in the manager.\nDialogue: 0,0:28:34.89,0:28:35.99,EN,,0,0,0,,That's pretty annoying.\nDialogue: 0,0:28:35.99,0:28:37.21,EN,,0,0,0,,It's even more annoying\nDialogue: 0,0:28:39.05,0:28:41.21,EN,,0,0,0,,It's even more annoying when you realize the manager's not doing anything\nDialogue: 0,0:28:42.59,0:28:44.67,EN,,0,0,0,,The manager is just being a paper pusher.\nDialogue: 0,0:28:45.84,0:28:51.13,EN,,0,0,0,,Let's look again at these programs. What are they doing?\nDialogue: 0,0:28:51.76,0:28:52.72,EN,,0,0,0,,What does real-part do?\nDialogue: 0,0:28:52.88,0:28:56.17,EN,,0,0,0,,Real-part says, oh, is it the kind of complex number that\nDialogue: 0,0:28:56.17,0:28:57.00,EN,,0,0,0,,George can handle?\nDialogue: 0,0:28:57.00,0:28:58.27,EN,,0,0,0,,If so, send it off to George.\nDialogue: 0,0:28:59.41,0:29:01.76,EN,,0,0,0,,Is it the kind of complex number that Martha can handle?\nDialogue: 0,0:29:01.82,0:29:04.06,EN,,0,0,0,,If so, send it off to Martha.\nDialogue: 0,0:29:05.04,0:29:08.72,EN,,0,0,0,,So it's really annoying that the bottleneck in this system,\nDialogue: 0,0:29:08.72,0:29:11.66,EN,,0,0,0,,the thing that's preventing flexibility and change,\nDialogue: 0,0:29:12.09,0:29:14.36,EN,,0,0,0,,is completely in the bureaucracy.\nDialogue: 0,0:29:15.00,0:29:17.02,EN,,0,0,0,,It's not in anybody who's doing any of the work.\nDialogue: 0,0:29:19.70,0:29:21.80,EN,,0,0,0,,Not an uncommon situation, unfortunately.\nDialogue: 0,0:29:23.18,0:29:24.41,EN,,0,0,0,,See, what's really going on--\nDialogue: 0,0:29:24.48,0:29:26.97,EN,,0,0,0,,abstractly in the system, there's a table.\nDialogue: 0,0:29:28.10,0:29:30.08,EN,,0,0,0,,So what's really happening is somewhere there's a table.\nDialogue: 0,0:29:30.84,0:29:33.64,EN,,0,0,0,,There're types.\nDialogue: 0,0:29:34.40,0:29:38.96,EN,,0,0,0,,There's polar and rectangular.\nDialogue: 0,0:29:41.55,0:29:43.02,EN,,0,0,0,,And Harry's may be over here.\nDialogue: 0,0:29:44.38,0:29:46.56,EN,,0,0,0,,And there are operators.\nDialogue: 0,0:29:48.05,0:29:58.24,EN,,0,0,0,,There's an operator like real-part. Or imaginary-part.\nDialogue: 0,0:30:00.01,0:30:04.22,EN,,0,0,0,,Or a magnitude and angle.\nDialogue: 0,0:30:05.83,0:30:18.97,EN,,0,0,0,,And sitting in this table are the right procedures.\nDialogue: 0,0:30:19.28,0:30:21.99,EN,,0,0,0,,So sitting here for the type polar and real-part is\nDialogue: 0,0:30:21.99,0:30:27.56,EN,,0,0,0,,Martha's procedure real-part-polar.\nDialogue: 0,0:30:30.57,0:30:36.62,EN,,0,0,0,,And over here in the table is George's procedure real-part-rectangular.\nDialogue: 0,0:30:37.74,0:30:43.07,EN,,0,0,0,,And over here would be, say, Martha's procedure magnitude-polar,\nDialogue: 0,0:30:44.46,0:30:49.76,EN,,0,0,0,,and George's procedure magnitude-rectangular, right, and so on.\nDialogue: 0,0:30:49.76,0:30:51.24,EN,,0,0,0,,The rest of this table's filled in.\nDialogue: 0,0:30:52.39,0:30:54.26,EN,,0,0,0,,And that's really what's going on.\nDialogue: 0,0:30:57.63,0:31:01.74,EN,,0,0,0,,So in some sense, all the manager is doing\nDialogue: 0,0:31:02.11,0:31:04.11,EN,,0,0,0,,is acting as this table.\nDialogue: 0,0:31:06.86,0:31:08.70,EN,,0,0,0,,Well how do we fix our system?\nDialogue: 0,0:31:11.74,0:31:13.77,EN,,0,0,0,,Well, how do you fix bureaucracies a lot of the time?\nDialogue: 0,0:31:13.77,0:31:15.44,EN,,0,0,0,,What you do is you get rid of the manager.\nDialogue: 0,0:31:16.01,0:31:19.55,EN,,0,0,0,,We just take the manager and replace him by a computer.\nDialogue: 0,0:31:20.17,0:31:21.76,EN,,0,0,0,,We're going to automate him out of existence.\nDialogue: 0,0:31:23.32,0:31:26.57,EN,,0,0,0,,Namely, instead of having the manager who basically consults this table,\nDialogue: 0,0:31:27.45,0:31:29.32,EN,,0,0,0,,we'll have our system use the table directly.\nDialogue: 0,0:31:31.02,0:31:32.11,EN,,0,0,0,,What do I mean by that?\nDialogue: 0,0:31:32.11,0:31:36.19,EN,,0,0,0,,Let's assume, again using data abstraction,\nDialogue: 0,0:31:37.71,0:31:40.40,EN,,0,0,0,,that we have some kind of data structure that's a table.\nDialogue: 0,0:31:40.88,0:31:43.61,EN,,0,0,0,,And we have ways of sticking things in and ways of getting things out.\nDialogue: 0,0:31:44.35,0:31:49.04,EN,,0,0,0,,And to be explicit, let me assume that there's an operation called \"put.\"\nDialogue: 0,0:31:50.30,0:31:58.32,EN,,0,0,0,,And put is going to take, case two things I'll call \"keys.\" key1 and key2.\nDialogue: 0,0:32:00.13,0:32:00.99,EN,,0,0,0,,And a value.\nDialogue: 0,0:32:06.20,0:32:11.12,EN,,0,0,0,,And that stores the value in the table under key1 and key2.\nDialogue: 0,0:32:11.49,0:32:13.16,EN,,0,0,0,,And then we'll assume there's a thing called \"get,\"\nDialogue: 0,0:32:15.23,0:32:18.72,EN,,0,0,0,,such that if later on I say, get me what's in the table\nDialogue: 0,0:32:19.40,0:32:22.76,EN,,0,0,0,,stored under key1 and key2,\nDialogue: 0,0:32:23.40,0:32:25.39,EN,,0,0,0,,it'll retrieve whatever value was stored there.\nDialogue: 0,0:32:26.73,0:32:29.44,EN,,0,0,0,,And let's not worry about how tables are implemented.\nDialogue: 0,0:32:30.00,0:32:32.52,EN,,0,0,0,,That's yet another data abstraction, George's problem.\nDialogue: 0,0:32:33.06,0:32:34.36,EN,,0,0,0,,And maybe we'll see later--\nDialogue: 0,0:32:34.70,0:32:36.97,EN,,0,0,0,,talk about how you might actually build tables in Lisp.\nDialogue: 0,0:32:40.71,0:32:45.50,EN,,0,0,0,,Well given this organization,what did George and Martha have to do?\nDialogue: 0,0:32:47.38,0:32:49.07,EN,,0,0,0,,Well when they build their system,\nDialogue: 0,0:32:49.13,0:32:51.08,EN,,0,0,0,,they each have the responsibility\nDialogue: 0,0:32:51.44,0:32:53.82,EN,,0,0,0,,to set up their appropriate column in the table.\nDialogue: 0,0:32:55.21,0:32:57.47,EN,,0,0,0,,So what George does, for example,\nDialogue: 0,0:32:59.79,0:33:02.06,EN,,0,0,0,,when he defines his procedures all he has to do\nDialogue: 0,0:33:02.27,0:33:07.99,EN,,0,0,0,,is go off and put into the table under the type-rectangular.\nDialogue: 0,0:33:09.82,0:33:12.12,EN,,0,0,0,,And the name of the operation is real-part,\nDialogue: 0,0:33:13.31,0:33:15.26,EN,,0,0,0,,his procedure real-part-rectangular.\nDialogue: 0,0:33:16.25,0:33:17.78,EN,,0,0,0,,So notice what's going into this table.\nDialogue: 0,0:33:17.78,0:33:22.10,EN,,0,0,0,,The two keys here are symbols, rectangular and real-part.\nDialogue: 0,0:33:22.10,0:33:22.75,EN,,0,0,0,,That's the quote.\nDialogue: 0,0:33:24.40,0:33:26.75,EN,,0,0,0,,And what's going into the table is the actual\nDialogue: 0,0:33:26.84,0:33:29.21,EN,,0,0,0,,procedure that he wrote, real-part rectangular.\nDialogue: 0,0:33:31.85,0:33:34.30,EN,,0,0,0,,And then puts an imaginary part into the table,\nDialogue: 0,0:33:34.59,0:33:37.80,EN,,0,0,0,,filed under the keys rectangular and imaginary-part,\nDialogue: 0,0:33:38.62,0:33:42.88,EN,,0,0,0,,and magnitude under the keys rectangular magnitude,\nDialogue: 0,0:33:43.61,0:33:45.20,EN,,0,0,0,,angle under rectangular-angle.\nDialogue: 0,0:33:47.04,0:33:50.84,EN,,0,0,0,,Okay? So that's what George has to do to be part of this system.\nDialogue: 0,0:33:54.42,0:33:58.86,EN,,0,0,0,,Martha similarly sets up the column and the table under polar.\nDialogue: 0,0:33:59.43,0:34:00.65,EN,,0,0,0,,Polar and real-part.\nDialogue: 0,0:34:01.69,0:34:03.58,EN,,0,0,0,,Right? Is the procedure real-part-polar?\nDialogue: 0,0:34:04.34,0:34:07.29,EN,,0,0,0,,And imaginary-part, and magnitude, and angle.\nDialogue: 0,0:34:08.91,0:34:11.40,EN,,0,0,0,,So this is what Martha has to do to be part of the system.\nDialogue: 0,0:34:11.40,0:34:13.55,EN,,0,0,0,,Everyone who makes a representation has the\nDialogue: 0,0:34:13.55,0:34:17.63,EN,,0,0,0,,responsibility for setting up a column in the table.\nDialogue: 0,0:34:17.76,0:34:19.90,EN,,0,0,0,,And what does Harry do when Harry comes in with his\nDialogue: 0,0:34:19.90,0:34:21.80,EN,,0,0,0,,brilliant idea for implementing complex numbers?\nDialogue: 0,0:34:21.80,0:34:23.96,EN,,0,0,0,,Well he makes whatever procedure he wants and\nDialogue: 0,0:34:24.04,0:34:26.52,EN,,0,0,0,,builds a new column in this table.\nDialogue: 0,0:34:28.55,0:34:30.04,EN,,0,0,0,,OK, well what happened to the manager?\nDialogue: 0,0:34:31.33,0:34:34.61,EN,,0,0,0,,The manager has been automated out of existence and is\nDialogue: 0,0:34:34.61,0:34:37.11,EN,,0,0,0,,replaced by a procedure called operate.\nDialogue: 0,0:34:37.11,0:34:39.55,EN,,0,0,0,,And this is the key procedure in the whole system.\nDialogue: 0,0:34:40.38,0:34:45.92,EN,,0,0,0,,Let's say define operate.\nDialogue: 0,0:34:51.06,0:34:56.09,EN,,0,0,0,,Operate is going to take an operation that you want to do,\nDialogue: 0,0:34:57.75,0:34:58.88,EN,,0,0,0,,the name of an operation,\nDialogue: 0,0:34:59.20,0:35:03.28,EN,,0,0,0,,and an object that you would like to apply that operation to.\nDialogue: 0,0:35:04.21,0:35:09.76,EN,,0,0,0,,So for example, the real-part of some particular complex number, what does it do?\nDialogue: 0,0:35:09.95,0:35:11.90,EN,,0,0,0,,Well the first thing it does, it looks in the table.\nDialogue: 0,0:35:12.64,0:35:13.87,EN,,0,0,0,,Goes into the table\nDialogue: 0,0:35:14.80,0:35:22.56,EN,,0,0,0,,and tries to find a procedure that's stored in the table.\nDialogue: 0,0:35:23.15,0:35:24.80,EN,,0,0,0,,So it gets from the table,\nDialogue: 0,0:35:25.50,0:35:33.92,EN,,0,0,0,,using as keys the type of the object and the operator,\nDialogue: 0,0:35:38.92,0:35:40.14,EN,,0,0,0,,but looks on the table and sees\nDialogue: 0,0:35:40.38,0:35:42.72,EN,,0,0,0,,what's stored under the type of the object and the operator\nDialogue: 0,0:35:42.89,0:35:44.35,EN,,0,0,0,,sees if anything's stored.\nDialogue: 0,0:35:44.44,0:35:45.93,EN,,0,0,0,,Let's assume that get is implemented.\nDialogue: 0,0:35:45.93,0:35:47.72,EN,,0,0,0,,So if nothing is stored there,\nDialogue: 0,0:35:48.11,0:35:51.79,EN,,0,0,0,,it'll return a nil, return the empty list.\nDialogue: 0,0:35:52.67,0:35:55.39,EN,,0,0,0,,So it says, if there's actually something stored there,\nDialogue: 0,0:35:56.62,0:36:00.43,EN,,0,0,0,,if the procedure here is not no,\nDialogue: 0,0:36:03.15,0:36:07.12,EN,,0,0,0,,then it'll take the procedure that it found in the table\nDialogue: 0,0:36:09.79,0:36:15.00,EN,,0,0,0,,procedure that it found in the table and apply it to the contents of the object.\nDialogue: 0,0:36:18.25,0:36:20.40,EN,,0,0,0,,And otherwise if there was nothing stored there,\nDialogue: 0,0:36:20.67,0:36:22.51,EN,,0,0,0,,it'll-- well we can decide.\nDialogue: 0,0:36:22.81,0:36:27.12,EN,,0,0,0,,In this case let's have it put out an error message saying, undefined operator.\nDialogue: 0,0:36:28.48,0:36:30.24,EN,,0,0,0,,No operator for this type.\nDialogue: 0,0:36:33.07,0:36:34.72,EN,,0,0,0,,Or some appropriate error message.\nDialogue: 0,0:36:39.07,0:36:39.48,EN,,0,0,0,,OK?\nDialogue: 0,0:36:39.72,0:36:41.04,EN,,0,0,0,,And that replaces the manager.\nDialogue: 0,0:36:41.89,0:36:42.91,EN,,0,0,0,,How do we really use it?\nDialogue: 0,0:36:43.96,0:36:49.80,EN,,0,0,0,,Well what we say is we'll go off and define our generic selectors using operate.\nDialogue: 0,0:36:50.04,0:36:56.75,EN,,0,0,0,,We'll say that the real-part of an object is found by\nDialogue: 0,0:36:57.14,0:37:05.66,EN,,0,0,0,,operating on the object with the name of the operation being real-part.\nDialogue: 0,0:37:08.07,0:37:12.22,EN,,0,0,0,,And then similarly, imaginary-part is operate using the name imaginary-part\nDialogue: 0,0:37:12.22,0:37:13.98,EN,,0,0,0,,and magnitude and angle.\nDialogue: 0,0:37:15.36,0:37:17.43,EN,,0,0,0,,That's our implementation.\nDialogue: 0,0:37:17.43,0:37:20.48,EN,,0,0,0,,That plus the type plus the operate procedure.\nDialogue: 0,0:37:21.33,0:37:24.00,EN,,0,0,0,,And the table effectively replaces what the  manager used to do.\nDialogue: 0,0:37:24.06,0:37:27.69,EN,,0,0,0,,Let's just go through that slowly to show you what's going on.\nDialogue: 0,0:37:27.90,0:37:33.00,EN,,0,0,0,,Suppose I have one of Martha's complex numbers.\nDialogue: 0,0:37:33.53,0:37:38.80,EN,,0,0,0,,It's got magnitude 1 and angle 2.\nDialogue: 0,0:37:39.10,0:37:40.22,EN,,0,0,0,,And it's one of Martha's.\nDialogue: 0,0:37:40.22,0:37:45.45,EN,,0,0,0,,So it's labeled here, polar.\nDialogue: 0,0:37:47.24,0:37:48.00,EN,,0,0,0,,Let's call that z.\nDialogue: 0,0:37:48.00,0:37:48.91,EN,,0,0,0,,Suppose that's z.\nDialogue: 0,0:37:51.77,0:37:54.46,EN,,0,0,0,,And suppose with this implementation someone comes up\nDialogue: 0,0:37:54.80,0:37:57.92,EN,,0,0,0,,asks for the real-part of z.\nDialogue: 0,0:38:04.87,0:38:07.96,EN,,0,0,0,,Well real-part now is defined in terms of operate.\nDialogue: 0,0:38:09.16,0:38:10.57,EN,,0,0,0,,So that's equivalent to saying\nDialogue: 0,0:38:12.09,0:38:24.81,EN,,0,0,0,,operate with the name of the operator being real-part, the symbol real-part on z.\nDialogue: 0,0:38:27.06,0:38:28.09,EN,,0,0,0,,And now operate comes.\nDialogue: 0,0:38:28.09,0:38:29.24,EN,,0,0,0,,It's going to look in the table,\nDialogue: 0,0:38:31.04,0:38:34.36,EN,,0,0,0,,and it's going to try and find something stored under--\nDialogue: 0,0:38:39.00,0:38:46.22,EN,,0,0,0,,the operation is going to apply by looking in the table under the type of the object.\nDialogue: 0,0:38:46.72,0:38:48.22,EN,,0,0,0,,And the type of z is polar.\nDialogue: 0,0:38:48.79,0:38:51.37,EN,,0,0,0,,So it's going to look and say, can I get using polar?\nDialogue: 0,0:38:52.99,0:38:58.57,EN,,0,0,0,,And the operation name, which was real-part.\nDialogue: 0,0:39:05.96,0:39:13.63,EN,,0,0,0,,It's going to look in there and apply that to the contents of z.\nDialogue: 0,0:39:14.83,0:39:17.13,EN,,0,0,0,,What's that is if everything was set up correctly,\nDialogue: 0,0:39:17.74,0:39:21.70,EN,,0,0,0,,this thing is the procedure that Martha put there.\nDialogue: 0,0:39:21.70,0:39:22.95,EN,,0,0,0,,This is real-part-polar.\nDialogue: 0,0:39:31.05,0:39:35.13,EN,,0,0,0,,And this is z without its type.\nDialogue: 0,0:39:35.44,0:39:38.94,EN,,0,0,0,,The thing that Martha originally designed those procedures to work on,\nDialogue: 0,0:39:39.40,0:39:40.43,EN,,0,0,0,,which is 1, 2.\nDialogue: 0,0:39:43.71,0:39:45.87,EN,,0,0,0,,And so operate sort of does uniformly\nDialogue: 0,0:39:46.46,0:39:48.89,EN,,0,0,0,,what the manager used to do sort of all over the system.\nDialogue: 0,0:39:49.45,0:39:52.59,EN,,0,0,0,,It finds the right thing, looks in the table, strips off the type,\nDialogue: 0,0:39:53.58,0:39:57.52,EN,,0,0,0,,and passes it down into the person who handles it.\nDialogue: 0,0:39:58.88,0:40:05.48,EN,,0,0,0,,This is another, and, you can see, more flexible for most purposes,\nDialogue: 0,0:40:06.22,0:40:08.04,EN,,0,0,0,,way of implementing generic operators.\nDialogue: 0,0:40:08.08,0:40:15.69,EN,,0,0,0,,And it's called data-directed programming.\nDialogue: 0,0:40:20.35,0:40:21.96,EN,,0,0,0,,And the idea of that is\nDialogue: 0,0:40:23.42,0:40:25.55,EN,,0,0,0,,And the idea of that is in some sense the data objects themselves,\nDialogue: 0,0:40:26.04,0:40:28.35,EN,,0,0,0,,those little complex numbers that are floating around the system,\nDialogue: 0,0:40:28.73,0:40:33.16,EN,,0,0,0,,are carrying with them the information about how you should operate on them.\nDialogue: 0,0:40:35.74,0:40:36.78,EN,,0,0,0,,Let's break for questions.\nDialogue: 0,0:40:41.00,0:40:41.24,EN,,0,0,0,,Yes.\nDialogue: 0,0:40:41.24,0:40:43.39,EN,,0,0,0,,AUDIENCE: What do you have stored in that data object?\nDialogue: 0,0:40:43.39,0:40:47.10,EN,,0,0,0,,You have the data itself, you have its type,\nDialogue: 0,0:40:47.10,0:40:49.60,EN,,0,0,0,,the operations for that type?\nDialogue: 0,0:40:49.69,0:40:53.08,EN,,0,0,0,,Or where are the operations that you found?\nDialogue: 0,0:40:53.60,0:40:54.17,EN,,0,0,0,,PROFESSOR: OK, let me--\nDialogue: 0,0:40:54.98,0:40:56.50,EN,,0,0,0,,yeah, that's a good question.\nDialogue: 0,0:40:56.50,0:41:00.46,EN,,0,0,0,,Because it raises other possibilities of how you might do it.\nDialogue: 0,0:41:00.75,0:41:02.48,EN,,0,0,0,,And of course there are a lot of possibilities.\nDialogue: 0,0:41:04.20,0:41:06.14,EN,,0,0,0,,In this particular implementation,\nDialogue: 0,0:41:06.24,0:41:09.72,EN,,0,0,0,,what's sitting in this data object, for example,\nDialogue: 0,0:41:10.44,0:41:13.45,EN,,0,0,0,,is the data itself-- which in this case is a pair of 1 and 2--\nDialogue: 0,0:41:14.98,0:41:16.55,EN,,0,0,0,,and also a symbol.\nDialogue: 0,0:41:16.55,0:41:19.07,EN,,0,0,0,,This is the symbol, the word P-O-L-A-R,\nDialogue: 0,0:41:20.60,0:41:22.33,EN,,0,0,0,,And that what's sitting in this data object.\nDialogue: 0,0:41:24.24,0:41:26.69,EN,,0,0,0,,OK, where are the operations themselves?\nDialogue: 0,0:41:26.69,0:41:29.00,EN,,0,0,0,,The operations are sitting in the table.\nDialogue: 0,0:41:29.85,0:41:31.07,EN,,0,0,0,,So in this table,\nDialogue: 0,0:41:32.30,0:41:36.46,EN,,0,0,0,,the rows and columns of the table are labeled by symbols.\nDialogue: 0,0:41:38.23,0:41:40.08,EN,,0,0,0,,So when I store something in this table,\nDialogue: 0,0:41:40.09,0:41:47.02,EN,,0,0,0,,the key might be the symbol polar and the symbol magnitude.\nDialogue: 0,0:41:48.24,0:41:51.31,EN,,0,0,0,,And I think by writing it this way I've been very confusing.\nDialogue: 0,0:41:51.31,0:41:52.70,EN,,0,0,0,,Because what's really sitting here isn't--\nDialogue: 0,0:41:53.16,0:41:54.57,EN,,0,0,0,,when I wrote magnitude polar,\nDialogue: 0,0:41:57.04,0:41:59.23,EN,,0,0,0,,what I mean is the procedure magnitude polar.\nDialogue: 0,0:41:59.85,0:42:01.85,EN,,0,0,0,,And probably what I really should have written--\nDialogue: 0,0:42:02.58,0:42:04.20,EN,,0,0,0,,except it's too small for me to write\nDialogue: 0,0:42:04.20,0:42:05.07,EN,,0,0,0,,in this little space--\nDialogue: 0,0:42:05.58,0:42:08.92,EN,,0,0,0,,is something like lambda of z,\nDialogue: 0,0:42:10.60,0:42:12.75,EN,,0,0,0,,the thing that Martha wrote to implement.\nDialogue: 0,0:42:14.71,0:42:15.72,EN,,0,0,0,,And then you can see from that,\nDialogue: 0,0:42:15.74,0:42:17.44,EN,,0,0,0,,there's another way that I alluded to\nDialogue: 0,0:42:17.71,0:42:19.82,EN,,0,0,0,,of solving this name conflict problem\nDialogue: 0,0:42:20.04,0:42:23.15,EN,,0,0,0,,which is that George and Martha never have to name their procedures at all.\nDialogue: 0,0:42:23.15,0:42:25.37,EN,,0,0,0,,They can just stick the lambda, the lambda...\nDialogue: 0,0:42:25.39,0:42:28.12,EN,,0,0,0,,the anonymous things generated by lambda directly into the table.\nDialogue: 0,0:42:28.66,0:42:31.76,EN,,0,0,0,,There's also another thing that your question raises,\nDialogue: 0,0:42:32.35,0:42:34.06,EN,,0,0,0,,is the possibility that maybe\nDialogue: 0,0:42:34.83,0:42:37.92,EN,,0,0,0,,what I would like somehow is to store in this data object\nDialogue: 0,0:42:37.95,0:42:39.48,EN,,0,0,0,,not the symbol P-O-L-A-R but\nDialogue: 0,0:42:39.93,0:42:42.35,EN,,0,0,0,,maybe actually all the operations themselves.\nDialogue: 0,0:42:43.90,0:42:45.63,EN,,0,0,0,,And that's another way to organize the system,\nDialogue: 0,0:42:45.66,0:42:46.60,EN,,0,0,0,,called message passing.\nDialogue: 0,0:42:48.65,0:42:49.92,EN,,0,0,0,,So there are a lot of ways you can do it.\nDialogue: 0,0:42:54.64,0:42:58.04,EN,,0,0,0,,AUDIENCE: Therefore if Martha and George had used the same\nDialogue: 0,0:42:58.04,0:43:01.23,EN,,0,0,0,,procedure names, it would be OK because it wouldn't look\nDialogue: 0,0:43:01.23,0:43:02.56,EN,,0,0,0,,it wouldn't look into it\nDialogue: 0,0:43:02.56,0:43:04.68,EN,,0,0,0,,PROFESSOR: That's right.That's right.\nDialogue: 0,0:43:04.80,0:43:07.85,EN,,0,0,0,,See, they wouldn't even have to name their procedures at all.\nDialogue: 0,0:43:08.04,0:43:09.36,EN,,0,0,0,,What George and Martha could writ --,\nDialogue: 0,0:43:09.50,0:43:10.62,EN,,0,0,0,,what George could have written\nDialogue: 0,0:43:10.83,0:43:15.28,EN,,0,0,0,,instead of saying put in the table under rectangular- and real-part,\nDialogue: 0,0:43:16.22,0:43:17.98,EN,,0,0,0,,the procedure real-part rectangular,\nDialogue: 0,0:43:18.03,0:43:21.15,EN,,0,0,0,,George could have written put under rectangular real-part,\nDialogue: 0,0:43:21.24,0:43:23.69,EN,,0,0,0,,lambda of z, such and such, such and such,\nDialogue: 0,0:43:24.54,0:43:26.84,EN,,0,0,0,,And the system would work completely the same.\nDialogue: 0,0:43:27.33,0:43:29.24,EN,,0,0,0,,AUDIENCE: My question is, Martha could put\nDialogue: 0,0:43:29.84,0:43:33.60,EN,,0,0,0,,could have put key1 key2 real-part,\nDialogue: 0,0:43:33.95,0:43:37.64,EN,,0,0,0,,and George could have put key1 key2 real-part,\nDialogue: 0,0:43:37.96,0:43:39.60,EN,,0,0,0,,and as long as they defined them differently\nDialogue: 0,0:43:39.80,0:43:41.26,EN,,0,0,0,,they wouldn't have had any conflicts, right?\nDialogue: 0,0:43:41.29,0:43:43.80,EN,,0,0,0,,PROFESSOR: Yes, that would all be OK except for the fact\nDialogue: 0,0:43:44.97,0:43:47.13,EN,,0,0,0,,that if you imagine George and Martha typing at the same\nDialogue: 0,0:43:47.13,0:43:49.20,EN,,0,0,0,,console with the same meanings for all their names,\nDialogue: 0,0:43:49.82,0:43:51.23,EN,,0,0,0,,and it would get confused by real-part,\nDialogue: 0,0:43:51.24,0:43:52.80,EN,,0,0,0,,but there are ways to arrange that, too.\nDialogue: 0,0:43:52.80,0:43:54.80,EN,,0,0,0,,And in principle you're absolutely right.\nDialogue: 0,0:43:54.98,0:43:56.29,EN,,0,0,0,,If their names didn't conflict--\nDialogue: 0,0:43:56.29,0:43:58.19,EN,,0,0,0,,it's the objects that go in the table, not the names.\nDialogue: 0,0:44:08.20,0:44:09.05,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:44:12.91,0:44:20.48,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:44:20.96,0:44:23.29,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:44:23.45,0:44:25.29,EN,,0,0,0,,By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:44:57.42,0:45:05.07,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:45:05.47,0:45:09.24,EN,,0,0,0,,Generic Operators\nDialogue: 0,0:45:12.88,0:45:16.88,EN,,0,0,0,,RPOFESSOR: All right, well we just looked at data-directed programming\nDialogue: 0,0:45:17.68,0:45:22.84,EN,,0,0,0,,as a way of implementing a system that does arithmetic on complex numbers.\nDialogue: 0,0:45:27.60,0:45:32.48,EN,,0,0,0,,So I had these operations in it called plus C and minus C,\nDialogue: 0,0:45:32.88,0:45:37.24,EN,,0,0,0,,and multiply, and divide,and maybe some others.\nDialogue: 0,0:45:38.23,0:45:45.72,EN,,0,0,0,,And that sat on top of-- and this is the key point--\nDialogue: 0,0:45:45.74,0:45:49.60,EN,,0,0,0,,sat on top of two different representations.\nDialogue: 0,0:45:50.34,0:45:55.44,EN,,0,0,0,,A rectangular package here, and a polar package.\nDialogue: 0,0:45:58.14,0:45:59.15,EN,,0,0,0,,And maybe some more.\nDialogue: 0,0:45:59.15,0:46:02.80,EN,,0,0,0,,And we saw that the whole idea is that maybe some more are now very easy to add.\nDialogue: 0,0:46:04.67,0:46:08.35,EN,,0,0,0,,But that doesn't really show the power of this methodology.\nDialogue: 0,0:46:08.90,0:46:10.15,EN,,0,0,0,,Shows you what's going on.\nDialogue: 0,0:46:10.15,0:46:12.33,EN,,0,0,0,,The power of the methodology only becomes apparent\nDialogue: 0,0:46:12.94,0:46:15.79,EN,,0,0,0,,when you start embedding this in some more complex system.\nDialogue: 0,0:46:16.17,0:46:17.74,EN,,0,0,0,,So let... What I'm going to do now\nDialogue: 0,0:46:17.87,0:46:20.01,EN,,0,0,0,,is embed this in some more complex system.\nDialogue: 0,0:46:20.25,0:46:25.28,EN,,0,0,0,,Let's assume that what we really have is a general kind of arithmetic system.\nDialogue: 0,0:46:25.28,0:46:27.24,EN,,0,0,0,,So called generic arithmetic system.\nDialogue: 0,0:46:27.24,0:46:28.54,EN,,0,0,0,,And at the top level here,\nDialogue: 0,0:46:30.76,0:46:35.92,EN,,0,0,0,,somebody can say add twothings, or subtract two things,\nDialogue: 0,0:46:37.45,0:46:41.05,EN,,0,0,0,,or multiply two  things, or divide two things.\nDialogue: 0,0:46:44.14,0:46:46.52,EN,,0,0,0,,And underneath that there's an abstraction barrier.\nDialogue: 0,0:46:47.93,0:46:49.15,EN,,0,0,0,,And underneath this barrier,\nDialogue: 0,0:46:49.50,0:46:52.48,EN,,0,0,0,,is, say, a complex arithmetic package.\nDialogue: 0,0:46:53.02,0:46:54.96,EN,,0,0,0,,And you can say, add two complex numbers.\nDialogue: 0,0:46:55.04,0:46:58.83,EN,,0,0,0,,Or you might also have--remember we did a rational number package\nDialogue: 0,0:46:58.88,0:46:59.93,EN,,0,0,0,,you might have that sitting there.\nDialogue: 0,0:47:00.19,0:47:01.72,EN,,0,0,0,,And there might be a rational thing.\nDialogue: 0,0:47:04.76,0:47:06.22,EN,,0,0,0,,And the rational number package,\nDialogue: 0,0:47:07.16,0:47:14.75,EN,,0,0,0,,well, has the things we implemented. Plus rat, and times rat, and so on.\nDialogue: 0,0:47:15.39,0:47:17.01,EN,,0,0,0,,Or you might have ordinary Lisp numbers.\nDialogue: 0,0:47:17.01,0:47:18.99,EN,,0,0,0,,You might say add three and four.\nDialogue: 0,0:47:19.42,0:47:20.94,EN,,0,0,0,,So we might have ordinary numbers,\nDialogue: 0,0:47:28.28,0:47:34.67,EN,,0,0,0,,in which case we have the Lisp supplied plus, and minus, and times, and slash.\nDialogue: 0,0:47:36.67,0:47:39.12,EN,,0,0,0,,OK, so we might imagine this complex number system\nDialogue: 0,0:47:39.44,0:47:44.44,EN,,0,0,0,,sitting in a more complicated generic operator structure at the next level up.\nDialogue: 0,0:47:47.73,0:47:48.73,EN,,0,0,0,,Well how can we make that?\nDialogue: 0,0:47:49.05,0:47:52.32,EN,,0,0,0,,We already have the idea, we're just going to do it again.\nDialogue: 0,0:47:52.78,0:47:54.72,EN,,0,0,0,,We've implemented a rational number package.\nDialogue: 0,0:47:54.72,0:47:56.89,EN,,0,0,0,,Let's look at how it has to be changed.\nDialogue: 0,0:48:01.48,0:48:03.40,EN,,0,0,0,,In fact, at this level it doesn't have to be changed at all.\nDialogue: 0,0:48:03.73,0:48:05.88,EN,,0,0,0,,This is exactly the code that we wrote last time.\nDialogue: 0,0:48:07.18,0:48:08.97,EN,,0,0,0,,To add two rational numbers,\nDialogue: 0,0:48:09.85,0:48:10.91,EN,,0,0,0,,remember there was this formula.\nDialogue: 0,0:48:11.14,0:48:13.37,EN,,0,0,0,,You make a rational number whose numerator--\nDialogue: 0,0:48:13.98,0:48:17.56,EN,,0,0,0,,is the numerator of the first times the denominator of the second\nDialogue: 0,0:48:17.93,0:48:21.52,EN,,0,0,0,,plus the denominator of the first times the numerator of the second.\nDialogue: 0,0:48:21.52,0:48:23.79,EN,,0,0,0,,And who's denominator is the product of the denominators.\nDialogue: 0,0:48:25.76,0:48:29.07,EN,,0,0,0,,And minus rat, and star rat, and slash rat.\nDialogue: 0,0:48:30.36,0:48:35.12,EN,,0,0,0,,And this is exactly the rational number package that we made before.\nDialogue: 0,0:48:36.31,0:48:38.89,EN,,0,0,0,,We're ignoring the GCD problem,but let's not worry about that.\nDialogue: 0,0:48:39.08,0:48:42.59,EN,,0,0,0,,How do we install... As implementers of this rational number package,\nDialogue: 0,0:48:42.80,0:48:45.10,EN,,0,0,0,,how do we install it in the generic arithmetic system?\nDialogue: 0,0:48:45.57,0:48:46.22,EN,,0,0,0,,Well that's easy.\nDialogue: 0,0:48:47.29,0:48:51.56,EN,,0,0,0,,Go off... There's only one thing we have to do differently.\nDialogue: 0,0:48:51.84,0:48:55.71,EN,,0,0,0,,Whereas previously we said that to make a rational number\nDialogue: 0,0:48:56.27,0:48:59.98,EN,,0,0,0,,you built a pair of the numerator and denominator,\nDialogue: 0,0:49:00.96,0:49:03.20,EN,,0,0,0,,here we'll not only build the pair, but we'll sign it.\nDialogue: 0,0:49:03.30,0:49:04.56,EN,,0,0,0,,We'll attach the type rational.\nDialogue: 0,0:49:06.36,0:49:08.09,EN,,0,0,0,,That's the only thing we have to do different,\nDialogue: 0,0:49:08.56,0:49:10.09,EN,,0,0,0,,make it a typed data object.\nDialogue: 0,0:49:12.38,0:49:14.08,EN,,0,0,0,,And now we'll stick our operations in the table.\nDialogue: 0,0:49:14.36,0:49:18.20,EN,,0,0,0,,We'll put under the symbol rational and the operation add\nDialogue: 0,0:49:18.92,0:49:20.25,EN,,0,0,0,,our procedure -- +rat.\nDialogue: 0,0:49:21.82,0:49:23.24,EN,,0,0,0,,And, again, note this is a symbol.\nDialogue: 0,0:49:23.74,0:49:23.93,EN,,0,0,0,,Right?\nDialogue: 0,0:49:24.03,0:49:25.29,EN,,0,0,0,,Quote, and quote,\nDialogue: 0,0:49:25.31,0:49:28.01,EN,,0,0,0,,but the actual thing we're putting in the table is the procedure.\nDialogue: 0,0:49:29.82,0:49:31.77,EN,,0,0,0,,And for how to subtract,\nDialogue: 0,0:49:31.79,0:49:36.81,EN,,0,0,0,,well you subtract rationals with minus rat.\nDialogue: 0,0:49:38.27,0:49:40.24,EN,,0,0,0,,And multiply, and divide.\nDialogue: 0,0:49:41.09,0:49:43.64,EN,,0,0,0,,And that is exactly and precisely what we have to do\nDialogue: 0,0:49:44.14,0:49:46.97,EN,,0,0,0,,to fit inside this generic arithmetic system.\nDialogue: 0,0:49:48.51,0:49:49.88,EN,,0,0,0,,Well how does the whole thing work?\nDialogue: 0,0:49:51.56,0:49:58.40,EN,,0,0,0,,See, what we want to do is have some generic operators.\nDialogue: 0,0:49:59.34,0:50:02.80,EN,,0,0,0,,Right? Have add and sub and mul and div be generic operators.\nDialogue: 0,0:50:03.99,0:50:17.36,EN,,0,0,0,,So we're going to define add and say, to add x and y,\nDialogue: 0,0:50:18.62,0:50:22.12,EN,,0,0,0,,that will be operate--\nDialogue: 0,0:50:26.08,0:50:27.49,EN,,0,0,0,,we were going to call it operate-2.\nDialogue: 0,0:50:27.49,0:50:30.78,EN,,0,0,0,,This is our operator procedure, but set up for two arguments\nDialogue: 0,0:50:31.60,0:50:35.84,EN,,0,0,0,,using add on x and y.\nDialogue: 0,0:50:37.60,0:50:39.76,EN,,0,0,0,,And so this is the analog to operate.\nDialogue: 0,0:50:40.42,0:50:41.68,EN,,0,0,0,,Let's look at the code for a second.\nDialogue: 0,0:50:41.68,0:50:42.93,EN,,0,0,0,,It's almost like operate.\nDialogue: 0,0:50:45.79,0:50:52.49,EN,,0,0,0,,Right? To operate with some operator on an argument1 and an argument2\nDialogue: 0,0:50:55.04,0:50:56.65,EN,,0,0,0,,well the first thing we're going to do is check\nDialogue: 0,0:50:56.83,0:51:00.73,EN,,0,0,0,,and see if the two arguments have the same type.\nDialogue: 0,0:51:01.90,0:51:02.96,EN,,0,0,0,,So we'll say,\nDialogue: 0,0:51:02.99,0:51:07.77,EN,,0,0,0,,is the type of the first argument the same as the type of the second argument?\nDialogue: 0,0:51:10.35,0:51:13.36,EN,,0,0,0,,And if they're not, if they're not\nDialogue: 0,0:51:13.58,0:51:15.63,EN,,0,0,0,,we'll go off and complain, and say, that's an error.\nDialogue: 0,0:51:15.67,0:51:16.67,EN,,0,0,0,,We don't know how to do that.\nDialogue: 0,0:51:19.14,0:51:20.49,EN,,0,0,0,,If they do have the same type,\nDialogue: 0,0:51:20.51,0:51:22.08,EN,,0,0,0,,we'll do exactly what we did before.\nDialogue: 0,0:51:22.08,0:51:26.46,EN,,0,0,0,,We'll go look and filed under the type of the argument--\nDialogue: 0,0:51:26.76,0:51:29.61,EN,,0,0,0,,arg 1 and arg 2 have the same type, so it doesn't matter.\nDialogue: 0,0:51:30.42,0:51:32.59,EN,,0,0,0,,So we'll look in the table, find the procedure.\nDialogue: 0,0:51:33.64,0:51:35.87,EN,,0,0,0,,If there is a procedure there,\nDialogue: 0,0:51:37.53,0:51:41.74,EN,,0,0,0,,then we'll apply it to the contents of the arg1 and the contents of arg2.\nDialogue: 0,0:51:43.03,0:51:44.76,EN,,0,0,0,,And otherwise we'll say, error.\nDialogue: 0,0:51:44.76,0:51:45.72,EN,,0,0,0,,Undefined operator.\nDialogue: 0,0:51:46.89,0:51:48.16,EN,,0,0,0,,And so there's operate-2.\nDialogue: 0,0:51:51.72,0:51:54.03,EN,,0,0,0,,And that's all we have to do.\nDialogue: 0,0:51:55.16,0:51:57.45,EN,,0,0,0,,We just built the complex number package before.\nDialogue: 0,0:51:57.64,0:52:01.00,EN,,0,0,0,,How do we embed that complex number package in this generic system?\nDialogue: 0,0:52:02.14,0:52:02.91,EN,,0,0,0,,Almost the same.\nDialogue: 0,0:52:06.41,0:52:08.59,EN,,0,0,0,,We make a procedure called make-complex\nDialogue: 0,0:52:09.95,0:52:12.81,EN,,0,0,0,,that takes whatever George and Martha hand to us\nDialogue: 0,0:52:13.64,0:52:15.00,EN,,0,0,0,,and add the type complex.\nDialogue: 0,0:52:18.17,0:52:23.87,EN,,0,0,0,,And then we say, to add complex numbers, plus complex,\nDialogue: 0,0:52:25.84,0:52:28.78,EN,,0,0,0,,we use our internal procedure, plus c,\nDialogue: 0,0:52:30.78,0:52:32.24,EN,,0,0,0,,and attach a type,\nDialogue: 0,0:52:32.24,0:52:33.42,EN,,0,0,0,,make that a complex number.\nDialogue: 0,0:52:37.68,0:52:42.52,EN,,0,0,0,,So our original package had names plus c and minus c\nDialogue: 0,0:52:42.68,0:52:44.75,EN,,0,0,0,,that we're using to communicate with George and Martha.\nDialogue: 0,0:52:45.25,0:52:47.39,EN,,0,0,0,,And then to communicate with the outside world,\nDialogue: 0,0:52:47.40,0:52:53.04,EN,,0,0,0,,we have a thing called plus-complex and minus-complex.\nDialogue: 0,0:52:55.92,0:52:56.53,EN,,0,0,0,,And so on.\nDialogue: 0,0:52:56.53,0:52:59.98,EN,,0,0,0,,And the only difference is that these return values that are typed\nDialogue: 0,0:53:01.12,0:53:02.41,EN,,0,0,0,,So they can be looked at up here.\nDialogue: 0,0:53:02.85,0:53:05.02,EN,,0,0,0,,And these are internal operations.\nDialogue: 0,0:53:09.25,0:53:10.68,EN,,0,0,0,,Let's go look at that slide again.\nDialogue: 0,0:53:10.68,0:53:13.04,EN,,0,0,0,,There's one more thing we do.\nDialogue: 0,0:53:13.74,0:53:15.61,EN,,0,0,0,,After defining plus-complex,\nDialogue: 0,0:53:15.68,0:53:20.52,EN,,0,0,0,,we put under the type complex and the symbol add,\nDialogue: 0,0:53:21.31,0:53:22.75,EN,,0,0,0,,that procedure plus complex.\nDialogue: 0,0:53:23.20,0:53:26.75,EN,,0,0,0,,And then similarly for subtracting complex numbers,\nDialogue: 0,0:53:27.13,0:53:29.13,EN,,0,0,0,,and multiplying them, and dividing them.\nDialogue: 0,0:53:31.70,0:53:33.48,EN,,0,0,0,,OK, how do we install ordinary numbers?\nDialogue: 0,0:53:35.25,0:53:36.12,EN,,0,0,0,,Exactly the same way.\nDialogue: 0,0:53:38.16,0:53:41.36,EN,,0,0,0,,Come off and say, well we'll make a thing called make-number\nDialogue: 0,0:53:44.34,0:53:48.11,EN,,0,0,0,,Make-number takes a number and attaches a type,\nDialogue: 0,0:53:48.14,0:53:49.29,EN,,0,0,0,,which is the symbol number.\nDialogue: 0,0:53:50.26,0:53:52.11,EN,,0,0,0,,We build a procedure called plus-number,\nDialogue: 0,0:53:52.92,0:53:58.75,EN,,0,0,0,,which is simply, add the two things using the ordinary addition,\nDialogue: 0,0:53:58.92,0:54:00.78,EN,,0,0,0,,because in this case we're talking about ordinary numbers,\nDialogue: 0,0:54:01.31,0:54:03.10,EN,,0,0,0,,and attach a type to it and make that a number.\nDialogue: 0,0:54:04.51,0:54:08.09,EN,,0,0,0,,And then we put into the table under the symbol number\nDialogue: 0,0:54:08.59,0:54:11.00,EN,,0,0,0,,and the operation add, this procedure plus-number,\nDialogue: 0,0:54:12.30,0:54:16.16,EN,,0,0,0,,and then the same thing for subtracting, and multiplying, and dividing.\nDialogue: 0,0:54:22.67,0:54:26.06,EN,,0,0,0,,Let's look at an example, just to make it clear.\nDialogue: 0,0:54:26.06,0:54:28.75,EN,,0,0,0,,Suppose, for instance,\nDialogue: 0,0:54:32.28,0:54:34.15,EN,,0,0,0,,I'm going to perform the operation.\nDialogue: 0,0:54:34.15,0:54:38.22,EN,,0,0,0,,So I sit up here and I'm going to perform the operation,\nDialogue: 0,0:54:38.22,0:54:40.46,EN,,0,0,0,,which looks like multiplying two complex numbers.\nDialogue: 0,0:54:40.93,0:54:48.64,EN,,0,0,0,,So I would multiply, say, 3 plus 4i and 2 plus 6i.\nDialogue: 0,0:54:50.17,0:54:52.60,EN,,0,0,0,,And that's something that I might want to take hand that to mul.\nDialogue: 0,0:54:52.84,0:54:55.76,EN,,0,0,0,,I'll write mul as my generic operator here.\nDialogue: 0,0:54:57.17,0:54:57.98,EN,,0,0,0,,How's that going to work?\nDialogue: 0,0:54:58.28,0:55:04.60,EN,,0,0,0,,Well 3 plus 4i, say, sits in the system at this level\nDialogue: 0,0:55:04.83,0:55:06.11,EN,,0,0,0,,as something that looks like this.\nDialogue: 0,0:55:06.25,0:55:07.52,EN,,0,0,0,,Let's say it was one of George's.\nDialogue: 0,0:55:08.28,0:55:14.97,EN,,0,0,0,,So it would have a 3 and a 4.\nDialogue: 0,0:55:18.49,0:55:20.97,EN,,0,0,0,,And attached to that would be George's type,\nDialogue: 0,0:55:24.33,0:55:28.32,EN,,0,0,0,,which says rectangular, it came from George.\nDialogue: 0,0:55:29.51,0:55:30.57,EN,,0,0,0,,And attached to that--\nDialogue: 0,0:55:31.23,0:55:35.79,EN,,0,0,0,,and this itself would be the data view from the next level up\nDialogue: 0,0:55:36.19,0:55:36.78,EN,,0,0,0,,which it is--\nDialogue: 0,0:55:37.93,0:55:39.96,EN,,0,0,0,,so that itself would be a type-data object\nDialogue: 0,0:55:40.60,0:55:41.80,EN,,0,0,0,,which would say complex.\nDialogue: 0,0:55:44.82,0:55:47.31,EN,,0,0,0,,So that's what this object would look like\nDialogue: 0,0:55:48.64,0:55:50.24,EN,,0,0,0,,up here at the very highest level,\nDialogue: 0,0:55:50.68,0:55:53.56,EN,,0,0,0,,where the really super-generic operations are looking at it.\nDialogue: 0,0:55:55.56,0:55:58.72,EN,,0,0,0,,Now what happens, mul eventually's going to come along\nDialogue: 0,0:55:58.84,0:56:00.40,EN,,0,0,0,,and say, oh,what's it's type?\nDialogue: 0,0:56:00.48,0:56:01.48,EN,,0,0,0,,It's type is complex.\nDialogue: 0,0:56:04.27,0:56:06.46,EN,,0,0,0,,Go through to operate-2 and say,\nDialogue: 0,0:56:06.46,0:56:09.72,EN,,0,0,0,,oh, what I want to do is apply what's in the table,\nDialogue: 0,0:56:09.72,0:56:13.04,EN,,0,0,0,,which is going to be the procedure star complex,\nDialogue: 0,0:56:15.08,0:56:17.76,EN,,0,0,0,,on this thing with the type stripped off.\nDialogue: 0,0:56:17.95,0:56:19.28,EN,,0,0,0,,So it's going to strip off the type,\nDialogue: 0,0:56:19.93,0:56:24.24,EN,,0,0,0,,take that much, and send that down into the complex world.\nDialogue: 0,0:56:26.70,0:56:28.73,EN,,0,0,0,,The complex world looks at its operations and says,\nDialogue: 0,0:56:28.76,0:56:30.56,EN,,0,0,0,,oh, I have to apply star c.\nDialogue: 0,0:56:31.28,0:56:32.14,EN,,0,0,0,,Star c might say,\nDialogue: 0,0:56:32.22,0:56:37.20,EN,,0,0,0,,at some point I want to look at the magnitude of this object that it's in, that it's got.\nDialogue: 0,0:56:39.42,0:56:40.16,EN,,0,0,0,,And they'll say, oh, it's\nDialogue: 0,0:56:40.16,0:56:41.71,EN,,0,0,0,,rectangular, it's one of George's.\nDialogue: 0,0:56:41.87,0:56:44.41,EN,,0,0,0,,So it'll then strip off the next version of type,\nDialogue: 0,0:56:46.91,0:56:49.80,EN,,0,0,0,,and hand that down to George to take the magnitude of.\nDialogue: 0,0:56:52.16,0:56:53.13,EN,,0,0,0,,So you see what's going on\nDialogue: 0,0:56:53.44,0:56:56.99,EN,,0,0,0,,is that there are these chains of types.\nDialogue: 0,0:56:59.32,0:57:01.50,EN,,0,0,0,,And the length of the chain is sort of the number of levels\nDialogue: 0,0:57:01.53,0:57:03.13,EN,,0,0,0,,that you're going to be going up in this table.\nDialogue: 0,0:57:05.09,0:57:05.96,EN,,0,0,0,,And what a type tells you,\nDialogue: 0,0:57:05.96,0:57:10.84,EN,,0,0,0,,every time you have a vertical barrier in this table,\nDialogue: 0,0:57:11.05,0:57:14.06,EN,,0,0,0,,where there's some ambiguity about where you should go down to the next level,\nDialogue: 0,0:57:14.41,0:57:15.85,EN,,0,0,0,,the type is telling you where to go.\nDialogue: 0,0:57:17.44,0:57:18.83,EN,,0,0,0,,And then everybody at the bottom,\nDialogue: 0,0:57:18.97,0:57:20.67,EN,,0,0,0,,as they construct data and filter it up,\nDialogue: 0,0:57:21.12,0:57:22.81,EN,,0,0,0,,they stick their type back on.\nDialogue: 0,0:57:25.35,0:57:30.75,EN,,0,0,0,,So that's the general structure of the system.\nDialogue: 0,0:57:33.41,0:57:33.77,EN,,0,0,0,,OK.\nDialogue: 0,0:57:34.82,0:57:35.68,EN,,0,0,0,,Now that we've got this,\nDialogue: 0,0:57:37.56,0:57:39.44,EN,,0,0,0,,let's go and make this thing even more complex.\nDialogue: 0,0:57:41.89,0:57:46.54,EN,,0,0,0,,Let's talk about adding to the system not only these kinds of numbers\nDialogue: 0,0:57:46.60,0:57:51.15,EN,,0,0,0,,numbers, but it's also meaningful to start talking about adding polynomials.\nDialogue: 0,0:57:51.51,0:57:52.97,EN,,0,0,0,,Might do arithmetic on polynomials.\nDialogue: 0,0:57:53.36,0:58:03.71,EN,,0,0,0,,Like we could have x to the fifteenth plus 2x to the seventh plus 5.\nDialogue: 0,0:58:04.48,0:58:05.84,EN,,0,0,0,,That might be some polynomial.\nDialogue: 0,0:58:06.38,0:58:07.93,EN,,0,0,0,,And if we have two such gadgets\nDialogue: 0,0:58:07.93,0:58:09.48,EN,,0,0,0,,we can add them or multiply them.\nDialogue: 0,0:58:10.53,0:58:11.79,EN,,0,0,0,,Let's not worry about dividing them.\nDialogue: 0,0:58:12.14,0:58:14.67,EN,,0,0,0,,Just add them, multiply them, then we'll subtract them.\nDialogue: 0,0:58:15.55,0:58:17.16,EN,,0,0,0,,Auhhh...What do we have to do? Well\nDialogue: 0,0:58:18.52,0:58:20.76,EN,,0,0,0,,let's think about how we might represent a polynomial.\nDialogue: 0,0:58:21.83,0:58:23.55,EN,,0,0,0,,It's going to be some typed data object.\nDialogue: 0,0:58:24.73,0:58:27.55,EN,,0,0,0,,So let's say a polynomial to this system\nDialogue: 0,0:58:28.54,0:58:31.68,EN,,0,0,0,,might look like a thing that starts with the type polynomial.\nDialogue: 0,0:58:32.00,0:58:34.55,EN,,0,0,0,,And then maybe it says the next thing is what variable its in.\nDialogue: 0,0:58:34.55,0:58:37.69,EN,,0,0,0,,So I might say I'm a polynomial in the variable x.\nDialogue: 0,0:58:38.96,0:58:41.39,EN,,0,0,0,,And then it'll have some information about what the terms are.\nDialogue: 0,0:58:42.25,0:58:44.16,EN,,0,0,0,,And there're just tons of ways to do this,\nDialogue: 0,0:58:44.25,0:58:47.63,EN,,0,0,0,,but one way is to say we're going to have a thing called a term-list.\nDialogue: 0,0:58:51.52,0:58:52.24,EN,,0,0,0,,And a term-list--\nDialogue: 0,0:58:53.70,0:58:55.61,EN,,0,0,0,,well, in our case we'll use something that looks like this.\nDialogue: 0,0:58:56.36,0:58:59.68,EN,,0,0,0,,We'll make it a bunch of pairs which have an order in a coefficient\nDialogue: 0,0:58:59.69,0:59:05.80,EN,,0,0,0,,So this polynomial would be represented by this term-list.\nDialogue: 0,0:59:09.42,0:59:10.68,EN,,0,0,0,,And what that means is that\nDialogue: 0,0:59:11.48,0:59:19.71,EN,,0,0,0,,this polynomial starts off with a term of order 15 and coefficient 1.\nDialogue: 0,0:59:23.82,0:59:27.50,EN,,0,0,0,,And the next thing in it is a term of order 7 and coefficient 2,\nDialogue: 0,0:59:27.53,0:59:30.49,EN,,0,0,0,,a term of order 0, which is constant in coefficient 5\nDialogue: 0,0:59:31.45,0:59:34.16,EN,,0,0,0,,And there are lots and lots of ways,\nDialogue: 0,0:59:34.25,0:59:35.96,EN,,0,0,0,,and lots and lots of trade-offs\nDialogue: 0,0:59:36.01,0:59:39.10,EN,,0,0,0,,when you really think about making algebraic manipulation packages\nDialogue: 0,0:59:39.44,0:59:41.73,EN,,0,0,0,,that exactly how you should represent these things.\nDialogue: 0,0:59:42.01,0:59:43.68,EN,,0,0,0,,But this is a fairly standard one.\nDialogue: 0,0:59:44.18,0:59:45.55,EN,,0,0,0,,It's useful in a lot of contexts.\nDialogue: 0,0:59:47.77,0:59:50.99,EN,,0,0,0,,OK, well how do we implement our polynomial arithmetic?\nDialogue: 0,0:59:53.47,0:59:54.96,EN,,0,0,0,,Let's start out.\nDialogue: 0,0:59:57.95,1:00:00.28,EN,,0,0,0,,What we'll do to make a polynomial--\nDialogue: 0,1:00:00.76,1:00:04.12,EN,,0,0,0,,we'll first have a way to make polynomials.\nDialogue: 0,1:00:05.69,1:00:10.28,EN,,0,0,0,,We're going to make a polynomial out of variable like x and term-list.\nDialogue: 0,1:00:11.24,1:00:14.09,EN,,0,0,0,,And all that does is we'll package them together someway.\nDialogue: 0,1:00:14.30,1:00:19.40,EN,,0,0,0,,We'll put the variable together with the term list using cons\nDialogue: 0,1:00:19.82,1:00:21.74,EN,,0,0,0,,and then attached to that the type polynomial.\nDialogue: 0,1:00:26.27,1:00:27.77,EN,,0,0,0,,OK, how do we add two polynomials?\nDialogue: 0,1:00:29.28,1:00:31.85,EN,,0,0,0,,To add a polynomial, p1 and p2,\nDialogue: 0,1:00:32.68,1:00:35.18,EN,,0,0,0,,and then just for simplicity let's say we\nDialogue: 0,1:00:35.37,1:00:37.15,EN,,0,0,0,,we will only add things in the same variable.\nDialogue: 0,1:00:37.38,1:00:39.28,EN,,0,0,0,,So if they have the same variable,\nDialogue: 0,1:00:39.69,1:00:42.57,EN,,0,0,0,,and same variable here is going to be some selector we write,\nDialogue: 0,1:00:42.96,1:00:44.38,EN,,0,0,0,,whose details we don't care about.\nDialogue: 0,1:00:45.15,1:00:47.04,EN,,0,0,0,,If the two polynomials have the same variable,\nDialogue: 0,1:00:48.03,1:00:48.81,EN,,0,0,0,,then we'll do something.\nDialogue: 0,1:00:48.81,1:00:51.26,EN,,0,0,0,,If they don't have the same variable, we'll give an error,\nDialogue: 0,1:00:52.35,1:00:54.01,EN,,0,0,0,,polynomials not in the same variable.\nDialogue: 0,1:00:55.48,1:00:57.37,EN,,0,0,0,,And if they do have the same variable,\nDialogue: 0,1:00:57.60,1:00:59.18,EN,,0,0,0,,what we'll do is we'll make a polynomial\nDialogue: 0,1:00:59.80,1:01:01.85,EN,,0,0,0,,whose variable is whatever that variable is,\nDialogue: 0,1:01:03.15,1:01:06.56,EN,,0,0,0,,and whose term-list is something we'll call sum-terms.\nDialogue: 0,1:01:07.48,1:01:09.80,EN,,0,0,0,,Plus terms will add the two term lists.\nDialogue: 0,1:01:10.17,1:01:12.01,EN,,0,0,0,,So we'll add the two term lists to the polynomial.\nDialogue: 0,1:01:13.50,1:01:14.51,EN,,0,0,0,,That'll give us a term-list.\nDialogue: 0,1:01:15.00,1:01:20.01,EN,,0,0,0,,We'll add on, we'll say it's a polynomial in the variable with that term-list.\nDialogue: 0,1:01:20.68,1:01:21.79,EN,,0,0,0,,That's plus poly.\nDialogue: 0,1:01:22.55,1:01:27.00,EN,,0,0,0,,And then we're going to put in our table under the type polynomial\nDialogue: 0,1:01:28.24,1:01:30.14,EN,,0,0,0,,add them using plus poly.\nDialogue: 0,1:01:30.52,1:01:31.75,EN,,0,0,0,,And of course we really haven't done much.\nDialogue: 0,1:01:31.75,1:01:35.31,EN,,0,0,0,,What we've really done is pushed all the work onto this thing, +terms\nDialogue: 0,1:01:35.79,1:01:37.02,EN,,0,0,0,,which is supposed to add term-lists.\nDialogue: 0,1:01:37.74,1:01:39.16,EN,,0,0,0,,Let's look at that.\nDialogue: 0,1:01:39.18,1:01:48.03,EN,,0,0,0,,Here's an overview of how we might add two term-lists.\nDialogue: 0,1:01:48.90,1:01:51.74,EN,,0,0,0,,So L1 and L2 were going to be two term-lists.\nDialogue: 0,1:01:52.00,1:01:54.81,EN,,0,0,0,,And a term-list is a bunch of pairs, coefficient in order.\nDialogue: 0,1:01:55.70,1:01:56.95,EN,,0,0,0,,And it's a big case analysis.\nDialogue: 0,1:01:59.86,1:02:04.14,EN,,0,0,0,,And the first thing we'll check for and see if there are any terms\nDialogue: 0,1:02:05.39,1:02:07.55,EN,,0,0,0,,We're going to recursively work down these term-lists\nDialogue: 0,1:02:08.16,1:02:11.74,EN,,0,0,0,,so eventually we'll get to a place where either L1 or L2 might be empty.\nDialogue: 0,1:02:12.27,1:02:14.35,EN,,0,0,0,,And if either one is empty,\nDialogue: 0,1:02:14.52,1:02:15.85,EN,,0,0,0,,our answer will be the other one.\nDialogue: 0,1:02:15.85,1:02:19.55,EN,,0,0,0,,So if L1 is empty we'll return L2,\nDialogue: 0,1:02:19.63,1:02:21.71,EN,,0,0,0,,and if L2 is empty we'll return L1.\nDialogue: 0,1:02:23.26,1:02:25.76,EN,,0,0,0,,Otherwise there are sort of three interesting cases.\nDialogue: 0,1:02:27.22,1:02:27.98,EN,,0,0,0,,What we're going to do is\nDialogue: 0,1:02:29.08,1:02:31.05,EN,,0,0,0,,grab the first term in each of those lists,\nDialogue: 0,1:02:33.50,1:02:36.04,EN,,0,0,0,,Right? Called t1 and t2.\nDialogue: 0,1:02:37.66,1:02:39.05,EN,,0,0,0,,And we're going to look at three cases,\nDialogue: 0,1:02:39.60,1:02:45.68,EN,,0,0,0,,depending on whether the order of t1 is greater than the order of t2,\nDialogue: 0,1:02:47.23,1:02:50.59,EN,,0,0,0,,or less than t2, or the same.\nDialogue: 0,1:02:53.28,1:02:54.91,EN,,0,0,0,,Those are the three cases we're going to look at.\nDialogue: 0,1:02:54.91,1:02:55.84,EN,,0,0,0,,Let's look at this case.\nDialogue: 0,1:02:58.64,1:03:01.31,EN,,0,0,0,,If the order of t1 is greater than the order of t2,\nDialogue: 0,1:03:03.40,1:03:04.70,EN,,0,0,0,,then what that means is that\nDialogue: 0,1:03:06.06,1:03:09.96,EN,,0,0,0,,then what that means is that our answer is going to start with this term of the order of t1.\nDialogue: 0,1:03:11.56,1:03:13.80,EN,,0,0,0,,Because it won't combine with any lower order terms.\nDialogue: 0,1:03:14.17,1:03:16.19,EN,,0,0,0,,So what we do is add the lower order terms.\nDialogue: 0,1:03:16.76,1:03:18.25,EN,,0,0,0,,We recursively add\nDialogue: 0,1:03:19.71,1:03:25.07,EN,,0,0,0,,together all the terms in the rest of the term-list in L1 and L2.\nDialogue: 0,1:03:27.13,1:03:29.32,EN,,0,0,0,,That's going to be the lower order terms of the answer.\nDialogue: 0,1:03:30.12,1:03:32.48,EN,,0,0,0,,And then we're going to adjoin to that the highest order term.\nDialogue: 0,1:03:33.18,1:03:35.45,EN,,0,0,0,,And I'm using here a whole bunch of procedures I haven't defined\nDialogue: 0,1:03:35.47,1:03:37.55,EN,,0,0,0,,like a adjoin-term, and rest-terms,\nDialogue: 0,1:03:38.48,1:03:40.17,EN,,0,0,0,,and selectors that get order.\nDialogue: 0,1:03:41.15,1:03:42.78,EN,,0,0,0,,But you can imagine what those are.\nDialogue: 0,1:03:44.44,1:03:48.76,EN,,0,0,0,,Right? So if the first term-list has a higher order than the second\nDialogue: 0,1:03:48.78,1:03:51.08,EN,,0,0,0,,we recursively add all the lower terms\nDialogue: 0,1:03:51.28,1:03:53.42,EN,,0,0,0,,and then stick on that last term.\nDialogue: 0,1:03:55.54,1:03:56.75,EN,,0,0,0,,The other case, the same way.\nDialogue: 0,1:03:56.89,1:04:00.28,EN,,0,0,0,,If the first term has a smaller order,\nDialogue: 0,1:04:00.54,1:04:08.36,EN,,0,0,0,,well then we add we add the first term-list and the rest of the terms in the second one\nDialogue: 0,1:04:08.62,1:04:12.65,EN,,0,0,0,,and adjoin on this highest order term.\nDialogue: 0,1:04:14.57,1:04:15.96,EN,,0,0,0,,So so far nothing's much happened,\nDialogue: 0,1:04:15.96,1:04:19.40,EN,,0,0,0,,we've just sort of pushed this thing off into adding lower order terms.\nDialogue: 0,1:04:19.47,1:04:21.96,EN,,0,0,0,,The last case where you actually get to a coefficients\nDialogue: 0,1:04:22.57,1:04:25.18,EN,,0,0,0,,that you have to add, this will be the case where the orders are equal.\nDialogue: 0,1:04:27.24,1:04:30.99,EN,,0,0,0,,What we do is, well again recursively add the lower order terms.\nDialogue: 0,1:04:31.00,1:04:32.83,EN,,0,0,0,,But now we have to really combine something.\nDialogue: 0,1:04:33.46,1:04:36.35,EN,,0,0,0,,What we do is we make a term\nDialogue: 0,1:04:37.31,1:04:39.93,EN,,0,0,0,,whose order is the order of the term we're looking at.\nDialogue: 0,1:04:40.82,1:04:42.72,EN,,0,0,0,,By now t1 and t2 have the same order.\nDialogue: 0,1:04:44.32,1:04:44.99,EN,,0,0,0,,That's its order.\nDialogue: 0,1:04:45.09,1:04:52.33,EN,,0,0,0,,And its coefficient is gotten by adding the coefficient of t1 and the coefficient of t2.\nDialogue: 0,1:04:55.79,1:04:59.64,EN,,0,0,0,,There's... This is a big recursive working down of terms,\nDialogue: 0,1:04:59.68,1:05:03.61,EN,,0,0,0,,but really there's only one interesting symbol in this procedure,\nDialogue: 0,1:05:04.25,1:05:05.69,EN,,0,0,0,,only one interesting idea.\nDialogue: 0,1:05:05.90,1:05:08.50,EN,,0,0,0,,The interesting idea is this add.\nDialogue: 0,1:05:12.39,1:05:14.80,EN,,0,0,0,,And the reason that's interesting is because\nDialogue: 0,1:05:15.42,1:05:17.37,EN,,0,0,0,,something completely wonderful just happened.\nDialogue: 0,1:05:18.22,1:05:21.37,EN,,0,0,0,,We reduced adding polynomials,\nDialogue: 0,1:05:22.56,1:05:26.46,EN,,0,0,0,,not to sort of plus, but to the generic add.\nDialogue: 0,1:05:28.82,1:05:32.28,EN,,0,0,0,,In other words, by implementing it that way,\nDialogue: 0,1:05:32.89,1:05:34.68,EN,,0,0,0,,not only do we have our system\nDialogue: 0,1:05:35.92,1:05:41.66,EN,,0,0,0,,where we can have rational numbers, or complex numbers, or ordinary numbers,\nDialogue: 0,1:05:41.85,1:05:43.82,EN,,0,0,0,,we've just added on polynomials.\nDialogue: 0,1:05:48.52,1:05:51.13,EN,,0,0,0,,But the coefficients of the polynomials\nDialogue: 0,1:05:51.24,1:05:52.86,EN,,0,0,0,,can be anything that the system can add.\nDialogue: 0,1:05:53.59,1:05:56.73,EN,,0,0,0,,So these could be polynomials whose coefficient\nDialogue: 0,1:05:57.20,1:06:01.20,EN,,0,0,0,,are rational numbers or complex numbers,\nDialogue: 0,1:06:02.76,1:06:06.99,EN,,0,0,0,,which in turn could be either rectangular, or polar,\nDialogue: 0,1:06:09.12,1:06:11.39,EN,,0,0,0,,or ordinary numbers.\nDialogue: 0,1:06:18.97,1:06:21.21,EN,,0,0,0,,Rignt? So what I mean precisely is\nDialogue: 0,1:06:22.06,1:06:24.35,EN,,0,0,0,,our system right now automatically\nDialogue: 0,1:06:26.60,1:06:31.50,EN,,0,0,0,,can handle things like adding together polynomials that have this form\nDialogue: 0,1:06:31.53,1:06:39.69,EN,,0,0,0,,2/3 of x squared plus 5/17 x plus 11/4.\nDialogue: 0,1:06:40.94,1:06:43.48,EN,,0,0,0,,Or automatically handle polynomials that look like\nDialogue: 0,1:06:43.82,1:06:52.57,EN,,0,0,0,,3 plus 2i times x to the fifth plus 4 plus 7i, or something.\nDialogue: 0,1:06:53.88,1:06:56.21,EN,,0,0,0,,Right? You can automatically handle those things.\nDialogue: 0,1:06:56.21,1:06:57.07,EN,,0,0,0,,Why is that?\nDialogue: 0,1:06:57.82,1:07:01.50,EN,,0,0,0,,That's merely because, or profoundly because\nDialogue: 0,1:07:02.17,1:07:05.93,EN,,0,0,0,,we reduced adding polynomials to adding their coefficients.\nDialogue: 0,1:07:06.79,1:07:10.22,EN,,0,0,0,,And adding coefficients was done by the generic add operator\nDialogue: 0,1:07:11.08,1:07:12.94,EN,,0,0,0,,which said, I don't care what your types are\nDialogue: 0,1:07:12.96,1:07:14.08,EN,,0,0,0,,as long as I know how to add you.\nDialogue: 0,1:07:15.23,1:07:18.86,EN,,0,0,0,,So automatically for free we get the ability to handle that.\nDialogue: 0,1:07:20.65,1:07:22.04,EN,,0,0,0,,What's even better than that,\nDialogue: 0,1:07:24.51,1:07:26.52,EN,,0,0,0,,one of the things we did\nDialogue: 0,1:07:27.20,1:07:30.52,EN,,0,0,0,,we put into the table that the way you add polynomials\nDialogue: 0,1:07:31.28,1:07:32.52,EN,,0,0,0,,is using plus poly.\nDialogue: 0,1:07:34.66,1:07:38.65,EN,,0,0,0,,That means that polynomials themselves are things that can be added.\nDialogue: 0,1:07:39.42,1:07:42.11,EN,,0,0,0,,So for instance let me write one here.\nDialogue: 0,1:07:43.18,1:07:46.19,EN,,0,0,0,,Here is... Here's a polynomial.\nDialogue: 0,1:07:50.56,1:07:52.41,EN,,0,0,0,,So this gadget here I'm writing up,\nDialogue: 0,1:07:54.12,1:07:58.46,EN,,0,0,0,,this is a polynomial in y\nDialogue: 0,1:08:01.07,1:08:04.69,EN,,0,0,0,,whose coefficients are polynomials in x.\nDialogue: 0,1:08:08.61,1:08:11.12,EN,,0,0,0,,So you see, simply by saying,\nDialogue: 0,1:08:11.76,1:08:14.06,EN,,0,0,0,,polynomials are themselves things that can be added,\nDialogue: 0,1:08:14.41,1:08:17.90,EN,,0,0,0,,we can go off and say, well not only can we deal with rationals,\nDialogue: 0,1:08:18.27,1:08:20.33,EN,,0,0,0,,or complex, or ordinary numbers,\nDialogue: 0,1:08:20.35,1:08:21.77,EN,,0,0,0,,but we can deal with polynomials\nDialogue: 0,1:08:22.09,1:08:25.39,EN,,0,0,0,,whose coefficients are rationals, or complex, or ordinary numbers,\nDialogue: 0,1:08:25.50,1:08:27.52,EN,,0,0,0,,or polynomials\nDialogue: 0,1:08:29.15,1:08:30.96,EN,,0,0,0,,whose coefficients are rationals,\nDialogue: 0,1:08:31.69,1:08:36.76,EN,,0,0,0,,or complex, rectangular, polar, or ordinary numbers,\nDialogue: 0,1:08:36.94,1:08:41.13,EN,,0,0,0,,or ordinary numbers, or polynomials whose coefficients are rationals,\nDialogue: 0,1:08:41.80,1:08:43.32,EN,,0,0,0,,complex, or ordinary numbers.\nDialogue: 0,1:08:43.67,1:08:45.21,EN,,0,0,0,,And so on, and so on, and so on.\nDialogue: 0,1:08:45.95,1:08:47.55,EN,,0,0,0,,So this is sort of an infinite\nDialogue: 0,1:08:48.49,1:08:52.88,EN,,0,0,0,,or maybe a recursive tower of types that we've built up.\nDialogue: 0,1:08:53.88,1:08:57.12,EN,,0,0,0,,And it's all exactly from that one little symbol, A-D-D.\nDialogue: 0,1:08:57.61,1:09:00.49,EN,,0,0,0,,Writing \"add\" instead of \"plus\" in the polynomial thing.\nDialogue: 0,1:09:02.27,1:09:03.77,EN,,0,0,0,,Slightly different way to think about it\nDialogue: 0,1:09:03.95,1:09:07.74,EN,,0,0,0,,is that polynomials are a constructor for types.\nDialogue: 0,1:09:08.74,1:09:11.20,EN,,0,0,0,,Namely you give it a type, like integer,\nDialogue: 0,1:09:11.48,1:09:15.74,EN,,0,0,0,,and it returns for you polynomials in x whose coefficients are integers.\nDialogue: 0,1:09:16.27,1:09:17.72,EN,,0,0,0,,And the important thing about\nDialogue: 0,1:09:18.65,1:09:20.73,EN,,0,0,0,,is that is that the operations on polynomials\nDialogue: 0,1:09:21.28,1:09:23.37,EN,,0,0,0,,reduce to the operations on the coefficients.\nDialogue: 0,1:09:23.39,1:09:24.96,EN,,0,0,0,,And there are a lot of things like that.\nDialogue: 0,1:09:25.84,1:09:27.92,EN,,0,0,0,,So for example, let's go back and rational numbers.\nDialogue: 0,1:09:28.87,1:09:32.65,EN,,0,0,0,,We thought about rational numbers as an integer over an integer\nDialogue: 0,1:09:32.67,1:09:35.66,EN,,0,0,0,,but there's the general notion of a rational object.\nDialogue: 0,1:09:36.24,1:09:42.03,EN,,0,0,0,,Like we might think about 3x plus 7 over x squared plus 1.\nDialogue: 0,1:09:43.07,1:09:48.86,EN,,0,0,0,,That's general rational object whose numerator and denominator are polynomials.\nDialogue: 0,1:09:50.31,1:09:52.41,EN,,0,0,0,,And to add two of them we use the same formula,\nDialogue: 0,1:09:52.44,1:09:55.40,EN,,0,0,0,,numerator times denominator plus denominator times numerator\nDialogue: 0,1:09:55.72,1:09:56.99,EN,,0,0,0,,over product of denominators.\nDialogue: 0,1:09:57.29,1:09:59.37,EN,,0,0,0,,How could we install that in our system?\nDialogue: 0,1:09:59.39,1:10:02.97,EN,,0,0,0,,Well here's our original rational number arithmetic package.\nDialogue: 0,1:10:04.25,1:10:08.24,EN,,0,0,0,,And all we have to do in order to make the entire system\nDialogue: 0,1:10:08.28,1:10:11.58,EN,,0,0,0,,continue working with general rational objects,\nDialogue: 0,1:10:11.85,1:10:16.44,EN,,0,0,0,,is replace these particular pluses and stars by the generic operator.\nDialogue: 0,1:10:16.48,1:10:19.18,EN,,0,0,0,,So if we simply change that procedure to this one,\nDialogue: 0,1:10:19.71,1:10:22.04,EN,,0,0,0,,here we've changed plus and star to add a mul,\nDialogue: 0,1:10:22.88,1:10:24.48,EN,,0,0,0,,those are absolutely the only change,\nDialogue: 0,1:10:24.84,1:10:26.03,EN,,0,0,0,,then suddenly\nDialogue: 0,1:10:27.52,1:10:31.40,EN,,0,0,0,,our entire system can start talking about objects that look like this.\nDialogue: 0,1:10:33.72,1:10:38.27,EN,,0,0,0,,So for example, here is a rational object\nDialogue: 0,1:10:39.18,1:10:44.86,EN,,0,0,0,,whose numerator is a polynomial in x whose coefficients are rational numbers.\nDialogue: 0,1:10:47.02,1:10:49.56,EN,,0,0,0,,Or here is a rational object\nDialogue: 0,1:10:51.10,1:10:54.43,EN,,0,0,0,,whose numerator is polynomials in x\nDialogue: 0,1:10:55.15,1:10:58.19,EN,,0,0,0,,whose coefficients are rational objects\nDialogue: 0,1:10:59.77,1:11:01.53,EN,,0,0,0,,constructed out of complex numbers.\nDialogue: 0,1:11:03.39,1:11:04.85,EN,,0,0,0,,And then there are a lot of other things like that.\nDialogue: 0,1:11:04.85,1:11:08.68,EN,,0,0,0,,See, whenever you have a thing where the operations reduce to operations on the pieces,\nDialogue: 0,1:11:08.89,1:11:10.00,EN,,0,0,0,,another example would be\nDialogue: 0,1:11:10.28,1:11:11.42,EN,,0,0,0,,two by two matrices.\nDialogue: 0,1:11:12.31,1:11:15.44,EN,,0,0,0,,I have the idea, there might be a matrix here\nDialogue: 0,1:11:16.43,1:11:18.33,EN,,0,0,0,,of general things that I don't care about.\nDialogue: 0,1:11:18.72,1:11:20.14,EN,,0,0,0,,But if I add two of them,\nDialogue: 0,1:11:22.33,1:11:25.18,EN,,0,0,0,,the answer over here is gotten by\nDialogue: 0,1:11:25.18,1:11:28.14,EN,,0,0,0,,adding this one and that one,however they like to add.\nDialogue: 0,1:11:29.03,1:11:31.11,EN,,0,0,0,,So I can implement that the same way.\nDialogue: 0,1:11:31.11,1:11:31.71,EN,,0,0,0,,And if I do that,\nDialogue: 0,1:11:31.96,1:11:34.60,EN,,0,0,0,,then again suddenly my system can start handling things like this.\nDialogue: 0,1:11:35.29,1:11:39.18,EN,,0,0,0,,So here's a matrix whose elements happen to be--\nDialogue: 0,1:11:39.46,1:11:42.16,EN,,0,0,0,,we'll say this element here is a rational object\nDialogue: 0,1:11:43.10,1:11:45.15,EN,,0,0,0,,whose numerator and denominators are polynomials.\nDialogue: 0,1:11:47.02,1:11:49.56,EN,,0,0,0,,Right? And all that comes for free.\nDialogue: 0,1:11:51.28,1:11:53.82,EN,,0,0,0,,Right? What's really going on here?\nDialogue: 0,1:11:53.92,1:11:56.17,EN,,0,0,0,,What's really going on is\nDialogue: 0,1:11:57.68,1:12:02.44,EN,,0,0,0,,getting rid of who's sitting there poking his nose into who everybody's business is.\nDialogue: 0,1:12:03.12,1:12:06.19,EN,,0,0,0,,We built a system that has decentralized control.\nDialogue: 0,1:12:14.78,1:12:18.34,EN,,0,0,0,,So when you come into and no one's poking around saying,\nDialogue: 0,1:12:18.35,1:12:22.30,EN,,0,0,0,,gee, are you in the official list of people who can be added?\nDialogue: 0,1:12:22.44,1:12:26.22,EN,,0,0,0,,Rather you say, well go off and add yourself how your parts like to be added.\nDialogue: 0,1:12:27.81,1:12:31.03,EN,,0,0,0,,And the result of that is you can get this very, very, very\nDialogue: 0,1:12:31.03,1:12:33.87,EN,,0,0,0,,complex hierarchy where a lot of things just get done and\nDialogue: 0,1:12:33.87,1:12:35.55,EN,,0,0,0,,rooted to the right place automatically.\nDialogue: 0,1:12:37.00,1:12:37.79,EN,,0,0,0,,Let's stop for questions.\nDialogue: 0,1:12:40.38,1:12:42.32,EN,,0,0,0,,AUDIENCE: You say you get this for free.\nDialogue: 0,1:12:42.35,1:12:45.82,EN,,0,0,0,,Um..... One thing that strikes me is that now you've lost\nDialogue: 0,1:12:46.48,1:12:50.91,EN,,0,0,0,,kind of the cleanness of the break between what's on top and what's underneath.\nDialogue: 0,1:12:50.91,1:12:52.77,EN,,0,0,0,,In other words, now you're defining some of the\nDialogue: 0,1:12:52.77,1:12:56.08,EN,,0,0,0,,lower-level procedures in terms of things above their own line.\nDialogue: 0,1:12:56.61,1:12:59.45,EN,,0,0,0,,Isn't that dangerous?\nDialogue: 0,1:13:00.35,1:13:04.49,EN,,0,0,0,,Or, if nothing more, a little less structured?\nDialogue: 0,1:13:05.44,1:13:05.95,EN,,0,0,0,,PROFESSOR: No, I--\nDialogue: 0,1:13:06.41,1:13:07.77,EN,,0,0,0,,the question is whether that's less structured.\nDialogue: 0,1:13:07.77,1:13:08.69,EN,,0,0,0,,Depends on what you mean by structure.\nDialogue: 0,1:13:08.69,1:13:10.17,EN,,0,0,0,,All this is doing is recursion.\nDialogue: 0,1:13:11.05,1:13:18.80,EN,,0,0,0,,See, it's saying that the way you add these guys is to use that.\nDialogue: 0,1:13:19.15,1:13:21.37,EN,,0,0,0,,And that's not less structured, it's just a recursive structure.\nDialogue: 0,1:13:22.70,1:13:24.99,EN,,0,0,0,,So I don't think it's particularly any less clean.\nDialogue: 0,1:13:24.99,1:13:28.16,EN,,0,0,0,,AUDIENCE: Now when you want to change the multiplier or the add operator\nDialogue: 0,1:13:29.34,1:13:31.38,EN,,0,0,0,,suddenly you've got tremendous consequences\nDialogue: 0,1:13:31.38,1:13:34.27,EN,,0,0,0,,underneath that you're not even sure the extent of.\nDialogue: 0,1:13:34.48,1:13:36.44,EN,,0,0,0,,PROFESSOR: That's right, but it depends what you mean.\nDialogue: 0,1:13:37.08,1:13:38.47,EN,,0,0,0,,See, this goes both ways.\nDialogue: 0,1:13:39.10,1:13:43.24,EN,,0,0,0,,Um....What would be a good example?\nDialogue: 0,1:13:44.69,1:13:47.50,EN,,0,0,0,,I ignored greatest common divisor, for instance.\nDialogue: 0,1:13:47.77,1:13:50.08,EN,,0,0,0,,I ignored that problem just to keep the example simple.\nDialogue: 0,1:13:50.28,1:13:56.92,EN,,0,0,0,,But if I suddenly decided that plus rat here\nDialogue: 0,1:13:57.82,1:14:01.69,EN,,0,0,0,,should do a GCD computation and install that,\nDialogue: 0,1:14:03.34,1:14:07.87,EN,,0,0,0,,then that immediately becomes available to all of these, to that guy, and that guy,\nDialogue: 0,1:14:08.03,1:14:10.08,EN,,0,0,0,,and that guy, and all the way down.\nDialogue: 0,1:14:11.56,1:14:13.89,EN,,0,0,0,,So it depends what you mean by the coherence of your system.\nDialogue: 0,1:14:13.89,1:14:17.03,EN,,0,0,0,,It's certainly true that you might want to have a special\nDialogue: 0,1:14:17.03,1:14:19.56,EN,,0,0,0,,different one that didn't filter down through the coefficients\nDialogue: 0,1:14:19.61,1:14:22.97,EN,,0,0,0,,but the nice thing about this particular example is that mostly you do.\nDialogue: 0,1:14:25.44,1:14:27.63,EN,,0,0,0,,AUDIENCE: Isn't that the problem, I think, that you're\nDialogue: 0,1:14:27.63,1:14:32.95,EN,,0,0,0,,getting to tied in with the fact that the structuring, the\nDialogue: 0,1:14:32.95,1:14:36.33,EN,,0,0,0,,recursiveness of that structuring there is actually\nDialogue: 0,1:14:36.33,1:14:40.34,EN,,0,0,0,,in execution as opposed to just definition of the actual\nDialogue: 0,1:14:40.34,1:14:41.16,EN,,0,0,0,,types themselves?\nDialogue: 0,1:14:44.68,1:14:46.12,EN,,0,0,0,,PROFESSOR: I think I understand the question.\nDialogue: 0,1:14:46.12,1:14:47.80,EN,,0,0,0,,The point is that these types evolve\nDialogue: 0,1:14:47.82,1:14:50.40,EN,,0,0,0,,and get more and more complex as the thing's actually running.\nDialogue: 0,1:14:50.40,1:14:50.73,EN,,0,0,0,,Is that what--\nDialogue: 0,1:14:50.73,1:14:50.99,EN,,0,0,0,,AUDIENCE: Yap.\nDialogue: 0,1:14:50.99,1:14:51.79,EN,,0,0,0,,As it's running.\nDialogue: 0,1:14:52.09,1:14:54.18,EN,,0,0,0,,AUDIENCE: As opposed to the basic definitions.\nDialogue: 0,1:14:54.18,1:14:54.83,EN,,0,0,0,,PROFESSOR: Right. There's...\nDialogue: 0,1:14:54.83,1:14:56.70,EN,,0,0,0,,The type structure is sort of recursive.\nDialogue: 0,1:14:57.21,1:15:00.22,EN,,0,0,0,,It's not that you can make this finite list of the\nDialogue: 0,1:15:01.58,1:15:04.85,EN,,0,0,0,,actual things they might look like before the system runs.\nDialogue: 0,1:15:04.85,1:15:05.79,EN,,0,0,0,,It's something that evolves.\nDialogue: 0,1:15:06.78,1:15:08.64,EN,,0,0,0,,So if you want to specify that system,\nDialogue: 0,1:15:08.67,1:15:10.96,EN,,0,0,0,,you have to do in some other way than by this finite list.\nDialogue: 0,1:15:11.00,1:15:13.18,EN,,0,0,0,,You have to do it by a recursive structure.\nDialogue: 0,1:15:13.67,1:15:17.90,EN,,0,0,0,,AUDIENCE: Because the basic structure of the types is pretty clean and simple.\nDialogue: 0,1:15:17.90,1:15:18.19,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:15:20.40,1:15:20.75,EN,,0,0,0,,Yes?\nDialogue: 0,1:15:21.46,1:15:22.87,EN,,0,0,0,,AUDIENCE: I have a question.\nDialogue: 0,1:15:22.87,1:15:25.68,EN,,0,0,0,,I understand once you have your data structure set up,\nDialogue: 0,1:15:25.71,1:15:28.73,EN,,0,0,0,,how it pulls off complex and passes that down,\nDialogue: 0,1:15:28.73,1:15:30.64,EN,,0,0,0,,and then pulls off rect, passes that down.\nDialogue: 0,1:15:30.64,1:15:33.95,EN,,0,0,0,,But if you're just a user and you don't know anything about rect or polar or whatever,\nDialogue: 0,1:15:34.25,1:15:36.04,EN,,0,0,0,,how do you initially set up that data structure\nDialogue: 0,1:15:36.09,1:15:38.08,EN,,0,0,0,,so that everything goes to the right spot?\nDialogue: 0,1:15:38.09,1:15:41.00,EN,,0,0,0,,If I just have the equation over there on the left\nDialogue: 0,1:15:41.02,1:15:42.50,EN,,0,0,0,,And I just want to add, multiply complex numbers--\nDialogue: 0,1:15:42.50,1:15:43.64,EN,,0,0,0,,PROFESSOR: Well that's the wonderful thing.\nDialogue: 0,1:15:43.64,1:15:45.26,EN,,0,0,0,,If you're just a user you say \"mul.\"\nDialogue: 0,1:15:47.73,1:15:49.95,EN,,0,0,0,,AUDIENCE: And it figures out that I mean complex numbers?\nDialogue: 0,1:15:49.96,1:15:51.23,EN,,0,0,0,,Or how do I tell it that I want--\nDialogue: 0,1:15:51.26,1:15:53.05,EN,,0,0,0,,PROFESSOR: Well you're going to have in your hands complex numbers.\nDialogue: 0,1:15:53.05,1:15:56.30,EN,,0,0,0,,See what you would have at some level, as a real user,\nDialogue: 0,1:15:56.32,1:15:58.14,EN,,0,0,0,,is a constructor for complex numbers.\nDialogue: 0,1:15:58.37,1:15:59.55,EN,,0,0,0,,AUDIENCE: So then I have to make complex numbers?\nDialogue: 0,1:15:59.56,1:16:00.35,EN,,0,0,0,,PROFESSOR: So you have to make them.\nDialogue: 0,1:16:00.35,1:16:04.01,EN,,0,0,0,,What you would probably have as a user is some little thing in the reader loop,\nDialogue: 0,1:16:04.65,1:16:07.56,EN,,0,0,0,,which would give you some plausible way\nDialogue: 0,1:16:07.56,1:16:08.86,EN,,0,0,0,,to type in a complex number,\nDialogue: 0,1:16:09.31,1:16:11.00,EN,,0,0,0,,in however whatever format you like.\nDialogue: 0,1:16:11.59,1:16:14.36,EN,,0,0,0,,Or it might be that you're never typing them in.\nDialogue: 0,1:16:14.36,1:16:16.17,EN,,0,0,0,,Someone's just handing you a complex number.\nDialogue: 0,1:16:16.78,1:16:19.82,EN,,0,0,0,,AUDIENCE: OK, so if I had a complex number that had a polynomial in it,\nDialogue: 0,1:16:19.82,1:16:21.96,EN,,0,0,0,,I'd have to make my polynomial and then make my complex number.\nDialogue: 0,1:16:21.96,1:16:23.96,EN,,0,0,0,,PROFESSOR: Right if you wanted it constructed from scratch.\nDialogue: 0,1:16:24.28,1:16:25.71,EN,,0,0,0,,At some point you construct them from scratch.\nDialogue: 0,1:16:25.71,1:16:27.05,EN,,0,0,0,,But what you don't have to know of that\nDialogue: 0,1:16:27.28,1:16:30.32,EN,,0,0,0,,is when you have the object you can just say \"mul.\" And it'll multiply.\nDialogue: 0,1:16:32.78,1:16:32.99,EN,,0,0,0,,Yeah?\nDialogue: 0,1:16:33.27,1:16:35.76,EN,,0,0,0,,AUDIENCE: I think the question that was being posed here is,\nDialogue: 0,1:16:36.45,1:16:40.01,EN,,0,0,0,,say if I want to change my presentation of complexes,\nDialogue: 0,1:16:40.03,1:16:41.44,EN,,0,0,0,,or some operation of complex,\nDialogue: 0,1:16:41.52,1:16:47.10,EN,,0,0,0,,how much real code I will have to gets around with,\nDialogue: 0,1:16:47.15,1:16:51.26,EN,,0,0,0,,or change to change it in one specific operation?\nDialogue: 0,1:16:52.27,1:16:53.49,EN,,0,0,0,,PROFESSOR: [UNINTELLIGIBLE] what you have to change.\nDialogue: 0,1:16:53.49,1:16:54.99,EN,,0,0,0,,And the point is that you only have to change\nDialogue: 0,1:16:55.39,1:16:56.07,EN,,0,0,0,,what you're changing.\nDialogue: 0,1:16:56.07,1:17:00.04,EN,,0,0,0,,See if Martha decides that she would rather--\nDialogue: 0,1:17:00.32,1:17:01.23,EN,,0,0,0,,let's see something silly--\nDialogue: 0,1:17:01.44,1:17:02.91,EN,,0,0,0,,like change the order in the pair.\nDialogue: 0,1:17:04.04,1:17:08.72,EN,,0,0,0,,Like angle and magnitude in the other order,\nDialogue: 0,1:17:09.39,1:17:10.80,EN,,0,0,0,,she just makes that change locally.\nDialogue: 0,1:17:10.97,1:17:13.29,EN,,0,0,0,,And the whole thing will propagate through the system in the right way.\nDialogue: 0,1:17:14.79,1:17:18.76,EN,,0,0,0,,Or if suddenly you said, gee, I have another representation for rationals.\nDialogue: 0,1:17:19.70,1:17:23.90,EN,,0,0,0,,And I'm going to stick it here, by filing those operations in the table.\nDialogue: 0,1:17:24.82,1:17:27.22,EN,,0,0,0,,Then suddenly all of these polynomials whose coefficients\nDialogue: 0,1:17:27.22,1:17:29.10,EN,,0,0,0,,are coefficients of coefficients, or whatever,\nDialogue: 0,1:17:29.24,1:17:32.40,EN,,0,0,0,,also can automatically have available that representation.\nDialogue: 0,1:17:32.70,1:17:34.67,EN,,0,0,0,,That's the power of this particular one.\nDialogue: 0,1:17:36.11,1:17:38.70,EN,,0,0,0,,AUDIENCE: I'm not sure if I can even pose an intelligent sounding question.\nDialogue: 0,1:17:38.70,1:17:42.38,EN,,0,0,0,,But somehow this whole thing went really nicely\nDialogue: 0,1:17:42.54,1:17:45.88,EN,,0,0,0,,to this beautiful finish where all the things seemed to fall into place.\nDialogue: 0,1:17:46.72,1:17:48.67,EN,,0,0,0,,And sort of seemed a little contrived.\nDialogue: 0,1:17:50.93,1:17:52.52,EN,,0,0,0,,That's all for the sake, I'm sure, of teaching.\nDialogue: 0,1:17:52.56,1:17:54.65,EN,,0,0,0,,I doubt that the guys who first did this--\nDialogue: 0,1:17:55.10,1:17:55.85,EN,,0,0,0,,and I could be wrong--\nDialogue: 0,1:17:56.60,1:17:59.72,EN,,0,0,0,,figured it all out so that when they just all put it all together,\nDialogue: 0,1:17:59.77,1:18:03.93,EN,,0,0,0,,you could all of the sudden, blam, do any kind of arithmetic on any kind of object.\nDialogue: 0,1:18:04.86,1:18:07.20,EN,,0,0,0,,It seems like maybe they had to play with it for a while\nDialogue: 0,1:18:07.93,1:18:10.62,EN,,0,0,0,,and had to bash it and rework it.\nDialogue: 0,1:18:11.80,1:18:14.12,EN,,0,0,0,,And it seems like that's the kind of problem we're really\nDialogue: 0,1:18:14.12,1:18:16.94,EN,,0,0,0,,faced with we start trying to design a really complex system\nDialogue: 0,1:18:17.31,1:18:20.35,EN,,0,0,0,,is having lots of different kinds of parts and not even knowing\nDialogue: 0,1:18:21.08,1:18:24.62,EN,,0,0,0,,what kinds of operations we're going to want to do on those parts.\nDialogue: 0,1:18:24.62,1:18:26.54,EN,,0,0,0,,How to organize the operations in this nice way\nDialogue: 0,1:18:26.56,1:18:29.63,EN,,0,0,0,,so that no matter what you do, when you start putting them together\nDialogue: 0,1:18:29.63,1:18:31.39,EN,,0,0,0,,everything starts falling out for free.\nDialogue: 0,1:18:31.70,1:18:34.34,EN,,0,0,0,,PROFESSOR: OK, well that's certainly a very intelligent question... Um\nDialogue: 0,1:18:35.10,1:18:39.52,EN,,0,0,0,,Um....One part is this is a very good methodology\nDialogue: 0,1:18:39.87,1:18:43.88,EN,,0,0,0,,that people have discovered a lot coming from symbolic algebra.\nDialogue: 0,1:18:44.59,1:18:45.90,EN,,0,0,0,,Because there are a lot of complications.\nDialogue: 0,1:18:47.59,1:18:50.71,EN,,0,0,0,,To allow you to implement these things before you decide\nDialogue: 0,1:18:50.71,1:18:52.89,EN,,0,0,0,,what you want all the operations to be, and all of that.\nDialogue: 0,1:18:53.31,1:18:57.72,EN,,0,0,0,,So in some sense it's an answer that people have discovered by wading through this stuff.\nDialogue: 0,1:18:58.56,1:19:00.75,EN,,0,0,0,,In another sense, it is a very contrived example.\nDialogue: 0,1:19:02.16,1:19:06.24,EN,,0,0,0,,AUDIENCE: It seems like to be able to do this you do have to\nDialogue: 0,1:19:06.24,1:19:09.01,EN,,0,0,0,,wade through it for a certain amount of time before you can become good at it.\nDialogue: 0,1:19:09.01,1:19:11.88,EN,,0,0,0,,PROFESSOR: Let me show you how terribly contrived this is.\nDialogue: 0,1:19:12.22,1:19:14.13,EN,,0,0,0,,So you can write all these wonderful things.\nDialogue: 0,1:19:14.13,1:19:16.25,EN,,0,0,0,,But the system that I wrote here,\nDialogue: 0,1:19:17.02,1:19:18.96,EN,,0,0,0,,and if we had another half an hour to give this lecture\nDialogue: 0,1:19:19.31,1:19:20.46,EN,,0,0,0,,I would have given this part of it,\nDialogue: 0,1:19:20.81,1:19:23.02,EN,,0,0,0,,which says, notice that it breaks down\nDialogue: 0,1:19:23.20,1:19:29.31,EN,,0,0,0,,if I tell it to do something as foolish as add 3 plus 7/2.\nDialogue: 0,1:19:30.88,1:19:33.42,EN,,0,0,0,,Because what will happen is you'll get to operate-2,\nDialogue: 0,1:19:33.80,1:19:35.95,EN,,0,0,0,,and operate-2 will say, oh this is type number,\nDialogue: 0,1:19:36.18,1:19:37.37,EN,,0,0,0,,and that's type rational.\nDialogue: 0,1:19:37.56,1:19:38.81,EN,,0,0,0,,I don't know how to add them.\nDialogue: 0,1:19:41.53,1:19:44.30,EN,,0,0,0,,So you'd like the system at least to be able to say something like,\nDialogue: 0,1:19:45.88,1:19:47.34,EN,,0,0,0,,gee,before you do that\nDialogue: 0,1:19:48.59,1:19:50.24,EN,,0,0,0,,change that to 3/1.\nDialogue: 0,1:19:50.48,1:19:53.21,EN,,0,0,0,,Turn it into a rational number, hand that to the rational package.\nDialogue: 0,1:19:54.86,1:19:58.70,EN,,0,0,0,,That's the thing I didn't talk about in this lecture.\nDialogue: 0,1:19:58.73,1:20:00.88,EN,,0,0,0,,It's a little bit in the book,which talks about the problem\nDialogue: 0,1:20:00.88,1:20:01.95,EN,,0,0,0,,of what's called coercion.\nDialogue: 0,1:20:03.39,1:20:05.15,EN,,0,0,0,,Where you wanted--\nDialogue: 0,1:20:05.31,1:20:08.89,EN,,0,0,0,,see, having so carefully set up all of these types as distinct objects\nDialogue: 0,1:20:08.91,1:20:12.17,EN,,0,0,0,,a lot of times you want to also put in knowledge\nDialogue: 0,1:20:12.40,1:20:17.98,EN,,0,0,0,,about how to view an ordinary number as a kind of rational.\nDialogue: 0,1:20:19.11,1:20:21.29,EN,,0,0,0,,Or view an ordinary number as a kind of complex.\nDialogue: 0,1:20:21.62,1:20:25.16,EN,,0,0,0,,That's where the complexity in the system really starts happening\nDialogue: 0,1:20:25.76,1:20:28.12,EN,,0,0,0,,where you talk about, see where do I put that knowledge?\nDialogue: 0,1:20:28.42,1:20:32.19,EN,,0,0,0,,Is it rational to know that ordinary numbers might be pieces of cons of them?\nDialogue: 0,1:20:33.13,1:20:36.38,EN,,0,0,0,,Or they're terrible, terrible examples, like\nDialogue: 0,1:20:38.14,1:20:47.48,EN,,0,0,0,,if I might want to add a complex number to a rational number.\nDialogue: 0,1:20:49.87,1:20:50.76,EN,,0,0,0,,Bad example.\nDialogue: 0,1:20:50.76,1:20:51.58,EN,,0,0,0,,5/7.\nDialogue: 0,1:20:53.86,1:20:55.72,EN,,0,0,0,,Then somebody's got to know that\nDialogue: 0,1:20:56.06,1:20:58.16,EN,,0,0,0,,I have to convert these to another type,\nDialogue: 0,1:20:58.20,1:21:00.65,EN,,0,0,0,,which is complex numbers whose parts might be rationals.\nDialogue: 0,1:21:01.54,1:21:02.68,EN,,0,0,0,,And who worries about that?\nDialogue: 0,1:21:02.68,1:21:03.95,EN,,0,0,0,,Does complex worry about that?\nDialogue: 0,1:21:03.95,1:21:05.03,EN,,0,0,0,,Does rational worry about that?\nDialogue: 0,1:21:05.24,1:21:06.22,EN,,0,0,0,,Does plus worry about that?\nDialogue: 0,1:21:06.90,1:21:08.52,EN,,0,0,0,,That's where the real complexity comes in.\nDialogue: 0,1:21:08.52,1:21:11.38,EN,,0,0,0,,And that's where it's pretty well sorted out.\nDialogue: 0,1:21:11.38,1:21:14.12,EN,,0,0,0,,And a lot of, in fact, all of this message passing stuff\nDialogue: 0,1:21:14.64,1:21:16.54,EN,,0,0,0,,was motivated by problems like this.\nDialogue: 0,1:21:18.46,1:21:20.89,EN,,0,0,0,,And when you really push it, people are--\nDialogue: 0,1:21:20.91,1:21:24.76,EN,,0,0,0,,somehow the algebraic manipulation problem seems to be so complex\nDialogue: 0,1:21:25.18,1:21:27.41,EN,,0,0,0,,that the people who are always at the edge of it are exactly in\nDialogue: 0,1:21:27.41,1:21:28.05,EN,,0,0,0,,the state you said.\nDialogue: 0,1:21:28.05,1:21:29.71,EN,,0,0,0,,They're wading through this thing, mucking around,\nDialogue: 0,1:21:29.72,1:21:31.37,EN,,0,0,0,,seeing what they use, trying to distill stuff.\nDialogue: 0,1:21:34.20,1:21:37.76,EN,,0,0,0,,AUDIENCE: I just want to come back to this issue of complexity once more.\nDialogue: 0,1:21:38.41,1:21:44.55,EN,,0,0,0,,Um... It certainly seems to be true that you have a great deal of\nDialogue: 0,1:21:44.55,1:21:48.32,EN,,0,0,0,,flexibility in altering the lower level kinds of things.\nDialogue: 0,1:21:49.71,1:21:53.40,EN,,0,0,0,,But it is true that you are, in a sense,\nDialogue: 0,1:21:53.44,1:21:55.26,EN,,0,0,0,,freezing higher level operations.\nDialogue: 0,1:21:55.45,1:21:58.51,EN,,0,0,0,,Or at least if you change them you don't know where all of\nDialogue: 0,1:21:58.51,1:22:02.06,EN,,0,0,0,,the changes are going to show up, or how they are.\nDialogue: 0,1:22:02.20,1:22:04.22,EN,,0,0,0,,PROFESSOR: OK, that's an extremely good question.\nDialogue: 0,1:22:04.68,1:22:05.87,EN,,0,0,0,,What I have to do is,\nDialogue: 0,1:22:08.68,1:22:10.84,EN,,0,0,0,,if I decide there's a new general operation\nDialogue: 0,1:22:11.45,1:22:13.07,EN,,0,0,0,,called equality test,\nDialogue: 0,1:22:14.96,1:22:17.15,EN,,0,0,0,,then all of these people have to decide\nDialogue: 0,1:22:18.22,1:22:22.54,EN,,0,0,0,,whether or not they would like to have an equality test by looking in the table.\nDialogue: 0,1:22:24.65,1:22:26.84,EN,,0,0,0,,There're ways to decentralize it even more.\nDialogue: 0,1:22:27.87,1:22:30.70,EN,,0,0,0,,That's what I sort of hinted at last time, where I said\nDialogue: 0,1:22:31.08,1:22:33.26,EN,,0,0,0,,you could not only have this type as a symbol,\nDialogue: 0,1:22:33.40,1:22:38.70,EN,,0,0,0,,but you actually might store in each object the operations that it knows of that.\nDialogue: 0,1:22:40.45,1:22:43.90,EN,,0,0,0,,So you might have things like greatest common divisor,\nDialogue: 0,1:22:44.43,1:22:46.81,EN,,0,0,0,,which is a thing here which is defined only for integers,\nDialogue: 0,1:22:47.40,1:22:49.21,EN,,0,0,0,,and not in general for rational numbers.\nDialogue: 0,1:22:51.03,1:22:53.11,EN,,0,0,0,,So it might be a very, very fragmented system.\nDialogue: 0,1:22:53.11,1:22:55.66,EN,,0,0,0,,And then depending on where you want your flexibility,\nDialogue: 0,1:22:56.22,1:22:59.02,EN,,0,0,0,,You...there's a whole spectrum of places that you  can build that in.\nDialogue: 0,1:22:59.96,1:23:02.56,EN,,0,0,0,,But you're pointing at the place where this starts being weak,\nDialogue: 0,1:23:02.60,1:23:06.37,EN,,0,0,0,,that there has to be some agreement on top here about these general operations.\nDialogue: 0,1:23:06.37,1:23:07.82,EN,,0,0,0,,Or at least people have to think about them.\nDialogue: 0,1:23:08.39,1:23:10.72,EN,,0,0,0,,Or you might decide, you might have a table that's very sparse\nDialogue: 0,1:23:10.75,1:23:11.96,EN,,0,0,0,,that only has a few things in it.\nDialogue: 0,1:23:14.01,1:23:15.49,EN,,0,0,0,,But there are lot of ways to play that game.\nDialogue: 0,1:23:19.78,1:23:20.43,EN,,0,0,0,,OK, thank you.\nDialogue: 0,1:23:23.53,1:23:36.56,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:23:23.53,1:23:36.56,Declare,,0,0,0,,{\\an2\\fad(500,500)}https://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec5a.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 1338\nActive Line: 1344\nVideo Position: 9363\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:18.31,0:00:22.00,EN,,0,0,0,,PROFESSOR: Well, so far we've invented enough programming\nDialogue: 0,0:00:22.25,0:00:24.06,EN,,0,0,0,,to do some very complicated things.\nDialogue: 0,0:00:24.76,0:00:29.66,EN,,0,0,0,,And you surely learned a lot about programming at this point.\nDialogue: 0,0:00:29.66,0:00:31.48,EN,,0,0,0,,You've learned almost all the most important tricks\nDialogue: 0,0:00:31.86,0:00:35.87,EN,,0,0,0,,that usually don't get taught to people until they have had a lot of experience.\nDialogue: 0,0:00:36.41,0:00:40.08,EN,,0,0,0,,For example, data directed programming is a major trick,\nDialogue: 0,0:00:40.75,0:00:43.15,EN,,0,0,0,,and yesterday you also saw an interpreted language.\nDialogue: 0,0:00:45.02,0:00:48.46,EN,,0,0,0,,We did this all in a computer language,\nDialogue: 0,0:00:48.54,0:00:49.63,EN,,0,0,0,,at this point,\nDialogue: 0,0:00:49.88,0:00:51.95,EN,,0,0,0,,where there was no assignment statement.\nDialogue: 0,0:00:53.77,0:00:58.17,EN,,0,0,0,,And presumably, for those of you who've seen your Basic or Pascal or whatever,\nDialogue: 0,0:00:58.68,0:01:01.23,EN,,0,0,0,,that's usually considered the most important thing.\nDialogue: 0,0:01:01.79,0:01:03.82,EN,,0,0,0,,Well today, we're going to do something horrible.\nDialogue: 0,0:01:03.82,0:01:05.45,EN,,0,0,0,,We're going to add an assignment statement.\nDialogue: 0,0:01:07.21,0:01:09.14,EN,,0,0,0,,And since we can do all these wonderful things without it,\nDialogue: 0,0:01:09.14,0:01:10.17,EN,,0,0,0,,why should we add it?\nDialogue: 0,0:01:10.99,0:01:12.43,EN,,0,0,0,,An important thing to understand it\nDialogue: 0,0:01:12.46,0:01:15.71,EN,,0,0,0,,is that today we're going to first of all, have a rule,\nDialogue: 0,0:01:16.48,0:01:17.93,EN,,0,0,0,,which is going to always be obeyed,\nDialogue: 0,0:01:17.93,0:01:20.80,EN,,0,0,0,,which is the only reason we ever add a feature to our language\nDialogue: 0,0:01:21.53,0:01:23.14,EN,,0,0,0,,is because there is a good reason.\nDialogue: 0,0:01:23.93,0:01:27.28,EN,,0,0,0,,And the good reason is going to boil down to the ability,\nDialogue: 0,0:01:27.42,0:01:31.51,EN,,0,0,0,,you now get an ability to break a problem into pieces that are different sets of pieces\nDialogue: 0,0:01:31.51,0:01:33.44,EN,,0,0,0,,then you could have broken it down without that,\nDialogue: 0,0:01:34.38,0:01:36.16,EN,,0,0,0,,give you another means of decomposition.\nDialogue: 0,0:01:38.30,0:01:39.45,EN,,0,0,0,,However, let's just start.\nDialogue: 0,0:01:39.45,0:01:41.88,EN,,0,0,0,,Let me quick begin by reviewing\nDialogue: 0,0:01:41.88,0:01:47.37,EN,,0,0,0,,the kind of language that we have now.\nDialogue: 0,0:01:48.16,0:01:50.44,EN,,0,0,0,,We've been writing what's called functional programs.\nDialogue: 0,0:01:51.21,0:01:52.52,EN,,0,0,0,,And functional programs\nDialogue: 0,0:01:53.04,0:01:57.95,EN,,0,0,0,,are a kind of encoding of mathematical truths.\nDialogue: 0,0:01:58.88,0:02:00.51,EN,,0,0,0,,For example, when we look at\nDialogue: 0,0:02:00.51,0:02:04.09,EN,,0,0,0,,the factorial procedure that you see on the slide here,\nDialogue: 0,0:02:05.07,0:02:06.62,EN,,0,0,0,,it's basically two clauses.\nDialogue: 0,0:02:06.99,0:02:08.64,EN,,0,0,0,,If n is one, the result is one,\nDialogue: 0,0:02:08.64,0:02:11.20,EN,,0,0,0,,otherwise n times factorial n minus one.\nDialogue: 0,0:02:11.20,0:02:12.33,EN,,0,0,0,,That's factorial of n.\nDialogue: 0,0:02:12.89,0:02:14.27,EN,,0,0,0,,Well, that is factorial of n.\nDialogue: 0,0:02:14.83,0:02:16.87,EN,,0,0,0,,And written down in some other obscure notation\nDialogue: 0,0:02:16.87,0:02:19.32,EN,,0,0,0,,that you might have learned in calculus classes,\nDialogue: 0,0:02:20.30,0:02:22.11,EN,,0,0,0,,Ahh.. mathematical logic,\nDialogue: 0,0:02:22.11,0:02:26.36,EN,,0,0,0,,what you see there is if n equals one,\nDialogue: 0,0:02:27.13,0:02:29.90,EN,,0,0,0,,for the result of n factorial is one, otherwise,\nDialogue: 0,0:02:29.90,0:02:32.56,EN,,0,0,0,,greater than one, n factorial is n times n minus one factorial.\nDialogue: 0,0:02:32.56,0:02:33.55,EN,,0,0,0,,True statements,\nDialogue: 0,0:02:34.92,0:02:36.70,EN,,0,0,0,,that's the kind of language we've been using.\nDialogue: 0,0:02:37.00,0:02:39.23,EN,,0,0,0,,And whenever we have true statements of that sort,\nDialogue: 0,0:02:39.53,0:02:46.65,EN,,0,0,0,,there is a kind of, a way of understanding how they work\nDialogue: 0,0:02:47.40,0:02:51.12,EN,,0,0,0,,which is that such processes can be evolved by substitution.\nDialogue: 0,0:02:51.29,0:02:53.71,EN,,0,0,0,,And so we see on the second slide here,\nDialogue: 0,0:02:54.99,0:02:58.81,EN,,0,0,0,,that the way we understand the execution\nDialogue: 0,0:02:58.83,0:03:03.50,EN,,0,0,0,,implied by those statements in arranged in that order,\nDialogue: 0,0:03:04.04,0:03:07.76,EN,,0,0,0,,is that you do successive substitutions of arguments\nDialogue: 0,0:03:07.87,0:03:10.88,EN,,0,0,0,,for formal parameters in the body of a procedure.\nDialogue: 0,0:03:12.00,0:03:14.51,EN,,0,0,0,,This is basically a sequence of equalities.\nDialogue: 0,0:03:14.61,0:03:17.25,EN,,0,0,0,,Factorial four is four times factorial three.\nDialogue: 0,0:03:17.25,0:03:20.05,EN,,0,0,0,,That is four times three times factorial of two\nDialogue: 0,0:03:20.05,0:03:21.01,EN,,0,0,0,,and so on.\nDialogue: 0,0:03:21.23,0:03:23.87,EN,,0,0,0,,We're always preserving truth.\nDialogue: 0,0:03:25.23,0:03:28.84,EN,,0,0,0,,Even though we're talking about true statements,\nDialogue: 0,0:03:28.84,0:03:31.96,EN,,0,0,0,,there might be more than one organization of these true statements\nDialogue: 0,0:03:31.96,0:03:35.12,EN,,0,0,0,,to describe the computation of a particular function,\nDialogue: 0,0:03:36.32,0:03:38.42,EN,,0,0,0,,the computation of the value of a particular function.\nDialogue: 0,0:03:38.42,0:03:40.92,EN,,0,0,0,,So, for example, looking at the next one here.\nDialogue: 0,0:03:41.48,0:03:49.02,EN,,0,0,0,,Here is a way of looking at the sum of n and m.\nDialogue: 0,0:03:49.53,0:03:52.04,EN,,0,0,0,,And we did this one by a recursive process.\nDialogue: 0,0:03:52.89,0:03:58.16,EN,,0,0,0,,It's the increment of the sum of the decrement of n and m.\nDialogue: 0,0:04:00.08,0:04:05.62,EN,,0,0,0,,And, of course, there is some piece of mathematical logic here that describes that.\nDialogue: 0,0:04:06.17,0:04:10.49,EN,,0,0,0,,It's the increment of the sum of the decrement of n and m,\nDialogue: 0,0:04:11.40,0:04:12.22,EN,,0,0,0,,just like that.\nDialogue: 0,0:04:13.10,0:04:16.40,EN,,0,0,0,,So there's nothing particularly magic about that.\nDialogue: 0,0:04:16.41,0:04:20.01,EN,,0,0,0,,And, of course, if we can also look at an iterative process for the same,\nDialogue: 0,0:04:20.19,0:04:24.92,EN,,0,0,0,,a program that evolves an iterative process, for the same function.\nDialogue: 0,0:04:25.26,0:04:27.56,EN,,0,0,0,,These are two things that compute the same answer.\nDialogue: 0,0:04:30.08,0:04:34.83,EN,,0,0,0,,And we have equivalent mathematical truths that are arranged there.\nDialogue: 0,0:04:36.65,0:04:39.93,EN,,0,0,0,,And just the way you arrange those truths determine the particular process.\nDialogue: 0,0:04:40.30,0:04:43.42,EN,,0,0,0,,In the way choose and arrange them determines the process that's evolved.\nDialogue: 0,0:04:44.33,0:04:48.60,EN,,0,0,0,,So we have the flexibility of talking about both the function to be computed,\nDialogue: 0,0:04:48.60,0:04:50.19,EN,,0,0,0,,and the method by which it's computed.\nDialogue: 0,0:04:50.60,0:04:52.60,EN,,0,0,0,,So it's not clear we need more.\nDialogue: 0,0:04:53.61,0:04:55.50,EN,,0,0,0,,However, today I'm going to this awful thing.\nDialogue: 0,0:04:55.50,0:04:58.43,EN,,0,0,0,,I'm going to introduce this assignment operation.\nDialogue: 0,0:04:58.89,0:05:00.41,EN,,0,0,0,,Now, what is this?\nDialogue: 0,0:05:02.89,0:05:09.22,EN,,0,0,0,,Well, first of all, there is going to be another kind of kind of statement, if you will,\nDialogue: 0,0:05:09.22,0:05:10.84,EN,,0,0,0,,in a programming language called Set!\nDialogue: 0,0:05:12.41,0:05:15.96,EN,,0,0,0,,And SET! -- Things that do things like assignment,\nDialogue: 0,0:05:15.96,0:05:15.98,EN,,0,0,0,,\nDialogue: 0,0:05:15.98,0:05:17.85,EN,,0,0,0,,I'm going to put exclamation points after.\nDialogue: 0,0:05:18.51,0:05:20.96,EN,,0,0,0,,We'll talk about what that means in a second.\nDialogue: 0,0:05:20.96,0:05:23.01,EN,,0,0,0,,The exclamation point, again like question mark,\nDialogue: 0,0:05:23.01,0:05:25.88,EN,,0,0,0,,is an arbitrary thing we attach to the symbol which is the name,\nDialogue: 0,0:05:25.88,0:05:27.88,EN,,0,0,0,,has no significance to the system.\nDialogue: 0,0:05:28.08,0:05:30.21,EN,,0,0,0,,The only significance is to me and you\nDialogue: 0,0:05:30.40,0:05:34.41,EN,,0,0,0,,to alert you that this is an assignment of some sort.\nDialogue: 0,0:05:35.88,0:05:40.06,EN,,0,0,0,,But we're going to set a variable to a value.\nDialogue: 0,0:05:43.74,0:05:45.13,EN,,0,0,0,,And what that's going to mean\nDialogue: 0,0:05:45.13,0:05:48.28,EN,,0,0,0,,is that there is a time at which something happens.\nDialogue: 0,0:05:48.65,0:05:49.61,EN,,0,0,0,,Here's a time.\nDialogue: 0,0:05:49.86,0:05:52.14,EN,,0,0,0,,If I have time going this way,\nDialogue: 0,0:05:53.50,0:05:54.82,EN,,0,0,0,,it's a time axis.\nDialogue: 0,0:05:55.00,0:05:57.82,EN,,0,0,0,,Time progresses by walking down the page.\nDialogue: 0,0:05:58.70,0:06:00.92,EN,,0,0,0,,Then an assignment is the first thing we have\nDialogue: 0,0:06:00.92,0:06:04.30,EN,,0,0,0,,that produces the difference between a before and an after.\nDialogue: 0,0:06:06.59,0:06:08.72,EN,,0,0,0,,All the other programs that we've written,\nDialogue: 0,0:06:09.18,0:06:10.68,EN,,0,0,0,,that have no assignments in them,\nDialogue: 0,0:06:10.68,0:06:13.12,EN,,0,0,0,,the order in which they were evaluated didn't matter.\nDialogue: 0,0:06:14.70,0:06:15.96,EN,,0,0,0,,But assignment is special,\nDialogue: 0,0:06:15.96,0:06:17.69,EN,,0,0,0,,it produces a moment in time.\nDialogue: 0,0:06:17.96,0:06:24.73,EN,,0,0,0,,So there is a moment before the set occurs and after,\nDialogue: 0,0:06:27.61,0:06:32.70,EN,,0,0,0,,such that after this moment in time,\nDialogue: 0,0:06:33.60,0:06:43.76,EN,,0,0,0,,the variable has the value, value.\nDialogue: 0,0:06:49.23,0:06:51.50,EN,,0,0,0,,Independent of what value it had before,\nDialogue: 0,0:06:52.80,0:06:55.79,EN,,0,0,0,,set! changes the value of the variable.\nDialogue: 0,0:06:57.69,0:06:58.75,EN,,0,0,0,,Until this moment,\nDialogue: 0,0:06:58.75,0:07:01.50,EN,,0,0,0,,we had nothing that changed.\nDialogue: 0,0:07:03.21,0:07:04.11,EN,,0,0,0,,So, for example,\nDialogue: 0,0:07:04.84,0:07:06.23,EN,,0,0,0,,one of the things we can think of\nDialogue: 0,0:07:06.23,0:07:09.42,EN,,0,0,0,,is that the procedures we write for something like factorial\nDialogue: 0,0:07:09.64,0:07:12.75,EN,,0,0,0,,are in fact pretty much identical to the function factorial.\nDialogue: 0,0:07:13.77,0:07:16.44,EN,,0,0,0,,Factorial of four, if I write fact4,\nDialogue: 0,0:07:17.23,0:07:19.15,EN,,0,0,0,,independent of what context it's in,\nDialogue: 0,0:07:19.69,0:07:21.29,EN,,0,0,0,,and independent of how many times I write it,\nDialogue: 0,0:07:21.29,0:07:22.35,EN,,0,0,0,,I always get the same answer.\nDialogue: 0,0:07:23.29,0:07:24.12,EN,,0,0,0,,It's always 24.\nDialogue: 0,0:07:25.37,0:07:28.92,EN,,0,0,0,,It's a unique map from the argument to the answer.\nDialogue: 0,0:07:30.30,0:07:32.65,EN,,0,0,0,,And all the programs we've written so far are like that.\nDialogue: 0,0:07:33.52,0:07:36.03,EN,,0,0,0,,However, once I have assignment, that isn't true.\nDialogue: 0,0:07:36.96,0:07:38.16,EN,,0,0,0,,So, for example,\nDialogue: 0,0:07:39.18,0:07:48.52,EN,,0,0,0,,if I were to define count to be one.\nDialogue: 0,0:07:50.00,0:07:52.41,EN,,0,0,0,,And then I'm going to define also a procedure,\nDialogue: 0,0:07:55.16,0:07:56.83,EN,,0,0,0,,a simple procedure called demo,\nDialogue: 0,0:07:59.52,0:08:03.84,EN,,0,0,0,,which takes argument x and does the following operations.\nDialogue: 0,0:08:03.84,0:08:09.62,EN,,0,0,0,,It first sets x to x plus one.\nDialogue: 0,0:08:09.62,0:08:11.77,EN,,0,0,0,,My gosh, this looksjust like FORTRAN, right--\nDialogue: 0,0:08:13.16,0:08:14.17,EN,,0,0,0,,in a funny syntax.\nDialogue: 0,0:08:16.80,0:08:21.37,EN,,0,0,0,,And then add to x count,\nDialogue: 0,0:08:22.14,0:08:24.14,EN,,0,0,0,,Oh, I just made a mistake.\nDialogue: 0,0:08:24.38,0:08:25.23,EN,,0,0,0,,I want to say,\nDialogue: 0,0:08:25.47,0:08:27.12,EN,,0,0,0,,set! count to one plus count.\nDialogue: 0,0:08:30.37,0:08:31.79,EN,,0,0,0,,It's this thing defined here.\nDialogue: 0,0:08:34.41,0:08:36.51,EN,,0,0,0,,And then add and said plus x count.\nDialogue: 0,0:08:40.35,0:08:42.06,EN,,0,0,0,,Then I can try this procedure.\nDialogue: 0,0:08:42.48,0:08:43.20,EN,,0,0,0,,Let's run it.\nDialogue: 0,0:08:43.92,0:08:47.22,EN,,0,0,0,,So, suppose I get a prompt and I say,\nDialogue: 0,0:08:47.48,0:08:48.68,EN,,0,0,0,,demo 3\nDialogue: 0,0:08:52.19,0:08:53.20,EN,,0,0,0,,Well, what happens here?\nDialogue: 0,0:08:53.74,0:08:55.28,EN,,0,0,0,,The first thing that happens\nDialogue: 0,0:08:55.53,0:08:56.89,EN,,0,0,0,,is count is currently one.\nDialogue: 0,0:08:56.89,0:08:58.40,EN,,0,0,0,,Currently, there is a time.\nDialogue: 0,0:08:59.12,0:09:00.29,EN,,0,0,0,,We're talking about time.\nDialogue: 0,0:09:00.62,0:09:01.74,EN,,0,0,0,,x gets three.\nDialogue: 0,0:09:02.92,0:09:04.03,EN,,0,0,0,,At this moment,\nDialogue: 0,0:09:04.67,0:09:07.53,EN,,0,0,0,,I say, oh yes, count is incremented, so count is two.\nDialogue: 0,0:09:09.02,0:09:10.44,EN,,0,0,0,,two plus three is five.\nDialogue: 0,0:09:10.80,0:09:12.43,EN,,0,0,0,,So the answer I get out is five.\nDialogue: 0,0:09:14.48,0:09:21.58,EN,,0,0,0,,Then I say, demo of say, three again.\nDialogue: 0,0:09:23.60,0:09:24.56,EN,,0,0,0,,Okay, What do I get?\nDialogue: 0,0:09:24.83,0:09:27.40,EN,,0,0,0,,Well, now count is two, it's not one anymore,\nDialogue: 0,0:09:28.91,0:09:30.35,EN,,0,0,0,,because I have incremented it.\nDialogue: 0,0:09:30.92,0:09:32.64,EN,,0,0,0,,But now I go through this process,\nDialogue: 0,0:09:32.72,0:09:33.66,EN,,0,0,0,,three goes into x,\nDialogue: 0,0:09:34.17,0:09:37.40,EN,,0,0,0,,count becomes one plus count, so that's three now.\nDialogue: 0,0:09:38.08,0:09:39.62,EN,,0,0,0,,The sum of those two is six,\nDialogue: 0,0:09:39.62,0:09:40.94,EN,,0,0,0,,so the answer is six.\nDialogue: 0,0:09:41.92,0:09:43.03,EN,,0,0,0,,And what we see\nDialogue: 0,0:09:43.03,0:09:44.72,EN,,0,0,0,,is the same expression\nDialogue: 0,0:09:45.08,0:09:46.64,EN,,0,0,0,,leads to two different answers,\nDialogue: 0,0:09:48.75,0:09:49.96,EN,,0,0,0,,depending upon time.\nDialogue: 0,0:09:52.08,0:09:53.74,EN,,0,0,0,,So demo is not a function,\nDialogue: 0,0:09:54.17,0:09:56.12,EN,,0,0,0,,does not compute a mathematical function.\nDialogue: 0,0:09:59.88,0:10:02.09,EN,,0,0,0,,In fact, you could also see why now, of course,\nDialogue: 0,0:10:02.84,0:10:06.41,EN,,0,0,0,,this is the first place where the substitution model isn't going to work.\nDialogue: 0,0:10:07.72,0:10:09.55,EN,,0,0,0,,This kills the substitution model dead.\nDialogue: 0,0:10:11.28,0:10:13.82,EN,,0,0,0,,You know, with quotation there were some little problems\nDialogue: 0,0:10:13.85,0:10:17.18,EN,,0,0,0,,that a philosopher might notice with substitutions,\nDialogue: 0,0:10:17.18,0:10:19.87,EN,,0,0,0,,because you have to worry about what deductions you can make\nDialogue: 0,0:10:20.91,0:10:22.12,EN,,0,0,0,,when you substitute into quotes,\nDialogue: 0,0:10:22.34,0:10:23.92,EN,,0,0,0,,if you're allowed to do that at all.\nDialogue: 0,0:10:25.08,0:10:25.60,EN,,0,0,0,,But\nDialogue: 0,0:10:26.06,0:10:28.00,EN,,0,0,0,,here the substitution model is dead,\nDialogue: 0,0:10:28.11,0:10:29.40,EN,,0,0,0,,can't do anything at all.\nDialogue: 0,0:10:29.64,0:10:30.57,EN,,0,0,0,,Because,\nDialogue: 0,0:10:30.57,0:10:35.85,EN,,0,0,0,,Supposing I wanted to use a substitution model to consider substituting for count?\nDialogue: 0,0:10:37.10,0:10:41.16,EN,,0,0,0,,Well, my gosh, if I substitute for here and here,\nDialogue: 0,0:10:41.69,0:10:42.96,EN,,0,0,0,,they're different ones.\nDialogue: 0,0:10:44.44,0:10:45.96,EN,,0,0,0,,It's not the same count any more.\nDialogue: 0,0:10:46.48,0:10:47.64,EN,,0,0,0,,I get the wrong answer.\nDialogue: 0,0:10:47.97,0:10:50.14,EN,,0,0,0,,The substitution model is a static phenomenon\nDialogue: 0,0:10:51.18,0:10:52.56,EN,,0,0,0,,describes things that are true\nDialogue: 0,0:10:53.93,0:10:55.29,EN,,0,0,0,,and not things that change.\nDialogue: 0,0:10:55.50,0:10:57.04,EN,,0,0,0,,Here, we have truths that change.\nDialogue: 0,0:11:00.60,0:11:06.74,EN,,0,0,0,,OK, Well, before I give you any understanding of this,\nDialogue: 0,0:11:06.74,0:11:07.79,EN,,0,0,0,,this is very bad.\nDialogue: 0,0:11:07.79,0:11:09.72,EN,,0,0,0,,Now, we've lost our model of computation.\nDialogue: 0,0:11:10.28,0:11:10.80,EN,,0,0,0,,And,\nDialogue: 0,0:11:11.48,0:11:13.69,EN,,0,0,0,,pretty soon, I'm going to have to build you a new model of computation.\nDialogue: 0,0:11:14.66,0:11:17.87,EN,,0,0,0,,But ours plays with this, just now, in an informal sense.\nDialogue: 0,0:11:18.56,0:11:20.16,EN,,0,0,0,,Of course, what you already see\nDialogue: 0,0:11:20.51,0:11:22.70,EN,,0,0,0,,is that when I have something like assignment,\nDialogue: 0,0:11:23.12,0:11:24.51,EN,,0,0,0,,the model that we're going to need\nDialogue: 0,0:11:24.51,0:11:26.89,EN,,0,0,0,,is different from the model that we had before\nDialogue: 0,0:11:26.89,0:11:30.93,EN,,0,0,0,,in that, the variables, those symbols like count, or x\nDialogue: 0,0:11:30.93,0:11:34.07,EN,,0,0,0,,are no longer going to refer to the values they have,\nDialogue: 0,0:11:34.07,0:11:37.31,EN,,0,0,0,,but rather to some sort of place where the value restored.\nDialogue: 0,0:11:37.68,0:11:39.47,EN,,0,0,0,,We're going to have to think that way for a while.\nDialogue: 0,0:11:40.20,0:11:42.11,EN,,0,0,0,,And it's going to be a very bad thing\nDialogue: 0,0:11:42.11,0:11:43.47,EN,,0,0,0,,and cause a lot of trouble.\nDialogue: 0,0:11:44.49,0:11:48.25,EN,,0,0,0,,And so, as I said, the very fact that we're inventing this bad thing,\nDialogue: 0,0:11:48.25,0:11:50.09,EN,,0,0,0,,means that there had better be a good reason for it,\nDialogue: 0,0:11:50.37,0:11:52.86,EN,,0,0,0,,otherwise, just a waste of time and a lot of effort.\nDialogue: 0,0:11:53.39,0:11:55.55,EN,,0,0,0,,Let's just look at some of it just to play.\nDialogue: 0,0:11:55.88,0:11:58.59,EN,,0,0,0,,Supposing we write down the functional version,\nDialogue: 0,0:11:58.59,0:12:00.48,EN,,0,0,0,,functional meaning in the old style,\nDialogue: 0,0:12:01.37,0:12:04.60,EN,,0,0,0,,of factorial by an iterative process.\nDialogue: 0,0:12:09.59,0:12:13.28,EN,,0,0,0,,Factorial of n.\nDialogue: 0,0:12:18.38,0:12:24.35,EN,,0,0,0,,we're going to iterate of m and i,\nDialogue: 0,0:12:26.12,0:12:33.13,EN,,0,0,0,,which says if i is greater than n,\nDialogue: 0,0:12:33.77,0:12:35.51,EN,,0,0,0,,then the result is m,\nDialogue: 0,0:12:36.30,0:12:37.39,EN,,0,0,0,,otherwise,\nDialogue: 0,0:12:39.79,0:12:46.82,EN,,0,0,0,,the result of iterating the product of i and m.\nDialogue: 0,0:12:46.82,0:12:49.95,EN,,0,0,0,,So m is going to be the product that I'm accumulating.\nDialogue: 0,0:12:51.58,0:12:52.62,EN,,0,0,0,,m is the product.\nDialogue: 0,0:12:57.97,0:13:00.17,EN,,0,0,0,,And the count I'm going to increase by one.\nDialogue: 0,0:13:04.62,0:13:10.97,EN,,0,0,0,,Plus, ITER, ELSE, COND, define.\nDialogue: 0,0:13:11.95,0:13:13.04,EN,,0,0,0,,I'm going to start this up.\nDialogue: 0,0:13:17.16,0:13:19.79,EN,,0,0,0,,And these days, you should have no trouble reading something like this.\nDialogue: 0,0:13:20.86,0:13:25.15,EN,,0,0,0,,What I have here is a product there being accumulated and a counter.\nDialogue: 0,0:13:26.48,0:13:28.46,EN,,0,0,0,,I start them up both at one.\nDialogue: 0,0:13:28.89,0:13:30.92,EN,,0,0,0,,I'm going to buzz the counter up,\nDialogue: 0,0:13:30.92,0:13:33.12,EN,,0,0,0,,i goes to i plus one every time around.\nDialogue: 0,0:13:34.56,0:13:37.47,EN,,0,0,0,,But that's only way our putting a time on the process,\nDialogue: 0,0:13:38.48,0:13:40.04,EN,,0,0,0,,each of this is just a set of truths,\nDialogue: 0,0:13:40.49,0:13:41.34,EN,,0,0,0,,true rules.\nDialogue: 0,0:13:42.81,0:13:46.13,EN,,0,0,0,,And m is going to get a new values of i and m,\nDialogue: 0,0:13:46.13,0:13:47.82,EN,,0,0,0,,i times m each time around,\nDialogue: 0,0:13:48.68,0:13:50.48,EN,,0,0,0,,and eventually i is going to be bigger than n,\nDialogue: 0,0:13:50.49,0:13:52.06,EN,,0,0,0,,in which case, the answer's going to be m.\nDialogue: 0,0:13:52.67,0:13:54.80,EN,,0,0,0,,Now, I'm speaking to you, use time in this.\nDialogue: 0,0:13:55.68,0:13:57.45,EN,,0,0,0,,That's just because I know how the computer works.\nDialogue: 0,0:13:58.25,0:13:59.24,EN,,0,0,0,,But I didn't have to.\nDialogue: 0,0:13:59.26,0:14:02.30,EN,,0,0,0,,This could be a purely mathematical description at this point,\nDialogue: 0,0:14:02.30,0:14:03.74,EN,,0,0,0,,because substitution will work for this.\nDialogue: 0,0:14:05.10,0:14:08.14,EN,,0,0,0,,But let's set right down a similar sort of program,\nDialogue: 0,0:14:08.30,0:14:09.95,EN,,0,0,0,,using the same algorithm,\nDialogue: 0,0:14:10.73,0:14:12.11,EN,,0,0,0,,but with assignments.\nDialogue: 0,0:14:15.69,0:14:17.16,EN,,0,0,0,,So this is called the functional version.\nDialogue: 0,0:14:23.72,0:14:25.56,EN,,0,0,0,,I want to write down an imperative version.\nDialogue: 0,0:14:34.48,0:14:35.39,EN,,0,0,0,,Factorial of n.\nDialogue: 0,0:14:35.92,0:14:37.74,EN,,0,0,0,,I'm going to create my two variables.\nDialogue: 0,0:14:40.16,0:14:45.53,EN,,0,0,0,,Let i initialize itself to one,\nDialogue: 0,0:14:46.32,0:14:49.77,EN,,0,0,0,,and m be initialized to one, similar.\nDialogue: 0,0:14:51.15,0:14:52.19,EN,,0,0,0,,We'll create a loop\nDialogue: 0,0:14:59.31,0:15:07.27,EN,,0,0,0,,which has COND greater than i, and if i is greater than n, we're done.\nDialogue: 0,0:15:07.27,0:15:08.87,EN,,0,0,0,,And the result is m,\nDialogue: 0,0:15:08.87,0:15:10.38,EN,,0,0,0,,the product I'm accumulating.\nDialogue: 0,0:15:10.87,0:15:11.77,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:15:15.52,0:15:17.40,EN,,0,0,0,,I'm going to write down three things to do.\nDialogue: 0,0:15:19.26,0:15:27.05,EN,,0,0,0,,I'm going to set! m to the product of i and m,\nDialogue: 0,0:15:29.36,0:15:35.20,EN,,0,0,0,,set! i to the sum of i and one,\nDialogue: 0,0:15:37.85,0:15:39.31,EN,,0,0,0,,and go around the loop again.\nDialogue: 0,0:15:40.41,0:15:43.02,EN,,0,0,0,,Looks very familiar to you FORTRAN programmers.\nDialogue: 0,0:15:44.73,0:15:46.64,EN,,0,0,0,,ELSE, COND, define,\nDialogue: 0,0:15:46.64,0:15:47.88,EN,,0,0,0,,funny syntax though.\nDialogue: 0,0:15:51.13,0:15:52.27,EN,,0,0,0,,Start the loop up,\nDialogue: 0,0:15:56.10,0:15:57.56,EN,,0,0,0,,and that's the program.\nDialogue: 0,0:15:59.15,0:16:00.52,EN,,0,0,0,,Now, this program,\nDialogue: 0,0:16:01.31,0:16:02.49,EN,,0,0,0,,how do we think about it?\nDialogue: 0,0:16:02.71,0:16:04.25,EN,,0,0,0,,Well, let's just say what we're seeing here.\nDialogue: 0,0:16:04.84,0:16:07.47,EN,,0,0,0,,There are two local variables, i and m,\nDialogue: 0,0:16:07.47,0:16:09.02,EN,,0,0,0,,that have been initialized to one.\nDialogue: 0,0:16:10.72,0:16:13.89,EN,,0,0,0,,Every time around the loop, I test to see if i is greater than n,\nDialogue: 0,0:16:13.89,0:16:15.08,EN,,0,0,0,,which is the input argument,\nDialogue: 0,0:16:15.30,0:16:18.14,EN,,0,0,0,,and if so, the result is the product being accumulated in m.\nDialogue: 0,0:16:19.16,0:16:21.21,EN,,0,0,0,,However, if it's not the end of the loop,\nDialogue: 0,0:16:21.21,0:16:22.89,EN,,0,0,0,,if I'm not done,\nDialogue: 0,0:16:23.64,0:16:25.55,EN,,0,0,0,,then what I'm going to do is change the product\nDialogue: 0,0:16:25.84,0:16:28.38,EN,,0,0,0,,to be the result of multiplying i times the current product.\nDialogue: 0,0:16:29.04,0:16:30.68,EN,,0,0,0,,Which is sort of what we were doing here.\nDialogue: 0,0:16:31.42,0:16:32.68,EN,,0,0,0,,Except here I wasn't changing.\nDialogue: 0,0:16:33.63,0:16:35.77,EN,,0,0,0,,I was making another copy,\nDialogue: 0,0:16:36.81,0:16:42.04,EN,,0,0,0,,because the substitution model says, you copy the body of the procedure\nDialogue: 0,0:16:43.08,0:16:45.88,EN,,0,0,0,,with the arguments substituted for the formal parameters.\nDialogue: 0,0:16:46.72,0:16:48.42,EN,,0,0,0,,Here I'm not worried about copying,\nDialogue: 0,0:16:48.42,0:16:50.52,EN,,0,0,0,,here I've changed the value of m.\nDialogue: 0,0:16:51.80,0:16:55.12,EN,,0,0,0,,I also then change the value of i to i plus one,\nDialogue: 0,0:16:55.61,0:16:56.96,EN,,0,0,0,,and go buzzing around.\nDialogue: 0,0:16:58.22,0:17:00.08,EN,,0,0,0,,Seems like essentially the same program,\nDialogue: 0,0:17:00.96,0:17:02.84,EN,,0,0,0,,but there are some ways of making errors here\nDialogue: 0,0:17:02.84,0:17:05.50,EN,,0,0,0,,that didn't exist until today.\nDialogue: 0,0:17:06.14,0:17:07.02,EN,,0,0,0,,For example,\nDialogue: 0,0:17:07.45,0:17:09.40,EN,,0,0,0,,if I were to do the horrible thing\nDialogue: 0,0:17:10.04,0:17:12.14,EN,,0,0,0,,of not being careful in writing my program\nDialogue: 0,0:17:12.64,0:17:16.08,EN,,0,0,0,,and interchange those two assignments,\nDialogue: 0,0:17:17.10,0:17:18.91,EN,,0,0,0,,the program wouldn't compute the same function.\nDialogue: 0,0:17:20.33,0:17:22.87,EN,,0,0,0,,I get a timing error because there's a dependency\nDialogue: 0,0:17:22.87,0:17:27.22,EN,,0,0,0,,that m depends upon having the last value of i.\nDialogue: 0,0:17:27.34,0:17:28.92,EN,,0,0,0,,If I try change i first,\nDialogue: 0,0:17:31.31,0:17:33.77,EN,,0,0,0,,then I've got the wrong value of i when I multiply by m.\nDialogue: 0,0:17:35.96,0:17:38.38,EN,,0,0,0,,It's a bug that wasn't available until this moment,\nDialogue: 0,0:17:38.38,0:17:40.59,EN,,0,0,0,,until we introduced something that had time in it.\nDialogue: 0,0:17:43.44,0:17:44.30,EN,,0,0,0,,So, as I said,\nDialogue: 0,0:17:45.53,0:17:47.39,EN,,0,0,0,,first we need a new model of computation,\nDialogue: 0,0:17:47.39,0:17:50.86,EN,,0,0,0,,and second, we have to be damn good reason for doing this kind of ugly thing.\nDialogue: 0,0:17:52.72,0:17:53.74,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:17:58.83,0:18:00.22,EN,,0,0,0,,Speak loudly, David\nDialogue: 0,0:18:00.40,0:18:03.47,EN,,0,0,0,,AUDIENCE: I'm confused about, we've introduced set now,\nDialogue: 0,0:18:03.90,0:18:06.36,EN,,0,0,0,,but we had let before and define before.\nDialogue: 0,0:18:06.89,0:18:09.70,EN,,0,0,0,,I'm confused about the difference between the three.\nDialogue: 0,0:18:09.70,0:18:13.25,EN,,0,0,0,,Wouldn't define work in the same situation as set!\nDialogue: 0,0:18:13.98,0:18:14.83,EN,,0,0,0,,if you introduced it a bit?\nDialogue: 0,0:18:14.83,0:18:19.31,EN,,0,0,0,,PROFESSOR: No, define is intended for setting something once the first time,\nDialogue: 0,0:18:19.31,0:18:21.36,EN,,0,0,0,,for making it, OK?\nDialogue: 0,0:18:22.08,0:18:24.70,EN,,0,0,0,,You've never seen me write on a blackboard\nDialogue: 0,0:18:25.60,0:18:26.94,EN,,0,0,0,,two defines in a row\nDialogue: 0,0:18:27.08,0:18:32.08,EN,,0,0,0,,whose intention was to change the old value of some variable to a new one.\nDialogue: 0,0:18:32.08,0:18:34.51,EN,,0,0,0,,AUDIENCE: Is that by convention or--\nDialogue: 0,0:18:34.51,0:18:36.35,EN,,0,0,0,,PROFESSOR: No, it's intention.\nDialogue: 0,0:18:36.35,0:18:38.92,EN,,0,0,0,,Okay? The answer is,\nDialogue: 0,0:18:39.69,0:18:40.84,EN,,0,0,0,,that, for example,\nDialogue: 0,0:18:40.84,0:18:42.27,EN,,0,0,0,,internal to a procedure,\nDialogue: 0,0:18:43.20,0:18:45.92,EN,,0,0,0,,two defines in a row are illegal,\nDialogue: 0,0:18:46.68,0:18:48.57,EN,,0,0,0,,two defines in a row of the same variable.\nDialogue: 0,0:18:50.24,0:18:51.74,EN,,0,0,0,,x can't be defined twice.\nDialogue: 0,0:18:51.74,0:18:55.20,EN,,0,0,0,,Whether or not a system catches that error is a different question,\nDialogue: 0,0:18:55.93,0:18:57.88,EN,,0,0,0,,but I legislate to you\nDialogue: 0,0:18:58.12,0:19:00.64,EN,,0,0,0,,that define happens once on anything.\nDialogue: 0,0:19:00.73,0:19:02.64,EN,,0,0,0,,Now, indeed, in interactive debugging,\nDialogue: 0,0:19:03.37,0:19:07.48,EN,,0,0,0,,we intend that you interacting with your computer will redefine things,\nDialogue: 0,0:19:08.19,0:19:11.21,EN,,0,0,0,,and so there's a special exception made for interactive debugging.\nDialogue: 0,0:19:11.82,0:19:16.48,EN,,0,0,0,,But define is intended to mean to set up something\nDialogue: 0,0:19:18.14,0:19:20.96,EN,,0,0,0,,which will be forever that value after that point.\nDialogue: 0,0:19:22.05,0:19:24.54,EN,,0,0,0,,It's as if all the defines were done at the beginning.\nDialogue: 0,0:19:26.09,0:19:30.92,EN,,0,0,0,,In fact, the only legal place to put a define in Scheme internal to a procedure\nDialogue: 0,0:19:31.02,0:19:33.36,EN,,0,0,0,,is just at the beginning of a lambda expression,\nDialogue: 0,0:19:34.47,0:19:37.66,EN,,0,0,0,,which is the beginning of the body of a procedure.\nDialogue: 0,0:19:40.40,0:19:45.80,EN,,0,0,0,,Now, let of course does nothing like either of that.\nDialogue: 0,0:19:48.09,0:19:49.55,EN,,0,0,0,,I mean, if you look at what's happening with a let,\nDialogue: 0,0:19:50.17,0:19:52.13,EN,,0,0,0,,this happens again exactly once.\nDialogue: 0,0:19:52.13,0:19:55.82,EN,,0,0,0,,It sets up a context where i and m are values one and one.\nDialogue: 0,0:19:56.83,0:20:00.57,EN,,0,0,0,,That context exists throughout this scope,\nDialogue: 0,0:20:01.31,0:20:02.80,EN,,0,0,0,,this region of the program.\nDialogue: 0,0:20:04.99,0:20:10.12,EN,,0,0,0,,However, you don't think of that let as setting i again.\nDialogue: 0,0:20:11.04,0:20:12.16,EN,,0,0,0,,It doesn't change it.\nDialogue: 0,0:20:12.16,0:20:14.01,EN,,0,0,0,,i never changes because of the let.\nDialogue: 0,0:20:15.28,0:20:16.81,EN,,0,0,0,,i gets created because of let.\nDialogue: 0,0:20:18.51,0:20:19.29,EN,,0,0,0,,In fact,\nDialogue: 0,0:20:19.73,0:20:21.42,EN,,0,0,0,,the let is a very simple idea.\nDialogue: 0,0:20:22.24,0:20:23.59,EN,,0,0,0,,Let does nothing more,\nDialogue: 0,0:20:23.59,0:20:31.62,EN,,0,0,0,,Let a variable one to have value one\nDialogue: 0,0:20:31.62,0:20:33.50,EN,,0,0,0,,I'll write this down a little bit more neatly;\nDialogue: 0,0:20:37.16,0:20:43.73,EN,,0,0,0,,Let's write, var one have value, the value of expression e1,\nDialogue: 0,0:20:43.73,0:20:47.36,EN,,0,0,0,,and variable two, have this value of the expression e2,\nDialogue: 0,0:20:48.14,0:20:49.74,EN,,0,0,0,,in an expression e3,\nDialogue: 0,0:20:51.60,0:21:05.80,EN,,0,0,0,,is the same thing as a procedure of var one and var two, the formal parameters,\nDialogue: 0,0:21:06.94,0:21:08.96,EN,,0,0,0,,and e3 being the body,\nDialogue: 0,0:21:10.91,0:21:14.00,EN,,0,0,0,,where var one is bound to the value of e1,\nDialogue: 0,0:21:14.27,0:21:16.91,EN,,0,0,0,,and var two gets the value of e2.\nDialogue: 0,0:21:19.53,0:21:23.26,EN,,0,0,0,,So this is, in fact, a perfectly understandable thing from a substitution point of view.\nDialogue: 0,0:21:24.89,0:21:27.95,EN,,0,0,0,,This is really the same expression written in two different ways.\nDialogue: 0,0:21:31.69,0:21:33.50,EN,,0,0,0,,In fact, the way the actual system works\nDialogue: 0,0:21:33.63,0:21:35.82,EN,,0,0,0,,is this gets translated into this before anything happens.\nDialogue: 0,0:21:37.64,0:21:41.77,EN,,0,0,0,,AUDIENCE: OK, I'm still unclear as then what makes the difference between a let and a define. They could--\nDialogue: 0,0:21:41.77,0:21:44.30,EN,,0,0,0,,PROFESSOR: A define is a syntactic sugar,\nDialogue: 0,0:21:44.62,0:21:49.10,EN,,0,0,0,,whereby, essentially a bunch of variables get created by lets and then set up once.\nDialogue: 0,0:21:57.10,0:21:59.74,EN,,0,0,0,,OK, time for the first break, I think. Thank you.\nDialogue: 0,0:22:02.52,0:22:12.84,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:23:04.28,0:23:06.11,EN,,0,0,0,,Well let's see.\nDialogue: 0,0:23:06.44,0:23:09.08,EN,,0,0,0,,I now have to rebuild the model of computation,\nDialogue: 0,0:23:09.77,0:23:14.16,EN,,0,0,0,,so you understand how some such mechanical mechanism could work\nDialogue: 0,0:23:14.91,0:23:16.46,EN,,0,0,0,,that can do what we've just talked about.\nDialogue: 0,0:23:17.53,0:23:21.39,EN,,0,0,0,,I just recently destroyed your substitution model.\nDialogue: 0,0:23:22.62,0:23:26.03,EN,,0,0,0,,Unfortunately, this model is significantly more complicated than the substitution model.\nDialogue: 0,0:23:26.62,0:23:27.93,EN,,0,0,0,,It's called the environment model.\nDialogue: 0,0:23:29.02,0:23:31.20,EN,,0,0,0,,And I'm going to have to introduce some terminology,\nDialogue: 0,0:23:32.03,0:23:34.51,EN,,0,0,0,,which is very good terminology for you to know anyway.\nDialogue: 0,0:23:34.51,0:23:35.74,EN,,0,0,0,,It's about names.\nDialogue: 0,0:23:36.51,0:23:39.63,EN,,0,0,0,,And we're going to give names to the kinds of names things have\nDialogue: 0,0:23:40.00,0:23:41.31,EN,,0,0,0,,and the way those names are used.\nDialogue: 0,0:23:42.48,0:23:47.94,EN,,0,0,0,,So this is a meta-description, if you will.\nDialogue: 0,0:23:48.56,0:23:50.85,EN,,0,0,0,,Anyway, there is a pile of an unfortunate terminology here,\nDialogue: 0,0:23:50.85,0:23:53.76,EN,,0,0,0,,but we're going to need this to understand what's called the environment model.\nDialogue: 0,0:23:54.70,0:23:57.53,EN,,0,0,0,,We're about to do a little bit of boring, dog-work here.\nDialogue: 0,0:23:58.04,0:24:01.58,EN,,0,0,0,,Let's look at the first transparency.\nDialogue: 0,0:24:02.25,0:24:06.97,EN,,0,0,0,,And we see a description of a word called bound.\nDialogue: 0,0:24:08.80,0:24:11.00,EN,,0,0,0,,And we're going to say that a variable, v,\nDialogue: 0,0:24:11.00,0:24:12.91,EN,,0,0,0,,is bound in an expression, e,\nDialogue: 0,0:24:13.41,0:24:21.52,EN,,0,0,0,,if the meaning of e is unchanged by the uniform replacement of a variable w,\nDialogue: 0,0:24:21.56,0:24:24.28,EN,,0,0,0,,not occurrent if for every occurrence of v in e.\nDialogue: 0,0:24:25.69,0:24:27.00,EN,,0,0,0,,Now that's a long sentence,\nDialogue: 0,0:24:27.37,0:24:29.96,EN,,0,0,0,,so, I think, I'm going to have to say a little bit about that\nDialogue: 0,0:24:29.98,0:24:32.62,EN,,0,0,0,,before we even fool around at all here.\nDialogue: 0,0:24:33.42,0:24:35.28,EN,,0,0,0,,Bound variables we're talking about here.\nDialogue: 0,0:24:44.16,0:24:45.56,EN,,0,0,0,,And you've seen lots of them.\nDialogue: 0,0:24:46.07,0:24:48.17,EN,,0,0,0,,You may not know that you've seen lots of them.\nDialogue: 0,0:24:48.24,0:24:52.24,EN,,0,0,0,,Well, I suppose in your logic, you saw a logical variables like,\nDialogue: 0,0:24:53.27,0:25:00.11,EN,,0,0,0,,for every x there exists a y such that p is true of x and y from your calculus class.\nDialogue: 0,0:25:02.88,0:25:05.82,EN,,0,0,0,,This variable, x, and this variable, y, are bound,\nDialogue: 0,0:25:07.08,0:25:07.92,EN,,0,0,0,,because,\nDialogue: 0,0:25:08.33,0:25:09.98,EN,,0,0,0,,the meaning of this expression\nDialogue: 0,0:25:09.98,0:25:15.61,EN,,0,0,0,,does not depend upon the particular letters I used to describe x and y.\nDialogue: 0,0:25:16.49,0:25:19.18,EN,,0,0,0,,If I were to change the w for x,\nDialogue: 0,0:25:19.84,0:25:25.68,EN,,0,0,0,,then said for every w there exists a y such that p is true of w and y,\nDialogue: 0,0:25:25.98,0:25:27.08,EN,,0,0,0,,it would be the same sentence.\nDialogue: 0,0:25:29.44,0:25:30.34,EN,,0,0,0,,That's what it means.\nDialogue: 0,0:25:30.34,0:25:34.89,EN,,0,0,0,,Or another case of this that you've seen is integral say,\nDialogue: 0,0:25:35.40,0:25:42.65,EN,,0,0,0,,from 0 to one of dx over one plus x square.\nDialogue: 0,0:25:46.03,0:25:47.92,EN,,0,0,0,,Well that's something you see all the time.\nDialogue: 0,0:25:47.92,0:25:50.92,EN,,0,0,0,,And this x is a bound variable.\nDialogue: 0,0:25:52.06,0:25:53.79,EN,,0,0,0,,If I change that to a t,\nDialogue: 0,0:25:54.15,0:25:56.25,EN,,0,0,0,,the expression is still the same thing.\nDialogue: 0,0:25:58.06,0:26:02.76,EN,,0,0,0,,This is a 1/4 of the arctan of one or something here, something like that.\nDialogue: 0,0:26:04.70,0:26:06.01,EN,,0,0,0,,Yes, that's the arctan of one.\nDialogue: 0,0:26:06.62,0:26:08.76,EN,,0,0,0,,So bound variables are actually fairly common,\nDialogue: 0,0:26:09.08,0:26:12.36,EN,,0,0,0,,for those of you who have played a bit with mathematics.\nDialogue: 0,0:26:13.26,0:26:17.47,EN,,0,0,0,,Well, let's go into the programming world.\nDialogue: 0,0:26:19.02,0:26:21.36,EN,,0,0,0,,Instead of the quantifier being something like,\nDialogue: 0,0:26:22.03,0:26:24.06,EN,,0,0,0,,for every, or there exists, or integral,\nDialogue: 0,0:26:24.06,0:26:26.43,EN,,0,0,0,,a quantifier is a symbol that binds a variable.\nDialogue: 0,0:26:27.47,0:26:28.99,EN,,0,0,0,,And we are going to use the quantifier lambda\nDialogue: 0,0:26:29.79,0:26:31.80,EN,,0,0,0,,as being the essential thing that binds variables.\nDialogue: 0,0:26:33.80,0:26:36.12,EN,,0,0,0,,And so we have some nice examples here\nDialogue: 0,0:26:36.59,0:26:44.14,EN,,0,0,0,,like that procedure of one argument y which does the following thing.\nDialogue: 0,0:26:44.14,0:26:46.96,EN,,0,0,0,,It calls the procedure of one argument x,\nDialogue: 0,0:26:47.87,0:26:51.13,EN,,0,0,0,,which multiplies x by y,\nDialogue: 0,0:26:52.88,0:26:54.52,EN,,0,0,0,,and applies that to three.\nDialogue: 0,0:26:58.76,0:27:01.66,EN,,0,0,0,,That procedure has the property there of two bound variables in it,\nDialogue: 0,0:27:02.01,0:27:02.92,EN,,0,0,0,,x and y\nDialogue: 0,0:27:04.83,0:27:07.47,EN,,0,0,0,,This quantifier, lambda here, binds this y,\nDialogue: 0,0:27:07.91,0:27:10.78,EN,,0,0,0,,and this quantifier, lambda, binds that x.\nDialogue: 0,0:27:12.11,0:27:17.05,EN,,0,0,0,,Because, if I were to take an arbitrary symbol does not occur in this expression like w\nDialogue: 0,0:27:17.98,0:27:21.04,EN,,0,0,0,,and replace all y's with w's in this expression,\nDialogue: 0,0:27:21.36,0:27:22.75,EN,,0,0,0,,the expression is still the same,\nDialogue: 0,0:27:23.66,0:27:24.80,EN,,0,0,0,,the same procedure.\nDialogue: 0,0:27:26.22,0:27:27.41,EN,,0,0,0,,And this is an important idea.\nDialogue: 0,0:27:27.41,0:27:29.64,EN,,0,0,0,,The reason why we had such things like that\nDialogue: 0,0:27:30.20,0:27:31.41,EN,,0,0,0,,is a kind of modularity.\nDialogue: 0,0:27:31.41,0:27:32.86,EN,,0,0,0,,If two people are writing programs,\nDialogue: 0,0:27:34.03,0:27:35.26,EN,,0,0,0,,and they work together,\nDialogue: 0,0:27:35.26,0:27:40.56,EN,,0,0,0,,it shouldn't matter what names they use internal to their own little machines that they're building.\nDialogue: 0,0:27:42.83,0:27:44.67,EN,,0,0,0,,And so, what I'm really telling you there,\nDialogue: 0,0:27:45.44,0:27:46.75,EN,,0,0,0,,is that, for example,\nDialogue: 0,0:27:46.84,0:27:51.26,EN,,0,0,0,,this is equivalent to that procedure of one argument y which\nDialogue: 0,0:27:52.35,0:27:59.23,EN,,0,0,0,,uses that procedure of one argument z which multiplies z by y.\nDialogue: 0,0:28:01.64,0:28:03.53,EN,,0,0,0,,Because nobody cares what I used in here.\nDialogue: 0,0:28:06.36,0:28:07.24,EN,,0,0,0,,It's a nice example.\nDialogue: 0,0:28:08.84,0:28:09.85,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:28:11.07,0:28:14.33,EN,,0,0,0,,I have some variables that are not bound.\nDialogue: 0,0:28:15.23,0:28:15.96,EN,,0,0,0,,And example,\nDialogue: 0,0:28:20.27,0:28:21.76,EN,,0,0,0,,that procedure of one argument x\nDialogue: 0,0:28:22.09,0:28:25.04,EN,,0,0,0,,which multiplies x by y\nDialogue: 0,0:28:27.28,0:28:28.16,EN,,0,0,0,,In this case,\nDialogue: 0,0:28:29.45,0:28:30.75,EN,,0,0,0,,y is not bound.\nDialogue: 0,0:28:32.46,0:28:34.27,EN,,0,0,0,,Supposing y had the value three,\nDialogue: 0,0:28:35.26,0:28:36.80,EN,,0,0,0,,and z had the value four,\nDialogue: 0,0:28:38.83,0:28:44.27,EN,,0,0,0,,then this procedure would be the thing that multiplies its argument by three.\nDialogue: 0,0:28:44.86,0:28:47.39,EN,,0,0,0,,If I were to replace every instance of y with z,\nDialogue: 0,0:28:47.52,0:28:51.96,EN,,0,0,0,,I would have a different procedure which multiplies every argument that's given by four.\nDialogue: 0,0:28:53.87,0:28:56.40,EN,,0,0,0,,And, in fact, we have a name for such a variable.\nDialogue: 0,0:28:57.76,0:29:04.01,EN,,0,0,0,,Here, we say that a variable, v, is free in the expression, e,\nDialogue: 0,0:29:04.01,0:29:09.42,EN,,0,0,0,,if the meaning of the expression, e, is changed by the uniform replacement of a variable, w, not occurring in e,\nDialogue: 0,0:29:09.58,0:29:11.15,EN,,0,0,0,,for every occurrence of v and e.\nDialogue: 0,0:29:13.26,0:29:13.71,EN,,0,0,0,,So,\nDialogue: 0,0:29:14.49,0:29:22.76,EN,,0,0,0,,So that's why this variable over here, y, is a free variable.\nDialogue: 0,0:29:29.16,0:29:32.27,EN,,0,0,0,,And so free variables in this expression--\nDialogue: 0,0:29:33.76,0:29:35.18,EN,,0,0,0,,And other examples of that is that\nDialogue: 0,0:29:36.17,0:29:39.32,EN,,0,0,0,,is that procedure of one argument y,\nDialogue: 0,0:29:40.43,0:29:42.00,EN,,0,0,0,,which is just what we had before,\nDialogue: 0,0:29:42.27,0:29:44.60,EN,,0,0,0,,which uses that procedure of one argument x\nDialogue: 0,0:29:45.08,0:29:48.54,EN,,0,0,0,,that multiplies x by y--\nDialogue: 0,0:29:51.40,0:29:52.65,EN,,0,0,0,,use that on three.\nDialogue: 0,0:29:57.24,0:30:00.35,EN,,0,0,0,,This procedure has a free variable in it\nDialogue: 0,0:30:00.92,0:30:01.98,EN,,0,0,0,,which is asterisk.\nDialogue: 0,0:30:05.00,0:30:05.89,EN,,0,0,0,,See, because,\nDialogue: 0,0:30:05.89,0:30:08.08,EN,,0,0,0,,if that has a normal meaning of multiplication,\nDialogue: 0,0:30:09.44,0:30:12.78,EN,,0,0,0,,then if I were to replace uniformly all asterisks with pluses,\nDialogue: 0,0:30:14.25,0:30:16.38,EN,,0,0,0,,then the meaning of this expression would change.\nDialogue: 0,0:30:19.34,0:30:20.76,EN,,0,0,0,,That's what you mean by a free variable.\nDialogue: 0,0:30:22.68,0:30:24.81,EN,,0,0,0,,So, so far you've learned some logician words\nDialogue: 0,0:30:25.64,0:30:27.58,EN,,0,0,0,,which describe the way names are used.\nDialogue: 0,0:30:28.94,0:30:31.26,EN,,0,0,0,,Now, we have to do a little bit more playing around here,\nDialogue: 0,0:30:32.96,0:30:33.72,EN,,0,0,0,,a little bit more.\nDialogue: 0,0:30:35.13,0:30:36.22,EN,,0,0,0,,I want to tell you about\nDialogue: 0,0:30:36.81,0:30:39.76,EN,,0,0,0,,about the regions are over which variables are defined.\nDialogue: 0,0:30:42.17,0:30:42.88,EN,,0,0,0,,You see,\nDialogue: 0,0:30:43.37,0:30:45.69,EN,,0,0,0,,we've been very informal about this up till now,\nDialogue: 0,0:30:46.33,0:30:50.16,EN,,0,0,0,,and, of course, many of you have probably understood very clearly or most of you,\nDialogue: 0,0:30:50.36,0:30:52.84,EN,,0,0,0,,that the x that's being declared here\nDialogue: 0,0:30:53.64,0:30:55.18,EN,,0,0,0,,is defined only in here.\nDialogue: 0,0:30:58.28,0:31:00.91,EN,,0,0,0,,This x is the defined only in here,\nDialogue: 0,0:31:01.61,0:31:04.33,EN,,0,0,0,,and this y is defined only in here.\nDialogue: 0,0:31:07.10,0:31:09.16,EN,,0,0,0,,We have a name for such an idea. It's called a scope.\nDialogue: 0,0:31:11.61,0:31:13.58,EN,,0,0,0,,And let me give you another piece of terminology.\nDialogue: 0,0:31:14.70,0:31:15.77,EN,,0,0,0,,It's a long story.\nDialogue: 0,0:31:15.96,0:31:17.64,EN,,0,0,0,,If x is a bound variable in e,\nDialogue: 0,0:31:18.16,0:31:20.24,EN,,0,0,0,,then there is a lambda expression where it is bound.\nDialogue: 0,0:31:20.89,0:31:24.91,EN,,0,0,0,,So the only way you can get a bound variable ultimately is by lambda expression.\nDialogue: 0,0:31:24.91,0:31:25.96,EN,,0,0,0,,Then you may worry,\nDialogue: 0,0:31:26.22,0:31:29.05,EN,,0,0,0,,does define quite an exception to this?\nDialogue: 0,0:31:29.64,0:31:32.92,EN,,0,0,0,,And it turns out, we could always arrange things so you don't need any defines.\nDialogue: 0,0:31:32.92,0:31:33.96,EN,,0,0,0,,And we'll see that in a while.\nDialogue: 0,0:31:34.24,0:31:35.72,EN,,0,0,0,,It's a very magical thing.\nDialogue: 0,0:31:36.54,0:31:38.40,EN,,0,0,0,,So define really can go away.\nDialogue: 0,0:31:38.68,0:31:41.55,EN,,0,0,0,,The really, only thing that makes names is lambda .\nDialogue: 0,0:31:42.64,0:31:43.40,EN,,0,0,0,,That's its job.\nDialogue: 0,0:31:44.30,0:31:46.23,EN,,0,0,0,,And what's so amazing about a lot of things\nDialogue: 0,0:31:46.23,0:31:47.87,EN,,0,0,0,,is you can compute with only lambda.\nDialogue: 0,0:31:48.73,0:31:49.58,EN,,0,0,0,,But, in any case,\nDialogue: 0,0:31:51.74,0:31:55.76,EN,,0,0,0,,a lambda expression has a place where it declares a variable.\nDialogue: 0,0:31:55.76,0:31:57.10,EN,,0,0,0,,We call it the formal parameter list\nDialogue: 0,0:31:58.94,0:32:00.56,EN,,0,0,0,,and we say or the bound variable list.\nDialogue: 0,0:32:01.26,0:32:04.51,EN,,0,0,0,,We say that the lambda expression binds -- so it's a verb\nDialogue: 0,0:32:05.02,0:32:07.34,EN,,0,0,0,,--binds the variables declared in it's bound variable list.\nDialogue: 0,0:32:08.59,0:32:12.48,EN,,0,0,0,,In addition, those parts of the expression where the variable is defined,\nDialogue: 0,0:32:13.23,0:32:15.23,EN,,0,0,0,,which was declared by some declaration\nDialogue: 0,0:32:15.56,0:32:19.26,EN,,0,0,0,,is called the scope of that variable.\nDialogue: 0,0:32:20.44,0:32:21.92,EN,,0,0,0,,So these are scopes.\nDialogue: 0,0:32:22.25,0:32:23.68,EN,,0,0,0,,This is the scope of y.\nDialogue: 0,0:32:27.16,0:32:28.54,EN,,0,0,0,,And this is the scope of x--\nDialogue: 0,0:32:33.10,0:32:34.03,EN,,0,0,0,,that sort of thing.\nDialogue: 0,0:32:41.32,0:32:42.08,EN,,0,0,0,,OK,\nDialogue: 0,0:32:43.93,0:32:45.63,EN,,0,0,0,,well, now we have enough terminology\nDialogue: 0,0:32:46.60,0:32:51.76,EN,,0,0,0,,to begin to understand how to make a new model for computation\nDialogue: 0,0:32:51.96,0:32:53.77,EN,,0,0,0,,because the key thing going on here\nDialogue: 0,0:32:54.94,0:32:57.00,EN,,0,0,0,,is that we destroyed the substitution model,\nDialogue: 0,0:32:57.18,0:32:58.38,EN,,0,0,0,,and we now have to have a model\nDialogue: 0,0:32:58.62,0:33:02.32,EN,,0,0,0,,that represents the names as referring to places.\nDialogue: 0,0:33:03.93,0:33:05.34,EN,,0,0,0,,Because if we are going to change something,\nDialogue: 0,0:33:05.98,0:33:07.47,EN,,0,0,0,,then we have a place where it's stored.\nDialogue: 0,0:33:09.56,0:33:10.35,EN,,0,0,0,,You see,\nDialogue: 0,0:33:10.83,0:33:13.31,EN,,0,0,0,,if a name only refers to a value,\nDialogue: 0,0:33:14.04,0:33:16.36,EN,,0,0,0,,and if I tried to change the name's meaning,\nDialogue: 0,0:33:16.73,0:33:20.32,EN,,0,0,0,,well, that's not clear.\nDialogue: 0,0:33:20.32,0:33:24.68,EN,,0,0,0,,There's nothing that is the place that that name referred to.\nDialogue: 0,0:33:24.99,0:33:25.80,EN,,0,0,0,,How am I really saying it?\nDialogue: 0,0:33:25.92,0:33:29.54,EN,,0,0,0,,There're nothing shared among all of the instances of that name.\nDialogue: 0,0:33:29.87,0:33:31.68,EN,,0,0,0,,And what we really mean, by a name,\nDialogue: 0,0:33:31.68,0:33:32.97,EN,,0,0,0,,is that we find something out.\nDialogue: 0,0:33:34.33,0:33:36.36,EN,,0,0,0,,We've given something a name, and you have it,\nDialogue: 0,0:33:36.73,0:33:39.06,EN,,0,0,0,,and you have it, because I'm given you a reference to it,\nDialogue: 0,0:33:39.06,0:33:40.44,EN,,0,0,0,,and I've given you a reference to it.\nDialogue: 0,0:33:41.02,0:33:42.30,EN,,0,0,0,,And we'll see a lot about that.\nDialogue: 0,0:33:43.61,0:33:45.21,EN,,0,0,0,,So let me tell you about environments.\nDialogue: 0,0:33:46.19,0:33:48.76,EN,,0,0,0,,I need the overhead projection machine,\nDialogue: 0,0:33:49.31,0:33:49.98,EN,,0,0,0,,thank you.\nDialogue: 0,0:33:52.19,0:33:53.02,EN,,0,0,0,,And so here\nDialogue: 0,0:33:55.48,0:34:00.40,EN,,0,0,0,,is a bunch of environment structures.\nDialogue: 0,0:34:01.53,0:34:05.76,EN,,0,0,0,,An environment is a way of doing substitutions virtually.\nDialogue: 0,0:34:06.38,0:34:07.89,EN,,0,0,0,,It represents a place\nDialogue: 0,0:34:07.89,0:34:11.39,EN,,0,0,0,,where something is stored which is the substitutions that you haven't done.\nDialogue: 0,0:34:13.34,0:34:16.50,EN,,0,0,0,,It's a place where everything accumulates,\nDialogue: 0,0:34:16.50,0:34:21.13,EN,,0,0,0,,where the names of the variables are associated with the values they have\nDialogue: 0,0:34:21.79,0:34:22.56,EN,,0,0,0,,such that,\nDialogue: 0,0:34:22.75,0:34:25.90,EN,,0,0,0,,when you say, what dose this name mean,\nDialogue: 0,0:34:25.90,0:34:27.40,EN,,0,0,0,,you look it up in an environment.\nDialogue: 0,0:34:28.08,0:34:29.48,EN,,0,0,0,,So an environment is a function,\nDialogue: 0,0:34:30.80,0:34:31.48,EN,,0,0,0,,or a table,\nDialogue: 0,0:34:32.22,0:34:33.24,EN,,0,0,0,,or something like that.\nDialogue: 0,0:34:33.24,0:34:34.89,EN,,0,0,0,,But it's a structured sort of table.\nDialogue: 0,0:34:35.76,0:34:37.39,EN,,0,0,0,,It's made out of things called frames.\nDialogue: 0,0:34:41.13,0:34:44.46,EN,,0,0,0,,Frames are pieces of environment,\nDialogue: 0,0:34:44.89,0:34:46.01,EN,,0,0,0,,and they are chained together,\nDialogue: 0,0:34:47.07,0:34:48.19,EN,,0,0,0,,in some nice ways,\nDialogue: 0,0:34:49.00,0:34:52.09,EN,,0,0,0,,by what's called parent links or something like that.\nDialogue: 0,0:34:54.03,0:34:55.02,EN,,0,0,0,,So here,\nDialogue: 0,0:34:55.64,0:34:57.62,EN,,0,0,0,,we have an environment structure\nDialogue: 0,0:34:57.62,0:35:04.22,EN,,0,0,0,,consisting of three environments, basically, A, B, and C.\nDialogue: 0,0:35:05.10,0:35:07.63,EN,,0,0,0,,d is also an environment, but it's the same one,\nDialogue: 0,0:35:08.88,0:35:10.17,EN,,0,0,0,,they share.\nDialogue: 0,0:35:11.45,0:35:13.96,EN,,0,0,0,,And that's the essence of assignment.\nDialogue: 0,0:35:14.40,0:35:16.10,EN,,0,0,0,,If I change a variable,\nDialogue: 0,0:35:16.10,0:35:19.80,EN,,0,0,0,,a value of a valuable that lives here, like that one,\nDialogue: 0,0:35:19.80,0:35:23.50,EN,,0,0,0,,it should be visible from all places that you're looking at it from.\nDialogue: 0,0:35:23.50,0:35:24.84,EN,,0,0,0,,Take this one, x.\nDialogue: 0,0:35:24.84,0:35:28.19,EN,,0,0,0,,If I change the x to four,\nDialogue: 0,0:35:28.19,0:35:30.19,EN,,0,0,0,,it's visible from other places.\nDialogue: 0,0:35:30.19,0:35:32.19,EN,,0,0,0,,But I'm not going to worry about that right now.\nDialogue: 0,0:35:32.19,0:35:33.84,EN,,0,0,0,,We're going to talk a lot about that in a little while.\nDialogue: 0,0:35:34.56,0:35:35.53,EN,,0,0,0,,What do we have here?\nDialogue: 0,0:35:36.76,0:35:38.84,EN,,0,0,0,,Well, these are called frames. Here is a frame,\nDialogue: 0,0:35:39.40,0:35:40.38,EN,,0,0,0,,here's a frame\nDialogue: 0,0:35:40.76,0:35:41.84,EN,,0,0,0,,and here's a frame.\nDialogue: 0,0:35:43.18,0:35:45.20,EN,,0,0,0,,A is an environment which consists of\nDialogue: 0,0:35:45.20,0:35:47.82,EN,,0,0,0,,the table label which is frame two,\nDialogue: 0,0:35:48.36,0:35:51.05,EN,,0,0,0,,followed by the table labeled frame one.\nDialogue: 0,0:35:52.52,0:35:54.60,EN,,0,0,0,,And, in this environment,\nDialogue: 0,0:35:54.99,0:35:59.68,EN,,0,0,0,,in C, this environment, frame two,\nDialogue: 0,0:36:00.48,0:36:03.26,EN,,0,0,0,,uh....x and y are bound.\nDialogue: 0,0:36:04.06,0:36:04.78,EN,,0,0,0,,They have values.\nDialogue: 0,0:36:05.26,0:36:07.18,EN,,0,0,0,,Sorry, in frame one\nDialogue: 0,0:36:07.18,0:36:08.28,EN,,0,0,0,,In frame two,\nDialogue: 0,0:36:09.72,0:36:10.83,EN,,0,0,0,,z is bound,\nDialogue: 0,0:36:10.99,0:36:12.17,EN,,0,0,0,,and x is bound,\nDialogue: 0,0:36:12.44,0:36:13.69,EN,,0,0,0,,and y is bound,\nDialogue: 0,0:36:15.24,0:36:17.40,EN,,0,0,0,,but the value of x that we see,\nDialogue: 0,0:36:17.42,0:36:19.04,EN,,0,0,0,,looking from this point of view,\nDialogue: 0,0:36:20.01,0:36:21.74,EN,,0,0,0,,is this x. It's x is seven,\nDialogue: 0,0:36:22.36,0:36:24.84,EN,,0,0,0,,rather than this one which is three.\nDialogue: 0,0:36:24.84,0:36:27.61,EN,,0,0,0,,We say that this x shadows this x.\nDialogue: 0,0:36:31.05,0:36:32.49,EN,,0,0,0,,From environment three--\nDialogue: 0,0:36:33.44,0:36:34.45,EN,,0,0,0,,from frame three,\nDialogue: 0,0:36:34.45,0:36:35.73,EN,,0,0,0,,from environment b,\nDialogue: 0,0:36:35.73,0:36:37.18,EN,,0,0,0,,which refers to frame three,\nDialogue: 0,0:36:37.45,0:36:42.12,EN,,0,0,0,,we have variables m and y bound and also x.\nDialogue: 0,0:36:44.84,0:36:46.97,EN,,0,0,0,,This y shadow this one.\nDialogue: 0,0:36:48.65,0:36:51.00,EN,,0,0,0,,So the value, looking from this point of view,\nDialogue: 0,0:36:51.10,0:36:52.65,EN,,0,0,0,,of y is two.\nDialogue: 0,0:36:53.45,0:36:55.28,EN,,0,0,0,,The value for looking from this point of view\nDialogue: 0,0:36:55.28,0:36:58.64,EN,,0,0,0,,and m is one. And the value, looking from this point of view, of x is three.\nDialogue: 0,0:37:02.22,0:37:03.15,EN,,0,0,0,,So there we have\nDialogue: 0,0:37:03.15,0:37:05.52,EN,,0,0,0,,a very simple environment structure made out of frames.\nDialogue: 0,0:37:06.38,0:37:09.80,EN,,0,0,0,,These correspond to the applications of procedures.\nDialogue: 0,0:37:10.94,0:37:12.17,EN,,0,0,0,,And we'll see that in a second.\nDialogue: 0,0:37:14.41,0:37:17.60,EN,,0,0,0,,So now I have to make you some other nice little structure that we build.\nDialogue: 0,0:37:20.75,0:37:21.71,EN,,0,0,0,,Next slide,\nDialogue: 0,0:37:22.14,0:37:24.36,EN,,0,0,0,,we see an object,\nDialogue: 0,0:37:24.84,0:37:26.54,EN,,0,0,0,,which I'm going to draw procedures.\nDialogue: 0,0:37:27.93,0:37:28.94,EN,,0,0,0,,This is a procedure.\nDialogue: 0,0:37:30.11,0:37:31.90,EN,,0,0,0,,A procedure is made out of two parts.\nDialogue: 0,0:37:33.10,0:37:34.80,EN,,0,0,0,,It's sort of like a cons.\nDialogue: 0,0:37:37.21,0:37:38.38,EN,,0,0,0,,However, it's the two parts.\nDialogue: 0,0:37:40.84,0:37:44.72,EN,,0,0,0,,The first part refers to some code,\nDialogue: 0,0:37:45.69,0:37:46.94,EN,,0,0,0,,something that can be executed,\nDialogue: 0,0:37:47.42,0:37:50.00,EN,,0,0,0,,a set of instructions, if you will. You can think of it that way.\nDialogue: 0,0:37:50.68,0:37:52.83,EN,,0,0,0,,And the second part is the environment.\nDialogue: 0,0:37:53.88,0:37:55.50,EN,,0,0,0,,The procedure is the whole thing.\nDialogue: 0,0:37:57.16,0:37:58.40,EN,,0,0,0,,And we're going to have to use this\nDialogue: 0,0:37:58.71,0:38:05.16,EN,,0,0,0,,to capture the values of the free variables that occur in the procedure.\nDialogue: 0,0:38:06.17,0:38:08.09,EN,,0,0,0,,If a variable occurs in the procedure\nDialogue: 0,0:38:08.11,0:38:09.92,EN,,0,0,0,,it's either bound in that procedure or free.\nDialogue: 0,0:38:11.10,0:38:11.96,EN,,0,0,0,,If it's bound,\nDialogue: 0,0:38:12.57,0:38:14.56,EN,,0,0,0,,then the value will somehow be easy to find.\nDialogue: 0,0:38:16.11,0:38:18.64,EN,,0,0,0,,It will be in some easy environment to get at.\nDialogue: 0,0:38:18.91,0:38:19.87,EN,,0,0,0,,If it's free,\nDialogue: 0,0:38:20.86,0:38:23.02,EN,,0,0,0,,we're going to have to have something that goes with the procedure\nDialogue: 0,0:38:23.02,0:38:24.81,EN,,0,0,0,,that says where we'll go look for its value.\nDialogue: 0,0:38:27.05,0:38:29.21,EN,,0,0,0,,And the reasons why are not obvious yet,\nDialogue: 0,0:38:29.21,0:38:30.60,EN,,0,0,0,,but will be soon.\nDialogue: 0,0:38:32.32,0:38:34.97,EN,,0,0,0,,So here's a procedure object. It's a composite object\nDialogue: 0,0:38:35.34,0:38:41.64,EN,,0,0,0,,consisting of a piece of code and a environment structure.\nDialogue: 0,0:38:42.72,0:38:45.50,EN,,0,0,0,,Now I will tell you the new rules, the complete new rules,\nDialogue: 0,0:38:46.41,0:38:47.47,EN,,0,0,0,,for evaluation.\nDialogue: 0,0:38:50.54,0:38:52.20,EN,,0,0,0,,The first rule is-- there's only two of them.\nDialogue: 0,0:38:53.20,0:38:55.39,EN,,0,0,0,,These correspond to the substitution model rules.\nDialogue: 0,0:38:57.26,0:38:59.32,EN,,0,0,0,,And the first one has to do with\nDialogue: 0,0:38:59.66,0:39:02.78,EN,,0,0,0,,how do you apply a procedure to its arguments?\nDialogue: 0,0:39:05.28,0:39:08.54,EN,,0,0,0,,Okay, And a procedural object is applied to a set of arguments\nDialogue: 0,0:39:08.96,0:39:10.43,EN,,0,0,0,,by constructing a new frame.\nDialogue: 0,0:39:11.31,0:39:15.76,EN,,0,0,0,,That frame will contain the mapping of the former parameters to the actual parameters\nDialogue: 0,0:39:15.83,0:39:19.48,EN,,0,0,0,,of the arguments that were supplied in the call.\nDialogue: 0,0:39:21.42,0:39:22.20,EN,,0,0,0,,As you know,\nDialogue: 0,0:39:22.31,0:39:26.94,EN,,0,0,0,,when we make up a call to a procedure like lambda x times x y,\nDialogue: 0,0:39:26.94,0:39:29.13,EN,,0,0,0,,and we call that with the argument three,\nDialogue: 0,0:39:30.19,0:39:32.75,EN,,0,0,0,,then we're going to need some mapping of x to three.\nDialogue: 0,0:39:34.19,0:39:37.39,EN,,0,0,0,,It's the same thing as later substituting, if you will\nDialogue: 0,0:39:38.27,0:39:40.30,EN,,0,0,0,,the three for the x in the old model.\nDialogue: 0,0:39:42.00,0:39:44.80,EN,,0,0,0,,So I'm going to build a frame which contains x equals three\nDialogue: 0,0:39:45.15,0:39:46.60,EN,,0,0,0,,as the information in that frame.\nDialogue: 0,0:39:49.12,0:39:49.71,EN,,0,0,0,,Now,\nDialogue: 0,0:39:50.33,0:39:53.31,EN,,0,0,0,,the body of the procedure will then have to be evaluated which is this,\nDialogue: 0,0:39:54.16,0:39:56.44,EN,,0,0,0,,and will be evaluated in an environment\nDialogue: 0,0:39:57.80,0:40:08.03,EN,,0,0,0,,which is constructed by adjoining the new frame that we just made\nDialogue: 0,0:40:08.54,0:40:11.69,EN,,0,0,0,,to the environment which was part of the procedure that we applied.\nDialogue: 0,0:40:13.15,0:40:15.77,EN,,0,0,0,,So I'm going to make a little example of that here.\nDialogue: 0,0:40:19.20,0:40:24.12,EN,,0,0,0,,Supposing I have some environment.\nDialogue: 0,0:40:25.15,0:40:27.23,EN,,0,0,0,,Here's a frame which represents it.\nDialogue: 0,0:40:27.96,0:40:32.19,EN,,0,0,0,,And some procedure-- which I'm going to draw with circles here because it's easier than little triangles--\nDialogue: 0,0:40:33.04,0:40:36.36,EN,,0,0,0,,Ummm.. sorry, those are rhombuses,\nDialogue: 0,0:40:37.66,0:40:40.78,EN,,0,0,0,,rhomboidal little pieces of fruit jelly or something.\nDialogue: 0,0:40:42.68,0:40:45.32,EN,,0,0,0,,So here's a procedure which takes this environment.\nDialogue: 0,0:40:45.95,0:40:48.16,EN,,0,0,0,,And the procedure has a piece of code,\nDialogue: 0,0:40:48.16,0:40:49.68,EN,,0,0,0,,which is a lambda expression,\nDialogue: 0,0:40:50.12,0:40:51.69,EN,,0,0,0,,which binds x and y\nDialogue: 0,0:40:53.15,0:40:56.43,EN,,0,0,0,,and then executes an expression, e.\nDialogue: 0,0:40:57.93,0:40:58.99,EN,,0,0,0,,And this is the procedure.\nDialogue: 0,0:40:59.56,0:41:00.57,EN,,0,0,0,,We'll call it p.\nDialogue: 0,0:41:01.44,0:41:05.79,EN,,0,0,0,,I wish to apply that procedure to three and four.\nDialogue: 0,0:41:06.38,0:41:08.36,EN,,0,0,0,,So I want to do p of three and four.\nDialogue: 0,0:41:09.76,0:41:12.17,EN,,0,0,0,,What I'm going to do, of course, is make a new frame.\nDialogue: 0,0:41:13.15,0:41:14.12,EN,,0,0,0,,I build a frame\nDialogue: 0,0:41:15.24,0:41:18.28,EN,,0,0,0,,which contains x equals three,\nDialogue: 0,0:41:18.84,0:41:20.51,EN,,0,0,0,,and y equals four.\nDialogue: 0,0:41:21.69,0:41:23.48,EN,,0,0,0,,I'm going to connect that frame\nDialogue: 0,0:41:24.27,0:41:25.37,EN,,0,0,0,,to this frame over here.\nDialogue: 0,0:41:27.63,0:41:28.99,EN,,0,0,0,,And then this environment,\nDialogue: 0,0:41:29.68,0:41:30.97,EN,,0,0,0,,with I will call b,\nDialogue: 0,0:41:31.55,0:41:35.02,EN,,0,0,0,,is the environment in which I will evaluate the body of e.\nDialogue: 0,0:41:39.88,0:41:40.33,EN,,0,0,0,,Now,\nDialogue: 0,0:41:41.95,0:41:45.04,EN,,0,0,0,,e may contain references to x and y and other things.\nDialogue: 0,0:41:46.84,0:41:49.95,EN,,0,0,0,,x and y will have values right here.\nDialogue: 0,0:41:50.70,0:41:52.52,EN,,0,0,0,,Other things will have their values here.\nDialogue: 0,0:41:55.05,0:41:56.25,EN,,0,0,0,,How do we get this frame?\nDialogue: 0,0:41:57.26,0:41:59.26,EN,,0,0,0,,That we do by the construction of procedures\nDialogue: 0,0:41:59.61,0:42:00.60,EN,,0,0,0,,which is the other rule.\nDialogue: 0,0:42:02.03,0:42:04.40,EN,,0,0,0,,And I think that's the next slide.\nDialogue: 0,0:42:05.34,0:42:06.12,EN,,0,0,0,,Rule two,\nDialogue: 0,0:42:07.80,0:42:09.90,EN,,0,0,0,,when a lambda expression is evaluated,\nDialogue: 0,0:42:09.90,0:42:11.76,EN,,0,0,0,,relative to a particular environment--\nDialogue: 0,0:42:14.19,0:42:14.40,EN,,0,0,0,,See,\nDialogue: 0,0:42:15.04,0:42:18.12,EN,,0,0,0,,the way I get a procedure is by evaluating the lambda expression.\nDialogue: 0,0:42:18.19,0:42:19.36,EN,,0,0,0,,Here's a lambda expression.\nDialogue: 0,0:42:20.04,0:42:21.12,EN,,0,0,0,,By evaluating it,\nDialogue: 0,0:42:21.90,0:42:23.96,EN,,0,0,0,,I get a procedure which I can apply to three.\nDialogue: 0,0:42:25.08,0:42:26.65,EN,,0,0,0,,Now this lambda expression\nDialogue: 0,0:42:26.65,0:42:30.38,EN,,0,0,0,,is evaluated in an environment where y is defined.\nDialogue: 0,0:42:31.84,0:42:35.84,EN,,0,0,0,,And I want the body of this which contains a free version of y.\nDialogue: 0,0:42:36.39,0:42:38.36,EN,,0,0,0,,y is free in here,\nDialogue: 0,0:42:38.72,0:42:40.38,EN,,0,0,0,,it's bound over the whole thing,\nDialogue: 0,0:42:41.36,0:42:42.75,EN,,0,0,0,,but it's free over here.\nDialogue: 0,0:42:43.32,0:42:46.24,EN,,0,0,0,,I want that y to be this one.\nDialogue: 0,0:42:47.44,0:42:55.13,EN,,0,0,0,,I evaluate this body of this procedure in the environment where y was created.\nDialogue: 0,0:42:55.32,0:42:58.40,EN,,0,0,0,,That's this kind of thing, because that was done by application.\nDialogue: 0,0:42:59.00,0:42:59.63,EN,,0,0,0,,Now,\nDialogue: 0,0:43:00.24,0:43:02.60,EN,,0,0,0,,if I ever want to look up the value of y,\nDialogue: 0,0:43:03.10,0:43:04.09,EN,,0,0,0,,I have to know where it is.\nDialogue: 0,0:43:04.54,0:43:06.42,EN,,0,0,0,,Therefore, this procedural was created,\nDialogue: 0,0:43:06.42,0:43:10.06,EN,,0,0,0,,the creation of the procedure which is the result of evaluating that lambda expression\nDialogue: 0,0:43:10.06,0:43:16.33,EN,,0,0,0,,had better capture a pointer or remember the frame in which y was bound.\nDialogue: 0,0:43:17.92,0:43:19.76,EN,,0,0,0,,So that's what this rule is telling us.\nDialogue: 0,0:43:22.11,0:43:23.13,EN,,0,0,0,,So, for example,\nDialogue: 0,0:43:24.44,0:43:29.32,EN,,0,0,0,,if I happen to be evaluating a lambda expression,\nDialogue: 0,0:43:30.89,0:43:33.32,EN,,0,0,0,,lambda expression in e,\nDialogue: 0,0:43:34.04,0:43:40.46,EN,,0,0,0,,lambda of say, x and y, let's call it g in e,\nDialogue: 0,0:43:41.08,0:43:42.36,EN,,0,0,0,,evaluating that.\nDialogue: 0,0:43:42.97,0:43:46.17,EN,,0,0,0,,all that means is I now construct a procedure object.\nDialogue: 0,0:43:47.10,0:43:48.28,EN,,0,0,0,,e is some environment.\nDialogue: 0,0:43:48.84,0:43:50.94,EN,,0,0,0,,e is something which has a pointer to it.\nDialogue: 0,0:43:51.79,0:43:56.68,EN,,0,0,0,,I construct a procedure object that points up to that environment,\nDialogue: 0,0:43:58.56,0:44:00.11,EN,,0,0,0,,where the code of that\nDialogue: 0,0:44:00.54,0:44:03.24,EN,,0,0,0,,is a lambda expression or whatever that translates into.\nDialogue: 0,0:44:06.24,0:44:07.56,EN,,0,0,0,,And this is the procedure.\nDialogue: 0,0:44:12.38,0:44:14.70,EN,,0,0,0,,So this produces for me-- this -- this\nDialogue: 0,0:44:14.94,0:44:16.37,EN,,0,0,0,,this object here,\nDialogue: 0,0:44:16.37,0:44:18.12,EN,,0,0,0,,this environment pointer,\nDialogue: 0,0:44:18.37,0:44:22.52,EN,,0,0,0,,captures the place where this lambda expression was evaluated,\nDialogue: 0,0:44:22.62,0:44:24.59,EN,,0,0,0,,where the definition was used,\nDialogue: 0,0:44:25.58,0:44:27.40,EN,,0,0,0,,where the definition was used to make a procedure,\nDialogue: 0,0:44:30.32,0:44:31.47,EN,,0,0,0,,to make the procedure.\nDialogue: 0,0:44:32.89,0:44:36.30,EN,,0,0,0,,So it picks up the environment from the place where that procedure was defined,\nDialogue: 0,0:44:37.42,0:44:38.92,EN,,0,0,0,,stores it in the procedure itself,\nDialogue: 0,0:44:39.60,0:44:40.97,EN,,0,0,0,,and then when the procedure is used,\nDialogue: 0,0:44:41.32,0:44:43.47,EN,,0,0,0,,the environment where it was defined is extended\nDialogue: 0,0:44:43.98,0:44:45.07,EN,,0,0,0,,with the new frame.\nDialogue: 0,0:44:48.72,0:44:52.33,EN,,0,0,0,,So this gives us a locus for putting where a variable has a value.\nDialogue: 0,0:44:53.04,0:44:53.96,EN,,0,0,0,,And, for example,\nDialogue: 0,0:44:53.96,0:44:56.81,EN,,0,0,0,,if there are lots of guys pointing in at that environment,\nDialogue: 0,0:44:57.74,0:45:00.33,EN,,0,0,0,,then they share that place.\nDialogue: 0,0:45:01.20,0:45:02.52,EN,,0,0,0,,And we'll see more of that shortly.\nDialogue: 0,0:45:04.01,0:45:05.34,EN,,0,0,0,,Well, now you have a new model\nDialogue: 0,0:45:06.38,0:45:09.92,EN,,0,0,0,,for understanding the execution of programs.\nDialogue: 0,0:45:11.36,0:45:12.78,EN,,0,0,0,,I suppose I'll take questions now,\nDialogue: 0,0:45:13.10,0:45:14.96,EN,,0,0,0,,and then we'll go on and use that for something.\nDialogue: 0,0:45:18.19,0:45:19.52,EN,,0,0,0,,AUDIENCE: Is it right to say then,\nDialogue: 0,0:45:19.52,0:45:23.96,EN,,0,0,0,,the environment is that linked chain of frames starting with--\nDialogue: 0,0:45:23.96,0:45:25.10,EN,,0,0,0,,PROFESSOR: That's right.\nDialogue: 0,0:45:25.48,0:45:26.64,EN,,0,0,0,,AUDIENCE:  working all the way back?\nDialogue: 0,0:45:27.71,0:45:31.45,EN,,0,0,0,,PROFESSOR: Yes, the environment is a sequence of frames linked together.\nDialogue: 0,0:45:32.43,0:45:35.47,EN,,0,0,0,,And the way I like to think about it, it's the pointer to the first one,\nDialogue: 0,0:45:36.88,0:45:38.72,EN,,0,0,0,,because once you've got that you've got them all.\nDialogue: 0,0:45:43.96,0:45:44.65,EN,,0,0,0,,Anybody else?\nDialogue: 0,0:45:45.20,0:45:49.36,EN,,0,0,0,,AUDIENCE: Is it possible to evaluate a procedure or to define a procedure in two different environments\nDialogue: 0,0:45:49.36,0:45:53.20,EN,,0,0,0,,such that it will behave differently, and have pointers to both--\nDialogue: 0,0:45:53.20,0:45:55.77,EN,,0,0,0,,PROFESSOR: Oh, yes. The same procedure is not going to have two different environments.\nDialogue: 0,0:45:56.90,0:45:59.02,EN,,0,0,0,,The same code,\nDialogue: 0,0:45:59.02,0:46:00.82,EN,,0,0,0,,the same lambda expression\nDialogue: 0,0:46:00.82,0:46:03.72,EN,,0,0,0,,can be evaluated in two environments producing two different procedures.\nDialogue: 0,0:46:06.03,0:46:07.18,EN,,0,0,0,,Each procedure--\nDialogue: 0,0:46:07.18,0:46:09.95,EN,,0,0,0,,AUDIENCE: Their definition has the same name. Their operation--\nDialogue: 0,0:46:09.95,0:46:11.92,EN,,0,0,0,,PROFESSOR: The definition is written the same, with the same characters.\nDialogue: 0,0:46:12.56,0:46:14.62,EN,,0,0,0,,I can evaluate that set of characters,\nDialogue: 0,0:46:14.93,0:46:18.14,EN,,0,0,0,,whatever, that list structure that defines,\nDialogue: 0,0:46:18.22,0:46:20.41,EN,,0,0,0,,that is the textual representation.\nDialogue: 0,0:46:20.91,0:46:24.86,EN,,0,0,0,,I can evaluate that in two different environments producing two different procedures.\nDialogue: 0,0:46:25.55,0:46:26.84,EN,,0,0,0,,Each of those procedures\nDialogue: 0,0:46:27.56,0:46:32.19,EN,,0,0,0,,has its own local sets of variables,\nDialogue: 0,0:46:32.34,0:46:33.45,EN,,0,0,0,,and we'll see that right now.\nDialogue: 0,0:46:36.70,0:46:37.36,EN,,0,0,0,,Anybody else?\nDialogue: 0,0:46:42.60,0:46:44.03,EN,,0,0,0,,OK, thank you. Let's take a break.\nDialogue: 0,0:46:47.98,0:46:57.61,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:47:22.67,0:47:25.69,EN,,0,0,0,,Well, now I've done this terrible thing to you.\nDialogue: 0,0:47:26.56,0:47:30.54,EN,,0,0,0,,I've introduced a very complicated thing,\nDialogue: 0,0:47:32.76,0:47:33.42,EN,,0,0,0,,assignment,\nDialogue: 0,0:47:34.51,0:47:38.08,EN,,0,0,0,,which destroys most of the interesting mathematical properties of our programs.\nDialogue: 0,0:47:41.07,0:47:42.46,EN,,0,0,0,,Why should I have done this?\nDialogue: 0,0:47:43.18,0:47:45.02,EN,,0,0,0,,What possible good could this do?\nDialogue: 0,0:47:46.51,0:47:48.86,EN,,0,0,0,,Clearly not a nice thing,\nDialogue: 0,0:47:49.60,0:47:51.23,EN,,0,0,0,,so I better have a good excuse.\nDialogue: 0,0:47:52.83,0:47:54.80,EN,,0,0,0,,Well, let's do a little bit of playing,\nDialogue: 0,0:47:54.80,0:47:58.35,EN,,0,0,0,,first of all, with some very interesting programs that have assignment.\nDialogue: 0,0:47:58.81,0:48:00.88,EN,,0,0,0,,Understand something special about them\nDialogue: 0,0:48:01.42,0:48:02.83,EN,,0,0,0,,that makes them somewhat valuable.\nDialogue: 0,0:48:04.96,0:48:06.70,EN,,0,0,0,,Start with a very simple program\nDialogue: 0,0:48:07.69,0:48:09.28,EN,,0,0,0,,I'm going to call make-counter.\nDialogue: 0,0:48:10.48,0:48:18.19,EN,,0,0,0,,I'm going to define make-counter\nDialogue: 0,0:48:24.17,0:48:28.12,EN,,0,0,0,,to be a procedure of one argument n\nDialogue: 0,0:48:29.23,0:48:32.94,EN,,0,0,0,,which returns as its value a procedure of no arguments--\nDialogue: 0,0:48:34.36,0:48:36.03,EN,,0,0,0,,a procedure that produces a procedure--\nDialogue: 0,0:48:36.84,0:48:44.35,EN,,0,0,0,,which sets n to the increment of n\nDialogue: 0,0:48:47.88,0:48:49.77,EN,,0,0,0,,and returns that value of n.\nDialogue: 0,0:48:55.37,0:48:57.54,EN,,0,0,0,,Now we're going to investigate the behavior of this.\nDialogue: 0,0:48:57.54,0:48:59.02,EN,,0,0,0,,It's a sort of interesting thing.\nDialogue: 0,0:48:59.82,0:49:01.45,EN,,0,0,0,,In order to investigate the behavior,\nDialogue: 0,0:49:01.45,0:49:03.08,EN,,0,0,0,,I have to make an environment model,\nDialogue: 0,0:49:04.11,0:49:05.98,EN,,0,0,0,,because we can't understand this any other way.\nDialogue: 0,0:49:08.65,0:49:09.63,EN,,0,0,0,,So let's just do that.\nDialogue: 0,0:49:10.00,0:49:12.86,EN,,0,0,0,,We start out with some sort of--\nDialogue: 0,0:49:13.24,0:49:15.90,EN,,0,0,0,,let's say there is a global environment that the machine is born with.\nDialogue: 0,0:49:16.13,0:49:17.12,EN,,0,0,0,,Global we'll call it.\nDialogue: 0,0:49:20.03,0:49:24.25,EN,,0,0,0,,And it's going to have in it a bunch of initial things.\nDialogue: 0,0:49:24.44,0:49:25.60,EN,,0,0,0,,We all know what it's got.\nDialogue: 0,0:49:25.72,0:49:30.88,EN,,0,0,0,,It's got things in it like say, plus, and times,\nDialogue: 0,0:49:32.24,0:49:37.26,EN,,0,0,0,,and quotient, and difference, and CAR,\nDialogue: 0,0:49:38.70,0:49:39.74,EN,,0,0,0,,and etcetera,\nDialogue: 0,0:49:41.45,0:49:42.48,EN,,0,0,0,,lots of things.\nDialogue: 0,0:49:42.88,0:49:43.98,EN,,0,0,0,,I don't know what they are,\nDialogue: 0,0:49:44.42,0:49:45.55,EN,,0,0,0,,some various squiggles\nDialogue: 0,0:49:46.08,0:49:48.88,EN,,0,0,0,,that are the things the machine is born with.\nDialogue: 0,0:49:51.21,0:49:53.23,EN,,0,0,0,,And by doing the definition here,\nDialogue: 0,0:49:54.68,0:49:55.76,EN,,0,0,0,,what I plan to do--\nDialogue: 0,0:49:56.32,0:49:57.31,EN,,0,0,0,,Well, what am I doing?\nDialogue: 0,0:49:57.31,0:49:59.58,EN,,0,0,0,,I'm doing this relative to the global environment.\nDialogue: 0,0:49:59.72,0:50:01.29,EN,,0,0,0,,So here's my environment pointer.\nDialogue: 0,0:50:03.72,0:50:06.70,EN,,0,0,0,,In order to do that I have to evaluate this lambda expression.\nDialogue: 0,0:50:08.35,0:50:10.01,EN,,0,0,0,,That means I make a procedure object.\nDialogue: 0,0:50:11.50,0:50:13.26,EN,,0,0,0,,So I'm going to make a procedure object here.\nDialogue: 0,0:50:17.36,0:50:18.68,EN,,0,0,0,,And the procedure object has,\nDialogue: 0,0:50:18.72,0:50:20.49,EN,,0,0,0,,as the place it's defined,\nDialogue: 0,0:50:21.16,0:50:22.35,EN,,0,0,0,,the global environment.\nDialogue: 0,0:50:24.06,0:50:25.79,EN,,0,0,0,,The procedure object contains\nDialogue: 0,0:50:28.16,0:50:31.47,EN,,0,0,0,,some code that represents a procedure of one argument n\nDialogue: 0,0:50:31.96,0:50:35.34,EN,,0,0,0,,which returns a procedure of no arguments which does something.\nDialogue: 0,0:50:38.24,0:50:43.28,EN,,0,0,0,,And the define is a way of changing this environment,\nDialogue: 0,0:50:44.32,0:50:46.73,EN,,0,0,0,,so that I now add to it a make-counter,\nDialogue: 0,0:50:52.28,0:50:55.05,EN,,0,0,0,,a special rule for the special thing defined.\nDialogue: 0,0:50:55.82,0:50:56.94,EN,,0,0,0,,But what that is,\nDialogue: 0,0:50:58.94,0:51:01.96,EN,,0,0,0,,is it gives me that pointer to that procedure.\nDialogue: 0,0:51:03.82,0:51:06.32,EN,,0,0,0,,So now the global environment contains make-counter as well.\nDialogue: 0,0:51:09.28,0:51:11.21,EN,,0,0,0,,Now, we're going to do some operations.\nDialogue: 0,0:51:11.87,0:51:13.50,EN,,0,0,0,,I'm going to use this to make some counters.\nDialogue: 0,0:51:14.99,0:51:16.20,EN,,0,0,0,,We'll see what a counter is.\nDialogue: 0,0:51:17.12,0:51:18.51,EN,,0,0,0,,So let's define\nDialogue: 0,0:51:23.32,0:51:26.65,EN,,0,0,0,,c1 to be a counter beginning at 0.\nDialogue: 0,0:51:35.72,0:51:38.38,EN,,0,0,0,,Well, we know how to do this now, according to the model.\nDialogue: 0,0:51:39.63,0:51:44.33,EN,,0,0,0,,I have to evaluate the expression make-counter in the global environment,\nDialogue: 0,0:51:45.40,0:51:46.27,EN,,0,0,0,,make-counter of 0.\nDialogue: 0,0:51:47.80,0:51:51.10,EN,,0,0,0,,Well, I look up make-counter and see that it's a procedure.\nDialogue: 0,0:51:53.61,0:51:55.29,EN,,0,0,0,,I'm going to have to apply that procedure.\nDialogue: 0,0:51:56.22,0:51:57.74,EN,,0,0,0,,The way I apply the procedure\nDialogue: 0,0:51:58.43,0:51:59.96,EN,,0,0,0,,is by constructing a frame.\nDialogue: 0,0:52:01.80,0:52:03.79,EN,,0,0,0,,Okay? So I construct a frame\nDialogue: 0,0:52:06.59,0:52:10.44,EN,,0,0,0,,which has a value for n in it\nDialogue: 0,0:52:11.77,0:52:12.64,EN,,0,0,0,,which is 0\nDialogue: 0,0:52:14.00,0:52:15.34,EN,,0,0,0,,and the parent environment\nDialogue: 0,0:52:15.87,0:52:19.32,EN,,0,0,0,,is the one which is the environment of definition of make-counter.\nDialogue: 0,0:52:23.93,0:52:28.36,EN,,0,0,0,,So I've made an environment by applying make-counter to 0.\nDialogue: 0,0:52:31.45,0:52:34.40,EN,,0,0,0,,Now, I have to evaluate the body of make-counter,\nDialogue: 0,0:52:34.41,0:52:37.72,EN,,0,0,0,,which is this lambda expression, in that environment.\nDialogue: 0,0:52:40.64,0:52:42.30,EN,,0,0,0,,Well evaluating this body,\nDialogue: 0,0:52:42.76,0:52:44.59,EN,,0,0,0,,this body is a lambda expression.\nDialogue: 0,0:52:46.28,0:52:48.86,EN,,0,0,0,,Evaluate a lambda expression means make a procedure object.\nDialogue: 0,0:52:49.56,0:52:51.00,EN,,0,0,0,,So I'm going to make a procedure object.\nDialogue: 0,0:52:56.76,0:52:58.29,EN,,0,0,0,,And that procedure object has\nDialogue: 0,0:52:58.29,0:53:00.46,EN,,0,0,0,,the environment it was defined in being that,\nDialogue: 0,0:53:04.20,0:53:05.88,EN,,0,0,0,,where n was defined to be 0.\nDialogue: 0,0:53:07.68,0:53:08.80,EN,,0,0,0,,And it has some code,\nDialogue: 0,0:53:08.83,0:53:11.37,EN,,0,0,0,,which is the procedure of no arguments\nDialogue: 0,0:53:11.40,0:53:15.28,EN,,0,0,0,,which does something, then sets something,\nDialogue: 0,0:53:15.28,0:53:16.73,EN,,0,0,0,,and returns n.\nDialogue: 0,0:53:17.88,0:53:18.81,EN,,0,0,0,,And this thing\nDialogue: 0,0:53:19.42,0:53:21.23,EN,,0,0,0,,is going to be the object,\nDialogue: 0,0:53:21.92,0:53:24.67,EN,,0,0,0,,which in the global environment, will have the name c1.\nDialogue: 0,0:53:26.12,0:53:28.33,EN,,0,0,0,,So we construct a name here, c1,\nDialogue: 0,0:53:28.64,0:53:32.14,EN,,0,0,0,,and say that equals that.\nDialogue: 0,0:53:35.48,0:53:37.36,EN,,0,0,0,,Now, but also make another counter,\nDialogue: 0,0:53:43.04,0:53:45.13,EN,,0,0,0,,c2 to be make-counter\nDialogue: 0,0:53:50.94,0:53:52.19,EN,,0,0,0,,say, starting with 10.\nDialogue: 0,0:53:54.25,0:53:55.90,EN,,0,0,0,,Then I do essentially the same thing.\nDialogue: 0,0:53:56.64,0:54:00.40,EN,,0,0,0,,I apply the make-counter procedure, which I got from here,\nDialogue: 0,0:54:00.99,0:54:04.52,EN,,0,0,0,,to make another frame with n being 10.\nDialogue: 0,0:54:05.63,0:54:09.18,EN,,0,0,0,,That frame has the global environment as its parent.\nDialogue: 0,0:54:10.04,0:54:11.80,EN,,0,0,0,,I then construct a procedure\nDialogue: 0,0:54:13.04,0:54:17.63,EN,,0,0,0,,which has that as it's frame of definition.\nDialogue: 0,0:54:18.27,0:54:21.66,EN,,0,0,0,,The code of it is\nDialogue: 0,0:54:21.80,0:54:24.38,EN,,0,0,0,,the procedure of no arguments which does something.\nDialogue: 0,0:54:25.54,0:54:28.60,EN,,0,0,0,,And it does a set, and so on.\nDialogue: 0,0:54:28.60,0:54:31.22,EN,,0,0,0,,And n comes out. Okay?\nDialogue: 0,0:54:31.45,0:54:34.83,EN,,0,0,0,,And c2 is this.\nDialogue: 0,0:54:36.88,0:54:39.32,EN,,0,0,0,,Well, you're already beginning to see something fairly interesting.\nDialogue: 0,0:54:40.17,0:54:41.92,EN,,0,0,0,,There are two n's here.\nDialogue: 0,0:54:42.92,0:54:44.19,EN,,0,0,0,,They are not one n.\nDialogue: 0,0:54:46.14,0:54:48.16,EN,,0,0,0,,Each time I called make-counter,\nDialogue: 0,0:54:48.64,0:54:50.25,EN,,0,0,0,,I made another instance of n.\nDialogue: 0,0:54:52.62,0:54:54.40,EN,,0,0,0,,These are distinct and separate from each other.\nDialogue: 0,0:54:57.79,0:55:00.28,EN,,0,0,0,,Now, let's do some execution, use those counters.\nDialogue: 0,0:55:05.92,0:55:15.00,EN,,0,0,0,,Well, what happens if I say, c1 at this point?\nDialogue: 0,0:55:15.84,0:55:17.34,EN,,0,0,0,,Well, I go over here,\nDialogue: 0,0:55:17.56,0:55:19.98,EN,,0,0,0,,and I say, oh yes, c1 is a procedure.\nDialogue: 0,0:55:20.64,0:55:22.78,EN,,0,0,0,,I'm going to call this procedure on no arguments,\nDialogue: 0,0:55:23.16,0:55:24.96,EN,,0,0,0,,but it has no parameters.\nDialogue: 0,0:55:24.96,0:55:25.63,EN,,0,0,0,,That's right.\nDialogue: 0,0:55:26.97,0:55:27.84,EN,,0,0,0,,What's its body?\nDialogue: 0,0:55:27.96,0:55:30.02,EN,,0,0,0,,Well, I have to look over here, because I didn't write it down.\nDialogue: 0,0:55:30.02,0:55:32.65,EN,,0,0,0,,It said, set n to one plus n\nDialogue: 0,0:55:33.80,0:55:34.89,EN,,0,0,0,,and return n,\nDialogue: 0,0:55:37.12,0:55:38.12,EN,,0,0,0,,increment n.\nDialogue: 0,0:55:38.97,0:55:41.60,EN,,0,0,0,,Well, the n it says is this one.\nDialogue: 0,0:55:43.08,0:55:44.60,EN,,0,0,0,,So I increment that n.\nDialogue: 0,0:55:45.80,0:55:47.00,EN,,0,0,0,,That becomes one,\nDialogue: 0,0:55:48.64,0:55:50.24,EN,,0,0,0,,and I return the value one.\nDialogue: 0,0:55:53.13,0:55:56.49,EN,,0,0,0,,Supposing I then called c2.\nDialogue: 0,0:55:58.38,0:55:59.20,EN,,0,0,0,,Well, what do I do?\nDialogue: 0,0:55:59.23,0:56:03.33,EN,,0,0,0,,I say c2 is this procedure which does the same thing,\nDialogue: 0,0:56:03.33,0:56:04.48,EN,,0,0,0,,but here's the n.\nDialogue: 0,0:56:05.33,0:56:06.57,EN,,0,0,0,,It becomes 11.\nDialogue: 0,0:56:10.97,0:56:14.59,EN,,0,0,0,,And so I have an 11 which is the value.\nDialogue: 0,0:56:15.92,0:56:18.32,EN,,0,0,0,,I then can say, let's try c1 again.\nDialogue: 0,0:56:20.91,0:56:22.56,EN,,0,0,0,,hum, c1 is this,\nDialogue: 0,0:56:23.28,0:56:24.16,EN,,0,0,0,,that's two,\nDialogue: 0,0:56:27.24,0:56:28.30,EN,,0,0,0,,so the answer is two.\nDialogue: 0,0:56:29.66,0:56:30.75,EN,,0,0,0,,And c2\nDialogue: 0,0:56:33.37,0:56:35.31,EN,,0,0,0,,gives me a 12 by the same method,\nDialogue: 0,0:56:35.74,0:56:37.55,EN,,0,0,0,,by walking down here looking at that\nDialogue: 0,0:56:37.55,0:56:39.28,EN,,0,0,0,,and saying, here's the n, I'm incrementing.\nDialogue: 0,0:56:41.64,0:56:43.68,EN,,0,0,0,,So what I have are computational objects.\nDialogue: 0,0:56:45.21,0:56:46.86,EN,,0,0,0,,There are two counters,\nDialogue: 0,0:56:48.96,0:56:51.02,EN,,0,0,0,,each with its own independent local state.\nDialogue: 0,0:56:55.48,0:56:56.62,EN,,0,0,0,,Let's talk about this a little.\nDialogue: 0,0:56:56.64,0:56:58.52,EN,,0,0,0,,This is a strange thing.\nDialogue: 0,0:57:01.12,0:57:02.22,EN,,0,0,0,,What's an object?\nDialogue: 0,0:57:04.11,0:57:06.12,EN,,0,0,0,,It's not at all obvious what an object is.\nDialogue: 0,0:57:07.55,0:57:09.45,EN,,0,0,0,,We like to think about objects,\nDialogue: 0,0:57:11.24,0:57:13.32,EN,,0,0,0,,because it's economical to think that way.\nDialogue: 0,0:57:14.62,0:57:17.28,EN,,0,0,0,,It's an intellectual economy.\nDialogue: 0,0:57:18.57,0:57:19.61,EN,,0,0,0,,I am an object.\nDialogue: 0,0:57:20.99,0:57:22.30,EN,,0,0,0,,You are an object.\nDialogue: 0,0:57:23.55,0:57:25.29,EN,,0,0,0,,We are not the same object.\nDialogue: 0,0:57:27.52,0:57:29.64,EN,,0,0,0,,I can divide the world into two parts,\nDialogue: 0,0:57:29.92,0:57:31.85,EN,,0,0,0,,me and you,\nDialogue: 0,0:57:31.92,0:57:33.31,EN,,0,0,0,,and there's other things as well,\nDialogue: 0,0:57:34.70,0:57:35.26,EN,,0,0,0,,such that\nDialogue: 0,0:57:35.44,0:57:39.50,EN,,0,0,0,,most of the things I might want to discuss about my workings\nDialogue: 0,0:57:39.68,0:57:40.89,EN,,0,0,0,,do not involve you,\nDialogue: 0,0:57:41.39,0:57:44.67,EN,,0,0,0,,and most of the things I want to discuss about your workings don't involve me.\nDialogue: 0,0:57:45.66,0:57:46.94,EN,,0,0,0,,I have a blood pressure,\nDialogue: 0,0:57:47.50,0:57:48.38,EN,,0,0,0,,a temperature,\nDialogue: 0,0:57:49.36,0:57:51.48,EN,,0,0,0,,a respiration rate,\nDialogue: 0,0:57:53.34,0:57:54.99,EN,,0,0,0,,certain amount of sugar in my blood,\nDialogue: 0,0:57:56.11,0:57:59.34,EN,,0,0,0,,and numerous, thousands, of state variables-- millions actually,\nDialogue: 0,0:57:59.37,0:58:00.65,EN,,0,0,0,,or I don't know how many--\nDialogue: 0,0:58:00.93,0:58:03.48,EN,,0,0,0,,huge numbers of state variables in the physical sense\nDialogue: 0,0:58:04.91,0:58:07.12,EN,,0,0,0,,which represent the state of me as a particle,\nDialogue: 0,0:58:09.15,0:58:10.64,EN,,0,0,0,,and you have gazillions of them as well.\nDialogue: 0,0:58:12.68,0:58:14.94,EN,,0,0,0,,And most of mine are uncoupled to most of yours.\nDialogue: 0,0:58:17.31,0:58:19.50,EN,,0,0,0,,So we can compute the properties of me\nDialogue: 0,0:58:20.56,0:58:22.83,EN,,0,0,0,,without worrying too much about the properties of you.\nDialogue: 0,0:58:23.82,0:58:25.77,EN,,0,0,0,,If we had to work about both of us together,\nDialogue: 0,0:58:25.96,0:58:27.82,EN,,0,0,0,,than the number of states that we have to consider\nDialogue: 0,0:58:27.82,0:58:30.01,EN,,0,0,0,,is the product of the number of states you have and the number of states I have.\nDialogue: 0,0:58:30.52,0:58:32.11,EN,,0,0,0,,But this way it's almost a sum.\nDialogue: 0,0:58:32.65,0:58:35.34,EN,,0,0,0,,Now, indeed there are forces that couple us.\nDialogue: 0,0:58:36.00,0:58:37.95,EN,,0,0,0,,I'm talking to you and your state changes.\nDialogue: 0,0:58:38.44,0:58:40.09,EN,,0,0,0,,I'm looking at you and my state changes.\nDialogue: 0,0:58:41.72,0:58:44.08,EN,,0,0,0,,Some of my state variables, a very few of them,\nDialogue: 0,0:58:44.33,0:58:46.07,EN,,0,0,0,,therefore, are coupled to yours.\nDialogue: 0,0:58:46.07,0:58:47.80,EN,,0,0,0,,If you were to suddenly yell very loud,\nDialogue: 0,0:58:47.80,0:58:48.88,EN,,0,0,0,,my blood pressure would go up.\nDialogue: 0,0:58:54.30,0:58:56.86,EN,,0,0,0,,However, and it may not be always appropriate\nDialogue: 0,0:58:57.17,0:59:01.16,EN,,0,0,0,,to think about the world as being made out of independent states and independent particles.\nDialogue: 0,0:59:02.12,0:59:04.46,EN,,0,0,0,,Lots of the bugs that occur in things like quantum mechanics,\nDialogue: 0,0:59:05.23,0:59:08.70,EN,,0,0,0,,or the bugs in our minds that occur when we think about things like quantum mechanics,\nDialogue: 0,0:59:08.89,0:59:10.97,EN,,0,0,0,,are due the fact that we are trying to think about things\nDialogue: 0,0:59:10.97,0:59:12.96,EN,,0,0,0,,being broken up into independent pieces,\nDialogue: 0,0:59:13.58,0:59:17.32,EN,,0,0,0,,when in fact there's more coupling than we see on the surface,\nDialogue: 0,0:59:18.01,0:59:19.44,EN,,0,0,0,,or that we want to believe in,\nDialogue: 0,0:59:19.61,0:59:21.69,EN,,0,0,0,,because we want to compute efficiently and effectively.\nDialogue: 0,0:59:22.19,0:59:23.82,EN,,0,0,0,,We've been trained to think that way.\nDialogue: 0,0:59:29.76,0:59:30.51,EN,,0,0,0,,Well, let's see.\nDialogue: 0,0:59:31.50,0:59:33.44,EN,,0,0,0,,How would we know if we had objects at all?\nDialogue: 0,0:59:35.12,0:59:37.34,EN,,0,0,0,,How can we tell if we have objects?\nDialogue: 0,0:59:37.64,0:59:41.45,EN,,0,0,0,,Consider some possible optical illusions.\nDialogue: 0,0:59:42.46,0:59:43.13,EN,,0,0,0,,This could be done.\nDialogue: 0,0:59:45.04,0:59:47.69,EN,,0,0,0,,These pieces of chalk are not appropriately identical,\nDialogue: 0,0:59:47.76,0:59:50.20,EN,,0,0,0,,but supposing you couldn't tell the difference of them by looking at them.\nDialogue: 0,0:59:52.04,0:59:53.32,EN,,0,0,0,,Well, there's a possibility\nDialogue: 0,0:59:53.32,0:59:55.16,EN,,0,0,0,,that this all a game I'm playing with mirrors.\nDialogue: 0,0:59:56.07,0:59:57.60,EN,,0,0,0,,It's really the same piece of chalk,\nDialogue: 0,0:59:59.36,1:00:00.48,EN,,0,0,0,,but you're seeing two of them.\nDialogue: 0,1:00:01.61,1:00:03.87,EN,,0,0,0,,How would you know if you're seeing one or two?\nDialogue: 0,1:00:05.04,1:00:06.70,EN,,0,0,0,,Well, there's only one way I know.\nDialogue: 0,1:00:07.37,1:00:08.94,EN,,0,0,0,,You grab one of them and change it\nDialogue: 0,1:00:09.45,1:00:10.67,EN,,0,0,0,,and see if the other one changed.\nDialogue: 0,1:00:14.01,1:00:14.67,EN,,0,0,0,,And it didn't,\nDialogue: 0,1:00:15.50,1:00:16.14,EN,,0,0,0,,so there's two of them.\nDialogue: 0,1:00:19.50,1:00:20.16,EN,,0,0,0,,And, on the other hand,\nDialogue: 0,1:00:20.17,1:00:22.20,EN,,0,0,0,,there is some other screwy properties of things like that.\nDialogue: 0,1:00:22.57,1:00:24.01,EN,,0,0,0,,Like, how do we know if something changed?\nDialogue: 0,1:00:25.00,1:00:27.93,EN,,0,0,0,,We have to look at it before and after the change.\nDialogue: 0,1:00:28.65,1:00:30.02,EN,,0,0,0,,The change is an assignment,\nDialogue: 0,1:00:30.02,1:00:31.45,EN,,0,0,0,,it's a moment in time.\nDialogue: 0,1:00:32.14,1:00:34.60,EN,,0,0,0,,But that means we have to know it was the same one that we're looking at.\nDialogue: 0,1:00:36.51,1:00:38.84,EN,,0,0,0,,So some very strange, and unusual,\nDialogue: 0,1:00:38.84,1:00:40.38,EN,,0,0,0,,and obscure, and -- I don't understand\nDialogue: 0,1:00:40.84,1:00:43.52,EN,,0,0,0,,the problems associated with assignment,\nDialogue: 0,1:00:44.45,1:00:46.28,EN,,0,0,0,,and change, and objects.\nDialogue: 0,1:00:47.29,1:00:48.99,EN,,0,0,0,,These could get very, very bad.\nDialogue: 0,1:00:51.40,1:00:52.12,EN,,0,0,0,,For example,\nDialogue: 0,1:00:53.31,1:00:55.60,EN,,0,0,0,,here I am, I am a particular person,\nDialogue: 0,1:00:56.16,1:00:57.72,EN,,0,0,0,,a particular object, okay?\nDialogue: 0,1:00:57.96,1:00:59.31,EN,,0,0,0,,Now, I can take out my knife,\nDialogue: 0,1:01:00.68,1:01:01.77,EN,,0,0,0,,and cut my fingernail.\nDialogue: 0,1:01:01.89,1:01:04.81,EN,,0,0,0,,Alright? A piece of my fingernail has fallen off onto the table.\nDialogue: 0,1:01:05.93,1:01:10.16,EN,,0,0,0,,I believe I am the same person I was a second ago,\nDialogue: 0,1:01:10.97,1:01:12.81,EN,,0,0,0,,but I'm not physically the same in the slightest.\nDialogue: 0,1:01:14.46,1:01:15.43,EN,,0,0,0,,I have changed.\nDialogue: 0,1:01:15.58,1:01:16.65,EN,,0,0,0,,Why am I the same?\nDialogue: 0,1:01:18.11,1:01:19.40,EN,,0,0,0,,What is the identity of me?\nDialogue: 0,1:01:20.96,1:01:23.50,EN,,0,0,0,,I don't know...Okay?\nDialogue: 0,1:01:25.05,1:01:27.88,EN,,0,0,0,,Except for the fact that I have some sort of identity.\nDialogue: 0,1:01:29.71,1:01:33.04,EN,,0,0,0,,And so, I think by introducing assignment and objects,\nDialogue: 0,1:01:33.64,1:01:38.28,EN,,0,0,0,,we have opened ourselves up to all the horrible questions of philosophy\nDialogue: 0,1:01:38.41,1:01:42.24,EN,,0,0,0,,that have been plaguing philosophers for some thousands of years about this sort of thing.\nDialogue: 0,1:01:43.42,1:01:44.99,EN,,0,0,0,,It's why mathematics is a lot cleaner.\nDialogue: 0,1:01:45.69,1:01:50.24,EN,,0,0,0,,Let's look at the best things I know to say about actions and identity.\nDialogue: 0,1:01:52.44,1:01:55.39,EN,,0,0,0,,We say that an action, a, had an effect on an object, x,\nDialogue: 0,1:01:55.77,1:01:56.70,EN,,0,0,0,,or equivalently,\nDialogue: 0,1:01:56.92,1:01:58.41,EN,,0,0,0,,that x was changed by a,\nDialogue: 0,1:01:58.89,1:02:01.66,EN,,0,0,0,,if some property, p, which was true of x before a,\nDialogue: 0,1:02:01.87,1:02:03.76,EN,,0,0,0,,became false of x after a.\nDialogue: 0,1:02:04.99,1:02:05.63,EN,,0,0,0,,That's test.\nDialogue: 0,1:02:06.62,1:02:09.66,EN,,0,0,0,,It still means I have to have the x before and after.\nDialogue: 0,1:02:10.91,1:02:12.54,EN,,0,0,0,,Or, the other way of saying this is,\nDialogue: 0,1:02:12.94,1:02:14.94,EN,,0,0,0,,we say that two objects x and y are the same for any action\nDialogue: 0,1:02:14.97,1:02:17.93,EN,,0,0,0,,which has an effect on x has the same effect on y\nDialogue: 0,1:02:19.63,1:02:21.39,EN,,0,0,0,,However, objects are very useful,\nDialogue: 0,1:02:21.44,1:02:23.18,EN,,0,0,0,,as I said, for intellectual economy.\nDialogue: 0,1:02:24.64,1:02:27.12,EN,,0,0,0,,One of the things that's incredibly useful about them,\nDialogue: 0,1:02:28.27,1:02:29.44,EN,,0,0,0,,is that the world\nDialogue: 0,1:02:30.78,1:02:34.80,EN,,0,0,0,,is made out of independent objects with independent local state.\nDialogue: 0,1:02:35.00,1:02:37.28,EN,,0,0,0,,We like to think that way, although it isn't completely true.\nDialogue: 0,1:02:39.68,1:02:42.03,EN,,0,0,0,,When we want to make very complicated programs\nDialogue: 0,1:02:42.03,1:02:43.26,EN,,0,0,0,,that deal with such a world,\nDialogue: 0,1:02:43.98,1:02:46.44,EN,,0,0,0,,if we want those programs to be understandable by us\nDialogue: 0,1:02:46.91,1:02:48.14,EN,,0,0,0,,and also to be changeable,\nDialogue: 0,1:02:48.73,1:02:51.12,EN,,0,0,0,,so that if we change the world we change the program only a little bit,\nDialogue: 0,1:02:51.39,1:02:53.70,EN,,0,0,0,,then we want there to be connections, isomorphism,\nDialogue: 0,1:02:53.82,1:02:56.88,EN,,0,0,0,,between the objects in the world and the objects in our mental model.\nDialogue: 0,1:02:58.76,1:03:01.44,EN,,0,0,0,,The modularity of the world can give us the modularity in our programming.\nDialogue: 0,1:03:02.41,1:03:05.36,EN,,0,0,0,,So we invent things called object-oriented programming and things like that\nDialogue: 0,1:03:05.88,1:03:08.36,EN,,0,0,0,,to provide us with that power.\nDialogue: 0,1:03:10.06,1:03:10.94,EN,,0,0,0,,But it's even easier.\nDialogue: 0,1:03:10.94,1:03:12.25,EN,,0,0,0,,Let's play a little game.\nDialogue: 0,1:03:12.27,1:03:13.18,EN,,0,0,0,,I want to play a little game,\nDialogue: 0,1:03:13.39,1:03:15.77,EN,,0,0,0,,show you an even easier example\nDialogue: 0,1:03:16.00,1:03:21.74,EN,,0,0,0,,or where modularity can be enhanced by using an assignment statement, judiciously.\nDialogue: 0,1:03:22.86,1:03:25.35,EN,,0,0,0,,One thing I want to enforce and impress on you,\nDialogue: 0,1:03:25.45,1:03:27.44,EN,,0,0,0,,is don't use assignment statements the way\nDialogue: 0,1:03:27.45,1:03:29.79,EN,,0,0,0,,you use it in FORTRAN or Basic or something or Pascal,\nDialogue: 0,1:03:30.00,1:03:31.71,EN,,0,0,0,,to do the things you don't have to do with it.\nDialogue: 0,1:03:34.04,1:03:36.62,EN,,0,0,0,,It's not the right way to think for most things.\nDialogue: 0,1:03:36.97,1:03:38.28,EN,,0,0,0,,Sometimes it's essential,\nDialogue: 0,1:03:38.68,1:03:39.69,EN,,0,0,0,,or maybe it's essential.\nDialogue: 0,1:03:39.69,1:03:40.97,EN,,0,0,0,,We'll see more about that too.\nDialogue: 0,1:03:42.24,1:03:44.22,EN,,0,0,0,,OK, let me show you a fun game here.\nDialogue: 0,1:03:47.61,1:03:49.42,EN,,0,0,0,,There was a mathematician\nDialogue: 0,1:03:49.68,1:03:53.69,EN,,0,0,0,,by the name of Cesaro--or Cesaro, Cesaro I suppose it is--\nDialogue: 0,1:03:54.48,1:03:57.45,EN,,0,0,0,,who figured out a clever way of computing pi.\nDialogue: 0,1:03:58.38,1:04:04.30,EN,,0,0,0,,It turns out that if I take two random numbers\nDialogue: 0,1:04:05.24,1:04:06.94,EN,,0,0,0,,two integers at random,\nDialogue: 0,1:04:07.74,1:04:09.48,EN,,0,0,0,,and compute the greatest common divisor,\nDialogue: 0,1:04:10.94,1:04:13.24,EN,,0,0,0,,their greatest common divisor is either one or it's not one.\nDialogue: 0,1:04:13.84,1:04:15.64,EN,,0,0,0,,If it's one, then they have no common divisors.\nDialogue: 0,1:04:18.14,1:04:20.68,EN,,0,0,0,,If their greatest common divisor is one--\nDialogue: 0,1:04:21.12,1:04:23.09,EN,,0,0,0,,the probability that two random numbers,\nDialogue: 0,1:04:23.09,1:04:26.38,EN,,0,0,0,,two numbers chosen at random, has as greatest common divisor one\nDialogue: 0,1:04:26.58,1:04:27.82,EN,,0,0,0,,is related to pi.\nDialogue: 0,1:04:29.32,1:04:30.11,EN,,0,0,0,,In fact--\nDialogue: 0,1:04:31.11,1:04:32.33,EN,,0,0,0,,yes, it's very strange--\nDialogue: 0,1:04:32.94,1:04:34.41,EN,,0,0,0,,of course there are other ways of computing pi,\nDialogue: 0,1:04:34.41,1:04:38.94,EN,,0,0,0,,like dropping pins on flags, and things like that, and sort of the same kind of thing.\nDialogue: 0,1:04:40.19,1:04:48.97,EN,,0,0,0,,So the probability of that the GCD of number one and number two,\nDialogue: 0,1:04:49.44,1:04:51.02,EN,,0,0,0,,two random numbers chosen,\nDialogue: 0,1:04:51.71,1:04:53.66,EN,,0,0,0,,is 6 over pi squared.\nDialogue: 0,1:04:55.61,1:04:56.83,EN,,0,0,0,,I'm not going to try to prove that.\nDialogue: 0,1:04:57.15,1:04:59.64,EN,,0,0,0,,It's actually not too hard and sort of fun.\nDialogue: 0,1:05:01.07,1:05:03.05,EN,,0,0,0,,How would we estimate such probability?\nDialogue: 0,1:05:03.53,1:05:06.46,EN,,0,0,0,,Well, the way we do that, the way we estimate the probabilities,\nDialogue: 0,1:05:07.23,1:05:08.65,EN,,0,0,0,,is by doing lots of experiments,\nDialogue: 0,1:05:09.20,1:05:12.01,EN,,0,0,0,,and then computing the ratios of the ones that come out one way\nDialogue: 0,1:05:12.01,1:05:13.58,EN,,0,0,0,,to the total number of experiments we do.\nDialogue: 0,1:05:16.32,1:05:17.28,EN,,0,0,0,,It's called Monte Carlo,\nDialogue: 0,1:05:18.04,1:05:22.38,EN,,0,0,0,,and it's useful in other contexts for doing things like integrals where you have lots and lots of variables--\nDialogue: 0,1:05:22.94,1:05:25.28,EN,,0,0,0,,the space which is limiting the dimensions you are doing you integral in.\nDialogue: 0,1:05:26.27,1:05:28.70,EN,,0,0,0,,But going back to here,\nDialogue: 0,1:05:29.76,1:05:31.72,EN,,0,0,0,,Let's look at this slide,\nDialogue: 0,1:05:33.96,1:05:36.92,EN,,0,0,0,,We can use Cesaro's method for estimating pi\nDialogue: 0,1:05:37.19,1:05:43.18,EN,,0,0,0,,with n trials by taking the square root of six over a Monte Carlo,\nDialogue: 0,1:05:43.29,1:05:46.46,EN,,0,0,0,,a Monte Carlo experiment with n trials,\nDialogue: 0,1:05:46.80,1:05:50.38,EN,,0,0,0,,with n trials using Cesaro's experiment,\nDialogue: 0,1:05:51.37,1:05:57.56,EN,,0,0,0,,where Cesaro's experiment is the test of whether the GCD of two random numbers--\nDialogue: 0,1:05:58.96,1:06:01.60,EN,,0,0,0,,And you can see that I've already got some assignments in here,\nDialogue: 0,1:06:01.84,1:06:03.13,EN,,0,0,0,,just by what I wrote.\nDialogue: 0,1:06:04.04,1:06:07.49,EN,,0,0,0,,The fact that this word rand, in parentheses,\nDialogue: 0,1:06:07.49,1:06:09.09,EN,,0,0,0,,therefore, that procedure call,\nDialogue: 0,1:06:09.09,1:06:11.39,EN,,0,0,0,,yields a different value than this one,\nDialogue: 0,1:06:11.39,1:06:13.72,EN,,0,0,0,,at least that's what I'm assuming by writing this this way,\nDialogue: 0,1:06:14.62,1:06:16.75,EN,,0,0,0,,indicates that this is not a function,\nDialogue: 0,1:06:18.20,1:06:20.57,EN,,0,0,0,,that there's internal state in it which is changing.\nDialogue: 0,1:06:22.27,1:06:28.64,EN,,0,0,0,,If the GCD of those two random numbers is equal to one,\nDialogue: 0,1:06:28.64,1:06:29.79,EN,,0,0,0,,that's the experiment.\nDialogue: 0,1:06:31.48,1:06:35.18,EN,,0,0,0,,So here I have an experimental method for estimating the value of pi.\nDialogue: 0,1:06:36.51,1:06:39.72,EN,,0,0,0,,Where, I can easily divide this problem into two parts.\nDialogue: 0,1:06:40.02,1:06:44.70,EN,,0,0,0,,One is the specific Monte Carlo experiment of Cesaro, which you just saw,\nDialogue: 0,1:06:44.99,1:06:48.56,EN,,0,0,0,,and the other is the general technique of doing Monte Carlo experiments.\nDialogue: 0,1:06:49.16,1:06:50.27,EN,,0,0,0,,And that's what this is.\nDialogue: 0,1:06:51.04,1:06:55.47,EN,,0,0,0,,If I want to do Monte Carlo experiments with n trials,\nDialogue: 0,1:06:55.67,1:06:58.36,EN,,0,0,0,,a certain number of trials, and a particular experiment,\nDialogue: 0,1:06:59.31,1:07:00.33,EN,,0,0,0,,the way I do that\nDialogue: 0,1:07:00.84,1:07:02.70,EN,,0,0,0,,is I make a little iterative procedure\nDialogue: 0,1:07:03.31,1:07:07.26,EN,,0,0,0,,which has variable the number of trials remaining and the number trials that have been passed,\nDialogue: 0,1:07:08.35,1:07:09.44,EN,,0,0,0,,that I've gotten true.\nDialogue: 0,1:07:10.13,1:07:12.21,EN,,0,0,0,,And if the number remaining is 0,\nDialogue: 0,1:07:12.21,1:07:15.36,EN,,0,0,0,,then the answer is the number past divided by this whole number of trials,\nDialogue: 0,1:07:16.04,1:07:17.52,EN,,0,0,0,,was the estimate of the probability.\nDialogue: 0,1:07:19.07,1:07:20.04,EN,,0,0,0,,And if it's not,\nDialogue: 0,1:07:20.04,1:07:22.08,EN,,0,0,0,,if I have more trials to do,\nDialogue: 0,1:07:22.08,1:07:23.82,EN,,0,0,0,,then let's do one. We do an experiment.\nDialogue: 0,1:07:23.85,1:07:27.30,EN,,0,0,0,,We call the procedure which is experiment on no arguments.\nDialogue: 0,1:07:27.30,1:07:28.43,EN,,0,0,0,,We do the experiment\nDialogue: 0,1:07:29.10,1:07:30.64,EN,,0,0,0,,and then, if that turned out to be true,\nDialogue: 0,1:07:30.82,1:07:32.25,EN,,0,0,0,,we go around the loop\nDialogue: 0,1:07:32.62,1:07:35.42,EN,,0,0,0,,decrementing the number of experiments we have to do by one\nDialogue: 0,1:07:35.70,1:07:37.48,EN,,0,0,0,,and incrementing the number that were passed.\nDialogue: 0,1:07:38.57,1:07:40.11,EN,,0,0,0,,And if the experiment was false,\nDialogue: 0,1:07:40.41,1:07:42.25,EN,,0,0,0,,we just go around the loop\nDialogue: 0,1:07:42.32,1:07:44.38,EN,,0,0,0,,decrementing the number of experiments remaining\nDialogue: 0,1:07:44.44,1:07:46.60,EN,,0,0,0,,and keeping the number passed the same.\nDialogue: 0,1:07:48.76,1:07:54.59,EN,,0,0,0,,We start this up iterating over the total number of trials with 0 experiments past.\nDialogue: 0,1:07:55.42,1:07:57.10,EN,,0,0,0,,A very elegant little program.\nDialogue: 0,1:07:57.74,1:08:00.55,EN,,0,0,0,,And I don't have to just do this with Cesaro's experiment,\nDialogue: 0,1:08:00.55,1:08:02.73,EN,,0,0,0,,it could be lots of Monte Carlo experiments I might do.\nDialogue: 0,1:08:03.36,1:08:07.12,EN,,0,0,0,,Of course, this depends upon the existence of some sort of random number generator.\nDialogue: 0,1:08:07.34,1:08:10.99,EN,,0,0,0,,And random number generators generally look something like this.\nDialogue: 0,1:08:13.60,1:08:16.32,EN,,0,0,0,,There is a random number generator--\nDialogue: 0,1:08:17.42,1:08:25.21,EN,,0,0,0,,is in fact a procedure which is going to do something just like the counter.\nDialogue: 0,1:08:25.61,1:08:27.52,EN,,0,0,0,,It's going to update an x\nDialogue: 0,1:08:28.33,1:08:31.82,EN,,0,0,0,,to the result of applying some function to x,\nDialogue: 0,1:08:32.20,1:08:35.28,EN,,0,0,0,,where this function is some screwy kind of function\nDialogue: 0,1:08:35.39,1:08:40.16,EN,,0,0,0,,that you might find out in Knuth's books on the details of programming.\nDialogue: 0,1:08:41.56,1:08:45.75,EN,,0,0,0,,He does these wonderful books that are full of the details of programming,\nDialogue: 0,1:08:45.75,1:08:48.52,EN,,0,0,0,,because I can't remember how to make a random number generator,\nDialogue: 0,1:08:48.63,1:08:50.62,EN,,0,0,0,,but I can look it up there, and I can find out.\nDialogue: 0,1:08:51.64,1:08:54.01,EN,,0,0,0,,And then, eventually, I return the value of x\nDialogue: 0,1:08:54.08,1:08:57.40,EN,,0,0,0,,which is the state variable internal to the random number generator.\nDialogue: 0,1:08:58.28,1:09:00.75,EN,,0,0,0,,That state variable is initialized somehow,\nDialogue: 0,1:09:01.32,1:09:02.24,EN,,0,0,0,,and has a value.\nDialogue: 0,1:09:03.39,1:09:08.11,EN,,0,0,0,,And this procedure is defined in the context where that variable is bound\nDialogue: 0,1:09:10.41,1:09:15.26,EN,,0,0,0,,So this is a hidden piece of local state that you see here.\nDialogue: 0,1:09:15.87,1:09:20.24,EN,,0,0,0,,And this procedure is defined in that context.\nDialogue: 0,1:09:21.56,1:09:23.66,EN,,0,0,0,,Now, that's a very simple thing to do.\nDialogue: 0,1:09:24.88,1:09:25.79,EN,,0,0,0,,And it's very nice.\nDialogue: 0,1:09:25.99,1:09:27.77,EN,,0,0,0,,Supposing, I didn't want to use assignments.\nDialogue: 0,1:09:29.10,1:09:31.47,EN,,0,0,0,,Supposing, I wanted to write this program without assignments.\nDialogue: 0,1:09:32.73,1:09:33.93,EN,,0,0,0,,What problems would I have?\nDialogue: 0,1:09:35.52,1:09:37.40,EN,,0,0,0,,Well, let's see.\nDialogue: 0,1:09:37.82,1:09:41.10,EN,,0,0,0,,I'd like to use the overhead machine here,\nDialogue: 0,1:09:42.06,1:09:42.70,EN,,0,0,0,,thank you.\nDialogue: 0,1:09:43.47,1:09:47.66,EN,,0,0,0,,First of all, let's look at the whole thing. It's a big story. Right?\nDialogue: 0,1:09:48.01,1:09:49.90,EN,,0,0,0,,Unfortunately, which tells you there is something wrong.\nDialogue: 0,1:09:50.96,1:09:52.75,EN,,0,0,0,,It's at least that big,\nDialogue: 0,1:09:53.42,1:09:54.60,EN,,0,0,0,,and it's monolithic.\nDialogue: 0,1:09:56.76,1:10:00.12,EN,,0,0,0,,You don't have to understand or look at the text there right now\nDialogue: 0,1:10:00.12,1:10:01.39,EN,,0,0,0,,to see that it's monolithic.\nDialogue: 0,1:10:01.92,1:10:04.89,EN,,0,0,0,,It isn't a thing which is Cesaro's experiment.\nDialogue: 0,1:10:04.89,1:10:07.90,EN,,0,0,0,,It's not pulled out from the Monte Carlo process.\nDialogue: 0,1:10:09.87,1:10:11.84,EN,,0,0,0,,It's not separated. Let's look why.\nDialogue: 0,1:10:14.22,1:10:15.85,EN,,0,0,0,,Remember, the constraint here\nDialogue: 0,1:10:15.85,1:10:17.87,EN,,0,0,0,,is that every procedure\nDialogue: 0,1:10:18.69,1:10:22.20,EN,,0,0,0,,return the same value for the same arguments.\nDialogue: 0,1:10:22.97,1:10:24.75,EN,,0,0,0,,Every procedure represents a function.\nDialogue: 0,1:10:26.92,1:10:28.50,EN,,0,0,0,,That's a different kind of constraint.\nDialogue: 0,1:10:28.50,1:10:31.21,EN,,0,0,0,,Because when I have assignments, I can  change some internal state variable.\nDialogue: 0,1:10:31.74,1:10:34.03,EN,,0,0,0,,So let's see how that causes things to go wrong.\nDialogue: 0,1:10:35.04,1:10:36.14,EN,,0,0,0,,Well, start at the beginning.\nDialogue: 0,1:10:37.50,1:10:41.92,EN,,0,0,0,,Ah...The estimate of pi looks sort of the same.\nDialogue: 0,1:10:42.66,1:10:45.88,EN,,0,0,0,,What I'm doing is I take the square root\nDialogue: 0,1:10:46.35,1:10:50.22,EN,,0,0,0,,of six over the random GCD test applied to n\nDialogue: 0,1:10:50.74,1:10:51.93,EN,,0,0,0,,whereas that's what this is.\nDialogue: 0,1:10:52.96,1:10:55.20,EN,,0,0,0,,But here, we are beginning to see something funny.\nDialogue: 0,1:10:55.20,1:10:57.93,EN,,0,0,0,,The random GCD test of a certain number of trials\nDialogue: 0,1:10:58.32,1:10:59.98,EN,,0,0,0,,is just like we had before,\nDialogue: 0,1:11:00.46,1:11:04.66,EN,,0,0,0,,an iteration on the number of trials remaining,\nDialogue: 0,1:11:04.66,1:11:06.80,EN,,0,0,0,,the number of trials that have been passed,\nDialogue: 0,1:11:08.27,1:11:09.71,EN,,0,0,0,,and another variable x.\nDialogue: 0,1:11:10.75,1:11:11.76,EN,,0,0,0,,What's that x?\nDialogue: 0,1:11:12.33,1:11:15.20,EN,,0,0,0,,That x is the state of the random number generator.\nDialogue: 0,1:11:19.00,1:11:21.16,EN,,0,0,0,,And it is now going to be used here.\nDialogue: 0,1:11:21.16,1:11:23.79,EN,,0,0,0,,The same random update function that I have over here\nDialogue: 0,1:11:23.79,1:11:27.15,EN,,0,0,0,,is the one I would have used in a random number generator if I were building it the other way,\nDialogue: 0,1:11:27.71,1:11:29.32,EN,,0,0,0,,the one I get out of Knuth's books.\nDialogue: 0,1:11:31.56,1:11:33.36,EN,,0,0,0,,x is going to get transformed into x1,\nDialogue: 0,1:11:33.37,1:11:34.36,EN,,0,0,0,,I need two random numbers.\nDialogue: 0,1:11:34.81,1:11:36.92,EN,,0,0,0,,And x1 is going to get transformed into x2,\nDialogue: 0,1:11:37.26,1:11:38.44,EN,,0,0,0,,I have two random numbers.\nDialogue: 0,1:11:39.50,1:11:42.14,EN,,0,0,0,,I then have to do exactly what I did before.\nDialogue: 0,1:11:42.52,1:11:44.19,EN,,0,0,0,,I take the GCD of x1 x2.\nDialogue: 0,1:11:44.22,1:11:47.15,EN,,0,0,0,,If that's one, then I go around the loop with X2 being the next value of x.\nDialogue: 0,1:11:54.78,1:11:55.98,EN,,0,0,0,,You see what's happened here\nDialogue: 0,1:11:56.88,1:11:58.70,EN,,0,0,0,,is that the state of the random number generator\nDialogue: 0,1:11:58.73,1:12:01.70,EN,,0,0,0,,is no longer confined to the insides of the random number generator.\nDialogue: 0,1:12:01.80,1:12:02.73,EN,,0,0,0,,It has leaked out.\nDialogue: 0,1:12:03.33,1:12:05.50,EN,,0,0,0,,It has leaked out into my procedure\nDialogue: 0,1:12:05.50,1:12:10.08,EN,,0,0,0,,that does the Monte Carlo experiment.\nDialogue: 0,1:12:10.70,1:12:11.87,EN,,0,0,0,,But what's worse than that,\nDialogue: 0,1:12:11.87,1:12:16.24,EN,,0,0,0,,is it's also, because it was contained inside my experiment itself, Cesaro,\nDialogue: 0,1:12:16.78,1:12:19.48,EN,,0,0,0,,It leaked out that two. Because Cesaro called twice,\nDialogue: 0,1:12:20.86,1:12:22.47,EN,,0,0,0,,has to have a different value each time,\nDialogue: 0,1:12:22.47,1:12:25.16,EN,,0,0,0,,if I going to have a legitimate experimental test.\nDialogue: 0,1:12:26.32,1:12:28.32,EN,,0,0,0,,So Cesaro can't be a function either,\nDialogue: 0,1:12:31.04,1:12:35.69,EN,,0,0,0,,unless I pass it the seed of the random number generator that is going to go wandering around.\nDialogue: 0,1:12:36.52,1:12:39.37,EN,,0,0,0,,So unfortunately, the seed of random number generator\nDialogue: 0,1:12:39.37,1:12:42.77,EN,,0,0,0,,has leaked out into Cesaro, from the random number generator,\nDialogue: 0,1:12:42.88,1:12:45.16,EN,,0,0,0,,that's leaked into the Monte Carlo experiment.\nDialogue: 0,1:12:45.64,1:12:49.12,EN,,0,0,0,,And, unfortunately, my Monte Carlo experiment here is no longer general.\nDialogue: 0,1:12:50.25,1:12:51.80,EN,,0,0,0,,The Monte Carlo experiment here\nDialogue: 0,1:12:52.03,1:12:54.73,EN,,0,0,0,,knows how many random numbers I need to do the experiment.\nDialogue: 0,1:12:58.96,1:12:59.74,EN,,0,0,0,,That's sort of horrible.\nDialogue: 0,1:13:00.08,1:13:02.54,EN,,0,0,0,,I lost an ability to decompose a problem into pieces,\nDialogue: 0,1:13:03.44,1:13:09.12,EN,,0,0,0,,because I wasn't willing to accept the little loop of information,\nDialogue: 0,1:13:09.50,1:13:12.43,EN,,0,0,0,,the feedback process,\nDialogue: 0,1:13:12.88,1:13:15.94,EN,,0,0,0,,that happens inside the random number generator before\nDialogue: 0,1:13:15.94,1:13:21.21,EN,,0,0,0,,that was made by having an assignment to a state variable that was confined to the random number generator.\nDialogue: 0,1:13:22.92,1:13:25.48,EN,,0,0,0,,So the fact that the random number generator is an object,\nDialogue: 0,1:13:25.92,1:13:27.37,EN,,0,0,0,,with an internal state variable,\nDialogue: 0,1:13:28.06,1:13:29.36,EN,,0,0,0,,it's affected by nothing,\nDialogue: 0,1:13:29.37,1:13:31.60,EN,,0,0,0,,but it'll give you something, and it will apply it's force to you,\nDialogue: 0,1:13:32.80,1:13:34.28,EN,,0,0,0,,that was what we're missing now.\nDialogue: 0,1:13:38.00,1:13:40.73,EN,,0,0,0,,OK, well I think we've seen\nDialogue: 0,1:13:40.73,1:13:42.30,EN,,0,0,0,,enough reason for doing this,\nDialogue: 0,1:13:42.83,1:13:45.24,EN,,0,0,0,,and it all sort of looks very wonderful.\nDialogue: 0,1:13:45.38,1:13:50.70,EN,,0,0,0,,Wouldn't it be nice if assignment was a good thing\nDialogue: 0,1:13:51.74,1:13:53.04,EN,,0,0,0,,and maybe it's worth it,\nDialogue: 0,1:13:53.28,1:13:54.14,EN,,0,0,0,,but I'm not sure.\nDialogue: 0,1:13:55.34,1:13:57.04,EN,,0,0,0,,As Mr. Gilbert and Sullivan said,\nDialogue: 0,1:13:57.04,1:13:58.51,EN,,0,0,0,,things are seldom what they seem,\nDialogue: 0,1:13:58.51,1:14:00.35,EN,,0,0,0,,skim milk masquerades as cream.\nDialogue: 0,1:14:01.87,1:14:03.90,EN,,0,0,0,,Are there any questions?\nDialogue: 0,1:14:16.97,1:14:18.30,EN,,0,0,0,,Are there any philosophers here?\nDialogue: 0,1:14:20.06,1:14:22.03,EN,,0,0,0,,Anybody want to argue about objects?\nDialogue: 0,1:14:24.32,1:14:25.50,EN,,0,0,0,,You're just floored, right?\nDialogue: 0,1:14:29.72,1:14:30.72,EN,,0,0,0,,And you haven't done your homework yet.\nDialogue: 0,1:14:30.73,1:14:32.00,EN,,0,0,0,,You haven't come up with a good question.\nDialogue: 0,1:14:36.35,1:14:37.44,EN,,0,0,0,,Oh, well.\nDialogue: 0,1:14:39.97,1:14:42.33,EN,,0,0,0,,Sure, thank you. Let's take the long break now.\nDialogue: 0,0:00:00.00,0:00:01.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:01.98,0:00:09.55,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N杨启钊（windfarer）\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.92,0:00:13.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}赋值、状态和副作用\nDialogue: 0,0:00:18.31,0:00:22.00,Default,,0,0,0,,教授：到目前为止 我们已经教了很多编程技巧\nDialogue: 0,0:00:22.25,0:00:24.06,Default,,0,0,0,,来编写复杂程序了\nDialogue: 0,0:00:24.76,0:00:29.66,Default,,0,0,0,,并且 到目前为止 关于编程你们学到了很多\nDialogue: 0,0:00:29.66,0:00:31.48,Default,,0,0,0,,你们已经学习了几乎所有的\nDialogue: 0,0:00:31.86,0:00:35.87,Default,,0,0,0,,那些拥有大量经验的人 才能领悟的技巧\nDialogue: 0,0:00:36.41,0:00:40.08,Default,,0,0,0,,例如 数据导向编程就是一个主要的技巧\nDialogue: 0,0:00:40.75,0:00:43.15,Default,,0,0,0,,昨天 你们也学习了一种解释型语言\nDialogue: 0,0:00:45.02,0:00:48.46,Default,,0,0,0,,我们所做的这一切\nDialogue: 0,0:00:48.54,0:00:49.63,Default,,0,0,0,,目前来讲\nDialogue: 0,0:00:49.88,0:00:51.95,Default,,0,0,0,,都是在一种没有赋值语句的计算机语言中完成的\nDialogue: 0,0:00:53.77,0:00:58.17,Default,,0,0,0,,对于你们中用过Basic或者Pascal的人\nDialogue: 0,0:00:58.68,0:01:01.23,Default,,0,0,0,,可能会认为“赋值”是最重要的东西\nDialogue: 0,0:01:01.79,0:01:03.82,Default,,0,0,0,,今天我们将要做一些糟糕的事情\nDialogue: 0,0:01:03.82,0:01:05.45,Default,,0,0,0,,我们要把赋值语句加进来\nDialogue: 0,0:01:07.21,0:01:09.14,Default,,0,0,0,,既然在没有赋值语句的时候 我们都可以很好地完成工作\nDialogue: 0,0:01:09.14,0:01:10.17,Default,,0,0,0,,为什么我们还要把它加进来呢？\nDialogue: 0,0:01:10.99,0:01:12.43,Default,,0,0,0,,为了理解它\nDialogue: 0,0:01:12.46,0:01:15.71,Default,,0,0,0,,我们今天首先要定下一个规则\nDialogue: 0,0:01:16.48,0:01:17.93,Default,,0,0,0,,而我们将一直遵守这个规则\nDialogue: 0,0:01:17.93,0:01:20.80,Default,,0,0,0,,这是我们为语言引入新的特性的唯一原因\nDialogue: 0,0:01:21.53,0:01:23.14,Default,,0,0,0,,是因为我们有一个好的理由\nDialogue: 0,0:01:23.93,0:01:27.28,Default,,0,0,0,,好的理由归结为能力\nDialogue: 0,0:01:27.42,0:01:31.51,Default,,0,0,0,,你现在获得了把问题分解为不同部分的能力\nDialogue: 0,0:01:31.51,0:01:33.44,Default,,0,0,0,,在没有相关能力之前可不行\nDialogue: 0,0:01:34.38,0:01:36.16,Default,,0,0,0,,这让你有用来分解问题的另外方法\nDialogue: 0,0:01:38.30,0:01:39.45,Default,,0,0,0,,我们这就开始\nDialogue: 0,0:01:39.45,0:01:41.88,Default,,0,0,0,,从回顾我们的\nDialogue: 0,0:01:41.88,0:01:47.37,Default,,0,0,0,,现在已经有的这种语言出发\nDialogue: 0,0:01:48.16,0:01:50.44,Default,,0,0,0,,我们之前写的是所谓的函数式程序\nDialogue: 0,0:01:51.21,0:01:52.52,Default,,0,0,0,,函数式程序\nDialogue: 0,0:01:53.04,0:01:57.95,Default,,0,0,0,,是一种对数学事实的编码\nDialogue: 0,0:01:58.88,0:02:00.51,Default,,0,0,0,,例如 当我们看到\nDialogue: 0,0:02:00.51,0:02:04.09,Default,,0,0,0,,像幻灯片上这样阶乘过程时\nDialogue: 0,0:02:05.07,0:02:06.62,Default,,0,0,0,,基本上是两个子句\nDialogue: 0,0:02:06.99,0:02:08.64,Default,,0,0,0,,如果n是1 则结果是1\nDialogue: 0,0:02:08.64,0:02:11.20,Default,,0,0,0,,否则返回n乘以n-1的阶乘\nDialogue: 0,0:02:11.20,0:02:12.33,Default,,0,0,0,,这是n的阶乘\nDialogue: 0,0:02:12.89,0:02:14.27,Default,,0,0,0,,它就是阶乘函数\nDialogue: 0,0:02:14.83,0:02:16.87,Default,,0,0,0,,如果用一些其他的记号\nDialogue: 0,0:02:16.87,0:02:19.32,Default,,0,0,0,,那些你在微积分课堂上学到的晦涩的符号来写\nDialogue: 0,0:02:20.30,0:02:22.11,Default,,0,0,0,,用数理逻辑来写\nDialogue: 0,0:02:22.11,0:02:26.36,Default,,0,0,0,,如果n等于1\nDialogue: 0,0:02:27.13,0:02:29.90,Default,,0,0,0,,那么n的阶乘结果是1 否则\nDialogue: 0,0:02:29.90,0:02:32.56,Default,,0,0,0,,如果n大于1 则n的阶乘就是n * (n-1)!\nDialogue: 0,0:02:32.56,0:02:33.55,Default,,0,0,0,,数学事实\nDialogue: 0,0:02:34.92,0:02:36.70,Default,,0,0,0,,就是我们一直使用的那种语言\nDialogue: 0,0:02:37.00,0:02:39.23,Default,,0,0,0,,无论何时 我们遇到了这样的数学事实\nDialogue: 0,0:02:39.53,0:02:46.65,Default,,0,0,0,,有一种理解它们工作原理的方法\nDialogue: 0,0:02:47.40,0:02:51.12,Default,,0,0,0,,就是这些过程可以由代换演算而来\nDialogue: 0,0:02:51.29,0:02:53.71,Default,,0,0,0,,来看第二张幻灯片\nDialogue: 0,0:02:54.99,0:02:58.81,Default,,0,0,0,,我们理解执行的过程\nDialogue: 0,0:02:58.83,0:03:03.50,Default,,0,0,0,,隐含在表达式的顺序中\nDialogue: 0,0:03:04.04,0:03:07.76,Default,,0,0,0,,也就是你不断地将实际参数\nDialogue: 0,0:03:07.87,0:03:10.88,Default,,0,0,0,,代换到程序体的形式参数中\nDialogue: 0,0:03:12.00,0:03:14.51,Default,,0,0,0,,这些基本上是一系列的等价代换\nDialogue: 0,0:03:14.61,0:03:17.25,Default,,0,0,0,,4的阶乘是4乘以3的阶乘\nDialogue: 0,0:03:17.25,0:03:20.05,Default,,0,0,0,,也就是4乘以3乘以2的阶乘\nDialogue: 0,0:03:20.05,0:03:21.01,Default,,0,0,0,,以此类推\nDialogue: 0,0:03:21.23,0:03:23.87,Default,,0,0,0,,我们总是保持数学事实成立\nDialogue: 0,0:03:25.23,0:03:28.84,Default,,0,0,0,,尽管我们正在讨论数学事实\nDialogue: 0,0:03:28.84,0:03:31.96,Default,,0,0,0,,可能有多种数学事实的组织方式\nDialogue: 0,0:03:31.96,0:03:35.12,Default,,0,0,0,,用来描述一个特定的函数的计算\nDialogue: 0,0:03:36.32,0:03:38.42,Default,,0,0,0,,这个特定的函数的值的计算\nDialogue: 0,0:03:38.42,0:03:40.92,Default,,0,0,0,,所以 让我来看下这里的例子\nDialogue: 0,0:03:41.48,0:03:49.02,Default,,0,0,0,,这有一个计算m与n之和的方法\nDialogue: 0,0:03:49.53,0:03:52.04,Default,,0,0,0,,我们使用一个递归的过程来完成\nDialogue: 0,0:03:52.89,0:03:58.16,Default,,0,0,0,,也就是(1+ (+ (-1+ n) m))\nDialogue: 0,0:04:00.08,0:04:05.62,Default,,0,0,0,,当然 这里也有相应的数理逻辑 解释了这个方法\nDialogue: 0,0:04:06.17,0:04:10.49,Default,,0,0,0,,也就是((n-1)+m)+1\nDialogue: 0,0:04:11.40,0:04:12.22,Default,,0,0,0,,跟之前那个一样\nDialogue: 0,0:04:13.10,0:04:16.40,Default,,0,0,0,,所以这儿并没有什么特殊的魔法\nDialogue: 0,0:04:16.41,0:04:20.01,Default,,0,0,0,,当然 如果我们可以再来看一个相同的迭代过程\nDialogue: 0,0:04:20.19,0:04:24.92,Default,,0,0,0,,计算同样的函数 但是进行逐步迭代的程序\nDialogue: 0,0:04:25.26,0:04:27.56,Default,,0,0,0,,这两个程序将得到同样的结果\nDialogue: 0,0:04:30.08,0:04:34.83,Default,,0,0,0,,我们就可以认为这两个程序在数学上是等效的\nDialogue: 0,0:04:36.65,0:04:39.93,Default,,0,0,0,,你对这些数学事实的排序 决定了具体（计算）过程\nDialogue: 0,0:04:40.30,0:04:43.42,Default,,0,0,0,,我们对于这些数学事实的排序和选择 决定了过程发展的方式\nDialogue: 0,0:04:44.33,0:04:48.60,Default,,0,0,0,,因此我们可以灵活地讨论待计算的函数\nDialogue: 0,0:04:48.60,0:04:50.19,Default,,0,0,0,,以及计算该函数的所用的方法\nDialogue: 0,0:04:50.60,0:04:52.60,Default,,0,0,0,,这并不清晰 我们需要再深入一些\nDialogue: 0,0:04:53.61,0:04:55.50,Default,,0,0,0,,然而 今天我要来讲这个糟糕的东西\nDialogue: 0,0:04:55.50,0:04:58.43,Default,,0,0,0,,我要给大家介绍赋值操作\nDialogue: 0,0:04:58.89,0:05:00.41,Default,,0,0,0,,这是什么？\nDialogue: 0,0:05:02.89,0:05:09.22,Default,,0,0,0,,首先 在编程语言中有另一种语句\nDialogue: 0,0:05:09.22,0:05:10.84,Default,,0,0,0,,这种语句叫做SET!\nDialogue: 0,0:05:12.41,0:05:15.96,Default,,0,0,0,,具有赋值操作的语句\nDialogue: 0,0:05:15.98,0:05:17.85,Default,,0,0,0,,我都会在后面加上一个感叹号\nDialogue: 0,0:05:18.51,0:05:20.96,Default,,0,0,0,,这个感叹号代表什么意思呢？\nDialogue: 0,0:05:20.96,0:05:23.01,Default,,0,0,0,,这个感叹号 与问号类似\nDialogue: 0,0:05:23.01,0:05:25.88,Default,,0,0,0,,是我们给名字随意加的符号\nDialogue: 0,0:05:25.88,0:05:27.88,Default,,0,0,0,,它对于系统来说没有意义\nDialogue: 0,0:05:28.08,0:05:30.21,Default,,0,0,0,,它唯一的意义就是告诉我们\nDialogue: 0,0:05:30.40,0:05:34.41,Default,,0,0,0,,注意这里是某种赋值操作\nDialogue: 0,0:05:35.88,0:05:40.06,Default,,0,0,0,,但是我们要给某个变量赋一个值\nDialogue: 0,0:05:43.74,0:05:45.13,Default,,0,0,0,,这意味着\nDialogue: 0,0:05:45.13,0:05:48.28,Default,,0,0,0,,在某个时间点发生了一些事情\nDialogue: 0,0:05:48.65,0:05:49.61,Default,,0,0,0,,这是一个时间点\nDialogue: 0,0:05:49.86,0:05:52.14,Default,,0,0,0,,如果时间以这个方向流动\nDialogue: 0,0:05:53.50,0:05:54.82,Default,,0,0,0,,这是个时间轴\nDialogue: 0,0:05:55.00,0:05:57.82,Default,,0,0,0,,时间在平面上由上到下地流逝\nDialogue: 0,0:05:58.70,0:06:00.92,Default,,0,0,0,,赋值是第一个\nDialogue: 0,0:06:00.92,0:06:04.30,Default,,0,0,0,,使过去和未来之间产生差别的事物\nDialogue: 0,0:06:06.59,0:06:08.72,Default,,0,0,0,,我们之前写的所有程序\nDialogue: 0,0:06:09.18,0:06:10.68,Default,,0,0,0,,都不包含赋值\nDialogue: 0,0:06:10.68,0:06:13.12,Default,,0,0,0,,这些程序以怎样的顺序进行执行都没关系\nDialogue: 0,0:06:14.70,0:06:15.96,Default,,0,0,0,,但是赋值比较特殊\nDialogue: 0,0:06:15.96,0:06:17.69,Default,,0,0,0,,它使时间中产生了一个时间点\nDialogue: 0,0:06:17.96,0:06:24.73,Default,,0,0,0,,因此在SET!出现之前和之后中间有一个时间点\nDialogue: 0,0:06:27.61,0:06:32.70,Default,,0,0,0,,使得在这个时间点之后\nDialogue: 0,0:06:33.60,0:06:43.76,Default,,0,0,0,,变量有了一个值 即VALUE\nDialogue: 0,0:06:49.23,0:06:51.50,Default,,0,0,0,,与这个变量之前的值无关\nDialogue: 0,0:06:52.80,0:06:55.79,Default,,0,0,0,,SET!改变了它的值\nDialogue: 0,0:06:57.69,0:06:58.75,Default,,0,0,0,,在此之前\nDialogue: 0,0:06:58.75,0:07:01.50,Default,,0,0,0,,什么都没有发生改变\nDialogue: 0,0:07:03.21,0:07:04.11,Default,,0,0,0,,举例来说\nDialogue: 0,0:07:04.84,0:07:06.23,Default,,0,0,0,,我们可以想到的一件事是\nDialogue: 0,0:07:06.23,0:07:09.42,Default,,0,0,0,,我们写的一些过程 比如阶乘的程序\nDialogue: 0,0:07:09.64,0:07:12.75,Default,,0,0,0,,事实上与数学中的阶乘函数完全相同\nDialogue: 0,0:07:13.77,0:07:16.44,Default,,0,0,0,,比如说4的阶乘 如果我写FACT(4)\nDialogue: 0,0:07:17.23,0:07:19.15,Default,,0,0,0,,无论它的上下文是怎样的\nDialogue: 0,0:07:19.69,0:07:21.29,Default,,0,0,0,,无论我写几遍\nDialogue: 0,0:07:21.29,0:07:22.35,Default,,0,0,0,,我总能得到同样的结果\nDialogue: 0,0:07:23.29,0:07:24.12,Default,,0,0,0,,结果永远是24\nDialogue: 0,0:07:25.37,0:07:28.92,Default,,0,0,0,,它是参数到到结果的唯一映射\nDialogue: 0,0:07:30.30,0:07:32.65,Default,,0,0,0,,迄今为止 我们之前写的所有程序都是这样的\nDialogue: 0,0:07:33.52,0:07:36.03,Default,,0,0,0,,然而 当引入赋值后 一切就不同了\nDialogue: 0,0:07:36.96,0:07:38.16,Default,,0,0,0,,举个例子\nDialogue: 0,0:07:39.18,0:07:48.52,Default,,0,0,0,,如果我将COUNT定义为1\nDialogue: 0,0:07:50.00,0:07:52.41,Default,,0,0,0,,然后定义一个过程\nDialogue: 0,0:07:55.16,0:07:56.83,Default,,0,0,0,,一个叫做DEMO的简单过程\nDialogue: 0,0:07:59.52,0:08:03.84,Default,,0,0,0,,它接受参数X 并执行下面的操作\nDialogue: 0,0:08:03.84,0:08:09.62,Default,,0,0,0,,首先将X修改为X+1\nDialogue: 0,0:08:09.62,0:08:11.77,Default,,0,0,0,,我的天啊！ 这看起来就像FORTRAN是吧？\nDialogue: 0,0:08:13.16,0:08:14.17,Default,,0,0,0,,只是用了些有趣的语法\nDialogue: 0,0:08:16.80,0:08:21.37,Default,,0,0,0,,然后返回(+ X COUNT)\nDialogue: 0,0:08:22.14,0:08:24.14,Default,,0,0,0,,哦 我刚犯了个错\nDialogue: 0,0:08:24.38,0:08:25.23,Default,,0,0,0,,我的意思是\nDialogue: 0,0:08:25.47,0:08:27.12,Default,,0,0,0,,(SET! COUNT (1+ COUNT))\nDialogue: 0,0:08:30.37,0:08:31.79,Default,,0,0,0,,就是我在这里定义的这个\nDialogue: 0,0:08:34.41,0:08:36.51,Default,,0,0,0,,然后X和COUNT相加\nDialogue: 0,0:08:40.35,0:08:42.06,Default,,0,0,0,,然后就可以试着运行这个过程了\nDialogue: 0,0:08:42.48,0:08:43.20,Default,,0,0,0,,让我们运行它\nDialogue: 0,0:08:43.92,0:08:47.22,Default,,0,0,0,,假设我可以输入\nDialogue: 0,0:08:47.48,0:08:48.68,Default,,0,0,0,,输入(DEMO 3)\nDialogue: 0,0:08:52.19,0:08:53.20,Default,,0,0,0,,这里发生了什么？\nDialogue: 0,0:08:53.74,0:08:55.28,Default,,0,0,0,,发生的第一件事情是\nDialogue: 0,0:08:55.53,0:08:56.89,Default,,0,0,0,,COUNT现在是1\nDialogue: 0,0:08:56.89,0:08:58.40,Default,,0,0,0,,现在 这是一个时间点\nDialogue: 0,0:08:59.12,0:09:00.29,Default,,0,0,0,,我们在讨论时间点\nDialogue: 0,0:09:00.62,0:09:01.74,Default,,0,0,0,,X的值为3\nDialogue: 0,0:09:02.92,0:09:04.03,Default,,0,0,0,,在这个时刻\nDialogue: 0,0:09:04.67,0:09:07.53,Default,,0,0,0,,COUNT增加了 所以COUNT是2\nDialogue: 0,0:09:09.02,0:09:10.44,Default,,0,0,0,,2加3等于5\nDialogue: 0,0:09:10.80,0:09:12.43,Default,,0,0,0,,所以结果是5\nDialogue: 0,0:09:14.48,0:09:21.58,Default,,0,0,0,,然后我再一次 输入(DEMO 3)\nDialogue: 0,0:09:23.60,0:09:24.56,Default,,0,0,0,,结果是什么？\nDialogue: 0,0:09:24.83,0:09:27.40,Default,,0,0,0,,现在COUNT是2 它不再是1了\nDialogue: 0,0:09:28.91,0:09:30.35,Default,,0,0,0,,因为我让COUNT加1了\nDialogue: 0,0:09:30.92,0:09:32.64,Default,,0,0,0,,但现在我执行这个过程\nDialogue: 0,0:09:32.72,0:09:33.66,Default,,0,0,0,,X的值为3\nDialogue: 0,0:09:34.17,0:09:37.40,Default,,0,0,0,,COUNT变为1+COUNT 因此现在是3了\nDialogue: 0,0:09:38.08,0:09:39.62,Default,,0,0,0,,这两个相加是6\nDialogue: 0,0:09:39.62,0:09:40.94,Default,,0,0,0,,所以结果是6\nDialogue: 0,0:09:41.92,0:09:43.03,Default,,0,0,0,,我们可以发现\nDialogue: 0,0:09:43.03,0:09:44.72,Default,,0,0,0,,同样的表达式\nDialogue: 0,0:09:45.08,0:09:46.64,Default,,0,0,0,,因为时间节点的不同\nDialogue: 0,0:09:48.75,0:09:49.96,Default,,0,0,0,,得到了不同的结果\nDialogue: 0,0:09:52.08,0:09:53.74,Default,,0,0,0,,所以DEMO不是函数\nDialogue: 0,0:09:54.17,0:09:56.12,Default,,0,0,0,,或者说它并没有计算一个数学意义上的函数\nDialogue: 0,0:09:59.88,0:10:02.09,Default,,0,0,0,,事实上 你可以知道这是为什么\nDialogue: 0,0:10:02.84,0:10:06.41,Default,,0,0,0,,因为这里是第一处代换模型失效的地方\nDialogue: 0,0:10:07.72,0:10:09.55,Default,,0,0,0,,它给代换模型判了死刑\nDialogue: 0,0:10:11.28,0:10:13.82,Default,,0,0,0,,有些关于引用的一些小问题\nDialogue: 0,0:10:13.85,0:10:17.18,Default,,0,0,0,,哲学家可能注意到 特别是与代换有关时\nDialogue: 0,0:10:17.18,0:10:19.87,Default,,0,0,0,,因为当你在引用中进行代换时\nDialogue: 0,0:10:20.91,0:10:22.12,Default,,0,0,0,,需要考虑你可以得到什么样的推论\nDialogue: 0,0:10:22.34,0:10:23.92,Default,,0,0,0,,如果你能够使用代换的话\nDialogue: 0,0:10:25.08,0:10:25.60,Default,,0,0,0,,但是\nDialogue: 0,0:10:26.06,0:10:28.00,Default,,0,0,0,,在这里代换模型已经失效了\nDialogue: 0,0:10:28.11,0:10:29.40,Default,,0,0,0,,它什么也不能做了\nDialogue: 0,0:10:29.64,0:10:30.57,Default,,0,0,0,,因为\nDialogue: 0,0:10:30.57,0:10:35.85,Default,,0,0,0,,假设我想用代换模型来考虑COUNT的代换\nDialogue: 0,0:10:37.10,0:10:41.16,Default,,0,0,0,,如果我在这里和这里进行代换\nDialogue: 0,0:10:41.69,0:10:42.96,Default,,0,0,0,,它们是不同的\nDialogue: 0,0:10:44.44,0:10:45.96,Default,,0,0,0,,它不再是同一个COUNT了\nDialogue: 0,0:10:46.48,0:10:47.64,Default,,0,0,0,,我得到了错误的结果\nDialogue: 0,0:10:47.97,0:10:50.14,Default,,0,0,0,,代换模型是一个静态的现象\nDialogue: 0,0:10:51.18,0:10:52.56,Default,,0,0,0,,它描述的事实\nDialogue: 0,0:10:53.93,0:10:55.29,Default,,0,0,0,,而不是变动\nDialogue: 0,0:10:55.50,0:10:57.04,Default,,0,0,0,,这里 我们的事实变动了\nDialogue: 0,0:11:00.60,0:11:06.74,Default,,0,0,0,,那么 在我给出任何解释之前\nDialogue: 0,0:11:06.74,0:11:07.79,Default,,0,0,0,,这很糟糕\nDialogue: 0,0:11:07.79,0:11:09.72,Default,,0,0,0,,我们失去了我们的计算模型\nDialogue: 0,0:11:10.28,0:11:10.80,Default,,0,0,0,,并且\nDialogue: 0,0:11:11.48,0:11:13.69,Default,,0,0,0,,很快 我将不得不构建一个新的计算模型\nDialogue: 0,0:11:14.66,0:11:17.87,Default,,0,0,0,,我们现在的讨论 还是从一个不严谨的角度进行的\nDialogue: 0,0:11:18.56,0:11:20.16,Default,,0,0,0,,当然 你们已经看到的是\nDialogue: 0,0:11:20.51,0:11:22.70,Default,,0,0,0,,当我做一些像赋值之类的事情时\nDialogue: 0,0:11:23.12,0:11:24.51,Default,,0,0,0,,我们所需要的模型\nDialogue: 0,0:11:24.51,0:11:26.89,Default,,0,0,0,,与我们之前模型不同\nDialogue: 0,0:11:26.89,0:11:30.93,Default,,0,0,0,,在这个的模型中 像COUNT或X这样的符号\nDialogue: 0,0:11:30.93,0:11:34.07,Default,,0,0,0,,不再关联于它们的值\nDialogue: 0,0:11:34.07,0:11:37.31,Default,,0,0,0,,而是关联于某个储存这些值的地方\nDialogue: 0,0:11:37.68,0:11:39.47,Default,,0,0,0,,我们将花些时间来适应这种思想\nDialogue: 0,0:11:40.20,0:11:42.11,Default,,0,0,0,,这将是一个很糟糕的事情\nDialogue: 0,0:11:42.11,0:11:43.47,Default,,0,0,0,,并且会造成很多麻烦\nDialogue: 0,0:11:44.49,0:11:48.25,Default,,0,0,0,,所以 就像我说的 若非理由周全\nDialogue: 0,0:11:48.25,0:11:50.09,Default,,0,0,0,,不然绝不要发明这种糟糕的东西\nDialogue: 0,0:11:50.37,0:11:52.86,Default,,0,0,0,,否则 就是劳神费力\nDialogue: 0,0:11:53.39,0:11:55.55,Default,,0,0,0,,让我们看看一些可以讨论的东西\nDialogue: 0,0:11:55.88,0:11:58.59,Default,,0,0,0,,假设我们写了函数式版本的阶乘函数\nDialogue: 0,0:11:58.59,0:12:00.48,Default,,0,0,0,,我们以前的就是“函数式”风格\nDialogue: 0,0:12:01.37,0:12:04.60,Default,,0,0,0,,具有迭代计算过程的阶乘函数\nDialogue: 0,0:12:09.59,0:12:13.28,Default,,0,0,0,,N的阶乘\nDialogue: 0,0:12:18.38,0:12:24.35,Default,,0,0,0,,我们要(ITER M I)\nDialogue: 0,0:12:26.12,0:12:33.13,Default,,0,0,0,,就是说如果I大于N\nDialogue: 0,0:12:33.77,0:12:35.51,Default,,0,0,0,,则结果是M\nDialogue: 0,0:12:36.30,0:12:37.39,Default,,0,0,0,,否则\nDialogue: 0,0:12:39.79,0:12:46.82,Default,,0,0,0,,结果是(ITER (* I M))\nDialogue: 0,0:12:46.82,0:12:49.95,Default,,0,0,0,,所以M将是我累积的结果\nDialogue: 0,0:12:51.58,0:12:52.62,Default,,0,0,0,,M就是这个乘积[注：此处教授笔误]\nDialogue: 0,0:12:57.97,0:13:00.17,Default,,0,0,0,,然后我要把COUNT加1\nDialogue: 0,0:13:04.62,0:13:10.97,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:13:11.95,0:13:13.04,Default,,0,0,0,,我在这里启动这个内部过程\nDialogue: 0,0:13:17.16,0:13:19.79,Default,,0,0,0,,对于这种代码 我想大家早已驾轻就熟了\nDialogue: 0,0:13:20.86,0:13:25.15,Default,,0,0,0,,这里是一个累积的乘积 和一个计数器\nDialogue: 0,0:13:26.48,0:13:28.46,Default,,0,0,0,,我让它们都从1开始\nDialogue: 0,0:13:28.89,0:13:30.92,Default,,0,0,0,,我将不断让计数器增加\nDialogue: 0,0:13:30.92,0:13:33.12,Default,,0,0,0,,每一轮I变成I+1\nDialogue: 0,0:13:34.56,0:13:37.47,Default,,0,0,0,,这是我们在这个过程中设置时间的唯一方法\nDialogue: 0,0:13:38.48,0:13:40.04,Default,,0,0,0,,这些都是一系列的事实\nDialogue: 0,0:13:40.49,0:13:41.34,Default,,0,0,0,,真实的规则\nDialogue: 0,0:13:42.81,0:13:46.13,Default,,0,0,0,,M将获得一个新的值 就是I乘M\nDialogue: 0,0:13:46.13,0:13:47.82,Default,,0,0,0,,每一轮I乘以M\nDialogue: 0,0:13:48.68,0:13:50.48,Default,,0,0,0,,最终I将大于N\nDialogue: 0,0:13:50.49,0:13:52.06,Default,,0,0,0,,在这种情况下 结果就是M\nDialogue: 0,0:13:52.67,0:13:54.80,Default,,0,0,0,,我给你们讲课的时候 用到了“时间”这个概念\nDialogue: 0,0:13:55.68,0:13:57.45,Default,,0,0,0,,那是因为我知道计算机是怎么工作的\nDialogue: 0,0:13:58.25,0:13:59.24,Default,,0,0,0,,但是我没必要这么做\nDialogue: 0,0:13:59.26,0:14:02.30,Default,,0,0,0,,这完全可以有一个纯数学的解释\nDialogue: 0,0:14:02.30,0:14:03.74,Default,,0,0,0,,因为在这里代换可以工作\nDialogue: 0,0:14:05.10,0:14:08.14,Default,,0,0,0,,但是我们写一个类似的程序\nDialogue: 0,0:14:08.30,0:14:09.95,Default,,0,0,0,,使用相同的算法\nDialogue: 0,0:14:10.73,0:14:12.11,Default,,0,0,0,,但使用了赋值\nDialogue: 0,0:14:15.69,0:14:17.16,Default,,0,0,0,,所以这个叫做函数式版本\nDialogue: 0,0:14:23.72,0:14:25.56,Default,,0,0,0,,我想写个命令式的版本的\nDialogue: 0,0:14:34.48,0:14:35.39,Default,,0,0,0,,N的阶乘\nDialogue: 0,0:14:35.92,0:14:37.74,Default,,0,0,0,,我要创建两个变量\nDialogue: 0,0:14:40.16,0:14:45.53,Default,,0,0,0,,把I的值初始化为1\nDialogue: 0,0:14:46.32,0:14:49.77,Default,,0,0,0,,M也初始化为1\nDialogue: 0,0:14:51.15,0:14:52.19,Default,,0,0,0,,我们创建一个循环\nDialogue: 0,0:14:59.31,0:15:07.27,Default,,0,0,0,,如果I比N大 循环结束\nDialogue: 0,0:15:07.27,0:15:08.87,Default,,0,0,0,,结果是M\nDialogue: 0,0:15:08.87,0:15:10.38,Default,,0,0,0,,也就是我累积的乘积\nDialogue: 0,0:15:10.87,0:15:11.77,Default,,0,0,0,,否则\nDialogue: 0,0:15:15.52,0:15:17.40,Default,,0,0,0,,我接下来要做三件事\nDialogue: 0,0:15:19.26,0:15:27.05,Default,,0,0,0,,我要把M赋值为I*M\nDialogue: 0,0:15:29.36,0:15:35.20,Default,,0,0,0,,把I赋值为I+1\nDialogue: 0,0:15:37.85,0:15:39.31,Default,,0,0,0,,然后继续循环\nDialogue: 0,0:15:40.41,0:15:43.02,Default,,0,0,0,,你们中的FORTRAN程序员应该觉得眼熟\nDialogue: 0,0:15:44.73,0:15:46.64,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:15:46.64,0:15:47.88,Default,,0,0,0,,就是这种语法有点陌生\nDialogue: 0,0:15:51.13,0:15:52.27,Default,,0,0,0,,启动循环\nDialogue: 0,0:15:56.10,0:15:57.56,Default,,0,0,0,,程序就写完了\nDialogue: 0,0:15:59.15,0:16:00.52,Default,,0,0,0,,那么 这个程序\nDialogue: 0,0:16:01.31,0:16:02.49,Default,,0,0,0,,我们应该怎么思考它呢？\nDialogue: 0,0:16:02.71,0:16:04.25,Default,,0,0,0,,先来看看这里是什么\nDialogue: 0,0:16:04.84,0:16:07.47,Default,,0,0,0,,这里有两个局部变量 I和M\nDialogue: 0,0:16:07.47,0:16:09.02,Default,,0,0,0,,它们都被初始化为1\nDialogue: 0,0:16:10.72,0:16:13.89,Default,,0,0,0,,在每一次循环里 我检测I是否大于N\nDialogue: 0,0:16:13.89,0:16:15.08,Default,,0,0,0,,就是我们传入的参数\nDialogue: 0,0:16:15.30,0:16:18.14,Default,,0,0,0,,如果成立的话 结果就是M中所累积的乘积\nDialogue: 0,0:16:19.16,0:16:21.21,Default,,0,0,0,,然而 如果循环没有结束\nDialogue: 0,0:16:21.21,0:16:22.89,Default,,0,0,0,,如果我们的工作没有结束\nDialogue: 0,0:16:23.64,0:16:25.55,Default,,0,0,0,,则我们要把乘积\nDialogue: 0,0:16:25.84,0:16:28.38,Default,,0,0,0,,变为i与当前乘积的结果\nDialogue: 0,0:16:29.04,0:16:30.68,Default,,0,0,0,,就是我们在这里做过的事情\nDialogue: 0,0:16:31.42,0:16:32.68,Default,,0,0,0,,除了这里我没有改动\nDialogue: 0,0:16:33.63,0:16:35.77,Default,,0,0,0,,我创建了一个复本\nDialogue: 0,0:16:36.81,0:16:42.04,Default,,0,0,0,,因为代换模型就是你复制过程的体\nDialogue: 0,0:16:43.08,0:16:45.88,Default,,0,0,0,,并用实际参数代换形式参数\nDialogue: 0,0:16:46.72,0:16:48.42,Default,,0,0,0,,这里 我考虑的不是副本\nDialogue: 0,0:16:48.42,0:16:50.52,Default,,0,0,0,,在这里 我已经改变了M的值\nDialogue: 0,0:16:51.80,0:16:55.12,Default,,0,0,0,,我也把I的值变成了I+1\nDialogue: 0,0:16:55.61,0:16:56.96,Default,,0,0,0,,然后继续循环\nDialogue: 0,0:16:58.22,0:17:00.08,Default,,0,0,0,,看起来是一样的程序\nDialogue: 0,0:17:00.96,0:17:02.84,Default,,0,0,0,,在今天引入赋值之后\nDialogue: 0,0:17:02.84,0:17:05.50,Default,,0,0,0,,我们在这里有很多种方式犯错\nDialogue: 0,0:17:06.14,0:17:07.02,Default,,0,0,0,,例如\nDialogue: 0,0:17:07.45,0:17:09.40,Default,,0,0,0,,如果我在赋值的时候\nDialogue: 0,0:17:10.04,0:17:12.14,Default,,0,0,0,,没有小心地写程序\nDialogue: 0,0:17:12.64,0:17:16.08,Default,,0,0,0,,把两个赋值的顺序调换了\nDialogue: 0,0:17:17.10,0:17:18.91,Default,,0,0,0,,程序计算的就不是相同的函数了\nDialogue: 0,0:17:20.33,0:17:22.87,Default,,0,0,0,,我得到了一个时间错误 因为这儿有个依赖关系\nDialogue: 0,0:17:22.87,0:17:27.22,Default,,0,0,0,,因为M依赖于I上一次的值\nDialogue: 0,0:17:27.34,0:17:28.92,Default,,0,0,0,,如果我先改变I的值\nDialogue: 0,0:17:31.31,0:17:33.77,Default,,0,0,0,,就会在乘以M的时候 得到错误的I值\nDialogue: 0,0:17:35.96,0:17:38.38,Default,,0,0,0,,没有赋值的话不会存在这样的BUG\nDialogue: 0,0:17:38.38,0:17:40.59,Default,,0,0,0,,这是由于我们引入了某些包含时间的东西造成的\nDialogue: 0,0:17:43.44,0:17:44.30,Default,,0,0,0,,如我所说的\nDialogue: 0,0:17:45.53,0:17:47.39,Default,,0,0,0,,首先 我们需要一个新的计算模型\nDialogue: 0,0:17:47.39,0:17:50.86,Default,,0,0,0,,然后 需要有一个非常好的理由来支持我们做如此丑陋的事\nDialogue: 0,0:17:52.72,0:17:53.74,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:17:58.83,0:18:00.22,Default,,0,0,0,,David 大点儿声说\nDialogue: 0,0:18:00.40,0:18:03.47,Default,,0,0,0,,学生：现在 我们引入了SET!\nDialogue: 0,0:18:03.90,0:18:06.36,Default,,0,0,0,,但是之前我们已经有LET和DEFINE了\nDialogue: 0,0:18:06.89,0:18:09.70,Default,,0,0,0,,我不太清楚它们的区别\nDialogue: 0,0:18:09.70,0:18:13.25,Default,,0,0,0,,DEFINE不能像SET!一样用吗？\nDialogue: 0,0:18:13.98,0:18:14.83,Default,,0,0,0,,请详细讲讲\nDialogue: 0,0:18:14.83,0:18:19.31,Default,,0,0,0,,教授：不 DEFINE用于创建并初始化\nDialogue: 0,0:18:19.31,0:18:21.36,Default,,0,0,0,,为了创建它\nDialogue: 0,0:18:22.08,0:18:24.70,Default,,0,0,0,,你永远也不会见到我在黑板上\nDialogue: 0,0:18:25.60,0:18:26.94,Default,,0,0,0,,在同一行写两个DEFINE\nDialogue: 0,0:18:27.08,0:18:32.08,Default,,0,0,0,,只是为了让某个变量的旧值变成一个新的值\nDialogue: 0,0:18:32.08,0:18:34.51,Default,,0,0,0,,学生：这是一个约定俗成的规矩 还是--\nDialogue: 0,0:18:34.51,0:18:36.35,Default,,0,0,0,,教授：不 这是有意为之的\nDialogue: 0,0:18:36.35,0:18:38.92,Default,,0,0,0,,答案是\nDialogue: 0,0:18:39.69,0:18:40.84,Default,,0,0,0,,举个例子\nDialogue: 0,0:18:40.84,0:18:42.27,Default,,0,0,0,,在一个过程内部\nDialogue: 0,0:18:43.20,0:18:45.92,Default,,0,0,0,,两个DEFINE写在一行里是非法的\nDialogue: 0,0:18:46.68,0:18:48.57,Default,,0,0,0,,对于同一个变量DEFINE两次是非法的\nDialogue: 0,0:18:50.24,0:18:51.74,Default,,0,0,0,,X不能被DEFINE两次\nDialogue: 0,0:18:51.74,0:18:55.20,Default,,0,0,0,,而系统会不会捕获这个错误 就是另一个问题了\nDialogue: 0,0:18:55.93,0:18:57.88,Default,,0,0,0,,但是我定下规矩\nDialogue: 0,0:18:58.12,0:19:00.64,Default,,0,0,0,,任何东西都只能DEFINE一次\nDialogue: 0,0:19:00.73,0:19:02.64,Default,,0,0,0,,确实 在交互式调试中\nDialogue: 0,0:19:03.37,0:19:07.48,Default,,0,0,0,,我们打算让你与计算机交互时可以重新DEFINE一些东西\nDialogue: 0,0:19:08.19,0:19:11.21,Default,,0,0,0,,所以交互式调试时产生的是一个特殊的异常\nDialogue: 0,0:19:11.82,0:19:16.48,Default,,0,0,0,,但是DEFINE的意思是建立某些东西\nDialogue: 0,0:19:18.14,0:19:20.96,Default,,0,0,0,,在那个时间点后 它的值是永远不变的\nDialogue: 0,0:19:22.05,0:19:24.54,Default,,0,0,0,,好像所有的DEFINE都是在最开始完成的\nDialogue: 0,0:19:26.09,0:19:30.92,Default,,0,0,0,,事实上 在Scheme过程中 DEFINE的唯一合法使用地方\nDialogue: 0,0:19:31.02,0:19:33.36,Default,,0,0,0,,就是在LAMBDA表达式的开始\nDialogue: 0,0:19:34.47,0:19:37.66,Default,,0,0,0,,也就是过程体的开始\nDialogue: 0,0:19:40.40,0:19:45.80,Default,,0,0,0,,LET当然与那个不一样\nDialogue: 0,0:19:48.09,0:19:49.55,Default,,0,0,0,,如果你想知道LET发生了什么\nDialogue: 0,0:19:50.17,0:19:52.13,Default,,0,0,0,,LET只会绑定一次\nDialogue: 0,0:19:52.13,0:19:55.82,Default,,0,0,0,,它建立了一个I和M的值分别为1的上下文\nDialogue: 0,0:19:56.83,0:20:00.57,Default,,0,0,0,,这个上下文存在于整个作用域中\nDialogue: 0,0:20:01.31,0:20:02.80,Default,,0,0,0,,也就是这个程序范围\nDialogue: 0,0:20:04.99,0:20:10.12,Default,,0,0,0,,然而 你不会认为LET再次设置了I的值\nDialogue: 0,0:20:11.04,0:20:12.16,Default,,0,0,0,,它没有改变I的值\nDialogue: 0,0:20:12.16,0:20:14.01,Default,,0,0,0,,因为LET的作用 I将永远不会变化\nDialogue: 0,0:20:15.28,0:20:16.81,Default,,0,0,0,,因为LET的作用 I才被创建\nDialogue: 0,0:20:18.51,0:20:19.29,Default,,0,0,0,,实际上\nDialogue: 0,0:20:19.73,0:20:21.42,Default,,0,0,0,,LET是一个非常简单的想法\nDialogue: 0,0:20:22.24,0:20:23.59,Default,,0,0,0,,LET不会做别的事情\nDialogue: 0,0:20:23.59,0:20:31.62,Default,,0,0,0,,LET的语义是……\nDialogue: 0,0:20:31.62,0:20:33.50,Default,,0,0,0,,我把它写得更准确点\nDialogue: 0,0:20:37.16,0:20:43.73,Default,,0,0,0,,表达式 (var1 e1)\nDialogue: 0,0:20:43.73,0:20:47.36,Default,,0,0,0,,还有(var2 e2)\nDialogue: 0,0:20:48.14,0:20:49.74,Default,,0,0,0,,在表达式e3中\nDialogue: 0,0:20:51.60,0:21:05.80,Default,,0,0,0,,与一个以var1和var2为形式参数的过程一样\nDialogue: 0,0:21:06.94,0:21:08.96,Default,,0,0,0,,e3成为过程的体\nDialogue: 0,0:21:10.91,0:21:14.00,Default,,0,0,0,,在这里 var1与e1的值绑定\nDialogue: 0,0:21:14.27,0:21:16.91,Default,,0,0,0,,var2与e2的值绑定\nDialogue: 0,0:21:19.53,0:21:23.26,Default,,0,0,0,,所以实际上 这是一个从代换的角度来看很容易理解的东西\nDialogue: 0,0:21:24.89,0:21:27.95,Default,,0,0,0,,其实就是同一个表达式的两种不同的写法\nDialogue: 0,0:21:31.69,0:21:33.50,Default,,0,0,0,,事实上 系统真正的工作方式\nDialogue: 0,0:21:33.63,0:21:35.82,Default,,0,0,0,,就是在运行之前把代码翻译成这种形式\nDialogue: 0,0:21:37.64,0:21:41.77,Default,,0,0,0,,学生：我还是不清楚是什么造成了LET和DEFINE之间的区别\nDialogue: 0,0:21:41.77,0:21:44.30,Default,,0,0,0,,教授：DEFINE就是个语法糖\nDialogue: 0,0:21:44.62,0:21:49.10,Default,,0,0,0,,本质上来说 是通过LET创建一系列变量 然后给它们一次性赋值\nDialogue: 0,0:21:57.10,0:21:59.74,Default,,0,0,0,,好吧 我们休息一会\nDialogue: 0,0:22:02.52,0:22:12.84,Default,,0,0,0,,[音乐]\nDialogue: 0,0:22:12.84,0:22:17.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:22:48.81,0:22:52.67,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:22:52.67,0:22:56.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:22:56.52,0:23:00.59,Declare,,0,0,0,,{\\an2\\fad(500,500)}赋值、状态和副作用\nDialogue: 0,0:23:04.28,0:23:06.11,Default,,0,0,0,,看\nDialogue: 0,0:23:06.44,0:23:09.08,Default,,0,0,0,,现在 我不得不重建计算模型\nDialogue: 0,0:23:09.77,0:23:14.16,Default,,0,0,0,,使得你能够明白那些机制是如何运作的\nDialogue: 0,0:23:14.91,0:23:16.46,Default,,0,0,0,,来完成我们刚才说的那些工作\nDialogue: 0,0:23:17.53,0:23:21.39,Default,,0,0,0,,我刚刚摧毁了你们的代换模型\nDialogue: 0,0:23:22.62,0:23:26.03,Default,,0,0,0,,不幸的是 这个模型比代换模型要复杂得多\nDialogue: 0,0:23:26.62,0:23:27.93,Default,,0,0,0,,这个模型叫环境模型\nDialogue: 0,0:23:29.02,0:23:31.20,Default,,0,0,0,,我即将介绍一些术语\nDialogue: 0,0:23:32.03,0:23:34.51,Default,,0,0,0,,无论如何 你知道这些术语都是很好的\nDialogue: 0,0:23:34.51,0:23:35.74,Default,,0,0,0,,它是关于名字的\nDialogue: 0,0:23:36.51,0:23:39.63,Default,,0,0,0,,我们要给事物的各种名字\nDialogue: 0,0:23:40.00,0:23:41.31,Default,,0,0,0,,和名字的使用途径以名字\nDialogue: 0,0:23:42.48,0:23:47.94,Default,,0,0,0,,如果硬要说的话 这是一个元描述\nDialogue: 0,0:23:48.56,0:23:50.85,Default,,0,0,0,,总之 这里面有一堆糟糕的术语\nDialogue: 0,0:23:50.85,0:23:53.76,Default,,0,0,0,,但我们需要利用它们来理解所谓的“环境模型”\nDialogue: 0,0:23:54.70,0:23:57.53,Default,,0,0,0,,我们可能要做一点无聊的事情了\nDialogue: 0,0:23:58.04,0:24:01.58,Default,,0,0,0,,我们来看第一张张幻灯片\nDialogue: 0,0:24:02.25,0:24:06.97,Default,,0,0,0,,我们看到了术语“约束”的解释\nDialogue: 0,0:24:08.80,0:24:11.00,Default,,0,0,0,,我们会说一个变量V\nDialogue: 0,0:24:11.00,0:24:12.91,Default,,0,0,0,,被约束在表达式E中\nDialogue: 0,0:24:13.41,0:24:21.52,Default,,0,0,0,,如果用一个没有出现在E中的变量W 对变量V统一换名\nDialogue: 0,0:24:21.56,0:24:24.28,Default,,0,0,0,,表达式语义没有发生改变\nDialogue: 0,0:24:25.69,0:24:27.00,Default,,0,0,0,,这个解释很长\nDialogue: 0,0:24:27.37,0:24:29.96,Default,,0,0,0,,在我们在被搞糊涂之前\nDialogue: 0,0:24:29.98,0:24:32.62,Default,,0,0,0,,我应该再多解释下\nDialogue: 0,0:24:33.42,0:24:35.28,Default,,0,0,0,,我们这里讨论的约束变量\nDialogue: 0,0:24:44.16,0:24:45.56,Default,,0,0,0,,你们已经看到它们很多次了\nDialogue: 0,0:24:46.07,0:24:48.17,Default,,0,0,0,,只是你们可能还没意识到\nDialogue: 0,0:24:48.24,0:24:52.24,Default,,0,0,0,,在逻辑学中 你们看到一个逻辑变量\nDialogue: 0,0:24:53.27,0:25:00.11,Default,,0,0,0,,就像微积分课上的 对于任意任何X 存在一个Y 使得P为真\nDialogue: 0,0:25:02.88,0:25:05.82,Default,,0,0,0,,这个变量X 这个变量Y 它们是约束变量\nDialogue: 0,0:25:07.08,0:25:07.92,Default,,0,0,0,,因为\nDialogue: 0,0:25:08.33,0:25:09.98,Default,,0,0,0,,这个表达式的含义\nDialogue: 0,0:25:09.98,0:25:15.61,Default,,0,0,0,,不取决于我用来描述X和Y的具体字母\nDialogue: 0,0:25:16.49,0:25:19.18,Default,,0,0,0,,如果我用W替换X\nDialogue: 0,0:25:19.84,0:25:25.68,Default,,0,0,0,,则可以说对于任意W 存在一个Y使得P为真\nDialogue: 0,0:25:25.98,0:25:27.08,Default,,0,0,0,,它们其实是同一句话\nDialogue: 0,0:25:29.44,0:25:30.34,Default,,0,0,0,,就是这个意思\nDialogue: 0,0:25:30.34,0:25:34.89,Default,,0,0,0,,又或者说 你们看到这样一个积分\nDialogue: 0,0:25:35.40,0:25:42.65,Default,,0,0,0,,对dx/(1+x^2)从0到1积分\nDialogue: 0,0:25:46.03,0:25:47.92,Default,,0,0,0,,这就是你们经常见到的那种东西\nDialogue: 0,0:25:47.92,0:25:50.92,Default,,0,0,0,,这个x是一个约束变量\nDialogue: 0,0:25:52.06,0:25:53.79,Default,,0,0,0,,如果我把它换成t\nDialogue: 0,0:25:54.15,0:25:56.25,Default,,0,0,0,,这个表达式其实没有变化\nDialogue: 0,0:25:58.06,0:26:02.76,Default,,0,0,0,,就是arctan(1)/4之类的\nDialogue: 0,0:26:04.70,0:26:06.01,Default,,0,0,0,,是的 就是arctan(1)\nDialogue: 0,0:26:06.62,0:26:08.76,Default,,0,0,0,,所以约束变量事实上很常见\nDialogue: 0,0:26:09.08,0:26:12.36,Default,,0,0,0,,如果你们接触过一些数学的话\nDialogue: 0,0:26:13.26,0:26:17.47,Default,,0,0,0,,好 让我们来到编程的世界\nDialogue: 0,0:26:19.02,0:26:21.36,Default,,0,0,0,,现在量词不再是\nDialogue: 0,0:26:22.03,0:26:24.06,Default,,0,0,0,,所有、存在和积分\nDialogue: 0,0:26:24.06,0:26:26.43,Default,,0,0,0,,我们有一个符号作为量词 用于约束变量\nDialogue: 0,0:26:27.47,0:26:28.99,Default,,0,0,0,,我们要使用量词LAMBDA\nDialogue: 0,0:26:29.79,0:26:31.80,Default,,0,0,0,,作为约束变量的一个必要的东西\nDialogue: 0,0:26:33.80,0:26:36.12,Default,,0,0,0,,我们有一个极好的例子\nDialogue: 0,0:26:36.59,0:26:44.14,Default,,0,0,0,,对于以Y为参数的过程 做了以下的事情\nDialogue: 0,0:26:44.14,0:26:46.96,Default,,0,0,0,,它调用一个含单个参数X的过程\nDialogue: 0,0:26:47.87,0:26:51.13,Default,,0,0,0,,该过程 将X乘以Y\nDialogue: 0,0:26:52.88,0:26:54.52,Default,,0,0,0,,并应用于3\nDialogue: 0,0:26:58.76,0:27:01.66,Default,,0,0,0,,这个过程中包含两个约束变量\nDialogue: 0,0:27:02.01,0:27:02.92,Default,,0,0,0,,X和Y\nDialogue: 0,0:27:04.83,0:27:07.47,Default,,0,0,0,,这个LAMBDA量词 约束了这个Y\nDialogue: 0,0:27:07.91,0:27:10.78,Default,,0,0,0,,这个LAMBDA量词 约束了这个X\nDialogue: 0,0:27:12.11,0:27:17.05,Default,,0,0,0,,因为 如果我用了一个没有出现在表达式中的任意符号 如W\nDialogue: 0,0:27:17.98,0:27:21.04,Default,,0,0,0,,用W替换表达式中的所有Y\nDialogue: 0,0:27:21.36,0:27:22.75,Default,,0,0,0,,这个表达式仍与原来的相同\nDialogue: 0,0:27:23.66,0:27:24.80,Default,,0,0,0,,是相同的过程\nDialogue: 0,0:27:26.22,0:27:27.41,Default,,0,0,0,,这是一个重要的想法\nDialogue: 0,0:27:27.41,0:27:29.64,Default,,0,0,0,,我们有这种东西的原因\nDialogue: 0,0:27:30.20,0:27:31.41,Default,,0,0,0,,这是一种模块性\nDialogue: 0,0:27:31.41,0:27:32.86,Default,,0,0,0,,如果有两个人写程序\nDialogue: 0,0:27:34.03,0:27:35.26,Default,,0,0,0,,并且他们在合作编程\nDialogue: 0,0:27:35.26,0:27:40.56,Default,,0,0,0,,在他们自己构建的小项目里用什么命名都没有关系\nDialogue: 0,0:27:42.83,0:27:44.67,Default,,0,0,0,,所以 实际上我想告诉你们\nDialogue: 0,0:27:45.44,0:27:46.75,Default,,0,0,0,,例如\nDialogue: 0,0:27:46.84,0:27:51.26,Default,,0,0,0,,这个表达式等于 以Y为参数的过程\nDialogue: 0,0:27:52.35,0:27:59.23,Default,,0,0,0,,使用这个对于一个参数Z的过程 这个过程将Z乘以Y\nDialogue: 0,0:28:01.64,0:28:03.53,Default,,0,0,0,,因为没人关心我在这用什么\nDialogue: 0,0:28:06.36,0:28:07.24,Default,,0,0,0,,这是一个极好的例子\nDialogue: 0,0:28:08.84,0:28:09.85,Default,,0,0,0,,另一方面\nDialogue: 0,0:28:11.07,0:28:14.33,Default,,0,0,0,,我有一些未被约束的变量\nDialogue: 0,0:28:15.23,0:28:15.96,Default,,0,0,0,,举个例子\nDialogue: 0,0:28:20.27,0:28:21.76,Default,,0,0,0,,这个对于一个以X为参数的过程\nDialogue: 0,0:28:22.09,0:28:25.04,Default,,0,0,0,,将X乘以Y\nDialogue: 0,0:28:27.28,0:28:28.16,Default,,0,0,0,,在这个例子中\nDialogue: 0,0:28:29.45,0:28:30.75,Default,,0,0,0,,y没有被约束\nDialogue: 0,0:28:32.46,0:28:34.27,Default,,0,0,0,,假设Y的值是3\nDialogue: 0,0:28:35.26,0:28:36.80,Default,,0,0,0,,Z的值是4\nDialogue: 0,0:28:38.83,0:28:44.27,Default,,0,0,0,,那么这个过程就是把它的参数乘以3\nDialogue: 0,0:28:44.86,0:28:47.39,Default,,0,0,0,,如果我把所有的y都用z来代替\nDialogue: 0,0:28:47.52,0:28:51.96,Default,,0,0,0,,我将得到一个完全不同的过程 它会把参数乘以4\nDialogue: 0,0:28:53.87,0:28:56.40,Default,,0,0,0,,事实上 我们给这类变量取了个名字\nDialogue: 0,0:28:57.76,0:29:04.01,Default,,0,0,0,,我们把表达式E中的变量V叫做自由变量\nDialogue: 0,0:29:04.01,0:29:09.42,Default,,0,0,0,,如果用没有出现在E中的变量W统一替换E中所有的V\nDialogue: 0,0:29:09.58,0:29:11.15,Default,,0,0,0,,使得表达式E的含义发生了改变\nDialogue: 0,0:29:13.26,0:29:13.71,Default,,0,0,0,,所以\nDialogue: 0,0:29:14.49,0:29:22.76,Default,,0,0,0,,所以这就是为什么这个变量Y 是一个自由变量\nDialogue: 0,0:29:29.16,0:29:32.27,Default,,0,0,0,,所以 这个表达式里的自由变量\nDialogue: 0,0:29:33.76,0:29:35.18,Default,,0,0,0,,另一个例子是\nDialogue: 0,0:29:36.17,0:29:39.32,Default,,0,0,0,,对于一个以Y为参数的过程\nDialogue: 0,0:29:40.43,0:29:42.00,Default,,0,0,0,,就像我们之前的那个一样\nDialogue: 0,0:29:42.27,0:29:44.60,Default,,0,0,0,,调用以X为参数的过程\nDialogue: 0,0:29:45.08,0:29:48.54,Default,,0,0,0,,将X与Y相乘--\nDialogue: 0,0:29:51.40,0:29:52.65,Default,,0,0,0,,并应用于3\nDialogue: 0,0:29:57.24,0:30:00.35,Default,,0,0,0,,这个过程中有一个自由变量\nDialogue: 0,0:30:00.92,0:30:01.98,Default,,0,0,0,,也就是这个星号\nDialogue: 0,0:30:05.00,0:30:05.89,Default,,0,0,0,,因为\nDialogue: 0,0:30:05.89,0:30:08.08,Default,,0,0,0,,如果它表示正常意义的乘法\nDialogue: 0,0:30:09.44,0:30:12.78,Default,,0,0,0,,如果我统一地用加号来代替星号\nDialogue: 0,0:30:14.25,0:30:16.38,Default,,0,0,0,,这个表达式的含义就变了\nDialogue: 0,0:30:19.34,0:30:20.76,Default,,0,0,0,,这就是自由变量的意思\nDialogue: 0,0:30:22.68,0:30:24.81,Default,,0,0,0,,现在 你们已经学到了一些逻辑学术语\nDialogue: 0,0:30:25.64,0:30:27.58,Default,,0,0,0,,用它们可以解释名字的用法\nDialogue: 0,0:30:28.94,0:30:31.26,Default,,0,0,0,,我们要需要更进一步深入\nDialogue: 0,0:30:32.96,0:30:33.72,Default,,0,0,0,,再多了解一些\nDialogue: 0,0:30:35.13,0:30:36.22,Default,,0,0,0,,我想给你们讲讲\nDialogue: 0,0:30:36.81,0:30:39.76,Default,,0,0,0,,变量被定义的区域\nDialogue: 0,0:30:42.17,0:30:42.88,Default,,0,0,0,,你瞧\nDialogue: 0,0:30:43.37,0:30:45.69,Default,,0,0,0,,目前为止 我们已经相当不正式了\nDialogue: 0,0:30:46.33,0:30:50.16,Default,,0,0,0,,当然 你们中的一些 或者大部分人可能已经理解得很透彻了\nDialogue: 0,0:30:50.36,0:30:52.84,Default,,0,0,0,,在这里被声明的X\nDialogue: 0,0:30:53.64,0:30:55.18,Default,,0,0,0,,只被定义在这里\nDialogue: 0,0:30:58.28,0:31:00.91,Default,,0,0,0,,这个X 只被定义在这里\nDialogue: 0,0:31:01.61,0:31:04.33,Default,,0,0,0,,这个Y 只被定义在这里\nDialogue: 0,0:31:07.10,0:31:09.16,Default,,0,0,0,,我们给这个概念取了个名字 叫“作用域”\nDialogue: 0,0:31:11.61,0:31:13.58,Default,,0,0,0,,我给你们再讲个术语\nDialogue: 0,0:31:14.70,0:31:15.77,Default,,0,0,0,,这个就比较复杂\nDialogue: 0,0:31:15.96,0:31:17.64,Default,,0,0,0,,如果X是E中的一个约束变量\nDialogue: 0,0:31:18.16,0:31:20.24,Default,,0,0,0,,那么它是约束于一个LAMBDA表达式中\nDialogue: 0,0:31:20.89,0:31:24.91,Default,,0,0,0,,LAMBDA表达式是约束变量的唯一方式\nDialogue: 0,0:31:24.91,0:31:25.96,Default,,0,0,0,,你可能会担心\nDialogue: 0,0:31:26.22,0:31:29.05,Default,,0,0,0,,DEFINE是它的一个例外吗？\nDialogue: 0,0:31:29.64,0:31:32.92,Default,,0,0,0,,事实证明 通过巧妙安排 我们可以避免使用DEFINE\nDialogue: 0,0:31:32.92,0:31:33.96,Default,,0,0,0,,一会我们就能看到了\nDialogue: 0,0:31:34.24,0:31:35.72,Default,,0,0,0,,它一个非常神奇的东西\nDialogue: 0,0:31:36.54,0:31:38.40,Default,,0,0,0,,所以我们完全不需要DEFINE\nDialogue: 0,0:31:38.68,0:31:41.55,Default,,0,0,0,,实际上 唯一能创建名字的东西是LAMBDA\nDialogue: 0,0:31:42.64,0:31:43.40,Default,,0,0,0,,这就是它的职责\nDialogue: 0,0:31:44.30,0:31:46.23,Default,,0,0,0,,多么的令人惊奇\nDialogue: 0,0:31:46.23,0:31:47.87,Default,,0,0,0,,很多东西你只凭借LAMBDA就可以计算\nDialogue: 0,0:31:48.73,0:31:49.58,Default,,0,0,0,,但是 在任何情况下\nDialogue: 0,0:31:51.74,0:31:55.76,Default,,0,0,0,,一个LAMBDA表达式有一个地方来声明变量\nDialogue: 0,0:31:55.76,0:31:57.10,Default,,0,0,0,,我们把它称为形式参数表\nDialogue: 0,0:31:58.94,0:32:00.56,Default,,0,0,0,,或者叫 约束变量表\nDialogue: 0,0:32:01.26,0:32:04.51,Default,,0,0,0,,我们说LAMBDA表达式约束了--这是一个动词\nDialogue: 0,0:32:05.02,0:32:07.34,Default,,0,0,0,,--约束了在约束变量表里声明的变量\nDialogue: 0,0:32:08.59,0:32:12.48,Default,,0,0,0,,另外 表达式中定义变量的那些部分\nDialogue: 0,0:32:13.23,0:32:15.23,Default,,0,0,0,,是被一些声明所声明的\nDialogue: 0,0:32:15.56,0:32:19.26,Default,,0,0,0,,这些部分被叫做变量的作用域\nDialogue: 0,0:32:20.44,0:32:21.92,Default,,0,0,0,,所以 这些是作用域\nDialogue: 0,0:32:22.25,0:32:23.68,Default,,0,0,0,,这是Y的作用域\nDialogue: 0,0:32:27.16,0:32:28.54,Default,,0,0,0,,这是X的作用域--\nDialogue: 0,0:32:33.10,0:32:34.03,Default,,0,0,0,,以此类推\nDialogue: 0,0:32:41.32,0:32:42.08,Default,,0,0,0,,好\nDialogue: 0,0:32:43.93,0:32:45.63,Default,,0,0,0,,现在我们有了足够多的术语\nDialogue: 0,0:32:46.60,0:32:51.76,Default,,0,0,0,,可以开始理解如何建立一个新的计算模型了\nDialogue: 0,0:32:51.96,0:32:53.77,Default,,0,0,0,,因为 这里很重要的一点是\nDialogue: 0,0:32:54.94,0:32:57.00,Default,,0,0,0,,我们摧毁了代换模型\nDialogue: 0,0:32:57.18,0:32:58.38,Default,,0,0,0,,我们现在不得不需要一个模型\nDialogue: 0,0:32:58.62,0:33:02.32,Default,,0,0,0,,来体现表示名字被关联到某些地方\nDialogue: 0,0:33:03.93,0:33:05.34,Default,,0,0,0,,因为 如果我们要改变某个东西\nDialogue: 0,0:33:05.98,0:33:07.47,Default,,0,0,0,,我们就需要一个存它的地方\nDialogue: 0,0:33:09.56,0:33:10.35,Default,,0,0,0,,请想一想\nDialogue: 0,0:33:10.83,0:33:13.31,Default,,0,0,0,,如果一个名字只是关联于一个值\nDialogue: 0,0:33:14.04,0:33:16.36,Default,,0,0,0,,如果我试图改变这个名字的含义\nDialogue: 0,0:33:16.73,0:33:20.32,Default,,0,0,0,,这不怎么明确\nDialogue: 0,0:33:20.32,0:33:24.68,Default,,0,0,0,,因为没有名字可以关联的地方\nDialogue: 0,0:33:24.99,0:33:25.80,Default,,0,0,0,,该怎么解释呢……\nDialogue: 0,0:33:25.92,0:33:29.54,Default,,0,0,0,,也就是名字的所有实例之间没有共享任何东西\nDialogue: 0,0:33:29.87,0:33:31.68,Default,,0,0,0,,也就是说 对于一个名字\nDialogue: 0,0:33:31.68,0:33:32.97,Default,,0,0,0,,是用来让我们找到某些东西的\nDialogue: 0,0:33:34.33,0:33:36.36,Default,,0,0,0,,我们把名字给某个东西 然后你拿到了它\nDialogue: 0,0:33:36.73,0:33:39.06,Default,,0,0,0,,你能得到它 是因为我给了你一个它的引用\nDialogue: 0,0:33:39.06,0:33:40.44,Default,,0,0,0,,我把对它的引用给了你\nDialogue: 0,0:33:41.02,0:33:42.30,Default,,0,0,0,,我们会看到很多相关的例子\nDialogue: 0,0:33:43.61,0:33:45.21,Default,,0,0,0,,让我们继续学习“环境”\nDialogue: 0,0:33:46.19,0:33:48.76,Default,,0,0,0,,我需要用一下头顶上的投影仪\nDialogue: 0,0:33:49.31,0:33:49.98,Default,,0,0,0,,谢谢你\nDialogue: 0,0:33:52.19,0:33:53.02,Default,,0,0,0,,这里\nDialogue: 0,0:33:55.48,0:34:00.40,Default,,0,0,0,,是一堆环境结构\nDialogue: 0,0:34:01.53,0:34:05.76,Default,,0,0,0,,环境就是执行虚拟的代换的一种方法\nDialogue: 0,0:34:06.38,0:34:07.89,Default,,0,0,0,,它代表了一个地方\nDialogue: 0,0:34:07.89,0:34:11.39,Default,,0,0,0,,是存储你的未完成的代换的地方\nDialogue: 0,0:34:13.34,0:34:16.50,Default,,0,0,0,,它是一个积累各种东西的地方\nDialogue: 0,0:34:16.50,0:34:21.13,Default,,0,0,0,,在那里 变量的名字与值关联在一起\nDialogue: 0,0:34:21.79,0:34:22.56,Default,,0,0,0,,使得\nDialogue: 0,0:34:22.75,0:34:25.90,Default,,0,0,0,,当你问某个名字是什么意思的时候\nDialogue: 0,0:34:25.90,0:34:27.40,Default,,0,0,0,,你要在一个环境中寻找答案\nDialogue: 0,0:34:28.08,0:34:29.48,Default,,0,0,0,,所以环境是一个函数\nDialogue: 0,0:34:30.80,0:34:31.48,Default,,0,0,0,,或一张表\nDialogue: 0,0:34:32.22,0:34:33.24,Default,,0,0,0,,或类似的东西\nDialogue: 0,0:34:33.24,0:34:34.89,Default,,0,0,0,,但它是一种结构化的表\nDialogue: 0,0:34:35.76,0:34:37.39,Default,,0,0,0,,它是由框架构成\nDialogue: 0,0:34:41.13,0:34:44.46,Default,,0,0,0,,框架是环境的一部分\nDialogue: 0,0:34:44.89,0:34:46.01,Default,,0,0,0,,它们被链接在一起\nDialogue: 0,0:34:47.07,0:34:48.19,Default,,0,0,0,,以某种很好的方式\nDialogue: 0,0:34:49.00,0:34:52.09,Default,,0,0,0,,用一种叫做父链接之类的东西\nDialogue: 0,0:34:54.03,0:34:55.02,Default,,0,0,0,,这里\nDialogue: 0,0:34:55.64,0:34:57.62,Default,,0,0,0,,有一个环境结构\nDialogue: 0,0:34:57.62,0:35:04.22,Default,,0,0,0,,它由三个环境组成 分别是A B和C\nDialogue: 0,0:35:05.10,0:35:07.63,Default,,0,0,0,,D也是环境 但它和C是一样的\nDialogue: 0,0:35:08.88,0:35:10.17,Default,,0,0,0,,它们共享了同一个环境\nDialogue: 0,0:35:11.45,0:35:13.96,Default,,0,0,0,,那就是赋值的本质所在\nDialogue: 0,0:35:14.40,0:35:16.10,Default,,0,0,0,,如果我改变了一个变量\nDialogue: 0,0:35:16.10,0:35:19.80,Default,,0,0,0,,比如改变这个变量的值\nDialogue: 0,0:35:19.80,0:35:23.50,Default,,0,0,0,,那么它将在所有地方都可见\nDialogue: 0,0:35:23.50,0:35:24.84,Default,,0,0,0,,用x来举例\nDialogue: 0,0:35:24.84,0:35:28.19,Default,,0,0,0,,如果我将X改为4\nDialogue: 0,0:35:28.19,0:35:30.19,Default,,0,0,0,,在其他地方也是可见的\nDialogue: 0,0:35:30.19,0:35:32.19,Default,,0,0,0,,但是我们现在不去关心这个\nDialogue: 0,0:35:32.19,0:35:33.84,Default,,0,0,0,,过一会儿会详细讨论这个问题\nDialogue: 0,0:35:34.56,0:35:35.53,Default,,0,0,0,,这里有什么？\nDialogue: 0,0:35:36.76,0:35:38.84,Default,,0,0,0,,这些叫做框架 这是一个框架\nDialogue: 0,0:35:39.40,0:35:40.38,Default,,0,0,0,,这是一个框架\nDialogue: 0,0:35:40.76,0:35:41.84,Default,,0,0,0,,这也是一个框架\nDialogue: 0,0:35:43.18,0:35:45.20,Default,,0,0,0,,A是一个环境\nDialogue: 0,0:35:45.20,0:35:47.82,Default,,0,0,0,,它由框架II\nDialogue: 0,0:35:48.36,0:35:51.05,Default,,0,0,0,,和框架I组成\nDialogue: 0,0:35:52.52,0:35:54.60,Default,,0,0,0,,在这个环境中\nDialogue: 0,0:35:54.99,0:35:59.68,Default,,0,0,0,,在环境C中 在框架II中\nDialogue: 0,0:36:00.48,0:36:03.26,Default,,0,0,0,,X和Y是被约束的\nDialogue: 0,0:36:04.06,0:36:04.78,Default,,0,0,0,,它们具有值\nDialogue: 0,0:36:05.26,0:36:07.18,Default,,0,0,0,,对不起 是在框架I中\nDialogue: 0,0:36:07.18,0:36:08.28,Default,,0,0,0,,而在框架II中\nDialogue: 0,0:36:09.72,0:36:10.83,Default,,0,0,0,,Z被约束\nDialogue: 0,0:36:10.99,0:36:12.17,Default,,0,0,0,,X被约束\nDialogue: 0,0:36:12.44,0:36:13.69,Default,,0,0,0,,并且Y也是被约束的\nDialogue: 0,0:36:15.24,0:36:17.40,Default,,0,0,0,,但是我们看到的X的值\nDialogue: 0,0:36:17.42,0:36:19.04,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:36:20.01,0:36:21.74,Default,,0,0,0,,是这个X 它的值是7\nDialogue: 0,0:36:22.36,0:36:24.84,Default,,0,0,0,,而不是这个值为3的X\nDialogue: 0,0:36:24.84,0:36:27.61,Default,,0,0,0,,我们称之为 这个X遮蔽了这个X\nDialogue: 0,0:36:31.05,0:36:32.49,Default,,0,0,0,,从环境III\nDialogue: 0,0:36:33.44,0:36:34.45,Default,,0,0,0,,从框架III\nDialogue: 0,0:36:34.45,0:36:35.73,Default,,0,0,0,,从环境B\nDialogue: 0,0:36:35.73,0:36:37.18,Default,,0,0,0,,它引用了框架III\nDialogue: 0,0:36:37.45,0:36:42.12,Default,,0,0,0,,变量M和Y被约束 X也被约束\nDialogue: 0,0:36:44.84,0:36:46.97,Default,,0,0,0,,这个Y遮蔽了这个Y\nDialogue: 0,0:36:48.65,0:36:51.00,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:36:51.10,0:36:52.65,Default,,0,0,0,,Y的值是2\nDialogue: 0,0:36:53.45,0:36:55.28,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:36:55.28,0:36:58.64,Default,,0,0,0,,M的值是1 X的值是3\nDialogue: 0,0:37:02.22,0:37:03.15,Default,,0,0,0,,所以 我们有了一个\nDialogue: 0,0:37:03.15,0:37:05.52,Default,,0,0,0,,由框架构成的非常简单的环境结构\nDialogue: 0,0:37:06.38,0:37:09.80,Default,,0,0,0,,它们与过程的应用相一致\nDialogue: 0,0:37:10.94,0:37:12.17,Default,,0,0,0,,我们马上就会看到\nDialogue: 0,0:37:14.41,0:37:17.60,Default,,0,0,0,,现在要给你们看看我们构建的一些其他的很好的小结构\nDialogue: 0,0:37:20.75,0:37:21.71,Default,,0,0,0,,下一张幻灯片\nDialogue: 0,0:37:22.14,0:37:24.36,Default,,0,0,0,,我们可以看到一个对象\nDialogue: 0,0:37:24.84,0:37:26.54,Default,,0,0,0,,我描绘的是一个过程的图像\nDialogue: 0,0:37:27.93,0:37:28.94,Default,,0,0,0,,这是一个过程\nDialogue: 0,0:37:30.11,0:37:31.90,Default,,0,0,0,,过程由两个部分组成\nDialogue: 0,0:37:33.10,0:37:34.80,Default,,0,0,0,,这有点像CONS\nDialogue: 0,0:37:37.21,0:37:38.38,Default,,0,0,0,,不管怎样 它有两个部分\nDialogue: 0,0:37:40.84,0:37:44.72,Default,,0,0,0,,第一个部分指向一些代码\nDialogue: 0,0:37:45.69,0:37:46.94,Default,,0,0,0,,这些代码将会被执行\nDialogue: 0,0:37:47.42,0:37:50.00,Default,,0,0,0,,你可以把它视作一组指令\nDialogue: 0,0:37:50.68,0:37:52.83,Default,,0,0,0,,第二部分是环境\nDialogue: 0,0:37:53.88,0:37:55.50,Default,,0,0,0,,这就是过程的全部了\nDialogue: 0,0:37:57.16,0:37:58.40,Default,,0,0,0,,我们要用它\nDialogue: 0,0:37:58.71,0:38:05.16,Default,,0,0,0,,来捕获出现在过程中的自由变量的值\nDialogue: 0,0:38:06.17,0:38:08.09,Default,,0,0,0,,如果变量出现在过程中\nDialogue: 0,0:38:08.11,0:38:09.92,Default,,0,0,0,,它不是被约束的就是自由的\nDialogue: 0,0:38:11.10,0:38:11.96,Default,,0,0,0,,如果它是被约束的\nDialogue: 0,0:38:12.57,0:38:14.56,Default,,0,0,0,,则它的值将很容易被找到\nDialogue: 0,0:38:16.11,0:38:18.64,Default,,0,0,0,,它将存在于某个很容易找到的环境中\nDialogue: 0,0:38:18.91,0:38:19.87,Default,,0,0,0,,如果它是自由的\nDialogue: 0,0:38:20.86,0:38:23.02,Default,,0,0,0,,我们就必须在过程中放入一些东西\nDialogue: 0,0:38:23.02,0:38:24.81,Default,,0,0,0,,用来指导我们查询自由变量的值\nDialogue: 0,0:38:27.05,0:38:29.21,Default,,0,0,0,,相关理由目前还不清楚\nDialogue: 0,0:38:29.21,0:38:30.60,Default,,0,0,0,,但很快就要真相大白了\nDialogue: 0,0:38:32.32,0:38:34.97,Default,,0,0,0,,这里有一个对象 它是个复合对象\nDialogue: 0,0:38:35.34,0:38:41.64,Default,,0,0,0,,由一些代码和一个环境结构组成\nDialogue: 0,0:38:42.72,0:38:45.50,Default,,0,0,0,,现在我要告诉你们一些全新的规则\nDialogue: 0,0:38:46.41,0:38:47.47,Default,,0,0,0,,关于执行的规则\nDialogue: 0,0:38:50.54,0:38:52.20,Default,,0,0,0,,仅有的两条规则的第一条是--\nDialogue: 0,0:38:53.20,0:38:55.39,Default,,0,0,0,,这些规则与代换模型规则相对应\nDialogue: 0,0:38:57.26,0:38:59.32,Default,,0,0,0,,第一条规则是用来解决\nDialogue: 0,0:38:59.66,0:39:02.78,Default,,0,0,0,,如何把一个过程 应用到参数上的问题\nDialogue: 0,0:39:05.28,0:39:08.54,Default,,0,0,0,,程序对象被应用于一组参数\nDialogue: 0,0:39:08.96,0:39:10.43,Default,,0,0,0,,是通过构建一个新的框架来完成\nDialogue: 0,0:39:11.31,0:39:15.76,Default,,0,0,0,,那个框架将包含形式参数\nDialogue: 0,0:39:15.83,0:39:19.48,Default,,0,0,0,,到调用中使用的实际参数的映射\nDialogue: 0,0:39:21.42,0:39:22.20,Default,,0,0,0,,如你所知\nDialogue: 0,0:39:22.31,0:39:26.94,Default,,0,0,0,,当我们调用一个过程 如(LAMBDA (X) (* X Y))\nDialogue: 0,0:39:26.94,0:39:29.13,Default,,0,0,0,,然后我们以3为参数调用它\nDialogue: 0,0:39:30.19,0:39:32.75,Default,,0,0,0,,那么我们需要某个从X到3的映射\nDialogue: 0,0:39:34.19,0:39:37.39,Default,,0,0,0,,你可以把它想做是代换的一种\nDialogue: 0,0:39:38.27,0:39:40.30,Default,,0,0,0,,在旧的模型中 用3代换X\nDialogue: 0,0:39:42.00,0:39:44.80,Default,,0,0,0,,所以我要建立一个框架\nDialogue: 0,0:39:45.15,0:39:46.60,Default,,0,0,0,,在框架中包含X等于3的这个信息\nDialogue: 0,0:39:49.12,0:39:49.71,Default,,0,0,0,,现在\nDialogue: 0,0:39:50.33,0:39:53.31,Default,,0,0,0,,过程的体即将被执行\nDialogue: 0,0:39:54.16,0:39:56.44,Default,,0,0,0,,它将在一个环境中执行\nDialogue: 0,0:39:57.80,0:40:08.03,Default,,0,0,0,,这个环境是由我们创建的新框架邻接组合而成\nDialogue: 0,0:40:08.54,0:40:11.69,Default,,0,0,0,,它是我们所应用的过程的一部分\nDialogue: 0,0:40:13.15,0:40:15.77,Default,,0,0,0,,所以 举个例子\nDialogue: 0,0:40:19.20,0:40:24.12,Default,,0,0,0,,假设我有一些环境\nDialogue: 0,0:40:25.15,0:40:27.23,Default,,0,0,0,,画个方框代表它\nDialogue: 0,0:40:27.96,0:40:32.19,Default,,0,0,0,,以及一些过程--我画圆来代表它们 因为这比小三角形好画--\nDialogue: 0,0:40:33.04,0:40:36.36,Default,,0,0,0,,抱歉 是菱形\nDialogue: 0,0:40:37.66,0:40:40.78,Default,,0,0,0,,小块菱形的果冻之类的东西\nDialogue: 0,0:40:42.68,0:40:45.32,Default,,0,0,0,,这有一个使用这个环境的过程\nDialogue: 0,0:40:45.95,0:40:48.16,Default,,0,0,0,,这个过程有一些代码\nDialogue: 0,0:40:48.16,0:40:49.68,Default,,0,0,0,,是一个LAMBDA表达式\nDialogue: 0,0:40:50.12,0:40:51.69,Default,,0,0,0,,约束了X和Y\nDialogue: 0,0:40:53.15,0:40:56.43,Default,,0,0,0,,然后执行了表达式E\nDialogue: 0,0:40:57.93,0:40:58.99,Default,,0,0,0,,这个过程就是这样的\nDialogue: 0,0:40:59.56,0:41:00.57,Default,,0,0,0,,我们叫它P\nDialogue: 0,0:41:01.44,0:41:05.79,Default,,0,0,0,,我希望将这个过程应用于3和4\nDialogue: 0,0:41:06.38,0:41:08.36,Default,,0,0,0,,所以我在这写(P 3 4)\nDialogue: 0,0:41:09.76,0:41:12.17,Default,,0,0,0,,我要做的事情则是 创建一个新的框架\nDialogue: 0,0:41:13.15,0:41:14.12,Default,,0,0,0,,创建一个框架\nDialogue: 0,0:41:15.24,0:41:18.28,Default,,0,0,0,,框架中X等于3\nDialogue: 0,0:41:18.84,0:41:20.51,Default,,0,0,0,,而Y等于4\nDialogue: 0,0:41:21.69,0:41:23.48,Default,,0,0,0,,我要把这个框架\nDialogue: 0,0:41:24.27,0:41:25.37,Default,,0,0,0,,连接到这一个框架上\nDialogue: 0,0:41:27.63,0:41:28.99,Default,,0,0,0,,对于这个环境\nDialogue: 0,0:41:29.68,0:41:30.97,Default,,0,0,0,,我把它叫做B\nDialogue: 0,0:41:31.55,0:41:35.02,Default,,0,0,0,,我会在这个环境中求值E的体\nDialogue: 0,0:41:39.88,0:41:40.33,Default,,0,0,0,,现在\nDialogue: 0,0:41:41.95,0:41:45.04,Default,,0,0,0,,E可能包含了X和Y的引用以及一些别的东西\nDialogue: 0,0:41:46.84,0:41:49.95,Default,,0,0,0,,X和Y的值在这里\nDialogue: 0,0:41:50.70,0:41:52.52,Default,,0,0,0,,其他的变量的值在这里\nDialogue: 0,0:41:55.05,0:41:56.25,Default,,0,0,0,,怎样才能获取这个框架呢？\nDialogue: 0,0:41:57.26,0:41:59.26,Default,,0,0,0,,我们通过过程构建来完成\nDialogue: 0,0:41:59.61,0:42:00.60,Default,,0,0,0,,这就是另一条规则了\nDialogue: 0,0:42:02.03,0:42:04.40,Default,,0,0,0,,请看下一张幻灯片\nDialogue: 0,0:42:05.34,0:42:06.12,Default,,0,0,0,,规则二\nDialogue: 0,0:42:07.80,0:42:09.90,Default,,0,0,0,,当一个LAMBDA表达式被求值时\nDialogue: 0,0:42:09.90,0:42:11.76,Default,,0,0,0,,相对于某个特定的环境--\nDialogue: 0,0:42:14.19,0:42:14.40,Default,,0,0,0,,例如\nDialogue: 0,0:42:15.04,0:42:18.12,Default,,0,0,0,,获取一个过程的方式就是求值一个LAMBDA表达式\nDialogue: 0,0:42:18.19,0:42:19.36,Default,,0,0,0,,这里有一个LAMBDA表达式\nDialogue: 0,0:42:20.04,0:42:21.12,Default,,0,0,0,,通过对它求值\nDialogue: 0,0:42:21.90,0:42:23.96,Default,,0,0,0,,我获得了一个可以应用于3的过程\nDialogue: 0,0:42:25.08,0:42:26.65,Default,,0,0,0,,现在这个LAMBDA表达式\nDialogue: 0,0:42:26.65,0:42:30.38,Default,,0,0,0,,在一个Y已被定义的环境中执行\nDialogue: 0,0:42:31.84,0:42:35.84,Default,,0,0,0,,我希望这个过程的体中包括的Y是自由的\nDialogue: 0,0:42:36.39,0:42:38.36,Default,,0,0,0,,在这里面 Y是自由的\nDialogue: 0,0:42:38.72,0:42:40.38,Default,,0,0,0,,但是在整个的表达式中却是被约束的\nDialogue: 0,0:42:41.36,0:42:42.75,Default,,0,0,0,,而在这里是自由的\nDialogue: 0,0:42:43.32,0:42:46.24,Default,,0,0,0,,我想让这两个Y指称同一个Y\nDialogue: 0,0:42:47.44,0:42:55.13,Default,,0,0,0,,我在Y被创建的环境中求值这个过程的体\nDialogue: 0,0:42:55.32,0:42:58.40,Default,,0,0,0,,就像这个一样 因为那是通过应用完成的\nDialogue: 0,0:42:59.00,0:42:59.63,Default,,0,0,0,,现在\nDialogue: 0,0:43:00.24,0:43:02.60,Default,,0,0,0,,如果我还想查找Y的值\nDialogue: 0,0:43:03.10,0:43:04.09,Default,,0,0,0,,我就必须知道它在哪\nDialogue: 0,0:43:04.54,0:43:06.42,Default,,0,0,0,,因此 这个过程在被创建时\nDialogue: 0,0:43:06.42,0:43:10.06,Default,,0,0,0,,过程的创建 也就是对LAMBDA表达式求值的结果\nDialogue: 0,0:43:10.06,0:43:16.33,Default,,0,0,0,,最好是获取一个指针或记住Y被约束在哪个框架中\nDialogue: 0,0:43:17.92,0:43:19.76,Default,,0,0,0,,这就是这个规则的内容\nDialogue: 0,0:43:22.11,0:43:23.13,Default,,0,0,0,,那么 举个例子\nDialogue: 0,0:43:24.44,0:43:29.32,Default,,0,0,0,,如果我恰好求值了一个LAMBDA表达式\nDialogue: 0,0:43:30.89,0:43:33.32,Default,,0,0,0,,在E中的LAMBDA表达式\nDialogue: 0,0:43:34.04,0:43:40.46,Default,,0,0,0,,在E中求值(LAMBDA (X Y) G)\nDialogue: 0,0:43:41.08,0:43:42.36,Default,,0,0,0,,对其求值\nDialogue: 0,0:43:42.97,0:43:46.17,Default,,0,0,0,,这些事的意义就是我现在构建了一个过程对象\nDialogue: 0,0:43:47.10,0:43:48.28,Default,,0,0,0,,E是某个环境\nDialogue: 0,0:43:48.84,0:43:50.94,Default,,0,0,0,,有个指针指向E\nDialogue: 0,0:43:51.79,0:43:56.68,Default,,0,0,0,,我构建了一个过程对象指向了这个环境\nDialogue: 0,0:43:58.56,0:44:00.11,Default,,0,0,0,,它的代码\nDialogue: 0,0:44:00.54,0:44:03.24,Default,,0,0,0,,是一个LAMBDA表达式 或者是某种中间代码\nDialogue: 0,0:44:06.24,0:44:07.56,Default,,0,0,0,,而这就是一个过程\nDialogue: 0,0:44:12.38,0:44:14.70,Default,,0,0,0,,它为我生成了这个和这个\nDialogue: 0,0:44:14.94,0:44:16.37,Default,,0,0,0,,这个对象\nDialogue: 0,0:44:16.37,0:44:18.12,Default,,0,0,0,,这个环境指针\nDialogue: 0,0:44:18.37,0:44:22.52,Default,,0,0,0,,获取了求值LAMBDA表达式时的环境\nDialogue: 0,0:44:22.62,0:44:24.59,Default,,0,0,0,,定义所使用的环境\nDialogue: 0,0:44:25.58,0:44:27.40,Default,,0,0,0,,创建一个过程时的定义所用的环境\nDialogue: 0,0:44:30.32,0:44:31.47,Default,,0,0,0,,从而创建了过程\nDialogue: 0,0:44:32.89,0:44:36.30,Default,,0,0,0,,所以 它将环境从定义过程的地方取出\nDialogue: 0,0:44:37.42,0:44:38.92,Default,,0,0,0,,将它保存在过程自己内部\nDialogue: 0,0:44:39.60,0:44:40.97,Default,,0,0,0,,之后当过程被调用时\nDialogue: 0,0:44:41.32,0:44:43.47,Default,,0,0,0,,它在被定义时的环境\nDialogue: 0,0:44:43.98,0:44:45.07,Default,,0,0,0,,将由新的框架扩充\nDialogue: 0,0:44:48.72,0:44:52.33,Default,,0,0,0,,这给了我们一个放置有值的变量的地方\nDialogue: 0,0:44:53.04,0:44:53.96,Default,,0,0,0,,举个例子\nDialogue: 0,0:44:53.96,0:44:56.81,Default,,0,0,0,,如果有很多东西指向那这个环境\nDialogue: 0,0:44:57.74,0:45:00.33,Default,,0,0,0,,它们就会共享这个环境\nDialogue: 0,0:45:01.20,0:45:02.52,Default,,0,0,0,,我们很快将会见到\nDialogue: 0,0:45:04.01,0:45:05.34,Default,,0,0,0,,现在你们有了一个新模型\nDialogue: 0,0:45:06.38,0:45:09.92,Default,,0,0,0,,我们用它来理解程序的执行\nDialogue: 0,0:45:11.36,0:45:12.78,Default,,0,0,0,,我觉得现在我应该解答一些问题了\nDialogue: 0,0:45:13.10,0:45:14.96,Default,,0,0,0,,之后我们再继续\nDialogue: 0,0:45:18.19,0:45:19.52,Default,,0,0,0,,学生：这么说是对的吗？\nDialogue: 0,0:45:19.52,0:45:23.96,Default,,0,0,0,,环境就是一些被连接在一起的框架\nDialogue: 0,0:45:23.96,0:45:25.10,Default,,0,0,0,,教授：对\nDialogue: 0,0:45:25.48,0:45:26.64,Default,,0,0,0,,学生：通过它能够访问所有的框架？\nDialogue: 0,0:45:27.71,0:45:31.45,Default,,0,0,0,,教授：是的 环境是一系列被连接在一起的框架\nDialogue: 0,0:45:32.43,0:45:35.47,Default,,0,0,0,,我对它的理解是 它是指向第一个框架的指针\nDialogue: 0,0:45:36.88,0:45:38.72,Default,,0,0,0,,因为一旦你获得了它 你就能拿到所有的框架\nDialogue: 0,0:45:43.96,0:45:44.65,Default,,0,0,0,,还有谁有问题吗？\nDialogue: 0,0:45:45.20,0:45:49.36,Default,,0,0,0,,学生：有可能在两个不同的环境中定义或求值一个过程\nDialogue: 0,0:45:49.36,0:45:53.20,Default,,0,0,0,,使得它有不同的行为 并且有指向两个环境的指针--\nDialogue: 0,0:45:53.20,0:45:55.77,Default,,0,0,0,,教授：噢 是的 同一个过程不会有两个不同环境\nDialogue: 0,0:45:56.90,0:45:59.02,Default,,0,0,0,,同样的代码\nDialogue: 0,0:45:59.02,0:46:00.82,Default,,0,0,0,,比如同样的LAMBDA表达式\nDialogue: 0,0:46:00.82,0:46:03.72,Default,,0,0,0,,再不同的环境下求值可能产生不同的过程\nDialogue: 0,0:46:06.03,0:46:07.18,Default,,0,0,0,,每个过程--\nDialogue: 0,0:46:07.18,0:46:09.95,Default,,0,0,0,,学生：它们的定义有同样的名字 它们的运算--\nDialogue: 0,0:46:09.95,0:46:11.92,Default,,0,0,0,,教授：它们定义是写起来是一样的 使用同样的字母\nDialogue: 0,0:46:12.56,0:46:14.62,Default,,0,0,0,,我能求值那一组字母\nDialogue: 0,0:46:14.93,0:46:18.14,Default,,0,0,0,,或定义的表结构之类的东西\nDialogue: 0,0:46:18.22,0:46:20.41,Default,,0,0,0,,那只是文本表示\nDialogue: 0,0:46:20.91,0:46:24.86,Default,,0,0,0,,我可以在两个不同环境种对它求值 产生两个不同的过程\nDialogue: 0,0:46:25.55,0:46:26.84,Default,,0,0,0,,每一个过程\nDialogue: 0,0:46:27.56,0:46:32.19,Default,,0,0,0,,有它们自己的一组局部变量\nDialogue: 0,0:46:32.34,0:46:33.45,Default,,0,0,0,,我们很快就会看到\nDialogue: 0,0:46:36.70,0:46:37.36,Default,,0,0,0,,还有问题吗？\nDialogue: 0,0:46:42.60,0:46:44.03,Default,,0,0,0,,好 谢谢大家 我们休息一会\nDialogue: 0,0:46:47.98,0:46:57.61,Default,,0,0,0,,[音乐]\nDialogue: 0,0:46:57.61,0:47:02.03,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:47:05.98,0:47:09.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:47:09.69,0:47:13.44,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:47:13.47,0:47:18.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}赋值、状态和副作用\nDialogue: 0,0:47:22.67,0:47:25.69,Default,,0,0,0,,现在 我已经对你们做了一件非常糟糕的事儿\nDialogue: 0,0:47:26.56,0:47:30.54,Default,,0,0,0,,我引入了一个非常复杂的东西\nDialogue: 0,0:47:32.76,0:47:33.42,Default,,0,0,0,,赋值\nDialogue: 0,0:47:34.51,0:47:38.08,Default,,0,0,0,,它摧毁了我们程序中大部分的 有趣的数学特性\nDialogue: 0,0:47:41.07,0:47:42.46,Default,,0,0,0,,我为什么要做这件事呢\nDialogue: 0,0:47:43.18,0:47:45.02,Default,,0,0,0,,这样做可能有什么好处吗？\nDialogue: 0,0:47:46.51,0:47:48.86,Default,,0,0,0,,很明显 这不是一个什么好东西\nDialogue: 0,0:47:49.60,0:47:51.23,Default,,0,0,0,,因此我最好有一个好的理由\nDialogue: 0,0:47:52.83,0:47:54.80,Default,,0,0,0,,让我们来小小地玩一下\nDialogue: 0,0:47:54.80,0:47:58.35,Default,,0,0,0,,首先 我们写些非常有趣的带赋值的程序\nDialogue: 0,0:47:58.81,0:48:00.88,Default,,0,0,0,,来理解它们的特殊之处\nDialogue: 0,0:48:01.42,0:48:02.83,Default,,0,0,0,,这些特殊之处使赋值变得有价值\nDialogue: 0,0:48:04.96,0:48:06.70,Default,,0,0,0,,我们从一个非常简单的程序开始\nDialogue: 0,0:48:07.69,0:48:09.28,Default,,0,0,0,,我把这个程序叫做MAKE-COUNTER\nDialogue: 0,0:48:10.48,0:48:18.19,Default,,0,0,0,,我要把它定义为\nDialogue: 0,0:48:24.17,0:48:28.12,Default,,0,0,0,,接受一个参数N的过程\nDialogue: 0,0:48:29.23,0:48:32.94,Default,,0,0,0,,并且它的返回值是一个没有参数的过程--\nDialogue: 0,0:48:34.36,0:48:36.03,Default,,0,0,0,,一个生成过程的过程--\nDialogue: 0,0:48:36.84,0:48:44.35,Default,,0,0,0,,这个过程把N的值设为N+1\nDialogue: 0,0:48:47.88,0:48:49.77,Default,,0,0,0,,并且返回N的值\nDialogue: 0,0:48:55.37,0:48:57.54,Default,,0,0,0,,现在 我们要研究它的行为\nDialogue: 0,0:48:57.54,0:48:59.02,Default,,0,0,0,,它很有趣\nDialogue: 0,0:48:59.82,0:49:01.45,Default,,0,0,0,,为了研究它的行为\nDialogue: 0,0:49:01.45,0:49:03.08,Default,,0,0,0,,我需要建立一个环境模型\nDialogue: 0,0:49:04.11,0:49:05.98,Default,,0,0,0,,因为我们不能通过其他的方式来理解它\nDialogue: 0,0:49:08.65,0:49:09.63,Default,,0,0,0,,所以我们开始吧\nDialogue: 0,0:49:10.00,0:49:12.86,Default,,0,0,0,,我们从这里开始\nDialogue: 0,0:49:13.24,0:49:15.90,Default,,0,0,0,,假设机器天生就有一个全局环境\nDialogue: 0,0:49:16.13,0:49:17.12,Default,,0,0,0,,我们把它叫做Global\nDialogue: 0,0:49:20.03,0:49:24.25,Default,,0,0,0,,它内部有一堆初始化的东西\nDialogue: 0,0:49:24.44,0:49:25.60,Default,,0,0,0,,我们都知道它里面有什么\nDialogue: 0,0:49:25.72,0:49:30.88,Default,,0,0,0,,这里面有+和*\nDialogue: 0,0:49:32.24,0:49:37.26,Default,,0,0,0,,/ -和CAR\nDialogue: 0,0:49:38.70,0:49:39.74,Default,,0,0,0,,以此类推\nDialogue: 0,0:49:41.45,0:49:42.48,Default,,0,0,0,,有很多东西\nDialogue: 0,0:49:42.88,0:49:43.98,Default,,0,0,0,,我不知道它们是什么\nDialogue: 0,0:49:44.42,0:49:45.55,Default,,0,0,0,,一些乱七八糟的符号\nDialogue: 0,0:49:46.08,0:49:48.88,Default,,0,0,0,,机器一开始就有这些特性\nDialogue: 0,0:49:51.21,0:49:53.23,Default,,0,0,0,,通过在这做定义\nDialogue: 0,0:49:54.68,0:49:55.76,Default,,0,0,0,,我要做的是--\nDialogue: 0,0:49:56.32,0:49:57.31,Default,,0,0,0,,我在干什么呢？\nDialogue: 0,0:49:57.31,0:49:59.58,Default,,0,0,0,,我要把它关联到全局环境上\nDialogue: 0,0:49:59.72,0:50:01.29,Default,,0,0,0,,这是我的环境指针\nDialogue: 0,0:50:03.72,0:50:06.70,Default,,0,0,0,,为了达到那个目的 我要求值这个LAMBDA表达式\nDialogue: 0,0:50:08.35,0:50:10.01,Default,,0,0,0,,这意味着我创建了一个过程对象\nDialogue: 0,0:50:11.50,0:50:13.26,Default,,0,0,0,,所以 我要在这创建一个过程对象\nDialogue: 0,0:50:17.36,0:50:18.68,Default,,0,0,0,,这个过程对象\nDialogue: 0,0:50:18.72,0:50:20.49,Default,,0,0,0,,由于在它被定义的地方\nDialogue: 0,0:50:21.16,0:50:22.35,Default,,0,0,0,,有一个全局的环境\nDialogue: 0,0:50:24.06,0:50:25.79,Default,,0,0,0,,这个过程对象包括了\nDialogue: 0,0:50:28.16,0:50:31.47,Default,,0,0,0,,以N为参数的过程的代码\nDialogue: 0,0:50:31.96,0:50:35.34,Default,,0,0,0,,它返回一个不接受参数的过程\nDialogue: 0,0:50:38.24,0:50:43.28,Default,,0,0,0,,DEFINE是一种改变环境的方法\nDialogue: 0,0:50:44.32,0:50:46.73,Default,,0,0,0,,所以我把MAKE-COUNTER加入全局环境中\nDialogue: 0,0:50:52.28,0:50:55.05,Default,,0,0,0,,这是对于特殊的东西定义的一个特殊的规则\nDialogue: 0,0:50:55.82,0:50:56.94,Default,,0,0,0,,但它其实是\nDialogue: 0,0:50:58.94,0:51:01.96,Default,,0,0,0,,它给了我们一个指针 指向那个过程\nDialogue: 0,0:51:03.82,0:51:06.32,Default,,0,0,0,,所以现在全局环境中也有了MAKE-COUNTER\nDialogue: 0,0:51:09.28,0:51:11.21,Default,,0,0,0,,现在 我们要进行一些操作\nDialogue: 0,0:51:11.87,0:51:13.50,Default,,0,0,0,,我要用它来创建一些计数器\nDialogue: 0,0:51:14.99,0:51:16.20,Default,,0,0,0,,我们来看看计数器是什么\nDialogue: 0,0:51:17.12,0:51:18.51,Default,,0,0,0,,所以我们定义\nDialogue: 0,0:51:23.32,0:51:26.65,Default,,0,0,0,,C1为一个从0开始的计数器\nDialogue: 0,0:51:35.72,0:51:38.38,Default,,0,0,0,,根据模型 我们知道如何做这个了\nDialogue: 0,0:51:39.63,0:51:44.33,Default,,0,0,0,,我需要在全局环境中求值这个表达式\nDialogue: 0,0:51:45.40,0:51:46.27,Default,,0,0,0,,(MAKE-COUNTER 0)\nDialogue: 0,0:51:47.80,0:51:51.10,Default,,0,0,0,,我查找MAKE-COUNTER 发现它是一个过程\nDialogue: 0,0:51:53.61,0:51:55.29,Default,,0,0,0,,我将要应用这个过程\nDialogue: 0,0:51:56.22,0:51:57.74,Default,,0,0,0,,应用这个过程的方式\nDialogue: 0,0:51:58.43,0:51:59.96,Default,,0,0,0,,就是构建一个框架\nDialogue: 0,0:52:01.80,0:52:03.79,Default,,0,0,0,,所以我构建了一个框架\nDialogue: 0,0:52:06.59,0:52:10.44,Default,,0,0,0,,它内部有一个N的值\nDialogue: 0,0:52:11.77,0:52:12.64,Default,,0,0,0,,这个值是0\nDialogue: 0,0:52:14.00,0:52:15.34,Default,,0,0,0,,它的父环境\nDialogue: 0,0:52:15.87,0:52:19.32,Default,,0,0,0,,就是定义MAKE-COUNTER时的环境\nDialogue: 0,0:52:23.93,0:52:28.36,Default,,0,0,0,,所以我已经通过将MAKE-COUNTER应用于0上 而创建了一个环境\nDialogue: 0,0:52:31.45,0:52:34.40,Default,,0,0,0,,现在 我需要求值MAKE-COUNTER的体\nDialogue: 0,0:52:34.41,0:52:37.72,Default,,0,0,0,,就是那个环境中的LAMBDA表达式\nDialogue: 0,0:52:40.64,0:52:42.30,Default,,0,0,0,,求值这个体\nDialogue: 0,0:52:42.76,0:52:44.59,Default,,0,0,0,,它是一个LAMBDA表达式\nDialogue: 0,0:52:46.28,0:52:48.86,Default,,0,0,0,,对LAMBDA表达式求值 意味着创建一个过程对象\nDialogue: 0,0:52:49.56,0:52:51.00,Default,,0,0,0,,所以我将创建一个过程对象\nDialogue: 0,0:52:56.76,0:52:58.29,Default,,0,0,0,,这个过程对象\nDialogue: 0,0:52:58.29,0:53:00.46,Default,,0,0,0,,拥有一个环境\nDialogue: 0,0:53:04.20,0:53:05.88,Default,,0,0,0,,在这个环境中N被定义为0\nDialogue: 0,0:53:07.68,0:53:08.80,Default,,0,0,0,,它有一些代码\nDialogue: 0,0:53:08.83,0:53:11.37,Default,,0,0,0,,这个过程不需要参数\nDialogue: 0,0:53:11.40,0:53:15.28,Default,,0,0,0,,该过程进行一些处理 然后进行赋值\nDialogue: 0,0:53:15.28,0:53:16.73,Default,,0,0,0,,并返回N\nDialogue: 0,0:53:17.88,0:53:18.81,Default,,0,0,0,,这个东西\nDialogue: 0,0:53:19.42,0:53:21.23,Default,,0,0,0,,将成为一个对象\nDialogue: 0,0:53:21.92,0:53:24.67,Default,,0,0,0,,在全局环境中 它的名字是C1\nDialogue: 0,0:53:26.12,0:53:28.33,Default,,0,0,0,,所以我们在这建立一个名字 C1\nDialogue: 0,0:53:28.64,0:53:32.14,Default,,0,0,0,,并且说C1等于这个过程\nDialogue: 0,0:53:35.48,0:53:37.36,Default,,0,0,0,,现在 再来创建另一个计数器\nDialogue: 0,0:53:43.04,0:53:45.13,Default,,0,0,0,,通过MAKE-COUNTER创建c2\nDialogue: 0,0:53:50.94,0:53:52.19,Default,,0,0,0,,让它从10开始\nDialogue: 0,0:53:54.25,0:53:55.90,Default,,0,0,0,,然后我执行同样的步骤\nDialogue: 0,0:53:56.64,0:54:00.40,Default,,0,0,0,,我应用这个MAKE-COUNTER过程\nDialogue: 0,0:54:00.99,0:54:04.52,Default,,0,0,0,,建立另一个框架 其中N等于10\nDialogue: 0,0:54:05.63,0:54:09.18,Default,,0,0,0,,全局环境作为它的父环境\nDialogue: 0,0:54:10.04,0:54:11.80,Default,,0,0,0,,然后我构建一个过程\nDialogue: 0,0:54:13.04,0:54:17.63,Default,,0,0,0,,以这个框架作为它定义的环境\nDialogue: 0,0:54:18.27,0:54:21.66,Default,,0,0,0,,它的代码是\nDialogue: 0,0:54:21.80,0:54:24.38,Default,,0,0,0,,完成一些操作的无参过程\nDialogue: 0,0:54:25.54,0:54:28.60,Default,,0,0,0,,然后进行赋值 等等\nDialogue: 0,0:54:28.60,0:54:31.22,Default,,0,0,0,,然后返回N\nDialogue: 0,0:54:31.45,0:54:34.83,Default,,0,0,0,,这就是C2\nDialogue: 0,0:54:36.88,0:54:39.32,Default,,0,0,0,,好 你们应该发现 某些东西开始变得有趣了\nDialogue: 0,0:54:40.17,0:54:41.92,Default,,0,0,0,,这里有两个N\nDialogue: 0,0:54:42.92,0:54:44.19,Default,,0,0,0,,它们不是同一个N\nDialogue: 0,0:54:46.14,0:54:48.16,Default,,0,0,0,,我每次调用MAKE-COUNTER的时候\nDialogue: 0,0:54:48.64,0:54:50.25,Default,,0,0,0,,我就创建了另一个N的实例\nDialogue: 0,0:54:52.62,0:54:54.40,Default,,0,0,0,,它们彼此独立 没有关联\nDialogue: 0,0:54:57.79,0:55:00.28,Default,,0,0,0,,现在 我们来使用一下这些计数器\nDialogue: 0,0:55:05.92,0:55:15.00,Default,,0,0,0,,如果此时 我调用C1 会发生什么？\nDialogue: 0,0:55:15.84,0:55:17.34,Default,,0,0,0,,我会在这里查找\nDialogue: 0,0:55:17.56,0:55:19.98,Default,,0,0,0,,发现C1是一个过程\nDialogue: 0,0:55:20.64,0:55:22.78,Default,,0,0,0,,我要不带参数地调用这个过程\nDialogue: 0,0:55:23.16,0:55:24.96,Default,,0,0,0,,因为它不需要参数\nDialogue: 0,0:55:24.96,0:55:25.63,Default,,0,0,0,,对吧？\nDialogue: 0,0:55:26.97,0:55:27.84,Default,,0,0,0,,它的体是什么呢？\nDialogue: 0,0:55:27.96,0:55:30.02,Default,,0,0,0,,我得来这里解释 因为我没有给誊过来\nDialogue: 0,0:55:30.02,0:55:32.65,Default,,0,0,0,,这个过程体是将N赋值为N+1\nDialogue: 0,0:55:33.80,0:55:34.89,Default,,0,0,0,,并且返回N\nDialogue: 0,0:55:37.12,0:55:38.12,Default,,0,0,0,,就是把N增大1\nDialogue: 0,0:55:38.97,0:55:41.60,Default,,0,0,0,,它的N指的是这个\nDialogue: 0,0:55:43.08,0:55:44.60,Default,,0,0,0,,所以我把这个n增大1\nDialogue: 0,0:55:45.80,0:55:47.00,Default,,0,0,0,,它变成了1\nDialogue: 0,0:55:48.64,0:55:50.24,Default,,0,0,0,,然后返回了1\nDialogue: 0,0:55:53.13,0:55:56.49,Default,,0,0,0,,之后我调用C2\nDialogue: 0,0:55:58.38,0:55:59.20,Default,,0,0,0,,我会做什么？\nDialogue: 0,0:55:59.23,0:56:03.33,Default,,0,0,0,,C2是相同的过程\nDialogue: 0,0:56:03.33,0:56:04.48,Default,,0,0,0,,但这个N\nDialogue: 0,0:56:05.33,0:56:06.57,Default,,0,0,0,,它变成了11\nDialogue: 0,0:56:10.97,0:56:14.59,Default,,0,0,0,,所以返回值是11\nDialogue: 0,0:56:15.92,0:56:18.32,Default,,0,0,0,,然后我们再来调用一下C1\nDialogue: 0,0:56:20.91,0:56:22.56,Default,,0,0,0,,C1是这个\nDialogue: 0,0:56:23.28,0:56:24.16,Default,,0,0,0,,它是2\nDialogue: 0,0:56:27.24,0:56:28.30,Default,,0,0,0,,所以结果是2\nDialogue: 0,0:56:29.66,0:56:30.75,Default,,0,0,0,,然后调用C2\nDialogue: 0,0:56:33.37,0:56:35.31,Default,,0,0,0,,然后C2通过同样的方法 返回了12\nDialogue: 0,0:56:35.74,0:56:37.55,Default,,0,0,0,,它在这里进行查找\nDialogue: 0,0:56:37.55,0:56:39.28,Default,,0,0,0,,发现了N 并把它加1\nDialogue: 0,0:56:41.64,0:56:43.68,Default,,0,0,0,,我拥有的是可计算的对象\nDialogue: 0,0:56:45.21,0:56:46.86,Default,,0,0,0,,它们是两个计数器\nDialogue: 0,0:56:48.96,0:56:51.02,Default,,0,0,0,,每一个都有各自独立的局部状态\nDialogue: 0,0:56:55.48,0:56:56.62,Default,,0,0,0,,我们再进一步\nDialogue: 0,0:56:56.64,0:56:58.52,Default,,0,0,0,,这是个奇怪的东西\nDialogue: 0,0:57:01.12,0:57:02.22,Default,,0,0,0,,什么是对象？\nDialogue: 0,0:57:04.11,0:57:06.12,Default,,0,0,0,,这个概念并不明确\nDialogue: 0,0:57:07.55,0:57:09.45,Default,,0,0,0,,我们倾向于以对象的角度思考\nDialogue: 0,0:57:11.24,0:57:13.32,Default,,0,0,0,,因为这样思考比较经济\nDialogue: 0,0:57:14.62,0:57:17.28,Default,,0,0,0,,这是一种智力上的经济\nDialogue: 0,0:57:18.57,0:57:19.61,Default,,0,0,0,,我是一个对象\nDialogue: 0,0:57:20.99,0:57:22.30,Default,,0,0,0,,你也是一个对象\nDialogue: 0,0:57:23.55,0:57:25.29,Default,,0,0,0,,但我们不是同一个对象\nDialogue: 0,0:57:27.52,0:57:29.64,Default,,0,0,0,,我可以把世界分为两部分\nDialogue: 0,0:57:29.92,0:57:31.85,Default,,0,0,0,,我和你\nDialogue: 0,0:57:31.92,0:57:33.31,Default,,0,0,0,,以及其它的东西\nDialogue: 0,0:57:34.70,0:57:35.26,Default,,0,0,0,,使得\nDialogue: 0,0:57:35.44,0:57:39.50,Default,,0,0,0,,大多数对于我的讨论\nDialogue: 0,0:57:39.68,0:57:40.89,Default,,0,0,0,,不会影响到你\nDialogue: 0,0:57:41.39,0:57:44.67,Default,,0,0,0,,大多数对于你的讨论不会牵涉到我\nDialogue: 0,0:57:45.66,0:57:46.94,Default,,0,0,0,,我有血压\nDialogue: 0,0:57:47.50,0:57:48.38,Default,,0,0,0,,体温\nDialogue: 0,0:57:49.36,0:57:51.48,Default,,0,0,0,,呼吸频率\nDialogue: 0,0:57:53.34,0:57:54.99,Default,,0,0,0,,血液中有确定的血糖值\nDialogue: 0,0:57:56.11,0:57:59.34,Default,,0,0,0,,数不清的 数以千计的状态变量--上百万实际上\nDialogue: 0,0:57:59.37,0:58:00.65,Default,,0,0,0,,我不知道具体有多少\nDialogue: 0,0:58:00.93,0:58:03.48,Default,,0,0,0,,以物理学观点 我拥有大量的状态变量\nDialogue: 0,0:58:04.91,0:58:07.12,Default,,0,0,0,,如果将我视为一个粒子的话\nDialogue: 0,0:58:09.15,0:58:10.64,Default,,0,0,0,,你也有许许多多这样的变量\nDialogue: 0,0:58:12.68,0:58:14.94,Default,,0,0,0,,我们的大多数变量之间是好无联系的\nDialogue: 0,0:58:17.31,0:58:19.50,Default,,0,0,0,,所以可以计算我的属性\nDialogue: 0,0:58:20.56,0:58:22.83,Default,,0,0,0,,而不用太担心你的属性\nDialogue: 0,0:58:23.82,0:58:25.77,Default,,0,0,0,,如果把我们两个放在一起计算\nDialogue: 0,0:58:25.96,0:58:27.82,Default,,0,0,0,,那么我们需要考虑的状态的数量\nDialogue: 0,0:58:27.82,0:58:30.01,Default,,0,0,0,,就是你与我的状态的数量的乘积\nDialogue: 0,0:58:30.52,0:58:32.11,Default,,0,0,0,,按对象解耦的话 则只需考虑你我状态之和\nDialogue: 0,0:58:32.65,0:58:35.34,Default,,0,0,0,,然而 实际上有一种力量把我们耦合起来\nDialogue: 0,0:58:36.00,0:58:37.95,Default,,0,0,0,,我对你讲话 你的状态就变了\nDialogue: 0,0:58:38.44,0:58:40.09,Default,,0,0,0,,我看着你 我的状态就变了\nDialogue: 0,0:58:41.72,0:58:44.08,Default,,0,0,0,,因此 我的变量中的一小部分\nDialogue: 0,0:58:44.33,0:58:46.07,Default,,0,0,0,,与你的一些变量是耦合的\nDialogue: 0,0:58:46.07,0:58:47.80,Default,,0,0,0,,如果你突然大喊大叫\nDialogue: 0,0:58:47.80,0:58:48.88,Default,,0,0,0,,我的血压就会升高\nDialogue: 0,0:58:54.30,0:58:56.86,Default,,0,0,0,,然而 将世界看作是由独立的变量\nDialogue: 0,0:58:57.17,0:59:01.16,Default,,0,0,0,,和独立的粒子组成的是不恰当的\nDialogue: 0,0:59:02.12,0:59:04.46,Default,,0,0,0,,在像量子力学这样的东西里存在大量的BUG\nDialogue: 0,0:59:05.23,0:59:08.70,Default,,0,0,0,,或者当我们思考像量子力学之类的东西的时候 会在我们的脑海中产生bug\nDialogue: 0,0:59:08.89,0:59:10.97,Default,,0,0,0,,这是由于 当我们思考事物时\nDialogue: 0,0:59:10.97,0:59:12.96,Default,,0,0,0,,会去将事物分解为相互独立的部分来看待\nDialogue: 0,0:59:13.58,0:59:17.32,Default,,0,0,0,,而事实上事物的耦合程度 远远大于在表面所看到的\nDialogue: 0,0:59:18.01,0:59:19.44,Default,,0,0,0,,即便这样 我们仍像那样思考\nDialogue: 0,0:59:19.61,0:59:21.69,Default,,0,0,0,,是因为我们希望高效并且有效的进行计算\nDialogue: 0,0:59:22.19,0:59:23.82,Default,,0,0,0,,我们被培养成以那种方式进行思考\nDialogue: 0,0:59:29.76,0:59:30.51,Default,,0,0,0,,大家看\nDialogue: 0,0:59:31.50,0:59:33.44,Default,,0,0,0,,我们如何才能知道我们是否有对象？\nDialogue: 0,0:59:35.12,0:59:37.34,Default,,0,0,0,,如果我们有对象 应该如何分辨呢？\nDialogue: 0,0:59:37.64,0:59:41.45,Default,,0,0,0,,通过思考一些光学现象\nDialogue: 0,0:59:42.46,0:59:43.13,Default,,0,0,0,,就能解答这个问题\nDialogue: 0,0:59:45.04,0:59:47.69,Default,,0,0,0,,这几截粉笔不完全相同\nDialogue: 0,0:59:47.76,0:59:50.20,Default,,0,0,0,,但假设 只通过观察是无法区分它们的\nDialogue: 0,0:59:52.04,0:59:53.32,Default,,0,0,0,,有一种可能\nDialogue: 0,0:59:53.32,0:59:55.16,Default,,0,0,0,,是这一切都是我们与镜子的游戏\nDialogue: 0,0:59:56.07,0:59:57.60,Default,,0,0,0,,它们真的是同一截粉笔\nDialogue: 0,0:59:59.36,1:00:00.48,Default,,0,0,0,,但你看到了两个\nDialogue: 0,1:00:01.61,1:00:03.87,Default,,0,0,0,,你怎么知道你看到的是一个还是两个呢？\nDialogue: 0,1:00:05.04,1:00:06.70,Default,,0,0,0,,我只知道有一种方法可以确定\nDialogue: 0,1:00:07.37,1:00:08.94,Default,,0,0,0,,抓起其中一个并且改变它\nDialogue: 0,1:00:09.45,1:00:10.67,Default,,0,0,0,,然后看看另一个有没有跟着变化\nDialogue: 0,1:00:14.01,1:00:14.67,Default,,0,0,0,,而另一个没有变化\nDialogue: 0,1:00:15.50,1:00:16.14,Default,,0,0,0,,所以它们是两截不同粉笔\nDialogue: 0,1:00:19.50,1:00:20.16,Default,,0,0,0,,另一方面\nDialogue: 0,1:00:20.17,1:00:22.20,Default,,0,0,0,,事物还有一些其它的类似的纠结属性\nDialogue: 0,1:00:22.57,1:00:24.01,Default,,0,0,0,,例如 我们怎么才知道某个东西是否改变了呢？\nDialogue: 0,1:00:25.00,1:00:27.93,Default,,0,0,0,,我们需要在它改变之前和之后进行观察\nDialogue: 0,1:00:28.65,1:00:30.02,Default,,0,0,0,,改变就是赋值\nDialogue: 0,1:00:30.02,1:00:31.45,Default,,0,0,0,,它是时间中的一个时刻\nDialogue: 0,1:00:32.14,1:00:34.60,Default,,0,0,0,,但是那意味着我们需要知道 我们看到的是否是同一个\nDialogue: 0,1:00:36.51,1:00:38.84,Default,,0,0,0,,所以一些东西非常奇怪\nDialogue: 0,1:00:38.84,1:00:40.38,Default,,0,0,0,,不同寻常并且晦涩难懂\nDialogue: 0,1:00:40.84,1:00:43.52,Default,,0,0,0,,并且我不理解与赋值\nDialogue: 0,1:00:44.45,1:00:46.28,Default,,0,0,0,,变化以及对象有关的问题\nDialogue: 0,1:00:47.29,1:00:48.99,Default,,0,0,0,,这些东西可能变得非常非常糟糕\nDialogue: 0,1:00:51.40,1:00:52.12,Default,,0,0,0,,例如\nDialogue: 0,1:00:53.31,1:00:55.60,Default,,0,0,0,,我 一个特定的人\nDialogue: 0,1:00:56.16,1:00:57.72,Default,,0,0,0,,一个特定的对象\nDialogue: 0,1:00:57.96,1:00:59.31,Default,,0,0,0,,现在 我可以拿出小刀\nDialogue: 0,1:01:00.68,1:01:01.77,Default,,0,0,0,,切下一片我的指甲\nDialogue: 0,1:01:01.89,1:01:04.81,Default,,0,0,0,,一片指甲掉在了桌子上\nDialogue: 0,1:01:05.93,1:01:10.16,Default,,0,0,0,,我相信自己和一秒钟之前的自己 是同一个人\nDialogue: 0,1:01:10.97,1:01:12.81,Default,,0,0,0,,但在物理上并不是分毫不差\nDialogue: 0,1:01:14.46,1:01:15.43,Default,,0,0,0,,我已经改变了\nDialogue: 0,1:01:15.58,1:01:16.65,Default,,0,0,0,,为什么我还是同一个人呢？\nDialogue: 0,1:01:18.11,1:01:19.40,Default,,0,0,0,,什么能认定我的身份呢？\nDialogue: 0,1:01:20.96,1:01:23.50,Default,,0,0,0,,我不知道\nDialogue: 0,1:01:25.05,1:01:27.88,Default,,0,0,0,,除非我有某种特征\nDialogue: 0,1:01:29.71,1:01:33.04,Default,,0,0,0,,我觉得 由于引入赋值和对象\nDialogue: 0,1:01:33.64,1:01:38.28,Default,,0,0,0,,我们不得不去面对这种\nDialogue: 0,1:01:38.41,1:01:42.24,Default,,0,0,0,,困扰了哲学家们上千年的哲学问题\nDialogue: 0,1:01:43.42,1:01:44.99,Default,,0,0,0,,这也是相比之下 为什么数学清晰得多\nDialogue: 0,1:01:45.69,1:01:50.24,Default,,0,0,0,,我将尽我所能地向大家阐述关于动作和身份的理解\nDialogue: 0,1:01:52.44,1:01:55.39,Default,,0,0,0,,我们说动作A 对于对于某个对象X有影响\nDialogue: 0,1:01:55.77,1:01:56.70,Default,,0,0,0,,换句话说\nDialogue: 0,1:01:56.92,1:01:58.41,Default,,0,0,0,,X被A改变\nDialogue: 0,1:01:58.89,1:02:01.66,Default,,0,0,0,,如果某个属性P 在P作用于X之前为真\nDialogue: 0,1:02:01.87,1:02:03.76,Default,,0,0,0,,在A作用于X之后为假\nDialogue: 0,1:02:04.99,1:02:05.63,Default,,0,0,0,,那是个测试\nDialogue: 0,1:02:06.62,1:02:09.66,Default,,0,0,0,,这也意味着 我必须有变动前和变动后的X\nDialogue: 0,1:02:10.91,1:02:12.54,Default,,0,0,0,,或者 换句话说\nDialogue: 0,1:02:12.94,1:02:14.94,Default,,0,0,0,,我们说对任一动作 两个对象X和Y是同一个对象\nDialogue: 0,1:02:14.97,1:02:17.93,Default,,0,0,0,,当且仅当 该动作对X、Y有同样的影响\nDialogue: 0,1:02:19.63,1:02:21.39,Default,,0,0,0,,然而 就像我说的\nDialogue: 0,1:02:21.44,1:02:23.18,Default,,0,0,0,,对象在智力经济上是非常有用的\nDialogue: 0,1:02:24.64,1:02:27.12,Default,,0,0,0,,对于它们来说非常有用的东西之一\nDialogue: 0,1:02:28.27,1:02:29.44,Default,,0,0,0,,就是对于这个世界\nDialogue: 0,1:02:30.78,1:02:34.80,Default,,0,0,0,,我们习惯于把它认为是由带有独立状态的独立对象所构成的\nDialogue: 0,1:02:35.00,1:02:37.28,Default,,0,0,0,,虽然那并不完全正确 但我们喜欢以那样的的方式来思考\nDialogue: 0,1:02:39.68,1:02:42.03,Default,,0,0,0,,当我们要写一个非常复杂的程序\nDialogue: 0,1:02:42.03,1:02:43.26,Default,,0,0,0,,来应对这样一个世界时\nDialogue: 0,1:02:43.98,1:02:46.44,Default,,0,0,0,,如果我们希望这些程序可以被我们理解\nDialogue: 0,1:02:46.91,1:02:48.14,Default,,0,0,0,,并且也是可修改的\nDialogue: 0,1:02:48.73,1:02:51.12,Default,,0,0,0,,那么如果世界改变了 我们只需要稍微改动一下程序\nDialogue: 0,1:02:51.39,1:02:53.70,Default,,0,0,0,,我们希望建立一种联系 一种同构\nDialogue: 0,1:02:53.82,1:02:56.88,Default,,0,0,0,,建立在真实世界的对象与我们脑海中的对象之间\nDialogue: 0,1:02:58.76,1:03:01.44,Default,,0,0,0,,世界的模块化 使我们的程序得以模块化\nDialogue: 0,1:03:02.41,1:03:05.36,Default,,0,0,0,,所以我们发明了面向对象编程\nDialogue: 0,1:03:05.88,1:03:08.36,Default,,0,0,0,,使我们获得那样的力量\nDialogue: 0,1:03:10.06,1:03:10.94,Default,,0,0,0,,但是 它甚至更简单\nDialogue: 0,1:03:10.94,1:03:12.25,Default,,0,0,0,,让我们玩一个小游戏\nDialogue: 0,1:03:12.27,1:03:13.18,Default,,0,0,0,,我想通过这个游戏\nDialogue: 0,1:03:13.39,1:03:15.77,Default,,0,0,0,,给你展示一个更简单的例子\nDialogue: 0,1:03:16.00,1:03:21.74,Default,,0,0,0,,来说明谨慎地使用赋值语句 可以增强模块性\nDialogue: 0,1:03:22.86,1:03:25.35,Default,,0,0,0,,有一件事 我想让你牢牢地铭记\nDialogue: 0,1:03:25.45,1:03:27.44,Default,,0,0,0,,就是不要像在FORTRAN Basic\nDialogue: 0,1:03:27.45,1:03:29.79,Default,,0,0,0,,或者Pascal里一样使用赋值语句\nDialogue: 0,1:03:30.00,1:03:31.71,Default,,0,0,0,,你不那样做 也能达到目的\nDialogue: 0,1:03:34.04,1:03:36.62,Default,,0,0,0,,这不是思考大多数事情的正确方式\nDialogue: 0,1:03:36.97,1:03:38.28,Default,,0,0,0,,有些时候它是必要的\nDialogue: 0,1:03:38.68,1:03:39.69,Default,,0,0,0,,或者可能是必要的\nDialogue: 0,1:03:39.69,1:03:40.97,Default,,0,0,0,,我们一会更深入地去研究\nDialogue: 0,1:03:42.24,1:03:44.22,Default,,0,0,0,,我要给你展示一个有趣的游戏\nDialogue: 0,1:03:47.61,1:03:49.42,Default,,0,0,0,,从前有一个数学家\nDialogue: 0,1:03:49.68,1:03:53.69,Default,,0,0,0,,叫做Cesaro\nDialogue: 0,1:03:54.48,1:03:57.45,Default,,0,0,0,,他发现了一个计算pi的巧妙方法\nDialogue: 0,1:03:58.38,1:04:04.30,Default,,0,0,0,,这个方法是说 如果我有两个随机数\nDialogue: 0,1:04:05.24,1:04:06.94,Default,,0,0,0,,两个随机的整数\nDialogue: 0,1:04:07.74,1:04:09.48,Default,,0,0,0,,计算它们的最大公约数\nDialogue: 0,1:04:10.94,1:04:13.24,Default,,0,0,0,,结果可能是1 或者不是1\nDialogue: 0,1:04:13.84,1:04:15.64,Default,,0,0,0,,如果是1 它们没有公约数\nDialogue: 0,1:04:18.14,1:04:20.68,Default,,0,0,0,,如果它们的最大公约数是1\nDialogue: 0,1:04:21.12,1:04:23.09,Default,,0,0,0,,这两个随机数\nDialogue: 0,1:04:23.09,1:04:26.38,Default,,0,0,0,,两个随机生成的数 最大公约数为1的概率\nDialogue: 0,1:04:26.58,1:04:27.82,Default,,0,0,0,,与pi有关系\nDialogue: 0,1:04:29.32,1:04:30.11,Default,,0,0,0,,事实上\nDialogue: 0,1:04:31.11,1:04:32.33,Default,,0,0,0,,是的 这很奇怪\nDialogue: 0,1:04:32.94,1:04:34.41,Default,,0,0,0,,当然有其他计算pi的方法\nDialogue: 0,1:04:34.41,1:04:38.94,Default,,0,0,0,,像投针法之类的的方法\nDialogue: 0,1:04:40.19,1:04:48.97,Default,,0,0,0,,N1和N2的最大公约数是1的概率为\nDialogue: 0,1:04:49.44,1:04:51.02,Default,,0,0,0,,N1、N2是随机选取的两个数\nDialogue: 0,1:04:51.71,1:04:53.66,Default,,0,0,0,,是6/pi^2\nDialogue: 0,1:04:55.61,1:04:56.83,Default,,0,0,0,,我不准备证明这个\nDialogue: 0,1:04:57.15,1:04:59.64,Default,,0,0,0,,事实上这不难 并且有些有趣\nDialogue: 0,1:05:01.07,1:05:03.05,Default,,0,0,0,,我们要怎样估算这个概率呢？\nDialogue: 0,1:05:03.53,1:05:06.46,Default,,0,0,0,,我们估算概率的方法则是\nDialogue: 0,1:05:07.23,1:05:08.65,Default,,0,0,0,,是做大量的实验\nDialogue: 0,1:05:09.20,1:05:12.01,Default,,0,0,0,,去计算成功的试验\nDialogue: 0,1:05:12.01,1:05:13.58,Default,,0,0,0,,与试验总次数的比率\nDialogue: 0,1:05:16.32,1:05:17.28,Default,,0,0,0,,这种方法叫做蒙特卡罗方法\nDialogue: 0,1:05:18.04,1:05:22.38,Default,,0,0,0,,它也可以用于计算包含大量变量的积分\nDialogue: 0,1:05:22.94,1:05:25.28,Default,,0,0,0,,其中积分的面积是限定的\nDialogue: 0,1:05:26.27,1:05:28.70,Default,,0,0,0,,回到这里\nDialogue: 0,1:05:29.76,1:05:31.72,Default,,0,0,0,,我们来看看这张幻灯片\nDialogue: 0,1:05:33.96,1:05:36.92,Default,,0,0,0,,我们可以用Cesaro的方法来估算pi的值\nDialogue: 0,1:05:37.19,1:05:43.18,Default,,0,0,0,,通过N次试验 取结果的六分之一 开根号\nDialogue: 0,1:05:43.29,1:05:46.46,Default,,0,0,0,,用蒙特卡罗方法\nDialogue: 0,1:05:46.80,1:05:50.38,Default,,0,0,0,,进行了N次Cesaro实验\nDialogue: 0,1:05:51.37,1:05:57.56,Default,,0,0,0,,这个实验是关于两个随机数的最大公约数的--\nDialogue: 0,1:05:58.96,1:06:01.60,Default,,0,0,0,,你可以看到 我已经在这里进行了一些赋值\nDialogue: 0,1:06:01.84,1:06:03.13,Default,,0,0,0,,就像我写的这样\nDialogue: 0,1:06:04.04,1:06:07.49,Default,,0,0,0,,这个在括号中的RAND\nDialogue: 0,1:06:07.49,1:06:09.09,Default,,0,0,0,,这个过程调用\nDialogue: 0,1:06:09.09,1:06:11.39,Default,,0,0,0,,生成了一个与这个RAND不同的值\nDialogue: 0,1:06:11.39,1:06:13.72,Default,,0,0,0,,至少是我写的这样所假设的\nDialogue: 0,1:06:14.62,1:06:16.75,Default,,0,0,0,,这表明这不是一个函数\nDialogue: 0,1:06:18.20,1:06:20.57,Default,,0,0,0,,这里面会有一个不断改变内部状态\nDialogue: 0,1:06:22.27,1:06:28.64,Default,,0,0,0,,如果两个随机数的最大公约数等于1\nDialogue: 0,1:06:28.64,1:06:29.79,Default,,0,0,0,,这就是整个实验过程\nDialogue: 0,1:06:31.48,1:06:35.18,Default,,0,0,0,,那么我有了一个实验方法 用来估算pi的值\nDialogue: 0,1:06:36.51,1:06:39.72,Default,,0,0,0,,我可以轻松地将这个问题分为两个部分\nDialogue: 0,1:06:40.02,1:06:44.70,Default,,0,0,0,,一部分是使用蒙特卡罗方法进行特定的Cesaro实验 就像你刚才看到那个\nDialogue: 0,1:06:44.99,1:06:48.56,Default,,0,0,0,,另一部分就是一般性蒙特卡罗方法的实现\nDialogue: 0,1:06:49.16,1:06:50.27,Default,,0,0,0,,就是这个\nDialogue: 0,1:06:51.04,1:06:55.47,Default,,0,0,0,,如果我想进行N次蒙特卡罗试验\nDialogue: 0,1:06:55.67,1:06:58.36,Default,,0,0,0,,即一个确定的试验次数 和一个确定的实验\nDialogue: 0,1:06:59.31,1:07:00.33,Default,,0,0,0,,我进行实验的方法就是\nDialogue: 0,1:07:00.84,1:07:02.70,Default,,0,0,0,,构建一个迭代过程\nDialogue: 0,1:07:03.31,1:07:07.26,Default,,0,0,0,,这个过程有两个变量 分别是试验的剩余次数和通过次数\nDialogue: 0,1:07:08.35,1:07:09.44,Default,,0,0,0,,也就是实验结果为真的次数\nDialogue: 0,1:07:10.13,1:07:12.21,Default,,0,0,0,,如果剩余次数为0\nDialogue: 0,1:07:12.21,1:07:15.36,Default,,0,0,0,,结果就是通过的次数除以总次数\nDialogue: 0,1:07:16.04,1:07:17.52,Default,,0,0,0,,也就是该概率的估算值\nDialogue: 0,1:07:19.07,1:07:20.04,Default,,0,0,0,,如果剩余次数不是0\nDialogue: 0,1:07:20.04,1:07:22.08,Default,,0,0,0,,如果还有试验要做\nDialogue: 0,1:07:22.08,1:07:23.82,Default,,0,0,0,,那么接下来我们就进行一次试验\nDialogue: 0,1:07:23.85,1:07:27.30,Default,,0,0,0,,我们调用一次没有参数的实验的过程\nDialogue: 0,1:07:27.30,1:07:28.43,Default,,0,0,0,,我们进行这个试验\nDialogue: 0,1:07:29.10,1:07:30.64,Default,,0,0,0,,如果实验结果为真\nDialogue: 0,1:07:30.82,1:07:32.25,Default,,0,0,0,,我们继续循环\nDialogue: 0,1:07:32.62,1:07:35.42,Default,,0,0,0,,试验剩余次数减1\nDialogue: 0,1:07:35.70,1:07:37.48,Default,,0,0,0,,将试验通过次数加1\nDialogue: 0,1:07:38.57,1:07:40.11,Default,,0,0,0,,如果试验的结果为假\nDialogue: 0,1:07:40.41,1:07:42.25,Default,,0,0,0,,我们继续循环\nDialogue: 0,1:07:42.32,1:07:44.38,Default,,0,0,0,,剩余试验次数减1\nDialogue: 0,1:07:44.44,1:07:46.60,Default,,0,0,0,,试验通过次数保持不变\nDialogue: 0,1:07:48.76,1:07:54.59,Default,,0,0,0,,我们以TRIAL为剩余次数 以0为通过次数 开始迭代\nDialogue: 0,1:07:55.42,1:07:57.10,Default,,0,0,0,,多么简洁的小程序啊\nDialogue: 0,1:07:57.74,1:08:00.55,Default,,0,0,0,,我不一定非要进行Cesaro的实验\nDialogue: 0,1:08:00.55,1:08:02.73,Default,,0,0,0,,它可以用来进行很多种蒙特卡罗实验\nDialogue: 0,1:08:03.36,1:08:07.12,Default,,0,0,0,,当然 它依赖于某种随机数生成器的存在\nDialogue: 0,1:08:07.34,1:08:10.99,Default,,0,0,0,,随机数生成器通常是像这种的东西\nDialogue: 0,1:08:13.60,1:08:16.32,Default,,0,0,0,,这是一个随机数生成器--\nDialogue: 0,1:08:17.42,1:08:25.21,Default,,0,0,0,,它实际上就是一个过程 具体行为跟计数器有些相似\nDialogue: 0,1:08:25.61,1:08:27.52,Default,,0,0,0,,它会把X的值更新为\nDialogue: 0,1:08:28.33,1:08:31.82,Default,,0,0,0,,将某个函数应用于X的结果\nDialogue: 0,1:08:32.20,1:08:35.28,Default,,0,0,0,,而这类古怪的函数\nDialogue: 0,1:08:35.39,1:08:40.16,Default,,0,0,0,,你可以在Kunth写的关于编程细节的书中找到\nDialogue: 0,1:08:41.56,1:08:45.75,Default,,0,0,0,,他写的书绝妙而充满了编程细节\nDialogue: 0,1:08:45.75,1:08:48.52,Default,,0,0,0,,虽然我记不住随机数生成器该怎样写\nDialogue: 0,1:08:48.63,1:08:50.62,Default,,0,0,0,,但我可以在书里找出一个来用\nDialogue: 0,1:08:51.64,1:08:54.01,Default,,0,0,0,,最后 我返回了X的值\nDialogue: 0,1:08:54.08,1:08:57.40,Default,,0,0,0,,也就是随机数生成器的内部状态变量\nDialogue: 0,1:08:58.28,1:09:00.75,Default,,0,0,0,,这个状态变量以某种方式被初始化\nDialogue: 0,1:09:01.32,1:09:02.24,Default,,0,0,0,,从而获得了一个值\nDialogue: 0,1:09:03.39,1:09:08.11,Default,,0,0,0,,这个过程被定义在那个变量被约束的上下文中\nDialogue: 0,1:09:10.41,1:09:15.26,Default,,0,0,0,,所以你在这看到的 是一个隐藏的局部状态\nDialogue: 0,1:09:15.87,1:09:20.24,Default,,0,0,0,,这个过程定义在那个上下文中\nDialogue: 0,1:09:21.56,1:09:23.66,Default,,0,0,0,,这样做起来非常容易\nDialogue: 0,1:09:24.88,1:09:25.79,Default,,0,0,0,,而且结果也非常好\nDialogue: 0,1:09:25.99,1:09:27.77,Default,,0,0,0,,设想 我不想用赋值\nDialogue: 0,1:09:29.10,1:09:31.47,Default,,0,0,0,,假设我想写一个不带赋值的程序\nDialogue: 0,1:09:32.73,1:09:33.93,Default,,0,0,0,,我将遇到什么困难？\nDialogue: 0,1:09:35.52,1:09:37.40,Default,,0,0,0,,让我们来看看\nDialogue: 0,1:09:37.82,1:09:41.10,Default,,0,0,0,,我要用一下头顶上的投影仪了\nDialogue: 0,1:09:42.06,1:09:42.70,Default,,0,0,0,,多谢\nDialogue: 0,1:09:43.47,1:09:47.66,Default,,0,0,0,,首先 我们来整体看一下 这是一个很庞大的东西\nDialogue: 0,1:09:48.01,1:09:49.90,Default,,0,0,0,,它告诉你有某些东西出了问题\nDialogue: 0,1:09:50.96,1:09:52.75,Default,,0,0,0,,毕竟有这么大一堆东西呢\nDialogue: 0,1:09:53.42,1:09:54.60,Default,,0,0,0,,庞大而单一\nDialogue: 0,1:09:56.76,1:10:00.12,Default,,0,0,0,,你不需要现在去理解或看这里的文本\nDialogue: 0,1:10:00.12,1:10:01.39,Default,,0,0,0,,就把它们看做一个整体\nDialogue: 0,1:10:01.92,1:10:04.89,Default,,0,0,0,,它不是Cesaro的实验\nDialogue: 0,1:10:04.89,1:10:07.90,Default,,0,0,0,,它不是从蒙特卡罗过程中抽取出来的\nDialogue: 0,1:10:09.87,1:10:11.84,Default,,0,0,0,,它不是分离的 让我们来看看为什么\nDialogue: 0,1:10:14.22,1:10:15.85,Default,,0,0,0,,记住 这里的约束是\nDialogue: 0,1:10:15.85,1:10:17.87,Default,,0,0,0,,每个过程\nDialogue: 0,1:10:18.69,1:10:22.20,Default,,0,0,0,,对于同样的参数 将返回同样的值\nDialogue: 0,1:10:22.97,1:10:24.75,Default,,0,0,0,,每个过程就是一个函数\nDialogue: 0,1:10:26.92,1:10:28.50,Default,,0,0,0,,那是另一种约束\nDialogue: 0,1:10:28.50,1:10:31.21,Default,,0,0,0,,因为当我赋值时 我可以改变一些内部状态变量\nDialogue: 0,1:10:31.74,1:10:34.03,Default,,0,0,0,,所以让我们来看看它是怎么出错的\nDialogue: 0,1:10:35.04,1:10:36.14,Default,,0,0,0,,我们从头开始\nDialogue: 0,1:10:37.50,1:10:41.92,Default,,0,0,0,,估算pi的过程看起来是一样的\nDialogue: 0,1:10:42.66,1:10:45.88,Default,,0,0,0,,我取RAMDOM-GCD-TEST应用于N\nDialogue: 0,1:10:46.35,1:10:50.22,Default,,0,0,0,,的结果分之6的平方根\nDialogue: 0,1:10:50.74,1:10:51.93,Default,,0,0,0,,就是这个\nDialogue: 0,1:10:52.96,1:10:55.20,Default,,0,0,0,,在这里 我们开始看到了一些有趣的东西\nDialogue: 0,1:10:55.20,1:10:57.93,Default,,0,0,0,,对于以TRAILS为参数的RANDOM-GCD-TEST过程\nDialogue: 0,1:10:58.32,1:10:59.98,Default,,0,0,0,,就像我们之前做的一样\nDialogue: 0,1:11:00.46,1:11:04.66,Default,,0,0,0,,是一个以剩余次数\nDialogue: 0,1:11:04.66,1:11:06.80,Default,,0,0,0,,通过次数\nDialogue: 0,1:11:08.27,1:11:09.71,Default,,0,0,0,,另一个变量X为基准的迭代\nDialogue: 0,1:11:10.75,1:11:11.76,Default,,0,0,0,,这个X是什么？\nDialogue: 0,1:11:12.33,1:11:15.20,Default,,0,0,0,,X是随机数发生器的状态\nDialogue: 0,1:11:19.00,1:11:21.16,Default,,0,0,0,,它会在这里被使用\nDialogue: 0,1:11:21.16,1:11:23.79,Default,,0,0,0,,这里的同样的随机更新函数\nDialogue: 0,1:11:23.79,1:11:27.15,Default,,0,0,0,,来自于一个我另外写的随机数发生器\nDialogue: 0,1:11:27.71,1:11:29.32,Default,,0,0,0,,或者从Knuth的书中找一个\nDialogue: 0,1:11:31.56,1:11:33.36,Default,,0,0,0,,X将转化为X1\nDialogue: 0,1:11:33.37,1:11:34.36,Default,,0,0,0,,但我需要两个随机数\nDialogue: 0,1:11:34.81,1:11:36.92,Default,,0,0,0,,X1将被转化为X2\nDialogue: 0,1:11:37.26,1:11:38.44,Default,,0,0,0,,我有两个随机数\nDialogue: 0,1:11:39.50,1:11:42.14,Default,,0,0,0,,然后进行和之前一样的步骤\nDialogue: 0,1:11:42.52,1:11:44.19,Default,,0,0,0,,取X1和X2的最大公约数\nDialogue: 0,1:11:44.22,1:11:47.15,Default,,0,0,0,,如果结果是1 则将X2作为下一个X的值继续循环\nDialogue: 0,1:11:54.78,1:11:55.98,Default,,0,0,0,,这里所发生的\nDialogue: 0,1:11:56.88,1:11:58.70,Default,,0,0,0,,随机数发生器的状态\nDialogue: 0,1:11:58.73,1:12:01.70,Default,,0,0,0,,不再被限制于其内部\nDialogue: 0,1:12:01.80,1:12:02.73,Default,,0,0,0,,它已经暴露了出来\nDialogue: 0,1:12:03.33,1:12:05.50,Default,,0,0,0,,它已经被暴露在\nDialogue: 0,1:12:05.50,1:12:10.08,Default,,0,0,0,,我们的的蒙特卡罗实验的过程中\nDialogue: 0,1:12:10.70,1:12:11.87,Default,,0,0,0,,但比那更糟糕的是\nDialogue: 0,1:12:11.87,1:12:16.24,Default,,0,0,0,,同样的 因为它也被包含在我们的Cesaro实验中\nDialogue: 0,1:12:16.78,1:12:19.48,Default,,0,0,0,,它被暴露了两次 因为Cesaro被调用了两次\nDialogue: 0,1:12:20.86,1:12:22.47,Default,,0,0,0,,每次有不同的值\nDialogue: 0,1:12:22.47,1:12:25.16,Default,,0,0,0,,如果我要进行一个合理的实验的话\nDialogue: 0,1:12:26.32,1:12:28.32,Default,,0,0,0,,所以Cesaro也不能成为函数了\nDialogue: 0,1:12:31.04,1:12:35.69,Default,,0,0,0,,除非我把随机数发生器的种子传给它\nDialogue: 0,1:12:36.52,1:12:39.37,Default,,0,0,0,,所以很不幸 随机数发生器的种子\nDialogue: 0,1:12:39.37,1:12:42.77,Default,,0,0,0,,从随机数发生器中暴露到了Cesaro内部\nDialogue: 0,1:12:42.88,1:12:45.16,Default,,0,0,0,,被暴露在蒙特卡罗实验中\nDialogue: 0,1:12:45.64,1:12:49.12,Default,,0,0,0,,很不幸 这里的蒙特卡罗实验不再是通用的了\nDialogue: 0,1:12:50.25,1:12:51.80,Default,,0,0,0,,这里的蒙特卡罗实验\nDialogue: 0,1:12:52.03,1:12:54.73,Default,,0,0,0,,知道了我在实验中需要多少个随机数\nDialogue: 0,1:12:58.96,1:12:59.74,Default,,0,0,0,,这真的很糟糕\nDialogue: 0,1:13:00.08,1:13:02.54,Default,,0,0,0,,我失去了将问题分解开来的能力\nDialogue: 0,1:13:03.44,1:13:09.12,Default,,0,0,0,,因为我不愿意接受信息的循环\nDialogue: 0,1:13:09.50,1:13:12.43,Default,,0,0,0,,反馈的过程\nDialogue: 0,1:13:12.88,1:13:15.94,Default,,0,0,0,,这之前都是发生在随机数发生器内部\nDialogue: 0,1:13:15.94,1:13:21.21,Default,,0,0,0,,也就是赋值给一个限制在随机数生成器内部的状态变量\nDialogue: 0,1:13:22.92,1:13:25.48,Default,,0,0,0,,所以实际上 随机数发生器是一个对象\nDialogue: 0,1:13:25.92,1:13:27.37,Default,,0,0,0,,它有一个内部状态变量\nDialogue: 0,1:13:28.06,1:13:29.36,Default,,0,0,0,,它不受任何东西影响\nDialogue: 0,1:13:29.37,1:13:31.60,Default,,0,0,0,,但是它会给你某些东西 把它的力量赐予你\nDialogue: 0,1:13:32.80,1:13:34.28,Default,,0,0,0,,那是我们现在缺少的\nDialogue: 0,1:13:38.00,1:13:40.73,Default,,0,0,0,,好 我认为我已经知道了\nDialogue: 0,1:13:40.73,1:13:42.30,Default,,0,0,0,,引入赋值的充分理由\nDialogue: 0,1:13:42.83,1:13:45.24,Default,,0,0,0,,并且一些看起来很圆满\nDialogue: 0,1:13:45.38,1:13:50.70,Default,,0,0,0,,如果赋值是一个好东西\nDialogue: 0,1:13:51.74,1:13:53.04,Default,,0,0,0,,并且赋值是值得的 这不是很好吗？\nDialogue: 0,1:13:53.28,1:13:54.14,Default,,0,0,0,,我不是很确定\nDialogue: 0,1:13:55.34,1:13:57.04,Default,,0,0,0,,Mr. Gilbert和Sullivan说过\nDialogue: 0,1:13:57.04,1:13:58.51,Default,,0,0,0,,事物往往不像表面看到的那样\nDialogue: 0,1:13:58.51,1:14:00.35,Default,,0,0,0,,脱脂牛奶也能装成奶油\nDialogue: 0,1:14:01.87,1:14:03.90,Default,,0,0,0,,谁有什么问题吗？\nDialogue: 0,1:14:16.97,1:14:18.30,Default,,0,0,0,,在座的有哲学家吗？\nDialogue: 0,1:14:20.06,1:14:22.03,Default,,0,0,0,,有人想要讨论有关“对象”的问题吗？\nDialogue: 0,1:14:24.32,1:14:25.50,Default,,0,0,0,,你们已经一头雾水了是吧？\nDialogue: 0,1:14:29.72,1:14:30.72,Default,,0,0,0,,你们还没有完成家庭作业呢\nDialogue: 0,1:14:30.73,1:14:32.00,Default,,0,0,0,,你们需要提一个好问题\nDialogue: 0,1:14:36.35,1:14:37.44,Default,,0,0,0,,好了\nDialogue: 0,1:14:39.97,1:14:42.33,Default,,0,0,0,,感谢你们 我们下课吧\nDialogue: 0,1:14:47.90,1:15:05.69,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:14:47.90,1:15:05.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec5a.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 89\nActive Line: 93\nVideo Position: 9470\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:01.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:01.98,0:00:09.55,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N杨启钊（windfarer）\nDialogue: 0,0:00:01.98,0:00:09.55,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.92,0:00:13.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}赋值、状态和副作用\nDialogue: 0,0:00:18.31,0:00:22.00,Default,,0,0,0,,教授：到目前为止 我们已经教了很多编程技巧\nDialogue: 0,0:00:22.25,0:00:24.06,Default,,0,0,0,,来编写复杂程序了\nDialogue: 0,0:00:24.76,0:00:29.66,Default,,0,0,0,,并且 到目前为止 关于编程你们学到了很多\nDialogue: 0,0:00:29.66,0:00:31.48,Default,,0,0,0,,你们已经学习了几乎所有的\nDialogue: 0,0:00:31.86,0:00:35.87,Default,,0,0,0,,那些拥有大量经验的人 才能领悟的技巧\nDialogue: 0,0:00:36.41,0:00:40.08,Default,,0,0,0,,例如 数据导向编程就是一个主要的技巧\nDialogue: 0,0:00:40.75,0:00:43.15,Default,,0,0,0,,昨天 你们也学习了一种解释型语言\nDialogue: 0,0:00:45.02,0:00:48.46,Default,,0,0,0,,我们所做的这一切\nDialogue: 0,0:00:48.54,0:00:49.63,Default,,0,0,0,,目前来讲\nDialogue: 0,0:00:49.88,0:00:51.95,Default,,0,0,0,,都是在一种没有赋值语句的计算机语言中完成的\nDialogue: 0,0:00:53.77,0:00:58.17,Default,,0,0,0,,对于你们中用过Basic或者Pascal的人\nDialogue: 0,0:00:58.68,0:01:01.23,Default,,0,0,0,,可能会认为“赋值”是最重要的东西\nDialogue: 0,0:01:01.79,0:01:03.82,Default,,0,0,0,,今天我们将要做一些糟糕的事情\nDialogue: 0,0:01:03.82,0:01:05.45,Default,,0,0,0,,我们要把赋值语句加进来\nDialogue: 0,0:01:07.21,0:01:09.14,Default,,0,0,0,,既然在没有赋值语句的时候 我们都可以很好地完成工作\nDialogue: 0,0:01:09.14,0:01:10.17,Default,,0,0,0,,为什么我们还要把它加进来呢？\nDialogue: 0,0:01:10.99,0:01:12.43,Default,,0,0,0,,为了理解它\nDialogue: 0,0:01:12.46,0:01:15.71,Default,,0,0,0,,我们今天首先要定下一个规则\nDialogue: 0,0:01:16.48,0:01:17.93,Default,,0,0,0,,而我们将一直遵守这个规则\nDialogue: 0,0:01:17.93,0:01:20.80,Default,,0,0,0,,这是我们为语言引入新的特性的唯一原因\nDialogue: 0,0:01:21.53,0:01:23.14,Default,,0,0,0,,是因为我们有一个好的理由\nDialogue: 0,0:01:23.93,0:01:27.28,Default,,0,0,0,,好的理由归结为能力\nDialogue: 0,0:01:27.42,0:01:31.51,Default,,0,0,0,,你现在获得了把问题分解为不同部分的能力\nDialogue: 0,0:01:31.51,0:01:33.44,Default,,0,0,0,,在没有相关能力之前可不行\nDialogue: 0,0:01:34.38,0:01:36.16,Default,,0,0,0,,这让你有用来分解问题的另外方法\nDialogue: 0,0:01:38.30,0:01:39.45,Default,,0,0,0,,我们这就开始\nDialogue: 0,0:01:39.45,0:01:41.88,Default,,0,0,0,,从回顾我们的\nDialogue: 0,0:01:41.88,0:01:47.37,Default,,0,0,0,,现在已经有的这种语言出发\nDialogue: 0,0:01:48.16,0:01:50.44,Default,,0,0,0,,我们之前写的是所谓的函数式程序\nDialogue: 0,0:01:51.21,0:01:52.52,Default,,0,0,0,,函数式程序\nDialogue: 0,0:01:53.04,0:01:57.95,Default,,0,0,0,,是一种对数学事实的编码\nDialogue: 0,0:01:58.88,0:02:00.51,Default,,0,0,0,,例如 当我们看到\nDialogue: 0,0:02:00.51,0:02:04.09,Default,,0,0,0,,像幻灯片上这样阶乘过程时\nDialogue: 0,0:02:05.07,0:02:06.62,Default,,0,0,0,,基本上是两个子句\nDialogue: 0,0:02:06.99,0:02:08.64,Default,,0,0,0,,如果n是1 则结果是1\nDialogue: 0,0:02:08.64,0:02:11.20,Default,,0,0,0,,否则返回n乘以n-1的阶乘\nDialogue: 0,0:02:11.20,0:02:12.33,Default,,0,0,0,,这是n的阶乘\nDialogue: 0,0:02:12.89,0:02:14.27,Default,,0,0,0,,它就是阶乘函数\nDialogue: 0,0:02:14.83,0:02:16.87,Default,,0,0,0,,如果用一些其他的记号\nDialogue: 0,0:02:16.87,0:02:19.32,Default,,0,0,0,,那些你在微积分课堂上学到的晦涩的符号来写\nDialogue: 0,0:02:20.30,0:02:22.11,Default,,0,0,0,,用数理逻辑来写\nDialogue: 0,0:02:22.11,0:02:26.36,Default,,0,0,0,,如果n等于1\nDialogue: 0,0:02:27.13,0:02:29.90,Default,,0,0,0,,那么n的阶乘结果是1 否则\nDialogue: 0,0:02:29.90,0:02:32.56,Default,,0,0,0,,如果n大于1 则n的阶乘就是n * (n-1)!\nDialogue: 0,0:02:32.56,0:02:33.55,Default,,0,0,0,,数学事实\nDialogue: 0,0:02:34.92,0:02:36.70,Default,,0,0,0,,就是我们一直使用的那种语言\nDialogue: 0,0:02:37.00,0:02:39.23,Default,,0,0,0,,无论何时 我们遇到了这样的数学事实\nDialogue: 0,0:02:39.53,0:02:46.65,Default,,0,0,0,,有一种理解它们工作原理的方法\nDialogue: 0,0:02:47.40,0:02:51.12,Default,,0,0,0,,就是这些过程可以由代换演算而来\nDialogue: 0,0:02:51.29,0:02:53.71,Default,,0,0,0,,来看第二张幻灯片\nDialogue: 0,0:02:54.99,0:02:58.81,Default,,0,0,0,,我们理解执行的过程\nDialogue: 0,0:02:58.83,0:03:03.50,Default,,0,0,0,,隐含在表达式的顺序中\nDialogue: 0,0:03:04.04,0:03:07.76,Default,,0,0,0,,也就是你不断地将实际参数\nDialogue: 0,0:03:07.87,0:03:10.88,Default,,0,0,0,,代换到程序体的形式参数中\nDialogue: 0,0:03:12.00,0:03:14.51,Default,,0,0,0,,这些基本上是一系列的等价代换\nDialogue: 0,0:03:14.61,0:03:17.25,Default,,0,0,0,,4的阶乘是4乘以3的阶乘\nDialogue: 0,0:03:17.25,0:03:20.05,Default,,0,0,0,,也就是4乘以3乘以2的阶乘\nDialogue: 0,0:03:20.05,0:03:21.01,Default,,0,0,0,,以此类推\nDialogue: 0,0:03:21.23,0:03:23.87,Default,,0,0,0,,我们总是保持数学事实成立\nDialogue: 0,0:03:25.23,0:03:28.84,Default,,0,0,0,,尽管我们正在讨论数学事实\nDialogue: 0,0:03:28.84,0:03:31.96,Default,,0,0,0,,可能有多种数学事实的组织方式\nDialogue: 0,0:03:31.96,0:03:35.12,Default,,0,0,0,,用来描述一个特定的函数的计算\nDialogue: 0,0:03:36.32,0:03:38.42,Default,,0,0,0,,这个特定的函数的值的计算\nDialogue: 0,0:03:38.42,0:03:40.92,Default,,0,0,0,,所以 让我来看下这里的例子\nDialogue: 0,0:03:41.48,0:03:49.02,Default,,0,0,0,,这有一个计算m与n之和的方法\nDialogue: 0,0:03:49.53,0:03:52.04,Default,,0,0,0,,我们使用一个递归的过程来完成\nDialogue: 0,0:03:52.89,0:03:58.16,Default,,0,0,0,,也就是(1+ (+ (-1+ n) m))\nDialogue: 0,0:04:00.08,0:04:05.62,Default,,0,0,0,,当然 这里也有相应的数理逻辑 解释了这个方法\nDialogue: 0,0:04:06.17,0:04:10.49,Default,,0,0,0,,也就是((n-1)+m)+1\nDialogue: 0,0:04:11.40,0:04:12.22,Default,,0,0,0,,跟之前那个一样\nDialogue: 0,0:04:13.10,0:04:16.40,Default,,0,0,0,,所以这儿并没有什么特殊的魔法\nDialogue: 0,0:04:16.41,0:04:20.01,Default,,0,0,0,,当然 如果我们可以再来看一个相同的迭代过程\nDialogue: 0,0:04:20.19,0:04:24.92,Default,,0,0,0,,计算同样的函数 但是进行逐步迭代的程序\nDialogue: 0,0:04:25.26,0:04:27.56,Default,,0,0,0,,这两个程序将得到同样的结果\nDialogue: 0,0:04:30.08,0:04:34.83,Default,,0,0,0,,我们就可以认为这两个程序在数学上是等效的\nDialogue: 0,0:04:36.65,0:04:39.93,Default,,0,0,0,,你对这些数学事实的排序 决定了具体（计算）过程\nDialogue: 0,0:04:40.30,0:04:43.42,Default,,0,0,0,,我们对于这些数学事实的排序和选择 决定了过程发展的方式\nDialogue: 0,0:04:44.33,0:04:48.60,Default,,0,0,0,,因此我们可以灵活地讨论待计算的函数\nDialogue: 0,0:04:48.60,0:04:50.19,Default,,0,0,0,,以及计算该函数的所用的方法\nDialogue: 0,0:04:50.60,0:04:52.60,Default,,0,0,0,,这并不清晰 我们需要再深入一些\nDialogue: 0,0:04:53.61,0:04:55.50,Default,,0,0,0,,然而 今天我要来讲这个糟糕的东西\nDialogue: 0,0:04:55.50,0:04:58.43,Default,,0,0,0,,我要给大家介绍赋值操作\nDialogue: 0,0:04:58.89,0:05:00.41,Default,,0,0,0,,这是什么？\nDialogue: 0,0:05:02.89,0:05:09.22,Default,,0,0,0,,首先 在编程语言中有另一种语句\nDialogue: 0,0:05:09.22,0:05:10.84,Default,,0,0,0,,这种语句叫做SET!\nDialogue: 0,0:05:12.41,0:05:15.96,Default,,0,0,0,,具有赋值操作的语句\nDialogue: 0,0:05:15.98,0:05:17.85,Default,,0,0,0,,我都会在后面加上一个感叹号\nDialogue: 0,0:05:18.51,0:05:20.96,Default,,0,0,0,,这个感叹号代表什么意思呢？\nDialogue: 0,0:05:20.96,0:05:23.01,Default,,0,0,0,,这个感叹号 与问号类似\nDialogue: 0,0:05:23.01,0:05:25.88,Default,,0,0,0,,是我们给名字随意加的符号\nDialogue: 0,0:05:25.88,0:05:27.88,Default,,0,0,0,,它对于系统来说没有意义\nDialogue: 0,0:05:28.08,0:05:30.21,Default,,0,0,0,,它唯一的意义就是告诉我们\nDialogue: 0,0:05:30.40,0:05:34.41,Default,,0,0,0,,注意这里是某种赋值操作\nDialogue: 0,0:05:35.88,0:05:40.06,Default,,0,0,0,,但是我们要给某个变量赋一个值\nDialogue: 0,0:05:43.74,0:05:45.13,Default,,0,0,0,,这意味着\nDialogue: 0,0:05:45.13,0:05:48.28,Default,,0,0,0,,在某个时间点发生了一些事情\nDialogue: 0,0:05:48.65,0:05:49.61,Default,,0,0,0,,这是一个时间点\nDialogue: 0,0:05:49.86,0:05:52.14,Default,,0,0,0,,如果时间以这个方向流动\nDialogue: 0,0:05:53.50,0:05:54.82,Default,,0,0,0,,这是个时间轴\nDialogue: 0,0:05:55.00,0:05:57.82,Default,,0,0,0,,时间在平面上由上到下地流逝\nDialogue: 0,0:05:58.70,0:06:00.92,Default,,0,0,0,,赋值是第一个\nDialogue: 0,0:06:00.92,0:06:04.30,Default,,0,0,0,,使过去和未来之间产生差别的事物\nDialogue: 0,0:06:06.59,0:06:08.72,Default,,0,0,0,,我们之前写的所有程序\nDialogue: 0,0:06:09.18,0:06:10.68,Default,,0,0,0,,都不包含赋值\nDialogue: 0,0:06:10.68,0:06:13.12,Default,,0,0,0,,这些程序以怎样的顺序进行执行都没关系\nDialogue: 0,0:06:14.70,0:06:15.96,Default,,0,0,0,,但是赋值比较特殊\nDialogue: 0,0:06:15.96,0:06:17.69,Default,,0,0,0,,它使时间中产生了一个时间点\nDialogue: 0,0:06:17.96,0:06:24.73,Default,,0,0,0,,因此在SET!出现之前和之后中间有一个时间点\nDialogue: 0,0:06:27.61,0:06:32.70,Default,,0,0,0,,使得在这个时间点之后\nDialogue: 0,0:06:33.60,0:06:43.76,Default,,0,0,0,,变量有了一个值 即VALUE\nDialogue: 0,0:06:49.23,0:06:51.50,Default,,0,0,0,,与这个变量之前的值无关\nDialogue: 0,0:06:52.80,0:06:55.79,Default,,0,0,0,,SET!改变了它的值\nDialogue: 0,0:06:57.69,0:06:58.75,Default,,0,0,0,,在此之前\nDialogue: 0,0:06:58.75,0:07:01.50,Default,,0,0,0,,什么都没有发生改变\nDialogue: 0,0:07:03.21,0:07:04.11,Default,,0,0,0,,举例来说\nDialogue: 0,0:07:04.84,0:07:06.23,Default,,0,0,0,,我们可以想到的一件事是\nDialogue: 0,0:07:06.23,0:07:09.42,Default,,0,0,0,,我们写的一些过程 比如阶乘的程序\nDialogue: 0,0:07:09.64,0:07:12.75,Default,,0,0,0,,事实上与数学中的阶乘函数完全相同\nDialogue: 0,0:07:13.77,0:07:16.44,Default,,0,0,0,,比如说4的阶乘 如果我写FACT(4)\nDialogue: 0,0:07:17.23,0:07:19.15,Default,,0,0,0,,无论它的上下文是怎样的\nDialogue: 0,0:07:19.69,0:07:21.29,Default,,0,0,0,,无论我写几遍\nDialogue: 0,0:07:21.29,0:07:22.35,Default,,0,0,0,,我总能得到同样的结果\nDialogue: 0,0:07:23.29,0:07:24.12,Default,,0,0,0,,结果永远是24\nDialogue: 0,0:07:25.37,0:07:28.92,Default,,0,0,0,,它是参数到到结果的唯一映射\nDialogue: 0,0:07:30.30,0:07:32.65,Default,,0,0,0,,迄今为止 我们之前写的所有程序都是这样的\nDialogue: 0,0:07:33.52,0:07:36.03,Default,,0,0,0,,然而 当引入赋值后 一切就不同了\nDialogue: 0,0:07:36.96,0:07:38.16,Default,,0,0,0,,举个例子\nDialogue: 0,0:07:39.18,0:07:48.52,Default,,0,0,0,,如果我将COUNT定义为1\nDialogue: 0,0:07:50.00,0:07:52.41,Default,,0,0,0,,然后定义一个过程\nDialogue: 0,0:07:55.16,0:07:56.83,Default,,0,0,0,,一个叫做DEMO的简单过程\nDialogue: 0,0:07:59.52,0:08:03.84,Default,,0,0,0,,它接受参数X 并执行下面的操作\nDialogue: 0,0:08:03.84,0:08:09.62,Default,,0,0,0,,首先将X修改为X+1\nDialogue: 0,0:08:09.62,0:08:11.77,Default,,0,0,0,,我的天啊！ 这看起来就像FORTRAN是吧？\nDialogue: 0,0:08:13.16,0:08:14.17,Default,,0,0,0,,只是用了些有趣的语法\nDialogue: 0,0:08:16.80,0:08:21.37,Default,,0,0,0,,然后返回(+ X COUNT)\nDialogue: 0,0:08:22.14,0:08:24.14,Default,,0,0,0,,哦 我刚犯了个错\nDialogue: 0,0:08:24.38,0:08:25.23,Default,,0,0,0,,我的意思是\nDialogue: 0,0:08:25.47,0:08:27.12,Default,,0,0,0,,(SET! COUNT (1+ COUNT))\nDialogue: 0,0:08:30.37,0:08:31.79,Default,,0,0,0,,就是我在这里定义的这个\nDialogue: 0,0:08:34.41,0:08:36.51,Default,,0,0,0,,然后X和COUNT相加\nDialogue: 0,0:08:40.35,0:08:42.06,Default,,0,0,0,,然后就可以试着运行这个过程了\nDialogue: 0,0:08:42.48,0:08:43.20,Default,,0,0,0,,让我们运行它\nDialogue: 0,0:08:43.92,0:08:47.22,Default,,0,0,0,,假设我可以输入\nDialogue: 0,0:08:47.48,0:08:48.68,Default,,0,0,0,,输入(DEMO 3)\nDialogue: 0,0:08:52.19,0:08:53.20,Default,,0,0,0,,这里发生了什么？\nDialogue: 0,0:08:53.74,0:08:55.28,Default,,0,0,0,,发生的第一件事情是\nDialogue: 0,0:08:55.53,0:08:56.89,Default,,0,0,0,,COUNT现在是1\nDialogue: 0,0:08:56.89,0:08:58.40,Default,,0,0,0,,现在 这是一个时间点\nDialogue: 0,0:08:59.12,0:09:00.29,Default,,0,0,0,,我们在讨论时间点\nDialogue: 0,0:09:00.62,0:09:01.74,Default,,0,0,0,,X的值为3\nDialogue: 0,0:09:02.92,0:09:04.03,Default,,0,0,0,,在这个时刻\nDialogue: 0,0:09:04.67,0:09:07.53,Default,,0,0,0,,COUNT增加了 所以COUNT是2\nDialogue: 0,0:09:09.02,0:09:10.44,Default,,0,0,0,,2加3等于5\nDialogue: 0,0:09:10.80,0:09:12.43,Default,,0,0,0,,所以结果是5\nDialogue: 0,0:09:14.48,0:09:21.58,Default,,0,0,0,,然后我再一次 输入(DEMO 3)\nDialogue: 0,0:09:23.60,0:09:24.56,Default,,0,0,0,,结果是什么？\nDialogue: 0,0:09:24.83,0:09:27.40,Default,,0,0,0,,现在COUNT是2 它不再是1了\nDialogue: 0,0:09:28.91,0:09:30.35,Default,,0,0,0,,因为我让COUNT加1了\nDialogue: 0,0:09:30.92,0:09:32.64,Default,,0,0,0,,但现在我执行这个过程\nDialogue: 0,0:09:32.72,0:09:33.66,Default,,0,0,0,,X的值为3\nDialogue: 0,0:09:34.17,0:09:37.40,Default,,0,0,0,,COUNT变为1+COUNT 因此现在是3了\nDialogue: 0,0:09:38.08,0:09:39.62,Default,,0,0,0,,这两个相加是6\nDialogue: 0,0:09:39.62,0:09:40.94,Default,,0,0,0,,所以结果是6\nDialogue: 0,0:09:41.92,0:09:43.03,Default,,0,0,0,,我们可以发现\nDialogue: 0,0:09:43.03,0:09:44.72,Default,,0,0,0,,同样的表达式\nDialogue: 0,0:09:45.08,0:09:46.64,Default,,0,0,0,,因为时间节点的不同\nDialogue: 0,0:09:48.75,0:09:49.96,Default,,0,0,0,,得到了不同的结果\nDialogue: 0,0:09:52.08,0:09:53.74,Default,,0,0,0,,所以DEMO不是函数\nDialogue: 0,0:09:54.17,0:09:56.12,Default,,0,0,0,,或者说它并没有计算一个数学意义上的函数\nDialogue: 0,0:09:59.88,0:10:02.09,Default,,0,0,0,,事实上 你可以知道这是为什么\nDialogue: 0,0:10:02.84,0:10:06.41,Default,,0,0,0,,因为这里是第一处代换模型失效的地方\nDialogue: 0,0:10:07.72,0:10:09.55,Default,,0,0,0,,它给代换模型判了死刑\nDialogue: 0,0:10:11.28,0:10:13.82,Default,,0,0,0,,有些关于引用的一些小问题\nDialogue: 0,0:10:13.85,0:10:17.18,Default,,0,0,0,,哲学家可能注意到 特别是与代换有关时\nDialogue: 0,0:10:17.18,0:10:19.87,Default,,0,0,0,,因为当你在引用中进行代换时\nDialogue: 0,0:10:20.91,0:10:22.12,Default,,0,0,0,,需要考虑你可以得到什么样的推论\nDialogue: 0,0:10:22.34,0:10:23.92,Default,,0,0,0,,如果你能够使用代换的话\nDialogue: 0,0:10:25.08,0:10:25.60,Default,,0,0,0,,但是\nDialogue: 0,0:10:26.06,0:10:28.00,Default,,0,0,0,,在这里代换模型已经失效了\nDialogue: 0,0:10:28.11,0:10:29.40,Default,,0,0,0,,它什么也不能做了\nDialogue: 0,0:10:29.64,0:10:30.57,Default,,0,0,0,,因为\nDialogue: 0,0:10:30.57,0:10:35.85,Default,,0,0,0,,假设我想用代换模型来考虑COUNT的代换\nDialogue: 0,0:10:37.10,0:10:41.16,Default,,0,0,0,,如果我在这里和这里进行代换\nDialogue: 0,0:10:41.69,0:10:42.96,Default,,0,0,0,,它们是不同的\nDialogue: 0,0:10:44.44,0:10:45.96,Default,,0,0,0,,它不再是同一个COUNT了\nDialogue: 0,0:10:46.48,0:10:47.64,Default,,0,0,0,,我得到了错误的结果\nDialogue: 0,0:10:47.97,0:10:50.14,Default,,0,0,0,,代换模型是一个静态的现象\nDialogue: 0,0:10:51.18,0:10:52.56,Default,,0,0,0,,它描述的事实\nDialogue: 0,0:10:53.93,0:10:55.29,Default,,0,0,0,,而不是变动\nDialogue: 0,0:10:55.50,0:10:57.04,Default,,0,0,0,,这里 我们的事实变动了\nDialogue: 0,0:11:00.60,0:11:06.74,Default,,0,0,0,,那么 在我给出任何解释之前\nDialogue: 0,0:11:06.74,0:11:07.79,Default,,0,0,0,,这很糟糕\nDialogue: 0,0:11:07.79,0:11:09.72,Default,,0,0,0,,我们失去了我们的计算模型\nDialogue: 0,0:11:10.28,0:11:10.80,Default,,0,0,0,,并且\nDialogue: 0,0:11:11.48,0:11:13.69,Default,,0,0,0,,很快 我将不得不构建一个新的计算模型\nDialogue: 0,0:11:14.66,0:11:17.87,Default,,0,0,0,,我们现在的讨论 还是从一个不严谨的角度进行的\nDialogue: 0,0:11:18.56,0:11:20.16,Default,,0,0,0,,当然 你们已经看到的是\nDialogue: 0,0:11:20.51,0:11:22.70,Default,,0,0,0,,当我做一些像赋值之类的事情时\nDialogue: 0,0:11:23.12,0:11:24.51,Default,,0,0,0,,我们所需要的模型\nDialogue: 0,0:11:24.51,0:11:26.89,Default,,0,0,0,,与我们之前模型不同\nDialogue: 0,0:11:26.89,0:11:30.93,Default,,0,0,0,,在这个的模型中 像COUNT或X这样的符号\nDialogue: 0,0:11:30.93,0:11:34.07,Default,,0,0,0,,不再关联于它们的值\nDialogue: 0,0:11:34.07,0:11:37.31,Default,,0,0,0,,而是关联于某个储存这些值的地方\nDialogue: 0,0:11:37.68,0:11:39.47,Default,,0,0,0,,我们将花些时间来适应这种思想\nDialogue: 0,0:11:40.20,0:11:42.11,Default,,0,0,0,,这将是一个很糟糕的事情\nDialogue: 0,0:11:42.11,0:11:43.47,Default,,0,0,0,,并且会造成很多麻烦\nDialogue: 0,0:11:44.49,0:11:48.25,Default,,0,0,0,,所以 就像我说的 若非理由周全\nDialogue: 0,0:11:48.25,0:11:50.09,Default,,0,0,0,,不然绝不要发明这种糟糕的东西\nDialogue: 0,0:11:50.37,0:11:52.86,Default,,0,0,0,,否则 就是劳神费力\nDialogue: 0,0:11:53.39,0:11:55.55,Default,,0,0,0,,让我们看看一些可以讨论的东西\nDialogue: 0,0:11:55.88,0:11:58.59,Default,,0,0,0,,假设我们写了函数式版本的阶乘函数\nDialogue: 0,0:11:58.59,0:12:00.48,Default,,0,0,0,,我们以前的就是“函数式”风格\nDialogue: 0,0:12:01.37,0:12:04.60,Default,,0,0,0,,具有迭代计算过程的阶乘函数\nDialogue: 0,0:12:09.59,0:12:13.28,Default,,0,0,0,,N的阶乘\nDialogue: 0,0:12:18.38,0:12:24.35,Default,,0,0,0,,我们要(ITER M I)\nDialogue: 0,0:12:26.12,0:12:33.13,Default,,0,0,0,,就是说如果I大于N\nDialogue: 0,0:12:33.77,0:12:35.51,Default,,0,0,0,,则结果是M\nDialogue: 0,0:12:36.30,0:12:37.39,Default,,0,0,0,,否则\nDialogue: 0,0:12:39.79,0:12:46.82,Default,,0,0,0,,结果是(ITER (* I M))\nDialogue: 0,0:12:46.82,0:12:49.95,Default,,0,0,0,,所以M将是我累积的结果\nDialogue: 0,0:12:51.58,0:12:52.62,Default,,0,0,0,,M就是这个乘积[注：此处教授笔误]\nDialogue: 0,0:12:57.97,0:13:00.17,Default,,0,0,0,,然后我要把COUNT加1\nDialogue: 0,0:13:04.62,0:13:10.97,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:13:11.95,0:13:13.04,Default,,0,0,0,,我在这里启动这个内部过程\nDialogue: 0,0:13:17.16,0:13:19.79,Default,,0,0,0,,对于这种代码 我想大家早已驾轻就熟了\nDialogue: 0,0:13:20.86,0:13:25.15,Default,,0,0,0,,这里是一个累积的乘积 和一个计数器\nDialogue: 0,0:13:26.48,0:13:28.46,Default,,0,0,0,,我让它们都从1开始\nDialogue: 0,0:13:28.89,0:13:30.92,Default,,0,0,0,,我将不断让计数器增加\nDialogue: 0,0:13:30.92,0:13:33.12,Default,,0,0,0,,每一轮I变成I+1\nDialogue: 0,0:13:34.56,0:13:37.47,Default,,0,0,0,,这是我们在这个过程中设置时间的唯一方法\nDialogue: 0,0:13:38.48,0:13:40.04,Default,,0,0,0,,这些都是一系列的事实\nDialogue: 0,0:13:40.49,0:13:41.34,Default,,0,0,0,,真实的规则\nDialogue: 0,0:13:42.81,0:13:46.13,Default,,0,0,0,,M将获得一个新的值 就是I乘M\nDialogue: 0,0:13:46.13,0:13:47.82,Default,,0,0,0,,每一轮I乘以M\nDialogue: 0,0:13:48.68,0:13:50.48,Default,,0,0,0,,最终I将大于N\nDialogue: 0,0:13:50.49,0:13:52.06,Default,,0,0,0,,在这种情况下 结果就是M\nDialogue: 0,0:13:52.67,0:13:54.80,Default,,0,0,0,,我给你们讲课的时候 用到了“时间”这个概念\nDialogue: 0,0:13:55.68,0:13:57.45,Default,,0,0,0,,那是因为我知道计算机是怎么工作的\nDialogue: 0,0:13:58.25,0:13:59.24,Default,,0,0,0,,但是我没必要这么做\nDialogue: 0,0:13:59.26,0:14:02.30,Default,,0,0,0,,这完全可以有一个纯数学的解释\nDialogue: 0,0:14:02.30,0:14:03.74,Default,,0,0,0,,因为在这里代换可以工作\nDialogue: 0,0:14:05.10,0:14:08.14,Default,,0,0,0,,但是我们写一个类似的程序\nDialogue: 0,0:14:08.30,0:14:09.95,Default,,0,0,0,,使用相同的算法\nDialogue: 0,0:14:10.73,0:14:12.11,Default,,0,0,0,,但使用了赋值\nDialogue: 0,0:14:15.69,0:14:17.16,Default,,0,0,0,,所以这个叫做函数式版本\nDialogue: 0,0:14:23.72,0:14:25.56,Default,,0,0,0,,我想写个命令式的版本的\nDialogue: 0,0:14:34.48,0:14:35.39,Default,,0,0,0,,N的阶乘\nDialogue: 0,0:14:35.92,0:14:37.74,Default,,0,0,0,,我要创建两个变量\nDialogue: 0,0:14:40.16,0:14:45.53,Default,,0,0,0,,把I的值初始化为1\nDialogue: 0,0:14:46.32,0:14:49.77,Default,,0,0,0,,M也初始化为1\nDialogue: 0,0:14:51.15,0:14:52.19,Default,,0,0,0,,我们创建一个循环\nDialogue: 0,0:14:59.31,0:15:07.27,Default,,0,0,0,,如果I比N大 循环结束\nDialogue: 0,0:15:07.27,0:15:08.87,Default,,0,0,0,,结果是M\nDialogue: 0,0:15:08.87,0:15:10.38,Default,,0,0,0,,也就是我累积的乘积\nDialogue: 0,0:15:10.87,0:15:11.77,Default,,0,0,0,,否则\nDialogue: 0,0:15:15.52,0:15:17.40,Default,,0,0,0,,我接下来要做三件事\nDialogue: 0,0:15:19.26,0:15:27.05,Default,,0,0,0,,我要把M赋值为I*M\nDialogue: 0,0:15:29.36,0:15:35.20,Default,,0,0,0,,把I赋值为I+1\nDialogue: 0,0:15:37.85,0:15:39.31,Default,,0,0,0,,然后继续循环\nDialogue: 0,0:15:40.41,0:15:43.02,Default,,0,0,0,,你们中的FORTRAN程序员应该觉得眼熟\nDialogue: 0,0:15:44.73,0:15:46.64,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:15:46.64,0:15:47.88,Default,,0,0,0,,就是这种语法有点陌生\nDialogue: 0,0:15:51.13,0:15:52.27,Default,,0,0,0,,启动循环\nDialogue: 0,0:15:56.10,0:15:57.56,Default,,0,0,0,,程序就写完了\nDialogue: 0,0:15:59.15,0:16:00.52,Default,,0,0,0,,那么 这个程序\nDialogue: 0,0:16:01.31,0:16:02.49,Default,,0,0,0,,我们应该怎么思考它呢？\nDialogue: 0,0:16:02.71,0:16:04.25,Default,,0,0,0,,先来看看这里是什么\nDialogue: 0,0:16:04.84,0:16:07.47,Default,,0,0,0,,这里有两个局部变量 I和M\nDialogue: 0,0:16:07.47,0:16:09.02,Default,,0,0,0,,它们都被初始化为1\nDialogue: 0,0:16:10.72,0:16:13.89,Default,,0,0,0,,在每一次循环里 我检测I是否大于N\nDialogue: 0,0:16:13.89,0:16:15.08,Default,,0,0,0,,就是我们传入的参数\nDialogue: 0,0:16:15.30,0:16:18.14,Default,,0,0,0,,如果成立的话 结果就是M中所累积的乘积\nDialogue: 0,0:16:19.16,0:16:21.21,Default,,0,0,0,,然而 如果循环没有结束\nDialogue: 0,0:16:21.21,0:16:22.89,Default,,0,0,0,,如果我们的工作没有结束\nDialogue: 0,0:16:23.64,0:16:25.55,Default,,0,0,0,,则我们要把乘积\nDialogue: 0,0:16:25.84,0:16:28.38,Default,,0,0,0,,变为i与当前乘积的结果\nDialogue: 0,0:16:29.04,0:16:30.68,Default,,0,0,0,,就是我们在这里做过的事情\nDialogue: 0,0:16:31.42,0:16:32.68,Default,,0,0,0,,除了这里我没有改动\nDialogue: 0,0:16:33.63,0:16:35.77,Default,,0,0,0,,我创建了一个复本\nDialogue: 0,0:16:36.81,0:16:42.04,Default,,0,0,0,,因为代换模型就是你复制过程的体\nDialogue: 0,0:16:43.08,0:16:45.88,Default,,0,0,0,,并用实际参数代换形式参数\nDialogue: 0,0:16:46.72,0:16:48.42,Default,,0,0,0,,这里 我考虑的不是副本\nDialogue: 0,0:16:48.42,0:16:50.52,Default,,0,0,0,,在这里 我已经改变了M的值\nDialogue: 0,0:16:51.80,0:16:55.12,Default,,0,0,0,,我也把I的值变成了I+1\nDialogue: 0,0:16:55.61,0:16:56.96,Default,,0,0,0,,然后继续循环\nDialogue: 0,0:16:58.22,0:17:00.08,Default,,0,0,0,,看起来是一样的程序\nDialogue: 0,0:17:00.96,0:17:02.84,Default,,0,0,0,,在今天引入赋值之后\nDialogue: 0,0:17:02.84,0:17:05.50,Default,,0,0,0,,我们在这里有很多种方式犯错\nDialogue: 0,0:17:06.14,0:17:07.02,Default,,0,0,0,,例如\nDialogue: 0,0:17:07.45,0:17:09.40,Default,,0,0,0,,如果我在赋值的时候\nDialogue: 0,0:17:10.04,0:17:12.14,Default,,0,0,0,,没有小心地写程序\nDialogue: 0,0:17:12.64,0:17:16.08,Default,,0,0,0,,把两个赋值的顺序调换了\nDialogue: 0,0:17:17.10,0:17:18.91,Default,,0,0,0,,程序计算的就不是相同的函数了\nDialogue: 0,0:17:20.33,0:17:22.87,Default,,0,0,0,,我得到了一个时间错误 因为这儿有个依赖关系\nDialogue: 0,0:17:22.87,0:17:27.22,Default,,0,0,0,,因为M依赖于I上一次的值\nDialogue: 0,0:17:27.34,0:17:28.92,Default,,0,0,0,,如果我先改变I的值\nDialogue: 0,0:17:31.31,0:17:33.77,Default,,0,0,0,,就会在乘以M的时候 得到错误的I值\nDialogue: 0,0:17:35.96,0:17:38.38,Default,,0,0,0,,没有赋值的话不会存在这样的BUG\nDialogue: 0,0:17:38.38,0:17:40.59,Default,,0,0,0,,这是由于我们引入了某些包含时间的东西造成的\nDialogue: 0,0:17:43.44,0:17:44.30,Default,,0,0,0,,如我所说的\nDialogue: 0,0:17:45.53,0:17:47.39,Default,,0,0,0,,首先 我们需要一个新的计算模型\nDialogue: 0,0:17:47.39,0:17:50.86,Default,,0,0,0,,然后 需要有一个非常好的理由来支持我们做如此丑陋的事\nDialogue: 0,0:17:52.72,0:17:53.74,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:17:58.83,0:18:00.22,Default,,0,0,0,,David 大点儿声说\nDialogue: 0,0:18:00.40,0:18:03.47,Default,,0,0,0,,学生：现在 我们引入了SET!\nDialogue: 0,0:18:03.90,0:18:06.36,Default,,0,0,0,,但是之前我们已经有LET和DEFINE了\nDialogue: 0,0:18:06.89,0:18:09.70,Default,,0,0,0,,我不太清楚它们的区别\nDialogue: 0,0:18:09.70,0:18:13.25,Default,,0,0,0,,DEFINE不能像SET!一样用吗？\nDialogue: 0,0:18:13.98,0:18:14.83,Default,,0,0,0,,请详细讲讲\nDialogue: 0,0:18:14.83,0:18:19.31,Default,,0,0,0,,教授：不 DEFINE用于创建并初始化\nDialogue: 0,0:18:19.31,0:18:21.36,Default,,0,0,0,,为了创建它\nDialogue: 0,0:18:22.08,0:18:24.70,Default,,0,0,0,,你永远也不会见到我在黑板上\nDialogue: 0,0:18:25.60,0:18:26.94,Default,,0,0,0,,在同一行写两个DEFINE\nDialogue: 0,0:18:27.08,0:18:32.08,Default,,0,0,0,,只是为了让某个变量的旧值变成一个新的值\nDialogue: 0,0:18:32.08,0:18:34.51,Default,,0,0,0,,学生：这是一个约定俗成的规矩 还是--\nDialogue: 0,0:18:34.51,0:18:36.35,Default,,0,0,0,,教授：不 这是有意为之的\nDialogue: 0,0:18:36.35,0:18:38.92,Default,,0,0,0,,答案是\nDialogue: 0,0:18:39.69,0:18:40.84,Default,,0,0,0,,举个例子\nDialogue: 0,0:18:40.84,0:18:42.27,Default,,0,0,0,,在一个过程内部\nDialogue: 0,0:18:43.20,0:18:45.92,Default,,0,0,0,,两个DEFINE写在一行里是非法的\nDialogue: 0,0:18:46.68,0:18:48.57,Default,,0,0,0,,对于同一个变量DEFINE两次是非法的\nDialogue: 0,0:18:50.24,0:18:51.74,Default,,0,0,0,,X不能被DEFINE两次\nDialogue: 0,0:18:51.74,0:18:55.20,Default,,0,0,0,,而系统会不会捕获这个错误 就是另一个问题了\nDialogue: 0,0:18:55.93,0:18:57.88,Default,,0,0,0,,但是我定下规矩\nDialogue: 0,0:18:58.12,0:19:00.64,Default,,0,0,0,,任何东西都只能DEFINE一次\nDialogue: 0,0:19:00.73,0:19:02.64,Default,,0,0,0,,确实 在交互式调试中\nDialogue: 0,0:19:03.37,0:19:07.48,Default,,0,0,0,,我们打算让你与计算机交互时可以重新DEFINE一些东西\nDialogue: 0,0:19:08.19,0:19:11.21,Default,,0,0,0,,所以交互式调试时产生的是一个特殊的异常\nDialogue: 0,0:19:11.82,0:19:16.48,Default,,0,0,0,,但是DEFINE的意思是建立某些东西\nDialogue: 0,0:19:18.14,0:19:20.96,Default,,0,0,0,,在那个时间点后 它的值是永远不变的\nDialogue: 0,0:19:22.05,0:19:24.54,Default,,0,0,0,,好像所有的DEFINE都是在最开始完成的\nDialogue: 0,0:19:26.09,0:19:30.92,Default,,0,0,0,,事实上 在Scheme过程中 DEFINE的唯一合法使用地方\nDialogue: 0,0:19:31.02,0:19:33.36,Default,,0,0,0,,就是在LAMBDA表达式的开始\nDialogue: 0,0:19:34.47,0:19:37.66,Default,,0,0,0,,也就是过程体的开始\nDialogue: 0,0:19:40.40,0:19:45.80,Default,,0,0,0,,LET当然与那个不一样\nDialogue: 0,0:19:48.09,0:19:49.55,Default,,0,0,0,,如果你想知道LET发生了什么\nDialogue: 0,0:19:50.17,0:19:52.13,Default,,0,0,0,,LET只会绑定一次\nDialogue: 0,0:19:52.13,0:19:55.82,Default,,0,0,0,,它建立了一个I和M的值分别为1的上下文\nDialogue: 0,0:19:56.83,0:20:00.57,Default,,0,0,0,,这个上下文存在于整个作用域中\nDialogue: 0,0:20:01.31,0:20:02.80,Default,,0,0,0,,也就是这个程序范围\nDialogue: 0,0:20:04.99,0:20:10.12,Default,,0,0,0,,然而 你不会认为LET再次设置了I的值\nDialogue: 0,0:20:11.04,0:20:12.16,Default,,0,0,0,,它没有改变I的值\nDialogue: 0,0:20:12.16,0:20:14.01,Default,,0,0,0,,因为LET的作用 I将永远不会变化\nDialogue: 0,0:20:15.28,0:20:16.81,Default,,0,0,0,,因为LET的作用 I才被创建\nDialogue: 0,0:20:18.51,0:20:19.29,Default,,0,0,0,,实际上\nDialogue: 0,0:20:19.73,0:20:21.42,Default,,0,0,0,,LET是一个非常简单的想法\nDialogue: 0,0:20:22.24,0:20:23.59,Default,,0,0,0,,LET不会做别的事情\nDialogue: 0,0:20:23.59,0:20:31.62,Default,,0,0,0,,LET的语义是……\nDialogue: 0,0:20:31.62,0:20:33.50,Default,,0,0,0,,我把它写得更准确点\nDialogue: 0,0:20:37.16,0:20:43.73,Default,,0,0,0,,表达式 (var1 e1)\nDialogue: 0,0:20:43.73,0:20:47.36,Default,,0,0,0,,还有(var2 e2)\nDialogue: 0,0:20:48.14,0:20:49.74,Default,,0,0,0,,在表达式e3中\nDialogue: 0,0:20:51.60,0:21:05.80,Default,,0,0,0,,与一个以var1和var2为形式参数的过程一样\nDialogue: 0,0:21:06.94,0:21:08.96,Default,,0,0,0,,e3成为过程的体\nDialogue: 0,0:21:10.91,0:21:14.00,Default,,0,0,0,,在这里 var1与e1的值绑定\nDialogue: 0,0:21:14.27,0:21:16.91,Default,,0,0,0,,var2与e2的值绑定\nDialogue: 0,0:21:19.53,0:21:23.26,Default,,0,0,0,,所以实际上 这是一个从代换的角度来看很容易理解的东西\nDialogue: 0,0:21:24.89,0:21:27.95,Default,,0,0,0,,其实就是同一个表达式的两种不同的写法\nDialogue: 0,0:21:31.69,0:21:33.50,Default,,0,0,0,,事实上 系统真正的工作方式\nDialogue: 0,0:21:33.63,0:21:35.82,Default,,0,0,0,,就是在运行之前把代码翻译成这种形式\nDialogue: 0,0:21:37.64,0:21:41.77,Default,,0,0,0,,学生：我还是不清楚是什么造成了LET和DEFINE之间的区别\nDialogue: 0,0:21:41.77,0:21:44.30,Default,,0,0,0,,教授：DEFINE就是个语法糖\nDialogue: 0,0:21:44.62,0:21:49.10,Default,,0,0,0,,本质上来说 是通过LET创建一系列变量 然后给它们一次性赋值\nDialogue: 0,0:21:57.10,0:21:59.74,Default,,0,0,0,,好吧 我们休息一会\nDialogue: 0,0:22:02.52,0:22:12.84,Default,,0,0,0,,[音乐]\nDialogue: 0,0:22:12.84,0:22:17.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:22:48.81,0:22:52.67,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:22:52.67,0:22:56.52,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:22:56.52,0:23:00.59,Declare,,0,0,0,,{\\an2\\fad(500,500)}赋值、状态和副作用\nDialogue: 0,0:23:04.28,0:23:06.11,Default,,0,0,0,,看\nDialogue: 0,0:23:06.44,0:23:09.08,Default,,0,0,0,,现在 我不得不重建计算模型\nDialogue: 0,0:23:09.77,0:23:14.16,Default,,0,0,0,,使得你能够明白那些机制是如何运作的\nDialogue: 0,0:23:14.91,0:23:16.46,Default,,0,0,0,,来完成我们刚才说的那些工作\nDialogue: 0,0:23:17.53,0:23:21.39,Default,,0,0,0,,我刚刚摧毁了你们的代换模型\nDialogue: 0,0:23:22.62,0:23:26.03,Default,,0,0,0,,不幸的是 这个模型比代换模型要复杂得多\nDialogue: 0,0:23:26.62,0:23:27.93,Default,,0,0,0,,这个模型叫环境模型\nDialogue: 0,0:23:29.02,0:23:31.20,Default,,0,0,0,,我即将介绍一些术语\nDialogue: 0,0:23:32.03,0:23:34.51,Default,,0,0,0,,无论如何 你知道这些术语都是很好的\nDialogue: 0,0:23:34.51,0:23:35.74,Default,,0,0,0,,它是关于名字的\nDialogue: 0,0:23:36.51,0:23:39.63,Default,,0,0,0,,我们要给事物的各种名字\nDialogue: 0,0:23:40.00,0:23:41.31,Default,,0,0,0,,和名字的使用途径以名字\nDialogue: 0,0:23:42.48,0:23:47.94,Default,,0,0,0,,如果硬要说的话 这是一个元描述\nDialogue: 0,0:23:48.56,0:23:50.85,Default,,0,0,0,,总之 这里面有一堆糟糕的术语\nDialogue: 0,0:23:50.85,0:23:53.76,Default,,0,0,0,,但我们需要利用它们来理解所谓的“环境模型”\nDialogue: 0,0:23:54.70,0:23:57.53,Default,,0,0,0,,我们可能要做一点无聊的事情了\nDialogue: 0,0:23:58.04,0:24:01.58,Default,,0,0,0,,我们来看第一张张幻灯片\nDialogue: 0,0:24:02.25,0:24:06.97,Default,,0,0,0,,我们看到了术语“约束”的解释\nDialogue: 0,0:24:08.80,0:24:11.00,Default,,0,0,0,,我们会说一个变量V\nDialogue: 0,0:24:11.00,0:24:12.91,Default,,0,0,0,,被约束在表达式E中\nDialogue: 0,0:24:13.41,0:24:21.52,Default,,0,0,0,,如果用一个没有出现在E中的变量W 对变量V统一换名\nDialogue: 0,0:24:21.56,0:24:24.28,Default,,0,0,0,,表达式语义没有发生改变\nDialogue: 0,0:24:25.69,0:24:27.00,Default,,0,0,0,,这个解释很长\nDialogue: 0,0:24:27.37,0:24:29.96,Default,,0,0,0,,在我们在被搞糊涂之前\nDialogue: 0,0:24:29.98,0:24:32.62,Default,,0,0,0,,我应该再多解释下\nDialogue: 0,0:24:33.42,0:24:35.28,Default,,0,0,0,,我们这里讨论的约束变量\nDialogue: 0,0:24:44.16,0:24:45.56,Default,,0,0,0,,你们已经看到它们很多次了\nDialogue: 0,0:24:46.07,0:24:48.17,Default,,0,0,0,,只是你们可能还没意识到\nDialogue: 0,0:24:48.24,0:24:52.24,Default,,0,0,0,,在逻辑学中 你们看到一个逻辑变量\nDialogue: 0,0:24:53.27,0:25:00.11,Default,,0,0,0,,就像微积分课上的 对于任意任何X 存在一个Y 使得P为真\nDialogue: 0,0:25:02.88,0:25:05.82,Default,,0,0,0,,这个变量X 这个变量Y 它们是约束变量\nDialogue: 0,0:25:07.08,0:25:07.92,Default,,0,0,0,,因为\nDialogue: 0,0:25:08.33,0:25:09.98,Default,,0,0,0,,这个表达式的含义\nDialogue: 0,0:25:09.98,0:25:15.61,Default,,0,0,0,,不取决于我用来描述X和Y的具体字母\nDialogue: 0,0:25:16.49,0:25:19.18,Default,,0,0,0,,如果我用W替换X\nDialogue: 0,0:25:19.84,0:25:25.68,Default,,0,0,0,,则可以说对于任意W 存在一个Y使得P为真\nDialogue: 0,0:25:25.98,0:25:27.08,Default,,0,0,0,,它们其实是同一句话\nDialogue: 0,0:25:29.44,0:25:30.34,Default,,0,0,0,,就是这个意思\nDialogue: 0,0:25:30.34,0:25:34.89,Default,,0,0,0,,又或者说 你们看到这样一个积分\nDialogue: 0,0:25:35.40,0:25:42.65,Default,,0,0,0,,对dx/(1+x^2)从0到1积分\nDialogue: 0,0:25:46.03,0:25:47.92,Default,,0,0,0,,这就是你们经常见到的那种东西\nDialogue: 0,0:25:47.92,0:25:50.92,Default,,0,0,0,,这个x是一个约束变量\nDialogue: 0,0:25:52.06,0:25:53.79,Default,,0,0,0,,如果我把它换成t\nDialogue: 0,0:25:54.15,0:25:56.25,Default,,0,0,0,,这个表达式其实没有变化\nDialogue: 0,0:25:58.06,0:26:02.76,Default,,0,0,0,,就是arctan(1)/4之类的\nDialogue: 0,0:26:04.70,0:26:06.01,Default,,0,0,0,,是的 就是arctan(1)\nDialogue: 0,0:26:06.62,0:26:08.76,Default,,0,0,0,,所以约束变量事实上很常见\nDialogue: 0,0:26:09.08,0:26:12.36,Default,,0,0,0,,如果你们接触过一些数学的话\nDialogue: 0,0:26:13.26,0:26:17.47,Default,,0,0,0,,好 让我们来到编程的世界\nDialogue: 0,0:26:19.02,0:26:21.36,Default,,0,0,0,,现在量词不再是\nDialogue: 0,0:26:22.03,0:26:24.06,Default,,0,0,0,,所有、存在和积分\nDialogue: 0,0:26:24.06,0:26:26.43,Default,,0,0,0,,我们有一个符号作为量词 用于约束变量\nDialogue: 0,0:26:27.47,0:26:28.99,Default,,0,0,0,,我们要使用量词LAMBDA\nDialogue: 0,0:26:29.79,0:26:31.80,Default,,0,0,0,,作为约束变量的一个必要的东西\nDialogue: 0,0:26:33.80,0:26:36.12,Default,,0,0,0,,我们有一个极好的例子\nDialogue: 0,0:26:36.59,0:26:44.14,Default,,0,0,0,,对于以Y为参数的过程 做了以下的事情\nDialogue: 0,0:26:44.14,0:26:46.96,Default,,0,0,0,,它调用一个含单个参数X的过程\nDialogue: 0,0:26:47.87,0:26:51.13,Default,,0,0,0,,该过程 将X乘以Y\nDialogue: 0,0:26:52.88,0:26:54.52,Default,,0,0,0,,并应用于3\nDialogue: 0,0:26:58.76,0:27:01.66,Default,,0,0,0,,这个过程中包含两个约束变量\nDialogue: 0,0:27:02.01,0:27:02.92,Default,,0,0,0,,X和Y\nDialogue: 0,0:27:04.83,0:27:07.47,Default,,0,0,0,,这个LAMBDA量词 约束了这个Y\nDialogue: 0,0:27:07.91,0:27:10.78,Default,,0,0,0,,这个LAMBDA量词 约束了这个X\nDialogue: 0,0:27:12.11,0:27:17.05,Default,,0,0,0,,因为 如果我用了一个没有出现在表达式中的任意符号 如W\nDialogue: 0,0:27:17.98,0:27:21.04,Default,,0,0,0,,用W替换表达式中的所有Y\nDialogue: 0,0:27:21.36,0:27:22.75,Default,,0,0,0,,这个表达式仍与原来的相同\nDialogue: 0,0:27:23.66,0:27:24.80,Default,,0,0,0,,是相同的过程\nDialogue: 0,0:27:26.22,0:27:27.41,Default,,0,0,0,,这是一个重要的想法\nDialogue: 0,0:27:27.41,0:27:29.64,Default,,0,0,0,,我们有这种东西的原因\nDialogue: 0,0:27:30.20,0:27:31.41,Default,,0,0,0,,这是一种模块性\nDialogue: 0,0:27:31.41,0:27:32.86,Default,,0,0,0,,如果有两个人写程序\nDialogue: 0,0:27:34.03,0:27:35.26,Default,,0,0,0,,并且他们在合作编程\nDialogue: 0,0:27:35.26,0:27:40.56,Default,,0,0,0,,在他们自己构建的小项目里用什么命名都没有关系\nDialogue: 0,0:27:42.83,0:27:44.67,Default,,0,0,0,,所以 实际上我想告诉你们\nDialogue: 0,0:27:45.44,0:27:46.75,Default,,0,0,0,,例如\nDialogue: 0,0:27:46.84,0:27:51.26,Default,,0,0,0,,这个表达式等于 以Y为参数的过程\nDialogue: 0,0:27:52.35,0:27:59.23,Default,,0,0,0,,使用这个对于一个参数Z的过程 这个过程将Z乘以Y\nDialogue: 0,0:28:01.64,0:28:03.53,Default,,0,0,0,,因为没人关心我在这用什么\nDialogue: 0,0:28:06.36,0:28:07.24,Default,,0,0,0,,这是一个极好的例子\nDialogue: 0,0:28:08.84,0:28:09.85,Default,,0,0,0,,另一方面\nDialogue: 0,0:28:11.07,0:28:14.33,Default,,0,0,0,,我有一些未被约束的变量\nDialogue: 0,0:28:15.23,0:28:15.96,Default,,0,0,0,,举个例子\nDialogue: 0,0:28:20.27,0:28:21.76,Default,,0,0,0,,这个对于一个以X为参数的过程\nDialogue: 0,0:28:22.09,0:28:25.04,Default,,0,0,0,,将X乘以Y\nDialogue: 0,0:28:27.28,0:28:28.16,Default,,0,0,0,,在这个例子中\nDialogue: 0,0:28:29.45,0:28:30.75,Default,,0,0,0,,y没有被约束\nDialogue: 0,0:28:32.46,0:28:34.27,Default,,0,0,0,,假设Y的值是3\nDialogue: 0,0:28:35.26,0:28:36.80,Default,,0,0,0,,Z的值是4\nDialogue: 0,0:28:38.83,0:28:44.27,Default,,0,0,0,,那么这个过程就是把它的参数乘以3\nDialogue: 0,0:28:44.86,0:28:47.39,Default,,0,0,0,,如果我把所有的y都用z来代替\nDialogue: 0,0:28:47.52,0:28:51.96,Default,,0,0,0,,我将得到一个完全不同的过程 它会把参数乘以4\nDialogue: 0,0:28:53.87,0:28:56.40,Default,,0,0,0,,事实上 我们给这类变量取了个名字\nDialogue: 0,0:28:57.76,0:29:04.01,Default,,0,0,0,,我们把表达式E中的变量V叫做自由变量\nDialogue: 0,0:29:04.01,0:29:09.42,Default,,0,0,0,,如果用没有出现在E中的变量W统一替换E中所有的V\nDialogue: 0,0:29:09.58,0:29:11.15,Default,,0,0,0,,使得表达式E的含义发生了改变\nDialogue: 0,0:29:13.26,0:29:13.71,Default,,0,0,0,,所以\nDialogue: 0,0:29:14.49,0:29:22.76,Default,,0,0,0,,所以这就是为什么这个变量Y 是一个自由变量\nDialogue: 0,0:29:29.16,0:29:32.27,Default,,0,0,0,,所以 这个表达式里的自由变量\nDialogue: 0,0:29:33.76,0:29:35.18,Default,,0,0,0,,另一个例子是\nDialogue: 0,0:29:36.17,0:29:39.32,Default,,0,0,0,,对于一个以Y为参数的过程\nDialogue: 0,0:29:40.43,0:29:42.00,Default,,0,0,0,,就像我们之前的那个一样\nDialogue: 0,0:29:42.27,0:29:44.60,Default,,0,0,0,,调用以X为参数的过程\nDialogue: 0,0:29:45.08,0:29:48.54,Default,,0,0,0,,将X与Y相乘--\nDialogue: 0,0:29:51.40,0:29:52.65,Default,,0,0,0,,并应用于3\nDialogue: 0,0:29:57.24,0:30:00.35,Default,,0,0,0,,这个过程中有一个自由变量\nDialogue: 0,0:30:00.92,0:30:01.98,Default,,0,0,0,,也就是这个星号\nDialogue: 0,0:30:05.00,0:30:05.89,Default,,0,0,0,,因为\nDialogue: 0,0:30:05.89,0:30:08.08,Default,,0,0,0,,如果它表示正常意义的乘法\nDialogue: 0,0:30:09.44,0:30:12.78,Default,,0,0,0,,如果我统一地用加号来代替星号\nDialogue: 0,0:30:14.25,0:30:16.38,Default,,0,0,0,,这个表达式的含义就变了\nDialogue: 0,0:30:19.34,0:30:20.76,Default,,0,0,0,,这就是自由变量的意思\nDialogue: 0,0:30:22.68,0:30:24.81,Default,,0,0,0,,现在 你们已经学到了一些逻辑学术语\nDialogue: 0,0:30:25.64,0:30:27.58,Default,,0,0,0,,用它们可以解释名字的用法\nDialogue: 0,0:30:28.94,0:30:31.26,Default,,0,0,0,,我们要需要更进一步深入\nDialogue: 0,0:30:32.96,0:30:33.72,Default,,0,0,0,,再多了解一些\nDialogue: 0,0:30:35.13,0:30:36.22,Default,,0,0,0,,我想给你们讲讲\nDialogue: 0,0:30:36.81,0:30:39.76,Default,,0,0,0,,变量被定义的区域\nDialogue: 0,0:30:42.17,0:30:42.88,Default,,0,0,0,,你瞧\nDialogue: 0,0:30:43.37,0:30:45.69,Default,,0,0,0,,目前为止 我们已经相当不正式了\nDialogue: 0,0:30:46.33,0:30:50.16,Default,,0,0,0,,当然 你们中的一些 或者大部分人可能已经理解得很透彻了\nDialogue: 0,0:30:50.36,0:30:52.84,Default,,0,0,0,,在这里被声明的X\nDialogue: 0,0:30:53.64,0:30:55.18,Default,,0,0,0,,只被定义在这里\nDialogue: 0,0:30:58.28,0:31:00.91,Default,,0,0,0,,这个X 只被定义在这里\nDialogue: 0,0:31:01.61,0:31:04.33,Default,,0,0,0,,这个Y 只被定义在这里\nDialogue: 0,0:31:07.10,0:31:09.16,Default,,0,0,0,,我们给这个概念取了个名字 叫“作用域”\nDialogue: 0,0:31:11.61,0:31:13.58,Default,,0,0,0,,我给你们再讲个术语\nDialogue: 0,0:31:14.70,0:31:15.77,Default,,0,0,0,,这个就比较复杂\nDialogue: 0,0:31:15.96,0:31:17.64,Default,,0,0,0,,如果X是E中的一个约束变量\nDialogue: 0,0:31:18.16,0:31:20.24,Default,,0,0,0,,那么它是约束于一个LAMBDA表达式中\nDialogue: 0,0:31:20.89,0:31:24.91,Default,,0,0,0,,LAMBDA表达式是约束变量的唯一方式\nDialogue: 0,0:31:24.91,0:31:25.96,Default,,0,0,0,,你可能会担心\nDialogue: 0,0:31:26.22,0:31:29.05,Default,,0,0,0,,DEFINE是它的一个例外吗？\nDialogue: 0,0:31:29.64,0:31:32.92,Default,,0,0,0,,事实证明 通过巧妙安排 我们可以避免使用DEFINE\nDialogue: 0,0:31:32.92,0:31:33.96,Default,,0,0,0,,一会我们就能看到了\nDialogue: 0,0:31:34.24,0:31:35.72,Default,,0,0,0,,它一个非常神奇的东西\nDialogue: 0,0:31:36.54,0:31:38.40,Default,,0,0,0,,所以我们完全不需要DEFINE\nDialogue: 0,0:31:38.68,0:31:41.55,Default,,0,0,0,,实际上 唯一能创建名字的东西是LAMBDA\nDialogue: 0,0:31:42.64,0:31:43.40,Default,,0,0,0,,这就是它的职责\nDialogue: 0,0:31:44.30,0:31:46.23,Default,,0,0,0,,多么的令人惊奇\nDialogue: 0,0:31:46.23,0:31:47.87,Default,,0,0,0,,很多东西你只凭借LAMBDA就可以计算\nDialogue: 0,0:31:48.73,0:31:49.58,Default,,0,0,0,,但是 在任何情况下\nDialogue: 0,0:31:51.74,0:31:55.76,Default,,0,0,0,,一个LAMBDA表达式有一个地方来声明变量\nDialogue: 0,0:31:55.76,0:31:57.10,Default,,0,0,0,,我们把它称为形式参数表\nDialogue: 0,0:31:58.94,0:32:00.56,Default,,0,0,0,,或者叫 约束变量表\nDialogue: 0,0:32:01.26,0:32:04.51,Default,,0,0,0,,我们说LAMBDA表达式约束了--这是一个动词\nDialogue: 0,0:32:05.02,0:32:07.34,Default,,0,0,0,,--约束了在约束变量表里声明的变量\nDialogue: 0,0:32:08.59,0:32:12.48,Default,,0,0,0,,另外 表达式中定义变量的那些部分\nDialogue: 0,0:32:13.23,0:32:15.23,Default,,0,0,0,,是被一些声明所声明的\nDialogue: 0,0:32:15.56,0:32:19.26,Default,,0,0,0,,这些部分被叫做变量的作用域\nDialogue: 0,0:32:20.44,0:32:21.92,Default,,0,0,0,,所以 这些是作用域\nDialogue: 0,0:32:22.25,0:32:23.68,Default,,0,0,0,,这是Y的作用域\nDialogue: 0,0:32:27.16,0:32:28.54,Default,,0,0,0,,这是X的作用域--\nDialogue: 0,0:32:33.10,0:32:34.03,Default,,0,0,0,,以此类推\nDialogue: 0,0:32:41.32,0:32:42.08,Default,,0,0,0,,好\nDialogue: 0,0:32:43.93,0:32:45.63,Default,,0,0,0,,现在我们有了足够多的术语\nDialogue: 0,0:32:46.60,0:32:51.76,Default,,0,0,0,,可以开始理解如何建立一个新的计算模型了\nDialogue: 0,0:32:51.96,0:32:53.77,Default,,0,0,0,,因为 这里很重要的一点是\nDialogue: 0,0:32:54.94,0:32:57.00,Default,,0,0,0,,我们摧毁了代换模型\nDialogue: 0,0:32:57.18,0:32:58.38,Default,,0,0,0,,我们现在不得不需要一个模型\nDialogue: 0,0:32:58.62,0:33:02.32,Default,,0,0,0,,来体现表示名字被关联到某些地方\nDialogue: 0,0:33:03.93,0:33:05.34,Default,,0,0,0,,因为 如果我们要改变某个东西\nDialogue: 0,0:33:05.98,0:33:07.47,Default,,0,0,0,,我们就需要一个存它的地方\nDialogue: 0,0:33:09.56,0:33:10.35,Default,,0,0,0,,请想一想\nDialogue: 0,0:33:10.83,0:33:13.31,Default,,0,0,0,,如果一个名字只是关联于一个值\nDialogue: 0,0:33:14.04,0:33:16.36,Default,,0,0,0,,如果我试图改变这个名字的含义\nDialogue: 0,0:33:16.73,0:33:20.32,Default,,0,0,0,,这不怎么明确\nDialogue: 0,0:33:20.32,0:33:24.68,Default,,0,0,0,,因为没有名字可以关联的地方\nDialogue: 0,0:33:24.99,0:33:25.80,Default,,0,0,0,,该怎么解释呢……\nDialogue: 0,0:33:25.92,0:33:29.54,Default,,0,0,0,,也就是名字的所有实例之间没有共享任何东西\nDialogue: 0,0:33:29.87,0:33:31.68,Default,,0,0,0,,也就是说 对于一个名字\nDialogue: 0,0:33:31.68,0:33:32.97,Default,,0,0,0,,是用来让我们找到某些东西的\nDialogue: 0,0:33:34.33,0:33:36.36,Default,,0,0,0,,我们把名字给某个东西 然后你拿到了它\nDialogue: 0,0:33:36.73,0:33:39.06,Default,,0,0,0,,你能得到它 是因为我给了你一个它的引用\nDialogue: 0,0:33:39.06,0:33:40.44,Default,,0,0,0,,我把对它的引用给了你\nDialogue: 0,0:33:41.02,0:33:42.30,Default,,0,0,0,,我们会看到很多相关的例子\nDialogue: 0,0:33:43.61,0:33:45.21,Default,,0,0,0,,让我们继续学习“环境”\nDialogue: 0,0:33:46.19,0:33:48.76,Default,,0,0,0,,我需要用一下头顶上的投影仪\nDialogue: 0,0:33:49.31,0:33:49.98,Default,,0,0,0,,谢谢你\nDialogue: 0,0:33:52.19,0:33:53.02,Default,,0,0,0,,这里\nDialogue: 0,0:33:55.48,0:34:00.40,Default,,0,0,0,,是一堆环境结构\nDialogue: 0,0:34:01.53,0:34:05.76,Default,,0,0,0,,环境就是执行虚拟的代换的一种方法\nDialogue: 0,0:34:06.38,0:34:07.89,Default,,0,0,0,,它代表了一个地方\nDialogue: 0,0:34:07.89,0:34:11.39,Default,,0,0,0,,是存储你的未完成的代换的地方\nDialogue: 0,0:34:13.34,0:34:16.50,Default,,0,0,0,,它是一个积累各种东西的地方\nDialogue: 0,0:34:16.50,0:34:21.13,Default,,0,0,0,,在那里 变量的名字与值关联在一起\nDialogue: 0,0:34:21.79,0:34:22.56,Default,,0,0,0,,使得\nDialogue: 0,0:34:22.75,0:34:25.90,Default,,0,0,0,,当你问某个名字是什么意思的时候\nDialogue: 0,0:34:25.90,0:34:27.40,Default,,0,0,0,,你要在一个环境中寻找答案\nDialogue: 0,0:34:28.08,0:34:29.48,Default,,0,0,0,,所以环境是一个函数\nDialogue: 0,0:34:30.80,0:34:31.48,Default,,0,0,0,,或一张表\nDialogue: 0,0:34:32.22,0:34:33.24,Default,,0,0,0,,或类似的东西\nDialogue: 0,0:34:33.24,0:34:34.89,Default,,0,0,0,,但它是一种结构化的表\nDialogue: 0,0:34:35.76,0:34:37.39,Default,,0,0,0,,它是由框架构成\nDialogue: 0,0:34:41.13,0:34:44.46,Default,,0,0,0,,框架是环境的一部分\nDialogue: 0,0:34:44.89,0:34:46.01,Default,,0,0,0,,它们被链接在一起\nDialogue: 0,0:34:47.07,0:34:48.19,Default,,0,0,0,,以某种很好的方式\nDialogue: 0,0:34:49.00,0:34:52.09,Default,,0,0,0,,用一种叫做父链接之类的东西\nDialogue: 0,0:34:54.03,0:34:55.02,Default,,0,0,0,,这里\nDialogue: 0,0:34:55.64,0:34:57.62,Default,,0,0,0,,有一个环境结构\nDialogue: 0,0:34:57.62,0:35:04.22,Default,,0,0,0,,它由三个环境组成 分别是A B和C\nDialogue: 0,0:35:05.10,0:35:07.63,Default,,0,0,0,,D也是环境 但它和C是一样的\nDialogue: 0,0:35:08.88,0:35:10.17,Default,,0,0,0,,它们共享了同一个环境\nDialogue: 0,0:35:11.45,0:35:13.96,Default,,0,0,0,,那就是赋值的本质所在\nDialogue: 0,0:35:14.40,0:35:16.10,Default,,0,0,0,,如果我改变了一个变量\nDialogue: 0,0:35:16.10,0:35:19.80,Default,,0,0,0,,比如改变这个变量的值\nDialogue: 0,0:35:19.80,0:35:23.50,Default,,0,0,0,,那么它将在所有地方都可见\nDialogue: 0,0:35:23.50,0:35:24.84,Default,,0,0,0,,用x来举例\nDialogue: 0,0:35:24.84,0:35:28.19,Default,,0,0,0,,如果我将X改为4\nDialogue: 0,0:35:28.19,0:35:30.19,Default,,0,0,0,,在其他地方也是可见的\nDialogue: 0,0:35:30.19,0:35:32.19,Default,,0,0,0,,但是我们现在不去关心这个\nDialogue: 0,0:35:32.19,0:35:33.84,Default,,0,0,0,,过一会儿会详细讨论这个问题\nDialogue: 0,0:35:34.56,0:35:35.53,Default,,0,0,0,,这里有什么？\nDialogue: 0,0:35:36.76,0:35:38.84,Default,,0,0,0,,这些叫做框架 这是一个框架\nDialogue: 0,0:35:39.40,0:35:40.38,Default,,0,0,0,,这是一个框架\nDialogue: 0,0:35:40.76,0:35:41.84,Default,,0,0,0,,这也是一个框架\nDialogue: 0,0:35:43.18,0:35:45.20,Default,,0,0,0,,A是一个环境\nDialogue: 0,0:35:45.20,0:35:47.82,Default,,0,0,0,,它由框架II\nDialogue: 0,0:35:48.36,0:35:51.05,Default,,0,0,0,,和框架I组成\nDialogue: 0,0:35:52.52,0:35:54.60,Default,,0,0,0,,在这个环境中\nDialogue: 0,0:35:54.99,0:35:59.68,Default,,0,0,0,,在环境C中 在框架II中\nDialogue: 0,0:36:00.48,0:36:03.26,Default,,0,0,0,,X和Y是被约束的\nDialogue: 0,0:36:04.06,0:36:04.78,Default,,0,0,0,,它们具有值\nDialogue: 0,0:36:05.26,0:36:07.18,Default,,0,0,0,,对不起 是在框架I中\nDialogue: 0,0:36:07.18,0:36:08.28,Default,,0,0,0,,而在框架II中\nDialogue: 0,0:36:09.72,0:36:10.83,Default,,0,0,0,,Z被约束\nDialogue: 0,0:36:10.99,0:36:12.17,Default,,0,0,0,,X被约束\nDialogue: 0,0:36:12.44,0:36:13.69,Default,,0,0,0,,并且Y也是被约束的\nDialogue: 0,0:36:15.24,0:36:17.40,Default,,0,0,0,,但是我们看到的X的值\nDialogue: 0,0:36:17.42,0:36:19.04,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:36:20.01,0:36:21.74,Default,,0,0,0,,是这个X 它的值是7\nDialogue: 0,0:36:22.36,0:36:24.84,Default,,0,0,0,,而不是这个值为3的X\nDialogue: 0,0:36:24.84,0:36:27.61,Default,,0,0,0,,我们称之为 这个X遮蔽了这个X\nDialogue: 0,0:36:31.05,0:36:32.49,Default,,0,0,0,,从环境III\nDialogue: 0,0:36:33.44,0:36:34.45,Default,,0,0,0,,从框架III\nDialogue: 0,0:36:34.45,0:36:35.73,Default,,0,0,0,,从环境B\nDialogue: 0,0:36:35.73,0:36:37.18,Default,,0,0,0,,它引用了框架III\nDialogue: 0,0:36:37.45,0:36:42.12,Default,,0,0,0,,变量M和Y被约束 X也被约束\nDialogue: 0,0:36:44.84,0:36:46.97,Default,,0,0,0,,这个Y遮蔽了这个Y\nDialogue: 0,0:36:48.65,0:36:51.00,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:36:51.10,0:36:52.65,Default,,0,0,0,,Y的值是2\nDialogue: 0,0:36:53.45,0:36:55.28,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:36:55.28,0:36:58.64,Default,,0,0,0,,M的值是1 X的值是3\nDialogue: 0,0:37:02.22,0:37:03.15,Default,,0,0,0,,所以 我们有了一个\nDialogue: 0,0:37:03.15,0:37:05.52,Default,,0,0,0,,由框架构成的非常简单的环境结构\nDialogue: 0,0:37:06.38,0:37:09.80,Default,,0,0,0,,它们与过程的应用相一致\nDialogue: 0,0:37:10.94,0:37:12.17,Default,,0,0,0,,我们马上就会看到\nDialogue: 0,0:37:14.41,0:37:17.60,Default,,0,0,0,,现在要给你们看看我们构建的一些其他的很好的小结构\nDialogue: 0,0:37:20.75,0:37:21.71,Default,,0,0,0,,下一张幻灯片\nDialogue: 0,0:37:22.14,0:37:24.36,Default,,0,0,0,,我们可以看到一个对象\nDialogue: 0,0:37:24.84,0:37:26.54,Default,,0,0,0,,我描绘的是一个过程的图像\nDialogue: 0,0:37:27.93,0:37:28.94,Default,,0,0,0,,这是一个过程\nDialogue: 0,0:37:30.11,0:37:31.90,Default,,0,0,0,,过程由两个部分组成\nDialogue: 0,0:37:33.10,0:37:34.80,Default,,0,0,0,,这有点像CONS\nDialogue: 0,0:37:37.21,0:37:38.38,Default,,0,0,0,,不管怎样 它有两个部分\nDialogue: 0,0:37:40.84,0:37:44.72,Default,,0,0,0,,第一个部分指向一些代码\nDialogue: 0,0:37:45.69,0:37:46.94,Default,,0,0,0,,这些代码将会被执行\nDialogue: 0,0:37:47.42,0:37:50.00,Default,,0,0,0,,你可以把它视作一组指令\nDialogue: 0,0:37:50.68,0:37:52.83,Default,,0,0,0,,第二部分是环境\nDialogue: 0,0:37:53.88,0:37:55.50,Default,,0,0,0,,这就是过程的全部了\nDialogue: 0,0:37:57.16,0:37:58.40,Default,,0,0,0,,我们要用它\nDialogue: 0,0:37:58.71,0:38:05.16,Default,,0,0,0,,来捕获出现在过程中的自由变量的值\nDialogue: 0,0:38:06.17,0:38:08.09,Default,,0,0,0,,如果变量出现在过程中\nDialogue: 0,0:38:08.11,0:38:09.92,Default,,0,0,0,,它不是被约束的就是自由的\nDialogue: 0,0:38:11.10,0:38:11.96,Default,,0,0,0,,如果它是被约束的\nDialogue: 0,0:38:12.57,0:38:14.56,Default,,0,0,0,,则它的值将很容易被找到\nDialogue: 0,0:38:16.11,0:38:18.64,Default,,0,0,0,,它将存在于某个很容易找到的环境中\nDialogue: 0,0:38:18.91,0:38:19.87,Default,,0,0,0,,如果它是自由的\nDialogue: 0,0:38:20.86,0:38:23.02,Default,,0,0,0,,我们就必须在过程中放入一些东西\nDialogue: 0,0:38:23.02,0:38:24.81,Default,,0,0,0,,用来指导我们查询自由变量的值\nDialogue: 0,0:38:27.05,0:38:29.21,Default,,0,0,0,,相关理由目前还不清楚\nDialogue: 0,0:38:29.21,0:38:30.60,Default,,0,0,0,,但很快就要真相大白了\nDialogue: 0,0:38:32.32,0:38:34.97,Default,,0,0,0,,这里有一个对象 它是个复合对象\nDialogue: 0,0:38:35.34,0:38:41.64,Default,,0,0,0,,由一些代码和一个环境结构组成\nDialogue: 0,0:38:42.72,0:38:45.50,Default,,0,0,0,,现在我要告诉你们一些全新的规则\nDialogue: 0,0:38:46.41,0:38:47.47,Default,,0,0,0,,关于执行的规则\nDialogue: 0,0:38:50.54,0:38:52.20,Default,,0,0,0,,仅有的两条规则的第一条是--\nDialogue: 0,0:38:53.20,0:38:55.39,Default,,0,0,0,,这些规则与代换模型规则相对应\nDialogue: 0,0:38:57.26,0:38:59.32,Default,,0,0,0,,第一条规则是用来解决\nDialogue: 0,0:38:59.66,0:39:02.78,Default,,0,0,0,,如何把一个过程 应用到参数上的问题\nDialogue: 0,0:39:05.28,0:39:08.54,Default,,0,0,0,,程序对象被应用于一组参数\nDialogue: 0,0:39:08.96,0:39:10.43,Default,,0,0,0,,是通过构建一个新的框架来完成\nDialogue: 0,0:39:11.31,0:39:15.76,Default,,0,0,0,,那个框架将包含形式参数\nDialogue: 0,0:39:15.83,0:39:19.48,Default,,0,0,0,,到调用中使用的实际参数的映射\nDialogue: 0,0:39:21.42,0:39:22.20,Default,,0,0,0,,如你所知\nDialogue: 0,0:39:22.31,0:39:26.94,Default,,0,0,0,,当我们调用一个过程 如(LAMBDA (X) (* X Y))\nDialogue: 0,0:39:26.94,0:39:29.13,Default,,0,0,0,,然后我们以3为参数调用它\nDialogue: 0,0:39:30.19,0:39:32.75,Default,,0,0,0,,那么我们需要某个从X到3的映射\nDialogue: 0,0:39:34.19,0:39:37.39,Default,,0,0,0,,你可以把它想做是代换的一种\nDialogue: 0,0:39:38.27,0:39:40.30,Default,,0,0,0,,在旧的模型中 用3代换X\nDialogue: 0,0:39:42.00,0:39:44.80,Default,,0,0,0,,所以我要建立一个框架\nDialogue: 0,0:39:45.15,0:39:46.60,Default,,0,0,0,,在框架中包含X等于3的这个信息\nDialogue: 0,0:39:49.12,0:39:49.71,Default,,0,0,0,,现在\nDialogue: 0,0:39:50.33,0:39:53.31,Default,,0,0,0,,过程的体即将被执行\nDialogue: 0,0:39:54.16,0:39:56.44,Default,,0,0,0,,它将在一个环境中执行\nDialogue: 0,0:39:57.80,0:40:08.03,Default,,0,0,0,,这个环境是由我们创建的新框架邻接组合而成\nDialogue: 0,0:40:08.54,0:40:11.69,Default,,0,0,0,,它是我们所应用的过程的一部分\nDialogue: 0,0:40:13.15,0:40:15.77,Default,,0,0,0,,所以 举个例子\nDialogue: 0,0:40:19.20,0:40:24.12,Default,,0,0,0,,假设我有一些环境\nDialogue: 0,0:40:25.15,0:40:27.23,Default,,0,0,0,,画个方框代表它\nDialogue: 0,0:40:27.96,0:40:32.19,Default,,0,0,0,,以及一些过程--我画圆来代表它们 因为这比小三角形好画--\nDialogue: 0,0:40:33.04,0:40:36.36,Default,,0,0,0,,抱歉 是菱形\nDialogue: 0,0:40:37.66,0:40:40.78,Default,,0,0,0,,小块菱形的果冻之类的东西\nDialogue: 0,0:40:42.68,0:40:45.32,Default,,0,0,0,,这有一个使用这个环境的过程\nDialogue: 0,0:40:45.95,0:40:48.16,Default,,0,0,0,,这个过程有一些代码\nDialogue: 0,0:40:48.16,0:40:49.68,Default,,0,0,0,,是一个LAMBDA表达式\nDialogue: 0,0:40:50.12,0:40:51.69,Default,,0,0,0,,约束了X和Y\nDialogue: 0,0:40:53.15,0:40:56.43,Default,,0,0,0,,然后执行了表达式E\nDialogue: 0,0:40:57.93,0:40:58.99,Default,,0,0,0,,这个过程就是这样的\nDialogue: 0,0:40:59.56,0:41:00.57,Default,,0,0,0,,我们叫它P\nDialogue: 0,0:41:01.44,0:41:05.79,Default,,0,0,0,,我希望将这个过程应用于3和4\nDialogue: 0,0:41:06.38,0:41:08.36,Default,,0,0,0,,所以我在这写(P 3 4)\nDialogue: 0,0:41:09.76,0:41:12.17,Default,,0,0,0,,我要做的事情则是 创建一个新的框架\nDialogue: 0,0:41:13.15,0:41:14.12,Default,,0,0,0,,创建一个框架\nDialogue: 0,0:41:15.24,0:41:18.28,Default,,0,0,0,,框架中X等于3\nDialogue: 0,0:41:18.84,0:41:20.51,Default,,0,0,0,,而Y等于4\nDialogue: 0,0:41:21.69,0:41:23.48,Default,,0,0,0,,我要把这个框架\nDialogue: 0,0:41:24.27,0:41:25.37,Default,,0,0,0,,连接到这一个框架上\nDialogue: 0,0:41:27.63,0:41:28.99,Default,,0,0,0,,对于这个环境\nDialogue: 0,0:41:29.68,0:41:30.97,Default,,0,0,0,,我把它叫做B\nDialogue: 0,0:41:31.55,0:41:35.02,Default,,0,0,0,,我会在这个环境中求值E的体\nDialogue: 0,0:41:39.88,0:41:40.33,Default,,0,0,0,,现在\nDialogue: 0,0:41:41.95,0:41:45.04,Default,,0,0,0,,E可能包含了X和Y的引用以及一些别的东西\nDialogue: 0,0:41:46.84,0:41:49.95,Default,,0,0,0,,X和Y的值在这里\nDialogue: 0,0:41:50.70,0:41:52.52,Default,,0,0,0,,其他的变量的值在这里\nDialogue: 0,0:41:55.05,0:41:56.25,Default,,0,0,0,,怎样才能获取这个框架呢？\nDialogue: 0,0:41:57.26,0:41:59.26,Default,,0,0,0,,我们通过过程构建来完成\nDialogue: 0,0:41:59.61,0:42:00.60,Default,,0,0,0,,这就是另一条规则了\nDialogue: 0,0:42:02.03,0:42:04.40,Default,,0,0,0,,请看下一张幻灯片\nDialogue: 0,0:42:05.34,0:42:06.12,Default,,0,0,0,,规则二\nDialogue: 0,0:42:07.80,0:42:09.90,Default,,0,0,0,,当一个LAMBDA表达式被求值时\nDialogue: 0,0:42:09.90,0:42:11.76,Default,,0,0,0,,相对于某个特定的环境--\nDialogue: 0,0:42:14.19,0:42:14.40,Default,,0,0,0,,例如\nDialogue: 0,0:42:15.04,0:42:18.12,Default,,0,0,0,,获取一个过程的方式就是求值一个LAMBDA表达式\nDialogue: 0,0:42:18.19,0:42:19.36,Default,,0,0,0,,这里有一个LAMBDA表达式\nDialogue: 0,0:42:20.04,0:42:21.12,Default,,0,0,0,,通过对它求值\nDialogue: 0,0:42:21.90,0:42:23.96,Default,,0,0,0,,我获得了一个可以应用于3的过程\nDialogue: 0,0:42:25.08,0:42:26.65,Default,,0,0,0,,现在这个LAMBDA表达式\nDialogue: 0,0:42:26.65,0:42:30.38,Default,,0,0,0,,在一个Y已被定义的环境中执行\nDialogue: 0,0:42:31.84,0:42:35.84,Default,,0,0,0,,我希望这个过程的体中包括的Y是自由的\nDialogue: 0,0:42:36.39,0:42:38.36,Default,,0,0,0,,在这里面 Y是自由的\nDialogue: 0,0:42:38.72,0:42:40.38,Default,,0,0,0,,但是在整个的表达式中却是被约束的\nDialogue: 0,0:42:41.36,0:42:42.75,Default,,0,0,0,,而在这里是自由的\nDialogue: 0,0:42:43.32,0:42:46.24,Default,,0,0,0,,我想让这两个Y指称同一个Y\nDialogue: 0,0:42:47.44,0:42:55.13,Default,,0,0,0,,我在Y被创建的环境中求值这个过程的体\nDialogue: 0,0:42:55.32,0:42:58.40,Default,,0,0,0,,就像这个一样 因为那是通过应用完成的\nDialogue: 0,0:42:59.00,0:42:59.63,Default,,0,0,0,,现在\nDialogue: 0,0:43:00.24,0:43:02.60,Default,,0,0,0,,如果我还想查找Y的值\nDialogue: 0,0:43:03.10,0:43:04.09,Default,,0,0,0,,我就必须知道它在哪\nDialogue: 0,0:43:04.54,0:43:06.42,Default,,0,0,0,,因此 这个过程在被创建时\nDialogue: 0,0:43:06.42,0:43:10.06,Default,,0,0,0,,过程的创建 也就是对LAMBDA表达式求值的结果\nDialogue: 0,0:43:10.06,0:43:16.33,Default,,0,0,0,,最好是获取一个指针或记住Y被约束在哪个框架中\nDialogue: 0,0:43:17.92,0:43:19.76,Default,,0,0,0,,这就是这个规则的内容\nDialogue: 0,0:43:22.11,0:43:23.13,Default,,0,0,0,,那么 举个例子\nDialogue: 0,0:43:24.44,0:43:29.32,Default,,0,0,0,,如果我恰好求值了一个LAMBDA表达式\nDialogue: 0,0:43:30.89,0:43:33.32,Default,,0,0,0,,在E中的LAMBDA表达式\nDialogue: 0,0:43:34.04,0:43:40.46,Default,,0,0,0,,在E中求值(LAMBDA (X Y) G)\nDialogue: 0,0:43:41.08,0:43:42.36,Default,,0,0,0,,对其求值\nDialogue: 0,0:43:42.97,0:43:46.17,Default,,0,0,0,,这些事的意义就是我现在构建了一个过程对象\nDialogue: 0,0:43:47.10,0:43:48.28,Default,,0,0,0,,E是某个环境\nDialogue: 0,0:43:48.84,0:43:50.94,Default,,0,0,0,,有个指针指向E\nDialogue: 0,0:43:51.79,0:43:56.68,Default,,0,0,0,,我构建了一个过程对象指向了这个环境\nDialogue: 0,0:43:58.56,0:44:00.11,Default,,0,0,0,,它的代码\nDialogue: 0,0:44:00.54,0:44:03.24,Default,,0,0,0,,是一个LAMBDA表达式 或者是某种中间代码\nDialogue: 0,0:44:06.24,0:44:07.56,Default,,0,0,0,,而这就是一个过程\nDialogue: 0,0:44:12.38,0:44:14.70,Default,,0,0,0,,它为我生成了这个和这个\nDialogue: 0,0:44:14.94,0:44:16.37,Default,,0,0,0,,这个对象\nDialogue: 0,0:44:16.37,0:44:18.12,Default,,0,0,0,,这个环境指针\nDialogue: 0,0:44:18.37,0:44:22.52,Default,,0,0,0,,获取了求值LAMBDA表达式时的环境\nDialogue: 0,0:44:22.62,0:44:24.59,Default,,0,0,0,,定义所使用的环境\nDialogue: 0,0:44:25.58,0:44:27.40,Default,,0,0,0,,创建一个过程时的定义所用的环境\nDialogue: 0,0:44:30.32,0:44:31.47,Default,,0,0,0,,从而创建了过程\nDialogue: 0,0:44:32.89,0:44:36.30,Default,,0,0,0,,所以 它将环境从定义过程的地方取出\nDialogue: 0,0:44:37.42,0:44:38.92,Default,,0,0,0,,将它保存在过程自己内部\nDialogue: 0,0:44:39.60,0:44:40.97,Default,,0,0,0,,之后当过程被调用时\nDialogue: 0,0:44:41.32,0:44:43.47,Default,,0,0,0,,它在被定义时的环境\nDialogue: 0,0:44:43.98,0:44:45.07,Default,,0,0,0,,将由新的框架扩充\nDialogue: 0,0:44:48.72,0:44:52.33,Default,,0,0,0,,这给了我们一个放置有值的变量的地方\nDialogue: 0,0:44:53.04,0:44:53.96,Default,,0,0,0,,举个例子\nDialogue: 0,0:44:53.96,0:44:56.81,Default,,0,0,0,,如果有很多东西指向那这个环境\nDialogue: 0,0:44:57.74,0:45:00.33,Default,,0,0,0,,它们就会共享这个环境\nDialogue: 0,0:45:01.20,0:45:02.52,Default,,0,0,0,,我们很快将会见到\nDialogue: 0,0:45:04.01,0:45:05.34,Default,,0,0,0,,现在你们有了一个新模型\nDialogue: 0,0:45:06.38,0:45:09.92,Default,,0,0,0,,我们用它来理解程序的执行\nDialogue: 0,0:45:11.36,0:45:12.78,Default,,0,0,0,,我觉得现在我应该解答一些问题了\nDialogue: 0,0:45:13.10,0:45:14.96,Default,,0,0,0,,之后我们再继续\nDialogue: 0,0:45:18.19,0:45:19.52,Default,,0,0,0,,学生：这么说是对的吗？\nDialogue: 0,0:45:19.52,0:45:23.96,Default,,0,0,0,,环境就是一些被连接在一起的框架\nDialogue: 0,0:45:23.96,0:45:25.10,Default,,0,0,0,,教授：对\nDialogue: 0,0:45:25.48,0:45:26.64,Default,,0,0,0,,学生：通过它能够访问所有的框架？\nDialogue: 0,0:45:27.71,0:45:31.45,Default,,0,0,0,,教授：是的 环境是一系列被连接在一起的框架\nDialogue: 0,0:45:32.43,0:45:35.47,Default,,0,0,0,,我对它的理解是 它是指向第一个框架的指针\nDialogue: 0,0:45:36.88,0:45:38.72,Default,,0,0,0,,因为一旦你获得了它 你就能拿到所有的框架\nDialogue: 0,0:45:43.96,0:45:44.65,Default,,0,0,0,,还有谁有问题吗？\nDialogue: 0,0:45:45.20,0:45:49.36,Default,,0,0,0,,学生：有可能在两个不同的环境中定义或求值一个过程\nDialogue: 0,0:45:49.36,0:45:53.20,Default,,0,0,0,,使得它有不同的行为 并且有指向两个环境的指针--\nDialogue: 0,0:45:53.20,0:45:55.77,Default,,0,0,0,,教授：噢 是的 同一个过程不会有两个不同环境\nDialogue: 0,0:45:56.90,0:45:59.02,Default,,0,0,0,,同样的代码\nDialogue: 0,0:45:59.02,0:46:00.82,Default,,0,0,0,,比如同样的LAMBDA表达式\nDialogue: 0,0:46:00.82,0:46:03.72,Default,,0,0,0,,再不同的环境下求值可能产生不同的过程\nDialogue: 0,0:46:06.03,0:46:07.18,Default,,0,0,0,,每个过程--\nDialogue: 0,0:46:07.18,0:46:09.95,Default,,0,0,0,,学生：它们的定义有同样的名字 它们的运算--\nDialogue: 0,0:46:09.95,0:46:11.92,Default,,0,0,0,,教授：它们定义是写起来是一样的 使用同样的字母\nDialogue: 0,0:46:12.56,0:46:14.62,Default,,0,0,0,,我能求值那一组字母\nDialogue: 0,0:46:14.93,0:46:18.14,Default,,0,0,0,,或定义的表结构之类的东西\nDialogue: 0,0:46:18.22,0:46:20.41,Default,,0,0,0,,那只是文本表示\nDialogue: 0,0:46:20.91,0:46:24.86,Default,,0,0,0,,我可以在两个不同环境种对它求值 产生两个不同的过程\nDialogue: 0,0:46:25.55,0:46:26.84,Default,,0,0,0,,每一个过程\nDialogue: 0,0:46:27.56,0:46:32.19,Default,,0,0,0,,有它们自己的一组局部变量\nDialogue: 0,0:46:32.34,0:46:33.45,Default,,0,0,0,,我们很快就会看到\nDialogue: 0,0:46:36.70,0:46:37.36,Default,,0,0,0,,还有问题吗？\nDialogue: 0,0:46:42.60,0:46:44.03,Default,,0,0,0,,好 谢谢大家 我们休息一会\nDialogue: 0,0:46:47.98,0:46:57.61,Default,,0,0,0,,[音乐]\nDialogue: 0,0:46:57.61,0:47:02.03,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:47:05.98,0:47:09.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:47:09.69,0:47:13.44,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:47:13.47,0:47:18.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}赋值、状态和副作用\nDialogue: 0,0:47:22.67,0:47:25.69,Default,,0,0,0,,现在 我已经对你们做了一件非常糟糕的事儿\nDialogue: 0,0:47:26.56,0:47:30.54,Default,,0,0,0,,我引入了一个非常复杂的东西\nDialogue: 0,0:47:32.76,0:47:33.42,Default,,0,0,0,,赋值\nDialogue: 0,0:47:34.51,0:47:38.08,Default,,0,0,0,,它摧毁了我们程序中大部分的 有趣的数学特性\nDialogue: 0,0:47:41.07,0:47:42.46,Default,,0,0,0,,我为什么要做这件事呢\nDialogue: 0,0:47:43.18,0:47:45.02,Default,,0,0,0,,这样做可能有什么好处吗？\nDialogue: 0,0:47:46.51,0:47:48.86,Default,,0,0,0,,很明显 这不是一个什么好东西\nDialogue: 0,0:47:49.60,0:47:51.23,Default,,0,0,0,,因此我最好有一个好的理由\nDialogue: 0,0:47:52.83,0:47:54.80,Default,,0,0,0,,让我们来小小地玩一下\nDialogue: 0,0:47:54.80,0:47:58.35,Default,,0,0,0,,首先 我们写些非常有趣的带赋值的程序\nDialogue: 0,0:47:58.81,0:48:00.88,Default,,0,0,0,,来理解它们的特殊之处\nDialogue: 0,0:48:01.42,0:48:02.83,Default,,0,0,0,,这些特殊之处使赋值变得有价值\nDialogue: 0,0:48:04.96,0:48:06.70,Default,,0,0,0,,我们从一个非常简单的程序开始\nDialogue: 0,0:48:07.69,0:48:09.28,Default,,0,0,0,,我把这个程序叫做MAKE-COUNTER\nDialogue: 0,0:48:10.48,0:48:18.19,Default,,0,0,0,,我要把它定义为\nDialogue: 0,0:48:24.17,0:48:28.12,Default,,0,0,0,,接受一个参数N的过程\nDialogue: 0,0:48:29.23,0:48:32.94,Default,,0,0,0,,并且它的返回值是一个没有参数的过程--\nDialogue: 0,0:48:34.36,0:48:36.03,Default,,0,0,0,,一个生成过程的过程--\nDialogue: 0,0:48:36.84,0:48:44.35,Default,,0,0,0,,这个过程把N的值设为N+1\nDialogue: 0,0:48:47.88,0:48:49.77,Default,,0,0,0,,并且返回N的值\nDialogue: 0,0:48:55.37,0:48:57.54,Default,,0,0,0,,现在 我们要研究它的行为\nDialogue: 0,0:48:57.54,0:48:59.02,Default,,0,0,0,,它很有趣\nDialogue: 0,0:48:59.82,0:49:01.45,Default,,0,0,0,,为了研究它的行为\nDialogue: 0,0:49:01.45,0:49:03.08,Default,,0,0,0,,我需要建立一个环境模型\nDialogue: 0,0:49:04.11,0:49:05.98,Default,,0,0,0,,因为我们不能通过其他的方式来理解它\nDialogue: 0,0:49:08.65,0:49:09.63,Default,,0,0,0,,所以我们开始吧\nDialogue: 0,0:49:10.00,0:49:12.86,Default,,0,0,0,,我们从这里开始\nDialogue: 0,0:49:13.24,0:49:15.90,Default,,0,0,0,,假设机器天生就有一个全局环境\nDialogue: 0,0:49:16.13,0:49:17.12,Default,,0,0,0,,我们把它叫做Global\nDialogue: 0,0:49:20.03,0:49:24.25,Default,,0,0,0,,它内部有一堆初始化的东西\nDialogue: 0,0:49:24.44,0:49:25.60,Default,,0,0,0,,我们都知道它里面有什么\nDialogue: 0,0:49:25.72,0:49:30.88,Default,,0,0,0,,这里面有+和*\nDialogue: 0,0:49:32.24,0:49:37.26,Default,,0,0,0,,/ -和CAR\nDialogue: 0,0:49:38.70,0:49:39.74,Default,,0,0,0,,以此类推\nDialogue: 0,0:49:41.45,0:49:42.48,Default,,0,0,0,,有很多东西\nDialogue: 0,0:49:42.88,0:49:43.98,Default,,0,0,0,,我不知道它们是什么\nDialogue: 0,0:49:44.42,0:49:45.55,Default,,0,0,0,,一些乱七八糟的符号\nDialogue: 0,0:49:46.08,0:49:48.88,Default,,0,0,0,,机器一开始就有这些特性\nDialogue: 0,0:49:51.21,0:49:53.23,Default,,0,0,0,,通过在这做定义\nDialogue: 0,0:49:54.68,0:49:55.76,Default,,0,0,0,,我要做的是--\nDialogue: 0,0:49:56.32,0:49:57.31,Default,,0,0,0,,我在干什么呢？\nDialogue: 0,0:49:57.31,0:49:59.58,Default,,0,0,0,,我要把它关联到全局环境上\nDialogue: 0,0:49:59.72,0:50:01.29,Default,,0,0,0,,这是我的环境指针\nDialogue: 0,0:50:03.72,0:50:06.70,Default,,0,0,0,,为了达到那个目的 我要求值这个LAMBDA表达式\nDialogue: 0,0:50:08.35,0:50:10.01,Default,,0,0,0,,这意味着我创建了一个过程对象\nDialogue: 0,0:50:11.50,0:50:13.26,Default,,0,0,0,,所以 我要在这创建一个过程对象\nDialogue: 0,0:50:17.36,0:50:18.68,Default,,0,0,0,,这个过程对象\nDialogue: 0,0:50:18.72,0:50:20.49,Default,,0,0,0,,由于在它被定义的地方\nDialogue: 0,0:50:21.16,0:50:22.35,Default,,0,0,0,,有一个全局的环境\nDialogue: 0,0:50:24.06,0:50:25.79,Default,,0,0,0,,这个过程对象包括了\nDialogue: 0,0:50:28.16,0:50:31.47,Default,,0,0,0,,以N为参数的过程的代码\nDialogue: 0,0:50:31.96,0:50:35.34,Default,,0,0,0,,它返回一个不接受参数的过程\nDialogue: 0,0:50:38.24,0:50:43.28,Default,,0,0,0,,DEFINE是一种改变环境的方法\nDialogue: 0,0:50:44.32,0:50:46.73,Default,,0,0,0,,所以我把MAKE-COUNTER加入全局环境中\nDialogue: 0,0:50:52.28,0:50:55.05,Default,,0,0,0,,这是对于特殊的东西定义的一个特殊的规则\nDialogue: 0,0:50:55.82,0:50:56.94,Default,,0,0,0,,但它其实是\nDialogue: 0,0:50:58.94,0:51:01.96,Default,,0,0,0,,它给了我们一个指针 指向那个过程\nDialogue: 0,0:51:03.82,0:51:06.32,Default,,0,0,0,,所以现在全局环境中也有了MAKE-COUNTER\nDialogue: 0,0:51:09.28,0:51:11.21,Default,,0,0,0,,现在 我们要进行一些操作\nDialogue: 0,0:51:11.87,0:51:13.50,Default,,0,0,0,,我要用它来创建一些计数器\nDialogue: 0,0:51:14.99,0:51:16.20,Default,,0,0,0,,我们来看看计数器是什么\nDialogue: 0,0:51:17.12,0:51:18.51,Default,,0,0,0,,所以我们定义\nDialogue: 0,0:51:23.32,0:51:26.65,Default,,0,0,0,,C1为一个从0开始的计数器\nDialogue: 0,0:51:35.72,0:51:38.38,Default,,0,0,0,,根据模型 我们知道如何做这个了\nDialogue: 0,0:51:39.63,0:51:44.33,Default,,0,0,0,,我需要在全局环境中求值这个表达式\nDialogue: 0,0:51:45.40,0:51:46.27,Default,,0,0,0,,(MAKE-COUNTER 0)\nDialogue: 0,0:51:47.80,0:51:51.10,Default,,0,0,0,,我查找MAKE-COUNTER 发现它是一个过程\nDialogue: 0,0:51:53.61,0:51:55.29,Default,,0,0,0,,我将要应用这个过程\nDialogue: 0,0:51:56.22,0:51:57.74,Default,,0,0,0,,应用这个过程的方式\nDialogue: 0,0:51:58.43,0:51:59.96,Default,,0,0,0,,就是构建一个框架\nDialogue: 0,0:52:01.80,0:52:03.79,Default,,0,0,0,,所以我构建了一个框架\nDialogue: 0,0:52:06.59,0:52:10.44,Default,,0,0,0,,它内部有一个N的值\nDialogue: 0,0:52:11.77,0:52:12.64,Default,,0,0,0,,这个值是0\nDialogue: 0,0:52:14.00,0:52:15.34,Default,,0,0,0,,它的父环境\nDialogue: 0,0:52:15.87,0:52:19.32,Default,,0,0,0,,就是定义MAKE-COUNTER时的环境\nDialogue: 0,0:52:23.93,0:52:28.36,Default,,0,0,0,,所以我已经通过将MAKE-COUNTER应用于0上 而创建了一个环境\nDialogue: 0,0:52:31.45,0:52:34.40,Default,,0,0,0,,现在 我需要求值MAKE-COUNTER的体\nDialogue: 0,0:52:34.41,0:52:37.72,Default,,0,0,0,,就是那个环境中的LAMBDA表达式\nDialogue: 0,0:52:40.64,0:52:42.30,Default,,0,0,0,,求值这个体\nDialogue: 0,0:52:42.76,0:52:44.59,Default,,0,0,0,,它是一个LAMBDA表达式\nDialogue: 0,0:52:46.28,0:52:48.86,Default,,0,0,0,,对LAMBDA表达式求值 意味着创建一个过程对象\nDialogue: 0,0:52:49.56,0:52:51.00,Default,,0,0,0,,所以我将创建一个过程对象\nDialogue: 0,0:52:56.76,0:52:58.29,Default,,0,0,0,,这个过程对象\nDialogue: 0,0:52:58.29,0:53:00.46,Default,,0,0,0,,拥有一个环境\nDialogue: 0,0:53:04.20,0:53:05.88,Default,,0,0,0,,在这个环境中N被定义为0\nDialogue: 0,0:53:07.68,0:53:08.80,Default,,0,0,0,,它有一些代码\nDialogue: 0,0:53:08.83,0:53:11.37,Default,,0,0,0,,这个过程不需要参数\nDialogue: 0,0:53:11.40,0:53:15.28,Default,,0,0,0,,该过程进行一些处理 然后进行赋值\nDialogue: 0,0:53:15.28,0:53:16.73,Default,,0,0,0,,并返回N\nDialogue: 0,0:53:17.88,0:53:18.81,Default,,0,0,0,,这个东西\nDialogue: 0,0:53:19.42,0:53:21.23,Default,,0,0,0,,将成为一个对象\nDialogue: 0,0:53:21.92,0:53:24.67,Default,,0,0,0,,在全局环境中 它的名字是C1\nDialogue: 0,0:53:26.12,0:53:28.33,Default,,0,0,0,,所以我们在这建立一个名字 C1\nDialogue: 0,0:53:28.64,0:53:32.14,Default,,0,0,0,,并且说C1等于这个过程\nDialogue: 0,0:53:35.48,0:53:37.36,Default,,0,0,0,,现在 再来创建另一个计数器\nDialogue: 0,0:53:43.04,0:53:45.13,Default,,0,0,0,,通过MAKE-COUNTER创建c2\nDialogue: 0,0:53:50.94,0:53:52.19,Default,,0,0,0,,让它从10开始\nDialogue: 0,0:53:54.25,0:53:55.90,Default,,0,0,0,,然后我执行同样的步骤\nDialogue: 0,0:53:56.64,0:54:00.40,Default,,0,0,0,,我应用这个MAKE-COUNTER过程\nDialogue: 0,0:54:00.99,0:54:04.52,Default,,0,0,0,,建立另一个框架 其中N等于10\nDialogue: 0,0:54:05.63,0:54:09.18,Default,,0,0,0,,全局环境作为它的父环境\nDialogue: 0,0:54:10.04,0:54:11.80,Default,,0,0,0,,然后我构建一个过程\nDialogue: 0,0:54:13.04,0:54:17.63,Default,,0,0,0,,以这个框架作为它定义的环境\nDialogue: 0,0:54:18.27,0:54:21.66,Default,,0,0,0,,它的代码是\nDialogue: 0,0:54:21.80,0:54:24.38,Default,,0,0,0,,完成一些操作的无参过程\nDialogue: 0,0:54:25.54,0:54:28.60,Default,,0,0,0,,然后进行赋值 等等\nDialogue: 0,0:54:28.60,0:54:31.22,Default,,0,0,0,,然后返回N\nDialogue: 0,0:54:31.45,0:54:34.83,Default,,0,0,0,,这就是C2\nDialogue: 0,0:54:36.88,0:54:39.32,Default,,0,0,0,,好 你们应该发现 某些东西开始变得有趣了\nDialogue: 0,0:54:40.17,0:54:41.92,Default,,0,0,0,,这里有两个N\nDialogue: 0,0:54:42.92,0:54:44.19,Default,,0,0,0,,它们不是同一个N\nDialogue: 0,0:54:46.14,0:54:48.16,Default,,0,0,0,,我每次调用MAKE-COUNTER的时候\nDialogue: 0,0:54:48.64,0:54:50.25,Default,,0,0,0,,我就创建了另一个N的实例\nDialogue: 0,0:54:52.62,0:54:54.40,Default,,0,0,0,,它们彼此独立 没有关联\nDialogue: 0,0:54:57.79,0:55:00.28,Default,,0,0,0,,现在 我们来使用一下这些计数器\nDialogue: 0,0:55:05.92,0:55:15.00,Default,,0,0,0,,如果此时 我调用C1 会发生什么？\nDialogue: 0,0:55:15.84,0:55:17.34,Default,,0,0,0,,我会在这里查找\nDialogue: 0,0:55:17.56,0:55:19.98,Default,,0,0,0,,发现C1是一个过程\nDialogue: 0,0:55:20.64,0:55:22.78,Default,,0,0,0,,我要不带参数地调用这个过程\nDialogue: 0,0:55:23.16,0:55:24.96,Default,,0,0,0,,因为它不需要参数\nDialogue: 0,0:55:24.96,0:55:25.63,Default,,0,0,0,,对吧？\nDialogue: 0,0:55:26.97,0:55:27.84,Default,,0,0,0,,它的体是什么呢？\nDialogue: 0,0:55:27.96,0:55:30.02,Default,,0,0,0,,我得来这里解释 因为我没有给誊过来\nDialogue: 0,0:55:30.02,0:55:32.65,Default,,0,0,0,,这个过程体是将N赋值为N+1\nDialogue: 0,0:55:33.80,0:55:34.89,Default,,0,0,0,,并且返回N\nDialogue: 0,0:55:37.12,0:55:38.12,Default,,0,0,0,,就是把N增大1\nDialogue: 0,0:55:38.97,0:55:41.60,Default,,0,0,0,,它的N指的是这个\nDialogue: 0,0:55:43.08,0:55:44.60,Default,,0,0,0,,所以我把这个n增大1\nDialogue: 0,0:55:45.80,0:55:47.00,Default,,0,0,0,,它变成了1\nDialogue: 0,0:55:48.64,0:55:50.24,Default,,0,0,0,,然后返回了1\nDialogue: 0,0:55:53.13,0:55:56.49,Default,,0,0,0,,之后我调用C2\nDialogue: 0,0:55:58.38,0:55:59.20,Default,,0,0,0,,我会做什么？\nDialogue: 0,0:55:59.23,0:56:03.33,Default,,0,0,0,,C2是相同的过程\nDialogue: 0,0:56:03.33,0:56:04.48,Default,,0,0,0,,但这个N\nDialogue: 0,0:56:05.33,0:56:06.57,Default,,0,0,0,,它变成了11\nDialogue: 0,0:56:10.97,0:56:14.59,Default,,0,0,0,,所以返回值是11\nDialogue: 0,0:56:15.92,0:56:18.32,Default,,0,0,0,,然后我们再来调用一下C1\nDialogue: 0,0:56:20.91,0:56:22.56,Default,,0,0,0,,C1是这个\nDialogue: 0,0:56:23.28,0:56:24.16,Default,,0,0,0,,它是2\nDialogue: 0,0:56:27.24,0:56:28.30,Default,,0,0,0,,所以结果是2\nDialogue: 0,0:56:29.66,0:56:30.75,Default,,0,0,0,,然后调用C2\nDialogue: 0,0:56:33.37,0:56:35.31,Default,,0,0,0,,然后C2通过同样的方法 返回了12\nDialogue: 0,0:56:35.74,0:56:37.55,Default,,0,0,0,,它在这里进行查找\nDialogue: 0,0:56:37.55,0:56:39.28,Default,,0,0,0,,发现了N 并把它加1\nDialogue: 0,0:56:41.64,0:56:43.68,Default,,0,0,0,,我拥有的是可计算的对象\nDialogue: 0,0:56:45.21,0:56:46.86,Default,,0,0,0,,它们是两个计数器\nDialogue: 0,0:56:48.96,0:56:51.02,Default,,0,0,0,,每一个都有各自独立的局部状态\nDialogue: 0,0:56:55.48,0:56:56.62,Default,,0,0,0,,我们再进一步\nDialogue: 0,0:56:56.64,0:56:58.52,Default,,0,0,0,,这是个奇怪的东西\nDialogue: 0,0:57:01.12,0:57:02.22,Default,,0,0,0,,什么是对象？\nDialogue: 0,0:57:04.11,0:57:06.12,Default,,0,0,0,,这个概念并不明确\nDialogue: 0,0:57:07.55,0:57:09.45,Default,,0,0,0,,我们倾向于以对象的角度思考\nDialogue: 0,0:57:11.24,0:57:13.32,Default,,0,0,0,,因为这样思考比较经济\nDialogue: 0,0:57:14.62,0:57:17.28,Default,,0,0,0,,这是一种智力上的经济\nDialogue: 0,0:57:18.57,0:57:19.61,Default,,0,0,0,,我是一个对象\nDialogue: 0,0:57:20.99,0:57:22.30,Default,,0,0,0,,你也是一个对象\nDialogue: 0,0:57:23.55,0:57:25.29,Default,,0,0,0,,但我们不是同一个对象\nDialogue: 0,0:57:27.52,0:57:29.64,Default,,0,0,0,,我可以把世界分为两部分\nDialogue: 0,0:57:29.92,0:57:31.85,Default,,0,0,0,,我和你\nDialogue: 0,0:57:31.92,0:57:33.31,Default,,0,0,0,,以及其它的东西\nDialogue: 0,0:57:34.70,0:57:35.26,Default,,0,0,0,,使得\nDialogue: 0,0:57:35.44,0:57:39.50,Default,,0,0,0,,大多数对于我的讨论\nDialogue: 0,0:57:39.68,0:57:40.89,Default,,0,0,0,,不会影响到你\nDialogue: 0,0:57:41.39,0:57:44.67,Default,,0,0,0,,大多数对于你的讨论不会牵涉到我\nDialogue: 0,0:57:45.66,0:57:46.94,Default,,0,0,0,,我有血压\nDialogue: 0,0:57:47.50,0:57:48.38,Default,,0,0,0,,体温\nDialogue: 0,0:57:49.36,0:57:51.48,Default,,0,0,0,,呼吸频率\nDialogue: 0,0:57:53.34,0:57:54.99,Default,,0,0,0,,血液中有确定的血糖值\nDialogue: 0,0:57:56.11,0:57:59.34,Default,,0,0,0,,数不清的 数以千计的状态变量--上百万实际上\nDialogue: 0,0:57:59.37,0:58:00.65,Default,,0,0,0,,我不知道具体有多少\nDialogue: 0,0:58:00.93,0:58:03.48,Default,,0,0,0,,以物理学观点 我拥有大量的状态变量\nDialogue: 0,0:58:04.91,0:58:07.12,Default,,0,0,0,,如果将我视为一个粒子的话\nDialogue: 0,0:58:09.15,0:58:10.64,Default,,0,0,0,,你也有许许多多这样的变量\nDialogue: 0,0:58:12.68,0:58:14.94,Default,,0,0,0,,我们的大多数变量之间是好无联系的\nDialogue: 0,0:58:17.31,0:58:19.50,Default,,0,0,0,,所以可以计算我的属性\nDialogue: 0,0:58:20.56,0:58:22.83,Default,,0,0,0,,而不用太担心你的属性\nDialogue: 0,0:58:23.82,0:58:25.77,Default,,0,0,0,,如果把我们两个放在一起计算\nDialogue: 0,0:58:25.96,0:58:27.82,Default,,0,0,0,,那么我们需要考虑的状态的数量\nDialogue: 0,0:58:27.82,0:58:30.01,Default,,0,0,0,,就是你与我的状态的数量的乘积\nDialogue: 0,0:58:30.52,0:58:32.11,Default,,0,0,0,,按对象解耦的话 则只需考虑你我状态之和\nDialogue: 0,0:58:32.65,0:58:35.34,Default,,0,0,0,,然而 实际上有一种力量把我们耦合起来\nDialogue: 0,0:58:36.00,0:58:37.95,Default,,0,0,0,,我对你讲话 你的状态就变了\nDialogue: 0,0:58:38.44,0:58:40.09,Default,,0,0,0,,我看着你 我的状态就变了\nDialogue: 0,0:58:41.72,0:58:44.08,Default,,0,0,0,,因此 我的变量中的一小部分\nDialogue: 0,0:58:44.33,0:58:46.07,Default,,0,0,0,,与你的一些变量是耦合的\nDialogue: 0,0:58:46.07,0:58:47.80,Default,,0,0,0,,如果你突然大喊大叫\nDialogue: 0,0:58:47.80,0:58:48.88,Default,,0,0,0,,我的血压就会升高\nDialogue: 0,0:58:54.30,0:58:56.86,Default,,0,0,0,,然而 将世界看作是由独立的变量\nDialogue: 0,0:58:57.17,0:59:01.16,Default,,0,0,0,,和独立的粒子组成的是不恰当的\nDialogue: 0,0:59:02.12,0:59:04.46,Default,,0,0,0,,在像量子力学这样的东西里存在大量的BUG\nDialogue: 0,0:59:05.23,0:59:08.70,Default,,0,0,0,,或者当我们思考像量子力学之类的东西的时候 会在我们的脑海中产生bug\nDialogue: 0,0:59:08.89,0:59:10.97,Default,,0,0,0,,这是由于 当我们思考事物时\nDialogue: 0,0:59:10.97,0:59:12.96,Default,,0,0,0,,会去将事物分解为相互独立的部分来看待\nDialogue: 0,0:59:13.58,0:59:17.32,Default,,0,0,0,,而事实上事物的耦合程度 远远大于在表面所看到的\nDialogue: 0,0:59:18.01,0:59:19.44,Default,,0,0,0,,即便这样 我们仍像那样思考\nDialogue: 0,0:59:19.61,0:59:21.69,Default,,0,0,0,,是因为我们希望高效并且有效的进行计算\nDialogue: 0,0:59:22.19,0:59:23.82,Default,,0,0,0,,我们被培养成以那种方式进行思考\nDialogue: 0,0:59:29.76,0:59:30.51,Default,,0,0,0,,大家看\nDialogue: 0,0:59:31.50,0:59:33.44,Default,,0,0,0,,我们如何才能知道我们是否有对象？\nDialogue: 0,0:59:35.12,0:59:37.34,Default,,0,0,0,,如果我们有对象 应该如何分辨呢？\nDialogue: 0,0:59:37.64,0:59:41.45,Default,,0,0,0,,通过思考一些光学现象\nDialogue: 0,0:59:42.46,0:59:43.13,Default,,0,0,0,,就能解答这个问题\nDialogue: 0,0:59:45.04,0:59:47.69,Default,,0,0,0,,这几截粉笔不完全相同\nDialogue: 0,0:59:47.76,0:59:50.20,Default,,0,0,0,,但假设 只通过观察是无法区分它们的\nDialogue: 0,0:59:52.04,0:59:53.32,Default,,0,0,0,,有一种可能\nDialogue: 0,0:59:53.32,0:59:55.16,Default,,0,0,0,,是这一切都是我们与镜子的游戏\nDialogue: 0,0:59:56.07,0:59:57.60,Default,,0,0,0,,它们真的是同一截粉笔\nDialogue: 0,0:59:59.36,1:00:00.48,Default,,0,0,0,,但你看到了两个\nDialogue: 0,1:00:01.61,1:00:03.87,Default,,0,0,0,,你怎么知道你看到的是一个还是两个呢？\nDialogue: 0,1:00:05.04,1:00:06.70,Default,,0,0,0,,我只知道有一种方法可以确定\nDialogue: 0,1:00:07.37,1:00:08.94,Default,,0,0,0,,抓起其中一个并且改变它\nDialogue: 0,1:00:09.45,1:00:10.67,Default,,0,0,0,,然后看看另一个有没有跟着变化\nDialogue: 0,1:00:14.01,1:00:14.67,Default,,0,0,0,,而另一个没有变化\nDialogue: 0,1:00:15.50,1:00:16.14,Default,,0,0,0,,所以它们是两截不同粉笔\nDialogue: 0,1:00:19.50,1:00:20.16,Default,,0,0,0,,另一方面\nDialogue: 0,1:00:20.17,1:00:22.20,Default,,0,0,0,,事物还有一些其它的类似的纠结属性\nDialogue: 0,1:00:22.57,1:00:24.01,Default,,0,0,0,,例如 我们怎么才知道某个东西是否改变了呢？\nDialogue: 0,1:00:25.00,1:00:27.93,Default,,0,0,0,,我们需要在它改变之前和之后进行观察\nDialogue: 0,1:00:28.65,1:00:30.02,Default,,0,0,0,,改变就是赋值\nDialogue: 0,1:00:30.02,1:00:31.45,Default,,0,0,0,,它是时间中的一个时刻\nDialogue: 0,1:00:32.14,1:00:34.60,Default,,0,0,0,,但是那意味着我们需要知道 我们看到的是否是同一个\nDialogue: 0,1:00:36.51,1:00:38.84,Default,,0,0,0,,所以一些东西非常奇怪\nDialogue: 0,1:00:38.84,1:00:40.38,Default,,0,0,0,,不同寻常并且晦涩难懂\nDialogue: 0,1:00:40.84,1:00:43.52,Default,,0,0,0,,并且我不理解与赋值\nDialogue: 0,1:00:44.45,1:00:46.28,Default,,0,0,0,,变化以及对象有关的问题\nDialogue: 0,1:00:47.29,1:00:48.99,Default,,0,0,0,,这些东西可能变得非常非常糟糕\nDialogue: 0,1:00:51.40,1:00:52.12,Default,,0,0,0,,例如\nDialogue: 0,1:00:53.31,1:00:55.60,Default,,0,0,0,,我 一个特定的人\nDialogue: 0,1:00:56.16,1:00:57.72,Default,,0,0,0,,一个特定的对象\nDialogue: 0,1:00:57.96,1:00:59.31,Default,,0,0,0,,现在 我可以拿出小刀\nDialogue: 0,1:01:00.68,1:01:01.77,Default,,0,0,0,,切下一片我的指甲\nDialogue: 0,1:01:01.89,1:01:04.81,Default,,0,0,0,,一片指甲掉在了桌子上\nDialogue: 0,1:01:05.93,1:01:10.16,Default,,0,0,0,,我相信自己和一秒钟之前的自己 是同一个人\nDialogue: 0,1:01:10.97,1:01:12.81,Default,,0,0,0,,但在物理上并不是分毫不差\nDialogue: 0,1:01:14.46,1:01:15.43,Default,,0,0,0,,我已经改变了\nDialogue: 0,1:01:15.58,1:01:16.65,Default,,0,0,0,,为什么我还是同一个人呢？\nDialogue: 0,1:01:18.11,1:01:19.40,Default,,0,0,0,,什么能认定我的身份呢？\nDialogue: 0,1:01:20.96,1:01:23.50,Default,,0,0,0,,我不知道\nDialogue: 0,1:01:25.05,1:01:27.88,Default,,0,0,0,,除非我有某种特征\nDialogue: 0,1:01:29.71,1:01:33.04,Default,,0,0,0,,我觉得 由于引入赋值和对象\nDialogue: 0,1:01:33.64,1:01:38.28,Default,,0,0,0,,我们不得不去面对这种\nDialogue: 0,1:01:38.41,1:01:42.24,Default,,0,0,0,,困扰了哲学家们上千年的哲学问题\nDialogue: 0,1:01:43.42,1:01:44.99,Default,,0,0,0,,这也是相比之下 为什么数学清晰得多\nDialogue: 0,1:01:45.69,1:01:50.24,Default,,0,0,0,,我将尽我所能地向大家阐述关于动作和身份的理解\nDialogue: 0,1:01:52.44,1:01:55.39,Default,,0,0,0,,我们说动作A 对于对于某个对象X有影响\nDialogue: 0,1:01:55.77,1:01:56.70,Default,,0,0,0,,换句话说\nDialogue: 0,1:01:56.92,1:01:58.41,Default,,0,0,0,,X被A改变\nDialogue: 0,1:01:58.89,1:02:01.66,Default,,0,0,0,,如果某个属性P 在P作用于X之前为真\nDialogue: 0,1:02:01.87,1:02:03.76,Default,,0,0,0,,在A作用于X之后为假\nDialogue: 0,1:02:04.99,1:02:05.63,Default,,0,0,0,,那是个测试\nDialogue: 0,1:02:06.62,1:02:09.66,Default,,0,0,0,,这也意味着 我必须有变动前和变动后的X\nDialogue: 0,1:02:10.91,1:02:12.54,Default,,0,0,0,,或者 换句话说\nDialogue: 0,1:02:12.94,1:02:14.94,Default,,0,0,0,,我们说对任一动作 两个对象X和Y是同一个对象\nDialogue: 0,1:02:14.97,1:02:17.93,Default,,0,0,0,,当且仅当 该动作对X、Y有同样的影响\nDialogue: 0,1:02:19.63,1:02:21.39,Default,,0,0,0,,然而 就像我说的\nDialogue: 0,1:02:21.44,1:02:23.18,Default,,0,0,0,,对象在智力经济上是非常有用的\nDialogue: 0,1:02:24.64,1:02:27.12,Default,,0,0,0,,对于它们来说非常有用的东西之一\nDialogue: 0,1:02:28.27,1:02:29.44,Default,,0,0,0,,就是对于这个世界\nDialogue: 0,1:02:30.78,1:02:34.80,Default,,0,0,0,,我们习惯于把它认为是由带有独立状态的独立对象所构成的\nDialogue: 0,1:02:35.00,1:02:37.28,Default,,0,0,0,,虽然那并不完全正确 但我们喜欢以那样的的方式来思考\nDialogue: 0,1:02:39.68,1:02:42.03,Default,,0,0,0,,当我们要写一个非常复杂的程序\nDialogue: 0,1:02:42.03,1:02:43.26,Default,,0,0,0,,来应对这样一个世界时\nDialogue: 0,1:02:43.98,1:02:46.44,Default,,0,0,0,,如果我们希望这些程序可以被我们理解\nDialogue: 0,1:02:46.91,1:02:48.14,Default,,0,0,0,,并且也是可修改的\nDialogue: 0,1:02:48.73,1:02:51.12,Default,,0,0,0,,那么如果世界改变了 我们只需要稍微改动一下程序\nDialogue: 0,1:02:51.39,1:02:53.70,Default,,0,0,0,,我们希望建立一种联系 一种同构\nDialogue: 0,1:02:53.82,1:02:56.88,Default,,0,0,0,,建立在真实世界的对象与我们脑海中的对象之间\nDialogue: 0,1:02:58.76,1:03:01.44,Default,,0,0,0,,世界的模块化 使我们的程序得以模块化\nDialogue: 0,1:03:02.41,1:03:05.36,Default,,0,0,0,,所以我们发明了面向对象编程\nDialogue: 0,1:03:05.88,1:03:08.36,Default,,0,0,0,,使我们获得那样的力量\nDialogue: 0,1:03:10.06,1:03:10.94,Default,,0,0,0,,但是 它甚至更简单\nDialogue: 0,1:03:10.94,1:03:12.25,Default,,0,0,0,,让我们玩一个小游戏\nDialogue: 0,1:03:12.27,1:03:13.18,Default,,0,0,0,,我想通过这个游戏\nDialogue: 0,1:03:13.39,1:03:15.77,Default,,0,0,0,,给你展示一个更简单的例子\nDialogue: 0,1:03:16.00,1:03:21.74,Default,,0,0,0,,来说明谨慎地使用赋值语句 可以增强模块性\nDialogue: 0,1:03:22.86,1:03:25.35,Default,,0,0,0,,有一件事 我想让你牢牢地铭记\nDialogue: 0,1:03:25.45,1:03:27.44,Default,,0,0,0,,就是不要像在FORTRAN Basic\nDialogue: 0,1:03:27.45,1:03:29.79,Default,,0,0,0,,或者Pascal里一样使用赋值语句\nDialogue: 0,1:03:30.00,1:03:31.71,Default,,0,0,0,,你不那样做 也能达到目的\nDialogue: 0,1:03:34.04,1:03:36.62,Default,,0,0,0,,这不是思考大多数事情的正确方式\nDialogue: 0,1:03:36.97,1:03:38.28,Default,,0,0,0,,有些时候它是必要的\nDialogue: 0,1:03:38.68,1:03:39.69,Default,,0,0,0,,或者可能是必要的\nDialogue: 0,1:03:39.69,1:03:40.97,Default,,0,0,0,,我们一会更深入地去研究\nDialogue: 0,1:03:42.24,1:03:44.22,Default,,0,0,0,,我要给你展示一个有趣的游戏\nDialogue: 0,1:03:47.61,1:03:49.42,Default,,0,0,0,,从前有一个数学家\nDialogue: 0,1:03:49.68,1:03:53.69,Default,,0,0,0,,叫做Cesaro\nDialogue: 0,1:03:54.48,1:03:57.45,Default,,0,0,0,,他发现了一个计算pi的巧妙方法\nDialogue: 0,1:03:58.38,1:04:04.30,Default,,0,0,0,,这个方法是说 如果我有两个随机数\nDialogue: 0,1:04:05.24,1:04:06.94,Default,,0,0,0,,两个随机的整数\nDialogue: 0,1:04:07.74,1:04:09.48,Default,,0,0,0,,计算它们的最大公约数\nDialogue: 0,1:04:10.94,1:04:13.24,Default,,0,0,0,,结果可能是1 或者不是1\nDialogue: 0,1:04:13.84,1:04:15.64,Default,,0,0,0,,如果是1 它们没有公约数\nDialogue: 0,1:04:18.14,1:04:20.68,Default,,0,0,0,,如果它们的最大公约数是1\nDialogue: 0,1:04:21.12,1:04:23.09,Default,,0,0,0,,这两个随机数\nDialogue: 0,1:04:23.09,1:04:26.38,Default,,0,0,0,,两个随机生成的数 最大公约数为1的概率\nDialogue: 0,1:04:26.58,1:04:27.82,Default,,0,0,0,,与pi有关系\nDialogue: 0,1:04:29.32,1:04:30.11,Default,,0,0,0,,事实上\nDialogue: 0,1:04:31.11,1:04:32.33,Default,,0,0,0,,是的 这很奇怪\nDialogue: 0,1:04:32.94,1:04:34.41,Default,,0,0,0,,当然有其他计算pi的方法\nDialogue: 0,1:04:34.41,1:04:38.94,Default,,0,0,0,,像投针法之类的的方法\nDialogue: 0,1:04:40.19,1:04:48.97,Default,,0,0,0,,N1和N2的最大公约数是1的概率为\nDialogue: 0,1:04:49.44,1:04:51.02,Default,,0,0,0,,N1、N2是随机选取的两个数\nDialogue: 0,1:04:51.71,1:04:53.66,Default,,0,0,0,,是6/pi^2\nDialogue: 0,1:04:55.61,1:04:56.83,Default,,0,0,0,,我不准备证明这个\nDialogue: 0,1:04:57.15,1:04:59.64,Default,,0,0,0,,事实上这不难 并且有些有趣\nDialogue: 0,1:05:01.07,1:05:03.05,Default,,0,0,0,,我们要怎样估算这个概率呢？\nDialogue: 0,1:05:03.53,1:05:06.46,Default,,0,0,0,,我们估算概率的方法则是\nDialogue: 0,1:05:07.23,1:05:08.65,Default,,0,0,0,,是做大量的实验\nDialogue: 0,1:05:09.20,1:05:12.01,Default,,0,0,0,,去计算成功的试验\nDialogue: 0,1:05:12.01,1:05:13.58,Default,,0,0,0,,与试验总次数的比率\nDialogue: 0,1:05:16.32,1:05:17.28,Default,,0,0,0,,这种方法叫做蒙特卡罗方法\nDialogue: 0,1:05:18.04,1:05:22.38,Default,,0,0,0,,它也可以用于计算包含大量变量的积分\nDialogue: 0,1:05:22.94,1:05:25.28,Default,,0,0,0,,其中积分的面积是限定的\nDialogue: 0,1:05:26.27,1:05:28.70,Default,,0,0,0,,回到这里\nDialogue: 0,1:05:29.76,1:05:31.72,Default,,0,0,0,,我们来看看这张幻灯片\nDialogue: 0,1:05:33.96,1:05:36.92,Default,,0,0,0,,我们可以用Cesaro的方法来估算pi的值\nDialogue: 0,1:05:37.19,1:05:43.18,Default,,0,0,0,,通过N次试验 取结果的六分之一 开根号\nDialogue: 0,1:05:43.29,1:05:46.46,Default,,0,0,0,,用蒙特卡罗方法\nDialogue: 0,1:05:46.80,1:05:50.38,Default,,0,0,0,,进行了N次Cesaro实验\nDialogue: 0,1:05:51.37,1:05:57.56,Default,,0,0,0,,这个实验是关于两个随机数的最大公约数的--\nDialogue: 0,1:05:58.96,1:06:01.60,Default,,0,0,0,,你可以看到 我已经在这里进行了一些赋值\nDialogue: 0,1:06:01.84,1:06:03.13,Default,,0,0,0,,就像我写的这样\nDialogue: 0,1:06:04.04,1:06:07.49,Default,,0,0,0,,这个在括号中的RAND\nDialogue: 0,1:06:07.49,1:06:09.09,Default,,0,0,0,,这个过程调用\nDialogue: 0,1:06:09.09,1:06:11.39,Default,,0,0,0,,生成了一个与这个RAND不同的值\nDialogue: 0,1:06:11.39,1:06:13.72,Default,,0,0,0,,至少是我写的这样所假设的\nDialogue: 0,1:06:14.62,1:06:16.75,Default,,0,0,0,,这表明这不是一个函数\nDialogue: 0,1:06:18.20,1:06:20.57,Default,,0,0,0,,这里面会有一个不断改变内部状态\nDialogue: 0,1:06:22.27,1:06:28.64,Default,,0,0,0,,如果两个随机数的最大公约数等于1\nDialogue: 0,1:06:28.64,1:06:29.79,Default,,0,0,0,,这就是整个实验过程\nDialogue: 0,1:06:31.48,1:06:35.18,Default,,0,0,0,,那么我有了一个实验方法 用来估算pi的值\nDialogue: 0,1:06:36.51,1:06:39.72,Default,,0,0,0,,我可以轻松地将这个问题分为两个部分\nDialogue: 0,1:06:40.02,1:06:44.70,Default,,0,0,0,,一部分是使用蒙特卡罗方法进行特定的Cesaro实验 就像你刚才看到那个\nDialogue: 0,1:06:44.99,1:06:48.56,Default,,0,0,0,,另一部分就是一般性蒙特卡罗方法的实现\nDialogue: 0,1:06:49.16,1:06:50.27,Default,,0,0,0,,就是这个\nDialogue: 0,1:06:51.04,1:06:55.47,Default,,0,0,0,,如果我想进行N次蒙特卡罗试验\nDialogue: 0,1:06:55.67,1:06:58.36,Default,,0,0,0,,即一个确定的试验次数 和一个确定的实验\nDialogue: 0,1:06:59.31,1:07:00.33,Default,,0,0,0,,我进行实验的方法就是\nDialogue: 0,1:07:00.84,1:07:02.70,Default,,0,0,0,,构建一个迭代过程\nDialogue: 0,1:07:03.31,1:07:07.26,Default,,0,0,0,,这个过程有两个变量 分别是试验的剩余次数和通过次数\nDialogue: 0,1:07:08.35,1:07:09.44,Default,,0,0,0,,也就是实验结果为真的次数\nDialogue: 0,1:07:10.13,1:07:12.21,Default,,0,0,0,,如果剩余次数为0\nDialogue: 0,1:07:12.21,1:07:15.36,Default,,0,0,0,,结果就是通过的次数除以总次数\nDialogue: 0,1:07:16.04,1:07:17.52,Default,,0,0,0,,也就是该概率的估算值\nDialogue: 0,1:07:19.07,1:07:20.04,Default,,0,0,0,,如果剩余次数不是0\nDialogue: 0,1:07:20.04,1:07:22.08,Default,,0,0,0,,如果还有试验要做\nDialogue: 0,1:07:22.08,1:07:23.82,Default,,0,0,0,,那么接下来我们就进行一次试验\nDialogue: 0,1:07:23.85,1:07:27.30,Default,,0,0,0,,我们调用一次没有参数的实验的过程\nDialogue: 0,1:07:27.30,1:07:28.43,Default,,0,0,0,,我们进行这个试验\nDialogue: 0,1:07:29.10,1:07:30.64,Default,,0,0,0,,如果实验结果为真\nDialogue: 0,1:07:30.82,1:07:32.25,Default,,0,0,0,,我们继续循环\nDialogue: 0,1:07:32.62,1:07:35.42,Default,,0,0,0,,试验剩余次数减1\nDialogue: 0,1:07:35.70,1:07:37.48,Default,,0,0,0,,将试验通过次数加1\nDialogue: 0,1:07:38.57,1:07:40.11,Default,,0,0,0,,如果试验的结果为假\nDialogue: 0,1:07:40.41,1:07:42.25,Default,,0,0,0,,我们继续循环\nDialogue: 0,1:07:42.32,1:07:44.38,Default,,0,0,0,,剩余试验次数减1\nDialogue: 0,1:07:44.44,1:07:46.60,Default,,0,0,0,,试验通过次数保持不变\nDialogue: 0,1:07:48.76,1:07:54.59,Default,,0,0,0,,我们以TRIAL为剩余次数 以0为通过次数 开始迭代\nDialogue: 0,1:07:55.42,1:07:57.10,Default,,0,0,0,,多么简洁的小程序啊\nDialogue: 0,1:07:57.74,1:08:00.55,Default,,0,0,0,,我不一定非要进行Cesaro的实验\nDialogue: 0,1:08:00.55,1:08:02.73,Default,,0,0,0,,它可以用来进行很多种蒙特卡罗实验\nDialogue: 0,1:08:03.36,1:08:07.12,Default,,0,0,0,,当然 它依赖于某种随机数生成器的存在\nDialogue: 0,1:08:07.34,1:08:10.99,Default,,0,0,0,,随机数生成器通常是像这种的东西\nDialogue: 0,1:08:13.60,1:08:16.32,Default,,0,0,0,,这是一个随机数生成器--\nDialogue: 0,1:08:17.42,1:08:25.21,Default,,0,0,0,,它实际上就是一个过程 具体行为跟计数器有些相似\nDialogue: 0,1:08:25.61,1:08:27.52,Default,,0,0,0,,它会把X的值更新为\nDialogue: 0,1:08:28.33,1:08:31.82,Default,,0,0,0,,将某个函数应用于X的结果\nDialogue: 0,1:08:32.20,1:08:35.28,Default,,0,0,0,,而这类古怪的函数\nDialogue: 0,1:08:35.39,1:08:40.16,Default,,0,0,0,,你可以在Kunth写的关于编程细节的书中找到\nDialogue: 0,1:08:41.56,1:08:45.75,Default,,0,0,0,,他写的书绝妙而充满了编程细节\nDialogue: 0,1:08:45.75,1:08:48.52,Default,,0,0,0,,虽然我记不住随机数生成器该怎样写\nDialogue: 0,1:08:48.63,1:08:50.62,Default,,0,0,0,,但我可以在书里找出一个来用\nDialogue: 0,1:08:51.64,1:08:54.01,Default,,0,0,0,,最后 我返回了X的值\nDialogue: 0,1:08:54.08,1:08:57.40,Default,,0,0,0,,也就是随机数生成器的内部状态变量\nDialogue: 0,1:08:58.28,1:09:00.75,Default,,0,0,0,,这个状态变量以某种方式被初始化\nDialogue: 0,1:09:01.32,1:09:02.24,Default,,0,0,0,,从而获得了一个值\nDialogue: 0,1:09:03.39,1:09:08.11,Default,,0,0,0,,这个过程被定义在那个变量被约束的上下文中\nDialogue: 0,1:09:10.41,1:09:15.26,Default,,0,0,0,,所以你在这看到的 是一个隐藏的局部状态\nDialogue: 0,1:09:15.87,1:09:20.24,Default,,0,0,0,,这个过程定义在那个上下文中\nDialogue: 0,1:09:21.56,1:09:23.66,Default,,0,0,0,,这样做起来非常容易\nDialogue: 0,1:09:24.88,1:09:25.79,Default,,0,0,0,,而且结果也非常好\nDialogue: 0,1:09:25.99,1:09:27.77,Default,,0,0,0,,设想 我不想用赋值\nDialogue: 0,1:09:29.10,1:09:31.47,Default,,0,0,0,,假设我想写一个不带赋值的程序\nDialogue: 0,1:09:32.73,1:09:33.93,Default,,0,0,0,,我将遇到什么困难？\nDialogue: 0,1:09:35.52,1:09:37.40,Default,,0,0,0,,让我们来看看\nDialogue: 0,1:09:37.82,1:09:41.10,Default,,0,0,0,,我要用一下头顶上的投影仪了\nDialogue: 0,1:09:42.06,1:09:42.70,Default,,0,0,0,,多谢\nDialogue: 0,1:09:43.47,1:09:47.66,Default,,0,0,0,,首先 我们来整体看一下 这是一个很庞大的东西\nDialogue: 0,1:09:48.01,1:09:49.90,Default,,0,0,0,,它告诉你有某些东西出了问题\nDialogue: 0,1:09:50.96,1:09:52.75,Default,,0,0,0,,毕竟有这么大一堆东西呢\nDialogue: 0,1:09:53.42,1:09:54.60,Default,,0,0,0,,庞大而单一\nDialogue: 0,1:09:56.76,1:10:00.12,Default,,0,0,0,,你不需要现在去理解或看这里的文本\nDialogue: 0,1:10:00.12,1:10:01.39,Default,,0,0,0,,就把它们看做一个整体\nDialogue: 0,1:10:01.92,1:10:04.89,Default,,0,0,0,,它不是Cesaro的实验\nDialogue: 0,1:10:04.89,1:10:07.90,Default,,0,0,0,,它不是从蒙特卡罗过程中抽取出来的\nDialogue: 0,1:10:09.87,1:10:11.84,Default,,0,0,0,,它不是分离的 让我们来看看为什么\nDialogue: 0,1:10:14.22,1:10:15.85,Default,,0,0,0,,记住 这里的约束是\nDialogue: 0,1:10:15.85,1:10:17.87,Default,,0,0,0,,每个过程\nDialogue: 0,1:10:18.69,1:10:22.20,Default,,0,0,0,,对于同样的参数 将返回同样的值\nDialogue: 0,1:10:22.97,1:10:24.75,Default,,0,0,0,,每个过程就是一个函数\nDialogue: 0,1:10:26.92,1:10:28.50,Default,,0,0,0,,那是另一种约束\nDialogue: 0,1:10:28.50,1:10:31.21,Default,,0,0,0,,因为当我赋值时 我可以改变一些内部状态变量\nDialogue: 0,1:10:31.74,1:10:34.03,Default,,0,0,0,,所以让我们来看看它是怎么出错的\nDialogue: 0,1:10:35.04,1:10:36.14,Default,,0,0,0,,我们从头开始\nDialogue: 0,1:10:37.50,1:10:41.92,Default,,0,0,0,,估算pi的过程看起来是一样的\nDialogue: 0,1:10:42.66,1:10:45.88,Default,,0,0,0,,我取RAMDOM-GCD-TEST应用于N\nDialogue: 0,1:10:46.35,1:10:50.22,Default,,0,0,0,,的结果分之6的平方根\nDialogue: 0,1:10:50.74,1:10:51.93,Default,,0,0,0,,就是这个\nDialogue: 0,1:10:52.96,1:10:55.20,Default,,0,0,0,,在这里 我们开始看到了一些有趣的东西\nDialogue: 0,1:10:55.20,1:10:57.93,Default,,0,0,0,,对于以TRAILS为参数的RANDOM-GCD-TEST过程\nDialogue: 0,1:10:58.32,1:10:59.98,Default,,0,0,0,,就像我们之前做的一样\nDialogue: 0,1:11:00.46,1:11:04.66,Default,,0,0,0,,是一个以剩余次数\nDialogue: 0,1:11:04.66,1:11:06.80,Default,,0,0,0,,通过次数\nDialogue: 0,1:11:08.27,1:11:09.71,Default,,0,0,0,,另一个变量X为基准的迭代\nDialogue: 0,1:11:10.75,1:11:11.76,Default,,0,0,0,,这个X是什么？\nDialogue: 0,1:11:12.33,1:11:15.20,Default,,0,0,0,,X是随机数发生器的状态\nDialogue: 0,1:11:19.00,1:11:21.16,Default,,0,0,0,,它会在这里被使用\nDialogue: 0,1:11:21.16,1:11:23.79,Default,,0,0,0,,这里的同样的随机更新函数\nDialogue: 0,1:11:23.79,1:11:27.15,Default,,0,0,0,,来自于一个我另外写的随机数发生器\nDialogue: 0,1:11:27.71,1:11:29.32,Default,,0,0,0,,或者从Knuth的书中找一个\nDialogue: 0,1:11:31.56,1:11:33.36,Default,,0,0,0,,X将转化为X1\nDialogue: 0,1:11:33.37,1:11:34.36,Default,,0,0,0,,但我需要两个随机数\nDialogue: 0,1:11:34.81,1:11:36.92,Default,,0,0,0,,X1将被转化为X2\nDialogue: 0,1:11:37.26,1:11:38.44,Default,,0,0,0,,我有两个随机数\nDialogue: 0,1:11:39.50,1:11:42.14,Default,,0,0,0,,然后进行和之前一样的步骤\nDialogue: 0,1:11:42.52,1:11:44.19,Default,,0,0,0,,取X1和X2的最大公约数\nDialogue: 0,1:11:44.22,1:11:47.15,Default,,0,0,0,,如果结果是1 则将X2作为下一个X的值继续循环\nDialogue: 0,1:11:54.78,1:11:55.98,Default,,0,0,0,,这里所发生的\nDialogue: 0,1:11:56.88,1:11:58.70,Default,,0,0,0,,随机数发生器的状态\nDialogue: 0,1:11:58.73,1:12:01.70,Default,,0,0,0,,不再被限制于其内部\nDialogue: 0,1:12:01.80,1:12:02.73,Default,,0,0,0,,它已经暴露了出来\nDialogue: 0,1:12:03.33,1:12:05.50,Default,,0,0,0,,它已经被暴露在\nDialogue: 0,1:12:05.50,1:12:10.08,Default,,0,0,0,,我们的的蒙特卡罗实验的过程中\nDialogue: 0,1:12:10.70,1:12:11.87,Default,,0,0,0,,但比那更糟糕的是\nDialogue: 0,1:12:11.87,1:12:16.24,Default,,0,0,0,,同样的 因为它也被包含在我们的Cesaro实验中\nDialogue: 0,1:12:16.78,1:12:19.48,Default,,0,0,0,,它被暴露了两次 因为Cesaro被调用了两次\nDialogue: 0,1:12:20.86,1:12:22.47,Default,,0,0,0,,每次有不同的值\nDialogue: 0,1:12:22.47,1:12:25.16,Default,,0,0,0,,如果我要进行一个合理的实验的话\nDialogue: 0,1:12:26.32,1:12:28.32,Default,,0,0,0,,所以Cesaro也不能成为函数了\nDialogue: 0,1:12:31.04,1:12:35.69,Default,,0,0,0,,除非我把随机数发生器的种子传给它\nDialogue: 0,1:12:36.52,1:12:39.37,Default,,0,0,0,,所以很不幸 随机数发生器的种子\nDialogue: 0,1:12:39.37,1:12:42.77,Default,,0,0,0,,从随机数发生器中暴露到了Cesaro内部\nDialogue: 0,1:12:42.88,1:12:45.16,Default,,0,0,0,,被暴露在蒙特卡罗实验中\nDialogue: 0,1:12:45.64,1:12:49.12,Default,,0,0,0,,很不幸 这里的蒙特卡罗实验不再是通用的了\nDialogue: 0,1:12:50.25,1:12:51.80,Default,,0,0,0,,这里的蒙特卡罗实验\nDialogue: 0,1:12:52.03,1:12:54.73,Default,,0,0,0,,知道了我在实验中需要多少个随机数\nDialogue: 0,1:12:58.96,1:12:59.74,Default,,0,0,0,,这真的很糟糕\nDialogue: 0,1:13:00.08,1:13:02.54,Default,,0,0,0,,我失去了将问题分解开来的能力\nDialogue: 0,1:13:03.44,1:13:09.12,Default,,0,0,0,,因为我不愿意接受信息的循环\nDialogue: 0,1:13:09.50,1:13:12.43,Default,,0,0,0,,反馈的过程\nDialogue: 0,1:13:12.88,1:13:15.94,Default,,0,0,0,,这之前都是发生在随机数发生器内部\nDialogue: 0,1:13:15.94,1:13:21.21,Default,,0,0,0,,也就是赋值给一个限制在随机数生成器内部的状态变量\nDialogue: 0,1:13:22.92,1:13:25.48,Default,,0,0,0,,所以实际上 随机数发生器是一个对象\nDialogue: 0,1:13:25.92,1:13:27.37,Default,,0,0,0,,它有一个内部状态变量\nDialogue: 0,1:13:28.06,1:13:29.36,Default,,0,0,0,,它不受任何东西影响\nDialogue: 0,1:13:29.37,1:13:31.60,Default,,0,0,0,,但是它会给你某些东西 把它的力量赐予你\nDialogue: 0,1:13:32.80,1:13:34.28,Default,,0,0,0,,那是我们现在缺少的\nDialogue: 0,1:13:38.00,1:13:40.73,Default,,0,0,0,,好 我认为我已经知道了\nDialogue: 0,1:13:40.73,1:13:42.30,Default,,0,0,0,,引入赋值的充分理由\nDialogue: 0,1:13:42.83,1:13:45.24,Default,,0,0,0,,并且一些看起来很圆满\nDialogue: 0,1:13:45.38,1:13:50.70,Default,,0,0,0,,如果赋值是一个好东西\nDialogue: 0,1:13:51.74,1:13:53.04,Default,,0,0,0,,并且赋值是值得的 这不是很好吗？\nDialogue: 0,1:13:53.28,1:13:54.14,Default,,0,0,0,,我不是很确定\nDialogue: 0,1:13:55.34,1:13:57.04,Default,,0,0,0,,Mr. Gilbert和Sullivan说过\nDialogue: 0,1:13:57.04,1:13:58.51,Default,,0,0,0,,事物往往不像表面看到的那样\nDialogue: 0,1:13:58.51,1:14:00.35,Default,,0,0,0,,脱脂牛奶也能装成奶油\nDialogue: 0,1:14:01.87,1:14:03.90,Default,,0,0,0,,谁有什么问题吗？\nDialogue: 0,1:14:16.97,1:14:18.30,Default,,0,0,0,,在座的有哲学家吗？\nDialogue: 0,1:14:20.06,1:14:22.03,Default,,0,0,0,,有人想要讨论有关“对象”的问题吗？\nDialogue: 0,1:14:24.32,1:14:25.50,Default,,0,0,0,,你们已经一头雾水了是吧？\nDialogue: 0,1:14:29.72,1:14:30.72,Default,,0,0,0,,你们还没有完成家庭作业呢\nDialogue: 0,1:14:30.73,1:14:32.00,Default,,0,0,0,,你们需要提一个好问题\nDialogue: 0,1:14:36.35,1:14:37.44,Default,,0,0,0,,好了\nDialogue: 0,1:14:39.97,1:14:42.33,Default,,0,0,0,,感谢你们 我们下课吧\nDialogue: 0,1:14:47.90,1:15:05.69,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:14:47.90,1:15:05.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec5a.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: EN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 1252\nActive Line: 1262\nVideo Position: 134759\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:09.92,0:00:13.63,EN,,0,0,0,,Assignment, State, and Side-effects\nDialogue: 0,0:00:18.31,0:00:22.00,EN,,0,0,0,,PROFESSOR: Well, so far we've invented enough programming\nDialogue: 0,0:00:22.25,0:00:24.06,EN,,0,0,0,,to do some very complicated things.\nDialogue: 0,0:00:24.76,0:00:29.66,EN,,0,0,0,,And you surely learned a lot about programming at this point.\nDialogue: 0,0:00:29.66,0:00:31.48,EN,,0,0,0,,You've learned almost all the most important tricks\nDialogue: 0,0:00:31.86,0:00:35.87,EN,,0,0,0,,that usually don't get taught to people until they have had a lot of experience.\nDialogue: 0,0:00:36.41,0:00:40.08,EN,,0,0,0,,For example, data directed programming is a major trick,\nDialogue: 0,0:00:40.75,0:00:43.15,EN,,0,0,0,,and yesterday you also saw an interpreted language.\nDialogue: 0,0:00:45.02,0:00:48.46,EN,,0,0,0,,We did this all in a computer language,\nDialogue: 0,0:00:48.54,0:00:49.63,EN,,0,0,0,,at this point,\nDialogue: 0,0:00:49.88,0:00:51.95,EN,,0,0,0,,where there was no assignment statement.\nDialogue: 0,0:00:53.77,0:00:58.17,EN,,0,0,0,,And presumably, for those of you who've seen your Basic or Pascal or whatever,\nDialogue: 0,0:00:58.68,0:01:01.23,EN,,0,0,0,,that's usually considered the most important thing.\nDialogue: 0,0:01:01.79,0:01:03.82,EN,,0,0,0,,Well today, we're going to do something horrible.\nDialogue: 0,0:01:03.82,0:01:05.45,EN,,0,0,0,,We're going to add an assignment statement.\nDialogue: 0,0:01:07.21,0:01:09.14,EN,,0,0,0,,And since we can do all these wonderful things without it,\nDialogue: 0,0:01:09.14,0:01:10.17,EN,,0,0,0,,why should we add it?\nDialogue: 0,0:01:10.99,0:01:12.43,EN,,0,0,0,,An important thing to understand it\nDialogue: 0,0:01:12.46,0:01:15.71,EN,,0,0,0,,is that today we're going to first of all, have a rule,\nDialogue: 0,0:01:16.48,0:01:17.93,EN,,0,0,0,,which is going to always be obeyed,\nDialogue: 0,0:01:17.93,0:01:20.80,EN,,0,0,0,,which is the only reason we ever add a feature to our language\nDialogue: 0,0:01:21.53,0:01:23.14,EN,,0,0,0,,is because there is a good reason.\nDialogue: 0,0:01:23.93,0:01:27.28,EN,,0,0,0,,And the good reason is going to boil down to the ability,\nDialogue: 0,0:01:27.42,0:01:31.51,EN,,0,0,0,,you now get an ability to break a problem into pieces that are different sets of pieces\nDialogue: 0,0:01:31.51,0:01:33.44,EN,,0,0,0,,then you could have broken it down without that,\nDialogue: 0,0:01:34.38,0:01:36.16,EN,,0,0,0,,give you another means of decomposition.\nDialogue: 0,0:01:38.30,0:01:39.45,EN,,0,0,0,,However, let's just start.\nDialogue: 0,0:01:39.45,0:01:41.88,EN,,0,0,0,,Let me quick begin by reviewing\nDialogue: 0,0:01:41.88,0:01:47.37,EN,,0,0,0,,the kind of language that we have now.\nDialogue: 0,0:01:48.16,0:01:50.44,EN,,0,0,0,,We've been writing what's called functional programs.\nDialogue: 0,0:01:51.21,0:01:52.52,EN,,0,0,0,,And functional programs\nDialogue: 0,0:01:53.04,0:01:57.95,EN,,0,0,0,,are a kind of encoding of mathematical truths.\nDialogue: 0,0:01:58.88,0:02:00.51,EN,,0,0,0,,For example, when we look at\nDialogue: 0,0:02:00.51,0:02:04.09,EN,,0,0,0,,the factorial procedure that you see on the slide here,\nDialogue: 0,0:02:05.07,0:02:06.62,EN,,0,0,0,,it's basically two clauses.\nDialogue: 0,0:02:06.99,0:02:08.64,EN,,0,0,0,,If n is one, the result is one,\nDialogue: 0,0:02:08.64,0:02:11.20,EN,,0,0,0,,otherwise n times factorial n minus one.\nDialogue: 0,0:02:11.20,0:02:12.33,EN,,0,0,0,,That's factorial of n.\nDialogue: 0,0:02:12.89,0:02:14.27,EN,,0,0,0,,Well, that is factorial of n.\nDialogue: 0,0:02:14.83,0:02:16.87,EN,,0,0,0,,And written down in some other obscure notation\nDialogue: 0,0:02:16.87,0:02:19.32,EN,,0,0,0,,that you might have learned in calculus classes,\nDialogue: 0,0:02:20.30,0:02:22.11,EN,,0,0,0,,Ahh.. mathematical logic,\nDialogue: 0,0:02:22.11,0:02:26.36,EN,,0,0,0,,what you see there is if n equals one,\nDialogue: 0,0:02:27.13,0:02:29.90,EN,,0,0,0,,for the result of n factorial is one, otherwise,\nDialogue: 0,0:02:29.90,0:02:32.56,EN,,0,0,0,,greater than one, n factorial is n times n minus one factorial.\nDialogue: 0,0:02:32.56,0:02:33.55,EN,,0,0,0,,True statements,\nDialogue: 0,0:02:34.92,0:02:36.70,EN,,0,0,0,,that's the kind of language we've been using.\nDialogue: 0,0:02:37.00,0:02:39.23,EN,,0,0,0,,And whenever we have true statements of that sort,\nDialogue: 0,0:02:39.53,0:02:46.65,EN,,0,0,0,,there is a kind of, a way of understanding how they work\nDialogue: 0,0:02:47.40,0:02:51.12,EN,,0,0,0,,which is that such processes can be evolved by substitution.\nDialogue: 0,0:02:51.29,0:02:53.71,EN,,0,0,0,,And so we see on the second slide here,\nDialogue: 0,0:02:54.99,0:02:58.81,EN,,0,0,0,,that the way we understand the execution\nDialogue: 0,0:02:58.83,0:03:03.50,EN,,0,0,0,,implied by those statements in arranged in that order,\nDialogue: 0,0:03:04.04,0:03:07.76,EN,,0,0,0,,is that you do successive substitutions of arguments\nDialogue: 0,0:03:07.87,0:03:10.88,EN,,0,0,0,,for formal parameters in the body of a procedure.\nDialogue: 0,0:03:12.00,0:03:14.51,EN,,0,0,0,,This is basically a sequence of equalities.\nDialogue: 0,0:03:14.61,0:03:17.25,EN,,0,0,0,,Factorial four is four times factorial three.\nDialogue: 0,0:03:17.25,0:03:20.05,EN,,0,0,0,,That is four times three times factorial of two\nDialogue: 0,0:03:20.05,0:03:21.01,EN,,0,0,0,,and so on.\nDialogue: 0,0:03:21.23,0:03:23.87,EN,,0,0,0,,We're always preserving truth.\nDialogue: 0,0:03:25.23,0:03:28.84,EN,,0,0,0,,Even though we're talking about true statements,\nDialogue: 0,0:03:28.84,0:03:31.96,EN,,0,0,0,,there might be more than one organization of these true statements\nDialogue: 0,0:03:31.96,0:03:35.12,EN,,0,0,0,,to describe the computation of a particular function,\nDialogue: 0,0:03:36.32,0:03:38.42,EN,,0,0,0,,the computation of the value of a particular function.\nDialogue: 0,0:03:38.42,0:03:40.92,EN,,0,0,0,,So, for example, looking at the next one here.\nDialogue: 0,0:03:41.48,0:03:49.02,EN,,0,0,0,,Here is a way of looking at the sum of n and m.\nDialogue: 0,0:03:49.53,0:03:52.04,EN,,0,0,0,,And we did this one by a recursive process.\nDialogue: 0,0:03:52.89,0:03:58.16,EN,,0,0,0,,It's the increment of the sum of the decrement of n and m.\nDialogue: 0,0:04:00.08,0:04:05.62,EN,,0,0,0,,And, of course, there is some piece of mathematical logic here that describes that.\nDialogue: 0,0:04:06.17,0:04:10.49,EN,,0,0,0,,It's the increment of the sum of the decrement of n and m,\nDialogue: 0,0:04:11.40,0:04:12.22,EN,,0,0,0,,just like that.\nDialogue: 0,0:04:13.10,0:04:16.40,EN,,0,0,0,,So there's nothing particularly magic about that.\nDialogue: 0,0:04:16.41,0:04:20.01,EN,,0,0,0,,And, of course, if we can also look at an iterative process for the same,\nDialogue: 0,0:04:20.19,0:04:24.92,EN,,0,0,0,,a program that evolves an iterative process, for the same function.\nDialogue: 0,0:04:25.26,0:04:27.56,EN,,0,0,0,,These are two things that compute the same answer.\nDialogue: 0,0:04:30.08,0:04:34.83,EN,,0,0,0,,And we have equivalent mathematical truths that are arranged there.\nDialogue: 0,0:04:36.65,0:04:39.93,EN,,0,0,0,,And just the way you arrange those truths determine the particular process.\nDialogue: 0,0:04:40.30,0:04:43.42,EN,,0,0,0,,In the way choose and arrange them determines the process that's evolved.\nDialogue: 0,0:04:44.33,0:04:48.60,EN,,0,0,0,,So we have the flexibility of talking about both the function to be computed,\nDialogue: 0,0:04:48.60,0:04:50.19,EN,,0,0,0,,and the method by which it's computed.\nDialogue: 0,0:04:50.60,0:04:52.60,EN,,0,0,0,,So it's not clear we need more.\nDialogue: 0,0:04:53.61,0:04:55.50,EN,,0,0,0,,However, today I'm going to this awful thing.\nDialogue: 0,0:04:55.50,0:04:58.43,EN,,0,0,0,,I'm going to introduce this assignment operation.\nDialogue: 0,0:04:58.89,0:05:00.41,EN,,0,0,0,,Now, what is this?\nDialogue: 0,0:05:02.89,0:05:09.22,EN,,0,0,0,,Well, first of all, there is going to be another kind of kind of statement, if you will,\nDialogue: 0,0:05:09.22,0:05:10.84,EN,,0,0,0,,in a programming language called Set!\nDialogue: 0,0:05:12.41,0:05:15.96,EN,,0,0,0,,And SET! -- Things that do things like assignment,\nDialogue: 0,0:05:15.96,0:05:15.98,EN,,0,0,0,,\nDialogue: 0,0:05:15.98,0:05:17.85,EN,,0,0,0,,I'm going to put exclamation points after.\nDialogue: 0,0:05:18.51,0:05:20.96,EN,,0,0,0,,We'll talk about what that means in a second.\nDialogue: 0,0:05:20.96,0:05:23.01,EN,,0,0,0,,The exclamation point, again like question mark,\nDialogue: 0,0:05:23.01,0:05:25.88,EN,,0,0,0,,is an arbitrary thing we attach to the symbol which is the name,\nDialogue: 0,0:05:25.88,0:05:27.88,EN,,0,0,0,,has no significance to the system.\nDialogue: 0,0:05:28.08,0:05:30.21,EN,,0,0,0,,The only significance is to me and you\nDialogue: 0,0:05:30.40,0:05:34.41,EN,,0,0,0,,to alert you that this is an assignment of some sort.\nDialogue: 0,0:05:35.88,0:05:40.06,EN,,0,0,0,,But we're going to set a variable to a value.\nDialogue: 0,0:05:43.74,0:05:45.13,EN,,0,0,0,,And what that's going to mean\nDialogue: 0,0:05:45.13,0:05:48.28,EN,,0,0,0,,is that there is a time at which something happens.\nDialogue: 0,0:05:48.65,0:05:49.61,EN,,0,0,0,,Here's a time.\nDialogue: 0,0:05:49.86,0:05:52.14,EN,,0,0,0,,If I have time going this way,\nDialogue: 0,0:05:53.50,0:05:54.82,EN,,0,0,0,,it's a time axis.\nDialogue: 0,0:05:55.00,0:05:57.82,EN,,0,0,0,,Time progresses by walking down the page.\nDialogue: 0,0:05:58.70,0:06:00.92,EN,,0,0,0,,Then an assignment is the first thing we have\nDialogue: 0,0:06:00.92,0:06:04.30,EN,,0,0,0,,that produces the difference between a before and an after.\nDialogue: 0,0:06:06.59,0:06:08.72,EN,,0,0,0,,All the other programs that we've written,\nDialogue: 0,0:06:09.18,0:06:10.68,EN,,0,0,0,,that have no assignments in them,\nDialogue: 0,0:06:10.68,0:06:13.12,EN,,0,0,0,,the order in which they were evaluated didn't matter.\nDialogue: 0,0:06:14.70,0:06:15.96,EN,,0,0,0,,But assignment is special,\nDialogue: 0,0:06:15.96,0:06:17.69,EN,,0,0,0,,it produces a moment in time.\nDialogue: 0,0:06:17.96,0:06:24.73,EN,,0,0,0,,So there is a moment before the set occurs and after,\nDialogue: 0,0:06:27.61,0:06:32.70,EN,,0,0,0,,such that after this moment in time,\nDialogue: 0,0:06:33.60,0:06:43.76,EN,,0,0,0,,the variable has the value, value.\nDialogue: 0,0:06:49.23,0:06:51.50,EN,,0,0,0,,Independent of what value it had before,\nDialogue: 0,0:06:52.80,0:06:55.79,EN,,0,0,0,,set! changes the value of the variable.\nDialogue: 0,0:06:57.69,0:06:58.75,EN,,0,0,0,,Until this moment,\nDialogue: 0,0:06:58.75,0:07:01.50,EN,,0,0,0,,we had nothing that changed.\nDialogue: 0,0:07:03.21,0:07:04.11,EN,,0,0,0,,So, for example,\nDialogue: 0,0:07:04.84,0:07:06.23,EN,,0,0,0,,one of the things we can think of\nDialogue: 0,0:07:06.23,0:07:09.42,EN,,0,0,0,,is that the procedures we write for something like factorial\nDialogue: 0,0:07:09.64,0:07:12.75,EN,,0,0,0,,are in fact pretty much identical to the function factorial.\nDialogue: 0,0:07:13.77,0:07:16.44,EN,,0,0,0,,Factorial of four, if I write fact4,\nDialogue: 0,0:07:17.23,0:07:19.15,EN,,0,0,0,,independent of what context it's in,\nDialogue: 0,0:07:19.69,0:07:21.29,EN,,0,0,0,,and independent of how many times I write it,\nDialogue: 0,0:07:21.29,0:07:22.35,EN,,0,0,0,,I always get the same answer.\nDialogue: 0,0:07:23.29,0:07:24.12,EN,,0,0,0,,It's always 24.\nDialogue: 0,0:07:25.37,0:07:28.92,EN,,0,0,0,,It's a unique map from the argument to the answer.\nDialogue: 0,0:07:30.30,0:07:32.65,EN,,0,0,0,,And all the programs we've written so far are like that.\nDialogue: 0,0:07:33.52,0:07:36.03,EN,,0,0,0,,However, once I have assignment, that isn't true.\nDialogue: 0,0:07:36.96,0:07:38.16,EN,,0,0,0,,So, for example,\nDialogue: 0,0:07:39.18,0:07:48.52,EN,,0,0,0,,if I were to define count to be one.\nDialogue: 0,0:07:50.00,0:07:52.41,EN,,0,0,0,,And then I'm going to define also a procedure,\nDialogue: 0,0:07:55.16,0:07:56.83,EN,,0,0,0,,a simple procedure called demo,\nDialogue: 0,0:07:59.52,0:08:03.84,EN,,0,0,0,,which takes argument x and does the following operations.\nDialogue: 0,0:08:03.84,0:08:09.62,EN,,0,0,0,,It first sets x to x plus one.\nDialogue: 0,0:08:09.62,0:08:11.77,EN,,0,0,0,,My gosh, this looksjust like FORTRAN, right--\nDialogue: 0,0:08:13.16,0:08:14.17,EN,,0,0,0,,in a funny syntax.\nDialogue: 0,0:08:16.80,0:08:21.37,EN,,0,0,0,,And then add to x count,\nDialogue: 0,0:08:22.14,0:08:24.14,EN,,0,0,0,,Oh, I just made a mistake.\nDialogue: 0,0:08:24.38,0:08:25.23,EN,,0,0,0,,I want to say,\nDialogue: 0,0:08:25.47,0:08:27.12,EN,,0,0,0,,set! count to one plus count.\nDialogue: 0,0:08:30.37,0:08:31.79,EN,,0,0,0,,It's this thing defined here.\nDialogue: 0,0:08:34.41,0:08:36.51,EN,,0,0,0,,And then add and said plus x count.\nDialogue: 0,0:08:40.35,0:08:42.06,EN,,0,0,0,,Then I can try this procedure.\nDialogue: 0,0:08:42.48,0:08:43.20,EN,,0,0,0,,Let's run it.\nDialogue: 0,0:08:43.92,0:08:47.22,EN,,0,0,0,,So, suppose I get a prompt and I say,\nDialogue: 0,0:08:47.48,0:08:48.68,EN,,0,0,0,,demo 3\nDialogue: 0,0:08:52.19,0:08:53.20,EN,,0,0,0,,Well, what happens here?\nDialogue: 0,0:08:53.74,0:08:55.28,EN,,0,0,0,,The first thing that happens\nDialogue: 0,0:08:55.53,0:08:56.89,EN,,0,0,0,,is count is currently one.\nDialogue: 0,0:08:56.89,0:08:58.40,EN,,0,0,0,,Currently, there is a time.\nDialogue: 0,0:08:59.12,0:09:00.29,EN,,0,0,0,,We're talking about time.\nDialogue: 0,0:09:00.62,0:09:01.74,EN,,0,0,0,,x gets three.\nDialogue: 0,0:09:02.92,0:09:04.03,EN,,0,0,0,,At this moment,\nDialogue: 0,0:09:04.67,0:09:07.53,EN,,0,0,0,,I say, oh yes, count is incremented, so count is two.\nDialogue: 0,0:09:09.02,0:09:10.44,EN,,0,0,0,,two plus three is five.\nDialogue: 0,0:09:10.80,0:09:12.43,EN,,0,0,0,,So the answer I get out is five.\nDialogue: 0,0:09:14.48,0:09:21.58,EN,,0,0,0,,Then I say, demo of say, three again.\nDialogue: 0,0:09:23.60,0:09:24.56,EN,,0,0,0,,Okay, What do I get?\nDialogue: 0,0:09:24.83,0:09:27.40,EN,,0,0,0,,Well, now count is two, it's not one anymore,\nDialogue: 0,0:09:28.91,0:09:30.35,EN,,0,0,0,,because I have incremented it.\nDialogue: 0,0:09:30.92,0:09:32.64,EN,,0,0,0,,But now I go through this process,\nDialogue: 0,0:09:32.72,0:09:33.66,EN,,0,0,0,,three goes into x,\nDialogue: 0,0:09:34.17,0:09:37.40,EN,,0,0,0,,count becomes one plus count, so that's three now.\nDialogue: 0,0:09:38.08,0:09:39.62,EN,,0,0,0,,The sum of those two is six,\nDialogue: 0,0:09:39.62,0:09:40.94,EN,,0,0,0,,so the answer is six.\nDialogue: 0,0:09:41.92,0:09:43.03,EN,,0,0,0,,And what we see\nDialogue: 0,0:09:43.03,0:09:44.72,EN,,0,0,0,,is the same expression\nDialogue: 0,0:09:45.08,0:09:46.64,EN,,0,0,0,,leads to two different answers,\nDialogue: 0,0:09:48.75,0:09:49.96,EN,,0,0,0,,depending upon time.\nDialogue: 0,0:09:52.08,0:09:53.74,EN,,0,0,0,,So demo is not a function,\nDialogue: 0,0:09:54.17,0:09:56.12,EN,,0,0,0,,does not compute a mathematical function.\nDialogue: 0,0:09:59.88,0:10:02.09,EN,,0,0,0,,In fact, you could also see why now, of course,\nDialogue: 0,0:10:02.84,0:10:06.41,EN,,0,0,0,,this is the first place where the substitution model isn't going to work.\nDialogue: 0,0:10:07.72,0:10:09.55,EN,,0,0,0,,This kills the substitution model dead.\nDialogue: 0,0:10:11.28,0:10:13.82,EN,,0,0,0,,You know, with quotation there were some little problems\nDialogue: 0,0:10:13.85,0:10:17.18,EN,,0,0,0,,that a philosopher might notice with substitutions,\nDialogue: 0,0:10:17.18,0:10:19.87,EN,,0,0,0,,because you have to worry about what deductions you can make\nDialogue: 0,0:10:20.91,0:10:22.12,EN,,0,0,0,,when you substitute into quotes,\nDialogue: 0,0:10:22.34,0:10:23.92,EN,,0,0,0,,if you're allowed to do that at all.\nDialogue: 0,0:10:25.08,0:10:25.60,EN,,0,0,0,,But\nDialogue: 0,0:10:26.06,0:10:28.00,EN,,0,0,0,,here the substitution model is dead,\nDialogue: 0,0:10:28.11,0:10:29.40,EN,,0,0,0,,can't do anything at all.\nDialogue: 0,0:10:29.64,0:10:30.57,EN,,0,0,0,,Because,\nDialogue: 0,0:10:30.57,0:10:35.85,EN,,0,0,0,,Supposing I wanted to use a substitution model to consider substituting for count?\nDialogue: 0,0:10:37.10,0:10:41.16,EN,,0,0,0,,Well, my gosh, if I substitute for here and here,\nDialogue: 0,0:10:41.69,0:10:42.96,EN,,0,0,0,,they're different ones.\nDialogue: 0,0:10:44.44,0:10:45.96,EN,,0,0,0,,It's not the same count any more.\nDialogue: 0,0:10:46.48,0:10:47.64,EN,,0,0,0,,I get the wrong answer.\nDialogue: 0,0:10:47.97,0:10:50.14,EN,,0,0,0,,The substitution model is a static phenomenon\nDialogue: 0,0:10:51.18,0:10:52.56,EN,,0,0,0,,describes things that are true\nDialogue: 0,0:10:53.93,0:10:55.29,EN,,0,0,0,,and not things that change.\nDialogue: 0,0:10:55.50,0:10:57.04,EN,,0,0,0,,Here, we have truths that change.\nDialogue: 0,0:11:00.60,0:11:06.74,EN,,0,0,0,,OK, Well, before I give you any understanding of this,\nDialogue: 0,0:11:06.74,0:11:07.79,EN,,0,0,0,,this is very bad.\nDialogue: 0,0:11:07.79,0:11:09.72,EN,,0,0,0,,Now, we've lost our model of computation.\nDialogue: 0,0:11:10.28,0:11:10.80,EN,,0,0,0,,And,\nDialogue: 0,0:11:11.48,0:11:13.69,EN,,0,0,0,,pretty soon, I'm going to have to build you a new model of computation.\nDialogue: 0,0:11:14.66,0:11:17.87,EN,,0,0,0,,But ours plays with this, just now, in an informal sense.\nDialogue: 0,0:11:18.56,0:11:20.16,EN,,0,0,0,,Of course, what you already see\nDialogue: 0,0:11:20.51,0:11:22.70,EN,,0,0,0,,is that when I have something like assignment,\nDialogue: 0,0:11:23.12,0:11:24.51,EN,,0,0,0,,the model that we're going to need\nDialogue: 0,0:11:24.51,0:11:26.89,EN,,0,0,0,,is different from the model that we had before\nDialogue: 0,0:11:26.89,0:11:30.93,EN,,0,0,0,,in that, the variables, those symbols like count, or x\nDialogue: 0,0:11:30.93,0:11:34.07,EN,,0,0,0,,are no longer going to refer to the values they have,\nDialogue: 0,0:11:34.07,0:11:37.31,EN,,0,0,0,,but rather to some sort of place where the value restored.\nDialogue: 0,0:11:37.68,0:11:39.47,EN,,0,0,0,,We're going to have to think that way for a while.\nDialogue: 0,0:11:40.20,0:11:42.11,EN,,0,0,0,,And it's going to be a very bad thing\nDialogue: 0,0:11:42.11,0:11:43.47,EN,,0,0,0,,and cause a lot of trouble.\nDialogue: 0,0:11:44.49,0:11:48.25,EN,,0,0,0,,And so, as I said, the very fact that we're inventing this bad thing,\nDialogue: 0,0:11:48.25,0:11:50.09,EN,,0,0,0,,means that there had better be a good reason for it,\nDialogue: 0,0:11:50.37,0:11:52.86,EN,,0,0,0,,otherwise, just a waste of time and a lot of effort.\nDialogue: 0,0:11:53.39,0:11:55.55,EN,,0,0,0,,Let's just look at some of it just to play.\nDialogue: 0,0:11:55.88,0:11:58.59,EN,,0,0,0,,Supposing we write down the functional version,\nDialogue: 0,0:11:58.59,0:12:00.48,EN,,0,0,0,,functional meaning in the old style,\nDialogue: 0,0:12:01.37,0:12:04.60,EN,,0,0,0,,of factorial by an iterative process.\nDialogue: 0,0:12:09.59,0:12:13.28,EN,,0,0,0,,Factorial of n.\nDialogue: 0,0:12:18.38,0:12:24.35,EN,,0,0,0,,we're going to iterate of m and i,\nDialogue: 0,0:12:26.12,0:12:33.13,EN,,0,0,0,,which says if i is greater than n,\nDialogue: 0,0:12:33.77,0:12:35.51,EN,,0,0,0,,then the result is m,\nDialogue: 0,0:12:36.30,0:12:37.39,EN,,0,0,0,,otherwise,\nDialogue: 0,0:12:39.79,0:12:46.82,EN,,0,0,0,,the result of iterating the product of i and m.\nDialogue: 0,0:12:46.82,0:12:49.95,EN,,0,0,0,,So m is going to be the product that I'm accumulating.\nDialogue: 0,0:12:51.58,0:12:52.62,EN,,0,0,0,,m is the product.\nDialogue: 0,0:12:57.97,0:13:00.17,EN,,0,0,0,,And the count I'm going to increase by one.\nDialogue: 0,0:13:04.62,0:13:10.97,EN,,0,0,0,,Plus, ITER, ELSE, COND, define.\nDialogue: 0,0:13:11.95,0:13:13.04,EN,,0,0,0,,I'm going to start this up.\nDialogue: 0,0:13:17.16,0:13:19.79,EN,,0,0,0,,And these days, you should have no trouble reading something like this.\nDialogue: 0,0:13:20.86,0:13:25.15,EN,,0,0,0,,What I have here is a product there being accumulated and a counter.\nDialogue: 0,0:13:26.48,0:13:28.46,EN,,0,0,0,,I start them up both at one.\nDialogue: 0,0:13:28.89,0:13:30.92,EN,,0,0,0,,I'm going to buzz the counter up,\nDialogue: 0,0:13:30.92,0:13:33.12,EN,,0,0,0,,i goes to i plus one every time around.\nDialogue: 0,0:13:34.56,0:13:37.47,EN,,0,0,0,,But that's only way our putting a time on the process,\nDialogue: 0,0:13:38.48,0:13:40.04,EN,,0,0,0,,each of this is just a set of truths,\nDialogue: 0,0:13:40.49,0:13:41.34,EN,,0,0,0,,true rules.\nDialogue: 0,0:13:42.81,0:13:46.13,EN,,0,0,0,,And m is going to get a new values of i and m,\nDialogue: 0,0:13:46.13,0:13:47.82,EN,,0,0,0,,i times m each time around,\nDialogue: 0,0:13:48.68,0:13:50.48,EN,,0,0,0,,and eventually i is going to be bigger than n,\nDialogue: 0,0:13:50.49,0:13:52.06,EN,,0,0,0,,in which case, the answer's going to be m.\nDialogue: 0,0:13:52.67,0:13:54.80,EN,,0,0,0,,Now, I'm speaking to you, use time in this.\nDialogue: 0,0:13:55.68,0:13:57.45,EN,,0,0,0,,That's just because I know how the computer works.\nDialogue: 0,0:13:58.25,0:13:59.24,EN,,0,0,0,,But I didn't have to.\nDialogue: 0,0:13:59.26,0:14:02.30,EN,,0,0,0,,This could be a purely mathematical description at this point,\nDialogue: 0,0:14:02.30,0:14:03.74,EN,,0,0,0,,because substitution will work for this.\nDialogue: 0,0:14:05.10,0:14:08.14,EN,,0,0,0,,But let's set right down a similar sort of program,\nDialogue: 0,0:14:08.30,0:14:09.95,EN,,0,0,0,,using the same algorithm,\nDialogue: 0,0:14:10.73,0:14:12.11,EN,,0,0,0,,but with assignments.\nDialogue: 0,0:14:15.69,0:14:17.16,EN,,0,0,0,,So this is called the functional version.\nDialogue: 0,0:14:23.72,0:14:25.56,EN,,0,0,0,,I want to write down an imperative version.\nDialogue: 0,0:14:34.48,0:14:35.39,EN,,0,0,0,,Factorial of n.\nDialogue: 0,0:14:35.92,0:14:37.74,EN,,0,0,0,,I'm going to create my two variables.\nDialogue: 0,0:14:40.16,0:14:45.53,EN,,0,0,0,,Let i initialize itself to one,\nDialogue: 0,0:14:46.32,0:14:49.77,EN,,0,0,0,,and m be initialized to one, similar.\nDialogue: 0,0:14:51.15,0:14:52.19,EN,,0,0,0,,We'll create a loop\nDialogue: 0,0:14:59.31,0:15:07.27,EN,,0,0,0,,which has COND greater than i, and if i is greater than n, we're done.\nDialogue: 0,0:15:07.27,0:15:08.87,EN,,0,0,0,,And the result is m,\nDialogue: 0,0:15:08.87,0:15:10.38,EN,,0,0,0,,the product I'm accumulating.\nDialogue: 0,0:15:10.87,0:15:11.77,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:15:15.52,0:15:17.40,EN,,0,0,0,,I'm going to write down three things to do.\nDialogue: 0,0:15:19.26,0:15:27.05,EN,,0,0,0,,I'm going to set! m to the product of i and m,\nDialogue: 0,0:15:29.36,0:15:35.20,EN,,0,0,0,,set! i to the sum of i and one,\nDialogue: 0,0:15:37.85,0:15:39.31,EN,,0,0,0,,and go around the loop again.\nDialogue: 0,0:15:40.41,0:15:43.02,EN,,0,0,0,,Looks very familiar to you FORTRAN programmers.\nDialogue: 0,0:15:44.73,0:15:46.64,EN,,0,0,0,,ELSE, COND, define,\nDialogue: 0,0:15:46.64,0:15:47.88,EN,,0,0,0,,funny syntax though.\nDialogue: 0,0:15:51.13,0:15:52.27,EN,,0,0,0,,Start the loop up,\nDialogue: 0,0:15:56.10,0:15:57.56,EN,,0,0,0,,and that's the program.\nDialogue: 0,0:15:59.15,0:16:00.52,EN,,0,0,0,,Now, this program,\nDialogue: 0,0:16:01.31,0:16:02.49,EN,,0,0,0,,how do we think about it?\nDialogue: 0,0:16:02.71,0:16:04.25,EN,,0,0,0,,Well, let's just say what we're seeing here.\nDialogue: 0,0:16:04.84,0:16:07.47,EN,,0,0,0,,There are two local variables, i and m,\nDialogue: 0,0:16:07.47,0:16:09.02,EN,,0,0,0,,that have been initialized to one.\nDialogue: 0,0:16:10.72,0:16:13.89,EN,,0,0,0,,Every time around the loop, I test to see if i is greater than n,\nDialogue: 0,0:16:13.89,0:16:15.08,EN,,0,0,0,,which is the input argument,\nDialogue: 0,0:16:15.30,0:16:18.14,EN,,0,0,0,,and if so, the result is the product being accumulated in m.\nDialogue: 0,0:16:19.16,0:16:21.21,EN,,0,0,0,,However, if it's not the end of the loop,\nDialogue: 0,0:16:21.21,0:16:22.89,EN,,0,0,0,,if I'm not done,\nDialogue: 0,0:16:23.64,0:16:25.55,EN,,0,0,0,,then what I'm going to do is change the product\nDialogue: 0,0:16:25.84,0:16:28.38,EN,,0,0,0,,to be the result of multiplying i times the current product.\nDialogue: 0,0:16:29.04,0:16:30.68,EN,,0,0,0,,Which is sort of what we were doing here.\nDialogue: 0,0:16:31.42,0:16:32.68,EN,,0,0,0,,Except here I wasn't changing.\nDialogue: 0,0:16:33.63,0:16:35.77,EN,,0,0,0,,I was making another copy,\nDialogue: 0,0:16:36.81,0:16:42.04,EN,,0,0,0,,because the substitution model says, you copy the body of the procedure\nDialogue: 0,0:16:43.08,0:16:45.88,EN,,0,0,0,,with the arguments substituted for the formal parameters.\nDialogue: 0,0:16:46.72,0:16:48.42,EN,,0,0,0,,Here I'm not worried about copying,\nDialogue: 0,0:16:48.42,0:16:50.52,EN,,0,0,0,,here I've changed the value of m.\nDialogue: 0,0:16:51.80,0:16:55.12,EN,,0,0,0,,I also then change the value of i to i plus one,\nDialogue: 0,0:16:55.61,0:16:56.96,EN,,0,0,0,,and go buzzing around.\nDialogue: 0,0:16:58.22,0:17:00.08,EN,,0,0,0,,Seems like essentially the same program,\nDialogue: 0,0:17:00.96,0:17:02.84,EN,,0,0,0,,but there are some ways of making errors here\nDialogue: 0,0:17:02.84,0:17:05.50,EN,,0,0,0,,that didn't exist until today.\nDialogue: 0,0:17:06.14,0:17:07.02,EN,,0,0,0,,For example,\nDialogue: 0,0:17:07.45,0:17:09.40,EN,,0,0,0,,if I were to do the horrible thing\nDialogue: 0,0:17:10.04,0:17:12.14,EN,,0,0,0,,of not being careful in writing my program\nDialogue: 0,0:17:12.64,0:17:16.08,EN,,0,0,0,,and interchange those two assignments,\nDialogue: 0,0:17:17.10,0:17:18.91,EN,,0,0,0,,the program wouldn't compute the same function.\nDialogue: 0,0:17:20.33,0:17:22.87,EN,,0,0,0,,I get a timing error because there's a dependency\nDialogue: 0,0:17:22.87,0:17:27.22,EN,,0,0,0,,that m depends upon having the last value of i.\nDialogue: 0,0:17:27.34,0:17:28.92,EN,,0,0,0,,If I try change i first,\nDialogue: 0,0:17:31.31,0:17:33.77,EN,,0,0,0,,then I've got the wrong value of i when I multiply by m.\nDialogue: 0,0:17:35.96,0:17:38.38,EN,,0,0,0,,It's a bug that wasn't available until this moment,\nDialogue: 0,0:17:38.38,0:17:40.59,EN,,0,0,0,,until we introduced something that had time in it.\nDialogue: 0,0:17:43.44,0:17:44.30,EN,,0,0,0,,So, as I said,\nDialogue: 0,0:17:45.53,0:17:47.39,EN,,0,0,0,,first we need a new model of computation,\nDialogue: 0,0:17:47.39,0:17:50.86,EN,,0,0,0,,and second, we have to be damn good reason for doing this kind of ugly thing.\nDialogue: 0,0:17:52.72,0:17:53.74,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:17:58.83,0:18:00.22,EN,,0,0,0,,Speak loudly, David\nDialogue: 0,0:18:00.40,0:18:03.47,EN,,0,0,0,,AUDIENCE: I'm confused about, we've introduced set now,\nDialogue: 0,0:18:03.90,0:18:06.36,EN,,0,0,0,,but we had let before and define before.\nDialogue: 0,0:18:06.89,0:18:09.70,EN,,0,0,0,,I'm confused about the difference between the three.\nDialogue: 0,0:18:09.70,0:18:13.25,EN,,0,0,0,,Wouldn't define work in the same situation as set!\nDialogue: 0,0:18:13.98,0:18:14.83,EN,,0,0,0,,if you introduced it a bit?\nDialogue: 0,0:18:14.83,0:18:19.31,EN,,0,0,0,,PROFESSOR: No, define is intended for setting something once the first time,\nDialogue: 0,0:18:19.31,0:18:21.36,EN,,0,0,0,,for making it, OK?\nDialogue: 0,0:18:22.08,0:18:24.70,EN,,0,0,0,,You've never seen me write on a blackboard\nDialogue: 0,0:18:25.60,0:18:26.94,EN,,0,0,0,,two defines in a row\nDialogue: 0,0:18:27.08,0:18:32.08,EN,,0,0,0,,whose intention was to change the old value of some variable to a new one.\nDialogue: 0,0:18:32.08,0:18:34.51,EN,,0,0,0,,AUDIENCE: Is that by convention or--\nDialogue: 0,0:18:34.51,0:18:36.35,EN,,0,0,0,,PROFESSOR: No, it's intention.\nDialogue: 0,0:18:36.35,0:18:38.92,EN,,0,0,0,,Okay? The answer is,\nDialogue: 0,0:18:39.69,0:18:40.84,EN,,0,0,0,,that, for example,\nDialogue: 0,0:18:40.84,0:18:42.27,EN,,0,0,0,,internal to a procedure,\nDialogue: 0,0:18:43.20,0:18:45.92,EN,,0,0,0,,two defines in a row are illegal,\nDialogue: 0,0:18:46.68,0:18:48.57,EN,,0,0,0,,two defines in a row of the same variable.\nDialogue: 0,0:18:50.24,0:18:51.74,EN,,0,0,0,,x can't be defined twice.\nDialogue: 0,0:18:51.74,0:18:55.20,EN,,0,0,0,,Whether or not a system catches that error is a different question,\nDialogue: 0,0:18:55.93,0:18:57.88,EN,,0,0,0,,but I legislate to you\nDialogue: 0,0:18:58.12,0:19:00.64,EN,,0,0,0,,that define happens once on anything.\nDialogue: 0,0:19:00.73,0:19:02.64,EN,,0,0,0,,Now, indeed, in interactive debugging,\nDialogue: 0,0:19:03.37,0:19:07.48,EN,,0,0,0,,we intend that you interacting with your computer will redefine things,\nDialogue: 0,0:19:08.19,0:19:11.21,EN,,0,0,0,,and so there's a special exception made for interactive debugging.\nDialogue: 0,0:19:11.82,0:19:16.48,EN,,0,0,0,,But define is intended to mean to set up something\nDialogue: 0,0:19:18.14,0:19:20.96,EN,,0,0,0,,which will be forever that value after that point.\nDialogue: 0,0:19:22.05,0:19:24.54,EN,,0,0,0,,It's as if all the defines were done at the beginning.\nDialogue: 0,0:19:26.09,0:19:30.92,EN,,0,0,0,,In fact, the only legal place to put a define in Scheme internal to a procedure\nDialogue: 0,0:19:31.02,0:19:33.36,EN,,0,0,0,,is just at the beginning of a lambda expression,\nDialogue: 0,0:19:34.47,0:19:37.66,EN,,0,0,0,,which is the beginning of the body of a procedure.\nDialogue: 0,0:19:40.40,0:19:45.80,EN,,0,0,0,,Now, let of course does nothing like either of that.\nDialogue: 0,0:19:48.09,0:19:49.55,EN,,0,0,0,,I mean, if you look at what's happening with a let,\nDialogue: 0,0:19:50.17,0:19:52.13,EN,,0,0,0,,this happens again exactly once.\nDialogue: 0,0:19:52.13,0:19:55.82,EN,,0,0,0,,It sets up a context where i and m are values one and one.\nDialogue: 0,0:19:56.83,0:20:00.57,EN,,0,0,0,,That context exists throughout this scope,\nDialogue: 0,0:20:01.31,0:20:02.80,EN,,0,0,0,,this region of the program.\nDialogue: 0,0:20:04.99,0:20:10.12,EN,,0,0,0,,However, you don't think of that let as setting i again.\nDialogue: 0,0:20:11.04,0:20:12.16,EN,,0,0,0,,It doesn't change it.\nDialogue: 0,0:20:12.16,0:20:14.01,EN,,0,0,0,,i never changes because of the let.\nDialogue: 0,0:20:15.28,0:20:16.81,EN,,0,0,0,,i gets created because of let.\nDialogue: 0,0:20:18.51,0:20:19.29,EN,,0,0,0,,In fact,\nDialogue: 0,0:20:19.73,0:20:21.42,EN,,0,0,0,,the let is a very simple idea.\nDialogue: 0,0:20:22.24,0:20:23.59,EN,,0,0,0,,Let does nothing more,\nDialogue: 0,0:20:23.59,0:20:31.62,EN,,0,0,0,,Let a variable one to have value one\nDialogue: 0,0:20:31.62,0:20:33.50,EN,,0,0,0,,I'll write this down a little bit more neatly;\nDialogue: 0,0:20:37.16,0:20:43.73,EN,,0,0,0,,Let's write, var one have value, the value of expression e1,\nDialogue: 0,0:20:43.73,0:20:47.36,EN,,0,0,0,,and variable two, have this value of the expression e2,\nDialogue: 0,0:20:48.14,0:20:49.74,EN,,0,0,0,,in an expression e3,\nDialogue: 0,0:20:51.60,0:21:05.80,EN,,0,0,0,,is the same thing as a procedure of var one and var two, the formal parameters,\nDialogue: 0,0:21:06.94,0:21:08.96,EN,,0,0,0,,and e3 being the body,\nDialogue: 0,0:21:10.91,0:21:14.00,EN,,0,0,0,,where var one is bound to the value of e1,\nDialogue: 0,0:21:14.27,0:21:16.91,EN,,0,0,0,,and var two gets the value of e2.\nDialogue: 0,0:21:19.53,0:21:23.26,EN,,0,0,0,,So this is, in fact, a perfectly understandable thing from a substitution point of view.\nDialogue: 0,0:21:24.89,0:21:27.95,EN,,0,0,0,,This is really the same expression written in two different ways.\nDialogue: 0,0:21:31.69,0:21:33.50,EN,,0,0,0,,In fact, the way the actual system works\nDialogue: 0,0:21:33.63,0:21:35.82,EN,,0,0,0,,is this gets translated into this before anything happens.\nDialogue: 0,0:21:37.64,0:21:41.77,EN,,0,0,0,,AUDIENCE: OK, I'm still unclear as then what makes the difference between a let and a define. They could--\nDialogue: 0,0:21:41.77,0:21:44.30,EN,,0,0,0,,PROFESSOR: A define is a syntactic sugar,\nDialogue: 0,0:21:44.62,0:21:49.10,EN,,0,0,0,,whereby, essentially a bunch of variables get created by lets and then set up once.\nDialogue: 0,0:21:57.10,0:21:59.74,EN,,0,0,0,,OK, time for the first break, I think. Thank you.\nDialogue: 0,0:22:02.52,0:22:12.84,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:22:12.84,0:22:17.84,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:22:48.81,0:22:52.67,EN,,0,0,0,,By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:22:52.67,0:22:56.52,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:22:56.52,0:23:00.59,EN,,0,0,0,,Assignment, State, and Side-effects\nDialogue: 0,0:23:04.28,0:23:06.11,EN,,0,0,0,,Well let's see.\nDialogue: 0,0:23:06.44,0:23:09.08,EN,,0,0,0,,I now have to rebuild the model of computation,\nDialogue: 0,0:23:09.77,0:23:14.16,EN,,0,0,0,,so you understand how some such mechanical mechanism could work\nDialogue: 0,0:23:14.91,0:23:16.46,EN,,0,0,0,,that can do what we've just talked about.\nDialogue: 0,0:23:17.53,0:23:21.39,EN,,0,0,0,,I just recently destroyed your substitution model.\nDialogue: 0,0:23:22.62,0:23:26.03,EN,,0,0,0,,Unfortunately, this model is significantly more complicated than the substitution model.\nDialogue: 0,0:23:26.62,0:23:27.93,EN,,0,0,0,,It's called the environment model.\nDialogue: 0,0:23:29.02,0:23:31.20,EN,,0,0,0,,And I'm going to have to introduce some terminology,\nDialogue: 0,0:23:32.03,0:23:34.51,EN,,0,0,0,,which is very good terminology for you to know anyway.\nDialogue: 0,0:23:34.51,0:23:35.74,EN,,0,0,0,,It's about names.\nDialogue: 0,0:23:36.51,0:23:39.63,EN,,0,0,0,,And we're going to give names to the kinds of names things have\nDialogue: 0,0:23:40.00,0:23:41.31,EN,,0,0,0,,and the way those names are used.\nDialogue: 0,0:23:42.48,0:23:47.94,EN,,0,0,0,,So this is a meta-description, if you will.\nDialogue: 0,0:23:48.56,0:23:50.85,EN,,0,0,0,,Anyway, there is a pile of an unfortunate terminology here,\nDialogue: 0,0:23:50.85,0:23:53.76,EN,,0,0,0,,but we're going to need this to understand what's called the environment model.\nDialogue: 0,0:23:54.70,0:23:57.53,EN,,0,0,0,,We're about to do a little bit of boring, dog-work here.\nDialogue: 0,0:23:58.04,0:24:01.58,EN,,0,0,0,,Let's look at the first transparency.\nDialogue: 0,0:24:02.25,0:24:06.97,EN,,0,0,0,,And we see a description of a word called bound.\nDialogue: 0,0:24:08.80,0:24:11.00,EN,,0,0,0,,And we're going to say that a variable, v,\nDialogue: 0,0:24:11.00,0:24:12.91,EN,,0,0,0,,is bound in an expression, e,\nDialogue: 0,0:24:13.41,0:24:21.52,EN,,0,0,0,,if the meaning of e is unchanged by the uniform replacement of a variable w,\nDialogue: 0,0:24:21.56,0:24:24.28,EN,,0,0,0,,not occurrent if for every occurrence of v in e.\nDialogue: 0,0:24:25.69,0:24:27.00,EN,,0,0,0,,Now that's a long sentence,\nDialogue: 0,0:24:27.37,0:24:29.96,EN,,0,0,0,,so, I think, I'm going to have to say a little bit about that\nDialogue: 0,0:24:29.98,0:24:32.62,EN,,0,0,0,,before we even fool around at all here.\nDialogue: 0,0:24:33.42,0:24:35.28,EN,,0,0,0,,Bound variables we're talking about here.\nDialogue: 0,0:24:44.16,0:24:45.56,EN,,0,0,0,,And you've seen lots of them.\nDialogue: 0,0:24:46.07,0:24:48.17,EN,,0,0,0,,You may not know that you've seen lots of them.\nDialogue: 0,0:24:48.24,0:24:52.24,EN,,0,0,0,,Well, I suppose in your logic, you saw a logical variables like,\nDialogue: 0,0:24:53.27,0:25:00.11,EN,,0,0,0,,for every x there exists a y such that p is true of x and y from your calculus class.\nDialogue: 0,0:25:02.88,0:25:05.82,EN,,0,0,0,,This variable, x, and this variable, y, are bound,\nDialogue: 0,0:25:07.08,0:25:07.92,EN,,0,0,0,,because,\nDialogue: 0,0:25:08.33,0:25:09.98,EN,,0,0,0,,the meaning of this expression\nDialogue: 0,0:25:09.98,0:25:15.61,EN,,0,0,0,,does not depend upon the particular letters I used to describe x and y.\nDialogue: 0,0:25:16.49,0:25:19.18,EN,,0,0,0,,If I were to change the w for x,\nDialogue: 0,0:25:19.84,0:25:25.68,EN,,0,0,0,,then said for every w there exists a y such that p is true of w and y,\nDialogue: 0,0:25:25.98,0:25:27.08,EN,,0,0,0,,it would be the same sentence.\nDialogue: 0,0:25:29.44,0:25:30.34,EN,,0,0,0,,That's what it means.\nDialogue: 0,0:25:30.34,0:25:34.89,EN,,0,0,0,,Or another case of this that you've seen is integral say,\nDialogue: 0,0:25:35.40,0:25:42.65,EN,,0,0,0,,from 0 to one of dx over one plus x square.\nDialogue: 0,0:25:46.03,0:25:47.92,EN,,0,0,0,,Well that's something you see all the time.\nDialogue: 0,0:25:47.92,0:25:50.92,EN,,0,0,0,,And this x is a bound variable.\nDialogue: 0,0:25:52.06,0:25:53.79,EN,,0,0,0,,If I change that to a t,\nDialogue: 0,0:25:54.15,0:25:56.25,EN,,0,0,0,,the expression is still the same thing.\nDialogue: 0,0:25:58.06,0:26:02.76,EN,,0,0,0,,This is a 1/4 of the arctan of one or something here, something like that.\nDialogue: 0,0:26:04.70,0:26:06.01,EN,,0,0,0,,Yes, that's the arctan of one.\nDialogue: 0,0:26:06.62,0:26:08.76,EN,,0,0,0,,So bound variables are actually fairly common,\nDialogue: 0,0:26:09.08,0:26:12.36,EN,,0,0,0,,for those of you who have played a bit with mathematics.\nDialogue: 0,0:26:13.26,0:26:17.47,EN,,0,0,0,,Well, let's go into the programming world.\nDialogue: 0,0:26:19.02,0:26:21.36,EN,,0,0,0,,Instead of the quantifier being something like,\nDialogue: 0,0:26:22.03,0:26:24.06,EN,,0,0,0,,for every, or there exists, or integral,\nDialogue: 0,0:26:24.06,0:26:26.43,EN,,0,0,0,,a quantifier is a symbol that binds a variable.\nDialogue: 0,0:26:27.47,0:26:28.99,EN,,0,0,0,,And we are going to use the quantifier lambda\nDialogue: 0,0:26:29.79,0:26:31.80,EN,,0,0,0,,as being the essential thing that binds variables.\nDialogue: 0,0:26:33.80,0:26:36.12,EN,,0,0,0,,And so we have some nice examples here\nDialogue: 0,0:26:36.59,0:26:44.14,EN,,0,0,0,,like that procedure of one argument y which does the following thing.\nDialogue: 0,0:26:44.14,0:26:46.96,EN,,0,0,0,,It calls the procedure of one argument x,\nDialogue: 0,0:26:47.87,0:26:51.13,EN,,0,0,0,,which multiplies x by y,\nDialogue: 0,0:26:52.88,0:26:54.52,EN,,0,0,0,,and applies that to three.\nDialogue: 0,0:26:58.76,0:27:01.66,EN,,0,0,0,,That procedure has the property there of two bound variables in it,\nDialogue: 0,0:27:02.01,0:27:02.92,EN,,0,0,0,,x and y\nDialogue: 0,0:27:04.83,0:27:07.47,EN,,0,0,0,,This quantifier, lambda here, binds this y,\nDialogue: 0,0:27:07.91,0:27:10.78,EN,,0,0,0,,and this quantifier, lambda, binds that x.\nDialogue: 0,0:27:12.11,0:27:17.05,EN,,0,0,0,,Because, if I were to take an arbitrary symbol does not occur in this expression like w\nDialogue: 0,0:27:17.98,0:27:21.04,EN,,0,0,0,,and replace all y's with w's in this expression,\nDialogue: 0,0:27:21.36,0:27:22.75,EN,,0,0,0,,the expression is still the same,\nDialogue: 0,0:27:23.66,0:27:24.80,EN,,0,0,0,,the same procedure.\nDialogue: 0,0:27:26.22,0:27:27.41,EN,,0,0,0,,And this is an important idea.\nDialogue: 0,0:27:27.41,0:27:29.64,EN,,0,0,0,,The reason why we had such things like that\nDialogue: 0,0:27:30.20,0:27:31.41,EN,,0,0,0,,is a kind of modularity.\nDialogue: 0,0:27:31.41,0:27:32.86,EN,,0,0,0,,If two people are writing programs,\nDialogue: 0,0:27:34.03,0:27:35.26,EN,,0,0,0,,and they work together,\nDialogue: 0,0:27:35.26,0:27:40.56,EN,,0,0,0,,it shouldn't matter what names they use internal to their own little machines that they're building.\nDialogue: 0,0:27:42.83,0:27:44.67,EN,,0,0,0,,And so, what I'm really telling you there,\nDialogue: 0,0:27:45.44,0:27:46.75,EN,,0,0,0,,is that, for example,\nDialogue: 0,0:27:46.84,0:27:51.26,EN,,0,0,0,,this is equivalent to that procedure of one argument y which\nDialogue: 0,0:27:52.35,0:27:59.23,EN,,0,0,0,,uses that procedure of one argument z which multiplies z by y.\nDialogue: 0,0:28:01.64,0:28:03.53,EN,,0,0,0,,Because nobody cares what I used in here.\nDialogue: 0,0:28:06.36,0:28:07.24,EN,,0,0,0,,It's a nice example.\nDialogue: 0,0:28:08.84,0:28:09.85,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:28:11.07,0:28:14.33,EN,,0,0,0,,I have some variables that are not bound.\nDialogue: 0,0:28:15.23,0:28:15.96,EN,,0,0,0,,And example,\nDialogue: 0,0:28:20.27,0:28:21.76,EN,,0,0,0,,that procedure of one argument x\nDialogue: 0,0:28:22.09,0:28:25.04,EN,,0,0,0,,which multiplies x by y\nDialogue: 0,0:28:27.28,0:28:28.16,EN,,0,0,0,,In this case,\nDialogue: 0,0:28:29.45,0:28:30.75,EN,,0,0,0,,y is not bound.\nDialogue: 0,0:28:32.46,0:28:34.27,EN,,0,0,0,,Supposing y had the value three,\nDialogue: 0,0:28:35.26,0:28:36.80,EN,,0,0,0,,and z had the value four,\nDialogue: 0,0:28:38.83,0:28:44.27,EN,,0,0,0,,then this procedure would be the thing that multiplies its argument by three.\nDialogue: 0,0:28:44.86,0:28:47.39,EN,,0,0,0,,If I were to replace every instance of y with z,\nDialogue: 0,0:28:47.52,0:28:51.96,EN,,0,0,0,,I would have a different procedure which multiplies every argument that's given by four.\nDialogue: 0,0:28:53.87,0:28:56.40,EN,,0,0,0,,And, in fact, we have a name for such a variable.\nDialogue: 0,0:28:57.76,0:29:04.01,EN,,0,0,0,,Here, we say that a variable, v, is free in the expression, e,\nDialogue: 0,0:29:04.01,0:29:09.42,EN,,0,0,0,,if the meaning of the expression, e, is changed by the uniform replacement of a variable, w, not occurring in e,\nDialogue: 0,0:29:09.58,0:29:11.15,EN,,0,0,0,,for every occurrence of v and e.\nDialogue: 0,0:29:13.26,0:29:13.71,EN,,0,0,0,,So,\nDialogue: 0,0:29:14.49,0:29:22.76,EN,,0,0,0,,So that's why this variable over here, y, is a free variable.\nDialogue: 0,0:29:29.16,0:29:32.27,EN,,0,0,0,,And so free variables in this expression--\nDialogue: 0,0:29:33.76,0:29:35.18,EN,,0,0,0,,And other examples of that is that\nDialogue: 0,0:29:36.17,0:29:39.32,EN,,0,0,0,,is that procedure of one argument y,\nDialogue: 0,0:29:40.43,0:29:42.00,EN,,0,0,0,,which is just what we had before,\nDialogue: 0,0:29:42.27,0:29:44.60,EN,,0,0,0,,which uses that procedure of one argument x\nDialogue: 0,0:29:45.08,0:29:48.54,EN,,0,0,0,,that multiplies x by y--\nDialogue: 0,0:29:51.40,0:29:52.65,EN,,0,0,0,,use that on three.\nDialogue: 0,0:29:57.24,0:30:00.35,EN,,0,0,0,,This procedure has a free variable in it\nDialogue: 0,0:30:00.92,0:30:01.98,EN,,0,0,0,,which is asterisk.\nDialogue: 0,0:30:05.00,0:30:05.89,EN,,0,0,0,,See, because,\nDialogue: 0,0:30:05.89,0:30:08.08,EN,,0,0,0,,if that has a normal meaning of multiplication,\nDialogue: 0,0:30:09.44,0:30:12.78,EN,,0,0,0,,then if I were to replace uniformly all asterisks with pluses,\nDialogue: 0,0:30:14.25,0:30:16.38,EN,,0,0,0,,then the meaning of this expression would change.\nDialogue: 0,0:30:19.34,0:30:20.76,EN,,0,0,0,,That's what you mean by a free variable.\nDialogue: 0,0:30:22.68,0:30:24.81,EN,,0,0,0,,So, so far you've learned some logician words\nDialogue: 0,0:30:25.64,0:30:27.58,EN,,0,0,0,,which describe the way names are used.\nDialogue: 0,0:30:28.94,0:30:31.26,EN,,0,0,0,,Now, we have to do a little bit more playing around here,\nDialogue: 0,0:30:32.96,0:30:33.72,EN,,0,0,0,,a little bit more.\nDialogue: 0,0:30:35.13,0:30:36.22,EN,,0,0,0,,I want to tell you about\nDialogue: 0,0:30:36.81,0:30:39.76,EN,,0,0,0,,about the regions are over which variables are defined.\nDialogue: 0,0:30:42.17,0:30:42.88,EN,,0,0,0,,You see,\nDialogue: 0,0:30:43.37,0:30:45.69,EN,,0,0,0,,we've been very informal about this up till now,\nDialogue: 0,0:30:46.33,0:30:50.16,EN,,0,0,0,,and, of course, many of you have probably understood very clearly or most of you,\nDialogue: 0,0:30:50.36,0:30:52.84,EN,,0,0,0,,that the x that's being declared here\nDialogue: 0,0:30:53.64,0:30:55.18,EN,,0,0,0,,is defined only in here.\nDialogue: 0,0:30:58.28,0:31:00.91,EN,,0,0,0,,This x is the defined only in here,\nDialogue: 0,0:31:01.61,0:31:04.33,EN,,0,0,0,,and this y is defined only in here.\nDialogue: 0,0:31:07.10,0:31:09.16,EN,,0,0,0,,We have a name for such an idea. It's called a scope.\nDialogue: 0,0:31:11.61,0:31:13.58,EN,,0,0,0,,And let me give you another piece of terminology.\nDialogue: 0,0:31:14.70,0:31:15.77,EN,,0,0,0,,It's a long story.\nDialogue: 0,0:31:15.96,0:31:17.64,EN,,0,0,0,,If x is a bound variable in e,\nDialogue: 0,0:31:18.16,0:31:20.24,EN,,0,0,0,,then there is a lambda expression where it is bound.\nDialogue: 0,0:31:20.89,0:31:24.91,EN,,0,0,0,,So the only way you can get a bound variable ultimately is by lambda expression.\nDialogue: 0,0:31:24.91,0:31:25.96,EN,,0,0,0,,Then you may worry,\nDialogue: 0,0:31:26.22,0:31:29.05,EN,,0,0,0,,does define quite an exception to this?\nDialogue: 0,0:31:29.64,0:31:32.92,EN,,0,0,0,,And it turns out, we could always arrange things so you don't need any defines.\nDialogue: 0,0:31:32.92,0:31:33.96,EN,,0,0,0,,And we'll see that in a while.\nDialogue: 0,0:31:34.24,0:31:35.72,EN,,0,0,0,,It's a very magical thing.\nDialogue: 0,0:31:36.54,0:31:38.40,EN,,0,0,0,,So define really can go away.\nDialogue: 0,0:31:38.68,0:31:41.55,EN,,0,0,0,,The really, only thing that makes names is lambda .\nDialogue: 0,0:31:42.64,0:31:43.40,EN,,0,0,0,,That's its job.\nDialogue: 0,0:31:44.30,0:31:46.23,EN,,0,0,0,,And what's so amazing about a lot of things\nDialogue: 0,0:31:46.23,0:31:47.87,EN,,0,0,0,,is you can compute with only lambda.\nDialogue: 0,0:31:48.73,0:31:49.58,EN,,0,0,0,,But, in any case,\nDialogue: 0,0:31:51.74,0:31:55.76,EN,,0,0,0,,a lambda expression has a place where it declares a variable.\nDialogue: 0,0:31:55.76,0:31:57.10,EN,,0,0,0,,We call it the formal parameter list\nDialogue: 0,0:31:58.94,0:32:00.56,EN,,0,0,0,,and we say or the bound variable list.\nDialogue: 0,0:32:01.26,0:32:04.51,EN,,0,0,0,,We say that the lambda expression binds -- so it's a verb\nDialogue: 0,0:32:05.02,0:32:07.34,EN,,0,0,0,,--binds the variables declared in it's bound variable list.\nDialogue: 0,0:32:08.59,0:32:12.48,EN,,0,0,0,,In addition, those parts of the expression where the variable is defined,\nDialogue: 0,0:32:13.23,0:32:15.23,EN,,0,0,0,,which was declared by some declaration\nDialogue: 0,0:32:15.56,0:32:19.26,EN,,0,0,0,,is called the scope of that variable.\nDialogue: 0,0:32:20.44,0:32:21.92,EN,,0,0,0,,So these are scopes.\nDialogue: 0,0:32:22.25,0:32:23.68,EN,,0,0,0,,This is the scope of y.\nDialogue: 0,0:32:27.16,0:32:28.54,EN,,0,0,0,,And this is the scope of x--\nDialogue: 0,0:32:33.10,0:32:34.03,EN,,0,0,0,,that sort of thing.\nDialogue: 0,0:32:41.32,0:32:42.08,EN,,0,0,0,,OK,\nDialogue: 0,0:32:43.93,0:32:45.63,EN,,0,0,0,,well, now we have enough terminology\nDialogue: 0,0:32:46.60,0:32:51.76,EN,,0,0,0,,to begin to understand how to make a new model for computation\nDialogue: 0,0:32:51.96,0:32:53.77,EN,,0,0,0,,because the key thing going on here\nDialogue: 0,0:32:54.94,0:32:57.00,EN,,0,0,0,,is that we destroyed the substitution model,\nDialogue: 0,0:32:57.18,0:32:58.38,EN,,0,0,0,,and we now have to have a model\nDialogue: 0,0:32:58.62,0:33:02.32,EN,,0,0,0,,that represents the names as referring to places.\nDialogue: 0,0:33:03.93,0:33:05.34,EN,,0,0,0,,Because if we are going to change something,\nDialogue: 0,0:33:05.98,0:33:07.47,EN,,0,0,0,,then we have a place where it's stored.\nDialogue: 0,0:33:09.56,0:33:10.35,EN,,0,0,0,,You see,\nDialogue: 0,0:33:10.83,0:33:13.31,EN,,0,0,0,,if a name only refers to a value,\nDialogue: 0,0:33:14.04,0:33:16.36,EN,,0,0,0,,and if I tried to change the name's meaning,\nDialogue: 0,0:33:16.73,0:33:20.32,EN,,0,0,0,,well, that's not clear.\nDialogue: 0,0:33:20.32,0:33:24.68,EN,,0,0,0,,There's nothing that is the place that that name referred to.\nDialogue: 0,0:33:24.99,0:33:25.80,EN,,0,0,0,,How am I really saying it?\nDialogue: 0,0:33:25.92,0:33:29.54,EN,,0,0,0,,There're nothing shared among all of the instances of that name.\nDialogue: 0,0:33:29.87,0:33:31.68,EN,,0,0,0,,And what we really mean, by a name,\nDialogue: 0,0:33:31.68,0:33:32.97,EN,,0,0,0,,is that we find something out.\nDialogue: 0,0:33:34.33,0:33:36.36,EN,,0,0,0,,We've given something a name, and you have it,\nDialogue: 0,0:33:36.73,0:33:39.06,EN,,0,0,0,,and you have it, because I'm given you a reference to it,\nDialogue: 0,0:33:39.06,0:33:40.44,EN,,0,0,0,,and I've given you a reference to it.\nDialogue: 0,0:33:41.02,0:33:42.30,EN,,0,0,0,,And we'll see a lot about that.\nDialogue: 0,0:33:43.61,0:33:45.21,EN,,0,0,0,,So let me tell you about environments.\nDialogue: 0,0:33:46.19,0:33:48.76,EN,,0,0,0,,I need the overhead projection machine,\nDialogue: 0,0:33:49.31,0:33:49.98,EN,,0,0,0,,thank you.\nDialogue: 0,0:33:52.19,0:33:53.02,EN,,0,0,0,,And so here\nDialogue: 0,0:33:55.48,0:34:00.40,EN,,0,0,0,,is a bunch of environment structures.\nDialogue: 0,0:34:01.53,0:34:05.76,EN,,0,0,0,,An environment is a way of doing substitutions virtually.\nDialogue: 0,0:34:06.38,0:34:07.89,EN,,0,0,0,,It represents a place\nDialogue: 0,0:34:07.89,0:34:11.39,EN,,0,0,0,,where something is stored which is the substitutions that you haven't done.\nDialogue: 0,0:34:13.34,0:34:16.50,EN,,0,0,0,,It's a place where everything accumulates,\nDialogue: 0,0:34:16.50,0:34:21.13,EN,,0,0,0,,where the names of the variables are associated with the values they have\nDialogue: 0,0:34:21.79,0:34:22.56,EN,,0,0,0,,such that,\nDialogue: 0,0:34:22.75,0:34:25.90,EN,,0,0,0,,when you say, what dose this name mean,\nDialogue: 0,0:34:25.90,0:34:27.40,EN,,0,0,0,,you look it up in an environment.\nDialogue: 0,0:34:28.08,0:34:29.48,EN,,0,0,0,,So an environment is a function,\nDialogue: 0,0:34:30.80,0:34:31.48,EN,,0,0,0,,or a table,\nDialogue: 0,0:34:32.22,0:34:33.24,EN,,0,0,0,,or something like that.\nDialogue: 0,0:34:33.24,0:34:34.89,EN,,0,0,0,,But it's a structured sort of table.\nDialogue: 0,0:34:35.76,0:34:37.39,EN,,0,0,0,,It's made out of things called frames.\nDialogue: 0,0:34:41.13,0:34:44.46,EN,,0,0,0,,Frames are pieces of environment,\nDialogue: 0,0:34:44.89,0:34:46.01,EN,,0,0,0,,and they are chained together,\nDialogue: 0,0:34:47.07,0:34:48.19,EN,,0,0,0,,in some nice ways,\nDialogue: 0,0:34:49.00,0:34:52.09,EN,,0,0,0,,by what's called parent links or something like that.\nDialogue: 0,0:34:54.03,0:34:55.02,EN,,0,0,0,,So here,\nDialogue: 0,0:34:55.64,0:34:57.62,EN,,0,0,0,,we have an environment structure\nDialogue: 0,0:34:57.62,0:35:04.22,EN,,0,0,0,,consisting of three environments, basically, A, B, and C.\nDialogue: 0,0:35:05.10,0:35:07.63,EN,,0,0,0,,d is also an environment, but it's the same one,\nDialogue: 0,0:35:08.88,0:35:10.17,EN,,0,0,0,,they share.\nDialogue: 0,0:35:11.45,0:35:13.96,EN,,0,0,0,,And that's the essence of assignment.\nDialogue: 0,0:35:14.40,0:35:16.10,EN,,0,0,0,,If I change a variable,\nDialogue: 0,0:35:16.10,0:35:19.80,EN,,0,0,0,,a value of a valuable that lives here, like that one,\nDialogue: 0,0:35:19.80,0:35:23.50,EN,,0,0,0,,it should be visible from all places that you're looking at it from.\nDialogue: 0,0:35:23.50,0:35:24.84,EN,,0,0,0,,Take this one, x.\nDialogue: 0,0:35:24.84,0:35:28.19,EN,,0,0,0,,If I change the x to four,\nDialogue: 0,0:35:28.19,0:35:30.19,EN,,0,0,0,,it's visible from other places.\nDialogue: 0,0:35:30.19,0:35:32.19,EN,,0,0,0,,But I'm not going to worry about that right now.\nDialogue: 0,0:35:32.19,0:35:33.84,EN,,0,0,0,,We're going to talk a lot about that in a little while.\nDialogue: 0,0:35:34.56,0:35:35.53,EN,,0,0,0,,What do we have here?\nDialogue: 0,0:35:36.76,0:35:38.84,EN,,0,0,0,,Well, these are called frames. Here is a frame,\nDialogue: 0,0:35:39.40,0:35:40.38,EN,,0,0,0,,here's a frame\nDialogue: 0,0:35:40.76,0:35:41.84,EN,,0,0,0,,and here's a frame.\nDialogue: 0,0:35:43.18,0:35:45.20,EN,,0,0,0,,A is an environment which consists of\nDialogue: 0,0:35:45.20,0:35:47.82,EN,,0,0,0,,the table label which is frame two,\nDialogue: 0,0:35:48.36,0:35:51.05,EN,,0,0,0,,followed by the table labeled frame one.\nDialogue: 0,0:35:52.52,0:35:54.60,EN,,0,0,0,,And, in this environment,\nDialogue: 0,0:35:54.99,0:35:59.68,EN,,0,0,0,,in C, this environment, frame two,\nDialogue: 0,0:36:00.48,0:36:03.26,EN,,0,0,0,,uh....x and y are bound.\nDialogue: 0,0:36:04.06,0:36:04.78,EN,,0,0,0,,They have values.\nDialogue: 0,0:36:05.26,0:36:07.18,EN,,0,0,0,,Sorry, in frame one\nDialogue: 0,0:36:07.18,0:36:08.28,EN,,0,0,0,,In frame two,\nDialogue: 0,0:36:09.72,0:36:10.83,EN,,0,0,0,,z is bound,\nDialogue: 0,0:36:10.99,0:36:12.17,EN,,0,0,0,,and x is bound,\nDialogue: 0,0:36:12.44,0:36:13.69,EN,,0,0,0,,and y is bound,\nDialogue: 0,0:36:15.24,0:36:17.40,EN,,0,0,0,,but the value of x that we see,\nDialogue: 0,0:36:17.42,0:36:19.04,EN,,0,0,0,,looking from this point of view,\nDialogue: 0,0:36:20.01,0:36:21.74,EN,,0,0,0,,is this x. It's x is seven,\nDialogue: 0,0:36:22.36,0:36:24.84,EN,,0,0,0,,rather than this one which is three.\nDialogue: 0,0:36:24.84,0:36:27.61,EN,,0,0,0,,We say that this x shadows this x.\nDialogue: 0,0:36:31.05,0:36:32.49,EN,,0,0,0,,From environment three--\nDialogue: 0,0:36:33.44,0:36:34.45,EN,,0,0,0,,from frame three,\nDialogue: 0,0:36:34.45,0:36:35.73,EN,,0,0,0,,from environment b,\nDialogue: 0,0:36:35.73,0:36:37.18,EN,,0,0,0,,which refers to frame three,\nDialogue: 0,0:36:37.45,0:36:42.12,EN,,0,0,0,,we have variables m and y bound and also x.\nDialogue: 0,0:36:44.84,0:36:46.97,EN,,0,0,0,,This y shadow this one.\nDialogue: 0,0:36:48.65,0:36:51.00,EN,,0,0,0,,So the value, looking from this point of view,\nDialogue: 0,0:36:51.10,0:36:52.65,EN,,0,0,0,,of y is two.\nDialogue: 0,0:36:53.45,0:36:55.28,EN,,0,0,0,,The value for looking from this point of view\nDialogue: 0,0:36:55.28,0:36:58.64,EN,,0,0,0,,and m is one. And the value, looking from this point of view, of x is three.\nDialogue: 0,0:37:02.22,0:37:03.15,EN,,0,0,0,,So there we have\nDialogue: 0,0:37:03.15,0:37:05.52,EN,,0,0,0,,a very simple environment structure made out of frames.\nDialogue: 0,0:37:06.38,0:37:09.80,EN,,0,0,0,,These correspond to the applications of procedures.\nDialogue: 0,0:37:10.94,0:37:12.17,EN,,0,0,0,,And we'll see that in a second.\nDialogue: 0,0:37:14.41,0:37:17.60,EN,,0,0,0,,So now I have to make you some other nice little structure that we build.\nDialogue: 0,0:37:20.75,0:37:21.71,EN,,0,0,0,,Next slide,\nDialogue: 0,0:37:22.14,0:37:24.36,EN,,0,0,0,,we see an object,\nDialogue: 0,0:37:24.84,0:37:26.54,EN,,0,0,0,,which I'm going to draw procedures.\nDialogue: 0,0:37:27.93,0:37:28.94,EN,,0,0,0,,This is a procedure.\nDialogue: 0,0:37:30.11,0:37:31.90,EN,,0,0,0,,A procedure is made out of two parts.\nDialogue: 0,0:37:33.10,0:37:34.80,EN,,0,0,0,,It's sort of like a cons.\nDialogue: 0,0:37:37.21,0:37:38.38,EN,,0,0,0,,However, it's the two parts.\nDialogue: 0,0:37:40.84,0:37:44.72,EN,,0,0,0,,The first part refers to some code,\nDialogue: 0,0:37:45.69,0:37:46.94,EN,,0,0,0,,something that can be executed,\nDialogue: 0,0:37:47.42,0:37:50.00,EN,,0,0,0,,a set of instructions, if you will. You can think of it that way.\nDialogue: 0,0:37:50.68,0:37:52.83,EN,,0,0,0,,And the second part is the environment.\nDialogue: 0,0:37:53.88,0:37:55.50,EN,,0,0,0,,The procedure is the whole thing.\nDialogue: 0,0:37:57.16,0:37:58.40,EN,,0,0,0,,And we're going to have to use this\nDialogue: 0,0:37:58.71,0:38:05.16,EN,,0,0,0,,to capture the values of the free variables that occur in the procedure.\nDialogue: 0,0:38:06.17,0:38:08.09,EN,,0,0,0,,If a variable occurs in the procedure\nDialogue: 0,0:38:08.11,0:38:09.92,EN,,0,0,0,,it's either bound in that procedure or free.\nDialogue: 0,0:38:11.10,0:38:11.96,EN,,0,0,0,,If it's bound,\nDialogue: 0,0:38:12.57,0:38:14.56,EN,,0,0,0,,then the value will somehow be easy to find.\nDialogue: 0,0:38:16.11,0:38:18.64,EN,,0,0,0,,It will be in some easy environment to get at.\nDialogue: 0,0:38:18.91,0:38:19.87,EN,,0,0,0,,If it's free,\nDialogue: 0,0:38:20.86,0:38:23.02,EN,,0,0,0,,we're going to have to have something that goes with the procedure\nDialogue: 0,0:38:23.02,0:38:24.81,EN,,0,0,0,,that says where we'll go look for its value.\nDialogue: 0,0:38:27.05,0:38:29.21,EN,,0,0,0,,And the reasons why are not obvious yet,\nDialogue: 0,0:38:29.21,0:38:30.60,EN,,0,0,0,,but will be soon.\nDialogue: 0,0:38:32.32,0:38:34.97,EN,,0,0,0,,So here's a procedure object. It's a composite object\nDialogue: 0,0:38:35.34,0:38:41.64,EN,,0,0,0,,consisting of a piece of code and a environment structure.\nDialogue: 0,0:38:42.72,0:38:45.50,EN,,0,0,0,,Now I will tell you the new rules, the complete new rules,\nDialogue: 0,0:38:46.41,0:38:47.47,EN,,0,0,0,,for evaluation.\nDialogue: 0,0:38:50.54,0:38:52.20,EN,,0,0,0,,The first rule is-- there's only two of them.\nDialogue: 0,0:38:53.20,0:38:55.39,EN,,0,0,0,,These correspond to the substitution model rules.\nDialogue: 0,0:38:57.26,0:38:59.32,EN,,0,0,0,,And the first one has to do with\nDialogue: 0,0:38:59.66,0:39:02.78,EN,,0,0,0,,how do you apply a procedure to its arguments?\nDialogue: 0,0:39:05.28,0:39:08.54,EN,,0,0,0,,Okay, And a procedural object is applied to a set of arguments\nDialogue: 0,0:39:08.96,0:39:10.43,EN,,0,0,0,,by constructing a new frame.\nDialogue: 0,0:39:11.31,0:39:15.76,EN,,0,0,0,,That frame will contain the mapping of the former parameters to the actual parameters\nDialogue: 0,0:39:15.83,0:39:19.48,EN,,0,0,0,,of the arguments that were supplied in the call.\nDialogue: 0,0:39:21.42,0:39:22.20,EN,,0,0,0,,As you know,\nDialogue: 0,0:39:22.31,0:39:26.94,EN,,0,0,0,,when we make up a call to a procedure like lambda x times x y,\nDialogue: 0,0:39:26.94,0:39:29.13,EN,,0,0,0,,and we call that with the argument three,\nDialogue: 0,0:39:30.19,0:39:32.75,EN,,0,0,0,,then we're going to need some mapping of x to three.\nDialogue: 0,0:39:34.19,0:39:37.39,EN,,0,0,0,,It's the same thing as later substituting, if you will\nDialogue: 0,0:39:38.27,0:39:40.30,EN,,0,0,0,,the three for the x in the old model.\nDialogue: 0,0:39:42.00,0:39:44.80,EN,,0,0,0,,So I'm going to build a frame which contains x equals three\nDialogue: 0,0:39:45.15,0:39:46.60,EN,,0,0,0,,as the information in that frame.\nDialogue: 0,0:39:49.12,0:39:49.71,EN,,0,0,0,,Now,\nDialogue: 0,0:39:50.33,0:39:53.31,EN,,0,0,0,,the body of the procedure will then have to be evaluated which is this,\nDialogue: 0,0:39:54.16,0:39:56.44,EN,,0,0,0,,and will be evaluated in an environment\nDialogue: 0,0:39:57.80,0:40:08.03,EN,,0,0,0,,which is constructed by adjoining the new frame that we just made\nDialogue: 0,0:40:08.54,0:40:11.69,EN,,0,0,0,,to the environment which was part of the procedure that we applied.\nDialogue: 0,0:40:13.15,0:40:15.77,EN,,0,0,0,,So I'm going to make a little example of that here.\nDialogue: 0,0:40:19.20,0:40:24.12,EN,,0,0,0,,Supposing I have some environment.\nDialogue: 0,0:40:25.15,0:40:27.23,EN,,0,0,0,,Here's a frame which represents it.\nDialogue: 0,0:40:27.96,0:40:32.19,EN,,0,0,0,,And some procedure-- which I'm going to draw with circles here because it's easier than little triangles--\nDialogue: 0,0:40:33.04,0:40:36.36,EN,,0,0,0,,Ummm.. sorry, those are rhombuses,\nDialogue: 0,0:40:37.66,0:40:40.78,EN,,0,0,0,,rhomboidal little pieces of fruit jelly or something.\nDialogue: 0,0:40:42.68,0:40:45.32,EN,,0,0,0,,So here's a procedure which takes this environment.\nDialogue: 0,0:40:45.95,0:40:48.16,EN,,0,0,0,,And the procedure has a piece of code,\nDialogue: 0,0:40:48.16,0:40:49.68,EN,,0,0,0,,which is a lambda expression,\nDialogue: 0,0:40:50.12,0:40:51.69,EN,,0,0,0,,which binds x and y\nDialogue: 0,0:40:53.15,0:40:56.43,EN,,0,0,0,,and then executes an expression, e.\nDialogue: 0,0:40:57.93,0:40:58.99,EN,,0,0,0,,And this is the procedure.\nDialogue: 0,0:40:59.56,0:41:00.57,EN,,0,0,0,,We'll call it p.\nDialogue: 0,0:41:01.44,0:41:05.79,EN,,0,0,0,,I wish to apply that procedure to three and four.\nDialogue: 0,0:41:06.38,0:41:08.36,EN,,0,0,0,,So I want to do p of three and four.\nDialogue: 0,0:41:09.76,0:41:12.17,EN,,0,0,0,,What I'm going to do, of course, is make a new frame.\nDialogue: 0,0:41:13.15,0:41:14.12,EN,,0,0,0,,I build a frame\nDialogue: 0,0:41:15.24,0:41:18.28,EN,,0,0,0,,which contains x equals three,\nDialogue: 0,0:41:18.84,0:41:20.51,EN,,0,0,0,,and y equals four.\nDialogue: 0,0:41:21.69,0:41:23.48,EN,,0,0,0,,I'm going to connect that frame\nDialogue: 0,0:41:24.27,0:41:25.37,EN,,0,0,0,,to this frame over here.\nDialogue: 0,0:41:27.63,0:41:28.99,EN,,0,0,0,,And then this environment,\nDialogue: 0,0:41:29.68,0:41:30.97,EN,,0,0,0,,with I will call b,\nDialogue: 0,0:41:31.55,0:41:35.02,EN,,0,0,0,,is the environment in which I will evaluate the body of e.\nDialogue: 0,0:41:39.88,0:41:40.33,EN,,0,0,0,,Now,\nDialogue: 0,0:41:41.95,0:41:45.04,EN,,0,0,0,,e may contain references to x and y and other things.\nDialogue: 0,0:41:46.84,0:41:49.95,EN,,0,0,0,,x and y will have values right here.\nDialogue: 0,0:41:50.70,0:41:52.52,EN,,0,0,0,,Other things will have their values here.\nDialogue: 0,0:41:55.05,0:41:56.25,EN,,0,0,0,,How do we get this frame?\nDialogue: 0,0:41:57.26,0:41:59.26,EN,,0,0,0,,That we do by the construction of procedures\nDialogue: 0,0:41:59.61,0:42:00.60,EN,,0,0,0,,which is the other rule.\nDialogue: 0,0:42:02.03,0:42:04.40,EN,,0,0,0,,And I think that's the next slide.\nDialogue: 0,0:42:05.34,0:42:06.12,EN,,0,0,0,,Rule two,\nDialogue: 0,0:42:07.80,0:42:09.90,EN,,0,0,0,,when a lambda expression is evaluated,\nDialogue: 0,0:42:09.90,0:42:11.76,EN,,0,0,0,,relative to a particular environment--\nDialogue: 0,0:42:14.19,0:42:14.40,EN,,0,0,0,,See,\nDialogue: 0,0:42:15.04,0:42:18.12,EN,,0,0,0,,the way I get a procedure is by evaluating the lambda expression.\nDialogue: 0,0:42:18.19,0:42:19.36,EN,,0,0,0,,Here's a lambda expression.\nDialogue: 0,0:42:20.04,0:42:21.12,EN,,0,0,0,,By evaluating it,\nDialogue: 0,0:42:21.90,0:42:23.96,EN,,0,0,0,,I get a procedure which I can apply to three.\nDialogue: 0,0:42:25.08,0:42:26.65,EN,,0,0,0,,Now this lambda expression\nDialogue: 0,0:42:26.65,0:42:30.38,EN,,0,0,0,,is evaluated in an environment where y is defined.\nDialogue: 0,0:42:31.84,0:42:35.84,EN,,0,0,0,,And I want the body of this which contains a free version of y.\nDialogue: 0,0:42:36.39,0:42:38.36,EN,,0,0,0,,y is free in here,\nDialogue: 0,0:42:38.72,0:42:40.38,EN,,0,0,0,,it's bound over the whole thing,\nDialogue: 0,0:42:41.36,0:42:42.75,EN,,0,0,0,,but it's free over here.\nDialogue: 0,0:42:43.32,0:42:46.24,EN,,0,0,0,,I want that y to be this one.\nDialogue: 0,0:42:47.44,0:42:55.13,EN,,0,0,0,,I evaluate this body of this procedure in the environment where y was created.\nDialogue: 0,0:42:55.32,0:42:58.40,EN,,0,0,0,,That's this kind of thing, because that was done by application.\nDialogue: 0,0:42:59.00,0:42:59.63,EN,,0,0,0,,Now,\nDialogue: 0,0:43:00.24,0:43:02.60,EN,,0,0,0,,if I ever want to look up the value of y,\nDialogue: 0,0:43:03.10,0:43:04.09,EN,,0,0,0,,I have to know where it is.\nDialogue: 0,0:43:04.54,0:43:06.42,EN,,0,0,0,,Therefore, this procedural was created,\nDialogue: 0,0:43:06.42,0:43:10.06,EN,,0,0,0,,the creation of the procedure which is the result of evaluating that lambda expression\nDialogue: 0,0:43:10.06,0:43:16.33,EN,,0,0,0,,had better capture a pointer or remember the frame in which y was bound.\nDialogue: 0,0:43:17.92,0:43:19.76,EN,,0,0,0,,So that's what this rule is telling us.\nDialogue: 0,0:43:22.11,0:43:23.13,EN,,0,0,0,,So, for example,\nDialogue: 0,0:43:24.44,0:43:29.32,EN,,0,0,0,,if I happen to be evaluating a lambda expression,\nDialogue: 0,0:43:30.89,0:43:33.32,EN,,0,0,0,,lambda expression in e,\nDialogue: 0,0:43:34.04,0:43:40.46,EN,,0,0,0,,lambda of say, x and y, let's call it g in e,\nDialogue: 0,0:43:41.08,0:43:42.36,EN,,0,0,0,,evaluating that.\nDialogue: 0,0:43:42.97,0:43:46.17,EN,,0,0,0,,all that means is I now construct a procedure object.\nDialogue: 0,0:43:47.10,0:43:48.28,EN,,0,0,0,,e is some environment.\nDialogue: 0,0:43:48.84,0:43:50.94,EN,,0,0,0,,e is something which has a pointer to it.\nDialogue: 0,0:43:51.79,0:43:56.68,EN,,0,0,0,,I construct a procedure object that points up to that environment,\nDialogue: 0,0:43:58.56,0:44:00.11,EN,,0,0,0,,where the code of that\nDialogue: 0,0:44:00.54,0:44:03.24,EN,,0,0,0,,is a lambda expression or whatever that translates into.\nDialogue: 0,0:44:06.24,0:44:07.56,EN,,0,0,0,,And this is the procedure.\nDialogue: 0,0:44:12.38,0:44:14.70,EN,,0,0,0,,So this produces for me-- this -- this\nDialogue: 0,0:44:14.94,0:44:16.37,EN,,0,0,0,,this object here,\nDialogue: 0,0:44:16.37,0:44:18.12,EN,,0,0,0,,this environment pointer,\nDialogue: 0,0:44:18.37,0:44:22.52,EN,,0,0,0,,captures the place where this lambda expression was evaluated,\nDialogue: 0,0:44:22.62,0:44:24.59,EN,,0,0,0,,where the definition was used,\nDialogue: 0,0:44:25.58,0:44:27.40,EN,,0,0,0,,where the definition was used to make a procedure,\nDialogue: 0,0:44:30.32,0:44:31.47,EN,,0,0,0,,to make the procedure.\nDialogue: 0,0:44:32.89,0:44:36.30,EN,,0,0,0,,So it picks up the environment from the place where that procedure was defined,\nDialogue: 0,0:44:37.42,0:44:38.92,EN,,0,0,0,,stores it in the procedure itself,\nDialogue: 0,0:44:39.60,0:44:40.97,EN,,0,0,0,,and then when the procedure is used,\nDialogue: 0,0:44:41.32,0:44:43.47,EN,,0,0,0,,the environment where it was defined is extended\nDialogue: 0,0:44:43.98,0:44:45.07,EN,,0,0,0,,with the new frame.\nDialogue: 0,0:44:48.72,0:44:52.33,EN,,0,0,0,,So this gives us a locus for putting where a variable has a value.\nDialogue: 0,0:44:53.04,0:44:53.96,EN,,0,0,0,,And, for example,\nDialogue: 0,0:44:53.96,0:44:56.81,EN,,0,0,0,,if there are lots of guys pointing in at that environment,\nDialogue: 0,0:44:57.74,0:45:00.33,EN,,0,0,0,,then they share that place.\nDialogue: 0,0:45:01.20,0:45:02.52,EN,,0,0,0,,And we'll see more of that shortly.\nDialogue: 0,0:45:04.01,0:45:05.34,EN,,0,0,0,,Well, now you have a new model\nDialogue: 0,0:45:06.38,0:45:09.92,EN,,0,0,0,,for understanding the execution of programs.\nDialogue: 0,0:45:11.36,0:45:12.78,EN,,0,0,0,,I suppose I'll take questions now,\nDialogue: 0,0:45:13.10,0:45:14.96,EN,,0,0,0,,and then we'll go on and use that for something.\nDialogue: 0,0:45:18.19,0:45:19.52,EN,,0,0,0,,AUDIENCE: Is it right to say then,\nDialogue: 0,0:45:19.52,0:45:23.96,EN,,0,0,0,,the environment is that linked chain of frames starting with--\nDialogue: 0,0:45:23.96,0:45:25.10,EN,,0,0,0,,PROFESSOR: That's right.\nDialogue: 0,0:45:25.48,0:45:26.64,EN,,0,0,0,,AUDIENCE:  working all the way back?\nDialogue: 0,0:45:27.71,0:45:31.45,EN,,0,0,0,,PROFESSOR: Yes, the environment is a sequence of frames linked together.\nDialogue: 0,0:45:32.43,0:45:35.47,EN,,0,0,0,,And the way I like to think about it, it's the pointer to the first one,\nDialogue: 0,0:45:36.88,0:45:38.72,EN,,0,0,0,,because once you've got that you've got them all.\nDialogue: 0,0:45:43.96,0:45:44.65,EN,,0,0,0,,Anybody else?\nDialogue: 0,0:45:45.20,0:45:49.36,EN,,0,0,0,,AUDIENCE: Is it possible to evaluate a procedure or to define a procedure in two different environments\nDialogue: 0,0:45:49.36,0:45:53.20,EN,,0,0,0,,such that it will behave differently, and have pointers to both--\nDialogue: 0,0:45:53.20,0:45:55.77,EN,,0,0,0,,PROFESSOR: Oh, yes. The same procedure is not going to have two different environments.\nDialogue: 0,0:45:56.90,0:45:59.02,EN,,0,0,0,,The same code,\nDialogue: 0,0:45:59.02,0:46:00.82,EN,,0,0,0,,the same lambda expression\nDialogue: 0,0:46:00.82,0:46:03.72,EN,,0,0,0,,can be evaluated in two environments producing two different procedures.\nDialogue: 0,0:46:06.03,0:46:07.18,EN,,0,0,0,,Each procedure--\nDialogue: 0,0:46:07.18,0:46:09.95,EN,,0,0,0,,AUDIENCE: Their definition has the same name. Their operation--\nDialogue: 0,0:46:09.95,0:46:11.92,EN,,0,0,0,,PROFESSOR: The definition is written the same, with the same characters.\nDialogue: 0,0:46:12.56,0:46:14.62,EN,,0,0,0,,I can evaluate that set of characters,\nDialogue: 0,0:46:14.93,0:46:18.14,EN,,0,0,0,,whatever, that list structure that defines,\nDialogue: 0,0:46:18.22,0:46:20.41,EN,,0,0,0,,that is the textual representation.\nDialogue: 0,0:46:20.91,0:46:24.86,EN,,0,0,0,,I can evaluate that in two different environments producing two different procedures.\nDialogue: 0,0:46:25.55,0:46:26.84,EN,,0,0,0,,Each of those procedures\nDialogue: 0,0:46:27.56,0:46:32.19,EN,,0,0,0,,has its own local sets of variables,\nDialogue: 0,0:46:32.34,0:46:33.45,EN,,0,0,0,,and we'll see that right now.\nDialogue: 0,0:46:36.70,0:46:37.36,EN,,0,0,0,,Anybody else?\nDialogue: 0,0:46:42.60,0:46:44.03,EN,,0,0,0,,OK, thank you. Let's take a break.\nDialogue: 0,0:46:47.98,0:46:57.61,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:46:57.61,0:47:02.03,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:47:05.98,0:47:09.69,EN,,0,0,0,,By: Prof. Harold Abelson && Gerald Jay Sussman\nDialogue: 0,0:47:09.69,0:47:13.44,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:47:13.47,0:47:18.84,EN,,0,0,0,,Assignment, State, and Side-effects\nDialogue: 0,0:47:22.67,0:47:25.69,EN,,0,0,0,,Well, now I've done this terrible thing to you.\nDialogue: 0,0:47:26.56,0:47:30.54,EN,,0,0,0,,I've introduced a very complicated thing,\nDialogue: 0,0:47:32.76,0:47:33.42,EN,,0,0,0,,assignment,\nDialogue: 0,0:47:34.51,0:47:38.08,EN,,0,0,0,,which destroys most of the interesting mathematical properties of our programs.\nDialogue: 0,0:47:41.07,0:47:42.46,EN,,0,0,0,,Why should I have done this?\nDialogue: 0,0:47:43.18,0:47:45.02,EN,,0,0,0,,What possible good could this do?\nDialogue: 0,0:47:46.51,0:47:48.86,EN,,0,0,0,,Clearly not a nice thing,\nDialogue: 0,0:47:49.60,0:47:51.23,EN,,0,0,0,,so I better have a good excuse.\nDialogue: 0,0:47:52.83,0:47:54.80,EN,,0,0,0,,Well, let's do a little bit of playing,\nDialogue: 0,0:47:54.80,0:47:58.35,EN,,0,0,0,,first of all, with some very interesting programs that have assignment.\nDialogue: 0,0:47:58.81,0:48:00.88,EN,,0,0,0,,Understand something special about them\nDialogue: 0,0:48:01.42,0:48:02.83,EN,,0,0,0,,that makes them somewhat valuable.\nDialogue: 0,0:48:04.96,0:48:06.70,EN,,0,0,0,,Start with a very simple program\nDialogue: 0,0:48:07.69,0:48:09.28,EN,,0,0,0,,I'm going to call make-counter.\nDialogue: 0,0:48:10.48,0:48:18.19,EN,,0,0,0,,I'm going to define make-counter\nDialogue: 0,0:48:24.17,0:48:28.12,EN,,0,0,0,,to be a procedure of one argument n\nDialogue: 0,0:48:29.23,0:48:32.94,EN,,0,0,0,,which returns as its value a procedure of no arguments--\nDialogue: 0,0:48:34.36,0:48:36.03,EN,,0,0,0,,a procedure that produces a procedure--\nDialogue: 0,0:48:36.84,0:48:44.35,EN,,0,0,0,,which sets n to the increment of n\nDialogue: 0,0:48:47.88,0:48:49.77,EN,,0,0,0,,and returns that value of n.\nDialogue: 0,0:48:55.37,0:48:57.54,EN,,0,0,0,,Now we're going to investigate the behavior of this.\nDialogue: 0,0:48:57.54,0:48:59.02,EN,,0,0,0,,It's a sort of interesting thing.\nDialogue: 0,0:48:59.82,0:49:01.45,EN,,0,0,0,,In order to investigate the behavior,\nDialogue: 0,0:49:01.45,0:49:03.08,EN,,0,0,0,,I have to make an environment model,\nDialogue: 0,0:49:04.11,0:49:05.98,EN,,0,0,0,,because we can't understand this any other way.\nDialogue: 0,0:49:08.65,0:49:09.63,EN,,0,0,0,,So let's just do that.\nDialogue: 0,0:49:10.00,0:49:12.86,EN,,0,0,0,,We start out with some sort of--\nDialogue: 0,0:49:13.24,0:49:15.90,EN,,0,0,0,,let's say there is a global environment that the machine is born with.\nDialogue: 0,0:49:16.13,0:49:17.12,EN,,0,0,0,,Global we'll call it.\nDialogue: 0,0:49:20.03,0:49:24.25,EN,,0,0,0,,And it's going to have in it a bunch of initial things.\nDialogue: 0,0:49:24.44,0:49:25.60,EN,,0,0,0,,We all know what it's got.\nDialogue: 0,0:49:25.72,0:49:30.88,EN,,0,0,0,,It's got things in it like say, plus, and times,\nDialogue: 0,0:49:32.24,0:49:37.26,EN,,0,0,0,,and quotient, and difference, and CAR,\nDialogue: 0,0:49:38.70,0:49:39.74,EN,,0,0,0,,and etcetera,\nDialogue: 0,0:49:41.45,0:49:42.48,EN,,0,0,0,,lots of things.\nDialogue: 0,0:49:42.88,0:49:43.98,EN,,0,0,0,,I don't know what they are,\nDialogue: 0,0:49:44.42,0:49:45.55,EN,,0,0,0,,some various squiggles\nDialogue: 0,0:49:46.08,0:49:48.88,EN,,0,0,0,,that are the things the machine is born with.\nDialogue: 0,0:49:51.21,0:49:53.23,EN,,0,0,0,,And by doing the definition here,\nDialogue: 0,0:49:54.68,0:49:55.76,EN,,0,0,0,,what I plan to do--\nDialogue: 0,0:49:56.32,0:49:57.31,EN,,0,0,0,,Well, what am I doing?\nDialogue: 0,0:49:57.31,0:49:59.58,EN,,0,0,0,,I'm doing this relative to the global environment.\nDialogue: 0,0:49:59.72,0:50:01.29,EN,,0,0,0,,So here's my environment pointer.\nDialogue: 0,0:50:03.72,0:50:06.70,EN,,0,0,0,,In order to do that I have to evaluate this lambda expression.\nDialogue: 0,0:50:08.35,0:50:10.01,EN,,0,0,0,,That means I make a procedure object.\nDialogue: 0,0:50:11.50,0:50:13.26,EN,,0,0,0,,So I'm going to make a procedure object here.\nDialogue: 0,0:50:17.36,0:50:18.68,EN,,0,0,0,,And the procedure object has,\nDialogue: 0,0:50:18.72,0:50:20.49,EN,,0,0,0,,as the place it's defined,\nDialogue: 0,0:50:21.16,0:50:22.35,EN,,0,0,0,,the global environment.\nDialogue: 0,0:50:24.06,0:50:25.79,EN,,0,0,0,,The procedure object contains\nDialogue: 0,0:50:28.16,0:50:31.47,EN,,0,0,0,,some code that represents a procedure of one argument n\nDialogue: 0,0:50:31.96,0:50:35.34,EN,,0,0,0,,which returns a procedure of no arguments which does something.\nDialogue: 0,0:50:38.24,0:50:43.28,EN,,0,0,0,,And the define is a way of changing this environment,\nDialogue: 0,0:50:44.32,0:50:46.73,EN,,0,0,0,,so that I now add to it a make-counter,\nDialogue: 0,0:50:52.28,0:50:55.05,EN,,0,0,0,,a special rule for the special thing defined.\nDialogue: 0,0:50:55.82,0:50:56.94,EN,,0,0,0,,But what that is,\nDialogue: 0,0:50:58.94,0:51:01.96,EN,,0,0,0,,is it gives me that pointer to that procedure.\nDialogue: 0,0:51:03.82,0:51:06.32,EN,,0,0,0,,So now the global environment contains make-counter as well.\nDialogue: 0,0:51:09.28,0:51:11.21,EN,,0,0,0,,Now, we're going to do some operations.\nDialogue: 0,0:51:11.87,0:51:13.50,EN,,0,0,0,,I'm going to use this to make some counters.\nDialogue: 0,0:51:14.99,0:51:16.20,EN,,0,0,0,,We'll see what a counter is.\nDialogue: 0,0:51:17.12,0:51:18.51,EN,,0,0,0,,So let's define\nDialogue: 0,0:51:23.32,0:51:26.65,EN,,0,0,0,,c1 to be a counter beginning at 0.\nDialogue: 0,0:51:35.72,0:51:38.38,EN,,0,0,0,,Well, we know how to do this now, according to the model.\nDialogue: 0,0:51:39.63,0:51:44.33,EN,,0,0,0,,I have to evaluate the expression make-counter in the global environment,\nDialogue: 0,0:51:45.40,0:51:46.27,EN,,0,0,0,,make-counter of 0.\nDialogue: 0,0:51:47.80,0:51:51.10,EN,,0,0,0,,Well, I look up make-counter and see that it's a procedure.\nDialogue: 0,0:51:53.61,0:51:55.29,EN,,0,0,0,,I'm going to have to apply that procedure.\nDialogue: 0,0:51:56.22,0:51:57.74,EN,,0,0,0,,The way I apply the procedure\nDialogue: 0,0:51:58.43,0:51:59.96,EN,,0,0,0,,is by constructing a frame.\nDialogue: 0,0:52:01.80,0:52:03.79,EN,,0,0,0,,Okay? So I construct a frame\nDialogue: 0,0:52:06.59,0:52:10.44,EN,,0,0,0,,which has a value for n in it\nDialogue: 0,0:52:11.77,0:52:12.64,EN,,0,0,0,,which is 0\nDialogue: 0,0:52:14.00,0:52:15.34,EN,,0,0,0,,and the parent environment\nDialogue: 0,0:52:15.87,0:52:19.32,EN,,0,0,0,,is the one which is the environment of definition of make-counter.\nDialogue: 0,0:52:23.93,0:52:28.36,EN,,0,0,0,,So I've made an environment by applying make-counter to 0.\nDialogue: 0,0:52:31.45,0:52:34.40,EN,,0,0,0,,Now, I have to evaluate the body of make-counter,\nDialogue: 0,0:52:34.41,0:52:37.72,EN,,0,0,0,,which is this lambda expression, in that environment.\nDialogue: 0,0:52:40.64,0:52:42.30,EN,,0,0,0,,Well evaluating this body,\nDialogue: 0,0:52:42.76,0:52:44.59,EN,,0,0,0,,this body is a lambda expression.\nDialogue: 0,0:52:46.28,0:52:48.86,EN,,0,0,0,,Evaluate a lambda expression means make a procedure object.\nDialogue: 0,0:52:49.56,0:52:51.00,EN,,0,0,0,,So I'm going to make a procedure object.\nDialogue: 0,0:52:56.76,0:52:58.29,EN,,0,0,0,,And that procedure object has\nDialogue: 0,0:52:58.29,0:53:00.46,EN,,0,0,0,,the environment it was defined in being that,\nDialogue: 0,0:53:04.20,0:53:05.88,EN,,0,0,0,,where n was defined to be 0.\nDialogue: 0,0:53:07.68,0:53:08.80,EN,,0,0,0,,And it has some code,\nDialogue: 0,0:53:08.83,0:53:11.37,EN,,0,0,0,,which is the procedure of no arguments\nDialogue: 0,0:53:11.40,0:53:15.28,EN,,0,0,0,,which does something, then sets something,\nDialogue: 0,0:53:15.28,0:53:16.73,EN,,0,0,0,,and returns n.\nDialogue: 0,0:53:17.88,0:53:18.81,EN,,0,0,0,,And this thing\nDialogue: 0,0:53:19.42,0:53:21.23,EN,,0,0,0,,is going to be the object,\nDialogue: 0,0:53:21.92,0:53:24.67,EN,,0,0,0,,which in the global environment, will have the name c1.\nDialogue: 0,0:53:26.12,0:53:28.33,EN,,0,0,0,,So we construct a name here, c1,\nDialogue: 0,0:53:28.64,0:53:32.14,EN,,0,0,0,,and say that equals that.\nDialogue: 0,0:53:35.48,0:53:37.36,EN,,0,0,0,,Now, but also make another counter,\nDialogue: 0,0:53:43.04,0:53:45.13,EN,,0,0,0,,c2 to be make-counter\nDialogue: 0,0:53:50.94,0:53:52.19,EN,,0,0,0,,say, starting with 10.\nDialogue: 0,0:53:54.25,0:53:55.90,EN,,0,0,0,,Then I do essentially the same thing.\nDialogue: 0,0:53:56.64,0:54:00.40,EN,,0,0,0,,I apply the make-counter procedure, which I got from here,\nDialogue: 0,0:54:00.99,0:54:04.52,EN,,0,0,0,,to make another frame with n being 10.\nDialogue: 0,0:54:05.63,0:54:09.18,EN,,0,0,0,,That frame has the global environment as its parent.\nDialogue: 0,0:54:10.04,0:54:11.80,EN,,0,0,0,,I then construct a procedure\nDialogue: 0,0:54:13.04,0:54:17.63,EN,,0,0,0,,which has that as it's frame of definition.\nDialogue: 0,0:54:18.27,0:54:21.66,EN,,0,0,0,,The code of it is\nDialogue: 0,0:54:21.80,0:54:24.38,EN,,0,0,0,,the procedure of no arguments which does something.\nDialogue: 0,0:54:25.54,0:54:28.60,EN,,0,0,0,,And it does a set, and so on.\nDialogue: 0,0:54:28.60,0:54:31.22,EN,,0,0,0,,And n comes out. Okay?\nDialogue: 0,0:54:31.45,0:54:34.83,EN,,0,0,0,,And c2 is this.\nDialogue: 0,0:54:36.88,0:54:39.32,EN,,0,0,0,,Well, you're already beginning to see something fairly interesting.\nDialogue: 0,0:54:40.17,0:54:41.92,EN,,0,0,0,,There are two n's here.\nDialogue: 0,0:54:42.92,0:54:44.19,EN,,0,0,0,,They are not one n.\nDialogue: 0,0:54:46.14,0:54:48.16,EN,,0,0,0,,Each time I called make-counter,\nDialogue: 0,0:54:48.64,0:54:50.25,EN,,0,0,0,,I made another instance of n.\nDialogue: 0,0:54:52.62,0:54:54.40,EN,,0,0,0,,These are distinct and separate from each other.\nDialogue: 0,0:54:57.79,0:55:00.28,EN,,0,0,0,,Now, let's do some execution, use those counters.\nDialogue: 0,0:55:05.92,0:55:15.00,EN,,0,0,0,,Well, what happens if I say, c1 at this point?\nDialogue: 0,0:55:15.84,0:55:17.34,EN,,0,0,0,,Well, I go over here,\nDialogue: 0,0:55:17.56,0:55:19.98,EN,,0,0,0,,and I say, oh yes, c1 is a procedure.\nDialogue: 0,0:55:20.64,0:55:22.78,EN,,0,0,0,,I'm going to call this procedure on no arguments,\nDialogue: 0,0:55:23.16,0:55:24.96,EN,,0,0,0,,but it has no parameters.\nDialogue: 0,0:55:24.96,0:55:25.63,EN,,0,0,0,,That's right.\nDialogue: 0,0:55:26.97,0:55:27.84,EN,,0,0,0,,What's its body?\nDialogue: 0,0:55:27.96,0:55:30.02,EN,,0,0,0,,Well, I have to look over here, because I didn't write it down.\nDialogue: 0,0:55:30.02,0:55:32.65,EN,,0,0,0,,It said, set n to one plus n\nDialogue: 0,0:55:33.80,0:55:34.89,EN,,0,0,0,,and return n,\nDialogue: 0,0:55:37.12,0:55:38.12,EN,,0,0,0,,increment n.\nDialogue: 0,0:55:38.97,0:55:41.60,EN,,0,0,0,,Well, the n it says is this one.\nDialogue: 0,0:55:43.08,0:55:44.60,EN,,0,0,0,,So I increment that n.\nDialogue: 0,0:55:45.80,0:55:47.00,EN,,0,0,0,,That becomes one,\nDialogue: 0,0:55:48.64,0:55:50.24,EN,,0,0,0,,and I return the value one.\nDialogue: 0,0:55:53.13,0:55:56.49,EN,,0,0,0,,Supposing I then called c2.\nDialogue: 0,0:55:58.38,0:55:59.20,EN,,0,0,0,,Well, what do I do?\nDialogue: 0,0:55:59.23,0:56:03.33,EN,,0,0,0,,I say c2 is this procedure which does the same thing,\nDialogue: 0,0:56:03.33,0:56:04.48,EN,,0,0,0,,but here's the n.\nDialogue: 0,0:56:05.33,0:56:06.57,EN,,0,0,0,,It becomes 11.\nDialogue: 0,0:56:10.97,0:56:14.59,EN,,0,0,0,,And so I have an 11 which is the value.\nDialogue: 0,0:56:15.92,0:56:18.32,EN,,0,0,0,,I then can say, let's try c1 again.\nDialogue: 0,0:56:20.91,0:56:22.56,EN,,0,0,0,,hum, c1 is this,\nDialogue: 0,0:56:23.28,0:56:24.16,EN,,0,0,0,,that's two,\nDialogue: 0,0:56:27.24,0:56:28.30,EN,,0,0,0,,so the answer is two.\nDialogue: 0,0:56:29.66,0:56:30.75,EN,,0,0,0,,And c2\nDialogue: 0,0:56:33.37,0:56:35.31,EN,,0,0,0,,gives me a 12 by the same method,\nDialogue: 0,0:56:35.74,0:56:37.55,EN,,0,0,0,,by walking down here looking at that\nDialogue: 0,0:56:37.55,0:56:39.28,EN,,0,0,0,,and saying, here's the n, I'm incrementing.\nDialogue: 0,0:56:41.64,0:56:43.68,EN,,0,0,0,,So what I have are computational objects.\nDialogue: 0,0:56:45.21,0:56:46.86,EN,,0,0,0,,There are two counters,\nDialogue: 0,0:56:48.96,0:56:51.02,EN,,0,0,0,,each with its own independent local state.\nDialogue: 0,0:56:55.48,0:56:56.62,EN,,0,0,0,,Let's talk about this a little.\nDialogue: 0,0:56:56.64,0:56:58.52,EN,,0,0,0,,This is a strange thing.\nDialogue: 0,0:57:01.12,0:57:02.22,EN,,0,0,0,,What's an object?\nDialogue: 0,0:57:04.11,0:57:06.12,EN,,0,0,0,,It's not at all obvious what an object is.\nDialogue: 0,0:57:07.55,0:57:09.45,EN,,0,0,0,,We like to think about objects,\nDialogue: 0,0:57:11.24,0:57:13.32,EN,,0,0,0,,because it's economical to think that way.\nDialogue: 0,0:57:14.62,0:57:17.28,EN,,0,0,0,,It's an intellectual economy.\nDialogue: 0,0:57:18.57,0:57:19.61,EN,,0,0,0,,I am an object.\nDialogue: 0,0:57:20.99,0:57:22.30,EN,,0,0,0,,You are an object.\nDialogue: 0,0:57:23.55,0:57:25.29,EN,,0,0,0,,We are not the same object.\nDialogue: 0,0:57:27.52,0:57:29.64,EN,,0,0,0,,I can divide the world into two parts,\nDialogue: 0,0:57:29.92,0:57:31.85,EN,,0,0,0,,me and you,\nDialogue: 0,0:57:31.92,0:57:33.31,EN,,0,0,0,,and there's other things as well,\nDialogue: 0,0:57:34.70,0:57:35.26,EN,,0,0,0,,such that\nDialogue: 0,0:57:35.44,0:57:39.50,EN,,0,0,0,,most of the things I might want to discuss about my workings\nDialogue: 0,0:57:39.68,0:57:40.89,EN,,0,0,0,,do not involve you,\nDialogue: 0,0:57:41.39,0:57:44.67,EN,,0,0,0,,and most of the things I want to discuss about your workings don't involve me.\nDialogue: 0,0:57:45.66,0:57:46.94,EN,,0,0,0,,I have a blood pressure,\nDialogue: 0,0:57:47.50,0:57:48.38,EN,,0,0,0,,a temperature,\nDialogue: 0,0:57:49.36,0:57:51.48,EN,,0,0,0,,a respiration rate,\nDialogue: 0,0:57:53.34,0:57:54.99,EN,,0,0,0,,certain amount of sugar in my blood,\nDialogue: 0,0:57:56.11,0:57:59.34,EN,,0,0,0,,and numerous, thousands, of state variables-- millions actually,\nDialogue: 0,0:57:59.37,0:58:00.65,EN,,0,0,0,,or I don't know how many--\nDialogue: 0,0:58:00.93,0:58:03.48,EN,,0,0,0,,huge numbers of state variables in the physical sense\nDialogue: 0,0:58:04.91,0:58:07.12,EN,,0,0,0,,which represent the state of me as a particle,\nDialogue: 0,0:58:09.15,0:58:10.64,EN,,0,0,0,,and you have gazillions of them as well.\nDialogue: 0,0:58:12.68,0:58:14.94,EN,,0,0,0,,And most of mine are uncoupled to most of yours.\nDialogue: 0,0:58:17.31,0:58:19.50,EN,,0,0,0,,So we can compute the properties of me\nDialogue: 0,0:58:20.56,0:58:22.83,EN,,0,0,0,,without worrying too much about the properties of you.\nDialogue: 0,0:58:23.82,0:58:25.77,EN,,0,0,0,,If we had to work about both of us together,\nDialogue: 0,0:58:25.96,0:58:27.82,EN,,0,0,0,,than the number of states that we have to consider\nDialogue: 0,0:58:27.82,0:58:30.01,EN,,0,0,0,,is the product of the number of states you have and the number of states I have.\nDialogue: 0,0:58:30.52,0:58:32.11,EN,,0,0,0,,But this way it's almost a sum.\nDialogue: 0,0:58:32.65,0:58:35.34,EN,,0,0,0,,Now, indeed there are forces that couple us.\nDialogue: 0,0:58:36.00,0:58:37.95,EN,,0,0,0,,I'm talking to you and your state changes.\nDialogue: 0,0:58:38.44,0:58:40.09,EN,,0,0,0,,I'm looking at you and my state changes.\nDialogue: 0,0:58:41.72,0:58:44.08,EN,,0,0,0,,Some of my state variables, a very few of them,\nDialogue: 0,0:58:44.33,0:58:46.07,EN,,0,0,0,,therefore, are coupled to yours.\nDialogue: 0,0:58:46.07,0:58:47.80,EN,,0,0,0,,If you were to suddenly yell very loud,\nDialogue: 0,0:58:47.80,0:58:48.88,EN,,0,0,0,,my blood pressure would go up.\nDialogue: 0,0:58:54.30,0:58:56.86,EN,,0,0,0,,However, and it may not be always appropriate\nDialogue: 0,0:58:57.17,0:59:01.16,EN,,0,0,0,,to think about the world as being made out of independent states and independent particles.\nDialogue: 0,0:59:02.12,0:59:04.46,EN,,0,0,0,,Lots of the bugs that occur in things like quantum mechanics,\nDialogue: 0,0:59:05.23,0:59:08.70,EN,,0,0,0,,or the bugs in our minds that occur when we think about things like quantum mechanics,\nDialogue: 0,0:59:08.89,0:59:10.97,EN,,0,0,0,,are due the fact that we are trying to think about things\nDialogue: 0,0:59:10.97,0:59:12.96,EN,,0,0,0,,being broken up into independent pieces,\nDialogue: 0,0:59:13.58,0:59:17.32,EN,,0,0,0,,when in fact there's more coupling than we see on the surface,\nDialogue: 0,0:59:18.01,0:59:19.44,EN,,0,0,0,,or that we want to believe in,\nDialogue: 0,0:59:19.61,0:59:21.69,EN,,0,0,0,,because we want to compute efficiently and effectively.\nDialogue: 0,0:59:22.19,0:59:23.82,EN,,0,0,0,,We've been trained to think that way.\nDialogue: 0,0:59:29.76,0:59:30.51,EN,,0,0,0,,Well, let's see.\nDialogue: 0,0:59:31.50,0:59:33.44,EN,,0,0,0,,How would we know if we had objects at all?\nDialogue: 0,0:59:35.12,0:59:37.34,EN,,0,0,0,,How can we tell if we have objects?\nDialogue: 0,0:59:37.64,0:59:41.45,EN,,0,0,0,,Consider some possible optical illusions.\nDialogue: 0,0:59:42.46,0:59:43.13,EN,,0,0,0,,This could be done.\nDialogue: 0,0:59:45.04,0:59:47.69,EN,,0,0,0,,These pieces of chalk are not appropriately identical,\nDialogue: 0,0:59:47.76,0:59:50.20,EN,,0,0,0,,but supposing you couldn't tell the difference of them by looking at them.\nDialogue: 0,0:59:52.04,0:59:53.32,EN,,0,0,0,,Well, there's a possibility\nDialogue: 0,0:59:53.32,0:59:55.16,EN,,0,0,0,,that this all a game I'm playing with mirrors.\nDialogue: 0,0:59:56.07,0:59:57.60,EN,,0,0,0,,It's really the same piece of chalk,\nDialogue: 0,0:59:59.36,1:00:00.48,EN,,0,0,0,,but you're seeing two of them.\nDialogue: 0,1:00:01.61,1:00:03.87,EN,,0,0,0,,How would you know if you're seeing one or two?\nDialogue: 0,1:00:05.04,1:00:06.70,EN,,0,0,0,,Well, there's only one way I know.\nDialogue: 0,1:00:07.37,1:00:08.94,EN,,0,0,0,,You grab one of them and change it\nDialogue: 0,1:00:09.45,1:00:10.67,EN,,0,0,0,,and see if the other one changed.\nDialogue: 0,1:00:14.01,1:00:14.67,EN,,0,0,0,,And it didn't,\nDialogue: 0,1:00:15.50,1:00:16.14,EN,,0,0,0,,so there's two of them.\nDialogue: 0,1:00:19.50,1:00:20.16,EN,,0,0,0,,And, on the other hand,\nDialogue: 0,1:00:20.17,1:00:22.20,EN,,0,0,0,,there is some other screwy properties of things like that.\nDialogue: 0,1:00:22.57,1:00:24.01,EN,,0,0,0,,Like, how do we know if something changed?\nDialogue: 0,1:00:25.00,1:00:27.93,EN,,0,0,0,,We have to look at it before and after the change.\nDialogue: 0,1:00:28.65,1:00:30.02,EN,,0,0,0,,The change is an assignment,\nDialogue: 0,1:00:30.02,1:00:31.45,EN,,0,0,0,,it's a moment in time.\nDialogue: 0,1:00:32.14,1:00:34.60,EN,,0,0,0,,But that means we have to know it was the same one that we're looking at.\nDialogue: 0,1:00:36.51,1:00:38.84,EN,,0,0,0,,So some very strange, and unusual,\nDialogue: 0,1:00:38.84,1:00:40.38,EN,,0,0,0,,and obscure, and -- I don't understand\nDialogue: 0,1:00:40.84,1:00:43.52,EN,,0,0,0,,the problems associated with assignment,\nDialogue: 0,1:00:44.45,1:00:46.28,EN,,0,0,0,,and change, and objects.\nDialogue: 0,1:00:47.29,1:00:48.99,EN,,0,0,0,,These could get very, very bad.\nDialogue: 0,1:00:51.40,1:00:52.12,EN,,0,0,0,,For example,\nDialogue: 0,1:00:53.31,1:00:55.60,EN,,0,0,0,,here I am, I am a particular person,\nDialogue: 0,1:00:56.16,1:00:57.72,EN,,0,0,0,,a particular object, okay?\nDialogue: 0,1:00:57.96,1:00:59.31,EN,,0,0,0,,Now, I can take out my knife,\nDialogue: 0,1:01:00.68,1:01:01.77,EN,,0,0,0,,and cut my fingernail.\nDialogue: 0,1:01:01.89,1:01:04.81,EN,,0,0,0,,Alright? A piece of my fingernail has fallen off onto the table.\nDialogue: 0,1:01:05.93,1:01:10.16,EN,,0,0,0,,I believe I am the same person I was a second ago,\nDialogue: 0,1:01:10.97,1:01:12.81,EN,,0,0,0,,but I'm not physically the same in the slightest.\nDialogue: 0,1:01:14.46,1:01:15.43,EN,,0,0,0,,I have changed.\nDialogue: 0,1:01:15.58,1:01:16.65,EN,,0,0,0,,Why am I the same?\nDialogue: 0,1:01:18.11,1:01:19.40,EN,,0,0,0,,What is the identity of me?\nDialogue: 0,1:01:20.96,1:01:23.50,EN,,0,0,0,,I don't know...Okay?\nDialogue: 0,1:01:25.05,1:01:27.88,EN,,0,0,0,,Except for the fact that I have some sort of identity.\nDialogue: 0,1:01:29.71,1:01:33.04,EN,,0,0,0,,And so, I think by introducing assignment and objects,\nDialogue: 0,1:01:33.64,1:01:38.28,EN,,0,0,0,,we have opened ourselves up to all the horrible questions of philosophy\nDialogue: 0,1:01:38.41,1:01:42.24,EN,,0,0,0,,that have been plaguing philosophers for some thousands of years about this sort of thing.\nDialogue: 0,1:01:43.42,1:01:44.99,EN,,0,0,0,,It's why mathematics is a lot cleaner.\nDialogue: 0,1:01:45.69,1:01:50.24,EN,,0,0,0,,Let's look at the best things I know to say about actions and identity.\nDialogue: 0,1:01:52.44,1:01:55.39,EN,,0,0,0,,We say that an action, a, had an effect on an object, x,\nDialogue: 0,1:01:55.77,1:01:56.70,EN,,0,0,0,,or equivalently,\nDialogue: 0,1:01:56.92,1:01:58.41,EN,,0,0,0,,that x was changed by a,\nDialogue: 0,1:01:58.89,1:02:01.66,EN,,0,0,0,,if some property, p, which was true of x before a,\nDialogue: 0,1:02:01.87,1:02:03.76,EN,,0,0,0,,became false of x after a.\nDialogue: 0,1:02:04.99,1:02:05.63,EN,,0,0,0,,That's test.\nDialogue: 0,1:02:06.62,1:02:09.66,EN,,0,0,0,,It still means I have to have the x before and after.\nDialogue: 0,1:02:10.91,1:02:12.54,EN,,0,0,0,,Or, the other way of saying this is,\nDialogue: 0,1:02:12.94,1:02:14.94,EN,,0,0,0,,we say that two objects x and y are the same for any action\nDialogue: 0,1:02:14.97,1:02:17.93,EN,,0,0,0,,which has an effect on x has the same effect on y\nDialogue: 0,1:02:19.63,1:02:21.39,EN,,0,0,0,,However, objects are very useful,\nDialogue: 0,1:02:21.44,1:02:23.18,EN,,0,0,0,,as I said, for intellectual economy.\nDialogue: 0,1:02:24.64,1:02:27.12,EN,,0,0,0,,One of the things that's incredibly useful about them,\nDialogue: 0,1:02:28.27,1:02:29.44,EN,,0,0,0,,is that the world\nDialogue: 0,1:02:30.78,1:02:34.80,EN,,0,0,0,,is made out of independent objects with independent local state.\nDialogue: 0,1:02:35.00,1:02:37.28,EN,,0,0,0,,We like to think that way, although it isn't completely true.\nDialogue: 0,1:02:39.68,1:02:42.03,EN,,0,0,0,,When we want to make very complicated programs\nDialogue: 0,1:02:42.03,1:02:43.26,EN,,0,0,0,,that deal with such a world,\nDialogue: 0,1:02:43.98,1:02:46.44,EN,,0,0,0,,if we want those programs to be understandable by us\nDialogue: 0,1:02:46.91,1:02:48.14,EN,,0,0,0,,and also to be changeable,\nDialogue: 0,1:02:48.73,1:02:51.12,EN,,0,0,0,,so that if we change the world we change the program only a little bit,\nDialogue: 0,1:02:51.39,1:02:53.70,EN,,0,0,0,,then we want there to be connections, isomorphism,\nDialogue: 0,1:02:53.82,1:02:56.88,EN,,0,0,0,,between the objects in the world and the objects in our mental model.\nDialogue: 0,1:02:58.76,1:03:01.44,EN,,0,0,0,,The modularity of the world can give us the modularity in our programming.\nDialogue: 0,1:03:02.41,1:03:05.36,EN,,0,0,0,,So we invent things called object-oriented programming and things like that\nDialogue: 0,1:03:05.88,1:03:08.36,EN,,0,0,0,,to provide us with that power.\nDialogue: 0,1:03:10.06,1:03:10.94,EN,,0,0,0,,But it's even easier.\nDialogue: 0,1:03:10.94,1:03:12.25,EN,,0,0,0,,Let's play a little game.\nDialogue: 0,1:03:12.27,1:03:13.18,EN,,0,0,0,,I want to play a little game,\nDialogue: 0,1:03:13.39,1:03:15.77,EN,,0,0,0,,show you an even easier example\nDialogue: 0,1:03:16.00,1:03:21.74,EN,,0,0,0,,or where modularity can be enhanced by using an assignment statement, judiciously.\nDialogue: 0,1:03:22.86,1:03:25.35,EN,,0,0,0,,One thing I want to enforce and impress on you,\nDialogue: 0,1:03:25.45,1:03:27.44,EN,,0,0,0,,is don't use assignment statements the way\nDialogue: 0,1:03:27.45,1:03:29.79,EN,,0,0,0,,you use it in FORTRAN or Basic or something or Pascal,\nDialogue: 0,1:03:30.00,1:03:31.71,EN,,0,0,0,,to do the things you don't have to do with it.\nDialogue: 0,1:03:34.04,1:03:36.62,EN,,0,0,0,,It's not the right way to think for most things.\nDialogue: 0,1:03:36.97,1:03:38.28,EN,,0,0,0,,Sometimes it's essential,\nDialogue: 0,1:03:38.68,1:03:39.69,EN,,0,0,0,,or maybe it's essential.\nDialogue: 0,1:03:39.69,1:03:40.97,EN,,0,0,0,,We'll see more about that too.\nDialogue: 0,1:03:42.24,1:03:44.22,EN,,0,0,0,,OK, let me show you a fun game here.\nDialogue: 0,1:03:47.61,1:03:49.42,EN,,0,0,0,,There was a mathematician\nDialogue: 0,1:03:49.68,1:03:53.69,EN,,0,0,0,,by the name of Cesaro--or Cesaro, Cesaro I suppose it is--\nDialogue: 0,1:03:54.48,1:03:57.45,EN,,0,0,0,,who figured out a clever way of computing pi.\nDialogue: 0,1:03:58.38,1:04:04.30,EN,,0,0,0,,It turns out that if I take two random numbers\nDialogue: 0,1:04:05.24,1:04:06.94,EN,,0,0,0,,two integers at random,\nDialogue: 0,1:04:07.74,1:04:09.48,EN,,0,0,0,,and compute the greatest common divisor,\nDialogue: 0,1:04:10.94,1:04:13.24,EN,,0,0,0,,their greatest common divisor is either one or it's not one.\nDialogue: 0,1:04:13.84,1:04:15.64,EN,,0,0,0,,If it's one, then they have no common divisors.\nDialogue: 0,1:04:18.14,1:04:20.68,EN,,0,0,0,,If their greatest common divisor is one--\nDialogue: 0,1:04:21.12,1:04:23.09,EN,,0,0,0,,the probability that two random numbers,\nDialogue: 0,1:04:23.09,1:04:26.38,EN,,0,0,0,,two numbers chosen at random, has as greatest common divisor one\nDialogue: 0,1:04:26.58,1:04:27.82,EN,,0,0,0,,is related to pi.\nDialogue: 0,1:04:29.32,1:04:30.11,EN,,0,0,0,,In fact--\nDialogue: 0,1:04:31.11,1:04:32.33,EN,,0,0,0,,yes, it's very strange--\nDialogue: 0,1:04:32.94,1:04:34.41,EN,,0,0,0,,of course there are other ways of computing pi,\nDialogue: 0,1:04:34.41,1:04:38.94,EN,,0,0,0,,like dropping pins on flags, and things like that, and sort of the same kind of thing.\nDialogue: 0,1:04:40.19,1:04:48.97,EN,,0,0,0,,So the probability of that the GCD of number one and number two,\nDialogue: 0,1:04:49.44,1:04:51.02,EN,,0,0,0,,two random numbers chosen,\nDialogue: 0,1:04:51.71,1:04:53.66,EN,,0,0,0,,is 6 over pi squared.\nDialogue: 0,1:04:55.61,1:04:56.83,EN,,0,0,0,,I'm not going to try to prove that.\nDialogue: 0,1:04:57.15,1:04:59.64,EN,,0,0,0,,It's actually not too hard and sort of fun.\nDialogue: 0,1:05:01.07,1:05:03.05,EN,,0,0,0,,How would we estimate such probability?\nDialogue: 0,1:05:03.53,1:05:06.46,EN,,0,0,0,,Well, the way we do that, the way we estimate the probabilities,\nDialogue: 0,1:05:07.23,1:05:08.65,EN,,0,0,0,,is by doing lots of experiments,\nDialogue: 0,1:05:09.20,1:05:12.01,EN,,0,0,0,,and then computing the ratios of the ones that come out one way\nDialogue: 0,1:05:12.01,1:05:13.58,EN,,0,0,0,,to the total number of experiments we do.\nDialogue: 0,1:05:16.32,1:05:17.28,EN,,0,0,0,,It's called Monte Carlo,\nDialogue: 0,1:05:18.04,1:05:22.38,EN,,0,0,0,,and it's useful in other contexts for doing things like integrals where you have lots and lots of variables--\nDialogue: 0,1:05:22.94,1:05:25.28,EN,,0,0,0,,the space which is limiting the dimensions you are doing you integral in.\nDialogue: 0,1:05:26.27,1:05:28.70,EN,,0,0,0,,But going back to here,\nDialogue: 0,1:05:29.76,1:05:31.72,EN,,0,0,0,,Let's look at this slide,\nDialogue: 0,1:05:33.96,1:05:36.92,EN,,0,0,0,,We can use Cesaro's method for estimating pi\nDialogue: 0,1:05:37.19,1:05:43.18,EN,,0,0,0,,with n trials by taking the square root of six over a Monte Carlo,\nDialogue: 0,1:05:43.29,1:05:46.46,EN,,0,0,0,,a Monte Carlo experiment with n trials,\nDialogue: 0,1:05:46.80,1:05:50.38,EN,,0,0,0,,with n trials using Cesaro's experiment,\nDialogue: 0,1:05:51.37,1:05:57.56,EN,,0,0,0,,where Cesaro's experiment is the test of whether the GCD of two random numbers--\nDialogue: 0,1:05:58.96,1:06:01.60,EN,,0,0,0,,And you can see that I've already got some assignments in here,\nDialogue: 0,1:06:01.84,1:06:03.13,EN,,0,0,0,,just by what I wrote.\nDialogue: 0,1:06:04.04,1:06:07.49,EN,,0,0,0,,The fact that this word rand, in parentheses,\nDialogue: 0,1:06:07.49,1:06:09.09,EN,,0,0,0,,therefore, that procedure call,\nDialogue: 0,1:06:09.09,1:06:11.39,EN,,0,0,0,,yields a different value than this one,\nDialogue: 0,1:06:11.39,1:06:13.72,EN,,0,0,0,,at least that's what I'm assuming by writing this this way,\nDialogue: 0,1:06:14.62,1:06:16.75,EN,,0,0,0,,indicates that this is not a function,\nDialogue: 0,1:06:18.20,1:06:20.57,EN,,0,0,0,,that there's internal state in it which is changing.\nDialogue: 0,1:06:22.27,1:06:28.64,EN,,0,0,0,,If the GCD of those two random numbers is equal to one,\nDialogue: 0,1:06:28.64,1:06:29.79,EN,,0,0,0,,that's the experiment.\nDialogue: 0,1:06:31.48,1:06:35.18,EN,,0,0,0,,So here I have an experimental method for estimating the value of pi.\nDialogue: 0,1:06:36.51,1:06:39.72,EN,,0,0,0,,Where, I can easily divide this problem into two parts.\nDialogue: 0,1:06:40.02,1:06:44.70,EN,,0,0,0,,One is the specific Monte Carlo experiment of Cesaro, which you just saw,\nDialogue: 0,1:06:44.99,1:06:48.56,EN,,0,0,0,,and the other is the general technique of doing Monte Carlo experiments.\nDialogue: 0,1:06:49.16,1:06:50.27,EN,,0,0,0,,And that's what this is.\nDialogue: 0,1:06:51.04,1:06:55.47,EN,,0,0,0,,If I want to do Monte Carlo experiments with n trials,\nDialogue: 0,1:06:55.67,1:06:58.36,EN,,0,0,0,,a certain number of trials, and a particular experiment,\nDialogue: 0,1:06:59.31,1:07:00.33,EN,,0,0,0,,the way I do that\nDialogue: 0,1:07:00.84,1:07:02.70,EN,,0,0,0,,is I make a little iterative procedure\nDialogue: 0,1:07:03.31,1:07:07.26,EN,,0,0,0,,which has variable the number of trials remaining and the number trials that have been passed,\nDialogue: 0,1:07:08.35,1:07:09.44,EN,,0,0,0,,that I've gotten true.\nDialogue: 0,1:07:10.13,1:07:12.21,EN,,0,0,0,,And if the number remaining is 0,\nDialogue: 0,1:07:12.21,1:07:15.36,EN,,0,0,0,,then the answer is the number past divided by this whole number of trials,\nDialogue: 0,1:07:16.04,1:07:17.52,EN,,0,0,0,,was the estimate of the probability.\nDialogue: 0,1:07:19.07,1:07:20.04,EN,,0,0,0,,And if it's not,\nDialogue: 0,1:07:20.04,1:07:22.08,EN,,0,0,0,,if I have more trials to do,\nDialogue: 0,1:07:22.08,1:07:23.82,EN,,0,0,0,,then let's do one. We do an experiment.\nDialogue: 0,1:07:23.85,1:07:27.30,EN,,0,0,0,,We call the procedure which is experiment on no arguments.\nDialogue: 0,1:07:27.30,1:07:28.43,EN,,0,0,0,,We do the experiment\nDialogue: 0,1:07:29.10,1:07:30.64,EN,,0,0,0,,and then, if that turned out to be true,\nDialogue: 0,1:07:30.82,1:07:32.25,EN,,0,0,0,,we go around the loop\nDialogue: 0,1:07:32.62,1:07:35.42,EN,,0,0,0,,decrementing the number of experiments we have to do by one\nDialogue: 0,1:07:35.70,1:07:37.48,EN,,0,0,0,,and incrementing the number that were passed.\nDialogue: 0,1:07:38.57,1:07:40.11,EN,,0,0,0,,And if the experiment was false,\nDialogue: 0,1:07:40.41,1:07:42.25,EN,,0,0,0,,we just go around the loop\nDialogue: 0,1:07:42.32,1:07:44.38,EN,,0,0,0,,decrementing the number of experiments remaining\nDialogue: 0,1:07:44.44,1:07:46.60,EN,,0,0,0,,and keeping the number passed the same.\nDialogue: 0,1:07:48.76,1:07:54.59,EN,,0,0,0,,We start this up iterating over the total number of trials with 0 experiments past.\nDialogue: 0,1:07:55.42,1:07:57.10,EN,,0,0,0,,A very elegant little program.\nDialogue: 0,1:07:57.74,1:08:00.55,EN,,0,0,0,,And I don't have to just do this with Cesaro's experiment,\nDialogue: 0,1:08:00.55,1:08:02.73,EN,,0,0,0,,it could be lots of Monte Carlo experiments I might do.\nDialogue: 0,1:08:03.36,1:08:07.12,EN,,0,0,0,,Of course, this depends upon the existence of some sort of random number generator.\nDialogue: 0,1:08:07.34,1:08:10.99,EN,,0,0,0,,And random number generators generally look something like this.\nDialogue: 0,1:08:13.60,1:08:16.32,EN,,0,0,0,,There is a random number generator--\nDialogue: 0,1:08:17.42,1:08:25.21,EN,,0,0,0,,is in fact a procedure which is going to do something just like the counter.\nDialogue: 0,1:08:25.61,1:08:27.52,EN,,0,0,0,,It's going to update an x\nDialogue: 0,1:08:28.33,1:08:31.82,EN,,0,0,0,,to the result of applying some function to x,\nDialogue: 0,1:08:32.20,1:08:35.28,EN,,0,0,0,,where this function is some screwy kind of function\nDialogue: 0,1:08:35.39,1:08:40.16,EN,,0,0,0,,that you might find out in Knuth's books on the details of programming.\nDialogue: 0,1:08:41.56,1:08:45.75,EN,,0,0,0,,He does these wonderful books that are full of the details of programming,\nDialogue: 0,1:08:45.75,1:08:48.52,EN,,0,0,0,,because I can't remember how to make a random number generator,\nDialogue: 0,1:08:48.63,1:08:50.62,EN,,0,0,0,,but I can look it up there, and I can find out.\nDialogue: 0,1:08:51.64,1:08:54.01,EN,,0,0,0,,And then, eventually, I return the value of x\nDialogue: 0,1:08:54.08,1:08:57.40,EN,,0,0,0,,which is the state variable internal to the random number generator.\nDialogue: 0,1:08:58.28,1:09:00.75,EN,,0,0,0,,That state variable is initialized somehow,\nDialogue: 0,1:09:01.32,1:09:02.24,EN,,0,0,0,,and has a value.\nDialogue: 0,1:09:03.39,1:09:08.11,EN,,0,0,0,,And this procedure is defined in the context where that variable is bound\nDialogue: 0,1:09:10.41,1:09:15.26,EN,,0,0,0,,So this is a hidden piece of local state that you see here.\nDialogue: 0,1:09:15.87,1:09:20.24,EN,,0,0,0,,And this procedure is defined in that context.\nDialogue: 0,1:09:21.56,1:09:23.66,EN,,0,0,0,,Now, that's a very simple thing to do.\nDialogue: 0,1:09:24.88,1:09:25.79,EN,,0,0,0,,And it's very nice.\nDialogue: 0,1:09:25.99,1:09:27.77,EN,,0,0,0,,Supposing, I didn't want to use assignments.\nDialogue: 0,1:09:29.10,1:09:31.47,EN,,0,0,0,,Supposing, I wanted to write this program without assignments.\nDialogue: 0,1:09:32.73,1:09:33.93,EN,,0,0,0,,What problems would I have?\nDialogue: 0,1:09:35.52,1:09:37.40,EN,,0,0,0,,Well, let's see.\nDialogue: 0,1:09:37.82,1:09:41.10,EN,,0,0,0,,I'd like to use the overhead machine here,\nDialogue: 0,1:09:42.06,1:09:42.70,EN,,0,0,0,,thank you.\nDialogue: 0,1:09:43.47,1:09:47.66,EN,,0,0,0,,First of all, let's look at the whole thing. It's a big story. Right?\nDialogue: 0,1:09:48.01,1:09:49.90,EN,,0,0,0,,Unfortunately, which tells you there is something wrong.\nDialogue: 0,1:09:50.96,1:09:52.75,EN,,0,0,0,,It's at least that big,\nDialogue: 0,1:09:53.42,1:09:54.60,EN,,0,0,0,,and it's monolithic.\nDialogue: 0,1:09:56.76,1:10:00.12,EN,,0,0,0,,You don't have to understand or look at the text there right now\nDialogue: 0,1:10:00.12,1:10:01.39,EN,,0,0,0,,to see that it's monolithic.\nDialogue: 0,1:10:01.92,1:10:04.89,EN,,0,0,0,,It isn't a thing which is Cesaro's experiment.\nDialogue: 0,1:10:04.89,1:10:07.90,EN,,0,0,0,,It's not pulled out from the Monte Carlo process.\nDialogue: 0,1:10:09.87,1:10:11.84,EN,,0,0,0,,It's not separated. Let's look why.\nDialogue: 0,1:10:14.22,1:10:15.85,EN,,0,0,0,,Remember, the constraint here\nDialogue: 0,1:10:15.85,1:10:17.87,EN,,0,0,0,,is that every procedure\nDialogue: 0,1:10:18.69,1:10:22.20,EN,,0,0,0,,return the same value for the same arguments.\nDialogue: 0,1:10:22.97,1:10:24.75,EN,,0,0,0,,Every procedure represents a function.\nDialogue: 0,1:10:26.92,1:10:28.50,EN,,0,0,0,,That's a different kind of constraint.\nDialogue: 0,1:10:28.50,1:10:31.21,EN,,0,0,0,,Because when I have assignments, I can  change some internal state variable.\nDialogue: 0,1:10:31.74,1:10:34.03,EN,,0,0,0,,So let's see how that causes things to go wrong.\nDialogue: 0,1:10:35.04,1:10:36.14,EN,,0,0,0,,Well, start at the beginning.\nDialogue: 0,1:10:37.50,1:10:41.92,EN,,0,0,0,,Ah...The estimate of pi looks sort of the same.\nDialogue: 0,1:10:42.66,1:10:45.88,EN,,0,0,0,,What I'm doing is I take the square root\nDialogue: 0,1:10:46.35,1:10:50.22,EN,,0,0,0,,of six over the random GCD test applied to n\nDialogue: 0,1:10:50.74,1:10:51.93,EN,,0,0,0,,whereas that's what this is.\nDialogue: 0,1:10:52.96,1:10:55.20,EN,,0,0,0,,But here, we are beginning to see something funny.\nDialogue: 0,1:10:55.20,1:10:57.93,EN,,0,0,0,,The random GCD test of a certain number of trials\nDialogue: 0,1:10:58.32,1:10:59.98,EN,,0,0,0,,is just like we had before,\nDialogue: 0,1:11:00.46,1:11:04.66,EN,,0,0,0,,an iteration on the number of trials remaining,\nDialogue: 0,1:11:04.66,1:11:06.80,EN,,0,0,0,,the number of trials that have been passed,\nDialogue: 0,1:11:08.27,1:11:09.71,EN,,0,0,0,,and another variable x.\nDialogue: 0,1:11:10.75,1:11:11.76,EN,,0,0,0,,What's that x?\nDialogue: 0,1:11:12.33,1:11:15.20,EN,,0,0,0,,That x is the state of the random number generator.\nDialogue: 0,1:11:19.00,1:11:21.16,EN,,0,0,0,,And it is now going to be used here.\nDialogue: 0,1:11:21.16,1:11:23.79,EN,,0,0,0,,The same random update function that I have over here\nDialogue: 0,1:11:23.79,1:11:27.15,EN,,0,0,0,,is the one I would have used in a random number generator if I were building it the other way,\nDialogue: 0,1:11:27.71,1:11:29.32,EN,,0,0,0,,the one I get out of Knuth's books.\nDialogue: 0,1:11:31.56,1:11:33.36,EN,,0,0,0,,x is going to get transformed into x1,\nDialogue: 0,1:11:33.37,1:11:34.36,EN,,0,0,0,,I need two random numbers.\nDialogue: 0,1:11:34.81,1:11:36.92,EN,,0,0,0,,And x1 is going to get transformed into x2,\nDialogue: 0,1:11:37.26,1:11:38.44,EN,,0,0,0,,I have two random numbers.\nDialogue: 0,1:11:39.50,1:11:42.14,EN,,0,0,0,,I then have to do exactly what I did before.\nDialogue: 0,1:11:42.52,1:11:44.19,EN,,0,0,0,,I take the GCD of x1 x2.\nDialogue: 0,1:11:44.22,1:11:47.15,EN,,0,0,0,,If that's one, then I go around the loop with X2 being the next value of x.\nDialogue: 0,1:11:54.78,1:11:55.98,EN,,0,0,0,,You see what's happened here\nDialogue: 0,1:11:56.88,1:11:58.70,EN,,0,0,0,,is that the state of the random number generator\nDialogue: 0,1:11:58.73,1:12:01.70,EN,,0,0,0,,is no longer confined to the insides of the random number generator.\nDialogue: 0,1:12:01.80,1:12:02.73,EN,,0,0,0,,It has leaked out.\nDialogue: 0,1:12:03.33,1:12:05.50,EN,,0,0,0,,It has leaked out into my procedure\nDialogue: 0,1:12:05.50,1:12:10.08,EN,,0,0,0,,that does the Monte Carlo experiment.\nDialogue: 0,1:12:10.70,1:12:11.87,EN,,0,0,0,,But what's worse than that,\nDialogue: 0,1:12:11.87,1:12:16.24,EN,,0,0,0,,is it's also, because it was contained inside my experiment itself, Cesaro,\nDialogue: 0,1:12:16.78,1:12:19.48,EN,,0,0,0,,It leaked out that two. Because Cesaro called twice,\nDialogue: 0,1:12:20.86,1:12:22.47,EN,,0,0,0,,has to have a different value each time,\nDialogue: 0,1:12:22.47,1:12:25.16,EN,,0,0,0,,if I going to have a legitimate experimental test.\nDialogue: 0,1:12:26.32,1:12:28.32,EN,,0,0,0,,So Cesaro can't be a function either,\nDialogue: 0,1:12:31.04,1:12:35.69,EN,,0,0,0,,unless I pass it the seed of the random number generator that is going to go wandering around.\nDialogue: 0,1:12:36.52,1:12:39.37,EN,,0,0,0,,So unfortunately, the seed of random number generator\nDialogue: 0,1:12:39.37,1:12:42.77,EN,,0,0,0,,has leaked out into Cesaro, from the random number generator,\nDialogue: 0,1:12:42.88,1:12:45.16,EN,,0,0,0,,that's leaked into the Monte Carlo experiment.\nDialogue: 0,1:12:45.64,1:12:49.12,EN,,0,0,0,,And, unfortunately, my Monte Carlo experiment here is no longer general.\nDialogue: 0,1:12:50.25,1:12:51.80,EN,,0,0,0,,The Monte Carlo experiment here\nDialogue: 0,1:12:52.03,1:12:54.73,EN,,0,0,0,,knows how many random numbers I need to do the experiment.\nDialogue: 0,1:12:58.96,1:12:59.74,EN,,0,0,0,,That's sort of horrible.\nDialogue: 0,1:13:00.08,1:13:02.54,EN,,0,0,0,,I lost an ability to decompose a problem into pieces,\nDialogue: 0,1:13:03.44,1:13:09.12,EN,,0,0,0,,because I wasn't willing to accept the little loop of information,\nDialogue: 0,1:13:09.50,1:13:12.43,EN,,0,0,0,,the feedback process,\nDialogue: 0,1:13:12.88,1:13:15.94,EN,,0,0,0,,that happens inside the random number generator before\nDialogue: 0,1:13:15.94,1:13:21.21,EN,,0,0,0,,that was made by having an assignment to a state variable that was confined to the random number generator.\nDialogue: 0,1:13:22.92,1:13:25.48,EN,,0,0,0,,So the fact that the random number generator is an object,\nDialogue: 0,1:13:25.92,1:13:27.37,EN,,0,0,0,,with an internal state variable,\nDialogue: 0,1:13:28.06,1:13:29.36,EN,,0,0,0,,it's affected by nothing,\nDialogue: 0,1:13:29.37,1:13:31.60,EN,,0,0,0,,but it'll give you something, and it will apply it's force to you,\nDialogue: 0,1:13:32.80,1:13:34.28,EN,,0,0,0,,that was what we're missing now.\nDialogue: 0,1:13:38.00,1:13:40.73,EN,,0,0,0,,OK, well I think we've seen\nDialogue: 0,1:13:40.73,1:13:42.30,EN,,0,0,0,,enough reason for doing this,\nDialogue: 0,1:13:42.83,1:13:45.24,EN,,0,0,0,,and it all sort of looks very wonderful.\nDialogue: 0,1:13:45.38,1:13:50.70,EN,,0,0,0,,Wouldn't it be nice if assignment was a good thing\nDialogue: 0,1:13:51.74,1:13:53.04,EN,,0,0,0,,and maybe it's worth it,\nDialogue: 0,1:13:53.28,1:13:54.14,EN,,0,0,0,,but I'm not sure.\nDialogue: 0,1:13:55.34,1:13:57.04,EN,,0,0,0,,As Mr. Gilbert and Sullivan said,\nDialogue: 0,1:13:57.04,1:13:58.51,EN,,0,0,0,,things are seldom what they seem,\nDialogue: 0,1:13:58.51,1:14:00.35,EN,,0,0,0,,skim milk masquerades as cream.\nDialogue: 0,1:14:01.87,1:14:03.90,EN,,0,0,0,,Are there any questions?\nDialogue: 0,1:14:16.97,1:14:18.30,EN,,0,0,0,,Are there any philosophers here?\nDialogue: 0,1:14:20.06,1:14:22.03,EN,,0,0,0,,Anybody want to argue about objects?\nDialogue: 0,1:14:24.32,1:14:25.50,EN,,0,0,0,,You're just floored, right?\nDialogue: 0,1:14:29.72,1:14:30.72,EN,,0,0,0,,And you haven't done your homework yet.\nDialogue: 0,1:14:30.73,1:14:32.00,EN,,0,0,0,,You haven't come up with a good question.\nDialogue: 0,1:14:36.35,1:14:37.44,EN,,0,0,0,,Oh, well.\nDialogue: 0,1:14:39.97,1:14:42.33,EN,,0,0,0,,Sure, thank you. Let's take the long break now.\nDialogue: 0,1:14:47.90,1:14:56.41,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:14:56.44,1:15:05.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}https://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec5b.chn+eng.ass",
    "content": "[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: EN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nVideo Position: 1\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:21.17,0:00:24.12,EN,,0,0,0,,PROFESSOR: Well, now that we've given you some power\nDialogue: 0,0:00:24.43,0:00:27.40,EN,,0,0,0,,to make independent local state and to model objects,\nDialogue: 0,0:00:28.33,0:00:32.67,EN,,0,0,0,,I thought we'd do a bit of programming of a very complicated kind,\nDialogue: 0,0:00:34.03,0:00:36.36,EN,,0,0,0,,just to illustrate what you can do with this sort of thing.\nDialogue: 0,0:00:40.43,0:00:43.48,EN,,0,0,0,,I suppose, as I said, we were motivated by physical systems\nDialogue: 0,0:00:44.11,0:00:46.25,EN,,0,0,0,,the ways we like to think about physical systems,\nDialogue: 0,0:00:46.99,0:00:51.08,EN,,0,0,0,,which is that there are these things that the world is made out of.\nDialogue: 0,0:00:52.06,0:00:55.98,EN,,0,0,0,,And each of these things has particular independent local state,\nDialogue: 0,0:00:57.24,0:00:59.87,EN,,0,0,0,,and therefore it is a thing. That's what makes it a thing.\nDialogue: 0,0:01:01.28,0:01:04.27,EN,,0,0,0,,And then we're going to say that in the model in the world\nDialogue: 0,0:01:04.28,0:01:09.90,EN,,0,0,0,,we have a world and a model in our minds and in the computer of that world.\nDialogue: 0,0:01:10.94,0:01:12.54,EN,,0,0,0,,And what I want to make is a correspondence\nDialogue: 0,0:01:12.78,0:01:15.21,EN,,0,0,0,,between the objects in the world and the objects in the computer,\nDialogue: 0,0:01:15.87,0:01:17.74,EN,,0,0,0,,the relationships between the objects in the world\nDialogue: 0,0:01:17.96,0:01:21.72,EN,,0,0,0,,and the relationships between those same obj...--the model objects in the computer,\nDialogue: 0,0:01:23.18,0:01:25.52,EN,,0,0,0,,and the functions that relate things in the\nDialogue: 0,0:01:25.93,0:01:28.11,EN,,0,0,0,,to the functions that relate things in the computer.\nDialogue: 0,0:01:30.84,0:01:33.82,EN,,0,0,0,,This buys us modularity.\nDialogue: 0,0:01:34.74,0:01:36.75,EN,,0,0,0,,If we really believe the world is like that,\nDialogue: 0,0:01:37.36,0:01:38.72,EN,,0,0,0,,that it's made out of these little pieces,\nDialogue: 0,0:01:39.20,0:01:41.47,EN,,0,0,0,,and of course we could arrange our world to be like that,\nDialogue: 0,0:01:42.03,0:01:43.95,EN,,0,0,0,,we could only model those things that are like that,\nDialogue: 0,0:01:45.45,0:01:49.02,EN,,0,0,0,,then we can inherit the modularity in the world into our programming.\nDialogue: 0,0:01:50.45,0:01:53.58,EN,,0,0,0,,That's why we would invent some of this object-oriented programming.\nDialogue: 0,0:01:55.42,0:01:58.19,EN,,0,0,0,,Well, let's take the best kind of objects I know.\nDialogue: 0,0:01:58.89,0:02:04.17,EN,,0,0,0,,They're completely--they're completely wonderful: electrical systems.\nDialogue: 0,0:02:06.40,0:02:12.99,EN,,0,0,0,,Electrical systems really are the physicist's best, best objects.\nDialogue: 0,0:02:14.22,0:02:16.76,EN,,0,0,0,,You see over here I have some piece of machinery.\nDialogue: 0,0:02:17.12,0:02:18.28,EN,,0,0,0,,Right here's a piece of machinery.\nDialogue: 0,0:02:20.04,0:02:22.88,EN,,0,0,0,,And it's got an electrical wire connecting\nDialogue: 0,0:02:23.66,0:02:26.40,EN,,0,0,0,,one part of the machinery with another part of the machinery.\nDialogue: 0,0:02:27.56,0:02:30.86,EN,,0,0,0,,And one of the wonderful properties of the electrical world\nDialogue: 0,0:02:31.64,0:02:33.12,EN,,0,0,0,,is that I can say this is an object,\nDialogue: 0,0:02:34.01,0:02:34.97,EN,,0,0,0,,and this is an object,\nDialogue: 0,0:02:35.71,0:02:37.53,EN,,0,0,0,,and they're-- the connection between them is clear.\nDialogue: 0,0:02:38.24,0:02:43.32,EN,,0,0,0,,In principle, there is no connection that I didn't describe with these wires.\nDialogue: 0,0:02:44.74,0:02:46.12,EN,,0,0,0,,Let's say if I have light bulbs,\nDialogue: 0,0:02:46.52,0:02:50.32,EN,,0,0,0,,Let's say if I have light bulbs, a light bulb and a power supply that's plugged into the outlet.\nDialogue: 0,0:02:51.63,0:02:53.53,EN,,0,0,0,,Then the connection is perfectly clear.\nDialogue: 0,0:02:53.62,0:02:55.42,EN,,0,0,0,,There's no other connections that we know of.\nDialogue: 0,0:02:56.22,0:03:02.33,EN,,0,0,0,,If I were to tie a knot in the wire that connects the light bulb to the power supply,\nDialogue: 0,0:03:02.68,0:03:03.64,EN,,0,0,0,,the light remains lit up.\nDialogue: 0,0:03:04.04,0:03:04.76,EN,,0,0,0,,It doesn't care.\nDialogue: 0,0:03:07.44,0:03:12.40,EN,,0,0,0,,That the way the physics is arranged is such that the connection can be made abstract,\nDialogue: 0,0:03:13.08,0:03:15.27,EN,,0,0,0,,at least for low frequencies and things like that.\nDialogue: 0,0:03:17.84,0:03:20.88,EN,,0,0,0,,So in fact, we have captured all of the connections there really are.\nDialogue: 0,0:03:22.35,0:03:23.87,EN,,0,0,0,,Well, as you can go one step further\nDialogue: 0,0:03:23.90,0:03:27.31,EN,,0,0,0,,and talk about the most abstract types of electrical systems we have,\nDialogue: 0,0:03:27.85,0:03:29.42,EN,,0,0,0,,digital to dual circuits.\nDialogue: 0,0:03:31.69,0:03:33.66,EN,,0,0,0,,And here there are certain kinds of objects.\nDialogue: 0,0:03:34.64,0:03:40.12,EN,,0,0,0,,For example, in digital circuits we have things like inverters.\nDialogue: 0,0:03:41.39,0:03:42.78,EN,,0,0,0,,We have things like and-gates.\nDialogue: 0,0:03:43.99,0:03:45.40,EN,,0,0,0,,We have things like or-gates.\nDialogue: 0,0:03:47.21,0:03:50.12,EN,,0,0,0,,We connect them together by sort-of wires\nDialogue: 0,0:03:52.00,0:03:54.94,EN,,0,0,0,,which represent abstract signals.\nDialogue: 0,0:03:55.61,0:03:57.18,EN,,0,0,0,,We don't really care as physical variables\nDialogue: 0,0:03:57.21,0:03:59.72,EN,,0,0,0,,whether these are voltages or currents or some combination\nDialogue: 0,0:04:00.01,0:04:03.44,EN,,0,0,0,,or water, water pressure.\nDialogue: 0,0:04:05.20,0:04:07.32,EN,,0,0,0,,These abstract variables represent certain signals.\nDialogue: 0,0:04:09.42,0:04:12.89,EN,,0,0,0,,And we build systems by wiring these things together with wires.\nDialogue: 0,0:04:14.07,0:04:16.22,EN,,0,0,0,,So today what I'm going to show you, right now,\nDialogue: 0,0:04:17.63,0:04:20.17,EN,,0,0,0,,we're going to build up an invented language in Lisp,\nDialogue: 0,0:04:22.14,0:04:25.08,EN,,0,0,0,,embedded in the same sense that Henderson's picture language was embedded,\nDialogue: 0,0:04:26.16,0:04:27.32,EN,,0,0,0,,which is not the same sense\nDialogue: 0,0:04:27.88,0:04:31.61,EN,,0,0,0,,as the language of pattern match and substitution was done yesterday.\nDialogue: 0,0:04:32.80,0:04:36.30,EN,,0,0,0,,The pattern match substitution language was interpreted by a Lisp program.\nDialogue: 0,0:04:38.16,0:04:40.52,EN,,0,0,0,,But the embedding of Henderson's program\nDialogue: 0,0:04:40.56,0:04:44.27,EN,,0,0,0,,is that we just build up more and more procedures that encapsulate the structure we want.\nDialogue: 0,0:04:45.48,0:04:46.75,EN,,0,0,0,,So for example here,\nDialogue: 0,0:04:47.72,0:04:50.64,EN,,0,0,0,,I'm going to have some various primitive kinds of objects, as you see,\nDialogue: 0,0:04:51.05,0:04:52.12,EN,,0,0,0,,that one and that one.\nDialogue: 0,0:04:53.50,0:04:55.18,EN,,0,0,0,,I'm going to use wires to combine them.\nDialogue: 0,0:04:55.98,0:04:59.37,EN,,0,0,0,,The way I represent attaching-- I can make wires.\nDialogue: 0,0:04:59.87,0:05:01.24,EN,,0,0,0,,So let's say A is a wire.\nDialogue: 0,0:05:01.74,0:05:02.69,EN,,0,0,0,,And B is a wire.\nDialogue: 0,0:05:02.69,0:05:03.46,EN,,0,0,0,,And C is a wire.\nDialogue: 0,0:05:03.46,0:05:04.23,EN,,0,0,0,,And D is a wire.\nDialogue: 0,0:05:04.23,0:05:04.83,EN,,0,0,0,,And E is wire.\nDialogue: 0,0:05:04.83,0:05:05.64,EN,,0,0,0,,And S is a wire.\nDialogue: 0,0:05:06.88,0:05:12.75,EN,,0,0,0,,Well, an or-gate that has both inputs, the inputs being A and B,\nDialogue: 0,0:05:13.16,0:05:14.75,EN,,0,0,0,,and the output being wire D,\nDialogue: 0,0:05:15.07,0:05:16.12,EN,,0,0,0,,you notate like this.\nDialogue: 0,0:05:18.14,0:05:22.14,EN,,0,0,0,,An and-gate, which has inputs A and B and output C,\nDialogue: 0,0:05:22.22,0:05:23.24,EN,,0,0,0,,we notate like that.\nDialogue: 0,0:05:24.82,0:05:28.46,EN,,0,0,0,,By making such a sequence of declarations,\nDialogue: 0,0:05:29.29,0:05:31.64,EN,,0,0,0,,I can wire together an arbitrary circuit.\nDialogue: 0,0:05:32.75,0:05:34.64,EN,,0,0,0,,So I've just told you a set of primitives\nDialogue: 0,0:05:35.31,0:05:38.51,EN,,0,0,0,,and means of combination for building digital circuits,\nDialogue: 0,0:05:40.09,0:05:43.04,EN,,0,0,0,,when I need more in a real language than abstraction.\nDialogue: 0,0:05:43.69,0:05:52.24,EN,,0,0,0,,And so for example, here I have--here I have a half adder.\nDialogue: 0,0:05:52.67,0:05:55.55,EN,,0,0,0,,It's something you all know if you've done any digital design.\nDialogue: 0,0:05:56.93,0:06:00.44,EN,,0,0,0,,It's used for adding numbers together on A and B\nDialogue: 0,0:06:00.62,0:06:02.12,EN,,0,0,0,,and putting out a sum and a carry.\nDialogue: 0,0:06:04.35,0:06:06.80,EN,,0,0,0,,And in fact, the wiring diagram is exactly what I told you.\nDialogue: 0,0:06:07.45,0:06:10.99,EN,,0,0,0,,A half adder with things that come out of the box--\nDialogue: 0,0:06:11.13,0:06:14.11,EN,,0,0,0,,you see the box, the boundary, the abstraction is always a box.\nDialogue: 0,0:06:14.79,0:06:19.70,EN,,0,0,0,,And there are things that come out of it, A, B, S, and C.\nDialogue: 0,0:06:19.70,0:06:21.79,EN,,0,0,0,,Those are the declared variables--\nDialogue: 0,0:06:23.39,0:06:26.25,EN,,0,0,0,,declared variables of a lambda expression,\nDialogue: 0,0:06:26.28,0:06:28.01,EN,,0,0,0,,which is the one that defines half adder.\nDialogue: 0,0:06:31.40,0:06:35.96,EN,,0,0,0,,And internal to that, I make up some more wires, D and E,\nDialogue: 0,0:06:36.00,0:06:37.44,EN,,0,0,0,,which I'm going to use for the interconnect--\nDialogue: 0,0:06:37.74,0:06:40.40,EN,,0,0,0,,here E is this one and D is this wire,\nDialogue: 0,0:06:41.32,0:06:43.50,EN,,0,0,0,,the interconnect that doesn't come through the walls of the box--\nDialogue: 0,0:06:45.05,0:06:46.83,EN,,0,0,0,,and wire things together as you just saw.\nDialogue: 0,0:06:48.79,0:06:50.89,EN,,0,0,0,,And the nice thing about this that I've just shown you\nDialogue: 0,0:06:51.05,0:06:53.02,EN,,0,0,0,,this language is hierarchical in the right way.\nDialogue: 0,0:06:53.85,0:06:55.71,EN,,0,0,0,,If a language isn't hierarchical in the right way,\nDialogue: 0,0:06:55.95,0:06:59.96,EN,,0,0,0,,if it turns out that a compound object doesn't look like a primitive,\nDialogue: 0,0:07:00.38,0:07:01.53,EN,,0,0,0,,there's something wrong with the language--\nDialogue: 0,0:07:02.59,0:07:04.22,EN,,0,0,0,,at least the way I feel about that.\nDialogue: 0,0:07:06.41,0:07:09.58,EN,,0,0,0,,So here we have--here, instead of starting with mathematical functions,\nDialogue: 0,0:07:09.60,0:07:11.12,EN,,0,0,0,,or things that compute mathematical functions,\nDialogue: 0,0:07:11.15,0:07:12.65,EN,,0,0,0,,which is what we've been doing up until now,\nDialogue: 0,0:07:13.85,0:07:16.65,EN,,0,0,0,,instead of starting with things that look like mathematical functions,\nDialogue: 0,0:07:16.67,0:07:17.63,EN,,0,0,0,,or compute such things,\nDialogue: 0,0:07:17.85,0:07:20.88,EN,,0,0,0,,we are starting with things that are electrical objects\nDialogue: 0,0:07:21.04,0:07:22.64,EN,,0,0,0,,and we build up more electrical objects.\nDialogue: 0,0:07:23.35,0:07:28.83,EN,,0,0,0,,And the glue we're using is basically the Lisp structure: lambdas.\nDialogue: 0,0:07:30.38,0:07:32.93,EN,,0,0,0,,Lambda is the ultimate glue, if you will.\nDialogue: 0,0:07:33.32,0:07:36.35,EN,,0,0,0,,And of course, half adder itself can be used\nDialogue: 0,0:07:37.64,0:07:41.04,EN,,0,0,0,,in a more complicated abstraction called a full adder,\nDialogue: 0,0:07:41.60,0:07:45.05,EN,,0,0,0,,which in fact involves two half adders, as you see here,\nDialogue: 0,0:07:45.47,0:07:47.87,EN,,0,0,0,,hooked together with some extra wires,\nDialogue: 0,0:07:48.08,0:07:51.29,EN,,0,0,0,,that you see here, S, C1, and C2, and an or-gate,\nDialogue: 0,0:07:52.19,0:07:53.60,EN,,0,0,0,,to manufacture a full adder,\nDialogue: 0,0:07:53.87,0:08:00.78,EN,,0,0,0,,which takes a input number, another input number, a carry in,\nDialogue: 0,0:08:01.36,0:08:04.17,EN,,0,0,0,,and produces output, a sum and a carry out.\nDialogue: 0,0:08:05.90,0:08:10.70,EN,,0,0,0,,And out of full adders, you can make real adder chains and big adders.\nDialogue: 0,0:08:12.99,0:08:14.83,EN,,0,0,0,,So we have here a language so far\nDialogue: 0,0:08:16.06,0:08:21.76,EN,,0,0,0,,That has primitives, means of combination, and means of abstraction to real language.\nDialogue: 0,0:08:22.27,0:08:23.36,EN,,0,0,0,,Now, how are we going to implement this?\nDialogue: 0,0:08:25.00,0:08:26.84,EN,,0,0,0,,Well, let's do it easily.\nDialogue: 0,0:08:27.07,0:08:27.96,EN,,0,0,0,,Let's look at the primitives.\nDialogue: 0,0:08:28.12,0:08:30.11,EN,,0,0,0,,The only problem is we have to implement the primitives.\nDialogue: 0,0:08:31.16,0:08:32.56,EN,,0,0,0,,Nothing else has to be implemented,\nDialogue: 0,0:08:33.74,0:08:38.00,EN,,0,0,0,,because we're picking up the means of combination and abstraction from Lisp,\nDialogue: 0,0:08:39.96,0:08:41.88,EN,,0,0,0,,inheriting them in the embedding.\nDialogue: 0,0:08:43.77,0:08:45.44,EN,,0,0,0,,OK, so let's look at a particular primitive.\nDialogue: 0,0:08:45.86,0:08:47.40,EN,,0,0,0,,An inverter is a nice one.\nDialogue: 0,0:08:51.54,0:08:54.67,EN,,0,0,0,,Now, inverter has two wires coming in, an in and an out.\nDialogue: 0,0:08:57.31,0:09:02.62,EN,,0,0,0,,And somehow, it's going to have to know what to do when a signal comes in.\nDialogue: 0,0:09:04.30,0:09:07.00,EN,,0,0,0,,So somehow it's going to have to tell its input wire--\nDialogue: 0,0:09:07.64,0:09:10.14,EN,,0,0,0,,and now we're going to talk about objects\nDialogue: 0,0:09:10.44,0:09:12.41,EN,,0,0,0,,and we're going to see this in a little more detail soon--\nDialogue: 0,0:09:13.23,0:09:14.84,EN,,0,0,0,,but it's going to have to tell its input wire\nDialogue: 0,0:09:15.82,0:09:18.48,EN,,0,0,0,,that when you change, tell me.\nDialogue: 0,0:09:20.12,0:09:22.11,EN,,0,0,0,,So this object, the object which is the inverter\nDialogue: 0,0:09:22.41,0:09:24.38,EN,,0,0,0,,has to tell the object which is the input wire,\nDialogue: 0,0:09:25.13,0:09:26.40,EN,,0,0,0,,hi, my name is George.\nDialogue: 0,0:09:26.87,0:09:31.02,EN,,0,0,0,,And my, my job is to do something with results when you change.\nDialogue: 0,0:09:31.72,0:09:34.19,EN,,0,0,0,,So when you change, you get a change, tell me about it.\nDialogue: 0,0:09:34.73,0:09:35.72,EN,,0,0,0,,Because I've got to do something with that.\nDialogue: 0,0:09:36.88,0:09:40.30,EN,,0,0,0,,Well, that's done down here by adding an action on the input wire called invert-in,\nDialogue: 0,0:09:41.40,0:09:44.64,EN,,0,0,0,,Well, that's done down here by adding an action on the input wire called invert-in,\nDialogue: 0,0:09:45.07,0:09:46.94,EN,,0,0,0,,where invert-in is defined over here\nDialogue: 0,0:09:47.05,0:09:48.76,EN,,0,0,0,,to be a procedure of no arguments,\nDialogue: 0,0:09:49.98,0:09:54.59,EN,,0,0,0,,which gets the logical not of the signal on the input wire.\nDialogue: 0,0:09:56.06,0:09:58.64,EN,,0,0,0,,And after some delay, which is the inverter delay,\nDialogue: 0,0:09:59.26,0:10:01.15,EN,,0,0,0,,all these electrical objects have delays,\nDialogue: 0,0:10:02.88,0:10:04.46,EN,,0,0,0,,we'll do the following thing--\nDialogue: 0,0:10:04.67,0:10:07.14,EN,,0,0,0,,set the signal on the output wire to the new value.\nDialogue: 0,0:10:10.16,0:10:11.36,EN,,0,0,0,,A very simple program.\nDialogue: 0,0:10:12.40,0:10:15.28,EN,,0,0,0,,Now, you have to imagine that the output wire has to be sensitive\nDialogue: 0,0:10:15.77,0:10:18.27,EN,,0,0,0,,and know that when its signal changes,\nDialogue: 0,0:10:19.28,0:10:21.15,EN,,0,0,0,,it may have to tell other guys,\nDialogue: 0,0:10:21.79,0:10:24.78,EN,,0,0,0,,Hi, wake up. My value has changed.\nDialogue: 0,0:10:26.05,0:10:30.14,EN,,0,0,0,,So when you hook together inverter with an and-gate or something like that,\nDialogue: 0,0:10:30.46,0:10:32.20,EN,,0,0,0,,there has to be a lot of communication going on\nDialogue: 0,0:10:32.86,0:10:35.07,EN,,0,0,0,,to make sure that the signal propagates right.\nDialogue: 0,0:10:36.81,0:10:38.62,EN,,0,0,0,,And down here is nothing very exciting.\nDialogue: 0,0:10:38.62,0:10:40.72,EN,,0,0,0,,This is just the definition of logical not\nDialogue: 0,0:10:40.72,0:10:45.24,EN,,0,0,0,,for some particular representations of the logical values-- 1, 0 in this case.\nDialogue: 0,0:10:46.73,0:10:49.16,EN,,0,0,0,,And we can look at things more complicated like and-gates.\nDialogue: 0,0:10:49.78,0:10:55.80,EN,,0,0,0,,And-gates take two inputs, A1 and A2, we'll call them, and produce an output.\nDialogue: 0,0:10:56.73,0:11:00.64,EN,,0,0,0,,But the structure of the and-gate is identical to the one we just saw.\nDialogue: 0,0:11:00.86,0:11:03.44,EN,,0,0,0,,There's one called an and-action procedure that's defined,\nDialogue: 0,0:11:04.52,0:11:09.07,EN,,0,0,0,,which is the thing that gets called when an input is changed.\nDialogue: 0,0:11:10.91,0:11:12.88,EN,,0,0,0,,And what it does, of course, is nothing more than\nDialogue: 0,0:11:12.91,0:11:15.37,EN,,0,0,0,,compute the logical and of the signals on the inputs.\nDialogue: 0,0:11:16.19,0:11:18.76,EN,,0,0,0,,And after some delay, called the and-gate-delay,\nDialogue: 0,0:11:20.46,0:11:24.36,EN,,0,0,0,,calls this procedure, which sets a signal on the output to a new value.\nDialogue: 0,0:11:25.47,0:11:28.35,EN,,0,0,0,,Now, how I implement these things is all wishful thinking.\nDialogue: 0,0:11:28.35,0:11:31.08,EN,,0,0,0,,As you see here, I have an assignment operation.\nDialogue: 0,0:11:32.02,0:11:32.78,EN,,0,0,0,,It's not set.\nDialogue: 0,0:11:34.57,0:11:36.78,EN,,0,0,0,,It's a derived assignment operation in the same way\nDialogue: 0,0:11:36.78,0:11:38.73,EN,,0,0,0,,we had functions that were derived from CAR and CDR.\nDialogue: 0,0:11:40.80,0:11:44.81,EN,,0,0,0,,So I, by convention, label that with an exclamation point.\nDialogue: 0,0:11:46.34,0:11:49.18,EN,,0,0,0,,And over here, you see there's an add-action!,\nDialogue: 0,0:11:49.44,0:11:54.67,EN,,0,0,0,,which is to inform the wire, called A1 locally in this and-gate,\nDialogue: 0,0:11:55.63,0:11:58.68,EN,,0,0,0,,to call the and-action-procedure when it gets changed,\nDialogue: 0,0:11:59.58,0:12:02.91,EN,,0,0,0,,and the wire A2 to call the and-action procedure when it gets changed.\nDialogue: 0,0:12:06.31,0:12:07.23,EN,,0,0,0,,All very simple.\nDialogue: 0,0:12:09.96,0:12:12.09,EN,,0,0,0,,Well, let's talk a little bit about this communication\nDialogue: 0,0:12:12.70,0:12:16.12,EN,,0,0,0,,that must occur between these various parts.\nDialogue: 0,0:12:18.54,0:12:19.66,EN,,0,0,0,,Suppose, for example,\nDialogue: 0,0:12:23.12,0:12:24.27,EN,,0,0,0,,I have a very simple circuit\nDialogue: 0,0:12:24.27,0:12:30.46,EN,,0,0,0,,which contains and-gate with wires a and b.\nDialogue: 0,0:12:31.92,0:12:38.00,EN,,0,0,0,,And that connects through a wire called c to an inverter\nDialogue: 0,0:12:39.72,0:12:41.53,EN,,0,0,0,,which has a wire output called d.\nDialogue: 0,0:12:44.20,0:12:47.34,EN,,0,0,0,,What are the comput...--here's the physical world.\nDialogue: 0,0:12:47.36,0:12:49.02,EN,,0,0,0,,It's an abstraction of the physical world.\nDialogue: 0,0:12:49.86,0:12:53.40,EN,,0,0,0,,Now I can buy these out of little pieces that you get at Radio Shack for a few cents.\nDialogue: 0,0:12:54.88,0:12:56.32,EN,,0,0,0,,And there are boxes that act like this,\nDialogue: 0,0:12:57.16,0:13:00.22,EN,,0,0,0,,which have little numbers on them like LS04 or something.\nDialogue: 0,0:13:01.53,0:13:08.16,EN,,0,0,0,,Now supposing I were to try to say what's the computational model.\nDialogue: 0,0:13:09.01,0:13:10.94,EN,,0,0,0,,What is the thing that corresponds to that,\nDialogue: 0,0:13:11.13,0:13:14.09,EN,,0,0,0,,that part of reality in the mind of us and in the computer?\nDialogue: 0,0:13:15.85,0:13:19.13,EN,,0,0,0,,Well, I have to assign for every object in the world an object in the computer,\nDialogue: 0,0:13:19.79,0:13:24.27,EN,,0,0,0,,and for every relationship in the world between them a relationship in the computer.\nDialogue: 0,0:13:26.06,0:13:26.80,EN,,0,0,0,,That's my goal.\nDialogue: 0,0:13:28.56,0:13:29.45,EN,,0,0,0,,So let's do that.\nDialogue: 0,0:13:30.90,0:13:34.20,EN,,0,0,0,,Well, I have some sort of thing called the signal, A.\nDialogue: 0,0:13:35.71,0:13:36.94,EN,,0,0,0,,This is A. It's a signal.\nDialogue: 0,0:13:37.94,0:13:39.32,EN,,0,0,0,,It's a cloudy thing like that.\nDialogue: 0,0:13:39.90,0:13:42.80,EN,,0,0,0,,And I have another one down here which I'm going to call B.\nDialogue: 0,0:13:46.68,0:13:47.47,EN,,0,0,0,,It's another signal.\nDialogue: 0,0:13:49.14,0:13:50.91,EN,,0,0,0,,Now this signal--these two signals\nDialogue: 0,0:13:51.10,0:13:52.81,EN,,0,0,0,,are somehow going to have to hook together\nDialogue: 0,0:13:53.72,0:13:58.75,EN,,0,0,0,,into a box, let's call it this, which is the and-gate, action procedure.\nDialogue: 0,0:14:00.32,0:14:02.04,EN,,0,0,0,,That's the and-gate's action procedure.\nDialogue: 0,0:14:07.66,0:14:08.59,EN,,0,0,0,,And it's going to produce\nDialogue: 0,0:14:09.15,0:14:13.29,EN,,0,0,0,,well, it's going to interact with a signal object, which we call C--\nDialogue: 0,0:14:16.22,0:14:18.88,EN,,0,0,0,,a wire object, excuse me, we call C.\nDialogue: 0,0:14:20.59,0:14:26.28,EN,,0,0,0,,this is going to put out again, or connect to, another action procedure\nDialogue: 0,0:14:26.28,0:14:30.33,EN,,0,0,0,,which is one associated with the inverter in the world, not.\nDialogue: 0,0:14:32.86,0:14:40.65,EN,,0,0,0,,And I'm going to have another--another wire, which we'll call D.\nDialogue: 0,0:14:42.97,0:14:45.29,EN,,0,0,0,,So here's my layout of stuff.\nDialogue: 0,0:14:46.00,0:14:49.44,EN,,0,0,0,,Now we have to say what's inside them and what they have to know to compute.\nDialogue: 0,0:14:51.50,0:14:53.69,EN,,0,0,0,,Well, every--every one of these wires has to know\nDialogue: 0,0:14:53.69,0:14:56.36,EN,,0,0,0,,what the value of the signal that's on that wire is.\nDialogue: 0,0:14:57.34,0:15:00.00,EN,,0,0,0,,So there's going to be some variable inside here, we'll call it signal.\nDialogue: 0,0:15:02.97,0:15:04.04,EN,,0,0,0,,And he owns a value.\nDialogue: 0,0:15:05.68,0:15:07.74,EN,,0,0,0,,So there must be some environment associated with this.\nDialogue: 0,0:15:08.89,0:15:11.34,EN,,0,0,0,,And for each one of these, there must be an environment that binds signal.\nDialogue: 0,0:15:15.40,0:15:16.88,EN,,0,0,0,,And there must be a signal here, therefore.\nDialogue: 0,0:15:19.40,0:15:21.92,EN,,0,0,0,,And presumably, signal's a value that's either 1 or 0,\nDialogue: 0,0:15:22.81,0:15:23.48,EN,,0,0,0,,and signal.\nDialogue: 0,0:15:28.00,0:15:30.56,EN,,0,0,0,,Now, we also have to have some\nDialogue: 0,0:15:31.26,0:15:34.11,EN,,0,0,0,,list of people to inform if the signal here changes.\nDialogue: 0,0:15:36.66,0:15:37.66,EN,,0,0,0,,We're going to have to inform this.\nDialogue: 0,0:15:39.30,0:15:43.96,EN,,0,0,0,,So I've got that list. We'll call it the Action Procedures, AP.\nDialogue: 0,0:15:44.50,0:15:45.60,EN,,0,0,0,,And it's presumably a list.\nDialogue: 0,0:15:46.44,0:15:49.00,EN,,0,0,0,,But the first thing on the list, in this case, is this guy.\nDialogue: 0,0:15:50.50,0:15:54.81,EN,,0,0,0,,And the action procedures of this one happens to have some list of stuff.\nDialogue: 0,0:15:54.81,0:15:58.17,EN,,0,0,0,,There might be other people who are sharing A, who are looking at it.\nDialogue: 0,0:15:59.02,0:16:01.31,EN,,0,0,0,,So there might be other guys on this list, like\nDialogue: 0,0:16:01.72,0:16:03.23,EN,,0,0,0,,like somebody over there that we don't know about.\nDialogue: 0,0:16:03.63,0:16:04.88,EN,,0,0,0,,It's the other guy attached to A.\nDialogue: 0,0:16:07.20,0:16:09.64,EN,,0,0,0,,And the action procedure here also has to point to that,\nDialogue: 0,0:16:11.12,0:16:12.40,EN,,0,0,0,,the list of action procedures.\nDialogue: 0,0:16:13.07,0:16:16.35,EN,,0,0,0,,And of course, that means this one, its action procedures\nDialogue: 0,0:16:16.78,0:16:18.53,EN,,0,0,0,,has to point up to here.\nDialogue: 0,0:16:18.53,0:16:20.89,EN,,0,0,0,,This is the things-- the people it has to inform.\nDialogue: 0,0:16:21.77,0:16:23.18,EN,,0,0,0,,And this guy has some too.\nDialogue: 0,0:16:24.28,0:16:25.24,EN,,0,0,0,,But I don't know what they are\nDialogue: 0,0:16:25.26,0:16:26.65,EN,,0,0,0,,because I didn't draw it in my diagram.\nDialogue: 0,0:16:27.19,0:16:28.36,EN,,0,0,0,,It's the things connected to D.\nDialogue: 0,0:16:30.32,0:16:32.62,EN,,0,0,0,,Now, it's also the case\nDialogue: 0,0:16:33.80,0:16:36.96,EN,,0,0,0,,that when the and-action procedure is awakened,\nDialogue: 0,0:16:37.02,0:16:41.31,EN,,0,0,0,,saying one of the people who know that you've told\nDialogue: 0,0:16:41.45,0:16:44.84,EN,,0,0,0,,one of the people you've told to wake you up if their signal changes,\nDialogue: 0,0:16:46.97,0:16:48.81,EN,,0,0,0,,you have to go look and ask them what's their signal\nDialogue: 0,0:16:49.32,0:16:52.25,EN,,0,0,0,,so you can do the and, and produce a signal for this one.\nDialogue: 0,0:16:57.09,0:16:58.75,EN,,0,0,0,,So there has to be, for example,\nDialogue: 0,0:16:58.84,0:17:03.00,EN,,0,0,0,,information here saying A1, my A1 is this guy,\nDialogue: 0,0:17:03.90,0:17:06.48,EN,,0,0,0,,my A1 is this guy, and my A2 is this guy.\nDialogue: 0,0:17:08.93,0:17:09.98,EN,,0,0,0,,And not only that,\nDialogue: 0,0:17:11.79,0:17:15.20,EN,,0,0,0,,when I do my and, I'm going to have to tell this guy something.\nDialogue: 0,0:17:16.30,0:17:21.05,EN,,0,0,0,,So I need an output--  being this guy.\nDialogue: 0,0:17:25.80,0:17:30.03,EN,,0,0,0,,And similarly, this guy's going to have a thing called the input\nDialogue: 0,0:17:32.38,0:17:34.92,EN,,0,0,0,,that he interrogates to find out\nDialogue: 0,0:17:36.75,0:17:38.64,EN,,0,0,0,,what the value of the signal on the input is,\nDialogue: 0,0:17:38.64,0:17:40.09,EN,,0,0,0,,when the signal wakes up and says, I've changed,\nDialogue: 0,0:17:41.05,0:17:43.47,EN,,0,0,0,,and sends a message this way saying, I've changed.\nDialogue: 0,0:17:43.52,0:17:45.53,EN,,0,0,0,,This guy says, OK, what's your value now?\nDialogue: 0,0:17:46.90,0:17:50.12,EN,,0,0,0,,When he gets that value, then he's going to have to say,\nDialogue: 0,0:17:50.14,0:17:55.86,EN,,0,0,0,,OK, output changes this guy, changes this guy.\nDialogue: 0,0:18:00.60,0:18:01.24,EN,,0,0,0,,And so on.\nDialogue: 0,0:18:02.84,0:18:04.56,EN,,0,0,0,,And so I have to have at least that much connected-ness.\nDialogue: 0,0:18:06.24,0:18:09.23,EN,,0,0,0,,Now, let's go back and look, for example, at the and-gate.\nDialogue: 0,0:18:10.26,0:18:12.09,EN,,0,0,0,,Here we are back on this slide.\nDialogue: 0,0:18:13.67,0:18:15.04,EN,,0,0,0,,And we can see some of these parts.\nDialogue: 0,0:18:16.04,0:18:19.32,EN,,0,0,0,,For any particular and-gate, there is an A1, there is an A2, and the output.\nDialogue: 0,0:18:21.03,0:18:23.53,EN,,0,0,0,,And those are, those are\nDialogue: 0,0:18:25.08,0:18:28.16,EN,,0,0,0,,an environment that was created at the--those produce a frame\nDialogue: 0,0:18:28.41,0:18:31.24,EN,,0,0,0,,at the time and-gate was called,\nDialogue: 0,0:18:33.31,0:18:35.90,EN,,0,0,0,,A frame where A1, A2, and output are--\nDialogue: 0,0:18:36.67,0:18:39.20,EN,,0,0,0,,have as their values, they're bound to\nDialogue: 0,0:18:39.60,0:18:44.25,EN,,0,0,0,,the wires which, they are--which were passed in.\nDialogue: 0,0:18:46.24,0:18:47.31,EN,,0,0,0,,In that environment,\nDialogue: 0,0:18:47.74,0:18:49.85,EN,,0,0,0,,I constructed a procedure\nDialogue: 0,0:18:50.97,0:18:53.68,EN,,0,0,0,,this one right there.\nDialogue: 0,0:18:54.59,0:18:57.31,EN,,0,0,0,,And-action-procedure was constructed in that environment.\nDialogue: 0,0:18:58.35,0:19:00.70,EN,,0,0,0,,That was the result of evaluating a lambda expression.\nDialogue: 0,0:19:01.62,0:19:05.48,EN,,0,0,0,,So it hangs onto the frame where these were defined.\nDialogue: 0,0:19:07.16,0:19:09.34,EN,,0,0,0,,Local--part of its local state is that.\nDialogue: 0,0:19:11.70,0:19:13.47,EN,,0,0,0,,The and-action-procedure, therefore, has\nDialogue: 0,0:19:13.64,0:19:16.94,EN,,0,0,0,,access to A1, A2, and output as we see here.\nDialogue: 0,0:19:17.31,0:19:19.64,EN,,0,0,0,,A1, A2, and output.\nDialogue: 0,0:19:22.36,0:19:23.95,EN,,0,0,0,,Now, we haven't looked inside of a wire yet.\nDialogue: 0,0:19:26.03,0:19:26.99,EN,,0,0,0,,That's all that remains.\nDialogue: 0,0:19:29.03,0:19:29.92,EN,,0,0,0,,Let's look at a wire.\nDialogue: 0,0:19:33.52,0:19:36.25,EN,,0,0,0,,Like the overhead, very good.\nDialogue: 0,0:19:39.50,0:19:42.56,EN,,0,0,0,,Well, the wire, again, is a, is a somewhat complicated mess.\nDialogue: 0,0:19:43.09,0:19:44.64,EN,,0,0,0,,Ooh, wrong one.\nDialogue: 0,0:19:47.05,0:19:48.75,EN,,0,0,0,,It's a big complicated mess, like that.\nDialogue: 0,0:19:50.06,0:19:53.10,EN,,0,0,0,,But let's look at it in detail and see what's going on.\nDialogue: 0,0:19:54.72,0:19:56.67,EN,,0,0,0,,Well, the wire is one of these.\nDialogue: 0,0:19:57.76,0:20:03.52,EN,,0,0,0,,And it has to have two things that are part of it, that it's state.\nDialogue: 0,0:20:05.01,0:20:07.39,EN,,0,0,0,,One of them is the signal we see here.\nDialogue: 0,0:20:07.45,0:20:10.06,EN,,0,0,0,,Heres, when we call make-wire to make a wire,\nDialogue: 0,0:20:10.46,0:20:13.02,EN,,0,0,0,,then the first thing we do is we create some variables\nDialogue: 0,0:20:14.94,0:20:16.08,EN,,0,0,0,,which are the signal\nDialogue: 0,0:20:17.10,0:20:19.29,EN,,0,0,0,,and the action procedures for this wire.\nDialogue: 0,0:20:22.32,0:20:23.44,EN,,0,0,0,,And in that context,\nDialogue: 0,0:20:23.76,0:20:27.04,EN,,0,0,0,,we define various functions--or procedures, excuse me, procedures.\nDialogue: 0,0:20:27.84,0:20:31.15,EN,,0,0,0,,One of them is called set-my-signal to a new value.\nDialogue: 0,0:20:32.85,0:20:37.42,EN,,0,0,0,,And what that does is takes a new value in.\nDialogue: 0,0:20:37.93,0:20:40.36,EN,,0,0,0,,If that's equal to my current value of my signal, I'm done.\nDialogue: 0,0:20:40.36,0:20:42.62,EN,,0,0,0,,Otherwise, I set the signal to the new value\nDialogue: 0,0:20:42.75,0:20:44.60,EN,,0,0,0,,and call each of the action procedures\nDialogue: 0,0:20:46.52,0:20:52.51,EN,,0,0,0,,that I've been, that I've been--what's the right word? --  introduced to.\nDialogue: 0,0:20:54.63,0:21:01.53,EN,,0,0,0,,I get introduced when the and-gate was applied to me.\nDialogue: 0,0:21:04.13,0:21:05.60,EN,,0,0,0,,By add action procedure at the bottom.\nDialogue: 0,0:21:07.41,0:21:10.80,EN,,0,0,0,,Also, I have to define a way of accepting an action procedure--\nDialogue: 0,0:21:10.81,0:21:11.82,EN,,0,0,0,,which is what you see here---\nDialogue: 0,0:21:12.80,0:21:15.13,EN,,0,0,0,,which increments my action procedures\nDialogue: 0,0:21:15.56,0:21:21.63,EN,,0,0,0,,using set to the result of CONSing up a new process--a procedure,\nDialogue: 0,0:21:21.79,0:21:24.25,EN,,0,0,0,,which is passed to me, on to my actions procedures list.\nDialogue: 0,0:21:25.40,0:21:27.58,EN,,0,0,0,,And for technical reasons, I have to call that procedure one.\nDialogue: 0,0:21:27.78,0:21:29.20,EN,,0,0,0,,So I'm not going to tell you anything about that,\nDialogue: 0,0:21:29.39,0:21:33.15,EN,,0,0,0,,that has to do with event-driven simulations and getting them started,\nDialogue: 0,0:21:34.59,0:21:36.00,EN,,0,0,0,,which takes a little bit of thinking.\nDialogue: 0,0:21:36.95,0:21:39.40,EN,,0,0,0,,And finally, I'm going to define a thing called the dispatcher,\nDialogue: 0,0:21:39.96,0:21:43.58,EN,,0,0,0,,which is a way of passing a message to a wire,\nDialogue: 0,0:21:45.37,0:21:48.65,EN,,0,0,0,,which is going to be used to extract from it various information,\nDialogue: 0,0:21:49.07,0:21:51.48,EN,,0,0,0,,like what is the current signal value?\nDialogue: 0,0:21:53.82,0:21:55.66,EN,,0,0,0,,What is the method of setting your signal?\nDialogue: 0,0:21:57.18,0:21:58.28,EN,,0,0,0,,I want to get that out of it.\nDialogue: 0,0:22:00.10,0:22:02.60,EN,,0,0,0,,How do I--how do I add another action procedure?\nDialogue: 0,0:22:05.51,0:22:09.36,EN,,0,0,0,,And I'm going to return that dispatch, that procedure as a value.\nDialogue: 0,0:22:09.94,0:22:11.87,EN,,0,0,0,,So the wire that I've constructed\nDialogue: 0,0:22:12.00,0:22:13.55,EN,,0,0,0,,is a message accepting object\nDialogue: 0,0:22:14.25,0:22:16.01,EN,,0,0,0,,which accepts a message like, like\nDialogue: 0,0:22:16.44,0:22:18.36,EN,,0,0,0,,what's your method of adding action procedures?\nDialogue: 0,0:22:19.92,0:22:21.00,EN,,0,0,0,,That it'll give me a procedure,\nDialogue: 0,0:22:21.64,0:22:23.05,EN,,0,0,0,,which is the add action procedure,\nDialogue: 0,0:22:23.07,0:22:26.54,EN,,0,0,0,,which I can then apply to an action procedure\nDialogue: 0,0:22:27.05,0:22:29.01,EN,,0,0,0,,to create another action procedure in the wire.\nDialogue: 0,0:22:31.62,0:22:32.82,EN,,0,0,0,,So that's a permission.\nDialogue: 0,0:22:33.20,0:22:36.08,EN,,0,0,0,,So it's given me permission to change your action procedures.\nDialogue: 0,0:22:37.82,0:22:40.16,EN,,0,0,0,,And in fact, you can see that over here.\nDialogue: 0,0:22:41.71,0:22:42.32,EN,,0,0,0,,Next slide.\nDialogue: 0,0:22:43.53,0:22:43.82,EN,,0,0,0,,Ah.\nDialogue: 0,0:22:47.76,0:22:49.12,EN,,0,0,0,,This is nothing very interesting.\nDialogue: 0,0:22:49.12,0:22:50.65,EN,,0,0,0,,The call each of the action procedures\nDialogue: 0,0:22:50.89,0:22:52.57,EN,,0,0,0,,is just a CDRing down a list.\nDialogue: 0,0:22:52.73,0:22:54.60,EN,,0,0,0,,And I'm not going to even talk about that anymore.\nDialogue: 0,0:22:54.99,0:22:56.25,EN,,0,0,0,,We're too advanced for that.\nDialogue: 0,0:22:57.56,0:23:00.67,EN,,0,0,0,,However, if I want to get a signal from a wire,\nDialogue: 0,0:23:01.02,0:23:02.54,EN,,0,0,0,,I ask the wire-- which is,\nDialogue: 0,0:23:02.54,0:23:03.09,EN,,0,0,0,,what is the wire?\nDialogue: 0,0:23:03.09,0:23:05.40,EN,,0,0,0,,The wire is the dispatch returned by creating the wire.\nDialogue: 0,0:23:05.86,0:23:06.48,EN,,0,0,0,,It's a procedure.\nDialogue: 0,0:23:06.83,0:23:12.27,EN,,0,0,0,,I call that dispatch on the message get-signal.\nDialogue: 0,0:23:12.91,0:23:15.40,EN,,0,0,0,,And what I should expect to get is a method of getting a signal.\nDialogue: 0,0:23:16.90,0:23:17.96,EN,,0,0,0,,Or actually, I get the signal.\nDialogue: 0,0:23:19.22,0:23:20.52,EN,,0,0,0,,If I want to set a signal,\nDialogue: 0,0:23:22.65,0:23:23.96,EN,,0,0,0,,I want to change a signal,\nDialogue: 0,0:23:24.51,0:23:26.76,EN,,0,0,0,,then what I'm going to do\nDialogue: 0,0:23:26.92,0:23:29.69,EN,,0,0,0,,is take a wire as an argument and a new value for the signal,\nDialogue: 0,0:23:30.01,0:23:32.43,EN,,0,0,0,,I would ask the wire for permission to set the signal\nDialogue: 0,0:23:32.84,0:23:37.61,EN,,0,0,0,,and use that permission, which is a procedure, on the new value.\nDialogue: 0,0:23:38.70,0:23:40.51,EN,,0,0,0,,And if we go back to the overhead here,\nDialogue: 0,0:23:41.64,0:23:43.24,EN,,0,0,0,,Okay, thank you,\nDialogue: 0,0:23:44.20,0:23:45.63,EN,,0,0,0,,we go back to the overhead here,\nDialogue: 0,0:23:45.92,0:23:48.75,EN,,0,0,0,,we see that the method-- if I ask for the method of setting the signal,\nDialogue: 0,0:23:49.34,0:23:50.44,EN,,0,0,0,,that's over here,\nDialogue: 0,0:23:52.25,0:23:55.69,EN,,0,0,0,,it's set-my-signal, a procedure that's defined inside the wire,\nDialogue: 0,0:23:56.25,0:23:57.69,EN,,0,0,0,,which if we look over here\nDialogue: 0,0:23:58.72,0:23:59.74,EN,,0,0,0,,is the thing that says\nDialogue: 0,0:24:00.43,0:24:02.68,EN,,0,0,0,,set my internal value called the signal,\nDialogue: 0,0:24:02.73,0:24:05.50,EN,,0,0,0,,my internal variable, which is the signal,\nDialogue: 0,0:24:07.61,0:24:10.03,EN,,0,0,0,,to the new value, which is passed to me as an argument,\nDialogue: 0,0:24:10.78,0:24:13.01,EN,,0,0,0,,and then call each of the action procedures waking them up.\nDialogue: 0,0:24:16.34,0:24:16.99,EN,,0,0,0,,Very simple.\nDialogue: 0,0:24:19.24,0:24:20.76,EN,,0,0,0,,Ok, Going back to that slide,\nDialogue: 0,0:24:22.48,0:24:24.32,EN,,0,0,0,,we also have the one last thing--\nDialogue: 0,0:24:24.36,0:24:27.31,EN,,0,0,0,,which I suppose now you can easily work out for yourself--\nDialogue: 0,0:24:27.77,0:24:29.15,EN,,0,0,0,,is the way you add an action.\nDialogue: 0,0:24:30.10,0:24:35.18,EN,,0,0,0,,You take a wire--a wire and an action procedure.\nDialogue: 0,0:24:36.47,0:24:39.31,EN,,0,0,0,,And I ask the wire for permission to add an action.\nDialogue: 0,0:24:40.05,0:24:44.22,EN,,0,0,0,,Getting that permission, I use that permission to give it an action procedure.\nDialogue: 0,0:24:45.84,0:24:47.08,EN,,0,0,0,,So that's a real object.\nDialogue: 0,0:24:48.57,0:24:50.32,EN,,0,0,0,,There's a few more details about this.\nDialogue: 0,0:24:52.46,0:24:58.39,EN,,0,0,0,,For example, how am I going to control this thing?\nDialogue: 0,0:24:58.39,0:24:59.69,EN,,0,0,0,,How do I do these delays?\nDialogue: 0,0:25:00.99,0:25:02.54,EN,,0,0,0,,Okay? Let's look at that for a second.\nDialogue: 0,0:25:05.50,0:25:07.98,EN,,0,0,0,,The next one here.\nDialogue: 0,0:25:08.36,0:25:08.88,EN,,0,0,0,,Let's see.\nDialogue: 0,0:25:09.57,0:25:14.17,EN,,0,0,0,,We know when we looked at the and-gate or the not-gate\nDialogue: 0,0:25:15.31,0:25:17.00,EN,,0,0,0,,that when a signal changed on the input,\nDialogue: 0,0:25:17.24,0:25:18.19,EN,,0,0,0,,there was a delay.\nDialogue: 0,0:25:18.77,0:25:21.24,EN,,0,0,0,,And then it was going to call the procedure,\nDialogue: 0,0:25:21.63,0:25:23.00,EN,,0,0,0,,which was going to change the output.\nDialogue: 0,0:25:26.04,0:25:27.92,EN,,0,0,0,,Well, how are we going to do this?\nDialogue: 0,0:25:28.12,0:25:29.92,EN,,0,0,0,,We're going to make up some mechanism,\nDialogue: 0,0:25:30.30,0:25:32.00,EN,,0,0,0,,a fairly complicated mechanism at that,\nDialogue: 0,0:25:32.33,0:25:33.76,EN,,0,0,0,,which we're going to have to be very careful about.\nDialogue: 0,0:25:34.72,0:25:37.23,EN,,0,0,0,,But after a delay, we're going to do an action.\nDialogue: 0,0:25:37.39,0:25:38.12,EN,,0,0,0,,A delay is a number,\nDialogue: 0,0:25:38.16,0:25:39.23,EN,,0,0,0,,and an action is a procedure.\nDialogue: 0,0:25:40.59,0:25:43.72,EN,,0,0,0,,What that's going to be is they're going to have a special structure called an agenda,\nDialogue: 0,0:25:45.50,0:25:48.80,EN,,0,0,0,,which is a thing that organizes time and actions.\nDialogue: 0,0:25:49.51,0:25:50.88,EN,,0,0,0,,And we're going to see that in a while.\nDialogue: 0,0:25:50.88,0:25:52.54,EN,,0,0,0,,I don't want to get into that right now.\nDialogue: 0,0:25:53.07,0:25:58.28,EN,,0,0,0,,But the agenda has a moment at which--at which something happens.\nDialogue: 0,0:25:59.13,0:26:02.46,EN,,0,0,0,,We're setting up for later at some moment,\nDialogue: 0,0:26:02.51,0:26:05.68,EN,,0,0,0,,which is the sum of the time, which is the delay time plus the current time,\nDialogue: 0,0:26:05.69,0:26:07.13,EN,,0,0,0,,which the agenda thinks is now.\nDialogue: 0,0:26:09.02,0:26:10.56,EN,,0,0,0,,We're going to set up to do this action,\nDialogue: 0,0:26:11.02,0:26:12.40,EN,,0,0,0,,and add that to the agenda.\nDialogue: 0,0:26:15.28,0:26:18.03,EN,,0,0,0,,And the way this machine will now run is very simple.\nDialogue: 0,0:26:18.66,0:26:21.48,EN,,0,0,0,,We have a thing called propagate, which is the way things run.\nDialogue: 0,0:26:22.71,0:26:25.95,EN,,0,0,0,,If the agenda is empty, we're done--if there's nothing more to be done.\nDialogue: 0,0:26:27.44,0:26:28.16,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:26:29.76,0:26:31.53,EN,,0,0,0,,we're going to take the first item off the agenda,\nDialogue: 0,0:26:31.71,0:26:33.34,EN,,0,0,0,,and that's a procedure of no arguments.\nDialogue: 0,0:26:34.20,0:26:36.03,EN,,0,0,0,,So that we're going to see extra parentheses here.\nDialogue: 0,0:26:36.03,0:26:37.85,EN,,0,0,0,,We call that on no arguments.\nDialogue: 0,0:26:39.19,0:26:40.17,EN,,0,0,0,,That takes the action.\nDialogue: 0,0:26:42.20,0:26:44.17,EN,,0,0,0,,Then we remove that first item from the agenda,\nDialogue: 0,0:26:44.59,0:26:46.14,EN,,0,0,0,,and we go around the propagation loop.\nDialogue: 0,0:26:48.91,0:26:50.75,EN,,0,0,0,,So that's the overall structure of this thing.\nDialogue: 0,0:26:53.38,0:26:55.93,EN,,0,0,0,,Now, there's a, a few other things we can look at.\nDialogue: 0,0:26:57.43,0:27:00.01,EN,,0,0,0,,And then we're going to look into the agenda a little while from now.\nDialogue: 0,0:27:00.57,0:27:01.55,EN,,0,0,0,,Now the overhead again.\nDialogue: 0,0:27:02.80,0:27:04.67,EN,,0,0,0,,Well, in order to set this thing going,\nDialogue: 0,0:27:04.67,0:27:07.41,EN,,0,0,0,,I just want to show you some behavior out of this simulator.\nDialogue: 0,0:27:07.85,0:27:09.93,EN,,0,0,0,,By the way, you may think this simulator is very simple,\nDialogue: 0,0:27:10.40,0:27:12.01,EN,,0,0,0,,and probably too simple to be useful.\nDialogue: 0,0:27:12.57,0:27:13.76,EN,,0,0,0,,The fact of the matter is\nDialogue: 0,0:27:13.98,0:27:15.39,EN,,0,0,0,,that this simulator has been used\nDialogue: 0,0:27:15.72,0:27:17.44,EN,,0,0,0,,to manufacture a fairly large computer.\nDialogue: 0,0:27:18.68,0:27:20.64,EN,,0,0,0,,So this is a real live example.\nDialogue: 0,0:27:22.36,0:27:24.06,EN,,0,0,0,,Actually, not exactly this simulator，\nDialogue: 0,0:27:24.06,0:27:25.39,EN,,0,0,0,,because I'll tell you the difference.\nDialogue: 0,0:27:25.84,0:27:28.70,EN,,0,0,0,,The difference is that there were many more different kinds of primitives.\nDialogue: 0,0:27:29.82,0:27:32.22,EN,,0,0,0,,There's not just the word inverter or and-gate.\nDialogue: 0,0:27:33.20,0:27:35.72,EN,,0,0,0,,There were things like edge-triggered,\nDialogue: 0,0:27:36.25,0:27:39.88,EN,,0,0,0,,flip-flops, and latches\nDialogue: 0,0:27:40.70,0:27:44.52,EN,,0,0,0,,transparent latches, and adders, and things like that.\nDialogue: 0,0:27:45.17,0:27:47.31,EN,,0,0,0,,And the difficulty with that\nDialogue: 0,0:27:47.45,0:27:50.86,EN,,0,0,0,,is there's pages and pages of the definitions of all these primitives\nDialogue: 0,0:27:51.20,0:27:52.89,EN,,0,0,0,,with numbers like LS04.\nDialogue: 0,0:27:54.69,0:27:56.74,EN,,0,0,0,,And then there's many more parameters for them.\nDialogue: 0,0:27:56.74,0:27:57.98,EN,,0,0,0,,It's not just one delay.\nDialogue: 0,0:27:58.48,0:28:00.81,EN,,0,0,0,,There's things like set up times and hold times and all that.\nDialogue: 0,0:28:01.22,0:28:03.40,EN,,0,0,0,,But with the exception of that part of the complexity,\nDialogue: 0,0:28:03.82,0:28:08.20,EN,,0,0,0,,the structure of the simulator that we use for building a real computer,\nDialogue: 0,0:28:09.08,0:28:12.89,EN,,0,0,0,,that works is exactly what you're seeing here.\nDialogue: 0,0:28:15.11,0:28:19.27,EN,,0,0,0,,Well in any case, what we have here is a few simple things.\nDialogue: 0,0:28:19.27,0:28:22.59,EN,,0,0,0,,Like, there's inverter delays being set up and making a new agenda.\nDialogue: 0,0:28:23.03,0:28:25.52,EN,,0,0,0,,And then we can make some inputs.\nDialogue: 0,0:28:26.03,0:28:29.18,EN,,0,0,0,,Ok? There's input-1, input-2, a sum and a carry, which are wires.\nDialogue: 0,0:28:29.46,0:28:31.88,EN,,0,0,0,,I'm going to put a special kind of object called a probe\nDialogue: 0,0:28:32.51,0:28:34.64,EN,,0,0,0,,onto, onto some of the wires,\nDialogue: 0,0:28:34.97,0:28:36.24,EN,,0,0,0,,onto sum and onto carry.\nDialogue: 0,0:28:37.23,0:28:40.56,EN,,0,0,0,,A probe is a, can object that has the property\nDialogue: 0,0:28:40.70,0:28:43.60,EN,,0,0,0,,that when you change a wire it's attached to,\nDialogue: 0,0:28:43.72,0:28:44.83,EN,,0,0,0,,it types out a message.\nDialogue: 0,0:28:46.12,0:28:46.92,EN,,0,0,0,,It's an easy thing to do.\nDialogue: 0,0:28:48.44,0:28:49.52,EN,,0,0,0,,And then once we have that,\nDialogue: 0,0:28:49.55,0:28:51.45,EN,,0,0,0,,of course, then when you put the probe on,\nDialogue: 0,0:28:51.45,0:28:52.41,EN,,0,0,0,,the first thing it does, it says,\nDialogue: 0,0:28:52.67,0:28:56.01,EN,,0,0,0,,the current value of the sum at time 0 is 0\nDialogue: 0,0:28:57.29,0:28:58.43,EN,,0,0,0,,And because I just noticed it.\nDialogue: 0,0:28:59.40,0:29:04.75,EN,,0,0,0,,And the value of the carry at time 0, this is the time, is 0.\nDialogue: 0,0:29:06.04,0:29:09.28,EN,,0,0,0,,And then we go off and we build some structure.\nDialogue: 0,0:29:09.62,0:29:12.28,EN,,0,0,0,,Like, we can build a structure here that says\nDialogue: 0,0:29:14.06,0:29:18.20,EN,,0,0,0,,you have a half-adder on input-1, input-2, sum, and carry.\nDialogue: 0,0:29:18.42,0:29:20.42,EN,,0,0,0,,And we're going to set the signal on input-1 to 1.\nDialogue: 0,0:29:20.62,0:29:21.72,EN,,0,0,0,,We do some propagation.\nDialogue: 0,0:29:21.88,0:29:22.84,EN,,0,0,0,,At time 8,\nDialogue: 0,0:29:23.90,0:29:26.12,EN,,0,0,0,,which you could see going through this thing if you wanted to,\nDialogue: 0,0:29:26.52,0:29:29.20,EN,,0,0,0,,the new value of sum became 1.\nDialogue: 0,0:29:29.52,0:29:30.44,EN,,0,0,0,,And the thing says I'm done.\nDialogue: 0,0:29:31.16,0:29:32.25,EN,,0,0,0,,That wasn't very interesting.\nDialogue: 0,0:29:32.63,0:29:33.90,EN,,0,0,0,,But we can send it some more signals.\nDialogue: 0,0:29:34.06,0:29:36.73,EN,,0,0,0,,Like, we set-signal on input-2 to be one.\nDialogue: 0,0:29:36.89,0:29:38.09,EN,,0,0,0,,And at that time if we propagate,\nDialogue: 0,0:29:38.36,0:29:39.95,EN,,0,0,0,,then it carried at 11,\nDialogue: 0,0:29:40.12,0:29:41.42,EN,,0,0,0,,the carry becomes 1,\nDialogue: 0,0:29:41.55,0:29:44.19,EN,,0,0,0,,and at 16, the sum's new value becomes 0.\nDialogue: 0,0:29:45.39,0:29:48.99,EN,,0,0,0,,And you might want to work out that, if you like, about the digital circuitry.\nDialogue: 0,0:29:48.99,0:29:50.12,EN,,0,0,0,,It's true, and it works.\nDialogue: 0,0:29:50.62,0:29:51.53,EN,,0,0,0,,And it's not very interesting.\nDialogue: 0,0:29:51.53,0:29:54.12,EN,,0,0,0,,But that's the kind of behavior we get out of this thing.\nDialogue: 0,0:30:01.83,0:30:03.29,EN,,0,0,0,,So what I've shown you right now\nDialogue: 0,0:30:03.48,0:30:05.52,EN,,0,0,0,,is a large-scale picture,\nDialogue: 0,0:30:06.60,0:30:08.56,EN,,0,0,0,,how you, at a bigger, big scale,\nDialogue: 0,0:30:08.72,0:30:12.04,EN,,0,0,0,,you implement an event-driven simulation of some sort.\nDialogue: 0,0:30:13.29,0:30:14.56,EN,,0,0,0,,And how you might organize it\nDialogue: 0,0:30:14.88,0:30:16.70,EN,,0,0,0,,to have nice hierarchical structure\nDialogue: 0,0:30:16.99,0:30:21.00,EN,,0,0,0,,allowing you to build abstract boxes that you can instantiate.\nDialogue: 0,0:30:21.56,0:30:24.96,EN,,0,0,0,,But I haven't told you any of the details about how this agenda and things like that work.\nDialogue: 0,0:30:25.78,0:30:26.54,EN,,0,0,0,,That we'll do next.\nDialogue: 0,0:30:28.63,0:30:32.94,EN,,0,0,0,,And that's going to involve change and mutation of data and things like that.\nDialogue: 0,0:30:34.31,0:30:35.86,EN,,0,0,0,,Are there any questions now, before I go on?\nDialogue: 0,0:30:47.16,0:30:48.24,EN,,0,0,0,,Thank you. Let's take a break.\nDialogue: 0,0:30:50.24,0:31:00.62,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:31:28.94,0:31:35.06,EN,,0,0,0,,Well, we've been making a simulation.\nDialogue: 0,0:31:35.39,0:31:37.77,EN,,0,0,0,,And the simulation is an event-driven simulation\nDialogue: 0,0:31:38.17,0:31:42.75,EN,,0,0,0,,where the objects in the world are the objects in the computer.\nDialogue: 0,0:31:43.92,0:31:47.28,EN,,0,0,0,,And the changes of state that are happening in the world in time\nDialogue: 0,0:31:47.98,0:31:50.83,EN,,0,0,0,,are organized to be time in the computer,\nDialogue: 0,0:31:52.99,0:31:56.04,EN,,0,0,0,,so that if something happens after something else in the world,\nDialogue: 0,0:31:56.46,0:31:57.96,EN,,0,0,0,,then we have it happen after,\nDialogue: 0,0:31:58.89,0:32:02.25,EN,,0,0,0,,after the corresponding events happen in the same order in the computer.\nDialogue: 0,0:32:04.42,0:32:07.16,EN,,0,0,0,,That's where we have assignments, when we make that alignment.\nDialogue: 0,0:32:08.22,0:32:11.21,EN,,0,0,0,,Right now I want to show you a way of organizing time,\nDialogue: 0,0:32:11.80,0:32:14.86,EN,,0,0,0,,which is an agenda or priority queue, it's sometimes called.\nDialogue: 0,0:32:16.04,0:32:18.57,EN,,0,0,0,,We'll do some--we'll do a little bit of just understanding\nDialogue: 0,0:32:18.62,0:32:21.00,EN,,0,0,0,,what are the things we need to be able to do to make agendas.\nDialogue: 0,0:32:28.33,0:32:31.28,EN,,0,0,0,,And so we're going to have--and so right now over here, I'm going to write down a bunch\nDialogue: 0,0:32:31.39,0:32:33.88,EN,,0,0,0,,of primitive operations for manipulating agendas.\nDialogue: 0,0:32:35.96,0:32:37.95,EN,,0,0,0,,I'm not going to show you the code for them\nDialogue: 0,0:32:38.14,0:32:39.58,EN,,0,0,0,,because they're all very simple,\nDialogue: 0,0:32:40.32,0:32:42.60,EN,,0,0,0,,Iand you've got listings of all that anyway.\nDialogue: 0,0:32:43.68,0:32:44.38,EN,,0,0,0,,So what do we have?\nDialogue: 0,0:32:44.38,0:32:53.50,EN,,0,0,0,,We have things like make-agenda which produces a new agenda.\nDialogue: 0,0:32:57.36,0:33:01.77,EN,,0,0,0,,We can ask--we get the current-time of an agenda,\nDialogue: 0,0:33:07.47,0:33:12.80,EN,,0,0,0,,of an agenda, which gives me a number, a time.\nDialogue: 0,0:33:16.99,0:33:21.37,EN,,0,0,0,,We can get--we can ask whether an agenda is empty, empty-agenda.\nDialogue: 0,0:33:30.20,0:33:32.57,EN,,0,0,0,,And that produces either a true or a false.\nDialogue: 0,0:33:42.72,0:33:44.72,EN,,0,0,0,,We can add an object to an agenda.\nDialogue: 0,0:33:52.71,0:33:56.06,EN,,0,0,0,,Actually, what we add to an agenda is an operation--an action to be done.\nDialogue: 0,0:33:56.91,0:33:58.14,EN,,0,0,0,,And that takes a time,\nDialogue: 0,0:33:59.63,0:34:00.56,EN,,0,0,0,,the action itself,\nDialogue: 0,0:34:02.86,0:34:04.64,EN,,0,0,0,,and the agenda I want to add it to.\nDialogue: 0,0:34:07.58,0:34:10.25,EN,,0,0,0,,OK? That inserts it in the appropriate place in the agenda.\nDialogue: 0,0:34:10.71,0:34:12.73,EN,,0,0,0,,I can get the first item off an agenda,\nDialogue: 0,0:34:14.24,0:34:15.39,EN,,0,0,0,,the first thing I have to do,\nDialogue: 0,0:34:21.84,0:34:23.84,EN,,0,0,0,,which is going to give me an action.\nDialogue: 0,0:34:26.46,0:34:28.73,EN,,0,0,0,,And I can remove the first item from an agenda.\nDialogue: 0,0:34:29.54,0:34:31.16,EN,,0,0,0,,That's what I have to be able to do with agendas.\nDialogue: 0,0:34:31.40,0:34:33.02,EN,,0,0,0,,That is a big complicated mess.\nDialogue: 0,0:34:42.53,0:34:43.36,EN,,0,0,0,,From an agenda.\nDialogue: 0,0:34:45.98,0:34:49.85,EN,,0,0,0,,Well, let's see how we can organize this thing as a data structure a bit.\nDialogue: 0,0:34:52.96,0:34:56.04,EN,,0,0,0,,Well, an agenda is going to be some kind of list.\nDialogue: 0,0:34:58.43,0:35:01.20,EN,,0,0,0,,And it's going to be a list that I'm going to have to be able to modify.\nDialogue: 0,0:35:01.57,0:35:04.03,EN,,0,0,0,,So we have to talk about modifying of lists,\nDialogue: 0,0:35:05.80,0:35:06.89,EN,,0,0,0,,because I'm going to add things to it,\nDialogue: 0,0:35:07.77,0:35:10.27,EN,,0,0,0,,and delete things from it, and things like that.\nDialogue: 0,0:35:11.07,0:35:12.51,EN,,0,0,0,,It's organized by time.\nDialogue: 0,0:35:13.82,0:35:15.57,EN,,0,0,0,,It's probably good to keep it in sorted order.\nDialogue: 0,0:35:18.33,0:35:20.88,EN,,0,0,0,,But sometimes there are lots of things that happen at the same time\nDialogue: 0,0:35:22.04,0:35:23.42,EN,,0,0,0,,approximate same time.\nDialogue: 0,0:35:23.80,0:35:24.72,EN,,0,0,0,,What I have to do is say,\nDialogue: 0,0:35:24.91,0:35:27.52,EN,,0,0,0,,group things by the time at which they're supposed to happen.\nDialogue: 0,0:35:29.04,0:35:31.61,EN,,0,0,0,,So I'm going to make an agenda as a list of segments.\nDialogue: 0,0:35:32.78,0:35:35.69,EN,,0,0,0,,And so I'm going to draw you a data structure for an agenda,\nDialogue: 0,0:35:36.68,0:35:37.93,EN,,0,0,0,,a perfectly reasonable one.\nDialogue: 0,0:35:39.62,0:35:40.49,EN,,0,0,0,,Here's an agenda.\nDialogue: 0,0:35:41.11,0:35:42.87,EN,,0,0,0,,It's a thing that begins with a name.\nDialogue: 0,0:35:47.85,0:35:50.19,EN,,0,0,0,,I'm going to do it right now out of list structure.\nDialogue: 0,0:35:52.60,0:35:53.39,EN,,0,0,0,,It's got a header.\nDialogue: 0,0:35:54.14,0:35:55.44,EN,,0,0,0,,There's a reason for the header.\nDialogue: 0,0:35:55.84,0:35:57.63,EN,,0,0,0,,We're going to see the reason soon.\nDialogue: 0,0:36:00.68,0:36:03.40,EN,,0,0,0,,And it will have a segment. We will have--\nDialogue: 0,0:36:03.96,0:36:05.62,EN,,0,0,0,,It will have--it will be a list of segments.\nDialogue: 0,0:36:08.31,0:36:10.54,EN,,0,0,0,,Supposing this agenda has two segments,\nDialogue: 0,0:36:11.58,0:36:15.07,EN,,0,0,0,,OK, they're the car's-- successive car's of this list.\nDialogue: 0,0:36:16.41,0:36:20.57,EN,,0,0,0,,Each segment is going to have a time--\nDialogue: 0,0:36:24.20,0:36:26.64,EN,,0,0,0,,say for example, 10--\nDialogue: 0,0:36:26.83,0:36:30.51,EN,,0,0,0,,that says that the things that happen in this segment are at time 10.\nDialogue: 0,0:36:33.16,0:36:36.52,EN,,0,0,0,,And what I'm going to have in here is another data structure\nDialogue: 0,0:36:36.56,0:36:38.01,EN,,0,0,0,,which I'm not going to describe,\nDialogue: 0,0:36:38.49,0:36:41.08,EN,,0,0,0,,which is a queue of things to do at time 10.\nDialogue: 0,0:36:42.24,0:36:43.33,EN,,0,0,0,,It's a queue.\nDialogue: 0,0:36:43.33,0:36:44.70,EN,,0,0,0,,And we'll talk about that in a second.\nDialogue: 0,0:36:45.20,0:36:50.35,EN,,0,0,0,,But abstractly, the queue is just a list of things to do at a particular time.\nDialogue: 0,0:36:50.40,0:36:52.04,EN,,0,0,0,,And I can add things to a queue.\nDialogue: 0,0:36:53.10,0:36:53.80,EN,,0,0,0,,This is a queue.\nDialogue: 0,0:36:56.14,0:36:59.11,EN,,0,0,0,,There's a time, there's a segment.\nDialogue: 0,0:37:03.23,0:37:06.36,EN,,0,0,0,,Now, I may have another segment in this agenda.\nDialogue: 0,0:37:08.94,0:37:11.20,EN,,0,0,0,,Supposing this is stuff that happens at time 30.\nDialogue: 0,0:37:13.50,0:37:15.92,EN,,0,0,0,,It has, of course, another queue\nDialogue: 0,0:37:16.92,0:37:20.24,EN,,0,0,0,,of things that are queued up to be done at time 30.\nDialogue: 0,0:37:23.21,0:37:25.66,EN,,0,0,0,,Well, there are various things I have to be able to do to an agenda.\nDialogue: 0,0:37:27.09,0:37:29.20,EN,,0,0,0,,Supposing I want to add to an agenda\nDialogue: 0,0:37:29.47,0:37:31.61,EN,,0,0,0,,another thing to be done at time 10.\nDialogue: 0,0:37:33.03,0:37:34.16,EN,,0,0,0,,Well, that's not very hard.\nDialogue: 0,0:37:34.70,0:37:38.65,EN,,0,0,0,,I'm going to walk down here, looking for the segment of time 10.\nDialogue: 0,0:37:39.73,0:37:42.14,EN,,0,0,0,,It is possible that there is no segment of time 10.\nDialogue: 0,0:37:42.93,0:37:44.56,EN,,0,0,0,,We'll cover that case in a second.\nDialogue: 0,0:37:45.42,0:37:47.56,EN,,0,0,0,,But if I find a segment of time 10,\nDialogue: 0,0:37:47.87,0:37:50.43,EN,,0,0,0,,then if I want to add another thing to be done at time 10,\nDialogue: 0,0:37:50.56,0:37:52.16,EN,,0,0,0,,I just increase that queue--\nDialogue: 0,0:37:53.85,0:37:56.22,EN,,0,0,0,,\"just increase\" isn't such an obvious idea.\nDialogue: 0,0:37:56.57,0:37:59.26,EN,,0,0,0,,But I increase the things to be done at that time.\nDialogue: 0,0:38:01.43,0:38:04.25,EN,,0,0,0,,Now, supposing I want to add something to be done at time 20.\nDialogue: 0,0:38:05.31,0:38:07.90,EN,,0,0,0,,There is no segment for time 20.\nDialogue: 0,0:38:08.99,0:38:10.64,EN,,0,0,0,,I'm going to have to create a new segment.\nDialogue: 0,0:38:11.34,0:38:15.64,EN,,0,0,0,,I want my time 20 segment to exist between time 10 and time 30.\nDialogue: 0,0:38:17.61,0:38:19.32,EN,,0,0,0,,Well, that takes a little work.\nDialogue: 0,0:38:20.17,0:38:21.52,EN,,0,0,0,,I'm going to have to do a CONS.\nDialogue: 0,0:38:24.26,0:38:29.94,EN,,0,0,0,,I'm going to have to make a new element of the agenda list--list of segments.\nDialogue: 0,0:38:33.60,0:38:34.81,EN,,0,0,0,,I'm going to have to change.\nDialogue: 0,0:38:35.40,0:38:36.30,EN,,0,0,0,,Here's change.\nDialogue: 0,0:38:37.54,0:38:42.80,EN,,0,0,0,,I'm going to have to change the CDR of the CDR of the agenda\nDialogue: 0,0:38:44.88,0:38:49.45,EN,,0,0,0,,point that a new CONS of the new segment\nDialogue: 0,0:38:50.11,0:38:54.65,EN,,0,0,0,,and the CDR of the CDR of the CDR of the agenda, the CD-D-D-DR.\nDialogue: 0,0:38:57.18,0:39:01.88,EN,,0,0,0,,And this is going to have a new segment now of time 20\nDialogue: 0,0:39:02.30,0:39:03.72,EN,,0,0,0,,with its own queue,\nDialogue: 0,0:39:04.84,0:39:06.29,EN,,0,0,0,,which now has one element in it.\nDialogue: 0,0:39:10.73,0:39:12.52,EN,,0,0,0,,If I wanted to add something at the end,\nDialogue: 0,0:39:12.54,0:39:15.87,EN,,0,0,0,,I'm going to have to replace the CDR of this,\nDialogue: 0,0:39:16.99,0:39:19.21,EN,,0,0,0,,of this list with something.\nDialogue: 0,0:39:20.59,0:39:23.31,EN,,0,0,0,,We're have to change that piece of data structure.\nDialogue: 0,0:39:24.04,0:39:25.79,EN,,0,0,0,,So I'm going to need new primitives for doing this.\nDialogue: 0,0:39:27.21,0:39:28.62,EN,,0,0,0,,But I'm just showing you why I need them.\nDialogue: 0,0:39:29.44,0:39:33.88,EN,,0,0,0,,And finally, if I wanted to add a thing to be done at time 5,\nDialogue: 0,0:39:37.12,0:39:39.20,EN,,0,0,0,,I'm going to have to change this one,\nDialogue: 0,0:39:40.81,0:39:42.12,EN,,0,0,0,,because I'm going to have to add it in over here,\nDialogue: 0,0:39:43.29,0:39:46.22,EN,,0,0,0,,which is why I planned ahead and had a header cell,\nDialogue: 0,0:39:47.56,0:39:48.59,EN,,0,0,0,,which has a place.\nDialogue: 0,0:39:49.40,0:39:52.11,EN,,0,0,0,,If I'm going to change things, I have to have places for the change.\nDialogue: 0,0:39:53.88,0:39:56.56,EN,,0,0,0,,I have to have a place to make the change.\nDialogue: 0,0:39:58.60,0:40:02.54,EN,,0,0,0,,If I remove things from the agenda, that's not so hard.\nDialogue: 0,0:40:02.54,0:40:04.62,EN,,0,0,0,,Removing them from the beginning is pretty easy,\nDialogue: 0,0:40:04.92,0:40:06.14,EN,,0,0,0,,which is the only case I have.\nDialogue: 0,0:40:06.49,0:40:10.19,EN,,0,0,0,,I can go looking for the first, the first segment.\nDialogue: 0,0:40:11.22,0:40:14.00,EN,,0,0,0,,I see if it has a non-empty queue.\nDialogue: 0,0:40:14.81,0:40:16.17,EN,,0,0,0,,If it has a non-empty queue,\nDialogue: 0,0:40:16.32,0:40:18.62,EN,,0,0,0,,well, I'm going to delete one element from the queue\nDialogue: 0,0:40:19.21,0:40:19.74,EN,,0,0,0,,like that.\nDialogue: 0,0:40:20.10,0:40:21.92,EN,,0,0,0,,If the queue ever becomes empty,\nDialogue: 0,0:40:22.64,0:40:24.22,EN,,0,0,0,,then I have to delete the whole segment.\nDialogue: 0,0:40:24.22,0:40:26.49,EN,,0,0,0,,And then this, this changes to point to here.\nDialogue: 0,0:40:28.22,0:40:31.08,EN,,0,0,0,,So it's quite a complicated data structure manipulation going on,\nDialogue: 0,0:40:32.25,0:40:35.37,EN,,0,0,0,,the details of which are not really very exciting.\nDialogue: 0,0:40:36.44,0:40:38.48,EN,,0,0,0,,Now, let's talk about queues.\nDialogue: 0,0:40:38.92,0:40:39.76,EN,,0,0,0,,They're similar.\nDialogue: 0,0:40:41.16,0:40:43.52,EN,,0,0,0,,Because each of these agendas has a queue in it.\nDialogue: 0,0:40:44.34,0:40:45.02,EN,,0,0,0,,What's a queue?\nDialogue: 0,0:40:49.47,0:40:51.85,EN,,0,0,0,,A queue is going to have the following primitive operations.\nDialogue: 0,0:40:52.78,0:41:02.17,EN,,0,0,0,,To make a queue, this gives me a new queue.\nDialogue: 0,0:41:07.77,0:41:17.10,EN,,0,0,0,,I'm going to have to be able to insert into a queue a new item.\nDialogue: 0,0:41:24.51,0:41:28.65,EN,,0,0,0,,I'm going to have to be able to delete from a queue the first item in the queue.\nDialogue: 0,0:41:40.44,0:41:52.04,EN,,0,0,0,,And I want to be able to get the first thing in the queue from some queue.\nDialogue: 0,0:41:53.13,0:41:55.14,EN,,0,0,0,,I also have to be able to test whether a queue is empty.\nDialogue: 0,0:42:07.11,0:42:08.70,EN,,0,0,0,,And when you invent things like this,\nDialogue: 0,0:42:09.02,0:42:10.44,EN,,0,0,0,,I want you to be very careful\nDialogue: 0,0:42:10.64,0:42:14.09,EN,,0,0,0,,to use the kinds of conventions I use for naming things.\nDialogue: 0,0:42:15.12,0:42:19.15,EN,,0,0,0,,Notice that I'm careful to say these change something and that tests it.\nDialogue: 0,0:42:19.87,0:42:21.85,EN,,0,0,0,,And presumably, I did the same thing over here.\nDialogue: 0,0:42:24.65,0:42:26.96,EN,,0,0,0,,OK, and there should be an empty test over here.\nDialogue: 0,0:42:29.24,0:42:30.72,EN,,0,0,0,,OK, well, how would I make a queue?\nDialogue: 0,0:42:31.72,0:42:34.11,EN,,0,0,0,,A queue wants to be something I can add to at the end of,\nDialogue: 0,0:42:35.12,0:42:36.83,EN,,0,0,0,,and pick up the thing at the beginning of.\nDialogue: 0,0:42:37.84,0:42:40.51,EN,,0,0,0,,I should be able to delete from the beginning and add to the end.\nDialogue: 0,0:42:41.23,0:42:43.24,EN,,0,0,0,,Well, I'm going to show you a very simple structure for that.\nDialogue: 0,0:42:43.88,0:42:45.72,EN,,0,0,0,,We can make this out of CONSes as well.\nDialogue: 0,0:42:47.08,0:42:47.79,EN,,0,0,0,,Here's a queue.\nDialogue: 0,0:42:49.91,0:42:52.36,EN,,0,0,0,,It has--it has a queue header,\nDialogue: 0,0:42:53.58,0:42:54.92,EN,,0,0,0,,which contains two parts--\nDialogue: 0,0:42:55.28,0:42:56.25,EN,,0,0,0,,a front pointer\nDialogue: 0,0:42:58.78,0:42:59.82,EN,,0,0,0,,and a rear pointer.\nDialogue: 0,0:43:03.12,0:43:06.33,EN,,0,0,0,,And here I have a queue with two items in it.\nDialogue: 0,0:43:09.13,0:43:12.09,EN,,0,0,0,,The first item, I don't know, it's perhaps a 1.\nDialogue: 0,0:43:12.46,0:43:16.53,EN,,0,0,0,,And the second item, I don't know, let's give it a 2.\nDialogue: 0,0:43:21.40,0:43:23.52,EN,,0,0,0,,The reason why I want two pointers in here,\nDialogue: 0,0:43:24.09,0:43:25.61,EN,,0,0,0,,a front pointer and a rear pointer,\nDialogue: 0,0:43:25.72,0:43:27.10,EN,,0,0,0,,is so I can add to the end\nDialogue: 0,0:43:27.48,0:43:29.45,EN,,0,0,0,,without having to chase down from the beginning.\nDialogue: 0,0:43:31.85,0:43:34.80,EN,,0,0,0,,So for example, if I wanted to add one more item to this queue,\nDialogue: 0,0:43:35.26,0:43:41.02,EN,,0,0,0,,if I want to add on another item to be worried about later,\nDialogue: 0,0:43:41.08,0:43:42.40,EN,,0,0,0,,all I have to do is make a CONS,\nDialogue: 0,0:43:43.47,0:43:46.59,EN,,0,0,0,,which contains that item, say a 3.\nDialogue: 0,0:43:47.53,0:43:51.34,EN,,0,0,0,,That's for inserting 3 into the queue.\nDialogue: 0,0:43:51.52,0:43:53.77,EN,,0,0,0,,Then I have to change this pointer here\nDialogue: 0,0:43:56.94,0:43:58.76,EN,,0,0,0,,Okay? to here.\nDialogue: 0,0:44:00.10,0:44:04.32,EN,,0,0,0,,And I have to change this one to point to the new rear.\nDialogue: 0,0:44:09.12,0:44:12.68,EN,,0,0,0,,If I wish to take the first element of the queue, the first item,\nDialogue: 0,0:44:12.96,0:44:17.12,EN,,0,0,0,,I just go chasing down the front pointer until I find the first one and pick it up.\nDialogue: 0,0:44:18.89,0:44:23.26,EN,,0,0,0,,If I wish to delete the first item from the queue, delete-queue,\nDialogue: 0,0:44:24.14,0:44:26.35,EN,,0,0,0,,all I do is move the front pointer along this way.\nDialogue: 0,0:44:27.71,0:44:29.31,EN,,0,0,0,,The new front of the queue is now this.\nDialogue: 0,0:44:31.70,0:44:33.13,EN,,0,0,0,,So queues are very simple too.\nDialogue: 0,0:44:34.48,0:44:35.76,EN,,0,0,0,,So what you see now\nDialogue: 0,0:44:37.24,0:44:40.83,EN,,0,0,0,,is that I need a certain number of new primitive operations.\nDialogue: 0,0:44:41.48,0:44:42.56,EN,,0,0,0,,And I'm going to give them some names.\nDialogue: 0,0:44:42.99,0:44:46.28,EN,,0,0,0,,And then we're going to look into how they work, and how they're used.\nDialogue: 0,0:44:47.35,0:44:55.04,EN,,0,0,0,,We have set the CAR of some pair,\nDialogue: 0,0:44:55.88,0:44:59.36,EN,,0,0,0,,or a thing produced by CONSing, to a new value.\nDialogue: 0,0:45:02.37,0:45:09.92,EN,,0,0,0,,And set the CDR of a pair to a new value.\nDialogue: 0,0:45:13.02,0:45:14.78,EN,,0,0,0,,And then we're going to look into how they work.\nDialogue: 0,0:45:16.03,0:45:20.51,EN,,0,0,0,,I needed setting CAR over here to delete the first element of the queue.\nDialogue: 0,0:45:20.96,0:45:22.52,EN,,0,0,0,,This is the CAR, and I had to set it.\nDialogue: 0,0:45:23.47,0:45:24.96,EN,,0,0,0,,I had to be able to set the CDR\nDialogue: 0,0:45:25.28,0:45:27.08,EN,,0,0,0,,to be able to move the rear pointer,\nDialogue: 0,0:45:27.21,0:45:28.76,EN,,0,0,0,,or to be able to increment the queue here.\nDialogue: 0,0:45:30.16,0:45:31.60,EN,,0,0,0,,All of the operations I did\nDialogue: 0,0:45:31.90,0:45:35.90,EN,,0,0,0,,were made out of those that I just showed you on the, on the last blackboard.\nDialogue: 0,0:45:38.17,0:45:40.14,EN,,0,0,0,,Good. Let's pause the time, and take a little break then.\nDialogue: 0,0:45:41.24,0:45:52.67,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:46:38.81,0:46:43.53,EN,,0,0,0,,When we originally introduced pairs made out of CONS, made by CONS,\nDialogue: 0,0:46:44.57,0:46:46.80,EN,,0,0,0,,we only said a few axioms about them,\nDialogue: 0,0:46:48.09,0:46:50.76,EN,,0,0,0,,which were of the form-- what were they--\nDialogue: 0,0:46:52.28,0:47:03.64,EN,,0,0,0,,for all X and Y, the CAR of the CONS of X and Y is X\nDialogue: 0,0:47:05.31,0:47:12.92,EN,,0,0,0,,and Y is X and the CDR of the CONS of X and Y is Y.\nDialogue: 0,0:47:14.80,0:47:20.00,EN,,0,0,0,,Now, these say nothing about whether a CONS has an identity like a person.\nDialogue: 0,0:47:21.85,0:47:25.58,EN,,0,0,0,,In fact, all they say is something sort of abstract,\nDialogue: 0,0:47:25.74,0:47:27.95,EN,,0,0,0,,that a CONS is the parts it's made out of.\nDialogue: 0,0:47:29.74,0:47:33.18,EN,,0,0,0,,And of course, two things are made out of the same parts, they're the same,\nDialogue: 0,0:47:33.93,0:47:35.71,EN,,0,0,0,,at least from the point of view of these axioms.\nDialogue: 0,0:47:37.32,0:47:39.21,EN,,0,0,0,,But by introducing assignment--\nDialogue: 0,0:47:39.84,0:47:42.32,EN,,0,0,0,,in fact, mutable data is a kind of assignment,\nDialogue: 0,0:47:42.88,0:47:44.43,EN,,0,0,0,,we have a set CAR and a set CDR--\nDialogue: 0,0:47:45.55,0:47:48.94,EN,,0,0,0,,by introducing those, these axioms no longer tell the whole story.\nDialogue: 0,0:47:49.83,0:47:52.03,EN,,0,0,0,,And they're still true if written exactly like this.\nDialogue: 0,0:47:53.25,0:47:54.94,EN,,0,0,0,,But they don't tell the whole story.\nDialogue: 0,0:47:56.07,0:48:01.68,EN,,0,0,0,,Because if I'm going to set a particular CAR in a particular CONS,\nDialogue: 0,0:48:03.02,0:48:04.03,EN,,0,0,0,,the questions are,\nDialogue: 0,0:48:04.24,0:48:08.64,EN,,0,0,0,,well, is that setting all CARs and all CONSes of the same two things or not?\nDialogue: 0,0:48:10.09,0:48:13.04,EN,,0,0,0,,If I--if we use CONSes to make up things like rational numbers,\nDialogue: 0,0:48:14.86,0:48:17.10,EN,,0,0,0,,or things like 3 over 4,\nDialogue: 0,0:48:17.34,0:48:20.25,EN,,0,0,0,,supposing I had two three-fourths.\nDialogue: 0,0:48:21.57,0:48:22.75,EN,,0,0,0,,Are they the same one--\nDialogue: 0,0:48:24.06,0:48:24.89,EN,,0,0,0,,or are they different?\nDialogue: 0,0:48:25.34,0:48:26.96,EN,,0,0,0,,Well, in the case of numbers, it doesn't matter.\nDialogue: 0,0:48:27.86,0:48:30.49,EN,,0,0,0,,Because there's no meaning to changing the denominator of a number.\nDialogue: 0,0:48:33.02,0:48:35.32,EN,,0,0,0,,What you could do is make a number which has a different denominator.\nDialogue: 0,0:48:36.84,0:48:39.88,EN,,0,0,0,,But the concept of changing a number which has to have a different denominator\nDialogue: 0,0:48:40.00,0:48:43.58,EN,,0,0,0,,is sort of a very weird, and sort of not supported by what you think of as mathematics.\nDialogue: 0,0:48:44.77,0:48:47.40,EN,,0,0,0,,However, when these CONSes represent things in the physical world,\nDialogue: 0,0:48:48.97,0:48:50.43,EN,,0,0,0,,then changing something like the CAR\nDialogue: 0,0:48:50.60,0:48:52.20,EN,,0,0,0,,like removing a piece of the fingernail.\nDialogue: 0,0:48:53.69,0:48:56.56,EN,,0,0,0,,And so CONSes have an identity.\nDialogue: 0,0:48:57.77,0:48:59.92,EN,,0,0,0,,Let me show you what I mean about identity, first of all.\nDialogue: 0,0:49:01.28,0:49:03.05,EN,,0,0,0,,Let's do some little example here.\nDialogue: 0,0:49:04.32,0:49:15.20,EN,,0,0,0,,Supposing I define A to the CONS of 1 and 2.\nDialogue: 0,0:49:18.32,0:49:19.76,EN,,0,0,0,,Well, what that means, first of all,\nDialogue: 0,0:49:20.67,0:49:25.20,EN,,0,0,0,,is that somewhere in some environment I've made a symbol A\nDialogue: 0,0:49:25.96,0:49:28.67,EN,,0,0,0,,to have a value which is a pair\nDialogue: 0,0:49:29.47,0:49:34.06,EN,,0,0,0,,consisting of pointers to a 1 and a pointer to a 2,\nDialogue: 0,0:49:35.34,0:49:36.16,EN,,0,0,0,,just like that.\nDialogue: 0,0:49:38.12,0:49:39.60,EN,,0,0,0,,Now, supposing I also say\nDialogue: 0,0:49:40.22,0:49:47.58,EN,,0,0,0,,define B to be the CONS--\nDialogue: 0,0:49:53.88,0:49:56.81,EN,,0,0,0,,it doesn't matter, but I like it better, it's prettier--\nDialogue: 0,0:49:57.63,0:49:59.88,EN,,0,0,0,,of A and A.\nDialogue: 0,0:50:03.97,0:50:06.03,EN,,0,0,0,,Well, first of all, I'm using the name A twice.\nDialogue: 0,0:50:07.84,0:50:10.57,EN,,0,0,0,,At this moment, I'm going to think of CONSes as having identity.\nDialogue: 0,0:50:11.30,0:50:12.64,EN,,0,0,0,,This is the same one.\nDialogue: 0,0:50:13.69,0:50:14.81,EN,,0,0,0,,And so what that means\nDialogue: 0,0:50:15.29,0:50:17.61,EN,,0,0,0,,is I make another pair,\nDialogue: 0,0:50:18.81,0:50:20.20,EN,,0,0,0,,which I'm going to call B.\nDialogue: 0,0:50:22.38,0:50:27.60,EN,,0,0,0,,And it contains two pointers to A.\nDialogue: 0,0:50:28.92,0:50:32.20,EN,,0,0,0,,At this point, I have three names for this object.\nDialogue: 0,0:50:33.10,0:50:34.16,EN,,0,0,0,,A is its name.\nDialogue: 0,0:50:34.88,0:50:36.46,EN,,0,0,0,,The CAR of B is its name.\nDialogue: 0,0:50:37.23,0:50:38.86,EN,,0,0,0,,And the CDR of B is its name.\nDialogue: 0,0:50:39.36,0:50:41.15,EN,,0,0,0,,It has several aliases, they're called.\nDialogue: 0,0:50:44.23,0:50:49.28,EN,,0,0,0,,Now, supposing I do something like set-the-CAR,\nDialogue: 0,0:50:53.77,0:51:08.38,EN,,0,0,0,,the CAR of the CAR of B to 3.\nDialogue: 0,0:51:12.75,0:51:17.45,EN,,0,0,0,,What that means is I find the CAR of B, that's this.\nDialogue: 0,0:51:17.83,0:51:20.93,EN,,0,0,0,,I set the CAR of that to be 3, changing this.\nDialogue: 0,0:51:24.76,0:51:25.69,EN,,0,0,0,,I've changed A.\nDialogue: 0,0:51:27.24,0:51:33.64,EN,,0,0,0,,If I were to ask what's the CAR of A--of A now?\nDialogue: 0,0:51:35.34,0:51:37.56,EN,,0,0,0,,I would get out 3,\nDialogue: 0,0:51:38.68,0:51:43.39,EN,,0,0,0,,even though here we see that A was the CONS of 1 and 2.\nDialogue: 0,0:51:45.29,0:51:47.44,EN,,0,0,0,,I caused A to change by changing B.\nDialogue: 0,0:51:48.56,0:51:49.64,EN,,0,0,0,,There is sharing here.\nDialogue: 0,0:51:52.25,0:51:53.47,EN,,0,0,0,,That's sometimes what we want.\nDialogue: 0,0:51:54.24,0:51:56.12,EN,,0,0,0,,Surely in the queues and things like that,\nDialogue: 0,0:51:56.24,0:52:02.38,EN,,0,0,0,,that's exactly what we defined our--organized our data structures to facilitate-- sharing.\nDialogue: 0,0:52:04.35,0:52:05.66,EN,,0,0,0,,But inadvertent sharing,\nDialogue: 0,0:52:07.76,0:52:09.72,EN,,0,0,0,,unanticipated interactions between objects,\nDialogue: 0,0:52:10.78,0:52:14.08,EN,,0,0,0,,is the source of most of the bugs that occur in complicated programs.\nDialogue: 0,0:52:15.44,0:52:21.66,EN,,0,0,0,,So by introducing this possibility of things having identity and sharing\nDialogue: 0,0:52:21.87,0:52:23.76,EN,,0,0,0,,and having multiple names for the same thing,\nDialogue: 0,0:52:24.08,0:52:25.05,EN,,0,0,0,,we get a lot of power.\nDialogue: 0,0:52:25.13,0:52:28.46,EN,,0,0,0,,But we're going to pay for it with lots of complexity and bugs.\nDialogue: 0,0:52:32.19,0:52:36.24,EN,,0,0,0,,So also, for example, if I just looked at this just to drive that home,\nDialogue: 0,0:52:37.10,0:52:39.87,EN,,0,0,0,,the CADR of B,\nDialogue: 0,0:52:42.46,0:52:46.56,EN,,0,0,0,,which has nothing to do with even the CAR of B, apparently.\nDialogue: 0,0:52:46.88,0:52:49.02,EN,,0,0,0,,The CADR of B, what's that?\nDialogue: 0,0:52:49.35,0:52:53.56,EN,,0,0,0,,Take that CDR of B and now take the CAR of that.\nDialogue: 0,0:52:53.56,0:52:54.86,EN,,0,0,0,,Oh, that's 3 also.\nDialogue: 0,0:52:56.48,0:53:00.43,EN,,0,0,0,,So I can have non-local interactions by sharing.\nDialogue: 0,0:53:01.12,0:53:02.48,EN,,0,0,0,,And I have to be very careful of that.\nDialogue: 0,0:53:06.64,0:53:12.64,EN,,0,0,0,,Well, so far, of course, it seems I've introduced several different assignment operators--\nDialogue: 0,0:53:13.18,0:53:17.61,EN,,0,0,0,,set, set CAR, set CDR.\nDialogue: 0,0:53:18.51,0:53:21.39,EN,,0,0,0,,Well, maybe I should just get rid of set CAR and set CDR. Maybe they're not worthwhile.\nDialogue: 0,0:53:22.82,0:53:23.66,EN,,0,0,0,,Well, the answer is\nDialogue: 0,0:53:24.12,0:53:26.11,EN,,0,0,0,,that once you let the camel's nose into the tent,\nDialogue: 0,0:53:26.24,0:53:27.34,EN,,0,0,0,,the rest of him follows.\nDialogue: 0,0:53:30.16,0:53:31.26,EN,,0,0,0,,All I have to have is set,\nDialogue: 0,0:53:31.61,0:53:35.85,EN,,0,0,0,,and I can make all of the--all of the bad things that can happen.\nDialogue: 0,0:53:38.55,0:53:39.80,EN,,0,0,0,,Let's play with that a little bit.\nDialogue: 0,0:53:40.69,0:53:43.72,EN,,0,0,0,,A couple of days ago, when we introduced compound data,\nDialogue: 0,0:53:45.13,0:53:51.20,EN,,0,0,0,,you saw Hal show you a definition of CONS in terms of a message acceptor.\nDialogue: 0,0:53:52.48,0:53:56.06,EN,,0,0,0,,I'm going to show you even a more horrible thing,\nDialogue: 0,0:53:57.13,0:54:00.04,EN,,0,0,0,,a definition of CONS in terms of nothing but air,\nDialogue: 0,0:54:02.56,0:54:03.02,EN,,0,0,0,,hot air.\nDialogue: 0,0:54:04.44,0:54:08.12,EN,,0,0,0,,What is the definition of CONS, of the old functional kind,\nDialogue: 0,0:54:09.26,0:54:11.66,EN,,0,0,0,,in terms of purely lambdic expressions,\nDialogue: 0,0:54:13.39,0:54:14.40,EN,,0,0,0,,procedures?\nDialogue: 0,0:54:17.39,0:54:19.66,EN,,0,0,0,,Because I'm going to then modify this definition\nDialogue: 0,0:54:20.30,0:54:23.16,EN,,0,0,0,,to get assignment to be only one kind of assignment,\nDialogue: 0,0:54:24.28,0:54:27.93,EN,,0,0,0,,to get rid of the set CAR and set CDR in terms of set.\nDialogue: 0,0:54:28.58,0:54:37.39,EN,,0,0,0,,So what if I define CONS of X and Y\nDialogue: 0,0:54:38.91,0:54:42.56,EN,,0,0,0,,to be a procedure of one argument called a message M,\nDialogue: 0,0:54:43.39,0:54:46.32,EN,,0,0,0,,which calls that message on X and Y?\nDialogue: 0,0:54:51.12,0:54:53.10,EN,,0,0,0,,This idea was invented by Alonzo Church,\nDialogue: 0,0:54:53.77,0:54:55.72,EN,,0,0,0,,who was the greatest programmer of the 20th century,\nDialogue: 0,0:54:55.79,0:54:57.15,EN,,0,0,0,,although he never saw a computer.\nDialogue: 0,0:54:57.87,0:54:59.13,EN,,0,0,0,,It was done in the 1930s.\nDialogue: 0,0:54:59.42,0:55:02.22,EN,,0,0,0,,He was a logician, I suppose at Princeton at the time.\nDialogue: 0,0:55:08.66,0:55:10.43,EN,,0,0,0,,Define CAR of X\nDialogue: 0,0:55:13.10,0:55:16.92,EN,,0,0,0,,to be the result of applying X to that procedure of two arguments,\nDialogue: 0,0:55:17.15,0:55:20.60,EN,,0,0,0,,A and D, which selects A.\nDialogue: 0,0:55:23.71,0:55:24.97,EN,,0,0,0,,I will define CDR of X\nDialogue: 0,0:55:33.10,0:55:34.78,EN,,0,0,0,,to be that procedure,\nDialogue: 0,0:55:35.08,0:55:40.25,EN,,0,0,0,,to be the result of applying X to that procedure of A and D,\nDialogue: 0,0:55:40.92,0:55:42.04,EN,,0,0,0,,which selects D.\nDialogue: 0,0:55:46.67,0:55:49.88,EN,,0,0,0,,Now, you may not recognize this as CAR, CDR, and CONS.\nDialogue: 0,0:55:50.51,0:55:53.61,EN,,0,0,0,,But I'm going to demonstrate to you that it satisfies the original axioms\nDialogue: 0,0:55:54.11,0:55:54.81,EN,,0,0,0,,just once.\nDialogue: 0,0:55:55.61,0:55:57.56,EN,,0,0,0,,And then we're going to do some playing of games.\nDialogue: 0,0:55:58.29,0:56:06.27,EN,,0,0,0,,Consider the problem CAR of CONS of, say, 35 and 47.\nDialogue: 0,0:56:09.93,0:56:10.96,EN,,0,0,0,,Well, what is that?\nDialogue: 0,0:56:11.12,0:56:15.24,EN,,0,0,0,,It is the result of taking car of the result of substituting 35 and 47\nDialogue: 0,0:56:15.37,0:56:18.20,EN,,0,0,0,,X and Y in the body of this.\nDialogue: 0,0:56:19.71,0:56:20.69,EN,,0,0,0,,Well, that's easy enough.\nDialogue: 0,0:56:20.69,0:56:30.88,EN,,0,0,0,,That's CAR of the result of substituting into lambda of M, M of 35 and 47.\nDialogue: 0,0:56:35.53,0:56:39.36,EN,,0,0,0,,Well, what this is, is the result of substituting this object\nDialogue: 0,0:56:39.44,0:56:41.85,EN,,0,0,0,,for X in the body of that.\nDialogue: 0,0:56:42.83,0:56:47.66,EN,,0,0,0,,So that's just lambda of M--\nDialogue: 0,0:56:48.33,0:56:52.19,EN,,0,0,0,,that's substituted, because this object is being substituted for X,\nDialogue: 0,0:56:52.88,0:56:54.35,EN,,0,0,0,,which is the beginning of a list,\nDialogue: 0,0:56:54.88,0:57:00.32,EN,,0,0,0,,lambda of M-- M of 35 and 47,\nDialogue: 0,0:57:03.10,0:57:07.31,EN,,0,0,0,,applied to that procedure of A and D,\nDialogue: 0,0:57:07.48,0:57:08.67,EN,,0,0,0,,which gives me A.\nDialogue: 0,0:57:10.91,0:57:14.62,EN,,0,0,0,,Well, that's the result of substituting this for M here.\nDialogue: 0,0:57:15.96,0:57:21.71,EN,,0,0,0,,So that's the same thing as lambda of A, D, A,\nDialogue: 0,0:57:22.22,0:57:24.84,EN,,0,0,0,,applied to 35 and 47.\nDialogue: 0,0:57:26.33,0:57:27.37,EN,,0,0,0,,Oh, well that's 35.\nDialogue: 0,0:57:27.40,0:57:31.21,EN,,0,0,0,,That's substituting 35 for A and for 47 for D in A.\nDialogue: 0,0:57:35.60,0:57:37.24,EN,,0,0,0,,So I don't need any data at all.\nDialogue: 0,0:57:37.88,0:57:38.75,EN,,0,0,0,,not even numbers.\nDialogue: 0,0:57:40.92,0:57:42.64,EN,,0,0,0,,This is Alonso Church's hack.\nDialogue: 0,0:57:52.42,0:57:56.17,EN,,0,0,0,,Well, now we're going to do something nasty to him.\nDialogue: 0,0:57:56.76,0:57:58.49,EN,,0,0,0,,Being a logician, he wouldn't like this.\nDialogue: 0,0:57:59.20,0:58:01.96,EN,,0,0,0,,But as programmers, let's look at the overhead.\nDialogue: 0,0:58:03.26,0:58:04.16,EN,,0,0,0,,And here we go.\nDialogue: 0,0:58:05.39,0:58:07.58,EN,,0,0,0,,I'm going to change the definition of CONS.\nDialogue: 0,0:58:09.57,0:58:12.35,EN,,0,0,0,,It's almost the same as Alonzo Church's, but not quite.\nDialogue: 0,0:58:14.41,0:58:15.50,EN,,0,0,0,,What do we have here?\nDialogue: 0,0:58:16.07,0:58:18.72,EN,,0,0,0,,The CONS of two arguments, X and Y,\nDialogue: 0,0:58:19.50,0:58:22.51,EN,,0,0,0,,is going to be that procedure of one argument M,\nDialogue: 0,0:58:23.39,0:58:25.64,EN,,0,0,0,,which supplies M to X and Y as before,\nDialogue: 0,0:58:26.19,0:58:29.29,EN,,0,0,0,,but also to two permissions,\nDialogue: 0,0:58:30.17,0:58:32.01,EN,,0,0,0,,the permission to set X to N\nDialogue: 0,0:58:32.60,0:58:34.40,EN,,0,0,0,,and the permission to set Y to N,\nDialogue: 0,0:58:34.44,0:58:35.68,EN,,0,0,0,,given that I have an N.\nDialogue: 0,0:58:40.94,0:58:44.72,EN,,0,0,0,,So besides the things that I had here in Church's definition,\nDialogue: 0,0:58:45.72,0:58:51.66,EN,,0,0,0,,what I have is that the thing that CONS returns\nDialogue: 0,0:58:52.12,0:58:53.82,EN,,0,0,0,,will apply its argument\nDialogue: 0,0:58:54.91,0:58:59.44,EN,,0,0,0,,to not just the values of the X and Y that the CONS is made of,\nDialogue: 0,0:58:59.69,0:59:03.58,EN,,0,0,0,,but also permissions to set X and Y to new values.\nDialogue: 0,0:59:06.54,0:59:08.08,EN,,0,0,0,,Now, of course, just as before,\nDialogue: 0,0:59:08.83,0:59:10.51,EN,,0,0,0,,CAR is exactly the same.\nDialogue: 0,0:59:11.69,0:59:14.36,EN,,0,0,0,,The CAR of X is nothing more than applying X,\nDialogue: 0,0:59:14.54,0:59:16.00,EN,,0,0,0,,as in Church's definition,\nDialogue: 0,0:59:16.86,0:59:19.00,EN,,0,0,0,,to a procedure, in this case, of four arguments,\nDialogue: 0,0:59:19.29,0:59:21.04,EN,,0,0,0,,which selects out the first one.\nDialogue: 0,0:59:22.54,0:59:24.16,EN,,0,0,0,,And just as we did before,\nDialogue: 0,0:59:25.42,0:59:26.96,EN,,0,0,0,,that will be the value of X\nDialogue: 0,0:59:29.04,0:59:35.40,EN,,0,0,0,,that was contained in the procedure which is the result of evaluating this lambda expression\nDialogue: 0,0:59:35.45,0:59:37.84,EN,,0,0,0,,in the environment where X and Y are defined over here.\nDialogue: 0,0:59:41.94,0:59:43.15,EN,,0,0,0,,That's the value of CONS.\nDialogue: 0,0:59:45.64,0:59:47.53,EN,,0,0,0,,Now, however, the exciting part.\nDialogue: 0,0:59:47.73,0:59:48.96,EN,,0,0,0,,CDR, of course, is the same.\nDialogue: 0,0:59:49.39,0:59:50.35,EN,,0,0,0,,The exciting part,\nDialogue: 0,0:59:51.23,0:59:52.52,EN,,0,0,0,,set CAR and set CDR.\nDialogue: 0,0:59:53.45,0:59:55.52,EN,,0,0,0,,Well, they're nothing very complicated anymore.\nDialogue: 0,0:59:55.80,1:00:00.64,EN,,0,0,0,,Set CAR of a CONS X to a new value Y\nDialogue: 0,1:00:01.63,1:00:03.85,EN,,0,0,0,,is nothing more than applying that CONS,\nDialogue: 0,1:00:04.11,1:00:06.76,EN,,0,0,0,,which is the procedure of four--the procedure of one argument\nDialogue: 0,1:00:07.69,1:00:09.80,EN,,0,0,0,,which applies its argument to four things,\nDialogue: 0,1:00:11.24,1:00:15.85,EN,,0,0,0,,to a procedure which is of four arguments--\nDialogue: 0,1:00:16.00,1:00:18.08,EN,,0,0,0,,the value of X, the value of Y,\nDialogue: 0,1:00:18.32,1:00:20.54,EN,,0,0,0,,permission to set X, the permission to set Y--\nDialogue: 0,1:00:21.32,1:00:26.09,EN,,0,0,0,,and using it--using that permission to set X to the new value.\nDialogue: 0,1:00:31.65,1:00:33.54,EN,,0,0,0,,And similarly, set-cdr is the same thing.\nDialogue: 0,1:00:36.25,1:00:39.44,EN,,0,0,0,,So what you've just seen is that I didn't introduce any new primitives at all.\nDialogue: 0,1:00:40.11,1:00:44.36,EN,,0,0,0,,I mean, Whether or not I want to implement it this way is a matter of engineering.\nDialogue: 0,1:00:45.34,1:00:47.39,EN,,0,0,0,,And the answer is of course I don't implement it this way\nDialogue: 0,1:00:48.09,1:00:49.63,EN,,0,0,0,,for reasons that have to do with engineering.\nDialogue: 0,1:00:51.68,1:00:53.40,EN,,0,0,0,,However in principle, logically,\nDialogue: 0,1:00:54.28,1:00:56.43,EN,,0,0,0,,I introduced one assignment operator,\nDialogue: 0,1:00:56.96,1:00:58.76,EN,,0,0,0,,I've assigned--I've introduced them all.\nDialogue: 0,1:01:05.42,1:01:06.67,EN,,0,0,0,,Are there any questions?\nDialogue: 0,1:01:09.20,1:01:10.89,EN,,0,0,0,,Yes, David.\nDialogue: 0,1:01:12.04,1:01:15.64,EN,,0,0,0,,AUDIENCE: I can follow you up until you get--I can follow all of that.\nDialogue: 0,1:01:15.64,1:01:17.61,EN,,0,0,0,,But when we bring in the permissions,\nDialogue: 0,1:01:18.14,1:01:21.64,EN,,0,0,0,,defining CONS in terms of the lambda N,\nDialogue: 0,1:01:21.80,1:01:24.21,EN,,0,0,0,,I don't follow where N gets passed.\nDialogue: 0,1:01:24.21,1:01:25.69,EN,,0,0,0,,PROFESSOR: Oh, I'm sorry. I'll show you.\nDialogue: 0,1:01:26.34,1:01:27.05,EN,,0,0,0,,Let's follow it.\nDialogue: 0,1:01:27.36,1:01:29.07,EN,,0,0,0,,Of course, we could do it on the blackboard.\nDialogue: 0,1:01:29.18,1:01:30.17,EN,,0,0,0,,It's not so hard.\nDialogue: 0,1:01:30.17,1:01:31.47,EN,,0,0,0,,But it's also easy here.\nDialogue: 0,1:01:32.45,1:01:35.79,EN,,0,0,0,,Supposing I wish to set-cdr of X to Y.\nDialogue: 0,1:01:37.79,1:01:39.66,EN,,0,0,0,,See that right there. set cdr x to y\nDialogue: 0,1:01:40.36,1:01:41.92,EN,,0,0,0,,X is presumably a CONS,\nDialogue: 0,1:01:43.31,1:01:45.24,EN,,0,0,0,,a thing resulting from evaluating CONS.\nDialogue: 0,1:01:45.88,1:01:46.35,EN,,0,0,0,,right?\nDialogue: 0,1:01:46.89,1:01:49.96,EN,,0,0,0,,Therefore X comes from a place over here,\nDialogue: 0,1:01:52.57,1:01:56.49,EN,,0,0,0,,that that X is of the result of evaluating this lambda expression.\nDialogue: 0,1:01:58.11,1:01:58.49,EN,,0,0,0,,Right?\nDialogue: 0,1:01:59.38,1:02:01.63,EN,,0,0,0,,That when I evaluated that lambda expression,\nDialogue: 0,1:02:04.01,1:02:08.76,EN,,0,0,0,,I evaluated it in an environment where the arguments to CONS were defined.\nDialogue: 0,1:02:11.75,1:02:15.18,EN,,0,0,0,,That means that as free variables in this lambda expression,\nDialogue: 0,1:02:16.25,1:02:18.68,EN,,0,0,0,,there is the--there are in the frame,\nDialogue: 0,1:02:18.72,1:02:22.44,EN,,0,0,0,,which is the parent frame of this lambda expression,\nDialogue: 0,1:02:23.23,1:02:25.82,EN,,0,0,0,,the procedure resulting from this lambda expression,\nDialogue: 0,1:02:26.65,1:02:28.51,EN,,0,0,0,,X and Y have places.\nDialogue: 0,1:02:29.25,1:02:30.83,EN,,0,0,0,,And it's possible to set them.\nDialogue: 0,1:02:31.91,1:02:36.08,EN,,0,0,0,,I set them to an N, which is the argument of the permission.\nDialogue: 0,1:02:37.26,1:02:39.31,EN,,0,0,0,,The permission is a procedure\nDialogue: 0,1:02:41.40,1:02:43.18,EN,,0,0,0,,which is passed to M,\nDialogue: 0,1:02:43.29,1:02:46.51,EN,,0,0,0,,which is the argument that the CONS object gets passed.\nDialogue: 0,1:02:47.94,1:02:50.91,EN,,0,0,0,,Now, let's go back here in the set-cdr\nDialogue: 0,1:02:52.11,1:02:55.42,EN,,0,0,0,,The CONS object, which is the first argument of set-cdr\nDialogue: 0,1:02:56.12,1:02:57.48,EN,,0,0,0,,gets passed an argument.\nDialogue: 0,1:02:59.77,1:03:02.22,EN,,0,0,0,,That--there's a procedure of four things, indeed,\nDialogue: 0,1:03:02.32,1:03:04.65,EN,,0,0,0,,because that's the same thing as this M over here,\nDialogue: 0,1:03:04.99,1:03:06.56,EN,,0,0,0,,which is applied to four objects.\nDialogue: 0,1:03:07.92,1:03:13.34,EN,,0,0,0,,The object over here, SD, is, in fact, this permission.\nDialogue: 0,1:03:15.47,1:03:19.93,EN,,0,0,0,,When I use SD, I apply it to Y, right there.\nDialogue: 0,1:03:22.91,1:03:24.04,EN,,0,0,0,,So that comes from this.\nDialogue: 0,1:03:25.37,1:03:26.92,EN,,0,0,0,,AUDIENCE: So what do you--\nDialogue: 0,1:03:27.00,1:03:32.19,EN,,0,0,0,,PROFESSOR: So to finish that, the N that was here is the Y which is here.\nDialogue: 0,1:03:34.04,1:03:34.52,EN,,0,0,0,,How's that?\nDialogue: 0,1:03:34.81,1:03:35.75,EN,,0,0,0,,AUDIENCE: Right, OK.\nDialogue: 0,1:03:35.75,1:03:37.29,EN,,0,0,0,,Now, when you do a set-cdr,\nDialogue: 0,1:03:39.07,1:03:41.97,EN,,0,0,0,,X is the value the CDR is going to become.\nDialogue: 0,1:03:41.97,1:03:44.03,EN,,0,0,0,,PROFESSOR: The X over here.\nDialogue: 0,1:03:44.96,1:03:46.20,EN,,0,0,0,,I'm sorry, that's not true.\nDialogue: 0,1:03:46.20,1:03:48.33,EN,,0,0,0,,The X is--set-cdr has two arguments--\nDialogue: 0,1:03:48.91,1:03:50.36,EN,,0,0,0,,The CONS I'm changing\nDialogue: 0,1:03:51.34,1:03:53.93,EN,,0,0,0,,and the value I'm changing it to.\nDialogue: 0,1:03:56.15,1:03:58.32,EN,,0,0,0,,So you have them backwards, that's all.\nDialogue: 0,1:04:02.17,1:04:03.16,EN,,0,0,0,,Are there any other questions?\nDialogue: 0,1:04:07.88,1:04:08.64,EN,,0,0,0,,Well, thank you.\nDialogue: 0,1:04:08.64,1:04:09.52,EN,,0,0,0,,It's time for lunch.\nDialogue: 0,0:00:00.01,0:00:02.46,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N张大伟\\N（DreamAndDead）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:10.10,0:00:14.60,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算对象\nDialogue: 0,0:00:21.17,0:00:24.12,Default,,0,0,0,,现在我们已经学习了\nDialogue: 0,0:00:24.43,0:00:27.40,Default,,0,0,0,,如何创建局部状态和如何建模对象\nDialogue: 0,0:00:28.33,0:00:32.67,Default,,0,0,0,,我想我们应该找点复杂的东西\nDialogue: 0,0:00:34.03,0:00:36.36,Default,,0,0,0,,来实践一下学过的这些知识\nDialogue: 0,0:00:40.43,0:00:43.48,Default,,0,0,0,,我可以这么说 假设我们处在现实世界中\nDialogue: 0,0:00:44.11,0:00:46.25,Default,,0,0,0,,我们把这个世界看作是\nDialogue: 0,0:00:46.99,0:00:51.08,Default,,0,0,0,,由许多的事物构成的\nDialogue: 0,0:00:52.06,0:00:55.98,Default,,0,0,0,,每个事物都有其独立的局部状态\nDialogue: 0,0:00:57.24,0:00:59.87,Default,,0,0,0,,正是这些独立的状态使其成为事物\nDialogue: 0,0:01:01.28,0:01:04.27,Default,,0,0,0,,因此我们说 在这个世界的模型中\nDialogue: 0,0:01:04.28,0:01:09.90,Default,,0,0,0,,我们在大脑中和计算机中对那个世界建模\nDialogue: 0,0:01:10.94,0:01:12.54,Default,,0,0,0,,我想要建立一种对应关系\nDialogue: 0,0:01:12.78,0:01:15.21,Default,,0,0,0,,把现实世界和计算机中的对象联系起来\nDialogue: 0,0:01:15.87,0:01:17.74,Default,,0,0,0,,把现实世界中对象间的关系\nDialogue: 0,0:01:17.96,0:01:21.72,Default,,0,0,0,,与计算机中的模型对象间的关系 对应起来\nDialogue: 0,0:01:23.18,0:01:25.52,Default,,0,0,0,,把现实世界中关联对象的函数\nDialogue: 0,0:01:25.93,0:01:28.11,Default,,0,0,0,,与计算机中的函数 对应起来\nDialogue: 0,0:01:30.84,0:01:33.82,Default,,0,0,0,,这让我们获得了模块性\nDialogue: 0,0:01:34.74,0:01:36.75,Default,,0,0,0,,如果我们认为现实世界是像那样的\nDialogue: 0,0:01:37.36,0:01:38.72,Default,,0,0,0,,也就是由许多小的事物构成的\nDialogue: 0,0:01:39.20,0:01:41.47,Default,,0,0,0,,当然 我们可以把世界安排成那样\nDialogue: 0,0:01:42.03,0:01:43.95,Default,,0,0,0,,我们只能对像那样的事物建模\nDialogue: 0,0:01:45.45,0:01:49.02,Default,,0,0,0,,这样 我们的程序就可以从现实世界中继承模块化\nDialogue: 0,0:01:50.45,0:01:53.58,Default,,0,0,0,,这就是发明面向对象编程的初衷\nDialogue: 0,0:01:55.42,0:01:58.19,Default,,0,0,0,,我所见过的最完美的对象（系统）\nDialogue: 0,0:01:58.89,0:02:04.17,Default,,0,0,0,,电气系统 就是非常非常完美的对象系统\nDialogue: 0,0:02:06.40,0:02:12.99,Default,,0,0,0,,电气系统真的是物理学家构造的非常非常好的一种对象\nDialogue: 0,0:02:14.22,0:02:16.76,Default,,0,0,0,,这里 我有一些机器零件\nDialogue: 0,0:02:17.12,0:02:18.28,Default,,0,0,0,,就是这些零件\nDialogue: 0,0:02:20.04,0:02:22.88,Default,,0,0,0,,有一个电线连接起了\nDialogue: 0,0:02:23.66,0:02:26.40,Default,,0,0,0,,零件的两个部分\nDialogue: 0,0:02:27.56,0:02:30.86,Default,,0,0,0,,电气世界中 有一个非常棒的特性\nDialogue: 0,0:02:31.64,0:02:33.12,Default,,0,0,0,,就是我可以说这是一个对象\nDialogue: 0,0:02:34.01,0:02:34.97,Default,,0,0,0,,这又是一个对象\nDialogue: 0,0:02:35.71,0:02:37.53,Default,,0,0,0,,它们间的关联一目了然\nDialogue: 0,0:02:38.24,0:02:43.32,Default,,0,0,0,,而且 如果我没有用电线连接 它们便没有关联\nDialogue: 0,0:02:44.74,0:02:46.12,Default,,0,0,0,,比如我有一个灯泡\nDialogue: 0,0:02:46.52,0:02:50.32,Default,,0,0,0,,一个灯泡和一个已经接在插座上的电源\nDialogue: 0,0:02:51.63,0:02:53.53,Default,,0,0,0,,关联非常明了\nDialogue: 0,0:02:53.62,0:02:55.42,Default,,0,0,0,,这就是已知所有的连接方式了\nDialogue: 0,0:02:56.22,0:03:02.33,Default,,0,0,0,,就算我把连接电灯和电源的电线打个结\nDialogue: 0,0:03:02.68,0:03:03.64,Default,,0,0,0,,灯仍然是亮的\nDialogue: 0,0:03:04.04,0:03:04.76,Default,,0,0,0,,没什么影响\nDialogue: 0,0:03:07.44,0:03:12.40,Default,,0,0,0,,物理学上这样安排 可以使连接变成抽象的\nDialogue: 0,0:03:13.08,0:03:15.27,Default,,0,0,0,,至少在低频状态下是可以的\nDialogue: 0,0:03:17.84,0:03:20.88,Default,,0,0,0,,而且这就是全部的关联方式了\nDialogue: 0,0:03:22.35,0:03:23.87,Default,,0,0,0,,当然 我们来进一步\nDialogue: 0,0:03:23.90,0:03:27.31,Default,,0,0,0,,讨论一种在电气系统中最为广泛的抽象\nDialogue: 0,0:03:27.85,0:03:29.42,Default,,0,0,0,,数字电路\nDialogue: 0,0:03:31.69,0:03:33.66,Default,,0,0,0,,这里有一些对象\nDialogue: 0,0:03:34.64,0:03:40.12,Default,,0,0,0,,例如 在数字电路里中 我们有非门\nDialogue: 0,0:03:41.39,0:03:42.78,Default,,0,0,0,,有与门\nDialogue: 0,0:03:43.99,0:03:45.40,Default,,0,0,0,,还有或门\nDialogue: 0,0:03:47.21,0:03:50.12,Default,,0,0,0,,我们用一种特殊的“电线” 把它们连接起来\nDialogue: 0,0:03:52.00,0:03:54.94,Default,,0,0,0,,这些“电线”代表抽象信号\nDialogue: 0,0:03:55.61,0:03:57.18,Default,,0,0,0,,我们不关心具体的物理因素\nDialogue: 0,0:03:57.21,0:03:59.72,Default,,0,0,0,,像电压、电流或者组合因素等\nDialogue: 0,0:04:00.01,0:04:03.44,Default,,0,0,0,,又或者是水压 等等\nDialogue: 0,0:04:05.20,0:04:07.32,Default,,0,0,0,,这些抽象变量代表某类信号\nDialogue: 0,0:04:09.42,0:04:12.89,Default,,0,0,0,,我们用电路连接元件 构建系统\nDialogue: 0,0:04:14.07,0:04:16.22,Default,,0,0,0,,现在 我要向你们介绍一门新的语言\nDialogue: 0,0:04:17.63,0:04:20.17,Default,,0,0,0,,我们要构建一门内嵌于Lisp中的语言\nDialogue: 0,0:04:22.14,0:04:25.08,Default,,0,0,0,,这是一种内部DSL 是类似于之前讲过的图形语言那种\nDialogue: 0,0:04:26.16,0:04:27.32,Default,,0,0,0,,而不是昨天那种\nDialogue: 0,0:04:27.88,0:04:31.61,Default,,0,0,0,,那种模式匹配语言 -- 那是外部DSL\nDialogue: 0,0:04:32.80,0:04:36.30,Default,,0,0,0,,模式匹配语言是由Lisp程序所解释的\nDialogue: 0,0:04:38.16,0:04:40.52,Default,,0,0,0,,而之前那种图形语言\nDialogue: 0,0:04:40.56,0:04:44.27,Default,,0,0,0,,是在Lisp中构造我们想要的过程 来封装图形结构\nDialogue: 0,0:04:45.48,0:04:46.75,Default,,0,0,0,,举例来说\nDialogue: 0,0:04:47.72,0:04:50.64,Default,,0,0,0,,首先我要有一些基本对象\nDialogue: 0,0:04:51.05,0:04:52.12,Default,,0,0,0,,比如这个和这个\nDialogue: 0,0:04:53.50,0:04:55.18,Default,,0,0,0,,然后用电线去组合它们\nDialogue: 0,0:04:55.98,0:04:59.37,Default,,0,0,0,,我用(MAKE-WIRE)来构造一个电线\nDialogue: 0,0:04:59.87,0:05:01.24,Default,,0,0,0,,A就代表了一根电线\nDialogue: 0,0:05:01.74,0:05:02.69,Default,,0,0,0,,B也是\nDialogue: 0,0:05:02.69,0:05:03.46,Default,,0,0,0,,C也是\nDialogue: 0,0:05:03.46,0:05:04.23,Default,,0,0,0,,D也是\nDialogue: 0,0:05:04.23,0:05:04.83,Default,,0,0,0,,还有E\nDialogue: 0,0:05:04.83,0:05:05.64,Default,,0,0,0,,S也是\nDialogue: 0,0:05:06.88,0:05:12.75,Default,,0,0,0,,而或门有两个输入 分别是A和B\nDialogue: 0,0:05:13.16,0:05:14.75,Default,,0,0,0,,它的输出是D\nDialogue: 0,0:05:15.07,0:05:16.12,Default,,0,0,0,,我们用这样的记号来表示\nDialogue: 0,0:05:18.14,0:05:22.14,Default,,0,0,0,,与门 输入是A和B 输出是C\nDialogue: 0,0:05:22.22,0:05:23.24,Default,,0,0,0,,我们这样表示\nDialogue: 0,0:05:24.82,0:05:28.46,Default,,0,0,0,,通过一系列像这样的声明\nDialogue: 0,0:05:29.29,0:05:31.64,Default,,0,0,0,,我可以组合出任意的电路\nDialogue: 0,0:05:32.75,0:05:34.64,Default,,0,0,0,,我已经告诉了你们创建数字电路\nDialogue: 0,0:05:35.31,0:05:38.51,Default,,0,0,0,,的基本元素和组合方法了\nDialogue: 0,0:05:40.09,0:05:43.04,Default,,0,0,0,,然后就该说抽象的方法了\nDialogue: 0,0:05:43.69,0:05:52.24,Default,,0,0,0,,举例来说 这是一个半加器\nDialogue: 0,0:05:52.67,0:05:55.55,Default,,0,0,0,,如果你学过电路设计肯定知道这个东西\nDialogue: 0,0:05:56.93,0:06:00.44,Default,,0,0,0,,输入两个数A和B\nDialogue: 0,0:06:00.62,0:06:02.12,Default,,0,0,0,,输出两者之和以及进位\nDialogue: 0,0:06:04.35,0:06:06.80,Default,,0,0,0,,事实上 完全可以用我刚刚说的来组合电路\nDialogue: 0,0:06:07.45,0:06:10.99,Default,,0,0,0,,盒子外面 半加器盒子的外面有一些接口\nDialogue: 0,0:06:11.13,0:06:14.11,Default,,0,0,0,,这些盒子的边界 我们总是抽象成盒子\nDialogue: 0,0:06:14.79,0:06:19.70,Default,,0,0,0,,从盒子里引出A、B、S、C四根线\nDialogue: 0,0:06:19.70,0:06:21.79,Default,,0,0,0,,这些是已经声明了的变量\nDialogue: 0,0:06:23.39,0:06:26.25,Default,,0,0,0,,由LAMBDA表达式声明的几个变量\nDialogue: 0,0:06:26.28,0:06:28.01,Default,,0,0,0,,定义了这个半加器\nDialogue: 0,0:06:31.40,0:06:35.96,Default,,0,0,0,,在盒子的内部 我构造了电线D和E\nDialogue: 0,0:06:36.00,0:06:37.44,Default,,0,0,0,,这是为了连接内部结构\nDialogue: 0,0:06:37.74,0:06:40.40,Default,,0,0,0,,这条是E 这条是D\nDialogue: 0,0:06:41.32,0:06:43.50,Default,,0,0,0,,内部连接的线路并没有引出盒子之外\nDialogue: 0,0:06:45.05,0:06:46.83,Default,,0,0,0,,就像电路图那样连起来\nDialogue: 0,0:06:48.79,0:06:50.89,Default,,0,0,0,,大家可以看得出来\nDialogue: 0,0:06:51.05,0:06:53.02,Default,,0,0,0,,这个语言非常有层次性\nDialogue: 0,0:06:53.85,0:06:55.71,Default,,0,0,0,,如果一门语言没有层次性\nDialogue: 0,0:06:55.95,0:06:59.96,Default,,0,0,0,,如果你不能把一个复合对象当成基本对象来使用\nDialogue: 0,0:07:00.38,0:07:01.53,Default,,0,0,0,,这门语言肯定是有问题的\nDialogue: 0,0:07:02.59,0:07:04.22,Default,,0,0,0,,至少我是这么认为的\nDialogue: 0,0:07:06.41,0:07:09.58,Default,,0,0,0,,之前 我们都是在研究数学函数\nDialogue: 0,0:07:09.60,0:07:11.12,Default,,0,0,0,,或者是计算数学函数的东西\nDialogue: 0,0:07:11.15,0:07:12.65,Default,,0,0,0,,这些都是我们之前研究的东西\nDialogue: 0,0:07:13.85,0:07:16.65,Default,,0,0,0,,而我们现在\nDialogue: 0,0:07:16.67,0:07:17.63,Default,,0,0,0,,不这么做了\nDialogue: 0,0:07:17.85,0:07:20.88,Default,,0,0,0,,我们从一些电气对象开始\nDialogue: 0,0:07:21.04,0:07:22.64,Default,,0,0,0,,构建更多的对象\nDialogue: 0,0:07:23.35,0:07:28.83,Default,,0,0,0,,我们用Lisp里的LAMBDA将其粘合起来\nDialogue: 0,0:07:30.38,0:07:32.93,Default,,0,0,0,,“LAMBDA: 终极之粘合剂”\nDialogue: 0,0:07:33.32,0:07:36.35,Default,,0,0,0,,当然 半加器可以用于\nDialogue: 0,0:07:37.64,0:07:41.04,Default,,0,0,0,,构造一种更复杂的抽象结构 -- 全加器\nDialogue: 0,0:07:41.60,0:07:45.05,Default,,0,0,0,,如这里所示 全加器由两个半加器构成\nDialogue: 0,0:07:45.47,0:07:47.87,Default,,0,0,0,,用一些额外的电线连接起来\nDialogue: 0,0:07:48.08,0:07:51.29,Default,,0,0,0,,就像这里所示的S、C1、C2以及一个或门\nDialogue: 0,0:07:52.19,0:07:53.60,Default,,0,0,0,,而对于一个全加器\nDialogue: 0,0:07:53.87,0:08:00.78,Default,,0,0,0,,它的输入有：两个待加的数 一个进位值\nDialogue: 0,0:08:01.36,0:08:04.17,Default,,0,0,0,,输出是：两数之和以及进位\nDialogue: 0,0:08:05.90,0:08:10.70,Default,,0,0,0,,构建好全加器以后 还可以把它们链起来组成更大的加法器\nDialogue: 0,0:08:12.99,0:08:14.83,Default,,0,0,0,,现在我们有了一门完整的语言\nDialogue: 0,0:08:16.06,0:08:21.76,Default,,0,0,0,,它有基本元素、组合方法以及抽象方法\nDialogue: 0,0:08:22.27,0:08:23.36,Default,,0,0,0,,现在 我们怎样实现这门语言？\nDialogue: 0,0:08:25.00,0:08:26.84,Default,,0,0,0,,其实并不难\nDialogue: 0,0:08:27.07,0:08:27.96,Default,,0,0,0,,首先来看基本元素\nDialogue: 0,0:08:28.12,0:08:30.11,Default,,0,0,0,,这是唯一的问题\nDialogue: 0,0:08:31.16,0:08:32.56,Default,,0,0,0,,不需要再做其它事情了\nDialogue: 0,0:08:33.74,0:08:38.00,Default,,0,0,0,,因为我们直接借用了Lisp中的组合方法以及抽象方法\nDialogue: 0,0:08:39.96,0:08:41.88,Default,,0,0,0,,我们的语言 继承自Lisp并内嵌于其中\nDialogue: 0,0:08:43.77,0:08:45.44,Default,,0,0,0,,好 我们先来看一个基本元素\nDialogue: 0,0:08:45.86,0:08:47.40,Default,,0,0,0,,就拿非门来说吧\nDialogue: 0,0:08:51.54,0:08:54.67,Default,,0,0,0,,非门有两个引脚 分别是输入和输出\nDialogue: 0,0:08:57.31,0:09:02.62,Default,,0,0,0,,它要对输入信号做出响应\nDialogue: 0,0:09:04.30,0:09:07.00,Default,,0,0,0,,它需要对输入电线说 --\nDialogue: 0,0:09:07.64,0:09:10.14,Default,,0,0,0,,我们现在把它们视作对象\nDialogue: 0,0:09:10.44,0:09:12.41,Default,,0,0,0,,其具体细节我们稍后讨论\nDialogue: 0,0:09:13.23,0:09:14.84,Default,,0,0,0,,它对其输入电线的说\nDialogue: 0,0:09:15.82,0:09:18.48,Default,,0,0,0,,“当你的值变发生改变时 告诉我一声”\nDialogue: 0,0:09:20.12,0:09:22.11,Default,,0,0,0,,所以非门这个对象\nDialogue: 0,0:09:22.41,0:09:24.38,Default,,0,0,0,,会对输入电线这个对象说 --\nDialogue: 0,0:09:25.13,0:09:26.40,Default,,0,0,0,,“Hi 我是George”\nDialogue: 0,0:09:26.87,0:09:31.02,Default,,0,0,0,,“我的工作就是 对你的变化做出响应”\nDialogue: 0,0:09:31.72,0:09:34.19,Default,,0,0,0,,“所以当你变化的时候 告诉我一声”\nDialogue: 0,0:09:34.73,0:09:35.72,Default,,0,0,0,,“这样我才能进一步的处理”\nDialogue: 0,0:09:36.88,0:09:40.30,Default,,0,0,0,,这是通过在这里 在输入电线上\nDialogue: 0,0:09:41.40,0:09:44.64,Default,,0,0,0,,添加一个叫做INVERT-IN的动作来实现的\nDialogue: 0,0:09:45.07,0:09:46.94,Default,,0,0,0,,INVERT-IN在这里定义\nDialogue: 0,0:09:47.05,0:09:48.76,Default,,0,0,0,,它是一个无参过程\nDialogue: 0,0:09:49.98,0:09:54.59,Default,,0,0,0,,它将线路上的信号逻辑取反\nDialogue: 0,0:09:56.06,0:09:58.64,Default,,0,0,0,,经过一段时长为INVERTER-DELAT的延时以后 --\nDialogue: 0,0:09:59.26,0:10:01.15,Default,,0,0,0,,每个电路对象都有延时 --\nDialogue: 0,0:10:02.88,0:10:04.46,Default,,0,0,0,,然后我们会 --\nDialogue: 0,0:10:04.67,0:10:07.14,Default,,0,0,0,,我们再把输出设置为新的值\nDialogue: 0,0:10:10.16,0:10:11.36,Default,,0,0,0,,非常简单\nDialogue: 0,0:10:12.40,0:10:15.28,Default,,0,0,0,,你可以想象输出电线也同样是信号敏感的\nDialogue: 0,0:10:15.77,0:10:18.27,Default,,0,0,0,,当信号改变的时候\nDialogue: 0,0:10:19.28,0:10:21.15,Default,,0,0,0,,它会“告知”其它对象\nDialogue: 0,0:10:21.79,0:10:24.78,Default,,0,0,0,,“快醒醒！我的值已经改变啦”\nDialogue: 0,0:10:26.05,0:10:30.14,Default,,0,0,0,,所以当你把非门和与门或者元件连在一起的时候\nDialogue: 0,0:10:30.46,0:10:32.20,Default,,0,0,0,,它们之间将会有大量的通信\nDialogue: 0,0:10:32.86,0:10:35.07,Default,,0,0,0,,以确保信号正确地传播\nDialogue: 0,0:10:36.81,0:10:38.62,Default,,0,0,0,,到目前为止 没什么新奇的东西\nDialogue: 0,0:10:38.62,0:10:40.72,Default,,0,0,0,,我们只是针对某个特定的表示法\nDialogue: 0,0:10:40.72,0:10:45.24,Default,,0,0,0,,也就是这个例子中的1、0 -- 实现了LOGICAL-NOT而已\nDialogue: 0,0:10:46.73,0:10:49.16,Default,,0,0,0,,与门就相对复杂一些\nDialogue: 0,0:10:49.78,0:10:55.80,Default,,0,0,0,,与门有两个输入A1和A2 输出是OUTPUT\nDialogue: 0,0:10:56.73,0:11:00.64,Default,,0,0,0,,但是其结构和非门没有什么大的不同\nDialogue: 0,0:11:00.86,0:11:03.44,Default,,0,0,0,,只不过是 当输入信号改变的时候\nDialogue: 0,0:11:04.52,0:11:09.07,Default,,0,0,0,,与门调用的是AND-ACTION过程罢了\nDialogue: 0,0:11:10.91,0:11:12.88,Default,,0,0,0,,当然 它所做的只是\nDialogue: 0,0:11:12.91,0:11:15.37,Default,,0,0,0,,对输入信号进行逻辑“与”运算\nDialogue: 0,0:11:16.19,0:11:18.76,Default,,0,0,0,,在经过AND-GATE-DELAY的延时之后\nDialogue: 0,0:11:20.46,0:11:24.36,Default,,0,0,0,,调用这个过程 更新输出信号值\nDialogue: 0,0:11:25.47,0:11:28.35,Default,,0,0,0,,那么 我们如何用“按愿望思维”来构造这一切呢？\nDialogue: 0,0:11:28.35,0:11:31.08,Default,,0,0,0,,如大家所见 这里有一个赋值运算\nDialogue: 0,0:11:32.02,0:11:32.78,Default,,0,0,0,,但并不是SET!\nDialogue: 0,0:11:34.57,0:11:36.78,Default,,0,0,0,,这是一个派生出来的运算\nDialogue: 0,0:11:36.78,0:11:38.73,Default,,0,0,0,,就像可以从CAR和CDR派生出其它函数一样\nDialogue: 0,0:11:40.80,0:11:44.81,Default,,0,0,0,,因此 按照约定 我加上“!”（表示这个过程有副作用）\nDialogue: 0,0:11:46.34,0:11:49.18,Default,,0,0,0,,这里有个过程ADD-ACTION!\nDialogue: 0,0:11:49.44,0:11:54.67,Default,,0,0,0,,它用来提醒与门中的局部线路A1\nDialogue: 0,0:11:55.63,0:11:58.68,Default,,0,0,0,,当它改变的时候记得执行过程AND-ACTION-PROCEDURE\nDialogue: 0,0:11:59.58,0:12:02.91,Default,,0,0,0,,A2也是一样\nDialogue: 0,0:12:06.31,0:12:07.23,Default,,0,0,0,,非常简单\nDialogue: 0,0:12:09.96,0:12:12.09,Default,,0,0,0,,现在我们再来看看\nDialogue: 0,0:12:12.70,0:12:16.12,Default,,0,0,0,,各部分间是如何通信的\nDialogue: 0,0:12:18.54,0:12:19.66,Default,,0,0,0,,例如\nDialogue: 0,0:12:23.12,0:12:24.27,Default,,0,0,0,,有一个非常简单的电路\nDialogue: 0,0:12:24.27,0:12:30.46,Default,,0,0,0,,它有一个与门 带有两个输入A、B\nDialogue: 0,0:12:31.92,0:12:38.00,Default,,0,0,0,,与门通过电线C跟非门相连\nDialogue: 0,0:12:39.72,0:12:41.53,Default,,0,0,0,,非门的输出是D\nDialogue: 0,0:12:44.20,0:12:47.34,Default,,0,0,0,,这就是物理世界\nDialogue: 0,0:12:47.36,0:12:49.02,Default,,0,0,0,,一个对物理世界的抽象\nDialogue: 0,0:12:49.86,0:12:53.40,Default,,0,0,0,,要不了几分钱就可以从Radio Shack买到这些元件\nDialogue: 0,0:12:54.88,0:12:56.32,Default,,0,0,0,,那些元件的作用和画在这里的差不多\nDialogue: 0,0:12:57.16,0:13:00.22,Default,,0,0,0,,元件上都标有类似于LS04的标签\nDialogue: 0,0:13:01.53,0:13:08.16,Default,,0,0,0,,现在来看其中的计算模型\nDialogue: 0,0:13:09.01,0:13:10.94,Default,,0,0,0,,它又对应着什么\nDialogue: 0,0:13:11.13,0:13:14.09,Default,,0,0,0,,计算机中的对象对应着我们思维中的什么\nDialogue: 0,0:13:15.85,0:13:19.13,Default,,0,0,0,,我需要把现实世界中的每个对象与计算机中的对应起来\nDialogue: 0,0:13:19.79,0:13:24.27,Default,,0,0,0,,把两个世界中对象之间的关系也对应起来\nDialogue: 0,0:13:26.06,0:13:26.80,Default,,0,0,0,,这是我的目标\nDialogue: 0,0:13:28.56,0:13:29.45,Default,,0,0,0,,让我们来看看怎么做\nDialogue: 0,0:13:30.90,0:13:34.20,Default,,0,0,0,,这一团东西代表信号A\nDialogue: 0,0:13:35.71,0:13:36.94,Default,,0,0,0,,这是信号A\nDialogue: 0,0:13:37.94,0:13:39.32,Default,,0,0,0,,画得像一团云\nDialogue: 0,0:13:39.90,0:13:42.80,Default,,0,0,0,,再画另一个信号 -- B\nDialogue: 0,0:13:46.68,0:13:47.47,Default,,0,0,0,,它是另一个信号\nDialogue: 0,0:13:49.14,0:13:50.91,Default,,0,0,0,,这两个信号\nDialogue: 0,0:13:51.10,0:13:52.81,Default,,0,0,0,,要通过某种方式连在一起\nDialogue: 0,0:13:53.72,0:13:58.75,Default,,0,0,0,,连在这个盒子上 -- 这就代表与门\nDialogue: 0,0:14:00.32,0:14:02.04,Default,,0,0,0,,这就是与门的动作过程\nDialogue: 0,0:14:07.66,0:14:08.59,Default,,0,0,0,,它将产生\nDialogue: 0,0:14:09.15,0:14:13.29,Default,,0,0,0,,它将与另外一个称作C的信号对象交互\nDialogue: 0,0:14:16.22,0:14:18.88,Default,,0,0,0,,哦 说错了 是一条电线C\nDialogue: 0,0:14:20.59,0:14:26.28,Default,,0,0,0,,这跟电线 又将连在另一个动作过程上\nDialogue: 0,0:14:26.28,0:14:30.33,Default,,0,0,0,,在我们的电气世界中 这个过程跟一个非门关联\nDialogue: 0,0:14:32.86,0:14:40.65,Default,,0,0,0,,我还有另外一根电线 -- D\nDialogue: 0,0:14:42.97,0:14:45.29,Default,,0,0,0,,整体布局就是这样\nDialogue: 0,0:14:46.00,0:14:49.44,Default,,0,0,0,,现在必须来研究它们 有关计算的内部机制了\nDialogue: 0,0:14:51.50,0:14:53.69,Default,,0,0,0,,每一跟电线都必须知道\nDialogue: 0,0:14:53.69,0:14:56.36,Default,,0,0,0,,自己承载的信号是什么\nDialogue: 0,0:14:57.34,0:15:00.00,Default,,0,0,0,,我们用变量SIGNAL来表示\nDialogue: 0,0:15:02.97,0:15:04.04,Default,,0,0,0,,SIGNAL的值就是信号\nDialogue: 0,0:15:05.68,0:15:07.74,Default,,0,0,0,,也不要忘了它所关联的环境\nDialogue: 0,0:15:08.89,0:15:11.34,Default,,0,0,0,,对于每个元件来说 一定有一个环境绑定了信号\nDialogue: 0,0:15:15.40,0:15:16.88,Default,,0,0,0,,因此 这里也有一个SIGNAL变量\nDialogue: 0,0:15:19.40,0:15:21.92,Default,,0,0,0,,SIGNAL的值不是0就是1\nDialogue: 0,0:15:22.81,0:15:23.48,Default,,0,0,0,,这儿也有个SIGNAL\nDialogue: 0,0:15:28.00,0:15:30.56,Default,,0,0,0,,现在 一旦这里的信号改变\nDialogue: 0,0:15:31.26,0:15:34.11,Default,,0,0,0,,我们需要通知一系列的对象\nDialogue: 0,0:15:36.66,0:15:37.66,Default,,0,0,0,,我们得通知这个与门\nDialogue: 0,0:15:39.30,0:15:43.96,Default,,0,0,0,,这里有个表 我们把它叫做AP\nDialogue: 0,0:15:44.50,0:15:45.60,Default,,0,0,0,,它可能是一个表\nDialogue: 0,0:15:46.44,0:15:49.00,Default,,0,0,0,,在本例中 表里面的第一项条目是这个东西\nDialogue: 0,0:15:50.50,0:15:54.81,Default,,0,0,0,,这个元件也有一个称为AP的表\nDialogue: 0,0:15:54.81,0:15:58.17,Default,,0,0,0,,也可能有一些其它对象 时刻等待着A来通知“它们”\nDialogue: 0,0:15:59.02,0:16:01.31,Default,,0,0,0,,所以这里可能有其它对象 比如\nDialogue: 0,0:16:01.72,0:16:03.23,Default,,0,0,0,,一些其它我们不知道的对象\nDialogue: 0,0:16:03.63,0:16:04.88,Default,,0,0,0,,这些是与A连接的其它对象\nDialogue: 0,0:16:07.20,0:16:09.64,Default,,0,0,0,,这里的AP表\nDialogue: 0,0:16:11.12,0:16:12.40,Default,,0,0,0,,也指向这个与门\nDialogue: 0,0:16:13.07,0:16:16.35,Default,,0,0,0,,相类似的 这里的AP表\nDialogue: 0,0:16:16.78,0:16:18.53,Default,,0,0,0,,也要指向这里\nDialogue: 0,0:16:18.53,0:16:20.89,Default,,0,0,0,,这里是C要通知的元件\nDialogue: 0,0:16:21.77,0:16:23.18,Default,,0,0,0,,D也一样\nDialogue: 0,0:16:24.28,0:16:25.24,Default,,0,0,0,,但是我不知道它要通知谁\nDialogue: 0,0:16:25.26,0:16:26.65,Default,,0,0,0,,因为我的图中没有画出来\nDialogue: 0,0:16:27.19,0:16:28.36,Default,,0,0,0,,可能是和D连接起来的其它元件\nDialogue: 0,0:16:30.32,0:16:32.62,Default,,0,0,0,,同样的\nDialogue: 0,0:16:33.80,0:16:36.96,Default,,0,0,0,,当AND-ACTION过程被唤醒时\nDialogue: 0,0:16:37.02,0:16:41.31,Default,,0,0,0,,也就是说 之前你拜托某人将你唤醒\nDialogue: 0,0:16:41.45,0:16:44.84,Default,,0,0,0,,你拜托它们 当它们的信号发生改变时通知你\nDialogue: 0,0:16:46.97,0:16:48.81,Default,,0,0,0,,你得去检查它的信号是什么\nDialogue: 0,0:16:49.32,0:16:52.25,Default,,0,0,0,,这样你就可以计算逻辑与 输出信号给下一个元件\nDialogue: 0,0:16:57.09,0:16:58.75,Default,,0,0,0,,所里 这里就必须要有\nDialogue: 0,0:16:58.84,0:17:03.00,Default,,0,0,0,,有信息说 A1是这个元件\nDialogue: 0,0:17:03.90,0:17:06.48,Default,,0,0,0,,A2就是这个元件\nDialogue: 0,0:17:08.93,0:17:09.98,Default,,0,0,0,,不只是这样\nDialogue: 0,0:17:11.79,0:17:15.20,Default,,0,0,0,,当我在计算逻辑与时 我还得告诉这个元件一些信息\nDialogue: 0,0:17:16.30,0:17:21.05,Default,,0,0,0,,还有一个输出 输出给这个元件\nDialogue: 0,0:17:25.80,0:17:30.03,Default,,0,0,0,,同样地 非门也有一个输入\nDialogue: 0,0:17:32.38,0:17:34.92,Default,,0,0,0,,当信号被唤醒并告知它信号被修改时\nDialogue: 0,0:17:36.75,0:17:38.64,Default,,0,0,0,,非门会询问该信号\nDialogue: 0,0:17:38.64,0:17:40.09,Default,,0,0,0,,你的值是什么\nDialogue: 0,0:17:41.05,0:17:43.47,Default,,0,0,0,,信号通过像这样发消息 告知“信号已改变”\nDialogue: 0,0:17:43.52,0:17:45.53,Default,,0,0,0,,它就反过来查询这个新的信号值\nDialogue: 0,0:17:46.90,0:17:50.12,Default,,0,0,0,,取到值之后 它将会\nDialogue: 0,0:17:50.14,0:17:55.86,Default,,0,0,0,,计算输出 并改变这个信号的值\nDialogue: 0,0:18:00.60,0:18:01.24,Default,,0,0,0,,以此类推\nDialogue: 0,0:18:02.84,0:18:04.56,Default,,0,0,0,,因此我也必须有这么多的连接\nDialogue: 0,0:18:06.24,0:18:09.23,Default,,0,0,0,,现在我们回头观察一下 这个与门\nDialogue: 0,0:18:10.26,0:18:12.09,Default,,0,0,0,,回到这张幻灯片\nDialogue: 0,0:18:13.67,0:18:15.04,Default,,0,0,0,,这几个部分的内容\nDialogue: 0,0:18:16.04,0:18:19.32,Default,,0,0,0,,对每个与门 都有A1、A2两个输入 一个OUTPUT输出\nDialogue: 0,0:18:21.03,0:18:23.53,Default,,0,0,0,,这些都是\nDialogue: 0,0:18:25.08,0:18:28.16,Default,,0,0,0,,在AND-GATE被调用时的环境中\nDialogue: 0,0:18:28.41,0:18:31.24,Default,,0,0,0,,这些参数创建了一个框架\nDialogue: 0,0:18:33.31,0:18:35.90,Default,,0,0,0,,这个框架用来存放A1、A2和OUTPUT的值\nDialogue: 0,0:18:36.67,0:18:39.20,Default,,0,0,0,,它们都要与电线相绑定\nDialogue: 0,0:18:39.60,0:18:44.25,Default,,0,0,0,,这些电线就是通过参数传进来的\nDialogue: 0,0:18:46.24,0:18:47.31,Default,,0,0,0,,在这个环境下\nDialogue: 0,0:18:47.74,0:18:49.85,Default,,0,0,0,,我构建一个过程\nDialogue: 0,0:18:50.97,0:18:53.68,Default,,0,0,0,,就在这里\nDialogue: 0,0:18:54.59,0:18:57.31,Default,,0,0,0,,在该环境下定义的AND-ACTION-PROCEDURE\nDialogue: 0,0:18:58.35,0:19:00.70,Default,,0,0,0,,这个实际上是对一个LAMBDA表达式求值\nDialogue: 0,0:19:01.62,0:19:05.48,Default,,0,0,0,,它跟求值该LAMBDA表达式时的环境相绑定\nDialogue: 0,0:19:07.16,0:19:09.34,Default,,0,0,0,,找到它的局部环境\nDialogue: 0,0:19:11.70,0:19:13.47,Default,,0,0,0,,因此AND-ACTION-PROCEDURE过程能够\nDialogue: 0,0:19:13.64,0:19:16.94,Default,,0,0,0,,存取这里看到的A1、A2和OUTPUT\nDialogue: 0,0:19:17.31,0:19:19.64,Default,,0,0,0,,A1、A2、OUTPUT\nDialogue: 0,0:19:22.36,0:19:23.95,Default,,0,0,0,,我们还没有深入探索“电线”的内部结构\nDialogue: 0,0:19:26.03,0:19:26.99,Default,,0,0,0,,那是仅剩的部分\nDialogue: 0,0:19:29.03,0:19:29.92,Default,,0,0,0,,来看看“电线”\nDialogue: 0,0:19:33.52,0:19:36.25,Default,,0,0,0,,麻烦请开一下投影仪\nDialogue: 0,0:19:39.50,0:19:42.56,Default,,0,0,0,,“电线”是有那么一点复杂\nDialogue: 0,0:19:43.09,0:19:44.64,Default,,0,0,0,,哦 摁错了\nDialogue: 0,0:19:47.05,0:19:48.75,Default,,0,0,0,,是非常复杂 像这样\nDialogue: 0,0:19:50.06,0:19:53.10,Default,,0,0,0,,但是还是来看一下 到底是什么\nDialogue: 0,0:19:54.72,0:19:56.67,Default,,0,0,0,,“电线”是这样的一种东西\nDialogue: 0,0:19:57.76,0:20:03.52,Default,,0,0,0,,有两个主要部分 都是它的状态\nDialogue: 0,0:20:05.01,0:20:07.39,Default,,0,0,0,,我们这里看到的 一个是信号值\nDialogue: 0,0:20:07.45,0:20:10.06,Default,,0,0,0,,这里 当我们调用MAKE-WIRE创建一条电线时\nDialogue: 0,0:20:10.46,0:20:13.02,Default,,0,0,0,,我们首先要创建一些变量\nDialogue: 0,0:20:14.94,0:20:16.08,Default,,0,0,0,,分别是这条电线的\nDialogue: 0,0:20:17.10,0:20:19.29,Default,,0,0,0,,SIGNAL和ACTION-PROCS\nDialogue: 0,0:20:22.32,0:20:23.44,Default,,0,0,0,,在这个上下文中\nDialogue: 0,0:20:23.76,0:20:27.04,Default,,0,0,0,,我们定义了一系列的过程\nDialogue: 0,0:20:27.84,0:20:31.15,Default,,0,0,0,,其中一个是(SET-MY-SIGNAL! NEW)\nDialogue: 0,0:20:32.85,0:20:37.42,Default,,0,0,0,,它所做的只是 取一个新值NEW\nDialogue: 0,0:20:37.93,0:20:40.36,Default,,0,0,0,,如果NEW和SIGNAL一样 信号没有变化 就没必要做什么了\nDialogue: 0,0:20:40.36,0:20:42.62,Default,,0,0,0,,否则 把SIGNAL的值赋值为NEW\nDialogue: 0,0:20:42.75,0:20:44.60,Default,,0,0,0,,再调用ACTION-PROCS里的所有过程\nDialogue: 0,0:20:46.52,0:20:52.51,Default,,0,0,0,,那些我之前引入的过程\nDialogue: 0,0:20:54.63,0:21:01.53,Default,,0,0,0,,也就是我在定义与门时就定义的过程\nDialogue: 0,0:21:04.13,0:21:05.60,Default,,0,0,0,,是在代码最后调用ADD-ACTION-PROCEDURE实现的\nDialogue: 0,0:21:07.41,0:21:10.80,Default,,0,0,0,,然后 我还得定义一个过程 用来接受动作\nDialogue: 0,0:21:10.81,0:21:11.82,Default,,0,0,0,,也就是这段代码\nDialogue: 0,0:21:12.80,0:21:15.13,Default,,0,0,0,,它增加了AP表\nDialogue: 0,0:21:15.56,0:21:21.63,Default,,0,0,0,,这是通过使用SET!将PROC与旧的AP表CONS起来实现的\nDialogue: 0,0:21:21.79,0:21:24.25,Default,,0,0,0,,而这个PROC是作为参数传递进来的\nDialogue: 0,0:21:25.40,0:21:27.58,Default,,0,0,0,,由于技术原因 最后还要再运行一次PROC\nDialogue: 0,0:21:27.78,0:21:29.20,Default,,0,0,0,,我不会再对此详细展开\nDialogue: 0,0:21:29.39,0:21:33.15,Default,,0,0,0,,这是一种事件驱动的模拟\nDialogue: 0,0:21:34.59,0:21:36.00,Default,,0,0,0,,要想把这个讲清楚还是得花点时间\nDialogue: 0,0:21:36.95,0:21:39.40,Default,,0,0,0,,最后 我还要定义一个“分派器”\nDialogue: 0,0:21:39.96,0:21:43.58,Default,,0,0,0,,这是一种将消息分派给电线的方法\nDialogue: 0,0:21:45.37,0:21:48.65,Default,,0,0,0,,它将用于从中抽取出不同的信息\nDialogue: 0,0:21:49.07,0:21:51.48,Default,,0,0,0,,比如这里 当前的信号值是多少？\nDialogue: 0,0:21:53.82,0:21:55.66,Default,,0,0,0,,设置新信号值的方法是什么？\nDialogue: 0,0:21:57.18,0:21:58.28,Default,,0,0,0,,我想要这个方法\nDialogue: 0,0:22:00.10,0:22:02.60,Default,,0,0,0,,我怎么样去添加另外的动作过程呢？\nDialogue: 0,0:22:05.51,0:22:09.36,Default,,0,0,0,,最后 以DISPATCH过程为返回值返回\nDialogue: 0,0:22:09.94,0:22:11.87,Default,,0,0,0,,因此 我所构造的电线\nDialogue: 0,0:22:12.00,0:22:13.55,Default,,0,0,0,,是一种可以接收消息的对象\nDialogue: 0,0:22:14.25,0:22:16.01,Default,,0,0,0,,它接收的消息类似于\nDialogue: 0,0:22:16.44,0:22:18.36,Default,,0,0,0,,“你的哪个方法可以用来添加动作过程？”\nDialogue: 0,0:22:19.92,0:22:21.00,Default,,0,0,0,,它返回一个过程\nDialogue: 0,0:22:21.64,0:22:23.05,Default,,0,0,0,,它返回ADD-ACTION-PROCUDURE\nDialogue: 0,0:22:23.07,0:22:26.54,Default,,0,0,0,,我可以将其应用在一个动作过程上\nDialogue: 0,0:22:27.05,0:22:29.01,Default,,0,0,0,,从而实现将一个动作过程加入电线的AP表中\nDialogue: 0,0:22:31.62,0:22:32.82,Default,,0,0,0,,这是一种“许可”\nDialogue: 0,0:22:33.20,0:22:36.08,Default,,0,0,0,,使得你可以去修改自身的AP表\nDialogue: 0,0:22:37.82,0:22:40.16,Default,,0,0,0,,实际上 你可以在这里看到\nDialogue: 0,0:22:41.71,0:22:42.32,Default,,0,0,0,,下一张幻灯片\nDialogue: 0,0:22:43.53,0:22:43.82,Default,,0,0,0,,噢\nDialogue: 0,0:22:47.76,0:22:49.12,Default,,0,0,0,,没什么有意思的\nDialogue: 0,0:22:49.12,0:22:50.65,Default,,0,0,0,,CALL-EACH调用每个动作过程\nDialogue: 0,0:22:50.89,0:22:52.57,Default,,0,0,0,,这只是对一个表不断做CDR\nDialogue: 0,0:22:52.73,0:22:54.60,Default,,0,0,0,,没什么好说的\nDialogue: 0,0:22:54.99,0:22:56.25,Default,,0,0,0,,我们早就知道了\nDialogue: 0,0:22:57.56,0:23:00.67,Default,,0,0,0,,然而 如果我想知道线路上的信号值\nDialogue: 0,0:23:01.02,0:23:02.54,Default,,0,0,0,,我询问该线路：你的 --\nDialogue: 0,0:23:02.54,0:23:03.09,Default,,0,0,0,,回想一下 什么是线路？\nDialogue: 0,0:23:03.09,0:23:05.40,Default,,0,0,0,,线路对象只是在创建它时所返回的分派过程而已\nDialogue: 0,0:23:05.86,0:23:06.48,Default,,0,0,0,,只是一个过程\nDialogue: 0,0:23:06.83,0:23:12.27,Default,,0,0,0,,我向该分派器发送一个消息'GET-SIGNAL\nDialogue: 0,0:23:12.91,0:23:15.40,Default,,0,0,0,,实际得到的是一个方法 用于取得线路信号值\nDialogue: 0,0:23:16.90,0:23:17.96,Default,,0,0,0,,进一步 我就可以得到信号值\nDialogue: 0,0:23:19.22,0:23:20.52,Default,,0,0,0,,如果我想要设置一个信号值\nDialogue: 0,0:23:22.65,0:23:23.96,Default,,0,0,0,,我想要改变一个信号值\nDialogue: 0,0:23:24.51,0:23:26.76,Default,,0,0,0,,我要做的是\nDialogue: 0,0:23:26.92,0:23:29.69,Default,,0,0,0,,以一个线路和信号的新值作为参数\nDialogue: 0,0:23:30.01,0:23:32.43,Default,,0,0,0,,我向线路请求许可 来设置它的信号值\nDialogue: 0,0:23:32.84,0:23:37.61,Default,,0,0,0,,我会用该许可 -- 也就是一个过程 -- 应用在一个新值上\nDialogue: 0,0:23:38.70,0:23:40.51,Default,,0,0,0,,我们再过来看投影\nDialogue: 0,0:23:41.64,0:23:43.24,Default,,0,0,0,,好的 谢谢\nDialogue: 0,0:23:44.20,0:23:45.63,Default,,0,0,0,,我们看这里的投影\nDialogue: 0,0:23:45.92,0:23:48.75,Default,,0,0,0,,我们看到 如果我请求设置信号的方法\nDialogue: 0,0:23:49.34,0:23:50.44,Default,,0,0,0,,也就是这段代码\nDialogue: 0,0:23:52.25,0:23:55.69,Default,,0,0,0,,返回的是一个定义在线路内部的SET-MY-SIGNAL!方法\nDialogue: 0,0:23:56.25,0:23:57.69,Default,,0,0,0,,回过头来看它的定义\nDialogue: 0,0:23:58.72,0:23:59.74,Default,,0,0,0,,它的定义是\nDialogue: 0,0:24:00.43,0:24:02.68,Default,,0,0,0,,将我的一个内部变量SIGNAL的值设为\nDialogue: 0,0:24:02.73,0:24:05.50,Default,,0,0,0,,这个内部变量 用于存储信号值\nDialogue: 0,0:24:07.61,0:24:10.03,Default,,0,0,0,,将其值设为通过参数传递的NEW\nDialogue: 0,0:24:10.78,0:24:13.01,Default,,0,0,0,,然后调用AP表中的过程 来唤醒它们\nDialogue: 0,0:24:16.34,0:24:16.99,Default,,0,0,0,,非常简单\nDialogue: 0,0:24:19.24,0:24:20.76,Default,,0,0,0,,回头来看刚才的幻灯片\nDialogue: 0,0:24:22.48,0:24:24.32,Default,,0,0,0,,还有最后一点\nDialogue: 0,0:24:24.36,0:24:27.31,Default,,0,0,0,,我想你们现在应该很轻易地就能理解了\nDialogue: 0,0:24:27.77,0:24:29.15,Default,,0,0,0,,关于我们如何添加新的动作过程\nDialogue: 0,0:24:30.10,0:24:35.18,Default,,0,0,0,,我们需要WIRE和ACTION-PROC两个参数\nDialogue: 0,0:24:36.47,0:24:39.31,Default,,0,0,0,,然后请求添加动作过程的许可\nDialogue: 0,0:24:40.05,0:24:44.22,Default,,0,0,0,,得到许可后 用该许可去添加新的动作过程\nDialogue: 0,0:24:45.84,0:24:47.08,Default,,0,0,0,,所以 这确实是一个“对象”\nDialogue: 0,0:24:48.57,0:24:50.32,Default,,0,0,0,,还有些细节\nDialogue: 0,0:24:52.46,0:24:58.39,Default,,0,0,0,,比如 我怎么来控制它？\nDialogue: 0,0:24:58.39,0:24:59.69,Default,,0,0,0,,这些延时怎么实现？\nDialogue: 0,0:25:00.99,0:25:02.54,Default,,0,0,0,,我们来快速过一遍\nDialogue: 0,0:25:05.50,0:25:07.98,Default,,0,0,0,,下一张\nDialogue: 0,0:25:08.36,0:25:08.88,Default,,0,0,0,,我们来看看\nDialogue: 0,0:25:09.57,0:25:14.17,Default,,0,0,0,,我们细看与门、或门的定义\nDialogue: 0,0:25:15.31,0:25:17.00,Default,,0,0,0,,会发现当输入信号改变时\nDialogue: 0,0:25:17.24,0:25:18.19,Default,,0,0,0,,会有“延时”\nDialogue: 0,0:25:18.77,0:25:21.24,Default,,0,0,0,,然后它将调用过程\nDialogue: 0,0:25:21.63,0:25:23.00,Default,,0,0,0,,来改变输出\nDialogue: 0,0:25:26.04,0:25:27.92,Default,,0,0,0,,这个要如何实现？\nDialogue: 0,0:25:28.12,0:25:29.92,Default,,0,0,0,,我们将要建立一种机制\nDialogue: 0,0:25:30.30,0:25:32.00,Default,,0,0,0,,一种相当复杂的机制\nDialogue: 0,0:25:32.33,0:25:33.76,Default,,0,0,0,,我们得非常细心地来看\nDialogue: 0,0:25:34.72,0:25:37.23,Default,,0,0,0,,一段延时之后 我们将执行一个动作\nDialogue: 0,0:25:37.39,0:25:38.12,Default,,0,0,0,,DELAY是一个数\nDialogue: 0,0:25:38.16,0:25:39.23,Default,,0,0,0,,而ACTION是一个过程\nDialogue: 0,0:25:40.59,0:25:43.72,Default,,0,0,0,,我们引入一种称为THE-AGENDA的特殊数据结构\nDialogue: 0,0:25:45.50,0:25:48.80,Default,,0,0,0,,用于组织时间与动作\nDialogue: 0,0:25:49.51,0:25:50.88,Default,,0,0,0,,一会儿再来仔细研究\nDialogue: 0,0:25:50.88,0:25:52.54,Default,,0,0,0,,先把这里说完\nDialogue: 0,0:25:53.07,0:25:58.28,Default,,0,0,0,,THE-AGENDA将记录执行动作的时刻\nDialogue: 0,0:25:59.13,0:26:02.46,Default,,0,0,0,,我们把它设定在未来的某个时刻\nDialogue: 0,0:26:02.51,0:26:05.68,Default,,0,0,0,,也就是在CURRENT-TIME加上DELAT的时刻\nDialogue: 0,0:26:05.69,0:26:07.13,Default,,0,0,0,,触发关联的动作\nDialogue: 0,0:26:09.02,0:26:10.56,Default,,0,0,0,,我们把准备好要执行的动作\nDialogue: 0,0:26:11.02,0:26:12.40,Default,,0,0,0,,添加入THE-AGENDA中\nDialogue: 0,0:26:15.28,0:26:18.03,Default,,0,0,0,,要使这个“机器”运行起来并不困难\nDialogue: 0,0:26:18.66,0:26:21.48,Default,,0,0,0,,我们利用这个PROPAGATE过程来完成这件事\nDialogue: 0,0:26:22.71,0:26:25.95,Default,,0,0,0,,如果THE-AGENDA为空 就没有要做的\nDialogue: 0,0:26:27.44,0:26:28.16,Default,,0,0,0,,否则\nDialogue: 0,0:26:29.76,0:26:31.53,Default,,0,0,0,,我们就取出THE-AGENDA的第一个元素\nDialogue: 0,0:26:31.71,0:26:33.34,Default,,0,0,0,,它是一个无参过程\nDialogue: 0,0:26:34.20,0:26:36.03,Default,,0,0,0,,所以这里有额外的括号\nDialogue: 0,0:26:36.03,0:26:37.85,Default,,0,0,0,,我们对其进行无参调用\nDialogue: 0,0:26:39.19,0:26:40.17,Default,,0,0,0,,这就执行了之前存入的动作\nDialogue: 0,0:26:42.20,0:26:44.17,Default,,0,0,0,,然后我们从THE-AGENDA中删除第一个元素\nDialogue: 0,0:26:44.59,0:26:46.14,Default,,0,0,0,,然后再进入传播循环\nDialogue: 0,0:26:48.91,0:26:50.75,Default,,0,0,0,,这就是整体的结构\nDialogue: 0,0:26:53.38,0:26:55.93,Default,,0,0,0,,还有点其它的\nDialogue: 0,0:26:57.43,0:27:00.01,Default,,0,0,0,,现在 我们来看看THE-AGENDA的内部结构\nDialogue: 0,0:27:00.57,0:27:01.55,Default,,0,0,0,,请看投影仪\nDialogue: 0,0:27:02.80,0:27:04.67,Default,,0,0,0,,该如何使用这个玩意儿呢？\nDialogue: 0,0:27:04.67,0:27:07.41,Default,,0,0,0,,我需要给你们说明下这个模拟器的用法\nDialogue: 0,0:27:07.85,0:27:09.93,Default,,0,0,0,,你们可能觉得这个模拟器太简陋了\nDialogue: 0,0:27:10.40,0:27:12.01,Default,,0,0,0,,甚至你们认为它根本没什么用\nDialogue: 0,0:27:12.57,0:27:13.76,Default,,0,0,0,,而实际上是\nDialogue: 0,0:27:13.98,0:27:15.39,Default,,0,0,0,,这样的模拟器曾被用于\nDialogue: 0,0:27:15.72,0:27:17.44,Default,,0,0,0,,操纵相当大型的计算机\nDialogue: 0,0:27:18.68,0:27:20.64,Default,,0,0,0,,那是一个真实的事例\nDialogue: 0,0:27:22.36,0:27:24.06,Default,,0,0,0,,当然 并不完全是这里的这个模拟器\nDialogue: 0,0:27:24.06,0:27:25.39,Default,,0,0,0,,我会告诉你它们的区别\nDialogue: 0,0:27:25.84,0:27:28.70,Default,,0,0,0,,区别就是 操纵大型机的模拟器有更多的基本元素\nDialogue: 0,0:27:29.82,0:27:32.22,Default,,0,0,0,,不只是有非门 与门之类的\nDialogue: 0,0:27:33.20,0:27:35.72,Default,,0,0,0,,还有边缘触发器\nDialogue: 0,0:27:36.25,0:27:39.88,Default,,0,0,0,,翻转触发器 锁存器\nDialogue: 0,0:27:40.70,0:27:44.52,Default,,0,0,0,,电平触发器 加法器等等之类的\nDialogue: 0,0:27:45.17,0:27:47.31,Default,,0,0,0,,困难之处在于\nDialogue: 0,0:27:47.45,0:27:50.86,Default,,0,0,0,,就在于需要很多页的文档\nDialogue: 0,0:27:51.20,0:27:52.89,Default,,0,0,0,,来描述这些基本元素\nDialogue: 0,0:27:54.69,0:27:56.74,Default,,0,0,0,,同时它们还有很多的参数\nDialogue: 0,0:27:56.74,0:27:57.98,Default,,0,0,0,,不是只有一个延时这么简单\nDialogue: 0,0:27:58.48,0:28:00.81,Default,,0,0,0,,还有建立时间 维持时间之类的\nDialogue: 0,0:28:01.22,0:28:03.40,Default,,0,0,0,,但是 如果不算上那部分的复杂度\nDialogue: 0,0:28:03.82,0:28:08.20,Default,,0,0,0,,我们用来构建真实计算机的模拟器的结构\nDialogue: 0,0:28:09.08,0:28:12.89,Default,,0,0,0,,跟你们在这里看到的的是一致的\nDialogue: 0,0:28:15.11,0:28:19.27,Default,,0,0,0,,无论如何 这里都是一些简单的东西\nDialogue: 0,0:28:19.27,0:28:22.59,Default,,0,0,0,,像这个 设置非门的延时时间 构建一个 AGENDA\nDialogue: 0,0:28:23.03,0:28:25.52,Default,,0,0,0,,我们可以构建一些输入（线路）\nDialogue: 0,0:28:26.03,0:28:29.18,Default,,0,0,0,,这里的四条线路分别是：INPUT-1、INPUT-2、SUM和CARRY\nDialogue: 0,0:28:29.46,0:28:31.88,Default,,0,0,0,,我将要放置一种被称为“探针”的特殊对象\nDialogue: 0,0:28:32.51,0:28:34.64,Default,,0,0,0,,放在一些线路上\nDialogue: 0,0:28:34.97,0:28:36.24,Default,,0,0,0,,放在SUM和CARRY上\nDialogue: 0,0:28:37.23,0:28:40.56,Default,,0,0,0,,探针是一种对象 它可以 --\nDialogue: 0,0:28:40.70,0:28:43.60,Default,,0,0,0,,当你改变它所附着线路的信号时\nDialogue: 0,0:28:43.72,0:28:44.83,Default,,0,0,0,,它会输出一条消息\nDialogue: 0,0:28:46.12,0:28:46.92,Default,,0,0,0,,这很容易实现\nDialogue: 0,0:28:48.44,0:28:49.52,Default,,0,0,0,,一旦我们设置好它们\nDialogue: 0,0:28:49.55,0:28:51.45,Default,,0,0,0,,当你在放置探针的时候\nDialogue: 0,0:28:51.45,0:28:52.41,Default,,0,0,0,,它首先会输出\nDialogue: 0,0:28:52.67,0:28:56.01,Default,,0,0,0,,SUM在0时刻的值为0\nDialogue: 0,0:28:57.29,0:28:58.43,Default,,0,0,0,,这个我已经注意到了\nDialogue: 0,0:28:59.40,0:29:04.75,Default,,0,0,0,,CARRY在0时刻的值也是0\nDialogue: 0,0:29:06.04,0:29:09.28,Default,,0,0,0,,我们继续来构建更多结构\nDialogue: 0,0:29:09.62,0:29:12.28,Default,,0,0,0,,比如 可以像这里一样构建一种结构\nDialogue: 0,0:29:14.06,0:29:18.20,Default,,0,0,0,,用INPUT-1、INPUT-2、SUM和CARRY组成一个半加器\nDialogue: 0,0:29:18.42,0:29:20.42,Default,,0,0,0,,然后我们把INPUT-1上的信号变为1\nDialogue: 0,0:29:20.62,0:29:21.72,Default,,0,0,0,,然后开始传播\nDialogue: 0,0:29:21.88,0:29:22.84,Default,,0,0,0,,在时刻8的时候\nDialogue: 0,0:29:23.90,0:29:26.12,Default,,0,0,0,,如果你想的话 也可以单步跟踪传播过程\nDialogue: 0,0:29:26.52,0:29:29.20,Default,,0,0,0,,SUM的值变为1\nDialogue: 0,0:29:29.52,0:29:30.44,Default,,0,0,0,,然后就结束了\nDialogue: 0,0:29:31.16,0:29:32.25,Default,,0,0,0,,好像没什么意思\nDialogue: 0,0:29:32.63,0:29:33.90,Default,,0,0,0,,我们还可以设置信号\nDialogue: 0,0:29:34.06,0:29:36.73,Default,,0,0,0,,把INPUT-2也变为1\nDialogue: 0,0:29:36.89,0:29:38.09,Default,,0,0,0,,如果再进行传播\nDialogue: 0,0:29:38.36,0:29:39.95,Default,,0,0,0,,在时刻11\nDialogue: 0,0:29:40.12,0:29:41.42,Default,,0,0,0,,CARRY变为1\nDialogue: 0,0:29:41.55,0:29:44.19,Default,,0,0,0,,在时刻16 SUM变为0\nDialogue: 0,0:29:45.39,0:29:48.99,Default,,0,0,0,,如果你仔细研究那个电路图\nDialogue: 0,0:29:48.99,0:29:50.12,Default,,0,0,0,,它确实是这个结果\nDialogue: 0,0:29:50.62,0:29:51.53,Default,,0,0,0,,也并没有什么特别的\nDialogue: 0,0:29:51.53,0:29:54.12,Default,,0,0,0,,但是却清楚地表明了这一些都是如何运作的\nDialogue: 0,0:30:01.83,0:30:03.29,Default,,0,0,0,,我现在给你们展示的是\nDialogue: 0,0:30:03.48,0:30:05.52,Default,,0,0,0,,一种宏观的图景\nDialogue: 0,0:30:06.60,0:30:08.56,Default,,0,0,0,,你如何在一个很大的规模中\nDialogue: 0,0:30:08.72,0:30:12.04,Default,,0,0,0,,你何去实现某种事件驱动的模拟\nDialogue: 0,0:30:13.29,0:30:14.56,Default,,0,0,0,,你应该如何去组织\nDialogue: 0,0:30:14.88,0:30:16.70,Default,,0,0,0,,来获得良好的层次性结构\nDialogue: 0,0:30:16.99,0:30:21.00,Default,,0,0,0,,使得你可以构建可具体化的抽象盒子\nDialogue: 0,0:30:21.56,0:30:24.96,Default,,0,0,0,,但我还没有告诉你AGENDA是如何运作的\nDialogue: 0,0:30:25.78,0:30:26.54,Default,,0,0,0,,下一小节再说\nDialogue: 0,0:30:28.63,0:30:32.94,Default,,0,0,0,,这将涉及到一些关于数据变化之类的事情\nDialogue: 0,0:30:34.31,0:30:35.86,Default,,0,0,0,,在我继续之前 有什么问题吗？\nDialogue: 0,0:30:47.16,0:30:48.24,Default,,0,0,0,,没有的话 那就休息一下\nDialogue: 0,0:30:50.24,0:31:00.62,Default,,0,0,0,,[音乐]\nDialogue: 0,0:31:00.62,0:31:06.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:31:11.23,0:31:17.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:31:17.76,0:31:21.34,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:31:21.34,0:31:25.18,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算对象\nDialogue: 0,0:31:28.94,0:31:35.06,Default,,0,0,0,,我们已经做了一个模拟器\nDialogue: 0,0:31:35.39,0:31:37.77,Default,,0,0,0,,这是一种事件驱动的模拟\nDialogue: 0,0:31:38.17,0:31:42.75,Default,,0,0,0,,其中 计算机中的对象与现实中的对象一一对应\nDialogue: 0,0:31:43.92,0:31:47.28,Default,,0,0,0,,现实世界中按时发生的状态改变\nDialogue: 0,0:31:47.98,0:31:50.83,Default,,0,0,0,,被组织成了计算机中的时间\nDialogue: 0,0:31:52.99,0:31:56.04,Default,,0,0,0,,如果现实中某件事后于另一件事发生\nDialogue: 0,0:31:56.46,0:31:57.96,Default,,0,0,0,,那么在计算机中\nDialogue: 0,0:31:58.89,0:32:02.25,Default,,0,0,0,,两个事件也保持同样的先后顺序发生\nDialogue: 0,0:32:04.42,0:32:07.16,Default,,0,0,0,,排列这些时间 就是我们要用到赋值的地方\nDialogue: 0,0:32:08.22,0:32:11.21,Default,,0,0,0,,现在我要介绍一种方法来组织时间\nDialogue: 0,0:32:11.80,0:32:14.86,Default,,0,0,0,,AGENDA -- 或者有时候所谓的“优先队列”\nDialogue: 0,0:32:16.04,0:32:18.57,Default,,0,0,0,,我们首先需要认识到\nDialogue: 0,0:32:18.62,0:32:21.00,Default,,0,0,0,,为了创建AGENDA 我们需要些什么东西？\nDialogue: 0,0:32:28.33,0:32:31.28,Default,,0,0,0,,首先我要在这里写下一些\nDialogue: 0,0:32:31.39,0:32:33.88,Default,,0,0,0,,用于操作AGENDA的基本运算\nDialogue: 0,0:32:35.96,0:32:37.95,Default,,0,0,0,,我不会给出具体代码\nDialogue: 0,0:32:38.14,0:32:39.58,Default,,0,0,0,,因为它们都非常简单\nDialogue: 0,0:32:40.32,0:32:42.60,Default,,0,0,0,,而且你们手上也有\nDialogue: 0,0:32:43.68,0:32:44.38,Default,,0,0,0,,有哪些运算呢？\nDialogue: 0,0:32:44.38,0:32:53.50,Default,,0,0,0,,MAKE-AGENDA可以新建一个AGENDA\nDialogue: 0,0:32:57.36,0:33:01.77,Default,,0,0,0,,CURRENT-TIME可以获得一个AGENDA的当前时间\nDialogue: 0,0:33:07.47,0:33:12.80,Default,,0,0,0,,返回一个数 -- 也就是当前时间\nDialogue: 0,0:33:16.99,0:33:21.37,Default,,0,0,0,,EMPTY-AGENDA?可用于判断一个AGENDA是否为空\nDialogue: 0,0:33:30.20,0:33:32.57,Default,,0,0,0,,返回TRUE或FALSE\nDialogue: 0,0:33:42.72,0:33:44.72,Default,,0,0,0,,我们也可以向AGENDA中添加对象\nDialogue: 0,0:33:52.71,0:33:56.06,Default,,0,0,0,,实际上 向AGENDA中添加的是一个运算 -- 或者说是需要完成的操作\nDialogue: 0,0:33:56.91,0:33:58.14,Default,,0,0,0,,它需要时间TIME\nDialogue: 0,0:33:59.63,0:34:00.56,Default,,0,0,0,,待添加的动作ACTION\nDialogue: 0,0:34:02.86,0:34:04.64,Default,,0,0,0,,以及AGENDA本身\nDialogue: 0,0:34:07.58,0:34:10.25,Default,,0,0,0,,它把ACTION 放入AGENDA中合适的地方\nDialogue: 0,0:34:10.71,0:34:12.73,Default,,0,0,0,,FIRST-ITEM用于从AGENDA取出第一个事项\nDialogue: 0,0:34:14.24,0:34:15.39,Default,,0,0,0,,那是我首先需要做的事情\nDialogue: 0,0:34:21.84,0:34:23.84,Default,,0,0,0,,该事项是一个动作\nDialogue: 0,0:34:26.46,0:34:28.73,Default,,0,0,0,,我还可以把第一个事项从AGENDA中移除\nDialogue: 0,0:34:29.54,0:34:31.16,Default,,0,0,0,,这是操作AGENDA的一个必要运算\nDialogue: 0,0:34:31.40,0:34:33.02,Default,,0,0,0,,这个运算实现起来非常繁杂\nDialogue: 0,0:34:42.53,0:34:43.36,Default,,0,0,0,,从AGENDA中移除\nDialogue: 0,0:34:45.98,0:34:49.85,Default,,0,0,0,,现在我们来看如何具体组织数据结构\nDialogue: 0,0:34:52.96,0:34:56.04,Default,,0,0,0,,AGENDA应该是一种表\nDialogue: 0,0:34:58.43,0:35:01.20,Default,,0,0,0,,一种可修改的表\nDialogue: 0,0:35:01.57,0:35:04.03,Default,,0,0,0,,因为我们要向其中添加元素\nDialogue: 0,0:35:05.80,0:35:06.89,Default,,0,0,0,,删除元素等等\nDialogue: 0,0:35:07.77,0:35:10.27,Default,,0,0,0,,所以我们需要一种可修改的表\nDialogue: 0,0:35:11.07,0:35:12.51,Default,,0,0,0,,它通过时间组织起来\nDialogue: 0,0:35:13.82,0:35:15.57,Default,,0,0,0,,让它有序 也许会有益处\nDialogue: 0,0:35:18.33,0:35:20.88,Default,,0,0,0,,但是也有可能同一时间会发生很多事\nDialogue: 0,0:35:22.04,0:35:23.42,Default,,0,0,0,,或者说几乎同时\nDialogue: 0,0:35:23.80,0:35:24.72,Default,,0,0,0,,因此我们需要\nDialogue: 0,0:35:24.91,0:35:27.52,Default,,0,0,0,,把它们按发生时间为事件分组\nDialogue: 0,0:35:29.04,0:35:31.61,Default,,0,0,0,,所以我要把AGENDA组织成由SEGMENT构成的表\nDialogue: 0,0:35:32.78,0:35:35.69,Default,,0,0,0,,我来画一下这个结构\nDialogue: 0,0:35:36.68,0:35:37.93,Default,,0,0,0,,方便理解\nDialogue: 0,0:35:39.62,0:35:40.49,Default,,0,0,0,,这是一个AGENDA\nDialogue: 0,0:35:41.11,0:35:42.87,Default,,0,0,0,,以一个名字开始\nDialogue: 0,0:35:47.85,0:35:50.19,Default,,0,0,0,,我把它画在表结构的外部\nDialogue: 0,0:35:52.60,0:35:53.39,Default,,0,0,0,,这是它的头部\nDialogue: 0,0:35:54.14,0:35:55.44,Default,,0,0,0,,这个头部的存在也是很必要的\nDialogue: 0,0:35:55.84,0:35:57.63,Default,,0,0,0,,待会你就会知道\nDialogue: 0,0:36:00.68,0:36:03.40,Default,,0,0,0,,再画一个SEGMENT\nDialogue: 0,0:36:03.96,0:36:05.62,Default,,0,0,0,,这是一个由SEGMENT构成的表\nDialogue: 0,0:36:08.31,0:36:10.54,Default,,0,0,0,,假设这个AGENDA有两个SEGMENT\nDialogue: 0,0:36:11.58,0:36:15.07,Default,,0,0,0,,不断对这个表取CAR即可得到\nDialogue: 0,0:36:16.41,0:36:20.57,Default,,0,0,0,,每个SEGMENT都有一个时间\nDialogue: 0,0:36:24.20,0:36:26.64,Default,,0,0,0,,比如说这里是10\nDialogue: 0,0:36:26.83,0:36:30.51,Default,,0,0,0,,也就是说 这个SEGMENT里的事件发生在10时刻\nDialogue: 0,0:36:33.16,0:36:36.52,Default,,0,0,0,,这里是另外一种数据结构\nDialogue: 0,0:36:36.56,0:36:38.01,Default,,0,0,0,,我先不具体描述\nDialogue: 0,0:36:38.49,0:36:41.08,Default,,0,0,0,,它是一个队列 表示在10时刻要做的事\nDialogue: 0,0:36:42.24,0:36:43.33,Default,,0,0,0,,它是一个队列\nDialogue: 0,0:36:43.33,0:36:44.70,Default,,0,0,0,,一会儿再细说\nDialogue: 0,0:36:45.20,0:36:50.35,Default,,0,0,0,,不过抽象地看 队列就是一系列在固定时间要做的事\nDialogue: 0,0:36:50.40,0:36:52.04,Default,,0,0,0,,我可以向其中添加其它要做的事\nDialogue: 0,0:36:53.10,0:36:53.80,Default,,0,0,0,,这是一个队列\nDialogue: 0,0:36:56.14,0:36:59.11,Default,,0,0,0,,这个是时间 这个是SEGMENT\nDialogue: 0,0:37:03.23,0:37:06.36,Default,,0,0,0,,在这个AGENDA中 还有另一个SEGMENT\nDialogue: 0,0:37:08.94,0:37:11.20,Default,,0,0,0,,假设它在30时刻发生\nDialogue: 0,0:37:13.50,0:37:15.92,Default,,0,0,0,,类似地 它也有一个队列\nDialogue: 0,0:37:16.92,0:37:20.24,Default,,0,0,0,,里面是在30时刻要去做的事\nDialogue: 0,0:37:23.21,0:37:25.66,Default,,0,0,0,,当然 我们的AGENDA还需要支持其它操作\nDialogue: 0,0:37:27.09,0:37:29.20,Default,,0,0,0,,假设我想将一个在10时刻发生的事\nDialogue: 0,0:37:29.47,0:37:31.61,Default,,0,0,0,,添加到AGENDA中\nDialogue: 0,0:37:33.03,0:37:34.16,Default,,0,0,0,,这并不难\nDialogue: 0,0:37:34.70,0:37:38.65,Default,,0,0,0,,我遍历到这里 找到时刻是10的SEGMENT\nDialogue: 0,0:37:39.73,0:37:42.14,Default,,0,0,0,,这样的SEGMENT也可能不存在\nDialogue: 0,0:37:42.93,0:37:44.56,Default,,0,0,0,,一会儿再考虑这种情况\nDialogue: 0,0:37:45.42,0:37:47.56,Default,,0,0,0,,如果我找到了时刻为10的SEGMENT\nDialogue: 0,0:37:47.87,0:37:50.43,Default,,0,0,0,,如果我想要把一个事情放入其中\nDialogue: 0,0:37:50.56,0:37:52.16,Default,,0,0,0,,我只要增加该队列即可\nDialogue: 0,0:37:53.85,0:37:56.22,Default,,0,0,0,,这个说起来倒是很容易\nDialogue: 0,0:37:56.57,0:37:59.26,Default,,0,0,0,,我在这里添加需要在那时做的事\nDialogue: 0,0:38:01.43,0:38:04.25,Default,,0,0,0,,现在 假设我想在时刻20做点什么\nDialogue: 0,0:38:05.31,0:38:07.90,Default,,0,0,0,,然而并没有时刻是20的SEGMENT\nDialogue: 0,0:38:08.99,0:38:10.64,Default,,0,0,0,,我不得不构造一个新的SEGMENT\nDialogue: 0,0:38:11.34,0:38:15.64,Default,,0,0,0,,我想把这个SEGMENT 放在10与30之间\nDialogue: 0,0:38:17.61,0:38:19.32,Default,,0,0,0,,这着实要花点功夫\nDialogue: 0,0:38:20.17,0:38:21.52,Default,,0,0,0,,先用CONS\nDialogue: 0,0:38:24.26,0:38:29.94,Default,,0,0,0,,我要为这个AGENDA构建一个新的SEGMENT\nDialogue: 0,0:38:33.60,0:38:34.81,Default,,0,0,0,,这里的连接必须要变\nDialogue: 0,0:38:35.40,0:38:36.30,Default,,0,0,0,,就像这样\nDialogue: 0,0:38:37.54,0:38:42.80,Default,,0,0,0,,我将要修改AGENDA的CDR部分的CDR部分\nDialogue: 0,0:38:44.88,0:38:49.45,Default,,0,0,0,,让它指向一个新的CONS单元\nDialogue: 0,0:38:50.11,0:38:54.65,Default,,0,0,0,,由一个新的SEGMENT和AGENDA的CDDDDR部分所构成的单元\nDialogue: 0,0:38:57.18,0:39:01.88,Default,,0,0,0,,我们有一个发生在20时刻的新的SEGMENT\nDialogue: 0,0:39:02.30,0:39:03.72,Default,,0,0,0,,它自己维护了一个队列\nDialogue: 0,0:39:04.84,0:39:06.29,Default,,0,0,0,,这个队列中只有一个元素\nDialogue: 0,0:39:10.73,0:39:12.52,Default,,0,0,0,,如果我想在后面添加点什么\nDialogue: 0,0:39:12.54,0:39:15.87,Default,,0,0,0,,我就需要替换这个东西的CDR部分\nDialogue: 0,0:39:16.99,0:39:19.21,Default,,0,0,0,,替换掉这个表的CDR部分\nDialogue: 0,0:39:20.59,0:39:23.31,Default,,0,0,0,,我们就对该数据结构进行修改\nDialogue: 0,0:39:24.04,0:39:25.79,Default,,0,0,0,,因此我需要新的基本运算\nDialogue: 0,0:39:27.21,0:39:28.62,Default,,0,0,0,,因为原有的基础运算达不到这一点\nDialogue: 0,0:39:29.44,0:39:33.88,Default,,0,0,0,,如果我想在5时刻做点什么事\nDialogue: 0,0:39:37.12,0:39:39.20,Default,,0,0,0,,我就得去修改这个东西\nDialogue: 0,0:39:40.81,0:39:42.12,Default,,0,0,0,,因为我得添加到这里\nDialogue: 0,0:39:43.29,0:39:46.22,Default,,0,0,0,,这也就是我预留了一个“头”序对的原因\nDialogue: 0,0:39:47.56,0:39:48.59,Default,,0,0,0,,它预留了空间\nDialogue: 0,0:39:49.40,0:39:52.11,Default,,0,0,0,,我需要有空间去做改变\nDialogue: 0,0:39:53.88,0:39:56.56,Default,,0,0,0,,需要有存储空间 去改变\nDialogue: 0,0:39:58.60,0:40:02.54,Default,,0,0,0,,从AGENDA中删除东西并不困难\nDialogue: 0,0:40:02.54,0:40:04.62,Default,,0,0,0,,移除第一个元素相当容易\nDialogue: 0,0:40:04.92,0:40:06.14,Default,,0,0,0,,这也是我需要考虑的唯一情况\nDialogue: 0,0:40:06.49,0:40:10.19,Default,,0,0,0,,我可以先找到第一个SEGMENT\nDialogue: 0,0:40:11.22,0:40:14.00,Default,,0,0,0,,先判断它的队列是否为空\nDialogue: 0,0:40:14.81,0:40:16.17,Default,,0,0,0,,如果队列不是空的\nDialogue: 0,0:40:16.32,0:40:18.62,Default,,0,0,0,,那么 我就会把元素从中删除\nDialogue: 0,0:40:19.21,0:40:19.74,Default,,0,0,0,,像这样\nDialogue: 0,0:40:20.10,0:40:21.92,Default,,0,0,0,,如果这时队列变为空的\nDialogue: 0,0:40:22.64,0:40:24.22,Default,,0,0,0,,就还要继续把SEGMENT删掉\nDialogue: 0,0:40:24.22,0:40:26.49,Default,,0,0,0,,然后 让这个单元指向这里\nDialogue: 0,0:40:28.22,0:40:31.08,Default,,0,0,0,,这个数据结构操作起来很复杂\nDialogue: 0,0:40:32.25,0:40:35.37,Default,,0,0,0,,它的具体实现也不是很有趣\nDialogue: 0,0:40:36.44,0:40:38.48,Default,,0,0,0,,现在我们来探讨一下队列\nDialogue: 0,0:40:38.92,0:40:39.76,Default,,0,0,0,,它们很相似\nDialogue: 0,0:40:41.16,0:40:43.52,Default,,0,0,0,,每一个AGENDA都有一个队列\nDialogue: 0,0:40:44.34,0:40:45.02,Default,,0,0,0,,队列是什么？\nDialogue: 0,0:40:49.47,0:40:51.85,Default,,0,0,0,,队列能够进行下述基本运算：\nDialogue: 0,0:40:52.78,0:41:02.17,Default,,0,0,0,,MAKE-QUEUE构建一个新队列\nDialogue: 0,0:41:07.77,0:41:17.10,Default,,0,0,0,,INSERT-QUEUE!向队列中插入新元素\nDialogue: 0,0:41:24.51,0:41:28.65,Default,,0,0,0,,DELETE-QUEUE!从队列中删除元素\nDialogue: 0,0:41:40.44,0:41:52.04,Default,,0,0,0,,FRONT-QUEUE查看队列中第一个元素\nDialogue: 0,0:41:53.13,0:41:55.14,Default,,0,0,0,,还需要检测队列是否为空\nDialogue: 0,0:42:07.11,0:42:08.70,Default,,0,0,0,,当你定义像这样的运算时\nDialogue: 0,0:42:09.02,0:42:10.44,Default,,0,0,0,,我希望你能够注意\nDialogue: 0,0:42:10.64,0:42:14.09,Default,,0,0,0,,按照我这样的习惯去为它们命名\nDialogue: 0,0:42:15.12,0:42:19.15,Default,,0,0,0,,“!”表示操作具有副作用 “?”代表定义谓词\nDialogue: 0,0:42:19.87,0:42:21.85,Default,,0,0,0,,就比如说 这里应该加上一个“!”\nDialogue: 0,0:42:24.65,0:42:26.96,Default,,0,0,0,,嗯 空检测谓词的“?”也不要遗漏了\nDialogue: 0,0:42:29.24,0:42:30.72,Default,,0,0,0,,那么 我要如何构建一个队列呢？\nDialogue: 0,0:42:31.72,0:42:34.11,Default,,0,0,0,,队列是一种 可以向其尾部添加东西\nDialogue: 0,0:42:35.12,0:42:36.83,Default,,0,0,0,,也可以从前面取出东西的结构\nDialogue: 0,0:42:37.84,0:42:40.51,Default,,0,0,0,,我可以从队列头删除元素 向队列尾添加元素\nDialogue: 0,0:42:41.23,0:42:43.24,Default,,0,0,0,,我可以用一种很简单的结构来实现\nDialogue: 0,0:42:43.88,0:42:45.72,Default,,0,0,0,,我们当然可以使用CONS来构造\nDialogue: 0,0:42:47.08,0:42:47.79,Default,,0,0,0,,这是一个队列\nDialogue: 0,0:42:49.91,0:42:52.36,Default,,0,0,0,,它有一个队列头\nDialogue: 0,0:42:53.58,0:42:54.92,Default,,0,0,0,,它包含两个部分\nDialogue: 0,0:42:55.28,0:42:56.25,Default,,0,0,0,,其中一个是头指针\nDialogue: 0,0:42:58.78,0:42:59.82,Default,,0,0,0,,另一个是尾指针\nDialogue: 0,0:43:03.12,0:43:06.33,Default,,0,0,0,,假设我有一个包含两个元素的队列\nDialogue: 0,0:43:09.13,0:43:12.09,Default,,0,0,0,,假设第一个元素是1\nDialogue: 0,0:43:12.46,0:43:16.53,Default,,0,0,0,,而第二个元素假定是2\nDialogue: 0,0:43:21.40,0:43:23.52,Default,,0,0,0,,我之所以要在这里设置两个指针\nDialogue: 0,0:43:24.09,0:43:25.61,Default,,0,0,0,,一个头指针和一个尾指针\nDialogue: 0,0:43:25.72,0:43:27.10,Default,,0,0,0,,这样 当向尾部添加元素的时候\nDialogue: 0,0:43:27.48,0:43:29.45,Default,,0,0,0,,就不用从最开始开始遍历\nDialogue: 0,0:43:31.85,0:43:34.80,Default,,0,0,0,,例如 我想要向队列添加入一个新元素\nDialogue: 0,0:43:35.26,0:43:41.02,Default,,0,0,0,,如果想添加一个稍后使用的元素\nDialogue: 0,0:43:41.08,0:43:42.40,Default,,0,0,0,,只需要先用CONS构建一个序对\nDialogue: 0,0:43:43.47,0:43:46.59,Default,,0,0,0,,假设它包含一个值 -- 3\nDialogue: 0,0:43:47.53,0:43:51.34,Default,,0,0,0,,再添加到队列里\nDialogue: 0,0:43:51.52,0:43:53.77,Default,,0,0,0,,这里就需要把这个元素CDR部分的指针\nDialogue: 0,0:43:56.94,0:43:58.76,Default,,0,0,0,,指向这个元素\nDialogue: 0,0:44:00.10,0:44:04.32,Default,,0,0,0,,同时也更新尾指针 让它指向新的地方\nDialogue: 0,0:44:09.12,0:44:12.68,Default,,0,0,0,,如果我想查看队列的第一个元素\nDialogue: 0,0:44:12.96,0:44:17.12,Default,,0,0,0,,我只需要通过头指针去寻找 即可轻松找到\nDialogue: 0,0:44:18.89,0:44:23.26,Default,,0,0,0,,如果我想调用DELETE-QUEUE删除元素\nDialogue: 0,0:44:24.14,0:44:26.35,Default,,0,0,0,,只需要把头指针向后移到就行\nDialogue: 0,0:44:27.71,0:44:29.31,Default,,0,0,0,,新的头指针指向这里\nDialogue: 0,0:44:31.70,0:44:33.13,Default,,0,0,0,,就是这么简单\nDialogue: 0,0:44:34.48,0:44:35.76,Default,,0,0,0,,为了实现这些操作\nDialogue: 0,0:44:37.24,0:44:40.83,Default,,0,0,0,,我们还需要一些新的基本运算\nDialogue: 0,0:44:41.48,0:44:42.56,Default,,0,0,0,,我先列出它们的名字\nDialogue: 0,0:44:42.99,0:44:46.28,Default,,0,0,0,,然后我们再来看 它们的原理和使用方法\nDialogue: 0,0:44:47.35,0:44:55.04,Default,,0,0,0,,SET-CAR!能够为序对的CAR部分\nDialogue: 0,0:44:55.88,0:44:59.36,Default,,0,0,0,,赋予一个新的值\nDialogue: 0,0:45:02.37,0:45:09.92,Default,,0,0,0,,SET-CDR!可以为序对的CDR部分赋新值\nDialogue: 0,0:45:13.02,0:45:14.78,Default,,0,0,0,,现在来看看它们到底做了什么\nDialogue: 0,0:45:16.03,0:45:20.51,Default,,0,0,0,,为了删除队列中的第一个元素 我需要修改这里的CAR部分\nDialogue: 0,0:45:20.96,0:45:22.52,Default,,0,0,0,,这是CAR部分 我需要修改它的值\nDialogue: 0,0:45:23.47,0:45:24.96,Default,,0,0,0,,我需要能够修改CDR部分\nDialogue: 0,0:45:25.28,0:45:27.08,Default,,0,0,0,,以便我能够移动尾指针\nDialogue: 0,0:45:27.21,0:45:28.76,Default,,0,0,0,,也使得我能够扩充队列\nDialogue: 0,0:45:30.16,0:45:31.60,Default,,0,0,0,,之前介绍的所有运算\nDialogue: 0,0:45:31.90,0:45:35.90,Default,,0,0,0,,上一块黑板上的所有东西 都是基于这些运算的\nDialogue: 0,0:45:38.17,0:45:40.14,Default,,0,0,0,,先讲到这里 大家休息一下\nDialogue: 0,0:45:41.24,0:45:52.67,Default,,0,0,0,,[音乐]\nDialogue: 0,0:45:52.67,0:45:57.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:18.64,0:46:22.80,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:46:22.80,0:46:27.15,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:27.16,0:46:30.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算对象\nDialogue: 0,0:46:38.81,0:46:43.53,Default,,0,0,0,,最初 我们说序对是通过CONS构造而来的\nDialogue: 0,0:46:44.57,0:46:46.80,Default,,0,0,0,,我们提到了几条公理\nDialogue: 0,0:46:48.09,0:46:50.76,Default,,0,0,0,,它们是怎样的呢？ 它们是形如 --\nDialogue: 0,0:46:52.28,0:47:03.64,Default,,0,0,0,,对于任意的X和Y (CAR (CONS X Y)) = X\nDialogue: 0,0:47:05.31,0:47:12.92,Default,,0,0,0,,以及 (CDR (CONS X Y)) = Y\nDialogue: 0,0:47:14.80,0:47:20.00,Default,,0,0,0,,但是 它们并没有陈述CONS单元 是否有像人一样的“身份”\nDialogue: 0,0:47:21.85,0:47:25.58,Default,,0,0,0,,实际上 它描述的是一种抽象\nDialogue: 0,0:47:25.74,0:47:27.95,Default,,0,0,0,,也就是CONS是由几个部分组成\nDialogue: 0,0:47:29.74,0:47:33.18,Default,,0,0,0,,如果两个CONS组成部分相同的  它俩则是同样的\nDialogue: 0,0:47:33.93,0:47:35.71,Default,,0,0,0,,至少从这些公理来看是这样的\nDialogue: 0,0:47:37.32,0:47:39.21,Default,,0,0,0,,但是引入了赋值以后\nDialogue: 0,0:47:39.84,0:47:42.32,Default,,0,0,0,,实际上 可变数据就是一种赋值\nDialogue: 0,0:47:42.88,0:47:44.43,Default,,0,0,0,,我们有SET-CAR!和SET-CDR!\nDialogue: 0,0:47:45.55,0:47:48.94,Default,,0,0,0,,引入这些运算后 这些公理就不完整了\nDialogue: 0,0:47:49.83,0:47:52.03,Default,,0,0,0,,但是这里写的也是对的\nDialogue: 0,0:47:53.25,0:47:54.94,Default,,0,0,0,,只不过描述的不再完整\nDialogue: 0,0:47:56.07,0:48:01.68,Default,,0,0,0,,因为如果我要修改一个特定的CONS的CAR部分\nDialogue: 0,0:48:03.02,0:48:04.03,Default,,0,0,0,,问题是\nDialogue: 0,0:48:04.24,0:48:08.64,Default,,0,0,0,,我会同时修改到相同CONS单元的CAR部分么？\nDialogue: 0,0:48:10.09,0:48:13.04,Default,,0,0,0,,假如我用CONS来构建有理数\nDialogue: 0,0:48:14.86,0:48:17.10,Default,,0,0,0,,比如说3/4\nDialogue: 0,0:48:17.34,0:48:20.25,Default,,0,0,0,,假设我有两个3/4\nDialogue: 0,0:48:21.57,0:48:22.75,Default,,0,0,0,,这两个一样吗？\nDialogue: 0,0:48:24.06,0:48:24.89,Default,,0,0,0,,或者又不一样？\nDialogue: 0,0:48:25.34,0:48:26.96,Default,,0,0,0,,当然 对于数字来说 这并不重要\nDialogue: 0,0:48:27.86,0:48:30.49,Default,,0,0,0,,修改一个数的分母并没有数学意义\nDialogue: 0,0:48:33.02,0:48:35.32,Default,,0,0,0,,我们只能够说创建一个数 具有不同的分母\nDialogue: 0,0:48:36.84,0:48:39.88,Default,,0,0,0,,而直接修改一个数的分母这种观念\nDialogue: 0,0:48:40.00,0:48:43.58,Default,,0,0,0,,在数学意义上是一种非常奇怪而不受支持的行为\nDialogue: 0,0:48:44.77,0:48:47.40,Default,,0,0,0,,然而 当这些CONS单元表示的是现实世界中的事物\nDialogue: 0,0:48:48.97,0:48:50.43,Default,,0,0,0,,那么修改它的CAR部分\nDialogue: 0,0:48:50.60,0:48:52.20,Default,,0,0,0,,就像除掉指甲壳的一块一样\nDialogue: 0,0:48:53.69,0:48:56.56,Default,,0,0,0,,所以 每一个CONS都有自己的“身份”\nDialogue: 0,0:48:57.77,0:48:59.92,Default,,0,0,0,,我来先说明“身份”是什么意思\nDialogue: 0,0:49:01.28,0:49:03.05,Default,,0,0,0,,来看些例子\nDialogue: 0,0:49:04.32,0:49:15.20,Default,,0,0,0,,假如(DEFINE A (CONS 1 2))\nDialogue: 0,0:49:18.32,0:49:19.76,Default,,0,0,0,,这是代表什么呢？ 首先\nDialogue: 0,0:49:20.67,0:49:25.20,Default,,0,0,0,,这是说我在某个环境中创建了符号A\nDialogue: 0,0:49:25.96,0:49:28.67,Default,,0,0,0,,而它的值是一个序对\nDialogue: 0,0:49:29.47,0:49:34.06,Default,,0,0,0,,这个序对由两个分别指向1和2的指针组成\nDialogue: 0,0:49:35.34,0:49:36.16,Default,,0,0,0,,就像这样\nDialogue: 0,0:49:38.12,0:49:39.60,Default,,0,0,0,,又假设\nDialogue: 0,0:49:40.22,0:49:47.58,Default,,0,0,0,,(DEFINE B (CONS A A))\nDialogue: 0,0:49:53.88,0:49:56.81,Default,,0,0,0,,虽然无所谓 不过我还是更喜欢用大写\nDialogue: 0,0:49:57.63,0:49:59.88,Default,,0,0,0,,(DEFINE B (CONS A A))\nDialogue: 0,0:50:03.97,0:50:06.03,Default,,0,0,0,,这里用了两次A\nDialogue: 0,0:50:07.84,0:50:10.57,Default,,0,0,0,,现在就要考虑序对的身份问题了\nDialogue: 0,0:50:11.30,0:50:12.64,Default,,0,0,0,,这两个A是同一个东西\nDialogue: 0,0:50:13.69,0:50:14.81,Default,,0,0,0,,这也就是说\nDialogue: 0,0:50:15.29,0:50:17.61,Default,,0,0,0,,我创建了另一个序对\nDialogue: 0,0:50:18.81,0:50:20.20,Default,,0,0,0,,我把它记作B\nDialogue: 0,0:50:22.38,0:50:27.60,Default,,0,0,0,,它由两个指向A的指针组成\nDialogue: 0,0:50:28.92,0:50:32.20,Default,,0,0,0,,对于这个对象来说 此时我有三个名字来指称它\nDialogue: 0,0:50:33.10,0:50:34.16,Default,,0,0,0,,A是一个\nDialogue: 0,0:50:34.88,0:50:36.46,Default,,0,0,0,,(CAR B)是一个\nDialogue: 0,0:50:37.23,0:50:38.86,Default,,0,0,0,,(CDR B)也是一个\nDialogue: 0,0:50:39.36,0:50:41.15,Default,,0,0,0,,都是这个序对的别名\nDialogue: 0,0:50:44.23,0:50:49.28,Default,,0,0,0,,假设现在我要执行\nDialogue: 0,0:50:53.77,0:51:08.38,Default,,0,0,0,,(SET-CAR! (CAR B) 3)\nDialogue: 0,0:51:12.75,0:51:17.45,Default,,0,0,0,,我先去找B的CAR部分 也就是它\nDialogue: 0,0:51:17.83,0:51:20.93,Default,,0,0,0,,再修改它的CAR部分 修改为3\nDialogue: 0,0:51:24.76,0:51:25.69,Default,,0,0,0,,这样我也就修改了A\nDialogue: 0,0:51:27.24,0:51:33.64,Default,,0,0,0,,如果我问 现在A的CAR部分是多少\nDialogue: 0,0:51:35.34,0:51:37.56,Default,,0,0,0,,结果是3\nDialogue: 0,0:51:38.68,0:51:43.39,Default,,0,0,0,,尽管在这里 A是由1和2构成的序对\nDialogue: 0,0:51:45.29,0:51:47.44,Default,,0,0,0,,我通过改变B而改变了A\nDialogue: 0,0:51:48.56,0:51:49.64,Default,,0,0,0,,它们之间存在共享\nDialogue: 0,0:51:52.25,0:51:53.47,Default,,0,0,0,,有时候我们需要这样的结构\nDialogue: 0,0:51:54.24,0:51:56.12,Default,,0,0,0,,当然 在类似于队列这类的数据结构中\nDialogue: 0,0:51:56.24,0:52:02.38,Default,,0,0,0,,我们正是这样来定义、组织数据结果来获得数据共享的\nDialogue: 0,0:52:04.35,0:52:05.66,Default,,0,0,0,,但是有一些非预期的共享\nDialogue: 0,0:52:07.76,0:52:09.72,Default,,0,0,0,,对象间的非预期交互\nDialogue: 0,0:52:10.78,0:52:14.08,Default,,0,0,0,,是大型程序中产生的BUG的主要来源\nDialogue: 0,0:52:15.44,0:52:21.66,Default,,0,0,0,,通过使对象具有“身份”、允许共享\nDialogue: 0,0:52:21.87,0:52:23.76,Default,,0,0,0,,给同一个对象取多个别名\nDialogue: 0,0:52:24.08,0:52:25.05,Default,,0,0,0,,我们获得了强大的能力\nDialogue: 0,0:52:25.13,0:52:28.46,Default,,0,0,0,,但是同时也为此引出的BUG和复杂度而付出代价\nDialogue: 0,0:52:32.19,0:52:36.24,Default,,0,0,0,,为了把这个讲透彻一点 我们再举一个例子\nDialogue: 0,0:52:37.10,0:52:39.87,Default,,0,0,0,,比如(CADR B)\nDialogue: 0,0:52:42.46,0:52:46.56,Default,,0,0,0,,看起来和(CAR B)没有一点关系\nDialogue: 0,0:52:46.88,0:52:49.02,Default,,0,0,0,,但是它的值是什么？\nDialogue: 0,0:52:49.35,0:52:53.56,Default,,0,0,0,,先取B的CDR部分 再取结果的CAR部分\nDialogue: 0,0:52:53.56,0:52:54.86,Default,,0,0,0,,哦 还是3\nDialogue: 0,0:52:56.48,0:53:00.43,Default,,0,0,0,,有了共享这样的机制 局部的含义也不是那么清楚了\nDialogue: 0,0:53:01.12,0:53:02.48,Default,,0,0,0,,所以我们要非常小心的操作\nDialogue: 0,0:53:06.64,0:53:12.64,Default,,0,0,0,,目前为止 我已经介绍了好几个赋值运算\nDialogue: 0,0:53:13.18,0:53:17.61,Default,,0,0,0,,比如SET!、SET-CAR!、SET-CDR!\nDialogue: 0,0:53:18.51,0:53:21.39,Default,,0,0,0,,或许我应该不用SET-CAR!、SET-CDR! 它们引入太多问题了\nDialogue: 0,0:53:22.82,0:53:23.66,Default,,0,0,0,,而事实则是\nDialogue: 0,0:53:24.12,0:53:26.11,Default,,0,0,0,,一旦把骆驼的鼻子牵进帐篷\nDialogue: 0,0:53:26.24,0:53:27.34,Default,,0,0,0,,它的身体可就自己跟进来了\nDialogue: 0,0:53:30.16,0:53:31.26,Default,,0,0,0,,只要有SET!\nDialogue: 0,0:53:31.61,0:53:35.85,Default,,0,0,0,,这些糟糕的东西都可能发生\nDialogue: 0,0:53:38.55,0:53:39.80,Default,,0,0,0,,我们来分析一下\nDialogue: 0,0:53:40.69,0:53:43.72,Default,,0,0,0,,前些日子 讲到复合数据的时候\nDialogue: 0,0:53:45.13,0:53:51.20,Default,,0,0,0,,哈罗德教授向你们展示了 用消息接收的方式来定义CONS\nDialogue: 0,0:53:52.48,0:53:56.06,Default,,0,0,0,,我将给你们展示一种更加糟糕的方式\nDialogue: 0,0:53:57.13,0:54:00.04,Default,,0,0,0,,凭“空”定义CONS\nDialogue: 0,0:54:02.56,0:54:03.02,Default,,0,0,0,,“什么”都不用\nDialogue: 0,0:54:04.44,0:54:08.12,Default,,0,0,0,,用传统的函数式的方法如何定义CONS呢？\nDialogue: 0,0:54:09.26,0:54:11.66,Default,,0,0,0,,纯粹只用LAMBDA表达式\nDialogue: 0,0:54:13.39,0:54:14.40,Default,,0,0,0,,把序对表示成过程\nDialogue: 0,0:54:17.39,0:54:19.66,Default,,0,0,0,,现在我要修改这个定义\nDialogue: 0,0:54:20.30,0:54:23.16,Default,,0,0,0,,使得只具有一种赋值\nDialogue: 0,0:54:24.28,0:54:27.93,Default,,0,0,0,,用SET!来代替SET-CAR!和SET-CDR!\nDialogue: 0,0:54:28.58,0:54:37.39,Default,,0,0,0,,如果我把CONS定义为\nDialogue: 0,0:54:38.91,0:54:42.56,Default,,0,0,0,,定义为一个过程 该过程接收参数M\nDialogue: 0,0:54:43.39,0:54:46.32,Default,,0,0,0,,该过程将M应用在X与Y上\nDialogue: 0,0:54:51.12,0:54:53.10,Default,,0,0,0,,这是阿隆佐·丘奇发明的方法\nDialogue: 0,0:54:53.77,0:54:55.72,Default,,0,0,0,,他是20世纪最伟大的程序员\nDialogue: 0,0:54:55.79,0:54:57.15,Default,,0,0,0,,尽管当时电脑还没有被发明\nDialogue: 0,0:54:57.87,0:54:59.13,Default,,0,0,0,,但他在20世纪30年代就提出了这个方法\nDialogue: 0,0:54:59.42,0:55:02.22,Default,,0,0,0,,他是一个逻辑学家 在普林斯顿大学做研究\nDialogue: 0,0:55:08.66,0:55:10.43,Default,,0,0,0,,定义(CAR X)为\nDialogue: 0,0:55:13.10,0:55:16.92,Default,,0,0,0,,把X应用在一个二元过程上\nDialogue: 0,0:55:17.15,0:55:20.60,Default,,0,0,0,,参数分别是A和D 而结果是选出A\nDialogue: 0,0:55:23.71,0:55:24.97,Default,,0,0,0,,而(CDR X)则是\nDialogue: 0,0:55:33.10,0:55:34.78,Default,,0,0,0,,这样的一个过程\nDialogue: 0,0:55:35.08,0:55:40.25,Default,,0,0,0,,把X应用在一个参数分别是A和D的过程上\nDialogue: 0,0:55:40.92,0:55:42.04,Default,,0,0,0,,该过程选择出D\nDialogue: 0,0:55:46.67,0:55:49.88,Default,,0,0,0,,可能你们还没意识到这些就是CAR、CDR和CONS\nDialogue: 0,0:55:50.51,0:55:53.61,Default,,0,0,0,,但我将要给你们演示它符合之前的公理\nDialogue: 0,0:55:54.11,0:55:54.81,Default,,0,0,0,,举一个例子\nDialogue: 0,0:55:55.61,0:55:57.56,Default,,0,0,0,,我们来看一下\nDialogue: 0,0:55:58.29,0:56:06.27,Default,,0,0,0,,考虑一下语句语句(CAR (CONS 35 47))\nDialogue: 0,0:56:09.93,0:56:10.96,Default,,0,0,0,,它的结果是多少呢？\nDialogue: 0,0:56:11.12,0:56:15.24,Default,,0,0,0,,它是通过把35和47代换进\nDialogue: 0,0:56:15.37,0:56:18.20,Default,,0,0,0,,语句体中的X和Y得到的\nDialogue: 0,0:56:19.71,0:56:20.69,Default,,0,0,0,,非常容易\nDialogue: 0,0:56:20.69,0:56:30.88,Default,,0,0,0,,就得到了语句(CAR (LAMBDA (M) (M 35 47)))\nDialogue: 0,0:56:35.53,0:56:39.36,Default,,0,0,0,,这个的结果是把这个对象\nDialogue: 0,0:56:39.44,0:56:41.85,Default,,0,0,0,,代换进这里的X而得到的\nDialogue: 0,0:56:42.83,0:56:47.66,Default,,0,0,0,,代换的结果是((LAMBDA (M --\nDialogue: 0,0:56:48.33,0:56:52.19,Default,,0,0,0,,用这个对象代换这里的X\nDialogue: 0,0:56:52.88,0:56:54.35,Default,,0,0,0,,这是表的头部\nDialogue: 0,0:56:54.88,0:57:00.32,Default,,0,0,0,,体的部分是(M 35 47)\nDialogue: 0,0:57:03.10,0:57:07.31,Default,,0,0,0,,把它应用于一个参数分别的A和D的过程上\nDialogue: 0,0:57:07.48,0:57:08.67,Default,,0,0,0,,后者返回参数A\nDialogue: 0,0:57:10.91,0:57:14.62,Default,,0,0,0,,然后我们用这个来代换这里的M\nDialogue: 0,0:57:15.96,0:57:21.71,Default,,0,0,0,,这个就相当于把(LAMBDA (A D) A)\nDialogue: 0,0:57:22.22,0:57:24.84,Default,,0,0,0,,应用在35和47上\nDialogue: 0,0:57:26.33,0:57:27.37,Default,,0,0,0,,结果就是35\nDialogue: 0,0:57:27.40,0:57:31.21,Default,,0,0,0,,它就是用35和47分别代换A、D 最后返回A\nDialogue: 0,0:57:35.60,0:57:37.24,Default,,0,0,0,,所以我根本不需要任何数据\nDialogue: 0,0:57:37.88,0:57:38.75,Default,,0,0,0,,甚至连数字都不需要\nDialogue: 0,0:57:40.92,0:57:42.64,Default,,0,0,0,,这就是 阿隆佐·邱奇的技巧\nDialogue: 0,0:57:52.42,0:57:56.17,Default,,0,0,0,,现在呢我们来对这个定义做点修改\nDialogue: 0,0:57:56.76,0:57:58.49,Default,,0,0,0,,作为逻辑学家 他可能会不太开心\nDialogue: 0,0:57:59.20,0:58:01.96,Default,,0,0,0,,但作为程序员 -- 请看投影仪\nDialogue: 0,0:58:03.26,0:58:04.16,Default,,0,0,0,,我们来看看\nDialogue: 0,0:58:05.39,0:58:07.58,Default,,0,0,0,,我修改了CONS的定义\nDialogue: 0,0:58:09.57,0:58:12.35,Default,,0,0,0,,和丘奇的定义很相似 但是不完全相同\nDialogue: 0,0:58:14.41,0:58:15.50,Default,,0,0,0,,具体到底是什么？\nDialogue: 0,0:58:16.07,0:58:18.72,Default,,0,0,0,,CONS有两个参数：X和Y\nDialogue: 0,0:58:19.50,0:58:22.51,Default,,0,0,0,,但它返回一个参数为M的过程\nDialogue: 0,0:58:23.39,0:58:25.64,Default,,0,0,0,,跟之前一样M会应用于X和Y上\nDialogue: 0,0:58:26.19,0:58:29.29,Default,,0,0,0,,但它额外还有两个“许可”\nDialogue: 0,0:58:30.17,0:58:32.01,Default,,0,0,0,,其中一个是把X赋值为N\nDialogue: 0,0:58:32.60,0:58:34.40,Default,,0,0,0,,另一个则是把Y赋值为N\nDialogue: 0,0:58:34.44,0:58:35.68,Default,,0,0,0,,只要我提供了相应的N\nDialogue: 0,0:58:40.94,0:58:44.72,Default,,0,0,0,,所以出了邱奇原本的定义之外\nDialogue: 0,0:58:45.72,0:58:51.66,Default,,0,0,0,,最大的不同在于CONS的返回值\nDialogue: 0,0:58:52.12,0:58:53.82,Default,,0,0,0,,不单会把它的参数应用于\nDialogue: 0,0:58:54.91,0:58:59.44,Default,,0,0,0,,用于构成序对的X和Y之上\nDialogue: 0,0:58:59.69,0:59:03.58,Default,,0,0,0,,它还有用于为X和Y赋值的两个“许可”\nDialogue: 0,0:59:06.54,0:59:08.08,Default,,0,0,0,,当然 就如之前一样\nDialogue: 0,0:59:08.83,0:59:10.51,Default,,0,0,0,,CAR看起来也很相似\nDialogue: 0,0:59:11.69,0:59:14.36,Default,,0,0,0,,就像邱奇定义的那样\nDialogue: 0,0:59:14.54,0:59:16.00,Default,,0,0,0,,(CAR X)只不过是把X应用在\nDialogue: 0,0:59:16.86,0:59:19.00,Default,,0,0,0,,过程上 -- 本例中是四个参数\nDialogue: 0,0:59:19.29,0:59:21.04,Default,,0,0,0,,然后从中选出第一个\nDialogue: 0,0:59:22.54,0:59:24.16,Default,,0,0,0,,这就和之前一样\nDialogue: 0,0:59:25.42,0:59:26.96,Default,,0,0,0,,结果将会返回X\nDialogue: 0,0:59:29.04,0:59:35.40,Default,,0,0,0,,X的值被包含在求值这个LAMBDA表达式所产生的过程中\nDialogue: 0,0:59:35.45,0:59:37.84,Default,,0,0,0,,X和Y的值也是在这个环境中定义的\nDialogue: 0,0:59:41.94,0:59:43.15,Default,,0,0,0,,这是我们对CONS的定义\nDialogue: 0,0:59:45.64,0:59:47.53,Default,,0,0,0,,那么 激动人心的地方来了\nDialogue: 0,0:59:47.73,0:59:48.96,Default,,0,0,0,,当然CDR的定义也类似\nDialogue: 0,0:59:49.39,0:59:50.35,Default,,0,0,0,,激动人心的地方\nDialogue: 0,0:59:51.23,0:59:52.52,Default,,0,0,0,,SET-CAR!和SET-CDR!的实现\nDialogue: 0,0:59:53.45,0:59:55.52,Default,,0,0,0,,说实话 它们也不是特别复杂\nDialogue: 0,0:59:55.80,1:00:00.64,Default,,0,0,0,,语句(SET-CAR! X Y)\nDialogue: 0,1:00:01.63,1:00:03.85,Default,,0,0,0,,无非就是把序对X应用于\nDialogue: 0,1:00:04.11,1:00:06.76,Default,,0,0,0,,注意X是一个一元过程\nDialogue: 0,1:00:07.69,1:00:09.80,Default,,0,0,0,,该过程的体是将参数应用在四个对象上\nDialogue: 0,1:00:11.24,1:00:15.85,Default,,0,0,0,,我们把X应用于一个四元过程上\nDialogue: 0,1:00:16.00,1:00:18.08,Default,,0,0,0,,X的值、Y的值\nDialogue: 0,1:00:18.32,1:00:20.54,Default,,0,0,0,,修改X的许可、修改Y的许可\nDialogue: 0,1:00:21.32,1:00:26.09,Default,,0,0,0,,语句的体则是用相应的许可 将X设置为新的值\nDialogue: 0,1:00:31.65,1:00:33.54,Default,,0,0,0,,当然SET-CDR!和它类似\nDialogue: 0,1:00:36.25,1:00:39.44,Default,,0,0,0,,你也看到了 我这里并没有引入新的基本运算\nDialogue: 0,1:00:40.11,1:00:44.36,Default,,0,0,0,,具体要不要这样来实现是一个工程性问题\nDialogue: 0,1:00:45.34,1:00:47.39,Default,,0,0,0,,当然出于工程上的考量\nDialogue: 0,1:00:48.09,1:00:49.63,Default,,0,0,0,,我不会这样来实现\nDialogue: 0,1:00:51.68,1:00:53.40,Default,,0,0,0,,但是从原理上来说\nDialogue: 0,1:00:54.28,1:00:56.43,Default,,0,0,0,,一旦引入了赋值运算\nDialogue: 0,1:00:56.96,1:00:58.76,Default,,0,0,0,,我就可以进行各种各样的赋值运算了\nDialogue: 0,1:01:05.42,1:01:06.67,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:01:09.20,1:01:10.89,Default,,0,0,0,,请讲\nDialogue: 0,1:01:12.04,1:01:15.64,Default,,0,0,0,,我可以跟的上你的思路 直到 --\nDialogue: 0,1:01:15.64,1:01:17.61,Default,,0,0,0,,在许可那里\nDialogue: 0,1:01:18.14,1:01:21.64,Default,,0,0,0,,我们把CONS定义为一个参数为N的过程\nDialogue: 0,1:01:21.80,1:01:24.21,Default,,0,0,0,,我不知道这个参数是什么时候传进来的\nDialogue: 0,1:01:24.21,1:01:25.69,Default,,0,0,0,,教授：哦 抱歉 我给你演示一下\nDialogue: 0,1:01:26.34,1:01:27.05,Default,,0,0,0,,我们来推演一下\nDialogue: 0,1:01:27.36,1:01:29.07,Default,,0,0,0,,虽然在黑板上推演更清晰\nDialogue: 0,1:01:29.18,1:01:30.17,Default,,0,0,0,,但这并不难懂\nDialogue: 0,1:01:30.17,1:01:31.47,Default,,0,0,0,,我就将就用投影仪了\nDialogue: 0,1:01:32.45,1:01:35.79,Default,,0,0,0,,调用(SET-CDR! X Y)会发生什么呢？\nDialogue: 0,1:01:37.79,1:01:39.66,Default,,0,0,0,,就在这里(SET-CDR! X Y)\nDialogue: 0,1:01:40.36,1:01:41.92,Default,,0,0,0,,X可能是一个序对\nDialogue: 0,1:01:43.31,1:01:45.24,Default,,0,0,0,,或者说对一个CONS表达式求值得到的结果\nDialogue: 0,1:01:45.88,1:01:46.35,Default,,0,0,0,,能跟上吧？\nDialogue: 0,1:01:46.89,1:01:49.96,Default,,0,0,0,,也就是说 X是由这里的代码构造出来的\nDialogue: 0,1:01:52.57,1:01:56.49,Default,,0,0,0,,这里的X是求值这个LAMBDA表达式得到的\nDialogue: 0,1:01:58.11,1:01:58.49,Default,,0,0,0,,对吧\nDialogue: 0,1:01:59.38,1:02:01.63,Default,,0,0,0,,因此当我对这个LAMBDA表达式求值时\nDialogue: 0,1:02:04.01,1:02:08.76,Default,,0,0,0,,我是在定义CONS时的一个环境里求值的\nDialogue: 0,1:02:11.75,1:02:15.18,Default,,0,0,0,,这也就是说 作为LAMBDA表达式中的自由变量\nDialogue: 0,1:02:16.25,1:02:18.68,Default,,0,0,0,,X和Y都存储一个框架中\nDialogue: 0,1:02:18.72,1:02:22.44,Default,,0,0,0,,也就是这整个LAMBDA表达式的父框架\nDialogue: 0,1:02:23.23,1:02:25.82,Default,,0,0,0,,因此在这个LAMBDA语句中\nDialogue: 0,1:02:26.65,1:02:28.51,Default,,0,0,0,,X和Y都有存储空间\nDialogue: 0,1:02:29.25,1:02:30.83,Default,,0,0,0,,也可以对它们赋值\nDialogue: 0,1:02:31.91,1:02:36.08,Default,,0,0,0,,这里赋值为N是通过参数来传递的\nDialogue: 0,1:02:37.26,1:02:39.31,Default,,0,0,0,,“许可”就是一个过程\nDialogue: 0,1:02:41.40,1:02:43.18,Default,,0,0,0,,它将作为M的一个参数\nDialogue: 0,1:02:43.29,1:02:46.51,Default,,0,0,0,,它实际上是CONS生成的对象的一部分\nDialogue: 0,1:02:47.94,1:02:50.91,Default,,0,0,0,,我们再来看看SET-CDR!\nDialogue: 0,1:02:52.11,1:02:55.42,Default,,0,0,0,,SET-CDR!的第一个参数X是一个序对\nDialogue: 0,1:02:56.12,1:02:57.48,Default,,0,0,0,,被传递了一个参数\nDialogue: 0,1:02:59.77,1:03:02.22,Default,,0,0,0,,这个是一个四元过程\nDialogue: 0,1:03:02.32,1:03:04.65,Default,,0,0,0,,这是因为 它要作为这里的M\nDialogue: 0,1:03:04.99,1:03:06.56,Default,,0,0,0,,要应用在四个对象上\nDialogue: 0,1:03:07.92,1:03:13.34,Default,,0,0,0,,这边的这个SD 就对应于这个过程\nDialogue: 0,1:03:15.47,1:03:19.93,Default,,0,0,0,,当我执行SD 把它应用于Y\nDialogue: 0,1:03:22.91,1:03:24.04,Default,,0,0,0,,这个Y是这里传过来的\nDialogue: 0,1:03:25.37,1:03:26.92,Default,,0,0,0,,学生：那--\nDialogue: 0,1:03:27.00,1:03:32.19,Default,,0,0,0,,教授：所以说 这里的N就对应于这里的Y\nDialogue: 0,1:03:34.04,1:03:34.52,Default,,0,0,0,,明白了吧\nDialogue: 0,1:03:34.81,1:03:35.75,Default,,0,0,0,,了解了\nDialogue: 0,1:03:35.75,1:03:37.29,Default,,0,0,0,,当你执行SET-CDR!的时候\nDialogue: 0,1:03:39.07,1:03:41.97,Default,,0,0,0,,X是CDR部分要赋值的新值\nDialogue: 0,1:03:41.97,1:03:44.03,Default,,0,0,0,,教授：这里的X\nDialogue: 0,1:03:44.96,1:03:46.20,Default,,0,0,0,,哦 指错了\nDialogue: 0,1:03:46.20,1:03:48.33,Default,,0,0,0,,这里的X是指 -- SET-CDR!有两个参数\nDialogue: 0,1:03:48.91,1:03:50.36,Default,,0,0,0,,一个是被修改的序对\nDialogue: 0,1:03:51.34,1:03:53.93,Default,,0,0,0,,还有就是新值\nDialogue: 0,1:03:56.15,1:03:58.32,Default,,0,0,0,,你可以代换回去看看 就很清楚了\nDialogue: 0,1:04:02.17,1:04:03.16,Default,,0,0,0,,还有什么问题吗？\nDialogue: 0,1:04:07.88,1:04:08.64,Default,,0,0,0,,好的\nDialogue: 0,1:04:08.64,1:04:09.52,Default,,0,0,0,,这节课就到这里\nDialogue: 0,1:04:10.44,1:04:28.73,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:04:10.44,1:04:28.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP"
  },
  {
    "path": "Ass/lec5b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 974\nVideo Position: 116001\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.01,0:00:02.46,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N张大伟\\N（DreamAndDead）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:10.10,0:00:14.60,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算对象\nDialogue: 0,0:00:21.17,0:00:24.12,Default,,0,0,0,,现在我们已经学习了\nDialogue: 0,0:00:24.43,0:00:27.40,Default,,0,0,0,,如何创建局部状态和如何建模对象\nDialogue: 0,0:00:28.33,0:00:32.67,Default,,0,0,0,,我想我们应该找点复杂的东西\nDialogue: 0,0:00:34.03,0:00:36.36,Default,,0,0,0,,来实践一下学过的这些知识\nDialogue: 0,0:00:40.43,0:00:43.48,Default,,0,0,0,,我可以这么说 假设我们处在现实世界中\nDialogue: 0,0:00:44.11,0:00:46.25,Default,,0,0,0,,我们把这个世界看作是\nDialogue: 0,0:00:46.99,0:00:51.08,Default,,0,0,0,,由许多的事物构成的\nDialogue: 0,0:00:52.06,0:00:55.98,Default,,0,0,0,,每个事物都有其独立的局部状态\nDialogue: 0,0:00:57.24,0:00:59.87,Default,,0,0,0,,正是这些独立的状态使其成为事物\nDialogue: 0,0:01:01.28,0:01:04.27,Default,,0,0,0,,因此我们说 在这个世界的模型中\nDialogue: 0,0:01:04.28,0:01:09.90,Default,,0,0,0,,我们在大脑中和计算机中对那个世界建模\nDialogue: 0,0:01:10.94,0:01:12.54,Default,,0,0,0,,我想要建立一种对应关系\nDialogue: 0,0:01:12.78,0:01:15.21,Default,,0,0,0,,把现实世界和计算机中的对象联系起来\nDialogue: 0,0:01:15.87,0:01:17.74,Default,,0,0,0,,把现实世界中对象间的关系\nDialogue: 0,0:01:17.96,0:01:21.72,Default,,0,0,0,,与计算机中的模型对象间的关系 对应起来\nDialogue: 0,0:01:23.18,0:01:25.52,Default,,0,0,0,,把现实世界中关联对象的函数\nDialogue: 0,0:01:25.93,0:01:28.11,Default,,0,0,0,,与计算机中的函数 对应起来\nDialogue: 0,0:01:30.84,0:01:33.82,Default,,0,0,0,,这让我们获得了模块性\nDialogue: 0,0:01:34.74,0:01:36.75,Default,,0,0,0,,如果我们认为现实世界是像那样的\nDialogue: 0,0:01:37.36,0:01:38.72,Default,,0,0,0,,也就是由许多小的事物构成的\nDialogue: 0,0:01:39.20,0:01:41.47,Default,,0,0,0,,当然 我们可以把世界安排成那样\nDialogue: 0,0:01:42.03,0:01:43.95,Default,,0,0,0,,我们只能对像那样的事物建模\nDialogue: 0,0:01:45.45,0:01:49.02,Default,,0,0,0,,这样 我们的程序就可以从现实世界中继承模块化\nDialogue: 0,0:01:50.45,0:01:53.58,Default,,0,0,0,,这就是发明面向对象编程的初衷\nDialogue: 0,0:01:55.42,0:01:58.19,Default,,0,0,0,,我所见过的最完美的对象（系统）\nDialogue: 0,0:01:58.89,0:02:04.17,Default,,0,0,0,,电气系统 就是非常非常完美的对象系统\nDialogue: 0,0:02:06.40,0:02:12.99,Default,,0,0,0,,电气系统真的是物理学家构造的非常非常好的一种对象\nDialogue: 0,0:02:14.22,0:02:16.76,Default,,0,0,0,,这里 我有一些机器零件\nDialogue: 0,0:02:17.12,0:02:18.28,Default,,0,0,0,,就是这些零件\nDialogue: 0,0:02:20.04,0:02:22.88,Default,,0,0,0,,有一个电线连接起了\nDialogue: 0,0:02:23.66,0:02:26.40,Default,,0,0,0,,零件的两个部分\nDialogue: 0,0:02:27.56,0:02:30.86,Default,,0,0,0,,电气世界中 有一个非常棒的特性\nDialogue: 0,0:02:31.64,0:02:33.12,Default,,0,0,0,,就是我可以说这是一个对象\nDialogue: 0,0:02:34.01,0:02:34.97,Default,,0,0,0,,这又是一个对象\nDialogue: 0,0:02:35.71,0:02:37.53,Default,,0,0,0,,它们间的关联一目了然\nDialogue: 0,0:02:38.24,0:02:43.32,Default,,0,0,0,,而且 如果我没有用电线连接 它们便没有关联\nDialogue: 0,0:02:44.74,0:02:46.12,Default,,0,0,0,,比如我有一个灯泡\nDialogue: 0,0:02:46.52,0:02:50.32,Default,,0,0,0,,一个灯泡和一个已经接在插座上的电源\nDialogue: 0,0:02:51.63,0:02:53.53,Default,,0,0,0,,关联非常明了\nDialogue: 0,0:02:53.62,0:02:55.42,Default,,0,0,0,,这就是已知所有的连接方式了\nDialogue: 0,0:02:56.22,0:03:02.33,Default,,0,0,0,,就算我把连接电灯和电源的电线打个结\nDialogue: 0,0:03:02.68,0:03:03.64,Default,,0,0,0,,灯仍然是亮的\nDialogue: 0,0:03:04.04,0:03:04.76,Default,,0,0,0,,没什么影响\nDialogue: 0,0:03:07.44,0:03:12.40,Default,,0,0,0,,物理学上这样安排 可以使连接变成抽象的\nDialogue: 0,0:03:13.08,0:03:15.27,Default,,0,0,0,,至少在低频状态下是可以的\nDialogue: 0,0:03:17.84,0:03:20.88,Default,,0,0,0,,而且这就是全部的关联方式了\nDialogue: 0,0:03:22.35,0:03:23.87,Default,,0,0,0,,当然 我们来进一步\nDialogue: 0,0:03:23.90,0:03:27.31,Default,,0,0,0,,讨论一种在电气系统中最为广泛的抽象\nDialogue: 0,0:03:27.85,0:03:29.42,Default,,0,0,0,,数字电路\nDialogue: 0,0:03:31.69,0:03:33.66,Default,,0,0,0,,这里有一些对象\nDialogue: 0,0:03:34.64,0:03:40.12,Default,,0,0,0,,例如 在数字电路里中 我们有非门\nDialogue: 0,0:03:41.39,0:03:42.78,Default,,0,0,0,,有与门\nDialogue: 0,0:03:43.99,0:03:45.40,Default,,0,0,0,,还有或门\nDialogue: 0,0:03:47.21,0:03:50.12,Default,,0,0,0,,我们用一种特殊的“电线” 把它们连接起来\nDialogue: 0,0:03:52.00,0:03:54.94,Default,,0,0,0,,这些“电线”代表抽象信号\nDialogue: 0,0:03:55.61,0:03:57.18,Default,,0,0,0,,我们不关心具体的物理因素\nDialogue: 0,0:03:57.21,0:03:59.72,Default,,0,0,0,,像电压、电流或者组合因素等\nDialogue: 0,0:04:00.01,0:04:03.44,Default,,0,0,0,,又或者是水压 等等\nDialogue: 0,0:04:05.20,0:04:07.32,Default,,0,0,0,,这些抽象变量代表某类信号\nDialogue: 0,0:04:09.42,0:04:12.89,Default,,0,0,0,,我们用电路连接元件 构建系统\nDialogue: 0,0:04:14.07,0:04:16.22,Default,,0,0,0,,现在 我要向你们介绍一门新的语言\nDialogue: 0,0:04:17.63,0:04:20.17,Default,,0,0,0,,我们要构建一门内嵌于Lisp中的语言\nDialogue: 0,0:04:22.14,0:04:25.08,Default,,0,0,0,,这是一种内部DSL 是类似于之前讲过的图形语言那种\nDialogue: 0,0:04:26.16,0:04:27.32,Default,,0,0,0,,而不是昨天那种\nDialogue: 0,0:04:27.88,0:04:31.61,Default,,0,0,0,,那种模式匹配语言 -- 那是外部DSL\nDialogue: 0,0:04:32.80,0:04:36.30,Default,,0,0,0,,模式匹配语言是由Lisp程序所解释的\nDialogue: 0,0:04:38.16,0:04:40.52,Default,,0,0,0,,而之前那种图形语言\nDialogue: 0,0:04:40.56,0:04:44.27,Default,,0,0,0,,是在Lisp中构造我们想要的过程 来封装图形结构\nDialogue: 0,0:04:45.48,0:04:46.75,Default,,0,0,0,,举例来说\nDialogue: 0,0:04:47.72,0:04:50.64,Default,,0,0,0,,首先我要有一些基本对象\nDialogue: 0,0:04:51.05,0:04:52.12,Default,,0,0,0,,比如这个和这个\nDialogue: 0,0:04:53.50,0:04:55.18,Default,,0,0,0,,然后用电线去组合它们\nDialogue: 0,0:04:55.98,0:04:59.37,Default,,0,0,0,,我用(MAKE-WIRE)来构造一个电线\nDialogue: 0,0:04:59.87,0:05:01.24,Default,,0,0,0,,A就代表了一根电线\nDialogue: 0,0:05:01.74,0:05:02.69,Default,,0,0,0,,B也是\nDialogue: 0,0:05:02.69,0:05:03.46,Default,,0,0,0,,C也是\nDialogue: 0,0:05:03.46,0:05:04.23,Default,,0,0,0,,D也是\nDialogue: 0,0:05:04.23,0:05:04.83,Default,,0,0,0,,还有E\nDialogue: 0,0:05:04.83,0:05:05.64,Default,,0,0,0,,S也是\nDialogue: 0,0:05:06.88,0:05:12.75,Default,,0,0,0,,而或门有两个输入 分别是A和B\nDialogue: 0,0:05:13.16,0:05:14.75,Default,,0,0,0,,它的输出是D\nDialogue: 0,0:05:15.07,0:05:16.12,Default,,0,0,0,,我们用这样的记号来表示\nDialogue: 0,0:05:18.14,0:05:22.14,Default,,0,0,0,,与门 输入是A和B 输出是C\nDialogue: 0,0:05:22.22,0:05:23.24,Default,,0,0,0,,我们这样表示\nDialogue: 0,0:05:24.82,0:05:28.46,Default,,0,0,0,,通过一系列像这样的声明\nDialogue: 0,0:05:29.29,0:05:31.64,Default,,0,0,0,,我可以组合出任意的电路\nDialogue: 0,0:05:32.75,0:05:34.64,Default,,0,0,0,,我已经告诉了你们创建数字电路\nDialogue: 0,0:05:35.31,0:05:38.51,Default,,0,0,0,,的基本元素和组合方法了\nDialogue: 0,0:05:40.09,0:05:43.04,Default,,0,0,0,,然后就该说抽象的方法了\nDialogue: 0,0:05:43.69,0:05:52.24,Default,,0,0,0,,举例来说 这是一个半加器\nDialogue: 0,0:05:52.67,0:05:55.55,Default,,0,0,0,,如果你学过电路设计肯定知道这个东西\nDialogue: 0,0:05:56.93,0:06:00.44,Default,,0,0,0,,输入两个数A和B\nDialogue: 0,0:06:00.62,0:06:02.12,Default,,0,0,0,,输出两者之和以及进位\nDialogue: 0,0:06:04.35,0:06:06.80,Default,,0,0,0,,事实上 完全可以用我刚刚说的来组合电路\nDialogue: 0,0:06:07.45,0:06:10.99,Default,,0,0,0,,盒子外面 半加器盒子的外面有一些接口\nDialogue: 0,0:06:11.13,0:06:14.11,Default,,0,0,0,,这些盒子的边界 我们总是抽象成盒子\nDialogue: 0,0:06:14.79,0:06:19.70,Default,,0,0,0,,从盒子里引出A、B、S、C四根线\nDialogue: 0,0:06:19.70,0:06:21.79,Default,,0,0,0,,这些是已经声明了的变量\nDialogue: 0,0:06:23.39,0:06:26.25,Default,,0,0,0,,由LAMBDA表达式声明的几个变量\nDialogue: 0,0:06:26.28,0:06:28.01,Default,,0,0,0,,定义了这个半加器\nDialogue: 0,0:06:31.40,0:06:35.96,Default,,0,0,0,,在盒子的内部 我构造了电线D和E\nDialogue: 0,0:06:36.00,0:06:37.44,Default,,0,0,0,,这是为了连接内部结构\nDialogue: 0,0:06:37.74,0:06:40.40,Default,,0,0,0,,这条是E 这条是D\nDialogue: 0,0:06:41.32,0:06:43.50,Default,,0,0,0,,内部连接的线路并没有引出盒子之外\nDialogue: 0,0:06:45.05,0:06:46.83,Default,,0,0,0,,就像电路图那样连起来\nDialogue: 0,0:06:48.79,0:06:50.89,Default,,0,0,0,,大家可以看得出来\nDialogue: 0,0:06:51.05,0:06:53.02,Default,,0,0,0,,这个语言非常有层次性\nDialogue: 0,0:06:53.85,0:06:55.71,Default,,0,0,0,,如果一门语言没有层次性\nDialogue: 0,0:06:55.95,0:06:59.96,Default,,0,0,0,,如果你不能把一个复合对象当成基本对象来使用\nDialogue: 0,0:07:00.38,0:07:01.53,Default,,0,0,0,,这门语言肯定是有问题的\nDialogue: 0,0:07:02.59,0:07:04.22,Default,,0,0,0,,至少我是这么认为的\nDialogue: 0,0:07:06.41,0:07:09.58,Default,,0,0,0,,之前 我们都是在研究数学函数\nDialogue: 0,0:07:09.60,0:07:11.12,Default,,0,0,0,,或者是计算数学函数的东西\nDialogue: 0,0:07:11.15,0:07:12.65,Default,,0,0,0,,这些都是我们之前研究的东西\nDialogue: 0,0:07:13.85,0:07:16.65,Default,,0,0,0,,而我们现在\nDialogue: 0,0:07:16.67,0:07:17.63,Default,,0,0,0,,不这么做了\nDialogue: 0,0:07:17.85,0:07:20.88,Default,,0,0,0,,我们从一些电气对象开始\nDialogue: 0,0:07:21.04,0:07:22.64,Default,,0,0,0,,构建更多的对象\nDialogue: 0,0:07:23.35,0:07:28.83,Default,,0,0,0,,我们用Lisp里的LAMBDA将其粘合起来\nDialogue: 0,0:07:30.38,0:07:32.93,Default,,0,0,0,,“LAMBDA: 终极之粘合剂”\nDialogue: 0,0:07:33.32,0:07:36.35,Default,,0,0,0,,当然 半加器可以用于\nDialogue: 0,0:07:37.64,0:07:41.04,Default,,0,0,0,,构造一种更复杂的抽象结构 -- 全加器\nDialogue: 0,0:07:41.60,0:07:45.05,Default,,0,0,0,,如这里所示 全加器由两个半加器构成\nDialogue: 0,0:07:45.47,0:07:47.87,Default,,0,0,0,,用一些额外的电线连接起来\nDialogue: 0,0:07:48.08,0:07:51.29,Default,,0,0,0,,就像这里所示的S、C1、C2以及一个或门\nDialogue: 0,0:07:52.19,0:07:53.60,Default,,0,0,0,,而对于一个全加器\nDialogue: 0,0:07:53.87,0:08:00.78,Default,,0,0,0,,它的输入有：两个待加的数 一个进位值\nDialogue: 0,0:08:01.36,0:08:04.17,Default,,0,0,0,,输出是：两数之和以及进位\nDialogue: 0,0:08:05.90,0:08:10.70,Default,,0,0,0,,构建好全加器以后 还可以把它们链起来组成更大的加法器\nDialogue: 0,0:08:12.99,0:08:14.83,Default,,0,0,0,,现在我们有了一门完整的语言\nDialogue: 0,0:08:16.06,0:08:21.76,Default,,0,0,0,,它有基本元素、组合方法以及抽象方法\nDialogue: 0,0:08:22.27,0:08:23.36,Default,,0,0,0,,现在 我们怎样实现这门语言？\nDialogue: 0,0:08:25.00,0:08:26.84,Default,,0,0,0,,其实并不难\nDialogue: 0,0:08:27.07,0:08:27.96,Default,,0,0,0,,首先来看基本元素\nDialogue: 0,0:08:28.12,0:08:30.11,Default,,0,0,0,,这是唯一的问题\nDialogue: 0,0:08:31.16,0:08:32.56,Default,,0,0,0,,不需要再做其它事情了\nDialogue: 0,0:08:33.74,0:08:38.00,Default,,0,0,0,,因为我们直接借用了Lisp中的组合方法以及抽象方法\nDialogue: 0,0:08:39.96,0:08:41.88,Default,,0,0,0,,我们的语言 继承自Lisp并内嵌于其中\nDialogue: 0,0:08:43.77,0:08:45.44,Default,,0,0,0,,好 我们先来看一个基本元素\nDialogue: 0,0:08:45.86,0:08:47.40,Default,,0,0,0,,就拿非门来说吧\nDialogue: 0,0:08:51.54,0:08:54.67,Default,,0,0,0,,非门有两个引脚 分别是输入和输出\nDialogue: 0,0:08:57.31,0:09:02.62,Default,,0,0,0,,它要对输入信号做出响应\nDialogue: 0,0:09:04.30,0:09:07.00,Default,,0,0,0,,它需要对输入电线说 --\nDialogue: 0,0:09:07.64,0:09:10.14,Default,,0,0,0,,我们现在把它们视作对象\nDialogue: 0,0:09:10.44,0:09:12.41,Default,,0,0,0,,其具体细节我们稍后讨论\nDialogue: 0,0:09:13.23,0:09:14.84,Default,,0,0,0,,它对其输入电线的说\nDialogue: 0,0:09:15.82,0:09:18.48,Default,,0,0,0,,“当你的值变发生改变时 告诉我一声”\nDialogue: 0,0:09:20.12,0:09:22.11,Default,,0,0,0,,所以非门这个对象\nDialogue: 0,0:09:22.41,0:09:24.38,Default,,0,0,0,,会对输入电线这个对象说 --\nDialogue: 0,0:09:25.13,0:09:26.40,Default,,0,0,0,,“Hi 我是George”\nDialogue: 0,0:09:26.87,0:09:31.02,Default,,0,0,0,,“我的工作就是 对你的变化做出响应”\nDialogue: 0,0:09:31.72,0:09:34.19,Default,,0,0,0,,“所以当你变化的时候 告诉我一声”\nDialogue: 0,0:09:34.73,0:09:35.72,Default,,0,0,0,,“这样我才能进一步的处理”\nDialogue: 0,0:09:36.88,0:09:40.30,Default,,0,0,0,,这是通过在这里 在输入电线上\nDialogue: 0,0:09:41.40,0:09:44.64,Default,,0,0,0,,添加一个叫做INVERT-IN的动作来实现的\nDialogue: 0,0:09:45.07,0:09:46.94,Default,,0,0,0,,INVERT-IN在这里定义\nDialogue: 0,0:09:47.05,0:09:48.76,Default,,0,0,0,,它是一个无参过程\nDialogue: 0,0:09:49.98,0:09:54.59,Default,,0,0,0,,它将线路上的信号逻辑取反\nDialogue: 0,0:09:56.06,0:09:58.64,Default,,0,0,0,,经过一段时长为INVERTER-DELAT的延时以后 --\nDialogue: 0,0:09:59.26,0:10:01.15,Default,,0,0,0,,每个电路对象都有延时 --\nDialogue: 0,0:10:02.88,0:10:04.46,Default,,0,0,0,,然后我们会 --\nDialogue: 0,0:10:04.67,0:10:07.14,Default,,0,0,0,,我们再把输出设置为新的值\nDialogue: 0,0:10:10.16,0:10:11.36,Default,,0,0,0,,非常简单\nDialogue: 0,0:10:12.40,0:10:15.28,Default,,0,0,0,,你可以想象输出电线也同样是信号敏感的\nDialogue: 0,0:10:15.77,0:10:18.27,Default,,0,0,0,,当信号改变的时候\nDialogue: 0,0:10:19.28,0:10:21.15,Default,,0,0,0,,它会“告知”其它对象\nDialogue: 0,0:10:21.79,0:10:24.78,Default,,0,0,0,,“快醒醒！我的值已经改变啦”\nDialogue: 0,0:10:26.05,0:10:30.14,Default,,0,0,0,,所以当你把非门和与门或者元件连在一起的时候\nDialogue: 0,0:10:30.46,0:10:32.20,Default,,0,0,0,,它们之间将会有大量的通信\nDialogue: 0,0:10:32.86,0:10:35.07,Default,,0,0,0,,以确保信号正确地传播\nDialogue: 0,0:10:36.81,0:10:38.62,Default,,0,0,0,,到目前为止 没什么新奇的东西\nDialogue: 0,0:10:38.62,0:10:40.72,Default,,0,0,0,,我们只是针对某个特定的表示法\nDialogue: 0,0:10:40.72,0:10:45.24,Default,,0,0,0,,也就是这个例子中的1、0 -- 实现了LOGICAL-NOT而已\nDialogue: 0,0:10:46.73,0:10:49.16,Default,,0,0,0,,与门就相对复杂一些\nDialogue: 0,0:10:49.78,0:10:55.80,Default,,0,0,0,,与门有两个输入A1和A2 输出是OUTPUT\nDialogue: 0,0:10:56.73,0:11:00.64,Default,,0,0,0,,但是其结构和非门没有什么大的不同\nDialogue: 0,0:11:00.86,0:11:03.44,Default,,0,0,0,,只不过是 当输入信号改变的时候\nDialogue: 0,0:11:04.52,0:11:09.07,Default,,0,0,0,,与门调用的是AND-ACTION过程罢了\nDialogue: 0,0:11:10.91,0:11:12.88,Default,,0,0,0,,当然 它所做的只是\nDialogue: 0,0:11:12.91,0:11:15.37,Default,,0,0,0,,对输入信号进行逻辑“与”运算\nDialogue: 0,0:11:16.19,0:11:18.76,Default,,0,0,0,,在经过AND-GATE-DELAY的延时之后\nDialogue: 0,0:11:20.46,0:11:24.36,Default,,0,0,0,,调用这个过程 更新输出信号值\nDialogue: 0,0:11:25.47,0:11:28.35,Default,,0,0,0,,那么 我们如何用“按愿望思维”来构造这一切呢？\nDialogue: 0,0:11:28.35,0:11:31.08,Default,,0,0,0,,如大家所见 这里有一个赋值运算\nDialogue: 0,0:11:32.02,0:11:32.78,Default,,0,0,0,,但并不是SET!\nDialogue: 0,0:11:34.57,0:11:36.78,Default,,0,0,0,,这是一个派生出来的运算\nDialogue: 0,0:11:36.78,0:11:38.73,Default,,0,0,0,,就像可以从CAR和CDR派生出其它函数一样\nDialogue: 0,0:11:40.80,0:11:44.81,Default,,0,0,0,,因此 按照约定 我加上“!”（表示这个过程有副作用）\nDialogue: 0,0:11:46.34,0:11:49.18,Default,,0,0,0,,这里有个过程ADD-ACTION!\nDialogue: 0,0:11:49.44,0:11:54.67,Default,,0,0,0,,它用来提醒与门中的局部线路A1\nDialogue: 0,0:11:55.63,0:11:58.68,Default,,0,0,0,,当它改变的时候记得执行过程AND-ACTION-PROCEDURE\nDialogue: 0,0:11:59.58,0:12:02.91,Default,,0,0,0,,A2也是一样\nDialogue: 0,0:12:06.31,0:12:07.23,Default,,0,0,0,,非常简单\nDialogue: 0,0:12:09.96,0:12:12.09,Default,,0,0,0,,现在我们再来看看\nDialogue: 0,0:12:12.70,0:12:16.12,Default,,0,0,0,,各部分间是如何通信的\nDialogue: 0,0:12:18.54,0:12:19.66,Default,,0,0,0,,例如\nDialogue: 0,0:12:23.12,0:12:24.27,Default,,0,0,0,,有一个非常简单的电路\nDialogue: 0,0:12:24.27,0:12:30.46,Default,,0,0,0,,它有一个与门 带有两个输入A、B\nDialogue: 0,0:12:31.92,0:12:38.00,Default,,0,0,0,,与门通过电线C跟非门相连\nDialogue: 0,0:12:39.72,0:12:41.53,Default,,0,0,0,,非门的输出是D\nDialogue: 0,0:12:44.20,0:12:47.34,Default,,0,0,0,,这就是物理世界\nDialogue: 0,0:12:47.36,0:12:49.02,Default,,0,0,0,,一个对物理世界的抽象\nDialogue: 0,0:12:49.86,0:12:53.40,Default,,0,0,0,,要不了几分钱就可以从Radio Shack买到这些元件\nDialogue: 0,0:12:54.88,0:12:56.32,Default,,0,0,0,,那些元件的作用和画在这里的差不多\nDialogue: 0,0:12:57.16,0:13:00.22,Default,,0,0,0,,元件上都标有类似于LS04的标签\nDialogue: 0,0:13:01.53,0:13:08.16,Default,,0,0,0,,现在来看其中的计算模型\nDialogue: 0,0:13:09.01,0:13:10.94,Default,,0,0,0,,它又对应着什么\nDialogue: 0,0:13:11.13,0:13:14.09,Default,,0,0,0,,计算机中的对象对应着我们思维中的什么\nDialogue: 0,0:13:15.85,0:13:19.13,Default,,0,0,0,,我需要把现实世界中的每个对象与计算机中的对应起来\nDialogue: 0,0:13:19.79,0:13:24.27,Default,,0,0,0,,把两个世界中对象之间的关系也对应起来\nDialogue: 0,0:13:26.06,0:13:26.80,Default,,0,0,0,,这是我的目标\nDialogue: 0,0:13:28.56,0:13:29.45,Default,,0,0,0,,让我们来看看怎么做\nDialogue: 0,0:13:30.90,0:13:34.20,Default,,0,0,0,,这一团东西代表信号A\nDialogue: 0,0:13:35.71,0:13:36.94,Default,,0,0,0,,这是信号A\nDialogue: 0,0:13:37.94,0:13:39.32,Default,,0,0,0,,画得像一团云\nDialogue: 0,0:13:39.90,0:13:42.80,Default,,0,0,0,,再画另一个信号 -- B\nDialogue: 0,0:13:46.68,0:13:47.47,Default,,0,0,0,,它是另一个信号\nDialogue: 0,0:13:49.14,0:13:50.91,Default,,0,0,0,,这两个信号\nDialogue: 0,0:13:51.10,0:13:52.81,Default,,0,0,0,,要通过某种方式连在一起\nDialogue: 0,0:13:53.72,0:13:58.75,Default,,0,0,0,,连在这个盒子上 -- 这就代表与门\nDialogue: 0,0:14:00.32,0:14:02.04,Default,,0,0,0,,这就是与门的动作过程\nDialogue: 0,0:14:07.66,0:14:08.59,Default,,0,0,0,,它将产生\nDialogue: 0,0:14:09.15,0:14:13.29,Default,,0,0,0,,它将与另外一个称作C的信号对象交互\nDialogue: 0,0:14:16.22,0:14:18.88,Default,,0,0,0,,哦 说错了 是一条电线C\nDialogue: 0,0:14:20.59,0:14:26.28,Default,,0,0,0,,这跟电线 又将连在另一个动作过程上\nDialogue: 0,0:14:26.28,0:14:30.33,Default,,0,0,0,,在我们的电气世界中 这个过程跟一个非门关联\nDialogue: 0,0:14:32.86,0:14:40.65,Default,,0,0,0,,我还有另外一根电线 -- D\nDialogue: 0,0:14:42.97,0:14:45.29,Default,,0,0,0,,整体布局就是这样\nDialogue: 0,0:14:46.00,0:14:49.44,Default,,0,0,0,,现在必须来研究它们 有关计算的内部机制了\nDialogue: 0,0:14:51.50,0:14:53.69,Default,,0,0,0,,每一跟电线都必须知道\nDialogue: 0,0:14:53.69,0:14:56.36,Default,,0,0,0,,自己承载的信号是什么\nDialogue: 0,0:14:57.34,0:15:00.00,Default,,0,0,0,,我们用变量SIGNAL来表示\nDialogue: 0,0:15:02.97,0:15:04.04,Default,,0,0,0,,SIGNAL的值就是信号\nDialogue: 0,0:15:05.68,0:15:07.74,Default,,0,0,0,,也不要忘了它所关联的环境\nDialogue: 0,0:15:08.89,0:15:11.34,Default,,0,0,0,,对于每个元件来说 一定有一个环境绑定了信号\nDialogue: 0,0:15:15.40,0:15:16.88,Default,,0,0,0,,因此 这里也有一个SIGNAL变量\nDialogue: 0,0:15:19.40,0:15:21.92,Default,,0,0,0,,SIGNAL的值不是0就是1\nDialogue: 0,0:15:22.81,0:15:23.48,Default,,0,0,0,,这儿也有个SIGNAL\nDialogue: 0,0:15:28.00,0:15:30.56,Default,,0,0,0,,现在 一旦这里的信号改变\nDialogue: 0,0:15:31.26,0:15:34.11,Default,,0,0,0,,我们需要通知一系列的对象\nDialogue: 0,0:15:36.66,0:15:37.66,Default,,0,0,0,,我们得通知这个与门\nDialogue: 0,0:15:39.30,0:15:43.96,Default,,0,0,0,,这里有个表 我们把它叫做AP\nDialogue: 0,0:15:44.50,0:15:45.60,Default,,0,0,0,,它可能是一个表\nDialogue: 0,0:15:46.44,0:15:49.00,Default,,0,0,0,,在本例中 表里面的第一项条目是这个东西\nDialogue: 0,0:15:50.50,0:15:54.81,Default,,0,0,0,,这个元件也有一个称为AP的表\nDialogue: 0,0:15:54.81,0:15:58.17,Default,,0,0,0,,也可能有一些其它对象 时刻等待着A来通知“它们”\nDialogue: 0,0:15:59.02,0:16:01.31,Default,,0,0,0,,所以这里可能有其它对象 比如\nDialogue: 0,0:16:01.72,0:16:03.23,Default,,0,0,0,,一些其它我们不知道的对象\nDialogue: 0,0:16:03.63,0:16:04.88,Default,,0,0,0,,这些是与A连接的其它对象\nDialogue: 0,0:16:07.20,0:16:09.64,Default,,0,0,0,,这里的AP表\nDialogue: 0,0:16:11.12,0:16:12.40,Default,,0,0,0,,也指向这个与门\nDialogue: 0,0:16:13.07,0:16:16.35,Default,,0,0,0,,相类似的 这里的AP表\nDialogue: 0,0:16:16.78,0:16:18.53,Default,,0,0,0,,也要指向这里\nDialogue: 0,0:16:18.53,0:16:20.89,Default,,0,0,0,,这里是C要通知的元件\nDialogue: 0,0:16:21.77,0:16:23.18,Default,,0,0,0,,D也一样\nDialogue: 0,0:16:24.28,0:16:25.24,Default,,0,0,0,,但是我不知道它要通知谁\nDialogue: 0,0:16:25.26,0:16:26.65,Default,,0,0,0,,因为我的图中没有画出来\nDialogue: 0,0:16:27.19,0:16:28.36,Default,,0,0,0,,可能是和D连接起来的其它元件\nDialogue: 0,0:16:30.32,0:16:32.62,Default,,0,0,0,,同样的\nDialogue: 0,0:16:33.80,0:16:36.96,Default,,0,0,0,,当AND-ACTION过程被唤醒时\nDialogue: 0,0:16:37.02,0:16:41.31,Default,,0,0,0,,也就是说 之前你拜托某人将你唤醒\nDialogue: 0,0:16:41.45,0:16:44.84,Default,,0,0,0,,你拜托它们 当它们的信号发生改变时通知你\nDialogue: 0,0:16:46.97,0:16:48.81,Default,,0,0,0,,你得去检查它的信号是什么\nDialogue: 0,0:16:49.32,0:16:52.25,Default,,0,0,0,,这样你就可以计算逻辑与 输出信号给下一个元件\nDialogue: 0,0:16:57.09,0:16:58.75,Default,,0,0,0,,所里 这里就必须要有\nDialogue: 0,0:16:58.84,0:17:03.00,Default,,0,0,0,,有信息说 A1是这个元件\nDialogue: 0,0:17:03.90,0:17:06.48,Default,,0,0,0,,A2就是这个元件\nDialogue: 0,0:17:08.93,0:17:09.98,Default,,0,0,0,,不只是这样\nDialogue: 0,0:17:11.79,0:17:15.20,Default,,0,0,0,,当我在计算逻辑与时 我还得告诉这个元件一些信息\nDialogue: 0,0:17:16.30,0:17:21.05,Default,,0,0,0,,还有一个输出 输出给这个元件\nDialogue: 0,0:17:25.80,0:17:30.03,Default,,0,0,0,,同样地 非门也有一个输入\nDialogue: 0,0:17:32.38,0:17:34.92,Default,,0,0,0,,当信号被唤醒并告知它信号被修改时\nDialogue: 0,0:17:36.75,0:17:38.64,Default,,0,0,0,,非门会询问该信号\nDialogue: 0,0:17:38.64,0:17:40.09,Default,,0,0,0,,你的值是什么\nDialogue: 0,0:17:41.05,0:17:43.47,Default,,0,0,0,,信号通过像这样发消息 告知“信号已改变”\nDialogue: 0,0:17:43.52,0:17:45.53,Default,,0,0,0,,它就反过来查询这个新的信号值\nDialogue: 0,0:17:46.90,0:17:50.12,Default,,0,0,0,,取到值之后 它将会\nDialogue: 0,0:17:50.14,0:17:55.86,Default,,0,0,0,,计算输出 并改变这个信号的值\nDialogue: 0,0:18:00.60,0:18:01.24,Default,,0,0,0,,以此类推\nDialogue: 0,0:18:02.84,0:18:04.56,Default,,0,0,0,,因此我也必须有这么多的连接\nDialogue: 0,0:18:06.24,0:18:09.23,Default,,0,0,0,,现在我们回头观察一下 这个与门\nDialogue: 0,0:18:10.26,0:18:12.09,Default,,0,0,0,,回到这张幻灯片\nDialogue: 0,0:18:13.67,0:18:15.04,Default,,0,0,0,,这几个部分的内容\nDialogue: 0,0:18:16.04,0:18:19.32,Default,,0,0,0,,对每个与门 都有A1、A2两个输入 一个OUTPUT输出\nDialogue: 0,0:18:21.03,0:18:23.53,Default,,0,0,0,,这些都是\nDialogue: 0,0:18:25.08,0:18:28.16,Default,,0,0,0,,在AND-GATE被调用时的环境中\nDialogue: 0,0:18:28.41,0:18:31.24,Default,,0,0,0,,这些参数创建了一个框架\nDialogue: 0,0:18:33.31,0:18:35.90,Default,,0,0,0,,这个框架用来存放A1、A2和OUTPUT的值\nDialogue: 0,0:18:36.67,0:18:39.20,Default,,0,0,0,,它们都要与电线相绑定\nDialogue: 0,0:18:39.60,0:18:44.25,Default,,0,0,0,,这些电线就是通过参数传进来的\nDialogue: 0,0:18:46.24,0:18:47.31,Default,,0,0,0,,在这个环境下\nDialogue: 0,0:18:47.74,0:18:49.85,Default,,0,0,0,,我构建一个过程\nDialogue: 0,0:18:50.97,0:18:53.68,Default,,0,0,0,,就在这里\nDialogue: 0,0:18:54.59,0:18:57.31,Default,,0,0,0,,在该环境下定义的AND-ACTION-PROCEDURE\nDialogue: 0,0:18:58.35,0:19:00.70,Default,,0,0,0,,这个实际上是对一个LAMBDA表达式求值\nDialogue: 0,0:19:01.62,0:19:05.48,Default,,0,0,0,,它跟求值该LAMBDA表达式时的环境相绑定\nDialogue: 0,0:19:07.16,0:19:09.34,Default,,0,0,0,,找到它的局部环境\nDialogue: 0,0:19:11.70,0:19:13.47,Default,,0,0,0,,因此AND-ACTION-PROCEDURE过程能够\nDialogue: 0,0:19:13.64,0:19:16.94,Default,,0,0,0,,存取这里看到的A1、A2和OUTPUT\nDialogue: 0,0:19:17.31,0:19:19.64,Default,,0,0,0,,A1、A2、OUTPUT\nDialogue: 0,0:19:22.36,0:19:23.95,Default,,0,0,0,,我们还没有深入探索“电线”的内部结构\nDialogue: 0,0:19:26.03,0:19:26.99,Default,,0,0,0,,那是仅剩的部分\nDialogue: 0,0:19:29.03,0:19:29.92,Default,,0,0,0,,来看看“电线”\nDialogue: 0,0:19:33.52,0:19:36.25,Default,,0,0,0,,麻烦请开一下投影仪\nDialogue: 0,0:19:39.50,0:19:42.56,Default,,0,0,0,,“电线”是有那么一点复杂\nDialogue: 0,0:19:43.09,0:19:44.64,Default,,0,0,0,,哦 摁错了\nDialogue: 0,0:19:47.05,0:19:48.75,Default,,0,0,0,,是非常复杂 像这样\nDialogue: 0,0:19:50.06,0:19:53.10,Default,,0,0,0,,但是还是来看一下 到底是什么\nDialogue: 0,0:19:54.72,0:19:56.67,Default,,0,0,0,,“电线”是这样的一种东西\nDialogue: 0,0:19:57.76,0:20:03.52,Default,,0,0,0,,有两个主要部分 都是它的状态\nDialogue: 0,0:20:05.01,0:20:07.39,Default,,0,0,0,,我们这里看到的 一个是信号值\nDialogue: 0,0:20:07.45,0:20:10.06,Default,,0,0,0,,这里 当我们调用MAKE-WIRE创建一条电线时\nDialogue: 0,0:20:10.46,0:20:13.02,Default,,0,0,0,,我们首先要创建一些变量\nDialogue: 0,0:20:14.94,0:20:16.08,Default,,0,0,0,,分别是这条电线的\nDialogue: 0,0:20:17.10,0:20:19.29,Default,,0,0,0,,SIGNAL和ACTION-PROCS\nDialogue: 0,0:20:22.32,0:20:23.44,Default,,0,0,0,,在这个上下文中\nDialogue: 0,0:20:23.76,0:20:27.04,Default,,0,0,0,,我们定义了一系列的过程\nDialogue: 0,0:20:27.84,0:20:31.15,Default,,0,0,0,,其中一个是(SET-MY-SIGNAL! NEW)\nDialogue: 0,0:20:32.85,0:20:37.42,Default,,0,0,0,,它所做的只是 取一个新值NEW\nDialogue: 0,0:20:37.93,0:20:40.36,Default,,0,0,0,,如果NEW和SIGNAL一样 信号没有变化 就没必要做什么了\nDialogue: 0,0:20:40.36,0:20:42.62,Default,,0,0,0,,否则 把SIGNAL的值赋值为NEW\nDialogue: 0,0:20:42.75,0:20:44.60,Default,,0,0,0,,再调用ACTION-PROCS里的所有过程\nDialogue: 0,0:20:46.52,0:20:52.51,Default,,0,0,0,,那些我之前引入的过程\nDialogue: 0,0:20:54.63,0:21:01.53,Default,,0,0,0,,也就是我在定义与门时就定义的过程\nDialogue: 0,0:21:04.13,0:21:05.60,Default,,0,0,0,,是在代码最后调用ADD-ACTION-PROCEDURE实现的\nDialogue: 0,0:21:07.41,0:21:10.80,Default,,0,0,0,,然后 我还得定义一个过程 用来接受动作\nDialogue: 0,0:21:10.81,0:21:11.82,Default,,0,0,0,,也就是这段代码\nDialogue: 0,0:21:12.80,0:21:15.13,Default,,0,0,0,,它增加了AP表\nDialogue: 0,0:21:15.56,0:21:21.63,Default,,0,0,0,,这是通过使用SET!将PROC与旧的AP表CONS起来实现的\nDialogue: 0,0:21:21.79,0:21:24.25,Default,,0,0,0,,而这个PROC是作为参数传递进来的\nDialogue: 0,0:21:25.40,0:21:27.58,Default,,0,0,0,,由于技术原因 最后还要再运行一次PROC\nDialogue: 0,0:21:27.78,0:21:29.20,Default,,0,0,0,,我不会再对此详细展开\nDialogue: 0,0:21:29.39,0:21:33.15,Default,,0,0,0,,这是一种事件驱动的模拟\nDialogue: 0,0:21:34.59,0:21:36.00,Default,,0,0,0,,要想把这个讲清楚还是得花点时间\nDialogue: 0,0:21:36.95,0:21:39.40,Default,,0,0,0,,最后 我还要定义一个“分派器”\nDialogue: 0,0:21:39.96,0:21:43.58,Default,,0,0,0,,这是一种将消息分派给电线的方法\nDialogue: 0,0:21:45.37,0:21:48.65,Default,,0,0,0,,它将用于从中抽取出不同的信息\nDialogue: 0,0:21:49.07,0:21:51.48,Default,,0,0,0,,比如这里 当前的信号值是多少？\nDialogue: 0,0:21:53.82,0:21:55.66,Default,,0,0,0,,设置新信号值的方法是什么？\nDialogue: 0,0:21:57.18,0:21:58.28,Default,,0,0,0,,我想要这个方法\nDialogue: 0,0:22:00.10,0:22:02.60,Default,,0,0,0,,我怎么样去添加另外的动作过程呢？\nDialogue: 0,0:22:05.51,0:22:09.36,Default,,0,0,0,,最后 以DISPATCH过程为返回值返回\nDialogue: 0,0:22:09.94,0:22:11.87,Default,,0,0,0,,因此 我所构造的电线\nDialogue: 0,0:22:12.00,0:22:13.55,Default,,0,0,0,,是一种可以接收消息的对象\nDialogue: 0,0:22:14.25,0:22:16.01,Default,,0,0,0,,它接收的消息类似于\nDialogue: 0,0:22:16.44,0:22:18.36,Default,,0,0,0,,“你的哪个方法可以用来添加动作过程？”\nDialogue: 0,0:22:19.92,0:22:21.00,Default,,0,0,0,,它返回一个过程\nDialogue: 0,0:22:21.64,0:22:23.05,Default,,0,0,0,,它返回ADD-ACTION-PROCUDURE\nDialogue: 0,0:22:23.07,0:22:26.54,Default,,0,0,0,,我可以将其应用在一个动作过程上\nDialogue: 0,0:22:27.05,0:22:29.01,Default,,0,0,0,,从而实现将一个动作过程加入电线的AP表中\nDialogue: 0,0:22:31.62,0:22:32.82,Default,,0,0,0,,这是一种“许可”\nDialogue: 0,0:22:33.20,0:22:36.08,Default,,0,0,0,,使得你可以去修改自身的AP表\nDialogue: 0,0:22:37.82,0:22:40.16,Default,,0,0,0,,实际上 你可以在这里看到\nDialogue: 0,0:22:41.71,0:22:42.32,Default,,0,0,0,,下一张幻灯片\nDialogue: 0,0:22:43.53,0:22:43.82,Default,,0,0,0,,噢\nDialogue: 0,0:22:47.76,0:22:49.12,Default,,0,0,0,,没什么有意思的\nDialogue: 0,0:22:49.12,0:22:50.65,Default,,0,0,0,,CALL-EACH调用每个动作过程\nDialogue: 0,0:22:50.89,0:22:52.57,Default,,0,0,0,,这只是对一个表不断做CDR\nDialogue: 0,0:22:52.73,0:22:54.60,Default,,0,0,0,,没什么好说的\nDialogue: 0,0:22:54.99,0:22:56.25,Default,,0,0,0,,我们早就知道了\nDialogue: 0,0:22:57.56,0:23:00.67,Default,,0,0,0,,然而 如果我想知道线路上的信号值\nDialogue: 0,0:23:01.02,0:23:02.54,Default,,0,0,0,,我询问该线路：你的 --\nDialogue: 0,0:23:02.54,0:23:03.09,Default,,0,0,0,,回想一下 什么是线路？\nDialogue: 0,0:23:03.09,0:23:05.40,Default,,0,0,0,,线路对象只是在创建它时所返回的分派过程而已\nDialogue: 0,0:23:05.86,0:23:06.48,Default,,0,0,0,,只是一个过程\nDialogue: 0,0:23:06.83,0:23:12.27,Default,,0,0,0,,我向该分派器发送一个消息'GET-SIGNAL\nDialogue: 0,0:23:12.91,0:23:15.40,Default,,0,0,0,,实际得到的是一个方法 用于取得线路信号值\nDialogue: 0,0:23:16.90,0:23:17.96,Default,,0,0,0,,进一步 我就可以得到信号值\nDialogue: 0,0:23:19.22,0:23:20.52,Default,,0,0,0,,如果我想要设置一个信号值\nDialogue: 0,0:23:22.65,0:23:23.96,Default,,0,0,0,,我想要改变一个信号值\nDialogue: 0,0:23:24.51,0:23:26.76,Default,,0,0,0,,我要做的是\nDialogue: 0,0:23:26.92,0:23:29.69,Default,,0,0,0,,以一个线路和信号的新值作为参数\nDialogue: 0,0:23:30.01,0:23:32.43,Default,,0,0,0,,我向线路请求许可 来设置它的信号值\nDialogue: 0,0:23:32.84,0:23:37.61,Default,,0,0,0,,我会用该许可 -- 也就是一个过程 -- 应用在一个新值上\nDialogue: 0,0:23:38.70,0:23:40.51,Default,,0,0,0,,我们再过来看投影\nDialogue: 0,0:23:41.64,0:23:43.24,Default,,0,0,0,,好的 谢谢\nDialogue: 0,0:23:44.20,0:23:45.63,Default,,0,0,0,,我们看这里的投影\nDialogue: 0,0:23:45.92,0:23:48.75,Default,,0,0,0,,我们看到 如果我请求设置信号的方法\nDialogue: 0,0:23:49.34,0:23:50.44,Default,,0,0,0,,也就是这段代码\nDialogue: 0,0:23:52.25,0:23:55.69,Default,,0,0,0,,返回的是一个定义在线路内部的SET-MY-SIGNAL!方法\nDialogue: 0,0:23:56.25,0:23:57.69,Default,,0,0,0,,回过头来看它的定义\nDialogue: 0,0:23:58.72,0:23:59.74,Default,,0,0,0,,它的定义是\nDialogue: 0,0:24:00.43,0:24:02.68,Default,,0,0,0,,将我的一个内部变量SIGNAL的值设为\nDialogue: 0,0:24:02.73,0:24:05.50,Default,,0,0,0,,这个内部变量 用于存储信号值\nDialogue: 0,0:24:07.61,0:24:10.03,Default,,0,0,0,,将其值设为通过参数传递的NEW\nDialogue: 0,0:24:10.78,0:24:13.01,Default,,0,0,0,,然后调用AP表中的过程 来唤醒它们\nDialogue: 0,0:24:16.34,0:24:16.99,Default,,0,0,0,,非常简单\nDialogue: 0,0:24:19.24,0:24:20.76,Default,,0,0,0,,回头来看刚才的幻灯片\nDialogue: 0,0:24:22.48,0:24:24.32,Default,,0,0,0,,还有最后一点\nDialogue: 0,0:24:24.36,0:24:27.31,Default,,0,0,0,,我想你们现在应该很轻易地就能理解了\nDialogue: 0,0:24:27.77,0:24:29.15,Default,,0,0,0,,关于我们如何添加新的动作过程\nDialogue: 0,0:24:30.10,0:24:35.18,Default,,0,0,0,,我们需要WIRE和ACTION-PROC两个参数\nDialogue: 0,0:24:36.47,0:24:39.31,Default,,0,0,0,,然后请求添加动作过程的许可\nDialogue: 0,0:24:40.05,0:24:44.22,Default,,0,0,0,,得到许可后 用该许可去添加新的动作过程\nDialogue: 0,0:24:45.84,0:24:47.08,Default,,0,0,0,,所以 这确实是一个“对象”\nDialogue: 0,0:24:48.57,0:24:50.32,Default,,0,0,0,,还有些细节\nDialogue: 0,0:24:52.46,0:24:58.39,Default,,0,0,0,,比如 我怎么来控制它？\nDialogue: 0,0:24:58.39,0:24:59.69,Default,,0,0,0,,这些延时怎么实现？\nDialogue: 0,0:25:00.99,0:25:02.54,Default,,0,0,0,,我们来快速过一遍\nDialogue: 0,0:25:05.50,0:25:07.98,Default,,0,0,0,,下一张\nDialogue: 0,0:25:08.36,0:25:08.88,Default,,0,0,0,,我们来看看\nDialogue: 0,0:25:09.57,0:25:14.17,Default,,0,0,0,,我们细看与门、或门的定义\nDialogue: 0,0:25:15.31,0:25:17.00,Default,,0,0,0,,会发现当输入信号改变时\nDialogue: 0,0:25:17.24,0:25:18.19,Default,,0,0,0,,会有“延时”\nDialogue: 0,0:25:18.77,0:25:21.24,Default,,0,0,0,,然后它将调用过程\nDialogue: 0,0:25:21.63,0:25:23.00,Default,,0,0,0,,来改变输出\nDialogue: 0,0:25:26.04,0:25:27.92,Default,,0,0,0,,这个要如何实现？\nDialogue: 0,0:25:28.12,0:25:29.92,Default,,0,0,0,,我们将要建立一种机制\nDialogue: 0,0:25:30.30,0:25:32.00,Default,,0,0,0,,一种相当复杂的机制\nDialogue: 0,0:25:32.33,0:25:33.76,Default,,0,0,0,,我们得非常细心地来看\nDialogue: 0,0:25:34.72,0:25:37.23,Default,,0,0,0,,一段延时之后 我们将执行一个动作\nDialogue: 0,0:25:37.39,0:25:38.12,Default,,0,0,0,,DELAY是一个数\nDialogue: 0,0:25:38.16,0:25:39.23,Default,,0,0,0,,而ACTION是一个过程\nDialogue: 0,0:25:40.59,0:25:43.72,Default,,0,0,0,,我们引入一种称为THE-AGENDA的特殊数据结构\nDialogue: 0,0:25:45.50,0:25:48.80,Default,,0,0,0,,用于组织时间与动作\nDialogue: 0,0:25:49.51,0:25:50.88,Default,,0,0,0,,一会儿再来仔细研究\nDialogue: 0,0:25:50.88,0:25:52.54,Default,,0,0,0,,先把这里说完\nDialogue: 0,0:25:53.07,0:25:58.28,Default,,0,0,0,,THE-AGENDA将记录执行动作的时刻\nDialogue: 0,0:25:59.13,0:26:02.46,Default,,0,0,0,,我们把它设定在未来的某个时刻\nDialogue: 0,0:26:02.51,0:26:05.68,Default,,0,0,0,,也就是在CURRENT-TIME加上DELAT的时刻\nDialogue: 0,0:26:05.69,0:26:07.13,Default,,0,0,0,,触发关联的动作\nDialogue: 0,0:26:09.02,0:26:10.56,Default,,0,0,0,,我们把准备好要执行的动作\nDialogue: 0,0:26:11.02,0:26:12.40,Default,,0,0,0,,添加入THE-AGENDA中\nDialogue: 0,0:26:15.28,0:26:18.03,Default,,0,0,0,,要使这个“机器”运行起来并不困难\nDialogue: 0,0:26:18.66,0:26:21.48,Default,,0,0,0,,我们利用这个PROPAGATE过程来完成这件事\nDialogue: 0,0:26:22.71,0:26:25.95,Default,,0,0,0,,如果THE-AGENDA为空 就没有要做的\nDialogue: 0,0:26:27.44,0:26:28.16,Default,,0,0,0,,否则\nDialogue: 0,0:26:29.76,0:26:31.53,Default,,0,0,0,,我们就取出THE-AGENDA的第一个元素\nDialogue: 0,0:26:31.71,0:26:33.34,Default,,0,0,0,,它是一个无参过程\nDialogue: 0,0:26:34.20,0:26:36.03,Default,,0,0,0,,所以这里有额外的括号\nDialogue: 0,0:26:36.03,0:26:37.85,Default,,0,0,0,,我们对其进行无参调用\nDialogue: 0,0:26:39.19,0:26:40.17,Default,,0,0,0,,这就执行了之前存入的动作\nDialogue: 0,0:26:42.20,0:26:44.17,Default,,0,0,0,,然后我们从THE-AGENDA中删除第一个元素\nDialogue: 0,0:26:44.59,0:26:46.14,Default,,0,0,0,,然后再进入传播循环\nDialogue: 0,0:26:48.91,0:26:50.75,Default,,0,0,0,,这就是整体的结构\nDialogue: 0,0:26:53.38,0:26:55.93,Default,,0,0,0,,还有点其它的\nDialogue: 0,0:26:57.43,0:27:00.01,Default,,0,0,0,,现在 我们来看看THE-AGENDA的内部结构\nDialogue: 0,0:27:00.57,0:27:01.55,Default,,0,0,0,,请看投影仪\nDialogue: 0,0:27:02.80,0:27:04.67,Default,,0,0,0,,该如何使用这个玩意儿呢？\nDialogue: 0,0:27:04.67,0:27:07.41,Default,,0,0,0,,我需要给你们说明下这个模拟器的用法\nDialogue: 0,0:27:07.85,0:27:09.93,Default,,0,0,0,,你们可能觉得这个模拟器太简陋了\nDialogue: 0,0:27:10.40,0:27:12.01,Default,,0,0,0,,甚至你们认为它根本没什么用\nDialogue: 0,0:27:12.57,0:27:13.76,Default,,0,0,0,,而实际上是\nDialogue: 0,0:27:13.98,0:27:15.39,Default,,0,0,0,,这样的模拟器曾被用于\nDialogue: 0,0:27:15.72,0:27:17.44,Default,,0,0,0,,操纵相当大型的计算机\nDialogue: 0,0:27:18.68,0:27:20.64,Default,,0,0,0,,那是一个真实的事例\nDialogue: 0,0:27:22.36,0:27:24.06,Default,,0,0,0,,当然 并不完全是这里的这个模拟器\nDialogue: 0,0:27:24.06,0:27:25.39,Default,,0,0,0,,我会告诉你它们的区别\nDialogue: 0,0:27:25.84,0:27:28.70,Default,,0,0,0,,区别就是 操纵大型机的模拟器有更多的基本元素\nDialogue: 0,0:27:29.82,0:27:32.22,Default,,0,0,0,,不只是有非门 与门之类的\nDialogue: 0,0:27:33.20,0:27:35.72,Default,,0,0,0,,还有边缘触发器\nDialogue: 0,0:27:36.25,0:27:39.88,Default,,0,0,0,,翻转触发器 锁存器\nDialogue: 0,0:27:40.70,0:27:44.52,Default,,0,0,0,,电平触发器 加法器等等之类的\nDialogue: 0,0:27:45.17,0:27:47.31,Default,,0,0,0,,困难之处在于\nDialogue: 0,0:27:47.45,0:27:50.86,Default,,0,0,0,,就在于需要很多页的文档\nDialogue: 0,0:27:51.20,0:27:52.89,Default,,0,0,0,,来描述这些基本元素\nDialogue: 0,0:27:54.69,0:27:56.74,Default,,0,0,0,,同时它们还有很多的参数\nDialogue: 0,0:27:56.74,0:27:57.98,Default,,0,0,0,,不是只有一个延时这么简单\nDialogue: 0,0:27:58.48,0:28:00.81,Default,,0,0,0,,还有建立时间 维持时间之类的\nDialogue: 0,0:28:01.22,0:28:03.40,Default,,0,0,0,,但是 如果不算上那部分的复杂度\nDialogue: 0,0:28:03.82,0:28:08.20,Default,,0,0,0,,我们用来构建真实计算机的模拟器的结构\nDialogue: 0,0:28:09.08,0:28:12.89,Default,,0,0,0,,跟你们在这里看到的的是一致的\nDialogue: 0,0:28:15.11,0:28:19.27,Default,,0,0,0,,无论如何 这里都是一些简单的东西\nDialogue: 0,0:28:19.27,0:28:22.59,Default,,0,0,0,,像这个 设置非门的延时时间 构建一个 AGENDA\nDialogue: 0,0:28:23.03,0:28:25.52,Default,,0,0,0,,我们可以构建一些输入（线路）\nDialogue: 0,0:28:26.03,0:28:29.18,Default,,0,0,0,,这里的四条线路分别是：INPUT-1、INPUT-2、SUM和CARRY\nDialogue: 0,0:28:29.46,0:28:31.88,Default,,0,0,0,,我将要放置一种被称为“探针”的特殊对象\nDialogue: 0,0:28:32.51,0:28:34.64,Default,,0,0,0,,放在一些线路上\nDialogue: 0,0:28:34.97,0:28:36.24,Default,,0,0,0,,放在SUM和CARRY上\nDialogue: 0,0:28:37.23,0:28:40.56,Default,,0,0,0,,探针是一种对象 它可以 --\nDialogue: 0,0:28:40.70,0:28:43.60,Default,,0,0,0,,当你改变它所附着线路的信号时\nDialogue: 0,0:28:43.72,0:28:44.83,Default,,0,0,0,,它会输出一条消息\nDialogue: 0,0:28:46.12,0:28:46.92,Default,,0,0,0,,这很容易实现\nDialogue: 0,0:28:48.44,0:28:49.52,Default,,0,0,0,,一旦我们设置好它们\nDialogue: 0,0:28:49.55,0:28:51.45,Default,,0,0,0,,当你在放置探针的时候\nDialogue: 0,0:28:51.45,0:28:52.41,Default,,0,0,0,,它首先会输出\nDialogue: 0,0:28:52.67,0:28:56.01,Default,,0,0,0,,SUM在0时刻的值为0\nDialogue: 0,0:28:57.29,0:28:58.43,Default,,0,0,0,,这个我已经注意到了\nDialogue: 0,0:28:59.40,0:29:04.75,Default,,0,0,0,,CARRY在0时刻的值也是0\nDialogue: 0,0:29:06.04,0:29:09.28,Default,,0,0,0,,我们继续来构建更多结构\nDialogue: 0,0:29:09.62,0:29:12.28,Default,,0,0,0,,比如 可以像这里一样构建一种结构\nDialogue: 0,0:29:14.06,0:29:18.20,Default,,0,0,0,,用INPUT-1、INPUT-2、SUM和CARRY组成一个半加器\nDialogue: 0,0:29:18.42,0:29:20.42,Default,,0,0,0,,然后我们把INPUT-1上的信号变为1\nDialogue: 0,0:29:20.62,0:29:21.72,Default,,0,0,0,,然后开始传播\nDialogue: 0,0:29:21.88,0:29:22.84,Default,,0,0,0,,在时刻8的时候\nDialogue: 0,0:29:23.90,0:29:26.12,Default,,0,0,0,,如果你想的话 也可以单步跟踪传播过程\nDialogue: 0,0:29:26.52,0:29:29.20,Default,,0,0,0,,SUM的值变为1\nDialogue: 0,0:29:29.52,0:29:30.44,Default,,0,0,0,,然后就结束了\nDialogue: 0,0:29:31.16,0:29:32.25,Default,,0,0,0,,好像没什么意思\nDialogue: 0,0:29:32.63,0:29:33.90,Default,,0,0,0,,我们还可以设置信号\nDialogue: 0,0:29:34.06,0:29:36.73,Default,,0,0,0,,把INPUT-2也变为1\nDialogue: 0,0:29:36.89,0:29:38.09,Default,,0,0,0,,如果再进行传播\nDialogue: 0,0:29:38.36,0:29:39.95,Default,,0,0,0,,在时刻11\nDialogue: 0,0:29:40.12,0:29:41.42,Default,,0,0,0,,CARRY变为1\nDialogue: 0,0:29:41.55,0:29:44.19,Default,,0,0,0,,在时刻16 SUM变为0\nDialogue: 0,0:29:45.39,0:29:48.99,Default,,0,0,0,,如果你仔细研究那个电路图\nDialogue: 0,0:29:48.99,0:29:50.12,Default,,0,0,0,,它确实是这个结果\nDialogue: 0,0:29:50.62,0:29:51.53,Default,,0,0,0,,也并没有什么特别的\nDialogue: 0,0:29:51.53,0:29:54.12,Default,,0,0,0,,但是却清楚地表明了这一些都是如何运作的\nDialogue: 0,0:30:01.83,0:30:03.29,Default,,0,0,0,,我现在给你们展示的是\nDialogue: 0,0:30:03.48,0:30:05.52,Default,,0,0,0,,一种宏观的图景\nDialogue: 0,0:30:06.60,0:30:08.56,Default,,0,0,0,,你如何在一个很大的规模中\nDialogue: 0,0:30:08.72,0:30:12.04,Default,,0,0,0,,你何去实现某种事件驱动的模拟\nDialogue: 0,0:30:13.29,0:30:14.56,Default,,0,0,0,,你应该如何去组织\nDialogue: 0,0:30:14.88,0:30:16.70,Default,,0,0,0,,来获得良好的层次性结构\nDialogue: 0,0:30:16.99,0:30:21.00,Default,,0,0,0,,使得你可以构建可具体化的抽象盒子\nDialogue: 0,0:30:21.56,0:30:24.96,Default,,0,0,0,,但我还没有告诉你AGENDA是如何运作的\nDialogue: 0,0:30:25.78,0:30:26.54,Default,,0,0,0,,下一小节再说\nDialogue: 0,0:30:28.63,0:30:32.94,Default,,0,0,0,,这将涉及到一些关于数据变化之类的事情\nDialogue: 0,0:30:34.31,0:30:35.86,Default,,0,0,0,,在我继续之前 有什么问题吗？\nDialogue: 0,0:30:47.16,0:30:48.24,Default,,0,0,0,,没有的话 那就休息一下\nDialogue: 0,0:30:50.24,0:31:00.62,Default,,0,0,0,,[音乐]\nDialogue: 0,0:31:00.62,0:31:06.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:31:11.23,0:31:17.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:31:17.76,0:31:21.34,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:31:21.34,0:31:25.18,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算对象\nDialogue: 0,0:31:28.94,0:31:35.06,Default,,0,0,0,,我们已经做了一个模拟器\nDialogue: 0,0:31:35.39,0:31:37.77,Default,,0,0,0,,这是一种事件驱动的模拟\nDialogue: 0,0:31:38.17,0:31:42.75,Default,,0,0,0,,其中 计算机中的对象与现实中的对象一一对应\nDialogue: 0,0:31:43.92,0:31:47.28,Default,,0,0,0,,现实世界中按时发生的状态改变\nDialogue: 0,0:31:47.98,0:31:50.83,Default,,0,0,0,,被组织成了计算机中的时间\nDialogue: 0,0:31:52.99,0:31:56.04,Default,,0,0,0,,如果现实中某件事后于另一件事发生\nDialogue: 0,0:31:56.46,0:31:57.96,Default,,0,0,0,,那么在计算机中\nDialogue: 0,0:31:58.89,0:32:02.25,Default,,0,0,0,,两个事件也保持同样的先后顺序发生\nDialogue: 0,0:32:04.42,0:32:07.16,Default,,0,0,0,,排列这些时间 就是我们要用到赋值的地方\nDialogue: 0,0:32:08.22,0:32:11.21,Default,,0,0,0,,现在我要介绍一种方法来组织时间\nDialogue: 0,0:32:11.80,0:32:14.86,Default,,0,0,0,,AGENDA -- 或者有时候所谓的“优先队列”\nDialogue: 0,0:32:16.04,0:32:18.57,Default,,0,0,0,,我们首先需要认识到\nDialogue: 0,0:32:18.62,0:32:21.00,Default,,0,0,0,,为了创建AGENDA 我们需要些什么东西？\nDialogue: 0,0:32:28.33,0:32:31.28,Default,,0,0,0,,首先我要在这里写下一些\nDialogue: 0,0:32:31.39,0:32:33.88,Default,,0,0,0,,用于操作AGENDA的基本运算\nDialogue: 0,0:32:35.96,0:32:37.95,Default,,0,0,0,,我不会给出具体代码\nDialogue: 0,0:32:38.14,0:32:39.58,Default,,0,0,0,,因为它们都非常简单\nDialogue: 0,0:32:40.32,0:32:42.60,Default,,0,0,0,,而且你们手上也有\nDialogue: 0,0:32:43.68,0:32:44.38,Default,,0,0,0,,有哪些运算呢？\nDialogue: 0,0:32:44.38,0:32:53.50,Default,,0,0,0,,MAKE-AGENDA可以新建一个AGENDA\nDialogue: 0,0:32:57.36,0:33:01.77,Default,,0,0,0,,CURRENT-TIME可以获得一个AGENDA的当前时间\nDialogue: 0,0:33:07.47,0:33:12.80,Default,,0,0,0,,返回一个数 -- 也就是当前时间\nDialogue: 0,0:33:16.99,0:33:21.37,Default,,0,0,0,,EMPTY-AGENDA?可用于判断一个AGENDA是否为空\nDialogue: 0,0:33:30.20,0:33:32.57,Default,,0,0,0,,返回TRUE或FALSE\nDialogue: 0,0:33:42.72,0:33:44.72,Default,,0,0,0,,我们也可以向AGENDA中添加对象\nDialogue: 0,0:33:52.71,0:33:56.06,Default,,0,0,0,,实际上 向AGENDA中添加的是一个运算 -- 或者说是需要完成的操作\nDialogue: 0,0:33:56.91,0:33:58.14,Default,,0,0,0,,它需要时间TIME\nDialogue: 0,0:33:59.63,0:34:00.56,Default,,0,0,0,,待添加的动作ACTION\nDialogue: 0,0:34:02.86,0:34:04.64,Default,,0,0,0,,以及AGENDA本身\nDialogue: 0,0:34:07.58,0:34:10.25,Default,,0,0,0,,它把ACTION 放入AGENDA中合适的地方\nDialogue: 0,0:34:10.71,0:34:12.73,Default,,0,0,0,,FIRST-ITEM用于从AGENDA取出第一个事项\nDialogue: 0,0:34:14.24,0:34:15.39,Default,,0,0,0,,那是我首先需要做的事情\nDialogue: 0,0:34:21.84,0:34:23.84,Default,,0,0,0,,该事项是一个动作\nDialogue: 0,0:34:26.46,0:34:28.73,Default,,0,0,0,,我还可以把第一个事项从AGENDA中移除\nDialogue: 0,0:34:29.54,0:34:31.16,Default,,0,0,0,,这是操作AGENDA的一个必要运算\nDialogue: 0,0:34:31.40,0:34:33.02,Default,,0,0,0,,这个运算实现起来非常繁杂\nDialogue: 0,0:34:42.53,0:34:43.36,Default,,0,0,0,,从AGENDA中移除\nDialogue: 0,0:34:45.98,0:34:49.85,Default,,0,0,0,,现在我们来看如何具体组织数据结构\nDialogue: 0,0:34:52.96,0:34:56.04,Default,,0,0,0,,AGENDA应该是一种表\nDialogue: 0,0:34:58.43,0:35:01.20,Default,,0,0,0,,一种可修改的表\nDialogue: 0,0:35:01.57,0:35:04.03,Default,,0,0,0,,因为我们要向其中添加元素\nDialogue: 0,0:35:05.80,0:35:06.89,Default,,0,0,0,,删除元素等等\nDialogue: 0,0:35:07.77,0:35:10.27,Default,,0,0,0,,所以我们需要一种可修改的表\nDialogue: 0,0:35:11.07,0:35:12.51,Default,,0,0,0,,它通过时间组织起来\nDialogue: 0,0:35:13.82,0:35:15.57,Default,,0,0,0,,让它有序 也许会有益处\nDialogue: 0,0:35:18.33,0:35:20.88,Default,,0,0,0,,但是也有可能同一时间会发生很多事\nDialogue: 0,0:35:22.04,0:35:23.42,Default,,0,0,0,,或者说几乎同时\nDialogue: 0,0:35:23.80,0:35:24.72,Default,,0,0,0,,因此我们需要\nDialogue: 0,0:35:24.91,0:35:27.52,Default,,0,0,0,,把它们按发生时间为事件分组\nDialogue: 0,0:35:29.04,0:35:31.61,Default,,0,0,0,,所以我要把AGENDA组织成由SEGMENT构成的表\nDialogue: 0,0:35:32.78,0:35:35.69,Default,,0,0,0,,我来画一下这个结构\nDialogue: 0,0:35:36.68,0:35:37.93,Default,,0,0,0,,方便理解\nDialogue: 0,0:35:39.62,0:35:40.49,Default,,0,0,0,,这是一个AGENDA\nDialogue: 0,0:35:41.11,0:35:42.87,Default,,0,0,0,,以一个名字开始\nDialogue: 0,0:35:47.85,0:35:50.19,Default,,0,0,0,,我把它画在表结构的外部\nDialogue: 0,0:35:52.60,0:35:53.39,Default,,0,0,0,,这是它的头部\nDialogue: 0,0:35:54.14,0:35:55.44,Default,,0,0,0,,这个头部的存在也是很必要的\nDialogue: 0,0:35:55.84,0:35:57.63,Default,,0,0,0,,待会你就会知道\nDialogue: 0,0:36:00.68,0:36:03.40,Default,,0,0,0,,再画一个SEGMENT\nDialogue: 0,0:36:03.96,0:36:05.62,Default,,0,0,0,,这是一个由SEGMENT构成的表\nDialogue: 0,0:36:08.31,0:36:10.54,Default,,0,0,0,,假设这个AGENDA有两个SEGMENT\nDialogue: 0,0:36:11.58,0:36:15.07,Default,,0,0,0,,不断对这个表取CAR即可得到\nDialogue: 0,0:36:16.41,0:36:20.57,Default,,0,0,0,,每个SEGMENT都有一个时间\nDialogue: 0,0:36:24.20,0:36:26.64,Default,,0,0,0,,比如说这里是10\nDialogue: 0,0:36:26.83,0:36:30.51,Default,,0,0,0,,也就是说 这个SEGMENT里的事件发生在10时刻\nDialogue: 0,0:36:33.16,0:36:36.52,Default,,0,0,0,,这里是另外一种数据结构\nDialogue: 0,0:36:36.56,0:36:38.01,Default,,0,0,0,,我先不具体描述\nDialogue: 0,0:36:38.49,0:36:41.08,Default,,0,0,0,,它是一个队列 表示在10时刻要做的事\nDialogue: 0,0:36:42.24,0:36:43.33,Default,,0,0,0,,它是一个队列\nDialogue: 0,0:36:43.33,0:36:44.70,Default,,0,0,0,,一会儿再细说\nDialogue: 0,0:36:45.20,0:36:50.35,Default,,0,0,0,,不过抽象地看 队列就是一系列在固定时间要做的事\nDialogue: 0,0:36:50.40,0:36:52.04,Default,,0,0,0,,我可以向其中添加其它要做的事\nDialogue: 0,0:36:53.10,0:36:53.80,Default,,0,0,0,,这是一个队列\nDialogue: 0,0:36:56.14,0:36:59.11,Default,,0,0,0,,这个是时间 这个是SEGMENT\nDialogue: 0,0:37:03.23,0:37:06.36,Default,,0,0,0,,在这个AGENDA中 还有另一个SEGMENT\nDialogue: 0,0:37:08.94,0:37:11.20,Default,,0,0,0,,假设它在30时刻发生\nDialogue: 0,0:37:13.50,0:37:15.92,Default,,0,0,0,,类似地 它也有一个队列\nDialogue: 0,0:37:16.92,0:37:20.24,Default,,0,0,0,,里面是在30时刻要去做的事\nDialogue: 0,0:37:23.21,0:37:25.66,Default,,0,0,0,,当然 我们的AGENDA还需要支持其它操作\nDialogue: 0,0:37:27.09,0:37:29.20,Default,,0,0,0,,假设我想将一个在10时刻发生的事\nDialogue: 0,0:37:29.47,0:37:31.61,Default,,0,0,0,,添加到AGENDA中\nDialogue: 0,0:37:33.03,0:37:34.16,Default,,0,0,0,,这并不难\nDialogue: 0,0:37:34.70,0:37:38.65,Default,,0,0,0,,我遍历到这里 找到时刻是10的SEGMENT\nDialogue: 0,0:37:39.73,0:37:42.14,Default,,0,0,0,,这样的SEGMENT也可能不存在\nDialogue: 0,0:37:42.93,0:37:44.56,Default,,0,0,0,,一会儿再考虑这种情况\nDialogue: 0,0:37:45.42,0:37:47.56,Default,,0,0,0,,如果我找到了时刻为10的SEGMENT\nDialogue: 0,0:37:47.87,0:37:50.43,Default,,0,0,0,,如果我想要把一个事情放入其中\nDialogue: 0,0:37:50.56,0:37:52.16,Default,,0,0,0,,我只要增加该队列即可\nDialogue: 0,0:37:53.85,0:37:56.22,Default,,0,0,0,,这个说起来倒是很容易\nDialogue: 0,0:37:56.57,0:37:59.26,Default,,0,0,0,,我在这里添加需要在那时做的事\nDialogue: 0,0:38:01.43,0:38:04.25,Default,,0,0,0,,现在 假设我想在时刻20做点什么\nDialogue: 0,0:38:05.31,0:38:07.90,Default,,0,0,0,,然而并没有时刻是20的SEGMENT\nDialogue: 0,0:38:08.99,0:38:10.64,Default,,0,0,0,,我不得不构造一个新的SEGMENT\nDialogue: 0,0:38:11.34,0:38:15.64,Default,,0,0,0,,我想把这个SEGMENT 放在10与30之间\nDialogue: 0,0:38:17.61,0:38:19.32,Default,,0,0,0,,这着实要花点功夫\nDialogue: 0,0:38:20.17,0:38:21.52,Default,,0,0,0,,先用CONS\nDialogue: 0,0:38:24.26,0:38:29.94,Default,,0,0,0,,我要为这个AGENDA构建一个新的SEGMENT\nDialogue: 0,0:38:33.60,0:38:34.81,Default,,0,0,0,,这里的连接必须要变\nDialogue: 0,0:38:35.40,0:38:36.30,Default,,0,0,0,,就像这样\nDialogue: 0,0:38:37.54,0:38:42.80,Default,,0,0,0,,我将要修改AGENDA的CDR部分的CDR部分\nDialogue: 0,0:38:44.88,0:38:49.45,Default,,0,0,0,,让它指向一个新的CONS单元\nDialogue: 0,0:38:50.11,0:38:54.65,Default,,0,0,0,,由一个新的SEGMENT和AGENDA的CDDDDR部分所构成的单元\nDialogue: 0,0:38:57.18,0:39:01.88,Default,,0,0,0,,我们有一个发生在20时刻的新的SEGMENT\nDialogue: 0,0:39:02.30,0:39:03.72,Default,,0,0,0,,它自己维护了一个队列\nDialogue: 0,0:39:04.84,0:39:06.29,Default,,0,0,0,,这个队列中只有一个元素\nDialogue: 0,0:39:10.73,0:39:12.52,Default,,0,0,0,,如果我想在后面添加点什么\nDialogue: 0,0:39:12.54,0:39:15.87,Default,,0,0,0,,我就需要替换这个东西的CDR部分\nDialogue: 0,0:39:16.99,0:39:19.21,Default,,0,0,0,,替换掉这个表的CDR部分\nDialogue: 0,0:39:20.59,0:39:23.31,Default,,0,0,0,,我们就对该数据结构进行修改\nDialogue: 0,0:39:24.04,0:39:25.79,Default,,0,0,0,,因此我需要新的基本运算\nDialogue: 0,0:39:27.21,0:39:28.62,Default,,0,0,0,,因为原有的基础运算达不到这一点\nDialogue: 0,0:39:29.44,0:39:33.88,Default,,0,0,0,,如果我想在5时刻做点什么事\nDialogue: 0,0:39:37.12,0:39:39.20,Default,,0,0,0,,我就得去修改这个东西\nDialogue: 0,0:39:40.81,0:39:42.12,Default,,0,0,0,,因为我得添加到这里\nDialogue: 0,0:39:43.29,0:39:46.22,Default,,0,0,0,,这也就是我预留了一个“头”序对的原因\nDialogue: 0,0:39:47.56,0:39:48.59,Default,,0,0,0,,它预留了空间\nDialogue: 0,0:39:49.40,0:39:52.11,Default,,0,0,0,,我需要有空间去做改变\nDialogue: 0,0:39:53.88,0:39:56.56,Default,,0,0,0,,需要有存储空间 去改变\nDialogue: 0,0:39:58.60,0:40:02.54,Default,,0,0,0,,从AGENDA中删除东西并不困难\nDialogue: 0,0:40:02.54,0:40:04.62,Default,,0,0,0,,移除第一个元素相当容易\nDialogue: 0,0:40:04.92,0:40:06.14,Default,,0,0,0,,这也是我需要考虑的唯一情况\nDialogue: 0,0:40:06.49,0:40:10.19,Default,,0,0,0,,我可以先找到第一个SEGMENT\nDialogue: 0,0:40:11.22,0:40:14.00,Default,,0,0,0,,先判断它的队列是否为空\nDialogue: 0,0:40:14.81,0:40:16.17,Default,,0,0,0,,如果队列不是空的\nDialogue: 0,0:40:16.32,0:40:18.62,Default,,0,0,0,,那么 我就会把元素从中删除\nDialogue: 0,0:40:19.21,0:40:19.74,Default,,0,0,0,,像这样\nDialogue: 0,0:40:20.10,0:40:21.92,Default,,0,0,0,,如果这时队列变为空的\nDialogue: 0,0:40:22.64,0:40:24.22,Default,,0,0,0,,就还要继续把SEGMENT删掉\nDialogue: 0,0:40:24.22,0:40:26.49,Default,,0,0,0,,然后 让这个单元指向这里\nDialogue: 0,0:40:28.22,0:40:31.08,Default,,0,0,0,,这个数据结构操作起来很复杂\nDialogue: 0,0:40:32.25,0:40:35.37,Default,,0,0,0,,它的具体实现也不是很有趣\nDialogue: 0,0:40:36.44,0:40:38.48,Default,,0,0,0,,现在我们来探讨一下队列\nDialogue: 0,0:40:38.92,0:40:39.76,Default,,0,0,0,,它们很相似\nDialogue: 0,0:40:41.16,0:40:43.52,Default,,0,0,0,,每一个AGENDA都有一个队列\nDialogue: 0,0:40:44.34,0:40:45.02,Default,,0,0,0,,队列是什么？\nDialogue: 0,0:40:49.47,0:40:51.85,Default,,0,0,0,,队列能够进行下述基本运算：\nDialogue: 0,0:40:52.78,0:41:02.17,Default,,0,0,0,,MAKE-QUEUE构建一个新队列\nDialogue: 0,0:41:07.77,0:41:17.10,Default,,0,0,0,,INSERT-QUEUE!向队列中插入新元素\nDialogue: 0,0:41:24.51,0:41:28.65,Default,,0,0,0,,DELETE-QUEUE!从队列中删除元素\nDialogue: 0,0:41:40.44,0:41:52.04,Default,,0,0,0,,FRONT-QUEUE查看队列中第一个元素\nDialogue: 0,0:41:53.13,0:41:55.14,Default,,0,0,0,,还需要检测队列是否为空\nDialogue: 0,0:42:07.11,0:42:08.70,Default,,0,0,0,,当你定义像这样的运算时\nDialogue: 0,0:42:09.02,0:42:10.44,Default,,0,0,0,,我希望你能够注意\nDialogue: 0,0:42:10.64,0:42:14.09,Default,,0,0,0,,按照我这样的习惯去为它们命名\nDialogue: 0,0:42:15.12,0:42:19.15,Default,,0,0,0,,“!”表示操作具有副作用 “?”代表定义谓词\nDialogue: 0,0:42:19.87,0:42:21.85,Default,,0,0,0,,就比如说 这里应该加上一个“!”\nDialogue: 0,0:42:24.65,0:42:26.96,Default,,0,0,0,,嗯 空检测谓词的“?”也不要遗漏了\nDialogue: 0,0:42:29.24,0:42:30.72,Default,,0,0,0,,那么 我要如何构建一个队列呢？\nDialogue: 0,0:42:31.72,0:42:34.11,Default,,0,0,0,,队列是一种 可以向其尾部添加东西\nDialogue: 0,0:42:35.12,0:42:36.83,Default,,0,0,0,,也可以从前面取出东西的结构\nDialogue: 0,0:42:37.84,0:42:40.51,Default,,0,0,0,,我可以从队列头删除元素 向队列尾添加元素\nDialogue: 0,0:42:41.23,0:42:43.24,Default,,0,0,0,,我可以用一种很简单的结构来实现\nDialogue: 0,0:42:43.88,0:42:45.72,Default,,0,0,0,,我们当然可以使用CONS来构造\nDialogue: 0,0:42:47.08,0:42:47.79,Default,,0,0,0,,这是一个队列\nDialogue: 0,0:42:49.91,0:42:52.36,Default,,0,0,0,,它有一个队列头\nDialogue: 0,0:42:53.58,0:42:54.92,Default,,0,0,0,,它包含两个部分\nDialogue: 0,0:42:55.28,0:42:56.25,Default,,0,0,0,,其中一个是头指针\nDialogue: 0,0:42:58.78,0:42:59.82,Default,,0,0,0,,另一个是尾指针\nDialogue: 0,0:43:03.12,0:43:06.33,Default,,0,0,0,,假设我有一个包含两个元素的队列\nDialogue: 0,0:43:09.13,0:43:12.09,Default,,0,0,0,,假设第一个元素是1\nDialogue: 0,0:43:12.46,0:43:16.53,Default,,0,0,0,,而第二个元素假定是2\nDialogue: 0,0:43:21.40,0:43:23.52,Default,,0,0,0,,我之所以要在这里设置两个指针\nDialogue: 0,0:43:24.09,0:43:25.61,Default,,0,0,0,,一个头指针和一个尾指针\nDialogue: 0,0:43:25.72,0:43:27.10,Default,,0,0,0,,这样 当向尾部添加元素的时候\nDialogue: 0,0:43:27.48,0:43:29.45,Default,,0,0,0,,就不用从最开始开始遍历\nDialogue: 0,0:43:31.85,0:43:34.80,Default,,0,0,0,,例如 我想要向队列添加入一个新元素\nDialogue: 0,0:43:35.26,0:43:41.02,Default,,0,0,0,,如果想添加一个稍后使用的元素\nDialogue: 0,0:43:41.08,0:43:42.40,Default,,0,0,0,,只需要先用CONS构建一个序对\nDialogue: 0,0:43:43.47,0:43:46.59,Default,,0,0,0,,假设它包含一个值 -- 3\nDialogue: 0,0:43:47.53,0:43:51.34,Default,,0,0,0,,再添加到队列里\nDialogue: 0,0:43:51.52,0:43:53.77,Default,,0,0,0,,这里就需要把这个元素CDR部分的指针\nDialogue: 0,0:43:56.94,0:43:58.76,Default,,0,0,0,,指向这个元素\nDialogue: 0,0:44:00.10,0:44:04.32,Default,,0,0,0,,同时也更新尾指针 让它指向新的地方\nDialogue: 0,0:44:09.12,0:44:12.68,Default,,0,0,0,,如果我想查看队列的第一个元素\nDialogue: 0,0:44:12.96,0:44:17.12,Default,,0,0,0,,我只需要通过头指针去寻找 即可轻松找到\nDialogue: 0,0:44:18.89,0:44:23.26,Default,,0,0,0,,如果我想调用DELETE-QUEUE删除元素\nDialogue: 0,0:44:24.14,0:44:26.35,Default,,0,0,0,,只需要把头指针向后移到就行\nDialogue: 0,0:44:27.71,0:44:29.31,Default,,0,0,0,,新的头指针指向这里\nDialogue: 0,0:44:31.70,0:44:33.13,Default,,0,0,0,,就是这么简单\nDialogue: 0,0:44:34.48,0:44:35.76,Default,,0,0,0,,为了实现这些操作\nDialogue: 0,0:44:37.24,0:44:40.83,Default,,0,0,0,,我们还需要一些新的基本运算\nDialogue: 0,0:44:41.48,0:44:42.56,Default,,0,0,0,,我先列出它们的名字\nDialogue: 0,0:44:42.99,0:44:46.28,Default,,0,0,0,,然后我们再来看 它们的原理和使用方法\nDialogue: 0,0:44:47.35,0:44:55.04,Default,,0,0,0,,SET-CAR!能够为序对的CAR部分\nDialogue: 0,0:44:55.88,0:44:59.36,Default,,0,0,0,,赋予一个新的值\nDialogue: 0,0:45:02.37,0:45:09.92,Default,,0,0,0,,SET-CDR!可以为序对的CDR部分赋新值\nDialogue: 0,0:45:13.02,0:45:14.78,Default,,0,0,0,,现在来看看它们到底做了什么\nDialogue: 0,0:45:16.03,0:45:20.51,Default,,0,0,0,,为了删除队列中的第一个元素 我需要修改这里的CAR部分\nDialogue: 0,0:45:20.96,0:45:22.52,Default,,0,0,0,,这是CAR部分 我需要修改它的值\nDialogue: 0,0:45:23.47,0:45:24.96,Default,,0,0,0,,我需要能够修改CDR部分\nDialogue: 0,0:45:25.28,0:45:27.08,Default,,0,0,0,,以便我能够移动尾指针\nDialogue: 0,0:45:27.21,0:45:28.76,Default,,0,0,0,,也使得我能够扩充队列\nDialogue: 0,0:45:30.16,0:45:31.60,Default,,0,0,0,,之前介绍的所有运算\nDialogue: 0,0:45:31.90,0:45:35.90,Default,,0,0,0,,上一块黑板上的所有东西 都是基于这些运算的\nDialogue: 0,0:45:38.17,0:45:40.14,Default,,0,0,0,,先讲到这里 大家休息一下\nDialogue: 0,0:45:41.24,0:45:52.67,Default,,0,0,0,,[音乐]\nDialogue: 0,0:45:52.67,0:45:57.84,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:18.64,0:46:22.80,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:46:22.80,0:46:27.15,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:46:27.16,0:46:30.76,Declare,,0,0,0,,{\\an2\\fad(500,500)}计算对象\nDialogue: 0,0:46:38.81,0:46:43.53,Default,,0,0,0,,最初 我们说序对是通过CONS构造而来的\nDialogue: 0,0:46:44.57,0:46:46.80,Default,,0,0,0,,我们提到了几条公理\nDialogue: 0,0:46:48.09,0:46:50.76,Default,,0,0,0,,它们是怎样的呢？ 它们是形如 --\nDialogue: 0,0:46:52.28,0:47:03.64,Default,,0,0,0,,对于任意的X和Y (CAR (CONS X Y)) = X\nDialogue: 0,0:47:05.31,0:47:12.92,Default,,0,0,0,,以及 (CDR (CONS X Y)) = Y\nDialogue: 0,0:47:14.80,0:47:20.00,Default,,0,0,0,,但是 它们并没有陈述CONS单元 是否有像人一样的“身份”\nDialogue: 0,0:47:21.85,0:47:25.58,Default,,0,0,0,,实际上 它描述的是一种抽象\nDialogue: 0,0:47:25.74,0:47:27.95,Default,,0,0,0,,也就是CONS是由几个部分组成\nDialogue: 0,0:47:29.74,0:47:33.18,Default,,0,0,0,,如果两个CONS组成部分相同的  它俩则是同样的\nDialogue: 0,0:47:33.93,0:47:35.71,Default,,0,0,0,,至少从这些公理来看是这样的\nDialogue: 0,0:47:37.32,0:47:39.21,Default,,0,0,0,,但是引入了赋值以后\nDialogue: 0,0:47:39.84,0:47:42.32,Default,,0,0,0,,实际上 可变数据就是一种赋值\nDialogue: 0,0:47:42.88,0:47:44.43,Default,,0,0,0,,我们有SET-CAR!和SET-CDR!\nDialogue: 0,0:47:45.55,0:47:48.94,Default,,0,0,0,,引入这些运算后 这些公理就不完整了\nDialogue: 0,0:47:49.83,0:47:52.03,Default,,0,0,0,,但是这里写的也是对的\nDialogue: 0,0:47:53.25,0:47:54.94,Default,,0,0,0,,只不过描述的不再完整\nDialogue: 0,0:47:56.07,0:48:01.68,Default,,0,0,0,,因为如果我要修改一个特定的CONS的CAR部分\nDialogue: 0,0:48:03.02,0:48:04.03,Default,,0,0,0,,问题是\nDialogue: 0,0:48:04.24,0:48:08.64,Default,,0,0,0,,我会同时修改到相同CONS单元的CAR部分么？\nDialogue: 0,0:48:10.09,0:48:13.04,Default,,0,0,0,,假如我用CONS来构建有理数\nDialogue: 0,0:48:14.86,0:48:17.10,Default,,0,0,0,,比如说3/4\nDialogue: 0,0:48:17.34,0:48:20.25,Default,,0,0,0,,假设我有两个3/4\nDialogue: 0,0:48:21.57,0:48:22.75,Default,,0,0,0,,这两个一样吗？\nDialogue: 0,0:48:24.06,0:48:24.89,Default,,0,0,0,,或者又不一样？\nDialogue: 0,0:48:25.34,0:48:26.96,Default,,0,0,0,,当然 对于数字来说 这并不重要\nDialogue: 0,0:48:27.86,0:48:30.49,Default,,0,0,0,,修改一个数的分母并没有数学意义\nDialogue: 0,0:48:33.02,0:48:35.32,Default,,0,0,0,,我们只能够说创建一个数 具有不同的分母\nDialogue: 0,0:48:36.84,0:48:39.88,Default,,0,0,0,,而直接修改一个数的分母这种观念\nDialogue: 0,0:48:40.00,0:48:43.58,Default,,0,0,0,,在数学意义上是一种非常奇怪而不受支持的行为\nDialogue: 0,0:48:44.77,0:48:47.40,Default,,0,0,0,,然而 当这些CONS单元表示的是现实世界中的事物\nDialogue: 0,0:48:48.97,0:48:50.43,Default,,0,0,0,,那么修改它的CAR部分\nDialogue: 0,0:48:50.60,0:48:52.20,Default,,0,0,0,,就像除掉指甲壳的一块一样\nDialogue: 0,0:48:53.69,0:48:56.56,Default,,0,0,0,,所以 每一个CONS都有自己的“身份”\nDialogue: 0,0:48:57.77,0:48:59.92,Default,,0,0,0,,我来先说明“身份”是什么意思\nDialogue: 0,0:49:01.28,0:49:03.05,Default,,0,0,0,,来看些例子\nDialogue: 0,0:49:04.32,0:49:15.20,Default,,0,0,0,,假如(DEFINE A (CONS 1 2))\nDialogue: 0,0:49:18.32,0:49:19.76,Default,,0,0,0,,这是代表什么呢？ 首先\nDialogue: 0,0:49:20.67,0:49:25.20,Default,,0,0,0,,这是说我在某个环境中创建了符号A\nDialogue: 0,0:49:25.96,0:49:28.67,Default,,0,0,0,,而它的值是一个序对\nDialogue: 0,0:49:29.47,0:49:34.06,Default,,0,0,0,,这个序对由两个分别指向1和2的指针组成\nDialogue: 0,0:49:35.34,0:49:36.16,Default,,0,0,0,,就像这样\nDialogue: 0,0:49:38.12,0:49:39.60,Default,,0,0,0,,又假设\nDialogue: 0,0:49:40.22,0:49:47.58,Default,,0,0,0,,(DEFINE B (CONS A A))\nDialogue: 0,0:49:53.88,0:49:56.81,Default,,0,0,0,,虽然无所谓 不过我还是更喜欢用大写\nDialogue: 0,0:49:57.63,0:49:59.88,Default,,0,0,0,,(DEFINE B (CONS A A))\nDialogue: 0,0:50:03.97,0:50:06.03,Default,,0,0,0,,这里用了两次A\nDialogue: 0,0:50:07.84,0:50:10.57,Default,,0,0,0,,现在就要考虑序对的身份问题了\nDialogue: 0,0:50:11.30,0:50:12.64,Default,,0,0,0,,这两个A是同一个东西\nDialogue: 0,0:50:13.69,0:50:14.81,Default,,0,0,0,,这也就是说\nDialogue: 0,0:50:15.29,0:50:17.61,Default,,0,0,0,,我创建了另一个序对\nDialogue: 0,0:50:18.81,0:50:20.20,Default,,0,0,0,,我把它记作B\nDialogue: 0,0:50:22.38,0:50:27.60,Default,,0,0,0,,它由两个指向A的指针组成\nDialogue: 0,0:50:28.92,0:50:32.20,Default,,0,0,0,,对于这个对象来说 此时我有三个名字来指称它\nDialogue: 0,0:50:33.10,0:50:34.16,Default,,0,0,0,,A是一个\nDialogue: 0,0:50:34.88,0:50:36.46,Default,,0,0,0,,(CAR B)是一个\nDialogue: 0,0:50:37.23,0:50:38.86,Default,,0,0,0,,(CDR B)也是一个\nDialogue: 0,0:50:39.36,0:50:41.15,Default,,0,0,0,,都是这个序对的别名\nDialogue: 0,0:50:44.23,0:50:49.28,Default,,0,0,0,,假设现在我要执行\nDialogue: 0,0:50:53.77,0:51:08.38,Default,,0,0,0,,(SET-CAR! (CAR B) 3)\nDialogue: 0,0:51:12.75,0:51:17.45,Default,,0,0,0,,我先去找B的CAR部分 也就是它\nDialogue: 0,0:51:17.83,0:51:20.93,Default,,0,0,0,,再修改它的CAR部分 修改为3\nDialogue: 0,0:51:24.76,0:51:25.69,Default,,0,0,0,,这样我也就修改了A\nDialogue: 0,0:51:27.24,0:51:33.64,Default,,0,0,0,,如果我问 现在A的CAR部分是多少\nDialogue: 0,0:51:35.34,0:51:37.56,Default,,0,0,0,,结果是3\nDialogue: 0,0:51:38.68,0:51:43.39,Default,,0,0,0,,尽管在这里 A是由1和2构成的序对\nDialogue: 0,0:51:45.29,0:51:47.44,Default,,0,0,0,,我通过改变B而改变了A\nDialogue: 0,0:51:48.56,0:51:49.64,Default,,0,0,0,,它们之间存在共享\nDialogue: 0,0:51:52.25,0:51:53.47,Default,,0,0,0,,有时候我们需要这样的结构\nDialogue: 0,0:51:54.24,0:51:56.12,Default,,0,0,0,,当然 在类似于队列这类的数据结构中\nDialogue: 0,0:51:56.24,0:52:02.38,Default,,0,0,0,,我们正是这样来定义、组织数据结果来获得数据共享的\nDialogue: 0,0:52:04.35,0:52:05.66,Default,,0,0,0,,但是有一些非预期的共享\nDialogue: 0,0:52:07.76,0:52:09.72,Default,,0,0,0,,对象间的非预期交互\nDialogue: 0,0:52:10.78,0:52:14.08,Default,,0,0,0,,是大型程序中产生的BUG的主要来源\nDialogue: 0,0:52:15.44,0:52:21.66,Default,,0,0,0,,通过使对象具有“身份”、允许共享\nDialogue: 0,0:52:21.87,0:52:23.76,Default,,0,0,0,,给同一个对象取多个别名\nDialogue: 0,0:52:24.08,0:52:25.05,Default,,0,0,0,,我们获得了强大的能力\nDialogue: 0,0:52:25.13,0:52:28.46,Default,,0,0,0,,但是同时也为此引出的BUG和复杂度而付出代价\nDialogue: 0,0:52:32.19,0:52:36.24,Default,,0,0,0,,为了把这个讲透彻一点 我们再举一个例子\nDialogue: 0,0:52:37.10,0:52:39.87,Default,,0,0,0,,比如(CADR B)\nDialogue: 0,0:52:42.46,0:52:46.56,Default,,0,0,0,,看起来和(CAR B)没有一点关系\nDialogue: 0,0:52:46.88,0:52:49.02,Default,,0,0,0,,但是它的值是什么？\nDialogue: 0,0:52:49.35,0:52:53.56,Default,,0,0,0,,先取B的CDR部分 再取结果的CAR部分\nDialogue: 0,0:52:53.56,0:52:54.86,Default,,0,0,0,,哦 还是3\nDialogue: 0,0:52:56.48,0:53:00.43,Default,,0,0,0,,有了共享这样的机制 局部的含义也不是那么清楚了\nDialogue: 0,0:53:01.12,0:53:02.48,Default,,0,0,0,,所以我们要非常小心的操作\nDialogue: 0,0:53:06.64,0:53:12.64,Default,,0,0,0,,目前为止 我已经介绍了好几个赋值运算\nDialogue: 0,0:53:13.18,0:53:17.61,Default,,0,0,0,,比如SET!、SET-CAR!、SET-CDR!\nDialogue: 0,0:53:18.51,0:53:21.39,Default,,0,0,0,,或许我应该不用SET-CAR!、SET-CDR! 它们引入太多问题了\nDialogue: 0,0:53:22.82,0:53:23.66,Default,,0,0,0,,而事实则是\nDialogue: 0,0:53:24.12,0:53:26.11,Default,,0,0,0,,一旦把骆驼的鼻子牵进帐篷\nDialogue: 0,0:53:26.24,0:53:27.34,Default,,0,0,0,,它的身体可就自己跟进来了\nDialogue: 0,0:53:30.16,0:53:31.26,Default,,0,0,0,,只要有SET!\nDialogue: 0,0:53:31.61,0:53:35.85,Default,,0,0,0,,这些糟糕的东西都可能发生\nDialogue: 0,0:53:38.55,0:53:39.80,Default,,0,0,0,,我们来分析一下\nDialogue: 0,0:53:40.69,0:53:43.72,Default,,0,0,0,,前些日子 讲到复合数据的时候\nDialogue: 0,0:53:45.13,0:53:51.20,Default,,0,0,0,,哈罗德教授向你们展示了 用消息接收的方式来定义CONS\nDialogue: 0,0:53:52.48,0:53:56.06,Default,,0,0,0,,我将给你们展示一种更加糟糕的方式\nDialogue: 0,0:53:57.13,0:54:00.04,Default,,0,0,0,,凭“空”定义CONS\nDialogue: 0,0:54:02.56,0:54:03.02,Default,,0,0,0,,“什么”都不用\nDialogue: 0,0:54:04.44,0:54:08.12,Default,,0,0,0,,用传统的函数式的方法如何定义CONS呢？\nDialogue: 0,0:54:09.26,0:54:11.66,Default,,0,0,0,,纯粹只用LAMBDA表达式\nDialogue: 0,0:54:13.39,0:54:14.40,Default,,0,0,0,,把序对表示成过程\nDialogue: 0,0:54:17.39,0:54:19.66,Default,,0,0,0,,现在我要修改这个定义\nDialogue: 0,0:54:20.30,0:54:23.16,Default,,0,0,0,,使得只具有一种赋值\nDialogue: 0,0:54:24.28,0:54:27.93,Default,,0,0,0,,用SET!来代替SET-CAR!和SET-CDR!\nDialogue: 0,0:54:28.58,0:54:37.39,Default,,0,0,0,,如果我把CONS定义为\nDialogue: 0,0:54:38.91,0:54:42.56,Default,,0,0,0,,定义为一个过程 该过程接收参数M\nDialogue: 0,0:54:43.39,0:54:46.32,Default,,0,0,0,,该过程将M应用在X与Y上\nDialogue: 0,0:54:51.12,0:54:53.10,Default,,0,0,0,,这是阿隆佐·丘奇发明的方法\nDialogue: 0,0:54:53.77,0:54:55.72,Default,,0,0,0,,他是20世纪最伟大的程序员\nDialogue: 0,0:54:55.79,0:54:57.15,Default,,0,0,0,,尽管当时电脑还没有被发明\nDialogue: 0,0:54:57.87,0:54:59.13,Default,,0,0,0,,但他在20世纪30年代就提出了这个方法\nDialogue: 0,0:54:59.42,0:55:02.22,Default,,0,0,0,,他是一个逻辑学家 在普林斯顿大学做研究\nDialogue: 0,0:55:08.66,0:55:10.43,Default,,0,0,0,,定义(CAR X)为\nDialogue: 0,0:55:13.10,0:55:16.92,Default,,0,0,0,,把X应用在一个二元过程上\nDialogue: 0,0:55:17.15,0:55:20.60,Default,,0,0,0,,参数分别是A和D 而结果是选出A\nDialogue: 0,0:55:23.71,0:55:24.97,Default,,0,0,0,,而(CDR X)则是\nDialogue: 0,0:55:33.10,0:55:34.78,Default,,0,0,0,,这样的一个过程\nDialogue: 0,0:55:35.08,0:55:40.25,Default,,0,0,0,,把X应用在一个参数分别是A和D的过程上\nDialogue: 0,0:55:40.92,0:55:42.04,Default,,0,0,0,,该过程选择出D\nDialogue: 0,0:55:46.67,0:55:49.88,Default,,0,0,0,,可能你们还没意识到这些就是CAR、CDR和CONS\nDialogue: 0,0:55:50.51,0:55:53.61,Default,,0,0,0,,但我将要给你们演示它符合之前的公理\nDialogue: 0,0:55:54.11,0:55:54.81,Default,,0,0,0,,举一个例子\nDialogue: 0,0:55:55.61,0:55:57.56,Default,,0,0,0,,我们来看一下\nDialogue: 0,0:55:58.29,0:56:06.27,Default,,0,0,0,,考虑一下语句语句(CAR (CONS 35 47))\nDialogue: 0,0:56:09.93,0:56:10.96,Default,,0,0,0,,它的结果是多少呢？\nDialogue: 0,0:56:11.12,0:56:15.24,Default,,0,0,0,,它是通过把35和47代换进\nDialogue: 0,0:56:15.37,0:56:18.20,Default,,0,0,0,,语句体中的X和Y得到的\nDialogue: 0,0:56:19.71,0:56:20.69,Default,,0,0,0,,非常容易\nDialogue: 0,0:56:20.69,0:56:30.88,Default,,0,0,0,,就得到了语句(CAR (LAMBDA (M) (M 35 47)))\nDialogue: 0,0:56:35.53,0:56:39.36,Default,,0,0,0,,这个的结果是把这个对象\nDialogue: 0,0:56:39.44,0:56:41.85,Default,,0,0,0,,代换进这里的X而得到的\nDialogue: 0,0:56:42.83,0:56:47.66,Default,,0,0,0,,代换的结果是((LAMBDA (M --\nDialogue: 0,0:56:48.33,0:56:52.19,Default,,0,0,0,,用这个对象代换这里的X\nDialogue: 0,0:56:52.88,0:56:54.35,Default,,0,0,0,,这是表的头部\nDialogue: 0,0:56:54.88,0:57:00.32,Default,,0,0,0,,体的部分是(M 35 47)\nDialogue: 0,0:57:03.10,0:57:07.31,Default,,0,0,0,,把它应用于一个参数分别的A和D的过程上\nDialogue: 0,0:57:07.48,0:57:08.67,Default,,0,0,0,,后者返回参数A\nDialogue: 0,0:57:10.91,0:57:14.62,Default,,0,0,0,,然后我们用这个来代换这里的M\nDialogue: 0,0:57:15.96,0:57:21.71,Default,,0,0,0,,这个就相当于把(LAMBDA (A D) A)\nDialogue: 0,0:57:22.22,0:57:24.84,Default,,0,0,0,,应用在35和47上\nDialogue: 0,0:57:26.33,0:57:27.37,Default,,0,0,0,,结果就是35\nDialogue: 0,0:57:27.40,0:57:31.21,Default,,0,0,0,,它就是用35和47分别代换A、D 最后返回A\nDialogue: 0,0:57:35.60,0:57:37.24,Default,,0,0,0,,所以我根本不需要任何数据\nDialogue: 0,0:57:37.88,0:57:38.75,Default,,0,0,0,,甚至连数字都不需要\nDialogue: 0,0:57:40.92,0:57:42.64,Default,,0,0,0,,这就是 阿隆佐·邱奇的技巧\nDialogue: 0,0:57:52.42,0:57:56.17,Default,,0,0,0,,现在呢我们来对这个定义做点修改\nDialogue: 0,0:57:56.76,0:57:58.49,Default,,0,0,0,,作为逻辑学家 他可能会不太开心\nDialogue: 0,0:57:59.20,0:58:01.96,Default,,0,0,0,,但作为程序员 -- 请看投影仪\nDialogue: 0,0:58:03.26,0:58:04.16,Default,,0,0,0,,我们来看看\nDialogue: 0,0:58:05.39,0:58:07.58,Default,,0,0,0,,我修改了CONS的定义\nDialogue: 0,0:58:09.57,0:58:12.35,Default,,0,0,0,,和丘奇的定义很相似 但是不完全相同\nDialogue: 0,0:58:14.41,0:58:15.50,Default,,0,0,0,,具体到底是什么？\nDialogue: 0,0:58:16.07,0:58:18.72,Default,,0,0,0,,CONS有两个参数：X和Y\nDialogue: 0,0:58:19.50,0:58:22.51,Default,,0,0,0,,但它返回一个参数为M的过程\nDialogue: 0,0:58:23.39,0:58:25.64,Default,,0,0,0,,跟之前一样M会应用于X和Y上\nDialogue: 0,0:58:26.19,0:58:29.29,Default,,0,0,0,,但它额外还有两个“许可”\nDialogue: 0,0:58:30.17,0:58:32.01,Default,,0,0,0,,其中一个是把X赋值为N\nDialogue: 0,0:58:32.60,0:58:34.40,Default,,0,0,0,,另一个则是把Y赋值为N\nDialogue: 0,0:58:34.44,0:58:35.68,Default,,0,0,0,,只要我提供了相应的N\nDialogue: 0,0:58:40.94,0:58:44.72,Default,,0,0,0,,所以出了邱奇原本的定义之外\nDialogue: 0,0:58:45.72,0:58:51.66,Default,,0,0,0,,最大的不同在于CONS的返回值\nDialogue: 0,0:58:52.12,0:58:53.82,Default,,0,0,0,,不单会把它的参数应用于\nDialogue: 0,0:58:54.91,0:58:59.44,Default,,0,0,0,,用于构成序对的X和Y之上\nDialogue: 0,0:58:59.69,0:59:03.58,Default,,0,0,0,,它还有用于为X和Y赋值的两个“许可”\nDialogue: 0,0:59:06.54,0:59:08.08,Default,,0,0,0,,当然 就如之前一样\nDialogue: 0,0:59:08.83,0:59:10.51,Default,,0,0,0,,CAR看起来也很相似\nDialogue: 0,0:59:11.69,0:59:14.36,Default,,0,0,0,,就像邱奇定义的那样\nDialogue: 0,0:59:14.54,0:59:16.00,Default,,0,0,0,,(CAR X)只不过是把X应用在\nDialogue: 0,0:59:16.86,0:59:19.00,Default,,0,0,0,,过程上 -- 本例中是四个参数\nDialogue: 0,0:59:19.29,0:59:21.04,Default,,0,0,0,,然后从中选出第一个\nDialogue: 0,0:59:22.54,0:59:24.16,Default,,0,0,0,,这就和之前一样\nDialogue: 0,0:59:25.42,0:59:26.96,Default,,0,0,0,,结果将会返回X\nDialogue: 0,0:59:29.04,0:59:35.40,Default,,0,0,0,,X的值被包含在求值这个LAMBDA表达式所产生的过程中\nDialogue: 0,0:59:35.45,0:59:37.84,Default,,0,0,0,,X和Y的值也是在这个环境中定义的\nDialogue: 0,0:59:41.94,0:59:43.15,Default,,0,0,0,,这是我们对CONS的定义\nDialogue: 0,0:59:45.64,0:59:47.53,Default,,0,0,0,,那么 激动人心的地方来了\nDialogue: 0,0:59:47.73,0:59:48.96,Default,,0,0,0,,当然CDR的定义也类似\nDialogue: 0,0:59:49.39,0:59:50.35,Default,,0,0,0,,激动人心的地方\nDialogue: 0,0:59:51.23,0:59:52.52,Default,,0,0,0,,SET-CAR!和SET-CDR!的实现\nDialogue: 0,0:59:53.45,0:59:55.52,Default,,0,0,0,,说实话 它们也不是特别复杂\nDialogue: 0,0:59:55.80,1:00:00.64,Default,,0,0,0,,语句(SET-CAR! X Y)\nDialogue: 0,1:00:01.63,1:00:03.85,Default,,0,0,0,,无非就是把序对X应用于\nDialogue: 0,1:00:04.11,1:00:06.76,Default,,0,0,0,,注意X是一个一元过程\nDialogue: 0,1:00:07.69,1:00:09.80,Default,,0,0,0,,该过程的体是将参数应用在四个对象上\nDialogue: 0,1:00:11.24,1:00:15.85,Default,,0,0,0,,我们把X应用于一个四元过程上\nDialogue: 0,1:00:16.00,1:00:18.08,Default,,0,0,0,,X的值、Y的值\nDialogue: 0,1:00:18.32,1:00:20.54,Default,,0,0,0,,修改X的许可、修改Y的许可\nDialogue: 0,1:00:21.32,1:00:26.09,Default,,0,0,0,,语句的体则是用相应的许可 将X设置为新的值\nDialogue: 0,1:00:31.65,1:00:33.54,Default,,0,0,0,,当然SET-CDR!和它类似\nDialogue: 0,1:00:36.25,1:00:39.44,Default,,0,0,0,,你也看到了 我这里并没有引入新的基本运算\nDialogue: 0,1:00:40.11,1:00:44.36,Default,,0,0,0,,具体要不要这样来实现是一个工程性问题\nDialogue: 0,1:00:45.34,1:00:47.39,Default,,0,0,0,,当然出于工程上的考量\nDialogue: 0,1:00:48.09,1:00:49.63,Default,,0,0,0,,我不会这样来实现\nDialogue: 0,1:00:51.68,1:00:53.40,Default,,0,0,0,,但是从原理上来说\nDialogue: 0,1:00:54.28,1:00:56.43,Default,,0,0,0,,一旦引入了赋值运算\nDialogue: 0,1:00:56.96,1:00:58.76,Default,,0,0,0,,我就可以进行各种各样的赋值运算了\nDialogue: 0,1:01:05.42,1:01:06.67,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:01:09.20,1:01:10.89,Default,,0,0,0,,请讲\nDialogue: 0,1:01:12.04,1:01:15.64,Default,,0,0,0,,我可以跟的上你的思路 直到 --\nDialogue: 0,1:01:15.64,1:01:17.61,Default,,0,0,0,,在许可那里\nDialogue: 0,1:01:18.14,1:01:21.64,Default,,0,0,0,,我们把CONS定义为一个参数为N的过程\nDialogue: 0,1:01:21.80,1:01:24.21,Default,,0,0,0,,我不知道这个参数是什么时候传进来的\nDialogue: 0,1:01:24.21,1:01:25.69,Default,,0,0,0,,教授：哦 抱歉 我给你演示一下\nDialogue: 0,1:01:26.34,1:01:27.05,Default,,0,0,0,,我们来推演一下\nDialogue: 0,1:01:27.36,1:01:29.07,Default,,0,0,0,,虽然在黑板上推演更清晰\nDialogue: 0,1:01:29.18,1:01:30.17,Default,,0,0,0,,但这并不难懂\nDialogue: 0,1:01:30.17,1:01:31.47,Default,,0,0,0,,我就将就用投影仪了\nDialogue: 0,1:01:32.45,1:01:35.79,Default,,0,0,0,,调用(SET-CDR! X Y)会发生什么呢？\nDialogue: 0,1:01:37.79,1:01:39.66,Default,,0,0,0,,就在这里(SET-CDR! X Y)\nDialogue: 0,1:01:40.36,1:01:41.92,Default,,0,0,0,,X可能是一个序对\nDialogue: 0,1:01:43.31,1:01:45.24,Default,,0,0,0,,或者说对一个CONS表达式求值得到的结果\nDialogue: 0,1:01:45.88,1:01:46.35,Default,,0,0,0,,能跟上吧？\nDialogue: 0,1:01:46.89,1:01:49.96,Default,,0,0,0,,也就是说 X是由这里的代码构造出来的\nDialogue: 0,1:01:52.57,1:01:56.49,Default,,0,0,0,,这里的X是求值这个LAMBDA表达式得到的\nDialogue: 0,1:01:58.11,1:01:58.49,Default,,0,0,0,,对吧\nDialogue: 0,1:01:59.38,1:02:01.63,Default,,0,0,0,,因此当我对这个LAMBDA表达式求值时\nDialogue: 0,1:02:04.01,1:02:08.76,Default,,0,0,0,,我是在定义CONS时的一个环境里求值的\nDialogue: 0,1:02:11.75,1:02:15.18,Default,,0,0,0,,这也就是说 作为LAMBDA表达式中的自由变量\nDialogue: 0,1:02:16.25,1:02:18.68,Default,,0,0,0,,X和Y都存储一个框架中\nDialogue: 0,1:02:18.72,1:02:22.44,Default,,0,0,0,,也就是这整个LAMBDA表达式的父框架\nDialogue: 0,1:02:23.23,1:02:25.82,Default,,0,0,0,,因此在这个LAMBDA语句中\nDialogue: 0,1:02:26.65,1:02:28.51,Default,,0,0,0,,X和Y都有存储空间\nDialogue: 0,1:02:29.25,1:02:30.83,Default,,0,0,0,,也可以对它们赋值\nDialogue: 0,1:02:31.91,1:02:36.08,Default,,0,0,0,,这里赋值为N是通过参数来传递的\nDialogue: 0,1:02:37.26,1:02:39.31,Default,,0,0,0,,“许可”就是一个过程\nDialogue: 0,1:02:41.40,1:02:43.18,Default,,0,0,0,,它将作为M的一个参数\nDialogue: 0,1:02:43.29,1:02:46.51,Default,,0,0,0,,它实际上是CONS生成的对象的一部分\nDialogue: 0,1:02:47.94,1:02:50.91,Default,,0,0,0,,我们再来看看SET-CDR!\nDialogue: 0,1:02:52.11,1:02:55.42,Default,,0,0,0,,SET-CDR!的第一个参数X是一个序对\nDialogue: 0,1:02:56.12,1:02:57.48,Default,,0,0,0,,被传递了一个参数\nDialogue: 0,1:02:59.77,1:03:02.22,Default,,0,0,0,,这个是一个四元过程\nDialogue: 0,1:03:02.32,1:03:04.65,Default,,0,0,0,,这是因为 它要作为这里的M\nDialogue: 0,1:03:04.99,1:03:06.56,Default,,0,0,0,,要应用在四个对象上\nDialogue: 0,1:03:07.92,1:03:13.34,Default,,0,0,0,,这边的这个SD 就对应于这个过程\nDialogue: 0,1:03:15.47,1:03:19.93,Default,,0,0,0,,当我执行SD 把它应用于Y\nDialogue: 0,1:03:22.91,1:03:24.04,Default,,0,0,0,,这个Y是这里传过来的\nDialogue: 0,1:03:25.37,1:03:26.92,Default,,0,0,0,,学生：那--\nDialogue: 0,1:03:27.00,1:03:32.19,Default,,0,0,0,,教授：所以说 这里的N就对应于这里的Y\nDialogue: 0,1:03:34.04,1:03:34.52,Default,,0,0,0,,明白了吧\nDialogue: 0,1:03:34.81,1:03:35.75,Default,,0,0,0,,了解了\nDialogue: 0,1:03:35.75,1:03:37.29,Default,,0,0,0,,当你执行SET-CDR!的时候\nDialogue: 0,1:03:39.07,1:03:41.97,Default,,0,0,0,,X是CDR部分要赋值的新值\nDialogue: 0,1:03:41.97,1:03:44.03,Default,,0,0,0,,教授：这里的X\nDialogue: 0,1:03:44.96,1:03:46.20,Default,,0,0,0,,哦 指错了\nDialogue: 0,1:03:46.20,1:03:48.33,Default,,0,0,0,,这里的X是指 -- SET-CDR!有两个参数\nDialogue: 0,1:03:48.91,1:03:50.36,Default,,0,0,0,,一个是被修改的序对\nDialogue: 0,1:03:51.34,1:03:53.93,Default,,0,0,0,,还有就是新值\nDialogue: 0,1:03:56.15,1:03:58.32,Default,,0,0,0,,你可以代换回去看看 就很清楚了\nDialogue: 0,1:04:02.17,1:04:03.16,Default,,0,0,0,,还有什么问题吗？\nDialogue: 0,1:04:07.88,1:04:08.64,Default,,0,0,0,,好的\nDialogue: 0,1:04:08.64,1:04:09.52,Default,,0,0,0,,这节课就到这里\nDialogue: 0,1:04:10.44,1:04:28.73,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:04:10.44,1:04:28.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec5b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: EN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nVideo Position: 1\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:10.10,0:00:14.60,EN,,0,0,0,,Computational Objects\nDialogue: 0,0:00:21.17,0:00:24.12,EN,,0,0,0,,PROFESSOR: Well, now that we've given you some power\nDialogue: 0,0:00:24.43,0:00:27.40,EN,,0,0,0,,to make independent local state and to model objects,\nDialogue: 0,0:00:28.33,0:00:32.67,EN,,0,0,0,,I thought we'd do a bit of programming of a very complicated kind,\nDialogue: 0,0:00:34.03,0:00:36.36,EN,,0,0,0,,just to illustrate what you can do with this sort of thing.\nDialogue: 0,0:00:40.43,0:00:43.48,EN,,0,0,0,,I suppose, as I said, we were motivated by physical systems\nDialogue: 0,0:00:44.11,0:00:46.25,EN,,0,0,0,,the ways we like to think about physical systems,\nDialogue: 0,0:00:46.99,0:00:51.08,EN,,0,0,0,,which is that there are these things that the world is made out of.\nDialogue: 0,0:00:52.06,0:00:55.98,EN,,0,0,0,,And each of these things has particular independent local state,\nDialogue: 0,0:00:57.24,0:00:59.87,EN,,0,0,0,,and therefore it is a thing. That's what makes it a thing.\nDialogue: 0,0:01:01.28,0:01:04.27,EN,,0,0,0,,And then we're going to say that in the model in the world\nDialogue: 0,0:01:04.28,0:01:09.90,EN,,0,0,0,,we have a world and a model in our minds and in the computer of that world.\nDialogue: 0,0:01:10.94,0:01:12.54,EN,,0,0,0,,And what I want to make is a correspondence\nDialogue: 0,0:01:12.78,0:01:15.21,EN,,0,0,0,,between the objects in the world and the objects in the computer,\nDialogue: 0,0:01:15.87,0:01:17.74,EN,,0,0,0,,the relationships between the objects in the world\nDialogue: 0,0:01:17.96,0:01:21.72,EN,,0,0,0,,and the relationships between those same obj...--the model objects in the computer,\nDialogue: 0,0:01:23.18,0:01:25.52,EN,,0,0,0,,and the functions that relate things in the\nDialogue: 0,0:01:25.93,0:01:28.11,EN,,0,0,0,,to the functions that relate things in the computer.\nDialogue: 0,0:01:30.84,0:01:33.82,EN,,0,0,0,,This buys us modularity.\nDialogue: 0,0:01:34.74,0:01:36.75,EN,,0,0,0,,If we really believe the world is like that,\nDialogue: 0,0:01:37.36,0:01:38.72,EN,,0,0,0,,that it's made out of these little pieces,\nDialogue: 0,0:01:39.20,0:01:41.47,EN,,0,0,0,,and of course we could arrange our world to be like that,\nDialogue: 0,0:01:42.03,0:01:43.95,EN,,0,0,0,,we could only model those things that are like that,\nDialogue: 0,0:01:45.45,0:01:49.02,EN,,0,0,0,,then we can inherit the modularity in the world into our programming.\nDialogue: 0,0:01:50.45,0:01:53.58,EN,,0,0,0,,That's why we would invent some of this object-oriented programming.\nDialogue: 0,0:01:55.42,0:01:58.19,EN,,0,0,0,,Well, let's take the best kind of objects I know.\nDialogue: 0,0:01:58.89,0:02:04.17,EN,,0,0,0,,They're completely--they're completely wonderful: electrical systems.\nDialogue: 0,0:02:06.40,0:02:12.99,EN,,0,0,0,,Electrical systems really are the physicist's best, best objects.\nDialogue: 0,0:02:14.22,0:02:16.76,EN,,0,0,0,,You see over here I have some piece of machinery.\nDialogue: 0,0:02:17.12,0:02:18.28,EN,,0,0,0,,Right here's a piece of machinery.\nDialogue: 0,0:02:20.04,0:02:22.88,EN,,0,0,0,,And it's got an electrical wire connecting\nDialogue: 0,0:02:23.66,0:02:26.40,EN,,0,0,0,,one part of the machinery with another part of the machinery.\nDialogue: 0,0:02:27.56,0:02:30.86,EN,,0,0,0,,And one of the wonderful properties of the electrical world\nDialogue: 0,0:02:31.64,0:02:33.12,EN,,0,0,0,,is that I can say this is an object,\nDialogue: 0,0:02:34.01,0:02:34.97,EN,,0,0,0,,and this is an object,\nDialogue: 0,0:02:35.71,0:02:37.53,EN,,0,0,0,,and they're-- the connection between them is clear.\nDialogue: 0,0:02:38.24,0:02:43.32,EN,,0,0,0,,In principle, there is no connection that I didn't describe with these wires.\nDialogue: 0,0:02:44.74,0:02:46.12,EN,,0,0,0,,Let's say if I have light bulbs,\nDialogue: 0,0:02:46.52,0:02:50.32,EN,,0,0,0,,Let's say if I have light bulbs, a light bulb and a power supply that's plugged into the outlet.\nDialogue: 0,0:02:51.63,0:02:53.53,EN,,0,0,0,,Then the connection is perfectly clear.\nDialogue: 0,0:02:53.62,0:02:55.42,EN,,0,0,0,,There's no other connections that we know of.\nDialogue: 0,0:02:56.22,0:03:02.33,EN,,0,0,0,,If I were to tie a knot in the wire that connects the light bulb to the power supply,\nDialogue: 0,0:03:02.68,0:03:03.64,EN,,0,0,0,,the light remains lit up.\nDialogue: 0,0:03:04.04,0:03:04.76,EN,,0,0,0,,It doesn't care.\nDialogue: 0,0:03:07.44,0:03:12.40,EN,,0,0,0,,That the way the physics is arranged is such that the connection can be made abstract,\nDialogue: 0,0:03:13.08,0:03:15.27,EN,,0,0,0,,at least for low frequencies and things like that.\nDialogue: 0,0:03:17.84,0:03:20.88,EN,,0,0,0,,So in fact, we have captured all of the connections there really are.\nDialogue: 0,0:03:22.35,0:03:23.87,EN,,0,0,0,,Well, as you can go one step further\nDialogue: 0,0:03:23.90,0:03:27.31,EN,,0,0,0,,and talk about the most abstract types of electrical systems we have,\nDialogue: 0,0:03:27.85,0:03:29.42,EN,,0,0,0,,digital to dual circuits.\nDialogue: 0,0:03:31.69,0:03:33.66,EN,,0,0,0,,And here there are certain kinds of objects.\nDialogue: 0,0:03:34.64,0:03:40.12,EN,,0,0,0,,For example, in digital circuits we have things like inverters.\nDialogue: 0,0:03:41.39,0:03:42.78,EN,,0,0,0,,We have things like and-gates.\nDialogue: 0,0:03:43.99,0:03:45.40,EN,,0,0,0,,We have things like or-gates.\nDialogue: 0,0:03:47.21,0:03:50.12,EN,,0,0,0,,We connect them together by sort-of wires\nDialogue: 0,0:03:52.00,0:03:54.94,EN,,0,0,0,,which represent abstract signals.\nDialogue: 0,0:03:55.61,0:03:57.18,EN,,0,0,0,,We don't really care as physical variables\nDialogue: 0,0:03:57.21,0:03:59.72,EN,,0,0,0,,whether these are voltages or currents or some combination\nDialogue: 0,0:04:00.01,0:04:03.44,EN,,0,0,0,,or water, water pressure.\nDialogue: 0,0:04:05.20,0:04:07.32,EN,,0,0,0,,These abstract variables represent certain signals.\nDialogue: 0,0:04:09.42,0:04:12.89,EN,,0,0,0,,And we build systems by wiring these things together with wires.\nDialogue: 0,0:04:14.07,0:04:16.22,EN,,0,0,0,,So today what I'm going to show you, right now,\nDialogue: 0,0:04:17.63,0:04:20.17,EN,,0,0,0,,we're going to build up an invented language in Lisp,\nDialogue: 0,0:04:22.14,0:04:25.08,EN,,0,0,0,,embedded in the same sense that Henderson's picture language was embedded,\nDialogue: 0,0:04:26.16,0:04:27.32,EN,,0,0,0,,which is not the same sense\nDialogue: 0,0:04:27.88,0:04:31.61,EN,,0,0,0,,as the language of pattern match and substitution was done yesterday.\nDialogue: 0,0:04:32.80,0:04:36.30,EN,,0,0,0,,The pattern match substitution language was interpreted by a Lisp program.\nDialogue: 0,0:04:38.16,0:04:40.52,EN,,0,0,0,,But the embedding of Henderson's program\nDialogue: 0,0:04:40.56,0:04:44.27,EN,,0,0,0,,is that we just build up more and more procedures that encapsulate the structure we want.\nDialogue: 0,0:04:45.48,0:04:46.75,EN,,0,0,0,,So for example here,\nDialogue: 0,0:04:47.72,0:04:50.64,EN,,0,0,0,,I'm going to have some various primitive kinds of objects, as you see,\nDialogue: 0,0:04:51.05,0:04:52.12,EN,,0,0,0,,that one and that one.\nDialogue: 0,0:04:53.50,0:04:55.18,EN,,0,0,0,,I'm going to use wires to combine them.\nDialogue: 0,0:04:55.98,0:04:59.37,EN,,0,0,0,,The way I represent attaching-- I can make wires.\nDialogue: 0,0:04:59.87,0:05:01.24,EN,,0,0,0,,So let's say A is a wire.\nDialogue: 0,0:05:01.74,0:05:02.69,EN,,0,0,0,,And B is a wire.\nDialogue: 0,0:05:02.69,0:05:03.46,EN,,0,0,0,,And C is a wire.\nDialogue: 0,0:05:03.46,0:05:04.23,EN,,0,0,0,,And D is a wire.\nDialogue: 0,0:05:04.23,0:05:04.83,EN,,0,0,0,,And E is wire.\nDialogue: 0,0:05:04.83,0:05:05.64,EN,,0,0,0,,And S is a wire.\nDialogue: 0,0:05:06.88,0:05:12.75,EN,,0,0,0,,Well, an or-gate that has both inputs, the inputs being A and B,\nDialogue: 0,0:05:13.16,0:05:14.75,EN,,0,0,0,,and the output being wire D,\nDialogue: 0,0:05:15.07,0:05:16.12,EN,,0,0,0,,you notate like this.\nDialogue: 0,0:05:18.14,0:05:22.14,EN,,0,0,0,,An and-gate, which has inputs A and B and output C,\nDialogue: 0,0:05:22.22,0:05:23.24,EN,,0,0,0,,we notate like that.\nDialogue: 0,0:05:24.82,0:05:28.46,EN,,0,0,0,,By making such a sequence of declarations,\nDialogue: 0,0:05:29.29,0:05:31.64,EN,,0,0,0,,I can wire together an arbitrary circuit.\nDialogue: 0,0:05:32.75,0:05:34.64,EN,,0,0,0,,So I've just told you a set of primitives\nDialogue: 0,0:05:35.31,0:05:38.51,EN,,0,0,0,,and means of combination for building digital circuits,\nDialogue: 0,0:05:40.09,0:05:43.04,EN,,0,0,0,,when I need more in a real language than abstraction.\nDialogue: 0,0:05:43.69,0:05:52.24,EN,,0,0,0,,And so for example, here I have--here I have a half adder.\nDialogue: 0,0:05:52.67,0:05:55.55,EN,,0,0,0,,It's something you all know if you've done any digital design.\nDialogue: 0,0:05:56.93,0:06:00.44,EN,,0,0,0,,It's used for adding numbers together on A and B\nDialogue: 0,0:06:00.62,0:06:02.12,EN,,0,0,0,,and putting out a sum and a carry.\nDialogue: 0,0:06:04.35,0:06:06.80,EN,,0,0,0,,And in fact, the wiring diagram is exactly what I told you.\nDialogue: 0,0:06:07.45,0:06:10.99,EN,,0,0,0,,A half adder with things that come out of the box--\nDialogue: 0,0:06:11.13,0:06:14.11,EN,,0,0,0,,you see the box, the boundary, the abstraction is always a box.\nDialogue: 0,0:06:14.79,0:06:19.70,EN,,0,0,0,,And there are things that come out of it, A, B, S, and C.\nDialogue: 0,0:06:19.70,0:06:21.79,EN,,0,0,0,,Those are the declared variables--\nDialogue: 0,0:06:23.39,0:06:26.25,EN,,0,0,0,,declared variables of a lambda expression,\nDialogue: 0,0:06:26.28,0:06:28.01,EN,,0,0,0,,which is the one that defines half adder.\nDialogue: 0,0:06:31.40,0:06:35.96,EN,,0,0,0,,And internal to that, I make up some more wires, D and E,\nDialogue: 0,0:06:36.00,0:06:37.44,EN,,0,0,0,,which I'm going to use for the interconnect--\nDialogue: 0,0:06:37.74,0:06:40.40,EN,,0,0,0,,here E is this one and D is this wire,\nDialogue: 0,0:06:41.32,0:06:43.50,EN,,0,0,0,,the interconnect that doesn't come through the walls of the box--\nDialogue: 0,0:06:45.05,0:06:46.83,EN,,0,0,0,,and wire things together as you just saw.\nDialogue: 0,0:06:48.79,0:06:50.89,EN,,0,0,0,,And the nice thing about this that I've just shown you\nDialogue: 0,0:06:51.05,0:06:53.02,EN,,0,0,0,,this language is hierarchical in the right way.\nDialogue: 0,0:06:53.85,0:06:55.71,EN,,0,0,0,,If a language isn't hierarchical in the right way,\nDialogue: 0,0:06:55.95,0:06:59.96,EN,,0,0,0,,if it turns out that a compound object doesn't look like a primitive,\nDialogue: 0,0:07:00.38,0:07:01.53,EN,,0,0,0,,there's something wrong with the language--\nDialogue: 0,0:07:02.59,0:07:04.22,EN,,0,0,0,,at least the way I feel about that.\nDialogue: 0,0:07:06.41,0:07:09.58,EN,,0,0,0,,So here we have--here, instead of starting with mathematical functions,\nDialogue: 0,0:07:09.60,0:07:11.12,EN,,0,0,0,,or things that compute mathematical functions,\nDialogue: 0,0:07:11.15,0:07:12.65,EN,,0,0,0,,which is what we've been doing up until now,\nDialogue: 0,0:07:13.85,0:07:16.65,EN,,0,0,0,,instead of starting with things that look like mathematical functions,\nDialogue: 0,0:07:16.67,0:07:17.63,EN,,0,0,0,,or compute such things,\nDialogue: 0,0:07:17.85,0:07:20.88,EN,,0,0,0,,we are starting with things that are electrical objects\nDialogue: 0,0:07:21.04,0:07:22.64,EN,,0,0,0,,and we build up more electrical objects.\nDialogue: 0,0:07:23.35,0:07:28.83,EN,,0,0,0,,And the glue we're using is basically the Lisp structure: lambdas.\nDialogue: 0,0:07:30.38,0:07:32.93,EN,,0,0,0,,Lambda is the ultimate glue, if you will.\nDialogue: 0,0:07:33.32,0:07:36.35,EN,,0,0,0,,And of course, half adder itself can be used\nDialogue: 0,0:07:37.64,0:07:41.04,EN,,0,0,0,,in a more complicated abstraction called a full adder,\nDialogue: 0,0:07:41.60,0:07:45.05,EN,,0,0,0,,which in fact involves two half adders, as you see here,\nDialogue: 0,0:07:45.47,0:07:47.87,EN,,0,0,0,,hooked together with some extra wires,\nDialogue: 0,0:07:48.08,0:07:51.29,EN,,0,0,0,,that you see here, S, C1, and C2, and an or-gate,\nDialogue: 0,0:07:52.19,0:07:53.60,EN,,0,0,0,,to manufacture a full adder,\nDialogue: 0,0:07:53.87,0:08:00.78,EN,,0,0,0,,which takes a input number, another input number, a carry in,\nDialogue: 0,0:08:01.36,0:08:04.17,EN,,0,0,0,,and produces output, a sum and a carry out.\nDialogue: 0,0:08:05.90,0:08:10.70,EN,,0,0,0,,And out of full adders, you can make real adder chains and big adders.\nDialogue: 0,0:08:12.99,0:08:14.83,EN,,0,0,0,,So we have here a language so far\nDialogue: 0,0:08:16.06,0:08:21.76,EN,,0,0,0,,That has primitives, means of combination, and means of abstraction to real language.\nDialogue: 0,0:08:22.27,0:08:23.36,EN,,0,0,0,,Now, how are we going to implement this?\nDialogue: 0,0:08:25.00,0:08:26.84,EN,,0,0,0,,Well, let's do it easily.\nDialogue: 0,0:08:27.07,0:08:27.96,EN,,0,0,0,,Let's look at the primitives.\nDialogue: 0,0:08:28.12,0:08:30.11,EN,,0,0,0,,The only problem is we have to implement the primitives.\nDialogue: 0,0:08:31.16,0:08:32.56,EN,,0,0,0,,Nothing else has to be implemented,\nDialogue: 0,0:08:33.74,0:08:38.00,EN,,0,0,0,,because we're picking up the means of combination and abstraction from Lisp,\nDialogue: 0,0:08:39.96,0:08:41.88,EN,,0,0,0,,inheriting them in the embedding.\nDialogue: 0,0:08:43.77,0:08:45.44,EN,,0,0,0,,OK, so let's look at a particular primitive.\nDialogue: 0,0:08:45.86,0:08:47.40,EN,,0,0,0,,An inverter is a nice one.\nDialogue: 0,0:08:51.54,0:08:54.67,EN,,0,0,0,,Now, inverter has two wires coming in, an in and an out.\nDialogue: 0,0:08:57.31,0:09:02.62,EN,,0,0,0,,And somehow, it's going to have to know what to do when a signal comes in.\nDialogue: 0,0:09:04.30,0:09:07.00,EN,,0,0,0,,So somehow it's going to have to tell its input wire--\nDialogue: 0,0:09:07.64,0:09:10.14,EN,,0,0,0,,and now we're going to talk about objects\nDialogue: 0,0:09:10.44,0:09:12.41,EN,,0,0,0,,and we're going to see this in a little more detail soon--\nDialogue: 0,0:09:13.23,0:09:14.84,EN,,0,0,0,,but it's going to have to tell its input wire\nDialogue: 0,0:09:15.82,0:09:18.48,EN,,0,0,0,,that when you change, tell me.\nDialogue: 0,0:09:20.12,0:09:22.11,EN,,0,0,0,,So this object, the object which is the inverter\nDialogue: 0,0:09:22.41,0:09:24.38,EN,,0,0,0,,has to tell the object which is the input wire,\nDialogue: 0,0:09:25.13,0:09:26.40,EN,,0,0,0,,hi, my name is George.\nDialogue: 0,0:09:26.87,0:09:31.02,EN,,0,0,0,,And my, my job is to do something with results when you change.\nDialogue: 0,0:09:31.72,0:09:34.19,EN,,0,0,0,,So when you change, you get a change, tell me about it.\nDialogue: 0,0:09:34.73,0:09:35.72,EN,,0,0,0,,Because I've got to do something with that.\nDialogue: 0,0:09:36.88,0:09:40.30,EN,,0,0,0,,Well, that's done down here by adding an action on the input wire called invert-in,\nDialogue: 0,0:09:41.40,0:09:44.64,EN,,0,0,0,,Well, that's done down here by adding an action on the input wire called invert-in,\nDialogue: 0,0:09:45.07,0:09:46.94,EN,,0,0,0,,where invert-in is defined over here\nDialogue: 0,0:09:47.05,0:09:48.76,EN,,0,0,0,,to be a procedure of no arguments,\nDialogue: 0,0:09:49.98,0:09:54.59,EN,,0,0,0,,which gets the logical not of the signal on the input wire.\nDialogue: 0,0:09:56.06,0:09:58.64,EN,,0,0,0,,And after some delay, which is the inverter delay,\nDialogue: 0,0:09:59.26,0:10:01.15,EN,,0,0,0,,all these electrical objects have delays,\nDialogue: 0,0:10:02.88,0:10:04.46,EN,,0,0,0,,we'll do the following thing--\nDialogue: 0,0:10:04.67,0:10:07.14,EN,,0,0,0,,set the signal on the output wire to the new value.\nDialogue: 0,0:10:10.16,0:10:11.36,EN,,0,0,0,,A very simple program.\nDialogue: 0,0:10:12.40,0:10:15.28,EN,,0,0,0,,Now, you have to imagine that the output wire has to be sensitive\nDialogue: 0,0:10:15.77,0:10:18.27,EN,,0,0,0,,and know that when its signal changes,\nDialogue: 0,0:10:19.28,0:10:21.15,EN,,0,0,0,,it may have to tell other guys,\nDialogue: 0,0:10:21.79,0:10:24.78,EN,,0,0,0,,Hi, wake up. My value has changed.\nDialogue: 0,0:10:26.05,0:10:30.14,EN,,0,0,0,,So when you hook together inverter with an and-gate or something like that,\nDialogue: 0,0:10:30.46,0:10:32.20,EN,,0,0,0,,there has to be a lot of communication going on\nDialogue: 0,0:10:32.86,0:10:35.07,EN,,0,0,0,,to make sure that the signal propagates right.\nDialogue: 0,0:10:36.81,0:10:38.62,EN,,0,0,0,,And down here is nothing very exciting.\nDialogue: 0,0:10:38.62,0:10:40.72,EN,,0,0,0,,This is just the definition of logical not\nDialogue: 0,0:10:40.72,0:10:45.24,EN,,0,0,0,,for some particular representations of the logical values-- 1, 0 in this case.\nDialogue: 0,0:10:46.73,0:10:49.16,EN,,0,0,0,,And we can look at things more complicated like and-gates.\nDialogue: 0,0:10:49.78,0:10:55.80,EN,,0,0,0,,And-gates take two inputs, A1 and A2, we'll call them, and produce an output.\nDialogue: 0,0:10:56.73,0:11:00.64,EN,,0,0,0,,But the structure of the and-gate is identical to the one we just saw.\nDialogue: 0,0:11:00.86,0:11:03.44,EN,,0,0,0,,There's one called an and-action procedure that's defined,\nDialogue: 0,0:11:04.52,0:11:09.07,EN,,0,0,0,,which is the thing that gets called when an input is changed.\nDialogue: 0,0:11:10.91,0:11:12.88,EN,,0,0,0,,And what it does, of course, is nothing more than\nDialogue: 0,0:11:12.91,0:11:15.37,EN,,0,0,0,,compute the logical and of the signals on the inputs.\nDialogue: 0,0:11:16.19,0:11:18.76,EN,,0,0,0,,And after some delay, called the and-gate-delay,\nDialogue: 0,0:11:20.46,0:11:24.36,EN,,0,0,0,,calls this procedure, which sets a signal on the output to a new value.\nDialogue: 0,0:11:25.47,0:11:28.35,EN,,0,0,0,,Now, how I implement these things is all wishful thinking.\nDialogue: 0,0:11:28.35,0:11:31.08,EN,,0,0,0,,As you see here, I have an assignment operation.\nDialogue: 0,0:11:32.02,0:11:32.78,EN,,0,0,0,,It's not set.\nDialogue: 0,0:11:34.57,0:11:36.78,EN,,0,0,0,,It's a derived assignment operation in the same way\nDialogue: 0,0:11:36.78,0:11:38.73,EN,,0,0,0,,we had functions that were derived from CAR and CDR.\nDialogue: 0,0:11:40.80,0:11:44.81,EN,,0,0,0,,So I, by convention, label that with an exclamation point.\nDialogue: 0,0:11:46.34,0:11:49.18,EN,,0,0,0,,And over here, you see there's an add-action!,\nDialogue: 0,0:11:49.44,0:11:54.67,EN,,0,0,0,,which is to inform the wire, called A1 locally in this and-gate,\nDialogue: 0,0:11:55.63,0:11:58.68,EN,,0,0,0,,to call the and-action-procedure when it gets changed,\nDialogue: 0,0:11:59.58,0:12:02.91,EN,,0,0,0,,and the wire A2 to call the and-action procedure when it gets changed.\nDialogue: 0,0:12:06.31,0:12:07.23,EN,,0,0,0,,All very simple.\nDialogue: 0,0:12:09.96,0:12:12.09,EN,,0,0,0,,Well, let's talk a little bit about this communication\nDialogue: 0,0:12:12.70,0:12:16.12,EN,,0,0,0,,that must occur between these various parts.\nDialogue: 0,0:12:18.54,0:12:19.66,EN,,0,0,0,,Suppose, for example,\nDialogue: 0,0:12:23.12,0:12:24.27,EN,,0,0,0,,I have a very simple circuit\nDialogue: 0,0:12:24.27,0:12:30.46,EN,,0,0,0,,which contains and-gate with wires a and b.\nDialogue: 0,0:12:31.92,0:12:38.00,EN,,0,0,0,,And that connects through a wire called c to an inverter\nDialogue: 0,0:12:39.72,0:12:41.53,EN,,0,0,0,,which has a wire output called d.\nDialogue: 0,0:12:44.20,0:12:47.34,EN,,0,0,0,,What are the comput...--here's the physical world.\nDialogue: 0,0:12:47.36,0:12:49.02,EN,,0,0,0,,It's an abstraction of the physical world.\nDialogue: 0,0:12:49.86,0:12:53.40,EN,,0,0,0,,Now I can buy these out of little pieces that you get at Radio Shack for a few cents.\nDialogue: 0,0:12:54.88,0:12:56.32,EN,,0,0,0,,And there are boxes that act like this,\nDialogue: 0,0:12:57.16,0:13:00.22,EN,,0,0,0,,which have little numbers on them like LS04 or something.\nDialogue: 0,0:13:01.53,0:13:08.16,EN,,0,0,0,,Now supposing I were to try to say what's the computational model.\nDialogue: 0,0:13:09.01,0:13:10.94,EN,,0,0,0,,What is the thing that corresponds to that,\nDialogue: 0,0:13:11.13,0:13:14.09,EN,,0,0,0,,that part of reality in the mind of us and in the computer?\nDialogue: 0,0:13:15.85,0:13:19.13,EN,,0,0,0,,Well, I have to assign for every object in the world an object in the computer,\nDialogue: 0,0:13:19.79,0:13:24.27,EN,,0,0,0,,and for every relationship in the world between them a relationship in the computer.\nDialogue: 0,0:13:26.06,0:13:26.80,EN,,0,0,0,,That's my goal.\nDialogue: 0,0:13:28.56,0:13:29.45,EN,,0,0,0,,So let's do that.\nDialogue: 0,0:13:30.90,0:13:34.20,EN,,0,0,0,,Well, I have some sort of thing called the signal, A.\nDialogue: 0,0:13:35.71,0:13:36.94,EN,,0,0,0,,This is A. It's a signal.\nDialogue: 0,0:13:37.94,0:13:39.32,EN,,0,0,0,,It's a cloudy thing like that.\nDialogue: 0,0:13:39.90,0:13:42.80,EN,,0,0,0,,And I have another one down here which I'm going to call B.\nDialogue: 0,0:13:46.68,0:13:47.47,EN,,0,0,0,,It's another signal.\nDialogue: 0,0:13:49.14,0:13:50.91,EN,,0,0,0,,Now this signal--these two signals\nDialogue: 0,0:13:51.10,0:13:52.81,EN,,0,0,0,,are somehow going to have to hook together\nDialogue: 0,0:13:53.72,0:13:58.75,EN,,0,0,0,,into a box, let's call it this, which is the and-gate, action procedure.\nDialogue: 0,0:14:00.32,0:14:02.04,EN,,0,0,0,,That's the and-gate's action procedure.\nDialogue: 0,0:14:07.66,0:14:08.59,EN,,0,0,0,,And it's going to produce\nDialogue: 0,0:14:09.15,0:14:13.29,EN,,0,0,0,,well, it's going to interact with a signal object, which we call C--\nDialogue: 0,0:14:16.22,0:14:18.88,EN,,0,0,0,,a wire object, excuse me, we call C.\nDialogue: 0,0:14:20.59,0:14:26.28,EN,,0,0,0,,this is going to put out again, or connect to, another action procedure\nDialogue: 0,0:14:26.28,0:14:30.33,EN,,0,0,0,,which is one associated with the inverter in the world, not.\nDialogue: 0,0:14:32.86,0:14:40.65,EN,,0,0,0,,And I'm going to have another--another wire, which we'll call D.\nDialogue: 0,0:14:42.97,0:14:45.29,EN,,0,0,0,,So here's my layout of stuff.\nDialogue: 0,0:14:46.00,0:14:49.44,EN,,0,0,0,,Now we have to say what's inside them and what they have to know to compute.\nDialogue: 0,0:14:51.50,0:14:53.69,EN,,0,0,0,,Well, every--every one of these wires has to know\nDialogue: 0,0:14:53.69,0:14:56.36,EN,,0,0,0,,what the value of the signal that's on that wire is.\nDialogue: 0,0:14:57.34,0:15:00.00,EN,,0,0,0,,So there's going to be some variable inside here, we'll call it signal.\nDialogue: 0,0:15:02.97,0:15:04.04,EN,,0,0,0,,And he owns a value.\nDialogue: 0,0:15:05.68,0:15:07.74,EN,,0,0,0,,So there must be some environment associated with this.\nDialogue: 0,0:15:08.89,0:15:11.34,EN,,0,0,0,,And for each one of these, there must be an environment that binds signal.\nDialogue: 0,0:15:15.40,0:15:16.88,EN,,0,0,0,,And there must be a signal here, therefore.\nDialogue: 0,0:15:19.40,0:15:21.92,EN,,0,0,0,,And presumably, signal's a value that's either 1 or 0,\nDialogue: 0,0:15:22.81,0:15:23.48,EN,,0,0,0,,and signal.\nDialogue: 0,0:15:28.00,0:15:30.56,EN,,0,0,0,,Now, we also have to have some\nDialogue: 0,0:15:31.26,0:15:34.11,EN,,0,0,0,,list of people to inform if the signal here changes.\nDialogue: 0,0:15:36.66,0:15:37.66,EN,,0,0,0,,We're going to have to inform this.\nDialogue: 0,0:15:39.30,0:15:43.96,EN,,0,0,0,,So I've got that list. We'll call it the Action Procedures, AP.\nDialogue: 0,0:15:44.50,0:15:45.60,EN,,0,0,0,,And it's presumably a list.\nDialogue: 0,0:15:46.44,0:15:49.00,EN,,0,0,0,,But the first thing on the list, in this case, is this guy.\nDialogue: 0,0:15:50.50,0:15:54.81,EN,,0,0,0,,And the action procedures of this one happens to have some list of stuff.\nDialogue: 0,0:15:54.81,0:15:58.17,EN,,0,0,0,,There might be other people who are sharing A, who are looking at it.\nDialogue: 0,0:15:59.02,0:16:01.31,EN,,0,0,0,,So there might be other guys on this list, like\nDialogue: 0,0:16:01.72,0:16:03.23,EN,,0,0,0,,like somebody over there that we don't know about.\nDialogue: 0,0:16:03.63,0:16:04.88,EN,,0,0,0,,It's the other guy attached to A.\nDialogue: 0,0:16:07.20,0:16:09.64,EN,,0,0,0,,And the action procedure here also has to point to that,\nDialogue: 0,0:16:11.12,0:16:12.40,EN,,0,0,0,,the list of action procedures.\nDialogue: 0,0:16:13.07,0:16:16.35,EN,,0,0,0,,And of course, that means this one, its action procedures\nDialogue: 0,0:16:16.78,0:16:18.53,EN,,0,0,0,,has to point up to here.\nDialogue: 0,0:16:18.53,0:16:20.89,EN,,0,0,0,,This is the things-- the people it has to inform.\nDialogue: 0,0:16:21.77,0:16:23.18,EN,,0,0,0,,And this guy has some too.\nDialogue: 0,0:16:24.28,0:16:25.24,EN,,0,0,0,,But I don't know what they are\nDialogue: 0,0:16:25.26,0:16:26.65,EN,,0,0,0,,because I didn't draw it in my diagram.\nDialogue: 0,0:16:27.19,0:16:28.36,EN,,0,0,0,,It's the things connected to D.\nDialogue: 0,0:16:30.32,0:16:32.62,EN,,0,0,0,,Now, it's also the case\nDialogue: 0,0:16:33.80,0:16:36.96,EN,,0,0,0,,that when the and-action procedure is awakened,\nDialogue: 0,0:16:37.02,0:16:41.31,EN,,0,0,0,,saying one of the people who know that you've told\nDialogue: 0,0:16:41.45,0:16:44.84,EN,,0,0,0,,one of the people you've told to wake you up if their signal changes,\nDialogue: 0,0:16:46.97,0:16:48.81,EN,,0,0,0,,you have to go look and ask them what's their signal\nDialogue: 0,0:16:49.32,0:16:52.25,EN,,0,0,0,,so you can do the and, and produce a signal for this one.\nDialogue: 0,0:16:57.09,0:16:58.75,EN,,0,0,0,,So there has to be, for example,\nDialogue: 0,0:16:58.84,0:17:03.00,EN,,0,0,0,,information here saying A1, my A1 is this guy,\nDialogue: 0,0:17:03.90,0:17:06.48,EN,,0,0,0,,my A1 is this guy, and my A2 is this guy.\nDialogue: 0,0:17:08.93,0:17:09.98,EN,,0,0,0,,And not only that,\nDialogue: 0,0:17:11.79,0:17:15.20,EN,,0,0,0,,when I do my and, I'm going to have to tell this guy something.\nDialogue: 0,0:17:16.30,0:17:21.05,EN,,0,0,0,,So I need an output--  being this guy.\nDialogue: 0,0:17:25.80,0:17:30.03,EN,,0,0,0,,And similarly, this guy's going to have a thing called the input\nDialogue: 0,0:17:32.38,0:17:34.92,EN,,0,0,0,,that he interrogates to find out\nDialogue: 0,0:17:36.75,0:17:38.64,EN,,0,0,0,,what the value of the signal on the input is,\nDialogue: 0,0:17:38.64,0:17:40.09,EN,,0,0,0,,when the signal wakes up and says, I've changed,\nDialogue: 0,0:17:41.05,0:17:43.47,EN,,0,0,0,,and sends a message this way saying, I've changed.\nDialogue: 0,0:17:43.52,0:17:45.53,EN,,0,0,0,,This guy says, OK, what's your value now?\nDialogue: 0,0:17:46.90,0:17:50.12,EN,,0,0,0,,When he gets that value, then he's going to have to say,\nDialogue: 0,0:17:50.14,0:17:55.86,EN,,0,0,0,,OK, output changes this guy, changes this guy.\nDialogue: 0,0:18:00.60,0:18:01.24,EN,,0,0,0,,And so on.\nDialogue: 0,0:18:02.84,0:18:04.56,EN,,0,0,0,,And so I have to have at least that much connected-ness.\nDialogue: 0,0:18:06.24,0:18:09.23,EN,,0,0,0,,Now, let's go back and look, for example, at the and-gate.\nDialogue: 0,0:18:10.26,0:18:12.09,EN,,0,0,0,,Here we are back on this slide.\nDialogue: 0,0:18:13.67,0:18:15.04,EN,,0,0,0,,And we can see some of these parts.\nDialogue: 0,0:18:16.04,0:18:19.32,EN,,0,0,0,,For any particular and-gate, there is an A1, there is an A2, and the output.\nDialogue: 0,0:18:21.03,0:18:23.53,EN,,0,0,0,,And those are, those are\nDialogue: 0,0:18:25.08,0:18:28.16,EN,,0,0,0,,an environment that was created at the--those produce a frame\nDialogue: 0,0:18:28.41,0:18:31.24,EN,,0,0,0,,at the time and-gate was called,\nDialogue: 0,0:18:33.31,0:18:35.90,EN,,0,0,0,,A frame where A1, A2, and output are--\nDialogue: 0,0:18:36.67,0:18:39.20,EN,,0,0,0,,have as their values, they're bound to\nDialogue: 0,0:18:39.60,0:18:44.25,EN,,0,0,0,,the wires which, they are--which were passed in.\nDialogue: 0,0:18:46.24,0:18:47.31,EN,,0,0,0,,In that environment,\nDialogue: 0,0:18:47.74,0:18:49.85,EN,,0,0,0,,I constructed a procedure\nDialogue: 0,0:18:50.97,0:18:53.68,EN,,0,0,0,,this one right there.\nDialogue: 0,0:18:54.59,0:18:57.31,EN,,0,0,0,,And-action-procedure was constructed in that environment.\nDialogue: 0,0:18:58.35,0:19:00.70,EN,,0,0,0,,That was the result of evaluating a lambda expression.\nDialogue: 0,0:19:01.62,0:19:05.48,EN,,0,0,0,,So it hangs onto the frame where these were defined.\nDialogue: 0,0:19:07.16,0:19:09.34,EN,,0,0,0,,Local--part of its local state is that.\nDialogue: 0,0:19:11.70,0:19:13.47,EN,,0,0,0,,The and-action-procedure, therefore, has\nDialogue: 0,0:19:13.64,0:19:16.94,EN,,0,0,0,,access to A1, A2, and output as we see here.\nDialogue: 0,0:19:17.31,0:19:19.64,EN,,0,0,0,,A1, A2, and output.\nDialogue: 0,0:19:22.36,0:19:23.95,EN,,0,0,0,,Now, we haven't looked inside of a wire yet.\nDialogue: 0,0:19:26.03,0:19:26.99,EN,,0,0,0,,That's all that remains.\nDialogue: 0,0:19:29.03,0:19:29.92,EN,,0,0,0,,Let's look at a wire.\nDialogue: 0,0:19:33.52,0:19:36.25,EN,,0,0,0,,Like the overhead, very good.\nDialogue: 0,0:19:39.50,0:19:42.56,EN,,0,0,0,,Well, the wire, again, is a, is a somewhat complicated mess.\nDialogue: 0,0:19:43.09,0:19:44.64,EN,,0,0,0,,Ooh, wrong one.\nDialogue: 0,0:19:47.05,0:19:48.75,EN,,0,0,0,,It's a big complicated mess, like that.\nDialogue: 0,0:19:50.06,0:19:53.10,EN,,0,0,0,,But let's look at it in detail and see what's going on.\nDialogue: 0,0:19:54.72,0:19:56.67,EN,,0,0,0,,Well, the wire is one of these.\nDialogue: 0,0:19:57.76,0:20:03.52,EN,,0,0,0,,And it has to have two things that are part of it, that it's state.\nDialogue: 0,0:20:05.01,0:20:07.39,EN,,0,0,0,,One of them is the signal we see here.\nDialogue: 0,0:20:07.45,0:20:10.06,EN,,0,0,0,,Heres, when we call make-wire to make a wire,\nDialogue: 0,0:20:10.46,0:20:13.02,EN,,0,0,0,,then the first thing we do is we create some variables\nDialogue: 0,0:20:14.94,0:20:16.08,EN,,0,0,0,,which are the signal\nDialogue: 0,0:20:17.10,0:20:19.29,EN,,0,0,0,,and the action procedures for this wire.\nDialogue: 0,0:20:22.32,0:20:23.44,EN,,0,0,0,,And in that context,\nDialogue: 0,0:20:23.76,0:20:27.04,EN,,0,0,0,,we define various functions--or procedures, excuse me, procedures.\nDialogue: 0,0:20:27.84,0:20:31.15,EN,,0,0,0,,One of them is called set-my-signal to a new value.\nDialogue: 0,0:20:32.85,0:20:37.42,EN,,0,0,0,,And what that does is takes a new value in.\nDialogue: 0,0:20:37.93,0:20:40.36,EN,,0,0,0,,If that's equal to my current value of my signal, I'm done.\nDialogue: 0,0:20:40.36,0:20:42.62,EN,,0,0,0,,Otherwise, I set the signal to the new value\nDialogue: 0,0:20:42.75,0:20:44.60,EN,,0,0,0,,and call each of the action procedures\nDialogue: 0,0:20:46.52,0:20:52.51,EN,,0,0,0,,that I've been, that I've been--what's the right word? --  introduced to.\nDialogue: 0,0:20:54.63,0:21:01.53,EN,,0,0,0,,I get introduced when the and-gate was applied to me.\nDialogue: 0,0:21:04.13,0:21:05.60,EN,,0,0,0,,By add action procedure at the bottom.\nDialogue: 0,0:21:07.41,0:21:10.80,EN,,0,0,0,,Also, I have to define a way of accepting an action procedure--\nDialogue: 0,0:21:10.81,0:21:11.82,EN,,0,0,0,,which is what you see here---\nDialogue: 0,0:21:12.80,0:21:15.13,EN,,0,0,0,,which increments my action procedures\nDialogue: 0,0:21:15.56,0:21:21.63,EN,,0,0,0,,using set to the result of CONSing up a new process--a procedure,\nDialogue: 0,0:21:21.79,0:21:24.25,EN,,0,0,0,,which is passed to me, on to my actions procedures list.\nDialogue: 0,0:21:25.40,0:21:27.58,EN,,0,0,0,,And for technical reasons, I have to call that procedure one.\nDialogue: 0,0:21:27.78,0:21:29.20,EN,,0,0,0,,So I'm not going to tell you anything about that,\nDialogue: 0,0:21:29.39,0:21:33.15,EN,,0,0,0,,that has to do with event-driven simulations and getting them started,\nDialogue: 0,0:21:34.59,0:21:36.00,EN,,0,0,0,,which takes a little bit of thinking.\nDialogue: 0,0:21:36.95,0:21:39.40,EN,,0,0,0,,And finally, I'm going to define a thing called the dispatcher,\nDialogue: 0,0:21:39.96,0:21:43.58,EN,,0,0,0,,which is a way of passing a message to a wire,\nDialogue: 0,0:21:45.37,0:21:48.65,EN,,0,0,0,,which is going to be used to extract from it various information,\nDialogue: 0,0:21:49.07,0:21:51.48,EN,,0,0,0,,like what is the current signal value?\nDialogue: 0,0:21:53.82,0:21:55.66,EN,,0,0,0,,What is the method of setting your signal?\nDialogue: 0,0:21:57.18,0:21:58.28,EN,,0,0,0,,I want to get that out of it.\nDialogue: 0,0:22:00.10,0:22:02.60,EN,,0,0,0,,How do I--how do I add another action procedure?\nDialogue: 0,0:22:05.51,0:22:09.36,EN,,0,0,0,,And I'm going to return that dispatch, that procedure as a value.\nDialogue: 0,0:22:09.94,0:22:11.87,EN,,0,0,0,,So the wire that I've constructed\nDialogue: 0,0:22:12.00,0:22:13.55,EN,,0,0,0,,is a message accepting object\nDialogue: 0,0:22:14.25,0:22:16.01,EN,,0,0,0,,which accepts a message like, like\nDialogue: 0,0:22:16.44,0:22:18.36,EN,,0,0,0,,what's your method of adding action procedures?\nDialogue: 0,0:22:19.92,0:22:21.00,EN,,0,0,0,,That it'll give me a procedure,\nDialogue: 0,0:22:21.64,0:22:23.05,EN,,0,0,0,,which is the add action procedure,\nDialogue: 0,0:22:23.07,0:22:26.54,EN,,0,0,0,,which I can then apply to an action procedure\nDialogue: 0,0:22:27.05,0:22:29.01,EN,,0,0,0,,to create another action procedure in the wire.\nDialogue: 0,0:22:31.62,0:22:32.82,EN,,0,0,0,,So that's a permission.\nDialogue: 0,0:22:33.20,0:22:36.08,EN,,0,0,0,,So it's given me permission to change your action procedures.\nDialogue: 0,0:22:37.82,0:22:40.16,EN,,0,0,0,,And in fact, you can see that over here.\nDialogue: 0,0:22:41.71,0:22:42.32,EN,,0,0,0,,Next slide.\nDialogue: 0,0:22:43.53,0:22:43.82,EN,,0,0,0,,Ah.\nDialogue: 0,0:22:47.76,0:22:49.12,EN,,0,0,0,,This is nothing very interesting.\nDialogue: 0,0:22:49.12,0:22:50.65,EN,,0,0,0,,The call each of the action procedures\nDialogue: 0,0:22:50.89,0:22:52.57,EN,,0,0,0,,is just a CDRing down a list.\nDialogue: 0,0:22:52.73,0:22:54.60,EN,,0,0,0,,And I'm not going to even talk about that anymore.\nDialogue: 0,0:22:54.99,0:22:56.25,EN,,0,0,0,,We're too advanced for that.\nDialogue: 0,0:22:57.56,0:23:00.67,EN,,0,0,0,,However, if I want to get a signal from a wire,\nDialogue: 0,0:23:01.02,0:23:02.54,EN,,0,0,0,,I ask the wire-- which is,\nDialogue: 0,0:23:02.54,0:23:03.09,EN,,0,0,0,,what is the wire?\nDialogue: 0,0:23:03.09,0:23:05.40,EN,,0,0,0,,The wire is the dispatch returned by creating the wire.\nDialogue: 0,0:23:05.86,0:23:06.48,EN,,0,0,0,,It's a procedure.\nDialogue: 0,0:23:06.83,0:23:12.27,EN,,0,0,0,,I call that dispatch on the message get-signal.\nDialogue: 0,0:23:12.91,0:23:15.40,EN,,0,0,0,,And what I should expect to get is a method of getting a signal.\nDialogue: 0,0:23:16.90,0:23:17.96,EN,,0,0,0,,Or actually, I get the signal.\nDialogue: 0,0:23:19.22,0:23:20.52,EN,,0,0,0,,If I want to set a signal,\nDialogue: 0,0:23:22.65,0:23:23.96,EN,,0,0,0,,I want to change a signal,\nDialogue: 0,0:23:24.51,0:23:26.76,EN,,0,0,0,,then what I'm going to do\nDialogue: 0,0:23:26.92,0:23:29.69,EN,,0,0,0,,is take a wire as an argument and a new value for the signal,\nDialogue: 0,0:23:30.01,0:23:32.43,EN,,0,0,0,,I would ask the wire for permission to set the signal\nDialogue: 0,0:23:32.84,0:23:37.61,EN,,0,0,0,,and use that permission, which is a procedure, on the new value.\nDialogue: 0,0:23:38.70,0:23:40.51,EN,,0,0,0,,And if we go back to the overhead here,\nDialogue: 0,0:23:41.64,0:23:43.24,EN,,0,0,0,,Okay, thank you,\nDialogue: 0,0:23:44.20,0:23:45.63,EN,,0,0,0,,we go back to the overhead here,\nDialogue: 0,0:23:45.92,0:23:48.75,EN,,0,0,0,,we see that the method-- if I ask for the method of setting the signal,\nDialogue: 0,0:23:49.34,0:23:50.44,EN,,0,0,0,,that's over here,\nDialogue: 0,0:23:52.25,0:23:55.69,EN,,0,0,0,,it's set-my-signal, a procedure that's defined inside the wire,\nDialogue: 0,0:23:56.25,0:23:57.69,EN,,0,0,0,,which if we look over here\nDialogue: 0,0:23:58.72,0:23:59.74,EN,,0,0,0,,is the thing that says\nDialogue: 0,0:24:00.43,0:24:02.68,EN,,0,0,0,,set my internal value called the signal,\nDialogue: 0,0:24:02.73,0:24:05.50,EN,,0,0,0,,my internal variable, which is the signal,\nDialogue: 0,0:24:07.61,0:24:10.03,EN,,0,0,0,,to the new value, which is passed to me as an argument,\nDialogue: 0,0:24:10.78,0:24:13.01,EN,,0,0,0,,and then call each of the action procedures waking them up.\nDialogue: 0,0:24:16.34,0:24:16.99,EN,,0,0,0,,Very simple.\nDialogue: 0,0:24:19.24,0:24:20.76,EN,,0,0,0,,Ok, Going back to that slide,\nDialogue: 0,0:24:22.48,0:24:24.32,EN,,0,0,0,,we also have the one last thing--\nDialogue: 0,0:24:24.36,0:24:27.31,EN,,0,0,0,,which I suppose now you can easily work out for yourself--\nDialogue: 0,0:24:27.77,0:24:29.15,EN,,0,0,0,,is the way you add an action.\nDialogue: 0,0:24:30.10,0:24:35.18,EN,,0,0,0,,You take a wire--a wire and an action procedure.\nDialogue: 0,0:24:36.47,0:24:39.31,EN,,0,0,0,,And I ask the wire for permission to add an action.\nDialogue: 0,0:24:40.05,0:24:44.22,EN,,0,0,0,,Getting that permission, I use that permission to give it an action procedure.\nDialogue: 0,0:24:45.84,0:24:47.08,EN,,0,0,0,,So that's a real object.\nDialogue: 0,0:24:48.57,0:24:50.32,EN,,0,0,0,,There's a few more details about this.\nDialogue: 0,0:24:52.46,0:24:58.39,EN,,0,0,0,,For example, how am I going to control this thing?\nDialogue: 0,0:24:58.39,0:24:59.69,EN,,0,0,0,,How do I do these delays?\nDialogue: 0,0:25:00.99,0:25:02.54,EN,,0,0,0,,Okay? Let's look at that for a second.\nDialogue: 0,0:25:05.50,0:25:07.98,EN,,0,0,0,,The next one here.\nDialogue: 0,0:25:08.36,0:25:08.88,EN,,0,0,0,,Let's see.\nDialogue: 0,0:25:09.57,0:25:14.17,EN,,0,0,0,,We know when we looked at the and-gate or the not-gate\nDialogue: 0,0:25:15.31,0:25:17.00,EN,,0,0,0,,that when a signal changed on the input,\nDialogue: 0,0:25:17.24,0:25:18.19,EN,,0,0,0,,there was a delay.\nDialogue: 0,0:25:18.77,0:25:21.24,EN,,0,0,0,,And then it was going to call the procedure,\nDialogue: 0,0:25:21.63,0:25:23.00,EN,,0,0,0,,which was going to change the output.\nDialogue: 0,0:25:26.04,0:25:27.92,EN,,0,0,0,,Well, how are we going to do this?\nDialogue: 0,0:25:28.12,0:25:29.92,EN,,0,0,0,,We're going to make up some mechanism,\nDialogue: 0,0:25:30.30,0:25:32.00,EN,,0,0,0,,a fairly complicated mechanism at that,\nDialogue: 0,0:25:32.33,0:25:33.76,EN,,0,0,0,,which we're going to have to be very careful about.\nDialogue: 0,0:25:34.72,0:25:37.23,EN,,0,0,0,,But after a delay, we're going to do an action.\nDialogue: 0,0:25:37.39,0:25:38.12,EN,,0,0,0,,A delay is a number,\nDialogue: 0,0:25:38.16,0:25:39.23,EN,,0,0,0,,and an action is a procedure.\nDialogue: 0,0:25:40.59,0:25:43.72,EN,,0,0,0,,What that's going to be is they're going to have a special structure called an agenda,\nDialogue: 0,0:25:45.50,0:25:48.80,EN,,0,0,0,,which is a thing that organizes time and actions.\nDialogue: 0,0:25:49.51,0:25:50.88,EN,,0,0,0,,And we're going to see that in a while.\nDialogue: 0,0:25:50.88,0:25:52.54,EN,,0,0,0,,I don't want to get into that right now.\nDialogue: 0,0:25:53.07,0:25:58.28,EN,,0,0,0,,But the agenda has a moment at which--at which something happens.\nDialogue: 0,0:25:59.13,0:26:02.46,EN,,0,0,0,,We're setting up for later at some moment,\nDialogue: 0,0:26:02.51,0:26:05.68,EN,,0,0,0,,which is the sum of the time, which is the delay time plus the current time,\nDialogue: 0,0:26:05.69,0:26:07.13,EN,,0,0,0,,which the agenda thinks is now.\nDialogue: 0,0:26:09.02,0:26:10.56,EN,,0,0,0,,We're going to set up to do this action,\nDialogue: 0,0:26:11.02,0:26:12.40,EN,,0,0,0,,and add that to the agenda.\nDialogue: 0,0:26:15.28,0:26:18.03,EN,,0,0,0,,And the way this machine will now run is very simple.\nDialogue: 0,0:26:18.66,0:26:21.48,EN,,0,0,0,,We have a thing called propagate, which is the way things run.\nDialogue: 0,0:26:22.71,0:26:25.95,EN,,0,0,0,,If the agenda is empty, we're done--if there's nothing more to be done.\nDialogue: 0,0:26:27.44,0:26:28.16,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:26:29.76,0:26:31.53,EN,,0,0,0,,we're going to take the first item off the agenda,\nDialogue: 0,0:26:31.71,0:26:33.34,EN,,0,0,0,,and that's a procedure of no arguments.\nDialogue: 0,0:26:34.20,0:26:36.03,EN,,0,0,0,,So that we're going to see extra parentheses here.\nDialogue: 0,0:26:36.03,0:26:37.85,EN,,0,0,0,,We call that on no arguments.\nDialogue: 0,0:26:39.19,0:26:40.17,EN,,0,0,0,,That takes the action.\nDialogue: 0,0:26:42.20,0:26:44.17,EN,,0,0,0,,Then we remove that first item from the agenda,\nDialogue: 0,0:26:44.59,0:26:46.14,EN,,0,0,0,,and we go around the propagation loop.\nDialogue: 0,0:26:48.91,0:26:50.75,EN,,0,0,0,,So that's the overall structure of this thing.\nDialogue: 0,0:26:53.38,0:26:55.93,EN,,0,0,0,,Now, there's a, a few other things we can look at.\nDialogue: 0,0:26:57.43,0:27:00.01,EN,,0,0,0,,And then we're going to look into the agenda a little while from now.\nDialogue: 0,0:27:00.57,0:27:01.55,EN,,0,0,0,,Now the overhead again.\nDialogue: 0,0:27:02.80,0:27:04.67,EN,,0,0,0,,Well, in order to set this thing going,\nDialogue: 0,0:27:04.67,0:27:07.41,EN,,0,0,0,,I just want to show you some behavior out of this simulator.\nDialogue: 0,0:27:07.85,0:27:09.93,EN,,0,0,0,,By the way, you may think this simulator is very simple,\nDialogue: 0,0:27:10.40,0:27:12.01,EN,,0,0,0,,and probably too simple to be useful.\nDialogue: 0,0:27:12.57,0:27:13.76,EN,,0,0,0,,The fact of the matter is\nDialogue: 0,0:27:13.98,0:27:15.39,EN,,0,0,0,,that this simulator has been used\nDialogue: 0,0:27:15.72,0:27:17.44,EN,,0,0,0,,to manufacture a fairly large computer.\nDialogue: 0,0:27:18.68,0:27:20.64,EN,,0,0,0,,So this is a real live example.\nDialogue: 0,0:27:22.36,0:27:24.06,EN,,0,0,0,,Actually, not exactly this simulator，\nDialogue: 0,0:27:24.06,0:27:25.39,EN,,0,0,0,,because I'll tell you the difference.\nDialogue: 0,0:27:25.84,0:27:28.70,EN,,0,0,0,,The difference is that there were many more different kinds of primitives.\nDialogue: 0,0:27:29.82,0:27:32.22,EN,,0,0,0,,There's not just the word inverter or and-gate.\nDialogue: 0,0:27:33.20,0:27:35.72,EN,,0,0,0,,There were things like edge-triggered,\nDialogue: 0,0:27:36.25,0:27:39.88,EN,,0,0,0,,flip-flops, and latches\nDialogue: 0,0:27:40.70,0:27:44.52,EN,,0,0,0,,transparent latches, and adders, and things like that.\nDialogue: 0,0:27:45.17,0:27:47.31,EN,,0,0,0,,And the difficulty with that\nDialogue: 0,0:27:47.45,0:27:50.86,EN,,0,0,0,,is there's pages and pages of the definitions of all these primitives\nDialogue: 0,0:27:51.20,0:27:52.89,EN,,0,0,0,,with numbers like LS04.\nDialogue: 0,0:27:54.69,0:27:56.74,EN,,0,0,0,,And then there's many more parameters for them.\nDialogue: 0,0:27:56.74,0:27:57.98,EN,,0,0,0,,It's not just one delay.\nDialogue: 0,0:27:58.48,0:28:00.81,EN,,0,0,0,,There's things like set up times and hold times and all that.\nDialogue: 0,0:28:01.22,0:28:03.40,EN,,0,0,0,,But with the exception of that part of the complexity,\nDialogue: 0,0:28:03.82,0:28:08.20,EN,,0,0,0,,the structure of the simulator that we use for building a real computer,\nDialogue: 0,0:28:09.08,0:28:12.89,EN,,0,0,0,,that works is exactly what you're seeing here.\nDialogue: 0,0:28:15.11,0:28:19.27,EN,,0,0,0,,Well in any case, what we have here is a few simple things.\nDialogue: 0,0:28:19.27,0:28:22.59,EN,,0,0,0,,Like, there's inverter delays being set up and making a new agenda.\nDialogue: 0,0:28:23.03,0:28:25.52,EN,,0,0,0,,And then we can make some inputs.\nDialogue: 0,0:28:26.03,0:28:29.18,EN,,0,0,0,,Ok? There's input-1, input-2, a sum and a carry, which are wires.\nDialogue: 0,0:28:29.46,0:28:31.88,EN,,0,0,0,,I'm going to put a special kind of object called a probe\nDialogue: 0,0:28:32.51,0:28:34.64,EN,,0,0,0,,onto, onto some of the wires,\nDialogue: 0,0:28:34.97,0:28:36.24,EN,,0,0,0,,onto sum and onto carry.\nDialogue: 0,0:28:37.23,0:28:40.56,EN,,0,0,0,,A probe is a, can object that has the property\nDialogue: 0,0:28:40.70,0:28:43.60,EN,,0,0,0,,that when you change a wire it's attached to,\nDialogue: 0,0:28:43.72,0:28:44.83,EN,,0,0,0,,it types out a message.\nDialogue: 0,0:28:46.12,0:28:46.92,EN,,0,0,0,,It's an easy thing to do.\nDialogue: 0,0:28:48.44,0:28:49.52,EN,,0,0,0,,And then once we have that,\nDialogue: 0,0:28:49.55,0:28:51.45,EN,,0,0,0,,of course, then when you put the probe on,\nDialogue: 0,0:28:51.45,0:28:52.41,EN,,0,0,0,,the first thing it does, it says,\nDialogue: 0,0:28:52.67,0:28:56.01,EN,,0,0,0,,the current value of the sum at time 0 is 0\nDialogue: 0,0:28:57.29,0:28:58.43,EN,,0,0,0,,And because I just noticed it.\nDialogue: 0,0:28:59.40,0:29:04.75,EN,,0,0,0,,And the value of the carry at time 0, this is the time, is 0.\nDialogue: 0,0:29:06.04,0:29:09.28,EN,,0,0,0,,And then we go off and we build some structure.\nDialogue: 0,0:29:09.62,0:29:12.28,EN,,0,0,0,,Like, we can build a structure here that says\nDialogue: 0,0:29:14.06,0:29:18.20,EN,,0,0,0,,you have a half-adder on input-1, input-2, sum, and carry.\nDialogue: 0,0:29:18.42,0:29:20.42,EN,,0,0,0,,And we're going to set the signal on input-1 to 1.\nDialogue: 0,0:29:20.62,0:29:21.72,EN,,0,0,0,,We do some propagation.\nDialogue: 0,0:29:21.88,0:29:22.84,EN,,0,0,0,,At time 8,\nDialogue: 0,0:29:23.90,0:29:26.12,EN,,0,0,0,,which you could see going through this thing if you wanted to,\nDialogue: 0,0:29:26.52,0:29:29.20,EN,,0,0,0,,the new value of sum became 1.\nDialogue: 0,0:29:29.52,0:29:30.44,EN,,0,0,0,,And the thing says I'm done.\nDialogue: 0,0:29:31.16,0:29:32.25,EN,,0,0,0,,That wasn't very interesting.\nDialogue: 0,0:29:32.63,0:29:33.90,EN,,0,0,0,,But we can send it some more signals.\nDialogue: 0,0:29:34.06,0:29:36.73,EN,,0,0,0,,Like, we set-signal on input-2 to be one.\nDialogue: 0,0:29:36.89,0:29:38.09,EN,,0,0,0,,And at that time if we propagate,\nDialogue: 0,0:29:38.36,0:29:39.95,EN,,0,0,0,,then it carried at 11,\nDialogue: 0,0:29:40.12,0:29:41.42,EN,,0,0,0,,the carry becomes 1,\nDialogue: 0,0:29:41.55,0:29:44.19,EN,,0,0,0,,and at 16, the sum's new value becomes 0.\nDialogue: 0,0:29:45.39,0:29:48.99,EN,,0,0,0,,And you might want to work out that, if you like, about the digital circuitry.\nDialogue: 0,0:29:48.99,0:29:50.12,EN,,0,0,0,,It's true, and it works.\nDialogue: 0,0:29:50.62,0:29:51.53,EN,,0,0,0,,And it's not very interesting.\nDialogue: 0,0:29:51.53,0:29:54.12,EN,,0,0,0,,But that's the kind of behavior we get out of this thing.\nDialogue: 0,0:30:01.83,0:30:03.29,EN,,0,0,0,,So what I've shown you right now\nDialogue: 0,0:30:03.48,0:30:05.52,EN,,0,0,0,,is a large-scale picture,\nDialogue: 0,0:30:06.60,0:30:08.56,EN,,0,0,0,,how you, at a bigger, big scale,\nDialogue: 0,0:30:08.72,0:30:12.04,EN,,0,0,0,,you implement an event-driven simulation of some sort.\nDialogue: 0,0:30:13.29,0:30:14.56,EN,,0,0,0,,And how you might organize it\nDialogue: 0,0:30:14.88,0:30:16.70,EN,,0,0,0,,to have nice hierarchical structure\nDialogue: 0,0:30:16.99,0:30:21.00,EN,,0,0,0,,allowing you to build abstract boxes that you can instantiate.\nDialogue: 0,0:30:21.56,0:30:24.96,EN,,0,0,0,,But I haven't told you any of the details about how this agenda and things like that work.\nDialogue: 0,0:30:25.78,0:30:26.54,EN,,0,0,0,,That we'll do next.\nDialogue: 0,0:30:28.63,0:30:32.94,EN,,0,0,0,,And that's going to involve change and mutation of data and things like that.\nDialogue: 0,0:30:34.31,0:30:35.86,EN,,0,0,0,,Are there any questions now, before I go on?\nDialogue: 0,0:30:47.16,0:30:48.24,EN,,0,0,0,,Thank you. Let's take a break.\nDialogue: 0,0:30:50.24,0:31:00.62,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:31:28.94,0:31:35.06,EN,,0,0,0,,Well, we've been making a simulation.\nDialogue: 0,0:31:35.39,0:31:37.77,EN,,0,0,0,,And the simulation is an event-driven simulation\nDialogue: 0,0:31:38.17,0:31:42.75,EN,,0,0,0,,where the objects in the world are the objects in the computer.\nDialogue: 0,0:31:43.92,0:31:47.28,EN,,0,0,0,,And the changes of state that are happening in the world in time\nDialogue: 0,0:31:47.98,0:31:50.83,EN,,0,0,0,,are organized to be time in the computer,\nDialogue: 0,0:31:52.99,0:31:56.04,EN,,0,0,0,,so that if something happens after something else in the world,\nDialogue: 0,0:31:56.46,0:31:57.96,EN,,0,0,0,,then we have it happen after,\nDialogue: 0,0:31:58.89,0:32:02.25,EN,,0,0,0,,after the corresponding events happen in the same order in the computer.\nDialogue: 0,0:32:04.42,0:32:07.16,EN,,0,0,0,,That's where we have assignments, when we make that alignment.\nDialogue: 0,0:32:08.22,0:32:11.21,EN,,0,0,0,,Right now I want to show you a way of organizing time,\nDialogue: 0,0:32:11.80,0:32:14.86,EN,,0,0,0,,which is an agenda or priority queue, it's sometimes called.\nDialogue: 0,0:32:16.04,0:32:18.57,EN,,0,0,0,,We'll do some--we'll do a little bit of just understanding\nDialogue: 0,0:32:18.62,0:32:21.00,EN,,0,0,0,,what are the things we need to be able to do to make agendas.\nDialogue: 0,0:32:28.33,0:32:31.28,EN,,0,0,0,,And so we're going to have--and so right now over here, I'm going to write down a bunch\nDialogue: 0,0:32:31.39,0:32:33.88,EN,,0,0,0,,of primitive operations for manipulating agendas.\nDialogue: 0,0:32:35.96,0:32:37.95,EN,,0,0,0,,I'm not going to show you the code for them\nDialogue: 0,0:32:38.14,0:32:39.58,EN,,0,0,0,,because they're all very simple,\nDialogue: 0,0:32:40.32,0:32:42.60,EN,,0,0,0,,Iand you've got listings of all that anyway.\nDialogue: 0,0:32:43.68,0:32:44.38,EN,,0,0,0,,So what do we have?\nDialogue: 0,0:32:44.38,0:32:53.50,EN,,0,0,0,,We have things like make-agenda which produces a new agenda.\nDialogue: 0,0:32:57.36,0:33:01.77,EN,,0,0,0,,We can ask--we get the current-time of an agenda,\nDialogue: 0,0:33:07.47,0:33:12.80,EN,,0,0,0,,of an agenda, which gives me a number, a time.\nDialogue: 0,0:33:16.99,0:33:21.37,EN,,0,0,0,,We can get--we can ask whether an agenda is empty, empty-agenda.\nDialogue: 0,0:33:30.20,0:33:32.57,EN,,0,0,0,,And that produces either a true or a false.\nDialogue: 0,0:33:42.72,0:33:44.72,EN,,0,0,0,,We can add an object to an agenda.\nDialogue: 0,0:33:52.71,0:33:56.06,EN,,0,0,0,,Actually, what we add to an agenda is an operation--an action to be done.\nDialogue: 0,0:33:56.91,0:33:58.14,EN,,0,0,0,,And that takes a time,\nDialogue: 0,0:33:59.63,0:34:00.56,EN,,0,0,0,,the action itself,\nDialogue: 0,0:34:02.86,0:34:04.64,EN,,0,0,0,,and the agenda I want to add it to.\nDialogue: 0,0:34:07.58,0:34:10.25,EN,,0,0,0,,OK? That inserts it in the appropriate place in the agenda.\nDialogue: 0,0:34:10.71,0:34:12.73,EN,,0,0,0,,I can get the first item off an agenda,\nDialogue: 0,0:34:14.24,0:34:15.39,EN,,0,0,0,,the first thing I have to do,\nDialogue: 0,0:34:21.84,0:34:23.84,EN,,0,0,0,,which is going to give me an action.\nDialogue: 0,0:34:26.46,0:34:28.73,EN,,0,0,0,,And I can remove the first item from an agenda.\nDialogue: 0,0:34:29.54,0:34:31.16,EN,,0,0,0,,That's what I have to be able to do with agendas.\nDialogue: 0,0:34:31.40,0:34:33.02,EN,,0,0,0,,That is a big complicated mess.\nDialogue: 0,0:34:42.53,0:34:43.36,EN,,0,0,0,,From an agenda.\nDialogue: 0,0:34:45.98,0:34:49.85,EN,,0,0,0,,Well, let's see how we can organize this thing as a data structure a bit.\nDialogue: 0,0:34:52.96,0:34:56.04,EN,,0,0,0,,Well, an agenda is going to be some kind of list.\nDialogue: 0,0:34:58.43,0:35:01.20,EN,,0,0,0,,And it's going to be a list that I'm going to have to be able to modify.\nDialogue: 0,0:35:01.57,0:35:04.03,EN,,0,0,0,,So we have to talk about modifying of lists,\nDialogue: 0,0:35:05.80,0:35:06.89,EN,,0,0,0,,because I'm going to add things to it,\nDialogue: 0,0:35:07.77,0:35:10.27,EN,,0,0,0,,and delete things from it, and things like that.\nDialogue: 0,0:35:11.07,0:35:12.51,EN,,0,0,0,,It's organized by time.\nDialogue: 0,0:35:13.82,0:35:15.57,EN,,0,0,0,,It's probably good to keep it in sorted order.\nDialogue: 0,0:35:18.33,0:35:20.88,EN,,0,0,0,,But sometimes there are lots of things that happen at the same time\nDialogue: 0,0:35:22.04,0:35:23.42,EN,,0,0,0,,approximate same time.\nDialogue: 0,0:35:23.80,0:35:24.72,EN,,0,0,0,,What I have to do is say,\nDialogue: 0,0:35:24.91,0:35:27.52,EN,,0,0,0,,group things by the time at which they're supposed to happen.\nDialogue: 0,0:35:29.04,0:35:31.61,EN,,0,0,0,,So I'm going to make an agenda as a list of segments.\nDialogue: 0,0:35:32.78,0:35:35.69,EN,,0,0,0,,And so I'm going to draw you a data structure for an agenda,\nDialogue: 0,0:35:36.68,0:35:37.93,EN,,0,0,0,,a perfectly reasonable one.\nDialogue: 0,0:35:39.62,0:35:40.49,EN,,0,0,0,,Here's an agenda.\nDialogue: 0,0:35:41.11,0:35:42.87,EN,,0,0,0,,It's a thing that begins with a name.\nDialogue: 0,0:35:47.85,0:35:50.19,EN,,0,0,0,,I'm going to do it right now out of list structure.\nDialogue: 0,0:35:52.60,0:35:53.39,EN,,0,0,0,,It's got a header.\nDialogue: 0,0:35:54.14,0:35:55.44,EN,,0,0,0,,There's a reason for the header.\nDialogue: 0,0:35:55.84,0:35:57.63,EN,,0,0,0,,We're going to see the reason soon.\nDialogue: 0,0:36:00.68,0:36:03.40,EN,,0,0,0,,And it will have a segment. We will have--\nDialogue: 0,0:36:03.96,0:36:05.62,EN,,0,0,0,,It will have--it will be a list of segments.\nDialogue: 0,0:36:08.31,0:36:10.54,EN,,0,0,0,,Supposing this agenda has two segments,\nDialogue: 0,0:36:11.58,0:36:15.07,EN,,0,0,0,,OK, they're the car's-- successive car's of this list.\nDialogue: 0,0:36:16.41,0:36:20.57,EN,,0,0,0,,Each segment is going to have a time--\nDialogue: 0,0:36:24.20,0:36:26.64,EN,,0,0,0,,say for example, 10--\nDialogue: 0,0:36:26.83,0:36:30.51,EN,,0,0,0,,that says that the things that happen in this segment are at time 10.\nDialogue: 0,0:36:33.16,0:36:36.52,EN,,0,0,0,,And what I'm going to have in here is another data structure\nDialogue: 0,0:36:36.56,0:36:38.01,EN,,0,0,0,,which I'm not going to describe,\nDialogue: 0,0:36:38.49,0:36:41.08,EN,,0,0,0,,which is a queue of things to do at time 10.\nDialogue: 0,0:36:42.24,0:36:43.33,EN,,0,0,0,,It's a queue.\nDialogue: 0,0:36:43.33,0:36:44.70,EN,,0,0,0,,And we'll talk about that in a second.\nDialogue: 0,0:36:45.20,0:36:50.35,EN,,0,0,0,,But abstractly, the queue is just a list of things to do at a particular time.\nDialogue: 0,0:36:50.40,0:36:52.04,EN,,0,0,0,,And I can add things to a queue.\nDialogue: 0,0:36:53.10,0:36:53.80,EN,,0,0,0,,This is a queue.\nDialogue: 0,0:36:56.14,0:36:59.11,EN,,0,0,0,,There's a time, there's a segment.\nDialogue: 0,0:37:03.23,0:37:06.36,EN,,0,0,0,,Now, I may have another segment in this agenda.\nDialogue: 0,0:37:08.94,0:37:11.20,EN,,0,0,0,,Supposing this is stuff that happens at time 30.\nDialogue: 0,0:37:13.50,0:37:15.92,EN,,0,0,0,,It has, of course, another queue\nDialogue: 0,0:37:16.92,0:37:20.24,EN,,0,0,0,,of things that are queued up to be done at time 30.\nDialogue: 0,0:37:23.21,0:37:25.66,EN,,0,0,0,,Well, there are various things I have to be able to do to an agenda.\nDialogue: 0,0:37:27.09,0:37:29.20,EN,,0,0,0,,Supposing I want to add to an agenda\nDialogue: 0,0:37:29.47,0:37:31.61,EN,,0,0,0,,another thing to be done at time 10.\nDialogue: 0,0:37:33.03,0:37:34.16,EN,,0,0,0,,Well, that's not very hard.\nDialogue: 0,0:37:34.70,0:37:38.65,EN,,0,0,0,,I'm going to walk down here, looking for the segment of time 10.\nDialogue: 0,0:37:39.73,0:37:42.14,EN,,0,0,0,,It is possible that there is no segment of time 10.\nDialogue: 0,0:37:42.93,0:37:44.56,EN,,0,0,0,,We'll cover that case in a second.\nDialogue: 0,0:37:45.42,0:37:47.56,EN,,0,0,0,,But if I find a segment of time 10,\nDialogue: 0,0:37:47.87,0:37:50.43,EN,,0,0,0,,then if I want to add another thing to be done at time 10,\nDialogue: 0,0:37:50.56,0:37:52.16,EN,,0,0,0,,I just increase that queue--\nDialogue: 0,0:37:53.85,0:37:56.22,EN,,0,0,0,,\"just increase\" isn't such an obvious idea.\nDialogue: 0,0:37:56.57,0:37:59.26,EN,,0,0,0,,But I increase the things to be done at that time.\nDialogue: 0,0:38:01.43,0:38:04.25,EN,,0,0,0,,Now, supposing I want to add something to be done at time 20.\nDialogue: 0,0:38:05.31,0:38:07.90,EN,,0,0,0,,There is no segment for time 20.\nDialogue: 0,0:38:08.99,0:38:10.64,EN,,0,0,0,,I'm going to have to create a new segment.\nDialogue: 0,0:38:11.34,0:38:15.64,EN,,0,0,0,,I want my time 20 segment to exist between time 10 and time 30.\nDialogue: 0,0:38:17.61,0:38:19.32,EN,,0,0,0,,Well, that takes a little work.\nDialogue: 0,0:38:20.17,0:38:21.52,EN,,0,0,0,,I'm going to have to do a CONS.\nDialogue: 0,0:38:24.26,0:38:29.94,EN,,0,0,0,,I'm going to have to make a new element of the agenda list--list of segments.\nDialogue: 0,0:38:33.60,0:38:34.81,EN,,0,0,0,,I'm going to have to change.\nDialogue: 0,0:38:35.40,0:38:36.30,EN,,0,0,0,,Here's change.\nDialogue: 0,0:38:37.54,0:38:42.80,EN,,0,0,0,,I'm going to have to change the CDR of the CDR of the agenda\nDialogue: 0,0:38:44.88,0:38:49.45,EN,,0,0,0,,point that a new CONS of the new segment\nDialogue: 0,0:38:50.11,0:38:54.65,EN,,0,0,0,,and the CDR of the CDR of the CDR of the agenda, the CD-D-D-DR.\nDialogue: 0,0:38:57.18,0:39:01.88,EN,,0,0,0,,And this is going to have a new segment now of time 20\nDialogue: 0,0:39:02.30,0:39:03.72,EN,,0,0,0,,with its own queue,\nDialogue: 0,0:39:04.84,0:39:06.29,EN,,0,0,0,,which now has one element in it.\nDialogue: 0,0:39:10.73,0:39:12.52,EN,,0,0,0,,If I wanted to add something at the end,\nDialogue: 0,0:39:12.54,0:39:15.87,EN,,0,0,0,,I'm going to have to replace the CDR of this,\nDialogue: 0,0:39:16.99,0:39:19.21,EN,,0,0,0,,of this list with something.\nDialogue: 0,0:39:20.59,0:39:23.31,EN,,0,0,0,,We're have to change that piece of data structure.\nDialogue: 0,0:39:24.04,0:39:25.79,EN,,0,0,0,,So I'm going to need new primitives for doing this.\nDialogue: 0,0:39:27.21,0:39:28.62,EN,,0,0,0,,But I'm just showing you why I need them.\nDialogue: 0,0:39:29.44,0:39:33.88,EN,,0,0,0,,And finally, if I wanted to add a thing to be done at time 5,\nDialogue: 0,0:39:37.12,0:39:39.20,EN,,0,0,0,,I'm going to have to change this one,\nDialogue: 0,0:39:40.81,0:39:42.12,EN,,0,0,0,,because I'm going to have to add it in over here,\nDialogue: 0,0:39:43.29,0:39:46.22,EN,,0,0,0,,which is why I planned ahead and had a header cell,\nDialogue: 0,0:39:47.56,0:39:48.59,EN,,0,0,0,,which has a place.\nDialogue: 0,0:39:49.40,0:39:52.11,EN,,0,0,0,,If I'm going to change things, I have to have places for the change.\nDialogue: 0,0:39:53.88,0:39:56.56,EN,,0,0,0,,I have to have a place to make the change.\nDialogue: 0,0:39:58.60,0:40:02.54,EN,,0,0,0,,If I remove things from the agenda, that's not so hard.\nDialogue: 0,0:40:02.54,0:40:04.62,EN,,0,0,0,,Removing them from the beginning is pretty easy,\nDialogue: 0,0:40:04.92,0:40:06.14,EN,,0,0,0,,which is the only case I have.\nDialogue: 0,0:40:06.49,0:40:10.19,EN,,0,0,0,,I can go looking for the first, the first segment.\nDialogue: 0,0:40:11.22,0:40:14.00,EN,,0,0,0,,I see if it has a non-empty queue.\nDialogue: 0,0:40:14.81,0:40:16.17,EN,,0,0,0,,If it has a non-empty queue,\nDialogue: 0,0:40:16.32,0:40:18.62,EN,,0,0,0,,well, I'm going to delete one element from the queue\nDialogue: 0,0:40:19.21,0:40:19.74,EN,,0,0,0,,like that.\nDialogue: 0,0:40:20.10,0:40:21.92,EN,,0,0,0,,If the queue ever becomes empty,\nDialogue: 0,0:40:22.64,0:40:24.22,EN,,0,0,0,,then I have to delete the whole segment.\nDialogue: 0,0:40:24.22,0:40:26.49,EN,,0,0,0,,And then this, this changes to point to here.\nDialogue: 0,0:40:28.22,0:40:31.08,EN,,0,0,0,,So it's quite a complicated data structure manipulation going on,\nDialogue: 0,0:40:32.25,0:40:35.37,EN,,0,0,0,,the details of which are not really very exciting.\nDialogue: 0,0:40:36.44,0:40:38.48,EN,,0,0,0,,Now, let's talk about queues.\nDialogue: 0,0:40:38.92,0:40:39.76,EN,,0,0,0,,They're similar.\nDialogue: 0,0:40:41.16,0:40:43.52,EN,,0,0,0,,Because each of these agendas has a queue in it.\nDialogue: 0,0:40:44.34,0:40:45.02,EN,,0,0,0,,What's a queue?\nDialogue: 0,0:40:49.47,0:40:51.85,EN,,0,0,0,,A queue is going to have the following primitive operations.\nDialogue: 0,0:40:52.78,0:41:02.17,EN,,0,0,0,,To make a queue, this gives me a new queue.\nDialogue: 0,0:41:07.77,0:41:17.10,EN,,0,0,0,,I'm going to have to be able to insert into a queue a new item.\nDialogue: 0,0:41:24.51,0:41:28.65,EN,,0,0,0,,I'm going to have to be able to delete from a queue the first item in the queue.\nDialogue: 0,0:41:40.44,0:41:52.04,EN,,0,0,0,,And I want to be able to get the first thing in the queue from some queue.\nDialogue: 0,0:41:53.13,0:41:55.14,EN,,0,0,0,,I also have to be able to test whether a queue is empty.\nDialogue: 0,0:42:07.11,0:42:08.70,EN,,0,0,0,,And when you invent things like this,\nDialogue: 0,0:42:09.02,0:42:10.44,EN,,0,0,0,,I want you to be very careful\nDialogue: 0,0:42:10.64,0:42:14.09,EN,,0,0,0,,to use the kinds of conventions I use for naming things.\nDialogue: 0,0:42:15.12,0:42:19.15,EN,,0,0,0,,Notice that I'm careful to say these change something and that tests it.\nDialogue: 0,0:42:19.87,0:42:21.85,EN,,0,0,0,,And presumably, I did the same thing over here.\nDialogue: 0,0:42:24.65,0:42:26.96,EN,,0,0,0,,OK, and there should be an empty test over here.\nDialogue: 0,0:42:29.24,0:42:30.72,EN,,0,0,0,,OK, well, how would I make a queue?\nDialogue: 0,0:42:31.72,0:42:34.11,EN,,0,0,0,,A queue wants to be something I can add to at the end of,\nDialogue: 0,0:42:35.12,0:42:36.83,EN,,0,0,0,,and pick up the thing at the beginning of.\nDialogue: 0,0:42:37.84,0:42:40.51,EN,,0,0,0,,I should be able to delete from the beginning and add to the end.\nDialogue: 0,0:42:41.23,0:42:43.24,EN,,0,0,0,,Well, I'm going to show you a very simple structure for that.\nDialogue: 0,0:42:43.88,0:42:45.72,EN,,0,0,0,,We can make this out of CONSes as well.\nDialogue: 0,0:42:47.08,0:42:47.79,EN,,0,0,0,,Here's a queue.\nDialogue: 0,0:42:49.91,0:42:52.36,EN,,0,0,0,,It has--it has a queue header,\nDialogue: 0,0:42:53.58,0:42:54.92,EN,,0,0,0,,which contains two parts--\nDialogue: 0,0:42:55.28,0:42:56.25,EN,,0,0,0,,a front pointer\nDialogue: 0,0:42:58.78,0:42:59.82,EN,,0,0,0,,and a rear pointer.\nDialogue: 0,0:43:03.12,0:43:06.33,EN,,0,0,0,,And here I have a queue with two items in it.\nDialogue: 0,0:43:09.13,0:43:12.09,EN,,0,0,0,,The first item, I don't know, it's perhaps a 1.\nDialogue: 0,0:43:12.46,0:43:16.53,EN,,0,0,0,,And the second item, I don't know, let's give it a 2.\nDialogue: 0,0:43:21.40,0:43:23.52,EN,,0,0,0,,The reason why I want two pointers in here,\nDialogue: 0,0:43:24.09,0:43:25.61,EN,,0,0,0,,a front pointer and a rear pointer,\nDialogue: 0,0:43:25.72,0:43:27.10,EN,,0,0,0,,is so I can add to the end\nDialogue: 0,0:43:27.48,0:43:29.45,EN,,0,0,0,,without having to chase down from the beginning.\nDialogue: 0,0:43:31.85,0:43:34.80,EN,,0,0,0,,So for example, if I wanted to add one more item to this queue,\nDialogue: 0,0:43:35.26,0:43:41.02,EN,,0,0,0,,if I want to add on another item to be worried about later,\nDialogue: 0,0:43:41.08,0:43:42.40,EN,,0,0,0,,all I have to do is make a CONS,\nDialogue: 0,0:43:43.47,0:43:46.59,EN,,0,0,0,,which contains that item, say a 3.\nDialogue: 0,0:43:47.53,0:43:51.34,EN,,0,0,0,,That's for inserting 3 into the queue.\nDialogue: 0,0:43:51.52,0:43:53.77,EN,,0,0,0,,Then I have to change this pointer here\nDialogue: 0,0:43:56.94,0:43:58.76,EN,,0,0,0,,Okay? to here.\nDialogue: 0,0:44:00.10,0:44:04.32,EN,,0,0,0,,And I have to change this one to point to the new rear.\nDialogue: 0,0:44:09.12,0:44:12.68,EN,,0,0,0,,If I wish to take the first element of the queue, the first item,\nDialogue: 0,0:44:12.96,0:44:17.12,EN,,0,0,0,,I just go chasing down the front pointer until I find the first one and pick it up.\nDialogue: 0,0:44:18.89,0:44:23.26,EN,,0,0,0,,If I wish to delete the first item from the queue, delete-queue,\nDialogue: 0,0:44:24.14,0:44:26.35,EN,,0,0,0,,all I do is move the front pointer along this way.\nDialogue: 0,0:44:27.71,0:44:29.31,EN,,0,0,0,,The new front of the queue is now this.\nDialogue: 0,0:44:31.70,0:44:33.13,EN,,0,0,0,,So queues are very simple too.\nDialogue: 0,0:44:34.48,0:44:35.76,EN,,0,0,0,,So what you see now\nDialogue: 0,0:44:37.24,0:44:40.83,EN,,0,0,0,,is that I need a certain number of new primitive operations.\nDialogue: 0,0:44:41.48,0:44:42.56,EN,,0,0,0,,And I'm going to give them some names.\nDialogue: 0,0:44:42.99,0:44:46.28,EN,,0,0,0,,And then we're going to look into how they work, and how they're used.\nDialogue: 0,0:44:47.35,0:44:55.04,EN,,0,0,0,,We have set the CAR of some pair,\nDialogue: 0,0:44:55.88,0:44:59.36,EN,,0,0,0,,or a thing produced by CONSing, to a new value.\nDialogue: 0,0:45:02.37,0:45:09.92,EN,,0,0,0,,And set the CDR of a pair to a new value.\nDialogue: 0,0:45:13.02,0:45:14.78,EN,,0,0,0,,And then we're going to look into how they work.\nDialogue: 0,0:45:16.03,0:45:20.51,EN,,0,0,0,,I needed setting CAR over here to delete the first element of the queue.\nDialogue: 0,0:45:20.96,0:45:22.52,EN,,0,0,0,,This is the CAR, and I had to set it.\nDialogue: 0,0:45:23.47,0:45:24.96,EN,,0,0,0,,I had to be able to set the CDR\nDialogue: 0,0:45:25.28,0:45:27.08,EN,,0,0,0,,to be able to move the rear pointer,\nDialogue: 0,0:45:27.21,0:45:28.76,EN,,0,0,0,,or to be able to increment the queue here.\nDialogue: 0,0:45:30.16,0:45:31.60,EN,,0,0,0,,All of the operations I did\nDialogue: 0,0:45:31.90,0:45:35.90,EN,,0,0,0,,were made out of those that I just showed you on the, on the last blackboard.\nDialogue: 0,0:45:38.17,0:45:40.14,EN,,0,0,0,,Good. Let's pause the time, and take a little break then.\nDialogue: 0,0:45:41.24,0:45:52.67,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:46:38.81,0:46:43.53,EN,,0,0,0,,When we originally introduced pairs made out of CONS, made by CONS,\nDialogue: 0,0:46:44.57,0:46:46.80,EN,,0,0,0,,we only said a few axioms about them,\nDialogue: 0,0:46:48.09,0:46:50.76,EN,,0,0,0,,which were of the form-- what were they--\nDialogue: 0,0:46:52.28,0:47:03.64,EN,,0,0,0,,for all X and Y, the CAR of the CONS of X and Y is X\nDialogue: 0,0:47:05.31,0:47:12.92,EN,,0,0,0,,and Y is X and the CDR of the CONS of X and Y is Y.\nDialogue: 0,0:47:14.80,0:47:20.00,EN,,0,0,0,,Now, these say nothing about whether a CONS has an identity like a person.\nDialogue: 0,0:47:21.85,0:47:25.58,EN,,0,0,0,,In fact, all they say is something sort of abstract,\nDialogue: 0,0:47:25.74,0:47:27.95,EN,,0,0,0,,that a CONS is the parts it's made out of.\nDialogue: 0,0:47:29.74,0:47:33.18,EN,,0,0,0,,And of course, two things are made out of the same parts, they're the same,\nDialogue: 0,0:47:33.93,0:47:35.71,EN,,0,0,0,,at least from the point of view of these axioms.\nDialogue: 0,0:47:37.32,0:47:39.21,EN,,0,0,0,,But by introducing assignment--\nDialogue: 0,0:47:39.84,0:47:42.32,EN,,0,0,0,,in fact, mutable data is a kind of assignment,\nDialogue: 0,0:47:42.88,0:47:44.43,EN,,0,0,0,,we have a set CAR and a set CDR--\nDialogue: 0,0:47:45.55,0:47:48.94,EN,,0,0,0,,by introducing those, these axioms no longer tell the whole story.\nDialogue: 0,0:47:49.83,0:47:52.03,EN,,0,0,0,,And they're still true if written exactly like this.\nDialogue: 0,0:47:53.25,0:47:54.94,EN,,0,0,0,,But they don't tell the whole story.\nDialogue: 0,0:47:56.07,0:48:01.68,EN,,0,0,0,,Because if I'm going to set a particular CAR in a particular CONS,\nDialogue: 0,0:48:03.02,0:48:04.03,EN,,0,0,0,,the questions are,\nDialogue: 0,0:48:04.24,0:48:08.64,EN,,0,0,0,,well, is that setting all CARs and all CONSes of the same two things or not?\nDialogue: 0,0:48:10.09,0:48:13.04,EN,,0,0,0,,If I--if we use CONSes to make up things like rational numbers,\nDialogue: 0,0:48:14.86,0:48:17.10,EN,,0,0,0,,or things like 3 over 4,\nDialogue: 0,0:48:17.34,0:48:20.25,EN,,0,0,0,,supposing I had two three-fourths.\nDialogue: 0,0:48:21.57,0:48:22.75,EN,,0,0,0,,Are they the same one--\nDialogue: 0,0:48:24.06,0:48:24.89,EN,,0,0,0,,or are they different?\nDialogue: 0,0:48:25.34,0:48:26.96,EN,,0,0,0,,Well, in the case of numbers, it doesn't matter.\nDialogue: 0,0:48:27.86,0:48:30.49,EN,,0,0,0,,Because there's no meaning to changing the denominator of a number.\nDialogue: 0,0:48:33.02,0:48:35.32,EN,,0,0,0,,What you could do is make a number which has a different denominator.\nDialogue: 0,0:48:36.84,0:48:39.88,EN,,0,0,0,,But the concept of changing a number which has to have a different denominator\nDialogue: 0,0:48:40.00,0:48:43.58,EN,,0,0,0,,is sort of a very weird, and sort of not supported by what you think of as mathematics.\nDialogue: 0,0:48:44.77,0:48:47.40,EN,,0,0,0,,However, when these CONSes represent things in the physical world,\nDialogue: 0,0:48:48.97,0:48:50.43,EN,,0,0,0,,then changing something like the CAR\nDialogue: 0,0:48:50.60,0:48:52.20,EN,,0,0,0,,like removing a piece of the fingernail.\nDialogue: 0,0:48:53.69,0:48:56.56,EN,,0,0,0,,And so CONSes have an identity.\nDialogue: 0,0:48:57.77,0:48:59.92,EN,,0,0,0,,Let me show you what I mean about identity, first of all.\nDialogue: 0,0:49:01.28,0:49:03.05,EN,,0,0,0,,Let's do some little example here.\nDialogue: 0,0:49:04.32,0:49:15.20,EN,,0,0,0,,Supposing I define A to the CONS of 1 and 2.\nDialogue: 0,0:49:18.32,0:49:19.76,EN,,0,0,0,,Well, what that means, first of all,\nDialogue: 0,0:49:20.67,0:49:25.20,EN,,0,0,0,,is that somewhere in some environment I've made a symbol A\nDialogue: 0,0:49:25.96,0:49:28.67,EN,,0,0,0,,to have a value which is a pair\nDialogue: 0,0:49:29.47,0:49:34.06,EN,,0,0,0,,consisting of pointers to a 1 and a pointer to a 2,\nDialogue: 0,0:49:35.34,0:49:36.16,EN,,0,0,0,,just like that.\nDialogue: 0,0:49:38.12,0:49:39.60,EN,,0,0,0,,Now, supposing I also say\nDialogue: 0,0:49:40.22,0:49:47.58,EN,,0,0,0,,define B to be the CONS--\nDialogue: 0,0:49:53.88,0:49:56.81,EN,,0,0,0,,it doesn't matter, but I like it better, it's prettier--\nDialogue: 0,0:49:57.63,0:49:59.88,EN,,0,0,0,,of A and A.\nDialogue: 0,0:50:03.97,0:50:06.03,EN,,0,0,0,,Well, first of all, I'm using the name A twice.\nDialogue: 0,0:50:07.84,0:50:10.57,EN,,0,0,0,,At this moment, I'm going to think of CONSes as having identity.\nDialogue: 0,0:50:11.30,0:50:12.64,EN,,0,0,0,,This is the same one.\nDialogue: 0,0:50:13.69,0:50:14.81,EN,,0,0,0,,And so what that means\nDialogue: 0,0:50:15.29,0:50:17.61,EN,,0,0,0,,is I make another pair,\nDialogue: 0,0:50:18.81,0:50:20.20,EN,,0,0,0,,which I'm going to call B.\nDialogue: 0,0:50:22.38,0:50:27.60,EN,,0,0,0,,And it contains two pointers to A.\nDialogue: 0,0:50:28.92,0:50:32.20,EN,,0,0,0,,At this point, I have three names for this object.\nDialogue: 0,0:50:33.10,0:50:34.16,EN,,0,0,0,,A is its name.\nDialogue: 0,0:50:34.88,0:50:36.46,EN,,0,0,0,,The CAR of B is its name.\nDialogue: 0,0:50:37.23,0:50:38.86,EN,,0,0,0,,And the CDR of B is its name.\nDialogue: 0,0:50:39.36,0:50:41.15,EN,,0,0,0,,It has several aliases, they're called.\nDialogue: 0,0:50:44.23,0:50:49.28,EN,,0,0,0,,Now, supposing I do something like set-the-CAR,\nDialogue: 0,0:50:53.77,0:51:08.38,EN,,0,0,0,,the CAR of the CAR of B to 3.\nDialogue: 0,0:51:12.75,0:51:17.45,EN,,0,0,0,,What that means is I find the CAR of B, that's this.\nDialogue: 0,0:51:17.83,0:51:20.93,EN,,0,0,0,,I set the CAR of that to be 3, changing this.\nDialogue: 0,0:51:24.76,0:51:25.69,EN,,0,0,0,,I've changed A.\nDialogue: 0,0:51:27.24,0:51:33.64,EN,,0,0,0,,If I were to ask what's the CAR of A--of A now?\nDialogue: 0,0:51:35.34,0:51:37.56,EN,,0,0,0,,I would get out 3,\nDialogue: 0,0:51:38.68,0:51:43.39,EN,,0,0,0,,even though here we see that A was the CONS of 1 and 2.\nDialogue: 0,0:51:45.29,0:51:47.44,EN,,0,0,0,,I caused A to change by changing B.\nDialogue: 0,0:51:48.56,0:51:49.64,EN,,0,0,0,,There is sharing here.\nDialogue: 0,0:51:52.25,0:51:53.47,EN,,0,0,0,,That's sometimes what we want.\nDialogue: 0,0:51:54.24,0:51:56.12,EN,,0,0,0,,Surely in the queues and things like that,\nDialogue: 0,0:51:56.24,0:52:02.38,EN,,0,0,0,,that's exactly what we defined our--organized our data structures to facilitate-- sharing.\nDialogue: 0,0:52:04.35,0:52:05.66,EN,,0,0,0,,But inadvertent sharing,\nDialogue: 0,0:52:07.76,0:52:09.72,EN,,0,0,0,,unanticipated interactions between objects,\nDialogue: 0,0:52:10.78,0:52:14.08,EN,,0,0,0,,is the source of most of the bugs that occur in complicated programs.\nDialogue: 0,0:52:15.44,0:52:21.66,EN,,0,0,0,,So by introducing this possibility of things having identity and sharing\nDialogue: 0,0:52:21.87,0:52:23.76,EN,,0,0,0,,and having multiple names for the same thing,\nDialogue: 0,0:52:24.08,0:52:25.05,EN,,0,0,0,,we get a lot of power.\nDialogue: 0,0:52:25.13,0:52:28.46,EN,,0,0,0,,But we're going to pay for it with lots of complexity and bugs.\nDialogue: 0,0:52:32.19,0:52:36.24,EN,,0,0,0,,So also, for example, if I just looked at this just to drive that home,\nDialogue: 0,0:52:37.10,0:52:39.87,EN,,0,0,0,,the CADR of B,\nDialogue: 0,0:52:42.46,0:52:46.56,EN,,0,0,0,,which has nothing to do with even the CAR of B, apparently.\nDialogue: 0,0:52:46.88,0:52:49.02,EN,,0,0,0,,The CADR of B, what's that?\nDialogue: 0,0:52:49.35,0:52:53.56,EN,,0,0,0,,Take that CDR of B and now take the CAR of that.\nDialogue: 0,0:52:53.56,0:52:54.86,EN,,0,0,0,,Oh, that's 3 also.\nDialogue: 0,0:52:56.48,0:53:00.43,EN,,0,0,0,,So I can have non-local interactions by sharing.\nDialogue: 0,0:53:01.12,0:53:02.48,EN,,0,0,0,,And I have to be very careful of that.\nDialogue: 0,0:53:06.64,0:53:12.64,EN,,0,0,0,,Well, so far, of course, it seems I've introduced several different assignment operators--\nDialogue: 0,0:53:13.18,0:53:17.61,EN,,0,0,0,,set, set CAR, set CDR.\nDialogue: 0,0:53:18.51,0:53:21.39,EN,,0,0,0,,Well, maybe I should just get rid of set CAR and set CDR. Maybe they're not worthwhile.\nDialogue: 0,0:53:22.82,0:53:23.66,EN,,0,0,0,,Well, the answer is\nDialogue: 0,0:53:24.12,0:53:26.11,EN,,0,0,0,,that once you let the camel's nose into the tent,\nDialogue: 0,0:53:26.24,0:53:27.34,EN,,0,0,0,,the rest of him follows.\nDialogue: 0,0:53:30.16,0:53:31.26,EN,,0,0,0,,All I have to have is set,\nDialogue: 0,0:53:31.61,0:53:35.85,EN,,0,0,0,,and I can make all of the--all of the bad things that can happen.\nDialogue: 0,0:53:38.55,0:53:39.80,EN,,0,0,0,,Let's play with that a little bit.\nDialogue: 0,0:53:40.69,0:53:43.72,EN,,0,0,0,,A couple of days ago, when we introduced compound data,\nDialogue: 0,0:53:45.13,0:53:51.20,EN,,0,0,0,,you saw Hal show you a definition of CONS in terms of a message acceptor.\nDialogue: 0,0:53:52.48,0:53:56.06,EN,,0,0,0,,I'm going to show you even a more horrible thing,\nDialogue: 0,0:53:57.13,0:54:00.04,EN,,0,0,0,,a definition of CONS in terms of nothing but air,\nDialogue: 0,0:54:02.56,0:54:03.02,EN,,0,0,0,,hot air.\nDialogue: 0,0:54:04.44,0:54:08.12,EN,,0,0,0,,What is the definition of CONS, of the old functional kind,\nDialogue: 0,0:54:09.26,0:54:11.66,EN,,0,0,0,,in terms of purely lambdic expressions,\nDialogue: 0,0:54:13.39,0:54:14.40,EN,,0,0,0,,procedures?\nDialogue: 0,0:54:17.39,0:54:19.66,EN,,0,0,0,,Because I'm going to then modify this definition\nDialogue: 0,0:54:20.30,0:54:23.16,EN,,0,0,0,,to get assignment to be only one kind of assignment,\nDialogue: 0,0:54:24.28,0:54:27.93,EN,,0,0,0,,to get rid of the set CAR and set CDR in terms of set.\nDialogue: 0,0:54:28.58,0:54:37.39,EN,,0,0,0,,So what if I define CONS of X and Y\nDialogue: 0,0:54:38.91,0:54:42.56,EN,,0,0,0,,to be a procedure of one argument called a message M,\nDialogue: 0,0:54:43.39,0:54:46.32,EN,,0,0,0,,which calls that message on X and Y?\nDialogue: 0,0:54:51.12,0:54:53.10,EN,,0,0,0,,This idea was invented by Alonzo Church,\nDialogue: 0,0:54:53.77,0:54:55.72,EN,,0,0,0,,who was the greatest programmer of the 20th century,\nDialogue: 0,0:54:55.79,0:54:57.15,EN,,0,0,0,,although he never saw a computer.\nDialogue: 0,0:54:57.87,0:54:59.13,EN,,0,0,0,,It was done in the 1930s.\nDialogue: 0,0:54:59.42,0:55:02.22,EN,,0,0,0,,He was a logician, I suppose at Princeton at the time.\nDialogue: 0,0:55:08.66,0:55:10.43,EN,,0,0,0,,Define CAR of X\nDialogue: 0,0:55:13.10,0:55:16.92,EN,,0,0,0,,to be the result of applying X to that procedure of two arguments,\nDialogue: 0,0:55:17.15,0:55:20.60,EN,,0,0,0,,A and D, which selects A.\nDialogue: 0,0:55:23.71,0:55:24.97,EN,,0,0,0,,I will define CDR of X\nDialogue: 0,0:55:33.10,0:55:34.78,EN,,0,0,0,,to be that procedure,\nDialogue: 0,0:55:35.08,0:55:40.25,EN,,0,0,0,,to be the result of applying X to that procedure of A and D,\nDialogue: 0,0:55:40.92,0:55:42.04,EN,,0,0,0,,which selects D.\nDialogue: 0,0:55:46.67,0:55:49.88,EN,,0,0,0,,Now, you may not recognize this as CAR, CDR, and CONS.\nDialogue: 0,0:55:50.51,0:55:53.61,EN,,0,0,0,,But I'm going to demonstrate to you that it satisfies the original axioms\nDialogue: 0,0:55:54.11,0:55:54.81,EN,,0,0,0,,just once.\nDialogue: 0,0:55:55.61,0:55:57.56,EN,,0,0,0,,And then we're going to do some playing of games.\nDialogue: 0,0:55:58.29,0:56:06.27,EN,,0,0,0,,Consider the problem CAR of CONS of, say, 35 and 47.\nDialogue: 0,0:56:09.93,0:56:10.96,EN,,0,0,0,,Well, what is that?\nDialogue: 0,0:56:11.12,0:56:15.24,EN,,0,0,0,,It is the result of taking car of the result of substituting 35 and 47\nDialogue: 0,0:56:15.37,0:56:18.20,EN,,0,0,0,,X and Y in the body of this.\nDialogue: 0,0:56:19.71,0:56:20.69,EN,,0,0,0,,Well, that's easy enough.\nDialogue: 0,0:56:20.69,0:56:30.88,EN,,0,0,0,,That's CAR of the result of substituting into lambda of M, M of 35 and 47.\nDialogue: 0,0:56:35.53,0:56:39.36,EN,,0,0,0,,Well, what this is, is the result of substituting this object\nDialogue: 0,0:56:39.44,0:56:41.85,EN,,0,0,0,,for X in the body of that.\nDialogue: 0,0:56:42.83,0:56:47.66,EN,,0,0,0,,So that's just lambda of M--\nDialogue: 0,0:56:48.33,0:56:52.19,EN,,0,0,0,,that's substituted, because this object is being substituted for X,\nDialogue: 0,0:56:52.88,0:56:54.35,EN,,0,0,0,,which is the beginning of a list,\nDialogue: 0,0:56:54.88,0:57:00.32,EN,,0,0,0,,lambda of M-- M of 35 and 47,\nDialogue: 0,0:57:03.10,0:57:07.31,EN,,0,0,0,,applied to that procedure of A and D,\nDialogue: 0,0:57:07.48,0:57:08.67,EN,,0,0,0,,which gives me A.\nDialogue: 0,0:57:10.91,0:57:14.62,EN,,0,0,0,,Well, that's the result of substituting this for M here.\nDialogue: 0,0:57:15.96,0:57:21.71,EN,,0,0,0,,So that's the same thing as lambda of A, D, A,\nDialogue: 0,0:57:22.22,0:57:24.84,EN,,0,0,0,,applied to 35 and 47.\nDialogue: 0,0:57:26.33,0:57:27.37,EN,,0,0,0,,Oh, well that's 35.\nDialogue: 0,0:57:27.40,0:57:31.21,EN,,0,0,0,,That's substituting 35 for A and for 47 for D in A.\nDialogue: 0,0:57:35.60,0:57:37.24,EN,,0,0,0,,So I don't need any data at all.\nDialogue: 0,0:57:37.88,0:57:38.75,EN,,0,0,0,,not even numbers.\nDialogue: 0,0:57:40.92,0:57:42.64,EN,,0,0,0,,This is Alonso Church's hack.\nDialogue: 0,0:57:52.42,0:57:56.17,EN,,0,0,0,,Well, now we're going to do something nasty to him.\nDialogue: 0,0:57:56.76,0:57:58.49,EN,,0,0,0,,Being a logician, he wouldn't like this.\nDialogue: 0,0:57:59.20,0:58:01.96,EN,,0,0,0,,But as programmers, let's look at the overhead.\nDialogue: 0,0:58:03.26,0:58:04.16,EN,,0,0,0,,And here we go.\nDialogue: 0,0:58:05.39,0:58:07.58,EN,,0,0,0,,I'm going to change the definition of CONS.\nDialogue: 0,0:58:09.57,0:58:12.35,EN,,0,0,0,,It's almost the same as Alonzo Church's, but not quite.\nDialogue: 0,0:58:14.41,0:58:15.50,EN,,0,0,0,,What do we have here?\nDialogue: 0,0:58:16.07,0:58:18.72,EN,,0,0,0,,The CONS of two arguments, X and Y,\nDialogue: 0,0:58:19.50,0:58:22.51,EN,,0,0,0,,is going to be that procedure of one argument M,\nDialogue: 0,0:58:23.39,0:58:25.64,EN,,0,0,0,,which supplies M to X and Y as before,\nDialogue: 0,0:58:26.19,0:58:29.29,EN,,0,0,0,,but also to two permissions,\nDialogue: 0,0:58:30.17,0:58:32.01,EN,,0,0,0,,the permission to set X to N\nDialogue: 0,0:58:32.60,0:58:34.40,EN,,0,0,0,,and the permission to set Y to N,\nDialogue: 0,0:58:34.44,0:58:35.68,EN,,0,0,0,,given that I have an N.\nDialogue: 0,0:58:40.94,0:58:44.72,EN,,0,0,0,,So besides the things that I had here in Church's definition,\nDialogue: 0,0:58:45.72,0:58:51.66,EN,,0,0,0,,what I have is that the thing that CONS returns\nDialogue: 0,0:58:52.12,0:58:53.82,EN,,0,0,0,,will apply its argument\nDialogue: 0,0:58:54.91,0:58:59.44,EN,,0,0,0,,to not just the values of the X and Y that the CONS is made of,\nDialogue: 0,0:58:59.69,0:59:03.58,EN,,0,0,0,,but also permissions to set X and Y to new values.\nDialogue: 0,0:59:06.54,0:59:08.08,EN,,0,0,0,,Now, of course, just as before,\nDialogue: 0,0:59:08.83,0:59:10.51,EN,,0,0,0,,CAR is exactly the same.\nDialogue: 0,0:59:11.69,0:59:14.36,EN,,0,0,0,,The CAR of X is nothing more than applying X,\nDialogue: 0,0:59:14.54,0:59:16.00,EN,,0,0,0,,as in Church's definition,\nDialogue: 0,0:59:16.86,0:59:19.00,EN,,0,0,0,,to a procedure, in this case, of four arguments,\nDialogue: 0,0:59:19.29,0:59:21.04,EN,,0,0,0,,which selects out the first one.\nDialogue: 0,0:59:22.54,0:59:24.16,EN,,0,0,0,,And just as we did before,\nDialogue: 0,0:59:25.42,0:59:26.96,EN,,0,0,0,,that will be the value of X\nDialogue: 0,0:59:29.04,0:59:35.40,EN,,0,0,0,,that was contained in the procedure which is the result of evaluating this lambda expression\nDialogue: 0,0:59:35.45,0:59:37.84,EN,,0,0,0,,in the environment where X and Y are defined over here.\nDialogue: 0,0:59:41.94,0:59:43.15,EN,,0,0,0,,That's the value of CONS.\nDialogue: 0,0:59:45.64,0:59:47.53,EN,,0,0,0,,Now, however, the exciting part.\nDialogue: 0,0:59:47.73,0:59:48.96,EN,,0,0,0,,CDR, of course, is the same.\nDialogue: 0,0:59:49.39,0:59:50.35,EN,,0,0,0,,The exciting part,\nDialogue: 0,0:59:51.23,0:59:52.52,EN,,0,0,0,,set CAR and set CDR.\nDialogue: 0,0:59:53.45,0:59:55.52,EN,,0,0,0,,Well, they're nothing very complicated anymore.\nDialogue: 0,0:59:55.80,1:00:00.64,EN,,0,0,0,,Set CAR of a CONS X to a new value Y\nDialogue: 0,1:00:01.63,1:00:03.85,EN,,0,0,0,,is nothing more than applying that CONS,\nDialogue: 0,1:00:04.11,1:00:06.76,EN,,0,0,0,,which is the procedure of four--the procedure of one argument\nDialogue: 0,1:00:07.69,1:00:09.80,EN,,0,0,0,,which applies its argument to four things,\nDialogue: 0,1:00:11.24,1:00:15.85,EN,,0,0,0,,to a procedure which is of four arguments--\nDialogue: 0,1:00:16.00,1:00:18.08,EN,,0,0,0,,the value of X, the value of Y,\nDialogue: 0,1:00:18.32,1:00:20.54,EN,,0,0,0,,permission to set X, the permission to set Y--\nDialogue: 0,1:00:21.32,1:00:26.09,EN,,0,0,0,,and using it--using that permission to set X to the new value.\nDialogue: 0,1:00:31.65,1:00:33.54,EN,,0,0,0,,And similarly, set-cdr is the same thing.\nDialogue: 0,1:00:36.25,1:00:39.44,EN,,0,0,0,,So what you've just seen is that I didn't introduce any new primitives at all.\nDialogue: 0,1:00:40.11,1:00:44.36,EN,,0,0,0,,I mean, Whether or not I want to implement it this way is a matter of engineering.\nDialogue: 0,1:00:45.34,1:00:47.39,EN,,0,0,0,,And the answer is of course I don't implement it this way\nDialogue: 0,1:00:48.09,1:00:49.63,EN,,0,0,0,,for reasons that have to do with engineering.\nDialogue: 0,1:00:51.68,1:00:53.40,EN,,0,0,0,,However in principle, logically,\nDialogue: 0,1:00:54.28,1:00:56.43,EN,,0,0,0,,I introduced one assignment operator,\nDialogue: 0,1:00:56.96,1:00:58.76,EN,,0,0,0,,I've assigned--I've introduced them all.\nDialogue: 0,1:01:05.42,1:01:06.67,EN,,0,0,0,,Are there any questions?\nDialogue: 0,1:01:09.20,1:01:10.89,EN,,0,0,0,,Yes, David.\nDialogue: 0,1:01:12.04,1:01:15.64,EN,,0,0,0,,AUDIENCE: I can follow you up until you get--I can follow all of that.\nDialogue: 0,1:01:15.64,1:01:17.61,EN,,0,0,0,,But when we bring in the permissions,\nDialogue: 0,1:01:18.14,1:01:21.64,EN,,0,0,0,,defining CONS in terms of the lambda N,\nDialogue: 0,1:01:21.80,1:01:24.21,EN,,0,0,0,,I don't follow where N gets passed.\nDialogue: 0,1:01:24.21,1:01:25.69,EN,,0,0,0,,PROFESSOR: Oh, I'm sorry. I'll show you.\nDialogue: 0,1:01:26.34,1:01:27.05,EN,,0,0,0,,Let's follow it.\nDialogue: 0,1:01:27.36,1:01:29.07,EN,,0,0,0,,Of course, we could do it on the blackboard.\nDialogue: 0,1:01:29.18,1:01:30.17,EN,,0,0,0,,It's not so hard.\nDialogue: 0,1:01:30.17,1:01:31.47,EN,,0,0,0,,But it's also easy here.\nDialogue: 0,1:01:32.45,1:01:35.79,EN,,0,0,0,,Supposing I wish to set-cdr of X to Y.\nDialogue: 0,1:01:37.79,1:01:39.66,EN,,0,0,0,,See that right there. set cdr x to y\nDialogue: 0,1:01:40.36,1:01:41.92,EN,,0,0,0,,X is presumably a CONS,\nDialogue: 0,1:01:43.31,1:01:45.24,EN,,0,0,0,,a thing resulting from evaluating CONS.\nDialogue: 0,1:01:45.88,1:01:46.35,EN,,0,0,0,,right?\nDialogue: 0,1:01:46.89,1:01:49.96,EN,,0,0,0,,Therefore X comes from a place over here,\nDialogue: 0,1:01:52.57,1:01:56.49,EN,,0,0,0,,that that X is of the result of evaluating this lambda expression.\nDialogue: 0,1:01:58.11,1:01:58.49,EN,,0,0,0,,Right?\nDialogue: 0,1:01:59.38,1:02:01.63,EN,,0,0,0,,That when I evaluated that lambda expression,\nDialogue: 0,1:02:04.01,1:02:08.76,EN,,0,0,0,,I evaluated it in an environment where the arguments to CONS were defined.\nDialogue: 0,1:02:11.75,1:02:15.18,EN,,0,0,0,,That means that as free variables in this lambda expression,\nDialogue: 0,1:02:16.25,1:02:18.68,EN,,0,0,0,,there is the--there are in the frame,\nDialogue: 0,1:02:18.72,1:02:22.44,EN,,0,0,0,,which is the parent frame of this lambda expression,\nDialogue: 0,1:02:23.23,1:02:25.82,EN,,0,0,0,,the procedure resulting from this lambda expression,\nDialogue: 0,1:02:26.65,1:02:28.51,EN,,0,0,0,,X and Y have places.\nDialogue: 0,1:02:29.25,1:02:30.83,EN,,0,0,0,,And it's possible to set them.\nDialogue: 0,1:02:31.91,1:02:36.08,EN,,0,0,0,,I set them to an N, which is the argument of the permission.\nDialogue: 0,1:02:37.26,1:02:39.31,EN,,0,0,0,,The permission is a procedure\nDialogue: 0,1:02:41.40,1:02:43.18,EN,,0,0,0,,which is passed to M,\nDialogue: 0,1:02:43.29,1:02:46.51,EN,,0,0,0,,which is the argument that the CONS object gets passed.\nDialogue: 0,1:02:47.94,1:02:50.91,EN,,0,0,0,,Now, let's go back here in the set-cdr\nDialogue: 0,1:02:52.11,1:02:55.42,EN,,0,0,0,,The CONS object, which is the first argument of set-cdr\nDialogue: 0,1:02:56.12,1:02:57.48,EN,,0,0,0,,gets passed an argument.\nDialogue: 0,1:02:59.77,1:03:02.22,EN,,0,0,0,,That--there's a procedure of four things, indeed,\nDialogue: 0,1:03:02.32,1:03:04.65,EN,,0,0,0,,because that's the same thing as this M over here,\nDialogue: 0,1:03:04.99,1:03:06.56,EN,,0,0,0,,which is applied to four objects.\nDialogue: 0,1:03:07.92,1:03:13.34,EN,,0,0,0,,The object over here, SD, is, in fact, this permission.\nDialogue: 0,1:03:15.47,1:03:19.93,EN,,0,0,0,,When I use SD, I apply it to Y, right there.\nDialogue: 0,1:03:22.91,1:03:24.04,EN,,0,0,0,,So that comes from this.\nDialogue: 0,1:03:25.37,1:03:26.92,EN,,0,0,0,,AUDIENCE: So what do you--\nDialogue: 0,1:03:27.00,1:03:32.19,EN,,0,0,0,,PROFESSOR: So to finish that, the N that was here is the Y which is here.\nDialogue: 0,1:03:34.04,1:03:34.52,EN,,0,0,0,,How's that?\nDialogue: 0,1:03:34.81,1:03:35.75,EN,,0,0,0,,AUDIENCE: Right, OK.\nDialogue: 0,1:03:35.75,1:03:37.29,EN,,0,0,0,,Now, when you do a set-cdr,\nDialogue: 0,1:03:39.07,1:03:41.97,EN,,0,0,0,,X is the value the CDR is going to become.\nDialogue: 0,1:03:41.97,1:03:44.03,EN,,0,0,0,,PROFESSOR: The X over here.\nDialogue: 0,1:03:44.96,1:03:46.20,EN,,0,0,0,,I'm sorry, that's not true.\nDialogue: 0,1:03:46.20,1:03:48.33,EN,,0,0,0,,The X is--set-cdr has two arguments--\nDialogue: 0,1:03:48.91,1:03:50.36,EN,,0,0,0,,The CONS I'm changing\nDialogue: 0,1:03:51.34,1:03:53.93,EN,,0,0,0,,and the value I'm changing it to.\nDialogue: 0,1:03:56.15,1:03:58.32,EN,,0,0,0,,So you have them backwards, that's all.\nDialogue: 0,1:04:02.17,1:04:03.16,EN,,0,0,0,,Are there any other questions?\nDialogue: 0,1:04:07.88,1:04:08.64,EN,,0,0,0,,Well, thank you.\nDialogue: 0,1:04:08.64,1:04:09.52,EN,,0,0,0,,It's time for lunch.\nDialogue: 0,1:04:10.44,1:04:28.73,Declare,,0,0,0,,{\\fad(500,500)}http://ocw.mit.edu\nDialogue: 0,1:04:10.44,1:04:28.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}https://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec6a.chn+eng.ass",
    "content": "[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: EN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nAudio File: ../../../../Movies/lec6a_480_muxed.mp4\nVideo File: ../../../../Movies/lec6a_480_muxed.mp4\nVideo AR Mode: 4\nVideo AR Value: 1.333333\nVideo Zoom Percent: 2.000000\nVideo Position: 556\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:18.55,0:00:21.84,EN,,0,0,0,,PROFESSOR: Well, last time Gerry really let the cat out of the bag.\nDialogue: 0,0:00:22.49,0:00:24.60,EN,,0,0,0,,He introduced the idea of assignment.\nDialogue: 0,0:00:26.35,0:00:33.61,EN,,0,0,0,,Assignment and state.\nDialogue: 0,0:00:37.48,0:00:40.03,EN,,0,0,0,,And as we started to see, the implications\nDialogue: 0,0:00:40.72,0:00:43.16,EN,,0,0,0,,of introducing assignment and state into the language\nDialogue: 0,0:00:43.16,0:00:44.41,EN,,0,0,0,,are absolutely frightening.\nDialogue: 0,0:00:45.08,0:00:48.62,EN,,0,0,0,,First of all, the substitution model of evaluation breaks down.\nDialogue: 0,0:00:49.13,0:00:52.48,EN,,0,0,0,,And we have to use this much more complicated environment model\nDialogue: 0,0:00:52.48,0:00:54.27,EN,,0,0,0,,this very mechanistic thing with diagrams,\nDialogue: 0,0:00:54.28,0:00:57.24,EN,,0,0,0,,even to say what statements in the programming language mean.\nDialogue: 0,0:00:58.46,0:01:00.12,EN,,0,0,0,,And that's not a mere technical point.\nDialogue: 0,0:01:00.26,0:01:03.28,EN,,0,0,0,,See, it's not that we had this particular substitution model and,\nDialogue: 0,0:01:03.60,0:01:05.68,EN,,0,0,0,,well, it doesn't quite work, so we have to do something else.\nDialogue: 0,0:01:05.71,0:01:09.79,EN,,0,0,0,,It's that nothing like the substitution model can work.\nDialogue: 0,0:01:10.73,0:01:13.32,EN,,0,0,0,,Because suddenly, a variable\nDialogue: 0,0:01:14.12,0:01:16.92,EN,,0,0,0,,is not just something that stands for a value.\nDialogue: 0,0:01:17.95,0:01:21.76,EN,,0,0,0,,A variable now has to somehow specify a place\nDialogue: 0,0:01:22.40,0:01:23.34,EN,,0,0,0,,that holds a value.\nDialogue: 0,0:01:23.63,0:01:26.14,EN,,0,0,0,,And the value that's in that place can change.\nDialogue: 0,0:01:30.28,0:01:34.09,EN,,0,0,0,,Or for instance, an expression like f of x\nDialogue: 0,0:01:37.36,0:01:39.64,EN,,0,0,0,,might have a side effect in it.\nDialogue: 0,0:01:40.41,0:01:42.60,EN,,0,0,0,,So if we say f of x and it has some value,\nDialogue: 0,0:01:43.18,0:01:45.34,EN,,0,0,0,,and then later we say f of x again,\nDialogue: 0,0:01:47.24,0:01:48.43,EN,,0,0,0,,we might get a different value\nDialogue: 0,0:01:48.86,0:01:49.74,EN,,0,0,0,,depending on the order.\nDialogue: 0,0:01:49.76,0:01:52.14,EN,,0,0,0,,So suddenly, we have to think not only about values\nDialogue: 0,0:01:52.52,0:01:53.60,EN,,0,0,0,,but about time.\nDialogue: 0,0:01:57.97,0:01:59.98,EN,,0,0,0,,And then things like pairs\nDialogue: 0,0:02:00.65,0:02:02.52,EN,,0,0,0,,are no longer just their CARs and their CDRs.\nDialogue: 0,0:02:02.52,0:02:05.61,EN,,0,0,0,,A pair now is not quite its CAR and its CDR.\nDialogue: 0,0:02:05.80,0:02:07.05,EN,,0,0,0,,It's rather its identity.\nDialogue: 0,0:02:08.44,0:02:11.65,EN,,0,0,0,,So a pair has identity.\nDialogue: 0,0:02:11.65,0:02:12.59,EN,,0,0,0,,It's an object.\nDialogue: 0,0:02:21.33,0:02:25.15,EN,,0,0,0,,And two pairs that have the same CAR and CDR\nDialogue: 0,0:02:25.40,0:02:27.05,EN,,0,0,0,,well, might be the same or different,\nDialogue: 0,0:02:27.87,0:02:30.51,EN,,0,0,0,,because suddenly we have to worry about sharing.\nDialogue: 0,0:02:34.96,0:02:39.45,EN,,0,0,0,,So all of these things enter as soon as we introduce assignment.\nDialogue: 0,0:02:40.48,0:02:43.98,EN,,0,0,0,,See, this is a really far cry from where we started with substitution.\nDialogue: 0,0:02:45.04,0:02:48.91,EN,,0,0,0,,It's a technically harder way of looking at things\nDialogue: 0,0:02:48.94,0:02:53.45,EN,,0,0,0,,because we have to think more mechanistically about our programming language.\nDialogue: 0,0:02:53.47,0:02:55.34,EN,,0,0,0,,We can't just think about it as mathematics.\nDialogue: 0,0:02:55.71,0:02:58.60,EN,,0,0,0,,It's philosophically harder,\nDialogue: 0,0:02:59.15,0:03:00.65,EN,,0,0,0,,because suddenly there are all these funny issues\nDialogue: 0,0:03:00.67,0:03:02.38,EN,,0,0,0,,what does it mean that something changes\nDialogue: 0,0:03:02.38,0:03:03.77,EN,,0,0,0,,or that two things are the same.\nDialogue: 0,0:03:03.84,0:03:06.83,EN,,0,0,0,,And also, it's programming harder, because\nDialogue: 0,0:03:07.47,0:03:08.54,EN,,0,0,0,,as Gerry showed last time,\nDialogue: 0,0:03:08.56,0:03:12.20,EN,,0,0,0,,there are all these bugs having to do with bad sequencing and aliasing\nDialogue: 0,0:03:12.22,0:03:16.19,EN,,0,0,0,,that just don't exist in a language where we don't worry about objects.\nDialogue: 0,0:03:18.21,0:03:21.20,EN,,0,0,0,,Well, how'd we get into this mess?\nDialogue: 0,0:03:24.01,0:03:27.20,EN,,0,0,0,,Remember what we did, the reason we got into this is\nDialogue: 0,0:03:27.40,0:03:31.47,EN,,0,0,0,,because we were looking to build modular systems.\nDialogue: 0,0:03:35.15,0:03:37.69,EN,,0,0,0,,We wanted to build systems that\nDialogue: 0,0:03:38.09,0:03:41.04,EN,,0,0,0,,that fall apart into chunks that seem natural.\nDialogue: 0,0:03:42.76,0:03:43.82,EN,,0,0,0,,So for instance,\nDialogue: 0,0:03:44.06,0:03:46.11,EN,,0,0,0,,we want to take a random number generator\nDialogue: 0,0:03:46.22,0:03:49.40,EN,,0,0,0,,and package up the state of that random number generator inside of it\nDialogue: 0,0:03:50.25,0:03:53.71,EN,,0,0,0,,so that we can separate the idea of picking random numbers\nDialogue: 0,0:03:54.65,0:03:57.79,EN,,0,0,0,,from the general Monte Carlo strategy of estimating something\nDialogue: 0,0:03:58.65,0:04:01.52,EN,,0,0,0,,and separate that from the particular way that you\nDialogue: 0,0:04:01.90,0:04:05.74,EN,,0,0,0,,work with random numbers in that formula developed by Cesaro for pi.\nDialogue: 0,0:04:06.80,0:04:07.92,EN,,0,0,0,,And similarly,\nDialogue: 0,0:04:09.61,0:04:11.74,EN,,0,0,0,,when we go off and construct some models of things,\nDialogue: 0,0:04:12.35,0:04:16.01,EN,,0,0,0,,Ah, if we go off and model a system that we see in the real world,\nDialogue: 0,0:04:17.31,0:04:19.42,EN,,0,0,0,,we'd like our program to break into natural pieces,\nDialogue: 0,0:04:19.44,0:04:20.52,EN,,0,0,0,,pieces that mirror\nDialogue: 0,0:04:21.05,0:04:23.16,EN,,0,0,0,,the parts of the system that we see in the real world.\nDialogue: 0,0:04:24.90,0:04:27.56,EN,,0,0,0,,So for example, if we look at a digital circuit,\nDialogue: 0,0:04:28.36,0:04:29.18,EN,,0,0,0,,we say, gee,\nDialogue: 0,0:04:30.44,0:04:31.44,EN,,0,0,0,,there's a circuit\nDialogue: 0,0:04:32.08,0:04:35.16,EN,,0,0,0,,and it has a piece and it has another piece.\nDialogue: 0,0:04:40.10,0:04:43.58,EN,,0,0,0,,And these different pieces sort of have identity.\nDialogue: 0,0:04:43.58,0:04:44.59,EN,,0,0,0,,They have state.\nDialogue: 0,0:04:45.55,0:04:47.13,EN,,0,0,0,,And the state sits on these wires.\nDialogue: 0,0:04:48.58,0:04:50.22,EN,,0,0,0,,And we think of this piece as an object\nDialogue: 0,0:04:50.49,0:04:51.93,EN,,0,0,0,,that's different from that as an object.\nDialogue: 0,0:04:52.54,0:04:53.85,EN,,0,0,0,,And when we watch the system change,\nDialogue: 0,0:04:53.87,0:04:55.40,EN,,0,0,0,,we think about a signal coming in here\nDialogue: 0,0:04:55.63,0:04:58.41,EN,,0,0,0,,changing a state that might be here and going here\nDialogue: 0,0:04:58.67,0:05:00.75,EN,,0,0,0,,and interacting with a state that might be stored there,\nDialogue: 0,0:05:01.24,0:05:02.17,EN,,0,0,0,,and so on and so on.\nDialogue: 0,0:05:06.86,0:05:11.24,EN,,0,0,0,,So what we'd like is we'd like to build in the computer\nDialogue: 0,0:05:12.76,0:05:14.36,EN,,0,0,0,,systems that fall into pieces\nDialogue: 0,0:05:14.68,0:05:17.87,EN,,0,0,0,,that fall into pieces that mirror our view of reality,\nDialogue: 0,0:05:17.88,0:05:19.87,EN,,0,0,0,,of the way that the actual systems we're modeling\nDialogue: 0,0:05:19.88,0:05:20.91,EN,,0,0,0,,seem to fall into pieces.\nDialogue: 0,0:05:23.20,0:05:23.48,EN,,0,0,0,,Well,\nDialogue: 0,0:05:25.74,0:05:28.99,EN,,0,0,0,,maybe the reason that building systems like this\nDialogue: 0,0:05:28.99,0:05:31.50,EN,,0,0,0,,seems to introduce such technical complications\nDialogue: 0,0:05:31.52,0:05:32.75,EN,,0,0,0,,has nothing to do with computers.\nDialogue: 0,0:05:33.61,0:05:35.60,EN,,0,0,0,,See, maybe the real reason\nDialogue: 0,0:05:36.70,0:05:38.65,EN,,0,0,0,,that we pay such a price to write programs\nDialogue: 0,0:05:38.67,0:05:40.94,EN,,0,0,0,,that mirror our view of reality\nDialogue: 0,0:05:41.52,0:05:43.13,EN,,0,0,0,,is that we have the wrong view of reality.\nDialogue: 0,0:05:44.55,0:05:46.75,EN,,0,0,0,,See, maybe time is just an illusion,\nDialogue: 0,0:05:47.26,0:05:48.60,EN,,0,0,0,,and nothing ever changes.\nDialogue: 0,0:05:50.15,0:05:51.71,EN,,0,0,0,,See, for example, if I take this chalk,\nDialogue: 0,0:05:52.44,0:05:53.77,EN,,0,0,0,,and we say, gee, this is an object\nDialogue: 0,0:05:54.01,0:05:54.99,EN,,0,0,0,,and it has a state.\nDialogue: 0,0:05:55.82,0:05:59.29,EN,,0,0,0,,At each moment it has a position and a velocity.\nDialogue: 0,0:05:59.71,0:06:01.48,EN,,0,0,0,,And if we do something, that state can change.\nDialogue: 0,0:06:04.34,0:06:07.37,EN,,0,0,0,,But if you studied any relativity, for instance,\nDialogue: 0,0:06:07.74,0:06:09.71,EN,,0,0,0,,you know that you don't think of the path of that chalk\nDialogue: 0,0:06:09.72,0:06:11.34,EN,,0,0,0,,as something that goes on instant by instant.\nDialogue: 0,0:06:11.34,0:06:14.38,EN,,0,0,0,,It's more insightful to think of that whole chalk's existence\nDialogue: 0,0:06:14.41,0:06:15.64,EN,,0,0,0,,as a path in space-time.\nDialogue: 0,0:06:16.02,0:06:17.37,EN,,0,0,0,,that's all splayed out.\nDialogue: 0,0:06:17.87,0:06:19.84,EN,,0,0,0,,There aren't individual positions and velocities.\nDialogue: 0,0:06:19.84,0:06:23.80,EN,,0,0,0,,There's just its unchanging existence in space-time.\nDialogue: 0,0:06:24.64,0:06:26.51,EN,,0,0,0,,Similarly, if we look at this electrical system,\nDialogue: 0,0:06:27.69,0:06:30.43,EN,,0,0,0,,if we imagine this electrical system is implementing\nDialogue: 0,0:06:30.59,0:06:33.96,EN,,0,0,0,,sort of signal processing system,\nDialogue: 0,0:06:34.36,0:06:36.68,EN,,0,0,0,,the signal processing engineer who put that thing together\nDialogue: 0,0:06:36.75,0:06:38.60,EN,,0,0,0,,doesn't think of it as, well,\nDialogue: 0,0:06:38.96,0:06:41.40,EN,,0,0,0,,at each instance there's a voltage coming in.\nDialogue: 0,0:06:41.49,0:06:43.16,EN,,0,0,0,,And that translates into something.\nDialogue: 0,0:06:43.34,0:06:45.52,EN,,0,0,0,,And that affects the state over here,\nDialogue: 0,0:06:45.53,0:06:46.81,EN,,0,0,0,,which changes the state over here.\nDialogue: 0,0:06:46.81,0:06:50.11,EN,,0,0,0,,Nobody putting together a signal processing system thinks about it like that.\nDialogue: 0,0:06:50.42,0:06:51.84,EN,,0,0,0,,Instead, you say there's this signal\nDialogue: 0,0:06:54.04,0:06:58.06,EN,,0,0,0,,that's splayed out over time.\nDialogue: 0,0:06:58.06,0:06:59.48,EN,,0,0,0,,And if this is acting as a filter,\nDialogue: 0,0:07:00.20,0:07:04.04,EN,,0,0,0,,this whole thing transforms this whole thing\nDialogue: 0,0:07:04.28,0:07:07.04,EN,,0,0,0,,for some sort of other output.\nDialogue: 0,0:07:09.57,0:07:11.28,EN,,0,0,0,,You don't think of it as what's happening\nDialogue: 0,0:07:11.28,0:07:13.29,EN,,0,0,0,,instant by instant as the state of these things.\nDialogue: 0,0:07:14.16,0:07:17.32,EN,,0,0,0,,And somehow you think of this box as a whole thing,\nDialogue: 0,0:07:17.32,0:07:20.16,EN,,0,0,0,,not as little pieces sending messages of state\nDialogue: 0,0:07:20.40,0:07:21.96,EN,,0,0,0,,to each other at particular instants.\nDialogue: 0,0:07:28.25,0:07:29.36,EN,,0,0,0,,Well, today we're going to look at\nDialogue: 0,0:07:29.39,0:07:31.13,EN,,0,0,0,,another way to decompose systems\nDialogue: 0,0:07:31.36,0:07:35.45,EN,,0,0,0,,that's more like the signal processing engineer's view of the world\nDialogue: 0,0:07:35.69,0:07:38.96,EN,,0,0,0,,than it is like thinking about objects that communicate sending messages.\nDialogue: 0,0:07:41.13,0:07:43.74,EN,,0,0,0,,That's called stream processing.\nDialogue: 0,0:07:54.57,0:07:58.96,EN,,0,0,0,,And we're going to start by showing\nDialogue: 0,0:08:00.59,0:08:04.16,EN,,0,0,0,,by showing how we can make our programs more uniform\nDialogue: 0,0:08:05.15,0:08:06.54,EN,,0,0,0,,and see a lot more commonality\nDialogue: 0,0:08:06.65,0:08:09.88,EN,,0,0,0,,if we throw out of these programs\nDialogue: 0,0:08:10.81,0:08:12.30,EN,,0,0,0,,what you might say is a\nDialogue: 0,0:08:12.35,0:08:15.12,EN,,0,0,0,,inordinate concern with worrying about time.\nDialogue: 0,0:08:16.89,0:08:20.22,EN,,0,0,0,,Let me start by comparing two procedures.\nDialogue: 0,0:08:23.55,0:08:25.69,EN,,0,0,0,,The first one does this.\nDialogue: 0,0:08:25.69,0:08:27.77,EN,,0,0,0,,We imagine that there's a tree.\nDialogue: 0,0:08:30.40,0:08:32.14,EN,,0,0,0,,Say there's a tree of integers.\nDialogue: 0,0:08:33.28,0:08:34.42,EN,,0,0,0,,It's a binary tree.\nDialogue: 0,0:08:36.12,0:08:36.97,EN,,0,0,0,,Say 1.\nDialogue: 0,0:08:39.10,0:08:40.23,EN,,0,0,0,,So it looks like this.\nDialogue: 0,0:08:40.23,0:08:42.92,EN,,0,0,0,,And there's integers in each of the nodes.\nDialogue: 0,0:08:45.18,0:08:47.80,EN,,0,0,0,,And what we would like to compute is\nDialogue: 0,0:08:48.67,0:08:51.56,EN,,0,0,0,,for each odd number sitting here,\nDialogue: 0,0:08:52.30,0:08:55.10,EN,,0,0,0,,we'd like to find the square and then sum up all those squares.\nDialogue: 0,0:08:57.05,0:08:59.48,EN,,0,0,0,,Well, that should be a familiar kind of thing.\nDialogue: 0,0:08:59.48,0:09:01.95,EN,,0,0,0,,There's a recursive strategy for doing it.\nDialogue: 0,0:09:02.93,0:09:04.35,EN,,0,0,0,,We look at each leaf, and either\nDialogue: 0,0:09:04.56,0:09:06.68,EN,,0,0,0,,it's going to contribute the square of the number if it's odd\nDialogue: 0,0:09:06.70,0:09:07.77,EN,,0,0,0,,or 0 if it's even.\nDialogue: 0,0:09:08.68,0:09:12.11,EN,,0,0,0,,And then recursively, we can say at each tree\nDialogue: 0,0:09:12.65,0:09:13.84,EN,,0,0,0,,the sum of all of them is\nDialogue: 0,0:09:13.92,0:09:15.93,EN,,0,0,0,,the sum coming from the right branch and the left branch,\nDialogue: 0,0:09:16.25,0:09:17.64,EN,,0,0,0,,and recursively down through the nodes.\nDialogue: 0,0:09:17.64,0:09:18.70,EN,,0,0,0,,And that's a familiar way of\nDialogue: 0,0:09:19.26,0:09:20.36,EN,,0,0,0,,thinking about programming.\nDialogue: 0,0:09:20.36,0:09:22.59,EN,,0,0,0,,Let's actually look at that on the slide.\nDialogue: 0,0:09:23.82,0:09:26.75,EN,,0,0,0,,We say to sum the odd squares in a tree,\nDialogue: 0,0:09:27.37,0:09:29.36,EN,,0,0,0,,there's a test. Either it's a leaf node,\nDialogue: 0,0:09:29.82,0:09:31.95,EN,,0,0,0,,and we're going to check to see if it's an integer,\nDialogue: 0,0:09:32.88,0:09:36.38,EN,,0,0,0,,and then either it's odd, in which we take the square, or else it's 0.\nDialogue: 0,0:09:37.16,0:09:38.99,EN,,0,0,0,,And then the sum of the whole thing\nDialogue: 0,0:09:39.21,0:09:42.12,EN,,0,0,0,,is the sum coming from the left branch and the right branch.\nDialogue: 0,0:09:46.34,0:09:50.56,EN,,0,0,0,,OK, well, let me contrast that with a second problem.\nDialogue: 0,0:09:51.56,0:09:53.68,EN,,0,0,0,,Suppose I give you an integer n,\nDialogue: 0,0:09:54.73,0:09:57.88,EN,,0,0,0,,and then some function to compute of the first of each integer\nDialogue: 0,0:09:57.93,0:09:58.83,EN,,0,0,0,,1 through n.\nDialogue: 0,0:09:59.10,0:10:01.08,EN,,0,0,0,,And then I want to collect together in a list\nDialogue: 0,0:10:01.28,0:10:04.65,EN,,0,0,0,,all those function values that satisfy some property.\nDialogue: 0,0:10:05.60,0:10:06.88,EN,,0,0,0,,That's a general kind of thing.\nDialogue: 0,0:10:06.88,0:10:07.98,EN,,0,0,0,,Let's say to be specific,\nDialogue: 0,0:10:08.62,0:10:10.48,EN,,0,0,0,,let's imagine that for each integer, k,\nDialogue: 0,0:10:10.65,0:10:12.51,EN,,0,0,0,,we're going to compute the k Fibonacci number.\nDialogue: 0,0:10:14.21,0:10:16.27,EN,,0,0,0,,And then we'll see which of those are odd\nDialogue: 0,0:10:16.83,0:10:18.40,EN,,0,0,0,,and assemble those into a list.\nDialogue: 0,0:10:19.05,0:10:20.71,EN,,0,0,0,,So here's a procedure that does that.\nDialogue: 0,0:10:23.73,0:10:26.24,EN,,0,0,0,,Find the odd Fibonacci numbers among the first n.\nDialogue: 0,0:10:26.24,0:10:28.91,EN,,0,0,0,,And here is a standard loop the way we've been writing it.\nDialogue: 0,0:10:28.91,0:10:29.82,EN,,0,0,0,,This is a recursion.\nDialogue: 0,0:10:30.80,0:10:31.79,EN,,0,0,0,,It's a loop on k,\nDialogue: 0,0:10:32.03,0:10:34.35,EN,,0,0,0,,and says if k is bigger than n, it's the empty list.\nDialogue: 0,0:10:35.13,0:10:37.36,EN,,0,0,0,,Otherwise we compute the k-th Fibonacci number,\nDialogue: 0,0:10:37.44,0:10:38.06,EN,,0,0,0,,call that f.\nDialogue: 0,0:10:40.37,0:10:42.84,EN,,0,0,0,,If it's odd, we CONS it on\nDialogue: 0,0:10:43.76,0:10:46.01,EN,,0,0,0,,to the list starting with the next one.\nDialogue: 0,0:10:47.69,0:10:50.12,EN,,0,0,0,,And otherwise, we just take the next one.\nDialogue: 0,0:10:50.73,0:10:53.00,EN,,0,0,0,,And this is the standard way we've been writing iterative loops.\nDialogue: 0,0:10:53.00,0:10:55.56,EN,,0,0,0,,And we start off calling that loop with 1.\nDialogue: 0,0:10:57.58,0:11:00.06,EN,,0,0,0,,OK, so there are two procedures.\nDialogue: 0,0:11:01.60,0:11:02.90,EN,,0,0,0,,Those procedures look very different.\nDialogue: 0,0:11:02.90,0:11:04.20,EN,,0,0,0,,They have very different structures.\nDialogue: 0,0:11:04.25,0:11:06.89,EN,,0,0,0,,Yet from a certain point of view,\nDialogue: 0,0:11:06.92,0:11:09.61,EN,,0,0,0,,those procedures are really doing very much the same thing.\nDialogue: 0,0:11:11.33,0:11:14.67,EN,,0,0,0,,So if I was talking like a signal processing engineer,\nDialogue: 0,0:11:14.70,0:11:16.81,EN,,0,0,0,,what I might say\nDialogue: 0,0:11:18.24,0:11:26.76,EN,,0,0,0,,the first procedure enumerates the leaves of a tree.\nDialogue: 0,0:11:31.16,0:11:34.56,EN,,0,0,0,,And then we can think of a signal coming out of that, which is all the leaves.\nDialogue: 0,0:11:35.33,0:11:43.39,EN,,0,0,0,,We'll filter them to see which ones are odd,\nDialogue: 0,0:11:43.58,0:11:44.94,EN,,0,0,0,,put them through some kind of filter.\nDialogue: 0,0:11:45.19,0:11:47.79,EN,,0,0,0,,We'll then put them through a kind of transducer.\nDialogue: 0,0:11:49.20,0:11:51.69,EN,,0,0,0,,And for each one of those things, we'll take the square.\nDialogue: 0,0:11:54.44,0:11:57.44,EN,,0,0,0,,And then we'll accumulate all of those.\nDialogue: 0,0:11:58.29,0:12:00.04,EN,,0,0,0,,We'll accumulate them by sticking them together\nDialogue: 0,0:12:00.35,0:12:03.37,EN,,0,0,0,,with addition starting from 0.\nDialogue: 0,0:12:07.14,0:12:08.21,EN,,0,0,0,,That's the first program.\nDialogue: 0,0:12:08.21,0:12:09.18,EN,,0,0,0,,The second program,\nDialogue: 0,0:12:09.24,0:12:11.21,EN,,0,0,0,,I can describe in a very, very similar way.\nDialogue: 0,0:12:11.78,0:12:13.42,EN,,0,0,0,,I'll say, we'll enumerate\nDialogue: 0,0:12:15.80,0:12:19.10,EN,,0,0,0,,the numbers on this interval, for the interval 1 through n.\nDialogue: 0,0:12:22.50,0:12:24.40,EN,,0,0,0,,We'll, for each one,\nDialogue: 0,0:12:25.45,0:12:26.92,EN,,0,0,0,,compute the Fibonacci number,\nDialogue: 0,0:12:27.79,0:12:29.27,EN,,0,0,0,,put them through a transducer.\nDialogue: 0,0:12:29.27,0:12:30.78,EN,,0,0,0,,We'll then take the result of that,\nDialogue: 0,0:12:31.31,0:12:34.20,EN,,0,0,0,,and we'll filter it for oddness.\nDialogue: 0,0:12:36.27,0:12:39.24,EN,,0,0,0,,And then we'll take those and put them into an accumulator.\nDialogue: 0,0:12:39.35,0:12:40.56,EN,,0,0,0,,This time we'll build up a list,\nDialogue: 0,0:12:40.78,0:12:42.17,EN,,0,0,0,,so we'll accumulate with CONS\nDialogue: 0,0:12:42.59,0:12:43.77,EN,,0,0,0,,starting from the empty list.\nDialogue: 0,0:12:47.11,0:12:49.80,EN,,0,0,0,,So this way of looking at the program\nDialogue: 0,0:12:49.85,0:12:51.84,EN,,0,0,0,,makes the two seem very, very similar.\nDialogue: 0,0:12:51.90,0:12:52.84,EN,,0,0,0,,The problem is\nDialogue: 0,0:12:53.20,0:12:56.49,EN,,0,0,0,,that that commonality is completely obscured\nDialogue: 0,0:12:56.64,0:12:58.05,EN,,0,0,0,,when we look at the procedures we wrote.\nDialogue: 0,0:12:58.05,0:13:01.44,EN,,0,0,0,,Let's go back and look at some odd squares again,\nDialogue: 0,0:13:02.22,0:13:04.64,EN,,0,0,0,,and say things like, where's the enumerator?\nDialogue: 0,0:13:06.35,0:13:08.14,EN,,0,0,0,,Where's the enumerator in this program?\nDialogue: 0,0:13:08.14,0:13:10.52,EN,,0,0,0,,Well, it's not in one place.\nDialogue: 0,0:13:11.02,0:13:15.47,EN,,0,0,0,,It's a little bit in this leaf-node test,\nDialogue: 0,0:13:16.43,0:13:17.16,EN,,0,0,0,,which is going to stop.\nDialogue: 0,0:13:17.16,0:13:20.06,EN,,0,0,0,,It's a little bit in the recursive structure of the thing itself.\nDialogue: 0,0:13:23.15,0:13:24.12,EN,,0,0,0,,Where's the accumulator?\nDialogue: 0,0:13:24.12,0:13:25.68,EN,,0,0,0,,The accumulator isn't in one place either.\nDialogue: 0,0:13:25.68,0:13:30.73,EN,,0,0,0,,It's partly in this 0 and partly in this plus.\nDialogue: 0,0:13:32.00,0:13:34.51,EN,,0,0,0,,Right? It's not there as a thing that we can look at.\nDialogue: 0,0:13:34.51,0:13:39.05,EN,,0,0,0,,Similarly, if we look at odd Fibs,\nDialogue: 0,0:13:39.05,0:13:42.80,EN,,0,0,0,,that's also, in some sense, an enumerator and an accumulator,\nDialogue: 0,0:13:42.80,0:13:44.01,EN,,0,0,0,,but it looks very different.\nDialogue: 0,0:13:44.62,0:13:50.09,EN,,0,0,0,,Because partly, the enumerator is here in this greater than sign in the test.\nDialogue: 0,0:13:50.38,0:13:52.84,EN,,0,0,0,,And partly it's in this whole recursive structure in the loop,\nDialogue: 0,0:13:53.18,0:13:54.24,EN,,0,0,0,,and the way that we call it.\nDialogue: 0,0:13:55.68,0:13:56.32,EN,,0,0,0,,And then similarly,\nDialogue: 0,0:13:56.52,0:13:58.76,EN,,0,0,0,,that's also mixed up in there with the accumulator,\nDialogue: 0,0:13:58.91,0:14:00.12,EN,,0,0,0,,which is partly over there\nDialogue: 0,0:14:00.41,0:14:01.40,EN,,0,0,0,,and partly over there.\nDialogue: 0,0:14:03.60,0:14:06.08,EN,,0,0,0,,So these very, very natural pieces,\nDialogue: 0,0:14:08.73,0:14:12.65,EN,,0,0,0,,these very natural boxes here don't appear in our programs.\nDialogue: 0,0:14:13.26,0:14:14.36,EN,,0,0,0,,Because they're kind of mixed up.\nDialogue: 0,0:14:14.36,0:14:16.29,EN,,0,0,0,,The programs don't chop things up in the right way.\nDialogue: 0,0:14:19.45,0:14:22.17,EN,,0,0,0,,Going back to this fundamental principle of computer science\nDialogue: 0,0:14:22.19,0:14:23.63,EN,,0,0,0,,that in order to control something,\nDialogue: 0,0:14:23.63,0:14:24.96,EN,,0,0,0,,you need the name of it,\nDialogue: 0,0:14:25.80,0:14:28.44,EN,,0,0,0,,we don't really have control over thinking about things this way\nDialogue: 0,0:14:28.67,0:14:31.06,EN,,0,0,0,,because we don't have our hands in them explicitly.\nDialogue: 0,0:14:31.06,0:14:33.80,EN,,0,0,0,,We don't have a good language for talking about them.\nDialogue: 0,0:14:35.42,0:14:38.86,EN,,0,0,0,,Well, let's invent an appropriate language\nDialogue: 0,0:14:42.52,0:14:44.04,EN,,0,0,0,,in which we can build these pieces.\nDialogue: 0,0:14:44.78,0:14:47.21,EN,,0,0,0,,The key to the language is these guys,\nDialogue: 0,0:14:47.21,0:14:49.71,EN,,0,0,0,,is what is these things I called signals?\nDialogue: 0,0:14:50.48,0:14:53.32,EN,,0,0,0,,What are these things that are flying on the arrows between the boxes?\nDialogue: 0,0:14:56.88,0:14:57.71,EN,,0,0,0,,Well, those things\nDialogue: 0,0:14:59.85,0:15:03.52,EN,,0,0,0,,are going to be data structures called streams.\nDialogue: 0,0:15:03.79,0:15:05.87,EN,,0,0,0,,That's going to be the key to inventing this language.\nDialogue: 0,0:15:07.98,0:15:08.51,EN,,0,0,0,,What's a stream?\nDialogue: 0,0:15:08.52,0:15:11.50,EN,,0,0,0,,Well, a stream is, like anything else, a data abstraction.\nDialogue: 0,0:15:12.22,0:15:15.82,EN,,0,0,0,,So I should tell you what its selectors and constructors are.\nDialogue: 0,0:15:16.87,0:15:19.48,EN,,0,0,0,,For a stream, we're going to have one constructor\nDialogue: 0,0:15:19.98,0:15:21.43,EN,,0,0,0,,that's called CONS-stream.\nDialogue: 0,0:15:25.69,0:15:28.11,EN,,0,0,0,,CONS-stream is going to put two things together\nDialogue: 0,0:15:28.59,0:15:30.22,EN,,0,0,0,,to form a thing called a stream.\nDialogue: 0,0:15:32.04,0:15:33.85,EN,,0,0,0,,And then to extract things from the stream,\nDialogue: 0,0:15:33.98,0:15:36.11,EN,,0,0,0,,we're going to have a selector called the head of the stream.\nDialogue: 0,0:15:38.01,0:15:38.86,EN,,0,0,0,,So if I have a stream,\nDialogue: 0,0:15:39.00,0:15:40.41,EN,,0,0,0,,I can take its head\nDialogue: 0,0:15:41.13,0:15:42.38,EN,,0,0,0,,or I can take its tail.\nDialogue: 0,0:15:44.72,0:15:47.42,EN,,0,0,0,,And remember, I have to tell you George's contract\nDialogue: 0,0:15:48.24,0:15:52.70,EN,,0,0,0,,to tell you what the axioms are that relate these.\nDialogue: 0,0:15:53.44,0:16:00.17,EN,,0,0,0,,And it's going to be for any x and y,\nDialogue: 0,0:16:03.40,0:16:05.44,EN,,0,0,0,,if I form the CONS-stream and take the head,\nDialogue: 0,0:16:05.69,0:16:11.96,EN,,0,0,0,,the head of CONS-stream of x and y\nDialogue: 0,0:16:13.29,0:16:14.52,EN,,0,0,0,,is going to be x\nDialogue: 0,0:16:16.14,0:16:27.45,EN,,0,0,0,,and the tail of CONS-stream of x and y is going to be y.\nDialogue: 0,0:16:28.44,0:16:34.75,EN,,0,0,0,,So those are the constructor, two selectors for streams, and an axiom.\nDialogue: 0,0:16:34.75,0:16:35.85,EN,,0,0,0,,There's something fishy here.\nDialogue: 0,0:16:36.98,0:16:39.00,EN,,0,0,0,,So you might notice that these are exactly\nDialogue: 0,0:16:40.19,0:16:42.08,EN,,0,0,0,,the axioms for CONS, CAR, and CDR.\nDialogue: 0,0:16:43.63,0:16:46.56,EN,,0,0,0,,So if I said instead of writing CONS-stream I wrote CONS\nDialogue: 0,0:16:47.10,0:16:49.80,EN,,0,0,0,,and I said head was the CAR and tail was the CDR,\nDialogue: 0,0:16:50.76,0:16:52.81,EN,,0,0,0,,those are exactly the axioms for pairs.\nDialogue: 0,0:16:52.81,0:16:54.32,EN,,0,0,0,,And in fact, there's another thing here.\nDialogue: 0,0:16:55.13,0:16:56.80,EN,,0,0,0,,We're going to have a thing called the-empty-stream\nDialogue: 0,0:17:02.80,0:17:04.04,EN,,0,0,0,,which is like the-empty-list.\nDialogue: 0,0:17:08.31,0:17:10.03,EN,,0,0,0,,So why am I introducing this terminology?\nDialogue: 0,0:17:10.03,0:17:12.12,EN,,0,0,0,,Why don't I just keep talking about pairs and lists?\nDialogue: 0,0:17:12.78,0:17:13.79,EN,,0,0,0,,Well, we'll see.\nDialogue: 0,0:17:15.51,0:17:18.24,EN,,0,0,0,,For now, if you like, why don't you just pretend\nDialogue: 0,0:17:18.30,0:17:21.56,EN,,0,0,0,,that streams really are just a terminology for lists.\nDialogue: 0,0:17:21.56,0:17:22.99,EN,,0,0,0,,And we'll see in a little while why\nDialogue: 0,0:17:23.61,0:17:26.09,EN,,0,0,0,,why we want to keep this extra abstraction layer\nDialogue: 0,0:17:26.83,0:17:28.15,EN,,0,0,0,,and not just call them lists.\nDialogue: 0,0:17:32.30,0:17:33.72,EN,,0,0,0,,OK, now that we have streams,\nDialogue: 0,0:17:33.74,0:17:35.85,EN,,0,0,0,,we can start constructing the pieces of the language\nDialogue: 0,0:17:37.04,0:17:38.17,EN,,0,0,0,,to operate on streams.\nDialogue: 0,0:17:38.75,0:17:42.12,EN,,0,0,0,,And there are a whole bunch of very useful things that we could start making.\nDialogue: 0,0:17:42.12,0:17:42.81,EN,,0,0,0,,For instance,\nDialogue: 0,0:17:44.89,0:17:49.79,EN,,0,0,0,,we'll make our map box to take a stream, s,\nDialogue: 0,0:17:54.80,0:17:56.62,EN,,0,0,0,,and a procedure,\nDialogue: 0,0:17:57.80,0:17:59.21,EN,,0,0,0,,and to generate a new stream\nDialogue: 0,0:18:00.14,0:18:02.28,EN,,0,0,0,,which has as its elements\nDialogue: 0,0:18:02.28,0:18:04.88,EN,,0,0,0,,the procedure applied to all the successive elements of s.\nDialogue: 0,0:18:05.87,0:18:07.40,EN,,0,0,0,,In fact, we've seen this before.\nDialogue: 0,0:18:07.40,0:18:10.24,EN,,0,0,0,,This is the procedure map that we did with lists.\nDialogue: 0,0:18:10.95,0:18:12.60,EN,,0,0,0,,And you see it's exactly map,\nDialogue: 0,0:18:12.60,0:18:14.65,EN,,0,0,0,,except we're testing for empty-stream.\nDialogue: 0,0:18:14.65,0:18:15.56,EN,,0,0,0,,Oh, I forgot to mention that.\nDialogue: 0,0:18:15.56,0:18:17.15,EN,,0,0,0,,Empty-stream is like the null test.\nDialogue: 0,0:18:18.03,0:18:20.48,EN,,0,0,0,,So if it's empty, we generate the empty stream.\nDialogue: 0,0:18:20.51,0:18:22.28,EN,,0,0,0,,Otherwise, we form a new stream\nDialogue: 0,0:18:23.52,0:18:27.18,EN,,0,0,0,,whose first element is the procedure applied to the head of the stream,\nDialogue: 0,0:18:28.51,0:18:29.32,EN,,0,0,0,,and whose rest\nDialogue: 0,0:18:29.60,0:18:32.43,EN,,0,0,0,,is gotten by mapping along with the procedure down the tail of the stream.\nDialogue: 0,0:18:33.14,0:18:35.90,EN,,0,0,0,,So that looks exactly like the map procedure we looked at before.\nDialogue: 0,0:18:37.03,0:18:38.20,EN,,0,0,0,,Here's another useful thing.\nDialogue: 0,0:18:38.35,0:18:40.46,EN,,0,0,0,,Filter, this is our filter box.\nDialogue: 0,0:18:40.46,0:18:43.89,EN,,0,0,0,,We're going to have a predicate and a stream.\nDialogue: 0,0:18:43.89,0:18:45.08,EN,,0,0,0,,We're going to make a new stream\nDialogue: 0,0:18:45.80,0:18:48.17,EN,,0,0,0,,consists of all the elements of the original one that satisfy the predicate.\nDialogue: 0,0:18:48.33,0:18:49.48,EN,,0,0,0,,that satisfy the predicate.\nDialogue: 0,0:18:50.38,0:18:51.31,EN,,0,0,0,,That's case analysis.\nDialogue: 0,0:18:51.32,0:18:52.73,EN,,0,0,0,,When there's nothing in the stream,\nDialogue: 0,0:18:53.04,0:18:54.22,EN,,0,0,0,,we return the empty stream.\nDialogue: 0,0:18:56.28,0:18:59.18,EN,,0,0,0,,We test the predicate on the head of the stream.\nDialogue: 0,0:19:00.06,0:19:01.04,EN,,0,0,0,,And if it's true,\nDialogue: 0,0:19:01.53,0:19:02.83,EN,,0,0,0,,we add the head of the stream onto the result\nDialogue: 0,0:19:03.02,0:19:06.22,EN,,0,0,0,,the result of filtering the tail of the stream.\nDialogue: 0,0:19:08.22,0:19:10.04,EN,,0,0,0,,And otherwise, if that predicate was false,\nDialogue: 0,0:19:10.49,0:19:11.98,EN,,0,0,0,,we just filter the tail of the stream.\nDialogue: 0,0:19:13.50,0:19:14.46,EN,,0,0,0,,Right, so there's filter.\nDialogue: 0,0:19:16.59,0:19:18.56,EN,,0,0,0,,Let me run through a couple more rather quickly.\nDialogue: 0,0:19:18.56,0:19:20.70,EN,,0,0,0,,They're all in the book and you can look at them.\nDialogue: 0,0:19:20.88,0:19:21.80,EN,,0,0,0,,Let me just flash through.\nDialogue: 0,0:19:22.11,0:19:22.94,EN,,0,0,0,,Here's accumulate.\nDialogue: 0,0:19:23.26,0:19:26.92,EN,,0,0,0,,Accumulate takes a way of combining things\nDialogue: 0,0:19:27.36,0:19:29.05,EN,,0,0,0,,an initial value in a stream\nDialogue: 0,0:19:29.96,0:19:31.13,EN,,0,0,0,,and sticks them all together.\nDialogue: 0,0:19:31.56,0:19:33.69,EN,,0,0,0,,If the stream's empty, it's just the initial value.\nDialogue: 0,0:19:33.97,0:19:36.20,EN,,0,0,0,,Otherwise, we combine the head of the stream\nDialogue: 0,0:19:36.32,0:19:37.82,EN,,0,0,0,,with the result of accumulating\nDialogue: 0,0:19:38.01,0:19:40.24,EN,,0,0,0,,the tail of the stream starting from the initial value.\nDialogue: 0,0:19:40.90,0:19:42.83,EN,,0,0,0,,So that's what I'd use to add up everything in the stream.\nDialogue: 0,0:19:42.83,0:19:43.98,EN,,0,0,0,,I'd accumulate with plus.\nDialogue: 0,0:19:45.83,0:19:47.56,EN,,0,0,0,,How would I enumerate the leaves of a tree?\nDialogue: 0,0:19:48.06,0:19:52.89,EN,,0,0,0,,Well, if the tree is just a leaf itself,\nDialogue: 0,0:19:53.79,0:19:55.90,EN,,0,0,0,,I make something which only has that node in it.\nDialogue: 0,0:19:56.64,0:19:59.32,EN,,0,0,0,,Otherwise, I append together the stuff of enumerating\nDialogue: 0,0:19:59.61,0:20:02.35,EN,,0,0,0,,the left branch and the right branch.\nDialogue: 0,0:20:04.34,0:20:08.32,EN,,0,0,0,,And then append here is like the ordinary append on lists.\nDialogue: 0,0:20:13.19,0:20:13.85,EN,,0,0,0,,You can look at that.\nDialogue: 0,0:20:13.85,0:20:17.53,EN,,0,0,0,,That's analogous to the ordinary procedure for appending two lists.\nDialogue: 0,0:20:18.91,0:20:20.60,EN,,0,0,0,,Ah... How would I enumerate an interval?\nDialogue: 0,0:20:21.96,0:20:23.77,EN,,0,0,0,,This will take two integers, low and high,\nDialogue: 0,0:20:23.88,0:20:27.00,EN,,0,0,0,,and generate a stream of the integers going from low to high.\nDialogue: 0,0:20:28.32,0:20:29.88,EN,,0,0,0,,And we can make a whole bunch of pieces.\nDialogue: 0,0:20:31.89,0:20:34.48,EN,,0,0,0,,So that's a little language of talking about streams.\nDialogue: 0,0:20:34.49,0:20:35.32,EN,,0,0,0,,Once we have streams,\nDialogue: 0,0:20:35.32,0:20:37.67,EN,,0,0,0,,we can build things for manipulating them.\nDialogue: 0,0:20:37.67,0:20:39.04,EN,,0,0,0,,Again, we're making a language.\nDialogue: 0,0:20:40.20,0:20:42.22,EN,,0,0,0,,And now we can start expressing things in this language.\nDialogue: 0,0:20:43.06,0:20:47.31,EN,,0,0,0,,Here's our original procedure for summing the odd squares in a tree.\nDialogue: 0,0:20:47.31,0:20:52.62,EN,,0,0,0,,And you'll notice it looks exactly now like the block diagram,\nDialogue: 0,0:20:52.64,0:20:54.59,EN,,0,0,0,,like the signal processing block diagram.\nDialogue: 0,0:20:54.59,0:20:57.53,EN,,0,0,0,,So to sum the odd squares in a tree,\nDialogue: 0,0:20:58.06,0:21:00.80,EN,,0,0,0,,we enumerate the leaves of the tree.\nDialogue: 0,0:21:01.32,0:21:03.72,EN,,0,0,0,,We filter that for oddness.\nDialogue: 0,0:21:04.83,0:21:06.54,EN,,0,0,0,,We map that for squareness.\nDialogue: 0,0:21:09.32,0:21:13.34,EN,,0,0,0,,And we accumulate the result of that using addition, starting from 0.\nDialogue: 0,0:21:14.76,0:21:17.20,EN,,0,0,0,,So we can see the pieces that we wanted.\nDialogue: 0,0:21:17.29,0:21:19.36,EN,,0,0,0,,Similarly, the Fibonacci one,\nDialogue: 0,0:21:20.04,0:21:21.88,EN,,0,0,0,,how do we get the odd Fibs?\nDialogue: 0,0:21:22.05,0:21:24.57,EN,,0,0,0,,Well, we enumerate the interval from 1 to n,\nDialogue: 0,0:21:26.32,0:21:28.64,EN,,0,0,0,,we map along that,\nDialogue: 0,0:21:28.99,0:21:30.70,EN,,0,0,0,,computing the Fibonacci of each one.\nDialogue: 0,0:21:30.92,0:21:33.79,EN,,0,0,0,,We filter the result of those for oddness.\nDialogue: 0,0:21:34.81,0:21:36.64,EN,,0,0,0,,And we accumulate all of that stuff\nDialogue: 0,0:21:36.88,0:21:39.12,EN,,0,0,0,,using CONS starting from the empty-list.\nDialogue: 0,0:21:43.65,0:21:47.53,EN,,0,0,0,,OK, what's the advantage of this?\nDialogue: 0,0:21:47.68,0:21:48.59,EN,,0,0,0,,Well, for one thing,\nDialogue: 0,0:21:48.68,0:21:51.15,EN,,0,0,0,,we now have pieces that we can start mixing and matching.\nDialogue: 0,0:21:51.88,0:21:52.64,EN,,0,0,0,,So for instance,\nDialogue: 0,0:21:52.91,0:21:55.08,EN,,0,0,0,,if I wanted to change this, if I wanted to ah...\nDialogue: 0,0:21:58.19,0:22:00.32,EN,,0,0,0,,compute the squares of the integers and then filter them,\nDialogue: 0,0:22:00.33,0:22:01.34,EN,,0,0,0,,all I need to do\nDialogue: 0,0:22:01.90,0:22:03.64,EN,,0,0,0,,is pick up a standard piece like this\nDialogue: 0,0:22:03.68,0:22:05.40,EN,,0,0,0,,it's a map square and put it in.\nDialogue: 0,0:22:06.57,0:22:07.60,EN,,0,0,0,,Or if we wanted to do\nDialogue: 0,0:22:07.69,0:22:11.45,EN,,0,0,0,,this whole Fibonacci computation on the leaves of a tree\nDialogue: 0,0:22:11.58,0:22:12.36,EN,,0,0,0,,rather than a sequence,\nDialogue: 0,0:22:12.38,0:22:13.24,EN,,0,0,0,,all I need to do\nDialogue: 0,0:22:13.40,0:22:15.93,EN,,0,0,0,,is replace this enumerator with that one.\nDialogue: 0,0:22:18.03,0:22:19.82,EN,,0,0,0,,See, the advantage of this stream processing\nDialogue: 0,0:22:20.24,0:22:21.53,EN,,0,0,0,,is that we're establishing--\nDialogue: 0,0:22:22.36,0:22:24.96,EN,,0,0,0,,this is one of the big themes of the course--\nDialogue: 0,0:22:25.29,0:22:27.48,EN,,0,0,0,,we're establishing conventional interfaces\nDialogue: 0,0:22:32.89,0:22:37.15,EN,,0,0,0,,conventional interfaces that allow us to glue things together.\nDialogue: 0,0:22:38.30,0:22:39.55,EN,,0,0,0,,Things like map and filter\nDialogue: 0,0:22:39.79,0:22:41.64,EN,,0,0,0,,are a standard set of components\nDialogue: 0,0:22:41.68,0:22:44.76,EN,,0,0,0,,that we can start using for pasting together programs in all sorts of ways.\nDialogue: 0,0:22:45.75,0:22:48.81,EN,,0,0,0,,It allows us to see the commonality of programs.\nDialogue: 0,0:22:49.95,0:22:50.92,EN,,0,0,0,,I just ought to mention,\nDialogue: 0,0:22:51.08,0:22:53.07,EN,,0,0,0,,I've only showed you two procedures.\nDialogue: 0,0:22:53.86,0:22:55.16,EN,,0,0,0,,But let me emphasize\nDialogue: 0,0:22:55.20,0:22:57.77,EN,,0,0,0,,that this way of putting things together\nDialogue: 0,0:22:57.80,0:23:01.00,EN,,0,0,0,,with maps, filters, and accumulators is very, very general.\nDialogue: 0,0:23:01.41,0:23:07.28,EN,,0,0,0,,It's the generate and test paradigm for programs.\nDialogue: 0,0:23:07.77,0:23:09.10,EN,,0,0,0,,And as an example of that,\nDialogue: 0,0:23:09.39,0:23:12.94,EN,,0,0,0,,Richard Waters, who was at MIT when he was a graduate student,\nDialogue: 0,0:23:12.96,0:23:15.26,EN,,0,0,0,,as part of his thesis research went and analyzed\nDialogue: 0,0:23:15.80,0:23:19.21,EN,,0,0,0,,a large chunk of the IBM scientific subroutine library,\nDialogue: 0,0:23:19.82,0:23:23.31,EN,,0,0,0,,and discovered that about 60% of the programs in it\nDialogue: 0,0:23:24.06,0:23:28.25,EN,,0,0,0,,could be expressed exactly in terms using no more than what we've put here--\nDialogue: 0,0:23:28.86,0:23:30.17,EN,,0,0,0,,map, filter, and accumulate.\nDialogue: 0,0:23:30.57,0:23:31.50,EN,,0,0,0,,All right, let's take a break.\nDialogue: 0,0:23:36.59,0:23:37.12,EN,,0,0,0,,Questions?\nDialogue: 0,0:23:41.18,0:23:42.89,EN,,0,0,0,,AUDIENCE: It seems like the essence of this whole thing\nDialogue: 0,0:23:42.89,0:23:45.96,EN,,0,0,0,,is just that you have a very uniform, simple data structure\nDialogue: 0,0:23:46.25,0:23:47.66,EN,,0,0,0,,to work with, the stream.\nDialogue: 0,0:23:48.38,0:23:48.92,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:23:48.92,0:23:50.38,EN,,0,0,0,,The essence is that you, again,\nDialogue: 0,0:23:50.40,0:23:53.07,EN,,0,0,0,,it's this sense of conventional interfaces.\nDialogue: 0,0:23:53.71,0:23:55.61,EN,,0,0,0,,So you can start putting a lot of things together.\nDialogue: 0,0:23:56.01,0:23:58.78,EN,,0,0,0,,And the stream is as you say,\nDialogue: 0,0:23:58.78,0:24:00.89,EN,,0,0,0,,the uniform data structure that supports that.\nDialogue: 0,0:24:00.89,0:24:02.84,EN,,0,0,0,,This is very much like APL, by the way.\nDialogue: 0,0:24:03.60,0:24:05.21,EN,,0,0,0,,APL is very much the same idea,\nDialogue: 0,0:24:05.21,0:24:06.96,EN,,0,0,0,,except in APL, instead of this stream,\nDialogue: 0,0:24:07.13,0:24:08.44,EN,,0,0,0,,you have arrays and vectors.\nDialogue: 0,0:24:09.56,0:24:14.48,EN,,0,0,0,,And a lot of the power of APL is exactly the same reason of the power of this.\nDialogue: 0,0:24:19.91,0:24:20.91,EN,,0,0,0,,OK, thank you.\nDialogue: 0,0:24:20.91,0:24:21.66,EN,,0,0,0,,Let's take a break.\nDialogue: 0,0:24:21.66,0:24:30.35,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:24:57.47,0:24:57.61,EN,,0,0,0,,All right.\nDialogue: 0,0:24:57.61,0:24:58.59,EN,,0,0,0,,We've been looking at\nDialogue: 0,0:25:00.54,0:25:03.20,EN,,0,0,0,,at ways of organizing computations using streams.\nDialogue: 0,0:25:03.85,0:25:05.47,EN,,0,0,0,,But what I want to do now is just show you two\nDialogue: 0,0:25:05.93,0:25:09.12,EN,,0,0,0,,somewhat more complicated examples of that.\nDialogue: 0,0:25:10.84,0:25:14.12,EN,,0,0,0,,Let's start by thinking about the following\nDialogue: 0,0:25:14.20,0:25:16.81,EN,,0,0,0,,kind of utility procedure that will come in useful.\nDialogue: 0,0:25:16.81,0:25:18.09,EN,,0,0,0,,Suppose I've got a stream.\nDialogue: 0,0:25:19.96,0:25:23.15,EN,,0,0,0,,And the elements of this stream are themselves streams.\nDialogue: 0,0:25:23.98,0:25:26.53,EN,,0,0,0,,So the first thing might be 1, 2, 3.\nDialogue: 0,0:25:32.72,0:25:33.88,EN,,0,0,0,,So I've got a stream.\nDialogue: 0,0:25:33.88,0:25:40.10,EN,,0,0,0,,And each element of the stream is itself a stream.\nDialogue: 0,0:25:40.97,0:25:43.42,EN,,0,0,0,,And what I'd like to do is build a stream\nDialogue: 0,0:25:43.64,0:25:46.75,EN,,0,0,0,,that sort of collects together all of the elements,\nDialogue: 0,0:25:46.76,0:25:49.24,EN,,0,0,0,,pulls all of the elements out of these sub-streams\nDialogue: 0,0:25:50.11,0:25:51.82,EN,,0,0,0,,and strings them all together in one thing.\nDialogue: 0,0:25:52.27,0:25:55.61,EN,,0,0,0,,So just to show you the use of this language, how easy it is,\nDialogue: 0,0:25:56.11,0:25:57.10,EN,,0,0,0,,call that flatten.\nDialogue: 0,0:25:57.95,0:26:10.64,EN,,0,0,0,,And I can define to flatten this stream of streams.\nDialogue: 0,0:26:12.89,0:26:13.80,EN,,0,0,0,,Well, what is that?\nDialogue: 0,0:26:13.96,0:26:16.24,EN,,0,0,0,,That's just an accumulation.\nDialogue: 0,0:26:16.32,0:26:25.05,EN,,0,0,0,,I want to accumulate using append,\nDialogue: 0,0:26:25.07,0:26:26.45,EN,,0,0,0,,by successively appending.\nDialogue: 0,0:26:26.73,0:26:29.29,EN,,0,0,0,,So I accumulate using append streams,\nDialogue: 0,0:26:35.90,0:26:48.20,EN,,0,0,0,,starting with the-empty-stream down that stream of streams.\nDialogue: 0,0:26:54.84,0:26:55.84,EN,,0,0,0,,OK, so there's an example of\nDialogue: 0,0:26:56.92,0:26:59.23,EN,,0,0,0,,how you can start using these higher order things\nDialogue: 0,0:26:59.60,0:27:00.83,EN,,0,0,0,,to do some interesting operations.\nDialogue: 0,0:27:00.83,0:27:05.10,EN,,0,0,0,,In fact, there's another useful thing that I want to do.\nDialogue: 0,0:27:05.10,0:27:07.05,EN,,0,0,0,,I want to define a procedure called flat-map,\nDialogue: 0,0:27:17.18,0:27:20.59,EN,,0,0,0,,flat map of some function and a stream.\nDialogue: 0,0:27:21.84,0:27:25.72,EN,,0,0,0,,And what this is going to do is s will be a stream of elements.\nDialogue: 0,0:27:25.72,0:27:27.69,EN,,0,0,0,,f is going to be a function\nDialogue: 0,0:27:27.72,0:27:30.62,EN,,0,0,0,,for each element in the stream produces another stream.\nDialogue: 0,0:27:31.95,0:27:34.52,EN,,0,0,0,,And what I want to do is take all of the elements and all of those streams\nDialogue: 0,0:27:35.00,0:27:36.00,EN,,0,0,0,,and combine them together.\nDialogue: 0,0:27:36.00,0:27:49.13,EN,,0,0,0,,So that's just going to be the flatten of map f down s.\nDialogue: 0,0:27:51.20,0:27:53.04,EN,,0,0,0,,Each time I apply f to an element of s,\nDialogue: 0,0:27:53.05,0:27:53.85,EN,,0,0,0,,I get a stream.\nDialogue: 0,0:27:54.29,0:27:55.24,EN,,0,0,0,,If I map it all the way down,\nDialogue: 0,0:27:55.24,0:27:56.27,EN,,0,0,0,,I get a stream of streams,\nDialogue: 0,0:27:56.46,0:27:57.42,EN,,0,0,0,,and I'll flatten that.\nDialogue: 0,0:27:58.67,0:28:02.64,EN,,0,0,0,,Well, I want to use that to show you a\nDialogue: 0,0:28:03.87,0:28:05.84,EN,,0,0,0,,a new way to do a familiar kind of problem.\nDialogue: 0,0:28:06.51,0:28:12.27,EN,,0,0,0,,The problem's going to be like a lot of problems you've seen,\nDialogue: 0,0:28:12.28,0:28:13.96,EN,,0,0,0,,although maybe not this particular one.\nDialogue: 0,0:28:14.19,0:28:15.49,EN,,0,0,0,,I'm going to give you an integer, n.\nDialogue: 0,0:28:18.68,0:28:19.93,EN,,0,0,0,,And the problem is going to be\nDialogue: 0,0:28:21.20,0:28:31.53,EN,,0,0,0,,find all pairs and integers i and j,\nDialogue: 0,0:28:32.30,0:28:39.96,EN,,0,0,0,,between 0 and i, with j less than i, up to n,\nDialogue: 0,0:28:42.33,0:28:52.03,EN,,0,0,0,,such that i plus j is prime.\nDialogue: 0,0:28:55.74,0:28:57.92,EN,,0,0,0,,So for example, if n equals 6,\nDialogue: 0,0:28:59.74,0:29:00.78,EN,,0,0,0,,let's make a little table here,\nDialogue: 0,0:29:01.55,0:29:06.67,EN,,0,0,0,,i and j and i plus j.\nDialogue: 0,0:29:09.70,0:29:14.91,EN,,0,0,0,,So for, say, i equals 2 and j equals 1, I'd get 3.\nDialogue: 0,0:29:15.52,0:29:20.38,EN,,0,0,0,,And for i equals 3, I could have j equals 2, and that would be 5.\nDialogue: 0,0:29:21.21,0:29:26.51,EN,,0,0,0,,And 4 and 1 would be 5 and so on,\nDialogue: 0,0:29:26.92,0:29:28.11,EN,,0,0,0,,up until i goes to 6.\nDialogue: 0,0:29:28.40,0:29:32.54,EN,,0,0,0,,And what I'd like to return is to produce a stream\nDialogue: 0,0:29:33.20,0:29:37.04,EN,,0,0,0,,all the triples like this, let's say i, j, and i plus j.\nDialogue: 0,0:29:37.66,0:29:39.55,EN,,0,0,0,,So for each n, I want to generate this stream.\nDialogue: 0,0:29:40.97,0:29:43.68,EN,,0,0,0,,OK, well, that's easy.\nDialogue: 0,0:29:43.68,0:29:44.35,EN,,0,0,0,,Let's build it up.\nDialogue: 0,0:29:47.23,0:29:48.22,EN,,0,0,0,,We start like this.\nDialogue: 0,0:29:50.15,0:29:54.25,EN,,0,0,0,,We're going to say for each i, for each i\nDialogue: 0,0:29:55.24,0:29:56.44,EN,,0,0,0,,we're going to generate a stream.\nDialogue: 0,0:29:57.00,0:29:58.59,EN,,0,0,0,,For each i in the interval 1 through n,\nDialogue: 0,0:29:58.59,0:29:59.76,EN,,0,0,0,,we're going to generate a stream.\nDialogue: 0,0:30:00.66,0:30:01.80,EN,,0,0,0,,What's that stream going to be?\nDialogue: 0,0:30:02.23,0:30:04.04,EN,,0,0,0,,We're going to start by generating all the pairs.\nDialogue: 0,0:30:04.18,0:30:07.55,EN,,0,0,0,,So for each i, we're going to generate,\nDialogue: 0,0:30:08.43,0:30:14.52,EN,,0,0,0,,for each j in the interval 1 to i minus 1,\nDialogue: 0,0:30:16.91,0:30:17.98,EN,,0,0,0,,we'll generate the pair,\nDialogue: 0,0:30:18.35,0:30:20.71,EN,,0,0,0,,or the list with two elements i and j.\nDialogue: 0,0:30:23.78,0:30:27.10,EN,,0,0,0,,So we map along the interval,\nDialogue: 0,0:30:28.60,0:30:29.74,EN,,0,0,0,,generating the pairs.\nDialogue: 0,0:30:31.07,0:30:33.17,EN,,0,0,0,,And for each i, that generates a stream of pairs.\nDialogue: 0,0:30:33.40,0:30:34.49,EN,,0,0,0,,And we flatmap it.\nDialogue: 0,0:30:34.59,0:30:36.20,EN,,0,0,0,,Now we have all the pairs i and j,\nDialogue: 0,0:30:36.81,0:30:38.08,EN,,0,0,0,,such that i is less than j.\nDialogue: 0,0:30:38.73,0:30:39.85,EN,,0,0,0,,So that builds that.\nDialogue: 0,0:30:39.85,0:30:40.76,EN,,0,0,0,,Now we're got to test them.\nDialogue: 0,0:30:42.99,0:30:45.84,EN,,0,0,0,,Well, we take that thing we just built, the flatmap,\nDialogue: 0,0:30:46.94,0:30:51.37,EN,,0,0,0,,and we filter it to see whether the i-- see, we had an i and a j.\nDialogue: 0,0:30:51.66,0:30:54.17,EN,,0,0,0,,i was the first thing in the list,\nDialogue: 0,0:30:54.30,0:30:55.60,EN,,0,0,0,,j was the second thing in the list.\nDialogue: 0,0:30:57.21,0:31:00.01,EN,,0,0,0,,So we have a predicate which says in that list of two elements\nDialogue: 0,0:31:00.22,0:31:02.00,EN,,0,0,0,,is the sum of the CAR and the CDR prime.\nDialogue: 0,0:31:02.07,0:31:05.52,EN,,0,0,0,,And we filter that collection of pairs we just built.\nDialogue: 0,0:31:06.54,0:31:07.85,EN,,0,0,0,,So those are the pairs we want.\nDialogue: 0,0:31:09.42,0:31:10.24,EN,,0,0,0,,Now we go ahead\nDialogue: 0,0:31:10.88,0:31:13.10,EN,,0,0,0,,Now we go ahead and we take the result of that filter\nDialogue: 0,0:31:13.26,0:31:19.05,EN,,0,0,0,,we map along it, generating the list i and j and i plus j.\nDialogue: 0,0:31:19.61,0:31:21.39,EN,,0,0,0,,And that's our procedure prime-sum-pairs.\nDialogue: 0,0:31:22.57,0:31:24.76,EN,,0,0,0,,Ok, and then just to flash it up, here's the whole procedure.\nDialogue: 0,0:31:28.08,0:31:30.97,EN,,0,0,0,,A map, a filter, a flatmap.\nDialogue: 0,0:31:34.85,0:31:35.66,EN,,0,0,0,,There's the whole thing,\nDialogue: 0,0:31:35.66,0:31:37.12,EN,,0,0,0,,even though this isn't particularly readable.\nDialogue: 0,0:31:37.42,0:31:38.94,EN,,0,0,0,,It's just expanding that flatmap.\nDialogue: 0,0:31:39.84,0:31:40.88,EN,,0,0,0,,So there's an example\nDialogue: 0,0:31:43.28,0:31:45.00,EN,,0,0,0,,which illustrates the general point\nDialogue: 0,0:31:45.12,0:31:46.30,EN,,0,0,0,,that nested loops\nDialogue: 0,0:31:47.66,0:31:50.09,EN,,0,0,0,,in this procedure start looking like compositions of\nDialogue: 0,0:31:50.11,0:31:52.81,EN,,0,0,0,,flatmaps of flatmaps of flatmaps of maps and things.\nDialogue: 0,0:31:54.27,0:31:57.61,EN,,0,0,0,,So not only can we enumerate individual things,\nDialogue: 0,0:31:57.61,0:31:58.81,EN,,0,0,0,,but by using flatmaps,\nDialogue: 0,0:31:59.12,0:32:02.24,EN,,0,0,0,,we can do what would correspond to nested loops in most other languages.\nDialogue: 0,0:32:03.23,0:32:03.76,EN,,0,0,0,,Of course,\nDialogue: 0,0:32:04.91,0:32:08.03,EN,,0,0,0,,it's pretty awful to keep writing these flatmaps of flatmaps of flatmaps.\nDialogue: 0,0:32:08.41,0:32:13.00,EN,,0,0,0,,Prime-sum-pairs you saw looked fairly complicated,\nDialogue: 0,0:32:13.56,0:32:15.28,EN,,0,0,0,,even though the individual pieces were easy.\nDialogue: 0,0:32:15.48,0:32:17.13,EN,,0,0,0,,So what you can do, if you like,\nDialogue: 0,0:32:17.15,0:32:20.12,EN,,0,0,0,,is introduced some syntactic sugar that's called collect.\nDialogue: 0,0:32:21.04,0:32:22.68,EN,,0,0,0,,And collect is just an abbreviation\nDialogue: 0,0:32:22.91,0:32:26.16,EN,,0,0,0,,for that nest of flatmaps and filters arranged in that particular way.\nDialogue: 0,0:32:26.16,0:32:28.60,EN,,0,0,0,,Here's prime-sum-pairs again, written using collect.\nDialogue: 0,0:32:29.45,0:32:36.27,EN,,0,0,0,,It says to find all those pairs, I'm going to collect together a result,\nDialogue: 0,0:32:36.52,0:32:39.20,EN,,0,0,0,,which is the list i, j, and i plus j,\nDialogue: 0,0:32:40.84,0:32:45.39,EN,,0,0,0,,that's going to be generated as i runs through the interval from 1 to n\nDialogue: 0,0:32:47.44,0:32:52.32,EN,,0,0,0,,and as j runs through the interval from 1 to i minus 1\nDialogue: 0,0:32:54.16,0:32:56.54,EN,,0,0,0,,such that i plus j is prime.\nDialogue: 0,0:32:58.04,0:33:00.32,EN,,0,0,0,,So I'm not going to say what collect does in general.\nDialogue: 0,0:33:00.69,0:33:02.75,EN,,0,0,0,,You can look at that by looking at it in the book.\nDialogue: 0,0:33:03.42,0:33:05.45,EN,,0,0,0,,But pretty much, you can see that the pieces of this\nDialogue: 0,0:33:05.84,0:33:08.60,EN,,0,0,0,,are the pieces of that original procedure I wrote.\nDialogue: 0,0:33:08.82,0:33:11.40,EN,,0,0,0,,And this collect is just some syntactic sugar\nDialogue: 0,0:33:11.44,0:33:14.80,EN,,0,0,0,,for automatically generating that nest of flatmaps and flatmaps.\nDialogue: 0,0:33:16.31,0:33:20.33,EN,,0,0,0,,OK, well, let me do one more example\nDialogue: 0,0:33:20.67,0:33:22.00,EN,,0,0,0,,that shows you the same kind of thing.\nDialogue: 0,0:33:22.12,0:33:23.53,EN,,0,0,0,,Here's a very famous problem\nDialogue: 0,0:33:24.70,0:33:28.75,EN,,0,0,0,,that's used to illustrate a lot of so-called backtracking computer algorithms\nDialogue: 0,0:33:28.76,0:33:30.20,EN,,0,0,0,,This is the eight queens problem.\nDialogue: 0,0:33:30.20,0:33:31.08,EN,,0,0,0,,This is a chess board.\nDialogue: 0,0:33:32.37,0:33:33.64,EN,,0,0,0,,And the eight queens problem says,\nDialogue: 0,0:33:33.64,0:33:35.85,EN,,0,0,0,,find a way to put down eight queens on a chess board\nDialogue: 0,0:33:36.44,0:33:38.00,EN,,0,0,0,,so that no two are attacking each other.\nDialogue: 0,0:33:38.00,0:33:40.60,EN,,0,0,0,,And here's a particular solution to the eight queens problem.\nDialogue: 0,0:33:41.21,0:33:43.68,EN,,0,0,0,,So I have to make sure to put down queens\nDialogue: 0,0:33:43.71,0:33:46.80,EN,,0,0,0,,no two are in the same row or the same column\nDialogue: 0,0:33:47.72,0:33:49.47,EN,,0,0,0,,or sit along the same diagonal.\nDialogue: 0,0:33:51.41,0:33:56.40,EN,,0,0,0,,Now, there's sort of a standard way of doing that.\nDialogue: 0,0:33:59.74,0:34:01.48,EN,,0,0,0,,Well, first we need to do is\nDialogue: 0,0:34:02.54,0:34:04.62,EN,,0,0,0,,below the surface, at George's level.\nDialogue: 0,0:34:04.94,0:34:08.09,EN,,0,0,0,,We have to find some way to represent a board, and represent positions.\nDialogue: 0,0:34:08.09,0:34:09.52,EN,,0,0,0,,And we'll not worry about that.\nDialogue: 0,0:34:09.80,0:34:12.78,EN,,0,0,0,,But let's assume that there's a predicate called safe.\nDialogue: 0,0:34:16.14,0:34:17.55,EN,,0,0,0,,And what safe is going to do\nDialogue: 0,0:34:17.96,0:34:20.84,EN,,0,0,0,,is going to say given that I have a bunch of queens down on the chess board,\nDialogue: 0,0:34:21.36,0:34:24.54,EN,,0,0,0,,is it OK to put a queen in this particular spot?\nDialogue: 0,0:34:25.40,0:34:31.26,EN,,0,0,0,,So safe is going to take a row and a column.\nDialogue: 0,0:34:32.76,0:34:35.47,EN,,0,0,0,,That's going to be a place where I'm going to try and put down the next queen,\nDialogue: 0,0:34:36.06,0:34:42.76,EN,,0,0,0,,and the rest of positions.\nDialogue: 0,0:34:45.58,0:34:46.75,EN,,0,0,0,,And what safe will say\nDialogue: 0,0:34:46.86,0:34:51.68,EN,,0,0,0,,is given that I already have queens down in these positions,\nDialogue: 0,0:34:53.02,0:34:54.76,EN,,0,0,0,,is it safe to put another queen down\nDialogue: 0,0:34:55.10,0:34:57.20,EN,,0,0,0,,in that row and that column?\nDialogue: 0,0:34:58.30,0:34:59.36,EN,,0,0,0,,And let's not worry about that.\nDialogue: 0,0:34:59.36,0:35:01.38,EN,,0,0,0,,That's George's problem. and it's not hard to write.\nDialogue: 0,0:35:01.38,0:35:06.27,EN,,0,0,0,,You just have to check whether this thing contains any things\nDialogue: 0,0:35:06.30,0:35:08.52,EN,,0,0,0,,on that row or that column or in that diagonal.\nDialogue: 0,0:35:10.53,0:35:13.12,EN,,0,0,0,,Now, how would you organize the program given that?\nDialogue: 0,0:35:13.84,0:35:17.21,EN,,0,0,0,,And there's sort of a traditional way to organize it\nDialogue: 0,0:35:17.93,0:35:18.97,EN,,0,0,0,,called backtracking.\nDialogue: 0,0:35:20.52,0:35:23.21,EN,,0,0,0,,And it says, well, let's start off\nDialogue: 0,0:35:25.13,0:35:28.88,EN,,0,0,0,,let's think about all the ways of putting the first queen down\nDialogue: 0,0:35:30.04,0:35:31.34,EN,,0,0,0,,in the first column.\nDialogue: 0,0:35:31.45,0:35:32.24,EN,,0,0,0,,There are eight ways.\nDialogue: 0,0:35:32.58,0:35:35.00,EN,,0,0,0,,Well, let's say try the first column.\nDialogue: 0,0:35:35.88,0:35:37.30,EN,,0,0,0,,Try column 1, row 1.\nDialogue: 0,0:35:37.30,0:35:38.70,EN,,0,0,0,,These branches are going to represent\nDialogue: 0,0:35:40.17,0:35:41.88,EN,,0,0,0,,the possibilities at each level.\nDialogue: 0,0:35:43.36,0:35:45.53,EN,,0,0,0,,So I'll try and put a queen down in the first column.\nDialogue: 0,0:35:46.14,0:35:47.74,EN,,0,0,0,,And now given that it's in the first column,\nDialogue: 0,0:35:47.77,0:35:49.98,EN,,0,0,0,,I'll try and put the next queen down in the first column.\nDialogue: 0,0:35:50.60,0:35:52.17,EN,,0,0,0,,That's no good, they're both...\nDialogue: 0,0:35:53.31,0:35:54.60,EN,,0,0,0,,I'll try and put the first queen,\nDialogue: 0,0:35:54.86,0:35:56.80,EN,,0,0,0,,the one in the first column, down in the first row.\nDialogue: 0,0:35:56.92,0:35:57.47,EN,,0,0,0,,I'm sorry.\nDialogue: 0,0:35:59.05,0:36:01.39,EN,,0,0,0,,And then given that, we'll put the next queen down in the first row.\nDialogue: 0,0:36:01.39,0:36:02.09,EN,,0,0,0,,And that's no good.\nDialogue: 0,0:36:02.09,0:36:03.18,EN,,0,0,0,,So I'll back up to here.\nDialogue: 0,0:36:04.20,0:36:04.72,EN,,0,0,0,,And I'll say,\nDialogue: 0,0:36:04.83,0:36:06.86,EN,,0,0,0,,oh, can I put the first queen down in the second row?\nDialogue: 0,0:36:07.32,0:36:08.38,EN,,0,0,0,,Well, that's no good.\nDialogue: 0,0:36:08.55,0:36:09.76,EN,,0,0,0,,Oh, can I put it down in the third row?\nDialogue: 0,0:36:09.76,0:36:10.52,EN,,0,0,0,,Well, that's good.\nDialogue: 0,0:36:12.79,0:36:15.13,EN,,0,0,0,,Well, now can I put the next queen down in the first column?\nDialogue: 0,0:36:15.38,0:36:17.82,EN,,0,0,0,,Well, I can't visualize this chess board anymore,\nDialogue: 0,0:36:17.82,0:36:18.86,EN,,0,0,0,,but I think that's right.\nDialogue: 0,0:36:19.19,0:36:20.45,EN,,0,0,0,,And I try the next one.\nDialogue: 0,0:36:20.45,0:36:24.17,EN,,0,0,0,,And at each place, I go as far down this tree as I can.\nDialogue: 0,0:36:24.54,0:36:25.64,EN,,0,0,0,,And I back up.\nDialogue: 0,0:36:25.64,0:36:28.97,EN,,0,0,0,,If I get down to here and find no possibilities below there,\nDialogue: 0,0:36:29.00,0:36:30.12,EN,,0,0,0,,I back all the way up to here,\nDialogue: 0,0:36:30.28,0:36:32.44,EN,,0,0,0,,and now start again generating this sub-tree.\nDialogue: 0,0:36:33.26,0:36:34.32,EN,,0,0,0,,And I sort of walk around.\nDialogue: 0,0:36:35.05,0:36:37.26,EN,,0,0,0,,And finally, if I ever manage to get all the way down,\nDialogue: 0,0:36:37.72,0:36:38.59,EN,,0,0,0,,I've found a solution.\nDialogue: 0,0:36:39.82,0:36:41.98,EN,,0,0,0,,So that's a typical sort of\nDialogue: 0,0:36:43.12,0:36:45.93,EN,,0,0,0,,paradigm that's used a lot in AI programming.\nDialogue: 0,0:36:45.93,0:36:47.30,EN,,0,0,0,,It's called backtracking search.\nDialogue: 0,0:36:57.47,0:37:03.04,EN,,0,0,0,,And it's really unnecessary.\nDialogue: 0,0:37:03.86,0:37:06.55,EN,,0,0,0,,You saw me get confused when I was visualizing this thing.\nDialogue: 0,0:37:06.81,0:37:08.25,EN,,0,0,0,,And you sort of see the complication.\nDialogue: 0,0:37:08.55,0:37:10.76,EN,,0,0,0,,This is a complicated thing to say.\nDialogue: 0,0:37:10.76,0:37:11.82,EN,,0,0,0,,Why is it complicated?\nDialogue: 0,0:37:12.39,0:37:13.29,EN,,0,0,0,,Its because somehow\nDialogue: 0,0:37:13.53,0:37:17.39,EN,,0,0,0,,this program is too inordinately concerned with time.\nDialogue: 0,0:37:18.58,0:37:20.43,EN,,0,0,0,,It's too much-- I try this one, and I try this one,\nDialogue: 0,0:37:20.49,0:37:22.38,EN,,0,0,0,,and I go back to the last possibility.\nDialogue: 0,0:37:22.89,0:37:24.34,EN,,0,0,0,,And that's a complicated thing.\nDialogue: 0,0:37:24.34,0:37:26.36,EN,,0,0,0,,If I stop worrying about time so much,\nDialogue: 0,0:37:28.04,0:37:29.76,EN,,0,0,0,,then there's a much simpler way to describe this.\nDialogue: 0,0:37:31.20,0:37:32.36,EN,,0,0,0,,It says, let's imagine\nDialogue: 0,0:37:33.31,0:37:36.57,EN,,0,0,0,,that I have in my hands\nDialogue: 0,0:37:38.32,0:37:42.16,EN,,0,0,0,,the tree down to k minus 1 levels.\nDialogue: 0,0:37:43.40,0:37:46.32,EN,,0,0,0,,See, suppose I had in my hands all possible ways\nDialogue: 0,0:37:48.09,0:37:52.19,EN,,0,0,0,,to solve... to put down queens in the first k columns.\nDialogue: 0,0:37:53.56,0:37:54.61,EN,,0,0,0,,Suppose I just had that.\nDialogue: 0,0:37:54.61,0:37:55.79,EN,,0,0,0,,Let's not worry about how we get it.\nDialogue: 0,0:37:57.07,0:37:59.20,EN,,0,0,0,,Well, then, how do I extend that?\nDialogue: 0,0:37:59.20,0:38:02.16,EN,,0,0,0,,How do I find all possible ways to put down queens in the next column?\nDialogue: 0,0:38:02.48,0:38:03.13,EN,,0,0,0,,It's really easy.\nDialogue: 0,0:38:03.62,0:38:06.41,EN,,0,0,0,,For each of these positions I have,\nDialogue: 0,0:38:07.82,0:38:13.96,EN,,0,0,0,,I enjoin, I think about putting down a queen in each row\nDialogue: 0,0:38:15.08,0:38:16.16,EN,,0,0,0,,to make the next thing.\nDialogue: 0,0:38:16.16,0:38:17.29,EN,,0,0,0,,And then for each one I put down,\nDialogue: 0,0:38:17.44,0:38:19.71,EN,,0,0,0,,I filter those by the ones that are safe.\nDialogue: 0,0:38:21.80,0:38:22.99,EN,,0,0,0,,So instead of thinking about\nDialogue: 0,0:38:22.99,0:38:24.67,EN,,0,0,0,,this tree as generated step by step,\nDialogue: 0,0:38:24.94,0:38:26.86,EN,,0,0,0,,I say, suppose I had it all there.\nDialogue: 0,0:38:29.68,0:38:32.41,EN,,0,0,0,,And to extend it from level k minus 1 to level k,\nDialogue: 0,0:38:32.64,0:38:36.24,EN,,0,0,0,,I just need to extend each thing in all possible ways\nDialogue: 0,0:38:36.48,0:38:37.80,EN,,0,0,0,,and only keep the ones that are safe.\nDialogue: 0,0:38:37.80,0:38:39.23,EN,,0,0,0,,And that will give me the tree to level k.\nDialogue: 0,0:38:39.30,0:38:40.67,EN,,0,0,0,,And that's a recursive strategy\nDialogue: 0,0:38:40.89,0:38:42.17,EN,,0,0,0,,for solving the eight queens problem.\nDialogue: 0,0:38:44.53,0:38:45.34,EN,,0,0,0,,All right, well, let's look at it.\nDialogue: 0,0:38:50.33,0:38:52.68,EN,,0,0,0,,To solve the eight queens problem\nDialogue: 0,0:38:53.00,0:38:55.53,EN,,0,0,0,,on a board of some specified size,\nDialogue: 0,0:38:58.92,0:39:01.03,EN,,0,0,0,,we write a sub-procedure called fill-columns.\nDialogue: 0,0:39:01.13,0:39:04.86,EN,,0,0,0,,Fill-columns is going to put down queens up through column k.\nDialogue: 0,0:39:06.35,0:39:07.70,EN,,0,0,0,,And here's the pattern of the recursion.\nDialogue: 0,0:39:07.70,0:39:10.92,EN,,0,0,0,,I'm going to call fill-columns with the size eventually.\nDialogue: 0,0:39:12.99,0:39:15.28,EN,,0,0,0,,So fill-columns says how to put down queens safely\nDialogue: 0,0:39:15.29,0:39:17.16,EN,,0,0,0,,safely in the first k columns of this chess board\nDialogue: 0,0:39:17.20,0:39:19.58,EN,,0,0,0,,with a size number of rows in it.\nDialogue: 0,0:39:20.36,0:39:21.64,EN,,0,0,0,,If k is equal to 0,\nDialogue: 0,0:39:22.27,0:39:23.60,EN,,0,0,0,,well, then I don't have to put anything down.\nDialogue: 0,0:39:23.94,0:39:25.93,EN,,0,0,0,,So my solution is just an empty chess board.\nDialogue: 0,0:39:26.71,0:39:28.07,EN,,0,0,0,,Otherwise, I'm going to do some stuff.\nDialogue: 0,0:39:28.35,0:39:29.44,EN,,0,0,0,,And I'm going to use collect.\nDialogue: 0,0:39:30.81,0:39:31.77,EN,,0,0,0,,And here's the collect.\nDialogue: 0,0:39:34.33,0:39:41.91,EN,,0,0,0,,I find all ways to put down queens in the first k minus 1 columns.\nDialogue: 0,0:39:42.19,0:39:43.32,EN,,0,0,0,,And this was just what I set for.\nDialogue: 0,0:39:43.32,0:39:46.36,EN,,0,0,0,,Imagine I have this tree down to k minus 1 levels.\nDialogue: 0,0:39:48.88,0:39:52.11,EN,,0,0,0,,And then I find all ways of trying a row,\nDialogue: 0,0:39:52.52,0:39:54.13,EN,,0,0,0,,that's just each of the possible rows.\nDialogue: 0,0:39:54.13,0:39:55.04,EN,,0,0,0,,They're size rows,\nDialogue: 0,0:39:55.31,0:39:56.49,EN,,0,0,0,,so that's enumerate interval.\nDialogue: 0,0:39:58.04,0:39:59.79,EN,,0,0,0,,And now what I do is I collect together\nDialogue: 0,0:40:03.15,0:40:05.82,EN,,0,0,0,,the new row I'm going to try and column k\nDialogue: 0,0:40:07.95,0:40:08.95,EN,,0,0,0,,with the rest of the queens.\nDialogue: 0,0:40:08.95,0:40:10.09,EN,,0,0,0,,I adjoin a position.\nDialogue: 0,0:40:10.20,0:40:11.29,EN,,0,0,0,,This is George's problem.\nDialogue: 0,0:40:11.29,0:40:12.75,EN,,0,0,0,,An adjoined position is like safe.\nDialogue: 0,0:40:13.64,0:40:15.28,EN,,0,0,0,,It's a thing that takes a row\nDialogue: 0,0:40:15.50,0:40:17.04,EN,,0,0,0,,and a column and the rest of the positions\nDialogue: 0,0:40:17.07,0:40:19.02,EN,,0,0,0,,and makes a new position collection.\nDialogue: 0,0:40:19.66,0:40:25.77,EN,,0,0,0,,So I adjoin a position of a new row and a new column\nDialogue: 0,0:40:26.06,0:40:27.68,EN,,0,0,0,,to the rest of the queens,\nDialogue: 0,0:40:28.57,0:40:29.76,EN,,0,0,0,,where the rest of the queens\nDialogue: 0,0:40:29.92,0:40:31.45,EN,,0,0,0,,runs through all possible ways\nDialogue: 0,0:40:31.87,0:40:34.16,EN,,0,0,0,,of solving the problem in k minus 1 columns.\nDialogue: 0,0:40:34.62,0:40:37.04,EN,,0,0,0,,And the new row runs through all possible rows\nDialogue: 0,0:40:37.85,0:40:40.76,EN,,0,0,0,,such that it was safe to put one there.\nDialogue: 0,0:40:43.24,0:40:44.70,EN,,0,0,0,,And that's the whole program.\nDialogue: 0,0:40:46.33,0:40:47.31,EN,,0,0,0,,There's the whole procedure.\nDialogue: 0,0:40:49.84,0:40:52.43,EN,,0,0,0,,Not only that, that doesn't just solve the eight queens problem,\nDialogue: 0,0:40:53.42,0:40:56.68,EN,,0,0,0,,Right? It gives you all solutions to the eight queens problem.\nDialogue: 0,0:40:56.68,0:40:58.48,EN,,0,0,0,,When you're done, you have a stream.\nDialogue: 0,0:40:58.48,0:41:01.90,EN,,0,0,0,,And the elements of that stream are all possible ways of solving that problem.\nDialogue: 0,0:41:05.31,0:41:06.26,EN,,0,0,0,,Why is that simpler?\nDialogue: 0,0:41:06.26,0:41:08.54,EN,,0,0,0,,Well, we threw away the whole idea that\nDialogue: 0,0:41:08.88,0:41:11.52,EN,,0,0,0,,is some process that happens in time with state.\nDialogue: 0,0:41:12.72,0:41:14.42,EN,,0,0,0,,And we just said it's a whole collection of stuff.\nDialogue: 0,0:41:14.94,0:41:16.00,EN,,0,0,0,,And that's why it's simpler.\nDialogue: 0,0:41:18.00,0:41:20.11,EN,,0,0,0,,Right? We've changed our view.\nDialogue: 0,0:41:20.11,0:41:22.59,EN,,0,0,0,,Remember, that's where we started today.\nDialogue: 0,0:41:22.82,0:41:26.23,EN,,0,0,0,,We've changed our view of what it is we're trying to model.\nDialogue: 0,0:41:26.23,0:41:29.20,EN,,0,0,0,,we stop modeling things that evolve in time\nDialogue: 0,0:41:29.37,0:41:31.31,EN,,0,0,0,,have steps and have state.\nDialogue: 0,0:41:31.75,0:41:33.79,EN,,0,0,0,,And instead, we're trying to model this global thing\nDialogue: 0,0:41:33.80,0:41:35.93,EN,,0,0,0,,like the whole flight of the chalk,\nDialogue: 0,0:41:36.28,0:41:38.88,EN,,0,0,0,,rather than its state at each instant.\nDialogue: 0,0:41:40.75,0:41:41.44,EN,,0,0,0,,Any questions?\nDialogue: 0,0:41:44.08,0:41:46.20,EN,,0,0,0,,AUDIENCE: It looks to me like backtracking would be\nDialogue: 0,0:41:46.22,0:41:48.96,EN,,0,0,0,,searching for the first solution it can find,\nDialogue: 0,0:41:49.31,0:41:51.48,EN,,0,0,0,,whereas this recursive search\nDialogue: 0,0:41:51.48,0:41:53.26,EN,,0,0,0,,would be looking for all solutions.\nDialogue: 0,0:41:53.32,0:41:53.60,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:41:54.03,0:41:55.26,EN,,0,0,0,,AUDIENCE: And it seems that\nDialogue: 0,0:41:55.26,0:41:57.92,EN,,0,0,0,,if you have a large enough area to search,\nDialogue: 0,0:41:57.92,0:42:00.92,EN,,0,0,0,,that the second is going to become impossible.\nDialogue: 0,0:42:01.36,0:42:05.93,EN,,0,0,0,,PROFESSOR: OK, the answer to that question\nDialogue: 0,0:42:07.13,0:42:08.44,EN,,0,0,0,,is the whole rest of this lecture.\nDialogue: 0,0:42:08.57,0:42:10.54,EN,,0,0,0,,It's exactly the right question.\nDialogue: 0,0:42:13.87,0:42:15.74,EN,,0,0,0,,And without trying to anticipate the lecture too much,\nDialogue: 0,0:42:15.96,0:42:19.23,EN,,0,0,0,,you should start being suspicious at this point,\nDialogue: 0,0:42:19.84,0:42:21.84,EN,,0,0,0,,and exactly those kinds of suspicions. Isn't it?\nDialogue: 0,0:42:22.22,0:42:24.51,EN,,0,0,0,,It's wonderful, but isn't it so terribly inefficient?\nDialogue: 0,0:42:24.83,0:42:26.03,EN,,0,0,0,,That's where we're going.\nDialogue: 0,0:42:28.10,0:42:30.02,EN,,0,0,0,,So I won't answer now, but I'll answer later.\nDialogue: 0,0:42:33.35,0:42:34.60,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:42:34.60,0:42:44.51,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:43:29.65,0:43:33.76,EN,,0,0,0,,Well, by now you should be starting to get suspicious.\nDialogue: 0,0:43:35.60,0:43:39.26,EN,,0,0,0,,See, I've showed your this simple, elegant\nDialogue: 0,0:43:40.51,0:43:42.28,EN,,0,0,0,,of putting programs together,\nDialogue: 0,0:43:42.86,0:43:46.91,EN,,0,0,0,,very unlike these other traditional programs\nDialogue: 0,0:43:46.92,0:43:48.19,EN,,0,0,0,,that sum the odd squares\nDialogue: 0,0:43:48.72,0:43:51.32,EN,,0,0,0,,or compute the odd Fibonacci numbers.\nDialogue: 0,0:43:53.74,0:43:55.48,EN,,0,0,0,,Very unlike these programs that mix up\nDialogue: 0,0:43:55.85,0:43:58.84,EN,,0,0,0,,the enumerator and the filter and the accumulator.\nDialogue: 0,0:44:00.44,0:44:01.82,EN,,0,0,0,,And by mixing it up,\nDialogue: 0,0:44:02.20,0:44:04.59,EN,,0,0,0,,we don't have all of these wonderful\nDialogue: 0,0:44:04.62,0:44:07.34,EN,,0,0,0,,conceptual advantages of these streams pieces,\nDialogue: 0,0:44:07.82,0:44:09.53,EN,,0,0,0,,these wonderful mix and match components\nDialogue: 0,0:44:09.55,0:44:11.77,EN,,0,0,0,,for putting together lots and lots of programs.\nDialogue: 0,0:44:13.80,0:44:14.25,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:44:14.28,0:44:16.88,EN,,0,0,0,,most of the programs you've seen look like these ugly ones.\nDialogue: 0,0:44:18.34,0:44:18.94,EN,,0,0,0,,Why's that?\nDialogue: 0,0:44:19.20,0:44:20.59,EN,,0,0,0,,Can it possibly be\nDialogue: 0,0:44:21.16,0:44:24.30,EN,,0,0,0,,that computer scientists are so obtuse\nDialogue: 0,0:44:25.42,0:44:26.44,EN,,0,0,0,,that they don't notice\nDialogue: 0,0:44:27.07,0:44:28.75,EN,,0,0,0,,that if you'd merely did this thing,\nDialogue: 0,0:44:29.63,0:44:31.93,EN,,0,0,0,,then you can get this great programming elegance?\nDialogue: 0,0:44:33.62,0:44:34.78,EN,,0,0,0,,There's got to be a catch.\nDialogue: 0,0:44:36.76,0:44:39.05,EN,,0,0,0,,And it's actually pretty easy to see what the catch is.\nDialogue: 0,0:44:39.51,0:44:41.74,EN,,0,0,0,,Let's think about the following problem.\nDialogue: 0,0:44:42.03,0:44:45.47,EN,,0,0,0,,Suppose I tell you to find the second prime\nDialogue: 0,0:44:46.16,0:44:48.16,EN,,0,0,0,,between 10,000 and 1 million,\nDialogue: 0,0:44:49.12,0:44:50.56,EN,,0,0,0,,or if your computer's larger,\nDialogue: 0,0:44:50.59,0:44:53.05,EN,,0,0,0,,say between 10,000 and 100 billion, or something.\nDialogue: 0,0:44:54.32,0:44:55.45,EN,,0,0,0,,And you say, oh, that's easy.\nDialogue: 0,0:44:55.47,0:44:56.65,EN,,0,0,0,,I can do that with a stream.\nDialogue: 0,0:44:57.08,0:44:59.87,EN,,0,0,0,,All I do is I enumerate\nDialogue: 0,0:45:00.57,0:45:02.89,EN,,0,0,0,,the interval from 10,000 to 1 million.\nDialogue: 0,0:45:04.16,0:45:06.51,EN,,0,0,0,,So I get all those integers from 10,000 to 1 million.\nDialogue: 0,0:45:06.80,0:45:08.64,EN,,0,0,0,,I filter them for prime-ness,\nDialogue: 0,0:45:09.39,0:45:11.10,EN,,0,0,0,,so test all of them and see if they're prime.\nDialogue: 0,0:45:11.76,0:45:12.83,EN,,0,0,0,,And I take the second element.\nDialogue: 0,0:45:12.84,0:45:14.04,EN,,0,0,0,,Right? That's the head of the tail.\nDialogue: 0,0:45:15.79,0:45:17.38,EN,,0,0,0,,OK? Well, that's clearly pretty ridiculous.\nDialogue: 0,0:45:21.66,0:45:23.20,EN,,0,0,0,,We'd not even have room in the machine\nDialogue: 0,0:45:23.58,0:45:25.24,EN,,0,0,0,,Right? To store the integers in the first place,\nDialogue: 0,0:45:25.28,0:45:26.35,EN,,0,0,0,,much less to test them.\nDialogue: 0,0:45:27.04,0:45:28.64,EN,,0,0,0,,And then I only want the second one.\nDialogue: 0,0:45:29.81,0:45:34.94,EN,,0,0,0,,See, the power of this traditional programming style\nDialogue: 0,0:45:36.43,0:45:37.68,EN,,0,0,0,,is exactly its weakness,\nDialogue: 0,0:45:37.96,0:45:38.94,EN,,0,0,0,,that we're mixing up\nDialogue: 0,0:45:39.61,0:45:43.50,EN,,0,0,0,,the enumerating and the testing and the accumulating.\nDialogue: 0,0:45:44.88,0:45:46.46,EN,,0,0,0,,Right? We sort of don't do it all.\nDialogue: 0,0:45:46.67,0:45:49.18,EN,,0,0,0,,So by the actual... so the very thing\nDialogue: 0,0:45:49.45,0:45:51.74,EN,,0,0,0,,makes it conceptually ugly\nDialogue: 0,0:45:52.20,0:45:53.80,EN,,0,0,0,,is the very thing that makes it efficient.\nDialogue: 0,0:45:54.91,0:45:55.84,EN,,0,0,0,,Right? It's this mixing up.\nDialogue: 0,0:45:57.80,0:45:59.34,EN,,0,0,0,,So it seems that all I've done this morning so far\nDialogue: 0,0:45:59.34,0:46:00.42,EN,,0,0,0,,is just confuse you.\nDialogue: 0,0:46:00.42,0:46:03.10,EN,,0,0,0,,I showed you this wonderful way that programming might work,\nDialogue: 0,0:46:03.10,0:46:03.96,EN,,0,0,0,,except that it doesn't.\nDialogue: 0,0:46:05.84,0:46:08.32,EN,,0,0,0,,Well, here's where the wonderful thing happens.\nDialogue: 0,0:46:09.04,0:46:10.57,EN,,0,0,0,,It turns out in this game\nDialogue: 0,0:46:11.21,0:46:13.84,EN,,0,0,0,,that we really can have our cake and eat it too.\nDialogue: 0,0:46:14.87,0:46:16.11,EN,,0,0,0,,And what I mean by that\nDialogue: 0,0:46:18.09,0:46:21.15,EN,,0,0,0,,is that we really can write stream programs\nDialogue: 0,0:46:21.16,0:46:22.48,EN,,0,0,0,,exactly like the ones I wrote\nDialogue: 0,0:46:23.55,0:46:27.74,EN,,0,0,0,,and arrange things so that when the machine actually runs,\nDialogue: 0,0:46:28.33,0:46:31.52,EN,,0,0,0,,it's as efficient as running this traditional programming style\nDialogue: 0,0:46:31.71,0:46:34.28,EN,,0,0,0,,that mixes up the generation and the test.\nDialogue: 0,0:46:36.16,0:46:38.80,EN,,0,0,0,,Well, that sounds pretty magic.\nDialogue: 0,0:46:40.77,0:46:41.82,EN,,0,0,0,,The key to this\nDialogue: 0,0:46:42.00,0:46:43.69,EN,,0,0,0,,is that streams are not lists.\nDialogue: 0,0:46:48.09,0:46:49.79,EN,,0,0,0,,We'll see this carefully in a second, but for now,\nDialogue: 0,0:46:49.80,0:46:51.77,EN,,0,0,0,,let's take a look at that slide again.\nDialogue: 0,0:46:52.24,0:46:53.80,EN,,0,0,0,,The image you should have here\nDialogue: 0,0:46:53.84,0:46:55.58,EN,,0,0,0,,of this signal processing system\nDialogue: 0,0:46:57.26,0:46:58.72,EN,,0,0,0,,is that what's going to happen\nDialogue: 0,0:46:59.13,0:47:00.92,EN,,0,0,0,,is there's sort of this box\nDialogue: 0,0:47:01.18,0:47:03.58,EN,,0,0,0,,that has the integers sitting in it.\nDialogue: 0,0:47:05.36,0:47:06.40,EN,,0,0,0,,And there's this filter\nDialogue: 0,0:47:07.45,0:47:09.37,EN,,0,0,0,,that's connected to it and it's tugging on them.\nDialogue: 0,0:47:10.94,0:47:13.15,EN,,0,0,0,,And then there's someone who's tugging on this stuff\nDialogue: 0,0:47:13.31,0:47:14.91,EN,,0,0,0,,saying what comes out of the filter.\nDialogue: 0,0:47:16.79,0:47:18.70,EN,,0,0,0,,And the image you should have is that\nDialogue: 0,0:47:18.99,0:47:20.72,EN,,0,0,0,,someone says, well, what's the first prime,\nDialogue: 0,0:47:22.67,0:47:24.14,EN,,0,0,0,,and tugs on this filter.\nDialogue: 0,0:47:24.59,0:47:26.12,EN,,0,0,0,,And the filter tugs on the integers.\nDialogue: 0,0:47:28.02,0:47:29.15,EN,,0,0,0,,And you look only at that much,\nDialogue: 0,0:47:29.16,0:47:30.93,EN,,0,0,0,,and then say, oh, I really wanted the second one.\nDialogue: 0,0:47:30.93,0:47:31.95,EN,,0,0,0,,What's the second prime?\nDialogue: 0,0:47:33.71,0:47:35.37,EN,,0,0,0,,And that no other computation\nDialogue: 0,0:47:35.37,0:47:36.64,EN,,0,0,0,,no computation gets done\nDialogue: 0,0:47:36.64,0:47:38.32,EN,,0,0,0,,except when you tug on these things.\nDialogue: 0,0:47:40.50,0:47:41.41,EN,,0,0,0,,Let me try that again.\nDialogue: 0,0:47:41.41,0:47:43.88,EN,,0,0,0,,This is a little device.\nDialogue: 0,0:47:43.90,0:47:44.97,EN,,0,0,0,,This is a little stream machine\nDialogue: 0,0:47:45.50,0:47:46.83,EN,,0,0,0,,invented by Eric Grimson\nDialogue: 0,0:47:47.60,0:47:49.24,EN,,0,0,0,,who's been teaching this course at MIT.\nDialogue: 0,0:47:49.83,0:47:52.51,EN,,0,0,0,,And the image is ... here's a stream of stuff,\nDialogue: 0,0:47:52.54,0:47:53.82,EN,,0,0,0,,like a whole bunch of the integers.\nDialogue: 0,0:47:54.78,0:47:56.33,EN,,0,0,0,,And here's some processing elements.\nDialogue: 0,0:47:58.70,0:48:02.60,EN,,0,0,0,,And if, say, it's filter of filter of map, or something.\nDialogue: 0,0:48:03.98,0:48:09.18,EN,,0,0,0,,And if I really tried to implement that with streams as lists,\nDialogue: 0,0:48:09.24,0:48:11.26,EN,,0,0,0,,what I'd say is, well, I've got this list of things,\nDialogue: 0,0:48:11.47,0:48:12.67,EN,,0,0,0,,and now I do the first filter.\nDialogue: 0,0:48:12.67,0:48:14.07,EN,,0,0,0,,So I sort of do all this processing.\nDialogue: 0,0:48:14.88,0:48:15.77,EN,,0,0,0,,And I take this\nDialogue: 0,0:48:16.32,0:48:19.21,EN,,0,0,0,,and I process and I process and I process and I process.\nDialogue: 0,0:48:19.61,0:48:21.05,EN,,0,0,0,,And now I'm got this new stream.\nDialogue: 0,0:48:21.63,0:48:24.07,EN,,0,0,0,,Right? Now I take that result in my hand someplace.\nDialogue: 0,0:48:24.07,0:48:25.26,EN,,0,0,0,,And I put that through the second one.\nDialogue: 0,0:48:25.56,0:48:26.94,EN,,0,0,0,,And I process the whole thing.\nDialogue: 0,0:48:28.27,0:48:29.51,EN,,0,0,0,,And there's this new stream.\nDialogue: 0,0:48:32.13,0:48:33.36,EN,,0,0,0,,And then I take the result\nDialogue: 0,0:48:34.28,0:48:36.36,EN,,0,0,0,,and I put it all the way through this one the same way.\nDialogue: 0,0:48:36.36,0:48:40.99,EN,,0,0,0,,That's what would happen to these stream programs\nDialogue: 0,0:48:41.69,0:48:42.97,EN,,0,0,0,,if streams were just lists.\nDialogue: 0,0:48:43.86,0:48:45.64,EN,,0,0,0,,But in fact, streams aren't lists, they're streams.\nDialogue: 0,0:48:45.82,0:48:48.11,EN,,0,0,0,,And the image you should have is something a little bit more like this.\nDialogue: 0,0:48:50.23,0:48:52.52,EN,,0,0,0,,I've got these gadgets connected up\nDialogue: 0,0:48:55.26,0:48:56.76,EN,,0,0,0,,by this data that's flowing out of them.\nDialogue: 0,0:49:00.33,0:49:02.30,EN,,0,0,0,,And here's my original source of the streams.\nDialogue: 0,0:49:02.32,0:49:02.92,EN,,0,0,0,,It might be\nDialogue: 0,0:49:04.19,0:49:05.72,EN,,0,0,0,,starting to generate the integers.\nDialogue: 0,0:49:05.98,0:49:07.39,EN,,0,0,0,,And now, what happens if I want a result?\nDialogue: 0,0:49:07.58,0:49:08.91,EN,,0,0,0,,I tug on the end here.\nDialogue: 0,0:49:10.20,0:49:11.07,EN,,0,0,0,,And this element says,\nDialogue: 0,0:49:11.08,0:49:12.20,EN,,0,0,0,,gee, I need some more data.\nDialogue: 0,0:49:13.09,0:49:15.52,EN,,0,0,0,,So it's sort of, this one comes here and tugs on that one.\nDialogue: 0,0:49:15.83,0:49:17.39,EN,,0,0,0,,And it says, gee, I need some more data.\nDialogue: 0,0:49:17.89,0:49:19.56,EN,,0,0,0,,And this one tugs on this thing,\nDialogue: 0,0:49:19.56,0:49:20.28,EN,,0,0,0,,which might be a filter,\nDialogue: 0,0:49:20.28,0:49:21.40,EN,,0,0,0,,and says, gee, I need some more data.\nDialogue: 0,0:49:21.64,0:49:23.15,EN,,0,0,0,,And only as much of this\nDialogue: 0,0:49:23.53,0:49:25.56,EN,,0,0,0,,thing at the end here gets generated as I tugged.\nDialogue: 0,0:49:25.78,0:49:28.30,EN,,0,0,0,,And only as much of this stuff goes through the processing units\nDialogue: 0,0:49:28.56,0:49:29.98,EN,,0,0,0,,as I'm pulling on the end I need.\nDialogue: 0,0:49:30.76,0:49:32.09,EN,,0,0,0,,That's the image you should have\nDialogue: 0,0:49:32.80,0:49:34.38,EN,,0,0,0,,of the difference between implementing\nDialogue: 0,0:49:34.56,0:49:35.92,EN,,0,0,0,,what we're actually going to do\nDialogue: 0,0:49:36.16,0:49:37.50,EN,,0,0,0,,and if streams were lists.\nDialogue: 0,0:49:40.78,0:49:42.14,EN,,0,0,0,,Well, how do we make this thing?\nDialogue: 0,0:49:42.35,0:49:43.32,EN,,0,0,0,,I hope you have the image.\nDialogue: 0,0:49:43.40,0:49:44.52,EN,,0,0,0,,The trick is how to make it.\nDialogue: 0,0:49:47.93,0:49:50.32,EN,,0,0,0,,We want to arrange for a stream\nDialogue: 0,0:49:50.41,0:49:51.58,EN,,0,0,0,,to be a data structure\nDialogue: 0,0:49:52.00,0:49:54.22,EN,,0,0,0,,that sorts of computes itself incrementally,\nDialogue: 0,0:49:54.22,0:49:56.22,EN,,0,0,0,,sort of on-demand data structure.\nDialogue: 0,0:49:58.96,0:50:00.51,EN,,0,0,0,,Right? And the basic idea\nDialogue: 0,0:50:00.97,0:50:02.70,EN,,0,0,0,,is again, one of the very basic ideas\nDialogue: 0,0:50:02.72,0:50:04.12,EN,,0,0,0,,that we're seeing throughout the whole course.\nDialogue: 0,0:50:04.49,0:50:05.00,EN,,0,0,0,,And that is\nDialogue: 0,0:50:05.52,0:50:06.97,EN,,0,0,0,,that there's not a firm distinction\nDialogue: 0,0:50:06.99,0:50:08.44,EN,,0,0,0,,between programs and data.\nDialogue: 0,0:50:09.24,0:50:10.54,EN,,0,0,0,,So what a stream is going to be\nDialogue: 0,0:50:10.59,0:50:13.40,EN,,0,0,0,,is simultaneously this data structure that you think of,\nDialogue: 0,0:50:13.45,0:50:15.92,EN,,0,0,0,,like the stream of the leaves of this tree.\nDialogue: 0,0:50:16.86,0:50:17.85,EN,,0,0,0,,But at the same time,\nDialogue: 0,0:50:17.85,0:50:19.32,EN,,0,0,0,,it's going to be a very clever procedure\nDialogue: 0,0:50:20.24,0:50:22.22,EN,,0,0,0,,that has the method of computing in it.\nDialogue: 0,0:50:23.74,0:50:25.93,EN,,0,0,0,,Well, let me try this.\nDialogue: 0,0:50:25.93,0:50:26.62,EN,,0,0,0,,It's going to turn out\nDialogue: 0,0:50:26.80,0:50:28.33,EN,,0,0,0,,that we don't need any more mechanism.\nDialogue: 0,0:50:28.46,0:50:29.87,EN,,0,0,0,,We already have everything we need\nDialogue: 0,0:50:30.14,0:50:30.99,EN,,0,0,0,,simply from the fact\nDialogue: 0,0:50:31.02,0:50:33.93,EN,,0,0,0,,that we know how to handle procedures as first-class objects.\nDialogue: 0,0:50:35.46,0:50:36.88,EN,,0,0,0,,Well, let's go back to the key.\nDialogue: 0,0:50:36.88,0:50:39.03,EN,,0,0,0,,The key is, remember, we had these operations.\nDialogue: 0,0:50:39.03,0:50:47.52,EN,,0,0,0,,CONS-stream and head and tail.\nDialogue: 0,0:50:48.08,0:50:49.36,EN,,0,0,0,,When I started, I said\nDialogue: 0,0:50:49.92,0:50:51.36,EN,,0,0,0,,you can think about this as CONS\nDialogue: 0,0:50:51.40,0:50:52.62,EN,,0,0,0,,and think about this as CAR\nDialogue: 0,0:50:52.62,0:50:53.52,EN,,0,0,0,,and think about that as CDR\nDialogue: 0,0:50:53.55,0:50:54.16,EN,,0,0,0,,but it's not.\nDialogue: 0,0:50:55.08,0:50:56.32,EN,,0,0,0,,Now, let's look at what they really are.\nDialogue: 0,0:50:57.71,0:51:05.84,EN,,0,0,0,,Well, CONS-stream of x and y\nDialogue: 0,0:51:07.48,0:51:17.79,EN,,0,0,0,,is going to be an abbreviation for the following thing.\nDialogue: 0,0:51:19.54,0:51:28.32,EN,,0,0,0,,CONS form a pair, ordinary CONS, of x to a thing called delay of y.\nDialogue: 0,0:51:31.68,0:51:33.53,EN,,0,0,0,,And before I explain that, let me go and write the rest.\nDialogue: 0,0:51:34.52,0:51:35.53,EN,,0,0,0,,The head of a stream\nDialogue: 0,0:51:38.09,0:51:39.79,EN,,0,0,0,,is going to be just the CAR.\nDialogue: 0,0:51:42.38,0:51:44.25,EN,,0,0,0,,And the tail of a stream\nDialogue: 0,0:51:46.68,0:51:54.60,EN,,0,0,0,,is going to be a thing called force the CDR of the stream.\nDialogue: 0,0:51:56.12,0:51:57.04,EN,,0,0,0,,Now let me explain this.\nDialogue: 0,0:51:58.06,0:51:59.88,EN,,0,0,0,,Delay is going to be a special magic thing.\nDialogue: 0,0:52:01.42,0:52:02.33,EN,,0,0,0,,What delay does\nDialogue: 0,0:52:03.85,0:52:05.31,EN,,0,0,0,,is take an expression\nDialogue: 0,0:52:05.50,0:52:06.86,EN,,0,0,0,,and produce a promise\nDialogue: 0,0:52:07.12,0:52:09.15,EN,,0,0,0,,to compute that expression when you ask for it.\nDialogue: 0,0:52:10.60,0:52:11.98,EN,,0,0,0,,It doesn't do any computation here.\nDialogue: 0,0:52:11.98,0:52:14.32,EN,,0,0,0,,Just sort of... It just gives you a rain check.\nDialogue: 0,0:52:14.82,0:52:16.20,EN,,0,0,0,,It produces a promise.\nDialogue: 0,0:52:17.11,0:52:18.20,EN,,0,0,0,,And CONS-stream says\nDialogue: 0,0:52:18.81,0:52:21.96,EN,,0,0,0,,I'm going to put together in a pair x\nDialogue: 0,0:52:23.31,0:52:25.36,EN,,0,0,0,,and a promise to compute y.\nDialogue: 0,0:52:28.23,0:52:28.99,EN,,0,0,0,,Now, if I want the head,\nDialogue: 0,0:52:28.99,0:52:30.75,EN,,0,0,0,,that's just the CAR that I put in the pair.\nDialogue: 0,0:52:31.84,0:52:33.71,EN,,0,0,0,,And the key is that the tail is going to be--\nDialogue: 0,0:52:34.62,0:52:36.65,EN,,0,0,0,,force calls in that promise.\nDialogue: 0,0:52:38.22,0:52:39.88,EN,,0,0,0,,Force -- Tail says, well,\nDialogue: 0,0:52:40.03,0:52:41.02,EN,,0,0,0,,well, take that promise\nDialogue: 0,0:52:41.85,0:52:44.52,EN,,0,0,0,,and now call in that promise.\nDialogue: 0,0:52:44.56,0:52:46.03,EN,,0,0,0,,And then we compute that thing.\nDialogue: 0,0:52:47.69,0:52:48.72,EN,,0,0,0,,That's how this is going to work.\nDialogue: 0,0:52:48.74,0:52:51.55,EN,,0,0,0,,That's what CONS-stream, head, and tail really are.\nDialogue: 0,0:52:54.60,0:52:55.57,EN,,0,0,0,,Now, let's see how this works.\nDialogue: 0,0:52:55.57,0:52:57.50,EN,,0,0,0,,And we'll go through this fairly carefully. Let's --\nDialogue: 0,0:52:58.76,0:53:00.62,EN,,0,0,0,,We're going to see how this\nDialogue: 0,0:53:01.32,0:53:03.66,EN,,0,0,0,,example of computing the second prime\nDialogue: 0,0:53:05.50,0:53:07.16,EN,,0,0,0,,right? between 10,000 and a million.\nDialogue: 0,0:53:08.65,0:53:12.03,EN,,0,0,0,,OK, so we start off and we have this expression.\nDialogue: 0,0:53:15.36,0:53:16.62,EN,,0,0,0,,Right? The second prime--\nDialogue: 0,0:53:16.64,0:53:21.90,EN,,0,0,0,,the head of the tail of the result of filtering for primality\nDialogue: 0,0:53:22.83,0:53:25.31,EN,,0,0,0,,the integers between 10,000 and 1 million.\nDialogue: 0,0:53:26.71,0:53:27.61,EN,,0,0,0,,Now, what is that?\nDialogue: 0,0:53:28.40,0:53:29.20,EN,,0,0,0,,What that is,\nDialogue: 0,0:53:31.63,0:53:34.17,EN,,0,0,0,,that interval between 10,000 and 1 million,\nDialogue: 0,0:53:35.72,0:53:37.32,EN,,0,0,0,,well, if you trace through enumerate interval,\nDialogue: 0,0:53:37.34,0:53:38.78,EN,,0,0,0,,there builds a CONS-stream.\nDialogue: 0,0:53:39.92,0:53:41.39,EN,,0,0,0,,And the CONS-stream is\nDialogue: 0,0:53:41.96,0:53:43.61,EN,,0,0,0,,the CONS of 10,000\nDialogue: 0,0:53:44.51,0:53:48.92,EN,,0,0,0,,to a promise to compute the integers between 10,001 and 1 million.\nDialogue: 0,0:53:54.00,0:53:55.75,EN,,0,0,0,,Okay? So that's what this expression is.\nDialogue: 0,0:53:55.75,0:53:57.32,EN,,0,0,0,,Here I'm using the substitution model.\nDialogue: 0,0:53:57.64,0:53:59.32,EN,,0,0,0,,And we can use the substitution model\nDialogue: 0,0:53:59.34,0:54:01.01,EN,,0,0,0,,because we don't have side effects and state.\nDialogue: 0,0:54:03.56,0:54:06.38,EN,,0,0,0,,Okay? So I have CONS of 10,000\nDialogue: 0,0:54:06.41,0:54:08.27,EN,,0,0,0,,to a promise to compute the rest of the integers.\nDialogue: 0,0:54:08.32,0:54:10.49,EN,,0,0,0,,So only one integer, so far, got enumerated.\nDialogue: 0,0:54:14.38,0:54:16.96,EN,,0,0,0,,Well, I'm going to filter that thing for primality.\nDialogue: 0,0:54:19.44,0:54:21.90,EN,,0,0,0,,Again, you go back and look at the filter code.\nDialogue: 0,0:54:22.36,0:54:24.46,EN,,0,0,0,,What the filter will first do is test the head.\nDialogue: 0,0:54:25.46,0:54:28.25,EN,,0,0,0,,So in this case, the filter will test 10,000\nDialogue: 0,0:54:30.30,0:54:32.97,EN,,0,0,0,,oh, 10,000's not prime.\nDialogue: 0,0:54:33.50,0:54:35.85,EN,,0,0,0,,Therefore, what I have to do recursively\nDialogue: 0,0:54:36.25,0:54:37.39,EN,,0,0,0,,is filter the tail.\nDialogue: 0,0:54:39.22,0:54:40.14,EN,,0,0,0,,And what's the tail of it,\nDialogue: 0,0:54:40.16,0:54:43.76,EN,,0,0,0,,well, that's the tail of this pair with a promise in it.\nDialogue: 0,0:54:46.34,0:54:48.06,EN,,0,0,0,,Tail now comes in and says,\nDialogue: 0,0:54:48.28,0:54:49.50,EN,,0,0,0,,well, I'm going to force that.\nDialogue: 0,0:54:49.68,0:54:50.94,EN,,0,0,0,,I'm going to force that promise,\nDialogue: 0,0:54:52.30,0:54:54.36,EN,,0,0,0,,which means now I'm going to compute\nDialogue: 0,0:54:55.58,0:54:57.96,EN,,0,0,0,,the integers between 10,001 and 1 million.\nDialogue: 0,0:55:00.80,0:55:02.97,EN,,0,0,0,,OK? So this filter now is looking at that.\nDialogue: 0,0:55:07.81,0:55:08.92,EN,,0,0,0,,That enumerate itself,\nDialogue: 0,0:55:08.94,0:55:11.23,EN,,0,0,0,,now we're back in the original enumerate situation.\nDialogue: 0,0:55:11.96,0:55:13.00,EN,,0,0,0,,The enumerate is\nDialogue: 0,0:55:14.12,0:55:16.44,EN,,0,0,0,,CONS of the first thing, 10,001,\nDialogue: 0,0:55:16.60,0:55:18.20,EN,,0,0,0,,onto a promise to compute the rest.\nDialogue: 0,0:55:19.74,0:55:22.75,EN,,0,0,0,,So now the primality filter is going to go look at 10,001.\nDialogue: 0,0:55:23.23,0:55:25.12,EN,,0,0,0,,It's going to decide if it likes that or not.\nDialogue: 0,0:55:25.12,0:55:27.08,EN,,0,0,0,,It turns out 10,001 isn't prime.\nDialogue: 0,0:55:27.55,0:55:29.61,EN,,0,0,0,,So it'll force it again and again and again.\nDialogue: 0,0:55:32.92,0:55:35.80,EN,,0,0,0,,And finally, I think the first prime it hits is 10,009.\nDialogue: 0,0:55:37.10,0:55:38.33,EN,,0,0,0,,And at that point, it'll stop.\nDialogue: 0,0:55:40.84,0:55:41.93,EN,,0,0,0,,And that will be the first prime,\nDialogue: 0,0:55:41.96,0:55:43.48,EN,,0,0,0,,and then eventually, it'll need the second prime.\nDialogue: 0,0:55:45.24,0:55:46.84,EN,,0,0,0,,So at that point, it will go again.\nDialogue: 0,0:55:47.03,0:55:48.25,EN,,0,0,0,,So you see what happens is that\nDialogue: 0,0:55:48.52,0:55:50.49,EN,,0,0,0,,no more gets generated\nDialogue: 0,0:55:51.85,0:55:52.91,EN,,0,0,0,,than you actually need.\nDialogue: 0,0:55:56.48,0:55:59.92,EN,,0,0,0,,That enumerator is not going to generate any more integers\nDialogue: 0,0:56:00.12,0:56:01.45,EN,,0,0,0,,than the filter asks it for\nDialogue: 0,0:56:01.47,0:56:03.45,EN,,0,0,0,,as it's pulling in things to check for primality.\nDialogue: 0,0:56:04.70,0:56:06.51,EN,,0,0,0,,And the filter is not going to generate\nDialogue: 0,0:56:06.54,0:56:08.04,EN,,0,0,0,,any more stuff than you ask it for,\nDialogue: 0,0:56:08.06,0:56:09.10,EN,,0,0,0,,which is the head of the tail.\nDialogue: 0,0:56:11.61,0:56:13.26,EN,,0,0,0,,You see, what's happened is\nDialogue: 0,0:56:14.70,0:56:18.24,EN,,0,0,0,,we've put that mixing of generation and test\nDialogue: 0,0:56:18.67,0:56:20.65,EN,,0,0,0,,into what actually happens in the computer,\nDialogue: 0,0:56:21.52,0:56:22.67,EN,,0,0,0,,even though\nDialogue: 0,0:56:23.18,0:56:25.63,EN,,0,0,0,,that's not apparently what's happening from looking at our programs.\nDialogue: 0,0:56:28.12,0:56:29.40,EN,,0,0,0,,OK, well, that seemed easy.\nDialogue: 0,0:56:30.23,0:56:32.67,EN,,0,0,0,,All of this mechanism got put into this magic delay.\nDialogue: 0,0:56:33.68,0:56:35.66,EN,,0,0,0,,So you're saying, gee, that must be where the magic is.\nDialogue: 0,0:56:36.90,0:56:38.57,EN,,0,0,0,,But see there's no magic there either.\nDialogue: 0,0:56:39.07,0:56:39.98,EN,,0,0,0,,You know what delay is.\nDialogue: 0,0:56:40.61,0:56:45.07,EN,,0,0,0,,Delay on some expression\nDialogue: 0,0:56:48.25,0:56:50.04,EN,,0,0,0,,is just an abbreviation for--\nDialogue: 0,0:56:53.36,0:56:55.63,EN,,0,0,0,,well, what's a promise to compute an expression?\nDialogue: 0,0:56:56.49,0:57:01.12,EN,,0,0,0,,Lambda of nil, procedure of no arguments, which is that expression.\nDialogue: 0,0:57:02.83,0:57:03.84,EN,,0,0,0,,Right? That's what a procedure is.\nDialogue: 0,0:57:03.98,0:57:05.53,EN,,0,0,0,,It says I'm going to compute an expression.\nDialogue: 0,0:57:06.05,0:57:06.73,EN,,0,0,0,,What's force?\nDialogue: 0,0:57:07.34,0:57:10.80,EN,,0,0,0,,Right, how do I take up a promise?\nDialogue: 0,0:57:10.80,0:57:14.11,EN,,0,0,0,,Well, force of some procedure, a promise,\nDialogue: 0,0:57:14.78,0:57:15.40,EN,,0,0,0,,is just run it.\nDialogue: 0,0:57:19.23,0:57:19.56,EN,,0,0,0,,Done.\nDialogue: 0,0:57:20.24,0:57:21.37,EN,,0,0,0,,So there's no magic there at all.\nDialogue: 0,0:57:23.52,0:57:24.24,EN,,0,0,0,,Well, what have we done?\nDialogue: 0,0:57:26.44,0:57:27.50,EN,,0,0,0,,We said the old style,\nDialogue: 0,0:57:28.14,0:57:30.81,EN,,0,0,0,,traditional style of programming is more efficient.\nDialogue: 0,0:57:30.96,0:57:33.92,EN,,0,0,0,,And the stream thing is more perspicacious.\nDialogue: 0,0:57:35.50,0:57:38.72,EN,,0,0,0,,And we managed to make the stream procedures\nDialogue: 0,0:57:38.81,0:57:43.23,EN,,0,0,0,,run like the other procedures by using delay.\nDialogue: 0,0:57:43.35,0:57:46.43,EN,,0,0,0,,And the thing that delay did for us was to de-couple\nDialogue: 0,0:57:46.68,0:57:50.40,EN,,0,0,0,,the apparent order of events in our programs\nDialogue: 0,0:57:51.21,0:57:53.84,EN,,0,0,0,,from the actual order of events that happened in the machine.\nDialogue: 0,0:57:54.44,0:57:55.93,EN,,0,0,0,,That's really what delay is doing.\nDialogue: 0,0:57:57.15,0:57:58.29,EN,,0,0,0,,That's exactly the whole point.\nDialogue: 0,0:57:58.29,0:58:01.92,EN,,0,0,0,,We've given up, right, we've given up the idea\nDialogue: 0,0:58:02.30,0:58:04.17,EN,,0,0,0,,that our procedures, as they run,\nDialogue: 0,0:58:04.67,0:58:05.95,EN,,0,0,0,,or as we look at them,\nDialogue: 0,0:58:06.33,0:58:08.25,EN,,0,0,0,,mirror some clear notion of time.\nDialogue: 0,0:58:09.45,0:58:10.57,EN,,0,0,0,,And by giving that up,\nDialogue: 0,0:58:11.21,0:58:13.32,EN,,0,0,0,,we give delay the freedom to arrange the order\nDialogue: 0,0:58:13.34,0:58:15.20,EN,,0,0,0,,of events in the computation the way it likes.\nDialogue: 0,0:58:16.69,0:58:17.61,EN,,0,0,0,,That's the whole idea.\nDialogue: 0,0:58:17.61,0:58:19.45,EN,,0,0,0,,We de-couple the apparent order\nDialogue: 0,0:58:19.95,0:58:21.13,EN,,0,0,0,,of events in our programs\nDialogue: 0,0:58:21.16,0:58:22.89,EN,,0,0,0,,from the actual order of events in the computer.\nDialogue: 0,0:58:24.09,0:58:25.77,EN,,0,0,0,,OK, well there's one more detail.\nDialogue: 0,0:58:25.77,0:58:27.21,EN,,0,0,0,,It's just a technical detail,\nDialogue: 0,0:58:27.21,0:58:28.43,EN,,0,0,0,,but it's actually an important one.\nDialogue: 0,0:58:29.73,0:58:32.01,EN,,0,0,0,,As you run through these recursive programs unwinding,\nDialogue: 0,0:58:32.16,0:58:33.58,EN,,0,0,0,,you'll see a lot of things that look like\nDialogue: 0,0:58:33.64,0:58:37.87,EN,,0,0,0,,tail of the tail of the tail.\nDialogue: 0,0:58:39.20,0:58:41.02,EN,,0,0,0,,Right. That's the kind of thing that would happen\nDialogue: 0,0:58:41.02,0:58:42.88,EN,,0,0,0,,as I go CONSing down a stream all the way.\nDialogue: 0,0:58:43.86,0:58:46.09,EN,,0,0,0,,And if each time I'm doing that,\nDialogue: 0,0:58:46.14,0:58:47.58,EN,,0,0,0,,each time to compute a tail,\nDialogue: 0,0:58:48.22,0:58:50.88,EN,,0,0,0,,I evaluate a procedure\nDialogue: 0,0:58:51.07,0:58:53.07,EN,,0,0,0,,which then has to go re-compute its tail,\nDialogue: 0,0:58:53.10,0:58:55.40,EN,,0,0,0,,and re-compute its tail and recompute its tail each time,\nDialogue: 0,0:58:55.50,0:58:56.88,EN,,0,0,0,,you can see that's very inefficient\nDialogue: 0,0:58:57.77,0:59:00.56,EN,,0,0,0,,compared to just having a list where the elements are all there,\nDialogue: 0,0:59:01.16,0:59:04.00,EN,,0,0,0,,and I don't have to re-compute each tail every time I get the next tail.\nDialogue: 0,0:59:05.29,0:59:08.28,EN,,0,0,0,,So there's one little hack\nDialogue: 0,0:59:09.66,0:59:13.13,EN,,0,0,0,,to slightly change the abbreviation, change what delay is\nDialogue: 0,0:59:14.96,0:59:18.20,EN,,0,0,0,,and make it a thing which is-- I'll write it this way.\nDialogue: 0,0:59:19.68,0:59:22.04,EN,,0,0,0,,Delay -- The actual implementation,\nDialogue: 0,0:59:24.52,0:59:27.93,EN,,0,0,0,,delay is an abbreviation for this thing,\nDialogue: 0,0:59:28.11,0:59:30.86,EN,,0,0,0,,memo-proc of a procedure.\nDialogue: 0,0:59:31.00,0:59:34.06,EN,,0,0,0,,Memo-proc is a special thing that transforms a procedure.\nDialogue: 0,0:59:35.15,0:59:37.80,EN,,0,0,0,,What it does is it takes a procedure of no arguments\nDialogue: 0,0:59:39.02,0:59:41.05,EN,,0,0,0,,and it transforms it into a procedure\nDialogue: 0,0:59:41.36,0:59:43.55,EN,,0,0,0,,that'll only have to do its computation once.\nDialogue: 0,0:59:45.10,0:59:47.45,EN,,0,0,0,,And what I mean by that is, you give it a procedure.\nDialogue: 0,0:59:48.70,0:59:50.86,EN,,0,0,0,,The result of memo-proc will be a new procedure,\nDialogue: 0,0:59:51.39,0:59:53.00,EN,,0,0,0,,which the first time you call it,\nDialogue: 0,0:59:53.71,0:59:55.07,EN,,0,0,0,,will run the original procedure,\nDialogue: 0,0:59:55.31,0:59:56.91,EN,,0,0,0,,remember what result it got,\nDialogue: 0,0:59:58.56,1:00:00.68,EN,,0,0,0,,and then from ever on after, when you call it,\nDialogue: 0,1:00:00.68,1:00:02.17,EN,,0,0,0,,it just won't have to do the computation.\nDialogue: 0,1:00:02.19,1:00:04.43,EN,,0,0,0,,It will have cached that result someplace.\nDialogue: 0,1:00:05.20,1:00:06.92,EN,,0,0,0,,And here's an implementation of memo-proc.\nDialogue: 0,1:00:11.21,1:00:12.71,EN,,0,0,0,,Once you have the idea, it's easy to implement.\nDialogue: 0,1:00:12.71,1:00:16.76,EN,,0,0,0,,Memo-proc is this little thing that has two little flags in there.\nDialogue: 0,1:00:17.39,1:00:19.20,EN,,0,0,0,,It says, have I already been run?\nDialogue: 0,1:00:20.32,1:00:22.48,EN,,0,0,0,,And initially it says, no, I haven't already been run.\nDialogue: 0,1:00:23.62,1:00:27.04,EN,,0,0,0,,And what was the result I got the last time I was run?\nDialogue: 0,1:00:29.07,1:00:31.07,EN,,0,0,0,,So memo-proc takes a procedure called proc,\nDialogue: 0,1:00:31.56,1:00:34.01,EN,,0,0,0,,and it returns a new procedure of no arguments.\nDialogue: 0,1:00:34.36,1:00:36.38,EN,,0,0,0,,Proc is supposed to be a procedure of no arguments.\nDialogue: 0,1:00:38.61,1:00:41.37,EN,,0,0,0,,And it says, oh, if I'm not already run,\nDialogue: 0,1:00:42.59,1:00:44.06,EN,,0,0,0,,then I'm going to do a sequence of things.\nDialogue: 0,1:00:44.43,1:00:46.56,EN,,0,0,0,,I'm going to compute proc,\nDialogue: 0,1:00:47.50,1:00:48.45,EN,,0,0,0,,I'm going to save that.\nDialogue: 0,1:00:48.45,1:00:50.48,EN,,0,0,0,,I'm going to stash that in the variable result.\nDialogue: 0,1:00:51.14,1:00:53.90,EN,,0,0,0,,I'm going to make a note to myself that I've already been run,\nDialogue: 0,1:00:54.28,1:00:55.47,EN,,0,0,0,,and then I'll return the result.\nDialogue: 0,1:00:56.61,1:00:59.01,EN,,0,0,0,,So that's if you compute it if it's not already run.\nDialogue: 0,1:00:59.01,1:01:01.88,EN,,0,0,0,,If you call it and it's already been run, it just returns the result.\nDialogue: 0,1:01:03.42,1:01:07.12,EN,,0,0,0,,So that's a little clever hack called memoization.\nDialogue: 0,1:01:08.40,1:01:09.13,EN,,0,0,0,,And in this case,\nDialogue: 0,1:01:10.35,1:01:14.14,EN,,0,0,0,,it short circuits having to re-compute the tail of the tail of the tail of the tail of the tail.\nDialogue: 0,1:01:15.27,1:01:17.81,EN,,0,0,0,,So there isn't even that kind of inefficiency.\nDialogue: 0,1:01:17.81,1:01:18.72,EN,,0,0,0,,And in fact, the streams\nDialogue: 0,1:01:19.20,1:01:22.75,EN,,0,0,0,,will run with pretty much the same efficiency as the other programs precisely.\nDialogue: 0,1:01:24.01,1:01:26.20,EN,,0,0,0,,And remember, again, the whole idea of this\nDialogue: 0,1:01:27.48,1:01:28.60,EN,,0,0,0,,is that we've used\nDialogue: 0,1:01:29.26,1:01:32.40,EN,,0,0,0,,the fact that there's no really good dividing line\nDialogue: 0,1:01:32.41,1:01:33.61,EN,,0,0,0,,between procedures and data.\nDialogue: 0,1:01:33.61,1:01:35.61,EN,,0,0,0,,We've written data structures that, in fact,\nDialogue: 0,1:01:36.00,1:01:37.31,EN,,0,0,0,,are sort of like procedures.\nDialogue: 0,1:01:38.76,1:01:40.73,EN,,0,0,0,,And what that's allowed us to do\nDialogue: 0,1:01:41.58,1:01:46.54,EN,,0,0,0,,is take an example of a common control structure,\nDialogue: 0,1:01:46.68,1:01:48.91,EN,,0,0,0,,in this place iteration.\nDialogue: 0,1:01:49.62,1:01:51.05,EN,,0,0,0,,And we've built a data structure\nDialogue: 0,1:01:51.32,1:01:52.84,EN,,0,0,0,,which, since itself is a procedure,\nDialogue: 0,1:01:52.86,1:01:55.12,EN,,0,0,0,,kind of has this iteration control structure in it.\nDialogue: 0,1:01:55.79,1:01:57.13,EN,,0,0,0,,And that's really what streams are.\nDialogue: 0,1:01:58.91,1:01:59.76,EN,,0,0,0,,OK, questions?\nDialogue: 0,1:02:03.95,1:02:05.84,EN,,0,0,0,,AUDIENCE: Your description of tail-tail-tail,\nDialogue: 0,1:02:05.85,1:02:07.16,EN,,0,0,0,,if I understand it correctly,\nDialogue: 0,1:02:07.28,1:02:10.76,EN,,0,0,0,,force is actually execution of a procedure,\nDialogue: 0,1:02:10.78,1:02:12.83,EN,,0,0,0,,if it's done without this memo-proc thing.\nDialogue: 0,1:02:12.89,1:02:13.15,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:02:13.44,1:02:16.38,EN,,0,0,0,,AUDIENCE: And you implied that memo-proc gets around that problem.\nDialogue: 0,1:02:16.38,1:02:18.73,EN,,0,0,0,,Doesn't it only get around it if\nDialogue: 0,1:02:19.34,1:02:22.19,EN,,0,0,0,,tail-tail-tail is always executing exactly the same--\nDialogue: 0,1:02:22.41,1:02:23.91,EN,,0,0,0,,PROFESSOR: Oh, that's-- sure.\nDialogue: 0,1:02:23.91,1:02:25.84,EN,,0,0,0,,AUDIENCE: I guess I missed that point.\nDialogue: 0,1:02:26.05,1:02:27.21,EN,,0,0,0,,PROFESSOR: Oh, sure. I mean the point is--  yeah.\nDialogue: 0,1:02:31.12,1:02:33.64,EN,,0,0,0,,Yeah, I mean I have to do a computation to get the answer.\nDialogue: 0,1:02:34.09,1:02:36.76,EN,,0,0,0,,But the point is, once I've found the tail of the stream,\nDialogue: 0,1:02:37.58,1:02:38.70,EN,,0,0,0,,to get the tail of the tail,\nDialogue: 0,1:02:38.70,1:02:40.51,EN,,0,0,0,,I shouldn't have had to re-compute the first tail.\nDialogue: 0,1:02:42.98,1:02:44.32,EN,,0,0,0,,See, and if I didn't use memo-proc,\nDialogue: 0,1:02:44.35,1:02:46.09,EN,,0,0,0,,that re-computation would have been done.\nDialogue: 0,1:02:46.46,1:02:47.13,EN,,0,0,0,,AUDIENCE: I understand now.\nDialogue: 0,1:02:50.83,1:02:52.56,EN,,0,0,0,,AUDIENCE: In one of your examples, you mentioned that\nDialogue: 0,1:02:52.60,1:02:54.22,EN,,0,0,0,,we were able to use the substitution model\nDialogue: 0,1:02:54.22,1:02:56.11,EN,,0,0,0,,because there are no side effects.\nDialogue: 0,1:02:56.83,1:03:00.73,EN,,0,0,0,,What if we had a signal processing unit--\nDialogue: 0,1:03:00.78,1:03:02.03,EN,,0,0,0,,if we had a side effect,\nDialogue: 0,1:03:02.04,1:03:03.04,EN,,0,0,0,,if we had a state?\nDialogue: 0,1:03:03.62,1:03:06.84,EN,,0,0,0,,Could we still practically build the stream model?\nDialogue: 0,1:03:08.46,1:03:10.59,EN,,0,0,0,,PROFESSOR: Hum... Maybe, That's a hard question.\nDialogue: 0,1:03:11.20,1:03:13.42,EN,,0,0,0,,I'm going to talk a little bit later about the places where\nDialogue: 0,1:03:14.36,1:03:18.24,EN,,0,0,0,,where substitution and side effects don't really mix very well.\nDialogue: 0,1:03:18.96,1:03:20.48,EN,,0,0,0,,But in general, I think the answer is\nDialogue: 0,1:03:20.49,1:03:21.63,EN,,0,0,0,,unless you're very careful,\nDialogue: 0,1:03:21.90,1:03:24.46,EN,,0,0,0,,any amount of side effect is going to mess up everything.\nDialogue: 0,1:03:35.04,1:03:38.25,EN,,0,0,0,,AUDIENCE: Sorry, I didn't quite understand the memo-proc operation. Uh...\nDialogue: 0,1:03:39.68,1:03:41.12,EN,,0,0,0,,When do you execute the lambda?\nDialogue: 0,1:03:41.99,1:03:43.21,EN,,0,0,0,,In other words,\nDialogue: 0,1:03:43.68,1:03:45.15,EN,,0,0,0,,when memo-proc is executed,\nDialogue: 0,1:03:45.18,1:03:47.71,EN,,0,0,0,,just this lambda expression is being generated.\nDialogue: 0,1:03:48.01,1:03:49.68,EN,,0,0,0,,But it's not clear to me when it's executed.\nDialogue: 0,1:03:50.39,1:03:51.12,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:03:51.35,1:03:52.68,EN,,0,0,0,,What memo-proc does-- remember,\nDialogue: 0,1:03:53.07,1:03:55.85,EN,,0,0,0,,the thing that's going into memo-proc, the thing proc,\nDialogue: 0,1:03:56.38,1:03:57.93,EN,,0,0,0,,is a procedure of no arguments.\nDialogue: 0,1:03:57.93,1:03:59.05,EN,,0,0,0,,And someday, you're going to call it.\nDialogue: 0,1:04:00.39,1:04:02.75,EN,,0,0,0,,Memo-proc translates that procedure\nDialogue: 0,1:04:02.75,1:04:04.56,EN,,0,0,0,,into another procedure of no arguments,\nDialogue: 0,1:04:04.59,1:04:05.80,EN,,0,0,0,,which someday you're going to call.\nDialogue: 0,1:04:06.62,1:04:07.42,EN,,0,0,0,,That's that lambda.\nDialogue: 0,1:04:09.89,1:04:14.08,EN,,0,0,0,,So here, where I initially built as my\nDialogue: 0,1:04:15.85,1:04:17.92,EN,,0,0,0,,I built as my tail of the stream,\nDialogue: 0,1:04:18.30,1:04:20.48,EN,,0,0,0,,say, this procedure of no arguments,\nDialogue: 0,1:04:20.51,1:04:21.61,EN,,0,0,0,,which someday I'll call.\nDialogue: 0,1:04:24.10,1:04:28.01,EN,,0,0,0,,Instead, I'm going to have the tail of the stream be memo-proc of it,\nDialogue: 0,1:04:28.12,1:04:29.24,EN,,0,0,0,,which someday I'll call.\nDialogue: 0,1:04:30.65,1:04:31.90,EN,,0,0,0,,So that lambda of nil,\nDialogue: 0,1:04:32.03,1:04:36.06,EN,,0,0,0,,that gets called when you call the memo-proc,\nDialogue: 0,1:04:38.97,1:04:40.96,EN,,0,0,0,,when you call the result of that memo-proc,\nDialogue: 0,1:04:40.97,1:04:42.28,EN,,0,0,0,,which would be ordinarily\nDialogue: 0,1:04:42.36,1:04:45.76,EN,,0,0,0,,when you would have called the original thing that you set it.\nDialogue: 0,1:04:47.64,1:04:48.86,EN,,0,0,0,,AUDIENCE: OK, my ask is\nDialogue: 0,1:04:48.86,1:04:50.86,EN,,0,0,0,,I had a feeling that when you call memo-proc,\nDialogue: 0,1:04:50.86,1:04:52.30,EN,,0,0,0,,you just return this lambda.\nDialogue: 0,1:04:52.61,1:04:53.07,EN,,0,0,0,,PROFESSOR: That's right.\nDialogue: 0,1:04:53.77,1:04:58.10,EN,,0,0,0,,When you call memo-proc, you return the lambda.\nDialogue: 0,1:04:58.10,1:04:59.84,EN,,0,0,0,,You never evaluate the expression at all,\nDialogue: 0,1:04:59.87,1:05:02.27,EN,,0,0,0,,until the first time that you would have evaluated it.\nDialogue: 0,1:05:07.76,1:05:09.10,EN,,0,0,0,,AUDIENCE: Do I understand it right\nDialogue: 0,1:05:09.18,1:05:11.40,EN,,0,0,0,,you actually have to build the list up,\nDialogue: 0,1:05:11.47,1:05:14.17,EN,,0,0,0,,but the elements of the list don't get evaluated?\nDialogue: 0,1:05:14.24,1:05:15.63,EN,,0,0,0,,The expressions don't get evaluated?\nDialogue: 0,1:05:15.63,1:05:18.54,EN,,0,0,0,,But at each stage, you actually are building a list.\nDialogue: 0,1:05:18.54,1:05:20.70,EN,,0,0,0,,PROFESSOR: That's-- I really should have said this.\nDialogue: 0,1:05:20.70,1:05:22.27,EN,,0,0,0,,That's a really good point.\nDialogue: 0,1:05:22.27,1:05:23.18,EN,,0,0,0,,No, it's not quite right.\nDialogue: 0,1:05:23.66,1:05:25.08,EN,,0,0,0,,See, cause what happens is this.\nDialogue: 0,1:05:25.08,1:05:26.35,EN,,0,0,0,,Let me draw this as pairs.\nDialogue: 0,1:05:26.89,1:05:28.03,EN,,0,0,0,,Suppose I'm going to make a big stream,\nDialogue: 0,1:05:28.96,1:05:30.12,EN,,0,0,0,,like enumerate interval,\nDialogue: 0,1:05:30.32,1:05:31.48,EN,,0,0,0,,1 through 1 billion.\nDialogue: 0,1:05:32.74,1:05:35.74,EN,,0,0,0,,What that is, is a pair\nDialogue: 0,1:05:39.34,1:05:43.36,EN,,0,0,0,,a 1 and a promise.\nDialogue: 0,1:05:46.73,1:05:47.89,EN,,0,0,0,,That's exactly what it is.\nDialogue: 0,1:05:47.89,1:05:48.76,EN,,0,0,0,,Nothing got built up.\nDialogue: 0,1:05:51.60,1:05:53.29,EN,,0,0,0,,When I go and force this,\nDialogue: 0,1:05:54.51,1:05:56.37,EN,,0,0,0,,and see, what happens?\nDialogue: 0,1:05:56.37,1:05:59.66,EN,,0,0,0,,Well, this thing is now also recursively a CONS.\nDialogue: 0,1:06:00.53,1:06:02.16,EN,,0,0,0,,So that this promise now is\nDialogue: 0,1:06:04.62,1:06:08.96,EN,,0,0,0,,the next thing, which is a 2 and a promise to do more.\nDialogue: 0,1:06:11.35,1:06:12.73,EN,,0,0,0,,And so on and so on and so on.\nDialogue: 0,1:06:14.47,1:06:17.63,EN,,0,0,0,,So nothing gets built up until you walk down the stream.\nDialogue: 0,1:06:18.20,1:06:19.58,EN,,0,0,0,,Because what's sitting here is not the list,\nDialogue: 0,1:06:20.03,1:06:21.48,EN,,0,0,0,,but a promise to generate the list.\nDialogue: 0,1:06:23.39,1:06:25.50,EN,,0,0,0,,And by promise, technically I mean procedure.\nDialogue: 0,1:06:27.80,1:06:29.10,EN,,0,0,0,,So it doesn't get built up.\nDialogue: 0,1:06:30.76,1:06:32.72,EN,,0,0,0,,Yeah, I should have said that before that.\nDialogue: 0,1:06:34.28,1:06:35.34,EN,,0,0,0,,OK. That you. Let's take a break.\nDialogue: 0,0:00:00.01,0:00:02.46,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N张大伟\\N（DreamAndDead）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:10.10,0:00:14.60,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 I\nDialogue: 0,0:00:18.55,0:00:21.84,Default,,0,0,0,,上次Gerry教授揭晓了秘密\nDialogue: 0,0:00:22.49,0:00:24.60,Default,,0,0,0,,他介绍了赋值的概念\nDialogue: 0,0:00:26.35,0:00:33.61,Default,,0,0,0,,赋值与状态\nDialogue: 0,0:00:37.48,0:00:40.03,Default,,0,0,0,,正如我们所见\nDialogue: 0,0:00:40.72,0:00:43.16,Default,,0,0,0,,将赋值和状态引入到语言中\nDialogue: 0,0:00:43.16,0:00:44.41,Default,,0,0,0,,后果相当糟糕\nDialogue: 0,0:00:45.08,0:00:48.62,Default,,0,0,0,,首先 代换模型不再能够描述求值过程了\nDialogue: 0,0:00:49.13,0:00:52.48,Default,,0,0,0,,为了解释程序中语句的语义\nDialogue: 0,0:00:52.48,0:00:54.27,Default,,0,0,0,,我们不得不使用更复杂的环境模型\nDialogue: 0,0:00:54.28,0:00:57.24,Default,,0,0,0,,也就是一种跟图表相关的非常机械的东西\nDialogue: 0,0:00:58.46,0:01:00.12,Default,,0,0,0,,并且 这不单纯地是一个技术上的问题\nDialogue: 0,0:01:00.26,0:01:03.28,Default,,0,0,0,,并不是因为代换模型在这里不怎么有效\nDialogue: 0,0:01:03.60,0:01:05.68,Default,,0,0,0,,所以我们得想些其它办法\nDialogue: 0,0:01:05.71,0:01:09.79,Default,,0,0,0,,而是代换模型这类机制都不再起效\nDialogue: 0,0:01:10.73,0:01:13.32,Default,,0,0,0,,这是因为突然间 一个变量\nDialogue: 0,0:01:14.12,0:01:16.92,Default,,0,0,0,,不再是代表着一个值了\nDialogue: 0,0:01:17.95,0:01:21.76,Default,,0,0,0,,现在 变量用于指明一个位置\nDialogue: 0,0:01:22.40,0:01:23.34,Default,,0,0,0,,一个存放值的位置\nDialogue: 0,0:01:23.63,0:01:26.14,Default,,0,0,0,,并且 这个位置的值可以发生改变\nDialogue: 0,0:01:30.28,0:01:34.09,Default,,0,0,0,,比如像 (F X) 这样的表达式\nDialogue: 0,0:01:37.36,0:01:39.64,Default,,0,0,0,,就可能含有副作用\nDialogue: 0,0:01:40.41,0:01:42.60,Default,,0,0,0,,如果我们执行 (F X) 得到某个值\nDialogue: 0,0:01:43.18,0:01:45.34,Default,,0,0,0,,之后我们再次执行 (F X)\nDialogue: 0,0:01:47.24,0:01:48.43,Default,,0,0,0,,可能因为求值的顺序\nDialogue: 0,0:01:48.86,0:01:49.74,Default,,0,0,0,,而得到不同的值\nDialogue: 0,0:01:49.76,0:01:52.14,Default,,0,0,0,,所以突然间 我们不能仅仅关注于值\nDialogue: 0,0:01:52.52,0:01:53.60,Default,,0,0,0,,也要关注时序\nDialogue: 0,0:01:57.97,0:01:59.98,Default,,0,0,0,,序对也不仅仅\nDialogue: 0,0:02:00.65,0:02:02.52,Default,,0,0,0,,只是它的CAR和CDR部分\nDialogue: 0,0:02:02.52,0:02:05.61,Default,,0,0,0,,不是作为CAR部分和CDR部分的别称\nDialogue: 0,0:02:05.80,0:02:07.05,Default,,0,0,0,,它也有自己的“身份”\nDialogue: 0,0:02:08.44,0:02:11.65,Default,,0,0,0,,序对具有“身份”\nDialogue: 0,0:02:11.65,0:02:12.59,Default,,0,0,0,,它是一个对象\nDialogue: 0,0:02:21.33,0:02:25.15,Default,,0,0,0,,两个具有相同CAR和CDR部分的序对\nDialogue: 0,0:02:25.40,0:02:27.05,Default,,0,0,0,,可能相同也可能不同\nDialogue: 0,0:02:27.87,0:02:30.51,Default,,0,0,0,,因为这之中可能存在“共享”\nDialogue: 0,0:02:34.96,0:02:39.45,Default,,0,0,0,,一引入赋值 这些就变成要考虑的问题了\nDialogue: 0,0:02:40.48,0:02:43.98,Default,,0,0,0,,确实 这和我们说讲代换的时候差别悬殊\nDialogue: 0,0:02:45.04,0:02:48.91,Default,,0,0,0,,技术上来看 我们思考起来更加困难了\nDialogue: 0,0:02:48.94,0:02:53.45,Default,,0,0,0,,因为我们必须相当机械地思考程序语言\nDialogue: 0,0:02:53.47,0:02:55.34,Default,,0,0,0,,而不能仅仅用数学的方式来思考\nDialogue: 0,0:02:55.71,0:02:58.60,Default,,0,0,0,,我们也会遇到哲学问题\nDialogue: 0,0:02:59.15,0:03:00.65,Default,,0,0,0,,我们会被这样的问题所困扰：\nDialogue: 0,0:03:00.67,0:03:02.38,Default,,0,0,0,,事物的“改变”指的是什么？\nDialogue: 0,0:03:02.38,0:03:03.77,Default,,0,0,0,,两个事物“同一”又如何判别？\nDialogue: 0,0:03:03.84,0:03:06.83,Default,,0,0,0,,并且 这也会给我们编程带来困扰\nDialogue: 0,0:03:07.47,0:03:08.54,Default,,0,0,0,,正如 Sussman 教授上节课中讲的那样\nDialogue: 0,0:03:08.56,0:03:12.20,Default,,0,0,0,,错误的表达式顺序和别名会产生BUG\nDialogue: 0,0:03:12.22,0:03:16.19,Default,,0,0,0,,这些问题在不需要考虑“对象”的语言中 是不存在的\nDialogue: 0,0:03:18.21,0:03:21.20,Default,,0,0,0,,我们是怎样陷入这样的困境的呢？\nDialogue: 0,0:03:24.01,0:03:27.20,Default,,0,0,0,,我们这样做的原因在于\nDialogue: 0,0:03:27.40,0:03:31.47,Default,,0,0,0,,我们想要构造模块化的系统\nDialogue: 0,0:03:35.15,0:03:37.69,Default,,0,0,0,,我们想把系统划分为\nDialogue: 0,0:03:38.09,0:03:41.04,Default,,0,0,0,,数个自然组合的小块\nDialogue: 0,0:03:42.76,0:03:43.82,Default,,0,0,0,,举例来说\nDialogue: 0,0:03:44.06,0:03:46.11,Default,,0,0,0,,我们想要构造一个随机数发生器\nDialogue: 0,0:03:46.22,0:03:49.40,Default,,0,0,0,,把该发生器的内部状态封装起来\nDialogue: 0,0:03:50.25,0:03:53.71,Default,,0,0,0,,这样我们就可以把选取随机数\nDialogue: 0,0:03:54.65,0:03:57.79,Default,,0,0,0,,和用于估计的蒙特卡洛方法分离开来\nDialogue: 0,0:03:58.65,0:04:01.52,Default,,0,0,0,,进一步地把它同由 Ceraso 发明的\nDialogue: 0,0:04:01.90,0:04:05.74,Default,,0,0,0,,求取 π 的公式分离开\nDialogue: 0,0:04:06.80,0:04:07.92,Default,,0,0,0,,相似地\nDialogue: 0,0:04:09.61,0:04:11.74,Default,,0,0,0,,当我们着手构建事物的模型时\nDialogue: 0,0:04:12.35,0:04:16.01,Default,,0,0,0,,我们去构建现实世界中事物的模型\nDialogue: 0,0:04:17.31,0:04:19.42,Default,,0,0,0,,我们想把程序组织成许多自然部分\nDialogue: 0,0:04:19.44,0:04:20.52,Default,,0,0,0,,这些部分就是\nDialogue: 0,0:04:21.05,0:04:23.16,Default,,0,0,0,,现实事物的镜像\nDialogue: 0,0:04:24.90,0:04:27.56,Default,,0,0,0,,举个例子 对于一个数字电路\nDialogue: 0,0:04:28.36,0:04:29.18,Default,,0,0,0,,我们会说\nDialogue: 0,0:04:30.44,0:04:31.44,Default,,0,0,0,,这儿有一个电路\nDialogue: 0,0:04:32.08,0:04:35.16,Default,,0,0,0,,它有一个这样的元件 有一个那样的元件\nDialogue: 0,0:04:40.10,0:04:43.58,Default,,0,0,0,,这些元件都有不同的“身份”\nDialogue: 0,0:04:43.58,0:04:44.59,Default,,0,0,0,,它们都有各自的状态\nDialogue: 0,0:04:45.55,0:04:47.13,Default,,0,0,0,,状态附着在电路上\nDialogue: 0,0:04:48.58,0:04:50.22,Default,,0,0,0,,我们认为这个元件是一个对象\nDialogue: 0,0:04:50.49,0:04:51.93,Default,,0,0,0,,这个元件又是另外一个不同的对象\nDialogue: 0,0:04:52.54,0:04:53.85,Default,,0,0,0,,当我们观察到系统发生了变化\nDialogue: 0,0:04:53.87,0:04:55.40,Default,,0,0,0,,信号从这里传递过来\nDialogue: 0,0:04:55.63,0:04:58.41,Default,,0,0,0,,改变了可能存放在这里的状态 并向这里继续传播\nDialogue: 0,0:04:58.67,0:05:00.75,Default,,0,0,0,,和一个存储在这里的状态交互\nDialogue: 0,0:05:01.24,0:05:02.17,Default,,0,0,0,,依此类推\nDialogue: 0,0:05:06.86,0:05:11.24,Default,,0,0,0,,我们想要在计算机中\nDialogue: 0,0:05:12.76,0:05:14.36,Default,,0,0,0,,构建模块化的系统\nDialogue: 0,0:05:14.68,0:05:17.87,Default,,0,0,0,,来反映我们对现实的看法\nDialogue: 0,0:05:17.88,0:05:19.87,Default,,0,0,0,,根据我们正在建模的实际系统\nDialogue: 0,0:05:19.88,0:05:20.91,Default,,0,0,0,,来划分子系统\nDialogue: 0,0:05:23.20,0:05:23.48,Default,,0,0,0,,然而\nDialogue: 0,0:05:25.74,0:05:28.99,Default,,0,0,0,,构建像这样的系统\nDialogue: 0,0:05:28.99,0:05:31.50,Default,,0,0,0,,看起来带来了不少技术上的麻烦\nDialogue: 0,0:05:31.52,0:05:32.75,Default,,0,0,0,,但这不是计算机造成的\nDialogue: 0,0:05:33.61,0:05:35.60,Default,,0,0,0,,或许 真正拖累我们\nDialogue: 0,0:05:36.70,0:05:38.65,Default,,0,0,0,,让我们花了那么大的功夫\nDialogue: 0,0:05:38.67,0:05:40.94,Default,,0,0,0,,才让程序反映现实世界的原因\nDialogue: 0,0:05:41.52,0:05:43.13,Default,,0,0,0,,是我们对现实世界的认识出了错\nDialogue: 0,0:05:44.55,0:05:46.75,Default,,0,0,0,,或许时间只是幻觉\nDialogue: 0,0:05:47.26,0:05:48.60,Default,,0,0,0,,什么都没有改变\nDialogue: 0,0:05:50.15,0:05:51.71,Default,,0,0,0,,就拿这个粉笔来说\nDialogue: 0,0:05:52.44,0:05:53.77,Default,,0,0,0,,我们认为它是一个对象\nDialogue: 0,0:05:54.01,0:05:54.99,Default,,0,0,0,,它有自己的状态\nDialogue: 0,0:05:55.82,0:05:59.29,Default,,0,0,0,,每时每刻 它都有一个位置和速度\nDialogue: 0,0:05:59.71,0:06:01.48,Default,,0,0,0,,如果我们做点什么 就可以改变它的状态\nDialogue: 0,0:06:04.34,0:06:07.37,Default,,0,0,0,,但是你如果了解一点相对性的概念\nDialogue: 0,0:06:07.74,0:06:09.71,Default,,0,0,0,,你可能会认为粉笔的路径\nDialogue: 0,0:06:09.72,0:06:11.34,Default,,0,0,0,,不是许多瞬时的离散点\nDialogue: 0,0:06:11.34,0:06:14.38,Default,,0,0,0,,一种深刻的见解是把整个粉笔的存在看作\nDialogue: 0,0:06:14.41,0:06:15.64,Default,,0,0,0,,时空中的路径\nDialogue: 0,0:06:16.02,0:06:17.37,Default,,0,0,0,,全部都展开了\nDialogue: 0,0:06:17.87,0:06:19.84,Default,,0,0,0,,没有单独的位置与速度\nDialogue: 0,0:06:19.84,0:06:23.80,Default,,0,0,0,,在时空中的存在是不会发生改变的\nDialogue: 0,0:06:24.64,0:06:26.51,Default,,0,0,0,,相似地 如果我们来考察这个电气系统\nDialogue: 0,0:06:27.69,0:06:30.43,Default,,0,0,0,,我们假设这个系统实现的是\nDialogue: 0,0:06:30.59,0:06:33.96,Default,,0,0,0,,某种信号处理系统\nDialogue: 0,0:06:34.36,0:06:36.68,Default,,0,0,0,,把这些元件组合在一起的工程师\nDialogue: 0,0:06:36.75,0:06:38.60,Default,,0,0,0,,也不会把它们看作\nDialogue: 0,0:06:38.96,0:06:41.40,Default,,0,0,0,,电压施加于每个独立的元件\nDialogue: 0,0:06:41.49,0:06:43.16,Default,,0,0,0,,转换成了某种东西\nDialogue: 0,0:06:43.34,0:06:45.52,Default,,0,0,0,,影响了这里的状态\nDialogue: 0,0:06:45.53,0:06:46.81,Default,,0,0,0,,还改变了那里的状态\nDialogue: 0,0:06:46.81,0:06:50.11,Default,,0,0,0,,没有一个做信号处理的会这样想\nDialogue: 0,0:06:50.42,0:06:51.84,Default,,0,0,0,,相反 你会说\nDialogue: 0,0:06:54.04,0:06:58.06,Default,,0,0,0,,这里有一个在时间上伸展的信号\nDialogue: 0,0:06:58.06,0:06:59.48,Default,,0,0,0,,如果把这个看作一个滤波器\nDialogue: 0,0:07:00.20,0:07:04.04,Default,,0,0,0,,这个滤波器会把整个信号转化成\nDialogue: 0,0:07:04.28,0:07:07.04,Default,,0,0,0,,不同的输出信号\nDialogue: 0,0:07:09.57,0:07:11.28,Default,,0,0,0,,你们不要把这些东西的状态\nDialogue: 0,0:07:11.28,0:07:13.29,Default,,0,0,0,,想象成在许多瞬间接连发生\nDialogue: 0,0:07:14.16,0:07:17.32,Default,,0,0,0,,我们把这个盒子看作一个整体\nDialogue: 0,0:07:17.32,0:07:20.16,Default,,0,0,0,,而不是在一个特定的瞬间\nDialogue: 0,0:07:20.40,0:07:21.96,Default,,0,0,0,,互相发送状态信息的小系统\nDialogue: 0,0:07:28.25,0:07:29.36,Default,,0,0,0,,今天我们将介绍\nDialogue: 0,0:07:29.39,0:07:31.13,Default,,0,0,0,,另一种分解系统的方法\nDialogue: 0,0:07:31.36,0:07:35.45,Default,,0,0,0,,站在信号工程师的角度去看待现实世界\nDialogue: 0,0:07:35.69,0:07:38.96,Default,,0,0,0,,而不再认为对象间通过消息传递来通信\nDialogue: 0,0:07:41.13,0:07:43.74,Default,,0,0,0,,它被称为“流处理”\nDialogue: 0,0:07:54.57,0:07:58.96,Default,,0,0,0,,我们打算展示\nDialogue: 0,0:08:00.59,0:08:04.16,Default,,0,0,0,,如何让我们的程序变得更加统一\nDialogue: 0,0:08:05.15,0:08:06.54,Default,,0,0,0,,从中看到更多的共性\nDialogue: 0,0:08:06.65,0:08:09.88,Default,,0,0,0,,如果我们跳出这些程序\nDialogue: 0,0:08:10.81,0:08:12.30,Default,,0,0,0,,我们会发现\nDialogue: 0,0:08:12.35,0:08:15.12,Default,,0,0,0,,我们对时序的考虑过度了\nDialogue: 0,0:08:16.89,0:08:20.22,Default,,0,0,0,,我们先来对比两个过程\nDialogue: 0,0:08:23.55,0:08:25.69,Default,,0,0,0,,第一个是这样\nDialogue: 0,0:08:25.69,0:08:27.77,Default,,0,0,0,,想像这有一个树\nDialogue: 0,0:08:30.40,0:08:32.14,Default,,0,0,0,,一个由整数构成的树\nDialogue: 0,0:08:33.28,0:08:34.42,Default,,0,0,0,,一个二叉树\nDialogue: 0,0:08:36.12,0:08:36.97,Default,,0,0,0,,这里是1\nDialogue: 0,0:08:39.10,0:08:40.23,Default,,0,0,0,,看起来就像这样\nDialogue: 0,0:08:40.23,0:08:42.92,Default,,0,0,0,,在每个节点上都有一个整数\nDialogue: 0,0:08:45.18,0:08:47.80,Default,,0,0,0,,我们想计算\nDialogue: 0,0:08:48.67,0:08:51.56,Default,,0,0,0,,对这个树中所有的奇数\nDialogue: 0,0:08:52.30,0:08:55.10,Default,,0,0,0,,计算它们的平方和\nDialogue: 0,0:08:57.05,0:08:59.48,Default,,0,0,0,,我们对这类问题很熟悉\nDialogue: 0,0:08:59.48,0:09:01.95,Default,,0,0,0,,有一种递归策略求解它\nDialogue: 0,0:09:02.93,0:09:04.35,Default,,0,0,0,,观察每个叶子节点\nDialogue: 0,0:09:04.56,0:09:06.68,Default,,0,0,0,,如果是奇数我们就求它的平方 并加和\nDialogue: 0,0:09:06.70,0:09:07.77,Default,,0,0,0,,如果是偶数 就是0\nDialogue: 0,0:09:08.68,0:09:12.11,Default,,0,0,0,,递归地看 对于每一颗树 我们可以说\nDialogue: 0,0:09:12.65,0:09:13.84,Default,,0,0,0,,它的平方和等于\nDialogue: 0,0:09:13.92,0:09:15.93,Default,,0,0,0,,右子树的平方和 加上左子树的平方和\nDialogue: 0,0:09:16.25,0:09:17.64,Default,,0,0,0,,就这样沿着节点递归下去\nDialogue: 0,0:09:17.64,0:09:18.70,Default,,0,0,0,,我们已经很熟悉\nDialogue: 0,0:09:19.26,0:09:20.36,Default,,0,0,0,,这种程序设计的思考方式了\nDialogue: 0,0:09:20.36,0:09:22.59,Default,,0,0,0,,我们来幻灯片上看一下\nDialogue: 0,0:09:23.82,0:09:26.75,Default,,0,0,0,,为了计算一棵树中奇数的平方和\nDialogue: 0,0:09:27.37,0:09:29.36,Default,,0,0,0,,我们先要判断它是否是一个叶子节点\nDialogue: 0,0:09:29.82,0:09:31.95,Default,,0,0,0,,判断方法则是考察该节点是否为整数\nDialogue: 0,0:09:32.88,0:09:36.38,Default,,0,0,0,,继而判断其奇偶性 以及是否应该求取平方并加和\nDialogue: 0,0:09:37.16,0:09:38.99,Default,,0,0,0,,然后 整个的解就是\nDialogue: 0,0:09:39.21,0:09:42.12,Default,,0,0,0,,左、右子树解的总和\nDialogue: 0,0:09:46.34,0:09:50.56,Default,,0,0,0,,好的 让我们再来和下面一个问题对比一下\nDialogue: 0,0:09:51.56,0:09:53.68,Default,,0,0,0,,假如给你一个整数N\nDialogue: 0,0:09:54.73,0:09:57.88,Default,,0,0,0,,再给定一个函数 把它应用在\nDialogue: 0,0:09:57.93,0:09:58.83,Default,,0,0,0,,1到N的每一个数上\nDialogue: 0,0:09:59.10,0:10:01.08,Default,,0,0,0,,我想把其中的一些值收集成一个表\nDialogue: 0,0:10:01.28,0:10:04.65,Default,,0,0,0,,那些满足某种属性的函数值\nDialogue: 0,0:10:05.60,0:10:06.88,Default,,0,0,0,,这是种一般性的说法\nDialogue: 0,0:10:06.88,0:10:07.98,Default,,0,0,0,,说得更具体一点\nDialogue: 0,0:10:08.62,0:10:10.48,Default,,0,0,0,,假设对于每个整数K\nDialogue: 0,0:10:10.65,0:10:12.51,Default,,0,0,0,,计算第K个斐波那契数\nDialogue: 0,0:10:14.21,0:10:16.27,Default,,0,0,0,,然后挑出其中的奇数\nDialogue: 0,0:10:16.83,0:10:18.40,Default,,0,0,0,,并把它们组成一个表\nDialogue: 0,0:10:19.05,0:10:20.71,Default,,0,0,0,,这个过程是这样的\nDialogue: 0,0:10:23.73,0:10:26.24,Default,,0,0,0,,寻找前N个斐波那契数中的奇数\nDialogue: 0,0:10:26.24,0:10:28.91,Default,,0,0,0,,这里是我们一直以来采用的循环方法\nDialogue: 0,0:10:28.91,0:10:29.82,Default,,0,0,0,,用到了递归\nDialogue: 0,0:10:30.80,0:10:31.79,Default,,0,0,0,,以K为循环变量\nDialogue: 0,0:10:32.03,0:10:34.35,Default,,0,0,0,,如果K大于N 返回空表\nDialogue: 0,0:10:35.13,0:10:37.36,Default,,0,0,0,,否则计算第K个斐波那契数\nDialogue: 0,0:10:37.44,0:10:38.06,Default,,0,0,0,,将其与变量F绑定\nDialogue: 0,0:10:40.37,0:10:42.84,Default,,0,0,0,,如果是奇数 我们把它与\nDialogue: 0,0:10:43.76,0:10:46.01,Default,,0,0,0,,从K+1计算得到的表相连接\nDialogue: 0,0:10:47.69,0:10:50.12,Default,,0,0,0,,否则 我们只取从K+1计算得到的结果\nDialogue: 0,0:10:50.73,0:10:53.00,Default,,0,0,0,,这是迭代式循环的标准写法\nDialogue: 0,0:10:53.00,0:10:55.56,Default,,0,0,0,,我们以1为初值 启动这个循环\nDialogue: 0,0:10:57.58,0:11:00.06,Default,,0,0,0,,好的 就是这两个过程\nDialogue: 0,0:11:01.60,0:11:02.90,Default,,0,0,0,,它们看起来非常不同\nDialogue: 0,0:11:02.90,0:11:04.20,Default,,0,0,0,,完全不同的结构\nDialogue: 0,0:11:04.25,0:11:06.89,Default,,0,0,0,,然而 从一个特定的角度来看\nDialogue: 0,0:11:06.92,0:11:09.61,Default,,0,0,0,,两个过程做的事情是一样的\nDialogue: 0,0:11:11.33,0:11:14.67,Default,,0,0,0,,如果我是一个信号处理工程师\nDialogue: 0,0:11:14.70,0:11:16.81,Default,,0,0,0,,我可能会说\nDialogue: 0,0:11:18.24,0:11:26.76,Default,,0,0,0,,第一个过程枚举了树的叶节点\nDialogue: 0,0:11:31.16,0:11:34.56,Default,,0,0,0,,可以认为是信号从一个全是叶节点的地方输出\nDialogue: 0,0:11:35.33,0:11:43.39,Default,,0,0,0,,我们想要过滤出其中的奇数\nDialogue: 0,0:11:43.58,0:11:44.94,Default,,0,0,0,,把它们放入某种滤波器中\nDialogue: 0,0:11:45.19,0:11:47.79,Default,,0,0,0,,然后再把它们放入某种换能器\nDialogue: 0,0:11:49.20,0:11:51.69,Default,,0,0,0,,对每一个输出 我们对其取平方\nDialogue: 0,0:11:54.44,0:11:57.44,Default,,0,0,0,,最后把结果累积在一起\nDialogue: 0,0:11:58.29,0:12:00.04,Default,,0,0,0,,我们以0为初值\nDialogue: 0,0:12:00.35,0:12:03.37,Default,,0,0,0,,通过加法把它们累积起来\nDialogue: 0,0:12:07.14,0:12:08.21,Default,,0,0,0,,这是第一个程序\nDialogue: 0,0:12:08.21,0:12:09.18,Default,,0,0,0,,对于第二个程序\nDialogue: 0,0:12:09.24,0:12:11.21,Default,,0,0,0,,我也可以用一种非常类似的方法来描述\nDialogue: 0,0:12:11.78,0:12:13.42,Default,,0,0,0,,我们枚举\nDialogue: 0,0:12:15.80,0:12:19.10,Default,,0,0,0,,从1到N这个区间上的数\nDialogue: 0,0:12:22.50,0:12:24.40,Default,,0,0,0,,对于每个数\nDialogue: 0,0:12:25.45,0:12:26.92,Default,,0,0,0,,计算对应的斐波那契数\nDialogue: 0,0:12:27.79,0:12:29.27,Default,,0,0,0,,再放入一个换能器\nDialogue: 0,0:12:29.27,0:12:30.78,Default,,0,0,0,,对于输出的结果\nDialogue: 0,0:12:31.31,0:12:34.20,Default,,0,0,0,,再通过奇偶性进行过滤\nDialogue: 0,0:12:36.27,0:12:39.24,Default,,0,0,0,,最后 我们将这些放入累积函数\nDialogue: 0,0:12:39.35,0:12:40.56,Default,,0,0,0,,这次我们要累积出一个表\nDialogue: 0,0:12:40.78,0:12:42.17,Default,,0,0,0,,所以我们用CONS来做积累\nDialogue: 0,0:12:42.59,0:12:43.77,Default,,0,0,0,,以空表为初始值\nDialogue: 0,0:12:47.11,0:12:49.80,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:12:49.85,0:12:51.84,Default,,0,0,0,,这两个程序真的是太相似了\nDialogue: 0,0:12:51.90,0:12:52.84,Default,,0,0,0,,问题在于\nDialogue: 0,0:12:53.20,0:12:56.49,Default,,0,0,0,,两个程序的写法导致\nDialogue: 0,0:12:56.64,0:12:58.05,Default,,0,0,0,,我们看不出其中的共性\nDialogue: 0,0:12:58.05,0:13:01.44,Default,,0,0,0,,再回头来看奇数平方和的问题\nDialogue: 0,0:13:02.22,0:13:04.64,Default,,0,0,0,,问题来了 哪个是枚举函数呢？\nDialogue: 0,0:13:06.35,0:13:08.14,Default,,0,0,0,,程序中哪一部分有枚举的作用？\nDialogue: 0,0:13:08.14,0:13:10.52,Default,,0,0,0,,枚举不是仅仅在一个地方表现出来的\nDialogue: 0,0:13:11.02,0:13:15.47,Default,,0,0,0,,在叶子节点的判断处存在一部分\nDialogue: 0,0:13:16.43,0:13:17.16,Default,,0,0,0,,在这个判断循环终止的地方\nDialogue: 0,0:13:17.16,0:13:20.06,Default,,0,0,0,,也下面的递归结构中也有体现\nDialogue: 0,0:13:23.15,0:13:24.12,Default,,0,0,0,,累积函数又在哪儿呢？\nDialogue: 0,0:13:24.12,0:13:25.68,Default,,0,0,0,,它也不只在一个地方\nDialogue: 0,0:13:25.68,0:13:30.73,Default,,0,0,0,,它在 0 和 + 这两个地方分别体现出来\nDialogue: 0,0:13:32.00,0:13:34.51,Default,,0,0,0,,累积函数分散在过程的每个部分\nDialogue: 0,0:13:34.51,0:13:39.05,Default,,0,0,0,,相似地 我们来观察奇数斐波那契数的例子\nDialogue: 0,0:13:39.05,0:13:42.80,Default,,0,0,0,,某种意义上 程序中也存在枚举函数与累积函数\nDialogue: 0,0:13:42.80,0:13:44.01,Default,,0,0,0,,但看起来非常不同\nDialogue: 0,0:13:44.62,0:13:50.09,Default,,0,0,0,,枚举部分地表现在(> k n)的判断中\nDialogue: 0,0:13:50.38,0:13:52.84,Default,,0,0,0,,部分地表现在下面的递归调用中\nDialogue: 0,0:13:53.18,0:13:54.24,Default,,0,0,0,,还有就是启动循环的地方\nDialogue: 0,0:13:55.68,0:13:56.32,Default,,0,0,0,,同样地\nDialogue: 0,0:13:56.52,0:13:58.76,Default,,0,0,0,,其中也混杂了累积函数\nDialogue: 0,0:13:58.91,0:14:00.12,Default,,0,0,0,,分别在这里\nDialogue: 0,0:14:00.41,0:14:01.40,Default,,0,0,0,,和这里\nDialogue: 0,0:14:03.60,0:14:06.08,Default,,0,0,0,,所以这些非常自然的部分\nDialogue: 0,0:14:08.73,0:14:12.65,Default,,0,0,0,,我们之前画的那些方框在程序中完全看不出来\nDialogue: 0,0:14:13.26,0:14:14.36,Default,,0,0,0,,因为它们混杂在一起了\nDialogue: 0,0:14:14.36,0:14:16.29,Default,,0,0,0,,这些程序并没有很好地对问题进行切分\nDialogue: 0,0:14:19.45,0:14:22.17,Default,,0,0,0,,回到计算机科学的基本原理上来\nDialogue: 0,0:14:22.19,0:14:23.63,Default,,0,0,0,,为了控制某种东西\nDialogue: 0,0:14:23.63,0:14:24.96,Default,,0,0,0,,你需要它的名字\nDialogue: 0,0:14:25.80,0:14:28.44,Default,,0,0,0,,我们还没有很好地掌握按这种方式来思考\nDialogue: 0,0:14:28.67,0:14:31.06,Default,,0,0,0,,这是因为我们没有显式地操作它们的手段\nDialogue: 0,0:14:31.06,0:14:33.80,Default,,0,0,0,,我们没有一门好的语言来讨论它们\nDialogue: 0,0:14:35.42,0:14:38.86,Default,,0,0,0,,好吧 我们来创造一门合适的语言\nDialogue: 0,0:14:42.52,0:14:44.04,Default,,0,0,0,,用它来构建这些器件\nDialogue: 0,0:14:44.78,0:14:47.21,Default,,0,0,0,,这种语言的关键在于\nDialogue: 0,0:14:47.21,0:14:49.71,Default,,0,0,0,,这些叫作信号的东西到底是什么？\nDialogue: 0,0:14:50.48,0:14:53.32,Default,,0,0,0,,这些沿着箭头传递的是什么？\nDialogue: 0,0:14:56.88,0:14:57.71,Default,,0,0,0,,这些东西\nDialogue: 0,0:14:59.85,0:15:03.52,Default,,0,0,0,,是一种称作“流”的数据结构\nDialogue: 0,0:15:03.79,0:15:05.87,Default,,0,0,0,,这也是发明这门语言的关键\nDialogue: 0,0:15:07.98,0:15:08.51,Default,,0,0,0,,“流”是什么东西呢？\nDialogue: 0,0:15:08.52,0:15:11.50,Default,,0,0,0,,和其它的东西一样 “流”是一种数据抽象\nDialogue: 0,0:15:12.22,0:15:15.82,Default,,0,0,0,,所以 我先说明它的选择函数与构造函数分别是什么\nDialogue: 0,0:15:16.87,0:15:19.48,Default,,0,0,0,,对于流结构 我们有一个构造函数\nDialogue: 0,0:15:19.98,0:15:21.43,Default,,0,0,0,,我们称其为CONS-STREAM\nDialogue: 0,0:15:25.69,0:15:28.11,Default,,0,0,0,,CONS-STREAM把两个事物放在一起\nDialogue: 0,0:15:28.59,0:15:30.22,Default,,0,0,0,,构造出一个流\nDialogue: 0,0:15:32.04,0:15:33.85,Default,,0,0,0,,选择函数叫作HEAD\nDialogue: 0,0:15:33.98,0:15:36.11,Default,,0,0,0,,用于从流中提取数据\nDialogue: 0,0:15:38.01,0:15:38.86,Default,,0,0,0,,如果我有一个流\nDialogue: 0,0:15:39.00,0:15:40.41,Default,,0,0,0,,我可以取它的头部\nDialogue: 0,0:15:41.13,0:15:42.38,Default,,0,0,0,,也可以取它的尾部\nDialogue: 0,0:15:44.72,0:15:47.42,Default,,0,0,0,,我把和George的约定告诉你\nDialogue: 0,0:15:48.24,0:15:52.70,Default,,0,0,0,,让你们知道和这个相关的公理\nDialogue: 0,0:15:53.44,0:16:00.17,Default,,0,0,0,,对于任何的X与Y\nDialogue: 0,0:16:03.40,0:16:05.44,Default,,0,0,0,,如果我把它们构造成一个流 并取其头部\nDialogue: 0,0:16:05.69,0:16:11.96,Default,,0,0,0,,(HEAD (CONS-STREAM X Y))\nDialogue: 0,0:16:13.29,0:16:14.52,Default,,0,0,0,,结果就是X\nDialogue: 0,0:16:16.14,0:16:27.45,Default,,0,0,0,,(TAIL (CONS-STREAM X Y)) = Y\nDialogue: 0,0:16:28.44,0:16:34.75,Default,,0,0,0,,一个构造函数 两个选择函数 一个公理 就是这些\nDialogue: 0,0:16:34.75,0:16:35.85,Default,,0,0,0,,这里有点可疑\nDialogue: 0,0:16:36.98,0:16:39.00,Default,,0,0,0,,你可能注意到了\nDialogue: 0,0:16:40.19,0:16:42.08,Default,,0,0,0,,这些就是CONS、CAR和CDR的公理\nDialogue: 0,0:16:43.63,0:16:46.56,Default,,0,0,0,,把CONS-STREAM换成CONS\nDialogue: 0,0:16:47.10,0:16:49.80,Default,,0,0,0,,HEAD换成CAR TAIL换成CDR\nDialogue: 0,0:16:50.76,0:16:52.81,Default,,0,0,0,,这些就是序对的公理\nDialogue: 0,0:16:52.81,0:16:54.32,Default,,0,0,0,,事实上 还有另一个东西\nDialogue: 0,0:16:55.13,0:16:56.80,Default,,0,0,0,,我们有一个叫THE-EMPTY-STREAM（空流）的东西\nDialogue: 0,0:17:02.80,0:17:04.04,Default,,0,0,0,,像空表一样\nDialogue: 0,0:17:08.31,0:17:10.03,Default,,0,0,0,,为什么我要引入这个术语呢？\nDialogue: 0,0:17:10.03,0:17:12.12,Default,,0,0,0,,为什么我不继续使用序对与表呢？\nDialogue: 0,0:17:12.78,0:17:13.79,Default,,0,0,0,,后面我们就知道了\nDialogue: 0,0:17:15.51,0:17:18.24,Default,,0,0,0,,暂时地 你们可以把术语“流”\nDialogue: 0,0:17:18.30,0:17:21.56,Default,,0,0,0,,当作“表”的另一种说法\nDialogue: 0,0:17:21.56,0:17:22.99,Default,,0,0,0,,一会儿我们就会知道 为什么\nDialogue: 0,0:17:23.61,0:17:26.09,Default,,0,0,0,,为什么我们需要这个额外的抽象层\nDialogue: 0,0:17:26.83,0:17:28.15,Default,,0,0,0,,而不是继续把它看做表\nDialogue: 0,0:17:32.30,0:17:33.72,Default,,0,0,0,,好的 有了流之后\nDialogue: 0,0:17:33.74,0:17:35.85,Default,,0,0,0,,我们就开始构建语言的部件了\nDialogue: 0,0:17:37.04,0:17:38.17,Default,,0,0,0,,用它来操作流\nDialogue: 0,0:17:38.75,0:17:42.12,Default,,0,0,0,,我们可以构建出太多有用的东西了\nDialogue: 0,0:17:42.12,0:17:42.81,Default,,0,0,0,,举例来说\nDialogue: 0,0:17:44.89,0:17:49.79,Default,,0,0,0,,我们构建MAP-STREAM 它的一个参数是流S\nDialogue: 0,0:17:54.80,0:17:56.62,Default,,0,0,0,,以及一个过程\nDialogue: 0,0:17:57.80,0:17:59.21,Default,,0,0,0,,它会生成一个新的流\nDialogue: 0,0:18:00.14,0:18:02.28,Default,,0,0,0,,它的构成元素是\nDialogue: 0,0:18:02.28,0:18:04.88,Default,,0,0,0,,将PROC应用到S的后续元素得到的结果\nDialogue: 0,0:18:05.87,0:18:07.40,Default,,0,0,0,,我们以前见过类似的\nDialogue: 0,0:18:07.40,0:18:10.24,Default,,0,0,0,,就是以前在表上定义的MAP过程\nDialogue: 0,0:18:10.95,0:18:12.60,Default,,0,0,0,,除了判断EMPTY-STREAM的部分\nDialogue: 0,0:18:12.60,0:18:14.65,Default,,0,0,0,,完全就和MAP一样\nDialogue: 0,0:18:14.65,0:18:15.56,Default,,0,0,0,,哦 我忘了说了\nDialogue: 0,0:18:15.56,0:18:17.15,Default,,0,0,0,,EMPTY-STREAM?就和NULL?差不多\nDialogue: 0,0:18:18.03,0:18:20.48,Default,,0,0,0,,如果是空的 就返回一个空的流\nDialogue: 0,0:18:20.51,0:18:22.28,Default,,0,0,0,,否则 就生成一个新的流\nDialogue: 0,0:18:23.52,0:18:27.18,Default,,0,0,0,,其第一个元素是PROC应用在流头部的结果\nDialogue: 0,0:18:28.51,0:18:29.32,Default,,0,0,0,,剩下的是\nDialogue: 0,0:18:29.60,0:18:32.43,Default,,0,0,0,,是MAP-STREAM对流尾部应用的结果\nDialogue: 0,0:18:33.14,0:18:35.90,Default,,0,0,0,,太像我们之前讲的MAP了\nDialogue: 0,0:18:37.03,0:18:38.20,Default,,0,0,0,,还有一个有用的函数\nDialogue: 0,0:18:38.35,0:18:40.46,Default,,0,0,0,,过滤函数 就是那个用来过滤的盒子\nDialogue: 0,0:18:40.46,0:18:43.89,Default,,0,0,0,,以一个谓词和一个流作为参数\nDialogue: 0,0:18:43.89,0:18:45.08,Default,,0,0,0,,它将生成一个新的流\nDialogue: 0,0:18:45.80,0:18:48.17,Default,,0,0,0,,包含了在流S中所有\nDialogue: 0,0:18:48.33,0:18:49.48,Default,,0,0,0,,满足谓词PRED的元素\nDialogue: 0,0:18:50.38,0:18:51.31,Default,,0,0,0,,这是一个“按条件分析语句”\nDialogue: 0,0:18:51.32,0:18:52.73,Default,,0,0,0,,如果流是空的\nDialogue: 0,0:18:53.04,0:18:54.22,Default,,0,0,0,,就返回一个空流\nDialogue: 0,0:18:56.28,0:18:59.18,Default,,0,0,0,,这里 用谓词来判断流的头元素\nDialogue: 0,0:19:00.06,0:19:01.04,Default,,0,0,0,,如果为真\nDialogue: 0,0:19:01.53,0:19:02.83,Default,,0,0,0,,就把这个元素\nDialogue: 0,0:19:03.02,0:19:06.22,Default,,0,0,0,,和过滤流的尾元素得到的结果连接在一起\nDialogue: 0,0:19:08.22,0:19:10.04,Default,,0,0,0,,否则 如果谓词判断为假\nDialogue: 0,0:19:10.49,0:19:11.98,Default,,0,0,0,,就只返回过滤流的尾元素的结果\nDialogue: 0,0:19:13.50,0:19:14.46,Default,,0,0,0,,这就是过滤函数的原理\nDialogue: 0,0:19:16.59,0:19:18.56,Default,,0,0,0,,剩下的我快速过一遍\nDialogue: 0,0:19:18.56,0:19:20.70,Default,,0,0,0,,这些在书上都有 你们可以自己看\nDialogue: 0,0:19:20.88,0:19:21.80,Default,,0,0,0,,来马上过一遍\nDialogue: 0,0:19:22.11,0:19:22.94,Default,,0,0,0,,过程ACCUMULATE\nDialogue: 0,0:19:23.26,0:19:26.92,Default,,0,0,0,,ACCUMULATE的参数有：一个组合函数\nDialogue: 0,0:19:27.36,0:19:29.05,Default,,0,0,0,,一个初始值和一个流\nDialogue: 0,0:19:29.96,0:19:31.13,Default,,0,0,0,,将它们组合在一起\nDialogue: 0,0:19:31.56,0:19:33.69,Default,,0,0,0,,如果流为空 返回初始值\nDialogue: 0,0:19:33.97,0:19:36.20,Default,,0,0,0,,否则 我们就把流头部\nDialogue: 0,0:19:36.32,0:19:37.82,Default,,0,0,0,,和流尾部做ACCUMLATE的结果\nDialogue: 0,0:19:38.01,0:19:40.24,Default,,0,0,0,,组合起来\nDialogue: 0,0:19:40.90,0:19:42.83,Default,,0,0,0,,这就是把流中元素累积在一起的方法\nDialogue: 0,0:19:42.83,0:19:43.98,Default,,0,0,0,,我会用加法来累积\nDialogue: 0,0:19:45.83,0:19:47.56,Default,,0,0,0,,如何枚举树上的叶节点呢？\nDialogue: 0,0:19:48.06,0:19:52.89,Default,,0,0,0,,如果这个树只是一个叶节点\nDialogue: 0,0:19:53.79,0:19:55.90,Default,,0,0,0,,我就构造一个只含有一个叶子节点的流\nDialogue: 0,0:19:56.64,0:19:59.32,Default,,0,0,0,,否则的话 我就把\nDialogue: 0,0:19:59.61,0:20:02.35,Default,,0,0,0,,左、右子树枚举的结果合并起来\nDialogue: 0,0:20:04.34,0:20:08.32,Default,,0,0,0,,这里的APPEND-STREAM跟表上的APPEND类似\nDialogue: 0,0:20:13.19,0:20:13.85,Default,,0,0,0,,再来看这个\nDialogue: 0,0:20:13.85,0:20:17.53,Default,,0,0,0,,这跟和合并两个表的过程太相似了\nDialogue: 0,0:20:18.91,0:20:20.60,Default,,0,0,0,,如何枚举一个区间呢？\nDialogue: 0,0:20:21.96,0:20:23.77,Default,,0,0,0,,它有两个参数 LOW和HIGH\nDialogue: 0,0:20:23.88,0:20:27.00,Default,,0,0,0,,生成一个包含从LOW到HIGH的所有整数的流\nDialogue: 0,0:20:28.32,0:20:29.88,Default,,0,0,0,,由此 我们就可以构造一大堆的元件\nDialogue: 0,0:20:31.89,0:20:34.48,Default,,0,0,0,,这就是一门用来讨论流的小型语言\nDialogue: 0,0:20:34.49,0:20:35.32,Default,,0,0,0,,当我们有了流\nDialogue: 0,0:20:35.32,0:20:37.67,Default,,0,0,0,,就可以构建用于操作它们的过程\nDialogue: 0,0:20:37.67,0:20:39.04,Default,,0,0,0,,请注意 我们正在构建一门语言\nDialogue: 0,0:20:40.20,0:20:42.22,Default,,0,0,0,,现在 我们可以用这门语言来表达我们的想法\nDialogue: 0,0:20:43.06,0:20:47.31,Default,,0,0,0,,这个原始过程是累加树中奇数的平方的\nDialogue: 0,0:20:47.31,0:20:52.62,Default,,0,0,0,,现在你会发现 它和那些方块图如出一辙\nDialogue: 0,0:20:52.64,0:20:54.59,Default,,0,0,0,,跟我们的信号处理方块图相吻合\nDialogue: 0,0:20:54.59,0:20:57.53,Default,,0,0,0,,要计算树上奇数平方和\nDialogue: 0,0:20:58.06,0:21:00.80,Default,,0,0,0,,先枚举树上的叶子节点\nDialogue: 0,0:21:01.32,0:21:03.72,Default,,0,0,0,,过滤出奇数\nDialogue: 0,0:21:04.83,0:21:06.54,Default,,0,0,0,,再用平方来做映射\nDialogue: 0,0:21:09.32,0:21:13.34,Default,,0,0,0,,最后用加法来累积 初始值是0\nDialogue: 0,0:21:14.76,0:21:17.20,Default,,0,0,0,,这样我们就可以看到需要的片段\nDialogue: 0,0:21:17.29,0:21:19.36,Default,,0,0,0,,类似地 斐波那契数的那个问题\nDialogue: 0,0:21:20.04,0:21:21.88,Default,,0,0,0,,我们如何获得奇斐波那契数呢？\nDialogue: 0,0:21:22.05,0:21:24.57,Default,,0,0,0,,从1到N枚举整数\nDialogue: 0,0:21:26.32,0:21:28.64,Default,,0,0,0,,再把FIB过程映射到上面\nDialogue: 0,0:21:28.99,0:21:30.70,Default,,0,0,0,,用来求取每项斐波那契数\nDialogue: 0,0:21:30.92,0:21:33.79,Default,,0,0,0,,过滤出奇数的部分\nDialogue: 0,0:21:34.81,0:21:36.64,Default,,0,0,0,,最后 以空表为初始值\nDialogue: 0,0:21:36.88,0:21:39.12,Default,,0,0,0,,用CONS将它们积累起来\nDialogue: 0,0:21:43.65,0:21:47.53,Default,,0,0,0,,那么 这么做有什么优势呢？\nDialogue: 0,0:21:47.68,0:21:48.59,Default,,0,0,0,,首先一点\nDialogue: 0,0:21:48.68,0:21:51.15,Default,,0,0,0,,我们现在有可以用来混搭的元件了\nDialogue: 0,0:21:51.88,0:21:52.64,Default,,0,0,0,,比如说\nDialogue: 0,0:21:52.91,0:21:55.08,Default,,0,0,0,,如果我想把这里改变一下\nDialogue: 0,0:21:58.19,0:22:00.32,Default,,0,0,0,,想要计算整数的平方再进行过滤\nDialogue: 0,0:22:00.33,0:22:01.34,Default,,0,0,0,,我只需要\nDialogue: 0,0:22:01.90,0:22:03.64,Default,,0,0,0,,拿个像这里的MAP SQUARE这样的元件\nDialogue: 0,0:22:03.68,0:22:05.40,Default,,0,0,0,,放进去就行了\nDialogue: 0,0:22:06.57,0:22:07.60,Default,,0,0,0,,又或者 如果我们想\nDialogue: 0,0:22:07.69,0:22:11.45,Default,,0,0,0,,寻找树的叶节点对应的斐波那契数\nDialogue: 0,0:22:11.58,0:22:12.36,Default,,0,0,0,,而不是一个序列所对应的\nDialogue: 0,0:22:12.38,0:22:13.24,Default,,0,0,0,,我只需要\nDialogue: 0,0:22:13.40,0:22:15.93,Default,,0,0,0,,用这个枚举函数替换这个枚举函数\nDialogue: 0,0:22:18.03,0:22:19.82,Default,,0,0,0,,看到了吧 流处理的优势就是\nDialogue: 0,0:22:20.24,0:22:21.53,Default,,0,0,0,,我们建立了 --\nDialogue: 0,0:22:22.36,0:22:24.96,Default,,0,0,0,,这也是本课中的一个重要主题 --\nDialogue: 0,0:22:25.29,0:22:27.48,Default,,0,0,0,,我们建立了一个约定的接口\nDialogue: 0,0:22:32.89,0:22:37.15,Default,,0,0,0,,约定的接口可以让我们把事物粘合起来\nDialogue: 0,0:22:38.30,0:22:39.55,Default,,0,0,0,,像MAP和FILTER这样的东西\nDialogue: 0,0:22:39.79,0:22:41.64,Default,,0,0,0,,可以作为一组标准的组件\nDialogue: 0,0:22:41.68,0:22:44.76,Default,,0,0,0,,我们可以拿过来随意组合去构造程序\nDialogue: 0,0:22:45.75,0:22:48.81,Default,,0,0,0,,它让我们看到了程序的共性\nDialogue: 0,0:22:49.95,0:22:50.92,Default,,0,0,0,,虽然在这里\nDialogue: 0,0:22:51.08,0:22:53.07,Default,,0,0,0,,我只是给你们演示了两个过程而已\nDialogue: 0,0:22:53.86,0:22:55.16,Default,,0,0,0,,但是我要告诉你\nDialogue: 0,0:22:55.20,0:22:57.77,Default,,0,0,0,,像这种用MAP、FILTER和ACCUMULATE\nDialogue: 0,0:22:57.80,0:23:01.00,Default,,0,0,0,,组合起来构建程序的方式是非常非常通用的\nDialogue: 0,0:23:01.41,0:23:07.28,Default,,0,0,0,,这是一种“生成-测试”的编程范式\nDialogue: 0,0:23:07.77,0:23:09.10,Default,,0,0,0,,举例来看\nDialogue: 0,0:23:09.39,0:23:12.94,Default,,0,0,0,,Richarc Waters -- MIT的一名硕士生\nDialogue: 0,0:23:12.96,0:23:15.26,Default,,0,0,0,,他的学位论文的一部分调研了\nDialogue: 0,0:23:15.80,0:23:19.21,Default,,0,0,0,,IBM的科学计算程序库的主要代码\nDialogue: 0,0:23:19.82,0:23:23.31,Default,,0,0,0,,发现其中60%的程序\nDialogue: 0,0:23:24.06,0:23:28.25,Default,,0,0,0,,都可以用这样的范式来准确的表示出来\nDialogue: 0,0:23:28.86,0:23:30.17,Default,,0,0,0,,只用MAP、FILTER和ACCUMULATE\nDialogue: 0,0:23:30.57,0:23:31.50,Default,,0,0,0,,好 让我们休息一会\nDialogue: 0,0:23:36.59,0:23:37.12,Default,,0,0,0,,有问题吗？\nDialogue: 0,0:23:41.18,0:23:42.89,Default,,0,0,0,,学生：整件事情的本质好像只是\nDialogue: 0,0:23:42.89,0:23:45.96,Default,,0,0,0,,因为你用了一个统一、简单的数据结构\nDialogue: 0,0:23:46.25,0:23:47.66,Default,,0,0,0,,也就是流\nDialogue: 0,0:23:48.38,0:23:48.92,Default,,0,0,0,,教授：对\nDialogue: 0,0:23:48.92,0:23:50.38,Default,,0,0,0,,本质就是\nDialogue: 0,0:23:50.40,0:23:53.07,Default,,0,0,0,,用这种约定的接口\nDialogue: 0,0:23:53.71,0:23:55.61,Default,,0,0,0,,因此你可以把许多东西组合起来\nDialogue: 0,0:23:56.01,0:23:58.78,Default,,0,0,0,,流只是 就像你说的\nDialogue: 0,0:23:58.78,0:24:00.89,Default,,0,0,0,,只是一种可以支持那样操作的统一的数据结构而已\nDialogue: 0,0:24:00.89,0:24:02.84,Default,,0,0,0,,顺便说下 这非常像APL\nDialogue: 0,0:24:03.60,0:24:05.21,Default,,0,0,0,,APL有着非常相似的思想\nDialogue: 0,0:24:05.21,0:24:06.96,Default,,0,0,0,,只是在APL中使用的不是流\nDialogue: 0,0:24:07.13,0:24:08.44,Default,,0,0,0,,而是使用数组和向量\nDialogue: 0,0:24:09.56,0:24:14.48,Default,,0,0,0,,而且APL的威力就在于此\nDialogue: 0,0:24:19.91,0:24:20.91,Default,,0,0,0,,好吧 谢谢\nDialogue: 0,0:24:20.91,0:24:21.66,Default,,0,0,0,,休息一下\nDialogue: 0,0:24:21.66,0:24:30.35,Default,,0,0,0,,[音乐]\nDialogue: 0,0:24:30.44,0:24:35.77,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:24:41.00,0:24:45.39,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:24:45.42,0:24:47.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:24:47.98,0:24:52.70,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 I\nDialogue: 0,0:24:57.47,0:24:57.61,Default,,0,0,0,,好的\nDialogue: 0,0:24:57.61,0:24:58.59,Default,,0,0,0,,我们已经见识过了\nDialogue: 0,0:25:00.54,0:25:03.20,Default,,0,0,0,,如何用流来组织计算过程\nDialogue: 0,0:25:03.85,0:25:05.47,Default,,0,0,0,,但是现在我想要给你们再演示两个\nDialogue: 0,0:25:05.93,0:25:09.12,Default,,0,0,0,,更复杂的例子\nDialogue: 0,0:25:10.84,0:25:14.12,Default,,0,0,0,,我们先来考虑一下\nDialogue: 0,0:25:14.20,0:25:16.81,Default,,0,0,0,,这样一种有用的过程\nDialogue: 0,0:25:16.81,0:25:18.09,Default,,0,0,0,,假设我有一个流\nDialogue: 0,0:25:19.96,0:25:23.15,Default,,0,0,0,,流中的元素本身就是一个流\nDialogue: 0,0:25:23.98,0:25:26.53,Default,,0,0,0,,一开始是1、2、3\nDialogue: 0,0:25:32.72,0:25:33.88,Default,,0,0,0,,就是这样的一个流\nDialogue: 0,0:25:33.88,0:25:40.10,Default,,0,0,0,,流中的元素也是一个流\nDialogue: 0,0:25:40.97,0:25:43.42,Default,,0,0,0,,而我想要构建出一个流\nDialogue: 0,0:25:43.64,0:25:46.75,Default,,0,0,0,,用来收集所有的元素\nDialogue: 0,0:25:46.76,0:25:49.24,Default,,0,0,0,,把所有元素从子流中提取出来\nDialogue: 0,0:25:50.11,0:25:51.82,Default,,0,0,0,,最后把它们串接在一起\nDialogue: 0,0:25:52.27,0:25:55.61,Default,,0,0,0,,为了凸显使用这门语言多么简单\nDialogue: 0,0:25:56.11,0:25:57.10,Default,,0,0,0,,我们来定义这个FLATTEN过程\nDialogue: 0,0:25:57.95,0:26:10.64,Default,,0,0,0,,FLATTEN过程的参数是由流构成的流\nDialogue: 0,0:26:12.89,0:26:13.80,Default,,0,0,0,,那么 具体定义是怎样的呢？\nDialogue: 0,0:26:13.96,0:26:16.24,Default,,0,0,0,,它只是一个累积\nDialogue: 0,0:26:16.32,0:26:25.05,Default,,0,0,0,,我想用APPEND来做累积\nDialogue: 0,0:26:25.07,0:26:26.45,Default,,0,0,0,,也就是不断地做APPEND\nDialogue: 0,0:26:26.73,0:26:29.29,Default,,0,0,0,,所以我用APPEND-STREAM做累积\nDialogue: 0,0:26:35.90,0:26:48.20,Default,,0,0,0,,以THE-EMPTY-STREAM为初始值 累积这个流\nDialogue: 0,0:26:54.84,0:26:55.84,Default,,0,0,0,,这个例子告诉我们\nDialogue: 0,0:26:56.92,0:26:59.23,Default,,0,0,0,,你可以使用这些高阶过程\nDialogue: 0,0:26:59.60,0:27:00.83,Default,,0,0,0,,来做一些有趣的运算\nDialogue: 0,0:27:00.83,0:27:05.10,Default,,0,0,0,,事实上 我还想定义另一个实用过程\nDialogue: 0,0:27:05.10,0:27:07.05,Default,,0,0,0,,定义一个过程FLAT-MAP\nDialogue: 0,0:27:17.18,0:27:20.59,Default,,0,0,0,,它以一个过程和一个流为参数\nDialogue: 0,0:27:21.84,0:27:25.72,Default,,0,0,0,,其中S是一个流\nDialogue: 0,0:27:25.72,0:27:27.69,Default,,0,0,0,,F是一个过程\nDialogue: 0,0:27:27.72,0:27:30.62,Default,,0,0,0,,它作用于流中的每个元素 并产生一个新的流\nDialogue: 0,0:27:31.95,0:27:34.52,Default,,0,0,0,,我想从这些流中取出所有的元素\nDialogue: 0,0:27:35.00,0:27:36.00,Default,,0,0,0,,并把它们组合在一起\nDialogue: 0,0:27:36.00,0:27:49.13,Default,,0,0,0,,所以对应的代码就是 (FLATTEN (MAP F S))\nDialogue: 0,0:27:51.20,0:27:53.04,Default,,0,0,0,,每当我将F应用在S的某个元素上\nDialogue: 0,0:27:53.05,0:27:53.85,Default,,0,0,0,,我得到了一个流\nDialogue: 0,0:27:54.29,0:27:55.24,Default,,0,0,0,,执行完这条MAP语句后\nDialogue: 0,0:27:55.24,0:27:56.27,Default,,0,0,0,,我得到了一个由流构成的流\nDialogue: 0,0:27:56.46,0:27:57.42,Default,,0,0,0,,再把它进行FLATTEN\nDialogue: 0,0:27:58.67,0:28:02.64,Default,,0,0,0,,我想再使用这种方式\nDialogue: 0,0:28:03.87,0:28:05.84,Default,,0,0,0,,来解决另一个大家很熟悉的问题\nDialogue: 0,0:28:06.51,0:28:12.27,Default,,0,0,0,,这个问题和我们以前遇到过的许多问题一样\nDialogue: 0,0:28:12.28,0:28:13.96,Default,,0,0,0,,只是有些变型\nDialogue: 0,0:28:14.19,0:28:15.49,Default,,0,0,0,,给定整数N\nDialogue: 0,0:28:18.68,0:28:19.93,Default,,0,0,0,,我们的问题是\nDialogue: 0,0:28:21.20,0:28:31.53,Default,,0,0,0,,找出所有的整数序对(I, J)\nDialogue: 0,0:28:32.30,0:28:39.96,Default,,0,0,0,,其中 0 < J < I <= N\nDialogue: 0,0:28:42.33,0:28:52.03,Default,,0,0,0,,使得 I+J 是一个质数\nDialogue: 0,0:28:55.74,0:28:57.92,Default,,0,0,0,,如果N=6\nDialogue: 0,0:28:59.74,0:29:00.78,Default,,0,0,0,,我在这儿画个小表格\nDialogue: 0,0:29:01.55,0:29:06.67,Default,,0,0,0,,表头是I、J和I+J\nDialogue: 0,0:29:09.70,0:29:14.91,Default,,0,0,0,,比如说I=2 J=1 那么I+J就是3\nDialogue: 0,0:29:15.52,0:29:20.38,Default,,0,0,0,,然后I=3 J=2 那么I+J就是5\nDialogue: 0,0:29:21.21,0:29:26.51,Default,,0,0,0,,I=4 J=1 I+J=5也是一样的 等等\nDialogue: 0,0:29:26.92,0:29:28.11,Default,,0,0,0,,直到I到了6就终止了\nDialogue: 0,0:29:28.40,0:29:32.54,Default,,0,0,0,,我想要这个过程产生并返回这样的一个流\nDialogue: 0,0:29:33.20,0:29:37.04,Default,,0,0,0,,就是像 (I, J, I+J) 这样的三元组组成的流\nDialogue: 0,0:29:37.66,0:29:39.55,Default,,0,0,0,,对于每个整数N 我想得到一个这样流\nDialogue: 0,0:29:40.97,0:29:43.68,Default,,0,0,0,,听起来很简单\nDialogue: 0,0:29:43.68,0:29:44.35,Default,,0,0,0,,我们做做看\nDialogue: 0,0:29:47.23,0:29:48.22,Default,,0,0,0,,先这样开始\nDialogue: 0,0:29:50.15,0:29:54.25,Default,,0,0,0,,对于每一个整数 I\nDialogue: 0,0:29:55.24,0:29:56.44,Default,,0,0,0,,生成一个流\nDialogue: 0,0:29:57.00,0:29:58.59,Default,,0,0,0,,对于I从1取到N\nDialogue: 0,0:29:58.59,0:29:59.76,Default,,0,0,0,,每个I都生成一个流\nDialogue: 0,0:30:00.66,0:30:01.80,Default,,0,0,0,,这个流将会是什么样子？\nDialogue: 0,0:30:02.23,0:30:04.04,Default,,0,0,0,,我们先生成所有的序对\nDialogue: 0,0:30:04.18,0:30:07.55,Default,,0,0,0,,对于每个I 我们先生成\nDialogue: 0,0:30:08.43,0:30:14.52,Default,,0,0,0,,对于每个从1取到I-1的J\nDialogue: 0,0:30:16.91,0:30:17.98,Default,,0,0,0,,我们先生成序对\nDialogue: 0,0:30:18.35,0:30:20.71,Default,,0,0,0,,也就是只含有I和J的表\nDialogue: 0,0:30:23.78,0:30:27.10,Default,,0,0,0,,因此我们对整个区间做映射\nDialogue: 0,0:30:28.60,0:30:29.74,Default,,0,0,0,,生成序对\nDialogue: 0,0:30:31.07,0:30:33.17,Default,,0,0,0,,对于每个I 都生成一个序对流\nDialogue: 0,0:30:33.40,0:30:34.49,Default,,0,0,0,,最后进行FLATMAP\nDialogue: 0,0:30:34.59,0:30:36.20,Default,,0,0,0,,这样我们就生成了所有的(I, J)序对\nDialogue: 0,0:30:36.81,0:30:38.08,Default,,0,0,0,,其中I <= J\nDialogue: 0,0:30:38.73,0:30:39.85,Default,,0,0,0,,就是这样\nDialogue: 0,0:30:39.85,0:30:40.76,Default,,0,0,0,,紧接着就是过滤\nDialogue: 0,0:30:42.99,0:30:45.84,Default,,0,0,0,,我们对刚才FLATMAP得到的东西\nDialogue: 0,0:30:46.94,0:30:51.37,Default,,0,0,0,,我们以I -- 这里分别是 I 和 J\nDialogue: 0,0:30:51.66,0:30:54.17,Default,,0,0,0,,I是表的第一个元素\nDialogue: 0,0:30:54.30,0:30:55.60,Default,,0,0,0,,J是第二个\nDialogue: 0,0:30:57.21,0:31:00.01,Default,,0,0,0,,我们用一个谓词来判断 表中的两个元素\nDialogue: 0,0:31:00.22,0:31:02.00,Default,,0,0,0,,也就是表的CAR部分与CDR部分之和 是否为质数\nDialogue: 0,0:31:02.07,0:31:05.52,Default,,0,0,0,,用这个谓词来过滤刚刚收集起来的表\nDialogue: 0,0:31:06.54,0:31:07.85,Default,,0,0,0,,就得到了我们想要的表\nDialogue: 0,0:31:09.42,0:31:10.24,Default,,0,0,0,,然后我们继续\nDialogue: 0,0:31:10.88,0:31:13.10,Default,,0,0,0,,把过滤得到的结果 再次进行MAP操作\nDialogue: 0,0:31:13.26,0:31:19.05,Default,,0,0,0,,用来生成 I、J 和 I+J 构成的表\nDialogue: 0,0:31:19.61,0:31:21.39,Default,,0,0,0,,这就是过程 PRIME-SUM-PAIRS\nDialogue: 0,0:31:22.57,0:31:24.76,Default,,0,0,0,,最后只需要过一遍 这就是整个过程\nDialogue: 0,0:31:28.08,0:31:30.97,Default,,0,0,0,,一个MAP、一个FILTER 以及一个FLATMAP\nDialogue: 0,0:31:34.85,0:31:35.66,Default,,0,0,0,,所有的东西都在这里了\nDialogue: 0,0:31:35.66,0:31:37.12,Default,,0,0,0,,尽管可读性不是那么好\nDialogue: 0,0:31:37.42,0:31:38.94,Default,,0,0,0,,我们只是把中间过程展开了\nDialogue: 0,0:31:39.84,0:31:40.88,Default,,0,0,0,,这个例子\nDialogue: 0,0:31:43.28,0:31:45.00,Default,,0,0,0,,向我们展示了\nDialogue: 0,0:31:45.12,0:31:46.30,Default,,0,0,0,,嵌套循环\nDialogue: 0,0:31:47.66,0:31:50.09,Default,,0,0,0,,在这个过程中 它看起来就像\nDialogue: 0,0:31:50.11,0:31:52.81,Default,,0,0,0,,各种嵌套的MAP和FLATMAP的组合\nDialogue: 0,0:31:54.27,0:31:57.61,Default,,0,0,0,,所以我们不仅仅可以枚举单个个体\nDialogue: 0,0:31:57.61,0:31:58.81,Default,,0,0,0,,通过使用FLATMAP\nDialogue: 0,0:31:59.12,0:32:02.24,Default,,0,0,0,,我们可以实现其它语言中的嵌套循环\nDialogue: 0,0:32:03.23,0:32:03.76,Default,,0,0,0,,当然\nDialogue: 0,0:32:04.91,0:32:08.03,Default,,0,0,0,,重复写这些FLATMAP很烦人\nDialogue: 0,0:32:08.41,0:32:13.00,Default,,0,0,0,,尽管PRIME-SUM-PAIRS其中单独的部分很容易\nDialogue: 0,0:32:13.56,0:32:15.28,Default,,0,0,0,,但整体看起来还是十分复杂\nDialogue: 0,0:32:15.48,0:32:17.13,Default,,0,0,0,,如果你愿意的话 可以\nDialogue: 0,0:32:17.15,0:32:20.12,Default,,0,0,0,,引进一个叫COLLECT的语法糖衣\nDialogue: 0,0:32:21.04,0:32:22.68,Default,,0,0,0,,COLLECT只是一个缩写\nDialogue: 0,0:32:22.91,0:32:26.16,Default,,0,0,0,,用来代表特定顺序的FLATMAP和FILTER操作\nDialogue: 0,0:32:26.16,0:32:28.60,Default,,0,0,0,,这里我们用COLLECT把PRIME-SUM-PAIRS写一遍\nDialogue: 0,0:32:29.45,0:32:36.27,Default,,0,0,0,,PRIME-SUM-PAIRS过程需要收集这样一个东西\nDialogue: 0,0:32:36.52,0:32:39.20,Default,,0,0,0,,它的元素是形如(I, J, I+J)这样的表\nDialogue: 0,0:32:40.84,0:32:45.39,Default,,0,0,0,,而这将通过I从1取到N\nDialogue: 0,0:32:47.44,0:32:52.32,Default,,0,0,0,,同时J要从1取到I-1来产生\nDialogue: 0,0:32:54.16,0:32:56.54,Default,,0,0,0,,并且要满足I+J是质数\nDialogue: 0,0:32:58.04,0:33:00.32,Default,,0,0,0,,课堂上我就不讲解如何定义COLLECT了\nDialogue: 0,0:33:00.69,0:33:02.75,Default,,0,0,0,,书上面有\nDialogue: 0,0:33:03.42,0:33:05.45,Default,,0,0,0,,不过你可以清楚地看到 这些代码片段\nDialogue: 0,0:33:05.84,0:33:08.60,Default,,0,0,0,,就是我原先写的过程中的片段\nDialogue: 0,0:33:08.82,0:33:11.40,Default,,0,0,0,,COLLECT过程只是一个语法糖衣\nDialogue: 0,0:33:11.44,0:33:14.80,Default,,0,0,0,,用来自动生成嵌套FLATMAP\nDialogue: 0,0:33:16.31,0:33:20.33,Default,,0,0,0,,好的 我们再来看另一个例子\nDialogue: 0,0:33:20.67,0:33:22.00,Default,,0,0,0,,也展示了同样的道理\nDialogue: 0,0:33:22.12,0:33:23.53,Default,,0,0,0,,这是一个非常著名的问题\nDialogue: 0,0:33:24.70,0:33:28.75,Default,,0,0,0,,经常用来演示所谓的“回溯”算法\nDialogue: 0,0:33:28.76,0:33:30.20,Default,,0,0,0,,这就是“八皇后问题”\nDialogue: 0,0:33:30.20,0:33:31.08,Default,,0,0,0,,这是一个棋盘\nDialogue: 0,0:33:32.37,0:33:33.64,Default,,0,0,0,,八皇后问题要求我们\nDialogue: 0,0:33:33.64,0:33:35.85,Default,,0,0,0,,找到一种将八个皇后放到棋盘上的摆法\nDialogue: 0,0:33:36.44,0:33:38.00,Default,,0,0,0,,使得任意的两个皇后不会相互攻击\nDialogue: 0,0:33:38.00,0:33:40.60,Default,,0,0,0,,这里给出了一个解法\nDialogue: 0,0:33:41.21,0:33:43.68,Default,,0,0,0,,我需要保证摆放好后\nDialogue: 0,0:33:43.71,0:33:46.80,Default,,0,0,0,,任意两个皇后不在同一行或同一列上\nDialogue: 0,0:33:47.72,0:33:49.47,Default,,0,0,0,,也不在同一对角线上\nDialogue: 0,0:33:51.41,0:33:56.40,Default,,0,0,0,,有一个解决这个问题的标准解法\nDialogue: 0,0:33:59.74,0:34:01.48,Default,,0,0,0,,首先我们要做是\nDialogue: 0,0:34:02.54,0:34:04.62,Default,,0,0,0,,进入底层 站在George的层面\nDialogue: 0,0:34:04.94,0:34:08.09,Default,,0,0,0,,找到一种表示棋盘与位置的方式\nDialogue: 0,0:34:08.09,0:34:09.52,Default,,0,0,0,,这个并不需要太担心\nDialogue: 0,0:34:09.80,0:34:12.78,Default,,0,0,0,,假设我们有一个谓词SAFE?\nDialogue: 0,0:34:16.14,0:34:17.55,Default,,0,0,0,,SAFE?判断的是\nDialogue: 0,0:34:17.96,0:34:20.84,Default,,0,0,0,,假如一些皇后已经放在棋盘上\nDialogue: 0,0:34:21.36,0:34:24.54,Default,,0,0,0,,在这个点再放置一个皇后是否是安全？\nDialogue: 0,0:34:25.40,0:34:31.26,Default,,0,0,0,,所以SAFE?的参数分别为ROW和COLUMN\nDialogue: 0,0:34:32.76,0:34:35.47,Default,,0,0,0,,我将尝试把下一个皇后放在那个地方\nDialogue: 0,0:34:36.06,0:34:42.76,Default,,0,0,0,,另外一个参数是剩下的位置\nDialogue: 0,0:34:45.58,0:34:46.75,Default,,0,0,0,,SAFE?要判断的是\nDialogue: 0,0:34:46.86,0:34:51.68,Default,,0,0,0,,在这些位置已经放置了皇后的情况下\nDialogue: 0,0:34:53.02,0:34:54.76,Default,,0,0,0,,在这行这列放置皇后\nDialogue: 0,0:34:55.10,0:34:57.20,Default,,0,0,0,,是否安全\nDialogue: 0,0:34:58.30,0:34:59.36,Default,,0,0,0,,不用过分深究这个\nDialogue: 0,0:34:59.36,0:35:01.38,Default,,0,0,0,,那是George的问题 也不难写出来\nDialogue: 0,0:35:01.38,0:35:06.27,Default,,0,0,0,,只需要检测该行、该列\nDialogue: 0,0:35:06.30,0:35:08.52,Default,,0,0,0,,以及对角线上是否有东西即可\nDialogue: 0,0:35:10.53,0:35:13.12,Default,,0,0,0,,那么 有了这个过程后 我们的程序该如何组织呢？\nDialogue: 0,0:35:13.84,0:35:17.21,Default,,0,0,0,,有一种传统的方式\nDialogue: 0,0:35:17.93,0:35:18.97,Default,,0,0,0,,我们称为“回溯”\nDialogue: 0,0:35:20.52,0:35:23.21,Default,,0,0,0,,首先让我们来考虑\nDialogue: 0,0:35:25.13,0:35:28.88,Default,,0,0,0,,把第一个皇后放在第一列的\nDialogue: 0,0:35:30.04,0:35:31.34,Default,,0,0,0,,所有方式\nDialogue: 0,0:35:31.45,0:35:32.24,Default,,0,0,0,,有8种\nDialogue: 0,0:35:32.58,0:35:35.00,Default,,0,0,0,,先试下第一列\nDialogue: 0,0:35:35.88,0:35:37.30,Default,,0,0,0,,第一行第一列\nDialogue: 0,0:35:37.30,0:35:38.70,Default,,0,0,0,,每个分支都代表了\nDialogue: 0,0:35:40.17,0:35:41.88,Default,,0,0,0,,在每一个层次的可能解\nDialogue: 0,0:35:43.36,0:35:45.53,Default,,0,0,0,,我试着把皇后放在第一列\nDialogue: 0,0:35:46.14,0:35:47.74,Default,,0,0,0,,现在 我在第一列放置好一个皇后以后\nDialogue: 0,0:35:47.77,0:35:49.98,Default,,0,0,0,,我又尝试在第一列放置下一个皇后\nDialogue: 0,0:35:50.60,0:35:52.17,Default,,0,0,0,,并不成功 它们都……\nDialogue: 0,0:35:53.31,0:35:54.60,Default,,0,0,0,,我尝试把第一个皇后\nDialogue: 0,0:35:54.86,0:35:56.80,Default,,0,0,0,,把在第一列上的那个皇后 放在第一行\nDialogue: 0,0:35:56.92,0:35:57.47,Default,,0,0,0,,不好意思\nDialogue: 0,0:35:59.05,0:36:01.39,Default,,0,0,0,,放好后 我们再把下一个皇后放在第一行\nDialogue: 0,0:36:01.39,0:36:02.09,Default,,0,0,0,,这不行\nDialogue: 0,0:36:02.09,0:36:03.18,Default,,0,0,0,,所以又回到这里\nDialogue: 0,0:36:04.20,0:36:04.72,Default,,0,0,0,,然后再考虑\nDialogue: 0,0:36:04.83,0:36:06.86,Default,,0,0,0,,我们把这个皇后放在第二行吗？\nDialogue: 0,0:36:07.32,0:36:08.38,Default,,0,0,0,,然而也不行\nDialogue: 0,0:36:08.55,0:36:09.76,Default,,0,0,0,,那么放在第三行呢？\nDialogue: 0,0:36:09.76,0:36:10.52,Default,,0,0,0,,这样可以\nDialogue: 0,0:36:12.79,0:36:15.13,Default,,0,0,0,,下一个皇后可以放在第一列吗？\nDialogue: 0,0:36:15.38,0:36:17.82,Default,,0,0,0,,我不能再画更多的棋盘了\nDialogue: 0,0:36:17.82,0:36:18.86,Default,,0,0,0,,但我先假设这个可行\nDialogue: 0,0:36:19.19,0:36:20.45,Default,,0,0,0,,我尝试下一个\nDialogue: 0,0:36:20.45,0:36:24.17,Default,,0,0,0,,在每一个地方 尽可能的沿着树往下\nDialogue: 0,0:36:24.54,0:36:25.64,Default,,0,0,0,,然后回退\nDialogue: 0,0:36:25.64,0:36:28.97,Default,,0,0,0,,如果我从这里往下走 发现下面不可能有解\nDialogue: 0,0:36:29.00,0:36:30.12,Default,,0,0,0,,我就回溯到这里来\nDialogue: 0,0:36:30.28,0:36:32.44,Default,,0,0,0,,然后开始生成这个子树\nDialogue: 0,0:36:33.26,0:36:34.32,Default,,0,0,0,,我就像这样遍历\nDialogue: 0,0:36:35.05,0:36:37.26,Default,,0,0,0,,最后 一路求解下来\nDialogue: 0,0:36:37.72,0:36:38.59,Default,,0,0,0,,就会得到答案\nDialogue: 0,0:36:39.82,0:36:41.98,Default,,0,0,0,,这种典型的范式\nDialogue: 0,0:36:43.12,0:36:45.93,Default,,0,0,0,,之前被广泛地使用在人工智能编程中\nDialogue: 0,0:36:45.93,0:36:47.30,Default,,0,0,0,,术语叫做 “回溯搜索”\nDialogue: 0,0:36:57.47,0:37:03.04,Default,,0,0,0,,这真的没有必要\nDialogue: 0,0:37:03.86,0:37:06.55,Default,,0,0,0,,你们也发现了 我在可视化这个过程时也犯了迷糊\nDialogue: 0,0:37:06.81,0:37:08.25,Default,,0,0,0,,你们也看到了复杂程度\nDialogue: 0,0:37:08.55,0:37:10.76,Default,,0,0,0,,而且这种复杂还很难描述\nDialogue: 0,0:37:10.76,0:37:11.82,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:37:12.39,0:37:13.29,Default,,0,0,0,,这是因为\nDialogue: 0,0:37:13.53,0:37:17.39,Default,,0,0,0,,这是因为这程序过分地关注于时间了\nDialogue: 0,0:37:18.58,0:37:20.43,Default,,0,0,0,,这之中太多 -- 先试试这个 再试试这个\nDialogue: 0,0:37:20.49,0:37:22.38,Default,,0,0,0,,再回到上一个可行的地方 -- 这种操作太多了\nDialogue: 0,0:37:22.89,0:37:24.34,Default,,0,0,0,,这很复杂\nDialogue: 0,0:37:24.34,0:37:26.36,Default,,0,0,0,,如果我们不再如此关注时间\nDialogue: 0,0:37:28.04,0:37:29.76,Default,,0,0,0,,就有一个更简单的方式来描述\nDialogue: 0,0:37:31.20,0:37:32.36,Default,,0,0,0,,让我们来想象一下\nDialogue: 0,0:37:33.31,0:37:36.57,Default,,0,0,0,,现在我有\nDialogue: 0,0:37:38.32,0:37:42.16,Default,,0,0,0,,有一个高达K-1层的树\nDialogue: 0,0:37:43.40,0:37:46.32,Default,,0,0,0,,假设我已经有了\nDialogue: 0,0:37:48.09,0:37:52.19,Default,,0,0,0,,把皇后放在前K列的所有解法\nDialogue: 0,0:37:53.56,0:37:54.61,Default,,0,0,0,,假设是这样\nDialogue: 0,0:37:54.61,0:37:55.79,Default,,0,0,0,,不要担心我是怎么得到的\nDialogue: 0,0:37:57.07,0:37:59.20,Default,,0,0,0,,现在 如何扩充下去呢？\nDialogue: 0,0:37:59.20,0:38:02.16,Default,,0,0,0,,怎样找到在下一列中放皇后的所有可行方法？\nDialogue: 0,0:38:02.48,0:38:03.13,Default,,0,0,0,,很简单\nDialogue: 0,0:38:03.62,0:38:06.41,Default,,0,0,0,,对于已有的位置\nDialogue: 0,0:38:07.82,0:38:13.96,Default,,0,0,0,,我考虑把下一个皇后放在每一行上\nDialogue: 0,0:38:15.08,0:38:16.16,Default,,0,0,0,,来构建出下一步的棋局\nDialogue: 0,0:38:16.16,0:38:17.29,Default,,0,0,0,,然后 把所有放置的位置\nDialogue: 0,0:38:17.44,0:38:19.71,Default,,0,0,0,,用SAFE?进行过滤\nDialogue: 0,0:38:21.80,0:38:22.99,Default,,0,0,0,,不像之前那样\nDialogue: 0,0:38:22.99,0:38:24.67,Default,,0,0,0,,把这个树看做是逐步生成的\nDialogue: 0,0:38:24.94,0:38:26.86,Default,,0,0,0,,我们假设所有的东西都生成好了\nDialogue: 0,0:38:29.68,0:38:32.41,Default,,0,0,0,,为了从K-1层扩展到K层\nDialogue: 0,0:38:32.64,0:38:36.24,Default,,0,0,0,,我只需要扩展所有可能的放置方法\nDialogue: 0,0:38:36.48,0:38:37.80,Default,,0,0,0,,最后保留安全的排列\nDialogue: 0,0:38:37.80,0:38:39.23,Default,,0,0,0,,就得到一个K层树的结果\nDialogue: 0,0:38:39.30,0:38:40.67,Default,,0,0,0,,这是解决八皇后问题\nDialogue: 0,0:38:40.89,0:38:42.17,Default,,0,0,0,,的一个递归策略\nDialogue: 0,0:38:44.53,0:38:45.34,Default,,0,0,0,,好的 我们来看看\nDialogue: 0,0:38:50.33,0:38:52.68,Default,,0,0,0,,我们编写子过程FILL-COLS\nDialogue: 0,0:38:53.00,0:38:55.53,Default,,0,0,0,,来解决在一个特定大小棋盘上的\nDialogue: 0,0:38:58.92,0:39:01.03,Default,,0,0,0,,八皇后问题\nDialogue: 0,0:39:01.13,0:39:04.86,Default,,0,0,0,,这个过程会把皇后放置到K个列中\nDialogue: 0,0:39:06.35,0:39:07.70,Default,,0,0,0,,这是递归的模式\nDialogue: 0,0:39:07.70,0:39:10.92,Default,,0,0,0,,最后会以棋盘的大小为参数 调用FILL-COLS\nDialogue: 0,0:39:12.99,0:39:15.28,Default,,0,0,0,,FILL-COLS是用来说明\nDialogue: 0,0:39:15.29,0:39:17.16,Default,,0,0,0,,如何安全地把皇后放置在\nDialogue: 0,0:39:17.20,0:39:19.58,Default,,0,0,0,,具有SIZE行的棋盘的前K列\nDialogue: 0,0:39:20.36,0:39:21.64,Default,,0,0,0,,如果K是0\nDialogue: 0,0:39:22.27,0:39:23.60,Default,,0,0,0,,就不用做什么\nDialogue: 0,0:39:23.94,0:39:25.93,Default,,0,0,0,,结果是一个空棋盘\nDialogue: 0,0:39:26.71,0:39:28.07,Default,,0,0,0,,否则就做点别的\nDialogue: 0,0:39:28.35,0:39:29.44,Default,,0,0,0,,这里将要使用COLLECT\nDialogue: 0,0:39:30.81,0:39:31.77,Default,,0,0,0,,完整的代码在这里\nDialogue: 0,0:39:34.33,0:39:41.91,Default,,0,0,0,,我找到了所有在前K-1列中放皇后的方法\nDialogue: 0,0:39:42.19,0:39:43.32,Default,,0,0,0,,这是我所假设的\nDialogue: 0,0:39:43.32,0:39:46.36,Default,,0,0,0,,想像这棵树下降到K-1层\nDialogue: 0,0:39:48.88,0:39:52.11,Default,,0,0,0,,然后我尝试每一行\nDialogue: 0,0:39:52.52,0:39:54.13,Default,,0,0,0,,尝试每一个可行的行\nDialogue: 0,0:39:54.13,0:39:55.04,Default,,0,0,0,,总共SIZE行\nDialogue: 0,0:39:55.31,0:39:56.49,Default,,0,0,0,,这里枚举了所有行数\nDialogue: 0,0:39:58.04,0:39:59.79,Default,,0,0,0,,现在要做的是\nDialogue: 0,0:40:03.15,0:40:05.82,Default,,0,0,0,,把我将要尝试的新行和第K列\nDialogue: 0,0:40:07.95,0:40:08.95,Default,,0,0,0,,收集起来\nDialogue: 0,0:40:08.95,0:40:10.09,Default,,0,0,0,,我邻接一个位置\nDialogue: 0,0:40:10.20,0:40:11.29,Default,,0,0,0,,这是George的问题了\nDialogue: 0,0:40:11.29,0:40:12.75,Default,,0,0,0,,实现ADJOIN-POSITION和SAFE?都是George的工作\nDialogue: 0,0:40:13.64,0:40:15.28,Default,,0,0,0,,这个过程需要的参数有\nDialogue: 0,0:40:15.50,0:40:17.04,Default,,0,0,0,,ROW、COL以及REST-OF-POS\nDialogue: 0,0:40:17.07,0:40:19.02,Default,,0,0,0,,然后返回位置的集合\nDialogue: 0,0:40:19.66,0:40:25.77,Default,,0,0,0,,我把新的行和列\nDialogue: 0,0:40:26.06,0:40:27.68,Default,,0,0,0,,和剩下的皇后邻接起来\nDialogue: 0,0:40:28.57,0:40:29.76,Default,,0,0,0,,那些剩下的皇后\nDialogue: 0,0:40:29.92,0:40:31.45,Default,,0,0,0,,会尝试所有的\nDialogue: 0,0:40:31.87,0:40:34.16,Default,,0,0,0,,放置在K-1列中的可行解\nDialogue: 0,0:40:34.62,0:40:37.04,Default,,0,0,0,,新的行遍历了所有的可能性\nDialogue: 0,0:40:37.85,0:40:40.76,Default,,0,0,0,,过滤出安全的位置\nDialogue: 0,0:40:43.24,0:40:44.70,Default,,0,0,0,,这就是整个程序了\nDialogue: 0,0:40:46.33,0:40:47.31,Default,,0,0,0,,整个过程\nDialogue: 0,0:40:49.84,0:40:52.43,Default,,0,0,0,,它不仅找到了八皇后的问题的解\nDialogue: 0,0:40:53.42,0:40:56.68,Default,,0,0,0,,它还给出了所有的解\nDialogue: 0,0:40:56.68,0:40:58.48,Default,,0,0,0,,运行结束之后 就得到一个流\nDialogue: 0,0:40:58.48,0:41:01.90,Default,,0,0,0,,流中的元素是所有的解\nDialogue: 0,0:41:05.31,0:41:06.26,Default,,0,0,0,,为什么这个更简单一点呢？\nDialogue: 0,0:41:06.26,0:41:08.54,Default,,0,0,0,,我们完全没有把这个当做\nDialogue: 0,0:41:08.88,0:41:11.52,Default,,0,0,0,,按时间发生的、具有状态的过程\nDialogue: 0,0:41:12.72,0:41:14.42,Default,,0,0,0,,我们只说 这是一些东西的集合\nDialogue: 0,0:41:14.94,0:41:16.00,Default,,0,0,0,,这是它更加简单的原因\nDialogue: 0,0:41:18.00,0:41:20.11,Default,,0,0,0,,我们已经转变了观念\nDialogue: 0,0:41:20.11,0:41:22.59,Default,,0,0,0,,还记得吗 这节课开始我们就讲过\nDialogue: 0,0:41:22.82,0:41:26.23,Default,,0,0,0,,我们转变了建模的观念\nDialogue: 0,0:41:26.23,0:41:29.20,Default,,0,0,0,,我们不再把事物看做按时间演进\nDialogue: 0,0:41:29.37,0:41:31.31,Default,,0,0,0,,也不再具有不同的阶段与状态\nDialogue: 0,0:41:31.75,0:41:33.79,Default,,0,0,0,,取而代之的是 我们对全局进行建模\nDialogue: 0,0:41:33.80,0:41:35.93,Default,,0,0,0,,我们关注粉笔的整个飞行过程\nDialogue: 0,0:41:36.28,0:41:38.88,Default,,0,0,0,,而不是专注于每个瞬时状态\nDialogue: 0,0:41:40.75,0:41:41.44,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:41:44.08,0:41:46.20,Default,,0,0,0,,学生：在我看来回溯会\nDialogue: 0,0:41:46.22,0:41:48.96,Default,,0,0,0,,搜索到它所能找到的第一个解\nDialogue: 0,0:41:49.31,0:41:51.48,Default,,0,0,0,,而这个递归搜索\nDialogue: 0,0:41:51.48,0:41:53.26,Default,,0,0,0,,会去寻找所有的解\nDialogue: 0,0:41:53.32,0:41:53.60,Default,,0,0,0,,教授：是这样的\nDialogue: 0,0:41:54.03,0:41:55.26,Default,,0,0,0,,学生：但问题是\nDialogue: 0,0:41:55.26,0:41:57.92,Default,,0,0,0,,如果需要搜索的空间足够的大\nDialogue: 0,0:41:57.92,0:42:00.92,Default,,0,0,0,,第二种搜索方式就会变得不现实\nDialogue: 0,0:42:01.36,0:42:05.93,Default,,0,0,0,,教授：呃 这个问题其实是\nDialogue: 0,0:42:07.13,0:42:08.44,Default,,0,0,0,,这一节课剩下的内容\nDialogue: 0,0:42:08.57,0:42:10.54,Default,,0,0,0,,这个问题很好\nDialogue: 0,0:42:13.87,0:42:15.74,Default,,0,0,0,,先不要尝试去预知后面的课\nDialogue: 0,0:42:15.96,0:42:19.23,Default,,0,0,0,,只是在现在 你们要保持谨慎\nDialogue: 0,0:42:19.84,0:42:21.84,Default,,0,0,0,,这里确实有点奇怪 难道不是么？\nDialogue: 0,0:42:22.22,0:42:24.51,Default,,0,0,0,,尽管这个看起来不错 但是难道它不低效吗？\nDialogue: 0,0:42:24.83,0:42:26.03,Default,,0,0,0,,这是我们待会儿要解决的问题\nDialogue: 0,0:42:28.10,0:42:30.02,Default,,0,0,0,,就让我们稍后来揭晓秘密吧\nDialogue: 0,0:42:33.35,0:42:34.60,Default,,0,0,0,,好吧 休息一下\nDialogue: 0,0:42:34.60,0:42:44.51,Default,,0,0,0,,[音乐]\nDialogue: 0,0:42:44.51,0:42:49.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:43:10.57,0:43:17.05,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:43:17.05,0:43:21.21,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:43:21.21,0:43:25.21,Declare,,0,0,0,,{\\an2\\fad(500,500)} I\nDialogue: 0,0:43:29.65,0:43:33.76,Default,,0,0,0,,你可能现在开始怀疑了\nDialogue: 0,0:43:35.60,0:43:39.26,Default,,0,0,0,,我已经展示了这种简单而优雅的\nDialogue: 0,0:43:40.51,0:43:42.28,Default,,0,0,0,,组合程序的方法\nDialogue: 0,0:43:42.86,0:43:46.91,Default,,0,0,0,,这跟那些传统程序非常不同\nDialogue: 0,0:43:46.92,0:43:48.19,Default,,0,0,0,,那些求奇数的平方和\nDialogue: 0,0:43:48.72,0:43:51.32,Default,,0,0,0,,或者求奇数项斐波那契数之类的程序\nDialogue: 0,0:43:53.74,0:43:55.48,Default,,0,0,0,,也不像那些混合了\nDialogue: 0,0:43:55.85,0:43:58.84,Default,,0,0,0,,枚举函数、过滤函数和累积函数的程序\nDialogue: 0,0:44:00.44,0:44:01.82,Default,,0,0,0,,通过把它们混合起来\nDialogue: 0,0:44:02.20,0:44:04.59,Default,,0,0,0,,通过这种混搭式的\nDialogue: 0,0:44:04.62,0:44:07.34,Default,,0,0,0,,组合程序的方法\nDialogue: 0,0:44:07.82,0:44:09.53,Default,,0,0,0,,我们并没有获得\nDialogue: 0,0:44:09.55,0:44:11.77,Default,,0,0,0,,流式程序设计的理论优势\nDialogue: 0,0:44:13.80,0:44:14.25,Default,,0,0,0,,另一方面\nDialogue: 0,0:44:14.28,0:44:16.88,Default,,0,0,0,,你们所见过的大多数程序是那种丑陋的风格\nDialogue: 0,0:44:18.34,0:44:18.94,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:44:19.20,0:44:20.59,Default,,0,0,0,,难道计算机科学家们\nDialogue: 0,0:44:21.16,0:44:24.30,Default,,0,0,0,,愚蠢得无以复加\nDialogue: 0,0:44:25.42,0:44:26.44,Default,,0,0,0,,以至于他们没有注意到这个现象么？\nDialogue: 0,0:44:27.07,0:44:28.75,Default,,0,0,0,,如果你仅仅只是做了这些事\nDialogue: 0,0:44:29.63,0:44:31.93,Default,,0,0,0,,你就能让程序变得极其优雅么？\nDialogue: 0,0:44:33.62,0:44:34.78,Default,,0,0,0,,肯定有什么缺陷\nDialogue: 0,0:44:36.76,0:44:39.05,Default,,0,0,0,,事实上这一缺陷也很容易发现\nDialogue: 0,0:44:39.51,0:44:41.74,Default,,0,0,0,,我们来看看接下来的这个问题\nDialogue: 0,0:44:42.03,0:44:45.47,Default,,0,0,0,,假设我让你去找\nDialogue: 0,0:44:46.16,0:44:48.16,Default,,0,0,0,,1,000到1,000,000之间的第二个素数\nDialogue: 0,0:44:49.12,0:44:50.56,Default,,0,0,0,,如果你的计算机性能更强劲的话\nDialogue: 0,0:44:50.59,0:44:53.05,Default,,0,0,0,,或者可以去找10,000到100,000,000之间的\nDialogue: 0,0:44:54.32,0:44:55.45,Default,,0,0,0,,你可能觉得这很容易\nDialogue: 0,0:44:55.47,0:44:56.65,Default,,0,0,0,,我可以用流来解决\nDialogue: 0,0:44:57.08,0:44:59.87,Default,,0,0,0,,我需要做的就是\nDialogue: 0,0:45:00.57,0:45:02.89,Default,,0,0,0,,从10,000枚举到1,000,000\nDialogue: 0,0:45:04.16,0:45:06.51,Default,,0,0,0,,我就获得了从10,000到1,000,000的所有整数\nDialogue: 0,0:45:06.80,0:45:08.64,Default,,0,0,0,,我过滤出所有的质数\nDialogue: 0,0:45:09.39,0:45:11.10,Default,,0,0,0,,也就是对这些数做素性检测\nDialogue: 0,0:45:11.76,0:45:12.83,Default,,0,0,0,,然后从中取出第二个元素\nDialogue: 0,0:45:12.84,0:45:14.04,Default,,0,0,0,,也就是 TAIL的HEAD部分\nDialogue: 0,0:45:15.79,0:45:17.38,Default,,0,0,0,,这显然是非常荒谬的\nDialogue: 0,0:45:21.66,0:45:23.20,Default,,0,0,0,,我们的机器没有这么大的空间\nDialogue: 0,0:45:23.58,0:45:25.24,Default,,0,0,0,,来存放这些整数\nDialogue: 0,0:45:25.28,0:45:26.35,Default,,0,0,0,,更别说来测试它们了\nDialogue: 0,0:45:27.04,0:45:28.64,Default,,0,0,0,,而且我也只是取第二个数而已\nDialogue: 0,0:45:29.81,0:45:34.94,Default,,0,0,0,,这种传统程序设计风格的威力\nDialogue: 0,0:45:36.43,0:45:37.68,Default,,0,0,0,,（虽然）也正是其弱点\nDialogue: 0,0:45:37.96,0:45:38.94,Default,,0,0,0,,这种程序设计风格\nDialogue: 0,0:45:39.61,0:45:43.50,Default,,0,0,0,,混合了枚举、测试以及累积\nDialogue: 0,0:45:44.88,0:45:46.46,Default,,0,0,0,,我们不需要做全部的事\nDialogue: 0,0:45:46.67,0:45:49.18,Default,,0,0,0,,所以说 实际上这是这种\nDialogue: 0,0:45:49.45,0:45:51.74,Default,,0,0,0,,概念上丑陋的风格\nDialogue: 0,0:45:52.20,0:45:53.80,Default,,0,0,0,,正是让它运行起来高效\nDialogue: 0,0:45:54.91,0:45:55.84,Default,,0,0,0,,就是像这样来混合\nDialogue: 0,0:45:57.80,0:45:59.34,Default,,0,0,0,,我今天一早上所做的好像都是在\nDialogue: 0,0:45:59.34,0:46:00.42,Default,,0,0,0,,把你们搞糊涂一样\nDialogue: 0,0:46:00.42,0:46:03.10,Default,,0,0,0,,我为你们展示了一种貌似可行的优雅程序设计方法\nDialogue: 0,0:46:03.10,0:46:03.96,Default,,0,0,0,,但它却不可行\nDialogue: 0,0:46:05.84,0:46:08.32,Default,,0,0,0,,但是 接下来就是见证奇迹的时刻\nDialogue: 0,0:46:09.04,0:46:10.57,Default,,0,0,0,,结果却是 这个游戏里\nDialogue: 0,0:46:11.21,0:46:13.84,Default,,0,0,0,,我们真的可以得到蛋糕并吃掉它\nDialogue: 0,0:46:14.87,0:46:16.11,Default,,0,0,0,,我的意思是\nDialogue: 0,0:46:18.09,0:46:21.15,Default,,0,0,0,,我们完全可以用流来组织程序\nDialogue: 0,0:46:21.16,0:46:22.48,Default,,0,0,0,,就像我之前编写的那样\nDialogue: 0,0:46:23.55,0:46:27.74,Default,,0,0,0,,以至于当机器真正运行的时候\nDialogue: 0,0:46:28.33,0:46:31.52,Default,,0,0,0,,它可以和传统风格的程序一样高效\nDialogue: 0,0:46:31.71,0:46:34.28,Default,,0,0,0,,那些混合了生成与测试的程序\nDialogue: 0,0:46:36.16,0:46:38.80,Default,,0,0,0,,听起来不可思议\nDialogue: 0,0:46:40.77,0:46:41.82,Default,,0,0,0,,关键在就于\nDialogue: 0,0:46:42.00,0:46:43.69,Default,,0,0,0,,流不是表\nDialogue: 0,0:46:48.09,0:46:49.79,Default,,0,0,0,,一会儿我们就会看到 但是现在\nDialogue: 0,0:46:49.80,0:46:51.77,Default,,0,0,0,,先让我们来看看幻灯片\nDialogue: 0,0:46:52.24,0:46:53.80,Default,,0,0,0,,你们对这个\nDialogue: 0,0:46:53.84,0:46:55.58,Default,,0,0,0,,信号处理系统的印象是\nDialogue: 0,0:46:57.26,0:46:58.72,Default,,0,0,0,,你们认为要发生的是\nDialogue: 0,0:46:59.13,0:47:00.92,Default,,0,0,0,,在这类盒子中\nDialogue: 0,0:47:01.18,0:47:03.58,Default,,0,0,0,,事先产生好了整数\nDialogue: 0,0:47:05.36,0:47:06.40,Default,,0,0,0,,这里有个过滤函数\nDialogue: 0,0:47:07.45,0:47:09.37,Default,,0,0,0,,它和那个盒子相连 并从中拉取东西\nDialogue: 0,0:47:10.94,0:47:13.15,Default,,0,0,0,,这里还有人从这整个系统中\nDialogue: 0,0:47:13.31,0:47:14.91,Default,,0,0,0,,拉取东西\nDialogue: 0,0:47:16.79,0:47:18.70,Default,,0,0,0,,你们应该这么来理解：\nDialogue: 0,0:47:18.99,0:47:20.72,Default,,0,0,0,,有人想要得到第一个质数\nDialogue: 0,0:47:22.67,0:47:24.14,Default,,0,0,0,,他从这个过滤函数这儿拉取\nDialogue: 0,0:47:24.59,0:47:26.12,Default,,0,0,0,,FILTER从枚举函数中去拉取\nDialogue: 0,0:47:28.02,0:47:29.15,Default,,0,0,0,,你只需要在固定范围内寻找\nDialogue: 0,0:47:29.16,0:47:30.93,Default,,0,0,0,,然后从里面取出第二个数\nDialogue: 0,0:47:30.93,0:47:31.95,Default,,0,0,0,,第二个质数是多少？\nDialogue: 0,0:47:33.71,0:47:35.37,Default,,0,0,0,,没有额外的计算\nDialogue: 0,0:47:35.37,0:47:36.64,Default,,0,0,0,,只要你不去拉取东西\nDialogue: 0,0:47:36.64,0:47:38.32,Default,,0,0,0,,就不会产生进行额外计算\nDialogue: 0,0:47:40.50,0:47:41.41,Default,,0,0,0,,我来用实物演示一下\nDialogue: 0,0:47:41.41,0:47:43.88,Default,,0,0,0,,这个小设备\nDialogue: 0,0:47:43.90,0:47:44.97,Default,,0,0,0,,这是个小型的流机器\nDialogue: 0,0:47:45.50,0:47:46.83,Default,,0,0,0,,这是Eric Grimson发明的\nDialogue: 0,0:47:47.60,0:47:49.24,Default,,0,0,0,,他也在MIT教这门课\nDialogue: 0,0:47:49.83,0:47:52.51,Default,,0,0,0,,实际的流程是 -- 这里有某种流\nDialogue: 0,0:47:52.54,0:47:53.82,Default,,0,0,0,,就像一串整数一样\nDialogue: 0,0:47:54.78,0:47:56.33,Default,,0,0,0,,这些是一些处理单元\nDialogue: 0,0:47:58.70,0:48:02.60,Default,,0,0,0,,就像是FILTER、MAP之类的东西\nDialogue: 0,0:48:03.98,0:48:09.18,Default,,0,0,0,,如果我把流实现为表 来进行处理\nDialogue: 0,0:48:09.24,0:48:11.26,Default,,0,0,0,,我拥有的是一个表\nDialogue: 0,0:48:11.47,0:48:12.67,Default,,0,0,0,,现在 我先执行第一个过滤函数\nDialogue: 0,0:48:12.67,0:48:14.07,Default,,0,0,0,,我像这样完全处理\nDialogue: 0,0:48:14.88,0:48:15.77,Default,,0,0,0,,针对这个流\nDialogue: 0,0:48:16.32,0:48:19.21,Default,,0,0,0,,不断地处理、处理、处理、处理\nDialogue: 0,0:48:19.61,0:48:21.05,Default,,0,0,0,,然后得到一个新的流\nDialogue: 0,0:48:21.63,0:48:24.07,Default,,0,0,0,,现在 我把得到的结果拿在我手中\nDialogue: 0,0:48:24.07,0:48:25.26,Default,,0,0,0,,然后把它放进第二个\nDialogue: 0,0:48:25.56,0:48:26.94,Default,,0,0,0,,又处理了全部的流\nDialogue: 0,0:48:28.27,0:48:29.51,Default,,0,0,0,,得到一个新流\nDialogue: 0,0:48:32.13,0:48:33.36,Default,,0,0,0,,然后我再把结果\nDialogue: 0,0:48:34.28,0:48:36.36,Default,,0,0,0,,用相同的方式再次处理\nDialogue: 0,0:48:36.36,0:48:40.99,Default,,0,0,0,,如果仅仅把流当做表的话\nDialogue: 0,0:48:41.69,0:48:42.97,Default,,0,0,0,,计算的过程就是这样的\nDialogue: 0,0:48:43.86,0:48:45.64,Default,,0,0,0,,但是事实上 流不是表 流就是流\nDialogue: 0,0:48:45.82,0:48:48.11,Default,,0,0,0,,而你们应该这样来想像\nDialogue: 0,0:48:50.23,0:48:52.52,Default,,0,0,0,,我把这些小玩意连接起来\nDialogue: 0,0:48:55.26,0:48:56.76,Default,,0,0,0,,数据在其中流动\nDialogue: 0,0:49:00.33,0:49:02.30,Default,,0,0,0,,这里是流的源头\nDialogue: 0,0:49:02.32,0:49:02.92,Default,,0,0,0,,它可能在\nDialogue: 0,0:49:04.19,0:49:05.72,Default,,0,0,0,,产生一些整数\nDialogue: 0,0:49:05.98,0:49:07.39,Default,,0,0,0,,如果我想要拉取一个结果 会发生什么？\nDialogue: 0,0:49:07.58,0:49:08.91,Default,,0,0,0,,我从尾部这里拉取\nDialogue: 0,0:49:10.20,0:49:11.07,Default,,0,0,0,,而这个单元会说\nDialogue: 0,0:49:11.08,0:49:12.20,Default,,0,0,0,,我需要更多的数据\nDialogue: 0,0:49:13.09,0:49:15.52,Default,,0,0,0,,所以 它就到这个单元去拉取数据\nDialogue: 0,0:49:15.83,0:49:17.39,Default,,0,0,0,,它说：“我需要更多的数据”\nDialogue: 0,0:49:17.89,0:49:19.56,Default,,0,0,0,,然后这个又从下一个单元拉取\nDialogue: 0,0:49:19.56,0:49:20.28,Default,,0,0,0,,可能是一个过滤函数\nDialogue: 0,0:49:20.28,0:49:21.40,Default,,0,0,0,,从它那里取得更多数据\nDialogue: 0,0:49:21.64,0:49:23.15,Default,,0,0,0,,我在这一端拉取数据时\nDialogue: 0,0:49:23.53,0:49:25.56,Default,,0,0,0,,只会生成这么多的数据\nDialogue: 0,0:49:25.78,0:49:28.30,Default,,0,0,0,,我在另一端请求一定量的数据时\nDialogue: 0,0:49:28.56,0:49:29.98,Default,,0,0,0,,只有相当数量的数据被生成并处理\nDialogue: 0,0:49:30.76,0:49:32.09,Default,,0,0,0,,这就是你们需要知道的\nDialogue: 0,0:49:32.80,0:49:34.38,Default,,0,0,0,,把流实现为表\nDialogue: 0,0:49:34.56,0:49:35.92,Default,,0,0,0,,和流真实的工作方式\nDialogue: 0,0:49:36.16,0:49:37.50,Default,,0,0,0,,的区别\nDialogue: 0,0:49:40.78,0:49:42.14,Default,,0,0,0,,那么 到底怎么来实现呢？\nDialogue: 0,0:49:42.35,0:49:43.32,Default,,0,0,0,,知道了流的真实工作方式\nDialogue: 0,0:49:43.40,0:49:44.52,Default,,0,0,0,,构造流有什么窍门呢？\nDialogue: 0,0:49:47.93,0:49:50.32,Default,,0,0,0,,我们想要把流组织成\nDialogue: 0,0:49:50.41,0:49:51.58,Default,,0,0,0,,一种数据结构\nDialogue: 0,0:49:52.00,0:49:54.22,Default,,0,0,0,,它能够增量式地计算自己\nDialogue: 0,0:49:54.22,0:49:56.22,Default,,0,0,0,,一种“按需”数据结构\nDialogue: 0,0:49:58.96,0:50:00.51,Default,,0,0,0,,基本思想在于\nDialogue: 0,0:50:00.97,0:50:02.70,Default,,0,0,0,,再次强调 这是贯穿整个课程的\nDialogue: 0,0:50:02.72,0:50:04.12,Default,,0,0,0,,几大基本思想之一\nDialogue: 0,0:50:04.49,0:50:05.00,Default,,0,0,0,,这就是\nDialogue: 0,0:50:05.52,0:50:06.97,Default,,0,0,0,,数据与过程之间\nDialogue: 0,0:50:06.99,0:50:08.44,Default,,0,0,0,,并没有绝对的界限\nDialogue: 0,0:50:09.24,0:50:10.54,Default,,0,0,0,,流会是这样的一种结构\nDialogue: 0,0:50:10.59,0:50:13.40,Default,,0,0,0,,它既是一种传统意义上的“数据结构”\nDialogue: 0,0:50:13.45,0:50:15.92,Default,,0,0,0,,比如树的叶子结点组成的流\nDialogue: 0,0:50:16.86,0:50:17.85,Default,,0,0,0,,但是同时\nDialogue: 0,0:50:17.85,0:50:19.32,Default,,0,0,0,,它又是一种非常聪明的过程\nDialogue: 0,0:50:20.24,0:50:22.22,Default,,0,0,0,,它包含了如何计算的方法\nDialogue: 0,0:50:23.74,0:50:25.93,Default,,0,0,0,,好吧 实际来看一下\nDialogue: 0,0:50:25.93,0:50:26.62,Default,,0,0,0,,事实上\nDialogue: 0,0:50:26.80,0:50:28.33,Default,,0,0,0,,我们不需要其它的机制\nDialogue: 0,0:50:28.46,0:50:29.87,Default,,0,0,0,,我们已经有了所需要的一切东西\nDialogue: 0,0:50:30.14,0:50:30.99,Default,,0,0,0,,这是因为\nDialogue: 0,0:50:31.02,0:50:33.93,Default,,0,0,0,,我们已经能够 把过程当作第一级对象来处理了\nDialogue: 0,0:50:35.46,0:50:36.88,Default,,0,0,0,,来看看这个关键之处\nDialogue: 0,0:50:36.88,0:50:39.03,Default,,0,0,0,,关键在于 -- 回想一下 我们有这些运算\nDialogue: 0,0:50:39.03,0:50:47.52,Default,,0,0,0,,CONS-STREAM、HEAD和TAIL\nDialogue: 0,0:50:48.08,0:50:49.36,Default,,0,0,0,,刚开始的时候我说\nDialogue: 0,0:50:49.92,0:50:51.36,Default,,0,0,0,,你们可以把这个看作CONS\nDialogue: 0,0:50:51.40,0:50:52.62,Default,,0,0,0,,把HEAD看作CAR\nDialogue: 0,0:50:52.62,0:50:53.52,Default,,0,0,0,,把TAIL看作CDR\nDialogue: 0,0:50:53.55,0:50:54.16,Default,,0,0,0,,事实上没这么简单\nDialogue: 0,0:50:55.08,0:50:56.32,Default,,0,0,0,,现在 来看看它们到底是什么\nDialogue: 0,0:50:57.71,0:51:05.84,Default,,0,0,0,,(CONS-STREAM X Y)\nDialogue: 0,0:51:07.48,0:51:17.79,Default,,0,0,0,,是这个东西的缩写形式\nDialogue: 0,0:51:19.54,0:51:28.32,Default,,0,0,0,,(CONS X (DELAY Y))\nDialogue: 0,0:51:31.68,0:51:33.53,Default,,0,0,0,,我先把它们写完再来解释\nDialogue: 0,0:51:34.52,0:51:35.53,Default,,0,0,0,,而(HEAD S)\nDialogue: 0,0:51:38.09,0:51:39.79,Default,,0,0,0,,就是 (CAR S)\nDialogue: 0,0:51:42.38,0:51:44.25,Default,,0,0,0,,而(TAIL S)\nDialogue: 0,0:51:46.68,0:51:54.60,Default,,0,0,0,,则是(FORCE (CDR S))\nDialogue: 0,0:51:56.12,0:51:57.04,Default,,0,0,0,,我来解释一下\nDialogue: 0,0:51:58.06,0:51:59.88,Default,,0,0,0,,DELAY是一个特殊而神奇的东西\nDialogue: 0,0:52:01.42,0:52:02.33,Default,,0,0,0,,DELAY所做是\nDialogue: 0,0:52:03.85,0:52:05.31,Default,,0,0,0,,取一个表达式\nDialogue: 0,0:52:05.50,0:52:06.86,Default,,0,0,0,,然后产生一个PROMISE\nDialogue: 0,0:52:07.12,0:52:09.15,Default,,0,0,0,,在你有需要时 这个PROMISE会计算那个表达式\nDialogue: 0,0:52:10.60,0:52:11.98,Default,,0,0,0,,但在此时没有做任何计算\nDialogue: 0,0:52:11.98,0:52:14.32,Default,,0,0,0,,只是一个延期的PROMISE\nDialogue: 0,0:52:14.82,0:52:16.20,Default,,0,0,0,,承诺要做这样的事\nDialogue: 0,0:52:17.11,0:52:18.20,Default,,0,0,0,,CONS-STREAM所做的就是\nDialogue: 0,0:52:18.81,0:52:21.96,Default,,0,0,0,,把X和一个计算Y的PROMISE\nDialogue: 0,0:52:23.31,0:52:25.36,Default,,0,0,0,,放在在一个序对里\nDialogue: 0,0:52:28.23,0:52:28.99,Default,,0,0,0,,如果我需要头部分\nDialogue: 0,0:52:28.99,0:52:30.75,Default,,0,0,0,,那么就是这个序对的CAR部分\nDialogue: 0,0:52:31.84,0:52:33.71,Default,,0,0,0,,关键在于 它的尾部分\nDialogue: 0,0:52:34.62,0:52:36.65,Default,,0,0,0,,强制会调用该PROMISE\nDialogue: 0,0:52:38.22,0:52:39.88,Default,,0,0,0,,而TAIL会说\nDialogue: 0,0:52:40.03,0:52:41.02,Default,,0,0,0,,好吧 取出该PROMISE\nDialogue: 0,0:52:41.85,0:52:44.52,Default,,0,0,0,,然后调用该PROMISE\nDialogue: 0,0:52:44.56,0:52:46.03,Default,,0,0,0,,这才开始实际的计算\nDialogue: 0,0:52:47.69,0:52:48.72,Default,,0,0,0,,这就是它的实际工作方式\nDialogue: 0,0:52:48.74,0:52:51.55,Default,,0,0,0,,这就是CONS-STREAM、HEAD和TAIL的真正定义\nDialogue: 0,0:52:54.60,0:52:55.57,Default,,0,0,0,,具体演示一下\nDialogue: 0,0:52:55.57,0:52:57.50,Default,,0,0,0,,我们小心翼翼地来审查一遍\nDialogue: 0,0:52:58.76,0:53:00.62,Default,,0,0,0,,现在从计算10,000到1,000,000中的\nDialogue: 0,0:53:01.32,0:53:03.66,Default,,0,0,0,,第二个质数这个实例来看\nDialogue: 0,0:53:05.50,0:53:07.16,Default,,0,0,0,,看看是怎么运行的\nDialogue: 0,0:53:08.65,0:53:12.03,Default,,0,0,0,,好的 我们从这个表达式开始\nDialogue: 0,0:53:15.36,0:53:16.62,Default,,0,0,0,,第二个质数就是\nDialogue: 0,0:53:16.64,0:53:21.90,Default,,0,0,0,,就是(HEAD (TAIL (FILTER PRIME? ... )))\nDialogue: 0,0:53:22.83,0:53:25.31,Default,,0,0,0,,枚举的范围是(E-I 10000 1000000)\nDialogue: 0,0:53:26.71,0:53:27.61,Default,,0,0,0,,这是什么呢？\nDialogue: 0,0:53:28.40,0:53:29.20,Default,,0,0,0,,那就是\nDialogue: 0,0:53:31.63,0:53:34.17,Default,,0,0,0,,枚举的这个10,000至1,000,000的区间\nDialogue: 0,0:53:35.72,0:53:37.32,Default,,0,0,0,,如果你追踪这个枚举区间\nDialogue: 0,0:53:37.34,0:53:38.78,Default,,0,0,0,,会发现它构造了一个流\nDialogue: 0,0:53:39.92,0:53:41.39,Default,,0,0,0,,CONS-STREAM实际代换过来是\nDialogue: 0,0:53:41.96,0:53:43.61,Default,,0,0,0,,把10,000\nDialogue: 0,0:53:44.51,0:53:48.92,Default,,0,0,0,,和一个计算10,001到1,000,000之间整数的PROMISE结合起来\nDialogue: 0,0:53:54.00,0:53:55.75,Default,,0,0,0,,这也就是上面这个表达式\nDialogue: 0,0:53:55.75,0:53:57.32,Default,,0,0,0,,现在我使用代换模型\nDialogue: 0,0:53:57.64,0:53:59.32,Default,,0,0,0,,我们可以用代换模型的原因是\nDialogue: 0,0:53:59.34,0:54:01.01,Default,,0,0,0,,这里并没有涉及状态和副作用\nDialogue: 0,0:54:03.56,0:54:06.38,Default,,0,0,0,,所以我有10,000\nDialogue: 0,0:54:06.41,0:54:08.27,Default,,0,0,0,,和一个计算剩余整数构成的流\nDialogue: 0,0:54:08.32,0:54:10.49,Default,,0,0,0,,而到现在为止 只有一个整数被枚举了出来\nDialogue: 0,0:54:14.38,0:54:16.96,Default,,0,0,0,,然后过滤函数会对它做素性测试\nDialogue: 0,0:54:19.44,0:54:21.90,Default,,0,0,0,,我们再来仔细看看过滤函数的代码\nDialogue: 0,0:54:22.36,0:54:24.46,Default,,0,0,0,,过滤函数首先测试流的首部分\nDialogue: 0,0:54:25.46,0:54:28.25,Default,,0,0,0,,这里 过滤函数会测试10,000\nDialogue: 0,0:54:30.30,0:54:32.97,Default,,0,0,0,,然后输出：10,000不是质数\nDialogue: 0,0:54:33.50,0:54:35.85,Default,,0,0,0,,因此我只需要\nDialogue: 0,0:54:36.25,0:54:37.39,Default,,0,0,0,,递归地过滤尾部分\nDialogue: 0,0:54:39.22,0:54:40.14,Default,,0,0,0,,尾部分是什么呢？\nDialogue: 0,0:54:40.16,0:54:43.76,Default,,0,0,0,,就是这个流的尾部分 -- 一个PROMISE\nDialogue: 0,0:54:46.34,0:54:48.06,Default,,0,0,0,,我们进入到尾部分\nDialogue: 0,0:54:48.28,0:54:49.50,Default,,0,0,0,,强制（计算）该PROMISE\nDialogue: 0,0:54:49.68,0:54:50.94,Default,,0,0,0,,我强制计算该PROMISE\nDialogue: 0,0:54:52.30,0:54:54.36,Default,,0,0,0,,这就意味着 我现在要\nDialogue: 0,0:54:55.58,0:54:57.96,Default,,0,0,0,,枚举10,001到1,000,000之间的整数\nDialogue: 0,0:55:00.80,0:55:02.97,Default,,0,0,0,,现在 过滤函数处理的是这个东西\nDialogue: 0,0:55:07.81,0:55:08.92,Default,,0,0,0,,这个枚举函数枚举了它自己\nDialogue: 0,0:55:08.94,0:55:11.23,Default,,0,0,0,,我们又回到了最初那种枚举情况\nDialogue: 0,0:55:11.96,0:55:13.00,Default,,0,0,0,,我们的枚举函数的\nDialogue: 0,0:55:14.12,0:55:16.44,Default,,0,0,0,,首部分是整数10,001\nDialogue: 0,0:55:16.60,0:55:18.20,Default,,0,0,0,,尾部分是计算剩余部分的PROMISE\nDialogue: 0,0:55:19.74,0:55:22.75,Default,,0,0,0,,因此现在素性过滤函数将会测试10,001\nDialogue: 0,0:55:23.23,0:55:25.12,Default,,0,0,0,,开始判断它是不是质数\nDialogue: 0,0:55:25.12,0:55:27.08,Default,,0,0,0,,结果10,001不是质数\nDialogue: 0,0:55:27.55,0:55:29.61,Default,,0,0,0,,然后再不断地强制求值PROMISE\nDialogue: 0,0:55:32.92,0:55:35.80,Default,,0,0,0,,最后 我觉得它找到的第一个质数可能是10,009\nDialogue: 0,0:55:37.10,0:55:38.33,Default,,0,0,0,,它会在这个时候停止\nDialogue: 0,0:55:40.84,0:55:41.93,Default,,0,0,0,,这只是第一个质数\nDialogue: 0,0:55:41.96,0:55:43.48,Default,,0,0,0,,然而 我们需要的是第二个\nDialogue: 0,0:55:45.24,0:55:46.84,Default,,0,0,0,,所以 这时它又启动了\nDialogue: 0,0:55:47.03,0:55:48.25,Default,,0,0,0,,你会发现\nDialogue: 0,0:55:48.52,0:55:50.49,Default,,0,0,0,,你需要多少\nDialogue: 0,0:55:51.85,0:55:52.91,Default,,0,0,0,,它就只会生成多少\nDialogue: 0,0:55:56.48,0:55:59.92,Default,,0,0,0,,枚举函数生成整数的数量\nDialogue: 0,0:56:00.12,0:56:01.45,Default,,0,0,0,,不会比过滤函数所要求的多\nDialogue: 0,0:56:01.47,0:56:03.45,Default,,0,0,0,,因为它只是取一部分数来做素性测试\nDialogue: 0,0:56:04.70,0:56:06.51,Default,,0,0,0,,过滤函数也不会生成\nDialogue: 0,0:56:06.54,0:56:08.04,Default,,0,0,0,,比你的要求更多的东西\nDialogue: 0,0:56:08.06,0:56:09.10,Default,,0,0,0,,也就是尾部分的首部分\nDialogue: 0,0:56:11.61,0:56:13.26,Default,,0,0,0,,你们看\nDialogue: 0,0:56:14.70,0:56:18.24,Default,,0,0,0,,我们把计算机运行中实际进行的\nDialogue: 0,0:56:18.67,0:56:20.65,Default,,0,0,0,,生成与测试的过程 混合在了一起\nDialogue: 0,0:56:21.52,0:56:22.67,Default,,0,0,0,,尽管\nDialogue: 0,0:56:23.18,0:56:25.63,Default,,0,0,0,,我们的程序“看起来”显然不是这样\nDialogue: 0,0:56:28.12,0:56:29.40,Default,,0,0,0,,看起来都很简单\nDialogue: 0,0:56:30.23,0:56:32.67,Default,,0,0,0,,这种机制的神奇之处在于DELAY\nDialogue: 0,0:56:33.68,0:56:35.66,Default,,0,0,0,,所以你也许会说 这全是因为DELAY很强大\nDialogue: 0,0:56:36.90,0:56:38.57,Default,,0,0,0,,但其实并不是\nDialogue: 0,0:56:39.07,0:56:39.98,Default,,0,0,0,,DELAY其实很简单\nDialogue: 0,0:56:40.61,0:56:45.07,Default,,0,0,0,,(DELAY <EXP>)\nDialogue: 0,0:56:48.25,0:56:50.04,Default,,0,0,0,,只是一个缩略表达\nDialogue: 0,0:56:53.36,0:56:55.63,Default,,0,0,0,,它是-- 创建一个用于计算表达式的PROMISE\nDialogue: 0,0:56:56.49,0:57:01.12,Default,,0,0,0,,(LAMBDA () <EXP>) 这样的一个表达式\nDialogue: 0,0:57:02.83,0:57:03.84,Default,,0,0,0,,这就是整个过程\nDialogue: 0,0:57:03.98,0:57:05.53,Default,,0,0,0,,这个PROMISE将要计算表达式<EXP>\nDialogue: 0,0:57:06.05,0:57:06.73,Default,,0,0,0,,FORCE过程又是什么？\nDialogue: 0,0:57:07.34,0:57:10.80,Default,,0,0,0,,如何处理这个PROMISE\nDialogue: 0,0:57:10.80,0:57:14.11,Default,,0,0,0,,FROCE一个PROMISE -- 也就是某个过程\nDialogue: 0,0:57:14.78,0:57:15.40,Default,,0,0,0,,只是简单地运行它\nDialogue: 0,0:57:19.23,0:57:19.56,Default,,0,0,0,,就是这样\nDialogue: 0,0:57:20.24,0:57:21.37,Default,,0,0,0,,所以这里并没有什么魔法\nDialogue: 0,0:57:23.52,0:57:24.24,Default,,0,0,0,,总结一下 我们都干了些什么？\nDialogue: 0,0:57:26.44,0:57:27.50,Default,,0,0,0,,我们说\nDialogue: 0,0:57:28.14,0:57:30.81,Default,,0,0,0,,传统的编程方式更有效\nDialogue: 0,0:57:30.96,0:57:33.92,Default,,0,0,0,,而流程序却更加清晰\nDialogue: 0,0:57:35.50,0:57:38.72,Default,,0,0,0,,我们设法用DELAY\nDialogue: 0,0:57:38.81,0:57:43.23,Default,,0,0,0,,使流程序和其它过程一样高效\nDialogue: 0,0:57:43.35,0:57:46.43,Default,,0,0,0,,DELAY所做的就是把\nDialogue: 0,0:57:46.68,0:57:50.40,Default,,0,0,0,,我们程序中 事件发生的逻辑顺序\nDialogue: 0,0:57:51.21,0:57:53.84,Default,,0,0,0,,和机器中 事件发生的实际顺序 解耦开来\nDialogue: 0,0:57:54.44,0:57:55.93,Default,,0,0,0,,这是DELAY的实质作用\nDialogue: 0,0:57:57.15,0:57:58.29,Default,,0,0,0,,也是全部的重点\nDialogue: 0,0:57:58.29,0:58:01.92,Default,,0,0,0,,我们放弃了那种想法\nDialogue: 0,0:58:02.30,0:58:04.17,Default,,0,0,0,,即程序的运行\nDialogue: 0,0:58:04.67,0:58:05.95,Default,,0,0,0,,或者源码的编排\nDialogue: 0,0:58:06.33,0:58:08.25,Default,,0,0,0,,反映了时间的明确概念\nDialogue: 0,0:58:09.45,0:58:10.57,Default,,0,0,0,,一旦放弃了这种想法\nDialogue: 0,0:58:11.21,0:58:13.32,Default,,0,0,0,,我们能使用DELAY\nDialogue: 0,0:58:13.34,0:58:15.20,Default,,0,0,0,,自由地安排计算顺序\nDialogue: 0,0:58:16.69,0:58:17.61,Default,,0,0,0,,整个思想就是这样\nDialogue: 0,0:58:17.61,0:58:19.45,Default,,0,0,0,,我们解耦了\nDialogue: 0,0:58:19.95,0:58:21.13,Default,,0,0,0,,程序的逻辑顺序\nDialogue: 0,0:58:21.16,0:58:22.89,Default,,0,0,0,,和其实际运行的顺序\nDialogue: 0,0:58:24.09,0:58:25.77,Default,,0,0,0,,对了 还有一个细节\nDialogue: 0,0:58:25.77,0:58:27.21,Default,,0,0,0,,一个技术性的细节\nDialogue: 0,0:58:27.21,0:58:28.43,Default,,0,0,0,,但是也非常重要\nDialogue: 0,0:58:29.73,0:58:32.01,Default,,0,0,0,,当你们运行这些递归程序的时候\nDialogue: 0,0:58:32.16,0:58:33.58,Default,,0,0,0,,你会看到很多像是\nDialogue: 0,0:58:33.64,0:58:37.87,Default,,0,0,0,,(TAIL (TAIL (TAIL ... 这样的东西\nDialogue: 0,0:58:39.20,0:58:41.02,Default,,0,0,0,,如果流是通过嵌套的CONS构造起来的\nDialogue: 0,0:58:41.02,0:58:42.88,Default,,0,0,0,,就会出现这种情况\nDialogue: 0,0:58:43.86,0:58:46.09,Default,,0,0,0,,如果我每次都要执行一次\nDialogue: 0,0:58:46.14,0:58:47.58,Default,,0,0,0,,如果我每次都要计算TAIL\nDialogue: 0,0:58:48.22,0:58:50.88,Default,,0,0,0,,我对一个过程求值\nDialogue: 0,0:58:51.07,0:58:53.07,Default,,0,0,0,,这个过程又将重新计算它的TAIL\nDialogue: 0,0:58:53.10,0:58:55.40,Default,,0,0,0,,它的TAIL又将重新计算TAIL的TAIL\nDialogue: 0,0:58:55.50,0:58:56.88,Default,,0,0,0,,你们可以发现这非常低效\nDialogue: 0,0:58:57.77,0:59:00.56,Default,,0,0,0,,尤其是跟已经存放了所有元素的表相比\nDialogue: 0,0:59:01.16,0:59:04.00,Default,,0,0,0,,因为那样 在取得下一个TAIL的时候不需要重新计算\nDialogue: 0,0:59:05.29,0:59:08.28,Default,,0,0,0,,因此 这里有一个小技巧\nDialogue: 0,0:59:09.66,0:59:13.13,Default,,0,0,0,,通过稍微修改DELAY的定义\nDialogue: 0,0:59:14.96,0:59:18.20,Default,,0,0,0,,就可以让整件事变得 -- 我先写一下\nDialogue: 0,0:59:19.68,0:59:22.04,Default,,0,0,0,,DELAY实际的实现是\nDialogue: 0,0:59:24.52,0:59:27.93,Default,,0,0,0,,(DELAY <exp>)是这样一个表达式的简写\nDialogue: 0,0:59:28.11,0:59:30.86,Default,,0,0,0,,(MEMO-PROC (LAMBDA () <EXP>))\nDialogue: 0,0:59:31.00,0:59:34.06,Default,,0,0,0,,MEMO-PROC是一个可以改变过程的特殊过程\nDialogue: 0,0:59:35.15,0:59:37.80,Default,,0,0,0,,它接受一个无参过程\nDialogue: 0,0:59:39.02,0:59:41.05,Default,,0,0,0,,并把该过程变为\nDialogue: 0,0:59:41.36,0:59:43.55,Default,,0,0,0,,只需要执行一次计算的过程\nDialogue: 0,0:59:45.10,0:59:47.45,Default,,0,0,0,,我们意思是 你给它一个过程\nDialogue: 0,0:59:48.70,0:59:50.86,Default,,0,0,0,,MEMO-PROC返回一个新的过程\nDialogue: 0,0:59:51.39,0:59:53.00,Default,,0,0,0,,当你首次调用这个新过程\nDialogue: 0,0:59:53.71,0:59:55.07,Default,,0,0,0,,它会运行原始过程\nDialogue: 0,0:59:55.31,0:59:56.91,Default,,0,0,0,,并记下结果\nDialogue: 0,0:59:58.56,1:00:00.68,Default,,0,0,0,,从那之后 每次你再运行这个过程\nDialogue: 0,1:00:00.68,1:00:02.17,Default,,0,0,0,,就不用再计算了\nDialogue: 0,1:00:02.19,1:00:04.43,Default,,0,0,0,,它会把结果存储在一个地方\nDialogue: 0,1:00:05.20,1:00:06.92,Default,,0,0,0,,可以这样来实现MEMO-PROC\nDialogue: 0,1:00:11.21,1:00:12.71,Default,,0,0,0,,一旦你了解怎么做 实现就很容易了\nDialogue: 0,1:00:12.71,1:00:16.76,Default,,0,0,0,,MEMO-PROC中有两个标记变量\nDialogue: 0,1:00:17.39,1:00:19.20,Default,,0,0,0,,ALREADY-RUN?用于记录是否运行过\nDialogue: 0,1:00:20.32,1:00:22.48,Default,,0,0,0,,初始值是NIL 指示没运行过\nDialogue: 0,1:00:23.62,1:00:27.04,Default,,0,0,0,,RESULT用于存储上一次计算的结果\nDialogue: 0,1:00:29.07,1:00:31.07,Default,,0,0,0,,MEMO-PROC接收一个过程PROC\nDialogue: 0,1:00:31.56,1:00:34.01,Default,,0,0,0,,返回一个新的无参过程\nDialogue: 0,1:00:34.36,1:00:36.38,Default,,0,0,0,,PROC也是一个无参过程\nDialogue: 0,1:00:38.61,1:00:41.37,Default,,0,0,0,,它会判断 -- 如果没有运行过\nDialogue: 0,1:00:42.59,1:00:44.06,Default,,0,0,0,,就进行一系列的运算\nDialogue: 0,1:00:44.43,1:00:46.56,Default,,0,0,0,,先计算PROC\nDialogue: 0,1:00:47.50,1:00:48.45,Default,,0,0,0,,然后存储它的值\nDialogue: 0,1:00:48.45,1:00:50.48,Default,,0,0,0,,存储在变量RESULT中\nDialogue: 0,1:00:51.14,1:00:53.90,Default,,0,0,0,,然后对ALREADY-RUN?赋值 提醒自己已经运行过了\nDialogue: 0,1:00:54.28,1:00:55.47,Default,,0,0,0,,最后返回RESULT\nDialogue: 0,1:00:56.61,1:00:59.01,Default,,0,0,0,,所以之前如果没运行过 就执行一次计算\nDialogue: 0,1:00:59.01,1:01:01.88,Default,,0,0,0,,当你调用它 但已经运行过了 就直接返回结果\nDialogue: 0,1:01:03.42,1:01:07.12,Default,,0,0,0,,这种聪明的小技巧被称作“记忆化”\nDialogue: 0,1:01:08.40,1:01:09.13,Default,,0,0,0,,这样的话\nDialogue: 0,1:01:10.35,1:01:14.14,Default,,0,0,0,,就不会重复的计算TAIL了\nDialogue: 0,1:01:15.27,1:01:17.81,Default,,0,0,0,,不再那样的没效率了\nDialogue: 0,1:01:17.81,1:01:18.72,Default,,0,0,0,,事实上 流式程序设计\nDialogue: 0,1:01:19.20,1:01:22.75,Default,,0,0,0,,甚至和传统的那种程序一样有效\nDialogue: 0,1:01:24.01,1:01:26.20,Default,,0,0,0,,再强调一下 整个的思想在于\nDialogue: 0,1:01:27.48,1:01:28.60,Default,,0,0,0,,我们已经讲过\nDialogue: 0,1:01:29.26,1:01:32.40,Default,,0,0,0,,过程与数据之间\nDialogue: 0,1:01:32.41,1:01:33.61,Default,,0,0,0,,没有一个明确的分界线\nDialogue: 0,1:01:33.61,1:01:35.61,Default,,0,0,0,,事实上 我们把数据结构组织得\nDialogue: 0,1:01:36.00,1:01:37.31,Default,,0,0,0,,像一个过程\nDialogue: 0,1:01:38.76,1:01:40.73,Default,,0,0,0,,它使得我们能够\nDialogue: 0,1:01:41.58,1:01:46.54,Default,,0,0,0,,可以实现一种常见的控制结构\nDialogue: 0,1:01:46.68,1:01:48.91,Default,,0,0,0,,在本例中是迭代\nDialogue: 0,1:01:49.62,1:01:51.05,Default,,0,0,0,,我们创建了一种数据结构\nDialogue: 0,1:01:51.32,1:01:52.84,Default,,0,0,0,,由于这种数据结构本身是一个过程\nDialogue: 0,1:01:52.86,1:01:55.12,Default,,0,0,0,,它其中就可以有某种控制结构\nDialogue: 0,1:01:55.79,1:01:57.13,Default,,0,0,0,,这就是流的实质\nDialogue: 0,1:01:58.91,1:01:59.76,Default,,0,0,0,,好 大家有什么问题吗？\nDialogue: 0,1:02:03.95,1:02:05.84,Default,,0,0,0,,学生：你刚才说(TAIL (TAIL (TAIL ...\nDialogue: 0,1:02:05.85,1:02:07.16,Default,,0,0,0,,如果我没理解错的话\nDialogue: 0,1:02:07.28,1:02:10.76,Default,,0,0,0,,没有没有MEMO-PROC的话\nDialogue: 0,1:02:10.78,1:02:12.83,Default,,0,0,0,,FORCE实际上执行了一个过程\nDialogue: 0,1:02:12.89,1:02:13.15,Default,,0,0,0,,教授：是的\nDialogue: 0,1:02:13.44,1:02:16.38,Default,,0,0,0,,学生：你说使用那个MEMO-PROC就不会有那样的问题\nDialogue: 0,1:02:16.38,1:02:18.73,Default,,0,0,0,,这难道不需要保证\nDialogue: 0,1:02:19.34,1:02:22.19,Default,,0,0,0,,(TAIL (TAIL (TAIL 每次的计算结构都是一致的么？\nDialogue: 0,1:02:22.41,1:02:23.91,Default,,0,0,0,,教授：哦 当然\nDialogue: 0,1:02:23.91,1:02:25.84,Default,,0,0,0,,学生：我可能是漏了什么知识点\nDialogue: 0,1:02:26.05,1:02:27.21,Default,,0,0,0,,教授：你说得很对 这里 --\nDialogue: 0,1:02:31.12,1:02:33.64,Default,,0,0,0,,首先 为了获得结果需要进行一次计算\nDialogue: 0,1:02:34.09,1:02:36.76,Default,,0,0,0,,关键在于 一旦得到 (TAIL STREAM)\nDialogue: 0,1:02:37.58,1:02:38.70,Default,,0,0,0,,再计算 (TAIL (TAIL STREAM)) 的时候\nDialogue: 0,1:02:38.70,1:02:40.51,Default,,0,0,0,,就不用再计算最内部的TAIL了\nDialogue: 0,1:02:42.98,1:02:44.32,Default,,0,0,0,,明白了吧 如果我没有用MEMO-PROC\nDialogue: 0,1:02:44.35,1:02:46.09,Default,,0,0,0,,还要再计算一遍 (TAIL STREAM)\nDialogue: 0,1:02:46.46,1:02:47.13,Default,,0,0,0,,学生：明白了\nDialogue: 0,1:02:50.83,1:02:52.56,Default,,0,0,0,,学生：之前的例子中你提到过\nDialogue: 0,1:02:52.60,1:02:54.22,Default,,0,0,0,,我们之所以可以使用代换模型\nDialogue: 0,1:02:54.22,1:02:56.11,Default,,0,0,0,,是因为这里没有副作用\nDialogue: 0,1:02:56.83,1:03:00.73,Default,,0,0,0,,如果我们的信号处理单元\nDialogue: 0,1:03:00.78,1:03:02.03,Default,,0,0,0,,具有副作用\nDialogue: 0,1:03:02.04,1:03:03.04,Default,,0,0,0,,具有内部状态\nDialogue: 0,1:03:03.62,1:03:06.84,Default,,0,0,0,,我们还有效地构建流模型么？\nDialogue: 0,1:03:08.46,1:03:10.59,Default,,0,0,0,,教授：可能吧 这是一个很困难的问题\nDialogue: 0,1:03:11.20,1:03:13.42,Default,,0,0,0,,关于代换模型和副作用并不是很兼容这一点\nDialogue: 0,1:03:14.36,1:03:18.24,Default,,0,0,0,,我以后会稍稍地讲解一下\nDialogue: 0,1:03:18.96,1:03:20.48,Default,,0,0,0,,但大体来说 我认为\nDialogue: 0,1:03:20.49,1:03:21.63,Default,,0,0,0,,除非你非常小心\nDialogue: 0,1:03:21.90,1:03:24.46,Default,,0,0,0,,否则副作用会把一切弄得很糟糕\nDialogue: 0,1:03:35.04,1:03:38.25,Default,,0,0,0,,学生：我不是很理解MEMO-PROC这个过程\nDialogue: 0,1:03:39.68,1:03:41.12,Default,,0,0,0,,你是什么时候执行那个LAMBDA的？\nDialogue: 0,1:03:41.99,1:03:43.21,Default,,0,0,0,,换句话说\nDialogue: 0,1:03:43.68,1:03:45.15,Default,,0,0,0,,当MEMO-PROC执行的时候\nDialogue: 0,1:03:45.18,1:03:47.71,Default,,0,0,0,,只生成了LAMBDA表达式\nDialogue: 0,1:03:48.01,1:03:49.68,Default,,0,0,0,,但我不太清楚它是什么时候被执行的\nDialogue: 0,1:03:50.39,1:03:51.12,Default,,0,0,0,,教授：好的\nDialogue: 0,1:03:51.35,1:03:52.68,Default,,0,0,0,,MEMO-PROC所做的 --\nDialogue: 0,1:03:53.07,1:03:55.85,Default,,0,0,0,,MEMO-PROC的一个参数是PROC\nDialogue: 0,1:03:56.38,1:03:57.93,Default,,0,0,0,,一个没有参数的过程\nDialogue: 0,1:03:57.93,1:03:59.05,Default,,0,0,0,,某个时刻 你会调用它\nDialogue: 0,1:04:00.39,1:04:02.75,Default,,0,0,0,,MEMO-PROC把该过程转化为\nDialogue: 0,1:04:02.75,1:04:04.56,Default,,0,0,0,,另一个无参过程\nDialogue: 0,1:04:04.59,1:04:05.80,Default,,0,0,0,,某个时刻你会调用到它\nDialogue: 0,1:04:06.62,1:04:07.42,Default,,0,0,0,,LAMBDA语句做的是这个\nDialogue: 0,1:04:09.89,1:04:14.08,Default,,0,0,0,,所以在这里 我最初构造\nDialogue: 0,1:04:15.85,1:04:17.92,Default,,0,0,0,,构造流的TAIL的时候\nDialogue: 0,1:04:18.30,1:04:20.48,Default,,0,0,0,,这里的这个无参过程\nDialogue: 0,1:04:20.51,1:04:21.61,Default,,0,0,0,,会在之后的某个时刻调用\nDialogue: 0,1:04:24.10,1:04:28.01,Default,,0,0,0,,相对应的 我要对(TAIL STREAM)调用MEMO-PROC\nDialogue: 0,1:04:28.12,1:04:29.24,Default,,0,0,0,,以后我会调用生成的过程\nDialogue: 0,1:04:30.65,1:04:31.90,Default,,0,0,0,,所以这个无参的LAMBDA\nDialogue: 0,1:04:32.03,1:04:36.06,Default,,0,0,0,,是当你在调用MEMO-PROC时调用的\nDialogue: 0,1:04:38.97,1:04:40.96,Default,,0,0,0,,当你调用MEMP-PROC返回的过程时\nDialogue: 0,1:04:40.97,1:04:42.28,Default,,0,0,0,,也就会像通常的过程调用那样\nDialogue: 0,1:04:42.36,1:04:45.76,Default,,0,0,0,,调用你最初设定的那个函数\nDialogue: 0,1:04:47.64,1:04:48.86,Default,,0,0,0,,学生：我想问的是\nDialogue: 0,1:04:48.86,1:04:50.86,Default,,0,0,0,,当你调用MEMO-PROC的时候\nDialogue: 0,1:04:50.86,1:04:52.30,Default,,0,0,0,,你返回了这个LAMBDA\nDialogue: 0,1:04:52.61,1:04:53.07,Default,,0,0,0,,教授：是的\nDialogue: 0,1:04:53.77,1:04:58.10,Default,,0,0,0,,你调用MEMO-PROC的时候 返回了一个LAMBDA\nDialogue: 0,1:04:58.10,1:04:59.84,Default,,0,0,0,,直到你第一次需要执行它的时候\nDialogue: 0,1:04:59.87,1:05:02.27,Default,,0,0,0,,你才去求值<EXP>\nDialogue: 0,1:05:07.76,1:05:09.10,Default,,0,0,0,,学生：我这样理解对吗？\nDialogue: 0,1:05:09.18,1:05:11.40,Default,,0,0,0,,你构造了一个表\nDialogue: 0,1:05:11.47,1:05:14.17,Default,,0,0,0,,但表中的元素还没有被求值\nDialogue: 0,1:05:14.24,1:05:15.63,Default,,0,0,0,,表达式没有被求值？\nDialogue: 0,1:05:15.63,1:05:18.54,Default,,0,0,0,,但在每个阶段 你还是构造了一个表\nDialogue: 0,1:05:18.54,1:05:20.70,Default,,0,0,0,,教授：啊 我应该这样说\nDialogue: 0,1:05:20.70,1:05:22.27,Default,,0,0,0,,这个想法很好\nDialogue: 0,1:05:22.27,1:05:23.18,Default,,0,0,0,,但是 也不全对\nDialogue: 0,1:05:23.66,1:05:25.08,Default,,0,0,0,,因为实际发生的事情是这样的\nDialogue: 0,1:05:25.08,1:05:26.35,Default,,0,0,0,,我先把这个画成序对\nDialogue: 0,1:05:26.89,1:05:28.03,Default,,0,0,0,,假设我要构造一个特别大的流\nDialogue: 0,1:05:28.96,1:05:30.12,Default,,0,0,0,,比如枚举一段区间\nDialogue: 0,1:05:30.32,1:05:31.48,Default,,0,0,0,,从1到1,000,000,000\nDialogue: 0,1:05:32.74,1:05:35.74,Default,,0,0,0,,这实际上是一个序对\nDialogue: 0,1:05:39.34,1:05:43.36,Default,,0,0,0,,由1和一个PROMISE组成\nDialogue: 0,1:05:46.73,1:05:47.89,Default,,0,0,0,,就是这样\nDialogue: 0,1:05:47.89,1:05:48.76,Default,,0,0,0,,什么都没有构造\nDialogue: 0,1:05:51.60,1:05:53.29,Default,,0,0,0,,当我继续FORCE这个PROMISE\nDialogue: 0,1:05:54.51,1:05:56.37,Default,,0,0,0,,再来看看 会发生什么\nDialogue: 0,1:05:56.37,1:05:59.66,Default,,0,0,0,,这个东西现在就成为了一个递归CONS\nDialogue: 0,1:06:00.53,1:06:02.16,Default,,0,0,0,,所以这个PROMISE现在就变成了\nDialogue: 0,1:06:04.62,1:06:08.96,Default,,0,0,0,,一个2和做更多事情的PROMISE\nDialogue: 0,1:06:11.35,1:06:12.73,Default,,0,0,0,,一直这样下去\nDialogue: 0,1:06:14.47,1:06:17.63,Default,,0,0,0,,直到你走完整个流才完整地构建了一个表\nDialogue: 0,1:06:18.20,1:06:19.58,Default,,0,0,0,,因为这个东西不是表\nDialogue: 0,1:06:20.03,1:06:21.48,Default,,0,0,0,,只是一个生成表的PROMISE\nDialogue: 0,1:06:23.39,1:06:25.50,Default,,0,0,0,,技术上来说 PROMISE就是一个过程\nDialogue: 0,1:06:27.80,1:06:29.10,Default,,0,0,0,,因此并没有直接构造好一个表\nDialogue: 0,1:06:30.76,1:06:32.72,Default,,0,0,0,,我应该早点说的\nDialogue: 0,1:06:34.28,1:06:35.34,Default,,0,0,0,,好吧 就到这里 下课\nDialogue: 0,1:06:35.82,1:06:51.15,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:06:35.82,1:06:51.15,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec6a.chn.ass",
    "content": "[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.01,0:00:02.46,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N张大伟\\N（DreamAndDead）\nDialogue: 0,0:00:02.60,0:00:10.00,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:10.10,0:00:14.60,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 I\nDialogue: 0,0:00:18.55,0:00:21.84,Default,,0,0,0,,上次Gerry教授揭晓了秘密\nDialogue: 0,0:00:22.49,0:00:24.60,Default,,0,0,0,,他介绍了赋值的概念\nDialogue: 0,0:00:26.35,0:00:33.61,Default,,0,0,0,,赋值与状态\nDialogue: 0,0:00:37.48,0:00:40.03,Default,,0,0,0,,正如我们所见\nDialogue: 0,0:00:40.72,0:00:43.16,Default,,0,0,0,,将赋值和状态引入到语言中\nDialogue: 0,0:00:43.16,0:00:44.41,Default,,0,0,0,,后果相当糟糕\nDialogue: 0,0:00:45.08,0:00:48.62,Default,,0,0,0,,首先 代换模型不再能够描述求值过程了\nDialogue: 0,0:00:49.13,0:00:52.48,Default,,0,0,0,,为了解释程序中语句的语义\nDialogue: 0,0:00:52.48,0:00:54.27,Default,,0,0,0,,我们不得不使用更复杂的环境模型\nDialogue: 0,0:00:54.28,0:00:57.24,Default,,0,0,0,,也就是一种跟图表相关的非常机械的东西\nDialogue: 0,0:00:58.46,0:01:00.12,Default,,0,0,0,,并且 这不单纯地是一个技术上的问题\nDialogue: 0,0:01:00.26,0:01:03.28,Default,,0,0,0,,并不是因为代换模型在这里不怎么有效\nDialogue: 0,0:01:03.60,0:01:05.68,Default,,0,0,0,,所以我们得想些其它办法\nDialogue: 0,0:01:05.71,0:01:09.79,Default,,0,0,0,,而是代换模型这类机制都不再起效\nDialogue: 0,0:01:10.73,0:01:13.32,Default,,0,0,0,,这是因为突然间 一个变量\nDialogue: 0,0:01:14.12,0:01:16.92,Default,,0,0,0,,不再是代表着一个值了\nDialogue: 0,0:01:17.95,0:01:21.76,Default,,0,0,0,,现在 变量用于指明一个位置\nDialogue: 0,0:01:22.40,0:01:23.34,Default,,0,0,0,,一个存放值的位置\nDialogue: 0,0:01:23.63,0:01:26.14,Default,,0,0,0,,并且 这个位置的值可以发生改变\nDialogue: 0,0:01:30.28,0:01:34.09,Default,,0,0,0,,比如像 (F X) 这样的表达式\nDialogue: 0,0:01:37.36,0:01:39.64,Default,,0,0,0,,就可能含有副作用\nDialogue: 0,0:01:40.41,0:01:42.60,Default,,0,0,0,,如果我们执行 (F X) 得到某个值\nDialogue: 0,0:01:43.18,0:01:45.34,Default,,0,0,0,,之后我们再次执行 (F X)\nDialogue: 0,0:01:47.24,0:01:48.43,Default,,0,0,0,,可能因为求值的顺序\nDialogue: 0,0:01:48.86,0:01:49.74,Default,,0,0,0,,而得到不同的值\nDialogue: 0,0:01:49.76,0:01:52.14,Default,,0,0,0,,所以突然间 我们不能仅仅关注于值\nDialogue: 0,0:01:52.52,0:01:53.60,Default,,0,0,0,,也要关注时序\nDialogue: 0,0:01:57.97,0:01:59.98,Default,,0,0,0,,序对也不仅仅\nDialogue: 0,0:02:00.65,0:02:02.52,Default,,0,0,0,,只是它的CAR和CDR部分\nDialogue: 0,0:02:02.52,0:02:05.61,Default,,0,0,0,,不是作为CAR部分和CDR部分的别称\nDialogue: 0,0:02:05.80,0:02:07.05,Default,,0,0,0,,它也有自己的“身份”\nDialogue: 0,0:02:08.44,0:02:11.65,Default,,0,0,0,,序对具有“身份”\nDialogue: 0,0:02:11.65,0:02:12.59,Default,,0,0,0,,它是一个对象\nDialogue: 0,0:02:21.33,0:02:25.15,Default,,0,0,0,,两个具有相同CAR和CDR部分的序对\nDialogue: 0,0:02:25.40,0:02:27.05,Default,,0,0,0,,可能相同也可能不同\nDialogue: 0,0:02:27.87,0:02:30.51,Default,,0,0,0,,因为这之中可能存在“共享”\nDialogue: 0,0:02:34.96,0:02:39.45,Default,,0,0,0,,一引入赋值 这些就变成要考虑的问题了\nDialogue: 0,0:02:40.48,0:02:43.98,Default,,0,0,0,,确实 这和我们说讲代换的时候差别悬殊\nDialogue: 0,0:02:45.04,0:02:48.91,Default,,0,0,0,,技术上来看 我们思考起来更加困难了\nDialogue: 0,0:02:48.94,0:02:53.45,Default,,0,0,0,,因为我们必须相当机械地思考程序语言\nDialogue: 0,0:02:53.47,0:02:55.34,Default,,0,0,0,,而不能仅仅用数学的方式来思考\nDialogue: 0,0:02:55.71,0:02:58.60,Default,,0,0,0,,我们也会遇到哲学问题\nDialogue: 0,0:02:59.15,0:03:00.65,Default,,0,0,0,,我们会被这样的问题所困扰：\nDialogue: 0,0:03:00.67,0:03:02.38,Default,,0,0,0,,事物的“改变”指的是什么？\nDialogue: 0,0:03:02.38,0:03:03.77,Default,,0,0,0,,两个事物“同一”又如何判别？\nDialogue: 0,0:03:03.84,0:03:06.83,Default,,0,0,0,,并且 这也会给我们编程带来困扰\nDialogue: 0,0:03:07.47,0:03:08.54,Default,,0,0,0,,正如 Sussman 教授上节课中讲的那样\nDialogue: 0,0:03:08.56,0:03:12.20,Default,,0,0,0,,错误的表达式顺序和别名会产生BUG\nDialogue: 0,0:03:12.22,0:03:16.19,Default,,0,0,0,,这些问题在不需要考虑“对象”的语言中 是不存在的\nDialogue: 0,0:03:18.21,0:03:21.20,Default,,0,0,0,,我们是怎样陷入这样的困境的呢？\nDialogue: 0,0:03:24.01,0:03:27.20,Default,,0,0,0,,我们这样做的原因在于\nDialogue: 0,0:03:27.40,0:03:31.47,Default,,0,0,0,,我们想要构造模块化的系统\nDialogue: 0,0:03:35.15,0:03:37.69,Default,,0,0,0,,我们想把系统划分为\nDialogue: 0,0:03:38.09,0:03:41.04,Default,,0,0,0,,数个自然组合的小块\nDialogue: 0,0:03:42.76,0:03:43.82,Default,,0,0,0,,举例来说\nDialogue: 0,0:03:44.06,0:03:46.11,Default,,0,0,0,,我们想要构造一个随机数发生器\nDialogue: 0,0:03:46.22,0:03:49.40,Default,,0,0,0,,把该发生器的内部状态封装起来\nDialogue: 0,0:03:50.25,0:03:53.71,Default,,0,0,0,,这样我们就可以把选取随机数\nDialogue: 0,0:03:54.65,0:03:57.79,Default,,0,0,0,,和用于估计的蒙特卡洛方法分离开来\nDialogue: 0,0:03:58.65,0:04:01.52,Default,,0,0,0,,进一步地把它同由 Ceraso 发明的\nDialogue: 0,0:04:01.90,0:04:05.74,Default,,0,0,0,,求取 π 的公式分离开\nDialogue: 0,0:04:06.80,0:04:07.92,Default,,0,0,0,,相似地\nDialogue: 0,0:04:09.61,0:04:11.74,Default,,0,0,0,,当我们着手构建事物的模型时\nDialogue: 0,0:04:12.35,0:04:16.01,Default,,0,0,0,,我们去构建现实世界中事物的模型\nDialogue: 0,0:04:17.31,0:04:19.42,Default,,0,0,0,,我们想把程序组织成许多自然部分\nDialogue: 0,0:04:19.44,0:04:20.52,Default,,0,0,0,,这些部分就是\nDialogue: 0,0:04:21.05,0:04:23.16,Default,,0,0,0,,现实事物的镜像\nDialogue: 0,0:04:24.90,0:04:27.56,Default,,0,0,0,,举个例子 对于一个数字电路\nDialogue: 0,0:04:28.36,0:04:29.18,Default,,0,0,0,,我们会说\nDialogue: 0,0:04:30.44,0:04:31.44,Default,,0,0,0,,这儿有一个电路\nDialogue: 0,0:04:32.08,0:04:35.16,Default,,0,0,0,,它有一个这样的元件 有一个那样的元件\nDialogue: 0,0:04:40.10,0:04:43.58,Default,,0,0,0,,这些元件都有不同的“身份”\nDialogue: 0,0:04:43.58,0:04:44.59,Default,,0,0,0,,它们都有各自的状态\nDialogue: 0,0:04:45.55,0:04:47.13,Default,,0,0,0,,状态附着在电路上\nDialogue: 0,0:04:48.58,0:04:50.22,Default,,0,0,0,,我们认为这个元件是一个对象\nDialogue: 0,0:04:50.49,0:04:51.93,Default,,0,0,0,,这个元件又是另外一个不同的对象\nDialogue: 0,0:04:52.54,0:04:53.85,Default,,0,0,0,,当我们观察到系统发生了变化\nDialogue: 0,0:04:53.87,0:04:55.40,Default,,0,0,0,,信号从这里传递过来\nDialogue: 0,0:04:55.63,0:04:58.41,Default,,0,0,0,,改变了可能存放在这里的状态 并向这里继续传播\nDialogue: 0,0:04:58.67,0:05:00.75,Default,,0,0,0,,和一个存储在这里的状态交互\nDialogue: 0,0:05:01.24,0:05:02.17,Default,,0,0,0,,依此类推\nDialogue: 0,0:05:06.86,0:05:11.24,Default,,0,0,0,,我们想要在计算机中\nDialogue: 0,0:05:12.76,0:05:14.36,Default,,0,0,0,,构建模块化的系统\nDialogue: 0,0:05:14.68,0:05:17.87,Default,,0,0,0,,来反映我们对现实的看法\nDialogue: 0,0:05:17.88,0:05:19.87,Default,,0,0,0,,根据我们正在建模的实际系统\nDialogue: 0,0:05:19.88,0:05:20.91,Default,,0,0,0,,来划分子系统\nDialogue: 0,0:05:23.20,0:05:23.48,Default,,0,0,0,,然而\nDialogue: 0,0:05:25.74,0:05:28.99,Default,,0,0,0,,构建像这样的系统\nDialogue: 0,0:05:28.99,0:05:31.50,Default,,0,0,0,,看起来带来了不少技术上的麻烦\nDialogue: 0,0:05:31.52,0:05:32.75,Default,,0,0,0,,但这不是计算机造成的\nDialogue: 0,0:05:33.61,0:05:35.60,Default,,0,0,0,,或许 真正拖累我们\nDialogue: 0,0:05:36.70,0:05:38.65,Default,,0,0,0,,让我们花了那么大的功夫\nDialogue: 0,0:05:38.67,0:05:40.94,Default,,0,0,0,,才让程序反映现实世界的原因\nDialogue: 0,0:05:41.52,0:05:43.13,Default,,0,0,0,,是我们对现实世界的认识出了错\nDialogue: 0,0:05:44.55,0:05:46.75,Default,,0,0,0,,或许时间只是幻觉\nDialogue: 0,0:05:47.26,0:05:48.60,Default,,0,0,0,,什么都没有改变\nDialogue: 0,0:05:50.15,0:05:51.71,Default,,0,0,0,,就拿这个粉笔来说\nDialogue: 0,0:05:52.44,0:05:53.77,Default,,0,0,0,,我们认为它是一个对象\nDialogue: 0,0:05:54.01,0:05:54.99,Default,,0,0,0,,它有自己的状态\nDialogue: 0,0:05:55.82,0:05:59.29,Default,,0,0,0,,每时每刻 它都有一个位置和速度\nDialogue: 0,0:05:59.71,0:06:01.48,Default,,0,0,0,,如果我们做点什么 就可以改变它的状态\nDialogue: 0,0:06:04.34,0:06:07.37,Default,,0,0,0,,但是你如果了解一点相对性的概念\nDialogue: 0,0:06:07.74,0:06:09.71,Default,,0,0,0,,你可能会认为粉笔的路径\nDialogue: 0,0:06:09.72,0:06:11.34,Default,,0,0,0,,不是许多瞬时的离散点\nDialogue: 0,0:06:11.34,0:06:14.38,Default,,0,0,0,,一种深刻的见解是把整个粉笔的存在看作\nDialogue: 0,0:06:14.41,0:06:15.64,Default,,0,0,0,,时空中的路径\nDialogue: 0,0:06:16.02,0:06:17.37,Default,,0,0,0,,全部都展开了\nDialogue: 0,0:06:17.87,0:06:19.84,Default,,0,0,0,,没有单独的位置与速度\nDialogue: 0,0:06:19.84,0:06:23.80,Default,,0,0,0,,在时空中的存在是不会发生改变的\nDialogue: 0,0:06:24.64,0:06:26.51,Default,,0,0,0,,相似地 如果我们来考察这个电气系统\nDialogue: 0,0:06:27.69,0:06:30.43,Default,,0,0,0,,我们假设这个系统实现的是\nDialogue: 0,0:06:30.59,0:06:33.96,Default,,0,0,0,,某种信号处理系统\nDialogue: 0,0:06:34.36,0:06:36.68,Default,,0,0,0,,把这些元件组合在一起的工程师\nDialogue: 0,0:06:36.75,0:06:38.60,Default,,0,0,0,,也不会把它们看作\nDialogue: 0,0:06:38.96,0:06:41.40,Default,,0,0,0,,电压施加于每个独立的元件\nDialogue: 0,0:06:41.49,0:06:43.16,Default,,0,0,0,,转换成了某种东西\nDialogue: 0,0:06:43.34,0:06:45.52,Default,,0,0,0,,影响了这里的状态\nDialogue: 0,0:06:45.53,0:06:46.81,Default,,0,0,0,,还改变了那里的状态\nDialogue: 0,0:06:46.81,0:06:50.11,Default,,0,0,0,,没有一个做信号处理的会这样想\nDialogue: 0,0:06:50.42,0:06:51.84,Default,,0,0,0,,相反 你会说\nDialogue: 0,0:06:54.04,0:06:58.06,Default,,0,0,0,,这里有一个在时间上伸展的信号\nDialogue: 0,0:06:58.06,0:06:59.48,Default,,0,0,0,,如果把这个看作一个滤波器\nDialogue: 0,0:07:00.20,0:07:04.04,Default,,0,0,0,,这个滤波器会把整个信号转化成\nDialogue: 0,0:07:04.28,0:07:07.04,Default,,0,0,0,,不同的输出信号\nDialogue: 0,0:07:09.57,0:07:11.28,Default,,0,0,0,,你们不要把这些东西的状态\nDialogue: 0,0:07:11.28,0:07:13.29,Default,,0,0,0,,想象成在许多瞬间接连发生\nDialogue: 0,0:07:14.16,0:07:17.32,Default,,0,0,0,,我们把这个盒子看作一个整体\nDialogue: 0,0:07:17.32,0:07:20.16,Default,,0,0,0,,而不是在一个特定的瞬间\nDialogue: 0,0:07:20.40,0:07:21.96,Default,,0,0,0,,互相发送状态信息的小系统\nDialogue: 0,0:07:28.25,0:07:29.36,Default,,0,0,0,,今天我们将介绍\nDialogue: 0,0:07:29.39,0:07:31.13,Default,,0,0,0,,另一种分解系统的方法\nDialogue: 0,0:07:31.36,0:07:35.45,Default,,0,0,0,,站在信号工程师的角度去看待现实世界\nDialogue: 0,0:07:35.69,0:07:38.96,Default,,0,0,0,,而不再认为对象间通过消息传递来通信\nDialogue: 0,0:07:41.13,0:07:43.74,Default,,0,0,0,,它被称为“流处理”\nDialogue: 0,0:07:54.57,0:07:58.96,Default,,0,0,0,,我们打算展示\nDialogue: 0,0:08:00.59,0:08:04.16,Default,,0,0,0,,如何让我们的程序变得更加统一\nDialogue: 0,0:08:05.15,0:08:06.54,Default,,0,0,0,,从中看到更多的共性\nDialogue: 0,0:08:06.65,0:08:09.88,Default,,0,0,0,,如果我们跳出这些程序\nDialogue: 0,0:08:10.81,0:08:12.30,Default,,0,0,0,,我们会发现\nDialogue: 0,0:08:12.35,0:08:15.12,Default,,0,0,0,,我们对时序的考虑过度了\nDialogue: 0,0:08:16.89,0:08:20.22,Default,,0,0,0,,我们先来对比两个过程\nDialogue: 0,0:08:23.55,0:08:25.69,Default,,0,0,0,,第一个是这样\nDialogue: 0,0:08:25.69,0:08:27.77,Default,,0,0,0,,想像这有一个树\nDialogue: 0,0:08:30.40,0:08:32.14,Default,,0,0,0,,一个由整数构成的树\nDialogue: 0,0:08:33.28,0:08:34.42,Default,,0,0,0,,一个二叉树\nDialogue: 0,0:08:36.12,0:08:36.97,Default,,0,0,0,,这里是1\nDialogue: 0,0:08:39.10,0:08:40.23,Default,,0,0,0,,看起来就像这样\nDialogue: 0,0:08:40.23,0:08:42.92,Default,,0,0,0,,在每个节点上都有一个整数\nDialogue: 0,0:08:45.18,0:08:47.80,Default,,0,0,0,,我们想计算\nDialogue: 0,0:08:48.67,0:08:51.56,Default,,0,0,0,,对这个树中所有的奇数\nDialogue: 0,0:08:52.30,0:08:55.10,Default,,0,0,0,,计算它们的平方和\nDialogue: 0,0:08:57.05,0:08:59.48,Default,,0,0,0,,我们对这类问题很熟悉\nDialogue: 0,0:08:59.48,0:09:01.95,Default,,0,0,0,,有一种递归策略求解它\nDialogue: 0,0:09:02.93,0:09:04.35,Default,,0,0,0,,观察每个叶子节点\nDialogue: 0,0:09:04.56,0:09:06.68,Default,,0,0,0,,如果是奇数我们就求它的平方 并加和\nDialogue: 0,0:09:06.70,0:09:07.77,Default,,0,0,0,,如果是偶数 就是0\nDialogue: 0,0:09:08.68,0:09:12.11,Default,,0,0,0,,递归地看 对于每一颗树 我们可以说\nDialogue: 0,0:09:12.65,0:09:13.84,Default,,0,0,0,,它的平方和等于\nDialogue: 0,0:09:13.92,0:09:15.93,Default,,0,0,0,,右子树的平方和 加上左子树的平方和\nDialogue: 0,0:09:16.25,0:09:17.64,Default,,0,0,0,,就这样沿着节点递归下去\nDialogue: 0,0:09:17.64,0:09:18.70,Default,,0,0,0,,我们已经很熟悉\nDialogue: 0,0:09:19.26,0:09:20.36,Default,,0,0,0,,这种程序设计的思考方式了\nDialogue: 0,0:09:20.36,0:09:22.59,Default,,0,0,0,,我们来幻灯片上看一下\nDialogue: 0,0:09:23.82,0:09:26.75,Default,,0,0,0,,为了计算一棵树中奇数的平方和\nDialogue: 0,0:09:27.37,0:09:29.36,Default,,0,0,0,,我们先要判断它是否是一个叶子节点\nDialogue: 0,0:09:29.82,0:09:31.95,Default,,0,0,0,,判断方法则是考察该节点是否为整数\nDialogue: 0,0:09:32.88,0:09:36.38,Default,,0,0,0,,继而判断其奇偶性 以及是否应该求取平方并加和\nDialogue: 0,0:09:37.16,0:09:38.99,Default,,0,0,0,,然后 整个的解就是\nDialogue: 0,0:09:39.21,0:09:42.12,Default,,0,0,0,,左、右子树解的总和\nDialogue: 0,0:09:46.34,0:09:50.56,Default,,0,0,0,,好的 让我们再来和下面一个问题对比一下\nDialogue: 0,0:09:51.56,0:09:53.68,Default,,0,0,0,,假如给你一个整数N\nDialogue: 0,0:09:54.73,0:09:57.88,Default,,0,0,0,,再给定一个函数 把它应用在\nDialogue: 0,0:09:57.93,0:09:58.83,Default,,0,0,0,,1到N的每一个数上\nDialogue: 0,0:09:59.10,0:10:01.08,Default,,0,0,0,,我想把其中的一些值收集成一个表\nDialogue: 0,0:10:01.28,0:10:04.65,Default,,0,0,0,,那些满足某种属性的函数值\nDialogue: 0,0:10:05.60,0:10:06.88,Default,,0,0,0,,这是种一般性的说法\nDialogue: 0,0:10:06.88,0:10:07.98,Default,,0,0,0,,说得更具体一点\nDialogue: 0,0:10:08.62,0:10:10.48,Default,,0,0,0,,假设对于每个整数K\nDialogue: 0,0:10:10.65,0:10:12.51,Default,,0,0,0,,计算第K个斐波那契数\nDialogue: 0,0:10:14.21,0:10:16.27,Default,,0,0,0,,然后挑出其中的奇数\nDialogue: 0,0:10:16.83,0:10:18.40,Default,,0,0,0,,并把它们组成一个表\nDialogue: 0,0:10:19.05,0:10:20.71,Default,,0,0,0,,这个过程是这样的\nDialogue: 0,0:10:23.73,0:10:26.24,Default,,0,0,0,,寻找前N个斐波那契数中的奇数\nDialogue: 0,0:10:26.24,0:10:28.91,Default,,0,0,0,,这里是我们一直以来采用的循环方法\nDialogue: 0,0:10:28.91,0:10:29.82,Default,,0,0,0,,用到了递归\nDialogue: 0,0:10:30.80,0:10:31.79,Default,,0,0,0,,以K为循环变量\nDialogue: 0,0:10:32.03,0:10:34.35,Default,,0,0,0,,如果K大于N 返回空表\nDialogue: 0,0:10:35.13,0:10:37.36,Default,,0,0,0,,否则计算第K个斐波那契数\nDialogue: 0,0:10:37.44,0:10:38.06,Default,,0,0,0,,将其与变量F绑定\nDialogue: 0,0:10:40.37,0:10:42.84,Default,,0,0,0,,如果是奇数 我们把它与\nDialogue: 0,0:10:43.76,0:10:46.01,Default,,0,0,0,,从K+1计算得到的表相连接\nDialogue: 0,0:10:47.69,0:10:50.12,Default,,0,0,0,,否则 我们只取从K+1计算得到的结果\nDialogue: 0,0:10:50.73,0:10:53.00,Default,,0,0,0,,这是迭代式循环的标准写法\nDialogue: 0,0:10:53.00,0:10:55.56,Default,,0,0,0,,我们以1为初值 启动这个循环\nDialogue: 0,0:10:57.58,0:11:00.06,Default,,0,0,0,,好的 就是这两个过程\nDialogue: 0,0:11:01.60,0:11:02.90,Default,,0,0,0,,它们看起来非常不同\nDialogue: 0,0:11:02.90,0:11:04.20,Default,,0,0,0,,完全不同的结构\nDialogue: 0,0:11:04.25,0:11:06.89,Default,,0,0,0,,然而 从一个特定的角度来看\nDialogue: 0,0:11:06.92,0:11:09.61,Default,,0,0,0,,两个过程做的事情是一样的\nDialogue: 0,0:11:11.33,0:11:14.67,Default,,0,0,0,,如果我是一个信号处理工程师\nDialogue: 0,0:11:14.70,0:11:16.81,Default,,0,0,0,,我可能会说\nDialogue: 0,0:11:18.24,0:11:26.76,Default,,0,0,0,,第一个过程枚举了树的叶节点\nDialogue: 0,0:11:31.16,0:11:34.56,Default,,0,0,0,,可以认为是信号从一个全是叶节点的地方输出\nDialogue: 0,0:11:35.33,0:11:43.39,Default,,0,0,0,,我们想要过滤出其中的奇数\nDialogue: 0,0:11:43.58,0:11:44.94,Default,,0,0,0,,把它们放入某种滤波器中\nDialogue: 0,0:11:45.19,0:11:47.79,Default,,0,0,0,,然后再把它们放入某种换能器\nDialogue: 0,0:11:49.20,0:11:51.69,Default,,0,0,0,,对每一个输出 我们对其取平方\nDialogue: 0,0:11:54.44,0:11:57.44,Default,,0,0,0,,最后把结果累积在一起\nDialogue: 0,0:11:58.29,0:12:00.04,Default,,0,0,0,,我们以0为初值\nDialogue: 0,0:12:00.35,0:12:03.37,Default,,0,0,0,,通过加法把它们累积起来\nDialogue: 0,0:12:07.14,0:12:08.21,Default,,0,0,0,,这是第一个程序\nDialogue: 0,0:12:08.21,0:12:09.18,Default,,0,0,0,,对于第二个程序\nDialogue: 0,0:12:09.24,0:12:11.21,Default,,0,0,0,,我也可以用一种非常类似的方法来描述\nDialogue: 0,0:12:11.78,0:12:13.42,Default,,0,0,0,,我们枚举\nDialogue: 0,0:12:15.80,0:12:19.10,Default,,0,0,0,,从1到N这个区间上的数\nDialogue: 0,0:12:22.50,0:12:24.40,Default,,0,0,0,,对于每个数\nDialogue: 0,0:12:25.45,0:12:26.92,Default,,0,0,0,,计算对应的斐波那契数\nDialogue: 0,0:12:27.79,0:12:29.27,Default,,0,0,0,,再放入一个换能器\nDialogue: 0,0:12:29.27,0:12:30.78,Default,,0,0,0,,对于输出的结果\nDialogue: 0,0:12:31.31,0:12:34.20,Default,,0,0,0,,再通过奇偶性进行过滤\nDialogue: 0,0:12:36.27,0:12:39.24,Default,,0,0,0,,最后 我们将这些放入累积函数\nDialogue: 0,0:12:39.35,0:12:40.56,Default,,0,0,0,,这次我们要累积出一个表\nDialogue: 0,0:12:40.78,0:12:42.17,Default,,0,0,0,,所以我们用CONS来做积累\nDialogue: 0,0:12:42.59,0:12:43.77,Default,,0,0,0,,以空表为初始值\nDialogue: 0,0:12:47.11,0:12:49.80,Default,,0,0,0,,从这个角度来看\nDialogue: 0,0:12:49.85,0:12:51.84,Default,,0,0,0,,这两个程序真的是太相似了\nDialogue: 0,0:12:51.90,0:12:52.84,Default,,0,0,0,,问题在于\nDialogue: 0,0:12:53.20,0:12:56.49,Default,,0,0,0,,两个程序的写法导致\nDialogue: 0,0:12:56.64,0:12:58.05,Default,,0,0,0,,我们看不出其中的共性\nDialogue: 0,0:12:58.05,0:13:01.44,Default,,0,0,0,,再回头来看奇数平方和的问题\nDialogue: 0,0:13:02.22,0:13:04.64,Default,,0,0,0,,问题来了 哪个是枚举函数呢？\nDialogue: 0,0:13:06.35,0:13:08.14,Default,,0,0,0,,程序中哪一部分有枚举的作用？\nDialogue: 0,0:13:08.14,0:13:10.52,Default,,0,0,0,,枚举不是仅仅在一个地方表现出来的\nDialogue: 0,0:13:11.02,0:13:15.47,Default,,0,0,0,,在叶子节点的判断处存在一部分\nDialogue: 0,0:13:16.43,0:13:17.16,Default,,0,0,0,,在这个判断循环终止的地方\nDialogue: 0,0:13:17.16,0:13:20.06,Default,,0,0,0,,也下面的递归结构中也有体现\nDialogue: 0,0:13:23.15,0:13:24.12,Default,,0,0,0,,累积函数又在哪儿呢？\nDialogue: 0,0:13:24.12,0:13:25.68,Default,,0,0,0,,它也不只在一个地方\nDialogue: 0,0:13:25.68,0:13:30.73,Default,,0,0,0,,它在 0 和 + 这两个地方分别体现出来\nDialogue: 0,0:13:32.00,0:13:34.51,Default,,0,0,0,,累积函数分散在过程的每个部分\nDialogue: 0,0:13:34.51,0:13:39.05,Default,,0,0,0,,相似地 我们来观察奇数斐波那契数的例子\nDialogue: 0,0:13:39.05,0:13:42.80,Default,,0,0,0,,某种意义上 程序中也存在枚举函数与累积函数\nDialogue: 0,0:13:42.80,0:13:44.01,Default,,0,0,0,,但看起来非常不同\nDialogue: 0,0:13:44.62,0:13:50.09,Default,,0,0,0,,枚举部分地表现在(> k n)的判断中\nDialogue: 0,0:13:50.38,0:13:52.84,Default,,0,0,0,,部分地表现在下面的递归调用中\nDialogue: 0,0:13:53.18,0:13:54.24,Default,,0,0,0,,还有就是启动循环的地方\nDialogue: 0,0:13:55.68,0:13:56.32,Default,,0,0,0,,同样地\nDialogue: 0,0:13:56.52,0:13:58.76,Default,,0,0,0,,其中也混杂了累积函数\nDialogue: 0,0:13:58.91,0:14:00.12,Default,,0,0,0,,分别在这里\nDialogue: 0,0:14:00.41,0:14:01.40,Default,,0,0,0,,和这里\nDialogue: 0,0:14:03.60,0:14:06.08,Default,,0,0,0,,所以这些非常自然的部分\nDialogue: 0,0:14:08.73,0:14:12.65,Default,,0,0,0,,我们之前画的那些方框在程序中完全看不出来\nDialogue: 0,0:14:13.26,0:14:14.36,Default,,0,0,0,,因为它们混杂在一起了\nDialogue: 0,0:14:14.36,0:14:16.29,Default,,0,0,0,,这些程序并没有很好地对问题进行切分\nDialogue: 0,0:14:19.45,0:14:22.17,Default,,0,0,0,,回到计算机科学的基本原理上来\nDialogue: 0,0:14:22.19,0:14:23.63,Default,,0,0,0,,为了控制某种东西\nDialogue: 0,0:14:23.63,0:14:24.96,Default,,0,0,0,,你需要它的名字\nDialogue: 0,0:14:25.80,0:14:28.44,Default,,0,0,0,,我们还没有很好地掌握按这种方式来思考\nDialogue: 0,0:14:28.67,0:14:31.06,Default,,0,0,0,,这是因为我们没有显式地操作它们的手段\nDialogue: 0,0:14:31.06,0:14:33.80,Default,,0,0,0,,我们没有一门好的语言来讨论它们\nDialogue: 0,0:14:35.42,0:14:38.86,Default,,0,0,0,,好吧 我们来创造一门合适的语言\nDialogue: 0,0:14:42.52,0:14:44.04,Default,,0,0,0,,用它来构建这些器件\nDialogue: 0,0:14:44.78,0:14:47.21,Default,,0,0,0,,这种语言的关键在于\nDialogue: 0,0:14:47.21,0:14:49.71,Default,,0,0,0,,这些叫作信号的东西到底是什么？\nDialogue: 0,0:14:50.48,0:14:53.32,Default,,0,0,0,,这些沿着箭头传递的是什么？\nDialogue: 0,0:14:56.88,0:14:57.71,Default,,0,0,0,,这些东西\nDialogue: 0,0:14:59.85,0:15:03.52,Default,,0,0,0,,是一种称作“流”的数据结构\nDialogue: 0,0:15:03.79,0:15:05.87,Default,,0,0,0,,这也是发明这门语言的关键\nDialogue: 0,0:15:07.98,0:15:08.51,Default,,0,0,0,,“流”是什么东西呢？\nDialogue: 0,0:15:08.52,0:15:11.50,Default,,0,0,0,,和其它的东西一样 “流”是一种数据抽象\nDialogue: 0,0:15:12.22,0:15:15.82,Default,,0,0,0,,所以 我先说明它的选择函数与构造函数分别是什么\nDialogue: 0,0:15:16.87,0:15:19.48,Default,,0,0,0,,对于流结构 我们有一个构造函数\nDialogue: 0,0:15:19.98,0:15:21.43,Default,,0,0,0,,我们称其为CONS-STREAM\nDialogue: 0,0:15:25.69,0:15:28.11,Default,,0,0,0,,CONS-STREAM把两个事物放在一起\nDialogue: 0,0:15:28.59,0:15:30.22,Default,,0,0,0,,构造出一个流\nDialogue: 0,0:15:32.04,0:15:33.85,Default,,0,0,0,,选择函数叫作HEAD\nDialogue: 0,0:15:33.98,0:15:36.11,Default,,0,0,0,,用于从流中提取数据\nDialogue: 0,0:15:38.01,0:15:38.86,Default,,0,0,0,,如果我有一个流\nDialogue: 0,0:15:39.00,0:15:40.41,Default,,0,0,0,,我可以取它的头部\nDialogue: 0,0:15:41.13,0:15:42.38,Default,,0,0,0,,也可以取它的尾部\nDialogue: 0,0:15:44.72,0:15:47.42,Default,,0,0,0,,我把和George的约定告诉你\nDialogue: 0,0:15:48.24,0:15:52.70,Default,,0,0,0,,让你们知道和这个相关的公理\nDialogue: 0,0:15:53.44,0:16:00.17,Default,,0,0,0,,对于任何的X与Y\nDialogue: 0,0:16:03.40,0:16:05.44,Default,,0,0,0,,如果我把它们构造成一个流 并取其头部\nDialogue: 0,0:16:05.69,0:16:11.96,Default,,0,0,0,,(HEAD (CONS-STREAM X Y))\nDialogue: 0,0:16:13.29,0:16:14.52,Default,,0,0,0,,结果就是X\nDialogue: 0,0:16:16.14,0:16:27.45,Default,,0,0,0,,(TAIL (CONS-STREAM X Y)) = Y\nDialogue: 0,0:16:28.44,0:16:34.75,Default,,0,0,0,,一个构造函数 两个选择函数 一个公理 就是这些\nDialogue: 0,0:16:34.75,0:16:35.85,Default,,0,0,0,,这里有点可疑\nDialogue: 0,0:16:36.98,0:16:39.00,Default,,0,0,0,,你可能注意到了\nDialogue: 0,0:16:40.19,0:16:42.08,Default,,0,0,0,,这些就是CONS、CAR和CDR的公理\nDialogue: 0,0:16:43.63,0:16:46.56,Default,,0,0,0,,把CONS-STREAM换成CONS\nDialogue: 0,0:16:47.10,0:16:49.80,Default,,0,0,0,,HEAD换成CAR TAIL换成CDR\nDialogue: 0,0:16:50.76,0:16:52.81,Default,,0,0,0,,这些就是序对的公理\nDialogue: 0,0:16:52.81,0:16:54.32,Default,,0,0,0,,事实上 还有另一个东西\nDialogue: 0,0:16:55.13,0:16:56.80,Default,,0,0,0,,我们有一个叫THE-EMPTY-STREAM（空流）的东西\nDialogue: 0,0:17:02.80,0:17:04.04,Default,,0,0,0,,像空表一样\nDialogue: 0,0:17:08.31,0:17:10.03,Default,,0,0,0,,为什么我要引入这个术语呢？\nDialogue: 0,0:17:10.03,0:17:12.12,Default,,0,0,0,,为什么我不继续使用序对与表呢？\nDialogue: 0,0:17:12.78,0:17:13.79,Default,,0,0,0,,后面我们就知道了\nDialogue: 0,0:17:15.51,0:17:18.24,Default,,0,0,0,,暂时地 你们可以把术语“流”\nDialogue: 0,0:17:18.30,0:17:21.56,Default,,0,0,0,,当作“表”的另一种说法\nDialogue: 0,0:17:21.56,0:17:22.99,Default,,0,0,0,,一会儿我们就会知道 为什么\nDialogue: 0,0:17:23.61,0:17:26.09,Default,,0,0,0,,为什么我们需要这个额外的抽象层\nDialogue: 0,0:17:26.83,0:17:28.15,Default,,0,0,0,,而不是继续把它看做表\nDialogue: 0,0:17:32.30,0:17:33.72,Default,,0,0,0,,好的 有了流之后\nDialogue: 0,0:17:33.74,0:17:35.85,Default,,0,0,0,,我们就开始构建语言的部件了\nDialogue: 0,0:17:37.04,0:17:38.17,Default,,0,0,0,,用它来操作流\nDialogue: 0,0:17:38.75,0:17:42.12,Default,,0,0,0,,我们可以构建出太多有用的东西了\nDialogue: 0,0:17:42.12,0:17:42.81,Default,,0,0,0,,举例来说\nDialogue: 0,0:17:44.89,0:17:49.79,Default,,0,0,0,,我们构建MAP-STREAM 它的一个参数是流S\nDialogue: 0,0:17:54.80,0:17:56.62,Default,,0,0,0,,以及一个过程\nDialogue: 0,0:17:57.80,0:17:59.21,Default,,0,0,0,,它会生成一个新的流\nDialogue: 0,0:18:00.14,0:18:02.28,Default,,0,0,0,,它的构成元素是\nDialogue: 0,0:18:02.28,0:18:04.88,Default,,0,0,0,,将PROC应用到S的后续元素得到的结果\nDialogue: 0,0:18:05.87,0:18:07.40,Default,,0,0,0,,我们以前见过类似的\nDialogue: 0,0:18:07.40,0:18:10.24,Default,,0,0,0,,就是以前在表上定义的MAP过程\nDialogue: 0,0:18:10.95,0:18:12.60,Default,,0,0,0,,除了判断EMPTY-STREAM的部分\nDialogue: 0,0:18:12.60,0:18:14.65,Default,,0,0,0,,完全就和MAP一样\nDialogue: 0,0:18:14.65,0:18:15.56,Default,,0,0,0,,哦 我忘了说了\nDialogue: 0,0:18:15.56,0:18:17.15,Default,,0,0,0,,EMPTY-STREAM?就和NULL?差不多\nDialogue: 0,0:18:18.03,0:18:20.48,Default,,0,0,0,,如果是空的 就返回一个空的流\nDialogue: 0,0:18:20.51,0:18:22.28,Default,,0,0,0,,否则 就生成一个新的流\nDialogue: 0,0:18:23.52,0:18:27.18,Default,,0,0,0,,其第一个元素是PROC应用在流头部的结果\nDialogue: 0,0:18:28.51,0:18:29.32,Default,,0,0,0,,剩下的是\nDialogue: 0,0:18:29.60,0:18:32.43,Default,,0,0,0,,是MAP-STREAM对流尾部应用的结果\nDialogue: 0,0:18:33.14,0:18:35.90,Default,,0,0,0,,太像我们之前讲的MAP了\nDialogue: 0,0:18:37.03,0:18:38.20,Default,,0,0,0,,还有一个有用的函数\nDialogue: 0,0:18:38.35,0:18:40.46,Default,,0,0,0,,过滤函数 就是那个用来过滤的盒子\nDialogue: 0,0:18:40.46,0:18:43.89,Default,,0,0,0,,以一个谓词和一个流作为参数\nDialogue: 0,0:18:43.89,0:18:45.08,Default,,0,0,0,,它将生成一个新的流\nDialogue: 0,0:18:45.80,0:18:48.17,Default,,0,0,0,,包含了在流S中所有\nDialogue: 0,0:18:48.33,0:18:49.48,Default,,0,0,0,,满足谓词PRED的元素\nDialogue: 0,0:18:50.38,0:18:51.31,Default,,0,0,0,,这是一个“按条件分析语句”\nDialogue: 0,0:18:51.32,0:18:52.73,Default,,0,0,0,,如果流是空的\nDialogue: 0,0:18:53.04,0:18:54.22,Default,,0,0,0,,就返回一个空流\nDialogue: 0,0:18:56.28,0:18:59.18,Default,,0,0,0,,这里 用谓词来判断流的头元素\nDialogue: 0,0:19:00.06,0:19:01.04,Default,,0,0,0,,如果为真\nDialogue: 0,0:19:01.53,0:19:02.83,Default,,0,0,0,,就把这个元素\nDialogue: 0,0:19:03.02,0:19:06.22,Default,,0,0,0,,和过滤流的尾元素得到的结果连接在一起\nDialogue: 0,0:19:08.22,0:19:10.04,Default,,0,0,0,,否则 如果谓词判断为假\nDialogue: 0,0:19:10.49,0:19:11.98,Default,,0,0,0,,就只返回过滤流的尾元素的结果\nDialogue: 0,0:19:13.50,0:19:14.46,Default,,0,0,0,,这就是过滤函数的原理\nDialogue: 0,0:19:16.59,0:19:18.56,Default,,0,0,0,,剩下的我快速过一遍\nDialogue: 0,0:19:18.56,0:19:20.70,Default,,0,0,0,,这些在书上都有 你们可以自己看\nDialogue: 0,0:19:20.88,0:19:21.80,Default,,0,0,0,,来马上过一遍\nDialogue: 0,0:19:22.11,0:19:22.94,Default,,0,0,0,,过程ACCUMULATE\nDialogue: 0,0:19:23.26,0:19:26.92,Default,,0,0,0,,ACCUMULATE的参数有：一个组合函数\nDialogue: 0,0:19:27.36,0:19:29.05,Default,,0,0,0,,一个初始值和一个流\nDialogue: 0,0:19:29.96,0:19:31.13,Default,,0,0,0,,将它们组合在一起\nDialogue: 0,0:19:31.56,0:19:33.69,Default,,0,0,0,,如果流为空 返回初始值\nDialogue: 0,0:19:33.97,0:19:36.20,Default,,0,0,0,,否则 我们就把流头部\nDialogue: 0,0:19:36.32,0:19:37.82,Default,,0,0,0,,和流尾部做ACCUMLATE的结果\nDialogue: 0,0:19:38.01,0:19:40.24,Default,,0,0,0,,组合起来\nDialogue: 0,0:19:40.90,0:19:42.83,Default,,0,0,0,,这就是把流中元素累积在一起的方法\nDialogue: 0,0:19:42.83,0:19:43.98,Default,,0,0,0,,我会用加法来累积\nDialogue: 0,0:19:45.83,0:19:47.56,Default,,0,0,0,,如何枚举树上的叶节点呢？\nDialogue: 0,0:19:48.06,0:19:52.89,Default,,0,0,0,,如果这个树只是一个叶节点\nDialogue: 0,0:19:53.79,0:19:55.90,Default,,0,0,0,,我就构造一个只含有一个叶子节点的流\nDialogue: 0,0:19:56.64,0:19:59.32,Default,,0,0,0,,否则的话 我就把\nDialogue: 0,0:19:59.61,0:20:02.35,Default,,0,0,0,,左、右子树枚举的结果合并起来\nDialogue: 0,0:20:04.34,0:20:08.32,Default,,0,0,0,,这里的APPEND-STREAM跟表上的APPEND类似\nDialogue: 0,0:20:13.19,0:20:13.85,Default,,0,0,0,,再来看这个\nDialogue: 0,0:20:13.85,0:20:17.53,Default,,0,0,0,,这跟和合并两个表的过程太相似了\nDialogue: 0,0:20:18.91,0:20:20.60,Default,,0,0,0,,如何枚举一个区间呢？\nDialogue: 0,0:20:21.96,0:20:23.77,Default,,0,0,0,,它有两个参数 LOW和HIGH\nDialogue: 0,0:20:23.88,0:20:27.00,Default,,0,0,0,,生成一个包含从LOW到HIGH的所有整数的流\nDialogue: 0,0:20:28.32,0:20:29.88,Default,,0,0,0,,由此 我们就可以构造一大堆的元件\nDialogue: 0,0:20:31.89,0:20:34.48,Default,,0,0,0,,这就是一门用来讨论流的小型语言\nDialogue: 0,0:20:34.49,0:20:35.32,Default,,0,0,0,,当我们有了流\nDialogue: 0,0:20:35.32,0:20:37.67,Default,,0,0,0,,就可以构建用于操作它们的过程\nDialogue: 0,0:20:37.67,0:20:39.04,Default,,0,0,0,,请注意 我们正在构建一门语言\nDialogue: 0,0:20:40.20,0:20:42.22,Default,,0,0,0,,现在 我们可以用这门语言来表达我们的想法\nDialogue: 0,0:20:43.06,0:20:47.31,Default,,0,0,0,,这个原始过程是累加树中奇数的平方的\nDialogue: 0,0:20:47.31,0:20:52.62,Default,,0,0,0,,现在你会发现 它和那些方块图如出一辙\nDialogue: 0,0:20:52.64,0:20:54.59,Default,,0,0,0,,跟我们的信号处理方块图相吻合\nDialogue: 0,0:20:54.59,0:20:57.53,Default,,0,0,0,,要计算树上奇数平方和\nDialogue: 0,0:20:58.06,0:21:00.80,Default,,0,0,0,,先枚举树上的叶子节点\nDialogue: 0,0:21:01.32,0:21:03.72,Default,,0,0,0,,过滤出奇数\nDialogue: 0,0:21:04.83,0:21:06.54,Default,,0,0,0,,再用平方来做映射\nDialogue: 0,0:21:09.32,0:21:13.34,Default,,0,0,0,,最后用加法来累积 初始值是0\nDialogue: 0,0:21:14.76,0:21:17.20,Default,,0,0,0,,这样我们就可以看到需要的片段\nDialogue: 0,0:21:17.29,0:21:19.36,Default,,0,0,0,,类似地 斐波那契数的那个问题\nDialogue: 0,0:21:20.04,0:21:21.88,Default,,0,0,0,,我们如何获得奇斐波那契数呢？\nDialogue: 0,0:21:22.05,0:21:24.57,Default,,0,0,0,,从1到N枚举整数\nDialogue: 0,0:21:26.32,0:21:28.64,Default,,0,0,0,,再把FIB过程映射到上面\nDialogue: 0,0:21:28.99,0:21:30.70,Default,,0,0,0,,用来求取每项斐波那契数\nDialogue: 0,0:21:30.92,0:21:33.79,Default,,0,0,0,,过滤出奇数的部分\nDialogue: 0,0:21:34.81,0:21:36.64,Default,,0,0,0,,最后 以空表为初始值\nDialogue: 0,0:21:36.88,0:21:39.12,Default,,0,0,0,,用CONS将它们积累起来\nDialogue: 0,0:21:43.65,0:21:47.53,Default,,0,0,0,,那么 这么做有什么优势呢？\nDialogue: 0,0:21:47.68,0:21:48.59,Default,,0,0,0,,首先一点\nDialogue: 0,0:21:48.68,0:21:51.15,Default,,0,0,0,,我们现在有可以用来混搭的元件了\nDialogue: 0,0:21:51.88,0:21:52.64,Default,,0,0,0,,比如说\nDialogue: 0,0:21:52.91,0:21:55.08,Default,,0,0,0,,如果我想把这里改变一下\nDialogue: 0,0:21:58.19,0:22:00.32,Default,,0,0,0,,想要计算整数的平方再进行过滤\nDialogue: 0,0:22:00.33,0:22:01.34,Default,,0,0,0,,我只需要\nDialogue: 0,0:22:01.90,0:22:03.64,Default,,0,0,0,,拿个像这里的MAP SQUARE这样的元件\nDialogue: 0,0:22:03.68,0:22:05.40,Default,,0,0,0,,放进去就行了\nDialogue: 0,0:22:06.57,0:22:07.60,Default,,0,0,0,,又或者 如果我们想\nDialogue: 0,0:22:07.69,0:22:11.45,Default,,0,0,0,,寻找树的叶节点对应的斐波那契数\nDialogue: 0,0:22:11.58,0:22:12.36,Default,,0,0,0,,而不是一个序列所对应的\nDialogue: 0,0:22:12.38,0:22:13.24,Default,,0,0,0,,我只需要\nDialogue: 0,0:22:13.40,0:22:15.93,Default,,0,0,0,,用这个枚举函数替换这个枚举函数\nDialogue: 0,0:22:18.03,0:22:19.82,Default,,0,0,0,,看到了吧 流处理的优势就是\nDialogue: 0,0:22:20.24,0:22:21.53,Default,,0,0,0,,我们建立了 --\nDialogue: 0,0:22:22.36,0:22:24.96,Default,,0,0,0,,这也是本课中的一个重要主题 --\nDialogue: 0,0:22:25.29,0:22:27.48,Default,,0,0,0,,我们建立了一个约定的接口\nDialogue: 0,0:22:32.89,0:22:37.15,Default,,0,0,0,,约定的接口可以让我们把事物粘合起来\nDialogue: 0,0:22:38.30,0:22:39.55,Default,,0,0,0,,像MAP和FILTER这样的东西\nDialogue: 0,0:22:39.79,0:22:41.64,Default,,0,0,0,,可以作为一组标准的组件\nDialogue: 0,0:22:41.68,0:22:44.76,Default,,0,0,0,,我们可以拿过来随意组合去构造程序\nDialogue: 0,0:22:45.75,0:22:48.81,Default,,0,0,0,,它让我们看到了程序的共性\nDialogue: 0,0:22:49.95,0:22:50.92,Default,,0,0,0,,虽然在这里\nDialogue: 0,0:22:51.08,0:22:53.07,Default,,0,0,0,,我只是给你们演示了两个过程而已\nDialogue: 0,0:22:53.86,0:22:55.16,Default,,0,0,0,,但是我要告诉你\nDialogue: 0,0:22:55.20,0:22:57.77,Default,,0,0,0,,像这种用MAP、FILTER和ACCUMULATE\nDialogue: 0,0:22:57.80,0:23:01.00,Default,,0,0,0,,组合起来构建程序的方式是非常非常通用的\nDialogue: 0,0:23:01.41,0:23:07.28,Default,,0,0,0,,这是一种“生成-测试”的编程范式\nDialogue: 0,0:23:07.77,0:23:09.10,Default,,0,0,0,,举例来看\nDialogue: 0,0:23:09.39,0:23:12.94,Default,,0,0,0,,Richarc Waters -- MIT的一名硕士生\nDialogue: 0,0:23:12.96,0:23:15.26,Default,,0,0,0,,他的学位论文的一部分调研了\nDialogue: 0,0:23:15.80,0:23:19.21,Default,,0,0,0,,IBM的科学计算程序库的主要代码\nDialogue: 0,0:23:19.82,0:23:23.31,Default,,0,0,0,,发现其中60%的程序\nDialogue: 0,0:23:24.06,0:23:28.25,Default,,0,0,0,,都可以用这样的范式来准确的表示出来\nDialogue: 0,0:23:28.86,0:23:30.17,Default,,0,0,0,,只用MAP、FILTER和ACCUMULATE\nDialogue: 0,0:23:30.57,0:23:31.50,Default,,0,0,0,,好 让我们休息一会\nDialogue: 0,0:23:36.59,0:23:37.12,Default,,0,0,0,,有问题吗？\nDialogue: 0,0:23:41.18,0:23:42.89,Default,,0,0,0,,学生：整件事情的本质好像只是\nDialogue: 0,0:23:42.89,0:23:45.96,Default,,0,0,0,,因为你用了一个统一、简单的数据结构\nDialogue: 0,0:23:46.25,0:23:47.66,Default,,0,0,0,,也就是流\nDialogue: 0,0:23:48.38,0:23:48.92,Default,,0,0,0,,教授：对\nDialogue: 0,0:23:48.92,0:23:50.38,Default,,0,0,0,,本质就是\nDialogue: 0,0:23:50.40,0:23:53.07,Default,,0,0,0,,用这种约定的接口\nDialogue: 0,0:23:53.71,0:23:55.61,Default,,0,0,0,,因此你可以把许多东西组合起来\nDialogue: 0,0:23:56.01,0:23:58.78,Default,,0,0,0,,流只是 就像你说的\nDialogue: 0,0:23:58.78,0:24:00.89,Default,,0,0,0,,只是一种可以支持那样操作的统一的数据结构而已\nDialogue: 0,0:24:00.89,0:24:02.84,Default,,0,0,0,,顺便说下 这非常像APL\nDialogue: 0,0:24:03.60,0:24:05.21,Default,,0,0,0,,APL有着非常相似的思想\nDialogue: 0,0:24:05.21,0:24:06.96,Default,,0,0,0,,只是在APL中使用的不是流\nDialogue: 0,0:24:07.13,0:24:08.44,Default,,0,0,0,,而是使用数组和向量\nDialogue: 0,0:24:09.56,0:24:14.48,Default,,0,0,0,,而且APL的威力就在于此\nDialogue: 0,0:24:19.91,0:24:20.91,Default,,0,0,0,,好吧 谢谢\nDialogue: 0,0:24:20.91,0:24:21.66,Default,,0,0,0,,休息一下\nDialogue: 0,0:24:21.66,0:24:30.35,Default,,0,0,0,,[音乐]\nDialogue: 0,0:24:30.44,0:24:35.77,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:24:41.00,0:24:45.39,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:24:45.42,0:24:47.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:24:47.98,0:24:52.70,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 I\nDialogue: 0,0:24:57.47,0:24:57.61,Default,,0,0,0,,好的\nDialogue: 0,0:24:57.61,0:24:58.59,Default,,0,0,0,,我们已经见识过了\nDialogue: 0,0:25:00.54,0:25:03.20,Default,,0,0,0,,如何用流来组织计算过程\nDialogue: 0,0:25:03.85,0:25:05.47,Default,,0,0,0,,但是现在我想要给你们再演示两个\nDialogue: 0,0:25:05.93,0:25:09.12,Default,,0,0,0,,更复杂的例子\nDialogue: 0,0:25:10.84,0:25:14.12,Default,,0,0,0,,我们先来考虑一下\nDialogue: 0,0:25:14.20,0:25:16.81,Default,,0,0,0,,这样一种有用的过程\nDialogue: 0,0:25:16.81,0:25:18.09,Default,,0,0,0,,假设我有一个流\nDialogue: 0,0:25:19.96,0:25:23.15,Default,,0,0,0,,流中的元素本身就是一个流\nDialogue: 0,0:25:23.98,0:25:26.53,Default,,0,0,0,,一开始是1、2、3\nDialogue: 0,0:25:32.72,0:25:33.88,Default,,0,0,0,,就是这样的一个流\nDialogue: 0,0:25:33.88,0:25:40.10,Default,,0,0,0,,流中的元素也是一个流\nDialogue: 0,0:25:40.97,0:25:43.42,Default,,0,0,0,,而我想要构建出一个流\nDialogue: 0,0:25:43.64,0:25:46.75,Default,,0,0,0,,用来收集所有的元素\nDialogue: 0,0:25:46.76,0:25:49.24,Default,,0,0,0,,把所有元素从子流中提取出来\nDialogue: 0,0:25:50.11,0:25:51.82,Default,,0,0,0,,最后把它们串接在一起\nDialogue: 0,0:25:52.27,0:25:55.61,Default,,0,0,0,,为了凸显使用这门语言多么简单\nDialogue: 0,0:25:56.11,0:25:57.10,Default,,0,0,0,,我们来定义这个FLATTEN过程\nDialogue: 0,0:25:57.95,0:26:10.64,Default,,0,0,0,,FLATTEN过程的参数是由流构成的流\nDialogue: 0,0:26:12.89,0:26:13.80,Default,,0,0,0,,那么 具体定义是怎样的呢？\nDialogue: 0,0:26:13.96,0:26:16.24,Default,,0,0,0,,它只是一个累积\nDialogue: 0,0:26:16.32,0:26:25.05,Default,,0,0,0,,我想用APPEND来做累积\nDialogue: 0,0:26:25.07,0:26:26.45,Default,,0,0,0,,也就是不断地做APPEND\nDialogue: 0,0:26:26.73,0:26:29.29,Default,,0,0,0,,所以我用APPEND-STREAM做累积\nDialogue: 0,0:26:35.90,0:26:48.20,Default,,0,0,0,,以THE-EMPTY-STREAM为初始值 累积这个流\nDialogue: 0,0:26:54.84,0:26:55.84,Default,,0,0,0,,这个例子告诉我们\nDialogue: 0,0:26:56.92,0:26:59.23,Default,,0,0,0,,你可以使用这些高阶过程\nDialogue: 0,0:26:59.60,0:27:00.83,Default,,0,0,0,,来做一些有趣的运算\nDialogue: 0,0:27:00.83,0:27:05.10,Default,,0,0,0,,事实上 我还想定义另一个实用过程\nDialogue: 0,0:27:05.10,0:27:07.05,Default,,0,0,0,,定义一个过程FLAT-MAP\nDialogue: 0,0:27:17.18,0:27:20.59,Default,,0,0,0,,它以一个过程和一个流为参数\nDialogue: 0,0:27:21.84,0:27:25.72,Default,,0,0,0,,其中S是一个流\nDialogue: 0,0:27:25.72,0:27:27.69,Default,,0,0,0,,F是一个过程\nDialogue: 0,0:27:27.72,0:27:30.62,Default,,0,0,0,,它作用于流中的每个元素 并产生一个新的流\nDialogue: 0,0:27:31.95,0:27:34.52,Default,,0,0,0,,我想从这些流中取出所有的元素\nDialogue: 0,0:27:35.00,0:27:36.00,Default,,0,0,0,,并把它们组合在一起\nDialogue: 0,0:27:36.00,0:27:49.13,Default,,0,0,0,,所以对应的代码就是 (FLATTEN (MAP F S))\nDialogue: 0,0:27:51.20,0:27:53.04,Default,,0,0,0,,每当我将F应用在S的某个元素上\nDialogue: 0,0:27:53.05,0:27:53.85,Default,,0,0,0,,我得到了一个流\nDialogue: 0,0:27:54.29,0:27:55.24,Default,,0,0,0,,执行完这条MAP语句后\nDialogue: 0,0:27:55.24,0:27:56.27,Default,,0,0,0,,我得到了一个由流构成的流\nDialogue: 0,0:27:56.46,0:27:57.42,Default,,0,0,0,,再把它进行FLATTEN\nDialogue: 0,0:27:58.67,0:28:02.64,Default,,0,0,0,,我想再使用这种方式\nDialogue: 0,0:28:03.87,0:28:05.84,Default,,0,0,0,,来解决另一个大家很熟悉的问题\nDialogue: 0,0:28:06.51,0:28:12.27,Default,,0,0,0,,这个问题和我们以前遇到过的许多问题一样\nDialogue: 0,0:28:12.28,0:28:13.96,Default,,0,0,0,,只是有些变型\nDialogue: 0,0:28:14.19,0:28:15.49,Default,,0,0,0,,给定整数N\nDialogue: 0,0:28:18.68,0:28:19.93,Default,,0,0,0,,我们的问题是\nDialogue: 0,0:28:21.20,0:28:31.53,Default,,0,0,0,,找出所有的整数序对(I, J)\nDialogue: 0,0:28:32.30,0:28:39.96,Default,,0,0,0,,其中 0 < J < I <= N\nDialogue: 0,0:28:42.33,0:28:52.03,Default,,0,0,0,,使得 I+J 是一个质数\nDialogue: 0,0:28:55.74,0:28:57.92,Default,,0,0,0,,如果N=6\nDialogue: 0,0:28:59.74,0:29:00.78,Default,,0,0,0,,我在这儿画个小表格\nDialogue: 0,0:29:01.55,0:29:06.67,Default,,0,0,0,,表头是I、J和I+J\nDialogue: 0,0:29:09.70,0:29:14.91,Default,,0,0,0,,比如说I=2 J=1 那么I+J就是3\nDialogue: 0,0:29:15.52,0:29:20.38,Default,,0,0,0,,然后I=3 J=2 那么I+J就是5\nDialogue: 0,0:29:21.21,0:29:26.51,Default,,0,0,0,,I=4 J=1 I+J=5也是一样的 等等\nDialogue: 0,0:29:26.92,0:29:28.11,Default,,0,0,0,,直到I到了6就终止了\nDialogue: 0,0:29:28.40,0:29:32.54,Default,,0,0,0,,我想要这个过程产生并返回这样的一个流\nDialogue: 0,0:29:33.20,0:29:37.04,Default,,0,0,0,,就是像 (I, J, I+J) 这样的三元组组成的流\nDialogue: 0,0:29:37.66,0:29:39.55,Default,,0,0,0,,对于每个整数N 我想得到一个这样流\nDialogue: 0,0:29:40.97,0:29:43.68,Default,,0,0,0,,听起来很简单\nDialogue: 0,0:29:43.68,0:29:44.35,Default,,0,0,0,,我们做做看\nDialogue: 0,0:29:47.23,0:29:48.22,Default,,0,0,0,,先这样开始\nDialogue: 0,0:29:50.15,0:29:54.25,Default,,0,0,0,,对于每一个整数 I\nDialogue: 0,0:29:55.24,0:29:56.44,Default,,0,0,0,,生成一个流\nDialogue: 0,0:29:57.00,0:29:58.59,Default,,0,0,0,,对于I从1取到N\nDialogue: 0,0:29:58.59,0:29:59.76,Default,,0,0,0,,每个I都生成一个流\nDialogue: 0,0:30:00.66,0:30:01.80,Default,,0,0,0,,这个流将会是什么样子？\nDialogue: 0,0:30:02.23,0:30:04.04,Default,,0,0,0,,我们先生成所有的序对\nDialogue: 0,0:30:04.18,0:30:07.55,Default,,0,0,0,,对于每个I 我们先生成\nDialogue: 0,0:30:08.43,0:30:14.52,Default,,0,0,0,,对于每个从1取到I-1的J\nDialogue: 0,0:30:16.91,0:30:17.98,Default,,0,0,0,,我们先生成序对\nDialogue: 0,0:30:18.35,0:30:20.71,Default,,0,0,0,,也就是只含有I和J的表\nDialogue: 0,0:30:23.78,0:30:27.10,Default,,0,0,0,,因此我们对整个区间做映射\nDialogue: 0,0:30:28.60,0:30:29.74,Default,,0,0,0,,生成序对\nDialogue: 0,0:30:31.07,0:30:33.17,Default,,0,0,0,,对于每个I 都生成一个序对流\nDialogue: 0,0:30:33.40,0:30:34.49,Default,,0,0,0,,最后进行FLATMAP\nDialogue: 0,0:30:34.59,0:30:36.20,Default,,0,0,0,,这样我们就生成了所有的(I, J)序对\nDialogue: 0,0:30:36.81,0:30:38.08,Default,,0,0,0,,其中I <= J\nDialogue: 0,0:30:38.73,0:30:39.85,Default,,0,0,0,,就是这样\nDialogue: 0,0:30:39.85,0:30:40.76,Default,,0,0,0,,紧接着就是过滤\nDialogue: 0,0:30:42.99,0:30:45.84,Default,,0,0,0,,我们对刚才FLATMAP得到的东西\nDialogue: 0,0:30:46.94,0:30:51.37,Default,,0,0,0,,我们以I -- 这里分别是 I 和 J\nDialogue: 0,0:30:51.66,0:30:54.17,Default,,0,0,0,,I是表的第一个元素\nDialogue: 0,0:30:54.30,0:30:55.60,Default,,0,0,0,,J是第二个\nDialogue: 0,0:30:57.21,0:31:00.01,Default,,0,0,0,,我们用一个谓词来判断 表中的两个元素\nDialogue: 0,0:31:00.22,0:31:02.00,Default,,0,0,0,,也就是表的CAR部分与CDR部分之和 是否为质数\nDialogue: 0,0:31:02.07,0:31:05.52,Default,,0,0,0,,用这个谓词来过滤刚刚收集起来的表\nDialogue: 0,0:31:06.54,0:31:07.85,Default,,0,0,0,,就得到了我们想要的表\nDialogue: 0,0:31:09.42,0:31:10.24,Default,,0,0,0,,然后我们继续\nDialogue: 0,0:31:10.88,0:31:13.10,Default,,0,0,0,,把过滤得到的结果 再次进行MAP操作\nDialogue: 0,0:31:13.26,0:31:19.05,Default,,0,0,0,,用来生成 I、J 和 I+J 构成的表\nDialogue: 0,0:31:19.61,0:31:21.39,Default,,0,0,0,,这就是过程 PRIME-SUM-PAIRS\nDialogue: 0,0:31:22.57,0:31:24.76,Default,,0,0,0,,最后只需要过一遍 这就是整个过程\nDialogue: 0,0:31:28.08,0:31:30.97,Default,,0,0,0,,一个MAP、一个FILTER 以及一个FLATMAP\nDialogue: 0,0:31:34.85,0:31:35.66,Default,,0,0,0,,所有的东西都在这里了\nDialogue: 0,0:31:35.66,0:31:37.12,Default,,0,0,0,,尽管可读性不是那么好\nDialogue: 0,0:31:37.42,0:31:38.94,Default,,0,0,0,,我们只是把中间过程展开了\nDialogue: 0,0:31:39.84,0:31:40.88,Default,,0,0,0,,这个例子\nDialogue: 0,0:31:43.28,0:31:45.00,Default,,0,0,0,,向我们展示了\nDialogue: 0,0:31:45.12,0:31:46.30,Default,,0,0,0,,嵌套循环\nDialogue: 0,0:31:47.66,0:31:50.09,Default,,0,0,0,,在这个过程中 它看起来就像\nDialogue: 0,0:31:50.11,0:31:52.81,Default,,0,0,0,,各种嵌套的MAP和FLATMAP的组合\nDialogue: 0,0:31:54.27,0:31:57.61,Default,,0,0,0,,所以我们不仅仅可以枚举单个个体\nDialogue: 0,0:31:57.61,0:31:58.81,Default,,0,0,0,,通过使用FLATMAP\nDialogue: 0,0:31:59.12,0:32:02.24,Default,,0,0,0,,我们可以实现其它语言中的嵌套循环\nDialogue: 0,0:32:03.23,0:32:03.76,Default,,0,0,0,,当然\nDialogue: 0,0:32:04.91,0:32:08.03,Default,,0,0,0,,重复写这些FLATMAP很烦人\nDialogue: 0,0:32:08.41,0:32:13.00,Default,,0,0,0,,尽管PRIME-SUM-PAIRS其中单独的部分很容易\nDialogue: 0,0:32:13.56,0:32:15.28,Default,,0,0,0,,但整体看起来还是十分复杂\nDialogue: 0,0:32:15.48,0:32:17.13,Default,,0,0,0,,如果你愿意的话 可以\nDialogue: 0,0:32:17.15,0:32:20.12,Default,,0,0,0,,引进一个叫COLLECT的语法糖衣\nDialogue: 0,0:32:21.04,0:32:22.68,Default,,0,0,0,,COLLECT只是一个缩写\nDialogue: 0,0:32:22.91,0:32:26.16,Default,,0,0,0,,用来代表特定顺序的FLATMAP和FILTER操作\nDialogue: 0,0:32:26.16,0:32:28.60,Default,,0,0,0,,这里我们用COLLECT把PRIME-SUM-PAIRS写一遍\nDialogue: 0,0:32:29.45,0:32:36.27,Default,,0,0,0,,PRIME-SUM-PAIRS过程需要收集这样一个东西\nDialogue: 0,0:32:36.52,0:32:39.20,Default,,0,0,0,,它的元素是形如(I, J, I+J)这样的表\nDialogue: 0,0:32:40.84,0:32:45.39,Default,,0,0,0,,而这将通过I从1取到N\nDialogue: 0,0:32:47.44,0:32:52.32,Default,,0,0,0,,同时J要从1取到I-1来产生\nDialogue: 0,0:32:54.16,0:32:56.54,Default,,0,0,0,,并且要满足I+J是质数\nDialogue: 0,0:32:58.04,0:33:00.32,Default,,0,0,0,,课堂上我就不讲解如何定义COLLECT了\nDialogue: 0,0:33:00.69,0:33:02.75,Default,,0,0,0,,书上面有\nDialogue: 0,0:33:03.42,0:33:05.45,Default,,0,0,0,,不过你可以清楚地看到 这些代码片段\nDialogue: 0,0:33:05.84,0:33:08.60,Default,,0,0,0,,就是我原先写的过程中的片段\nDialogue: 0,0:33:08.82,0:33:11.40,Default,,0,0,0,,COLLECT过程只是一个语法糖衣\nDialogue: 0,0:33:11.44,0:33:14.80,Default,,0,0,0,,用来自动生成嵌套FLATMAP\nDialogue: 0,0:33:16.31,0:33:20.33,Default,,0,0,0,,好的 我们再来看另一个例子\nDialogue: 0,0:33:20.67,0:33:22.00,Default,,0,0,0,,也展示了同样的道理\nDialogue: 0,0:33:22.12,0:33:23.53,Default,,0,0,0,,这是一个非常著名的问题\nDialogue: 0,0:33:24.70,0:33:28.75,Default,,0,0,0,,经常用来演示所谓的“回溯”算法\nDialogue: 0,0:33:28.76,0:33:30.20,Default,,0,0,0,,这就是“八皇后问题”\nDialogue: 0,0:33:30.20,0:33:31.08,Default,,0,0,0,,这是一个棋盘\nDialogue: 0,0:33:32.37,0:33:33.64,Default,,0,0,0,,八皇后问题要求我们\nDialogue: 0,0:33:33.64,0:33:35.85,Default,,0,0,0,,找到一种将八个皇后放到棋盘上的摆法\nDialogue: 0,0:33:36.44,0:33:38.00,Default,,0,0,0,,使得任意的两个皇后不会相互攻击\nDialogue: 0,0:33:38.00,0:33:40.60,Default,,0,0,0,,这里给出了一个解法\nDialogue: 0,0:33:41.21,0:33:43.68,Default,,0,0,0,,我需要保证摆放好后\nDialogue: 0,0:33:43.71,0:33:46.80,Default,,0,0,0,,任意两个皇后不在同一行或同一列上\nDialogue: 0,0:33:47.72,0:33:49.47,Default,,0,0,0,,也不在同一对角线上\nDialogue: 0,0:33:51.41,0:33:56.40,Default,,0,0,0,,有一个解决这个问题的标准解法\nDialogue: 0,0:33:59.74,0:34:01.48,Default,,0,0,0,,首先我们要做是\nDialogue: 0,0:34:02.54,0:34:04.62,Default,,0,0,0,,进入底层 站在George的层面\nDialogue: 0,0:34:04.94,0:34:08.09,Default,,0,0,0,,找到一种表示棋盘与位置的方式\nDialogue: 0,0:34:08.09,0:34:09.52,Default,,0,0,0,,这个并不需要太担心\nDialogue: 0,0:34:09.80,0:34:12.78,Default,,0,0,0,,假设我们有一个谓词SAFE?\nDialogue: 0,0:34:16.14,0:34:17.55,Default,,0,0,0,,SAFE?判断的是\nDialogue: 0,0:34:17.96,0:34:20.84,Default,,0,0,0,,假如一些皇后已经放在棋盘上\nDialogue: 0,0:34:21.36,0:34:24.54,Default,,0,0,0,,在这个点再放置一个皇后是否是安全？\nDialogue: 0,0:34:25.40,0:34:31.26,Default,,0,0,0,,所以SAFE?的参数分别为ROW和COLUMN\nDialogue: 0,0:34:32.76,0:34:35.47,Default,,0,0,0,,我将尝试把下一个皇后放在那个地方\nDialogue: 0,0:34:36.06,0:34:42.76,Default,,0,0,0,,另外一个参数是剩下的位置\nDialogue: 0,0:34:45.58,0:34:46.75,Default,,0,0,0,,SAFE?要判断的是\nDialogue: 0,0:34:46.86,0:34:51.68,Default,,0,0,0,,在这些位置已经放置了皇后的情况下\nDialogue: 0,0:34:53.02,0:34:54.76,Default,,0,0,0,,在这行这列放置皇后\nDialogue: 0,0:34:55.10,0:34:57.20,Default,,0,0,0,,是否安全\nDialogue: 0,0:34:58.30,0:34:59.36,Default,,0,0,0,,不用过分深究这个\nDialogue: 0,0:34:59.36,0:35:01.38,Default,,0,0,0,,那是George的问题 也不难写出来\nDialogue: 0,0:35:01.38,0:35:06.27,Default,,0,0,0,,只需要检测该行、该列\nDialogue: 0,0:35:06.30,0:35:08.52,Default,,0,0,0,,以及对角线上是否有东西即可\nDialogue: 0,0:35:10.53,0:35:13.12,Default,,0,0,0,,那么 有了这个过程后 我们的程序该如何组织呢？\nDialogue: 0,0:35:13.84,0:35:17.21,Default,,0,0,0,,有一种传统的方式\nDialogue: 0,0:35:17.93,0:35:18.97,Default,,0,0,0,,我们称为“回溯”\nDialogue: 0,0:35:20.52,0:35:23.21,Default,,0,0,0,,首先让我们来考虑\nDialogue: 0,0:35:25.13,0:35:28.88,Default,,0,0,0,,把第一个皇后放在第一列的\nDialogue: 0,0:35:30.04,0:35:31.34,Default,,0,0,0,,所有方式\nDialogue: 0,0:35:31.45,0:35:32.24,Default,,0,0,0,,有8种\nDialogue: 0,0:35:32.58,0:35:35.00,Default,,0,0,0,,先试下第一列\nDialogue: 0,0:35:35.88,0:35:37.30,Default,,0,0,0,,第一行第一列\nDialogue: 0,0:35:37.30,0:35:38.70,Default,,0,0,0,,每个分支都代表了\nDialogue: 0,0:35:40.17,0:35:41.88,Default,,0,0,0,,在每一个层次的可能解\nDialogue: 0,0:35:43.36,0:35:45.53,Default,,0,0,0,,我试着把皇后放在第一列\nDialogue: 0,0:35:46.14,0:35:47.74,Default,,0,0,0,,现在 我在第一列放置好一个皇后以后\nDialogue: 0,0:35:47.77,0:35:49.98,Default,,0,0,0,,我又尝试在第一列放置下一个皇后\nDialogue: 0,0:35:50.60,0:35:52.17,Default,,0,0,0,,并不成功 它们都……\nDialogue: 0,0:35:53.31,0:35:54.60,Default,,0,0,0,,我尝试把第一个皇后\nDialogue: 0,0:35:54.86,0:35:56.80,Default,,0,0,0,,把在第一列上的那个皇后 放在第一行\nDialogue: 0,0:35:56.92,0:35:57.47,Default,,0,0,0,,不好意思\nDialogue: 0,0:35:59.05,0:36:01.39,Default,,0,0,0,,放好后 我们再把下一个皇后放在第一行\nDialogue: 0,0:36:01.39,0:36:02.09,Default,,0,0,0,,这不行\nDialogue: 0,0:36:02.09,0:36:03.18,Default,,0,0,0,,所以又回到这里\nDialogue: 0,0:36:04.20,0:36:04.72,Default,,0,0,0,,然后再考虑\nDialogue: 0,0:36:04.83,0:36:06.86,Default,,0,0,0,,我们把这个皇后放在第二行吗？\nDialogue: 0,0:36:07.32,0:36:08.38,Default,,0,0,0,,然而也不行\nDialogue: 0,0:36:08.55,0:36:09.76,Default,,0,0,0,,那么放在第三行呢？\nDialogue: 0,0:36:09.76,0:36:10.52,Default,,0,0,0,,这样可以\nDialogue: 0,0:36:12.79,0:36:15.13,Default,,0,0,0,,下一个皇后可以放在第一列吗？\nDialogue: 0,0:36:15.38,0:36:17.82,Default,,0,0,0,,我不能再画更多的棋盘了\nDialogue: 0,0:36:17.82,0:36:18.86,Default,,0,0,0,,但我先假设这个可行\nDialogue: 0,0:36:19.19,0:36:20.45,Default,,0,0,0,,我尝试下一个\nDialogue: 0,0:36:20.45,0:36:24.17,Default,,0,0,0,,在每一个地方 尽可能的沿着树往下\nDialogue: 0,0:36:24.54,0:36:25.64,Default,,0,0,0,,然后回退\nDialogue: 0,0:36:25.64,0:36:28.97,Default,,0,0,0,,如果我从这里往下走 发现下面不可能有解\nDialogue: 0,0:36:29.00,0:36:30.12,Default,,0,0,0,,我就回溯到这里来\nDialogue: 0,0:36:30.28,0:36:32.44,Default,,0,0,0,,然后开始生成这个子树\nDialogue: 0,0:36:33.26,0:36:34.32,Default,,0,0,0,,我就像这样遍历\nDialogue: 0,0:36:35.05,0:36:37.26,Default,,0,0,0,,最后 一路求解下来\nDialogue: 0,0:36:37.72,0:36:38.59,Default,,0,0,0,,就会得到答案\nDialogue: 0,0:36:39.82,0:36:41.98,Default,,0,0,0,,这种典型的范式\nDialogue: 0,0:36:43.12,0:36:45.93,Default,,0,0,0,,之前被广泛地使用在人工智能编程中\nDialogue: 0,0:36:45.93,0:36:47.30,Default,,0,0,0,,术语叫做 “回溯搜索”\nDialogue: 0,0:36:57.47,0:37:03.04,Default,,0,0,0,,这真的没有必要\nDialogue: 0,0:37:03.86,0:37:06.55,Default,,0,0,0,,你们也发现了 我在可视化这个过程时也犯了迷糊\nDialogue: 0,0:37:06.81,0:37:08.25,Default,,0,0,0,,你们也看到了复杂程度\nDialogue: 0,0:37:08.55,0:37:10.76,Default,,0,0,0,,而且这种复杂还很难描述\nDialogue: 0,0:37:10.76,0:37:11.82,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:37:12.39,0:37:13.29,Default,,0,0,0,,这是因为\nDialogue: 0,0:37:13.53,0:37:17.39,Default,,0,0,0,,这是因为这程序过分地关注于时间了\nDialogue: 0,0:37:18.58,0:37:20.43,Default,,0,0,0,,这之中太多 -- 先试试这个 再试试这个\nDialogue: 0,0:37:20.49,0:37:22.38,Default,,0,0,0,,再回到上一个可行的地方 -- 这种操作太多了\nDialogue: 0,0:37:22.89,0:37:24.34,Default,,0,0,0,,这很复杂\nDialogue: 0,0:37:24.34,0:37:26.36,Default,,0,0,0,,如果我们不再如此关注时间\nDialogue: 0,0:37:28.04,0:37:29.76,Default,,0,0,0,,就有一个更简单的方式来描述\nDialogue: 0,0:37:31.20,0:37:32.36,Default,,0,0,0,,让我们来想象一下\nDialogue: 0,0:37:33.31,0:37:36.57,Default,,0,0,0,,现在我有\nDialogue: 0,0:37:38.32,0:37:42.16,Default,,0,0,0,,有一个高达K-1层的树\nDialogue: 0,0:37:43.40,0:37:46.32,Default,,0,0,0,,假设我已经有了\nDialogue: 0,0:37:48.09,0:37:52.19,Default,,0,0,0,,把皇后放在前K列的所有解法\nDialogue: 0,0:37:53.56,0:37:54.61,Default,,0,0,0,,假设是这样\nDialogue: 0,0:37:54.61,0:37:55.79,Default,,0,0,0,,不要担心我是怎么得到的\nDialogue: 0,0:37:57.07,0:37:59.20,Default,,0,0,0,,现在 如何扩充下去呢？\nDialogue: 0,0:37:59.20,0:38:02.16,Default,,0,0,0,,怎样找到在下一列中放皇后的所有可行方法？\nDialogue: 0,0:38:02.48,0:38:03.13,Default,,0,0,0,,很简单\nDialogue: 0,0:38:03.62,0:38:06.41,Default,,0,0,0,,对于已有的位置\nDialogue: 0,0:38:07.82,0:38:13.96,Default,,0,0,0,,我考虑把下一个皇后放在每一行上\nDialogue: 0,0:38:15.08,0:38:16.16,Default,,0,0,0,,来构建出下一步的棋局\nDialogue: 0,0:38:16.16,0:38:17.29,Default,,0,0,0,,然后 把所有放置的位置\nDialogue: 0,0:38:17.44,0:38:19.71,Default,,0,0,0,,用SAFE?进行过滤\nDialogue: 0,0:38:21.80,0:38:22.99,Default,,0,0,0,,不像之前那样\nDialogue: 0,0:38:22.99,0:38:24.67,Default,,0,0,0,,把这个树看做是逐步生成的\nDialogue: 0,0:38:24.94,0:38:26.86,Default,,0,0,0,,我们假设所有的东西都生成好了\nDialogue: 0,0:38:29.68,0:38:32.41,Default,,0,0,0,,为了从K-1层扩展到K层\nDialogue: 0,0:38:32.64,0:38:36.24,Default,,0,0,0,,我只需要扩展所有可能的放置方法\nDialogue: 0,0:38:36.48,0:38:37.80,Default,,0,0,0,,最后保留安全的排列\nDialogue: 0,0:38:37.80,0:38:39.23,Default,,0,0,0,,就得到一个K层树的结果\nDialogue: 0,0:38:39.30,0:38:40.67,Default,,0,0,0,,这是解决八皇后问题\nDialogue: 0,0:38:40.89,0:38:42.17,Default,,0,0,0,,的一个递归策略\nDialogue: 0,0:38:44.53,0:38:45.34,Default,,0,0,0,,好的 我们来看看\nDialogue: 0,0:38:50.33,0:38:52.68,Default,,0,0,0,,我们编写子过程FILL-COLS\nDialogue: 0,0:38:53.00,0:38:55.53,Default,,0,0,0,,来解决在一个特定大小棋盘上的\nDialogue: 0,0:38:58.92,0:39:01.03,Default,,0,0,0,,八皇后问题\nDialogue: 0,0:39:01.13,0:39:04.86,Default,,0,0,0,,这个过程会把皇后放置到K个列中\nDialogue: 0,0:39:06.35,0:39:07.70,Default,,0,0,0,,这是递归的模式\nDialogue: 0,0:39:07.70,0:39:10.92,Default,,0,0,0,,最后会以棋盘的大小为参数 调用FILL-COLS\nDialogue: 0,0:39:12.99,0:39:15.28,Default,,0,0,0,,FILL-COLS是用来说明\nDialogue: 0,0:39:15.29,0:39:17.16,Default,,0,0,0,,如何安全地把皇后放置在\nDialogue: 0,0:39:17.20,0:39:19.58,Default,,0,0,0,,具有SIZE行的棋盘的前K列\nDialogue: 0,0:39:20.36,0:39:21.64,Default,,0,0,0,,如果K是0\nDialogue: 0,0:39:22.27,0:39:23.60,Default,,0,0,0,,就不用做什么\nDialogue: 0,0:39:23.94,0:39:25.93,Default,,0,0,0,,结果是一个空棋盘\nDialogue: 0,0:39:26.71,0:39:28.07,Default,,0,0,0,,否则就做点别的\nDialogue: 0,0:39:28.35,0:39:29.44,Default,,0,0,0,,这里将要使用COLLECT\nDialogue: 0,0:39:30.81,0:39:31.77,Default,,0,0,0,,完整的代码在这里\nDialogue: 0,0:39:34.33,0:39:41.91,Default,,0,0,0,,我找到了所有在前K-1列中放皇后的方法\nDialogue: 0,0:39:42.19,0:39:43.32,Default,,0,0,0,,这是我所假设的\nDialogue: 0,0:39:43.32,0:39:46.36,Default,,0,0,0,,想像这棵树下降到K-1层\nDialogue: 0,0:39:48.88,0:39:52.11,Default,,0,0,0,,然后我尝试每一行\nDialogue: 0,0:39:52.52,0:39:54.13,Default,,0,0,0,,尝试每一个可行的行\nDialogue: 0,0:39:54.13,0:39:55.04,Default,,0,0,0,,总共SIZE行\nDialogue: 0,0:39:55.31,0:39:56.49,Default,,0,0,0,,这里枚举了所有行数\nDialogue: 0,0:39:58.04,0:39:59.79,Default,,0,0,0,,现在要做的是\nDialogue: 0,0:40:03.15,0:40:05.82,Default,,0,0,0,,把我将要尝试的新行和第K列\nDialogue: 0,0:40:07.95,0:40:08.95,Default,,0,0,0,,收集起来\nDialogue: 0,0:40:08.95,0:40:10.09,Default,,0,0,0,,我邻接一个位置\nDialogue: 0,0:40:10.20,0:40:11.29,Default,,0,0,0,,这是George的问题了\nDialogue: 0,0:40:11.29,0:40:12.75,Default,,0,0,0,,实现ADJOIN-POSITION和SAFE?都是George的工作\nDialogue: 0,0:40:13.64,0:40:15.28,Default,,0,0,0,,这个过程需要的参数有\nDialogue: 0,0:40:15.50,0:40:17.04,Default,,0,0,0,,ROW、COL以及REST-OF-POS\nDialogue: 0,0:40:17.07,0:40:19.02,Default,,0,0,0,,然后返回位置的集合\nDialogue: 0,0:40:19.66,0:40:25.77,Default,,0,0,0,,我把新的行和列\nDialogue: 0,0:40:26.06,0:40:27.68,Default,,0,0,0,,和剩下的皇后邻接起来\nDialogue: 0,0:40:28.57,0:40:29.76,Default,,0,0,0,,那些剩下的皇后\nDialogue: 0,0:40:29.92,0:40:31.45,Default,,0,0,0,,会尝试所有的\nDialogue: 0,0:40:31.87,0:40:34.16,Default,,0,0,0,,放置在K-1列中的可行解\nDialogue: 0,0:40:34.62,0:40:37.04,Default,,0,0,0,,新的行遍历了所有的可能性\nDialogue: 0,0:40:37.85,0:40:40.76,Default,,0,0,0,,过滤出安全的位置\nDialogue: 0,0:40:43.24,0:40:44.70,Default,,0,0,0,,这就是整个程序了\nDialogue: 0,0:40:46.33,0:40:47.31,Default,,0,0,0,,整个过程\nDialogue: 0,0:40:49.84,0:40:52.43,Default,,0,0,0,,它不仅找到了八皇后的问题的解\nDialogue: 0,0:40:53.42,0:40:56.68,Default,,0,0,0,,它还给出了所有的解\nDialogue: 0,0:40:56.68,0:40:58.48,Default,,0,0,0,,运行结束之后 就得到一个流\nDialogue: 0,0:40:58.48,0:41:01.90,Default,,0,0,0,,流中的元素是所有的解\nDialogue: 0,0:41:05.31,0:41:06.26,Default,,0,0,0,,为什么这个更简单一点呢？\nDialogue: 0,0:41:06.26,0:41:08.54,Default,,0,0,0,,我们完全没有把这个当做\nDialogue: 0,0:41:08.88,0:41:11.52,Default,,0,0,0,,按时间发生的、具有状态的过程\nDialogue: 0,0:41:12.72,0:41:14.42,Default,,0,0,0,,我们只说 这是一些东西的集合\nDialogue: 0,0:41:14.94,0:41:16.00,Default,,0,0,0,,这是它更加简单的原因\nDialogue: 0,0:41:18.00,0:41:20.11,Default,,0,0,0,,我们已经转变了观念\nDialogue: 0,0:41:20.11,0:41:22.59,Default,,0,0,0,,还记得吗 这节课开始我们就讲过\nDialogue: 0,0:41:22.82,0:41:26.23,Default,,0,0,0,,我们转变了建模的观念\nDialogue: 0,0:41:26.23,0:41:29.20,Default,,0,0,0,,我们不再把事物看做按时间演进\nDialogue: 0,0:41:29.37,0:41:31.31,Default,,0,0,0,,也不再具有不同的阶段与状态\nDialogue: 0,0:41:31.75,0:41:33.79,Default,,0,0,0,,取而代之的是 我们对全局进行建模\nDialogue: 0,0:41:33.80,0:41:35.93,Default,,0,0,0,,我们关注粉笔的整个飞行过程\nDialogue: 0,0:41:36.28,0:41:38.88,Default,,0,0,0,,而不是专注于每个瞬时状态\nDialogue: 0,0:41:40.75,0:41:41.44,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:41:44.08,0:41:46.20,Default,,0,0,0,,学生：在我看来回溯会\nDialogue: 0,0:41:46.22,0:41:48.96,Default,,0,0,0,,搜索到它所能找到的第一个解\nDialogue: 0,0:41:49.31,0:41:51.48,Default,,0,0,0,,而这个递归搜索\nDialogue: 0,0:41:51.48,0:41:53.26,Default,,0,0,0,,会去寻找所有的解\nDialogue: 0,0:41:53.32,0:41:53.60,Default,,0,0,0,,教授：是这样的\nDialogue: 0,0:41:54.03,0:41:55.26,Default,,0,0,0,,学生：但问题是\nDialogue: 0,0:41:55.26,0:41:57.92,Default,,0,0,0,,如果需要搜索的空间足够的大\nDialogue: 0,0:41:57.92,0:42:00.92,Default,,0,0,0,,第二种搜索方式就会变得不现实\nDialogue: 0,0:42:01.36,0:42:05.93,Default,,0,0,0,,教授：呃 这个问题其实是\nDialogue: 0,0:42:07.13,0:42:08.44,Default,,0,0,0,,这一节课剩下的内容\nDialogue: 0,0:42:08.57,0:42:10.54,Default,,0,0,0,,这个问题很好\nDialogue: 0,0:42:13.87,0:42:15.74,Default,,0,0,0,,先不要尝试去预知后面的课\nDialogue: 0,0:42:15.96,0:42:19.23,Default,,0,0,0,,只是在现在 你们要保持谨慎\nDialogue: 0,0:42:19.84,0:42:21.84,Default,,0,0,0,,这里确实有点奇怪 难道不是么？\nDialogue: 0,0:42:22.22,0:42:24.51,Default,,0,0,0,,尽管这个看起来不错 但是难道它不低效吗？\nDialogue: 0,0:42:24.83,0:42:26.03,Default,,0,0,0,,这是我们待会儿要解决的问题\nDialogue: 0,0:42:28.10,0:42:30.02,Default,,0,0,0,,就让我们稍后来揭晓秘密吧\nDialogue: 0,0:42:33.35,0:42:34.60,Default,,0,0,0,,好吧 休息一下\nDialogue: 0,0:42:34.60,0:42:44.51,Default,,0,0,0,,[音乐]\nDialogue: 0,0:42:44.51,0:42:49.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:43:10.57,0:43:17.05,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:43:17.05,0:43:21.21,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:43:21.21,0:43:25.21,Declare,,0,0,0,,{\\an2\\fad(500,500)} 流 I\nDialogue: 0,0:43:29.65,0:43:33.76,Default,,0,0,0,,你可能现在开始怀疑了\nDialogue: 0,0:43:35.60,0:43:39.26,Default,,0,0,0,,我已经展示了这种简单而优雅的\nDialogue: 0,0:43:40.51,0:43:42.28,Default,,0,0,0,,组合程序的方法\nDialogue: 0,0:43:42.86,0:43:46.91,Default,,0,0,0,,这跟那些传统程序非常不同\nDialogue: 0,0:43:46.92,0:43:48.19,Default,,0,0,0,,那些求奇数的平方和\nDialogue: 0,0:43:48.72,0:43:51.32,Default,,0,0,0,,或者求奇数项斐波那契数之类的程序\nDialogue: 0,0:43:53.74,0:43:55.48,Default,,0,0,0,,也不像那些混合了\nDialogue: 0,0:43:55.85,0:43:58.84,Default,,0,0,0,,枚举函数、过滤函数和累积函数的程序\nDialogue: 0,0:44:00.44,0:44:01.82,Default,,0,0,0,,通过把它们混合起来\nDialogue: 0,0:44:02.20,0:44:04.59,Default,,0,0,0,,通过这种混搭式的\nDialogue: 0,0:44:04.62,0:44:07.34,Default,,0,0,0,,组合程序的方法\nDialogue: 0,0:44:07.82,0:44:09.53,Default,,0,0,0,,我们并没有获得\nDialogue: 0,0:44:09.55,0:44:11.77,Default,,0,0,0,,流式程序设计的理论优势\nDialogue: 0,0:44:13.80,0:44:14.25,Default,,0,0,0,,另一方面\nDialogue: 0,0:44:14.28,0:44:16.88,Default,,0,0,0,,你们所见过的大多数程序是那种丑陋的风格\nDialogue: 0,0:44:18.34,0:44:18.94,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:44:19.20,0:44:20.59,Default,,0,0,0,,难道计算机科学家们\nDialogue: 0,0:44:21.16,0:44:24.30,Default,,0,0,0,,愚蠢得无以复加\nDialogue: 0,0:44:25.42,0:44:26.44,Default,,0,0,0,,以至于他们没有注意到这个现象么？\nDialogue: 0,0:44:27.07,0:44:28.75,Default,,0,0,0,,如果你仅仅只是做了这些事\nDialogue: 0,0:44:29.63,0:44:31.93,Default,,0,0,0,,你就能让程序变得极其优雅么？\nDialogue: 0,0:44:33.62,0:44:34.78,Default,,0,0,0,,肯定有什么缺陷\nDialogue: 0,0:44:36.76,0:44:39.05,Default,,0,0,0,,事实上这一缺陷也很容易发现\nDialogue: 0,0:44:39.51,0:44:41.74,Default,,0,0,0,,我们来看看接下来的这个问题\nDialogue: 0,0:44:42.03,0:44:45.47,Default,,0,0,0,,假设我让你去找\nDialogue: 0,0:44:46.16,0:44:48.16,Default,,0,0,0,,1,000到1,000,000之间的第二个素数\nDialogue: 0,0:44:49.12,0:44:50.56,Default,,0,0,0,,如果你的计算机性能更强劲的话\nDialogue: 0,0:44:50.59,0:44:53.05,Default,,0,0,0,,或者可以去找10,000到100,000,000之间的\nDialogue: 0,0:44:54.32,0:44:55.45,Default,,0,0,0,,你可能觉得这很容易\nDialogue: 0,0:44:55.47,0:44:56.65,Default,,0,0,0,,我可以用流来解决\nDialogue: 0,0:44:57.08,0:44:59.87,Default,,0,0,0,,我需要做的就是\nDialogue: 0,0:45:00.57,0:45:02.89,Default,,0,0,0,,从10,000枚举到1,000,000\nDialogue: 0,0:45:04.16,0:45:06.51,Default,,0,0,0,,我就获得了从10,000到1,000,000的所有整数\nDialogue: 0,0:45:06.80,0:45:08.64,Default,,0,0,0,,我过滤出所有的质数\nDialogue: 0,0:45:09.39,0:45:11.10,Default,,0,0,0,,也就是对这些数做素性检测\nDialogue: 0,0:45:11.76,0:45:12.83,Default,,0,0,0,,然后从中取出第二个元素\nDialogue: 0,0:45:12.84,0:45:14.04,Default,,0,0,0,,也就是 TAIL的HEAD部分\nDialogue: 0,0:45:15.79,0:45:17.38,Default,,0,0,0,,这显然是非常荒谬的\nDialogue: 0,0:45:21.66,0:45:23.20,Default,,0,0,0,,我们的机器没有这么大的空间\nDialogue: 0,0:45:23.58,0:45:25.24,Default,,0,0,0,,来存放这些整数\nDialogue: 0,0:45:25.28,0:45:26.35,Default,,0,0,0,,更别说来测试它们了\nDialogue: 0,0:45:27.04,0:45:28.64,Default,,0,0,0,,而且我也只是取第二个数而已\nDialogue: 0,0:45:29.81,0:45:34.94,Default,,0,0,0,,这种传统程序设计风格的威力\nDialogue: 0,0:45:36.43,0:45:37.68,Default,,0,0,0,,（虽然）也正是其弱点\nDialogue: 0,0:45:37.96,0:45:38.94,Default,,0,0,0,,这种程序设计风格\nDialogue: 0,0:45:39.61,0:45:43.50,Default,,0,0,0,,混合了枚举、测试以及累积\nDialogue: 0,0:45:44.88,0:45:46.46,Default,,0,0,0,,我们不需要做全部的事\nDialogue: 0,0:45:46.67,0:45:49.18,Default,,0,0,0,,所以说 实际上这是这种\nDialogue: 0,0:45:49.45,0:45:51.74,Default,,0,0,0,,概念上丑陋的风格\nDialogue: 0,0:45:52.20,0:45:53.80,Default,,0,0,0,,正是让它运行起来高效\nDialogue: 0,0:45:54.91,0:45:55.84,Default,,0,0,0,,就是像这样来混合\nDialogue: 0,0:45:57.80,0:45:59.34,Default,,0,0,0,,我今天一早上所做的好像都是在\nDialogue: 0,0:45:59.34,0:46:00.42,Default,,0,0,0,,把你们搞糊涂一样\nDialogue: 0,0:46:00.42,0:46:03.10,Default,,0,0,0,,我为你们展示了一种貌似可行的优雅程序设计方法\nDialogue: 0,0:46:03.10,0:46:03.96,Default,,0,0,0,,但它却不可行\nDialogue: 0,0:46:05.84,0:46:08.32,Default,,0,0,0,,但是 接下来就是见证奇迹的时刻\nDialogue: 0,0:46:09.04,0:46:10.57,Default,,0,0,0,,结果却是 这个游戏里\nDialogue: 0,0:46:11.21,0:46:13.84,Default,,0,0,0,,我们真的可以得到蛋糕并吃掉它\nDialogue: 0,0:46:14.87,0:46:16.11,Default,,0,0,0,,我的意思是\nDialogue: 0,0:46:18.09,0:46:21.15,Default,,0,0,0,,我们完全可以用流来组织程序\nDialogue: 0,0:46:21.16,0:46:22.48,Default,,0,0,0,,就像我之前编写的那样\nDialogue: 0,0:46:23.55,0:46:27.74,Default,,0,0,0,,以至于当机器真正运行的时候\nDialogue: 0,0:46:28.33,0:46:31.52,Default,,0,0,0,,它可以和传统风格的程序一样高效\nDialogue: 0,0:46:31.71,0:46:34.28,Default,,0,0,0,,那些混合了生成与测试的程序\nDialogue: 0,0:46:36.16,0:46:38.80,Default,,0,0,0,,听起来不可思议\nDialogue: 0,0:46:40.77,0:46:41.82,Default,,0,0,0,,关键在就于\nDialogue: 0,0:46:42.00,0:46:43.69,Default,,0,0,0,,流不是表\nDialogue: 0,0:46:48.09,0:46:49.79,Default,,0,0,0,,一会儿我们就会看到 但是现在\nDialogue: 0,0:46:49.80,0:46:51.77,Default,,0,0,0,,先让我们来看看幻灯片\nDialogue: 0,0:46:52.24,0:46:53.80,Default,,0,0,0,,你们对这个\nDialogue: 0,0:46:53.84,0:46:55.58,Default,,0,0,0,,信号处理系统的印象是\nDialogue: 0,0:46:57.26,0:46:58.72,Default,,0,0,0,,你们认为要发生的是\nDialogue: 0,0:46:59.13,0:47:00.92,Default,,0,0,0,,在这类盒子中\nDialogue: 0,0:47:01.18,0:47:03.58,Default,,0,0,0,,事先产生好了整数\nDialogue: 0,0:47:05.36,0:47:06.40,Default,,0,0,0,,这里有个过滤函数\nDialogue: 0,0:47:07.45,0:47:09.37,Default,,0,0,0,,它和那个盒子相连 并从中拉取东西\nDialogue: 0,0:47:10.94,0:47:13.15,Default,,0,0,0,,这里还有人从这整个系统中\nDialogue: 0,0:47:13.31,0:47:14.91,Default,,0,0,0,,拉取东西\nDialogue: 0,0:47:16.79,0:47:18.70,Default,,0,0,0,,你们应该这么来理解：\nDialogue: 0,0:47:18.99,0:47:20.72,Default,,0,0,0,,有人想要得到第一个质数\nDialogue: 0,0:47:22.67,0:47:24.14,Default,,0,0,0,,他从这个过滤函数这儿拉取\nDialogue: 0,0:47:24.59,0:47:26.12,Default,,0,0,0,,FILTER从枚举函数中去拉取\nDialogue: 0,0:47:28.02,0:47:29.15,Default,,0,0,0,,你只需要在固定范围内寻找\nDialogue: 0,0:47:29.16,0:47:30.93,Default,,0,0,0,,然后从里面取出第二个数\nDialogue: 0,0:47:30.93,0:47:31.95,Default,,0,0,0,,第二个质数是多少？\nDialogue: 0,0:47:33.71,0:47:35.37,Default,,0,0,0,,没有额外的计算\nDialogue: 0,0:47:35.37,0:47:36.64,Default,,0,0,0,,只要你不去拉取东西\nDialogue: 0,0:47:36.64,0:47:38.32,Default,,0,0,0,,就不会产生进行额外计算\nDialogue: 0,0:47:40.50,0:47:41.41,Default,,0,0,0,,我来用实物演示一下\nDialogue: 0,0:47:41.41,0:47:43.88,Default,,0,0,0,,这个小设备\nDialogue: 0,0:47:43.90,0:47:44.97,Default,,0,0,0,,这是个小型的流机器\nDialogue: 0,0:47:45.50,0:47:46.83,Default,,0,0,0,,这是Eric Grimson发明的\nDialogue: 0,0:47:47.60,0:47:49.24,Default,,0,0,0,,他也在MIT教这门课\nDialogue: 0,0:47:49.83,0:47:52.51,Default,,0,0,0,,实际的流程是 -- 这里有某种流\nDialogue: 0,0:47:52.54,0:47:53.82,Default,,0,0,0,,就像一串整数一样\nDialogue: 0,0:47:54.78,0:47:56.33,Default,,0,0,0,,这些是一些处理单元\nDialogue: 0,0:47:58.70,0:48:02.60,Default,,0,0,0,,就像是FILTER、MAP之类的东西\nDialogue: 0,0:48:03.98,0:48:09.18,Default,,0,0,0,,如果我把流实现为表 来进行处理\nDialogue: 0,0:48:09.24,0:48:11.26,Default,,0,0,0,,我拥有的是一个表\nDialogue: 0,0:48:11.47,0:48:12.67,Default,,0,0,0,,现在 我先执行第一个过滤函数\nDialogue: 0,0:48:12.67,0:48:14.07,Default,,0,0,0,,我像这样完全处理\nDialogue: 0,0:48:14.88,0:48:15.77,Default,,0,0,0,,针对这个流\nDialogue: 0,0:48:16.32,0:48:19.21,Default,,0,0,0,,不断地处理、处理、处理、处理\nDialogue: 0,0:48:19.61,0:48:21.05,Default,,0,0,0,,然后得到一个新的流\nDialogue: 0,0:48:21.63,0:48:24.07,Default,,0,0,0,,现在 我把得到的结果拿在我手中\nDialogue: 0,0:48:24.07,0:48:25.26,Default,,0,0,0,,然后把它放进第二个\nDialogue: 0,0:48:25.56,0:48:26.94,Default,,0,0,0,,又处理了全部的流\nDialogue: 0,0:48:28.27,0:48:29.51,Default,,0,0,0,,得到一个新流\nDialogue: 0,0:48:32.13,0:48:33.36,Default,,0,0,0,,然后我再把结果\nDialogue: 0,0:48:34.28,0:48:36.36,Default,,0,0,0,,用相同的方式再次处理\nDialogue: 0,0:48:36.36,0:48:40.99,Default,,0,0,0,,如果仅仅把流当做表的话\nDialogue: 0,0:48:41.69,0:48:42.97,Default,,0,0,0,,计算的过程就是这样的\nDialogue: 0,0:48:43.86,0:48:45.64,Default,,0,0,0,,但是事实上 流不是表 流就是流\nDialogue: 0,0:48:45.82,0:48:48.11,Default,,0,0,0,,而你们应该这样来想像\nDialogue: 0,0:48:50.23,0:48:52.52,Default,,0,0,0,,我把这些小玩意连接起来\nDialogue: 0,0:48:55.26,0:48:56.76,Default,,0,0,0,,数据在其中流动\nDialogue: 0,0:49:00.33,0:49:02.30,Default,,0,0,0,,这里是流的源头\nDialogue: 0,0:49:02.32,0:49:02.92,Default,,0,0,0,,它可能在\nDialogue: 0,0:49:04.19,0:49:05.72,Default,,0,0,0,,产生一些整数\nDialogue: 0,0:49:05.98,0:49:07.39,Default,,0,0,0,,如果我想要拉取一个结果 会发生什么？\nDialogue: 0,0:49:07.58,0:49:08.91,Default,,0,0,0,,我从尾部这里拉取\nDialogue: 0,0:49:10.20,0:49:11.07,Default,,0,0,0,,而这个单元会说\nDialogue: 0,0:49:11.08,0:49:12.20,Default,,0,0,0,,我需要更多的数据\nDialogue: 0,0:49:13.09,0:49:15.52,Default,,0,0,0,,所以 它就到这个单元去拉取数据\nDialogue: 0,0:49:15.83,0:49:17.39,Default,,0,0,0,,它说：“我需要更多的数据”\nDialogue: 0,0:49:17.89,0:49:19.56,Default,,0,0,0,,然后这个又从下一个单元拉取\nDialogue: 0,0:49:19.56,0:49:20.28,Default,,0,0,0,,可能是一个过滤函数\nDialogue: 0,0:49:20.28,0:49:21.40,Default,,0,0,0,,从它那里取得更多数据\nDialogue: 0,0:49:21.64,0:49:23.15,Default,,0,0,0,,我在这一端拉取数据时\nDialogue: 0,0:49:23.53,0:49:25.56,Default,,0,0,0,,只会生成这么多的数据\nDialogue: 0,0:49:25.78,0:49:28.30,Default,,0,0,0,,我在另一端请求一定量的数据时\nDialogue: 0,0:49:28.56,0:49:29.98,Default,,0,0,0,,只有相当数量的数据被生成并处理\nDialogue: 0,0:49:30.76,0:49:32.09,Default,,0,0,0,,这就是你们需要知道的\nDialogue: 0,0:49:32.80,0:49:34.38,Default,,0,0,0,,把流实现为表\nDialogue: 0,0:49:34.56,0:49:35.92,Default,,0,0,0,,和流真实的工作方式\nDialogue: 0,0:49:36.16,0:49:37.50,Default,,0,0,0,,的区别\nDialogue: 0,0:49:40.78,0:49:42.14,Default,,0,0,0,,那么 到底怎么来实现呢？\nDialogue: 0,0:49:42.35,0:49:43.32,Default,,0,0,0,,知道了流的真实工作方式\nDialogue: 0,0:49:43.40,0:49:44.52,Default,,0,0,0,,构造流有什么窍门呢？\nDialogue: 0,0:49:47.93,0:49:50.32,Default,,0,0,0,,我们想要把流组织成\nDialogue: 0,0:49:50.41,0:49:51.58,Default,,0,0,0,,一种数据结构\nDialogue: 0,0:49:52.00,0:49:54.22,Default,,0,0,0,,它能够增量式地计算自己\nDialogue: 0,0:49:54.22,0:49:56.22,Default,,0,0,0,,一种“按需”数据结构\nDialogue: 0,0:49:58.96,0:50:00.51,Default,,0,0,0,,基本思想在于\nDialogue: 0,0:50:00.97,0:50:02.70,Default,,0,0,0,,再次强调 这是贯穿整个课程的\nDialogue: 0,0:50:02.72,0:50:04.12,Default,,0,0,0,,几大基本思想之一\nDialogue: 0,0:50:04.49,0:50:05.00,Default,,0,0,0,,这就是\nDialogue: 0,0:50:05.52,0:50:06.97,Default,,0,0,0,,数据与过程之间\nDialogue: 0,0:50:06.99,0:50:08.44,Default,,0,0,0,,并没有绝对的界限\nDialogue: 0,0:50:09.24,0:50:10.54,Default,,0,0,0,,流会是这样的一种结构\nDialogue: 0,0:50:10.59,0:50:13.40,Default,,0,0,0,,它既是一种传统意义上的“数据结构”\nDialogue: 0,0:50:13.45,0:50:15.92,Default,,0,0,0,,比如树的叶子结点组成的流\nDialogue: 0,0:50:16.86,0:50:17.85,Default,,0,0,0,,但是同时\nDialogue: 0,0:50:17.85,0:50:19.32,Default,,0,0,0,,它又是一种非常聪明的过程\nDialogue: 0,0:50:20.24,0:50:22.22,Default,,0,0,0,,它包含了如何计算的方法\nDialogue: 0,0:50:23.74,0:50:25.93,Default,,0,0,0,,好吧 实际来看一下\nDialogue: 0,0:50:25.93,0:50:26.62,Default,,0,0,0,,事实上\nDialogue: 0,0:50:26.80,0:50:28.33,Default,,0,0,0,,我们不需要其它的机制\nDialogue: 0,0:50:28.46,0:50:29.87,Default,,0,0,0,,我们已经有了所需要的一切东西\nDialogue: 0,0:50:30.14,0:50:30.99,Default,,0,0,0,,这是因为\nDialogue: 0,0:50:31.02,0:50:33.93,Default,,0,0,0,,我们已经能够 把过程当作第一级对象来处理了\nDialogue: 0,0:50:35.46,0:50:36.88,Default,,0,0,0,,来看看这个关键之处\nDialogue: 0,0:50:36.88,0:50:39.03,Default,,0,0,0,,关键在于 -- 回想一下 我们有这些运算\nDialogue: 0,0:50:39.03,0:50:47.52,Default,,0,0,0,,CONS-STREAM、HEAD和TAIL\nDialogue: 0,0:50:48.08,0:50:49.36,Default,,0,0,0,,刚开始的时候我说\nDialogue: 0,0:50:49.92,0:50:51.36,Default,,0,0,0,,你们可以把这个看作CONS\nDialogue: 0,0:50:51.40,0:50:52.62,Default,,0,0,0,,把HEAD看作CAR\nDialogue: 0,0:50:52.62,0:50:53.52,Default,,0,0,0,,把TAIL看作CDR\nDialogue: 0,0:50:53.55,0:50:54.16,Default,,0,0,0,,事实上没这么简单\nDialogue: 0,0:50:55.08,0:50:56.32,Default,,0,0,0,,现在 来看看它们到底是什么\nDialogue: 0,0:50:57.71,0:51:05.84,Default,,0,0,0,,(CONS-STREAM X Y)\nDialogue: 0,0:51:07.48,0:51:17.79,Default,,0,0,0,,是这个东西的缩写形式\nDialogue: 0,0:51:19.54,0:51:28.32,Default,,0,0,0,,(CONS X (DELAY Y))\nDialogue: 0,0:51:31.68,0:51:33.53,Default,,0,0,0,,我先把它们写完再来解释\nDialogue: 0,0:51:34.52,0:51:35.53,Default,,0,0,0,,而(HEAD S)\nDialogue: 0,0:51:38.09,0:51:39.79,Default,,0,0,0,,就是 (CAR S)\nDialogue: 0,0:51:42.38,0:51:44.25,Default,,0,0,0,,而(TAIL S)\nDialogue: 0,0:51:46.68,0:51:54.60,Default,,0,0,0,,则是(FORCE (CDR S))\nDialogue: 0,0:51:56.12,0:51:57.04,Default,,0,0,0,,我来解释一下\nDialogue: 0,0:51:58.06,0:51:59.88,Default,,0,0,0,,DELAY是一个特殊而神奇的东西\nDialogue: 0,0:52:01.42,0:52:02.33,Default,,0,0,0,,DELAY所做是\nDialogue: 0,0:52:03.85,0:52:05.31,Default,,0,0,0,,取一个表达式\nDialogue: 0,0:52:05.50,0:52:06.86,Default,,0,0,0,,然后产生一个PROMISE\nDialogue: 0,0:52:07.12,0:52:09.15,Default,,0,0,0,,在你有需要时 这个PROMISE会计算那个表达式\nDialogue: 0,0:52:10.60,0:52:11.98,Default,,0,0,0,,但在此时没有做任何计算\nDialogue: 0,0:52:11.98,0:52:14.32,Default,,0,0,0,,只是一个延期的PROMISE\nDialogue: 0,0:52:14.82,0:52:16.20,Default,,0,0,0,,承诺要做这样的事\nDialogue: 0,0:52:17.11,0:52:18.20,Default,,0,0,0,,CONS-STREAM所做的就是\nDialogue: 0,0:52:18.81,0:52:21.96,Default,,0,0,0,,把X和一个计算Y的PROMISE\nDialogue: 0,0:52:23.31,0:52:25.36,Default,,0,0,0,,放在在一个序对里\nDialogue: 0,0:52:28.23,0:52:28.99,Default,,0,0,0,,如果我需要头部分\nDialogue: 0,0:52:28.99,0:52:30.75,Default,,0,0,0,,那么就是这个序对的CAR部分\nDialogue: 0,0:52:31.84,0:52:33.71,Default,,0,0,0,,关键在于 它的尾部分\nDialogue: 0,0:52:34.62,0:52:36.65,Default,,0,0,0,,强制会调用该PROMISE\nDialogue: 0,0:52:38.22,0:52:39.88,Default,,0,0,0,,而TAIL会说\nDialogue: 0,0:52:40.03,0:52:41.02,Default,,0,0,0,,好吧 取出该PROMISE\nDialogue: 0,0:52:41.85,0:52:44.52,Default,,0,0,0,,然后调用该PROMISE\nDialogue: 0,0:52:44.56,0:52:46.03,Default,,0,0,0,,这才开始实际的计算\nDialogue: 0,0:52:47.69,0:52:48.72,Default,,0,0,0,,这就是它的实际工作方式\nDialogue: 0,0:52:48.74,0:52:51.55,Default,,0,0,0,,这就是CONS-STREAM、HEAD和TAIL的真正定义\nDialogue: 0,0:52:54.60,0:52:55.57,Default,,0,0,0,,具体演示一下\nDialogue: 0,0:52:55.57,0:52:57.50,Default,,0,0,0,,我们小心翼翼地来审查一遍\nDialogue: 0,0:52:58.76,0:53:00.62,Default,,0,0,0,,现在从计算10,000到1,000,000中的\nDialogue: 0,0:53:01.32,0:53:03.66,Default,,0,0,0,,第二个质数这个实例来看\nDialogue: 0,0:53:05.50,0:53:07.16,Default,,0,0,0,,看看是怎么运行的\nDialogue: 0,0:53:08.65,0:53:12.03,Default,,0,0,0,,好的 我们从这个表达式开始\nDialogue: 0,0:53:15.36,0:53:16.62,Default,,0,0,0,,第二个质数就是\nDialogue: 0,0:53:16.64,0:53:21.90,Default,,0,0,0,,就是(HEAD (TAIL (FILTER PRIME? ... )))\nDialogue: 0,0:53:22.83,0:53:25.31,Default,,0,0,0,,枚举的范围是(E-I 10000 1000000)\nDialogue: 0,0:53:26.71,0:53:27.61,Default,,0,0,0,,这是什么呢？\nDialogue: 0,0:53:28.40,0:53:29.20,Default,,0,0,0,,那就是\nDialogue: 0,0:53:31.63,0:53:34.17,Default,,0,0,0,,枚举的这个10,000至1,000,000的区间\nDialogue: 0,0:53:35.72,0:53:37.32,Default,,0,0,0,,如果你追踪这个枚举区间\nDialogue: 0,0:53:37.34,0:53:38.78,Default,,0,0,0,,会发现它构造了一个流\nDialogue: 0,0:53:39.92,0:53:41.39,Default,,0,0,0,,CONS-STREAM实际代换过来是\nDialogue: 0,0:53:41.96,0:53:43.61,Default,,0,0,0,,把10,000\nDialogue: 0,0:53:44.51,0:53:48.92,Default,,0,0,0,,和一个计算10,001到1,000,000之间整数的PROMISE结合起来\nDialogue: 0,0:53:54.00,0:53:55.75,Default,,0,0,0,,这也就是上面这个表达式\nDialogue: 0,0:53:55.75,0:53:57.32,Default,,0,0,0,,现在我使用代换模型\nDialogue: 0,0:53:57.64,0:53:59.32,Default,,0,0,0,,我们可以用代换模型的原因是\nDialogue: 0,0:53:59.34,0:54:01.01,Default,,0,0,0,,这里并没有涉及状态和副作用\nDialogue: 0,0:54:03.56,0:54:06.38,Default,,0,0,0,,所以我有10,000\nDialogue: 0,0:54:06.41,0:54:08.27,Default,,0,0,0,,和一个计算剩余整数构成的流\nDialogue: 0,0:54:08.32,0:54:10.49,Default,,0,0,0,,而到现在为止 只有一个整数被枚举了出来\nDialogue: 0,0:54:14.38,0:54:16.96,Default,,0,0,0,,然后过滤函数会对它做素性测试\nDialogue: 0,0:54:19.44,0:54:21.90,Default,,0,0,0,,我们再来仔细看看过滤函数的代码\nDialogue: 0,0:54:22.36,0:54:24.46,Default,,0,0,0,,过滤函数首先测试流的首部分\nDialogue: 0,0:54:25.46,0:54:28.25,Default,,0,0,0,,这里 过滤函数会测试10,000\nDialogue: 0,0:54:30.30,0:54:32.97,Default,,0,0,0,,然后输出：10,000不是质数\nDialogue: 0,0:54:33.50,0:54:35.85,Default,,0,0,0,,因此我只需要\nDialogue: 0,0:54:36.25,0:54:37.39,Default,,0,0,0,,递归地过滤尾部分\nDialogue: 0,0:54:39.22,0:54:40.14,Default,,0,0,0,,尾部分是什么呢？\nDialogue: 0,0:54:40.16,0:54:43.76,Default,,0,0,0,,就是这个流的尾部分 -- 一个PROMISE\nDialogue: 0,0:54:46.34,0:54:48.06,Default,,0,0,0,,我们进入到尾部分\nDialogue: 0,0:54:48.28,0:54:49.50,Default,,0,0,0,,强制（计算）该PROMISE\nDialogue: 0,0:54:49.68,0:54:50.94,Default,,0,0,0,,我强制计算该PROMISE\nDialogue: 0,0:54:52.30,0:54:54.36,Default,,0,0,0,,这就意味着 我现在要\nDialogue: 0,0:54:55.58,0:54:57.96,Default,,0,0,0,,枚举10,001到1,000,000之间的整数\nDialogue: 0,0:55:00.80,0:55:02.97,Default,,0,0,0,,现在 过滤函数处理的是这个东西\nDialogue: 0,0:55:07.81,0:55:08.92,Default,,0,0,0,,这个枚举函数枚举了它自己\nDialogue: 0,0:55:08.94,0:55:11.23,Default,,0,0,0,,我们又回到了最初那种枚举情况\nDialogue: 0,0:55:11.96,0:55:13.00,Default,,0,0,0,,我们的枚举函数的\nDialogue: 0,0:55:14.12,0:55:16.44,Default,,0,0,0,,首部分是整数10,001\nDialogue: 0,0:55:16.60,0:55:18.20,Default,,0,0,0,,尾部分是计算剩余部分的PROMISE\nDialogue: 0,0:55:19.74,0:55:22.75,Default,,0,0,0,,因此现在素性过滤函数将会测试10,001\nDialogue: 0,0:55:23.23,0:55:25.12,Default,,0,0,0,,开始判断它是不是质数\nDialogue: 0,0:55:25.12,0:55:27.08,Default,,0,0,0,,结果10,001不是质数\nDialogue: 0,0:55:27.55,0:55:29.61,Default,,0,0,0,,然后再不断地强制求值PROMISE\nDialogue: 0,0:55:32.92,0:55:35.80,Default,,0,0,0,,最后 我觉得它找到的第一个质数可能是10,009\nDialogue: 0,0:55:37.10,0:55:38.33,Default,,0,0,0,,它会在这个时候停止\nDialogue: 0,0:55:40.84,0:55:41.93,Default,,0,0,0,,这只是第一个质数\nDialogue: 0,0:55:41.96,0:55:43.48,Default,,0,0,0,,然而 我们需要的是第二个\nDialogue: 0,0:55:45.24,0:55:46.84,Default,,0,0,0,,所以 这时它又启动了\nDialogue: 0,0:55:47.03,0:55:48.25,Default,,0,0,0,,你会发现\nDialogue: 0,0:55:48.52,0:55:50.49,Default,,0,0,0,,你需要多少\nDialogue: 0,0:55:51.85,0:55:52.91,Default,,0,0,0,,它就只会生成多少\nDialogue: 0,0:55:56.48,0:55:59.92,Default,,0,0,0,,枚举函数生成整数的数量\nDialogue: 0,0:56:00.12,0:56:01.45,Default,,0,0,0,,不会比过滤函数所要求的多\nDialogue: 0,0:56:01.47,0:56:03.45,Default,,0,0,0,,因为它只是取一部分数来做素性测试\nDialogue: 0,0:56:04.70,0:56:06.51,Default,,0,0,0,,过滤函数也不会生成\nDialogue: 0,0:56:06.54,0:56:08.04,Default,,0,0,0,,比你的要求更多的东西\nDialogue: 0,0:56:08.06,0:56:09.10,Default,,0,0,0,,也就是尾部分的首部分\nDialogue: 0,0:56:11.61,0:56:13.26,Default,,0,0,0,,你们看\nDialogue: 0,0:56:14.70,0:56:18.24,Default,,0,0,0,,我们把计算机运行中实际进行的\nDialogue: 0,0:56:18.67,0:56:20.65,Default,,0,0,0,,生成与测试的过程 混合在了一起\nDialogue: 0,0:56:21.52,0:56:22.67,Default,,0,0,0,,尽管\nDialogue: 0,0:56:23.18,0:56:25.63,Default,,0,0,0,,我们的程序“看起来”显然不是这样\nDialogue: 0,0:56:28.12,0:56:29.40,Default,,0,0,0,,看起来都很简单\nDialogue: 0,0:56:30.23,0:56:32.67,Default,,0,0,0,,这种机制的神奇之处在于DELAY\nDialogue: 0,0:56:33.68,0:56:35.66,Default,,0,0,0,,所以你也许会说 这全是因为DELAY很强大\nDialogue: 0,0:56:36.90,0:56:38.57,Default,,0,0,0,,但其实并不是\nDialogue: 0,0:56:39.07,0:56:39.98,Default,,0,0,0,,DELAY其实很简单\nDialogue: 0,0:56:40.61,0:56:45.07,Default,,0,0,0,,(DELAY <EXP>)\nDialogue: 0,0:56:48.25,0:56:50.04,Default,,0,0,0,,只是一个缩略表达\nDialogue: 0,0:56:53.36,0:56:55.63,Default,,0,0,0,,它是-- 创建一个用于计算表达式的PROMISE\nDialogue: 0,0:56:56.49,0:57:01.12,Default,,0,0,0,,(LAMBDA () <EXP>) 这样的一个表达式\nDialogue: 0,0:57:02.83,0:57:03.84,Default,,0,0,0,,这就是整个过程\nDialogue: 0,0:57:03.98,0:57:05.53,Default,,0,0,0,,这个PROMISE将要计算表达式<EXP>\nDialogue: 0,0:57:06.05,0:57:06.73,Default,,0,0,0,,FORCE过程又是什么？\nDialogue: 0,0:57:07.34,0:57:10.80,Default,,0,0,0,,如何处理这个PROMISE\nDialogue: 0,0:57:10.80,0:57:14.11,Default,,0,0,0,,FROCE一个PROMISE -- 也就是某个过程\nDialogue: 0,0:57:14.78,0:57:15.40,Default,,0,0,0,,只是简单地运行它\nDialogue: 0,0:57:19.23,0:57:19.56,Default,,0,0,0,,就是这样\nDialogue: 0,0:57:20.24,0:57:21.37,Default,,0,0,0,,所以这里并没有什么魔法\nDialogue: 0,0:57:23.52,0:57:24.24,Default,,0,0,0,,总结一下 我们都干了些什么？\nDialogue: 0,0:57:26.44,0:57:27.50,Default,,0,0,0,,我们说\nDialogue: 0,0:57:28.14,0:57:30.81,Default,,0,0,0,,传统的编程方式更有效\nDialogue: 0,0:57:30.96,0:57:33.92,Default,,0,0,0,,而流程序却更加清晰\nDialogue: 0,0:57:35.50,0:57:38.72,Default,,0,0,0,,我们设法用DELAY\nDialogue: 0,0:57:38.81,0:57:43.23,Default,,0,0,0,,使流程序和其它过程一样高效\nDialogue: 0,0:57:43.35,0:57:46.43,Default,,0,0,0,,DELAY所做的就是把\nDialogue: 0,0:57:46.68,0:57:50.40,Default,,0,0,0,,我们程序中 事件发生的逻辑顺序\nDialogue: 0,0:57:51.21,0:57:53.84,Default,,0,0,0,,和机器中 事件发生的实际顺序 解耦开来\nDialogue: 0,0:57:54.44,0:57:55.93,Default,,0,0,0,,这是DELAY的实质作用\nDialogue: 0,0:57:57.15,0:57:58.29,Default,,0,0,0,,也是全部的重点\nDialogue: 0,0:57:58.29,0:58:01.92,Default,,0,0,0,,我们放弃了那种想法\nDialogue: 0,0:58:02.30,0:58:04.17,Default,,0,0,0,,即程序的运行\nDialogue: 0,0:58:04.67,0:58:05.95,Default,,0,0,0,,或者源码的编排\nDialogue: 0,0:58:06.33,0:58:08.25,Default,,0,0,0,,反映了时间的明确概念\nDialogue: 0,0:58:09.45,0:58:10.57,Default,,0,0,0,,一旦放弃了这种想法\nDialogue: 0,0:58:11.21,0:58:13.32,Default,,0,0,0,,我们能使用DELAY\nDialogue: 0,0:58:13.34,0:58:15.20,Default,,0,0,0,,自由地安排计算顺序\nDialogue: 0,0:58:16.69,0:58:17.61,Default,,0,0,0,,整个思想就是这样\nDialogue: 0,0:58:17.61,0:58:19.45,Default,,0,0,0,,我们解耦了\nDialogue: 0,0:58:19.95,0:58:21.13,Default,,0,0,0,,程序的逻辑顺序\nDialogue: 0,0:58:21.16,0:58:22.89,Default,,0,0,0,,和其实际运行的顺序\nDialogue: 0,0:58:24.09,0:58:25.77,Default,,0,0,0,,对了 还有一个细节\nDialogue: 0,0:58:25.77,0:58:27.21,Default,,0,0,0,,一个技术性的细节\nDialogue: 0,0:58:27.21,0:58:28.43,Default,,0,0,0,,但是也非常重要\nDialogue: 0,0:58:29.73,0:58:32.01,Default,,0,0,0,,当你们运行这些递归程序的时候\nDialogue: 0,0:58:32.16,0:58:33.58,Default,,0,0,0,,你会看到很多像是\nDialogue: 0,0:58:33.64,0:58:37.87,Default,,0,0,0,,(TAIL (TAIL (TAIL ... 这样的东西\nDialogue: 0,0:58:39.20,0:58:41.02,Default,,0,0,0,,如果流是通过嵌套的CONS构造起来的\nDialogue: 0,0:58:41.02,0:58:42.88,Default,,0,0,0,,就会出现这种情况\nDialogue: 0,0:58:43.86,0:58:46.09,Default,,0,0,0,,如果我每次都要执行一次\nDialogue: 0,0:58:46.14,0:58:47.58,Default,,0,0,0,,如果我每次都要计算TAIL\nDialogue: 0,0:58:48.22,0:58:50.88,Default,,0,0,0,,我对一个过程求值\nDialogue: 0,0:58:51.07,0:58:53.07,Default,,0,0,0,,这个过程又将重新计算它的TAIL\nDialogue: 0,0:58:53.10,0:58:55.40,Default,,0,0,0,,它的TAIL又将重新计算TAIL的TAIL\nDialogue: 0,0:58:55.50,0:58:56.88,Default,,0,0,0,,你们可以发现这非常低效\nDialogue: 0,0:58:57.77,0:59:00.56,Default,,0,0,0,,尤其是跟已经存放了所有元素的表相比\nDialogue: 0,0:59:01.16,0:59:04.00,Default,,0,0,0,,因为那样 在取得下一个TAIL的时候不需要重新计算\nDialogue: 0,0:59:05.29,0:59:08.28,Default,,0,0,0,,因此 这里有一个小技巧\nDialogue: 0,0:59:09.66,0:59:13.13,Default,,0,0,0,,通过稍微修改DELAY的定义\nDialogue: 0,0:59:14.96,0:59:18.20,Default,,0,0,0,,就可以让整件事变得 -- 我先写一下\nDialogue: 0,0:59:19.68,0:59:22.04,Default,,0,0,0,,DELAY实际的实现是\nDialogue: 0,0:59:24.52,0:59:27.93,Default,,0,0,0,,(DELAY <exp>)是这样一个表达式的简写\nDialogue: 0,0:59:28.11,0:59:30.86,Default,,0,0,0,,(MEMO-PROC (LAMBDA () <EXP>))\nDialogue: 0,0:59:31.00,0:59:34.06,Default,,0,0,0,,MEMO-PROC是一个可以改变过程的特殊过程\nDialogue: 0,0:59:35.15,0:59:37.80,Default,,0,0,0,,它接受一个无参过程\nDialogue: 0,0:59:39.02,0:59:41.05,Default,,0,0,0,,并把该过程变为\nDialogue: 0,0:59:41.36,0:59:43.55,Default,,0,0,0,,只需要执行一次计算的过程\nDialogue: 0,0:59:45.10,0:59:47.45,Default,,0,0,0,,我们意思是 你给它一个过程\nDialogue: 0,0:59:48.70,0:59:50.86,Default,,0,0,0,,MEMO-PROC返回一个新的过程\nDialogue: 0,0:59:51.39,0:59:53.00,Default,,0,0,0,,当你首次调用这个新过程\nDialogue: 0,0:59:53.71,0:59:55.07,Default,,0,0,0,,它会运行原始过程\nDialogue: 0,0:59:55.31,0:59:56.91,Default,,0,0,0,,并记下结果\nDialogue: 0,0:59:58.56,1:00:00.68,Default,,0,0,0,,从那之后 每次你再运行这个过程\nDialogue: 0,1:00:00.68,1:00:02.17,Default,,0,0,0,,就不用再计算了\nDialogue: 0,1:00:02.19,1:00:04.43,Default,,0,0,0,,它会把结果存储在一个地方\nDialogue: 0,1:00:05.20,1:00:06.92,Default,,0,0,0,,可以这样来实现MEMO-PROC\nDialogue: 0,1:00:11.21,1:00:12.71,Default,,0,0,0,,一旦你了解怎么做 实现就很容易了\nDialogue: 0,1:00:12.71,1:00:16.76,Default,,0,0,0,,MEMO-PROC中有两个标记变量\nDialogue: 0,1:00:17.39,1:00:19.20,Default,,0,0,0,,ALREADY-RUN?用于记录是否运行过\nDialogue: 0,1:00:20.32,1:00:22.48,Default,,0,0,0,,初始值是NIL 指示没运行过\nDialogue: 0,1:00:23.62,1:00:27.04,Default,,0,0,0,,RESULT用于存储上一次计算的结果\nDialogue: 0,1:00:29.07,1:00:31.07,Default,,0,0,0,,MEMO-PROC接收一个过程PROC\nDialogue: 0,1:00:31.56,1:00:34.01,Default,,0,0,0,,返回一个新的无参过程\nDialogue: 0,1:00:34.36,1:00:36.38,Default,,0,0,0,,PROC也是一个无参过程\nDialogue: 0,1:00:38.61,1:00:41.37,Default,,0,0,0,,它会判断 -- 如果没有运行过\nDialogue: 0,1:00:42.59,1:00:44.06,Default,,0,0,0,,就进行一系列的运算\nDialogue: 0,1:00:44.43,1:00:46.56,Default,,0,0,0,,先计算PROC\nDialogue: 0,1:00:47.50,1:00:48.45,Default,,0,0,0,,然后存储它的值\nDialogue: 0,1:00:48.45,1:00:50.48,Default,,0,0,0,,存储在变量RESULT中\nDialogue: 0,1:00:51.14,1:00:53.90,Default,,0,0,0,,然后对ALREADY-RUN?赋值 提醒自己已经运行过了\nDialogue: 0,1:00:54.28,1:00:55.47,Default,,0,0,0,,最后返回RESULT\nDialogue: 0,1:00:56.61,1:00:59.01,Default,,0,0,0,,所以之前如果没运行过 就执行一次计算\nDialogue: 0,1:00:59.01,1:01:01.88,Default,,0,0,0,,当你调用它 但已经运行过了 就直接返回结果\nDialogue: 0,1:01:03.42,1:01:07.12,Default,,0,0,0,,这种聪明的小技巧被称作“记忆化”\nDialogue: 0,1:01:08.40,1:01:09.13,Default,,0,0,0,,这样的话\nDialogue: 0,1:01:10.35,1:01:14.14,Default,,0,0,0,,就不会重复的计算TAIL了\nDialogue: 0,1:01:15.27,1:01:17.81,Default,,0,0,0,,不再那样的没效率了\nDialogue: 0,1:01:17.81,1:01:18.72,Default,,0,0,0,,事实上 流式程序设计\nDialogue: 0,1:01:19.20,1:01:22.75,Default,,0,0,0,,甚至和传统的那种程序一样有效\nDialogue: 0,1:01:24.01,1:01:26.20,Default,,0,0,0,,再强调一下 整个的思想在于\nDialogue: 0,1:01:27.48,1:01:28.60,Default,,0,0,0,,我们已经讲过\nDialogue: 0,1:01:29.26,1:01:32.40,Default,,0,0,0,,过程与数据之间\nDialogue: 0,1:01:32.41,1:01:33.61,Default,,0,0,0,,没有一个明确的分界线\nDialogue: 0,1:01:33.61,1:01:35.61,Default,,0,0,0,,事实上 我们把数据结构组织得\nDialogue: 0,1:01:36.00,1:01:37.31,Default,,0,0,0,,像一个过程\nDialogue: 0,1:01:38.76,1:01:40.73,Default,,0,0,0,,它使得我们能够\nDialogue: 0,1:01:41.58,1:01:46.54,Default,,0,0,0,,可以实现一种常见的控制结构\nDialogue: 0,1:01:46.68,1:01:48.91,Default,,0,0,0,,在本例中是迭代\nDialogue: 0,1:01:49.62,1:01:51.05,Default,,0,0,0,,我们创建了一种数据结构\nDialogue: 0,1:01:51.32,1:01:52.84,Default,,0,0,0,,由于这种数据结构本身是一个过程\nDialogue: 0,1:01:52.86,1:01:55.12,Default,,0,0,0,,它其中就可以有某种控制结构\nDialogue: 0,1:01:55.79,1:01:57.13,Default,,0,0,0,,这就是流的实质\nDialogue: 0,1:01:58.91,1:01:59.76,Default,,0,0,0,,好 大家有什么问题吗？\nDialogue: 0,1:02:03.95,1:02:05.84,Default,,0,0,0,,学生：你刚才说(TAIL (TAIL (TAIL ...\nDialogue: 0,1:02:05.85,1:02:07.16,Default,,0,0,0,,如果我没理解错的话\nDialogue: 0,1:02:07.28,1:02:10.76,Default,,0,0,0,,没有没有MEMO-PROC的话\nDialogue: 0,1:02:10.78,1:02:12.83,Default,,0,0,0,,FORCE实际上执行了一个过程\nDialogue: 0,1:02:12.89,1:02:13.15,Default,,0,0,0,,教授：是的\nDialogue: 0,1:02:13.44,1:02:16.38,Default,,0,0,0,,学生：你说使用那个MEMO-PROC就不会有那样的问题\nDialogue: 0,1:02:16.38,1:02:18.73,Default,,0,0,0,,这难道不需要保证\nDialogue: 0,1:02:19.34,1:02:22.19,Default,,0,0,0,,(TAIL (TAIL (TAIL 每次的计算结构都是一致的么？\nDialogue: 0,1:02:22.41,1:02:23.91,Default,,0,0,0,,教授：哦 当然\nDialogue: 0,1:02:23.91,1:02:25.84,Default,,0,0,0,,学生：我可能是漏了什么知识点\nDialogue: 0,1:02:26.05,1:02:27.21,Default,,0,0,0,,教授：你说得很对 这里 --\nDialogue: 0,1:02:31.12,1:02:33.64,Default,,0,0,0,,首先 为了获得结果需要进行一次计算\nDialogue: 0,1:02:34.09,1:02:36.76,Default,,0,0,0,,关键在于 一旦得到 (TAIL STREAM)\nDialogue: 0,1:02:37.58,1:02:38.70,Default,,0,0,0,,再计算 (TAIL (TAIL STREAM)) 的时候\nDialogue: 0,1:02:38.70,1:02:40.51,Default,,0,0,0,,就不用再计算最内部的TAIL了\nDialogue: 0,1:02:42.98,1:02:44.32,Default,,0,0,0,,明白了吧 如果我没有用MEMO-PROC\nDialogue: 0,1:02:44.35,1:02:46.09,Default,,0,0,0,,还要再计算一遍 (TAIL STREAM)\nDialogue: 0,1:02:46.46,1:02:47.13,Default,,0,0,0,,学生：明白了\nDialogue: 0,1:02:50.83,1:02:52.56,Default,,0,0,0,,学生：之前的例子中你提到过\nDialogue: 0,1:02:52.60,1:02:54.22,Default,,0,0,0,,我们之所以可以使用代换模型\nDialogue: 0,1:02:54.22,1:02:56.11,Default,,0,0,0,,是因为这里没有副作用\nDialogue: 0,1:02:56.83,1:03:00.73,Default,,0,0,0,,如果我们的信号处理单元\nDialogue: 0,1:03:00.78,1:03:02.03,Default,,0,0,0,,具有副作用\nDialogue: 0,1:03:02.04,1:03:03.04,Default,,0,0,0,,具有内部状态\nDialogue: 0,1:03:03.62,1:03:06.84,Default,,0,0,0,,我们还有效地构建流模型么？\nDialogue: 0,1:03:08.46,1:03:10.59,Default,,0,0,0,,教授：可能吧 这是一个很困难的问题\nDialogue: 0,1:03:11.20,1:03:13.42,Default,,0,0,0,,关于代换模型和副作用并不是很兼容这一点\nDialogue: 0,1:03:14.36,1:03:18.24,Default,,0,0,0,,我以后会稍稍地讲解一下\nDialogue: 0,1:03:18.96,1:03:20.48,Default,,0,0,0,,但大体来说 我认为\nDialogue: 0,1:03:20.49,1:03:21.63,Default,,0,0,0,,除非你非常小心\nDialogue: 0,1:03:21.90,1:03:24.46,Default,,0,0,0,,否则副作用会把一切弄得很糟糕\nDialogue: 0,1:03:35.04,1:03:38.25,Default,,0,0,0,,学生：我不是很理解MEMO-PROC这个过程\nDialogue: 0,1:03:39.68,1:03:41.12,Default,,0,0,0,,你是什么时候执行那个LAMBDA的？\nDialogue: 0,1:03:41.99,1:03:43.21,Default,,0,0,0,,换句话说\nDialogue: 0,1:03:43.68,1:03:45.15,Default,,0,0,0,,当MEMO-PROC执行的时候\nDialogue: 0,1:03:45.18,1:03:47.71,Default,,0,0,0,,只生成了LAMBDA表达式\nDialogue: 0,1:03:48.01,1:03:49.68,Default,,0,0,0,,但我不太清楚它是什么时候被执行的\nDialogue: 0,1:03:50.39,1:03:51.12,Default,,0,0,0,,教授：好的\nDialogue: 0,1:03:51.35,1:03:52.68,Default,,0,0,0,,MEMO-PROC所做的 --\nDialogue: 0,1:03:53.07,1:03:55.85,Default,,0,0,0,,MEMO-PROC的一个参数是PROC\nDialogue: 0,1:03:56.38,1:03:57.93,Default,,0,0,0,,一个没有参数的过程\nDialogue: 0,1:03:57.93,1:03:59.05,Default,,0,0,0,,某个时刻 你会调用它\nDialogue: 0,1:04:00.39,1:04:02.75,Default,,0,0,0,,MEMO-PROC把该过程转化为\nDialogue: 0,1:04:02.75,1:04:04.56,Default,,0,0,0,,另一个无参过程\nDialogue: 0,1:04:04.59,1:04:05.80,Default,,0,0,0,,某个时刻你会调用到它\nDialogue: 0,1:04:06.62,1:04:07.42,Default,,0,0,0,,LAMBDA语句做的是这个\nDialogue: 0,1:04:09.89,1:04:14.08,Default,,0,0,0,,所以在这里 我最初构造\nDialogue: 0,1:04:15.85,1:04:17.92,Default,,0,0,0,,构造流的TAIL的时候\nDialogue: 0,1:04:18.30,1:04:20.48,Default,,0,0,0,,这里的这个无参过程\nDialogue: 0,1:04:20.51,1:04:21.61,Default,,0,0,0,,会在之后的某个时刻调用\nDialogue: 0,1:04:24.10,1:04:28.01,Default,,0,0,0,,相对应的 我要对(TAIL STREAM)调用MEMO-PROC\nDialogue: 0,1:04:28.12,1:04:29.24,Default,,0,0,0,,以后我会调用生成的过程\nDialogue: 0,1:04:30.65,1:04:31.90,Default,,0,0,0,,所以这个无参的LAMBDA\nDialogue: 0,1:04:32.03,1:04:36.06,Default,,0,0,0,,是当你在调用MEMO-PROC时调用的\nDialogue: 0,1:04:38.97,1:04:40.96,Default,,0,0,0,,当你调用MEMP-PROC返回的过程时\nDialogue: 0,1:04:40.97,1:04:42.28,Default,,0,0,0,,也就会像通常的过程调用那样\nDialogue: 0,1:04:42.36,1:04:45.76,Default,,0,0,0,,调用你最初设定的那个函数\nDialogue: 0,1:04:47.64,1:04:48.86,Default,,0,0,0,,学生：我想问的是\nDialogue: 0,1:04:48.86,1:04:50.86,Default,,0,0,0,,当你调用MEMO-PROC的时候\nDialogue: 0,1:04:50.86,1:04:52.30,Default,,0,0,0,,你返回了这个LAMBDA\nDialogue: 0,1:04:52.61,1:04:53.07,Default,,0,0,0,,教授：是的\nDialogue: 0,1:04:53.77,1:04:58.10,Default,,0,0,0,,你调用MEMO-PROC的时候 返回了一个LAMBDA\nDialogue: 0,1:04:58.10,1:04:59.84,Default,,0,0,0,,直到你第一次需要执行它的时候\nDialogue: 0,1:04:59.87,1:05:02.27,Default,,0,0,0,,你才去求值<EXP>\nDialogue: 0,1:05:07.76,1:05:09.10,Default,,0,0,0,,学生：我这样理解对吗？\nDialogue: 0,1:05:09.18,1:05:11.40,Default,,0,0,0,,你构造了一个表\nDialogue: 0,1:05:11.47,1:05:14.17,Default,,0,0,0,,但表中的元素还没有被求值\nDialogue: 0,1:05:14.24,1:05:15.63,Default,,0,0,0,,表达式没有被求值？\nDialogue: 0,1:05:15.63,1:05:18.54,Default,,0,0,0,,但在每个阶段 你还是构造了一个表\nDialogue: 0,1:05:18.54,1:05:20.70,Default,,0,0,0,,教授：啊 我应该这样说\nDialogue: 0,1:05:20.70,1:05:22.27,Default,,0,0,0,,这个想法很好\nDialogue: 0,1:05:22.27,1:05:23.18,Default,,0,0,0,,但是 也不全对\nDialogue: 0,1:05:23.66,1:05:25.08,Default,,0,0,0,,因为实际发生的事情是这样的\nDialogue: 0,1:05:25.08,1:05:26.35,Default,,0,0,0,,我先把这个画成序对\nDialogue: 0,1:05:26.89,1:05:28.03,Default,,0,0,0,,假设我要构造一个特别大的流\nDialogue: 0,1:05:28.96,1:05:30.12,Default,,0,0,0,,比如枚举一段区间\nDialogue: 0,1:05:30.32,1:05:31.48,Default,,0,0,0,,从1到1,000,000,000\nDialogue: 0,1:05:32.74,1:05:35.74,Default,,0,0,0,,这实际上是一个序对\nDialogue: 0,1:05:39.34,1:05:43.36,Default,,0,0,0,,由1和一个PROMISE组成\nDialogue: 0,1:05:46.73,1:05:47.89,Default,,0,0,0,,就是这样\nDialogue: 0,1:05:47.89,1:05:48.76,Default,,0,0,0,,什么都没有构造\nDialogue: 0,1:05:51.60,1:05:53.29,Default,,0,0,0,,当我继续FORCE这个PROMISE\nDialogue: 0,1:05:54.51,1:05:56.37,Default,,0,0,0,,再来看看 会发生什么\nDialogue: 0,1:05:56.37,1:05:59.66,Default,,0,0,0,,这个东西现在就成为了一个递归CONS\nDialogue: 0,1:06:00.53,1:06:02.16,Default,,0,0,0,,所以这个PROMISE现在就变成了\nDialogue: 0,1:06:04.62,1:06:08.96,Default,,0,0,0,,一个2和做更多事情的PROMISE\nDialogue: 0,1:06:11.35,1:06:12.73,Default,,0,0,0,,一直这样下去\nDialogue: 0,1:06:14.47,1:06:17.63,Default,,0,0,0,,直到你走完整个流才完整地构建了一个表\nDialogue: 0,1:06:18.20,1:06:19.58,Default,,0,0,0,,因为这个东西不是表\nDialogue: 0,1:06:20.03,1:06:21.48,Default,,0,0,0,,只是一个生成表的PROMISE\nDialogue: 0,1:06:23.39,1:06:25.50,Default,,0,0,0,,技术上来说 PROMISE就是一个过程\nDialogue: 0,1:06:27.80,1:06:29.10,Default,,0,0,0,,因此并没有直接构造好一个表\nDialogue: 0,1:06:30.76,1:06:32.72,Default,,0,0,0,,我应该早点说的\nDialogue: 0,1:06:34.28,1:06:35.34,Default,,0,0,0,,好吧 就到这里 下课\nDialogue: 0,1:06:35.82,1:06:51.15,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:06:35.82,1:06:51.15,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec6a.eng.ass",
    "content": "[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: EN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:09.67,0:00:13.34,EN,,0,0,0,,Stream\nDialogue: 0,0:00:18.55,0:00:21.84,EN,,0,0,0,,PROFESSOR: Well, last time Gerry really let the cat out of the bag.\nDialogue: 0,0:00:22.49,0:00:24.60,EN,,0,0,0,,He introduced the idea of assignment.\nDialogue: 0,0:00:26.35,0:00:33.61,EN,,0,0,0,,Assignment and state.\nDialogue: 0,0:00:37.48,0:00:40.03,EN,,0,0,0,,And as we started to see, the implications\nDialogue: 0,0:00:40.72,0:00:43.16,EN,,0,0,0,,of introducing assignment and state into the language\nDialogue: 0,0:00:43.16,0:00:44.41,EN,,0,0,0,,are absolutely frightening.\nDialogue: 0,0:00:45.08,0:00:48.62,EN,,0,0,0,,First of all, the substitution model of evaluation breaks down.\nDialogue: 0,0:00:49.13,0:00:52.48,EN,,0,0,0,,And we have to use this much more complicated environment model\nDialogue: 0,0:00:52.48,0:00:54.27,EN,,0,0,0,,this very mechanistic thing with diagrams,\nDialogue: 0,0:00:54.28,0:00:57.24,EN,,0,0,0,,even to say what statements in the programming language mean.\nDialogue: 0,0:00:58.46,0:01:00.12,EN,,0,0,0,,And that's not a mere technical point.\nDialogue: 0,0:01:00.26,0:01:03.28,EN,,0,0,0,,See, it's not that we had this particular substitution model and,\nDialogue: 0,0:01:03.60,0:01:05.68,EN,,0,0,0,,well, it doesn't quite work, so we have to do something else.\nDialogue: 0,0:01:05.71,0:01:09.79,EN,,0,0,0,,It's that nothing like the substitution model can work.\nDialogue: 0,0:01:10.73,0:01:13.32,EN,,0,0,0,,Because suddenly, a variable\nDialogue: 0,0:01:14.12,0:01:16.92,EN,,0,0,0,,is not just something that stands for a value.\nDialogue: 0,0:01:17.95,0:01:21.76,EN,,0,0,0,,A variable now has to somehow specify a place\nDialogue: 0,0:01:22.40,0:01:23.34,EN,,0,0,0,,that holds a value.\nDialogue: 0,0:01:23.63,0:01:26.14,EN,,0,0,0,,And the value that's in that place can change.\nDialogue: 0,0:01:30.28,0:01:34.09,EN,,0,0,0,,Or for instance, an expression like f of x\nDialogue: 0,0:01:37.36,0:01:39.64,EN,,0,0,0,,might have a side effect in it.\nDialogue: 0,0:01:40.41,0:01:42.60,EN,,0,0,0,,So if we say f of x and it has some value,\nDialogue: 0,0:01:43.18,0:01:45.34,EN,,0,0,0,,and then later we say f of x again,\nDialogue: 0,0:01:47.24,0:01:48.43,EN,,0,0,0,,we might get a different value\nDialogue: 0,0:01:48.86,0:01:49.74,EN,,0,0,0,,depending on the order.\nDialogue: 0,0:01:49.76,0:01:52.14,EN,,0,0,0,,So suddenly, we have to think not only about values\nDialogue: 0,0:01:52.52,0:01:53.60,EN,,0,0,0,,but about time.\nDialogue: 0,0:01:57.97,0:01:59.98,EN,,0,0,0,,And then things like pairs\nDialogue: 0,0:02:00.65,0:02:02.52,EN,,0,0,0,,are no longer just their CARs and their CDRs.\nDialogue: 0,0:02:02.52,0:02:05.61,EN,,0,0,0,,A pair now is not quite its CAR and its CDR.\nDialogue: 0,0:02:05.80,0:02:07.05,EN,,0,0,0,,It's rather its identity.\nDialogue: 0,0:02:08.44,0:02:11.65,EN,,0,0,0,,So a pair has identity.\nDialogue: 0,0:02:11.65,0:02:12.59,EN,,0,0,0,,It's an object.\nDialogue: 0,0:02:21.33,0:02:25.15,EN,,0,0,0,,And two pairs that have the same CAR and CDR\nDialogue: 0,0:02:25.40,0:02:27.05,EN,,0,0,0,,well, might be the same or different,\nDialogue: 0,0:02:27.87,0:02:30.51,EN,,0,0,0,,because suddenly we have to worry about sharing.\nDialogue: 0,0:02:34.96,0:02:39.45,EN,,0,0,0,,So all of these things enter as soon as we introduce assignment.\nDialogue: 0,0:02:40.48,0:02:43.98,EN,,0,0,0,,See, this is a really far cry from where we started with substitution.\nDialogue: 0,0:02:45.04,0:02:48.91,EN,,0,0,0,,It's a technically harder way of looking at things\nDialogue: 0,0:02:48.94,0:02:53.45,EN,,0,0,0,,because we have to think more mechanistically about our programming language.\nDialogue: 0,0:02:53.47,0:02:55.34,EN,,0,0,0,,We can't just think about it as mathematics.\nDialogue: 0,0:02:55.71,0:02:58.60,EN,,0,0,0,,It's philosophically harder,\nDialogue: 0,0:02:59.15,0:03:00.65,EN,,0,0,0,,because suddenly there are all these funny issues\nDialogue: 0,0:03:00.67,0:03:02.38,EN,,0,0,0,,what does it mean that something changes\nDialogue: 0,0:03:02.38,0:03:03.77,EN,,0,0,0,,or that two things are the same.\nDialogue: 0,0:03:03.84,0:03:06.83,EN,,0,0,0,,And also, it's programming harder, because\nDialogue: 0,0:03:07.47,0:03:08.54,EN,,0,0,0,,as Gerry showed last time,\nDialogue: 0,0:03:08.56,0:03:12.20,EN,,0,0,0,,there are all these bugs having to do with bad sequencing and aliasing\nDialogue: 0,0:03:12.22,0:03:16.19,EN,,0,0,0,,that just don't exist in a language where we don't worry about objects.\nDialogue: 0,0:03:18.21,0:03:21.20,EN,,0,0,0,,Well, how'd we get into this mess?\nDialogue: 0,0:03:24.01,0:03:27.20,EN,,0,0,0,,Remember what we did, the reason we got into this is\nDialogue: 0,0:03:27.40,0:03:31.47,EN,,0,0,0,,because we were looking to build modular systems.\nDialogue: 0,0:03:35.15,0:03:37.69,EN,,0,0,0,,We wanted to build systems that\nDialogue: 0,0:03:38.09,0:03:41.04,EN,,0,0,0,,that fall apart into chunks that seem natural.\nDialogue: 0,0:03:42.76,0:03:43.82,EN,,0,0,0,,So for instance,\nDialogue: 0,0:03:44.06,0:03:46.11,EN,,0,0,0,,we want to take a random number generator\nDialogue: 0,0:03:46.22,0:03:49.40,EN,,0,0,0,,and package up the state of that random number generator inside of it\nDialogue: 0,0:03:50.25,0:03:53.71,EN,,0,0,0,,so that we can separate the idea of picking random numbers\nDialogue: 0,0:03:54.65,0:03:57.79,EN,,0,0,0,,from the general Monte Carlo strategy of estimating something\nDialogue: 0,0:03:58.65,0:04:01.52,EN,,0,0,0,,and separate that from the particular way that you\nDialogue: 0,0:04:01.90,0:04:05.74,EN,,0,0,0,,work with random numbers in that formula developed by Cesaro for pi.\nDialogue: 0,0:04:06.80,0:04:07.92,EN,,0,0,0,,And similarly,\nDialogue: 0,0:04:09.61,0:04:11.74,EN,,0,0,0,,when we go off and construct some models of things,\nDialogue: 0,0:04:12.35,0:04:16.01,EN,,0,0,0,,Ah, if we go off and model a system that we see in the real world,\nDialogue: 0,0:04:17.31,0:04:19.42,EN,,0,0,0,,we'd like our program to break into natural pieces,\nDialogue: 0,0:04:19.44,0:04:20.52,EN,,0,0,0,,pieces that mirror\nDialogue: 0,0:04:21.05,0:04:23.16,EN,,0,0,0,,the parts of the system that we see in the real world.\nDialogue: 0,0:04:24.90,0:04:27.56,EN,,0,0,0,,So for example, if we look at a digital circuit,\nDialogue: 0,0:04:28.36,0:04:29.18,EN,,0,0,0,,we say, gee,\nDialogue: 0,0:04:30.44,0:04:31.44,EN,,0,0,0,,there's a circuit\nDialogue: 0,0:04:32.08,0:04:35.16,EN,,0,0,0,,and it has a piece and it has another piece.\nDialogue: 0,0:04:40.10,0:04:43.58,EN,,0,0,0,,And these different pieces sort of have identity.\nDialogue: 0,0:04:43.58,0:04:44.59,EN,,0,0,0,,They have state.\nDialogue: 0,0:04:45.55,0:04:47.13,EN,,0,0,0,,And the state sits on these wires.\nDialogue: 0,0:04:48.58,0:04:50.22,EN,,0,0,0,,And we think of this piece as an object\nDialogue: 0,0:04:50.49,0:04:51.93,EN,,0,0,0,,that's different from that as an object.\nDialogue: 0,0:04:52.54,0:04:53.85,EN,,0,0,0,,And when we watch the system change,\nDialogue: 0,0:04:53.87,0:04:55.40,EN,,0,0,0,,we think about a signal coming in here\nDialogue: 0,0:04:55.63,0:04:58.41,EN,,0,0,0,,changing a state that might be here and going here\nDialogue: 0,0:04:58.67,0:05:00.75,EN,,0,0,0,,and interacting with a state that might be stored there,\nDialogue: 0,0:05:01.24,0:05:02.17,EN,,0,0,0,,and so on and so on.\nDialogue: 0,0:05:06.86,0:05:11.24,EN,,0,0,0,,So what we'd like is we'd like to build in the computer\nDialogue: 0,0:05:12.76,0:05:14.36,EN,,0,0,0,,systems that fall into pieces\nDialogue: 0,0:05:14.68,0:05:17.87,EN,,0,0,0,,that fall into pieces that mirror our view of reality,\nDialogue: 0,0:05:17.88,0:05:19.87,EN,,0,0,0,,of the way that the actual systems we're modeling\nDialogue: 0,0:05:19.88,0:05:20.91,EN,,0,0,0,,seem to fall into pieces.\nDialogue: 0,0:05:23.20,0:05:23.48,EN,,0,0,0,,Well,\nDialogue: 0,0:05:25.74,0:05:28.99,EN,,0,0,0,,maybe the reason that building systems like this\nDialogue: 0,0:05:28.99,0:05:31.50,EN,,0,0,0,,seems to introduce such technical complications\nDialogue: 0,0:05:31.52,0:05:32.75,EN,,0,0,0,,has nothing to do with computers.\nDialogue: 0,0:05:33.61,0:05:35.60,EN,,0,0,0,,See, maybe the real reason\nDialogue: 0,0:05:36.70,0:05:38.65,EN,,0,0,0,,that we pay such a price to write programs\nDialogue: 0,0:05:38.67,0:05:40.94,EN,,0,0,0,,that mirror our view of reality\nDialogue: 0,0:05:41.52,0:05:43.13,EN,,0,0,0,,is that we have the wrong view of reality.\nDialogue: 0,0:05:44.55,0:05:46.75,EN,,0,0,0,,See, maybe time is just an illusion,\nDialogue: 0,0:05:47.26,0:05:48.60,EN,,0,0,0,,and nothing ever changes.\nDialogue: 0,0:05:50.15,0:05:51.71,EN,,0,0,0,,See, for example, if I take this chalk,\nDialogue: 0,0:05:52.44,0:05:53.77,EN,,0,0,0,,and we say, gee, this is an object\nDialogue: 0,0:05:54.01,0:05:54.99,EN,,0,0,0,,and it has a state.\nDialogue: 0,0:05:55.82,0:05:59.29,EN,,0,0,0,,At each moment it has a position and a velocity.\nDialogue: 0,0:05:59.71,0:06:01.48,EN,,0,0,0,,And if we do something, that state can change.\nDialogue: 0,0:06:04.34,0:06:07.37,EN,,0,0,0,,But if you studied any relativity, for instance,\nDialogue: 0,0:06:07.74,0:06:09.71,EN,,0,0,0,,you know that you don't think of the path of that chalk\nDialogue: 0,0:06:09.72,0:06:11.34,EN,,0,0,0,,as something that goes on instant by instant.\nDialogue: 0,0:06:11.34,0:06:14.38,EN,,0,0,0,,It's more insightful to think of that whole chalk's existence\nDialogue: 0,0:06:14.41,0:06:15.64,EN,,0,0,0,,as a path in space-time.\nDialogue: 0,0:06:16.02,0:06:17.37,EN,,0,0,0,,that's all splayed out.\nDialogue: 0,0:06:17.87,0:06:19.84,EN,,0,0,0,,There aren't individual positions and velocities.\nDialogue: 0,0:06:19.84,0:06:23.80,EN,,0,0,0,,There's just its unchanging existence in space-time.\nDialogue: 0,0:06:24.64,0:06:26.51,EN,,0,0,0,,Similarly, if we look at this electrical system,\nDialogue: 0,0:06:27.69,0:06:30.43,EN,,0,0,0,,if we imagine this electrical system is implementing\nDialogue: 0,0:06:30.59,0:06:33.96,EN,,0,0,0,,sort of signal processing system,\nDialogue: 0,0:06:34.36,0:06:36.68,EN,,0,0,0,,the signal processing engineer who put that thing together\nDialogue: 0,0:06:36.75,0:06:38.60,EN,,0,0,0,,doesn't think of it as, well,\nDialogue: 0,0:06:38.96,0:06:41.40,EN,,0,0,0,,at each instance there's a voltage coming in.\nDialogue: 0,0:06:41.49,0:06:43.16,EN,,0,0,0,,And that translates into something.\nDialogue: 0,0:06:43.34,0:06:45.52,EN,,0,0,0,,And that affects the state over here,\nDialogue: 0,0:06:45.53,0:06:46.81,EN,,0,0,0,,which changes the state over here.\nDialogue: 0,0:06:46.81,0:06:50.11,EN,,0,0,0,,Nobody putting together a signal processing system thinks about it like that.\nDialogue: 0,0:06:50.42,0:06:51.84,EN,,0,0,0,,Instead, you say there's this signal\nDialogue: 0,0:06:54.04,0:06:58.06,EN,,0,0,0,,that's splayed out over time.\nDialogue: 0,0:06:58.06,0:06:59.48,EN,,0,0,0,,And if this is acting as a filter,\nDialogue: 0,0:07:00.20,0:07:04.04,EN,,0,0,0,,this whole thing transforms this whole thing\nDialogue: 0,0:07:04.28,0:07:07.04,EN,,0,0,0,,for some sort of other output.\nDialogue: 0,0:07:09.57,0:07:11.28,EN,,0,0,0,,You don't think of it as what's happening\nDialogue: 0,0:07:11.28,0:07:13.29,EN,,0,0,0,,instant by instant as the state of these things.\nDialogue: 0,0:07:14.16,0:07:17.32,EN,,0,0,0,,And somehow you think of this box as a whole thing,\nDialogue: 0,0:07:17.32,0:07:20.16,EN,,0,0,0,,not as little pieces sending messages of state\nDialogue: 0,0:07:20.40,0:07:21.96,EN,,0,0,0,,to each other at particular instants.\nDialogue: 0,0:07:28.25,0:07:29.36,EN,,0,0,0,,Well, today we're going to look at\nDialogue: 0,0:07:29.39,0:07:31.13,EN,,0,0,0,,another way to decompose systems\nDialogue: 0,0:07:31.36,0:07:35.45,EN,,0,0,0,,that's more like the signal processing engineer's view of the world\nDialogue: 0,0:07:35.69,0:07:38.96,EN,,0,0,0,,than it is like thinking about objects that communicate sending messages.\nDialogue: 0,0:07:41.13,0:07:43.74,EN,,0,0,0,,That's called stream processing.\nDialogue: 0,0:07:54.57,0:07:58.96,EN,,0,0,0,,And we're going to start by showing\nDialogue: 0,0:08:00.59,0:08:04.16,EN,,0,0,0,,by showing how we can make our programs more uniform\nDialogue: 0,0:08:05.15,0:08:06.54,EN,,0,0,0,,and see a lot more commonality\nDialogue: 0,0:08:06.65,0:08:09.88,EN,,0,0,0,,if we throw out of these programs\nDialogue: 0,0:08:10.81,0:08:12.30,EN,,0,0,0,,what you might say is a\nDialogue: 0,0:08:12.35,0:08:15.12,EN,,0,0,0,,inordinate concern with worrying about time.\nDialogue: 0,0:08:16.89,0:08:20.22,EN,,0,0,0,,Let me start by comparing two procedures.\nDialogue: 0,0:08:23.55,0:08:25.69,EN,,0,0,0,,The first one does this.\nDialogue: 0,0:08:25.69,0:08:27.77,EN,,0,0,0,,We imagine that there's a tree.\nDialogue: 0,0:08:30.40,0:08:32.14,EN,,0,0,0,,Say there's a tree of integers.\nDialogue: 0,0:08:33.28,0:08:34.42,EN,,0,0,0,,It's a binary tree.\nDialogue: 0,0:08:36.12,0:08:36.97,EN,,0,0,0,,Say 1.\nDialogue: 0,0:08:39.10,0:08:40.23,EN,,0,0,0,,So it looks like this.\nDialogue: 0,0:08:40.23,0:08:42.92,EN,,0,0,0,,And there's integers in each of the nodes.\nDialogue: 0,0:08:45.18,0:08:47.80,EN,,0,0,0,,And what we would like to compute is\nDialogue: 0,0:08:48.67,0:08:51.56,EN,,0,0,0,,for each odd number sitting here,\nDialogue: 0,0:08:52.30,0:08:55.10,EN,,0,0,0,,we'd like to find the square and then sum up all those squares.\nDialogue: 0,0:08:57.05,0:08:59.48,EN,,0,0,0,,Well, that should be a familiar kind of thing.\nDialogue: 0,0:08:59.48,0:09:01.95,EN,,0,0,0,,There's a recursive strategy for doing it.\nDialogue: 0,0:09:02.93,0:09:04.35,EN,,0,0,0,,We look at each leaf, and either\nDialogue: 0,0:09:04.56,0:09:06.68,EN,,0,0,0,,it's going to contribute the square of the number if it's odd\nDialogue: 0,0:09:06.70,0:09:07.77,EN,,0,0,0,,or 0 if it's even.\nDialogue: 0,0:09:08.68,0:09:12.11,EN,,0,0,0,,And then recursively, we can say at each tree\nDialogue: 0,0:09:12.65,0:09:13.84,EN,,0,0,0,,the sum of all of them is\nDialogue: 0,0:09:13.92,0:09:15.93,EN,,0,0,0,,the sum coming from the right branch and the left branch,\nDialogue: 0,0:09:16.25,0:09:17.64,EN,,0,0,0,,and recursively down through the nodes.\nDialogue: 0,0:09:17.64,0:09:18.70,EN,,0,0,0,,And that's a familiar way of\nDialogue: 0,0:09:19.26,0:09:20.36,EN,,0,0,0,,thinking about programming.\nDialogue: 0,0:09:20.36,0:09:22.59,EN,,0,0,0,,Let's actually look at that on the slide.\nDialogue: 0,0:09:23.82,0:09:26.75,EN,,0,0,0,,We say to sum the odd squares in a tree,\nDialogue: 0,0:09:27.37,0:09:29.36,EN,,0,0,0,,there's a test. Either it's a leaf node,\nDialogue: 0,0:09:29.82,0:09:31.95,EN,,0,0,0,,and we're going to check to see if it's an integer,\nDialogue: 0,0:09:32.88,0:09:36.38,EN,,0,0,0,,and then either it's odd, in which we take the square, or else it's 0.\nDialogue: 0,0:09:37.16,0:09:38.99,EN,,0,0,0,,And then the sum of the whole thing\nDialogue: 0,0:09:39.21,0:09:42.12,EN,,0,0,0,,is the sum coming from the left branch and the right branch.\nDialogue: 0,0:09:46.34,0:09:50.56,EN,,0,0,0,,OK, well, let me contrast that with a second problem.\nDialogue: 0,0:09:51.56,0:09:53.68,EN,,0,0,0,,Suppose I give you an integer n,\nDialogue: 0,0:09:54.73,0:09:57.88,EN,,0,0,0,,and then some function to compute of the first of each integer\nDialogue: 0,0:09:57.93,0:09:58.83,EN,,0,0,0,,1 through n.\nDialogue: 0,0:09:59.10,0:10:01.08,EN,,0,0,0,,And then I want to collect together in a list\nDialogue: 0,0:10:01.28,0:10:04.65,EN,,0,0,0,,all those function values that satisfy some property.\nDialogue: 0,0:10:05.60,0:10:06.88,EN,,0,0,0,,That's a general kind of thing.\nDialogue: 0,0:10:06.88,0:10:07.98,EN,,0,0,0,,Let's say to be specific,\nDialogue: 0,0:10:08.62,0:10:10.48,EN,,0,0,0,,let's imagine that for each integer, k,\nDialogue: 0,0:10:10.65,0:10:12.51,EN,,0,0,0,,we're going to compute the k Fibonacci number.\nDialogue: 0,0:10:14.21,0:10:16.27,EN,,0,0,0,,And then we'll see which of those are odd\nDialogue: 0,0:10:16.83,0:10:18.40,EN,,0,0,0,,and assemble those into a list.\nDialogue: 0,0:10:19.05,0:10:20.71,EN,,0,0,0,,So here's a procedure that does that.\nDialogue: 0,0:10:23.73,0:10:26.24,EN,,0,0,0,,Find the odd Fibonacci numbers among the first n.\nDialogue: 0,0:10:26.24,0:10:28.91,EN,,0,0,0,,And here is a standard loop the way we've been writing it.\nDialogue: 0,0:10:28.91,0:10:29.82,EN,,0,0,0,,This is a recursion.\nDialogue: 0,0:10:30.80,0:10:31.79,EN,,0,0,0,,It's a loop on k,\nDialogue: 0,0:10:32.03,0:10:34.35,EN,,0,0,0,,and says if k is bigger than n, it's the empty list.\nDialogue: 0,0:10:35.13,0:10:37.36,EN,,0,0,0,,Otherwise we compute the k-th Fibonacci number,\nDialogue: 0,0:10:37.44,0:10:38.06,EN,,0,0,0,,call that f.\nDialogue: 0,0:10:40.37,0:10:42.84,EN,,0,0,0,,If it's odd, we CONS it on\nDialogue: 0,0:10:43.76,0:10:46.01,EN,,0,0,0,,to the list starting with the next one.\nDialogue: 0,0:10:47.69,0:10:50.12,EN,,0,0,0,,And otherwise, we just take the next one.\nDialogue: 0,0:10:50.73,0:10:53.00,EN,,0,0,0,,And this is the standard way we've been writing iterative loops.\nDialogue: 0,0:10:53.00,0:10:55.56,EN,,0,0,0,,And we start off calling that loop with 1.\nDialogue: 0,0:10:57.58,0:11:00.06,EN,,0,0,0,,OK, so there are two procedures.\nDialogue: 0,0:11:01.60,0:11:02.90,EN,,0,0,0,,Those procedures look very different.\nDialogue: 0,0:11:02.90,0:11:04.20,EN,,0,0,0,,They have very different structures.\nDialogue: 0,0:11:04.25,0:11:06.89,EN,,0,0,0,,Yet from a certain point of view,\nDialogue: 0,0:11:06.92,0:11:09.61,EN,,0,0,0,,those procedures are really doing very much the same thing.\nDialogue: 0,0:11:11.33,0:11:14.67,EN,,0,0,0,,So if I was talking like a signal processing engineer,\nDialogue: 0,0:11:14.70,0:11:16.81,EN,,0,0,0,,what I might say\nDialogue: 0,0:11:18.24,0:11:26.76,EN,,0,0,0,,the first procedure enumerates the leaves of a tree.\nDialogue: 0,0:11:31.16,0:11:34.56,EN,,0,0,0,,And then we can think of a signal coming out of that, which is all the leaves.\nDialogue: 0,0:11:35.33,0:11:43.39,EN,,0,0,0,,We'll filter them to see which ones are odd,\nDialogue: 0,0:11:43.58,0:11:44.94,EN,,0,0,0,,put them through some kind of filter.\nDialogue: 0,0:11:45.19,0:11:47.79,EN,,0,0,0,,We'll then put them through a kind of transducer.\nDialogue: 0,0:11:49.20,0:11:51.69,EN,,0,0,0,,And for each one of those things, we'll take the square.\nDialogue: 0,0:11:54.44,0:11:57.44,EN,,0,0,0,,And then we'll accumulate all of those.\nDialogue: 0,0:11:58.29,0:12:00.04,EN,,0,0,0,,We'll accumulate them by sticking them together\nDialogue: 0,0:12:00.35,0:12:03.37,EN,,0,0,0,,with addition starting from 0.\nDialogue: 0,0:12:07.14,0:12:08.21,EN,,0,0,0,,That's the first program.\nDialogue: 0,0:12:08.21,0:12:09.18,EN,,0,0,0,,The second program,\nDialogue: 0,0:12:09.24,0:12:11.21,EN,,0,0,0,,I can describe in a very, very similar way.\nDialogue: 0,0:12:11.78,0:12:13.42,EN,,0,0,0,,I'll say, we'll enumerate\nDialogue: 0,0:12:15.80,0:12:19.10,EN,,0,0,0,,the numbers on this interval, for the interval 1 through n.\nDialogue: 0,0:12:22.50,0:12:24.40,EN,,0,0,0,,We'll, for each one,\nDialogue: 0,0:12:25.45,0:12:26.92,EN,,0,0,0,,compute the Fibonacci number,\nDialogue: 0,0:12:27.79,0:12:29.27,EN,,0,0,0,,put them through a transducer.\nDialogue: 0,0:12:29.27,0:12:30.78,EN,,0,0,0,,We'll then take the result of that,\nDialogue: 0,0:12:31.31,0:12:34.20,EN,,0,0,0,,and we'll filter it for oddness.\nDialogue: 0,0:12:36.27,0:12:39.24,EN,,0,0,0,,And then we'll take those and put them into an accumulator.\nDialogue: 0,0:12:39.35,0:12:40.56,EN,,0,0,0,,This time we'll build up a list,\nDialogue: 0,0:12:40.78,0:12:42.17,EN,,0,0,0,,so we'll accumulate with CONS\nDialogue: 0,0:12:42.59,0:12:43.77,EN,,0,0,0,,starting from the empty list.\nDialogue: 0,0:12:47.11,0:12:49.80,EN,,0,0,0,,So this way of looking at the program\nDialogue: 0,0:12:49.85,0:12:51.84,EN,,0,0,0,,makes the two seem very, very similar.\nDialogue: 0,0:12:51.90,0:12:52.84,EN,,0,0,0,,The problem is\nDialogue: 0,0:12:53.20,0:12:56.49,EN,,0,0,0,,that that commonality is completely obscured\nDialogue: 0,0:12:56.64,0:12:58.05,EN,,0,0,0,,when we look at the procedures we wrote.\nDialogue: 0,0:12:58.05,0:13:01.44,EN,,0,0,0,,Let's go back and look at some odd squares again,\nDialogue: 0,0:13:02.22,0:13:04.64,EN,,0,0,0,,and say things like, where's the enumerator?\nDialogue: 0,0:13:06.35,0:13:08.14,EN,,0,0,0,,Where's the enumerator in this program?\nDialogue: 0,0:13:08.14,0:13:10.52,EN,,0,0,0,,Well, it's not in one place.\nDialogue: 0,0:13:11.02,0:13:15.47,EN,,0,0,0,,It's a little bit in this leaf-node test,\nDialogue: 0,0:13:16.43,0:13:17.16,EN,,0,0,0,,which is going to stop.\nDialogue: 0,0:13:17.16,0:13:20.06,EN,,0,0,0,,It's a little bit in the recursive structure of the thing itself.\nDialogue: 0,0:13:23.15,0:13:24.12,EN,,0,0,0,,Where's the accumulator?\nDialogue: 0,0:13:24.12,0:13:25.68,EN,,0,0,0,,The accumulator isn't in one place either.\nDialogue: 0,0:13:25.68,0:13:30.73,EN,,0,0,0,,It's partly in this 0 and partly in this plus.\nDialogue: 0,0:13:32.00,0:13:34.51,EN,,0,0,0,,Right? It's not there as a thing that we can look at.\nDialogue: 0,0:13:34.51,0:13:39.05,EN,,0,0,0,,Similarly, if we look at odd Fibs,\nDialogue: 0,0:13:39.05,0:13:42.80,EN,,0,0,0,,that's also, in some sense, an enumerator and an accumulator,\nDialogue: 0,0:13:42.80,0:13:44.01,EN,,0,0,0,,but it looks very different.\nDialogue: 0,0:13:44.62,0:13:50.09,EN,,0,0,0,,Because partly, the enumerator is here in this greater than sign in the test.\nDialogue: 0,0:13:50.38,0:13:52.84,EN,,0,0,0,,And partly it's in this whole recursive structure in the loop,\nDialogue: 0,0:13:53.18,0:13:54.24,EN,,0,0,0,,and the way that we call it.\nDialogue: 0,0:13:55.68,0:13:56.32,EN,,0,0,0,,And then similarly,\nDialogue: 0,0:13:56.52,0:13:58.76,EN,,0,0,0,,that's also mixed up in there with the accumulator,\nDialogue: 0,0:13:58.91,0:14:00.12,EN,,0,0,0,,which is partly over there\nDialogue: 0,0:14:00.41,0:14:01.40,EN,,0,0,0,,and partly over there.\nDialogue: 0,0:14:03.60,0:14:06.08,EN,,0,0,0,,So these very, very natural pieces,\nDialogue: 0,0:14:08.73,0:14:12.65,EN,,0,0,0,,these very natural boxes here don't appear in our programs.\nDialogue: 0,0:14:13.26,0:14:14.36,EN,,0,0,0,,Because they're kind of mixed up.\nDialogue: 0,0:14:14.36,0:14:16.29,EN,,0,0,0,,The programs don't chop things up in the right way.\nDialogue: 0,0:14:19.45,0:14:22.17,EN,,0,0,0,,Going back to this fundamental principle of computer science\nDialogue: 0,0:14:22.19,0:14:23.63,EN,,0,0,0,,that in order to control something,\nDialogue: 0,0:14:23.63,0:14:24.96,EN,,0,0,0,,you need the name of it,\nDialogue: 0,0:14:25.80,0:14:28.44,EN,,0,0,0,,we don't really have control over thinking about things this way\nDialogue: 0,0:14:28.67,0:14:31.06,EN,,0,0,0,,because we don't have our hands in them explicitly.\nDialogue: 0,0:14:31.06,0:14:33.80,EN,,0,0,0,,We don't have a good language for talking about them.\nDialogue: 0,0:14:35.42,0:14:38.86,EN,,0,0,0,,Well, let's invent an appropriate language\nDialogue: 0,0:14:42.52,0:14:44.04,EN,,0,0,0,,in which we can build these pieces.\nDialogue: 0,0:14:44.78,0:14:47.21,EN,,0,0,0,,The key to the language is these guys,\nDialogue: 0,0:14:47.21,0:14:49.71,EN,,0,0,0,,is what is these things I called signals?\nDialogue: 0,0:14:50.48,0:14:53.32,EN,,0,0,0,,What are these things that are flying on the arrows between the boxes?\nDialogue: 0,0:14:56.88,0:14:57.71,EN,,0,0,0,,Well, those things\nDialogue: 0,0:14:59.85,0:15:03.52,EN,,0,0,0,,are going to be data structures called streams.\nDialogue: 0,0:15:03.79,0:15:05.87,EN,,0,0,0,,That's going to be the key to inventing this language.\nDialogue: 0,0:15:07.98,0:15:08.51,EN,,0,0,0,,What's a stream?\nDialogue: 0,0:15:08.52,0:15:11.50,EN,,0,0,0,,Well, a stream is, like anything else, a data abstraction.\nDialogue: 0,0:15:12.22,0:15:15.82,EN,,0,0,0,,So I should tell you what its selectors and constructors are.\nDialogue: 0,0:15:16.87,0:15:19.48,EN,,0,0,0,,For a stream, we're going to have one constructor\nDialogue: 0,0:15:19.98,0:15:21.43,EN,,0,0,0,,that's called CONS-stream.\nDialogue: 0,0:15:25.69,0:15:28.11,EN,,0,0,0,,CONS-stream is going to put two things together\nDialogue: 0,0:15:28.59,0:15:30.22,EN,,0,0,0,,to form a thing called a stream.\nDialogue: 0,0:15:32.04,0:15:33.85,EN,,0,0,0,,And then to extract things from the stream,\nDialogue: 0,0:15:33.98,0:15:36.11,EN,,0,0,0,,we're going to have a selector called the head of the stream.\nDialogue: 0,0:15:38.01,0:15:38.86,EN,,0,0,0,,So if I have a stream,\nDialogue: 0,0:15:39.00,0:15:40.41,EN,,0,0,0,,I can take its head\nDialogue: 0,0:15:41.13,0:15:42.38,EN,,0,0,0,,or I can take its tail.\nDialogue: 0,0:15:44.72,0:15:47.42,EN,,0,0,0,,And remember, I have to tell you George's contract\nDialogue: 0,0:15:48.24,0:15:52.70,EN,,0,0,0,,to tell you what the axioms are that relate these.\nDialogue: 0,0:15:53.44,0:16:00.17,EN,,0,0,0,,And it's going to be for any x and y,\nDialogue: 0,0:16:03.40,0:16:05.44,EN,,0,0,0,,if I form the CONS-stream and take the head,\nDialogue: 0,0:16:05.69,0:16:11.96,EN,,0,0,0,,the head of CONS-stream of x and y\nDialogue: 0,0:16:13.29,0:16:14.52,EN,,0,0,0,,is going to be x\nDialogue: 0,0:16:16.14,0:16:27.45,EN,,0,0,0,,and the tail of CONS-stream of x and y is going to be y.\nDialogue: 0,0:16:28.44,0:16:34.75,EN,,0,0,0,,So those are the constructor, two selectors for streams, and an axiom.\nDialogue: 0,0:16:34.75,0:16:35.85,EN,,0,0,0,,There's something fishy here.\nDialogue: 0,0:16:36.98,0:16:39.00,EN,,0,0,0,,So you might notice that these are exactly\nDialogue: 0,0:16:40.19,0:16:42.08,EN,,0,0,0,,the axioms for CONS, CAR, and CDR.\nDialogue: 0,0:16:43.63,0:16:46.56,EN,,0,0,0,,So if I said instead of writing CONS-stream I wrote CONS\nDialogue: 0,0:16:47.10,0:16:49.80,EN,,0,0,0,,and I said head was the CAR and tail was the CDR,\nDialogue: 0,0:16:50.76,0:16:52.81,EN,,0,0,0,,those are exactly the axioms for pairs.\nDialogue: 0,0:16:52.81,0:16:54.32,EN,,0,0,0,,And in fact, there's another thing here.\nDialogue: 0,0:16:55.13,0:16:56.80,EN,,0,0,0,,We're going to have a thing called the-empty-stream\nDialogue: 0,0:17:02.80,0:17:04.04,EN,,0,0,0,,which is like the-empty-list.\nDialogue: 0,0:17:08.31,0:17:10.03,EN,,0,0,0,,So why am I introducing this terminology?\nDialogue: 0,0:17:10.03,0:17:12.12,EN,,0,0,0,,Why don't I just keep talking about pairs and lists?\nDialogue: 0,0:17:12.78,0:17:13.79,EN,,0,0,0,,Well, we'll see.\nDialogue: 0,0:17:15.51,0:17:18.24,EN,,0,0,0,,For now, if you like, why don't you just pretend\nDialogue: 0,0:17:18.30,0:17:21.56,EN,,0,0,0,,that streams really are just a terminology for lists.\nDialogue: 0,0:17:21.56,0:17:22.99,EN,,0,0,0,,And we'll see in a little while why\nDialogue: 0,0:17:23.61,0:17:26.09,EN,,0,0,0,,why we want to keep this extra abstraction layer\nDialogue: 0,0:17:26.83,0:17:28.15,EN,,0,0,0,,and not just call them lists.\nDialogue: 0,0:17:32.30,0:17:33.72,EN,,0,0,0,,OK, now that we have streams,\nDialogue: 0,0:17:33.74,0:17:35.85,EN,,0,0,0,,we can start constructing the pieces of the language\nDialogue: 0,0:17:37.04,0:17:38.17,EN,,0,0,0,,to operate on streams.\nDialogue: 0,0:17:38.75,0:17:42.12,EN,,0,0,0,,And there are a whole bunch of very useful things that we could start making.\nDialogue: 0,0:17:42.12,0:17:42.81,EN,,0,0,0,,For instance,\nDialogue: 0,0:17:44.89,0:17:49.79,EN,,0,0,0,,we'll make our map box to take a stream, s,\nDialogue: 0,0:17:54.80,0:17:56.62,EN,,0,0,0,,and a procedure,\nDialogue: 0,0:17:57.80,0:17:59.21,EN,,0,0,0,,and to generate a new stream\nDialogue: 0,0:18:00.14,0:18:02.28,EN,,0,0,0,,which has as its elements\nDialogue: 0,0:18:02.28,0:18:04.88,EN,,0,0,0,,the procedure applied to all the successive elements of s.\nDialogue: 0,0:18:05.87,0:18:07.40,EN,,0,0,0,,In fact, we've seen this before.\nDialogue: 0,0:18:07.40,0:18:10.24,EN,,0,0,0,,This is the procedure map that we did with lists.\nDialogue: 0,0:18:10.95,0:18:12.60,EN,,0,0,0,,And you see it's exactly map,\nDialogue: 0,0:18:12.60,0:18:14.65,EN,,0,0,0,,except we're testing for empty-stream.\nDialogue: 0,0:18:14.65,0:18:15.56,EN,,0,0,0,,Oh, I forgot to mention that.\nDialogue: 0,0:18:15.56,0:18:17.15,EN,,0,0,0,,Empty-stream is like the null test.\nDialogue: 0,0:18:18.03,0:18:20.48,EN,,0,0,0,,So if it's empty, we generate the empty stream.\nDialogue: 0,0:18:20.51,0:18:22.28,EN,,0,0,0,,Otherwise, we form a new stream\nDialogue: 0,0:18:23.52,0:18:27.18,EN,,0,0,0,,whose first element is the procedure applied to the head of the stream,\nDialogue: 0,0:18:28.51,0:18:29.32,EN,,0,0,0,,and whose rest\nDialogue: 0,0:18:29.60,0:18:32.43,EN,,0,0,0,,is gotten by mapping along with the procedure down the tail of the stream.\nDialogue: 0,0:18:33.14,0:18:35.90,EN,,0,0,0,,So that looks exactly like the map procedure we looked at before.\nDialogue: 0,0:18:37.03,0:18:38.20,EN,,0,0,0,,Here's another useful thing.\nDialogue: 0,0:18:38.35,0:18:40.46,EN,,0,0,0,,Filter, this is our filter box.\nDialogue: 0,0:18:40.46,0:18:43.89,EN,,0,0,0,,We're going to have a predicate and a stream.\nDialogue: 0,0:18:43.89,0:18:45.08,EN,,0,0,0,,We're going to make a new stream\nDialogue: 0,0:18:45.80,0:18:48.17,EN,,0,0,0,,consists of all the elements of the original one that satisfy the predicate.\nDialogue: 0,0:18:48.33,0:18:49.48,EN,,0,0,0,,that satisfy the predicate.\nDialogue: 0,0:18:50.38,0:18:51.31,EN,,0,0,0,,That's case analysis.\nDialogue: 0,0:18:51.32,0:18:52.73,EN,,0,0,0,,When there's nothing in the stream,\nDialogue: 0,0:18:53.04,0:18:54.22,EN,,0,0,0,,we return the empty stream.\nDialogue: 0,0:18:56.28,0:18:59.18,EN,,0,0,0,,We test the predicate on the head of the stream.\nDialogue: 0,0:19:00.06,0:19:01.04,EN,,0,0,0,,And if it's true,\nDialogue: 0,0:19:01.53,0:19:02.83,EN,,0,0,0,,we add the head of the stream onto the result\nDialogue: 0,0:19:03.02,0:19:06.22,EN,,0,0,0,,the result of filtering the tail of the stream.\nDialogue: 0,0:19:08.22,0:19:10.04,EN,,0,0,0,,And otherwise, if that predicate was false,\nDialogue: 0,0:19:10.49,0:19:11.98,EN,,0,0,0,,we just filter the tail of the stream.\nDialogue: 0,0:19:13.50,0:19:14.46,EN,,0,0,0,,Right, so there's filter.\nDialogue: 0,0:19:16.59,0:19:18.56,EN,,0,0,0,,Let me run through a couple more rather quickly.\nDialogue: 0,0:19:18.56,0:19:20.70,EN,,0,0,0,,They're all in the book and you can look at them.\nDialogue: 0,0:19:20.88,0:19:21.80,EN,,0,0,0,,Let me just flash through.\nDialogue: 0,0:19:22.11,0:19:22.94,EN,,0,0,0,,Here's accumulate.\nDialogue: 0,0:19:23.26,0:19:26.92,EN,,0,0,0,,Accumulate takes a way of combining things\nDialogue: 0,0:19:27.36,0:19:29.05,EN,,0,0,0,,an initial value in a stream\nDialogue: 0,0:19:29.96,0:19:31.13,EN,,0,0,0,,and sticks them all together.\nDialogue: 0,0:19:31.56,0:19:33.69,EN,,0,0,0,,If the stream's empty, it's just the initial value.\nDialogue: 0,0:19:33.97,0:19:36.20,EN,,0,0,0,,Otherwise, we combine the head of the stream\nDialogue: 0,0:19:36.32,0:19:37.82,EN,,0,0,0,,with the result of accumulating\nDialogue: 0,0:19:38.01,0:19:40.24,EN,,0,0,0,,the tail of the stream starting from the initial value.\nDialogue: 0,0:19:40.90,0:19:42.83,EN,,0,0,0,,So that's what I'd use to add up everything in the stream.\nDialogue: 0,0:19:42.83,0:19:43.98,EN,,0,0,0,,I'd accumulate with plus.\nDialogue: 0,0:19:45.83,0:19:47.56,EN,,0,0,0,,How would I enumerate the leaves of a tree?\nDialogue: 0,0:19:48.06,0:19:52.89,EN,,0,0,0,,Well, if the tree is just a leaf itself,\nDialogue: 0,0:19:53.79,0:19:55.90,EN,,0,0,0,,I make something which only has that node in it.\nDialogue: 0,0:19:56.64,0:19:59.32,EN,,0,0,0,,Otherwise, I append together the stuff of enumerating\nDialogue: 0,0:19:59.61,0:20:02.35,EN,,0,0,0,,the left branch and the right branch.\nDialogue: 0,0:20:04.34,0:20:08.32,EN,,0,0,0,,And then append here is like the ordinary append on lists.\nDialogue: 0,0:20:13.19,0:20:13.85,EN,,0,0,0,,You can look at that.\nDialogue: 0,0:20:13.85,0:20:17.53,EN,,0,0,0,,That's analogous to the ordinary procedure for appending two lists.\nDialogue: 0,0:20:18.91,0:20:20.60,EN,,0,0,0,,Ah... How would I enumerate an interval?\nDialogue: 0,0:20:21.96,0:20:23.77,EN,,0,0,0,,This will take two integers, low and high,\nDialogue: 0,0:20:23.88,0:20:27.00,EN,,0,0,0,,and generate a stream of the integers going from low to high.\nDialogue: 0,0:20:28.32,0:20:29.88,EN,,0,0,0,,And we can make a whole bunch of pieces.\nDialogue: 0,0:20:31.89,0:20:34.48,EN,,0,0,0,,So that's a little language of talking about streams.\nDialogue: 0,0:20:34.49,0:20:35.32,EN,,0,0,0,,Once we have streams,\nDialogue: 0,0:20:35.32,0:20:37.67,EN,,0,0,0,,we can build things for manipulating them.\nDialogue: 0,0:20:37.67,0:20:39.04,EN,,0,0,0,,Again, we're making a language.\nDialogue: 0,0:20:40.20,0:20:42.22,EN,,0,0,0,,And now we can start expressing things in this language.\nDialogue: 0,0:20:43.06,0:20:47.31,EN,,0,0,0,,Here's our original procedure for summing the odd squares in a tree.\nDialogue: 0,0:20:47.31,0:20:52.62,EN,,0,0,0,,And you'll notice it looks exactly now like the block diagram,\nDialogue: 0,0:20:52.64,0:20:54.59,EN,,0,0,0,,like the signal processing block diagram.\nDialogue: 0,0:20:54.59,0:20:57.53,EN,,0,0,0,,So to sum the odd squares in a tree,\nDialogue: 0,0:20:58.06,0:21:00.80,EN,,0,0,0,,we enumerate the leaves of the tree.\nDialogue: 0,0:21:01.32,0:21:03.72,EN,,0,0,0,,We filter that for oddness.\nDialogue: 0,0:21:04.83,0:21:06.54,EN,,0,0,0,,We map that for squareness.\nDialogue: 0,0:21:09.32,0:21:13.34,EN,,0,0,0,,And we accumulate the result of that using addition, starting from 0.\nDialogue: 0,0:21:14.76,0:21:17.20,EN,,0,0,0,,So we can see the pieces that we wanted.\nDialogue: 0,0:21:17.29,0:21:19.36,EN,,0,0,0,,Similarly, the Fibonacci one,\nDialogue: 0,0:21:20.04,0:21:21.88,EN,,0,0,0,,how do we get the odd Fibs?\nDialogue: 0,0:21:22.05,0:21:24.57,EN,,0,0,0,,Well, we enumerate the interval from 1 to n,\nDialogue: 0,0:21:26.32,0:21:28.64,EN,,0,0,0,,we map along that,\nDialogue: 0,0:21:28.99,0:21:30.70,EN,,0,0,0,,computing the Fibonacci of each one.\nDialogue: 0,0:21:30.92,0:21:33.79,EN,,0,0,0,,We filter the result of those for oddness.\nDialogue: 0,0:21:34.81,0:21:36.64,EN,,0,0,0,,And we accumulate all of that stuff\nDialogue: 0,0:21:36.88,0:21:39.12,EN,,0,0,0,,using CONS starting from the empty-list.\nDialogue: 0,0:21:43.65,0:21:47.53,EN,,0,0,0,,OK, what's the advantage of this?\nDialogue: 0,0:21:47.68,0:21:48.59,EN,,0,0,0,,Well, for one thing,\nDialogue: 0,0:21:48.68,0:21:51.15,EN,,0,0,0,,we now have pieces that we can start mixing and matching.\nDialogue: 0,0:21:51.88,0:21:52.64,EN,,0,0,0,,So for instance,\nDialogue: 0,0:21:52.91,0:21:55.08,EN,,0,0,0,,if I wanted to change this, if I wanted to ah...\nDialogue: 0,0:21:58.19,0:22:00.32,EN,,0,0,0,,compute the squares of the integers and then filter them,\nDialogue: 0,0:22:00.33,0:22:01.34,EN,,0,0,0,,all I need to do\nDialogue: 0,0:22:01.90,0:22:03.64,EN,,0,0,0,,is pick up a standard piece like this\nDialogue: 0,0:22:03.68,0:22:05.40,EN,,0,0,0,,it's a map square and put it in.\nDialogue: 0,0:22:06.57,0:22:07.60,EN,,0,0,0,,Or if we wanted to do\nDialogue: 0,0:22:07.69,0:22:11.45,EN,,0,0,0,,this whole Fibonacci computation on the leaves of a tree\nDialogue: 0,0:22:11.58,0:22:12.36,EN,,0,0,0,,rather than a sequence,\nDialogue: 0,0:22:12.38,0:22:13.24,EN,,0,0,0,,all I need to do\nDialogue: 0,0:22:13.40,0:22:15.93,EN,,0,0,0,,is replace this enumerator with that one.\nDialogue: 0,0:22:18.03,0:22:19.82,EN,,0,0,0,,See, the advantage of this stream processing\nDialogue: 0,0:22:20.24,0:22:21.53,EN,,0,0,0,,is that we're establishing--\nDialogue: 0,0:22:22.36,0:22:24.96,EN,,0,0,0,,this is one of the big themes of the course--\nDialogue: 0,0:22:25.29,0:22:27.48,EN,,0,0,0,,we're establishing conventional interfaces\nDialogue: 0,0:22:32.89,0:22:37.15,EN,,0,0,0,,conventional interfaces that allow us to glue things together.\nDialogue: 0,0:22:38.30,0:22:39.55,EN,,0,0,0,,Things like map and filter\nDialogue: 0,0:22:39.79,0:22:41.64,EN,,0,0,0,,are a standard set of components\nDialogue: 0,0:22:41.68,0:22:44.76,EN,,0,0,0,,that we can start using for pasting together programs in all sorts of ways.\nDialogue: 0,0:22:45.75,0:22:48.81,EN,,0,0,0,,It allows us to see the commonality of programs.\nDialogue: 0,0:22:49.95,0:22:50.92,EN,,0,0,0,,I just ought to mention,\nDialogue: 0,0:22:51.08,0:22:53.07,EN,,0,0,0,,I've only showed you two procedures.\nDialogue: 0,0:22:53.86,0:22:55.16,EN,,0,0,0,,But let me emphasize\nDialogue: 0,0:22:55.20,0:22:57.77,EN,,0,0,0,,that this way of putting things together\nDialogue: 0,0:22:57.80,0:23:01.00,EN,,0,0,0,,with maps, filters, and accumulators is very, very general.\nDialogue: 0,0:23:01.41,0:23:07.28,EN,,0,0,0,,It's the generate and test paradigm for programs.\nDialogue: 0,0:23:07.77,0:23:09.10,EN,,0,0,0,,And as an example of that,\nDialogue: 0,0:23:09.39,0:23:12.94,EN,,0,0,0,,Richard Waters, who was at MIT when he was a graduate student,\nDialogue: 0,0:23:12.96,0:23:15.26,EN,,0,0,0,,as part of his thesis research went and analyzed\nDialogue: 0,0:23:15.80,0:23:19.21,EN,,0,0,0,,a large chunk of the IBM scientific subroutine library,\nDialogue: 0,0:23:19.82,0:23:23.31,EN,,0,0,0,,and discovered that about 60% of the programs in it\nDialogue: 0,0:23:24.06,0:23:28.25,EN,,0,0,0,,could be expressed exactly in terms using no more than what we've put here--\nDialogue: 0,0:23:28.86,0:23:30.17,EN,,0,0,0,,map, filter, and accumulate.\nDialogue: 0,0:23:30.57,0:23:31.50,EN,,0,0,0,,All right, let's take a break.\nDialogue: 0,0:23:36.59,0:23:37.12,EN,,0,0,0,,Questions?\nDialogue: 0,0:23:41.18,0:23:42.89,EN,,0,0,0,,AUDIENCE: It seems like the essence of this whole thing\nDialogue: 0,0:23:42.89,0:23:45.96,EN,,0,0,0,,is just that you have a very uniform, simple data structure\nDialogue: 0,0:23:46.25,0:23:47.66,EN,,0,0,0,,to work with, the stream.\nDialogue: 0,0:23:48.38,0:23:48.92,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:23:48.92,0:23:50.38,EN,,0,0,0,,The essence is that you, again,\nDialogue: 0,0:23:50.40,0:23:53.07,EN,,0,0,0,,it's this sense of conventional interfaces.\nDialogue: 0,0:23:53.71,0:23:55.61,EN,,0,0,0,,So you can start putting a lot of things together.\nDialogue: 0,0:23:56.01,0:23:58.78,EN,,0,0,0,,And the stream is as you say,\nDialogue: 0,0:23:58.78,0:24:00.89,EN,,0,0,0,,the uniform data structure that supports that.\nDialogue: 0,0:24:00.89,0:24:02.84,EN,,0,0,0,,This is very much like APL, by the way.\nDialogue: 0,0:24:03.60,0:24:05.21,EN,,0,0,0,,APL is very much the same idea,\nDialogue: 0,0:24:05.21,0:24:06.96,EN,,0,0,0,,except in APL, instead of this stream,\nDialogue: 0,0:24:07.13,0:24:08.44,EN,,0,0,0,,you have arrays and vectors.\nDialogue: 0,0:24:09.56,0:24:14.48,EN,,0,0,0,,And a lot of the power of APL is exactly the same reason of the power of this.\nDialogue: 0,0:24:19.91,0:24:20.91,EN,,0,0,0,,OK, thank you.\nDialogue: 0,0:24:20.91,0:24:21.66,EN,,0,0,0,,Let's take a break.\nDialogue: 0,0:24:21.66,0:24:30.35,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:24:57.47,0:24:57.61,EN,,0,0,0,,All right.\nDialogue: 0,0:24:57.61,0:24:58.59,EN,,0,0,0,,We've been looking at\nDialogue: 0,0:25:00.54,0:25:03.20,EN,,0,0,0,,at ways of organizing computations using streams.\nDialogue: 0,0:25:03.85,0:25:05.47,EN,,0,0,0,,But what I want to do now is just show you two\nDialogue: 0,0:25:05.93,0:25:09.12,EN,,0,0,0,,somewhat more complicated examples of that.\nDialogue: 0,0:25:10.84,0:25:14.12,EN,,0,0,0,,Let's start by thinking about the following\nDialogue: 0,0:25:14.20,0:25:16.81,EN,,0,0,0,,kind of utility procedure that will come in useful.\nDialogue: 0,0:25:16.81,0:25:18.09,EN,,0,0,0,,Suppose I've got a stream.\nDialogue: 0,0:25:19.96,0:25:23.15,EN,,0,0,0,,And the elements of this stream are themselves streams.\nDialogue: 0,0:25:23.98,0:25:26.53,EN,,0,0,0,,So the first thing might be 1, 2, 3.\nDialogue: 0,0:25:32.72,0:25:33.88,EN,,0,0,0,,So I've got a stream.\nDialogue: 0,0:25:33.88,0:25:40.10,EN,,0,0,0,,And each element of the stream is itself a stream.\nDialogue: 0,0:25:40.97,0:25:43.42,EN,,0,0,0,,And what I'd like to do is build a stream\nDialogue: 0,0:25:43.64,0:25:46.75,EN,,0,0,0,,that sort of collects together all of the elements,\nDialogue: 0,0:25:46.76,0:25:49.24,EN,,0,0,0,,pulls all of the elements out of these sub-streams\nDialogue: 0,0:25:50.11,0:25:51.82,EN,,0,0,0,,and strings them all together in one thing.\nDialogue: 0,0:25:52.27,0:25:55.61,EN,,0,0,0,,So just to show you the use of this language, how easy it is,\nDialogue: 0,0:25:56.11,0:25:57.10,EN,,0,0,0,,call that flatten.\nDialogue: 0,0:25:57.95,0:26:10.64,EN,,0,0,0,,And I can define to flatten this stream of streams.\nDialogue: 0,0:26:12.89,0:26:13.80,EN,,0,0,0,,Well, what is that?\nDialogue: 0,0:26:13.96,0:26:16.24,EN,,0,0,0,,That's just an accumulation.\nDialogue: 0,0:26:16.32,0:26:25.05,EN,,0,0,0,,I want to accumulate using append,\nDialogue: 0,0:26:25.07,0:26:26.45,EN,,0,0,0,,by successively appending.\nDialogue: 0,0:26:26.73,0:26:29.29,EN,,0,0,0,,So I accumulate using append streams,\nDialogue: 0,0:26:35.90,0:26:48.20,EN,,0,0,0,,starting with the-empty-stream down that stream of streams.\nDialogue: 0,0:26:54.84,0:26:55.84,EN,,0,0,0,,OK, so there's an example of\nDialogue: 0,0:26:56.92,0:26:59.23,EN,,0,0,0,,how you can start using these higher order things\nDialogue: 0,0:26:59.60,0:27:00.83,EN,,0,0,0,,to do some interesting operations.\nDialogue: 0,0:27:00.83,0:27:05.10,EN,,0,0,0,,In fact, there's another useful thing that I want to do.\nDialogue: 0,0:27:05.10,0:27:07.05,EN,,0,0,0,,I want to define a procedure called flat-map,\nDialogue: 0,0:27:17.18,0:27:20.59,EN,,0,0,0,,flat map of some function and a stream.\nDialogue: 0,0:27:21.84,0:27:25.72,EN,,0,0,0,,And what this is going to do is s will be a stream of elements.\nDialogue: 0,0:27:25.72,0:27:27.69,EN,,0,0,0,,f is going to be a function\nDialogue: 0,0:27:27.72,0:27:30.62,EN,,0,0,0,,for each element in the stream produces another stream.\nDialogue: 0,0:27:31.95,0:27:34.52,EN,,0,0,0,,And what I want to do is take all of the elements and all of those streams\nDialogue: 0,0:27:35.00,0:27:36.00,EN,,0,0,0,,and combine them together.\nDialogue: 0,0:27:36.00,0:27:49.13,EN,,0,0,0,,So that's just going to be the flatten of map f down s.\nDialogue: 0,0:27:51.20,0:27:53.04,EN,,0,0,0,,Each time I apply f to an element of s,\nDialogue: 0,0:27:53.05,0:27:53.85,EN,,0,0,0,,I get a stream.\nDialogue: 0,0:27:54.29,0:27:55.24,EN,,0,0,0,,If I map it all the way down,\nDialogue: 0,0:27:55.24,0:27:56.27,EN,,0,0,0,,I get a stream of streams,\nDialogue: 0,0:27:56.46,0:27:57.42,EN,,0,0,0,,and I'll flatten that.\nDialogue: 0,0:27:58.67,0:28:02.64,EN,,0,0,0,,Well, I want to use that to show you a\nDialogue: 0,0:28:03.87,0:28:05.84,EN,,0,0,0,,a new way to do a familiar kind of problem.\nDialogue: 0,0:28:06.51,0:28:12.27,EN,,0,0,0,,The problem's going to be like a lot of problems you've seen,\nDialogue: 0,0:28:12.28,0:28:13.96,EN,,0,0,0,,although maybe not this particular one.\nDialogue: 0,0:28:14.19,0:28:15.49,EN,,0,0,0,,I'm going to give you an integer, n.\nDialogue: 0,0:28:18.68,0:28:19.93,EN,,0,0,0,,And the problem is going to be\nDialogue: 0,0:28:21.20,0:28:31.53,EN,,0,0,0,,find all pairs and integers i and j,\nDialogue: 0,0:28:32.30,0:28:39.96,EN,,0,0,0,,between 0 and i, with j less than i, up to n,\nDialogue: 0,0:28:42.33,0:28:52.03,EN,,0,0,0,,such that i plus j is prime.\nDialogue: 0,0:28:55.74,0:28:57.92,EN,,0,0,0,,So for example, if n equals 6,\nDialogue: 0,0:28:59.74,0:29:00.78,EN,,0,0,0,,let's make a little table here,\nDialogue: 0,0:29:01.55,0:29:06.67,EN,,0,0,0,,i and j and i plus j.\nDialogue: 0,0:29:09.70,0:29:14.91,EN,,0,0,0,,So for, say, i equals 2 and j equals 1, I'd get 3.\nDialogue: 0,0:29:15.52,0:29:20.38,EN,,0,0,0,,And for i equals 3, I could have j equals 2, and that would be 5.\nDialogue: 0,0:29:21.21,0:29:26.51,EN,,0,0,0,,And 4 and 1 would be 5 and so on,\nDialogue: 0,0:29:26.92,0:29:28.11,EN,,0,0,0,,up until i goes to 6.\nDialogue: 0,0:29:28.40,0:29:32.54,EN,,0,0,0,,And what I'd like to return is to produce a stream\nDialogue: 0,0:29:33.20,0:29:37.04,EN,,0,0,0,,all the triples like this, let's say i, j, and i plus j.\nDialogue: 0,0:29:37.66,0:29:39.55,EN,,0,0,0,,So for each n, I want to generate this stream.\nDialogue: 0,0:29:40.97,0:29:43.68,EN,,0,0,0,,OK, well, that's easy.\nDialogue: 0,0:29:43.68,0:29:44.35,EN,,0,0,0,,Let's build it up.\nDialogue: 0,0:29:47.23,0:29:48.22,EN,,0,0,0,,We start like this.\nDialogue: 0,0:29:50.15,0:29:54.25,EN,,0,0,0,,We're going to say for each i, for each i\nDialogue: 0,0:29:55.24,0:29:56.44,EN,,0,0,0,,we're going to generate a stream.\nDialogue: 0,0:29:57.00,0:29:58.59,EN,,0,0,0,,For each i in the interval 1 through n,\nDialogue: 0,0:29:58.59,0:29:59.76,EN,,0,0,0,,we're going to generate a stream.\nDialogue: 0,0:30:00.66,0:30:01.80,EN,,0,0,0,,What's that stream going to be?\nDialogue: 0,0:30:02.23,0:30:04.04,EN,,0,0,0,,We're going to start by generating all the pairs.\nDialogue: 0,0:30:04.18,0:30:07.55,EN,,0,0,0,,So for each i, we're going to generate,\nDialogue: 0,0:30:08.43,0:30:14.52,EN,,0,0,0,,for each j in the interval 1 to i minus 1,\nDialogue: 0,0:30:16.91,0:30:17.98,EN,,0,0,0,,we'll generate the pair,\nDialogue: 0,0:30:18.35,0:30:20.71,EN,,0,0,0,,or the list with two elements i and j.\nDialogue: 0,0:30:23.78,0:30:27.10,EN,,0,0,0,,So we map along the interval,\nDialogue: 0,0:30:28.60,0:30:29.74,EN,,0,0,0,,generating the pairs.\nDialogue: 0,0:30:31.07,0:30:33.17,EN,,0,0,0,,And for each i, that generates a stream of pairs.\nDialogue: 0,0:30:33.40,0:30:34.49,EN,,0,0,0,,And we flatmap it.\nDialogue: 0,0:30:34.59,0:30:36.20,EN,,0,0,0,,Now we have all the pairs i and j,\nDialogue: 0,0:30:36.81,0:30:38.08,EN,,0,0,0,,such that i is less than j.\nDialogue: 0,0:30:38.73,0:30:39.85,EN,,0,0,0,,So that builds that.\nDialogue: 0,0:30:39.85,0:30:40.76,EN,,0,0,0,,Now we're got to test them.\nDialogue: 0,0:30:42.99,0:30:45.84,EN,,0,0,0,,Well, we take that thing we just built, the flatmap,\nDialogue: 0,0:30:46.94,0:30:51.37,EN,,0,0,0,,and we filter it to see whether the i-- see, we had an i and a j.\nDialogue: 0,0:30:51.66,0:30:54.17,EN,,0,0,0,,i was the first thing in the list,\nDialogue: 0,0:30:54.30,0:30:55.60,EN,,0,0,0,,j was the second thing in the list.\nDialogue: 0,0:30:57.21,0:31:00.01,EN,,0,0,0,,So we have a predicate which says in that list of two elements\nDialogue: 0,0:31:00.22,0:31:02.00,EN,,0,0,0,,is the sum of the CAR and the CDR prime.\nDialogue: 0,0:31:02.07,0:31:05.52,EN,,0,0,0,,And we filter that collection of pairs we just built.\nDialogue: 0,0:31:06.54,0:31:07.85,EN,,0,0,0,,So those are the pairs we want.\nDialogue: 0,0:31:09.42,0:31:10.24,EN,,0,0,0,,Now we go ahead\nDialogue: 0,0:31:10.88,0:31:13.10,EN,,0,0,0,,Now we go ahead and we take the result of that filter\nDialogue: 0,0:31:13.26,0:31:19.05,EN,,0,0,0,,we map along it, generating the list i and j and i plus j.\nDialogue: 0,0:31:19.61,0:31:21.39,EN,,0,0,0,,And that's our procedure prime-sum-pairs.\nDialogue: 0,0:31:22.57,0:31:24.76,EN,,0,0,0,,Ok, and then just to flash it up, here's the whole procedure.\nDialogue: 0,0:31:28.08,0:31:30.97,EN,,0,0,0,,A map, a filter, a flatmap.\nDialogue: 0,0:31:34.85,0:31:35.66,EN,,0,0,0,,There's the whole thing,\nDialogue: 0,0:31:35.66,0:31:37.12,EN,,0,0,0,,even though this isn't particularly readable.\nDialogue: 0,0:31:37.42,0:31:38.94,EN,,0,0,0,,It's just expanding that flatmap.\nDialogue: 0,0:31:39.84,0:31:40.88,EN,,0,0,0,,So there's an example\nDialogue: 0,0:31:43.28,0:31:45.00,EN,,0,0,0,,which illustrates the general point\nDialogue: 0,0:31:45.12,0:31:46.30,EN,,0,0,0,,that nested loops\nDialogue: 0,0:31:47.66,0:31:50.09,EN,,0,0,0,,in this procedure start looking like compositions of\nDialogue: 0,0:31:50.11,0:31:52.81,EN,,0,0,0,,flatmaps of flatmaps of flatmaps of maps and things.\nDialogue: 0,0:31:54.27,0:31:57.61,EN,,0,0,0,,So not only can we enumerate individual things,\nDialogue: 0,0:31:57.61,0:31:58.81,EN,,0,0,0,,but by using flatmaps,\nDialogue: 0,0:31:59.12,0:32:02.24,EN,,0,0,0,,we can do what would correspond to nested loops in most other languages.\nDialogue: 0,0:32:03.23,0:32:03.76,EN,,0,0,0,,Of course,\nDialogue: 0,0:32:04.91,0:32:08.03,EN,,0,0,0,,it's pretty awful to keep writing these flatmaps of flatmaps of flatmaps.\nDialogue: 0,0:32:08.41,0:32:13.00,EN,,0,0,0,,Prime-sum-pairs you saw looked fairly complicated,\nDialogue: 0,0:32:13.56,0:32:15.28,EN,,0,0,0,,even though the individual pieces were easy.\nDialogue: 0,0:32:15.48,0:32:17.13,EN,,0,0,0,,So what you can do, if you like,\nDialogue: 0,0:32:17.15,0:32:20.12,EN,,0,0,0,,is introduced some syntactic sugar that's called collect.\nDialogue: 0,0:32:21.04,0:32:22.68,EN,,0,0,0,,And collect is just an abbreviation\nDialogue: 0,0:32:22.91,0:32:26.16,EN,,0,0,0,,for that nest of flatmaps and filters arranged in that particular way.\nDialogue: 0,0:32:26.16,0:32:28.60,EN,,0,0,0,,Here's prime-sum-pairs again, written using collect.\nDialogue: 0,0:32:29.45,0:32:36.27,EN,,0,0,0,,It says to find all those pairs, I'm going to collect together a result,\nDialogue: 0,0:32:36.52,0:32:39.20,EN,,0,0,0,,which is the list i, j, and i plus j,\nDialogue: 0,0:32:40.84,0:32:45.39,EN,,0,0,0,,that's going to be generated as i runs through the interval from 1 to n\nDialogue: 0,0:32:47.44,0:32:52.32,EN,,0,0,0,,and as j runs through the interval from 1 to i minus 1\nDialogue: 0,0:32:54.16,0:32:56.54,EN,,0,0,0,,such that i plus j is prime.\nDialogue: 0,0:32:58.04,0:33:00.32,EN,,0,0,0,,So I'm not going to say what collect does in general.\nDialogue: 0,0:33:00.69,0:33:02.75,EN,,0,0,0,,You can look at that by looking at it in the book.\nDialogue: 0,0:33:03.42,0:33:05.45,EN,,0,0,0,,But pretty much, you can see that the pieces of this\nDialogue: 0,0:33:05.84,0:33:08.60,EN,,0,0,0,,are the pieces of that original procedure I wrote.\nDialogue: 0,0:33:08.82,0:33:11.40,EN,,0,0,0,,And this collect is just some syntactic sugar\nDialogue: 0,0:33:11.44,0:33:14.80,EN,,0,0,0,,for automatically generating that nest of flatmaps and flatmaps.\nDialogue: 0,0:33:16.31,0:33:20.33,EN,,0,0,0,,OK, well, let me do one more example\nDialogue: 0,0:33:20.67,0:33:22.00,EN,,0,0,0,,that shows you the same kind of thing.\nDialogue: 0,0:33:22.12,0:33:23.53,EN,,0,0,0,,Here's a very famous problem\nDialogue: 0,0:33:24.70,0:33:28.75,EN,,0,0,0,,that's used to illustrate a lot of so-called backtracking computer algorithms\nDialogue: 0,0:33:28.76,0:33:30.20,EN,,0,0,0,,This is the eight queens problem.\nDialogue: 0,0:33:30.20,0:33:31.08,EN,,0,0,0,,This is a chess board.\nDialogue: 0,0:33:32.37,0:33:33.64,EN,,0,0,0,,And the eight queens problem says,\nDialogue: 0,0:33:33.64,0:33:35.85,EN,,0,0,0,,find a way to put down eight queens on a chess board\nDialogue: 0,0:33:36.44,0:33:38.00,EN,,0,0,0,,so that no two are attacking each other.\nDialogue: 0,0:33:38.00,0:33:40.60,EN,,0,0,0,,And here's a particular solution to the eight queens problem.\nDialogue: 0,0:33:41.21,0:33:43.68,EN,,0,0,0,,So I have to make sure to put down queens\nDialogue: 0,0:33:43.71,0:33:46.80,EN,,0,0,0,,no two are in the same row or the same column\nDialogue: 0,0:33:47.72,0:33:49.47,EN,,0,0,0,,or sit along the same diagonal.\nDialogue: 0,0:33:51.41,0:33:56.40,EN,,0,0,0,,Now, there's sort of a standard way of doing that.\nDialogue: 0,0:33:59.74,0:34:01.48,EN,,0,0,0,,Well, first we need to do is\nDialogue: 0,0:34:02.54,0:34:04.62,EN,,0,0,0,,below the surface, at George's level.\nDialogue: 0,0:34:04.94,0:34:08.09,EN,,0,0,0,,We have to find some way to represent a board, and represent positions.\nDialogue: 0,0:34:08.09,0:34:09.52,EN,,0,0,0,,And we'll not worry about that.\nDialogue: 0,0:34:09.80,0:34:12.78,EN,,0,0,0,,But let's assume that there's a predicate called safe.\nDialogue: 0,0:34:16.14,0:34:17.55,EN,,0,0,0,,And what safe is going to do\nDialogue: 0,0:34:17.96,0:34:20.84,EN,,0,0,0,,is going to say given that I have a bunch of queens down on the chess board,\nDialogue: 0,0:34:21.36,0:34:24.54,EN,,0,0,0,,is it OK to put a queen in this particular spot?\nDialogue: 0,0:34:25.40,0:34:31.26,EN,,0,0,0,,So safe is going to take a row and a column.\nDialogue: 0,0:34:32.76,0:34:35.47,EN,,0,0,0,,That's going to be a place where I'm going to try and put down the next queen,\nDialogue: 0,0:34:36.06,0:34:42.76,EN,,0,0,0,,and the rest of positions.\nDialogue: 0,0:34:45.58,0:34:46.75,EN,,0,0,0,,And what safe will say\nDialogue: 0,0:34:46.86,0:34:51.68,EN,,0,0,0,,is given that I already have queens down in these positions,\nDialogue: 0,0:34:53.02,0:34:54.76,EN,,0,0,0,,is it safe to put another queen down\nDialogue: 0,0:34:55.10,0:34:57.20,EN,,0,0,0,,in that row and that column?\nDialogue: 0,0:34:58.30,0:34:59.36,EN,,0,0,0,,And let's not worry about that.\nDialogue: 0,0:34:59.36,0:35:01.38,EN,,0,0,0,,That's George's problem. and it's not hard to write.\nDialogue: 0,0:35:01.38,0:35:06.27,EN,,0,0,0,,You just have to check whether this thing contains any things\nDialogue: 0,0:35:06.30,0:35:08.52,EN,,0,0,0,,on that row or that column or in that diagonal.\nDialogue: 0,0:35:10.53,0:35:13.12,EN,,0,0,0,,Now, how would you organize the program given that?\nDialogue: 0,0:35:13.84,0:35:17.21,EN,,0,0,0,,And there's sort of a traditional way to organize it\nDialogue: 0,0:35:17.93,0:35:18.97,EN,,0,0,0,,called backtracking.\nDialogue: 0,0:35:20.52,0:35:23.21,EN,,0,0,0,,And it says, well, let's start off\nDialogue: 0,0:35:25.13,0:35:28.88,EN,,0,0,0,,let's think about all the ways of putting the first queen down\nDialogue: 0,0:35:30.04,0:35:31.34,EN,,0,0,0,,in the first column.\nDialogue: 0,0:35:31.45,0:35:32.24,EN,,0,0,0,,There are eight ways.\nDialogue: 0,0:35:32.58,0:35:35.00,EN,,0,0,0,,Well, let's say try the first column.\nDialogue: 0,0:35:35.88,0:35:37.30,EN,,0,0,0,,Try column 1, row 1.\nDialogue: 0,0:35:37.30,0:35:38.70,EN,,0,0,0,,These branches are going to represent\nDialogue: 0,0:35:40.17,0:35:41.88,EN,,0,0,0,,the possibilities at each level.\nDialogue: 0,0:35:43.36,0:35:45.53,EN,,0,0,0,,So I'll try and put a queen down in the first column.\nDialogue: 0,0:35:46.14,0:35:47.74,EN,,0,0,0,,And now given that it's in the first column,\nDialogue: 0,0:35:47.77,0:35:49.98,EN,,0,0,0,,I'll try and put the next queen down in the first column.\nDialogue: 0,0:35:50.60,0:35:52.17,EN,,0,0,0,,That's no good, they're both...\nDialogue: 0,0:35:53.31,0:35:54.60,EN,,0,0,0,,I'll try and put the first queen,\nDialogue: 0,0:35:54.86,0:35:56.80,EN,,0,0,0,,the one in the first column, down in the first row.\nDialogue: 0,0:35:56.92,0:35:57.47,EN,,0,0,0,,I'm sorry.\nDialogue: 0,0:35:59.05,0:36:01.39,EN,,0,0,0,,And then given that, we'll put the next queen down in the first row.\nDialogue: 0,0:36:01.39,0:36:02.09,EN,,0,0,0,,And that's no good.\nDialogue: 0,0:36:02.09,0:36:03.18,EN,,0,0,0,,So I'll back up to here.\nDialogue: 0,0:36:04.20,0:36:04.72,EN,,0,0,0,,And I'll say,\nDialogue: 0,0:36:04.83,0:36:06.86,EN,,0,0,0,,oh, can I put the first queen down in the second row?\nDialogue: 0,0:36:07.32,0:36:08.38,EN,,0,0,0,,Well, that's no good.\nDialogue: 0,0:36:08.55,0:36:09.76,EN,,0,0,0,,Oh, can I put it down in the third row?\nDialogue: 0,0:36:09.76,0:36:10.52,EN,,0,0,0,,Well, that's good.\nDialogue: 0,0:36:12.79,0:36:15.13,EN,,0,0,0,,Well, now can I put the next queen down in the first column?\nDialogue: 0,0:36:15.38,0:36:17.82,EN,,0,0,0,,Well, I can't visualize this chess board anymore,\nDialogue: 0,0:36:17.82,0:36:18.86,EN,,0,0,0,,but I think that's right.\nDialogue: 0,0:36:19.19,0:36:20.45,EN,,0,0,0,,And I try the next one.\nDialogue: 0,0:36:20.45,0:36:24.17,EN,,0,0,0,,And at each place, I go as far down this tree as I can.\nDialogue: 0,0:36:24.54,0:36:25.64,EN,,0,0,0,,And I back up.\nDialogue: 0,0:36:25.64,0:36:28.97,EN,,0,0,0,,If I get down to here and find no possibilities below there,\nDialogue: 0,0:36:29.00,0:36:30.12,EN,,0,0,0,,I back all the way up to here,\nDialogue: 0,0:36:30.28,0:36:32.44,EN,,0,0,0,,and now start again generating this sub-tree.\nDialogue: 0,0:36:33.26,0:36:34.32,EN,,0,0,0,,And I sort of walk around.\nDialogue: 0,0:36:35.05,0:36:37.26,EN,,0,0,0,,And finally, if I ever manage to get all the way down,\nDialogue: 0,0:36:37.72,0:36:38.59,EN,,0,0,0,,I've found a solution.\nDialogue: 0,0:36:39.82,0:36:41.98,EN,,0,0,0,,So that's a typical sort of\nDialogue: 0,0:36:43.12,0:36:45.93,EN,,0,0,0,,paradigm that's used a lot in AI programming.\nDialogue: 0,0:36:45.93,0:36:47.30,EN,,0,0,0,,It's called backtracking search.\nDialogue: 0,0:36:57.47,0:37:03.04,EN,,0,0,0,,And it's really unnecessary.\nDialogue: 0,0:37:03.86,0:37:06.55,EN,,0,0,0,,You saw me get confused when I was visualizing this thing.\nDialogue: 0,0:37:06.81,0:37:08.25,EN,,0,0,0,,And you sort of see the complication.\nDialogue: 0,0:37:08.55,0:37:10.76,EN,,0,0,0,,This is a complicated thing to say.\nDialogue: 0,0:37:10.76,0:37:11.82,EN,,0,0,0,,Why is it complicated?\nDialogue: 0,0:37:12.39,0:37:13.29,EN,,0,0,0,,Its because somehow\nDialogue: 0,0:37:13.53,0:37:17.39,EN,,0,0,0,,this program is too inordinately concerned with time.\nDialogue: 0,0:37:18.58,0:37:20.43,EN,,0,0,0,,It's too much-- I try this one, and I try this one,\nDialogue: 0,0:37:20.49,0:37:22.38,EN,,0,0,0,,and I go back to the last possibility.\nDialogue: 0,0:37:22.89,0:37:24.34,EN,,0,0,0,,And that's a complicated thing.\nDialogue: 0,0:37:24.34,0:37:26.36,EN,,0,0,0,,If I stop worrying about time so much,\nDialogue: 0,0:37:28.04,0:37:29.76,EN,,0,0,0,,then there's a much simpler way to describe this.\nDialogue: 0,0:37:31.20,0:37:32.36,EN,,0,0,0,,It says, let's imagine\nDialogue: 0,0:37:33.31,0:37:36.57,EN,,0,0,0,,that I have in my hands\nDialogue: 0,0:37:38.32,0:37:42.16,EN,,0,0,0,,the tree down to k minus 1 levels.\nDialogue: 0,0:37:43.40,0:37:46.32,EN,,0,0,0,,See, suppose I had in my hands all possible ways\nDialogue: 0,0:37:48.09,0:37:52.19,EN,,0,0,0,,to solve... to put down queens in the first k columns.\nDialogue: 0,0:37:53.56,0:37:54.61,EN,,0,0,0,,Suppose I just had that.\nDialogue: 0,0:37:54.61,0:37:55.79,EN,,0,0,0,,Let's not worry about how we get it.\nDialogue: 0,0:37:57.07,0:37:59.20,EN,,0,0,0,,Well, then, how do I extend that?\nDialogue: 0,0:37:59.20,0:38:02.16,EN,,0,0,0,,How do I find all possible ways to put down queens in the next column?\nDialogue: 0,0:38:02.48,0:38:03.13,EN,,0,0,0,,It's really easy.\nDialogue: 0,0:38:03.62,0:38:06.41,EN,,0,0,0,,For each of these positions I have,\nDialogue: 0,0:38:07.82,0:38:13.96,EN,,0,0,0,,I enjoin, I think about putting down a queen in each row\nDialogue: 0,0:38:15.08,0:38:16.16,EN,,0,0,0,,to make the next thing.\nDialogue: 0,0:38:16.16,0:38:17.29,EN,,0,0,0,,And then for each one I put down,\nDialogue: 0,0:38:17.44,0:38:19.71,EN,,0,0,0,,I filter those by the ones that are safe.\nDialogue: 0,0:38:21.80,0:38:22.99,EN,,0,0,0,,So instead of thinking about\nDialogue: 0,0:38:22.99,0:38:24.67,EN,,0,0,0,,this tree as generated step by step,\nDialogue: 0,0:38:24.94,0:38:26.86,EN,,0,0,0,,I say, suppose I had it all there.\nDialogue: 0,0:38:29.68,0:38:32.41,EN,,0,0,0,,And to extend it from level k minus 1 to level k,\nDialogue: 0,0:38:32.64,0:38:36.24,EN,,0,0,0,,I just need to extend each thing in all possible ways\nDialogue: 0,0:38:36.48,0:38:37.80,EN,,0,0,0,,and only keep the ones that are safe.\nDialogue: 0,0:38:37.80,0:38:39.23,EN,,0,0,0,,And that will give me the tree to level k.\nDialogue: 0,0:38:39.30,0:38:40.67,EN,,0,0,0,,And that's a recursive strategy\nDialogue: 0,0:38:40.89,0:38:42.17,EN,,0,0,0,,for solving the eight queens problem.\nDialogue: 0,0:38:44.53,0:38:45.34,EN,,0,0,0,,All right, well, let's look at it.\nDialogue: 0,0:38:50.33,0:38:52.68,EN,,0,0,0,,To solve the eight queens problem\nDialogue: 0,0:38:53.00,0:38:55.53,EN,,0,0,0,,on a board of some specified size,\nDialogue: 0,0:38:58.92,0:39:01.03,EN,,0,0,0,,we write a sub-procedure called fill-columns.\nDialogue: 0,0:39:01.13,0:39:04.86,EN,,0,0,0,,Fill-columns is going to put down queens up through column k.\nDialogue: 0,0:39:06.35,0:39:07.70,EN,,0,0,0,,And here's the pattern of the recursion.\nDialogue: 0,0:39:07.70,0:39:10.92,EN,,0,0,0,,I'm going to call fill-columns with the size eventually.\nDialogue: 0,0:39:12.99,0:39:15.28,EN,,0,0,0,,So fill-columns says how to put down queens safely\nDialogue: 0,0:39:15.29,0:39:17.16,EN,,0,0,0,,safely in the first k columns of this chess board\nDialogue: 0,0:39:17.20,0:39:19.58,EN,,0,0,0,,with a size number of rows in it.\nDialogue: 0,0:39:20.36,0:39:21.64,EN,,0,0,0,,If k is equal to 0,\nDialogue: 0,0:39:22.27,0:39:23.60,EN,,0,0,0,,well, then I don't have to put anything down.\nDialogue: 0,0:39:23.94,0:39:25.93,EN,,0,0,0,,So my solution is just an empty chess board.\nDialogue: 0,0:39:26.71,0:39:28.07,EN,,0,0,0,,Otherwise, I'm going to do some stuff.\nDialogue: 0,0:39:28.35,0:39:29.44,EN,,0,0,0,,And I'm going to use collect.\nDialogue: 0,0:39:30.81,0:39:31.77,EN,,0,0,0,,And here's the collect.\nDialogue: 0,0:39:34.33,0:39:41.91,EN,,0,0,0,,I find all ways to put down queens in the first k minus 1 columns.\nDialogue: 0,0:39:42.19,0:39:43.32,EN,,0,0,0,,And this was just what I set for.\nDialogue: 0,0:39:43.32,0:39:46.36,EN,,0,0,0,,Imagine I have this tree down to k minus 1 levels.\nDialogue: 0,0:39:48.88,0:39:52.11,EN,,0,0,0,,And then I find all ways of trying a row,\nDialogue: 0,0:39:52.52,0:39:54.13,EN,,0,0,0,,that's just each of the possible rows.\nDialogue: 0,0:39:54.13,0:39:55.04,EN,,0,0,0,,They're size rows,\nDialogue: 0,0:39:55.31,0:39:56.49,EN,,0,0,0,,so that's enumerate interval.\nDialogue: 0,0:39:58.04,0:39:59.79,EN,,0,0,0,,And now what I do is I collect together\nDialogue: 0,0:40:03.15,0:40:05.82,EN,,0,0,0,,the new row I'm going to try and column k\nDialogue: 0,0:40:07.95,0:40:08.95,EN,,0,0,0,,with the rest of the queens.\nDialogue: 0,0:40:08.95,0:40:10.09,EN,,0,0,0,,I adjoin a position.\nDialogue: 0,0:40:10.20,0:40:11.29,EN,,0,0,0,,This is George's problem.\nDialogue: 0,0:40:11.29,0:40:12.75,EN,,0,0,0,,An adjoined position is like safe.\nDialogue: 0,0:40:13.64,0:40:15.28,EN,,0,0,0,,It's a thing that takes a row\nDialogue: 0,0:40:15.50,0:40:17.04,EN,,0,0,0,,and a column and the rest of the positions\nDialogue: 0,0:40:17.07,0:40:19.02,EN,,0,0,0,,and makes a new position collection.\nDialogue: 0,0:40:19.66,0:40:25.77,EN,,0,0,0,,So I adjoin a position of a new row and a new column\nDialogue: 0,0:40:26.06,0:40:27.68,EN,,0,0,0,,to the rest of the queens,\nDialogue: 0,0:40:28.57,0:40:29.76,EN,,0,0,0,,where the rest of the queens\nDialogue: 0,0:40:29.92,0:40:31.45,EN,,0,0,0,,runs through all possible ways\nDialogue: 0,0:40:31.87,0:40:34.16,EN,,0,0,0,,of solving the problem in k minus 1 columns.\nDialogue: 0,0:40:34.62,0:40:37.04,EN,,0,0,0,,And the new row runs through all possible rows\nDialogue: 0,0:40:37.85,0:40:40.76,EN,,0,0,0,,such that it was safe to put one there.\nDialogue: 0,0:40:43.24,0:40:44.70,EN,,0,0,0,,And that's the whole program.\nDialogue: 0,0:40:46.33,0:40:47.31,EN,,0,0,0,,There's the whole procedure.\nDialogue: 0,0:40:49.84,0:40:52.43,EN,,0,0,0,,Not only that, that doesn't just solve the eight queens problem,\nDialogue: 0,0:40:53.42,0:40:56.68,EN,,0,0,0,,Right? It gives you all solutions to the eight queens problem.\nDialogue: 0,0:40:56.68,0:40:58.48,EN,,0,0,0,,When you're done, you have a stream.\nDialogue: 0,0:40:58.48,0:41:01.90,EN,,0,0,0,,And the elements of that stream are all possible ways of solving that problem.\nDialogue: 0,0:41:05.31,0:41:06.26,EN,,0,0,0,,Why is that simpler?\nDialogue: 0,0:41:06.26,0:41:08.54,EN,,0,0,0,,Well, we threw away the whole idea that\nDialogue: 0,0:41:08.88,0:41:11.52,EN,,0,0,0,,is some process that happens in time with state.\nDialogue: 0,0:41:12.72,0:41:14.42,EN,,0,0,0,,And we just said it's a whole collection of stuff.\nDialogue: 0,0:41:14.94,0:41:16.00,EN,,0,0,0,,And that's why it's simpler.\nDialogue: 0,0:41:18.00,0:41:20.11,EN,,0,0,0,,Right? We've changed our view.\nDialogue: 0,0:41:20.11,0:41:22.59,EN,,0,0,0,,Remember, that's where we started today.\nDialogue: 0,0:41:22.82,0:41:26.23,EN,,0,0,0,,We've changed our view of what it is we're trying to model.\nDialogue: 0,0:41:26.23,0:41:29.20,EN,,0,0,0,,we stop modeling things that evolve in time\nDialogue: 0,0:41:29.37,0:41:31.31,EN,,0,0,0,,have steps and have state.\nDialogue: 0,0:41:31.75,0:41:33.79,EN,,0,0,0,,And instead, we're trying to model this global thing\nDialogue: 0,0:41:33.80,0:41:35.93,EN,,0,0,0,,like the whole flight of the chalk,\nDialogue: 0,0:41:36.28,0:41:38.88,EN,,0,0,0,,rather than its state at each instant.\nDialogue: 0,0:41:40.75,0:41:41.44,EN,,0,0,0,,Any questions?\nDialogue: 0,0:41:44.08,0:41:46.20,EN,,0,0,0,,AUDIENCE: It looks to me like backtracking would be\nDialogue: 0,0:41:46.22,0:41:48.96,EN,,0,0,0,,searching for the first solution it can find,\nDialogue: 0,0:41:49.31,0:41:51.48,EN,,0,0,0,,whereas this recursive search\nDialogue: 0,0:41:51.48,0:41:53.26,EN,,0,0,0,,would be looking for all solutions.\nDialogue: 0,0:41:53.32,0:41:53.60,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:41:54.03,0:41:55.26,EN,,0,0,0,,AUDIENCE: And it seems that\nDialogue: 0,0:41:55.26,0:41:57.92,EN,,0,0,0,,if you have a large enough area to search,\nDialogue: 0,0:41:57.92,0:42:00.92,EN,,0,0,0,,that the second is going to become impossible.\nDialogue: 0,0:42:01.36,0:42:05.93,EN,,0,0,0,,PROFESSOR: OK, the answer to that question\nDialogue: 0,0:42:07.13,0:42:08.44,EN,,0,0,0,,is the whole rest of this lecture.\nDialogue: 0,0:42:08.57,0:42:10.54,EN,,0,0,0,,It's exactly the right question.\nDialogue: 0,0:42:13.87,0:42:15.74,EN,,0,0,0,,And without trying to anticipate the lecture too much,\nDialogue: 0,0:42:15.96,0:42:19.23,EN,,0,0,0,,you should start being suspicious at this point,\nDialogue: 0,0:42:19.84,0:42:21.84,EN,,0,0,0,,and exactly those kinds of suspicions. Isn't it?\nDialogue: 0,0:42:22.22,0:42:24.51,EN,,0,0,0,,It's wonderful, but isn't it so terribly inefficient?\nDialogue: 0,0:42:24.83,0:42:26.03,EN,,0,0,0,,That's where we're going.\nDialogue: 0,0:42:28.10,0:42:30.02,EN,,0,0,0,,So I won't answer now, but I'll answer later.\nDialogue: 0,0:42:33.35,0:42:34.60,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:42:34.60,0:42:44.51,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:43:29.65,0:43:33.76,EN,,0,0,0,,Well, by now you should be starting to get suspicious.\nDialogue: 0,0:43:35.60,0:43:39.26,EN,,0,0,0,,See, I've showed your this simple, elegant\nDialogue: 0,0:43:40.51,0:43:42.28,EN,,0,0,0,,of putting programs together,\nDialogue: 0,0:43:42.86,0:43:46.91,EN,,0,0,0,,very unlike these other traditional programs\nDialogue: 0,0:43:46.92,0:43:48.19,EN,,0,0,0,,that sum the odd squares\nDialogue: 0,0:43:48.72,0:43:51.32,EN,,0,0,0,,or compute the odd Fibonacci numbers.\nDialogue: 0,0:43:53.74,0:43:55.48,EN,,0,0,0,,Very unlike these programs that mix up\nDialogue: 0,0:43:55.85,0:43:58.84,EN,,0,0,0,,the enumerator and the filter and the accumulator.\nDialogue: 0,0:44:00.44,0:44:01.82,EN,,0,0,0,,And by mixing it up,\nDialogue: 0,0:44:02.20,0:44:04.59,EN,,0,0,0,,we don't have all of these wonderful\nDialogue: 0,0:44:04.62,0:44:07.34,EN,,0,0,0,,conceptual advantages of these streams pieces,\nDialogue: 0,0:44:07.82,0:44:09.53,EN,,0,0,0,,these wonderful mix and match components\nDialogue: 0,0:44:09.55,0:44:11.77,EN,,0,0,0,,for putting together lots and lots of programs.\nDialogue: 0,0:44:13.80,0:44:14.25,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:44:14.28,0:44:16.88,EN,,0,0,0,,most of the programs you've seen look like these ugly ones.\nDialogue: 0,0:44:18.34,0:44:18.94,EN,,0,0,0,,Why's that?\nDialogue: 0,0:44:19.20,0:44:20.59,EN,,0,0,0,,Can it possibly be\nDialogue: 0,0:44:21.16,0:44:24.30,EN,,0,0,0,,that computer scientists are so obtuse\nDialogue: 0,0:44:25.42,0:44:26.44,EN,,0,0,0,,that they don't notice\nDialogue: 0,0:44:27.07,0:44:28.75,EN,,0,0,0,,that if you'd merely did this thing,\nDialogue: 0,0:44:29.63,0:44:31.93,EN,,0,0,0,,then you can get this great programming elegance?\nDialogue: 0,0:44:33.62,0:44:34.78,EN,,0,0,0,,There's got to be a catch.\nDialogue: 0,0:44:36.76,0:44:39.05,EN,,0,0,0,,And it's actually pretty easy to see what the catch is.\nDialogue: 0,0:44:39.51,0:44:41.74,EN,,0,0,0,,Let's think about the following problem.\nDialogue: 0,0:44:42.03,0:44:45.47,EN,,0,0,0,,Suppose I tell you to find the second prime\nDialogue: 0,0:44:46.16,0:44:48.16,EN,,0,0,0,,between 10,000 and 1 million,\nDialogue: 0,0:44:49.12,0:44:50.56,EN,,0,0,0,,or if your computer's larger,\nDialogue: 0,0:44:50.59,0:44:53.05,EN,,0,0,0,,say between 10,000 and 100 billion, or something.\nDialogue: 0,0:44:54.32,0:44:55.45,EN,,0,0,0,,And you say, oh, that's easy.\nDialogue: 0,0:44:55.47,0:44:56.65,EN,,0,0,0,,I can do that with a stream.\nDialogue: 0,0:44:57.08,0:44:59.87,EN,,0,0,0,,All I do is I enumerate\nDialogue: 0,0:45:00.57,0:45:02.89,EN,,0,0,0,,the interval from 10,000 to 1 million.\nDialogue: 0,0:45:04.16,0:45:06.51,EN,,0,0,0,,So I get all those integers from 10,000 to 1 million.\nDialogue: 0,0:45:06.80,0:45:08.64,EN,,0,0,0,,I filter them for prime-ness,\nDialogue: 0,0:45:09.39,0:45:11.10,EN,,0,0,0,,so test all of them and see if they're prime.\nDialogue: 0,0:45:11.76,0:45:12.83,EN,,0,0,0,,And I take the second element.\nDialogue: 0,0:45:12.84,0:45:14.04,EN,,0,0,0,,Right? That's the head of the tail.\nDialogue: 0,0:45:15.79,0:45:17.38,EN,,0,0,0,,OK? Well, that's clearly pretty ridiculous.\nDialogue: 0,0:45:21.66,0:45:23.20,EN,,0,0,0,,We'd not even have room in the machine\nDialogue: 0,0:45:23.58,0:45:25.24,EN,,0,0,0,,Right? To store the integers in the first place,\nDialogue: 0,0:45:25.28,0:45:26.35,EN,,0,0,0,,much less to test them.\nDialogue: 0,0:45:27.04,0:45:28.64,EN,,0,0,0,,And then I only want the second one.\nDialogue: 0,0:45:29.81,0:45:34.94,EN,,0,0,0,,See, the power of this traditional programming style\nDialogue: 0,0:45:36.43,0:45:37.68,EN,,0,0,0,,is exactly its weakness,\nDialogue: 0,0:45:37.96,0:45:38.94,EN,,0,0,0,,that we're mixing up\nDialogue: 0,0:45:39.61,0:45:43.50,EN,,0,0,0,,the enumerating and the testing and the accumulating.\nDialogue: 0,0:45:44.88,0:45:46.46,EN,,0,0,0,,Right? We sort of don't do it all.\nDialogue: 0,0:45:46.67,0:45:49.18,EN,,0,0,0,,So by the actual... so the very thing\nDialogue: 0,0:45:49.45,0:45:51.74,EN,,0,0,0,,makes it conceptually ugly\nDialogue: 0,0:45:52.20,0:45:53.80,EN,,0,0,0,,is the very thing that makes it efficient.\nDialogue: 0,0:45:54.91,0:45:55.84,EN,,0,0,0,,Right? It's this mixing up.\nDialogue: 0,0:45:57.80,0:45:59.34,EN,,0,0,0,,So it seems that all I've done this morning so far\nDialogue: 0,0:45:59.34,0:46:00.42,EN,,0,0,0,,is just confuse you.\nDialogue: 0,0:46:00.42,0:46:03.10,EN,,0,0,0,,I showed you this wonderful way that programming might work,\nDialogue: 0,0:46:03.10,0:46:03.96,EN,,0,0,0,,except that it doesn't.\nDialogue: 0,0:46:05.84,0:46:08.32,EN,,0,0,0,,Well, here's where the wonderful thing happens.\nDialogue: 0,0:46:09.04,0:46:10.57,EN,,0,0,0,,It turns out in this game\nDialogue: 0,0:46:11.21,0:46:13.84,EN,,0,0,0,,that we really can have our cake and eat it too.\nDialogue: 0,0:46:14.87,0:46:16.11,EN,,0,0,0,,And what I mean by that\nDialogue: 0,0:46:18.09,0:46:21.15,EN,,0,0,0,,is that we really can write stream programs\nDialogue: 0,0:46:21.16,0:46:22.48,EN,,0,0,0,,exactly like the ones I wrote\nDialogue: 0,0:46:23.55,0:46:27.74,EN,,0,0,0,,and arrange things so that when the machine actually runs,\nDialogue: 0,0:46:28.33,0:46:31.52,EN,,0,0,0,,it's as efficient as running this traditional programming style\nDialogue: 0,0:46:31.71,0:46:34.28,EN,,0,0,0,,that mixes up the generation and the test.\nDialogue: 0,0:46:36.16,0:46:38.80,EN,,0,0,0,,Well, that sounds pretty magic.\nDialogue: 0,0:46:40.77,0:46:41.82,EN,,0,0,0,,The key to this\nDialogue: 0,0:46:42.00,0:46:43.69,EN,,0,0,0,,is that streams are not lists.\nDialogue: 0,0:46:48.09,0:46:49.79,EN,,0,0,0,,We'll see this carefully in a second, but for now,\nDialogue: 0,0:46:49.80,0:46:51.77,EN,,0,0,0,,let's take a look at that slide again.\nDialogue: 0,0:46:52.24,0:46:53.80,EN,,0,0,0,,The image you should have here\nDialogue: 0,0:46:53.84,0:46:55.58,EN,,0,0,0,,of this signal processing system\nDialogue: 0,0:46:57.26,0:46:58.72,EN,,0,0,0,,is that what's going to happen\nDialogue: 0,0:46:59.13,0:47:00.92,EN,,0,0,0,,is there's sort of this box\nDialogue: 0,0:47:01.18,0:47:03.58,EN,,0,0,0,,that has the integers sitting in it.\nDialogue: 0,0:47:05.36,0:47:06.40,EN,,0,0,0,,And there's this filter\nDialogue: 0,0:47:07.45,0:47:09.37,EN,,0,0,0,,that's connected to it and it's tugging on them.\nDialogue: 0,0:47:10.94,0:47:13.15,EN,,0,0,0,,And then there's someone who's tugging on this stuff\nDialogue: 0,0:47:13.31,0:47:14.91,EN,,0,0,0,,saying what comes out of the filter.\nDialogue: 0,0:47:16.79,0:47:18.70,EN,,0,0,0,,And the image you should have is that\nDialogue: 0,0:47:18.99,0:47:20.72,EN,,0,0,0,,someone says, well, what's the first prime,\nDialogue: 0,0:47:22.67,0:47:24.14,EN,,0,0,0,,and tugs on this filter.\nDialogue: 0,0:47:24.59,0:47:26.12,EN,,0,0,0,,And the filter tugs on the integers.\nDialogue: 0,0:47:28.02,0:47:29.15,EN,,0,0,0,,And you look only at that much,\nDialogue: 0,0:47:29.16,0:47:30.93,EN,,0,0,0,,and then say, oh, I really wanted the second one.\nDialogue: 0,0:47:30.93,0:47:31.95,EN,,0,0,0,,What's the second prime?\nDialogue: 0,0:47:33.71,0:47:35.37,EN,,0,0,0,,And that no other computation\nDialogue: 0,0:47:35.37,0:47:36.64,EN,,0,0,0,,no computation gets done\nDialogue: 0,0:47:36.64,0:47:38.32,EN,,0,0,0,,except when you tug on these things.\nDialogue: 0,0:47:40.50,0:47:41.41,EN,,0,0,0,,Let me try that again.\nDialogue: 0,0:47:41.41,0:47:43.88,EN,,0,0,0,,This is a little device.\nDialogue: 0,0:47:43.90,0:47:44.97,EN,,0,0,0,,This is a little stream machine\nDialogue: 0,0:47:45.50,0:47:46.83,EN,,0,0,0,,invented by Eric Grimson\nDialogue: 0,0:47:47.60,0:47:49.24,EN,,0,0,0,,who's been teaching this course at MIT.\nDialogue: 0,0:47:49.83,0:47:52.51,EN,,0,0,0,,And the image is ... here's a stream of stuff,\nDialogue: 0,0:47:52.54,0:47:53.82,EN,,0,0,0,,like a whole bunch of the integers.\nDialogue: 0,0:47:54.78,0:47:56.33,EN,,0,0,0,,And here's some processing elements.\nDialogue: 0,0:47:58.70,0:48:02.60,EN,,0,0,0,,And if, say, it's filter of filter of map, or something.\nDialogue: 0,0:48:03.98,0:48:09.18,EN,,0,0,0,,And if I really tried to implement that with streams as lists,\nDialogue: 0,0:48:09.24,0:48:11.26,EN,,0,0,0,,what I'd say is, well, I've got this list of things,\nDialogue: 0,0:48:11.47,0:48:12.67,EN,,0,0,0,,and now I do the first filter.\nDialogue: 0,0:48:12.67,0:48:14.07,EN,,0,0,0,,So I sort of do all this processing.\nDialogue: 0,0:48:14.88,0:48:15.77,EN,,0,0,0,,And I take this\nDialogue: 0,0:48:16.32,0:48:19.21,EN,,0,0,0,,and I process and I process and I process and I process.\nDialogue: 0,0:48:19.61,0:48:21.05,EN,,0,0,0,,And now I'm got this new stream.\nDialogue: 0,0:48:21.63,0:48:24.07,EN,,0,0,0,,Right? Now I take that result in my hand someplace.\nDialogue: 0,0:48:24.07,0:48:25.26,EN,,0,0,0,,And I put that through the second one.\nDialogue: 0,0:48:25.56,0:48:26.94,EN,,0,0,0,,And I process the whole thing.\nDialogue: 0,0:48:28.27,0:48:29.51,EN,,0,0,0,,And there's this new stream.\nDialogue: 0,0:48:32.13,0:48:33.36,EN,,0,0,0,,And then I take the result\nDialogue: 0,0:48:34.28,0:48:36.36,EN,,0,0,0,,and I put it all the way through this one the same way.\nDialogue: 0,0:48:36.36,0:48:40.99,EN,,0,0,0,,That's what would happen to these stream programs\nDialogue: 0,0:48:41.69,0:48:42.97,EN,,0,0,0,,if streams were just lists.\nDialogue: 0,0:48:43.86,0:48:45.64,EN,,0,0,0,,But in fact, streams aren't lists, they're streams.\nDialogue: 0,0:48:45.82,0:48:48.11,EN,,0,0,0,,And the image you should have is something a little bit more like this.\nDialogue: 0,0:48:50.23,0:48:52.52,EN,,0,0,0,,I've got these gadgets connected up\nDialogue: 0,0:48:55.26,0:48:56.76,EN,,0,0,0,,by this data that's flowing out of them.\nDialogue: 0,0:49:00.33,0:49:02.30,EN,,0,0,0,,And here's my original source of the streams.\nDialogue: 0,0:49:02.32,0:49:02.92,EN,,0,0,0,,It might be\nDialogue: 0,0:49:04.19,0:49:05.72,EN,,0,0,0,,starting to generate the integers.\nDialogue: 0,0:49:05.98,0:49:07.39,EN,,0,0,0,,And now, what happens if I want a result?\nDialogue: 0,0:49:07.58,0:49:08.91,EN,,0,0,0,,I tug on the end here.\nDialogue: 0,0:49:10.20,0:49:11.07,EN,,0,0,0,,And this element says,\nDialogue: 0,0:49:11.08,0:49:12.20,EN,,0,0,0,,gee, I need some more data.\nDialogue: 0,0:49:13.09,0:49:15.52,EN,,0,0,0,,So it's sort of, this one comes here and tugs on that one.\nDialogue: 0,0:49:15.83,0:49:17.39,EN,,0,0,0,,And it says, gee, I need some more data.\nDialogue: 0,0:49:17.89,0:49:19.56,EN,,0,0,0,,And this one tugs on this thing,\nDialogue: 0,0:49:19.56,0:49:20.28,EN,,0,0,0,,which might be a filter,\nDialogue: 0,0:49:20.28,0:49:21.40,EN,,0,0,0,,and says, gee, I need some more data.\nDialogue: 0,0:49:21.64,0:49:23.15,EN,,0,0,0,,And only as much of this\nDialogue: 0,0:49:23.53,0:49:25.56,EN,,0,0,0,,thing at the end here gets generated as I tugged.\nDialogue: 0,0:49:25.78,0:49:28.30,EN,,0,0,0,,And only as much of this stuff goes through the processing units\nDialogue: 0,0:49:28.56,0:49:29.98,EN,,0,0,0,,as I'm pulling on the end I need.\nDialogue: 0,0:49:30.76,0:49:32.09,EN,,0,0,0,,That's the image you should have\nDialogue: 0,0:49:32.80,0:49:34.38,EN,,0,0,0,,of the difference between implementing\nDialogue: 0,0:49:34.56,0:49:35.92,EN,,0,0,0,,what we're actually going to do\nDialogue: 0,0:49:36.16,0:49:37.50,EN,,0,0,0,,and if streams were lists.\nDialogue: 0,0:49:40.78,0:49:42.14,EN,,0,0,0,,Well, how do we make this thing?\nDialogue: 0,0:49:42.35,0:49:43.32,EN,,0,0,0,,I hope you have the image.\nDialogue: 0,0:49:43.40,0:49:44.52,EN,,0,0,0,,The trick is how to make it.\nDialogue: 0,0:49:47.93,0:49:50.32,EN,,0,0,0,,We want to arrange for a stream\nDialogue: 0,0:49:50.41,0:49:51.58,EN,,0,0,0,,to be a data structure\nDialogue: 0,0:49:52.00,0:49:54.22,EN,,0,0,0,,that sorts of computes itself incrementally,\nDialogue: 0,0:49:54.22,0:49:56.22,EN,,0,0,0,,sort of on-demand data structure.\nDialogue: 0,0:49:58.96,0:50:00.51,EN,,0,0,0,,Right? And the basic idea\nDialogue: 0,0:50:00.97,0:50:02.70,EN,,0,0,0,,is again, one of the very basic ideas\nDialogue: 0,0:50:02.72,0:50:04.12,EN,,0,0,0,,that we're seeing throughout the whole course.\nDialogue: 0,0:50:04.49,0:50:05.00,EN,,0,0,0,,And that is\nDialogue: 0,0:50:05.52,0:50:06.97,EN,,0,0,0,,that there's not a firm distinction\nDialogue: 0,0:50:06.99,0:50:08.44,EN,,0,0,0,,between programs and data.\nDialogue: 0,0:50:09.24,0:50:10.54,EN,,0,0,0,,So what a stream is going to be\nDialogue: 0,0:50:10.59,0:50:13.40,EN,,0,0,0,,is simultaneously this data structure that you think of,\nDialogue: 0,0:50:13.45,0:50:15.92,EN,,0,0,0,,like the stream of the leaves of this tree.\nDialogue: 0,0:50:16.86,0:50:17.85,EN,,0,0,0,,But at the same time,\nDialogue: 0,0:50:17.85,0:50:19.32,EN,,0,0,0,,it's going to be a very clever procedure\nDialogue: 0,0:50:20.24,0:50:22.22,EN,,0,0,0,,that has the method of computing in it.\nDialogue: 0,0:50:23.74,0:50:25.93,EN,,0,0,0,,Well, let me try this.\nDialogue: 0,0:50:25.93,0:50:26.62,EN,,0,0,0,,It's going to turn out\nDialogue: 0,0:50:26.80,0:50:28.33,EN,,0,0,0,,that we don't need any more mechanism.\nDialogue: 0,0:50:28.46,0:50:29.87,EN,,0,0,0,,We already have everything we need\nDialogue: 0,0:50:30.14,0:50:30.99,EN,,0,0,0,,simply from the fact\nDialogue: 0,0:50:31.02,0:50:33.93,EN,,0,0,0,,that we know how to handle procedures as first-class objects.\nDialogue: 0,0:50:35.46,0:50:36.88,EN,,0,0,0,,Well, let's go back to the key.\nDialogue: 0,0:50:36.88,0:50:39.03,EN,,0,0,0,,The key is, remember, we had these operations.\nDialogue: 0,0:50:39.03,0:50:47.52,EN,,0,0,0,,CONS-stream and head and tail.\nDialogue: 0,0:50:48.08,0:50:49.36,EN,,0,0,0,,When I started, I said\nDialogue: 0,0:50:49.92,0:50:51.36,EN,,0,0,0,,you can think about this as CONS\nDialogue: 0,0:50:51.40,0:50:52.62,EN,,0,0,0,,and think about this as CAR\nDialogue: 0,0:50:52.62,0:50:53.52,EN,,0,0,0,,and think about that as CDR\nDialogue: 0,0:50:53.55,0:50:54.16,EN,,0,0,0,,but it's not.\nDialogue: 0,0:50:55.08,0:50:56.32,EN,,0,0,0,,Now, let's look at what they really are.\nDialogue: 0,0:50:57.71,0:51:05.84,EN,,0,0,0,,Well, CONS-stream of x and y\nDialogue: 0,0:51:07.48,0:51:17.79,EN,,0,0,0,,is going to be an abbreviation for the following thing.\nDialogue: 0,0:51:19.54,0:51:28.32,EN,,0,0,0,,CONS form a pair, ordinary CONS, of x to a thing called delay of y.\nDialogue: 0,0:51:31.68,0:51:33.53,EN,,0,0,0,,And before I explain that, let me go and write the rest.\nDialogue: 0,0:51:34.52,0:51:35.53,EN,,0,0,0,,The head of a stream\nDialogue: 0,0:51:38.09,0:51:39.79,EN,,0,0,0,,is going to be just the CAR.\nDialogue: 0,0:51:42.38,0:51:44.25,EN,,0,0,0,,And the tail of a stream\nDialogue: 0,0:51:46.68,0:51:54.60,EN,,0,0,0,,is going to be a thing called force the CDR of the stream.\nDialogue: 0,0:51:56.12,0:51:57.04,EN,,0,0,0,,Now let me explain this.\nDialogue: 0,0:51:58.06,0:51:59.88,EN,,0,0,0,,Delay is going to be a special magic thing.\nDialogue: 0,0:52:01.42,0:52:02.33,EN,,0,0,0,,What delay does\nDialogue: 0,0:52:03.85,0:52:05.31,EN,,0,0,0,,is take an expression\nDialogue: 0,0:52:05.50,0:52:06.86,EN,,0,0,0,,and produce a promise\nDialogue: 0,0:52:07.12,0:52:09.15,EN,,0,0,0,,to compute that expression when you ask for it.\nDialogue: 0,0:52:10.60,0:52:11.98,EN,,0,0,0,,It doesn't do any computation here.\nDialogue: 0,0:52:11.98,0:52:14.32,EN,,0,0,0,,Just sort of... It just gives you a rain check.\nDialogue: 0,0:52:14.82,0:52:16.20,EN,,0,0,0,,It produces a promise.\nDialogue: 0,0:52:17.11,0:52:18.20,EN,,0,0,0,,And CONS-stream says\nDialogue: 0,0:52:18.81,0:52:21.96,EN,,0,0,0,,I'm going to put together in a pair x\nDialogue: 0,0:52:23.31,0:52:25.36,EN,,0,0,0,,and a promise to compute y.\nDialogue: 0,0:52:28.23,0:52:28.99,EN,,0,0,0,,Now, if I want the head,\nDialogue: 0,0:52:28.99,0:52:30.75,EN,,0,0,0,,that's just the CAR that I put in the pair.\nDialogue: 0,0:52:31.84,0:52:33.71,EN,,0,0,0,,And the key is that the tail is going to be--\nDialogue: 0,0:52:34.62,0:52:36.65,EN,,0,0,0,,force calls in that promise.\nDialogue: 0,0:52:38.22,0:52:39.88,EN,,0,0,0,,Force -- Tail says, well,\nDialogue: 0,0:52:40.03,0:52:41.02,EN,,0,0,0,,well, take that promise\nDialogue: 0,0:52:41.85,0:52:44.52,EN,,0,0,0,,and now call in that promise.\nDialogue: 0,0:52:44.56,0:52:46.03,EN,,0,0,0,,And then we compute that thing.\nDialogue: 0,0:52:47.69,0:52:48.72,EN,,0,0,0,,That's how this is going to work.\nDialogue: 0,0:52:48.74,0:52:51.55,EN,,0,0,0,,That's what CONS-stream, head, and tail really are.\nDialogue: 0,0:52:54.60,0:52:55.57,EN,,0,0,0,,Now, let's see how this works.\nDialogue: 0,0:52:55.57,0:52:57.50,EN,,0,0,0,,And we'll go through this fairly carefully. Let's --\nDialogue: 0,0:52:58.76,0:53:00.62,EN,,0,0,0,,We're going to see how this\nDialogue: 0,0:53:01.32,0:53:03.66,EN,,0,0,0,,example of computing the second prime\nDialogue: 0,0:53:05.50,0:53:07.16,EN,,0,0,0,,right? between 10,000 and a million.\nDialogue: 0,0:53:08.65,0:53:12.03,EN,,0,0,0,,OK, so we start off and we have this expression.\nDialogue: 0,0:53:15.36,0:53:16.62,EN,,0,0,0,,Right? The second prime--\nDialogue: 0,0:53:16.64,0:53:21.90,EN,,0,0,0,,the head of the tail of the result of filtering for primality\nDialogue: 0,0:53:22.83,0:53:25.31,EN,,0,0,0,,the integers between 10,000 and 1 million.\nDialogue: 0,0:53:26.71,0:53:27.61,EN,,0,0,0,,Now, what is that?\nDialogue: 0,0:53:28.40,0:53:29.20,EN,,0,0,0,,What that is,\nDialogue: 0,0:53:31.63,0:53:34.17,EN,,0,0,0,,that interval between 10,000 and 1 million,\nDialogue: 0,0:53:35.72,0:53:37.32,EN,,0,0,0,,well, if you trace through enumerate interval,\nDialogue: 0,0:53:37.34,0:53:38.78,EN,,0,0,0,,there builds a CONS-stream.\nDialogue: 0,0:53:39.92,0:53:41.39,EN,,0,0,0,,And the CONS-stream is\nDialogue: 0,0:53:41.96,0:53:43.61,EN,,0,0,0,,the CONS of 10,000\nDialogue: 0,0:53:44.51,0:53:48.92,EN,,0,0,0,,to a promise to compute the integers between 10,001 and 1 million.\nDialogue: 0,0:53:54.00,0:53:55.75,EN,,0,0,0,,Okay? So that's what this expression is.\nDialogue: 0,0:53:55.75,0:53:57.32,EN,,0,0,0,,Here I'm using the substitution model.\nDialogue: 0,0:53:57.64,0:53:59.32,EN,,0,0,0,,And we can use the substitution model\nDialogue: 0,0:53:59.34,0:54:01.01,EN,,0,0,0,,because we don't have side effects and state.\nDialogue: 0,0:54:03.56,0:54:06.38,EN,,0,0,0,,Okay? So I have CONS of 10,000\nDialogue: 0,0:54:06.41,0:54:08.27,EN,,0,0,0,,to a promise to compute the rest of the integers.\nDialogue: 0,0:54:08.32,0:54:10.49,EN,,0,0,0,,So only one integer, so far, got enumerated.\nDialogue: 0,0:54:14.38,0:54:16.96,EN,,0,0,0,,Well, I'm going to filter that thing for primality.\nDialogue: 0,0:54:19.44,0:54:21.90,EN,,0,0,0,,Again, you go back and look at the filter code.\nDialogue: 0,0:54:22.36,0:54:24.46,EN,,0,0,0,,What the filter will first do is test the head.\nDialogue: 0,0:54:25.46,0:54:28.25,EN,,0,0,0,,So in this case, the filter will test 10,000\nDialogue: 0,0:54:30.30,0:54:32.97,EN,,0,0,0,,oh, 10,000's not prime.\nDialogue: 0,0:54:33.50,0:54:35.85,EN,,0,0,0,,Therefore, what I have to do recursively\nDialogue: 0,0:54:36.25,0:54:37.39,EN,,0,0,0,,is filter the tail.\nDialogue: 0,0:54:39.22,0:54:40.14,EN,,0,0,0,,And what's the tail of it,\nDialogue: 0,0:54:40.16,0:54:43.76,EN,,0,0,0,,well, that's the tail of this pair with a promise in it.\nDialogue: 0,0:54:46.34,0:54:48.06,EN,,0,0,0,,Tail now comes in and says,\nDialogue: 0,0:54:48.28,0:54:49.50,EN,,0,0,0,,well, I'm going to force that.\nDialogue: 0,0:54:49.68,0:54:50.94,EN,,0,0,0,,I'm going to force that promise,\nDialogue: 0,0:54:52.30,0:54:54.36,EN,,0,0,0,,which means now I'm going to compute\nDialogue: 0,0:54:55.58,0:54:57.96,EN,,0,0,0,,the integers between 10,001 and 1 million.\nDialogue: 0,0:55:00.80,0:55:02.97,EN,,0,0,0,,OK? So this filter now is looking at that.\nDialogue: 0,0:55:07.81,0:55:08.92,EN,,0,0,0,,That enumerate itself,\nDialogue: 0,0:55:08.94,0:55:11.23,EN,,0,0,0,,now we're back in the original enumerate situation.\nDialogue: 0,0:55:11.96,0:55:13.00,EN,,0,0,0,,The enumerate is\nDialogue: 0,0:55:14.12,0:55:16.44,EN,,0,0,0,,CONS of the first thing, 10,001,\nDialogue: 0,0:55:16.60,0:55:18.20,EN,,0,0,0,,onto a promise to compute the rest.\nDialogue: 0,0:55:19.74,0:55:22.75,EN,,0,0,0,,So now the primality filter is going to go look at 10,001.\nDialogue: 0,0:55:23.23,0:55:25.12,EN,,0,0,0,,It's going to decide if it likes that or not.\nDialogue: 0,0:55:25.12,0:55:27.08,EN,,0,0,0,,It turns out 10,001 isn't prime.\nDialogue: 0,0:55:27.55,0:55:29.61,EN,,0,0,0,,So it'll force it again and again and again.\nDialogue: 0,0:55:32.92,0:55:35.80,EN,,0,0,0,,And finally, I think the first prime it hits is 10,009.\nDialogue: 0,0:55:37.10,0:55:38.33,EN,,0,0,0,,And at that point, it'll stop.\nDialogue: 0,0:55:40.84,0:55:41.93,EN,,0,0,0,,And that will be the first prime,\nDialogue: 0,0:55:41.96,0:55:43.48,EN,,0,0,0,,and then eventually, it'll need the second prime.\nDialogue: 0,0:55:45.24,0:55:46.84,EN,,0,0,0,,So at that point, it will go again.\nDialogue: 0,0:55:47.03,0:55:48.25,EN,,0,0,0,,So you see what happens is that\nDialogue: 0,0:55:48.52,0:55:50.49,EN,,0,0,0,,no more gets generated\nDialogue: 0,0:55:51.85,0:55:52.91,EN,,0,0,0,,than you actually need.\nDialogue: 0,0:55:56.48,0:55:59.92,EN,,0,0,0,,That enumerator is not going to generate any more integers\nDialogue: 0,0:56:00.12,0:56:01.45,EN,,0,0,0,,than the filter asks it for\nDialogue: 0,0:56:01.47,0:56:03.45,EN,,0,0,0,,as it's pulling in things to check for primality.\nDialogue: 0,0:56:04.70,0:56:06.51,EN,,0,0,0,,And the filter is not going to generate\nDialogue: 0,0:56:06.54,0:56:08.04,EN,,0,0,0,,any more stuff than you ask it for,\nDialogue: 0,0:56:08.06,0:56:09.10,EN,,0,0,0,,which is the head of the tail.\nDialogue: 0,0:56:11.61,0:56:13.26,EN,,0,0,0,,You see, what's happened is\nDialogue: 0,0:56:14.70,0:56:18.24,EN,,0,0,0,,we've put that mixing of generation and test\nDialogue: 0,0:56:18.67,0:56:20.65,EN,,0,0,0,,into what actually happens in the computer,\nDialogue: 0,0:56:21.52,0:56:22.67,EN,,0,0,0,,even though\nDialogue: 0,0:56:23.18,0:56:25.63,EN,,0,0,0,,that's not apparently what's happening from looking at our programs.\nDialogue: 0,0:56:28.12,0:56:29.40,EN,,0,0,0,,OK, well, that seemed easy.\nDialogue: 0,0:56:30.23,0:56:32.67,EN,,0,0,0,,All of this mechanism got put into this magic delay.\nDialogue: 0,0:56:33.68,0:56:35.66,EN,,0,0,0,,So you're saying, gee, that must be where the magic is.\nDialogue: 0,0:56:36.90,0:56:38.57,EN,,0,0,0,,But see there's no magic there either.\nDialogue: 0,0:56:39.07,0:56:39.98,EN,,0,0,0,,You know what delay is.\nDialogue: 0,0:56:40.61,0:56:45.07,EN,,0,0,0,,Delay on some expression\nDialogue: 0,0:56:48.25,0:56:50.04,EN,,0,0,0,,is just an abbreviation for--\nDialogue: 0,0:56:53.36,0:56:55.63,EN,,0,0,0,,well, what's a promise to compute an expression?\nDialogue: 0,0:56:56.49,0:57:01.12,EN,,0,0,0,,Lambda of nil, procedure of no arguments, which is that expression.\nDialogue: 0,0:57:02.83,0:57:03.84,EN,,0,0,0,,Right? That's what a procedure is.\nDialogue: 0,0:57:03.98,0:57:05.53,EN,,0,0,0,,It says I'm going to compute an expression.\nDialogue: 0,0:57:06.05,0:57:06.73,EN,,0,0,0,,What's force?\nDialogue: 0,0:57:07.34,0:57:10.80,EN,,0,0,0,,Right, how do I take up a promise?\nDialogue: 0,0:57:10.80,0:57:14.11,EN,,0,0,0,,Well, force of some procedure, a promise,\nDialogue: 0,0:57:14.78,0:57:15.40,EN,,0,0,0,,is just run it.\nDialogue: 0,0:57:19.23,0:57:19.56,EN,,0,0,0,,Done.\nDialogue: 0,0:57:20.24,0:57:21.37,EN,,0,0,0,,So there's no magic there at all.\nDialogue: 0,0:57:23.52,0:57:24.24,EN,,0,0,0,,Well, what have we done?\nDialogue: 0,0:57:26.44,0:57:27.50,EN,,0,0,0,,We said the old style,\nDialogue: 0,0:57:28.14,0:57:30.81,EN,,0,0,0,,traditional style of programming is more efficient.\nDialogue: 0,0:57:30.96,0:57:33.92,EN,,0,0,0,,And the stream thing is more perspicacious.\nDialogue: 0,0:57:35.50,0:57:38.72,EN,,0,0,0,,And we managed to make the stream procedures\nDialogue: 0,0:57:38.81,0:57:43.23,EN,,0,0,0,,run like the other procedures by using delay.\nDialogue: 0,0:57:43.35,0:57:46.43,EN,,0,0,0,,And the thing that delay did for us was to de-couple\nDialogue: 0,0:57:46.68,0:57:50.40,EN,,0,0,0,,the apparent order of events in our programs\nDialogue: 0,0:57:51.21,0:57:53.84,EN,,0,0,0,,from the actual order of events that happened in the machine.\nDialogue: 0,0:57:54.44,0:57:55.93,EN,,0,0,0,,That's really what delay is doing.\nDialogue: 0,0:57:57.15,0:57:58.29,EN,,0,0,0,,That's exactly the whole point.\nDialogue: 0,0:57:58.29,0:58:01.92,EN,,0,0,0,,We've given up, right, we've given up the idea\nDialogue: 0,0:58:02.30,0:58:04.17,EN,,0,0,0,,that our procedures, as they run,\nDialogue: 0,0:58:04.67,0:58:05.95,EN,,0,0,0,,or as we look at them,\nDialogue: 0,0:58:06.33,0:58:08.25,EN,,0,0,0,,mirror some clear notion of time.\nDialogue: 0,0:58:09.45,0:58:10.57,EN,,0,0,0,,And by giving that up,\nDialogue: 0,0:58:11.21,0:58:13.32,EN,,0,0,0,,we give delay the freedom to arrange the order\nDialogue: 0,0:58:13.34,0:58:15.20,EN,,0,0,0,,of events in the computation the way it likes.\nDialogue: 0,0:58:16.69,0:58:17.61,EN,,0,0,0,,That's the whole idea.\nDialogue: 0,0:58:17.61,0:58:19.45,EN,,0,0,0,,We de-couple the apparent order\nDialogue: 0,0:58:19.95,0:58:21.13,EN,,0,0,0,,of events in our programs\nDialogue: 0,0:58:21.16,0:58:22.89,EN,,0,0,0,,from the actual order of events in the computer.\nDialogue: 0,0:58:24.09,0:58:25.77,EN,,0,0,0,,OK, well there's one more detail.\nDialogue: 0,0:58:25.77,0:58:27.21,EN,,0,0,0,,It's just a technical detail,\nDialogue: 0,0:58:27.21,0:58:28.43,EN,,0,0,0,,but it's actually an important one.\nDialogue: 0,0:58:29.73,0:58:32.01,EN,,0,0,0,,As you run through these recursive programs unwinding,\nDialogue: 0,0:58:32.16,0:58:33.58,EN,,0,0,0,,you'll see a lot of things that look like\nDialogue: 0,0:58:33.64,0:58:37.87,EN,,0,0,0,,tail of the tail of the tail.\nDialogue: 0,0:58:39.20,0:58:41.02,EN,,0,0,0,,Right. That's the kind of thing that would happen\nDialogue: 0,0:58:41.02,0:58:42.88,EN,,0,0,0,,as I go CONSing down a stream all the way.\nDialogue: 0,0:58:43.86,0:58:46.09,EN,,0,0,0,,And if each time I'm doing that,\nDialogue: 0,0:58:46.14,0:58:47.58,EN,,0,0,0,,each time to compute a tail,\nDialogue: 0,0:58:48.22,0:58:50.88,EN,,0,0,0,,I evaluate a procedure\nDialogue: 0,0:58:51.07,0:58:53.07,EN,,0,0,0,,which then has to go re-compute its tail,\nDialogue: 0,0:58:53.10,0:58:55.40,EN,,0,0,0,,and re-compute its tail and recompute its tail each time,\nDialogue: 0,0:58:55.50,0:58:56.88,EN,,0,0,0,,you can see that's very inefficient\nDialogue: 0,0:58:57.77,0:59:00.56,EN,,0,0,0,,compared to just having a list where the elements are all there,\nDialogue: 0,0:59:01.16,0:59:04.00,EN,,0,0,0,,and I don't have to re-compute each tail every time I get the next tail.\nDialogue: 0,0:59:05.29,0:59:08.28,EN,,0,0,0,,So there's one little hack\nDialogue: 0,0:59:09.66,0:59:13.13,EN,,0,0,0,,to slightly change the abbreviation, change what delay is\nDialogue: 0,0:59:14.96,0:59:18.20,EN,,0,0,0,,and make it a thing which is-- I'll write it this way.\nDialogue: 0,0:59:19.68,0:59:22.04,EN,,0,0,0,,Delay -- The actual implementation,\nDialogue: 0,0:59:24.52,0:59:27.93,EN,,0,0,0,,delay is an abbreviation for this thing,\nDialogue: 0,0:59:28.11,0:59:30.86,EN,,0,0,0,,memo-proc of a procedure.\nDialogue: 0,0:59:31.00,0:59:34.06,EN,,0,0,0,,Memo-proc is a special thing that transforms a procedure.\nDialogue: 0,0:59:35.15,0:59:37.80,EN,,0,0,0,,What it does is it takes a procedure of no arguments\nDialogue: 0,0:59:39.02,0:59:41.05,EN,,0,0,0,,and it transforms it into a procedure\nDialogue: 0,0:59:41.36,0:59:43.55,EN,,0,0,0,,that'll only have to do its computation once.\nDialogue: 0,0:59:45.10,0:59:47.45,EN,,0,0,0,,And what I mean by that is, you give it a procedure.\nDialogue: 0,0:59:48.70,0:59:50.86,EN,,0,0,0,,The result of memo-proc will be a new procedure,\nDialogue: 0,0:59:51.39,0:59:53.00,EN,,0,0,0,,which the first time you call it,\nDialogue: 0,0:59:53.71,0:59:55.07,EN,,0,0,0,,will run the original procedure,\nDialogue: 0,0:59:55.31,0:59:56.91,EN,,0,0,0,,remember what result it got,\nDialogue: 0,0:59:58.56,1:00:00.68,EN,,0,0,0,,and then from ever on after, when you call it,\nDialogue: 0,1:00:00.68,1:00:02.17,EN,,0,0,0,,it just won't have to do the computation.\nDialogue: 0,1:00:02.19,1:00:04.43,EN,,0,0,0,,It will have cached that result someplace.\nDialogue: 0,1:00:05.20,1:00:06.92,EN,,0,0,0,,And here's an implementation of memo-proc.\nDialogue: 0,1:00:11.21,1:00:12.71,EN,,0,0,0,,Once you have the idea, it's easy to implement.\nDialogue: 0,1:00:12.71,1:00:16.76,EN,,0,0,0,,Memo-proc is this little thing that has two little flags in there.\nDialogue: 0,1:00:17.39,1:00:19.20,EN,,0,0,0,,It says, have I already been run?\nDialogue: 0,1:00:20.32,1:00:22.48,EN,,0,0,0,,And initially it says, no, I haven't already been run.\nDialogue: 0,1:00:23.62,1:00:27.04,EN,,0,0,0,,And what was the result I got the last time I was run?\nDialogue: 0,1:00:29.07,1:00:31.07,EN,,0,0,0,,So memo-proc takes a procedure called proc,\nDialogue: 0,1:00:31.56,1:00:34.01,EN,,0,0,0,,and it returns a new procedure of no arguments.\nDialogue: 0,1:00:34.36,1:00:36.38,EN,,0,0,0,,Proc is supposed to be a procedure of no arguments.\nDialogue: 0,1:00:38.61,1:00:41.37,EN,,0,0,0,,And it says, oh, if I'm not already run,\nDialogue: 0,1:00:42.59,1:00:44.06,EN,,0,0,0,,then I'm going to do a sequence of things.\nDialogue: 0,1:00:44.43,1:00:46.56,EN,,0,0,0,,I'm going to compute proc,\nDialogue: 0,1:00:47.50,1:00:48.45,EN,,0,0,0,,I'm going to save that.\nDialogue: 0,1:00:48.45,1:00:50.48,EN,,0,0,0,,I'm going to stash that in the variable result.\nDialogue: 0,1:00:51.14,1:00:53.90,EN,,0,0,0,,I'm going to make a note to myself that I've already been run,\nDialogue: 0,1:00:54.28,1:00:55.47,EN,,0,0,0,,and then I'll return the result.\nDialogue: 0,1:00:56.61,1:00:59.01,EN,,0,0,0,,So that's if you compute it if it's not already run.\nDialogue: 0,1:00:59.01,1:01:01.88,EN,,0,0,0,,If you call it and it's already been run, it just returns the result.\nDialogue: 0,1:01:03.42,1:01:07.12,EN,,0,0,0,,So that's a little clever hack called memoization.\nDialogue: 0,1:01:08.40,1:01:09.13,EN,,0,0,0,,And in this case,\nDialogue: 0,1:01:10.35,1:01:14.14,EN,,0,0,0,,it short circuits having to re-compute the tail of the tail of the tail of the tail of the tail.\nDialogue: 0,1:01:15.27,1:01:17.81,EN,,0,0,0,,So there isn't even that kind of inefficiency.\nDialogue: 0,1:01:17.81,1:01:18.72,EN,,0,0,0,,And in fact, the streams\nDialogue: 0,1:01:19.20,1:01:22.75,EN,,0,0,0,,will run with pretty much the same efficiency as the other programs precisely.\nDialogue: 0,1:01:24.01,1:01:26.20,EN,,0,0,0,,And remember, again, the whole idea of this\nDialogue: 0,1:01:27.48,1:01:28.60,EN,,0,0,0,,is that we've used\nDialogue: 0,1:01:29.26,1:01:32.40,EN,,0,0,0,,the fact that there's no really good dividing line\nDialogue: 0,1:01:32.41,1:01:33.61,EN,,0,0,0,,between procedures and data.\nDialogue: 0,1:01:33.61,1:01:35.61,EN,,0,0,0,,We've written data structures that, in fact,\nDialogue: 0,1:01:36.00,1:01:37.31,EN,,0,0,0,,are sort of like procedures.\nDialogue: 0,1:01:38.76,1:01:40.73,EN,,0,0,0,,And what that's allowed us to do\nDialogue: 0,1:01:41.58,1:01:46.54,EN,,0,0,0,,is take an example of a common control structure,\nDialogue: 0,1:01:46.68,1:01:48.91,EN,,0,0,0,,in this place iteration.\nDialogue: 0,1:01:49.62,1:01:51.05,EN,,0,0,0,,And we've built a data structure\nDialogue: 0,1:01:51.32,1:01:52.84,EN,,0,0,0,,which, since itself is a procedure,\nDialogue: 0,1:01:52.86,1:01:55.12,EN,,0,0,0,,kind of has this iteration control structure in it.\nDialogue: 0,1:01:55.79,1:01:57.13,EN,,0,0,0,,And that's really what streams are.\nDialogue: 0,1:01:58.91,1:01:59.76,EN,,0,0,0,,OK, questions?\nDialogue: 0,1:02:03.95,1:02:05.84,EN,,0,0,0,,AUDIENCE: Your description of tail-tail-tail,\nDialogue: 0,1:02:05.85,1:02:07.16,EN,,0,0,0,,if I understand it correctly,\nDialogue: 0,1:02:07.28,1:02:10.76,EN,,0,0,0,,force is actually execution of a procedure,\nDialogue: 0,1:02:10.78,1:02:12.83,EN,,0,0,0,,if it's done without this memo-proc thing.\nDialogue: 0,1:02:12.89,1:02:13.15,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:02:13.44,1:02:16.38,EN,,0,0,0,,AUDIENCE: And you implied that memo-proc gets around that problem.\nDialogue: 0,1:02:16.38,1:02:18.73,EN,,0,0,0,,Doesn't it only get around it if\nDialogue: 0,1:02:19.34,1:02:22.19,EN,,0,0,0,,tail-tail-tail is always executing exactly the same--\nDialogue: 0,1:02:22.41,1:02:23.91,EN,,0,0,0,,PROFESSOR: Oh, that's-- sure.\nDialogue: 0,1:02:23.91,1:02:25.84,EN,,0,0,0,,AUDIENCE: I guess I missed that point.\nDialogue: 0,1:02:26.05,1:02:27.21,EN,,0,0,0,,PROFESSOR: Oh, sure. I mean the point is--  yeah.\nDialogue: 0,1:02:31.12,1:02:33.64,EN,,0,0,0,,Yeah, I mean I have to do a computation to get the answer.\nDialogue: 0,1:02:34.09,1:02:36.76,EN,,0,0,0,,But the point is, once I've found the tail of the stream,\nDialogue: 0,1:02:37.58,1:02:38.70,EN,,0,0,0,,to get the tail of the tail,\nDialogue: 0,1:02:38.70,1:02:40.51,EN,,0,0,0,,I shouldn't have had to re-compute the first tail.\nDialogue: 0,1:02:42.98,1:02:44.32,EN,,0,0,0,,See, and if I didn't use memo-proc,\nDialogue: 0,1:02:44.35,1:02:46.09,EN,,0,0,0,,that re-computation would have been done.\nDialogue: 0,1:02:46.46,1:02:47.13,EN,,0,0,0,,AUDIENCE: I understand now.\nDialogue: 0,1:02:50.83,1:02:52.56,EN,,0,0,0,,AUDIENCE: In one of your examples, you mentioned that\nDialogue: 0,1:02:52.60,1:02:54.22,EN,,0,0,0,,we were able to use the substitution model\nDialogue: 0,1:02:54.22,1:02:56.11,EN,,0,0,0,,because there are no side effects.\nDialogue: 0,1:02:56.83,1:03:00.73,EN,,0,0,0,,What if we had a signal processing unit--\nDialogue: 0,1:03:00.78,1:03:02.03,EN,,0,0,0,,if we had a side effect,\nDialogue: 0,1:03:02.04,1:03:03.04,EN,,0,0,0,,if we had a state?\nDialogue: 0,1:03:03.62,1:03:06.84,EN,,0,0,0,,Could we still practically build the stream model?\nDialogue: 0,1:03:08.46,1:03:10.59,EN,,0,0,0,,PROFESSOR: Hum... Maybe, That's a hard question.\nDialogue: 0,1:03:11.20,1:03:13.42,EN,,0,0,0,,I'm going to talk a little bit later about the places where\nDialogue: 0,1:03:14.36,1:03:18.24,EN,,0,0,0,,where substitution and side effects don't really mix very well.\nDialogue: 0,1:03:18.96,1:03:20.48,EN,,0,0,0,,But in general, I think the answer is\nDialogue: 0,1:03:20.49,1:03:21.63,EN,,0,0,0,,unless you're very careful,\nDialogue: 0,1:03:21.90,1:03:24.46,EN,,0,0,0,,any amount of side effect is going to mess up everything.\nDialogue: 0,1:03:35.04,1:03:38.25,EN,,0,0,0,,AUDIENCE: Sorry, I didn't quite understand the memo-proc operation. Uh...\nDialogue: 0,1:03:39.68,1:03:41.12,EN,,0,0,0,,When do you execute the lambda?\nDialogue: 0,1:03:41.99,1:03:43.21,EN,,0,0,0,,In other words,\nDialogue: 0,1:03:43.68,1:03:45.15,EN,,0,0,0,,when memo-proc is executed,\nDialogue: 0,1:03:45.18,1:03:47.71,EN,,0,0,0,,just this lambda expression is being generated.\nDialogue: 0,1:03:48.01,1:03:49.68,EN,,0,0,0,,But it's not clear to me when it's executed.\nDialogue: 0,1:03:50.39,1:03:51.12,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:03:51.35,1:03:52.68,EN,,0,0,0,,What memo-proc does-- remember,\nDialogue: 0,1:03:53.07,1:03:55.85,EN,,0,0,0,,the thing that's going into memo-proc, the thing proc,\nDialogue: 0,1:03:56.38,1:03:57.93,EN,,0,0,0,,is a procedure of no arguments.\nDialogue: 0,1:03:57.93,1:03:59.05,EN,,0,0,0,,And someday, you're going to call it.\nDialogue: 0,1:04:00.39,1:04:02.75,EN,,0,0,0,,Memo-proc translates that procedure\nDialogue: 0,1:04:02.75,1:04:04.56,EN,,0,0,0,,into another procedure of no arguments,\nDialogue: 0,1:04:04.59,1:04:05.80,EN,,0,0,0,,which someday you're going to call.\nDialogue: 0,1:04:06.62,1:04:07.42,EN,,0,0,0,,That's that lambda.\nDialogue: 0,1:04:09.89,1:04:14.08,EN,,0,0,0,,So here, where I initially built as my\nDialogue: 0,1:04:15.85,1:04:17.92,EN,,0,0,0,,I built as my tail of the stream,\nDialogue: 0,1:04:18.30,1:04:20.48,EN,,0,0,0,,say, this procedure of no arguments,\nDialogue: 0,1:04:20.51,1:04:21.61,EN,,0,0,0,,which someday I'll call.\nDialogue: 0,1:04:24.10,1:04:28.01,EN,,0,0,0,,Instead, I'm going to have the tail of the stream be memo-proc of it,\nDialogue: 0,1:04:28.12,1:04:29.24,EN,,0,0,0,,which someday I'll call.\nDialogue: 0,1:04:30.65,1:04:31.90,EN,,0,0,0,,So that lambda of nil,\nDialogue: 0,1:04:32.03,1:04:36.06,EN,,0,0,0,,that gets called when you call the memo-proc,\nDialogue: 0,1:04:38.97,1:04:40.96,EN,,0,0,0,,when you call the result of that memo-proc,\nDialogue: 0,1:04:40.97,1:04:42.28,EN,,0,0,0,,which would be ordinarily\nDialogue: 0,1:04:42.36,1:04:45.76,EN,,0,0,0,,when you would have called the original thing that you set it.\nDialogue: 0,1:04:47.64,1:04:48.86,EN,,0,0,0,,AUDIENCE: OK, my ask is\nDialogue: 0,1:04:48.86,1:04:50.86,EN,,0,0,0,,I had a feeling that when you call memo-proc,\nDialogue: 0,1:04:50.86,1:04:52.30,EN,,0,0,0,,you just return this lambda.\nDialogue: 0,1:04:52.61,1:04:53.07,EN,,0,0,0,,PROFESSOR: That's right.\nDialogue: 0,1:04:53.77,1:04:58.10,EN,,0,0,0,,When you call memo-proc, you return the lambda.\nDialogue: 0,1:04:58.10,1:04:59.84,EN,,0,0,0,,You never evaluate the expression at all,\nDialogue: 0,1:04:59.87,1:05:02.27,EN,,0,0,0,,until the first time that you would have evaluated it.\nDialogue: 0,1:05:07.76,1:05:09.10,EN,,0,0,0,,AUDIENCE: Do I understand it right\nDialogue: 0,1:05:09.18,1:05:11.40,EN,,0,0,0,,you actually have to build the list up,\nDialogue: 0,1:05:11.47,1:05:14.17,EN,,0,0,0,,but the elements of the list don't get evaluated?\nDialogue: 0,1:05:14.24,1:05:15.63,EN,,0,0,0,,The expressions don't get evaluated?\nDialogue: 0,1:05:15.63,1:05:18.54,EN,,0,0,0,,But at each stage, you actually are building a list.\nDialogue: 0,1:05:18.54,1:05:20.70,EN,,0,0,0,,PROFESSOR: That's-- I really should have said this.\nDialogue: 0,1:05:20.70,1:05:22.27,EN,,0,0,0,,That's a really good point.\nDialogue: 0,1:05:22.27,1:05:23.18,EN,,0,0,0,,No, it's not quite right.\nDialogue: 0,1:05:23.66,1:05:25.08,EN,,0,0,0,,See, cause what happens is this.\nDialogue: 0,1:05:25.08,1:05:26.35,EN,,0,0,0,,Let me draw this as pairs.\nDialogue: 0,1:05:26.89,1:05:28.03,EN,,0,0,0,,Suppose I'm going to make a big stream,\nDialogue: 0,1:05:28.96,1:05:30.12,EN,,0,0,0,,like enumerate interval,\nDialogue: 0,1:05:30.32,1:05:31.48,EN,,0,0,0,,1 through 1 billion.\nDialogue: 0,1:05:32.74,1:05:35.74,EN,,0,0,0,,What that is, is a pair\nDialogue: 0,1:05:39.34,1:05:43.36,EN,,0,0,0,,a 1 and a promise.\nDialogue: 0,1:05:46.73,1:05:47.89,EN,,0,0,0,,That's exactly what it is.\nDialogue: 0,1:05:47.89,1:05:48.76,EN,,0,0,0,,Nothing got built up.\nDialogue: 0,1:05:51.60,1:05:53.29,EN,,0,0,0,,When I go and force this,\nDialogue: 0,1:05:54.51,1:05:56.37,EN,,0,0,0,,and see, what happens?\nDialogue: 0,1:05:56.37,1:05:59.66,EN,,0,0,0,,Well, this thing is now also recursively a CONS.\nDialogue: 0,1:06:00.53,1:06:02.16,EN,,0,0,0,,So that this promise now is\nDialogue: 0,1:06:04.62,1:06:08.96,EN,,0,0,0,,the next thing, which is a 2 and a promise to do more.\nDialogue: 0,1:06:11.35,1:06:12.73,EN,,0,0,0,,And so on and so on and so on.\nDialogue: 0,1:06:14.47,1:06:17.63,EN,,0,0,0,,So nothing gets built up until you walk down the stream.\nDialogue: 0,1:06:18.20,1:06:19.58,EN,,0,0,0,,Because what's sitting here is not the list,\nDialogue: 0,1:06:20.03,1:06:21.48,EN,,0,0,0,,but a promise to generate the list.\nDialogue: 0,1:06:23.39,1:06:25.50,EN,,0,0,0,,And by promise, technically I mean procedure.\nDialogue: 0,1:06:27.80,1:06:29.10,EN,,0,0,0,,So it doesn't get built up.\nDialogue: 0,1:06:30.76,1:06:32.72,EN,,0,0,0,,Yeah, I should have said that before that.\nDialogue: 0,1:06:34.28,1:06:35.34,EN,,0,0,0,,OK. That you. Let's take a break.\nDialogue: 0,1:06:35.82,1:06:51.15,Declare,,0,0,0,,{\\fad(500,500)}http://ocw.mit.edu\nDialogue: 0,1:06:35.82,1:06:51.15,Declare,,0,0,0,,{\\an2\\fad(500,500)}https://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec6b.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nVideo Position: 629\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:20.97,0:00:24.08,EN,,0,0,0,,PROFESSOR: OK, well, we've been looking at streams,\nDialogue: 0,0:00:24.08,0:00:27.82,EN,,0,0,0,,this signal processing way of putting systems together.\nDialogue: 0,0:00:28.87,0:00:31.42,EN,,0,0,0,,And remember, the key idea is that\nDialogue: 0,0:00:31.90,0:00:32.96,EN,,0,0,0,,we decouple\nDialogue: 0,0:00:34.20,0:00:37.31,EN,,0,0,0,,the apparent order of events in our programs\nDialogue: 0,0:00:37.58,0:00:40.17,EN,,0,0,0,,from the actual order of events in the computer.\nDialogue: 0,0:00:41.07,0:00:42.28,EN,,0,0,0,,And that means that we can start\nDialogue: 0,0:00:42.57,0:00:44.14,EN,,0,0,0,,dealing with very long streams\nDialogue: 0,0:00:44.89,0:00:47.39,EN,,0,0,0,,and only having to generate the elements on demand.\nDialogue: 0,0:00:47.53,0:00:49.39,EN,,0,0,0,,That sort of on-demand computation\nDialogue: 0,0:00:49.52,0:00:51.40,EN,,0,0,0,,is built into the stream's data structure.\nDialogue: 0,0:00:54.11,0:00:55.64,EN,,0,0,0,,So if we have a very long stream,\nDialogue: 0,0:00:55.66,0:00:57.08,EN,,0,0,0,,we only compute what we need.\nDialogue: 0,0:00:58.04,0:01:00.75,EN,,0,0,0,,The things only get computed when we actually ask for them.\nDialogue: 0,0:01:00.75,0:01:01.74,EN,,0,0,0,,Well, what are examples?\nDialogue: 0,0:01:02.11,0:01:03.60,EN,,0,0,0,,Are they actually asking for them?\nDialogue: 0,0:01:05.02,0:01:06.01,EN,,0,0,0,,For instance, we might\nDialogue: 0,0:01:09.21,0:01:11.37,EN,,0,0,0,,might ask for the n-th element of a stream.\nDialogue: 0,0:01:15.36,0:01:18.92,EN,,0,0,0,,Here's a procedure that computes the n-th element of a stream.\nDialogue: 0,0:01:20.09,0:01:21.23,EN,,0,0,0,,An integer n,\nDialogue: 0,0:01:21.24,0:01:22.84,EN,,0,0,0,,the n-th element of some stream s,\nDialogue: 0,0:01:23.40,0:01:25.42,EN,,0,0,0,,and we just recursively walk down the stream.\nDialogue: 0,0:01:25.57,0:01:27.39,EN,,0,0,0,,And if n is 0, we compute the head.\nDialogue: 0,0:01:27.96,0:01:30.99,EN,,0,0,0,,Otherwise, it's the n-th the minus 1 element\nDialogue: 0,0:01:31.74,0:01:32.80,EN,,0,0,0,,of the stream.\nDialogue: 0,0:01:34.31,0:01:36.43,EN,,0,0,0,,Those two are just like for Lisp, but the difference\nDialogue: 0,0:01:36.62,0:01:38.76,EN,,0,0,0,,is those elements aren't going to get computed\nDialogue: 0,0:01:38.86,0:01:40.99,EN,,0,0,0,,until we walk down, taking successive n-ths.\nDialogue: 0,0:01:41.52,0:01:44.78,EN,,0,0,0,,So that's one way that the stream elements might get forced.\nDialogue: 0,0:01:45.77,0:01:46.64,EN,,0,0,0,,And another way,\nDialogue: 0,0:01:47.18,0:01:48.92,EN,,0,0,0,,here's a little procedure that prints a stream.\nDialogue: 0,0:01:49.30,0:01:50.38,EN,,0,0,0,,We say print a stream,\nDialogue: 0,0:01:51.90,0:01:53.28,EN,,0,0,0,,so to print a stream s.\nDialogue: 0,0:01:54.15,0:01:55.12,EN,,0,0,0,,Well, what do we do? We'll\nDialogue: 0,0:01:55.74,0:01:56.86,EN,,0,0,0,,We print the head of the stream,\nDialogue: 0,0:01:57.74,0:01:59.32,EN,,0,0,0,,and that will cause the head to be computed.\nDialogue: 0,0:01:59.72,0:02:02.84,EN,,0,0,0,,And then we recursively print stream the tail of the stream.\nDialogue: 0,0:02:04.99,0:02:06.03,EN,,0,0,0,,And if we're already done,\nDialogue: 0,0:02:06.04,0:02:08.57,EN,,0,0,0,,maybe we have to return something about the message done.\nDialogue: 0,0:02:09.66,0:02:11.39,EN,,0,0,0,,OK, and then so if you make a stream,\nDialogue: 0,0:02:11.64,0:02:13.64,EN,,0,0,0,,you could say here's the stream, this very long stream.\nDialogue: 0,0:02:14.31,0:02:16.33,EN,,0,0,0,,And then you say print the stream,\nDialogue: 0,0:02:16.41,0:02:19.77,EN,,0,0,0,,and the elements of the stream will get computed successively\nDialogue: 0,0:02:19.87,0:02:21.12,EN,,0,0,0,,as that print calls them.\nDialogue: 0,0:02:21.32,0:02:22.81,EN,,0,0,0,,They won't get all computed initially.\nDialogue: 0,0:02:24.30,0:02:25.66,EN,,0,0,0,,So in this way, we can\nDialogue: 0,0:02:27.50,0:02:29.61,EN,,0,0,0,,So in this way, we can deal with some very long streams.\nDialogue: 0,0:02:30.19,0:02:31.92,EN,,0,0,0,,Well, how long can a stream be?\nDialogue: 0,0:02:33.74,0:02:35.12,EN,,0,0,0,,Well, it can be infinitely long.\nDialogue: 0,0:02:35.90,0:02:38.04,EN,,0,0,0,,Let's look at an example here on the computer.\nDialogue: 0,0:02:38.92,0:02:41.96,EN,,0,0,0,,I could walk up to this computer, and I could say--\nDialogue: 0,0:02:43.48,0:02:53.31,EN,,0,0,0,,how about we'll define the stream of integers starting with some number N,\nDialogue: 0,0:02:54.24,0:02:57.13,EN,,0,0,0,,the stream of positive integers starting with some number n.\nDialogue: 0,0:03:00.36,0:03:19.16,EN,,0,0,0,,And that's cons-stream of n onto the integers from one more.\nDialogue: 0,0:03:24.41,0:03:25.61,EN,,0,0,0,,So there are the integers.\nDialogue: 0,0:03:28.99,0:03:31.50,EN,,0,0,0,,Then I could say let's get all the integers.\nDialogue: 0,0:03:34.57,0:03:44.33,EN,,0,0,0,,define the stream of integers to be the integers starting with 1.\nDialogue: 0,0:03:48.84,0:03:50.94,EN,,0,0,0,,And now if I say something like\nDialogue: 0,0:03:54.41,0:03:55.80,EN,,0,0,0,,what's the what's the 20th integer.\nDialogue: 0,0:04:03.42,0:04:05.53,EN,,0,0,0,,So it's 21 because we start counting at 0.\nDialogue: 0,0:04:06.84,0:04:08.88,EN,,0,0,0,,Or I can do more complicated things.\nDialogue: 0,0:04:09.45,0:04:10.84,EN,,0,0,0,,Let me to define a little predicate here.\nDialogue: 0,0:04:11.77,0:04:18.51,EN,,0,0,0,,How about define no-seven.\nDialogue: 0,0:04:19.58,0:04:20.75,EN,,0,0,0,,It's going to test an integer,\nDialogue: 0,0:04:21.79,0:04:23.16,EN,,0,0,0,,and it's going to say it's not.\nDialogue: 0,0:04:28.82,0:04:33.96,EN,,0,0,0,,I take the remainder of x by 7,\nDialogue: 0,0:04:36.62,0:04:38.35,EN,,0,0,0,,I don't get 0.\nDialogue: 0,0:04:43.80,0:04:49.77,EN,,0,0,0,,And then I could say define the integers with no sevens\nDialogue: 0,0:04:50.22,0:04:59.12,EN,,0,0,0,,take all the integers and filter them to have no sevens.\nDialogue: 0,0:05:11.57,0:05:13.34,EN,,0,0,0,,So now I've got the stream of all the integers\nDialogue: 0,0:05:13.63,0:05:15.05,EN,,0,0,0,,that are not divisible by seven.\nDialogue: 0,0:05:16.49,0:05:23.44,EN,,0,0,0,,So if I say what's the 100th integer\nDialogue: 0,0:05:24.70,0:05:26.48,EN,,0,0,0,,and the list not divisible by seven,\nDialogue: 0,0:05:26.86,0:05:28.11,EN,,0,0,0,,I get 117.\nDialogue: 0,0:05:28.32,0:05:30.67,EN,,0,0,0,,Or if I'd like to say well, I could say ah.\nDialogue: 0,0:05:32.30,0:05:34.38,EN,,0,0,0,,well, gee, what are all of them?\nDialogue: 0,0:05:35.27,0:05:40.35,EN,,0,0,0,,So I could say print stream all these integers with no seven,\nDialogue: 0,0:05:40.83,0:05:41.79,EN,,0,0,0,,it goes off printing.\nDialogue: 0,0:05:45.10,0:05:47.07,EN,,0,0,0,,You may have to wait a very long time to see them all.\nDialogue: 0,0:05:52.67,0:05:53.84,EN,,0,0,0,,Well, you can start asking, gee,\nDialogue: 0,0:05:54.81,0:05:57.00,EN,,0,0,0,,you know, is it really true that this data structure\nDialogue: 0,0:05:58.28,0:06:00.65,EN,,0,0,0,,with the integers is really all the integers?\nDialogue: 0,0:06:01.10,0:06:04.05,EN,,0,0,0,,And let me draw a picture of that program I just wrote.\nDialogue: 0,0:06:04.96,0:06:10.57,EN,,0,0,0,,Here's the, right, here's the definition of the integers again that I just typed in,\nDialogue: 0,0:06:12.33,0:06:15.98,EN,,0,0,0,,Right it's a cons of the first integer under the integer starting with the rest.\nDialogue: 0,0:06:17.61,0:06:19.77,EN,,0,0,0,,Now, we can make a picture of that and see what it looks like.\nDialogue: 0,0:06:22.72,0:06:24.32,EN,,0,0,0,,Conceptually, what I have is a box\nDialogue: 0,0:06:25.53,0:06:27.18,EN,,0,0,0,,that's the integer starting with n.\nDialogue: 0,0:06:27.42,0:06:29.08,EN,,0,0,0,,It takes in some number n,\nDialogue: 0,0:06:31.42,0:06:32.97,EN,,0,0,0,,and it's going to return a stream of--\nDialogue: 0,0:06:35.02,0:06:37.36,EN,,0,0,0,,this infinite stream of all integers starting with n.\nDialogue: 0,0:06:38.08,0:06:38.73,EN,,0,0,0,,And what do I do?\nDialogue: 0,0:06:38.75,0:06:42.38,EN,,0,0,0,,Well, this is an integers-from box.\nDialogue: 0,0:06:45.07,0:06:45.80,EN,,0,0,0,,What's it got in it?\nDialogue: 0,0:06:45.80,0:06:48.60,EN,,0,0,0,,Well, it takes in this n,\nDialogue: 0,0:06:52.27,0:06:53.92,EN,,0,0,0,,and it increments it.\nDialogue: 0,0:06:57.95,0:07:03.15,EN,,0,0,0,,And then it puts the result into recursively another integer's from box.\nDialogue: 0,0:07:06.87,0:07:09.60,EN,,0,0,0,,It takes the result of that and the original n\nDialogue: 0,0:07:10.24,0:07:12.78,EN,,0,0,0,,and puts those together with a cons\nDialogue: 0,0:07:13.39,0:07:14.36,EN,,0,0,0,,and forms a stream.\nDialogue: 0,0:07:14.57,0:07:17.26,EN,,0,0,0,,So that's a picture of that program I wrote. And this is a ...\nDialogue: 0,0:07:18.52,0:07:20.32,EN,,0,0,0,,Let's see. These kind of diagrams we first saw\nDialogue: 0,0:07:20.78,0:07:21.74,EN,,0,0,0,,drawn by Peter Henderson,\nDialogue: 0,0:07:21.76,0:07:23.32,EN,,0,0,0,,the same guy who did the Escher language.\nDialogue: 0,0:07:23.32,0:07:24.75,EN,,0,0,0,,We call them Henderson diagrams.\nDialogue: 0,0:07:25.37,0:07:27.90,EN,,0,0,0,,And the convention here is that you put these things together.\nDialogue: 0,0:07:28.53,0:07:32.51,EN,,0,0,0,,And the solid lines are things coming out are streams,\nDialogue: 0,0:07:33.02,0:07:36.20,EN,,0,0,0,,and dotted lines are initial values going in.\nDialogue: 0,0:07:37.27,0:07:39.02,EN,,0,0,0,,So this one has the shape of--\nDialogue: 0,0:07:39.40,0:07:41.60,EN,,0,0,0,,it takes in some integer, some initial value,\nDialogue: 0,0:07:41.80,0:07:42.91,EN,,0,0,0,,and outputs a stream.\nDialogue: 0,0:07:46.35,0:07:48.22,EN,,0,0,0,,Again, you can ask. You know it's really\nDialogue: 0,0:07:48.38,0:07:50.88,EN,,0,0,0,,Is that data structure integers really all the integers?\nDialogue: 0,0:07:52.09,0:07:54.91,EN,,0,0,0,,Alright? Or is it is something that's cleverly arranged\nDialogue: 0,0:07:54.94,0:07:56.43,EN,,0,0,0,,so that whenever you look for an integer\nDialogue: 0,0:07:56.44,0:07:57.24,EN,,0,0,0,,you find it there?\nDialogue: 0,0:07:57.95,0:07:59.74,EN,,0,0,0,,That's sort of a philosophical question, right?\nDialogue: 0,0:07:59.78,0:08:01.69,EN,,0,0,0,,If something is there\nDialogue: 0,0:08:02.14,0:08:03.96,EN,,0,0,0,,whenever you look, is it really there or not?\nDialogue: 0,0:08:04.45,0:08:07.34,EN,,0,0,0,,It's sort of the same sense in which\nDialogue: 0,0:08:07.36,0:08:09.42,EN,,0,0,0,,the money in your savings account is in the bank.\nDialogue: 0,0:08:12.38,0:08:12.64,EN,,0,0,0,,Well\nDialogue: 0,0:08:16.35,0:08:17.48,EN,,0,0,0,,let me do another example.\nDialogue: 0,0:08:18.68,0:08:20.70,EN,,0,0,0,,Umm, Gee, we started the course\nDialogue: 0,0:08:20.72,0:08:22.72,EN,,0,0,0,,with an algorithm from Alexandria,\nDialogue: 0,0:08:23.29,0:08:25.80,EN,,0,0,0,,which was Heron of Alexandria's algorithm\nDialogue: 0,0:08:25.82,0:08:26.94,EN,,0,0,0,,for computing the square root.\nDialogue: 0,0:08:28.47,0:08:32.03,EN,,0,0,0,,Let's take a look at another Alexandrian algorithm.\nDialogue: 0,0:08:32.03,0:08:35.08,EN,,0,0,0,,This one is Eratosthenes method for\nDialogue: 0,0:08:36.19,0:08:38.44,EN,,0,0,0,,for computing all of the primes.\nDialogue: 0,0:08:41.16,0:08:42.83,EN,,0,0,0,,It is called the Sieve of Eratosthenes.\nDialogue: 0,0:08:42.83,0:08:49.72,EN,,0,0,0,,And what you do is you start out,\nDialogue: 0,0:08:50.99,0:08:52.28,EN,,0,0,0,,and you list all the integers,\nDialogue: 0,0:08:52.60,0:08:53.53,EN,,0,0,0,,say, starting with 2.\nDialogue: 0,0:08:53.88,0:08:55.04,EN,,0,0,0,,And then you take the first integer, and you say,\nDialogue: 0,0:08:55.08,0:08:56.67,EN,,0,0,0,,and you say, oh, that's prime.\nDialogue: 0,0:08:57.31,0:08:58.35,EN,,0,0,0,,And then you go look at the rest,\nDialogue: 0,0:08:58.68,0:09:00.88,EN,,0,0,0,,and you cross out all the things divisible by 2.\nDialogue: 0,0:09:01.52,0:09:04.73,EN,,0,0,0,,So I cross out this and this and this.\nDialogue: 0,0:09:05.25,0:09:06.35,EN,,0,0,0,,This takes a long time\nDialogue: 0,0:09:06.36,0:09:08.91,EN,,0,0,0,,because I have to do it for all of the integers.\nDialogue: 0,0:09:11.16,0:09:15.39,EN,,0,0,0,,So I go through the entire list of integers,\nDialogue: 0,0:09:18.27,0:09:20.94,EN,,0,0,0,,crossing the ones divisible by 2.\nDialogue: 0,0:09:22.11,0:09:24.38,EN,,0,0,0,,And now when I finish with all of the integers,\nDialogue: 0,0:09:24.78,0:09:26.72,EN,,0,0,0,,I go back and look and say what am I left with?\nDialogue: 0,0:09:27.04,0:09:28.80,EN,,0,0,0,,Well, the first thing that starts there is 3.\nDialogue: 0,0:09:29.33,0:09:30.33,EN,,0,0,0,,So 3 is a prime.\nDialogue: 0,0:09:30.77,0:09:33.05,EN,,0,0,0,,And now I go back through what I'm left with,\nDialogue: 0,0:09:33.36,0:09:35.07,EN,,0,0,0,,and I cross out all the things divisible by 3.\nDialogue: 0,0:09:35.08,0:09:43.80,EN,,0,0,0,,So let's see, 9 and 15 and 21 and 27 and 33 and so on.\nDialogue: 0,0:09:44.33,0:09:45.12,EN,,0,0,0,,I won't finish.\nDialogue: 0,0:09:45.35,0:09:46.52,EN,,0,0,0,,Then I see what I'm left with.\nDialogue: 0,0:09:47.25,0:09:49.84,EN,,0,0,0,,And the next one I have is 5.\nDialogue: 0,0:09:50.49,0:09:52.04,EN,,0,0,0,,Now I can through the rest,\nDialogue: 0,0:09:52.43,0:09:54.51,EN,,0,0,0,,and I find the first one that's divisible by 5.\nDialogue: 0,0:09:54.54,0:09:57.61,EN,,0,0,0,,I cross out from the remainder all the ones that are divisible by 5.\nDialogue: 0,0:09:58.35,0:09:59.24,EN,,0,0,0,,And I did that,\nDialogue: 0,0:09:59.82,0:10:01.89,EN,,0,0,0,,and then I go through and find 7.\nDialogue: 0,0:10:01.89,0:10:02.72,EN,,0,0,0,,Go through all the rest,\nDialogue: 0,0:10:02.76,0:10:03.95,EN,,0,0,0,,cross out things divisible 7,\nDialogue: 0,0:10:03.98,0:10:05.47,EN,,0,0,0,,and I keep doing that forever.\nDialogue: 0,0:10:06.81,0:10:07.40,EN,,0,0,0,,And when I'm done,\nDialogue: 0,0:10:07.40,0:10:09.10,EN,,0,0,0,,what I'm left with is a list of all the primes.\nDialogue: 0,0:10:09.90,0:10:13.31,EN,,0,0,0,,So that's the Sieve of Eratosthenes.\nDialogue: 0,0:10:15.43,0:10:17.69,EN,,0,0,0,,Let's look at it as a computer program.\nDialogue: 0,0:10:17.93,0:10:19.85,EN,,0,0,0,,It's a procedure called sieve.\nDialogue: 0,0:10:27.91,0:10:29.40,EN,,0,0,0,,Now, I just write what I did.\nDialogue: 0,0:10:30.33,0:10:34.48,EN,,0,0,0,,I'll say to sieve some stream s.\nDialogue: 0,0:10:38.77,0:10:39.93,EN,,0,0,0,,I'm going to build a stream\nDialogue: 0,0:10:40.27,0:10:41.84,EN,,0,0,0,,whose first element is the head of this.\nDialogue: 0,0:10:41.87,0:10:44.43,EN,,0,0,0,,Remember, I always found the first thing I was left with,\nDialogue: 0,0:10:44.91,0:10:48.75,EN,,0,0,0,,and the rest of it is the result of taking the tail of S,\nDialogue: 0,0:10:51.08,0:10:53.72,EN,,0,0,0,,filtering it to throw away all the things\nDialogue: 0,0:10:53.74,0:10:55.32,EN,,0,0,0,,that are divisible by the head of S,\nDialogue: 0,0:10:56.41,0:10:57.56,EN,,0,0,0,,and now sieving the result.\nDialogue: 0,0:10:59.02,0:11:00.09,EN,,0,0,0,,That's just what I did.\nDialogue: 0,0:11:01.98,0:11:04.68,EN,,0,0,0,,And now to get the infinite stream of times,\nDialogue: 0,0:11:05.02,0:11:06.90,EN,,0,0,0,,we just sieve all the integers starting from 2.\nDialogue: 0,0:11:14.92,0:11:15.56,EN,,0,0,0,,Let's try that.\nDialogue: 0,0:11:16.30,0:11:18.30,EN,,0,0,0,,We can actually do it.\nDialogue: 0,0:11:19.76,0:11:22.12,EN,,0,0,0,,I typed in the definition of sieve before, I hope,\nDialogue: 0,0:11:22.86,0:11:24.06,EN,,0,0,0,,so I can say something like\nDialogue: 0,0:11:24.92,0:11:33.45,EN,,0,0,0,,define the primes to be\nDialogue: 0,0:11:34.64,0:11:41.45,EN,,0,0,0,,the result of sieving the integers starting with 2.\nDialogue: 0,0:11:46.76,0:11:48.10,EN,,0,0,0,,So now I've got this list of primes.\nDialogue: 0,0:11:48.10,0:11:50.99,EN,,0,0,0,,That's all of the primes, right?\nDialogue: 0,0:11:50.99,0:11:53.52,EN,,0,0,0,,So, if for example, what's the 20th prime in that list?\nDialogue: 0,0:12:00.73,0:12:01.68,EN,,0,0,0,,73.\nDialogue: 0,0:12:02.54,0:12:03.34,EN,,0,0,0,,See, and that little pause,\nDialogue: 0,0:12:03.36,0:12:04.92,EN,,0,0,0,,it was only at the point\nDialogue: 0,0:12:04.94,0:12:06.43,EN,,0,0,0,,when I started asking for the 20th prime\nDialogue: 0,0:12:06.46,0:12:07.68,EN,,0,0,0,,is that it started computing.\nDialogue: 0,0:12:10.37,0:12:11.29,EN,,0,0,0,,Or I can say here\nDialogue: 0,0:12:13.80,0:12:14.88,EN,,0,0,0,,Or I can say here let's look at all of the primes.\nDialogue: 0,0:12:22.64,0:12:24.40,EN,,0,0,0,,And there it goes computing all of the primes.\nDialogue: 0,0:12:25.35,0:12:26.28,EN,,0,0,0,,Of course, it will take a while\nDialogue: 0,0:12:26.28,0:12:27.61,EN,,0,0,0,,again if I want to look at all of them,\nDialogue: 0,0:12:27.79,0:12:28.57,EN,,0,0,0,,so let's stop it.\nDialogue: 0,0:12:32.03,0:12:33.13,EN,,0,0,0,,Let me draw you a picture of that.\nDialogue: 0,0:12:33.13,0:12:34.17,EN,,0,0,0,,Well, I've got a picture of that.\nDialogue: 0,0:12:34.89,0:12:36.19,EN,,0,0,0,,What's that program really look like?\nDialogue: 0,0:12:37.90,0:12:39.77,EN,,0,0,0,,Again, some practice with these diagrams,\nDialogue: 0,0:12:39.82,0:12:40.54,EN,,0,0,0,,I have a sieve box.\nDialogue: 0,0:12:42.61,0:12:43.56,EN,,0,0,0,,How does sieve work?\nDialogue: 0,0:12:43.56,0:12:44.81,EN,,0,0,0,,It takes in a stream.\nDialogue: 0,0:12:48.85,0:12:50.59,EN,,0,0,0,,It splits off the head from the tail.\nDialogue: 0,0:12:50.87,0:12:53.26,EN,,0,0,0,,And the first thing that's going to come out of the sieve\nDialogue: 0,0:12:53.48,0:12:54.97,EN,,0,0,0,,is the head of the original stream.\nDialogue: 0,0:12:58.20,0:13:00.92,EN,,0,0,0,,Then it also takes the head and uses that.\nDialogue: 0,0:13:02.55,0:13:05.10,EN,,0,0,0,,It takes the stream. It filters the tail\nDialogue: 0,0:13:05.55,0:13:08.33,EN,,0,0,0,,It filters the tail and uses the head to filter for nondivisibility.\nDialogue: 0,0:13:09.53,0:13:11.18,EN,,0,0,0,,It takes the result of nondivisibility\nDialogue: 0,0:13:11.24,0:13:13.12,EN,,0,0,0,,and puts it through another sieve box\nDialogue: 0,0:13:13.90,0:13:15.13,EN,,0,0,0,,and puts the result together.\nDialogue: 0,0:13:15.13,0:13:16.89,EN,,0,0,0,,So you can think of this sieve a filter,\nDialogue: 0,0:13:17.20,0:13:19.23,EN,,0,0,0,,but notice that it's an infinitely recursive filter.\nDialogue: 0,0:13:19.65,0:13:20.88,EN,,0,0,0,,Because inside the sieve box\nDialogue: 0,0:13:21.52,0:13:22.60,EN,,0,0,0,,is another sieve box,\nDialogue: 0,0:13:23.37,0:13:25.85,EN,,0,0,0,,and inside that is another sieve box and another sieve box.\nDialogue: 0,0:13:27.13,0:13:28.96,EN,,0,0,0,,So you see we start getting some very powerful things.\nDialogue: 0,0:13:28.96,0:13:32.84,EN,,0,0,0,,We're starting to mix this signal processing view of the world\nDialogue: 0,0:13:33.90,0:13:36.41,EN,,0,0,0,,with things like recursion that come from computation.\nDialogue: 0,0:13:37.42,0:13:39.82,EN,,0,0,0,,And there are all sorts of interesting things you can do that are like this.\nDialogue: 0,0:13:40.97,0:13:42.09,EN,,0,0,0,,All right, any questions?\nDialogue: 0,0:13:48.19,0:13:49.16,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:14:28.65,0:14:30.36,EN,,0,0,0,,Well, we've been looking at a couple\nDialogue: 0,0:14:30.36,0:14:32.09,EN,,0,0,0,,of examples of stream programming.\nDialogue: 0,0:14:34.79,0:14:39.21,EN,,0,0,0,,All the stream procedures that we've looked at so far\nDialogue: 0,0:14:39.72,0:14:41.32,EN,,0,0,0,,have the same kind of character.\nDialogue: 0,0:14:41.49,0:14:43.63,EN,,0,0,0,,We've been writing these recursive procedures\nDialogue: 0,0:14:44.16,0:14:46.49,EN,,0,0,0,,that kind of generate these stream elements one at a time\nDialogue: 0,0:14:46.51,0:14:48.72,EN,,0,0,0,,and put them together in cons-streams.\nDialogue: 0,0:14:49.15,0:14:50.86,EN,,0,0,0,,So we've been thinking a lot about generators.\nDialogue: 0,0:14:50.92,0:14:53.63,EN,,0,0,0,,There's another way to think about stream processing,\nDialogue: 0,0:14:53.79,0:14:56.96,EN,,0,0,0,,and that's to focus not on programs that sort of\nDialogue: 0,0:14:57.36,0:14:59.93,EN,,0,0,0,,process these elements as you walk down the stream,\nDialogue: 0,0:15:00.25,0:15:05.68,EN,,0,0,0,,but on things that kind of process the streams all at once.\nDialogue: 0,0:15:07.18,0:15:09.16,EN,,0,0,0,,To show you what I mean, let me start by defining\nDialogue: 0,0:15:09.23,0:15:11.50,EN,,0,0,0,,two procedures that will come in handy.\nDialogue: 0,0:15:12.41,0:15:13.60,EN,,0,0,0,,The first one's called add streams.\nDialogue: 0,0:15:15.36,0:15:18.25,EN,,0,0,0,,Add streams takes two streams:\nDialogue: 0,0:15:18.81,0:15:20.88,EN,,0,0,0,,s1 and s2.\nDialogue: 0,0:15:22.30,0:15:24.67,EN,,0,0,0,,And it's going to produce a stream\nDialogue: 0,0:15:24.99,0:15:28.17,EN,,0,0,0,,whose elements are the are the corresponding sums\nDialogue: 0,0:15:30.22,0:15:31.88,EN,,0,0,0,,We just sort of add them element-wise.\nDialogue: 0,0:15:32.97,0:15:33.95,EN,,0,0,0,,If either stream is empty,\nDialogue: 0,0:15:33.96,0:15:35.39,EN,,0,0,0,,we just return the other one.\nDialogue: 0,0:15:36.81,0:15:38.96,EN,,0,0,0,,Otherwise, we're going to make a new stream\nDialogue: 0,0:15:39.90,0:15:42.96,EN,,0,0,0,,whose head is the sum of the two heads\nDialogue: 0,0:15:44.00,0:15:44.88,EN,,0,0,0,,whose tail\nDialogue: 0,0:15:46.00,0:15:48.62,EN,,0,0,0,,is the result of recursively adding the tails.\nDialogue: 0,0:15:50.09,0:15:52.73,EN,,0,0,0,,So that will produce the element-wise sum of two streams.\nDialogue: 0,0:15:53.15,0:15:57.04,EN,,0,0,0,,And then another useful thing to have around is scale stream.\nDialogue: 0,0:15:57.50,0:16:01.66,EN,,0,0,0,,Scale stream takes some constant number in a stream s\nDialogue: 0,0:16:04.11,0:16:06.62,EN,,0,0,0,,and is going to produce the stream\nDialogue: 0,0:16:07.18,0:16:09.50,EN,,0,0,0,,of elements of s multiplied by this constant.\nDialogue: 0,0:16:09.71,0:16:11.21,EN,,0,0,0,,And that's easy, that's just a map\nDialogue: 0,0:16:12.20,0:16:16.22,EN,,0,0,0,,of the function of an element that multiplies it by the constant,\nDialogue: 0,0:16:16.35,0:16:17.80,EN,,0,0,0,,and we map that down the stream.\nDialogue: 0,0:16:20.06,0:16:21.47,EN,,0,0,0,,So given those two,\nDialogue: 0,0:16:22.64,0:16:24.36,EN,,0,0,0,,let me show you what I mean by programs that\nDialogue: 0,0:16:24.70,0:16:27.00,EN,,0,0,0,,that operate on streams all at once.\nDialogue: 0,0:16:28.12,0:16:28.73,EN,,0,0,0,,Let's look at this.\nDialogue: 0,0:16:30.20,0:16:30.92,EN,,0,0,0,,Suppose I write this.\nDialogue: 0,0:16:31.68,0:16:52.35,EN,,0,0,0,,I say define--  I'll call it ones-- to be cons-stream of 1 onto ones.\nDialogue: 0,0:16:54.86,0:16:55.52,EN,,0,0,0,,What's that?\nDialogue: 0,0:16:56.95,0:16:58.94,EN,,0,0,0,,That's going to be an infinite stream of ones\nDialogue: 0,0:16:59.96,0:17:01.44,EN,,0,0,0,,because the first thing is 1.\nDialogue: 0,0:17:03.33,0:17:05.15,EN,,0,0,0,,And the tail of it is a thing\nDialogue: 0,0:17:05.55,0:17:06.83,EN,,0,0,0,,whose first thing is 1\nDialogue: 0,0:17:07.63,0:17:09.02,EN,,0,0,0,,whose tail is a thing\nDialogue: 0,0:17:09.12,0:17:10.24,EN,,0,0,0,,whose first thing is 1\nDialogue: 0,0:17:10.52,0:17:11.78,EN,,0,0,0,,and so on and so on.\nDialogue: 0,0:17:11.78,0:17:13.32,EN,,0,0,0,,So that's an infinite stream of ones.\nDialogue: 0,0:17:15.13,0:17:15.93,EN,,0,0,0,,And now using that,\nDialogue: 0,0:17:16.12,0:17:18.03,EN,,0,0,0,,let me give you another definition of the integers.\nDialogue: 0,0:17:19.47,0:17:27.36,EN,,0,0,0,,We can define the integers to be--\nDialogue: 0,0:17:28.24,0:17:30.76,EN,,0,0,0,,well, the first integer we'll take to be 1,\nDialogue: 0,0:17:32.75,0:17:38.57,EN,,0,0,0,,his cons-stream of 1 onto the element-wise sum\nDialogue: 0,0:17:40.22,0:17:48.27,EN,,0,0,0,,onto add streams of the integers to ones.\nDialogue: 0,0:17:55.10,0:17:56.35,EN,,0,0,0,,The integers are a thing\nDialogue: 0,0:17:57.24,0:17:59.98,EN,,0,0,0,,whose first element is 1,\nDialogue: 0,0:18:00.88,0:18:02.32,EN,,0,0,0,,and the rest of them you get\nDialogue: 0,0:18:03.12,0:18:06.14,EN,,0,0,0,,by taking those integers and incrementing each one by one.\nDialogue: 0,0:18:06.64,0:18:08.19,EN,,0,0,0,,So the second element of the integers\nDialogue: 0,0:18:08.51,0:18:11.96,EN,,0,0,0,,is the first element of the integers incremented by one.\nDialogue: 0,0:18:13.92,0:18:15.18,EN,,0,0,0,,And the rest of that is the next one,\nDialogue: 0,0:18:15.20,0:18:16.48,EN,,0,0,0,,and the third element of that\nDialogue: 0,0:18:16.62,0:18:20.41,EN,,0,0,0,,is the same as the first element of the tail of the integers\nDialogue: 0,0:18:20.84,0:18:21.96,EN,,0,0,0,,incremented by one,\nDialogue: 0,0:18:22.51,0:18:23.76,EN,,0,0,0,,which is the same as the\nDialogue: 0,0:18:25.08,0:18:28.65,EN,,0,0,0,,first element of the original integers incremented by one\nDialogue: 0,0:18:28.86,0:18:31.25,EN,,0,0,0,,and incremented by one again and so on.\nDialogue: 0,0:18:35.24,0:18:36.31,EN,,0,0,0,,That looks pretty suspicious.\nDialogue: 0,0:18:36.31,0:18:37.47,EN,,0,0,0,,See, notice that it works\nDialogue: 0,0:18:38.12,0:18:38.99,EN,,0,0,0,,because of delay.\nDialogue: 0,0:18:40.15,0:18:43.32,EN,,0,0,0,,See, this looks like-- let's take a look at ones.\nDialogue: 0,0:18:43.87,0:18:45.92,EN,,0,0,0,,This looks like it couldn't even be processed\nDialogue: 0,0:18:46.25,0:18:47.63,EN,,0,0,0,,because it's suddenly saying\nDialogue: 0,0:18:47.79,0:18:48.96,EN,,0,0,0,,in order to know what ones is,\nDialogue: 0,0:18:49.00,0:18:50.91,EN,,0,0,0,,I say it's cons-stream of something onto ones.\nDialogue: 0,0:18:51.13,0:18:52.08,EN,,0,0,0,,The reason that works\nDialogue: 0,0:18:52.09,0:18:54.04,EN,,0,0,0,,because of that very sneaky hidden delay in there.\nDialogue: 0,0:18:55.25,0:18:56.56,EN,,0,0,0,,Because what this really is,\nDialogue: 0,0:18:57.79,0:18:59.69,EN,,0,0,0,,remember, cons-stream is just an abbreviation.\nDialogue: 0,0:19:00.29,0:19:01.15,EN,,0,0,0,,This really is\nDialogue: 0,0:19:01.85,0:19:08.99,EN,,0,0,0,,cons of 1 onto delay of ones.\nDialogue: 0,0:19:12.14,0:19:13.21,EN,,0,0,0,,So how does that work?\nDialogue: 0,0:19:15.50,0:19:16.88,EN,,0,0,0,,You say I'm going to define ones.\nDialogue: 0,0:19:18.02,0:19:20.24,EN,,0,0,0,,First I see what ones is supposed to be defined as.\nDialogue: 0,0:19:20.70,0:19:23.40,EN,,0,0,0,,Well, ones is supposed to be defined as\nDialogue: 0,0:19:24.89,0:19:28.11,EN,,0,0,0,,a cons whose first part is 1\nDialogue: 0,0:19:28.32,0:19:29.45,EN,,0,0,0,,and the second part is,\nDialogue: 0,0:19:29.45,0:19:30.73,EN,,0,0,0,,well, it's a promise to compute something\nDialogue: 0,0:19:30.75,0:19:31.69,EN,,0,0,0,,that I don't worry about yet.\nDialogue: 0,0:19:32.71,0:19:34.25,EN,,0,0,0,,So it doesn't bother me that at the point\nDialogue: 0,0:19:34.28,0:19:36.30,EN,,0,0,0,,I do this definition, ones isn't defined.\nDialogue: 0,0:19:37.27,0:19:39.45,EN,,0,0,0,,Having run the definition, now ones is defined.\nDialogue: 0,0:19:40.67,0:19:42.83,EN,,0,0,0,,So that when I go and look at the tail of it, it's defined.\nDialogue: 0,0:19:44.92,0:19:46.06,EN,,0,0,0,,It's very sneaky.\nDialogue: 0,0:19:46.59,0:19:47.90,EN,,0,0,0,,And an integer is the same way.\nDialogue: 0,0:19:48.47,0:19:50.46,EN,,0,0,0,,I can refer to integers here because\nDialogue: 0,0:19:51.13,0:19:53.21,EN,,0,0,0,,hidden way down-- because of this cons-stream.\nDialogue: 0,0:19:53.85,0:19:55.24,EN,,0,0,0,,It's the cons-stream of 1\nDialogue: 0,0:19:55.37,0:19:57.05,EN,,0,0,0,,onto something that I don't worry that yet.\nDialogue: 0,0:19:57.05,0:19:59.60,EN,,0,0,0,,So I don't look at it, and I don't notice that integers isn't defined\nDialogue: 0,0:20:00.22,0:20:01.90,EN,,0,0,0,,at the point where I try and run the definition.\nDialogue: 0,0:20:06.32,0:20:08.27,EN,,0,0,0,,OK, let me draw a picture of that integers thing\nDialogue: 0,0:20:08.44,0:20:11.50,EN,,0,0,0,,because it still maybe seems a little bit shaky.\nDialogue: 0,0:20:12.43,0:20:14.72,EN,,0,0,0,,What do I do? Uh...\nDialogue: 0,0:20:15.02,0:20:16.30,EN,,0,0,0,,I've got the stream of ones,\nDialogue: 0,0:20:20.51,0:20:21.88,EN,,0,0,0,,and that sort of comes in\nDialogue: 0,0:20:23.26,0:20:24.92,EN,,0,0,0,,comes in and goes into an adder\nDialogue: 0,0:20:24.96,0:20:26.59,EN,,0,0,0,,that's going to be this add streams thing.\nDialogue: 0,0:20:29.31,0:20:35.87,EN,,0,0,0,,And that goes in-- that's going to put out the integers.\nDialogue: 0,0:20:40.76,0:20:42.70,EN,,0,0,0,,And the other thing that goes into the adder here\nDialogue: 0,0:20:44.94,0:20:46.97,EN,,0,0,0,,is the integer, so there's a little feedback loop.\nDialogue: 0,0:20:48.06,0:20:49.42,EN,,0,0,0,,And all I need to start it off\nDialogue: 0,0:20:50.09,0:20:52.88,EN,,0,0,0,,is someplace I've got a stick that initial 1.\nDialogue: 0,0:20:57.10,0:20:58.64,EN,,0,0,0,,In a real signal processing thing,\nDialogue: 0,0:20:58.72,0:21:02.48,EN,,0,0,0,,this might be a delay element with that was initialized to 1.\nDialogue: 0,0:21:02.91,0:21:05.90,EN,,0,0,0,,But there's a picture of that ones program.\nDialogue: 0,0:21:07.86,0:21:09.63,EN,,0,0,0,,And in fact, that looks a lot like--\nDialogue: 0,0:21:09.80,0:21:13.77,EN,,0,0,0,,if you've seen real signal block diagram things,\nDialogue: 0,0:21:13.77,0:21:16.30,EN,,0,0,0,,that looks a lot like accumulators,\nDialogue: 0,0:21:16.35,0:21:17.48,EN,,0,0,0,,finite state accumulators.\nDialogue: 0,0:21:17.98,0:21:20.06,EN,,0,0,0,,And in fact, we can modify this a little bit\nDialogue: 0,0:21:21.18,0:21:23.96,EN,,0,0,0,,to change this into something that integrates a stream\nDialogue: 0,0:21:25.37,0:21:26.97,EN,,0,0,0,,or a finite state accumulator,\nDialogue: 0,0:21:27.00,0:21:28.04,EN,,0,0,0,,however you like to think about it.\nDialogue: 0,0:21:28.44,0:21:30.86,EN,,0,0,0,,So instead of the ones coming in and getting out the integers,\nDialogue: 0,0:21:31.68,0:21:32.38,EN,,0,0,0,,what we'll do is\nDialogue: 0,0:21:32.91,0:21:34.83,EN,,0,0,0,,say there's a stream s coming in,\nDialogue: 0,0:21:35.76,0:21:40.56,EN,,0,0,0,,and we're going to get out the integral of this.\nDialogue: 0,0:21:42.60,0:21:44.09,EN,,0,0,0,,successive values of that,\nDialogue: 0,0:21:44.44,0:21:45.63,EN,,0,0,0,,and it looks almost the same.\nDialogue: 0,0:21:45.66,0:21:46.84,EN,,0,0,0,,The only thing we're going to do is\nDialogue: 0,0:21:47.02,0:21:48.08,EN,,0,0,0,,when s comes in here,\nDialogue: 0,0:21:49.21,0:21:50.64,EN,,0,0,0,,before we just add it in\nDialogue: 0,0:21:50.91,0:21:54.26,EN,,0,0,0,,we're going to multiply it by some number dt.\nDialogue: 0,0:21:57.68,0:22:00.00,EN,,0,0,0,,And now what we have here, this is exactly the same thing.\nDialogue: 0,0:22:00.00,0:22:00.91,EN,,0,0,0,,We have a box,\nDialogue: 0,0:22:03.36,0:22:04.56,EN,,0,0,0,,which is an integrator.\nDialogue: 0,0:22:09.79,0:22:11.26,EN,,0,0,0,,And it takes in a stream s,\nDialogue: 0,0:22:11.90,0:22:14.51,EN,,0,0,0,,and instead of 1 here,\nDialogue: 0,0:22:14.94,0:22:18.35,EN,,0,0,0,,we can put the additional value for the integral.\nDialogue: 0,0:22:19.98,0:22:21.60,EN,,0,0,0,,And that one looks very much like a\nDialogue: 0,0:22:22.35,0:22:24.86,EN,,0,0,0,,a signal processing block diagram program.\nDialogue: 0,0:22:25.27,0:22:28.11,EN,,0,0,0,,In fact, here's the procedure that looks exactly like that.\nDialogue: 0,0:22:31.49,0:22:33.61,EN,,0,0,0,,Find the integral of a stream.\nDialogue: 0,0:22:34.01,0:22:35.48,EN,,0,0,0,,So an integral's going to take a stream\nDialogue: 0,0:22:35.68,0:22:36.86,EN,,0,0,0,,Sand produce a new stream,\nDialogue: 0,0:22:37.53,0:22:40.67,EN,,0,0,0,,and it takes in an initial value and some time constant.\nDialogue: 0,0:22:42.23,0:22:42.97,EN,,0,0,0,,And what do we do?\nDialogue: 0,0:22:43.04,0:22:45.05,EN,,0,0,0,,Well, we internally define this thing int,\nDialogue: 0,0:22:45.20,0:22:46.32,EN,,0,0,0,,and we make this internal name\nDialogue: 0,0:22:46.33,0:22:48.86,EN,,0,0,0,,so we can feed it back, loop it around itself.\nDialogue: 0,0:22:49.40,0:22:50.80,EN,,0,0,0,,And int is defined to be\nDialogue: 0,0:22:51.10,0:22:53.32,EN,,0,0,0,,something that starts out at the initial value,\nDialogue: 0,0:22:54.97,0:23:00.14,EN,,0,0,0,,and the rest of it is gotten by adding together.\nDialogue: 0,0:23:01.28,0:23:03.61,EN,,0,0,0,,We take our input stream, scale it by dt,\nDialogue: 0,0:23:03.87,0:23:04.92,EN,,0,0,0,,and add that to int.\nDialogue: 0,0:23:06.88,0:23:09.66,EN,,0,0,0,,And now we'll return from all that the value of integral is this thing int.\nDialogue: 0,0:23:10.69,0:23:12.94,EN,,0,0,0,,And we use this internal definition syntax so we could\nDialogue: 0,0:23:13.34,0:23:15.66,EN,,0,0,0,,write a little internal definition that refers to itself.\nDialogue: 0,0:23:21.88,0:23:23.71,EN,,0,0,0,,Well, there are all sorts of things we can do.\nDialogue: 0,0:23:23.71,0:23:24.51,EN,,0,0,0,,Let's try this one.\nDialogue: 0,0:23:25.63,0:23:26.89,EN,,0,0,0,,how about the Fibonacci numbers.\nDialogue: 0,0:23:26.89,0:23:32.62,EN,,0,0,0,,You can say define fibs.\nDialogue: 0,0:23:36.35,0:23:37.63,EN,,0,0,0,,Well, what are the Fibonacci numbers?\nDialogue: 0,0:23:37.98,0:23:46.54,EN,,0,0,0,,They're something that starts out with 0,\nDialogue: 0,0:23:48.65,0:23:50.09,EN,,0,0,0,,and the next one is 1.\nDialogue: 0,0:23:56.26,0:23:59.16,EN,,0,0,0,,And the rest of the Fibonacci numbers are gotten by\nDialogue: 0,0:23:59.87,0:24:11.00,EN,,0,0,0,,adding the Fibonacci numbers to their own tail.\nDialogue: 0,0:24:17.57,0:24:19.28,EN,,0,0,0,,There's a definition of the Fibonacci numbers.\nDialogue: 0,0:24:20.58,0:24:21.43,EN,,0,0,0,,How does that work?\nDialogue: 0,0:24:21.43,0:24:24.19,EN,,0,0,0,,Well, we start off,\nDialogue: 0,0:24:24.20,0:24:26.49,EN,,0,0,0,,and someone says compute for us the Fibonacci numbers,\nDialogue: 0,0:24:29.64,0:24:31.92,EN,,0,0,0,,and we're going to tell you it starts out with 0 and 1.\nDialogue: 0,0:24:35.79,0:24:38.22,EN,,0,0,0,,And everything after the 0 and 1\nDialogue: 0,0:24:39.18,0:24:40.86,EN,,0,0,0,,is gotten by summing two streams.\nDialogue: 0,0:24:41.12,0:24:42.59,EN,,0,0,0,,One is the fibs themselves,\nDialogue: 0,0:24:44.06,0:24:45.69,EN,,0,0,0,,and the other one is the tail of the fibs.\nDialogue: 0,0:24:49.12,0:24:51.16,EN,,0,0,0,,So if I know that these start out with 0 and 1,\nDialogue: 0,0:24:51.79,0:24:55.42,EN,,0,0,0,,I know that the fibs now start out with 0 and 1,\nDialogue: 0,0:24:55.74,0:24:57.40,EN,,0,0,0,,and the tail of the fibs start out with 1.\nDialogue: 0,0:24:58.36,0:24:59.45,EN,,0,0,0,,So as soon as I know that,\nDialogue: 0,0:24:59.66,0:25:02.11,EN,,0,0,0,,I know that the next one here is 0 plus 1 is 1,\nDialogue: 0,0:25:02.96,0:25:04.60,EN,,0,0,0,,and that tells me that the next one here is 1\nDialogue: 0,0:25:04.62,0:25:05.72,EN,,0,0,0,,and the next one here is 1.\nDialogue: 0,0:25:06.30,0:25:07.28,EN,,0,0,0,,And as soon as I know that,\nDialogue: 0,0:25:07.29,0:25:08.76,EN,,0,0,0,,I know that the next one is 2.\nDialogue: 0,0:25:09.39,0:25:11.70,EN,,0,0,0,,So the next one here is 2 and the next one here is 2.\nDialogue: 0,0:25:11.70,0:25:12.56,EN,,0,0,0,,And this is 3.\nDialogue: 0,0:25:14.72,0:25:15.79,EN,,0,0,0,,This one goes to 3,\nDialogue: 0,0:25:16.19,0:25:17.13,EN,,0,0,0,,and this is 5.\nDialogue: 0,0:25:18.67,0:25:19.96,EN,,0,0,0,,So it's a perfectly sensible definition.\nDialogue: 0,0:25:21.50,0:25:22.78,EN,,0,0,0,,It's a one-line definition.\nDialogue: 0,0:25:22.83,0:25:25.00,EN,,0,0,0,,And again, I could walk over to the computer\nDialogue: 0,0:25:25.00,0:25:26.62,EN,,0,0,0,,and type that in, exactly that,\nDialogue: 0,0:25:27.04,0:25:28.94,EN,,0,0,0,,and then say print stream the Fibonacci numbers,\nDialogue: 0,0:25:28.94,0:25:30.15,EN,,0,0,0,,and they all come flying out.\nDialogue: 0,0:25:32.79,0:25:35.20,EN,,0,0,0,,See, this is a lot like learning about recursion again.\nDialogue: 0,0:25:36.81,0:25:39.79,EN,,0,0,0,,Instead of thinking that recursive procedures,\nDialogue: 0,0:25:40.99,0:25:43.50,EN,,0,0,0,,we have recursively defined data objects.\nDialogue: 0,0:25:45.16,0:25:46.92,EN,,0,0,0,,But that shouldn't surprise you at all,\nDialogue: 0,0:25:47.12,0:25:49.50,EN,,0,0,0,,because by now, you should be coming to really believe\nDialogue: 0,0:25:49.52,0:25:53.05,EN,,0,0,0,,that there's no difference really between procedures and data.\nDialogue: 0,0:25:53.09,0:25:53.92,EN,,0,0,0,,In fact, in some sense,\nDialogue: 0,0:25:53.93,0:25:56.41,EN,,0,0,0,,the underlying streams are procedures sitting there,\nDialogue: 0,0:25:56.43,0:25:57.79,EN,,0,0,0,,although we don't think of them that way.\nDialogue: 0,0:25:58.21,0:26:00.38,EN,,0,0,0,,So the fact that we have recursive procedures,\nDialogue: 0,0:26:00.70,0:26:03.63,EN,,0,0,0,,well, then it should be natural that we have recursive data, too.\nDialogue: 0,0:26:07.72,0:26:09.69,EN,,0,0,0,,OK, well, this is all pretty neat.\nDialogue: 0,0:26:09.72,0:26:13.92,EN,,0,0,0,,Unfortunately, there are problems that streams aren't going to solve.\nDialogue: 0,0:26:14.99,0:26:16.48,EN,,0,0,0,,Let me show you one of them.\nDialogue: 0,0:26:17.58,0:26:20.35,EN,,0,0,0,,See, in the same way, let's imagine that we're\nDialogue: 0,0:26:20.76,0:26:23.61,EN,,0,0,0,,building an analog computer to solve some differential equation\nDialogue: 0,0:26:25.20,0:26:34.30,EN,,0,0,0,,like, say, we want to solve the equation y prime dy dt is y squared,\nDialogue: 0,0:26:34.76,0:26:36.16,EN,,0,0,0,,and I'm going to give you some initial value.\nDialogue: 0,0:26:36.39,0:26:38.03,EN,,0,0,0,,I'll tell you y of 0 equals 1.\nDialogue: 0,0:26:41.48,0:26:44.06,EN,,0,0,0,,Let's say dt is equal to something.\nDialogue: 0,0:26:46.77,0:26:47.53,EN,,0,0,0,,Now, in the old days,\nDialogue: 0,0:26:48.00,0:26:50.65,EN,,0,0,0,,people built analog computers to solve these kinds of things.\nDialogue: 0,0:26:51.36,0:26:53.02,EN,,0,0,0,,And the way you do that is really simple.\nDialogue: 0,0:26:53.02,0:26:54.41,EN,,0,0,0,,You get yourself an integrator,\nDialogue: 0,0:27:00.04,0:27:01.69,EN,,0,0,0,,like that one, an integrator box.\nDialogue: 0,0:27:03.05,0:27:06.48,EN,,0,0,0,,And we put in the initial value y of 0 is 1.\nDialogue: 0,0:27:08.53,0:27:10.92,EN,,0,0,0,,And now if we feed something in and get something out,\nDialogue: 0,0:27:10.96,0:27:13.16,EN,,0,0,0,,we'll say, gee, what we're getting out is the answer.\nDialogue: 0,0:27:14.25,0:27:16.96,EN,,0,0,0,,And what we're going to feed in is the derivative,\nDialogue: 0,0:27:17.52,0:27:20.52,EN,,0,0,0,,and the derivative is supposed to be the square of the answer.\nDialogue: 0,0:27:21.49,0:27:27.07,EN,,0,0,0,,So if we take these values and map using square,\nDialogue: 0,0:27:30.73,0:27:32.09,EN,,0,0,0,,and if I feed this around,\nDialogue: 0,0:27:36.28,0:27:38.48,EN,,0,0,0,,that's how I build a block diagram\nDialogue: 0,0:27:38.57,0:27:41.08,EN,,0,0,0,,for an analog computer that solves this differential equation.\nDialogue: 0,0:27:42.91,0:27:44.80,EN,,0,0,0,,Now, what we'd like to do is write a stream\nDialogue: 0,0:27:44.80,0:27:46.78,EN,,0,0,0,,program that looks exactly like that.\nDialogue: 0,0:27:47.23,0:27:48.72,EN,,0,0,0,,And what do I mean exactly like that?\nDialogue: 0,0:27:49.39,0:27:58.30,EN,,0,0,0,,Well, I'd say define y to be the integral\nDialogue: 0,0:28:04.28,0:28:11.68,EN,,0,0,0,,of dy starting at 1 with 0.001 as a time step.\nDialogue: 0,0:28:13.79,0:28:15.45,EN,,0,0,0,,And I'd like to say that says this.\nDialogue: 0,0:28:16.80,0:28:20.85,EN,,0,0,0,,And then I'd like to say, well, dy is gotten by mapping the square along y.\nDialogue: 0,0:28:20.85,0:28:32.81,EN,,0,0,0,,So define dy to be map square along y.\nDialogue: 0,0:28:33.51,0:28:36.80,EN,,0,0,0,,So there's a stream description of this analog computer,\nDialogue: 0,0:28:38.62,0:28:40.32,EN,,0,0,0,,and unfortunately, it doesn't work.\nDialogue: 0,0:28:41.41,0:28:42.67,EN,,0,0,0,,And you can see why it doesn't work\nDialogue: 0,0:28:42.97,0:28:44.99,EN,,0,0,0,,because when I come in and say define y\nDialogue: 0,0:28:46.43,0:28:47.85,EN,,0,0,0,,to be the integral of dy\nDialogue: 0,0:28:49.04,0:28:50.65,EN,,0,0,0,,it says, oh, the integral of what-- huh?\nDialogue: 0,0:28:51.19,0:28:52.12,EN,,0,0,0,,Oh, that's undefined.\nDialogue: 0,0:28:53.71,0:28:57.63,EN,,0,0,0,,So I can't write this definition before I've written this one.\nDialogue: 0,0:28:58.77,0:29:00.51,EN,,0,0,0,,On the other hand, if I try and write this one first,\nDialogue: 0,0:29:00.51,0:29:03.02,EN,,0,0,0,,it says, oh, I define y to be the map of square along what?\nDialogue: 0,0:29:03.58,0:29:04.64,EN,,0,0,0,,Oh, that's not defined yet.\nDialogue: 0,0:29:05.77,0:29:08.17,EN,,0,0,0,,So I can't write this one first, and I can't write that one first.\nDialogue: 0,0:29:09.08,0:29:11.58,EN,,0,0,0,,So I can't quite play this game.\nDialogue: 0,0:29:17.56,0:29:18.51,EN,,0,0,0,,Well, is there a way out?\nDialogue: 0,0:29:20.60,0:29:21.84,EN,,0,0,0,,See, we can do that with ones.\nDialogue: 0,0:29:22.20,0:29:25.82,EN,,0,0,0,,See, over here, we did this thing ones,\nDialogue: 0,0:29:27.24,0:29:29.90,EN,,0,0,0,,and we were able to define ones in terms of ones because\nDialogue: 0,0:29:30.40,0:29:32.03,EN,,0,0,0,,of this delay that was built inside\nDialogue: 0,0:29:32.43,0:29:34.12,EN,,0,0,0,,because cons-stream had a delay.\nDialogue: 0,0:29:34.77,0:29:35.79,EN,,0,0,0,,Now, why's it sensible?\nDialogue: 0,0:29:35.92,0:29:38.51,EN,,0,0,0,,Why's it sensible for cons-stream to be built with this delay?\nDialogue: 0,0:29:40.73,0:29:43.13,EN,,0,0,0,,The reason is that cons-stream can do a useful thing\nDialogue: 0,0:29:43.48,0:29:44.88,EN,,0,0,0,,without looking at its tail.\nDialogue: 0,0:29:45.95,0:29:46.84,EN,,0,0,0,,See, if I say\nDialogue: 0,0:29:47.48,0:29:49.64,EN,,0,0,0,,this is cons-stream of 1 onto something\nDialogue: 0,0:29:49.92,0:29:51.69,EN,,0,0,0,,without knowing anything about something,\nDialogue: 0,0:29:52.16,0:29:54.03,EN,,0,0,0,,I know that the stream starts off with 1.\nDialogue: 0,0:29:54.87,0:29:57.29,EN,,0,0,0,,That's why it was sensible to build something like cons-stream.\nDialogue: 0,0:29:59.96,0:30:01.24,EN,,0,0,0,,So we put a delay in there,\nDialogue: 0,0:30:01.42,0:30:04.65,EN,,0,0,0,,and that allows us to have this sort of self-referential definition.\nDialogue: 0,0:30:06.32,0:30:07.95,EN,,0,0,0,,Well, integral is a little bit the same way.\nDialogue: 0,0:30:08.19,0:30:12.52,EN,,0,0,0,,See, notice for an integral, I can--\nDialogue: 0,0:30:14.60,0:30:16.08,EN,,0,0,0,,let's go back and look at integral for a second.\nDialogue: 0,0:30:17.58,0:30:18.56,EN,,0,0,0,,See, notice integral,\nDialogue: 0,0:30:21.39,0:30:25.00,EN,,0,0,0,,it makes sense to say what's the first thing in the integral\nDialogue: 0,0:30:26.04,0:30:27.87,EN,,0,0,0,,without knowing the stream that you're integrating.\nDialogue: 0,0:30:28.97,0:30:30.17,EN,,0,0,0,,Because the first thing in the integral\nDialogue: 0,0:30:30.20,0:30:32.16,EN,,0,0,0,,is always going to be the initial value that you're handed.\nDialogue: 0,0:30:33.14,0:30:36.11,EN,,0,0,0,,So integral could be a procedure like cons-stream.\nDialogue: 0,0:30:37.09,0:30:37.98,EN,,0,0,0,,You could define it,\nDialogue: 0,0:30:38.25,0:30:40.88,EN,,0,0,0,,and then even before it knows what it's supposed to be integrating,\nDialogue: 0,0:30:42.84,0:30:45.18,EN,,0,0,0,,it knows enough to say what its initial value is.\nDialogue: 0,0:30:46.71,0:30:48.17,EN,,0,0,0,,So we can make a smarter integral,\nDialogue: 0,0:30:48.41,0:30:50.68,EN,,0,0,0,,which is aha, you're going to give me a stream to integrate\nDialogue: 0,0:30:50.83,0:30:51.92,EN,,0,0,0,,and an initial value,\nDialogue: 0,0:30:52.11,0:30:54.99,EN,,0,0,0,,but I really don't have to look at that stream that I'm supposed to integrate\nDialogue: 0,0:30:55.21,0:30:56.97,EN,,0,0,0,,until you ask me to work down the stream.\nDialogue: 0,0:30:58.43,0:31:00.51,EN,,0,0,0,,In other words, integral can be like cons-stream,\nDialogue: 0,0:31:00.57,0:31:03.74,EN,,0,0,0,,and you can expect that there's going to be a delay around its integrand.\nDialogue: 0,0:31:03.76,0:31:04.86,EN,,0,0,0,,And we can write that.\nDialogue: 0,0:31:05.61,0:31:07.02,EN,,0,0,0,,Here's a procedure that does that.\nDialogue: 0,0:31:07.65,0:31:08.75,EN,,0,0,0,,Another version of integral,\nDialogue: 0,0:31:08.89,0:31:10.54,EN,,0,0,0,,and this is almost like the previous one,\nDialogue: 0,0:31:11.10,0:31:13.34,EN,,0,0,0,,except the stream it's going to get in\nDialogue: 0,0:31:13.77,0:31:15.69,EN,,0,0,0,,is going to expect to be a delayed object.\nDialogue: 0,0:31:17.11,0:31:18.43,EN,,0,0,0,,And how does this integral work?\nDialogue: 0,0:31:18.85,0:31:21.79,EN,,0,0,0,,Well, the little thing it's going to define inside of itself\nDialogue: 0,0:31:22.14,0:31:24.19,EN,,0,0,0,,says on the cons-stream,\nDialogue: 0,0:31:24.73,0:31:26.44,EN,,0,0,0,,the initial value is the initial value,\nDialogue: 0,0:31:27.16,0:31:29.68,EN,,0,0,0,,but only inside of that cons-stream,\nDialogue: 0,0:31:29.74,0:31:32.30,EN,,0,0,0,,and remember, there's going to be a hidden delay inside here.\nDialogue: 0,0:31:34.95,0:31:39.07,EN,,0,0,0,,Only inside of that cons-stream will I start looking at\nDialogue: 0,0:31:39.82,0:31:42.11,EN,,0,0,0,,what the actual delayed object is.\nDialogue: 0,0:31:43.18,0:31:45.79,EN,,0,0,0,,So my answer is the first thing's the initial value.\nDialogue: 0,0:31:45.97,0:31:47.90,EN,,0,0,0,,If anybody now asks me for my tail,\nDialogue: 0,0:31:48.40,0:31:49.42,EN,,0,0,0,,at that point,\nDialogue: 0,0:31:50.00,0:31:51.72,EN,,0,0,0,,I'm going to force that delayed object--\nDialogue: 0,0:31:52.62,0:31:53.60,EN,,0,0,0,,and I'll call that s--\nDialogue: 0,0:31:54.44,0:31:55.60,EN,,0,0,0,,and I do the add streams.\nDialogue: 0,0:31:56.36,0:31:59.26,EN,,0,0,0,,So this is an integral which is sort of like cons-stream.\nDialogue: 0,0:31:59.26,0:32:02.59,EN,,0,0,0,,It's not going to actually try and see what you handed it\nDialogue: 0,0:32:03.88,0:32:07.13,EN,,0,0,0,,as the thing to integrate until you look past the first element.\nDialogue: 0,0:32:10.12,0:32:11.02,EN,,0,0,0,,And if we do that\nDialogue: 0,0:32:11.52,0:32:12.83,EN,,0,0,0,,and we can make this work,\nDialogue: 0,0:32:13.36,0:32:15.20,EN,,0,0,0,,all we have to do here is\nDialogue: 0,0:32:16.00,0:32:25.31,EN,,0,0,0,,define y to the integral of delay of y, of delay of dy.\nDialogue: 0,0:32:27.09,0:32:28.22,EN,,0,0,0,,So y is going to be\nDialogue: 0,0:32:28.40,0:32:34.36,EN,,0,0,0,,the integral of delay of dy starting at 1,\nDialogue: 0,0:32:34.38,0:32:35.13,EN,,0,0,0,,and now this will work.\nDialogue: 0,0:32:35.28,0:32:37.44,EN,,0,0,0,,Because I type in the definition of y,\nDialogue: 0,0:32:38.00,0:32:39.68,EN,,0,0,0,,and that says, oh, I'm supposed to use the integral of\nDialogue: 0,0:32:40.20,0:32:42.68,EN,,0,0,0,,something I don't care about right now because it's a delay.\nDialogue: 0,0:32:44.60,0:32:46.32,EN,,0,0,0,,And these things, now you define dy.\nDialogue: 0,0:32:46.32,0:32:47.37,EN,,0,0,0,,Now, y is defined.\nDialogue: 0,0:32:47.55,0:32:48.89,EN,,0,0,0,,So when I define dy,\nDialogue: 0,0:32:49.13,0:32:50.67,EN,,0,0,0,,it can see that definition for y.\nDialogue: 0,0:32:51.70,0:32:52.84,EN,,0,0,0,,Everything is now started up.\nDialogue: 0,0:32:52.84,0:32:54.33,EN,,0,0,0,,Both streams have their first element.\nDialogue: 0,0:32:54.92,0:32:56.25,EN,,0,0,0,,And then when I start mapping down,\nDialogue: 0,0:32:56.27,0:32:57.31,EN,,0,0,0,,looking at successive elements,\nDialogue: 0,0:32:57.37,0:32:58.88,EN,,0,0,0,,both y and dy are defined.\nDialogue: 0,0:33:00.59,0:33:04.24,EN,,0,0,0,,So there's a little game you can play that goes a little bit beyond\nDialogue: 0,0:33:04.67,0:33:07.13,EN,,0,0,0,,just using the delay that's hidden inside streams.\nDialogue: 0,0:33:08.36,0:33:08.97,EN,,0,0,0,,Questions?\nDialogue: 0,0:33:13.52,0:33:14.27,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:34:07.30,0:34:10.04,EN,,0,0,0,,Well, just before the break, um..\nDialogue: 0,0:34:10.89,0:34:11.80,EN,,0,0,0,,I'm not sure if you noticed it,\nDialogue: 0,0:34:11.82,0:34:13.55,EN,,0,0,0,,but something nasty started to happen.\nDialogue: 0,0:34:14.83,0:34:18.40,EN,,0,0,0,,We've been going along with the streams\nDialogue: 0,0:34:19.16,0:34:22.68,EN,,0,0,0,,and divorcing time in the programs from time in the computers,\nDialogue: 0,0:34:22.86,0:34:26.28,EN,,0,0,0,,and all that divorcing got hidden inside the streams.\nDialogue: 0,0:34:27.28,0:34:29.50,EN,,0,0,0,,And then at the very end, we saw that sometimes\nDialogue: 0,0:34:29.71,0:34:32.19,EN,,0,0,0,,in order to really take advantage of this method,\nDialogue: 0,0:34:32.22,0:34:34.38,EN,,0,0,0,,you have to pull out other delays.\nDialogue: 0,0:34:34.38,0:34:35.85,EN,,0,0,0,,You have to write some explicit delays\nDialogue: 0,0:34:36.09,0:34:37.95,EN,,0,0,0,,that are not hidden inside that cons-stream.\nDialogue: 0,0:34:39.03,0:34:41.88,EN,,0,0,0,,And I did a very simple example with differential equations,\nDialogue: 0,0:34:42.35,0:34:44.08,EN,,0,0,0,,but if you have some very complicated system\nDialogue: 0,0:34:44.12,0:34:45.40,EN,,0,0,0,,with all kinds of self-loops,\nDialogue: 0,0:34:45.95,0:34:47.84,EN,,0,0,0,,it becomes very, very difficult to\nDialogue: 0,0:34:47.90,0:34:49.31,EN,,0,0,0,,see where you need those delays.\nDialogue: 0,0:34:49.92,0:34:51.18,EN,,0,0,0,,And if you leave them out by mistake,\nDialogue: 0,0:34:51.45,0:34:54.36,EN,,0,0,0,,it becomes very, very difficult to see why the thing maybe isn't working.\nDialogue: 0,0:34:55.55,0:34:57.15,EN,,0,0,0,,So that's kind of mess,\nDialogue: 0,0:34:57.79,0:35:01.71,EN,,0,0,0,,that by getting this power and allowing us to use delay,\nDialogue: 0,0:35:02.08,0:35:04.70,EN,,0,0,0,,we end up with some very complicated programming sometimes,\nDialogue: 0,0:35:04.72,0:35:06.80,EN,,0,0,0,,because it can't all be hidden inside the streams.\nDialogue: 0,0:35:08.51,0:35:09.79,EN,,0,0,0,,Well, is there a way out of that?\nDialogue: 0,0:35:11.13,0:35:12.67,EN,,0,0,0,,Yeah, there is a way out of that.\nDialogue: 0,0:35:13.48,0:35:16.08,EN,,0,0,0,,We could change the language so that\nDialogue: 0,0:35:16.14,0:35:18.19,EN,,0,0,0,,all procedures acted like cons-stream,\nDialogue: 0,0:35:19.10,0:35:21.48,EN,,0,0,0,,so that every procedure automatically\nDialogue: 0,0:35:22.32,0:35:25.45,EN,,0,0,0,,has an implicit delay around its arguments.\nDialogue: 0,0:35:25.45,0:35:26.43,EN,,0,0,0,,And what would that mean?\nDialogue: 0,0:35:27.52,0:35:29.53,EN,,0,0,0,,That would mean when you call a procedure,\nDialogue: 0,0:35:30.16,0:35:31.88,EN,,0,0,0,,the arguments wouldn't get evaluated.\nDialogue: 0,0:35:32.21,0:35:34.70,EN,,0,0,0,,Instead, they'd only be evaluated when you need them,\nDialogue: 0,0:35:34.89,0:35:36.72,EN,,0,0,0,,so they might be passed off to some other procedure,\nDialogue: 0,0:35:36.76,0:35:38.12,EN,,0,0,0,,which wouldn't evaluate them either.\nDialogue: 0,0:35:39.26,0:35:41.90,EN,,0,0,0,,So all these procedures would be passing promises around.\nDialogue: 0,0:35:42.15,0:35:44.46,EN,,0,0,0,,And then finally maybe when you finally got down\nDialogue: 0,0:35:44.65,0:35:47.34,EN,,0,0,0,,to having to look at the value of something\nDialogue: 0,0:35:47.36,0:35:48.99,EN,,0,0,0,,that was handed to a primitive operator\nDialogue: 0,0:35:49.37,0:35:51.48,EN,,0,0,0,,which you actually start calling in all those promises.\nDialogue: 0,0:35:52.38,0:35:53.16,EN,,0,0,0,,If we did that,\nDialogue: 0,0:35:53.36,0:35:55.37,EN,,0,0,0,,since everything would have a uniform delay,\nDialogue: 0,0:35:57.16,0:35:59.00,EN,,0,0,0,,then you wouldn't have to write any explicit delays,\nDialogue: 0,0:35:59.04,0:36:01.55,EN,,0,0,0,,because it would be automatically built into the way the language works.\nDialogue: 0,0:36:03.24,0:36:04.38,EN,,0,0,0,,Or another way to say that,\nDialogue: 0,0:36:05.10,0:36:08.14,EN,,0,0,0,,technically what I'm describing is what's called\nDialogue: 0,0:36:09.02,0:36:10.76,EN,,0,0,0,,if we did that, our language would be\nDialogue: 0,0:36:12.19,0:36:16.57,EN,,0,0,0,,so-called normal-order evaluation language\nDialogue: 0,0:36:20.20,0:36:23.47,EN,,0,0,0,,versus what we've actually been working with,\nDialogue: 0,0:36:23.87,0:36:33.79,EN,,0,0,0,,which is called applicative order--  versus applicative-order evaluation.\nDialogue: 0,0:36:34.56,0:36:36.83,EN,,0,0,0,,And remember the substitution model for applicative order.\nDialogue: 0,0:36:36.83,0:36:40.49,EN,,0,0,0,,It says when you go and evaluate a combination,\nDialogue: 0,0:36:40.51,0:36:42.11,EN,,0,0,0,,you find the values of all the pieces.\nDialogue: 0,0:36:43.59,0:36:45.40,EN,,0,0,0,,You evaluate the arguments and then you\nDialogue: 0,0:36:45.72,0:36:47.42,EN,,0,0,0,,substitute them in the body of the procedure.\nDialogue: 0,0:36:47.60,0:36:49.55,EN,,0,0,0,,Normal order says no, don't do that.\nDialogue: 0,0:36:49.89,0:36:51.90,EN,,0,0,0,,What you do is effectively\nDialogue: 0,0:36:52.76,0:36:54.41,EN,,0,0,0,,substitute in the body of the procedure,\nDialogue: 0,0:36:54.44,0:36:56.19,EN,,0,0,0,,but instead of evaluating the arguments,\nDialogue: 0,0:36:56.54,0:36:58.08,EN,,0,0,0,,you just put a promise to compute them there.\nDialogue: 0,0:36:58.81,0:36:59.90,EN,,0,0,0,,Or another way to say that\nDialogue: 0,0:36:59.92,0:37:02.09,EN,,0,0,0,,you take the expressions for the arguments, if you like,\nDialogue: 0,0:37:02.28,0:37:04.84,EN,,0,0,0,,and substitute them in the body of the procedure and go on,\nDialogue: 0,0:37:05.16,0:37:06.88,EN,,0,0,0,,and never really simplify anything\nDialogue: 0,0:37:07.16,0:37:08.76,EN,,0,0,0,,until you get down to a primitive operator.\nDialogue: 0,0:37:09.47,0:37:10.99,EN,,0,0,0,,So that would be a normal-order language.\nDialogue: 0,0:37:12.17,0:37:13.12,EN,,0,0,0,,Well, why don't we do that?\nDialogue: 0,0:37:13.82,0:37:14.60,EN,,0,0,0,,Because if we did,\nDialogue: 0,0:37:15.00,0:37:17.34,EN,,0,0,0,,we'd get all the advantages of delayed evaluation\nDialogue: 0,0:37:17.90,0:37:18.80,EN,,0,0,0,,with none of the mess.\nDialogue: 0,0:37:18.94,0:37:20.19,EN,,0,0,0,,In fact, if we did that\nDialogue: 0,0:37:20.43,0:37:22.67,EN,,0,0,0,,and cons was just a delayed procedure,\nDialogue: 0,0:37:22.68,0:37:24.57,EN,,0,0,0,,that would make cons the same as cons-stream.\nDialogue: 0,0:37:24.71,0:37:25.82,EN,,0,0,0,,We wouldn't need streams at all\nDialogue: 0,0:37:26.36,0:37:28.54,EN,,0,0,0,,because lists would automatically be streams.\nDialogue: 0,0:37:29.55,0:37:30.70,EN,,0,0,0,,That's how lists would behave,\nDialogue: 0,0:37:30.75,0:37:32.35,EN,,0,0,0,,all data structures would behave that way.\nDialogue: 0,0:37:32.35,0:37:33.64,EN,,0,0,0,,Everything would behave that way.\nDialogue: 0,0:37:35.07,0:37:37.63,EN,,0,0,0,,Right, You'd never really do any computation\nDialogue: 0,0:37:37.66,0:37:39.42,EN,,0,0,0,,until you actually needed the answer.\nDialogue: 0,0:37:40.80,0:37:43.58,EN,,0,0,0,,You wouldn't have to worry about all these explicit annoying delays.\nDialogue: 0,0:37:44.79,0:37:46.16,EN,,0,0,0,,Well, why don't we do that?\nDialogue: 0,0:37:47.16,0:37:48.81,EN,,0,0,0,,First of all, I should say people do do that.\nDialogue: 0,0:37:49.23,0:37:51.85,EN,,0,0,0,,There's some very beautiful languages.\nDialogue: 0,0:37:51.85,0:37:55.21,EN,,0,0,0,,One of the very nicest is a language called Miranda,\nDialogue: 0,0:37:55.77,0:37:56.76,EN,,0,0,0,,which is, um..\nDialogue: 0,0:37:57.44,0:37:59.80,EN,,0,0,0,,developed by David Turner at the University of Kent.\nDialogue: 0,0:38:00.71,0:38:01.93,EN,,0,0,0,,And that's how this language works.\nDialogue: 0,0:38:01.93,0:38:03.34,EN,,0,0,0,,It's a normal-order language\nDialogue: 0,0:38:04.27,0:38:05.55,EN,,0,0,0,,and its data structures,\nDialogue: 0,0:38:06.16,0:38:08.41,EN,,0,0,0,,which look like lists, are actually streams.\nDialogue: 0,0:38:08.96,0:38:10.91,EN,,0,0,0,,And you write ordinary procedures in Miranda,\nDialogue: 0,0:38:11.28,0:38:13.28,EN,,0,0,0,,and they do these prime things and eight queens things,\nDialogue: 0,0:38:13.32,0:38:14.97,EN,,0,0,0,,just without anything special.\nDialogue: 0,0:38:14.97,0:38:16.35,EN,,0,0,0,,It's all built in there.\nDialogue: 0,0:38:17.93,0:38:18.91,EN,,0,0,0,,But there's a price.\nDialogue: 0,0:38:21.19,0:38:22.36,EN,,0,0,0,,Remember how we got here.\nDialogue: 0,0:38:23.17,0:38:27.48,EN,,0,0,0,,We're decoupling time in the programs from time in the machines.\nDialogue: 0,0:38:27.96,0:38:28.88,EN,,0,0,0,,And if we put delay,\nDialogue: 0,0:38:29.04,0:38:30.33,EN,,0,0,0,,that sort of decouples it everywhere,\nDialogue: 0,0:38:30.40,0:38:31.42,EN,,0,0,0,,not just in streams.\nDialogue: 0,0:38:32.19,0:38:33.14,EN,,0,0,0,,Remember what we're trying to do.\nDialogue: 0,0:38:33.14,0:38:38.11,EN,,0,0,0,,We're trying to think about programming as a way to specify processes.\nDialogue: 0,0:38:39.30,0:38:40.62,EN,,0,0,0,,And if we give up too much time,\nDialogue: 0,0:38:40.65,0:38:42.41,EN,,0,0,0,,our language becomes more elegant,\nDialogue: 0,0:38:43.74,0:38:45.87,EN,,0,0,0,,but it becomes a little bit less expressive.\nDialogue: 0,0:38:47.03,0:38:49.84,EN,,0,0,0,,There are certain distinctions that we can't draw.\nDialogue: 0,0:38:51.48,0:38:53.15,EN,,0,0,0,,One of them, for instance, is iteration.\nDialogue: 0,0:38:53.98,0:38:56.44,EN,,0,0,0,,Remember this old procedure,\nDialogue: 0,0:38:56.96,0:38:58.28,EN,,0,0,0,,iterative factorial,\nDialogue: 0,0:38:58.44,0:39:00.48,EN,,0,0,0,,that we looked at quite a long time ago.\nDialogue: 0,0:39:01.23,0:39:02.97,EN,,0,0,0,,Iterative factorial had a thing,\nDialogue: 0,0:39:03.04,0:39:04.91,EN,,0,0,0,,and it said there was an internal procedure,\nDialogue: 0,0:39:05.18,0:39:07.50,EN,,0,0,0,,and there was a state which was a product and a counter,\nDialogue: 0,0:39:08.70,0:39:10.96,EN,,0,0,0,,and we iterate that going around the loop.\nDialogue: 0,0:39:12.12,0:39:13.68,EN,,0,0,0,,And we said that was an iterative procedure\nDialogue: 0,0:39:13.71,0:39:14.83,EN,,0,0,0,,because it didn't build up state.\nDialogue: 0,0:39:15.73,0:39:17.45,EN,,0,0,0,,And the reason it didn't build up state is\nDialogue: 0,0:39:17.47,0:39:20.25,EN,,0,0,0,,because this iter that's called\nDialogue: 0,0:39:20.30,0:39:22.86,EN,,0,0,0,,is just passing these things around to itself.\nDialogue: 0,0:39:23.90,0:39:25.39,EN,,0,0,0,,Or in the substitution model that,\nDialogue: 0,0:39:25.55,0:39:27.79,EN,,0,0,0,,you could see in the substitution model that Jerry did,\nDialogue: 0,0:39:28.72,0:39:30.01,EN,,0,0,0,,that in an iterative procedure,\nDialogue: 0,0:39:30.03,0:39:31.44,EN,,0,0,0,,that state doesn't have to grow.\nDialogue: 0,0:39:31.82,0:39:34.22,EN,,0,0,0,,And in fact, we said it doesn't, so this is an iteration.\nDialogue: 0,0:39:34.99,0:39:37.47,EN,,0,0,0,,But now think about this exact same text\nDialogue: 0,0:39:37.47,0:39:39.10,EN,,0,0,0,,if we had a normal-order language.\nDialogue: 0,0:39:41.15,0:39:42.17,EN,,0,0,0,,What would happen is\nDialogue: 0,0:39:42.88,0:39:44.96,EN,,0,0,0,,this would no longer be an iterative procedure\nDialogue: 0,0:39:45.65,0:39:48.67,EN,,0,0,0,,And if you really think about the details of the substitution model,\nDialogue: 0,0:39:48.67,0:39:49.90,EN,,0,0,0,,which I'm not going to do here,\nDialogue: 0,0:39:51.20,0:39:52.35,EN,,0,0,0,,this expression would grow.\nDialogue: 0,0:39:52.36,0:39:53.18,EN,,0,0,0,,Why would it grow?\nDialogue: 0,0:39:53.28,0:39:55.20,EN,,0,0,0,,It's because when iter calls itself,\nDialogue: 0,0:39:55.85,0:39:57.31,EN,,0,0,0,,it calls itself with this product.\nDialogue: 0,0:39:58.08,0:39:59.36,EN,,0,0,0,,If it's a normal-order language,\nDialogue: 0,0:39:59.39,0:40:01.16,EN,,0,0,0,,that multiplication is not going to get done.\nDialogue: 0,0:40:02.51,0:40:03.82,EN,,0,0,0,,That's going to say I'm to call myself\nDialogue: 0,0:40:03.93,0:40:05.68,EN,,0,0,0,,with a promise to compute this product.\nDialogue: 0,0:40:06.67,0:40:08.03,EN,,0,0,0,,And now iter goes around again.\nDialogue: 0,0:40:09.76,0:40:11.55,EN,,0,0,0,,And I'm going to call myself\nDialogue: 0,0:40:11.84,0:40:14.04,EN,,0,0,0,,with a promise to compute this product\nDialogue: 0,0:40:14.04,0:40:17.82,EN,,0,0,0,,where now one of the one factors is a promise.\nDialogue: 0,0:40:18.40,0:40:19.43,EN,,0,0,0,,And I call myself again.\nDialogue: 0,0:40:19.43,0:40:21.13,EN,,0,0,0,,And if you write out the substitution model\nDialogue: 0,0:40:21.98,0:40:23.60,EN,,0,0,0,,for that iterative process,\nDialogue: 0,0:40:23.77,0:40:26.83,EN,,0,0,0,,you'll see exactly the same growth in state,\nDialogue: 0,0:40:27.16,0:40:28.96,EN,,0,0,0,,all those promises that are getting remembered\nDialogue: 0,0:40:28.97,0:40:30.76,EN,,0,0,0,,that have to get called in at the very end.\nDialogue: 0,0:40:31.79,0:40:35.02,EN,,0,0,0,,So one of the disadvantages\nDialogue: 0,0:40:35.05,0:40:36.86,EN,,0,0,0,,is that you can't really express iteration.\nDialogue: 0,0:40:36.98,0:40:39.60,EN,,0,0,0,,Maybe that's a little theoretical reason why not,\nDialogue: 0,0:40:39.61,0:40:43.90,EN,,0,0,0,,but in fact, people who are trying to write real operating systems\nDialogue: 0,0:40:44.27,0:40:47.56,EN,,0,0,0,,in these languages are running into exactly these types of problems.\nDialogue: 0,0:40:48.20,0:40:50.75,EN,,0,0,0,,Like it's perfectly possible to\nDialogue: 0,0:40:51.64,0:40:54.38,EN,,0,0,0,,implement a text editor in languages like these.\nDialogue: 0,0:40:54.61,0:40:56.08,EN,,0,0,0,,But after you work a while,\nDialogue: 0,0:40:56.72,0:40:59.39,EN,,0,0,0,,you suddenly have 3 megabytes of stuff,\nDialogue: 0,0:40:59.44,0:41:02.04,EN,,0,0,0,,which is-- I guess they call them\nDialogue: 0,0:41:02.16,0:41:05.60,EN,,0,0,0,,the dragging tail problem who are looking at these,\nDialogue: 0,0:41:05.82,0:41:08.20,EN,,0,0,0,,of stuff of promises that sort of haven't been called in\nDialogue: 0,0:41:08.24,0:41:10.46,EN,,0,0,0,,because you couldn't quite express an iteration.\nDialogue: 0,0:41:10.72,0:41:14.81,EN,,0,0,0,,And one of the research questions in these kinds of languages\nDialogue: 0,0:41:14.83,0:41:17.48,EN,,0,0,0,,are figuring out the right compiler technology\nDialogue: 0,0:41:17.82,0:41:19.85,EN,,0,0,0,,to get rid of the so-called dragging tails.\nDialogue: 0,0:41:20.17,0:41:21.61,EN,,0,0,0,,It's not simple.\nDialogue: 0,0:41:23.94,0:41:27.31,EN,,0,0,0,,But there's another kind of more striking issue\nDialogue: 0,0:41:27.96,0:41:31.04,EN,,0,0,0,,about why you just don't go ahead and make your language normal order.\nDialogue: 0,0:41:32.51,0:41:33.29,EN,,0,0,0,,And the reason is\nDialogue: 0,0:41:35.05,0:41:38.09,EN,,0,0,0,,that normal-order evaluation and side effects\nDialogue: 0,0:41:38.89,0:41:40.19,EN,,0,0,0,,just don't mix.\nDialogue: 0,0:41:42.00,0:41:43.96,EN,,0,0,0,,They just don't go together very well.\nDialogue: 0,0:41:45.44,0:41:46.65,EN,,0,0,0,,Somehow, you can't-\nDialogue: 0,0:41:48.28,0:41:50.80,EN,,0,0,0,,it's sort of you can't simultaneously\nDialogue: 0,0:41:51.00,0:41:54.33,EN,,0,0,0,,go around trying to model objects with local state and change\nDialogue: 0,0:41:55.72,0:41:56.96,EN,,0,0,0,,at the same time\nDialogue: 0,0:41:57.18,0:41:59.55,EN,,0,0,0,,do these normal-order tricks of de-coupling time.\nDialogue: 0,0:42:00.40,0:42:03.55,EN,,0,0,0,,Let me just show you a really simple example, very, very simple.\nDialogue: 0,0:42:03.79,0:42:05.50,EN,,0,0,0,,Suppose we had a normal-order language.\nDialogue: 0,0:42:07.52,0:42:09.55,EN,,0,0,0,,And I'm going to start out in this language.\nDialogue: 0,0:42:09.55,0:42:10.52,EN,,0,0,0,,This is now normal order.\nDialogue: 0,0:42:10.52,0:42:12.22,EN,,0,0,0,,I'm going to define x to be 0.\nDialogue: 0,0:42:13.57,0:42:15.56,EN,,0,0,0,,It's just some variable I'll initialize.\nDialogue: 0,0:42:15.75,0:42:17.69,EN,,0,0,0,,And now I'm going to define this little funny function,\nDialogue: 0,0:42:18.57,0:42:20.44,EN,,0,0,0,,which is an identity function.\nDialogue: 0,0:42:22.64,0:42:23.90,EN,,0,0,0,,And what it does,\nDialogue: 0,0:42:24.11,0:42:26.60,EN,,0,0,0,,it keeps track of the last time you called it using x.\nDialogue: 0,0:42:31.40,0:42:34.16,EN,,0,0,0,,Right? So the identity of n just returns n,\nDialogue: 0,0:42:34.17,0:42:35.39,EN,,0,0,0,,but it sets x to be n.\nDialogue: 0,0:42:36.76,0:42:38.54,EN,,0,0,0,,And now I'll define a little increment function,\nDialogue: 0,0:42:39.55,0:42:42.30,EN,,0,0,0,,which is a very little, simple scenario.\nDialogue: 0,0:42:42.58,0:42:45.34,EN,,0,0,0,,Now, imagine I'm interacting with this in the normal-order language,\nDialogue: 0,0:42:46.27,0:42:47.23,EN,,0,0,0,,and I type the following.\nDialogue: 0,0:42:47.23,0:42:52.83,EN,,0,0,0,,I say define y to be increment the identity function of 3,\nDialogue: 0,0:42:52.83,0:42:53.96,EN,,0,0,0,,so y is going to be 4.\nDialogue: 0,0:42:57.41,0:42:58.35,EN,,0,0,0,,Now, I say what's x?\nDialogue: 0,0:42:59.52,0:43:02.16,EN,,0,0,0,,Well, x should have been the value that was remembered last\nDialogue: 0,0:43:02.64,0:43:04.01,EN,,0,0,0,,when I called the identity function.\nDialogue: 0,0:43:04.71,0:43:06.73,EN,,0,0,0,,So you'd expect to say, well, x is 3 at this point,\nDialogue: 0,0:43:06.91,0:43:07.52,EN,,0,0,0,,but it's not.\nDialogue: 0,0:43:08.53,0:43:11.15,EN,,0,0,0,,Because when I defined here, y here,\nDialogue: 0,0:43:11.79,0:43:13.45,EN,,0,0,0,,what I really defined y to be\nDialogue: 0,0:43:13.47,0:43:15.71,EN,,0,0,0,,increment of a promise to do this thing.\nDialogue: 0,0:43:17.00,0:43:18.17,EN,,0,0,0,,So I didn't look at y,\nDialogue: 0,0:43:18.36,0:43:20.25,EN,,0,0,0,,so that identity function didn't get run.\nDialogue: 0,0:43:21.56,0:43:23.20,EN,,0,0,0,,So if I type in this definition\nDialogue: 0,0:43:23.31,0:43:24.80,EN,,0,0,0,,and look at x, I'm going to get 0.\nDialogue: 0,0:43:28.36,0:43:31.20,EN,,0,0,0,,Now, if I go look at y and say what's y,\nDialogue: 0,0:43:31.52,0:43:32.43,EN,,0,0,0,,say y is 4,\nDialogue: 0,0:43:32.67,0:43:35.16,EN,,0,0,0,,looking at y, that very active looking at y\nDialogue: 0,0:43:35.29,0:43:37.42,EN,,0,0,0,,caused the identity function to be run.\nDialogue: 0,0:43:38.72,0:43:40.48,EN,,0,0,0,,And now x will get remembered as 3.\nDialogue: 0,0:43:40.74,0:43:41.87,EN,,0,0,0,,So here x will be 0.\nDialogue: 0,0:43:41.93,0:43:42.96,EN,,0,0,0,,Here, x will be 3.\nDialogue: 0,0:43:43.28,0:43:46.16,EN,,0,0,0,,That's a tiny, little, simple scenario,\nDialogue: 0,0:43:46.30,0:43:49.28,EN,,0,0,0,,but you can see what kind of a mess that's going to make\nDialogue: 0,0:43:50.36,0:43:53.34,EN,,0,0,0,,for debugging interactive programs\nDialogue: 0,0:43:54.12,0:43:55.88,EN,,0,0,0,,when you have normal-order evaluation.\nDialogue: 0,0:43:57.10,0:43:58.12,EN,,0,0,0,,It's very confusing.\nDialogue: 0,0:43:59.69,0:44:02.04,EN,,0,0,0,,But it's very confusing for a very deep reason,\nDialogue: 0,0:44:02.80,0:44:06.41,EN,,0,0,0,,which is that the whole idea of putting in delays\nDialogue: 0,0:44:06.92,0:44:08.43,EN,,0,0,0,,is that you throw away time.\nDialogue: 0,0:44:09.78,0:44:11.75,EN,,0,0,0,,That's why we can have these infinite processes.\nDialogue: 0,0:44:11.75,0:44:12.97,EN,,0,0,0,,Since we've thrown away time,\nDialogue: 0,0:44:12.99,0:44:14.27,EN,,0,0,0,,we don't have to wait for them to run,\nDialogue: 0,0:44:17.55,0:44:20.44,EN,,0,0,0,,Right? We decouple the order of events in the computer\nDialogue: 0,0:44:20.83,0:44:22.11,EN,,0,0,0,,from what we write in our programs.\nDialogue: 0,0:44:22.35,0:44:25.28,EN,,0,0,0,,But when we talk about state and set and change,\nDialogue: 0,0:44:25.48,0:44:27.42,EN,,0,0,0,,that's exactly what we do want control of.\nDialogue: 0,0:44:28.76,0:44:33.82,EN,,0,0,0,,So it's almost as if there's this fundamental contradiction in what you want.\nDialogue: 0,0:44:34.57,0:44:39.12,EN,,0,0,0,,And that brings us back to these sort of philosophical mutterings\nDialogue: 0,0:44:39.13,0:44:40.75,EN,,0,0,0,,what is it that you're trying to model\nDialogue: 0,0:44:40.78,0:44:41.77,EN,,0,0,0,,and how do you look at the world.\nDialogue: 0,0:44:42.41,0:44:44.30,EN,,0,0,0,,Or sometimes this is called the\nDialogue: 0,0:44:44.76,0:44:46.60,EN,,0,0,0,,the debate over functional programming.\nDialogue: 0,0:44:54.19,0:44:56.60,EN,,0,0,0,,A so-called purely functional language\nDialogue: 0,0:44:57.07,0:44:59.20,EN,,0,0,0,,is one that just doesn't have any side effects.\nDialogue: 0,0:45:00.44,0:45:01.63,EN,,0,0,0,,Since you have no side effects,\nDialogue: 0,0:45:01.64,0:45:03.02,EN,,0,0,0,,there's no assignment operator,\nDialogue: 0,0:45:03.34,0:45:05.72,EN,,0,0,0,,so there are no terrible consequences of it.\nDialogue: 0,0:45:06.36,0:45:07.93,EN,,0,0,0,,You can use a substitution-like thing.\nDialogue: 0,0:45:07.93,0:45:10.48,EN,,0,0,0,,Programs really are like mathematics and not like\nDialogue: 0,0:45:10.76,0:45:13.82,EN,,0,0,0,,not like models in the real world, not like objects in the real world.\nDialogue: 0,0:45:15.05,0:45:17.17,EN,,0,0,0,,There are a lot of wonderful things about functional languages.\nDialogue: 0,0:45:17.17,0:45:19.63,EN,,0,0,0,,Since there's no time, you never have any synchronization problems.\nDialogue: 0,0:45:20.64,0:45:23.72,EN,,0,0,0,,And if you want to put something into a parallel algorithm,\nDialogue: 0,0:45:24.72,0:45:28.20,EN,,0,0,0,,you can run the pieces of that parallel processing any way you want.\nDialogue: 0,0:45:29.40,0:45:31.44,EN,,0,0,0,,There's just never any synchronization to worry that,\nDialogue: 0,0:45:31.50,0:45:33.34,EN,,0,0,0,,and it's a very congenial environment for doing this.\nDialogue: 0,0:45:33.64,0:45:35.71,EN,,0,0,0,,The price is you give up assignment.\nDialogue: 0,0:45:39.10,0:45:41.32,EN,,0,0,0,,So an advocate of a functional language would say,\nDialogue: 0,0:45:41.34,0:45:43.04,EN,,0,0,0,,gee, that's just a tiny price to pay.\nDialogue: 0,0:45:44.52,0:45:46.51,EN,,0,0,0,,You probably shouldn't use assignment most of the time anyway.\nDialogue: 0,0:45:46.88,0:45:48.27,EN,,0,0,0,,And if you just give up assignment,\nDialogue: 0,0:45:48.43,0:45:51.40,EN,,0,0,0,,you can be in this much, much nicer world\nDialogue: 0,0:45:51.96,0:45:53.24,EN,,0,0,0,,than this place with objects.\nDialogue: 0,0:45:54.19,0:45:56.30,EN,,0,0,0,,Well, what's the rejoinder to that?\nDialogue: 0,0:45:56.30,0:45:58.59,EN,,0,0,0,,Remember how we got into this mess.\nDialogue: 0,0:46:00.06,0:46:03.79,EN,,0,0,0,,We started trying to model things that had local state.\nDialogue: 0,0:46:04.44,0:46:06.49,EN,,0,0,0,,So remember Gerry's random number generator.\nDialogue: 0,0:46:07.16,0:46:08.67,EN,,0,0,0,,There was this random number generator\nDialogue: 0,0:46:09.28,0:46:10.62,EN,,0,0,0,,that had some little state in it\nDialogue: 0,0:46:10.83,0:46:12.08,EN,,0,0,0,,to compute the next random number\nDialogue: 0,0:46:12.12,0:46:14.08,EN,,0,0,0,,and the next random number and the next random number.\nDialogue: 0,0:46:14.28,0:46:16.14,EN,,0,0,0,,And we wanted to hide that state away from the\nDialogue: 0,0:46:16.43,0:46:18.96,EN,,0,0,0,,the Cesaro compute pi process,\nDialogue: 0,0:46:19.84,0:46:20.92,EN,,0,0,0,,and that's why we needed set!\nDialogue: 0,0:46:20.97,0:46:22.91,EN,,0,0,0,,We wanted to package that stated modularly.\nDialogue: 0,0:46:24.07,0:46:26.36,EN,,0,0,0,,Well, a functional programming person would say,\nDialogue: 0,0:46:26.38,0:46:27.56,EN,,0,0,0,,well, you're just all wet.\nDialogue: 0,0:46:27.56,0:46:29.84,EN,,0,0,0,,I mean, you can write a perfectly good modular program.\nDialogue: 0,0:46:29.84,0:46:32.46,EN,,0,0,0,,It's just you're thinking about modularity wrong.\nDialogue: 0,0:46:33.08,0:46:35.02,EN,,0,0,0,,You're hung up in this next random number\nDialogue: 0,0:46:35.07,0:46:36.88,EN,,0,0,0,,and the next random number and the next random number.\nDialogue: 0,0:46:36.88,0:46:39.42,EN,,0,0,0,,Why don't you just say let's write a program.\nDialogue: 0,0:46:40.09,0:46:41.29,EN,,0,0,0,,Let's write an enumerator\nDialogue: 0,0:46:41.95,0:46:44.48,EN,,0,0,0,,which just generates an infinite stream of random numbers.\nDialogue: 0,0:46:49.01,0:46:50.91,EN,,0,0,0,,We can sort of have that stream all at once,\nDialogue: 0,0:46:52.64,0:46:54.54,EN,,0,0,0,,and that's going to be our source of random numbers.\nDialogue: 0,0:46:54.54,0:46:55.24,EN,,0,0,0,,And then if you like,\nDialogue: 0,0:46:55.53,0:46:57.47,EN,,0,0,0,,you can put that through some sort of processor,\nDialogue: 0,0:46:57.77,0:47:01.16,EN,,0,0,0,,which is-- I don't know-- a Cesaro test,\nDialogue: 0,0:47:04.94,0:47:06.22,EN,,0,0,0,,and that can do what it wants.\nDialogue: 0,0:47:06.88,0:47:08.56,EN,,0,0,0,,And what would come out of there\nDialogue: 0,0:47:08.72,0:47:27.45,EN,,0,0,0,,would be a stream of successive approximations to pi.\nDialogue: 0,0:47:28.14,0:47:30.65,EN,,0,0,0,,So as we looked further down this stream,\nDialogue: 0,0:47:30.76,0:47:32.38,EN,,0,0,0,,we'd tug on this Cesaro thing,\nDialogue: 0,0:47:33.12,0:47:35.36,EN,,0,0,0,,and it would pull out more and more random numbers.\nDialogue: 0,0:47:35.54,0:47:37.21,EN,,0,0,0,,And the further and further we look down the stream,\nDialogue: 0,0:47:37.23,0:47:38.96,EN,,0,0,0,,the better an approximation we'd get to pi.\nDialogue: 0,0:47:39.72,0:47:41.66,EN,,0,0,0,,And it would do exactly the same as the other computation,\nDialogue: 0,0:47:41.66,0:47:43.79,EN,,0,0,0,,except we're thinking about the modularity different.\nDialogue: 0,0:47:43.89,0:47:45.55,EN,,0,0,0,,We're saying imagine we had all that\nDialogue: 0,0:47:45.56,0:47:47.47,EN,,0,0,0,,infinite streams of random numbers all at once.\nDialogue: 0,0:47:49.28,0:47:52.24,EN,,0,0,0,,You can see the details of this procedure in the book.\nDialogue: 0,0:47:53.61,0:47:57.85,EN,,0,0,0,,But similarly, there are other things that we tend to get locked into\nDialogue: 0,0:47:58.27,0:48:01.20,EN,,0,0,0,,on this one and that one and the next one and the next one,\nDialogue: 0,0:48:01.37,0:48:02.81,EN,,0,0,0,,which don't have to be that way.\nDialogue: 0,0:48:03.28,0:48:06.54,EN,,0,0,0,,Like you might think about like a banking system,\nDialogue: 0,0:48:07.68,0:48:08.90,EN,,0,0,0,,which is a very simple idea.\nDialogue: 0,0:48:08.90,0:48:12.21,EN,,0,0,0,,Imagine we have a program that sort of represents a bank account.\nDialogue: 0,0:48:18.81,0:48:20.84,EN,,0,0,0,,The bank account might have in it--\nDialogue: 0,0:48:22.78,0:48:26.22,EN,,0,0,0,,if we looked at this in a sort of message-passing view of the world,\nDialogue: 0,0:48:26.44,0:48:28.12,EN,,0,0,0,,we'd say a bank account is an object\nDialogue: 0,0:48:28.59,0:48:31.51,EN,,0,0,0,,that has some local state in there, which is the balance, say.\nDialogue: 0,0:48:34.11,0:48:36.00,EN,,0,0,0,,And a user using this system comes\nDialogue: 0,0:48:36.44,0:48:38.14,EN,,0,0,0,,and sends a transaction request.\nDialogue: 0,0:48:39.31,0:48:41.05,EN,,0,0,0,,So the user sends a transaction request,\nDialogue: 0,0:48:41.07,0:48:42.20,EN,,0,0,0,,like deposit some money,\nDialogue: 0,0:48:42.28,0:48:43.53,EN,,0,0,0,,and the bank account maybe--\nDialogue: 0,0:48:43.92,0:48:46.78,EN,,0,0,0,,let's say the bank account always responds with what the current balance is.\nDialogue: 0,0:48:48.22,0:48:50.04,EN,,0,0,0,,The user says let's deposits some money,\nDialogue: 0,0:48:50.06,0:48:53.21,EN,,0,0,0,,and the bank account sends back a message which is the balance.\nDialogue: 0,0:48:54.35,0:48:57.42,EN,,0,0,0,,And the user says deposit some more,\nDialogue: 0,0:48:57.45,0:48:58.81,EN,,0,0,0,,and the bank account sends back a message.\nDialogue: 0,0:48:59.15,0:49:00.75,EN,,0,0,0,,And just like the random number generating\nDialogue: 0,0:49:00.78,0:49:02.12,EN,,0,0,0,,you'd say, gee, we would like to use set.\nDialogue: 0,0:49:03.20,0:49:06.88,EN,,0,0,0,,We'd like to have balance be a piece of local state inside this bank account\nDialogue: 0,0:49:06.88,0:49:08.40,EN,,0,0,0,,because we want to separate the state of the user\nDialogue: 0,0:49:08.41,0:49:09.57,EN,,0,0,0,,from the state of the bank account.\nDialogue: 0,0:49:13.28,0:49:16.42,EN,,0,0,0,,Well, that's the message-processing view.\nDialogue: 0,0:49:16.42,0:49:18.20,EN,,0,0,0,,There's a stream view with that thing,\nDialogue: 0,0:49:19.48,0:49:22.19,EN,,0,0,0,,which does the same thing without any set or side effects.\nDialogue: 0,0:49:22.74,0:49:26.73,EN,,0,0,0,,And the idea is again\nDialogue: 0,0:49:27.37,0:49:30.25,EN,,0,0,0,,we don't think about anything having local state.\nDialogue: 0,0:49:31.18,0:49:33.08,EN,,0,0,0,,We think about the bank account as something\nDialogue: 0,0:49:33.40,0:49:37.71,EN,,0,0,0,,that's going to process a stream of transaction requests.\nDialogue: 0,0:49:38.64,0:49:40.16,EN,,0,0,0,,So think about this bank account not\nDialogue: 0,0:49:40.22,0:49:42.00,EN,,0,0,0,,as something that goes message by message,\nDialogue: 0,0:49:42.44,0:49:45.85,EN,,0,0,0,,but something that takes in a stream of transaction requests\nDialogue: 0,0:49:45.87,0:49:48.49,EN,,0,0,0,,like maybe successive deposit announced.\nDialogue: 0,0:49:49.49,0:49:54.94,EN,,0,0,0,,1, 2, 2, 4, those might be successive amounts to deposit.\nDialogue: 0,0:49:55.94,0:50:02.44,EN,,0,0,0,,And then coming out of it is the successive balances 1, 3, 5, 9.\nDialogue: 0,0:50:03.77,0:50:06.14,EN,,0,0,0,,So we think of the bank account not as something that has state,\nDialogue: 0,0:50:06.40,0:50:07.26,EN,,0,0,0,,but something that acts\nDialogue: 0,0:50:08.92,0:50:10.82,EN,,0,0,0,,sort of on the infinite stream of requests.\nDialogue: 0,0:50:10.82,0:50:12.30,EN,,0,0,0,,But remember, we've thrown away time.\nDialogue: 0,0:50:12.37,0:50:14.27,EN,,0,0,0,,So what we can do is if the user's here,\nDialogue: 0,0:50:16.12,0:50:19.13,EN,,0,0,0,,we can have this infinite stream of requests\nDialogue: 0,0:50:19.18,0:50:22.54,EN,,0,0,0,,being generated one at a time coming from the user\nDialogue: 0,0:50:24.06,0:50:26.57,EN,,0,0,0,,and this transaction stream\nDialogue: 0,0:50:26.57,0:50:28.80,EN,,0,0,0,,coming back on a printer being printed one at a time.\nDialogue: 0,0:50:30.01,0:50:31.37,EN,,0,0,0,,And if we drew a little line here,\nDialogue: 0,0:50:32.56,0:50:33.08,EN,,0,0,0,,right there to the user,\nDialogue: 0,0:50:33.28,0:50:34.91,EN,,0,0,0,,the user couldn't tell that this system doesn't have state.\nDialogue: 0,0:50:36.19,0:50:37.71,EN,,0,0,0,,that this system doesn't have state.\nDialogue: 0,0:50:39.56,0:50:41.13,EN,,0,0,0,,It looks just like the other one,\nDialogue: 0,0:50:41.29,0:50:42.46,EN,,0,0,0,,but there's no state in there.\nDialogue: 0,0:50:42.84,0:50:45.87,EN,,0,0,0,,And by the way,\nDialogue: 0,0:50:46.72,0:50:49.47,EN,,0,0,0,,just to show you, here's an actual implementation\nDialogue: 0,0:50:50.52,0:50:52.30,EN,,0,0,0,,of this-- we'll call it make deposit account\nDialogue: 0,0:50:52.32,0:50:53.32,EN,,0,0,0,,because you can only deposit.\nDialogue: 0,0:50:54.17,0:50:55.77,EN,,0,0,0,,It takes an initial balance\nDialogue: 0,0:50:56.09,0:50:58.09,EN,,0,0,0,,and then a stream of deposits you might make.\nDialogue: 0,0:51:00.02,0:51:00.82,EN,,0,0,0,,And what is it?\nDialogue: 0,0:51:00.82,0:51:02.54,EN,,0,0,0,,Well, it's just cons-stream of the balance\nDialogue: 0,0:51:03.23,0:51:05.31,EN,,0,0,0,,onto make a new account stream\nDialogue: 0,0:51:06.24,0:51:07.32,EN,,0,0,0,,whose initial balance\nDialogue: 0,0:51:07.48,0:51:10.27,EN,,0,0,0,,is the old balance plus the first thing in the deposit stream\nDialogue: 0,0:51:10.86,0:51:13.40,EN,,0,0,0,,whose rest, right and,\nDialogue: 0,0:51:13.76,0:51:17.37,EN,,0,0,0,,make deposit account works on the rest of which is the tail of the deposit stream.\nDialogue: 0,0:51:18.30,0:51:23.84,EN,,0,0,0,,So there's sort of a very typical message-passing,\nDialogue: 0,0:51:23.95,0:51:27.55,EN,,0,0,0,,message-passing, object-oriented thing that's done without side effects at all.\nDialogue: 0,0:51:29.05,0:51:30.76,EN,,0,0,0,,There are very many things you can do this way.\nDialogue: 0,0:51:32.25,0:51:35.23,EN,,0,0,0,,Well, can you do everything without assignment?\nDialogue: 0,0:51:36.40,0:51:39.00,EN,,0,0,0,,Can everybody go over to purely functional languages?\nDialogue: 0,0:51:40.05,0:51:42.04,EN,,0,0,0,,Well, we don't know,\nDialogue: 0,0:51:42.27,0:51:43.44,EN,,0,0,0,,but there seem to be places\nDialogue: 0,0:51:43.92,0:51:46.03,EN,,0,0,0,,where purely functional programming breaks down.\nDialogue: 0,0:51:48.10,0:51:50.27,EN,,0,0,0,,Where it starts hurting is when you have things like this,\nDialogue: 0,0:51:50.43,0:51:52.32,EN,,0,0,0,,but you also mix it up with\nDialogue: 0,0:51:52.60,0:51:54.27,EN,,0,0,0,,the other things that we had to worry that,\nDialogue: 0,0:51:54.30,0:51:55.64,EN,,0,0,0,,which are objects and sharing\nDialogue: 0,0:51:55.90,0:51:58.52,EN,,0,0,0,,and two independent agents being the same.\nDialogue: 0,0:51:58.85,0:51:59.93,EN,,0,0,0,,So under a typical one,\nDialogue: 0,0:51:59.96,0:52:01.63,EN,,0,0,0,,suppose you want to extend this bank account.\nDialogue: 0,0:52:03.24,0:52:04.27,EN,,0,0,0,,So here's a bank account.\nDialogue: 0,0:52:12.22,0:52:14.75,EN,,0,0,0,,Bank accounts take in a stream of transaction requests\nDialogue: 0,0:52:15.20,0:52:18.44,EN,,0,0,0,,and put out streams of, say, balances or responses to that.\nDialogue: 0,0:52:18.78,0:52:20.16,EN,,0,0,0,,But suppose you want to model the fact\nDialogue: 0,0:52:20.17,0:52:24.36,EN,,0,0,0,,that this is a joint bank account between two independent people.\nDialogue: 0,0:52:25.68,0:52:28.65,EN,,0,0,0,,Right? I don't know. So suppose there are two people,\nDialogue: 0,0:52:28.97,0:52:30.96,EN,,0,0,0,,say, Bill and Dave,\nDialogue: 0,0:52:31.77,0:52:33.14,EN,,0,0,0,,who have a joint bank account.\nDialogue: 0,0:52:35.96,0:52:36.85,EN,,0,0,0,,How would you model this?\nDialogue: 0,0:52:36.88,0:52:39.80,EN,,0,0,0,,Well, you might, Bill puts out a stream of transaction requests,\nDialogue: 0,0:52:40.24,0:52:42.25,EN,,0,0,0,,and Dave puts out a stream of transaction requests,\nDialogue: 0,0:52:42.25,0:52:45.16,EN,,0,0,0,,and somehow, they have to merge into this bank account.\nDialogue: 0,0:52:45.88,0:52:47.85,EN,,0,0,0,,So what you might do is write a little stream\nDialogue: 0,0:52:47.90,0:52:50.65,EN,,0,0,0,,processing thing called merge,\nDialogue: 0,0:52:57.23,0:52:59.13,EN,,0,0,0,,which sort of takes these, merges them together,\nDialogue: 0,0:52:59.34,0:53:01.19,EN,,0,0,0,,produces a single stream for the bank account.\nDialogue: 0,0:53:01.19,0:53:02.99,EN,,0,0,0,,Now they're both talking to the same bank account.\nDialogue: 0,0:53:03.61,0:53:05.48,EN,,0,0,0,,That's all great, but how do you write merge?\nDialogue: 0,0:53:05.93,0:53:08.24,EN,,0,0,0,,What, What's this procedure merge?\nDialogue: 0,0:53:09.73,0:53:11.42,EN,,0,0,0,,You want to do something that's reasonable.\nDialogue: 0,0:53:12.38,0:53:13.80,EN,,0,0,0,,Your first guess might be to say,\nDialogue: 0,0:53:13.80,0:53:16.68,EN,,0,0,0,,well, we'll take alternate requests from Bill and Dave.\nDialogue: 0,0:53:18.19,0:53:20.97,EN,,0,0,0,,But what happens if But what happens if suddenly in the middle thing\nDialogue: 0,0:53:21.18,0:53:23.08,EN,,0,0,0,,Dave goes away on vacation for two years?\nDialogue: 0,0:53:24.15,0:53:25.40,EN,,0,0,0,,Then Bill's sort of stuck.\nDialogue: 0,0:53:27.69,0:53:29.75,EN,,0,0,0,,So what you want to do is-- well, it's hard to describe.\nDialogue: 0,0:53:29.75,0:53:33.64,EN,,0,0,0,,What you want to do is what people call fair merge.\nDialogue: 0,0:53:38.41,0:53:40.17,EN,,0,0,0,,The idea of fair merge is\nDialogue: 0,0:53:40.73,0:53:42.46,EN,,0,0,0,,is it sort of should do them alternately,\nDialogue: 0,0:53:42.49,0:53:43.92,EN,,0,0,0,,but if there's nothing waiting here,\nDialogue: 0,0:53:43.96,0:53:44.91,EN,,0,0,0,,it should take one twice.\nDialogue: 0,0:53:46.01,0:53:48.45,EN,,0,0,0,,Notice I can't even say that without talking about time.\nDialogue: 0,0:53:51.30,0:53:56.41,EN,,0,0,0,,So one of the other active researcher areas in functional languages\nDialogue: 0,0:53:56.43,0:53:59.48,EN,,0,0,0,,is inventing little things like fair merge\nDialogue: 0,0:54:00.35,0:54:01.31,EN,,0,0,0,,maybe some others,\nDialogue: 0,0:54:01.56,0:54:06.25,EN,,0,0,0,,which will take the places where I used to need side effects and objects\nDialogue: 0,0:54:06.80,0:54:10.52,EN,,0,0,0,,and sort of hide them away in some very well-defined modules of the system\nDialogue: 0,0:54:10.86,0:54:13.50,EN,,0,0,0,,so that all the problems of assignment\nDialogue: 0,0:54:13.52,0:54:15.34,EN,,0,0,0,,don't sort of leak out all over the system but\nDialogue: 0,0:54:15.40,0:54:17.88,EN,,0,0,0,,are captured in some fairly well-understood things.\nDialogue: 0,0:54:20.78,0:54:22.70,EN,,0,0,0,,More generally, I think what you're seeing\nDialogue: 0,0:54:23.12,0:54:24.06,EN,,0,0,0,,is that we're running across\nDialogue: 0,0:54:24.08,0:54:26.67,EN,,0,0,0,,what I think is a very basic problem in computer science,\nDialogue: 0,0:54:26.97,0:54:27.82,EN,,0,0,0,,which is how to\nDialogue: 0,0:54:28.24,0:54:32.03,EN,,0,0,0,,how to define languages that somehow can talk about delayed evaluation\nDialogue: 0,0:54:34.14,0:54:35.08,EN,,0,0,0,,But also\nDialogue: 0,0:54:35.87,0:54:38.25,EN,,0,0,0,,be able to reflect this view that there are objects in the world.\nDialogue: 0,0:54:38.36,0:54:40.36,EN,,0,0,0,,How do we somehow get both?\nDialogue: 0,0:54:41.23,0:54:43.04,EN,,0,0,0,,And I think that's a very hard problem.\nDialogue: 0,0:54:43.04,0:54:45.52,EN,,0,0,0,,And it may be that it's a very hard problem\nDialogue: 0,0:54:45.85,0:54:48.17,EN,,0,0,0,,that has almost nothing to do with computer science,\nDialogue: 0,0:54:48.59,0:54:50.24,EN,,0,0,0,,that it really is a problem having to do with\nDialogue: 0,0:54:50.27,0:54:52.73,EN,,0,0,0,,two very incompatible ways of looking at the world.\nDialogue: 0,0:54:54.14,0:54:54.72,EN,,0,0,0,,OK, questions?\nDialogue: 0,0:55:17.55,0:55:19.20,EN,,0,0,0,,AUDIENCE: You mentioned earlier that\nDialogue: 0,0:55:20.11,0:55:21.32,EN,,0,0,0,,once you introduce assignment,\nDialogue: 0,0:55:21.32,0:55:25.89,EN,,0,0,0,,the general rule for using the substitution model is you can't.\nDialogue: 0,0:55:25.89,0:55:27.57,EN,,0,0,0,,Unless you're very careful, you can't.\nDialogue: 0,0:55:27.57,0:55:27.96,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:55:28.26,0:55:33.28,EN,,0,0,0,,AUDIENCE: Is there a set of techniques or a set of guidelines\nDialogue: 0,0:55:33.42,0:55:35.92,EN,,0,0,0,,for localizing the effects of assignment\nDialogue: 0,0:55:36.52,0:55:40.30,EN,,0,0,0,,so that the very careful becomes defined?\nDialogue: 0,0:55:40.30,0:55:42.60,EN,,0,0,0,,PROFESSOR: I don't know. Um...\nDialogue: 0,0:55:42.89,0:55:43.58,EN,,0,0,0,,Let me think.\nDialogue: 0,0:55:45.43,0:55:48.94,EN,,0,0,0,,Well, certainly, there was an assignment inside memo proc,\nDialogue: 0,0:55:50.12,0:55:51.48,EN,,0,0,0,,but that was sort of hidden away.\nDialogue: 0,0:55:51.48,0:55:53.00,EN,,0,0,0,,It ended up not making any difference.\nDialogue: 0,0:55:53.48,0:55:56.44,EN,,0,0,0,,Part of the reason for that is once this thing triggered\nDialogue: 0,0:55:57.15,0:55:58.83,EN,,0,0,0,,that it had run and gotten an answer,\nDialogue: 0,0:55:58.83,0:56:00.06,EN,,0,0,0,,that answer will never change.\nDialogue: 0,0:56:00.60,0:56:02.33,EN,,0,0,0,,So that was sort of a one-time assignment.\nDialogue: 0,0:56:02.35,0:56:03.85,EN,,0,0,0,,So one very general thing you can do\nDialogue: 0,0:56:04.30,0:56:06.35,EN,,0,0,0,,is if you only do what's called a one-time assignment\nDialogue: 0,0:56:08.04,0:56:09.24,EN,,0,0,0,,and never change anything,\nDialogue: 0,0:56:09.63,0:56:10.54,EN,,0,0,0,,then you can do better.\nDialogue: 0,0:56:11.25,0:56:14.12,EN,,0,0,0,,One of the problems in this merge thing, people have--\nDialogue: 0,0:56:14.67,0:56:18.32,EN,,0,0,0,,people have-- let me see if this is right.\nDialogue: 0,0:56:18.49,0:56:21.55,EN,,0,0,0,,I think it's true that with fair merge,\nDialogue: 0,0:56:22.25,0:56:26.09,EN,,0,0,0,,with just fair merge, you can begin effectively simulating\nDialogue: 0,0:56:27.02,0:56:28.89,EN,,0,0,0,,assignment in the rest of the language.\nDialogue: 0,0:56:30.82,0:56:33.29,EN,,0,0,0,,It seems like anything you do to go outside--\nDialogue: 0,0:56:33.50,0:56:35.50,EN,,0,0,0,,I'm not quite sure that's true for fair merge,\nDialogue: 0,0:56:35.53,0:56:39.31,EN,,0,0,0,,but it's true of a little bit more general things that people have been doing.\nDialogue: 0,0:56:39.52,0:56:41.34,EN,,0,0,0,,So it might be that any little bit you put in,\nDialogue: 0,0:56:41.61,0:56:44.14,EN,,0,0,0,,suddenly if they allow you to build arbitrary stuff,\nDialogue: 0,0:56:44.16,0:56:46.51,EN,,0,0,0,,it's almost as bad as having assignment altogether.\nDialogue: 0,0:56:47.97,0:56:50.67,EN,,0,0,0,,But that's an area that people are thinking about now.\nDialogue: 0,0:56:51.59,0:56:54.30,EN,,0,0,0,,AUDIENCE: I guess I don't see the problem here with merge\nDialogue: 0,0:56:54.83,0:56:59.20,EN,,0,0,0,,if, you know the sense, I call Bill, if Bill is a procedure,\nDialogue: 0,0:56:59.21,0:57:02.41,EN,,0,0,0,,then Bill is going to increment the bank account\nDialogue: 0,0:57:02.44,0:57:04.73,EN,,0,0,0,,or build the list that 's going to put in the next element.\nDialogue: 0,0:57:04.73,0:57:06.84,EN,,0,0,0,,If I call Dave twice in a row, that will do that.\nDialogue: 0,0:57:07.17,0:57:09.35,EN,,0,0,0,,I'm not sure where fair merge has to be involved.\nDialogue: 0,0:57:09.35,0:57:11.20,EN,,0,0,0,,PROFESSOR: The problem is imagine these really as people.\nDialogue: 0,0:57:11.20,0:57:14.20,EN,,0,0,0,,See, here I have the user who's interacting with this bank account.\nDialogue: 0,0:57:14.85,0:57:17.07,EN,,0,0,0,,Put in a request, get an answer. Put in a request, get an answer.\nDialogue: 0,0:57:17.20,0:57:17.56,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:57:18.20,0:57:20.62,EN,,0,0,0,,PROFESSOR: But if the only way I can process request\nDialogue: 0,0:57:20.65,0:57:22.25,EN,,0,0,0,,is to alternate them from two people--\nDialogue: 0,0:57:22.91,0:57:24.22,EN,,0,0,0,,AUDIENCE: Well, why would you alternate them?\nDialogue: 0,0:57:24.22,0:57:25.23,EN,,0,0,0,,PROFESSOR: Why don't I?\nDialogue: 0,0:57:25.45,0:57:25.80,EN,,0,0,0,,AUDIENCE: Yes. Why do you?\nDialogue: 0,0:57:26.60,0:57:27.72,EN,,0,0,0,,PROFESSOR: Think of them as real people, right?\nDialogue: 0,0:57:27.76,0:57:28.97,EN,,0,0,0,,This guy might go away for a year.\nDialogue: 0,0:57:29.28,0:57:31.74,EN,,0,0,0,,And you're sitting here at the bank account window,\nDialogue: 0,0:57:32.43,0:57:33.72,EN,,0,0,0,,and you can't put in two requests\nDialogue: 0,0:57:33.74,0:57:34.94,EN,,0,0,0,,because it's waiting for this guy.\nDialogue: 0,0:57:35.48,0:57:37.07,EN,,0,0,0,,AUDIENCE: Why does it have to be waiting for one?\nDialogue: 0,0:57:37.38,0:57:39.11,EN,,0,0,0,,PROFESSOR: Because it's trying to compute a function.\nDialogue: 0,0:57:39.11,0:57:40.92,EN,,0,0,0,,I have to define a function.\nDialogue: 0,0:57:41.72,0:57:42.60,EN,,0,0,0,,Another way to say that\nDialogue: 0,0:57:42.84,0:57:44.99,EN,,0,0,0,,is the answer to what comes out of this merge box\nDialogue: 0,0:57:46.24,0:57:49.48,EN,,0,0,0,,is not a function of what goes in.\nDialogue: 0,0:57:51.69,0:57:53.49,EN,,0,0,0,,Because, see, what would the function be?\nDialogue: 0,0:57:53.49,0:57:58.86,EN,,0,0,0,,Suppose he puts in 1, 1, 1, 1,\nDialogue: 0,0:57:59.82,0:58:02.78,EN,,0,0,0,,and he puts in 2, 2, 2, 2.\nDialogue: 0,0:58:03.47,0:58:04.80,EN,,0,0,0,,What's the answer supposed to be?\nDialogue: 0,0:58:05.58,0:58:08.74,EN,,0,0,0,,It's not good enough to say it's 1, 2, 1, 2, 1, 2.\nDialogue: 0,0:58:08.74,0:58:09.39,EN,,0,0,0,,AUDIENCE: I understand.\nDialogue: 0,0:58:09.39,0:58:11.56,EN,,0,0,0,,But when Bill puts in 1, 1 goes in.\nDialogue: 0,0:58:11.56,0:58:13.95,EN,,0,0,0,,When Dave puts in 2, twice 2 goes in twice.\nDialogue: 0,0:58:13.95,0:58:14.73,EN,,0,0,0,,AUDIENCE: When Bill puts in--\nDialogue: 0,0:58:14.76,0:58:15.08,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:58:15.13,0:58:18.43,EN,,0,0,0,,AUDIENCE: Why can't it be hooked to the time of the input--\nDialogue: 0,0:58:18.59,0:58:20.06,EN,,0,0,0,,the actual procedural--\nDialogue: 0,0:58:20.12,0:58:21.84,EN,,0,0,0,,PROFESSOR: Because I don't have time.\nDialogue: 0,0:58:23.98,0:58:26.90,EN,,0,0,0,,See, all I can say is I'm going to define a function.\nDialogue: 0,0:58:26.90,0:58:28.15,EN,,0,0,0,,I don't have time.\nDialogue: 0,0:58:32.00,0:58:34.19,EN,,0,0,0,,There's no concept if it's going to alternate,\nDialogue: 0,0:58:34.19,0:58:36.54,EN,,0,0,0,,except if nobody's there, it's going to wait a while for him.\nDialogue: 0,0:58:38.42,0:58:41.36,EN,,0,0,0,,It's just going to say I have the stream of requests,\nDialogue: 0,0:58:41.74,0:58:43.34,EN,,0,0,0,,the timeless infinite streams\nDialogue: 0,0:58:43.36,0:58:45.29,EN,,0,0,0,,of all the requests that Dave would have made, right?\nDialogue: 0,0:58:47.55,0:58:50.41,EN,,0,0,0,,And the timeless infinite stream of all the requests Bill would have made,\nDialogue: 0,0:58:50.54,0:58:51.69,EN,,0,0,0,,and I want to operate on them.\nDialogue: 0,0:58:51.69,0:58:53.51,EN,,0,0,0,,See, that's how this bank account is working.\nDialogue: 0,0:58:56.71,0:58:57.58,EN,,0,0,0,,And the problem is\nDialogue: 0,0:58:57.61,0:59:00.75,EN,,0,0,0,,that these poor people who are sitting at the bank account windows\nDialogue: 0,0:59:00.76,0:59:03.82,EN,,0,0,0,,have the misfortune to exist in time.\nDialogue: 0,0:59:05.29,0:59:07.13,EN,,0,0,0,,They don't see their infinite stream\nDialogue: 0,0:59:07.69,0:59:09.53,EN,,0,0,0,,of all the requests they would have ever made.\nDialogue: 0,0:59:10.07,0:59:11.55,EN,,0,0,0,,They're waiting now, and they want an answer.\nDialogue: 0,0:59:14.48,0:59:15.76,EN,,0,0,0,,So if you're sitting there--\nDialogue: 0,0:59:16.24,0:59:20.86,EN,,0,0,0,,if this is the screen operation on some time-sharing system\nDialogue: 0,0:59:21.52,0:59:22.60,EN,,0,0,0,,and it's working functionally,\nDialogue: 0,0:59:22.64,0:59:24.59,EN,,0,0,0,,you want an answer then when you talk the character.\nDialogue: 0,0:59:25.29,0:59:27.42,EN,,0,0,0,,You don't want it to have to wait for everybody in the whole system\nDialogue: 0,0:59:27.45,0:59:29.92,EN,,0,0,0,,to have typed one character before it can get around to service you.\nDialogue: 0,0:59:30.91,0:59:31.92,EN,,0,0,0,,So that's the problem.\nDialogue: 0,0:59:34.00,0:59:36.38,EN,,0,0,0,,I mean, the fact that people live in time, apparently.\nDialogue: 0,0:59:37.21,0:59:38.62,EN,,0,0,0,,If they didn't, it wouldn't be a problem.\nDialogue: 0,0:59:49.10,0:59:51.02,EN,,0,0,0,,AUDIENCE: I'm afraid I miss the point of\nDialogue: 0,0:59:51.08,0:59:54.24,EN,,0,0,0,,having no time in this banking transaction.\nDialogue: 0,0:59:54.74,0:59:56.65,EN,,0,0,0,,Isn't time very important?\nDialogue: 0,0:59:56.88,0:59:59.05,EN,,0,0,0,,For instance, the sequence of events.\nDialogue: 0,0:59:59.95,1:00:05.02,EN,,0,0,0,,As if, If Dave take out $100, and then\nDialogue: 0,1:00:06.30,1:00:08.40,EN,,0,0,0,,then the timing sequence should be important.\nDialogue: 0,1:00:08.40,1:00:10.86,EN,,0,0,0,,How do you treat transactions as streams?\nDialogue: 0,1:00:11.26,1:00:14.26,EN,,0,0,0,,PROFESSOR: Well, that's the thing I'm saying.\nDialogue: 0,1:00:14.26,1:00:15.61,EN,,0,0,0,,This is an example where you can't.\nDialogue: 0,1:00:17.51,1:00:18.12,EN,,0,0,0,,You can't.\nDialogue: 0,1:00:18.16,1:00:20.08,EN,,0,0,0,,What goes, The point is what comes out of here\nDialogue: 0,1:00:20.24,1:00:21.88,EN,,0,0,0,,is simply not a function of the stream going in here\nDialogue: 0,1:00:21.92,1:00:23.60,EN,,0,0,0,,going in here and the stream going in here.\nDialogue: 0,1:00:24.17,1:00:25.98,EN,,0,0,0,,It's a function of the stream going in here\nDialogue: 0,1:00:26.19,1:00:27.26,EN,,0,0,0,,and the stream going in here\nDialogue: 0,1:00:27.36,1:00:29.07,EN,,0,0,0,,and some kind of information about time,\nDialogue: 0,1:00:29.37,1:00:32.36,EN,,0,0,0,,which is precisely what a normal-order language won't let you say.\nDialogue: 0,1:00:34.81,1:00:37.95,EN,,0,0,0,,AUDIENCE: In order to brings this back into a more functional perspective,\nDialogue: 0,1:00:38.54,1:00:42.04,EN,,0,0,0,,could we just explicitly time stamp all the inputs from Bill and Dave\nDialogue: 0,1:00:42.54,1:00:46.40,EN,,0,0,0,,and define fair merge to just be the sort on those time stamps?\nDialogue: 0,1:00:48.41,1:00:49.55,EN,,0,0,0,,PROFESSOR: Yeah, you can do that.\nDialogue: 0,1:00:49.55,1:00:50.60,EN,,0,0,0,,You can do that sort of thing.\nDialogue: 0,1:00:50.60,1:00:52.56,EN,,0,0,0,,Another thing you could say is imagine\nDialogue: 0,1:00:52.76,1:00:54.44,EN,,0,0,0,,that really what this function is,\nDialogue: 0,1:00:54.78,1:00:56.88,EN,,0,0,0,,is that it does a read every microsecond,\nDialogue: 0,1:00:58.86,1:00:59.93,EN,,0,0,0,,and then if there's none there,\nDialogue: 0,1:00:59.93,1:01:00.97,EN,,0,0,0,,that's considered an empty one.\nDialogue: 0,1:01:00.97,1:01:03.39,EN,,0,0,0,,That's about equivalent to what you said.\nDialogue: 0,1:01:03.61,1:01:06.08,EN,,0,0,0,,And yes, you can do that, but that's a glitch.\nDialogue: 0,1:01:07.11,1:01:10.14,EN,,0,0,0,,So it's not quite only implementation we're worried about.\nDialogue: 0,1:01:10.76,1:01:12.73,EN,,0,0,0,,We're worried about expressive power in the language,\nDialogue: 0,1:01:12.75,1:01:14.67,EN,,0,0,0,,and what we're running across is a real mismatch\nDialogue: 0,1:01:14.99,1:01:17.44,EN,,0,0,0,,between what we can say easily and what we'd like to say.\nDialogue: 0,1:01:19.88,1:01:22.01,EN,,0,0,0,,AUDIENCE: It sounds like where we're getting hung up with that\nDialogue: 0,1:01:22.06,1:01:26.09,EN,,0,0,0,,one input from both Bill and Dave at the same time.\nDialogue: 0,1:01:26.12,1:01:28.43,EN,,0,0,0,,PROFESSOR: It's not quite one, but it's anything you define.\nDialogue: 0,1:01:28.53,1:01:30.57,EN,,0,0,0,,So you can say Dave can go twice as often,\nDialogue: 0,1:01:30.72,1:01:32.32,EN,,0,0,0,,but if anything you predefine,\nDialogue: 0,1:01:32.68,1:01:33.87,EN,,0,0,0,,it's not the right thing.\nDialogue: 0,1:01:36.11,1:01:40.70,EN,,0,0,0,,You can't decide at some particular function of their input requests.\nDialogue: 0,1:01:41.93,1:01:43.37,EN,,0,0,0,,Worse yet, I mean, worse yet,\nDialogue: 0,1:01:44.12,1:01:45.72,EN,,0,0,0,,there are things that even merge can't do.\nDialogue: 0,1:01:47.29,1:01:49.69,EN,,0,0,0,,One thing you might want to do that's even more general is suddenly\nDialogue: 0,1:01:50.24,1:01:52.47,EN,,0,0,0,,you add somebody else to this bank account system.\nDialogue: 0,1:01:52.47,1:01:54.51,EN,,0,0,0,,You go and you add John to this bank account system.\nDialogue: 0,1:01:56.03,1:01:58.89,EN,,0,0,0,,And now there's yet another stream that's going to come into the picture\nDialogue: 0,1:01:58.91,1:02:00.70,EN,,0,0,0,,at some time which we haven't prespecified.\nDialogue: 0,1:02:02.04,1:02:04.00,EN,,0,0,0,,So that's something even fair merge can't do,\nDialogue: 0,1:02:04.00,1:02:08.25,EN,,0,0,0,,and they're things called-- I forget-- manager or something.\nDialogue: 0,1:02:08.86,1:02:11.79,EN,,0,0,0,,That's a generalization of fair merge to allow that.\nDialogue: 0,1:02:11.79,1:02:13.98,EN,,0,0,0,,There's a whole sort of research discipline saying\nDialogue: 0,1:02:14.00,1:02:16.30,EN,,0,0,0,,how far can you push this functional perspective\nDialogue: 0,1:02:16.59,1:02:18.72,EN,,0,0,0,,by adding more and more mechanism?\nDialogue: 0,1:02:19.58,1:02:21.79,EN,,0,0,0,,And how far does that go before the whole thing breaks down\nDialogue: 0,1:02:21.82,1:02:23.40,EN,,0,0,0,,and you might as well been using set anyway.\nDialogue: 0,1:02:25.98,1:02:28.00,EN,,0,0,0,,AUDIENCE: But not automatic deposit.\nDialogue: 0,1:02:39.32,1:02:40.49,EN,,0,0,0,,PROFESSOR: OK, thank you.\nDialogue: 0,0:00:00.03,0:00:03.10,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:04.09,0:00:12.08,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N张大伟\\N（DreamAndDead）\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:12.54,0:00:17.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 II\nDialogue: 0,0:00:20.97,0:00:24.08,Default,,0,0,0,,教授：上节课 我们介绍了流\nDialogue: 0,0:00:24.08,0:00:27.82,Default,,0,0,0,,按照信号处理的方式来组织系统\nDialogue: 0,0:00:28.87,0:00:31.42,Default,,0,0,0,,要记住的是 关键点在于\nDialogue: 0,0:00:31.90,0:00:32.96,Default,,0,0,0,,我们分离开\nDialogue: 0,0:00:34.20,0:00:37.31,Default,,0,0,0,,程序中 事件表面上的顺序\nDialogue: 0,0:00:37.58,0:00:40.17,Default,,0,0,0,,与机器中的实际计算顺序\nDialogue: 0,0:00:41.07,0:00:42.28,Default,,0,0,0,,那就意味着 我们可以\nDialogue: 0,0:00:42.57,0:00:44.14,Default,,0,0,0,,着手处理非常长的流\nDialogue: 0,0:00:44.89,0:00:47.39,Default,,0,0,0,,并且只有在需要的时候才生成其中的元素\nDialogue: 0,0:00:47.53,0:00:49.39,Default,,0,0,0,,这种按需计算的方式\nDialogue: 0,0:00:49.52,0:00:51.40,Default,,0,0,0,,是内建在流的数据结构中的\nDialogue: 0,0:00:54.11,0:00:55.64,Default,,0,0,0,,即使这个流非常之长\nDialogue: 0,0:00:55.66,0:00:57.08,Default,,0,0,0,,我们只计算所需要的\nDialogue: 0,0:00:58.04,0:01:00.75,Default,,0,0,0,,只有当我们要求的时候 新的数据才会生成\nDialogue: 0,0:01:00.75,0:01:01.74,Default,,0,0,0,,要举个什么样的例子呢？\nDialogue: 0,0:01:02.11,0:01:03.60,Default,,0,0,0,,这个“按需”是什么个情况呢？\nDialogue: 0,0:01:05.02,0:01:06.01,Default,,0,0,0,,举个例子\nDialogue: 0,0:01:09.21,0:01:11.37,Default,,0,0,0,,我们可能会想要一个流中的第N个元素\nDialogue: 0,0:01:15.36,0:01:18.92,Default,,0,0,0,,这个过程可以用于计算流的第N个元素\nDialogue: 0,0:01:20.09,0:01:21.23,Default,,0,0,0,,一个参数为索引N\nDialogue: 0,0:01:21.24,0:01:22.84,Default,,0,0,0,,另一个参数是流S\nDialogue: 0,0:01:23.40,0:01:25.42,Default,,0,0,0,,递归遍历这个流即可求解\nDialogue: 0,0:01:25.57,0:01:27.39,Default,,0,0,0,,如果N为0 我们就计算头部分\nDialogue: 0,0:01:27.96,0:01:30.99,Default,,0,0,0,,否则 就在流的尾部分\nDialogue: 0,0:01:31.74,0:01:32.80,Default,,0,0,0,,查找第N-1个元素\nDialogue: 0,0:01:34.31,0:01:36.43,Default,,0,0,0,,看起来是Lisp中很普通的编程方式 但是不同的是\nDialogue: 0,0:01:36.62,0:01:38.76,Default,,0,0,0,,直到我们不断遍历 取得相继的N个元素\nDialogue: 0,0:01:38.86,0:01:40.99,Default,,0,0,0,,这些元素才被计算出来\nDialogue: 0,0:01:41.52,0:01:44.78,Default,,0,0,0,,这是这些流元素可能被FORCE的一种方式\nDialogue: 0,0:01:45.77,0:01:46.64,Default,,0,0,0,,另外一种方式则是\nDialogue: 0,0:01:47.18,0:01:48.92,Default,,0,0,0,,这里有个简单的过程 用来打印一个流\nDialogue: 0,0:01:49.30,0:01:50.38,Default,,0,0,0,,它的定义是\nDialogue: 0,0:01:51.90,0:01:53.28,Default,,0,0,0,,过程PRINT-STREAM的定义是\nDialogue: 0,0:01:54.15,0:01:55.12,Default,,0,0,0,,我们要怎么做呢？\nDialogue: 0,0:01:55.74,0:01:56.86,Default,,0,0,0,,先打印流的头部分\nDialogue: 0,0:01:57.74,0:01:59.32,Default,,0,0,0,,流的头部分在这时就被计算出来\nDialogue: 0,0:01:59.72,0:02:02.84,Default,,0,0,0,,然后我们再递归地打印流的尾部分\nDialogue: 0,0:02:04.99,0:02:06.03,Default,,0,0,0,,完成以后\nDialogue: 0,0:02:06.04,0:02:08.57,Default,,0,0,0,,就返回一个的表示完成的消息 “DONE”\nDialogue: 0,0:02:09.66,0:02:11.39,Default,,0,0,0,,如果你构造了一个流\nDialogue: 0,0:02:11.64,0:02:13.64,Default,,0,0,0,,这个流非常的长\nDialogue: 0,0:02:14.31,0:02:16.33,Default,,0,0,0,,当你调用这个过程\nDialogue: 0,0:02:16.41,0:02:19.77,Default,,0,0,0,,流中的元素会随着PRINT-STREAM的调用\nDialogue: 0,0:02:19.87,0:02:21.12,Default,,0,0,0,,而被依次计算出来\nDialogue: 0,0:02:21.32,0:02:22.81,Default,,0,0,0,,不会在一开始就全部计算出来\nDialogue: 0,0:02:24.30,0:02:25.66,Default,,0,0,0,,正因为如此 我们能够\nDialogue: 0,0:02:27.50,0:02:29.61,Default,,0,0,0,,我们能够处理非常长的流\nDialogue: 0,0:02:30.19,0:02:31.92,Default,,0,0,0,,多长呢？\nDialogue: 0,0:02:33.74,0:02:35.12,Default,,0,0,0,,可以是无限长\nDialogue: 0,0:02:35.90,0:02:38.04,Default,,0,0,0,,我们在计算机上实践一下\nDialogue: 0,0:02:38.92,0:02:41.96,Default,,0,0,0,,我可以在计算机前输入\nDialogue: 0,0:02:43.48,0:02:53.31,Default,,0,0,0,,我先定义一个函数 (INTEGERS-FROM N)\nDialogue: 0,0:02:54.24,0:02:57.13,Default,,0,0,0,,用于生成一个从N开始的正整数流\nDialogue: 0,0:03:00.36,0:03:19.16,Default,,0,0,0,,也就是 (CONS-STREAM N (INTEGERS-FROM (+ N 1))))\nDialogue: 0,0:03:24.41,0:03:25.61,Default,,0,0,0,,这样就我们要的全部整数\nDialogue: 0,0:03:28.99,0:03:31.50,Default,,0,0,0,,现在我来尝试得到所有的整数\nDialogue: 0,0:03:34.57,0:03:44.33,Default,,0,0,0,,(DEFINE INTEGERS (INTEGERS-FROM 1))\nDialogue: 0,0:03:48.84,0:03:50.94,Default,,0,0,0,,如果现在我执行 (NTH-STREAM 20 INTEGERS)\nDialogue: 0,0:03:54.41,0:03:55.80,Default,,0,0,0,,来查看第20个元素\nDialogue: 0,0:04:03.42,0:04:05.53,Default,,0,0,0,,得到21 因为索引是从0开始的\nDialogue: 0,0:04:06.84,0:04:08.88,Default,,0,0,0,,或者我们来点更复杂的\nDialogue: 0,0:04:09.45,0:04:10.84,Default,,0,0,0,,我再来定义一个谓词\nDialogue: 0,0:04:11.77,0:04:18.51,Default,,0,0,0,,谓词NO-SEVEN用来检测是否为7的倍数\nDialogue: 0,0:04:19.58,0:04:20.75,Default,,0,0,0,,它的判定方法是这样的：\nDialogue: 0,0:04:21.79,0:04:23.16,Default,,0,0,0,,如果整数X不是7的倍数\nDialogue: 0,0:04:28.82,0:04:33.96,Default,,0,0,0,,我取X除7的余数\nDialogue: 0,0:04:36.62,0:04:38.35,Default,,0,0,0,,余数不应该为0\nDialogue: 0,0:04:43.80,0:04:49.77,Default,,0,0,0,,这时用NO-SEVEN这个谓词\nDialogue: 0,0:04:50.22,0:04:59.12,Default,,0,0,0,,过滤全部的整数\nDialogue: 0,0:05:11.57,0:05:13.34,Default,,0,0,0,,这样我就得到了所有的\nDialogue: 0,0:05:13.63,0:05:15.05,Default,,0,0,0,,不是7的倍数的整数构成的流\nDialogue: 0,0:05:16.49,0:05:23.44,Default,,0,0,0,,如果我问 这些不是7的倍数的整数中\nDialogue: 0,0:05:24.70,0:05:26.48,Default,,0,0,0,,的第100个数是多少？\nDialogue: 0,0:05:26.86,0:05:28.11,Default,,0,0,0,,结果是117\nDialogue: 0,0:05:28.32,0:05:30.67,Default,,0,0,0,,或者我也可以问\nDialogue: 0,0:05:32.30,0:05:34.38,Default,,0,0,0,,这个流的所有元素都是些什么？\nDialogue: 0,0:05:35.27,0:05:40.35,Default,,0,0,0,,我可以用(PRINT-STREAM NS)来尝试打印这个流\nDialogue: 0,0:05:40.83,0:05:41.79,Default,,0,0,0,,它就会输出个不停\nDialogue: 0,0:05:45.10,0:05:47.07,Default,,0,0,0,,你可能需要等上很久才能得到全部结果\nDialogue: 0,0:05:52.67,0:05:53.84,Default,,0,0,0,,你可能会问了\nDialogue: 0,0:05:54.81,0:05:57.00,Default,,0,0,0,,这个数据结构\nDialogue: 0,0:05:58.28,0:06:00.65,Default,,0,0,0,,真的全部是由整数构成的吗？\nDialogue: 0,0:06:01.10,0:06:04.05,Default,,0,0,0,,现在我画一个图来演示下刚写的那个程序\nDialogue: 0,0:06:04.96,0:06:10.57,Default,,0,0,0,,这是我刚才键入的整数定义\nDialogue: 0,0:06:12.33,0:06:15.98,Default,,0,0,0,,它是一个由第一个整数和由下一个整数生成的流 所构成的序对\nDialogue: 0,0:06:17.61,0:06:19.77,Default,,0,0,0,,现在我们画个图来看看它到底是什么样\nDialogue: 0,0:06:22.72,0:06:24.32,Default,,0,0,0,,从概念上来说 这应该是一个盒子\nDialogue: 0,0:06:25.53,0:06:27.18,Default,,0,0,0,,这个盒子是(INTEGER-FROM N)\nDialogue: 0,0:06:27.42,0:06:29.08,Default,,0,0,0,,它接受一个参数N\nDialogue: 0,0:06:31.42,0:06:32.97,Default,,0,0,0,,然后返回一个流\nDialogue: 0,0:06:35.02,0:06:37.36,Default,,0,0,0,,这个无穷流表示从N开始的所有整数\nDialogue: 0,0:06:38.08,0:06:38.73,Default,,0,0,0,,我要做什么呢？\nDialogue: 0,0:06:38.75,0:06:42.38,Default,,0,0,0,,呃 这个是INT-FROM盒子\nDialogue: 0,0:06:45.07,0:06:45.80,Default,,0,0,0,,里面是什么样子呢？\nDialogue: 0,0:06:45.80,0:06:48.60,Default,,0,0,0,,取得参数N之后\nDialogue: 0,0:06:52.27,0:06:53.92,Default,,0,0,0,,将其 +1\nDialogue: 0,0:06:57.95,0:07:03.15,Default,,0,0,0,,然后把结果递归地传递给另一个INT-FROM盒子\nDialogue: 0,0:07:06.87,0:07:09.60,Default,,0,0,0,,把这个盒子的结果和最初的N\nDialogue: 0,0:07:10.24,0:07:12.78,Default,,0,0,0,,用CONS组合起来\nDialogue: 0,0:07:13.39,0:07:14.36,Default,,0,0,0,,就形成了一个流\nDialogue: 0,0:07:14.57,0:07:17.26,Default,,0,0,0,,我刚才写的那个过程 画出来就是这样子\nDialogue: 0,0:07:18.52,0:07:20.32,Default,,0,0,0,,我们看到的这类图像\nDialogue: 0,0:07:20.78,0:07:21.74,Default,,0,0,0,,首先是由Peter Henderson提出的\nDialogue: 0,0:07:21.76,0:07:23.32,Default,,0,0,0,,也就是前面课程中绘图语言的发明者\nDialogue: 0,0:07:23.32,0:07:24.75,Default,,0,0,0,,我们把这种图叫做Henderson图\nDialogue: 0,0:07:25.37,0:07:27.90,Default,,0,0,0,,画这种图需要遵守一定的约定\nDialogue: 0,0:07:28.53,0:07:32.51,Default,,0,0,0,,这些实线代表输出的流\nDialogue: 0,0:07:33.02,0:07:36.20,Default,,0,0,0,,这些虚线则是初始的输入值\nDialogue: 0,0:07:37.27,0:07:39.02,Default,,0,0,0,,而这个图描述的形状是——\nDialogue: 0,0:07:39.40,0:07:41.60,Default,,0,0,0,,它会取一个整数作为初始值\nDialogue: 0,0:07:41.80,0:07:42.91,Default,,0,0,0,,然后输出一个流\nDialogue: 0,0:07:46.35,0:07:48.22,Default,,0,0,0,,现在 你可能又要问了\nDialogue: 0,0:07:48.38,0:07:50.88,Default,,0,0,0,,那个INTEGERS的数据结构真的全部都是整数吗？\nDialogue: 0,0:07:52.09,0:07:54.91,Default,,0,0,0,,或者它只是经过了精心组织\nDialogue: 0,0:07:54.94,0:07:56.43,Default,,0,0,0,,以至于总可以在其中找到\nDialogue: 0,0:07:56.44,0:07:57.24,Default,,0,0,0,,我们需要的那个整数？\nDialogue: 0,0:07:57.95,0:07:59.74,Default,,0,0,0,,这有点像个哲学问题 不是么？\nDialogue: 0,0:07:59.78,0:08:01.69,Default,,0,0,0,,如果有一个东西\nDialogue: 0,0:08:02.14,0:08:03.96,Default,,0,0,0,,你不去观测它 能否知道它“存在”呢？\nDialogue: 0,0:08:04.45,0:08:07.34,Default,,0,0,0,,这就有点像\nDialogue: 0,0:08:07.36,0:08:09.42,Default,,0,0,0,,你在银行中的存款那样\nDialogue: 0,0:08:12.38,0:08:12.64,Default,,0,0,0,,好吧\nDialogue: 0,0:08:16.35,0:08:17.48,Default,,0,0,0,,我们再来看一个例子\nDialogue: 0,0:08:18.68,0:08:20.70,Default,,0,0,0,,这门课的第一节课\nDialogue: 0,0:08:20.72,0:08:22.72,Default,,0,0,0,,我们就讲了一个来自于亚历山大的算法\nDialogue: 0,0:08:23.29,0:08:25.80,Default,,0,0,0,,来自亚历山大的Heron提出的\nDialogue: 0,0:08:25.82,0:08:26.94,Default,,0,0,0,,一个用于计算平方根的算法\nDialogue: 0,0:08:28.47,0:08:32.03,Default,,0,0,0,,现在再来看一个 同样来自于亚力山大的算法\nDialogue: 0,0:08:32.03,0:08:35.08,Default,,0,0,0,,这个被称为Eratosthenes算法的方法\nDialogue: 0,0:08:36.19,0:08:38.44,Default,,0,0,0,,用于计算所有的质数\nDialogue: 0,0:08:41.16,0:08:42.83,Default,,0,0,0,,它被称为Eratosthenes筛法\nDialogue: 0,0:08:42.83,0:08:49.72,Default,,0,0,0,,它是这样的 一开始\nDialogue: 0,0:08:50.99,0:08:52.28,Default,,0,0,0,,先列举所有的整数\nDialogue: 0,0:08:52.60,0:08:53.53,Default,,0,0,0,,从2开始\nDialogue: 0,0:08:53.88,0:08:55.04,Default,,0,0,0,,然后取第一个整数\nDialogue: 0,0:08:55.08,0:08:56.67,Default,,0,0,0,,然后你发现 哦 2是一个质数\nDialogue: 0,0:08:57.31,0:08:58.35,Default,,0,0,0,,然后你考察剩余的整数\nDialogue: 0,0:08:58.68,0:09:00.88,Default,,0,0,0,,划掉其中可以被2整除的数\nDialogue: 0,0:09:01.52,0:09:04.73,Default,,0,0,0,,我把这个划掉 还有这个 这个\nDialogue: 0,0:09:05.25,0:09:06.35,Default,,0,0,0,,有点费时\nDialogue: 0,0:09:06.36,0:09:08.91,Default,,0,0,0,,我要对所有的整数进行这样的操作\nDialogue: 0,0:09:11.16,0:09:15.39,Default,,0,0,0,,我遍历整个整数表\nDialogue: 0,0:09:18.27,0:09:20.94,Default,,0,0,0,,划掉所有被2整除的数\nDialogue: 0,0:09:22.11,0:09:24.38,Default,,0,0,0,,所有的整数都操作完后\nDialogue: 0,0:09:24.78,0:09:26.72,Default,,0,0,0,,回过头再来看还剩些什么\nDialogue: 0,0:09:27.04,0:09:28.80,Default,,0,0,0,,好的 下一个数就是3了\nDialogue: 0,0:09:29.33,0:09:30.33,Default,,0,0,0,,3也是一个质数\nDialogue: 0,0:09:30.77,0:09:33.05,Default,,0,0,0,,现在 我会继续在剩下的数中\nDialogue: 0,0:09:33.36,0:09:35.07,Default,,0,0,0,,划掉所有被3整除的数\nDialogue: 0,0:09:35.08,0:09:43.80,Default,,0,0,0,,划掉 9、15、21、27、33 等等\nDialogue: 0,0:09:44.33,0:09:45.12,Default,,0,0,0,,我就不往下划了\nDialogue: 0,0:09:45.35,0:09:46.52,Default,,0,0,0,,然后看看我们还剩下什么\nDialogue: 0,0:09:47.25,0:09:49.84,Default,,0,0,0,,而下一个就是5了\nDialogue: 0,0:09:50.49,0:09:52.04,Default,,0,0,0,,我又遍历剩下的数\nDialogue: 0,0:09:52.43,0:09:54.51,Default,,0,0,0,,找到第一个能被5整除的数\nDialogue: 0,0:09:54.54,0:09:57.61,Default,,0,0,0,,把剩下的能被5整除的数都划掉\nDialogue: 0,0:09:58.35,0:09:59.24,Default,,0,0,0,,做完这个之后\nDialogue: 0,0:09:59.82,0:10:01.89,Default,,0,0,0,,下一个数就是7\nDialogue: 0,0:10:01.89,0:10:02.72,Default,,0,0,0,,再遍历剩下的数\nDialogue: 0,0:10:02.76,0:10:03.95,Default,,0,0,0,,划掉所有被7整除的数\nDialogue: 0,0:10:03.98,0:10:05.47,Default,,0,0,0,,然后一直这样下去\nDialogue: 0,0:10:06.81,0:10:07.40,Default,,0,0,0,,全部结束的时候\nDialogue: 0,0:10:07.40,0:10:09.10,Default,,0,0,0,,我也就得到了所有的质数\nDialogue: 0,0:10:09.90,0:10:13.31,Default,,0,0,0,,这就是Eratosthenes筛法\nDialogue: 0,0:10:15.43,0:10:17.69,Default,,0,0,0,,我们来看下实际代码\nDialogue: 0,0:10:17.93,0:10:19.85,Default,,0,0,0,,这个过程命名为SIEVE\nDialogue: 0,0:10:27.91,0:10:29.40,Default,,0,0,0,,这是对应的代码\nDialogue: 0,0:10:30.33,0:10:34.48,Default,,0,0,0,,SIEVE过程 以一个流S为参数\nDialogue: 0,0:10:38.77,0:10:39.93,Default,,0,0,0,,返回一个新的流\nDialogue: 0,0:10:40.27,0:10:41.84,Default,,0,0,0,,新的流的头部分 就是流S的头部分\nDialogue: 0,0:10:41.87,0:10:44.43,Default,,0,0,0,,回忆一下 我总是取剩下的数中的第一个\nDialogue: 0,0:10:44.91,0:10:48.75,Default,,0,0,0,,而尾部分则是把流S的尾部分\nDialogue: 0,0:10:51.08,0:10:53.72,Default,,0,0,0,,过滤掉所有\nDialogue: 0,0:10:53.74,0:10:55.32,Default,,0,0,0,,能被S头部分整除的数\nDialogue: 0,0:10:56.41,0:10:57.56,Default,,0,0,0,,然后再对结果筛选\nDialogue: 0,0:10:59.02,0:11:00.09,Default,,0,0,0,,这个代码就是这样\nDialogue: 0,0:11:01.98,0:11:04.68,Default,,0,0,0,,现在 为了得到由质数构成的无穷流\nDialogue: 0,0:11:05.02,0:11:06.90,Default,,0,0,0,,我们对从2开始的整数流进行SIEVE\nDialogue: 0,0:11:14.92,0:11:15.56,Default,,0,0,0,,我们来实践一下\nDialogue: 0,0:11:16.30,0:11:18.30,Default,,0,0,0,,实际上 我们可以在计算机中运行\nDialogue: 0,0:11:19.76,0:11:22.12,Default,,0,0,0,,我希望我已经预先输入过SIEVE的定义了\nDialogue: 0,0:11:22.86,0:11:24.06,Default,,0,0,0,,所以我可以定义\nDialogue: 0,0:11:24.92,0:11:33.45,Default,,0,0,0,,我可以把PRIMES定义为\nDialogue: 0,0:11:34.64,0:11:41.45,Default,,0,0,0,,(SIEVE (INTEGERS-FROM 2))\nDialogue: 0,0:11:46.76,0:11:48.10,Default,,0,0,0,,现在我就得到了质数构成的表\nDialogue: 0,0:11:48.10,0:11:50.99,Default,,0,0,0,,这样就得到了所有的质数 对吧？\nDialogue: 0,0:11:50.99,0:11:53.52,Default,,0,0,0,,比如我可以问 第20个质数是什么？\nDialogue: 0,0:12:00.73,0:12:01.68,Default,,0,0,0,,结果是73\nDialogue: 0,0:12:02.54,0:12:03.34,Default,,0,0,0,,那个短促的停顿\nDialogue: 0,0:12:03.36,0:12:04.92,Default,,0,0,0,,这是因为\nDialogue: 0,0:12:04.94,0:12:06.43,Default,,0,0,0,,在我询问第20个元素时\nDialogue: 0,0:12:06.46,0:12:07.68,Default,,0,0,0,,它才进行实际的计算\nDialogue: 0,0:12:10.37,0:12:11.29,Default,,0,0,0,,在这里 我也可以要求\nDialogue: 0,0:12:13.80,0:12:14.88,Default,,0,0,0,,打印所有的质数\nDialogue: 0,0:12:22.64,0:12:24.40,Default,,0,0,0,,解释器就开始计算并打印所有的质数\nDialogue: 0,0:12:25.35,0:12:26.28,Default,,0,0,0,,得花上好一会儿\nDialogue: 0,0:12:26.28,0:12:27.61,Default,,0,0,0,,才能打赢完整\nDialogue: 0,0:12:27.79,0:12:28.57,Default,,0,0,0,,所以先把它停掉\nDialogue: 0,0:12:32.03,0:12:33.13,Default,,0,0,0,,让我来画图演示一下\nDialogue: 0,0:12:33.13,0:12:34.17,Default,,0,0,0,,我已经画好了\nDialogue: 0,0:12:34.89,0:12:36.19,Default,,0,0,0,,这个过程的图形应该是什么样子呢？\nDialogue: 0,0:12:37.90,0:12:39.77,Default,,0,0,0,,用这类图形的约定来说\nDialogue: 0,0:12:39.82,0:12:40.54,Default,,0,0,0,,我有一个叫SIEVE的盒子\nDialogue: 0,0:12:42.61,0:12:43.56,Default,,0,0,0,,它是如何运作的呢？\nDialogue: 0,0:12:43.56,0:12:44.81,Default,,0,0,0,,它以一个流作为输入\nDialogue: 0,0:12:48.85,0:12:50.59,Default,,0,0,0,,分离流的头、尾部分\nDialogue: 0,0:12:50.87,0:12:53.26,Default,,0,0,0,,从SIEVE盒子出来的第一个东西\nDialogue: 0,0:12:53.48,0:12:54.97,Default,,0,0,0,,就是原来流的头部分\nDialogue: 0,0:12:58.20,0:13:00.92,Default,,0,0,0,,头部分同样也用于这个盒子\nDialogue: 0,0:13:02.55,0:13:05.10,Default,,0,0,0,,这个盒子会过滤流的尾部分\nDialogue: 0,0:13:05.55,0:13:08.33,Default,,0,0,0,,过滤的依据是 能否被头部分整除\nDialogue: 0,0:13:09.53,0:13:11.18,Default,,0,0,0,,过滤得到的不可整除的那些数\nDialogue: 0,0:13:11.24,0:13:13.12,Default,,0,0,0,,再放入另一个SIEVE盒子\nDialogue: 0,0:13:13.90,0:13:15.13,Default,,0,0,0,,然后把它们组合输出\nDialogue: 0,0:13:15.13,0:13:16.89,Default,,0,0,0,,你可以把SIEVE想象为一个过滤器\nDialogue: 0,0:13:17.20,0:13:19.23,Default,,0,0,0,,只不过它是一个无穷递归的过滤器\nDialogue: 0,0:13:19.65,0:13:20.88,Default,,0,0,0,,这是因为在SIEVE盒子中\nDialogue: 0,0:13:21.52,0:13:22.60,Default,,0,0,0,,还有另外一个SIEVE盒子\nDialogue: 0,0:13:23.37,0:13:25.85,Default,,0,0,0,,内部的盒子里面还有另外一个SIEVE盒子\nDialogue: 0,0:13:27.13,0:13:28.96,Default,,0,0,0,,我们现在逐渐有了非常厉害的能力\nDialogue: 0,0:13:28.96,0:13:32.84,Default,,0,0,0,,我们开始把 信号处理的方法\nDialogue: 0,0:13:33.90,0:13:36.41,Default,,0,0,0,,和计算中的递归结合在一起 来建模世界\nDialogue: 0,0:13:37.42,0:13:39.82,Default,,0,0,0,,还有很多像是这样的事\nDialogue: 0,0:13:40.97,0:13:42.09,Default,,0,0,0,,好的 有什么问题吗？\nDialogue: 0,0:13:48.19,0:13:49.16,Default,,0,0,0,,好吧 那我们休息一下\nDialogue: 0,0:13:49.64,0:14:04.12,Default,,0,0,0,,[音乐]\nDialogue: 0,0:14:04.46,0:14:08.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:14:12.08,0:14:16.38,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:14:16.44,0:14:20.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:14:20.35,0:14:25.05,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 II\nDialogue: 0,0:14:28.65,0:14:30.36,Default,,0,0,0,,我们已经看了\nDialogue: 0,0:14:30.36,0:14:32.09,Default,,0,0,0,,好几个流式程序设计的例子\nDialogue: 0,0:14:34.79,0:14:39.21,Default,,0,0,0,,我们目前接触到的流过程\nDialogue: 0,0:14:39.72,0:14:41.32,Default,,0,0,0,,都有一个共同的特征\nDialogue: 0,0:14:41.49,0:14:43.63,Default,,0,0,0,,这些过程总是递归地\nDialogue: 0,0:14:44.16,0:14:46.49,Default,,0,0,0,,一次生成一个元素\nDialogue: 0,0:14:46.51,0:14:48.72,Default,,0,0,0,,再用CONS-STREAM连接起来\nDialogue: 0,0:14:49.15,0:14:50.86,Default,,0,0,0,,因此 我们一直把它当作是生成器\nDialogue: 0,0:14:50.92,0:14:53.63,Default,,0,0,0,,还有一种思考流式程序设计的方式\nDialogue: 0,0:14:53.79,0:14:56.96,Default,,0,0,0,,我们不认为程序是\nDialogue: 0,0:14:57.36,0:14:59.93,Default,,0,0,0,,沿着流逐一处理元素\nDialogue: 0,0:15:00.25,0:15:05.68,Default,,0,0,0,,而是一下子处理了整个流\nDialogue: 0,0:15:07.18,0:15:09.16,Default,,0,0,0,,我先来定义两个非常有用的过程\nDialogue: 0,0:15:09.23,0:15:11.50,Default,,0,0,0,,来帮助我说明\nDialogue: 0,0:15:12.41,0:15:13.60,Default,,0,0,0,,第一个过程是ADD-STREAMS\nDialogue: 0,0:15:15.36,0:15:18.25,Default,,0,0,0,,它接受两个流作为参数\nDialogue: 0,0:15:18.81,0:15:20.88,Default,,0,0,0,,S1和S2\nDialogue: 0,0:15:22.30,0:15:24.67,Default,,0,0,0,,它生成一个新的流\nDialogue: 0,0:15:24.99,0:15:28.17,Default,,0,0,0,,其元素是两个流相应位置元素的和\nDialogue: 0,0:15:30.22,0:15:31.88,Default,,0,0,0,,相当于是“按元素”的加\nDialogue: 0,0:15:32.97,0:15:33.95,Default,,0,0,0,,如果其中一个流是空的\nDialogue: 0,0:15:33.96,0:15:35.39,Default,,0,0,0,,我们就返回另一个\nDialogue: 0,0:15:36.81,0:15:38.96,Default,,0,0,0,,否则 我们就构建一个新的流\nDialogue: 0,0:15:39.90,0:15:42.96,Default,,0,0,0,,新流的头部分是两个流头部分之和\nDialogue: 0,0:15:44.00,0:15:44.88,Default,,0,0,0,,而新流的尾部分\nDialogue: 0,0:15:46.00,0:15:48.62,Default,,0,0,0,,则是递归地加和尾部分\nDialogue: 0,0:15:50.09,0:15:52.73,Default,,0,0,0,,这就会产生“按元素”地加的效果\nDialogue: 0,0:15:53.15,0:15:57.04,Default,,0,0,0,,另一个过程是SCALE-STREAM\nDialogue: 0,0:15:57.50,0:16:01.66,Default,,0,0,0,,SCALE-STREAM有两个参数 常数C和流S\nDialogue: 0,0:16:04.11,0:16:06.62,Default,,0,0,0,,结果生成的流\nDialogue: 0,0:16:07.18,0:16:09.50,Default,,0,0,0,,就是将流S的所有元素乘上了C\nDialogue: 0,0:16:09.71,0:16:11.21,Default,,0,0,0,,这很简单 就是一个MAP\nDialogue: 0,0:16:12.20,0:16:16.22,Default,,0,0,0,,用到的函数是 X*C\nDialogue: 0,0:16:16.35,0:16:17.80,Default,,0,0,0,,把这个函数MAP于整个流\nDialogue: 0,0:16:20.06,0:16:21.47,Default,,0,0,0,,有了这两个过程\nDialogue: 0,0:16:22.64,0:16:24.36,Default,,0,0,0,,我来给你们解释 什么叫做\nDialogue: 0,0:16:24.70,0:16:27.00,Default,,0,0,0,,“一下子处理整个流”\nDialogue: 0,0:16:28.12,0:16:28.73,Default,,0,0,0,,我们来看这个\nDialogue: 0,0:16:30.20,0:16:30.92,Default,,0,0,0,,假设这样\nDialogue: 0,0:16:31.68,0:16:52.35,Default,,0,0,0,,(DEFINE ONES (CONS-STREAM 1 ONES))\nDialogue: 0,0:16:54.86,0:16:55.52,Default,,0,0,0,,这是什么？\nDialogue: 0,0:16:56.95,0:16:58.94,Default,,0,0,0,,这是一个表示无穷个1的流\nDialogue: 0,0:16:59.96,0:17:01.44,Default,,0,0,0,,因为第一个元素是1\nDialogue: 0,0:17:03.33,0:17:05.15,Default,,0,0,0,,尾部分则是这样的\nDialogue: 0,0:17:05.55,0:17:06.83,Default,,0,0,0,,它的头部分是1\nDialogue: 0,0:17:07.63,0:17:09.02,Default,,0,0,0,,它的尾部分\nDialogue: 0,0:17:09.12,0:17:10.24,Default,,0,0,0,,的头部分又为1\nDialogue: 0,0:17:10.52,0:17:11.78,Default,,0,0,0,,以此类推\nDialogue: 0,0:17:11.78,0:17:13.32,Default,,0,0,0,,这就是无穷个1的流\nDialogue: 0,0:17:15.13,0:17:15.93,Default,,0,0,0,,现在根据ONES\nDialogue: 0,0:17:16.12,0:17:18.03,Default,,0,0,0,,我再给出另一种定义整数的方式\nDialogue: 0,0:17:19.47,0:17:27.36,Default,,0,0,0,,(DEFINE INTEGERS\nDialogue: 0,0:17:28.24,0:17:30.76,Default,,0,0,0,,当然 第一个数是1\nDialogue: 0,0:17:32.75,0:17:38.57,Default,,0,0,0,,(CONS-STREAM 1 (ADD-STREAM\nDialogue: 0,0:17:40.22,0:17:48.27,Default,,0,0,0,,INTEGERS ONES)))\nDialogue: 0,0:17:55.10,0:17:56.35,Default,,0,0,0,,整数流是这样的：\nDialogue: 0,0:17:57.24,0:17:59.98,Default,,0,0,0,,它的第一个元素是1\nDialogue: 0,0:18:00.88,0:18:02.32,Default,,0,0,0,,而其余部分则是\nDialogue: 0,0:18:03.12,0:18:06.14,Default,,0,0,0,,依次把每个整数加1\nDialogue: 0,0:18:06.64,0:18:08.19,Default,,0,0,0,,因此 整数流的第二个元素则是\nDialogue: 0,0:18:08.51,0:18:11.96,Default,,0,0,0,,整数流的第一个元素加1\nDialogue: 0,0:18:13.92,0:18:15.18,Default,,0,0,0,,下一个数又要加1\nDialogue: 0,0:18:15.20,0:18:16.48,Default,,0,0,0,,第三个元素则是\nDialogue: 0,0:18:16.62,0:18:20.41,Default,,0,0,0,,INTEGER流尾部分的第一个元素\nDialogue: 0,0:18:20.84,0:18:21.96,Default,,0,0,0,,加1\nDialogue: 0,0:18:22.51,0:18:23.76,Default,,0,0,0,,这也就相当于\nDialogue: 0,0:18:25.08,0:18:28.65,Default,,0,0,0,,最初整数流的第一个元素加1\nDialogue: 0,0:18:28.86,0:18:31.25,Default,,0,0,0,,然后再加1 以此类推\nDialogue: 0,0:18:35.24,0:18:36.31,Default,,0,0,0,,这看起来有点匪夷所思\nDialogue: 0,0:18:36.31,0:18:37.47,Default,,0,0,0,,这样的过程可以正常运行\nDialogue: 0,0:18:38.12,0:18:38.99,Default,,0,0,0,,关键在于延时求值\nDialogue: 0,0:18:40.15,0:18:43.32,Default,,0,0,0,,我们来看这个ONES\nDialogue: 0,0:18:43.87,0:18:45.92,Default,,0,0,0,,这看起来根本不可能\nDialogue: 0,0:18:46.25,0:18:47.63,Default,,0,0,0,,因为它突然说\nDialogue: 0,0:18:47.79,0:18:48.96,Default,,0,0,0,,在定义ONES的时候\nDialogue: 0,0:18:49.00,0:18:50.91,Default,,0,0,0,,发现它依赖于它本身\nDialogue: 0,0:18:51.13,0:18:52.08,Default,,0,0,0,,它之所以可以运行是因为\nDialogue: 0,0:18:52.09,0:18:54.04,Default,,0,0,0,,这里暗中隐藏着延时求值\nDialogue: 0,0:18:55.25,0:18:56.56,Default,,0,0,0,,这个代码实际上是\nDialogue: 0,0:18:57.79,0:18:59.69,Default,,0,0,0,,回忆下 CONS-STREAM是只是一个缩写\nDialogue: 0,0:19:00.29,0:19:01.15,Default,,0,0,0,,实际上则是\nDialogue: 0,0:19:01.85,0:19:08.99,Default,,0,0,0,,(CONS 1 (DELAY ONES))\nDialogue: 0,0:19:12.14,0:19:13.21,Default,,0,0,0,,它又是怎么运作的呢？\nDialogue: 0,0:19:15.50,0:19:16.88,Default,,0,0,0,,你想要定义ONES\nDialogue: 0,0:19:18.02,0:19:20.24,Default,,0,0,0,,我来看看ONES要被定义成什么样\nDialogue: 0,0:19:20.70,0:19:23.40,Default,,0,0,0,,ONES被定义为一个序对\nDialogue: 0,0:19:24.89,0:19:28.11,Default,,0,0,0,,其CAR部分为1\nDialogue: 0,0:19:28.32,0:19:29.45,Default,,0,0,0,,而CDR部分则是\nDialogue: 0,0:19:29.45,0:19:30.73,Default,,0,0,0,,是一个计算某物的PROMISE\nDialogue: 0,0:19:30.75,0:19:31.69,Default,,0,0,0,,我现在还不用关心\nDialogue: 0,0:19:32.71,0:19:34.25,Default,,0,0,0,,所以虽然这时ONES还没有定义\nDialogue: 0,0:19:34.28,0:19:36.30,Default,,0,0,0,,但对我并不造成什么影响\nDialogue: 0,0:19:37.27,0:19:39.45,Default,,0,0,0,,一旦运行了整个定义 ONES就被定义了\nDialogue: 0,0:19:40.67,0:19:42.83,Default,,0,0,0,,所以 访问它尾部的时候 它就有定义了\nDialogue: 0,0:19:44.92,0:19:46.06,Default,,0,0,0,,这一点非常隐讳\nDialogue: 0,0:19:46.59,0:19:47.90,Default,,0,0,0,,整数流的定义也是如此\nDialogue: 0,0:19:48.47,0:19:50.46,Default,,0,0,0,,我可以在这里引用INTEGERS是因为\nDialogue: 0,0:19:51.13,0:19:53.21,Default,,0,0,0,,是因为这个CONS-STREAM的缘故\nDialogue: 0,0:19:53.85,0:19:55.24,Default,,0,0,0,,用CONS-STREAM把1\nDialogue: 0,0:19:55.37,0:19:57.05,Default,,0,0,0,,和一个不立即需要的东西组合起来\nDialogue: 0,0:19:57.05,0:19:59.60,Default,,0,0,0,,所以我在运行INTEGERS的定义的时候\nDialogue: 0,0:20:00.22,0:20:01.90,Default,,0,0,0,,并不会发现INTEGER没有定义过\nDialogue: 0,0:20:06.32,0:20:08.27,Default,,0,0,0,,听上去非常玄乎\nDialogue: 0,0:20:08.44,0:20:11.50,Default,,0,0,0,,让我用图像来演示一下INTEGERS的原理\nDialogue: 0,0:20:12.43,0:20:14.72,Default,,0,0,0,,怎么画呢？\nDialogue: 0,0:20:15.02,0:20:16.30,Default,,0,0,0,,首先是ONES这个流\nDialogue: 0,0:20:20.51,0:20:21.88,Default,,0,0,0,,它作为参数输入\nDialogue: 0,0:20:23.26,0:20:24.92,Default,,0,0,0,,进入一个加法器\nDialogue: 0,0:20:24.96,0:20:26.59,Default,,0,0,0,,进行流的加法运算\nDialogue: 0,0:20:29.31,0:20:35.87,Default,,0,0,0,,输出则是整数流INTEGERS\nDialogue: 0,0:20:40.76,0:20:42.70,Default,,0,0,0,,这里 这个整数流又重新进入加法器\nDialogue: 0,0:20:44.94,0:20:46.97,Default,,0,0,0,,形成了一个小型的反馈回路\nDialogue: 0,0:20:48.06,0:20:49.42,Default,,0,0,0,,我需要在某处接入最初的ONES\nDialogue: 0,0:20:50.09,0:20:52.88,Default,,0,0,0,,才能让它生效\nDialogue: 0,0:20:57.10,0:20:58.64,Default,,0,0,0,,在真实的信号处理中\nDialogue: 0,0:20:58.72,0:21:02.48,Default,,0,0,0,,这里是一个被初始化为1的延时元件\nDialogue: 0,0:21:02.91,0:21:05.90,Default,,0,0,0,,这就是ONES程序的图示\nDialogue: 0,0:21:07.86,0:21:09.63,Default,,0,0,0,,事实上 这个非常像\nDialogue: 0,0:21:09.80,0:21:13.77,Default,,0,0,0,,如果你见过真正的信号方块图的话\nDialogue: 0,0:21:13.77,0:21:16.30,Default,,0,0,0,,这个图形非常像累加器\nDialogue: 0,0:21:16.35,0:21:17.48,Default,,0,0,0,,有穷状态累加器\nDialogue: 0,0:21:17.98,0:21:20.06,Default,,0,0,0,,事实上 我们可以稍加修改\nDialogue: 0,0:21:21.18,0:21:23.96,Default,,0,0,0,,就可以让它对一个流做积分\nDialogue: 0,0:21:25.37,0:21:26.97,Default,,0,0,0,,或者说是有穷状态累加器\nDialogue: 0,0:21:27.00,0:21:28.04,Default,,0,0,0,,你怎么认为都可以\nDialogue: 0,0:21:28.44,0:21:30.86,Default,,0,0,0,,现在 不再是输入ONES 输出INTEGERS\nDialogue: 0,0:21:31.68,0:21:32.38,Default,,0,0,0,,我们要做的是\nDialogue: 0,0:21:32.91,0:21:34.83,Default,,0,0,0,,这里有一个流S为输入\nDialogue: 0,0:21:35.76,0:21:40.56,Default,,0,0,0,,我们要计算这个流的积分\nDialogue: 0,0:21:42.60,0:21:44.09,Default,,0,0,0,,也就是累加这个流的值\nDialogue: 0,0:21:44.44,0:21:45.63,Default,,0,0,0,,这看起来几乎就是一样的\nDialogue: 0,0:21:45.66,0:21:46.84,Default,,0,0,0,,我们要做的就是\nDialogue: 0,0:21:47.02,0:21:48.08,Default,,0,0,0,,当S从这里输入时\nDialogue: 0,0:21:49.21,0:21:50.64,Default,,0,0,0,,在把它求和之前\nDialogue: 0,0:21:50.91,0:21:54.26,Default,,0,0,0,,先将其乘以dt\nDialogue: 0,0:21:57.68,0:22:00.00,Default,,0,0,0,,剩下的就不用改了\nDialogue: 0,0:22:00.00,0:22:00.91,Default,,0,0,0,,我们就得到了一个盒子\nDialogue: 0,0:22:03.36,0:22:04.56,Default,,0,0,0,,一个积分器\nDialogue: 0,0:22:09.79,0:22:11.26,Default,,0,0,0,,对一个流S进行积分\nDialogue: 0,0:22:11.90,0:22:14.51,Default,,0,0,0,,把这里的1替换为\nDialogue: 0,0:22:14.94,0:22:18.35,Default,,0,0,0,,该积分的初始值\nDialogue: 0,0:22:19.98,0:22:21.60,Default,,0,0,0,,这个看起来就非常像\nDialogue: 0,0:22:22.35,0:22:24.86,Default,,0,0,0,,信号处理中的方框图了\nDialogue: 0,0:22:25.27,0:22:28.11,Default,,0,0,0,,事实上 这个图示对应的是这样一个过程\nDialogue: 0,0:22:31.49,0:22:33.61,Default,,0,0,0,,对一个流进行积分\nDialogue: 0,0:22:34.01,0:22:35.48,Default,,0,0,0,,INTEGRAL函数接收一个流\nDialogue: 0,0:22:35.68,0:22:36.86,Default,,0,0,0,,返回一个新的流\nDialogue: 0,0:22:37.53,0:22:40.67,Default,,0,0,0,,它还接收一个初始值和某个时间常量\nDialogue: 0,0:22:42.23,0:22:42.97,Default,,0,0,0,,然后呢？\nDialogue: 0,0:22:43.04,0:22:45.05,Default,,0,0,0,,首先在内部定义一个流INT\nDialogue: 0,0:22:45.20,0:22:46.32,Default,,0,0,0,,之所以要给它一个内部名字\nDialogue: 0,0:22:46.33,0:22:48.86,Default,,0,0,0,,原因在于可以使它反馈 以形成循环\nDialogue: 0,0:22:49.40,0:22:50.80,Default,,0,0,0,,INT的定义是\nDialogue: 0,0:22:51.10,0:22:53.32,Default,,0,0,0,,一个以INITIA-VALUE开始的流\nDialogue: 0,0:22:54.97,0:23:00.14,Default,,0,0,0,,而其余的元素则是把它们加起来\nDialogue: 0,0:23:01.28,0:23:03.61,Default,,0,0,0,,我们把输入流乘以dt\nDialogue: 0,0:23:03.87,0:23:04.92,Default,,0,0,0,,然后和INT相加\nDialogue: 0,0:23:06.88,0:23:09.66,Default,,0,0,0,,整个INTEGRAL函数的结果就是这个INT\nDialogue: 0,0:23:10.69,0:23:12.94,Default,,0,0,0,,我们使用这种内部定义的语法\nDialogue: 0,0:23:13.34,0:23:15.66,Default,,0,0,0,,是为了可以在内部引用它自己\nDialogue: 0,0:23:21.88,0:23:23.71,Default,,0,0,0,,我们还可以做更多的事情\nDialogue: 0,0:23:23.71,0:23:24.51,Default,,0,0,0,,来看这个\nDialogue: 0,0:23:25.63,0:23:26.89,Default,,0,0,0,,斐波那契数\nDialogue: 0,0:23:26.89,0:23:32.62,Default,,0,0,0,,(DEFINE FIBS\nDialogue: 0,0:23:36.35,0:23:37.63,Default,,0,0,0,,斐波那契数是什么呢？\nDialogue: 0,0:23:37.98,0:23:46.54,Default,,0,0,0,,它从0开始\nDialogue: 0,0:23:48.65,0:23:50.09,Default,,0,0,0,,下一个是1\nDialogue: 0,0:23:56.26,0:23:59.16,Default,,0,0,0,,的其余的斐波那契数是通过\nDialogue: 0,0:23:59.87,0:24:11.00,Default,,0,0,0,,把它们的尾部分求和而得来\nDialogue: 0,0:24:17.57,0:24:19.28,Default,,0,0,0,,这样来定义斐波那契数\nDialogue: 0,0:24:20.58,0:24:21.43,Default,,0,0,0,,这是如何运作的呢？\nDialogue: 0,0:24:21.43,0:24:24.19,Default,,0,0,0,,我们来试试\nDialogue: 0,0:24:24.20,0:24:26.49,Default,,0,0,0,,假如开始计算斐波那契数\nDialogue: 0,0:24:29.64,0:24:31.92,Default,,0,0,0,,首先告诉你 它以0和1开始\nDialogue: 0,0:24:35.79,0:24:38.22,Default,,0,0,0,,而0和1之后的数则是\nDialogue: 0,0:24:39.18,0:24:40.86,Default,,0,0,0,,通过加和两个流而得\nDialogue: 0,0:24:41.12,0:24:42.59,Default,,0,0,0,,一个流是FIBS本身\nDialogue: 0,0:24:44.06,0:24:45.69,Default,,0,0,0,,另一个是FIBS的尾部分\nDialogue: 0,0:24:49.12,0:24:51.16,Default,,0,0,0,,如果我知道这是以0和1起始的\nDialogue: 0,0:24:51.79,0:24:55.42,Default,,0,0,0,,我就能知道 FIBS是以0和1起始的\nDialogue: 0,0:24:55.74,0:24:57.40,Default,,0,0,0,,那么 FIBS的尾部分则应该以1开始\nDialogue: 0,0:24:58.36,0:24:59.45,Default,,0,0,0,,一旦我知道了这点\nDialogue: 0,0:24:59.66,0:25:02.11,Default,,0,0,0,,我就知道 FIBS的下一个数就是0+1=1\nDialogue: 0,0:25:02.96,0:25:04.60,Default,,0,0,0,,它也同样告诉我这里是1\nDialogue: 0,0:25:04.62,0:25:05.72,Default,,0,0,0,,这里也是1\nDialogue: 0,0:25:06.30,0:25:07.28,Default,,0,0,0,,知道了这些之后\nDialogue: 0,0:25:07.29,0:25:08.76,Default,,0,0,0,,我就知道下一个是2\nDialogue: 0,0:25:09.39,0:25:11.70,Default,,0,0,0,,这里是2 这里也是2\nDialogue: 0,0:25:11.70,0:25:12.56,Default,,0,0,0,,下一个是3\nDialogue: 0,0:25:14.72,0:25:15.79,Default,,0,0,0,,这里是3\nDialogue: 0,0:25:16.19,0:25:17.13,Default,,0,0,0,,这里是5\nDialogue: 0,0:25:18.67,0:25:19.96,Default,,0,0,0,,这个定义完全说得通\nDialogue: 0,0:25:21.50,0:25:22.78,Default,,0,0,0,,这个定义只有一行\nDialogue: 0,0:25:22.83,0:25:25.00,Default,,0,0,0,,当然 我也可以在计算机中\nDialogue: 0,0:25:25.00,0:25:26.62,Default,,0,0,0,,原原本本地键入计算机中\nDialogue: 0,0:25:27.04,0:25:28.94,Default,,0,0,0,,然后要求输出斐波那契数\nDialogue: 0,0:25:28.94,0:25:30.15,Default,,0,0,0,,然后它就会不断输出\nDialogue: 0,0:25:32.79,0:25:35.20,Default,,0,0,0,,这又像是在学习递归\nDialogue: 0,0:25:36.81,0:25:39.79,Default,,0,0,0,,过程可以被递归定义\nDialogue: 0,0:25:40.99,0:25:43.50,Default,,0,0,0,,我们也可以递归地定义数据对象\nDialogue: 0,0:25:45.16,0:25:46.92,Default,,0,0,0,,但你们一点儿不应该感到吃惊\nDialogue: 0,0:25:47.12,0:25:49.50,Default,,0,0,0,,因为现在 你们应该真正相信\nDialogue: 0,0:25:49.52,0:25:53.05,Default,,0,0,0,,过程与数据之间没有区别\nDialogue: 0,0:25:53.09,0:25:53.92,Default,,0,0,0,,事实上 就某种意义上来说\nDialogue: 0,0:25:53.93,0:25:56.41,Default,,0,0,0,,流也是由过程来实现的\nDialogue: 0,0:25:56.43,0:25:57.79,Default,,0,0,0,,只不过我们不把它看做过程而已\nDialogue: 0,0:25:58.21,0:26:00.38,Default,,0,0,0,,因此既然我们有递归过程\nDialogue: 0,0:26:00.70,0:26:03.63,Default,,0,0,0,,那么 有递归数据也就不足为奇了\nDialogue: 0,0:26:07.72,0:26:09.69,Default,,0,0,0,,虽然流非常简洁\nDialogue: 0,0:26:09.72,0:26:13.92,Default,,0,0,0,,但不幸的是 有些问题流无法解决\nDialogue: 0,0:26:14.99,0:26:16.48,Default,,0,0,0,,我来举个例子\nDialogue: 0,0:26:17.58,0:26:20.35,Default,,0,0,0,,同样地 我们来想象一下\nDialogue: 0,0:26:20.76,0:26:23.61,Default,,0,0,0,,我们正在构建求解微分方程的模拟计算机\nDialogue: 0,0:26:25.20,0:26:34.30,Default,,0,0,0,,比如求解方程 y' = y^2\nDialogue: 0,0:26:34.76,0:26:36.16,Default,,0,0,0,,我会给你一个初值\nDialogue: 0,0:26:36.39,0:26:38.03,Default,,0,0,0,,y(0) = 1\nDialogue: 0,0:26:41.48,0:26:44.06,Default,,0,0,0,,dt = .0001\nDialogue: 0,0:26:46.77,0:26:47.53,Default,,0,0,0,,很久之前\nDialogue: 0,0:26:48.00,0:26:50.65,Default,,0,0,0,,就有人构建模拟计算机 来解决这类问题\nDialogue: 0,0:26:51.36,0:26:53.02,Default,,0,0,0,,原理非常简单\nDialogue: 0,0:26:53.02,0:26:54.41,Default,,0,0,0,,你首先需要一个积分器\nDialogue: 0,0:27:00.04,0:27:01.69,Default,,0,0,0,,比如这个INT盒子\nDialogue: 0,0:27:03.05,0:27:06.48,Default,,0,0,0,,我们设定初始值 y(0) = 1\nDialogue: 0,0:27:08.53,0:27:10.92,Default,,0,0,0,,现在如果我们送入一个输入 就会得到输出\nDialogue: 0,0:27:10.96,0:27:13.16,Default,,0,0,0,,输出的结果就是y\nDialogue: 0,0:27:14.25,0:27:16.96,Default,,0,0,0,,输入的是y的导数\nDialogue: 0,0:27:17.52,0:27:20.52,Default,,0,0,0,,在这里 导数 y' = y^2\nDialogue: 0,0:27:21.49,0:27:27.07,Default,,0,0,0,,如果我们用MAP把SQUARE映射在这些值上\nDialogue: 0,0:27:30.73,0:27:32.09,Default,,0,0,0,,然后把这个引过来\nDialogue: 0,0:27:36.28,0:27:38.48,Default,,0,0,0,,这个方块图\nDialogue: 0,0:27:38.57,0:27:41.08,Default,,0,0,0,,就是用于求解这个微分方程的模拟计算机\nDialogue: 0,0:27:42.91,0:27:44.80,Default,,0,0,0,,现在我们用代码\nDialogue: 0,0:27:44.80,0:27:46.78,Default,,0,0,0,,来表示下这个过程\nDialogue: 0,0:27:47.23,0:27:48.72,Default,,0,0,0,,这个图究竟表示的是什么呢？\nDialogue: 0,0:27:49.39,0:27:58.30,Default,,0,0,0,,(DEFINE Y\nDialogue: 0,0:28:04.28,0:28:11.68,Default,,0,0,0,,(INTEGRAL DY 1 .001))\nDialogue: 0,0:28:13.79,0:28:15.45,Default,,0,0,0,,接下来\nDialogue: 0,0:28:16.80,0:28:20.85,Default,,0,0,0,,通过MAP SQUARE 来表示dy\nDialogue: 0,0:28:20.85,0:28:32.81,Default,,0,0,0,,(DEFINE DY (MAP SQUARE Y))\nDialogue: 0,0:28:33.51,0:28:36.80,Default,,0,0,0,,这就是这个模拟计算机的流式描述\nDialogue: 0,0:28:38.62,0:28:40.32,Default,,0,0,0,,不幸的是 它并不起效\nDialogue: 0,0:28:41.41,0:28:42.67,Default,,0,0,0,,你也可以发现这是为什么\nDialogue: 0,0:28:42.97,0:28:44.99,Default,,0,0,0,,因为我把Y定义为\nDialogue: 0,0:28:46.43,0:28:47.85,Default,,0,0,0,,DY 的积分\nDialogue: 0,0:28:49.04,0:28:50.65,Default,,0,0,0,,它会问 对什么的积分？\nDialogue: 0,0:28:51.19,0:28:52.12,Default,,0,0,0,,没定义啊\nDialogue: 0,0:28:53.71,0:28:57.63,Default,,0,0,0,,所以这个定义必须写在这个定义的后面\nDialogue: 0,0:28:58.77,0:29:00.51,Default,,0,0,0,,另一方面 如果先定义了dy\nDialogue: 0,0:29:00.51,0:29:03.02,Default,,0,0,0,,定义为 (MAP SQUARE 某个东西)\nDialogue: 0,0:29:03.58,0:29:04.64,Default,,0,0,0,,这个也还没有定义\nDialogue: 0,0:29:05.77,0:29:08.17,Default,,0,0,0,,我既不能先写这个 又不能先写那个\nDialogue: 0,0:29:09.08,0:29:11.58,Default,,0,0,0,,这个游戏就没法玩了\nDialogue: 0,0:29:17.56,0:29:18.51,Default,,0,0,0,,怎样来解决呢？\nDialogue: 0,0:29:20.60,0:29:21.84,Default,,0,0,0,,我们可以用ONES来解决\nDialogue: 0,0:29:22.20,0:29:25.82,Default,,0,0,0,,所以 我们在这里定义的ONES\nDialogue: 0,0:29:27.24,0:29:29.90,Default,,0,0,0,,我们之所以可以使用ONES来定义ONES\nDialogue: 0,0:29:30.40,0:29:32.03,Default,,0,0,0,,这是因为其中的延时求值\nDialogue: 0,0:29:32.43,0:29:34.12,Default,,0,0,0,,CONS-STREAM是延时求值的\nDialogue: 0,0:29:34.77,0:29:35.79,Default,,0,0,0,,那么 这又为什么说得通呢？\nDialogue: 0,0:29:35.92,0:29:38.51,Default,,0,0,0,,为什么CONS-STREAM是延时求值的是合理的呢？\nDialogue: 0,0:29:40.73,0:29:43.13,Default,,0,0,0,,原因在于 CONS-STREAM不需要其尾部分\nDialogue: 0,0:29:43.48,0:29:44.88,Default,,0,0,0,,就可以完成有意义的事\nDialogue: 0,0:29:45.95,0:29:46.84,Default,,0,0,0,,比如我说\nDialogue: 0,0:29:47.48,0:29:49.64,Default,,0,0,0,,这个是1和某个东西组成的流\nDialogue: 0,0:29:49.92,0:29:51.69,Default,,0,0,0,,虽然我对它一无所知\nDialogue: 0,0:29:52.16,0:29:54.03,Default,,0,0,0,,但我却知道整个流是以1开始的\nDialogue: 0,0:29:54.87,0:29:57.29,Default,,0,0,0,,所以用CONS-STREAM来构造是有意义的\nDialogue: 0,0:29:59.96,0:30:01.24,Default,,0,0,0,,我们在这里放了一个DELAY\nDialogue: 0,0:30:01.42,0:30:04.65,Default,,0,0,0,,这就使得我们能够进行某种自引用的定义\nDialogue: 0,0:30:06.32,0:30:07.95,Default,,0,0,0,,INTEGRAL也可以用这种方式来解决\nDialogue: 0,0:30:08.19,0:30:12.52,Default,,0,0,0,,注意 对于INTEGRAL来说 我可以\nDialogue: 0,0:30:14.60,0:30:16.08,Default,,0,0,0,,让我们回过头来再看看INTEGRAL的定义\nDialogue: 0,0:30:17.58,0:30:18.56,Default,,0,0,0,,求积分的时候\nDialogue: 0,0:30:21.39,0:30:25.00,Default,,0,0,0,,知道INTEGRAL的第一个元素是合理的\nDialogue: 0,0:30:26.04,0:30:27.87,Default,,0,0,0,,尽管还不知道整个流是什么样的\nDialogue: 0,0:30:28.97,0:30:30.17,Default,,0,0,0,,这是因为INTEGRAL中第一个元素\nDialogue: 0,0:30:30.20,0:30:32.16,Default,,0,0,0,,总会是你传递过来的INITIAL-VALUE\nDialogue: 0,0:30:33.14,0:30:36.11,Default,,0,0,0,,所以INTEGRAL可以用CONS-STREAM来实现\nDialogue: 0,0:30:37.09,0:30:37.98,Default,,0,0,0,,我们可以定义它\nDialogue: 0,0:30:38.25,0:30:40.88,Default,,0,0,0,,甚至不用知道要积分的流是什么\nDialogue: 0,0:30:42.84,0:30:45.18,Default,,0,0,0,,只需要知道初始值是什么就行了\nDialogue: 0,0:30:46.71,0:30:48.17,Default,,0,0,0,,INTEGRAL还可以修改得更为智能\nDialogue: 0,0:30:48.41,0:30:50.68,Default,,0,0,0,,我们给它一个待积分的流\nDialogue: 0,0:30:50.83,0:30:51.92,Default,,0,0,0,,以及一个初值\nDialogue: 0,0:30:52.11,0:30:54.99,Default,,0,0,0,,直到你要求沿着这个流求解积分时\nDialogue: 0,0:30:55.21,0:30:56.97,Default,,0,0,0,,我才关心这个流是什么\nDialogue: 0,0:30:58.43,0:31:00.51,Default,,0,0,0,,换句话说INTEGRAL可以像CONS-STREAM一样\nDialogue: 0,0:31:00.57,0:31:03.74,Default,,0,0,0,,你可以认为INTEGRAL被放在DELAY之中\nDialogue: 0,0:31:03.76,0:31:04.86,Default,,0,0,0,,我们这样修改\nDialogue: 0,0:31:05.61,0:31:07.02,Default,,0,0,0,,这个过程是像这样的\nDialogue: 0,0:31:07.65,0:31:08.75,Default,,0,0,0,,这是另一个版本的INTEGRAL\nDialogue: 0,0:31:08.89,0:31:10.54,Default,,0,0,0,,这个跟之前的版本非常相似\nDialogue: 0,0:31:11.10,0:31:13.34,Default,,0,0,0,,只不过作为参数的流\nDialogue: 0,0:31:13.77,0:31:15.69,Default,,0,0,0,,必须要是一个延时对象\nDialogue: 0,0:31:17.11,0:31:18.43,Default,,0,0,0,,这个INTEGRAL又是如何运作的呢？\nDialogue: 0,0:31:18.85,0:31:21.79,Default,,0,0,0,,我们在内部定义的INT则是\nDialogue: 0,0:31:22.14,0:31:24.19,Default,,0,0,0,,用CONS-STREAM构造一个流\nDialogue: 0,0:31:24.73,0:31:26.44,Default,,0,0,0,,初值还是INITIAL-VALUE\nDialogue: 0,0:31:27.16,0:31:29.68,Default,,0,0,0,,但是在CONS-STREAM中\nDialogue: 0,0:31:29.74,0:31:32.30,Default,,0,0,0,,要注意 这里面有个隐藏的DELAY\nDialogue: 0,0:31:34.95,0:31:39.07,Default,,0,0,0,,只有在这个CONS-STREAM的内部\nDialogue: 0,0:31:39.82,0:31:42.11,Default,,0,0,0,,我才会查看延时对象的实际内容\nDialogue: 0,0:31:43.18,0:31:45.79,Default,,0,0,0,,所以 答案的第一个元素将会是初值\nDialogue: 0,0:31:45.97,0:31:47.90,Default,,0,0,0,,如果有人想访问我的尾部分\nDialogue: 0,0:31:48.40,0:31:49.42,Default,,0,0,0,,此时\nDialogue: 0,0:31:50.00,0:31:51.72,Default,,0,0,0,,我会FORCE该延迟对象\nDialogue: 0,0:31:52.62,0:31:53.60,Default,,0,0,0,,把结果记作S\nDialogue: 0,0:31:54.44,0:31:55.60,Default,,0,0,0,,然后再进行ADD-STREAMS\nDialogue: 0,0:31:56.36,0:31:59.26,Default,,0,0,0,,这个INTEGRAL就有点像CONS-STREAM\nDialogue: 0,0:31:59.26,0:32:02.59,Default,,0,0,0,,直到你确实需要知道第一个元素的时候\nDialogue: 0,0:32:03.88,0:32:07.13,Default,,0,0,0,,它才会去查看DELAYED-S是什么\nDialogue: 0,0:32:10.12,0:32:11.02,Default,,0,0,0,,如果这样的话\nDialogue: 0,0:32:11.52,0:32:12.83,Default,,0,0,0,,也就能求解 y' = y^2 了\nDialogue: 0,0:32:13.36,0:32:15.20,Default,,0,0,0,,这里我们只需要\nDialogue: 0,0:32:16.00,0:32:25.31,Default,,0,0,0,,把Y定义为对延时对象DY的积分\nDialogue: 0,0:32:27.09,0:32:28.22,Default,,0,0,0,,所以Y的定义就变成了\nDialogue: 0,0:32:28.40,0:32:34.36,Default,,0,0,0,,(INTEGRAL (DELAY DY) 1 .001)\nDialogue: 0,0:32:34.38,0:32:35.13,Default,,0,0,0,,这样一来就可以了\nDialogue: 0,0:32:35.28,0:32:37.44,Default,,0,0,0,,因为我输入Y的定义\nDialogue: 0,0:32:38.00,0:32:39.68,Default,,0,0,0,,它是某个东西的积分\nDialogue: 0,0:32:40.20,0:32:42.68,Default,,0,0,0,,但这是个延迟对象 我现在还不用关心\nDialogue: 0,0:32:44.60,0:32:46.32,Default,,0,0,0,,这之后 再定义DY\nDialogue: 0,0:32:46.32,0:32:47.37,Default,,0,0,0,,现在Y就有定义了\nDialogue: 0,0:32:47.55,0:32:48.89,Default,,0,0,0,,所以我在定义DY时\nDialogue: 0,0:32:49.13,0:32:50.67,Default,,0,0,0,,它可以知道Y的定义\nDialogue: 0,0:32:51.70,0:32:52.84,Default,,0,0,0,,一切都正常了\nDialogue: 0,0:32:52.84,0:32:54.33,Default,,0,0,0,,两个流都有第一个元素\nDialogue: 0,0:32:54.92,0:32:56.25,Default,,0,0,0,,当我不断取得下一个元素\nDialogue: 0,0:32:56.27,0:32:57.31,Default,,0,0,0,,沿着流做MAP运算时\nDialogue: 0,0:32:57.37,0:32:58.88,Default,,0,0,0,,Y和DY都被定义过了\nDialogue: 0,0:33:00.59,0:33:04.24,Default,,0,0,0,,所以为了继续这个游戏 我们不能仅仅\nDialogue: 0,0:33:04.67,0:33:07.13,Default,,0,0,0,,只使用隐藏在流中的DELAY\nDialogue: 0,0:33:08.36,0:33:08.97,Default,,0,0,0,,有问题么？\nDialogue: 0,0:33:13.52,0:33:14.27,Default,,0,0,0,,休息一下吧\nDialogue: 0,0:33:14.72,0:33:26.86,Default,,0,0,0,,[音乐]\nDialogue: 0,0:33:27.37,0:33:30.94,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:33:52.16,0:33:55.26,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:33:55.42,0:33:59.26,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:34:00.38,0:34:03.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 II\nDialogue: 0,0:34:07.30,0:34:10.04,Default,,0,0,0,,上节课的最后\nDialogue: 0,0:34:10.89,0:34:11.80,Default,,0,0,0,,不知道你们注意到没有\nDialogue: 0,0:34:11.82,0:34:13.55,Default,,0,0,0,,事情正变得糟糕起来\nDialogue: 0,0:34:14.83,0:34:18.40,Default,,0,0,0,,我们讲了很多关于 流\nDialogue: 0,0:34:19.16,0:34:22.68,Default,,0,0,0,,以及分离程序中的时间和计算机中的时间\nDialogue: 0,0:34:22.86,0:34:26.28,Default,,0,0,0,,这些分离都被隐藏在流中了\nDialogue: 0,0:34:27.28,0:34:29.50,Default,,0,0,0,,上节课快结束时我们发现\nDialogue: 0,0:34:29.71,0:34:32.19,Default,,0,0,0,,为了真正发挥这种方法的优势\nDialogue: 0,0:34:32.22,0:34:34.38,Default,,0,0,0,,我们需要另外的DELAY\nDialogue: 0,0:34:34.38,0:34:35.85,Default,,0,0,0,,不只需要隐藏在CONS-STREAM中的DELAY\nDialogue: 0,0:34:36.09,0:34:37.95,Default,,0,0,0,,还需要显式地使用DELAY\nDialogue: 0,0:34:39.03,0:34:41.88,Default,,0,0,0,,我只是用微分方程举了一个很简单的例子\nDialogue: 0,0:34:42.35,0:34:44.08,Default,,0,0,0,,但是如果你有一个非常复杂的系统\nDialogue: 0,0:34:44.12,0:34:45.40,Default,,0,0,0,,里面充斥着各种各样的自循环\nDialogue: 0,0:34:45.95,0:34:47.84,Default,,0,0,0,,那就很难再发现\nDialogue: 0,0:34:47.90,0:34:49.31,Default,,0,0,0,,在什么地方需要额外的DELAY了\nDialogue: 0,0:34:49.92,0:34:51.18,Default,,0,0,0,,假如你一不小心漏了一个\nDialogue: 0,0:34:51.45,0:34:54.36,Default,,0,0,0,,就很难发现程序为什么不起效\nDialogue: 0,0:34:55.55,0:34:57.15,Default,,0,0,0,,这是一种混乱\nDialogue: 0,0:34:57.79,0:35:01.71,Default,,0,0,0,,让我们能够使用DELAY\nDialogue: 0,0:35:02.08,0:35:04.70,Default,,0,0,0,,有时却会让程序设计变得非常复杂\nDialogue: 0,0:35:04.72,0:35:06.80,Default,,0,0,0,,因为它们不能完全隐藏在流中\nDialogue: 0,0:35:08.51,0:35:09.79,Default,,0,0,0,,那么 有没有什么解决方案呢？\nDialogue: 0,0:35:11.13,0:35:12.67,Default,,0,0,0,,所幸的是 有\nDialogue: 0,0:35:13.48,0:35:16.08,Default,,0,0,0,,我们可以修改整个语言\nDialogue: 0,0:35:16.14,0:35:18.19,Default,,0,0,0,,使得所有的过程都表现得像CONS-STREAM一样\nDialogue: 0,0:35:19.10,0:35:21.48,Default,,0,0,0,,这样所有的过程都会\nDialogue: 0,0:35:22.32,0:35:25.45,Default,,0,0,0,,自动、隐式地为它的参数加上DELAY\nDialogue: 0,0:35:25.45,0:35:26.43,Default,,0,0,0,,这是什么意思呢？\nDialogue: 0,0:35:27.52,0:35:29.53,Default,,0,0,0,,就是说 当你调用一个过程时\nDialogue: 0,0:35:30.16,0:35:31.88,Default,,0,0,0,,参数并不会立即求值\nDialogue: 0,0:35:32.21,0:35:34.70,Default,,0,0,0,,只有在需要被求值的时候 它们才会被求值\nDialogue: 0,0:35:34.89,0:35:36.72,Default,,0,0,0,,它们也可能被传递给其它的过程\nDialogue: 0,0:35:36.76,0:35:38.12,Default,,0,0,0,,而这个过程也不会求值这些参数\nDialogue: 0,0:35:39.26,0:35:41.90,Default,,0,0,0,,因此这些过程间传递的是PROMISE\nDialogue: 0,0:35:42.15,0:35:44.46,Default,,0,0,0,,直到最后\nDialogue: 0,0:35:44.65,0:35:47.34,Default,,0,0,0,,你需要查看某个值的时候\nDialogue: 0,0:35:47.36,0:35:48.99,Default,,0,0,0,,可能是因为一个基本运算所需要\nDialogue: 0,0:35:49.37,0:35:51.48,Default,,0,0,0,,这是你才实际求值这些PROMISE\nDialogue: 0,0:35:52.38,0:35:53.16,Default,,0,0,0,,像这样修改语言之后\nDialogue: 0,0:35:53.36,0:35:55.37,Default,,0,0,0,,由于所有的东西都是统一被延时的\nDialogue: 0,0:35:57.16,0:35:59.00,Default,,0,0,0,,就不需要任何显式的DELAY了\nDialogue: 0,0:35:59.04,0:36:01.55,Default,,0,0,0,,因为它自动地内建在语言之中了\nDialogue: 0,0:36:03.24,0:36:04.38,Default,,0,0,0,,换句话来说\nDialogue: 0,0:36:05.10,0:36:08.14,Default,,0,0,0,,从技术上来说 我所描述的\nDialogue: 0,0:36:09.02,0:36:10.76,Default,,0,0,0,,如果修改后的语言被称作\nDialogue: 0,0:36:12.19,0:36:16.57,Default,,0,0,0,,所谓的“正则序求值”语言\nDialogue: 0,0:36:20.20,0:36:23.47,Default,,0,0,0,,这个跟我们一直使用的语言不同\nDialogue: 0,0:36:23.87,0:36:33.79,Default,,0,0,0,,我们所用的是“应用序求值”语言\nDialogue: 0,0:36:34.56,0:36:36.83,Default,,0,0,0,,还记得应用序求值的代换模型吧\nDialogue: 0,0:36:36.83,0:36:40.49,Default,,0,0,0,,当你求值一个组合式的时候\nDialogue: 0,0:36:40.51,0:36:42.11,Default,,0,0,0,,你需要先计算出每一个元素的值\nDialogue: 0,0:36:43.59,0:36:45.40,Default,,0,0,0,,先求值所有的参数\nDialogue: 0,0:36:45.72,0:36:47.42,Default,,0,0,0,,再把它们代换入过程的体\nDialogue: 0,0:36:47.60,0:36:49.55,Default,,0,0,0,,正则序则不是这样\nDialogue: 0,0:36:49.89,0:36:51.90,Default,,0,0,0,,你所做的则是\nDialogue: 0,0:36:52.76,0:36:54.41,Default,,0,0,0,,直接将参数代换入过程的体\nDialogue: 0,0:36:54.44,0:36:56.19,Default,,0,0,0,,而不先对参数求值\nDialogue: 0,0:36:56.54,0:36:58.08,Default,,0,0,0,,只是代换入了一个计算参数的PROMISE\nDialogue: 0,0:36:58.81,0:36:59.90,Default,,0,0,0,,换句话说就是\nDialogue: 0,0:36:59.92,0:37:02.09,Default,,0,0,0,,把作为参数的整个表达式\nDialogue: 0,0:37:02.28,0:37:04.84,Default,,0,0,0,,直接代入过程的体进行代换\nDialogue: 0,0:37:05.16,0:37:06.88,Default,,0,0,0,,在此之间从不进行任何化简\nDialogue: 0,0:37:07.16,0:37:08.76,Default,,0,0,0,,直到遇到一个基本运算符\nDialogue: 0,0:37:09.47,0:37:10.99,Default,,0,0,0,,这就是所谓的正则序求值语言\nDialogue: 0,0:37:12.17,0:37:13.12,Default,,0,0,0,,我们为什么不这样做呢？\nDialogue: 0,0:37:13.82,0:37:14.60,Default,,0,0,0,,这样做了之后\nDialogue: 0,0:37:15.00,0:37:17.34,Default,,0,0,0,,我们就获得了延时求值的所有优点\nDialogue: 0,0:37:17.90,0:37:18.80,Default,,0,0,0,,而不会一片混乱\nDialogue: 0,0:37:18.94,0:37:20.19,Default,,0,0,0,,事实上 如果我们这样做了之后\nDialogue: 0,0:37:20.43,0:37:22.67,Default,,0,0,0,,CONS也会是延时求值的\nDialogue: 0,0:37:22.68,0:37:24.57,Default,,0,0,0,,就和CONS-STREAM一样\nDialogue: 0,0:37:24.71,0:37:25.82,Default,,0,0,0,,我们就不再需要流了\nDialogue: 0,0:37:26.36,0:37:28.54,Default,,0,0,0,,因为表自动成为了流\nDialogue: 0,0:37:29.55,0:37:30.70,Default,,0,0,0,,表和流有一样的行为\nDialogue: 0,0:37:30.75,0:37:32.35,Default,,0,0,0,,所有的数据结构也会像那样\nDialogue: 0,0:37:32.35,0:37:33.64,Default,,0,0,0,,所有的都是\nDialogue: 0,0:37:35.07,0:37:37.63,Default,,0,0,0,,直到需要答案的时候\nDialogue: 0,0:37:37.66,0:37:39.42,Default,,0,0,0,,才会去实际的求值\nDialogue: 0,0:37:40.80,0:37:43.58,Default,,0,0,0,,不必再担心 什么时候需要显式地标注DELAY\nDialogue: 0,0:37:44.79,0:37:46.16,Default,,0,0,0,,为什么不这样做呢？\nDialogue: 0,0:37:47.16,0:37:48.81,Default,,0,0,0,,首先 已经有人这样做过了\nDialogue: 0,0:37:49.23,0:37:51.85,Default,,0,0,0,,有一些十分优雅的语言\nDialogue: 0,0:37:51.85,0:37:55.21,Default,,0,0,0,,其中最为人称道的是一门名为 Miranda 的语言\nDialogue: 0,0:37:55.77,0:37:56.76,Default,,0,0,0,,它是由\nDialogue: 0,0:37:57.44,0:37:59.80,Default,,0,0,0,,肯特大学的 David Turner 开发的\nDialogue: 0,0:38:00.71,0:38:01.93,Default,,0,0,0,,它就是用这样的原理实现的\nDialogue: 0,0:38:01.93,0:38:03.34,Default,,0,0,0,,Miranda是正则序求值语言\nDialogue: 0,0:38:04.27,0:38:05.55,Default,,0,0,0,,它的数据结构\nDialogue: 0,0:38:06.16,0:38:08.41,Default,,0,0,0,,看起来像表 实际上确实流\nDialogue: 0,0:38:08.96,0:38:10.91,Default,,0,0,0,,你不需要任何特殊的功能\nDialogue: 0,0:38:11.28,0:38:13.28,Default,,0,0,0,,就可以在Miranda中编写普通的过程\nDialogue: 0,0:38:13.32,0:38:14.97,Default,,0,0,0,,来解决质数、八皇后这样的问题\nDialogue: 0,0:38:14.97,0:38:16.35,Default,,0,0,0,,这些都是语言的内建功能\nDialogue: 0,0:38:17.93,0:38:18.91,Default,,0,0,0,,但这样做也要付出代价\nDialogue: 0,0:38:21.19,0:38:22.36,Default,,0,0,0,,还记得我们为什么引入流了吗？\nDialogue: 0,0:38:23.17,0:38:27.48,Default,,0,0,0,,我们分离了程序的时间和它实际执行的时间\nDialogue: 0,0:38:27.96,0:38:28.88,Default,,0,0,0,,如果我们引入了DELAY\nDialogue: 0,0:38:29.04,0:38:30.33,Default,,0,0,0,,这样就在所有的地方完成了解耦\nDialogue: 0,0:38:30.40,0:38:31.42,Default,,0,0,0,,而不单单是在流中\nDialogue: 0,0:38:32.19,0:38:33.14,Default,,0,0,0,,我们的初衷是什么？\nDialogue: 0,0:38:33.14,0:38:38.11,Default,,0,0,0,,我们把程序设计看做是指定计算过程\nDialogue: 0,0:38:39.30,0:38:40.62,Default,,0,0,0,,如果我们放弃了对时间的控制\nDialogue: 0,0:38:40.65,0:38:42.41,Default,,0,0,0,,尽管语言变得优雅起来\nDialogue: 0,0:38:43.74,0:38:45.87,Default,,0,0,0,,但是它的表达力却有所下降\nDialogue: 0,0:38:47.03,0:38:49.84,Default,,0,0,0,,这里面还有一些我们无法消除的区别\nDialogue: 0,0:38:51.48,0:38:53.15,Default,,0,0,0,,其中之一就是迭代\nDialogue: 0,0:38:53.98,0:38:56.44,Default,,0,0,0,,还记得这个程序吗？\nDialogue: 0,0:38:56.96,0:38:58.28,Default,,0,0,0,,迭代式的阶乘\nDialogue: 0,0:38:58.44,0:39:00.48,Default,,0,0,0,,这是我们很早之前就研究过的\nDialogue: 0,0:39:01.23,0:39:02.97,Default,,0,0,0,,过程FACT-ITER\nDialogue: 0,0:39:03.04,0:39:04.91,Default,,0,0,0,,有一个内部过程ITER\nDialogue: 0,0:39:05.18,0:39:07.50,Default,,0,0,0,,它含有两个状态PRODUCT和COUNTER\nDialogue: 0,0:39:08.70,0:39:10.96,Default,,0,0,0,,它们随着循环不断迭代\nDialogue: 0,0:39:12.12,0:39:13.68,Default,,0,0,0,,之所以说这个过程是迭代的\nDialogue: 0,0:39:13.71,0:39:14.83,Default,,0,0,0,,是因为它没有创建新状态\nDialogue: 0,0:39:15.73,0:39:17.45,Default,,0,0,0,,之所以没有创建新状态\nDialogue: 0,0:39:17.47,0:39:20.25,Default,,0,0,0,,是因为在调用ITER时\nDialogue: 0,0:39:20.30,0:39:22.86,Default,,0,0,0,,作为参数传递给它自己的始终是这些东西\nDialogue: 0,0:39:23.90,0:39:25.39,Default,,0,0,0,,在代换模型中\nDialogue: 0,0:39:25.55,0:39:27.79,Default,,0,0,0,,Gerald教授给你们讲解过\nDialogue: 0,0:39:28.72,0:39:30.01,Default,,0,0,0,,在迭代过程中\nDialogue: 0,0:39:30.03,0:39:31.44,Default,,0,0,0,,状态并不需要增长\nDialogue: 0,0:39:31.82,0:39:34.22,Default,,0,0,0,,因此这是一个迭代过程\nDialogue: 0,0:39:34.99,0:39:37.47,Default,,0,0,0,,但是如果用正则序语言\nDialogue: 0,0:39:37.47,0:39:39.10,Default,,0,0,0,,来运行这段程序\nDialogue: 0,0:39:41.15,0:39:42.17,Default,,0,0,0,,这就会导致\nDialogue: 0,0:39:42.88,0:39:44.96,Default,,0,0,0,,这个过程不再是迭代式了\nDialogue: 0,0:39:45.65,0:39:48.67,Default,,0,0,0,,如果你仔细地思考代换模型\nDialogue: 0,0:39:48.67,0:39:49.90,Default,,0,0,0,,在这里我就不细说了\nDialogue: 0,0:39:51.20,0:39:52.35,Default,,0,0,0,,这个表达式会不断增长\nDialogue: 0,0:39:52.36,0:39:53.18,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:39:53.28,0:39:55.20,Default,,0,0,0,,因为当ITER调用自己时\nDialogue: 0,0:39:55.85,0:39:57.31,Default,,0,0,0,,参数是这个乘法表达式\nDialogue: 0,0:39:58.08,0:39:59.36,Default,,0,0,0,,而在正则序语言中\nDialogue: 0,0:39:59.39,0:40:01.16,Default,,0,0,0,,这个乘法并不会在这里求值\nDialogue: 0,0:40:02.51,0:40:03.82,Default,,0,0,0,,传递给自己并代换的\nDialogue: 0,0:40:03.93,0:40:05.68,Default,,0,0,0,,只是这个乘法计算的PROMISE\nDialogue: 0,0:40:06.67,0:40:08.03,Default,,0,0,0,,然后继续代换下去\nDialogue: 0,0:40:09.76,0:40:11.55,Default,,0,0,0,,我调用自己\nDialogue: 0,0:40:11.84,0:40:14.04,Default,,0,0,0,,用的是计算这个乘法的PROMISE\nDialogue: 0,0:40:14.04,0:40:17.82,Default,,0,0,0,,但其中的一个因数也是个PROMISE\nDialogue: 0,0:40:18.40,0:40:19.43,Default,,0,0,0,,然后我又自调用\nDialogue: 0,0:40:19.43,0:40:21.13,Default,,0,0,0,,如果你用代换模型\nDialogue: 0,0:40:21.98,0:40:23.60,Default,,0,0,0,,来推演这个迭代步骤\nDialogue: 0,0:40:23.77,0:40:26.83,Default,,0,0,0,,你会发现同样的状态增长\nDialogue: 0,0:40:27.16,0:40:28.96,Default,,0,0,0,,所有的PROMISE都需要被记住\nDialogue: 0,0:40:28.97,0:40:30.76,Default,,0,0,0,,以便在最后被调用\nDialogue: 0,0:40:31.79,0:40:35.02,Default,,0,0,0,,所以 正则序的缺点之一\nDialogue: 0,0:40:35.05,0:40:36.86,Default,,0,0,0,,就是无法有效地表达迭代\nDialogue: 0,0:40:36.98,0:40:39.60,Default,,0,0,0,,也许这个理由有点偏理论\nDialogue: 0,0:40:39.61,0:40:43.90,Default,,0,0,0,,但事实上 那些使用这类语言来编写\nDialogue: 0,0:40:44.27,0:40:47.56,Default,,0,0,0,,实际操作系统的人 也都遇到了这类问题\nDialogue: 0,0:40:48.20,0:40:50.75,Default,,0,0,0,,当然 完全可以\nDialogue: 0,0:40:51.64,0:40:54.38,Default,,0,0,0,,用这类语言实现一个文本编辑器\nDialogue: 0,0:40:54.61,0:40:56.08,Default,,0,0,0,,但是你才用了一会儿\nDialogue: 0,0:40:56.72,0:40:59.39,Default,,0,0,0,,就发现已经占用了3MB空间\nDialogue: 0,0:40:59.44,0:41:02.04,Default,,0,0,0,,我想 那些遇到这类问题的人\nDialogue: 0,0:41:02.16,0:41:05.60,Default,,0,0,0,,把它叫做 “拖尾问题”\nDialogue: 0,0:41:05.82,0:41:08.20,Default,,0,0,0,,由于不能有效地表达迭代计算\nDialogue: 0,0:41:08.24,0:41:10.46,Default,,0,0,0,,导致堆积了一堆没有被调用的PROMISE\nDialogue: 0,0:41:10.72,0:41:14.81,Default,,0,0,0,,针对这类语言的一个研究方向就是\nDialogue: 0,0:41:14.83,0:41:17.48,Default,,0,0,0,,找出一种有效的编译器技术\nDialogue: 0,0:41:17.82,0:41:19.85,Default,,0,0,0,,来避免这种所谓的“拖尾问题”\nDialogue: 0,0:41:20.17,0:41:21.61,Default,,0,0,0,,这并不简单\nDialogue: 0,0:41:23.94,0:41:27.31,Default,,0,0,0,,但是 还有一个很突出的问题\nDialogue: 0,0:41:27.96,0:41:31.04,Default,,0,0,0,,使你的语言不能变成正则序\nDialogue: 0,0:41:32.51,0:41:33.29,Default,,0,0,0,,问题就在于\nDialogue: 0,0:41:35.05,0:41:38.09,Default,,0,0,0,,正则序和副作用\nDialogue: 0,0:41:38.89,0:41:40.19,Default,,0,0,0,,是不相容的\nDialogue: 0,0:41:42.00,0:41:43.96,Default,,0,0,0,,它们不能很好地相互配合\nDialogue: 0,0:41:45.44,0:41:46.65,Default,,0,0,0,,这是因为 你不能\nDialogue: 0,0:41:48.28,0:41:50.80,Default,,0,0,0,,你不能一边\nDialogue: 0,0:41:51.00,0:41:54.33,Default,,0,0,0,,建模具有局部状态的对象\nDialogue: 0,0:41:55.72,0:41:56.96,Default,,0,0,0,,同时又\nDialogue: 0,0:41:57.18,0:41:59.55,Default,,0,0,0,,使用正则序的技巧来解耦时间\nDialogue: 0,0:42:00.40,0:42:03.55,Default,,0,0,0,,我来举一个非常简单的例子\nDialogue: 0,0:42:03.79,0:42:05.50,Default,,0,0,0,,假设语言是正则序求值\nDialogue: 0,0:42:07.52,0:42:09.55,Default,,0,0,0,,例子是这样的\nDialogue: 0,0:42:09.55,0:42:10.52,Default,,0,0,0,,注意现在是正则序求值\nDialogue: 0,0:42:10.52,0:42:12.22,Default,,0,0,0,,(DEFINE X 0)\nDialogue: 0,0:42:13.57,0:42:15.56,Default,,0,0,0,,这只是变量的初始化\nDialogue: 0,0:42:15.75,0:42:17.69,Default,,0,0,0,,现在我要定义一个有趣的函数\nDialogue: 0,0:42:18.57,0:42:20.44,Default,,0,0,0,,它就是恒等函数ID\nDialogue: 0,0:42:22.64,0:42:23.90,Default,,0,0,0,,它所做的就是\nDialogue: 0,0:42:24.11,0:42:26.60,Default,,0,0,0,,用X来记录上一次调用它时N的值\nDialogue: 0,0:42:31.40,0:42:34.16,Default,,0,0,0,,因此(ID N)就返回N\nDialogue: 0,0:42:34.17,0:42:35.39,Default,,0,0,0,,但还要把X赋值为N\nDialogue: 0,0:42:36.76,0:42:38.54,Default,,0,0,0,,最后再定义一个过程INC\nDialogue: 0,0:42:39.55,0:42:42.30,Default,,0,0,0,,也非常简单\nDialogue: 0,0:42:42.58,0:42:45.34,Default,,0,0,0,,假设在正则序求值的语言里\nDialogue: 0,0:42:46.27,0:42:47.23,Default,,0,0,0,,求值下面的表达式\nDialogue: 0,0:42:47.23,0:42:52.83,Default,,0,0,0,,我输入 (DEFINE Y (INC (ID 3)))\nDialogue: 0,0:42:52.83,0:42:53.96,Default,,0,0,0,,因此Y的值应该是4\nDialogue: 0,0:42:57.41,0:42:58.35,Default,,0,0,0,,X应该是多少呢？\nDialogue: 0,0:42:59.52,0:43:02.16,Default,,0,0,0,,X应该是最后一次被记住的值\nDialogue: 0,0:43:02.64,0:43:04.01,Default,,0,0,0,,也就是我调用函数ID的时候\nDialogue: 0,0:43:04.71,0:43:06.73,Default,,0,0,0,,你可能会想 这里X应该是3\nDialogue: 0,0:43:06.91,0:43:07.52,Default,,0,0,0,,但是并不是这样\nDialogue: 0,0:43:08.53,0:43:11.15,Default,,0,0,0,,这是因为当我在这里定义Y的时候\nDialogue: 0,0:43:11.79,0:43:13.45,Default,,0,0,0,,Y的真正定义却是\nDialogue: 0,0:43:13.47,0:43:15.71,Default,,0,0,0,,一个调用函数ID的PROMISE的增量\nDialogue: 0,0:43:17.00,0:43:18.17,Default,,0,0,0,,因为我没有访问Y\nDialogue: 0,0:43:18.36,0:43:20.25,Default,,0,0,0,,所以ID没有运行\nDialogue: 0,0:43:21.56,0:43:23.20,Default,,0,0,0,,我输入这个定义之后\nDialogue: 0,0:43:23.31,0:43:24.80,Default,,0,0,0,,然后查询X得到的结果是0\nDialogue: 0,0:43:28.36,0:43:31.20,Default,,0,0,0,,现在 我输入Y查询它的值\nDialogue: 0,0:43:31.52,0:43:32.43,Default,,0,0,0,,就会得到结果4\nDialogue: 0,0:43:32.67,0:43:35.16,Default,,0,0,0,,对Y的主动查询\nDialogue: 0,0:43:35.29,0:43:37.42,Default,,0,0,0,,会导致ID运行\nDialogue: 0,0:43:38.72,0:43:40.48,Default,,0,0,0,,现在X=3就被记住\nDialogue: 0,0:43:40.74,0:43:41.87,Default,,0,0,0,,所以上面这里的X就应该是0\nDialogue: 0,0:43:41.93,0:43:42.96,Default,,0,0,0,,下面这里是3\nDialogue: 0,0:43:43.28,0:43:46.16,Default,,0,0,0,,这是一个非常简单的场景\nDialogue: 0,0:43:46.30,0:43:49.28,Default,,0,0,0,,但你会发现 调试正则序语言\nDialogue: 0,0:43:50.36,0:43:53.34,Default,,0,0,0,,的交互式程序\nDialogue: 0,0:43:54.12,0:43:55.88,Default,,0,0,0,,会变得相当混乱\nDialogue: 0,0:43:57.10,0:43:58.12,Default,,0,0,0,,很令人迷惑\nDialogue: 0,0:43:59.69,0:44:02.04,Default,,0,0,0,,导致这样的深层次的原因\nDialogue: 0,0:44:02.80,0:44:06.41,Default,,0,0,0,,也就是引入DELAY的根本理念\nDialogue: 0,0:44:06.92,0:44:08.43,Default,,0,0,0,,是因为我们抛弃了时间的概念\nDialogue: 0,0:44:09.78,0:44:11.75,Default,,0,0,0,,也因为如此我们可以处理一些无穷的情况\nDialogue: 0,0:44:11.75,0:44:12.97,Default,,0,0,0,,我们抛弃了时间\nDialogue: 0,0:44:12.99,0:44:14.27,Default,,0,0,0,,就没有必要等它们运行\nDialogue: 0,0:44:17.55,0:44:20.44,Default,,0,0,0,,我们把计算机中事件发生的顺序\nDialogue: 0,0:44:20.83,0:44:22.11,Default,,0,0,0,,与程序中的顺序 分离开来\nDialogue: 0,0:44:22.35,0:44:25.28,Default,,0,0,0,,但是当我们谈及状态、赋值和改变的时候\nDialogue: 0,0:44:25.48,0:44:27.42,Default,,0,0,0,,这些又都是我们想要控制的\nDialogue: 0,0:44:28.76,0:44:33.82,Default,,0,0,0,,我们的目的有着根本性的矛盾\nDialogue: 0,0:44:34.57,0:44:39.12,Default,,0,0,0,,这又让我们进入了一个哲学问题\nDialogue: 0,0:44:39.13,0:44:40.75,Default,,0,0,0,,用什么样的模型\nDialogue: 0,0:44:40.78,0:44:41.77,Default,,0,0,0,,和从什么角度来看这个世界\nDialogue: 0,0:44:42.41,0:44:44.30,Default,,0,0,0,,有时这也被称为\nDialogue: 0,0:44:44.76,0:44:46.60,Default,,0,0,0,,“函数式程序设计的争论”\nDialogue: 0,0:44:54.19,0:44:56.60,Default,,0,0,0,,所谓的“纯函数式语言”\nDialogue: 0,0:44:57.07,0:44:59.20,Default,,0,0,0,,是完全没有副作用的\nDialogue: 0,0:45:00.44,0:45:01.63,Default,,0,0,0,,不需要副作用\nDialogue: 0,0:45:01.64,0:45:03.02,Default,,0,0,0,,也就不需要赋值运算符\nDialogue: 0,0:45:03.34,0:45:05.72,Default,,0,0,0,,也就没有什么糟糕的后果\nDialogue: 0,0:45:06.36,0:45:07.93,Default,,0,0,0,,可以使用类似代换模型\nDialogue: 0,0:45:07.93,0:45:10.48,Default,,0,0,0,,程序更像是数学\nDialogue: 0,0:45:10.76,0:45:13.82,Default,,0,0,0,,而不像现实世界中的模型和对象\nDialogue: 0,0:45:15.05,0:45:17.17,Default,,0,0,0,,函数式语言有很多了不起的特性\nDialogue: 0,0:45:17.17,0:45:19.63,Default,,0,0,0,,没有时间的概念 所以完全不用担心同步的问题\nDialogue: 0,0:45:20.64,0:45:23.72,Default,,0,0,0,,如果你想在并行算法中应用一些东西\nDialogue: 0,0:45:24.72,0:45:28.20,Default,,0,0,0,,你可以在这些并行过程中随心所欲地使用\nDialogue: 0,0:45:29.40,0:45:31.44,Default,,0,0,0,,从来不担心同步问题\nDialogue: 0,0:45:31.50,0:45:33.34,Default,,0,0,0,,在这种环境下这样做是非常方便的\nDialogue: 0,0:45:33.64,0:45:35.71,Default,,0,0,0,,代价则是 放弃了赋值\nDialogue: 0,0:45:39.10,0:45:41.32,Default,,0,0,0,,函数式语言的支持者会认为\nDialogue: 0,0:45:41.34,0:45:43.04,Default,,0,0,0,,这点代价算不了什么\nDialogue: 0,0:45:44.52,0:45:46.51,Default,,0,0,0,,在大部分情况下 你都不应该使用赋值\nDialogue: 0,0:45:46.88,0:45:48.27,Default,,0,0,0,,如果用你放弃了赋值\nDialogue: 0,0:45:48.43,0:45:51.40,Default,,0,0,0,,你可以得到一个比对象世界\nDialogue: 0,0:45:51.96,0:45:53.24,Default,,0,0,0,,好得多的世界\nDialogue: 0,0:45:54.19,0:45:56.30,Default,,0,0,0,,怎么来反驳这个观点呢？\nDialogue: 0,0:45:56.30,0:45:58.59,Default,,0,0,0,,想想 我们如何走到这一步的\nDialogue: 0,0:46:00.06,0:46:03.79,Default,,0,0,0,,我们尝试建模具有局部状态的对象\nDialogue: 0,0:46:04.44,0:46:06.49,Default,,0,0,0,,想一想Gerald教授给你们讲的随机数生成器\nDialogue: 0,0:46:07.16,0:46:08.67,Default,,0,0,0,,这里有一个随机数生成器\nDialogue: 0,0:46:09.28,0:46:10.62,Default,,0,0,0,,它内部有一些状态\nDialogue: 0,0:46:10.83,0:46:12.08,Default,,0,0,0,,用来计算下一个随机数\nDialogue: 0,0:46:12.12,0:46:14.08,Default,,0,0,0,,下下一个 以及再下一个\nDialogue: 0,0:46:14.28,0:46:16.14,Default,,0,0,0,,我们想要把这些状态跟\nDialogue: 0,0:46:16.43,0:46:18.96,Default,,0,0,0,,计算π的Cesaro算法分离开来\nDialogue: 0,0:46:19.84,0:46:20.92,Default,,0,0,0,,这就是我们为什么需要赋值\nDialogue: 0,0:46:20.97,0:46:22.91,Default,,0,0,0,,我们想要把状态封装在模块中\nDialogue: 0,0:46:24.07,0:46:26.36,Default,,0,0,0,,函数式语言程序员可能会说\nDialogue: 0,0:46:26.38,0:46:27.56,Default,,0,0,0,,“你搞错了”\nDialogue: 0,0:46:27.56,0:46:29.84,Default,,0,0,0,,“我的意思是 你能写出另一种更具模块化的程序”\nDialogue: 0,0:46:29.84,0:46:32.46,Default,,0,0,0,,“你对模块化的认识并不正确”\nDialogue: 0,0:46:33.08,0:46:35.02,Default,,0,0,0,,你太执着于 “生成一个随机数\nDialogue: 0,0:46:35.07,0:46:36.88,Default,,0,0,0,,再生成一个 再生成一个” 这种范式了\nDialogue: 0,0:46:36.88,0:46:39.42,Default,,0,0,0,,为什么不写一个这样的程序\nDialogue: 0,0:46:40.09,0:46:41.29,Default,,0,0,0,,构造一个枚举器\nDialogue: 0,0:46:41.95,0:46:44.48,Default,,0,0,0,,它会生成一个随机数的无穷流\nDialogue: 0,0:46:49.01,0:46:50.91,Default,,0,0,0,,我们可以立即生成这个流\nDialogue: 0,0:46:52.64,0:46:54.54,Default,,0,0,0,,这样就可以用作随机数的源泉\nDialogue: 0,0:46:54.54,0:46:55.24,Default,,0,0,0,,如果有需要的话\nDialogue: 0,0:46:55.53,0:46:57.47,Default,,0,0,0,,你可以把它跟某个处理过程相连\nDialogue: 0,0:46:57.77,0:47:01.16,Default,,0,0,0,,比如说Cesaro测试\nDialogue: 0,0:47:04.94,0:47:06.22,Default,,0,0,0,,然后这个处理过程进行自己的计算\nDialogue: 0,0:47:06.88,0:47:08.56,Default,,0,0,0,,从这里出来的则是\nDialogue: 0,0:47:08.72,0:47:27.45,Default,,0,0,0,,其中是一串的对π的估计值组成的流\nDialogue: 0,0:47:28.14,0:47:30.65,Default,,0,0,0,,随着我们深入访问这个流\nDialogue: 0,0:47:30.76,0:47:32.38,Default,,0,0,0,,相当于去拽这个Cesaro盒子\nDialogue: 0,0:47:33.12,0:47:35.36,Default,,0,0,0,,它就会拉取出许多随机数\nDialogue: 0,0:47:35.54,0:47:37.21,Default,,0,0,0,,随着我们对流的深入访问\nDialogue: 0,0:47:37.23,0:47:38.96,Default,,0,0,0,,得到的对π的估计值就越准\nDialogue: 0,0:47:39.72,0:47:41.66,Default,,0,0,0,,具体的计算过程还是一样的\nDialogue: 0,0:47:41.66,0:47:43.79,Default,,0,0,0,,只不过使用了另一种模块化的方式\nDialogue: 0,0:47:43.89,0:47:45.55,Default,,0,0,0,,我们可以想象成一下子\nDialogue: 0,0:47:45.56,0:47:47.47,Default,,0,0,0,,就有了这所有的随机数\nDialogue: 0,0:47:49.28,0:47:52.24,Default,,0,0,0,,这个过程的细节在书上有\nDialogue: 0,0:47:53.61,0:47:57.85,Default,,0,0,0,,我们同样也陷于另外一些类似的事情中\nDialogue: 0,0:47:58.27,0:48:01.20,Default,,0,0,0,,这种关于 这个、下一个以及再下一个的范式\nDialogue: 0,0:48:01.37,0:48:02.81,Default,,0,0,0,,完全可以不这么来做\nDialogue: 0,0:48:03.28,0:48:06.54,Default,,0,0,0,,我们来思考一下银行系统\nDialogue: 0,0:48:07.68,0:48:08.90,Default,,0,0,0,,有个非常简单的场景\nDialogue: 0,0:48:08.90,0:48:12.21,Default,,0,0,0,,我们假设这个程序代表了银行帐户\nDialogue: 0,0:48:18.81,0:48:20.84,Default,,0,0,0,,银行账户中可能有\nDialogue: 0,0:48:22.78,0:48:26.22,Default,,0,0,0,,如果我们以消息传递的角度来看\nDialogue: 0,0:48:26.44,0:48:28.12,Default,,0,0,0,,我们认为银行账户是一个对象\nDialogue: 0,0:48:28.59,0:48:31.51,Default,,0,0,0,,内部保存着标识余额的局部状态BALANCE\nDialogue: 0,0:48:34.11,0:48:36.00,Default,,0,0,0,,如果一个用户使用这个系统\nDialogue: 0,0:48:36.44,0:48:38.14,Default,,0,0,0,,发出交易请求\nDialogue: 0,0:48:39.31,0:48:41.05,Default,,0,0,0,,用户发出的交易请求可能是\nDialogue: 0,0:48:41.07,0:48:42.20,Default,,0,0,0,,存一些钱\nDialogue: 0,0:48:42.28,0:48:43.53,Default,,0,0,0,,银行账户就会\nDialogue: 0,0:48:43.92,0:48:46.78,Default,,0,0,0,,我们假设银行账户总是以当前余额作为回应\nDialogue: 0,0:48:48.22,0:48:50.04,Default,,0,0,0,,用户存了一些钱\nDialogue: 0,0:48:50.06,0:48:53.21,Default,,0,0,0,,银行账户就会返回一个消息指明当前余额\nDialogue: 0,0:48:54.35,0:48:57.42,Default,,0,0,0,,用户再存一些钱\nDialogue: 0,0:48:57.45,0:48:58.81,Default,,0,0,0,,银行就再返回消息\nDialogue: 0,0:48:59.15,0:49:00.75,Default,,0,0,0,,就像生成随机数一样\nDialogue: 0,0:49:00.78,0:49:02.12,Default,,0,0,0,,我们想使用赋值来实现\nDialogue: 0,0:49:03.20,0:49:06.88,Default,,0,0,0,,帐户的内部保存了局部状态BALANCE\nDialogue: 0,0:49:06.88,0:49:08.40,Default,,0,0,0,,因为我们想要把用户状态\nDialogue: 0,0:49:08.41,0:49:09.57,Default,,0,0,0,,和银行账户的状态分离开来\nDialogue: 0,0:49:13.28,0:49:16.42,Default,,0,0,0,,这是从消息传递的角度来看\nDialogue: 0,0:49:16.42,0:49:18.20,Default,,0,0,0,,如果从流的角度来看\nDialogue: 0,0:49:19.48,0:49:22.19,Default,,0,0,0,,不需要赋值或副作用就可以达到同样的效果\nDialogue: 0,0:49:22.74,0:49:26.73,Default,,0,0,0,,再次强调 想法是这样的\nDialogue: 0,0:49:27.37,0:49:30.25,Default,,0,0,0,,我们认为它们都没有局部状态\nDialogue: 0,0:49:31.18,0:49:33.08,Default,,0,0,0,,我们把银行账户看作是\nDialogue: 0,0:49:33.40,0:49:37.71,Default,,0,0,0,,能够处理一系列交易请求的东西\nDialogue: 0,0:49:38.64,0:49:40.16,Default,,0,0,0,,不把银行账户看做\nDialogue: 0,0:49:40.22,0:49:42.00,Default,,0,0,0,,逐个消息地处理\nDialogue: 0,0:49:42.44,0:49:45.85,Default,,0,0,0,,而是处理某种交易请求流的东西\nDialogue: 0,0:49:45.87,0:49:48.49,Default,,0,0,0,,这个请求流可能是一些列的存款声明\nDialogue: 0,0:49:49.49,0:49:54.94,Default,,0,0,0,,比如 1 2 2 4 这样的连续存钱请求\nDialogue: 0,0:49:55.94,0:50:02.44,Default,,0,0,0,,从帐户出来的流应该是 1 3 5 9\nDialogue: 0,0:50:03.77,0:50:06.14,Default,,0,0,0,,我们不把银行账户看做某种具有状态的东西\nDialogue: 0,0:50:06.40,0:50:07.26,Default,,0,0,0,,而是某种能够处理\nDialogue: 0,0:50:08.92,0:50:10.82,Default,,0,0,0,,有关请求的无穷流的东西\nDialogue: 0,0:50:10.82,0:50:12.30,Default,,0,0,0,,但要注意 我们抛弃了时间\nDialogue: 0,0:50:12.37,0:50:14.27,Default,,0,0,0,,如果这里有一个用户\nDialogue: 0,0:50:16.12,0:50:19.13,Default,,0,0,0,,这个无穷请求流的元素\nDialogue: 0,0:50:19.18,0:50:22.54,Default,,0,0,0,,我们可以一次生成一个\nDialogue: 0,0:50:24.06,0:50:26.57,Default,,0,0,0,,而这个交易流\nDialogue: 0,0:50:26.57,0:50:28.80,Default,,0,0,0,,则会逐个打印在屏幕上\nDialogue: 0,0:50:30.01,0:50:31.37,Default,,0,0,0,,如果在这里画一条线\nDialogue: 0,0:50:32.56,0:50:33.08,Default,,0,0,0,,就在这里\nDialogue: 0,0:50:33.28,0:50:34.91,Default,,0,0,0,,对用户来说 他根本无法分辨\nDialogue: 0,0:50:36.19,0:50:37.71,Default,,0,0,0,,这个系统是否有内部状态\nDialogue: 0,0:50:39.56,0:50:41.13,Default,,0,0,0,,这个跟消息传递那种是一样的\nDialogue: 0,0:50:41.29,0:50:42.46,Default,,0,0,0,,只不过这个没有状态\nDialogue: 0,0:50:42.84,0:50:45.87,Default,,0,0,0,,哦 顺便提一下\nDialogue: 0,0:50:46.72,0:50:49.47,Default,,0,0,0,,这是具体的代码实现\nDialogue: 0,0:50:50.52,0:50:52.30,Default,,0,0,0,,我们把它叫做MAKE-DEPOSIT-ACCOUNT\nDialogue: 0,0:50:52.32,0:50:53.32,Default,,0,0,0,,因为它只能够存钱\nDialogue: 0,0:50:54.17,0:50:55.77,Default,,0,0,0,,这个过程接受一个初始余额\nDialogue: 0,0:50:56.09,0:50:58.09,Default,,0,0,0,,以及一个可能发起的存款流\nDialogue: 0,0:51:00.02,0:51:00.82,Default,,0,0,0,,具体怎么做呢？\nDialogue: 0,0:51:00.82,0:51:02.54,Default,,0,0,0,,它只是用CONS-STREAM把余额BALANCE\nDialogue: 0,0:51:03.23,0:51:05.31,Default,,0,0,0,,和一个新的存款账户流组合在一起\nDialogue: 0,0:51:06.24,0:51:07.32,Default,,0,0,0,,新存款流的初始余额\nDialogue: 0,0:51:07.48,0:51:10.27,Default,,0,0,0,,就是之前BALANCE的值加上存款流的第一个元素\nDialogue: 0,0:51:10.86,0:51:13.40,Default,,0,0,0,,而其余部分则是\nDialogue: 0,0:51:13.76,0:51:17.37,Default,,0,0,0,,存款流的尾部分\nDialogue: 0,0:51:18.30,0:51:23.84,Default,,0,0,0,,因此这种非常典型的消息传递式、面向对象的问题\nDialogue: 0,0:51:23.95,0:51:27.55,Default,,0,0,0,,完全可以不用副作用来解决\nDialogue: 0,0:51:29.05,0:51:30.76,Default,,0,0,0,,很多地方都可以这样做\nDialogue: 0,0:51:32.25,0:51:35.23,Default,,0,0,0,,那么 我们可以完全不用赋值么？\nDialogue: 0,0:51:36.40,0:51:39.00,Default,,0,0,0,,可以只用纯函数式语言吗？\nDialogue: 0,0:51:40.05,0:51:42.04,Default,,0,0,0,,这个问题谁也说不清\nDialogue: 0,0:51:42.27,0:51:43.44,Default,,0,0,0,,好像有些地方\nDialogue: 0,0:51:43.92,0:51:46.03,Default,,0,0,0,,纯函数式语言无法派上用场\nDialogue: 0,0:51:48.10,0:51:50.27,Default,,0,0,0,,当遇到像这样的系统时 问题就变得棘手起来\nDialogue: 0,0:51:50.43,0:51:52.32,Default,,0,0,0,,特别是当你\nDialogue: 0,0:51:52.60,0:51:54.27,Default,,0,0,0,,还需要考虑其它因素的时候\nDialogue: 0,0:51:54.30,0:51:55.64,Default,,0,0,0,,有关对象和共享\nDialogue: 0,0:51:55.90,0:51:58.52,Default,,0,0,0,,以及两个独立的主体共享同一个东西\nDialogue: 0,0:51:58.85,0:51:59.93,Default,,0,0,0,,举一个典型的例子\nDialogue: 0,0:51:59.96,0:52:01.63,Default,,0,0,0,,假如你来扩展这个帐户\nDialogue: 0,0:52:03.24,0:52:04.27,Default,,0,0,0,,这是一个帐户\nDialogue: 0,0:52:12.22,0:52:14.75,Default,,0,0,0,,帐户接受一个交易请求流\nDialogue: 0,0:52:15.20,0:52:18.44,Default,,0,0,0,,输出的流则是关于余额的回复\nDialogue: 0,0:52:18.78,0:52:20.16,Default,,0,0,0,,假设你所建模的是联合账户\nDialogue: 0,0:52:20.17,0:52:24.36,Default,,0,0,0,,而由两个独立用户共享\nDialogue: 0,0:52:25.68,0:52:28.65,Default,,0,0,0,,我们假设 假设有两个人\nDialogue: 0,0:52:28.97,0:52:30.96,Default,,0,0,0,,比如说Bill和Dave\nDialogue: 0,0:52:31.77,0:52:33.14,Default,,0,0,0,,他们俩共享一个帐户\nDialogue: 0,0:52:35.96,0:52:36.85,Default,,0,0,0,,怎么来建模呢？\nDialogue: 0,0:52:36.88,0:52:39.80,Default,,0,0,0,,你或许会让Bill输出一个交易请求流\nDialogue: 0,0:52:40.24,0:52:42.25,Default,,0,0,0,,Dave也产生一个这样的流\nDialogue: 0,0:52:42.25,0:52:45.16,Default,,0,0,0,,这两个流需要以某种方式合并到银行账户中\nDialogue: 0,0:52:45.88,0:52:47.85,Default,,0,0,0,,因此你需要编写一个MERGE过程\nDialogue: 0,0:52:47.90,0:52:50.65,Default,,0,0,0,,来处理这些流\nDialogue: 0,0:52:57.23,0:52:59.13,Default,,0,0,0,,它把这些流合并在一起\nDialogue: 0,0:52:59.34,0:53:01.19,Default,,0,0,0,,形成单个流 送入银行账户\nDialogue: 0,0:53:01.19,0:53:02.99,Default,,0,0,0,,现在他们就共享一个帐户了\nDialogue: 0,0:53:03.61,0:53:05.48,Default,,0,0,0,,看起来不错 问题是怎么来实现MERGE\nDialogue: 0,0:53:05.93,0:53:08.24,Default,,0,0,0,,MERGE怎么来合并？\nDialogue: 0,0:53:09.73,0:53:11.42,Default,,0,0,0,,需要合理的合并依据\nDialogue: 0,0:53:12.38,0:53:13.80,Default,,0,0,0,,你可能首先会想\nDialogue: 0,0:53:13.80,0:53:16.68,Default,,0,0,0,,我们从Bill和Dave中选一个请求来处理\nDialogue: 0,0:53:18.19,0:53:20.97,Default,,0,0,0,,但是如果在这中途\nDialogue: 0,0:53:21.18,0:53:23.08,Default,,0,0,0,,Dave突然外出度假两年 会怎么样？\nDialogue: 0,0:53:24.15,0:53:25.40,Default,,0,0,0,,Bill的交易就完全被阻塞了\nDialogue: 0,0:53:27.69,0:53:29.75,Default,,0,0,0,,你想要的是\nDialogue: 0,0:53:29.75,0:53:33.64,Default,,0,0,0,,是一种公平的合并\nDialogue: 0,0:53:38.41,0:53:40.17,Default,,0,0,0,,这个所谓公平的合并\nDialogue: 0,0:53:40.73,0:53:42.46,Default,,0,0,0,,应该是交替地一次处理一个\nDialogue: 0,0:53:42.49,0:53:43.92,Default,,0,0,0,,但是如果一个人没有了交易\nDialogue: 0,0:53:43.96,0:53:44.91,Default,,0,0,0,,应该继续去处理另一个人的交易\nDialogue: 0,0:53:46.01,0:53:48.45,Default,,0,0,0,,但是没有时间 我就不能这样做\nDialogue: 0,0:53:51.30,0:53:56.41,Default,,0,0,0,,函数式语言的另一个活跃研究领域就是\nDialogue: 0,0:53:56.43,0:53:59.48,Default,,0,0,0,,发明类似于“公平合并”的算法\nDialogue: 0,0:54:00.35,0:54:01.31,Default,,0,0,0,,又或者是其它的东西\nDialogue: 0,0:54:01.56,0:54:06.25,Default,,0,0,0,,用于取代原来需要副作用和对象的地方\nDialogue: 0,0:54:06.80,0:54:10.52,Default,,0,0,0,,用一种良好定义的模块化系统来隐藏它们\nDialogue: 0,0:54:10.86,0:54:13.50,Default,,0,0,0,,这样 系统中就不会到处产生\nDialogue: 0,0:54:13.52,0:54:15.34,Default,,0,0,0,,赋值所带来的问题\nDialogue: 0,0:54:15.40,0:54:17.88,Default,,0,0,0,,因为它可以被理解透彻的概念所描述\nDialogue: 0,0:54:20.78,0:54:22.70,Default,,0,0,0,,推而广之 我想你们也发现了\nDialogue: 0,0:54:23.12,0:54:24.06,Default,,0,0,0,,我们正面对 我所认为的\nDialogue: 0,0:54:24.08,0:54:26.67,Default,,0,0,0,,计算机科学中最基本的问题\nDialogue: 0,0:54:26.97,0:54:27.82,Default,,0,0,0,,也就是\nDialogue: 0,0:54:28.24,0:54:32.03,Default,,0,0,0,,我们如何定义一门支持延迟求值的语言\nDialogue: 0,0:54:34.14,0:54:35.08,Default,,0,0,0,,但同时又能够\nDialogue: 0,0:54:35.87,0:54:38.25,Default,,0,0,0,,又能够把事物看做对象来操作\nDialogue: 0,0:54:38.36,0:54:40.36,Default,,0,0,0,,怎么样才能两者兼有之？\nDialogue: 0,0:54:41.23,0:54:43.04,Default,,0,0,0,,我认为这个问题很困难\nDialogue: 0,0:54:43.04,0:54:45.52,Default,,0,0,0,,但是这个很困难的问题\nDialogue: 0,0:54:45.85,0:54:48.17,Default,,0,0,0,,却和计算机科学的关系不大\nDialogue: 0,0:54:48.59,0:54:50.24,Default,,0,0,0,,它真正涉及的是\nDialogue: 0,0:54:50.27,0:54:52.73,Default,,0,0,0,,两种不相容的看待世界的方式\nDialogue: 0,0:54:54.14,0:54:54.72,Default,,0,0,0,,有问题吗？\nDialogue: 0,0:55:17.55,0:55:19.20,Default,,0,0,0,,学生：你之前提到过\nDialogue: 0,0:55:20.11,0:55:21.32,Default,,0,0,0,,一旦引入了赋值\nDialogue: 0,0:55:21.32,0:55:25.89,Default,,0,0,0,,就不能使用代换模型了\nDialogue: 0,0:55:25.89,0:55:27.57,Default,,0,0,0,,除非你非常小心\nDialogue: 0,0:55:27.57,0:55:27.96,Default,,0,0,0,,教授：对的\nDialogue: 0,0:55:28.26,0:55:33.28,Default,,0,0,0,,学生：有什么技术或者指导方针\nDialogue: 0,0:55:33.42,0:55:35.92,Default,,0,0,0,,来确定赋值的影响\nDialogue: 0,0:55:36.52,0:55:40.30,Default,,0,0,0,,以便说清楚这个“很小心”是怎么回事吗？\nDialogue: 0,0:55:40.30,0:55:42.60,Default,,0,0,0,,教授：我不知道\nDialogue: 0,0:55:42.89,0:55:43.58,Default,,0,0,0,,我想想\nDialogue: 0,0:55:45.43,0:55:48.94,Default,,0,0,0,,当然 实现MEM-PROC也使用了赋值\nDialogue: 0,0:55:50.12,0:55:51.48,Default,,0,0,0,,但是它被隐藏了起来\nDialogue: 0,0:55:51.48,0:55:53.00,Default,,0,0,0,,因为它没有对结果造成影响\nDialogue: 0,0:55:53.48,0:55:56.44,Default,,0,0,0,,部分原因之一在于 一旦触发这个过程\nDialogue: 0,0:55:57.15,0:55:58.83,Default,,0,0,0,,它被求值并得到结果\nDialogue: 0,0:55:58.83,0:56:00.06,Default,,0,0,0,,这个结果不会再变化\nDialogue: 0,0:56:00.60,0:56:02.33,Default,,0,0,0,,有点像单次赋值\nDialogue: 0,0:56:02.35,0:56:03.85,Default,,0,0,0,,一个一般性原则就是\nDialogue: 0,0:56:04.30,0:56:06.35,Default,,0,0,0,,如果你只用这种单次赋值\nDialogue: 0,0:56:08.04,0:56:09.24,Default,,0,0,0,,并且它不再改变\nDialogue: 0,0:56:09.63,0:56:10.54,Default,,0,0,0,,我想应该不会有太大问题\nDialogue: 0,0:56:11.25,0:56:14.12,Default,,0,0,0,,还有一个问题在于MERGE --\nDialogue: 0,0:56:14.67,0:56:18.32,Default,,0,0,0,,让我想想对不对\nDialogue: 0,0:56:18.49,0:56:21.55,Default,,0,0,0,,我认为有了公平合并这一技术\nDialogue: 0,0:56:22.25,0:56:26.09,Default,,0,0,0,,你可以在语言的其它地方\nDialogue: 0,0:56:27.02,0:56:28.89,Default,,0,0,0,,有效地模拟赋值\nDialogue: 0,0:56:30.82,0:56:33.29,Default,,0,0,0,,这就像为了解决问题你会引入一些东西\nDialogue: 0,0:56:33.50,0:56:35.50,Default,,0,0,0,,我不清楚对公平合并来说是否成立\nDialogue: 0,0:56:35.53,0:56:39.31,Default,,0,0,0,,但是对人们正在尝试的一些一般性事情是成立的\nDialogue: 0,0:56:39.52,0:56:41.34,Default,,0,0,0,,所以 这可能是你引入的这一点点东西\nDialogue: 0,0:56:41.61,0:56:44.14,Default,,0,0,0,,突然间 使你能构建任何东西\nDialogue: 0,0:56:44.16,0:56:46.51,Default,,0,0,0,,这就几乎跟有了赋值一样糟糕了\nDialogue: 0,0:56:47.97,0:56:50.67,Default,,0,0,0,,这也是人们在研究的一个领域\nDialogue: 0,0:56:51.59,0:56:54.30,Default,,0,0,0,,学生：我还没有太明白MERGE的问题\nDialogue: 0,0:56:54.83,0:56:59.20,Default,,0,0,0,,如果我调用Bill它是个过程\nDialogue: 0,0:56:59.21,0:57:02.41,Default,,0,0,0,,那么Bill就会增加银行账户\nDialogue: 0,0:57:02.44,0:57:04.73,Default,,0,0,0,,或者创建一个表 用于放置下一个存款\nDialogue: 0,0:57:04.73,0:57:06.84,Default,,0,0,0,,如果我连续调用Dave两次 他肯定也会那样\nDialogue: 0,0:57:07.17,0:57:09.35,Default,,0,0,0,,我并不清楚为什么需要公平合并\nDialogue: 0,0:57:09.35,0:57:11.20,Default,,0,0,0,,教授：关键在于你得把这些当作真人一样\nDialogue: 0,0:57:11.20,0:57:14.20,Default,,0,0,0,,这里有一个用户在操作帐户\nDialogue: 0,0:57:14.85,0:57:17.07,Default,,0,0,0,,请求一次 得到结果\nDialogue: 0,0:57:17.20,0:57:17.56,Default,,0,0,0,,学生：对\nDialogue: 0,0:57:18.20,0:57:20.62,Default,,0,0,0,,教授：如果我只能通过从两个流中选择一个\nDialogue: 0,0:57:20.65,0:57:22.25,Default,,0,0,0,,来处理请求的话\nDialogue: 0,0:57:22.91,0:57:24.22,Default,,0,0,0,,学生：为什么要二选一呢？\nDialogue: 0,0:57:24.22,0:57:25.23,Default,,0,0,0,,教授：为什么不呢？\nDialogue: 0,0:57:25.45,0:57:25.80,Default,,0,0,0,,学生：对啊 为什么要这样呢？\nDialogue: 0,0:57:26.60,0:57:27.72,Default,,0,0,0,,教授：假设这些是现实中的人 对吗？\nDialogue: 0,0:57:27.76,0:57:28.97,Default,,0,0,0,,这个人外出一年\nDialogue: 0,0:57:29.28,0:57:31.74,Default,,0,0,0,,你只能在银行账户窗口旁边等待\nDialogue: 0,0:57:32.43,0:57:33.72,Default,,0,0,0,,就是不能处理两个请求\nDialogue: 0,0:57:33.74,0:57:34.94,Default,,0,0,0,,因为你还得等这个人\nDialogue: 0,0:57:35.48,0:57:37.07,Default,,0,0,0,,学生：为什么非得等他呢？\nDialogue: 0,0:57:37.38,0:57:39.11,Default,,0,0,0,,教授：因为这里是在计算一个函数\nDialogue: 0,0:57:39.11,0:57:40.92,Default,,0,0,0,,我必须定义一个函数\nDialogue: 0,0:57:41.72,0:57:42.60,Default,,0,0,0,,换种方式来说\nDialogue: 0,0:57:42.84,0:57:44.99,Default,,0,0,0,,这个MERGE盒子的输出\nDialogue: 0,0:57:46.24,0:57:49.48,Default,,0,0,0,,并不是输入的函数\nDialogue: 0,0:57:51.69,0:57:53.49,Default,,0,0,0,,明白了吗？再来看看这个MERGE是怎么运行的\nDialogue: 0,0:57:53.49,0:57:58.86,Default,,0,0,0,,假设Bill输入 1 1 1 1\nDialogue: 0,0:57:59.82,0:58:02.78,Default,,0,0,0,,Dave输入2 2 2 2\nDialogue: 0,0:58:03.47,0:58:04.80,Default,,0,0,0,,MERGE应该输出什么呢？\nDialogue: 0,0:58:05.58,0:58:08.74,Default,,0,0,0,,这里并不一定是 1 2 1 2 1 2\nDialogue: 0,0:58:08.74,0:58:09.39,Default,,0,0,0,,学生：我明白了\nDialogue: 0,0:58:09.39,0:58:11.56,Default,,0,0,0,,当Bill输入1 1也就进去了\nDialogue: 0,0:58:11.56,0:58:13.95,Default,,0,0,0,,Dave再输入两个2 MERGE就输出两个2\nDialogue: 0,0:58:13.95,0:58:14.73,Default,,0,0,0,,学生：当Bill输入\nDialogue: 0,0:58:14.76,0:58:15.08,Default,,0,0,0,,教授：对的\nDialogue: 0,0:58:15.13,0:58:18.43,Default,,0,0,0,,学生：为什么不能在输入的数据上\nDialogue: 0,0:58:18.59,0:58:20.06,Default,,0,0,0,,加上时间信息呢？\nDialogue: 0,0:58:20.12,0:58:21.84,Default,,0,0,0,,教授：因为这里没有时间这个概念\nDialogue: 0,0:58:23.98,0:58:26.90,Default,,0,0,0,,我只是定义一个函数\nDialogue: 0,0:58:26.90,0:58:28.15,Default,,0,0,0,,没有时间概念\nDialogue: 0,0:58:32.00,0:58:34.19,Default,,0,0,0,,如果是二选一的话\nDialogue: 0,0:58:34.19,0:58:36.54,Default,,0,0,0,,如果选中的流没有人 就得等待它\nDialogue: 0,0:58:38.42,0:58:41.36,Default,,0,0,0,,它只会说 我有一个请求流\nDialogue: 0,0:58:41.74,0:58:43.34,Default,,0,0,0,,这是是Dave生成的\nDialogue: 0,0:58:43.36,0:58:45.29,Default,,0,0,0,,没有时刻的、无穷长度的请求流\nDialogue: 0,0:58:47.55,0:58:50.41,Default,,0,0,0,,Bill可能生成 没有时刻的无穷请求流\nDialogue: 0,0:58:50.54,0:58:51.69,Default,,0,0,0,,我想对这些东西做运算\nDialogue: 0,0:58:51.69,0:58:53.51,Default,,0,0,0,,这就是银行帐户的工作原理\nDialogue: 0,0:58:56.71,0:58:57.58,Default,,0,0,0,,问题是\nDialogue: 0,0:58:57.61,0:59:00.75,Default,,0,0,0,,这些坐在银行窗口前的倒霉蛋们\nDialogue: 0,0:59:00.76,0:59:03.82,Default,,0,0,0,,来得并不是时候\nDialogue: 0,0:59:05.29,0:59:07.13,Default,,0,0,0,,它们才看不到这个无穷流\nDialogue: 0,0:59:07.69,0:59:09.53,Default,,0,0,0,,什么时候其中会有请求\nDialogue: 0,0:59:10.07,0:59:11.55,Default,,0,0,0,,他们只是等着 等待帐户的响应\nDialogue: 0,0:59:14.48,0:59:15.76,Default,,0,0,0,,假设你坐在屏幕前\nDialogue: 0,0:59:16.24,0:59:20.86,Default,,0,0,0,,操作着一台分时系统的计算机\nDialogue: 0,0:59:21.52,0:59:22.60,Default,,0,0,0,,而且它还是函数式的\nDialogue: 0,0:59:22.64,0:59:24.59,Default,,0,0,0,,输入指令后你就希望看到结果\nDialogue: 0,0:59:25.29,0:59:27.42,Default,,0,0,0,,但是你并不想主机在处理完所有其它人的命令\nDialogue: 0,0:59:27.45,0:59:29.92,Default,,0,0,0,,之后再来处理你的命令\nDialogue: 0,0:59:30.91,0:59:31.92,Default,,0,0,0,,这就是问题所在\nDialogue: 0,0:59:34.00,0:59:36.38,Default,,0,0,0,,我的意思就是 用户的世界当然是存在时间概念的\nDialogue: 0,0:59:37.21,0:59:38.62,Default,,0,0,0,,如果没有 这就不构成问题\nDialogue: 0,0:59:49.10,0:59:51.02,Default,,0,0,0,,学生：我想我还是不太理解\nDialogue: 0,0:59:51.08,0:59:54.24,Default,,0,0,0,,银行交易中为什么没有时间概念这一要点\nDialogue: 0,0:59:54.74,0:59:56.65,Default,,0,0,0,,难道时间不是非常重要吗？\nDialogue: 0,0:59:56.88,0:59:59.05,Default,,0,0,0,,举例说 有一系列事件\nDialogue: 0,0:59:59.95,1:00:05.02,Default,,0,0,0,,比如Dave取款$100\nDialogue: 0,1:00:06.30,1:00:08.40,Default,,0,0,0,,这些顺序应该很重要才对\nDialogue: 0,1:00:08.40,1:00:10.86,Default,,0,0,0,,你怎么能把它们看作是流呢？\nDialogue: 0,1:00:11.26,1:00:14.26,Default,,0,0,0,,教授：这就是我一直在强调的\nDialogue: 0,1:00:14.26,1:00:15.61,Default,,0,0,0,,在这个例子中确实做不到那一点\nDialogue: 0,1:00:17.51,1:00:18.12,Default,,0,0,0,,做不到\nDialogue: 0,1:00:18.16,1:00:20.08,Default,,0,0,0,,关键在于 这里的输出\nDialogue: 0,1:00:20.24,1:00:21.88,Default,,0,0,0,,并不是这两个输入流\nDialogue: 0,1:00:21.92,1:00:23.60,Default,,0,0,0,,的函数\nDialogue: 0,1:00:24.17,1:00:25.98,Default,,0,0,0,,这个函数跟这个输入流有关\nDialogue: 0,1:00:26.19,1:00:27.26,Default,,0,0,0,,还跟这个输入流有关\nDialogue: 0,1:00:27.36,1:00:29.07,Default,,0,0,0,,还包括某种有关时间的信息\nDialogue: 0,1:00:29.37,1:00:32.36,Default,,0,0,0,,这也正是正则序语言不想让你知道的\nDialogue: 0,1:00:34.81,1:00:37.95,Default,,0,0,0,,学生：为了让这个系统更加函数式\nDialogue: 0,1:00:38.54,1:00:42.04,Default,,0,0,0,,我们能不能把Bill和Dave的交易请求附上时间戳\nDialogue: 0,1:00:42.54,1:00:46.40,Default,,0,0,0,,而使用时间戳作为公平合并的依据？\nDialogue: 0,1:00:48.41,1:00:49.55,Default,,0,0,0,,教授：当然 当然可以\nDialogue: 0,1:00:49.55,1:00:50.60,Default,,0,0,0,,你可以那样做\nDialogue: 0,1:00:50.60,1:00:52.56,Default,,0,0,0,,或者 我们可以这样来想象\nDialogue: 0,1:00:52.76,1:00:54.44,Default,,0,0,0,,我们把这个函数看作是\nDialogue: 0,1:00:54.78,1:00:56.88,Default,,0,0,0,,MERGE每毫秒读一次输入\nDialogue: 0,1:00:58.86,1:00:59.93,Default,,0,0,0,,如果没有读到东西\nDialogue: 0,1:00:59.93,1:01:00.97,Default,,0,0,0,,就认为没有请求\nDialogue: 0,1:01:00.97,1:01:03.39,Default,,0,0,0,,这和你刚刚说的那种方式是等价的\nDialogue: 0,1:01:03.61,1:01:06.08,Default,,0,0,0,,当然可以这样做 但有点旁门左道\nDialogue: 0,1:01:07.11,1:01:10.14,Default,,0,0,0,,我们不只是关心函数的具体实现\nDialogue: 0,1:01:10.76,1:01:12.73,Default,,0,0,0,,我们关心的是语言的表达力\nDialogue: 0,1:01:12.75,1:01:14.67,Default,,0,0,0,,我们遇到的困难是\nDialogue: 0,1:01:14.99,1:01:17.44,Default,,0,0,0,,我们不能很容易地表达我们想要表达的东西\nDialogue: 0,1:01:19.88,1:01:22.01,Default,,0,0,0,,学生：听起来好像如果两个人同时发出请求\nDialogue: 0,1:01:22.06,1:01:26.09,Default,,0,0,0,,这个方法就会出问题\nDialogue: 0,1:01:26.12,1:01:28.43,Default,,0,0,0,,教授：并不只是这个 只要是你定义的都可能出问题\nDialogue: 0,1:01:28.53,1:01:30.57,Default,,0,0,0,,你当然可以说Dave经常发起两个请求\nDialogue: 0,1:01:30.72,1:01:32.32,Default,,0,0,0,,但是你如果预先定义了什么\nDialogue: 0,1:01:32.68,1:01:33.87,Default,,0,0,0,,这样做也不正确\nDialogue: 0,1:01:36.11,1:01:40.70,Default,,0,0,0,,你不能确定某些特定函数的输入请求\nDialogue: 0,1:01:41.93,1:01:43.37,Default,,0,0,0,,但是还有更坏的情况\nDialogue: 0,1:01:44.12,1:01:45.72,Default,,0,0,0,,有一些情况甚至MERGE也处理不了\nDialogue: 0,1:01:47.29,1:01:49.69,Default,,0,0,0,,比如突然有一天你想要\nDialogue: 0,1:01:50.24,1:01:52.47,Default,,0,0,0,,把另一个人关联在这个银行帐户上\nDialogue: 0,1:01:52.47,1:01:54.51,Default,,0,0,0,,假如这个人是John\nDialogue: 0,1:01:56.03,1:01:58.89,Default,,0,0,0,,现在图上就要多一个流\nDialogue: 0,1:01:58.91,1:02:00.70,Default,,0,0,0,,在一个我们未曾指定的时候\nDialogue: 0,1:02:02.04,1:02:04.00,Default,,0,0,0,,这种情况甚至公平合并也无法给出合理的合并\nDialogue: 0,1:02:04.00,1:02:08.25,Default,,0,0,0,,还需要有MANAGER一类的东西\nDialogue: 0,1:02:08.86,1:02:11.79,Default,,0,0,0,,需要一种更一般性的公平合并来解决\nDialogue: 0,1:02:11.79,1:02:13.98,Default,,0,0,0,,有很多研究都在讨论\nDialogue: 0,1:02:14.00,1:02:16.30,Default,,0,0,0,,通过不断引入新机制\nDialogue: 0,1:02:16.59,1:02:18.72,Default,,0,0,0,,函数式思维能应用到哪种程度？\nDialogue: 0,1:02:19.58,1:02:21.79,Default,,0,0,0,,在我们不得不使用赋值之前\nDialogue: 0,1:02:21.82,1:02:23.40,Default,,0,0,0,,函数式程序设计能干成什么样？\nDialogue: 0,1:02:25.98,1:02:28.00,Default,,0,0,0,,学生：看来自动存款就不行\nDialogue: 0,1:02:39.32,1:02:40.49,Default,,0,0,0,,教授：好的 下课\nDialogue: 0,1:02:41.32,1:03:00.08,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:02:41.32,1:03:00.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP"
  },
  {
    "path": "Ass/lec6b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.03,0:00:03.10,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:04.09,0:00:12.08,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N张大伟\\N（DreamAndDead）\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:04.09,0:00:12.08,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:12.54,0:00:17.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 II\nDialogue: 0,0:00:20.97,0:00:24.08,Default,,0,0,0,,教授：上节课 我们介绍了流\nDialogue: 0,0:00:24.08,0:00:27.82,Default,,0,0,0,,按照信号处理的方式来组织系统\nDialogue: 0,0:00:28.87,0:00:31.42,Default,,0,0,0,,要记住的是 关键点在于\nDialogue: 0,0:00:31.90,0:00:32.96,Default,,0,0,0,,我们分离开\nDialogue: 0,0:00:34.20,0:00:37.31,Default,,0,0,0,,程序中 事件表面上的顺序\nDialogue: 0,0:00:37.58,0:00:40.17,Default,,0,0,0,,与机器中的实际计算顺序\nDialogue: 0,0:00:41.07,0:00:42.28,Default,,0,0,0,,那就意味着 我们可以\nDialogue: 0,0:00:42.57,0:00:44.14,Default,,0,0,0,,着手处理非常长的流\nDialogue: 0,0:00:44.89,0:00:47.39,Default,,0,0,0,,并且只有在需要的时候才生成其中的元素\nDialogue: 0,0:00:47.53,0:00:49.39,Default,,0,0,0,,这种按需计算的方式\nDialogue: 0,0:00:49.52,0:00:51.40,Default,,0,0,0,,是内建在流的数据结构中的\nDialogue: 0,0:00:54.11,0:00:55.64,Default,,0,0,0,,即使这个流非常之长\nDialogue: 0,0:00:55.66,0:00:57.08,Default,,0,0,0,,我们只计算所需要的\nDialogue: 0,0:00:58.04,0:01:00.75,Default,,0,0,0,,只有当我们要求的时候 新的数据才会生成\nDialogue: 0,0:01:00.75,0:01:01.74,Default,,0,0,0,,要举个什么样的例子呢？\nDialogue: 0,0:01:02.11,0:01:03.60,Default,,0,0,0,,这个“按需”是什么个情况呢？\nDialogue: 0,0:01:05.02,0:01:06.01,Default,,0,0,0,,举个例子\nDialogue: 0,0:01:09.21,0:01:11.37,Default,,0,0,0,,我们可能会想要一个流中的第N个元素\nDialogue: 0,0:01:15.36,0:01:18.92,Default,,0,0,0,,这个过程可以用于计算流的第N个元素\nDialogue: 0,0:01:20.09,0:01:21.23,Default,,0,0,0,,一个参数为索引N\nDialogue: 0,0:01:21.24,0:01:22.84,Default,,0,0,0,,另一个参数是流S\nDialogue: 0,0:01:23.40,0:01:25.42,Default,,0,0,0,,递归遍历这个流即可求解\nDialogue: 0,0:01:25.57,0:01:27.39,Default,,0,0,0,,如果N为0 我们就计算头部分\nDialogue: 0,0:01:27.96,0:01:30.99,Default,,0,0,0,,否则 就在流的尾部分\nDialogue: 0,0:01:31.74,0:01:32.80,Default,,0,0,0,,查找第N-1个元素\nDialogue: 0,0:01:34.31,0:01:36.43,Default,,0,0,0,,看起来是Lisp中很普通的编程方式 但是不同的是\nDialogue: 0,0:01:36.62,0:01:38.76,Default,,0,0,0,,直到我们不断遍历 取得相继的N个元素\nDialogue: 0,0:01:38.86,0:01:40.99,Default,,0,0,0,,这些元素才被计算出来\nDialogue: 0,0:01:41.52,0:01:44.78,Default,,0,0,0,,这是这些流元素可能被FORCE的一种方式\nDialogue: 0,0:01:45.77,0:01:46.64,Default,,0,0,0,,另外一种方式则是\nDialogue: 0,0:01:47.18,0:01:48.92,Default,,0,0,0,,这里有个简单的过程 用来打印一个流\nDialogue: 0,0:01:49.30,0:01:50.38,Default,,0,0,0,,它的定义是\nDialogue: 0,0:01:51.90,0:01:53.28,Default,,0,0,0,,过程PRINT-STREAM的定义是\nDialogue: 0,0:01:54.15,0:01:55.12,Default,,0,0,0,,我们要怎么做呢？\nDialogue: 0,0:01:55.74,0:01:56.86,Default,,0,0,0,,先打印流的头部分\nDialogue: 0,0:01:57.74,0:01:59.32,Default,,0,0,0,,流的头部分在这时就被计算出来\nDialogue: 0,0:01:59.72,0:02:02.84,Default,,0,0,0,,然后我们再递归地打印流的尾部分\nDialogue: 0,0:02:04.99,0:02:06.03,Default,,0,0,0,,完成以后\nDialogue: 0,0:02:06.04,0:02:08.57,Default,,0,0,0,,就返回一个的表示完成的消息 “DONE”\nDialogue: 0,0:02:09.66,0:02:11.39,Default,,0,0,0,,如果你构造了一个流\nDialogue: 0,0:02:11.64,0:02:13.64,Default,,0,0,0,,这个流非常的长\nDialogue: 0,0:02:14.31,0:02:16.33,Default,,0,0,0,,当你调用这个过程\nDialogue: 0,0:02:16.41,0:02:19.77,Default,,0,0,0,,流中的元素会随着PRINT-STREAM的调用\nDialogue: 0,0:02:19.87,0:02:21.12,Default,,0,0,0,,而被依次计算出来\nDialogue: 0,0:02:21.32,0:02:22.81,Default,,0,0,0,,不会在一开始就全部计算出来\nDialogue: 0,0:02:24.30,0:02:25.66,Default,,0,0,0,,正因为如此 我们能够\nDialogue: 0,0:02:27.50,0:02:29.61,Default,,0,0,0,,我们能够处理非常长的流\nDialogue: 0,0:02:30.19,0:02:31.92,Default,,0,0,0,,多长呢？\nDialogue: 0,0:02:33.74,0:02:35.12,Default,,0,0,0,,可以是无限长\nDialogue: 0,0:02:35.90,0:02:38.04,Default,,0,0,0,,我们在计算机上实践一下\nDialogue: 0,0:02:38.92,0:02:41.96,Default,,0,0,0,,我可以在计算机前输入\nDialogue: 0,0:02:43.48,0:02:53.31,Default,,0,0,0,,我先定义一个函数 (INTEGERS-FROM N)\nDialogue: 0,0:02:54.24,0:02:57.13,Default,,0,0,0,,用于生成一个从N开始的正整数流\nDialogue: 0,0:03:00.36,0:03:19.16,Default,,0,0,0,,也就是 (CONS-STREAM N (INTEGERS-FROM (+ N 1))))\nDialogue: 0,0:03:24.41,0:03:25.61,Default,,0,0,0,,这样就我们要的全部整数\nDialogue: 0,0:03:28.99,0:03:31.50,Default,,0,0,0,,现在我来尝试得到所有的整数\nDialogue: 0,0:03:34.57,0:03:44.33,Default,,0,0,0,,(DEFINE INTEGERS (INTEGERS-FROM 1))\nDialogue: 0,0:03:48.84,0:03:50.94,Default,,0,0,0,,如果现在我执行 (NTH-STREAM 20 INTEGERS)\nDialogue: 0,0:03:54.41,0:03:55.80,Default,,0,0,0,,来查看第20个元素\nDialogue: 0,0:04:03.42,0:04:05.53,Default,,0,0,0,,得到21 因为索引是从0开始的\nDialogue: 0,0:04:06.84,0:04:08.88,Default,,0,0,0,,或者我们来点更复杂的\nDialogue: 0,0:04:09.45,0:04:10.84,Default,,0,0,0,,我再来定义一个谓词\nDialogue: 0,0:04:11.77,0:04:18.51,Default,,0,0,0,,谓词NO-SEVEN用来检测是否为7的倍数\nDialogue: 0,0:04:19.58,0:04:20.75,Default,,0,0,0,,它的判定方法是这样的：\nDialogue: 0,0:04:21.79,0:04:23.16,Default,,0,0,0,,如果整数X不是7的倍数\nDialogue: 0,0:04:28.82,0:04:33.96,Default,,0,0,0,,我取X除7的余数\nDialogue: 0,0:04:36.62,0:04:38.35,Default,,0,0,0,,余数不应该为0\nDialogue: 0,0:04:43.80,0:04:49.77,Default,,0,0,0,,这时用NO-SEVEN这个谓词\nDialogue: 0,0:04:50.22,0:04:59.12,Default,,0,0,0,,过滤全部的整数\nDialogue: 0,0:05:11.57,0:05:13.34,Default,,0,0,0,,这样我就得到了所有的\nDialogue: 0,0:05:13.63,0:05:15.05,Default,,0,0,0,,不是7的倍数的整数构成的流\nDialogue: 0,0:05:16.49,0:05:23.44,Default,,0,0,0,,如果我问 这些不是7的倍数的整数中\nDialogue: 0,0:05:24.70,0:05:26.48,Default,,0,0,0,,的第100个数是多少？\nDialogue: 0,0:05:26.86,0:05:28.11,Default,,0,0,0,,结果是117\nDialogue: 0,0:05:28.32,0:05:30.67,Default,,0,0,0,,或者我也可以问\nDialogue: 0,0:05:32.30,0:05:34.38,Default,,0,0,0,,这个流的所有元素都是些什么？\nDialogue: 0,0:05:35.27,0:05:40.35,Default,,0,0,0,,我可以用(PRINT-STREAM NS)来尝试打印这个流\nDialogue: 0,0:05:40.83,0:05:41.79,Default,,0,0,0,,它就会输出个不停\nDialogue: 0,0:05:45.10,0:05:47.07,Default,,0,0,0,,你可能需要等上很久才能得到全部结果\nDialogue: 0,0:05:52.67,0:05:53.84,Default,,0,0,0,,你可能会问了\nDialogue: 0,0:05:54.81,0:05:57.00,Default,,0,0,0,,这个数据结构\nDialogue: 0,0:05:58.28,0:06:00.65,Default,,0,0,0,,真的全部是由整数构成的吗？\nDialogue: 0,0:06:01.10,0:06:04.05,Default,,0,0,0,,现在我画一个图来演示下刚写的那个程序\nDialogue: 0,0:06:04.96,0:06:10.57,Default,,0,0,0,,这是我刚才键入的整数定义\nDialogue: 0,0:06:12.33,0:06:15.98,Default,,0,0,0,,它是一个由第一个整数和由下一个整数生成的流 所构成的序对\nDialogue: 0,0:06:17.61,0:06:19.77,Default,,0,0,0,,现在我们画个图来看看它到底是什么样\nDialogue: 0,0:06:22.72,0:06:24.32,Default,,0,0,0,,从概念上来说 这应该是一个盒子\nDialogue: 0,0:06:25.53,0:06:27.18,Default,,0,0,0,,这个盒子是(INTEGER-FROM N)\nDialogue: 0,0:06:27.42,0:06:29.08,Default,,0,0,0,,它接受一个参数N\nDialogue: 0,0:06:31.42,0:06:32.97,Default,,0,0,0,,然后返回一个流\nDialogue: 0,0:06:35.02,0:06:37.36,Default,,0,0,0,,这个无穷流表示从N开始的所有整数\nDialogue: 0,0:06:38.08,0:06:38.73,Default,,0,0,0,,我要做什么呢？\nDialogue: 0,0:06:38.75,0:06:42.38,Default,,0,0,0,,呃 这个是INT-FROM盒子\nDialogue: 0,0:06:45.07,0:06:45.80,Default,,0,0,0,,里面是什么样子呢？\nDialogue: 0,0:06:45.80,0:06:48.60,Default,,0,0,0,,取得参数N之后\nDialogue: 0,0:06:52.27,0:06:53.92,Default,,0,0,0,,将其 +1\nDialogue: 0,0:06:57.95,0:07:03.15,Default,,0,0,0,,然后把结果递归地传递给另一个INT-FROM盒子\nDialogue: 0,0:07:06.87,0:07:09.60,Default,,0,0,0,,把这个盒子的结果和最初的N\nDialogue: 0,0:07:10.24,0:07:12.78,Default,,0,0,0,,用CONS组合起来\nDialogue: 0,0:07:13.39,0:07:14.36,Default,,0,0,0,,就形成了一个流\nDialogue: 0,0:07:14.57,0:07:17.26,Default,,0,0,0,,我刚才写的那个过程 画出来就是这样子\nDialogue: 0,0:07:18.52,0:07:20.32,Default,,0,0,0,,我们看到的这类图像\nDialogue: 0,0:07:20.78,0:07:21.74,Default,,0,0,0,,首先是由Peter Henderson提出的\nDialogue: 0,0:07:21.76,0:07:23.32,Default,,0,0,0,,也就是前面课程中绘图语言的发明者\nDialogue: 0,0:07:23.32,0:07:24.75,Default,,0,0,0,,我们把这种图叫做Henderson图\nDialogue: 0,0:07:25.37,0:07:27.90,Default,,0,0,0,,画这种图需要遵守一定的约定\nDialogue: 0,0:07:28.53,0:07:32.51,Default,,0,0,0,,这些实线代表输出的流\nDialogue: 0,0:07:33.02,0:07:36.20,Default,,0,0,0,,这些虚线则是初始的输入值\nDialogue: 0,0:07:37.27,0:07:39.02,Default,,0,0,0,,而这个图描述的形状是——\nDialogue: 0,0:07:39.40,0:07:41.60,Default,,0,0,0,,它会取一个整数作为初始值\nDialogue: 0,0:07:41.80,0:07:42.91,Default,,0,0,0,,然后输出一个流\nDialogue: 0,0:07:46.35,0:07:48.22,Default,,0,0,0,,现在 你可能又要问了\nDialogue: 0,0:07:48.38,0:07:50.88,Default,,0,0,0,,那个INTEGERS的数据结构真的全部都是整数吗？\nDialogue: 0,0:07:52.09,0:07:54.91,Default,,0,0,0,,或者它只是经过了精心组织\nDialogue: 0,0:07:54.94,0:07:56.43,Default,,0,0,0,,以至于总可以在其中找到\nDialogue: 0,0:07:56.44,0:07:57.24,Default,,0,0,0,,我们需要的那个整数？\nDialogue: 0,0:07:57.95,0:07:59.74,Default,,0,0,0,,这有点像个哲学问题 不是么？\nDialogue: 0,0:07:59.78,0:08:01.69,Default,,0,0,0,,如果有一个东西\nDialogue: 0,0:08:02.14,0:08:03.96,Default,,0,0,0,,你不去观测它 能否知道它“存在”呢？\nDialogue: 0,0:08:04.45,0:08:07.34,Default,,0,0,0,,这就有点像\nDialogue: 0,0:08:07.36,0:08:09.42,Default,,0,0,0,,你在银行中的存款那样\nDialogue: 0,0:08:12.38,0:08:12.64,Default,,0,0,0,,好吧\nDialogue: 0,0:08:16.35,0:08:17.48,Default,,0,0,0,,我们再来看一个例子\nDialogue: 0,0:08:18.68,0:08:20.70,Default,,0,0,0,,这门课的第一节课\nDialogue: 0,0:08:20.72,0:08:22.72,Default,,0,0,0,,我们就讲了一个来自于亚历山大的算法\nDialogue: 0,0:08:23.29,0:08:25.80,Default,,0,0,0,,来自亚历山大的Heron提出的\nDialogue: 0,0:08:25.82,0:08:26.94,Default,,0,0,0,,一个用于计算平方根的算法\nDialogue: 0,0:08:28.47,0:08:32.03,Default,,0,0,0,,现在再来看一个 同样来自于亚力山大的算法\nDialogue: 0,0:08:32.03,0:08:35.08,Default,,0,0,0,,这个被称为Eratosthenes算法的方法\nDialogue: 0,0:08:36.19,0:08:38.44,Default,,0,0,0,,用于计算所有的质数\nDialogue: 0,0:08:41.16,0:08:42.83,Default,,0,0,0,,它被称为Eratosthenes筛法\nDialogue: 0,0:08:42.83,0:08:49.72,Default,,0,0,0,,它是这样的 一开始\nDialogue: 0,0:08:50.99,0:08:52.28,Default,,0,0,0,,先列举所有的整数\nDialogue: 0,0:08:52.60,0:08:53.53,Default,,0,0,0,,从2开始\nDialogue: 0,0:08:53.88,0:08:55.04,Default,,0,0,0,,然后取第一个整数\nDialogue: 0,0:08:55.08,0:08:56.67,Default,,0,0,0,,然后你发现 哦 2是一个质数\nDialogue: 0,0:08:57.31,0:08:58.35,Default,,0,0,0,,然后你考察剩余的整数\nDialogue: 0,0:08:58.68,0:09:00.88,Default,,0,0,0,,划掉其中可以被2整除的数\nDialogue: 0,0:09:01.52,0:09:04.73,Default,,0,0,0,,我把这个划掉 还有这个 这个\nDialogue: 0,0:09:05.25,0:09:06.35,Default,,0,0,0,,有点费时\nDialogue: 0,0:09:06.36,0:09:08.91,Default,,0,0,0,,我要对所有的整数进行这样的操作\nDialogue: 0,0:09:11.16,0:09:15.39,Default,,0,0,0,,我遍历整个整数表\nDialogue: 0,0:09:18.27,0:09:20.94,Default,,0,0,0,,划掉所有被2整除的数\nDialogue: 0,0:09:22.11,0:09:24.38,Default,,0,0,0,,所有的整数都操作完后\nDialogue: 0,0:09:24.78,0:09:26.72,Default,,0,0,0,,回过头再来看还剩些什么\nDialogue: 0,0:09:27.04,0:09:28.80,Default,,0,0,0,,好的 下一个数就是3了\nDialogue: 0,0:09:29.33,0:09:30.33,Default,,0,0,0,,3也是一个质数\nDialogue: 0,0:09:30.77,0:09:33.05,Default,,0,0,0,,现在 我会继续在剩下的数中\nDialogue: 0,0:09:33.36,0:09:35.07,Default,,0,0,0,,划掉所有被3整除的数\nDialogue: 0,0:09:35.08,0:09:43.80,Default,,0,0,0,,划掉 9、15、21、27、33 等等\nDialogue: 0,0:09:44.33,0:09:45.12,Default,,0,0,0,,我就不往下划了\nDialogue: 0,0:09:45.35,0:09:46.52,Default,,0,0,0,,然后看看我们还剩下什么\nDialogue: 0,0:09:47.25,0:09:49.84,Default,,0,0,0,,而下一个就是5了\nDialogue: 0,0:09:50.49,0:09:52.04,Default,,0,0,0,,我又遍历剩下的数\nDialogue: 0,0:09:52.43,0:09:54.51,Default,,0,0,0,,找到第一个能被5整除的数\nDialogue: 0,0:09:54.54,0:09:57.61,Default,,0,0,0,,把剩下的能被5整除的数都划掉\nDialogue: 0,0:09:58.35,0:09:59.24,Default,,0,0,0,,做完这个之后\nDialogue: 0,0:09:59.82,0:10:01.89,Default,,0,0,0,,下一个数就是7\nDialogue: 0,0:10:01.89,0:10:02.72,Default,,0,0,0,,再遍历剩下的数\nDialogue: 0,0:10:02.76,0:10:03.95,Default,,0,0,0,,划掉所有被7整除的数\nDialogue: 0,0:10:03.98,0:10:05.47,Default,,0,0,0,,然后一直这样下去\nDialogue: 0,0:10:06.81,0:10:07.40,Default,,0,0,0,,全部结束的时候\nDialogue: 0,0:10:07.40,0:10:09.10,Default,,0,0,0,,我也就得到了所有的质数\nDialogue: 0,0:10:09.90,0:10:13.31,Default,,0,0,0,,这就是Eratosthenes筛法\nDialogue: 0,0:10:15.43,0:10:17.69,Default,,0,0,0,,我们来看下实际代码\nDialogue: 0,0:10:17.93,0:10:19.85,Default,,0,0,0,,这个过程命名为SIEVE\nDialogue: 0,0:10:27.91,0:10:29.40,Default,,0,0,0,,这是对应的代码\nDialogue: 0,0:10:30.33,0:10:34.48,Default,,0,0,0,,SIEVE过程 以一个流S为参数\nDialogue: 0,0:10:38.77,0:10:39.93,Default,,0,0,0,,返回一个新的流\nDialogue: 0,0:10:40.27,0:10:41.84,Default,,0,0,0,,新的流的头部分 就是流S的头部分\nDialogue: 0,0:10:41.87,0:10:44.43,Default,,0,0,0,,回忆一下 我总是取剩下的数中的第一个\nDialogue: 0,0:10:44.91,0:10:48.75,Default,,0,0,0,,而尾部分则是把流S的尾部分\nDialogue: 0,0:10:51.08,0:10:53.72,Default,,0,0,0,,过滤掉所有\nDialogue: 0,0:10:53.74,0:10:55.32,Default,,0,0,0,,能被S头部分整除的数\nDialogue: 0,0:10:56.41,0:10:57.56,Default,,0,0,0,,然后再对结果筛选\nDialogue: 0,0:10:59.02,0:11:00.09,Default,,0,0,0,,这个代码就是这样\nDialogue: 0,0:11:01.98,0:11:04.68,Default,,0,0,0,,现在 为了得到由质数构成的无穷流\nDialogue: 0,0:11:05.02,0:11:06.90,Default,,0,0,0,,我们对从2开始的整数流进行SIEVE\nDialogue: 0,0:11:14.92,0:11:15.56,Default,,0,0,0,,我们来实践一下\nDialogue: 0,0:11:16.30,0:11:18.30,Default,,0,0,0,,实际上 我们可以在计算机中运行\nDialogue: 0,0:11:19.76,0:11:22.12,Default,,0,0,0,,我希望我已经预先输入过SIEVE的定义了\nDialogue: 0,0:11:22.86,0:11:24.06,Default,,0,0,0,,所以我可以定义\nDialogue: 0,0:11:24.92,0:11:33.45,Default,,0,0,0,,我可以把PRIMES定义为\nDialogue: 0,0:11:34.64,0:11:41.45,Default,,0,0,0,,(SIEVE (INTEGERS-FROM 2))\nDialogue: 0,0:11:46.76,0:11:48.10,Default,,0,0,0,,现在我就得到了质数构成的表\nDialogue: 0,0:11:48.10,0:11:50.99,Default,,0,0,0,,这样就得到了所有的质数 对吧？\nDialogue: 0,0:11:50.99,0:11:53.52,Default,,0,0,0,,比如我可以问 第20个质数是什么？\nDialogue: 0,0:12:00.73,0:12:01.68,Default,,0,0,0,,结果是73\nDialogue: 0,0:12:02.54,0:12:03.34,Default,,0,0,0,,那个短促的停顿\nDialogue: 0,0:12:03.36,0:12:04.92,Default,,0,0,0,,这是因为\nDialogue: 0,0:12:04.94,0:12:06.43,Default,,0,0,0,,在我询问第20个元素时\nDialogue: 0,0:12:06.46,0:12:07.68,Default,,0,0,0,,它才进行实际的计算\nDialogue: 0,0:12:10.37,0:12:11.29,Default,,0,0,0,,在这里 我也可以要求\nDialogue: 0,0:12:13.80,0:12:14.88,Default,,0,0,0,,打印所有的质数\nDialogue: 0,0:12:22.64,0:12:24.40,Default,,0,0,0,,解释器就开始计算并打印所有的质数\nDialogue: 0,0:12:25.35,0:12:26.28,Default,,0,0,0,,得花上好一会儿\nDialogue: 0,0:12:26.28,0:12:27.61,Default,,0,0,0,,才能打赢完整\nDialogue: 0,0:12:27.79,0:12:28.57,Default,,0,0,0,,所以先把它停掉\nDialogue: 0,0:12:32.03,0:12:33.13,Default,,0,0,0,,让我来画图演示一下\nDialogue: 0,0:12:33.13,0:12:34.17,Default,,0,0,0,,我已经画好了\nDialogue: 0,0:12:34.89,0:12:36.19,Default,,0,0,0,,这个过程的图形应该是什么样子呢？\nDialogue: 0,0:12:37.90,0:12:39.77,Default,,0,0,0,,用这类图形的约定来说\nDialogue: 0,0:12:39.82,0:12:40.54,Default,,0,0,0,,我有一个叫SIEVE的盒子\nDialogue: 0,0:12:42.61,0:12:43.56,Default,,0,0,0,,它是如何运作的呢？\nDialogue: 0,0:12:43.56,0:12:44.81,Default,,0,0,0,,它以一个流作为输入\nDialogue: 0,0:12:48.85,0:12:50.59,Default,,0,0,0,,分离流的头、尾部分\nDialogue: 0,0:12:50.87,0:12:53.26,Default,,0,0,0,,从SIEVE盒子出来的第一个东西\nDialogue: 0,0:12:53.48,0:12:54.97,Default,,0,0,0,,就是原来流的头部分\nDialogue: 0,0:12:58.20,0:13:00.92,Default,,0,0,0,,头部分同样也用于这个盒子\nDialogue: 0,0:13:02.55,0:13:05.10,Default,,0,0,0,,这个盒子会过滤流的尾部分\nDialogue: 0,0:13:05.55,0:13:08.33,Default,,0,0,0,,过滤的依据是 能否被头部分整除\nDialogue: 0,0:13:09.53,0:13:11.18,Default,,0,0,0,,过滤得到的不可整除的那些数\nDialogue: 0,0:13:11.24,0:13:13.12,Default,,0,0,0,,再放入另一个SIEVE盒子\nDialogue: 0,0:13:13.90,0:13:15.13,Default,,0,0,0,,然后把它们组合输出\nDialogue: 0,0:13:15.13,0:13:16.89,Default,,0,0,0,,你可以把SIEVE想象为一个过滤器\nDialogue: 0,0:13:17.20,0:13:19.23,Default,,0,0,0,,只不过它是一个无穷递归的过滤器\nDialogue: 0,0:13:19.65,0:13:20.88,Default,,0,0,0,,这是因为在SIEVE盒子中\nDialogue: 0,0:13:21.52,0:13:22.60,Default,,0,0,0,,还有另外一个SIEVE盒子\nDialogue: 0,0:13:23.37,0:13:25.85,Default,,0,0,0,,内部的盒子里面还有另外一个SIEVE盒子\nDialogue: 0,0:13:27.13,0:13:28.96,Default,,0,0,0,,我们现在逐渐有了非常厉害的能力\nDialogue: 0,0:13:28.96,0:13:32.84,Default,,0,0,0,,我们开始把 信号处理的方法\nDialogue: 0,0:13:33.90,0:13:36.41,Default,,0,0,0,,和计算中的递归结合在一起 来建模世界\nDialogue: 0,0:13:37.42,0:13:39.82,Default,,0,0,0,,还有很多像是这样的事\nDialogue: 0,0:13:40.97,0:13:42.09,Default,,0,0,0,,好的 有什么问题吗？\nDialogue: 0,0:13:48.19,0:13:49.16,Default,,0,0,0,,好吧 那我们休息一下\nDialogue: 0,0:13:49.64,0:14:04.12,Default,,0,0,0,,[音乐]\nDialogue: 0,0:14:04.46,0:14:08.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:14:12.08,0:14:16.38,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:14:16.44,0:14:20.22,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:14:20.35,0:14:25.05,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 II\nDialogue: 0,0:14:28.65,0:14:30.36,Default,,0,0,0,,我们已经看了\nDialogue: 0,0:14:30.36,0:14:32.09,Default,,0,0,0,,好几个流式程序设计的例子\nDialogue: 0,0:14:34.79,0:14:39.21,Default,,0,0,0,,我们目前接触到的流过程\nDialogue: 0,0:14:39.72,0:14:41.32,Default,,0,0,0,,都有一个共同的特征\nDialogue: 0,0:14:41.49,0:14:43.63,Default,,0,0,0,,这些过程总是递归地\nDialogue: 0,0:14:44.16,0:14:46.49,Default,,0,0,0,,一次生成一个元素\nDialogue: 0,0:14:46.51,0:14:48.72,Default,,0,0,0,,再用CONS-STREAM连接起来\nDialogue: 0,0:14:49.15,0:14:50.86,Default,,0,0,0,,因此 我们一直把它当作是生成器\nDialogue: 0,0:14:50.92,0:14:53.63,Default,,0,0,0,,还有一种思考流式程序设计的方式\nDialogue: 0,0:14:53.79,0:14:56.96,Default,,0,0,0,,我们不认为程序是\nDialogue: 0,0:14:57.36,0:14:59.93,Default,,0,0,0,,沿着流逐一处理元素\nDialogue: 0,0:15:00.25,0:15:05.68,Default,,0,0,0,,而是一下子处理了整个流\nDialogue: 0,0:15:07.18,0:15:09.16,Default,,0,0,0,,我先来定义两个非常有用的过程\nDialogue: 0,0:15:09.23,0:15:11.50,Default,,0,0,0,,来帮助我说明\nDialogue: 0,0:15:12.41,0:15:13.60,Default,,0,0,0,,第一个过程是ADD-STREAMS\nDialogue: 0,0:15:15.36,0:15:18.25,Default,,0,0,0,,它接受两个流作为参数\nDialogue: 0,0:15:18.81,0:15:20.88,Default,,0,0,0,,S1和S2\nDialogue: 0,0:15:22.30,0:15:24.67,Default,,0,0,0,,它生成一个新的流\nDialogue: 0,0:15:24.99,0:15:28.17,Default,,0,0,0,,其元素是两个流相应位置元素的和\nDialogue: 0,0:15:30.22,0:15:31.88,Default,,0,0,0,,相当于是“按元素”的加\nDialogue: 0,0:15:32.97,0:15:33.95,Default,,0,0,0,,如果其中一个流是空的\nDialogue: 0,0:15:33.96,0:15:35.39,Default,,0,0,0,,我们就返回另一个\nDialogue: 0,0:15:36.81,0:15:38.96,Default,,0,0,0,,否则 我们就构建一个新的流\nDialogue: 0,0:15:39.90,0:15:42.96,Default,,0,0,0,,新流的头部分是两个流头部分之和\nDialogue: 0,0:15:44.00,0:15:44.88,Default,,0,0,0,,而新流的尾部分\nDialogue: 0,0:15:46.00,0:15:48.62,Default,,0,0,0,,则是递归地加和尾部分\nDialogue: 0,0:15:50.09,0:15:52.73,Default,,0,0,0,,这就会产生“按元素”地加的效果\nDialogue: 0,0:15:53.15,0:15:57.04,Default,,0,0,0,,另一个过程是SCALE-STREAM\nDialogue: 0,0:15:57.50,0:16:01.66,Default,,0,0,0,,SCALE-STREAM有两个参数 常数C和流S\nDialogue: 0,0:16:04.11,0:16:06.62,Default,,0,0,0,,结果生成的流\nDialogue: 0,0:16:07.18,0:16:09.50,Default,,0,0,0,,就是将流S的所有元素乘上了C\nDialogue: 0,0:16:09.71,0:16:11.21,Default,,0,0,0,,这很简单 就是一个MAP\nDialogue: 0,0:16:12.20,0:16:16.22,Default,,0,0,0,,用到的函数是 X*C\nDialogue: 0,0:16:16.35,0:16:17.80,Default,,0,0,0,,把这个函数MAP于整个流\nDialogue: 0,0:16:20.06,0:16:21.47,Default,,0,0,0,,有了这两个过程\nDialogue: 0,0:16:22.64,0:16:24.36,Default,,0,0,0,,我来给你们解释 什么叫做\nDialogue: 0,0:16:24.70,0:16:27.00,Default,,0,0,0,,“一下子处理整个流”\nDialogue: 0,0:16:28.12,0:16:28.73,Default,,0,0,0,,我们来看这个\nDialogue: 0,0:16:30.20,0:16:30.92,Default,,0,0,0,,假设这样\nDialogue: 0,0:16:31.68,0:16:52.35,Default,,0,0,0,,(DEFINE ONES (CONS-STREAM 1 ONES))\nDialogue: 0,0:16:54.86,0:16:55.52,Default,,0,0,0,,这是什么？\nDialogue: 0,0:16:56.95,0:16:58.94,Default,,0,0,0,,这是一个表示无穷个1的流\nDialogue: 0,0:16:59.96,0:17:01.44,Default,,0,0,0,,因为第一个元素是1\nDialogue: 0,0:17:03.33,0:17:05.15,Default,,0,0,0,,尾部分则是这样的\nDialogue: 0,0:17:05.55,0:17:06.83,Default,,0,0,0,,它的头部分是1\nDialogue: 0,0:17:07.63,0:17:09.02,Default,,0,0,0,,它的尾部分\nDialogue: 0,0:17:09.12,0:17:10.24,Default,,0,0,0,,的头部分又为1\nDialogue: 0,0:17:10.52,0:17:11.78,Default,,0,0,0,,以此类推\nDialogue: 0,0:17:11.78,0:17:13.32,Default,,0,0,0,,这就是无穷个1的流\nDialogue: 0,0:17:15.13,0:17:15.93,Default,,0,0,0,,现在根据ONES\nDialogue: 0,0:17:16.12,0:17:18.03,Default,,0,0,0,,我再给出另一种定义整数的方式\nDialogue: 0,0:17:19.47,0:17:27.36,Default,,0,0,0,,(DEFINE INTEGERS\nDialogue: 0,0:17:28.24,0:17:30.76,Default,,0,0,0,,当然 第一个数是1\nDialogue: 0,0:17:32.75,0:17:38.57,Default,,0,0,0,,(CONS-STREAM 1 (ADD-STREAM\nDialogue: 0,0:17:40.22,0:17:48.27,Default,,0,0,0,,INTEGERS ONES)))\nDialogue: 0,0:17:55.10,0:17:56.35,Default,,0,0,0,,整数流是这样的：\nDialogue: 0,0:17:57.24,0:17:59.98,Default,,0,0,0,,它的第一个元素是1\nDialogue: 0,0:18:00.88,0:18:02.32,Default,,0,0,0,,而其余部分则是\nDialogue: 0,0:18:03.12,0:18:06.14,Default,,0,0,0,,依次把每个整数加1\nDialogue: 0,0:18:06.64,0:18:08.19,Default,,0,0,0,,因此 整数流的第二个元素则是\nDialogue: 0,0:18:08.51,0:18:11.96,Default,,0,0,0,,整数流的第一个元素加1\nDialogue: 0,0:18:13.92,0:18:15.18,Default,,0,0,0,,下一个数又要加1\nDialogue: 0,0:18:15.20,0:18:16.48,Default,,0,0,0,,第三个元素则是\nDialogue: 0,0:18:16.62,0:18:20.41,Default,,0,0,0,,INTEGER流尾部分的第一个元素\nDialogue: 0,0:18:20.84,0:18:21.96,Default,,0,0,0,,加1\nDialogue: 0,0:18:22.51,0:18:23.76,Default,,0,0,0,,这也就相当于\nDialogue: 0,0:18:25.08,0:18:28.65,Default,,0,0,0,,最初整数流的第一个元素加1\nDialogue: 0,0:18:28.86,0:18:31.25,Default,,0,0,0,,然后再加1 以此类推\nDialogue: 0,0:18:35.24,0:18:36.31,Default,,0,0,0,,这看起来有点匪夷所思\nDialogue: 0,0:18:36.31,0:18:37.47,Default,,0,0,0,,这样的过程可以正常运行\nDialogue: 0,0:18:38.12,0:18:38.99,Default,,0,0,0,,关键在于延时求值\nDialogue: 0,0:18:40.15,0:18:43.32,Default,,0,0,0,,我们来看这个ONES\nDialogue: 0,0:18:43.87,0:18:45.92,Default,,0,0,0,,这看起来根本不可能\nDialogue: 0,0:18:46.25,0:18:47.63,Default,,0,0,0,,因为它突然说\nDialogue: 0,0:18:47.79,0:18:48.96,Default,,0,0,0,,在定义ONES的时候\nDialogue: 0,0:18:49.00,0:18:50.91,Default,,0,0,0,,发现它依赖于它本身\nDialogue: 0,0:18:51.13,0:18:52.08,Default,,0,0,0,,它之所以可以运行是因为\nDialogue: 0,0:18:52.09,0:18:54.04,Default,,0,0,0,,这里暗中隐藏着延时求值\nDialogue: 0,0:18:55.25,0:18:56.56,Default,,0,0,0,,这个代码实际上是\nDialogue: 0,0:18:57.79,0:18:59.69,Default,,0,0,0,,回忆下 CONS-STREAM是只是一个缩写\nDialogue: 0,0:19:00.29,0:19:01.15,Default,,0,0,0,,实际上则是\nDialogue: 0,0:19:01.85,0:19:08.99,Default,,0,0,0,,(CONS 1 (DELAY ONES))\nDialogue: 0,0:19:12.14,0:19:13.21,Default,,0,0,0,,它又是怎么运作的呢？\nDialogue: 0,0:19:15.50,0:19:16.88,Default,,0,0,0,,你想要定义ONES\nDialogue: 0,0:19:18.02,0:19:20.24,Default,,0,0,0,,我来看看ONES要被定义成什么样\nDialogue: 0,0:19:20.70,0:19:23.40,Default,,0,0,0,,ONES被定义为一个序对\nDialogue: 0,0:19:24.89,0:19:28.11,Default,,0,0,0,,其CAR部分为1\nDialogue: 0,0:19:28.32,0:19:29.45,Default,,0,0,0,,而CDR部分则是\nDialogue: 0,0:19:29.45,0:19:30.73,Default,,0,0,0,,是一个计算某物的PROMISE\nDialogue: 0,0:19:30.75,0:19:31.69,Default,,0,0,0,,我现在还不用关心\nDialogue: 0,0:19:32.71,0:19:34.25,Default,,0,0,0,,所以虽然这时ONES还没有定义\nDialogue: 0,0:19:34.28,0:19:36.30,Default,,0,0,0,,但对我并不造成什么影响\nDialogue: 0,0:19:37.27,0:19:39.45,Default,,0,0,0,,一旦运行了整个定义 ONES就被定义了\nDialogue: 0,0:19:40.67,0:19:42.83,Default,,0,0,0,,所以 访问它尾部的时候 它就有定义了\nDialogue: 0,0:19:44.92,0:19:46.06,Default,,0,0,0,,这一点非常隐讳\nDialogue: 0,0:19:46.59,0:19:47.90,Default,,0,0,0,,整数流的定义也是如此\nDialogue: 0,0:19:48.47,0:19:50.46,Default,,0,0,0,,我可以在这里引用INTEGERS是因为\nDialogue: 0,0:19:51.13,0:19:53.21,Default,,0,0,0,,是因为这个CONS-STREAM的缘故\nDialogue: 0,0:19:53.85,0:19:55.24,Default,,0,0,0,,用CONS-STREAM把1\nDialogue: 0,0:19:55.37,0:19:57.05,Default,,0,0,0,,和一个不立即需要的东西组合起来\nDialogue: 0,0:19:57.05,0:19:59.60,Default,,0,0,0,,所以我在运行INTEGERS的定义的时候\nDialogue: 0,0:20:00.22,0:20:01.90,Default,,0,0,0,,并不会发现INTEGER没有定义过\nDialogue: 0,0:20:06.32,0:20:08.27,Default,,0,0,0,,听上去非常玄乎\nDialogue: 0,0:20:08.44,0:20:11.50,Default,,0,0,0,,让我用图像来演示一下INTEGERS的原理\nDialogue: 0,0:20:12.43,0:20:14.72,Default,,0,0,0,,怎么画呢？\nDialogue: 0,0:20:15.02,0:20:16.30,Default,,0,0,0,,首先是ONES这个流\nDialogue: 0,0:20:20.51,0:20:21.88,Default,,0,0,0,,它作为参数输入\nDialogue: 0,0:20:23.26,0:20:24.92,Default,,0,0,0,,进入一个加法器\nDialogue: 0,0:20:24.96,0:20:26.59,Default,,0,0,0,,进行流的加法运算\nDialogue: 0,0:20:29.31,0:20:35.87,Default,,0,0,0,,输出则是整数流INTEGERS\nDialogue: 0,0:20:40.76,0:20:42.70,Default,,0,0,0,,这里 这个整数流又重新进入加法器\nDialogue: 0,0:20:44.94,0:20:46.97,Default,,0,0,0,,形成了一个小型的反馈回路\nDialogue: 0,0:20:48.06,0:20:49.42,Default,,0,0,0,,我需要在某处接入最初的ONES\nDialogue: 0,0:20:50.09,0:20:52.88,Default,,0,0,0,,才能让它生效\nDialogue: 0,0:20:57.10,0:20:58.64,Default,,0,0,0,,在真实的信号处理中\nDialogue: 0,0:20:58.72,0:21:02.48,Default,,0,0,0,,这里是一个被初始化为1的延时元件\nDialogue: 0,0:21:02.91,0:21:05.90,Default,,0,0,0,,这就是ONES程序的图示\nDialogue: 0,0:21:07.86,0:21:09.63,Default,,0,0,0,,事实上 这个非常像\nDialogue: 0,0:21:09.80,0:21:13.77,Default,,0,0,0,,如果你见过真正的信号方块图的话\nDialogue: 0,0:21:13.77,0:21:16.30,Default,,0,0,0,,这个图形非常像累加器\nDialogue: 0,0:21:16.35,0:21:17.48,Default,,0,0,0,,有穷状态累加器\nDialogue: 0,0:21:17.98,0:21:20.06,Default,,0,0,0,,事实上 我们可以稍加修改\nDialogue: 0,0:21:21.18,0:21:23.96,Default,,0,0,0,,就可以让它对一个流做积分\nDialogue: 0,0:21:25.37,0:21:26.97,Default,,0,0,0,,或者说是有穷状态累加器\nDialogue: 0,0:21:27.00,0:21:28.04,Default,,0,0,0,,你怎么认为都可以\nDialogue: 0,0:21:28.44,0:21:30.86,Default,,0,0,0,,现在 不再是输入ONES 输出INTEGERS\nDialogue: 0,0:21:31.68,0:21:32.38,Default,,0,0,0,,我们要做的是\nDialogue: 0,0:21:32.91,0:21:34.83,Default,,0,0,0,,这里有一个流S为输入\nDialogue: 0,0:21:35.76,0:21:40.56,Default,,0,0,0,,我们要计算这个流的积分\nDialogue: 0,0:21:42.60,0:21:44.09,Default,,0,0,0,,也就是累加这个流的值\nDialogue: 0,0:21:44.44,0:21:45.63,Default,,0,0,0,,这看起来几乎就是一样的\nDialogue: 0,0:21:45.66,0:21:46.84,Default,,0,0,0,,我们要做的就是\nDialogue: 0,0:21:47.02,0:21:48.08,Default,,0,0,0,,当S从这里输入时\nDialogue: 0,0:21:49.21,0:21:50.64,Default,,0,0,0,,在把它求和之前\nDialogue: 0,0:21:50.91,0:21:54.26,Default,,0,0,0,,先将其乘以dt\nDialogue: 0,0:21:57.68,0:22:00.00,Default,,0,0,0,,剩下的就不用改了\nDialogue: 0,0:22:00.00,0:22:00.91,Default,,0,0,0,,我们就得到了一个盒子\nDialogue: 0,0:22:03.36,0:22:04.56,Default,,0,0,0,,一个积分器\nDialogue: 0,0:22:09.79,0:22:11.26,Default,,0,0,0,,对一个流S进行积分\nDialogue: 0,0:22:11.90,0:22:14.51,Default,,0,0,0,,把这里的1替换为\nDialogue: 0,0:22:14.94,0:22:18.35,Default,,0,0,0,,该积分的初始值\nDialogue: 0,0:22:19.98,0:22:21.60,Default,,0,0,0,,这个看起来就非常像\nDialogue: 0,0:22:22.35,0:22:24.86,Default,,0,0,0,,信号处理中的方框图了\nDialogue: 0,0:22:25.27,0:22:28.11,Default,,0,0,0,,事实上 这个图示对应的是这样一个过程\nDialogue: 0,0:22:31.49,0:22:33.61,Default,,0,0,0,,对一个流进行积分\nDialogue: 0,0:22:34.01,0:22:35.48,Default,,0,0,0,,INTEGRAL函数接收一个流\nDialogue: 0,0:22:35.68,0:22:36.86,Default,,0,0,0,,返回一个新的流\nDialogue: 0,0:22:37.53,0:22:40.67,Default,,0,0,0,,它还接收一个初始值和某个时间常量\nDialogue: 0,0:22:42.23,0:22:42.97,Default,,0,0,0,,然后呢？\nDialogue: 0,0:22:43.04,0:22:45.05,Default,,0,0,0,,首先在内部定义一个流INT\nDialogue: 0,0:22:45.20,0:22:46.32,Default,,0,0,0,,之所以要给它一个内部名字\nDialogue: 0,0:22:46.33,0:22:48.86,Default,,0,0,0,,原因在于可以使它反馈 以形成循环\nDialogue: 0,0:22:49.40,0:22:50.80,Default,,0,0,0,,INT的定义是\nDialogue: 0,0:22:51.10,0:22:53.32,Default,,0,0,0,,一个以INITIA-VALUE开始的流\nDialogue: 0,0:22:54.97,0:23:00.14,Default,,0,0,0,,而其余的元素则是把它们加起来\nDialogue: 0,0:23:01.28,0:23:03.61,Default,,0,0,0,,我们把输入流乘以dt\nDialogue: 0,0:23:03.87,0:23:04.92,Default,,0,0,0,,然后和INT相加\nDialogue: 0,0:23:06.88,0:23:09.66,Default,,0,0,0,,整个INTEGRAL函数的结果就是这个INT\nDialogue: 0,0:23:10.69,0:23:12.94,Default,,0,0,0,,我们使用这种内部定义的语法\nDialogue: 0,0:23:13.34,0:23:15.66,Default,,0,0,0,,是为了可以在内部引用它自己\nDialogue: 0,0:23:21.88,0:23:23.71,Default,,0,0,0,,我们还可以做更多的事情\nDialogue: 0,0:23:23.71,0:23:24.51,Default,,0,0,0,,来看这个\nDialogue: 0,0:23:25.63,0:23:26.89,Default,,0,0,0,,斐波那契数\nDialogue: 0,0:23:26.89,0:23:32.62,Default,,0,0,0,,(DEFINE FIBS\nDialogue: 0,0:23:36.35,0:23:37.63,Default,,0,0,0,,斐波那契数是什么呢？\nDialogue: 0,0:23:37.98,0:23:46.54,Default,,0,0,0,,它从0开始\nDialogue: 0,0:23:48.65,0:23:50.09,Default,,0,0,0,,下一个是1\nDialogue: 0,0:23:56.26,0:23:59.16,Default,,0,0,0,,的其余的斐波那契数是通过\nDialogue: 0,0:23:59.87,0:24:11.00,Default,,0,0,0,,把它们的尾部分求和而得来\nDialogue: 0,0:24:17.57,0:24:19.28,Default,,0,0,0,,这样来定义斐波那契数\nDialogue: 0,0:24:20.58,0:24:21.43,Default,,0,0,0,,这是如何运作的呢？\nDialogue: 0,0:24:21.43,0:24:24.19,Default,,0,0,0,,我们来试试\nDialogue: 0,0:24:24.20,0:24:26.49,Default,,0,0,0,,假如开始计算斐波那契数\nDialogue: 0,0:24:29.64,0:24:31.92,Default,,0,0,0,,首先告诉你 它以0和1开始\nDialogue: 0,0:24:35.79,0:24:38.22,Default,,0,0,0,,而0和1之后的数则是\nDialogue: 0,0:24:39.18,0:24:40.86,Default,,0,0,0,,通过加和两个流而得\nDialogue: 0,0:24:41.12,0:24:42.59,Default,,0,0,0,,一个流是FIBS本身\nDialogue: 0,0:24:44.06,0:24:45.69,Default,,0,0,0,,另一个是FIBS的尾部分\nDialogue: 0,0:24:49.12,0:24:51.16,Default,,0,0,0,,如果我知道这是以0和1起始的\nDialogue: 0,0:24:51.79,0:24:55.42,Default,,0,0,0,,我就能知道 FIBS是以0和1起始的\nDialogue: 0,0:24:55.74,0:24:57.40,Default,,0,0,0,,那么 FIBS的尾部分则应该以1开始\nDialogue: 0,0:24:58.36,0:24:59.45,Default,,0,0,0,,一旦我知道了这点\nDialogue: 0,0:24:59.66,0:25:02.11,Default,,0,0,0,,我就知道 FIBS的下一个数就是0+1=1\nDialogue: 0,0:25:02.96,0:25:04.60,Default,,0,0,0,,它也同样告诉我这里是1\nDialogue: 0,0:25:04.62,0:25:05.72,Default,,0,0,0,,这里也是1\nDialogue: 0,0:25:06.30,0:25:07.28,Default,,0,0,0,,知道了这些之后\nDialogue: 0,0:25:07.29,0:25:08.76,Default,,0,0,0,,我就知道下一个是2\nDialogue: 0,0:25:09.39,0:25:11.70,Default,,0,0,0,,这里是2 这里也是2\nDialogue: 0,0:25:11.70,0:25:12.56,Default,,0,0,0,,下一个是3\nDialogue: 0,0:25:14.72,0:25:15.79,Default,,0,0,0,,这里是3\nDialogue: 0,0:25:16.19,0:25:17.13,Default,,0,0,0,,这里是5\nDialogue: 0,0:25:18.67,0:25:19.96,Default,,0,0,0,,这个定义完全说得通\nDialogue: 0,0:25:21.50,0:25:22.78,Default,,0,0,0,,这个定义只有一行\nDialogue: 0,0:25:22.83,0:25:25.00,Default,,0,0,0,,当然 我也可以在计算机中\nDialogue: 0,0:25:25.00,0:25:26.62,Default,,0,0,0,,原原本本地键入计算机中\nDialogue: 0,0:25:27.04,0:25:28.94,Default,,0,0,0,,然后要求输出斐波那契数\nDialogue: 0,0:25:28.94,0:25:30.15,Default,,0,0,0,,然后它就会不断输出\nDialogue: 0,0:25:32.79,0:25:35.20,Default,,0,0,0,,这又像是在学习递归\nDialogue: 0,0:25:36.81,0:25:39.79,Default,,0,0,0,,过程可以被递归定义\nDialogue: 0,0:25:40.99,0:25:43.50,Default,,0,0,0,,我们也可以递归地定义数据对象\nDialogue: 0,0:25:45.16,0:25:46.92,Default,,0,0,0,,但你们一点儿不应该感到吃惊\nDialogue: 0,0:25:47.12,0:25:49.50,Default,,0,0,0,,因为现在 你们应该真正相信\nDialogue: 0,0:25:49.52,0:25:53.05,Default,,0,0,0,,过程与数据之间没有区别\nDialogue: 0,0:25:53.09,0:25:53.92,Default,,0,0,0,,事实上 就某种意义上来说\nDialogue: 0,0:25:53.93,0:25:56.41,Default,,0,0,0,,流也是由过程来实现的\nDialogue: 0,0:25:56.43,0:25:57.79,Default,,0,0,0,,只不过我们不把它看做过程而已\nDialogue: 0,0:25:58.21,0:26:00.38,Default,,0,0,0,,因此既然我们有递归过程\nDialogue: 0,0:26:00.70,0:26:03.63,Default,,0,0,0,,那么 有递归数据也就不足为奇了\nDialogue: 0,0:26:07.72,0:26:09.69,Default,,0,0,0,,虽然流非常简洁\nDialogue: 0,0:26:09.72,0:26:13.92,Default,,0,0,0,,但不幸的是 有些问题流无法解决\nDialogue: 0,0:26:14.99,0:26:16.48,Default,,0,0,0,,我来举个例子\nDialogue: 0,0:26:17.58,0:26:20.35,Default,,0,0,0,,同样地 我们来想象一下\nDialogue: 0,0:26:20.76,0:26:23.61,Default,,0,0,0,,我们正在构建求解微分方程的模拟计算机\nDialogue: 0,0:26:25.20,0:26:34.30,Default,,0,0,0,,比如求解方程 y' = y^2\nDialogue: 0,0:26:34.76,0:26:36.16,Default,,0,0,0,,我会给你一个初值\nDialogue: 0,0:26:36.39,0:26:38.03,Default,,0,0,0,,y(0) = 1\nDialogue: 0,0:26:41.48,0:26:44.06,Default,,0,0,0,,dt = .0001\nDialogue: 0,0:26:46.77,0:26:47.53,Default,,0,0,0,,很久之前\nDialogue: 0,0:26:48.00,0:26:50.65,Default,,0,0,0,,就有人构建模拟计算机 来解决这类问题\nDialogue: 0,0:26:51.36,0:26:53.02,Default,,0,0,0,,原理非常简单\nDialogue: 0,0:26:53.02,0:26:54.41,Default,,0,0,0,,你首先需要一个积分器\nDialogue: 0,0:27:00.04,0:27:01.69,Default,,0,0,0,,比如这个INT盒子\nDialogue: 0,0:27:03.05,0:27:06.48,Default,,0,0,0,,我们设定初始值 y(0) = 1\nDialogue: 0,0:27:08.53,0:27:10.92,Default,,0,0,0,,现在如果我们送入一个输入 就会得到输出\nDialogue: 0,0:27:10.96,0:27:13.16,Default,,0,0,0,,输出的结果就是y\nDialogue: 0,0:27:14.25,0:27:16.96,Default,,0,0,0,,输入的是y的导数\nDialogue: 0,0:27:17.52,0:27:20.52,Default,,0,0,0,,在这里 导数 y' = y^2\nDialogue: 0,0:27:21.49,0:27:27.07,Default,,0,0,0,,如果我们用MAP把SQUARE映射在这些值上\nDialogue: 0,0:27:30.73,0:27:32.09,Default,,0,0,0,,然后把这个引过来\nDialogue: 0,0:27:36.28,0:27:38.48,Default,,0,0,0,,这个方块图\nDialogue: 0,0:27:38.57,0:27:41.08,Default,,0,0,0,,就是用于求解这个微分方程的模拟计算机\nDialogue: 0,0:27:42.91,0:27:44.80,Default,,0,0,0,,现在我们用代码\nDialogue: 0,0:27:44.80,0:27:46.78,Default,,0,0,0,,来表示下这个过程\nDialogue: 0,0:27:47.23,0:27:48.72,Default,,0,0,0,,这个图究竟表示的是什么呢？\nDialogue: 0,0:27:49.39,0:27:58.30,Default,,0,0,0,,(DEFINE Y\nDialogue: 0,0:28:04.28,0:28:11.68,Default,,0,0,0,,(INTEGRAL DY 1 .001))\nDialogue: 0,0:28:13.79,0:28:15.45,Default,,0,0,0,,接下来\nDialogue: 0,0:28:16.80,0:28:20.85,Default,,0,0,0,,通过MAP SQUARE 来表示dy\nDialogue: 0,0:28:20.85,0:28:32.81,Default,,0,0,0,,(DEFINE DY (MAP SQUARE Y))\nDialogue: 0,0:28:33.51,0:28:36.80,Default,,0,0,0,,这就是这个模拟计算机的流式描述\nDialogue: 0,0:28:38.62,0:28:40.32,Default,,0,0,0,,不幸的是 它并不起效\nDialogue: 0,0:28:41.41,0:28:42.67,Default,,0,0,0,,你也可以发现这是为什么\nDialogue: 0,0:28:42.97,0:28:44.99,Default,,0,0,0,,因为我把Y定义为\nDialogue: 0,0:28:46.43,0:28:47.85,Default,,0,0,0,,DY 的积分\nDialogue: 0,0:28:49.04,0:28:50.65,Default,,0,0,0,,它会问 对什么的积分？\nDialogue: 0,0:28:51.19,0:28:52.12,Default,,0,0,0,,没定义啊\nDialogue: 0,0:28:53.71,0:28:57.63,Default,,0,0,0,,所以这个定义必须写在这个定义的后面\nDialogue: 0,0:28:58.77,0:29:00.51,Default,,0,0,0,,另一方面 如果先定义了dy\nDialogue: 0,0:29:00.51,0:29:03.02,Default,,0,0,0,,定义为 (MAP SQUARE 某个东西)\nDialogue: 0,0:29:03.58,0:29:04.64,Default,,0,0,0,,这个也还没有定义\nDialogue: 0,0:29:05.77,0:29:08.17,Default,,0,0,0,,我既不能先写这个 又不能先写那个\nDialogue: 0,0:29:09.08,0:29:11.58,Default,,0,0,0,,这个游戏就没法玩了\nDialogue: 0,0:29:17.56,0:29:18.51,Default,,0,0,0,,怎样来解决呢？\nDialogue: 0,0:29:20.60,0:29:21.84,Default,,0,0,0,,我们可以用ONES来解决\nDialogue: 0,0:29:22.20,0:29:25.82,Default,,0,0,0,,所以 我们在这里定义的ONES\nDialogue: 0,0:29:27.24,0:29:29.90,Default,,0,0,0,,我们之所以可以使用ONES来定义ONES\nDialogue: 0,0:29:30.40,0:29:32.03,Default,,0,0,0,,这是因为其中的延时求值\nDialogue: 0,0:29:32.43,0:29:34.12,Default,,0,0,0,,CONS-STREAM是延时求值的\nDialogue: 0,0:29:34.77,0:29:35.79,Default,,0,0,0,,那么 这又为什么说得通呢？\nDialogue: 0,0:29:35.92,0:29:38.51,Default,,0,0,0,,为什么CONS-STREAM是延时求值的是合理的呢？\nDialogue: 0,0:29:40.73,0:29:43.13,Default,,0,0,0,,原因在于 CONS-STREAM不需要其尾部分\nDialogue: 0,0:29:43.48,0:29:44.88,Default,,0,0,0,,就可以完成有意义的事\nDialogue: 0,0:29:45.95,0:29:46.84,Default,,0,0,0,,比如我说\nDialogue: 0,0:29:47.48,0:29:49.64,Default,,0,0,0,,这个是1和某个东西组成的流\nDialogue: 0,0:29:49.92,0:29:51.69,Default,,0,0,0,,虽然我对它一无所知\nDialogue: 0,0:29:52.16,0:29:54.03,Default,,0,0,0,,但我却知道整个流是以1开始的\nDialogue: 0,0:29:54.87,0:29:57.29,Default,,0,0,0,,所以用CONS-STREAM来构造是有意义的\nDialogue: 0,0:29:59.96,0:30:01.24,Default,,0,0,0,,我们在这里放了一个DELAY\nDialogue: 0,0:30:01.42,0:30:04.65,Default,,0,0,0,,这就使得我们能够进行某种自引用的定义\nDialogue: 0,0:30:06.32,0:30:07.95,Default,,0,0,0,,INTEGRAL也可以用这种方式来解决\nDialogue: 0,0:30:08.19,0:30:12.52,Default,,0,0,0,,注意 对于INTEGRAL来说 我可以\nDialogue: 0,0:30:14.60,0:30:16.08,Default,,0,0,0,,让我们回过头来再看看INTEGRAL的定义\nDialogue: 0,0:30:17.58,0:30:18.56,Default,,0,0,0,,求积分的时候\nDialogue: 0,0:30:21.39,0:30:25.00,Default,,0,0,0,,知道INTEGRAL的第一个元素是合理的\nDialogue: 0,0:30:26.04,0:30:27.87,Default,,0,0,0,,尽管还不知道整个流是什么样的\nDialogue: 0,0:30:28.97,0:30:30.17,Default,,0,0,0,,这是因为INTEGRAL中第一个元素\nDialogue: 0,0:30:30.20,0:30:32.16,Default,,0,0,0,,总会是你传递过来的INITIAL-VALUE\nDialogue: 0,0:30:33.14,0:30:36.11,Default,,0,0,0,,所以INTEGRAL可以用CONS-STREAM来实现\nDialogue: 0,0:30:37.09,0:30:37.98,Default,,0,0,0,,我们可以定义它\nDialogue: 0,0:30:38.25,0:30:40.88,Default,,0,0,0,,甚至不用知道要积分的流是什么\nDialogue: 0,0:30:42.84,0:30:45.18,Default,,0,0,0,,只需要知道初始值是什么就行了\nDialogue: 0,0:30:46.71,0:30:48.17,Default,,0,0,0,,INTEGRAL还可以修改得更为智能\nDialogue: 0,0:30:48.41,0:30:50.68,Default,,0,0,0,,我们给它一个待积分的流\nDialogue: 0,0:30:50.83,0:30:51.92,Default,,0,0,0,,以及一个初值\nDialogue: 0,0:30:52.11,0:30:54.99,Default,,0,0,0,,直到你要求沿着这个流求解积分时\nDialogue: 0,0:30:55.21,0:30:56.97,Default,,0,0,0,,我才关心这个流是什么\nDialogue: 0,0:30:58.43,0:31:00.51,Default,,0,0,0,,换句话说INTEGRAL可以像CONS-STREAM一样\nDialogue: 0,0:31:00.57,0:31:03.74,Default,,0,0,0,,你可以认为INTEGRAL被放在DELAY之中\nDialogue: 0,0:31:03.76,0:31:04.86,Default,,0,0,0,,我们这样修改\nDialogue: 0,0:31:05.61,0:31:07.02,Default,,0,0,0,,这个过程是像这样的\nDialogue: 0,0:31:07.65,0:31:08.75,Default,,0,0,0,,这是另一个版本的INTEGRAL\nDialogue: 0,0:31:08.89,0:31:10.54,Default,,0,0,0,,这个跟之前的版本非常相似\nDialogue: 0,0:31:11.10,0:31:13.34,Default,,0,0,0,,只不过作为参数的流\nDialogue: 0,0:31:13.77,0:31:15.69,Default,,0,0,0,,必须要是一个延时对象\nDialogue: 0,0:31:17.11,0:31:18.43,Default,,0,0,0,,这个INTEGRAL又是如何运作的呢？\nDialogue: 0,0:31:18.85,0:31:21.79,Default,,0,0,0,,我们在内部定义的INT则是\nDialogue: 0,0:31:22.14,0:31:24.19,Default,,0,0,0,,用CONS-STREAM构造一个流\nDialogue: 0,0:31:24.73,0:31:26.44,Default,,0,0,0,,初值还是INITIAL-VALUE\nDialogue: 0,0:31:27.16,0:31:29.68,Default,,0,0,0,,但是在CONS-STREAM中\nDialogue: 0,0:31:29.74,0:31:32.30,Default,,0,0,0,,要注意 这里面有个隐藏的DELAY\nDialogue: 0,0:31:34.95,0:31:39.07,Default,,0,0,0,,只有在这个CONS-STREAM的内部\nDialogue: 0,0:31:39.82,0:31:42.11,Default,,0,0,0,,我才会查看延时对象的实际内容\nDialogue: 0,0:31:43.18,0:31:45.79,Default,,0,0,0,,所以 答案的第一个元素将会是初值\nDialogue: 0,0:31:45.97,0:31:47.90,Default,,0,0,0,,如果有人想访问我的尾部分\nDialogue: 0,0:31:48.40,0:31:49.42,Default,,0,0,0,,此时\nDialogue: 0,0:31:50.00,0:31:51.72,Default,,0,0,0,,我会FORCE该延迟对象\nDialogue: 0,0:31:52.62,0:31:53.60,Default,,0,0,0,,把结果记作S\nDialogue: 0,0:31:54.44,0:31:55.60,Default,,0,0,0,,然后再进行ADD-STREAMS\nDialogue: 0,0:31:56.36,0:31:59.26,Default,,0,0,0,,这个INTEGRAL就有点像CONS-STREAM\nDialogue: 0,0:31:59.26,0:32:02.59,Default,,0,0,0,,直到你确实需要知道第一个元素的时候\nDialogue: 0,0:32:03.88,0:32:07.13,Default,,0,0,0,,它才会去查看DELAYED-S是什么\nDialogue: 0,0:32:10.12,0:32:11.02,Default,,0,0,0,,如果这样的话\nDialogue: 0,0:32:11.52,0:32:12.83,Default,,0,0,0,,也就能求解 y' = y^2 了\nDialogue: 0,0:32:13.36,0:32:15.20,Default,,0,0,0,,这里我们只需要\nDialogue: 0,0:32:16.00,0:32:25.31,Default,,0,0,0,,把Y定义为对延时对象DY的积分\nDialogue: 0,0:32:27.09,0:32:28.22,Default,,0,0,0,,所以Y的定义就变成了\nDialogue: 0,0:32:28.40,0:32:34.36,Default,,0,0,0,,(INTEGRAL (DELAY DY) 1 .001)\nDialogue: 0,0:32:34.38,0:32:35.13,Default,,0,0,0,,这样一来就可以了\nDialogue: 0,0:32:35.28,0:32:37.44,Default,,0,0,0,,因为我输入Y的定义\nDialogue: 0,0:32:38.00,0:32:39.68,Default,,0,0,0,,它是某个东西的积分\nDialogue: 0,0:32:40.20,0:32:42.68,Default,,0,0,0,,但这是个延迟对象 我现在还不用关心\nDialogue: 0,0:32:44.60,0:32:46.32,Default,,0,0,0,,这之后 再定义DY\nDialogue: 0,0:32:46.32,0:32:47.37,Default,,0,0,0,,现在Y就有定义了\nDialogue: 0,0:32:47.55,0:32:48.89,Default,,0,0,0,,所以我在定义DY时\nDialogue: 0,0:32:49.13,0:32:50.67,Default,,0,0,0,,它可以知道Y的定义\nDialogue: 0,0:32:51.70,0:32:52.84,Default,,0,0,0,,一切都正常了\nDialogue: 0,0:32:52.84,0:32:54.33,Default,,0,0,0,,两个流都有第一个元素\nDialogue: 0,0:32:54.92,0:32:56.25,Default,,0,0,0,,当我不断取得下一个元素\nDialogue: 0,0:32:56.27,0:32:57.31,Default,,0,0,0,,沿着流做MAP运算时\nDialogue: 0,0:32:57.37,0:32:58.88,Default,,0,0,0,,Y和DY都被定义过了\nDialogue: 0,0:33:00.59,0:33:04.24,Default,,0,0,0,,所以为了继续这个游戏 我们不能仅仅\nDialogue: 0,0:33:04.67,0:33:07.13,Default,,0,0,0,,只使用隐藏在流中的DELAY\nDialogue: 0,0:33:08.36,0:33:08.97,Default,,0,0,0,,有问题么？\nDialogue: 0,0:33:13.52,0:33:14.27,Default,,0,0,0,,休息一下吧\nDialogue: 0,0:33:14.72,0:33:26.86,Default,,0,0,0,,[音乐]\nDialogue: 0,0:33:27.37,0:33:30.94,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:33:52.16,0:33:55.26,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:33:55.42,0:33:59.26,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:34:00.38,0:34:03.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}流 II\nDialogue: 0,0:34:07.30,0:34:10.04,Default,,0,0,0,,上节课的最后\nDialogue: 0,0:34:10.89,0:34:11.80,Default,,0,0,0,,不知道你们注意到没有\nDialogue: 0,0:34:11.82,0:34:13.55,Default,,0,0,0,,事情正变得糟糕起来\nDialogue: 0,0:34:14.83,0:34:18.40,Default,,0,0,0,,我们讲了很多关于 流\nDialogue: 0,0:34:19.16,0:34:22.68,Default,,0,0,0,,以及分离程序中的时间和计算机中的时间\nDialogue: 0,0:34:22.86,0:34:26.28,Default,,0,0,0,,这些分离都被隐藏在流中了\nDialogue: 0,0:34:27.28,0:34:29.50,Default,,0,0,0,,上节课快结束时我们发现\nDialogue: 0,0:34:29.71,0:34:32.19,Default,,0,0,0,,为了真正发挥这种方法的优势\nDialogue: 0,0:34:32.22,0:34:34.38,Default,,0,0,0,,我们需要另外的DELAY\nDialogue: 0,0:34:34.38,0:34:35.85,Default,,0,0,0,,不只需要隐藏在CONS-STREAM中的DELAY\nDialogue: 0,0:34:36.09,0:34:37.95,Default,,0,0,0,,还需要显式地使用DELAY\nDialogue: 0,0:34:39.03,0:34:41.88,Default,,0,0,0,,我只是用微分方程举了一个很简单的例子\nDialogue: 0,0:34:42.35,0:34:44.08,Default,,0,0,0,,但是如果你有一个非常复杂的系统\nDialogue: 0,0:34:44.12,0:34:45.40,Default,,0,0,0,,里面充斥着各种各样的自循环\nDialogue: 0,0:34:45.95,0:34:47.84,Default,,0,0,0,,那就很难再发现\nDialogue: 0,0:34:47.90,0:34:49.31,Default,,0,0,0,,在什么地方需要额外的DELAY了\nDialogue: 0,0:34:49.92,0:34:51.18,Default,,0,0,0,,假如你一不小心漏了一个\nDialogue: 0,0:34:51.45,0:34:54.36,Default,,0,0,0,,就很难发现程序为什么不起效\nDialogue: 0,0:34:55.55,0:34:57.15,Default,,0,0,0,,这是一种混乱\nDialogue: 0,0:34:57.79,0:35:01.71,Default,,0,0,0,,让我们能够使用DELAY\nDialogue: 0,0:35:02.08,0:35:04.70,Default,,0,0,0,,有时却会让程序设计变得非常复杂\nDialogue: 0,0:35:04.72,0:35:06.80,Default,,0,0,0,,因为它们不能完全隐藏在流中\nDialogue: 0,0:35:08.51,0:35:09.79,Default,,0,0,0,,那么 有没有什么解决方案呢？\nDialogue: 0,0:35:11.13,0:35:12.67,Default,,0,0,0,,所幸的是 有\nDialogue: 0,0:35:13.48,0:35:16.08,Default,,0,0,0,,我们可以修改整个语言\nDialogue: 0,0:35:16.14,0:35:18.19,Default,,0,0,0,,使得所有的过程都表现得像CONS-STREAM一样\nDialogue: 0,0:35:19.10,0:35:21.48,Default,,0,0,0,,这样所有的过程都会\nDialogue: 0,0:35:22.32,0:35:25.45,Default,,0,0,0,,自动、隐式地为它的参数加上DELAY\nDialogue: 0,0:35:25.45,0:35:26.43,Default,,0,0,0,,这是什么意思呢？\nDialogue: 0,0:35:27.52,0:35:29.53,Default,,0,0,0,,就是说 当你调用一个过程时\nDialogue: 0,0:35:30.16,0:35:31.88,Default,,0,0,0,,参数并不会立即求值\nDialogue: 0,0:35:32.21,0:35:34.70,Default,,0,0,0,,只有在需要被求值的时候 它们才会被求值\nDialogue: 0,0:35:34.89,0:35:36.72,Default,,0,0,0,,它们也可能被传递给其它的过程\nDialogue: 0,0:35:36.76,0:35:38.12,Default,,0,0,0,,而这个过程也不会求值这些参数\nDialogue: 0,0:35:39.26,0:35:41.90,Default,,0,0,0,,因此这些过程间传递的是PROMISE\nDialogue: 0,0:35:42.15,0:35:44.46,Default,,0,0,0,,直到最后\nDialogue: 0,0:35:44.65,0:35:47.34,Default,,0,0,0,,你需要查看某个值的时候\nDialogue: 0,0:35:47.36,0:35:48.99,Default,,0,0,0,,可能是因为一个基本运算所需要\nDialogue: 0,0:35:49.37,0:35:51.48,Default,,0,0,0,,这是你才实际求值这些PROMISE\nDialogue: 0,0:35:52.38,0:35:53.16,Default,,0,0,0,,像这样修改语言之后\nDialogue: 0,0:35:53.36,0:35:55.37,Default,,0,0,0,,由于所有的东西都是统一被延时的\nDialogue: 0,0:35:57.16,0:35:59.00,Default,,0,0,0,,就不需要任何显式的DELAY了\nDialogue: 0,0:35:59.04,0:36:01.55,Default,,0,0,0,,因为它自动地内建在语言之中了\nDialogue: 0,0:36:03.24,0:36:04.38,Default,,0,0,0,,换句话来说\nDialogue: 0,0:36:05.10,0:36:08.14,Default,,0,0,0,,从技术上来说 我所描述的\nDialogue: 0,0:36:09.02,0:36:10.76,Default,,0,0,0,,如果修改后的语言被称作\nDialogue: 0,0:36:12.19,0:36:16.57,Default,,0,0,0,,所谓的“正则序求值”语言\nDialogue: 0,0:36:20.20,0:36:23.47,Default,,0,0,0,,这个跟我们一直使用的语言不同\nDialogue: 0,0:36:23.87,0:36:33.79,Default,,0,0,0,,我们所用的是“应用序求值”语言\nDialogue: 0,0:36:34.56,0:36:36.83,Default,,0,0,0,,还记得应用序求值的代换模型吧\nDialogue: 0,0:36:36.83,0:36:40.49,Default,,0,0,0,,当你求值一个组合式的时候\nDialogue: 0,0:36:40.51,0:36:42.11,Default,,0,0,0,,你需要先计算出每一个元素的值\nDialogue: 0,0:36:43.59,0:36:45.40,Default,,0,0,0,,先求值所有的参数\nDialogue: 0,0:36:45.72,0:36:47.42,Default,,0,0,0,,再把它们代换入过程的体\nDialogue: 0,0:36:47.60,0:36:49.55,Default,,0,0,0,,正则序则不是这样\nDialogue: 0,0:36:49.89,0:36:51.90,Default,,0,0,0,,你所做的则是\nDialogue: 0,0:36:52.76,0:36:54.41,Default,,0,0,0,,直接将参数代换入过程的体\nDialogue: 0,0:36:54.44,0:36:56.19,Default,,0,0,0,,而不先对参数求值\nDialogue: 0,0:36:56.54,0:36:58.08,Default,,0,0,0,,只是代换入了一个计算参数的PROMISE\nDialogue: 0,0:36:58.81,0:36:59.90,Default,,0,0,0,,换句话说就是\nDialogue: 0,0:36:59.92,0:37:02.09,Default,,0,0,0,,把作为参数的整个表达式\nDialogue: 0,0:37:02.28,0:37:04.84,Default,,0,0,0,,直接代入过程的体进行代换\nDialogue: 0,0:37:05.16,0:37:06.88,Default,,0,0,0,,在此之间从不进行任何化简\nDialogue: 0,0:37:07.16,0:37:08.76,Default,,0,0,0,,直到遇到一个基本运算符\nDialogue: 0,0:37:09.47,0:37:10.99,Default,,0,0,0,,这就是所谓的正则序求值语言\nDialogue: 0,0:37:12.17,0:37:13.12,Default,,0,0,0,,我们为什么不这样做呢？\nDialogue: 0,0:37:13.82,0:37:14.60,Default,,0,0,0,,这样做了之后\nDialogue: 0,0:37:15.00,0:37:17.34,Default,,0,0,0,,我们就获得了延时求值的所有优点\nDialogue: 0,0:37:17.90,0:37:18.80,Default,,0,0,0,,而不会一片混乱\nDialogue: 0,0:37:18.94,0:37:20.19,Default,,0,0,0,,事实上 如果我们这样做了之后\nDialogue: 0,0:37:20.43,0:37:22.67,Default,,0,0,0,,CONS也会是延时求值的\nDialogue: 0,0:37:22.68,0:37:24.57,Default,,0,0,0,,就和CONS-STREAM一样\nDialogue: 0,0:37:24.71,0:37:25.82,Default,,0,0,0,,我们就不再需要流了\nDialogue: 0,0:37:26.36,0:37:28.54,Default,,0,0,0,,因为表自动成为了流\nDialogue: 0,0:37:29.55,0:37:30.70,Default,,0,0,0,,表和流有一样的行为\nDialogue: 0,0:37:30.75,0:37:32.35,Default,,0,0,0,,所有的数据结构也会像那样\nDialogue: 0,0:37:32.35,0:37:33.64,Default,,0,0,0,,所有的都是\nDialogue: 0,0:37:35.07,0:37:37.63,Default,,0,0,0,,直到需要答案的时候\nDialogue: 0,0:37:37.66,0:37:39.42,Default,,0,0,0,,才会去实际的求值\nDialogue: 0,0:37:40.80,0:37:43.58,Default,,0,0,0,,不必再担心 什么时候需要显式地标注DELAY\nDialogue: 0,0:37:44.79,0:37:46.16,Default,,0,0,0,,为什么不这样做呢？\nDialogue: 0,0:37:47.16,0:37:48.81,Default,,0,0,0,,首先 已经有人这样做过了\nDialogue: 0,0:37:49.23,0:37:51.85,Default,,0,0,0,,有一些十分优雅的语言\nDialogue: 0,0:37:51.85,0:37:55.21,Default,,0,0,0,,其中最为人称道的是一门名为 Miranda 的语言\nDialogue: 0,0:37:55.77,0:37:56.76,Default,,0,0,0,,它是由\nDialogue: 0,0:37:57.44,0:37:59.80,Default,,0,0,0,,肯特大学的 David Turner 开发的\nDialogue: 0,0:38:00.71,0:38:01.93,Default,,0,0,0,,它就是用这样的原理实现的\nDialogue: 0,0:38:01.93,0:38:03.34,Default,,0,0,0,,Miranda是正则序求值语言\nDialogue: 0,0:38:04.27,0:38:05.55,Default,,0,0,0,,它的数据结构\nDialogue: 0,0:38:06.16,0:38:08.41,Default,,0,0,0,,看起来像表 实际上确实流\nDialogue: 0,0:38:08.96,0:38:10.91,Default,,0,0,0,,你不需要任何特殊的功能\nDialogue: 0,0:38:11.28,0:38:13.28,Default,,0,0,0,,就可以在Miranda中编写普通的过程\nDialogue: 0,0:38:13.32,0:38:14.97,Default,,0,0,0,,来解决质数、八皇后这样的问题\nDialogue: 0,0:38:14.97,0:38:16.35,Default,,0,0,0,,这些都是语言的内建功能\nDialogue: 0,0:38:17.93,0:38:18.91,Default,,0,0,0,,但这样做也要付出代价\nDialogue: 0,0:38:21.19,0:38:22.36,Default,,0,0,0,,还记得我们为什么引入流了吗？\nDialogue: 0,0:38:23.17,0:38:27.48,Default,,0,0,0,,我们分离了程序的时间和它实际执行的时间\nDialogue: 0,0:38:27.96,0:38:28.88,Default,,0,0,0,,如果我们引入了DELAY\nDialogue: 0,0:38:29.04,0:38:30.33,Default,,0,0,0,,这样就在所有的地方完成了解耦\nDialogue: 0,0:38:30.40,0:38:31.42,Default,,0,0,0,,而不单单是在流中\nDialogue: 0,0:38:32.19,0:38:33.14,Default,,0,0,0,,我们的初衷是什么？\nDialogue: 0,0:38:33.14,0:38:38.11,Default,,0,0,0,,我们把程序设计看做是指定计算过程\nDialogue: 0,0:38:39.30,0:38:40.62,Default,,0,0,0,,如果我们放弃了对时间的控制\nDialogue: 0,0:38:40.65,0:38:42.41,Default,,0,0,0,,尽管语言变得优雅起来\nDialogue: 0,0:38:43.74,0:38:45.87,Default,,0,0,0,,但是它的表达力却有所下降\nDialogue: 0,0:38:47.03,0:38:49.84,Default,,0,0,0,,这里面还有一些我们无法消除的区别\nDialogue: 0,0:38:51.48,0:38:53.15,Default,,0,0,0,,其中之一就是迭代\nDialogue: 0,0:38:53.98,0:38:56.44,Default,,0,0,0,,还记得这个程序吗？\nDialogue: 0,0:38:56.96,0:38:58.28,Default,,0,0,0,,迭代式的阶乘\nDialogue: 0,0:38:58.44,0:39:00.48,Default,,0,0,0,,这是我们很早之前就研究过的\nDialogue: 0,0:39:01.23,0:39:02.97,Default,,0,0,0,,过程FACT-ITER\nDialogue: 0,0:39:03.04,0:39:04.91,Default,,0,0,0,,有一个内部过程ITER\nDialogue: 0,0:39:05.18,0:39:07.50,Default,,0,0,0,,它含有两个状态PRODUCT和COUNTER\nDialogue: 0,0:39:08.70,0:39:10.96,Default,,0,0,0,,它们随着循环不断迭代\nDialogue: 0,0:39:12.12,0:39:13.68,Default,,0,0,0,,之所以说这个过程是迭代的\nDialogue: 0,0:39:13.71,0:39:14.83,Default,,0,0,0,,是因为它没有创建新状态\nDialogue: 0,0:39:15.73,0:39:17.45,Default,,0,0,0,,之所以没有创建新状态\nDialogue: 0,0:39:17.47,0:39:20.25,Default,,0,0,0,,是因为在调用ITER时\nDialogue: 0,0:39:20.30,0:39:22.86,Default,,0,0,0,,作为参数传递给它自己的始终是这些东西\nDialogue: 0,0:39:23.90,0:39:25.39,Default,,0,0,0,,在代换模型中\nDialogue: 0,0:39:25.55,0:39:27.79,Default,,0,0,0,,Gerald教授给你们讲解过\nDialogue: 0,0:39:28.72,0:39:30.01,Default,,0,0,0,,在迭代过程中\nDialogue: 0,0:39:30.03,0:39:31.44,Default,,0,0,0,,状态并不需要增长\nDialogue: 0,0:39:31.82,0:39:34.22,Default,,0,0,0,,因此这是一个迭代过程\nDialogue: 0,0:39:34.99,0:39:37.47,Default,,0,0,0,,但是如果用正则序语言\nDialogue: 0,0:39:37.47,0:39:39.10,Default,,0,0,0,,来运行这段程序\nDialogue: 0,0:39:41.15,0:39:42.17,Default,,0,0,0,,这就会导致\nDialogue: 0,0:39:42.88,0:39:44.96,Default,,0,0,0,,这个过程不再是迭代式了\nDialogue: 0,0:39:45.65,0:39:48.67,Default,,0,0,0,,如果你仔细地思考代换模型\nDialogue: 0,0:39:48.67,0:39:49.90,Default,,0,0,0,,在这里我就不细说了\nDialogue: 0,0:39:51.20,0:39:52.35,Default,,0,0,0,,这个表达式会不断增长\nDialogue: 0,0:39:52.36,0:39:53.18,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:39:53.28,0:39:55.20,Default,,0,0,0,,因为当ITER调用自己时\nDialogue: 0,0:39:55.85,0:39:57.31,Default,,0,0,0,,参数是这个乘法表达式\nDialogue: 0,0:39:58.08,0:39:59.36,Default,,0,0,0,,而在正则序语言中\nDialogue: 0,0:39:59.39,0:40:01.16,Default,,0,0,0,,这个乘法并不会在这里求值\nDialogue: 0,0:40:02.51,0:40:03.82,Default,,0,0,0,,传递给自己并代换的\nDialogue: 0,0:40:03.93,0:40:05.68,Default,,0,0,0,,只是这个乘法计算的PROMISE\nDialogue: 0,0:40:06.67,0:40:08.03,Default,,0,0,0,,然后继续代换下去\nDialogue: 0,0:40:09.76,0:40:11.55,Default,,0,0,0,,我调用自己\nDialogue: 0,0:40:11.84,0:40:14.04,Default,,0,0,0,,用的是计算这个乘法的PROMISE\nDialogue: 0,0:40:14.04,0:40:17.82,Default,,0,0,0,,但其中的一个因数也是个PROMISE\nDialogue: 0,0:40:18.40,0:40:19.43,Default,,0,0,0,,然后我又自调用\nDialogue: 0,0:40:19.43,0:40:21.13,Default,,0,0,0,,如果你用代换模型\nDialogue: 0,0:40:21.98,0:40:23.60,Default,,0,0,0,,来推演这个迭代步骤\nDialogue: 0,0:40:23.77,0:40:26.83,Default,,0,0,0,,你会发现同样的状态增长\nDialogue: 0,0:40:27.16,0:40:28.96,Default,,0,0,0,,所有的PROMISE都需要被记住\nDialogue: 0,0:40:28.97,0:40:30.76,Default,,0,0,0,,以便在最后被调用\nDialogue: 0,0:40:31.79,0:40:35.02,Default,,0,0,0,,所以 正则序的缺点之一\nDialogue: 0,0:40:35.05,0:40:36.86,Default,,0,0,0,,就是无法有效地表达迭代\nDialogue: 0,0:40:36.98,0:40:39.60,Default,,0,0,0,,也许这个理由有点偏理论\nDialogue: 0,0:40:39.61,0:40:43.90,Default,,0,0,0,,但事实上 那些使用这类语言来编写\nDialogue: 0,0:40:44.27,0:40:47.56,Default,,0,0,0,,实际操作系统的人 也都遇到了这类问题\nDialogue: 0,0:40:48.20,0:40:50.75,Default,,0,0,0,,当然 完全可以\nDialogue: 0,0:40:51.64,0:40:54.38,Default,,0,0,0,,用这类语言实现一个文本编辑器\nDialogue: 0,0:40:54.61,0:40:56.08,Default,,0,0,0,,但是你才用了一会儿\nDialogue: 0,0:40:56.72,0:40:59.39,Default,,0,0,0,,就发现已经占用了3MB空间\nDialogue: 0,0:40:59.44,0:41:02.04,Default,,0,0,0,,我想 那些遇到这类问题的人\nDialogue: 0,0:41:02.16,0:41:05.60,Default,,0,0,0,,把它叫做 “拖尾问题”\nDialogue: 0,0:41:05.82,0:41:08.20,Default,,0,0,0,,由于不能有效地表达迭代计算\nDialogue: 0,0:41:08.24,0:41:10.46,Default,,0,0,0,,导致堆积了一堆没有被调用的PROMISE\nDialogue: 0,0:41:10.72,0:41:14.81,Default,,0,0,0,,针对这类语言的一个研究方向就是\nDialogue: 0,0:41:14.83,0:41:17.48,Default,,0,0,0,,找出一种有效的编译器技术\nDialogue: 0,0:41:17.82,0:41:19.85,Default,,0,0,0,,来避免这种所谓的“拖尾问题”\nDialogue: 0,0:41:20.17,0:41:21.61,Default,,0,0,0,,这并不简单\nDialogue: 0,0:41:23.94,0:41:27.31,Default,,0,0,0,,但是 还有一个很突出的问题\nDialogue: 0,0:41:27.96,0:41:31.04,Default,,0,0,0,,使你的语言不能变成正则序\nDialogue: 0,0:41:32.51,0:41:33.29,Default,,0,0,0,,问题就在于\nDialogue: 0,0:41:35.05,0:41:38.09,Default,,0,0,0,,正则序和副作用\nDialogue: 0,0:41:38.89,0:41:40.19,Default,,0,0,0,,是不相容的\nDialogue: 0,0:41:42.00,0:41:43.96,Default,,0,0,0,,它们不能很好地相互配合\nDialogue: 0,0:41:45.44,0:41:46.65,Default,,0,0,0,,这是因为 你不能\nDialogue: 0,0:41:48.28,0:41:50.80,Default,,0,0,0,,你不能一边\nDialogue: 0,0:41:51.00,0:41:54.33,Default,,0,0,0,,建模具有局部状态的对象\nDialogue: 0,0:41:55.72,0:41:56.96,Default,,0,0,0,,同时又\nDialogue: 0,0:41:57.18,0:41:59.55,Default,,0,0,0,,使用正则序的技巧来解耦时间\nDialogue: 0,0:42:00.40,0:42:03.55,Default,,0,0,0,,我来举一个非常简单的例子\nDialogue: 0,0:42:03.79,0:42:05.50,Default,,0,0,0,,假设语言是正则序求值\nDialogue: 0,0:42:07.52,0:42:09.55,Default,,0,0,0,,例子是这样的\nDialogue: 0,0:42:09.55,0:42:10.52,Default,,0,0,0,,注意现在是正则序求值\nDialogue: 0,0:42:10.52,0:42:12.22,Default,,0,0,0,,(DEFINE X 0)\nDialogue: 0,0:42:13.57,0:42:15.56,Default,,0,0,0,,这只是变量的初始化\nDialogue: 0,0:42:15.75,0:42:17.69,Default,,0,0,0,,现在我要定义一个有趣的函数\nDialogue: 0,0:42:18.57,0:42:20.44,Default,,0,0,0,,它就是恒等函数ID\nDialogue: 0,0:42:22.64,0:42:23.90,Default,,0,0,0,,它所做的就是\nDialogue: 0,0:42:24.11,0:42:26.60,Default,,0,0,0,,用X来记录上一次调用它时N的值\nDialogue: 0,0:42:31.40,0:42:34.16,Default,,0,0,0,,因此(ID N)就返回N\nDialogue: 0,0:42:34.17,0:42:35.39,Default,,0,0,0,,但还要把X赋值为N\nDialogue: 0,0:42:36.76,0:42:38.54,Default,,0,0,0,,最后再定义一个过程INC\nDialogue: 0,0:42:39.55,0:42:42.30,Default,,0,0,0,,也非常简单\nDialogue: 0,0:42:42.58,0:42:45.34,Default,,0,0,0,,假设在正则序求值的语言里\nDialogue: 0,0:42:46.27,0:42:47.23,Default,,0,0,0,,求值下面的表达式\nDialogue: 0,0:42:47.23,0:42:52.83,Default,,0,0,0,,我输入 (DEFINE Y (INC (ID 3)))\nDialogue: 0,0:42:52.83,0:42:53.96,Default,,0,0,0,,因此Y的值应该是4\nDialogue: 0,0:42:57.41,0:42:58.35,Default,,0,0,0,,X应该是多少呢？\nDialogue: 0,0:42:59.52,0:43:02.16,Default,,0,0,0,,X应该是最后一次被记住的值\nDialogue: 0,0:43:02.64,0:43:04.01,Default,,0,0,0,,也就是我调用函数ID的时候\nDialogue: 0,0:43:04.71,0:43:06.73,Default,,0,0,0,,你可能会想 这里X应该是3\nDialogue: 0,0:43:06.91,0:43:07.52,Default,,0,0,0,,但是并不是这样\nDialogue: 0,0:43:08.53,0:43:11.15,Default,,0,0,0,,这是因为当我在这里定义Y的时候\nDialogue: 0,0:43:11.79,0:43:13.45,Default,,0,0,0,,Y的真正定义却是\nDialogue: 0,0:43:13.47,0:43:15.71,Default,,0,0,0,,一个调用函数ID的PROMISE的增量\nDialogue: 0,0:43:17.00,0:43:18.17,Default,,0,0,0,,因为我没有访问Y\nDialogue: 0,0:43:18.36,0:43:20.25,Default,,0,0,0,,所以ID没有运行\nDialogue: 0,0:43:21.56,0:43:23.20,Default,,0,0,0,,我输入这个定义之后\nDialogue: 0,0:43:23.31,0:43:24.80,Default,,0,0,0,,然后查询X得到的结果是0\nDialogue: 0,0:43:28.36,0:43:31.20,Default,,0,0,0,,现在 我输入Y查询它的值\nDialogue: 0,0:43:31.52,0:43:32.43,Default,,0,0,0,,就会得到结果4\nDialogue: 0,0:43:32.67,0:43:35.16,Default,,0,0,0,,对Y的主动查询\nDialogue: 0,0:43:35.29,0:43:37.42,Default,,0,0,0,,会导致ID运行\nDialogue: 0,0:43:38.72,0:43:40.48,Default,,0,0,0,,现在X=3就被记住\nDialogue: 0,0:43:40.74,0:43:41.87,Default,,0,0,0,,所以上面这里的X就应该是0\nDialogue: 0,0:43:41.93,0:43:42.96,Default,,0,0,0,,下面这里是3\nDialogue: 0,0:43:43.28,0:43:46.16,Default,,0,0,0,,这是一个非常简单的场景\nDialogue: 0,0:43:46.30,0:43:49.28,Default,,0,0,0,,但你会发现 调试正则序语言\nDialogue: 0,0:43:50.36,0:43:53.34,Default,,0,0,0,,的交互式程序\nDialogue: 0,0:43:54.12,0:43:55.88,Default,,0,0,0,,会变得相当混乱\nDialogue: 0,0:43:57.10,0:43:58.12,Default,,0,0,0,,很令人迷惑\nDialogue: 0,0:43:59.69,0:44:02.04,Default,,0,0,0,,导致这样的深层次的原因\nDialogue: 0,0:44:02.80,0:44:06.41,Default,,0,0,0,,也就是引入DELAY的根本理念\nDialogue: 0,0:44:06.92,0:44:08.43,Default,,0,0,0,,是因为我们抛弃了时间的概念\nDialogue: 0,0:44:09.78,0:44:11.75,Default,,0,0,0,,也因为如此我们可以处理一些无穷的情况\nDialogue: 0,0:44:11.75,0:44:12.97,Default,,0,0,0,,我们抛弃了时间\nDialogue: 0,0:44:12.99,0:44:14.27,Default,,0,0,0,,就没有必要等它们运行\nDialogue: 0,0:44:17.55,0:44:20.44,Default,,0,0,0,,我们把计算机中事件发生的顺序\nDialogue: 0,0:44:20.83,0:44:22.11,Default,,0,0,0,,与程序中的顺序 分离开来\nDialogue: 0,0:44:22.35,0:44:25.28,Default,,0,0,0,,但是当我们谈及状态、赋值和改变的时候\nDialogue: 0,0:44:25.48,0:44:27.42,Default,,0,0,0,,这些又都是我们想要控制的\nDialogue: 0,0:44:28.76,0:44:33.82,Default,,0,0,0,,我们的目的有着根本性的矛盾\nDialogue: 0,0:44:34.57,0:44:39.12,Default,,0,0,0,,这又让我们进入了一个哲学问题\nDialogue: 0,0:44:39.13,0:44:40.75,Default,,0,0,0,,用什么样的模型\nDialogue: 0,0:44:40.78,0:44:41.77,Default,,0,0,0,,和从什么角度来看这个世界\nDialogue: 0,0:44:42.41,0:44:44.30,Default,,0,0,0,,有时这也被称为\nDialogue: 0,0:44:44.76,0:44:46.60,Default,,0,0,0,,“函数式程序设计的争论”\nDialogue: 0,0:44:54.19,0:44:56.60,Default,,0,0,0,,所谓的“纯函数式语言”\nDialogue: 0,0:44:57.07,0:44:59.20,Default,,0,0,0,,是完全没有副作用的\nDialogue: 0,0:45:00.44,0:45:01.63,Default,,0,0,0,,不需要副作用\nDialogue: 0,0:45:01.64,0:45:03.02,Default,,0,0,0,,也就不需要赋值运算符\nDialogue: 0,0:45:03.34,0:45:05.72,Default,,0,0,0,,也就没有什么糟糕的后果\nDialogue: 0,0:45:06.36,0:45:07.93,Default,,0,0,0,,可以使用类似代换模型\nDialogue: 0,0:45:07.93,0:45:10.48,Default,,0,0,0,,程序更像是数学\nDialogue: 0,0:45:10.76,0:45:13.82,Default,,0,0,0,,而不像现实世界中的模型和对象\nDialogue: 0,0:45:15.05,0:45:17.17,Default,,0,0,0,,函数式语言有很多了不起的特性\nDialogue: 0,0:45:17.17,0:45:19.63,Default,,0,0,0,,没有时间的概念 所以完全不用担心同步的问题\nDialogue: 0,0:45:20.64,0:45:23.72,Default,,0,0,0,,如果你想在并行算法中应用一些东西\nDialogue: 0,0:45:24.72,0:45:28.20,Default,,0,0,0,,你可以在这些并行过程中随心所欲地使用\nDialogue: 0,0:45:29.40,0:45:31.44,Default,,0,0,0,,从来不担心同步问题\nDialogue: 0,0:45:31.50,0:45:33.34,Default,,0,0,0,,在这种环境下这样做是非常方便的\nDialogue: 0,0:45:33.64,0:45:35.71,Default,,0,0,0,,代价则是 放弃了赋值\nDialogue: 0,0:45:39.10,0:45:41.32,Default,,0,0,0,,函数式语言的支持者会认为\nDialogue: 0,0:45:41.34,0:45:43.04,Default,,0,0,0,,这点代价算不了什么\nDialogue: 0,0:45:44.52,0:45:46.51,Default,,0,0,0,,在大部分情况下 你都不应该使用赋值\nDialogue: 0,0:45:46.88,0:45:48.27,Default,,0,0,0,,如果用你放弃了赋值\nDialogue: 0,0:45:48.43,0:45:51.40,Default,,0,0,0,,你可以得到一个比对象世界\nDialogue: 0,0:45:51.96,0:45:53.24,Default,,0,0,0,,好得多的世界\nDialogue: 0,0:45:54.19,0:45:56.30,Default,,0,0,0,,怎么来反驳这个观点呢？\nDialogue: 0,0:45:56.30,0:45:58.59,Default,,0,0,0,,想想 我们如何走到这一步的\nDialogue: 0,0:46:00.06,0:46:03.79,Default,,0,0,0,,我们尝试建模具有局部状态的对象\nDialogue: 0,0:46:04.44,0:46:06.49,Default,,0,0,0,,想一想Gerald教授给你们讲的随机数生成器\nDialogue: 0,0:46:07.16,0:46:08.67,Default,,0,0,0,,这里有一个随机数生成器\nDialogue: 0,0:46:09.28,0:46:10.62,Default,,0,0,0,,它内部有一些状态\nDialogue: 0,0:46:10.83,0:46:12.08,Default,,0,0,0,,用来计算下一个随机数\nDialogue: 0,0:46:12.12,0:46:14.08,Default,,0,0,0,,下下一个 以及再下一个\nDialogue: 0,0:46:14.28,0:46:16.14,Default,,0,0,0,,我们想要把这些状态跟\nDialogue: 0,0:46:16.43,0:46:18.96,Default,,0,0,0,,计算π的Cesaro算法分离开来\nDialogue: 0,0:46:19.84,0:46:20.92,Default,,0,0,0,,这就是我们为什么需要赋值\nDialogue: 0,0:46:20.97,0:46:22.91,Default,,0,0,0,,我们想要把状态封装在模块中\nDialogue: 0,0:46:24.07,0:46:26.36,Default,,0,0,0,,函数式语言程序员可能会说\nDialogue: 0,0:46:26.38,0:46:27.56,Default,,0,0,0,,“你搞错了”\nDialogue: 0,0:46:27.56,0:46:29.84,Default,,0,0,0,,“我的意思是 你能写出另一种更具模块化的程序”\nDialogue: 0,0:46:29.84,0:46:32.46,Default,,0,0,0,,“你对模块化的认识并不正确”\nDialogue: 0,0:46:33.08,0:46:35.02,Default,,0,0,0,,你太执着于 “生成一个随机数\nDialogue: 0,0:46:35.07,0:46:36.88,Default,,0,0,0,,再生成一个 再生成一个” 这种范式了\nDialogue: 0,0:46:36.88,0:46:39.42,Default,,0,0,0,,为什么不写一个这样的程序\nDialogue: 0,0:46:40.09,0:46:41.29,Default,,0,0,0,,构造一个枚举器\nDialogue: 0,0:46:41.95,0:46:44.48,Default,,0,0,0,,它会生成一个随机数的无穷流\nDialogue: 0,0:46:49.01,0:46:50.91,Default,,0,0,0,,我们可以立即生成这个流\nDialogue: 0,0:46:52.64,0:46:54.54,Default,,0,0,0,,这样就可以用作随机数的源泉\nDialogue: 0,0:46:54.54,0:46:55.24,Default,,0,0,0,,如果有需要的话\nDialogue: 0,0:46:55.53,0:46:57.47,Default,,0,0,0,,你可以把它跟某个处理过程相连\nDialogue: 0,0:46:57.77,0:47:01.16,Default,,0,0,0,,比如说Cesaro测试\nDialogue: 0,0:47:04.94,0:47:06.22,Default,,0,0,0,,然后这个处理过程进行自己的计算\nDialogue: 0,0:47:06.88,0:47:08.56,Default,,0,0,0,,从这里出来的则是\nDialogue: 0,0:47:08.72,0:47:27.45,Default,,0,0,0,,其中是一串的对π的估计值组成的流\nDialogue: 0,0:47:28.14,0:47:30.65,Default,,0,0,0,,随着我们深入访问这个流\nDialogue: 0,0:47:30.76,0:47:32.38,Default,,0,0,0,,相当于去拽这个Cesaro盒子\nDialogue: 0,0:47:33.12,0:47:35.36,Default,,0,0,0,,它就会拉取出许多随机数\nDialogue: 0,0:47:35.54,0:47:37.21,Default,,0,0,0,,随着我们对流的深入访问\nDialogue: 0,0:47:37.23,0:47:38.96,Default,,0,0,0,,得到的对π的估计值就越准\nDialogue: 0,0:47:39.72,0:47:41.66,Default,,0,0,0,,具体的计算过程还是一样的\nDialogue: 0,0:47:41.66,0:47:43.79,Default,,0,0,0,,只不过使用了另一种模块化的方式\nDialogue: 0,0:47:43.89,0:47:45.55,Default,,0,0,0,,我们可以想象成一下子\nDialogue: 0,0:47:45.56,0:47:47.47,Default,,0,0,0,,就有了这所有的随机数\nDialogue: 0,0:47:49.28,0:47:52.24,Default,,0,0,0,,这个过程的细节在书上有\nDialogue: 0,0:47:53.61,0:47:57.85,Default,,0,0,0,,我们同样也陷于另外一些类似的事情中\nDialogue: 0,0:47:58.27,0:48:01.20,Default,,0,0,0,,这种关于 这个、下一个以及再下一个的范式\nDialogue: 0,0:48:01.37,0:48:02.81,Default,,0,0,0,,完全可以不这么来做\nDialogue: 0,0:48:03.28,0:48:06.54,Default,,0,0,0,,我们来思考一下银行系统\nDialogue: 0,0:48:07.68,0:48:08.90,Default,,0,0,0,,有个非常简单的场景\nDialogue: 0,0:48:08.90,0:48:12.21,Default,,0,0,0,,我们假设这个程序代表了银行帐户\nDialogue: 0,0:48:18.81,0:48:20.84,Default,,0,0,0,,银行账户中可能有\nDialogue: 0,0:48:22.78,0:48:26.22,Default,,0,0,0,,如果我们以消息传递的角度来看\nDialogue: 0,0:48:26.44,0:48:28.12,Default,,0,0,0,,我们认为银行账户是一个对象\nDialogue: 0,0:48:28.59,0:48:31.51,Default,,0,0,0,,内部保存着标识余额的局部状态BALANCE\nDialogue: 0,0:48:34.11,0:48:36.00,Default,,0,0,0,,如果一个用户使用这个系统\nDialogue: 0,0:48:36.44,0:48:38.14,Default,,0,0,0,,发出交易请求\nDialogue: 0,0:48:39.31,0:48:41.05,Default,,0,0,0,,用户发出的交易请求可能是\nDialogue: 0,0:48:41.07,0:48:42.20,Default,,0,0,0,,存一些钱\nDialogue: 0,0:48:42.28,0:48:43.53,Default,,0,0,0,,银行账户就会\nDialogue: 0,0:48:43.92,0:48:46.78,Default,,0,0,0,,我们假设银行账户总是以当前余额作为回应\nDialogue: 0,0:48:48.22,0:48:50.04,Default,,0,0,0,,用户存了一些钱\nDialogue: 0,0:48:50.06,0:48:53.21,Default,,0,0,0,,银行账户就会返回一个消息指明当前余额\nDialogue: 0,0:48:54.35,0:48:57.42,Default,,0,0,0,,用户再存一些钱\nDialogue: 0,0:48:57.45,0:48:58.81,Default,,0,0,0,,银行就再返回消息\nDialogue: 0,0:48:59.15,0:49:00.75,Default,,0,0,0,,就像生成随机数一样\nDialogue: 0,0:49:00.78,0:49:02.12,Default,,0,0,0,,我们想使用赋值来实现\nDialogue: 0,0:49:03.20,0:49:06.88,Default,,0,0,0,,帐户的内部保存了局部状态BALANCE\nDialogue: 0,0:49:06.88,0:49:08.40,Default,,0,0,0,,因为我们想要把用户状态\nDialogue: 0,0:49:08.41,0:49:09.57,Default,,0,0,0,,和银行账户的状态分离开来\nDialogue: 0,0:49:13.28,0:49:16.42,Default,,0,0,0,,这是从消息传递的角度来看\nDialogue: 0,0:49:16.42,0:49:18.20,Default,,0,0,0,,如果从流的角度来看\nDialogue: 0,0:49:19.48,0:49:22.19,Default,,0,0,0,,不需要赋值或副作用就可以达到同样的效果\nDialogue: 0,0:49:22.74,0:49:26.73,Default,,0,0,0,,再次强调 想法是这样的\nDialogue: 0,0:49:27.37,0:49:30.25,Default,,0,0,0,,我们认为它们都没有局部状态\nDialogue: 0,0:49:31.18,0:49:33.08,Default,,0,0,0,,我们把银行账户看作是\nDialogue: 0,0:49:33.40,0:49:37.71,Default,,0,0,0,,能够处理一系列交易请求的东西\nDialogue: 0,0:49:38.64,0:49:40.16,Default,,0,0,0,,不把银行账户看做\nDialogue: 0,0:49:40.22,0:49:42.00,Default,,0,0,0,,逐个消息地处理\nDialogue: 0,0:49:42.44,0:49:45.85,Default,,0,0,0,,而是处理某种交易请求流的东西\nDialogue: 0,0:49:45.87,0:49:48.49,Default,,0,0,0,,这个请求流可能是一些列的存款声明\nDialogue: 0,0:49:49.49,0:49:54.94,Default,,0,0,0,,比如 1 2 2 4 这样的连续存钱请求\nDialogue: 0,0:49:55.94,0:50:02.44,Default,,0,0,0,,从帐户出来的流应该是 1 3 5 9\nDialogue: 0,0:50:03.77,0:50:06.14,Default,,0,0,0,,我们不把银行账户看做某种具有状态的东西\nDialogue: 0,0:50:06.40,0:50:07.26,Default,,0,0,0,,而是某种能够处理\nDialogue: 0,0:50:08.92,0:50:10.82,Default,,0,0,0,,有关请求的无穷流的东西\nDialogue: 0,0:50:10.82,0:50:12.30,Default,,0,0,0,,但要注意 我们抛弃了时间\nDialogue: 0,0:50:12.37,0:50:14.27,Default,,0,0,0,,如果这里有一个用户\nDialogue: 0,0:50:16.12,0:50:19.13,Default,,0,0,0,,这个无穷请求流的元素\nDialogue: 0,0:50:19.18,0:50:22.54,Default,,0,0,0,,我们可以一次生成一个\nDialogue: 0,0:50:24.06,0:50:26.57,Default,,0,0,0,,而这个交易流\nDialogue: 0,0:50:26.57,0:50:28.80,Default,,0,0,0,,则会逐个打印在屏幕上\nDialogue: 0,0:50:30.01,0:50:31.37,Default,,0,0,0,,如果在这里画一条线\nDialogue: 0,0:50:32.56,0:50:33.08,Default,,0,0,0,,就在这里\nDialogue: 0,0:50:33.28,0:50:34.91,Default,,0,0,0,,对用户来说 他根本无法分辨\nDialogue: 0,0:50:36.19,0:50:37.71,Default,,0,0,0,,这个系统是否有内部状态\nDialogue: 0,0:50:39.56,0:50:41.13,Default,,0,0,0,,这个跟消息传递那种是一样的\nDialogue: 0,0:50:41.29,0:50:42.46,Default,,0,0,0,,只不过这个没有状态\nDialogue: 0,0:50:42.84,0:50:45.87,Default,,0,0,0,,哦 顺便提一下\nDialogue: 0,0:50:46.72,0:50:49.47,Default,,0,0,0,,这是具体的代码实现\nDialogue: 0,0:50:50.52,0:50:52.30,Default,,0,0,0,,我们把它叫做MAKE-DEPOSIT-ACCOUNT\nDialogue: 0,0:50:52.32,0:50:53.32,Default,,0,0,0,,因为它只能够存钱\nDialogue: 0,0:50:54.17,0:50:55.77,Default,,0,0,0,,这个过程接受一个初始余额\nDialogue: 0,0:50:56.09,0:50:58.09,Default,,0,0,0,,以及一个可能发起的存款流\nDialogue: 0,0:51:00.02,0:51:00.82,Default,,0,0,0,,具体怎么做呢？\nDialogue: 0,0:51:00.82,0:51:02.54,Default,,0,0,0,,它只是用CONS-STREAM把余额BALANCE\nDialogue: 0,0:51:03.23,0:51:05.31,Default,,0,0,0,,和一个新的存款账户流组合在一起\nDialogue: 0,0:51:06.24,0:51:07.32,Default,,0,0,0,,新存款流的初始余额\nDialogue: 0,0:51:07.48,0:51:10.27,Default,,0,0,0,,就是之前BALANCE的值加上存款流的第一个元素\nDialogue: 0,0:51:10.86,0:51:13.40,Default,,0,0,0,,而其余部分则是\nDialogue: 0,0:51:13.76,0:51:17.37,Default,,0,0,0,,存款流的尾部分\nDialogue: 0,0:51:18.30,0:51:23.84,Default,,0,0,0,,因此这种非常典型的消息传递式、面向对象的问题\nDialogue: 0,0:51:23.95,0:51:27.55,Default,,0,0,0,,完全可以不用副作用来解决\nDialogue: 0,0:51:29.05,0:51:30.76,Default,,0,0,0,,很多地方都可以这样做\nDialogue: 0,0:51:32.25,0:51:35.23,Default,,0,0,0,,那么 我们可以完全不用赋值么？\nDialogue: 0,0:51:36.40,0:51:39.00,Default,,0,0,0,,可以只用纯函数式语言吗？\nDialogue: 0,0:51:40.05,0:51:42.04,Default,,0,0,0,,这个问题谁也说不清\nDialogue: 0,0:51:42.27,0:51:43.44,Default,,0,0,0,,好像有些地方\nDialogue: 0,0:51:43.92,0:51:46.03,Default,,0,0,0,,纯函数式语言无法派上用场\nDialogue: 0,0:51:48.10,0:51:50.27,Default,,0,0,0,,当遇到像这样的系统时 问题就变得棘手起来\nDialogue: 0,0:51:50.43,0:51:52.32,Default,,0,0,0,,特别是当你\nDialogue: 0,0:51:52.60,0:51:54.27,Default,,0,0,0,,还需要考虑其它因素的时候\nDialogue: 0,0:51:54.30,0:51:55.64,Default,,0,0,0,,有关对象和共享\nDialogue: 0,0:51:55.90,0:51:58.52,Default,,0,0,0,,以及两个独立的主体共享同一个东西\nDialogue: 0,0:51:58.85,0:51:59.93,Default,,0,0,0,,举一个典型的例子\nDialogue: 0,0:51:59.96,0:52:01.63,Default,,0,0,0,,假如你来扩展这个帐户\nDialogue: 0,0:52:03.24,0:52:04.27,Default,,0,0,0,,这是一个帐户\nDialogue: 0,0:52:12.22,0:52:14.75,Default,,0,0,0,,帐户接受一个交易请求流\nDialogue: 0,0:52:15.20,0:52:18.44,Default,,0,0,0,,输出的流则是关于余额的回复\nDialogue: 0,0:52:18.78,0:52:20.16,Default,,0,0,0,,假设你所建模的是联合账户\nDialogue: 0,0:52:20.17,0:52:24.36,Default,,0,0,0,,而由两个独立用户共享\nDialogue: 0,0:52:25.68,0:52:28.65,Default,,0,0,0,,我们假设 假设有两个人\nDialogue: 0,0:52:28.97,0:52:30.96,Default,,0,0,0,,比如说Bill和Dave\nDialogue: 0,0:52:31.77,0:52:33.14,Default,,0,0,0,,他们俩共享一个帐户\nDialogue: 0,0:52:35.96,0:52:36.85,Default,,0,0,0,,怎么来建模呢？\nDialogue: 0,0:52:36.88,0:52:39.80,Default,,0,0,0,,你或许会让Bill输出一个交易请求流\nDialogue: 0,0:52:40.24,0:52:42.25,Default,,0,0,0,,Dave也产生一个这样的流\nDialogue: 0,0:52:42.25,0:52:45.16,Default,,0,0,0,,这两个流需要以某种方式合并到银行账户中\nDialogue: 0,0:52:45.88,0:52:47.85,Default,,0,0,0,,因此你需要编写一个MERGE过程\nDialogue: 0,0:52:47.90,0:52:50.65,Default,,0,0,0,,来处理这些流\nDialogue: 0,0:52:57.23,0:52:59.13,Default,,0,0,0,,它把这些流合并在一起\nDialogue: 0,0:52:59.34,0:53:01.19,Default,,0,0,0,,形成单个流 送入银行账户\nDialogue: 0,0:53:01.19,0:53:02.99,Default,,0,0,0,,现在他们就共享一个帐户了\nDialogue: 0,0:53:03.61,0:53:05.48,Default,,0,0,0,,看起来不错 问题是怎么来实现MERGE\nDialogue: 0,0:53:05.93,0:53:08.24,Default,,0,0,0,,MERGE怎么来合并？\nDialogue: 0,0:53:09.73,0:53:11.42,Default,,0,0,0,,需要合理的合并依据\nDialogue: 0,0:53:12.38,0:53:13.80,Default,,0,0,0,,你可能首先会想\nDialogue: 0,0:53:13.80,0:53:16.68,Default,,0,0,0,,我们从Bill和Dave中选一个请求来处理\nDialogue: 0,0:53:18.19,0:53:20.97,Default,,0,0,0,,但是如果在这中途\nDialogue: 0,0:53:21.18,0:53:23.08,Default,,0,0,0,,Dave突然外出度假两年 会怎么样？\nDialogue: 0,0:53:24.15,0:53:25.40,Default,,0,0,0,,Bill的交易就完全被阻塞了\nDialogue: 0,0:53:27.69,0:53:29.75,Default,,0,0,0,,你想要的是\nDialogue: 0,0:53:29.75,0:53:33.64,Default,,0,0,0,,是一种公平的合并\nDialogue: 0,0:53:38.41,0:53:40.17,Default,,0,0,0,,这个所谓公平的合并\nDialogue: 0,0:53:40.73,0:53:42.46,Default,,0,0,0,,应该是交替地一次处理一个\nDialogue: 0,0:53:42.49,0:53:43.92,Default,,0,0,0,,但是如果一个人没有了交易\nDialogue: 0,0:53:43.96,0:53:44.91,Default,,0,0,0,,应该继续去处理另一个人的交易\nDialogue: 0,0:53:46.01,0:53:48.45,Default,,0,0,0,,但是没有时间 我就不能这样做\nDialogue: 0,0:53:51.30,0:53:56.41,Default,,0,0,0,,函数式语言的另一个活跃研究领域就是\nDialogue: 0,0:53:56.43,0:53:59.48,Default,,0,0,0,,发明类似于“公平合并”的算法\nDialogue: 0,0:54:00.35,0:54:01.31,Default,,0,0,0,,又或者是其它的东西\nDialogue: 0,0:54:01.56,0:54:06.25,Default,,0,0,0,,用于取代原来需要副作用和对象的地方\nDialogue: 0,0:54:06.80,0:54:10.52,Default,,0,0,0,,用一种良好定义的模块化系统来隐藏它们\nDialogue: 0,0:54:10.86,0:54:13.50,Default,,0,0,0,,这样 系统中就不会到处产生\nDialogue: 0,0:54:13.52,0:54:15.34,Default,,0,0,0,,赋值所带来的问题\nDialogue: 0,0:54:15.40,0:54:17.88,Default,,0,0,0,,因为它可以被理解透彻的概念所描述\nDialogue: 0,0:54:20.78,0:54:22.70,Default,,0,0,0,,推而广之 我想你们也发现了\nDialogue: 0,0:54:23.12,0:54:24.06,Default,,0,0,0,,我们正面对 我所认为的\nDialogue: 0,0:54:24.08,0:54:26.67,Default,,0,0,0,,计算机科学中最基本的问题\nDialogue: 0,0:54:26.97,0:54:27.82,Default,,0,0,0,,也就是\nDialogue: 0,0:54:28.24,0:54:32.03,Default,,0,0,0,,我们如何定义一门支持延迟求值的语言\nDialogue: 0,0:54:34.14,0:54:35.08,Default,,0,0,0,,但同时又能够\nDialogue: 0,0:54:35.87,0:54:38.25,Default,,0,0,0,,又能够把事物看做对象来操作\nDialogue: 0,0:54:38.36,0:54:40.36,Default,,0,0,0,,怎么样才能两者兼有之？\nDialogue: 0,0:54:41.23,0:54:43.04,Default,,0,0,0,,我认为这个问题很困难\nDialogue: 0,0:54:43.04,0:54:45.52,Default,,0,0,0,,但是这个很困难的问题\nDialogue: 0,0:54:45.85,0:54:48.17,Default,,0,0,0,,却和计算机科学的关系不大\nDialogue: 0,0:54:48.59,0:54:50.24,Default,,0,0,0,,它真正涉及的是\nDialogue: 0,0:54:50.27,0:54:52.73,Default,,0,0,0,,两种不相容的看待世界的方式\nDialogue: 0,0:54:54.14,0:54:54.72,Default,,0,0,0,,有问题吗？\nDialogue: 0,0:55:17.55,0:55:19.20,Default,,0,0,0,,学生：你之前提到过\nDialogue: 0,0:55:20.11,0:55:21.32,Default,,0,0,0,,一旦引入了赋值\nDialogue: 0,0:55:21.32,0:55:25.89,Default,,0,0,0,,就不能使用代换模型了\nDialogue: 0,0:55:25.89,0:55:27.57,Default,,0,0,0,,除非你非常小心\nDialogue: 0,0:55:27.57,0:55:27.96,Default,,0,0,0,,教授：对的\nDialogue: 0,0:55:28.26,0:55:33.28,Default,,0,0,0,,学生：有什么技术或者指导方针\nDialogue: 0,0:55:33.42,0:55:35.92,Default,,0,0,0,,来确定赋值的影响\nDialogue: 0,0:55:36.52,0:55:40.30,Default,,0,0,0,,以便说清楚这个“很小心”是怎么回事吗？\nDialogue: 0,0:55:40.30,0:55:42.60,Default,,0,0,0,,教授：我不知道\nDialogue: 0,0:55:42.89,0:55:43.58,Default,,0,0,0,,我想想\nDialogue: 0,0:55:45.43,0:55:48.94,Default,,0,0,0,,当然 实现MEM-PROC也使用了赋值\nDialogue: 0,0:55:50.12,0:55:51.48,Default,,0,0,0,,但是它被隐藏了起来\nDialogue: 0,0:55:51.48,0:55:53.00,Default,,0,0,0,,因为它没有对结果造成影响\nDialogue: 0,0:55:53.48,0:55:56.44,Default,,0,0,0,,部分原因之一在于 一旦触发这个过程\nDialogue: 0,0:55:57.15,0:55:58.83,Default,,0,0,0,,它被求值并得到结果\nDialogue: 0,0:55:58.83,0:56:00.06,Default,,0,0,0,,这个结果不会再变化\nDialogue: 0,0:56:00.60,0:56:02.33,Default,,0,0,0,,有点像单次赋值\nDialogue: 0,0:56:02.35,0:56:03.85,Default,,0,0,0,,一个一般性原则就是\nDialogue: 0,0:56:04.30,0:56:06.35,Default,,0,0,0,,如果你只用这种单次赋值\nDialogue: 0,0:56:08.04,0:56:09.24,Default,,0,0,0,,并且它不再改变\nDialogue: 0,0:56:09.63,0:56:10.54,Default,,0,0,0,,我想应该不会有太大问题\nDialogue: 0,0:56:11.25,0:56:14.12,Default,,0,0,0,,还有一个问题在于MERGE --\nDialogue: 0,0:56:14.67,0:56:18.32,Default,,0,0,0,,让我想想对不对\nDialogue: 0,0:56:18.49,0:56:21.55,Default,,0,0,0,,我认为有了公平合并这一技术\nDialogue: 0,0:56:22.25,0:56:26.09,Default,,0,0,0,,你可以在语言的其它地方\nDialogue: 0,0:56:27.02,0:56:28.89,Default,,0,0,0,,有效地模拟赋值\nDialogue: 0,0:56:30.82,0:56:33.29,Default,,0,0,0,,这就像为了解决问题你会引入一些东西\nDialogue: 0,0:56:33.50,0:56:35.50,Default,,0,0,0,,我不清楚对公平合并来说是否成立\nDialogue: 0,0:56:35.53,0:56:39.31,Default,,0,0,0,,但是对人们正在尝试的一些一般性事情是成立的\nDialogue: 0,0:56:39.52,0:56:41.34,Default,,0,0,0,,所以 这可能是你引入的这一点点东西\nDialogue: 0,0:56:41.61,0:56:44.14,Default,,0,0,0,,突然间 使你能构建任何东西\nDialogue: 0,0:56:44.16,0:56:46.51,Default,,0,0,0,,这就几乎跟有了赋值一样糟糕了\nDialogue: 0,0:56:47.97,0:56:50.67,Default,,0,0,0,,这也是人们在研究的一个领域\nDialogue: 0,0:56:51.59,0:56:54.30,Default,,0,0,0,,学生：我还没有太明白MERGE的问题\nDialogue: 0,0:56:54.83,0:56:59.20,Default,,0,0,0,,如果我调用Bill它是个过程\nDialogue: 0,0:56:59.21,0:57:02.41,Default,,0,0,0,,那么Bill就会增加银行账户\nDialogue: 0,0:57:02.44,0:57:04.73,Default,,0,0,0,,或者创建一个表 用于放置下一个存款\nDialogue: 0,0:57:04.73,0:57:06.84,Default,,0,0,0,,如果我连续调用Dave两次 他肯定也会那样\nDialogue: 0,0:57:07.17,0:57:09.35,Default,,0,0,0,,我并不清楚为什么需要公平合并\nDialogue: 0,0:57:09.35,0:57:11.20,Default,,0,0,0,,教授：关键在于你得把这些当作真人一样\nDialogue: 0,0:57:11.20,0:57:14.20,Default,,0,0,0,,这里有一个用户在操作帐户\nDialogue: 0,0:57:14.85,0:57:17.07,Default,,0,0,0,,请求一次 得到结果\nDialogue: 0,0:57:17.20,0:57:17.56,Default,,0,0,0,,学生：对\nDialogue: 0,0:57:18.20,0:57:20.62,Default,,0,0,0,,教授：如果我只能通过从两个流中选择一个\nDialogue: 0,0:57:20.65,0:57:22.25,Default,,0,0,0,,来处理请求的话\nDialogue: 0,0:57:22.91,0:57:24.22,Default,,0,0,0,,学生：为什么要二选一呢？\nDialogue: 0,0:57:24.22,0:57:25.23,Default,,0,0,0,,教授：为什么不呢？\nDialogue: 0,0:57:25.45,0:57:25.80,Default,,0,0,0,,学生：对啊 为什么要这样呢？\nDialogue: 0,0:57:26.60,0:57:27.72,Default,,0,0,0,,教授：假设这些是现实中的人 对吗？\nDialogue: 0,0:57:27.76,0:57:28.97,Default,,0,0,0,,这个人外出一年\nDialogue: 0,0:57:29.28,0:57:31.74,Default,,0,0,0,,你只能在银行账户窗口旁边等待\nDialogue: 0,0:57:32.43,0:57:33.72,Default,,0,0,0,,就是不能处理两个请求\nDialogue: 0,0:57:33.74,0:57:34.94,Default,,0,0,0,,因为你还得等这个人\nDialogue: 0,0:57:35.48,0:57:37.07,Default,,0,0,0,,学生：为什么非得等他呢？\nDialogue: 0,0:57:37.38,0:57:39.11,Default,,0,0,0,,教授：因为这里是在计算一个函数\nDialogue: 0,0:57:39.11,0:57:40.92,Default,,0,0,0,,我必须定义一个函数\nDialogue: 0,0:57:41.72,0:57:42.60,Default,,0,0,0,,换种方式来说\nDialogue: 0,0:57:42.84,0:57:44.99,Default,,0,0,0,,这个MERGE盒子的输出\nDialogue: 0,0:57:46.24,0:57:49.48,Default,,0,0,0,,并不是输入的函数\nDialogue: 0,0:57:51.69,0:57:53.49,Default,,0,0,0,,明白了吗？再来看看这个MERGE是怎么运行的\nDialogue: 0,0:57:53.49,0:57:58.86,Default,,0,0,0,,假设Bill输入 1 1 1 1\nDialogue: 0,0:57:59.82,0:58:02.78,Default,,0,0,0,,Dave输入2 2 2 2\nDialogue: 0,0:58:03.47,0:58:04.80,Default,,0,0,0,,MERGE应该输出什么呢？\nDialogue: 0,0:58:05.58,0:58:08.74,Default,,0,0,0,,这里并不一定是 1 2 1 2 1 2\nDialogue: 0,0:58:08.74,0:58:09.39,Default,,0,0,0,,学生：我明白了\nDialogue: 0,0:58:09.39,0:58:11.56,Default,,0,0,0,,当Bill输入1 1也就进去了\nDialogue: 0,0:58:11.56,0:58:13.95,Default,,0,0,0,,Dave再输入两个2 MERGE就输出两个2\nDialogue: 0,0:58:13.95,0:58:14.73,Default,,0,0,0,,学生：当Bill输入\nDialogue: 0,0:58:14.76,0:58:15.08,Default,,0,0,0,,教授：对的\nDialogue: 0,0:58:15.13,0:58:18.43,Default,,0,0,0,,学生：为什么不能在输入的数据上\nDialogue: 0,0:58:18.59,0:58:20.06,Default,,0,0,0,,加上时间信息呢？\nDialogue: 0,0:58:20.12,0:58:21.84,Default,,0,0,0,,教授：因为这里没有时间这个概念\nDialogue: 0,0:58:23.98,0:58:26.90,Default,,0,0,0,,我只是定义一个函数\nDialogue: 0,0:58:26.90,0:58:28.15,Default,,0,0,0,,没有时间概念\nDialogue: 0,0:58:32.00,0:58:34.19,Default,,0,0,0,,如果是二选一的话\nDialogue: 0,0:58:34.19,0:58:36.54,Default,,0,0,0,,如果选中的流没有人 就得等待它\nDialogue: 0,0:58:38.42,0:58:41.36,Default,,0,0,0,,它只会说 我有一个请求流\nDialogue: 0,0:58:41.74,0:58:43.34,Default,,0,0,0,,这是是Dave生成的\nDialogue: 0,0:58:43.36,0:58:45.29,Default,,0,0,0,,没有时刻的、无穷长度的请求流\nDialogue: 0,0:58:47.55,0:58:50.41,Default,,0,0,0,,Bill可能生成 没有时刻的无穷请求流\nDialogue: 0,0:58:50.54,0:58:51.69,Default,,0,0,0,,我想对这些东西做运算\nDialogue: 0,0:58:51.69,0:58:53.51,Default,,0,0,0,,这就是银行帐户的工作原理\nDialogue: 0,0:58:56.71,0:58:57.58,Default,,0,0,0,,问题是\nDialogue: 0,0:58:57.61,0:59:00.75,Default,,0,0,0,,这些坐在银行窗口前的倒霉蛋们\nDialogue: 0,0:59:00.76,0:59:03.82,Default,,0,0,0,,来得并不是时候\nDialogue: 0,0:59:05.29,0:59:07.13,Default,,0,0,0,,它们才看不到这个无穷流\nDialogue: 0,0:59:07.69,0:59:09.53,Default,,0,0,0,,什么时候其中会有请求\nDialogue: 0,0:59:10.07,0:59:11.55,Default,,0,0,0,,他们只是等着 等待帐户的响应\nDialogue: 0,0:59:14.48,0:59:15.76,Default,,0,0,0,,假设你坐在屏幕前\nDialogue: 0,0:59:16.24,0:59:20.86,Default,,0,0,0,,操作着一台分时系统的计算机\nDialogue: 0,0:59:21.52,0:59:22.60,Default,,0,0,0,,而且它还是函数式的\nDialogue: 0,0:59:22.64,0:59:24.59,Default,,0,0,0,,输入指令后你就希望看到结果\nDialogue: 0,0:59:25.29,0:59:27.42,Default,,0,0,0,,但是你并不想主机在处理完所有其它人的命令\nDialogue: 0,0:59:27.45,0:59:29.92,Default,,0,0,0,,之后再来处理你的命令\nDialogue: 0,0:59:30.91,0:59:31.92,Default,,0,0,0,,这就是问题所在\nDialogue: 0,0:59:34.00,0:59:36.38,Default,,0,0,0,,我的意思就是 用户的世界当然是存在时间概念的\nDialogue: 0,0:59:37.21,0:59:38.62,Default,,0,0,0,,如果没有 这就不构成问题\nDialogue: 0,0:59:49.10,0:59:51.02,Default,,0,0,0,,学生：我想我还是不太理解\nDialogue: 0,0:59:51.08,0:59:54.24,Default,,0,0,0,,银行交易中为什么没有时间概念这一要点\nDialogue: 0,0:59:54.74,0:59:56.65,Default,,0,0,0,,难道时间不是非常重要吗？\nDialogue: 0,0:59:56.88,0:59:59.05,Default,,0,0,0,,举例说 有一系列事件\nDialogue: 0,0:59:59.95,1:00:05.02,Default,,0,0,0,,比如Dave取款$100\nDialogue: 0,1:00:06.30,1:00:08.40,Default,,0,0,0,,这些顺序应该很重要才对\nDialogue: 0,1:00:08.40,1:00:10.86,Default,,0,0,0,,你怎么能把它们看作是流呢？\nDialogue: 0,1:00:11.26,1:00:14.26,Default,,0,0,0,,教授：这就是我一直在强调的\nDialogue: 0,1:00:14.26,1:00:15.61,Default,,0,0,0,,在这个例子中确实做不到那一点\nDialogue: 0,1:00:17.51,1:00:18.12,Default,,0,0,0,,做不到\nDialogue: 0,1:00:18.16,1:00:20.08,Default,,0,0,0,,关键在于 这里的输出\nDialogue: 0,1:00:20.24,1:00:21.88,Default,,0,0,0,,并不是这两个输入流\nDialogue: 0,1:00:21.92,1:00:23.60,Default,,0,0,0,,的函数\nDialogue: 0,1:00:24.17,1:00:25.98,Default,,0,0,0,,这个函数跟这个输入流有关\nDialogue: 0,1:00:26.19,1:00:27.26,Default,,0,0,0,,还跟这个输入流有关\nDialogue: 0,1:00:27.36,1:00:29.07,Default,,0,0,0,,还包括某种有关时间的信息\nDialogue: 0,1:00:29.37,1:00:32.36,Default,,0,0,0,,这也正是正则序语言不想让你知道的\nDialogue: 0,1:00:34.81,1:00:37.95,Default,,0,0,0,,学生：为了让这个系统更加函数式\nDialogue: 0,1:00:38.54,1:00:42.04,Default,,0,0,0,,我们能不能把Bill和Dave的交易请求附上时间戳\nDialogue: 0,1:00:42.54,1:00:46.40,Default,,0,0,0,,而使用时间戳作为公平合并的依据？\nDialogue: 0,1:00:48.41,1:00:49.55,Default,,0,0,0,,教授：当然 当然可以\nDialogue: 0,1:00:49.55,1:00:50.60,Default,,0,0,0,,你可以那样做\nDialogue: 0,1:00:50.60,1:00:52.56,Default,,0,0,0,,或者 我们可以这样来想象\nDialogue: 0,1:00:52.76,1:00:54.44,Default,,0,0,0,,我们把这个函数看作是\nDialogue: 0,1:00:54.78,1:00:56.88,Default,,0,0,0,,MERGE每毫秒读一次输入\nDialogue: 0,1:00:58.86,1:00:59.93,Default,,0,0,0,,如果没有读到东西\nDialogue: 0,1:00:59.93,1:01:00.97,Default,,0,0,0,,就认为没有请求\nDialogue: 0,1:01:00.97,1:01:03.39,Default,,0,0,0,,这和你刚刚说的那种方式是等价的\nDialogue: 0,1:01:03.61,1:01:06.08,Default,,0,0,0,,当然可以这样做 但有点旁门左道\nDialogue: 0,1:01:07.11,1:01:10.14,Default,,0,0,0,,我们不只是关心函数的具体实现\nDialogue: 0,1:01:10.76,1:01:12.73,Default,,0,0,0,,我们关心的是语言的表达力\nDialogue: 0,1:01:12.75,1:01:14.67,Default,,0,0,0,,我们遇到的困难是\nDialogue: 0,1:01:14.99,1:01:17.44,Default,,0,0,0,,我们不能很容易地表达我们想要表达的东西\nDialogue: 0,1:01:19.88,1:01:22.01,Default,,0,0,0,,学生：听起来好像如果两个人同时发出请求\nDialogue: 0,1:01:22.06,1:01:26.09,Default,,0,0,0,,这个方法就会出问题\nDialogue: 0,1:01:26.12,1:01:28.43,Default,,0,0,0,,教授：并不只是这个 只要是你定义的都可能出问题\nDialogue: 0,1:01:28.53,1:01:30.57,Default,,0,0,0,,你当然可以说Dave经常发起两个请求\nDialogue: 0,1:01:30.72,1:01:32.32,Default,,0,0,0,,但是你如果预先定义了什么\nDialogue: 0,1:01:32.68,1:01:33.87,Default,,0,0,0,,这样做也不正确\nDialogue: 0,1:01:36.11,1:01:40.70,Default,,0,0,0,,你不能确定某些特定函数的输入请求\nDialogue: 0,1:01:41.93,1:01:43.37,Default,,0,0,0,,但是还有更坏的情况\nDialogue: 0,1:01:44.12,1:01:45.72,Default,,0,0,0,,有一些情况甚至MERGE也处理不了\nDialogue: 0,1:01:47.29,1:01:49.69,Default,,0,0,0,,比如突然有一天你想要\nDialogue: 0,1:01:50.24,1:01:52.47,Default,,0,0,0,,把另一个人关联在这个银行帐户上\nDialogue: 0,1:01:52.47,1:01:54.51,Default,,0,0,0,,假如这个人是John\nDialogue: 0,1:01:56.03,1:01:58.89,Default,,0,0,0,,现在图上就要多一个流\nDialogue: 0,1:01:58.91,1:02:00.70,Default,,0,0,0,,在一个我们未曾指定的时候\nDialogue: 0,1:02:02.04,1:02:04.00,Default,,0,0,0,,这种情况甚至公平合并也无法给出合理的合并\nDialogue: 0,1:02:04.00,1:02:08.25,Default,,0,0,0,,还需要有MANAGER一类的东西\nDialogue: 0,1:02:08.86,1:02:11.79,Default,,0,0,0,,需要一种更一般性的公平合并来解决\nDialogue: 0,1:02:11.79,1:02:13.98,Default,,0,0,0,,有很多研究都在讨论\nDialogue: 0,1:02:14.00,1:02:16.30,Default,,0,0,0,,通过不断引入新机制\nDialogue: 0,1:02:16.59,1:02:18.72,Default,,0,0,0,,函数式思维能应用到哪种程度？\nDialogue: 0,1:02:19.58,1:02:21.79,Default,,0,0,0,,在我们不得不使用赋值之前\nDialogue: 0,1:02:21.82,1:02:23.40,Default,,0,0,0,,函数式程序设计能干成什么样？\nDialogue: 0,1:02:25.98,1:02:28.00,Default,,0,0,0,,学生：看来自动存款就不行\nDialogue: 0,1:02:39.32,1:02:40.49,Default,,0,0,0,,教授：好的 下课\nDialogue: 0,1:02:41.32,1:03:00.08,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:02:41.32,1:03:00.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec6b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nVideo Position: 629\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:20.97,0:00:24.08,EN,,0,0,0,,PROFESSOR: OK, well, we've been looking at streams,\nDialogue: 0,0:00:24.08,0:00:27.82,EN,,0,0,0,,this signal processing way of putting systems together.\nDialogue: 0,0:00:28.87,0:00:31.42,EN,,0,0,0,,And remember, the key idea is that\nDialogue: 0,0:00:31.90,0:00:32.96,EN,,0,0,0,,we decouple\nDialogue: 0,0:00:34.20,0:00:37.31,EN,,0,0,0,,the apparent order of events in our programs\nDialogue: 0,0:00:37.58,0:00:40.17,EN,,0,0,0,,from the actual order of events in the computer.\nDialogue: 0,0:00:41.07,0:00:42.28,EN,,0,0,0,,And that means that we can start\nDialogue: 0,0:00:42.57,0:00:44.14,EN,,0,0,0,,dealing with very long streams\nDialogue: 0,0:00:44.89,0:00:47.39,EN,,0,0,0,,and only having to generate the elements on demand.\nDialogue: 0,0:00:47.53,0:00:49.39,EN,,0,0,0,,That sort of on-demand computation\nDialogue: 0,0:00:49.52,0:00:51.40,EN,,0,0,0,,is built into the stream's data structure.\nDialogue: 0,0:00:54.11,0:00:55.64,EN,,0,0,0,,So if we have a very long stream,\nDialogue: 0,0:00:55.66,0:00:57.08,EN,,0,0,0,,we only compute what we need.\nDialogue: 0,0:00:58.04,0:01:00.75,EN,,0,0,0,,The things only get computed when we actually ask for them.\nDialogue: 0,0:01:00.75,0:01:01.74,EN,,0,0,0,,Well, what are examples?\nDialogue: 0,0:01:02.11,0:01:03.60,EN,,0,0,0,,Are they actually asking for them?\nDialogue: 0,0:01:05.02,0:01:06.01,EN,,0,0,0,,For instance, we might\nDialogue: 0,0:01:09.21,0:01:11.37,EN,,0,0,0,,might ask for the n-th element of a stream.\nDialogue: 0,0:01:15.36,0:01:18.92,EN,,0,0,0,,Here's a procedure that computes the n-th element of a stream.\nDialogue: 0,0:01:20.09,0:01:21.23,EN,,0,0,0,,An integer n,\nDialogue: 0,0:01:21.24,0:01:22.84,EN,,0,0,0,,the n-th element of some stream s,\nDialogue: 0,0:01:23.40,0:01:25.42,EN,,0,0,0,,and we just recursively walk down the stream.\nDialogue: 0,0:01:25.57,0:01:27.39,EN,,0,0,0,,And if n is 0, we compute the head.\nDialogue: 0,0:01:27.96,0:01:30.99,EN,,0,0,0,,Otherwise, it's the n-th the minus 1 element\nDialogue: 0,0:01:31.74,0:01:32.80,EN,,0,0,0,,of the stream.\nDialogue: 0,0:01:34.31,0:01:36.43,EN,,0,0,0,,Those two are just like for Lisp, but the difference\nDialogue: 0,0:01:36.62,0:01:38.76,EN,,0,0,0,,is those elements aren't going to get computed\nDialogue: 0,0:01:38.86,0:01:40.99,EN,,0,0,0,,until we walk down, taking successive n-ths.\nDialogue: 0,0:01:41.52,0:01:44.78,EN,,0,0,0,,So that's one way that the stream elements might get forced.\nDialogue: 0,0:01:45.77,0:01:46.64,EN,,0,0,0,,And another way,\nDialogue: 0,0:01:47.18,0:01:48.92,EN,,0,0,0,,here's a little procedure that prints a stream.\nDialogue: 0,0:01:49.30,0:01:50.38,EN,,0,0,0,,We say print a stream,\nDialogue: 0,0:01:51.90,0:01:53.28,EN,,0,0,0,,so to print a stream s.\nDialogue: 0,0:01:54.15,0:01:55.12,EN,,0,0,0,,Well, what do we do? We'll\nDialogue: 0,0:01:55.74,0:01:56.86,EN,,0,0,0,,We print the head of the stream,\nDialogue: 0,0:01:57.74,0:01:59.32,EN,,0,0,0,,and that will cause the head to be computed.\nDialogue: 0,0:01:59.72,0:02:02.84,EN,,0,0,0,,And then we recursively print stream the tail of the stream.\nDialogue: 0,0:02:04.99,0:02:06.03,EN,,0,0,0,,And if we're already done,\nDialogue: 0,0:02:06.04,0:02:08.57,EN,,0,0,0,,maybe we have to return something about the message done.\nDialogue: 0,0:02:09.66,0:02:11.39,EN,,0,0,0,,OK, and then so if you make a stream,\nDialogue: 0,0:02:11.64,0:02:13.64,EN,,0,0,0,,you could say here's the stream, this very long stream.\nDialogue: 0,0:02:14.31,0:02:16.33,EN,,0,0,0,,And then you say print the stream,\nDialogue: 0,0:02:16.41,0:02:19.77,EN,,0,0,0,,and the elements of the stream will get computed successively\nDialogue: 0,0:02:19.87,0:02:21.12,EN,,0,0,0,,as that print calls them.\nDialogue: 0,0:02:21.32,0:02:22.81,EN,,0,0,0,,They won't get all computed initially.\nDialogue: 0,0:02:24.30,0:02:25.66,EN,,0,0,0,,So in this way, we can\nDialogue: 0,0:02:27.50,0:02:29.61,EN,,0,0,0,,So in this way, we can deal with some very long streams.\nDialogue: 0,0:02:30.19,0:02:31.92,EN,,0,0,0,,Well, how long can a stream be?\nDialogue: 0,0:02:33.74,0:02:35.12,EN,,0,0,0,,Well, it can be infinitely long.\nDialogue: 0,0:02:35.90,0:02:38.04,EN,,0,0,0,,Let's look at an example here on the computer.\nDialogue: 0,0:02:38.92,0:02:41.96,EN,,0,0,0,,I could walk up to this computer, and I could say--\nDialogue: 0,0:02:43.48,0:02:53.31,EN,,0,0,0,,how about we'll define the stream of integers starting with some number N,\nDialogue: 0,0:02:54.24,0:02:57.13,EN,,0,0,0,,the stream of positive integers starting with some number n.\nDialogue: 0,0:03:00.36,0:03:19.16,EN,,0,0,0,,And that's cons-stream of n onto the integers from one more.\nDialogue: 0,0:03:24.41,0:03:25.61,EN,,0,0,0,,So there are the integers.\nDialogue: 0,0:03:28.99,0:03:31.50,EN,,0,0,0,,Then I could say let's get all the integers.\nDialogue: 0,0:03:34.57,0:03:44.33,EN,,0,0,0,,define the stream of integers to be the integers starting with 1.\nDialogue: 0,0:03:48.84,0:03:50.94,EN,,0,0,0,,And now if I say something like\nDialogue: 0,0:03:54.41,0:03:55.80,EN,,0,0,0,,what's the what's the 20th integer.\nDialogue: 0,0:04:03.42,0:04:05.53,EN,,0,0,0,,So it's 21 because we start counting at 0.\nDialogue: 0,0:04:06.84,0:04:08.88,EN,,0,0,0,,Or I can do more complicated things.\nDialogue: 0,0:04:09.45,0:04:10.84,EN,,0,0,0,,Let me to define a little predicate here.\nDialogue: 0,0:04:11.77,0:04:18.51,EN,,0,0,0,,How about define no-seven.\nDialogue: 0,0:04:19.58,0:04:20.75,EN,,0,0,0,,It's going to test an integer,\nDialogue: 0,0:04:21.79,0:04:23.16,EN,,0,0,0,,and it's going to say it's not.\nDialogue: 0,0:04:28.82,0:04:33.96,EN,,0,0,0,,I take the remainder of x by 7,\nDialogue: 0,0:04:36.62,0:04:38.35,EN,,0,0,0,,I don't get 0.\nDialogue: 0,0:04:43.80,0:04:49.77,EN,,0,0,0,,And then I could say define the integers with no sevens\nDialogue: 0,0:04:50.22,0:04:59.12,EN,,0,0,0,,take all the integers and filter them to have no sevens.\nDialogue: 0,0:05:11.57,0:05:13.34,EN,,0,0,0,,So now I've got the stream of all the integers\nDialogue: 0,0:05:13.63,0:05:15.05,EN,,0,0,0,,that are not divisible by seven.\nDialogue: 0,0:05:16.49,0:05:23.44,EN,,0,0,0,,So if I say what's the 100th integer\nDialogue: 0,0:05:24.70,0:05:26.48,EN,,0,0,0,,and the list not divisible by seven,\nDialogue: 0,0:05:26.86,0:05:28.11,EN,,0,0,0,,I get 117.\nDialogue: 0,0:05:28.32,0:05:30.67,EN,,0,0,0,,Or if I'd like to say well, I could say ah.\nDialogue: 0,0:05:32.30,0:05:34.38,EN,,0,0,0,,well, gee, what are all of them?\nDialogue: 0,0:05:35.27,0:05:40.35,EN,,0,0,0,,So I could say print stream all these integers with no seven,\nDialogue: 0,0:05:40.83,0:05:41.79,EN,,0,0,0,,it goes off printing.\nDialogue: 0,0:05:45.10,0:05:47.07,EN,,0,0,0,,You may have to wait a very long time to see them all.\nDialogue: 0,0:05:52.67,0:05:53.84,EN,,0,0,0,,Well, you can start asking, gee,\nDialogue: 0,0:05:54.81,0:05:57.00,EN,,0,0,0,,you know, is it really true that this data structure\nDialogue: 0,0:05:58.28,0:06:00.65,EN,,0,0,0,,with the integers is really all the integers?\nDialogue: 0,0:06:01.10,0:06:04.05,EN,,0,0,0,,And let me draw a picture of that program I just wrote.\nDialogue: 0,0:06:04.96,0:06:10.57,EN,,0,0,0,,Here's the, right, here's the definition of the integers again that I just typed in,\nDialogue: 0,0:06:12.33,0:06:15.98,EN,,0,0,0,,Right it's a cons of the first integer under the integer starting with the rest.\nDialogue: 0,0:06:17.61,0:06:19.77,EN,,0,0,0,,Now, we can make a picture of that and see what it looks like.\nDialogue: 0,0:06:22.72,0:06:24.32,EN,,0,0,0,,Conceptually, what I have is a box\nDialogue: 0,0:06:25.53,0:06:27.18,EN,,0,0,0,,that's the integer starting with n.\nDialogue: 0,0:06:27.42,0:06:29.08,EN,,0,0,0,,It takes in some number n,\nDialogue: 0,0:06:31.42,0:06:32.97,EN,,0,0,0,,and it's going to return a stream of--\nDialogue: 0,0:06:35.02,0:06:37.36,EN,,0,0,0,,this infinite stream of all integers starting with n.\nDialogue: 0,0:06:38.08,0:06:38.73,EN,,0,0,0,,And what do I do?\nDialogue: 0,0:06:38.75,0:06:42.38,EN,,0,0,0,,Well, this is an integers-from box.\nDialogue: 0,0:06:45.07,0:06:45.80,EN,,0,0,0,,What's it got in it?\nDialogue: 0,0:06:45.80,0:06:48.60,EN,,0,0,0,,Well, it takes in this n,\nDialogue: 0,0:06:52.27,0:06:53.92,EN,,0,0,0,,and it increments it.\nDialogue: 0,0:06:57.95,0:07:03.15,EN,,0,0,0,,And then it puts the result into recursively another integer's from box.\nDialogue: 0,0:07:06.87,0:07:09.60,EN,,0,0,0,,It takes the result of that and the original n\nDialogue: 0,0:07:10.24,0:07:12.78,EN,,0,0,0,,and puts those together with a cons\nDialogue: 0,0:07:13.39,0:07:14.36,EN,,0,0,0,,and forms a stream.\nDialogue: 0,0:07:14.57,0:07:17.26,EN,,0,0,0,,So that's a picture of that program I wrote. And this is a ...\nDialogue: 0,0:07:18.52,0:07:20.32,EN,,0,0,0,,Let's see. These kind of diagrams we first saw\nDialogue: 0,0:07:20.78,0:07:21.74,EN,,0,0,0,,drawn by Peter Henderson,\nDialogue: 0,0:07:21.76,0:07:23.32,EN,,0,0,0,,the same guy who did the Escher language.\nDialogue: 0,0:07:23.32,0:07:24.75,EN,,0,0,0,,We call them Henderson diagrams.\nDialogue: 0,0:07:25.37,0:07:27.90,EN,,0,0,0,,And the convention here is that you put these things together.\nDialogue: 0,0:07:28.53,0:07:32.51,EN,,0,0,0,,And the solid lines are things coming out are streams,\nDialogue: 0,0:07:33.02,0:07:36.20,EN,,0,0,0,,and dotted lines are initial values going in.\nDialogue: 0,0:07:37.27,0:07:39.02,EN,,0,0,0,,So this one has the shape of--\nDialogue: 0,0:07:39.40,0:07:41.60,EN,,0,0,0,,it takes in some integer, some initial value,\nDialogue: 0,0:07:41.80,0:07:42.91,EN,,0,0,0,,and outputs a stream.\nDialogue: 0,0:07:46.35,0:07:48.22,EN,,0,0,0,,Again, you can ask. You know it's really\nDialogue: 0,0:07:48.38,0:07:50.88,EN,,0,0,0,,Is that data structure integers really all the integers?\nDialogue: 0,0:07:52.09,0:07:54.91,EN,,0,0,0,,Alright? Or is it is something that's cleverly arranged\nDialogue: 0,0:07:54.94,0:07:56.43,EN,,0,0,0,,so that whenever you look for an integer\nDialogue: 0,0:07:56.44,0:07:57.24,EN,,0,0,0,,you find it there?\nDialogue: 0,0:07:57.95,0:07:59.74,EN,,0,0,0,,That's sort of a philosophical question, right?\nDialogue: 0,0:07:59.78,0:08:01.69,EN,,0,0,0,,If something is there\nDialogue: 0,0:08:02.14,0:08:03.96,EN,,0,0,0,,whenever you look, is it really there or not?\nDialogue: 0,0:08:04.45,0:08:07.34,EN,,0,0,0,,It's sort of the same sense in which\nDialogue: 0,0:08:07.36,0:08:09.42,EN,,0,0,0,,the money in your savings account is in the bank.\nDialogue: 0,0:08:12.38,0:08:12.64,EN,,0,0,0,,Well\nDialogue: 0,0:08:16.35,0:08:17.48,EN,,0,0,0,,let me do another example.\nDialogue: 0,0:08:18.68,0:08:20.70,EN,,0,0,0,,Umm, Gee, we started the course\nDialogue: 0,0:08:20.72,0:08:22.72,EN,,0,0,0,,with an algorithm from Alexandria,\nDialogue: 0,0:08:23.29,0:08:25.80,EN,,0,0,0,,which was Heron of Alexandria's algorithm\nDialogue: 0,0:08:25.82,0:08:26.94,EN,,0,0,0,,for computing the square root.\nDialogue: 0,0:08:28.47,0:08:32.03,EN,,0,0,0,,Let's take a look at another Alexandrian algorithm.\nDialogue: 0,0:08:32.03,0:08:35.08,EN,,0,0,0,,This one is Eratosthenes method for\nDialogue: 0,0:08:36.19,0:08:38.44,EN,,0,0,0,,for computing all of the primes.\nDialogue: 0,0:08:41.16,0:08:42.83,EN,,0,0,0,,It is called the Sieve of Eratosthenes.\nDialogue: 0,0:08:42.83,0:08:49.72,EN,,0,0,0,,And what you do is you start out,\nDialogue: 0,0:08:50.99,0:08:52.28,EN,,0,0,0,,and you list all the integers,\nDialogue: 0,0:08:52.60,0:08:53.53,EN,,0,0,0,,say, starting with 2.\nDialogue: 0,0:08:53.88,0:08:55.04,EN,,0,0,0,,And then you take the first integer, and you say,\nDialogue: 0,0:08:55.08,0:08:56.67,EN,,0,0,0,,and you say, oh, that's prime.\nDialogue: 0,0:08:57.31,0:08:58.35,EN,,0,0,0,,And then you go look at the rest,\nDialogue: 0,0:08:58.68,0:09:00.88,EN,,0,0,0,,and you cross out all the things divisible by 2.\nDialogue: 0,0:09:01.52,0:09:04.73,EN,,0,0,0,,So I cross out this and this and this.\nDialogue: 0,0:09:05.25,0:09:06.35,EN,,0,0,0,,This takes a long time\nDialogue: 0,0:09:06.36,0:09:08.91,EN,,0,0,0,,because I have to do it for all of the integers.\nDialogue: 0,0:09:11.16,0:09:15.39,EN,,0,0,0,,So I go through the entire list of integers,\nDialogue: 0,0:09:18.27,0:09:20.94,EN,,0,0,0,,crossing the ones divisible by 2.\nDialogue: 0,0:09:22.11,0:09:24.38,EN,,0,0,0,,And now when I finish with all of the integers,\nDialogue: 0,0:09:24.78,0:09:26.72,EN,,0,0,0,,I go back and look and say what am I left with?\nDialogue: 0,0:09:27.04,0:09:28.80,EN,,0,0,0,,Well, the first thing that starts there is 3.\nDialogue: 0,0:09:29.33,0:09:30.33,EN,,0,0,0,,So 3 is a prime.\nDialogue: 0,0:09:30.77,0:09:33.05,EN,,0,0,0,,And now I go back through what I'm left with,\nDialogue: 0,0:09:33.36,0:09:35.07,EN,,0,0,0,,and I cross out all the things divisible by 3.\nDialogue: 0,0:09:35.08,0:09:43.80,EN,,0,0,0,,So let's see, 9 and 15 and 21 and 27 and 33 and so on.\nDialogue: 0,0:09:44.33,0:09:45.12,EN,,0,0,0,,I won't finish.\nDialogue: 0,0:09:45.35,0:09:46.52,EN,,0,0,0,,Then I see what I'm left with.\nDialogue: 0,0:09:47.25,0:09:49.84,EN,,0,0,0,,And the next one I have is 5.\nDialogue: 0,0:09:50.49,0:09:52.04,EN,,0,0,0,,Now I can through the rest,\nDialogue: 0,0:09:52.43,0:09:54.51,EN,,0,0,0,,and I find the first one that's divisible by 5.\nDialogue: 0,0:09:54.54,0:09:57.61,EN,,0,0,0,,I cross out from the remainder all the ones that are divisible by 5.\nDialogue: 0,0:09:58.35,0:09:59.24,EN,,0,0,0,,And I did that,\nDialogue: 0,0:09:59.82,0:10:01.89,EN,,0,0,0,,and then I go through and find 7.\nDialogue: 0,0:10:01.89,0:10:02.72,EN,,0,0,0,,Go through all the rest,\nDialogue: 0,0:10:02.76,0:10:03.95,EN,,0,0,0,,cross out things divisible 7,\nDialogue: 0,0:10:03.98,0:10:05.47,EN,,0,0,0,,and I keep doing that forever.\nDialogue: 0,0:10:06.81,0:10:07.40,EN,,0,0,0,,And when I'm done,\nDialogue: 0,0:10:07.40,0:10:09.10,EN,,0,0,0,,what I'm left with is a list of all the primes.\nDialogue: 0,0:10:09.90,0:10:13.31,EN,,0,0,0,,So that's the Sieve of Eratosthenes.\nDialogue: 0,0:10:15.43,0:10:17.69,EN,,0,0,0,,Let's look at it as a computer program.\nDialogue: 0,0:10:17.93,0:10:19.85,EN,,0,0,0,,It's a procedure called sieve.\nDialogue: 0,0:10:27.91,0:10:29.40,EN,,0,0,0,,Now, I just write what I did.\nDialogue: 0,0:10:30.33,0:10:34.48,EN,,0,0,0,,I'll say to sieve some stream s.\nDialogue: 0,0:10:38.77,0:10:39.93,EN,,0,0,0,,I'm going to build a stream\nDialogue: 0,0:10:40.27,0:10:41.84,EN,,0,0,0,,whose first element is the head of this.\nDialogue: 0,0:10:41.87,0:10:44.43,EN,,0,0,0,,Remember, I always found the first thing I was left with,\nDialogue: 0,0:10:44.91,0:10:48.75,EN,,0,0,0,,and the rest of it is the result of taking the tail of S,\nDialogue: 0,0:10:51.08,0:10:53.72,EN,,0,0,0,,filtering it to throw away all the things\nDialogue: 0,0:10:53.74,0:10:55.32,EN,,0,0,0,,that are divisible by the head of S,\nDialogue: 0,0:10:56.41,0:10:57.56,EN,,0,0,0,,and now sieving the result.\nDialogue: 0,0:10:59.02,0:11:00.09,EN,,0,0,0,,That's just what I did.\nDialogue: 0,0:11:01.98,0:11:04.68,EN,,0,0,0,,And now to get the infinite stream of times,\nDialogue: 0,0:11:05.02,0:11:06.90,EN,,0,0,0,,we just sieve all the integers starting from 2.\nDialogue: 0,0:11:14.92,0:11:15.56,EN,,0,0,0,,Let's try that.\nDialogue: 0,0:11:16.30,0:11:18.30,EN,,0,0,0,,We can actually do it.\nDialogue: 0,0:11:19.76,0:11:22.12,EN,,0,0,0,,I typed in the definition of sieve before, I hope,\nDialogue: 0,0:11:22.86,0:11:24.06,EN,,0,0,0,,so I can say something like\nDialogue: 0,0:11:24.92,0:11:33.45,EN,,0,0,0,,define the primes to be\nDialogue: 0,0:11:34.64,0:11:41.45,EN,,0,0,0,,the result of sieving the integers starting with 2.\nDialogue: 0,0:11:46.76,0:11:48.10,EN,,0,0,0,,So now I've got this list of primes.\nDialogue: 0,0:11:48.10,0:11:50.99,EN,,0,0,0,,That's all of the primes, right?\nDialogue: 0,0:11:50.99,0:11:53.52,EN,,0,0,0,,So, if for example, what's the 20th prime in that list?\nDialogue: 0,0:12:00.73,0:12:01.68,EN,,0,0,0,,73.\nDialogue: 0,0:12:02.54,0:12:03.34,EN,,0,0,0,,See, and that little pause,\nDialogue: 0,0:12:03.36,0:12:04.92,EN,,0,0,0,,it was only at the point\nDialogue: 0,0:12:04.94,0:12:06.43,EN,,0,0,0,,when I started asking for the 20th prime\nDialogue: 0,0:12:06.46,0:12:07.68,EN,,0,0,0,,is that it started computing.\nDialogue: 0,0:12:10.37,0:12:11.29,EN,,0,0,0,,Or I can say here\nDialogue: 0,0:12:13.80,0:12:14.88,EN,,0,0,0,,Or I can say here let's look at all of the primes.\nDialogue: 0,0:12:22.64,0:12:24.40,EN,,0,0,0,,And there it goes computing all of the primes.\nDialogue: 0,0:12:25.35,0:12:26.28,EN,,0,0,0,,Of course, it will take a while\nDialogue: 0,0:12:26.28,0:12:27.61,EN,,0,0,0,,again if I want to look at all of them,\nDialogue: 0,0:12:27.79,0:12:28.57,EN,,0,0,0,,so let's stop it.\nDialogue: 0,0:12:32.03,0:12:33.13,EN,,0,0,0,,Let me draw you a picture of that.\nDialogue: 0,0:12:33.13,0:12:34.17,EN,,0,0,0,,Well, I've got a picture of that.\nDialogue: 0,0:12:34.89,0:12:36.19,EN,,0,0,0,,What's that program really look like?\nDialogue: 0,0:12:37.90,0:12:39.77,EN,,0,0,0,,Again, some practice with these diagrams,\nDialogue: 0,0:12:39.82,0:12:40.54,EN,,0,0,0,,I have a sieve box.\nDialogue: 0,0:12:42.61,0:12:43.56,EN,,0,0,0,,How does sieve work?\nDialogue: 0,0:12:43.56,0:12:44.81,EN,,0,0,0,,It takes in a stream.\nDialogue: 0,0:12:48.85,0:12:50.59,EN,,0,0,0,,It splits off the head from the tail.\nDialogue: 0,0:12:50.87,0:12:53.26,EN,,0,0,0,,And the first thing that's going to come out of the sieve\nDialogue: 0,0:12:53.48,0:12:54.97,EN,,0,0,0,,is the head of the original stream.\nDialogue: 0,0:12:58.20,0:13:00.92,EN,,0,0,0,,Then it also takes the head and uses that.\nDialogue: 0,0:13:02.55,0:13:05.10,EN,,0,0,0,,It takes the stream. It filters the tail\nDialogue: 0,0:13:05.55,0:13:08.33,EN,,0,0,0,,It filters the tail and uses the head to filter for nondivisibility.\nDialogue: 0,0:13:09.53,0:13:11.18,EN,,0,0,0,,It takes the result of nondivisibility\nDialogue: 0,0:13:11.24,0:13:13.12,EN,,0,0,0,,and puts it through another sieve box\nDialogue: 0,0:13:13.90,0:13:15.13,EN,,0,0,0,,and puts the result together.\nDialogue: 0,0:13:15.13,0:13:16.89,EN,,0,0,0,,So you can think of this sieve a filter,\nDialogue: 0,0:13:17.20,0:13:19.23,EN,,0,0,0,,but notice that it's an infinitely recursive filter.\nDialogue: 0,0:13:19.65,0:13:20.88,EN,,0,0,0,,Because inside the sieve box\nDialogue: 0,0:13:21.52,0:13:22.60,EN,,0,0,0,,is another sieve box,\nDialogue: 0,0:13:23.37,0:13:25.85,EN,,0,0,0,,and inside that is another sieve box and another sieve box.\nDialogue: 0,0:13:27.13,0:13:28.96,EN,,0,0,0,,So you see we start getting some very powerful things.\nDialogue: 0,0:13:28.96,0:13:32.84,EN,,0,0,0,,We're starting to mix this signal processing view of the world\nDialogue: 0,0:13:33.90,0:13:36.41,EN,,0,0,0,,with things like recursion that come from computation.\nDialogue: 0,0:13:37.42,0:13:39.82,EN,,0,0,0,,And there are all sorts of interesting things you can do that are like this.\nDialogue: 0,0:13:40.97,0:13:42.09,EN,,0,0,0,,All right, any questions?\nDialogue: 0,0:13:48.19,0:13:49.16,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:14:28.65,0:14:30.36,EN,,0,0,0,,Well, we've been looking at a couple\nDialogue: 0,0:14:30.36,0:14:32.09,EN,,0,0,0,,of examples of stream programming.\nDialogue: 0,0:14:34.79,0:14:39.21,EN,,0,0,0,,All the stream procedures that we've looked at so far\nDialogue: 0,0:14:39.72,0:14:41.32,EN,,0,0,0,,have the same kind of character.\nDialogue: 0,0:14:41.49,0:14:43.63,EN,,0,0,0,,We've been writing these recursive procedures\nDialogue: 0,0:14:44.16,0:14:46.49,EN,,0,0,0,,that kind of generate these stream elements one at a time\nDialogue: 0,0:14:46.51,0:14:48.72,EN,,0,0,0,,and put them together in cons-streams.\nDialogue: 0,0:14:49.15,0:14:50.86,EN,,0,0,0,,So we've been thinking a lot about generators.\nDialogue: 0,0:14:50.92,0:14:53.63,EN,,0,0,0,,There's another way to think about stream processing,\nDialogue: 0,0:14:53.79,0:14:56.96,EN,,0,0,0,,and that's to focus not on programs that sort of\nDialogue: 0,0:14:57.36,0:14:59.93,EN,,0,0,0,,process these elements as you walk down the stream,\nDialogue: 0,0:15:00.25,0:15:05.68,EN,,0,0,0,,but on things that kind of process the streams all at once.\nDialogue: 0,0:15:07.18,0:15:09.16,EN,,0,0,0,,To show you what I mean, let me start by defining\nDialogue: 0,0:15:09.23,0:15:11.50,EN,,0,0,0,,two procedures that will come in handy.\nDialogue: 0,0:15:12.41,0:15:13.60,EN,,0,0,0,,The first one's called add streams.\nDialogue: 0,0:15:15.36,0:15:18.25,EN,,0,0,0,,Add streams takes two streams:\nDialogue: 0,0:15:18.81,0:15:20.88,EN,,0,0,0,,s1 and s2.\nDialogue: 0,0:15:22.30,0:15:24.67,EN,,0,0,0,,And it's going to produce a stream\nDialogue: 0,0:15:24.99,0:15:28.17,EN,,0,0,0,,whose elements are the are the corresponding sums\nDialogue: 0,0:15:30.22,0:15:31.88,EN,,0,0,0,,We just sort of add them element-wise.\nDialogue: 0,0:15:32.97,0:15:33.95,EN,,0,0,0,,If either stream is empty,\nDialogue: 0,0:15:33.96,0:15:35.39,EN,,0,0,0,,we just return the other one.\nDialogue: 0,0:15:36.81,0:15:38.96,EN,,0,0,0,,Otherwise, we're going to make a new stream\nDialogue: 0,0:15:39.90,0:15:42.96,EN,,0,0,0,,whose head is the sum of the two heads\nDialogue: 0,0:15:44.00,0:15:44.88,EN,,0,0,0,,whose tail\nDialogue: 0,0:15:46.00,0:15:48.62,EN,,0,0,0,,is the result of recursively adding the tails.\nDialogue: 0,0:15:50.09,0:15:52.73,EN,,0,0,0,,So that will produce the element-wise sum of two streams.\nDialogue: 0,0:15:53.15,0:15:57.04,EN,,0,0,0,,And then another useful thing to have around is scale stream.\nDialogue: 0,0:15:57.50,0:16:01.66,EN,,0,0,0,,Scale stream takes some constant number in a stream s\nDialogue: 0,0:16:04.11,0:16:06.62,EN,,0,0,0,,and is going to produce the stream\nDialogue: 0,0:16:07.18,0:16:09.50,EN,,0,0,0,,of elements of s multiplied by this constant.\nDialogue: 0,0:16:09.71,0:16:11.21,EN,,0,0,0,,And that's easy, that's just a map\nDialogue: 0,0:16:12.20,0:16:16.22,EN,,0,0,0,,of the function of an element that multiplies it by the constant,\nDialogue: 0,0:16:16.35,0:16:17.80,EN,,0,0,0,,and we map that down the stream.\nDialogue: 0,0:16:20.06,0:16:21.47,EN,,0,0,0,,So given those two,\nDialogue: 0,0:16:22.64,0:16:24.36,EN,,0,0,0,,let me show you what I mean by programs that\nDialogue: 0,0:16:24.70,0:16:27.00,EN,,0,0,0,,that operate on streams all at once.\nDialogue: 0,0:16:28.12,0:16:28.73,EN,,0,0,0,,Let's look at this.\nDialogue: 0,0:16:30.20,0:16:30.92,EN,,0,0,0,,Suppose I write this.\nDialogue: 0,0:16:31.68,0:16:52.35,EN,,0,0,0,,I say define--  I'll call it ones-- to be cons-stream of 1 onto ones.\nDialogue: 0,0:16:54.86,0:16:55.52,EN,,0,0,0,,What's that?\nDialogue: 0,0:16:56.95,0:16:58.94,EN,,0,0,0,,That's going to be an infinite stream of ones\nDialogue: 0,0:16:59.96,0:17:01.44,EN,,0,0,0,,because the first thing is 1.\nDialogue: 0,0:17:03.33,0:17:05.15,EN,,0,0,0,,And the tail of it is a thing\nDialogue: 0,0:17:05.55,0:17:06.83,EN,,0,0,0,,whose first thing is 1\nDialogue: 0,0:17:07.63,0:17:09.02,EN,,0,0,0,,whose tail is a thing\nDialogue: 0,0:17:09.12,0:17:10.24,EN,,0,0,0,,whose first thing is 1\nDialogue: 0,0:17:10.52,0:17:11.78,EN,,0,0,0,,and so on and so on.\nDialogue: 0,0:17:11.78,0:17:13.32,EN,,0,0,0,,So that's an infinite stream of ones.\nDialogue: 0,0:17:15.13,0:17:15.93,EN,,0,0,0,,And now using that,\nDialogue: 0,0:17:16.12,0:17:18.03,EN,,0,0,0,,let me give you another definition of the integers.\nDialogue: 0,0:17:19.47,0:17:27.36,EN,,0,0,0,,We can define the integers to be--\nDialogue: 0,0:17:28.24,0:17:30.76,EN,,0,0,0,,well, the first integer we'll take to be 1,\nDialogue: 0,0:17:32.75,0:17:38.57,EN,,0,0,0,,his cons-stream of 1 onto the element-wise sum\nDialogue: 0,0:17:40.22,0:17:48.27,EN,,0,0,0,,onto add streams of the integers to ones.\nDialogue: 0,0:17:55.10,0:17:56.35,EN,,0,0,0,,The integers are a thing\nDialogue: 0,0:17:57.24,0:17:59.98,EN,,0,0,0,,whose first element is 1,\nDialogue: 0,0:18:00.88,0:18:02.32,EN,,0,0,0,,and the rest of them you get\nDialogue: 0,0:18:03.12,0:18:06.14,EN,,0,0,0,,by taking those integers and incrementing each one by one.\nDialogue: 0,0:18:06.64,0:18:08.19,EN,,0,0,0,,So the second element of the integers\nDialogue: 0,0:18:08.51,0:18:11.96,EN,,0,0,0,,is the first element of the integers incremented by one.\nDialogue: 0,0:18:13.92,0:18:15.18,EN,,0,0,0,,And the rest of that is the next one,\nDialogue: 0,0:18:15.20,0:18:16.48,EN,,0,0,0,,and the third element of that\nDialogue: 0,0:18:16.62,0:18:20.41,EN,,0,0,0,,is the same as the first element of the tail of the integers\nDialogue: 0,0:18:20.84,0:18:21.96,EN,,0,0,0,,incremented by one,\nDialogue: 0,0:18:22.51,0:18:23.76,EN,,0,0,0,,which is the same as the\nDialogue: 0,0:18:25.08,0:18:28.65,EN,,0,0,0,,first element of the original integers incremented by one\nDialogue: 0,0:18:28.86,0:18:31.25,EN,,0,0,0,,and incremented by one again and so on.\nDialogue: 0,0:18:35.24,0:18:36.31,EN,,0,0,0,,That looks pretty suspicious.\nDialogue: 0,0:18:36.31,0:18:37.47,EN,,0,0,0,,See, notice that it works\nDialogue: 0,0:18:38.12,0:18:38.99,EN,,0,0,0,,because of delay.\nDialogue: 0,0:18:40.15,0:18:43.32,EN,,0,0,0,,See, this looks like-- let's take a look at ones.\nDialogue: 0,0:18:43.87,0:18:45.92,EN,,0,0,0,,This looks like it couldn't even be processed\nDialogue: 0,0:18:46.25,0:18:47.63,EN,,0,0,0,,because it's suddenly saying\nDialogue: 0,0:18:47.79,0:18:48.96,EN,,0,0,0,,in order to know what ones is,\nDialogue: 0,0:18:49.00,0:18:50.91,EN,,0,0,0,,I say it's cons-stream of something onto ones.\nDialogue: 0,0:18:51.13,0:18:52.08,EN,,0,0,0,,The reason that works\nDialogue: 0,0:18:52.09,0:18:54.04,EN,,0,0,0,,because of that very sneaky hidden delay in there.\nDialogue: 0,0:18:55.25,0:18:56.56,EN,,0,0,0,,Because what this really is,\nDialogue: 0,0:18:57.79,0:18:59.69,EN,,0,0,0,,remember, cons-stream is just an abbreviation.\nDialogue: 0,0:19:00.29,0:19:01.15,EN,,0,0,0,,This really is\nDialogue: 0,0:19:01.85,0:19:08.99,EN,,0,0,0,,cons of 1 onto delay of ones.\nDialogue: 0,0:19:12.14,0:19:13.21,EN,,0,0,0,,So how does that work?\nDialogue: 0,0:19:15.50,0:19:16.88,EN,,0,0,0,,You say I'm going to define ones.\nDialogue: 0,0:19:18.02,0:19:20.24,EN,,0,0,0,,First I see what ones is supposed to be defined as.\nDialogue: 0,0:19:20.70,0:19:23.40,EN,,0,0,0,,Well, ones is supposed to be defined as\nDialogue: 0,0:19:24.89,0:19:28.11,EN,,0,0,0,,a cons whose first part is 1\nDialogue: 0,0:19:28.32,0:19:29.45,EN,,0,0,0,,and the second part is,\nDialogue: 0,0:19:29.45,0:19:30.73,EN,,0,0,0,,well, it's a promise to compute something\nDialogue: 0,0:19:30.75,0:19:31.69,EN,,0,0,0,,that I don't worry about yet.\nDialogue: 0,0:19:32.71,0:19:34.25,EN,,0,0,0,,So it doesn't bother me that at the point\nDialogue: 0,0:19:34.28,0:19:36.30,EN,,0,0,0,,I do this definition, ones isn't defined.\nDialogue: 0,0:19:37.27,0:19:39.45,EN,,0,0,0,,Having run the definition, now ones is defined.\nDialogue: 0,0:19:40.67,0:19:42.83,EN,,0,0,0,,So that when I go and look at the tail of it, it's defined.\nDialogue: 0,0:19:44.92,0:19:46.06,EN,,0,0,0,,It's very sneaky.\nDialogue: 0,0:19:46.59,0:19:47.90,EN,,0,0,0,,And an integer is the same way.\nDialogue: 0,0:19:48.47,0:19:50.46,EN,,0,0,0,,I can refer to integers here because\nDialogue: 0,0:19:51.13,0:19:53.21,EN,,0,0,0,,hidden way down-- because of this cons-stream.\nDialogue: 0,0:19:53.85,0:19:55.24,EN,,0,0,0,,It's the cons-stream of 1\nDialogue: 0,0:19:55.37,0:19:57.05,EN,,0,0,0,,onto something that I don't worry that yet.\nDialogue: 0,0:19:57.05,0:19:59.60,EN,,0,0,0,,So I don't look at it, and I don't notice that integers isn't defined\nDialogue: 0,0:20:00.22,0:20:01.90,EN,,0,0,0,,at the point where I try and run the definition.\nDialogue: 0,0:20:06.32,0:20:08.27,EN,,0,0,0,,OK, let me draw a picture of that integers thing\nDialogue: 0,0:20:08.44,0:20:11.50,EN,,0,0,0,,because it still maybe seems a little bit shaky.\nDialogue: 0,0:20:12.43,0:20:14.72,EN,,0,0,0,,What do I do? Uh...\nDialogue: 0,0:20:15.02,0:20:16.30,EN,,0,0,0,,I've got the stream of ones,\nDialogue: 0,0:20:20.51,0:20:21.88,EN,,0,0,0,,and that sort of comes in\nDialogue: 0,0:20:23.26,0:20:24.92,EN,,0,0,0,,comes in and goes into an adder\nDialogue: 0,0:20:24.96,0:20:26.59,EN,,0,0,0,,that's going to be this add streams thing.\nDialogue: 0,0:20:29.31,0:20:35.87,EN,,0,0,0,,And that goes in-- that's going to put out the integers.\nDialogue: 0,0:20:40.76,0:20:42.70,EN,,0,0,0,,And the other thing that goes into the adder here\nDialogue: 0,0:20:44.94,0:20:46.97,EN,,0,0,0,,is the integer, so there's a little feedback loop.\nDialogue: 0,0:20:48.06,0:20:49.42,EN,,0,0,0,,And all I need to start it off\nDialogue: 0,0:20:50.09,0:20:52.88,EN,,0,0,0,,is someplace I've got a stick that initial 1.\nDialogue: 0,0:20:57.10,0:20:58.64,EN,,0,0,0,,In a real signal processing thing,\nDialogue: 0,0:20:58.72,0:21:02.48,EN,,0,0,0,,this might be a delay element with that was initialized to 1.\nDialogue: 0,0:21:02.91,0:21:05.90,EN,,0,0,0,,But there's a picture of that ones program.\nDialogue: 0,0:21:07.86,0:21:09.63,EN,,0,0,0,,And in fact, that looks a lot like--\nDialogue: 0,0:21:09.80,0:21:13.77,EN,,0,0,0,,if you've seen real signal block diagram things,\nDialogue: 0,0:21:13.77,0:21:16.30,EN,,0,0,0,,that looks a lot like accumulators,\nDialogue: 0,0:21:16.35,0:21:17.48,EN,,0,0,0,,finite state accumulators.\nDialogue: 0,0:21:17.98,0:21:20.06,EN,,0,0,0,,And in fact, we can modify this a little bit\nDialogue: 0,0:21:21.18,0:21:23.96,EN,,0,0,0,,to change this into something that integrates a stream\nDialogue: 0,0:21:25.37,0:21:26.97,EN,,0,0,0,,or a finite state accumulator,\nDialogue: 0,0:21:27.00,0:21:28.04,EN,,0,0,0,,however you like to think about it.\nDialogue: 0,0:21:28.44,0:21:30.86,EN,,0,0,0,,So instead of the ones coming in and getting out the integers,\nDialogue: 0,0:21:31.68,0:21:32.38,EN,,0,0,0,,what we'll do is\nDialogue: 0,0:21:32.91,0:21:34.83,EN,,0,0,0,,say there's a stream s coming in,\nDialogue: 0,0:21:35.76,0:21:40.56,EN,,0,0,0,,and we're going to get out the integral of this.\nDialogue: 0,0:21:42.60,0:21:44.09,EN,,0,0,0,,successive values of that,\nDialogue: 0,0:21:44.44,0:21:45.63,EN,,0,0,0,,and it looks almost the same.\nDialogue: 0,0:21:45.66,0:21:46.84,EN,,0,0,0,,The only thing we're going to do is\nDialogue: 0,0:21:47.02,0:21:48.08,EN,,0,0,0,,when s comes in here,\nDialogue: 0,0:21:49.21,0:21:50.64,EN,,0,0,0,,before we just add it in\nDialogue: 0,0:21:50.91,0:21:54.26,EN,,0,0,0,,we're going to multiply it by some number dt.\nDialogue: 0,0:21:57.68,0:22:00.00,EN,,0,0,0,,And now what we have here, this is exactly the same thing.\nDialogue: 0,0:22:00.00,0:22:00.91,EN,,0,0,0,,We have a box,\nDialogue: 0,0:22:03.36,0:22:04.56,EN,,0,0,0,,which is an integrator.\nDialogue: 0,0:22:09.79,0:22:11.26,EN,,0,0,0,,And it takes in a stream s,\nDialogue: 0,0:22:11.90,0:22:14.51,EN,,0,0,0,,and instead of 1 here,\nDialogue: 0,0:22:14.94,0:22:18.35,EN,,0,0,0,,we can put the additional value for the integral.\nDialogue: 0,0:22:19.98,0:22:21.60,EN,,0,0,0,,And that one looks very much like a\nDialogue: 0,0:22:22.35,0:22:24.86,EN,,0,0,0,,a signal processing block diagram program.\nDialogue: 0,0:22:25.27,0:22:28.11,EN,,0,0,0,,In fact, here's the procedure that looks exactly like that.\nDialogue: 0,0:22:31.49,0:22:33.61,EN,,0,0,0,,Find the integral of a stream.\nDialogue: 0,0:22:34.01,0:22:35.48,EN,,0,0,0,,So an integral's going to take a stream\nDialogue: 0,0:22:35.68,0:22:36.86,EN,,0,0,0,,Sand produce a new stream,\nDialogue: 0,0:22:37.53,0:22:40.67,EN,,0,0,0,,and it takes in an initial value and some time constant.\nDialogue: 0,0:22:42.23,0:22:42.97,EN,,0,0,0,,And what do we do?\nDialogue: 0,0:22:43.04,0:22:45.05,EN,,0,0,0,,Well, we internally define this thing int,\nDialogue: 0,0:22:45.20,0:22:46.32,EN,,0,0,0,,and we make this internal name\nDialogue: 0,0:22:46.33,0:22:48.86,EN,,0,0,0,,so we can feed it back, loop it around itself.\nDialogue: 0,0:22:49.40,0:22:50.80,EN,,0,0,0,,And int is defined to be\nDialogue: 0,0:22:51.10,0:22:53.32,EN,,0,0,0,,something that starts out at the initial value,\nDialogue: 0,0:22:54.97,0:23:00.14,EN,,0,0,0,,and the rest of it is gotten by adding together.\nDialogue: 0,0:23:01.28,0:23:03.61,EN,,0,0,0,,We take our input stream, scale it by dt,\nDialogue: 0,0:23:03.87,0:23:04.92,EN,,0,0,0,,and add that to int.\nDialogue: 0,0:23:06.88,0:23:09.66,EN,,0,0,0,,And now we'll return from all that the value of integral is this thing int.\nDialogue: 0,0:23:10.69,0:23:12.94,EN,,0,0,0,,And we use this internal definition syntax so we could\nDialogue: 0,0:23:13.34,0:23:15.66,EN,,0,0,0,,write a little internal definition that refers to itself.\nDialogue: 0,0:23:21.88,0:23:23.71,EN,,0,0,0,,Well, there are all sorts of things we can do.\nDialogue: 0,0:23:23.71,0:23:24.51,EN,,0,0,0,,Let's try this one.\nDialogue: 0,0:23:25.63,0:23:26.89,EN,,0,0,0,,how about the Fibonacci numbers.\nDialogue: 0,0:23:26.89,0:23:32.62,EN,,0,0,0,,You can say define fibs.\nDialogue: 0,0:23:36.35,0:23:37.63,EN,,0,0,0,,Well, what are the Fibonacci numbers?\nDialogue: 0,0:23:37.98,0:23:46.54,EN,,0,0,0,,They're something that starts out with 0,\nDialogue: 0,0:23:48.65,0:23:50.09,EN,,0,0,0,,and the next one is 1.\nDialogue: 0,0:23:56.26,0:23:59.16,EN,,0,0,0,,And the rest of the Fibonacci numbers are gotten by\nDialogue: 0,0:23:59.87,0:24:11.00,EN,,0,0,0,,adding the Fibonacci numbers to their own tail.\nDialogue: 0,0:24:17.57,0:24:19.28,EN,,0,0,0,,There's a definition of the Fibonacci numbers.\nDialogue: 0,0:24:20.58,0:24:21.43,EN,,0,0,0,,How does that work?\nDialogue: 0,0:24:21.43,0:24:24.19,EN,,0,0,0,,Well, we start off,\nDialogue: 0,0:24:24.20,0:24:26.49,EN,,0,0,0,,and someone says compute for us the Fibonacci numbers,\nDialogue: 0,0:24:29.64,0:24:31.92,EN,,0,0,0,,and we're going to tell you it starts out with 0 and 1.\nDialogue: 0,0:24:35.79,0:24:38.22,EN,,0,0,0,,And everything after the 0 and 1\nDialogue: 0,0:24:39.18,0:24:40.86,EN,,0,0,0,,is gotten by summing two streams.\nDialogue: 0,0:24:41.12,0:24:42.59,EN,,0,0,0,,One is the fibs themselves,\nDialogue: 0,0:24:44.06,0:24:45.69,EN,,0,0,0,,and the other one is the tail of the fibs.\nDialogue: 0,0:24:49.12,0:24:51.16,EN,,0,0,0,,So if I know that these start out with 0 and 1,\nDialogue: 0,0:24:51.79,0:24:55.42,EN,,0,0,0,,I know that the fibs now start out with 0 and 1,\nDialogue: 0,0:24:55.74,0:24:57.40,EN,,0,0,0,,and the tail of the fibs start out with 1.\nDialogue: 0,0:24:58.36,0:24:59.45,EN,,0,0,0,,So as soon as I know that,\nDialogue: 0,0:24:59.66,0:25:02.11,EN,,0,0,0,,I know that the next one here is 0 plus 1 is 1,\nDialogue: 0,0:25:02.96,0:25:04.60,EN,,0,0,0,,and that tells me that the next one here is 1\nDialogue: 0,0:25:04.62,0:25:05.72,EN,,0,0,0,,and the next one here is 1.\nDialogue: 0,0:25:06.30,0:25:07.28,EN,,0,0,0,,And as soon as I know that,\nDialogue: 0,0:25:07.29,0:25:08.76,EN,,0,0,0,,I know that the next one is 2.\nDialogue: 0,0:25:09.39,0:25:11.70,EN,,0,0,0,,So the next one here is 2 and the next one here is 2.\nDialogue: 0,0:25:11.70,0:25:12.56,EN,,0,0,0,,And this is 3.\nDialogue: 0,0:25:14.72,0:25:15.79,EN,,0,0,0,,This one goes to 3,\nDialogue: 0,0:25:16.19,0:25:17.13,EN,,0,0,0,,and this is 5.\nDialogue: 0,0:25:18.67,0:25:19.96,EN,,0,0,0,,So it's a perfectly sensible definition.\nDialogue: 0,0:25:21.50,0:25:22.78,EN,,0,0,0,,It's a one-line definition.\nDialogue: 0,0:25:22.83,0:25:25.00,EN,,0,0,0,,And again, I could walk over to the computer\nDialogue: 0,0:25:25.00,0:25:26.62,EN,,0,0,0,,and type that in, exactly that,\nDialogue: 0,0:25:27.04,0:25:28.94,EN,,0,0,0,,and then say print stream the Fibonacci numbers,\nDialogue: 0,0:25:28.94,0:25:30.15,EN,,0,0,0,,and they all come flying out.\nDialogue: 0,0:25:32.79,0:25:35.20,EN,,0,0,0,,See, this is a lot like learning about recursion again.\nDialogue: 0,0:25:36.81,0:25:39.79,EN,,0,0,0,,Instead of thinking that recursive procedures,\nDialogue: 0,0:25:40.99,0:25:43.50,EN,,0,0,0,,we have recursively defined data objects.\nDialogue: 0,0:25:45.16,0:25:46.92,EN,,0,0,0,,But that shouldn't surprise you at all,\nDialogue: 0,0:25:47.12,0:25:49.50,EN,,0,0,0,,because by now, you should be coming to really believe\nDialogue: 0,0:25:49.52,0:25:53.05,EN,,0,0,0,,that there's no difference really between procedures and data.\nDialogue: 0,0:25:53.09,0:25:53.92,EN,,0,0,0,,In fact, in some sense,\nDialogue: 0,0:25:53.93,0:25:56.41,EN,,0,0,0,,the underlying streams are procedures sitting there,\nDialogue: 0,0:25:56.43,0:25:57.79,EN,,0,0,0,,although we don't think of them that way.\nDialogue: 0,0:25:58.21,0:26:00.38,EN,,0,0,0,,So the fact that we have recursive procedures,\nDialogue: 0,0:26:00.70,0:26:03.63,EN,,0,0,0,,well, then it should be natural that we have recursive data, too.\nDialogue: 0,0:26:07.72,0:26:09.69,EN,,0,0,0,,OK, well, this is all pretty neat.\nDialogue: 0,0:26:09.72,0:26:13.92,EN,,0,0,0,,Unfortunately, there are problems that streams aren't going to solve.\nDialogue: 0,0:26:14.99,0:26:16.48,EN,,0,0,0,,Let me show you one of them.\nDialogue: 0,0:26:17.58,0:26:20.35,EN,,0,0,0,,See, in the same way, let's imagine that we're\nDialogue: 0,0:26:20.76,0:26:23.61,EN,,0,0,0,,building an analog computer to solve some differential equation\nDialogue: 0,0:26:25.20,0:26:34.30,EN,,0,0,0,,like, say, we want to solve the equation y prime dy dt is y squared,\nDialogue: 0,0:26:34.76,0:26:36.16,EN,,0,0,0,,and I'm going to give you some initial value.\nDialogue: 0,0:26:36.39,0:26:38.03,EN,,0,0,0,,I'll tell you y of 0 equals 1.\nDialogue: 0,0:26:41.48,0:26:44.06,EN,,0,0,0,,Let's say dt is equal to something.\nDialogue: 0,0:26:46.77,0:26:47.53,EN,,0,0,0,,Now, in the old days,\nDialogue: 0,0:26:48.00,0:26:50.65,EN,,0,0,0,,people built analog computers to solve these kinds of things.\nDialogue: 0,0:26:51.36,0:26:53.02,EN,,0,0,0,,And the way you do that is really simple.\nDialogue: 0,0:26:53.02,0:26:54.41,EN,,0,0,0,,You get yourself an integrator,\nDialogue: 0,0:27:00.04,0:27:01.69,EN,,0,0,0,,like that one, an integrator box.\nDialogue: 0,0:27:03.05,0:27:06.48,EN,,0,0,0,,And we put in the initial value y of 0 is 1.\nDialogue: 0,0:27:08.53,0:27:10.92,EN,,0,0,0,,And now if we feed something in and get something out,\nDialogue: 0,0:27:10.96,0:27:13.16,EN,,0,0,0,,we'll say, gee, what we're getting out is the answer.\nDialogue: 0,0:27:14.25,0:27:16.96,EN,,0,0,0,,And what we're going to feed in is the derivative,\nDialogue: 0,0:27:17.52,0:27:20.52,EN,,0,0,0,,and the derivative is supposed to be the square of the answer.\nDialogue: 0,0:27:21.49,0:27:27.07,EN,,0,0,0,,So if we take these values and map using square,\nDialogue: 0,0:27:30.73,0:27:32.09,EN,,0,0,0,,and if I feed this around,\nDialogue: 0,0:27:36.28,0:27:38.48,EN,,0,0,0,,that's how I build a block diagram\nDialogue: 0,0:27:38.57,0:27:41.08,EN,,0,0,0,,for an analog computer that solves this differential equation.\nDialogue: 0,0:27:42.91,0:27:44.80,EN,,0,0,0,,Now, what we'd like to do is write a stream\nDialogue: 0,0:27:44.80,0:27:46.78,EN,,0,0,0,,program that looks exactly like that.\nDialogue: 0,0:27:47.23,0:27:48.72,EN,,0,0,0,,And what do I mean exactly like that?\nDialogue: 0,0:27:49.39,0:27:58.30,EN,,0,0,0,,Well, I'd say define y to be the integral\nDialogue: 0,0:28:04.28,0:28:11.68,EN,,0,0,0,,of dy starting at 1 with 0.001 as a time step.\nDialogue: 0,0:28:13.79,0:28:15.45,EN,,0,0,0,,And I'd like to say that says this.\nDialogue: 0,0:28:16.80,0:28:20.85,EN,,0,0,0,,And then I'd like to say, well, dy is gotten by mapping the square along y.\nDialogue: 0,0:28:20.85,0:28:32.81,EN,,0,0,0,,So define dy to be map square along y.\nDialogue: 0,0:28:33.51,0:28:36.80,EN,,0,0,0,,So there's a stream description of this analog computer,\nDialogue: 0,0:28:38.62,0:28:40.32,EN,,0,0,0,,and unfortunately, it doesn't work.\nDialogue: 0,0:28:41.41,0:28:42.67,EN,,0,0,0,,And you can see why it doesn't work\nDialogue: 0,0:28:42.97,0:28:44.99,EN,,0,0,0,,because when I come in and say define y\nDialogue: 0,0:28:46.43,0:28:47.85,EN,,0,0,0,,to be the integral of dy\nDialogue: 0,0:28:49.04,0:28:50.65,EN,,0,0,0,,it says, oh, the integral of what-- huh?\nDialogue: 0,0:28:51.19,0:28:52.12,EN,,0,0,0,,Oh, that's undefined.\nDialogue: 0,0:28:53.71,0:28:57.63,EN,,0,0,0,,So I can't write this definition before I've written this one.\nDialogue: 0,0:28:58.77,0:29:00.51,EN,,0,0,0,,On the other hand, if I try and write this one first,\nDialogue: 0,0:29:00.51,0:29:03.02,EN,,0,0,0,,it says, oh, I define y to be the map of square along what?\nDialogue: 0,0:29:03.58,0:29:04.64,EN,,0,0,0,,Oh, that's not defined yet.\nDialogue: 0,0:29:05.77,0:29:08.17,EN,,0,0,0,,So I can't write this one first, and I can't write that one first.\nDialogue: 0,0:29:09.08,0:29:11.58,EN,,0,0,0,,So I can't quite play this game.\nDialogue: 0,0:29:17.56,0:29:18.51,EN,,0,0,0,,Well, is there a way out?\nDialogue: 0,0:29:20.60,0:29:21.84,EN,,0,0,0,,See, we can do that with ones.\nDialogue: 0,0:29:22.20,0:29:25.82,EN,,0,0,0,,See, over here, we did this thing ones,\nDialogue: 0,0:29:27.24,0:29:29.90,EN,,0,0,0,,and we were able to define ones in terms of ones because\nDialogue: 0,0:29:30.40,0:29:32.03,EN,,0,0,0,,of this delay that was built inside\nDialogue: 0,0:29:32.43,0:29:34.12,EN,,0,0,0,,because cons-stream had a delay.\nDialogue: 0,0:29:34.77,0:29:35.79,EN,,0,0,0,,Now, why's it sensible?\nDialogue: 0,0:29:35.92,0:29:38.51,EN,,0,0,0,,Why's it sensible for cons-stream to be built with this delay?\nDialogue: 0,0:29:40.73,0:29:43.13,EN,,0,0,0,,The reason is that cons-stream can do a useful thing\nDialogue: 0,0:29:43.48,0:29:44.88,EN,,0,0,0,,without looking at its tail.\nDialogue: 0,0:29:45.95,0:29:46.84,EN,,0,0,0,,See, if I say\nDialogue: 0,0:29:47.48,0:29:49.64,EN,,0,0,0,,this is cons-stream of 1 onto something\nDialogue: 0,0:29:49.92,0:29:51.69,EN,,0,0,0,,without knowing anything about something,\nDialogue: 0,0:29:52.16,0:29:54.03,EN,,0,0,0,,I know that the stream starts off with 1.\nDialogue: 0,0:29:54.87,0:29:57.29,EN,,0,0,0,,That's why it was sensible to build something like cons-stream.\nDialogue: 0,0:29:59.96,0:30:01.24,EN,,0,0,0,,So we put a delay in there,\nDialogue: 0,0:30:01.42,0:30:04.65,EN,,0,0,0,,and that allows us to have this sort of self-referential definition.\nDialogue: 0,0:30:06.32,0:30:07.95,EN,,0,0,0,,Well, integral is a little bit the same way.\nDialogue: 0,0:30:08.19,0:30:12.52,EN,,0,0,0,,See, notice for an integral, I can--\nDialogue: 0,0:30:14.60,0:30:16.08,EN,,0,0,0,,let's go back and look at integral for a second.\nDialogue: 0,0:30:17.58,0:30:18.56,EN,,0,0,0,,See, notice integral,\nDialogue: 0,0:30:21.39,0:30:25.00,EN,,0,0,0,,it makes sense to say what's the first thing in the integral\nDialogue: 0,0:30:26.04,0:30:27.87,EN,,0,0,0,,without knowing the stream that you're integrating.\nDialogue: 0,0:30:28.97,0:30:30.17,EN,,0,0,0,,Because the first thing in the integral\nDialogue: 0,0:30:30.20,0:30:32.16,EN,,0,0,0,,is always going to be the initial value that you're handed.\nDialogue: 0,0:30:33.14,0:30:36.11,EN,,0,0,0,,So integral could be a procedure like cons-stream.\nDialogue: 0,0:30:37.09,0:30:37.98,EN,,0,0,0,,You could define it,\nDialogue: 0,0:30:38.25,0:30:40.88,EN,,0,0,0,,and then even before it knows what it's supposed to be integrating,\nDialogue: 0,0:30:42.84,0:30:45.18,EN,,0,0,0,,it knows enough to say what its initial value is.\nDialogue: 0,0:30:46.71,0:30:48.17,EN,,0,0,0,,So we can make a smarter integral,\nDialogue: 0,0:30:48.41,0:30:50.68,EN,,0,0,0,,which is aha, you're going to give me a stream to integrate\nDialogue: 0,0:30:50.83,0:30:51.92,EN,,0,0,0,,and an initial value,\nDialogue: 0,0:30:52.11,0:30:54.99,EN,,0,0,0,,but I really don't have to look at that stream that I'm supposed to integrate\nDialogue: 0,0:30:55.21,0:30:56.97,EN,,0,0,0,,until you ask me to work down the stream.\nDialogue: 0,0:30:58.43,0:31:00.51,EN,,0,0,0,,In other words, integral can be like cons-stream,\nDialogue: 0,0:31:00.57,0:31:03.74,EN,,0,0,0,,and you can expect that there's going to be a delay around its integrand.\nDialogue: 0,0:31:03.76,0:31:04.86,EN,,0,0,0,,And we can write that.\nDialogue: 0,0:31:05.61,0:31:07.02,EN,,0,0,0,,Here's a procedure that does that.\nDialogue: 0,0:31:07.65,0:31:08.75,EN,,0,0,0,,Another version of integral,\nDialogue: 0,0:31:08.89,0:31:10.54,EN,,0,0,0,,and this is almost like the previous one,\nDialogue: 0,0:31:11.10,0:31:13.34,EN,,0,0,0,,except the stream it's going to get in\nDialogue: 0,0:31:13.77,0:31:15.69,EN,,0,0,0,,is going to expect to be a delayed object.\nDialogue: 0,0:31:17.11,0:31:18.43,EN,,0,0,0,,And how does this integral work?\nDialogue: 0,0:31:18.85,0:31:21.79,EN,,0,0,0,,Well, the little thing it's going to define inside of itself\nDialogue: 0,0:31:22.14,0:31:24.19,EN,,0,0,0,,says on the cons-stream,\nDialogue: 0,0:31:24.73,0:31:26.44,EN,,0,0,0,,the initial value is the initial value,\nDialogue: 0,0:31:27.16,0:31:29.68,EN,,0,0,0,,but only inside of that cons-stream,\nDialogue: 0,0:31:29.74,0:31:32.30,EN,,0,0,0,,and remember, there's going to be a hidden delay inside here.\nDialogue: 0,0:31:34.95,0:31:39.07,EN,,0,0,0,,Only inside of that cons-stream will I start looking at\nDialogue: 0,0:31:39.82,0:31:42.11,EN,,0,0,0,,what the actual delayed object is.\nDialogue: 0,0:31:43.18,0:31:45.79,EN,,0,0,0,,So my answer is the first thing's the initial value.\nDialogue: 0,0:31:45.97,0:31:47.90,EN,,0,0,0,,If anybody now asks me for my tail,\nDialogue: 0,0:31:48.40,0:31:49.42,EN,,0,0,0,,at that point,\nDialogue: 0,0:31:50.00,0:31:51.72,EN,,0,0,0,,I'm going to force that delayed object--\nDialogue: 0,0:31:52.62,0:31:53.60,EN,,0,0,0,,and I'll call that s--\nDialogue: 0,0:31:54.44,0:31:55.60,EN,,0,0,0,,and I do the add streams.\nDialogue: 0,0:31:56.36,0:31:59.26,EN,,0,0,0,,So this is an integral which is sort of like cons-stream.\nDialogue: 0,0:31:59.26,0:32:02.59,EN,,0,0,0,,It's not going to actually try and see what you handed it\nDialogue: 0,0:32:03.88,0:32:07.13,EN,,0,0,0,,as the thing to integrate until you look past the first element.\nDialogue: 0,0:32:10.12,0:32:11.02,EN,,0,0,0,,And if we do that\nDialogue: 0,0:32:11.52,0:32:12.83,EN,,0,0,0,,and we can make this work,\nDialogue: 0,0:32:13.36,0:32:15.20,EN,,0,0,0,,all we have to do here is\nDialogue: 0,0:32:16.00,0:32:25.31,EN,,0,0,0,,define y to the integral of delay of y, of delay of dy.\nDialogue: 0,0:32:27.09,0:32:28.22,EN,,0,0,0,,So y is going to be\nDialogue: 0,0:32:28.40,0:32:34.36,EN,,0,0,0,,the integral of delay of dy starting at 1,\nDialogue: 0,0:32:34.38,0:32:35.13,EN,,0,0,0,,and now this will work.\nDialogue: 0,0:32:35.28,0:32:37.44,EN,,0,0,0,,Because I type in the definition of y,\nDialogue: 0,0:32:38.00,0:32:39.68,EN,,0,0,0,,and that says, oh, I'm supposed to use the integral of\nDialogue: 0,0:32:40.20,0:32:42.68,EN,,0,0,0,,something I don't care about right now because it's a delay.\nDialogue: 0,0:32:44.60,0:32:46.32,EN,,0,0,0,,And these things, now you define dy.\nDialogue: 0,0:32:46.32,0:32:47.37,EN,,0,0,0,,Now, y is defined.\nDialogue: 0,0:32:47.55,0:32:48.89,EN,,0,0,0,,So when I define dy,\nDialogue: 0,0:32:49.13,0:32:50.67,EN,,0,0,0,,it can see that definition for y.\nDialogue: 0,0:32:51.70,0:32:52.84,EN,,0,0,0,,Everything is now started up.\nDialogue: 0,0:32:52.84,0:32:54.33,EN,,0,0,0,,Both streams have their first element.\nDialogue: 0,0:32:54.92,0:32:56.25,EN,,0,0,0,,And then when I start mapping down,\nDialogue: 0,0:32:56.27,0:32:57.31,EN,,0,0,0,,looking at successive elements,\nDialogue: 0,0:32:57.37,0:32:58.88,EN,,0,0,0,,both y and dy are defined.\nDialogue: 0,0:33:00.59,0:33:04.24,EN,,0,0,0,,So there's a little game you can play that goes a little bit beyond\nDialogue: 0,0:33:04.67,0:33:07.13,EN,,0,0,0,,just using the delay that's hidden inside streams.\nDialogue: 0,0:33:08.36,0:33:08.97,EN,,0,0,0,,Questions?\nDialogue: 0,0:33:13.52,0:33:14.27,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:34:07.30,0:34:10.04,EN,,0,0,0,,Well, just before the break, um..\nDialogue: 0,0:34:10.89,0:34:11.80,EN,,0,0,0,,I'm not sure if you noticed it,\nDialogue: 0,0:34:11.82,0:34:13.55,EN,,0,0,0,,but something nasty started to happen.\nDialogue: 0,0:34:14.83,0:34:18.40,EN,,0,0,0,,We've been going along with the streams\nDialogue: 0,0:34:19.16,0:34:22.68,EN,,0,0,0,,and divorcing time in the programs from time in the computers,\nDialogue: 0,0:34:22.86,0:34:26.28,EN,,0,0,0,,and all that divorcing got hidden inside the streams.\nDialogue: 0,0:34:27.28,0:34:29.50,EN,,0,0,0,,And then at the very end, we saw that sometimes\nDialogue: 0,0:34:29.71,0:34:32.19,EN,,0,0,0,,in order to really take advantage of this method,\nDialogue: 0,0:34:32.22,0:34:34.38,EN,,0,0,0,,you have to pull out other delays.\nDialogue: 0,0:34:34.38,0:34:35.85,EN,,0,0,0,,You have to write some explicit delays\nDialogue: 0,0:34:36.09,0:34:37.95,EN,,0,0,0,,that are not hidden inside that cons-stream.\nDialogue: 0,0:34:39.03,0:34:41.88,EN,,0,0,0,,And I did a very simple example with differential equations,\nDialogue: 0,0:34:42.35,0:34:44.08,EN,,0,0,0,,but if you have some very complicated system\nDialogue: 0,0:34:44.12,0:34:45.40,EN,,0,0,0,,with all kinds of self-loops,\nDialogue: 0,0:34:45.95,0:34:47.84,EN,,0,0,0,,it becomes very, very difficult to\nDialogue: 0,0:34:47.90,0:34:49.31,EN,,0,0,0,,see where you need those delays.\nDialogue: 0,0:34:49.92,0:34:51.18,EN,,0,0,0,,And if you leave them out by mistake,\nDialogue: 0,0:34:51.45,0:34:54.36,EN,,0,0,0,,it becomes very, very difficult to see why the thing maybe isn't working.\nDialogue: 0,0:34:55.55,0:34:57.15,EN,,0,0,0,,So that's kind of mess,\nDialogue: 0,0:34:57.79,0:35:01.71,EN,,0,0,0,,that by getting this power and allowing us to use delay,\nDialogue: 0,0:35:02.08,0:35:04.70,EN,,0,0,0,,we end up with some very complicated programming sometimes,\nDialogue: 0,0:35:04.72,0:35:06.80,EN,,0,0,0,,because it can't all be hidden inside the streams.\nDialogue: 0,0:35:08.51,0:35:09.79,EN,,0,0,0,,Well, is there a way out of that?\nDialogue: 0,0:35:11.13,0:35:12.67,EN,,0,0,0,,Yeah, there is a way out of that.\nDialogue: 0,0:35:13.48,0:35:16.08,EN,,0,0,0,,We could change the language so that\nDialogue: 0,0:35:16.14,0:35:18.19,EN,,0,0,0,,all procedures acted like cons-stream,\nDialogue: 0,0:35:19.10,0:35:21.48,EN,,0,0,0,,so that every procedure automatically\nDialogue: 0,0:35:22.32,0:35:25.45,EN,,0,0,0,,has an implicit delay around its arguments.\nDialogue: 0,0:35:25.45,0:35:26.43,EN,,0,0,0,,And what would that mean?\nDialogue: 0,0:35:27.52,0:35:29.53,EN,,0,0,0,,That would mean when you call a procedure,\nDialogue: 0,0:35:30.16,0:35:31.88,EN,,0,0,0,,the arguments wouldn't get evaluated.\nDialogue: 0,0:35:32.21,0:35:34.70,EN,,0,0,0,,Instead, they'd only be evaluated when you need them,\nDialogue: 0,0:35:34.89,0:35:36.72,EN,,0,0,0,,so they might be passed off to some other procedure,\nDialogue: 0,0:35:36.76,0:35:38.12,EN,,0,0,0,,which wouldn't evaluate them either.\nDialogue: 0,0:35:39.26,0:35:41.90,EN,,0,0,0,,So all these procedures would be passing promises around.\nDialogue: 0,0:35:42.15,0:35:44.46,EN,,0,0,0,,And then finally maybe when you finally got down\nDialogue: 0,0:35:44.65,0:35:47.34,EN,,0,0,0,,to having to look at the value of something\nDialogue: 0,0:35:47.36,0:35:48.99,EN,,0,0,0,,that was handed to a primitive operator\nDialogue: 0,0:35:49.37,0:35:51.48,EN,,0,0,0,,which you actually start calling in all those promises.\nDialogue: 0,0:35:52.38,0:35:53.16,EN,,0,0,0,,If we did that,\nDialogue: 0,0:35:53.36,0:35:55.37,EN,,0,0,0,,since everything would have a uniform delay,\nDialogue: 0,0:35:57.16,0:35:59.00,EN,,0,0,0,,then you wouldn't have to write any explicit delays,\nDialogue: 0,0:35:59.04,0:36:01.55,EN,,0,0,0,,because it would be automatically built into the way the language works.\nDialogue: 0,0:36:03.24,0:36:04.38,EN,,0,0,0,,Or another way to say that,\nDialogue: 0,0:36:05.10,0:36:08.14,EN,,0,0,0,,technically what I'm describing is what's called\nDialogue: 0,0:36:09.02,0:36:10.76,EN,,0,0,0,,if we did that, our language would be\nDialogue: 0,0:36:12.19,0:36:16.57,EN,,0,0,0,,so-called normal-order evaluation language\nDialogue: 0,0:36:20.20,0:36:23.47,EN,,0,0,0,,versus what we've actually been working with,\nDialogue: 0,0:36:23.87,0:36:33.79,EN,,0,0,0,,which is called applicative order--  versus applicative-order evaluation.\nDialogue: 0,0:36:34.56,0:36:36.83,EN,,0,0,0,,And remember the substitution model for applicative order.\nDialogue: 0,0:36:36.83,0:36:40.49,EN,,0,0,0,,It says when you go and evaluate a combination,\nDialogue: 0,0:36:40.51,0:36:42.11,EN,,0,0,0,,you find the values of all the pieces.\nDialogue: 0,0:36:43.59,0:36:45.40,EN,,0,0,0,,You evaluate the arguments and then you\nDialogue: 0,0:36:45.72,0:36:47.42,EN,,0,0,0,,substitute them in the body of the procedure.\nDialogue: 0,0:36:47.60,0:36:49.55,EN,,0,0,0,,Normal order says no, don't do that.\nDialogue: 0,0:36:49.89,0:36:51.90,EN,,0,0,0,,What you do is effectively\nDialogue: 0,0:36:52.76,0:36:54.41,EN,,0,0,0,,substitute in the body of the procedure,\nDialogue: 0,0:36:54.44,0:36:56.19,EN,,0,0,0,,but instead of evaluating the arguments,\nDialogue: 0,0:36:56.54,0:36:58.08,EN,,0,0,0,,you just put a promise to compute them there.\nDialogue: 0,0:36:58.81,0:36:59.90,EN,,0,0,0,,Or another way to say that\nDialogue: 0,0:36:59.92,0:37:02.09,EN,,0,0,0,,you take the expressions for the arguments, if you like,\nDialogue: 0,0:37:02.28,0:37:04.84,EN,,0,0,0,,and substitute them in the body of the procedure and go on,\nDialogue: 0,0:37:05.16,0:37:06.88,EN,,0,0,0,,and never really simplify anything\nDialogue: 0,0:37:07.16,0:37:08.76,EN,,0,0,0,,until you get down to a primitive operator.\nDialogue: 0,0:37:09.47,0:37:10.99,EN,,0,0,0,,So that would be a normal-order language.\nDialogue: 0,0:37:12.17,0:37:13.12,EN,,0,0,0,,Well, why don't we do that?\nDialogue: 0,0:37:13.82,0:37:14.60,EN,,0,0,0,,Because if we did,\nDialogue: 0,0:37:15.00,0:37:17.34,EN,,0,0,0,,we'd get all the advantages of delayed evaluation\nDialogue: 0,0:37:17.90,0:37:18.80,EN,,0,0,0,,with none of the mess.\nDialogue: 0,0:37:18.94,0:37:20.19,EN,,0,0,0,,In fact, if we did that\nDialogue: 0,0:37:20.43,0:37:22.67,EN,,0,0,0,,and cons was just a delayed procedure,\nDialogue: 0,0:37:22.68,0:37:24.57,EN,,0,0,0,,that would make cons the same as cons-stream.\nDialogue: 0,0:37:24.71,0:37:25.82,EN,,0,0,0,,We wouldn't need streams at all\nDialogue: 0,0:37:26.36,0:37:28.54,EN,,0,0,0,,because lists would automatically be streams.\nDialogue: 0,0:37:29.55,0:37:30.70,EN,,0,0,0,,That's how lists would behave,\nDialogue: 0,0:37:30.75,0:37:32.35,EN,,0,0,0,,all data structures would behave that way.\nDialogue: 0,0:37:32.35,0:37:33.64,EN,,0,0,0,,Everything would behave that way.\nDialogue: 0,0:37:35.07,0:37:37.63,EN,,0,0,0,,Right, You'd never really do any computation\nDialogue: 0,0:37:37.66,0:37:39.42,EN,,0,0,0,,until you actually needed the answer.\nDialogue: 0,0:37:40.80,0:37:43.58,EN,,0,0,0,,You wouldn't have to worry about all these explicit annoying delays.\nDialogue: 0,0:37:44.79,0:37:46.16,EN,,0,0,0,,Well, why don't we do that?\nDialogue: 0,0:37:47.16,0:37:48.81,EN,,0,0,0,,First of all, I should say people do do that.\nDialogue: 0,0:37:49.23,0:37:51.85,EN,,0,0,0,,There's some very beautiful languages.\nDialogue: 0,0:37:51.85,0:37:55.21,EN,,0,0,0,,One of the very nicest is a language called Miranda,\nDialogue: 0,0:37:55.77,0:37:56.76,EN,,0,0,0,,which is, um..\nDialogue: 0,0:37:57.44,0:37:59.80,EN,,0,0,0,,developed by David Turner at the University of Kent.\nDialogue: 0,0:38:00.71,0:38:01.93,EN,,0,0,0,,And that's how this language works.\nDialogue: 0,0:38:01.93,0:38:03.34,EN,,0,0,0,,It's a normal-order language\nDialogue: 0,0:38:04.27,0:38:05.55,EN,,0,0,0,,and its data structures,\nDialogue: 0,0:38:06.16,0:38:08.41,EN,,0,0,0,,which look like lists, are actually streams.\nDialogue: 0,0:38:08.96,0:38:10.91,EN,,0,0,0,,And you write ordinary procedures in Miranda,\nDialogue: 0,0:38:11.28,0:38:13.28,EN,,0,0,0,,and they do these prime things and eight queens things,\nDialogue: 0,0:38:13.32,0:38:14.97,EN,,0,0,0,,just without anything special.\nDialogue: 0,0:38:14.97,0:38:16.35,EN,,0,0,0,,It's all built in there.\nDialogue: 0,0:38:17.93,0:38:18.91,EN,,0,0,0,,But there's a price.\nDialogue: 0,0:38:21.19,0:38:22.36,EN,,0,0,0,,Remember how we got here.\nDialogue: 0,0:38:23.17,0:38:27.48,EN,,0,0,0,,We're decoupling time in the programs from time in the machines.\nDialogue: 0,0:38:27.96,0:38:28.88,EN,,0,0,0,,And if we put delay,\nDialogue: 0,0:38:29.04,0:38:30.33,EN,,0,0,0,,that sort of decouples it everywhere,\nDialogue: 0,0:38:30.40,0:38:31.42,EN,,0,0,0,,not just in streams.\nDialogue: 0,0:38:32.19,0:38:33.14,EN,,0,0,0,,Remember what we're trying to do.\nDialogue: 0,0:38:33.14,0:38:38.11,EN,,0,0,0,,We're trying to think about programming as a way to specify processes.\nDialogue: 0,0:38:39.30,0:38:40.62,EN,,0,0,0,,And if we give up too much time,\nDialogue: 0,0:38:40.65,0:38:42.41,EN,,0,0,0,,our language becomes more elegant,\nDialogue: 0,0:38:43.74,0:38:45.87,EN,,0,0,0,,but it becomes a little bit less expressive.\nDialogue: 0,0:38:47.03,0:38:49.84,EN,,0,0,0,,There are certain distinctions that we can't draw.\nDialogue: 0,0:38:51.48,0:38:53.15,EN,,0,0,0,,One of them, for instance, is iteration.\nDialogue: 0,0:38:53.98,0:38:56.44,EN,,0,0,0,,Remember this old procedure,\nDialogue: 0,0:38:56.96,0:38:58.28,EN,,0,0,0,,iterative factorial,\nDialogue: 0,0:38:58.44,0:39:00.48,EN,,0,0,0,,that we looked at quite a long time ago.\nDialogue: 0,0:39:01.23,0:39:02.97,EN,,0,0,0,,Iterative factorial had a thing,\nDialogue: 0,0:39:03.04,0:39:04.91,EN,,0,0,0,,and it said there was an internal procedure,\nDialogue: 0,0:39:05.18,0:39:07.50,EN,,0,0,0,,and there was a state which was a product and a counter,\nDialogue: 0,0:39:08.70,0:39:10.96,EN,,0,0,0,,and we iterate that going around the loop.\nDialogue: 0,0:39:12.12,0:39:13.68,EN,,0,0,0,,And we said that was an iterative procedure\nDialogue: 0,0:39:13.71,0:39:14.83,EN,,0,0,0,,because it didn't build up state.\nDialogue: 0,0:39:15.73,0:39:17.45,EN,,0,0,0,,And the reason it didn't build up state is\nDialogue: 0,0:39:17.47,0:39:20.25,EN,,0,0,0,,because this iter that's called\nDialogue: 0,0:39:20.30,0:39:22.86,EN,,0,0,0,,is just passing these things around to itself.\nDialogue: 0,0:39:23.90,0:39:25.39,EN,,0,0,0,,Or in the substitution model that,\nDialogue: 0,0:39:25.55,0:39:27.79,EN,,0,0,0,,you could see in the substitution model that Jerry did,\nDialogue: 0,0:39:28.72,0:39:30.01,EN,,0,0,0,,that in an iterative procedure,\nDialogue: 0,0:39:30.03,0:39:31.44,EN,,0,0,0,,that state doesn't have to grow.\nDialogue: 0,0:39:31.82,0:39:34.22,EN,,0,0,0,,And in fact, we said it doesn't, so this is an iteration.\nDialogue: 0,0:39:34.99,0:39:37.47,EN,,0,0,0,,But now think about this exact same text\nDialogue: 0,0:39:37.47,0:39:39.10,EN,,0,0,0,,if we had a normal-order language.\nDialogue: 0,0:39:41.15,0:39:42.17,EN,,0,0,0,,What would happen is\nDialogue: 0,0:39:42.88,0:39:44.96,EN,,0,0,0,,this would no longer be an iterative procedure\nDialogue: 0,0:39:45.65,0:39:48.67,EN,,0,0,0,,And if you really think about the details of the substitution model,\nDialogue: 0,0:39:48.67,0:39:49.90,EN,,0,0,0,,which I'm not going to do here,\nDialogue: 0,0:39:51.20,0:39:52.35,EN,,0,0,0,,this expression would grow.\nDialogue: 0,0:39:52.36,0:39:53.18,EN,,0,0,0,,Why would it grow?\nDialogue: 0,0:39:53.28,0:39:55.20,EN,,0,0,0,,It's because when iter calls itself,\nDialogue: 0,0:39:55.85,0:39:57.31,EN,,0,0,0,,it calls itself with this product.\nDialogue: 0,0:39:58.08,0:39:59.36,EN,,0,0,0,,If it's a normal-order language,\nDialogue: 0,0:39:59.39,0:40:01.16,EN,,0,0,0,,that multiplication is not going to get done.\nDialogue: 0,0:40:02.51,0:40:03.82,EN,,0,0,0,,That's going to say I'm to call myself\nDialogue: 0,0:40:03.93,0:40:05.68,EN,,0,0,0,,with a promise to compute this product.\nDialogue: 0,0:40:06.67,0:40:08.03,EN,,0,0,0,,And now iter goes around again.\nDialogue: 0,0:40:09.76,0:40:11.55,EN,,0,0,0,,And I'm going to call myself\nDialogue: 0,0:40:11.84,0:40:14.04,EN,,0,0,0,,with a promise to compute this product\nDialogue: 0,0:40:14.04,0:40:17.82,EN,,0,0,0,,where now one of the one factors is a promise.\nDialogue: 0,0:40:18.40,0:40:19.43,EN,,0,0,0,,And I call myself again.\nDialogue: 0,0:40:19.43,0:40:21.13,EN,,0,0,0,,And if you write out the substitution model\nDialogue: 0,0:40:21.98,0:40:23.60,EN,,0,0,0,,for that iterative process,\nDialogue: 0,0:40:23.77,0:40:26.83,EN,,0,0,0,,you'll see exactly the same growth in state,\nDialogue: 0,0:40:27.16,0:40:28.96,EN,,0,0,0,,all those promises that are getting remembered\nDialogue: 0,0:40:28.97,0:40:30.76,EN,,0,0,0,,that have to get called in at the very end.\nDialogue: 0,0:40:31.79,0:40:35.02,EN,,0,0,0,,So one of the disadvantages\nDialogue: 0,0:40:35.05,0:40:36.86,EN,,0,0,0,,is that you can't really express iteration.\nDialogue: 0,0:40:36.98,0:40:39.60,EN,,0,0,0,,Maybe that's a little theoretical reason why not,\nDialogue: 0,0:40:39.61,0:40:43.90,EN,,0,0,0,,but in fact, people who are trying to write real operating systems\nDialogue: 0,0:40:44.27,0:40:47.56,EN,,0,0,0,,in these languages are running into exactly these types of problems.\nDialogue: 0,0:40:48.20,0:40:50.75,EN,,0,0,0,,Like it's perfectly possible to\nDialogue: 0,0:40:51.64,0:40:54.38,EN,,0,0,0,,implement a text editor in languages like these.\nDialogue: 0,0:40:54.61,0:40:56.08,EN,,0,0,0,,But after you work a while,\nDialogue: 0,0:40:56.72,0:40:59.39,EN,,0,0,0,,you suddenly have 3 megabytes of stuff,\nDialogue: 0,0:40:59.44,0:41:02.04,EN,,0,0,0,,which is-- I guess they call them\nDialogue: 0,0:41:02.16,0:41:05.60,EN,,0,0,0,,the dragging tail problem who are looking at these,\nDialogue: 0,0:41:05.82,0:41:08.20,EN,,0,0,0,,of stuff of promises that sort of haven't been called in\nDialogue: 0,0:41:08.24,0:41:10.46,EN,,0,0,0,,because you couldn't quite express an iteration.\nDialogue: 0,0:41:10.72,0:41:14.81,EN,,0,0,0,,And one of the research questions in these kinds of languages\nDialogue: 0,0:41:14.83,0:41:17.48,EN,,0,0,0,,are figuring out the right compiler technology\nDialogue: 0,0:41:17.82,0:41:19.85,EN,,0,0,0,,to get rid of the so-called dragging tails.\nDialogue: 0,0:41:20.17,0:41:21.61,EN,,0,0,0,,It's not simple.\nDialogue: 0,0:41:23.94,0:41:27.31,EN,,0,0,0,,But there's another kind of more striking issue\nDialogue: 0,0:41:27.96,0:41:31.04,EN,,0,0,0,,about why you just don't go ahead and make your language normal order.\nDialogue: 0,0:41:32.51,0:41:33.29,EN,,0,0,0,,And the reason is\nDialogue: 0,0:41:35.05,0:41:38.09,EN,,0,0,0,,that normal-order evaluation and side effects\nDialogue: 0,0:41:38.89,0:41:40.19,EN,,0,0,0,,just don't mix.\nDialogue: 0,0:41:42.00,0:41:43.96,EN,,0,0,0,,They just don't go together very well.\nDialogue: 0,0:41:45.44,0:41:46.65,EN,,0,0,0,,Somehow, you can't-\nDialogue: 0,0:41:48.28,0:41:50.80,EN,,0,0,0,,it's sort of you can't simultaneously\nDialogue: 0,0:41:51.00,0:41:54.33,EN,,0,0,0,,go around trying to model objects with local state and change\nDialogue: 0,0:41:55.72,0:41:56.96,EN,,0,0,0,,at the same time\nDialogue: 0,0:41:57.18,0:41:59.55,EN,,0,0,0,,do these normal-order tricks of de-coupling time.\nDialogue: 0,0:42:00.40,0:42:03.55,EN,,0,0,0,,Let me just show you a really simple example, very, very simple.\nDialogue: 0,0:42:03.79,0:42:05.50,EN,,0,0,0,,Suppose we had a normal-order language.\nDialogue: 0,0:42:07.52,0:42:09.55,EN,,0,0,0,,And I'm going to start out in this language.\nDialogue: 0,0:42:09.55,0:42:10.52,EN,,0,0,0,,This is now normal order.\nDialogue: 0,0:42:10.52,0:42:12.22,EN,,0,0,0,,I'm going to define x to be 0.\nDialogue: 0,0:42:13.57,0:42:15.56,EN,,0,0,0,,It's just some variable I'll initialize.\nDialogue: 0,0:42:15.75,0:42:17.69,EN,,0,0,0,,And now I'm going to define this little funny function,\nDialogue: 0,0:42:18.57,0:42:20.44,EN,,0,0,0,,which is an identity function.\nDialogue: 0,0:42:22.64,0:42:23.90,EN,,0,0,0,,And what it does,\nDialogue: 0,0:42:24.11,0:42:26.60,EN,,0,0,0,,it keeps track of the last time you called it using x.\nDialogue: 0,0:42:31.40,0:42:34.16,EN,,0,0,0,,Right? So the identity of n just returns n,\nDialogue: 0,0:42:34.17,0:42:35.39,EN,,0,0,0,,but it sets x to be n.\nDialogue: 0,0:42:36.76,0:42:38.54,EN,,0,0,0,,And now I'll define a little increment function,\nDialogue: 0,0:42:39.55,0:42:42.30,EN,,0,0,0,,which is a very little, simple scenario.\nDialogue: 0,0:42:42.58,0:42:45.34,EN,,0,0,0,,Now, imagine I'm interacting with this in the normal-order language,\nDialogue: 0,0:42:46.27,0:42:47.23,EN,,0,0,0,,and I type the following.\nDialogue: 0,0:42:47.23,0:42:52.83,EN,,0,0,0,,I say define y to be increment the identity function of 3,\nDialogue: 0,0:42:52.83,0:42:53.96,EN,,0,0,0,,so y is going to be 4.\nDialogue: 0,0:42:57.41,0:42:58.35,EN,,0,0,0,,Now, I say what's x?\nDialogue: 0,0:42:59.52,0:43:02.16,EN,,0,0,0,,Well, x should have been the value that was remembered last\nDialogue: 0,0:43:02.64,0:43:04.01,EN,,0,0,0,,when I called the identity function.\nDialogue: 0,0:43:04.71,0:43:06.73,EN,,0,0,0,,So you'd expect to say, well, x is 3 at this point,\nDialogue: 0,0:43:06.91,0:43:07.52,EN,,0,0,0,,but it's not.\nDialogue: 0,0:43:08.53,0:43:11.15,EN,,0,0,0,,Because when I defined here, y here,\nDialogue: 0,0:43:11.79,0:43:13.45,EN,,0,0,0,,what I really defined y to be\nDialogue: 0,0:43:13.47,0:43:15.71,EN,,0,0,0,,increment of a promise to do this thing.\nDialogue: 0,0:43:17.00,0:43:18.17,EN,,0,0,0,,So I didn't look at y,\nDialogue: 0,0:43:18.36,0:43:20.25,EN,,0,0,0,,so that identity function didn't get run.\nDialogue: 0,0:43:21.56,0:43:23.20,EN,,0,0,0,,So if I type in this definition\nDialogue: 0,0:43:23.31,0:43:24.80,EN,,0,0,0,,and look at x, I'm going to get 0.\nDialogue: 0,0:43:28.36,0:43:31.20,EN,,0,0,0,,Now, if I go look at y and say what's y,\nDialogue: 0,0:43:31.52,0:43:32.43,EN,,0,0,0,,say y is 4,\nDialogue: 0,0:43:32.67,0:43:35.16,EN,,0,0,0,,looking at y, that very active looking at y\nDialogue: 0,0:43:35.29,0:43:37.42,EN,,0,0,0,,caused the identity function to be run.\nDialogue: 0,0:43:38.72,0:43:40.48,EN,,0,0,0,,And now x will get remembered as 3.\nDialogue: 0,0:43:40.74,0:43:41.87,EN,,0,0,0,,So here x will be 0.\nDialogue: 0,0:43:41.93,0:43:42.96,EN,,0,0,0,,Here, x will be 3.\nDialogue: 0,0:43:43.28,0:43:46.16,EN,,0,0,0,,That's a tiny, little, simple scenario,\nDialogue: 0,0:43:46.30,0:43:49.28,EN,,0,0,0,,but you can see what kind of a mess that's going to make\nDialogue: 0,0:43:50.36,0:43:53.34,EN,,0,0,0,,for debugging interactive programs\nDialogue: 0,0:43:54.12,0:43:55.88,EN,,0,0,0,,when you have normal-order evaluation.\nDialogue: 0,0:43:57.10,0:43:58.12,EN,,0,0,0,,It's very confusing.\nDialogue: 0,0:43:59.69,0:44:02.04,EN,,0,0,0,,But it's very confusing for a very deep reason,\nDialogue: 0,0:44:02.80,0:44:06.41,EN,,0,0,0,,which is that the whole idea of putting in delays\nDialogue: 0,0:44:06.92,0:44:08.43,EN,,0,0,0,,is that you throw away time.\nDialogue: 0,0:44:09.78,0:44:11.75,EN,,0,0,0,,That's why we can have these infinite processes.\nDialogue: 0,0:44:11.75,0:44:12.97,EN,,0,0,0,,Since we've thrown away time,\nDialogue: 0,0:44:12.99,0:44:14.27,EN,,0,0,0,,we don't have to wait for them to run,\nDialogue: 0,0:44:17.55,0:44:20.44,EN,,0,0,0,,Right? We decouple the order of events in the computer\nDialogue: 0,0:44:20.83,0:44:22.11,EN,,0,0,0,,from what we write in our programs.\nDialogue: 0,0:44:22.35,0:44:25.28,EN,,0,0,0,,But when we talk about state and set and change,\nDialogue: 0,0:44:25.48,0:44:27.42,EN,,0,0,0,,that's exactly what we do want control of.\nDialogue: 0,0:44:28.76,0:44:33.82,EN,,0,0,0,,So it's almost as if there's this fundamental contradiction in what you want.\nDialogue: 0,0:44:34.57,0:44:39.12,EN,,0,0,0,,And that brings us back to these sort of philosophical mutterings\nDialogue: 0,0:44:39.13,0:44:40.75,EN,,0,0,0,,what is it that you're trying to model\nDialogue: 0,0:44:40.78,0:44:41.77,EN,,0,0,0,,and how do you look at the world.\nDialogue: 0,0:44:42.41,0:44:44.30,EN,,0,0,0,,Or sometimes this is called the\nDialogue: 0,0:44:44.76,0:44:46.60,EN,,0,0,0,,the debate over functional programming.\nDialogue: 0,0:44:54.19,0:44:56.60,EN,,0,0,0,,A so-called purely functional language\nDialogue: 0,0:44:57.07,0:44:59.20,EN,,0,0,0,,is one that just doesn't have any side effects.\nDialogue: 0,0:45:00.44,0:45:01.63,EN,,0,0,0,,Since you have no side effects,\nDialogue: 0,0:45:01.64,0:45:03.02,EN,,0,0,0,,there's no assignment operator,\nDialogue: 0,0:45:03.34,0:45:05.72,EN,,0,0,0,,so there are no terrible consequences of it.\nDialogue: 0,0:45:06.36,0:45:07.93,EN,,0,0,0,,You can use a substitution-like thing.\nDialogue: 0,0:45:07.93,0:45:10.48,EN,,0,0,0,,Programs really are like mathematics and not like\nDialogue: 0,0:45:10.76,0:45:13.82,EN,,0,0,0,,not like models in the real world, not like objects in the real world.\nDialogue: 0,0:45:15.05,0:45:17.17,EN,,0,0,0,,There are a lot of wonderful things about functional languages.\nDialogue: 0,0:45:17.17,0:45:19.63,EN,,0,0,0,,Since there's no time, you never have any synchronization problems.\nDialogue: 0,0:45:20.64,0:45:23.72,EN,,0,0,0,,And if you want to put something into a parallel algorithm,\nDialogue: 0,0:45:24.72,0:45:28.20,EN,,0,0,0,,you can run the pieces of that parallel processing any way you want.\nDialogue: 0,0:45:29.40,0:45:31.44,EN,,0,0,0,,There's just never any synchronization to worry that,\nDialogue: 0,0:45:31.50,0:45:33.34,EN,,0,0,0,,and it's a very congenial environment for doing this.\nDialogue: 0,0:45:33.64,0:45:35.71,EN,,0,0,0,,The price is you give up assignment.\nDialogue: 0,0:45:39.10,0:45:41.32,EN,,0,0,0,,So an advocate of a functional language would say,\nDialogue: 0,0:45:41.34,0:45:43.04,EN,,0,0,0,,gee, that's just a tiny price to pay.\nDialogue: 0,0:45:44.52,0:45:46.51,EN,,0,0,0,,You probably shouldn't use assignment most of the time anyway.\nDialogue: 0,0:45:46.88,0:45:48.27,EN,,0,0,0,,And if you just give up assignment,\nDialogue: 0,0:45:48.43,0:45:51.40,EN,,0,0,0,,you can be in this much, much nicer world\nDialogue: 0,0:45:51.96,0:45:53.24,EN,,0,0,0,,than this place with objects.\nDialogue: 0,0:45:54.19,0:45:56.30,EN,,0,0,0,,Well, what's the rejoinder to that?\nDialogue: 0,0:45:56.30,0:45:58.59,EN,,0,0,0,,Remember how we got into this mess.\nDialogue: 0,0:46:00.06,0:46:03.79,EN,,0,0,0,,We started trying to model things that had local state.\nDialogue: 0,0:46:04.44,0:46:06.49,EN,,0,0,0,,So remember Gerry's random number generator.\nDialogue: 0,0:46:07.16,0:46:08.67,EN,,0,0,0,,There was this random number generator\nDialogue: 0,0:46:09.28,0:46:10.62,EN,,0,0,0,,that had some little state in it\nDialogue: 0,0:46:10.83,0:46:12.08,EN,,0,0,0,,to compute the next random number\nDialogue: 0,0:46:12.12,0:46:14.08,EN,,0,0,0,,and the next random number and the next random number.\nDialogue: 0,0:46:14.28,0:46:16.14,EN,,0,0,0,,And we wanted to hide that state away from the\nDialogue: 0,0:46:16.43,0:46:18.96,EN,,0,0,0,,the Cesaro compute pi process,\nDialogue: 0,0:46:19.84,0:46:20.92,EN,,0,0,0,,and that's why we needed set!\nDialogue: 0,0:46:20.97,0:46:22.91,EN,,0,0,0,,We wanted to package that stated modularly.\nDialogue: 0,0:46:24.07,0:46:26.36,EN,,0,0,0,,Well, a functional programming person would say,\nDialogue: 0,0:46:26.38,0:46:27.56,EN,,0,0,0,,well, you're just all wet.\nDialogue: 0,0:46:27.56,0:46:29.84,EN,,0,0,0,,I mean, you can write a perfectly good modular program.\nDialogue: 0,0:46:29.84,0:46:32.46,EN,,0,0,0,,It's just you're thinking about modularity wrong.\nDialogue: 0,0:46:33.08,0:46:35.02,EN,,0,0,0,,You're hung up in this next random number\nDialogue: 0,0:46:35.07,0:46:36.88,EN,,0,0,0,,and the next random number and the next random number.\nDialogue: 0,0:46:36.88,0:46:39.42,EN,,0,0,0,,Why don't you just say let's write a program.\nDialogue: 0,0:46:40.09,0:46:41.29,EN,,0,0,0,,Let's write an enumerator\nDialogue: 0,0:46:41.95,0:46:44.48,EN,,0,0,0,,which just generates an infinite stream of random numbers.\nDialogue: 0,0:46:49.01,0:46:50.91,EN,,0,0,0,,We can sort of have that stream all at once,\nDialogue: 0,0:46:52.64,0:46:54.54,EN,,0,0,0,,and that's going to be our source of random numbers.\nDialogue: 0,0:46:54.54,0:46:55.24,EN,,0,0,0,,And then if you like,\nDialogue: 0,0:46:55.53,0:46:57.47,EN,,0,0,0,,you can put that through some sort of processor,\nDialogue: 0,0:46:57.77,0:47:01.16,EN,,0,0,0,,which is-- I don't know-- a Cesaro test,\nDialogue: 0,0:47:04.94,0:47:06.22,EN,,0,0,0,,and that can do what it wants.\nDialogue: 0,0:47:06.88,0:47:08.56,EN,,0,0,0,,And what would come out of there\nDialogue: 0,0:47:08.72,0:47:27.45,EN,,0,0,0,,would be a stream of successive approximations to pi.\nDialogue: 0,0:47:28.14,0:47:30.65,EN,,0,0,0,,So as we looked further down this stream,\nDialogue: 0,0:47:30.76,0:47:32.38,EN,,0,0,0,,we'd tug on this Cesaro thing,\nDialogue: 0,0:47:33.12,0:47:35.36,EN,,0,0,0,,and it would pull out more and more random numbers.\nDialogue: 0,0:47:35.54,0:47:37.21,EN,,0,0,0,,And the further and further we look down the stream,\nDialogue: 0,0:47:37.23,0:47:38.96,EN,,0,0,0,,the better an approximation we'd get to pi.\nDialogue: 0,0:47:39.72,0:47:41.66,EN,,0,0,0,,And it would do exactly the same as the other computation,\nDialogue: 0,0:47:41.66,0:47:43.79,EN,,0,0,0,,except we're thinking about the modularity different.\nDialogue: 0,0:47:43.89,0:47:45.55,EN,,0,0,0,,We're saying imagine we had all that\nDialogue: 0,0:47:45.56,0:47:47.47,EN,,0,0,0,,infinite streams of random numbers all at once.\nDialogue: 0,0:47:49.28,0:47:52.24,EN,,0,0,0,,You can see the details of this procedure in the book.\nDialogue: 0,0:47:53.61,0:47:57.85,EN,,0,0,0,,But similarly, there are other things that we tend to get locked into\nDialogue: 0,0:47:58.27,0:48:01.20,EN,,0,0,0,,on this one and that one and the next one and the next one,\nDialogue: 0,0:48:01.37,0:48:02.81,EN,,0,0,0,,which don't have to be that way.\nDialogue: 0,0:48:03.28,0:48:06.54,EN,,0,0,0,,Like you might think about like a banking system,\nDialogue: 0,0:48:07.68,0:48:08.90,EN,,0,0,0,,which is a very simple idea.\nDialogue: 0,0:48:08.90,0:48:12.21,EN,,0,0,0,,Imagine we have a program that sort of represents a bank account.\nDialogue: 0,0:48:18.81,0:48:20.84,EN,,0,0,0,,The bank account might have in it--\nDialogue: 0,0:48:22.78,0:48:26.22,EN,,0,0,0,,if we looked at this in a sort of message-passing view of the world,\nDialogue: 0,0:48:26.44,0:48:28.12,EN,,0,0,0,,we'd say a bank account is an object\nDialogue: 0,0:48:28.59,0:48:31.51,EN,,0,0,0,,that has some local state in there, which is the balance, say.\nDialogue: 0,0:48:34.11,0:48:36.00,EN,,0,0,0,,And a user using this system comes\nDialogue: 0,0:48:36.44,0:48:38.14,EN,,0,0,0,,and sends a transaction request.\nDialogue: 0,0:48:39.31,0:48:41.05,EN,,0,0,0,,So the user sends a transaction request,\nDialogue: 0,0:48:41.07,0:48:42.20,EN,,0,0,0,,like deposit some money,\nDialogue: 0,0:48:42.28,0:48:43.53,EN,,0,0,0,,and the bank account maybe--\nDialogue: 0,0:48:43.92,0:48:46.78,EN,,0,0,0,,let's say the bank account always responds with what the current balance is.\nDialogue: 0,0:48:48.22,0:48:50.04,EN,,0,0,0,,The user says let's deposits some money,\nDialogue: 0,0:48:50.06,0:48:53.21,EN,,0,0,0,,and the bank account sends back a message which is the balance.\nDialogue: 0,0:48:54.35,0:48:57.42,EN,,0,0,0,,And the user says deposit some more,\nDialogue: 0,0:48:57.45,0:48:58.81,EN,,0,0,0,,and the bank account sends back a message.\nDialogue: 0,0:48:59.15,0:49:00.75,EN,,0,0,0,,And just like the random number generating\nDialogue: 0,0:49:00.78,0:49:02.12,EN,,0,0,0,,you'd say, gee, we would like to use set.\nDialogue: 0,0:49:03.20,0:49:06.88,EN,,0,0,0,,We'd like to have balance be a piece of local state inside this bank account\nDialogue: 0,0:49:06.88,0:49:08.40,EN,,0,0,0,,because we want to separate the state of the user\nDialogue: 0,0:49:08.41,0:49:09.57,EN,,0,0,0,,from the state of the bank account.\nDialogue: 0,0:49:13.28,0:49:16.42,EN,,0,0,0,,Well, that's the message-processing view.\nDialogue: 0,0:49:16.42,0:49:18.20,EN,,0,0,0,,There's a stream view with that thing,\nDialogue: 0,0:49:19.48,0:49:22.19,EN,,0,0,0,,which does the same thing without any set or side effects.\nDialogue: 0,0:49:22.74,0:49:26.73,EN,,0,0,0,,And the idea is again\nDialogue: 0,0:49:27.37,0:49:30.25,EN,,0,0,0,,we don't think about anything having local state.\nDialogue: 0,0:49:31.18,0:49:33.08,EN,,0,0,0,,We think about the bank account as something\nDialogue: 0,0:49:33.40,0:49:37.71,EN,,0,0,0,,that's going to process a stream of transaction requests.\nDialogue: 0,0:49:38.64,0:49:40.16,EN,,0,0,0,,So think about this bank account not\nDialogue: 0,0:49:40.22,0:49:42.00,EN,,0,0,0,,as something that goes message by message,\nDialogue: 0,0:49:42.44,0:49:45.85,EN,,0,0,0,,but something that takes in a stream of transaction requests\nDialogue: 0,0:49:45.87,0:49:48.49,EN,,0,0,0,,like maybe successive deposit announced.\nDialogue: 0,0:49:49.49,0:49:54.94,EN,,0,0,0,,1, 2, 2, 4, those might be successive amounts to deposit.\nDialogue: 0,0:49:55.94,0:50:02.44,EN,,0,0,0,,And then coming out of it is the successive balances 1, 3, 5, 9.\nDialogue: 0,0:50:03.77,0:50:06.14,EN,,0,0,0,,So we think of the bank account not as something that has state,\nDialogue: 0,0:50:06.40,0:50:07.26,EN,,0,0,0,,but something that acts\nDialogue: 0,0:50:08.92,0:50:10.82,EN,,0,0,0,,sort of on the infinite stream of requests.\nDialogue: 0,0:50:10.82,0:50:12.30,EN,,0,0,0,,But remember, we've thrown away time.\nDialogue: 0,0:50:12.37,0:50:14.27,EN,,0,0,0,,So what we can do is if the user's here,\nDialogue: 0,0:50:16.12,0:50:19.13,EN,,0,0,0,,we can have this infinite stream of requests\nDialogue: 0,0:50:19.18,0:50:22.54,EN,,0,0,0,,being generated one at a time coming from the user\nDialogue: 0,0:50:24.06,0:50:26.57,EN,,0,0,0,,and this transaction stream\nDialogue: 0,0:50:26.57,0:50:28.80,EN,,0,0,0,,coming back on a printer being printed one at a time.\nDialogue: 0,0:50:30.01,0:50:31.37,EN,,0,0,0,,And if we drew a little line here,\nDialogue: 0,0:50:32.56,0:50:33.08,EN,,0,0,0,,right there to the user,\nDialogue: 0,0:50:33.28,0:50:34.91,EN,,0,0,0,,the user couldn't tell that this system doesn't have state.\nDialogue: 0,0:50:36.19,0:50:37.71,EN,,0,0,0,,that this system doesn't have state.\nDialogue: 0,0:50:39.56,0:50:41.13,EN,,0,0,0,,It looks just like the other one,\nDialogue: 0,0:50:41.29,0:50:42.46,EN,,0,0,0,,but there's no state in there.\nDialogue: 0,0:50:42.84,0:50:45.87,EN,,0,0,0,,And by the way,\nDialogue: 0,0:50:46.72,0:50:49.47,EN,,0,0,0,,just to show you, here's an actual implementation\nDialogue: 0,0:50:50.52,0:50:52.30,EN,,0,0,0,,of this-- we'll call it make deposit account\nDialogue: 0,0:50:52.32,0:50:53.32,EN,,0,0,0,,because you can only deposit.\nDialogue: 0,0:50:54.17,0:50:55.77,EN,,0,0,0,,It takes an initial balance\nDialogue: 0,0:50:56.09,0:50:58.09,EN,,0,0,0,,and then a stream of deposits you might make.\nDialogue: 0,0:51:00.02,0:51:00.82,EN,,0,0,0,,And what is it?\nDialogue: 0,0:51:00.82,0:51:02.54,EN,,0,0,0,,Well, it's just cons-stream of the balance\nDialogue: 0,0:51:03.23,0:51:05.31,EN,,0,0,0,,onto make a new account stream\nDialogue: 0,0:51:06.24,0:51:07.32,EN,,0,0,0,,whose initial balance\nDialogue: 0,0:51:07.48,0:51:10.27,EN,,0,0,0,,is the old balance plus the first thing in the deposit stream\nDialogue: 0,0:51:10.86,0:51:13.40,EN,,0,0,0,,whose rest, right and,\nDialogue: 0,0:51:13.76,0:51:17.37,EN,,0,0,0,,make deposit account works on the rest of which is the tail of the deposit stream.\nDialogue: 0,0:51:18.30,0:51:23.84,EN,,0,0,0,,So there's sort of a very typical message-passing,\nDialogue: 0,0:51:23.95,0:51:27.55,EN,,0,0,0,,message-passing, object-oriented thing that's done without side effects at all.\nDialogue: 0,0:51:29.05,0:51:30.76,EN,,0,0,0,,There are very many things you can do this way.\nDialogue: 0,0:51:32.25,0:51:35.23,EN,,0,0,0,,Well, can you do everything without assignment?\nDialogue: 0,0:51:36.40,0:51:39.00,EN,,0,0,0,,Can everybody go over to purely functional languages?\nDialogue: 0,0:51:40.05,0:51:42.04,EN,,0,0,0,,Well, we don't know,\nDialogue: 0,0:51:42.27,0:51:43.44,EN,,0,0,0,,but there seem to be places\nDialogue: 0,0:51:43.92,0:51:46.03,EN,,0,0,0,,where purely functional programming breaks down.\nDialogue: 0,0:51:48.10,0:51:50.27,EN,,0,0,0,,Where it starts hurting is when you have things like this,\nDialogue: 0,0:51:50.43,0:51:52.32,EN,,0,0,0,,but you also mix it up with\nDialogue: 0,0:51:52.60,0:51:54.27,EN,,0,0,0,,the other things that we had to worry that,\nDialogue: 0,0:51:54.30,0:51:55.64,EN,,0,0,0,,which are objects and sharing\nDialogue: 0,0:51:55.90,0:51:58.52,EN,,0,0,0,,and two independent agents being the same.\nDialogue: 0,0:51:58.85,0:51:59.93,EN,,0,0,0,,So under a typical one,\nDialogue: 0,0:51:59.96,0:52:01.63,EN,,0,0,0,,suppose you want to extend this bank account.\nDialogue: 0,0:52:03.24,0:52:04.27,EN,,0,0,0,,So here's a bank account.\nDialogue: 0,0:52:12.22,0:52:14.75,EN,,0,0,0,,Bank accounts take in a stream of transaction requests\nDialogue: 0,0:52:15.20,0:52:18.44,EN,,0,0,0,,and put out streams of, say, balances or responses to that.\nDialogue: 0,0:52:18.78,0:52:20.16,EN,,0,0,0,,But suppose you want to model the fact\nDialogue: 0,0:52:20.17,0:52:24.36,EN,,0,0,0,,that this is a joint bank account between two independent people.\nDialogue: 0,0:52:25.68,0:52:28.65,EN,,0,0,0,,Right? I don't know. So suppose there are two people,\nDialogue: 0,0:52:28.97,0:52:30.96,EN,,0,0,0,,say, Bill and Dave,\nDialogue: 0,0:52:31.77,0:52:33.14,EN,,0,0,0,,who have a joint bank account.\nDialogue: 0,0:52:35.96,0:52:36.85,EN,,0,0,0,,How would you model this?\nDialogue: 0,0:52:36.88,0:52:39.80,EN,,0,0,0,,Well, you might, Bill puts out a stream of transaction requests,\nDialogue: 0,0:52:40.24,0:52:42.25,EN,,0,0,0,,and Dave puts out a stream of transaction requests,\nDialogue: 0,0:52:42.25,0:52:45.16,EN,,0,0,0,,and somehow, they have to merge into this bank account.\nDialogue: 0,0:52:45.88,0:52:47.85,EN,,0,0,0,,So what you might do is write a little stream\nDialogue: 0,0:52:47.90,0:52:50.65,EN,,0,0,0,,processing thing called merge,\nDialogue: 0,0:52:57.23,0:52:59.13,EN,,0,0,0,,which sort of takes these, merges them together,\nDialogue: 0,0:52:59.34,0:53:01.19,EN,,0,0,0,,produces a single stream for the bank account.\nDialogue: 0,0:53:01.19,0:53:02.99,EN,,0,0,0,,Now they're both talking to the same bank account.\nDialogue: 0,0:53:03.61,0:53:05.48,EN,,0,0,0,,That's all great, but how do you write merge?\nDialogue: 0,0:53:05.93,0:53:08.24,EN,,0,0,0,,What, What's this procedure merge?\nDialogue: 0,0:53:09.73,0:53:11.42,EN,,0,0,0,,You want to do something that's reasonable.\nDialogue: 0,0:53:12.38,0:53:13.80,EN,,0,0,0,,Your first guess might be to say,\nDialogue: 0,0:53:13.80,0:53:16.68,EN,,0,0,0,,well, we'll take alternate requests from Bill and Dave.\nDialogue: 0,0:53:18.19,0:53:20.97,EN,,0,0,0,,But what happens if But what happens if suddenly in the middle thing\nDialogue: 0,0:53:21.18,0:53:23.08,EN,,0,0,0,,Dave goes away on vacation for two years?\nDialogue: 0,0:53:24.15,0:53:25.40,EN,,0,0,0,,Then Bill's sort of stuck.\nDialogue: 0,0:53:27.69,0:53:29.75,EN,,0,0,0,,So what you want to do is-- well, it's hard to describe.\nDialogue: 0,0:53:29.75,0:53:33.64,EN,,0,0,0,,What you want to do is what people call fair merge.\nDialogue: 0,0:53:38.41,0:53:40.17,EN,,0,0,0,,The idea of fair merge is\nDialogue: 0,0:53:40.73,0:53:42.46,EN,,0,0,0,,is it sort of should do them alternately,\nDialogue: 0,0:53:42.49,0:53:43.92,EN,,0,0,0,,but if there's nothing waiting here,\nDialogue: 0,0:53:43.96,0:53:44.91,EN,,0,0,0,,it should take one twice.\nDialogue: 0,0:53:46.01,0:53:48.45,EN,,0,0,0,,Notice I can't even say that without talking about time.\nDialogue: 0,0:53:51.30,0:53:56.41,EN,,0,0,0,,So one of the other active researcher areas in functional languages\nDialogue: 0,0:53:56.43,0:53:59.48,EN,,0,0,0,,is inventing little things like fair merge\nDialogue: 0,0:54:00.35,0:54:01.31,EN,,0,0,0,,maybe some others,\nDialogue: 0,0:54:01.56,0:54:06.25,EN,,0,0,0,,which will take the places where I used to need side effects and objects\nDialogue: 0,0:54:06.80,0:54:10.52,EN,,0,0,0,,and sort of hide them away in some very well-defined modules of the system\nDialogue: 0,0:54:10.86,0:54:13.50,EN,,0,0,0,,so that all the problems of assignment\nDialogue: 0,0:54:13.52,0:54:15.34,EN,,0,0,0,,don't sort of leak out all over the system but\nDialogue: 0,0:54:15.40,0:54:17.88,EN,,0,0,0,,are captured in some fairly well-understood things.\nDialogue: 0,0:54:20.78,0:54:22.70,EN,,0,0,0,,More generally, I think what you're seeing\nDialogue: 0,0:54:23.12,0:54:24.06,EN,,0,0,0,,is that we're running across\nDialogue: 0,0:54:24.08,0:54:26.67,EN,,0,0,0,,what I think is a very basic problem in computer science,\nDialogue: 0,0:54:26.97,0:54:27.82,EN,,0,0,0,,which is how to\nDialogue: 0,0:54:28.24,0:54:32.03,EN,,0,0,0,,how to define languages that somehow can talk about delayed evaluation\nDialogue: 0,0:54:34.14,0:54:35.08,EN,,0,0,0,,But also\nDialogue: 0,0:54:35.87,0:54:38.25,EN,,0,0,0,,be able to reflect this view that there are objects in the world.\nDialogue: 0,0:54:38.36,0:54:40.36,EN,,0,0,0,,How do we somehow get both?\nDialogue: 0,0:54:41.23,0:54:43.04,EN,,0,0,0,,And I think that's a very hard problem.\nDialogue: 0,0:54:43.04,0:54:45.52,EN,,0,0,0,,And it may be that it's a very hard problem\nDialogue: 0,0:54:45.85,0:54:48.17,EN,,0,0,0,,that has almost nothing to do with computer science,\nDialogue: 0,0:54:48.59,0:54:50.24,EN,,0,0,0,,that it really is a problem having to do with\nDialogue: 0,0:54:50.27,0:54:52.73,EN,,0,0,0,,two very incompatible ways of looking at the world.\nDialogue: 0,0:54:54.14,0:54:54.72,EN,,0,0,0,,OK, questions?\nDialogue: 0,0:55:17.55,0:55:19.20,EN,,0,0,0,,AUDIENCE: You mentioned earlier that\nDialogue: 0,0:55:20.11,0:55:21.32,EN,,0,0,0,,once you introduce assignment,\nDialogue: 0,0:55:21.32,0:55:25.89,EN,,0,0,0,,the general rule for using the substitution model is you can't.\nDialogue: 0,0:55:25.89,0:55:27.57,EN,,0,0,0,,Unless you're very careful, you can't.\nDialogue: 0,0:55:27.57,0:55:27.96,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:55:28.26,0:55:33.28,EN,,0,0,0,,AUDIENCE: Is there a set of techniques or a set of guidelines\nDialogue: 0,0:55:33.42,0:55:35.92,EN,,0,0,0,,for localizing the effects of assignment\nDialogue: 0,0:55:36.52,0:55:40.30,EN,,0,0,0,,so that the very careful becomes defined?\nDialogue: 0,0:55:40.30,0:55:42.60,EN,,0,0,0,,PROFESSOR: I don't know. Um...\nDialogue: 0,0:55:42.89,0:55:43.58,EN,,0,0,0,,Let me think.\nDialogue: 0,0:55:45.43,0:55:48.94,EN,,0,0,0,,Well, certainly, there was an assignment inside memo proc,\nDialogue: 0,0:55:50.12,0:55:51.48,EN,,0,0,0,,but that was sort of hidden away.\nDialogue: 0,0:55:51.48,0:55:53.00,EN,,0,0,0,,It ended up not making any difference.\nDialogue: 0,0:55:53.48,0:55:56.44,EN,,0,0,0,,Part of the reason for that is once this thing triggered\nDialogue: 0,0:55:57.15,0:55:58.83,EN,,0,0,0,,that it had run and gotten an answer,\nDialogue: 0,0:55:58.83,0:56:00.06,EN,,0,0,0,,that answer will never change.\nDialogue: 0,0:56:00.60,0:56:02.33,EN,,0,0,0,,So that was sort of a one-time assignment.\nDialogue: 0,0:56:02.35,0:56:03.85,EN,,0,0,0,,So one very general thing you can do\nDialogue: 0,0:56:04.30,0:56:06.35,EN,,0,0,0,,is if you only do what's called a one-time assignment\nDialogue: 0,0:56:08.04,0:56:09.24,EN,,0,0,0,,and never change anything,\nDialogue: 0,0:56:09.63,0:56:10.54,EN,,0,0,0,,then you can do better.\nDialogue: 0,0:56:11.25,0:56:14.12,EN,,0,0,0,,One of the problems in this merge thing, people have--\nDialogue: 0,0:56:14.67,0:56:18.32,EN,,0,0,0,,people have-- let me see if this is right.\nDialogue: 0,0:56:18.49,0:56:21.55,EN,,0,0,0,,I think it's true that with fair merge,\nDialogue: 0,0:56:22.25,0:56:26.09,EN,,0,0,0,,with just fair merge, you can begin effectively simulating\nDialogue: 0,0:56:27.02,0:56:28.89,EN,,0,0,0,,assignment in the rest of the language.\nDialogue: 0,0:56:30.82,0:56:33.29,EN,,0,0,0,,It seems like anything you do to go outside--\nDialogue: 0,0:56:33.50,0:56:35.50,EN,,0,0,0,,I'm not quite sure that's true for fair merge,\nDialogue: 0,0:56:35.53,0:56:39.31,EN,,0,0,0,,but it's true of a little bit more general things that people have been doing.\nDialogue: 0,0:56:39.52,0:56:41.34,EN,,0,0,0,,So it might be that any little bit you put in,\nDialogue: 0,0:56:41.61,0:56:44.14,EN,,0,0,0,,suddenly if they allow you to build arbitrary stuff,\nDialogue: 0,0:56:44.16,0:56:46.51,EN,,0,0,0,,it's almost as bad as having assignment altogether.\nDialogue: 0,0:56:47.97,0:56:50.67,EN,,0,0,0,,But that's an area that people are thinking about now.\nDialogue: 0,0:56:51.59,0:56:54.30,EN,,0,0,0,,AUDIENCE: I guess I don't see the problem here with merge\nDialogue: 0,0:56:54.83,0:56:59.20,EN,,0,0,0,,if, you know the sense, I call Bill, if Bill is a procedure,\nDialogue: 0,0:56:59.21,0:57:02.41,EN,,0,0,0,,then Bill is going to increment the bank account\nDialogue: 0,0:57:02.44,0:57:04.73,EN,,0,0,0,,or build the list that 's going to put in the next element.\nDialogue: 0,0:57:04.73,0:57:06.84,EN,,0,0,0,,If I call Dave twice in a row, that will do that.\nDialogue: 0,0:57:07.17,0:57:09.35,EN,,0,0,0,,I'm not sure where fair merge has to be involved.\nDialogue: 0,0:57:09.35,0:57:11.20,EN,,0,0,0,,PROFESSOR: The problem is imagine these really as people.\nDialogue: 0,0:57:11.20,0:57:14.20,EN,,0,0,0,,See, here I have the user who's interacting with this bank account.\nDialogue: 0,0:57:14.85,0:57:17.07,EN,,0,0,0,,Put in a request, get an answer. Put in a request, get an answer.\nDialogue: 0,0:57:17.20,0:57:17.56,EN,,0,0,0,,AUDIENCE: Right.\nDialogue: 0,0:57:18.20,0:57:20.62,EN,,0,0,0,,PROFESSOR: But if the only way I can process request\nDialogue: 0,0:57:20.65,0:57:22.25,EN,,0,0,0,,is to alternate them from two people--\nDialogue: 0,0:57:22.91,0:57:24.22,EN,,0,0,0,,AUDIENCE: Well, why would you alternate them?\nDialogue: 0,0:57:24.22,0:57:25.23,EN,,0,0,0,,PROFESSOR: Why don't I?\nDialogue: 0,0:57:25.45,0:57:25.80,EN,,0,0,0,,AUDIENCE: Yes. Why do you?\nDialogue: 0,0:57:26.60,0:57:27.72,EN,,0,0,0,,PROFESSOR: Think of them as real people, right?\nDialogue: 0,0:57:27.76,0:57:28.97,EN,,0,0,0,,This guy might go away for a year.\nDialogue: 0,0:57:29.28,0:57:31.74,EN,,0,0,0,,And you're sitting here at the bank account window,\nDialogue: 0,0:57:32.43,0:57:33.72,EN,,0,0,0,,and you can't put in two requests\nDialogue: 0,0:57:33.74,0:57:34.94,EN,,0,0,0,,because it's waiting for this guy.\nDialogue: 0,0:57:35.48,0:57:37.07,EN,,0,0,0,,AUDIENCE: Why does it have to be waiting for one?\nDialogue: 0,0:57:37.38,0:57:39.11,EN,,0,0,0,,PROFESSOR: Because it's trying to compute a function.\nDialogue: 0,0:57:39.11,0:57:40.92,EN,,0,0,0,,I have to define a function.\nDialogue: 0,0:57:41.72,0:57:42.60,EN,,0,0,0,,Another way to say that\nDialogue: 0,0:57:42.84,0:57:44.99,EN,,0,0,0,,is the answer to what comes out of this merge box\nDialogue: 0,0:57:46.24,0:57:49.48,EN,,0,0,0,,is not a function of what goes in.\nDialogue: 0,0:57:51.69,0:57:53.49,EN,,0,0,0,,Because, see, what would the function be?\nDialogue: 0,0:57:53.49,0:57:58.86,EN,,0,0,0,,Suppose he puts in 1, 1, 1, 1,\nDialogue: 0,0:57:59.82,0:58:02.78,EN,,0,0,0,,and he puts in 2, 2, 2, 2.\nDialogue: 0,0:58:03.47,0:58:04.80,EN,,0,0,0,,What's the answer supposed to be?\nDialogue: 0,0:58:05.58,0:58:08.74,EN,,0,0,0,,It's not good enough to say it's 1, 2, 1, 2, 1, 2.\nDialogue: 0,0:58:08.74,0:58:09.39,EN,,0,0,0,,AUDIENCE: I understand.\nDialogue: 0,0:58:09.39,0:58:11.56,EN,,0,0,0,,But when Bill puts in 1, 1 goes in.\nDialogue: 0,0:58:11.56,0:58:13.95,EN,,0,0,0,,When Dave puts in 2, twice 2 goes in twice.\nDialogue: 0,0:58:13.95,0:58:14.73,EN,,0,0,0,,AUDIENCE: When Bill puts in--\nDialogue: 0,0:58:14.76,0:58:15.08,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:58:15.13,0:58:18.43,EN,,0,0,0,,AUDIENCE: Why can't it be hooked to the time of the input--\nDialogue: 0,0:58:18.59,0:58:20.06,EN,,0,0,0,,the actual procedural--\nDialogue: 0,0:58:20.12,0:58:21.84,EN,,0,0,0,,PROFESSOR: Because I don't have time.\nDialogue: 0,0:58:23.98,0:58:26.90,EN,,0,0,0,,See, all I can say is I'm going to define a function.\nDialogue: 0,0:58:26.90,0:58:28.15,EN,,0,0,0,,I don't have time.\nDialogue: 0,0:58:32.00,0:58:34.19,EN,,0,0,0,,There's no concept if it's going to alternate,\nDialogue: 0,0:58:34.19,0:58:36.54,EN,,0,0,0,,except if nobody's there, it's going to wait a while for him.\nDialogue: 0,0:58:38.42,0:58:41.36,EN,,0,0,0,,It's just going to say I have the stream of requests,\nDialogue: 0,0:58:41.74,0:58:43.34,EN,,0,0,0,,the timeless infinite streams\nDialogue: 0,0:58:43.36,0:58:45.29,EN,,0,0,0,,of all the requests that Dave would have made, right?\nDialogue: 0,0:58:47.55,0:58:50.41,EN,,0,0,0,,And the timeless infinite stream of all the requests Bill would have made,\nDialogue: 0,0:58:50.54,0:58:51.69,EN,,0,0,0,,and I want to operate on them.\nDialogue: 0,0:58:51.69,0:58:53.51,EN,,0,0,0,,See, that's how this bank account is working.\nDialogue: 0,0:58:56.71,0:58:57.58,EN,,0,0,0,,And the problem is\nDialogue: 0,0:58:57.61,0:59:00.75,EN,,0,0,0,,that these poor people who are sitting at the bank account windows\nDialogue: 0,0:59:00.76,0:59:03.82,EN,,0,0,0,,have the misfortune to exist in time.\nDialogue: 0,0:59:05.29,0:59:07.13,EN,,0,0,0,,They don't see their infinite stream\nDialogue: 0,0:59:07.69,0:59:09.53,EN,,0,0,0,,of all the requests they would have ever made.\nDialogue: 0,0:59:10.07,0:59:11.55,EN,,0,0,0,,They're waiting now, and they want an answer.\nDialogue: 0,0:59:14.48,0:59:15.76,EN,,0,0,0,,So if you're sitting there--\nDialogue: 0,0:59:16.24,0:59:20.86,EN,,0,0,0,,if this is the screen operation on some time-sharing system\nDialogue: 0,0:59:21.52,0:59:22.60,EN,,0,0,0,,and it's working functionally,\nDialogue: 0,0:59:22.64,0:59:24.59,EN,,0,0,0,,you want an answer then when you talk the character.\nDialogue: 0,0:59:25.29,0:59:27.42,EN,,0,0,0,,You don't want it to have to wait for everybody in the whole system\nDialogue: 0,0:59:27.45,0:59:29.92,EN,,0,0,0,,to have typed one character before it can get around to service you.\nDialogue: 0,0:59:30.91,0:59:31.92,EN,,0,0,0,,So that's the problem.\nDialogue: 0,0:59:34.00,0:59:36.38,EN,,0,0,0,,I mean, the fact that people live in time, apparently.\nDialogue: 0,0:59:37.21,0:59:38.62,EN,,0,0,0,,If they didn't, it wouldn't be a problem.\nDialogue: 0,0:59:49.10,0:59:51.02,EN,,0,0,0,,AUDIENCE: I'm afraid I miss the point of\nDialogue: 0,0:59:51.08,0:59:54.24,EN,,0,0,0,,having no time in this banking transaction.\nDialogue: 0,0:59:54.74,0:59:56.65,EN,,0,0,0,,Isn't time very important?\nDialogue: 0,0:59:56.88,0:59:59.05,EN,,0,0,0,,For instance, the sequence of events.\nDialogue: 0,0:59:59.95,1:00:05.02,EN,,0,0,0,,As if, If Dave take out $100, and then\nDialogue: 0,1:00:06.30,1:00:08.40,EN,,0,0,0,,then the timing sequence should be important.\nDialogue: 0,1:00:08.40,1:00:10.86,EN,,0,0,0,,How do you treat transactions as streams?\nDialogue: 0,1:00:11.26,1:00:14.26,EN,,0,0,0,,PROFESSOR: Well, that's the thing I'm saying.\nDialogue: 0,1:00:14.26,1:00:15.61,EN,,0,0,0,,This is an example where you can't.\nDialogue: 0,1:00:17.51,1:00:18.12,EN,,0,0,0,,You can't.\nDialogue: 0,1:00:18.16,1:00:20.08,EN,,0,0,0,,What goes, The point is what comes out of here\nDialogue: 0,1:00:20.24,1:00:21.88,EN,,0,0,0,,is simply not a function of the stream going in here\nDialogue: 0,1:00:21.92,1:00:23.60,EN,,0,0,0,,going in here and the stream going in here.\nDialogue: 0,1:00:24.17,1:00:25.98,EN,,0,0,0,,It's a function of the stream going in here\nDialogue: 0,1:00:26.19,1:00:27.26,EN,,0,0,0,,and the stream going in here\nDialogue: 0,1:00:27.36,1:00:29.07,EN,,0,0,0,,and some kind of information about time,\nDialogue: 0,1:00:29.37,1:00:32.36,EN,,0,0,0,,which is precisely what a normal-order language won't let you say.\nDialogue: 0,1:00:34.81,1:00:37.95,EN,,0,0,0,,AUDIENCE: In order to brings this back into a more functional perspective,\nDialogue: 0,1:00:38.54,1:00:42.04,EN,,0,0,0,,could we just explicitly time stamp all the inputs from Bill and Dave\nDialogue: 0,1:00:42.54,1:00:46.40,EN,,0,0,0,,and define fair merge to just be the sort on those time stamps?\nDialogue: 0,1:00:48.41,1:00:49.55,EN,,0,0,0,,PROFESSOR: Yeah, you can do that.\nDialogue: 0,1:00:49.55,1:00:50.60,EN,,0,0,0,,You can do that sort of thing.\nDialogue: 0,1:00:50.60,1:00:52.56,EN,,0,0,0,,Another thing you could say is imagine\nDialogue: 0,1:00:52.76,1:00:54.44,EN,,0,0,0,,that really what this function is,\nDialogue: 0,1:00:54.78,1:00:56.88,EN,,0,0,0,,is that it does a read every microsecond,\nDialogue: 0,1:00:58.86,1:00:59.93,EN,,0,0,0,,and then if there's none there,\nDialogue: 0,1:00:59.93,1:01:00.97,EN,,0,0,0,,that's considered an empty one.\nDialogue: 0,1:01:00.97,1:01:03.39,EN,,0,0,0,,That's about equivalent to what you said.\nDialogue: 0,1:01:03.61,1:01:06.08,EN,,0,0,0,,And yes, you can do that, but that's a glitch.\nDialogue: 0,1:01:07.11,1:01:10.14,EN,,0,0,0,,So it's not quite only implementation we're worried about.\nDialogue: 0,1:01:10.76,1:01:12.73,EN,,0,0,0,,We're worried about expressive power in the language,\nDialogue: 0,1:01:12.75,1:01:14.67,EN,,0,0,0,,and what we're running across is a real mismatch\nDialogue: 0,1:01:14.99,1:01:17.44,EN,,0,0,0,,between what we can say easily and what we'd like to say.\nDialogue: 0,1:01:19.88,1:01:22.01,EN,,0,0,0,,AUDIENCE: It sounds like where we're getting hung up with that\nDialogue: 0,1:01:22.06,1:01:26.09,EN,,0,0,0,,one input from both Bill and Dave at the same time.\nDialogue: 0,1:01:26.12,1:01:28.43,EN,,0,0,0,,PROFESSOR: It's not quite one, but it's anything you define.\nDialogue: 0,1:01:28.53,1:01:30.57,EN,,0,0,0,,So you can say Dave can go twice as often,\nDialogue: 0,1:01:30.72,1:01:32.32,EN,,0,0,0,,but if anything you predefine,\nDialogue: 0,1:01:32.68,1:01:33.87,EN,,0,0,0,,it's not the right thing.\nDialogue: 0,1:01:36.11,1:01:40.70,EN,,0,0,0,,You can't decide at some particular function of their input requests.\nDialogue: 0,1:01:41.93,1:01:43.37,EN,,0,0,0,,Worse yet, I mean, worse yet,\nDialogue: 0,1:01:44.12,1:01:45.72,EN,,0,0,0,,there are things that even merge can't do.\nDialogue: 0,1:01:47.29,1:01:49.69,EN,,0,0,0,,One thing you might want to do that's even more general is suddenly\nDialogue: 0,1:01:50.24,1:01:52.47,EN,,0,0,0,,you add somebody else to this bank account system.\nDialogue: 0,1:01:52.47,1:01:54.51,EN,,0,0,0,,You go and you add John to this bank account system.\nDialogue: 0,1:01:56.03,1:01:58.89,EN,,0,0,0,,And now there's yet another stream that's going to come into the picture\nDialogue: 0,1:01:58.91,1:02:00.70,EN,,0,0,0,,at some time which we haven't prespecified.\nDialogue: 0,1:02:02.04,1:02:04.00,EN,,0,0,0,,So that's something even fair merge can't do,\nDialogue: 0,1:02:04.00,1:02:08.25,EN,,0,0,0,,and they're things called-- I forget-- manager or something.\nDialogue: 0,1:02:08.86,1:02:11.79,EN,,0,0,0,,That's a generalization of fair merge to allow that.\nDialogue: 0,1:02:11.79,1:02:13.98,EN,,0,0,0,,There's a whole sort of research discipline saying\nDialogue: 0,1:02:14.00,1:02:16.30,EN,,0,0,0,,how far can you push this functional perspective\nDialogue: 0,1:02:16.59,1:02:18.72,EN,,0,0,0,,by adding more and more mechanism?\nDialogue: 0,1:02:19.58,1:02:21.79,EN,,0,0,0,,And how far does that go before the whole thing breaks down\nDialogue: 0,1:02:21.82,1:02:23.40,EN,,0,0,0,,and you might as well been using set anyway.\nDialogue: 0,1:02:25.98,1:02:28.00,EN,,0,0,0,,AUDIENCE: But not automatic deposit.\nDialogue: 0,1:02:39.32,1:02:40.49,EN,,0,0,0,,PROFESSOR: OK, thank you.\n"
  },
  {
    "path": "Ass/lec7a.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 601\nActive Line: 612\nVideo Position: 62464\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:15.79,0:00:17.32,EN,,0,0,0,,PROFESSOR: Well today we're going to learn about something\nDialogue: 0,0:00:17.52,0:00:18.41,EN,,0,0,0,,quite amazing.\nDialogue: 0,0:00:19.20,0:00:21.88,EN,,0,0,0,,We're going to understand what we mean by a program\nDialogue: 0,0:00:22.59,0:00:25.21,EN,,0,0,0,,a little bit more profoundly than we have up till now.\nDialogue: 0,0:00:26.80,0:00:29.12,EN,,0,0,0,,Up till now, we've been thinking\nDialogue: 0,0:00:29.26,0:00:32.09,EN,,0,0,0,,programs as describing machines.\nDialogue: 0,0:00:32.72,0:00:37.21,EN,,0,0,0,,So for example, looking at this still store\nDialogue: 0,0:00:37.93,0:00:41.77,EN,,0,0,0,,we see here is a program for factorial.\nDialogue: 0,0:00:42.80,0:00:47.31,EN,,0,0,0,,And what it is, is a character string description, if you will,\nDialogue: 0,0:00:47.66,0:00:51.98,EN,,0,0,0,,of the wiring diagram of a potentially infinite machine.\nDialogue: 0,0:00:52.49,0:00:54.80,EN,,0,0,0,,And we can look at that a little bit and just see the idea.\nDialogue: 0,0:00:55.13,0:00:58.20,EN,,0,0,0,,That this is a sort of compact notation which says,\nDialogue: 0,0:00:58.54,0:01:00.17,EN,,0,0,0,,if n is 0, the result is one.\nDialogue: 0,0:01:00.17,0:01:02.00,EN,,0,0,0,,Well here comes n coming into this machine,\nDialogue: 0,0:01:02.33,0:01:03.52,EN,,0,0,0,,and if it's 0,\nDialogue: 0,0:01:03.74,0:01:05.20,EN,,0,0,0,,then I control this switch\nDialogue: 0,0:01:05.47,0:01:08.20,EN,,0,0,0,,in such a way that the switch allows the output to be one.\nDialogue: 0,0:01:09.34,0:01:10.08,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:01:10.38,0:01:12.83,EN,,0,0,0,,it's n times factorial of n minus one.\nDialogue: 0,0:01:12.97,0:01:15.13,EN,,0,0,0,,Well, I'm computing factorial of n minus one\nDialogue: 0,0:01:15.29,0:01:16.68,EN,,0,0,0,,and multiplying that by n,\nDialogue: 0,0:01:16.84,0:01:18.91,EN,,0,0,0,,in the case that it's not 0,\nDialogue: 0,0:01:18.91,0:01:20.60,EN,,0,0,0,,this switch makes the output come from there.\nDialogue: 0,0:01:21.90,0:01:22.32,EN,,0,0,0,,Of course,\nDialogue: 0,0:01:22.36,0:01:25.13,EN,,0,0,0,,this is a machine with a potentially infinite number of parts,\nDialogue: 0,0:01:25.48,0:01:28.12,EN,,0,0,0,,because factorial occurs within factorial,\nDialogue: 0,0:01:28.43,0:01:30.17,EN,,0,0,0,,so we don't know how deep it has to be.\nDialogue: 0,0:01:31.07,0:01:33.55,EN,,0,0,0,,But that's basically what our notation\nDialogue: 0,0:01:34.22,0:01:37.69,EN,,0,0,0,,for programs really means to us at this point.\nDialogue: 0,0:01:38.31,0:01:40.59,EN,,0,0,0,,It's a character string description, if you will,\nDialogue: 0,0:01:41.28,0:01:44.16,EN,,0,0,0,,of a wiring diagram that could also be drawn some other way.\nDialogue: 0,0:01:44.90,0:01:46.60,EN,,0,0,0,,And, in fact, many people have proposed to me,\nDialogue: 0,0:01:46.84,0:01:49.04,EN,,0,0,0,,programming languages look graphical like this.\nDialogue: 0,0:01:49.49,0:01:51.80,EN,,0,0,0,,I'm not sure I believe there are many advantages.\nDialogue: 0,0:01:52.00,0:01:53.79,EN,,0,0,0,,The major disadvantage, of course,\nDialogue: 0,0:01:53.80,0:01:55.63,EN,,0,0,0,,is that it takes up more space on a page,\nDialogue: 0,0:01:55.96,0:01:59.95,EN,,0,0,0,,and, therefore, it's harder to pack into a listing or to edit very well.\nDialogue: 0,0:02:01.34,0:02:02.16,EN,,0,0,0,,But in any case,\nDialogue: 0,0:02:03.58,0:02:05.15,EN,,0,0,0,,there's something very remarkable\nDialogue: 0,0:02:05.18,0:02:07.05,EN,,0,0,0,,that can happen in the computation world\nDialogue: 0,0:02:07.64,0:02:10.64,EN,,0,0,0,,which is that you can have something called a universal machine.\nDialogue: 0,0:02:10.73,0:02:15.24,EN,,0,0,0,,If we look at the second slide,\nDialogue: 0,0:02:16.04,0:02:17.18,EN,,0,0,0,,what we see is\nDialogue: 0,0:02:18.14,0:02:19.88,EN,,0,0,0,,a special machine called eval.\nDialogue: 0,0:02:21.26,0:02:22.86,EN,,0,0,0,,There is a machine called eval,\nDialogue: 0,0:02:22.88,0:02:24.24,EN,,0,0,0,,and I'm going to show it to you today.\nDialogue: 0,0:02:25.82,0:02:26.67,EN,,0,0,0,,It's very simple.\nDialogue: 0,0:02:27.78,0:02:30.80,EN,,0,0,0,,What is remarkable is that it will fit on the blackboard.\nDialogue: 0,0:02:33.35,0:02:35.79,EN,,0,0,0,,However, eval is a machine\nDialogue: 0,0:02:36.00,0:02:39.84,EN,,0,0,0,,which takes as input a description of another machine.\nDialogue: 0,0:02:40.45,0:02:42.12,EN,,0,0,0,,It could take the wiring diagram\nDialogue: 0,0:02:42.40,0:02:45.58,EN,,0,0,0,,of a factorial machine as input.\nDialogue: 0,0:02:46.49,0:02:47.66,EN,,0,0,0,,Having done so,\nDialogue: 0,0:02:48.49,0:02:52.57,EN,,0,0,0,,it becomes a simulator for the factorial machine\nDialogue: 0,0:02:53.13,0:02:53.79,EN,,0,0,0,,such that,\nDialogue: 0,0:02:54.16,0:02:56.36,EN,,0,0,0,,if you put a six in, out comes a 720.\nDialogue: 0,0:02:58.91,0:03:01.68,EN,,0,0,0,,That's a very remarkable sort of machine.\nDialogue: 0,0:03:02.13,0:03:03.58,EN,,0,0,0,,And the most amazing part of it\nDialogue: 0,0:03:03.77,0:03:05.13,EN,,0,0,0,,it is that it fits on a blackboard.\nDialogue: 0,0:03:05.59,0:03:06.65,EN,,0,0,0,,By contrast,\nDialogue: 0,0:03:07.32,0:03:10.44,EN,,0,0,0,,one could imagine in the analog electronics world\nDialogue: 0,0:03:11.55,0:03:12.86,EN,,0,0,0,,a very different machine.\nDialogue: 0,0:03:14.57,0:03:16.33,EN,,0,0,0,,a machine where, a machine\nDialogue: 0,0:03:16.52,0:03:18.81,EN,,0,0,0,,which also was, in some sense, universal,\nDialogue: 0,0:03:19.26,0:03:23.12,EN,,0,0,0,,where you gave a circuit diagram as one of the inputs,\nDialogue: 0,0:03:23.82,0:03:25.74,EN,,0,0,0,,for example, of this little low-pass filter,\nDialogue: 0,0:03:26.01,0:03:27.48,EN,,0,0,0,,one-pole low-pass filter.\nDialogue: 0,0:03:28.05,0:03:29.53,EN,,0,0,0,,And you can imagine that\nDialogue: 0,0:03:29.71,0:03:33.15,EN,,0,0,0,,you could, for example, scan this out-- the scan lines\nDialogue: 0,0:03:34.43,0:03:37.13,EN,,0,0,0,,Right? are the signal that's describing\nDialogue: 0,0:03:37.39,0:03:40.40,EN,,0,0,0,,what this machine is to simulate--\nDialogue: 0,0:03:40.78,0:03:43.39,EN,,0,0,0,,then the analog of eval which is made out of electrical circuits,\nDialogue: 0,0:03:43.68,0:03:45.15,EN,,0,0,0,,which configure itself into a filter\nDialogue: 0,0:03:45.18,0:03:48.04,EN,,0,0,0,,has the frequency response specified by the circuit diagram.\nDialogue: 0,0:03:49.89,0:03:51.48,EN,,0,0,0,,That's a very hard machine to make,\nDialogue: 0,0:03:51.61,0:03:54.06,EN,,0,0,0,,and, surely, there's no chance that I could put it on a blackboard.\nDialogue: 0,0:03:55.67,0:03:57.58,EN,,0,0,0,,So we're going to see an amazing thing today.\nDialogue: 0,0:03:58.43,0:04:00.81,EN,,0,0,0,,We're going to see, on the blackboard,\nDialogue: 0,0:04:01.16,0:04:02.49,EN,,0,0,0,,the universal machine.\nDialogue: 0,0:04:02.79,0:04:04.41,EN,,0,0,0,,And we'll see that among other things,\nDialogue: 0,0:04:04.52,0:04:05.80,EN,,0,0,0,,it's extremely simple.\nDialogue: 0,0:04:06.78,0:04:08.75,EN,,0,0,0,,Now, we're getting very close\nDialogue: 0,0:04:09.08,0:04:10.97,EN,,0,0,0,,the real spirit in the computer at this point.\nDialogue: 0,0:04:11.28,0:04:14.62,EN,,0,0,0,,So I have to show a certain amount of reverence and respect,\nDialogue: 0,0:04:15.18,0:04:17.32,EN,,0,0,0,,so I'm going to wear a suit jacket for the only time\nDialogue: 0,0:04:17.52,0:04:19.29,EN,,0,0,0,,that you'll ever see me wear a suit jacket here.\nDialogue: 0,0:04:20.47,0:04:22.73,EN,,0,0,0,,And I think I'm also going to\nDialogue: 0,0:04:23.55,0:04:26.70,EN,,0,0,0,,put on an appropriate hat for the occasion.\nDialogue: 0,0:04:28.78,0:04:31.44,EN,,0,0,0,,Now, this is a lecturer which I have to warn you--\nDialogue: 0,0:04:34.14,0:04:36.91,EN,,0,0,0,,let's see, normally, people under 40\nDialogue: 0,0:04:37.16,0:04:38.49,EN,,0,0,0,,and who don't have several children\nDialogue: 0,0:04:38.67,0:04:40.49,EN,,0,0,0,,are advised to be careful.\nDialogue: 0,0:04:40.49,0:04:41.96,EN,,0,0,0,,If they're really worried, they should leave.\nDialogue: 0,0:04:43.34,0:04:45.56,EN,,0,0,0,,Because there's a certain amount of\nDialogue: 0,0:04:45.72,0:04:47.13,EN,,0,0,0,,mysticism that will appear here\nDialogue: 0,0:04:47.74,0:04:51.05,EN,,0,0,0,,which may be disturbing and cause trouble in your minds.\nDialogue: 0,0:04:51.82,0:04:54.28,EN,,0,0,0,,Well in any case, let's see,\nDialogue: 0,0:04:55.71,0:05:01.10,EN,,0,0,0,,I wish to write for you the evaluator for Lisp.\nDialogue: 0,0:05:02.51,0:05:04.28,EN,,0,0,0,,Now the evaluator isn't very complicated.\nDialogue: 0,0:05:05.02,0:05:07.63,EN,,0,0,0,,It's very much like all the programs we've seen already.\nDialogue: 0,0:05:08.24,0:05:09.48,EN,,0,0,0,,That's the amazing part of it.\nDialogue: 0,0:05:10.86,0:05:13.10,EN,,0,0,0,,It's going to be-- and I'm going to write it right here--\nDialogue: 0,0:05:15.28,0:05:16.62,EN,,0,0,0,,it's a program called eval.\nDialogue: 0,0:05:22.90,0:05:26.24,EN,,0,0,0,,And it's a procedure of two arguments\nDialogue: 0,0:05:26.28,0:05:29.44,EN,,0,0,0,,expression and an environment.\nDialogue: 0,0:05:31.86,0:05:33.79,EN,,0,0,0,,And like every interesting procedure,\nDialogue: 0,0:05:34.01,0:05:35.13,EN,,0,0,0,,it's a case analysis.\nDialogue: 0,0:05:40.46,0:05:41.87,EN,,0,0,0,,But before I start on this,\nDialogue: 0,0:05:42.52,0:05:43.90,EN,,0,0,0,,I want to tell you some things.\nDialogue: 0,0:05:44.44,0:05:46.06,EN,,0,0,0,,The program we're going to write on the blackboard\nDialogue: 0,0:05:46.56,0:05:50.24,EN,,0,0,0,,is ugly, dirty, disgusting,\nDialogue: 0,0:05:50.94,0:05:53.16,EN,,0,0,0,,not the way I would write this is a professional.\nDialogue: 0,0:05:54.32,0:05:56.57,EN,,0,0,0,,It is written with concrete syntax,\nDialogue: 0,0:05:57.24,0:05:58.83,EN,,0,0,0,,meaning you've got really to use lots of CARs and CDRs\nDialogue: 0,0:05:58.84,0:06:00.62,EN,,0,0,0,,which is exactly what I told you not to do.\nDialogue: 0,0:06:02.94,0:06:05.61,EN,,0,0,0,,That's on purpose in this case,\nDialogue: 0,0:06:06.11,0:06:09.02,EN,,0,0,0,,because I want it to be small, compact,\nDialogue: 0,0:06:09.34,0:06:10.40,EN,,0,0,0,,fit on the blackboard\nDialogue: 0,0:06:10.43,0:06:11.85,EN,,0,0,0,,so you can get the whole thing.\nDialogue: 0,0:06:12.42,0:06:14.80,EN,,0,0,0,,So I don't want to use long names like I normally use.\nDialogue: 0,0:06:15.60,0:06:17.29,EN,,0,0,0,,I want to use CAR-CDR because it's short.\nDialogue: 0,0:06:18.06,0:06:20.78,EN,,0,0,0,,Okay, I wanna, it's a whole, that's a trade-off.\nDialogue: 0,0:06:20.89,0:06:22.81,EN,,0,0,0,,I don't want you writing programs like this.\nDialogue: 0,0:06:23.57,0:06:25.08,EN,,0,0,0,,This is purely for an effect.\nDialogue: 0,0:06:25.85,0:06:27.61,EN,,0,0,0,,Now, you're going to have to work a little harder to read it,\nDialogue: 0,0:06:27.77,0:06:30.19,EN,,0,0,0,,but I'm going to try to make it clear as I'm writing it.\nDialogue: 0,0:06:31.27,0:06:34.40,EN,,0,0,0,,I'm also-- this is a pretty much complete interpreter,\nDialogue: 0,0:06:34.51,0:06:36.24,EN,,0,0,0,,but there's going to be room for putting in more things--\nDialogue: 0,0:06:36.25,0:06:38.60,EN,,0,0,0,,I'm going to leave out definition and assignment,\nDialogue: 0,0:06:39.10,0:06:42.41,EN,,0,0,0,,just because they are not essential,\nDialogue: 0,0:06:42.88,0:06:46.46,EN,,0,0,0,,and a, for a mathematical reason I'll show you later\nDialogue: 0,0:06:46.92,0:06:49.96,EN,,0,0,0,,and also they take up more space.\nDialogue: 0,0:06:51.88,0:06:53.64,EN,,0,0,0,,But, in any case, what do we have to do?\nDialogue: 0,0:06:53.95,0:06:55.66,EN,,0,0,0,,We have to do a dispatch\nDialogue: 0,0:06:56.09,0:06:57.90,EN,,0,0,0,,which breaks the types of expressions up\nDialogue: 0,0:06:58.28,0:07:00.38,EN,,0,0,0,,into particular classes.\nDialogue: 0,0:07:01.72,0:07:03.26,EN,,0,0,0,,Okay? So that's what we're going to have here.\nDialogue: 0,0:07:03.82,0:07:05.15,EN,,0,0,0,,Well, what expressions are there?\nDialogue: 0,0:07:05.15,0:07:06.36,EN,,0,0,0,,Let's look at the kinds of expressions.\nDialogue: 0,0:07:06.81,0:07:09.60,EN,,0,0,0,,We can have things like the numeral three.\nDialogue: 0,0:07:10.42,0:07:11.58,EN,,0,0,0,,What do I want that to do?\nDialogue: 0,0:07:12.72,0:07:14.75,EN,,0,0,0,,I can make choices, but I think right now,\nDialogue: 0,0:07:15.05,0:07:16.20,EN,,0,0,0,,I want it to be a three.\nDialogue: 0,0:07:17.05,0:07:17.88,EN,,0,0,0,,That's what I want.\nDialogue: 0,0:07:18.72,0:07:19.69,EN,,0,0,0,,So that's easy enough.\nDialogue: 0,0:07:20.03,0:07:22.91,EN,,0,0,0,,That means I want, if the thing is a number,\nDialogue: 0,0:07:27.29,0:07:31.68,EN,,0,0,0,,that I want the expression itself as the answer.\nDialogue: 0,0:07:35.42,0:07:36.76,EN,,0,0,0,,Now the next possibility\nDialogue: 0,0:07:36.89,0:07:38.86,EN,,0,0,0,,is things that we represent as symbols.\nDialogue: 0,0:07:39.39,0:07:46.75,EN,,0,0,0,,Examples of symbols are things like x, n, eval, number, x.\nDialogue: 0,0:07:48.01,0:07:49.18,EN,,0,0,0,,What do I mean them to be?\nDialogue: 0,0:07:50.16,0:07:51.63,EN,,0,0,0,,Those are things that stand for other things.\nDialogue: 0,0:07:51.63,0:07:53.23,EN,,0,0,0,,Those are the variables of our language.\nDialogue: 0,0:07:54.77,0:07:56.88,EN,,0,0,0,,And so I want to be able to say, for example,\nDialogue: 0,0:07:57.05,0:08:01.04,EN,,0,0,0,,that x, for example, transforms to it's value which might be three.\nDialogue: 0,0:08:02.64,0:08:05.76,EN,,0,0,0,,Or I might ask something like car.\nDialogue: 0,0:08:07.76,0:08:09.40,EN,,0,0,0,,I want to have as its value--\nDialogue: 0,0:08:09.63,0:08:11.34,EN,,0,0,0,,be something like some procedure,\nDialogue: 0,0:08:16.51,0:08:18.43,EN,,0,0,0,,which I don't know what is inside there,\nDialogue: 0,0:08:18.64,0:08:21.15,EN,,0,0,0,,perhaps a machine language code or something like that.\nDialogue: 0,0:08:22.84,0:08:24.27,EN,,0,0,0,,Ok? So, well, that's easy enough.\nDialogue: 0,0:08:24.43,0:08:26.89,EN,,0,0,0,,I'm going to push that off on someone else.\nDialogue: 0,0:08:27.80,0:08:28.89,EN,,0,0,0,,If something is a symbol,\nDialogue: 0,0:08:30.80,0:08:32.48,EN,,0,0,0,,if the expression is a symbol,\nDialogue: 0,0:08:33.42,0:08:34.88,EN,,0,0,0,,then I want the answer to be the result,\nDialogue: 0,0:08:34.91,0:08:40.24,EN,,0,0,0,,looking up the expression in the environment.\nDialogue: 0,0:08:46.48,0:08:48.99,EN,,0,0,0,,Now the environment is a dictionary\nDialogue: 0,0:08:49.96,0:08:54.06,EN,,0,0,0,,which maps the symbol names to their values.\nDialogue: 0,0:08:54.28,0:08:55.16,EN,,0,0,0,,And that's all it is.\nDialogue: 0,0:08:56.28,0:08:57.20,EN,,0,0,0,,How it's done?\nDialogue: 0,0:08:57.53,0:08:58.52,EN,,0,0,0,,Well, we'll see that later.\nDialogue: 0,0:08:59.68,0:09:00.57,EN,,0,0,0,,It's very easy.\nDialogue: 0,0:09:01.67,0:09:04.28,EN,,0,0,0,,It's easy to make data structures that are tables of various sorts.\nDialogue: 0,0:09:04.84,0:09:05.74,EN,,0,0,0,,But it's only a table,\nDialogue: 0,0:09:05.77,0:09:07.56,EN,,0,0,0,,and this is the access routine for some table.\nDialogue: 0,0:09:09.55,0:09:10.81,EN,,0,0,0,,Ok? Well, the next thing,\nDialogue: 0,0:09:11.31,0:09:12.56,EN,,0,0,0,,another kind of expression--\nDialogue: 0,0:09:12.67,0:09:15.56,EN,,0,0,0,,you have things that are described constants that are not numbers,\nDialogue: 0,0:09:16.06,0:09:17.43,EN,,0,0,0,,like 'foo.\nDialogue: 0,0:09:20.17,0:09:21.29,EN,,0,0,0,,Well, for my convenience,\nDialogue: 0,0:09:21.31,0:09:23.36,EN,,0,0,0,,I want to syntactically transform that\nDialogue: 0,0:09:24.73,0:09:26.80,EN,,0,0,0,,into a list structure which is,\nDialogue: 0,0:09:26.84,0:09:31.52,EN,,0,0,0,,which is, quote foo.\nDialogue: 0,0:09:33.72,0:09:37.18,EN,,0,0,0,,Or it's -- A quoted object, whatever it is,\nDialogue: 0,0:09:38.35,0:09:40.83,EN,,0,0,0,,is going to be actually an abbreviation,\nDialogue: 0,0:09:41.04,0:09:42.59,EN,,0,0,0,,which is not part of the evaluator\nDialogue: 0,0:09:43.21,0:09:44.46,EN,,0,0,0,,but happens somewhere else,\nDialogue: 0,0:09:44.75,0:09:47.79,EN,,0,0,0,,an abbreviation for an expression that looks like this.\nDialogue: 0,0:09:48.78,0:09:50.48,EN,,0,0,0,,This way, I can test for\nDialogue: 0,0:09:50.57,0:09:53.12,EN,,0,0,0,,the type of the expression as being a quotation\nDialogue: 0,0:09:53.31,0:09:55.95,EN,,0,0,0,,by examining the car of the expression.\nDialogue: 0,0:09:58.46,0:10:01.08,EN,,0,0,0,,So I'm not going to worry about that in the evaluator.\nDialogue: 0,0:10:01.65,0:10:02.68,EN,,0,0,0,,It's happening somewhere earlier\nDialogue: 0,0:10:02.70,0:10:03.96,EN,,0,0,0,,in the reader or something.\nDialogue: 0,0:10:05.54,0:10:15.04,EN,,0,0,0,,If the expression of the expression is quote,\nDialogue: 0,0:10:18.27,0:10:19.10,EN,,0,0,0,,then what I want,\nDialogue: 0,0:10:19.63,0:10:25.13,EN,,0,0,0,,I want quote foo to itself evaluate to foo.\nDialogue: 0,0:10:25.14,0:10:25.95,EN,,0,0,0,,It's a constant.\nDialogue: 0,0:10:27.53,0:10:28.92,EN,,0,0,0,,This is just a way of saying\nDialogue: 0,0:10:29.08,0:10:30.73,EN,,0,0,0,,that this evaluates to itself.\nDialogue: 0,0:10:31.79,0:10:33.66,EN,,0,0,0,,Ok? So thats the. What is that?\nDialogue: 0,0:10:33.66,0:10:36.36,EN,,0,0,0,,That's the first of the second of the list.\nDialogue: 0,0:10:36.59,0:10:37.58,EN,,0,0,0,,That's the second of the list.\nDialogue: 0,0:10:38.49,0:10:40.32,EN,,0,0,0,,The second element of the list is it's CADR.\nDialogue: 0,0:10:41.28,0:10:42.38,EN,,0,0,0,,So I'm just going to write here, CADR.\nDialogue: 0,0:10:51.08,0:10:52.35,EN,,0,0,0,,OK? What else do we have here?\nDialogue: 0,0:10:52.51,0:10:53.80,EN,,0,0,0,,We have lambda expressions,\nDialogue: 0,0:10:55.00,0:11:03.29,EN,,0,0,0,,for example, lambda of x plus x y.\nDialogue: 0,0:11:04.16,0:11:06.33,EN,,0,0,0,,Well, I going have to have some representation for the procedure\nDialogue: 0,0:11:06.33,0:11:07.85,EN,,0,0,0,,which is the value of an expression,\nDialogue: 0,0:11:08.11,0:11:09.08,EN,,0,0,0,,of a lambda expression.\nDialogue: 0,0:11:09.60,0:11:12.62,EN,,0,0,0,,The procedure here is not the expression lambda x.\nDialogue: 0,0:11:13.13,0:11:15.56,EN,,0,0,0,,That's the description of it, the textual description.\nDialogue: 0,0:11:16.41,0:11:18.33,EN,,0,0,0,,However, what what I going to expect to see here\nDialogue: 0,0:11:18.56,0:11:21.20,EN,,0,0,0,,is something which contains an environment as one of its parts\nDialogue: 0,0:11:23.23,0:11:25.36,EN,,0,0,0,,if I'm implementing a lexical language.\nDialogue: 0,0:11:25.84,0:11:29.07,EN,,0,0,0,,And so what I'd like to see\nDialogue: 0,0:11:29.20,0:11:30.67,EN,,0,0,0,,is some type flags.\nDialogue: 0,0:11:30.70,0:11:33.90,EN,,0,0,0,,I'm going to have to be able to distinguish procedures later,\nDialogue: 0,0:11:34.30,0:11:36.59,EN,,0,0,0,,procedures which were produced by lambdas,\nDialogue: 0,0:11:36.81,0:11:38.03,EN,,0,0,0,,from ones that may be primitive.\nDialogue: 0,0:11:39.06,0:11:41.96,EN,,0,0,0,,And so I'm going to have some flag,\nDialogue: 0,0:11:41.98,0:11:43.56,EN,,0,0,0,,which I'll just arbitrarily call closure,\nDialogue: 0,0:11:43.56,0:11:45.10,EN,,0,0,0,,just for historical reasons.\nDialogue: 0,0:11:47.68,0:11:49.60,EN,,0,0,0,,Now, to say what parts of this are important.\nDialogue: 0,0:11:49.92,0:11:51.12,EN,,0,0,0,,I'm going to need to know\nDialogue: 0,0:11:51.24,0:11:52.92,EN,,0,0,0,,the bound variable list and the body.\nDialogue: 0,0:11:54.22,0:11:55.40,EN,,0,0,0,,Well, that's the CDR of this,\nDialogue: 0,0:11:56.09,0:12:01.85,EN,,0,0,0,,so it's going to be x and plus x y and some environment.\nDialogue: 0,0:12:03.04,0:12:03.87,EN,,0,0,0,,and some environment.\nDialogue: 0,0:12:08.17,0:12:12.20,EN,,0,0,0,,Now this is not something that users should ever see,\nDialogue: 0,0:12:13.53,0:12:16.19,EN,,0,0,0,,this is purely a representation, internally,\nDialogue: 0,0:12:16.76,0:12:18.30,EN,,0,0,0,,for a procedure object.\nDialogue: 0,0:12:18.52,0:12:20.52,EN,,0,0,0,,It contains a bound variable list,\nDialogue: 0,0:12:20.70,0:12:22.62,EN,,0,0,0,,a body, and an environment,\nDialogue: 0,0:12:23.53,0:12:25.80,EN,,0,0,0,,and some type tag saying, I am a procedure.\nDialogue: 0,0:12:26.34,0:12:27.37,EN,,0,0,0,,I'm going to make one now.\nDialogue: 0,0:12:28.08,0:12:38.72,EN,,0,0,0,,So if the CAR of the expression is quote lambda,\nDialogue: 0,0:12:43.47,0:12:44.81,EN,,0,0,0,,then what I'm going to put here\nDialogue: 0,0:12:45.64,0:12:51.84,EN,,0,0,0,,is-- I'm going to make a list of closure,\nDialogue: 0,0:12:55.15,0:13:00.73,EN,,0,0,0,,the CDR of the procedure description\nDialogue: 0,0:13:01.56,0:13:02.97,EN,,0,0,0,,was everything except the lambda,\nDialogue: 0,0:13:07.74,0:13:08.86,EN,,0,0,0,,and the current environment.\nDialogue: 0,0:13:10.25,0:13:15.32,EN,,0,0,0,,This implements the rule for environments in the environment model.\nDialogue: 0,0:13:15.45,0:13:18.52,EN,,0,0,0,,It has to do with construction of procedures from lambda expressions.\nDialogue: 0,0:13:19.40,0:13:20.97,EN,,0,0,0,,The environment that was around\nDialogue: 0,0:13:21.48,0:13:24.32,EN,,0,0,0,,at the time the evaluator encountered the lambda expression\nDialogue: 0,0:13:25.04,0:13:28.46,EN,,0,0,0,,is the environment where the lambda expression gets\nDialogue: 0,0:13:28.68,0:13:31.77,EN,,0,0,0,,where the procedure resulting interprets it's free variables.\nDialogue: 0,0:13:34.72,0:13:35.82,EN,,0,0,0,,So that's part of that.\nDialogue: 0,0:13:35.92,0:13:37.55,EN,,0,0,0,,And so we have to capture that environment\nDialogue: 0,0:13:37.56,0:13:38.86,EN,,0,0,0,,as part of the procedure object.\nDialogue: 0,0:13:39.21,0:13:40.62,EN,,0,0,0,,And we'll see how that gets used later.\nDialogue: 0,0:13:42.03,0:13:43.77,EN,,0,0,0,,There are also conditional expressions\nDialogue: 0,0:13:44.59,0:13:52.81,EN,,0,0,0,,of things like COND of say, p one, e one, p two, e two.\nDialogue: 0,0:13:54.40,0:13:56.09,EN,,0,0,0,,Where this is a predicate,\nDialogue: 0,0:13:56.35,0:13:58.43,EN,,0,0,0,,a predicate is a thing that is either true or false,\nDialogue: 0,0:13:58.99,0:14:01.76,EN,,0,0,0,,and the expression to be evaluated if the predicate is true.\nDialogue: 0,0:14:03.44,0:14:06.08,EN,,0,0,0,,A set of clauses, if you will, that's the name for such a thing.\nDialogue: 0,0:14:06.79,0:14:09.36,EN,,0,0,0,,So I'm going put that somewhere else.\nDialogue: 0,0:14:09.36,0:14:11.56,EN,,0,0,0,,We're going to worry about that in another piece of code.\nDialogue: 0,0:14:12.42,0:14:21.28,EN,,0,0,0,,So EQ--  if the CAR of the expression is COND,\nDialogue: 0,0:14:24.00,0:14:26.84,EN,,0,0,0,,then I'm going to do nothing more than evaluate the COND,\nDialogue: 0,0:14:30.20,0:14:31.42,EN,,0,0,0,,the CDR of the expression.\nDialogue: 0,0:14:34.40,0:14:38.49,EN,,0,0,0,,That's all the clauses in the environment that I'm given.\nDialogue: 0,0:14:41.43,0:14:42.60,EN,,0,0,0,,Well, there's one more case,\nDialogue: 0,0:14:44.09,0:14:48.22,EN,,0,0,0,,arbitrary thing like the sum of x and three,\nDialogue: 0,0:14:50.62,0:14:53.95,EN,,0,0,0,,where this is an operator applied to operands,\nDialogue: 0,0:14:55.13,0:14:56.59,EN,,0,0,0,,and there's nothing special about it.\nDialogue: 0,0:14:56.59,0:14:59.63,EN,,0,0,0,,It's not one of the special cases, the special forms.\nDialogue: 0,0:14:59.85,0:15:01.42,EN,,0,0,0,,These are the special forms.\nDialogue: 0,0:15:09.65,0:15:12.12,EN,,0,0,0,,And if I were writing here a professional program, again,\nDialogue: 0,0:15:12.36,0:15:14.17,EN,,0,0,0,,I would somehow make this data directed.\nDialogue: 0,0:15:14.48,0:15:16.52,EN,,0,0,0,,So there wouldn't be a sequence of conditionals here,\nDialogue: 0,0:15:16.65,0:15:18.20,EN,,0,0,0,,there'd be a dispatch on some bits\nDialogue: 0,0:15:19.42,0:15:22.25,EN,,0,0,0,,if I were trying to do this in a more professional way.\nDialogue: 0,0:15:22.36,0:15:24.14,EN,,0,0,0,,So that, in fact, I can add to the thing\nDialogue: 0,0:15:24.68,0:15:26.38,EN,,0,0,0,,without changing my program much.\nDialogue: 0,0:15:26.71,0:15:28.46,EN,,0,0,0,,So, for example, they would run fast,\nDialogue: 0,0:15:29.04,0:15:30.43,EN,,0,0,0,,but I'm not worried about that.\nDialogue: 0,0:15:31.28,0:15:33.98,EN,,0,0,0,,Here we're trying to look at this in its entirety.\nDialogue: 0,0:15:35.07,0:15:35.80,EN,,0,0,0,,So it's else.\nDialogue: 0,0:15:37.69,0:15:38.56,EN,,0,0,0,,Well, what do we do?\nDialogue: 0,0:15:38.56,0:15:41.23,EN,,0,0,0,,In this case, I have to somehow do an addition.\nDialogue: 0,0:15:44.35,0:15:46.16,EN,,0,0,0,,Well, I could find out what the plus is.\nDialogue: 0,0:15:46.84,0:15:49.29,EN,,0,0,0,,I have to find out what the x and the three are.\nDialogue: 0,0:15:50.55,0:15:53.96,EN,,0,0,0,,And then I have to apply the result of finding what the plus is\nDialogue: 0,0:15:54.43,0:15:57.00,EN,,0,0,0,,to the result of finding out what the x and the three are.\nDialogue: 0,0:15:58.11,0:15:59.39,EN,,0,0,0,,We'll have a name for that.\nDialogue: 0,0:15:59.87,0:16:09.55,EN,,0,0,0,,So I'm going to apply the result of evaluating the CAR\nDialogue: 0,0:16:11.20,0:16:12.14,EN,,0,0,0,,of the expression--\nDialogue: 0,0:16:13.21,0:16:15.50,EN,,0,0,0,,the car of the expression is the operator--\nDialogue: 0,0:16:17.20,0:16:18.51,EN,,0,0,0,,in the environment given.\nDialogue: 0,0:16:20.51,0:16:22.89,EN,,0,0,0,,So evaluating the operator gets me the procedure.\nDialogue: 0,0:16:24.05,0:16:26.78,EN,,0,0,0,,Now I have to evaluate all the operands to get the arguments.\nDialogue: 0,0:16:27.29,0:16:28.22,EN,,0,0,0,,I'll call that EVLIST,\nDialogue: 0,0:16:31.26,0:16:35.53,EN,,0,0,0,,the CDR of the operands, of the expression,\nDialogue: 0,0:16:36.76,0:16:39.00,EN,,0,0,0,,with respect to the environment.\nDialogue: 0,0:16:41.94,0:16:43.13,EN,,0,0,0,,EVLIST will come up later--\nDialogue: 0,0:16:43.26,0:16:48.07,EN,,0,0,0,,EVLIST, apply, COND pair, COND, lambda, define.\nDialogue: 0,0:16:50.90,0:16:52.33,EN,,0,0,0,,So that what you are seeing here\nDialogue: 0,0:16:52.67,0:16:56.11,EN,,0,0,0,,is pretty much all there is in the evaluator itself.\nDialogue: 0,0:16:56.49,0:17:01.00,EN,,0,0,0,,It's the case dispatch on the type of the expression\nDialogue: 0,0:17:01.24,0:17:02.11,EN,,0,0,0,,with the default\nDialogue: 0,0:17:04.99,0:17:07.95,EN,,0,0,0,,being a general application or a combination.\nDialogue: 0,0:17:17.52,0:17:19.52,EN,,0,0,0,,Now there is lots of things we haven't defined yet.\nDialogue: 0,0:17:20.08,0:17:21.60,EN,,0,0,0,,Let's just look at them and see what they are.\nDialogue: 0,0:17:21.78,0:17:24.12,EN,,0,0,0,,We're going to have to do this later, evcond.\nDialogue: 0,0:17:25.48,0:17:26.67,EN,,0,0,0,,We have to write apply.\nDialogue: 0,0:17:27.57,0:17:28.62,EN,,0,0,0,,We're going to have to write EVLIST.\nDialogue: 0,0:17:28.94,0:17:30.20,EN,,0,0,0,,We're going to write LOOKUP.\nDialogue: 0,0:17:31.79,0:17:33.43,EN,,0,0,0,,I think that's everything, isn't there?\nDialogue: 0,0:17:33.43,0:17:35.16,EN,,0,0,0,,Everything else is something which is simple,\nDialogue: 0,0:17:35.16,0:17:37.18,EN,,0,0,0,,or primitive, or something like that.\nDialogue: 0,0:17:38.57,0:17:39.48,EN,,0,0,0,,And, of course,\nDialogue: 0,0:17:39.69,0:17:42.06,EN,,0,0,0,,we could many more special forms here,\nDialogue: 0,0:17:42.25,0:17:44.45,EN,,0,0,0,,but that would be a bad idea in general in a language.\nDialogue: 0,0:17:44.45,0:17:45.92,EN,,0,0,0,,You make a language very complicated\nDialogue: 0,0:17:46.00,0:17:47.48,EN,,0,0,0,,by putting a lot of things in there.\nDialogue: 0,0:17:47.69,0:17:50.35,EN,,0,0,0,,The number of reserve words that should exist in a language\nDialogue: 0,0:17:50.76,0:17:53.61,EN,,0,0,0,,should be no more than a person could remember on his fingers and toes.\nDialogue: 0,0:17:54.16,0:17:55.53,EN,,0,0,0,,And I get very upset with languages\nDialogue: 0,0:17:55.56,0:17:58.20,EN,,0,0,0,,which have hundreds of reserve words.\nDialogue: 0,0:17:59.41,0:18:00.71,EN,,0,0,0,,But that's where the reserve words go.\nDialogue: 0,0:18:03.15,0:18:06.54,EN,,0,0,0,,Okay. Well, now let's get to the next part of this,\nDialogue: 0,0:18:06.56,0:18:07.69,EN,,0,0,0,,the kernel, apply.\nDialogue: 0,0:18:09.64,0:18:10.75,EN,,0,0,0,,What else is this doing?\nDialogue: 0,0:18:11.59,0:18:17.53,EN,,0,0,0,,Well, apply's job is to take a procedure and apply it to its arguments\nDialogue: 0,0:18:17.66,0:18:20.68,EN,,0,0,0,,after both have been evaluated to come up with a procedure and the arguments\nDialogue: 0,0:18:20.91,0:18:23.85,EN,,0,0,0,,rather the operator symbols and the operand symbols,\nDialogue: 0,0:18:24.09,0:18:26.96,EN,,0,0,0,,whatever they are-- symbolic expressions.\nDialogue: 0,0:18:33.27,0:18:35.08,EN,,0,0,0,,So we will define apply\nDialogue: 0,0:18:38.35,0:18:40.65,EN,,0,0,0,,to be a procedure of two arguments,\nDialogue: 0,0:18:40.75,0:18:43.44,EN,,0,0,0,,a procedure and arguments.\nDialogue: 0,0:18:47.24,0:18:48.12,EN,,0,0,0,,And what does it do?\nDialogue: 0,0:18:48.14,0:18:49.55,EN,,0,0,0,,It does nothing very complicated.\nDialogue: 0,0:18:49.93,0:18:50.78,EN,,0,0,0,,It's got two cases.\nDialogue: 0,0:18:53.58,0:18:55.16,EN,,0,0,0,,Either the procedure is primitive--\nDialogue: 0,0:19:03.42,0:19:06.41,EN,,0,0,0,,And I don't know exactly how that is done.\nDialogue: 0,0:19:06.86,0:19:10.24,EN,,0,0,0,,It's possible there's some type information\nDialogue: 0,0:19:10.38,0:19:12.41,EN,,0,0,0,,just like we made closure for, here,\nDialogue: 0,0:19:12.68,0:19:15.05,EN,,0,0,0,,being the description of the type of a compound thing--\nDialogue: 0,0:19:16.33,0:19:17.79,EN,,0,0,0,,OK? probably so.\nDialogue: 0,0:19:18.55,0:19:20.20,EN,,0,0,0,,But it is not essential how that works,\nDialogue: 0,0:19:20.68,0:19:22.01,EN,,0,0,0,,in fact, it turns out,\nDialogue: 0,0:19:22.19,0:19:23.85,EN,,0,0,0,,as you probably know or have deduced,\nDialogue: 0,0:19:23.87,0:19:25.47,EN,,0,0,0,,that you don't need any primitives anyway.\nDialogue: 0,0:19:27.35,0:19:29.28,EN,,0,0,0,,You can compute anything because without\nDialogue: 0,0:19:30.46,0:19:33.19,EN,,0,0,0,,because some of the lambda that I've been playing with.\nDialogue: 0,0:19:33.61,0:19:34.76,EN,,0,0,0,,But it's nice to have them.\nDialogue: 0,0:19:34.81,0:19:36.27,EN,,0,0,0,,So here we're going to do some magic\nDialogue: 0,0:19:36.30,0:19:37.47,EN,,0,0,0,,which I'm not going to explain.\nDialogue: 0,0:19:38.06,0:19:41.44,EN,,0,0,0,,Go to machine language, apply primop.\nDialogue: 0,0:19:42.91,0:19:43.80,EN,,0,0,0,,Here's how it adds.\nDialogue: 0,0:19:44.78,0:19:46.10,EN,,0,0,0,,Execute an add instruction.\nDialogue: 0,0:19:50.62,0:19:52.11,EN,,0,0,0,,However, the interesting part of a language\nDialogue: 0,0:19:52.14,0:19:54.27,EN,,0,0,0,,is the glue by which the primitives are glued together.\nDialogue: 0,0:19:54.91,0:19:55.90,EN,,0,0,0,,So let's look at that.\nDialogue: 0,0:19:56.91,0:19:58.38,EN,,0,0,0,,Well, the other possibility\nDialogue: 0,0:19:58.75,0:20:04.12,EN,,0,0,0,,this is a compound made up by executing a lambda expression,\nDialogue: 0,0:20:04.97,0:20:07.05,EN,,0,0,0,,this is a compound procedure.\nDialogue: 0,0:20:07.62,0:20:09.36,EN,,0,0,0,,Well, we'll check its type.\nDialogue: 0,0:20:10.11,0:20:17.07,EN,,0,0,0,,If it is closure,\nDialogue: 0,0:20:20.51,0:20:24.09,EN,,0,0,0,,if it's one of those, then I have to do an eval of the body.\nDialogue: 0,0:20:24.19,0:20:27.39,EN,,0,0,0,,The way I do this, the way I deal with this at all\nDialogue: 0,0:20:28.08,0:20:31.69,EN,,0,0,0,,is the way I evaluate the application of a procedure to its arguments,\nDialogue: 0,0:20:31.72,0:20:33.71,EN,,0,0,0,,is by evaluating the body of the procedure\nDialogue: 0,0:20:34.19,0:20:37.80,EN,,0,0,0,,in the environment resulting from extending the environment of the procedure\nDialogue: 0,0:20:37.92,0:20:40.48,EN,,0,0,0,,with the bindings of the formal parameters\nDialogue: 0,0:20:41.02,0:20:43.68,EN,,0,0,0,,of the procedure to the arguments that were passed to it.\nDialogue: 0,0:20:46.70,0:20:47.87,EN,,0,0,0,,That was a long sentence.\nDialogue: 0,0:20:51.13,0:20:52.16,EN,,0,0,0,,Well that's easy enough.\nDialogue: 0,0:20:52.82,0:20:54.48,EN,,0,0,0,,Now here's going to be a lot of CAR-CDRing.\nDialogue: 0,0:20:56.46,0:20:58.11,EN,,0,0,0,,I have to get the body of the procedure.\nDialogue: 0,0:20:59.40,0:21:02.30,EN,,0,0,0,,Where's the body of the procedure in here?\nDialogue: 0,0:21:02.96,0:21:04.08,EN,,0,0,0,,Well here's the CAR,\nDialogue: 0,0:21:04.49,0:21:06.13,EN,,0,0,0,,here's the CDR is the whole rest of this.\nDialogue: 0,0:21:06.13,0:21:06.96,EN,,0,0,0,,So here's the CADR.\nDialogue: 0,0:21:07.40,0:21:09.45,EN,,0,0,0,,And so I see, what I have here is the body\nDialogue: 0,0:21:09.45,0:21:13.04,EN,,0,0,0,,is the second element of the second element of the procedure.\nDialogue: 0,0:21:13.20,0:21:15.15,EN,,0,0,0,,So it's the CADR of the CADR or the CADADR.\nDialogue: 0,0:21:19.17,0:21:27.68,EN,,0,0,0,,It's the C-A-D-A-D-R, CADADR of the procedure.\nDialogue: 0,0:21:30.26,0:21:31.56,EN,,0,0,0,,To evaluate the body\nDialogue: 0,0:21:31.98,0:21:36.48,EN,,0,0,0,,in the result of binding that's making up more environment,\nDialogue: 0,0:21:38.09,0:21:42.06,EN,,0,0,0,,well I need the formal parameters of the of the procedure,\nDialogue: 0,0:21:42.06,0:21:42.72,EN,,0,0,0,,what is that?\nDialogue: 0,0:21:43.50,0:21:45.13,EN,,0,0,0,,That's the CAR of the CADR.\nDialogue: 0,0:21:46.52,0:21:48.78,EN,,0,0,0,,OK? It's horrible isn't it?\nDialogue: 0,0:21:52.65,0:21:53.63,EN,,0,0,0,,--of the procedure.\nDialogue: 0,0:21:55.44,0:22:00.86,EN,,0,0,0,,Bind that to the arguments that were passed in the environment,\nDialogue: 0,0:22:00.89,0:22:04.14,EN,,0,0,0,,which is passed also as part of the procedure.\nDialogue: 0,0:22:04.54,0:22:07.90,EN,,0,0,0,,Well, that's the CAR of the CDR of the CDR of this,\nDialogue: 0,0:22:09.79,0:22:16.62,EN,,0,0,0,,CADDR, of the procedure.\nDialogue: 0,0:22:20.29,0:22:24.96,EN,,0,0,0,,Bind, eval, pair, COND, lamda, define--\nDialogue: 0,0:22:26.14,0:22:29.68,EN,,0,0,0,,Now, of course, if I were being really a neat character,\nDialogue: 0,0:22:29.87,0:22:31.34,EN,,0,0,0,,and I was being very careful,\nDialogue: 0,0:22:32.24,0:22:34.12,EN,,0,0,0,,I would actually put an extra case here\nDialogue: 0,0:22:34.38,0:22:35.98,EN,,0,0,0,,for checking for certain errors like,\nDialogue: 0,0:22:36.17,0:22:38.41,EN,,0,0,0,,did you try to apply one to an argument?\nDialogue: 0,0:22:39.00,0:22:41.69,EN,,0,0,0,,You get a undefined procedure type.\nDialogue: 0,0:22:42.57,0:22:44.09,EN,,0,0,0,,So I may as well do that anyway.\nDialogue: 0,0:22:45.80,0:22:55.96,EN,,0,0,0,,--else, some sort of error, like that.\nDialogue: 0,0:22:57.61,0:23:01.61,EN,,0,0,0,,Now, of course, again, in some sort of more real system,\nDialogue: 0,0:23:02.56,0:23:04.22,EN,,0,0,0,,written for professional reasons,\nDialogue: 0,0:23:05.32,0:23:08.00,EN,,0,0,0,,this would be written with a case analysis\nDialogue: 0,0:23:08.36,0:23:09.90,EN,,0,0,0,,done by some sort of dispatch.\nDialogue: 0,0:23:10.75,0:23:12.68,EN,,0,0,0,,Over here, I would probably have other cases\nDialogue: 0,0:23:12.70,0:23:14.14,EN,,0,0,0,,like, is this compiled code?\nDialogue: 0,0:23:16.22,0:23:16.84,EN,,0,0,0,,It's very important.\nDialogue: 0,0:23:16.88,0:23:18.35,EN,,0,0,0,,I might have distinguished the kind of code\nDialogue: 0,0:23:18.38,0:23:22.33,EN,,0,0,0,,that's produced by a directly evaluating a lambda in interpretation\nDialogue: 0,0:23:22.94,0:23:25.87,EN,,0,0,0,,from code that was produced by somebody's compiler or something like that.\nDialogue: 0,0:23:26.11,0:23:27.23,EN,,0,0,0,,And we'll talk about that later.\nDialogue: 0,0:23:27.23,0:23:29.61,EN,,0,0,0,,Or is this a piece Fortran program I have to go off and execute.\nDialogue: 0,0:23:30.51,0:23:32.51,EN,,0,0,0,,It's a perfectly possible thing, at this point, to do that.\nDialogue: 0,0:23:32.92,0:23:36.41,EN,,0,0,0,,In fact, in this concrete syntax evaluator I'm writing here,\nDialogue: 0,0:23:37.45,0:23:40.86,EN,,0,0,0,,there's an assumption built in that this is Lisp,\nDialogue: 0,0:23:42.30,0:23:43.82,EN,,0,0,0,,because I'm using CARs and CDRs.\nDialogue: 0,0:23:43.84,0:23:45.10,EN,,0,0,0,,CAR means the operator,\nDialogue: 0,0:23:45.28,0:23:46.64,EN,,0,0,0,,and CDR means the operand.\nDialogue: 0,0:23:46.75,0:23:49.96,EN,,0,0,0,,In the text, there is an abstract syntax evaluator\nDialogue: 0,0:23:50.35,0:23:53.15,EN,,0,0,0,,which these could be-- these are given abstract names\nDialogue: 0,0:23:53.16,0:23:54.09,EN,,0,0,0,,like operator, and operand,\nDialogue: 0,0:23:54.14,0:23:55.82,EN,,0,0,0,,and all these other things are like that.\nDialogue: 0,0:23:56.16,0:23:56.86,EN,,0,0,0,,And, in that case,\nDialogue: 0,0:23:57.02,0:24:00.91,EN,,0,0,0,,you could reprogram it to be ALGOL with no problem.\nDialogue: 0,0:24:03.36,0:24:06.40,EN,,0,0,0,,Well, here we have added another couple of things\nDialogue: 0,0:24:07.20,0:24:08.43,EN,,0,0,0,,that we haven't defined.\nDialogue: 0,0:24:10.81,0:24:12.57,EN,,0,0,0,,I don't think I'll worry about these at all,\nDialogue: 0,0:24:13.39,0:24:15.05,EN,,0,0,0,,however, this one will be interesting later.\nDialogue: 0,0:24:17.18,0:24:19.76,EN,,0,0,0,,Let's just proceed through this and get it done.\nDialogue: 0,0:24:20.55,0:24:22.65,EN,,0,0,0,,There's only two more blackboards so it can't be very long.\nDialogue: 0,0:24:27.40,0:24:29.08,EN,,0,0,0,,It's carefully tailored to exactly fit.\nDialogue: 0,0:24:30.07,0:24:30.98,EN,,0,0,0,,Well, what do we have left?\nDialogue: 0,0:24:30.98,0:24:33.20,EN,,0,0,0,,We have to define EVLIST, which is over here.\nDialogue: 0,0:24:33.73,0:24:35.07,EN,,0,0,0,,And EVLIST is nothing more\nDialogue: 0,0:24:35.26,0:24:43.08,EN,,0,0,0,,than a map down a bunch of operands producing arguments.\nDialogue: 0,0:24:44.30,0:24:45.40,EN,,0,0,0,,But I'm going to write it out.\nDialogue: 0,0:24:45.82,0:24:48.30,EN,,0,0,0,,And one of the reasons I'm going to write this out is for a mystical reason,\nDialogue: 0,0:24:49.88,0:24:52.04,EN,,0,0,0,,which is I want to make this evaluator so simple\nDialogue: 0,0:24:52.06,0:24:53.56,EN,,0,0,0,,that it can understand itself.\nDialogue: 0,0:24:56.45,0:24:58.09,EN,,0,0,0,,I'm going to really worry about that a little bit.\nDialogue: 0,0:25:00.23,0:25:01.74,EN,,0,0,0,,So let's write it out completely.\nDialogue: 0,0:25:02.85,0:25:04.24,EN,,0,0,0,,See, I don't want to worry about\nDialogue: 0,0:25:04.27,0:25:06.08,EN,,0,0,0,,whether or not the thing can pass functional arguments.\nDialogue: 0,0:25:06.27,0:25:08.06,EN,,0,0,0,,The value evaluator is not going to use them.\nDialogue: 0,0:25:08.98,0:25:10.78,EN,,0,0,0,,The evaluator is not going to produce functional values.\nDialogue: 0,0:25:10.88,0:25:12.67,EN,,0,0,0,,So even if there were a different, alternative language\nDialogue: 0,0:25:12.80,0:25:13.96,EN,,0,0,0,,that were very close to this,\nDialogue: 0,0:25:15.16,0:25:17.79,EN,,0,0,0,,this evaluates a complex language like Scheme\nDialogue: 0,0:25:17.80,0:25:23.12,EN,,0,0,0,,which does allow procedural arguments, procedural values, and procedural data.\nDialogue: 0,0:25:24.07,0:25:25.95,EN,,0,0,0,,But even if I were evaluating ALGOL,\nDialogue: 0,0:25:27.34,0:25:28.96,EN,,0,0,0,,which doesn't allow procedural values,\nDialogue: 0,0:25:29.47,0:25:30.59,EN,,0,0,0,,I could use this evaluator.\nDialogue: 0,0:25:31.58,0:25:33.92,EN,,0,0,0,,And this evaluator is not making any assumptions about that.\nDialogue: 0,0:25:34.27,0:25:36.03,EN,,0,0,0,,And, in fact, if this evaluator were to be restricted\nDialogue: 0,0:25:36.27,0:25:37.50,EN,,0,0,0,,to not being able to that, it wouldn't matter\nDialogue: 0,0:25:37.52,0:25:40.03,EN,,0,0,0,,because it doesn't use any of those clever things.\nDialogue: 0,0:25:40.64,0:25:42.41,EN,,0,0,0,,So that's why I'm arranging this to be super simple.\nDialogue: 0,0:25:44.07,0:25:46.46,EN,,0,0,0,,This is sort of the kernel of all possible language evaluators.\nDialogue: 0,0:25:47.81,0:25:48.48,EN,,0,0,0,,How about that?\nDialogue: 0,0:25:49.42,0:25:53.56,EN,,0,0,0,,Evlist--  well, what is it?\nDialogue: 0,0:25:53.82,0:25:57.04,EN,,0,0,0,,It's the procedure of two arguments, l and an environment,\nDialogue: 0,0:25:58.09,0:25:59.08,EN,,0,0,0,,where l is a list\nDialogue: 0,0:25:59.58,0:26:08.27,EN,,0,0,0,,such that if the list of arguments is the empty list,\nDialogue: 0,0:26:10.19,0:26:12.68,EN,,0,0,0,,then the result is the empty list.\nDialogue: 0,0:26:14.03,0:26:19.23,EN,,0,0,0,,Otherwise, I want to cons up\nDialogue: 0,0:26:20.75,0:26:26.67,EN,,0,0,0,,result of evaluating the CAR of the\nDialogue: 0,0:26:28.16,0:26:32.51,EN,,0,0,0,,the CAR of the list of operands in the environment.\nDialogue: 0,0:26:33.34,0:26:35.71,EN,,0,0,0,,So I want the first operand evaluated,\nDialogue: 0,0:26:35.98,0:26:38.40,EN,,0,0,0,,and I'm going to make a list of the results\nDialogue: 0,0:26:38.97,0:26:40.76,EN,,0,0,0,,by CONSing that onto the result\nDialogue: 0,0:26:41.08,0:26:45.42,EN,,0,0,0,,of this EVLISTing as a CDR recursion,\nDialogue: 0,0:26:46.22,0:26:50.13,EN,,0,0,0,,the CDR of the list relative to the same environment.\nDialogue: 0,0:26:53.08,0:26:58.24,EN,,0,0,0,,Evlist, cons, else, COND, lambda, define--\nDialogue: 0,0:26:59.66,0:27:01.84,EN,,0,0,0,,OK? And I have one more\nDialogue: 0,0:27:01.84,0:27:03.36,EN,,0,0,0,,that I want to put on the blackboard.\nDialogue: 0,0:27:03.62,0:27:05.21,EN,,0,0,0,,It's the essence of this whole thing.\nDialogue: 0,0:27:05.64,0:27:08.13,EN,,0,0,0,,And there's some sort of next layer down.\nDialogue: 0,0:27:14.54,0:27:15.44,EN,,0,0,0,,Conditionals--\nDialogue: 0,0:27:15.69,0:27:16.99,EN,,0,0,0,,conditionals are the only thing left\nDialogue: 0,0:27:17.02,0:27:18.17,EN,,0,0,0,,that are sort of substantial.\nDialogue: 0,0:27:18.88,0:27:20.75,EN,,0,0,0,,Then below that, we have to worry about\nDialogue: 0,0:27:21.07,0:27:22.94,EN,,0,0,0,,things like lookup and bind,\nDialogue: 0,0:27:23.56,0:27:25.36,EN,,0,0,0,,and we'll look at that in a second.\nDialogue: 0,0:27:25.53,0:27:27.93,EN,,0,0,0,,But of the substantial stuff at this level of detail,\nDialogue: 0,0:27:28.65,0:27:30.62,EN,,0,0,0,,next important thing is how you deal with conditionals.\nDialogue: 0,0:27:31.60,0:27:33.33,EN,,0,0,0,,Well, how do we have a conditional thing?\nDialogue: 0,0:27:36.97,0:27:38.56,EN,,0,0,0,,It's a procedure\nDialogue: 0,0:27:39.48,0:27:45.00,EN,,0,0,0,,of clauses and an environment.\nDialogue: 0,0:27:47.71,0:27:48.51,EN,,0,0,0,,And what does it do?\nDialogue: 0,0:27:49.82,0:27:55.47,EN,,0,0,0,,It says, if I've no more clauses,\nDialogue: 0,0:28:02.60,0:28:03.96,EN,,0,0,0,,well, I have to give this a value.\nDialogue: 0,0:28:04.70,0:28:05.87,EN,,0,0,0,,It could be that it was an error.\nDialogue: 0,0:28:06.54,0:28:08.59,EN,,0,0,0,,Supposing it run off the end of a conditional,\nDialogue: 0,0:28:09.15,0:28:10.06,EN,,0,0,0,,it's pretty arbitrary.\nDialogue: 0,0:28:10.06,0:28:12.88,EN,,0,0,0,,It's up to me as programmer to choose what I want to happen.\nDialogue: 0,0:28:13.65,0:28:15.45,EN,,0,0,0,,It's convenient for me, right now, to write down\nDialogue: 0,0:28:15.63,0:28:17.53,EN,,0,0,0,,this has a value which is the empty list,\nDialogue: 0,0:28:18.14,0:28:18.83,EN,,0,0,0,,doesn't matter.\nDialogue: 0,0:28:20.10,0:28:20.88,EN,,0,0,0,,For error checking,\nDialogue: 0,0:28:20.89,0:28:22.76,EN,,0,0,0,,some people might prefer something else.\nDialogue: 0,0:28:23.11,0:28:24.81,EN,,0,0,0,,But the interesting things are the following ones.\nDialogue: 0,0:28:25.39,0:28:27.24,EN,,0,0,0,,If I've got an else clause--\nDialogue: 0,0:28:31.00,0:28:32.73,EN,,0,0,0,,You see, if I have a list of clauses,\nDialogue: 0,0:28:33.21,0:28:34.41,EN,,0,0,0,,then each clause is a list.\nDialogue: 0,0:28:35.44,0:28:40.52,EN,,0,0,0,,And so the predicate part is the CAAR of the clauses.\nDialogue: 0,0:28:43.56,0:28:45.02,EN,,0,0,0,,It's the CAR,\nDialogue: 0,0:28:45.04,0:28:49.00,EN,,0,0,0,,which is the first part of the first clause in the list of clauses.\nDialogue: 0,0:28:51.09,0:28:51.84,EN,,0,0,0,,If it's an else,\nDialogue: 0,0:28:54.32,0:28:56.51,EN,,0,0,0,,then it means I want my result of the conditional\nDialogue: 0,0:28:56.64,0:28:59.15,EN,,0,0,0,,to be the result of evaluating the matching expression.\nDialogue: 0,0:29:00.12,0:29:04.32,EN,,0,0,0,,So I eval the CADAR.\nDialogue: 0,0:29:07.00,0:29:09.56,EN,,0,0,0,,So this is the first clause,\nDialogue: 0,0:29:10.12,0:29:11.63,EN,,0,0,0,,the second element of it, CADAR--\nDialogue: 0,0:29:12.81,0:29:17.08,EN,,0,0,0,,CADR of a CAR-- of the clauses,\nDialogue: 0,0:29:21.23,0:29:22.57,EN,,0,0,0,,with respect to the environment.\nDialogue: 0,0:29:26.62,0:29:28.60,EN,,0,0,0,,Now the next possibility is more interesting.\nDialogue: 0,0:29:29.63,0:29:30.44,EN,,0,0,0,,If it's false,\nDialogue: 0,0:29:33.05,0:29:35.10,EN,,0,0,0,,if the first predicate in the predicate list\nDialogue: 0,0:29:35.74,0:29:37.68,EN,,0,0,0,,is not an else, and it's not false,\nDialogue: 0,0:29:38.32,0:29:39.50,EN,,0,0,0,,if it's not the word else,\nDialogue: 0,0:29:40.16,0:29:42.00,EN,,0,0,0,,and if it's not a false thing--\nDialogue: 0,0:29:42.03,0:29:43.66,EN,,0,0,0,,Let's write down what it is if it's a false thing.\nDialogue: 0,0:29:44.36,0:29:50.08,EN,,0,0,0,,If the result of evaluating the first clause -- first predicate,\nDialogue: 0,0:29:52.33,0:29:56.76,EN,,0,0,0,,the clauses--  respect the environment,\nDialogue: 0,0:29:58.19,0:30:01.00,EN,,0,0,0,,if that evaluation yields false,\nDialogue: 0,0:30:01.69,0:30:03.82,EN,,0,0,0,,then it means, I want to look at the next clause.\nDialogue: 0,0:30:04.36,0:30:05.74,EN,,0,0,0,,So I want to discard the first one.\nDialogue: 0,0:30:06.25,0:30:08.33,EN,,0,0,0,,So we just go around loop, evcond,\nDialogue: 0,0:30:09.95,0:30:16.49,EN,,0,0,0,,the CDR of the clauses relative to that environment.\nDialogue: 0,0:30:19.95,0:30:25.15,EN,,0,0,0,,And otherwise, I had a true clause,\nDialogue: 0,0:30:26.84,0:30:28.96,EN,,0,0,0,,what I want is to evaluate\nDialogue: 0,0:30:31.85,0:30:41.45,EN,,0,0,0,,the CADAR of the clauses relative to that environment.\nDialogue: 0,0:30:48.20,0:30:49.61,EN,,0,0,0,,Boy, it's almost done.\nDialogue: 0,0:30:51.21,0:30:52.80,EN,,0,0,0,,It's quite close to done.\nDialogue: 0,0:30:53.73,0:30:55.87,EN,,0,0,0,,I think we're going to finish this part off.\nDialogue: 0,0:30:56.21,0:30:58.57,EN,,0,0,0,,So just buzzing through this evaluator,\nDialogue: 0,0:30:58.81,0:31:00.70,EN,,0,0,0,,but so far you're seeing almost everything.\nDialogue: 0,0:31:01.08,0:31:04.04,EN,,0,0,0,,Let's look at the next transparency here.\nDialogue: 0,0:31:06.32,0:31:10.43,EN,,0,0,0,,And see IS, Here is bind.\nDialogue: 0,0:31:11.98,0:31:14.54,EN,,0,0,0,,Bind is for making more table.\nDialogue: 0,0:31:15.46,0:31:18.67,EN,,0,0,0,,And what we are going to do here is make a--\nDialogue: 0,0:31:19.24,0:31:22.80,EN,,0,0,0,,we're going to make a new frame for an environment structure.\nDialogue: 0,0:31:22.80,0:31:25.42,EN,,0,0,0,,The environment structure is going to be represented\nDialogue: 0,0:31:25.93,0:31:27.20,EN,,0,0,0,,as a list of frames.\nDialogue: 0,0:31:28.08,0:31:30.19,EN,,0,0,0,,So given an existing environment structure,\nDialogue: 0,0:31:30.32,0:31:32.11,EN,,0,0,0,,I'm going to make a new environment structure\nDialogue: 0,0:31:32.25,0:31:33.82,EN,,0,0,0,,by consing a new frame\nDialogue: 0,0:31:33.93,0:31:35.69,EN,,0,0,0,,onto the existing environment structure,\nDialogue: 0,0:31:36.62,0:31:40.36,EN,,0,0,0,,where the new frame consists of the result of pairing up the variables,\nDialogue: 0,0:31:41.05,0:31:43.79,EN,,0,0,0,,which are the bound variables of the procedure I'm applying,\nDialogue: 0,0:31:44.12,0:31:48.25,EN,,0,0,0,,to the values which are the arguments that were passed that procedure.\nDialogue: 0,0:31:49.69,0:31:50.65,EN,,0,0,0,,This is just making a list,\nDialogue: 0,0:31:51.64,0:31:54.06,EN,,0,0,0,,adding a new element to our list of frames,\nDialogue: 0,0:31:54.30,0:31:55.60,EN,,0,0,0,,which is an environment structure,\nDialogue: 0,0:31:55.74,0:31:56.89,EN,,0,0,0,,to make a new environment.\nDialogue: 0,0:31:58.65,0:32:00.65,EN,,0,0,0,,Where pair-up is very simple.\nDialogue: 0,0:32:01.54,0:32:02.84,EN,,0,0,0,,Pair-up is nothing more\nDialogue: 0,0:32:03.13,0:32:05.56,EN,,0,0,0,,than if I have a list of variables and a list of values,\nDialogue: 0,0:32:05.93,0:32:08.62,EN,,0,0,0,,well, if I run out of variables and if I run out of values,\nDialogue: 0,0:32:08.62,0:32:09.58,EN,,0,0,0,,everything's OK.\nDialogue: 0,0:32:09.72,0:32:11.48,EN,,0,0,0,,Otherwise, I've given too many arguments.\nDialogue: 0,0:32:12.51,0:32:15.98,EN,,0,0,0,,If I've not run out of variables, but I've run out of values,\nDialogue: 0,0:32:16.06,0:32:17.37,EN,,0,0,0,,that I have too few arguments.\nDialogue: 0,0:32:18.51,0:32:19.63,EN,,0,0,0,,And in the general case,\nDialogue: 0,0:32:19.63,0:32:21.48,EN,,0,0,0,,where I don't have any errors, and I'm not done,\nDialogue: 0,0:32:22.06,0:32:25.61,EN,,0,0,0,,OK? Then I really am just adding a new pair\nDialogue: 0,0:32:25.76,0:32:30.17,EN,,0,0,0,,of the first variable with the first argument,\nDialogue: 0,0:32:30.94,0:32:32.12,EN,,0,0,0,,the first value,\nDialogue: 0,0:32:32.76,0:32:36.40,EN,,0,0,0,,onto a list resulting from pairing-up\nDialogue: 0,0:32:37.12,0:32:40.64,EN,,0,0,0,,the rest of the variables with the rest of the values.\nDialogue: 0,0:32:42.95,0:32:44.78,EN,,0,0,0,,Lookup is of course equally simple.\nDialogue: 0,0:32:46.28,0:32:49.63,EN,,0,0,0,,If I have to look up a symbol in an environment,\nDialogue: 0,0:32:49.93,0:32:51.39,EN,,0,0,0,,well, if the environment is empty,\nDialogue: 0,0:32:51.56,0:32:53.00,EN,,0,0,0,,then I've got an unbound variable.\nDialogue: 0,0:32:54.65,0:32:55.47,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:32:56.86,0:33:00.36,EN,,0,0,0,,what I'm going to do is use a special pair list lookup procedure,\nDialogue: 0,0:33:00.38,0:33:01.87,EN,,0,0,0,,which we'll have very shortly,\nDialogue: 0,0:33:02.24,0:33:05.44,EN,,0,0,0,,of the symbol in the first frame of the environment.\nDialogue: 0,0:33:05.93,0:33:07.21,EN,,0,0,0,,Since I know the environment is not empty,\nDialogue: 0,0:33:07.23,0:33:08.40,EN,,0,0,0,,it must have a first frame.\nDialogue: 0,0:33:09.20,0:33:11.14,EN,,0,0,0,,So I lookup the symbol in the first frame.\nDialogue: 0,0:33:11.56,0:33:13.58,EN,,0,0,0,,That becomes the value cell here.\nDialogue: 0,0:33:14.38,0:33:17.61,EN,,0,0,0,,OK? And then, if the value cell is empty,\nDialogue: 0,0:33:18.44,0:33:20.57,EN,,0,0,0,,if there is no such value cell,\nDialogue: 0,0:33:20.70,0:33:22.84,EN,,0,0,0,,then I have to continue and look at the rest of the frames.\nDialogue: 0,0:33:23.72,0:33:25.04,EN,,0,0,0,,It means there was nothing found there.\nDialogue: 0,0:33:25.99,0:33:28.89,EN,,0,0,0,,So that's a property of ASSQ is it returns emptiness\nDialogue: 0,0:33:29.52,0:33:30.80,EN,,0,0,0,,if it doesn't find something.\nDialogue: 0,0:33:32.32,0:33:33.85,EN,,0,0,0,,but if it did find something,\nDialogue: 0,0:33:33.85,0:33:36.06,EN,,0,0,0,,then I'm going to use the CDR of the value cell here,\nDialogue: 0,0:33:36.46,0:33:40.25,EN,,0,0,0,,which is the thing that was the pair consisting of the variable and the value.\nDialogue: 0,0:33:41.05,0:33:43.93,EN,,0,0,0,,So the CDR of it is the value part. OK?\nDialogue: 0,0:33:45.00,0:33:47.82,EN,,0,0,0,,Finally, ASSQ is something you've probably seen already.\nDialogue: 0,0:33:47.97,0:33:50.83,EN,,0,0,0,,ASSQ takes a symbol and a list of pairs,\nDialogue: 0,0:33:51.42,0:33:53.40,EN,,0,0,0,,and if the list is empty, it's empty.\nDialogue: 0,0:33:53.52,0:33:56.30,EN,,0,0,0,,If the symbol is the first thing in the list--\nDialogue: 0,0:33:58.06,0:33:58.91,EN,,0,0,0,,That's an error.\nDialogue: 0,0:33:59.82,0:34:02.17,EN,,0,0,0,,That should be CAAR, C-A-A-R.\nDialogue: 0,0:34:03.16,0:34:04.16,EN,,0,0,0,,Everybody note that.\nDialogue: 0,0:34:07.63,0:34:09.37,EN,,0,0,0,,Right there, OK?\nDialogue: 0,0:34:13.42,0:34:14.41,EN,,0,0,0,,And in any case,\nDialogue: 0,0:34:14.56,0:34:16.81,EN,,0,0,0,,f the symbol is the CAAR of the A list,\nDialogue: 0,0:34:17.16,0:34:20.97,EN,,0,0,0,,then I want the first, the first pair, in the alist.\nDialogue: 0,0:34:22.08,0:34:25.50,EN,,0,0,0,,So, in other words, if this is the key matching the right entry,\nDialogue: 0,0:34:26.24,0:34:26.97,EN,,0,0,0,,otherwise,\nDialogue: 0,0:34:27.08,0:34:28.94,EN,,0,0,0,,I want to look up that symbol in the rest.\nDialogue: 0,0:34:30.08,0:34:33.31,EN,,0,0,0,,Sorry for producing a bug, bugs appear.\nDialogue: 0,0:34:35.19,0:34:36.28,EN,,0,0,0,,Well, in any case,\nDialogue: 0,0:34:37.05,0:34:39.48,EN,,0,0,0,,you're pretty much seeing the whole thing now.\nDialogue: 0,0:34:41.88,0:34:43.29,EN,,0,0,0,,It's a very beautiful thing,\nDialogue: 0,0:34:44.19,0:34:46.00,EN,,0,0,0,,even though it's written in an ugly style,\nDialogue: 0,0:34:46.76,0:34:48.30,EN,,0,0,0,,being the kernel of every language.\nDialogue: 0,0:34:49.60,0:34:51.37,EN,,0,0,0,,I suggest that we just-- let's look at it for a while.\nDialogue: 0,0:35:00.32,0:35:47.02,EN,,0,0,0,,[ALSO SPRACH ZARATHUSTRA]\nDialogue: 0,0:35:49.75,0:35:50.91,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:36:01.18,0:36:03.29,EN,,0,0,0,,Alright, I suppose it's time to take a small break then.\nDialogue: 0,0:36:04.04,0:36:10.73,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:36:56.78,0:36:58.99,EN,,0,0,0,,OK, now we're just going to do a little bit of practice\nDialogue: 0,0:36:59.29,0:37:02.67,EN,,0,0,0,,understanding what it is we've just shown you. OK?\nDialogue: 0,0:37:03.47,0:37:05.48,EN,,0,0,0,,What we're going to do is go through, in detail,\nDialogue: 0,0:37:05.50,0:37:10.36,EN,,0,0,0,,an evaluation by informally substituting through the interpreter.\nDialogue: 0,0:37:11.50,0:37:14.94,EN,,0,0,0,,And since we have no assignments or definitions in this interpreter,\nDialogue: 0,0:37:15.20,0:37:17.34,EN,,0,0,0,,we have no possible side effects,\nDialogue: 0,0:37:17.98,0:37:22.03,EN,,0,0,0,,and so the we can do substitution with impunity\nDialogue: 0,0:37:22.52,0:37:24.59,EN,,0,0,0,,and not worry about results.\nDialogue: 0,0:37:25.33,0:37:27.80,EN,,0,0,0,,So the particular problem I'd like to look at\nDialogue: 0,0:37:28.06,0:37:29.63,EN,,0,0,0,,is it an interesting one.\nDialogue: 0,0:37:30.69,0:37:34.09,EN,,0,0,0,,It's the evaluation of\nDialogue: 0,0:37:34.91,0:37:48.08,EN,,0,0,0,,quote, open, open, open, lambda of x, lambda of y plus x y,\nDialogue: 0,0:37:50.30,0:37:52.62,EN,,0,0,0,,lambda, lambda,\nDialogue: 0,0:37:53.04,0:37:56.12,EN,,0,0,0,,applied to three, applied to four,\nDialogue: 0,0:37:56.94,0:37:59.58,EN,,0,0,0,,in some global environment which I'll call e0.\nDialogue: 0,0:38:04.93,0:38:05.96,EN,,0,0,0,,So what we have here\nDialogue: 0,0:38:06.36,0:38:08.04,EN,,0,0,0,,is a procedure of one argument x,\nDialogue: 0,0:38:08.09,0:38:11.05,EN,,0,0,0,,which produces as its value a procedure of one argument y,\nDialogue: 0,0:38:11.07,0:38:12.12,EN,,0,0,0,,which adds x to y.\nDialogue: 0,0:38:14.30,0:38:17.96,EN,,0,0,0,,We are applying the procedure of one argument x to three.\nDialogue: 0,0:38:17.96,0:38:19.39,EN,,0,0,0,,So x should become three.\nDialogue: 0,0:38:21.40,0:38:23.98,EN,,0,0,0,,And the result of that should be procedure of one argument y,\nDialogue: 0,0:38:24.33,0:38:25.82,EN,,0,0,0,,which will then apply to 4.\nDialogue: 0,0:38:28.91,0:38:30.32,EN,,0,0,0,,And there is a very simple case,\nDialogue: 0,0:38:31.04,0:38:32.73,EN,,0,0,0,,they will then add those results.\nDialogue: 0,0:38:34.79,0:38:35.82,EN,,0,0,0,,And now in order to do that,\nDialogue: 0,0:38:35.84,0:38:37.76,EN,,0,0,0,,I want to make a very simple environment model.\nDialogue: 0,0:38:37.90,0:38:40.48,EN,,0,0,0,,And at this point, you should already have in your mind\nDialogue: 0,0:38:40.99,0:38:42.59,EN,,0,0,0,,the environments that this produces.\nDialogue: 0,0:38:44.46,0:38:46.62,EN,,0,0,0,,But we're going to start out with a global environment,\nDialogue: 0,0:38:48.59,0:38:50.06,EN,,0,0,0,,which I'll call e0,\nDialogue: 0,0:38:54.60,0:38:55.47,EN,,0,0,0,,which is that.\nDialogue: 0,0:38:56.74,0:39:02.46,EN,,0,0,0,,And it's going to have in it things, definitions for plus, and times,\nDialogue: 0,0:39:06.30,0:39:10.36,EN,,0,0,0,,and-- using Greek letters, isn't that interesting, for the objects--\nDialogue: 0,0:39:11.21,0:39:27.93,EN,,0,0,0,,and minus, and quotient, and CAR, and CDR, and CONS, and EQ,\nDialogue: 0,0:39:28.59,0:39:31.05,EN,,0,0,0,,and everything else you might imagine in a global environment.\nDialogue: 0,0:39:31.27,0:39:33.82,EN,,0,0,0,,It's got something there for each of those things,\nDialogue: 0,0:39:34.62,0:39:36.09,EN,,0,0,0,,something the machine is born with,\nDialogue: 0,0:39:37.10,0:39:38.09,EN,,0,0,0,,that's e0.\nDialogue: 0,0:39:39.22,0:39:41.84,EN,,0,0,0,,Now what does it mean to do this evaluation?\nDialogue: 0,0:39:42.94,0:39:45.18,EN,,0,0,0,,Well, we go through the set of special forms.\nDialogue: 0,0:39:45.69,0:39:47.05,EN,,0,0,0,,First of all, this is not a number.\nDialogue: 0,0:39:48.67,0:39:50.38,EN,,0,0,0,,This is not a symbol.\nDialogue: 0,0:39:53.13,0:39:55.60,EN,,0,0,0,,Gee, it's not a quoted expression.\nDialogue: 0,0:39:56.60,0:39:58.38,EN,,0,0,0,,This is a quoted expression,\nDialogue: 0,0:39:59.47,0:40:00.80,EN,,0,0,0,,but that's not what I mentioned.\nDialogue: 0,0:40:00.83,0:40:01.36,EN,,0,0,0,,The question is,\nDialogue: 0,0:40:01.39,0:40:04.96,EN,,0,0,0,,whether or not the thing which is quoted is quoted expression?\nDialogue: 0,0:40:05.89,0:40:07.96,EN,,0,0,0,,I'm evaluating an expression.\nDialogue: 0,0:40:07.96,0:40:09.98,EN,,0,0,0,,This just says it's this particular expression.\nDialogue: 0,0:40:11.41,0:40:12.66,EN,,0,0,0,,This is not a quoted expression.\nDialogue: 0,0:40:13.71,0:40:17.21,EN,,0,0,0,,OK? It's not a thing that begins with lambda.\nDialogue: 0,0:40:19.12,0:40:20.67,EN,,0,0,0,,It's not a thing that begins with COND.\nDialogue: 0,0:40:22.03,0:40:25.95,EN,,0,0,0,,Therefore, it's an application of its of an operated operands.\nDialogue: 0,0:40:26.31,0:40:27.12,EN,,0,0,0,,It's a combination.\nDialogue: 0,0:40:28.57,0:40:30.70,EN,,0,0,0,,The combination thus has\nDialogue: 0,0:40:30.89,0:40:34.00,EN,,0,0,0,,this as the operator\nDialogue: 0,0:40:34.64,0:40:36.08,EN,,0,0,0,,and this is the operands.\nDialogue: 0,0:40:40.13,0:40:42.41,EN,,0,0,0,,Well, that means that what I'm going to do is\nDialogue: 0,0:40:42.57,0:40:47.90,EN,,0,0,0,,transform this into apply of eval,\nDialogue: 0,0:40:50.12,0:40:57.61,EN,,0,0,0,,of quote, open, open lambda of x, lambda of y--\nDialogue: 0,0:40:57.88,0:40:59.12,EN,,0,0,0,,I'm evaluating the operator--\nDialogue: 0,0:40:59.95,0:41:04.19,EN,,0,0,0,,plus x y, in the environment,\nDialogue: 0,0:41:07.26,0:41:08.64,EN,,0,0,0,,also e0,\nDialogue: 0,0:41:12.78,0:41:15.20,EN,,0,0,0,,with the operands that I'm going to apply this to,\nDialogue: 0,0:41:15.26,0:41:17.28,EN,,0,0,0,,the arguments being the result of EVLIST,\nDialogue: 0,0:41:21.21,0:41:24.49,EN,,0,0,0,,the list containing four, fin e0.\nDialogue: 0,0:41:29.01,0:41:31.26,EN,,0,0,0,,I'm using this funny notation here for e0\nDialogue: 0,0:41:32.32,0:41:34.83,EN,,0,0,0,,because this should be that environment.\nDialogue: 0,0:41:35.45,0:41:37.77,EN,,0,0,0,,I haven't a name for it,\nDialogue: 0,0:41:37.80,0:41:39.15,EN,,0,0,0,,because I have no environment to name it in.\nDialogue: 0,0:41:41.96,0:41:44.09,EN,,0,0,0,,So this is just a representation\nDialogue: 0,0:41:44.17,0:41:46.17,EN,,0,0,0,,what would be a quoted expression, if you will.\nDialogue: 0,0:41:47.73,0:41:51.16,EN,,0,0,0,,The data structure, which is the environment, goes there.\nDialogue: 0,0:41:53.04,0:41:55.04,EN,,0,0,0,,Well, that's what we're seeing here.\nDialogue: 0,0:41:55.85,0:41:56.67,EN,,0,0,0,,Well in order to do this,\nDialogue: 0,0:41:56.68,0:41:58.04,EN,,0,0,0,,I have to do this, and I have to do that.\nDialogue: 0,0:41:59.61,0:42:00.49,EN,,0,0,0,,Well this one's easy,\nDialogue: 0,0:42:00.57,0:42:03.18,EN,,0,0,0,,so why don't we do that one first. OK?\nDialogue: 0,0:42:03.77,0:42:07.44,EN,,0,0,0,,This turns into apply of eval--\nDialogue: 0,0:42:07.45,0:42:08.83,EN,,0,0,0,,just copying something now.\nDialogue: 0,0:42:09.42,0:42:11.00,EN,,0,0,0,,Most of the substitution rule is copying.\nDialogue: 0,0:42:18.53,0:42:21.24,EN,,0,0,0,,So I'm going to not say the words when I copy,\nDialogue: 0,0:42:21.71,0:42:23.87,EN,,0,0,0,,because it's faster.\nDialogue: 0,0:42:26.41,0:42:28.64,EN,,0,0,0,,And then the EVLIST is going to turn into a\nDialogue: 0,0:42:28.65,0:42:36.72,EN,,0,0,0,,cons, of eval, of four, in e0--\nDialogue: 0,0:42:38.78,0:42:40.17,EN,,0,0,0,,because it was not an empty list--\nDialogue: 0,0:42:41.44,0:42:49.39,EN,,0,0,0,,onto the result of EVLISTing, on the empty list, in e0.\nDialogue: 0,0:42:52.58,0:42:54.20,EN,,0,0,0,,And I'm going to start leaving out steps soon,\nDialogue: 0,0:42:54.24,0:42:55.36,EN,,0,0,0,,because it's going to get boring.\nDialogue: 0,0:42:59.87,0:43:05.42,EN,,0,0,0,,But this is basically the same thing as apply, of eval--\nDialogue: 0,0:43:07.50,0:43:08.54,EN,,0,0,0,,I'm going to keep doing this--\nDialogue: 0,0:43:10.68,0:43:20.24,EN,,0,0,0,,the lambda of x, the lambda of y, plus xy, 3, close, e0.\nDialogue: 0,0:43:20.24,0:43:21.20,EN,,0,0,0,,I'm a pretty good machine.\nDialogue: 0,0:43:24.24,0:43:26.24,EN,,0,0,0,,Well, eval of four,\nDialogue: 0,0:43:26.56,0:43:28.44,EN,,0,0,0,,that's meets the question, is it a number.\nDialogue: 0,0:43:29.00,0:43:33.90,EN,,0,0,0,,So that's cons, right, cons of 4.\nDialogue: 0,0:43:34.03,0:43:37.47,EN,,0,0,0,,And EVLIST of the empty list is the empty list,\nDialogue: 0,0:43:38.33,0:43:39.24,EN,,0,0,0,,so that's this.\nDialogue: 0,0:43:42.62,0:43:45.08,EN,,0,0,0,,OK. And that's very simple to understand,\nDialogue: 0,0:43:45.10,0:43:47.44,EN,,0,0,0,,because that means the list containing four itself.\nDialogue: 0,0:43:48.71,0:43:53.84,EN,,0,0,0,,So this is nothing more than apply of eval,\nDialogue: 0,0:43:55.28,0:44:02.51,EN,,0,0,0,,quote, open, open, lambda of x, lambda of y, plus x y,\nDialogue: 0,0:44:03.40,0:44:07.48,EN,,0,0,0,,three applied to, e0, applied to the list four--\nDialogue: 0,0:44:08.68,0:44:12.60,EN,,0,0,0,,applied to the list four-- bang\nDialogue: 0,0:44:13.94,0:44:15.05,EN,,0,0,0,,So that's that step.\nDialogue: 0,0:44:17.00,0:44:19.96,EN,,0,0,0,,Now let's look at the next, more interesting thing.\nDialogue: 0,0:44:20.36,0:44:21.72,EN,,0,0,0,,What do I do to evaluate that?\nDialogue: 0,0:44:23.07,0:44:24.44,EN,,0,0,0,,Evaluating this means\nDialogue: 0,0:44:25.20,0:44:28.65,EN,,0,0,0,,means I have to evaluate-- Well, it's not.\nDialogue: 0,0:44:29.46,0:44:31.04,EN,,0,0,0,,It's nothing but an application.\nDialogue: 0,0:44:31.68,0:44:33.10,EN,,0,0,0,,It's not one of the special things.\nDialogue: 0,0:44:33.57,0:44:36.51,EN,,0,0,0,,If the application of this operator,\nDialogue: 0,0:44:36.51,0:44:37.37,EN,,0,0,0,,which we see here--\nDialogue: 0,0:44:37.66,0:44:38.94,EN,,0,0,0,,here's the operator--\nDialogue: 0,0:44:40.19,0:44:41.77,EN,,0,0,0,,applied to this operands,\nDialogue: 0,0:44:44.54,0:44:45.74,EN,,0,0,0,,that combination.\nDialogue: 0,0:44:46.72,0:44:48.25,EN,,0,0,0,,But we know how to do that,\nDialogue: 0,0:44:48.84,0:44:52.37,EN,,0,0,0,,because that's the last case of the conditional.\nDialogue: 0,0:44:52.37,0:44:55.52,EN,,0,0,0,,So substituting in for this evaluation,\nDialogue: 0,0:44:55.71,0:44:57.47,EN,,0,0,0,,it's apply of eval of the operator\nDialogue: 0,0:44:57.50,0:44:59.00,EN,,0,0,0,,in the EVLIST of the operands.\nDialogue: 0,0:45:01.16,0:45:08.20,EN,,0,0,0,,Well, it's apply, of apply, of eval,\nDialogue: 0,0:45:10.57,0:45:21.07,EN,,0,0,0,,of quote, open, lambda of x, lambda of y, plus x y,\nDialogue: 0,0:45:21.80,0:45:23.45,EN,,0,0,0,,lambda, lambda,\nDialogue: 0,0:45:23.74,0:45:25.42,EN,,0,0,0,,in environment e0.\nDialogue: 0,0:45:30.52,0:45:32.67,EN,,0,0,0,,I'm going to short circuit the evaluation of the operands,\nDialogue: 0,0:45:32.68,0:45:34.14,EN,,0,0,0,,because they're the same as they were before.\nDialogue: 0,0:45:35.23,0:45:36.48,EN,,0,0,0,,I got a list containing three,\nDialogue: 0,0:45:36.51,0:45:39.16,EN,,0,0,0,,apply that, and apply that to four.\nDialogue: 0,0:45:42.44,0:45:43.56,EN,,0,0,0,,Well let's see.\nDialogue: 0,0:45:44.41,0:45:46.38,EN,,0,0,0,,Eval of a lambda expression\nDialogue: 0,0:45:48.01,0:45:49.45,EN,,0,0,0,,produces a procedure object.\nDialogue: 0,0:45:52.03,0:45:57.88,EN,,0,0,0,,So this is apply, of apply,\nDialogue: 0,0:46:00.30,0:46:02.27,EN,,0,0,0,,of the procedure object closure,\nDialogue: 0,0:46:04.52,0:46:08.68,EN,,0,0,0,,which contains the body of the procedure, x,\nDialogue: 0,0:46:08.94,0:46:11.92,EN,,0,0,0,,which is lambda, which binds x [UNINTELLIGIBLE]\nDialogue: 0,0:46:12.13,0:46:15.40,EN,,0,0,0,,the internals of the body,\nDialogue: 0,0:46:15.80,0:46:18.17,EN,,0,0,0,,it returns the procedure of one argument y,\nDialogue: 0,0:46:18.56,0:46:20.63,EN,,0,0,0,,which adds x to y.\nDialogue: 0,0:46:23.21,0:46:25.50,EN,,0,0,0,,Environment e0 is now captured in it,\nDialogue: 0,0:46:27.24,0:46:29.63,EN,,0,0,0,,because this was evaluated with respect to e0.\nDialogue: 0,0:46:30.11,0:46:32.43,EN,,0,0,0,,e0 is part now of the closure object.\nDialogue: 0,0:46:33.04,0:46:38.19,EN,,0,0,0,,Apply that to open, three, close, apply,\nDialogue: 0,0:46:38.81,0:46:41.30,EN,,0,0,0,,to open, 4, close, apply.\nDialogue: 0,0:46:47.39,0:46:49.29,EN,,0,0,0,,So going from this step to this step\nDialogue: 0,0:46:49.31,0:46:50.89,EN,,0,0,0,,meant that I made up a procedure object\nDialogue: 0,0:46:50.91,0:46:52.03,EN,,0,0,0,,which captured in it\nDialogue: 0,0:46:53.88,0:46:55.98,EN,,0,0,0,,e0 as part of the procedure object.\nDialogue: 0,0:46:57.15,0:46:58.51,EN,,0,0,0,,Now, we're going to pass those to apply.\nDialogue: 0,0:46:58.52,0:46:59.71,EN,,0,0,0,,We have to apply this procedure\nDialogue: 0,0:47:00.48,0:47:01.58,EN,,0,0,0,,to that set of arguments.\nDialogue: 0,0:47:02.71,0:47:06.51,EN,,0,0,0,,Well, but that procedure is not primitive.\nDialogue: 0,0:47:07.38,0:47:09.88,EN,,0,0,0,,It's, in fact, a thing which has got the tag closure,\nDialogue: 0,0:47:10.24,0:47:12.09,EN,,0,0,0,,and, therefore, what we have to do is do a bind.\nDialogue: 0,0:47:13.71,0:47:14.72,EN,,0,0,0,,We have to bind.\nDialogue: 0,0:47:15.83,0:47:19.40,EN,,0,0,0,,A new environment is made at this point,\nDialogue: 0,0:47:20.44,0:47:22.80,EN,,0,0,0,,which has as its parent environment\nDialogue: 0,0:47:22.94,0:47:27.56,EN,,0,0,0,,the one over here, e0, that environment.\nDialogue: 0,0:47:30.32,0:47:31.57,EN,,0,0,0,,And we'll call this one, e1.\nDialogue: 0,0:47:34.62,0:47:35.74,EN,,0,0,0,,Now what's bound in there?\nDialogue: 0,0:47:36.04,0:47:37.48,EN,,0,0,0,,x is bound to three.\nDialogue: 0,0:47:38.62,0:47:40.44,EN,,0,0,0,,So I have x equal three.\nDialogue: 0,0:47:41.48,0:47:42.33,EN,,0,0,0,,That's what's in there.\nDialogue: 0,0:47:44.94,0:47:46.24,EN,,0,0,0,,And we'll call that e1.\nDialogue: 0,0:47:46.24,0:47:48.44,EN,,0,0,0,,So what this transforms into\nDialogue: 0,0:47:49.13,0:47:50.72,EN,,0,0,0,,is an eval of the body\nDialogue: 0,0:47:51.72,0:47:53.07,EN,,0,0,0,,of this, which is this,\nDialogue: 0,0:47:54.40,0:47:55.72,EN,,0,0,0,,the body of that procedure,\nDialogue: 0,0:47:56.44,0:47:58.52,EN,,0,0,0,,in the environment that you just saw.\nDialogue: 0,0:48:00.29,0:48:05.05,EN,,0,0,0,,So that's an apply, of eval,\nDialogue: 0,0:48:06.92,0:48:16.43,EN,,0,0,0,,quote, open, lambda of y, plus x y-- the body-- in e1.\nDialogue: 0,0:48:20.49,0:48:22.48,EN,,0,0,0,,And apply the result of that to four,\nDialogue: 0,0:48:23.68,0:48:26.73,EN,,0,0,0,,open, close, 4-- list of arguments.\nDialogue: 0,0:48:28.43,0:48:29.87,EN,,0,0,0,,Well, that's sensible enough\nDialogue: 0,0:48:30.08,0:48:32.27,EN,,0,0,0,,because evaluating a lambda, I know what to do.\nDialogue: 0,0:48:33.11,0:48:34.17,EN,,0,0,0,,That means I apply,\nDialogue: 0,0:48:37.16,0:48:38.92,EN,,0,0,0,,the procedure which is closure,\nDialogue: 0,0:48:43.74,0:48:46.84,EN,,0,0,0,,binds one argument y, adds x to y,\nDialogue: 0,0:48:49.28,0:48:52.15,EN,,0,0,0,,with e1 captured in it.\nDialogue: 0,0:48:55.79,0:48:57.42,EN,,0,0,0,,And you should really see this. Right?\nDialogue: 0,0:48:57.80,0:49:00.14,EN,,0,0,0,,I somehow manufactured a closure.\nDialogue: 0,0:49:00.14,0:49:01.16,EN,,0,0,0,,I should've put this here.\nDialogue: 0,0:49:01.79,0:49:03.04,EN,,0,0,0,,There was one over here too.\nDialogue: 0,0:49:05.90,0:49:07.47,EN,,0,0,0,,OK? Well, there's one here now.\nDialogue: 0,0:49:08.08,0:49:09.80,EN,,0,0,0,,I've captured e1,\nDialogue: 0,0:49:10.41,0:49:14.25,EN,,0,0,0,,and this is the procedure of one argument y,\nDialogue: 0,0:49:15.45,0:49:16.70,EN,,0,0,0,,whatever this is.\nDialogue: 0,0:49:18.09,0:49:20.72,EN,,0,0,0,,That's what that is there, that closure.\nDialogue: 0,0:49:22.57,0:49:26.46,EN,,0,0,0,,OK? I'm going to apply that to four.\nDialogue: 0,0:49:30.28,0:49:31.77,EN,,0,0,0,,OK. Well, that's easy enough.\nDialogue: 0,0:49:36.83,0:49:38.73,EN,,0,0,0,,That means I have to make a new environment\nDialogue: 0,0:49:38.86,0:49:40.52,EN,,0,0,0,,by copying this pointer,\nDialogue: 0,0:49:41.56,0:49:43.21,EN,,0,0,0,,which was the pointer of the procedure,\nDialogue: 0,0:49:44.94,0:49:48.96,EN,,0,0,0,,which binds y equal 4 with that environment.\nDialogue: 0,0:49:49.82,0:49:52.22,EN,,0,0,0,,And here's my new environment, which I'll call e2.\nDialogue: 0,0:49:56.03,0:49:58.12,EN,,0,0,0,,And, of course, this application then\nDialogue: 0,0:49:58.22,0:50:00.33,EN,,0,0,0,,is evaluate the body in e2.\nDialogue: 0,0:50:01.58,0:50:07.87,EN,,0,0,0,,So this is eval, the body,\nDialogue: 0,0:50:07.90,0:50:11.85,EN,,0,0,0,,which is plus x y, in the environment e2.\nDialogue: 0,0:50:13.71,0:50:14.94,EN,,0,0,0,,But this is an application,\nDialogue: 0,0:50:15.48,0:50:23.88,EN,,0,0,0,,so this is the apply, of eval, plus in e2,\nDialogue: 0,0:50:26.33,0:50:37.34,EN,,0,0,0,,an EVLIST, quote, open, x y, in e2.\nDialogue: 0,0:50:44.88,0:50:45.59,EN,,0,0,0,,Well, but let's see.\nDialogue: 0,0:50:45.59,0:50:51.71,EN,,0,0,0,,That is apply, the object\nDialogue: 0,0:50:52.08,0:50:53.87,EN,,0,0,0,,which is a result of that and plus.\nDialogue: 0,0:50:54.19,0:50:55.66,EN,,0,0,0,,So here we are in e2,\nDialogue: 0,0:50:55.69,0:50:57.72,EN,,0,0,0,,plus is not here, it's not here,\nDialogue: 0,0:50:57.74,0:51:01.05,EN,,0,0,0,,yes, but's here as some primitive operator.\nDialogue: 0,0:51:01.78,0:51:04.74,EN,,0,0,0,,So it's the primitive operator for addition.\nDialogue: 0,0:51:07.47,0:51:14.12,EN,,0,0,0,,Apply that to the result of evaluating x and y in e2.\nDialogue: 0,0:51:14.37,0:51:17.00,EN,,0,0,0,,But we can see that x is three and y is four.\nDialogue: 0,0:51:18.11,0:51:23.31,EN,,0,0,0,,So that's a three and four, here.\nDialogue: 0,0:51:24.16,0:51:26.28,EN,,0,0,0,,And that magically produces for me a seven.\nDialogue: 0,0:51:30.52,0:51:32.44,EN,,0,0,0,,I wanted to go through this so you would see,\nDialogue: 0,0:51:32.70,0:51:34.73,EN,,0,0,0,,essentially, one important ingredient,\nDialogue: 0,0:51:35.76,0:51:37.29,EN,,0,0,0,,which is what's being passed around,\nDialogue: 0,0:51:37.31,0:51:39.56,EN,,0,0,0,,and who owns what, and what his job is.\nDialogue: 0,0:51:40.47,0:51:41.61,EN,,0,0,0,,So what do we have here?\nDialogue: 0,0:51:41.70,0:51:42.62,EN,,0,0,0,,We have eval,\nDialogue: 0,0:51:44.80,0:51:45.64,EN,,0,0,0,,We have eval, and we have apply,\nDialogue: 0,0:51:45.66,0:51:46.62,EN,,0,0,0,,the two main players.\nDialogue: 0,0:51:49.37,0:51:51.56,EN,,0,0,0,,And there is a big loop the goes around like this.\nDialogue: 0,0:51:52.32,0:52:04.57,EN,,0,0,0,,Which is eval produces a procedure and arguments for apply.\nDialogue: 0,0:52:06.27,0:52:08.57,EN,,0,0,0,,Now some things eval could do by itself.\nDialogue: 0,0:52:09.50,0:52:10.86,EN,,0,0,0,,Those are little self things here.\nDialogue: 0,0:52:10.86,0:52:11.74,EN,,0,0,0,,They're not interesting.\nDialogue: 0,0:52:12.70,0:52:15.60,EN,,0,0,0,,Also eval evaluates all of the arguments, one after another.\nDialogue: 0,0:52:16.24,0:52:17.28,EN,,0,0,0,,That's not very interesting.\nDialogue: 0,0:52:17.65,0:52:20.09,EN,,0,0,0,,Apply can apply some procedures like plus,\nDialogue: 0,0:52:21.02,0:52:22.04,EN,,0,0,0,,not very interesting.\nDialogue: 0,0:52:22.30,0:52:24.64,EN,,0,0,0,,However, if apply can't apply a procedure like plus,\nDialogue: 0,0:52:25.31,0:52:33.31,EN,,0,0,0,,it produces an expression and environment for eval.\nDialogue: 0,0:52:35.47,0:52:37.61,EN,,0,0,0,,The procedural arguments wrap up\nDialogue: 0,0:52:38.24,0:52:40.60,EN,,0,0,0,,essentially the state of a computation\nDialogue: 0,0:52:41.66,0:52:43.42,EN,,0,0,0,,and, certainly, the expression of environment.\nDialogue: 0,0:52:43.74,0:52:45.31,EN,,0,0,0,,And so what we're actually going to do next\nDialogue: 0,0:52:45.32,0:52:46.46,EN,,0,0,0,,is not the complete state,\nDialogue: 0,0:52:46.48,0:52:48.82,EN,,0,0,0,,because it doesn't say who wants the answers.\nDialogue: 0,0:52:51.28,0:52:52.20,EN,,0,0,0,,But what we're going to do--\nDialogue: 0,0:52:52.24,0:52:54.80,EN,,0,0,0,,it's always got something like an expression of environment\nDialogue: 0,0:52:54.99,0:52:56.14,EN,,0,0,0,,or procedure and arguments\nDialogue: 0,0:52:56.28,0:52:58.08,EN,,0,0,0,,as the main loop that we're going around.\nDialogue: 0,0:52:58.97,0:53:01.80,EN,,0,0,0,,There are minor little sub loops like eval through EVLIST,\nDialogue: 0,0:53:04.49,0:53:06.76,EN,,0,0,0,,or eval through evcond,\nDialogue: 0,0:53:09.10,0:53:11.96,EN,,0,0,0,,or apply through a primitive apply.\nDialogue: 0,0:53:16.14,0:53:17.64,EN,,0,0,0,,But they're not the essential things.\nDialogue: 0,0:53:18.86,0:53:20.28,EN,,0,0,0,,So that's what I wanted you to see.\nDialogue: 0,0:53:21.86,0:53:22.88,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:53:25.93,0:53:27.37,EN,,0,0,0,,Yes. David\nDialogue: 0,0:53:27.74,0:53:33.31,EN,,0,0,0,,AUDIENCE: I'm trying to understand how x got down to three\nDialogue: 0,0:53:34.01,0:53:36.30,EN,,0,0,0,,instead of four.\nDialogue: 0,0:53:37.07,0:53:38.52,EN,,0,0,0,,At the early part of the--\nDialogue: 0,0:53:38.56,0:53:40.54,EN,,0,0,0,,PROFESSOR: Here.\nDialogue: 0,0:53:41.31,0:53:43.31,EN,,0,0,0,,You want to know how x got down to three?\nDialogue: 0,0:53:43.52,0:53:47.42,EN,,0,0,0,,AUDIENCE: Because x is the outer procedure,\nDialogue: 0,0:53:48.46,0:53:50.99,EN,,0,0,0,,and x and y are the inner procedure.\nDialogue: 0,0:53:51.26,0:53:51.88,EN,,0,0,0,,PROFESSOR: Fine.\nDialogue: 0,0:53:52.84,0:53:54.62,EN,,0,0,0,,Well, I was very careful and mechanical.\nDialogue: 0,0:53:55.02,0:53:56.92,EN,,0,0,0,,First of all, I should write those procedures\nDialogue: 0,0:53:56.94,0:53:58.41,EN,,0,0,0,,again for you, pretty printed.\nDialogue: 0,0:54:00.61,0:54:01.47,EN,,0,0,0,,First order of business,\nDialogue: 0,0:54:01.48,0:54:02.99,EN,,0,0,0,,because you're probably not reading them well.\nDialogue: 0,0:54:03.83,0:54:04.70,EN,,0,0,0,,So I have here\nDialogue: 0,0:54:05.15,0:54:09.60,EN,,0,0,0,,that procedure of-- was it x over there--\nDialogue: 0,0:54:11.21,0:54:14.99,EN,,0,0,0,,which is -- value of that procedure of y\nDialogue: 0,0:54:15.72,0:54:18.44,EN,,0,0,0,,which adds x to y,\nDialogue: 0,0:54:19.82,0:54:21.10,EN,,0,0,0,,lambda, lambda,\nDialogue: 0,0:54:21.40,0:54:22.89,EN,,0,0,0,,applied that to three,\nDialogue: 0,0:54:24.08,0:54:26.12,EN,,0,0,0,,takes the result of that, and applied that to four.\nDialogue: 0,0:54:26.14,0:54:28.81,EN,,0,0,0,,Is that not what I wrote? OK?\nDialogue: 0,0:54:28.81,0:54:32.33,EN,,0,0,0,,Now, you should immediately see that\nDialogue: 0,0:54:33.77,0:54:34.94,EN,,0,0,0,,here is an application--\nDialogue: 0,0:54:35.16,0:54:36.46,EN,,0,0,0,,let me get a white piece of chalk--\nDialogue: 0,0:54:37.32,0:54:41.12,EN,,0,0,0,,here is an application, a combination.\nDialogue: 0,0:54:43.44,0:54:46.40,EN,,0,0,0,,OK? That combination has this as the operator\nDialogue: 0,0:54:48.14,0:54:49.55,EN,,0,0,0,,and this as the operand.\nDialogue: 0,0:54:51.04,0:54:53.05,EN,,0,0,0,,The three is going in for the x here.\nDialogue: 0,0:54:54.90,0:54:56.36,EN,,0,0,0,,The result of this\nDialogue: 0,0:54:56.56,0:54:58.46,EN,,0,0,0,,is a procedure of one argument y,\nDialogue: 0,0:54:58.73,0:54:59.79,EN,,0,0,0,,which gets applied to four.\nDialogue: 0,0:55:00.88,0:55:01.58,EN,,0,0,0,,OK?\nDialogue: 0,0:55:02.20,0:55:04.08,EN,,0,0,0,,So you just weren't reading the expression right.\nDialogue: 0,0:55:04.40,0:55:07.85,EN,,0,0,0,,The way you see that over here. OK.\nDialogue: 0,0:55:09.42,0:55:12.96,EN,,0,0,0,,is that here I have the actual procedure object, x.\nDialogue: 0,0:55:13.34,0:55:15.31,EN,,0,0,0,,It's getting applied to three,\nDialogue: 0,0:55:15.95,0:55:17.07,EN,,0,0,0,,the list containing three.\nDialogue: 0,0:55:18.98,0:55:21.34,EN,,0,0,0,,What I'm left over with is something which gets applied to four.\nDialogue: 0,0:55:24.08,0:55:25.20,EN,,0,0,0,,Are there any other questions?\nDialogue: 0,0:55:28.35,0:55:30.38,EN,,0,0,0,,Time for our next small break then.\nDialogue: 0,0:55:30.83,0:55:31.37,EN,,0,0,0,,Thank you.\nDialogue: 0,0:55:33.73,0:55:41.40,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:56:08.41,0:56:11.29,EN,,0,0,0,,PROFESSOR: Let's see, at this point,\nDialogue: 0,0:56:13.32,0:56:14.59,EN,,0,0,0,,you should be getting the feeling,\nDialogue: 0,0:56:14.75,0:56:17.96,EN,,0,0,0,,what's this nonsense this Sussman character is feeding me?\nDialogue: 0,0:56:20.74,0:56:23.92,EN,,0,0,0,,There's an awful lot of strange nonsense here.\nDialogue: 0,0:56:24.80,0:56:27.40,EN,,0,0,0,,After all, he purported to explain to me Lisp,\nDialogue: 0,0:56:28.01,0:56:29.90,EN,,0,0,0,,and he wrote me a Lisp program on the blackboard.\nDialogue: 0,0:56:31.23,0:56:33.53,EN,,0,0,0,,The Lisp program was intended to be interpreted for Lisp,\nDialogue: 0,0:56:33.85,0:56:35.02,EN,,0,0,0,,but you need a Lisp interpreter\nDialogue: 0,0:56:35.04,0:56:36.30,EN,,0,0,0,,in order to understand that program.\nDialogue: 0,0:56:38.37,0:56:40.19,EN,,0,0,0,,How could that program have told me anything\nDialogue: 0,0:56:40.22,0:56:43.20,EN,,0,0,0,,there is to be known about Lisp?\nDialogue: 0,0:56:44.15,0:56:46.22,EN,,0,0,0,,How is that not completely vacuous?\nDialogue: 0,0:56:48.49,0:56:50.25,EN,,0,0,0,,It's a very strange thing.\nDialogue: 0,0:56:50.99,0:56:52.43,EN,,0,0,0,,Does it tell me anything at all?\nDialogue: 0,0:56:56.07,0:56:57.20,EN,,0,0,0,,Well, you see, the whole thing\nDialogue: 0,0:56:57.32,0:56:59.79,EN,,0,0,0,,is sort of like these Escher's hands\nDialogue: 0,0:57:00.46,0:57:03.55,EN,,0,0,0,,that we see on this slide.\nDialogue: 0,0:57:06.18,0:57:07.72,EN,,0,0,0,,Yes, eval and apply\nDialogue: 0,0:57:07.76,0:57:10.16,EN,,0,0,0,,each sort of draw each other\nDialogue: 0,0:57:11.50,0:57:14.16,EN,,0,0,0,,and construct the real thing,\nDialogue: 0,0:57:14.86,0:57:16.30,EN,,0,0,0,,which can sit out and draw itself.\nDialogue: 0,0:57:17.11,0:57:18.46,EN,,0,0,0,,Escher was a very brilliant man,\nDialogue: 0,0:57:18.68,0:57:20.41,EN,,0,0,0,,he just didn't know the names of these spirits.\nDialogue: 0,0:57:23.91,0:57:25.00,EN,,0,0,0,,Well, I'm going to do now,\nDialogue: 0,0:57:26.09,0:57:28.00,EN,,0,0,0,,is I'm going to try to convince you\nDialogue: 0,0:57:28.16,0:57:29.87,EN,,0,0,0,,that both this mean something,\nDialogue: 0,0:57:30.16,0:57:31.98,EN,,0,0,0,,and, as a aside,\nDialogue: 0,0:57:32.99,0:57:34.72,EN,,0,0,0,,I'm going to show you why you don't need definitions.\nDialogue: 0,0:57:36.09,0:57:37.71,EN,,0,0,0,,Just turns out that sort of falls out,\nDialogue: 0,0:57:38.09,0:57:41.12,EN,,0,0,0,,why definitions are not essential in a mathematical sense\nDialogue: 0,0:57:42.51,0:57:44.89,EN,,0,0,0,,for doing all the things we need to do for computing.\nDialogue: 0,0:57:49.10,0:57:50.03,EN,,0,0,0,,Well, let's see here.\nDialogue: 0,0:57:50.69,0:57:53.31,EN,,0,0,0,,Consider the following small program,\nDialogue: 0,0:57:53.74,0:57:54.64,EN,,0,0,0,,what does it mean?\nDialogue: 0,0:57:54.87,0:57:57.64,EN,,0,0,0,,This is a program for computing exponentials.\nDialogue: 0,0:58:07.27,0:58:13.23,EN,,0,0,0,,The exponential of x to the nth power is if--\nDialogue: 0,0:58:16.83,0:58:18.12,EN,,0,0,0,,n is zero,\nDialogue: 0,0:58:19.20,0:58:20.76,EN,,0,0,0,,then the result is one.\nDialogue: 0,0:58:22.07,0:58:22.81,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:58:25.56,0:58:28.48,EN,,0,0,0,,I want the product of x\nDialogue: 0,0:58:28.75,0:58:33.93,EN,,0,0,0,,and the result of exponentiating x to the n minus one power.\nDialogue: 0,0:58:43.69,0:58:44.56,EN,,0,0,0,,I think I got it right.\nDialogue: 0,0:58:46.63,0:58:48.72,EN,,0,0,0,,Now this is a recursive definition.\nDialogue: 0,0:58:49.47,0:58:52.17,EN,,0,0,0,,It's a definition of the exponentiation\nDialogue: 0,0:58:52.46,0:58:54.78,EN,,0,0,0,,procedure in terms of itself.\nDialogue: 0,0:58:56.41,0:58:58.32,EN,,0,0,0,,And, as it has been mentioned before,\nDialogue: 0,0:58:59.28,0:59:01.68,EN,,0,0,0,,your high school geometry teacher\nDialogue: 0,0:59:01.84,0:59:04.04,EN,,0,0,0,,probably gave you a hard time about things like that.\nDialogue: 0,0:59:05.65,0:59:06.73,EN,,0,0,0,,Was that justified?\nDialogue: 0,0:59:07.91,0:59:10.84,EN,,0,0,0,,Why does this self referential definition\nDialogue: 0,0:59:10.96,0:59:12.04,EN,,0,0,0,,make any sense?\nDialogue: 0,0:59:13.43,0:59:15.10,EN,,0,0,0,,Well, first of all, I'm going to convince you that\nDialogue: 0,0:59:15.13,0:59:17.60,EN,,0,0,0,,your high school geometry teacher was not telling you nonsense.\nDialogue: 0,0:59:20.37,0:59:23.42,EN,,0,0,0,,Consider the following set of definitions here.\nDialogue: 0,0:59:24.27,0:59:27.42,EN,,0,0,0,,x plus y equals three,\nDialogue: 0,0:59:28.24,0:59:32.24,EN,,0,0,0,,and x minus y equal one.\nDialogue: 0,0:59:33.07,0:59:35.56,EN,,0,0,0,,Well, gee, this tells you x in terms of y,\nDialogue: 0,0:59:35.58,0:59:37.84,EN,,0,0,0,,and this one tells you y in terms of x, presumably.\nDialogue: 0,0:59:40.15,0:59:42.95,EN,,0,0,0,,And yet this happens to have a unique solution in x and y.\nDialogue: 0,0:59:55.91,0:59:58.11,EN,,0,0,0,,However, I could also write\nDialogue: 0,0:59:59.87,1:00:04.25,EN,,0,0,0,,two x plus two y is six.\nDialogue: 0,1:00:06.83,1:00:09.87,EN,,0,0,0,,These two equations have an infinite number solutions.\nDialogue: 0,1:00:15.73,1:00:17.42,EN,,0,0,0,,And I could write you, for example,\nDialogue: 0,1:00:18.89,1:00:21.53,EN,,0,0,0,,x minus y equal 2,\nDialogue: 0,1:00:22.14,1:00:24.41,EN,,0,0,0,,and these two equations have no solutions.\nDialogue: 0,1:00:29.82,1:00:33.04,EN,,0,0,0,,Well, I have here three sets of simultaneous linear equations,\nDialogue: 0,1:00:35.45,1:00:39.51,EN,,0,0,0,,this set, this set, and this set.\nDialogue: 0,1:00:39.88,1:00:41.79,EN,,0,0,0,,But they have different numbers of solutions.\nDialogue: 0,1:00:42.90,1:00:45.76,EN,,0,0,0,,The number of solutions is not in the form of the equations.\nDialogue: 0,1:00:46.33,1:00:48.20,EN,,0,0,0,,They all three sets have the same form.\nDialogue: 0,1:00:48.54,1:00:50.41,EN,,0,0,0,,The number of solutions is in the content.\nDialogue: 0,1:00:53.00,1:00:55.15,EN,,0,0,0,,I can't tell by looking at the form of a definition\nDialogue: 0,1:00:55.16,1:00:56.24,EN,,0,0,0,,whether it makes sense,\nDialogue: 0,1:00:56.86,1:00:58.60,EN,,0,0,0,,only by its detailed content.\nDialogue: 0,1:00:59.66,1:01:00.88,EN,,0,0,0,,What are the coefficients,\nDialogue: 0,1:01:01.34,1:01:03.39,EN,,0,0,0,,for example, in the case of linear equations?\nDialogue: 0,1:01:05.10,1:01:06.72,EN,,0,0,0,,So I shouldn't expect to be able to tell\nDialogue: 0,1:01:06.99,1:01:08.33,EN,,0,0,0,,looking at something like this,\nDialogue: 0,1:01:08.59,1:01:09.95,EN,,0,0,0,,from some simple things like,\nDialogue: 0,1:01:10.08,1:01:14.49,EN,,0,0,0,,oh yes, EXPT is the solution of this recursion equation.\nDialogue: 0,1:01:16.03,1:01:18.41,EN,,0,0,0,,Expt is the procedure\nDialogue: 0,1:01:18.91,1:01:21.10,EN,,0,0,0,,which if substituted in here,\nDialogue: 0,1:01:22.04,1:01:24.06,EN,,0,0,0,,gives me expt back.\nDialogue: 0,1:01:25.32,1:01:25.68,EN,,0,0,0,,OK?\nDialogue: 0,1:01:26.04,1:01:29.24,EN,,0,0,0,,I can't tell, looking at this form,\nDialogue: 0,1:01:29.80,1:01:32.60,EN,,0,0,0,,whether or not there's a single, unique solution for EXPT,\nDialogue: 0,1:01:33.23,1:01:35.31,EN,,0,0,0,,an infinite number of solutions, or no solutions.\nDialogue: 0,1:01:37.20,1:01:38.62,EN,,0,0,0,,It's got to be how it counts\nDialogue: 0,1:01:38.64,1:01:40.14,EN,,0,0,0,,and things like that, the details.\nDialogue: 0,1:01:40.60,1:01:42.75,EN,,0,0,0,,And it's harder in programming than linear algebra.\nDialogue: 0,1:01:43.28,1:01:45.21,EN,,0,0,0,,There aren't too many theorems about it in programming.\nDialogue: 0,1:01:48.45,1:01:51.21,EN,,0,0,0,,Well, I want to rewrite these equations a little bit,\nDialogue: 0,1:01:51.93,1:01:53.77,EN,,0,0,0,,these over here.\nDialogue: 0,1:01:53.97,1:01:56.62,EN,,0,0,0,,Because what we're investigating is equations like this.\nDialogue: 0,1:01:57.00,1:01:58.38,EN,,0,0,0,,But I want to play a little with equations\nDialogue: 0,1:01:58.40,1:01:59.53,EN,,0,0,0,,like this that we understand,\nDialogue: 0,1:02:00.70,1:02:02.91,EN,,0,0,0,,just so we get some insight into this kind of question.\nDialogue: 0,1:02:04.72,1:02:06.43,EN,,0,0,0,,We could rewrite our equations here,\nDialogue: 0,1:02:06.75,1:02:08.67,EN,,0,0,0,,say these two, the ones that are interesting,\nDialogue: 0,1:02:09.77,1:02:14.86,EN,,0,0,0,,as x equals three minus y,\nDialogue: 0,1:02:15.88,1:02:19.68,EN,,0,0,0,,and y equals x minus one.\nDialogue: 0,1:02:22.01,1:02:24.05,EN,,0,0,0,,What do we call this transformation?\nDialogue: 0,1:02:24.05,1:02:26.52,EN,,0,0,0,,This is a linear transformation, t.\nDialogue: 0,1:02:29.43,1:02:32.25,EN,,0,0,0,,Then what we're getting here is an equation\nDialogue: 0,1:02:32.97,1:02:37.37,EN,,0,0,0,,x y equals t of x y.\nDialogue: 0,1:02:42.99,1:02:43.98,EN,,0,0,0,,What am I looking for?\nDialogue: 0,1:02:44.56,1:02:46.01,EN,,0,0,0,,I'm looking for a fixed point of t.\nDialogue: 0,1:02:46.97,1:02:59.42,EN,,0,0,0,,The solution is a fixed point of t.\nDialogue: 0,1:03:01.91,1:03:05.53,EN,,0,0,0,,So the methods we should have for looking for solutions to equations,\nDialogue: 0,1:03:05.90,1:03:07.48,EN,,0,0,0,,if I can do it by fixed points,\nDialogue: 0,1:03:08.65,1:03:09.87,EN,,0,0,0,,might be applicable.\nDialogue: 0,1:03:10.88,1:03:12.36,EN,,0,0,0,,If I have a means of finding a solution\nDialogue: 0,1:03:12.38,1:03:14.32,EN,,0,0,0,,to an equations by fixed points--\nDialogue: 0,1:03:15.52,1:03:18.19,EN,,0,0,0,,just, might not work--\nDialogue: 0,1:03:18.57,1:03:19.80,EN,,0,0,0,,but it might be applicable\nDialogue: 0,1:03:20.09,1:03:22.27,EN,,0,0,0,,to investigating solutions of equations like this.\nDialogue: 0,1:03:27.24,1:03:29.48,EN,,0,0,0,,But what I want you to feel is that this is an equation.\nDialogue: 0,1:03:30.26,1:03:31.21,EN,,0,0,0,,It's an expression\nDialogue: 0,1:03:31.36,1:03:33.58,EN,,0,0,0,,with several instances of various names\nDialogue: 0,1:03:34.70,1:03:37.66,EN,,0,0,0,,which puts a constraint on the name,\nDialogue: 0,1:03:38.43,1:03:40.52,EN,,0,0,0,,saying what that name could have as its value,\nDialogue: 0,1:03:41.48,1:03:45.01,EN,,0,0,0,,rather than some sort of mechanical process of substitution right now.\nDialogue: 0,1:03:47.74,1:03:49.77,EN,,0,0,0,,This is an equation which I'm going to try to solve.\nDialogue: 0,1:03:51.22,1:03:52.43,EN,,0,0,0,,Well, let's play around and solve it.\nDialogue: 0,1:03:53.96,1:03:55.66,EN,,0,0,0,,First of all, I want to write down\nDialogue: 0,1:03:56.64,1:03:59.00,EN,,0,0,0,,the function which corresponds to t.\nDialogue: 0,1:04:00.32,1:04:03.00,EN,,0,0,0,,First I want to write down the function which corresponds to t\nDialogue: 0,1:04:04.49,1:04:06.96,EN,,0,0,0,,whose fixed point is the answer to this question.\nDialogue: 0,1:04:10.76,1:04:11.28,EN,,0,0,0,,OK?\nDialogue: 0,1:04:12.25,1:04:14.30,EN,,0,0,0,,Well, let's consider the following procedure f.\nDialogue: 0,1:04:16.87,1:04:18.30,EN,,0,0,0,,I claim it computes that function.\nDialogue: 0,1:04:19.34,1:04:22.91,EN,,0,0,0,,f is that procedure of one argument g,\nDialogue: 0,1:04:25.23,1:04:25.93,EN,,0,0,0,,which is\nDialogue: 0,1:04:26.40,1:04:32.00,EN,,0,0,0,,that procedure of two arguments x and n.\nDialogue: 0,1:04:33.43,1:04:34.73,EN,,0,0,0,,Which have the property that\nDialogue: 0,1:04:36.72,1:04:40.43,EN,,0,0,0,,if n is zero,\nDialogue: 0,1:04:41.72,1:04:43.20,EN,,0,0,0,,then the result is one,\nDialogue: 0,1:04:45.34,1:04:46.17,EN,,0,0,0,,otherwise,\nDialogue: 0,1:04:49.90,1:05:01.40,EN,,0,0,0,,the result is the product of x and g, applied to x, and minus n1.\nDialogue: 0,1:05:03.37,1:05:07.80,EN,,0,0,0,,g, times, else, COND, lambda, lambda--\nDialogue: 0,1:05:08.94,1:05:09.40,EN,,0,0,0,,OK?\nDialogue: 0,1:05:12.30,1:05:14.62,EN,,0,0,0,,Here f is a procedure,\nDialogue: 0,1:05:15.05,1:05:17.79,EN,,0,0,0,,which if I had a solution to that equation,\nDialogue: 0,1:05:19.04,1:05:22.04,EN,,0,0,0,,if I had a good exponentiation procedure,\nDialogue: 0,1:05:23.42,1:05:26.32,EN,,0,0,0,,and I applied f to that procedure,\nDialogue: 0,1:05:27.60,1:05:31.24,EN,,0,0,0,,then the result would be a good exponentiation procedure.\nDialogue: 0,1:05:37.46,1:05:38.57,EN,,0,0,0,,Because, what does it do?\nDialogue: 0,1:05:39.42,1:05:40.88,EN,,0,0,0,,Well, all it is\nDialogue: 0,1:05:42.36,1:05:44.64,EN,,0,0,0,,is exposing g were a good exponentiation procedure,\nDialogue: 0,1:05:45.63,1:05:47.58,EN,,0,0,0,,well then this would produce, as its value,\nDialogue: 0,1:05:47.84,1:05:49.68,EN,,0,0,0,,a procedure to arguments x and n,\nDialogue: 0,1:05:50.49,1:05:51.52,EN,,0,0,0,,such that if n were 0,\nDialogue: 0,1:05:51.55,1:05:52.41,EN,,0,0,0,,the result would be one,\nDialogue: 0,1:05:52.44,1:05:54.16,EN,,0,0,0,,which is certainly true of exponentiation.\nDialogue: 0,1:05:54.64,1:05:57.05,EN,,0,0,0,,Otherwise, it will be the result of multiplying x\nDialogue: 0,1:05:57.26,1:05:59.26,EN,,0,0,0,,by the exponentiation procedure given to me\nDialogue: 0,1:06:00.17,1:06:02.44,EN,,0,0,0,,with x and n minus one as arguments.\nDialogue: 0,1:06:03.47,1:06:04.78,EN,,0,0,0,,So if this computed the correct\nDialogue: 0,1:06:04.81,1:06:06.30,EN,,0,0,0,,exponentiation for n minus one,\nDialogue: 0,1:06:07.87,1:06:11.28,EN,,0,0,0,,then this would be the correct exponentiation for exponent n,\nDialogue: 0,1:06:12.17,1:06:14.41,EN,,0,0,0,,so this would have been the right exponentiation procedure.\nDialogue: 0,1:06:17.50,1:06:19.82,EN,,0,0,0,,So what I really want to say here is\nDialogue: 0,1:06:21.02,1:06:32.44,EN,,0,0,0,,E-X-P-T is a fixed point of f.\nDialogue: 0,1:06:36.99,1:06:38.35,EN,,0,0,0,,Now our problem is\nDialogue: 0,1:06:38.35,1:06:39.68,EN,,0,0,0,,there might be more than one fixed point.\nDialogue: 0,1:06:40.06,1:06:42.19,EN,,0,0,0,,There might be no fixed points.\nDialogue: 0,1:06:43.27,1:06:44.81,EN,,0,0,0,,I have to go hunting for the fixed points.\nDialogue: 0,1:06:48.22,1:06:49.37,EN,,0,0,0,,Got to solve this equation.\nDialogue: 0,1:06:52.16,1:06:54.28,EN,,0,0,0,,Well there are various ways to hunt for fixed points.\nDialogue: 0,1:06:55.58,1:06:57.08,EN,,0,0,0,,Of course, the one we played with\nDialogue: 0,1:06:57.24,1:07:01.16,EN,,0,0,0,,at the beginning of this term worked for cosine.\nDialogue: 0,1:07:02.73,1:07:07.69,EN,,0,0,0,,Going to. Go into radians mode on your calculator\nDialogue: 0,1:07:07.85,1:07:10.51,EN,,0,0,0,,and push cosine, and just keep doing it,\nDialogue: 0,1:07:11.84,1:07:15.45,EN,,0,0,0,,and you get to some number which is about 0.73 or 0.74.\nDialogue: 0,1:07:16.09,1:07:17.18,EN,,0,0,0,,I can't remember which.\nDialogue: 0,1:07:20.57,1:07:22.64,EN,,0,0,0,,By iterating a procedure, which has\nDialogue: 0,1:07:22.81,1:07:24.40,EN,,0,0,0,,By iterating a function,\nDialogue: 0,1:07:25.60,1:07:27.16,EN,,0,0,0,,whose fixed point I'm searching for,\nDialogue: 0,1:07:27.50,1:07:31.13,EN,,0,0,0,,it is sometimes the case that that function will converge\nDialogue: 0,1:07:31.87,1:07:33.08,EN,,0,0,0,,in producing the fixed point.\nDialogue: 0,1:07:33.77,1:07:35.44,EN,,0,0,0,,I think we luck out in this case,\nDialogue: 0,1:07:36.44,1:07:37.21,EN,,0,0,0,,so let's look for it.\nDialogue: 0,1:07:39.91,1:07:46.28,EN,,0,0,0,,Let's look at this overhead, this slide.\nDialogue: 0,1:07:48.03,1:07:51.71,EN,,0,0,0,,Consider the following sequence of procedures.\nDialogue: 0,1:07:56.40,1:07:57.79,EN,,0,0,0,,e0 over here\nDialogue: 0,1:07:59.24,1:08:01.63,EN,,0,0,0,,the procedure which does nothing at all.\nDialogue: 0,1:08:02.89,1:08:05.10,EN,,0,0,0,,It's the procedure which produces an error\nDialogue: 0,1:08:05.10,1:08:06.24,EN,,0,0,0,,for any arguments you give it.\nDialogue: 0,1:08:07.78,1:08:09.03,EN,,0,0,0,,It's basically useless.\nDialogue: 0,1:08:14.48,1:08:20.08,EN,,0,0,0,,Well, however, I can make an approximation.\nDialogue: 0,1:08:20.08,1:08:23.93,EN,,0,0,0,,Let's consider it the worst possible approximation to exponentiation,\nDialogue: 0,1:08:24.73,1:08:25.53,EN,,0,0,0,,because it does nothing.\nDialogue: 0,1:08:26.99,1:08:29.68,EN,,0,0,0,,Well, supposing I substituted e0\nDialogue: 0,1:08:30.35,1:08:33.26,EN,,0,0,0,,for g by calling f,\nDialogue: 0,1:08:33.79,1:08:36.30,EN,,0,0,0,,as you see over here on e0.\nDialogue: 0,1:08:37.38,1:08:39.77,EN,,0,0,0,,So you see over here, have e0 there.\nDialogue: 0,1:08:40.84,1:08:42.35,EN,,0,0,0,,Then gee, what's e1?\nDialogue: 0,1:08:43.63,1:08:46.03,EN,,0,0,0,,e1 is a procedure which exponentiate things\nDialogue: 0,1:08:46.67,1:08:48.78,EN,,0,0,0,,to the 0th power, with no trouble.\nDialogue: 0,1:08:49.60,1:08:50.75,EN,,0,0,0,,It gets the right answer,\nDialogue: 0,1:08:51.05,1:08:52.35,EN,,0,0,0,,anything to the zero is one,\nDialogue: 0,1:08:52.68,1:08:54.25,EN,,0,0,0,,and it makes an error on anything else.\nDialogue: 0,1:08:57.39,1:09:01.56,EN,,0,0,0,,Well, now what if I take e1\nDialogue: 0,1:09:02.30,1:09:07.40,EN,,0,0,0,,and substituted it for g by calling f on e1?\nDialogue: 0,1:09:09.58,1:09:11.18,EN,,0,0,0,,Oh gosh,\nDialogue: 0,1:09:12.01,1:09:15.02,EN,,0,0,0,,I have here a procedure of two arguments.\nDialogue: 0,1:09:15.67,1:09:16.84,EN,,0,0,0,,Now remember e1\nDialogue: 0,1:09:16.96,1:09:19.66,EN,,0,0,0,,was appropriate for taking exponentiations of 0,\nDialogue: 0,1:09:21.47,1:09:23.37,EN,,0,0,0,,for raising to the 0 exponent.\nDialogue: 0,1:09:24.20,1:09:25.00,EN,,0,0,0,,So here,\nDialogue: 0,1:09:25.52,1:09:27.28,EN,,0,0,0,,if is n is 0, the result is one,\nDialogue: 0,1:09:27.29,1:09:28.67,EN,,0,0,0,,so this guy is good for that too.\nDialogue: 0,1:09:29.52,1:09:32.01,EN,,0,0,0,,However, I can use something for raising to the 0th power\nDialogue: 0,1:09:32.51,1:09:35.26,EN,,0,0,0,,to multiply it by x to raise something to the first power.\nDialogue: 0,1:09:35.97,1:09:39.67,EN,,0,0,0,,So e2 is good for both power 0 and 1.\nDialogue: 0,1:09:41.60,1:09:41.92,EN,,0,0,0,,OK?\nDialogue: 0,1:09:43.71,1:09:46.67,EN,,0,0,0,,And e3 is constructed from e2 in the same way.\nDialogue: 0,1:09:47.89,1:09:50.24,EN,,0,0,0,,And e3, of course, by the same argument\nDialogue: 0,1:09:50.32,1:09:53.37,EN,,0,0,0,,is good for powers 0, one, and two.\nDialogue: 0,1:09:55.12,1:09:55.40,EN,,0,0,0,,OK?\nDialogue: 0,1:09:56.09,1:09:59.08,EN,,0,0,0,,And so I will assert for you, without proof,\nDialogue: 0,1:09:59.66,1:10:01.72,EN,,0,0,0,,because the proof is horribly difficult.\nDialogue: 0,1:10:02.52,1:10:03.60,EN,,0,0,0,,And that's the sort of thing that\nDialogue: 0,1:10:03.63,1:10:06.36,EN,,0,0,0,,people called denotational semanticists do.\nDialogue: 0,1:10:06.59,1:10:07.64,EN,,0,0,0,,I suppose it was invented\nDialogue: 0,1:10:07.87,1:10:10.59,EN,,0,0,0,,This great idea was invented by Scott and Strachey.\nDialogue: 0,1:10:11.64,1:10:16.32,EN,,0,0,0,,Ah, sort of. They're very famous mathematician types\nDialogue: 0,1:10:16.86,1:10:21.21,EN,,0,0,0,,who invented the interpretation for these programs that we have\nDialogue: 0,1:10:22.36,1:10:24.00,EN,,0,0,0,,that I'm talking to you about right now.\nDialogue: 0,1:10:24.24,1:10:26.17,EN,,0,0,0,,And they proved, by topology\nDialogue: 0,1:10:27.04,1:10:29.32,EN,,0,0,0,,that there is such a fixed point\nDialogue: 0,1:10:29.82,1:10:31.26,EN,,0,0,0,,in the cases that we want.\nDialogue: 0,1:10:32.22,1:10:33.24,EN,,0,0,0,,But the assertion is\nDialogue: 0,1:10:33.40,1:10:44.24,EN,,0,0,0,,E-X-P-T is limit as n goes to infinity of em.\nDialogue: 0,1:10:45.52,1:10:47.90,EN,,0,0,0,,and And that we've constructed this by the following way.\nDialogue: 0,1:10:50.52,1:10:55.66,EN,,0,0,0,,--is Well, it's f of, f of, f of, f of, f of--\nDialogue: 0,1:10:57.61,1:11:00.19,EN,,0,0,0,,f applied to anything at all.\nDialogue: 0,1:11:01.12,1:11:02.46,EN,,0,0,0,,It didn't matter what that was,\nDialogue: 0,1:11:03.18,1:11:05.00,EN,,0,0,0,,because, in fact, this always produces an error.\nDialogue: 0,1:11:07.45,1:11:08.41,EN,,0,0,0,,Applied to this--\nDialogue: 0,1:11:12.89,1:11:14.48,EN,,0,0,0,,That's by infinite nesting of f's.\nDialogue: 0,1:11:16.38,1:11:17.71,EN,,0,0,0,,So now my problem\nDialogue: 0,1:11:18.22,1:11:19.76,EN,,0,0,0,,is to make some infinite things.\nDialogue: 0,1:11:22.59,1:11:24.08,EN,,0,0,0,,We need some infinite things.\nDialogue: 0,1:11:24.92,1:11:26.25,EN,,0,0,0,,How am I going to nest up an f\nDialogue: 0,1:11:26.56,1:11:27.80,EN,,0,0,0,,an infinite number of times?\nDialogue: 0,1:11:28.98,1:11:30.12,EN,,0,0,0,,I'd better construct this.\nDialogue: 0,1:11:32.38,1:11:32.93,EN,,0,0,0,,Well, I don't know.\nDialogue: 0,1:11:32.93,1:11:34.32,EN,,0,0,0,,How would I make an infinite loop at all?\nDialogue: 0,1:11:34.81,1:11:36.32,EN,,0,0,0,,Let's take a very simple infinite loop,\nDialogue: 0,1:11:36.57,1:11:38.34,EN,,0,0,0,,the simplest infinite loop imaginable.\nDialogue: 0,1:11:43.55,1:11:47.55,EN,,0,0,0,,If I were to take that procedure of one argument x\nDialogue: 0,1:11:48.00,1:11:49.79,EN,,0,0,0,,which applies x to x\nDialogue: 0,1:11:53.55,1:11:53.92,EN,,0,0,0,,OK?\nDialogue: 0,1:11:55.05,1:11:58.41,EN,,0,0,0,,and apply that to the procedure of one argument x\nDialogue: 0,1:11:59.36,1:12:01.05,EN,,0,0,0,,which applies x to x,\nDialogue: 0,1:12:04.83,1:12:06.00,EN,,0,0,0,,then this is an infinite loop.\nDialogue: 0,1:12:07.21,1:12:09.31,EN,,0,0,0,,The reason why this is an infinite loop is as follows.\nDialogue: 0,1:12:09.98,1:12:11.31,EN,,0,0,0,,The way I understand this\nDialogue: 0,1:12:11.52,1:12:13.69,EN,,0,0,0,,is I substitute the argument\nDialogue: 0,1:12:14.22,1:12:16.59,EN,,0,0,0,,for the formal parameter in the body.\nDialogue: 0,1:12:18.85,1:12:21.60,EN,,0,0,0,,But if I do that, I take for each of these x's,\nDialogue: 0,1:12:22.40,1:12:23.76,EN,,0,0,0,,I substitute one of these,\nDialogue: 0,1:12:24.36,1:12:26.96,EN,,0,0,0,,making a copy of the original expression I just started with,\nDialogue: 0,1:12:28.35,1:12:29.37,EN,,0,0,0,,the simplest infinite loop.\nDialogue: 0,1:12:35.44,1:12:39.29,EN,,0,0,0,,Now I want to tell you about a particular operator\nDialogue: 0,1:12:40.38,1:12:43.09,EN,,0,0,0,,which is constructed by a perturbation from this infinite loop.\nDialogue: 0,1:12:46.96,1:12:47.92,EN,,0,0,0,,I'll call it y.\nDialogue: 0,1:12:50.89,1:12:55.82,EN,,0,0,0,,OK y -- This is called Curry's Paradoxical Combinator of y\nDialogue: 0,1:12:56.62,1:12:58.99,EN,,0,0,0,,after a fellow by the name of Curry,\nDialogue: 0,1:12:59.34,1:13:01.85,EN,,0,0,0,,who was a logician of the 1930s also.\nDialogue: 0,1:13:04.48,1:13:06.88,EN,,0,0,0,,And if I have a procedure of one argument f,\nDialogue: 0,1:13:08.17,1:13:09.33,EN,,0,0,0,,what's it going to have in it?\nDialogue: 0,1:13:09.33,1:13:11.20,EN,,0,0,0,,It's going to have a kind of infinite loop in it,\nDialogue: 0,1:13:11.98,1:13:15.47,EN,,0,0,0,,which is that procedure of one argument x\nDialogue: 0,1:13:15.95,1:13:18.80,EN,,0,0,0,,which applies f to x of x,\nDialogue: 0,1:13:21.63,1:13:24.75,EN,,0,0,0,,applied to that procedure of one argument x,\nDialogue: 0,1:13:25.10,1:13:27.34,EN,,0,0,0,,which applies f to f of x.\nDialogue: 0,1:13:32.30,1:13:33.13,EN,,0,0,0,,Now what's this do?\nDialogue: 0,1:13:34.80,1:13:36.06,EN,,0,0,0,,Suppose we apply y to F.\nDialogue: 0,1:13:41.31,1:13:42.57,EN,,0,0,0,,OK? Well, that's easy enough.\nDialogue: 0,1:13:43.15,1:13:44.62,EN,,0,0,0,,That's this capital F over here.\nDialogue: 0,1:13:46.91,1:13:48.16,EN,,0,0,0,,Well, the easiest thing to say there\nDialogue: 0,1:13:48.30,1:13:49.92,EN,,0,0,0,,is, I substitute F for here.\nDialogue: 0,1:13:55.32,1:13:57.07,EN,,0,0,0,,So that's going to give me, basically--\nDialogue: 0,1:13:58.75,1:14:00.84,EN,,0,0,0,,because then I'm going to substitute this\nDialogue: 0,1:14:01.45,1:14:02.80,EN,,0,0,0,,for x in here.\nDialogue: 0,1:14:04.17,1:14:05.23,EN,,0,0,0,,That F of\nDialogue: 0,1:14:08.97,1:14:10.09,EN,,0,0,0,,Let me actually do it in steps,\nDialogue: 0,1:14:10.22,1:14:11.45,EN,,0,0,0,,so you can see it completely.\nDialogue: 0,1:14:11.92,1:14:14.27,EN,,0,0,0,,I'm going to be very careful. OK?\nDialogue: 0,1:14:15.02,1:14:18.25,EN,,0,0,0,,This is open, open, lambda of x ,\nDialogue: 0,1:14:19.08,1:14:22.11,EN,,0,0,0,,capital F, x, x,\nDialogue: 0,1:14:26.88,1:14:35.55,EN,,0,0,0,,applied to itself, F of x of x.\nDialogue: 0,1:14:37.91,1:14:39.66,EN,,0,0,0,,Substituting this for this in here,\nDialogue: 0,1:14:40.06,1:14:40.91,EN,,0,0,0,,this is\nDialogue: 0,1:14:43.13,1:14:48.35,EN,,0,0,0,,F applied to-- what is it-- substituting this in here\nDialogue: 0,1:14:48.65,1:14:54.81,EN,,0,0,0,,open, open, lambda of x, F, of x and x,\nDialogue: 0,1:14:57.07,1:14:58.17,EN,,0,0,0,,applied to\nDialogue: 0,1:14:59.18,1:15:06.48,EN,,0,0,0,,lambda of x, F of x of x, F,\nDialogue: 0,1:15:06.99,1:15:10.44,EN,,0,0,0,,lambda, pair, F.\nDialogue: 0,1:15:11.51,1:15:12.40,EN,,0,0,0,,Oh, but what is this?\nDialogue: 0,1:15:13.42,1:15:16.35,EN,,0,0,0,,This thing over here that I just computed,\nDialogue: 0,1:15:17.13,1:15:18.56,EN,,0,0,0,,is this thing over here.\nDialogue: 0,1:15:20.19,1:15:21.84,EN,,0,0,0,,But I just wrapped another F around it.\nDialogue: 0,1:15:23.37,1:15:24.67,EN,,0,0,0,,So by applying y to F,\nDialogue: 0,1:15:24.68,1:15:26.22,EN,,0,0,0,,I make an infinite series of F's.\nDialogue: 0,1:15:27.85,1:15:29.45,EN,,0,0,0,,If I just let this run forever,\nDialogue: 0,1:15:29.69,1:15:31.77,EN,,0,0,0,,I'll just keep making more and more F's outside.\nDialogue: 0,1:15:33.17,1:15:34.80,EN,,0,0,0,,I ran an infinite loop which is useless,\nDialogue: 0,1:15:35.20,1:15:37.02,EN,,0,0,0,,but it doesn't matter that the inside is useless.\nDialogue: 0,1:15:39.85,1:15:47.85,EN,,0,0,0,,OK? So y of F is F applied to y of F.\nDialogue: 0,1:15:50.33,1:15:52.14,EN,,0,0,0,,So y is a magical thing\nDialogue: 0,1:15:53.85,1:15:56.25,EN,,0,0,0,,which, when applied to some function,\nDialogue: 0,1:15:57.37,1:16:00.38,EN,,0,0,0,,produces the object which is the fixed point of that function,\nDialogue: 0,1:16:01.69,1:16:04.25,EN,,0,0,0,,if it exists, and if this all works.\nDialogue: 0,1:16:07.91,1:16:10.08,EN,,0,0,0,,Because, indeed, if I take y of F\nDialogue: 0,1:16:10.12,1:16:11.12,EN,,0,0,0,,I get y of F out.\nDialogue: 0,1:16:16.24,1:16:18.86,EN,,0,0,0,,Now I want you to think this in terms of\nDialogue: 0,1:16:19.85,1:16:22.38,EN,,0,0,0,,the eval-apply interpreter for a bit.\nDialogue: 0,1:16:23.86,1:16:26.27,EN,,0,0,0,,I wrote down a whole bunch of recursion equations out there.\nDialogue: 0,1:16:28.54,1:16:30.22,EN,,0,0,0,,They're simultaneous in the same way\nDialogue: 0,1:16:30.22,1:16:31.23,EN,,0,0,0,,these are simultaneous equations.\nDialogue: 0,1:16:31.47,1:16:33.31,EN,,0,0,0,,Exponentiation was not a simultaneous equation.\nDialogue: 0,1:16:33.31,1:16:35.79,EN,,0,0,0,,It was only one variable I was looking for a meaning for.\nDialogue: 0,1:16:38.15,1:16:40.76,EN,,0,0,0,,But what Lisp is is the fixed point of the process\nDialogue: 0,1:16:40.81,1:16:42.57,EN,,0,0,0,,that's which says, if I knew what Lisp was\nDialogue: 0,1:16:42.59,1:16:46.51,EN,,0,0,0,,and substituted it in for eval, and apply, and so on,\nDialogue: 0,1:16:46.59,1:16:49.79,EN,,0,0,0,,on the right hand sides of all those recursion equations,\nDialogue: 0,1:16:50.94,1:16:53.96,EN,,0,0,0,,then if it was a real good Lisp, is a real one,\nDialogue: 0,1:16:54.36,1:16:56.30,EN,,0,0,0,,then the left hand side would also be Lisp.\nDialogue: 0,1:16:58.22,1:16:59.82,EN,,0,0,0,,So I made sense of that definition.\nDialogue: 0,1:17:02.42,1:17:05.41,EN,,0,0,0,,Now whether or not there's an answer isn't so obvious.\nDialogue: 0,1:17:05.69,1:17:06.75,EN,,0,0,0,,I can't attack that.\nDialogue: 0,1:17:07.74,1:17:09.21,EN,,0,0,0,,Now these arguments that I'm giving you now\nDialogue: 0,1:17:09.26,1:17:10.27,EN,,0,0,0,,are quite dangerous.\nDialogue: 0,1:17:10.66,1:17:11.64,EN,,0,0,0,,Let's look over here.\nDialogue: 0,1:17:13.05,1:17:14.61,EN,,0,0,0,,On the. These are limit arguments.\nDialogue: 0,1:17:14.61,1:17:15.39,EN,,0,0,0,,We're talking about limits,\nDialogue: 0,1:17:15.45,1:17:17.68,EN,,0,0,0,,and it's really calculus, or topology,\nDialogue: 0,1:17:17.87,1:17:20.03,EN,,0,0,0,,or something like that, a kind of analysis.\nDialogue: 0,1:17:20.76,1:17:23.38,EN,,0,0,0,,OK？Now here's an argument that you all believe.\nDialogue: 0,1:17:23.38,1:17:25.29,EN,,0,0,0,,And I want to make sure you realize\nDialogue: 0,1:17:25.42,1:17:27.66,EN,,0,0,0,,that I could be bullshitting you.\nDialogue: 0,1:17:28.86,1:17:30.48,EN,,0,0,0,,Alright? What is this?\nDialogue: 0,1:17:34.25,1:17:39.52,EN,,0,0,0,,u is the sum of 1/2, 1/4, and 1/8, and so on,\nDialogue: 0,1:17:39.74,1:17:41.32,EN,,0,0,0,,the sum of a geometric series.\nDialogue: 0,1:17:42.82,1:17:44.68,EN,,0,0,0,,And, of course, I could play a game here.\nDialogue: 0,1:17:44.82,1:17:47.57,EN,,0,0,0,,u minus one is 1/2, plus 1/4, plus 1/8, and so on.\nDialogue: 0,1:17:51.90,1:17:54.46,EN,,0,0,0,,But now if I multiple. What I could do here--\nDialogue: 0,1:17:56.09,1:17:57.93,EN,,0,0,0,,Ooops. There is a parentheses error here.\nDialogue: 0,1:17:58.92,1:18:01.45,EN,,0,0,0,,But I can put here two times u minus one\nDialogue: 0,1:18:01.74,1:18:03.99,EN,,0,0,0,,is one plus 1/2, plus 1/4, plus 1/8.\nDialogue: 0,1:18:07.57,1:18:08.54,EN,,0,0,0,,Can I fix that?\nDialogue: 0,1:18:14.01,1:18:16.43,EN,,0,0,0,,Yes, well.\nDialogue: 0,1:18:18.19,1:18:18.65,EN,,0,0,0,,OK?\nDialogue: 0,1:18:19.52,1:18:20.64,EN,,0,0,0,,But that gives me back\nDialogue: 0,1:18:23.53,1:18:26.64,EN,,0,0,0,,two times u minus one is u,\nDialogue: 0,1:18:27.80,1:18:29.58,EN,,0,0,0,,therefore, we conclude that u is two.\nDialogue: 0,1:18:30.30,1:18:31.37,EN,,0,0,0,,And this actually is true.\nDialogue: 0,1:18:31.96,1:18:33.32,EN,,0,0,0,,There's no problem like that.\nDialogue: 0,1:18:34.04,1:18:37.55,EN,,0,0,0,,But supposing I did something different.\nDialogue: 0,1:18:38.54,1:18:39.48,EN,,0,0,0,,Supposing I start up with something\nDialogue: 0,1:18:39.50,1:18:41.20,EN,,0,0,0,,which manifestly has no sum.\nDialogue: 0,1:18:41.56,1:18:46.99,EN,,0,0,0,,v is one, plus two, plus four, plus 8, plus dot, dot, dot. OK?\nDialogue: 0,1:18:47.39,1:18:51.39,EN,,0,0,0,,Well, v minus one is surely two, plus four, plus eight, plus dot, dot, dot. Right?\nDialogue: 0,1:18:52.27,1:18:56.03,EN,,0,0,0,,v minus one over two, gee, that looks like v again.\nDialogue: 0,1:18:57.41,1:19:00.54,EN,,0,0,0,,From that I should be able to conclude that--\nDialogue: 0,1:19:01.37,1:19:02.91,EN,,0,0,0,,that's also wrong, apparently.\nDialogue: 0,1:19:03.07,1:19:04.51,EN,,0,0,0,,v equals minus one.\nDialogue: 0,1:19:12.45,1:19:13.82,EN,,0,0,0,,That should be a minus one.\nDialogue: 0,1:19:15.28,1:19:16.91,EN,,0,0,0,,And that's certainly a false conclusion.\nDialogue: 0,1:19:22.00,1:19:23.47,EN,,0,0,0,,So when you play with limits,\nDialogue: 0,1:19:24.22,1:19:27.85,EN,,0,0,0,,arguments that may work in one case\nDialogue: 0,1:19:29.42,1:19:30.75,EN,,0,0,0,,they may not work in some other case.\nDialogue: 0,1:19:30.75,1:19:31.69,EN,,0,0,0,,You have to be very careful.\nDialogue: 0,1:19:32.24,1:19:33.87,EN,,0,0,0,,The arguments have to be well-formed.\nDialogue: 0,1:19:36.14,1:19:39.23,EN,,0,0,0,,And I don't know, in general,\nDialogue: 0,1:19:39.85,1:19:41.93,EN,,0,0,0,,what the story is about arguments like this.\nDialogue: 0,1:19:43.27,1:19:45.24,EN,,0,0,0,,We can read a pile of topology and find out.\nDialogue: 0,1:19:46.27,1:19:48.64,EN,,0,0,0,,But, surely, at least you understand now,\nDialogue: 0,1:19:49.10,1:19:51.13,EN,,0,0,0,,why it might be some meaning\nDialogue: 0,1:19:51.15,1:19:52.76,EN,,0,0,0,,to the things we've been writing on the blackboard.\nDialogue: 0,1:19:53.66,1:19:55.61,EN,,0,0,0,,And you understand what that might mean.\nDialogue: 0,1:19:56.48,1:19:58.35,EN,,0,0,0,,So, I suppose, it's almost about time\nDialogue: 0,1:19:59.07,1:20:03.84,EN,,0,0,0,,for you to merit being made a member\nDialogue: 0,1:20:04.28,1:20:05.55,EN,,0,0,0,,of the grand recursive order\nDialogue: 0,1:20:05.56,1:20:07.04,EN,,0,0,0,,of lambda calculus hackers.\nDialogue: 0,1:20:08.84,1:20:10.17,EN,,0,0,0,,I would. This is the badge.\nDialogue: 0,1:20:10.82,1:20:12.54,EN,,0,0,0,,Because you now understand, for example,\nDialogue: 0,1:20:13.40,1:20:15.20,EN,,0,0,0,,what it says at the very top,\nDialogue: 0,1:20:16.89,1:20:18.41,EN,,0,0,0,,y F equals F y F.\nDialogue: 0,1:20:21.04,1:20:21.66,EN,,0,0,0,,Thank you.\nDialogue: 0,1:20:21.85,1:20:22.75,EN,,0,0,0,,Are there any questions?\nDialogue: 0,1:20:24.71,1:20:25.15,EN,,0,0,0,,Yes, Lev.\nDialogue: 0,1:20:25.37,1:20:27.39,EN,,0,0,0,,AUDIENCE: With this, it seems that\nDialogue: 0,1:20:27.40,1:20:30.22,EN,,0,0,0,,there's no need to define, as you imply,\nDialogue: 0,1:20:30.24,1:20:32.70,EN,,0,0,0,,to just remember a value, to apply it later.\nDialogue: 0,1:20:32.99,1:20:33.32,EN,,0,0,0,,PROFESSOR: Yeah.\nDialogue: 0,1:20:33.50,1:20:36.44,EN,,0,0,0,,AUDIENCE: Defines were kind of a side-effect it seemed in the language.\nDialogue: 0,1:20:36.49,1:20:38.52,EN,,0,0,0,,[INTERPOSING] are order dependent.\nDialogue: 0,1:20:39.30,1:20:42.06,EN,,0,0,0,,Does this eliminate the side-effect from the.\nDialogue: 0,1:20:42.28,1:20:44.68,EN,,0,0,0,,PROFESSOR: Well. The answer is,\nDialogue: 0,1:20:44.88,1:20:46.44,EN,,0,0,0,,this is not the way these things were implemented.\nDialogue: 0,1:20:47.52,1:20:47.93,EN,,0,0,0,,OK?\nDialogue: 0,1:20:48.92,1:20:53.15,EN,,0,0,0,,Define, indeed is implemented as an operation\nDialogue: 0,1:20:53.18,1:20:55.53,EN,,0,0,0,,that actually modifies an environment structure,\nDialogue: 0,1:20:57.95,1:21:02.33,EN,,0,0,0,,changes the frame that the define is executed in.\nDialogue: 0,1:21:03.69,1:21:06.51,EN,,0,0,0,,And there are many reasons for that,\nDialogue: 0,1:21:07.39,1:21:08.64,EN,,0,0,0,,but a lot of this has to do with\nDialogue: 0,1:21:08.67,1:21:10.09,EN,,0,0,0,,making an interactive system.\nDialogue: 0,1:21:11.34,1:21:14.12,EN,,0,0,0,,What this is saying is that if you've made a system,\nDialogue: 0,1:21:14.35,1:21:15.20,EN,,0,0,0,,and you know\nDialogue: 0,1:21:15.42,1:21:16.60,EN,,0,0,0,,and you know you're not going to do any debugging\nDialogue: 0,1:21:16.60,1:21:17.55,EN,,0,0,0,,or anything like that,\nDialogue: 0,1:21:17.84,1:21:20.72,EN,,0,0,0,,and you know everything there is all at once,\nDialogue: 0,1:21:20.75,1:21:21.24,EN,,0,0,0,,and you want to say,\nDialogue: 0,1:21:21.26,1:21:23.12,EN,,0,0,0,,what is the meaning of a final set of equations?\nDialogue: 0,1:21:24.09,1:21:25.26,EN,,0,0,0,,This gives you a meaning for it.\nDialogue: 0,1:21:25.79,1:21:27.45,EN,,0,0,0,,But in order to make an interactive system,\nDialogue: 0,1:21:27.45,1:21:28.75,EN,,0,0,0,,where you can change the meaning of one\nDialogue: 0,1:21:28.76,1:21:31.68,EN,,0,0,0,,without changing everything else, incrementally,\nDialogue: 0,1:21:32.33,1:21:35.04,EN,,0,0,0,,you can't do that by implementing it this way.\nDialogue: 0,1:21:40.99,1:21:41.24,EN,,0,0,0,,Yes.\nDialogue: 0,1:21:42.30,1:21:44.25,EN,,0,0,0,,AUDIENCE: Another question on your danger slide.\nDialogue: 0,1:21:44.65,1:21:47.13,EN,,0,0,0,,It seemed that the two examples that you gave\nDialogue: 0,1:21:47.16,1:21:49.07,EN,,0,0,0,,had to do with convergence and non-convergence?\nDialogue: 0,1:21:49.18,1:21:49.56,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:21:50.30,1:21:52.62,EN,,0,0,0,,AUDIENCE: And that may or may not have something to do with\nDialogue: 0,1:21:52.76,1:21:54.68,EN,,0,0,0,,with function theory in a way which\nDialogue: 0,1:21:54.72,1:21:56.60,EN,,0,0,0,,would lead you to think of it in terms of linear systems,\nDialogue: 0,1:21:57.74,1:21:59.00,EN,,0,0,0,,or non-linear systems.\nDialogue: 0,1:21:59.34,1:22:01.76,EN,,0,0,0,,How does this convergence relate to being able to\nDialogue: 0,1:22:02.35,1:22:05.53,EN,,0,0,0,,see a priori what properties of that might be violated?\nDialogue: 0,1:22:05.79,1:22:06.57,EN,,0,0,0,,PROFESSOR: I don't know.\nDialogue: 0,1:22:07.68,1:22:10.09,EN,,0,0,0,,The answer is, I don't know under what circumstances.\nDialogue: 0,1:22:10.61,1:22:12.04,EN,,0,0,0,,I don't know how to translate that\nDialogue: 0,1:22:12.52,1:22:14.73,EN,,0,0,0,,into less than an hour of talk more.\nDialogue: 0,1:22:16.91,1:22:18.48,EN,,0,0,0,,What are the conditions under which,\nDialogue: 0,1:22:18.86,1:22:20.76,EN,,0,0,0,,for which we know that these things converge?\nDialogue: 0,1:22:22.86,1:22:23.31,EN,,0,0,0,,And indeed,\nDialogue: 0,1:22:23.32,1:22:26.35,EN,,0,0,0,,all that was telling you that arguments that are based on convergence\nDialogue: 0,1:22:28.24,1:22:29.47,EN,,0,0,0,,are flaky\nDialogue: 0,1:22:29.66,1:22:31.58,EN,,0,0,0,,if you don't know the convergence beforehand.\nDialogue: 0,1:22:32.81,1:22:34.20,EN,,0,0,0,,You can make wrong arguments.\nDialogue: 0,1:22:34.44,1:22:37.31,EN,,0,0,0,,You can make deductions, as if you know the answer,\nDialogue: 0,1:22:37.39,1:22:39.93,EN,,0,0,0,,and not be stopped somewhere by some obvious contradiction.\nDialogue: 0,1:22:40.97,1:22:42.28,EN,,0,0,0,,AUDIENCE: So can we say then that\nDialogue: 0,1:22:42.33,1:22:44.88,EN,,0,0,0,,if F is a convergent mathematical expression,\nDialogue: 0,1:22:45.00,1:22:47.36,EN,,0,0,0,,then the recursion property can be--\nDialogue: 0,1:22:47.58,1:22:51.29,EN,,0,0,0,,PROFESSOR: Well, I think there's a technical kind of F,\nDialogue: 0,1:22:52.12,1:22:54.22,EN,,0,0,0,,OK? There is a technical description\nDialogue: 0,1:22:54.24,1:22:55.90,EN,,0,0,0,,of those F's that have the property\nDialogue: 0,1:22:55.98,1:23:01.31,EN,,0,0,0,,that when you iteratively apply them like this,\nDialogue: 0,1:23:01.52,1:23:02.25,EN,,0,0,0,,you converge.\nDialogue: 0,1:23:03.02,1:23:06.51,EN,,0,0,0,,Things that are monotonic, and continuous,\nDialogue: 0,1:23:07.32,1:23:07.95,EN,,0,0,0,,OK?\nDialogue: 0,1:23:08.38,1:23:09.37,EN,,0,0,0,,and I forgot what else.\nDialogue: 0,1:23:09.37,1:23:11.13,EN,,0,0,0,,There is a whole bunch of little conditions like that\nDialogue: 0,1:23:11.68,1:23:12.99,EN,,0,0,0,,which have this property.\nDialogue: 0,1:23:13.43,1:23:16.00,EN,,0,0,0,,Now the real problem is deducing from looking at the F,\nDialogue: 0,1:23:16.92,1:23:17.88,EN,,0,0,0,,its definition here,\nDialogue: 0,1:23:18.17,1:23:19.66,EN,,0,0,0,,whether not it has those properties,\nDialogue: 0,1:23:20.27,1:23:21.32,EN,,0,0,0,,and that's very hard.\nDialogue: 0,1:23:22.01,1:23:24.00,EN,,0,0,0,,The properties are easy. You can write them down.\nDialogue: 0,1:23:24.58,1:23:26.32,EN,,0,0,0,,You can look in a book by Joe Stoy.\nDialogue: 0,1:23:26.67,1:23:29.58,EN,,0,0,0,,It's a great book-- Stoy.\nDialogue: 0,1:23:32.22,1:23:34.06,EN,,0,0,0,,It's called, The Scott-Strachey\nDialogue: 0,1:23:34.49,1:23:38.46,EN,,0,0,0,,The Scott-Strachey Method of Denotational Semantics,\nDialogue: 0,1:23:39.55,1:23:40.76,EN,,0,0,0,,and it's by Joe Stoy,\nDialogue: 0,1:23:40.80,1:23:41.76,EN,,0,0,0,,MIT Press.\nDialogue: 0,1:23:48.06,1:23:49.88,EN,,0,0,0,,And he works out all this in great detail,\nDialogue: 0,1:23:50.20,1:23:51.37,EN,,0,0,0,,enough to horrify you.\nDialogue: 0,1:23:55.05,1:23:56.19,EN,,0,0,0,,But it really is readable.\nDialogue: 0,1:24:09.15,1:24:10.08,EN,,0,0,0,,OK, well, thank you.\nDialogue: 0,1:24:11.49,1:24:12.99,EN,,0,0,0,,Time for the bigger break, I suppose.\nDialogue: 0,0:00:00.03,0:00:01.28,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:01.39,0:00:08.09,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N张大伟\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:08.94,0:00:12.59,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 I\nDialogue: 0,0:00:15.79,0:00:17.32,Default,,0,0,0,,教授：今天我们将学习一些\nDialogue: 0,0:00:17.52,0:00:18.41,Default,,0,0,0,,非同一般的东西\nDialogue: 0,0:00:19.20,0:00:21.88,Default,,0,0,0,,我们将对计算机程序\nDialogue: 0,0:00:22.59,0:00:25.21,Default,,0,0,0,,有更深层次的理解\nDialogue: 0,0:00:26.80,0:00:29.12,Default,,0,0,0,,目前为止 我们一直把程序看作\nDialogue: 0,0:00:29.26,0:00:32.09,Default,,0,0,0,,对机器的描述\nDialogue: 0,0:00:32.72,0:00:37.21,Default,,0,0,0,,举个例子 在这个幻灯片上\nDialogue: 0,0:00:37.93,0:00:41.77,Default,,0,0,0,,我们可以看到一个计算阶乘的程序\nDialogue: 0,0:00:42.80,0:00:47.31,Default,,0,0,0,,当然 你可以认为这些字符串描述了\nDialogue: 0,0:00:47.66,0:00:51.98,Default,,0,0,0,,这个线路图所表示的无穷机器\nDialogue: 0,0:00:52.49,0:00:54.80,Default,,0,0,0,,我们可以稍稍地看下 它描述的是什么\nDialogue: 0,0:00:55.13,0:00:58.20,Default,,0,0,0,,这种紧凑的记法 描述的是：\nDialogue: 0,0:00:58.54,0:01:00.17,Default,,0,0,0,,如果N是0 结果就是1\nDialogue: 0,0:01:00.17,0:01:02.00,Default,,0,0,0,,N是从这里进入机器的\nDialogue: 0,0:01:02.33,0:01:03.52,Default,,0,0,0,,如果它是0的话\nDialogue: 0,0:01:03.74,0:01:05.20,Default,,0,0,0,,那么我就控制这个开关\nDialogue: 0,0:01:05.47,0:01:08.20,Default,,0,0,0,,把它掰到输出为1的那一端\nDialogue: 0,0:01:09.34,0:01:10.08,Default,,0,0,0,,否则的话\nDialogue: 0,0:01:10.38,0:01:12.83,Default,,0,0,0,,就是(* N (FACT (- N 1)))\nDialogue: 0,0:01:12.97,0:01:15.13,Default,,0,0,0,,我先计算(FACT (- N 1))\nDialogue: 0,0:01:15.29,0:01:16.68,Default,,0,0,0,,再把结果乘以N\nDialogue: 0,0:01:16.84,0:01:18.91,Default,,0,0,0,,这样如果N不为0的话\nDialogue: 0,0:01:18.91,0:01:20.60,Default,,0,0,0,,这个开关就会输出这里的结果\nDialogue: 0,0:01:21.90,0:01:22.32,Default,,0,0,0,,当然了\nDialogue: 0,0:01:22.36,0:01:25.13,Default,,0,0,0,,这个机器可能有无穷多个部件\nDialogue: 0,0:01:25.48,0:01:28.12,Default,,0,0,0,,因为FACT内部又调用了FACT\nDialogue: 0,0:01:28.43,0:01:30.17,Default,,0,0,0,,因此我们不知道调用栈有多深\nDialogue: 0,0:01:31.07,0:01:33.55,Default,,0,0,0,,但到目前为止\nDialogue: 0,0:01:34.22,0:01:37.69,Default,,0,0,0,,代码对我们来说就是这样的东西了\nDialogue: 0,0:01:38.31,0:01:40.59,Default,,0,0,0,,你可以认为代码是用字符串来描述\nDialogue: 0,0:01:41.28,0:01:44.16,Default,,0,0,0,,某种用其它方式描画的线路图\nDialogue: 0,0:01:44.90,0:01:46.60,Default,,0,0,0,,事实上 很多人都向我提议\nDialogue: 0,0:01:46.84,0:01:49.04,Default,,0,0,0,,说程序设计语言应该像这个一样 是图像化的\nDialogue: 0,0:01:49.49,0:01:51.80,Default,,0,0,0,,不过我不认为用图形表示会有很多优势\nDialogue: 0,0:01:52.00,0:01:53.79,Default,,0,0,0,,当然 最主要的劣势就是\nDialogue: 0,0:01:53.80,0:01:55.63,Default,,0,0,0,,它需要占用很大的平面空间\nDialogue: 0,0:01:55.96,0:01:59.95,Default,,0,0,0,,所以展示和修改起来就非常麻烦\nDialogue: 0,0:02:01.34,0:02:02.16,Default,,0,0,0,,但是不管怎样\nDialogue: 0,0:02:03.58,0:02:05.15,Default,,0,0,0,,在计算的世界中\nDialogue: 0,0:02:05.18,0:02:07.05,Default,,0,0,0,,还有一个非常重要的东西\nDialogue: 0,0:02:07.64,0:02:10.64,Default,,0,0,0,,也就是所谓的“通用机器”\nDialogue: 0,0:02:10.73,0:02:15.24,Default,,0,0,0,,我们再来看第二张幻灯片\nDialogue: 0,0:02:16.04,0:02:17.18,Default,,0,0,0,,我们看到的就是\nDialogue: 0,0:02:18.14,0:02:19.88,Default,,0,0,0,,名为EVAL的特殊机器\nDialogue: 0,0:02:21.26,0:02:22.86,Default,,0,0,0,,这个叫做EVAL的机器\nDialogue: 0,0:02:22.88,0:02:24.24,Default,,0,0,0,,也就是我今天要讲解的\nDialogue: 0,0:02:25.82,0:02:26.67,Default,,0,0,0,,它非常简单\nDialogue: 0,0:02:27.78,0:02:30.80,Default,,0,0,0,,最了不起的是 它简单得可以写在黑板上\nDialogue: 0,0:02:33.35,0:02:35.79,Default,,0,0,0,,然而 EVAL这个机器\nDialogue: 0,0:02:36.00,0:02:39.84,Default,,0,0,0,,是以其它机器的描述作为输入的\nDialogue: 0,0:02:40.45,0:02:42.12,Default,,0,0,0,,它可以接收一个\nDialogue: 0,0:02:42.40,0:02:45.58,Default,,0,0,0,,阶乘机器的线路图作为输入\nDialogue: 0,0:02:46.49,0:02:47.66,Default,,0,0,0,,这样一来\nDialogue: 0,0:02:48.49,0:02:52.57,Default,,0,0,0,,它就可以模拟那台阶乘机器\nDialogue: 0,0:02:53.13,0:02:53.79,Default,,0,0,0,,这样的话\nDialogue: 0,0:02:54.16,0:02:56.36,Default,,0,0,0,,如果输入6 就会得到720\nDialogue: 0,0:02:58.91,0:03:01.68,Default,,0,0,0,,这是一个非常了不起的机器\nDialogue: 0,0:03:02.13,0:03:03.58,Default,,0,0,0,,而最让人惊奇的是\nDialogue: 0,0:03:03.77,0:03:05.13,Default,,0,0,0,,它竟然可以写在一个黑板内\nDialogue: 0,0:03:05.59,0:03:06.65,Default,,0,0,0,,与之相反的是\nDialogue: 0,0:03:07.32,0:03:10.44,Default,,0,0,0,,我们可以想象一下模拟电子世界中的\nDialogue: 0,0:03:11.55,0:03:12.86,Default,,0,0,0,,一台非常不同的机器\nDialogue: 0,0:03:14.57,0:03:16.33,Default,,0,0,0,,这台机器呢\nDialogue: 0,0:03:16.52,0:03:18.81,Default,,0,0,0,,某种意义上 同样也是“通用机器”\nDialogue: 0,0:03:19.26,0:03:23.12,Default,,0,0,0,,只要你输入一个电路图\nDialogue: 0,0:03:23.82,0:03:25.74,Default,,0,0,0,,比如这个小型的低通滤波器\nDialogue: 0,0:03:26.01,0:03:27.48,Default,,0,0,0,,单极低通滤波器之类的\nDialogue: 0,0:03:28.05,0:03:29.53,Default,,0,0,0,,你可以想像\nDialogue: 0,0:03:29.71,0:03:33.15,Default,,0,0,0,,如果我们扫描这个元件得到扫描线\nDialogue: 0,0:03:34.43,0:03:37.13,Default,,0,0,0,,得到的信号描述的就是\nDialogue: 0,0:03:37.39,0:03:40.40,Default,,0,0,0,,这个机器所模拟的\nDialogue: 0,0:03:40.78,0:03:43.39,Default,,0,0,0,,这个模拟机器EVAL是由电路构成\nDialogue: 0,0:03:43.68,0:03:45.15,Default,,0,0,0,,它可以把自己配置成一个滤波器\nDialogue: 0,0:03:45.18,0:03:48.04,Default,,0,0,0,,响应由电路图指定的频率\nDialogue: 0,0:03:49.89,0:03:51.48,Default,,0,0,0,,这种机器很难制造出来\nDialogue: 0,0:03:51.61,0:03:54.06,Default,,0,0,0,,当然 更不可能用一个黑板就把它说清楚\nDialogue: 0,0:03:55.67,0:03:57.58,Default,,0,0,0,,所以今天我们将学习一些神奇的东西\nDialogue: 0,0:03:58.43,0:04:00.81,Default,,0,0,0,,我们将在黑板上见证\nDialogue: 0,0:04:01.16,0:04:02.49,Default,,0,0,0,,通用机器\nDialogue: 0,0:04:02.79,0:04:04.41,Default,,0,0,0,,跟其它程序比起来\nDialogue: 0,0:04:04.52,0:04:05.80,Default,,0,0,0,,它真是非常简单\nDialogue: 0,0:04:06.78,0:04:08.75,Default,,0,0,0,,现在 我们已经非常接近\nDialogue: 0,0:04:09.08,0:04:10.97,Default,,0,0,0,,计算机中真正的精灵了\nDialogue: 0,0:04:11.28,0:04:14.62,Default,,0,0,0,,所以为了保持足够的尊重\nDialogue: 0,0:04:15.18,0:04:17.32,Default,,0,0,0,,我特地穿上外套\nDialogue: 0,0:04:17.52,0:04:19.29,Default,,0,0,0,,你们应该从没见我穿过\nDialogue: 0,0:04:20.47,0:04:22.73,Default,,0,0,0,,在这个盛重的场合\nDialogue: 0,0:04:23.55,0:04:26.70,Default,,0,0,0,,我还得戴上一顶合适的帽子\nDialogue: 0,0:04:28.78,0:04:31.44,Default,,0,0,0,,开讲前再给大家提个醒\nDialogue: 0,0:04:34.14,0:04:36.91,Default,,0,0,0,,那些40岁以下\nDialogue: 0,0:04:37.16,0:04:38.49,Default,,0,0,0,,以及没有孩子的人\nDialogue: 0,0:04:38.67,0:04:40.49,Default,,0,0,0,,你们可要小心了\nDialogue: 0,0:04:40.49,0:04:41.96,Default,,0,0,0,,如果真的受不了 可以选择离开\nDialogue: 0,0:04:43.34,0:04:45.56,Default,,0,0,0,,因为一会儿要发生一些\nDialogue: 0,0:04:45.72,0:04:47.13,Default,,0,0,0,,非常神秘的事情\nDialogue: 0,0:04:47.74,0:04:51.05,Default,,0,0,0,,可能使你的大脑异常混乱\nDialogue: 0,0:04:51.82,0:04:54.28,Default,,0,0,0,,好了 无论如何\nDialogue: 0,0:04:55.71,0:05:01.10,Default,,0,0,0,,我要带着你们写一个Lisp求值器\nDialogue: 0,0:05:02.51,0:05:04.28,Default,,0,0,0,,求值器并不复杂\nDialogue: 0,0:05:05.02,0:05:07.63,Default,,0,0,0,,很像我们以前见到过的程序\nDialogue: 0,0:05:08.24,0:05:09.48,Default,,0,0,0,,这也是它令人吃惊的地方\nDialogue: 0,0:05:10.86,0:05:13.10,Default,,0,0,0,,现在我开始写这个程序\nDialogue: 0,0:05:15.28,0:05:16.62,Default,,0,0,0,,我把这个程序叫做EVAL\nDialogue: 0,0:05:22.90,0:05:26.24,Default,,0,0,0,,这个过程接收两个参数\nDialogue: 0,0:05:26.28,0:05:29.44,Default,,0,0,0,,表达式EXP和环境ENV\nDialogue: 0,0:05:31.86,0:05:33.79,Default,,0,0,0,,跟所有实用过程一样\nDialogue: 0,0:05:34.01,0:05:35.13,Default,,0,0,0,,它是个“按情况分析”语句\nDialogue: 0,0:05:40.46,0:05:41.87,Default,,0,0,0,,但是在我开始之前\nDialogue: 0,0:05:42.52,0:05:43.90,Default,,0,0,0,,我还想你们注意一下\nDialogue: 0,0:05:44.44,0:05:46.06,Default,,0,0,0,,我将要在黑板上写的程序\nDialogue: 0,0:05:46.56,0:05:50.24,Default,,0,0,0,,非常丑陋、混乱、令人作呕\nDialogue: 0,0:05:50.94,0:05:53.16,Default,,0,0,0,,并不是一种专业的写法\nDialogue: 0,0:05:54.32,0:05:56.57,Default,,0,0,0,,它是用具体语法写就的\nDialogue: 0,0:05:57.24,0:05:58.83,Default,,0,0,0,,也就是说用了很多CAR、CDR\nDialogue: 0,0:05:58.84,0:06:00.62,Default,,0,0,0,,我之前告诉过你们这样写并不好\nDialogue: 0,0:06:02.94,0:06:05.61,Default,,0,0,0,,在这里是故意这样来写的\nDialogue: 0,0:06:06.11,0:06:09.02,Default,,0,0,0,,因为我想让它尽量精简\nDialogue: 0,0:06:09.34,0:06:10.40,Default,,0,0,0,,能塞在黑板内\nDialogue: 0,0:06:10.43,0:06:11.85,Default,,0,0,0,,你们就可以看到整个代码\nDialogue: 0,0:06:12.42,0:06:14.80,Default,,0,0,0,,我就不像平时那样实用长变量名了\nDialogue: 0,0:06:15.60,0:06:17.29,Default,,0,0,0,,就用CAR、CDR 因为它们短小\nDialogue: 0,0:06:18.06,0:06:20.78,Default,,0,0,0,,这算是一种取舍\nDialogue: 0,0:06:20.89,0:06:22.81,Default,,0,0,0,,我不希望你们这样来写程序\nDialogue: 0,0:06:23.57,0:06:25.08,Default,,0,0,0,,这里单纯地想达到一种简洁的效果\nDialogue: 0,0:06:25.85,0:06:27.61,Default,,0,0,0,,因此你们读起来可能有些费力\nDialogue: 0,0:06:27.77,0:06:30.19,Default,,0,0,0,,我尽量写得清楚一些\nDialogue: 0,0:06:31.27,0:06:34.40,Default,,0,0,0,,这个解释器已经比较完整了\nDialogue: 0,0:06:34.51,0:06:36.24,Default,,0,0,0,,但是还是缺少一些功能\nDialogue: 0,0:06:36.25,0:06:38.60,Default,,0,0,0,,我就不写定义和赋值的部分了\nDialogue: 0,0:06:39.10,0:06:42.41,Default,,0,0,0,,因为它们都不是最本质的\nDialogue: 0,0:06:42.88,0:06:46.46,Default,,0,0,0,,稍后我就会解释 这是数学上的原因\nDialogue: 0,0:06:46.92,0:06:49.96,Default,,0,0,0,,当然啦 黑板也没有那么大\nDialogue: 0,0:06:51.88,0:06:53.64,Default,,0,0,0,,但是 我们怎么做呢？\nDialogue: 0,0:06:53.95,0:06:55.66,Default,,0,0,0,,我们需要一个分派\nDialogue: 0,0:06:56.09,0:06:57.90,Default,,0,0,0,,它根据表达式的类型\nDialogue: 0,0:06:58.28,0:07:00.38,Default,,0,0,0,,把它们划分为几类\nDialogue: 0,0:07:01.72,0:07:03.26,Default,,0,0,0,,这就是现在要做的\nDialogue: 0,0:07:03.82,0:07:05.15,Default,,0,0,0,,我们都有哪些表达式？\nDialogue: 0,0:07:05.15,0:07:06.36,Default,,0,0,0,,我们先来看几种表达式\nDialogue: 0,0:07:06.81,0:07:09.60,Default,,0,0,0,,比如说 数字“3”就是一个表达式\nDialogue: 0,0:07:10.42,0:07:11.58,Default,,0,0,0,,我想让它代表什么呢？\nDialogue: 0,0:07:12.72,0:07:14.75,Default,,0,0,0,,我有很多选择 但是就现在而言\nDialogue: 0,0:07:15.05,0:07:16.20,Default,,0,0,0,,我就想让它表示数字3\nDialogue: 0,0:07:17.05,0:07:17.88,Default,,0,0,0,,这就是我要的\nDialogue: 0,0:07:18.72,0:07:19.69,Default,,0,0,0,,这个足够简单\nDialogue: 0,0:07:20.03,0:07:22.91,Default,,0,0,0,,那就意味着 如果表达式是数字\nDialogue: 0,0:07:27.29,0:07:31.68,Default,,0,0,0,,表达式本身就应该是求值结果\nDialogue: 0,0:07:35.42,0:07:36.76,Default,,0,0,0,,另外一种情况是\nDialogue: 0,0:07:36.89,0:07:38.86,Default,,0,0,0,,表达式还可能是符号\nDialogue: 0,0:07:39.39,0:07:46.75,Default,,0,0,0,,比如EXP、ENV、EVAL、NUMBER、X之类\nDialogue: 0,0:07:48.01,0:07:49.18,Default,,0,0,0,,它们意味着什么？\nDialogue: 0,0:07:50.16,0:07:51.63,Default,,0,0,0,,它们是一类代表其它事物的事物\nDialogue: 0,0:07:51.63,0:07:53.23,Default,,0,0,0,,也就是我们语言中所谓的变量\nDialogue: 0,0:07:54.77,0:07:56.88,Default,,0,0,0,,因此我想要能够 比如说\nDialogue: 0,0:07:57.05,0:08:01.04,Default,,0,0,0,,对X求值 可能会得到3\nDialogue: 0,0:08:02.64,0:08:05.76,Default,,0,0,0,,又可能是CAR\nDialogue: 0,0:08:07.76,0:08:09.40,Default,,0,0,0,,我希望它的值是\nDialogue: 0,0:08:09.63,0:08:11.34,Default,,0,0,0,,某种类似于过程的东西\nDialogue: 0,0:08:16.51,0:08:18.43,Default,,0,0,0,,我不需要知道它内部是什么\nDialogue: 0,0:08:18.64,0:08:21.15,Default,,0,0,0,,可能是一些机器码 或者类似的东西\nDialogue: 0,0:08:22.84,0:08:24.27,Default,,0,0,0,,到这是还是相对简单的\nDialogue: 0,0:08:24.43,0:08:26.89,Default,,0,0,0,,我想把这部分交给其他人来写\nDialogue: 0,0:08:27.80,0:08:28.89,Default,,0,0,0,,如果我们有一个符号\nDialogue: 0,0:08:30.80,0:08:32.48,Default,,0,0,0,,假如表达式是符号\nDialogue: 0,0:08:33.42,0:08:34.88,Default,,0,0,0,,那么我求值它的结果就应该是\nDialogue: 0,0:08:34.91,0:08:40.24,Default,,0,0,0,,在环境ENV中查找该表达式的值\nDialogue: 0,0:08:46.48,0:08:48.99,Default,,0,0,0,,环境是一个字典\nDialogue: 0,0:08:49.96,0:08:54.06,Default,,0,0,0,,它把符号映射成一个值\nDialogue: 0,0:08:54.28,0:08:55.16,Default,,0,0,0,,就这么简单\nDialogue: 0,0:08:56.28,0:08:57.20,Default,,0,0,0,,怎么完成的呢？\nDialogue: 0,0:08:57.53,0:08:58.52,Default,,0,0,0,,稍后我们再谈这个\nDialogue: 0,0:08:59.68,0:09:00.57,Default,,0,0,0,,其实并不难\nDialogue: 0,0:09:01.67,0:09:04.28,Default,,0,0,0,,编写类似于表的数据结构非常容易\nDialogue: 0,0:09:04.84,0:09:05.74,Default,,0,0,0,,但它只是一个表\nDialogue: 0,0:09:05.77,0:09:07.56,Default,,0,0,0,,而这是存取某个表的过程\nDialogue: 0,0:09:09.55,0:09:10.81,Default,,0,0,0,,好的 接下来\nDialogue: 0,0:09:11.31,0:09:12.56,Default,,0,0,0,,另一类表达式\nDialogue: 0,0:09:12.67,0:09:15.56,Default,,0,0,0,,表达式可能是一些不是数字的常量\nDialogue: 0,0:09:16.06,0:09:17.43,Default,,0,0,0,,比如 'FOO\nDialogue: 0,0:09:20.17,0:09:21.29,Default,,0,0,0,,为了方便起见\nDialogue: 0,0:09:21.31,0:09:23.36,Default,,0,0,0,,我想在语法上\nDialogue: 0,0:09:24.73,0:09:26.80,Default,,0,0,0,,把它转换成表结构\nDialogue: 0,0:09:26.84,0:09:31.52,Default,,0,0,0,,比如说是(QUOTE FOO)\nDialogue: 0,0:09:33.72,0:09:37.18,Default,,0,0,0,,一个被引用起来的对象 无论它是什么\nDialogue: 0,0:09:38.35,0:09:40.83,Default,,0,0,0,,都实际上是一个缩写\nDialogue: 0,0:09:41.04,0:09:42.59,Default,,0,0,0,,这一部分并不由求值器负责\nDialogue: 0,0:09:43.21,0:09:44.46,Default,,0,0,0,,这是在其它地方完成的\nDialogue: 0,0:09:44.75,0:09:47.79,Default,,0,0,0,,左边的符号就是右边表达式的缩略形式\nDialogue: 0,0:09:48.78,0:09:50.48,Default,,0,0,0,,这样 我就可以\nDialogue: 0,0:09:50.57,0:09:53.12,Default,,0,0,0,,依据表达式的CAR部分\nDialogue: 0,0:09:53.31,0:09:55.95,Default,,0,0,0,,来判断它的类型了\nDialogue: 0,0:09:58.46,0:10:01.08,Default,,0,0,0,,因此这一部分也不会出现在求值器中\nDialogue: 0,0:10:01.65,0:10:02.68,Default,,0,0,0,,这在更早时候\nDialogue: 0,0:10:02.70,0:10:03.96,Default,,0,0,0,,比如源代码读取阶段完成\nDialogue: 0,0:10:05.54,0:10:15.04,Default,,0,0,0,,如果是引用表达式\nDialogue: 0,0:10:18.27,0:10:19.10,Default,,0,0,0,,那么求值的结果就是\nDialogue: 0,0:10:19.63,0:10:25.13,Default,,0,0,0,,我想让(QUOTE FOO)求值为自身FOO\nDialogue: 0,0:10:25.14,0:10:25.95,Default,,0,0,0,,一个常量\nDialogue: 0,0:10:27.53,0:10:28.92,Default,,0,0,0,,这条代码是说\nDialogue: 0,0:10:29.08,0:10:30.73,Default,,0,0,0,,这类表达式求值为它自己\nDialogue: 0,0:10:31.79,0:10:33.66,Default,,0,0,0,,怎么才能把它取出来呢？\nDialogue: 0,0:10:33.66,0:10:36.36,Default,,0,0,0,,这是列表第二个元素的第一个部分\nDialogue: 0,0:10:36.59,0:10:37.58,Default,,0,0,0,,也就是表的第二个元素\nDialogue: 0,0:10:38.49,0:10:40.32,Default,,0,0,0,,也就是CADR\nDialogue: 0,0:10:41.28,0:10:42.38,Default,,0,0,0,,所以这里我就写CADR\nDialogue: 0,0:10:51.08,0:10:52.35,Default,,0,0,0,,表达式还可能是什么类型呢？\nDialogue: 0,0:10:52.51,0:10:53.80,Default,,0,0,0,,还有LAMBDA表达式\nDialogue: 0,0:10:55.00,0:11:03.29,Default,,0,0,0,,比如 (LAMBDA (X) (+ X Y))\nDialogue: 0,0:11:04.16,0:11:06.33,Default,,0,0,0,,我还得找到某种表示方法\nDialogue: 0,0:11:06.33,0:11:07.85,Default,,0,0,0,,LAMBDA表达式求值的结果\nDialogue: 0,0:11:08.11,0:11:09.08,Default,,0,0,0,,也就是如何表示过程\nDialogue: 0,0:11:09.60,0:11:12.62,Default,,0,0,0,,过程并不就是表达式(LAMBDA (x))\nDialogue: 0,0:11:13.13,0:11:15.56,Default,,0,0,0,,表达式只是过程的代码描述\nDialogue: 0,0:11:16.41,0:11:18.33,Default,,0,0,0,,如果在词法作用域的语言中实现过程\nDialogue: 0,0:11:18.56,0:11:21.20,Default,,0,0,0,,那么我希望在表示过程的时候\nDialogue: 0,0:11:23.23,0:11:25.36,Default,,0,0,0,,能够把当前的求值环境包括进来\nDialogue: 0,0:11:25.84,0:11:29.07,Default,,0,0,0,,所以这里我还需要\nDialogue: 0,0:11:29.20,0:11:30.67,Default,,0,0,0,,一些类型标志\nDialogue: 0,0:11:30.70,0:11:33.90,Default,,0,0,0,,这样后面我就可以用它们来区分过程\nDialogue: 0,0:11:34.30,0:11:36.59,Default,,0,0,0,,看哪些是由LAMBDA表达式生成的\nDialogue: 0,0:11:36.81,0:11:38.03,Default,,0,0,0,,哪些是基本过程\nDialogue: 0,0:11:39.06,0:11:41.96,Default,,0,0,0,,所以这里是个类型标志\nDialogue: 0,0:11:41.98,0:11:43.56,Default,,0,0,0,,出于历史原因\nDialogue: 0,0:11:43.56,0:11:45.10,Default,,0,0,0,,我用CLOSURE作为类型标志\nDialogue: 0,0:11:47.68,0:11:49.60,Default,,0,0,0,,现在来看看 哪部分比较重要\nDialogue: 0,0:11:49.92,0:11:51.12,Default,,0,0,0,,我需要知道\nDialogue: 0,0:11:51.24,0:11:52.92,Default,,0,0,0,,绑定变量表和过程的体\nDialogue: 0,0:11:54.22,0:11:55.40,Default,,0,0,0,,这是它的CDR部分\nDialogue: 0,0:11:56.09,0:12:01.85,Default,,0,0,0,,这里就是((X) (+ X Y))\nDialogue: 0,0:12:03.04,0:12:03.87,Default,,0,0,0,,以及某个环境<ENV>\nDialogue: 0,0:12:08.17,0:12:12.20,Default,,0,0,0,,用户不应该看到这个东西\nDialogue: 0,0:12:13.53,0:12:16.19,Default,,0,0,0,,这只是过程对象的\nDialogue: 0,0:12:16.76,0:12:18.30,Default,,0,0,0,,一种内部表示\nDialogue: 0,0:12:18.52,0:12:20.52,Default,,0,0,0,,它包括绑定变量表\nDialogue: 0,0:12:20.70,0:12:22.62,Default,,0,0,0,,过程的体和某个环境\nDialogue: 0,0:12:23.53,0:12:25.80,Default,,0,0,0,,以及一个类型标签 表示这是一个过程\nDialogue: 0,0:12:26.34,0:12:27.37,Default,,0,0,0,,接下来写代码\nDialogue: 0,0:12:28.08,0:12:38.72,Default,,0,0,0,,如果表达式的CAR部分是'LAMBDA\nDialogue: 0,0:12:43.47,0:12:44.81,Default,,0,0,0,,这里 我就要\nDialogue: 0,0:12:45.64,0:12:51.84,Default,,0,0,0,,创建一个表 表头是'CLOSURE\nDialogue: 0,0:12:55.15,0:13:00.73,Default,,0,0,0,,接着是 过程代码的CDR部分\nDialogue: 0,0:13:01.56,0:13:02.97,Default,,0,0,0,,也就是除开LAMBDA的其它部分\nDialogue: 0,0:13:07.74,0:13:08.86,Default,,0,0,0,,以及当前的环境\nDialogue: 0,0:13:10.25,0:13:15.32,Default,,0,0,0,,这样就实现了环境模型中的那些规则\nDialogue: 0,0:13:15.45,0:13:18.52,Default,,0,0,0,,这是从LAMBDA表达式中构建过程所必须遵守的\nDialogue: 0,0:13:19.40,0:13:20.97,Default,,0,0,0,,那个求值器在遇到\nDialogue: 0,0:13:21.48,0:13:24.32,Default,,0,0,0,,LAMBDA表达式时的环境\nDialogue: 0,0:13:25.04,0:13:28.46,Default,,0,0,0,,在过程运行的时候\nDialogue: 0,0:13:28.68,0:13:31.77,Default,,0,0,0,,会去这个环境中查找自由变量的值\nDialogue: 0,0:13:34.72,0:13:35.82,Default,,0,0,0,,所以需要把它囊括进来\nDialogue: 0,0:13:35.92,0:13:37.55,Default,,0,0,0,,因此我们必须把求值时的环境\nDialogue: 0,0:13:37.56,0:13:38.86,Default,,0,0,0,,作为过程对象的一部分\nDialogue: 0,0:13:39.21,0:13:40.62,Default,,0,0,0,,之后再来看它的作用\nDialogue: 0,0:13:42.03,0:13:43.77,Default,,0,0,0,,我们也有COND表达式\nDialogue: 0,0:13:44.59,0:13:52.81,Default,,0,0,0,,像是(COND (P1 E1) (P2 E2) ...)这样的\nDialogue: 0,0:13:54.40,0:13:56.09,Default,,0,0,0,,P1是谓词\nDialogue: 0,0:13:56.35,0:13:58.43,Default,,0,0,0,,谓词总是返回TRUE或者FALSE\nDialogue: 0,0:13:58.99,0:14:01.76,Default,,0,0,0,,如果谓词P1为真时 表达式E1才被求值\nDialogue: 0,0:14:03.44,0:14:06.08,Default,,0,0,0,,当然 你也可以列这么一组子句\nDialogue: 0,0:14:06.79,0:14:09.36,Default,,0,0,0,,我会把它封装在另一个过程中\nDialogue: 0,0:14:09.36,0:14:11.56,Default,,0,0,0,,我们稍后在那个过程中进行处理\nDialogue: 0,0:14:12.42,0:14:21.28,Default,,0,0,0,,如果表达式的CAR部分是'COND的话\nDialogue: 0,0:14:24.00,0:14:26.84,Default,,0,0,0,,那么我就用EVCOND来求值这个表达式\nDialogue: 0,0:14:30.20,0:14:31.42,Default,,0,0,0,,求值表达式的CDR部分\nDialogue: 0,0:14:34.40,0:14:38.49,Default,,0,0,0,,记得带上环境\nDialogue: 0,0:14:41.43,0:14:42.60,Default,,0,0,0,,好的 还有一种情况\nDialogue: 0,0:14:44.09,0:14:48.22,Default,,0,0,0,,任意的像(+ X 3)这样的表达式\nDialogue: 0,0:14:50.62,0:14:53.95,Default,,0,0,0,,这是把运算符应用在运算对象上\nDialogue: 0,0:14:55.13,0:14:56.59,Default,,0,0,0,,这并没有什么特殊的\nDialogue: 0,0:14:56.59,0:14:59.63,Default,,0,0,0,,就是说 它不属于这里的特殊形式\nDialogue: 0,0:14:59.85,0:15:01.42,Default,,0,0,0,,上面写的这些都是特殊形式\nDialogue: 0,0:15:09.65,0:15:12.12,Default,,0,0,0,,再说明一下 如果我要把这个程序写得专业一点\nDialogue: 0,0:15:12.36,0:15:14.17,Default,,0,0,0,,我会把它设计成数据导向的\nDialogue: 0,0:15:14.48,0:15:16.52,Default,,0,0,0,,那样的话 这里就不会是一系列的条件判断\nDialogue: 0,0:15:16.65,0:15:18.20,Default,,0,0,0,,而是根据一些比特位来做分派\nDialogue: 0,0:15:19.42,0:15:22.25,Default,,0,0,0,,这样来设计会更加专业一些\nDialogue: 0,0:15:22.36,0:15:24.14,Default,,0,0,0,,并且 我不用大量修改程序\nDialogue: 0,0:15:24.68,0:15:26.38,Default,,0,0,0,,就可以添加规则\nDialogue: 0,0:15:26.71,0:15:28.46,Default,,0,0,0,,这样来做可能运行得更快\nDialogue: 0,0:15:29.04,0:15:30.43,Default,,0,0,0,,但这里我并不打算这么做\nDialogue: 0,0:15:31.28,0:15:33.98,Default,,0,0,0,,现在的目的是把握EVAL过程的整体\nDialogue: 0,0:15:35.07,0:15:35.80,Default,,0,0,0,,那么 最后一种情况\nDialogue: 0,0:15:37.69,0:15:38.56,Default,,0,0,0,,要怎么做呢？\nDialogue: 0,0:15:38.56,0:15:41.23,Default,,0,0,0,,在这种情况下 我需要进行加法运算\nDialogue: 0,0:15:44.35,0:15:46.16,Default,,0,0,0,,那么我就得搞清楚 '+到底是什么\nDialogue: 0,0:15:46.84,0:15:49.29,Default,,0,0,0,,我还得知道X和3又代表什么\nDialogue: 0,0:15:50.55,0:15:53.96,Default,,0,0,0,,然后再把'+的所代表的东西\nDialogue: 0,0:15:54.43,0:15:57.00,Default,,0,0,0,,应用于'X与3所代表的东西上\nDialogue: 0,0:15:58.11,0:15:59.39,Default,,0,0,0,,具体来写一下\nDialogue: 0,0:15:59.87,0:16:09.55,Default,,0,0,0,,我要把表达式CAR部分的求值结果\nDialogue: 0,0:16:11.20,0:16:12.14,Default,,0,0,0,,应用在\nDialogue: 0,0:16:13.21,0:16:15.50,Default,,0,0,0,,表达式的CAR部分就是运算符\nDialogue: 0,0:16:17.20,0:16:18.51,Default,,0,0,0,,要在给定的环境中进行\nDialogue: 0,0:16:20.51,0:16:22.89,Default,,0,0,0,,对运算符求值会得到一个过程\nDialogue: 0,0:16:24.05,0:16:26.78,Default,,0,0,0,,现在 我要求值所有运算对象来取得参数\nDialogue: 0,0:16:27.29,0:16:28.22,Default,,0,0,0,,我将调用EVLIST\nDialogue: 0,0:16:31.26,0:16:35.53,Default,,0,0,0,,来求值表达式的CDR部分 也就是运算对象\nDialogue: 0,0:16:36.76,0:16:39.00,Default,,0,0,0,,当然是在相应的环境中\nDialogue: 0,0:16:41.94,0:16:43.13,Default,,0,0,0,,我们待会儿再定义EVLIST\nDialogue: 0,0:16:43.26,0:16:48.07,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:16:50.90,0:16:52.33,Default,,0,0,0,,你现在看到的\nDialogue: 0,0:16:52.67,0:16:56.11,Default,,0,0,0,,基本上就是一个完整的求值器\nDialogue: 0,0:16:56.49,0:17:01.00,Default,,0,0,0,,它根据表达式的类型分情况处理\nDialogue: 0,0:17:01.24,0:17:02.11,Default,,0,0,0,,默认的情况是\nDialogue: 0,0:17:04.99,0:17:07.95,Default,,0,0,0,,表达式应用或者说是组合式\nDialogue: 0,0:17:17.52,0:17:19.52,Default,,0,0,0,,不过还有好些过程 我们没有定义\nDialogue: 0,0:17:20.08,0:17:21.60,Default,,0,0,0,,接下来就看这些未定义的部分\nDialogue: 0,0:17:21.78,0:17:24.12,Default,,0,0,0,,我们还要定义EVCOND\nDialogue: 0,0:17:25.48,0:17:26.67,Default,,0,0,0,,我得定义APPLY\nDialogue: 0,0:17:27.57,0:17:28.62,Default,,0,0,0,,还有EVLIST\nDialogue: 0,0:17:28.94,0:17:30.20,Default,,0,0,0,,以及LOOKUP\nDialogue: 0,0:17:31.79,0:17:33.43,Default,,0,0,0,,我看看 没别的了吧？\nDialogue: 0,0:17:33.43,0:17:35.16,Default,,0,0,0,,剩下的东西都很简单\nDialogue: 0,0:17:35.16,0:17:37.18,Default,,0,0,0,,比如基本元素之类的东西\nDialogue: 0,0:17:38.57,0:17:39.48,Default,,0,0,0,,当然\nDialogue: 0,0:17:39.69,0:17:42.06,Default,,0,0,0,,在这里 可以扩充很多特殊形式\nDialogue: 0,0:17:42.25,0:17:44.45,Default,,0,0,0,,但如果在通用语言中这么做就很糟糕\nDialogue: 0,0:17:44.45,0:17:45.92,Default,,0,0,0,,在这里添加大量的东西\nDialogue: 0,0:17:46.00,0:17:47.48,Default,,0,0,0,,会让语言变得复杂\nDialogue: 0,0:17:47.69,0:17:50.35,Default,,0,0,0,,语言中的保留字\nDialogue: 0,0:17:50.76,0:17:53.61,Default,,0,0,0,,不该比你能用几个手指、脚指记住的数目多\nDialogue: 0,0:17:54.16,0:17:55.53,Default,,0,0,0,,有些语言的保留字有成百上千个\nDialogue: 0,0:17:55.56,0:17:58.20,Default,,0,0,0,,我都不知道该说什么了\nDialogue: 0,0:17:59.41,0:18:00.71,Default,,0,0,0,,保留字就是在这里定义的\nDialogue: 0,0:18:03.15,0:18:06.54,Default,,0,0,0,,好 接下来 我们来看下一个部分\nDialogue: 0,0:18:06.56,0:18:07.69,Default,,0,0,0,,求值器的核心 APPLY\nDialogue: 0,0:18:09.64,0:18:10.75,Default,,0,0,0,,它还做些什么呢？\nDialogue: 0,0:18:11.59,0:18:17.53,Default,,0,0,0,,APPLY把还是符号状态的求值运算符和运算对象\nDialogue: 0,0:18:17.66,0:18:20.68,Default,,0,0,0,,求值为相应的过程以及参数值\nDialogue: 0,0:18:20.91,0:18:23.85,Default,,0,0,0,,然后把得到的过程应用在参数上\nDialogue: 0,0:18:24.09,0:18:26.96,Default,,0,0,0,,无论它们是什么符号表达式\nDialogue: 0,0:18:33.27,0:18:35.08,Default,,0,0,0,,我们把APPLY定义为\nDialogue: 0,0:18:38.35,0:18:40.65,Default,,0,0,0,,接收两个参数的过程\nDialogue: 0,0:18:40.75,0:18:43.44,Default,,0,0,0,,一个过程和对应的参数\nDialogue: 0,0:18:47.24,0:18:48.12,Default,,0,0,0,,它要怎么做呢？\nDialogue: 0,0:18:48.14,0:18:49.55,Default,,0,0,0,,其实并不复杂\nDialogue: 0,0:18:49.93,0:18:50.78,Default,,0,0,0,,分两种情况就够了\nDialogue: 0,0:18:53.58,0:18:55.16,Default,,0,0,0,,如果这个过程是基本过程--\nDialogue: 0,0:19:03.42,0:19:06.41,Default,,0,0,0,,我不知道这个谓词具体是如何判断的\nDialogue: 0,0:19:06.86,0:19:10.24,Default,,0,0,0,,可能这里面有某种类型信息\nDialogue: 0,0:19:10.38,0:19:12.41,Default,,0,0,0,,就像我们在这里用'CLOSURE\nDialogue: 0,0:19:12.68,0:19:15.05,Default,,0,0,0,,来描述一些复合对象一样\nDialogue: 0,0:19:16.33,0:19:17.79,Default,,0,0,0,,我想可能是这样\nDialogue: 0,0:19:18.55,0:19:20.20,Default,,0,0,0,,但是具体怎么判断并不重要\nDialogue: 0,0:19:20.68,0:19:22.01,Default,,0,0,0,,事实上\nDialogue: 0,0:19:22.19,0:19:23.85,Default,,0,0,0,,你可能已经知道或者推断过\nDialogue: 0,0:19:23.87,0:19:25.47,Default,,0,0,0,,我们并不需要任何基本过程\nDialogue: 0,0:19:27.35,0:19:29.28,Default,,0,0,0,,就算没有它们 照样可以进行计算\nDialogue: 0,0:19:30.46,0:19:33.19,Default,,0,0,0,,因为我们可以用一直在用的LAMBDA\nDialogue: 0,0:19:33.61,0:19:34.76,Default,,0,0,0,,但是有它们总归方便点儿\nDialogue: 0,0:19:34.81,0:19:36.27,Default,,0,0,0,,我在这儿略施魔法\nDialogue: 0,0:19:36.30,0:19:37.47,Default,,0,0,0,,但不会去解释\nDialogue: 0,0:19:38.06,0:19:41.44,Default,,0,0,0,,转到机器语言 执行APPLY-PRIMOP\nDialogue: 0,0:19:42.91,0:19:43.80,Default,,0,0,0,,加法是在这里运算的\nDialogue: 0,0:19:44.78,0:19:46.10,Default,,0,0,0,,执行加法指令\nDialogue: 0,0:19:50.62,0:19:52.11,Default,,0,0,0,,然而一门语言有趣的部分\nDialogue: 0,0:19:52.14,0:19:54.27,Default,,0,0,0,,在于组合基本元素的粘合剂\nDialogue: 0,0:19:54.91,0:19:55.90,Default,,0,0,0,,我们接着往下看\nDialogue: 0,0:19:56.91,0:19:58.38,Default,,0,0,0,,另一种可能就是\nDialogue: 0,0:19:58.75,0:20:04.12,Default,,0,0,0,,这个复合对象是求值LAMBDA表达式得到的\nDialogue: 0,0:20:04.97,0:20:07.05,Default,,0,0,0,,这是个复合过程\nDialogue: 0,0:20:07.62,0:20:09.36,Default,,0,0,0,,检测它的类型标志\nDialogue: 0,0:20:10.11,0:20:17.07,Default,,0,0,0,,如果是'CLOSURE\nDialogue: 0,0:20:20.51,0:20:24.09,Default,,0,0,0,,如果是的话 我就得求值这个过程的体\nDialogue: 0,0:20:24.19,0:20:27.39,Default,,0,0,0,,过程的体的求值方式则是\nDialogue: 0,0:20:28.08,0:20:31.69,Default,,0,0,0,,我求值过程的应用是通过\nDialogue: 0,0:20:31.72,0:20:33.71,Default,,0,0,0,,先扩充程序的求值环境\nDialogue: 0,0:20:34.19,0:20:37.80,Default,,0,0,0,,在这个环境中 把过程的形式参数\nDialogue: 0,0:20:37.92,0:20:40.48,Default,,0,0,0,,跟传递过来的实际参数绑定在一起\nDialogue: 0,0:20:41.02,0:20:43.68,Default,,0,0,0,,在这个环境中求值过程的体\nDialogue: 0,0:20:46.70,0:20:47.87,Default,,0,0,0,,这句话很长\nDialogue: 0,0:20:51.13,0:20:52.16,Default,,0,0,0,,但其实简单\nDialogue: 0,0:20:52.82,0:20:54.48,Default,,0,0,0,,一会儿可能会出现许多CAR CDR...\nDialogue: 0,0:20:56.46,0:20:58.11,Default,,0,0,0,,现在我先要得到过程体\nDialogue: 0,0:20:59.40,0:21:02.30,Default,,0,0,0,,如何取出过程体呢？\nDialogue: 0,0:21:02.96,0:21:04.08,Default,,0,0,0,,这里是CAR部分\nDialogue: 0,0:21:04.49,0:21:06.13,Default,,0,0,0,,这一块是剩下部分的CDR部分\nDialogue: 0,0:21:06.13,0:21:06.96,Default,,0,0,0,,因此这就是CADR\nDialogue: 0,0:21:07.40,0:21:09.45,Default,,0,0,0,,所以这里我得到的过程体\nDialogue: 0,0:21:09.45,0:21:13.04,Default,,0,0,0,,是过程对象第二个元素的第二个元素\nDialogue: 0,0:21:13.20,0:21:15.15,Default,,0,0,0,,因此CADR的CADR 也就是CADADR\nDialogue: 0,0:21:19.17,0:21:27.68,Default,,0,0,0,,这里取过程对象的CADADR部分\nDialogue: 0,0:21:30.26,0:21:31.56,Default,,0,0,0,,为了求值过程体\nDialogue: 0,0:21:31.98,0:21:36.48,Default,,0,0,0,,要在参数绑定后的新环境之中进行\nDialogue: 0,0:21:38.09,0:21:42.06,Default,,0,0,0,,我还得获取过程的形式参数\nDialogue: 0,0:21:42.06,0:21:42.72,Default,,0,0,0,,要怎么取呢？\nDialogue: 0,0:21:43.50,0:21:45.13,Default,,0,0,0,,就是CADR部分的CAR部分\nDialogue: 0,0:21:46.52,0:21:48.78,Default,,0,0,0,,这很糟糕不是吗？\nDialogue: 0,0:21:52.65,0:21:53.63,Default,,0,0,0,,过程的CADR部分\nDialogue: 0,0:21:55.44,0:22:00.86,Default,,0,0,0,,在随着过程一起传递过来的环境中\nDialogue: 0,0:22:00.89,0:22:04.14,Default,,0,0,0,,把形参和由环境传递过来的实参绑定起来\nDialogue: 0,0:22:04.54,0:22:07.90,Default,,0,0,0,,也就是CDR的CDR的CAR\nDialogue: 0,0:22:09.79,0:22:16.62,Default,,0,0,0,,也就是过程的CADDR部分\nDialogue: 0,0:22:20.29,0:22:24.96,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:22:26.14,0:22:29.68,Default,,0,0,0,,当然 如果我非常追求整洁\nDialogue: 0,0:22:29.87,0:22:31.34,Default,,0,0,0,,并且又非常谨慎\nDialogue: 0,0:22:32.24,0:22:34.12,Default,,0,0,0,,我会在后面多加一个情况\nDialogue: 0,0:22:34.38,0:22:35.98,Default,,0,0,0,,来判断是否出错\nDialogue: 0,0:22:36.17,0:22:38.41,Default,,0,0,0,,比如应用在参数上的是一个过程吗？\nDialogue: 0,0:22:39.00,0:22:41.69,Default,,0,0,0,,如果不是 这里就是未定义的过程类型\nDialogue: 0,0:22:42.57,0:22:44.09,Default,,0,0,0,,我在这里也会这么做\nDialogue: 0,0:22:45.80,0:22:55.96,Default,,0,0,0,,像这样 在ELSE子句中返回错误\nDialogue: 0,0:22:57.61,0:23:01.61,Default,,0,0,0,,当然 在现实中的一些系统中\nDialogue: 0,0:23:02.56,0:23:04.22,Default,,0,0,0,,出于专业设计的考虑\nDialogue: 0,0:23:05.32,0:23:08.00,Default,,0,0,0,,这里可能会根据某种分派\nDialogue: 0,0:23:08.36,0:23:09.90,Default,,0,0,0,,来进行“分情况处理”\nDialogue: 0,0:23:10.75,0:23:12.68,Default,,0,0,0,,回到这里 我可能还会添加新的条件来检查\nDialogue: 0,0:23:12.70,0:23:14.14,Default,,0,0,0,,比如 这是编译过的代码吗？\nDialogue: 0,0:23:16.22,0:23:16.84,Default,,0,0,0,,这很重要\nDialogue: 0,0:23:16.88,0:23:18.35,Default,,0,0,0,,这样的话我就可以区分\nDialogue: 0,0:23:18.38,0:23:22.33,Default,,0,0,0,,过程是直接由解释LAMBDA表达式而来\nDialogue: 0,0:23:22.94,0:23:25.87,Default,,0,0,0,,还是从另外的编译器中得到的 等等\nDialogue: 0,0:23:26.11,0:23:27.23,Default,,0,0,0,,之后再讨论这个话题\nDialogue: 0,0:23:27.23,0:23:29.61,Default,,0,0,0,,又或许是 我必须要执行的一段Frotran代码\nDialogue: 0,0:23:30.51,0:23:32.51,Default,,0,0,0,,这完全是可能的\nDialogue: 0,0:23:32.92,0:23:36.41,Default,,0,0,0,,实际上 我用具体语法写的这个求值器\nDialogue: 0,0:23:37.45,0:23:40.86,Default,,0,0,0,,假定了它是用Lisp来编写的\nDialogue: 0,0:23:42.30,0:23:43.82,Default,,0,0,0,,这是因为我用了CAR和CDR\nDialogue: 0,0:23:43.84,0:23:45.10,Default,,0,0,0,,用CAR来取运算符\nDialogue: 0,0:23:45.28,0:23:46.64,Default,,0,0,0,,用CDR来取运算对象\nDialogue: 0,0:23:46.75,0:23:49.96,Default,,0,0,0,,教科书上给出了一个用抽象语法编写的求值器\nDialogue: 0,0:23:50.35,0:23:53.15,Default,,0,0,0,,它使用的都是抽象的名字\nDialogue: 0,0:23:53.16,0:23:54.09,Default,,0,0,0,,比如OPERATOR、OPERAND\nDialogue: 0,0:23:54.14,0:23:55.82,Default,,0,0,0,,以及类似的名字\nDialogue: 0,0:23:56.16,0:23:56.86,Default,,0,0,0,,那样的话\nDialogue: 0,0:23:57.02,0:24:00.91,Default,,0,0,0,,你可以毫无问题地用ALGOL来重新实现\nDialogue: 0,0:24:03.36,0:24:06.40,Default,,0,0,0,,写完APPLY之后\nDialogue: 0,0:24:07.20,0:24:08.43,Default,,0,0,0,,又有一些东西没有定义\nDialogue: 0,0:24:10.81,0:24:12.57,Default,,0,0,0,,我先不操心这两个\nDialogue: 0,0:24:13.39,0:24:15.05,Default,,0,0,0,,我们稍后讨论这个很重要的BIND\nDialogue: 0,0:24:17.18,0:24:19.76,Default,,0,0,0,,现在我们来快速过一遍 结束这一部分\nDialogue: 0,0:24:20.55,0:24:22.65,Default,,0,0,0,,只剩下两块黑板了 不能够写太长\nDialogue: 0,0:24:27.40,0:24:29.08,Default,,0,0,0,,我还得悉心裁剪才能刚好写下\nDialogue: 0,0:24:30.07,0:24:30.98,Default,,0,0,0,,嗯 还剩下点什么？\nDialogue: 0,0:24:30.98,0:24:33.20,Default,,0,0,0,,我们得定义这里的EVLIST\nDialogue: 0,0:24:33.73,0:24:35.07,Default,,0,0,0,,EVLIST只不过是\nDialogue: 0,0:24:35.26,0:24:43.08,Default,,0,0,0,,在运算对象上映射某个函数得到参数\nDialogue: 0,0:24:44.30,0:24:45.40,Default,,0,0,0,,但是我还是要写出来看看\nDialogue: 0,0:24:45.82,0:24:48.30,Default,,0,0,0,,我把它写出来的原因有点神秘\nDialogue: 0,0:24:49.88,0:24:52.04,Default,,0,0,0,,我想让这个求值器简单得\nDialogue: 0,0:24:52.06,0:24:53.56,Default,,0,0,0,,可以求值自身\nDialogue: 0,0:24:56.45,0:24:58.09,Default,,0,0,0,,我真的很在意这一点\nDialogue: 0,0:25:00.23,0:25:01.74,Default,,0,0,0,,现在我就把它完全写在这里\nDialogue: 0,0:25:02.85,0:25:04.24,Default,,0,0,0,,我并不关心\nDialogue: 0,0:25:04.27,0:25:06.08,Default,,0,0,0,,它能否把过程作为参数传递\nDialogue: 0,0:25:06.27,0:25:08.06,Default,,0,0,0,,求值器并不会用到这些参数\nDialogue: 0,0:25:08.98,0:25:10.78,Default,,0,0,0,,求值器也不会生成一个是过程的值\nDialogue: 0,0:25:10.88,0:25:12.67,Default,,0,0,0,,因此 如果另外有个不同的语言\nDialogue: 0,0:25:12.80,0:25:13.96,Default,,0,0,0,,跟这个又非常相似\nDialogue: 0,0:25:15.16,0:25:17.79,Default,,0,0,0,,这个求值器能够求值像Scheme这样的复杂语言\nDialogue: 0,0:25:17.80,0:25:23.12,Default,,0,0,0,,Scheme是能够把过程当做参数传递的\nDialogue: 0,0:25:24.07,0:25:25.95,Default,,0,0,0,,但当我在求值ALGOL时\nDialogue: 0,0:25:27.34,0:25:28.96,Default,,0,0,0,,尽管ALGOL并不支持过程值\nDialogue: 0,0:25:29.47,0:25:30.59,Default,,0,0,0,,这个求值器也能正常工作\nDialogue: 0,0:25:31.58,0:25:33.92,Default,,0,0,0,,因为这个解释器 并没有对这个做过什么假定\nDialogue: 0,0:25:34.27,0:25:36.03,Default,,0,0,0,,实际上 就算这个求值器\nDialogue: 0,0:25:36.27,0:25:37.50,Default,,0,0,0,,被限制不允许那么做 也没有什么关系\nDialogue: 0,0:25:37.52,0:25:40.03,Default,,0,0,0,,因为它没有使用那些高级功能\nDialogue: 0,0:25:40.64,0:25:42.41,Default,,0,0,0,,这就是我为什么要把它设计得非常简单\nDialogue: 0,0:25:44.07,0:25:46.46,Default,,0,0,0,,这几乎是所有可能的语言求值器的核心\nDialogue: 0,0:25:47.81,0:25:48.48,Default,,0,0,0,,回到这个定义上来\nDialogue: 0,0:25:49.42,0:25:53.56,Default,,0,0,0,,EVLIST -- 它是什么呢？\nDialogue: 0,0:25:53.82,0:25:57.04,Default,,0,0,0,,这个过程接收两个参数 L和ENV\nDialogue: 0,0:25:58.09,0:25:59.08,Default,,0,0,0,,其中L是个表\nDialogue: 0,0:25:59.58,0:26:08.27,Default,,0,0,0,,这样的话 如果参数表是空表\nDialogue: 0,0:26:10.19,0:26:12.68,Default,,0,0,0,,那么结果就是空表\nDialogue: 0,0:26:14.03,0:26:19.23,Default,,0,0,0,,否则的话 我就要组合\nDialogue: 0,0:26:20.75,0:26:26.67,Default,,0,0,0,,在ENV中求值运算对象表的CAR部分\nDialogue: 0,0:26:28.16,0:26:32.51,Default,,0,0,0,,在ENV中求值运算对象CAR部分的结果\nDialogue: 0,0:26:33.34,0:26:35.71,Default,,0,0,0,,我想先求值第一个运算对象\nDialogue: 0,0:26:35.98,0:26:38.40,Default,,0,0,0,,返回的结果将是一个新表\nDialogue: 0,0:26:38.97,0:26:40.76,Default,,0,0,0,,是通过把这个和\nDialogue: 0,0:26:41.08,0:26:45.42,Default,,0,0,0,,用CDR递归EVLIST的结果组合得到的\nDialogue: 0,0:26:46.22,0:26:50.13,Default,,0,0,0,,在同样的ENV下 L的CDR部分\nDialogue: 0,0:26:53.08,0:26:58.24,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:26:59.66,0:27:01.84,Default,,0,0,0,,还有一个过程\nDialogue: 0,0:27:01.84,0:27:03.36,Default,,0,0,0,,我也想写在这里\nDialogue: 0,0:27:03.62,0:27:05.21,Default,,0,0,0,,它是这整个的关键\nDialogue: 0,0:27:05.64,0:27:08.13,Default,,0,0,0,,还要深入一个层次\nDialogue: 0,0:27:14.54,0:27:15.44,Default,,0,0,0,,也就是COND语句\nDialogue: 0,0:27:15.69,0:27:16.99,Default,,0,0,0,,在剩下的东西中\nDialogue: 0,0:27:17.02,0:27:18.17,Default,,0,0,0,,EVCOND是唯一的重要过程\nDialogue: 0,0:27:18.88,0:27:20.75,Default,,0,0,0,,解决完这个后\nDialogue: 0,0:27:21.07,0:27:22.94,Default,,0,0,0,,我们再讨论LOOKUP和BIND\nDialogue: 0,0:27:23.56,0:27:25.36,Default,,0,0,0,,稍后再来讨论\nDialogue: 0,0:27:25.53,0:27:27.93,Default,,0,0,0,,在这个层次上 这是非常重要的\nDialogue: 0,0:27:28.65,0:27:30.62,Default,,0,0,0,,下一个重要的事就是如何处理COND语句\nDialogue: 0,0:27:31.60,0:27:33.33,Default,,0,0,0,,那么 我们怎么来处理呢？\nDialogue: 0,0:27:36.97,0:27:38.56,Default,,0,0,0,,它是一个过程\nDialogue: 0,0:27:39.48,0:27:45.00,Default,,0,0,0,,参数是一组子句CLAUSES和环境ENV\nDialogue: 0,0:27:47.71,0:27:48.51,Default,,0,0,0,,它做些什么呢？\nDialogue: 0,0:27:49.82,0:27:55.47,Default,,0,0,0,,如果子句为空\nDialogue: 0,0:28:02.60,0:28:03.96,Default,,0,0,0,,我得有一个返回值\nDialogue: 0,0:28:04.70,0:28:05.87,Default,,0,0,0,,可能是一个错误\nDialogue: 0,0:28:06.54,0:28:08.59,Default,,0,0,0,,如果遍历完了所有条件 都没有符合的\nDialogue: 0,0:28:09.15,0:28:10.06,Default,,0,0,0,,那么它可能有任意的行为\nDialogue: 0,0:28:10.06,0:28:12.88,Default,,0,0,0,,这完全取决于程序员要怎么处理\nDialogue: 0,0:28:13.65,0:28:15.45,Default,,0,0,0,,现在对我来说最方便的是\nDialogue: 0,0:28:15.63,0:28:17.53,Default,,0,0,0,,让它返回一个空表\nDialogue: 0,0:28:18.14,0:28:18.83,Default,,0,0,0,,这无所谓\nDialogue: 0,0:28:20.10,0:28:20.88,Default,,0,0,0,,为了检查出错误\nDialogue: 0,0:28:20.89,0:28:22.76,Default,,0,0,0,,有些人喜欢在这里写点别的\nDialogue: 0,0:28:23.11,0:28:24.81,Default,,0,0,0,,下面的更有意思\nDialogue: 0,0:28:25.39,0:28:27.24,Default,,0,0,0,,如果我遇到了ELSE子句\nDialogue: 0,0:28:31.00,0:28:32.73,Default,,0,0,0,,请看 我们有一个由子句组成的表\nDialogue: 0,0:28:33.21,0:28:34.41,Default,,0,0,0,,其中每个子句也是一个表\nDialogue: 0,0:28:35.44,0:28:40.52,Default,,0,0,0,,因此谓词就应该是CLAUSES的CAAR部分\nDialogue: 0,0:28:43.56,0:28:45.02,Default,,0,0,0,,它是\nDialogue: 0,0:28:45.04,0:28:49.00,Default,,0,0,0,,CLAUSES表中第一个元素的CAR部分\nDialogue: 0,0:28:51.09,0:28:51.84,Default,,0,0,0,,如果它是'ELSE的话\nDialogue: 0,0:28:54.32,0:28:56.51,Default,,0,0,0,,就意味着整个COND表达式的结果\nDialogue: 0,0:28:56.64,0:28:59.15,Default,,0,0,0,,就是求值匹配表达式的结果\nDialogue: 0,0:29:00.12,0:29:04.32,Default,,0,0,0,,所以我求值CADAR部分\nDialogue: 0,0:29:07.00,0:29:09.56,Default,,0,0,0,,这是第一个子句的\nDialogue: 0,0:29:10.12,0:29:11.63,Default,,0,0,0,,第二个元素 也就是CADAR\nDialogue: 0,0:29:12.81,0:29:17.08,Default,,0,0,0,,也就是CLAUSES的CAR部分的CADR部分\nDialogue: 0,0:29:21.23,0:29:22.57,Default,,0,0,0,,求值的环境是ENV\nDialogue: 0,0:29:26.62,0:29:28.60,Default,,0,0,0,,下一种可能性更有意思\nDialogue: 0,0:29:29.63,0:29:30.44,Default,,0,0,0,,如果它返回FALSE的话\nDialogue: 0,0:29:33.05,0:29:35.10,Default,,0,0,0,,如果谓词表中的第一个谓词\nDialogue: 0,0:29:35.74,0:29:37.68,Default,,0,0,0,,既不是ELSE子句 又不为FALSE\nDialogue: 0,0:29:38.32,0:29:39.50,Default,,0,0,0,,也就是它不是保留字ELSE\nDialogue: 0,0:29:40.16,0:29:42.00,Default,,0,0,0,,并且也不是一个值为FALSE的东西\nDialogue: 0,0:29:42.03,0:29:43.66,Default,,0,0,0,,如果为FALSE又要怎么处理呢？\nDialogue: 0,0:29:44.36,0:29:50.08,Default,,0,0,0,,如果在相应的环境中\nDialogue: 0,0:29:52.33,0:29:56.76,Default,,0,0,0,,求值子句中第一个谓词的结果\nDialogue: 0,0:29:58.19,0:30:01.00,Default,,0,0,0,,如果求值的结果是FALSE的话\nDialogue: 0,0:30:01.69,0:30:03.82,Default,,0,0,0,,这就意味着 还得接着判断后面的子句\nDialogue: 0,0:30:04.36,0:30:05.74,Default,,0,0,0,,第一个就扔掉不管了\nDialogue: 0,0:30:06.25,0:30:08.33,Default,,0,0,0,,所以就进入下一个EVCOND循环\nDialogue: 0,0:30:09.95,0:30:16.49,Default,,0,0,0,,在对应的环境中继续判断子句的CDR部分\nDialogue: 0,0:30:19.95,0:30:25.15,Default,,0,0,0,,又或者 我遇到了求值为TRUE的子句\nDialogue: 0,0:30:26.84,0:30:28.96,Default,,0,0,0,,这样的话 我想在对应的环境中\nDialogue: 0,0:30:31.85,0:30:41.45,Default,,0,0,0,,求值CLAUSES的CADAR部分\nDialogue: 0,0:30:48.20,0:30:49.61,Default,,0,0,0,,快了 快完成了\nDialogue: 0,0:30:51.21,0:30:52.80,Default,,0,0,0,,基本上完整了\nDialogue: 0,0:30:53.73,0:30:55.87,Default,,0,0,0,,把这一部分结束\nDialogue: 0,0:30:56.21,0:30:58.57,Default,,0,0,0,,再回顾一下这个求值器\nDialogue: 0,0:30:58.81,0:31:00.70,Default,,0,0,0,,它基本上就是这样了\nDialogue: 0,0:31:01.08,0:31:04.04,Default,,0,0,0,,接着来看一张幻灯片\nDialogue: 0,0:31:06.32,0:31:10.43,Default,,0,0,0,,这是BIND的定义\nDialogue: 0,0:31:11.98,0:31:14.54,Default,,0,0,0,,BIND用于在环境中添加新的绑定\nDialogue: 0,0:31:15.46,0:31:18.67,Default,,0,0,0,,我们要在这里\nDialogue: 0,0:31:19.24,0:31:22.80,Default,,0,0,0,,为环境结构创建一个新框架\nDialogue: 0,0:31:22.80,0:31:25.42,Default,,0,0,0,,环境结构是通过由框架组成的表\nDialogue: 0,0:31:25.93,0:31:27.20,Default,,0,0,0,,来表示的\nDialogue: 0,0:31:28.08,0:31:30.19,Default,,0,0,0,,给定一个已有的环境\nDialogue: 0,0:31:30.32,0:31:32.11,Default,,0,0,0,,我可以通过把一个新建的框架\nDialogue: 0,0:31:32.25,0:31:33.82,Default,,0,0,0,,CONS在已有的环境上\nDialogue: 0,0:31:33.93,0:31:35.69,Default,,0,0,0,,来获得新的环境\nDialogue: 0,0:31:36.62,0:31:40.36,Default,,0,0,0,,正在应用的过程中 那些被绑定变量\nDialogue: 0,0:31:41.05,0:31:43.79,Default,,0,0,0,,与传递给过程的参数值结合在一起\nDialogue: 0,0:31:44.12,0:31:48.25,Default,,0,0,0,,组成了我们所创建的新框架\nDialogue: 0,0:31:49.69,0:31:50.65,Default,,0,0,0,,BIND其实就是创建表\nDialogue: 0,0:31:51.64,0:31:54.06,Default,,0,0,0,,环境就是一组由框架组成的表\nDialogue: 0,0:31:54.30,0:31:55.60,Default,,0,0,0,,把新的元素加入其中\nDialogue: 0,0:31:55.74,0:31:56.89,Default,,0,0,0,,也就形成了新的环境\nDialogue: 0,0:31:58.65,0:32:00.65,Default,,0,0,0,,而PAIR-UP的定义非常简单\nDialogue: 0,0:32:01.54,0:32:02.84,Default,,0,0,0,,PAIR-UP只不过是\nDialogue: 0,0:32:03.13,0:32:05.56,Default,,0,0,0,,如果我们有一个变量表和一个值表\nDialogue: 0,0:32:05.93,0:32:08.62,Default,,0,0,0,,那么 如果它俩的元素个数又相同\nDialogue: 0,0:32:08.62,0:32:09.58,Default,,0,0,0,,就可以让它们一一对应\nDialogue: 0,0:32:09.72,0:32:11.48,Default,,0,0,0,,否则的话 就是参数传递多了\nDialogue: 0,0:32:12.51,0:32:15.98,Default,,0,0,0,,如果值的个数比变量的个数多\nDialogue: 0,0:32:16.06,0:32:17.37,Default,,0,0,0,,那就说明参数传递少了\nDialogue: 0,0:32:18.51,0:32:19.63,Default,,0,0,0,,通常的情况是\nDialogue: 0,0:32:19.63,0:32:21.48,Default,,0,0,0,,如果没有出错 又没有完成的话\nDialogue: 0,0:32:22.06,0:32:25.61,Default,,0,0,0,,我就添加一个由第一个变量\nDialogue: 0,0:32:25.76,0:32:30.17,Default,,0,0,0,,和第一个参数组成的新序对\nDialogue: 0,0:32:30.94,0:32:32.12,Default,,0,0,0,,这是第一个值\nDialogue: 0,0:32:32.76,0:32:36.40,Default,,0,0,0,,把它们CONS在\nDialogue: 0,0:32:37.12,0:32:40.64,Default,,0,0,0,,剩余变量和值组成的表上\nDialogue: 0,0:32:42.95,0:32:44.78,Default,,0,0,0,,LOOKUP也同样简单\nDialogue: 0,0:32:46.28,0:32:49.63,Default,,0,0,0,,加入我要在环境中查找一个符号\nDialogue: 0,0:32:49.93,0:32:51.39,Default,,0,0,0,,那么 如果是空环境\nDialogue: 0,0:32:51.56,0:32:53.00,Default,,0,0,0,,那么就说明 该变量尚未绑定\nDialogue: 0,0:32:54.65,0:32:55.47,Default,,0,0,0,,否则\nDialogue: 0,0:32:56.86,0:33:00.36,Default,,0,0,0,,我就要使用一个特殊的关联表查找过程\nDialogue: 0,0:33:00.38,0:33:01.87,Default,,0,0,0,,我们不久就会看到它的定义\nDialogue: 0,0:33:02.24,0:33:05.44,Default,,0,0,0,,用它在环境的第一个框架中查找该符号\nDialogue: 0,0:33:05.93,0:33:07.21,Default,,0,0,0,,由于我知道这个环境不是空的\nDialogue: 0,0:33:07.23,0:33:08.40,Default,,0,0,0,,因此 它至少有一个框架\nDialogue: 0,0:33:09.20,0:33:11.14,Default,,0,0,0,,所以 我就在它第一个框架中查找\nDialogue: 0,0:33:11.56,0:33:13.58,Default,,0,0,0,,找到的序对会传递给这里的VCELL\nDialogue: 0,0:33:14.38,0:33:17.61,Default,,0,0,0,,如果VCELL为空\nDialogue: 0,0:33:18.44,0:33:20.57,Default,,0,0,0,,那就说明当前框架中没有这个符号\nDialogue: 0,0:33:20.70,0:33:22.84,Default,,0,0,0,,我就需要在环境中剩下的框架中查找\nDialogue: 0,0:33:23.72,0:33:25.04,Default,,0,0,0,,VCELL为空 意味着当前框架没有相应的符号\nDialogue: 0,0:33:25.99,0:33:28.89,Default,,0,0,0,,如果没有找到\nDialogue: 0,0:33:29.52,0:33:30.80,Default,,0,0,0,,ASSQ就会返回空表\nDialogue: 0,0:33:32.32,0:33:33.85,Default,,0,0,0,,如果找到了\nDialogue: 0,0:33:33.85,0:33:36.06,Default,,0,0,0,,那么我就使用VCELL的CDR部分\nDialogue: 0,0:33:36.46,0:33:40.25,Default,,0,0,0,,因为VCELL是变量和值组成的序对\nDialogue: 0,0:33:41.05,0:33:43.93,Default,,0,0,0,,因此可以用CDR取得对应的值\nDialogue: 0,0:33:45.00,0:33:47.82,Default,,0,0,0,,ASSQ这个过程你们之前见过\nDialogue: 0,0:33:47.97,0:33:50.83,Default,,0,0,0,,ASSQ的参数是一个符号和一个由序对组成的表\nDialogue: 0,0:33:51.42,0:33:53.40,Default,,0,0,0,,如果表为空 它就返回空表\nDialogue: 0,0:33:53.52,0:33:56.30,Default,,0,0,0,,如果这个符号是ALIST的第一个元素\nDialogue: 0,0:33:58.06,0:33:58.91,Default,,0,0,0,,这里写错了\nDialogue: 0,0:33:59.82,0:34:02.17,Default,,0,0,0,,应该是CAAR\nDialogue: 0,0:34:03.16,0:34:04.16,Default,,0,0,0,,大家注意一下\nDialogue: 0,0:34:07.63,0:34:09.37,Default,,0,0,0,,就是这里 看到了吗？\nDialogue: 0,0:34:13.42,0:34:14.41,Default,,0,0,0,,总之\nDialogue: 0,0:34:14.56,0:34:16.81,Default,,0,0,0,,如果符号等于表的CAAR\nDialogue: 0,0:34:17.16,0:34:20.97,Default,,0,0,0,,那么我就返回ALIST中第一个序对\nDialogue: 0,0:34:22.08,0:34:25.50,Default,,0,0,0,,换句话说 这个键匹配了正确的条目\nDialogue: 0,0:34:26.24,0:34:26.97,Default,,0,0,0,,否则的话\nDialogue: 0,0:34:27.08,0:34:28.94,Default,,0,0,0,,我就需要在剩下的表中继续查找\nDialogue: 0,0:34:30.08,0:34:33.31,Default,,0,0,0,,这里有个笔误 很抱歉\nDialogue: 0,0:34:35.19,0:34:36.28,Default,,0,0,0,,好了 不管如何\nDialogue: 0,0:34:37.05,0:34:39.48,Default,,0,0,0,,你们基本上已经看到了全貌\nDialogue: 0,0:34:41.88,0:34:43.29,Default,,0,0,0,,虽然我们的代码风格非常丑陋\nDialogue: 0,0:34:44.19,0:34:46.00,Default,,0,0,0,,但是作为所有语言的核心\nDialogue: 0,0:34:46.76,0:34:48.30,Default,,0,0,0,,它却是非常美妙\nDialogue: 0,0:34:49.60,0:34:51.37,Default,,0,0,0,,我提议 让我们再欣赏一会儿\nDialogue: 0,0:35:00.32,0:35:47.02,Default,,0,0,0,,[音乐]\nDialogue: 0,0:35:49.75,0:35:50.91,Default,,0,0,0,,大家有什么问题吗？\nDialogue: 0,0:36:01.18,0:36:03.29,Default,,0,0,0,,没有的话就休息一会儿吧\nDialogue: 0,0:36:04.04,0:36:10.73,Default,,0,0,0,,[音乐]\nDialogue: 0,0:36:13.88,0:36:17.64,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:36:40.80,0:36:43.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:36:43.95,0:36:47.98,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:36:48.06,0:36:51.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 I\nDialogue: 0,0:36:56.78,0:36:58.99,Default,,0,0,0,,现在 我们将用一个实例\nDialogue: 0,0:36:59.29,0:37:02.67,Default,,0,0,0,,来理解一下求值器的运作过程\nDialogue: 0,0:37:03.47,0:37:05.48,Default,,0,0,0,,我们通过手工进行代换\nDialogue: 0,0:37:05.50,0:37:10.36,Default,,0,0,0,,来深入解释器的详细工作原理\nDialogue: 0,0:37:11.50,0:37:14.94,Default,,0,0,0,,由于我们的求值器不支持赋值和定义\nDialogue: 0,0:37:15.20,0:37:17.34,Default,,0,0,0,,我们也就不用担心副作用\nDialogue: 0,0:37:17.98,0:37:22.03,Default,,0,0,0,,因此我们可以放心大胆地进行代换\nDialogue: 0,0:37:22.52,0:37:24.59,Default,,0,0,0,,不用担心任何副作用\nDialogue: 0,0:37:25.33,0:37:27.80,Default,,0,0,0,,我们将要尝试去手工代换\nDialogue: 0,0:37:28.06,0:37:29.63,Default,,0,0,0,,这个复杂的表达式\nDialogue: 0,0:37:30.69,0:37:34.09,Default,,0,0,0,,(EVAL\nDialogue: 0,0:37:34.91,0:37:48.08,Default,,0,0,0,,'(((LAMBDA (X) (LAMBDA (Y) (+ X Y)))\nDialogue: 0,0:37:50.30,0:37:52.62,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:37:53.04,0:37:56.12,Default,,0,0,0,,要把它应用在3和4上\nDialogue: 0,0:37:56.94,0:37:59.58,Default,,0,0,0,,求值过程是发生在全局环境E0中的\nDialogue: 0,0:38:04.93,0:38:05.96,Default,,0,0,0,,这里的这个表达式\nDialogue: 0,0:38:06.36,0:38:08.04,Default,,0,0,0,,是个参数为X的一元过程\nDialogue: 0,0:38:08.09,0:38:11.05,Default,,0,0,0,,返回一个参数为Y的一元过程\nDialogue: 0,0:38:11.07,0:38:12.12,Default,,0,0,0,,后者计算X+Y\nDialogue: 0,0:38:14.30,0:38:17.96,Default,,0,0,0,,外层的这个过程应用于数字3\nDialogue: 0,0:38:17.96,0:38:19.39,Default,,0,0,0,,所以X应该是3\nDialogue: 0,0:38:21.40,0:38:23.98,Default,,0,0,0,,返回的结果是一个参数为Y的一元过程\nDialogue: 0,0:38:24.33,0:38:25.82,Default,,0,0,0,,该过程将应用于数字4\nDialogue: 0,0:38:28.91,0:38:30.32,Default,,0,0,0,,然后要做的也很简单\nDialogue: 0,0:38:31.04,0:38:32.73,Default,,0,0,0,,计算X+Y即可\nDialogue: 0,0:38:34.79,0:38:35.82,Default,,0,0,0,,具体做之前\nDialogue: 0,0:38:35.84,0:38:37.76,Default,,0,0,0,,先来构造一个非常简单的环境模型\nDialogue: 0,0:38:37.90,0:38:40.48,Default,,0,0,0,,到了现在 我相信你们已经想到\nDialogue: 0,0:38:40.99,0:38:42.59,Default,,0,0,0,,这个过程产生的环境了\nDialogue: 0,0:38:44.46,0:38:46.62,Default,,0,0,0,,我们从全局环境开始\nDialogue: 0,0:38:48.59,0:38:50.06,Default,,0,0,0,,我们把它记作E0\nDialogue: 0,0:38:54.60,0:38:55.47,Default,,0,0,0,,就像这样\nDialogue: 0,0:38:56.74,0:39:02.46,Default,,0,0,0,,里面应该有过程+、*的定义\nDialogue: 0,0:39:06.30,0:39:10.36,Default,,0,0,0,,这里 我们用希腊字母来表示过程对象 这样有趣点\nDialogue: 0,0:39:11.21,0:39:27.93,Default,,0,0,0,,-、/、CAR、CDR、CONS以及EQ?\nDialogue: 0,0:39:28.59,0:39:31.05,Default,,0,0,0,,其它需要的基本过程都在全局环境中\nDialogue: 0,0:39:31.27,0:39:33.82,Default,,0,0,0,,每个符号都对应着一个过程对象\nDialogue: 0,0:39:34.62,0:39:36.09,Default,,0,0,0,,这些都是解释器自带的\nDialogue: 0,0:39:37.10,0:39:38.09,Default,,0,0,0,,这就是E0\nDialogue: 0,0:39:39.22,0:39:41.84,Default,,0,0,0,,现在 这个求值要怎样进行呢？\nDialogue: 0,0:39:42.94,0:39:45.18,Default,,0,0,0,,我们来看看这些特殊形式\nDialogue: 0,0:39:45.69,0:39:47.05,Default,,0,0,0,,首先 这不是数字\nDialogue: 0,0:39:48.67,0:39:50.38,Default,,0,0,0,,也不是符号\nDialogue: 0,0:39:53.13,0:39:55.60,Default,,0,0,0,,这不是一个引用表达式\nDialogue: 0,0:39:56.60,0:39:58.38,Default,,0,0,0,,虽然外层是一个引用表达式\nDialogue: 0,0:39:59.47,0:40:00.80,Default,,0,0,0,,但并不是我想要去求值的那个\nDialogue: 0,0:40:00.83,0:40:01.36,Default,,0,0,0,,我想问的是\nDialogue: 0,0:40:01.39,0:40:04.96,Default,,0,0,0,,被引用的这个表达式 是否也是个引用表达式？\nDialogue: 0,0:40:05.89,0:40:07.96,Default,,0,0,0,,我是在求值一个表达式\nDialogue: 0,0:40:07.96,0:40:09.98,Default,,0,0,0,,这个引号是为了引用这个特定表达式\nDialogue: 0,0:40:11.41,0:40:12.66,Default,,0,0,0,,而被引用的并非引用表达式\nDialogue: 0,0:40:13.71,0:40:17.21,Default,,0,0,0,,当然 它也不是以LAMBDA开头\nDialogue: 0,0:40:19.12,0:40:20.67,Default,,0,0,0,,也不以COND开头\nDialogue: 0,0:40:22.03,0:40:25.95,Default,,0,0,0,,因此它是过程的应用\nDialogue: 0,0:40:26.31,0:40:27.12,Default,,0,0,0,,这是一个组合式\nDialogue: 0,0:40:28.57,0:40:30.70,Default,,0,0,0,,既然它是组合式\nDialogue: 0,0:40:30.89,0:40:34.00,Default,,0,0,0,,这就是它的运算符\nDialogue: 0,0:40:34.64,0:40:36.08,Default,,0,0,0,,而这是它的运算对象\nDialogue: 0,0:40:40.13,0:40:42.41,Default,,0,0,0,,这就意味着 我要\nDialogue: 0,0:40:42.57,0:40:47.90,Default,,0,0,0,,把它转换成\nDialogue: 0,0:40:50.12,0:40:57.61,Default,,0,0,0,,(APPLY (EVAL '((LAMBDA (X) (LAMBDA (y)\nDialogue: 0,0:40:57.88,0:40:59.12,Default,,0,0,0,,也就是在E0环境中\nDialogue: 0,0:40:59.95,0:41:04.19,Default,,0,0,0,,求值(+ X Y)\nDialogue: 0,0:41:07.26,0:41:08.64,Default,,0,0,0,,不要漏了<E0>\nDialogue: 0,0:41:12.78,0:41:15.20,Default,,0,0,0,,要应用到的运算对象则是\nDialogue: 0,0:41:15.26,0:41:17.28,Default,,0,0,0,,用EVLIST求值参数的结果\nDialogue: 0,0:41:21.21,0:41:24.49,Default,,0,0,0,,也就是'(4)\nDialogue: 0,0:41:29.01,0:41:31.26,Default,,0,0,0,,我用这个特殊的记号来表示<E0>\nDialogue: 0,0:41:32.32,0:41:34.83,Default,,0,0,0,,这是为了指代那个环境\nDialogue: 0,0:41:35.45,0:41:37.77,Default,,0,0,0,,我无法为它命名\nDialogue: 0,0:41:37.80,0:41:39.15,Default,,0,0,0,,因为我没有环境来存放<E0>的名字\nDialogue: 0,0:41:41.96,0:41:44.09,Default,,0,0,0,,你当然可以把<E0>看作是\nDialogue: 0,0:41:44.17,0:41:46.17,Default,,0,0,0,,某种引用表达式\nDialogue: 0,0:41:47.73,0:41:51.16,Default,,0,0,0,,在那里 它表示环境这种数据结构\nDialogue: 0,0:41:53.04,0:41:55.04,Default,,0,0,0,,好的 这是变换后的结果\nDialogue: 0,0:41:55.85,0:41:56.67,Default,,0,0,0,,为了执行这个表达式\nDialogue: 0,0:41:56.68,0:41:58.04,Default,,0,0,0,,我还得求值这两个表达式\nDialogue: 0,0:41:59.61,0:42:00.49,Default,,0,0,0,,EVLIST简单点\nDialogue: 0,0:42:00.57,0:42:03.18,Default,,0,0,0,,我们先计算这个吧\nDialogue: 0,0:42:03.77,0:42:07.44,Default,,0,0,0,,这就被归约为\nDialogue: 0,0:42:07.45,0:42:08.83,Default,,0,0,0,,上面的某些部分直接抄过来就好\nDialogue: 0,0:42:09.42,0:42:11.00,Default,,0,0,0,,代换的过程中少不了照抄\nDialogue: 0,0:42:18.53,0:42:21.24,Default,,0,0,0,,抄写的时候我就不多加解释了\nDialogue: 0,0:42:21.71,0:42:23.87,Default,,0,0,0,,这样能快一点儿\nDialogue: 0,0:42:26.41,0:42:28.64,Default,,0,0,0,,EVLIST的部分就代换成为\nDialogue: 0,0:42:28.65,0:42:36.72,Default,,0,0,0,,(CONS (EVAL '4 <E0>)\nDialogue: 0,0:42:38.78,0:42:40.17,Default,,0,0,0,,因为它不是空表\nDialogue: 0,0:42:41.44,0:42:49.39,Default,,0,0,0,,(EVLIST '() <E0>))\nDialogue: 0,0:42:52.58,0:42:54.20,Default,,0,0,0,,我要省略一些步骤了\nDialogue: 0,0:42:54.24,0:42:55.36,Default,,0,0,0,,因为太详细就有些无聊了\nDialogue: 0,0:42:59.87,0:43:05.42,Default,,0,0,0,,下一步跟上面基本上一样\nDialogue: 0,0:43:07.50,0:43:08.54,Default,,0,0,0,,继续照抄\nDialogue: 0,0:43:10.68,0:43:20.24,Default,,0,0,0,,(((LAMBDA (X) (LAMBDA (Y) (+ X Y)) 3) 4) <E0>)\nDialogue: 0,0:43:20.24,0:43:21.20,Default,,0,0,0,,看来我还宝刀未老嘛\nDialogue: 0,0:43:24.24,0:43:26.24,Default,,0,0,0,,下面对4求值\nDialogue: 0,0:43:26.56,0:43:28.44,Default,,0,0,0,,4是一个数字\nDialogue: 0,0:43:29.00,0:43:33.90,Default,,0,0,0,,结果就应该是(CONS 4\nDialogue: 0,0:43:34.03,0:43:37.47,Default,,0,0,0,,EVLIST对空表求值 结果也是空表\nDialogue: 0,0:43:38.33,0:43:39.24,Default,,0,0,0,,也就是这个\nDialogue: 0,0:43:42.62,0:43:45.08,Default,,0,0,0,,这个非常容易理解\nDialogue: 0,0:43:45.10,0:43:47.44,Default,,0,0,0,,就是一个只含有4的表\nDialogue: 0,0:43:48.71,0:43:53.84,Default,,0,0,0,,继续代换为 (APPLY (EVAL\nDialogue: 0,0:43:55.28,0:44:02.51,Default,,0,0,0,,'((LAMBDA (X) (LAMBDA (Y) (+ X Y))\nDialogue: 0,0:44:03.40,0:44:07.48,Default,,0,0,0,,3) 4) <E0>)\nDialogue: 0,0:44:08.68,0:44:12.60,Default,,0,0,0,,应用在'(4)上 这样就完成了\nDialogue: 0,0:44:13.94,0:44:15.05,Default,,0,0,0,,这是这一步的结果\nDialogue: 0,0:44:17.00,0:44:19.96,Default,,0,0,0,,现在让我们进行下一步 更有意思的一步\nDialogue: 0,0:44:20.36,0:44:21.72,Default,,0,0,0,,这行代码要如何求值？\nDialogue: 0,0:44:23.07,0:44:24.44,Default,,0,0,0,,为了求值这一部分\nDialogue: 0,0:44:25.20,0:44:28.65,Default,,0,0,0,,我得先求值-- 首先 它不是--\nDialogue: 0,0:44:29.46,0:44:31.04,Default,,0,0,0,,这是一个应用\nDialogue: 0,0:44:31.68,0:44:33.10,Default,,0,0,0,,它并不是特殊形式\nDialogue: 0,0:44:33.57,0:44:36.51,Default,,0,0,0,,如果应用中的运算符\nDialogue: 0,0:44:36.51,0:44:37.37,Default,,0,0,0,,就是这里\nDialogue: 0,0:44:37.66,0:44:38.94,Default,,0,0,0,,这就是运算符\nDialogue: 0,0:44:40.19,0:44:41.77,Default,,0,0,0,,应用在这个运算对象上\nDialogue: 0,0:44:44.54,0:44:45.74,Default,,0,0,0,,形成了一个组合式\nDialogue: 0,0:44:46.72,0:44:48.25,Default,,0,0,0,,现在我们要如何来求值呢？\nDialogue: 0,0:44:48.84,0:44:52.37,Default,,0,0,0,,它是COND语句中的最后一种情况\nDialogue: 0,0:44:52.37,0:44:55.52,Default,,0,0,0,,在这步求值中 进行的代换是\nDialogue: 0,0:44:55.71,0:44:57.47,Default,,0,0,0,,把运算符的求值结果\nDialogue: 0,0:44:57.50,0:44:59.00,Default,,0,0,0,,应用在EVLIST的运算对象上\nDialogue: 0,0:45:01.16,0:45:08.20,Default,,0,0,0,,这也就是 (APPLY (APPLY (EVAL\nDialogue: 0,0:45:10.57,0:45:21.07,Default,,0,0,0,,'(LAMBDA (X) (LAMBDA (Y) (+ X Y)))\nDialogue: 0,0:45:21.80,0:45:23.45,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:45:23.74,0:45:25.42,Default,,0,0,0,,<E0>)\nDialogue: 0,0:45:30.52,0:45:32.67,Default,,0,0,0,,我就直接给出运算对象的求值结果了\nDialogue: 0,0:45:32.68,0:45:34.14,Default,,0,0,0,,具体过程跟之前是一样的\nDialogue: 0,0:45:35.23,0:45:36.48,Default,,0,0,0,,我有一个表'(3)\nDialogue: 0,0:45:36.51,0:45:39.16,Default,,0,0,0,,把它应用于'(4)\nDialogue: 0,0:45:42.44,0:45:43.56,Default,,0,0,0,,我们接着看\nDialogue: 0,0:45:44.41,0:45:46.38,Default,,0,0,0,,对一个LAMBDA表达式求值\nDialogue: 0,0:45:48.01,0:45:49.45,Default,,0,0,0,,会产生一个过程对象\nDialogue: 0,0:45:52.03,0:45:57.88,Default,,0,0,0,,继续变换就是 (APPLY (APPLY\nDialogue: 0,0:46:00.30,0:46:02.27,Default,,0,0,0,,然后是一个过程对象 '(CLOSURE\nDialogue: 0,0:46:04.52,0:46:08.68,Default,,0,0,0,,它里面包含了过程的体\nDialogue: 0,0:46:08.94,0:46:11.92,Default,,0,0,0,,它绑定了变量X\nDialogue: 0,0:46:12.13,0:46:15.40,Default,,0,0,0,,然后是函数体内部\nDialogue: 0,0:46:15.80,0:46:18.17,Default,,0,0,0,,它返回一个参数为Y的单参过程\nDialogue: 0,0:46:18.56,0:46:20.63,Default,,0,0,0,,这个过程计算X+Y\nDialogue: 0,0:46:23.21,0:46:25.50,Default,,0,0,0,,这个过程对象捕获了环境<E0>\nDialogue: 0,0:46:27.24,0:46:29.63,Default,,0,0,0,,因为这些求值都是在<E0>中发生的\nDialogue: 0,0:46:30.11,0:46:32.43,Default,,0,0,0,,现在 <E0>也是CLOSURE对象的一部分\nDialogue: 0,0:46:33.04,0:46:38.19,Default,,0,0,0,,先应用于'(3)\nDialogue: 0,0:46:38.81,0:46:41.30,Default,,0,0,0,,再应用于'(4)\nDialogue: 0,0:46:47.39,0:46:49.29,Default,,0,0,0,,在这步到这步的过程中\nDialogue: 0,0:46:49.31,0:46:50.89,Default,,0,0,0,,我构建了一个过程对象\nDialogue: 0,0:46:50.91,0:46:52.03,Default,,0,0,0,,它捕获了<E0>\nDialogue: 0,0:46:53.88,0:46:55.98,Default,,0,0,0,,并将其作为本身的一部分\nDialogue: 0,0:46:57.15,0:46:58.51,Default,,0,0,0,,现在 要把它们传递给APPLY了\nDialogue: 0,0:46:58.52,0:46:59.71,Default,,0,0,0,,我们得把这个过程\nDialogue: 0,0:47:00.48,0:47:01.58,Default,,0,0,0,,应用在对应的参数上\nDialogue: 0,0:47:02.71,0:47:06.51,Default,,0,0,0,,这里的过程并不是基本过程\nDialogue: 0,0:47:07.38,0:47:09.88,Default,,0,0,0,,它有一个类型标志'CLOSURE\nDialogue: 0,0:47:10.24,0:47:12.09,Default,,0,0,0,,因此还需要进行参数绑定\nDialogue: 0,0:47:13.71,0:47:14.72,Default,,0,0,0,,必须要绑定\nDialogue: 0,0:47:15.83,0:47:19.40,Default,,0,0,0,,在这里构造的新环境\nDialogue: 0,0:47:20.44,0:47:22.80,Default,,0,0,0,,它有一个父环境\nDialogue: 0,0:47:22.94,0:47:27.56,Default,,0,0,0,,父环境是这里的<E0>\nDialogue: 0,0:47:30.32,0:47:31.57,Default,,0,0,0,,我们把新环境记作<E1>\nDialogue: 0,0:47:34.62,0:47:35.74,Default,,0,0,0,,这里要绑定些什么呢？\nDialogue: 0,0:47:36.04,0:47:37.48,Default,,0,0,0,,变量X绑定为值3\nDialogue: 0,0:47:38.62,0:47:40.44,Default,,0,0,0,,这里写X=3\nDialogue: 0,0:47:41.48,0:47:42.33,Default,,0,0,0,,就是这些\nDialogue: 0,0:47:44.94,0:47:46.24,Default,,0,0,0,,新环境记作E1\nDialogue: 0,0:47:46.24,0:47:48.44,Default,,0,0,0,,而这个表达式会变换为\nDialogue: 0,0:47:49.13,0:47:50.72,Default,,0,0,0,,对一个过程体的求值\nDialogue: 0,0:47:51.72,0:47:53.07,Default,,0,0,0,,就是这个 在这里\nDialogue: 0,0:47:54.40,0:47:55.72,Default,,0,0,0,,这个过程的体\nDialogue: 0,0:47:56.44,0:47:58.52,Default,,0,0,0,,在刚才创建的<E1>中进行求值\nDialogue: 0,0:48:00.29,0:48:05.05,Default,,0,0,0,,也就是 (APPLY (EVAL\nDialogue: 0,0:48:06.92,0:48:16.43,Default,,0,0,0,,'(LAMBDA (Y) (+ X Y)) <E1>)\nDialogue: 0,0:48:20.49,0:48:22.48,Default,,0,0,0,,把求值的结果应用于4\nDialogue: 0,0:48:23.68,0:48:26.73,Default,,0,0,0,,也就是'(4)\nDialogue: 0,0:48:28.43,0:48:29.87,Default,,0,0,0,,到了这里就很清晰了\nDialogue: 0,0:48:30.08,0:48:32.27,Default,,0,0,0,,我知道该如何求值LAMBDA表达式\nDialogue: 0,0:48:33.11,0:48:34.17,Default,,0,0,0,,也就是(APPLY\nDialogue: 0,0:48:37.16,0:48:38.92,Default,,0,0,0,,一个过程对象'(CLOSURE\nDialogue: 0,0:48:43.74,0:48:46.84,Default,,0,0,0,,它绑定参数Y 计算X+Y\nDialogue: 0,0:48:49.28,0:48:52.15,Default,,0,0,0,,并且捕获了环境<E1>\nDialogue: 0,0:48:55.79,0:48:57.42,Default,,0,0,0,,你应该已经见过了 对吧？\nDialogue: 0,0:48:57.80,0:49:00.14,Default,,0,0,0,,我构造了一个CLOSURE对象\nDialogue: 0,0:49:00.14,0:49:01.16,Default,,0,0,0,,放在这里\nDialogue: 0,0:49:01.79,0:49:03.04,Default,,0,0,0,,之前的那个也是\nDialogue: 0,0:49:05.90,0:49:07.47,Default,,0,0,0,,这是现在的这个\nDialogue: 0,0:49:08.08,0:49:09.80,Default,,0,0,0,,它捕获了环境<E1>\nDialogue: 0,0:49:10.41,0:49:14.25,Default,,0,0,0,,而这个是参数为Y的一元过程\nDialogue: 0,0:49:15.45,0:49:16.70,Default,,0,0,0,,先不管它具体是什么\nDialogue: 0,0:49:18.09,0:49:20.72,Default,,0,0,0,,我们只知道它是一个CLOSURE\nDialogue: 0,0:49:22.57,0:49:26.46,Default,,0,0,0,,将这个过程应用于'(4)\nDialogue: 0,0:49:30.28,0:49:31.77,Default,,0,0,0,,很简单\nDialogue: 0,0:49:36.83,0:49:38.73,Default,,0,0,0,,我需要通过复制一个指针\nDialogue: 0,0:49:38.86,0:49:40.52,Default,,0,0,0,,就是这个过程的指针\nDialogue: 0,0:49:41.56,0:49:43.21,Default,,0,0,0,,来构造一个新环境\nDialogue: 0,0:49:44.94,0:49:48.96,Default,,0,0,0,,同时还得把参数Y跟值4绑定\nDialogue: 0,0:49:49.82,0:49:52.22,Default,,0,0,0,,我把这个新环境 记作<E2>\nDialogue: 0,0:49:56.03,0:49:58.12,Default,,0,0,0,,当然 这里的这个应用\nDialogue: 0,0:49:58.22,0:50:00.33,Default,,0,0,0,,其过程体的求值 是在<E2>中进行的\nDialogue: 0,0:50:01.58,0:50:07.87,Default,,0,0,0,,所以这就变成了对过程体的求值\nDialogue: 0,0:50:07.90,0:50:11.85,Default,,0,0,0,,也就是 (EVAL '(+ X Y) <E2>)\nDialogue: 0,0:50:13.71,0:50:14.94,Default,,0,0,0,,但由于这是一个应用\nDialogue: 0,0:50:15.48,0:50:23.88,Default,,0,0,0,,所以又代换为 (APPLY (EVAL '+ <E2>)\nDialogue: 0,0:50:26.33,0:50:37.34,Default,,0,0,0,,(EVLIST '(X Y) <E2>))\nDialogue: 0,0:50:44.88,0:50:45.59,Default,,0,0,0,,我们来看\nDialogue: 0,0:50:45.59,0:50:51.71,Default,,0,0,0,,下一步代换为 (APPLY\nDialogue: 0,0:50:52.08,0:50:53.87,Default,,0,0,0,,求值‘+得到的结果\nDialogue: 0,0:50:54.19,0:50:55.66,Default,,0,0,0,,所以我们从<E2>开始找\nDialogue: 0,0:50:55.69,0:50:57.72,Default,,0,0,0,,'+既不在<E2> 也不在<E1>\nDialogue: 0,0:50:57.74,0:51:01.05,Default,,0,0,0,,‘+是<E0>中的基本运算符\nDialogue: 0,0:51:01.78,0:51:04.74,Default,,0,0,0,,这个基本运算符是用于加法的\nDialogue: 0,0:51:07.47,0:51:14.12,Default,,0,0,0,,把它应用于 在<E2>中求值X和Y的结果\nDialogue: 0,0:51:14.37,0:51:17.00,Default,,0,0,0,,我们知道X是3 Y是4\nDialogue: 0,0:51:18.11,0:51:23.31,Default,,0,0,0,,所以这里是'(3 4)\nDialogue: 0,0:51:24.16,0:51:26.28,Default,,0,0,0,,然后就神奇地得到结果7\nDialogue: 0,0:51:30.52,0:51:32.44,Default,,0,0,0,,我再来整理一下这个过程 这样你们\nDialogue: 0,0:51:32.70,0:51:34.73,Default,,0,0,0,,就能了解这其中的重要本质\nDialogue: 0,0:51:35.76,0:51:37.29,Default,,0,0,0,,这个过程中传递了些什么？\nDialogue: 0,0:51:37.31,0:51:39.56,Default,,0,0,0,,每个模块持有什么 又负责什么？\nDialogue: 0,0:51:40.47,0:51:41.61,Default,,0,0,0,,有哪些模块呢？\nDialogue: 0,0:51:41.70,0:51:42.62,Default,,0,0,0,,一个是EVAL\nDialogue: 0,0:51:44.80,0:51:45.64,Default,,0,0,0,,还有个APPLY\nDialogue: 0,0:51:45.66,0:51:46.62,Default,,0,0,0,,两个主要角色\nDialogue: 0,0:51:49.37,0:51:51.56,Default,,0,0,0,,它们之间有个像这样的大循环\nDialogue: 0,0:51:52.32,0:52:04.57,Default,,0,0,0,,其中 EVAL为APPLY生成过程和参数\nDialogue: 0,0:52:06.27,0:52:08.57,Default,,0,0,0,,也有些事情 EVAL也可以自己做\nDialogue: 0,0:52:09.50,0:52:10.86,Default,,0,0,0,,都是一些细小的事情\nDialogue: 0,0:52:10.86,0:52:11.74,Default,,0,0,0,,并不十分有趣\nDialogue: 0,0:52:12.70,0:52:15.60,Default,,0,0,0,,同时 EVAL也逐个求值所有的参数\nDialogue: 0,0:52:16.24,0:52:17.28,Default,,0,0,0,,也没什么意思\nDialogue: 0,0:52:17.65,0:52:20.09,Default,,0,0,0,,APPLY可以应用像+这类的过程\nDialogue: 0,0:52:21.02,0:52:22.04,Default,,0,0,0,,这很普通\nDialogue: 0,0:52:22.30,0:52:24.64,Default,,0,0,0,,然而 如果APPLY不能应用像+这样的过程\nDialogue: 0,0:52:25.31,0:52:33.31,Default,,0,0,0,,它就为EVAL生成一个表达式及相应的环境\nDialogue: 0,0:52:35.47,0:52:37.61,Default,,0,0,0,,过程的参数封装了\nDialogue: 0,0:52:38.24,0:52:40.60,Default,,0,0,0,,计算所必需的状态\nDialogue: 0,0:52:41.66,0:52:43.42,Default,,0,0,0,,以及相应的环境\nDialogue: 0,0:52:43.74,0:52:45.31,Default,,0,0,0,,但我们接下来要做的\nDialogue: 0,0:52:45.32,0:52:46.46,Default,,0,0,0,,并不是完整的状态\nDialogue: 0,0:52:46.48,0:52:48.82,Default,,0,0,0,,因为它没有说明谁需要返回的结果\nDialogue: 0,0:52:51.28,0:52:52.20,Default,,0,0,0,,我们要做的就是\nDialogue: 0,0:52:52.24,0:52:54.80,Default,,0,0,0,,总是把某个表达式以及相应的环境\nDialogue: 0,0:52:54.99,0:52:56.14,Default,,0,0,0,,或者过程对象以及其参数\nDialogue: 0,0:52:56.28,0:52:58.08,Default,,0,0,0,,在这个循环之间不断传递\nDialogue: 0,0:52:58.97,0:53:01.80,Default,,0,0,0,,这里还有一些小型的子循环 比如EVLIST\nDialogue: 0,0:53:04.49,0:53:06.76,Default,,0,0,0,,又或者是EVAL中的EVCOND循环\nDialogue: 0,0:53:09.10,0:53:11.96,Default,,0,0,0,,甚至于APPLY调用PRIMITIVE-APPLY\nDialogue: 0,0:53:16.14,0:53:17.64,Default,,0,0,0,,但是它们并不是最主要的\nDialogue: 0,0:53:18.86,0:53:20.28,Default,,0,0,0,,这整个就是我想让你们看到的\nDialogue: 0,0:53:21.86,0:53:22.88,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:53:25.93,0:53:27.37,Default,,0,0,0,,David 请说\nDialogue: 0,0:53:27.74,0:53:33.31,Default,,0,0,0,,学生：我不明白为什么X是3\nDialogue: 0,0:53:34.01,0:53:36.30,Default,,0,0,0,,而不是4\nDialogue: 0,0:53:37.07,0:53:38.52,Default,,0,0,0,,在那个部分\nDialogue: 0,0:53:38.56,0:53:40.54,Default,,0,0,0,,教授：是在这里\nDialogue: 0,0:53:41.31,0:53:43.31,Default,,0,0,0,,你想知道X是如何跟3绑定的\nDialogue: 0,0:53:43.52,0:53:47.42,Default,,0,0,0,,学生：因为X是外层过程的参数\nDialogue: 0,0:53:48.46,0:53:50.99,Default,,0,0,0,,而内层过程中既有X又有Y\nDialogue: 0,0:53:51.26,0:53:51.88,Default,,0,0,0,,教授：明白了\nDialogue: 0,0:53:52.84,0:53:54.62,Default,,0,0,0,,代换的过程中 我已经非常小心了\nDialogue: 0,0:53:55.02,0:53:56.92,Default,,0,0,0,,或许首先 我应该把这些过程\nDialogue: 0,0:53:56.94,0:53:58.41,Default,,0,0,0,,重新编排得更易读一点\nDialogue: 0,0:54:00.61,0:54:01.47,Default,,0,0,0,,你之所以有所疑惑\nDialogue: 0,0:54:01.48,0:54:02.99,Default,,0,0,0,,或许是因为你把程序看岔了\nDialogue: 0,0:54:03.83,0:54:04.70,Default,,0,0,0,,所以这里应该是\nDialogue: 0,0:54:05.15,0:54:09.60,Default,,0,0,0,,一个以X为参数的过程\nDialogue: 0,0:54:11.21,0:54:14.99,Default,,0,0,0,,它返回一个以Y为参数的过程\nDialogue: 0,0:54:15.72,0:54:18.44,Default,,0,0,0,,后者计算X+Y\nDialogue: 0,0:54:19.82,0:54:21.10,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:54:21.40,0:54:22.89,Default,,0,0,0,,外面的过程应用到3上\nDialogue: 0,0:54:24.08,0:54:26.12,Default,,0,0,0,,把得到的结果应用到4上\nDialogue: 0,0:54:26.14,0:54:28.81,Default,,0,0,0,,这个和之前那个是一样的 对吧？\nDialogue: 0,0:54:28.81,0:54:32.33,Default,,0,0,0,,现在 你可以立马发现\nDialogue: 0,0:54:33.77,0:54:34.94,Default,,0,0,0,,这里是一个应用\nDialogue: 0,0:54:35.16,0:54:36.46,Default,,0,0,0,,我先换根白粉笔\nDialogue: 0,0:54:37.32,0:54:41.12,Default,,0,0,0,,这一部分是应用 是一个组合式\nDialogue: 0,0:54:43.44,0:54:46.40,Default,,0,0,0,,这部分是组合式的运算符\nDialogue: 0,0:54:48.14,0:54:49.55,Default,,0,0,0,,而这是运算对象\nDialogue: 0,0:54:51.04,0:54:53.05,Default,,0,0,0,,这个3会跟这里的X绑定\nDialogue: 0,0:54:54.90,0:54:56.36,Default,,0,0,0,,而这个组合式的结果\nDialogue: 0,0:54:56.56,0:54:58.46,Default,,0,0,0,,是一个参数为Y的一元过程\nDialogue: 0,0:54:58.73,0:54:59.79,Default,,0,0,0,,它将应用于4\nDialogue: 0,0:55:00.88,0:55:01.58,Default,,0,0,0,,明白了吧？\nDialogue: 0,0:55:02.20,0:55:04.08,Default,,0,0,0,,所以你可能只是看岔了\nDialogue: 0,0:55:04.40,0:55:07.85,Default,,0,0,0,,而你们在这里看到的\nDialogue: 0,0:55:09.42,0:55:12.96,Default,,0,0,0,,是一个实际的过程对象 它有一个参数X\nDialogue: 0,0:55:13.34,0:55:15.31,Default,,0,0,0,,这个CLOSURE将应用于3\nDialogue: 0,0:55:15.95,0:55:17.07,Default,,0,0,0,,也就是'(3)\nDialogue: 0,0:55:18.98,0:55:21.34,Default,,0,0,0,,得到的结果再应用于'(4)\nDialogue: 0,0:55:24.08,0:55:25.20,Default,,0,0,0,,还有疑问吗？\nDialogue: 0,0:55:28.35,0:55:30.38,Default,,0,0,0,,那就休息一下吧\nDialogue: 0,0:55:30.83,0:55:31.37,Default,,0,0,0,,谢谢大家\nDialogue: 0,0:55:33.73,0:55:41.40,Default,,0,0,0,,[音乐]\nDialogue: 0,0:55:42.12,0:55:47.44,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:55:50.70,0:55:54.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:55:54.12,0:55:59.16,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:55:59.23,0:56:03.95,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 I\nDialogue: 0,0:56:08.41,0:56:11.29,Default,,0,0,0,,教授：课上到这里\nDialogue: 0,0:56:13.32,0:56:14.59,Default,,0,0,0,,你们可能开始觉得\nDialogue: 0,0:56:14.75,0:56:17.96,Default,,0,0,0,,Sussman教授又在胡说八道些什么\nDialogue: 0,0:56:20.74,0:56:23.92,Default,,0,0,0,,他讲的东西奇怪、愚蠢又毫无意义\nDialogue: 0,0:56:24.80,0:56:27.40,Default,,0,0,0,,他还宣称要给我们解释Lisp\nDialogue: 0,0:56:28.01,0:56:29.90,Default,,0,0,0,,然后在黑板上给我们写了一个Lisp程序\nDialogue: 0,0:56:31.23,0:56:33.53,Default,,0,0,0,,他还说：“这个Lisp程序就是Lisp解释器”\nDialogue: 0,0:56:33.85,0:56:35.02,Default,,0,0,0,,但是为了运行这个Lisp程序\nDialogue: 0,0:56:35.04,0:56:36.30,Default,,0,0,0,,你还先得有一个Lisp解释器啊\nDialogue: 0,0:56:38.37,0:56:40.19,Default,,0,0,0,,那个程序怎么能告诉我\nDialogue: 0,0:56:40.22,0:56:43.20,Default,,0,0,0,,有关于Lisp的知识呢？\nDialogue: 0,0:56:44.15,0:56:46.22,Default,,0,0,0,,它为什么又不是空中楼阁呢？\nDialogue: 0,0:56:48.49,0:56:50.25,Default,,0,0,0,,这件事非常奇怪\nDialogue: 0,0:56:50.99,0:56:52.43,Default,,0,0,0,,它究竟告诉了我什么？\nDialogue: 0,0:56:56.07,0:56:57.20,Default,,0,0,0,,我们发现 其实这整件事\nDialogue: 0,0:56:57.32,0:56:59.79,Default,,0,0,0,,非常像我们在这张幻灯片上看到的\nDialogue: 0,0:57:00.46,0:57:03.55,Default,,0,0,0,,Escher所画的手\nDialogue: 0,0:57:06.18,0:57:07.72,Default,,0,0,0,,是的 EVAL和APPLY\nDialogue: 0,0:57:07.76,0:57:10.16,Default,,0,0,0,,彼此画出彼此\nDialogue: 0,0:57:11.50,0:57:14.16,Default,,0,0,0,,并且构造出了真实的东西\nDialogue: 0,0:57:14.86,0:57:16.30,Default,,0,0,0,,它完全是自己画出了自己\nDialogue: 0,0:57:17.11,0:57:18.46,Default,,0,0,0,,Escher真是绝顶聪明\nDialogue: 0,0:57:18.68,0:57:20.41,Default,,0,0,0,,他只不过叫不出这些精灵的名字\nDialogue: 0,0:57:23.91,0:57:25.00,Default,,0,0,0,,我现在要做的就是\nDialogue: 0,0:57:26.09,0:57:28.00,Default,,0,0,0,,使你们相信\nDialogue: 0,0:57:28.16,0:57:29.87,Default,,0,0,0,,这一切都是有意义的\nDialogue: 0,0:57:30.16,0:57:31.98,Default,,0,0,0,,并且\nDialogue: 0,0:57:32.99,0:57:34.72,Default,,0,0,0,,我将要解释为什么我们不需要DEFINE\nDialogue: 0,0:57:36.09,0:57:37.71,Default,,0,0,0,,事实证明 我们并不需要DEFINE\nDialogue: 0,0:57:38.09,0:57:41.12,Default,,0,0,0,,为了进行数学意义上的计算\nDialogue: 0,0:57:42.51,0:57:44.89,Default,,0,0,0,,DEFINE并不是必需的\nDialogue: 0,0:57:49.10,0:57:50.03,Default,,0,0,0,,我们来看一下\nDialogue: 0,0:57:50.69,0:57:53.31,Default,,0,0,0,,考虑下面的一小段程序\nDialogue: 0,0:57:53.74,0:57:54.64,Default,,0,0,0,,它有什么作用？\nDialogue: 0,0:57:54.87,0:57:57.64,Default,,0,0,0,,这是一个计算指数的程序\nDialogue: 0,0:58:07.27,0:58:13.23,Default,,0,0,0,,EXPT计算X的N次方\nDialogue: 0,0:58:16.83,0:58:18.12,Default,,0,0,0,,如果N为0\nDialogue: 0,0:58:19.20,0:58:20.76,Default,,0,0,0,,那么结果就是1\nDialogue: 0,0:58:22.07,0:58:22.81,Default,,0,0,0,,否则\nDialogue: 0,0:58:25.56,0:58:28.48,Default,,0,0,0,,结果就是X乘以\nDialogue: 0,0:58:28.75,0:58:33.93,Default,,0,0,0,,(EXPT X (- N 1))))\nDialogue: 0,0:58:43.69,0:58:44.56,Default,,0,0,0,,应该没错\nDialogue: 0,0:58:46.63,0:58:48.72,Default,,0,0,0,,一个递归定义\nDialogue: 0,0:58:49.47,0:58:52.17,Default,,0,0,0,,用EXPT自身\nDialogue: 0,0:58:52.46,0:58:54.78,Default,,0,0,0,,来定义EXPT过程自己\nDialogue: 0,0:58:56.41,0:58:58.32,Default,,0,0,0,,就像我之前说的那样\nDialogue: 0,0:58:59.28,0:59:01.68,Default,,0,0,0,,你们高中数学老师在教这些东西的时候\nDialogue: 0,0:59:01.84,0:59:04.04,Default,,0,0,0,,你们一定学得很痛苦\nDialogue: 0,0:59:05.65,0:59:06.73,Default,,0,0,0,,这样定义合理吗？\nDialogue: 0,0:59:07.91,0:59:10.84,Default,,0,0,0,,为什么这种自引用的定义\nDialogue: 0,0:59:10.96,0:59:12.04,Default,,0,0,0,,能够说得通呢？\nDialogue: 0,0:59:13.43,0:59:15.10,Default,,0,0,0,,首先我要说的是\nDialogue: 0,0:59:15.13,0:59:17.60,Default,,0,0,0,,你们高中数学老师并非在胡说八道\nDialogue: 0,0:59:20.37,0:59:23.42,Default,,0,0,0,,考虑下面的几组定义\nDialogue: 0,0:59:24.27,0:59:27.42,Default,,0,0,0,,X+Y=3\nDialogue: 0,0:59:28.24,0:59:32.24,Default,,0,0,0,,X-Y=1\nDialogue: 0,0:59:33.07,0:59:35.56,Default,,0,0,0,,这个方程用Y来告诉你X\nDialogue: 0,0:59:35.58,0:59:37.84,Default,,0,0,0,,而这个方程或许是用X来告诉你Y\nDialogue: 0,0:59:40.15,0:59:42.95,Default,,0,0,0,,碰巧这组方程有唯一的解\nDialogue: 0,0:59:55.91,0:59:58.11,Default,,0,0,0,,然而 我也可能有这样的方程\nDialogue: 0,0:59:59.87,1:00:04.25,Default,,0,0,0,,2X+2Y=6\nDialogue: 0,1:00:06.83,1:00:09.87,Default,,0,0,0,,这两个方程有无穷多个解\nDialogue: 0,1:00:15.73,1:00:17.42,Default,,0,0,0,,我还可以有像这样的方程\nDialogue: 0,1:00:18.89,1:00:21.53,Default,,0,0,0,,X-Y=2\nDialogue: 0,1:00:22.14,1:00:24.41,Default,,0,0,0,,而下面的这两个方程没有解\nDialogue: 0,1:00:29.82,1:00:33.04,Default,,0,0,0,,这里 我有三组线性方程组\nDialogue: 0,1:00:35.45,1:00:39.51,Default,,0,0,0,,分别是这组、这组和这组\nDialogue: 0,1:00:39.88,1:00:41.79,Default,,0,0,0,,它们的解的数目完全不同\nDialogue: 0,1:00:42.90,1:00:45.76,Default,,0,0,0,,解的数目并不取决于方程的形式\nDialogue: 0,1:00:46.33,1:00:48.20,Default,,0,0,0,,三组方程都有一样的形式\nDialogue: 0,1:00:48.54,1:00:50.41,Default,,0,0,0,,解的数目取决于方程的内容\nDialogue: 0,1:00:53.00,1:00:55.15,Default,,0,0,0,,我不能通过观察方程的形式\nDialogue: 0,1:00:55.16,1:00:56.24,Default,,0,0,0,,来判断解的数目\nDialogue: 0,1:00:56.86,1:00:58.60,Default,,0,0,0,,必须要看它的内容\nDialogue: 0,1:00:59.66,1:01:00.88,Default,,0,0,0,,比如 对于线性方程组\nDialogue: 0,1:01:01.34,1:01:03.39,Default,,0,0,0,,它的系数都是什么？\nDialogue: 0,1:01:05.10,1:01:06.72,Default,,0,0,0,,我不能够通过观察\nDialogue: 0,1:01:06.99,1:01:08.33,Default,,0,0,0,,像这样的简单情况\nDialogue: 0,1:01:08.59,1:01:09.95,Default,,0,0,0,,来判定\nDialogue: 0,1:01:10.08,1:01:14.49,Default,,0,0,0,,EXPT就是这个递归方程的解\nDialogue: 0,1:01:16.03,1:01:18.41,Default,,0,0,0,,我不能说 EXPT就是那个过程\nDialogue: 0,1:01:18.91,1:01:21.10,Default,,0,0,0,,如果我们把它代换入其中\nDialogue: 0,1:01:22.04,1:01:24.06,Default,,0,0,0,,它就能给我们返回EXPT\nDialogue: 0,1:01:25.32,1:01:25.68,Default,,0,0,0,,能跟上吗？\nDialogue: 0,1:01:26.04,1:01:29.24,Default,,0,0,0,,通过观察这个形式 我也无法判别\nDialogue: 0,1:01:29.80,1:01:32.60,Default,,0,0,0,,EXPT是否有唯一解\nDialogue: 0,1:01:33.23,1:01:35.31,Default,,0,0,0,,有无穷个解 还是根本没有解\nDialogue: 0,1:01:37.20,1:01:38.62,Default,,0,0,0,,我们要了解它是如何计数的\nDialogue: 0,1:01:38.64,1:01:40.14,Default,,0,0,0,,或者是一些类似的计算细节\nDialogue: 0,1:01:40.60,1:01:42.75,Default,,0,0,0,,这可比在线性代数难多了\nDialogue: 0,1:01:43.28,1:01:45.21,Default,,0,0,0,,程序设计中可用的定理并不多\nDialogue: 0,1:01:48.45,1:01:51.21,Default,,0,0,0,,我想把这些方程稍稍重写一下\nDialogue: 0,1:01:51.93,1:01:53.77,Default,,0,0,0,,就是这里的方程\nDialogue: 0,1:01:53.97,1:01:56.62,Default,,0,0,0,,因为我们要研究的是这种形式的方程\nDialogue: 0,1:01:57.00,1:01:58.38,Default,,0,0,0,,但是我想用我们比较了解的方程\nDialogue: 0,1:01:58.40,1:01:59.53,Default,,0,0,0,,来做演示\nDialogue: 0,1:02:00.70,1:02:02.91,Default,,0,0,0,,以便于对于这类问题有深入的洞见\nDialogue: 0,1:02:04.72,1:02:06.43,Default,,0,0,0,,我们可以把这里的方程 改写为\nDialogue: 0,1:02:06.75,1:02:08.67,Default,,0,0,0,,这样的一种有趣形式\nDialogue: 0,1:02:09.77,1:02:14.86,Default,,0,0,0,,X=3-Y\nDialogue: 0,1:02:15.88,1:02:19.68,Default,,0,0,0,,Y=X-1\nDialogue: 0,1:02:22.01,1:02:24.05,Default,,0,0,0,,我们把这种变换叫什么来着？\nDialogue: 0,1:02:24.05,1:02:26.52,Default,,0,0,0,,这是一个线性变换 记为T\nDialogue: 0,1:02:29.43,1:02:32.25,Default,,0,0,0,,我们这里就得到了一个方程\nDialogue: 0,1:02:32.97,1:02:37.37,Default,,0,0,0,,<X Y> = T<X Y>\nDialogue: 0,1:02:42.99,1:02:43.98,Default,,0,0,0,,我要去找什么呢？\nDialogue: 0,1:02:44.56,1:02:46.01,Default,,0,0,0,,我在找T的不动点\nDialogue: 0,1:02:46.97,1:02:59.42,Default,,0,0,0,,T的不动点就是方程的解\nDialogue: 0,1:03:01.91,1:03:05.53,Default,,0,0,0,,所以 如果我们能通过找不动点\nDialogue: 0,1:03:05.90,1:03:07.48,Default,,0,0,0,,来求解方程\nDialogue: 0,1:03:08.65,1:03:09.87,Default,,0,0,0,,这看来是可行的\nDialogue: 0,1:03:10.88,1:03:12.36,Default,,0,0,0,,如果我可以用不动点\nDialogue: 0,1:03:12.38,1:03:14.32,Default,,0,0,0,,来求解方程\nDialogue: 0,1:03:15.52,1:03:18.19,Default,,0,0,0,,当然 也许它不可行\nDialogue: 0,1:03:18.57,1:03:19.80,Default,,0,0,0,,不过也可以借鉴来\nDialogue: 0,1:03:20.09,1:03:22.27,Default,,0,0,0,,研究如何求解这类方程\nDialogue: 0,1:03:27.24,1:03:29.48,Default,,0,0,0,,重要的是 我想让你们把它看成一个方程\nDialogue: 0,1:03:30.26,1:03:31.21,Default,,0,0,0,,它是一个表达式\nDialogue: 0,1:03:31.36,1:03:33.58,Default,,0,0,0,,其中有不同的变量\nDialogue: 0,1:03:34.70,1:03:37.66,Default,,0,0,0,,只不过这些名字还得满足一定的约束\nDialogue: 0,1:03:38.43,1:03:40.52,Default,,0,0,0,,这些名字限定了对应变量的取值\nDialogue: 0,1:03:41.48,1:03:45.01,Default,,0,0,0,,我们不能够随意、机械地代换\nDialogue: 0,1:03:47.74,1:03:49.77,Default,,0,0,0,,这就是我尝试求解的方程\nDialogue: 0,1:03:51.22,1:03:52.43,Default,,0,0,0,,我们来试试看\nDialogue: 0,1:03:53.96,1:03:55.66,Default,,0,0,0,,首先我需要写下\nDialogue: 0,1:03:56.64,1:03:59.00,Default,,0,0,0,,跟T相对应的函数\nDialogue: 0,1:04:00.32,1:04:03.00,Default,,0,0,0,,我写下的这个T对应的函数\nDialogue: 0,1:04:04.49,1:04:06.96,Default,,0,0,0,,它的不动点就是这个方程的解\nDialogue: 0,1:04:10.76,1:04:11.28,Default,,0,0,0,,能明白吗？\nDialogue: 0,1:04:12.25,1:04:14.30,Default,,0,0,0,,让我们来看下面这个过程F\nDialogue: 0,1:04:16.87,1:04:18.30,Default,,0,0,0,,我说 F计算的是这样一个函数\nDialogue: 0,1:04:19.34,1:04:22.91,Default,,0,0,0,,F本身是一个参数为G的一元过程\nDialogue: 0,1:04:25.23,1:04:25.93,Default,,0,0,0,,它返回\nDialogue: 0,1:04:26.40,1:04:32.00,Default,,0,0,0,,一个参数为X和N的过程\nDialogue: 0,1:04:33.43,1:04:34.73,Default,,0,0,0,,这个过程的定义是：\nDialogue: 0,1:04:36.72,1:04:40.43,Default,,0,0,0,,如果N为0\nDialogue: 0,1:04:41.72,1:04:43.20,Default,,0,0,0,,那么结果就是1\nDialogue: 0,1:04:45.34,1:04:46.17,Default,,0,0,0,,否则的话\nDialogue: 0,1:04:49.90,1:05:01.40,Default,,0,0,0,,结果就是(* X (G X (- N 1)))\nDialogue: 0,1:05:03.37,1:05:07.80,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,1:05:08.94,1:05:09.40,Default,,0,0,0,,没问题吧\nDialogue: 0,1:05:12.30,1:05:14.62,Default,,0,0,0,,这里 F是一个过程\nDialogue: 0,1:05:15.05,1:05:17.79,Default,,0,0,0,,如果我能解出这个方程\nDialogue: 0,1:05:19.04,1:05:22.04,Default,,0,0,0,,如果我找到了一个良好的指数过程\nDialogue: 0,1:05:23.42,1:05:26.32,Default,,0,0,0,,我把这个F应用到那个过程上\nDialogue: 0,1:05:27.60,1:05:31.24,Default,,0,0,0,,那么返回的应该也是一个良好的指数过程\nDialogue: 0,1:05:37.46,1:05:38.57,Default,,0,0,0,,这是为什么呢？\nDialogue: 0,1:05:39.42,1:05:40.88,Default,,0,0,0,,这是因为\nDialogue: 0,1:05:42.36,1:05:44.64,Default,,0,0,0,,F假设G是一个良好的指数过程\nDialogue: 0,1:05:45.63,1:05:47.58,Default,,0,0,0,,那么这里就会返回\nDialogue: 0,1:05:47.84,1:05:49.68,Default,,0,0,0,,一个参数为X和N的过程\nDialogue: 0,1:05:50.49,1:05:51.52,Default,,0,0,0,,其中如果N=0\nDialogue: 0,1:05:51.55,1:05:52.41,Default,,0,0,0,,结果就是1\nDialogue: 0,1:05:52.44,1:05:54.16,Default,,0,0,0,,这是非常符合定义的\nDialogue: 0,1:05:54.64,1:05:57.05,Default,,0,0,0,,否则 就返回X乘以\nDialogue: 0,1:05:57.26,1:05:59.26,Default,,0,0,0,,用给定的指数过程G\nDialogue: 0,1:06:00.17,1:06:02.44,Default,,0,0,0,,计算(G X (- N 1))\nDialogue: 0,1:06:03.47,1:06:04.78,Default,,0,0,0,,因此如果G能够\nDialogue: 0,1:06:04.81,1:06:06.30,Default,,0,0,0,,正确计算X^(N-1)\nDialogue: 0,1:06:07.87,1:06:11.28,Default,,0,0,0,,那么这个表达式就能正确计算X^N\nDialogue: 0,1:06:12.17,1:06:14.41,Default,,0,0,0,,所以整个就会是一个正确的求指数过程\nDialogue: 0,1:06:17.50,1:06:19.82,Default,,0,0,0,,因此 我在这里真正想指出的是\nDialogue: 0,1:06:21.02,1:06:32.44,Default,,0,0,0,,过程EXPT是函数F的不动点\nDialogue: 0,1:06:36.99,1:06:38.35,Default,,0,0,0,,现在我们的问题在于\nDialogue: 0,1:06:38.35,1:06:39.68,Default,,0,0,0,,不动点可能不止一个\nDialogue: 0,1:06:40.06,1:06:42.19,Default,,0,0,0,,也可能没有不动点\nDialogue: 0,1:06:43.27,1:06:44.81,Default,,0,0,0,,所以我们必须求出不动点\nDialogue: 0,1:06:48.22,1:06:49.37,Default,,0,0,0,,需要来解这个方程\nDialogue: 0,1:06:52.16,1:06:54.28,Default,,0,0,0,,求不动点的方法有很多种\nDialogue: 0,1:06:55.58,1:06:57.08,Default,,0,0,0,,本门课程的第一节课\nDialogue: 0,1:06:57.24,1:07:01.16,Default,,0,0,0,,我们就用余弦函数做了演示\nDialogue: 0,1:07:02.73,1:07:07.69,Default,,0,0,0,,先把你的计算器调成弧度制\nDialogue: 0,1:07:07.85,1:07:10.51,Default,,0,0,0,,然后一直按COS键\nDialogue: 0,1:07:11.84,1:07:15.45,Default,,0,0,0,,最后数字会稳定在0.73、0.74左右\nDialogue: 0,1:07:16.09,1:07:17.18,Default,,0,0,0,,我记不清是哪个了\nDialogue: 0,1:07:20.57,1:07:22.64,Default,,0,0,0,,通过迭代一个过程\nDialogue: 0,1:07:22.81,1:07:24.40,Default,,0,0,0,,我们不断迭代\nDialogue: 0,1:07:25.60,1:07:27.16,Default,,0,0,0,,想要寻找不动点的函数\nDialogue: 0,1:07:27.50,1:07:31.13,Default,,0,0,0,,有时候 它就会收敛在一个点上\nDialogue: 0,1:07:31.87,1:07:33.08,Default,,0,0,0,,这就是不动点\nDialogue: 0,1:07:33.77,1:07:35.44,Default,,0,0,0,,碰碰运气\nDialogue: 0,1:07:36.44,1:07:37.21,Default,,0,0,0,,来试试这种方法\nDialogue: 0,1:07:39.91,1:07:46.28,Default,,0,0,0,,来看这张幻灯片\nDialogue: 0,1:07:48.03,1:07:51.71,Default,,0,0,0,,考虑这么一连串的过程\nDialogue: 0,1:07:56.40,1:07:57.79,Default,,0,0,0,,这里的E0\nDialogue: 0,1:07:59.24,1:08:01.63,Default,,0,0,0,,这个E0过程什么也不做\nDialogue: 0,1:08:02.89,1:08:05.10,Default,,0,0,0,,无论你给它传递什么参数\nDialogue: 0,1:08:05.10,1:08:06.24,Default,,0,0,0,,它都会产生ERROR\nDialogue: 0,1:08:07.78,1:08:09.03,Default,,0,0,0,,基本上没什么用\nDialogue: 0,1:08:14.48,1:08:20.08,Default,,0,0,0,,然而 我可以做近似\nDialogue: 0,1:08:20.08,1:08:23.93,Default,,0,0,0,,让我们考虑下 指数过程的最差近似\nDialogue: 0,1:08:24.73,1:08:25.53,Default,,0,0,0,,因为它什么也做不了\nDialogue: 0,1:08:26.99,1:08:29.68,Default,,0,0,0,,假设我调用F\nDialogue: 0,1:08:30.35,1:08:33.26,Default,,0,0,0,,用E0去代换G\nDialogue: 0,1:08:33.79,1:08:36.30,Default,,0,0,0,,这里 G就被代换为了E0\nDialogue: 0,1:08:37.38,1:08:39.77,Default,,0,0,0,,所以在这里就是E0\nDialogue: 0,1:08:40.84,1:08:42.35,Default,,0,0,0,,那么E1又成了什么呢？\nDialogue: 0,1:08:43.63,1:08:46.03,Default,,0,0,0,,如果用E1来计算X^0\nDialogue: 0,1:08:46.67,1:08:48.78,Default,,0,0,0,,没什么问题\nDialogue: 0,1:08:49.60,1:08:50.75,Default,,0,0,0,,它返回的结果是正确的\nDialogue: 0,1:08:51.05,1:08:52.35,Default,,0,0,0,,任何数的0次幂都是1\nDialogue: 0,1:08:52.68,1:08:54.25,Default,,0,0,0,,然而计算其它次幂就会出错\nDialogue: 0,1:08:57.39,1:09:01.56,Default,,0,0,0,,现在如果我用E1来调用F\nDialogue: 0,1:09:02.30,1:09:07.40,Default,,0,0,0,,把G代换为E1 会发生什么？\nDialogue: 0,1:09:09.58,1:09:11.18,Default,,0,0,0,,这样的话\nDialogue: 0,1:09:12.01,1:09:15.02,Default,,0,0,0,,我就会得到这个二元过程\nDialogue: 0,1:09:15.67,1:09:16.84,Default,,0,0,0,,想一想 E1这个过程\nDialogue: 0,1:09:16.96,1:09:19.66,Default,,0,0,0,,只能正确计算X^0\nDialogue: 0,1:09:21.47,1:09:23.37,Default,,0,0,0,,它只能计算0次幂\nDialogue: 0,1:09:24.20,1:09:25.00,Default,,0,0,0,,所以这里\nDialogue: 0,1:09:25.52,1:09:27.28,Default,,0,0,0,,如果N为0 结果就是1\nDialogue: 0,1:09:27.29,1:09:28.67,Default,,0,0,0,,E2的这部分也正确\nDialogue: 0,1:09:29.52,1:09:32.01,Default,,0,0,0,,然而 我可以通过把0次幂乘以X\nDialogue: 0,1:09:32.51,1:09:35.26,Default,,0,0,0,,来计算1次幂\nDialogue: 0,1:09:35.97,1:09:39.67,Default,,0,0,0,,所以E2可以正确计算0次幂和1次幂\nDialogue: 0,1:09:41.60,1:09:41.92,Default,,0,0,0,,对吧？\nDialogue: 0,1:09:43.71,1:09:46.67,Default,,0,0,0,,E3的构造过程和E2是类似的\nDialogue: 0,1:09:47.89,1:09:50.24,Default,,0,0,0,,当然 E3具有同样的参数\nDialogue: 0,1:09:50.32,1:09:53.37,Default,,0,0,0,,能够正确计算0、1、2次幂\nDialogue: 0,1:09:55.12,1:09:55.40,Default,,0,0,0,,对吧？\nDialogue: 0,1:09:56.09,1:09:59.08,Default,,0,0,0,,因此我就不加证明地告诉你结论\nDialogue: 0,1:09:59.66,1:10:01.72,Default,,0,0,0,,因为这个证明过程太难了\nDialogue: 0,1:10:02.52,1:10:03.60,Default,,0,0,0,,这种事情\nDialogue: 0,1:10:03.63,1:10:06.36,Default,,0,0,0,,是由人们所谓“指称语义学家”完成的\nDialogue: 0,1:10:06.59,1:10:07.64,Default,,0,0,0,,这个伟大的想法\nDialogue: 0,1:10:07.87,1:10:10.59,Default,,0,0,0,,应该是由Scott和Strachey提出的\nDialogue: 0,1:10:11.64,1:10:16.32,Default,,0,0,0,,他们是非常著名的数学家\nDialogue: 0,1:10:16.86,1:10:21.21,Default,,0,0,0,,他们发明了这些程序的解释方式\nDialogue: 0,1:10:22.36,1:10:24.00,Default,,0,0,0,,就是我刚才讲的那些\nDialogue: 0,1:10:24.24,1:10:26.17,Default,,0,0,0,,他们通过拓扑学的方法证明了\nDialogue: 0,1:10:27.04,1:10:29.32,Default,,0,0,0,,在我们刚才那种情况下\nDialogue: 0,1:10:29.82,1:10:31.26,Default,,0,0,0,,不动点是存在的\nDialogue: 0,1:10:32.22,1:10:33.24,Default,,0,0,0,,这个结论就是：\nDialogue: 0,1:10:33.40,1:10:44.24,Default,,0,0,0,,当N趋近于无穷时 EXPT是E(N)的极限\nDialogue: 0,1:10:45.52,1:10:47.90,Default,,0,0,0,,我们是通过下面这种方式来构造这个极限的\nDialogue: 0,1:10:50.52,1:10:55.66,Default,,0,0,0,,EXPT=(F (F (F (F ....\nDialogue: 0,1:10:57.61,1:11:00.19,Default,,0,0,0,,(F 丄)\nDialogue: 0,1:11:01.12,1:11:02.46,Default,,0,0,0,,它是什么都无所谓\nDialogue: 0,1:11:03.18,1:11:05.00,Default,,0,0,0,,因为它总会生成一个错误\nDialogue: 0,1:11:07.45,1:11:08.41,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,1:11:12.89,1:11:14.48,Default,,0,0,0,,这是F无穷嵌套调用\nDialogue: 0,1:11:16.38,1:11:17.71,Default,,0,0,0,,现在我们的问题\nDialogue: 0,1:11:18.22,1:11:19.76,Default,,0,0,0,,又变成了如何构造出无穷调用\nDialogue: 0,1:11:22.59,1:11:24.08,Default,,0,0,0,,我们需要它们\nDialogue: 0,1:11:24.92,1:11:26.25,Default,,0,0,0,,我怎样才能把F\nDialogue: 0,1:11:26.56,1:11:27.80,Default,,0,0,0,,嵌套无穷层呢？\nDialogue: 0,1:11:28.98,1:11:30.12,Default,,0,0,0,,我得把它构造出来\nDialogue: 0,1:11:32.38,1:11:32.93,Default,,0,0,0,,好吧 我不知道\nDialogue: 0,1:11:32.93,1:11:34.32,Default,,0,0,0,,到底怎么样构建一个无穷循环呢？\nDialogue: 0,1:11:34.81,1:11:36.32,Default,,0,0,0,,我们先来看个非常简单的无穷循环\nDialogue: 0,1:11:36.57,1:11:38.34,Default,,0,0,0,,能想到的最简单的无穷循环\nDialogue: 0,1:11:43.55,1:11:47.55,Default,,0,0,0,,把这样一个参数为X的函数过程\nDialogue: 0,1:11:48.00,1:11:49.79,Default,,0,0,0,,过程体是(X X)\nDialogue: 0,1:11:53.55,1:11:53.92,Default,,0,0,0,,看到了吧？\nDialogue: 0,1:11:55.05,1:11:58.41,Default,,0,0,0,,应用在一个参数为X过程上\nDialogue: 0,1:11:59.36,1:12:01.05,Default,,0,0,0,,后者的过程体也是(X X)\nDialogue: 0,1:12:04.83,1:12:06.00,Default,,0,0,0,,这就形成了一个无穷循环\nDialogue: 0,1:12:07.21,1:12:09.31,Default,,0,0,0,,这个循环之所以是无穷的\nDialogue: 0,1:12:09.98,1:12:11.31,Default,,0,0,0,,是因为\nDialogue: 0,1:12:11.52,1:12:13.69,Default,,0,0,0,,我用实际参数代换掉\nDialogue: 0,1:12:14.22,1:12:16.59,Default,,0,0,0,,过程体的形式参数\nDialogue: 0,1:12:18.85,1:12:21.60,Default,,0,0,0,,这样做了以后 这里的每个X\nDialogue: 0,1:12:22.40,1:12:23.76,Default,,0,0,0,,都被代换为了这个\nDialogue: 0,1:12:24.36,1:12:26.96,Default,,0,0,0,,相当于把最初的表达式又复制了一遍\nDialogue: 0,1:12:28.35,1:12:29.37,Default,,0,0,0,,这就是最简单的无穷循环\nDialogue: 0,1:12:35.44,1:12:39.29,Default,,0,0,0,,现在 我要介绍一个特殊的运算符\nDialogue: 0,1:12:40.38,1:12:43.09,Default,,0,0,0,,它是通过对这个无穷循环稍作修改而来\nDialogue: 0,1:12:46.96,1:12:47.92,Default,,0,0,0,,我把它记作“Y”\nDialogue: 0,1:12:50.89,1:12:55.82,Default,,0,0,0,,它的全称是：Curry的矛盾Y组合子\nDialogue: 0,1:12:56.62,1:12:58.99,Default,,0,0,0,,这是用二十世纪三十年代的逻辑学家\nDialogue: 0,1:12:59.34,1:13:01.85,Default,,0,0,0,,Curry的名字来命名的\nDialogue: 0,1:13:04.48,1:13:06.88,Default,,0,0,0,,Y组合子是一个参数为f的过程\nDialogue: 0,1:13:08.17,1:13:09.33,Default,,0,0,0,,它的过程体是什么呢？\nDialogue: 0,1:13:09.33,1:13:11.20,Default,,0,0,0,,它的内部是某种无穷循环\nDialogue: 0,1:13:11.98,1:13:15.47,Default,,0,0,0,,是一个参数为x的过程\nDialogue: 0,1:13:15.95,1:13:18.80,Default,,0,0,0,,它调用(f (x x))\nDialogue: 0,1:13:21.63,1:13:24.75,Default,,0,0,0,,这个过程应用在一个参数为X的过程上\nDialogue: 0,1:13:25.10,1:13:27.34,Default,,0,0,0,,后者调用(f (x x))\nDialogue: 0,1:13:32.30,1:13:33.13,Default,,0,0,0,,这个是怎么运作的？\nDialogue: 0,1:13:34.80,1:13:36.06,Default,,0,0,0,,假设执行(Y F)\nDialogue: 0,1:13:41.31,1:13:42.57,Default,,0,0,0,,这非常简单\nDialogue: 0,1:13:43.15,1:13:44.62,Default,,0,0,0,,这里大写的F跟那边的是同一个\nDialogue: 0,1:13:46.91,1:13:48.16,Default,,0,0,0,,在这里 很简单\nDialogue: 0,1:13:48.30,1:13:49.92,Default,,0,0,0,,我把F代换到这里来\nDialogue: 0,1:13:55.32,1:13:57.07,Default,,0,0,0,,基本上 我就会得到\nDialogue: 0,1:13:58.75,1:14:00.84,Default,,0,0,0,,因为我待会儿要用这个表达式\nDialogue: 0,1:14:01.45,1:14:02.80,Default,,0,0,0,,代换这里的x\nDialogue: 0,1:14:04.17,1:14:05.23,Default,,0,0,0,,这里就是(F\nDialogue: 0,1:14:08.97,1:14:10.09,Default,,0,0,0,,我还是把这步写出来吧\nDialogue: 0,1:14:10.22,1:14:11.45,Default,,0,0,0,,这样你们就能看得更全面\nDialogue: 0,1:14:11.92,1:14:14.27,Default,,0,0,0,,我会非常小心 好吗？\nDialogue: 0,1:14:15.02,1:14:18.25,Default,,0,0,0,,这里是 ((LAMBDA (x)\nDialogue: 0,1:14:19.08,1:14:22.11,Default,,0,0,0,,(F (x x))\nDialogue: 0,1:14:26.88,1:14:35.55,Default,,0,0,0,,把它应用到自身 (LAMBDA (x) (F (x x)))\nDialogue: 0,1:14:37.91,1:14:39.66,Default,,0,0,0,,把这个表达式代换进去\nDialogue: 0,1:14:40.06,1:14:40.91,Default,,0,0,0,,就得到\nDialogue: 0,1:14:43.13,1:14:48.35,Default,,0,0,0,,把这个代进去 得到什么呢？\nDialogue: 0,1:14:48.65,1:14:54.81,Default,,0,0,0,,(F (LAMBDA (x) (F (x x)))\nDialogue: 0,1:14:57.07,1:14:58.17,Default,,0,0,0,,应用到\nDialogue: 0,1:14:59.18,1:15:06.48,Default,,0,0,0,,(LAMBDA (x) (F (x x))))\nDialogue: 0,1:15:06.99,1:15:10.44,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,1:15:11.51,1:15:12.40,Default,,0,0,0,,哇 这又是什么？\nDialogue: 0,1:15:13.42,1:15:16.35,Default,,0,0,0,,我刚才计算的这一部分\nDialogue: 0,1:15:17.13,1:15:18.56,Default,,0,0,0,,就是这里的这部分\nDialogue: 0,1:15:20.19,1:15:21.84,Default,,0,0,0,,只不过它被包在另一个F里面\nDialogue: 0,1:15:23.37,1:15:24.67,Default,,0,0,0,,因此 通过把Y应用在F上\nDialogue: 0,1:15:24.68,1:15:26.22,Default,,0,0,0,,我构造出了F的无穷嵌套\nDialogue: 0,1:15:27.85,1:15:29.45,Default,,0,0,0,,我如果让它一直这样进行下去\nDialogue: 0,1:15:29.69,1:15:31.77,Default,,0,0,0,,我在外层就会得到越来越多的F\nDialogue: 0,1:15:33.17,1:15:34.80,Default,,0,0,0,,我运行一个无用的循环\nDialogue: 0,1:15:35.20,1:15:37.02,Default,,0,0,0,,但内部是无用的并不重要\nDialogue: 0,1:15:39.85,1:15:47.85,Default,,0,0,0,,因此 我们有 (Y F)=(F (Y F))\nDialogue: 0,1:15:50.33,1:15:52.14,Default,,0,0,0,,Y组合子十分神奇\nDialogue: 0,1:15:53.85,1:15:56.25,Default,,0,0,0,,如果把它应用于某个函数\nDialogue: 0,1:15:57.37,1:16:00.38,Default,,0,0,0,,它就会返回这个函数的不动点\nDialogue: 0,1:16:01.69,1:16:04.25,Default,,0,0,0,,当然是在不动点存在的前提下\nDialogue: 0,1:16:07.91,1:16:10.08,Default,,0,0,0,,这是因为 如果我把(Y F)带入F\nDialogue: 0,1:16:10.12,1:16:11.12,Default,,0,0,0,,结果还是(Y F)\nDialogue: 0,1:16:16.24,1:16:18.86,Default,,0,0,0,,现在我想让你们在\nDialogue: 0,1:16:19.85,1:16:22.38,Default,,0,0,0,,EVAL-APPLY解释器方面思考一下\nDialogue: 0,1:16:23.86,1:16:26.27,Default,,0,0,0,,我在这里写了一大堆递归方程组\nDialogue: 0,1:16:28.54,1:16:30.22,Default,,0,0,0,,那些联立方程组像\nDialogue: 0,1:16:30.22,1:16:31.23,Default,,0,0,0,,这些方程一样联立起来\nDialogue: 0,1:16:31.47,1:16:33.31,Default,,0,0,0,,但EXPT不是联立方程\nDialogue: 0,1:16:33.31,1:16:35.79,Default,,0,0,0,,只是一个需要我赋义的变量\nDialogue: 0,1:16:38.15,1:16:40.76,Default,,0,0,0,,而Lisp则是某个过程的不动点\nDialogue: 0,1:16:40.81,1:16:42.57,Default,,0,0,0,,对这个过程来说 如果我知道Lisp的定义\nDialogue: 0,1:16:42.59,1:16:46.51,Default,,0,0,0,,然后在递归方程等号的右边\nDialogue: 0,1:16:46.59,1:16:49.79,Default,,0,0,0,,用它来代换EVAL、APPLY等变量\nDialogue: 0,1:16:50.94,1:16:53.96,Default,,0,0,0,,如果它是一个良好定义的Lisp的话\nDialogue: 0,1:16:54.36,1:16:56.30,Default,,0,0,0,,那么递归方程等号左边 也是一个良好定义的Lisp\nDialogue: 0,1:16:58.22,1:16:59.82,Default,,0,0,0,,这样 那个定义就讲得通了\nDialogue: 0,1:17:02.42,1:17:05.41,Default,,0,0,0,,不过是否有解却不太明显\nDialogue: 0,1:17:05.69,1:17:06.75,Default,,0,0,0,,我也说不清\nDialogue: 0,1:17:07.74,1:17:09.21,Default,,0,0,0,,现在我要介绍的论证\nDialogue: 0,1:17:09.26,1:17:10.27,Default,,0,0,0,,相当危险\nDialogue: 0,1:17:10.66,1:17:11.64,Default,,0,0,0,,具体看这里\nDialogue: 0,1:17:13.05,1:17:14.61,Default,,0,0,0,,这些是关于极限的论证\nDialogue: 0,1:17:14.61,1:17:15.39,Default,,0,0,0,,我们要讨论的极限\nDialogue: 0,1:17:15.45,1:17:17.68,Default,,0,0,0,,是微积分或者拓扑学的概念\nDialogue: 0,1:17:17.87,1:17:20.03,Default,,0,0,0,,或者说是类似的 数学分析中的概念\nDialogue: 0,1:17:20.76,1:17:23.38,Default,,0,0,0,,这个论证是你们都承认的\nDialogue: 0,1:17:23.38,1:17:25.29,Default,,0,0,0,,我想让你们意识到\nDialogue: 0,1:17:25.42,1:17:27.66,Default,,0,0,0,,我可以把你们耍得团团转\nDialogue: 0,1:17:28.86,1:17:30.48,Default,,0,0,0,,准备好了吗？ 这是什么？\nDialogue: 0,1:17:34.25,1:17:39.52,Default,,0,0,0,,u = 1 + 1/2 + 1/4 + .......\nDialogue: 0,1:17:39.74,1:17:41.32,Default,,0,0,0,,这是几何级数求和\nDialogue: 0,1:17:42.82,1:17:44.68,Default,,0,0,0,,当然 我也可以耍点小把戏\nDialogue: 0,1:17:44.82,1:17:47.57,Default,,0,0,0,,u - 1 = 1/2 + 1/4 + 1/8 ......\nDialogue: 0,1:17:51.90,1:17:54.46,Default,,0,0,0,,这里我可以\nDialogue: 0,1:17:56.09,1:17:57.93,Default,,0,0,0,,糟糕了 这里漏掉了括号\nDialogue: 0,1:17:58.92,1:18:01.45,Default,,0,0,0,,这里应该是\nDialogue: 0,1:18:01.74,1:18:03.99,Default,,0,0,0,,2(u - 1) = 1 + 1/2 + 1/4 + 1/8 ........\nDialogue: 0,1:18:07.57,1:18:08.54,Default,,0,0,0,,这里能修改一下吗？\nDialogue: 0,1:18:14.01,1:18:16.43,Default,,0,0,0,,哦 可以\nDialogue: 0,1:18:18.19,1:18:18.65,Default,,0,0,0,,看到了吗？\nDialogue: 0,1:18:19.52,1:18:20.64,Default,,0,0,0,,这样 我就得到\nDialogue: 0,1:18:23.53,1:18:26.64,Default,,0,0,0,,2(u - 1) = u\nDialogue: 0,1:18:27.80,1:18:29.58,Default,,0,0,0,,因此我们推断出 u=2\nDialogue: 0,1:18:30.30,1:18:31.37,Default,,0,0,0,,这是正确的\nDialogue: 0,1:18:31.96,1:18:33.32,Default,,0,0,0,,这个推理过程没有问题\nDialogue: 0,1:18:34.04,1:18:37.55,Default,,0,0,0,,但如果我要是做点别的什么呢？\nDialogue: 0,1:18:38.54,1:18:39.48,Default,,0,0,0,,假设我要求和的式子\nDialogue: 0,1:18:39.50,1:18:41.20,Default,,0,0,0,,明显没有和\nDialogue: 0,1:18:41.56,1:18:46.99,Default,,0,0,0,,v = 1 + 2 + 4 + ........\nDialogue: 0,1:18:47.39,1:18:51.39,Default,,0,0,0,,v - 1 = 2 + 4 + 8 + ......\nDialogue: 0,1:18:52.27,1:18:56.03,Default,,0,0,0,,(v - 1)/2 = v\nDialogue: 0,1:18:57.41,1:19:00.54,Default,,0,0,0,,这里我就可以推断出\nDialogue: 0,1:19:01.37,1:19:02.91,Default,,0,0,0,,显然这里又写错了\nDialogue: 0,1:19:03.07,1:19:04.51,Default,,0,0,0,,应该是 v = -1\nDialogue: 0,1:19:12.45,1:19:13.82,Default,,0,0,0,,这里应该是-1\nDialogue: 0,1:19:15.28,1:19:16.91,Default,,0,0,0,,这个结论明显是错误的\nDialogue: 0,1:19:22.00,1:19:23.47,Default,,0,0,0,,当你处理极限的时候\nDialogue: 0,1:19:24.22,1:19:27.85,Default,,0,0,0,,在某种方式下可行的论证\nDialogue: 0,1:19:29.42,1:19:30.75,Default,,0,0,0,,在其它情况下可能又不行了\nDialogue: 0,1:19:30.75,1:19:31.69,Default,,0,0,0,,要多加注意\nDialogue: 0,1:19:32.24,1:19:33.87,Default,,0,0,0,,参数必须具有良好的形式\nDialogue: 0,1:19:36.14,1:19:39.23,Default,,0,0,0,,但我不清楚 通常来说\nDialogue: 0,1:19:39.85,1:19:41.93,Default,,0,0,0,,像这样的论证有什么样的要求\nDialogue: 0,1:19:43.27,1:19:45.24,Default,,0,0,0,,我们要研习一大堆拓扑学文献来寻找答案\nDialogue: 0,1:19:46.27,1:19:48.64,Default,,0,0,0,,但是至少你们现在理解了\nDialogue: 0,1:19:49.10,1:19:51.13,Default,,0,0,0,,为什么我们在黑板上写的这些东西\nDialogue: 0,1:19:51.15,1:19:52.76,Default,,0,0,0,,是有一定语义的\nDialogue: 0,1:19:53.66,1:19:55.61,Default,,0,0,0,,你们也理解了它的语义\nDialogue: 0,1:19:56.48,1:19:58.35,Default,,0,0,0,,我想现在是时候\nDialogue: 0,1:19:59.07,1:20:03.84,Default,,0,0,0,,祝贺你们成为\nDialogue: 0,1:20:04.28,1:20:05.55,Default,,0,0,0,,神圣的递归秩序中的\nDialogue: 0,1:20:05.56,1:20:07.04,Default,,0,0,0,,一名LAMBDA演算黑客了\nDialogue: 0,1:20:08.84,1:20:10.17,Default,,0,0,0,,这是我们的徽章\nDialogue: 0,1:20:10.82,1:20:12.54,Default,,0,0,0,,因为你已经理解了\nDialogue: 0,1:20:13.40,1:20:15.20,Default,,0,0,0,,它上面的那句话\nDialogue: 0,1:20:16.89,1:20:18.41,Default,,0,0,0,,(Y F) = (F (Y F))\nDialogue: 0,1:20:21.04,1:20:21.66,Default,,0,0,0,,这节课讲完了\nDialogue: 0,1:20:21.85,1:20:22.75,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:20:24.71,1:20:25.15,Default,,0,0,0,,Lev 请说\nDialogue: 0,1:20:25.37,1:20:27.39,Default,,0,0,0,,学生：目前的状况来看\nDialogue: 0,1:20:27.40,1:20:30.22,Default,,0,0,0,,正如你指出的那样 我们不再需要DEFINE\nDialogue: 0,1:20:30.24,1:20:32.70,Default,,0,0,0,,不需要先存储一个值 以后再用\nDialogue: 0,1:20:32.99,1:20:33.32,Default,,0,0,0,,教授：对\nDialogue: 0,1:20:33.50,1:20:36.44,Default,,0,0,0,,学生：DEFINE在语言中好像有一些副作用\nDialogue: 0,1:20:36.49,1:20:38.52,Default,,0,0,0,,（听不清）并且依赖于时序\nDialogue: 0,1:20:39.30,1:20:42.06,Default,,0,0,0,,不用DEFINE 是否消除了副作用？\nDialogue: 0,1:20:42.28,1:20:44.68,Default,,0,0,0,,教授： 实际上\nDialogue: 0,1:20:44.88,1:20:46.44,Default,,0,0,0,,解释器并不是像这样实现的\nDialogue: 0,1:20:47.52,1:20:47.93,Default,,0,0,0,,明白了吧？\nDialogue: 0,1:20:48.92,1:20:53.15,Default,,0,0,0,,在实际的实现中 DEFINE这个运算\nDialogue: 0,1:20:53.18,1:20:55.53,Default,,0,0,0,,确实修改了环境\nDialogue: 0,1:20:57.95,1:21:02.33,Default,,0,0,0,,改变了执行DEFINE的那个框架\nDialogue: 0,1:21:03.69,1:21:06.51,Default,,0,0,0,,这样做是有很多原因的\nDialogue: 0,1:21:07.39,1:21:08.64,Default,,0,0,0,,其中之一就是\nDialogue: 0,1:21:08.67,1:21:10.09,Default,,0,0,0,,方便交互式系统\nDialogue: 0,1:21:11.34,1:21:14.12,Default,,0,0,0,,就是说 如果你构造了一个系统\nDialogue: 0,1:21:14.35,1:21:15.20,Default,,0,0,0,,而且你知道\nDialogue: 0,1:21:15.42,1:21:16.60,Default,,0,0,0,,你不打算进行调试\nDialogue: 0,1:21:16.60,1:21:17.55,Default,,0,0,0,,或之类的事儿\nDialogue: 0,1:21:17.84,1:21:20.72,Default,,0,0,0,,你想立马知道所有的东西\nDialogue: 0,1:21:20.75,1:21:21.24,Default,,0,0,0,,你想知道的是\nDialogue: 0,1:21:21.26,1:21:23.12,Default,,0,0,0,,方程组的最终解是什么？\nDialogue: 0,1:21:24.09,1:21:25.26,Default,,0,0,0,,然后系统返回你相应的值\nDialogue: 0,1:21:25.79,1:21:27.45,Default,,0,0,0,,但如果想要让系统变成交互式的\nDialogue: 0,1:21:27.45,1:21:28.75,Default,,0,0,0,,这样你可以在不影响其它部分的情况下\nDialogue: 0,1:21:28.76,1:21:31.68,Default,,0,0,0,,增量式地修改某一部分\nDialogue: 0,1:21:32.33,1:21:35.04,Default,,0,0,0,,没有DEFINE的话 就不能这么做了\nDialogue: 0,1:21:40.99,1:21:41.24,Default,,0,0,0,,你说\nDialogue: 0,1:21:42.30,1:21:44.25,Default,,0,0,0,,学生：就是那张“危险”的幻灯片\nDialogue: 0,1:21:44.65,1:21:47.13,Default,,0,0,0,,好像你举的两个例子\nDialogue: 0,1:21:47.16,1:21:49.07,Default,,0,0,0,,与其收敛与否有关系？\nDialogue: 0,1:21:49.18,1:21:49.56,Default,,0,0,0,,教授：是的\nDialogue: 0,1:21:50.30,1:21:52.62,Default,,0,0,0,,学生：函数理论中是否有\nDialogue: 0,1:21:52.76,1:21:54.68,Default,,0,0,0,,像线性系统\nDialogue: 0,1:21:54.72,1:21:56.60,Default,,0,0,0,,或者非线性系统中的\nDialogue: 0,1:21:57.74,1:21:59.00,Default,,0,0,0,,那种思考方式\nDialogue: 0,1:21:59.34,1:22:01.76,Default,,0,0,0,,函数的收敛性能否先验地知道\nDialogue: 0,1:22:02.35,1:22:05.53,Default,,0,0,0,,哪些属性可能被违反？\nDialogue: 0,1:22:05.79,1:22:06.57,Default,,0,0,0,,教授：我不知道\nDialogue: 0,1:22:07.68,1:22:10.09,Default,,0,0,0,,我也不知道它需要什么条件\nDialogue: 0,1:22:10.61,1:22:12.04,Default,,0,0,0,,我不知道怎么在一节课内\nDialogue: 0,1:22:12.52,1:22:14.73,Default,,0,0,0,,就给你们讲清楚\nDialogue: 0,1:22:16.91,1:22:18.48,Default,,0,0,0,,有什么条件来判别它们\nDialogue: 0,1:22:18.86,1:22:20.76,Default,,0,0,0,,是否收敛？\nDialogue: 0,1:22:22.86,1:22:23.31,Default,,0,0,0,,确实\nDialogue: 0,1:22:23.32,1:22:26.35,Default,,0,0,0,,这些都是为了告诉你 基于收敛的论证\nDialogue: 0,1:22:28.24,1:22:29.47,Default,,0,0,0,,都不可靠\nDialogue: 0,1:22:29.66,1:22:31.58,Default,,0,0,0,,如果你事先不知道收敛性的话\nDialogue: 0,1:22:32.81,1:22:34.20,Default,,0,0,0,,你可能做出错误的论证\nDialogue: 0,1:22:34.44,1:22:37.31,Default,,0,0,0,,你可以先假设知道了答案 然后进行演绎\nDialogue: 0,1:22:37.39,1:22:39.93,Default,,0,0,0,,看它会不会产生什么明显的矛盾\nDialogue: 0,1:22:40.97,1:22:42.28,Default,,0,0,0,,学生：我们是否可以说\nDialogue: 0,1:22:42.33,1:22:44.88,Default,,0,0,0,,如果数学表达式F收敛\nDialogue: 0,1:22:45.00,1:22:47.36,Default,,0,0,0,,那么它的递归性质就--\nDialogue: 0,1:22:47.58,1:22:51.29,Default,,0,0,0,,教授：我认为 在技术上有一类F\nDialogue: 0,1:22:52.12,1:22:54.22,Default,,0,0,0,,通过一些技术准则\nDialogue: 0,1:22:54.24,1:22:55.90,Default,,0,0,0,,我们可以找到这样的F\nDialogue: 0,1:22:55.98,1:23:01.31,Default,,0,0,0,,当你像这样迭代地应用它们时\nDialogue: 0,1:23:01.52,1:23:02.25,Default,,0,0,0,,它一定会收敛\nDialogue: 0,1:23:03.02,1:23:06.51,Default,,0,0,0,,这类准则包括：单调、连续\nDialogue: 0,1:23:07.32,1:23:07.95,Default,,0,0,0,,我想想\nDialogue: 0,1:23:08.38,1:23:09.37,Default,,0,0,0,,我把其它的准则忘了\nDialogue: 0,1:23:09.37,1:23:11.13,Default,,0,0,0,,还有一些列像这样的\nDialogue: 0,1:23:11.68,1:23:12.99,Default,,0,0,0,,判别准则\nDialogue: 0,1:23:13.43,1:23:16.00,Default,,0,0,0,,现在的难点是 给定F然后进行推理\nDialogue: 0,1:23:16.92,1:23:17.88,Default,,0,0,0,,这是F的定义\nDialogue: 0,1:23:18.17,1:23:19.66,Default,,0,0,0,,它满足这些准则吗？\nDialogue: 0,1:23:20.27,1:23:21.32,Default,,0,0,0,,这很难判断\nDialogue: 0,1:23:22.01,1:23:24.00,Default,,0,0,0,,那些准则都很简单得可以写下来\nDialogue: 0,1:23:24.58,1:23:26.32,Default,,0,0,0,,你可以看Joe Stoy写的一本书\nDialogue: 0,1:23:26.67,1:23:29.58,Default,,0,0,0,,那本书非常不错\nDialogue: 0,1:23:32.22,1:23:34.06,Default,,0,0,0,,叫做The Scott-Strachey\nDialogue: 0,1:23:34.49,1:23:38.46,Default,,0,0,0,,《指称语义：基于Scott-Strachey方法》\nDialogue: 0,1:23:39.55,1:23:40.76,Default,,0,0,0,,作者是Joe Stoy\nDialogue: 0,1:23:40.80,1:23:41.76,Default,,0,0,0,,由MIT出版社出版\nDialogue: 0,1:23:48.06,1:23:49.88,Default,,0,0,0,,他把这一方面讲得非常详细\nDialogue: 0,1:23:50.20,1:23:51.37,Default,,0,0,0,,绝对会让你吓一大跳\nDialogue: 0,1:23:55.05,1:23:56.19,Default,,0,0,0,,但是这本书仍然值得一读\nDialogue: 0,1:24:09.15,1:24:10.08,Default,,0,0,0,,好吧 谢谢大家\nDialogue: 0,1:24:11.49,1:24:12.99,Default,,0,0,0,,这节课到此为止\nDialogue: 0,1:24:14.17,1:24:34.60,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:24:14.17,1:24:34.49,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec7a.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 621\nActive Line: 629\nVideo Position: 66176\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.03,0:00:01.28,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:01.39,0:00:08.09,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N张大伟\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.39,0:00:08.09,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:08.94,0:00:12.59,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 I\nDialogue: 0,0:00:15.79,0:00:17.32,Default,,0,0,0,,教授：今天我们将学习一些\nDialogue: 0,0:00:17.52,0:00:18.41,Default,,0,0,0,,非同一般的东西\nDialogue: 0,0:00:19.20,0:00:21.88,Default,,0,0,0,,我们将对计算机程序\nDialogue: 0,0:00:22.59,0:00:25.21,Default,,0,0,0,,有更深层次的理解\nDialogue: 0,0:00:26.80,0:00:29.12,Default,,0,0,0,,目前为止 我们一直把程序看作\nDialogue: 0,0:00:29.26,0:00:32.09,Default,,0,0,0,,对机器的描述\nDialogue: 0,0:00:32.72,0:00:37.21,Default,,0,0,0,,举个例子 在这个幻灯片上\nDialogue: 0,0:00:37.93,0:00:41.77,Default,,0,0,0,,我们可以看到一个计算阶乘的程序\nDialogue: 0,0:00:42.80,0:00:47.31,Default,,0,0,0,,当然 你可以认为这些字符串描述了\nDialogue: 0,0:00:47.66,0:00:51.98,Default,,0,0,0,,这个线路图所表示的无穷机器\nDialogue: 0,0:00:52.49,0:00:54.80,Default,,0,0,0,,我们可以稍稍地看下 它描述的是什么\nDialogue: 0,0:00:55.13,0:00:58.20,Default,,0,0,0,,这种紧凑的记法 描述的是：\nDialogue: 0,0:00:58.54,0:01:00.17,Default,,0,0,0,,如果N是0 结果就是1\nDialogue: 0,0:01:00.17,0:01:02.00,Default,,0,0,0,,N是从这里进入机器的\nDialogue: 0,0:01:02.33,0:01:03.52,Default,,0,0,0,,如果它是0的话\nDialogue: 0,0:01:03.74,0:01:05.20,Default,,0,0,0,,那么我就控制这个开关\nDialogue: 0,0:01:05.47,0:01:08.20,Default,,0,0,0,,把它掰到输出为1的那一端\nDialogue: 0,0:01:09.34,0:01:10.08,Default,,0,0,0,,否则的话\nDialogue: 0,0:01:10.38,0:01:12.83,Default,,0,0,0,,就是(* N (FACT (- N 1)))\nDialogue: 0,0:01:12.97,0:01:15.13,Default,,0,0,0,,我先计算(FACT (- N 1))\nDialogue: 0,0:01:15.29,0:01:16.68,Default,,0,0,0,,再把结果乘以N\nDialogue: 0,0:01:16.84,0:01:18.91,Default,,0,0,0,,这样如果N不为0的话\nDialogue: 0,0:01:18.91,0:01:20.60,Default,,0,0,0,,这个开关就会输出这里的结果\nDialogue: 0,0:01:21.90,0:01:22.32,Default,,0,0,0,,当然了\nDialogue: 0,0:01:22.36,0:01:25.13,Default,,0,0,0,,这个机器可能有无穷多个部件\nDialogue: 0,0:01:25.48,0:01:28.12,Default,,0,0,0,,因为FACT内部又调用了FACT\nDialogue: 0,0:01:28.43,0:01:30.17,Default,,0,0,0,,因此我们不知道调用栈有多深\nDialogue: 0,0:01:31.07,0:01:33.55,Default,,0,0,0,,但到目前为止\nDialogue: 0,0:01:34.22,0:01:37.69,Default,,0,0,0,,代码对我们来说就是这样的东西了\nDialogue: 0,0:01:38.31,0:01:40.59,Default,,0,0,0,,你可以认为代码是用字符串来描述\nDialogue: 0,0:01:41.28,0:01:44.16,Default,,0,0,0,,某种用其它方式描画的线路图\nDialogue: 0,0:01:44.90,0:01:46.60,Default,,0,0,0,,事实上 很多人都向我提议\nDialogue: 0,0:01:46.84,0:01:49.04,Default,,0,0,0,,说程序设计语言应该像这个一样 是图像化的\nDialogue: 0,0:01:49.49,0:01:51.80,Default,,0,0,0,,不过我不认为用图形表示会有很多优势\nDialogue: 0,0:01:52.00,0:01:53.79,Default,,0,0,0,,当然 最主要的劣势就是\nDialogue: 0,0:01:53.80,0:01:55.63,Default,,0,0,0,,它需要占用很大的平面空间\nDialogue: 0,0:01:55.96,0:01:59.95,Default,,0,0,0,,所以展示和修改起来就非常麻烦\nDialogue: 0,0:02:01.34,0:02:02.16,Default,,0,0,0,,但是不管怎样\nDialogue: 0,0:02:03.58,0:02:05.15,Default,,0,0,0,,在计算的世界中\nDialogue: 0,0:02:05.18,0:02:07.05,Default,,0,0,0,,还有一个非常重要的东西\nDialogue: 0,0:02:07.64,0:02:10.64,Default,,0,0,0,,也就是所谓的“通用机器”\nDialogue: 0,0:02:10.73,0:02:15.24,Default,,0,0,0,,我们再来看第二张幻灯片\nDialogue: 0,0:02:16.04,0:02:17.18,Default,,0,0,0,,我们看到的就是\nDialogue: 0,0:02:18.14,0:02:19.88,Default,,0,0,0,,名为EVAL的特殊机器\nDialogue: 0,0:02:21.26,0:02:22.86,Default,,0,0,0,,这个叫做EVAL的机器\nDialogue: 0,0:02:22.88,0:02:24.24,Default,,0,0,0,,也就是我今天要讲解的\nDialogue: 0,0:02:25.82,0:02:26.67,Default,,0,0,0,,它非常简单\nDialogue: 0,0:02:27.78,0:02:30.80,Default,,0,0,0,,最了不起的是 它简单得可以写在黑板上\nDialogue: 0,0:02:33.35,0:02:35.79,Default,,0,0,0,,然而 EVAL这个机器\nDialogue: 0,0:02:36.00,0:02:39.84,Default,,0,0,0,,是以其它机器的描述作为输入的\nDialogue: 0,0:02:40.45,0:02:42.12,Default,,0,0,0,,它可以接收一个\nDialogue: 0,0:02:42.40,0:02:45.58,Default,,0,0,0,,阶乘机器的线路图作为输入\nDialogue: 0,0:02:46.49,0:02:47.66,Default,,0,0,0,,这样一来\nDialogue: 0,0:02:48.49,0:02:52.57,Default,,0,0,0,,它就可以模拟那台阶乘机器\nDialogue: 0,0:02:53.13,0:02:53.79,Default,,0,0,0,,这样的话\nDialogue: 0,0:02:54.16,0:02:56.36,Default,,0,0,0,,如果输入6 就会得到720\nDialogue: 0,0:02:58.91,0:03:01.68,Default,,0,0,0,,这是一个非常了不起的机器\nDialogue: 0,0:03:02.13,0:03:03.58,Default,,0,0,0,,而最让人惊奇的是\nDialogue: 0,0:03:03.77,0:03:05.13,Default,,0,0,0,,它竟然可以写在一个黑板内\nDialogue: 0,0:03:05.59,0:03:06.65,Default,,0,0,0,,与之相反的是\nDialogue: 0,0:03:07.32,0:03:10.44,Default,,0,0,0,,我们可以想象一下模拟电子世界中的\nDialogue: 0,0:03:11.55,0:03:12.86,Default,,0,0,0,,一台非常不同的机器\nDialogue: 0,0:03:14.57,0:03:16.33,Default,,0,0,0,,这台机器呢\nDialogue: 0,0:03:16.52,0:03:18.81,Default,,0,0,0,,某种意义上 同样也是“通用机器”\nDialogue: 0,0:03:19.26,0:03:23.12,Default,,0,0,0,,只要你输入一个电路图\nDialogue: 0,0:03:23.82,0:03:25.74,Default,,0,0,0,,比如这个小型的低通滤波器\nDialogue: 0,0:03:26.01,0:03:27.48,Default,,0,0,0,,单极低通滤波器之类的\nDialogue: 0,0:03:28.05,0:03:29.53,Default,,0,0,0,,你可以想像\nDialogue: 0,0:03:29.71,0:03:33.15,Default,,0,0,0,,如果我们扫描这个元件得到扫描线\nDialogue: 0,0:03:34.43,0:03:37.13,Default,,0,0,0,,得到的信号描述的就是\nDialogue: 0,0:03:37.39,0:03:40.40,Default,,0,0,0,,这个机器所模拟的\nDialogue: 0,0:03:40.78,0:03:43.39,Default,,0,0,0,,这个模拟机器EVAL是由电路构成\nDialogue: 0,0:03:43.68,0:03:45.15,Default,,0,0,0,,它可以把自己配置成一个滤波器\nDialogue: 0,0:03:45.18,0:03:48.04,Default,,0,0,0,,响应由电路图指定的频率\nDialogue: 0,0:03:49.89,0:03:51.48,Default,,0,0,0,,这种机器很难制造出来\nDialogue: 0,0:03:51.61,0:03:54.06,Default,,0,0,0,,当然 更不可能用一个黑板就把它说清楚\nDialogue: 0,0:03:55.67,0:03:57.58,Default,,0,0,0,,所以今天我们将学习一些神奇的东西\nDialogue: 0,0:03:58.43,0:04:00.81,Default,,0,0,0,,我们将在黑板上见证\nDialogue: 0,0:04:01.16,0:04:02.49,Default,,0,0,0,,通用机器\nDialogue: 0,0:04:02.79,0:04:04.41,Default,,0,0,0,,跟其它程序比起来\nDialogue: 0,0:04:04.52,0:04:05.80,Default,,0,0,0,,它真是非常简单\nDialogue: 0,0:04:06.78,0:04:08.75,Default,,0,0,0,,现在 我们已经非常接近\nDialogue: 0,0:04:09.08,0:04:10.97,Default,,0,0,0,,计算机中真正的精灵了\nDialogue: 0,0:04:11.28,0:04:14.62,Default,,0,0,0,,所以为了保持足够的尊重\nDialogue: 0,0:04:15.18,0:04:17.32,Default,,0,0,0,,我特地穿上外套\nDialogue: 0,0:04:17.52,0:04:19.29,Default,,0,0,0,,你们应该从没见我穿过\nDialogue: 0,0:04:20.47,0:04:22.73,Default,,0,0,0,,在这个盛重的场合\nDialogue: 0,0:04:23.55,0:04:26.70,Default,,0,0,0,,我还得戴上一顶合适的帽子\nDialogue: 0,0:04:28.78,0:04:31.44,Default,,0,0,0,,开讲前再给大家提个醒\nDialogue: 0,0:04:34.14,0:04:36.91,Default,,0,0,0,,那些40岁以下\nDialogue: 0,0:04:37.16,0:04:38.49,Default,,0,0,0,,以及没有孩子的人\nDialogue: 0,0:04:38.67,0:04:40.49,Default,,0,0,0,,你们可要小心了\nDialogue: 0,0:04:40.49,0:04:41.96,Default,,0,0,0,,如果真的受不了 可以选择离开\nDialogue: 0,0:04:43.34,0:04:45.56,Default,,0,0,0,,因为一会儿要发生一些\nDialogue: 0,0:04:45.72,0:04:47.13,Default,,0,0,0,,非常神秘的事情\nDialogue: 0,0:04:47.74,0:04:51.05,Default,,0,0,0,,可能使你的大脑异常混乱\nDialogue: 0,0:04:51.82,0:04:54.28,Default,,0,0,0,,好了 无论如何\nDialogue: 0,0:04:55.71,0:05:01.10,Default,,0,0,0,,我要带着你们写一个Lisp求值器\nDialogue: 0,0:05:02.51,0:05:04.28,Default,,0,0,0,,求值器并不复杂\nDialogue: 0,0:05:05.02,0:05:07.63,Default,,0,0,0,,很像我们以前见到过的程序\nDialogue: 0,0:05:08.24,0:05:09.48,Default,,0,0,0,,这也是它令人吃惊的地方\nDialogue: 0,0:05:10.86,0:05:13.10,Default,,0,0,0,,现在我开始写这个程序\nDialogue: 0,0:05:15.28,0:05:16.62,Default,,0,0,0,,我把这个程序叫做EVAL\nDialogue: 0,0:05:22.90,0:05:26.24,Default,,0,0,0,,这个过程接收两个参数\nDialogue: 0,0:05:26.28,0:05:29.44,Default,,0,0,0,,表达式EXP和环境ENV\nDialogue: 0,0:05:31.86,0:05:33.79,Default,,0,0,0,,跟所有实用过程一样\nDialogue: 0,0:05:34.01,0:05:35.13,Default,,0,0,0,,它是个“按情况分析”语句\nDialogue: 0,0:05:40.46,0:05:41.87,Default,,0,0,0,,但是在我开始之前\nDialogue: 0,0:05:42.52,0:05:43.90,Default,,0,0,0,,我还想你们注意一下\nDialogue: 0,0:05:44.44,0:05:46.06,Default,,0,0,0,,我将要在黑板上写的程序\nDialogue: 0,0:05:46.56,0:05:50.24,Default,,0,0,0,,非常丑陋、混乱、令人作呕\nDialogue: 0,0:05:50.94,0:05:53.16,Default,,0,0,0,,并不是一种专业的写法\nDialogue: 0,0:05:54.32,0:05:56.57,Default,,0,0,0,,它是用具体语法写就的\nDialogue: 0,0:05:57.24,0:05:58.83,Default,,0,0,0,,也就是说用了很多CAR、CDR\nDialogue: 0,0:05:58.84,0:06:00.62,Default,,0,0,0,,我之前告诉过你们这样写并不好\nDialogue: 0,0:06:02.94,0:06:05.61,Default,,0,0,0,,在这里是故意这样来写的\nDialogue: 0,0:06:06.11,0:06:09.02,Default,,0,0,0,,因为我想让它尽量精简\nDialogue: 0,0:06:09.34,0:06:10.40,Default,,0,0,0,,能塞在黑板内\nDialogue: 0,0:06:10.43,0:06:11.85,Default,,0,0,0,,你们就可以看到整个代码\nDialogue: 0,0:06:12.42,0:06:14.80,Default,,0,0,0,,我就不像平时那样实用长变量名了\nDialogue: 0,0:06:15.60,0:06:17.29,Default,,0,0,0,,就用CAR、CDR 因为它们短小\nDialogue: 0,0:06:18.06,0:06:20.78,Default,,0,0,0,,这算是一种取舍\nDialogue: 0,0:06:20.89,0:06:22.81,Default,,0,0,0,,我不希望你们这样来写程序\nDialogue: 0,0:06:23.57,0:06:25.08,Default,,0,0,0,,这里单纯地想达到一种简洁的效果\nDialogue: 0,0:06:25.85,0:06:27.61,Default,,0,0,0,,因此你们读起来可能有些费力\nDialogue: 0,0:06:27.77,0:06:30.19,Default,,0,0,0,,我尽量写得清楚一些\nDialogue: 0,0:06:31.27,0:06:34.40,Default,,0,0,0,,这个解释器已经比较完整了\nDialogue: 0,0:06:34.51,0:06:36.24,Default,,0,0,0,,但是还是缺少一些功能\nDialogue: 0,0:06:36.25,0:06:38.60,Default,,0,0,0,,我就不写定义和赋值的部分了\nDialogue: 0,0:06:39.10,0:06:42.41,Default,,0,0,0,,因为它们都不是最本质的\nDialogue: 0,0:06:42.88,0:06:46.46,Default,,0,0,0,,稍后我就会解释 这是数学上的原因\nDialogue: 0,0:06:46.92,0:06:49.96,Default,,0,0,0,,当然啦 黑板也没有那么大\nDialogue: 0,0:06:51.88,0:06:53.64,Default,,0,0,0,,但是 我们怎么做呢？\nDialogue: 0,0:06:53.95,0:06:55.66,Default,,0,0,0,,我们需要一个分派\nDialogue: 0,0:06:56.09,0:06:57.90,Default,,0,0,0,,它根据表达式的类型\nDialogue: 0,0:06:58.28,0:07:00.38,Default,,0,0,0,,把它们划分为几类\nDialogue: 0,0:07:01.72,0:07:03.26,Default,,0,0,0,,这就是现在要做的\nDialogue: 0,0:07:03.82,0:07:05.15,Default,,0,0,0,,我们都有哪些表达式？\nDialogue: 0,0:07:05.15,0:07:06.36,Default,,0,0,0,,我们先来看几种表达式\nDialogue: 0,0:07:06.81,0:07:09.60,Default,,0,0,0,,比如说 数字“3”就是一个表达式\nDialogue: 0,0:07:10.42,0:07:11.58,Default,,0,0,0,,我想让它代表什么呢？\nDialogue: 0,0:07:12.72,0:07:14.75,Default,,0,0,0,,我有很多选择 但是就现在而言\nDialogue: 0,0:07:15.05,0:07:16.20,Default,,0,0,0,,我就想让它表示数字3\nDialogue: 0,0:07:17.05,0:07:17.88,Default,,0,0,0,,这就是我要的\nDialogue: 0,0:07:18.72,0:07:19.69,Default,,0,0,0,,这个足够简单\nDialogue: 0,0:07:20.03,0:07:22.91,Default,,0,0,0,,那就意味着 如果表达式是数字\nDialogue: 0,0:07:27.29,0:07:31.68,Default,,0,0,0,,表达式本身就应该是求值结果\nDialogue: 0,0:07:35.42,0:07:36.76,Default,,0,0,0,,另外一种情况是\nDialogue: 0,0:07:36.89,0:07:38.86,Default,,0,0,0,,表达式还可能是符号\nDialogue: 0,0:07:39.39,0:07:46.75,Default,,0,0,0,,比如EXP、ENV、EVAL、NUMBER、X之类\nDialogue: 0,0:07:48.01,0:07:49.18,Default,,0,0,0,,它们意味着什么？\nDialogue: 0,0:07:50.16,0:07:51.63,Default,,0,0,0,,它们是一类代表其它事物的事物\nDialogue: 0,0:07:51.63,0:07:53.23,Default,,0,0,0,,也就是我们语言中所谓的变量\nDialogue: 0,0:07:54.77,0:07:56.88,Default,,0,0,0,,因此我想要能够 比如说\nDialogue: 0,0:07:57.05,0:08:01.04,Default,,0,0,0,,对X求值 可能会得到3\nDialogue: 0,0:08:02.64,0:08:05.76,Default,,0,0,0,,又可能是CAR\nDialogue: 0,0:08:07.76,0:08:09.40,Default,,0,0,0,,我希望它的值是\nDialogue: 0,0:08:09.63,0:08:11.34,Default,,0,0,0,,某种类似于过程的东西\nDialogue: 0,0:08:16.51,0:08:18.43,Default,,0,0,0,,我不需要知道它内部是什么\nDialogue: 0,0:08:18.64,0:08:21.15,Default,,0,0,0,,可能是一些机器码 或者类似的东西\nDialogue: 0,0:08:22.84,0:08:24.27,Default,,0,0,0,,到这是还是相对简单的\nDialogue: 0,0:08:24.43,0:08:26.89,Default,,0,0,0,,我想把这部分交给其他人来写\nDialogue: 0,0:08:27.80,0:08:28.89,Default,,0,0,0,,如果我们有一个符号\nDialogue: 0,0:08:30.80,0:08:32.48,Default,,0,0,0,,假如表达式是符号\nDialogue: 0,0:08:33.42,0:08:34.88,Default,,0,0,0,,那么我求值它的结果就应该是\nDialogue: 0,0:08:34.91,0:08:40.24,Default,,0,0,0,,在环境ENV中查找该表达式的值\nDialogue: 0,0:08:46.48,0:08:48.99,Default,,0,0,0,,环境是一个字典\nDialogue: 0,0:08:49.96,0:08:54.06,Default,,0,0,0,,它把符号映射成一个值\nDialogue: 0,0:08:54.28,0:08:55.16,Default,,0,0,0,,就这么简单\nDialogue: 0,0:08:56.28,0:08:57.20,Default,,0,0,0,,怎么完成的呢？\nDialogue: 0,0:08:57.53,0:08:58.52,Default,,0,0,0,,稍后我们再谈这个\nDialogue: 0,0:08:59.68,0:09:00.57,Default,,0,0,0,,其实并不难\nDialogue: 0,0:09:01.67,0:09:04.28,Default,,0,0,0,,编写类似于表的数据结构非常容易\nDialogue: 0,0:09:04.84,0:09:05.74,Default,,0,0,0,,但它只是一个表\nDialogue: 0,0:09:05.77,0:09:07.56,Default,,0,0,0,,而这是存取某个表的过程\nDialogue: 0,0:09:09.55,0:09:10.81,Default,,0,0,0,,好的 接下来\nDialogue: 0,0:09:11.31,0:09:12.56,Default,,0,0,0,,另一类表达式\nDialogue: 0,0:09:12.67,0:09:15.56,Default,,0,0,0,,表达式可能是一些不是数字的常量\nDialogue: 0,0:09:16.06,0:09:17.43,Default,,0,0,0,,比如 'FOO\nDialogue: 0,0:09:20.17,0:09:21.29,Default,,0,0,0,,为了方便起见\nDialogue: 0,0:09:21.31,0:09:23.36,Default,,0,0,0,,我想在语法上\nDialogue: 0,0:09:24.73,0:09:26.80,Default,,0,0,0,,把它转换成表结构\nDialogue: 0,0:09:26.84,0:09:31.52,Default,,0,0,0,,比如说是(QUOTE FOO)\nDialogue: 0,0:09:33.72,0:09:37.18,Default,,0,0,0,,一个被引用起来的对象 无论它是什么\nDialogue: 0,0:09:38.35,0:09:40.83,Default,,0,0,0,,都实际上是一个缩写\nDialogue: 0,0:09:41.04,0:09:42.59,Default,,0,0,0,,这一部分并不由求值器负责\nDialogue: 0,0:09:43.21,0:09:44.46,Default,,0,0,0,,这是在其它地方完成的\nDialogue: 0,0:09:44.75,0:09:47.79,Default,,0,0,0,,左边的符号就是右边表达式的缩略形式\nDialogue: 0,0:09:48.78,0:09:50.48,Default,,0,0,0,,这样 我就可以\nDialogue: 0,0:09:50.57,0:09:53.12,Default,,0,0,0,,依据表达式的CAR部分\nDialogue: 0,0:09:53.31,0:09:55.95,Default,,0,0,0,,来判断它的类型了\nDialogue: 0,0:09:58.46,0:10:01.08,Default,,0,0,0,,因此这一部分也不会出现在求值器中\nDialogue: 0,0:10:01.65,0:10:02.68,Default,,0,0,0,,这在更早时候\nDialogue: 0,0:10:02.70,0:10:03.96,Default,,0,0,0,,比如源代码读取阶段完成\nDialogue: 0,0:10:05.54,0:10:15.04,Default,,0,0,0,,如果是引用表达式\nDialogue: 0,0:10:18.27,0:10:19.10,Default,,0,0,0,,那么求值的结果就是\nDialogue: 0,0:10:19.63,0:10:25.13,Default,,0,0,0,,我想让(QUOTE FOO)求值为自身FOO\nDialogue: 0,0:10:25.14,0:10:25.95,Default,,0,0,0,,一个常量\nDialogue: 0,0:10:27.53,0:10:28.92,Default,,0,0,0,,这条代码是说\nDialogue: 0,0:10:29.08,0:10:30.73,Default,,0,0,0,,这类表达式求值为它自己\nDialogue: 0,0:10:31.79,0:10:33.66,Default,,0,0,0,,怎么才能把它取出来呢？\nDialogue: 0,0:10:33.66,0:10:36.36,Default,,0,0,0,,这是列表第二个元素的第一个部分\nDialogue: 0,0:10:36.59,0:10:37.58,Default,,0,0,0,,也就是表的第二个元素\nDialogue: 0,0:10:38.49,0:10:40.32,Default,,0,0,0,,也就是CADR\nDialogue: 0,0:10:41.28,0:10:42.38,Default,,0,0,0,,所以这里我就写CADR\nDialogue: 0,0:10:51.08,0:10:52.35,Default,,0,0,0,,表达式还可能是什么类型呢？\nDialogue: 0,0:10:52.51,0:10:53.80,Default,,0,0,0,,还有LAMBDA表达式\nDialogue: 0,0:10:55.00,0:11:03.29,Default,,0,0,0,,比如 (LAMBDA (X) (+ X Y))\nDialogue: 0,0:11:04.16,0:11:06.33,Default,,0,0,0,,我还得找到某种表示方法\nDialogue: 0,0:11:06.33,0:11:07.85,Default,,0,0,0,,LAMBDA表达式求值的结果\nDialogue: 0,0:11:08.11,0:11:09.08,Default,,0,0,0,,也就是如何表示过程\nDialogue: 0,0:11:09.60,0:11:12.62,Default,,0,0,0,,过程并不就是表达式(LAMBDA (x))\nDialogue: 0,0:11:13.13,0:11:15.56,Default,,0,0,0,,表达式只是过程的代码描述\nDialogue: 0,0:11:16.41,0:11:18.33,Default,,0,0,0,,如果在词法作用域的语言中实现过程\nDialogue: 0,0:11:18.56,0:11:21.20,Default,,0,0,0,,那么我希望在表示过程的时候\nDialogue: 0,0:11:23.23,0:11:25.36,Default,,0,0,0,,能够把当前的求值环境包括进来\nDialogue: 0,0:11:25.84,0:11:29.07,Default,,0,0,0,,所以这里我还需要\nDialogue: 0,0:11:29.20,0:11:30.67,Default,,0,0,0,,一些类型标志\nDialogue: 0,0:11:30.70,0:11:33.90,Default,,0,0,0,,这样后面我就可以用它们来区分过程\nDialogue: 0,0:11:34.30,0:11:36.59,Default,,0,0,0,,看哪些是由LAMBDA表达式生成的\nDialogue: 0,0:11:36.81,0:11:38.03,Default,,0,0,0,,哪些是基本过程\nDialogue: 0,0:11:39.06,0:11:41.96,Default,,0,0,0,,所以这里是个类型标志\nDialogue: 0,0:11:41.98,0:11:43.56,Default,,0,0,0,,出于历史原因\nDialogue: 0,0:11:43.56,0:11:45.10,Default,,0,0,0,,我用CLOSURE作为类型标志\nDialogue: 0,0:11:47.68,0:11:49.60,Default,,0,0,0,,现在来看看 哪部分比较重要\nDialogue: 0,0:11:49.92,0:11:51.12,Default,,0,0,0,,我需要知道\nDialogue: 0,0:11:51.24,0:11:52.92,Default,,0,0,0,,绑定变量表和过程的体\nDialogue: 0,0:11:54.22,0:11:55.40,Default,,0,0,0,,这是它的CDR部分\nDialogue: 0,0:11:56.09,0:12:01.85,Default,,0,0,0,,这里就是((X) (+ X Y))\nDialogue: 0,0:12:03.04,0:12:03.87,Default,,0,0,0,,以及某个环境<ENV>\nDialogue: 0,0:12:08.17,0:12:12.20,Default,,0,0,0,,用户不应该看到这个东西\nDialogue: 0,0:12:13.53,0:12:16.19,Default,,0,0,0,,这只是过程对象的\nDialogue: 0,0:12:16.76,0:12:18.30,Default,,0,0,0,,一种内部表示\nDialogue: 0,0:12:18.52,0:12:20.52,Default,,0,0,0,,它包括绑定变量表\nDialogue: 0,0:12:20.70,0:12:22.62,Default,,0,0,0,,过程的体和某个环境\nDialogue: 0,0:12:23.53,0:12:25.80,Default,,0,0,0,,以及一个类型标签 表示这是一个过程\nDialogue: 0,0:12:26.34,0:12:27.37,Default,,0,0,0,,接下来写代码\nDialogue: 0,0:12:28.08,0:12:38.72,Default,,0,0,0,,如果表达式的CAR部分是'LAMBDA\nDialogue: 0,0:12:43.47,0:12:44.81,Default,,0,0,0,,这里 我就要\nDialogue: 0,0:12:45.64,0:12:51.84,Default,,0,0,0,,创建一个表 表头是'CLOSURE\nDialogue: 0,0:12:55.15,0:13:00.73,Default,,0,0,0,,接着是 过程代码的CDR部分\nDialogue: 0,0:13:01.56,0:13:02.97,Default,,0,0,0,,也就是除开LAMBDA的其它部分\nDialogue: 0,0:13:07.74,0:13:08.86,Default,,0,0,0,,以及当前的环境\nDialogue: 0,0:13:10.25,0:13:15.32,Default,,0,0,0,,这样就实现了环境模型中的那些规则\nDialogue: 0,0:13:15.45,0:13:18.52,Default,,0,0,0,,这是从LAMBDA表达式中构建过程所必须遵守的\nDialogue: 0,0:13:19.40,0:13:20.97,Default,,0,0,0,,那个求值器在遇到\nDialogue: 0,0:13:21.48,0:13:24.32,Default,,0,0,0,,LAMBDA表达式时的环境\nDialogue: 0,0:13:25.04,0:13:28.46,Default,,0,0,0,,在过程运行的时候\nDialogue: 0,0:13:28.68,0:13:31.77,Default,,0,0,0,,会去这个环境中查找自由变量的值\nDialogue: 0,0:13:34.72,0:13:35.82,Default,,0,0,0,,所以需要把它囊括进来\nDialogue: 0,0:13:35.92,0:13:37.55,Default,,0,0,0,,因此我们必须把求值时的环境\nDialogue: 0,0:13:37.56,0:13:38.86,Default,,0,0,0,,作为过程对象的一部分\nDialogue: 0,0:13:39.21,0:13:40.62,Default,,0,0,0,,之后再来看它的作用\nDialogue: 0,0:13:42.03,0:13:43.77,Default,,0,0,0,,我们也有COND表达式\nDialogue: 0,0:13:44.59,0:13:52.81,Default,,0,0,0,,像是(COND (P1 E1) (P2 E2) ...)这样的\nDialogue: 0,0:13:54.40,0:13:56.09,Default,,0,0,0,,P1是谓词\nDialogue: 0,0:13:56.35,0:13:58.43,Default,,0,0,0,,谓词总是返回TRUE或者FALSE\nDialogue: 0,0:13:58.99,0:14:01.76,Default,,0,0,0,,如果谓词P1为真时 表达式E1才被求值\nDialogue: 0,0:14:03.44,0:14:06.08,Default,,0,0,0,,当然 你也可以列这么一组子句\nDialogue: 0,0:14:06.79,0:14:09.36,Default,,0,0,0,,我会把它封装在另一个过程中\nDialogue: 0,0:14:09.36,0:14:11.56,Default,,0,0,0,,我们稍后在那个过程中进行处理\nDialogue: 0,0:14:12.42,0:14:21.28,Default,,0,0,0,,如果表达式的CAR部分是'COND的话\nDialogue: 0,0:14:24.00,0:14:26.84,Default,,0,0,0,,那么我就用EVCOND来求值这个表达式\nDialogue: 0,0:14:30.20,0:14:31.42,Default,,0,0,0,,求值表达式的CDR部分\nDialogue: 0,0:14:34.40,0:14:38.49,Default,,0,0,0,,记得带上环境\nDialogue: 0,0:14:41.43,0:14:42.60,Default,,0,0,0,,好的 还有一种情况\nDialogue: 0,0:14:44.09,0:14:48.22,Default,,0,0,0,,任意的像(+ X 3)这样的表达式\nDialogue: 0,0:14:50.62,0:14:53.95,Default,,0,0,0,,这是把运算符应用在运算对象上\nDialogue: 0,0:14:55.13,0:14:56.59,Default,,0,0,0,,这并没有什么特殊的\nDialogue: 0,0:14:56.59,0:14:59.63,Default,,0,0,0,,就是说 它不属于这里的特殊形式\nDialogue: 0,0:14:59.85,0:15:01.42,Default,,0,0,0,,上面写的这些都是特殊形式\nDialogue: 0,0:15:09.65,0:15:12.12,Default,,0,0,0,,再说明一下 如果我要把这个程序写得专业一点\nDialogue: 0,0:15:12.36,0:15:14.17,Default,,0,0,0,,我会把它设计成数据导向的\nDialogue: 0,0:15:14.48,0:15:16.52,Default,,0,0,0,,那样的话 这里就不会是一系列的条件判断\nDialogue: 0,0:15:16.65,0:15:18.20,Default,,0,0,0,,而是根据一些比特位来做分派\nDialogue: 0,0:15:19.42,0:15:22.25,Default,,0,0,0,,这样来设计会更加专业一些\nDialogue: 0,0:15:22.36,0:15:24.14,Default,,0,0,0,,并且 我不用大量修改程序\nDialogue: 0,0:15:24.68,0:15:26.38,Default,,0,0,0,,就可以添加规则\nDialogue: 0,0:15:26.71,0:15:28.46,Default,,0,0,0,,这样来做可能运行得更快\nDialogue: 0,0:15:29.04,0:15:30.43,Default,,0,0,0,,但这里我并不打算这么做\nDialogue: 0,0:15:31.28,0:15:33.98,Default,,0,0,0,,现在的目的是把握EVAL过程的整体\nDialogue: 0,0:15:35.07,0:15:35.80,Default,,0,0,0,,那么 最后一种情况\nDialogue: 0,0:15:37.69,0:15:38.56,Default,,0,0,0,,要怎么做呢？\nDialogue: 0,0:15:38.56,0:15:41.23,Default,,0,0,0,,在这种情况下 我需要进行加法运算\nDialogue: 0,0:15:44.35,0:15:46.16,Default,,0,0,0,,那么我就得搞清楚 '+到底是什么\nDialogue: 0,0:15:46.84,0:15:49.29,Default,,0,0,0,,我还得知道X和3又代表什么\nDialogue: 0,0:15:50.55,0:15:53.96,Default,,0,0,0,,然后再把'+的所代表的东西\nDialogue: 0,0:15:54.43,0:15:57.00,Default,,0,0,0,,应用于'X与3所代表的东西上\nDialogue: 0,0:15:58.11,0:15:59.39,Default,,0,0,0,,具体来写一下\nDialogue: 0,0:15:59.87,0:16:09.55,Default,,0,0,0,,我要把表达式CAR部分的求值结果\nDialogue: 0,0:16:11.20,0:16:12.14,Default,,0,0,0,,应用在\nDialogue: 0,0:16:13.21,0:16:15.50,Default,,0,0,0,,表达式的CAR部分就是运算符\nDialogue: 0,0:16:17.20,0:16:18.51,Default,,0,0,0,,要在给定的环境中进行\nDialogue: 0,0:16:20.51,0:16:22.89,Default,,0,0,0,,对运算符求值会得到一个过程\nDialogue: 0,0:16:24.05,0:16:26.78,Default,,0,0,0,,现在 我要求值所有运算对象来取得参数\nDialogue: 0,0:16:27.29,0:16:28.22,Default,,0,0,0,,我将调用EVLIST\nDialogue: 0,0:16:31.26,0:16:35.53,Default,,0,0,0,,来求值表达式的CDR部分 也就是运算对象\nDialogue: 0,0:16:36.76,0:16:39.00,Default,,0,0,0,,当然是在相应的环境中\nDialogue: 0,0:16:41.94,0:16:43.13,Default,,0,0,0,,我们待会儿再定义EVLIST\nDialogue: 0,0:16:43.26,0:16:48.07,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:16:50.90,0:16:52.33,Default,,0,0,0,,你现在看到的\nDialogue: 0,0:16:52.67,0:16:56.11,Default,,0,0,0,,基本上就是一个完整的求值器\nDialogue: 0,0:16:56.49,0:17:01.00,Default,,0,0,0,,它根据表达式的类型分情况处理\nDialogue: 0,0:17:01.24,0:17:02.11,Default,,0,0,0,,默认的情况是\nDialogue: 0,0:17:04.99,0:17:07.95,Default,,0,0,0,,表达式应用或者说是组合式\nDialogue: 0,0:17:17.52,0:17:19.52,Default,,0,0,0,,不过还有好些过程 我们没有定义\nDialogue: 0,0:17:20.08,0:17:21.60,Default,,0,0,0,,接下来就看这些未定义的部分\nDialogue: 0,0:17:21.78,0:17:24.12,Default,,0,0,0,,我们还要定义EVCOND\nDialogue: 0,0:17:25.48,0:17:26.67,Default,,0,0,0,,我得定义APPLY\nDialogue: 0,0:17:27.57,0:17:28.62,Default,,0,0,0,,还有EVLIST\nDialogue: 0,0:17:28.94,0:17:30.20,Default,,0,0,0,,以及LOOKUP\nDialogue: 0,0:17:31.79,0:17:33.43,Default,,0,0,0,,我看看 没别的了吧？\nDialogue: 0,0:17:33.43,0:17:35.16,Default,,0,0,0,,剩下的东西都很简单\nDialogue: 0,0:17:35.16,0:17:37.18,Default,,0,0,0,,比如基本元素之类的东西\nDialogue: 0,0:17:38.57,0:17:39.48,Default,,0,0,0,,当然\nDialogue: 0,0:17:39.69,0:17:42.06,Default,,0,0,0,,在这里 可以扩充很多特殊形式\nDialogue: 0,0:17:42.25,0:17:44.45,Default,,0,0,0,,但如果在通用语言中这么做就很糟糕\nDialogue: 0,0:17:44.45,0:17:45.92,Default,,0,0,0,,在这里添加大量的东西\nDialogue: 0,0:17:46.00,0:17:47.48,Default,,0,0,0,,会让语言变得复杂\nDialogue: 0,0:17:47.69,0:17:50.35,Default,,0,0,0,,语言中的保留字\nDialogue: 0,0:17:50.76,0:17:53.61,Default,,0,0,0,,不该比你能用几个手指、脚指记住的数目多\nDialogue: 0,0:17:54.16,0:17:55.53,Default,,0,0,0,,有些语言的保留字有成百上千个\nDialogue: 0,0:17:55.56,0:17:58.20,Default,,0,0,0,,我都不知道该说什么了\nDialogue: 0,0:17:59.41,0:18:00.71,Default,,0,0,0,,保留字就是在这里定义的\nDialogue: 0,0:18:03.15,0:18:06.54,Default,,0,0,0,,好 接下来 我们来看下一个部分\nDialogue: 0,0:18:06.56,0:18:07.69,Default,,0,0,0,,求值器的核心 APPLY\nDialogue: 0,0:18:09.64,0:18:10.75,Default,,0,0,0,,它还做些什么呢？\nDialogue: 0,0:18:11.59,0:18:17.53,Default,,0,0,0,,APPLY把还是符号状态的求值运算符和运算对象\nDialogue: 0,0:18:17.66,0:18:20.68,Default,,0,0,0,,求值为相应的过程以及参数值\nDialogue: 0,0:18:20.91,0:18:23.85,Default,,0,0,0,,然后把得到的过程应用在参数上\nDialogue: 0,0:18:24.09,0:18:26.96,Default,,0,0,0,,无论它们是什么符号表达式\nDialogue: 0,0:18:33.27,0:18:35.08,Default,,0,0,0,,我们把APPLY定义为\nDialogue: 0,0:18:38.35,0:18:40.65,Default,,0,0,0,,接收两个参数的过程\nDialogue: 0,0:18:40.75,0:18:43.44,Default,,0,0,0,,一个过程和对应的参数\nDialogue: 0,0:18:47.24,0:18:48.12,Default,,0,0,0,,它要怎么做呢？\nDialogue: 0,0:18:48.14,0:18:49.55,Default,,0,0,0,,其实并不复杂\nDialogue: 0,0:18:49.93,0:18:50.78,Default,,0,0,0,,分两种情况就够了\nDialogue: 0,0:18:53.58,0:18:55.16,Default,,0,0,0,,如果这个过程是基本过程--\nDialogue: 0,0:19:03.42,0:19:06.41,Default,,0,0,0,,我不知道这个谓词具体是如何判断的\nDialogue: 0,0:19:06.86,0:19:10.24,Default,,0,0,0,,可能这里面有某种类型信息\nDialogue: 0,0:19:10.38,0:19:12.41,Default,,0,0,0,,就像我们在这里用'CLOSURE\nDialogue: 0,0:19:12.68,0:19:15.05,Default,,0,0,0,,来描述一些复合对象一样\nDialogue: 0,0:19:16.33,0:19:17.79,Default,,0,0,0,,我想可能是这样\nDialogue: 0,0:19:18.55,0:19:20.20,Default,,0,0,0,,但是具体怎么判断并不重要\nDialogue: 0,0:19:20.68,0:19:22.01,Default,,0,0,0,,事实上\nDialogue: 0,0:19:22.19,0:19:23.85,Default,,0,0,0,,你可能已经知道或者推断过\nDialogue: 0,0:19:23.87,0:19:25.47,Default,,0,0,0,,我们并不需要任何基本过程\nDialogue: 0,0:19:27.35,0:19:29.28,Default,,0,0,0,,就算没有它们 照样可以进行计算\nDialogue: 0,0:19:30.46,0:19:33.19,Default,,0,0,0,,因为我们可以用一直在用的LAMBDA\nDialogue: 0,0:19:33.61,0:19:34.76,Default,,0,0,0,,但是有它们总归方便点儿\nDialogue: 0,0:19:34.81,0:19:36.27,Default,,0,0,0,,我在这儿略施魔法\nDialogue: 0,0:19:36.30,0:19:37.47,Default,,0,0,0,,但不会去解释\nDialogue: 0,0:19:38.06,0:19:41.44,Default,,0,0,0,,转到机器语言 执行APPLY-PRIMOP\nDialogue: 0,0:19:42.91,0:19:43.80,Default,,0,0,0,,加法是在这里运算的\nDialogue: 0,0:19:44.78,0:19:46.10,Default,,0,0,0,,执行加法指令\nDialogue: 0,0:19:50.62,0:19:52.11,Default,,0,0,0,,然而一门语言有趣的部分\nDialogue: 0,0:19:52.14,0:19:54.27,Default,,0,0,0,,在于组合基本元素的粘合剂\nDialogue: 0,0:19:54.91,0:19:55.90,Default,,0,0,0,,我们接着往下看\nDialogue: 0,0:19:56.91,0:19:58.38,Default,,0,0,0,,另一种可能就是\nDialogue: 0,0:19:58.75,0:20:04.12,Default,,0,0,0,,这个复合对象是求值LAMBDA表达式得到的\nDialogue: 0,0:20:04.97,0:20:07.05,Default,,0,0,0,,这是个复合过程\nDialogue: 0,0:20:07.62,0:20:09.36,Default,,0,0,0,,检测它的类型标志\nDialogue: 0,0:20:10.11,0:20:17.07,Default,,0,0,0,,如果是'CLOSURE\nDialogue: 0,0:20:20.51,0:20:24.09,Default,,0,0,0,,如果是的话 我就得求值这个过程的体\nDialogue: 0,0:20:24.19,0:20:27.39,Default,,0,0,0,,过程的体的求值方式则是\nDialogue: 0,0:20:28.08,0:20:31.69,Default,,0,0,0,,我求值过程的应用是通过\nDialogue: 0,0:20:31.72,0:20:33.71,Default,,0,0,0,,先扩充程序的求值环境\nDialogue: 0,0:20:34.19,0:20:37.80,Default,,0,0,0,,在这个环境中 把过程的形式参数\nDialogue: 0,0:20:37.92,0:20:40.48,Default,,0,0,0,,跟传递过来的实际参数绑定在一起\nDialogue: 0,0:20:41.02,0:20:43.68,Default,,0,0,0,,在这个环境中求值过程的体\nDialogue: 0,0:20:46.70,0:20:47.87,Default,,0,0,0,,这句话很长\nDialogue: 0,0:20:51.13,0:20:52.16,Default,,0,0,0,,但其实简单\nDialogue: 0,0:20:52.82,0:20:54.48,Default,,0,0,0,,一会儿可能会出现许多CAR CDR...\nDialogue: 0,0:20:56.46,0:20:58.11,Default,,0,0,0,,现在我先要得到过程体\nDialogue: 0,0:20:59.40,0:21:02.30,Default,,0,0,0,,如何取出过程体呢？\nDialogue: 0,0:21:02.96,0:21:04.08,Default,,0,0,0,,这里是CAR部分\nDialogue: 0,0:21:04.49,0:21:06.13,Default,,0,0,0,,这一块是剩下部分的CDR部分\nDialogue: 0,0:21:06.13,0:21:06.96,Default,,0,0,0,,因此这就是CADR\nDialogue: 0,0:21:07.40,0:21:09.45,Default,,0,0,0,,所以这里我得到的过程体\nDialogue: 0,0:21:09.45,0:21:13.04,Default,,0,0,0,,是过程对象第二个元素的第二个元素\nDialogue: 0,0:21:13.20,0:21:15.15,Default,,0,0,0,,因此CADR的CADR 也就是CADADR\nDialogue: 0,0:21:19.17,0:21:27.68,Default,,0,0,0,,这里取过程对象的CADADR部分\nDialogue: 0,0:21:30.26,0:21:31.56,Default,,0,0,0,,为了求值过程体\nDialogue: 0,0:21:31.98,0:21:36.48,Default,,0,0,0,,要在参数绑定后的新环境之中进行\nDialogue: 0,0:21:38.09,0:21:42.06,Default,,0,0,0,,我还得获取过程的形式参数\nDialogue: 0,0:21:42.06,0:21:42.72,Default,,0,0,0,,要怎么取呢？\nDialogue: 0,0:21:43.50,0:21:45.13,Default,,0,0,0,,就是CADR部分的CAR部分\nDialogue: 0,0:21:46.52,0:21:48.78,Default,,0,0,0,,这很糟糕不是吗？\nDialogue: 0,0:21:52.65,0:21:53.63,Default,,0,0,0,,过程的CADR部分\nDialogue: 0,0:21:55.44,0:22:00.86,Default,,0,0,0,,在随着过程一起传递过来的环境中\nDialogue: 0,0:22:00.89,0:22:04.14,Default,,0,0,0,,把形参和由环境传递过来的实参绑定起来\nDialogue: 0,0:22:04.54,0:22:07.90,Default,,0,0,0,,也就是CDR的CDR的CAR\nDialogue: 0,0:22:09.79,0:22:16.62,Default,,0,0,0,,也就是过程的CADDR部分\nDialogue: 0,0:22:20.29,0:22:24.96,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:22:26.14,0:22:29.68,Default,,0,0,0,,当然 如果我非常追求整洁\nDialogue: 0,0:22:29.87,0:22:31.34,Default,,0,0,0,,并且又非常谨慎\nDialogue: 0,0:22:32.24,0:22:34.12,Default,,0,0,0,,我会在后面多加一个情况\nDialogue: 0,0:22:34.38,0:22:35.98,Default,,0,0,0,,来判断是否出错\nDialogue: 0,0:22:36.17,0:22:38.41,Default,,0,0,0,,比如应用在参数上的是一个过程吗？\nDialogue: 0,0:22:39.00,0:22:41.69,Default,,0,0,0,,如果不是 这里就是未定义的过程类型\nDialogue: 0,0:22:42.57,0:22:44.09,Default,,0,0,0,,我在这里也会这么做\nDialogue: 0,0:22:45.80,0:22:55.96,Default,,0,0,0,,像这样 在ELSE子句中返回错误\nDialogue: 0,0:22:57.61,0:23:01.61,Default,,0,0,0,,当然 在现实中的一些系统中\nDialogue: 0,0:23:02.56,0:23:04.22,Default,,0,0,0,,出于专业设计的考虑\nDialogue: 0,0:23:05.32,0:23:08.00,Default,,0,0,0,,这里可能会根据某种分派\nDialogue: 0,0:23:08.36,0:23:09.90,Default,,0,0,0,,来进行“分情况处理”\nDialogue: 0,0:23:10.75,0:23:12.68,Default,,0,0,0,,回到这里 我可能还会添加新的条件来检查\nDialogue: 0,0:23:12.70,0:23:14.14,Default,,0,0,0,,比如 这是编译过的代码吗？\nDialogue: 0,0:23:16.22,0:23:16.84,Default,,0,0,0,,这很重要\nDialogue: 0,0:23:16.88,0:23:18.35,Default,,0,0,0,,这样的话我就可以区分\nDialogue: 0,0:23:18.38,0:23:22.33,Default,,0,0,0,,过程是直接由解释LAMBDA表达式而来\nDialogue: 0,0:23:22.94,0:23:25.87,Default,,0,0,0,,还是从另外的编译器中得到的 等等\nDialogue: 0,0:23:26.11,0:23:27.23,Default,,0,0,0,,之后再讨论这个话题\nDialogue: 0,0:23:27.23,0:23:29.61,Default,,0,0,0,,又或许是 我必须要执行的一段Frotran代码\nDialogue: 0,0:23:30.51,0:23:32.51,Default,,0,0,0,,这完全是可能的\nDialogue: 0,0:23:32.92,0:23:36.41,Default,,0,0,0,,实际上 我用具体语法写的这个求值器\nDialogue: 0,0:23:37.45,0:23:40.86,Default,,0,0,0,,假定了它是用Lisp来编写的\nDialogue: 0,0:23:42.30,0:23:43.82,Default,,0,0,0,,这是因为我用了CAR和CDR\nDialogue: 0,0:23:43.84,0:23:45.10,Default,,0,0,0,,用CAR来取运算符\nDialogue: 0,0:23:45.28,0:23:46.64,Default,,0,0,0,,用CDR来取运算对象\nDialogue: 0,0:23:46.75,0:23:49.96,Default,,0,0,0,,教科书上给出了一个用抽象语法编写的求值器\nDialogue: 0,0:23:50.35,0:23:53.15,Default,,0,0,0,,它使用的都是抽象的名字\nDialogue: 0,0:23:53.16,0:23:54.09,Default,,0,0,0,,比如OPERATOR、OPERAND\nDialogue: 0,0:23:54.14,0:23:55.82,Default,,0,0,0,,以及类似的名字\nDialogue: 0,0:23:56.16,0:23:56.86,Default,,0,0,0,,那样的话\nDialogue: 0,0:23:57.02,0:24:00.91,Default,,0,0,0,,你可以毫无问题地用ALGOL来重新实现\nDialogue: 0,0:24:03.36,0:24:06.40,Default,,0,0,0,,写完APPLY之后\nDialogue: 0,0:24:07.20,0:24:08.43,Default,,0,0,0,,又有一些东西没有定义\nDialogue: 0,0:24:10.81,0:24:12.57,Default,,0,0,0,,我先不操心这两个\nDialogue: 0,0:24:13.39,0:24:15.05,Default,,0,0,0,,我们稍后讨论这个很重要的BIND\nDialogue: 0,0:24:17.18,0:24:19.76,Default,,0,0,0,,现在我们来快速过一遍 结束这一部分\nDialogue: 0,0:24:20.55,0:24:22.65,Default,,0,0,0,,只剩下两块黑板了 不能够写太长\nDialogue: 0,0:24:27.40,0:24:29.08,Default,,0,0,0,,我还得悉心裁剪才能刚好写下\nDialogue: 0,0:24:30.07,0:24:30.98,Default,,0,0,0,,嗯 还剩下点什么？\nDialogue: 0,0:24:30.98,0:24:33.20,Default,,0,0,0,,我们得定义这里的EVLIST\nDialogue: 0,0:24:33.73,0:24:35.07,Default,,0,0,0,,EVLIST只不过是\nDialogue: 0,0:24:35.26,0:24:43.08,Default,,0,0,0,,在运算对象上映射某个函数得到参数\nDialogue: 0,0:24:44.30,0:24:45.40,Default,,0,0,0,,但是我还是要写出来看看\nDialogue: 0,0:24:45.82,0:24:48.30,Default,,0,0,0,,我把它写出来的原因有点神秘\nDialogue: 0,0:24:49.88,0:24:52.04,Default,,0,0,0,,我想让这个求值器简单得\nDialogue: 0,0:24:52.06,0:24:53.56,Default,,0,0,0,,可以求值自身\nDialogue: 0,0:24:56.45,0:24:58.09,Default,,0,0,0,,我真的很在意这一点\nDialogue: 0,0:25:00.23,0:25:01.74,Default,,0,0,0,,现在我就把它完全写在这里\nDialogue: 0,0:25:02.85,0:25:04.24,Default,,0,0,0,,我并不关心\nDialogue: 0,0:25:04.27,0:25:06.08,Default,,0,0,0,,它能否把过程作为参数传递\nDialogue: 0,0:25:06.27,0:25:08.06,Default,,0,0,0,,求值器并不会用到这些参数\nDialogue: 0,0:25:08.98,0:25:10.78,Default,,0,0,0,,求值器也不会生成一个是过程的值\nDialogue: 0,0:25:10.88,0:25:12.67,Default,,0,0,0,,因此 如果另外有个不同的语言\nDialogue: 0,0:25:12.80,0:25:13.96,Default,,0,0,0,,跟这个又非常相似\nDialogue: 0,0:25:15.16,0:25:17.79,Default,,0,0,0,,这个求值器能够求值像Scheme这样的复杂语言\nDialogue: 0,0:25:17.80,0:25:23.12,Default,,0,0,0,,Scheme是能够把过程当做参数传递的\nDialogue: 0,0:25:24.07,0:25:25.95,Default,,0,0,0,,但当我在求值ALGOL时\nDialogue: 0,0:25:27.34,0:25:28.96,Default,,0,0,0,,尽管ALGOL并不支持过程值\nDialogue: 0,0:25:29.47,0:25:30.59,Default,,0,0,0,,这个求值器也能正常工作\nDialogue: 0,0:25:31.58,0:25:33.92,Default,,0,0,0,,因为这个解释器 并没有对这个做过什么假定\nDialogue: 0,0:25:34.27,0:25:36.03,Default,,0,0,0,,实际上 就算这个求值器\nDialogue: 0,0:25:36.27,0:25:37.50,Default,,0,0,0,,被限制不允许那么做 也没有什么关系\nDialogue: 0,0:25:37.52,0:25:40.03,Default,,0,0,0,,因为它没有使用那些高级功能\nDialogue: 0,0:25:40.64,0:25:42.41,Default,,0,0,0,,这就是我为什么要把它设计得非常简单\nDialogue: 0,0:25:44.07,0:25:46.46,Default,,0,0,0,,这几乎是所有可能的语言求值器的核心\nDialogue: 0,0:25:47.81,0:25:48.48,Default,,0,0,0,,回到这个定义上来\nDialogue: 0,0:25:49.42,0:25:53.56,Default,,0,0,0,,EVLIST -- 它是什么呢？\nDialogue: 0,0:25:53.82,0:25:57.04,Default,,0,0,0,,这个过程接收两个参数 L和ENV\nDialogue: 0,0:25:58.09,0:25:59.08,Default,,0,0,0,,其中L是个表\nDialogue: 0,0:25:59.58,0:26:08.27,Default,,0,0,0,,这样的话 如果参数表是空表\nDialogue: 0,0:26:10.19,0:26:12.68,Default,,0,0,0,,那么结果就是空表\nDialogue: 0,0:26:14.03,0:26:19.23,Default,,0,0,0,,否则的话 我就要组合\nDialogue: 0,0:26:20.75,0:26:26.67,Default,,0,0,0,,在ENV中求值运算对象表的CAR部分\nDialogue: 0,0:26:28.16,0:26:32.51,Default,,0,0,0,,在ENV中求值运算对象CAR部分的结果\nDialogue: 0,0:26:33.34,0:26:35.71,Default,,0,0,0,,我想先求值第一个运算对象\nDialogue: 0,0:26:35.98,0:26:38.40,Default,,0,0,0,,返回的结果将是一个新表\nDialogue: 0,0:26:38.97,0:26:40.76,Default,,0,0,0,,是通过把这个和\nDialogue: 0,0:26:41.08,0:26:45.42,Default,,0,0,0,,用CDR递归EVLIST的结果组合得到的\nDialogue: 0,0:26:46.22,0:26:50.13,Default,,0,0,0,,在同样的ENV下 L的CDR部分\nDialogue: 0,0:26:53.08,0:26:58.24,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:26:59.66,0:27:01.84,Default,,0,0,0,,还有一个过程\nDialogue: 0,0:27:01.84,0:27:03.36,Default,,0,0,0,,我也想写在这里\nDialogue: 0,0:27:03.62,0:27:05.21,Default,,0,0,0,,它是这整个的关键\nDialogue: 0,0:27:05.64,0:27:08.13,Default,,0,0,0,,还要深入一个层次\nDialogue: 0,0:27:14.54,0:27:15.44,Default,,0,0,0,,也就是COND语句\nDialogue: 0,0:27:15.69,0:27:16.99,Default,,0,0,0,,在剩下的东西中\nDialogue: 0,0:27:17.02,0:27:18.17,Default,,0,0,0,,EVCOND是唯一的重要过程\nDialogue: 0,0:27:18.88,0:27:20.75,Default,,0,0,0,,解决完这个后\nDialogue: 0,0:27:21.07,0:27:22.94,Default,,0,0,0,,我们再讨论LOOKUP和BIND\nDialogue: 0,0:27:23.56,0:27:25.36,Default,,0,0,0,,稍后再来讨论\nDialogue: 0,0:27:25.53,0:27:27.93,Default,,0,0,0,,在这个层次上 这是非常重要的\nDialogue: 0,0:27:28.65,0:27:30.62,Default,,0,0,0,,下一个重要的事就是如何处理COND语句\nDialogue: 0,0:27:31.60,0:27:33.33,Default,,0,0,0,,那么 我们怎么来处理呢？\nDialogue: 0,0:27:36.97,0:27:38.56,Default,,0,0,0,,它是一个过程\nDialogue: 0,0:27:39.48,0:27:45.00,Default,,0,0,0,,参数是一组子句CLAUSES和环境ENV\nDialogue: 0,0:27:47.71,0:27:48.51,Default,,0,0,0,,它做些什么呢？\nDialogue: 0,0:27:49.82,0:27:55.47,Default,,0,0,0,,如果子句为空\nDialogue: 0,0:28:02.60,0:28:03.96,Default,,0,0,0,,我得有一个返回值\nDialogue: 0,0:28:04.70,0:28:05.87,Default,,0,0,0,,可能是一个错误\nDialogue: 0,0:28:06.54,0:28:08.59,Default,,0,0,0,,如果遍历完了所有条件 都没有符合的\nDialogue: 0,0:28:09.15,0:28:10.06,Default,,0,0,0,,那么它可能有任意的行为\nDialogue: 0,0:28:10.06,0:28:12.88,Default,,0,0,0,,这完全取决于程序员要怎么处理\nDialogue: 0,0:28:13.65,0:28:15.45,Default,,0,0,0,,现在对我来说最方便的是\nDialogue: 0,0:28:15.63,0:28:17.53,Default,,0,0,0,,让它返回一个空表\nDialogue: 0,0:28:18.14,0:28:18.83,Default,,0,0,0,,这无所谓\nDialogue: 0,0:28:20.10,0:28:20.88,Default,,0,0,0,,为了检查出错误\nDialogue: 0,0:28:20.89,0:28:22.76,Default,,0,0,0,,有些人喜欢在这里写点别的\nDialogue: 0,0:28:23.11,0:28:24.81,Default,,0,0,0,,下面的更有意思\nDialogue: 0,0:28:25.39,0:28:27.24,Default,,0,0,0,,如果我遇到了ELSE子句\nDialogue: 0,0:28:31.00,0:28:32.73,Default,,0,0,0,,请看 我们有一个由子句组成的表\nDialogue: 0,0:28:33.21,0:28:34.41,Default,,0,0,0,,其中每个子句也是一个表\nDialogue: 0,0:28:35.44,0:28:40.52,Default,,0,0,0,,因此谓词就应该是CLAUSES的CAAR部分\nDialogue: 0,0:28:43.56,0:28:45.02,Default,,0,0,0,,它是\nDialogue: 0,0:28:45.04,0:28:49.00,Default,,0,0,0,,CLAUSES表中第一个元素的CAR部分\nDialogue: 0,0:28:51.09,0:28:51.84,Default,,0,0,0,,如果它是'ELSE的话\nDialogue: 0,0:28:54.32,0:28:56.51,Default,,0,0,0,,就意味着整个COND表达式的结果\nDialogue: 0,0:28:56.64,0:28:59.15,Default,,0,0,0,,就是求值匹配表达式的结果\nDialogue: 0,0:29:00.12,0:29:04.32,Default,,0,0,0,,所以我求值CADAR部分\nDialogue: 0,0:29:07.00,0:29:09.56,Default,,0,0,0,,这是第一个子句的\nDialogue: 0,0:29:10.12,0:29:11.63,Default,,0,0,0,,第二个元素 也就是CADAR\nDialogue: 0,0:29:12.81,0:29:17.08,Default,,0,0,0,,也就是CLAUSES的CAR部分的CADR部分\nDialogue: 0,0:29:21.23,0:29:22.57,Default,,0,0,0,,求值的环境是ENV\nDialogue: 0,0:29:26.62,0:29:28.60,Default,,0,0,0,,下一种可能性更有意思\nDialogue: 0,0:29:29.63,0:29:30.44,Default,,0,0,0,,如果它返回FALSE的话\nDialogue: 0,0:29:33.05,0:29:35.10,Default,,0,0,0,,如果谓词表中的第一个谓词\nDialogue: 0,0:29:35.74,0:29:37.68,Default,,0,0,0,,既不是ELSE子句 又不为FALSE\nDialogue: 0,0:29:38.32,0:29:39.50,Default,,0,0,0,,也就是它不是保留字ELSE\nDialogue: 0,0:29:40.16,0:29:42.00,Default,,0,0,0,,并且也不是一个值为FALSE的东西\nDialogue: 0,0:29:42.03,0:29:43.66,Default,,0,0,0,,如果为FALSE又要怎么处理呢？\nDialogue: 0,0:29:44.36,0:29:50.08,Default,,0,0,0,,如果在相应的环境中\nDialogue: 0,0:29:52.33,0:29:56.76,Default,,0,0,0,,求值子句中第一个谓词的结果\nDialogue: 0,0:29:58.19,0:30:01.00,Default,,0,0,0,,如果求值的结果是FALSE的话\nDialogue: 0,0:30:01.69,0:30:03.82,Default,,0,0,0,,这就意味着 还得接着判断后面的子句\nDialogue: 0,0:30:04.36,0:30:05.74,Default,,0,0,0,,第一个就扔掉不管了\nDialogue: 0,0:30:06.25,0:30:08.33,Default,,0,0,0,,所以就进入下一个EVCOND循环\nDialogue: 0,0:30:09.95,0:30:16.49,Default,,0,0,0,,在对应的环境中继续判断子句的CDR部分\nDialogue: 0,0:30:19.95,0:30:25.15,Default,,0,0,0,,又或者 我遇到了求值为TRUE的子句\nDialogue: 0,0:30:26.84,0:30:28.96,Default,,0,0,0,,这样的话 我想在对应的环境中\nDialogue: 0,0:30:31.85,0:30:41.45,Default,,0,0,0,,求值CLAUSES的CADAR部分\nDialogue: 0,0:30:48.20,0:30:49.61,Default,,0,0,0,,快了 快完成了\nDialogue: 0,0:30:51.21,0:30:52.80,Default,,0,0,0,,基本上完整了\nDialogue: 0,0:30:53.73,0:30:55.87,Default,,0,0,0,,把这一部分结束\nDialogue: 0,0:30:56.21,0:30:58.57,Default,,0,0,0,,再回顾一下这个求值器\nDialogue: 0,0:30:58.81,0:31:00.70,Default,,0,0,0,,它基本上就是这样了\nDialogue: 0,0:31:01.08,0:31:04.04,Default,,0,0,0,,接着来看一张幻灯片\nDialogue: 0,0:31:06.32,0:31:10.43,Default,,0,0,0,,这是BIND的定义\nDialogue: 0,0:31:11.98,0:31:14.54,Default,,0,0,0,,BIND用于在环境中添加新的绑定\nDialogue: 0,0:31:15.46,0:31:18.67,Default,,0,0,0,,我们要在这里\nDialogue: 0,0:31:19.24,0:31:22.80,Default,,0,0,0,,为环境结构创建一个新框架\nDialogue: 0,0:31:22.80,0:31:25.42,Default,,0,0,0,,环境结构是通过由框架组成的表\nDialogue: 0,0:31:25.93,0:31:27.20,Default,,0,0,0,,来表示的\nDialogue: 0,0:31:28.08,0:31:30.19,Default,,0,0,0,,给定一个已有的环境\nDialogue: 0,0:31:30.32,0:31:32.11,Default,,0,0,0,,我可以通过把一个新建的框架\nDialogue: 0,0:31:32.25,0:31:33.82,Default,,0,0,0,,CONS在已有的环境上\nDialogue: 0,0:31:33.93,0:31:35.69,Default,,0,0,0,,来获得新的环境\nDialogue: 0,0:31:36.62,0:31:40.36,Default,,0,0,0,,正在应用的过程中 那些被绑定变量\nDialogue: 0,0:31:41.05,0:31:43.79,Default,,0,0,0,,与传递给过程的参数值结合在一起\nDialogue: 0,0:31:44.12,0:31:48.25,Default,,0,0,0,,组成了我们所创建的新框架\nDialogue: 0,0:31:49.69,0:31:50.65,Default,,0,0,0,,BIND其实就是创建表\nDialogue: 0,0:31:51.64,0:31:54.06,Default,,0,0,0,,环境就是一组由框架组成的表\nDialogue: 0,0:31:54.30,0:31:55.60,Default,,0,0,0,,把新的元素加入其中\nDialogue: 0,0:31:55.74,0:31:56.89,Default,,0,0,0,,也就形成了新的环境\nDialogue: 0,0:31:58.65,0:32:00.65,Default,,0,0,0,,而PAIR-UP的定义非常简单\nDialogue: 0,0:32:01.54,0:32:02.84,Default,,0,0,0,,PAIR-UP只不过是\nDialogue: 0,0:32:03.13,0:32:05.56,Default,,0,0,0,,如果我们有一个变量表和一个值表\nDialogue: 0,0:32:05.93,0:32:08.62,Default,,0,0,0,,那么 如果它俩的元素个数又相同\nDialogue: 0,0:32:08.62,0:32:09.58,Default,,0,0,0,,就可以让它们一一对应\nDialogue: 0,0:32:09.72,0:32:11.48,Default,,0,0,0,,否则的话 就是参数传递多了\nDialogue: 0,0:32:12.51,0:32:15.98,Default,,0,0,0,,如果值的个数比变量的个数多\nDialogue: 0,0:32:16.06,0:32:17.37,Default,,0,0,0,,那就说明参数传递少了\nDialogue: 0,0:32:18.51,0:32:19.63,Default,,0,0,0,,通常的情况是\nDialogue: 0,0:32:19.63,0:32:21.48,Default,,0,0,0,,如果没有出错 又没有完成的话\nDialogue: 0,0:32:22.06,0:32:25.61,Default,,0,0,0,,我就添加一个由第一个变量\nDialogue: 0,0:32:25.76,0:32:30.17,Default,,0,0,0,,和第一个参数组成的新序对\nDialogue: 0,0:32:30.94,0:32:32.12,Default,,0,0,0,,这是第一个值\nDialogue: 0,0:32:32.76,0:32:36.40,Default,,0,0,0,,把它们CONS在\nDialogue: 0,0:32:37.12,0:32:40.64,Default,,0,0,0,,剩余变量和值组成的表上\nDialogue: 0,0:32:42.95,0:32:44.78,Default,,0,0,0,,LOOKUP也同样简单\nDialogue: 0,0:32:46.28,0:32:49.63,Default,,0,0,0,,加入我要在环境中查找一个符号\nDialogue: 0,0:32:49.93,0:32:51.39,Default,,0,0,0,,那么 如果是空环境\nDialogue: 0,0:32:51.56,0:32:53.00,Default,,0,0,0,,那么就说明 该变量尚未绑定\nDialogue: 0,0:32:54.65,0:32:55.47,Default,,0,0,0,,否则\nDialogue: 0,0:32:56.86,0:33:00.36,Default,,0,0,0,,我就要使用一个特殊的关联表查找过程\nDialogue: 0,0:33:00.38,0:33:01.87,Default,,0,0,0,,我们不久就会看到它的定义\nDialogue: 0,0:33:02.24,0:33:05.44,Default,,0,0,0,,用它在环境的第一个框架中查找该符号\nDialogue: 0,0:33:05.93,0:33:07.21,Default,,0,0,0,,由于我知道这个环境不是空的\nDialogue: 0,0:33:07.23,0:33:08.40,Default,,0,0,0,,因此 它至少有一个框架\nDialogue: 0,0:33:09.20,0:33:11.14,Default,,0,0,0,,所以 我就在它第一个框架中查找\nDialogue: 0,0:33:11.56,0:33:13.58,Default,,0,0,0,,找到的序对会传递给这里的VCELL\nDialogue: 0,0:33:14.38,0:33:17.61,Default,,0,0,0,,如果VCELL为空\nDialogue: 0,0:33:18.44,0:33:20.57,Default,,0,0,0,,那就说明当前框架中没有这个符号\nDialogue: 0,0:33:20.70,0:33:22.84,Default,,0,0,0,,我就需要在环境中剩下的框架中查找\nDialogue: 0,0:33:23.72,0:33:25.04,Default,,0,0,0,,VCELL为空 意味着当前框架没有相应的符号\nDialogue: 0,0:33:25.99,0:33:28.89,Default,,0,0,0,,如果没有找到\nDialogue: 0,0:33:29.52,0:33:30.80,Default,,0,0,0,,ASSQ就会返回空表\nDialogue: 0,0:33:32.32,0:33:33.85,Default,,0,0,0,,如果找到了\nDialogue: 0,0:33:33.85,0:33:36.06,Default,,0,0,0,,那么我就使用VCELL的CDR部分\nDialogue: 0,0:33:36.46,0:33:40.25,Default,,0,0,0,,因为VCELL是变量和值组成的序对\nDialogue: 0,0:33:41.05,0:33:43.93,Default,,0,0,0,,因此可以用CDR取得对应的值\nDialogue: 0,0:33:45.00,0:33:47.82,Default,,0,0,0,,ASSQ这个过程你们之前见过\nDialogue: 0,0:33:47.97,0:33:50.83,Default,,0,0,0,,ASSQ的参数是一个符号和一个由序对组成的表\nDialogue: 0,0:33:51.42,0:33:53.40,Default,,0,0,0,,如果表为空 它就返回空表\nDialogue: 0,0:33:53.52,0:33:56.30,Default,,0,0,0,,如果这个符号是ALIST的第一个元素\nDialogue: 0,0:33:58.06,0:33:58.91,Default,,0,0,0,,这里写错了\nDialogue: 0,0:33:59.82,0:34:02.17,Default,,0,0,0,,应该是CAAR\nDialogue: 0,0:34:03.16,0:34:04.16,Default,,0,0,0,,大家注意一下\nDialogue: 0,0:34:07.63,0:34:09.37,Default,,0,0,0,,就是这里 看到了吗？\nDialogue: 0,0:34:13.42,0:34:14.41,Default,,0,0,0,,总之\nDialogue: 0,0:34:14.56,0:34:16.81,Default,,0,0,0,,如果符号等于表的CAAR\nDialogue: 0,0:34:17.16,0:34:20.97,Default,,0,0,0,,那么我就返回ALIST中第一个序对\nDialogue: 0,0:34:22.08,0:34:25.50,Default,,0,0,0,,换句话说 这个键匹配了正确的条目\nDialogue: 0,0:34:26.24,0:34:26.97,Default,,0,0,0,,否则的话\nDialogue: 0,0:34:27.08,0:34:28.94,Default,,0,0,0,,我就需要在剩下的表中继续查找\nDialogue: 0,0:34:30.08,0:34:33.31,Default,,0,0,0,,这里有个笔误 很抱歉\nDialogue: 0,0:34:35.19,0:34:36.28,Default,,0,0,0,,好了 不管如何\nDialogue: 0,0:34:37.05,0:34:39.48,Default,,0,0,0,,你们基本上已经看到了全貌\nDialogue: 0,0:34:41.88,0:34:43.29,Default,,0,0,0,,虽然我们的代码风格非常丑陋\nDialogue: 0,0:34:44.19,0:34:46.00,Default,,0,0,0,,但是作为所有语言的核心\nDialogue: 0,0:34:46.76,0:34:48.30,Default,,0,0,0,,它却是非常美妙\nDialogue: 0,0:34:49.60,0:34:51.37,Default,,0,0,0,,我提议 让我们再欣赏一会儿\nDialogue: 0,0:35:00.32,0:35:47.02,Default,,0,0,0,,[音乐]\nDialogue: 0,0:35:49.75,0:35:50.91,Default,,0,0,0,,大家有什么问题吗？\nDialogue: 0,0:36:01.18,0:36:03.29,Default,,0,0,0,,没有的话就休息一会儿吧\nDialogue: 0,0:36:04.04,0:36:10.73,Default,,0,0,0,,[音乐]\nDialogue: 0,0:36:13.88,0:36:17.64,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:36:40.80,0:36:43.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:36:43.95,0:36:47.98,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:36:48.06,0:36:51.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 I\nDialogue: 0,0:36:56.78,0:36:58.99,Default,,0,0,0,,现在 我们将用一个实例\nDialogue: 0,0:36:59.29,0:37:02.67,Default,,0,0,0,,来理解一下求值器的运作过程\nDialogue: 0,0:37:03.47,0:37:05.48,Default,,0,0,0,,我们通过手工进行代换\nDialogue: 0,0:37:05.50,0:37:10.36,Default,,0,0,0,,来深入解释器的详细工作原理\nDialogue: 0,0:37:11.50,0:37:14.94,Default,,0,0,0,,由于我们的求值器不支持赋值和定义\nDialogue: 0,0:37:15.20,0:37:17.34,Default,,0,0,0,,我们也就不用担心副作用\nDialogue: 0,0:37:17.98,0:37:22.03,Default,,0,0,0,,因此我们可以放心大胆地进行代换\nDialogue: 0,0:37:22.52,0:37:24.59,Default,,0,0,0,,不用担心任何副作用\nDialogue: 0,0:37:25.33,0:37:27.80,Default,,0,0,0,,我们将要尝试去手工代换\nDialogue: 0,0:37:28.06,0:37:29.63,Default,,0,0,0,,这个复杂的表达式\nDialogue: 0,0:37:30.69,0:37:34.09,Default,,0,0,0,,(EVAL\nDialogue: 0,0:37:34.91,0:37:48.08,Default,,0,0,0,,'(((LAMBDA (X) (LAMBDA (Y) (+ X Y)))\nDialogue: 0,0:37:50.30,0:37:52.62,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:37:53.04,0:37:56.12,Default,,0,0,0,,要把它应用在3和4上\nDialogue: 0,0:37:56.94,0:37:59.58,Default,,0,0,0,,求值过程是发生在全局环境E0中的\nDialogue: 0,0:38:04.93,0:38:05.96,Default,,0,0,0,,这里的这个表达式\nDialogue: 0,0:38:06.36,0:38:08.04,Default,,0,0,0,,是个参数为X的一元过程\nDialogue: 0,0:38:08.09,0:38:11.05,Default,,0,0,0,,返回一个参数为Y的一元过程\nDialogue: 0,0:38:11.07,0:38:12.12,Default,,0,0,0,,后者计算X+Y\nDialogue: 0,0:38:14.30,0:38:17.96,Default,,0,0,0,,外层的这个过程应用于数字3\nDialogue: 0,0:38:17.96,0:38:19.39,Default,,0,0,0,,所以X应该是3\nDialogue: 0,0:38:21.40,0:38:23.98,Default,,0,0,0,,返回的结果是一个参数为Y的一元过程\nDialogue: 0,0:38:24.33,0:38:25.82,Default,,0,0,0,,该过程将应用于数字4\nDialogue: 0,0:38:28.91,0:38:30.32,Default,,0,0,0,,然后要做的也很简单\nDialogue: 0,0:38:31.04,0:38:32.73,Default,,0,0,0,,计算X+Y即可\nDialogue: 0,0:38:34.79,0:38:35.82,Default,,0,0,0,,具体做之前\nDialogue: 0,0:38:35.84,0:38:37.76,Default,,0,0,0,,先来构造一个非常简单的环境模型\nDialogue: 0,0:38:37.90,0:38:40.48,Default,,0,0,0,,到了现在 我相信你们已经想到\nDialogue: 0,0:38:40.99,0:38:42.59,Default,,0,0,0,,这个过程产生的环境了\nDialogue: 0,0:38:44.46,0:38:46.62,Default,,0,0,0,,我们从全局环境开始\nDialogue: 0,0:38:48.59,0:38:50.06,Default,,0,0,0,,我们把它记作E0\nDialogue: 0,0:38:54.60,0:38:55.47,Default,,0,0,0,,就像这样\nDialogue: 0,0:38:56.74,0:39:02.46,Default,,0,0,0,,里面应该有过程+、*的定义\nDialogue: 0,0:39:06.30,0:39:10.36,Default,,0,0,0,,这里 我们用希腊字母来表示过程对象 这样有趣点\nDialogue: 0,0:39:11.21,0:39:27.93,Default,,0,0,0,,-、/、CAR、CDR、CONS以及EQ?\nDialogue: 0,0:39:28.59,0:39:31.05,Default,,0,0,0,,其它需要的基本过程都在全局环境中\nDialogue: 0,0:39:31.27,0:39:33.82,Default,,0,0,0,,每个符号都对应着一个过程对象\nDialogue: 0,0:39:34.62,0:39:36.09,Default,,0,0,0,,这些都是解释器自带的\nDialogue: 0,0:39:37.10,0:39:38.09,Default,,0,0,0,,这就是E0\nDialogue: 0,0:39:39.22,0:39:41.84,Default,,0,0,0,,现在 这个求值要怎样进行呢？\nDialogue: 0,0:39:42.94,0:39:45.18,Default,,0,0,0,,我们来看看这些特殊形式\nDialogue: 0,0:39:45.69,0:39:47.05,Default,,0,0,0,,首先 这不是数字\nDialogue: 0,0:39:48.67,0:39:50.38,Default,,0,0,0,,也不是符号\nDialogue: 0,0:39:53.13,0:39:55.60,Default,,0,0,0,,这不是一个引用表达式\nDialogue: 0,0:39:56.60,0:39:58.38,Default,,0,0,0,,虽然外层是一个引用表达式\nDialogue: 0,0:39:59.47,0:40:00.80,Default,,0,0,0,,但并不是我想要去求值的那个\nDialogue: 0,0:40:00.83,0:40:01.36,Default,,0,0,0,,我想问的是\nDialogue: 0,0:40:01.39,0:40:04.96,Default,,0,0,0,,被引用的这个表达式 是否也是个引用表达式？\nDialogue: 0,0:40:05.89,0:40:07.96,Default,,0,0,0,,我是在求值一个表达式\nDialogue: 0,0:40:07.96,0:40:09.98,Default,,0,0,0,,这个引号是为了引用这个特定表达式\nDialogue: 0,0:40:11.41,0:40:12.66,Default,,0,0,0,,而被引用的并非引用表达式\nDialogue: 0,0:40:13.71,0:40:17.21,Default,,0,0,0,,当然 它也不是以LAMBDA开头\nDialogue: 0,0:40:19.12,0:40:20.67,Default,,0,0,0,,也不以COND开头\nDialogue: 0,0:40:22.03,0:40:25.95,Default,,0,0,0,,因此它是过程的应用\nDialogue: 0,0:40:26.31,0:40:27.12,Default,,0,0,0,,这是一个组合式\nDialogue: 0,0:40:28.57,0:40:30.70,Default,,0,0,0,,既然它是组合式\nDialogue: 0,0:40:30.89,0:40:34.00,Default,,0,0,0,,这就是它的运算符\nDialogue: 0,0:40:34.64,0:40:36.08,Default,,0,0,0,,而这是它的运算对象\nDialogue: 0,0:40:40.13,0:40:42.41,Default,,0,0,0,,这就意味着 我要\nDialogue: 0,0:40:42.57,0:40:47.90,Default,,0,0,0,,把它转换成\nDialogue: 0,0:40:50.12,0:40:57.61,Default,,0,0,0,,(APPLY (EVAL '((LAMBDA (X) (LAMBDA (y)\nDialogue: 0,0:40:57.88,0:40:59.12,Default,,0,0,0,,也就是在E0环境中\nDialogue: 0,0:40:59.95,0:41:04.19,Default,,0,0,0,,求值(+ X Y)\nDialogue: 0,0:41:07.26,0:41:08.64,Default,,0,0,0,,不要漏了<E0>\nDialogue: 0,0:41:12.78,0:41:15.20,Default,,0,0,0,,要应用到的运算对象则是\nDialogue: 0,0:41:15.26,0:41:17.28,Default,,0,0,0,,用EVLIST求值参数的结果\nDialogue: 0,0:41:21.21,0:41:24.49,Default,,0,0,0,,也就是'(4)\nDialogue: 0,0:41:29.01,0:41:31.26,Default,,0,0,0,,我用这个特殊的记号来表示<E0>\nDialogue: 0,0:41:32.32,0:41:34.83,Default,,0,0,0,,这是为了指代那个环境\nDialogue: 0,0:41:35.45,0:41:37.77,Default,,0,0,0,,我无法为它命名\nDialogue: 0,0:41:37.80,0:41:39.15,Default,,0,0,0,,因为我没有环境来存放<E0>的名字\nDialogue: 0,0:41:41.96,0:41:44.09,Default,,0,0,0,,你当然可以把<E0>看作是\nDialogue: 0,0:41:44.17,0:41:46.17,Default,,0,0,0,,某种引用表达式\nDialogue: 0,0:41:47.73,0:41:51.16,Default,,0,0,0,,在那里 它表示环境这种数据结构\nDialogue: 0,0:41:53.04,0:41:55.04,Default,,0,0,0,,好的 这是变换后的结果\nDialogue: 0,0:41:55.85,0:41:56.67,Default,,0,0,0,,为了执行这个表达式\nDialogue: 0,0:41:56.68,0:41:58.04,Default,,0,0,0,,我还得求值这两个表达式\nDialogue: 0,0:41:59.61,0:42:00.49,Default,,0,0,0,,EVLIST简单点\nDialogue: 0,0:42:00.57,0:42:03.18,Default,,0,0,0,,我们先计算这个吧\nDialogue: 0,0:42:03.77,0:42:07.44,Default,,0,0,0,,这就被归约为\nDialogue: 0,0:42:07.45,0:42:08.83,Default,,0,0,0,,上面的某些部分直接抄过来就好\nDialogue: 0,0:42:09.42,0:42:11.00,Default,,0,0,0,,代换的过程中少不了照抄\nDialogue: 0,0:42:18.53,0:42:21.24,Default,,0,0,0,,抄写的时候我就不多加解释了\nDialogue: 0,0:42:21.71,0:42:23.87,Default,,0,0,0,,这样能快一点儿\nDialogue: 0,0:42:26.41,0:42:28.64,Default,,0,0,0,,EVLIST的部分就代换成为\nDialogue: 0,0:42:28.65,0:42:36.72,Default,,0,0,0,,(CONS (EVAL '4 <E0>)\nDialogue: 0,0:42:38.78,0:42:40.17,Default,,0,0,0,,因为它不是空表\nDialogue: 0,0:42:41.44,0:42:49.39,Default,,0,0,0,,(EVLIST '() <E0>))\nDialogue: 0,0:42:52.58,0:42:54.20,Default,,0,0,0,,我要省略一些步骤了\nDialogue: 0,0:42:54.24,0:42:55.36,Default,,0,0,0,,因为太详细就有些无聊了\nDialogue: 0,0:42:59.87,0:43:05.42,Default,,0,0,0,,下一步跟上面基本上一样\nDialogue: 0,0:43:07.50,0:43:08.54,Default,,0,0,0,,继续照抄\nDialogue: 0,0:43:10.68,0:43:20.24,Default,,0,0,0,,(((LAMBDA (X) (LAMBDA (Y) (+ X Y)) 3) 4) <E0>)\nDialogue: 0,0:43:20.24,0:43:21.20,Default,,0,0,0,,看来我还宝刀未老嘛\nDialogue: 0,0:43:24.24,0:43:26.24,Default,,0,0,0,,下面对4求值\nDialogue: 0,0:43:26.56,0:43:28.44,Default,,0,0,0,,4是一个数字\nDialogue: 0,0:43:29.00,0:43:33.90,Default,,0,0,0,,结果就应该是(CONS 4\nDialogue: 0,0:43:34.03,0:43:37.47,Default,,0,0,0,,EVLIST对空表求值 结果也是空表\nDialogue: 0,0:43:38.33,0:43:39.24,Default,,0,0,0,,也就是这个\nDialogue: 0,0:43:42.62,0:43:45.08,Default,,0,0,0,,这个非常容易理解\nDialogue: 0,0:43:45.10,0:43:47.44,Default,,0,0,0,,就是一个只含有4的表\nDialogue: 0,0:43:48.71,0:43:53.84,Default,,0,0,0,,继续代换为 (APPLY (EVAL\nDialogue: 0,0:43:55.28,0:44:02.51,Default,,0,0,0,,'((LAMBDA (X) (LAMBDA (Y) (+ X Y))\nDialogue: 0,0:44:03.40,0:44:07.48,Default,,0,0,0,,3) 4) <E0>)\nDialogue: 0,0:44:08.68,0:44:12.60,Default,,0,0,0,,应用在'(4)上 这样就完成了\nDialogue: 0,0:44:13.94,0:44:15.05,Default,,0,0,0,,这是这一步的结果\nDialogue: 0,0:44:17.00,0:44:19.96,Default,,0,0,0,,现在让我们进行下一步 更有意思的一步\nDialogue: 0,0:44:20.36,0:44:21.72,Default,,0,0,0,,这行代码要如何求值？\nDialogue: 0,0:44:23.07,0:44:24.44,Default,,0,0,0,,为了求值这一部分\nDialogue: 0,0:44:25.20,0:44:28.65,Default,,0,0,0,,我得先求值-- 首先 它不是--\nDialogue: 0,0:44:29.46,0:44:31.04,Default,,0,0,0,,这是一个应用\nDialogue: 0,0:44:31.68,0:44:33.10,Default,,0,0,0,,它并不是特殊形式\nDialogue: 0,0:44:33.57,0:44:36.51,Default,,0,0,0,,如果应用中的运算符\nDialogue: 0,0:44:36.51,0:44:37.37,Default,,0,0,0,,就是这里\nDialogue: 0,0:44:37.66,0:44:38.94,Default,,0,0,0,,这就是运算符\nDialogue: 0,0:44:40.19,0:44:41.77,Default,,0,0,0,,应用在这个运算对象上\nDialogue: 0,0:44:44.54,0:44:45.74,Default,,0,0,0,,形成了一个组合式\nDialogue: 0,0:44:46.72,0:44:48.25,Default,,0,0,0,,现在我们要如何来求值呢？\nDialogue: 0,0:44:48.84,0:44:52.37,Default,,0,0,0,,它是COND语句中的最后一种情况\nDialogue: 0,0:44:52.37,0:44:55.52,Default,,0,0,0,,在这步求值中 进行的代换是\nDialogue: 0,0:44:55.71,0:44:57.47,Default,,0,0,0,,把运算符的求值结果\nDialogue: 0,0:44:57.50,0:44:59.00,Default,,0,0,0,,应用在EVLIST的运算对象上\nDialogue: 0,0:45:01.16,0:45:08.20,Default,,0,0,0,,这也就是 (APPLY (APPLY (EVAL\nDialogue: 0,0:45:10.57,0:45:21.07,Default,,0,0,0,,'(LAMBDA (X) (LAMBDA (Y) (+ X Y)))\nDialogue: 0,0:45:21.80,0:45:23.45,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:45:23.74,0:45:25.42,Default,,0,0,0,,<E0>)\nDialogue: 0,0:45:30.52,0:45:32.67,Default,,0,0,0,,我就直接给出运算对象的求值结果了\nDialogue: 0,0:45:32.68,0:45:34.14,Default,,0,0,0,,具体过程跟之前是一样的\nDialogue: 0,0:45:35.23,0:45:36.48,Default,,0,0,0,,我有一个表'(3)\nDialogue: 0,0:45:36.51,0:45:39.16,Default,,0,0,0,,把它应用于'(4)\nDialogue: 0,0:45:42.44,0:45:43.56,Default,,0,0,0,,我们接着看\nDialogue: 0,0:45:44.41,0:45:46.38,Default,,0,0,0,,对一个LAMBDA表达式求值\nDialogue: 0,0:45:48.01,0:45:49.45,Default,,0,0,0,,会产生一个过程对象\nDialogue: 0,0:45:52.03,0:45:57.88,Default,,0,0,0,,继续变换就是 (APPLY (APPLY\nDialogue: 0,0:46:00.30,0:46:02.27,Default,,0,0,0,,然后是一个过程对象 '(CLOSURE\nDialogue: 0,0:46:04.52,0:46:08.68,Default,,0,0,0,,它里面包含了过程的体\nDialogue: 0,0:46:08.94,0:46:11.92,Default,,0,0,0,,它绑定了变量X\nDialogue: 0,0:46:12.13,0:46:15.40,Default,,0,0,0,,然后是函数体内部\nDialogue: 0,0:46:15.80,0:46:18.17,Default,,0,0,0,,它返回一个参数为Y的单参过程\nDialogue: 0,0:46:18.56,0:46:20.63,Default,,0,0,0,,这个过程计算X+Y\nDialogue: 0,0:46:23.21,0:46:25.50,Default,,0,0,0,,这个过程对象捕获了环境<E0>\nDialogue: 0,0:46:27.24,0:46:29.63,Default,,0,0,0,,因为这些求值都是在<E0>中发生的\nDialogue: 0,0:46:30.11,0:46:32.43,Default,,0,0,0,,现在 <E0>也是CLOSURE对象的一部分\nDialogue: 0,0:46:33.04,0:46:38.19,Default,,0,0,0,,先应用于'(3)\nDialogue: 0,0:46:38.81,0:46:41.30,Default,,0,0,0,,再应用于'(4)\nDialogue: 0,0:46:47.39,0:46:49.29,Default,,0,0,0,,在这步到这步的过程中\nDialogue: 0,0:46:49.31,0:46:50.89,Default,,0,0,0,,我构建了一个过程对象\nDialogue: 0,0:46:50.91,0:46:52.03,Default,,0,0,0,,它捕获了<E0>\nDialogue: 0,0:46:53.88,0:46:55.98,Default,,0,0,0,,并将其作为本身的一部分\nDialogue: 0,0:46:57.15,0:46:58.51,Default,,0,0,0,,现在 要把它们传递给APPLY了\nDialogue: 0,0:46:58.52,0:46:59.71,Default,,0,0,0,,我们得把这个过程\nDialogue: 0,0:47:00.48,0:47:01.58,Default,,0,0,0,,应用在对应的参数上\nDialogue: 0,0:47:02.71,0:47:06.51,Default,,0,0,0,,这里的过程并不是基本过程\nDialogue: 0,0:47:07.38,0:47:09.88,Default,,0,0,0,,它有一个类型标志'CLOSURE\nDialogue: 0,0:47:10.24,0:47:12.09,Default,,0,0,0,,因此还需要进行参数绑定\nDialogue: 0,0:47:13.71,0:47:14.72,Default,,0,0,0,,必须要绑定\nDialogue: 0,0:47:15.83,0:47:19.40,Default,,0,0,0,,在这里构造的新环境\nDialogue: 0,0:47:20.44,0:47:22.80,Default,,0,0,0,,它有一个父环境\nDialogue: 0,0:47:22.94,0:47:27.56,Default,,0,0,0,,父环境是这里的<E0>\nDialogue: 0,0:47:30.32,0:47:31.57,Default,,0,0,0,,我们把新环境记作<E1>\nDialogue: 0,0:47:34.62,0:47:35.74,Default,,0,0,0,,这里要绑定些什么呢？\nDialogue: 0,0:47:36.04,0:47:37.48,Default,,0,0,0,,变量X绑定为值3\nDialogue: 0,0:47:38.62,0:47:40.44,Default,,0,0,0,,这里写X=3\nDialogue: 0,0:47:41.48,0:47:42.33,Default,,0,0,0,,就是这些\nDialogue: 0,0:47:44.94,0:47:46.24,Default,,0,0,0,,新环境记作E1\nDialogue: 0,0:47:46.24,0:47:48.44,Default,,0,0,0,,而这个表达式会变换为\nDialogue: 0,0:47:49.13,0:47:50.72,Default,,0,0,0,,对一个过程体的求值\nDialogue: 0,0:47:51.72,0:47:53.07,Default,,0,0,0,,就是这个 在这里\nDialogue: 0,0:47:54.40,0:47:55.72,Default,,0,0,0,,这个过程的体\nDialogue: 0,0:47:56.44,0:47:58.52,Default,,0,0,0,,在刚才创建的<E1>中进行求值\nDialogue: 0,0:48:00.29,0:48:05.05,Default,,0,0,0,,也就是 (APPLY (EVAL\nDialogue: 0,0:48:06.92,0:48:16.43,Default,,0,0,0,,'(LAMBDA (Y) (+ X Y)) <E1>)\nDialogue: 0,0:48:20.49,0:48:22.48,Default,,0,0,0,,把求值的结果应用于4\nDialogue: 0,0:48:23.68,0:48:26.73,Default,,0,0,0,,也就是'(4)\nDialogue: 0,0:48:28.43,0:48:29.87,Default,,0,0,0,,到了这里就很清晰了\nDialogue: 0,0:48:30.08,0:48:32.27,Default,,0,0,0,,我知道该如何求值LAMBDA表达式\nDialogue: 0,0:48:33.11,0:48:34.17,Default,,0,0,0,,也就是(APPLY\nDialogue: 0,0:48:37.16,0:48:38.92,Default,,0,0,0,,一个过程对象'(CLOSURE\nDialogue: 0,0:48:43.74,0:48:46.84,Default,,0,0,0,,它绑定参数Y 计算X+Y\nDialogue: 0,0:48:49.28,0:48:52.15,Default,,0,0,0,,并且捕获了环境<E1>\nDialogue: 0,0:48:55.79,0:48:57.42,Default,,0,0,0,,你应该已经见过了 对吧？\nDialogue: 0,0:48:57.80,0:49:00.14,Default,,0,0,0,,我构造了一个CLOSURE对象\nDialogue: 0,0:49:00.14,0:49:01.16,Default,,0,0,0,,放在这里\nDialogue: 0,0:49:01.79,0:49:03.04,Default,,0,0,0,,之前的那个也是\nDialogue: 0,0:49:05.90,0:49:07.47,Default,,0,0,0,,这是现在的这个\nDialogue: 0,0:49:08.08,0:49:09.80,Default,,0,0,0,,它捕获了环境<E1>\nDialogue: 0,0:49:10.41,0:49:14.25,Default,,0,0,0,,而这个是参数为Y的一元过程\nDialogue: 0,0:49:15.45,0:49:16.70,Default,,0,0,0,,先不管它具体是什么\nDialogue: 0,0:49:18.09,0:49:20.72,Default,,0,0,0,,我们只知道它是一个CLOSURE\nDialogue: 0,0:49:22.57,0:49:26.46,Default,,0,0,0,,将这个过程应用于'(4)\nDialogue: 0,0:49:30.28,0:49:31.77,Default,,0,0,0,,很简单\nDialogue: 0,0:49:36.83,0:49:38.73,Default,,0,0,0,,我需要通过复制一个指针\nDialogue: 0,0:49:38.86,0:49:40.52,Default,,0,0,0,,就是这个过程的指针\nDialogue: 0,0:49:41.56,0:49:43.21,Default,,0,0,0,,来构造一个新环境\nDialogue: 0,0:49:44.94,0:49:48.96,Default,,0,0,0,,同时还得把参数Y跟值4绑定\nDialogue: 0,0:49:49.82,0:49:52.22,Default,,0,0,0,,我把这个新环境 记作<E2>\nDialogue: 0,0:49:56.03,0:49:58.12,Default,,0,0,0,,当然 这里的这个应用\nDialogue: 0,0:49:58.22,0:50:00.33,Default,,0,0,0,,其过程体的求值 是在<E2>中进行的\nDialogue: 0,0:50:01.58,0:50:07.87,Default,,0,0,0,,所以这就变成了对过程体的求值\nDialogue: 0,0:50:07.90,0:50:11.85,Default,,0,0,0,,也就是 (EVAL '(+ X Y) <E2>)\nDialogue: 0,0:50:13.71,0:50:14.94,Default,,0,0,0,,但由于这是一个应用\nDialogue: 0,0:50:15.48,0:50:23.88,Default,,0,0,0,,所以又代换为 (APPLY (EVAL '+ <E2>)\nDialogue: 0,0:50:26.33,0:50:37.34,Default,,0,0,0,,(EVLIST '(X Y) <E2>))\nDialogue: 0,0:50:44.88,0:50:45.59,Default,,0,0,0,,我们来看\nDialogue: 0,0:50:45.59,0:50:51.71,Default,,0,0,0,,下一步代换为 (APPLY\nDialogue: 0,0:50:52.08,0:50:53.87,Default,,0,0,0,,求值‘+得到的结果\nDialogue: 0,0:50:54.19,0:50:55.66,Default,,0,0,0,,所以我们从<E2>开始找\nDialogue: 0,0:50:55.69,0:50:57.72,Default,,0,0,0,,'+既不在<E2> 也不在<E1>\nDialogue: 0,0:50:57.74,0:51:01.05,Default,,0,0,0,,‘+是<E0>中的基本运算符\nDialogue: 0,0:51:01.78,0:51:04.74,Default,,0,0,0,,这个基本运算符是用于加法的\nDialogue: 0,0:51:07.47,0:51:14.12,Default,,0,0,0,,把它应用于 在<E2>中求值X和Y的结果\nDialogue: 0,0:51:14.37,0:51:17.00,Default,,0,0,0,,我们知道X是3 Y是4\nDialogue: 0,0:51:18.11,0:51:23.31,Default,,0,0,0,,所以这里是'(3 4)\nDialogue: 0,0:51:24.16,0:51:26.28,Default,,0,0,0,,然后就神奇地得到结果7\nDialogue: 0,0:51:30.52,0:51:32.44,Default,,0,0,0,,我再来整理一下这个过程 这样你们\nDialogue: 0,0:51:32.70,0:51:34.73,Default,,0,0,0,,就能了解这其中的重要本质\nDialogue: 0,0:51:35.76,0:51:37.29,Default,,0,0,0,,这个过程中传递了些什么？\nDialogue: 0,0:51:37.31,0:51:39.56,Default,,0,0,0,,每个模块持有什么 又负责什么？\nDialogue: 0,0:51:40.47,0:51:41.61,Default,,0,0,0,,有哪些模块呢？\nDialogue: 0,0:51:41.70,0:51:42.62,Default,,0,0,0,,一个是EVAL\nDialogue: 0,0:51:44.80,0:51:45.64,Default,,0,0,0,,还有个APPLY\nDialogue: 0,0:51:45.66,0:51:46.62,Default,,0,0,0,,两个主要角色\nDialogue: 0,0:51:49.37,0:51:51.56,Default,,0,0,0,,它们之间有个像这样的大循环\nDialogue: 0,0:51:52.32,0:52:04.57,Default,,0,0,0,,其中 EVAL为APPLY生成过程和参数\nDialogue: 0,0:52:06.27,0:52:08.57,Default,,0,0,0,,也有些事情 EVAL也可以自己做\nDialogue: 0,0:52:09.50,0:52:10.86,Default,,0,0,0,,都是一些细小的事情\nDialogue: 0,0:52:10.86,0:52:11.74,Default,,0,0,0,,并不十分有趣\nDialogue: 0,0:52:12.70,0:52:15.60,Default,,0,0,0,,同时 EVAL也逐个求值所有的参数\nDialogue: 0,0:52:16.24,0:52:17.28,Default,,0,0,0,,也没什么意思\nDialogue: 0,0:52:17.65,0:52:20.09,Default,,0,0,0,,APPLY可以应用像+这类的过程\nDialogue: 0,0:52:21.02,0:52:22.04,Default,,0,0,0,,这很普通\nDialogue: 0,0:52:22.30,0:52:24.64,Default,,0,0,0,,然而 如果APPLY不能应用像+这样的过程\nDialogue: 0,0:52:25.31,0:52:33.31,Default,,0,0,0,,它就为EVAL生成一个表达式及相应的环境\nDialogue: 0,0:52:35.47,0:52:37.61,Default,,0,0,0,,过程的参数封装了\nDialogue: 0,0:52:38.24,0:52:40.60,Default,,0,0,0,,计算所必需的状态\nDialogue: 0,0:52:41.66,0:52:43.42,Default,,0,0,0,,以及相应的环境\nDialogue: 0,0:52:43.74,0:52:45.31,Default,,0,0,0,,但我们接下来要做的\nDialogue: 0,0:52:45.32,0:52:46.46,Default,,0,0,0,,并不是完整的状态\nDialogue: 0,0:52:46.48,0:52:48.82,Default,,0,0,0,,因为它没有说明谁需要返回的结果\nDialogue: 0,0:52:51.28,0:52:52.20,Default,,0,0,0,,我们要做的就是\nDialogue: 0,0:52:52.24,0:52:54.80,Default,,0,0,0,,总是把某个表达式以及相应的环境\nDialogue: 0,0:52:54.99,0:52:56.14,Default,,0,0,0,,或者过程对象以及其参数\nDialogue: 0,0:52:56.28,0:52:58.08,Default,,0,0,0,,在这个循环之间不断传递\nDialogue: 0,0:52:58.97,0:53:01.80,Default,,0,0,0,,这里还有一些小型的子循环 比如EVLIST\nDialogue: 0,0:53:04.49,0:53:06.76,Default,,0,0,0,,又或者是EVAL中的EVCOND循环\nDialogue: 0,0:53:09.10,0:53:11.96,Default,,0,0,0,,甚至于APPLY调用PRIMITIVE-APPLY\nDialogue: 0,0:53:16.14,0:53:17.64,Default,,0,0,0,,但是它们并不是最主要的\nDialogue: 0,0:53:18.86,0:53:20.28,Default,,0,0,0,,这整个就是我想让你们看到的\nDialogue: 0,0:53:21.86,0:53:22.88,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:53:25.93,0:53:27.37,Default,,0,0,0,,David 请说\nDialogue: 0,0:53:27.74,0:53:33.31,Default,,0,0,0,,学生：我不明白为什么X是3\nDialogue: 0,0:53:34.01,0:53:36.30,Default,,0,0,0,,而不是4\nDialogue: 0,0:53:37.07,0:53:38.52,Default,,0,0,0,,在那个部分\nDialogue: 0,0:53:38.56,0:53:40.54,Default,,0,0,0,,教授：是在这里\nDialogue: 0,0:53:41.31,0:53:43.31,Default,,0,0,0,,你想知道X是如何跟3绑定的\nDialogue: 0,0:53:43.52,0:53:47.42,Default,,0,0,0,,学生：因为X是外层过程的参数\nDialogue: 0,0:53:48.46,0:53:50.99,Default,,0,0,0,,而内层过程中既有X又有Y\nDialogue: 0,0:53:51.26,0:53:51.88,Default,,0,0,0,,教授：明白了\nDialogue: 0,0:53:52.84,0:53:54.62,Default,,0,0,0,,代换的过程中 我已经非常小心了\nDialogue: 0,0:53:55.02,0:53:56.92,Default,,0,0,0,,或许首先 我应该把这些过程\nDialogue: 0,0:53:56.94,0:53:58.41,Default,,0,0,0,,重新编排得更易读一点\nDialogue: 0,0:54:00.61,0:54:01.47,Default,,0,0,0,,你之所以有所疑惑\nDialogue: 0,0:54:01.48,0:54:02.99,Default,,0,0,0,,或许是因为你把程序看岔了\nDialogue: 0,0:54:03.83,0:54:04.70,Default,,0,0,0,,所以这里应该是\nDialogue: 0,0:54:05.15,0:54:09.60,Default,,0,0,0,,一个以X为参数的过程\nDialogue: 0,0:54:11.21,0:54:14.99,Default,,0,0,0,,它返回一个以Y为参数的过程\nDialogue: 0,0:54:15.72,0:54:18.44,Default,,0,0,0,,后者计算X+Y\nDialogue: 0,0:54:19.82,0:54:21.10,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:54:21.40,0:54:22.89,Default,,0,0,0,,外面的过程应用到3上\nDialogue: 0,0:54:24.08,0:54:26.12,Default,,0,0,0,,把得到的结果应用到4上\nDialogue: 0,0:54:26.14,0:54:28.81,Default,,0,0,0,,这个和之前那个是一样的 对吧？\nDialogue: 0,0:54:28.81,0:54:32.33,Default,,0,0,0,,现在 你可以立马发现\nDialogue: 0,0:54:33.77,0:54:34.94,Default,,0,0,0,,这里是一个应用\nDialogue: 0,0:54:35.16,0:54:36.46,Default,,0,0,0,,我先换根白粉笔\nDialogue: 0,0:54:37.32,0:54:41.12,Default,,0,0,0,,这一部分是应用 是一个组合式\nDialogue: 0,0:54:43.44,0:54:46.40,Default,,0,0,0,,这部分是组合式的运算符\nDialogue: 0,0:54:48.14,0:54:49.55,Default,,0,0,0,,而这是运算对象\nDialogue: 0,0:54:51.04,0:54:53.05,Default,,0,0,0,,这个3会跟这里的X绑定\nDialogue: 0,0:54:54.90,0:54:56.36,Default,,0,0,0,,而这个组合式的结果\nDialogue: 0,0:54:56.56,0:54:58.46,Default,,0,0,0,,是一个参数为Y的一元过程\nDialogue: 0,0:54:58.73,0:54:59.79,Default,,0,0,0,,它将应用于4\nDialogue: 0,0:55:00.88,0:55:01.58,Default,,0,0,0,,明白了吧？\nDialogue: 0,0:55:02.20,0:55:04.08,Default,,0,0,0,,所以你可能只是看岔了\nDialogue: 0,0:55:04.40,0:55:07.85,Default,,0,0,0,,而你们在这里看到的\nDialogue: 0,0:55:09.42,0:55:12.96,Default,,0,0,0,,是一个实际的过程对象 它有一个参数X\nDialogue: 0,0:55:13.34,0:55:15.31,Default,,0,0,0,,这个CLOSURE将应用于3\nDialogue: 0,0:55:15.95,0:55:17.07,Default,,0,0,0,,也就是'(3)\nDialogue: 0,0:55:18.98,0:55:21.34,Default,,0,0,0,,得到的结果再应用于'(4)\nDialogue: 0,0:55:24.08,0:55:25.20,Default,,0,0,0,,还有疑问吗？\nDialogue: 0,0:55:28.35,0:55:30.38,Default,,0,0,0,,那就休息一下吧\nDialogue: 0,0:55:30.83,0:55:31.37,Default,,0,0,0,,谢谢大家\nDialogue: 0,0:55:33.73,0:55:41.40,Default,,0,0,0,,[音乐]\nDialogue: 0,0:55:42.12,0:55:47.44,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:55:50.70,0:55:54.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:55:54.12,0:55:59.16,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:55:59.23,0:56:03.95,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 I\nDialogue: 0,0:56:08.41,0:56:11.29,Default,,0,0,0,,教授：课上到这里\nDialogue: 0,0:56:13.32,0:56:14.59,Default,,0,0,0,,你们可能开始觉得\nDialogue: 0,0:56:14.75,0:56:17.96,Default,,0,0,0,,Sussman教授又在胡说八道些什么\nDialogue: 0,0:56:20.74,0:56:23.92,Default,,0,0,0,,他讲的东西奇怪、愚蠢又毫无意义\nDialogue: 0,0:56:24.80,0:56:27.40,Default,,0,0,0,,他还宣称要给我们解释Lisp\nDialogue: 0,0:56:28.01,0:56:29.90,Default,,0,0,0,,然后在黑板上给我们写了一个Lisp程序\nDialogue: 0,0:56:31.23,0:56:33.53,Default,,0,0,0,,他还说：“这个Lisp程序就是Lisp解释器”\nDialogue: 0,0:56:33.85,0:56:35.02,Default,,0,0,0,,但是为了运行这个Lisp程序\nDialogue: 0,0:56:35.04,0:56:36.30,Default,,0,0,0,,你还先得有一个Lisp解释器啊\nDialogue: 0,0:56:38.37,0:56:40.19,Default,,0,0,0,,那个程序怎么能告诉我\nDialogue: 0,0:56:40.22,0:56:43.20,Default,,0,0,0,,有关于Lisp的知识呢？\nDialogue: 0,0:56:44.15,0:56:46.22,Default,,0,0,0,,它为什么又不是空中楼阁呢？\nDialogue: 0,0:56:48.49,0:56:50.25,Default,,0,0,0,,这件事非常奇怪\nDialogue: 0,0:56:50.99,0:56:52.43,Default,,0,0,0,,它究竟告诉了我什么？\nDialogue: 0,0:56:56.07,0:56:57.20,Default,,0,0,0,,我们发现 其实这整件事\nDialogue: 0,0:56:57.32,0:56:59.79,Default,,0,0,0,,非常像我们在这张幻灯片上看到的\nDialogue: 0,0:57:00.46,0:57:03.55,Default,,0,0,0,,Escher所画的手\nDialogue: 0,0:57:06.18,0:57:07.72,Default,,0,0,0,,是的 EVAL和APPLY\nDialogue: 0,0:57:07.76,0:57:10.16,Default,,0,0,0,,彼此画出彼此\nDialogue: 0,0:57:11.50,0:57:14.16,Default,,0,0,0,,并且构造出了真实的东西\nDialogue: 0,0:57:14.86,0:57:16.30,Default,,0,0,0,,它完全是自己画出了自己\nDialogue: 0,0:57:17.11,0:57:18.46,Default,,0,0,0,,Escher真是绝顶聪明\nDialogue: 0,0:57:18.68,0:57:20.41,Default,,0,0,0,,他只不过叫不出这些精灵的名字\nDialogue: 0,0:57:23.91,0:57:25.00,Default,,0,0,0,,我现在要做的就是\nDialogue: 0,0:57:26.09,0:57:28.00,Default,,0,0,0,,使你们相信\nDialogue: 0,0:57:28.16,0:57:29.87,Default,,0,0,0,,这一切都是有意义的\nDialogue: 0,0:57:30.16,0:57:31.98,Default,,0,0,0,,并且\nDialogue: 0,0:57:32.99,0:57:34.72,Default,,0,0,0,,我将要解释为什么我们不需要DEFINE\nDialogue: 0,0:57:36.09,0:57:37.71,Default,,0,0,0,,事实证明 我们并不需要DEFINE\nDialogue: 0,0:57:38.09,0:57:41.12,Default,,0,0,0,,为了进行数学意义上的计算\nDialogue: 0,0:57:42.51,0:57:44.89,Default,,0,0,0,,DEFINE并不是必需的\nDialogue: 0,0:57:49.10,0:57:50.03,Default,,0,0,0,,我们来看一下\nDialogue: 0,0:57:50.69,0:57:53.31,Default,,0,0,0,,考虑下面的一小段程序\nDialogue: 0,0:57:53.74,0:57:54.64,Default,,0,0,0,,它有什么作用？\nDialogue: 0,0:57:54.87,0:57:57.64,Default,,0,0,0,,这是一个计算指数的程序\nDialogue: 0,0:58:07.27,0:58:13.23,Default,,0,0,0,,EXPT计算X的N次方\nDialogue: 0,0:58:16.83,0:58:18.12,Default,,0,0,0,,如果N为0\nDialogue: 0,0:58:19.20,0:58:20.76,Default,,0,0,0,,那么结果就是1\nDialogue: 0,0:58:22.07,0:58:22.81,Default,,0,0,0,,否则\nDialogue: 0,0:58:25.56,0:58:28.48,Default,,0,0,0,,结果就是X乘以\nDialogue: 0,0:58:28.75,0:58:33.93,Default,,0,0,0,,(EXPT X (- N 1))))\nDialogue: 0,0:58:43.69,0:58:44.56,Default,,0,0,0,,应该没错\nDialogue: 0,0:58:46.63,0:58:48.72,Default,,0,0,0,,一个递归定义\nDialogue: 0,0:58:49.47,0:58:52.17,Default,,0,0,0,,用EXPT自身\nDialogue: 0,0:58:52.46,0:58:54.78,Default,,0,0,0,,来定义EXPT过程自己\nDialogue: 0,0:58:56.41,0:58:58.32,Default,,0,0,0,,就像我之前说的那样\nDialogue: 0,0:58:59.28,0:59:01.68,Default,,0,0,0,,你们高中数学老师在教这些东西的时候\nDialogue: 0,0:59:01.84,0:59:04.04,Default,,0,0,0,,你们一定学得很痛苦\nDialogue: 0,0:59:05.65,0:59:06.73,Default,,0,0,0,,这样定义合理吗？\nDialogue: 0,0:59:07.91,0:59:10.84,Default,,0,0,0,,为什么这种自引用的定义\nDialogue: 0,0:59:10.96,0:59:12.04,Default,,0,0,0,,能够说得通呢？\nDialogue: 0,0:59:13.43,0:59:15.10,Default,,0,0,0,,首先我要说的是\nDialogue: 0,0:59:15.13,0:59:17.60,Default,,0,0,0,,你们高中数学老师并非在胡说八道\nDialogue: 0,0:59:20.37,0:59:23.42,Default,,0,0,0,,考虑下面的几组定义\nDialogue: 0,0:59:24.27,0:59:27.42,Default,,0,0,0,,X+Y=3\nDialogue: 0,0:59:28.24,0:59:32.24,Default,,0,0,0,,X-Y=1\nDialogue: 0,0:59:33.07,0:59:35.56,Default,,0,0,0,,这个方程用Y来告诉你X\nDialogue: 0,0:59:35.58,0:59:37.84,Default,,0,0,0,,而这个方程或许是用X来告诉你Y\nDialogue: 0,0:59:40.15,0:59:42.95,Default,,0,0,0,,碰巧这组方程有唯一的解\nDialogue: 0,0:59:55.91,0:59:58.11,Default,,0,0,0,,然而 我也可能有这样的方程\nDialogue: 0,0:59:59.87,1:00:04.25,Default,,0,0,0,,2X+2Y=6\nDialogue: 0,1:00:06.83,1:00:09.87,Default,,0,0,0,,这两个方程有无穷多个解\nDialogue: 0,1:00:15.73,1:00:17.42,Default,,0,0,0,,我还可以有像这样的方程\nDialogue: 0,1:00:18.89,1:00:21.53,Default,,0,0,0,,X-Y=2\nDialogue: 0,1:00:22.14,1:00:24.41,Default,,0,0,0,,而下面的这两个方程没有解\nDialogue: 0,1:00:29.82,1:00:33.04,Default,,0,0,0,,这里 我有三组线性方程组\nDialogue: 0,1:00:35.45,1:00:39.51,Default,,0,0,0,,分别是这组、这组和这组\nDialogue: 0,1:00:39.88,1:00:41.79,Default,,0,0,0,,它们的解的数目完全不同\nDialogue: 0,1:00:42.90,1:00:45.76,Default,,0,0,0,,解的数目并不取决于方程的形式\nDialogue: 0,1:00:46.33,1:00:48.20,Default,,0,0,0,,三组方程都有一样的形式\nDialogue: 0,1:00:48.54,1:00:50.41,Default,,0,0,0,,解的数目取决于方程的内容\nDialogue: 0,1:00:53.00,1:00:55.15,Default,,0,0,0,,我不能通过观察方程的形式\nDialogue: 0,1:00:55.16,1:00:56.24,Default,,0,0,0,,来判断解的数目\nDialogue: 0,1:00:56.86,1:00:58.60,Default,,0,0,0,,必须要看它的内容\nDialogue: 0,1:00:59.66,1:01:00.88,Default,,0,0,0,,比如 对于线性方程组\nDialogue: 0,1:01:01.34,1:01:03.39,Default,,0,0,0,,它的系数都是什么？\nDialogue: 0,1:01:05.10,1:01:06.72,Default,,0,0,0,,我不能够通过观察\nDialogue: 0,1:01:06.99,1:01:08.33,Default,,0,0,0,,像这样的简单情况\nDialogue: 0,1:01:08.59,1:01:09.95,Default,,0,0,0,,来判定\nDialogue: 0,1:01:10.08,1:01:14.49,Default,,0,0,0,,EXPT就是这个递归方程的解\nDialogue: 0,1:01:16.03,1:01:18.41,Default,,0,0,0,,我不能说 EXPT就是那个过程\nDialogue: 0,1:01:18.91,1:01:21.10,Default,,0,0,0,,如果我们把它代换入其中\nDialogue: 0,1:01:22.04,1:01:24.06,Default,,0,0,0,,它就能给我们返回EXPT\nDialogue: 0,1:01:25.32,1:01:25.68,Default,,0,0,0,,能跟上吗？\nDialogue: 0,1:01:26.04,1:01:29.24,Default,,0,0,0,,通过观察这个形式 我也无法判别\nDialogue: 0,1:01:29.80,1:01:32.60,Default,,0,0,0,,EXPT是否有唯一解\nDialogue: 0,1:01:33.23,1:01:35.31,Default,,0,0,0,,有无穷个解 还是根本没有解\nDialogue: 0,1:01:37.20,1:01:38.62,Default,,0,0,0,,我们要了解它是如何计数的\nDialogue: 0,1:01:38.64,1:01:40.14,Default,,0,0,0,,或者是一些类似的计算细节\nDialogue: 0,1:01:40.60,1:01:42.75,Default,,0,0,0,,这可比在线性代数难多了\nDialogue: 0,1:01:43.28,1:01:45.21,Default,,0,0,0,,程序设计中可用的定理并不多\nDialogue: 0,1:01:48.45,1:01:51.21,Default,,0,0,0,,我想把这些方程稍稍重写一下\nDialogue: 0,1:01:51.93,1:01:53.77,Default,,0,0,0,,就是这里的方程\nDialogue: 0,1:01:53.97,1:01:56.62,Default,,0,0,0,,因为我们要研究的是这种形式的方程\nDialogue: 0,1:01:57.00,1:01:58.38,Default,,0,0,0,,但是我想用我们比较了解的方程\nDialogue: 0,1:01:58.40,1:01:59.53,Default,,0,0,0,,来做演示\nDialogue: 0,1:02:00.70,1:02:02.91,Default,,0,0,0,,以便于对于这类问题有深入的洞见\nDialogue: 0,1:02:04.72,1:02:06.43,Default,,0,0,0,,我们可以把这里的方程 改写为\nDialogue: 0,1:02:06.75,1:02:08.67,Default,,0,0,0,,这样的一种有趣形式\nDialogue: 0,1:02:09.77,1:02:14.86,Default,,0,0,0,,X=3-Y\nDialogue: 0,1:02:15.88,1:02:19.68,Default,,0,0,0,,Y=X-1\nDialogue: 0,1:02:22.01,1:02:24.05,Default,,0,0,0,,我们把这种变换叫什么来着？\nDialogue: 0,1:02:24.05,1:02:26.52,Default,,0,0,0,,这是一个线性变换 记为T\nDialogue: 0,1:02:29.43,1:02:32.25,Default,,0,0,0,,我们这里就得到了一个方程\nDialogue: 0,1:02:32.97,1:02:37.37,Default,,0,0,0,,<X Y> = T<X Y>\nDialogue: 0,1:02:42.99,1:02:43.98,Default,,0,0,0,,我要去找什么呢？\nDialogue: 0,1:02:44.56,1:02:46.01,Default,,0,0,0,,我在找T的不动点\nDialogue: 0,1:02:46.97,1:02:59.42,Default,,0,0,0,,T的不动点就是方程的解\nDialogue: 0,1:03:01.91,1:03:05.53,Default,,0,0,0,,所以 如果我们能通过找不动点\nDialogue: 0,1:03:05.90,1:03:07.48,Default,,0,0,0,,来求解方程\nDialogue: 0,1:03:08.65,1:03:09.87,Default,,0,0,0,,这看来是可行的\nDialogue: 0,1:03:10.88,1:03:12.36,Default,,0,0,0,,如果我可以用不动点\nDialogue: 0,1:03:12.38,1:03:14.32,Default,,0,0,0,,来求解方程\nDialogue: 0,1:03:15.52,1:03:18.19,Default,,0,0,0,,当然 也许它不可行\nDialogue: 0,1:03:18.57,1:03:19.80,Default,,0,0,0,,不过也可以借鉴来\nDialogue: 0,1:03:20.09,1:03:22.27,Default,,0,0,0,,研究如何求解这类方程\nDialogue: 0,1:03:27.24,1:03:29.48,Default,,0,0,0,,重要的是 我想让你们把它看成一个方程\nDialogue: 0,1:03:30.26,1:03:31.21,Default,,0,0,0,,它是一个表达式\nDialogue: 0,1:03:31.36,1:03:33.58,Default,,0,0,0,,其中有不同的变量\nDialogue: 0,1:03:34.70,1:03:37.66,Default,,0,0,0,,只不过这些名字还得满足一定的约束\nDialogue: 0,1:03:38.43,1:03:40.52,Default,,0,0,0,,这些名字限定了对应变量的取值\nDialogue: 0,1:03:41.48,1:03:45.01,Default,,0,0,0,,我们不能够随意、机械地代换\nDialogue: 0,1:03:47.74,1:03:49.77,Default,,0,0,0,,这就是我尝试求解的方程\nDialogue: 0,1:03:51.22,1:03:52.43,Default,,0,0,0,,我们来试试看\nDialogue: 0,1:03:53.96,1:03:55.66,Default,,0,0,0,,首先我需要写下\nDialogue: 0,1:03:56.64,1:03:59.00,Default,,0,0,0,,跟T相对应的函数\nDialogue: 0,1:04:00.32,1:04:03.00,Default,,0,0,0,,我写下的这个T对应的函数\nDialogue: 0,1:04:04.49,1:04:06.96,Default,,0,0,0,,它的不动点就是这个方程的解\nDialogue: 0,1:04:10.76,1:04:11.28,Default,,0,0,0,,能明白吗？\nDialogue: 0,1:04:12.25,1:04:14.30,Default,,0,0,0,,让我们来看下面这个过程F\nDialogue: 0,1:04:16.87,1:04:18.30,Default,,0,0,0,,我说 F计算的是这样一个函数\nDialogue: 0,1:04:19.34,1:04:22.91,Default,,0,0,0,,F本身是一个参数为G的一元过程\nDialogue: 0,1:04:25.23,1:04:25.93,Default,,0,0,0,,它返回\nDialogue: 0,1:04:26.40,1:04:32.00,Default,,0,0,0,,一个参数为X和N的过程\nDialogue: 0,1:04:33.43,1:04:34.73,Default,,0,0,0,,这个过程的定义是：\nDialogue: 0,1:04:36.72,1:04:40.43,Default,,0,0,0,,如果N为0\nDialogue: 0,1:04:41.72,1:04:43.20,Default,,0,0,0,,那么结果就是1\nDialogue: 0,1:04:45.34,1:04:46.17,Default,,0,0,0,,否则的话\nDialogue: 0,1:04:49.90,1:05:01.40,Default,,0,0,0,,结果就是(* X (G X (- N 1)))\nDialogue: 0,1:05:03.37,1:05:07.80,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,1:05:08.94,1:05:09.40,Default,,0,0,0,,没问题吧\nDialogue: 0,1:05:12.30,1:05:14.62,Default,,0,0,0,,这里 F是一个过程\nDialogue: 0,1:05:15.05,1:05:17.79,Default,,0,0,0,,如果我能解出这个方程\nDialogue: 0,1:05:19.04,1:05:22.04,Default,,0,0,0,,如果我找到了一个良好的指数过程\nDialogue: 0,1:05:23.42,1:05:26.32,Default,,0,0,0,,我把这个F应用到那个过程上\nDialogue: 0,1:05:27.60,1:05:31.24,Default,,0,0,0,,那么返回的应该也是一个良好的指数过程\nDialogue: 0,1:05:37.46,1:05:38.57,Default,,0,0,0,,这是为什么呢？\nDialogue: 0,1:05:39.42,1:05:40.88,Default,,0,0,0,,这是因为\nDialogue: 0,1:05:42.36,1:05:44.64,Default,,0,0,0,,F假设G是一个良好的指数过程\nDialogue: 0,1:05:45.63,1:05:47.58,Default,,0,0,0,,那么这里就会返回\nDialogue: 0,1:05:47.84,1:05:49.68,Default,,0,0,0,,一个参数为X和N的过程\nDialogue: 0,1:05:50.49,1:05:51.52,Default,,0,0,0,,其中如果N=0\nDialogue: 0,1:05:51.55,1:05:52.41,Default,,0,0,0,,结果就是1\nDialogue: 0,1:05:52.44,1:05:54.16,Default,,0,0,0,,这是非常符合定义的\nDialogue: 0,1:05:54.64,1:05:57.05,Default,,0,0,0,,否则 就返回X乘以\nDialogue: 0,1:05:57.26,1:05:59.26,Default,,0,0,0,,用给定的指数过程G\nDialogue: 0,1:06:00.17,1:06:02.44,Default,,0,0,0,,计算(G X (- N 1))\nDialogue: 0,1:06:03.47,1:06:04.78,Default,,0,0,0,,因此如果G能够\nDialogue: 0,1:06:04.81,1:06:06.30,Default,,0,0,0,,正确计算X^(N-1)\nDialogue: 0,1:06:07.87,1:06:11.28,Default,,0,0,0,,那么这个表达式就能正确计算X^N\nDialogue: 0,1:06:12.17,1:06:14.41,Default,,0,0,0,,所以整个就会是一个正确的求指数过程\nDialogue: 0,1:06:17.50,1:06:19.82,Default,,0,0,0,,因此 我在这里真正想指出的是\nDialogue: 0,1:06:21.02,1:06:32.44,Default,,0,0,0,,过程EXPT是函数F的不动点\nDialogue: 0,1:06:36.99,1:06:38.35,Default,,0,0,0,,现在我们的问题在于\nDialogue: 0,1:06:38.35,1:06:39.68,Default,,0,0,0,,不动点可能不止一个\nDialogue: 0,1:06:40.06,1:06:42.19,Default,,0,0,0,,也可能没有不动点\nDialogue: 0,1:06:43.27,1:06:44.81,Default,,0,0,0,,所以我们必须求出不动点\nDialogue: 0,1:06:48.22,1:06:49.37,Default,,0,0,0,,需要来解这个方程\nDialogue: 0,1:06:52.16,1:06:54.28,Default,,0,0,0,,求不动点的方法有很多种\nDialogue: 0,1:06:55.58,1:06:57.08,Default,,0,0,0,,本门课程的第一节课\nDialogue: 0,1:06:57.24,1:07:01.16,Default,,0,0,0,,我们就用余弦函数做了演示\nDialogue: 0,1:07:02.73,1:07:07.69,Default,,0,0,0,,先把你的计算器调成弧度制\nDialogue: 0,1:07:07.85,1:07:10.51,Default,,0,0,0,,然后一直按COS键\nDialogue: 0,1:07:11.84,1:07:15.45,Default,,0,0,0,,最后数字会稳定在0.73、0.74左右\nDialogue: 0,1:07:16.09,1:07:17.18,Default,,0,0,0,,我记不清是哪个了\nDialogue: 0,1:07:20.57,1:07:22.64,Default,,0,0,0,,通过迭代一个过程\nDialogue: 0,1:07:22.81,1:07:24.40,Default,,0,0,0,,我们不断迭代\nDialogue: 0,1:07:25.60,1:07:27.16,Default,,0,0,0,,想要寻找不动点的函数\nDialogue: 0,1:07:27.50,1:07:31.13,Default,,0,0,0,,有时候 它就会收敛在一个点上\nDialogue: 0,1:07:31.87,1:07:33.08,Default,,0,0,0,,这就是不动点\nDialogue: 0,1:07:33.77,1:07:35.44,Default,,0,0,0,,碰碰运气\nDialogue: 0,1:07:36.44,1:07:37.21,Default,,0,0,0,,来试试这种方法\nDialogue: 0,1:07:39.91,1:07:46.28,Default,,0,0,0,,来看这张幻灯片\nDialogue: 0,1:07:48.03,1:07:51.71,Default,,0,0,0,,考虑这么一连串的过程\nDialogue: 0,1:07:56.40,1:07:57.79,Default,,0,0,0,,这里的E0\nDialogue: 0,1:07:59.24,1:08:01.63,Default,,0,0,0,,这个E0过程什么也不做\nDialogue: 0,1:08:02.89,1:08:05.10,Default,,0,0,0,,无论你给它传递什么参数\nDialogue: 0,1:08:05.10,1:08:06.24,Default,,0,0,0,,它都会产生ERROR\nDialogue: 0,1:08:07.78,1:08:09.03,Default,,0,0,0,,基本上没什么用\nDialogue: 0,1:08:14.48,1:08:20.08,Default,,0,0,0,,然而 我可以做近似\nDialogue: 0,1:08:20.08,1:08:23.93,Default,,0,0,0,,让我们考虑下 指数过程的最差近似\nDialogue: 0,1:08:24.73,1:08:25.53,Default,,0,0,0,,因为它什么也做不了\nDialogue: 0,1:08:26.99,1:08:29.68,Default,,0,0,0,,假设我调用F\nDialogue: 0,1:08:30.35,1:08:33.26,Default,,0,0,0,,用E0去代换G\nDialogue: 0,1:08:33.79,1:08:36.30,Default,,0,0,0,,这里 G就被代换为了E0\nDialogue: 0,1:08:37.38,1:08:39.77,Default,,0,0,0,,所以在这里就是E0\nDialogue: 0,1:08:40.84,1:08:42.35,Default,,0,0,0,,那么E1又成了什么呢？\nDialogue: 0,1:08:43.63,1:08:46.03,Default,,0,0,0,,如果用E1来计算X^0\nDialogue: 0,1:08:46.67,1:08:48.78,Default,,0,0,0,,没什么问题\nDialogue: 0,1:08:49.60,1:08:50.75,Default,,0,0,0,,它返回的结果是正确的\nDialogue: 0,1:08:51.05,1:08:52.35,Default,,0,0,0,,任何数的0次幂都是1\nDialogue: 0,1:08:52.68,1:08:54.25,Default,,0,0,0,,然而计算其它次幂就会出错\nDialogue: 0,1:08:57.39,1:09:01.56,Default,,0,0,0,,现在如果我用E1来调用F\nDialogue: 0,1:09:02.30,1:09:07.40,Default,,0,0,0,,把G代换为E1 会发生什么？\nDialogue: 0,1:09:09.58,1:09:11.18,Default,,0,0,0,,这样的话\nDialogue: 0,1:09:12.01,1:09:15.02,Default,,0,0,0,,我就会得到这个二元过程\nDialogue: 0,1:09:15.67,1:09:16.84,Default,,0,0,0,,想一想 E1这个过程\nDialogue: 0,1:09:16.96,1:09:19.66,Default,,0,0,0,,只能正确计算X^0\nDialogue: 0,1:09:21.47,1:09:23.37,Default,,0,0,0,,它只能计算0次幂\nDialogue: 0,1:09:24.20,1:09:25.00,Default,,0,0,0,,所以这里\nDialogue: 0,1:09:25.52,1:09:27.28,Default,,0,0,0,,如果N为0 结果就是1\nDialogue: 0,1:09:27.29,1:09:28.67,Default,,0,0,0,,E2的这部分也正确\nDialogue: 0,1:09:29.52,1:09:32.01,Default,,0,0,0,,然而 我可以通过把0次幂乘以X\nDialogue: 0,1:09:32.51,1:09:35.26,Default,,0,0,0,,来计算1次幂\nDialogue: 0,1:09:35.97,1:09:39.67,Default,,0,0,0,,所以E2可以正确计算0次幂和1次幂\nDialogue: 0,1:09:41.60,1:09:41.92,Default,,0,0,0,,对吧？\nDialogue: 0,1:09:43.71,1:09:46.67,Default,,0,0,0,,E3的构造过程和E2是类似的\nDialogue: 0,1:09:47.89,1:09:50.24,Default,,0,0,0,,当然 E3具有同样的参数\nDialogue: 0,1:09:50.32,1:09:53.37,Default,,0,0,0,,能够正确计算0、1、2次幂\nDialogue: 0,1:09:55.12,1:09:55.40,Default,,0,0,0,,对吧？\nDialogue: 0,1:09:56.09,1:09:59.08,Default,,0,0,0,,因此我就不加证明地告诉你结论\nDialogue: 0,1:09:59.66,1:10:01.72,Default,,0,0,0,,因为这个证明过程太难了\nDialogue: 0,1:10:02.52,1:10:03.60,Default,,0,0,0,,这种事情\nDialogue: 0,1:10:03.63,1:10:06.36,Default,,0,0,0,,是由人们所谓“指称语义学家”完成的\nDialogue: 0,1:10:06.59,1:10:07.64,Default,,0,0,0,,这个伟大的想法\nDialogue: 0,1:10:07.87,1:10:10.59,Default,,0,0,0,,应该是由Scott和Strachey提出的\nDialogue: 0,1:10:11.64,1:10:16.32,Default,,0,0,0,,他们是非常著名的数学家\nDialogue: 0,1:10:16.86,1:10:21.21,Default,,0,0,0,,他们发明了这些程序的解释方式\nDialogue: 0,1:10:22.36,1:10:24.00,Default,,0,0,0,,就是我刚才讲的那些\nDialogue: 0,1:10:24.24,1:10:26.17,Default,,0,0,0,,他们通过拓扑学的方法证明了\nDialogue: 0,1:10:27.04,1:10:29.32,Default,,0,0,0,,在我们刚才那种情况下\nDialogue: 0,1:10:29.82,1:10:31.26,Default,,0,0,0,,不动点是存在的\nDialogue: 0,1:10:32.22,1:10:33.24,Default,,0,0,0,,这个结论就是：\nDialogue: 0,1:10:33.40,1:10:44.24,Default,,0,0,0,,当N趋近于无穷时 EXPT是E(N)的极限\nDialogue: 0,1:10:45.52,1:10:47.90,Default,,0,0,0,,我们是通过下面这种方式来构造这个极限的\nDialogue: 0,1:10:50.52,1:10:55.66,Default,,0,0,0,,EXPT=(F (F (F (F ....\nDialogue: 0,1:10:57.61,1:11:00.19,Default,,0,0,0,,(F 丄)\nDialogue: 0,1:11:01.12,1:11:02.46,Default,,0,0,0,,它是什么都无所谓\nDialogue: 0,1:11:03.18,1:11:05.00,Default,,0,0,0,,因为它总会生成一个错误\nDialogue: 0,1:11:07.45,1:11:08.41,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,1:11:12.89,1:11:14.48,Default,,0,0,0,,这是F无穷嵌套调用\nDialogue: 0,1:11:16.38,1:11:17.71,Default,,0,0,0,,现在我们的问题\nDialogue: 0,1:11:18.22,1:11:19.76,Default,,0,0,0,,又变成了如何构造出无穷调用\nDialogue: 0,1:11:22.59,1:11:24.08,Default,,0,0,0,,我们需要它们\nDialogue: 0,1:11:24.92,1:11:26.25,Default,,0,0,0,,我怎样才能把F\nDialogue: 0,1:11:26.56,1:11:27.80,Default,,0,0,0,,嵌套无穷层呢？\nDialogue: 0,1:11:28.98,1:11:30.12,Default,,0,0,0,,我得把它构造出来\nDialogue: 0,1:11:32.38,1:11:32.93,Default,,0,0,0,,好吧 我不知道\nDialogue: 0,1:11:32.93,1:11:34.32,Default,,0,0,0,,到底怎么样构建一个无穷循环呢？\nDialogue: 0,1:11:34.81,1:11:36.32,Default,,0,0,0,,我们先来看个非常简单的无穷循环\nDialogue: 0,1:11:36.57,1:11:38.34,Default,,0,0,0,,能想到的最简单的无穷循环\nDialogue: 0,1:11:43.55,1:11:47.55,Default,,0,0,0,,把这样一个参数为X的函数过程\nDialogue: 0,1:11:48.00,1:11:49.79,Default,,0,0,0,,过程体是(X X)\nDialogue: 0,1:11:53.55,1:11:53.92,Default,,0,0,0,,看到了吧？\nDialogue: 0,1:11:55.05,1:11:58.41,Default,,0,0,0,,应用在一个参数为X过程上\nDialogue: 0,1:11:59.36,1:12:01.05,Default,,0,0,0,,后者的过程体也是(X X)\nDialogue: 0,1:12:04.83,1:12:06.00,Default,,0,0,0,,这就形成了一个无穷循环\nDialogue: 0,1:12:07.21,1:12:09.31,Default,,0,0,0,,这个循环之所以是无穷的\nDialogue: 0,1:12:09.98,1:12:11.31,Default,,0,0,0,,是因为\nDialogue: 0,1:12:11.52,1:12:13.69,Default,,0,0,0,,我用实际参数代换掉\nDialogue: 0,1:12:14.22,1:12:16.59,Default,,0,0,0,,过程体的形式参数\nDialogue: 0,1:12:18.85,1:12:21.60,Default,,0,0,0,,这样做了以后 这里的每个X\nDialogue: 0,1:12:22.40,1:12:23.76,Default,,0,0,0,,都被代换为了这个\nDialogue: 0,1:12:24.36,1:12:26.96,Default,,0,0,0,,相当于把最初的表达式又复制了一遍\nDialogue: 0,1:12:28.35,1:12:29.37,Default,,0,0,0,,这就是最简单的无穷循环\nDialogue: 0,1:12:35.44,1:12:39.29,Default,,0,0,0,,现在 我要介绍一个特殊的运算符\nDialogue: 0,1:12:40.38,1:12:43.09,Default,,0,0,0,,它是通过对这个无穷循环稍作修改而来\nDialogue: 0,1:12:46.96,1:12:47.92,Default,,0,0,0,,我把它记作“Y”\nDialogue: 0,1:12:50.89,1:12:55.82,Default,,0,0,0,,它的全称是：Curry的矛盾Y组合子\nDialogue: 0,1:12:56.62,1:12:58.99,Default,,0,0,0,,这是用二十世纪三十年代的逻辑学家\nDialogue: 0,1:12:59.34,1:13:01.85,Default,,0,0,0,,Curry的名字来命名的\nDialogue: 0,1:13:04.48,1:13:06.88,Default,,0,0,0,,Y组合子是一个参数为f的过程\nDialogue: 0,1:13:08.17,1:13:09.33,Default,,0,0,0,,它的过程体是什么呢？\nDialogue: 0,1:13:09.33,1:13:11.20,Default,,0,0,0,,它的内部是某种无穷循环\nDialogue: 0,1:13:11.98,1:13:15.47,Default,,0,0,0,,是一个参数为x的过程\nDialogue: 0,1:13:15.95,1:13:18.80,Default,,0,0,0,,它调用(f (x x))\nDialogue: 0,1:13:21.63,1:13:24.75,Default,,0,0,0,,这个过程应用在一个参数为X的过程上\nDialogue: 0,1:13:25.10,1:13:27.34,Default,,0,0,0,,后者调用(f (x x))\nDialogue: 0,1:13:32.30,1:13:33.13,Default,,0,0,0,,这个是怎么运作的？\nDialogue: 0,1:13:34.80,1:13:36.06,Default,,0,0,0,,假设执行(Y F)\nDialogue: 0,1:13:41.31,1:13:42.57,Default,,0,0,0,,这非常简单\nDialogue: 0,1:13:43.15,1:13:44.62,Default,,0,0,0,,这里大写的F跟那边的是同一个\nDialogue: 0,1:13:46.91,1:13:48.16,Default,,0,0,0,,在这里 很简单\nDialogue: 0,1:13:48.30,1:13:49.92,Default,,0,0,0,,我把F代换到这里来\nDialogue: 0,1:13:55.32,1:13:57.07,Default,,0,0,0,,基本上 我就会得到\nDialogue: 0,1:13:58.75,1:14:00.84,Default,,0,0,0,,因为我待会儿要用这个表达式\nDialogue: 0,1:14:01.45,1:14:02.80,Default,,0,0,0,,代换这里的x\nDialogue: 0,1:14:04.17,1:14:05.23,Default,,0,0,0,,这里就是(F\nDialogue: 0,1:14:08.97,1:14:10.09,Default,,0,0,0,,我还是把这步写出来吧\nDialogue: 0,1:14:10.22,1:14:11.45,Default,,0,0,0,,这样你们就能看得更全面\nDialogue: 0,1:14:11.92,1:14:14.27,Default,,0,0,0,,我会非常小心 好吗？\nDialogue: 0,1:14:15.02,1:14:18.25,Default,,0,0,0,,这里是 ((LAMBDA (x)\nDialogue: 0,1:14:19.08,1:14:22.11,Default,,0,0,0,,(F (x x))\nDialogue: 0,1:14:26.88,1:14:35.55,Default,,0,0,0,,把它应用到自身 (LAMBDA (x) (F (x x)))\nDialogue: 0,1:14:37.91,1:14:39.66,Default,,0,0,0,,把这个表达式代换进去\nDialogue: 0,1:14:40.06,1:14:40.91,Default,,0,0,0,,就得到\nDialogue: 0,1:14:43.13,1:14:48.35,Default,,0,0,0,,把这个代进去 得到什么呢？\nDialogue: 0,1:14:48.65,1:14:54.81,Default,,0,0,0,,(F (LAMBDA (x) (F (x x)))\nDialogue: 0,1:14:57.07,1:14:58.17,Default,,0,0,0,,应用到\nDialogue: 0,1:14:59.18,1:15:06.48,Default,,0,0,0,,(LAMBDA (x) (F (x x))))\nDialogue: 0,1:15:06.99,1:15:10.44,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,1:15:11.51,1:15:12.40,Default,,0,0,0,,哇 这又是什么？\nDialogue: 0,1:15:13.42,1:15:16.35,Default,,0,0,0,,我刚才计算的这一部分\nDialogue: 0,1:15:17.13,1:15:18.56,Default,,0,0,0,,就是这里的这部分\nDialogue: 0,1:15:20.19,1:15:21.84,Default,,0,0,0,,只不过它被包在另一个F里面\nDialogue: 0,1:15:23.37,1:15:24.67,Default,,0,0,0,,因此 通过把Y应用在F上\nDialogue: 0,1:15:24.68,1:15:26.22,Default,,0,0,0,,我构造出了F的无穷嵌套\nDialogue: 0,1:15:27.85,1:15:29.45,Default,,0,0,0,,我如果让它一直这样进行下去\nDialogue: 0,1:15:29.69,1:15:31.77,Default,,0,0,0,,我在外层就会得到越来越多的F\nDialogue: 0,1:15:33.17,1:15:34.80,Default,,0,0,0,,我运行一个无用的循环\nDialogue: 0,1:15:35.20,1:15:37.02,Default,,0,0,0,,但内部是无用的并不重要\nDialogue: 0,1:15:39.85,1:15:47.85,Default,,0,0,0,,因此 我们有 (Y F)=(F (Y F))\nDialogue: 0,1:15:50.33,1:15:52.14,Default,,0,0,0,,Y组合子十分神奇\nDialogue: 0,1:15:53.85,1:15:56.25,Default,,0,0,0,,如果把它应用于某个函数\nDialogue: 0,1:15:57.37,1:16:00.38,Default,,0,0,0,,它就会返回这个函数的不动点\nDialogue: 0,1:16:01.69,1:16:04.25,Default,,0,0,0,,当然是在不动点存在的前提下\nDialogue: 0,1:16:07.91,1:16:10.08,Default,,0,0,0,,这是因为 如果我把(Y F)带入F\nDialogue: 0,1:16:10.12,1:16:11.12,Default,,0,0,0,,结果还是(Y F)\nDialogue: 0,1:16:16.24,1:16:18.86,Default,,0,0,0,,现在我想让你们在\nDialogue: 0,1:16:19.85,1:16:22.38,Default,,0,0,0,,EVAL-APPLY解释器方面思考一下\nDialogue: 0,1:16:23.86,1:16:26.27,Default,,0,0,0,,我在这里写了一大堆递归方程组\nDialogue: 0,1:16:28.54,1:16:30.22,Default,,0,0,0,,那些联立方程组像\nDialogue: 0,1:16:30.22,1:16:31.23,Default,,0,0,0,,这些方程一样联立起来\nDialogue: 0,1:16:31.47,1:16:33.31,Default,,0,0,0,,但EXPT不是联立方程\nDialogue: 0,1:16:33.31,1:16:35.79,Default,,0,0,0,,只是一个需要我赋义的变量\nDialogue: 0,1:16:38.15,1:16:40.76,Default,,0,0,0,,而Lisp则是某个过程的不动点\nDialogue: 0,1:16:40.81,1:16:42.57,Default,,0,0,0,,对这个过程来说 如果我知道Lisp的定义\nDialogue: 0,1:16:42.59,1:16:46.51,Default,,0,0,0,,然后在递归方程等号的右边\nDialogue: 0,1:16:46.59,1:16:49.79,Default,,0,0,0,,用它来代换EVAL、APPLY等变量\nDialogue: 0,1:16:50.94,1:16:53.96,Default,,0,0,0,,如果它是一个良好定义的Lisp的话\nDialogue: 0,1:16:54.36,1:16:56.30,Default,,0,0,0,,那么递归方程等号左边 也是一个良好定义的Lisp\nDialogue: 0,1:16:58.22,1:16:59.82,Default,,0,0,0,,这样 那个定义就讲得通了\nDialogue: 0,1:17:02.42,1:17:05.41,Default,,0,0,0,,不过是否有解却不太明显\nDialogue: 0,1:17:05.69,1:17:06.75,Default,,0,0,0,,我也说不清\nDialogue: 0,1:17:07.74,1:17:09.21,Default,,0,0,0,,现在我要介绍的论证\nDialogue: 0,1:17:09.26,1:17:10.27,Default,,0,0,0,,相当危险\nDialogue: 0,1:17:10.66,1:17:11.64,Default,,0,0,0,,具体看这里\nDialogue: 0,1:17:13.05,1:17:14.61,Default,,0,0,0,,这些是关于极限的论证\nDialogue: 0,1:17:14.61,1:17:15.39,Default,,0,0,0,,我们要讨论的极限\nDialogue: 0,1:17:15.45,1:17:17.68,Default,,0,0,0,,是微积分或者拓扑学的概念\nDialogue: 0,1:17:17.87,1:17:20.03,Default,,0,0,0,,或者说是类似的 数学分析中的概念\nDialogue: 0,1:17:20.76,1:17:23.38,Default,,0,0,0,,这个论证是你们都承认的\nDialogue: 0,1:17:23.38,1:17:25.29,Default,,0,0,0,,我想让你们意识到\nDialogue: 0,1:17:25.42,1:17:27.66,Default,,0,0,0,,我可以把你们耍得团团转\nDialogue: 0,1:17:28.86,1:17:30.48,Default,,0,0,0,,准备好了吗？ 这是什么？\nDialogue: 0,1:17:34.25,1:17:39.52,Default,,0,0,0,,u = 1 + 1/2 + 1/4 + .......\nDialogue: 0,1:17:39.74,1:17:41.32,Default,,0,0,0,,这是几何级数求和\nDialogue: 0,1:17:42.82,1:17:44.68,Default,,0,0,0,,当然 我也可以耍点小把戏\nDialogue: 0,1:17:44.82,1:17:47.57,Default,,0,0,0,,u - 1 = 1/2 + 1/4 + 1/8 ......\nDialogue: 0,1:17:51.90,1:17:54.46,Default,,0,0,0,,这里我可以\nDialogue: 0,1:17:56.09,1:17:57.93,Default,,0,0,0,,糟糕了 这里漏掉了括号\nDialogue: 0,1:17:58.92,1:18:01.45,Default,,0,0,0,,这里应该是\nDialogue: 0,1:18:01.74,1:18:03.99,Default,,0,0,0,,2(u - 1) = 1 + 1/2 + 1/4 + 1/8 ........\nDialogue: 0,1:18:07.57,1:18:08.54,Default,,0,0,0,,这里能修改一下吗？\nDialogue: 0,1:18:14.01,1:18:16.43,Default,,0,0,0,,哦 可以\nDialogue: 0,1:18:18.19,1:18:18.65,Default,,0,0,0,,看到了吗？\nDialogue: 0,1:18:19.52,1:18:20.64,Default,,0,0,0,,这样 我就得到\nDialogue: 0,1:18:23.53,1:18:26.64,Default,,0,0,0,,2(u - 1) = u\nDialogue: 0,1:18:27.80,1:18:29.58,Default,,0,0,0,,因此我们推断出 u=2\nDialogue: 0,1:18:30.30,1:18:31.37,Default,,0,0,0,,这是正确的\nDialogue: 0,1:18:31.96,1:18:33.32,Default,,0,0,0,,这个推理过程没有问题\nDialogue: 0,1:18:34.04,1:18:37.55,Default,,0,0,0,,但如果我要是做点别的什么呢？\nDialogue: 0,1:18:38.54,1:18:39.48,Default,,0,0,0,,假设我要求和的式子\nDialogue: 0,1:18:39.50,1:18:41.20,Default,,0,0,0,,明显没有和\nDialogue: 0,1:18:41.56,1:18:46.99,Default,,0,0,0,,v = 1 + 2 + 4 + ........\nDialogue: 0,1:18:47.39,1:18:51.39,Default,,0,0,0,,v - 1 = 2 + 4 + 8 + ......\nDialogue: 0,1:18:52.27,1:18:56.03,Default,,0,0,0,,(v - 1)/2 = v\nDialogue: 0,1:18:57.41,1:19:00.54,Default,,0,0,0,,这里我就可以推断出\nDialogue: 0,1:19:01.37,1:19:02.91,Default,,0,0,0,,显然这里又写错了\nDialogue: 0,1:19:03.07,1:19:04.51,Default,,0,0,0,,应该是 v = -1\nDialogue: 0,1:19:12.45,1:19:13.82,Default,,0,0,0,,这里应该是-1\nDialogue: 0,1:19:15.28,1:19:16.91,Default,,0,0,0,,这个结论明显是错误的\nDialogue: 0,1:19:22.00,1:19:23.47,Default,,0,0,0,,当你处理极限的时候\nDialogue: 0,1:19:24.22,1:19:27.85,Default,,0,0,0,,在某种方式下可行的论证\nDialogue: 0,1:19:29.42,1:19:30.75,Default,,0,0,0,,在其它情况下可能又不行了\nDialogue: 0,1:19:30.75,1:19:31.69,Default,,0,0,0,,要多加注意\nDialogue: 0,1:19:32.24,1:19:33.87,Default,,0,0,0,,参数必须具有良好的形式\nDialogue: 0,1:19:36.14,1:19:39.23,Default,,0,0,0,,但我不清楚 通常来说\nDialogue: 0,1:19:39.85,1:19:41.93,Default,,0,0,0,,像这样的论证有什么样的要求\nDialogue: 0,1:19:43.27,1:19:45.24,Default,,0,0,0,,我们要研习一大堆拓扑学文献来寻找答案\nDialogue: 0,1:19:46.27,1:19:48.64,Default,,0,0,0,,但是至少你们现在理解了\nDialogue: 0,1:19:49.10,1:19:51.13,Default,,0,0,0,,为什么我们在黑板上写的这些东西\nDialogue: 0,1:19:51.15,1:19:52.76,Default,,0,0,0,,是有一定语义的\nDialogue: 0,1:19:53.66,1:19:55.61,Default,,0,0,0,,你们也理解了它的语义\nDialogue: 0,1:19:56.48,1:19:58.35,Default,,0,0,0,,我想现在是时候\nDialogue: 0,1:19:59.07,1:20:03.84,Default,,0,0,0,,祝贺你们成为\nDialogue: 0,1:20:04.28,1:20:05.55,Default,,0,0,0,,神圣的递归秩序中的\nDialogue: 0,1:20:05.56,1:20:07.04,Default,,0,0,0,,一名LAMBDA演算黑客了\nDialogue: 0,1:20:08.84,1:20:10.17,Default,,0,0,0,,这是我们的徽章\nDialogue: 0,1:20:10.82,1:20:12.54,Default,,0,0,0,,因为你已经理解了\nDialogue: 0,1:20:13.40,1:20:15.20,Default,,0,0,0,,它上面的那句话\nDialogue: 0,1:20:16.89,1:20:18.41,Default,,0,0,0,,(Y F) = (F (Y F))\nDialogue: 0,1:20:21.04,1:20:21.66,Default,,0,0,0,,这节课讲完了\nDialogue: 0,1:20:21.85,1:20:22.75,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:20:24.71,1:20:25.15,Default,,0,0,0,,Lev 请说\nDialogue: 0,1:20:25.37,1:20:27.39,Default,,0,0,0,,学生：目前的状况来看\nDialogue: 0,1:20:27.40,1:20:30.22,Default,,0,0,0,,正如你指出的那样 我们不再需要DEFINE\nDialogue: 0,1:20:30.24,1:20:32.70,Default,,0,0,0,,不需要先存储一个值 以后再用\nDialogue: 0,1:20:32.99,1:20:33.32,Default,,0,0,0,,教授：对\nDialogue: 0,1:20:33.50,1:20:36.44,Default,,0,0,0,,学生：DEFINE在语言中好像有一些副作用\nDialogue: 0,1:20:36.49,1:20:38.52,Default,,0,0,0,,（听不清）并且依赖于时序\nDialogue: 0,1:20:39.30,1:20:42.06,Default,,0,0,0,,不用DEFINE 是否消除了副作用？\nDialogue: 0,1:20:42.28,1:20:44.68,Default,,0,0,0,,教授： 实际上\nDialogue: 0,1:20:44.88,1:20:46.44,Default,,0,0,0,,解释器并不是像这样实现的\nDialogue: 0,1:20:47.52,1:20:47.93,Default,,0,0,0,,明白了吧？\nDialogue: 0,1:20:48.92,1:20:53.15,Default,,0,0,0,,在实际的实现中 DEFINE这个运算\nDialogue: 0,1:20:53.18,1:20:55.53,Default,,0,0,0,,确实修改了环境\nDialogue: 0,1:20:57.95,1:21:02.33,Default,,0,0,0,,改变了执行DEFINE的那个框架\nDialogue: 0,1:21:03.69,1:21:06.51,Default,,0,0,0,,这样做是有很多原因的\nDialogue: 0,1:21:07.39,1:21:08.64,Default,,0,0,0,,其中之一就是\nDialogue: 0,1:21:08.67,1:21:10.09,Default,,0,0,0,,方便交互式系统\nDialogue: 0,1:21:11.34,1:21:14.12,Default,,0,0,0,,就是说 如果你构造了一个系统\nDialogue: 0,1:21:14.35,1:21:15.20,Default,,0,0,0,,而且你知道\nDialogue: 0,1:21:15.42,1:21:16.60,Default,,0,0,0,,你不打算进行调试\nDialogue: 0,1:21:16.60,1:21:17.55,Default,,0,0,0,,或之类的事儿\nDialogue: 0,1:21:17.84,1:21:20.72,Default,,0,0,0,,你想立马知道所有的东西\nDialogue: 0,1:21:20.75,1:21:21.24,Default,,0,0,0,,你想知道的是\nDialogue: 0,1:21:21.26,1:21:23.12,Default,,0,0,0,,方程组的最终解是什么？\nDialogue: 0,1:21:24.09,1:21:25.26,Default,,0,0,0,,然后系统返回你相应的值\nDialogue: 0,1:21:25.79,1:21:27.45,Default,,0,0,0,,但如果想要让系统变成交互式的\nDialogue: 0,1:21:27.45,1:21:28.75,Default,,0,0,0,,这样你可以在不影响其它部分的情况下\nDialogue: 0,1:21:28.76,1:21:31.68,Default,,0,0,0,,增量式地修改某一部分\nDialogue: 0,1:21:32.33,1:21:35.04,Default,,0,0,0,,没有DEFINE的话 就不能这么做了\nDialogue: 0,1:21:40.99,1:21:41.24,Default,,0,0,0,,你说\nDialogue: 0,1:21:42.30,1:21:44.25,Default,,0,0,0,,学生：就是那张“危险”的幻灯片\nDialogue: 0,1:21:44.65,1:21:47.13,Default,,0,0,0,,好像你举的两个例子\nDialogue: 0,1:21:47.16,1:21:49.07,Default,,0,0,0,,与其收敛与否有关系？\nDialogue: 0,1:21:49.18,1:21:49.56,Default,,0,0,0,,教授：是的\nDialogue: 0,1:21:50.30,1:21:52.62,Default,,0,0,0,,学生：函数理论中是否有\nDialogue: 0,1:21:52.76,1:21:54.68,Default,,0,0,0,,像线性系统\nDialogue: 0,1:21:54.72,1:21:56.60,Default,,0,0,0,,或者非线性系统中的\nDialogue: 0,1:21:57.74,1:21:59.00,Default,,0,0,0,,那种思考方式\nDialogue: 0,1:21:59.34,1:22:01.76,Default,,0,0,0,,函数的收敛性能否先验地知道\nDialogue: 0,1:22:02.35,1:22:05.53,Default,,0,0,0,,哪些属性可能被违反？\nDialogue: 0,1:22:05.79,1:22:06.57,Default,,0,0,0,,教授：我不知道\nDialogue: 0,1:22:07.68,1:22:10.09,Default,,0,0,0,,我也不知道它需要什么条件\nDialogue: 0,1:22:10.61,1:22:12.04,Default,,0,0,0,,我不知道怎么在一节课内\nDialogue: 0,1:22:12.52,1:22:14.73,Default,,0,0,0,,就给你们讲清楚\nDialogue: 0,1:22:16.91,1:22:18.48,Default,,0,0,0,,有什么条件来判别它们\nDialogue: 0,1:22:18.86,1:22:20.76,Default,,0,0,0,,是否收敛？\nDialogue: 0,1:22:22.86,1:22:23.31,Default,,0,0,0,,确实\nDialogue: 0,1:22:23.32,1:22:26.35,Default,,0,0,0,,这些都是为了告诉你 基于收敛的论证\nDialogue: 0,1:22:28.24,1:22:29.47,Default,,0,0,0,,都不可靠\nDialogue: 0,1:22:29.66,1:22:31.58,Default,,0,0,0,,如果你事先不知道收敛性的话\nDialogue: 0,1:22:32.81,1:22:34.20,Default,,0,0,0,,你可能做出错误的论证\nDialogue: 0,1:22:34.44,1:22:37.31,Default,,0,0,0,,你可以先假设知道了答案 然后进行演绎\nDialogue: 0,1:22:37.39,1:22:39.93,Default,,0,0,0,,看它会不会产生什么明显的矛盾\nDialogue: 0,1:22:40.97,1:22:42.28,Default,,0,0,0,,学生：我们是否可以说\nDialogue: 0,1:22:42.33,1:22:44.88,Default,,0,0,0,,如果数学表达式F收敛\nDialogue: 0,1:22:45.00,1:22:47.36,Default,,0,0,0,,那么它的递归性质就--\nDialogue: 0,1:22:47.58,1:22:51.29,Default,,0,0,0,,教授：我认为 在技术上有一类F\nDialogue: 0,1:22:52.12,1:22:54.22,Default,,0,0,0,,通过一些技术准则\nDialogue: 0,1:22:54.24,1:22:55.90,Default,,0,0,0,,我们可以找到这样的F\nDialogue: 0,1:22:55.98,1:23:01.31,Default,,0,0,0,,当你像这样迭代地应用它们时\nDialogue: 0,1:23:01.52,1:23:02.25,Default,,0,0,0,,它一定会收敛\nDialogue: 0,1:23:03.02,1:23:06.51,Default,,0,0,0,,这类准则包括：单调、连续\nDialogue: 0,1:23:07.32,1:23:07.95,Default,,0,0,0,,我想想\nDialogue: 0,1:23:08.38,1:23:09.37,Default,,0,0,0,,我把其它的准则忘了\nDialogue: 0,1:23:09.37,1:23:11.13,Default,,0,0,0,,还有一些列像这样的\nDialogue: 0,1:23:11.68,1:23:12.99,Default,,0,0,0,,判别准则\nDialogue: 0,1:23:13.43,1:23:16.00,Default,,0,0,0,,现在的难点是 给定F然后进行推理\nDialogue: 0,1:23:16.92,1:23:17.88,Default,,0,0,0,,这是F的定义\nDialogue: 0,1:23:18.17,1:23:19.66,Default,,0,0,0,,它满足这些准则吗？\nDialogue: 0,1:23:20.27,1:23:21.32,Default,,0,0,0,,这很难判断\nDialogue: 0,1:23:22.01,1:23:24.00,Default,,0,0,0,,那些准则都很简单得可以写下来\nDialogue: 0,1:23:24.58,1:23:26.32,Default,,0,0,0,,你可以看Joe Stoy写的一本书\nDialogue: 0,1:23:26.67,1:23:29.58,Default,,0,0,0,,那本书非常不错\nDialogue: 0,1:23:32.22,1:23:34.06,Default,,0,0,0,,叫做The Scott-Strachey\nDialogue: 0,1:23:34.49,1:23:38.46,Default,,0,0,0,,《指称语义：基于Scott-Strachey方法》\nDialogue: 0,1:23:39.55,1:23:40.76,Default,,0,0,0,,作者是Joe Stoy\nDialogue: 0,1:23:40.80,1:23:41.76,Default,,0,0,0,,由MIT出版社出版\nDialogue: 0,1:23:48.06,1:23:49.88,Default,,0,0,0,,他把这一方面讲得非常详细\nDialogue: 0,1:23:50.20,1:23:51.37,Default,,0,0,0,,绝对会让你吓一大跳\nDialogue: 0,1:23:55.05,1:23:56.19,Default,,0,0,0,,但是这本书仍然值得一读\nDialogue: 0,1:24:09.15,1:24:10.08,Default,,0,0,0,,好吧 谢谢大家\nDialogue: 0,1:24:11.49,1:24:12.99,Default,,0,0,0,,这节课到此为止\nDialogue: 0,1:24:14.17,1:24:34.60,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:24:14.17,1:24:34.49,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec7a.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nVideo Position: 343\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:11.42,0:00:13.24,EN,,0,0,0,,Metacircular Evaluator - I\nDialogue: 0,0:00:15.79,0:00:17.32,EN,,0,0,0,,PROFESSOR: Well today we're going to learn about something\nDialogue: 0,0:00:17.52,0:00:18.41,EN,,0,0,0,,quite amazing.\nDialogue: 0,0:00:19.20,0:00:21.88,EN,,0,0,0,,We're going to understand what we mean by a program\nDialogue: 0,0:00:22.59,0:00:25.21,EN,,0,0,0,,a little bit more profoundly than we have up till now.\nDialogue: 0,0:00:26.80,0:00:29.12,EN,,0,0,0,,Up till now, we've been thinking\nDialogue: 0,0:00:29.26,0:00:32.09,EN,,0,0,0,,programs as describing machines.\nDialogue: 0,0:00:32.72,0:00:37.21,EN,,0,0,0,,So for example, looking at this still store\nDialogue: 0,0:00:37.93,0:00:41.77,EN,,0,0,0,,we see here is a program for factorial.\nDialogue: 0,0:00:42.80,0:00:47.31,EN,,0,0,0,,And what it is, is a character string description, if you will,\nDialogue: 0,0:00:47.66,0:00:51.98,EN,,0,0,0,,of the wiring diagram of a potentially infinite machine.\nDialogue: 0,0:00:52.49,0:00:54.80,EN,,0,0,0,,And we can look at that a little bit and just see the idea.\nDialogue: 0,0:00:55.13,0:00:58.20,EN,,0,0,0,,That this is a sort of compact notation which says,\nDialogue: 0,0:00:58.54,0:01:00.17,EN,,0,0,0,,if n is 0, the result is one.\nDialogue: 0,0:01:00.17,0:01:02.00,EN,,0,0,0,,Well here comes n coming into this machine,\nDialogue: 0,0:01:02.33,0:01:03.52,EN,,0,0,0,,and if it's 0,\nDialogue: 0,0:01:03.74,0:01:05.20,EN,,0,0,0,,then I control this switch\nDialogue: 0,0:01:05.47,0:01:08.20,EN,,0,0,0,,in such a way that the switch allows the output to be one.\nDialogue: 0,0:01:09.34,0:01:10.08,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:01:10.38,0:01:12.83,EN,,0,0,0,,it's n times factorial of n minus one.\nDialogue: 0,0:01:12.97,0:01:15.13,EN,,0,0,0,,Well, I'm computing factorial of n minus one\nDialogue: 0,0:01:15.29,0:01:16.68,EN,,0,0,0,,and multiplying that by n,\nDialogue: 0,0:01:16.84,0:01:18.91,EN,,0,0,0,,in the case that it's not 0,\nDialogue: 0,0:01:18.91,0:01:20.60,EN,,0,0,0,,this switch makes the output come from there.\nDialogue: 0,0:01:21.90,0:01:22.32,EN,,0,0,0,,Of course,\nDialogue: 0,0:01:22.36,0:01:25.13,EN,,0,0,0,,this is a machine with a potentially infinite number of parts,\nDialogue: 0,0:01:25.48,0:01:28.12,EN,,0,0,0,,because factorial occurs within factorial,\nDialogue: 0,0:01:28.43,0:01:30.17,EN,,0,0,0,,so we don't know how deep it has to be.\nDialogue: 0,0:01:31.07,0:01:33.55,EN,,0,0,0,,But that's basically what our notation\nDialogue: 0,0:01:34.22,0:01:37.69,EN,,0,0,0,,for programs really means to us at this point.\nDialogue: 0,0:01:38.31,0:01:40.59,EN,,0,0,0,,It's a character string description, if you will,\nDialogue: 0,0:01:41.28,0:01:44.16,EN,,0,0,0,,of a wiring diagram that could also be drawn some other way.\nDialogue: 0,0:01:44.90,0:01:46.60,EN,,0,0,0,,And, in fact, many people have proposed to me,\nDialogue: 0,0:01:46.84,0:01:49.04,EN,,0,0,0,,programming languages look graphical like this.\nDialogue: 0,0:01:49.49,0:01:51.80,EN,,0,0,0,,I'm not sure I believe there are many advantages.\nDialogue: 0,0:01:52.00,0:01:53.79,EN,,0,0,0,,The major disadvantage, of course,\nDialogue: 0,0:01:53.80,0:01:55.63,EN,,0,0,0,,is that it takes up more space on a page,\nDialogue: 0,0:01:55.96,0:01:59.95,EN,,0,0,0,,and, therefore, it's harder to pack into a listing or to edit very well.\nDialogue: 0,0:02:01.34,0:02:02.16,EN,,0,0,0,,But in any case,\nDialogue: 0,0:02:03.58,0:02:05.15,EN,,0,0,0,,there's something very remarkable\nDialogue: 0,0:02:05.18,0:02:07.05,EN,,0,0,0,,that can happen in the computation world\nDialogue: 0,0:02:07.64,0:02:10.64,EN,,0,0,0,,which is that you can have something called a universal machine.\nDialogue: 0,0:02:10.73,0:02:15.24,EN,,0,0,0,,If we look at the second slide,\nDialogue: 0,0:02:16.04,0:02:17.18,EN,,0,0,0,,what we see is\nDialogue: 0,0:02:18.14,0:02:19.88,EN,,0,0,0,,a special machine called eval.\nDialogue: 0,0:02:21.26,0:02:22.86,EN,,0,0,0,,There is a machine called eval,\nDialogue: 0,0:02:22.88,0:02:24.24,EN,,0,0,0,,and I'm going to show it to you today.\nDialogue: 0,0:02:25.82,0:02:26.67,EN,,0,0,0,,It's very simple.\nDialogue: 0,0:02:27.78,0:02:30.80,EN,,0,0,0,,What is remarkable is that it will fit on the blackboard.\nDialogue: 0,0:02:33.35,0:02:35.79,EN,,0,0,0,,However, eval is a machine\nDialogue: 0,0:02:36.00,0:02:39.84,EN,,0,0,0,,which takes as input a description of another machine.\nDialogue: 0,0:02:40.45,0:02:42.12,EN,,0,0,0,,It could take the wiring diagram\nDialogue: 0,0:02:42.40,0:02:45.58,EN,,0,0,0,,of a factorial machine as input.\nDialogue: 0,0:02:46.49,0:02:47.66,EN,,0,0,0,,Having done so,\nDialogue: 0,0:02:48.49,0:02:52.57,EN,,0,0,0,,it becomes a simulator for the factorial machine\nDialogue: 0,0:02:53.13,0:02:53.79,EN,,0,0,0,,such that,\nDialogue: 0,0:02:54.16,0:02:56.36,EN,,0,0,0,,if you put a six in, out comes a 720.\nDialogue: 0,0:02:58.91,0:03:01.68,EN,,0,0,0,,That's a very remarkable sort of machine.\nDialogue: 0,0:03:02.13,0:03:03.58,EN,,0,0,0,,And the most amazing part of it\nDialogue: 0,0:03:03.77,0:03:05.13,EN,,0,0,0,,it is that it fits on a blackboard.\nDialogue: 0,0:03:05.59,0:03:06.65,EN,,0,0,0,,By contrast,\nDialogue: 0,0:03:07.32,0:03:10.44,EN,,0,0,0,,one could imagine in the analog electronics world\nDialogue: 0,0:03:11.55,0:03:12.86,EN,,0,0,0,,a very different machine.\nDialogue: 0,0:03:14.57,0:03:16.33,EN,,0,0,0,,a machine where, a machine\nDialogue: 0,0:03:16.52,0:03:18.81,EN,,0,0,0,,which also was, in some sense, universal,\nDialogue: 0,0:03:19.26,0:03:23.12,EN,,0,0,0,,where you gave a circuit diagram as one of the inputs,\nDialogue: 0,0:03:23.82,0:03:25.74,EN,,0,0,0,,for example, of this little low-pass filter,\nDialogue: 0,0:03:26.01,0:03:27.48,EN,,0,0,0,,one-pole low-pass filter.\nDialogue: 0,0:03:28.05,0:03:29.53,EN,,0,0,0,,And you can imagine that\nDialogue: 0,0:03:29.71,0:03:33.15,EN,,0,0,0,,you could, for example, scan this out-- the scan lines\nDialogue: 0,0:03:34.43,0:03:37.13,EN,,0,0,0,,Right? are the signal that's describing\nDialogue: 0,0:03:37.39,0:03:40.40,EN,,0,0,0,,what this machine is to simulate--\nDialogue: 0,0:03:40.78,0:03:43.39,EN,,0,0,0,,then the analog of eval which is made out of electrical circuits,\nDialogue: 0,0:03:43.68,0:03:45.15,EN,,0,0,0,,which configure itself into a filter\nDialogue: 0,0:03:45.18,0:03:48.04,EN,,0,0,0,,has the frequency response specified by the circuit diagram.\nDialogue: 0,0:03:49.89,0:03:51.48,EN,,0,0,0,,That's a very hard machine to make,\nDialogue: 0,0:03:51.61,0:03:54.06,EN,,0,0,0,,and, surely, there's no chance that I could put it on a blackboard.\nDialogue: 0,0:03:55.67,0:03:57.58,EN,,0,0,0,,So we're going to see an amazing thing today.\nDialogue: 0,0:03:58.43,0:04:00.81,EN,,0,0,0,,We're going to see, on the blackboard,\nDialogue: 0,0:04:01.16,0:04:02.49,EN,,0,0,0,,the universal machine.\nDialogue: 0,0:04:02.79,0:04:04.41,EN,,0,0,0,,And we'll see that among other things,\nDialogue: 0,0:04:04.52,0:04:05.80,EN,,0,0,0,,it's extremely simple.\nDialogue: 0,0:04:06.78,0:04:08.75,EN,,0,0,0,,Now, we're getting very close\nDialogue: 0,0:04:09.08,0:04:10.97,EN,,0,0,0,,the real spirit in the computer at this point.\nDialogue: 0,0:04:11.28,0:04:14.62,EN,,0,0,0,,So I have to show a certain amount of reverence and respect,\nDialogue: 0,0:04:15.18,0:04:17.32,EN,,0,0,0,,so I'm going to wear a suit jacket for the only time\nDialogue: 0,0:04:17.52,0:04:19.29,EN,,0,0,0,,that you'll ever see me wear a suit jacket here.\nDialogue: 0,0:04:20.47,0:04:22.73,EN,,0,0,0,,And I think I'm also going to\nDialogue: 0,0:04:23.55,0:04:26.70,EN,,0,0,0,,put on an appropriate hat for the occasion.\nDialogue: 0,0:04:28.78,0:04:31.44,EN,,0,0,0,,Now, this is a lecturer which I have to warn you--\nDialogue: 0,0:04:34.14,0:04:36.91,EN,,0,0,0,,let's see, normally, people under 40\nDialogue: 0,0:04:37.16,0:04:38.49,EN,,0,0,0,,and who don't have several children\nDialogue: 0,0:04:38.67,0:04:40.49,EN,,0,0,0,,are advised to be careful.\nDialogue: 0,0:04:40.49,0:04:41.96,EN,,0,0,0,,If they're really worried, they should leave.\nDialogue: 0,0:04:43.34,0:04:45.56,EN,,0,0,0,,Because there's a certain amount of\nDialogue: 0,0:04:45.72,0:04:47.13,EN,,0,0,0,,mysticism that will appear here\nDialogue: 0,0:04:47.74,0:04:51.05,EN,,0,0,0,,which may be disturbing and cause trouble in your minds.\nDialogue: 0,0:04:51.82,0:04:54.28,EN,,0,0,0,,Well in any case, let's see,\nDialogue: 0,0:04:55.71,0:05:01.10,EN,,0,0,0,,I wish to write for you the evaluator for Lisp.\nDialogue: 0,0:05:02.51,0:05:04.28,EN,,0,0,0,,Now the evaluator isn't very complicated.\nDialogue: 0,0:05:05.02,0:05:07.63,EN,,0,0,0,,It's very much like all the programs we've seen already.\nDialogue: 0,0:05:08.24,0:05:09.48,EN,,0,0,0,,That's the amazing part of it.\nDialogue: 0,0:05:10.86,0:05:13.10,EN,,0,0,0,,It's going to be-- and I'm going to write it right here--\nDialogue: 0,0:05:15.28,0:05:16.62,EN,,0,0,0,,it's a program called eval.\nDialogue: 0,0:05:22.90,0:05:26.24,EN,,0,0,0,,And it's a procedure of two arguments\nDialogue: 0,0:05:26.28,0:05:29.44,EN,,0,0,0,,expression and an environment.\nDialogue: 0,0:05:31.86,0:05:33.79,EN,,0,0,0,,And like every interesting procedure,\nDialogue: 0,0:05:34.01,0:05:35.13,EN,,0,0,0,,it's a case analysis.\nDialogue: 0,0:05:40.46,0:05:41.87,EN,,0,0,0,,But before I start on this,\nDialogue: 0,0:05:42.52,0:05:43.90,EN,,0,0,0,,I want to tell you some things.\nDialogue: 0,0:05:44.44,0:05:46.06,EN,,0,0,0,,The program we're going to write on the blackboard\nDialogue: 0,0:05:46.56,0:05:50.24,EN,,0,0,0,,is ugly, dirty, disgusting,\nDialogue: 0,0:05:50.94,0:05:53.16,EN,,0,0,0,,not the way I would write this is a professional.\nDialogue: 0,0:05:54.32,0:05:56.57,EN,,0,0,0,,It is written with concrete syntax,\nDialogue: 0,0:05:57.24,0:05:58.83,EN,,0,0,0,,meaning you've got really to use lots of CARs and CDRs\nDialogue: 0,0:05:58.84,0:06:00.62,EN,,0,0,0,,which is exactly what I told you not to do.\nDialogue: 0,0:06:02.94,0:06:05.61,EN,,0,0,0,,That's on purpose in this case,\nDialogue: 0,0:06:06.11,0:06:09.02,EN,,0,0,0,,because I want it to be small, compact,\nDialogue: 0,0:06:09.34,0:06:10.40,EN,,0,0,0,,fit on the blackboard\nDialogue: 0,0:06:10.43,0:06:11.85,EN,,0,0,0,,so you can get the whole thing.\nDialogue: 0,0:06:12.42,0:06:14.80,EN,,0,0,0,,So I don't want to use long names like I normally use.\nDialogue: 0,0:06:15.60,0:06:17.29,EN,,0,0,0,,I want to use CAR-CDR because it's short.\nDialogue: 0,0:06:18.06,0:06:20.78,EN,,0,0,0,,Okay, I wanna, it's a whole, that's a trade-off.\nDialogue: 0,0:06:20.89,0:06:22.81,EN,,0,0,0,,I don't want you writing programs like this.\nDialogue: 0,0:06:23.57,0:06:25.08,EN,,0,0,0,,This is purely for an effect.\nDialogue: 0,0:06:25.85,0:06:27.61,EN,,0,0,0,,Now, you're going to have to work a little harder to read it,\nDialogue: 0,0:06:27.77,0:06:30.19,EN,,0,0,0,,but I'm going to try to make it clear as I'm writing it.\nDialogue: 0,0:06:31.27,0:06:34.40,EN,,0,0,0,,I'm also-- this is a pretty much complete interpreter,\nDialogue: 0,0:06:34.51,0:06:36.24,EN,,0,0,0,,but there's going to be room for putting in more things--\nDialogue: 0,0:06:36.25,0:06:38.60,EN,,0,0,0,,I'm going to leave out definition and assignment,\nDialogue: 0,0:06:39.10,0:06:42.41,EN,,0,0,0,,just because they are not essential,\nDialogue: 0,0:06:42.88,0:06:46.46,EN,,0,0,0,,and a, for a mathematical reason I'll show you later\nDialogue: 0,0:06:46.92,0:06:49.96,EN,,0,0,0,,and also they take up more space.\nDialogue: 0,0:06:51.88,0:06:53.64,EN,,0,0,0,,But, in any case, what do we have to do?\nDialogue: 0,0:06:53.95,0:06:55.66,EN,,0,0,0,,We have to do a dispatch\nDialogue: 0,0:06:56.09,0:06:57.90,EN,,0,0,0,,which breaks the types of expressions up\nDialogue: 0,0:06:58.28,0:07:00.38,EN,,0,0,0,,into particular classes.\nDialogue: 0,0:07:01.72,0:07:03.26,EN,,0,0,0,,Okay? So that's what we're going to have here.\nDialogue: 0,0:07:03.82,0:07:05.15,EN,,0,0,0,,Well, what expressions are there?\nDialogue: 0,0:07:05.15,0:07:06.36,EN,,0,0,0,,Let's look at the kinds of expressions.\nDialogue: 0,0:07:06.81,0:07:09.60,EN,,0,0,0,,We can have things like the numeral three.\nDialogue: 0,0:07:10.42,0:07:11.58,EN,,0,0,0,,What do I want that to do?\nDialogue: 0,0:07:12.72,0:07:14.75,EN,,0,0,0,,I can make choices, but I think right now,\nDialogue: 0,0:07:15.05,0:07:16.20,EN,,0,0,0,,I want it to be a three.\nDialogue: 0,0:07:17.05,0:07:17.88,EN,,0,0,0,,That's what I want.\nDialogue: 0,0:07:18.72,0:07:19.69,EN,,0,0,0,,So that's easy enough.\nDialogue: 0,0:07:20.03,0:07:22.91,EN,,0,0,0,,That means I want, if the thing is a number,\nDialogue: 0,0:07:27.29,0:07:31.68,EN,,0,0,0,,that I want the expression itself as the answer.\nDialogue: 0,0:07:35.42,0:07:36.76,EN,,0,0,0,,Now the next possibility\nDialogue: 0,0:07:36.89,0:07:38.86,EN,,0,0,0,,is things that we represent as symbols.\nDialogue: 0,0:07:39.39,0:07:46.75,EN,,0,0,0,,Examples of symbols are things like x, n, eval, number, x.\nDialogue: 0,0:07:48.01,0:07:49.18,EN,,0,0,0,,What do I mean them to be?\nDialogue: 0,0:07:50.16,0:07:51.63,EN,,0,0,0,,Those are things that stand for other things.\nDialogue: 0,0:07:51.63,0:07:53.23,EN,,0,0,0,,Those are the variables of our language.\nDialogue: 0,0:07:54.77,0:07:56.88,EN,,0,0,0,,And so I want to be able to say, for example,\nDialogue: 0,0:07:57.05,0:08:01.04,EN,,0,0,0,,that x, for example, transforms to it's value which might be three.\nDialogue: 0,0:08:02.64,0:08:05.76,EN,,0,0,0,,Or I might ask something like car.\nDialogue: 0,0:08:07.76,0:08:09.40,EN,,0,0,0,,I want to have as its value--\nDialogue: 0,0:08:09.63,0:08:11.34,EN,,0,0,0,,be something like some procedure,\nDialogue: 0,0:08:16.51,0:08:18.43,EN,,0,0,0,,which I don't know what is inside there,\nDialogue: 0,0:08:18.64,0:08:21.15,EN,,0,0,0,,perhaps a machine language code or something like that.\nDialogue: 0,0:08:22.84,0:08:24.27,EN,,0,0,0,,Ok? So, well, that's easy enough.\nDialogue: 0,0:08:24.43,0:08:26.89,EN,,0,0,0,,I'm going to push that off on someone else.\nDialogue: 0,0:08:27.80,0:08:28.89,EN,,0,0,0,,If something is a symbol,\nDialogue: 0,0:08:30.80,0:08:32.48,EN,,0,0,0,,if the expression is a symbol,\nDialogue: 0,0:08:33.42,0:08:34.88,EN,,0,0,0,,then I want the answer to be the result,\nDialogue: 0,0:08:34.91,0:08:40.24,EN,,0,0,0,,looking up the expression in the environment.\nDialogue: 0,0:08:46.48,0:08:48.99,EN,,0,0,0,,Now the environment is a dictionary\nDialogue: 0,0:08:49.96,0:08:54.06,EN,,0,0,0,,which maps the symbol names to their values.\nDialogue: 0,0:08:54.28,0:08:55.16,EN,,0,0,0,,And that's all it is.\nDialogue: 0,0:08:56.28,0:08:57.20,EN,,0,0,0,,How it's done?\nDialogue: 0,0:08:57.53,0:08:58.52,EN,,0,0,0,,Well, we'll see that later.\nDialogue: 0,0:08:59.68,0:09:00.57,EN,,0,0,0,,It's very easy.\nDialogue: 0,0:09:01.67,0:09:04.28,EN,,0,0,0,,It's easy to make data structures that are tables of various sorts.\nDialogue: 0,0:09:04.84,0:09:05.74,EN,,0,0,0,,But it's only a table,\nDialogue: 0,0:09:05.77,0:09:07.56,EN,,0,0,0,,and this is the access routine for some table.\nDialogue: 0,0:09:09.55,0:09:10.81,EN,,0,0,0,,Ok? Well, the next thing,\nDialogue: 0,0:09:11.31,0:09:12.56,EN,,0,0,0,,another kind of expression--\nDialogue: 0,0:09:12.67,0:09:15.56,EN,,0,0,0,,you have things that are described constants that are not numbers,\nDialogue: 0,0:09:16.06,0:09:17.43,EN,,0,0,0,,like 'foo.\nDialogue: 0,0:09:20.17,0:09:21.29,EN,,0,0,0,,Well, for my convenience,\nDialogue: 0,0:09:21.31,0:09:23.36,EN,,0,0,0,,I want to syntactically transform that\nDialogue: 0,0:09:24.73,0:09:26.80,EN,,0,0,0,,into a list structure which is,\nDialogue: 0,0:09:26.84,0:09:31.52,EN,,0,0,0,,which is, quote foo.\nDialogue: 0,0:09:33.72,0:09:37.18,EN,,0,0,0,,Or it's -- A quoted object, whatever it is,\nDialogue: 0,0:09:38.35,0:09:40.83,EN,,0,0,0,,is going to be actually an abbreviation,\nDialogue: 0,0:09:41.04,0:09:42.59,EN,,0,0,0,,which is not part of the evaluator\nDialogue: 0,0:09:43.21,0:09:44.46,EN,,0,0,0,,but happens somewhere else,\nDialogue: 0,0:09:44.75,0:09:47.79,EN,,0,0,0,,an abbreviation for an expression that looks like this.\nDialogue: 0,0:09:48.78,0:09:50.48,EN,,0,0,0,,This way, I can test for\nDialogue: 0,0:09:50.57,0:09:53.12,EN,,0,0,0,,the type of the expression as being a quotation\nDialogue: 0,0:09:53.31,0:09:55.95,EN,,0,0,0,,by examining the car of the expression.\nDialogue: 0,0:09:58.46,0:10:01.08,EN,,0,0,0,,So I'm not going to worry about that in the evaluator.\nDialogue: 0,0:10:01.65,0:10:02.68,EN,,0,0,0,,It's happening somewhere earlier\nDialogue: 0,0:10:02.70,0:10:03.96,EN,,0,0,0,,in the reader or something.\nDialogue: 0,0:10:05.54,0:10:15.04,EN,,0,0,0,,If the expression of the expression is quote,\nDialogue: 0,0:10:18.27,0:10:19.10,EN,,0,0,0,,then what I want,\nDialogue: 0,0:10:19.63,0:10:25.13,EN,,0,0,0,,I want quote foo to itself evaluate to foo.\nDialogue: 0,0:10:25.14,0:10:25.95,EN,,0,0,0,,It's a constant.\nDialogue: 0,0:10:27.53,0:10:28.92,EN,,0,0,0,,This is just a way of saying\nDialogue: 0,0:10:29.08,0:10:30.73,EN,,0,0,0,,that this evaluates to itself.\nDialogue: 0,0:10:31.79,0:10:33.66,EN,,0,0,0,,Ok? So thats the. What is that?\nDialogue: 0,0:10:33.66,0:10:36.36,EN,,0,0,0,,That's the first of the second of the list.\nDialogue: 0,0:10:36.59,0:10:37.58,EN,,0,0,0,,That's the second of the list.\nDialogue: 0,0:10:38.49,0:10:40.32,EN,,0,0,0,,The second element of the list is it's CADR.\nDialogue: 0,0:10:41.28,0:10:42.38,EN,,0,0,0,,So I'm just going to write here, CADR.\nDialogue: 0,0:10:51.08,0:10:52.35,EN,,0,0,0,,OK? What else do we have here?\nDialogue: 0,0:10:52.51,0:10:53.80,EN,,0,0,0,,We have lambda expressions,\nDialogue: 0,0:10:55.00,0:11:03.29,EN,,0,0,0,,for example, lambda of x plus x y.\nDialogue: 0,0:11:04.16,0:11:06.33,EN,,0,0,0,,Well, I going have to have some representation for the procedure\nDialogue: 0,0:11:06.33,0:11:07.85,EN,,0,0,0,,which is the value of an expression,\nDialogue: 0,0:11:08.11,0:11:09.08,EN,,0,0,0,,of a lambda expression.\nDialogue: 0,0:11:09.60,0:11:12.62,EN,,0,0,0,,The procedure here is not the expression lambda x.\nDialogue: 0,0:11:13.13,0:11:15.56,EN,,0,0,0,,That's the description of it, the textual description.\nDialogue: 0,0:11:16.41,0:11:18.33,EN,,0,0,0,,However, what what I going to expect to see here\nDialogue: 0,0:11:18.56,0:11:21.20,EN,,0,0,0,,is something which contains an environment as one of its parts\nDialogue: 0,0:11:23.23,0:11:25.36,EN,,0,0,0,,if I'm implementing a lexical language.\nDialogue: 0,0:11:25.84,0:11:29.07,EN,,0,0,0,,And so what I'd like to see\nDialogue: 0,0:11:29.20,0:11:30.67,EN,,0,0,0,,is some type flags.\nDialogue: 0,0:11:30.70,0:11:33.90,EN,,0,0,0,,I'm going to have to be able to distinguish procedures later,\nDialogue: 0,0:11:34.30,0:11:36.59,EN,,0,0,0,,procedures which were produced by lambdas,\nDialogue: 0,0:11:36.81,0:11:38.03,EN,,0,0,0,,from ones that may be primitive.\nDialogue: 0,0:11:39.06,0:11:41.96,EN,,0,0,0,,And so I'm going to have some flag,\nDialogue: 0,0:11:41.98,0:11:43.56,EN,,0,0,0,,which I'll just arbitrarily call closure,\nDialogue: 0,0:11:43.56,0:11:45.10,EN,,0,0,0,,just for historical reasons.\nDialogue: 0,0:11:47.68,0:11:49.60,EN,,0,0,0,,Now, to say what parts of this are important.\nDialogue: 0,0:11:49.92,0:11:51.12,EN,,0,0,0,,I'm going to need to know\nDialogue: 0,0:11:51.24,0:11:52.92,EN,,0,0,0,,the bound variable list and the body.\nDialogue: 0,0:11:54.22,0:11:55.40,EN,,0,0,0,,Well, that's the CDR of this,\nDialogue: 0,0:11:56.09,0:12:01.85,EN,,0,0,0,,so it's going to be x and plus x y and some environment.\nDialogue: 0,0:12:03.04,0:12:03.87,EN,,0,0,0,,and some environment.\nDialogue: 0,0:12:08.17,0:12:12.20,EN,,0,0,0,,Now this is not something that users should ever see,\nDialogue: 0,0:12:13.53,0:12:16.19,EN,,0,0,0,,this is purely a representation, internally,\nDialogue: 0,0:12:16.76,0:12:18.30,EN,,0,0,0,,for a procedure object.\nDialogue: 0,0:12:18.52,0:12:20.52,EN,,0,0,0,,It contains a bound variable list,\nDialogue: 0,0:12:20.70,0:12:22.62,EN,,0,0,0,,a body, and an environment,\nDialogue: 0,0:12:23.53,0:12:25.80,EN,,0,0,0,,and some type tag saying, I am a procedure.\nDialogue: 0,0:12:26.34,0:12:27.37,EN,,0,0,0,,I'm going to make one now.\nDialogue: 0,0:12:28.08,0:12:38.72,EN,,0,0,0,,So if the CAR of the expression is quote lambda,\nDialogue: 0,0:12:43.47,0:12:44.81,EN,,0,0,0,,then what I'm going to put here\nDialogue: 0,0:12:45.64,0:12:51.84,EN,,0,0,0,,is-- I'm going to make a list of closure,\nDialogue: 0,0:12:55.15,0:13:00.73,EN,,0,0,0,,the CDR of the procedure description\nDialogue: 0,0:13:01.56,0:13:02.97,EN,,0,0,0,,was everything except the lambda,\nDialogue: 0,0:13:07.74,0:13:08.86,EN,,0,0,0,,and the current environment.\nDialogue: 0,0:13:10.25,0:13:15.32,EN,,0,0,0,,This implements the rule for environments in the environment model.\nDialogue: 0,0:13:15.45,0:13:18.52,EN,,0,0,0,,It has to do with construction of procedures from lambda expressions.\nDialogue: 0,0:13:19.40,0:13:20.97,EN,,0,0,0,,The environment that was around\nDialogue: 0,0:13:21.48,0:13:24.32,EN,,0,0,0,,at the time the evaluator encountered the lambda expression\nDialogue: 0,0:13:25.04,0:13:28.46,EN,,0,0,0,,is the environment where the lambda expression gets\nDialogue: 0,0:13:28.68,0:13:31.77,EN,,0,0,0,,where the procedure resulting interprets it's free variables.\nDialogue: 0,0:13:34.72,0:13:35.82,EN,,0,0,0,,So that's part of that.\nDialogue: 0,0:13:35.92,0:13:37.55,EN,,0,0,0,,And so we have to capture that environment\nDialogue: 0,0:13:37.56,0:13:38.86,EN,,0,0,0,,as part of the procedure object.\nDialogue: 0,0:13:39.21,0:13:40.62,EN,,0,0,0,,And we'll see how that gets used later.\nDialogue: 0,0:13:42.03,0:13:43.77,EN,,0,0,0,,There are also conditional expressions\nDialogue: 0,0:13:44.59,0:13:52.81,EN,,0,0,0,,of things like COND of say, p one, e one, p two, e two.\nDialogue: 0,0:13:54.40,0:13:56.09,EN,,0,0,0,,Where this is a predicate,\nDialogue: 0,0:13:56.35,0:13:58.43,EN,,0,0,0,,a predicate is a thing that is either true or false,\nDialogue: 0,0:13:58.99,0:14:01.76,EN,,0,0,0,,and the expression to be evaluated if the predicate is true.\nDialogue: 0,0:14:03.44,0:14:06.08,EN,,0,0,0,,A set of clauses, if you will, that's the name for such a thing.\nDialogue: 0,0:14:06.79,0:14:09.36,EN,,0,0,0,,So I'm going put that somewhere else.\nDialogue: 0,0:14:09.36,0:14:11.56,EN,,0,0,0,,We're going to worry about that in another piece of code.\nDialogue: 0,0:14:12.42,0:14:21.28,EN,,0,0,0,,So EQ--  if the CAR of the expression is COND,\nDialogue: 0,0:14:24.00,0:14:26.84,EN,,0,0,0,,then I'm going to do nothing more than evaluate the COND,\nDialogue: 0,0:14:30.20,0:14:31.42,EN,,0,0,0,,the CDR of the expression.\nDialogue: 0,0:14:34.40,0:14:38.49,EN,,0,0,0,,That's all the clauses in the environment that I'm given.\nDialogue: 0,0:14:41.43,0:14:42.60,EN,,0,0,0,,Well, there's one more case,\nDialogue: 0,0:14:44.09,0:14:48.22,EN,,0,0,0,,arbitrary thing like the sum of x and three,\nDialogue: 0,0:14:50.62,0:14:53.95,EN,,0,0,0,,where this is an operator applied to operands,\nDialogue: 0,0:14:55.13,0:14:56.59,EN,,0,0,0,,and there's nothing special about it.\nDialogue: 0,0:14:56.59,0:14:59.63,EN,,0,0,0,,It's not one of the special cases, the special forms.\nDialogue: 0,0:14:59.85,0:15:01.42,EN,,0,0,0,,These are the special forms.\nDialogue: 0,0:15:09.65,0:15:12.12,EN,,0,0,0,,And if I were writing here a professional program, again,\nDialogue: 0,0:15:12.36,0:15:14.17,EN,,0,0,0,,I would somehow make this data directed.\nDialogue: 0,0:15:14.48,0:15:16.52,EN,,0,0,0,,So there wouldn't be a sequence of conditionals here,\nDialogue: 0,0:15:16.65,0:15:18.20,EN,,0,0,0,,there'd be a dispatch on some bits\nDialogue: 0,0:15:19.42,0:15:22.25,EN,,0,0,0,,if I were trying to do this in a more professional way.\nDialogue: 0,0:15:22.36,0:15:24.14,EN,,0,0,0,,So that, in fact, I can add to the thing\nDialogue: 0,0:15:24.68,0:15:26.38,EN,,0,0,0,,without changing my program much.\nDialogue: 0,0:15:26.71,0:15:28.46,EN,,0,0,0,,So, for example, they would run fast,\nDialogue: 0,0:15:29.04,0:15:30.43,EN,,0,0,0,,but I'm not worried about that.\nDialogue: 0,0:15:31.28,0:15:33.98,EN,,0,0,0,,Here we're trying to look at this in its entirety.\nDialogue: 0,0:15:35.07,0:15:35.80,EN,,0,0,0,,So it's else.\nDialogue: 0,0:15:37.69,0:15:38.56,EN,,0,0,0,,Well, what do we do?\nDialogue: 0,0:15:38.56,0:15:41.23,EN,,0,0,0,,In this case, I have to somehow do an addition.\nDialogue: 0,0:15:44.35,0:15:46.16,EN,,0,0,0,,Well, I could find out what the plus is.\nDialogue: 0,0:15:46.84,0:15:49.29,EN,,0,0,0,,I have to find out what the x and the three are.\nDialogue: 0,0:15:50.55,0:15:53.96,EN,,0,0,0,,And then I have to apply the result of finding what the plus is\nDialogue: 0,0:15:54.43,0:15:57.00,EN,,0,0,0,,to the result of finding out what the x and the three are.\nDialogue: 0,0:15:58.11,0:15:59.39,EN,,0,0,0,,We'll have a name for that.\nDialogue: 0,0:15:59.87,0:16:09.55,EN,,0,0,0,,So I'm going to apply the result of evaluating the CAR\nDialogue: 0,0:16:11.20,0:16:12.14,EN,,0,0,0,,of the expression--\nDialogue: 0,0:16:13.21,0:16:15.50,EN,,0,0,0,,the car of the expression is the operator--\nDialogue: 0,0:16:17.20,0:16:18.51,EN,,0,0,0,,in the environment given.\nDialogue: 0,0:16:20.51,0:16:22.89,EN,,0,0,0,,So evaluating the operator gets me the procedure.\nDialogue: 0,0:16:24.05,0:16:26.78,EN,,0,0,0,,Now I have to evaluate all the operands to get the arguments.\nDialogue: 0,0:16:27.29,0:16:28.22,EN,,0,0,0,,I'll call that EVLIST,\nDialogue: 0,0:16:31.26,0:16:35.53,EN,,0,0,0,,the CDR of the operands, of the expression,\nDialogue: 0,0:16:36.76,0:16:39.00,EN,,0,0,0,,with respect to the environment.\nDialogue: 0,0:16:41.94,0:16:43.13,EN,,0,0,0,,EVLIST will come up later--\nDialogue: 0,0:16:43.26,0:16:48.07,EN,,0,0,0,,EVLIST, apply, COND pair, COND, lambda, define.\nDialogue: 0,0:16:50.90,0:16:52.33,EN,,0,0,0,,So that what you are seeing here\nDialogue: 0,0:16:52.67,0:16:56.11,EN,,0,0,0,,is pretty much all there is in the evaluator itself.\nDialogue: 0,0:16:56.49,0:17:01.00,EN,,0,0,0,,It's the case dispatch on the type of the expression\nDialogue: 0,0:17:01.24,0:17:02.11,EN,,0,0,0,,with the default\nDialogue: 0,0:17:04.99,0:17:07.95,EN,,0,0,0,,being a general application or a combination.\nDialogue: 0,0:17:17.52,0:17:19.52,EN,,0,0,0,,Now there is lots of things we haven't defined yet.\nDialogue: 0,0:17:20.08,0:17:21.60,EN,,0,0,0,,Let's just look at them and see what they are.\nDialogue: 0,0:17:21.78,0:17:24.12,EN,,0,0,0,,We're going to have to do this later, evcond.\nDialogue: 0,0:17:25.48,0:17:26.67,EN,,0,0,0,,We have to write apply.\nDialogue: 0,0:17:27.57,0:17:28.62,EN,,0,0,0,,We're going to have to write EVLIST.\nDialogue: 0,0:17:28.94,0:17:30.20,EN,,0,0,0,,We're going to write LOOKUP.\nDialogue: 0,0:17:31.79,0:17:33.43,EN,,0,0,0,,I think that's everything, isn't there?\nDialogue: 0,0:17:33.43,0:17:35.16,EN,,0,0,0,,Everything else is something which is simple,\nDialogue: 0,0:17:35.16,0:17:37.18,EN,,0,0,0,,or primitive, or something like that.\nDialogue: 0,0:17:38.57,0:17:39.48,EN,,0,0,0,,And, of course,\nDialogue: 0,0:17:39.69,0:17:42.06,EN,,0,0,0,,we could many more special forms here,\nDialogue: 0,0:17:42.25,0:17:44.45,EN,,0,0,0,,but that would be a bad idea in general in a language.\nDialogue: 0,0:17:44.45,0:17:45.92,EN,,0,0,0,,You make a language very complicated\nDialogue: 0,0:17:46.00,0:17:47.48,EN,,0,0,0,,by putting a lot of things in there.\nDialogue: 0,0:17:47.69,0:17:50.35,EN,,0,0,0,,The number of reserve words that should exist in a language\nDialogue: 0,0:17:50.76,0:17:53.61,EN,,0,0,0,,should be no more than a person could remember on his fingers and toes.\nDialogue: 0,0:17:54.16,0:17:55.53,EN,,0,0,0,,And I get very upset with languages\nDialogue: 0,0:17:55.56,0:17:58.20,EN,,0,0,0,,which have hundreds of reserve words.\nDialogue: 0,0:17:59.41,0:18:00.71,EN,,0,0,0,,But that's where the reserve words go.\nDialogue: 0,0:18:03.15,0:18:06.54,EN,,0,0,0,,Okay. Well, now let's get to the next part of this,\nDialogue: 0,0:18:06.56,0:18:07.69,EN,,0,0,0,,the kernel, apply.\nDialogue: 0,0:18:09.64,0:18:10.75,EN,,0,0,0,,What else is this doing?\nDialogue: 0,0:18:11.59,0:18:17.53,EN,,0,0,0,,Well, apply's job is to take a procedure and apply it to its arguments\nDialogue: 0,0:18:17.66,0:18:20.68,EN,,0,0,0,,after both have been evaluated to come up with a procedure and the arguments\nDialogue: 0,0:18:20.91,0:18:23.85,EN,,0,0,0,,rather the operator symbols and the operand symbols,\nDialogue: 0,0:18:24.09,0:18:26.96,EN,,0,0,0,,whatever they are-- symbolic expressions.\nDialogue: 0,0:18:33.27,0:18:35.08,EN,,0,0,0,,So we will define apply\nDialogue: 0,0:18:38.35,0:18:40.65,EN,,0,0,0,,to be a procedure of two arguments,\nDialogue: 0,0:18:40.75,0:18:43.44,EN,,0,0,0,,a procedure and arguments.\nDialogue: 0,0:18:47.24,0:18:48.12,EN,,0,0,0,,And what does it do?\nDialogue: 0,0:18:48.14,0:18:49.55,EN,,0,0,0,,It does nothing very complicated.\nDialogue: 0,0:18:49.93,0:18:50.78,EN,,0,0,0,,It's got two cases.\nDialogue: 0,0:18:53.58,0:18:55.16,EN,,0,0,0,,Either the procedure is primitive--\nDialogue: 0,0:19:03.42,0:19:06.41,EN,,0,0,0,,And I don't know exactly how that is done.\nDialogue: 0,0:19:06.86,0:19:10.24,EN,,0,0,0,,It's possible there's some type information\nDialogue: 0,0:19:10.38,0:19:12.41,EN,,0,0,0,,just like we made closure for, here,\nDialogue: 0,0:19:12.68,0:19:15.05,EN,,0,0,0,,being the description of the type of a compound thing--\nDialogue: 0,0:19:16.33,0:19:17.79,EN,,0,0,0,,OK? probably so.\nDialogue: 0,0:19:18.55,0:19:20.20,EN,,0,0,0,,But it is not essential how that works,\nDialogue: 0,0:19:20.68,0:19:22.01,EN,,0,0,0,,in fact, it turns out,\nDialogue: 0,0:19:22.19,0:19:23.85,EN,,0,0,0,,as you probably know or have deduced,\nDialogue: 0,0:19:23.87,0:19:25.47,EN,,0,0,0,,that you don't need any primitives anyway.\nDialogue: 0,0:19:27.35,0:19:29.28,EN,,0,0,0,,You can compute anything because without\nDialogue: 0,0:19:30.46,0:19:33.19,EN,,0,0,0,,because some of the lambda that I've been playing with.\nDialogue: 0,0:19:33.61,0:19:34.76,EN,,0,0,0,,But it's nice to have them.\nDialogue: 0,0:19:34.81,0:19:36.27,EN,,0,0,0,,So here we're going to do some magic\nDialogue: 0,0:19:36.30,0:19:37.47,EN,,0,0,0,,which I'm not going to explain.\nDialogue: 0,0:19:38.06,0:19:41.44,EN,,0,0,0,,Go to machine language, apply primop.\nDialogue: 0,0:19:42.91,0:19:43.80,EN,,0,0,0,,Here's how it adds.\nDialogue: 0,0:19:44.78,0:19:46.10,EN,,0,0,0,,Execute an add instruction.\nDialogue: 0,0:19:50.62,0:19:52.11,EN,,0,0,0,,However, the interesting part of a language\nDialogue: 0,0:19:52.14,0:19:54.27,EN,,0,0,0,,is the glue by which the primitives are glued together.\nDialogue: 0,0:19:54.91,0:19:55.90,EN,,0,0,0,,So let's look at that.\nDialogue: 0,0:19:56.91,0:19:58.38,EN,,0,0,0,,Well, the other possibility\nDialogue: 0,0:19:58.75,0:20:04.12,EN,,0,0,0,,this is a compound made up by executing a lambda expression,\nDialogue: 0,0:20:04.97,0:20:07.05,EN,,0,0,0,,this is a compound procedure.\nDialogue: 0,0:20:07.62,0:20:09.36,EN,,0,0,0,,Well, we'll check its type.\nDialogue: 0,0:20:10.11,0:20:17.07,EN,,0,0,0,,If it is closure,\nDialogue: 0,0:20:20.51,0:20:24.09,EN,,0,0,0,,if it's one of those, then I have to do an eval of the body.\nDialogue: 0,0:20:24.19,0:20:27.39,EN,,0,0,0,,The way I do this, the way I deal with this at all\nDialogue: 0,0:20:28.08,0:20:31.69,EN,,0,0,0,,is the way I evaluate the application of a procedure to its arguments,\nDialogue: 0,0:20:31.72,0:20:33.71,EN,,0,0,0,,is by evaluating the body of the procedure\nDialogue: 0,0:20:34.19,0:20:37.80,EN,,0,0,0,,in the environment resulting from extending the environment of the procedure\nDialogue: 0,0:20:37.92,0:20:40.48,EN,,0,0,0,,with the bindings of the formal parameters\nDialogue: 0,0:20:41.02,0:20:43.68,EN,,0,0,0,,of the procedure to the arguments that were passed to it.\nDialogue: 0,0:20:46.70,0:20:47.87,EN,,0,0,0,,That was a long sentence.\nDialogue: 0,0:20:51.13,0:20:52.16,EN,,0,0,0,,Well that's easy enough.\nDialogue: 0,0:20:52.82,0:20:54.48,EN,,0,0,0,,Now here's going to be a lot of CAR-CDRing.\nDialogue: 0,0:20:56.46,0:20:58.11,EN,,0,0,0,,I have to get the body of the procedure.\nDialogue: 0,0:20:59.40,0:21:02.30,EN,,0,0,0,,Where's the body of the procedure in here?\nDialogue: 0,0:21:02.96,0:21:04.08,EN,,0,0,0,,Well here's the CAR,\nDialogue: 0,0:21:04.49,0:21:06.13,EN,,0,0,0,,here's the CDR is the whole rest of this.\nDialogue: 0,0:21:06.13,0:21:06.96,EN,,0,0,0,,So here's the CADR.\nDialogue: 0,0:21:07.40,0:21:09.45,EN,,0,0,0,,And so I see, what I have here is the body\nDialogue: 0,0:21:09.45,0:21:13.04,EN,,0,0,0,,is the second element of the second element of the procedure.\nDialogue: 0,0:21:13.20,0:21:15.15,EN,,0,0,0,,So it's the CADR of the CADR or the CADADR.\nDialogue: 0,0:21:19.17,0:21:27.68,EN,,0,0,0,,It's the C-A-D-A-D-R, CADADR of the procedure.\nDialogue: 0,0:21:30.26,0:21:31.56,EN,,0,0,0,,To evaluate the body\nDialogue: 0,0:21:31.98,0:21:36.48,EN,,0,0,0,,in the result of binding that's making up more environment,\nDialogue: 0,0:21:38.09,0:21:42.06,EN,,0,0,0,,well I need the formal parameters of the of the procedure,\nDialogue: 0,0:21:42.06,0:21:42.72,EN,,0,0,0,,what is that?\nDialogue: 0,0:21:43.50,0:21:45.13,EN,,0,0,0,,That's the CAR of the CADR.\nDialogue: 0,0:21:46.52,0:21:48.78,EN,,0,0,0,,OK? It's horrible isn't it?\nDialogue: 0,0:21:52.65,0:21:53.63,EN,,0,0,0,,--of the procedure.\nDialogue: 0,0:21:55.44,0:22:00.86,EN,,0,0,0,,Bind that to the arguments that were passed in the environment,\nDialogue: 0,0:22:00.89,0:22:04.14,EN,,0,0,0,,which is passed also as part of the procedure.\nDialogue: 0,0:22:04.54,0:22:07.90,EN,,0,0,0,,Well, that's the CAR of the CDR of the CDR of this,\nDialogue: 0,0:22:09.79,0:22:16.62,EN,,0,0,0,,CADDR, of the procedure.\nDialogue: 0,0:22:20.29,0:22:24.96,EN,,0,0,0,,Bind, eval, pair, COND, lamda, define--\nDialogue: 0,0:22:26.14,0:22:29.68,EN,,0,0,0,,Now, of course, if I were being really a neat character,\nDialogue: 0,0:22:29.87,0:22:31.34,EN,,0,0,0,,and I was being very careful,\nDialogue: 0,0:22:32.24,0:22:34.12,EN,,0,0,0,,I would actually put an extra case here\nDialogue: 0,0:22:34.38,0:22:35.98,EN,,0,0,0,,for checking for certain errors like,\nDialogue: 0,0:22:36.17,0:22:38.41,EN,,0,0,0,,did you try to apply one to an argument?\nDialogue: 0,0:22:39.00,0:22:41.69,EN,,0,0,0,,You get a undefined procedure type.\nDialogue: 0,0:22:42.57,0:22:44.09,EN,,0,0,0,,So I may as well do that anyway.\nDialogue: 0,0:22:45.80,0:22:55.96,EN,,0,0,0,,--else, some sort of error, like that.\nDialogue: 0,0:22:57.61,0:23:01.61,EN,,0,0,0,,Now, of course, again, in some sort of more real system,\nDialogue: 0,0:23:02.56,0:23:04.22,EN,,0,0,0,,written for professional reasons,\nDialogue: 0,0:23:05.32,0:23:08.00,EN,,0,0,0,,this would be written with a case analysis\nDialogue: 0,0:23:08.36,0:23:09.90,EN,,0,0,0,,done by some sort of dispatch.\nDialogue: 0,0:23:10.75,0:23:12.68,EN,,0,0,0,,Over here, I would probably have other cases\nDialogue: 0,0:23:12.70,0:23:14.14,EN,,0,0,0,,like, is this compiled code?\nDialogue: 0,0:23:16.22,0:23:16.84,EN,,0,0,0,,It's very important.\nDialogue: 0,0:23:16.88,0:23:18.35,EN,,0,0,0,,I might have distinguished the kind of code\nDialogue: 0,0:23:18.38,0:23:22.33,EN,,0,0,0,,that's produced by a directly evaluating a lambda in interpretation\nDialogue: 0,0:23:22.94,0:23:25.87,EN,,0,0,0,,from code that was produced by somebody's compiler or something like that.\nDialogue: 0,0:23:26.11,0:23:27.23,EN,,0,0,0,,And we'll talk about that later.\nDialogue: 0,0:23:27.23,0:23:29.61,EN,,0,0,0,,Or is this a piece Fortran program I have to go off and execute.\nDialogue: 0,0:23:30.51,0:23:32.51,EN,,0,0,0,,It's a perfectly possible thing, at this point, to do that.\nDialogue: 0,0:23:32.92,0:23:36.41,EN,,0,0,0,,In fact, in this concrete syntax evaluator I'm writing here,\nDialogue: 0,0:23:37.45,0:23:40.86,EN,,0,0,0,,there's an assumption built in that this is Lisp,\nDialogue: 0,0:23:42.30,0:23:43.82,EN,,0,0,0,,because I'm using CARs and CDRs.\nDialogue: 0,0:23:43.84,0:23:45.10,EN,,0,0,0,,CAR means the operator,\nDialogue: 0,0:23:45.28,0:23:46.64,EN,,0,0,0,,and CDR means the operand.\nDialogue: 0,0:23:46.75,0:23:49.96,EN,,0,0,0,,In the text, there is an abstract syntax evaluator\nDialogue: 0,0:23:50.35,0:23:53.15,EN,,0,0,0,,which these could be-- these are given abstract names\nDialogue: 0,0:23:53.16,0:23:54.09,EN,,0,0,0,,like operator, and operand,\nDialogue: 0,0:23:54.14,0:23:55.82,EN,,0,0,0,,and all these other things are like that.\nDialogue: 0,0:23:56.16,0:23:56.86,EN,,0,0,0,,And, in that case,\nDialogue: 0,0:23:57.02,0:24:00.91,EN,,0,0,0,,you could reprogram it to be ALGOL with no problem.\nDialogue: 0,0:24:03.36,0:24:06.40,EN,,0,0,0,,Well, here we have added another couple of things\nDialogue: 0,0:24:07.20,0:24:08.43,EN,,0,0,0,,that we haven't defined.\nDialogue: 0,0:24:10.81,0:24:12.57,EN,,0,0,0,,I don't think I'll worry about these at all,\nDialogue: 0,0:24:13.39,0:24:15.05,EN,,0,0,0,,however, this one will be interesting later.\nDialogue: 0,0:24:17.18,0:24:19.76,EN,,0,0,0,,Let's just proceed through this and get it done.\nDialogue: 0,0:24:20.55,0:24:22.65,EN,,0,0,0,,There's only two more blackboards so it can't be very long.\nDialogue: 0,0:24:27.40,0:24:29.08,EN,,0,0,0,,It's carefully tailored to exactly fit.\nDialogue: 0,0:24:30.07,0:24:30.98,EN,,0,0,0,,Well, what do we have left?\nDialogue: 0,0:24:30.98,0:24:33.20,EN,,0,0,0,,We have to define EVLIST, which is over here.\nDialogue: 0,0:24:33.73,0:24:35.07,EN,,0,0,0,,And EVLIST is nothing more\nDialogue: 0,0:24:35.26,0:24:43.08,EN,,0,0,0,,than a map down a bunch of operands producing arguments.\nDialogue: 0,0:24:44.30,0:24:45.40,EN,,0,0,0,,But I'm going to write it out.\nDialogue: 0,0:24:45.82,0:24:48.30,EN,,0,0,0,,And one of the reasons I'm going to write this out is for a mystical reason,\nDialogue: 0,0:24:49.88,0:24:52.04,EN,,0,0,0,,which is I want to make this evaluator so simple\nDialogue: 0,0:24:52.06,0:24:53.56,EN,,0,0,0,,that it can understand itself.\nDialogue: 0,0:24:56.45,0:24:58.09,EN,,0,0,0,,I'm going to really worry about that a little bit.\nDialogue: 0,0:25:00.23,0:25:01.74,EN,,0,0,0,,So let's write it out completely.\nDialogue: 0,0:25:02.85,0:25:04.24,EN,,0,0,0,,See, I don't want to worry about\nDialogue: 0,0:25:04.27,0:25:06.08,EN,,0,0,0,,whether or not the thing can pass functional arguments.\nDialogue: 0,0:25:06.27,0:25:08.06,EN,,0,0,0,,The value evaluator is not going to use them.\nDialogue: 0,0:25:08.98,0:25:10.78,EN,,0,0,0,,The evaluator is not going to produce functional values.\nDialogue: 0,0:25:10.88,0:25:12.67,EN,,0,0,0,,So even if there were a different, alternative language\nDialogue: 0,0:25:12.80,0:25:13.96,EN,,0,0,0,,that were very close to this,\nDialogue: 0,0:25:15.16,0:25:17.79,EN,,0,0,0,,this evaluates a complex language like Scheme\nDialogue: 0,0:25:17.80,0:25:23.12,EN,,0,0,0,,which does allow procedural arguments, procedural values, and procedural data.\nDialogue: 0,0:25:24.07,0:25:25.95,EN,,0,0,0,,But even if I were evaluating ALGOL,\nDialogue: 0,0:25:27.34,0:25:28.96,EN,,0,0,0,,which doesn't allow procedural values,\nDialogue: 0,0:25:29.47,0:25:30.59,EN,,0,0,0,,I could use this evaluator.\nDialogue: 0,0:25:31.58,0:25:33.92,EN,,0,0,0,,And this evaluator is not making any assumptions about that.\nDialogue: 0,0:25:34.27,0:25:36.03,EN,,0,0,0,,And, in fact, if this evaluator were to be restricted\nDialogue: 0,0:25:36.27,0:25:37.50,EN,,0,0,0,,to not being able to that, it wouldn't matter\nDialogue: 0,0:25:37.52,0:25:40.03,EN,,0,0,0,,because it doesn't use any of those clever things.\nDialogue: 0,0:25:40.64,0:25:42.41,EN,,0,0,0,,So that's why I'm arranging this to be super simple.\nDialogue: 0,0:25:44.07,0:25:46.46,EN,,0,0,0,,This is sort of the kernel of all possible language evaluators.\nDialogue: 0,0:25:47.81,0:25:48.48,EN,,0,0,0,,How about that?\nDialogue: 0,0:25:49.42,0:25:53.56,EN,,0,0,0,,Evlist--  well, what is it?\nDialogue: 0,0:25:53.82,0:25:57.04,EN,,0,0,0,,It's the procedure of two arguments, l and an environment,\nDialogue: 0,0:25:58.09,0:25:59.08,EN,,0,0,0,,where l is a list\nDialogue: 0,0:25:59.58,0:26:08.27,EN,,0,0,0,,such that if the list of arguments is the empty list,\nDialogue: 0,0:26:10.19,0:26:12.68,EN,,0,0,0,,then the result is the empty list.\nDialogue: 0,0:26:14.03,0:26:19.23,EN,,0,0,0,,Otherwise, I want to cons up\nDialogue: 0,0:26:20.75,0:26:26.67,EN,,0,0,0,,result of evaluating the CAR of the\nDialogue: 0,0:26:28.16,0:26:32.51,EN,,0,0,0,,the CAR of the list of operands in the environment.\nDialogue: 0,0:26:33.34,0:26:35.71,EN,,0,0,0,,So I want the first operand evaluated,\nDialogue: 0,0:26:35.98,0:26:38.40,EN,,0,0,0,,and I'm going to make a list of the results\nDialogue: 0,0:26:38.97,0:26:40.76,EN,,0,0,0,,by CONSing that onto the result\nDialogue: 0,0:26:41.08,0:26:45.42,EN,,0,0,0,,of this EVLISTing as a CDR recursion,\nDialogue: 0,0:26:46.22,0:26:50.13,EN,,0,0,0,,the CDR of the list relative to the same environment.\nDialogue: 0,0:26:53.08,0:26:58.24,EN,,0,0,0,,Evlist, cons, else, COND, lambda, define--\nDialogue: 0,0:26:59.66,0:27:01.84,EN,,0,0,0,,OK? And I have one more\nDialogue: 0,0:27:01.84,0:27:03.36,EN,,0,0,0,,that I want to put on the blackboard.\nDialogue: 0,0:27:03.62,0:27:05.21,EN,,0,0,0,,It's the essence of this whole thing.\nDialogue: 0,0:27:05.64,0:27:08.13,EN,,0,0,0,,And there's some sort of next layer down.\nDialogue: 0,0:27:14.54,0:27:15.44,EN,,0,0,0,,Conditionals--\nDialogue: 0,0:27:15.69,0:27:16.99,EN,,0,0,0,,conditionals are the only thing left\nDialogue: 0,0:27:17.02,0:27:18.17,EN,,0,0,0,,that are sort of substantial.\nDialogue: 0,0:27:18.88,0:27:20.75,EN,,0,0,0,,Then below that, we have to worry about\nDialogue: 0,0:27:21.07,0:27:22.94,EN,,0,0,0,,things like lookup and bind,\nDialogue: 0,0:27:23.56,0:27:25.36,EN,,0,0,0,,and we'll look at that in a second.\nDialogue: 0,0:27:25.53,0:27:27.93,EN,,0,0,0,,But of the substantial stuff at this level of detail,\nDialogue: 0,0:27:28.65,0:27:30.62,EN,,0,0,0,,next important thing is how you deal with conditionals.\nDialogue: 0,0:27:31.60,0:27:33.33,EN,,0,0,0,,Well, how do we have a conditional thing?\nDialogue: 0,0:27:36.97,0:27:38.56,EN,,0,0,0,,It's a procedure\nDialogue: 0,0:27:39.48,0:27:45.00,EN,,0,0,0,,of clauses and an environment.\nDialogue: 0,0:27:47.71,0:27:48.51,EN,,0,0,0,,And what does it do?\nDialogue: 0,0:27:49.82,0:27:55.47,EN,,0,0,0,,It says, if I've no more clauses,\nDialogue: 0,0:28:02.60,0:28:03.96,EN,,0,0,0,,well, I have to give this a value.\nDialogue: 0,0:28:04.70,0:28:05.87,EN,,0,0,0,,It could be that it was an error.\nDialogue: 0,0:28:06.54,0:28:08.59,EN,,0,0,0,,Supposing it run off the end of a conditional,\nDialogue: 0,0:28:09.15,0:28:10.06,EN,,0,0,0,,it's pretty arbitrary.\nDialogue: 0,0:28:10.06,0:28:12.88,EN,,0,0,0,,It's up to me as programmer to choose what I want to happen.\nDialogue: 0,0:28:13.65,0:28:15.45,EN,,0,0,0,,It's convenient for me, right now, to write down\nDialogue: 0,0:28:15.63,0:28:17.53,EN,,0,0,0,,this has a value which is the empty list,\nDialogue: 0,0:28:18.14,0:28:18.83,EN,,0,0,0,,doesn't matter.\nDialogue: 0,0:28:20.10,0:28:20.88,EN,,0,0,0,,For error checking,\nDialogue: 0,0:28:20.89,0:28:22.76,EN,,0,0,0,,some people might prefer something else.\nDialogue: 0,0:28:23.11,0:28:24.81,EN,,0,0,0,,But the interesting things are the following ones.\nDialogue: 0,0:28:25.39,0:28:27.24,EN,,0,0,0,,If I've got an else clause--\nDialogue: 0,0:28:31.00,0:28:32.73,EN,,0,0,0,,You see, if I have a list of clauses,\nDialogue: 0,0:28:33.21,0:28:34.41,EN,,0,0,0,,then each clause is a list.\nDialogue: 0,0:28:35.44,0:28:40.52,EN,,0,0,0,,And so the predicate part is the CAAR of the clauses.\nDialogue: 0,0:28:43.56,0:28:45.02,EN,,0,0,0,,It's the CAR,\nDialogue: 0,0:28:45.04,0:28:49.00,EN,,0,0,0,,which is the first part of the first clause in the list of clauses.\nDialogue: 0,0:28:51.09,0:28:51.84,EN,,0,0,0,,If it's an else,\nDialogue: 0,0:28:54.32,0:28:56.51,EN,,0,0,0,,then it means I want my result of the conditional\nDialogue: 0,0:28:56.64,0:28:59.15,EN,,0,0,0,,to be the result of evaluating the matching expression.\nDialogue: 0,0:29:00.12,0:29:04.32,EN,,0,0,0,,So I eval the CADAR.\nDialogue: 0,0:29:07.00,0:29:09.56,EN,,0,0,0,,So this is the first clause,\nDialogue: 0,0:29:10.12,0:29:11.63,EN,,0,0,0,,the second element of it, CADAR--\nDialogue: 0,0:29:12.81,0:29:17.08,EN,,0,0,0,,CADR of a CAR-- of the clauses,\nDialogue: 0,0:29:21.23,0:29:22.57,EN,,0,0,0,,with respect to the environment.\nDialogue: 0,0:29:26.62,0:29:28.60,EN,,0,0,0,,Now the next possibility is more interesting.\nDialogue: 0,0:29:29.63,0:29:30.44,EN,,0,0,0,,If it's false,\nDialogue: 0,0:29:33.05,0:29:35.10,EN,,0,0,0,,if the first predicate in the predicate list\nDialogue: 0,0:29:35.74,0:29:37.68,EN,,0,0,0,,is not an else, and it's not false,\nDialogue: 0,0:29:38.32,0:29:39.50,EN,,0,0,0,,if it's not the word else,\nDialogue: 0,0:29:40.16,0:29:42.00,EN,,0,0,0,,and if it's not a false thing--\nDialogue: 0,0:29:42.03,0:29:43.66,EN,,0,0,0,,Let's write down what it is if it's a false thing.\nDialogue: 0,0:29:44.36,0:29:50.08,EN,,0,0,0,,If the result of evaluating the first clause -- first predicate,\nDialogue: 0,0:29:52.33,0:29:56.76,EN,,0,0,0,,the clauses--  respect the environment,\nDialogue: 0,0:29:58.19,0:30:01.00,EN,,0,0,0,,if that evaluation yields false,\nDialogue: 0,0:30:01.69,0:30:03.82,EN,,0,0,0,,then it means, I want to look at the next clause.\nDialogue: 0,0:30:04.36,0:30:05.74,EN,,0,0,0,,So I want to discard the first one.\nDialogue: 0,0:30:06.25,0:30:08.33,EN,,0,0,0,,So we just go around loop, evcond,\nDialogue: 0,0:30:09.95,0:30:16.49,EN,,0,0,0,,the CDR of the clauses relative to that environment.\nDialogue: 0,0:30:19.95,0:30:25.15,EN,,0,0,0,,And otherwise, I had a true clause,\nDialogue: 0,0:30:26.84,0:30:28.96,EN,,0,0,0,,what I want is to evaluate\nDialogue: 0,0:30:31.85,0:30:41.45,EN,,0,0,0,,the CADAR of the clauses relative to that environment.\nDialogue: 0,0:30:48.20,0:30:49.61,EN,,0,0,0,,Boy, it's almost done.\nDialogue: 0,0:30:51.21,0:30:52.80,EN,,0,0,0,,It's quite close to done.\nDialogue: 0,0:30:53.73,0:30:55.87,EN,,0,0,0,,I think we're going to finish this part off.\nDialogue: 0,0:30:56.21,0:30:58.57,EN,,0,0,0,,So just buzzing through this evaluator,\nDialogue: 0,0:30:58.81,0:31:00.70,EN,,0,0,0,,but so far you're seeing almost everything.\nDialogue: 0,0:31:01.08,0:31:04.04,EN,,0,0,0,,Let's look at the next transparency here.\nDialogue: 0,0:31:06.32,0:31:10.43,EN,,0,0,0,,And see IS, Here is bind.\nDialogue: 0,0:31:11.98,0:31:14.54,EN,,0,0,0,,Bind is for making more table.\nDialogue: 0,0:31:15.46,0:31:18.67,EN,,0,0,0,,And what we are going to do here is make a--\nDialogue: 0,0:31:19.24,0:31:22.80,EN,,0,0,0,,we're going to make a new frame for an environment structure.\nDialogue: 0,0:31:22.80,0:31:25.42,EN,,0,0,0,,The environment structure is going to be represented\nDialogue: 0,0:31:25.93,0:31:27.20,EN,,0,0,0,,as a list of frames.\nDialogue: 0,0:31:28.08,0:31:30.19,EN,,0,0,0,,So given an existing environment structure,\nDialogue: 0,0:31:30.32,0:31:32.11,EN,,0,0,0,,I'm going to make a new environment structure\nDialogue: 0,0:31:32.25,0:31:33.82,EN,,0,0,0,,by consing a new frame\nDialogue: 0,0:31:33.93,0:31:35.69,EN,,0,0,0,,onto the existing environment structure,\nDialogue: 0,0:31:36.62,0:31:40.36,EN,,0,0,0,,where the new frame consists of the result of pairing up the variables,\nDialogue: 0,0:31:41.05,0:31:43.79,EN,,0,0,0,,which are the bound variables of the procedure I'm applying,\nDialogue: 0,0:31:44.12,0:31:48.25,EN,,0,0,0,,to the values which are the arguments that were passed that procedure.\nDialogue: 0,0:31:49.69,0:31:50.65,EN,,0,0,0,,This is just making a list,\nDialogue: 0,0:31:51.64,0:31:54.06,EN,,0,0,0,,adding a new element to our list of frames,\nDialogue: 0,0:31:54.30,0:31:55.60,EN,,0,0,0,,which is an environment structure,\nDialogue: 0,0:31:55.74,0:31:56.89,EN,,0,0,0,,to make a new environment.\nDialogue: 0,0:31:58.65,0:32:00.65,EN,,0,0,0,,Where pair-up is very simple.\nDialogue: 0,0:32:01.54,0:32:02.84,EN,,0,0,0,,Pair-up is nothing more\nDialogue: 0,0:32:03.13,0:32:05.56,EN,,0,0,0,,than if I have a list of variables and a list of values,\nDialogue: 0,0:32:05.93,0:32:08.62,EN,,0,0,0,,well, if I run out of variables and if I run out of values,\nDialogue: 0,0:32:08.62,0:32:09.58,EN,,0,0,0,,everything's OK.\nDialogue: 0,0:32:09.72,0:32:11.48,EN,,0,0,0,,Otherwise, I've given too many arguments.\nDialogue: 0,0:32:12.51,0:32:15.98,EN,,0,0,0,,If I've not run out of variables, but I've run out of values,\nDialogue: 0,0:32:16.06,0:32:17.37,EN,,0,0,0,,that I have too few arguments.\nDialogue: 0,0:32:18.51,0:32:19.63,EN,,0,0,0,,And in the general case,\nDialogue: 0,0:32:19.63,0:32:21.48,EN,,0,0,0,,where I don't have any errors, and I'm not done,\nDialogue: 0,0:32:22.06,0:32:25.61,EN,,0,0,0,,OK? Then I really am just adding a new pair\nDialogue: 0,0:32:25.76,0:32:30.17,EN,,0,0,0,,of the first variable with the first argument,\nDialogue: 0,0:32:30.94,0:32:32.12,EN,,0,0,0,,the first value,\nDialogue: 0,0:32:32.76,0:32:36.40,EN,,0,0,0,,onto a list resulting from pairing-up\nDialogue: 0,0:32:37.12,0:32:40.64,EN,,0,0,0,,the rest of the variables with the rest of the values.\nDialogue: 0,0:32:42.95,0:32:44.78,EN,,0,0,0,,Lookup is of course equally simple.\nDialogue: 0,0:32:46.28,0:32:49.63,EN,,0,0,0,,If I have to look up a symbol in an environment,\nDialogue: 0,0:32:49.93,0:32:51.39,EN,,0,0,0,,well, if the environment is empty,\nDialogue: 0,0:32:51.56,0:32:53.00,EN,,0,0,0,,then I've got an unbound variable.\nDialogue: 0,0:32:54.65,0:32:55.47,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:32:56.86,0:33:00.36,EN,,0,0,0,,what I'm going to do is use a special pair list lookup procedure,\nDialogue: 0,0:33:00.38,0:33:01.87,EN,,0,0,0,,which we'll have very shortly,\nDialogue: 0,0:33:02.24,0:33:05.44,EN,,0,0,0,,of the symbol in the first frame of the environment.\nDialogue: 0,0:33:05.93,0:33:07.21,EN,,0,0,0,,Since I know the environment is not empty,\nDialogue: 0,0:33:07.23,0:33:08.40,EN,,0,0,0,,it must have a first frame.\nDialogue: 0,0:33:09.20,0:33:11.14,EN,,0,0,0,,So I lookup the symbol in the first frame.\nDialogue: 0,0:33:11.56,0:33:13.58,EN,,0,0,0,,That becomes the value cell here.\nDialogue: 0,0:33:14.38,0:33:17.61,EN,,0,0,0,,OK? And then, if the value cell is empty,\nDialogue: 0,0:33:18.44,0:33:20.57,EN,,0,0,0,,if there is no such value cell,\nDialogue: 0,0:33:20.70,0:33:22.84,EN,,0,0,0,,then I have to continue and look at the rest of the frames.\nDialogue: 0,0:33:23.72,0:33:25.04,EN,,0,0,0,,It means there was nothing found there.\nDialogue: 0,0:33:25.99,0:33:28.89,EN,,0,0,0,,So that's a property of ASSQ is it returns emptiness\nDialogue: 0,0:33:29.52,0:33:30.80,EN,,0,0,0,,if it doesn't find something.\nDialogue: 0,0:33:32.32,0:33:33.85,EN,,0,0,0,,but if it did find something,\nDialogue: 0,0:33:33.85,0:33:36.06,EN,,0,0,0,,then I'm going to use the CDR of the value cell here,\nDialogue: 0,0:33:36.46,0:33:40.25,EN,,0,0,0,,which is the thing that was the pair consisting of the variable and the value.\nDialogue: 0,0:33:41.05,0:33:43.93,EN,,0,0,0,,So the CDR of it is the value part. OK?\nDialogue: 0,0:33:45.00,0:33:47.82,EN,,0,0,0,,Finally, ASSQ is something you've probably seen already.\nDialogue: 0,0:33:47.97,0:33:50.83,EN,,0,0,0,,ASSQ takes a symbol and a list of pairs,\nDialogue: 0,0:33:51.42,0:33:53.40,EN,,0,0,0,,and if the list is empty, it's empty.\nDialogue: 0,0:33:53.52,0:33:56.30,EN,,0,0,0,,If the symbol is the first thing in the list--\nDialogue: 0,0:33:58.06,0:33:58.91,EN,,0,0,0,,That's an error.\nDialogue: 0,0:33:59.82,0:34:02.17,EN,,0,0,0,,That should be CAAR, C-A-A-R.\nDialogue: 0,0:34:03.16,0:34:04.16,EN,,0,0,0,,Everybody note that.\nDialogue: 0,0:34:07.63,0:34:09.37,EN,,0,0,0,,Right there, OK?\nDialogue: 0,0:34:13.42,0:34:14.41,EN,,0,0,0,,And in any case,\nDialogue: 0,0:34:14.56,0:34:16.81,EN,,0,0,0,,f the symbol is the CAAR of the A list,\nDialogue: 0,0:34:17.16,0:34:20.97,EN,,0,0,0,,then I want the first, the first pair, in the alist.\nDialogue: 0,0:34:22.08,0:34:25.50,EN,,0,0,0,,So, in other words, if this is the key matching the right entry,\nDialogue: 0,0:34:26.24,0:34:26.97,EN,,0,0,0,,otherwise,\nDialogue: 0,0:34:27.08,0:34:28.94,EN,,0,0,0,,I want to look up that symbol in the rest.\nDialogue: 0,0:34:30.08,0:34:33.31,EN,,0,0,0,,Sorry for producing a bug, bugs appear.\nDialogue: 0,0:34:35.19,0:34:36.28,EN,,0,0,0,,Well, in any case,\nDialogue: 0,0:34:37.05,0:34:39.48,EN,,0,0,0,,you're pretty much seeing the whole thing now.\nDialogue: 0,0:34:41.88,0:34:43.29,EN,,0,0,0,,It's a very beautiful thing,\nDialogue: 0,0:34:44.19,0:34:46.00,EN,,0,0,0,,even though it's written in an ugly style,\nDialogue: 0,0:34:46.76,0:34:48.30,EN,,0,0,0,,being the kernel of every language.\nDialogue: 0,0:34:49.60,0:34:51.37,EN,,0,0,0,,I suggest that we just-- let's look at it for a while.\nDialogue: 0,0:35:00.32,0:35:47.02,EN,,0,0,0,,[ALSO SPRACH ZARATHUSTRA]\nDialogue: 0,0:35:49.75,0:35:50.91,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:36:01.18,0:36:03.29,EN,,0,0,0,,Alright, I suppose it's time to take a small break then.\nDialogue: 0,0:36:04.04,0:36:10.73,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:36:56.78,0:36:58.99,EN,,0,0,0,,OK, now we're just going to do a little bit of practice\nDialogue: 0,0:36:59.29,0:37:02.67,EN,,0,0,0,,understanding what it is we've just shown you. OK?\nDialogue: 0,0:37:03.47,0:37:05.48,EN,,0,0,0,,What we're going to do is go through, in detail,\nDialogue: 0,0:37:05.50,0:37:10.36,EN,,0,0,0,,an evaluation by informally substituting through the interpreter.\nDialogue: 0,0:37:11.50,0:37:14.94,EN,,0,0,0,,And since we have no assignments or definitions in this interpreter,\nDialogue: 0,0:37:15.20,0:37:17.34,EN,,0,0,0,,we have no possible side effects,\nDialogue: 0,0:37:17.98,0:37:22.03,EN,,0,0,0,,and so the we can do substitution with impunity\nDialogue: 0,0:37:22.52,0:37:24.59,EN,,0,0,0,,and not worry about results.\nDialogue: 0,0:37:25.33,0:37:27.80,EN,,0,0,0,,So the particular problem I'd like to look at\nDialogue: 0,0:37:28.06,0:37:29.63,EN,,0,0,0,,is it an interesting one.\nDialogue: 0,0:37:30.69,0:37:34.09,EN,,0,0,0,,It's the evaluation of\nDialogue: 0,0:37:34.91,0:37:48.08,EN,,0,0,0,,quote, open, open, open, lambda of x, lambda of y plus x y,\nDialogue: 0,0:37:50.30,0:37:52.62,EN,,0,0,0,,lambda, lambda,\nDialogue: 0,0:37:53.04,0:37:56.12,EN,,0,0,0,,applied to three, applied to four,\nDialogue: 0,0:37:56.94,0:37:59.58,EN,,0,0,0,,in some global environment which I'll call e0.\nDialogue: 0,0:38:04.93,0:38:05.96,EN,,0,0,0,,So what we have here\nDialogue: 0,0:38:06.36,0:38:08.04,EN,,0,0,0,,is a procedure of one argument x,\nDialogue: 0,0:38:08.09,0:38:11.05,EN,,0,0,0,,which produces as its value a procedure of one argument y,\nDialogue: 0,0:38:11.07,0:38:12.12,EN,,0,0,0,,which adds x to y.\nDialogue: 0,0:38:14.30,0:38:17.96,EN,,0,0,0,,We are applying the procedure of one argument x to three.\nDialogue: 0,0:38:17.96,0:38:19.39,EN,,0,0,0,,So x should become three.\nDialogue: 0,0:38:21.40,0:38:23.98,EN,,0,0,0,,And the result of that should be procedure of one argument y,\nDialogue: 0,0:38:24.33,0:38:25.82,EN,,0,0,0,,which will then apply to 4.\nDialogue: 0,0:38:28.91,0:38:30.32,EN,,0,0,0,,And there is a very simple case,\nDialogue: 0,0:38:31.04,0:38:32.73,EN,,0,0,0,,they will then add those results.\nDialogue: 0,0:38:34.79,0:38:35.82,EN,,0,0,0,,And now in order to do that,\nDialogue: 0,0:38:35.84,0:38:37.76,EN,,0,0,0,,I want to make a very simple environment model.\nDialogue: 0,0:38:37.90,0:38:40.48,EN,,0,0,0,,And at this point, you should already have in your mind\nDialogue: 0,0:38:40.99,0:38:42.59,EN,,0,0,0,,the environments that this produces.\nDialogue: 0,0:38:44.46,0:38:46.62,EN,,0,0,0,,But we're going to start out with a global environment,\nDialogue: 0,0:38:48.59,0:38:50.06,EN,,0,0,0,,which I'll call e0,\nDialogue: 0,0:38:54.60,0:38:55.47,EN,,0,0,0,,which is that.\nDialogue: 0,0:38:56.74,0:39:02.46,EN,,0,0,0,,And it's going to have in it things, definitions for plus, and times,\nDialogue: 0,0:39:06.30,0:39:10.36,EN,,0,0,0,,and-- using Greek letters, isn't that interesting, for the objects--\nDialogue: 0,0:39:11.21,0:39:27.93,EN,,0,0,0,,and minus, and quotient, and CAR, and CDR, and CONS, and EQ,\nDialogue: 0,0:39:28.59,0:39:31.05,EN,,0,0,0,,and everything else you might imagine in a global environment.\nDialogue: 0,0:39:31.27,0:39:33.82,EN,,0,0,0,,It's got something there for each of those things,\nDialogue: 0,0:39:34.62,0:39:36.09,EN,,0,0,0,,something the machine is born with,\nDialogue: 0,0:39:37.10,0:39:38.09,EN,,0,0,0,,that's e0.\nDialogue: 0,0:39:39.22,0:39:41.84,EN,,0,0,0,,Now what does it mean to do this evaluation?\nDialogue: 0,0:39:42.94,0:39:45.18,EN,,0,0,0,,Well, we go through the set of special forms.\nDialogue: 0,0:39:45.69,0:39:47.05,EN,,0,0,0,,First of all, this is not a number.\nDialogue: 0,0:39:48.67,0:39:50.38,EN,,0,0,0,,This is not a symbol.\nDialogue: 0,0:39:53.13,0:39:55.60,EN,,0,0,0,,Gee, it's not a quoted expression.\nDialogue: 0,0:39:56.60,0:39:58.38,EN,,0,0,0,,This is a quoted expression,\nDialogue: 0,0:39:59.47,0:40:00.80,EN,,0,0,0,,but that's not what I mentioned.\nDialogue: 0,0:40:00.83,0:40:01.36,EN,,0,0,0,,The question is,\nDialogue: 0,0:40:01.39,0:40:04.96,EN,,0,0,0,,whether or not the thing which is quoted is quoted expression?\nDialogue: 0,0:40:05.89,0:40:07.96,EN,,0,0,0,,I'm evaluating an expression.\nDialogue: 0,0:40:07.96,0:40:09.98,EN,,0,0,0,,This just says it's this particular expression.\nDialogue: 0,0:40:11.41,0:40:12.66,EN,,0,0,0,,This is not a quoted expression.\nDialogue: 0,0:40:13.71,0:40:17.21,EN,,0,0,0,,OK? It's not a thing that begins with lambda.\nDialogue: 0,0:40:19.12,0:40:20.67,EN,,0,0,0,,It's not a thing that begins with COND.\nDialogue: 0,0:40:22.03,0:40:25.95,EN,,0,0,0,,Therefore, it's an application of its of an operated operands.\nDialogue: 0,0:40:26.31,0:40:27.12,EN,,0,0,0,,It's a combination.\nDialogue: 0,0:40:28.57,0:40:30.70,EN,,0,0,0,,The combination thus has\nDialogue: 0,0:40:30.89,0:40:34.00,EN,,0,0,0,,this as the operator\nDialogue: 0,0:40:34.64,0:40:36.08,EN,,0,0,0,,and this is the operands.\nDialogue: 0,0:40:40.13,0:40:42.41,EN,,0,0,0,,Well, that means that what I'm going to do is\nDialogue: 0,0:40:42.57,0:40:47.90,EN,,0,0,0,,transform this into apply of eval,\nDialogue: 0,0:40:50.12,0:40:57.61,EN,,0,0,0,,of quote, open, open lambda of x, lambda of y--\nDialogue: 0,0:40:57.88,0:40:59.12,EN,,0,0,0,,I'm evaluating the operator--\nDialogue: 0,0:40:59.95,0:41:04.19,EN,,0,0,0,,plus x y, in the environment,\nDialogue: 0,0:41:07.26,0:41:08.64,EN,,0,0,0,,also e0,\nDialogue: 0,0:41:12.78,0:41:15.20,EN,,0,0,0,,with the operands that I'm going to apply this to,\nDialogue: 0,0:41:15.26,0:41:17.28,EN,,0,0,0,,the arguments being the result of EVLIST,\nDialogue: 0,0:41:21.21,0:41:24.49,EN,,0,0,0,,the list containing four, fin e0.\nDialogue: 0,0:41:29.01,0:41:31.26,EN,,0,0,0,,I'm using this funny notation here for e0\nDialogue: 0,0:41:32.32,0:41:34.83,EN,,0,0,0,,because this should be that environment.\nDialogue: 0,0:41:35.45,0:41:37.77,EN,,0,0,0,,I haven't a name for it,\nDialogue: 0,0:41:37.80,0:41:39.15,EN,,0,0,0,,because I have no environment to name it in.\nDialogue: 0,0:41:41.96,0:41:44.09,EN,,0,0,0,,So this is just a representation\nDialogue: 0,0:41:44.17,0:41:46.17,EN,,0,0,0,,what would be a quoted expression, if you will.\nDialogue: 0,0:41:47.73,0:41:51.16,EN,,0,0,0,,The data structure, which is the environment, goes there.\nDialogue: 0,0:41:53.04,0:41:55.04,EN,,0,0,0,,Well, that's what we're seeing here.\nDialogue: 0,0:41:55.85,0:41:56.67,EN,,0,0,0,,Well in order to do this,\nDialogue: 0,0:41:56.68,0:41:58.04,EN,,0,0,0,,I have to do this, and I have to do that.\nDialogue: 0,0:41:59.61,0:42:00.49,EN,,0,0,0,,Well this one's easy,\nDialogue: 0,0:42:00.57,0:42:03.18,EN,,0,0,0,,so why don't we do that one first. OK?\nDialogue: 0,0:42:03.77,0:42:07.44,EN,,0,0,0,,This turns into apply of eval--\nDialogue: 0,0:42:07.45,0:42:08.83,EN,,0,0,0,,just copying something now.\nDialogue: 0,0:42:09.42,0:42:11.00,EN,,0,0,0,,Most of the substitution rule is copying.\nDialogue: 0,0:42:18.53,0:42:21.24,EN,,0,0,0,,So I'm going to not say the words when I copy,\nDialogue: 0,0:42:21.71,0:42:23.87,EN,,0,0,0,,because it's faster.\nDialogue: 0,0:42:26.41,0:42:28.64,EN,,0,0,0,,And then the EVLIST is going to turn into a\nDialogue: 0,0:42:28.65,0:42:36.72,EN,,0,0,0,,cons, of eval, of four, in e0--\nDialogue: 0,0:42:38.78,0:42:40.17,EN,,0,0,0,,because it was not an empty list--\nDialogue: 0,0:42:41.44,0:42:49.39,EN,,0,0,0,,onto the result of EVLISTing, on the empty list, in e0.\nDialogue: 0,0:42:52.58,0:42:54.20,EN,,0,0,0,,And I'm going to start leaving out steps soon,\nDialogue: 0,0:42:54.24,0:42:55.36,EN,,0,0,0,,because it's going to get boring.\nDialogue: 0,0:42:59.87,0:43:05.42,EN,,0,0,0,,But this is basically the same thing as apply, of eval--\nDialogue: 0,0:43:07.50,0:43:08.54,EN,,0,0,0,,I'm going to keep doing this--\nDialogue: 0,0:43:10.68,0:43:20.24,EN,,0,0,0,,the lambda of x, the lambda of y, plus xy, 3, close, e0.\nDialogue: 0,0:43:20.24,0:43:21.20,EN,,0,0,0,,I'm a pretty good machine.\nDialogue: 0,0:43:24.24,0:43:26.24,EN,,0,0,0,,Well, eval of four,\nDialogue: 0,0:43:26.56,0:43:28.44,EN,,0,0,0,,that's meets the question, is it a number.\nDialogue: 0,0:43:29.00,0:43:33.90,EN,,0,0,0,,So that's cons, right, cons of 4.\nDialogue: 0,0:43:34.03,0:43:37.47,EN,,0,0,0,,And EVLIST of the empty list is the empty list,\nDialogue: 0,0:43:38.33,0:43:39.24,EN,,0,0,0,,so that's this.\nDialogue: 0,0:43:42.62,0:43:45.08,EN,,0,0,0,,OK. And that's very simple to understand,\nDialogue: 0,0:43:45.10,0:43:47.44,EN,,0,0,0,,because that means the list containing four itself.\nDialogue: 0,0:43:48.71,0:43:53.84,EN,,0,0,0,,So this is nothing more than apply of eval,\nDialogue: 0,0:43:55.28,0:44:02.51,EN,,0,0,0,,quote, open, open, lambda of x, lambda of y, plus x y,\nDialogue: 0,0:44:03.40,0:44:07.48,EN,,0,0,0,,three applied to, e0, applied to the list four--\nDialogue: 0,0:44:08.68,0:44:12.60,EN,,0,0,0,,applied to the list four-- bang\nDialogue: 0,0:44:13.94,0:44:15.05,EN,,0,0,0,,So that's that step.\nDialogue: 0,0:44:17.00,0:44:19.96,EN,,0,0,0,,Now let's look at the next, more interesting thing.\nDialogue: 0,0:44:20.36,0:44:21.72,EN,,0,0,0,,What do I do to evaluate that?\nDialogue: 0,0:44:23.07,0:44:24.44,EN,,0,0,0,,Evaluating this means\nDialogue: 0,0:44:25.20,0:44:28.65,EN,,0,0,0,,means I have to evaluate-- Well, it's not.\nDialogue: 0,0:44:29.46,0:44:31.04,EN,,0,0,0,,It's nothing but an application.\nDialogue: 0,0:44:31.68,0:44:33.10,EN,,0,0,0,,It's not one of the special things.\nDialogue: 0,0:44:33.57,0:44:36.51,EN,,0,0,0,,If the application of this operator,\nDialogue: 0,0:44:36.51,0:44:37.37,EN,,0,0,0,,which we see here--\nDialogue: 0,0:44:37.66,0:44:38.94,EN,,0,0,0,,here's the operator--\nDialogue: 0,0:44:40.19,0:44:41.77,EN,,0,0,0,,applied to this operands,\nDialogue: 0,0:44:44.54,0:44:45.74,EN,,0,0,0,,that combination.\nDialogue: 0,0:44:46.72,0:44:48.25,EN,,0,0,0,,But we know how to do that,\nDialogue: 0,0:44:48.84,0:44:52.37,EN,,0,0,0,,because that's the last case of the conditional.\nDialogue: 0,0:44:52.37,0:44:55.52,EN,,0,0,0,,So substituting in for this evaluation,\nDialogue: 0,0:44:55.71,0:44:57.47,EN,,0,0,0,,it's apply of eval of the operator\nDialogue: 0,0:44:57.50,0:44:59.00,EN,,0,0,0,,in the EVLIST of the operands.\nDialogue: 0,0:45:01.16,0:45:08.20,EN,,0,0,0,,Well, it's apply, of apply, of eval,\nDialogue: 0,0:45:10.57,0:45:21.07,EN,,0,0,0,,of quote, open, lambda of x, lambda of y, plus x y,\nDialogue: 0,0:45:21.80,0:45:23.45,EN,,0,0,0,,lambda, lambda,\nDialogue: 0,0:45:23.74,0:45:25.42,EN,,0,0,0,,in environment e0.\nDialogue: 0,0:45:30.52,0:45:32.67,EN,,0,0,0,,I'm going to short circuit the evaluation of the operands,\nDialogue: 0,0:45:32.68,0:45:34.14,EN,,0,0,0,,because they're the same as they were before.\nDialogue: 0,0:45:35.23,0:45:36.48,EN,,0,0,0,,I got a list containing three,\nDialogue: 0,0:45:36.51,0:45:39.16,EN,,0,0,0,,apply that, and apply that to four.\nDialogue: 0,0:45:42.44,0:45:43.56,EN,,0,0,0,,Well let's see.\nDialogue: 0,0:45:44.41,0:45:46.38,EN,,0,0,0,,Eval of a lambda expression\nDialogue: 0,0:45:48.01,0:45:49.45,EN,,0,0,0,,produces a procedure object.\nDialogue: 0,0:45:52.03,0:45:57.88,EN,,0,0,0,,So this is apply, of apply,\nDialogue: 0,0:46:00.30,0:46:02.27,EN,,0,0,0,,of the procedure object closure,\nDialogue: 0,0:46:04.52,0:46:08.68,EN,,0,0,0,,which contains the body of the procedure, x,\nDialogue: 0,0:46:08.94,0:46:11.92,EN,,0,0,0,,which is lambda, which binds x [UNINTELLIGIBLE]\nDialogue: 0,0:46:12.13,0:46:15.40,EN,,0,0,0,,the internals of the body,\nDialogue: 0,0:46:15.80,0:46:18.17,EN,,0,0,0,,it returns the procedure of one argument y,\nDialogue: 0,0:46:18.56,0:46:20.63,EN,,0,0,0,,which adds x to y.\nDialogue: 0,0:46:23.21,0:46:25.50,EN,,0,0,0,,Environment e0 is now captured in it,\nDialogue: 0,0:46:27.24,0:46:29.63,EN,,0,0,0,,because this was evaluated with respect to e0.\nDialogue: 0,0:46:30.11,0:46:32.43,EN,,0,0,0,,e0 is part now of the closure object.\nDialogue: 0,0:46:33.04,0:46:38.19,EN,,0,0,0,,Apply that to open, three, close, apply,\nDialogue: 0,0:46:38.81,0:46:41.30,EN,,0,0,0,,to open, 4, close, apply.\nDialogue: 0,0:46:47.39,0:46:49.29,EN,,0,0,0,,So going from this step to this step\nDialogue: 0,0:46:49.31,0:46:50.89,EN,,0,0,0,,meant that I made up a procedure object\nDialogue: 0,0:46:50.91,0:46:52.03,EN,,0,0,0,,which captured in it\nDialogue: 0,0:46:53.88,0:46:55.98,EN,,0,0,0,,e0 as part of the procedure object.\nDialogue: 0,0:46:57.15,0:46:58.51,EN,,0,0,0,,Now, we're going to pass those to apply.\nDialogue: 0,0:46:58.52,0:46:59.71,EN,,0,0,0,,We have to apply this procedure\nDialogue: 0,0:47:00.48,0:47:01.58,EN,,0,0,0,,to that set of arguments.\nDialogue: 0,0:47:02.71,0:47:06.51,EN,,0,0,0,,Well, but that procedure is not primitive.\nDialogue: 0,0:47:07.38,0:47:09.88,EN,,0,0,0,,It's, in fact, a thing which has got the tag closure,\nDialogue: 0,0:47:10.24,0:47:12.09,EN,,0,0,0,,and, therefore, what we have to do is do a bind.\nDialogue: 0,0:47:13.71,0:47:14.72,EN,,0,0,0,,We have to bind.\nDialogue: 0,0:47:15.83,0:47:19.40,EN,,0,0,0,,A new environment is made at this point,\nDialogue: 0,0:47:20.44,0:47:22.80,EN,,0,0,0,,which has as its parent environment\nDialogue: 0,0:47:22.94,0:47:27.56,EN,,0,0,0,,the one over here, e0, that environment.\nDialogue: 0,0:47:30.32,0:47:31.57,EN,,0,0,0,,And we'll call this one, e1.\nDialogue: 0,0:47:34.62,0:47:35.74,EN,,0,0,0,,Now what's bound in there?\nDialogue: 0,0:47:36.04,0:47:37.48,EN,,0,0,0,,x is bound to three.\nDialogue: 0,0:47:38.62,0:47:40.44,EN,,0,0,0,,So I have x equal three.\nDialogue: 0,0:47:41.48,0:47:42.33,EN,,0,0,0,,That's what's in there.\nDialogue: 0,0:47:44.94,0:47:46.24,EN,,0,0,0,,And we'll call that e1.\nDialogue: 0,0:47:46.24,0:47:48.44,EN,,0,0,0,,So what this transforms into\nDialogue: 0,0:47:49.13,0:47:50.72,EN,,0,0,0,,is an eval of the body\nDialogue: 0,0:47:51.72,0:47:53.07,EN,,0,0,0,,of this, which is this,\nDialogue: 0,0:47:54.40,0:47:55.72,EN,,0,0,0,,the body of that procedure,\nDialogue: 0,0:47:56.44,0:47:58.52,EN,,0,0,0,,in the environment that you just saw.\nDialogue: 0,0:48:00.29,0:48:05.05,EN,,0,0,0,,So that's an apply, of eval,\nDialogue: 0,0:48:06.92,0:48:16.43,EN,,0,0,0,,quote, open, lambda of y, plus x y-- the body-- in e1.\nDialogue: 0,0:48:20.49,0:48:22.48,EN,,0,0,0,,And apply the result of that to four,\nDialogue: 0,0:48:23.68,0:48:26.73,EN,,0,0,0,,open, close, 4-- list of arguments.\nDialogue: 0,0:48:28.43,0:48:29.87,EN,,0,0,0,,Well, that's sensible enough\nDialogue: 0,0:48:30.08,0:48:32.27,EN,,0,0,0,,because evaluating a lambda, I know what to do.\nDialogue: 0,0:48:33.11,0:48:34.17,EN,,0,0,0,,That means I apply,\nDialogue: 0,0:48:37.16,0:48:38.92,EN,,0,0,0,,the procedure which is closure,\nDialogue: 0,0:48:43.74,0:48:46.84,EN,,0,0,0,,binds one argument y, adds x to y,\nDialogue: 0,0:48:49.28,0:48:52.15,EN,,0,0,0,,with e1 captured in it.\nDialogue: 0,0:48:55.79,0:48:57.42,EN,,0,0,0,,And you should really see this. Right?\nDialogue: 0,0:48:57.80,0:49:00.14,EN,,0,0,0,,I somehow manufactured a closure.\nDialogue: 0,0:49:00.14,0:49:01.16,EN,,0,0,0,,I should've put this here.\nDialogue: 0,0:49:01.79,0:49:03.04,EN,,0,0,0,,There was one over here too.\nDialogue: 0,0:49:05.90,0:49:07.47,EN,,0,0,0,,OK? Well, there's one here now.\nDialogue: 0,0:49:08.08,0:49:09.80,EN,,0,0,0,,I've captured e1,\nDialogue: 0,0:49:10.41,0:49:14.25,EN,,0,0,0,,and this is the procedure of one argument y,\nDialogue: 0,0:49:15.45,0:49:16.70,EN,,0,0,0,,whatever this is.\nDialogue: 0,0:49:18.09,0:49:20.72,EN,,0,0,0,,That's what that is there, that closure.\nDialogue: 0,0:49:22.57,0:49:26.46,EN,,0,0,0,,OK? I'm going to apply that to four.\nDialogue: 0,0:49:30.28,0:49:31.77,EN,,0,0,0,,OK. Well, that's easy enough.\nDialogue: 0,0:49:36.83,0:49:38.73,EN,,0,0,0,,That means I have to make a new environment\nDialogue: 0,0:49:38.86,0:49:40.52,EN,,0,0,0,,by copying this pointer,\nDialogue: 0,0:49:41.56,0:49:43.21,EN,,0,0,0,,which was the pointer of the procedure,\nDialogue: 0,0:49:44.94,0:49:48.96,EN,,0,0,0,,which binds y equal 4 with that environment.\nDialogue: 0,0:49:49.82,0:49:52.22,EN,,0,0,0,,And here's my new environment, which I'll call e2.\nDialogue: 0,0:49:56.03,0:49:58.12,EN,,0,0,0,,And, of course, this application then\nDialogue: 0,0:49:58.22,0:50:00.33,EN,,0,0,0,,is evaluate the body in e2.\nDialogue: 0,0:50:01.58,0:50:07.87,EN,,0,0,0,,So this is eval, the body,\nDialogue: 0,0:50:07.90,0:50:11.85,EN,,0,0,0,,which is plus x y, in the environment e2.\nDialogue: 0,0:50:13.71,0:50:14.94,EN,,0,0,0,,But this is an application,\nDialogue: 0,0:50:15.48,0:50:23.88,EN,,0,0,0,,so this is the apply, of eval, plus in e2,\nDialogue: 0,0:50:26.33,0:50:37.34,EN,,0,0,0,,an EVLIST, quote, open, x y, in e2.\nDialogue: 0,0:50:44.88,0:50:45.59,EN,,0,0,0,,Well, but let's see.\nDialogue: 0,0:50:45.59,0:50:51.71,EN,,0,0,0,,That is apply, the object\nDialogue: 0,0:50:52.08,0:50:53.87,EN,,0,0,0,,which is a result of that and plus.\nDialogue: 0,0:50:54.19,0:50:55.66,EN,,0,0,0,,So here we are in e2,\nDialogue: 0,0:50:55.69,0:50:57.72,EN,,0,0,0,,plus is not here, it's not here,\nDialogue: 0,0:50:57.74,0:51:01.05,EN,,0,0,0,,yes, but's here as some primitive operator.\nDialogue: 0,0:51:01.78,0:51:04.74,EN,,0,0,0,,So it's the primitive operator for addition.\nDialogue: 0,0:51:07.47,0:51:14.12,EN,,0,0,0,,Apply that to the result of evaluating x and y in e2.\nDialogue: 0,0:51:14.37,0:51:17.00,EN,,0,0,0,,But we can see that x is three and y is four.\nDialogue: 0,0:51:18.11,0:51:23.31,EN,,0,0,0,,So that's a three and four, here.\nDialogue: 0,0:51:24.16,0:51:26.28,EN,,0,0,0,,And that magically produces for me a seven.\nDialogue: 0,0:51:30.52,0:51:32.44,EN,,0,0,0,,I wanted to go through this so you would see,\nDialogue: 0,0:51:32.70,0:51:34.73,EN,,0,0,0,,essentially, one important ingredient,\nDialogue: 0,0:51:35.76,0:51:37.29,EN,,0,0,0,,which is what's being passed around,\nDialogue: 0,0:51:37.31,0:51:39.56,EN,,0,0,0,,and who owns what, and what his job is.\nDialogue: 0,0:51:40.47,0:51:41.61,EN,,0,0,0,,So what do we have here?\nDialogue: 0,0:51:41.70,0:51:42.62,EN,,0,0,0,,We have eval,\nDialogue: 0,0:51:44.80,0:51:45.64,EN,,0,0,0,,We have eval, and we have apply,\nDialogue: 0,0:51:45.66,0:51:46.62,EN,,0,0,0,,the two main players.\nDialogue: 0,0:51:49.37,0:51:51.56,EN,,0,0,0,,And there is a big loop the goes around like this.\nDialogue: 0,0:51:52.32,0:52:04.57,EN,,0,0,0,,Which is eval produces a procedure and arguments for apply.\nDialogue: 0,0:52:06.27,0:52:08.57,EN,,0,0,0,,Now some things eval could do by itself.\nDialogue: 0,0:52:09.50,0:52:10.86,EN,,0,0,0,,Those are little self things here.\nDialogue: 0,0:52:10.86,0:52:11.74,EN,,0,0,0,,They're not interesting.\nDialogue: 0,0:52:12.70,0:52:15.60,EN,,0,0,0,,Also eval evaluates all of the arguments, one after another.\nDialogue: 0,0:52:16.24,0:52:17.28,EN,,0,0,0,,That's not very interesting.\nDialogue: 0,0:52:17.65,0:52:20.09,EN,,0,0,0,,Apply can apply some procedures like plus,\nDialogue: 0,0:52:21.02,0:52:22.04,EN,,0,0,0,,not very interesting.\nDialogue: 0,0:52:22.30,0:52:24.64,EN,,0,0,0,,However, if apply can't apply a procedure like plus,\nDialogue: 0,0:52:25.31,0:52:33.31,EN,,0,0,0,,it produces an expression and environment for eval.\nDialogue: 0,0:52:35.47,0:52:37.61,EN,,0,0,0,,The procedural arguments wrap up\nDialogue: 0,0:52:38.24,0:52:40.60,EN,,0,0,0,,essentially the state of a computation\nDialogue: 0,0:52:41.66,0:52:43.42,EN,,0,0,0,,and, certainly, the expression of environment.\nDialogue: 0,0:52:43.74,0:52:45.31,EN,,0,0,0,,And so what we're actually going to do next\nDialogue: 0,0:52:45.32,0:52:46.46,EN,,0,0,0,,is not the complete state,\nDialogue: 0,0:52:46.48,0:52:48.82,EN,,0,0,0,,because it doesn't say who wants the answers.\nDialogue: 0,0:52:51.28,0:52:52.20,EN,,0,0,0,,But what we're going to do--\nDialogue: 0,0:52:52.24,0:52:54.80,EN,,0,0,0,,it's always got something like an expression of environment\nDialogue: 0,0:52:54.99,0:52:56.14,EN,,0,0,0,,or procedure and arguments\nDialogue: 0,0:52:56.28,0:52:58.08,EN,,0,0,0,,as the main loop that we're going around.\nDialogue: 0,0:52:58.97,0:53:01.80,EN,,0,0,0,,There are minor little sub loops like eval through EVLIST,\nDialogue: 0,0:53:04.49,0:53:06.76,EN,,0,0,0,,or eval through evcond,\nDialogue: 0,0:53:09.10,0:53:11.96,EN,,0,0,0,,or apply through a primitive apply.\nDialogue: 0,0:53:16.14,0:53:17.64,EN,,0,0,0,,But they're not the essential things.\nDialogue: 0,0:53:18.86,0:53:20.28,EN,,0,0,0,,So that's what I wanted you to see.\nDialogue: 0,0:53:21.86,0:53:22.88,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:53:25.93,0:53:27.37,EN,,0,0,0,,Yes. David\nDialogue: 0,0:53:27.74,0:53:33.31,EN,,0,0,0,,AUDIENCE: I'm trying to understand how x got down to three\nDialogue: 0,0:53:34.01,0:53:36.30,EN,,0,0,0,,instead of four.\nDialogue: 0,0:53:37.07,0:53:38.52,EN,,0,0,0,,At the early part of the--\nDialogue: 0,0:53:38.56,0:53:40.54,EN,,0,0,0,,PROFESSOR: Here.\nDialogue: 0,0:53:41.31,0:53:43.31,EN,,0,0,0,,You want to know how x got down to three?\nDialogue: 0,0:53:43.52,0:53:47.42,EN,,0,0,0,,AUDIENCE: Because x is the outer procedure,\nDialogue: 0,0:53:48.46,0:53:50.99,EN,,0,0,0,,and x and y are the inner procedure.\nDialogue: 0,0:53:51.26,0:53:51.88,EN,,0,0,0,,PROFESSOR: Fine.\nDialogue: 0,0:53:52.84,0:53:54.62,EN,,0,0,0,,Well, I was very careful and mechanical.\nDialogue: 0,0:53:55.02,0:53:56.92,EN,,0,0,0,,First of all, I should write those procedures\nDialogue: 0,0:53:56.94,0:53:58.41,EN,,0,0,0,,again for you, pretty printed.\nDialogue: 0,0:54:00.61,0:54:01.47,EN,,0,0,0,,First order of business,\nDialogue: 0,0:54:01.48,0:54:02.99,EN,,0,0,0,,because you're probably not reading them well.\nDialogue: 0,0:54:03.83,0:54:04.70,EN,,0,0,0,,So I have here\nDialogue: 0,0:54:05.15,0:54:09.60,EN,,0,0,0,,that procedure of-- was it x over there--\nDialogue: 0,0:54:11.21,0:54:14.99,EN,,0,0,0,,which is -- value of that procedure of y\nDialogue: 0,0:54:15.72,0:54:18.44,EN,,0,0,0,,which adds x to y,\nDialogue: 0,0:54:19.82,0:54:21.10,EN,,0,0,0,,lambda, lambda,\nDialogue: 0,0:54:21.40,0:54:22.89,EN,,0,0,0,,applied that to three,\nDialogue: 0,0:54:24.08,0:54:26.12,EN,,0,0,0,,takes the result of that, and applied that to four.\nDialogue: 0,0:54:26.14,0:54:28.81,EN,,0,0,0,,Is that not what I wrote? OK?\nDialogue: 0,0:54:28.81,0:54:32.33,EN,,0,0,0,,Now, you should immediately see that\nDialogue: 0,0:54:33.77,0:54:34.94,EN,,0,0,0,,here is an application--\nDialogue: 0,0:54:35.16,0:54:36.46,EN,,0,0,0,,let me get a white piece of chalk--\nDialogue: 0,0:54:37.32,0:54:41.12,EN,,0,0,0,,here is an application, a combination.\nDialogue: 0,0:54:43.44,0:54:46.40,EN,,0,0,0,,OK? That combination has this as the operator\nDialogue: 0,0:54:48.14,0:54:49.55,EN,,0,0,0,,and this as the operand.\nDialogue: 0,0:54:51.04,0:54:53.05,EN,,0,0,0,,The three is going in for the x here.\nDialogue: 0,0:54:54.90,0:54:56.36,EN,,0,0,0,,The result of this\nDialogue: 0,0:54:56.56,0:54:58.46,EN,,0,0,0,,is a procedure of one argument y,\nDialogue: 0,0:54:58.73,0:54:59.79,EN,,0,0,0,,which gets applied to four.\nDialogue: 0,0:55:00.88,0:55:01.58,EN,,0,0,0,,OK?\nDialogue: 0,0:55:02.20,0:55:04.08,EN,,0,0,0,,So you just weren't reading the expression right.\nDialogue: 0,0:55:04.40,0:55:07.85,EN,,0,0,0,,The way you see that over here. OK.\nDialogue: 0,0:55:09.42,0:55:12.96,EN,,0,0,0,,is that here I have the actual procedure object, x.\nDialogue: 0,0:55:13.34,0:55:15.31,EN,,0,0,0,,It's getting applied to three,\nDialogue: 0,0:55:15.95,0:55:17.07,EN,,0,0,0,,the list containing three.\nDialogue: 0,0:55:18.98,0:55:21.34,EN,,0,0,0,,What I'm left over with is something which gets applied to four.\nDialogue: 0,0:55:24.08,0:55:25.20,EN,,0,0,0,,Are there any other questions?\nDialogue: 0,0:55:28.35,0:55:30.38,EN,,0,0,0,,Time for our next small break then.\nDialogue: 0,0:55:30.83,0:55:31.37,EN,,0,0,0,,Thank you.\nDialogue: 0,0:55:33.73,0:55:41.40,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:56:08.41,0:56:11.29,EN,,0,0,0,,PROFESSOR: Let's see, at this point,\nDialogue: 0,0:56:13.32,0:56:14.59,EN,,0,0,0,,you should be getting the feeling,\nDialogue: 0,0:56:14.75,0:56:17.96,EN,,0,0,0,,what's this nonsense this Sussman character is feeding me?\nDialogue: 0,0:56:20.74,0:56:23.92,EN,,0,0,0,,There's an awful lot of strange nonsense here.\nDialogue: 0,0:56:24.80,0:56:27.40,EN,,0,0,0,,After all, he purported to explain to me Lisp,\nDialogue: 0,0:56:28.01,0:56:29.90,EN,,0,0,0,,and he wrote me a Lisp program on the blackboard.\nDialogue: 0,0:56:31.23,0:56:33.53,EN,,0,0,0,,The Lisp program was intended to be interpreted for Lisp,\nDialogue: 0,0:56:33.85,0:56:35.02,EN,,0,0,0,,but you need a Lisp interpreter\nDialogue: 0,0:56:35.04,0:56:36.30,EN,,0,0,0,,in order to understand that program.\nDialogue: 0,0:56:38.37,0:56:40.19,EN,,0,0,0,,How could that program have told me anything\nDialogue: 0,0:56:40.22,0:56:43.20,EN,,0,0,0,,there is to be known about Lisp?\nDialogue: 0,0:56:44.15,0:56:46.22,EN,,0,0,0,,How is that not completely vacuous?\nDialogue: 0,0:56:48.49,0:56:50.25,EN,,0,0,0,,It's a very strange thing.\nDialogue: 0,0:56:50.99,0:56:52.43,EN,,0,0,0,,Does it tell me anything at all?\nDialogue: 0,0:56:56.07,0:56:57.20,EN,,0,0,0,,Well, you see, the whole thing\nDialogue: 0,0:56:57.32,0:56:59.79,EN,,0,0,0,,is sort of like these Escher's hands\nDialogue: 0,0:57:00.46,0:57:03.55,EN,,0,0,0,,that we see on this slide.\nDialogue: 0,0:57:06.18,0:57:07.72,EN,,0,0,0,,Yes, eval and apply\nDialogue: 0,0:57:07.76,0:57:10.16,EN,,0,0,0,,each sort of draw each other\nDialogue: 0,0:57:11.50,0:57:14.16,EN,,0,0,0,,and construct the real thing,\nDialogue: 0,0:57:14.86,0:57:16.30,EN,,0,0,0,,which can sit out and draw itself.\nDialogue: 0,0:57:17.11,0:57:18.46,EN,,0,0,0,,Escher was a very brilliant man,\nDialogue: 0,0:57:18.68,0:57:20.41,EN,,0,0,0,,he just didn't know the names of these spirits.\nDialogue: 0,0:57:23.91,0:57:25.00,EN,,0,0,0,,Well, I'm going to do now,\nDialogue: 0,0:57:26.09,0:57:28.00,EN,,0,0,0,,is I'm going to try to convince you\nDialogue: 0,0:57:28.16,0:57:29.87,EN,,0,0,0,,that both this mean something,\nDialogue: 0,0:57:30.16,0:57:31.98,EN,,0,0,0,,and, as a aside,\nDialogue: 0,0:57:32.99,0:57:34.72,EN,,0,0,0,,I'm going to show you why you don't need definitions.\nDialogue: 0,0:57:36.09,0:57:37.71,EN,,0,0,0,,Just turns out that sort of falls out,\nDialogue: 0,0:57:38.09,0:57:41.12,EN,,0,0,0,,why definitions are not essential in a mathematical sense\nDialogue: 0,0:57:42.51,0:57:44.89,EN,,0,0,0,,for doing all the things we need to do for computing.\nDialogue: 0,0:57:49.10,0:57:50.03,EN,,0,0,0,,Well, let's see here.\nDialogue: 0,0:57:50.69,0:57:53.31,EN,,0,0,0,,Consider the following small program,\nDialogue: 0,0:57:53.74,0:57:54.64,EN,,0,0,0,,what does it mean?\nDialogue: 0,0:57:54.87,0:57:57.64,EN,,0,0,0,,This is a program for computing exponentials.\nDialogue: 0,0:58:07.27,0:58:13.23,EN,,0,0,0,,The exponential of x to the nth power is if--\nDialogue: 0,0:58:16.83,0:58:18.12,EN,,0,0,0,,n is zero,\nDialogue: 0,0:58:19.20,0:58:20.76,EN,,0,0,0,,then the result is one.\nDialogue: 0,0:58:22.07,0:58:22.81,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:58:25.56,0:58:28.48,EN,,0,0,0,,I want the product of x\nDialogue: 0,0:58:28.75,0:58:33.93,EN,,0,0,0,,and the result of exponentiating x to the n minus one power.\nDialogue: 0,0:58:43.69,0:58:44.56,EN,,0,0,0,,I think I got it right.\nDialogue: 0,0:58:46.63,0:58:48.72,EN,,0,0,0,,Now this is a recursive definition.\nDialogue: 0,0:58:49.47,0:58:52.17,EN,,0,0,0,,It's a definition of the exponentiation\nDialogue: 0,0:58:52.46,0:58:54.78,EN,,0,0,0,,procedure in terms of itself.\nDialogue: 0,0:58:56.41,0:58:58.32,EN,,0,0,0,,And, as it has been mentioned before,\nDialogue: 0,0:58:59.28,0:59:01.68,EN,,0,0,0,,your high school geometry teacher\nDialogue: 0,0:59:01.84,0:59:04.04,EN,,0,0,0,,probably gave you a hard time about things like that.\nDialogue: 0,0:59:05.65,0:59:06.73,EN,,0,0,0,,Was that justified?\nDialogue: 0,0:59:07.91,0:59:10.84,EN,,0,0,0,,Why does this self referential definition\nDialogue: 0,0:59:10.96,0:59:12.04,EN,,0,0,0,,make any sense?\nDialogue: 0,0:59:13.43,0:59:15.10,EN,,0,0,0,,Well, first of all, I'm going to convince you that\nDialogue: 0,0:59:15.13,0:59:17.60,EN,,0,0,0,,your high school geometry teacher was not telling you nonsense.\nDialogue: 0,0:59:20.37,0:59:23.42,EN,,0,0,0,,Consider the following set of definitions here.\nDialogue: 0,0:59:24.27,0:59:27.42,EN,,0,0,0,,x plus y equals three,\nDialogue: 0,0:59:28.24,0:59:32.24,EN,,0,0,0,,and x minus y equal one.\nDialogue: 0,0:59:33.07,0:59:35.56,EN,,0,0,0,,Well, gee, this tells you x in terms of y,\nDialogue: 0,0:59:35.58,0:59:37.84,EN,,0,0,0,,and this one tells you y in terms of x, presumably.\nDialogue: 0,0:59:40.15,0:59:42.95,EN,,0,0,0,,And yet this happens to have a unique solution in x and y.\nDialogue: 0,0:59:55.91,0:59:58.11,EN,,0,0,0,,However, I could also write\nDialogue: 0,0:59:59.87,1:00:04.25,EN,,0,0,0,,two x plus two y is six.\nDialogue: 0,1:00:06.83,1:00:09.87,EN,,0,0,0,,These two equations have an infinite number solutions.\nDialogue: 0,1:00:15.73,1:00:17.42,EN,,0,0,0,,And I could write you, for example,\nDialogue: 0,1:00:18.89,1:00:21.53,EN,,0,0,0,,x minus y equal 2,\nDialogue: 0,1:00:22.14,1:00:24.41,EN,,0,0,0,,and these two equations have no solutions.\nDialogue: 0,1:00:29.82,1:00:33.04,EN,,0,0,0,,Well, I have here three sets of simultaneous linear equations,\nDialogue: 0,1:00:35.45,1:00:39.51,EN,,0,0,0,,this set, this set, and this set.\nDialogue: 0,1:00:39.88,1:00:41.79,EN,,0,0,0,,But they have different numbers of solutions.\nDialogue: 0,1:00:42.90,1:00:45.76,EN,,0,0,0,,The number of solutions is not in the form of the equations.\nDialogue: 0,1:00:46.33,1:00:48.20,EN,,0,0,0,,They all three sets have the same form.\nDialogue: 0,1:00:48.54,1:00:50.41,EN,,0,0,0,,The number of solutions is in the content.\nDialogue: 0,1:00:53.00,1:00:55.15,EN,,0,0,0,,I can't tell by looking at the form of a definition\nDialogue: 0,1:00:55.16,1:00:56.24,EN,,0,0,0,,whether it makes sense,\nDialogue: 0,1:00:56.86,1:00:58.60,EN,,0,0,0,,only by its detailed content.\nDialogue: 0,1:00:59.66,1:01:00.88,EN,,0,0,0,,What are the coefficients,\nDialogue: 0,1:01:01.34,1:01:03.39,EN,,0,0,0,,for example, in the case of linear equations?\nDialogue: 0,1:01:05.10,1:01:06.72,EN,,0,0,0,,So I shouldn't expect to be able to tell\nDialogue: 0,1:01:06.99,1:01:08.33,EN,,0,0,0,,looking at something like this,\nDialogue: 0,1:01:08.59,1:01:09.95,EN,,0,0,0,,from some simple things like,\nDialogue: 0,1:01:10.08,1:01:14.49,EN,,0,0,0,,oh yes, EXPT is the solution of this recursion equation.\nDialogue: 0,1:01:16.03,1:01:18.41,EN,,0,0,0,,Expt is the procedure\nDialogue: 0,1:01:18.91,1:01:21.10,EN,,0,0,0,,which if substituted in here,\nDialogue: 0,1:01:22.04,1:01:24.06,EN,,0,0,0,,gives me expt back.\nDialogue: 0,1:01:25.32,1:01:25.68,EN,,0,0,0,,OK?\nDialogue: 0,1:01:26.04,1:01:29.24,EN,,0,0,0,,I can't tell, looking at this form,\nDialogue: 0,1:01:29.80,1:01:32.60,EN,,0,0,0,,whether or not there's a single, unique solution for EXPT,\nDialogue: 0,1:01:33.23,1:01:35.31,EN,,0,0,0,,an infinite number of solutions, or no solutions.\nDialogue: 0,1:01:37.20,1:01:38.62,EN,,0,0,0,,It's got to be how it counts\nDialogue: 0,1:01:38.64,1:01:40.14,EN,,0,0,0,,and things like that, the details.\nDialogue: 0,1:01:40.60,1:01:42.75,EN,,0,0,0,,And it's harder in programming than linear algebra.\nDialogue: 0,1:01:43.28,1:01:45.21,EN,,0,0,0,,There aren't too many theorems about it in programming.\nDialogue: 0,1:01:48.45,1:01:51.21,EN,,0,0,0,,Well, I want to rewrite these equations a little bit,\nDialogue: 0,1:01:51.93,1:01:53.77,EN,,0,0,0,,these over here.\nDialogue: 0,1:01:53.97,1:01:56.62,EN,,0,0,0,,Because what we're investigating is equations like this.\nDialogue: 0,1:01:57.00,1:01:58.38,EN,,0,0,0,,But I want to play a little with equations\nDialogue: 0,1:01:58.40,1:01:59.53,EN,,0,0,0,,like this that we understand,\nDialogue: 0,1:02:00.70,1:02:02.91,EN,,0,0,0,,just so we get some insight into this kind of question.\nDialogue: 0,1:02:04.72,1:02:06.43,EN,,0,0,0,,We could rewrite our equations here,\nDialogue: 0,1:02:06.75,1:02:08.67,EN,,0,0,0,,say these two, the ones that are interesting,\nDialogue: 0,1:02:09.77,1:02:14.86,EN,,0,0,0,,as x equals three minus y,\nDialogue: 0,1:02:15.88,1:02:19.68,EN,,0,0,0,,and y equals x minus one.\nDialogue: 0,1:02:22.01,1:02:24.05,EN,,0,0,0,,What do we call this transformation?\nDialogue: 0,1:02:24.05,1:02:26.52,EN,,0,0,0,,This is a linear transformation, t.\nDialogue: 0,1:02:29.43,1:02:32.25,EN,,0,0,0,,Then what we're getting here is an equation\nDialogue: 0,1:02:32.97,1:02:37.37,EN,,0,0,0,,x y equals t of x y.\nDialogue: 0,1:02:42.99,1:02:43.98,EN,,0,0,0,,What am I looking for?\nDialogue: 0,1:02:44.56,1:02:46.01,EN,,0,0,0,,I'm looking for a fixed point of t.\nDialogue: 0,1:02:46.97,1:02:59.42,EN,,0,0,0,,The solution is a fixed point of t.\nDialogue: 0,1:03:01.91,1:03:05.53,EN,,0,0,0,,So the methods we should have for looking for solutions to equations,\nDialogue: 0,1:03:05.90,1:03:07.48,EN,,0,0,0,,if I can do it by fixed points,\nDialogue: 0,1:03:08.65,1:03:09.87,EN,,0,0,0,,might be applicable.\nDialogue: 0,1:03:10.88,1:03:12.36,EN,,0,0,0,,If I have a means of finding a solution\nDialogue: 0,1:03:12.38,1:03:14.32,EN,,0,0,0,,to an equations by fixed points--\nDialogue: 0,1:03:15.52,1:03:18.19,EN,,0,0,0,,just, might not work--\nDialogue: 0,1:03:18.57,1:03:19.80,EN,,0,0,0,,but it might be applicable\nDialogue: 0,1:03:20.09,1:03:22.27,EN,,0,0,0,,to investigating solutions of equations like this.\nDialogue: 0,1:03:27.24,1:03:29.48,EN,,0,0,0,,But what I want you to feel is that this is an equation.\nDialogue: 0,1:03:30.26,1:03:31.21,EN,,0,0,0,,It's an expression\nDialogue: 0,1:03:31.36,1:03:33.58,EN,,0,0,0,,with several instances of various names\nDialogue: 0,1:03:34.70,1:03:37.66,EN,,0,0,0,,which puts a constraint on the name,\nDialogue: 0,1:03:38.43,1:03:40.52,EN,,0,0,0,,saying what that name could have as its value,\nDialogue: 0,1:03:41.48,1:03:45.01,EN,,0,0,0,,rather than some sort of mechanical process of substitution right now.\nDialogue: 0,1:03:47.74,1:03:49.77,EN,,0,0,0,,This is an equation which I'm going to try to solve.\nDialogue: 0,1:03:51.22,1:03:52.43,EN,,0,0,0,,Well, let's play around and solve it.\nDialogue: 0,1:03:53.96,1:03:55.66,EN,,0,0,0,,First of all, I want to write down\nDialogue: 0,1:03:56.64,1:03:59.00,EN,,0,0,0,,the function which corresponds to t.\nDialogue: 0,1:04:00.32,1:04:03.00,EN,,0,0,0,,First I want to write down the function which corresponds to t\nDialogue: 0,1:04:04.49,1:04:06.96,EN,,0,0,0,,whose fixed point is the answer to this question.\nDialogue: 0,1:04:10.76,1:04:11.28,EN,,0,0,0,,OK?\nDialogue: 0,1:04:12.25,1:04:14.30,EN,,0,0,0,,Well, let's consider the following procedure f.\nDialogue: 0,1:04:16.87,1:04:18.30,EN,,0,0,0,,I claim it computes that function.\nDialogue: 0,1:04:19.34,1:04:22.91,EN,,0,0,0,,f is that procedure of one argument g,\nDialogue: 0,1:04:25.23,1:04:25.93,EN,,0,0,0,,which is\nDialogue: 0,1:04:26.40,1:04:32.00,EN,,0,0,0,,that procedure of two arguments x and n.\nDialogue: 0,1:04:33.43,1:04:34.73,EN,,0,0,0,,Which have the property that\nDialogue: 0,1:04:36.72,1:04:40.43,EN,,0,0,0,,if n is zero,\nDialogue: 0,1:04:41.72,1:04:43.20,EN,,0,0,0,,then the result is one,\nDialogue: 0,1:04:45.34,1:04:46.17,EN,,0,0,0,,otherwise,\nDialogue: 0,1:04:49.90,1:05:01.40,EN,,0,0,0,,the result is the product of x and g, applied to x, and minus n1.\nDialogue: 0,1:05:03.37,1:05:07.80,EN,,0,0,0,,g, times, else, COND, lambda, lambda--\nDialogue: 0,1:05:08.94,1:05:09.40,EN,,0,0,0,,OK?\nDialogue: 0,1:05:12.30,1:05:14.62,EN,,0,0,0,,Here f is a procedure,\nDialogue: 0,1:05:15.05,1:05:17.79,EN,,0,0,0,,which if I had a solution to that equation,\nDialogue: 0,1:05:19.04,1:05:22.04,EN,,0,0,0,,if I had a good exponentiation procedure,\nDialogue: 0,1:05:23.42,1:05:26.32,EN,,0,0,0,,and I applied f to that procedure,\nDialogue: 0,1:05:27.60,1:05:31.24,EN,,0,0,0,,then the result would be a good exponentiation procedure.\nDialogue: 0,1:05:37.46,1:05:38.57,EN,,0,0,0,,Because, what does it do?\nDialogue: 0,1:05:39.42,1:05:40.88,EN,,0,0,0,,Well, all it is\nDialogue: 0,1:05:42.36,1:05:44.64,EN,,0,0,0,,is exposing g were a good exponentiation procedure,\nDialogue: 0,1:05:45.63,1:05:47.58,EN,,0,0,0,,well then this would produce, as its value,\nDialogue: 0,1:05:47.84,1:05:49.68,EN,,0,0,0,,a procedure to arguments x and n,\nDialogue: 0,1:05:50.49,1:05:51.52,EN,,0,0,0,,such that if n were 0,\nDialogue: 0,1:05:51.55,1:05:52.41,EN,,0,0,0,,the result would be one,\nDialogue: 0,1:05:52.44,1:05:54.16,EN,,0,0,0,,which is certainly true of exponentiation.\nDialogue: 0,1:05:54.64,1:05:57.05,EN,,0,0,0,,Otherwise, it will be the result of multiplying x\nDialogue: 0,1:05:57.26,1:05:59.26,EN,,0,0,0,,by the exponentiation procedure given to me\nDialogue: 0,1:06:00.17,1:06:02.44,EN,,0,0,0,,with x and n minus one as arguments.\nDialogue: 0,1:06:03.47,1:06:04.78,EN,,0,0,0,,So if this computed the correct\nDialogue: 0,1:06:04.81,1:06:06.30,EN,,0,0,0,,exponentiation for n minus one,\nDialogue: 0,1:06:07.87,1:06:11.28,EN,,0,0,0,,then this would be the correct exponentiation for exponent n,\nDialogue: 0,1:06:12.17,1:06:14.41,EN,,0,0,0,,so this would have been the right exponentiation procedure.\nDialogue: 0,1:06:17.50,1:06:19.82,EN,,0,0,0,,So what I really want to say here is\nDialogue: 0,1:06:21.02,1:06:32.44,EN,,0,0,0,,E-X-P-T is a fixed point of f.\nDialogue: 0,1:06:36.99,1:06:38.35,EN,,0,0,0,,Now our problem is\nDialogue: 0,1:06:38.35,1:06:39.68,EN,,0,0,0,,there might be more than one fixed point.\nDialogue: 0,1:06:40.06,1:06:42.19,EN,,0,0,0,,There might be no fixed points.\nDialogue: 0,1:06:43.27,1:06:44.81,EN,,0,0,0,,I have to go hunting for the fixed points.\nDialogue: 0,1:06:48.22,1:06:49.37,EN,,0,0,0,,Got to solve this equation.\nDialogue: 0,1:06:52.16,1:06:54.28,EN,,0,0,0,,Well there are various ways to hunt for fixed points.\nDialogue: 0,1:06:55.58,1:06:57.08,EN,,0,0,0,,Of course, the one we played with\nDialogue: 0,1:06:57.24,1:07:01.16,EN,,0,0,0,,at the beginning of this term worked for cosine.\nDialogue: 0,1:07:02.73,1:07:07.69,EN,,0,0,0,,Going to. Go into radians mode on your calculator\nDialogue: 0,1:07:07.85,1:07:10.51,EN,,0,0,0,,and push cosine, and just keep doing it,\nDialogue: 0,1:07:11.84,1:07:15.45,EN,,0,0,0,,and you get to some number which is about 0.73 or 0.74.\nDialogue: 0,1:07:16.09,1:07:17.18,EN,,0,0,0,,I can't remember which.\nDialogue: 0,1:07:20.57,1:07:22.64,EN,,0,0,0,,By iterating a procedure, which has\nDialogue: 0,1:07:22.81,1:07:24.40,EN,,0,0,0,,By iterating a function,\nDialogue: 0,1:07:25.60,1:07:27.16,EN,,0,0,0,,whose fixed point I'm searching for,\nDialogue: 0,1:07:27.50,1:07:31.13,EN,,0,0,0,,it is sometimes the case that that function will converge\nDialogue: 0,1:07:31.87,1:07:33.08,EN,,0,0,0,,in producing the fixed point.\nDialogue: 0,1:07:33.77,1:07:35.44,EN,,0,0,0,,I think we luck out in this case,\nDialogue: 0,1:07:36.44,1:07:37.21,EN,,0,0,0,,so let's look for it.\nDialogue: 0,1:07:39.91,1:07:46.28,EN,,0,0,0,,Let's look at this overhead, this slide.\nDialogue: 0,1:07:48.03,1:07:51.71,EN,,0,0,0,,Consider the following sequence of procedures.\nDialogue: 0,1:07:56.40,1:07:57.79,EN,,0,0,0,,e0 over here\nDialogue: 0,1:07:59.24,1:08:01.63,EN,,0,0,0,,the procedure which does nothing at all.\nDialogue: 0,1:08:02.89,1:08:05.10,EN,,0,0,0,,It's the procedure which produces an error\nDialogue: 0,1:08:05.10,1:08:06.24,EN,,0,0,0,,for any arguments you give it.\nDialogue: 0,1:08:07.78,1:08:09.03,EN,,0,0,0,,It's basically useless.\nDialogue: 0,1:08:14.48,1:08:20.08,EN,,0,0,0,,Well, however, I can make an approximation.\nDialogue: 0,1:08:20.08,1:08:23.93,EN,,0,0,0,,Let's consider it the worst possible approximation to exponentiation,\nDialogue: 0,1:08:24.73,1:08:25.53,EN,,0,0,0,,because it does nothing.\nDialogue: 0,1:08:26.99,1:08:29.68,EN,,0,0,0,,Well, supposing I substituted e0\nDialogue: 0,1:08:30.35,1:08:33.26,EN,,0,0,0,,for g by calling f,\nDialogue: 0,1:08:33.79,1:08:36.30,EN,,0,0,0,,as you see over here on e0.\nDialogue: 0,1:08:37.38,1:08:39.77,EN,,0,0,0,,So you see over here, have e0 there.\nDialogue: 0,1:08:40.84,1:08:42.35,EN,,0,0,0,,Then gee, what's e1?\nDialogue: 0,1:08:43.63,1:08:46.03,EN,,0,0,0,,e1 is a procedure which exponentiate things\nDialogue: 0,1:08:46.67,1:08:48.78,EN,,0,0,0,,to the 0th power, with no trouble.\nDialogue: 0,1:08:49.60,1:08:50.75,EN,,0,0,0,,It gets the right answer,\nDialogue: 0,1:08:51.05,1:08:52.35,EN,,0,0,0,,anything to the zero is one,\nDialogue: 0,1:08:52.68,1:08:54.25,EN,,0,0,0,,and it makes an error on anything else.\nDialogue: 0,1:08:57.39,1:09:01.56,EN,,0,0,0,,Well, now what if I take e1\nDialogue: 0,1:09:02.30,1:09:07.40,EN,,0,0,0,,and substituted it for g by calling f on e1?\nDialogue: 0,1:09:09.58,1:09:11.18,EN,,0,0,0,,Oh gosh,\nDialogue: 0,1:09:12.01,1:09:15.02,EN,,0,0,0,,I have here a procedure of two arguments.\nDialogue: 0,1:09:15.67,1:09:16.84,EN,,0,0,0,,Now remember e1\nDialogue: 0,1:09:16.96,1:09:19.66,EN,,0,0,0,,was appropriate for taking exponentiations of 0,\nDialogue: 0,1:09:21.47,1:09:23.37,EN,,0,0,0,,for raising to the 0 exponent.\nDialogue: 0,1:09:24.20,1:09:25.00,EN,,0,0,0,,So here,\nDialogue: 0,1:09:25.52,1:09:27.28,EN,,0,0,0,,if is n is 0, the result is one,\nDialogue: 0,1:09:27.29,1:09:28.67,EN,,0,0,0,,so this guy is good for that too.\nDialogue: 0,1:09:29.52,1:09:32.01,EN,,0,0,0,,However, I can use something for raising to the 0th power\nDialogue: 0,1:09:32.51,1:09:35.26,EN,,0,0,0,,to multiply it by x to raise something to the first power.\nDialogue: 0,1:09:35.97,1:09:39.67,EN,,0,0,0,,So e2 is good for both power 0 and 1.\nDialogue: 0,1:09:41.60,1:09:41.92,EN,,0,0,0,,OK?\nDialogue: 0,1:09:43.71,1:09:46.67,EN,,0,0,0,,And e3 is constructed from e2 in the same way.\nDialogue: 0,1:09:47.89,1:09:50.24,EN,,0,0,0,,And e3, of course, by the same argument\nDialogue: 0,1:09:50.32,1:09:53.37,EN,,0,0,0,,is good for powers 0, one, and two.\nDialogue: 0,1:09:55.12,1:09:55.40,EN,,0,0,0,,OK?\nDialogue: 0,1:09:56.09,1:09:59.08,EN,,0,0,0,,And so I will assert for you, without proof,\nDialogue: 0,1:09:59.66,1:10:01.72,EN,,0,0,0,,because the proof is horribly difficult.\nDialogue: 0,1:10:02.52,1:10:03.60,EN,,0,0,0,,And that's the sort of thing that\nDialogue: 0,1:10:03.63,1:10:06.36,EN,,0,0,0,,people called denotational semanticists do.\nDialogue: 0,1:10:06.59,1:10:07.64,EN,,0,0,0,,I suppose it was invented\nDialogue: 0,1:10:07.87,1:10:10.59,EN,,0,0,0,,This great idea was invented by Scott and Strachey.\nDialogue: 0,1:10:11.64,1:10:16.32,EN,,0,0,0,,Ah, sort of. They're very famous mathematician types\nDialogue: 0,1:10:16.86,1:10:21.21,EN,,0,0,0,,who invented the interpretation for these programs that we have\nDialogue: 0,1:10:22.36,1:10:24.00,EN,,0,0,0,,that I'm talking to you about right now.\nDialogue: 0,1:10:24.24,1:10:26.17,EN,,0,0,0,,And they proved, by topology\nDialogue: 0,1:10:27.04,1:10:29.32,EN,,0,0,0,,that there is such a fixed point\nDialogue: 0,1:10:29.82,1:10:31.26,EN,,0,0,0,,in the cases that we want.\nDialogue: 0,1:10:32.22,1:10:33.24,EN,,0,0,0,,But the assertion is\nDialogue: 0,1:10:33.40,1:10:44.24,EN,,0,0,0,,E-X-P-T is limit as n goes to infinity of em.\nDialogue: 0,1:10:45.52,1:10:47.90,EN,,0,0,0,,and And that we've constructed this by the following way.\nDialogue: 0,1:10:50.52,1:10:55.66,EN,,0,0,0,,--is Well, it's f of, f of, f of, f of, f of--\nDialogue: 0,1:10:57.61,1:11:00.19,EN,,0,0,0,,f applied to anything at all.\nDialogue: 0,1:11:01.12,1:11:02.46,EN,,0,0,0,,It didn't matter what that was,\nDialogue: 0,1:11:03.18,1:11:05.00,EN,,0,0,0,,because, in fact, this always produces an error.\nDialogue: 0,1:11:07.45,1:11:08.41,EN,,0,0,0,,Applied to this--\nDialogue: 0,1:11:12.89,1:11:14.48,EN,,0,0,0,,That's by infinite nesting of f's.\nDialogue: 0,1:11:16.38,1:11:17.71,EN,,0,0,0,,So now my problem\nDialogue: 0,1:11:18.22,1:11:19.76,EN,,0,0,0,,is to make some infinite things.\nDialogue: 0,1:11:22.59,1:11:24.08,EN,,0,0,0,,We need some infinite things.\nDialogue: 0,1:11:24.92,1:11:26.25,EN,,0,0,0,,How am I going to nest up an f\nDialogue: 0,1:11:26.56,1:11:27.80,EN,,0,0,0,,an infinite number of times?\nDialogue: 0,1:11:28.98,1:11:30.12,EN,,0,0,0,,I'd better construct this.\nDialogue: 0,1:11:32.38,1:11:32.93,EN,,0,0,0,,Well, I don't know.\nDialogue: 0,1:11:32.93,1:11:34.32,EN,,0,0,0,,How would I make an infinite loop at all?\nDialogue: 0,1:11:34.81,1:11:36.32,EN,,0,0,0,,Let's take a very simple infinite loop,\nDialogue: 0,1:11:36.57,1:11:38.34,EN,,0,0,0,,the simplest infinite loop imaginable.\nDialogue: 0,1:11:43.55,1:11:47.55,EN,,0,0,0,,If I were to take that procedure of one argument x\nDialogue: 0,1:11:48.00,1:11:49.79,EN,,0,0,0,,which applies x to x\nDialogue: 0,1:11:53.55,1:11:53.92,EN,,0,0,0,,OK?\nDialogue: 0,1:11:55.05,1:11:58.41,EN,,0,0,0,,and apply that to the procedure of one argument x\nDialogue: 0,1:11:59.36,1:12:01.05,EN,,0,0,0,,which applies x to x,\nDialogue: 0,1:12:04.83,1:12:06.00,EN,,0,0,0,,then this is an infinite loop.\nDialogue: 0,1:12:07.21,1:12:09.31,EN,,0,0,0,,The reason why this is an infinite loop is as follows.\nDialogue: 0,1:12:09.98,1:12:11.31,EN,,0,0,0,,The way I understand this\nDialogue: 0,1:12:11.52,1:12:13.69,EN,,0,0,0,,is I substitute the argument\nDialogue: 0,1:12:14.22,1:12:16.59,EN,,0,0,0,,for the formal parameter in the body.\nDialogue: 0,1:12:18.85,1:12:21.60,EN,,0,0,0,,But if I do that, I take for each of these x's,\nDialogue: 0,1:12:22.40,1:12:23.76,EN,,0,0,0,,I substitute one of these,\nDialogue: 0,1:12:24.36,1:12:26.96,EN,,0,0,0,,making a copy of the original expression I just started with,\nDialogue: 0,1:12:28.35,1:12:29.37,EN,,0,0,0,,the simplest infinite loop.\nDialogue: 0,1:12:35.44,1:12:39.29,EN,,0,0,0,,Now I want to tell you about a particular operator\nDialogue: 0,1:12:40.38,1:12:43.09,EN,,0,0,0,,which is constructed by a perturbation from this infinite loop.\nDialogue: 0,1:12:46.96,1:12:47.92,EN,,0,0,0,,I'll call it y.\nDialogue: 0,1:12:50.89,1:12:55.82,EN,,0,0,0,,OK y -- This is called Curry's Paradoxical Combinator of y\nDialogue: 0,1:12:56.62,1:12:58.99,EN,,0,0,0,,after a fellow by the name of Curry,\nDialogue: 0,1:12:59.34,1:13:01.85,EN,,0,0,0,,who was a logician of the 1930s also.\nDialogue: 0,1:13:04.48,1:13:06.88,EN,,0,0,0,,And if I have a procedure of one argument f,\nDialogue: 0,1:13:08.17,1:13:09.33,EN,,0,0,0,,what's it going to have in it?\nDialogue: 0,1:13:09.33,1:13:11.20,EN,,0,0,0,,It's going to have a kind of infinite loop in it,\nDialogue: 0,1:13:11.98,1:13:15.47,EN,,0,0,0,,which is that procedure of one argument x\nDialogue: 0,1:13:15.95,1:13:18.80,EN,,0,0,0,,which applies f to x of x,\nDialogue: 0,1:13:21.63,1:13:24.75,EN,,0,0,0,,applied to that procedure of one argument x,\nDialogue: 0,1:13:25.10,1:13:27.34,EN,,0,0,0,,which applies f to f of x.\nDialogue: 0,1:13:32.30,1:13:33.13,EN,,0,0,0,,Now what's this do?\nDialogue: 0,1:13:34.80,1:13:36.06,EN,,0,0,0,,Suppose we apply y to F.\nDialogue: 0,1:13:41.31,1:13:42.57,EN,,0,0,0,,OK? Well, that's easy enough.\nDialogue: 0,1:13:43.15,1:13:44.62,EN,,0,0,0,,That's this capital F over here.\nDialogue: 0,1:13:46.91,1:13:48.16,EN,,0,0,0,,Well, the easiest thing to say there\nDialogue: 0,1:13:48.30,1:13:49.92,EN,,0,0,0,,is, I substitute F for here.\nDialogue: 0,1:13:55.32,1:13:57.07,EN,,0,0,0,,So that's going to give me, basically--\nDialogue: 0,1:13:58.75,1:14:00.84,EN,,0,0,0,,because then I'm going to substitute this\nDialogue: 0,1:14:01.45,1:14:02.80,EN,,0,0,0,,for x in here.\nDialogue: 0,1:14:04.17,1:14:05.23,EN,,0,0,0,,That F of\nDialogue: 0,1:14:08.97,1:14:10.09,EN,,0,0,0,,Let me actually do it in steps,\nDialogue: 0,1:14:10.22,1:14:11.45,EN,,0,0,0,,so you can see it completely.\nDialogue: 0,1:14:11.92,1:14:14.27,EN,,0,0,0,,I'm going to be very careful. OK?\nDialogue: 0,1:14:15.02,1:14:18.25,EN,,0,0,0,,This is open, open, lambda of x ,\nDialogue: 0,1:14:19.08,1:14:22.11,EN,,0,0,0,,capital F, x, x,\nDialogue: 0,1:14:26.88,1:14:35.55,EN,,0,0,0,,applied to itself, F of x of x.\nDialogue: 0,1:14:37.91,1:14:39.66,EN,,0,0,0,,Substituting this for this in here,\nDialogue: 0,1:14:40.06,1:14:40.91,EN,,0,0,0,,this is\nDialogue: 0,1:14:43.13,1:14:48.35,EN,,0,0,0,,F applied to-- what is it-- substituting this in here\nDialogue: 0,1:14:48.65,1:14:54.81,EN,,0,0,0,,open, open, lambda of x, F, of x and x,\nDialogue: 0,1:14:57.07,1:14:58.17,EN,,0,0,0,,applied to\nDialogue: 0,1:14:59.18,1:15:06.48,EN,,0,0,0,,lambda of x, F of x of x, F,\nDialogue: 0,1:15:06.99,1:15:10.44,EN,,0,0,0,,lambda, pair, F.\nDialogue: 0,1:15:11.51,1:15:12.40,EN,,0,0,0,,Oh, but what is this?\nDialogue: 0,1:15:13.42,1:15:16.35,EN,,0,0,0,,This thing over here that I just computed,\nDialogue: 0,1:15:17.13,1:15:18.56,EN,,0,0,0,,is this thing over here.\nDialogue: 0,1:15:20.19,1:15:21.84,EN,,0,0,0,,But I just wrapped another F around it.\nDialogue: 0,1:15:23.37,1:15:24.67,EN,,0,0,0,,So by applying y to F,\nDialogue: 0,1:15:24.68,1:15:26.22,EN,,0,0,0,,I make an infinite series of F's.\nDialogue: 0,1:15:27.85,1:15:29.45,EN,,0,0,0,,If I just let this run forever,\nDialogue: 0,1:15:29.69,1:15:31.77,EN,,0,0,0,,I'll just keep making more and more F's outside.\nDialogue: 0,1:15:33.17,1:15:34.80,EN,,0,0,0,,I ran an infinite loop which is useless,\nDialogue: 0,1:15:35.20,1:15:37.02,EN,,0,0,0,,but it doesn't matter that the inside is useless.\nDialogue: 0,1:15:39.85,1:15:47.85,EN,,0,0,0,,OK? So y of F is F applied to y of F.\nDialogue: 0,1:15:50.33,1:15:52.14,EN,,0,0,0,,So y is a magical thing\nDialogue: 0,1:15:53.85,1:15:56.25,EN,,0,0,0,,which, when applied to some function,\nDialogue: 0,1:15:57.37,1:16:00.38,EN,,0,0,0,,produces the object which is the fixed point of that function,\nDialogue: 0,1:16:01.69,1:16:04.25,EN,,0,0,0,,if it exists, and if this all works.\nDialogue: 0,1:16:07.91,1:16:10.08,EN,,0,0,0,,Because, indeed, if I take y of F\nDialogue: 0,1:16:10.12,1:16:11.12,EN,,0,0,0,,I get y of F out.\nDialogue: 0,1:16:16.24,1:16:18.86,EN,,0,0,0,,Now I want you to think this in terms of\nDialogue: 0,1:16:19.85,1:16:22.38,EN,,0,0,0,,the eval-apply interpreter for a bit.\nDialogue: 0,1:16:23.86,1:16:26.27,EN,,0,0,0,,I wrote down a whole bunch of recursion equations out there.\nDialogue: 0,1:16:28.54,1:16:30.22,EN,,0,0,0,,They're simultaneous in the same way\nDialogue: 0,1:16:30.22,1:16:31.23,EN,,0,0,0,,these are simultaneous equations.\nDialogue: 0,1:16:31.47,1:16:33.31,EN,,0,0,0,,Exponentiation was not a simultaneous equation.\nDialogue: 0,1:16:33.31,1:16:35.79,EN,,0,0,0,,It was only one variable I was looking for a meaning for.\nDialogue: 0,1:16:38.15,1:16:40.76,EN,,0,0,0,,But what Lisp is is the fixed point of the process\nDialogue: 0,1:16:40.81,1:16:42.57,EN,,0,0,0,,that's which says, if I knew what Lisp was\nDialogue: 0,1:16:42.59,1:16:46.51,EN,,0,0,0,,and substituted it in for eval, and apply, and so on,\nDialogue: 0,1:16:46.59,1:16:49.79,EN,,0,0,0,,on the right hand sides of all those recursion equations,\nDialogue: 0,1:16:50.94,1:16:53.96,EN,,0,0,0,,then if it was a real good Lisp, is a real one,\nDialogue: 0,1:16:54.36,1:16:56.30,EN,,0,0,0,,then the left hand side would also be Lisp.\nDialogue: 0,1:16:58.22,1:16:59.82,EN,,0,0,0,,So I made sense of that definition.\nDialogue: 0,1:17:02.42,1:17:05.41,EN,,0,0,0,,Now whether or not there's an answer isn't so obvious.\nDialogue: 0,1:17:05.69,1:17:06.75,EN,,0,0,0,,I can't attack that.\nDialogue: 0,1:17:07.74,1:17:09.21,EN,,0,0,0,,Now these arguments that I'm giving you now\nDialogue: 0,1:17:09.26,1:17:10.27,EN,,0,0,0,,are quite dangerous.\nDialogue: 0,1:17:10.66,1:17:11.64,EN,,0,0,0,,Let's look over here.\nDialogue: 0,1:17:13.05,1:17:14.61,EN,,0,0,0,,On the. These are limit arguments.\nDialogue: 0,1:17:14.61,1:17:15.39,EN,,0,0,0,,We're talking about limits,\nDialogue: 0,1:17:15.45,1:17:17.68,EN,,0,0,0,,and it's really calculus, or topology,\nDialogue: 0,1:17:17.87,1:17:20.03,EN,,0,0,0,,or something like that, a kind of analysis.\nDialogue: 0,1:17:20.76,1:17:23.38,EN,,0,0,0,,OK？Now here's an argument that you all believe.\nDialogue: 0,1:17:23.38,1:17:25.29,EN,,0,0,0,,And I want to make sure you realize\nDialogue: 0,1:17:25.42,1:17:27.66,EN,,0,0,0,,that I could be bullshitting you.\nDialogue: 0,1:17:28.86,1:17:30.48,EN,,0,0,0,,Alright? What is this?\nDialogue: 0,1:17:34.25,1:17:39.52,EN,,0,0,0,,u is the sum of 1/2, 1/4, and 1/8, and so on,\nDialogue: 0,1:17:39.74,1:17:41.32,EN,,0,0,0,,the sum of a geometric series.\nDialogue: 0,1:17:42.82,1:17:44.68,EN,,0,0,0,,And, of course, I could play a game here.\nDialogue: 0,1:17:44.82,1:17:47.57,EN,,0,0,0,,u minus one is 1/2, plus 1/4, plus 1/8, and so on.\nDialogue: 0,1:17:51.90,1:17:54.46,EN,,0,0,0,,But now if I multiple. What I could do here--\nDialogue: 0,1:17:56.09,1:17:57.93,EN,,0,0,0,,Ooops. There is a parentheses error here.\nDialogue: 0,1:17:58.92,1:18:01.45,EN,,0,0,0,,But I can put here two times u minus one\nDialogue: 0,1:18:01.74,1:18:03.99,EN,,0,0,0,,is one plus 1/2, plus 1/4, plus 1/8.\nDialogue: 0,1:18:07.57,1:18:08.54,EN,,0,0,0,,Can I fix that?\nDialogue: 0,1:18:14.01,1:18:16.43,EN,,0,0,0,,Yes, well.\nDialogue: 0,1:18:18.19,1:18:18.65,EN,,0,0,0,,OK?\nDialogue: 0,1:18:19.52,1:18:20.64,EN,,0,0,0,,But that gives me back\nDialogue: 0,1:18:23.53,1:18:26.64,EN,,0,0,0,,two times u minus one is u,\nDialogue: 0,1:18:27.80,1:18:29.58,EN,,0,0,0,,therefore, we conclude that u is two.\nDialogue: 0,1:18:30.30,1:18:31.37,EN,,0,0,0,,And this actually is true.\nDialogue: 0,1:18:31.96,1:18:33.32,EN,,0,0,0,,There's no problem like that.\nDialogue: 0,1:18:34.04,1:18:37.55,EN,,0,0,0,,But supposing I did something different.\nDialogue: 0,1:18:38.54,1:18:39.48,EN,,0,0,0,,Supposing I start up with something\nDialogue: 0,1:18:39.50,1:18:41.20,EN,,0,0,0,,which manifestly has no sum.\nDialogue: 0,1:18:41.56,1:18:46.99,EN,,0,0,0,,v is one, plus two, plus four, plus 8, plus dot, dot, dot. OK?\nDialogue: 0,1:18:47.39,1:18:51.39,EN,,0,0,0,,Well, v minus one is surely two, plus four, plus eight, plus dot, dot, dot. Right?\nDialogue: 0,1:18:52.27,1:18:56.03,EN,,0,0,0,,v minus one over two, gee, that looks like v again.\nDialogue: 0,1:18:57.41,1:19:00.54,EN,,0,0,0,,From that I should be able to conclude that--\nDialogue: 0,1:19:01.37,1:19:02.91,EN,,0,0,0,,that's also wrong, apparently.\nDialogue: 0,1:19:03.07,1:19:04.51,EN,,0,0,0,,v equals minus one.\nDialogue: 0,1:19:12.45,1:19:13.82,EN,,0,0,0,,That should be a minus one.\nDialogue: 0,1:19:15.28,1:19:16.91,EN,,0,0,0,,And that's certainly a false conclusion.\nDialogue: 0,1:19:22.00,1:19:23.47,EN,,0,0,0,,So when you play with limits,\nDialogue: 0,1:19:24.22,1:19:27.85,EN,,0,0,0,,arguments that may work in one case\nDialogue: 0,1:19:29.42,1:19:30.75,EN,,0,0,0,,they may not work in some other case.\nDialogue: 0,1:19:30.75,1:19:31.69,EN,,0,0,0,,You have to be very careful.\nDialogue: 0,1:19:32.24,1:19:33.87,EN,,0,0,0,,The arguments have to be well-formed.\nDialogue: 0,1:19:36.14,1:19:39.23,EN,,0,0,0,,And I don't know, in general,\nDialogue: 0,1:19:39.85,1:19:41.93,EN,,0,0,0,,what the story is about arguments like this.\nDialogue: 0,1:19:43.27,1:19:45.24,EN,,0,0,0,,We can read a pile of topology and find out.\nDialogue: 0,1:19:46.27,1:19:48.64,EN,,0,0,0,,But, surely, at least you understand now,\nDialogue: 0,1:19:49.10,1:19:51.13,EN,,0,0,0,,why it might be some meaning\nDialogue: 0,1:19:51.15,1:19:52.76,EN,,0,0,0,,to the things we've been writing on the blackboard.\nDialogue: 0,1:19:53.66,1:19:55.61,EN,,0,0,0,,And you understand what that might mean.\nDialogue: 0,1:19:56.48,1:19:58.35,EN,,0,0,0,,So, I suppose, it's almost about time\nDialogue: 0,1:19:59.07,1:20:03.84,EN,,0,0,0,,for you to merit being made a member\nDialogue: 0,1:20:04.28,1:20:05.55,EN,,0,0,0,,of the grand recursive order\nDialogue: 0,1:20:05.56,1:20:07.04,EN,,0,0,0,,of lambda calculus hackers.\nDialogue: 0,1:20:08.84,1:20:10.17,EN,,0,0,0,,I would. This is the badge.\nDialogue: 0,1:20:10.82,1:20:12.54,EN,,0,0,0,,Because you now understand, for example,\nDialogue: 0,1:20:13.40,1:20:15.20,EN,,0,0,0,,what it says at the very top,\nDialogue: 0,1:20:16.89,1:20:18.41,EN,,0,0,0,,y F equals F y F.\nDialogue: 0,1:20:21.04,1:20:21.66,EN,,0,0,0,,Thank you.\nDialogue: 0,1:20:21.85,1:20:22.75,EN,,0,0,0,,Are there any questions?\nDialogue: 0,1:20:24.71,1:20:25.15,EN,,0,0,0,,Yes, Lev.\nDialogue: 0,1:20:25.37,1:20:27.39,EN,,0,0,0,,AUDIENCE: With this, it seems that\nDialogue: 0,1:20:27.40,1:20:30.22,EN,,0,0,0,,there's no need to define, as you imply,\nDialogue: 0,1:20:30.24,1:20:32.70,EN,,0,0,0,,to just remember a value, to apply it later.\nDialogue: 0,1:20:32.99,1:20:33.32,EN,,0,0,0,,PROFESSOR: Yeah.\nDialogue: 0,1:20:33.50,1:20:36.44,EN,,0,0,0,,AUDIENCE: Defines were kind of a side-effect it seemed in the language.\nDialogue: 0,1:20:36.49,1:20:38.52,EN,,0,0,0,,[INTERPOSING] are order dependent.\nDialogue: 0,1:20:39.30,1:20:42.06,EN,,0,0,0,,Does this eliminate the side-effect from the.\nDialogue: 0,1:20:42.28,1:20:44.68,EN,,0,0,0,,PROFESSOR: Well. The answer is,\nDialogue: 0,1:20:44.88,1:20:46.44,EN,,0,0,0,,this is not the way these things were implemented.\nDialogue: 0,1:20:47.52,1:20:47.93,EN,,0,0,0,,OK?\nDialogue: 0,1:20:48.92,1:20:53.15,EN,,0,0,0,,Define, indeed is implemented as an operation\nDialogue: 0,1:20:53.18,1:20:55.53,EN,,0,0,0,,that actually modifies an environment structure,\nDialogue: 0,1:20:57.95,1:21:02.33,EN,,0,0,0,,changes the frame that the define is executed in.\nDialogue: 0,1:21:03.69,1:21:06.51,EN,,0,0,0,,And there are many reasons for that,\nDialogue: 0,1:21:07.39,1:21:08.64,EN,,0,0,0,,but a lot of this has to do with\nDialogue: 0,1:21:08.67,1:21:10.09,EN,,0,0,0,,making an interactive system.\nDialogue: 0,1:21:11.34,1:21:14.12,EN,,0,0,0,,What this is saying is that if you've made a system,\nDialogue: 0,1:21:14.35,1:21:15.20,EN,,0,0,0,,and you know\nDialogue: 0,1:21:15.42,1:21:16.60,EN,,0,0,0,,and you know you're not going to do any debugging\nDialogue: 0,1:21:16.60,1:21:17.55,EN,,0,0,0,,or anything like that,\nDialogue: 0,1:21:17.84,1:21:20.72,EN,,0,0,0,,and you know everything there is all at once,\nDialogue: 0,1:21:20.75,1:21:21.24,EN,,0,0,0,,and you want to say,\nDialogue: 0,1:21:21.26,1:21:23.12,EN,,0,0,0,,what is the meaning of a final set of equations?\nDialogue: 0,1:21:24.09,1:21:25.26,EN,,0,0,0,,This gives you a meaning for it.\nDialogue: 0,1:21:25.79,1:21:27.45,EN,,0,0,0,,But in order to make an interactive system,\nDialogue: 0,1:21:27.45,1:21:28.75,EN,,0,0,0,,where you can change the meaning of one\nDialogue: 0,1:21:28.76,1:21:31.68,EN,,0,0,0,,without changing everything else, incrementally,\nDialogue: 0,1:21:32.33,1:21:35.04,EN,,0,0,0,,you can't do that by implementing it this way.\nDialogue: 0,1:21:40.99,1:21:41.24,EN,,0,0,0,,Yes.\nDialogue: 0,1:21:42.30,1:21:44.25,EN,,0,0,0,,AUDIENCE: Another question on your danger slide.\nDialogue: 0,1:21:44.65,1:21:47.13,EN,,0,0,0,,It seemed that the two examples that you gave\nDialogue: 0,1:21:47.16,1:21:49.07,EN,,0,0,0,,had to do with convergence and non-convergence?\nDialogue: 0,1:21:49.18,1:21:49.56,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,1:21:50.30,1:21:52.62,EN,,0,0,0,,AUDIENCE: And that may or may not have something to do with\nDialogue: 0,1:21:52.76,1:21:54.68,EN,,0,0,0,,with function theory in a way which\nDialogue: 0,1:21:54.72,1:21:56.60,EN,,0,0,0,,would lead you to think of it in terms of linear systems,\nDialogue: 0,1:21:57.74,1:21:59.00,EN,,0,0,0,,or non-linear systems.\nDialogue: 0,1:21:59.34,1:22:01.76,EN,,0,0,0,,How does this convergence relate to being able to\nDialogue: 0,1:22:02.35,1:22:05.53,EN,,0,0,0,,see a priori what properties of that might be violated?\nDialogue: 0,1:22:05.79,1:22:06.57,EN,,0,0,0,,PROFESSOR: I don't know.\nDialogue: 0,1:22:07.68,1:22:10.09,EN,,0,0,0,,The answer is, I don't know under what circumstances.\nDialogue: 0,1:22:10.61,1:22:12.04,EN,,0,0,0,,I don't know how to translate that\nDialogue: 0,1:22:12.52,1:22:14.73,EN,,0,0,0,,into less than an hour of talk more.\nDialogue: 0,1:22:16.91,1:22:18.48,EN,,0,0,0,,What are the conditions under which,\nDialogue: 0,1:22:18.86,1:22:20.76,EN,,0,0,0,,for which we know that these things converge?\nDialogue: 0,1:22:22.86,1:22:23.31,EN,,0,0,0,,And indeed,\nDialogue: 0,1:22:23.32,1:22:26.35,EN,,0,0,0,,all that was telling you that arguments that are based on convergence\nDialogue: 0,1:22:28.24,1:22:29.47,EN,,0,0,0,,are flaky\nDialogue: 0,1:22:29.66,1:22:31.58,EN,,0,0,0,,if you don't know the convergence beforehand.\nDialogue: 0,1:22:32.81,1:22:34.20,EN,,0,0,0,,You can make wrong arguments.\nDialogue: 0,1:22:34.44,1:22:37.31,EN,,0,0,0,,You can make deductions, as if you know the answer,\nDialogue: 0,1:22:37.39,1:22:39.93,EN,,0,0,0,,and not be stopped somewhere by some obvious contradiction.\nDialogue: 0,1:22:40.97,1:22:42.28,EN,,0,0,0,,AUDIENCE: So can we say then that\nDialogue: 0,1:22:42.33,1:22:44.88,EN,,0,0,0,,if F is a convergent mathematical expression,\nDialogue: 0,1:22:45.00,1:22:47.36,EN,,0,0,0,,then the recursion property can be--\nDialogue: 0,1:22:47.58,1:22:51.29,EN,,0,0,0,,PROFESSOR: Well, I think there's a technical kind of F,\nDialogue: 0,1:22:52.12,1:22:54.22,EN,,0,0,0,,OK? There is a technical description\nDialogue: 0,1:22:54.24,1:22:55.90,EN,,0,0,0,,of those F's that have the property\nDialogue: 0,1:22:55.98,1:23:01.31,EN,,0,0,0,,that when you iteratively apply them like this,\nDialogue: 0,1:23:01.52,1:23:02.25,EN,,0,0,0,,you converge.\nDialogue: 0,1:23:03.02,1:23:06.51,EN,,0,0,0,,Things that are monotonic, and continuous,\nDialogue: 0,1:23:07.32,1:23:07.95,EN,,0,0,0,,OK?\nDialogue: 0,1:23:08.38,1:23:09.37,EN,,0,0,0,,and I forgot what else.\nDialogue: 0,1:23:09.37,1:23:11.13,EN,,0,0,0,,There is a whole bunch of little conditions like that\nDialogue: 0,1:23:11.68,1:23:12.99,EN,,0,0,0,,which have this property.\nDialogue: 0,1:23:13.43,1:23:16.00,EN,,0,0,0,,Now the real problem is deducing from looking at the F,\nDialogue: 0,1:23:16.92,1:23:17.88,EN,,0,0,0,,its definition here,\nDialogue: 0,1:23:18.17,1:23:19.66,EN,,0,0,0,,whether not it has those properties,\nDialogue: 0,1:23:20.27,1:23:21.32,EN,,0,0,0,,and that's very hard.\nDialogue: 0,1:23:22.01,1:23:24.00,EN,,0,0,0,,The properties are easy. You can write them down.\nDialogue: 0,1:23:24.58,1:23:26.32,EN,,0,0,0,,You can look in a book by Joe Stoy.\nDialogue: 0,1:23:26.67,1:23:29.58,EN,,0,0,0,,It's a great book-- Stoy.\nDialogue: 0,1:23:32.22,1:23:34.06,EN,,0,0,0,,It's called, The Scott-Strachey\nDialogue: 0,1:23:34.49,1:23:38.46,EN,,0,0,0,,The Scott-Strachey Method of Denotational Semantics,\nDialogue: 0,1:23:39.55,1:23:40.76,EN,,0,0,0,,and it's by Joe Stoy,\nDialogue: 0,1:23:40.80,1:23:41.76,EN,,0,0,0,,MIT Press.\nDialogue: 0,1:23:48.06,1:23:49.88,EN,,0,0,0,,And he works out all this in great detail,\nDialogue: 0,1:23:50.20,1:23:51.37,EN,,0,0,0,,enough to horrify you.\nDialogue: 0,1:23:55.05,1:23:56.19,EN,,0,0,0,,But it really is readable.\nDialogue: 0,1:24:09.15,1:24:10.08,EN,,0,0,0,,OK, well, thank you.\nDialogue: 0,1:24:11.49,1:24:12.99,EN,,0,0,0,,Time for the bigger break, I suppose.\nDialogue: 0,1:24:14.17,1:24:20.92,EN,,0,0,0,,http://ocw.mit.edu\nDialogue: 0,1:24:20.92,1:24:34.49,EN,,0,0,0,,https://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec7b.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 3\nVideo Position: 790\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:17.21,0:00:17.96,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:00:19.52,0:00:21.29,EN,,0,0,0,,What we did so far was a lot of fun,\nDialogue: 0,0:00:21.52,0:00:23.05,EN,,0,0,0,,was it useful for anything?\nDialogue: 0,0:00:26.33,0:00:27.96,EN,,0,0,0,,I suppose the answer is going to be yes.\nDialogue: 0,0:00:29.38,0:00:31.92,EN,,0,0,0,,If these metacircular interpreters\nDialogue: 0,0:00:32.96,0:00:34.60,EN,,0,0,0,,are a valuable thing to play with.\nDialogue: 0,0:00:34.62,0:00:36.17,EN,,0,0,0,,I spend, say\nDialogue: 0,0:00:38.05,0:00:41.85,EN,,0,0,0,,there have been times I spend 50% of my time, over a year,\nDialogue: 0,0:00:42.86,0:00:45.26,EN,,0,0,0,,trying various design alternatives\nDialogue: 0,0:00:45.76,0:00:48.19,EN,,0,0,0,,by experimenting with them with metacircular interpreters--\nDialogue: 0,0:00:49.47,0:00:52.01,EN,,0,0,0,,metacircular interpreters like the sort you just saw.\nDialogue: 0,0:00:52.57,0:00:54.11,EN,,0,0,0,,Metacircular is because\nDialogue: 0,0:00:54.72,0:00:56.94,EN,,0,0,0,,they are defined in terms of themselves in such a way\nDialogue: 0,0:00:56.97,0:00:59.71,EN,,0,0,0,,that the language they interpret contains itself.\nDialogue: 0,0:01:01.27,0:01:03.87,EN,,0,0,0,,Such interpreters are a convenient medium\nDialogue: 0,0:01:03.88,0:01:05.58,EN,,0,0,0,,for exploring language issues.\nDialogue: 0,0:01:06.80,0:01:09.44,EN,,0,0,0,,If you want to try adding a new feature,\nDialogue: 0,0:01:10.51,0:01:12.38,EN,,0,0,0,,it's sort of a snap, it's easy,\nDialogue: 0,0:01:12.73,0:01:15.10,EN,,0,0,0,,you just do it and see what happens.\nDialogue: 0,0:01:15.49,0:01:17.20,EN,,0,0,0,,You play with that language for a while you say,\nDialogue: 0,0:01:17.24,0:01:18.24,EN,,0,0,0,,gee, I'm didn't like that,\nDialogue: 0,0:01:18.52,0:01:19.47,EN,,0,0,0,,you throw it away.\nDialogue: 0,0:01:20.96,0:01:23.55,EN,,0,0,0,,Or you might want to see what\nDialogue: 0,0:01:23.64,0:01:27.37,EN,,0,0,0,,the difference is if you'd make a slight difference in the binding strategy,\nDialogue: 0,0:01:28.81,0:01:31.90,EN,,0,0,0,,or some more complicated things that might occur.\nDialogue: 0,0:01:33.72,0:01:35.48,EN,,0,0,0,,In fact, these metacircular interpreters\nDialogue: 0,0:01:36.17,0:01:37.88,EN,,0,0,0,,are an excellent medium for people\nDialogue: 0,0:01:38.20,0:01:42.56,EN,,0,0,0,,exchanging ideas about language design,\nDialogue: 0,0:01:43.98,0:01:45.74,EN,,0,0,0,,because they're pretty easy to understand,\nDialogue: 0,0:01:46.28,0:01:48.46,EN,,0,0,0,,and they're short, and compact, and simple.\nDialogue: 0,0:01:49.32,0:01:50.80,EN,,0,0,0,,If I have some idea\nDialogue: 0,0:01:51.53,0:01:53.77,EN,,0,0,0,,that I want somebody to criticize\nDialogue: 0,0:01:54.25,0:01:58.32,EN,,0,0,0,,like say, Dan Friedman at Indiana,\nDialogue: 0,0:01:59.05,0:02:02.00,EN,,0,0,0,,I'd write a little metacircular interpreter\nDialogue: 0,0:02:02.56,0:02:03.79,EN,,0,0,0,,send him some network mail\nDialogue: 0,0:02:04.65,0:02:05.45,EN,,0,0,0,,with this interpreter in it.\nDialogue: 0,0:02:05.45,0:02:07.90,EN,,0,0,0,,He could whip it up on his machine and play with it\nDialogue: 0,0:02:07.92,0:02:09.82,EN,,0,0,0,,and say, that's no good.\nDialogue: 0,0:02:11.94,0:02:13.10,EN,,0,0,0,,And then send it back to me and say,\nDialogue: 0,0:02:13.13,0:02:14.83,EN,,0,0,0,,well, why don't you try this one, it's a little better.\nDialogue: 0,0:02:16.88,0:02:19.36,EN,,0,0,0,,So I want to show you some of that technology.\nDialogue: 0,0:02:20.16,0:02:24.20,EN,,0,0,0,,See, because, really, it's the essential, simple technology\nDialogue: 0,0:02:24.72,0:02:28.68,EN,,0,0,0,,for getting started in designing your own languages for particular purposes.\nDialogue: 0,0:02:30.79,0:02:32.08,EN,,0,0,0,,Let's start by adding\nDialogue: 0,0:02:32.51,0:02:34.21,EN,,0,0,0,,a very simple feature to a Lisp.\nDialogue: 0,0:02:40.64,0:02:44.37,EN,,0,0,0,,Now, one thing I want to tell you about is features, before I start.\nDialogue: 0,0:02:49.56,0:02:52.17,EN,,0,0,0,,There are many languages that have made a mess of themselves\nDialogue: 0,0:02:53.05,0:02:54.91,EN,,0,0,0,,by adding huge numbers of features.\nDialogue: 0,0:02:56.86,0:02:58.38,EN,,0,0,0,,Computer scientists have a joke\nDialogue: 0,0:02:59.28,0:03:02.52,EN,,0,0,0,,about bugs that transform it to features all the time.\nDialogue: 0,0:03:05.03,0:03:06.46,EN,,0,0,0,,But I like to think of it is that\nDialogue: 0,0:03:08.91,0:03:11.44,EN,,0,0,0,,many systems suffer from what's called creeping featurism.\nDialogue: 0,0:03:12.82,0:03:13.44,EN,,0,0,0,,Which is that\nDialogue: 0,0:03:14.94,0:03:18.16,EN,,0,0,0,,George has a pet feature he'd like in the system,\nDialogue: 0,0:03:18.72,0:03:19.36,EN,,0,0,0,,so he adds it.\nDialogue: 0,0:03:20.17,0:03:22.14,EN,,0,0,0,,And then Harry says, go says\nDialogue: 0,0:03:22.17,0:03:24.20,EN,,0,0,0,,gee, this system is no longer what exactly I like,\nDialogue: 0,0:03:24.24,0:03:25.92,EN,,0,0,0,,so I'm going to add my favorite feature.\nDialogue: 0,0:03:26.64,0:03:30.24,EN,,0,0,0,,And then Jim adds his favorite feature.\nDialogue: 0,0:03:30.83,0:03:31.79,EN,,0,0,0,,And, after a while,\nDialogue: 0,0:03:31.80,0:03:34.81,EN,,0,0,0,,the thing has a manual 500 pages long\nDialogue: 0,0:03:35.15,0:03:36.51,EN,,0,0,0,,that no one can understand.\nDialogue: 0,0:03:37.79,0:03:39.32,EN,,0,0,0,,And sometimes it's the same person\nDialogue: 0,0:03:39.90,0:03:41.37,EN,,0,0,0,,who writes all of these features\nDialogue: 0,0:03:41.39,0:03:43.23,EN,,0,0,0,,and produces this terribly complicated thing.\nDialogue: 0,0:03:44.14,0:03:46.09,EN,,0,0,0,,In some cases, like editors,\nDialogue: 0,0:03:47.37,0:03:49.12,EN,,0,0,0,,it's sort of reasonable to have lots of features,\nDialogue: 0,0:03:50.92,0:03:52.65,EN,,0,0,0,,because there are a lot of things you want to be able to do\nDialogue: 0,0:03:52.68,0:03:53.76,EN,,0,0,0,,and many of them arbitrary.\nDialogue: 0,0:03:56.11,0:03:57.29,EN,,0,0,0,,But in computer languages,\nDialogue: 0,0:03:57.85,0:03:58.91,EN,,0,0,0,,I think it's a disaster\nDialogue: 0,0:04:00.01,0:04:01.29,EN,,0,0,0,,to have too much stuff in them.\nDialogue: 0,0:04:04.03,0:04:08.00,EN,,0,0,0,,The other alternative you get into is something called feeping creaturism,\nDialogue: 0,0:04:09.52,0:04:11.39,EN,,0,0,0,,which is where you have a box\nDialogue: 0,0:04:11.80,0:04:15.29,EN,,0,0,0,,which has a display, a fancy display, and a mouse,\nDialogue: 0,0:04:15.95,0:04:20.04,EN,,0,0,0,,and there is all sorts of complexity associated with all this fancy IO.\nDialogue: 0,0:04:21.01,0:04:22.80,EN,,0,0,0,,And your computer language becomes\nDialogue: 0,0:04:23.34,0:04:25.37,EN,,0,0,0,,a dismal, little, tiny thing that barely works\nDialogue: 0,0:04:25.40,0:04:27.90,EN,,0,0,0,,because of all the swapping, and disk twitching, and so on,\nDialogue: 0,0:04:28.09,0:04:29.36,EN,,0,0,0,,caused by your Window system.\nDialogue: 0,0:04:30.08,0:04:31.82,EN,,0,0,0,,And every time you go near the computer,\nDialogue: 0,0:04:31.93,0:04:33.45,EN,,0,0,0,,the mouse process wakes up and says,\nDialogue: 0,0:04:33.85,0:04:35.95,EN,,0,0,0,,gee do you have something for me to do,\nDialogue: 0,0:04:36.14,0:04:37.23,EN,,0,0,0,,and then it goes back to sleep.\nDialogue: 0,0:04:37.44,0:04:39.44,EN,,0,0,0,,And if you accidentally push mouse with you elbow,\nDialogue: 0,0:04:39.61,0:04:42.32,EN,,0,0,0,,a big puff of smoke comes out of your computer and things like that.\nDialogue: 0,0:04:42.94,0:04:45.29,EN,,0,0,0,,So two ways to disastrously\nDialogue: 0,0:04:45.55,0:04:47.21,EN,,0,0,0,,destroy a system by adding features.\nDialogue: 0,0:04:47.50,0:04:49.73,EN,,0,0,0,,But try right now to add a little, simple feature.\nDialogue: 0,0:04:52.60,0:04:53.77,EN,,0,0,0,,This actually is a good one,\nDialogue: 0,0:04:53.85,0:04:56.17,EN,,0,0,0,,and in fact, real Lisps have it.\nDialogue: 0,0:04:57.25,0:04:58.17,EN,,0,0,0,,As you've seen,\nDialogue: 0,0:04:59.29,0:05:03.13,EN,,0,0,0,,there are procedures like plus and times\nDialogue: 0,0:05:03.37,0:05:04.89,EN,,0,0,0,,that take any number of arguments.\nDialogue: 0,0:05:05.43,0:05:06.44,EN,,0,0,0,,So we can write things\nDialogue: 0,0:05:06.57,0:05:10.94,EN,,0,0,0,,like the sum of the product of a and x and x,\nDialogue: 0,0:05:12.09,0:05:16.99,EN,,0,0,0,,and the product of b and x and c.\nDialogue: 0,0:05:17.54,0:05:18.68,EN,,0,0,0,,As you can see here,\nDialogue: 0,0:05:18.92,0:05:21.76,EN,,0,0,0,,addition takes three arguments or two arguments,\nDialogue: 0,0:05:22.30,0:05:24.81,EN,,0,0,0,,multiplication takes two arguments or three arguments,\nDialogue: 0,0:05:25.08,0:05:26.76,EN,,0,0,0,,taking numbers of arguments\nDialogue: 0,0:05:26.78,0:05:28.49,EN,,0,0,0,,all of which are to be treated in the same way.\nDialogue: 0,0:05:30.00,0:05:32.17,EN,,0,0,0,,This is a valuable thing,\nDialogue: 0,0:05:32.28,0:05:34.01,EN,,0,0,0,,indefinite numbers of arguments.\nDialogue: 0,0:05:34.96,0:05:38.41,EN,,0,0,0,,Yet the particular Lisp system that I show you\nDialogue: 0,0:05:39.23,0:05:41.85,EN,,0,0,0,,is one where the numbers of arguments is fixed,\nDialogue: 0,0:05:42.62,0:05:45.28,EN,,0,0,0,,because I had to match the arguments against the formal parameters\nDialogue: 0,0:05:45.63,0:05:47.92,EN,,0,0,0,,in the binder, where there's a pairup.\nDialogue: 0,0:05:50.81,0:05:53.80,EN,,0,0,0,,Well, I'd like to be able to define new procedures like this\nDialogue: 0,0:05:54.89,0:05:57.32,EN,,0,0,0,,that can have any number of arguments.\nDialogue: 0,0:05:58.75,0:06:00.40,EN,,0,0,0,,Well there's several parts to this problem.\nDialogue: 0,0:06:01.34,0:06:04.81,EN,,0,0,0,,The first part is coming up with the syntactic specification,\nDialogue: 0,0:06:05.72,0:06:11.21,EN,,0,0,0,,some way of notating the additional arguments,\nDialogue: 0,0:06:12.17,0:06:13.63,EN,,0,0,0,,of which you don't know how many there are.\nDialogue: 0,0:06:15.48,0:06:16.62,EN,,0,0,0,,And then there's the other thing,\nDialogue: 0,0:06:17.10,0:06:18.70,EN,,0,0,0,,which is once we've notated it,\nDialogue: 0,0:06:19.07,0:06:20.78,EN,,0,0,0,,how are we going to interpret that notation\nDialogue: 0,0:06:21.74,0:06:23.10,EN,,0,0,0,,so as to do the right thing,\nDialogue: 0,0:06:23.85,0:06:25.37,EN,,0,0,0,,whatever the right thing is?\nDialogue: 0,0:06:26.98,0:06:28.80,EN,,0,0,0,,So let's consider an example of a sort of thing\nDialogue: 0,0:06:28.84,0:06:30.27,EN,,0,0,0,,we might want to be able to do.\nDialogue: 0,0:06:33.07,0:06:34.51,EN,,0,0,0,,So an example might be,\nDialogue: 0,0:06:35.42,0:06:37.34,EN,,0,0,0,,that I might want to be able to define a procedure\nDialogue: 0,0:06:37.95,0:06:41.36,EN,,0,0,0,,which is a procedure of one required argument x\nDialogue: 0,0:06:42.20,0:06:45.26,EN,,0,0,0,,and a non-required -- bunch of arguments,\nDialogue: 0,0:06:45.28,0:06:47.23,EN,,0,0,0,,I don't know how many there are, called y.\nDialogue: 0,0:06:49.09,0:06:50.36,EN,,0,0,0,,So x is required,\nDialogue: 0,0:06:55.88,0:06:57.44,EN,,0,0,0,,and there are many y's,\nDialogue: 0,0:06:59.53,0:07:05.99,EN,,0,0,0,,many arguments-- y will be the list of them.\nDialogue: 0,0:07:14.48,0:07:16.06,EN,,0,0,0,,Now, with such a thing,\nDialogue: 0,0:07:16.09,0:07:17.68,EN,,0,0,0,,we might be able to say something like,\nDialogue: 0,0:07:19.02,0:07:21.98,EN,,0,0,0,,map-- I'm going to do something to every one--\nDialogue: 0,0:07:22.52,0:07:25.76,EN,,0,0,0,,of that procedure of one argument u,\nDialogue: 0,0:07:27.00,0:07:34.54,EN,,0,0,0,,which multiplies x by u, and we'll apply that to y.\nDialogue: 0,0:07:36.89,0:07:38.04,EN,,0,0,0,,I've used a dot here\nDialogue: 0,0:07:38.59,0:07:41.31,EN,,0,0,0,,to indicate that the thing after this\nDialogue: 0,0:07:42.19,0:07:44.30,EN,,0,0,0,,is a list of all the rest of the arguments.\nDialogue: 0,0:07:46.30,0:07:48.12,EN,,0,0,0,,I'm making a syntactic specification.\nDialogue: 0,0:07:53.32,0:07:54.64,EN,,0,0,0,,Now, what this depends upon,\nDialogue: 0,0:07:55.71,0:07:58.06,EN,,0,0,0,,the reason why this is sort of a reasonable thing to do,\nDialogue: 0,0:07:59.77,0:08:01.96,EN,,0,0,0,,is because this happens to be a syntax\nDialogue: 0,0:08:02.00,0:08:03.60,EN,,0,0,0,,that's used in the Lisp reader\nDialogue: 0,0:08:04.41,0:08:07.15,EN,,0,0,0,,for representing conses.\nDialogue: 0,0:08:08.94,0:08:11.08,EN,,0,0,0,,We've never introduced that before.You never see.\nDialogue: 0,0:08:11.08,0:08:12.78,EN,,0,0,0,,You may have seen when playing with the system\nDialogue: 0,0:08:13.04,0:08:14.62,EN,,0,0,0,,if you cons two things together, you get the\nDialogue: 0,0:08:14.89,0:08:18.12,EN,,0,0,0,,first, space, dot, the second, space--\nDialogue: 0,0:08:19.79,0:08:22.83,EN,,0,0,0,,the first, space, dot, space, the second\nDialogue: 0,0:08:23.08,0:08:24.64,EN,,0,0,0,,with parentheses around the whole thing.\nDialogue: 0,0:08:26.98,0:08:28.16,EN,,0,0,0,,So that, for example,\nDialogue: 0,0:08:28.97,0:08:35.04,EN,,0,0,0,,this x dot y corresponds to a pair,\nDialogue: 0,0:08:36.33,0:08:39.29,EN,,0,0,0,,which has got an x in it and a y in it.\nDialogue: 0,0:08:41.48,0:08:43.98,EN,,0,0,0,,The other notations that you've seen so far\nDialogue: 0,0:08:44.94,0:08:46.67,EN,,0,0,0,,are things like, like\nDialogue: 0,0:08:46.92,0:08:55.24,EN,,0,0,0,,a procedure of arguments x and y and z which do things\nDialogue: 0,0:08:55.71,0:08:57.63,EN,,0,0,0,,and that looks like--\nDialogue: 0,0:09:02.00,0:09:03.61,EN,,0,0,0,,Just looking at the bound variable list,\nDialogue: 0,0:09:04.22,0:09:05.29,EN,,0,0,0,,it looks like this,\nDialogue: 0,0:09:09.93,0:09:17.32,EN,,0,0,0,,x, y, z, and the empty thing.\nDialogue: 0,0:09:18.28,0:09:21.08,EN,,0,0,0,,If I have a list of arguments I wish to match this against,\nDialogue: 0,0:09:22.60,0:09:25.60,EN,,0,0,0,,I have a list of arguments one, two, three,\nDialogue: 0,0:09:25.87,0:09:27.26,EN,,0,0,0,,I want to match these against.\nDialogue: 0,0:09:28.38,0:09:37.10,EN,,0,0,0,,OK? So I might have here a list of three things,\nDialogue: 0,0:09:42.44,0:09:46.94,EN,,0,0,0,,one, two, three.\nDialogue: 0,0:09:48.99,0:09:53.16,EN,,0,0,0,,And I want to match x, y, z against one, two, three.\nDialogue: 0,0:09:54.22,0:09:56.28,EN,,0,0,0,,Well, it's clear that the one matches the x,\nDialogue: 0,0:09:56.32,0:09:58.01,EN,,0,0,0,,because I can just sort of follow the structure,\nDialogue: 0,0:09:58.86,0:10:01.56,EN,,0,0,0,,and the two matches the y,\nDialogue: 0,0:10:02.46,0:10:04.04,EN,,0,0,0,,and the three matches the z.\nDialogue: 0,0:10:05.48,0:10:09.53,EN,,0,0,0,,But now, supposing I were to compare this x dot y.\nDialogue: 0,0:10:09.55,0:10:11.84,EN,,0,0,0,,this is x dot y--\nDialogue: 0,0:10:12.51,0:10:16.91,EN,,0,0,0,,supposing I compare that with a list of three arguments, one, two, three.\nDialogue: 0,0:10:19.08,0:10:20.00,EN,,0,0,0,,Let's look at that again.\nDialogue: 0,0:10:28.00,0:10:30.32,EN,,0,0,0,,One, two, three--\nDialogue: 0,0:10:30.86,0:10:32.88,EN,,0,0,0,,Well, I can walk along here\nDialogue: 0,0:10:32.99,0:10:35.50,EN,,0,0,0,,and say, oh yes, x matches the one,\nDialogue: 0,0:10:37.56,0:10:41.84,EN,,0,0,0,,Ah, the y matches the list, which is two and three.\nDialogue: 0,0:10:43.74,0:10:46.22,EN,,0,0,0,,So the notation I'm choosing here\nDialogue: 0,0:10:46.41,0:10:50.16,EN,,0,0,0,,is one that's very natural for Lisp system.\nDialogue: 0,0:10:52.66,0:10:54.14,EN,,0,0,0,,But I'm going to choose this as a notation\nDialogue: 0,0:10:54.17,0:10:55.80,EN,,0,0,0,,for representing a bunch of arguments.\nDialogue: 0,0:10:58.29,0:11:00.09,EN,,0,0,0,,Now, there's an alternative possibility.\nDialogue: 0,0:11:00.59,0:11:02.78,EN,,0,0,0,,If I don't want to take one special out,\nDialogue: 0,0:11:03.00,0:11:05.00,EN,,0,0,0,,or two special ones out or something like that,\nDialogue: 0,0:11:06.54,0:11:07.56,EN,,0,0,0,,if I don't want to do that,\nDialogue: 0,0:11:08.78,0:11:10.44,EN,,0,0,0,,if I want to talk about\nDialogue: 0,0:11:10.52,0:11:12.52,EN,,0,0,0,,just the list of all the arguments like in addition，\nDialogue: 0,0:11:13.88,0:11:17.96,EN,,0,0,0,,well then the argument list I'm going to choose to be\nDialogue: 0,0:11:18.20,0:11:23.45,EN,,0,0,0,,that procedure of all the arguments x, which does something with x\nDialogue: 0,0:11:25.14,0:11:26.30,EN,,0,0,0,,And which, for example,\nDialogue: 0,0:11:26.81,0:11:27.96,EN,,0,0,0,,if I take the procedure,\nDialogue: 0,0:11:28.06,0:11:30.44,EN,,0,0,0,,which takes all the arguments x\nDialogue: 0,0:11:31.12,0:11:32.70,EN,,0,0,0,,and returned the list of them,\nDialogue: 0,0:11:34.81,0:11:38.67,EN,,0,0,0,,OK? That's list. That's the procedure list.\nDialogue: 0,0:11:45.85,0:11:46.67,EN,,0,0,0,,How does this work?\nDialogue: 0,0:11:46.84,0:11:50.06,EN,,0,0,0,,Well, indeed what I had as the bound variable list in this case,\nDialogue: 0,0:11:50.60,0:11:51.45,EN,,0,0,0,,whatever it is,\nDialogue: 0,0:11:51.61,0:11:53.68,EN,,0,0,0,,is being matched against a list of arguments.\nDialogue: 0,0:11:55.14,0:11:57.14,EN,,0,0,0,,This symbol now is all of the arguments.\nDialogue: 0,0:12:01.49,0:12:05.13,EN,,0,0,0,,And so this is the choice I'm making for a particular syntactic specification,\nDialogue: 0,0:12:05.64,0:12:07.63,EN,,0,0,0,,for the description of procedures\nDialogue: 0,0:12:08.04,0:12:10.56,EN,,0,0,0,,which take indefinite numbers of arguments.\nDialogue: 0,0:12:13.45,0:12:14.60,EN,,0,0,0,,There are two cases of it,\nDialogue: 0,0:12:15.40,0:12:16.35,EN,,0,0,0,,this one and this one.\nDialogue: 0,0:12:17.44,0:12:18.36,EN,,0,0,0,,And none of this.\nDialogue: 0,0:12:18.42,0:12:20.11,EN,,0,0,0,,When you make syntactic specifications,\nDialogue: 0,0:12:20.44,0:12:22.54,EN,,0,0,0,,it's important that it's unambiguous,\nDialogue: 0,0:12:23.56,0:12:27.36,EN,,0,0,0,,that neither of these can be confused with\nDialogue: 0,0:12:27.66,0:12:31.20,EN,,0,0,0,,a representation we already have, this one.\nDialogue: 0,0:12:33.61,0:12:35.82,EN,,0,0,0,,I can always tell whether I have\nDialogue: 0,0:12:36.54,0:12:39.80,EN,,0,0,0,,a fixed number of explicitly named arguments\nDialogue: 0,0:12:40.28,0:12:41.76,EN,,0,0,0,,made by these formal parameters,\nDialogue: 0,0:12:42.64,0:12:43.13,EN,,0,0,0,,or\nDialogue: 0,0:12:43.28,0:12:45.36,EN,,0,0,0,,a fixed number of named formal parameters\nDialogue: 0,0:12:45.44,0:12:48.01,EN,,0,0,0,,followed by a thing which picks up all the rest of them,\nDialogue: 0,0:12:49.42,0:12:53.52,EN,,0,0,0,,or a list of all the arguments\nDialogue: 0,0:12:53.68,0:12:56.52,EN,,0,0,0,,which will be matched against this particular formal parameter called x,\nDialogue: 0,0:12:56.99,0:12:58.84,EN,,0,0,0,,because these are syntactically distinguishable.\nDialogue: 0,0:13:02.25,0:13:04.62,EN,,0,0,0,,Many languages make terrible errors in that form\nDialogue: 0,0:13:05.04,0:13:08.03,EN,,0,0,0,,where whole segments of interpretation are cut off,\nDialogue: 0,0:13:08.64,0:13:13.92,EN,,0,0,0,,because there are syntactic ambiguities in the language.\nDialogue: 0,0:13:14.56,0:13:16.67,EN,,0,0,0,,They are the traditional problems with ALGOL like languages\nDialogue: 0,0:13:16.67,0:13:23.47,EN,,0,0,0,,having to do with the nesting of ifs in the predicate part.\nDialogue: 0,0:13:25.06,0:13:25.93,EN,,0,0,0,,In any case,\nDialogue: 0,0:13:27.52,0:13:29.44,EN,,0,0,0,,now, so I've told you about the syntax,\nDialogue: 0,0:13:30.27,0:13:34.83,EN,,0,0,0,,now, what are we going to do about the semantics of this?\nDialogue: 0,0:13:35.25,0:13:36.11,EN,,0,0,0,,How do we interpret it?\nDialogue: 0,0:13:36.59,0:13:37.96,EN,,0,0,0,,Well this is just super easy.\nDialogue: 0,0:13:38.44,0:13:42.57,EN,,0,0,0,,I'm going to modify the metacircular interpreter to do it.\nDialogue: 0,0:13:43.71,0:13:44.76,EN,,0,0,0,,And that's a one liner.\nDialogue: 0,0:13:45.98,0:13:46.57,EN,,0,0,0,,There it is.\nDialogue: 0,0:13:47.53,0:13:49.56,EN,,0,0,0,,I'm changing the way you pair things up.\nDialogue: 0,0:13:50.81,0:13:54.19,EN,,0,0,0,,OK? Here we have procedure that pairs --\nDialogue: 0,0:13:56.76,0:14:02.03,EN,,0,0,0,,Here's the procedure that pairs the\nDialogue: 0,0:14:04.81,0:14:09.56,EN,,0,0,0,,the variables, the formal parameters, with the arguments that were passed\nDialogue: 0,0:14:12.16,0:14:16.68,EN,,0,0,0,,from the last description of the metacircular interpreter.\nDialogue: 0,0:14:18.96,0:14:21.93,EN,,0,0,0,,And here's some things that are the same as they were before.\nDialogue: 0,0:14:22.67,0:14:23.23,EN,,0,0,0,,In other words,\nDialogue: 0,0:14:23.31,0:14:25.07,EN,,0,0,0,,if the list of variables is empty,\nDialogue: 0,0:14:25.52,0:14:27.31,EN,,0,0,0,,then if the list of values is empty,\nDialogue: 0,0:14:27.45,0:14:29.61,EN,,0,0,0,,then I have an empty list.\nDialogue: 0,0:14:31.05,0:14:33.00,EN,,0,0,0,,Otherwise, I have too many arguments,\nDialogue: 0,0:14:33.98,0:14:40.19,EN,,0,0,0,,If I have, that is if I have empty variables but not empty values.\nDialogue: 0,0:14:41.58,0:14:44.00,EN,,0,0,0,,If I have empty values,\nDialogue: 0,0:14:44.96,0:14:47.47,EN,,0,0,0,,OK? But the variables are not empty,\nDialogue: 0,0:14:47.48,0:14:48.56,EN,,0,0,0,,that I have too few arguments.\nDialogue: 0,0:14:48.94,0:14:51.31,EN,,0,0,0,,However if I have a variable -- the variables are a symbol--\nDialogue: 0,0:14:55.53,0:14:56.49,EN,,0,0,0,,interesting case--\nDialogue: 0,0:14:58.30,0:15:04.40,EN,,0,0,0,,then, what I should do is say, oh yes, this is the special case\nDialogue: 0,0:15:04.59,0:15:06.51,EN,,0,0,0,,that I have a symbolic tail.\nDialogue: 0,0:15:08.35,0:15:14.11,EN,,0,0,0,,OK. I have here a thing just like we looked over here.\nDialogue: 0,0:15:14.90,0:15:17.87,EN,,0,0,0,,This is a tail which is a symbol, y.\nDialogue: 0,0:15:18.63,0:15:19.39,EN,,0,0,0,,It's not a nil.\nDialogue: 0,0:15:20.73,0:15:21.72,EN,,0,0,0,,It's not the empty list.\nDialogue: 0,0:15:23.26,0:15:25.60,EN,,0,0,0,,Here's a symbolic tail that is just the very beginning of the tail.\nDialogue: 0,0:15:25.98,0:15:26.81,EN,,0,0,0,,There is nothing else.\nDialogue: 0,0:15:27.79,0:15:28.72,EN,,0,0,0,,In that case,\nDialogue: 0,0:15:29.96,0:15:37.20,EN,,0,0,0,,I wish to match that variable with all the values\nDialogue: 0,0:15:38.03,0:15:42.52,EN,,0,0,0,,and add that to the pairing that I'm making.\nDialogue: 0,0:15:44.50,0:15:46.91,EN,,0,0,0,,Otherwise, I go through the normal arrangement\nDialogue: 0,0:15:47.15,0:15:48.52,EN,,0,0,0,,of making up the whole pairing.\nDialogue: 0,0:15:52.02,0:15:53.82,EN,,0,0,0,,I suppose that's very simple.\nDialogue: 0,0:15:54.51,0:15:55.84,EN,,0,0,0,,And that's all there is to it.\nDialogue: 0,0:15:57.08,0:15:58.33,EN,,0,0,0,,And now I'll answer some questions.\nDialogue: 0,0:16:02.62,0:16:05.05,EN,,0,0,0,,The first one-- Are there any questions?\nDialogue: 0,0:16:06.60,0:16:06.94,EN,,0,0,0,,Yes?\nDialogue: 0,0:16:07.37,0:16:09.92,EN,,0,0,0,,AUDIENCE: Could you explain that third form?\nDialogue: 0,0:16:09.98,0:16:12.12,EN,,0,0,0,,PROFESSOR: Third form. This one? OK.\nDialogue: 0,0:16:12.59,0:16:14.27,EN,,0,0,0,,Well, maybe we should look at the thing\nDialogue: 0,0:16:14.30,0:16:16.24,EN,,0,0,0,,as a piece of list structure.\nDialogue: 0,0:16:18.57,0:16:22.73,EN,,0,0,0,,This is a procedure which contains a lambda.\nDialogue: 0,0:16:25.85,0:16:29.61,EN,,0,0,0,,I'm just looking at the list structure which represents this.\nDialogue: 0,0:16:31.26,0:16:32.44,EN,,0,0,0,,Here's x.\nDialogue: 0,0:16:32.73,0:16:33.98,EN,,0,0,0,,These are our symbols.\nDialogue: 0,0:16:37.41,0:16:39.58,EN,,0,0,0,,And then the body is nothing but x.\nDialogue: 0,0:16:44.84,0:16:48.75,EN,,0,0,0,,If I were looking for the bound variable list part of this procedure,\nDialogue: 0,0:16:50.09,0:16:51.58,EN,,0,0,0,,I would go looking at the CADR,\nDialogue: 0,0:16:52.14,0:16:53.16,EN,,0,0,0,,and I'd find a symbol.\nDialogue: 0,0:16:54.01,0:16:57.16,EN,,0,0,0,,So the, matcher, which is this pairup thing I just showed you,\nDialogue: 0,0:16:58.24,0:17:00.44,EN,,0,0,0,,is going to be matching a symbolic object\nDialogue: 0,0:17:01.56,0:17:04.40,EN,,0,0,0,,against a list of arguments that were passed.\nDialogue: 0,0:17:05.76,0:17:09.55,EN,,0,0,0,,And it will bind that symbol to the list of arguments.\nDialogue: 0,0:17:11.37,0:17:16.48,EN,,0,0,0,,The -- In this case, if I'm looking for it,\nDialogue: 0,0:17:16.92,0:17:20.97,EN,,0,0,0,,the match will be against this in the bound variable list position.\nDialogue: 0,0:17:24.14,0:17:26.14,EN,,0,0,0,,Now, if what this does is\nDialogue: 0,0:17:26.17,0:17:29.13,EN,,0,0,0,,it gets a list of arguments and returns it, that's list\nDialogue: 0,0:17:30.40,0:17:31.39,EN,,0,0,0,,That's the procedure is.\nDialogue: 0,0:17:34.51,0:17:35.48,EN,,0,0,0,,Oh well, thank you.\nDialogue: 0,0:17:36.14,0:17:37.28,EN,,0,0,0,,Let's take a break.\nDialogue: 0,0:17:37.83,0:17:55.36,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:17:55.36,0:17:59.02,EN,,0,0,0,,\nDialogue: 0,0:18:03.53,0:18:07.56,EN,,0,0,0,,\nDialogue: 0,0:18:07.56,0:18:11.69,EN,,0,0,0,,\nDialogue: 0,0:18:12.25,0:18:16.11,EN,,0,0,0,,\nDialogue: 0,0:18:20.86,0:18:21.61,EN,,0,0,0,,PROFESSOR: Well let's see.\nDialogue: 0,0:18:23.26,0:18:26.32,EN,,0,0,0,,Now, I'm going to tell you about a rather more substantial variation\nDialogue: 0,0:18:27.45,0:18:31.04,EN,,0,0,0,,one that's a famous variation\nDialogue: 0,0:18:31.60,0:18:36.80,EN,,0,0,0,,hat many early Lisps had.\nDialogue: 0,0:18:38.25,0:18:40.06,EN,,0,0,0,,It's called dynamic binding of variables.\nDialogue: 0,0:18:41.77,0:18:44.68,EN,,0,0,0,,And we'll investigate a little bit about that right now.\nDialogue: 0,0:18:47.62,0:18:50.16,EN,,0,0,0,,I'm going to first introduce this by showing you the sort of thing\nDialogue: 0,0:18:50.35,0:18:52.36,EN,,0,0,0,,that would make someone want this idea.\nDialogue: 0,0:18:53.74,0:18:55.23,EN,,0,0,0,,I'm not going to tell what it is yet,\nDialogue: 0,0:18:55.40,0:18:57.60,EN,,0,0,0,,I'm going to show you why you might want it.\nDialogue: 0,0:18:58.64,0:18:59.93,EN,,0,0,0,,Suppose, for example,\nDialogue: 0,0:19:00.75,0:19:02.59,EN,,0,0,0,,we looked at the sum procedure again\nDialogue: 0,0:19:05.02,0:19:06.43,EN,,0,0,0,,for summing up a bunch of things.\nDialogue: 0,0:19:08.14,0:19:09.47,EN,,0,0,0,,To be that procedure,\nDialogue: 0,0:19:09.60,0:19:10.78,EN,,0,0,0,,of a term,\nDialogue: 0,0:19:13.04,0:19:14.41,EN,,0,0,0,,lower bound,\nDialogue: 0,0:19:15.24,0:19:17.04,EN,,0,0,0,,method of computing the next index,\nDialogue: 0,0:19:17.24,0:19:18.56,EN,,0,0,0,,and upper bound,\nDialogue: 0,0:19:19.36,0:19:20.16,EN,,0,0,0,,such that,\nDialogue: 0,0:19:23.16,0:19:26.94,EN,,0,0,0,,if a is greater than b\nDialogue: 0,0:19:27.15,0:19:28.64,EN,,0,0,0,,then the result is 0,\nDialogue: 0,0:19:30.24,0:19:31.08,EN,,0,0,0,,otherwise,\nDialogue: 0,0:19:33.68,0:19:39.82,EN,,0,0,0,,it's the sum, of the term, procedure, applied to a\nDialogue: 0,0:19:40.60,0:19:44.24,EN,,0,0,0,,and the result of adding up, terms,\nDialogue: 0,0:19:47.68,0:19:52.64,EN,,0,0,0,,with the next a being the a,\nDialogue: 0,0:20:00.30,0:20:03.56,EN,,0,0,0,,the next procedure passed along,\nDialogue: 0,0:20:06.40,0:20:08.25,EN,,0,0,0,,and the upper bound being passed along.\nDialogue: 0,0:20:14.51,0:20:15.76,EN,,0,0,0,,Blink, blink, blink--\nDialogue: 0,0:20:17.82,0:20:21.45,EN,,0,0,0,,OK? Now, when I use this sum procedure,\nDialogue: 0,0:20:21.96,0:20:24.35,EN,,0,0,0,,I can use it, for example, like this.\nDialogue: 0,0:20:25.45,0:20:38.04,EN,,0,0,0,,We can define the sum of the powers to be,\nDialogue: 0,0:20:38.08,0:20:40.33,EN,,0,0,0,,for example, sum of a bunch of powers x to the n,\nDialogue: 0,0:20:41.10,0:20:45.93,EN,,0,0,0,,to be that procedure of a, b, and n--\nDialogue: 0,0:20:45.95,0:20:47.69,EN,,0,0,0,,lower bound, the upper bound, and n--\nDialogue: 0,0:20:48.06,0:20:53.34,EN,,0,0,0,,which is sum, of lambda of x,\nDialogue: 0,0:20:53.60,0:20:59.31,EN,,0,0,0,,the procedure of one argument x, which exponentiates x to the n,\nDialogue: 0,0:21:02.19,0:21:09.29,EN,,0,0,0,,with the a, the incrementer, and b, being passed along.\nDialogue: 0,0:21:11.82,0:21:15.76,EN,,0,0,0,,So we're adding up x to n, given an x.\nDialogue: 0,0:21:16.14,0:21:19.74,EN,,0,0,0,,x takes on values from a to b, incrementing by one.\nDialogue: 0,0:21:22.94,0:21:24.38,EN,,0,0,0,,I can also write the--\nDialogue: 0,0:21:27.68,0:21:28.20,EN,,0,0,0,,That's right.\nDialogue: 0,0:21:29.78,0:21:31.02,EN,,0,0,0,,Product, excuse me.\nDialogue: 0,0:21:31.91,0:21:33.36,EN,,0,0,0,,The product of a bunch of powers.\nDialogue: 0,0:21:38.08,0:21:39.12,EN,,0,0,0,,It's a strange name.\nDialogue: 0,0:21:40.02,0:21:40.80,EN,,0,0,0,,I'm going to leave it there.\nDialogue: 0,0:21:41.96,0:21:46.32,EN,,0,0,0,,Weird-- OK? I write up what I have.\nDialogue: 0,0:21:49.34,0:21:50.19,EN,,0,0,0,,I'm sure that's right.\nDialogue: 0,0:21:51.37,0:21:53.82,EN,,0,0,0,,And if I want the product of a bunch of powers--\nDialogue: 0,0:21:58.41,0:22:02.36,EN,,0,0,0,,That was 12 brain cells, that double-take.\nDialogue: 0,0:22:03.00,0:22:06.81,EN,,0,0,0,,I can for example use the procedure which is like sum,\nDialogue: 0,0:22:06.81,0:22:08.22,EN,,0,0,0,,which is for making products,\nDialogue: 0,0:22:08.56,0:22:11.05,EN,,0,0,0,,but it's similar to that, that you've seen before.\nDialogue: 0,0:22:11.45,0:22:16.38,EN,,0,0,0,,There's a procedure of three arguments again.\nDialogue: 0,0:22:17.00,0:22:25.42,EN,,0,0,0,,Which is the product of terms that are constructed, or factors in this case,\nDialogue: 0,0:22:25.66,0:22:31.60,EN,,0,0,0,,constructed from exponentiating x to the n,\nDialogue: 0,0:22:34.43,0:22:37.85,EN,,0,0,0,,where I start with a, I increment, and I go to b.\nDialogue: 0,0:22:41.53,0:22:41.88,EN,,0,0,0,,Now,\nDialogue: 0,0:22:46.83,0:22:49.50,EN,,0,0,0,,there's some sort of thing here that should disturb you immediately.\nDialogue: 0,0:22:50.75,0:22:52.01,EN,,0,0,0,,These look the same.\nDialogue: 0,0:22:53.18,0:22:55.20,EN,,0,0,0,,Why am I writing this code so many times?\nDialogue: 0,0:22:56.59,0:22:59.72,EN,,0,0,0,,Here I am, in the same boat I've been in before.\nDialogue: 0,0:23:01.00,0:23:03.15,EN,,0,0,0,,Right? Wouldn't it be nice to make an abstraction here?\nDialogue: 0,0:23:03.81,0:23:05.76,EN,,0,0,0,,What's an example of a good abstraction to make?\nDialogue: 0,0:23:05.85,0:23:07.55,EN,,0,0,0,,Well, I see some codes that's identical.\nDialogue: 0,0:23:08.47,0:23:09.32,EN,,0,0,0,,Here's one,\nDialogue: 0,0:23:09.98,0:23:11.08,EN,,0,0,0,,and here's another.\nDialogue: 0,0:23:14.45,0:23:16.22,EN,,0,0,0,,And so maybe I should be able to pull that out.\nDialogue: 0,0:23:17.09,0:23:19.23,EN,,0,0,0,,I should be able to say, oh yes,\nDialogue: 0,0:23:20.51,0:23:22.67,EN,,0,0,0,,the sum of the powers could be written in terms of\nDialogue: 0,0:23:22.88,0:23:24.52,EN,,0,0,0,,something called the nth power procedure.\nDialogue: 0,0:23:25.71,0:23:27.40,EN,,0,0,0,,Imagine somebody wanted to write\nDialogue: 0,0:23:27.74,0:23:30.03,EN,,0,0,0,,a slightly different procedure that looks like this.\nDialogue: 0,0:23:37.63,0:23:45.18,EN,,0,0,0,,The sum powers to be a procedure\nDialogue: 0,0:23:46.44,0:23:48.46,EN,,0,0,0,,of a, b, and n,\nDialogue: 0,0:23:48.75,0:23:52.27,EN,,0,0,0,,which the result of summing up the nth power.\nDialogue: 0,0:23:53.88,0:23:55.42,EN,,0,0,0,,We're going to give a name to that idea,\nDialogue: 0,0:23:58.35,0:24:02.27,EN,,0,0,0,,for starting at a, going by one, and ending at b.\nDialogue: 0,0:24:05.74,0:24:06.91,EN,,0,0,0,,And similarly,\nDialogue: 0,0:24:10.65,0:24:12.76,EN,,0,0,0,,I might want to write the product powers this way,\nDialogue: 0,0:24:12.89,0:24:15.24,EN,,0,0,0,,abstracting out this idea.\nDialogue: 0,0:24:16.27,0:24:17.37,EN,,0,0,0,,I might want this.\nDialogue: 0,0:24:22.10,0:24:23.02,EN,,0,0,0,,Product powers,\nDialogue: 0,0:24:29.48,0:24:34.94,EN,,0,0,0,,to be a procedure of a, b, and n,\nDialogue: 0,0:24:35.31,0:24:42.33,EN,,0,0,0,,which is the product of the nth power operation\nDialogue: 0,0:24:46.44,0:24:50.30,EN,,0,0,0,,on a with the incrementation and b being\nDialogue: 0,0:24:53.50,0:24:57.56,EN,,0,0,0,,being my arguments for the analogous-thing product.\nDialogue: 0,0:24:58.38,0:25:00.24,EN,,0,0,0,,And I'd like to be able to define,\nDialogue: 0,0:25:02.04,0:25:03.88,EN,,0,0,0,,I'd like to be able to define nth power--\nDialogue: 0,0:25:04.89,0:25:05.93,EN,,0,0,0,,I'll put it over here.\nDialogue: 0,0:25:12.22,0:25:12.99,EN,,0,0,0,,I'll put it at the top.\nDialogue: 0,0:25:25.41,0:25:29.04,EN,,0,0,0,,--to be, in fact, my procedure of one argument x\nDialogue: 0,0:25:29.60,0:25:34.56,EN,,0,0,0,,which is the result of exponentiating x to the n.\nDialogue: 0,0:25:35.93,0:25:36.96,EN,,0,0,0,,But I have a problem.\nDialogue: 0,0:25:38.64,0:25:39.93,EN,,0,0,0,,My environment model,\nDialogue: 0,0:25:40.57,0:25:43.23,EN,,0,0,0,,that is my means of interpretation\nDialogue: 0,0:25:44.00,0:25:45.95,EN,,0,0,0,,of interpretation for the language that we've defined so far,\nDialogue: 0,0:25:46.27,0:25:48.81,EN,,0,0,0,,does not give me a meaning for this n.\nDialogue: 0,0:25:52.76,0:25:59.26,EN,,0,0,0,,Because, as you know, the, as you know\nDialogue: 0,0:26:00.76,0:26:04.25,EN,,0,0,0,,this n is free in this procedure.\nDialogue: 0,0:26:06.41,0:26:07.98,EN,,0,0,0,,The environment model tells us\nDialogue: 0,0:26:08.60,0:26:10.20,EN,,0,0,0,,that the meaning of a free variable\nDialogue: 0,0:26:11.21,0:26:14.99,EN,,0,0,0,,is determined in the environment in which this procedure is defined.\nDialogue: 0,0:26:16.64,0:26:17.47,EN,,0,0,0,,In a way I have written it,\nDialogue: 0,0:26:17.48,0:26:19.84,EN,,0,0,0,,assuming these things are defined on the blackboard as is,\nDialogue: 0,0:26:21.64,0:26:23.63,EN,,0,0,0,,this is defined in the global environment,\nDialogue: 0,0:26:24.06,0:26:25.15,EN,,0,0,0,,where there is no n.\nDialogue: 0,0:26:25.93,0:26:27.63,EN,,0,0,0,,Therefore, n is unbound variable.\nDialogue: 0,0:26:28.72,0:26:31.66,EN,,0,0,0,,But it's perfectly clear, to most of us,\nDialogue: 0,0:26:32.60,0:26:36.32,EN,,0,0,0,,that we would like it to be this n and this n.\nDialogue: 0,0:26:38.99,0:26:42.67,EN,,0,0,0,,On the other hand, OK, it would be nice.\nDialogue: 0,0:26:42.84,0:26:44.28,EN,,0,0,0,,Certainly we've got to be careful here\nDialogue: 0,0:26:44.56,0:26:46.06,EN,,0,0,0,,of keeping this to be this,\nDialogue: 0,0:26:48.96,0:26:52.83,EN,,0,0,0,,and this one over here, wherever it is to be this one.\nDialogue: 0,0:26:57.39,0:26:59.74,EN,,0,0,0,,Well, the desire to make this work\nDialogue: 0,0:27:00.67,0:27:02.72,EN,,0,0,0,,has led to a very famous bug.\nDialogue: 0,0:27:04.65,0:27:06.04,EN,,0,0,0,,I'll tell you about the famous bug.\nDialogue: 0,0:27:07.15,0:27:09.40,EN,,0,0,0,,Look at this slide.\nDialogue: 0,0:27:10.66,0:27:12.70,EN,,0,0,0,,This is an idea called dynamic binding.\nDialogue: 0,0:27:13.99,0:27:16.91,EN,,0,0,0,,Where, instead of the free variable being interpreted\nDialogue: 0,0:27:17.76,0:27:21.23,EN,,0,0,0,,in the environment of definition of a procedure,\nDialogue: 0,0:27:22.40,0:27:25.16,EN,,0,0,0,,the free variable is interpreted as having its value\nDialogue: 0,0:27:25.44,0:27:29.31,EN,,0,0,0,,in the environment of the caller of the procedure.\nDialogue: 0,0:27:31.85,0:27:34.84,EN,,0,0,0,,So what you have is a system\nDialogue: 0,0:27:34.86,0:27:39.68,EN,,0,0,0,,where you search up the chain of callers of a particular procedure,\nDialogue: 0,0:27:40.43,0:27:42.65,EN,,0,0,0,,and, of course, in this case,\nDialogue: 0,0:27:42.84,0:27:44.30,EN,,0,0,0,,since nth power is called\nDialogue: 0,0:27:44.33,0:27:45.98,EN,,0,0,0,,from inside product whatever it is--\nDialogue: 0,0:27:46.41,0:27:48.68,EN,,0,0,0,,I had to write our own sum which is the analogous procedure--\nDialogue: 0,0:27:50.51,0:27:54.92,EN,,0,0,0,,and product is presumably called from product powers,\nDialogue: 0,0:27:55.13,0:27:56.14,EN,,0,0,0,,as you see over here,\nDialogue: 0,0:27:56.83,0:27:59.37,EN,,0,0,0,,then since product powers bind with variable n ,\nDialogue: 0,0:28:00.09,0:28:04.09,EN,,0,0,0,,then nth powers n would be derived through that chain.\nDialogue: 0,0:28:08.14,0:28:09.64,EN,,0,0,0,,Similarly, this n,\nDialogue: 0,0:28:10.11,0:28:12.01,EN,,0,0,0,,the nth power in n in this case,\nDialogue: 0,0:28:12.32,0:28:15.80,EN,,0,0,0,,would come through nth power here being called from inside sum.\nDialogue: 0,0:28:15.80,0:28:18.27,EN,,0,0,0,,You can see it being called from inside sum here.\nDialogue: 0,0:28:20.73,0:28:21.69,EN,,0,0,0,,It's called term here.\nDialogue: 0,0:28:22.90,0:28:25.72,EN,,0,0,0,,But sum was called from inside of sum powers,\nDialogue: 0,0:28:26.94,0:28:27.96,EN,,0,0,0,,which bound n.\nDialogue: 0,0:28:28.93,0:28:30.65,EN,,0,0,0,,Therefore, there would be an n available\nDialogue: 0,0:28:32.75,0:28:36.11,EN,,0,0,0,,that n to get it's value from.\nDialogue: 0,0:28:37.95,0:28:39.24,EN,,0,0,0,,This is called dynamic --\nDialogue: 0,0:28:39.28,0:28:43.10,EN,,0,0,0,,What we have below this white line plus over here\nDialogue: 0,0:28:43.31,0:28:46.04,EN,,0,0,0,,is what's called a dynamic binding view of the world.\nDialogue: 0,0:28:46.59,0:28:49.00,EN,,0,0,0,,If that works, that's a dynamic binding view.\nDialogue: 0,0:28:50.85,0:28:52.65,EN,,0,0,0,,Now, let's take a look, for example,\nDialogue: 0,0:28:54.54,0:28:55.99,EN,,0,0,0,,at just what it takes to implement that.\nDialogue: 0,0:28:55.99,0:28:56.96,EN,,0,0,0,,That's real easy.\nDialogue: 0,0:28:57.48,0:28:59.34,EN,,0,0,0,,In fact, the very first Lisps\nDialogue: 0,0:29:00.01,0:29:02.52,EN,,0,0,0,,had any form of interpretations of the free variables at all,\nDialogue: 0,0:29:03.31,0:29:05.98,EN,,0,0,0,,had dynamic binding interpretations for the free variables.\nDialogue: 0,0:29:06.40,0:29:10.14,EN,,0,0,0,,APL has dynamic binding interpretation for the free variables,\nDialogue: 0,0:29:11.68,0:29:14.32,EN,,0,0,0,,not lexical or static binding.\nDialogue: 0,0:29:15.22,0:29:17.00,EN,,0,0,0,,So, of course, the change is in eval.\nDialogue: 0,0:29:19.31,0:29:20.59,EN,,0,0,0,,And it's really in two places.\nDialogue: 0,0:29:22.78,0:29:25.61,EN,,0,0,0,,First of all, one thing we see,\nDialogue: 0,0:29:26.52,0:29:28.49,EN,,0,0,0,,is that things become a little simpler.\nDialogue: 0,0:29:29.39,0:29:33.63,EN,,0,0,0,,If I don't have to have the -- If I don't have to have the\nDialogue: 0,0:29:33.64,0:29:36.20,EN,,0,0,0,,environment be the environment of definition for procedure,\nDialogue: 0,0:29:36.44,0:29:38.04,EN,,0,0,0,,the procedure need not capture\nDialogue: 0,0:29:38.43,0:29:40.17,EN,,0,0,0,,the environment at the time it's defined.\nDialogue: 0,0:29:42.03,0:29:44.96,EN,,0,0,0,,And so if we look here at this slide,\nDialogue: 0,0:29:45.84,0:29:50.08,EN,,0,0,0,,we see that the clause for a lambda expression,\nDialogue: 0,0:29:50.73,0:29:52.43,EN,,0,0,0,,which is the way a procedure is defined,\nDialogue: 0,0:29:53.92,0:29:56.73,EN,,0,0,0,,does not make up a thing which has a type closure\nDialogue: 0,0:29:56.75,0:30:01.05,EN,,0,0,0,,and a attached environment structure.\nDialogue: 0,0:30:01.29,0:30:02.54,EN,,0,0,0,,It's just the expression itself.\nDialogue: 0,0:30:02.54,0:30:04.76,EN,,0,0,0,,And we'll decompose that some other way somewhere else.\nDialogue: 0,0:30:06.44,0:30:09.40,EN,,0,0,0,,The other thing we see is the applicator\nDialogue: 0,0:30:10.36,0:30:13.69,EN,,0,0,0,,applicator must be able to get the environment of the caller.\nDialogue: 0,0:30:14.29,0:30:17.24,EN,,0,0,0,,The caller of a procedure is right here.\nDialogue: 0,0:30:17.26,0:30:19.45,EN,,0,0,0,,If the procedure is a application--\nDialogue: 0,0:30:19.56,0:30:21.63,EN,,0,0,0,,If the expression we're evaluating is a combination,\nDialogue: 0,0:30:21.79,0:30:23.71,EN,,0,0,0,,then we're going to call a combination\nDialogue: 0,0:30:23.93,0:30:25.50,EN,,0,0,0,,then we're going to call a procedure\nDialogue: 0,0:30:25.66,0:30:27.37,EN,,0,0,0,,which is the value of the operator.\nDialogue: 0,0:30:29.84,0:30:31.44,EN,,0,0,0,,The environment of the caller\nDialogue: 0,0:30:31.98,0:30:34.51,EN,,0,0,0,,is the environment we have right here, available now.\nDialogue: 0,0:30:35.89,0:30:40.72,EN,,0,0,0,,So all I have to do is pass that environment to the applicator, to apply.\nDialogue: 0,0:30:41.49,0:30:42.75,EN,,0,0,0,,And if we look at that here,\nDialogue: 0,0:30:43.58,0:30:44.97,EN,,0,0,0,,the only change we have to make\nDialogue: 0,0:30:45.71,0:30:48.41,EN,,0,0,0,,is that fellow takes that environment\nDialogue: 0,0:30:48.78,0:30:55.68,EN,,0,0,0,,uses that environment for the purpose of extending that environment\nDialogue: 0,0:30:56.67,0:30:59.02,EN,,0,0,0,,when abiding the formal parameters\nDialogue: 0,0:30:59.02,0:31:01.37,EN,,0,0,0,,of the procedure to the arguments that were passed,\nDialogue: 0,0:31:03.08,0:31:05.98,EN,,0,0,0,,not an environment that was captured in the procedure.\nDialogue: 0,0:31:06.81,0:31:09.45,EN,,0,0,0,,The reason why the first Lisps were implemented this way,\nDialogue: 0,0:31:09.66,0:31:11.96,EN,,0,0,0,,is the sort of the obvious, accidental implementation.\nDialogue: 0,0:31:14.13,0:31:16.68,EN,,0,0,0,,And, of course, as usual, people got used to it and liked it.\nDialogue: 0,0:31:17.25,0:31:18.27,EN,,0,0,0,,And there were some people said,\nDialogue: 0,0:31:18.40,0:31:19.50,EN,,0,0,0,,this is the way to do it.\nDialogue: 0,0:31:21.59,0:31:24.09,EN,,0,0,0,,Unfortunately that causes some serious problems.\nDialogue: 0,0:31:25.40,0:31:27.24,EN,,0,0,0,,The most important, serious problem\nDialogue: 0,0:31:27.53,0:31:29.84,EN,,0,0,0,,in using dynamic binding\nDialogue: 0,0:31:31.00,0:31:33.56,EN,,0,0,0,,is there's a modularity crisis that's involved it.\nDialogue: 0,0:31:35.46,0:31:37.66,EN,,0,0,0,,If two people are working together on some big system,\nDialogue: 0,0:31:38.57,0:31:40.01,EN,,0,0,0,,then an important thing to one\nDialogue: 0,0:31:40.35,0:31:42.19,EN,,0,0,0,,is that the names used by each one\nDialogue: 0,0:31:42.99,0:31:44.58,EN,,0,0,0,,don't interfere with the names of the other.\nDialogue: 0,0:31:47.93,0:31:50.78,EN,,0,0,0,,It's important that when I invent some segment of code\nDialogue: 0,0:31:51.07,0:31:53.13,EN,,0,0,0,,that no one can make my code stop working\nDialogue: 0,0:31:53.88,0:31:56.57,EN,,0,0,0,,by using my names that I use internal to my code,\nDialogue: 0,0:31:56.75,0:31:57.71,EN,,0,0,0,,internal to his code.\nDialogue: 0,0:31:59.85,0:32:00.46,EN,,0,0,0,,However,\nDialogue: 0,0:32:01.04,0:32:05.18,EN,,0,0,0,,dynamic binding violates that particular modularity constraint in a clear way.\nDialogue: 0,0:32:06.67,0:32:08.08,EN,,0,0,0,,Consider, for example,\nDialogue: 0,0:32:09.18,0:32:10.35,EN,,0,0,0,,what happens over here.\nDialogue: 0,0:32:12.54,0:32:13.79,EN,,0,0,0,,Suppose it was the case\nDialogue: 0,0:32:15.47,0:32:19.81,EN,,0,0,0,,that I decided to change the word next.\nDialogue: 0,0:32:19.81,0:32:24.41,EN,,0,0,0,,Supposing somebody is writing, somebody is writing sum,\nDialogue: 0,0:32:25.10,0:32:26.68,EN,,0,0,0,,and somebody else is going to use sum.\nDialogue: 0,0:32:28.97,0:32:30.32,EN,,0,0,0,,The writer of sum\nDialogue: 0,0:32:30.49,0:32:32.30,EN,,0,0,0,,has a choice of what names he may use.\nDialogue: 0,0:32:33.66,0:32:34.84,EN,,0,0,0,,Let's say, I'm that writer.\nDialogue: 0,0:32:36.83,0:32:39.30,EN,,0,0,0,,Well, by gosh, just happens I didn't want to call this next.\nDialogue: 0,0:32:39.30,0:32:40.09,EN,,0,0,0,,I called it n.\nDialogue: 0,0:32:41.74,0:32:43.10,EN,,0,0,0,,So all places where you see next,\nDialogue: 0,0:32:44.28,0:32:45.26,EN,,0,0,0,,I called it n.\nDialogue: 0,0:32:48.14,0:32:48.48,EN,,0,0,0,,Whoops.\nDialogue: 0,0:32:49.94,0:32:52.22,EN,,0,0,0,,I changed nothing about the specifications of this program,\nDialogue: 0,0:32:53.32,0:32:54.86,EN,,0,0,0,,but this program stops working.\nDialogue: 0,0:32:56.11,0:32:57.96,EN,,0,0,0,,Not only that, unfortunately, this one does too.\nDialogue: 0,0:32:59.50,0:33:01.40,EN,,0,0,0,,Why do these programs stop working?\nDialogue: 0,0:33:02.26,0:33:03.24,EN,,0,0,0,,Well, it's sort of clear.\nDialogue: 0,0:33:04.48,0:33:09.29,EN,,0,0,0,,Instead of chasing out the value of the n\nDialogue: 0,0:33:09.31,0:33:13.72,EN,,0,0,0,,that occurs in nth power over here or over here,\nDialogue: 0,0:33:14.97,0:33:17.16,EN,,0,0,0,,through the environment of definition,\nDialogue: 0,0:33:17.20,0:33:19.58,EN,,0,0,0,,where this one is always linked to this one,\nDialogue: 0,0:33:19.87,0:33:21.48,EN,,0,0,0,,if it was through the environment of definition,\nDialogue: 0,0:33:21.55,0:33:23.63,EN,,0,0,0,,because here is the definition.\nDialogue: 0,0:33:24.37,0:33:26.25,EN,,0,0,0,,This lambda expression was executed\nDialogue: 0,0:33:26.59,0:33:28.59,EN,,0,0,0,,in the environment where that n was defined.\nDialogue: 0,0:33:30.70,0:33:31.84,EN,,0,0,0,,If instead of doing that,\nDialogue: 0,0:33:32.01,0:33:33.68,EN,,0,0,0,,I have to chase through the call chain,\nDialogue: 0,0:33:34.78,0:33:36.27,EN,,0,0,0,,then look what horrible thing happens.\nDialogue: 0,0:33:37.32,0:33:41.18,EN,,0,0,0,,Well, this was called from inside sum as term, term a.\nDialogue: 0,0:33:41.76,0:33:42.38,EN,,0,0,0,,term a.\nDialogue: 0,0:33:44.78,0:33:46.19,EN,,0,0,0,,I'm looking for a value of n.\nDialogue: 0,0:33:47.35,0:33:48.40,EN,,0,0,0,,Instead of getting this one,\nDialogue: 0,0:33:48.84,0:33:49.76,EN,,0,0,0,,I get that one.\nDialogue: 0,0:33:50.70,0:33:52.54,EN,,0,0,0,,So by changing the insides of this program,\nDialogue: 0,0:33:52.86,0:33:54.09,EN,,0,0,0,,this program stops working.\nDialogue: 0,0:33:56.77,0:34:00.08,EN,,0,0,0,,So I no longer have a quantifier, as I described before.\nDialogue: 0,0:34:01.12,0:34:05.13,EN,,0,0,0,,Which is a symbol -- The lambda symbol is supposed to be a quantifier.\nDialogue: 0,0:34:05.43,0:34:06.70,EN,,0,0,0,,A thing which has the property\nDialogue: 0,0:34:06.89,0:34:11.42,EN,,0,0,0,,that the names that are bound by it are unimportant,\nDialogue: 0,0:34:12.65,0:34:15.71,EN,,0,0,0,,that I can uniformly substitute any names for these\nDialogue: 0,0:34:16.92,0:34:19.98,EN,,0,0,0,,throughout this thing, so long as they don't occur in here, the new names,\nDialogue: 0,0:34:20.94,0:34:23.16,EN,,0,0,0,,and the meaning of this expression should remain unchanged.\nDialogue: 0,0:34:24.04,0:34:25.50,EN,,0,0,0,,I've just changed the meaning of the expression\nDialogue: 0,0:34:25.53,0:34:27.20,EN,,0,0,0,,by changing the one of the names.\nDialogue: 0,0:34:28.69,0:34:30.89,EN,,0,0,0,,So lambda is no longer a well defined idea.\nDialogue: 0,0:34:32.17,0:34:33.37,EN,,0,0,0,,It's a very serious problem.\nDialogue: 0,0:34:34.55,0:34:35.55,EN,,0,0,0,,So for that reason,\nDialogue: 0,0:34:36.64,0:34:42.51,EN,,0,0,0,,I and my buddies have given up this particular kind of abstraction,\nDialogue: 0,0:34:43.13,0:34:44.36,EN,,0,0,0,,which I would like to have,\nDialogue: 0,0:34:45.61,0:34:47.50,EN,,0,0,0,,in favor of a modularity principle.\nDialogue: 0,0:34:48.09,0:34:50.20,EN,,0,0,0,,But this is the kind of experiment you can do\nDialogue: 0,0:34:51.96,0:34:53.68,EN,,0,0,0,,if you want to play with these interpreters.\nDialogue: 0,0:34:54.83,0:34:56.91,EN,,0,0,0,,You can try them out this way, that way, and the other way.\nDialogue: 0,0:34:58.11,0:35:00.25,EN,,0,0,0,,You see what makes a nicer language.\nDialogue: 0,0:35:02.68,0:35:04.49,EN,,0,0,0,,So that's a very important thing to be able to do.\nDialogue: 0,0:35:04.99,0:35:06.68,EN,,0,0,0,,Now, I would like to give you a feeling\nDialogue: 0,0:35:06.72,0:35:08.49,EN,,0,0,0,,for I think the right thing to do is here.\nDialogue: 0,0:35:09.32,0:35:12.91,EN,,0,0,0,,How are you going to, how are you going to I get this kind of\nDialogue: 0,0:35:13.04,0:35:15.34,EN,,0,0,0,,of power in a lexical system?\nDialogue: 0,0:35:16.28,0:35:17.39,EN,,0,0,0,,And the answer is, of course,\nDialogue: 0,0:35:17.55,0:35:20.03,EN,,0,0,0,,what I really want is a something that makes up for me\nDialogue: 0,0:35:20.68,0:35:22.60,EN,,0,0,0,,an exponentiator for a particular n.\nDialogue: 0,0:35:23.69,0:35:24.28,EN,,0,0,0,,Given an n,\nDialogue: 0,0:35:24.32,0:35:25.66,EN,,0,0,0,,it will make me an exponentiator.\nDialogue: 0,0:35:26.28,0:35:27.40,EN,,0,0,0,,Oh, but that's easy too.\nDialogue: 0,0:35:28.17,0:35:30.57,EN,,0,0,0,,In other words, I can write my program this way.\nDialogue: 0,0:35:35.84,0:35:37.84,EN,,0,0,0,,I'm going to define a thing called PGEN,\nDialogue: 0,0:35:40.25,0:35:42.54,EN,,0,0,0,,which is a procedure of n\nDialogue: 0,0:35:43.16,0:35:45.95,EN,,0,0,0,,which produces for me an exponentiator.\nDialogue: 0,0:35:50.24,0:35:51.23,EN,,0,0,0,,--x to the n.\nDialogue: 0,0:35:56.80,0:35:57.98,EN,,0,0,0,,Given that I have that,\nDialogue: 0,0:35:58.59,0:36:00.88,EN,,0,0,0,,then I can capture the abstraction I wanted\nDialogue: 0,0:36:01.42,0:36:03.93,EN,,0,0,0,,even better, because now it's encapsulated in a way\nDialogue: 0,0:36:04.09,0:36:06.60,EN,,0,0,0,,where I can't be destroyed by a change of names.\nDialogue: 0,0:36:07.89,0:36:12.35,EN,,0,0,0,,I can define some powers\nDialogue: 0,0:36:17.28,0:36:20.70,EN,,0,0,0,,I can define some powers to be a procedure again of a, b, and n\nDialogue: 0,0:36:21.61,0:36:26.83,EN,,0,0,0,,which is the sum of the term function\nDialogue: 0,0:36:26.88,0:36:32.32,EN,,0,0,0,,generated by using this generator, PGEN, n,\nDialogue: 0,0:36:34.40,0:36:38.01,EN,,0,0,0,,with a, incrementer, and b.\nDialogue: 0,0:36:42.49,0:36:47.95,EN,,0,0,0,,And I can define the product of powers\nDialogue: 0,0:36:54.11,0:36:58.84,EN,,0,0,0,,to be a procedure of a, b, and n\nDialogue: 0,0:36:59.80,0:37:09.96,EN,,0,0,0,,which is the product PGEN, n, with a, increment, and b.\nDialogue: 0,0:37:11.28,0:37:13.28,EN,,0,0,0,,Now, of course, this is a very simple example\nDialogue: 0,0:37:13.60,0:37:16.35,EN,,0,0,0,,where this object that I'm trying to abstract over is small.\nDialogue: 0,0:37:17.28,0:37:18.83,EN,,0,0,0,,But it could be a 100 lines of code.\nDialogue: 0,0:37:20.10,0:37:23.67,EN,,0,0,0,,And so, the purpose of this is, of course, to make it simple.\nDialogue: 0,0:37:23.67,0:37:24.57,EN,,0,0,0,,I'd give a name to it,\nDialogue: 0,0:37:24.73,0:37:26.94,EN,,0,0,0,,it's just that here it's a parameterized name.\nDialogue: 0,0:37:28.20,0:37:30.27,EN,,0,0,0,,It's a name that depends upon, explicitly,\nDialogue: 0,0:37:30.49,0:37:33.63,EN,,0,0,0,,the lexically apparent value of n.\nDialogue: 0,0:37:37.13,0:37:38.59,EN,,0,0,0,,So you can think of this as a long name.\nDialogue: 0,0:37:40.21,0:37:41.58,EN,,0,0,0,,And here, I've solved my problem\nDialogue: 0,0:37:41.76,0:37:45.82,EN,,0,0,0,,by naming my... by naming the term generation\nDialogue: 0,0:37:46.12,0:37:49.22,EN,,0,0,0,,procedures within an n in them.\nDialogue: 0,0:37:55.08,0:37:55.87,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:37:57.00,0:37:58.38,EN,,0,0,0,,Oh, yes, David.\nDialogue: 0,0:37:58.57,0:38:02.27,EN,,0,0,0,,AUDIENCE: Is the only solution to um...\nDialogue: 0,0:38:03.07,0:38:06.46,EN,,0,0,0,,the problem you raise to create another procedure?\nDialogue: 0,0:38:06.47,0:38:08.92,EN,,0,0,0,,In other words, can this only work in languages that are\nDialogue: 0,0:38:08.99,0:38:11.56,EN,,0,0,0,,capable of defining objects as procedures?\nDialogue: 0,0:38:12.41,0:38:13.76,EN,,0,0,0,,PROFESSOR: Oh, I see.\nDialogue: 0,0:38:15.90,0:38:19.74,EN,,0,0,0,,My solution to making this abstraction,\nDialogue: 0,0:38:20.14,0:38:22.86,EN,,0,0,0,,when I didn't want include the procedure inside the body,\nDialogue: 0,0:38:23.26,0:38:26.81,EN,,0,0,0,,depends upon my ability to return a procedure or export one.\nDialogue: 0,0:38:27.04,0:38:27.24,EN,,0,0,0,,AUDIENCE: And that's right.\nDialogue: 0,0:38:28.19,0:38:28.88,EN,,0,0,0,,PROFESSOR: And that's right.\nDialogue: 0,0:38:29.53,0:38:31.52,EN,,0,0,0,,If I don't have that,\nDialogue: 0,0:38:32.24,0:38:35.13,EN,,0,0,0,,then I just don't have this ability to make an abstraction in a way\nDialogue: 0,0:38:35.53,0:38:41.77,EN,,0,0,0,,where I don't have possibilities of symbol conflicts that were unanticipated.\nDialogue: 0,0:38:43.00,0:38:43.48,EN,,0,0,0,,That's right.\nDialogue: 0,0:38:44.14,0:38:46.51,EN,,0,0,0,,So one of the, the essential -- I consider, I consider\nDialogue: 0,0:38:46.54,0:38:48.91,EN,,0,0,0,,being able to return the procedural value and, therefore,\nDialogue: 0,0:38:49.20,0:38:58.28,EN,,0,0,0,,and therefore, to sort of have first class procedures, in general,\nDialogue: 0,0:38:59.13,0:39:02.46,EN,,0,0,0,,as being essential to doing very good modular programming.\nDialogue: 0,0:39:03.70,0:39:06.43,EN,,0,0,0,,Now, indeed there are many other ways to skin this cat.\nDialogue: 0,0:39:07.44,0:39:09.16,EN,,0,0,0,,What you can do is take for each of the\nDialogue: 0,0:39:09.18,0:39:11.84,EN,,0,0,0,,for each of the bad things that you have to worry about,\nDialogue: 0,0:39:12.27,0:39:15.20,EN,,0,0,0,,you can make a special feature that covers that thing.\nDialogue: 0,0:39:15.84,0:39:17.12,EN,,0,0,0,,You can make a package system.\nDialogue: 0,0:39:17.74,0:39:21.16,EN,,0,0,0,,You can make a module system as in Ada, et cetera. OK?\nDialogue: 0,0:39:22.24,0:39:24.88,EN,,0,0,0,,And all of those work, or they cover little regions of it.\nDialogue: 0,0:39:26.44,0:39:28.38,EN,,0,0,0,,The thing is that returning procedures as values\nDialogue: 0,0:39:28.41,0:39:29.74,EN,,0,0,0,,cover all of those problems.\nDialogue: 0,0:39:32.68,0:39:34.60,EN,,0,0,0,,And so it's the simplest mechanism\nDialogue: 0,0:39:35.58,0:39:37.79,EN,,0,0,0,,that gives you the best modularity,\nDialogue: 0,0:39:39.21,0:39:41.31,EN,,0,0,0,,gives you all of the known modularity mechanisms.\nDialogue: 0,0:39:45.59,0:39:48.24,EN,,0,0,0,,Well, I suppose it's time for the next break, thank you.\nDialogue: 0,0:39:48.24,0:40:01.08,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:40:01.28,0:40:04.75,EN,,0,0,0,,\nDialogue: 0,0:40:25.69,0:40:29.42,EN,,0,0,0,,\nDialogue: 0,0:40:30.01,0:40:33.28,EN,,0,0,0,,\nDialogue: 0,0:40:34.17,0:40:37.61,EN,,0,0,0,,\nDialogue: 0,0:40:42.32,0:40:44.28,EN,,0,0,0,,PROFESSOR: Well, yesterday when you learned about streams,\nDialogue: 0,0:40:46.01,0:40:51.16,EN,,0,0,0,,Hal worried to you about the order of evaluation\nDialogue: 0,0:40:51.95,0:40:53.87,EN,,0,0,0,,and delayed arguments to procedures.\nDialogue: 0,0:40:55.61,0:40:58.30,EN,,0,0,0,,The way we played with streams yesterday,\nDialogue: 0,0:41:00.25,0:41:04.22,EN,,0,0,0,,it was the responsibility of the caller and the callee\nDialogue: 0,0:41:05.77,0:41:08.84,EN,,0,0,0,,both agree that an argument was delayed,\nDialogue: 0,0:41:09.42,0:41:13.44,EN,,0,0,0,,and the callee must force the argument if it needs the answer.\nDialogue: 0,0:41:15.13,0:41:17.87,EN,,0,0,0,,So there had to be a lot of hand shaking between\nDialogue: 0,0:41:18.17,0:41:24.32,EN,,0,0,0,,the designer of a procedure and user of it over delayedness.\nDialogue: 0,0:41:26.36,0:41:28.72,EN,,0,0,0,,That turns out, of course, to be a fairly bad thing,\nDialogue: 0,0:41:29.48,0:41:30.96,EN,,0,0,0,,it works all right with streams.\nDialogue: 0,0:41:31.74,0:41:32.86,EN,,0,0,0,,But as a general thing,\nDialogue: 0,0:41:32.92,0:41:36.32,EN,,0,0,0,,what you want is an idea to have a locus,\nDialogue: 0,0:41:36.46,0:41:38.49,EN,,0,0,0,,a decision, a design decision in general,\nDialogue: 0,0:41:38.89,0:41:41.28,EN,,0,0,0,,to have a place where it's made, explicitly,\nDialogue: 0,0:41:41.63,0:41:43.93,EN,,0,0,0,,and notated in a clear way.\nDialogue: 0,0:41:45.88,0:41:49.28,EN,,0,0,0,,And so it's not a very good idea to have to have an agreement,\nDialogue: 0,0:41:50.46,0:41:54.89,EN,,0,0,0,,between the person who writes a procedure and the person who calls it,\nDialogue: 0,0:41:55.08,0:41:57.98,EN,,0,0,0,,about such details as, maybe, the arguments of evaluation,\nDialogue: 0,0:41:58.43,0:41:59.50,EN,,0,0,0,,the order of evaluation.\nDialogue: 0,0:41:59.50,0:42:00.75,EN,,0,0,0,,Although, that's not so bad.\nDialogue: 0,0:42:01.02,0:42:03.95,EN,,0,0,0,,I mean, we have other such agreements like, the input's a number.\nDialogue: 0,0:42:05.20,0:42:06.08,EN,,0,0,0,,But it would be nice if\nDialogue: 0,0:42:06.35,0:42:09.20,EN,,0,0,0,,one of these guys could take responsibility, completely.\nDialogue: 0,0:42:11.02,0:42:13.31,EN,,0,0,0,,Now this is not a new idea.\nDialogue: 0,0:42:15.51,0:42:21.16,EN,,0,0,0,,ALGOL 60 had two different ways of calling a procedure.\nDialogue: 0,0:42:22.02,0:42:24.28,EN,,0,0,0,,The arguments could be passed by name or by value.\nDialogue: 0,0:42:25.59,0:42:27.48,EN,,0,0,0,,And what that meant was that\nDialogue: 0,0:42:27.63,0:42:29.72,EN,,0,0,0,,a name argument was delayed.\nDialogue: 0,0:42:31.11,0:42:32.84,EN,,0,0,0,,That when you passed an argument by name,\nDialogue: 0,0:42:33.64,0:42:36.52,EN,,0,0,0,,that its value would only be obtained\nDialogue: 0,0:42:36.96,0:42:39.55,EN,,0,0,0,,if you accessed that argument.\nDialogue: 0,0:42:42.29,0:42:44.20,EN,,0,0,0,,So what I'd like to do now is show you,\nDialogue: 0,0:42:44.43,0:42:46.96,EN,,0,0,0,,first of all, a little bit about, again,\nDialogue: 0,0:42:46.99,0:42:48.65,EN,,0,0,0,,we're going to make a modification to a language.\nDialogue: 0,0:42:50.32,0:42:51.79,EN,,0,0,0,,In this case, we're going to add a feature.\nDialogue: 0,0:42:53.37,0:42:55.05,EN,,0,0,0,,We're going to add the feature of,\nDialogue: 0,0:42:55.36,0:42:58.73,EN,,0,0,0,,by name parameters, if you will, or delayed parameters.\nDialogue: 0,0:43:00.43,0:43:04.41,EN,,0,0,0,,Because, in fact, the default in our Lisp system\nDialogue: 0,0:43:04.76,0:43:06.60,EN,,0,0,0,,is by the value of a pointer.\nDialogue: 0,0:43:08.22,0:43:09.15,EN,,0,0,0,,A pointer is copied,\nDialogue: 0,0:43:09.15,0:43:10.91,EN,,0,0,0,,but the data structure it points at is not.\nDialogue: 0,0:43:13.41,0:43:14.84,EN,,0,0,0,,But I'd like to, in fact, show you\nDialogue: 0,0:43:15.04,0:43:18.38,EN,,0,0,0,,is how you add name arguments as well.\nDialogue: 0,0:43:19.99,0:43:22.12,EN,,0,0,0,,Now again, why would we need such a thing?\nDialogue: 0,0:43:23.10,0:43:24.72,EN,,0,0,0,,Well supposing we wanted to invent\nDialogue: 0,0:43:25.24,0:43:28.44,EN,,0,0,0,,certain kinds of what otherwise would be special forms,\nDialogue: 0,0:43:28.73,0:43:29.72,EN,,0,0,0,,reserve words?\nDialogue: 0,0:43:29.72,0:43:31.48,EN,,0,0,0,,But I'd rather not take up reserve words.\nDialogue: 0,0:43:32.18,0:43:34.76,EN,,0,0,0,,I want procedures that can do things like if.\nDialogue: 0,0:43:36.36,0:43:39.42,EN,,0,0,0,,If is special, or cond, or whatever it is.\nDialogue: 0,0:43:39.42,0:43:40.43,EN,,0,0,0,,It's the same thing.\nDialogue: 0,0:43:40.59,0:43:42.86,EN,,0,0,0,,It's special in that it determines whether or not\nDialogue: 0,0:43:42.92,0:43:45.02,EN,,0,0,0,,to evaluate the consequent or the alternative\nDialogue: 0,0:43:46.22,0:43:49.76,EN,,0,0,0,,based on the value of the predicate part of an expression.\nDialogue: 0,0:43:50.84,0:43:53.12,EN,,0,0,0,,So taking the value of one thing\nDialogue: 0,0:43:53.44,0:43:55.36,EN,,0,0,0,,determines whether or not to do something else.\nDialogue: 0,0:43:57.27,0:43:58.88,EN,,0,0,0,,Whereas all the procedures like plus,\nDialogue: 0,0:43:59.15,0:44:01.20,EN,,0,0,0,,evaluate... the ones that we can define right now,\nDialogue: 0,0:44:01.42,0:44:06.56,EN,,0,0,0,,evaluate all of their arguments before application.\nDialogue: 0,0:44:08.67,0:44:09.64,EN,,0,0,0,,So, for example,\nDialogue: 0,0:44:10.46,0:44:12.41,EN,,0,0,0,,supposing I wish to be able to define something like\nDialogue: 0,0:44:15.39,0:44:18.75,EN,,0,0,0,,the reverse of if in terms of if.\nDialogue: 0,0:44:19.85,0:44:20.70,EN,,0,0,0,,Call it unless.\nDialogue: 0,0:44:24.89,0:44:27.47,EN,,0,0,0,,We've a predicate, a consequent, and an alternative.\nDialogue: 0,0:44:28.67,0:44:30.44,EN,,0,0,0,,Now what I would like to sort of be able to do is\nDialogue: 0,0:44:30.46,0:44:32.08,EN,,0,0,0,,say-- oh, I'll do it in terms of cond.\nDialogue: 0,0:44:32.64,0:44:36.72,EN,,0,0,0,,Cond, if not the predicate,\nDialogue: 0,0:44:38.96,0:44:40.32,EN,,0,0,0,,then take the consequent,\nDialogue: 0,0:44:41.58,0:44:45.63,EN,,0,0,0,,otherwise, take the alternative.\nDialogue: 0,0:44:51.29,0:44:52.76,EN,,0,0,0,,Now, what I'd like this to mean,\nDialogue: 0,0:44:53.32,0:44:55.40,EN,,0,0,0,,is supposing I do something like this.\nDialogue: 0,0:44:56.92,0:45:04.12,EN,,0,0,0,,I'd like this unless say if equals one, 0,\nDialogue: 0,0:45:05.08,0:45:06.64,EN,,0,0,0,,then the answer is two,\nDialogue: 0,0:45:07.90,0:45:11.35,EN,,0,0,0,,otherwise, the quotient of one and 0.\nDialogue: 0,0:45:15.92,0:45:18.91,EN,,0,0,0,,What I'd like that to mean is the result of substituting\nDialogue: 0,0:45:20.00,0:45:23.26,EN,,0,0,0,,equal one, 0, and the quotient of one, 0\nDialogue: 0,0:45:23.66,0:45:24.76,EN,,0,0,0,,for p, c, and a.\nDialogue: 0,0:45:25.58,0:45:27.58,EN,,0,0,0,,I'd like that to mean, and this is funny,\nDialogue: 0,0:45:28.11,0:45:30.33,EN,,0,0,0,,I'd like it to transform into or mean\nDialogue: 0,0:45:30.75,0:45:38.44,EN,,0,0,0,,cond not equal one, 0,\nDialogue: 0,0:45:40.62,0:45:42.54,EN,,0,0,0,,then the result is two,\nDialogue: 0,0:45:44.28,0:45:45.10,EN,,0,0,0,,otherwise\nDialogue: 0,0:45:48.22,0:45:51.16,EN,,0,0,0,,I want it to be the quotient one and 0.\nDialogue: 0,0:45:54.48,0:45:56.48,EN,,0,0,0,,Now, you know that if I were to type this into Lisp,\nDialogue: 0,0:45:57.74,0:45:58.59,EN,,0,0,0,,I'd get a two.\nDialogue: 0,0:45:59.97,0:46:01.32,EN,,0,0,0,,There's no problem with that.\nDialogue: 0,0:46:02.91,0:46:04.64,EN,,0,0,0,,However, if I were to type this into Lisp,\nDialogue: 0,0:46:05.28,0:46:07.79,EN,,0,0,0,,because all the arguments are evaluated before I start,\nDialogue: 0,0:46:09.12,0:46:10.73,EN,,0,0,0,,then I'm going to get an error out of this.\nDialogue: 0,0:46:13.38,0:46:15.61,EN,,0,0,0,,So that if the substitutions work at all, of course,\nDialogue: 0,0:46:16.03,0:46:16.88,EN,,0,0,0,,I would get the right answer.\nDialogue: 0,0:46:16.88,0:46:20.16,EN,,0,0,0,,But here's a case where the substitutions don't work.\nDialogue: 0,0:46:22.17,0:46:23.86,EN,,0,0,0,,I don't get the wrong answer.\nDialogue: 0,0:46:23.86,0:46:24.67,EN,,0,0,0,,I get no answer.\nDialogue: 0,0:46:24.80,0:46:25.60,EN,,0,0,0,,I get an error.\nDialogue: 0,0:46:28.42,0:46:31.21,EN,,0,0,0,,Now, however, I'd like to be able to make my definition\nDialogue: 0,0:46:31.61,0:46:32.99,EN,,0,0,0,,so that this kind of thing works.\nDialogue: 0,0:46:34.48,0:46:36.51,EN,,0,0,0,,What I want to do is say something special\nDialogue: 0,0:46:36.70,0:46:38.76,EN,,0,0,0,,about c and a.\nDialogue: 0,0:46:39.93,0:46:43.15,EN,,0,0,0,,I want them to be delayed automatically.\nDialogue: 0,0:46:44.27,0:46:48.08,EN,,0,0,0,,I don't want them to be, I don't want them to be evaluated\nDialogue: 0,0:46:48.52,0:46:49.74,EN,,0,0,0,,at the time I call.\nDialogue: 0,0:46:51.52,0:46:52.72,EN,,0,0,0,,So I'm going to make a declaration,\nDialogue: 0,0:46:52.75,0:46:55.32,EN,,0,0,0,,and then I'm going to see how to implement such a declaration.\nDialogue: 0,0:46:55.60,0:46:57.63,EN,,0,0,0,,But again, I want you to say to yourself,\nDialogue: 0,0:46:57.79,0:47:00.25,EN,,0,0,0,,oh, this is an interesting kluge he's adding in here.\nDialogue: 0,0:47:00.76,0:47:02.16,EN,,0,0,0,,A kluge, you know.\nDialogue: 0,0:47:02.25,0:47:04.72,EN,,0,0,0,,The piles of kluges make a big complicated mess.\nDialogue: 0,0:47:05.75,0:47:09.79,EN,,0,0,0,,And is this going to foul up something else that might occur.\nDialogue: 0,0:47:10.12,0:47:12.70,EN,,0,0,0,,First of all, is it syntactically unambiguous?\nDialogue: 0,0:47:13.86,0:47:15.50,EN,,0,0,0,,Well, it will be syntactically unambiguous\nDialogue: 0,0:47:15.71,0:47:16.91,EN,,0,0,0,,with what we've seen so far.\nDialogue: 0,0:47:17.84,0:47:20.76,EN,,0,0,0,,But what I'm going to do may, in fact, cause trouble.\nDialogue: 0,0:47:21.67,0:47:24.67,EN,,0,0,0,,It may be that the thing I had will conflict with\nDialogue: 0,0:47:25.15,0:47:27.10,EN,,0,0,0,,type declarations I might want to add in the future\nDialogue: 0,0:47:28.19,0:47:31.08,EN,,0,0,0,,for giving some system, some compiler or something,\nDialogue: 0,0:47:31.21,0:47:33.66,EN,,0,0,0,,the ability to optimize given the types are known.\nDialogue: 0,0:47:34.75,0:47:36.97,EN,,0,0,0,,Or it might conflict with other types of declarations\nDialogue: 0,0:47:37.00,0:47:39.71,EN,,0,0,0,,that I might want to make about the formal parameters.\nDialogue: 0,0:47:40.57,0:47:42.56,EN,,0,0,0,,So I'm not making a general mechanism here\nDialogue: 0,0:47:43.77,0:47:45.24,EN,,0,0,0,,where I can add declarations.\nDialogue: 0,0:47:45.28,0:47:46.54,EN,,0,0,0,,And I would like to be able to do that.\nDialogue: 0,0:47:46.89,0:47:48.81,EN,,0,0,0,,But I don't want to talk about that right now.\nDialogue: 0,0:47:51.01,0:47:53.88,EN,,0,0,0,,So here I'm going to do, I'm going to build a kluge.\nDialogue: 0,0:47:57.56,0:48:08.38,EN,,0,0,0,,So we're going to define unless of a predicate--\nDialogue: 0,0:48:08.81,0:48:10.27,EN,,0,0,0,,and I'm going to call these by name--\nDialogue: 0,0:48:12.78,0:48:15.28,EN,,0,0,0,,the consequent, and name the alternative.\nDialogue: 0,0:48:19.85,0:48:25.28,EN,,0,0,0,,Huh, huh-- I got caught in the corner.\nDialogue: 0,0:48:31.76,0:48:35.61,EN,,0,0,0,,If not p then the result is c,\nDialogue: 0,0:48:36.80,0:48:41.16,EN,,0,0,0,,else-- that's what I'd like.\nDialogue: 0,0:48:44.67,0:48:46.88,EN,,0,0,0,,Where I can explicitly declare\nDialogue: 0,0:48:47.55,0:48:51.65,EN,,0,0,0,,certain of the parameters to be delayed, to be computed later.\nDialogue: 0,0:48:55.60,0:48:58.48,EN,,0,0,0,,Now, this is actually a very complicated modification to an interpreter\nDialogue: 0,0:48:58.70,0:48:59.77,EN,,0,0,0,,rather than a simple one.\nDialogue: 0,0:49:00.45,0:49:03.10,EN,,0,0,0,,The ones you saw before, dynamic binding\nDialogue: 0,0:49:03.40,0:49:06.89,EN,,0,0,0,,or adding indefinite argument procedures,\nDialogue: 0,0:49:07.50,0:49:08.52,EN,,0,0,0,,is relatively simple.\nDialogue: 0,0:49:09.28,0:49:11.28,EN,,0,0,0,,But this one changes a basic strategy.\nDialogue: 0,0:49:12.32,0:49:13.39,EN,,0,0,0,,The problem here\nDialogue: 0,0:49:13.96,0:49:17.63,EN,,0,0,0,,is that our interpreter, as written\nDialogue: 0,0:49:17.96,0:49:23.40,EN,,0,0,0,,evaluates a combination by evaluating the procedure,\nDialogue: 0,0:49:24.24,0:49:25.92,EN,,0,0,0,,the operator producing the procedure,\nDialogue: 0,0:49:26.20,0:49:30.35,EN,,0,0,0,,and evaluating the operands producing the arguments,\nDialogue: 0,0:49:30.76,0:49:35.26,EN,,0,0,0,,and then doing apply of the procedure to the arguments.\nDialogue: 0,0:49:36.38,0:49:37.07,EN,,0,0,0,,However, here,\nDialogue: 0,0:49:37.36,0:49:41.48,EN,,0,0,0,,I don't want to evaluate the operands to produce the arguments\nDialogue: 0,0:49:41.74,0:49:43.66,EN,,0,0,0,,until after I examined the procedure\nDialogue: 0,0:49:44.62,0:49:46.86,EN,,0,0,0,,to see what the procedure's declarations look like.\nDialogue: 0,0:49:49.59,0:49:50.59,EN,,0,0,0,,So let's look at that.\nDialogue: 0,0:49:52.68,0:49:56.54,EN,,0,0,0,,Here we have a changed evaluator.\nDialogue: 0,0:49:57.48,0:50:01.15,EN,,0,0,0,,I'm starting with the simple lexical evaluator,\nDialogue: 0,0:50:01.72,0:50:02.65,EN,,0,0,0,,not dynamic\nDialogue: 0,0:50:04.14,0:50:08.20,EN,,0,0,0,,but we're going to have to do something sort of similar in some ways.\nDialogue: 0,0:50:09.75,0:50:11.45,EN,,0,0,0,,Because of the fact that,\nDialogue: 0,0:50:11.90,0:50:13.34,EN,,0,0,0,,if I delay a procedure--\nDialogue: 0,0:50:13.66,0:50:15.15,EN,,0,0,0,,I'm sorry-- delay an argument to a procedure,\nDialogue: 0,0:50:15.40,0:50:17.52,EN,,0,0,0,,I'm going to have to attach and environment to it.\nDialogue: 0,0:50:19.36,0:50:21.55,EN,,0,0,0,,Remember how Hal implemented delay.\nDialogue: 0,0:50:23.38,0:50:25.44,EN,,0,0,0,,Hal implemented delay as being\nDialogue: 0,0:50:25.50,0:50:27.47,EN,,0,0,0,,a procedure of no arguments\nDialogue: 0,0:50:28.56,0:50:30.52,EN,,0,0,0,,which does some expression.\nDialogue: 0,0:50:31.18,0:50:36.94,EN,,0,0,0,,That's what delay of the expression is. --of that expression.\nDialogue: 0,0:50:39.29,0:50:40.99,EN,,0,0,0,,This turned into something like this.\nDialogue: 0,0:50:44.52,0:50:46.92,EN,,0,0,0,,Now, however, if I evaluate a lambda expression,\nDialogue: 0,0:50:47.42,0:50:49.20,EN,,0,0,0,,I have to capture the environment.\nDialogue: 0,0:50:51.41,0:50:53.45,EN,,0,0,0,,The reason why is because there are\nDialogue: 0,0:50:54.60,0:50:56.32,EN,,0,0,0,,there are variables in there\nDialogue: 0,0:50:57.02,0:51:00.83,EN,,0,0,0,,who's meaning I wish to derive from the context where this was written.\nDialogue: 0,0:51:04.01,0:51:05.76,EN,,0,0,0,,So that's why a lambda does the job.\nDialogue: 0,0:51:06.62,0:51:07.50,EN,,0,0,0,,It's the right thing.\nDialogue: 0,0:51:08.07,0:51:15.12,EN,,0,0,0,,And such that the forcing of a delayed expression\nDialogue: 0,0:51:16.52,0:51:20.08,EN,,0,0,0,,was same thing as calling that with no arguments.\nDialogue: 0,0:51:21.09,0:51:22.28,EN,,0,0,0,,It's just the opposite of this.\nDialogue: 0,0:51:24.10,0:51:26.94,EN,,0,0,0,,Producing an environment of the call\nDialogue: 0,0:51:27.36,0:51:29.90,EN,,0,0,0,,which is, in fact, the environment where this was defined\nDialogue: 0,0:51:30.81,0:51:32.36,EN,,0,0,0,,with an extra frame in it that's empty.\nDialogue: 0,0:51:33.23,0:51:34.41,EN,,0,0,0,,I don't care about that.\nDialogue: 0,0:51:36.24,0:51:39.40,EN,,0,0,0,,Well, if we go back to this slide,\nDialogue: 0,0:51:40.99,0:51:43.72,EN,,0,0,0,,since it's the case, if we look at this for a second,\nDialogue: 0,0:51:44.14,0:51:46.12,EN,,0,0,0,,everything is the same as it was before\nDialogue: 0,0:51:46.35,0:51:50.65,EN,,0,0,0,,except the case of applications or combinations.\nDialogue: 0,0:51:51.98,0:51:53.71,EN,,0,0,0,,And combinations are going to do two things.\nDialogue: 0,0:51:54.68,0:51:57.79,EN,,0,0,0,,One, is I have to evaluate the procedure--\nDialogue: 0,0:51:57.92,0:51:59.88,EN,,0,0,0,,I have to get the procedure-- by evaluating the operator.\nDialogue: 0,0:52:00.70,0:52:01.69,EN,,0,0,0,,That's what you see right here.\nDialogue: 0,0:52:02.38,0:52:04.35,EN,,0,0,0,,I have to make sure that that's current,\nDialogue: 0,0:52:04.46,0:52:05.76,EN,,0,0,0,,that is not a delayed object,\nDialogue: 0,0:52:06.36,0:52:09.85,EN,,0,0,0,,and evaluate that to the point where became it's forced now.\nDialogue: 0,0:52:10.73,0:52:12.08,EN,,0,0,0,,And then I have to somehow\nDialogue: 0,0:52:12.24,0:52:17.32,EN,,0,0,0,,apply that to the, to the operands.\nDialogue: 0,0:52:18.03,0:52:19.61,EN,,0,0,0,,But I have to keep the environment,\nDialogue: 0,0:52:19.63,0:52:20.92,EN,,0,0,0,,pass that environmental along.\nDialogue: 0,0:52:21.53,0:52:23.71,EN,,0,0,0,,So some of those operands I may have to delay.\nDialogue: 0,0:52:23.71,0:52:27.53,EN,,0,0,0,,I may have to attach that environment to those operands.\nDialogue: 0,0:52:29.66,0:52:31.52,EN,,0,0,0,,This is a rather complicated thing happening here.\nDialogue: 0,0:52:32.99,0:52:34.24,EN,,0,0,0,,Looking at that in apply.\nDialogue: 0,0:52:36.40,0:52:38.72,EN,,0,0,0,,Apply, well it has a primitive procedure\nDialogue: 0,0:52:39.36,0:52:40.60,EN,,0,0,0,,thing just like before.\nDialogue: 0,0:52:42.61,0:52:44.68,EN,,0,0,0,,But the compound one is a little more interesting.\nDialogue: 0,0:52:47.25,0:52:49.52,EN,,0,0,0,,I have to evaluate the body, just as before,\nDialogue: 0,0:52:50.48,0:52:51.98,EN,,0,0,0,,in an environment which is\nDialogue: 0,0:52:52.28,0:52:54.97,EN,,0,0,0,,which is the result of binding some\nDialogue: 0,0:52:55.61,0:53:00.29,EN,,0,0,0,,formal parameters to arguments in the environment.\nDialogue: 0,0:53:00.29,0:53:01.07,EN,,0,0,0,,That's true.\nDialogue: 0,0:53:01.53,0:53:03.82,EN,,0,0,0,,The environment is the one that comes from the procedure now.\nDialogue: 0,0:53:03.82,0:53:06.65,EN,,0,0,0,,It's a lexical language, statically bound.\nDialogue: 0,0:53:08.04,0:53:11.82,EN,,0,0,0,,However, one thing I have to do is strip off the declarations\nDialogue: 0,0:53:11.84,0:53:12.84,EN,,0,0,0,,to get the names of the variables.\nDialogue: 0,0:53:12.84,0:53:15.20,EN,,0,0,0,,That's what this guy does, vnames.\nDialogue: 0,0:53:15.45,0:53:16.67,EN,,0,0,0,,And the other thing I have to do\nDialogue: 0,0:53:16.97,0:53:18.86,EN,,0,0,0,,is process these declarations,\nDialogue: 0,0:53:19.13,0:53:21.52,EN,,0,0,0,,deciding which of these operands--\nDialogue: 0,0:53:21.76,0:53:23.92,EN,,0,0,0,,that's the operands now, as opposed to the arguments--\nDialogue: 0,0:53:24.09,0:53:25.87,EN,,0,0,0,,which of these operands to evaluate,\nDialogue: 0,0:53:26.62,0:53:30.20,EN,,0,0,0,,and which of them are to be\nDialogue: 0,0:53:30.99,0:53:33.77,EN,,0,0,0,,encapsulated in delays of some sort.\nDialogue: 0,0:53:37.28,0:53:40.08,EN,,0,0,0,,The other thing you see here is that we got a primitive,\nDialogue: 0,0:53:40.60,0:53:42.38,EN,,0,0,0,,a primitive like plus,\nDialogue: 0,0:53:42.68,0:53:45.58,EN,,0,0,0,,had better get at the real operands.\nDialogue: 0,0:53:45.82,0:53:47.39,EN,,0,0,0,,So here is a place where we're going to have to force them.\nDialogue: 0,0:53:47.92,0:53:50.38,EN,,0,0,0,,And we're going to look at what evlist is going to have to do a bunch of forces.\nDialogue: 0,0:53:51.34,0:53:52.78,EN,,0,0,0,,So we have two different kinds of evlist now.\nDialogue: 0,0:53:52.78,0:53:54.09,EN,,0,0,0,,We have evlist and gevlist.\nDialogue: 0,0:53:54.52,0:53:57.16,EN,,0,0,0,,Gevlist is going to wrap delays around some things\nDialogue: 0,0:53:57.18,0:53:59.74,EN,,0,0,0,,and force others, evaluate others.\nDialogue: 0,0:53:59.87,0:54:05.85,EN,,0,0,0,,And this guy's going to do some forcing of things.\nDialogue: 0,0:54:07.90,0:54:09.16,EN,,0,0,0,,Just looking at this a little bit,\nDialogue: 0,0:54:09.69,0:54:11.98,EN,,0,0,0,,this is a game you must play for yourself, you know.\nDialogue: 0,0:54:12.25,0:54:14.67,EN,,0,0,0,,It's not something that you're going to see all possible\nDialogue: 0,0:54:14.72,0:54:18.20,EN,,0,0,0,,variations on an evaluator talking to me.\nDialogue: 0,0:54:19.52,0:54:21.24,EN,,0,0,0,,What you have to do is do this for yourself.\nDialogue: 0,0:54:21.37,0:54:23.84,EN,,0,0,0,,And after you feel this, you play this a bit,\nDialogue: 0,0:54:24.22,0:54:27.02,EN,,0,0,0,,you get to see all the possible design decisions and what they might mean,\nDialogue: 0,0:54:27.77,0:54:29.16,EN,,0,0,0,,and how they interact with each other.\nDialogue: 0,0:54:29.93,0:54:32.38,EN,,0,0,0,,So what languages might have in them.\nDialogue: 0,0:54:33.16,0:54:34.64,EN,,0,0,0,,And what are some of the consistent sets\nDialogue: 0,0:54:34.94,0:54:36.32,EN,,0,0,0,,that make a legitimate language.\nDialogue: 0,0:54:37.20,0:54:40.06,EN,,0,0,0,,Whereas what things are complicated kluges that are just piles of junk.\nDialogue: 0,0:54:41.85,0:54:44.68,EN,,0,0,0,,So evlist of course, over here, just as I said,\nDialogue: 0,0:54:44.81,0:54:46.03,EN,,0,0,0,,is a list of operands\nDialogue: 0,0:54:46.70,0:54:50.28,EN,,0,0,0,,which are going to be undelayed after evaluation.\nDialogue: 0,0:54:50.75,0:54:51.90,EN,,0,0,0,,So these are going to be forced,\nDialogue: 0,0:54:53.28,0:54:54.44,EN,,0,0,0,,whatever that's going to mean.\nDialogue: 0,0:54:56.05,0:54:58.51,EN,,0,0,0,,And gevlist, which is the next thing--\nDialogue: 0,0:55:01.26,0:55:01.85,EN,,0,0,0,,Thank you.\nDialogue: 0,0:55:04.04,0:55:06.35,EN,,0,0,0,,What we see here, uh\nDialogue: 0,0:55:07.80,0:55:09.61,EN,,0,0,0,,well there's a couple of possibilities.\nDialogue: 0,0:55:09.81,0:55:11.52,EN,,0,0,0,,Either it's a normal, ordinary thing,\nDialogue: 0,0:55:12.48,0:55:13.69,EN,,0,0,0,,a symbol sitting there\nDialogue: 0,0:55:13.74,0:55:16.20,EN,,0,0,0,,like the predicate in the unless,\nDialogue: 0,0:55:17.64,0:55:18.81,EN,,0,0,0,,and that's what we have here.\nDialogue: 0,0:55:19.39,0:55:22.49,EN,,0,0,0,,In which case, this is intended to be evaluated in applicative order.\nDialogue: 0,0:55:23.34,0:55:25.45,EN,,0,0,0,,And it's, essentially, just what we had before.\nDialogue: 0,0:55:25.63,0:55:28.84,EN,,0,0,0,,It's mapping eval down the list.\nDialogue: 0,0:55:29.95,0:55:32.14,EN,,0,0,0,,In other words, I evaluate the first expression\nDialogue: 0,0:55:32.65,0:55:37.36,EN,,0,0,0,,and continue gevlisting the CDR of the expression in the environment.\nDialogue: 0,0:55:37.93,0:55:43.20,EN,,0,0,0,,However, it's possible that this is a name parameter.\nDialogue: 0,0:55:44.00,0:55:45.05,EN,,0,0,0,,If it's a name parameter,\nDialogue: 0,0:55:45.20,0:55:46.59,EN,,0,0,0,,I want to put a delay in\nDialogue: 0,0:55:47.00,0:55:50.97,EN,,0,0,0,,which combines that expression, which I'm calling by name,\nDialogue: 0,0:55:52.14,0:55:57.74,EN,,0,0,0,,with the environment that's available at this time\nDialogue: 0,0:55:59.05,0:56:00.59,EN,,0,0,0,,and passing that as the parameter.\nDialogue: 0,0:56:02.79,0:56:05.04,EN,,0,0,0,,And this is part of the mapping process that you see here.\nDialogue: 0,0:56:09.07,0:56:11.31,EN,,0,0,0,,The only other interesting place in this procedure\nDialogue: 0,0:56:11.37,0:56:13.53,EN,,0,0,0,,in this interpreter is cond.\nDialogue: 0,0:56:14.70,0:56:15.92,EN,,0,0,0,,People tend to write this thing,\nDialogue: 0,0:56:15.93,0:56:17.24,EN,,0,0,0,,and then they leave this one out.\nDialogue: 0,0:56:18.55,0:56:19.98,EN,,0,0,0,,There's a place where you have to force.\nDialogue: 0,0:56:20.51,0:56:23.10,EN,,0,0,0,,Conditionals have to know\nDialogue: 0,0:56:24.20,0:56:25.90,EN,,0,0,0,,whether or not the answer is true or false.\nDialogue: 0,0:56:25.99,0:56:26.83,EN,,0,0,0,,It's like a primitive.\nDialogue: 0,0:56:28.55,0:56:30.56,EN,,0,0,0,,When you do a conditional, you have to force.\nDialogue: 0,0:56:31.72,0:56:33.95,EN,,0,0,0,,Now, I'm not going to look at any more of this in any detail.\nDialogue: 0,0:56:34.62,0:56:36.28,EN,,0,0,0,,It isn't very exciting.\nDialogue: 0,0:56:36.75,0:56:38.99,EN,,0,0,0,,And what's left is how you make delays.\nDialogue: 0,0:56:38.99,0:56:40.91,EN,,0,0,0,,Well, delays are data structures\nDialogue: 0,0:56:41.31,0:56:44.75,EN,,0,0,0,,which contain an expression, an environment, and a type on them.\nDialogue: 0,0:56:44.84,0:56:46.36,EN,,0,0,0,,And it says they're a thunk.\nDialogue: 0,0:56:46.96,0:56:48.46,EN,,0,0,0,,That comes from ALGOL language,\nDialogue: 0,0:56:49.07,0:56:50.81,EN,,0,0,0,,and it's claimed to be the sound of\nDialogue: 0,0:56:50.83,0:56:52.06,EN,,0,0,0,,of something being pushed on a stack.\nDialogue: 0,0:56:52.97,0:56:53.41,EN,,0,0,0,,I don't know.\nDialogue: 0,0:56:53.41,0:56:57.12,EN,,0,0,0,,I was not an ALGOLician, so or an ALGOLite or whatever,\nDialogue: 0,0:56:57.60,0:56:58.38,EN,,0,0,0,,so I don't know.\nDialogue: 0,0:56:58.74,0:56:59.64,EN,,0,0,0,,But that's what was claimed.\nDialogue: 0,0:57:00.27,0:57:01.56,EN,,0,0,0,,And undelay is something\nDialogue: 0,0:57:01.77,0:57:03.66,EN,,0,0,0,,which will recursively undelay thunks\nDialogue: 0,0:57:03.69,0:57:06.00,EN,,0,0,0,,until the thunk becomes something which isn't a thunk.\nDialogue: 0,0:57:07.72,0:57:10.94,EN,,0,0,0,,This is the way you implement a call by name like thing in ALGOL.\nDialogue: 0,0:57:12.05,0:57:13.76,EN,,0,0,0,,And that's about all there is.\nDialogue: 0,0:57:15.21,0:57:16.25,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:57:26.68,0:57:27.52,EN,,0,0,0,,AUDIENCE: Gerry?\nDialogue: 0,0:57:28.09,0:57:28.80,EN,,0,0,0,,PROFESSOR: Yes, Vesko?\nDialogue: 0,0:57:30.03,0:57:32.99,EN,,0,0,0,,AUDIENCE: I noticed you avoided calling by name\nDialogue: 0,0:57:33.44,0:57:34.89,EN,,0,0,0,,in the primitive procedures,\nDialogue: 0,0:57:36.41,0:57:38.38,EN,,0,0,0,,I was wondering what cause you have on that?\nDialogue: 0,0:57:38.41,0:57:39.21,EN,,0,0,0,,You never need that?\nDialogue: 0,0:57:40.07,0:57:41.61,EN,,0,0,0,,PROFESSOR: Vesko is asking\nDialogue: 0,0:57:42.06,0:57:46.00,EN,,0,0,0,,if it's ever reasonable to call a primitive procedure by name?\nDialogue: 0,0:57:47.14,0:57:48.70,EN,,0,0,0,,The answer is, yes.\nDialogue: 0,0:57:49.27,0:57:52.32,EN,,0,0,0,,There's one particular case where it's reasonable, actually two.\nDialogue: 0,0:57:55.53,0:57:58.27,EN,,0,0,0,,Construction of a data structure like cons\nDialogue: 0,0:57:59.02,0:58:02.00,EN,,0,0,0,,where making an array if you have arrays with any number of elements.\nDialogue: 0,0:58:03.26,0:58:07.44,EN,,0,0,0,,OK? It's unnecessary to evaluate those arguments.\nDialogue: 0,0:58:07.44,0:58:08.83,EN,,0,0,0,,All you need is promises\nDialogue: 0,0:58:09.10,0:58:10.81,EN,,0,0,0,,to evaluate those arguments if you look at them.\nDialogue: 0,0:58:11.50,0:58:15.08,EN,,0,0,0,,If I cons together a, two things,\nDialogue: 0,0:58:16.24,0:58:17.77,EN,,0,0,0,,then I could cons together the promises\nDialogue: 0,0:58:17.80,0:58:19.93,EN,,0,0,0,,just as easily as I can cons together the things.\nDialogue: 0,0:58:21.15,0:58:23.37,EN,,0,0,0,,And it's not even when I CAR CDR them\nDialogue: 0,0:58:23.39,0:58:24.30,EN,,0,0,0,,that I have to look at them.\nDialogue: 0,0:58:24.84,0:58:26.97,EN,,0,0,0,,That just gets out the promises and passes them to somebody.\nDialogue: 0,0:58:28.26,0:58:30.51,EN,,0,0,0,,That's why the lambda calculus definition, the\nDialogue: 0,0:58:30.57,0:58:34.03,EN,,0,0,0,,the Alonzo Church definition of CAR, CDR, and cons makes sense.\nDialogue: 0,0:58:34.42,0:58:36.32,EN,,0,0,0,,It's because no work is done in CAR, CDR, and cons,\nDialogue: 0,0:58:36.38,0:58:40.06,EN,,0,0,0,,it's just shuffling data, it's just routing, if you will.\nDialogue: 0,0:58:40.99,0:58:42.20,EN,,0,0,0,,However, the things that do have\nDialogue: 0,0:58:42.24,0:58:43.84,EN,,0,0,0,,to look at data are things like plus.\nDialogue: 0,0:58:45.28,0:58:46.91,EN,,0,0,0,,Because they have a look at the bits\nDialogue: 0,0:58:47.12,0:58:48.30,EN,,0,0,0,,that the numbers are made out of,\nDialogue: 0,0:58:48.32,0:58:50.44,EN,,0,0,0,,unless they're lambda calculus numbers\nDialogue: 0,0:58:50.44,0:58:51.88,EN,,0,0,0,,which are funny. OK?\nDialogue: 0,0:58:52.43,0:58:53.58,EN,,0,0,0,,They have to look at the bits to\nDialogue: 0,0:58:53.77,0:58:55.53,EN,,0,0,0,,be able to crunch them together to do the add.\nDialogue: 0,0:58:59.21,0:58:59.92,EN,,0,0,0,,So, in fact,\nDialogue: 0,0:59:00.19,0:59:02.78,EN,,0,0,0,,data constructors, data selectors,\nDialogue: 0,0:59:03.24,0:59:05.50,EN,,0,0,0,,in fact, things that side-effect data objects\nDialogue: 0,0:59:06.27,0:59:09.76,EN,,0,0,0,,don't need to do, don't need to do any forcing\nDialogue: 0,0:59:11.34,0:59:13.39,EN,,0,0,0,,in the laziest possible interpreters.\nDialogue: 0,0:59:16.46,0:59:16.99,EN,,0,0,0,,On the other hand\nDialogue: 0,0:59:17.02,0:59:18.70,EN,,0,0,0,,predicates on data structures have to.\nDialogue: 0,0:59:19.61,0:59:22.65,EN,,0,0,0,,If you want to say, is this a, is this a pair?\nDialogue: 0,0:59:23.56,0:59:24.40,EN,,0,0,0,,Or is it a symbol?\nDialogue: 0,0:59:24.64,0:59:26.57,EN,,0,0,0,,Well, you better find out. You got to look at it then.\nDialogue: 0,0:59:30.30,0:59:31.18,EN,,0,0,0,,Any other questions?\nDialogue: 0,0:59:40.05,0:59:41.61,EN,,0,0,0,,Oh, well, I suppose it's time for a break.\nDialogue: 0,0:00:00.01,0:00:01.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N张大伟\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:01.63,0:00:09.15,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:09.52,0:00:13.66,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 II\nDialogue: 0,0:00:17.21,0:00:17.96,Default,,0,0,0,,教授：目前为止\nDialogue: 0,0:00:19.52,0:00:21.29,Default,,0,0,0,,我们学的东西都非常有趣\nDialogue: 0,0:00:21.52,0:00:23.05,Default,,0,0,0,,但它有什么实际的用途吗？\nDialogue: 0,0:00:26.33,0:00:27.96,Default,,0,0,0,,我想答案是“是的”\nDialogue: 0,0:00:29.38,0:00:31.92,Default,,0,0,0,,这些元循环解释器\nDialogue: 0,0:00:32.96,0:00:34.60,Default,,0,0,0,,非常值得琢磨\nDialogue: 0,0:00:34.62,0:00:36.17,Default,,0,0,0,,我花了大概\nDialogue: 0,0:00:38.05,0:00:41.85,Default,,0,0,0,,曾几何时 我花了半年的功夫\nDialogue: 0,0:00:42.86,0:00:45.26,Default,,0,0,0,,用上节课讲的那种\nDialogue: 0,0:00:45.76,0:00:48.19,Default,,0,0,0,,元循环解释器来试验\nDialogue: 0,0:00:49.47,0:00:52.01,Default,,0,0,0,,各种各样的设计变种\nDialogue: 0,0:00:52.57,0:00:54.11,Default,,0,0,0,,用元循环解释器是因为\nDialogue: 0,0:00:54.72,0:00:56.94,Default,,0,0,0,,它们通过自己定义自己\nDialogue: 0,0:00:56.97,0:00:59.71,Default,,0,0,0,,因此被解释的语言也包含了自己\nDialogue: 0,0:01:01.27,0:01:03.87,Default,,0,0,0,,这样的解释器是一种的媒介\nDialogue: 0,0:01:03.88,0:01:05.58,Default,,0,0,0,,方便我们探索语言问题\nDialogue: 0,0:01:06.80,0:01:09.44,Default,,0,0,0,,如果你想添加一个新的FEATURE\nDialogue: 0,0:01:10.51,0:01:12.38,Default,,0,0,0,,这就是小菜一碟\nDialogue: 0,0:01:12.73,0:01:15.10,Default,,0,0,0,,你只需要稍作修改 然后观察结果\nDialogue: 0,0:01:15.49,0:01:17.20,Default,,0,0,0,,在尝试了一会儿新语言后\nDialogue: 0,0:01:17.24,0:01:18.24,Default,,0,0,0,,你可能觉得它不好\nDialogue: 0,0:01:18.52,0:01:19.47,Default,,0,0,0,,就把它扔到一边去了\nDialogue: 0,0:01:20.96,0:01:23.55,Default,,0,0,0,,或者你也想研究\nDialogue: 0,0:01:23.64,0:01:27.37,Default,,0,0,0,,不同绑定策略的差异\nDialogue: 0,0:01:28.81,0:01:31.90,Default,,0,0,0,,或者是一些更复杂的东西\nDialogue: 0,0:01:33.72,0:01:35.48,Default,,0,0,0,,事实上 这些元循环解释器\nDialogue: 0,0:01:36.17,0:01:37.88,Default,,0,0,0,,非常适合作为交换媒介\nDialogue: 0,0:01:38.20,0:01:42.56,Default,,0,0,0,,用于承载人们关于语言设计想法\nDialogue: 0,0:01:43.98,0:01:45.74,Default,,0,0,0,,因为它们易于理解\nDialogue: 0,0:01:46.28,0:01:48.46,Default,,0,0,0,,它们短小、紧凑而且简洁\nDialogue: 0,0:01:49.32,0:01:50.80,Default,,0,0,0,,如果我有一些点子\nDialogue: 0,0:01:51.53,0:01:53.77,Default,,0,0,0,,想让其它人评论一下\nDialogue: 0,0:01:54.25,0:01:58.32,Default,,0,0,0,,比如Indiana大学的Dan Friedman教授\nDialogue: 0,0:01:59.05,0:02:02.00,Default,,0,0,0,,我就编写一个小型元循环解释器\nDialogue: 0,0:02:02.56,0:02:03.79,Default,,0,0,0,,然后给他发一封电子邮件\nDialogue: 0,0:02:04.65,0:02:05.45,Default,,0,0,0,,并附上解释器\nDialogue: 0,0:02:05.45,0:02:07.90,Default,,0,0,0,,他就可以在计算机上安装并运行\nDialogue: 0,0:02:07.92,0:02:09.82,Default,,0,0,0,,可能他会觉得这个设计并不好\nDialogue: 0,0:02:11.94,0:02:13.10,Default,,0,0,0,,然后他会给我回一封邮件\nDialogue: 0,0:02:13.13,0:02:14.83,Default,,0,0,0,,“为什么不试试这个 这个更好一点”\nDialogue: 0,0:02:16.88,0:02:19.36,Default,,0,0,0,,所以我将会讲一些这方面的技术\nDialogue: 0,0:02:20.16,0:02:24.20,Default,,0,0,0,,因为在设计你自己的特定用途语言时\nDialogue: 0,0:02:24.72,0:02:28.68,Default,,0,0,0,,这种简单的技术非常重要\nDialogue: 0,0:02:30.79,0:02:32.08,Default,,0,0,0,,我们试着先在Lisp中\nDialogue: 0,0:02:32.51,0:02:34.21,Default,,0,0,0,,添加一个非常简单的FEATURE\nDialogue: 0,0:02:40.64,0:02:44.37,Default,,0,0,0,,在这之前 我先来谈谈FEATURE吧\nDialogue: 0,0:02:49.56,0:02:52.17,Default,,0,0,0,,很多语言添加了大量的FEATURE\nDialogue: 0,0:02:53.05,0:02:54.91,Default,,0,0,0,,把它们本身搞得混乱不堪\nDialogue: 0,0:02:56.86,0:02:58.38,Default,,0,0,0,,计算机科学家有一个笑话\nDialogue: 0,0:02:59.28,0:03:02.52,Default,,0,0,0,,“这不是BUG 这是FEATURE”\nDialogue: 0,0:03:05.03,0:03:06.46,Default,,0,0,0,,而我宁愿认为\nDialogue: 0,0:03:08.91,0:03:11.44,Default,,0,0,0,,很多系统都在遭受着“功能蔓延”的影响\nDialogue: 0,0:03:12.82,0:03:13.44,Default,,0,0,0,,比方说\nDialogue: 0,0:03:14.94,0:03:18.16,Default,,0,0,0,,George希望系统中有某个FEATURE\nDialogue: 0,0:03:18.72,0:03:19.36,Default,,0,0,0,,他就加了进来\nDialogue: 0,0:03:20.17,0:03:22.14,Default,,0,0,0,,Harry也想着\nDialogue: 0,0:03:22.17,0:03:24.20,Default,,0,0,0,,这个系统现在也不是我喜欢的那个了\nDialogue: 0,0:03:24.24,0:03:25.92,Default,,0,0,0,,然后加入了自己最喜欢的FEATURE\nDialogue: 0,0:03:26.64,0:03:30.24,Default,,0,0,0,,Jim也这样做\nDialogue: 0,0:03:30.83,0:03:31.79,Default,,0,0,0,,一段时间过后\nDialogue: 0,0:03:31.80,0:03:34.81,Default,,0,0,0,,操作手册就多达500页\nDialogue: 0,0:03:35.15,0:03:36.51,Default,,0,0,0,,以至于没人能看得懂\nDialogue: 0,0:03:37.79,0:03:39.32,Default,,0,0,0,,有时候也可能只是\nDialogue: 0,0:03:39.90,0:03:41.37,Default,,0,0,0,,同一个人在添加FEATURE\nDialogue: 0,0:03:41.39,0:03:43.23,Default,,0,0,0,,也会导致同样糟糕的结果\nDialogue: 0,0:03:44.14,0:03:46.09,Default,,0,0,0,,很多情况下 比如编辑器\nDialogue: 0,0:03:47.37,0:03:49.12,Default,,0,0,0,,具有很多FEATURE就很合理\nDialogue: 0,0:03:50.92,0:03:52.65,Default,,0,0,0,,因为你想要能够完成\nDialogue: 0,0:03:52.68,0:03:53.76,Default,,0,0,0,,各种不同的事情\nDialogue: 0,0:03:56.11,0:03:57.29,Default,,0,0,0,,但对计算机语言来说\nDialogue: 0,0:03:57.85,0:03:58.91,Default,,0,0,0,,我认为太多的FEATURE\nDialogue: 0,0:04:00.01,0:04:01.29,Default,,0,0,0,,是一个灾难\nDialogue: 0,0:04:04.03,0:04:08.00,Default,,0,0,0,,另外 系统也可能变成某种“尖叫的怪物”\nDialogue: 0,0:04:09.52,0:04:11.39,Default,,0,0,0,,假设你有一个盒子\nDialogue: 0,0:04:11.80,0:04:15.29,Default,,0,0,0,,它有一个鼠标和花哨的显示器\nDialogue: 0,0:04:15.95,0:04:20.04,Default,,0,0,0,,这些花哨的IO带来了各种各样的复杂性\nDialogue: 0,0:04:21.01,0:04:22.80,Default,,0,0,0,,你的程序语言就变成了\nDialogue: 0,0:04:23.34,0:04:25.37,Default,,0,0,0,,阴暗无用的小玩意儿\nDialogue: 0,0:04:25.40,0:04:27.90,Default,,0,0,0,,这是由计算机上的视窗系统进行的\nDialogue: 0,0:04:28.09,0:04:29.36,Default,,0,0,0,,内存换页和磁盘抖动所导致的\nDialogue: 0,0:04:30.08,0:04:31.82,Default,,0,0,0,,每当你使用计算机的时候\nDialogue: 0,0:04:31.93,0:04:33.45,Default,,0,0,0,,鼠标处理进程就会唤醒\nDialogue: 0,0:04:33.85,0:04:35.95,Default,,0,0,0,,你有什么事情要我做的吗？\nDialogue: 0,0:04:36.14,0:04:37.23,Default,,0,0,0,,然后又回去休眠\nDialogue: 0,0:04:37.44,0:04:39.44,Default,,0,0,0,,如果你的胳膊肘不小心碰到了鼠标\nDialogue: 0,0:04:39.61,0:04:42.32,Default,,0,0,0,,一大堆烟雾就会从你的电脑出来 类似于这样\nDialogue: 0,0:04:42.94,0:04:45.29,Default,,0,0,0,,这就是由于添加FEATURE\nDialogue: 0,0:04:45.55,0:04:47.21,Default,,0,0,0,,导致系统不能用的两种典型情况\nDialogue: 0,0:04:47.50,0:04:49.73,Default,,0,0,0,,现在我们要添加的是 一个非常简单的FEATURE\nDialogue: 0,0:04:52.60,0:04:53.77,Default,,0,0,0,,这个FEATURE非常好\nDialogue: 0,0:04:53.85,0:04:56.17,Default,,0,0,0,,事实上 Lisp中就有这个FEATURE\nDialogue: 0,0:04:57.25,0:04:58.17,Default,,0,0,0,,我们都知道\nDialogue: 0,0:04:59.29,0:05:03.13,Default,,0,0,0,,像+、*这样的过程\nDialogue: 0,0:05:03.37,0:05:04.89,Default,,0,0,0,,可以接受不定数目的参数\nDialogue: 0,0:05:05.43,0:05:06.44,Default,,0,0,0,,因此我们就可以写\nDialogue: 0,0:05:06.57,0:05:10.94,Default,,0,0,0,,(+ (* A X X)\nDialogue: 0,0:05:12.09,0:05:16.99,Default,,0,0,0,,(* B X) C)\nDialogue: 0,0:05:17.54,0:05:18.68,Default,,0,0,0,,这里可以看到\nDialogue: 0,0:05:18.92,0:05:21.76,Default,,0,0,0,,+有两到三个参数\nDialogue: 0,0:05:22.30,0:05:24.81,Default,,0,0,0,,*也有两到三个参数\nDialogue: 0,0:05:25.08,0:05:26.76,Default,,0,0,0,,不管多少个参数\nDialogue: 0,0:05:26.78,0:05:28.49,Default,,0,0,0,,都应该用同样的方式对待\nDialogue: 0,0:05:30.00,0:05:32.17,Default,,0,0,0,,支持不定数目的参数\nDialogue: 0,0:05:32.28,0:05:34.01,Default,,0,0,0,,这一点非常有用\nDialogue: 0,0:05:34.96,0:05:38.41,Default,,0,0,0,,而我上节课所讲的Lisp求值器\nDialogue: 0,0:05:39.23,0:05:41.85,Default,,0,0,0,,只能处理固定数目的参数\nDialogue: 0,0:05:42.62,0:05:45.28,Default,,0,0,0,,因为我要用BIND过程中的PAIR-UP过程\nDialogue: 0,0:05:45.63,0:05:47.92,Default,,0,0,0,,让形式参数与实际参数一一对应\nDialogue: 0,0:05:50.81,0:05:53.80,Default,,0,0,0,,假如我想能够定义像这样的过程\nDialogue: 0,0:05:54.89,0:05:57.32,Default,,0,0,0,,它们可以接收任意个数的参数\nDialogue: 0,0:05:58.75,0:06:00.40,Default,,0,0,0,,这个问题有好几部分\nDialogue: 0,0:06:01.34,0:06:04.81,Default,,0,0,0,,首先是挑选合适的语法描述\nDialogue: 0,0:06:05.72,0:06:11.21,Default,,0,0,0,,我们需要能够标注额外的参数\nDialogue: 0,0:06:12.17,0:06:13.63,Default,,0,0,0,,标注那些不知道个数的参数\nDialogue: 0,0:06:15.48,0:06:16.62,Default,,0,0,0,,另外就是\nDialogue: 0,0:06:17.10,0:06:18.70,Default,,0,0,0,,一旦我们标注出来后\nDialogue: 0,0:06:19.07,0:06:20.78,Default,,0,0,0,,我们怎样解释这些个记号\nDialogue: 0,0:06:21.74,0:06:23.10,Default,,0,0,0,,才能得到\nDialogue: 0,0:06:23.85,0:06:25.37,Default,,0,0,0,,正确的结果呢？\nDialogue: 0,0:06:26.98,0:06:28.80,Default,,0,0,0,,让我们来考虑一种\nDialogue: 0,0:06:28.84,0:06:30.27,Default,,0,0,0,,我们可能会遇到的情况\nDialogue: 0,0:06:33.07,0:06:34.51,Default,,0,0,0,,比如说\nDialogue: 0,0:06:35.42,0:06:37.34,Default,,0,0,0,,我想要定义这样的一个过程\nDialogue: 0,0:06:37.95,0:06:41.36,Default,,0,0,0,,它有一个必选参数X\nDialogue: 0,0:06:42.20,0:06:45.26,Default,,0,0,0,,还有个可选参数 -- 或者说一堆参数\nDialogue: 0,0:06:45.28,0:06:47.23,Default,,0,0,0,,我不知道它们的数目 就记作Y吧\nDialogue: 0,0:06:49.09,0:06:50.36,Default,,0,0,0,,X是必选的\nDialogue: 0,0:06:55.88,0:06:57.44,Default,,0,0,0,,然而有很多参数Y\nDialogue: 0,0:06:59.53,0:07:05.99,Default,,0,0,0,,这些参数形成的表 -- 我就记作Y\nDialogue: 0,0:07:14.48,0:07:16.06,Default,,0,0,0,,写好了参数表\nDialogue: 0,0:07:16.09,0:07:17.68,Default,,0,0,0,,我现在要这样定义过程体\nDialogue: 0,0:07:19.02,0:07:21.98,Default,,0,0,0,,我要对每一个元素都做同样的处理\nDialogue: 0,0:07:22.52,0:07:25.76,Default,,0,0,0,,(MAP (LAMBDA (U)\nDialogue: 0,0:07:27.00,0:07:34.54,Default,,0,0,0,,(* X U)) Y)\nDialogue: 0,0:07:36.89,0:07:38.04,Default,,0,0,0,,这里 我用了一个“点号”\nDialogue: 0,0:07:38.59,0:07:41.31,Default,,0,0,0,,来表明点号后面的东西\nDialogue: 0,0:07:42.19,0:07:44.30,Default,,0,0,0,,是剩下的所有参数构成的表\nDialogue: 0,0:07:46.30,0:07:48.12,Default,,0,0,0,,这就是一个语法规范\nDialogue: 0,0:07:53.32,0:07:54.64,Default,,0,0,0,,为什么这样来写呢？\nDialogue: 0,0:07:55.71,0:07:58.06,Default,,0,0,0,,这种语法规范之所以合理\nDialogue: 0,0:07:59.77,0:08:01.96,Default,,0,0,0,,是因为Lisp的源码读取器\nDialogue: 0,0:08:02.00,0:08:03.60,Default,,0,0,0,,刚好使用这种语法\nDialogue: 0,0:08:04.41,0:08:07.15,Default,,0,0,0,,来表示序对\nDialogue: 0,0:08:08.94,0:08:11.08,Default,,0,0,0,,我们之前没有介绍过\nDialogue: 0,0:08:11.08,0:08:12.78,Default,,0,0,0,,你在自己尝试的时候可能遇到过\nDialogue: 0,0:08:13.04,0:08:14.62,Default,,0,0,0,,当你调用(CONS X Y)时\nDialogue: 0,0:08:14.89,0:08:18.12,Default,,0,0,0,,你会得到 X . Y\nDialogue: 0,0:08:19.79,0:08:22.83,Default,,0,0,0,,准确来说是(X . Y)\nDialogue: 0,0:08:23.08,0:08:24.64,Default,,0,0,0,,两边还有括号\nDialogue: 0,0:08:26.98,0:08:28.16,Default,,0,0,0,,举例来说吧\nDialogue: 0,0:08:28.97,0:08:35.04,Default,,0,0,0,,这里的(X . Y)对应着一个序对\nDialogue: 0,0:08:36.33,0:08:39.29,Default,,0,0,0,,X是CAR部分 Y是CDR部分\nDialogue: 0,0:08:41.48,0:08:43.98,Default,,0,0,0,,你们目前为止见过的其它记号\nDialogue: 0,0:08:44.94,0:08:46.67,Default,,0,0,0,,是像\nDialogue: 0,0:08:46.92,0:08:55.24,Default,,0,0,0,,(LAMBDA (X Y Z) ...)这样的\nDialogue: 0,0:08:55.71,0:08:57.63,Default,,0,0,0,,它们则是像这样的\nDialogue: 0,0:09:02.00,0:09:03.61,Default,,0,0,0,,就拿形式参数表来说\nDialogue: 0,0:09:04.22,0:09:05.29,Default,,0,0,0,,它实际上是这样\nDialogue: 0,0:09:09.93,0:09:17.32,Default,,0,0,0,,这里分别是 X、Y、Z和空表\nDialogue: 0,0:09:18.28,0:09:21.08,Default,,0,0,0,,如果我有一个想要与之匹配的参数表的话\nDialogue: 0,0:09:22.60,0:09:25.60,Default,,0,0,0,,假设实际参数表是'(1 2 3)\nDialogue: 0,0:09:25.87,0:09:27.26,Default,,0,0,0,,我想把它们和形参相匹配\nDialogue: 0,0:09:28.38,0:09:37.10,Default,,0,0,0,,所以这里 可能有个三个元素的表\nDialogue: 0,0:09:42.44,0:09:46.94,Default,,0,0,0,,分别是1、2、3\nDialogue: 0,0:09:48.99,0:09:53.16,Default,,0,0,0,,用'(1 2 3)来匹配'(X Y Z)\nDialogue: 0,0:09:54.22,0:09:56.28,Default,,0,0,0,,很显然1和X相匹配\nDialogue: 0,0:09:56.32,0:09:58.01,Default,,0,0,0,,因为我可以顺着这个结构来\nDialogue: 0,0:09:58.86,0:10:01.56,Default,,0,0,0,,2和Y相匹配\nDialogue: 0,0:10:02.46,0:10:04.04,Default,,0,0,0,,3和Z相匹配\nDialogue: 0,0:10:05.48,0:10:09.53,Default,,0,0,0,,假设我现在要把这个(X . Y)\nDialogue: 0,0:10:09.55,0:10:11.84,Default,,0,0,0,,这个是(X . Y)\nDialogue: 0,0:10:12.51,0:10:16.91,Default,,0,0,0,,如果我想把它跟'(1 2 3)相匹配的话\nDialogue: 0,0:10:19.08,0:10:20.00,Default,,0,0,0,,我们再来看\nDialogue: 0,0:10:28.00,0:10:30.32,Default,,0,0,0,,这里是1、2、3\nDialogue: 0,0:10:30.86,0:10:32.88,Default,,0,0,0,,我可以沿着这里遍历\nDialogue: 0,0:10:32.99,0:10:35.50,Default,,0,0,0,,会发现 1和X相匹配\nDialogue: 0,0:10:37.56,0:10:41.84,Default,,0,0,0,,而Y和表'(2 3)相匹配\nDialogue: 0,0:10:43.74,0:10:46.22,Default,,0,0,0,,所以这里选用的表示法\nDialogue: 0,0:10:46.41,0:10:50.16,Default,,0,0,0,,对于Lisp来说是非常自然的\nDialogue: 0,0:10:52.66,0:10:54.14,Default,,0,0,0,,所以我就选择用这个记号\nDialogue: 0,0:10:54.17,0:10:55.80,Default,,0,0,0,,来表示数目不定的参数\nDialogue: 0,0:10:58.29,0:11:00.09,Default,,0,0,0,,还有一种可能性\nDialogue: 0,0:11:00.59,0:11:02.78,Default,,0,0,0,,如果我不是特别想命名某个参数\nDialogue: 0,0:11:03.00,0:11:05.00,Default,,0,0,0,,或者是命名某两个参数之类的\nDialogue: 0,0:11:06.54,0:11:07.56,Default,,0,0,0,,如果我不想那样的话\nDialogue: 0,0:11:08.78,0:11:10.44,Default,,0,0,0,,如果我想像+那样\nDialogue: 0,0:11:10.52,0:11:12.52,Default,,0,0,0,,一下子引用所有的参数\nDialogue: 0,0:11:13.88,0:11:17.96,Default,,0,0,0,,那么我就应该把参数表写成\nDialogue: 0,0:11:18.20,0:11:23.45,Default,,0,0,0,,(LAMBDA X ...)\nDialogue: 0,0:11:25.14,0:11:26.30,Default,,0,0,0,,举例来说\nDialogue: 0,0:11:26.81,0:11:27.96,Default,,0,0,0,,如果我定义一个过程\nDialogue: 0,0:11:28.06,0:11:30.44,Default,,0,0,0,,它把接收所有的参数\nDialogue: 0,0:11:31.12,0:11:32.70,Default,,0,0,0,,然后返回一个由它们组成的表X\nDialogue: 0,0:11:34.81,0:11:38.67,Default,,0,0,0,,返回的结果就是过程的参数表 明白吗？\nDialogue: 0,0:11:45.85,0:11:46.67,Default,,0,0,0,,这又是怎么回事呢？\nDialogue: 0,0:11:46.84,0:11:50.06,Default,,0,0,0,,实际上 无论我们的参数表是何种形式\nDialogue: 0,0:11:50.60,0:11:51.45,Default,,0,0,0,,无论是何种形式\nDialogue: 0,0:11:51.61,0:11:53.68,Default,,0,0,0,,都要与实际参数表相匹配\nDialogue: 0,0:11:55.14,0:11:57.14,Default,,0,0,0,,现在 这个符号就是所有的实际参数了\nDialogue: 0,0:12:01.49,0:12:05.13,Default,,0,0,0,,所以 我选择使用这个特定的语法规范\nDialogue: 0,0:12:05.64,0:12:07.63,Default,,0,0,0,,来描述那些\nDialogue: 0,0:12:08.04,0:12:10.56,Default,,0,0,0,,接收不定数目参数的过程\nDialogue: 0,0:12:13.45,0:12:14.60,Default,,0,0,0,,一共有两种情况\nDialogue: 0,0:12:15.40,0:12:16.35,Default,,0,0,0,,上面这种和下面这种\nDialogue: 0,0:12:17.44,0:12:18.36,Default,,0,0,0,,这两种都 --\nDialogue: 0,0:12:18.42,0:12:20.11,Default,,0,0,0,,当你们在制定语法规范时\nDialogue: 0,0:12:20.44,0:12:22.54,Default,,0,0,0,,千万注意不要有歧义\nDialogue: 0,0:12:23.56,0:12:27.36,Default,,0,0,0,,就比如说这里的两种情况\nDialogue: 0,0:12:27.66,0:12:31.20,Default,,0,0,0,,就不要与这里我们已有的这种混淆了\nDialogue: 0,0:12:33.61,0:12:35.82,Default,,0,0,0,,我总是可以区分出\nDialogue: 0,0:12:36.54,0:12:39.80,Default,,0,0,0,,过程的形式参数\nDialogue: 0,0:12:40.28,0:12:41.76,Default,,0,0,0,,是数目固定的具名参数\nDialogue: 0,0:12:42.64,0:12:43.13,Default,,0,0,0,,还是\nDialogue: 0,0:12:43.28,0:12:45.36,Default,,0,0,0,,既有数目固定的具名参数\nDialogue: 0,0:12:45.44,0:12:48.01,Default,,0,0,0,,又跟着数目可变的参数\nDialogue: 0,0:12:49.42,0:12:53.52,Default,,0,0,0,,又或者是所有参数组成的表\nDialogue: 0,0:12:53.68,0:12:56.52,Default,,0,0,0,,这个表会和这里的形式参数X相匹配\nDialogue: 0,0:12:56.99,0:12:58.84,Default,,0,0,0,,我都是可以从语法上区分它们\nDialogue: 0,0:13:02.25,0:13:04.62,Default,,0,0,0,,由于语言中存在语法歧义\nDialogue: 0,0:13:05.04,0:13:08.03,Default,,0,0,0,,整个待解释的程序被错误地分段\nDialogue: 0,0:13:08.64,0:13:13.92,Default,,0,0,0,,从而导致了可怕的错误\nDialogue: 0,0:13:14.56,0:13:16.67,Default,,0,0,0,,类Algol语言中就有些传统问题\nDialogue: 0,0:13:16.67,0:13:23.47,Default,,0,0,0,,就跟谓词部分的嵌套IF语句有关\nDialogue: 0,0:13:25.06,0:13:25.93,Default,,0,0,0,,总之\nDialogue: 0,0:13:27.52,0:13:29.44,Default,,0,0,0,,我现在已经把语法告诉你们了\nDialogue: 0,0:13:30.27,0:13:34.83,Default,,0,0,0,,我们要怎么来处理它的语义呢？\nDialogue: 0,0:13:35.25,0:13:36.11,Default,,0,0,0,,我们如何来解释它？\nDialogue: 0,0:13:36.59,0:13:37.96,Default,,0,0,0,,其实很简单\nDialogue: 0,0:13:38.44,0:13:42.57,Default,,0,0,0,,我修改一下元循环解释器就行\nDialogue: 0,0:13:43.71,0:13:44.76,Default,,0,0,0,,只需修改一行\nDialogue: 0,0:13:45.98,0:13:46.57,Default,,0,0,0,,在这里\nDialogue: 0,0:13:47.53,0:13:49.56,Default,,0,0,0,,我修改一下PAIR-UP过程\nDialogue: 0,0:13:50.81,0:13:54.19,Default,,0,0,0,,这里的PAIR-UP过程把\nDialogue: 0,0:13:56.76,0:14:02.03,Default,,0,0,0,,这是从上节课的元循环求值器中\nDialogue: 0,0:14:04.81,0:14:09.56,Default,,0,0,0,,摘录过来的PAIR-UP过程\nDialogue: 0,0:14:12.16,0:14:16.68,Default,,0,0,0,,它把形式参数与传递过来的实际参数匹配起来\nDialogue: 0,0:14:18.96,0:14:21.93,Default,,0,0,0,,大部分地方都和以前一样\nDialogue: 0,0:14:22.67,0:14:23.23,Default,,0,0,0,,也就是说\nDialogue: 0,0:14:23.31,0:14:25.07,Default,,0,0,0,,如果变量表为空\nDialogue: 0,0:14:25.52,0:14:27.31,Default,,0,0,0,,并且值表也为空\nDialogue: 0,0:14:27.45,0:14:29.61,Default,,0,0,0,,就返回空表\nDialogue: 0,0:14:31.05,0:14:33.00,Default,,0,0,0,,否则就是参数过多\nDialogue: 0,0:14:33.98,0:14:40.19,Default,,0,0,0,,如果变量表为空 但值表非空\nDialogue: 0,0:14:41.58,0:14:44.00,Default,,0,0,0,,如果值表为空\nDialogue: 0,0:14:44.96,0:14:47.47,Default,,0,0,0,,但是变量表又非空\nDialogue: 0,0:14:47.48,0:14:48.56,Default,,0,0,0,,那就是实际参数少了\nDialogue: 0,0:14:48.94,0:14:51.31,Default,,0,0,0,,然而如果我有一个变量是符号的话\nDialogue: 0,0:14:55.53,0:14:56.49,Default,,0,0,0,,这就有意思了\nDialogue: 0,0:14:58.30,0:15:04.40,Default,,0,0,0,,那么 我就认为遇到了特殊情况\nDialogue: 0,0:15:04.59,0:15:06.51,Default,,0,0,0,,也就是尾部分为符号的情况\nDialogue: 0,0:15:08.35,0:15:14.11,Default,,0,0,0,,情况就像这里的一样\nDialogue: 0,0:15:14.90,0:15:17.87,Default,,0,0,0,,这个尾部分就是一个符号Y\nDialogue: 0,0:15:18.63,0:15:19.39,Default,,0,0,0,,它不是NIL\nDialogue: 0,0:15:20.73,0:15:21.72,Default,,0,0,0,,不是个空表\nDialogue: 0,0:15:23.26,0:15:25.60,Default,,0,0,0,,而这个一开始就是个符号\nDialogue: 0,0:15:25.98,0:15:26.81,Default,,0,0,0,,就没有别的东西了\nDialogue: 0,0:15:27.79,0:15:28.72,Default,,0,0,0,,这种情况下\nDialogue: 0,0:15:29.96,0:15:37.20,Default,,0,0,0,,我就用这个符号去匹配所有的值\nDialogue: 0,0:15:38.03,0:15:42.52,Default,,0,0,0,,并把它们添加到要返回的结果中\nDialogue: 0,0:15:44.50,0:15:46.91,Default,,0,0,0,,否则的话 我就像正常情况那样\nDialogue: 0,0:15:47.15,0:15:48.52,Default,,0,0,0,,来创建所有的配对\nDialogue: 0,0:15:52.02,0:15:53.82,Default,,0,0,0,,我认为这很容易理解\nDialogue: 0,0:15:54.51,0:15:55.84,Default,,0,0,0,,就是这些\nDialogue: 0,0:15:57.08,0:15:58.33,Default,,0,0,0,,现在 答疑时间\nDialogue: 0,0:16:02.62,0:16:05.05,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:16:06.60,0:16:06.94,Default,,0,0,0,,你说\nDialogue: 0,0:16:07.37,0:16:09.92,Default,,0,0,0,,学生：你能再解释一下第三种形式吗？\nDialogue: 0,0:16:09.98,0:16:12.12,Default,,0,0,0,,教授：第三种？这个？\nDialogue: 0,0:16:12.59,0:16:14.27,Default,,0,0,0,,或许你用表结构来思考\nDialogue: 0,0:16:14.30,0:16:16.24,Default,,0,0,0,,会更容易理解一些\nDialogue: 0,0:16:18.57,0:16:22.73,Default,,0,0,0,,这是一个过程 包含一个LAMBDA\nDialogue: 0,0:16:25.85,0:16:29.61,Default,,0,0,0,,我画出来的这个表结构就代表上面的这个\nDialogue: 0,0:16:31.26,0:16:32.44,Default,,0,0,0,,这里是X\nDialogue: 0,0:16:32.73,0:16:33.98,Default,,0,0,0,,这些是我们的符号\nDialogue: 0,0:16:37.41,0:16:39.58,Default,,0,0,0,,过程体就是X而已\nDialogue: 0,0:16:44.84,0:16:48.75,Default,,0,0,0,,如果我需要这个过程的形式参数表\nDialogue: 0,0:16:50.09,0:16:51.58,Default,,0,0,0,,我就取它的CADR部分\nDialogue: 0,0:16:52.14,0:16:53.16,Default,,0,0,0,,我会得到一个符号\nDialogue: 0,0:16:54.01,0:16:57.16,Default,,0,0,0,,所以我们的匹配器 -- 也就是我给你们展示的PAIR-UP过程\nDialogue: 0,0:16:58.24,0:17:00.44,Default,,0,0,0,,就会把这个符号对象\nDialogue: 0,0:17:01.56,0:17:04.40,Default,,0,0,0,,跟我们传递的实际参数表相匹配了\nDialogue: 0,0:17:05.76,0:17:09.55,Default,,0,0,0,,这个符号与实际参数表相绑定\nDialogue: 0,0:17:11.37,0:17:16.48,Default,,0,0,0,,而在这个例子中 如果我去取它的话\nDialogue: 0,0:17:16.92,0:17:20.97,Default,,0,0,0,,匹配器就会把它与变量表的这个部分相匹配\nDialogue: 0,0:17:24.14,0:17:26.14,Default,,0,0,0,,如果一个过程只是\nDialogue: 0,0:17:26.17,0:17:29.13,Default,,0,0,0,,直接返回得到的参数表的话 返回的就是一个表\nDialogue: 0,0:17:30.40,0:17:31.39,Default,,0,0,0,,这个过程就是这样的\nDialogue: 0,0:17:34.51,0:17:35.48,Default,,0,0,0,,好吧 谢谢大家\nDialogue: 0,0:17:36.14,0:17:37.28,Default,,0,0,0,,大家休息一下吧\nDialogue: 0,0:17:37.83,0:17:55.36,Default,,0,0,0,,[音乐]\nDialogue: 0,0:17:55.36,0:17:59.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:18:03.53,0:18:07.56,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:18:07.56,0:18:11.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:18:12.25,0:18:16.11,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 II\nDialogue: 0,0:18:20.86,0:18:21.61,Default,,0,0,0,,教授：我们接着来看\nDialogue: 0,0:18:23.26,0:18:26.32,Default,,0,0,0,,现在 我将介绍一种相当重要的变种\nDialogue: 0,0:18:27.45,0:18:31.04,Default,,0,0,0,,这种变体非常有名\nDialogue: 0,0:18:31.60,0:18:36.80,Default,,0,0,0,,早期的很多Lisp都支持它\nDialogue: 0,0:18:38.25,0:18:40.06,Default,,0,0,0,,它被称为变量的动态绑定\nDialogue: 0,0:18:41.77,0:18:44.68,Default,,0,0,0,,我们现在来研究一下它\nDialogue: 0,0:18:47.62,0:18:50.16,Default,,0,0,0,,我先来介绍一下是什么导致\nDialogue: 0,0:18:50.35,0:18:52.36,Default,,0,0,0,,人们产生这样的想法\nDialogue: 0,0:18:53.74,0:18:55.23,Default,,0,0,0,,然而我并不会直接点明原因\nDialogue: 0,0:18:55.40,0:18:57.60,Default,,0,0,0,,我来举一个例子 你们来感受一下\nDialogue: 0,0:18:58.64,0:18:59.93,Default,,0,0,0,,假设\nDialogue: 0,0:19:00.75,0:19:02.59,Default,,0,0,0,,我们再来考察一下\nDialogue: 0,0:19:05.02,0:19:06.43,Default,,0,0,0,,计算一系列数之和的SUM过程\nDialogue: 0,0:19:08.14,0:19:09.47,Default,,0,0,0,,它的参数为\nDialogue: 0,0:19:09.60,0:19:10.78,Default,,0,0,0,,计算当前项的TERM\nDialogue: 0,0:19:13.04,0:19:14.41,Default,,0,0,0,,下界A\nDialogue: 0,0:19:15.24,0:19:17.04,Default,,0,0,0,,计算下一项索引的NEXT\nDialogue: 0,0:19:17.24,0:19:18.56,Default,,0,0,0,,上界B\nDialogue: 0,0:19:19.36,0:19:20.16,Default,,0,0,0,,过程体是\nDialogue: 0,0:19:23.16,0:19:26.94,Default,,0,0,0,,如果A>B\nDialogue: 0,0:19:27.15,0:19:28.64,Default,,0,0,0,,那么结果就是0\nDialogue: 0,0:19:30.24,0:19:31.08,Default,,0,0,0,,否则就是\nDialogue: 0,0:19:33.68,0:19:39.82,Default,,0,0,0,,(+ (TERM A)\nDialogue: 0,0:19:40.60,0:19:44.24,Default,,0,0,0,,(SUM TERM\nDialogue: 0,0:19:47.68,0:19:52.64,Default,,0,0,0,,(NEXT A)\nDialogue: 0,0:20:00.30,0:20:03.56,Default,,0,0,0,,这个NEXT过程直接传递过去\nDialogue: 0,0:20:06.40,0:20:08.25,Default,,0,0,0,,上界B也直接传递过去\nDialogue: 0,0:20:14.51,0:20:15.76,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:20:17.82,0:20:21.45,Default,,0,0,0,,当我使用SUM过程的时候\nDialogue: 0,0:20:21.96,0:20:24.35,Default,,0,0,0,,我可以像这样来用\nDialogue: 0,0:20:25.45,0:20:38.04,Default,,0,0,0,,我们可以把SUM-POWERS过程定义为\nDialogue: 0,0:20:38.08,0:20:40.33,Default,,0,0,0,,这个函数是用来计算Σ(X^N)的\nDialogue: 0,0:20:41.10,0:20:45.93,Default,,0,0,0,,它的参数有A、B以及N\nDialogue: 0,0:20:45.95,0:20:47.69,Default,,0,0,0,,分别指下界、上界以及指数\nDialogue: 0,0:20:48.06,0:20:53.34,Default,,0,0,0,,它的定义是(SUM (LAMBDA (X)\nDialogue: 0,0:20:53.60,0:20:59.31,Default,,0,0,0,,这个参数为X的过程计算(EXPT X N)\nDialogue: 0,0:21:02.19,0:21:09.29,Default,,0,0,0,,我们还要传递A、1+还有B\nDialogue: 0,0:21:11.82,0:21:15.76,Default,,0,0,0,,因此 给定一系列X 我们计算Σ(X^N)的值\nDialogue: 0,0:21:16.14,0:21:19.74,Default,,0,0,0,,X从A到B取值 步长为1\nDialogue: 0,0:21:22.94,0:21:24.38,Default,,0,0,0,,我也可以定义--\nDialogue: 0,0:21:27.68,0:21:28.20,Default,,0,0,0,,好像这里有点问题\nDialogue: 0,0:21:29.78,0:21:31.02,Default,,0,0,0,,不好意思\nDialogue: 0,0:21:31.91,0:21:33.36,Default,,0,0,0,,这里应该是PRODUCT-POWERS\nDialogue: 0,0:21:38.08,0:21:39.12,Default,,0,0,0,,名字有点奇怪\nDialogue: 0,0:21:40.02,0:21:40.80,Default,,0,0,0,,还是不改了\nDialogue: 0,0:21:41.96,0:21:46.32,Default,,0,0,0,,有点怪 就按原来的吧\nDialogue: 0,0:21:49.34,0:21:50.19,Default,,0,0,0,,这回应该对了\nDialogue: 0,0:21:51.37,0:21:53.82,Default,,0,0,0,,而PRODUCT-POWERS的定义则是\nDialogue: 0,0:21:58.41,0:22:02.36,Default,,0,0,0,,（意义不明）\nDialogue: 0,0:22:03.00,0:22:06.81,Default,,0,0,0,,我可以用像SUM一样的过程\nDialogue: 0,0:22:06.81,0:22:08.22,Default,,0,0,0,,只不过是用来计算乘积的\nDialogue: 0,0:22:08.56,0:22:11.05,Default,,0,0,0,,但是很类似 就跟你们在那里见到的一样\nDialogue: 0,0:22:11.45,0:22:16.38,Default,,0,0,0,,它也是一个三参数的过程\nDialogue: 0,0:22:17.00,0:22:25.42,Default,,0,0,0,,求积的因数是通过构造而来\nDialogue: 0,0:22:25.66,0:22:31.60,Default,,0,0,0,,也就是(PRODUCT (LAMBDA (X) (EXPT X N))\nDialogue: 0,0:22:34.43,0:22:37.85,Default,,0,0,0,,下界是A 步长为1 上界为B\nDialogue: 0,0:22:41.53,0:22:41.88,Default,,0,0,0,,现在\nDialogue: 0,0:22:46.83,0:22:49.50,Default,,0,0,0,,你可能马上就意识到一些问题\nDialogue: 0,0:22:50.75,0:22:52.01,Default,,0,0,0,,它们看起来几乎一样\nDialogue: 0,0:22:53.18,0:22:55.20,Default,,0,0,0,,为什么要重复写代码呢？\nDialogue: 0,0:22:56.59,0:22:59.72,Default,,0,0,0,,现在就很像我们之前遇到的情况了\nDialogue: 0,0:23:01.00,0:23:03.15,Default,,0,0,0,,构建一个抽象不是更好吗？\nDialogue: 0,0:23:03.81,0:23:05.76,Default,,0,0,0,,如何构建良好的抽象呢？\nDialogue: 0,0:23:05.85,0:23:07.55,Default,,0,0,0,,我看到有一些完全相同的代码\nDialogue: 0,0:23:08.47,0:23:09.32,Default,,0,0,0,,这有一段\nDialogue: 0,0:23:09.98,0:23:11.08,Default,,0,0,0,,这是另一段\nDialogue: 0,0:23:14.45,0:23:16.22,Default,,0,0,0,,所以我应该把它们提取出来\nDialogue: 0,0:23:17.09,0:23:19.23,Default,,0,0,0,,我就会想\nDialogue: 0,0:23:20.51,0:23:22.67,Default,,0,0,0,,SUM-POWERS可以用\nDialogue: 0,0:23:22.88,0:23:24.52,Default,,0,0,0,,NTH-POWERS的过程来编写\nDialogue: 0,0:23:25.71,0:23:27.40,Default,,0,0,0,,假如有人想写一个\nDialogue: 0,0:23:27.74,0:23:30.03,Default,,0,0,0,,稍微不同的过程 就像这个一样\nDialogue: 0,0:23:37.63,0:23:45.18,Default,,0,0,0,,(DEFINE SUM-POWERS\nDialogue: 0,0:23:46.44,0:23:48.46,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:23:48.75,0:23:52.27,Default,,0,0,0,,(SUM (NTH-POWER\nDialogue: 0,0:23:53.88,0:23:55.42,Default,,0,0,0,,我们调用过程NTH-POWER\nDialogue: 0,0:23:58.35,0:24:02.27,Default,,0,0,0,,下界为A 步长为1 上界为B\nDialogue: 0,0:24:05.74,0:24:06.91,Default,,0,0,0,,类似地\nDialogue: 0,0:24:10.65,0:24:12.76,Default,,0,0,0,,我想用这种方式来重写PRODUCT-POWERS\nDialogue: 0,0:24:12.89,0:24:15.24,Default,,0,0,0,,把求幂指数从这里抽象出来\nDialogue: 0,0:24:16.27,0:24:17.37,Default,,0,0,0,,可以这样写\nDialogue: 0,0:24:22.10,0:24:23.02,Default,,0,0,0,,(DEFINE PRODUCT-POWERS\nDialogue: 0,0:24:29.48,0:24:34.94,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:24:35.31,0:24:42.33,Default,,0,0,0,,(PRODUCT NTH-POWERS\nDialogue: 0,0:24:46.44,0:24:50.30,Default,,0,0,0,,A 1+ B)))\nDialogue: 0,0:24:53.50,0:24:57.56,Default,,0,0,0,,把NTH-POWER的结果作为PRODUCT的参数\nDialogue: 0,0:24:58.38,0:25:00.24,Default,,0,0,0,,我们还需要定义\nDialogue: 0,0:25:02.04,0:25:03.88,Default,,0,0,0,,还需要定义过程NTH-POWERS\nDialogue: 0,0:25:04.89,0:25:05.93,Default,,0,0,0,,我把它写在这边\nDialogue: 0,0:25:12.22,0:25:12.99,Default,,0,0,0,,写在上面\nDialogue: 0,0:25:25.41,0:25:29.04,Default,,0,0,0,,它是一个参数为X的过程\nDialogue: 0,0:25:29.60,0:25:34.56,Default,,0,0,0,,计算(EXPT X N)\nDialogue: 0,0:25:35.93,0:25:36.96,Default,,0,0,0,,但是我遇到一个问题\nDialogue: 0,0:25:38.64,0:25:39.93,Default,,0,0,0,,我们使用的环境模型\nDialogue: 0,0:25:40.57,0:25:43.23,Default,,0,0,0,,我们用来解释\nDialogue: 0,0:25:44.00,0:25:45.95,Default,,0,0,0,,目前所定义的语言的这种手段\nDialogue: 0,0:25:46.27,0:25:48.81,Default,,0,0,0,,并没有给我说明这个N的值\nDialogue: 0,0:25:52.76,0:25:59.26,Default,,0,0,0,,因为 正如大家所知\nDialogue: 0,0:26:00.76,0:26:04.25,Default,,0,0,0,,在这个过程中 N是自由变量\nDialogue: 0,0:26:06.41,0:26:07.98,Default,,0,0,0,,环境模型告诉我们\nDialogue: 0,0:26:08.60,0:26:10.20,Default,,0,0,0,,自由变量的值\nDialogue: 0,0:26:11.21,0:26:14.99,Default,,0,0,0,,取决于过程被定义时所在的环境\nDialogue: 0,0:26:16.64,0:26:17.47,Default,,0,0,0,,在我编写它们的时候\nDialogue: 0,0:26:17.48,0:26:19.84,Default,,0,0,0,,就假设它们已经在黑板上被定义了\nDialogue: 0,0:26:21.64,0:26:23.63,Default,,0,0,0,,NTH-POWER是定义在全局环境下的\nDialogue: 0,0:26:24.06,0:26:25.15,Default,,0,0,0,,其中没有N的定义\nDialogue: 0,0:26:25.93,0:26:27.63,Default,,0,0,0,,因此 N是未绑定的变量\nDialogue: 0,0:26:28.72,0:26:31.66,Default,,0,0,0,,但对我们来说\nDialogue: 0,0:26:32.60,0:26:36.32,Default,,0,0,0,,我们明确希望它是这里和这里的N\nDialogue: 0,0:26:38.99,0:26:42.67,Default,,0,0,0,,另外一方面\nDialogue: 0,0:26:42.84,0:26:44.28,Default,,0,0,0,,当然我们要十分小心地确保\nDialogue: 0,0:26:44.56,0:26:46.06,Default,,0,0,0,,这里的N是这里的N\nDialogue: 0,0:26:48.96,0:26:52.83,Default,,0,0,0,,还有这里的这个 要跟这里的一致\nDialogue: 0,0:26:57.39,0:26:59.74,Default,,0,0,0,,这种想法造就了\nDialogue: 0,0:27:00.67,0:27:02.72,Default,,0,0,0,,一个非常著名的BUG\nDialogue: 0,0:27:04.65,0:27:06.04,Default,,0,0,0,,我来细说下这个BUG\nDialogue: 0,0:27:07.15,0:27:09.40,Default,,0,0,0,,请看这张幻灯片\nDialogue: 0,0:27:10.66,0:27:12.70,Default,,0,0,0,,这种想法被称作“动态绑定”\nDialogue: 0,0:27:13.99,0:27:16.91,Default,,0,0,0,,在这种情况下 自由变量不再被\nDialogue: 0,0:27:17.76,0:27:21.23,Default,,0,0,0,,定义过程时的环境所解释\nDialogue: 0,0:27:22.40,0:27:25.16,Default,,0,0,0,,这种情况下 自由变量的值\nDialogue: 0,0:27:25.44,0:27:29.31,Default,,0,0,0,,就像是存储在过程调用者的环境中一样\nDialogue: 0,0:27:31.85,0:27:34.84,Default,,0,0,0,,所以在这个系统中\nDialogue: 0,0:27:34.86,0:27:39.68,Default,,0,0,0,,你需要不断地搜索调用过程的调用者的环境\nDialogue: 0,0:27:40.43,0:27:42.65,Default,,0,0,0,,当然 在本例中\nDialogue: 0,0:27:42.84,0:27:44.30,Default,,0,0,0,,无论NTH-POWER在何处定义\nDialogue: 0,0:27:44.33,0:27:45.98,Default,,0,0,0,,它都是在PRODUCT过程中被调用的\nDialogue: 0,0:27:46.41,0:27:48.68,Default,,0,0,0,,我就需要在SUM过程中再编写一个类似的过程\nDialogue: 0,0:27:50.51,0:27:54.92,Default,,0,0,0,,而PRODUCT又是被PRODUCT-POWERS所调用\nDialogue: 0,0:27:55.13,0:27:56.14,Default,,0,0,0,,就是你们在这里看到的\nDialogue: 0,0:27:56.83,0:27:59.37,Default,,0,0,0,,由于PRODUCT-POWERS过程绑定了变量N\nDialogue: 0,0:28:00.09,0:28:04.09,Default,,0,0,0,,因此NTH-POWER中的N会从这个链中派生出来\nDialogue: 0,0:28:08.14,0:28:09.64,Default,,0,0,0,,相似地 这个N\nDialogue: 0,0:28:10.11,0:28:12.01,Default,,0,0,0,,NTH-POWER中的N在这种情况下\nDialogue: 0,0:28:12.32,0:28:15.80,Default,,0,0,0,,可能是来自于这里SUM过程的调用\nDialogue: 0,0:28:15.80,0:28:18.27,Default,,0,0,0,,你们可以从这里看到 它在SUM内部被调用\nDialogue: 0,0:28:20.73,0:28:21.69,Default,,0,0,0,,对应这里的TERM\nDialogue: 0,0:28:22.90,0:28:25.72,Default,,0,0,0,,而SUM是在SUM-POWERS的内部被调用\nDialogue: 0,0:28:26.94,0:28:27.96,Default,,0,0,0,,后者绑定了N\nDialogue: 0,0:28:28.93,0:28:30.65,Default,,0,0,0,,因此这里就有一个N\nDialogue: 0,0:28:32.75,0:28:36.11,Default,,0,0,0,,可供NTH-POWER中的N取值\nDialogue: 0,0:28:37.95,0:28:39.24,Default,,0,0,0,,这就是动态 --\nDialogue: 0,0:28:39.28,0:28:43.10,Default,,0,0,0,,这条白线以下的东西 再加上这部分\nDialogue: 0,0:28:43.31,0:28:46.04,Default,,0,0,0,,就是我们所谓的动态绑定\nDialogue: 0,0:28:46.59,0:28:49.00,Default,,0,0,0,,用动态绑定的角度来解释 就可以正常运行\nDialogue: 0,0:28:50.85,0:28:52.65,Default,,0,0,0,,现在 让我们来看一个例子\nDialogue: 0,0:28:54.54,0:28:55.99,Default,,0,0,0,,要怎么实现这个功能\nDialogue: 0,0:28:55.99,0:28:56.96,Default,,0,0,0,,非常简单\nDialogue: 0,0:28:57.48,0:28:59.34,Default,,0,0,0,,事实上 最早的Lisp实现\nDialogue: 0,0:29:00.01,0:29:02.52,Default,,0,0,0,,对自由变量有各种形式的解释\nDialogue: 0,0:29:03.31,0:29:05.98,Default,,0,0,0,,包括用动态绑定来解释自由变量\nDialogue: 0,0:29:06.40,0:29:10.14,Default,,0,0,0,,APL也是用动态绑定来解释自由变量的\nDialogue: 0,0:29:11.68,0:29:14.32,Default,,0,0,0,,而不是词法绑定 或者说静态绑定\nDialogue: 0,0:29:15.22,0:29:17.00,Default,,0,0,0,,当然 要从EVAL开始修改\nDialogue: 0,0:29:19.31,0:29:20.59,Default,,0,0,0,,只需修改两个地方就行\nDialogue: 0,0:29:22.78,0:29:25.61,Default,,0,0,0,,首先我们会发现\nDialogue: 0,0:29:26.52,0:29:28.49,Default,,0,0,0,,事情变得更简单了\nDialogue: 0,0:29:29.39,0:29:33.63,Default,,0,0,0,,如果我不需要\nDialogue: 0,0:29:33.64,0:29:36.20,Default,,0,0,0,,在定义过程的那个环境中求值\nDialogue: 0,0:29:36.44,0:29:38.04,Default,,0,0,0,,过程在定义的时候就无需\nDialogue: 0,0:29:38.43,0:29:40.17,Default,,0,0,0,,捕获当时的环境了\nDialogue: 0,0:29:42.03,0:29:44.96,Default,,0,0,0,,所以我们可以在幻灯片的这里看到\nDialogue: 0,0:29:45.84,0:29:50.08,Default,,0,0,0,,这条用于判断是否为LAMBDA表达式的子句\nDialogue: 0,0:29:50.73,0:29:52.43,Default,,0,0,0,,过程就是在这个时候创建的\nDialogue: 0,0:29:53.92,0:29:56.73,Default,,0,0,0,,就不会返回一个带有类型标签\nDialogue: 0,0:29:56.75,0:30:01.05,Default,,0,0,0,,和环境结构的过程对象了\nDialogue: 0,0:30:01.29,0:30:02.54,Default,,0,0,0,,就是EXP本身\nDialogue: 0,0:30:02.54,0:30:04.76,Default,,0,0,0,,而我们会在其它地方用某种方式来解耦\nDialogue: 0,0:30:06.44,0:30:09.40,Default,,0,0,0,,另外一处修改就是组合式的应用\nDialogue: 0,0:30:10.36,0:30:13.69,Default,,0,0,0,,应用的时候必须要取得调用者的环境\nDialogue: 0,0:30:14.29,0:30:17.24,Default,,0,0,0,,调用者的环境就在这里\nDialogue: 0,0:30:17.26,0:30:19.45,Default,,0,0,0,,如果表达式是一个过程应用--\nDialogue: 0,0:30:19.56,0:30:21.63,Default,,0,0,0,,如果我们求值的是一个组合式\nDialogue: 0,0:30:21.79,0:30:23.71,Default,,0,0,0,,我们就会调用一个组合式\nDialogue: 0,0:30:23.93,0:30:25.50,Default,,0,0,0,,调用一个过程\nDialogue: 0,0:30:25.66,0:30:27.37,Default,,0,0,0,,来取得运算符的值\nDialogue: 0,0:30:29.84,0:30:31.44,Default,,0,0,0,,调用者的环境\nDialogue: 0,0:30:31.98,0:30:34.51,Default,,0,0,0,,就是我们当前的环境\nDialogue: 0,0:30:35.89,0:30:40.72,Default,,0,0,0,,所以 我只需要要把这个环境传递给APPLY\nDialogue: 0,0:30:41.49,0:30:42.75,Default,,0,0,0,,我们再来看看APPLY\nDialogue: 0,0:30:43.58,0:30:44.97,Default,,0,0,0,,我们只需要\nDialogue: 0,0:30:45.71,0:30:48.41,Default,,0,0,0,,把参数列表加上一个环境ENV\nDialogue: 0,0:30:48.78,0:30:55.68,Default,,0,0,0,,然后用这个环境来扩展环境\nDialogue: 0,0:30:56.67,0:30:59.02,Default,,0,0,0,,扩展把形式参数\nDialogue: 0,0:30:59.02,0:31:01.37,Default,,0,0,0,,和传递过来的实际参数绑定在一起的环境\nDialogue: 0,0:31:03.08,0:31:05.98,Default,,0,0,0,,而不再是之前由过程捕获的环境了\nDialogue: 0,0:31:06.81,0:31:09.45,Default,,0,0,0,,最早的Lisp偶然地采用了\nDialogue: 0,0:31:09.66,0:31:11.96,Default,,0,0,0,,这种最显然的方式实现\nDialogue: 0,0:31:14.13,0:31:16.68,Default,,0,0,0,,当然 像往常一样 人们习惯了并喜欢上了它\nDialogue: 0,0:31:17.25,0:31:18.27,Default,,0,0,0,,因此就有一些人说\nDialogue: 0,0:31:18.40,0:31:19.50,Default,,0,0,0,,“就应该这么来做”\nDialogue: 0,0:31:21.59,0:31:24.09,Default,,0,0,0,,不幸的是 这导致一些严重的问题\nDialogue: 0,0:31:25.40,0:31:27.24,Default,,0,0,0,,最严重的一点是\nDialogue: 0,0:31:27.53,0:31:29.84,Default,,0,0,0,,采用动态绑定\nDialogue: 0,0:31:31.00,0:31:33.56,Default,,0,0,0,,破坏了模块性\nDialogue: 0,0:31:35.46,0:31:37.66,Default,,0,0,0,,如果有两个人在一个大型系统上协同工作\nDialogue: 0,0:31:38.57,0:31:40.01,Default,,0,0,0,,那么一个重要的原则就是\nDialogue: 0,0:31:40.35,0:31:42.19,Default,,0,0,0,,每个人所使用的名字\nDialogue: 0,0:31:42.99,0:31:44.58,Default,,0,0,0,,都不应该干扰到对方的名字\nDialogue: 0,0:31:47.93,0:31:50.78,Default,,0,0,0,,如果我写了一段代码\nDialogue: 0,0:31:51.07,0:31:53.13,Default,,0,0,0,,别人就不能通过在他代码内部\nDialogue: 0,0:31:53.88,0:31:56.57,Default,,0,0,0,,使用我代码中的名字来破坏我的代码\nDialogue: 0,0:31:56.75,0:31:57.71,Default,,0,0,0,,这一点很重要\nDialogue: 0,0:31:59.85,0:32:00.46,Default,,0,0,0,,然而\nDialogue: 0,0:32:01.04,0:32:05.18,Default,,0,0,0,,动态绑定明显地违背了这种特定的模块化约束\nDialogue: 0,0:32:06.67,0:32:08.08,Default,,0,0,0,,我们考虑一下\nDialogue: 0,0:32:09.18,0:32:10.35,Default,,0,0,0,,这段代码会有什么效果？\nDialogue: 0,0:32:12.54,0:32:13.79,Default,,0,0,0,,假设我想要把\nDialogue: 0,0:32:15.47,0:32:19.81,Default,,0,0,0,,我想要把变量NEXT换个名字\nDialogue: 0,0:32:19.81,0:32:24.41,Default,,0,0,0,,假设某个人要编写SUM过程\nDialogue: 0,0:32:25.10,0:32:26.68,Default,,0,0,0,,而别人则会使用这个SUM过程\nDialogue: 0,0:32:28.97,0:32:30.32,Default,,0,0,0,,编写SUM的那个人\nDialogue: 0,0:32:30.49,0:32:32.30,Default,,0,0,0,,可以选择他想要使用的名字\nDialogue: 0,0:32:33.66,0:32:34.84,Default,,0,0,0,,假设我就是那个编写者\nDialogue: 0,0:32:36.83,0:32:39.30,Default,,0,0,0,,刚巧 这里我不想用NEXT来表示\nDialogue: 0,0:32:39.30,0:32:40.09,Default,,0,0,0,,而是用N来表示\nDialogue: 0,0:32:41.74,0:32:43.10,Default,,0,0,0,,所以我把所有出现NEXT的地方\nDialogue: 0,0:32:44.28,0:32:45.26,Default,,0,0,0,,都换成N\nDialogue: 0,0:32:48.14,0:32:48.48,Default,,0,0,0,,哎呀\nDialogue: 0,0:32:49.94,0:32:52.22,Default,,0,0,0,,我没有改变这个程序的规范\nDialogue: 0,0:32:53.32,0:32:54.86,Default,,0,0,0,,但是整个程序就崩溃了\nDialogue: 0,0:32:56.11,0:32:57.96,Default,,0,0,0,,不仅如此 这边也出现了问题\nDialogue: 0,0:32:59.50,0:33:01.40,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:33:02.26,0:33:03.24,Default,,0,0,0,,答案非常明显\nDialogue: 0,0:33:04.48,0:33:09.29,Default,,0,0,0,,NTH-POWER中的变量N的值\nDialogue: 0,0:33:09.31,0:33:13.72,Default,,0,0,0,,也就是这个N和这个N\nDialogue: 0,0:33:14.97,0:33:17.16,Default,,0,0,0,,根据环境模型的定义\nDialogue: 0,0:33:17.20,0:33:19.58,Default,,0,0,0,,这两个N总是相关的\nDialogue: 0,0:33:19.87,0:33:21.48,Default,,0,0,0,,如果是根据环境模型的定义的话\nDialogue: 0,0:33:21.55,0:33:23.63,Default,,0,0,0,,因为N在这里被绑定\nDialogue: 0,0:33:24.37,0:33:26.25,Default,,0,0,0,,这个LAMBDA表达式是在\nDialogue: 0,0:33:26.59,0:33:28.59,Default,,0,0,0,,N被绑定的环境中执行的\nDialogue: 0,0:33:30.70,0:33:31.84,Default,,0,0,0,,如果不用环境模型的话\nDialogue: 0,0:33:32.01,0:33:33.68,Default,,0,0,0,,我必须追踪过程的调用链\nDialogue: 0,0:33:34.78,0:33:36.27,Default,,0,0,0,,那么就会发生糟糕的事儿\nDialogue: 0,0:33:37.32,0:33:41.18,Default,,0,0,0,,在SUM内部 这个是作为TERM调用的\nDialogue: 0,0:33:41.76,0:33:42.38,Default,,0,0,0,,这里的(TERM A)\nDialogue: 0,0:33:44.78,0:33:46.19,Default,,0,0,0,,这时再来查找N的值\nDialogue: 0,0:33:47.35,0:33:48.40,Default,,0,0,0,,我得到的不知这个值\nDialogue: 0,0:33:48.84,0:33:49.76,Default,,0,0,0,,而是这个值\nDialogue: 0,0:33:50.70,0:33:52.54,Default,,0,0,0,,因此 只是这个程序的内部做了修改\nDialogue: 0,0:33:52.86,0:33:54.09,Default,,0,0,0,,这个程序却崩溃了\nDialogue: 0,0:33:56.77,0:34:00.08,Default,,0,0,0,,LAMBDA就不再像我以前说得那样是个量词了\nDialogue: 0,0:34:01.12,0:34:05.13,Default,,0,0,0,,LAMBDA应该是一个量词\nDialogue: 0,0:34:05.43,0:34:06.70,Default,,0,0,0,,量词有一个性质\nDialogue: 0,0:34:06.89,0:34:11.42,Default,,0,0,0,,被它绑定的名字都不重要\nDialogue: 0,0:34:12.65,0:34:15.71,Default,,0,0,0,,只要我用不在过程体中的新名字\nDialogue: 0,0:34:16.92,0:34:19.98,Default,,0,0,0,,统一地在过程体中代换旧名字\nDialogue: 0,0:34:20.94,0:34:23.16,Default,,0,0,0,,就不会改变表达式的语义\nDialogue: 0,0:34:24.04,0:34:25.50,Default,,0,0,0,,而我刚才却通过修改一个名字\nDialogue: 0,0:34:25.53,0:34:27.20,Default,,0,0,0,,改变了表达式的语义\nDialogue: 0,0:34:28.69,0:34:30.89,Default,,0,0,0,,因此LAMBDA就不再是一个良好定义的量词了\nDialogue: 0,0:34:32.17,0:34:33.37,Default,,0,0,0,,这个问题非常严重\nDialogue: 0,0:34:34.55,0:34:35.55,Default,,0,0,0,,正是因为这个原因\nDialogue: 0,0:34:36.64,0:34:42.51,Default,,0,0,0,,我和同事放弃了这种抽象方法\nDialogue: 0,0:34:43.13,0:34:44.36,Default,,0,0,0,,相对的 我更喜欢\nDialogue: 0,0:34:45.61,0:34:47.50,Default,,0,0,0,,模块化原则\nDialogue: 0,0:34:48.09,0:34:50.20,Default,,0,0,0,,如果你愿意探索解释器\nDialogue: 0,0:34:51.96,0:34:53.68,Default,,0,0,0,,那就非常值得做这类实验\nDialogue: 0,0:34:54.83,0:34:56.91,Default,,0,0,0,,你可以尝试多种设计\nDialogue: 0,0:34:58.11,0:35:00.25,Default,,0,0,0,,探索更优雅的语言设计\nDialogue: 0,0:35:02.68,0:35:04.49,Default,,0,0,0,,这是元循环求值器非常重要的功能\nDialogue: 0,0:35:04.99,0:35:06.68,Default,,0,0,0,,现在 我也想讲一讲\nDialogue: 0,0:35:06.72,0:35:08.49,Default,,0,0,0,,这种情况下的正确做法\nDialogue: 0,0:35:09.32,0:35:12.91,Default,,0,0,0,,我又如何来获得这种\nDialogue: 0,0:35:13.04,0:35:15.34,Default,,0,0,0,,词法作用域的能力呢？\nDialogue: 0,0:35:16.28,0:35:17.39,Default,,0,0,0,,当然 实际情况是\nDialogue: 0,0:35:17.55,0:35:20.03,Default,,0,0,0,,在这里我想要的是\nDialogue: 0,0:35:20.68,0:35:22.60,Default,,0,0,0,,针对特定N的求指数函数\nDialogue: 0,0:35:23.69,0:35:24.28,Default,,0,0,0,,给定一个N\nDialogue: 0,0:35:24.32,0:35:25.66,Default,,0,0,0,,它会返回给我一个特定的求指数过程\nDialogue: 0,0:35:26.28,0:35:27.40,Default,,0,0,0,,这非常简单\nDialogue: 0,0:35:28.17,0:35:30.57,Default,,0,0,0,,换言之 我可以这样来写\nDialogue: 0,0:35:35.84,0:35:37.84,Default,,0,0,0,,我要定义一个过程PGEN\nDialogue: 0,0:35:40.25,0:35:42.54,Default,,0,0,0,,它有一个参数N\nDialogue: 0,0:35:43.16,0:35:45.95,Default,,0,0,0,,返回一个指数过程\nDialogue: 0,0:35:50.24,0:35:51.23,Default,,0,0,0,,计算X^N\nDialogue: 0,0:35:56.80,0:35:57.98,Default,,0,0,0,,有了这个以后\nDialogue: 0,0:35:58.59,0:36:00.88,Default,,0,0,0,,我就可以进行想要的那种抽象\nDialogue: 0,0:36:01.42,0:36:03.93,Default,,0,0,0,,甚至于现在的封装方法还要更好一些\nDialogue: 0,0:36:04.09,0:36:06.60,Default,,0,0,0,,因为系统现在不会因改名而崩溃了\nDialogue: 0,0:36:07.89,0:36:12.35,Default,,0,0,0,,(DEFINE SUM-POWERS\nDialogue: 0,0:36:17.28,0:36:20.70,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:36:21.61,0:36:26.83,Default,,0,0,0,,(SUM\nDialogue: 0,0:36:26.88,0:36:32.32,Default,,0,0,0,,(PGEN N)\nDialogue: 0,0:36:34.40,0:36:38.01,Default,,0,0,0,,A 1+ B)))\nDialogue: 0,0:36:42.49,0:36:47.95,Default,,0,0,0,,(DEFINE PRODUCT-POWERS\nDialogue: 0,0:36:54.11,0:36:58.84,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:36:59.80,0:37:09.96,Default,,0,0,0,,(PRODUCT (PGEN N) A 1+ B)))\nDialogue: 0,0:37:11.28,0:37:13.28,Default,,0,0,0,,当然 这只是一个非常简单的例子\nDialogue: 0,0:37:13.60,0:37:16.35,Default,,0,0,0,,这里 我想要抽象的对象也十分简单\nDialogue: 0,0:37:17.28,0:37:18.83,Default,,0,0,0,,但它也有可能是长达100行的代码\nDialogue: 0,0:37:20.10,0:37:23.67,Default,,0,0,0,,我这么写是为了保持简单\nDialogue: 0,0:37:23.67,0:37:24.57,Default,,0,0,0,,我给它命了名\nDialogue: 0,0:37:24.73,0:37:26.94,Default,,0,0,0,,这里它只是一个参数化的名字\nDialogue: 0,0:37:28.20,0:37:30.27,Default,,0,0,0,,这个名字显式地依赖于\nDialogue: 0,0:37:30.49,0:37:33.63,Default,,0,0,0,,词法作用域下N的值\nDialogue: 0,0:37:37.13,0:37:38.59,Default,,0,0,0,,因此可以把它看做一个很长的名字\nDialogue: 0,0:37:40.21,0:37:41.58,Default,,0,0,0,,这里 我是通过\nDialogue: 0,0:37:41.76,0:37:45.82,Default,,0,0,0,,为计算TERM的过程命名\nDialogue: 0,0:37:46.12,0:37:49.22,Default,,0,0,0,,来解决问题的\nDialogue: 0,0:37:55.08,0:37:55.87,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:37:57.00,0:37:58.38,Default,,0,0,0,,David 你说\nDialogue: 0,0:37:58.57,0:38:02.27,Default,,0,0,0,,学生：刚才那个问题\nDialogue: 0,0:38:03.07,0:38:06.46,Default,,0,0,0,,只能通过新建一个过程来解决吗？\nDialogue: 0,0:38:06.47,0:38:08.92,Default,,0,0,0,,换句话说 是不是必须要语言能够\nDialogue: 0,0:38:08.99,0:38:11.56,Default,,0,0,0,,把对象定义为过程？\nDialogue: 0,0:38:12.41,0:38:13.76,Default,,0,0,0,,教授：我明白了\nDialogue: 0,0:38:15.90,0:38:19.74,Default,,0,0,0,,我构建抽象的这种方法\nDialogue: 0,0:38:20.14,0:38:22.86,Default,,0,0,0,,需要过程能够返回或者导出一个过程\nDialogue: 0,0:38:23.26,0:38:26.81,Default,,0,0,0,,以便我不想让过程体中包含特定过程\nDialogue: 0,0:38:27.04,0:38:27.24,Default,,0,0,0,,学生：没错\nDialogue: 0,0:38:28.19,0:38:28.88,Default,,0,0,0,,教授：是这样的\nDialogue: 0,0:38:29.53,0:38:31.52,Default,,0,0,0,,如果我不能这么做的话\nDialogue: 0,0:38:32.24,0:38:35.13,Default,,0,0,0,,那么我就无法去构造一个抽象\nDialogue: 0,0:38:35.53,0:38:41.77,Default,,0,0,0,,使得符号之间不会出现冲突\nDialogue: 0,0:38:43.00,0:38:43.48,Default,,0,0,0,,你说得对\nDialogue: 0,0:38:44.14,0:38:46.51,Default,,0,0,0,,我认为\nDialogue: 0,0:38:46.54,0:38:48.91,Default,,0,0,0,,能够把过程作为返回值\nDialogue: 0,0:38:49.20,0:38:58.28,Default,,0,0,0,,更一般地说是支持“第一级过程”\nDialogue: 0,0:38:59.13,0:39:02.46,Default,,0,0,0,,是模块化程序程序设计所必须的\nDialogue: 0,0:39:03.70,0:39:06.43,Default,,0,0,0,,有很多种方式来解决这个问题\nDialogue: 0,0:39:07.44,0:39:09.16,Default,,0,0,0,,你可以的做的就是\nDialogue: 0,0:39:09.18,0:39:11.84,Default,,0,0,0,,针对你所需要关心的每一种糟糕情况\nDialogue: 0,0:39:12.27,0:39:15.20,Default,,0,0,0,,你可以添加一个特殊的FEATURE来解决它\nDialogue: 0,0:39:15.84,0:39:17.12,Default,,0,0,0,,你可以做一个包系统\nDialogue: 0,0:39:17.74,0:39:21.16,Default,,0,0,0,,或者像Ada中的模块系统 等等\nDialogue: 0,0:39:22.24,0:39:24.88,Default,,0,0,0,,这些都可以 可能区别只是解决的程度不一\nDialogue: 0,0:39:26.44,0:39:28.38,Default,,0,0,0,,而能够把过程作为返回值\nDialogue: 0,0:39:28.41,0:39:29.74,Default,,0,0,0,,可以解决这所有的问题\nDialogue: 0,0:39:32.68,0:39:34.60,Default,,0,0,0,,这种最简单的机制\nDialogue: 0,0:39:35.58,0:39:37.79,Default,,0,0,0,,却可以给予你最好的模块性\nDialogue: 0,0:39:39.21,0:39:41.31,Default,,0,0,0,,它赋予你所有已知的模块机制\nDialogue: 0,0:39:45.59,0:39:48.24,Default,,0,0,0,,好的 该休息一会儿了 谢谢大家\nDialogue: 0,0:39:48.24,0:40:01.08,Default,,0,0,0,,[音乐]\nDialogue: 0,0:40:01.28,0:40:04.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:40:25.69,0:40:29.42,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:40:30.01,0:40:33.28,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:40:34.17,0:40:37.61,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 II\nDialogue: 0,0:40:42.32,0:40:44.28,Default,,0,0,0,,教授：昨天你们学习流的时候\nDialogue: 0,0:40:46.01,0:40:51.16,Default,,0,0,0,,Hal教授告诉了你们求值顺序\nDialogue: 0,0:40:51.95,0:40:53.87,Default,,0,0,0,,以及过程的延迟求值\nDialogue: 0,0:40:55.61,0:40:58.30,Default,,0,0,0,,昨天在讲流的时候 我们说\nDialogue: 0,0:41:00.25,0:41:04.22,Default,,0,0,0,,调用者和被调者都应该认同\nDialogue: 0,0:41:05.77,0:41:08.84,Default,,0,0,0,,参数是被延迟了的\nDialogue: 0,0:41:09.42,0:41:13.44,Default,,0,0,0,,如果被调者需要结果 就需要对参数FORCE\nDialogue: 0,0:41:15.13,0:41:17.87,Default,,0,0,0,,因此在过程的设计者和使用者之间\nDialogue: 0,0:41:18.17,0:41:24.32,Default,,0,0,0,,就有很多关于延时求值的握手\nDialogue: 0,0:41:26.36,0:41:28.72,Default,,0,0,0,,当然 这看起来相当糟糕\nDialogue: 0,0:41:29.48,0:41:30.96,Default,,0,0,0,,虽说对于流没什么不妥\nDialogue: 0,0:41:31.74,0:41:32.86,Default,,0,0,0,,但作为一般性的原则来说\nDialogue: 0,0:41:32.92,0:41:36.32,Default,,0,0,0,,我们希望能有个地方\nDialogue: 0,0:41:36.46,0:41:38.49,Default,,0,0,0,,能够把我们的设计考虑\nDialogue: 0,0:41:38.89,0:41:41.28,Default,,0,0,0,,显式地、清晰地\nDialogue: 0,0:41:41.63,0:41:43.93,Default,,0,0,0,,标注出来\nDialogue: 0,0:41:45.88,0:41:49.28,Default,,0,0,0,,因此就不必在过程编写者\nDialogue: 0,0:41:50.46,0:41:54.89,Default,,0,0,0,,和使用者之间达成共识\nDialogue: 0,0:41:55.08,0:41:57.98,Default,,0,0,0,,有关于参数求值\nDialogue: 0,0:41:58.43,0:41:59.50,Default,,0,0,0,,以及求值顺序等细节\nDialogue: 0,0:41:59.50,0:42:00.75,Default,,0,0,0,,虽然 这也不是太糟糕\nDialogue: 0,0:42:01.02,0:42:03.95,Default,,0,0,0,,我的意思是 可能还有像“输入是一个数字”这样的共识\nDialogue: 0,0:42:05.20,0:42:06.08,Default,,0,0,0,,但是\nDialogue: 0,0:42:06.35,0:42:09.20,Default,,0,0,0,,如果其中一个人可以全权负责 就再好不过了\nDialogue: 0,0:42:11.02,0:42:13.31,Default,,0,0,0,,这个想法已经不算新潮了\nDialogue: 0,0:42:15.51,0:42:21.16,Default,,0,0,0,,Algol60就支持两种不同的过程调用方法\nDialogue: 0,0:42:22.02,0:42:24.28,Default,,0,0,0,,参数可以按名或按值传递\nDialogue: 0,0:42:25.59,0:42:27.48,Default,,0,0,0,,按名传递就意味着\nDialogue: 0,0:42:27.63,0:42:29.72,Default,,0,0,0,,参数会延时求值\nDialogue: 0,0:42:31.11,0:42:32.84,Default,,0,0,0,,当你按名传递一个参数时\nDialogue: 0,0:42:33.64,0:42:36.52,Default,,0,0,0,,只有你去取它的值的时候\nDialogue: 0,0:42:36.96,0:42:39.55,Default,,0,0,0,,它的值才会被计算出来\nDialogue: 0,0:42:42.29,0:42:44.20,Default,,0,0,0,,所以 现在我就要\nDialogue: 0,0:42:44.43,0:42:46.96,Default,,0,0,0,,像之前那样\nDialogue: 0,0:42:46.99,0:42:48.65,Default,,0,0,0,,对语言做出一些小小的修改\nDialogue: 0,0:42:50.32,0:42:51.79,Default,,0,0,0,,这里 我们再添加一个新的FEATURE\nDialogue: 0,0:42:53.37,0:42:55.05,Default,,0,0,0,,我们要添加的FEATURE是\nDialogue: 0,0:42:55.36,0:42:58.73,Default,,0,0,0,,“按名传递参数” 或者可以叫做“延迟求值参数”\nDialogue: 0,0:43:00.43,0:43:04.41,Default,,0,0,0,,因为事实上 Lisp系统中默认\nDialogue: 0,0:43:04.76,0:43:06.60,Default,,0,0,0,,传递的是一个指针\nDialogue: 0,0:43:08.22,0:43:09.15,Default,,0,0,0,,指针被复制了一份\nDialogue: 0,0:43:09.15,0:43:10.91,Default,,0,0,0,,但所指的数据结构却没有被复制\nDialogue: 0,0:43:13.41,0:43:14.84,Default,,0,0,0,,现在我要告诉你们\nDialogue: 0,0:43:15.04,0:43:18.38,Default,,0,0,0,,如何来添加按名传递参数\nDialogue: 0,0:43:19.99,0:43:22.12,Default,,0,0,0,,为什么我们需要这样的FEATURE呢？\nDialogue: 0,0:43:23.10,0:43:24.72,Default,,0,0,0,,假设我们想要开发\nDialogue: 0,0:43:25.24,0:43:28.44,Default,,0,0,0,,像是某种特殊形式的功能\nDialogue: 0,0:43:28.73,0:43:29.72,Default,,0,0,0,,类似于“保留字”\nDialogue: 0,0:43:29.72,0:43:31.48,Default,,0,0,0,,但不是用保留字的方式来实现\nDialogue: 0,0:43:32.18,0:43:34.76,Default,,0,0,0,,我想用过程来实现类似IF的效果\nDialogue: 0,0:43:36.36,0:43:39.42,Default,,0,0,0,,无论是IF还是COND 都是特殊形式\nDialogue: 0,0:43:39.42,0:43:40.43,Default,,0,0,0,,它俩是一样的\nDialogue: 0,0:43:40.59,0:43:42.86,Default,,0,0,0,,这个特殊形式用于\nDialogue: 0,0:43:42.92,0:43:45.02,Default,,0,0,0,,根据谓词返回真假\nDialogue: 0,0:43:46.22,0:43:49.76,Default,,0,0,0,,决定求值真子句还是假子句\nDialogue: 0,0:43:50.84,0:43:53.12,Default,,0,0,0,,它们都是根据某个值\nDialogue: 0,0:43:53.44,0:43:55.36,Default,,0,0,0,,来决定是否去做另外的某件事\nDialogue: 0,0:43:57.27,0:43:58.88,Default,,0,0,0,,然而像+之类的过程\nDialogue: 0,0:43:59.15,0:44:01.20,Default,,0,0,0,,也就是那些我们现在可以定义的过程\nDialogue: 0,0:44:01.42,0:44:06.56,Default,,0,0,0,,是在应用前就求值所有的参数\nDialogue: 0,0:44:08.67,0:44:09.64,Default,,0,0,0,,因此 举例来说\nDialogue: 0,0:44:10.46,0:44:12.41,Default,,0,0,0,,假设我想定义一个过程\nDialogue: 0,0:44:15.39,0:44:18.75,Default,,0,0,0,,用IF来实现与IF相反的效果\nDialogue: 0,0:44:19.85,0:44:20.70,Default,,0,0,0,,我叫它UNLESS\nDialogue: 0,0:44:24.89,0:44:27.47,Default,,0,0,0,,参数是 谓词P、真子句C和假子句A\nDialogue: 0,0:44:28.67,0:44:30.44,Default,,0,0,0,,接下来 我想\nDialogue: 0,0:44:30.46,0:44:32.08,Default,,0,0,0,,用COND来实现\nDialogue: 0,0:44:32.64,0:44:36.72,Default,,0,0,0,,(COND ((NOT P)\nDialogue: 0,0:44:38.96,0:44:40.32,Default,,0,0,0,,结果就是真子句C\nDialogue: 0,0:44:41.58,0:44:45.63,Default,,0,0,0,,否则就是假子句A\nDialogue: 0,0:44:51.29,0:44:52.76,Default,,0,0,0,,我定义这个过程是为了\nDialogue: 0,0:44:53.32,0:44:55.40,Default,,0,0,0,,请考虑下面这种情况\nDialogue: 0,0:44:56.92,0:45:04.12,Default,,0,0,0,,(UNLESS (= 1 0)\nDialogue: 0,0:45:05.08,0:45:06.64,Default,,0,0,0,,那么结果就是2\nDialogue: 0,0:45:07.90,0:45:11.35,Default,,0,0,0,,否则 结果就是(/ 1 0)\nDialogue: 0,0:45:15.92,0:45:18.91,Default,,0,0,0,,这段代码相当于进行这样的代换：\nDialogue: 0,0:45:20.00,0:45:23.26,Default,,0,0,0,,用(= 1 0)、2和(/ 1 0)\nDialogue: 0,0:45:23.66,0:45:24.76,Default,,0,0,0,,分别代换上面的P、C以及A\nDialogue: 0,0:45:25.58,0:45:27.58,Default,,0,0,0,,这样很有趣\nDialogue: 0,0:45:28.11,0:45:30.33,Default,,0,0,0,,代换后就变成了\nDialogue: 0,0:45:30.75,0:45:38.44,Default,,0,0,0,,(COND ((NOT (= 1 0))\nDialogue: 0,0:45:40.62,0:45:42.54,Default,,0,0,0,,结果就是2\nDialogue: 0,0:45:44.28,0:45:45.10,Default,,0,0,0,,否则就是\nDialogue: 0,0:45:48.22,0:45:51.16,Default,,0,0,0,,(/ 1 0)\nDialogue: 0,0:45:54.48,0:45:56.48,Default,,0,0,0,,你们也知道 如果向Lisp中输入这段代码\nDialogue: 0,0:45:57.74,0:45:58.59,Default,,0,0,0,,结果会是2\nDialogue: 0,0:45:59.97,0:46:01.32,Default,,0,0,0,,这没问题\nDialogue: 0,0:46:02.91,0:46:04.64,Default,,0,0,0,,但如果我输入的是这段代码\nDialogue: 0,0:46:05.28,0:46:07.79,Default,,0,0,0,,由于参数会在过程调用前求值\nDialogue: 0,0:46:09.12,0:46:10.73,Default,,0,0,0,,那么这段代码就会报错\nDialogue: 0,0:46:13.38,0:46:15.61,Default,,0,0,0,,当然 如果成功进行代换的话\nDialogue: 0,0:46:16.03,0:46:16.88,Default,,0,0,0,,我可以得到正确的结果\nDialogue: 0,0:46:16.88,0:46:20.16,Default,,0,0,0,,但是这里这种情况 代换并不能进行\nDialogue: 0,0:46:22.17,0:46:23.86,Default,,0,0,0,,我连错误的结果都无法得到\nDialogue: 0,0:46:23.86,0:46:24.67,Default,,0,0,0,,没有结果\nDialogue: 0,0:46:24.80,0:46:25.60,Default,,0,0,0,,只能得到错误\nDialogue: 0,0:46:28.42,0:46:31.21,Default,,0,0,0,,现在 我要想办法\nDialogue: 0,0:46:31.61,0:46:32.99,Default,,0,0,0,,使这样的定义可以成功运行\nDialogue: 0,0:46:34.48,0:46:36.51,Default,,0,0,0,,但我想标注出\nDialogue: 0,0:46:36.70,0:46:38.76,Default,,0,0,0,,C和A是特殊的东西\nDialogue: 0,0:46:39.93,0:46:43.15,Default,,0,0,0,,我想使它们自动地延时求值\nDialogue: 0,0:46:44.27,0:46:48.08,Default,,0,0,0,,我不想它们在我调用过程的时候\nDialogue: 0,0:46:48.52,0:46:49.74,Default,,0,0,0,,就被求值\nDialogue: 0,0:46:51.52,0:46:52.72,Default,,0,0,0,,所以我得先制定一种声明\nDialogue: 0,0:46:52.75,0:46:55.32,Default,,0,0,0,,然后再考虑如何实现此种声明\nDialogue: 0,0:46:55.60,0:46:57.63,Default,,0,0,0,,再次强调 希望你们能够提醒自己\nDialogue: 0,0:46:57.79,0:47:00.25,Default,,0,0,0,,我们这里添加的是临时组件\nDialogue: 0,0:47:00.76,0:47:02.16,Default,,0,0,0,,必须要知道\nDialogue: 0,0:47:02.25,0:47:04.72,Default,,0,0,0,,滥用临时组件会造成大混乱\nDialogue: 0,0:47:05.75,0:47:09.79,Default,,0,0,0,,还会破坏一些已有的东西\nDialogue: 0,0:47:10.12,0:47:12.70,Default,,0,0,0,,首先 它会造成语法歧义性么？\nDialogue: 0,0:47:13.86,0:47:15.50,Default,,0,0,0,,就我们目前已有的语法来说\nDialogue: 0,0:47:15.71,0:47:16.91,Default,,0,0,0,,它不会造成什么歧义\nDialogue: 0,0:47:17.84,0:47:20.76,Default,,0,0,0,,但接下来要做的却可能招来麻烦\nDialogue: 0,0:47:21.67,0:47:24.67,Default,,0,0,0,,我要添加的东西可能会跟\nDialogue: 0,0:47:25.15,0:47:27.10,Default,,0,0,0,,我以后添加的类型声明冲突\nDialogue: 0,0:47:28.19,0:47:31.08,Default,,0,0,0,,类型系统通过提供已知的类型信息\nDialogue: 0,0:47:31.21,0:47:33.66,Default,,0,0,0,,使得语言系统或者编译器可以做出优化\nDialogue: 0,0:47:34.75,0:47:36.97,Default,,0,0,0,,当然也会与我想添加的形式参数的\nDialogue: 0,0:47:37.00,0:47:39.71,Default,,0,0,0,,其它类型的声明相冲突\nDialogue: 0,0:47:40.57,0:47:42.56,Default,,0,0,0,,所以这里我并不打算做一个一般性的机制\nDialogue: 0,0:47:43.77,0:47:45.24,Default,,0,0,0,,使得我可以添加声明\nDialogue: 0,0:47:45.28,0:47:46.54,Default,,0,0,0,,虽然我很想那么做\nDialogue: 0,0:47:46.89,0:47:48.81,Default,,0,0,0,,但现在并不打算这么做\nDialogue: 0,0:47:51.01,0:47:53.88,Default,,0,0,0,,接下来 我要添加某种临时的解决方法\nDialogue: 0,0:47:57.56,0:48:08.38,Default,,0,0,0,,(DEFINE (UNLESS P\nDialogue: 0,0:48:08.81,0:48:10.27,Default,,0,0,0,,后面的参数都是按名调用\nDialogue: 0,0:48:12.78,0:48:15.28,Default,,0,0,0,,分别记作(NAME C)和(NAME A)\nDialogue: 0,0:48:19.85,0:48:25.28,Default,,0,0,0,,哈 哈 卡在黑板边了\nDialogue: 0,0:48:31.76,0:48:35.61,Default,,0,0,0,,(COND ((NOT P) C)\nDialogue: 0,0:48:36.80,0:48:41.16,Default,,0,0,0,,(ELSE A)))\nDialogue: 0,0:48:44.67,0:48:46.88,Default,,0,0,0,,我可以显式地声明\nDialogue: 0,0:48:47.55,0:48:51.65,Default,,0,0,0,,哪些参数按名称传递或延时求值\nDialogue: 0,0:48:55.60,0:48:58.48,Default,,0,0,0,,对解释器的这个修改并不简单\nDialogue: 0,0:48:58.70,0:48:59.77,Default,,0,0,0,,反而相当复杂\nDialogue: 0,0:49:00.45,0:49:03.10,Default,,0,0,0,,我们之前介绍的动态绑定\nDialogue: 0,0:49:03.40,0:49:06.89,Default,,0,0,0,,或者让过程支持不定数目的参数\nDialogue: 0,0:49:07.50,0:49:08.52,Default,,0,0,0,,都相对简单\nDialogue: 0,0:49:09.28,0:49:11.28,Default,,0,0,0,,这次的修改涉及基本策略\nDialogue: 0,0:49:12.32,0:49:13.39,Default,,0,0,0,,这里的问题是\nDialogue: 0,0:49:13.96,0:49:17.63,Default,,0,0,0,,我们的解释器 就如代码所写的那样\nDialogue: 0,0:49:17.96,0:49:23.40,Default,,0,0,0,,在求值组合式时\nDialogue: 0,0:49:24.24,0:49:25.92,Default,,0,0,0,,先通过求值运算符取得过程\nDialogue: 0,0:49:26.20,0:49:30.35,Default,,0,0,0,,然后再求值运算对象得到参数\nDialogue: 0,0:49:30.76,0:49:35.26,Default,,0,0,0,,再把过程应用到参数上\nDialogue: 0,0:49:36.38,0:49:37.07,Default,,0,0,0,,然而这里\nDialogue: 0,0:49:37.36,0:49:41.48,Default,,0,0,0,,直到我检查了整个过程\nDialogue: 0,0:49:41.74,0:49:43.66,Default,,0,0,0,,确定了程序的声明\nDialogue: 0,0:49:44.62,0:49:46.86,Default,,0,0,0,,才会去求值程序的参数\nDialogue: 0,0:49:49.59,0:49:50.59,Default,,0,0,0,,我们来看这个\nDialogue: 0,0:49:52.68,0:49:56.54,Default,,0,0,0,,这是修改后的求值器\nDialogue: 0,0:49:57.48,0:50:01.15,Default,,0,0,0,,我是基于那个最简单的词法作用域求值器\nDialogue: 0,0:50:01.72,0:50:02.65,Default,,0,0,0,,不是动态绑定的那个\nDialogue: 0,0:50:04.14,0:50:08.20,Default,,0,0,0,,但是却要做一些类似于动态绑定的修改\nDialogue: 0,0:50:09.75,0:50:11.45,Default,,0,0,0,,这是因为\nDialogue: 0,0:50:11.90,0:50:13.34,Default,,0,0,0,,如果我延时一个过程 --\nDialogue: 0,0:50:13.66,0:50:15.15,Default,,0,0,0,,哦说错了 -- 延时一个过程的参数\nDialogue: 0,0:50:15.40,0:50:17.52,Default,,0,0,0,,就必须把当前的环境和参数关联在一起\nDialogue: 0,0:50:19.36,0:50:21.55,Default,,0,0,0,,还记得Hal教授如何实现DELAY的吧？\nDialogue: 0,0:50:23.38,0:50:25.44,Default,,0,0,0,,Hal教授把DELAY实现为\nDialogue: 0,0:50:25.50,0:50:27.47,Default,,0,0,0,,一个无参过程\nDialogue: 0,0:50:28.56,0:50:30.52,Default,,0,0,0,,用来执行某些表达式\nDialogue: 0,0:50:31.18,0:50:36.94,Default,,0,0,0,,就是这样让表达式延迟求值的\nDialogue: 0,0:50:39.29,0:50:40.99,Default,,0,0,0,,(DELAY E)实际上是这个\nDialogue: 0,0:50:44.52,0:50:46.92,Default,,0,0,0,,然而 如果我求值这个LAMBDA表达式\nDialogue: 0,0:50:47.42,0:50:49.20,Default,,0,0,0,,我就必须得捕获当前环境\nDialogue: 0,0:50:51.41,0:50:53.45,Default,,0,0,0,,这是因为\nDialogue: 0,0:50:54.60,0:50:56.32,Default,,0,0,0,,我想让这其中的变量的值\nDialogue: 0,0:50:57.02,0:51:00.83,Default,,0,0,0,,取决于它们被定义时的上下文\nDialogue: 0,0:51:04.01,0:51:05.76,Default,,0,0,0,,这也就是为什么要用LAMBDA表达式\nDialogue: 0,0:51:06.62,0:51:07.50,Default,,0,0,0,,这才是正确的\nDialogue: 0,0:51:08.07,0:51:15.12,Default,,0,0,0,,(FORCE E)则相当于\nDialogue: 0,0:51:16.52,0:51:20.08,Default,,0,0,0,,无参地调用这个过程\nDialogue: 0,0:51:21.09,0:51:22.28,Default,,0,0,0,,恰恰和上面相对\nDialogue: 0,0:51:24.10,0:51:26.94,Default,,0,0,0,,这个调用产生的环境则是\nDialogue: 0,0:51:27.36,0:51:29.90,Default,,0,0,0,,定义这个过程时的环境\nDialogue: 0,0:51:30.81,0:51:32.36,Default,,0,0,0,,额外加上一个空框架\nDialogue: 0,0:51:33.23,0:51:34.41,Default,,0,0,0,,我并不在意它\nDialogue: 0,0:51:36.24,0:51:39.40,Default,,0,0,0,,我们再来看这张幻灯片\nDialogue: 0,0:51:40.99,0:51:43.72,Default,,0,0,0,,仔细观察一会儿\nDialogue: 0,0:51:44.14,0:51:46.12,Default,,0,0,0,,会发现大部分跟以前相同\nDialogue: 0,0:51:46.35,0:51:50.65,Default,,0,0,0,,只是对应用或组合式的处理不同\nDialogue: 0,0:51:51.98,0:51:53.71,Default,,0,0,0,,处理组合式分两步\nDialogue: 0,0:51:54.68,0:51:57.79,Default,,0,0,0,,首先要求值这个过程\nDialogue: 0,0:51:57.92,0:51:59.88,Default,,0,0,0,,我就必须通过求值运算符来得到对应过程\nDialogue: 0,0:52:00.70,0:52:01.69,Default,,0,0,0,,也就是这一部分\nDialogue: 0,0:52:02.38,0:52:04.35,Default,,0,0,0,,我得这个值是计算求出的现值\nDialogue: 0,0:52:04.46,0:52:05.76,Default,,0,0,0,,而不是一个延时对象\nDialogue: 0,0:52:06.36,0:52:09.85,Default,,0,0,0,,也就要求值它在被延时前的表达式\nDialogue: 0,0:52:10.73,0:52:12.08,Default,,0,0,0,,接下来我就要\nDialogue: 0,0:52:12.24,0:52:17.32,Default,,0,0,0,,把它应用于运算对象\nDialogue: 0,0:52:18.03,0:52:19.61,Default,,0,0,0,,但我仍然要保持这个环境\nDialogue: 0,0:52:19.63,0:52:20.92,Default,,0,0,0,,并将其传递过去\nDialogue: 0,0:52:21.53,0:52:23.71,Default,,0,0,0,,如果有一些运算对象是延时了的\nDialogue: 0,0:52:23.71,0:52:27.53,Default,,0,0,0,,我就需要为这些运算对象附上相应的环境\nDialogue: 0,0:52:29.66,0:52:31.52,Default,,0,0,0,,这里的处理相当复杂\nDialogue: 0,0:52:32.99,0:52:34.24,Default,,0,0,0,,来看看APPLY中对应的部分\nDialogue: 0,0:52:36.40,0:52:38.72,Default,,0,0,0,,APPLY这一部分处理基本过程\nDialogue: 0,0:52:39.36,0:52:40.60,Default,,0,0,0,,这和之前一样\nDialogue: 0,0:52:42.61,0:52:44.68,Default,,0,0,0,,但复合过程部分就比较有意思了\nDialogue: 0,0:52:47.25,0:52:49.52,Default,,0,0,0,,和之前一样 我需要求值过程体\nDialogue: 0,0:52:50.48,0:52:51.98,Default,,0,0,0,,基于的环境是\nDialogue: 0,0:52:52.28,0:52:54.97,Default,,0,0,0,,把形式参数和\nDialogue: 0,0:52:55.61,0:53:00.29,Default,,0,0,0,,实际参数绑定在一起的结果\nDialogue: 0,0:53:00.29,0:53:01.07,Default,,0,0,0,,是这样的\nDialogue: 0,0:53:01.53,0:53:03.82,Default,,0,0,0,,环境来自于过程对象\nDialogue: 0,0:53:03.82,0:53:06.65,Default,,0,0,0,,因为我们的语言是词法作用域、静态绑定的\nDialogue: 0,0:53:08.04,0:53:11.82,Default,,0,0,0,,然而 我还需要去掉NAME声明\nDialogue: 0,0:53:11.84,0:53:12.84,Default,,0,0,0,,获得变量的实际名字\nDialogue: 0,0:53:12.84,0:53:15.20,Default,,0,0,0,,这是由VNAMES过程完成的\nDialogue: 0,0:53:15.45,0:53:16.67,Default,,0,0,0,,然后要做的就是\nDialogue: 0,0:53:16.97,0:53:18.86,Default,,0,0,0,,处理这些声明\nDialogue: 0,0:53:19.13,0:53:21.52,Default,,0,0,0,,决定这些运算对象中\nDialogue: 0,0:53:21.76,0:53:23.92,Default,,0,0,0,,现在它们还是形式参数 而非实际参数\nDialogue: 0,0:53:24.09,0:53:25.87,Default,,0,0,0,,哪些运算对象需要立即求值\nDialogue: 0,0:53:26.62,0:53:30.20,Default,,0,0,0,,而哪些运算对象又要\nDialogue: 0,0:53:30.99,0:53:33.77,Default,,0,0,0,,用某种方式封装为延时对象\nDialogue: 0,0:53:37.28,0:53:40.08,Default,,0,0,0,,另外 在处理基本过程这里\nDialogue: 0,0:53:40.60,0:53:42.38,Default,,0,0,0,,当遇到像+这样的基本过程\nDialogue: 0,0:53:42.68,0:53:45.58,Default,,0,0,0,,它们的参数最好立即求值\nDialogue: 0,0:53:45.82,0:53:47.39,Default,,0,0,0,,也就我们需要是这里FORCE这些表达式\nDialogue: 0,0:53:47.92,0:53:50.38,Default,,0,0,0,,EVLIST中完成了很多FORCE操作\nDialogue: 0,0:53:51.34,0:53:52.78,Default,,0,0,0,,现在 我们有了两种不同的EVLIST\nDialogue: 0,0:53:52.78,0:53:54.09,Default,,0,0,0,,EVLIST和GEVLIST\nDialogue: 0,0:53:54.52,0:53:57.16,Default,,0,0,0,,GEVLIST封装延迟参数\nDialogue: 0,0:53:57.18,0:53:59.74,Default,,0,0,0,,而对另外的参数立即求值\nDialogue: 0,0:53:59.87,0:54:05.85,Default,,0,0,0,,而EVLIST则会FORCE所有的表达式\nDialogue: 0,0:54:07.90,0:54:09.16,Default,,0,0,0,,简单地看下EVLIST的代码\nDialogue: 0,0:54:09.69,0:54:11.98,Default,,0,0,0,,课后你们一定要亲自上手试试\nDialogue: 0,0:54:12.25,0:54:14.67,Default,,0,0,0,,光是听我在这里讲课\nDialogue: 0,0:54:14.72,0:54:18.20,Default,,0,0,0,,可不能够学到求值器的不同变种\nDialogue: 0,0:54:19.52,0:54:21.24,Default,,0,0,0,,你们需要上手亲自实践一下。\nDialogue: 0,0:54:21.37,0:54:23.84,Default,,0,0,0,,你试验过后 对它们有了感悟\nDialogue: 0,0:54:24.22,0:54:27.02,Default,,0,0,0,,你才能理解各种可能的设计决策\nDialogue: 0,0:54:27.77,0:54:29.16,Default,,0,0,0,,才能清楚它们如何相互关联\nDialogue: 0,0:54:29.93,0:54:32.38,Default,,0,0,0,,了解求值器描述的是何种语言\nDialogue: 0,0:54:33.16,0:54:34.64,Default,,0,0,0,,以及构建一门合理的语言\nDialogue: 0,0:54:34.94,0:54:36.32,Default,,0,0,0,,需要哪些一致性集合\nDialogue: 0,0:54:37.20,0:54:40.06,Default,,0,0,0,,哪些临时方案又是复杂而无用\nDialogue: 0,0:54:41.85,0:54:44.68,Default,,0,0,0,,就和我说得一样 这里的EVLIST\nDialogue: 0,0:54:44.81,0:54:46.03,Default,,0,0,0,,参数之一为运算对象表\nDialogue: 0,0:54:46.70,0:54:50.28,Default,,0,0,0,,表中的元素会在求值之后被取消延时\nDialogue: 0,0:54:50.75,0:54:51.90,Default,,0,0,0,,它们都会被FORCE\nDialogue: 0,0:54:53.28,0:54:54.44,Default,,0,0,0,,无论它们是否为延时对象\nDialogue: 0,0:54:56.05,0:54:58.51,Default,,0,0,0,,下一个 GEVLIST\nDialogue: 0,0:55:01.26,0:55:01.85,Default,,0,0,0,,谢谢\nDialogue: 0,0:55:04.04,0:55:06.35,Default,,0,0,0,,我们在这里会发现\nDialogue: 0,0:55:07.80,0:55:09.61,Default,,0,0,0,,这里面有多种可能\nDialogue: 0,0:55:09.81,0:55:11.52,Default,,0,0,0,,要么是普通的情况\nDialogue: 0,0:55:12.48,0:55:13.69,Default,,0,0,0,,比如元素直接是一个符号\nDialogue: 0,0:55:13.74,0:55:16.20,Default,,0,0,0,,就像UNLESS中的参数P那样\nDialogue: 0,0:55:17.64,0:55:18.81,Default,,0,0,0,,对应这一部分代码\nDialogue: 0,0:55:19.39,0:55:22.49,Default,,0,0,0,,在这种情况下 我们就用应用序来求值\nDialogue: 0,0:55:23.34,0:55:25.45,Default,,0,0,0,,基本上就像以前一样\nDialogue: 0,0:55:25.63,0:55:28.84,Default,,0,0,0,,就是将EVAL映射在这个表上\nDialogue: 0,0:55:29.95,0:55:32.14,Default,,0,0,0,,换言之 就是先求值第一个表达式\nDialogue: 0,0:55:32.65,0:55:37.36,Default,,0,0,0,,然后在ENV中 求值(GEVLIST (CDR EXPRS))\nDialogue: 0,0:55:37.93,0:55:43.20,Default,,0,0,0,,然而 我们也可能遇到按名传递的参数\nDialogue: 0,0:55:44.00,0:55:45.05,Default,,0,0,0,,如果参数是按名传递\nDialogue: 0,0:55:45.20,0:55:46.59,Default,,0,0,0,,我就需要给它包裹上一个DELAY\nDialogue: 0,0:55:47.00,0:55:50.97,Default,,0,0,0,,DELAY里面就是我想按名调用的表达式\nDialogue: 0,0:55:52.14,0:55:57.74,Default,,0,0,0,,还要附上定义过程时的环境\nDialogue: 0,0:55:59.05,0:56:00.59,Default,,0,0,0,,把它们作为实际参数\nDialogue: 0,0:56:02.79,0:56:05.04,Default,,0,0,0,,然后像这样继续递归处理\nDialogue: 0,0:56:09.07,0:56:11.31,Default,,0,0,0,,这个解释器中另外一个有意思的地方\nDialogue: 0,0:56:11.37,0:56:13.53,Default,,0,0,0,,就在于COND\nDialogue: 0,0:56:14.70,0:56:15.92,Default,,0,0,0,,人们可能就这么来写\nDialogue: 0,0:56:15.93,0:56:17.24,Default,,0,0,0,,然后就不管了\nDialogue: 0,0:56:18.55,0:56:19.98,Default,,0,0,0,,你需要在一处FORCE\nDialogue: 0,0:56:20.51,0:56:23.10,Default,,0,0,0,,COND表达式需要知道\nDialogue: 0,0:56:24.20,0:56:25.90,Default,,0,0,0,,谓词判定结果的真假\nDialogue: 0,0:56:25.99,0:56:26.83,Default,,0,0,0,,就像基本过程那样\nDialogue: 0,0:56:28.55,0:56:30.56,Default,,0,0,0,,求值COND语句时 需要FORCE\nDialogue: 0,0:56:31.72,0:56:33.95,Default,,0,0,0,,剩下的细节就没什么特别的了\nDialogue: 0,0:56:34.62,0:56:36.28,Default,,0,0,0,,就先不深究了\nDialogue: 0,0:56:36.75,0:56:38.99,Default,,0,0,0,,剩下的就是如何实现MAKE-DELAY\nDialogue: 0,0:56:38.99,0:56:40.91,Default,,0,0,0,,延时对象是一种数据结构\nDialogue: 0,0:56:41.31,0:56:44.75,Default,,0,0,0,,它包括：类型标识、表达式以及环境\nDialogue: 0,0:56:44.84,0:56:46.36,Default,,0,0,0,,它的类型标识是'THUNK\nDialogue: 0,0:56:46.96,0:56:48.46,Default,,0,0,0,,这个术语来自于Algol语言\nDialogue: 0,0:56:49.07,0:56:50.81,Default,,0,0,0,,据说这是个拟声词\nDialogue: 0,0:56:50.83,0:56:52.06,Default,,0,0,0,,是把东西压栈的声音\nDialogue: 0,0:56:52.97,0:56:53.41,Default,,0,0,0,,我不太清楚\nDialogue: 0,0:56:53.41,0:56:57.12,Default,,0,0,0,,我既不是Algol学家 又不是Algol程序员\nDialogue: 0,0:56:57.60,0:56:58.38,Default,,0,0,0,,所以我不太清楚\nDialogue: 0,0:56:58.74,0:56:59.64,Default,,0,0,0,,但据说它是那样的\nDialogue: 0,0:57:00.27,0:57:01.56,Default,,0,0,0,,而UNDELAY的定义则是\nDialogue: 0,0:57:01.77,0:57:03.66,Default,,0,0,0,,递归地UNDELAY这些THUNK\nDialogue: 0,0:57:03.69,0:57:06.00,Default,,0,0,0,,直到得到一个非THUNK对象\nDialogue: 0,0:57:07.72,0:57:10.94,Default,,0,0,0,,这就是如何实现Algol中的按名调用\nDialogue: 0,0:57:12.05,0:57:13.76,Default,,0,0,0,,差不多就是这样了\nDialogue: 0,0:57:15.21,0:57:16.25,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:57:26.68,0:57:27.52,Default,,0,0,0,,学生：Gerry？\nDialogue: 0,0:57:28.09,0:57:28.80,Default,,0,0,0,,教授：你说 Vesko\nDialogue: 0,0:57:30.03,0:57:32.99,Default,,0,0,0,,学生：我注意到 对于基本过程\nDialogue: 0,0:57:33.44,0:57:34.89,Default,,0,0,0,,你是避免按名调用的\nDialogue: 0,0:57:36.41,0:57:38.38,Default,,0,0,0,,我很想知道 你为什么要这样？\nDialogue: 0,0:57:38.41,0:57:39.21,Default,,0,0,0,,需要这样吗？\nDialogue: 0,0:57:40.07,0:57:41.61,Default,,0,0,0,,教授：Vesko想问的是\nDialogue: 0,0:57:42.06,0:57:46.00,Default,,0,0,0,,基本过程也按名调用是否合理？\nDialogue: 0,0:57:47.14,0:57:48.70,Default,,0,0,0,,答案是：是的\nDialogue: 0,0:57:49.27,0:57:52.32,Default,,0,0,0,,有一种情况下是可以的 实际上是两种\nDialogue: 0,0:57:55.53,0:57:58.27,Default,,0,0,0,,比如用CONS来构造一个数据结构\nDialogue: 0,0:57:59.02,0:58:02.00,Default,,0,0,0,,构建一个元素个数不定的数组时\nDialogue: 0,0:58:03.26,0:58:07.44,Default,,0,0,0,,就没必要求值参数\nDialogue: 0,0:58:07.44,0:58:08.83,Default,,0,0,0,,你只需要创建一些PROMISE\nDialogue: 0,0:58:09.10,0:58:10.81,Default,,0,0,0,,在确实需要时才来求值这些参数\nDialogue: 0,0:58:11.50,0:58:15.08,Default,,0,0,0,,如果我把两个对象CONS起来\nDialogue: 0,0:58:16.24,0:58:17.77,Default,,0,0,0,,那么我CONS这些PROMISE\nDialogue: 0,0:58:17.80,0:58:19.93,Default,,0,0,0,,就和CONS这些对象一样容易\nDialogue: 0,0:58:21.15,0:58:23.37,Default,,0,0,0,,甚至在对它们进行CAR CDR的时候\nDialogue: 0,0:58:23.39,0:58:24.30,Default,,0,0,0,,也不用进行实际的计算\nDialogue: 0,0:58:24.84,0:58:26.97,Default,,0,0,0,,取出PROMISE 并直接传递给其它人\nDialogue: 0,0:58:28.26,0:58:30.51,Default,,0,0,0,,这也就是为什么Alonzo Church用LAMBDA演算\nDialogue: 0,0:58:30.57,0:58:34.03,Default,,0,0,0,,定义的CAR、CDR和CONS说得通的原因\nDialogue: 0,0:58:34.42,0:58:36.32,Default,,0,0,0,,这是因为CAR、CDR以及CONS并没有执行计算\nDialogue: 0,0:58:36.38,0:58:40.06,Default,,0,0,0,,你们可以认为它是在重组数据而已\nDialogue: 0,0:58:40.99,0:58:42.20,Default,,0,0,0,,然而像 + 这样的过程\nDialogue: 0,0:58:42.24,0:58:43.84,Default,,0,0,0,,必须要了解参数是什么\nDialogue: 0,0:58:45.28,0:58:46.91,Default,,0,0,0,,它们需要确认\nDialogue: 0,0:58:47.12,0:58:48.30,Default,,0,0,0,,构成这些数字的比特\nDialogue: 0,0:58:48.32,0:58:50.44,Default,,0,0,0,,除非它们处理的是LAMBDA演算中的数字\nDialogue: 0,0:58:50.44,0:58:51.88,Default,,0,0,0,,这就是另外一码事了\nDialogue: 0,0:58:52.43,0:58:53.58,Default,,0,0,0,,为了运算加法\nDialogue: 0,0:58:53.77,0:58:55.53,Default,,0,0,0,,它需要知道构成数字的比特\nDialogue: 0,0:58:59.21,0:58:59.92,Default,,0,0,0,,因此 实际上\nDialogue: 0,0:59:00.19,0:59:02.78,Default,,0,0,0,,数据的构造过程和选择过程\nDialogue: 0,0:59:03.24,0:59:05.50,Default,,0,0,0,,以及具有副作用的数据对象\nDialogue: 0,0:59:06.27,0:59:09.76,Default,,0,0,0,,在最极端的惰性解释器中\nDialogue: 0,0:59:11.34,0:59:13.39,Default,,0,0,0,,也不需要被FORCE\nDialogue: 0,0:59:16.46,0:59:16.99,Default,,0,0,0,,另外一方面\nDialogue: 0,0:59:17.02,0:59:18.70,Default,,0,0,0,,针对数据结构的谓词需要被FORCE\nDialogue: 0,0:59:19.61,0:59:22.65,Default,,0,0,0,,如果你想判断 这是一个序对吗？\nDialogue: 0,0:59:23.56,0:59:24.40,Default,,0,0,0,,或者是一个符号？\nDialogue: 0,0:59:24.64,0:59:26.57,Default,,0,0,0,,最好搞清楚是什么\nDialogue: 0,0:59:30.30,0:59:31.18,Default,,0,0,0,,还有问题吗？\nDialogue: 0,0:59:40.05,0:59:41.61,Default,,0,0,0,,那好吧 下课\nDialogue: 0,0:59:42.10,1:00:04.56,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:59:42.10,1:00:04.56,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec7b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 6\nVideo Position: 286\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.01,0:00:01.63,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N张大伟\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.63,0:00:09.15,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:01.63,0:00:09.15,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:09.52,0:00:13.66,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 II\nDialogue: 0,0:00:17.21,0:00:17.96,Default,,0,0,0,,教授：目前为止\nDialogue: 0,0:00:19.52,0:00:21.29,Default,,0,0,0,,我们学的东西都非常有趣\nDialogue: 0,0:00:21.52,0:00:23.05,Default,,0,0,0,,但它有什么实际的用途吗？\nDialogue: 0,0:00:26.33,0:00:27.96,Default,,0,0,0,,我想答案是“是的”\nDialogue: 0,0:00:29.38,0:00:31.92,Default,,0,0,0,,这些元循环解释器\nDialogue: 0,0:00:32.96,0:00:34.60,Default,,0,0,0,,非常值得琢磨\nDialogue: 0,0:00:34.62,0:00:36.17,Default,,0,0,0,,我花了大概\nDialogue: 0,0:00:38.05,0:00:41.85,Default,,0,0,0,,曾几何时 我花了半年的功夫\nDialogue: 0,0:00:42.86,0:00:45.26,Default,,0,0,0,,用上节课讲的那种\nDialogue: 0,0:00:45.76,0:00:48.19,Default,,0,0,0,,元循环解释器来试验\nDialogue: 0,0:00:49.47,0:00:52.01,Default,,0,0,0,,各种各样的设计变种\nDialogue: 0,0:00:52.57,0:00:54.11,Default,,0,0,0,,用元循环解释器是因为\nDialogue: 0,0:00:54.72,0:00:56.94,Default,,0,0,0,,它们通过自己定义自己\nDialogue: 0,0:00:56.97,0:00:59.71,Default,,0,0,0,,因此被解释的语言也包含了自己\nDialogue: 0,0:01:01.27,0:01:03.87,Default,,0,0,0,,这样的解释器是一种的媒介\nDialogue: 0,0:01:03.88,0:01:05.58,Default,,0,0,0,,方便我们探索语言问题\nDialogue: 0,0:01:06.80,0:01:09.44,Default,,0,0,0,,如果你想添加一个新的FEATURE\nDialogue: 0,0:01:10.51,0:01:12.38,Default,,0,0,0,,这就是小菜一碟\nDialogue: 0,0:01:12.73,0:01:15.10,Default,,0,0,0,,你只需要稍作修改 然后观察结果\nDialogue: 0,0:01:15.49,0:01:17.20,Default,,0,0,0,,在尝试了一会儿新语言后\nDialogue: 0,0:01:17.24,0:01:18.24,Default,,0,0,0,,你可能觉得它不好\nDialogue: 0,0:01:18.52,0:01:19.47,Default,,0,0,0,,就把它扔到一边去了\nDialogue: 0,0:01:20.96,0:01:23.55,Default,,0,0,0,,或者你也想研究\nDialogue: 0,0:01:23.64,0:01:27.37,Default,,0,0,0,,不同绑定策略的差异\nDialogue: 0,0:01:28.81,0:01:31.90,Default,,0,0,0,,或者是一些更复杂的东西\nDialogue: 0,0:01:33.72,0:01:35.48,Default,,0,0,0,,事实上 这些元循环解释器\nDialogue: 0,0:01:36.17,0:01:37.88,Default,,0,0,0,,非常适合作为交换媒介\nDialogue: 0,0:01:38.20,0:01:42.56,Default,,0,0,0,,用于承载人们关于语言设计想法\nDialogue: 0,0:01:43.98,0:01:45.74,Default,,0,0,0,,因为它们易于理解\nDialogue: 0,0:01:46.28,0:01:48.46,Default,,0,0,0,,它们短小、紧凑而且简洁\nDialogue: 0,0:01:49.32,0:01:50.80,Default,,0,0,0,,如果我有一些点子\nDialogue: 0,0:01:51.53,0:01:53.77,Default,,0,0,0,,想让其它人评论一下\nDialogue: 0,0:01:54.25,0:01:58.32,Default,,0,0,0,,比如Indiana大学的Dan Friedman教授\nDialogue: 0,0:01:59.05,0:02:02.00,Default,,0,0,0,,我就编写一个小型元循环解释器\nDialogue: 0,0:02:02.56,0:02:03.79,Default,,0,0,0,,然后给他发一封电子邮件\nDialogue: 0,0:02:04.65,0:02:05.45,Default,,0,0,0,,并附上解释器\nDialogue: 0,0:02:05.45,0:02:07.90,Default,,0,0,0,,他就可以在计算机上安装并运行\nDialogue: 0,0:02:07.92,0:02:09.82,Default,,0,0,0,,可能他会觉得这个设计并不好\nDialogue: 0,0:02:11.94,0:02:13.10,Default,,0,0,0,,然后他会给我回一封邮件\nDialogue: 0,0:02:13.13,0:02:14.83,Default,,0,0,0,,“为什么不试试这个 这个更好一点”\nDialogue: 0,0:02:16.88,0:02:19.36,Default,,0,0,0,,所以我将会讲一些这方面的技术\nDialogue: 0,0:02:20.16,0:02:24.20,Default,,0,0,0,,因为在设计你自己的特定用途语言时\nDialogue: 0,0:02:24.72,0:02:28.68,Default,,0,0,0,,这种简单的技术非常重要\nDialogue: 0,0:02:30.79,0:02:32.08,Default,,0,0,0,,我们试着先在Lisp中\nDialogue: 0,0:02:32.51,0:02:34.21,Default,,0,0,0,,添加一个非常简单的FEATURE\nDialogue: 0,0:02:40.64,0:02:44.37,Default,,0,0,0,,在这之前 我先来谈谈FEATURE吧\nDialogue: 0,0:02:49.56,0:02:52.17,Default,,0,0,0,,很多语言添加了大量的FEATURE\nDialogue: 0,0:02:53.05,0:02:54.91,Default,,0,0,0,,把它们本身搞得混乱不堪\nDialogue: 0,0:02:56.86,0:02:58.38,Default,,0,0,0,,计算机科学家有一个笑话\nDialogue: 0,0:02:59.28,0:03:02.52,Default,,0,0,0,,“这不是BUG 这是FEATURE”\nDialogue: 0,0:03:05.03,0:03:06.46,Default,,0,0,0,,而我宁愿认为\nDialogue: 0,0:03:08.91,0:03:11.44,Default,,0,0,0,,很多系统都在遭受着“功能蔓延”的影响\nDialogue: 0,0:03:12.82,0:03:13.44,Default,,0,0,0,,比方说\nDialogue: 0,0:03:14.94,0:03:18.16,Default,,0,0,0,,George希望系统中有某个FEATURE\nDialogue: 0,0:03:18.72,0:03:19.36,Default,,0,0,0,,他就加了进来\nDialogue: 0,0:03:20.17,0:03:22.14,Default,,0,0,0,,Harry也想着\nDialogue: 0,0:03:22.17,0:03:24.20,Default,,0,0,0,,这个系统现在也不是我喜欢的那个了\nDialogue: 0,0:03:24.24,0:03:25.92,Default,,0,0,0,,然后加入了自己最喜欢的FEATURE\nDialogue: 0,0:03:26.64,0:03:30.24,Default,,0,0,0,,Jim也这样做\nDialogue: 0,0:03:30.83,0:03:31.79,Default,,0,0,0,,一段时间过后\nDialogue: 0,0:03:31.80,0:03:34.81,Default,,0,0,0,,操作手册就多达500页\nDialogue: 0,0:03:35.15,0:03:36.51,Default,,0,0,0,,以至于没人能看得懂\nDialogue: 0,0:03:37.79,0:03:39.32,Default,,0,0,0,,有时候也可能只是\nDialogue: 0,0:03:39.90,0:03:41.37,Default,,0,0,0,,同一个人在添加FEATURE\nDialogue: 0,0:03:41.39,0:03:43.23,Default,,0,0,0,,也会导致同样糟糕的结果\nDialogue: 0,0:03:44.14,0:03:46.09,Default,,0,0,0,,很多情况下 比如编辑器\nDialogue: 0,0:03:47.37,0:03:49.12,Default,,0,0,0,,具有很多FEATURE就很合理\nDialogue: 0,0:03:50.92,0:03:52.65,Default,,0,0,0,,因为你想要能够完成\nDialogue: 0,0:03:52.68,0:03:53.76,Default,,0,0,0,,各种不同的事情\nDialogue: 0,0:03:56.11,0:03:57.29,Default,,0,0,0,,但对计算机语言来说\nDialogue: 0,0:03:57.85,0:03:58.91,Default,,0,0,0,,我认为太多的FEATURE\nDialogue: 0,0:04:00.01,0:04:01.29,Default,,0,0,0,,是一个灾难\nDialogue: 0,0:04:04.03,0:04:08.00,Default,,0,0,0,,另外 系统也可能变成某种“尖叫的怪物”\nDialogue: 0,0:04:09.52,0:04:11.39,Default,,0,0,0,,假设你有一个盒子\nDialogue: 0,0:04:11.80,0:04:15.29,Default,,0,0,0,,它有一个鼠标和花哨的显示器\nDialogue: 0,0:04:15.95,0:04:20.04,Default,,0,0,0,,这些花哨的IO带来了各种各样的复杂性\nDialogue: 0,0:04:21.01,0:04:22.80,Default,,0,0,0,,你的程序语言就变成了\nDialogue: 0,0:04:23.34,0:04:25.37,Default,,0,0,0,,阴暗无用的小玩意儿\nDialogue: 0,0:04:25.40,0:04:27.90,Default,,0,0,0,,这是由计算机上的视窗系统进行的\nDialogue: 0,0:04:28.09,0:04:29.36,Default,,0,0,0,,内存换页和磁盘抖动所导致的\nDialogue: 0,0:04:30.08,0:04:31.82,Default,,0,0,0,,每当你使用计算机的时候\nDialogue: 0,0:04:31.93,0:04:33.45,Default,,0,0,0,,鼠标处理进程就会唤醒\nDialogue: 0,0:04:33.85,0:04:35.95,Default,,0,0,0,,你有什么事情要我做的吗？\nDialogue: 0,0:04:36.14,0:04:37.23,Default,,0,0,0,,然后又回去休眠\nDialogue: 0,0:04:37.44,0:04:39.44,Default,,0,0,0,,如果你的胳膊肘不小心碰到了鼠标\nDialogue: 0,0:04:39.61,0:04:42.32,Default,,0,0,0,,一大堆烟雾就会从你的电脑出来 类似于这样\nDialogue: 0,0:04:42.94,0:04:45.29,Default,,0,0,0,,这就是由于添加FEATURE\nDialogue: 0,0:04:45.55,0:04:47.21,Default,,0,0,0,,导致系统不能用的两种典型情况\nDialogue: 0,0:04:47.50,0:04:49.73,Default,,0,0,0,,现在我们要添加的是 一个非常简单的FEATURE\nDialogue: 0,0:04:52.60,0:04:53.77,Default,,0,0,0,,这个FEATURE非常好\nDialogue: 0,0:04:53.85,0:04:56.17,Default,,0,0,0,,事实上 Lisp中就有这个FEATURE\nDialogue: 0,0:04:57.25,0:04:58.17,Default,,0,0,0,,我们都知道\nDialogue: 0,0:04:59.29,0:05:03.13,Default,,0,0,0,,像+、*这样的过程\nDialogue: 0,0:05:03.37,0:05:04.89,Default,,0,0,0,,可以接受不定数目的参数\nDialogue: 0,0:05:05.43,0:05:06.44,Default,,0,0,0,,因此我们就可以写\nDialogue: 0,0:05:06.57,0:05:10.94,Default,,0,0,0,,(+ (* A X X)\nDialogue: 0,0:05:12.09,0:05:16.99,Default,,0,0,0,,(* B X) C)\nDialogue: 0,0:05:17.54,0:05:18.68,Default,,0,0,0,,这里可以看到\nDialogue: 0,0:05:18.92,0:05:21.76,Default,,0,0,0,,+有两到三个参数\nDialogue: 0,0:05:22.30,0:05:24.81,Default,,0,0,0,,*也有两到三个参数\nDialogue: 0,0:05:25.08,0:05:26.76,Default,,0,0,0,,不管多少个参数\nDialogue: 0,0:05:26.78,0:05:28.49,Default,,0,0,0,,都应该用同样的方式对待\nDialogue: 0,0:05:30.00,0:05:32.17,Default,,0,0,0,,支持不定数目的参数\nDialogue: 0,0:05:32.28,0:05:34.01,Default,,0,0,0,,这一点非常有用\nDialogue: 0,0:05:34.96,0:05:38.41,Default,,0,0,0,,而我上节课所讲的Lisp求值器\nDialogue: 0,0:05:39.23,0:05:41.85,Default,,0,0,0,,只能处理固定数目的参数\nDialogue: 0,0:05:42.62,0:05:45.28,Default,,0,0,0,,因为我要用BIND过程中的PAIR-UP过程\nDialogue: 0,0:05:45.63,0:05:47.92,Default,,0,0,0,,让形式参数与实际参数一一对应\nDialogue: 0,0:05:50.81,0:05:53.80,Default,,0,0,0,,假如我想能够定义像这样的过程\nDialogue: 0,0:05:54.89,0:05:57.32,Default,,0,0,0,,它们可以接收任意个数的参数\nDialogue: 0,0:05:58.75,0:06:00.40,Default,,0,0,0,,这个问题有好几部分\nDialogue: 0,0:06:01.34,0:06:04.81,Default,,0,0,0,,首先是挑选合适的语法描述\nDialogue: 0,0:06:05.72,0:06:11.21,Default,,0,0,0,,我们需要能够标注额外的参数\nDialogue: 0,0:06:12.17,0:06:13.63,Default,,0,0,0,,标注那些不知道个数的参数\nDialogue: 0,0:06:15.48,0:06:16.62,Default,,0,0,0,,另外就是\nDialogue: 0,0:06:17.10,0:06:18.70,Default,,0,0,0,,一旦我们标注出来后\nDialogue: 0,0:06:19.07,0:06:20.78,Default,,0,0,0,,我们怎样解释这些个记号\nDialogue: 0,0:06:21.74,0:06:23.10,Default,,0,0,0,,才能得到\nDialogue: 0,0:06:23.85,0:06:25.37,Default,,0,0,0,,正确的结果呢？\nDialogue: 0,0:06:26.98,0:06:28.80,Default,,0,0,0,,让我们来考虑一种\nDialogue: 0,0:06:28.84,0:06:30.27,Default,,0,0,0,,我们可能会遇到的情况\nDialogue: 0,0:06:33.07,0:06:34.51,Default,,0,0,0,,比如说\nDialogue: 0,0:06:35.42,0:06:37.34,Default,,0,0,0,,我想要定义这样的一个过程\nDialogue: 0,0:06:37.95,0:06:41.36,Default,,0,0,0,,它有一个必选参数X\nDialogue: 0,0:06:42.20,0:06:45.26,Default,,0,0,0,,还有个可选参数 -- 或者说一堆参数\nDialogue: 0,0:06:45.28,0:06:47.23,Default,,0,0,0,,我不知道它们的数目 就记作Y吧\nDialogue: 0,0:06:49.09,0:06:50.36,Default,,0,0,0,,X是必选的\nDialogue: 0,0:06:55.88,0:06:57.44,Default,,0,0,0,,然而有很多参数Y\nDialogue: 0,0:06:59.53,0:07:05.99,Default,,0,0,0,,这些参数形成的表 -- 我就记作Y\nDialogue: 0,0:07:14.48,0:07:16.06,Default,,0,0,0,,写好了参数表\nDialogue: 0,0:07:16.09,0:07:17.68,Default,,0,0,0,,我现在要这样定义过程体\nDialogue: 0,0:07:19.02,0:07:21.98,Default,,0,0,0,,我要对每一个元素都做同样的处理\nDialogue: 0,0:07:22.52,0:07:25.76,Default,,0,0,0,,(MAP (LAMBDA (U)\nDialogue: 0,0:07:27.00,0:07:34.54,Default,,0,0,0,,(* X U)) Y)\nDialogue: 0,0:07:36.89,0:07:38.04,Default,,0,0,0,,这里 我用了一个“点号”\nDialogue: 0,0:07:38.59,0:07:41.31,Default,,0,0,0,,来表明点号后面的东西\nDialogue: 0,0:07:42.19,0:07:44.30,Default,,0,0,0,,是剩下的所有参数构成的表\nDialogue: 0,0:07:46.30,0:07:48.12,Default,,0,0,0,,这就是一个语法规范\nDialogue: 0,0:07:53.32,0:07:54.64,Default,,0,0,0,,为什么这样来写呢？\nDialogue: 0,0:07:55.71,0:07:58.06,Default,,0,0,0,,这种语法规范之所以合理\nDialogue: 0,0:07:59.77,0:08:01.96,Default,,0,0,0,,是因为Lisp的源码读取器\nDialogue: 0,0:08:02.00,0:08:03.60,Default,,0,0,0,,刚好使用这种语法\nDialogue: 0,0:08:04.41,0:08:07.15,Default,,0,0,0,,来表示序对\nDialogue: 0,0:08:08.94,0:08:11.08,Default,,0,0,0,,我们之前没有介绍过\nDialogue: 0,0:08:11.08,0:08:12.78,Default,,0,0,0,,你在自己尝试的时候可能遇到过\nDialogue: 0,0:08:13.04,0:08:14.62,Default,,0,0,0,,当你调用(CONS X Y)时\nDialogue: 0,0:08:14.89,0:08:18.12,Default,,0,0,0,,你会得到 X . Y\nDialogue: 0,0:08:19.79,0:08:22.83,Default,,0,0,0,,准确来说是(X . Y)\nDialogue: 0,0:08:23.08,0:08:24.64,Default,,0,0,0,,两边还有括号\nDialogue: 0,0:08:26.98,0:08:28.16,Default,,0,0,0,,举例来说吧\nDialogue: 0,0:08:28.97,0:08:35.04,Default,,0,0,0,,这里的(X . Y)对应着一个序对\nDialogue: 0,0:08:36.33,0:08:39.29,Default,,0,0,0,,X是CAR部分 Y是CDR部分\nDialogue: 0,0:08:41.48,0:08:43.98,Default,,0,0,0,,你们目前为止见过的其它记号\nDialogue: 0,0:08:44.94,0:08:46.67,Default,,0,0,0,,是像\nDialogue: 0,0:08:46.92,0:08:55.24,Default,,0,0,0,,(LAMBDA (X Y Z) ...)这样的\nDialogue: 0,0:08:55.71,0:08:57.63,Default,,0,0,0,,它们则是像这样的\nDialogue: 0,0:09:02.00,0:09:03.61,Default,,0,0,0,,就拿形式参数表来说\nDialogue: 0,0:09:04.22,0:09:05.29,Default,,0,0,0,,它实际上是这样\nDialogue: 0,0:09:09.93,0:09:17.32,Default,,0,0,0,,这里分别是 X、Y、Z和空表\nDialogue: 0,0:09:18.28,0:09:21.08,Default,,0,0,0,,如果我有一个想要与之匹配的参数表的话\nDialogue: 0,0:09:22.60,0:09:25.60,Default,,0,0,0,,假设实际参数表是'(1 2 3)\nDialogue: 0,0:09:25.87,0:09:27.26,Default,,0,0,0,,我想把它们和形参相匹配\nDialogue: 0,0:09:28.38,0:09:37.10,Default,,0,0,0,,所以这里 可能有个三个元素的表\nDialogue: 0,0:09:42.44,0:09:46.94,Default,,0,0,0,,分别是1、2、3\nDialogue: 0,0:09:48.99,0:09:53.16,Default,,0,0,0,,用'(1 2 3)来匹配'(X Y Z)\nDialogue: 0,0:09:54.22,0:09:56.28,Default,,0,0,0,,很显然1和X相匹配\nDialogue: 0,0:09:56.32,0:09:58.01,Default,,0,0,0,,因为我可以顺着这个结构来\nDialogue: 0,0:09:58.86,0:10:01.56,Default,,0,0,0,,2和Y相匹配\nDialogue: 0,0:10:02.46,0:10:04.04,Default,,0,0,0,,3和Z相匹配\nDialogue: 0,0:10:05.48,0:10:09.53,Default,,0,0,0,,假设我现在要把这个(X . Y)\nDialogue: 0,0:10:09.55,0:10:11.84,Default,,0,0,0,,这个是(X . Y)\nDialogue: 0,0:10:12.51,0:10:16.91,Default,,0,0,0,,如果我想把它跟'(1 2 3)相匹配的话\nDialogue: 0,0:10:19.08,0:10:20.00,Default,,0,0,0,,我们再来看\nDialogue: 0,0:10:28.00,0:10:30.32,Default,,0,0,0,,这里是1、2、3\nDialogue: 0,0:10:30.86,0:10:32.88,Default,,0,0,0,,我可以沿着这里遍历\nDialogue: 0,0:10:32.99,0:10:35.50,Default,,0,0,0,,会发现 1和X相匹配\nDialogue: 0,0:10:37.56,0:10:41.84,Default,,0,0,0,,而Y和表'(2 3)相匹配\nDialogue: 0,0:10:43.74,0:10:46.22,Default,,0,0,0,,所以这里选用的表示法\nDialogue: 0,0:10:46.41,0:10:50.16,Default,,0,0,0,,对于Lisp来说是非常自然的\nDialogue: 0,0:10:52.66,0:10:54.14,Default,,0,0,0,,所以我就选择用这个记号\nDialogue: 0,0:10:54.17,0:10:55.80,Default,,0,0,0,,来表示数目不定的参数\nDialogue: 0,0:10:58.29,0:11:00.09,Default,,0,0,0,,还有一种可能性\nDialogue: 0,0:11:00.59,0:11:02.78,Default,,0,0,0,,如果我不是特别想命名某个参数\nDialogue: 0,0:11:03.00,0:11:05.00,Default,,0,0,0,,或者是命名某两个参数之类的\nDialogue: 0,0:11:06.54,0:11:07.56,Default,,0,0,0,,如果我不想那样的话\nDialogue: 0,0:11:08.78,0:11:10.44,Default,,0,0,0,,如果我想像+那样\nDialogue: 0,0:11:10.52,0:11:12.52,Default,,0,0,0,,一下子引用所有的参数\nDialogue: 0,0:11:13.88,0:11:17.96,Default,,0,0,0,,那么我就应该把参数表写成\nDialogue: 0,0:11:18.20,0:11:23.45,Default,,0,0,0,,(LAMBDA X ...)\nDialogue: 0,0:11:25.14,0:11:26.30,Default,,0,0,0,,举例来说\nDialogue: 0,0:11:26.81,0:11:27.96,Default,,0,0,0,,如果我定义一个过程\nDialogue: 0,0:11:28.06,0:11:30.44,Default,,0,0,0,,它把接收所有的参数\nDialogue: 0,0:11:31.12,0:11:32.70,Default,,0,0,0,,然后返回一个由它们组成的表X\nDialogue: 0,0:11:34.81,0:11:38.67,Default,,0,0,0,,返回的结果就是过程的参数表 明白吗？\nDialogue: 0,0:11:45.85,0:11:46.67,Default,,0,0,0,,这又是怎么回事呢？\nDialogue: 0,0:11:46.84,0:11:50.06,Default,,0,0,0,,实际上 无论我们的参数表是何种形式\nDialogue: 0,0:11:50.60,0:11:51.45,Default,,0,0,0,,无论是何种形式\nDialogue: 0,0:11:51.61,0:11:53.68,Default,,0,0,0,,都要与实际参数表相匹配\nDialogue: 0,0:11:55.14,0:11:57.14,Default,,0,0,0,,现在 这个符号就是所有的实际参数了\nDialogue: 0,0:12:01.49,0:12:05.13,Default,,0,0,0,,所以 我选择使用这个特定的语法规范\nDialogue: 0,0:12:05.64,0:12:07.63,Default,,0,0,0,,来描述那些\nDialogue: 0,0:12:08.04,0:12:10.56,Default,,0,0,0,,接收不定数目参数的过程\nDialogue: 0,0:12:13.45,0:12:14.60,Default,,0,0,0,,一共有两种情况\nDialogue: 0,0:12:15.40,0:12:16.35,Default,,0,0,0,,上面这种和下面这种\nDialogue: 0,0:12:17.44,0:12:18.36,Default,,0,0,0,,这两种都 --\nDialogue: 0,0:12:18.42,0:12:20.11,Default,,0,0,0,,当你们在制定语法规范时\nDialogue: 0,0:12:20.44,0:12:22.54,Default,,0,0,0,,千万注意不要有歧义\nDialogue: 0,0:12:23.56,0:12:27.36,Default,,0,0,0,,就比如说这里的两种情况\nDialogue: 0,0:12:27.66,0:12:31.20,Default,,0,0,0,,就不要与这里我们已有的这种混淆了\nDialogue: 0,0:12:33.61,0:12:35.82,Default,,0,0,0,,我总是可以区分出\nDialogue: 0,0:12:36.54,0:12:39.80,Default,,0,0,0,,过程的形式参数\nDialogue: 0,0:12:40.28,0:12:41.76,Default,,0,0,0,,是数目固定的具名参数\nDialogue: 0,0:12:42.64,0:12:43.13,Default,,0,0,0,,还是\nDialogue: 0,0:12:43.28,0:12:45.36,Default,,0,0,0,,既有数目固定的具名参数\nDialogue: 0,0:12:45.44,0:12:48.01,Default,,0,0,0,,又跟着数目可变的参数\nDialogue: 0,0:12:49.42,0:12:53.52,Default,,0,0,0,,又或者是所有参数组成的表\nDialogue: 0,0:12:53.68,0:12:56.52,Default,,0,0,0,,这个表会和这里的形式参数X相匹配\nDialogue: 0,0:12:56.99,0:12:58.84,Default,,0,0,0,,我都是可以从语法上区分它们\nDialogue: 0,0:13:02.25,0:13:04.62,Default,,0,0,0,,由于语言中存在语法歧义\nDialogue: 0,0:13:05.04,0:13:08.03,Default,,0,0,0,,整个待解释的程序被错误地分段\nDialogue: 0,0:13:08.64,0:13:13.92,Default,,0,0,0,,从而导致了可怕的错误\nDialogue: 0,0:13:14.56,0:13:16.67,Default,,0,0,0,,类Algol语言中就有些传统问题\nDialogue: 0,0:13:16.67,0:13:23.47,Default,,0,0,0,,就跟谓词部分的嵌套IF语句有关\nDialogue: 0,0:13:25.06,0:13:25.93,Default,,0,0,0,,总之\nDialogue: 0,0:13:27.52,0:13:29.44,Default,,0,0,0,,我现在已经把语法告诉你们了\nDialogue: 0,0:13:30.27,0:13:34.83,Default,,0,0,0,,我们要怎么来处理它的语义呢？\nDialogue: 0,0:13:35.25,0:13:36.11,Default,,0,0,0,,我们如何来解释它？\nDialogue: 0,0:13:36.59,0:13:37.96,Default,,0,0,0,,其实很简单\nDialogue: 0,0:13:38.44,0:13:42.57,Default,,0,0,0,,我修改一下元循环解释器就行\nDialogue: 0,0:13:43.71,0:13:44.76,Default,,0,0,0,,只需修改一行\nDialogue: 0,0:13:45.98,0:13:46.57,Default,,0,0,0,,在这里\nDialogue: 0,0:13:47.53,0:13:49.56,Default,,0,0,0,,我修改一下PAIR-UP过程\nDialogue: 0,0:13:50.81,0:13:54.19,Default,,0,0,0,,这里的PAIR-UP过程把\nDialogue: 0,0:13:56.76,0:14:02.03,Default,,0,0,0,,这是从上节课的元循环求值器中\nDialogue: 0,0:14:04.81,0:14:09.56,Default,,0,0,0,,摘录过来的PAIR-UP过程\nDialogue: 0,0:14:12.16,0:14:16.68,Default,,0,0,0,,它把形式参数与传递过来的实际参数匹配起来\nDialogue: 0,0:14:18.96,0:14:21.93,Default,,0,0,0,,大部分地方都和以前一样\nDialogue: 0,0:14:22.67,0:14:23.23,Default,,0,0,0,,也就是说\nDialogue: 0,0:14:23.31,0:14:25.07,Default,,0,0,0,,如果变量表为空\nDialogue: 0,0:14:25.52,0:14:27.31,Default,,0,0,0,,并且值表也为空\nDialogue: 0,0:14:27.45,0:14:29.61,Default,,0,0,0,,就返回空表\nDialogue: 0,0:14:31.05,0:14:33.00,Default,,0,0,0,,否则就是参数过多\nDialogue: 0,0:14:33.98,0:14:40.19,Default,,0,0,0,,如果变量表为空 但值表非空\nDialogue: 0,0:14:41.58,0:14:44.00,Default,,0,0,0,,如果值表为空\nDialogue: 0,0:14:44.96,0:14:47.47,Default,,0,0,0,,但是变量表又非空\nDialogue: 0,0:14:47.48,0:14:48.56,Default,,0,0,0,,那就是实际参数少了\nDialogue: 0,0:14:48.94,0:14:51.31,Default,,0,0,0,,然而如果我有一个变量是符号的话\nDialogue: 0,0:14:55.53,0:14:56.49,Default,,0,0,0,,这就有意思了\nDialogue: 0,0:14:58.30,0:15:04.40,Default,,0,0,0,,那么 我就认为遇到了特殊情况\nDialogue: 0,0:15:04.59,0:15:06.51,Default,,0,0,0,,也就是尾部分为符号的情况\nDialogue: 0,0:15:08.35,0:15:14.11,Default,,0,0,0,,情况就像这里的一样\nDialogue: 0,0:15:14.90,0:15:17.87,Default,,0,0,0,,这个尾部分就是一个符号Y\nDialogue: 0,0:15:18.63,0:15:19.39,Default,,0,0,0,,它不是NIL\nDialogue: 0,0:15:20.73,0:15:21.72,Default,,0,0,0,,不是个空表\nDialogue: 0,0:15:23.26,0:15:25.60,Default,,0,0,0,,而这个一开始就是个符号\nDialogue: 0,0:15:25.98,0:15:26.81,Default,,0,0,0,,就没有别的东西了\nDialogue: 0,0:15:27.79,0:15:28.72,Default,,0,0,0,,这种情况下\nDialogue: 0,0:15:29.96,0:15:37.20,Default,,0,0,0,,我就用这个符号去匹配所有的值\nDialogue: 0,0:15:38.03,0:15:42.52,Default,,0,0,0,,并把它们添加到要返回的结果中\nDialogue: 0,0:15:44.50,0:15:46.91,Default,,0,0,0,,否则的话 我就像正常情况那样\nDialogue: 0,0:15:47.15,0:15:48.52,Default,,0,0,0,,来创建所有的配对\nDialogue: 0,0:15:52.02,0:15:53.82,Default,,0,0,0,,我认为这很容易理解\nDialogue: 0,0:15:54.51,0:15:55.84,Default,,0,0,0,,就是这些\nDialogue: 0,0:15:57.08,0:15:58.33,Default,,0,0,0,,现在 答疑时间\nDialogue: 0,0:16:02.62,0:16:05.05,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:16:06.60,0:16:06.94,Default,,0,0,0,,你说\nDialogue: 0,0:16:07.37,0:16:09.92,Default,,0,0,0,,学生：你能再解释一下第三种形式吗？\nDialogue: 0,0:16:09.98,0:16:12.12,Default,,0,0,0,,教授：第三种？这个？\nDialogue: 0,0:16:12.59,0:16:14.27,Default,,0,0,0,,或许你用表结构来思考\nDialogue: 0,0:16:14.30,0:16:16.24,Default,,0,0,0,,会更容易理解一些\nDialogue: 0,0:16:18.57,0:16:22.73,Default,,0,0,0,,这是一个过程 包含一个LAMBDA\nDialogue: 0,0:16:25.85,0:16:29.61,Default,,0,0,0,,我画出来的这个表结构就代表上面的这个\nDialogue: 0,0:16:31.26,0:16:32.44,Default,,0,0,0,,这里是X\nDialogue: 0,0:16:32.73,0:16:33.98,Default,,0,0,0,,这些是我们的符号\nDialogue: 0,0:16:37.41,0:16:39.58,Default,,0,0,0,,过程体就是X而已\nDialogue: 0,0:16:44.84,0:16:48.75,Default,,0,0,0,,如果我需要这个过程的形式参数表\nDialogue: 0,0:16:50.09,0:16:51.58,Default,,0,0,0,,我就取它的CADR部分\nDialogue: 0,0:16:52.14,0:16:53.16,Default,,0,0,0,,我会得到一个符号\nDialogue: 0,0:16:54.01,0:16:57.16,Default,,0,0,0,,所以我们的匹配器 -- 也就是我给你们展示的PAIR-UP过程\nDialogue: 0,0:16:58.24,0:17:00.44,Default,,0,0,0,,就会把这个符号对象\nDialogue: 0,0:17:01.56,0:17:04.40,Default,,0,0,0,,跟我们传递的实际参数表相匹配了\nDialogue: 0,0:17:05.76,0:17:09.55,Default,,0,0,0,,这个符号与实际参数表相绑定\nDialogue: 0,0:17:11.37,0:17:16.48,Default,,0,0,0,,而在这个例子中 如果我去取它的话\nDialogue: 0,0:17:16.92,0:17:20.97,Default,,0,0,0,,匹配器就会把它与变量表的这个部分相匹配\nDialogue: 0,0:17:24.14,0:17:26.14,Default,,0,0,0,,如果一个过程只是\nDialogue: 0,0:17:26.17,0:17:29.13,Default,,0,0,0,,直接返回得到的参数表的话 返回的就是一个表\nDialogue: 0,0:17:30.40,0:17:31.39,Default,,0,0,0,,这个过程就是这样的\nDialogue: 0,0:17:34.51,0:17:35.48,Default,,0,0,0,,好吧 谢谢大家\nDialogue: 0,0:17:36.14,0:17:37.28,Default,,0,0,0,,大家休息一下吧\nDialogue: 0,0:17:37.83,0:17:55.36,Default,,0,0,0,,[音乐]\nDialogue: 0,0:17:55.36,0:17:59.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:18:03.53,0:18:07.56,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:18:07.56,0:18:11.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:18:12.25,0:18:16.11,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 II\nDialogue: 0,0:18:20.86,0:18:21.61,Default,,0,0,0,,教授：我们接着来看\nDialogue: 0,0:18:23.26,0:18:26.32,Default,,0,0,0,,现在 我将介绍一种相当重要的变种\nDialogue: 0,0:18:27.45,0:18:31.04,Default,,0,0,0,,这种变体非常有名\nDialogue: 0,0:18:31.60,0:18:36.80,Default,,0,0,0,,早期的很多Lisp都支持它\nDialogue: 0,0:18:38.25,0:18:40.06,Default,,0,0,0,,它被称为变量的动态绑定\nDialogue: 0,0:18:41.77,0:18:44.68,Default,,0,0,0,,我们现在来研究一下它\nDialogue: 0,0:18:47.62,0:18:50.16,Default,,0,0,0,,我先来介绍一下是什么导致\nDialogue: 0,0:18:50.35,0:18:52.36,Default,,0,0,0,,人们产生这样的想法\nDialogue: 0,0:18:53.74,0:18:55.23,Default,,0,0,0,,然而我并不会直接点明原因\nDialogue: 0,0:18:55.40,0:18:57.60,Default,,0,0,0,,我来举一个例子 你们来感受一下\nDialogue: 0,0:18:58.64,0:18:59.93,Default,,0,0,0,,假设\nDialogue: 0,0:19:00.75,0:19:02.59,Default,,0,0,0,,我们再来考察一下\nDialogue: 0,0:19:05.02,0:19:06.43,Default,,0,0,0,,计算一系列数之和的SUM过程\nDialogue: 0,0:19:08.14,0:19:09.47,Default,,0,0,0,,它的参数为\nDialogue: 0,0:19:09.60,0:19:10.78,Default,,0,0,0,,计算当前项的TERM\nDialogue: 0,0:19:13.04,0:19:14.41,Default,,0,0,0,,下界A\nDialogue: 0,0:19:15.24,0:19:17.04,Default,,0,0,0,,计算下一项索引的NEXT\nDialogue: 0,0:19:17.24,0:19:18.56,Default,,0,0,0,,上界B\nDialogue: 0,0:19:19.36,0:19:20.16,Default,,0,0,0,,过程体是\nDialogue: 0,0:19:23.16,0:19:26.94,Default,,0,0,0,,如果A>B\nDialogue: 0,0:19:27.15,0:19:28.64,Default,,0,0,0,,那么结果就是0\nDialogue: 0,0:19:30.24,0:19:31.08,Default,,0,0,0,,否则就是\nDialogue: 0,0:19:33.68,0:19:39.82,Default,,0,0,0,,(+ (TERM A)\nDialogue: 0,0:19:40.60,0:19:44.24,Default,,0,0,0,,(SUM TERM\nDialogue: 0,0:19:47.68,0:19:52.64,Default,,0,0,0,,(NEXT A)\nDialogue: 0,0:20:00.30,0:20:03.56,Default,,0,0,0,,这个NEXT过程直接传递过去\nDialogue: 0,0:20:06.40,0:20:08.25,Default,,0,0,0,,上界B也直接传递过去\nDialogue: 0,0:20:14.51,0:20:15.76,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:20:17.82,0:20:21.45,Default,,0,0,0,,当我使用SUM过程的时候\nDialogue: 0,0:20:21.96,0:20:24.35,Default,,0,0,0,,我可以像这样来用\nDialogue: 0,0:20:25.45,0:20:38.04,Default,,0,0,0,,我们可以把SUM-POWERS过程定义为\nDialogue: 0,0:20:38.08,0:20:40.33,Default,,0,0,0,,这个函数是用来计算Σ(X^N)的\nDialogue: 0,0:20:41.10,0:20:45.93,Default,,0,0,0,,它的参数有A、B以及N\nDialogue: 0,0:20:45.95,0:20:47.69,Default,,0,0,0,,分别指下界、上界以及指数\nDialogue: 0,0:20:48.06,0:20:53.34,Default,,0,0,0,,它的定义是(SUM (LAMBDA (X)\nDialogue: 0,0:20:53.60,0:20:59.31,Default,,0,0,0,,这个参数为X的过程计算(EXPT X N)\nDialogue: 0,0:21:02.19,0:21:09.29,Default,,0,0,0,,我们还要传递A、1+还有B\nDialogue: 0,0:21:11.82,0:21:15.76,Default,,0,0,0,,因此 给定一系列X 我们计算Σ(X^N)的值\nDialogue: 0,0:21:16.14,0:21:19.74,Default,,0,0,0,,X从A到B取值 步长为1\nDialogue: 0,0:21:22.94,0:21:24.38,Default,,0,0,0,,我也可以定义--\nDialogue: 0,0:21:27.68,0:21:28.20,Default,,0,0,0,,好像这里有点问题\nDialogue: 0,0:21:29.78,0:21:31.02,Default,,0,0,0,,不好意思\nDialogue: 0,0:21:31.91,0:21:33.36,Default,,0,0,0,,这里应该是PRODUCT-POWERS\nDialogue: 0,0:21:38.08,0:21:39.12,Default,,0,0,0,,名字有点奇怪\nDialogue: 0,0:21:40.02,0:21:40.80,Default,,0,0,0,,还是不改了\nDialogue: 0,0:21:41.96,0:21:46.32,Default,,0,0,0,,有点怪 就按原来的吧\nDialogue: 0,0:21:49.34,0:21:50.19,Default,,0,0,0,,这回应该对了\nDialogue: 0,0:21:51.37,0:21:53.82,Default,,0,0,0,,而PRODUCT-POWERS的定义则是\nDialogue: 0,0:21:58.41,0:22:02.36,Default,,0,0,0,,（意义不明）\nDialogue: 0,0:22:03.00,0:22:06.81,Default,,0,0,0,,我可以用像SUM一样的过程\nDialogue: 0,0:22:06.81,0:22:08.22,Default,,0,0,0,,只不过是用来计算乘积的\nDialogue: 0,0:22:08.56,0:22:11.05,Default,,0,0,0,,但是很类似 就跟你们在那里见到的一样\nDialogue: 0,0:22:11.45,0:22:16.38,Default,,0,0,0,,它也是一个三参数的过程\nDialogue: 0,0:22:17.00,0:22:25.42,Default,,0,0,0,,求积的因数是通过构造而来\nDialogue: 0,0:22:25.66,0:22:31.60,Default,,0,0,0,,也就是(PRODUCT (LAMBDA (X) (EXPT X N))\nDialogue: 0,0:22:34.43,0:22:37.85,Default,,0,0,0,,下界是A 步长为1 上界为B\nDialogue: 0,0:22:41.53,0:22:41.88,Default,,0,0,0,,现在\nDialogue: 0,0:22:46.83,0:22:49.50,Default,,0,0,0,,你可能马上就意识到一些问题\nDialogue: 0,0:22:50.75,0:22:52.01,Default,,0,0,0,,它们看起来几乎一样\nDialogue: 0,0:22:53.18,0:22:55.20,Default,,0,0,0,,为什么要重复写代码呢？\nDialogue: 0,0:22:56.59,0:22:59.72,Default,,0,0,0,,现在就很像我们之前遇到的情况了\nDialogue: 0,0:23:01.00,0:23:03.15,Default,,0,0,0,,构建一个抽象不是更好吗？\nDialogue: 0,0:23:03.81,0:23:05.76,Default,,0,0,0,,如何构建良好的抽象呢？\nDialogue: 0,0:23:05.85,0:23:07.55,Default,,0,0,0,,我看到有一些完全相同的代码\nDialogue: 0,0:23:08.47,0:23:09.32,Default,,0,0,0,,这有一段\nDialogue: 0,0:23:09.98,0:23:11.08,Default,,0,0,0,,这是另一段\nDialogue: 0,0:23:14.45,0:23:16.22,Default,,0,0,0,,所以我应该把它们提取出来\nDialogue: 0,0:23:17.09,0:23:19.23,Default,,0,0,0,,我就会想\nDialogue: 0,0:23:20.51,0:23:22.67,Default,,0,0,0,,SUM-POWERS可以用\nDialogue: 0,0:23:22.88,0:23:24.52,Default,,0,0,0,,NTH-POWERS的过程来编写\nDialogue: 0,0:23:25.71,0:23:27.40,Default,,0,0,0,,假如有人想写一个\nDialogue: 0,0:23:27.74,0:23:30.03,Default,,0,0,0,,稍微不同的过程 就像这个一样\nDialogue: 0,0:23:37.63,0:23:45.18,Default,,0,0,0,,(DEFINE SUM-POWERS\nDialogue: 0,0:23:46.44,0:23:48.46,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:23:48.75,0:23:52.27,Default,,0,0,0,,(SUM (NTH-POWER\nDialogue: 0,0:23:53.88,0:23:55.42,Default,,0,0,0,,我们调用过程NTH-POWER\nDialogue: 0,0:23:58.35,0:24:02.27,Default,,0,0,0,,下界为A 步长为1 上界为B\nDialogue: 0,0:24:05.74,0:24:06.91,Default,,0,0,0,,类似地\nDialogue: 0,0:24:10.65,0:24:12.76,Default,,0,0,0,,我想用这种方式来重写PRODUCT-POWERS\nDialogue: 0,0:24:12.89,0:24:15.24,Default,,0,0,0,,把求幂指数从这里抽象出来\nDialogue: 0,0:24:16.27,0:24:17.37,Default,,0,0,0,,可以这样写\nDialogue: 0,0:24:22.10,0:24:23.02,Default,,0,0,0,,(DEFINE PRODUCT-POWERS\nDialogue: 0,0:24:29.48,0:24:34.94,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:24:35.31,0:24:42.33,Default,,0,0,0,,(PRODUCT NTH-POWERS\nDialogue: 0,0:24:46.44,0:24:50.30,Default,,0,0,0,,A 1+ B)))\nDialogue: 0,0:24:53.50,0:24:57.56,Default,,0,0,0,,把NTH-POWER的结果作为PRODUCT的参数\nDialogue: 0,0:24:58.38,0:25:00.24,Default,,0,0,0,,我们还需要定义\nDialogue: 0,0:25:02.04,0:25:03.88,Default,,0,0,0,,还需要定义过程NTH-POWERS\nDialogue: 0,0:25:04.89,0:25:05.93,Default,,0,0,0,,我把它写在这边\nDialogue: 0,0:25:12.22,0:25:12.99,Default,,0,0,0,,写在上面\nDialogue: 0,0:25:25.41,0:25:29.04,Default,,0,0,0,,它是一个参数为X的过程\nDialogue: 0,0:25:29.60,0:25:34.56,Default,,0,0,0,,计算(EXPT X N)\nDialogue: 0,0:25:35.93,0:25:36.96,Default,,0,0,0,,但是我遇到一个问题\nDialogue: 0,0:25:38.64,0:25:39.93,Default,,0,0,0,,我们使用的环境模型\nDialogue: 0,0:25:40.57,0:25:43.23,Default,,0,0,0,,我们用来解释\nDialogue: 0,0:25:44.00,0:25:45.95,Default,,0,0,0,,目前所定义的语言的这种手段\nDialogue: 0,0:25:46.27,0:25:48.81,Default,,0,0,0,,并没有给我说明这个N的值\nDialogue: 0,0:25:52.76,0:25:59.26,Default,,0,0,0,,因为 正如大家所知\nDialogue: 0,0:26:00.76,0:26:04.25,Default,,0,0,0,,在这个过程中 N是自由变量\nDialogue: 0,0:26:06.41,0:26:07.98,Default,,0,0,0,,环境模型告诉我们\nDialogue: 0,0:26:08.60,0:26:10.20,Default,,0,0,0,,自由变量的值\nDialogue: 0,0:26:11.21,0:26:14.99,Default,,0,0,0,,取决于过程被定义时所在的环境\nDialogue: 0,0:26:16.64,0:26:17.47,Default,,0,0,0,,在我编写它们的时候\nDialogue: 0,0:26:17.48,0:26:19.84,Default,,0,0,0,,就假设它们已经在黑板上被定义了\nDialogue: 0,0:26:21.64,0:26:23.63,Default,,0,0,0,,NTH-POWER是定义在全局环境下的\nDialogue: 0,0:26:24.06,0:26:25.15,Default,,0,0,0,,其中没有N的定义\nDialogue: 0,0:26:25.93,0:26:27.63,Default,,0,0,0,,因此 N是未绑定的变量\nDialogue: 0,0:26:28.72,0:26:31.66,Default,,0,0,0,,但对我们来说\nDialogue: 0,0:26:32.60,0:26:36.32,Default,,0,0,0,,我们明确希望它是这里和这里的N\nDialogue: 0,0:26:38.99,0:26:42.67,Default,,0,0,0,,另外一方面\nDialogue: 0,0:26:42.84,0:26:44.28,Default,,0,0,0,,当然我们要十分小心地确保\nDialogue: 0,0:26:44.56,0:26:46.06,Default,,0,0,0,,这里的N是这里的N\nDialogue: 0,0:26:48.96,0:26:52.83,Default,,0,0,0,,还有这里的这个 要跟这里的一致\nDialogue: 0,0:26:57.39,0:26:59.74,Default,,0,0,0,,这种想法造就了\nDialogue: 0,0:27:00.67,0:27:02.72,Default,,0,0,0,,一个非常著名的BUG\nDialogue: 0,0:27:04.65,0:27:06.04,Default,,0,0,0,,我来细说下这个BUG\nDialogue: 0,0:27:07.15,0:27:09.40,Default,,0,0,0,,请看这张幻灯片\nDialogue: 0,0:27:10.66,0:27:12.70,Default,,0,0,0,,这种想法被称作“动态绑定”\nDialogue: 0,0:27:13.99,0:27:16.91,Default,,0,0,0,,在这种情况下 自由变量不再被\nDialogue: 0,0:27:17.76,0:27:21.23,Default,,0,0,0,,定义过程时的环境所解释\nDialogue: 0,0:27:22.40,0:27:25.16,Default,,0,0,0,,这种情况下 自由变量的值\nDialogue: 0,0:27:25.44,0:27:29.31,Default,,0,0,0,,就像是存储在过程调用者的环境中一样\nDialogue: 0,0:27:31.85,0:27:34.84,Default,,0,0,0,,所以在这个系统中\nDialogue: 0,0:27:34.86,0:27:39.68,Default,,0,0,0,,你需要不断地搜索调用过程的调用者的环境\nDialogue: 0,0:27:40.43,0:27:42.65,Default,,0,0,0,,当然 在本例中\nDialogue: 0,0:27:42.84,0:27:44.30,Default,,0,0,0,,无论NTH-POWER在何处定义\nDialogue: 0,0:27:44.33,0:27:45.98,Default,,0,0,0,,它都是在PRODUCT过程中被调用的\nDialogue: 0,0:27:46.41,0:27:48.68,Default,,0,0,0,,我就需要在SUM过程中再编写一个类似的过程\nDialogue: 0,0:27:50.51,0:27:54.92,Default,,0,0,0,,而PRODUCT又是被PRODUCT-POWERS所调用\nDialogue: 0,0:27:55.13,0:27:56.14,Default,,0,0,0,,就是你们在这里看到的\nDialogue: 0,0:27:56.83,0:27:59.37,Default,,0,0,0,,由于PRODUCT-POWERS过程绑定了变量N\nDialogue: 0,0:28:00.09,0:28:04.09,Default,,0,0,0,,因此NTH-POWER中的N会从这个链中派生出来\nDialogue: 0,0:28:08.14,0:28:09.64,Default,,0,0,0,,相似地 这个N\nDialogue: 0,0:28:10.11,0:28:12.01,Default,,0,0,0,,NTH-POWER中的N在这种情况下\nDialogue: 0,0:28:12.32,0:28:15.80,Default,,0,0,0,,可能是来自于这里SUM过程的调用\nDialogue: 0,0:28:15.80,0:28:18.27,Default,,0,0,0,,你们可以从这里看到 它在SUM内部被调用\nDialogue: 0,0:28:20.73,0:28:21.69,Default,,0,0,0,,对应这里的TERM\nDialogue: 0,0:28:22.90,0:28:25.72,Default,,0,0,0,,而SUM是在SUM-POWERS的内部被调用\nDialogue: 0,0:28:26.94,0:28:27.96,Default,,0,0,0,,后者绑定了N\nDialogue: 0,0:28:28.93,0:28:30.65,Default,,0,0,0,,因此这里就有一个N\nDialogue: 0,0:28:32.75,0:28:36.11,Default,,0,0,0,,可供NTH-POWER中的N取值\nDialogue: 0,0:28:37.95,0:28:39.24,Default,,0,0,0,,这就是动态 --\nDialogue: 0,0:28:39.28,0:28:43.10,Default,,0,0,0,,这条白线以下的东西 再加上这部分\nDialogue: 0,0:28:43.31,0:28:46.04,Default,,0,0,0,,就是我们所谓的动态绑定\nDialogue: 0,0:28:46.59,0:28:49.00,Default,,0,0,0,,用动态绑定的角度来解释 就可以正常运行\nDialogue: 0,0:28:50.85,0:28:52.65,Default,,0,0,0,,现在 让我们来看一个例子\nDialogue: 0,0:28:54.54,0:28:55.99,Default,,0,0,0,,要怎么实现这个功能\nDialogue: 0,0:28:55.99,0:28:56.96,Default,,0,0,0,,非常简单\nDialogue: 0,0:28:57.48,0:28:59.34,Default,,0,0,0,,事实上 最早的Lisp实现\nDialogue: 0,0:29:00.01,0:29:02.52,Default,,0,0,0,,对自由变量有各种形式的解释\nDialogue: 0,0:29:03.31,0:29:05.98,Default,,0,0,0,,包括用动态绑定来解释自由变量\nDialogue: 0,0:29:06.40,0:29:10.14,Default,,0,0,0,,APL也是用动态绑定来解释自由变量的\nDialogue: 0,0:29:11.68,0:29:14.32,Default,,0,0,0,,而不是词法绑定 或者说静态绑定\nDialogue: 0,0:29:15.22,0:29:17.00,Default,,0,0,0,,当然 要从EVAL开始修改\nDialogue: 0,0:29:19.31,0:29:20.59,Default,,0,0,0,,只需修改两个地方就行\nDialogue: 0,0:29:22.78,0:29:25.61,Default,,0,0,0,,首先我们会发现\nDialogue: 0,0:29:26.52,0:29:28.49,Default,,0,0,0,,事情变得更简单了\nDialogue: 0,0:29:29.39,0:29:33.63,Default,,0,0,0,,如果我不需要\nDialogue: 0,0:29:33.64,0:29:36.20,Default,,0,0,0,,在定义过程的那个环境中求值\nDialogue: 0,0:29:36.44,0:29:38.04,Default,,0,0,0,,过程在定义的时候就无需\nDialogue: 0,0:29:38.43,0:29:40.17,Default,,0,0,0,,捕获当时的环境了\nDialogue: 0,0:29:42.03,0:29:44.96,Default,,0,0,0,,所以我们可以在幻灯片的这里看到\nDialogue: 0,0:29:45.84,0:29:50.08,Default,,0,0,0,,这条用于判断是否为LAMBDA表达式的子句\nDialogue: 0,0:29:50.73,0:29:52.43,Default,,0,0,0,,过程就是在这个时候创建的\nDialogue: 0,0:29:53.92,0:29:56.73,Default,,0,0,0,,就不会返回一个带有类型标签\nDialogue: 0,0:29:56.75,0:30:01.05,Default,,0,0,0,,和环境结构的过程对象了\nDialogue: 0,0:30:01.29,0:30:02.54,Default,,0,0,0,,就是EXP本身\nDialogue: 0,0:30:02.54,0:30:04.76,Default,,0,0,0,,而我们会在其它地方用某种方式来解耦\nDialogue: 0,0:30:06.44,0:30:09.40,Default,,0,0,0,,另外一处修改就是组合式的应用\nDialogue: 0,0:30:10.36,0:30:13.69,Default,,0,0,0,,应用的时候必须要取得调用者的环境\nDialogue: 0,0:30:14.29,0:30:17.24,Default,,0,0,0,,调用者的环境就在这里\nDialogue: 0,0:30:17.26,0:30:19.45,Default,,0,0,0,,如果表达式是一个过程应用--\nDialogue: 0,0:30:19.56,0:30:21.63,Default,,0,0,0,,如果我们求值的是一个组合式\nDialogue: 0,0:30:21.79,0:30:23.71,Default,,0,0,0,,我们就会调用一个组合式\nDialogue: 0,0:30:23.93,0:30:25.50,Default,,0,0,0,,调用一个过程\nDialogue: 0,0:30:25.66,0:30:27.37,Default,,0,0,0,,来取得运算符的值\nDialogue: 0,0:30:29.84,0:30:31.44,Default,,0,0,0,,调用者的环境\nDialogue: 0,0:30:31.98,0:30:34.51,Default,,0,0,0,,就是我们当前的环境\nDialogue: 0,0:30:35.89,0:30:40.72,Default,,0,0,0,,所以 我只需要要把这个环境传递给APPLY\nDialogue: 0,0:30:41.49,0:30:42.75,Default,,0,0,0,,我们再来看看APPLY\nDialogue: 0,0:30:43.58,0:30:44.97,Default,,0,0,0,,我们只需要\nDialogue: 0,0:30:45.71,0:30:48.41,Default,,0,0,0,,把参数列表加上一个环境ENV\nDialogue: 0,0:30:48.78,0:30:55.68,Default,,0,0,0,,然后用这个环境来扩展环境\nDialogue: 0,0:30:56.67,0:30:59.02,Default,,0,0,0,,扩展把形式参数\nDialogue: 0,0:30:59.02,0:31:01.37,Default,,0,0,0,,和传递过来的实际参数绑定在一起的环境\nDialogue: 0,0:31:03.08,0:31:05.98,Default,,0,0,0,,而不再是之前由过程捕获的环境了\nDialogue: 0,0:31:06.81,0:31:09.45,Default,,0,0,0,,最早的Lisp偶然地采用了\nDialogue: 0,0:31:09.66,0:31:11.96,Default,,0,0,0,,这种最显然的方式实现\nDialogue: 0,0:31:14.13,0:31:16.68,Default,,0,0,0,,当然 像往常一样 人们习惯了并喜欢上了它\nDialogue: 0,0:31:17.25,0:31:18.27,Default,,0,0,0,,因此就有一些人说\nDialogue: 0,0:31:18.40,0:31:19.50,Default,,0,0,0,,“就应该这么来做”\nDialogue: 0,0:31:21.59,0:31:24.09,Default,,0,0,0,,不幸的是 这导致一些严重的问题\nDialogue: 0,0:31:25.40,0:31:27.24,Default,,0,0,0,,最严重的一点是\nDialogue: 0,0:31:27.53,0:31:29.84,Default,,0,0,0,,采用动态绑定\nDialogue: 0,0:31:31.00,0:31:33.56,Default,,0,0,0,,破坏了模块性\nDialogue: 0,0:31:35.46,0:31:37.66,Default,,0,0,0,,如果有两个人在一个大型系统上协同工作\nDialogue: 0,0:31:38.57,0:31:40.01,Default,,0,0,0,,那么一个重要的原则就是\nDialogue: 0,0:31:40.35,0:31:42.19,Default,,0,0,0,,每个人所使用的名字\nDialogue: 0,0:31:42.99,0:31:44.58,Default,,0,0,0,,都不应该干扰到对方的名字\nDialogue: 0,0:31:47.93,0:31:50.78,Default,,0,0,0,,如果我写了一段代码\nDialogue: 0,0:31:51.07,0:31:53.13,Default,,0,0,0,,别人就不能通过在他代码内部\nDialogue: 0,0:31:53.88,0:31:56.57,Default,,0,0,0,,使用我代码中的名字来破坏我的代码\nDialogue: 0,0:31:56.75,0:31:57.71,Default,,0,0,0,,这一点很重要\nDialogue: 0,0:31:59.85,0:32:00.46,Default,,0,0,0,,然而\nDialogue: 0,0:32:01.04,0:32:05.18,Default,,0,0,0,,动态绑定明显地违背了这种特定的模块化约束\nDialogue: 0,0:32:06.67,0:32:08.08,Default,,0,0,0,,我们考虑一下\nDialogue: 0,0:32:09.18,0:32:10.35,Default,,0,0,0,,这段代码会有什么效果？\nDialogue: 0,0:32:12.54,0:32:13.79,Default,,0,0,0,,假设我想要把\nDialogue: 0,0:32:15.47,0:32:19.81,Default,,0,0,0,,我想要把变量NEXT换个名字\nDialogue: 0,0:32:19.81,0:32:24.41,Default,,0,0,0,,假设某个人要编写SUM过程\nDialogue: 0,0:32:25.10,0:32:26.68,Default,,0,0,0,,而别人则会使用这个SUM过程\nDialogue: 0,0:32:28.97,0:32:30.32,Default,,0,0,0,,编写SUM的那个人\nDialogue: 0,0:32:30.49,0:32:32.30,Default,,0,0,0,,可以选择他想要使用的名字\nDialogue: 0,0:32:33.66,0:32:34.84,Default,,0,0,0,,假设我就是那个编写者\nDialogue: 0,0:32:36.83,0:32:39.30,Default,,0,0,0,,刚巧 这里我不想用NEXT来表示\nDialogue: 0,0:32:39.30,0:32:40.09,Default,,0,0,0,,而是用N来表示\nDialogue: 0,0:32:41.74,0:32:43.10,Default,,0,0,0,,所以我把所有出现NEXT的地方\nDialogue: 0,0:32:44.28,0:32:45.26,Default,,0,0,0,,都换成N\nDialogue: 0,0:32:48.14,0:32:48.48,Default,,0,0,0,,哎呀\nDialogue: 0,0:32:49.94,0:32:52.22,Default,,0,0,0,,我没有改变这个程序的规范\nDialogue: 0,0:32:53.32,0:32:54.86,Default,,0,0,0,,但是整个程序就崩溃了\nDialogue: 0,0:32:56.11,0:32:57.96,Default,,0,0,0,,不仅如此 这边也出现了问题\nDialogue: 0,0:32:59.50,0:33:01.40,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:33:02.26,0:33:03.24,Default,,0,0,0,,答案非常明显\nDialogue: 0,0:33:04.48,0:33:09.29,Default,,0,0,0,,NTH-POWER中的变量N的值\nDialogue: 0,0:33:09.31,0:33:13.72,Default,,0,0,0,,也就是这个N和这个N\nDialogue: 0,0:33:14.97,0:33:17.16,Default,,0,0,0,,根据环境模型的定义\nDialogue: 0,0:33:17.20,0:33:19.58,Default,,0,0,0,,这两个N总是相关的\nDialogue: 0,0:33:19.87,0:33:21.48,Default,,0,0,0,,如果是根据环境模型的定义的话\nDialogue: 0,0:33:21.55,0:33:23.63,Default,,0,0,0,,因为N在这里被绑定\nDialogue: 0,0:33:24.37,0:33:26.25,Default,,0,0,0,,这个LAMBDA表达式是在\nDialogue: 0,0:33:26.59,0:33:28.59,Default,,0,0,0,,N被绑定的环境中执行的\nDialogue: 0,0:33:30.70,0:33:31.84,Default,,0,0,0,,如果不用环境模型的话\nDialogue: 0,0:33:32.01,0:33:33.68,Default,,0,0,0,,我必须追踪过程的调用链\nDialogue: 0,0:33:34.78,0:33:36.27,Default,,0,0,0,,那么就会发生糟糕的事儿\nDialogue: 0,0:33:37.32,0:33:41.18,Default,,0,0,0,,在SUM内部 这个是作为TERM调用的\nDialogue: 0,0:33:41.76,0:33:42.38,Default,,0,0,0,,这里的(TERM A)\nDialogue: 0,0:33:44.78,0:33:46.19,Default,,0,0,0,,这时再来查找N的值\nDialogue: 0,0:33:47.35,0:33:48.40,Default,,0,0,0,,我得到的不知这个值\nDialogue: 0,0:33:48.84,0:33:49.76,Default,,0,0,0,,而是这个值\nDialogue: 0,0:33:50.70,0:33:52.54,Default,,0,0,0,,因此 只是这个程序的内部做了修改\nDialogue: 0,0:33:52.86,0:33:54.09,Default,,0,0,0,,这个程序却崩溃了\nDialogue: 0,0:33:56.77,0:34:00.08,Default,,0,0,0,,LAMBDA就不再像我以前说得那样是个量词了\nDialogue: 0,0:34:01.12,0:34:05.13,Default,,0,0,0,,LAMBDA应该是一个量词\nDialogue: 0,0:34:05.43,0:34:06.70,Default,,0,0,0,,量词有一个性质\nDialogue: 0,0:34:06.89,0:34:11.42,Default,,0,0,0,,被它绑定的名字都不重要\nDialogue: 0,0:34:12.65,0:34:15.71,Default,,0,0,0,,只要我用不在过程体中的新名字\nDialogue: 0,0:34:16.92,0:34:19.98,Default,,0,0,0,,统一地在过程体中代换旧名字\nDialogue: 0,0:34:20.94,0:34:23.16,Default,,0,0,0,,就不会改变表达式的语义\nDialogue: 0,0:34:24.04,0:34:25.50,Default,,0,0,0,,而我刚才却通过修改一个名字\nDialogue: 0,0:34:25.53,0:34:27.20,Default,,0,0,0,,改变了表达式的语义\nDialogue: 0,0:34:28.69,0:34:30.89,Default,,0,0,0,,因此LAMBDA就不再是一个良好定义的量词了\nDialogue: 0,0:34:32.17,0:34:33.37,Default,,0,0,0,,这个问题非常严重\nDialogue: 0,0:34:34.55,0:34:35.55,Default,,0,0,0,,正是因为这个原因\nDialogue: 0,0:34:36.64,0:34:42.51,Default,,0,0,0,,我和同事放弃了这种抽象方法\nDialogue: 0,0:34:43.13,0:34:44.36,Default,,0,0,0,,相对的 我更喜欢\nDialogue: 0,0:34:45.61,0:34:47.50,Default,,0,0,0,,模块化原则\nDialogue: 0,0:34:48.09,0:34:50.20,Default,,0,0,0,,如果你愿意探索解释器\nDialogue: 0,0:34:51.96,0:34:53.68,Default,,0,0,0,,那就非常值得做这类实验\nDialogue: 0,0:34:54.83,0:34:56.91,Default,,0,0,0,,你可以尝试多种设计\nDialogue: 0,0:34:58.11,0:35:00.25,Default,,0,0,0,,探索更优雅的语言设计\nDialogue: 0,0:35:02.68,0:35:04.49,Default,,0,0,0,,这是元循环求值器非常重要的功能\nDialogue: 0,0:35:04.99,0:35:06.68,Default,,0,0,0,,现在 我也想讲一讲\nDialogue: 0,0:35:06.72,0:35:08.49,Default,,0,0,0,,这种情况下的正确做法\nDialogue: 0,0:35:09.32,0:35:12.91,Default,,0,0,0,,我又如何来获得这种\nDialogue: 0,0:35:13.04,0:35:15.34,Default,,0,0,0,,词法作用域的能力呢？\nDialogue: 0,0:35:16.28,0:35:17.39,Default,,0,0,0,,当然 实际情况是\nDialogue: 0,0:35:17.55,0:35:20.03,Default,,0,0,0,,在这里我想要的是\nDialogue: 0,0:35:20.68,0:35:22.60,Default,,0,0,0,,针对特定N的求指数函数\nDialogue: 0,0:35:23.69,0:35:24.28,Default,,0,0,0,,给定一个N\nDialogue: 0,0:35:24.32,0:35:25.66,Default,,0,0,0,,它会返回给我一个特定的求指数过程\nDialogue: 0,0:35:26.28,0:35:27.40,Default,,0,0,0,,这非常简单\nDialogue: 0,0:35:28.17,0:35:30.57,Default,,0,0,0,,换言之 我可以这样来写\nDialogue: 0,0:35:35.84,0:35:37.84,Default,,0,0,0,,我要定义一个过程PGEN\nDialogue: 0,0:35:40.25,0:35:42.54,Default,,0,0,0,,它有一个参数N\nDialogue: 0,0:35:43.16,0:35:45.95,Default,,0,0,0,,返回一个指数过程\nDialogue: 0,0:35:50.24,0:35:51.23,Default,,0,0,0,,计算X^N\nDialogue: 0,0:35:56.80,0:35:57.98,Default,,0,0,0,,有了这个以后\nDialogue: 0,0:35:58.59,0:36:00.88,Default,,0,0,0,,我就可以进行想要的那种抽象\nDialogue: 0,0:36:01.42,0:36:03.93,Default,,0,0,0,,甚至于现在的封装方法还要更好一些\nDialogue: 0,0:36:04.09,0:36:06.60,Default,,0,0,0,,因为系统现在不会因改名而崩溃了\nDialogue: 0,0:36:07.89,0:36:12.35,Default,,0,0,0,,(DEFINE SUM-POWERS\nDialogue: 0,0:36:17.28,0:36:20.70,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:36:21.61,0:36:26.83,Default,,0,0,0,,(SUM\nDialogue: 0,0:36:26.88,0:36:32.32,Default,,0,0,0,,(PGEN N)\nDialogue: 0,0:36:34.40,0:36:38.01,Default,,0,0,0,,A 1+ B)))\nDialogue: 0,0:36:42.49,0:36:47.95,Default,,0,0,0,,(DEFINE PRODUCT-POWERS\nDialogue: 0,0:36:54.11,0:36:58.84,Default,,0,0,0,,(LAMBDA (A B N)\nDialogue: 0,0:36:59.80,0:37:09.96,Default,,0,0,0,,(PRODUCT (PGEN N) A 1+ B)))\nDialogue: 0,0:37:11.28,0:37:13.28,Default,,0,0,0,,当然 这只是一个非常简单的例子\nDialogue: 0,0:37:13.60,0:37:16.35,Default,,0,0,0,,这里 我想要抽象的对象也十分简单\nDialogue: 0,0:37:17.28,0:37:18.83,Default,,0,0,0,,但它也有可能是长达100行的代码\nDialogue: 0,0:37:20.10,0:37:23.67,Default,,0,0,0,,我这么写是为了保持简单\nDialogue: 0,0:37:23.67,0:37:24.57,Default,,0,0,0,,我给它命了名\nDialogue: 0,0:37:24.73,0:37:26.94,Default,,0,0,0,,这里它只是一个参数化的名字\nDialogue: 0,0:37:28.20,0:37:30.27,Default,,0,0,0,,这个名字显式地依赖于\nDialogue: 0,0:37:30.49,0:37:33.63,Default,,0,0,0,,词法作用域下N的值\nDialogue: 0,0:37:37.13,0:37:38.59,Default,,0,0,0,,因此可以把它看做一个很长的名字\nDialogue: 0,0:37:40.21,0:37:41.58,Default,,0,0,0,,这里 我是通过\nDialogue: 0,0:37:41.76,0:37:45.82,Default,,0,0,0,,为计算TERM的过程命名\nDialogue: 0,0:37:46.12,0:37:49.22,Default,,0,0,0,,来解决问题的\nDialogue: 0,0:37:55.08,0:37:55.87,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:37:57.00,0:37:58.38,Default,,0,0,0,,David 你说\nDialogue: 0,0:37:58.57,0:38:02.27,Default,,0,0,0,,学生：刚才那个问题\nDialogue: 0,0:38:03.07,0:38:06.46,Default,,0,0,0,,只能通过新建一个过程来解决吗？\nDialogue: 0,0:38:06.47,0:38:08.92,Default,,0,0,0,,换句话说 是不是必须要语言能够\nDialogue: 0,0:38:08.99,0:38:11.56,Default,,0,0,0,,把对象定义为过程？\nDialogue: 0,0:38:12.41,0:38:13.76,Default,,0,0,0,,教授：我明白了\nDialogue: 0,0:38:15.90,0:38:19.74,Default,,0,0,0,,我构建抽象的这种方法\nDialogue: 0,0:38:20.14,0:38:22.86,Default,,0,0,0,,需要过程能够返回或者导出一个过程\nDialogue: 0,0:38:23.26,0:38:26.81,Default,,0,0,0,,以便我不想让过程体中包含特定过程\nDialogue: 0,0:38:27.04,0:38:27.24,Default,,0,0,0,,学生：没错\nDialogue: 0,0:38:28.19,0:38:28.88,Default,,0,0,0,,教授：是这样的\nDialogue: 0,0:38:29.53,0:38:31.52,Default,,0,0,0,,如果我不能这么做的话\nDialogue: 0,0:38:32.24,0:38:35.13,Default,,0,0,0,,那么我就无法去构造一个抽象\nDialogue: 0,0:38:35.53,0:38:41.77,Default,,0,0,0,,使得符号之间不会出现冲突\nDialogue: 0,0:38:43.00,0:38:43.48,Default,,0,0,0,,你说得对\nDialogue: 0,0:38:44.14,0:38:46.51,Default,,0,0,0,,我认为\nDialogue: 0,0:38:46.54,0:38:48.91,Default,,0,0,0,,能够把过程作为返回值\nDialogue: 0,0:38:49.20,0:38:58.28,Default,,0,0,0,,更一般地说是支持“第一级过程”\nDialogue: 0,0:38:59.13,0:39:02.46,Default,,0,0,0,,是模块化程序程序设计所必须的\nDialogue: 0,0:39:03.70,0:39:06.43,Default,,0,0,0,,有很多种方式来解决这个问题\nDialogue: 0,0:39:07.44,0:39:09.16,Default,,0,0,0,,你可以的做的就是\nDialogue: 0,0:39:09.18,0:39:11.84,Default,,0,0,0,,针对你所需要关心的每一种糟糕情况\nDialogue: 0,0:39:12.27,0:39:15.20,Default,,0,0,0,,你可以添加一个特殊的FEATURE来解决它\nDialogue: 0,0:39:15.84,0:39:17.12,Default,,0,0,0,,你可以做一个包系统\nDialogue: 0,0:39:17.74,0:39:21.16,Default,,0,0,0,,或者像Ada中的模块系统 等等\nDialogue: 0,0:39:22.24,0:39:24.88,Default,,0,0,0,,这些都可以 可能区别只是解决的程度不一\nDialogue: 0,0:39:26.44,0:39:28.38,Default,,0,0,0,,而能够把过程作为返回值\nDialogue: 0,0:39:28.41,0:39:29.74,Default,,0,0,0,,可以解决这所有的问题\nDialogue: 0,0:39:32.68,0:39:34.60,Default,,0,0,0,,这种最简单的机制\nDialogue: 0,0:39:35.58,0:39:37.79,Default,,0,0,0,,却可以给予你最好的模块性\nDialogue: 0,0:39:39.21,0:39:41.31,Default,,0,0,0,,它赋予你所有已知的模块机制\nDialogue: 0,0:39:45.59,0:39:48.24,Default,,0,0,0,,好的 该休息一会儿了 谢谢大家\nDialogue: 0,0:39:48.24,0:40:01.08,Default,,0,0,0,,[音乐]\nDialogue: 0,0:40:01.28,0:40:04.75,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:40:25.69,0:40:29.42,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:40:30.01,0:40:33.28,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:40:34.17,0:40:37.61,Declare,,0,0,0,,{\\an2\\fad(500,500)}元循环求值器 II\nDialogue: 0,0:40:42.32,0:40:44.28,Default,,0,0,0,,教授：昨天你们学习流的时候\nDialogue: 0,0:40:46.01,0:40:51.16,Default,,0,0,0,,Hal教授告诉了你们求值顺序\nDialogue: 0,0:40:51.95,0:40:53.87,Default,,0,0,0,,以及过程的延迟求值\nDialogue: 0,0:40:55.61,0:40:58.30,Default,,0,0,0,,昨天在讲流的时候 我们说\nDialogue: 0,0:41:00.25,0:41:04.22,Default,,0,0,0,,调用者和被调者都应该认同\nDialogue: 0,0:41:05.77,0:41:08.84,Default,,0,0,0,,参数是被延迟了的\nDialogue: 0,0:41:09.42,0:41:13.44,Default,,0,0,0,,如果被调者需要结果 就需要对参数FORCE\nDialogue: 0,0:41:15.13,0:41:17.87,Default,,0,0,0,,因此在过程的设计者和使用者之间\nDialogue: 0,0:41:18.17,0:41:24.32,Default,,0,0,0,,就有很多关于延时求值的握手\nDialogue: 0,0:41:26.36,0:41:28.72,Default,,0,0,0,,当然 这看起来相当糟糕\nDialogue: 0,0:41:29.48,0:41:30.96,Default,,0,0,0,,虽说对于流没什么不妥\nDialogue: 0,0:41:31.74,0:41:32.86,Default,,0,0,0,,但作为一般性的原则来说\nDialogue: 0,0:41:32.92,0:41:36.32,Default,,0,0,0,,我们希望能有个地方\nDialogue: 0,0:41:36.46,0:41:38.49,Default,,0,0,0,,能够把我们的设计考虑\nDialogue: 0,0:41:38.89,0:41:41.28,Default,,0,0,0,,显式地、清晰地\nDialogue: 0,0:41:41.63,0:41:43.93,Default,,0,0,0,,标注出来\nDialogue: 0,0:41:45.88,0:41:49.28,Default,,0,0,0,,因此就不必在过程编写者\nDialogue: 0,0:41:50.46,0:41:54.89,Default,,0,0,0,,和使用者之间达成共识\nDialogue: 0,0:41:55.08,0:41:57.98,Default,,0,0,0,,有关于参数求值\nDialogue: 0,0:41:58.43,0:41:59.50,Default,,0,0,0,,以及求值顺序等细节\nDialogue: 0,0:41:59.50,0:42:00.75,Default,,0,0,0,,虽然 这也不是太糟糕\nDialogue: 0,0:42:01.02,0:42:03.95,Default,,0,0,0,,我的意思是 可能还有像“输入是一个数字”这样的共识\nDialogue: 0,0:42:05.20,0:42:06.08,Default,,0,0,0,,但是\nDialogue: 0,0:42:06.35,0:42:09.20,Default,,0,0,0,,如果其中一个人可以全权负责 就再好不过了\nDialogue: 0,0:42:11.02,0:42:13.31,Default,,0,0,0,,这个想法已经不算新潮了\nDialogue: 0,0:42:15.51,0:42:21.16,Default,,0,0,0,,Algol60就支持两种不同的过程调用方法\nDialogue: 0,0:42:22.02,0:42:24.28,Default,,0,0,0,,参数可以按名或按值传递\nDialogue: 0,0:42:25.59,0:42:27.48,Default,,0,0,0,,按名传递就意味着\nDialogue: 0,0:42:27.63,0:42:29.72,Default,,0,0,0,,参数会延时求值\nDialogue: 0,0:42:31.11,0:42:32.84,Default,,0,0,0,,当你按名传递一个参数时\nDialogue: 0,0:42:33.64,0:42:36.52,Default,,0,0,0,,只有你去取它的值的时候\nDialogue: 0,0:42:36.96,0:42:39.55,Default,,0,0,0,,它的值才会被计算出来\nDialogue: 0,0:42:42.29,0:42:44.20,Default,,0,0,0,,所以 现在我就要\nDialogue: 0,0:42:44.43,0:42:46.96,Default,,0,0,0,,像之前那样\nDialogue: 0,0:42:46.99,0:42:48.65,Default,,0,0,0,,对语言做出一些小小的修改\nDialogue: 0,0:42:50.32,0:42:51.79,Default,,0,0,0,,这里 我们再添加一个新的FEATURE\nDialogue: 0,0:42:53.37,0:42:55.05,Default,,0,0,0,,我们要添加的FEATURE是\nDialogue: 0,0:42:55.36,0:42:58.73,Default,,0,0,0,,“按名传递参数” 或者可以叫做“延迟求值参数”\nDialogue: 0,0:43:00.43,0:43:04.41,Default,,0,0,0,,因为事实上 Lisp系统中默认\nDialogue: 0,0:43:04.76,0:43:06.60,Default,,0,0,0,,传递的是一个指针\nDialogue: 0,0:43:08.22,0:43:09.15,Default,,0,0,0,,指针被复制了一份\nDialogue: 0,0:43:09.15,0:43:10.91,Default,,0,0,0,,但所指的数据结构却没有被复制\nDialogue: 0,0:43:13.41,0:43:14.84,Default,,0,0,0,,现在我要告诉你们\nDialogue: 0,0:43:15.04,0:43:18.38,Default,,0,0,0,,如何来添加按名传递参数\nDialogue: 0,0:43:19.99,0:43:22.12,Default,,0,0,0,,为什么我们需要这样的FEATURE呢？\nDialogue: 0,0:43:23.10,0:43:24.72,Default,,0,0,0,,假设我们想要开发\nDialogue: 0,0:43:25.24,0:43:28.44,Default,,0,0,0,,像是某种特殊形式的功能\nDialogue: 0,0:43:28.73,0:43:29.72,Default,,0,0,0,,类似于“保留字”\nDialogue: 0,0:43:29.72,0:43:31.48,Default,,0,0,0,,但不是用保留字的方式来实现\nDialogue: 0,0:43:32.18,0:43:34.76,Default,,0,0,0,,我想用过程来实现类似IF的效果\nDialogue: 0,0:43:36.36,0:43:39.42,Default,,0,0,0,,无论是IF还是COND 都是特殊形式\nDialogue: 0,0:43:39.42,0:43:40.43,Default,,0,0,0,,它俩是一样的\nDialogue: 0,0:43:40.59,0:43:42.86,Default,,0,0,0,,这个特殊形式用于\nDialogue: 0,0:43:42.92,0:43:45.02,Default,,0,0,0,,根据谓词返回真假\nDialogue: 0,0:43:46.22,0:43:49.76,Default,,0,0,0,,决定求值真子句还是假子句\nDialogue: 0,0:43:50.84,0:43:53.12,Default,,0,0,0,,它们都是根据某个值\nDialogue: 0,0:43:53.44,0:43:55.36,Default,,0,0,0,,来决定是否去做另外的某件事\nDialogue: 0,0:43:57.27,0:43:58.88,Default,,0,0,0,,然而像+之类的过程\nDialogue: 0,0:43:59.15,0:44:01.20,Default,,0,0,0,,也就是那些我们现在可以定义的过程\nDialogue: 0,0:44:01.42,0:44:06.56,Default,,0,0,0,,是在应用前就求值所有的参数\nDialogue: 0,0:44:08.67,0:44:09.64,Default,,0,0,0,,因此 举例来说\nDialogue: 0,0:44:10.46,0:44:12.41,Default,,0,0,0,,假设我想定义一个过程\nDialogue: 0,0:44:15.39,0:44:18.75,Default,,0,0,0,,用IF来实现与IF相反的效果\nDialogue: 0,0:44:19.85,0:44:20.70,Default,,0,0,0,,我叫它UNLESS\nDialogue: 0,0:44:24.89,0:44:27.47,Default,,0,0,0,,参数是 谓词P、真子句C和假子句A\nDialogue: 0,0:44:28.67,0:44:30.44,Default,,0,0,0,,接下来 我想\nDialogue: 0,0:44:30.46,0:44:32.08,Default,,0,0,0,,用COND来实现\nDialogue: 0,0:44:32.64,0:44:36.72,Default,,0,0,0,,(COND ((NOT P)\nDialogue: 0,0:44:38.96,0:44:40.32,Default,,0,0,0,,结果就是真子句C\nDialogue: 0,0:44:41.58,0:44:45.63,Default,,0,0,0,,否则就是假子句A\nDialogue: 0,0:44:51.29,0:44:52.76,Default,,0,0,0,,我定义这个过程是为了\nDialogue: 0,0:44:53.32,0:44:55.40,Default,,0,0,0,,请考虑下面这种情况\nDialogue: 0,0:44:56.92,0:45:04.12,Default,,0,0,0,,(UNLESS (= 1 0)\nDialogue: 0,0:45:05.08,0:45:06.64,Default,,0,0,0,,那么结果就是2\nDialogue: 0,0:45:07.90,0:45:11.35,Default,,0,0,0,,否则 结果就是(/ 1 0)\nDialogue: 0,0:45:15.92,0:45:18.91,Default,,0,0,0,,这段代码相当于进行这样的代换：\nDialogue: 0,0:45:20.00,0:45:23.26,Default,,0,0,0,,用(= 1 0)、2和(/ 1 0)\nDialogue: 0,0:45:23.66,0:45:24.76,Default,,0,0,0,,分别代换上面的P、C以及A\nDialogue: 0,0:45:25.58,0:45:27.58,Default,,0,0,0,,这样很有趣\nDialogue: 0,0:45:28.11,0:45:30.33,Default,,0,0,0,,代换后就变成了\nDialogue: 0,0:45:30.75,0:45:38.44,Default,,0,0,0,,(COND ((NOT (= 1 0))\nDialogue: 0,0:45:40.62,0:45:42.54,Default,,0,0,0,,结果就是2\nDialogue: 0,0:45:44.28,0:45:45.10,Default,,0,0,0,,否则就是\nDialogue: 0,0:45:48.22,0:45:51.16,Default,,0,0,0,,(/ 1 0)\nDialogue: 0,0:45:54.48,0:45:56.48,Default,,0,0,0,,你们也知道 如果向Lisp中输入这段代码\nDialogue: 0,0:45:57.74,0:45:58.59,Default,,0,0,0,,结果会是2\nDialogue: 0,0:45:59.97,0:46:01.32,Default,,0,0,0,,这没问题\nDialogue: 0,0:46:02.91,0:46:04.64,Default,,0,0,0,,但如果我输入的是这段代码\nDialogue: 0,0:46:05.28,0:46:07.79,Default,,0,0,0,,由于参数会在过程调用前求值\nDialogue: 0,0:46:09.12,0:46:10.73,Default,,0,0,0,,那么这段代码就会报错\nDialogue: 0,0:46:13.38,0:46:15.61,Default,,0,0,0,,当然 如果成功进行代换的话\nDialogue: 0,0:46:16.03,0:46:16.88,Default,,0,0,0,,我可以得到正确的结果\nDialogue: 0,0:46:16.88,0:46:20.16,Default,,0,0,0,,但是这里这种情况 代换并不能进行\nDialogue: 0,0:46:22.17,0:46:23.86,Default,,0,0,0,,我连错误的结果都无法得到\nDialogue: 0,0:46:23.86,0:46:24.67,Default,,0,0,0,,没有结果\nDialogue: 0,0:46:24.80,0:46:25.60,Default,,0,0,0,,只能得到错误\nDialogue: 0,0:46:28.42,0:46:31.21,Default,,0,0,0,,现在 我要想办法\nDialogue: 0,0:46:31.61,0:46:32.99,Default,,0,0,0,,使这样的定义可以成功运行\nDialogue: 0,0:46:34.48,0:46:36.51,Default,,0,0,0,,但我想标注出\nDialogue: 0,0:46:36.70,0:46:38.76,Default,,0,0,0,,C和A是特殊的东西\nDialogue: 0,0:46:39.93,0:46:43.15,Default,,0,0,0,,我想使它们自动地延时求值\nDialogue: 0,0:46:44.27,0:46:48.08,Default,,0,0,0,,我不想它们在我调用过程的时候\nDialogue: 0,0:46:48.52,0:46:49.74,Default,,0,0,0,,就被求值\nDialogue: 0,0:46:51.52,0:46:52.72,Default,,0,0,0,,所以我得先制定一种声明\nDialogue: 0,0:46:52.75,0:46:55.32,Default,,0,0,0,,然后再考虑如何实现此种声明\nDialogue: 0,0:46:55.60,0:46:57.63,Default,,0,0,0,,再次强调 希望你们能够提醒自己\nDialogue: 0,0:46:57.79,0:47:00.25,Default,,0,0,0,,我们这里添加的是临时组件\nDialogue: 0,0:47:00.76,0:47:02.16,Default,,0,0,0,,必须要知道\nDialogue: 0,0:47:02.25,0:47:04.72,Default,,0,0,0,,滥用临时组件会造成大混乱\nDialogue: 0,0:47:05.75,0:47:09.79,Default,,0,0,0,,还会破坏一些已有的东西\nDialogue: 0,0:47:10.12,0:47:12.70,Default,,0,0,0,,首先 它会造成语法歧义性么？\nDialogue: 0,0:47:13.86,0:47:15.50,Default,,0,0,0,,就我们目前已有的语法来说\nDialogue: 0,0:47:15.71,0:47:16.91,Default,,0,0,0,,它不会造成什么歧义\nDialogue: 0,0:47:17.84,0:47:20.76,Default,,0,0,0,,但接下来要做的却可能招来麻烦\nDialogue: 0,0:47:21.67,0:47:24.67,Default,,0,0,0,,我要添加的东西可能会跟\nDialogue: 0,0:47:25.15,0:47:27.10,Default,,0,0,0,,我以后添加的类型声明冲突\nDialogue: 0,0:47:28.19,0:47:31.08,Default,,0,0,0,,类型系统通过提供已知的类型信息\nDialogue: 0,0:47:31.21,0:47:33.66,Default,,0,0,0,,使得语言系统或者编译器可以做出优化\nDialogue: 0,0:47:34.75,0:47:36.97,Default,,0,0,0,,当然也会与我想添加的形式参数的\nDialogue: 0,0:47:37.00,0:47:39.71,Default,,0,0,0,,其它类型的声明相冲突\nDialogue: 0,0:47:40.57,0:47:42.56,Default,,0,0,0,,所以这里我并不打算做一个一般性的机制\nDialogue: 0,0:47:43.77,0:47:45.24,Default,,0,0,0,,使得我可以添加声明\nDialogue: 0,0:47:45.28,0:47:46.54,Default,,0,0,0,,虽然我很想那么做\nDialogue: 0,0:47:46.89,0:47:48.81,Default,,0,0,0,,但现在并不打算这么做\nDialogue: 0,0:47:51.01,0:47:53.88,Default,,0,0,0,,接下来 我要添加某种临时的解决方法\nDialogue: 0,0:47:57.56,0:48:08.38,Default,,0,0,0,,(DEFINE (UNLESS P\nDialogue: 0,0:48:08.81,0:48:10.27,Default,,0,0,0,,后面的参数都是按名调用\nDialogue: 0,0:48:12.78,0:48:15.28,Default,,0,0,0,,分别记作(NAME C)和(NAME A)\nDialogue: 0,0:48:19.85,0:48:25.28,Default,,0,0,0,,哈 哈 卡在黑板边了\nDialogue: 0,0:48:31.76,0:48:35.61,Default,,0,0,0,,(COND ((NOT P) C)\nDialogue: 0,0:48:36.80,0:48:41.16,Default,,0,0,0,,(ELSE A)))\nDialogue: 0,0:48:44.67,0:48:46.88,Default,,0,0,0,,我可以显式地声明\nDialogue: 0,0:48:47.55,0:48:51.65,Default,,0,0,0,,哪些参数按名称传递或延时求值\nDialogue: 0,0:48:55.60,0:48:58.48,Default,,0,0,0,,对解释器的这个修改并不简单\nDialogue: 0,0:48:58.70,0:48:59.77,Default,,0,0,0,,反而相当复杂\nDialogue: 0,0:49:00.45,0:49:03.10,Default,,0,0,0,,我们之前介绍的动态绑定\nDialogue: 0,0:49:03.40,0:49:06.89,Default,,0,0,0,,或者让过程支持不定数目的参数\nDialogue: 0,0:49:07.50,0:49:08.52,Default,,0,0,0,,都相对简单\nDialogue: 0,0:49:09.28,0:49:11.28,Default,,0,0,0,,这次的修改涉及基本策略\nDialogue: 0,0:49:12.32,0:49:13.39,Default,,0,0,0,,这里的问题是\nDialogue: 0,0:49:13.96,0:49:17.63,Default,,0,0,0,,我们的解释器 就如代码所写的那样\nDialogue: 0,0:49:17.96,0:49:23.40,Default,,0,0,0,,在求值组合式时\nDialogue: 0,0:49:24.24,0:49:25.92,Default,,0,0,0,,先通过求值运算符取得过程\nDialogue: 0,0:49:26.20,0:49:30.35,Default,,0,0,0,,然后再求值运算对象得到参数\nDialogue: 0,0:49:30.76,0:49:35.26,Default,,0,0,0,,再把过程应用到参数上\nDialogue: 0,0:49:36.38,0:49:37.07,Default,,0,0,0,,然而这里\nDialogue: 0,0:49:37.36,0:49:41.48,Default,,0,0,0,,直到我检查了整个过程\nDialogue: 0,0:49:41.74,0:49:43.66,Default,,0,0,0,,确定了程序的声明\nDialogue: 0,0:49:44.62,0:49:46.86,Default,,0,0,0,,才会去求值程序的参数\nDialogue: 0,0:49:49.59,0:49:50.59,Default,,0,0,0,,我们来看这个\nDialogue: 0,0:49:52.68,0:49:56.54,Default,,0,0,0,,这是修改后的求值器\nDialogue: 0,0:49:57.48,0:50:01.15,Default,,0,0,0,,我是基于那个最简单的词法作用域求值器\nDialogue: 0,0:50:01.72,0:50:02.65,Default,,0,0,0,,不是动态绑定的那个\nDialogue: 0,0:50:04.14,0:50:08.20,Default,,0,0,0,,但是却要做一些类似于动态绑定的修改\nDialogue: 0,0:50:09.75,0:50:11.45,Default,,0,0,0,,这是因为\nDialogue: 0,0:50:11.90,0:50:13.34,Default,,0,0,0,,如果我延时一个过程 --\nDialogue: 0,0:50:13.66,0:50:15.15,Default,,0,0,0,,哦说错了 -- 延时一个过程的参数\nDialogue: 0,0:50:15.40,0:50:17.52,Default,,0,0,0,,就必须把当前的环境和参数关联在一起\nDialogue: 0,0:50:19.36,0:50:21.55,Default,,0,0,0,,还记得Hal教授如何实现DELAY的吧？\nDialogue: 0,0:50:23.38,0:50:25.44,Default,,0,0,0,,Hal教授把DELAY实现为\nDialogue: 0,0:50:25.50,0:50:27.47,Default,,0,0,0,,一个无参过程\nDialogue: 0,0:50:28.56,0:50:30.52,Default,,0,0,0,,用来执行某些表达式\nDialogue: 0,0:50:31.18,0:50:36.94,Default,,0,0,0,,就是这样让表达式延迟求值的\nDialogue: 0,0:50:39.29,0:50:40.99,Default,,0,0,0,,(DELAY E)实际上是这个\nDialogue: 0,0:50:44.52,0:50:46.92,Default,,0,0,0,,然而 如果我求值这个LAMBDA表达式\nDialogue: 0,0:50:47.42,0:50:49.20,Default,,0,0,0,,我就必须得捕获当前环境\nDialogue: 0,0:50:51.41,0:50:53.45,Default,,0,0,0,,这是因为\nDialogue: 0,0:50:54.60,0:50:56.32,Default,,0,0,0,,我想让这其中的变量的值\nDialogue: 0,0:50:57.02,0:51:00.83,Default,,0,0,0,,取决于它们被定义时的上下文\nDialogue: 0,0:51:04.01,0:51:05.76,Default,,0,0,0,,这也就是为什么要用LAMBDA表达式\nDialogue: 0,0:51:06.62,0:51:07.50,Default,,0,0,0,,这才是正确的\nDialogue: 0,0:51:08.07,0:51:15.12,Default,,0,0,0,,(FORCE E)则相当于\nDialogue: 0,0:51:16.52,0:51:20.08,Default,,0,0,0,,无参地调用这个过程\nDialogue: 0,0:51:21.09,0:51:22.28,Default,,0,0,0,,恰恰和上面相对\nDialogue: 0,0:51:24.10,0:51:26.94,Default,,0,0,0,,这个调用产生的环境则是\nDialogue: 0,0:51:27.36,0:51:29.90,Default,,0,0,0,,定义这个过程时的环境\nDialogue: 0,0:51:30.81,0:51:32.36,Default,,0,0,0,,额外加上一个空框架\nDialogue: 0,0:51:33.23,0:51:34.41,Default,,0,0,0,,我并不在意它\nDialogue: 0,0:51:36.24,0:51:39.40,Default,,0,0,0,,我们再来看这张幻灯片\nDialogue: 0,0:51:40.99,0:51:43.72,Default,,0,0,0,,仔细观察一会儿\nDialogue: 0,0:51:44.14,0:51:46.12,Default,,0,0,0,,会发现大部分跟以前相同\nDialogue: 0,0:51:46.35,0:51:50.65,Default,,0,0,0,,只是对应用或组合式的处理不同\nDialogue: 0,0:51:51.98,0:51:53.71,Default,,0,0,0,,处理组合式分两步\nDialogue: 0,0:51:54.68,0:51:57.79,Default,,0,0,0,,首先要求值这个过程\nDialogue: 0,0:51:57.92,0:51:59.88,Default,,0,0,0,,我就必须通过求值运算符来得到对应过程\nDialogue: 0,0:52:00.70,0:52:01.69,Default,,0,0,0,,也就是这一部分\nDialogue: 0,0:52:02.38,0:52:04.35,Default,,0,0,0,,我得这个值是计算求出的现值\nDialogue: 0,0:52:04.46,0:52:05.76,Default,,0,0,0,,而不是一个延时对象\nDialogue: 0,0:52:06.36,0:52:09.85,Default,,0,0,0,,也就要求值它在被延时前的表达式\nDialogue: 0,0:52:10.73,0:52:12.08,Default,,0,0,0,,接下来我就要\nDialogue: 0,0:52:12.24,0:52:17.32,Default,,0,0,0,,把它应用于运算对象\nDialogue: 0,0:52:18.03,0:52:19.61,Default,,0,0,0,,但我仍然要保持这个环境\nDialogue: 0,0:52:19.63,0:52:20.92,Default,,0,0,0,,并将其传递过去\nDialogue: 0,0:52:21.53,0:52:23.71,Default,,0,0,0,,如果有一些运算对象是延时了的\nDialogue: 0,0:52:23.71,0:52:27.53,Default,,0,0,0,,我就需要为这些运算对象附上相应的环境\nDialogue: 0,0:52:29.66,0:52:31.52,Default,,0,0,0,,这里的处理相当复杂\nDialogue: 0,0:52:32.99,0:52:34.24,Default,,0,0,0,,来看看APPLY中对应的部分\nDialogue: 0,0:52:36.40,0:52:38.72,Default,,0,0,0,,APPLY这一部分处理基本过程\nDialogue: 0,0:52:39.36,0:52:40.60,Default,,0,0,0,,这和之前一样\nDialogue: 0,0:52:42.61,0:52:44.68,Default,,0,0,0,,但复合过程部分就比较有意思了\nDialogue: 0,0:52:47.25,0:52:49.52,Default,,0,0,0,,和之前一样 我需要求值过程体\nDialogue: 0,0:52:50.48,0:52:51.98,Default,,0,0,0,,基于的环境是\nDialogue: 0,0:52:52.28,0:52:54.97,Default,,0,0,0,,把形式参数和\nDialogue: 0,0:52:55.61,0:53:00.29,Default,,0,0,0,,实际参数绑定在一起的结果\nDialogue: 0,0:53:00.29,0:53:01.07,Default,,0,0,0,,是这样的\nDialogue: 0,0:53:01.53,0:53:03.82,Default,,0,0,0,,环境来自于过程对象\nDialogue: 0,0:53:03.82,0:53:06.65,Default,,0,0,0,,因为我们的语言是词法作用域、静态绑定的\nDialogue: 0,0:53:08.04,0:53:11.82,Default,,0,0,0,,然而 我还需要去掉NAME声明\nDialogue: 0,0:53:11.84,0:53:12.84,Default,,0,0,0,,获得变量的实际名字\nDialogue: 0,0:53:12.84,0:53:15.20,Default,,0,0,0,,这是由VNAMES过程完成的\nDialogue: 0,0:53:15.45,0:53:16.67,Default,,0,0,0,,然后要做的就是\nDialogue: 0,0:53:16.97,0:53:18.86,Default,,0,0,0,,处理这些声明\nDialogue: 0,0:53:19.13,0:53:21.52,Default,,0,0,0,,决定这些运算对象中\nDialogue: 0,0:53:21.76,0:53:23.92,Default,,0,0,0,,现在它们还是形式参数 而非实际参数\nDialogue: 0,0:53:24.09,0:53:25.87,Default,,0,0,0,,哪些运算对象需要立即求值\nDialogue: 0,0:53:26.62,0:53:30.20,Default,,0,0,0,,而哪些运算对象又要\nDialogue: 0,0:53:30.99,0:53:33.77,Default,,0,0,0,,用某种方式封装为延时对象\nDialogue: 0,0:53:37.28,0:53:40.08,Default,,0,0,0,,另外 在处理基本过程这里\nDialogue: 0,0:53:40.60,0:53:42.38,Default,,0,0,0,,当遇到像+这样的基本过程\nDialogue: 0,0:53:42.68,0:53:45.58,Default,,0,0,0,,它们的参数最好立即求值\nDialogue: 0,0:53:45.82,0:53:47.39,Default,,0,0,0,,也就我们需要是这里FORCE这些表达式\nDialogue: 0,0:53:47.92,0:53:50.38,Default,,0,0,0,,EVLIST中完成了很多FORCE操作\nDialogue: 0,0:53:51.34,0:53:52.78,Default,,0,0,0,,现在 我们有了两种不同的EVLIST\nDialogue: 0,0:53:52.78,0:53:54.09,Default,,0,0,0,,EVLIST和GEVLIST\nDialogue: 0,0:53:54.52,0:53:57.16,Default,,0,0,0,,GEVLIST封装延迟参数\nDialogue: 0,0:53:57.18,0:53:59.74,Default,,0,0,0,,而对另外的参数立即求值\nDialogue: 0,0:53:59.87,0:54:05.85,Default,,0,0,0,,而EVLIST则会FORCE所有的表达式\nDialogue: 0,0:54:07.90,0:54:09.16,Default,,0,0,0,,简单地看下EVLIST的代码\nDialogue: 0,0:54:09.69,0:54:11.98,Default,,0,0,0,,课后你们一定要亲自上手试试\nDialogue: 0,0:54:12.25,0:54:14.67,Default,,0,0,0,,光是听我在这里讲课\nDialogue: 0,0:54:14.72,0:54:18.20,Default,,0,0,0,,可不能够学到求值器的不同变种\nDialogue: 0,0:54:19.52,0:54:21.24,Default,,0,0,0,,你们需要上手亲自实践一下。\nDialogue: 0,0:54:21.37,0:54:23.84,Default,,0,0,0,,你试验过后 对它们有了感悟\nDialogue: 0,0:54:24.22,0:54:27.02,Default,,0,0,0,,你才能理解各种可能的设计决策\nDialogue: 0,0:54:27.77,0:54:29.16,Default,,0,0,0,,才能清楚它们如何相互关联\nDialogue: 0,0:54:29.93,0:54:32.38,Default,,0,0,0,,了解求值器描述的是何种语言\nDialogue: 0,0:54:33.16,0:54:34.64,Default,,0,0,0,,以及构建一门合理的语言\nDialogue: 0,0:54:34.94,0:54:36.32,Default,,0,0,0,,需要哪些一致性集合\nDialogue: 0,0:54:37.20,0:54:40.06,Default,,0,0,0,,哪些临时方案又是复杂而无用\nDialogue: 0,0:54:41.85,0:54:44.68,Default,,0,0,0,,就和我说得一样 这里的EVLIST\nDialogue: 0,0:54:44.81,0:54:46.03,Default,,0,0,0,,参数之一为运算对象表\nDialogue: 0,0:54:46.70,0:54:50.28,Default,,0,0,0,,表中的元素会在求值之后被取消延时\nDialogue: 0,0:54:50.75,0:54:51.90,Default,,0,0,0,,它们都会被FORCE\nDialogue: 0,0:54:53.28,0:54:54.44,Default,,0,0,0,,无论它们是否为延时对象\nDialogue: 0,0:54:56.05,0:54:58.51,Default,,0,0,0,,下一个 GEVLIST\nDialogue: 0,0:55:01.26,0:55:01.85,Default,,0,0,0,,谢谢\nDialogue: 0,0:55:04.04,0:55:06.35,Default,,0,0,0,,我们在这里会发现\nDialogue: 0,0:55:07.80,0:55:09.61,Default,,0,0,0,,这里面有多种可能\nDialogue: 0,0:55:09.81,0:55:11.52,Default,,0,0,0,,要么是普通的情况\nDialogue: 0,0:55:12.48,0:55:13.69,Default,,0,0,0,,比如元素直接是一个符号\nDialogue: 0,0:55:13.74,0:55:16.20,Default,,0,0,0,,就像UNLESS中的参数P那样\nDialogue: 0,0:55:17.64,0:55:18.81,Default,,0,0,0,,对应这一部分代码\nDialogue: 0,0:55:19.39,0:55:22.49,Default,,0,0,0,,在这种情况下 我们就用应用序来求值\nDialogue: 0,0:55:23.34,0:55:25.45,Default,,0,0,0,,基本上就像以前一样\nDialogue: 0,0:55:25.63,0:55:28.84,Default,,0,0,0,,就是将EVAL映射在这个表上\nDialogue: 0,0:55:29.95,0:55:32.14,Default,,0,0,0,,换言之 就是先求值第一个表达式\nDialogue: 0,0:55:32.65,0:55:37.36,Default,,0,0,0,,然后在ENV中 求值(GEVLIST (CDR EXPRS))\nDialogue: 0,0:55:37.93,0:55:43.20,Default,,0,0,0,,然而 我们也可能遇到按名传递的参数\nDialogue: 0,0:55:44.00,0:55:45.05,Default,,0,0,0,,如果参数是按名传递\nDialogue: 0,0:55:45.20,0:55:46.59,Default,,0,0,0,,我就需要给它包裹上一个DELAY\nDialogue: 0,0:55:47.00,0:55:50.97,Default,,0,0,0,,DELAY里面就是我想按名调用的表达式\nDialogue: 0,0:55:52.14,0:55:57.74,Default,,0,0,0,,还要附上定义过程时的环境\nDialogue: 0,0:55:59.05,0:56:00.59,Default,,0,0,0,,把它们作为实际参数\nDialogue: 0,0:56:02.79,0:56:05.04,Default,,0,0,0,,然后像这样继续递归处理\nDialogue: 0,0:56:09.07,0:56:11.31,Default,,0,0,0,,这个解释器中另外一个有意思的地方\nDialogue: 0,0:56:11.37,0:56:13.53,Default,,0,0,0,,就在于COND\nDialogue: 0,0:56:14.70,0:56:15.92,Default,,0,0,0,,人们可能就这么来写\nDialogue: 0,0:56:15.93,0:56:17.24,Default,,0,0,0,,然后就不管了\nDialogue: 0,0:56:18.55,0:56:19.98,Default,,0,0,0,,你需要在一处FORCE\nDialogue: 0,0:56:20.51,0:56:23.10,Default,,0,0,0,,COND表达式需要知道\nDialogue: 0,0:56:24.20,0:56:25.90,Default,,0,0,0,,谓词判定结果的真假\nDialogue: 0,0:56:25.99,0:56:26.83,Default,,0,0,0,,就像基本过程那样\nDialogue: 0,0:56:28.55,0:56:30.56,Default,,0,0,0,,求值COND语句时 需要FORCE\nDialogue: 0,0:56:31.72,0:56:33.95,Default,,0,0,0,,剩下的细节就没什么特别的了\nDialogue: 0,0:56:34.62,0:56:36.28,Default,,0,0,0,,就先不深究了\nDialogue: 0,0:56:36.75,0:56:38.99,Default,,0,0,0,,剩下的就是如何实现MAKE-DELAY\nDialogue: 0,0:56:38.99,0:56:40.91,Default,,0,0,0,,延时对象是一种数据结构\nDialogue: 0,0:56:41.31,0:56:44.75,Default,,0,0,0,,它包括：类型标识、表达式以及环境\nDialogue: 0,0:56:44.84,0:56:46.36,Default,,0,0,0,,它的类型标识是'THUNK\nDialogue: 0,0:56:46.96,0:56:48.46,Default,,0,0,0,,这个术语来自于Algol语言\nDialogue: 0,0:56:49.07,0:56:50.81,Default,,0,0,0,,据说这是个拟声词\nDialogue: 0,0:56:50.83,0:56:52.06,Default,,0,0,0,,是把东西压栈的声音\nDialogue: 0,0:56:52.97,0:56:53.41,Default,,0,0,0,,我不太清楚\nDialogue: 0,0:56:53.41,0:56:57.12,Default,,0,0,0,,我既不是Algol学家 又不是Algol程序员\nDialogue: 0,0:56:57.60,0:56:58.38,Default,,0,0,0,,所以我不太清楚\nDialogue: 0,0:56:58.74,0:56:59.64,Default,,0,0,0,,但据说它是那样的\nDialogue: 0,0:57:00.27,0:57:01.56,Default,,0,0,0,,而UNDELAY的定义则是\nDialogue: 0,0:57:01.77,0:57:03.66,Default,,0,0,0,,递归地UNDELAY这些THUNK\nDialogue: 0,0:57:03.69,0:57:06.00,Default,,0,0,0,,直到得到一个非THUNK对象\nDialogue: 0,0:57:07.72,0:57:10.94,Default,,0,0,0,,这就是如何实现Algol中的按名调用\nDialogue: 0,0:57:12.05,0:57:13.76,Default,,0,0,0,,差不多就是这样了\nDialogue: 0,0:57:15.21,0:57:16.25,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,0:57:26.68,0:57:27.52,Default,,0,0,0,,学生：Gerry？\nDialogue: 0,0:57:28.09,0:57:28.80,Default,,0,0,0,,教授：你说 Vesko\nDialogue: 0,0:57:30.03,0:57:32.99,Default,,0,0,0,,学生：我注意到 对于基本过程\nDialogue: 0,0:57:33.44,0:57:34.89,Default,,0,0,0,,你是避免按名调用的\nDialogue: 0,0:57:36.41,0:57:38.38,Default,,0,0,0,,我很想知道 你为什么要这样？\nDialogue: 0,0:57:38.41,0:57:39.21,Default,,0,0,0,,需要这样吗？\nDialogue: 0,0:57:40.07,0:57:41.61,Default,,0,0,0,,教授：Vesko想问的是\nDialogue: 0,0:57:42.06,0:57:46.00,Default,,0,0,0,,基本过程也按名调用是否合理？\nDialogue: 0,0:57:47.14,0:57:48.70,Default,,0,0,0,,答案是：是的\nDialogue: 0,0:57:49.27,0:57:52.32,Default,,0,0,0,,有一种情况下是可以的 实际上是两种\nDialogue: 0,0:57:55.53,0:57:58.27,Default,,0,0,0,,比如用CONS来构造一个数据结构\nDialogue: 0,0:57:59.02,0:58:02.00,Default,,0,0,0,,构建一个元素个数不定的数组时\nDialogue: 0,0:58:03.26,0:58:07.44,Default,,0,0,0,,就没必要求值参数\nDialogue: 0,0:58:07.44,0:58:08.83,Default,,0,0,0,,你只需要创建一些PROMISE\nDialogue: 0,0:58:09.10,0:58:10.81,Default,,0,0,0,,在确实需要时才来求值这些参数\nDialogue: 0,0:58:11.50,0:58:15.08,Default,,0,0,0,,如果我把两个对象CONS起来\nDialogue: 0,0:58:16.24,0:58:17.77,Default,,0,0,0,,那么我CONS这些PROMISE\nDialogue: 0,0:58:17.80,0:58:19.93,Default,,0,0,0,,就和CONS这些对象一样容易\nDialogue: 0,0:58:21.15,0:58:23.37,Default,,0,0,0,,甚至在对它们进行CAR CDR的时候\nDialogue: 0,0:58:23.39,0:58:24.30,Default,,0,0,0,,也不用进行实际的计算\nDialogue: 0,0:58:24.84,0:58:26.97,Default,,0,0,0,,取出PROMISE 并直接传递给其它人\nDialogue: 0,0:58:28.26,0:58:30.51,Default,,0,0,0,,这也就是为什么Alonzo Church用LAMBDA演算\nDialogue: 0,0:58:30.57,0:58:34.03,Default,,0,0,0,,定义的CAR、CDR和CONS说得通的原因\nDialogue: 0,0:58:34.42,0:58:36.32,Default,,0,0,0,,这是因为CAR、CDR以及CONS并没有执行计算\nDialogue: 0,0:58:36.38,0:58:40.06,Default,,0,0,0,,你们可以认为它是在重组数据而已\nDialogue: 0,0:58:40.99,0:58:42.20,Default,,0,0,0,,然而像 + 这样的过程\nDialogue: 0,0:58:42.24,0:58:43.84,Default,,0,0,0,,必须要了解参数是什么\nDialogue: 0,0:58:45.28,0:58:46.91,Default,,0,0,0,,它们需要确认\nDialogue: 0,0:58:47.12,0:58:48.30,Default,,0,0,0,,构成这些数字的比特\nDialogue: 0,0:58:48.32,0:58:50.44,Default,,0,0,0,,除非它们处理的是LAMBDA演算中的数字\nDialogue: 0,0:58:50.44,0:58:51.88,Default,,0,0,0,,这就是另外一码事了\nDialogue: 0,0:58:52.43,0:58:53.58,Default,,0,0,0,,为了运算加法\nDialogue: 0,0:58:53.77,0:58:55.53,Default,,0,0,0,,它需要知道构成数字的比特\nDialogue: 0,0:58:59.21,0:58:59.92,Default,,0,0,0,,因此 实际上\nDialogue: 0,0:59:00.19,0:59:02.78,Default,,0,0,0,,数据的构造过程和选择过程\nDialogue: 0,0:59:03.24,0:59:05.50,Default,,0,0,0,,以及具有副作用的数据对象\nDialogue: 0,0:59:06.27,0:59:09.76,Default,,0,0,0,,在最极端的惰性解释器中\nDialogue: 0,0:59:11.34,0:59:13.39,Default,,0,0,0,,也不需要被FORCE\nDialogue: 0,0:59:16.46,0:59:16.99,Default,,0,0,0,,另外一方面\nDialogue: 0,0:59:17.02,0:59:18.70,Default,,0,0,0,,针对数据结构的谓词需要被FORCE\nDialogue: 0,0:59:19.61,0:59:22.65,Default,,0,0,0,,如果你想判断 这是一个序对吗？\nDialogue: 0,0:59:23.56,0:59:24.40,Default,,0,0,0,,或者是一个符号？\nDialogue: 0,0:59:24.64,0:59:26.57,Default,,0,0,0,,最好搞清楚是什么\nDialogue: 0,0:59:30.30,0:59:31.18,Default,,0,0,0,,还有问题吗？\nDialogue: 0,0:59:40.05,0:59:41.61,Default,,0,0,0,,那好吧 下课\nDialogue: 0,0:59:42.10,1:00:04.56,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:59:42.10,1:00:04.56,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec7b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 1\nVideo Position: 516\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:09.52,0:00:13.66,EN,,0,0,0,,Metacircular Evaluator II\nDialogue: 0,0:00:17.21,0:00:17.96,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:00:19.52,0:00:21.29,EN,,0,0,0,,What we did so far was a lot of fun,\nDialogue: 0,0:00:21.52,0:00:23.05,EN,,0,0,0,,was it useful for anything?\nDialogue: 0,0:00:26.33,0:00:27.96,EN,,0,0,0,,I suppose the answer is going to be yes.\nDialogue: 0,0:00:29.38,0:00:31.92,EN,,0,0,0,,If these metacircular interpreters\nDialogue: 0,0:00:32.96,0:00:34.60,EN,,0,0,0,,are a valuable thing to play with.\nDialogue: 0,0:00:34.62,0:00:36.17,EN,,0,0,0,,I spend, say\nDialogue: 0,0:00:38.05,0:00:41.85,EN,,0,0,0,,there have been times I spend 50% of my time, over a year,\nDialogue: 0,0:00:42.86,0:00:45.26,EN,,0,0,0,,trying various design alternatives\nDialogue: 0,0:00:45.76,0:00:48.19,EN,,0,0,0,,by experimenting with them with metacircular interpreters--\nDialogue: 0,0:00:49.47,0:00:52.01,EN,,0,0,0,,metacircular interpreters like the sort you just saw.\nDialogue: 0,0:00:52.57,0:00:54.11,EN,,0,0,0,,Metacircular is because\nDialogue: 0,0:00:54.72,0:00:56.94,EN,,0,0,0,,they are defined in terms of themselves in such a way\nDialogue: 0,0:00:56.97,0:00:59.71,EN,,0,0,0,,that the language they interpret contains itself.\nDialogue: 0,0:01:01.27,0:01:03.87,EN,,0,0,0,,Such interpreters are a convenient medium\nDialogue: 0,0:01:03.88,0:01:05.58,EN,,0,0,0,,for exploring language issues.\nDialogue: 0,0:01:06.80,0:01:09.44,EN,,0,0,0,,If you want to try adding a new feature,\nDialogue: 0,0:01:10.51,0:01:12.38,EN,,0,0,0,,it's sort of a snap, it's easy,\nDialogue: 0,0:01:12.73,0:01:15.10,EN,,0,0,0,,you just do it and see what happens.\nDialogue: 0,0:01:15.49,0:01:17.20,EN,,0,0,0,,You play with that language for a while you say,\nDialogue: 0,0:01:17.24,0:01:18.24,EN,,0,0,0,,gee, I'm didn't like that,\nDialogue: 0,0:01:18.52,0:01:19.47,EN,,0,0,0,,you throw it away.\nDialogue: 0,0:01:20.96,0:01:23.55,EN,,0,0,0,,Or you might want to see what\nDialogue: 0,0:01:23.64,0:01:27.37,EN,,0,0,0,,the difference is if you'd make a slight difference in the binding strategy,\nDialogue: 0,0:01:28.81,0:01:31.90,EN,,0,0,0,,or some more complicated things that might occur.\nDialogue: 0,0:01:33.72,0:01:35.48,EN,,0,0,0,,In fact, these metacircular interpreters\nDialogue: 0,0:01:36.17,0:01:37.88,EN,,0,0,0,,are an excellent medium for people\nDialogue: 0,0:01:38.20,0:01:42.56,EN,,0,0,0,,exchanging ideas about language design,\nDialogue: 0,0:01:43.98,0:01:45.74,EN,,0,0,0,,because they're pretty easy to understand,\nDialogue: 0,0:01:46.28,0:01:48.46,EN,,0,0,0,,and they're short, and compact, and simple.\nDialogue: 0,0:01:49.32,0:01:50.80,EN,,0,0,0,,If I have some idea\nDialogue: 0,0:01:51.53,0:01:53.77,EN,,0,0,0,,that I want somebody to criticize\nDialogue: 0,0:01:54.25,0:01:58.32,EN,,0,0,0,,like say, Dan Friedman at Indiana,\nDialogue: 0,0:01:59.05,0:02:02.00,EN,,0,0,0,,I'd write a little metacircular interpreter\nDialogue: 0,0:02:02.56,0:02:03.79,EN,,0,0,0,,send him some network mail\nDialogue: 0,0:02:04.65,0:02:05.45,EN,,0,0,0,,with this interpreter in it.\nDialogue: 0,0:02:05.45,0:02:07.90,EN,,0,0,0,,He could whip it up on his machine and play with it\nDialogue: 0,0:02:07.92,0:02:09.82,EN,,0,0,0,,and say, that's no good.\nDialogue: 0,0:02:11.94,0:02:13.10,EN,,0,0,0,,And then send it back to me and say,\nDialogue: 0,0:02:13.13,0:02:14.83,EN,,0,0,0,,well, why don't you try this one, it's a little better.\nDialogue: 0,0:02:16.88,0:02:19.36,EN,,0,0,0,,So I want to show you some of that technology.\nDialogue: 0,0:02:20.16,0:02:24.20,EN,,0,0,0,,See, because, really, it's the essential, simple technology\nDialogue: 0,0:02:24.72,0:02:28.68,EN,,0,0,0,,for getting started in designing your own languages for particular purposes.\nDialogue: 0,0:02:30.79,0:02:32.08,EN,,0,0,0,,Let's start by adding\nDialogue: 0,0:02:32.51,0:02:34.21,EN,,0,0,0,,a very simple feature to a Lisp.\nDialogue: 0,0:02:40.64,0:02:44.37,EN,,0,0,0,,Now, one thing I want to tell you about is features, before I start.\nDialogue: 0,0:02:49.56,0:02:52.17,EN,,0,0,0,,There are many languages that have made a mess of themselves\nDialogue: 0,0:02:53.05,0:02:54.91,EN,,0,0,0,,by adding huge numbers of features.\nDialogue: 0,0:02:56.86,0:02:58.38,EN,,0,0,0,,Computer scientists have a joke\nDialogue: 0,0:02:59.28,0:03:02.52,EN,,0,0,0,,about bugs that transform it to features all the time.\nDialogue: 0,0:03:05.03,0:03:06.46,EN,,0,0,0,,But I like to think of it is that\nDialogue: 0,0:03:08.91,0:03:11.44,EN,,0,0,0,,many systems suffer from what's called creeping featurism.\nDialogue: 0,0:03:12.82,0:03:13.44,EN,,0,0,0,,Which is that\nDialogue: 0,0:03:14.94,0:03:18.16,EN,,0,0,0,,George has a pet feature he'd like in the system,\nDialogue: 0,0:03:18.72,0:03:19.36,EN,,0,0,0,,so he adds it.\nDialogue: 0,0:03:20.17,0:03:22.14,EN,,0,0,0,,And then Harry says, go says\nDialogue: 0,0:03:22.17,0:03:24.20,EN,,0,0,0,,gee, this system is no longer what exactly I like,\nDialogue: 0,0:03:24.24,0:03:25.92,EN,,0,0,0,,so I'm going to add my favorite feature.\nDialogue: 0,0:03:26.64,0:03:30.24,EN,,0,0,0,,And then Jim adds his favorite feature.\nDialogue: 0,0:03:30.83,0:03:31.79,EN,,0,0,0,,And, after a while,\nDialogue: 0,0:03:31.80,0:03:34.81,EN,,0,0,0,,the thing has a manual 500 pages long\nDialogue: 0,0:03:35.15,0:03:36.51,EN,,0,0,0,,that no one can understand.\nDialogue: 0,0:03:37.79,0:03:39.32,EN,,0,0,0,,And sometimes it's the same person\nDialogue: 0,0:03:39.90,0:03:41.37,EN,,0,0,0,,who writes all of these features\nDialogue: 0,0:03:41.39,0:03:43.23,EN,,0,0,0,,and produces this terribly complicated thing.\nDialogue: 0,0:03:44.14,0:03:46.09,EN,,0,0,0,,In some cases, like editors,\nDialogue: 0,0:03:47.37,0:03:49.12,EN,,0,0,0,,it's sort of reasonable to have lots of features,\nDialogue: 0,0:03:50.92,0:03:52.65,EN,,0,0,0,,because there are a lot of things you want to be able to do\nDialogue: 0,0:03:52.68,0:03:53.76,EN,,0,0,0,,and many of them arbitrary.\nDialogue: 0,0:03:56.11,0:03:57.29,EN,,0,0,0,,But in computer languages,\nDialogue: 0,0:03:57.85,0:03:58.91,EN,,0,0,0,,I think it's a disaster\nDialogue: 0,0:04:00.01,0:04:01.29,EN,,0,0,0,,to have too much stuff in them.\nDialogue: 0,0:04:04.03,0:04:08.00,EN,,0,0,0,,The other alternative you get into is something called feeping creaturism,\nDialogue: 0,0:04:09.52,0:04:11.39,EN,,0,0,0,,which is where you have a box\nDialogue: 0,0:04:11.80,0:04:15.29,EN,,0,0,0,,which has a display, a fancy display, and a mouse,\nDialogue: 0,0:04:15.95,0:04:20.04,EN,,0,0,0,,and there is all sorts of complexity associated with all this fancy IO.\nDialogue: 0,0:04:21.01,0:04:22.80,EN,,0,0,0,,And your computer language becomes\nDialogue: 0,0:04:23.34,0:04:25.37,EN,,0,0,0,,a dismal, little, tiny thing that barely works\nDialogue: 0,0:04:25.40,0:04:27.90,EN,,0,0,0,,because of all the swapping, and disk twitching, and so on,\nDialogue: 0,0:04:28.09,0:04:29.36,EN,,0,0,0,,caused by your Window system.\nDialogue: 0,0:04:30.08,0:04:31.82,EN,,0,0,0,,And every time you go near the computer,\nDialogue: 0,0:04:31.93,0:04:33.45,EN,,0,0,0,,the mouse process wakes up and says,\nDialogue: 0,0:04:33.85,0:04:35.95,EN,,0,0,0,,gee do you have something for me to do,\nDialogue: 0,0:04:36.14,0:04:37.23,EN,,0,0,0,,and then it goes back to sleep.\nDialogue: 0,0:04:37.44,0:04:39.44,EN,,0,0,0,,And if you accidentally push mouse with you elbow,\nDialogue: 0,0:04:39.61,0:04:42.32,EN,,0,0,0,,a big puff of smoke comes out of your computer and things like that.\nDialogue: 0,0:04:42.94,0:04:45.29,EN,,0,0,0,,So two ways to disastrously\nDialogue: 0,0:04:45.55,0:04:47.21,EN,,0,0,0,,destroy a system by adding features.\nDialogue: 0,0:04:47.50,0:04:49.73,EN,,0,0,0,,But try right now to add a little, simple feature.\nDialogue: 0,0:04:52.60,0:04:53.77,EN,,0,0,0,,This actually is a good one,\nDialogue: 0,0:04:53.85,0:04:56.17,EN,,0,0,0,,and in fact, real Lisps have it.\nDialogue: 0,0:04:57.25,0:04:58.17,EN,,0,0,0,,As you've seen,\nDialogue: 0,0:04:59.29,0:05:03.13,EN,,0,0,0,,there are procedures like plus and times\nDialogue: 0,0:05:03.37,0:05:04.89,EN,,0,0,0,,that take any number of arguments.\nDialogue: 0,0:05:05.43,0:05:06.44,EN,,0,0,0,,So we can write things\nDialogue: 0,0:05:06.57,0:05:10.94,EN,,0,0,0,,like the sum of the product of a and x and x,\nDialogue: 0,0:05:12.09,0:05:16.99,EN,,0,0,0,,and the product of b and x and c.\nDialogue: 0,0:05:17.54,0:05:18.68,EN,,0,0,0,,As you can see here,\nDialogue: 0,0:05:18.92,0:05:21.76,EN,,0,0,0,,addition takes three arguments or two arguments,\nDialogue: 0,0:05:22.30,0:05:24.81,EN,,0,0,0,,multiplication takes two arguments or three arguments,\nDialogue: 0,0:05:25.08,0:05:26.76,EN,,0,0,0,,taking numbers of arguments\nDialogue: 0,0:05:26.78,0:05:28.49,EN,,0,0,0,,all of which are to be treated in the same way.\nDialogue: 0,0:05:30.00,0:05:32.17,EN,,0,0,0,,This is a valuable thing,\nDialogue: 0,0:05:32.28,0:05:34.01,EN,,0,0,0,,indefinite numbers of arguments.\nDialogue: 0,0:05:34.96,0:05:38.41,EN,,0,0,0,,Yet the particular Lisp system that I show you\nDialogue: 0,0:05:39.23,0:05:41.85,EN,,0,0,0,,is one where the numbers of arguments is fixed,\nDialogue: 0,0:05:42.62,0:05:45.28,EN,,0,0,0,,because I had to match the arguments against the formal parameters\nDialogue: 0,0:05:45.63,0:05:47.92,EN,,0,0,0,,in the binder, where there's a pairup.\nDialogue: 0,0:05:50.81,0:05:53.80,EN,,0,0,0,,Well, I'd like to be able to define new procedures like this\nDialogue: 0,0:05:54.89,0:05:57.32,EN,,0,0,0,,that can have any number of arguments.\nDialogue: 0,0:05:58.75,0:06:00.40,EN,,0,0,0,,Well there's several parts to this problem.\nDialogue: 0,0:06:01.34,0:06:04.81,EN,,0,0,0,,The first part is coming up with the syntactic specification,\nDialogue: 0,0:06:05.72,0:06:11.21,EN,,0,0,0,,some way of notating the additional arguments,\nDialogue: 0,0:06:12.17,0:06:13.63,EN,,0,0,0,,of which you don't know how many there are.\nDialogue: 0,0:06:15.48,0:06:16.62,EN,,0,0,0,,And then there's the other thing,\nDialogue: 0,0:06:17.10,0:06:18.70,EN,,0,0,0,,which is once we've notated it,\nDialogue: 0,0:06:19.07,0:06:20.78,EN,,0,0,0,,how are we going to interpret that notation\nDialogue: 0,0:06:21.74,0:06:23.10,EN,,0,0,0,,so as to do the right thing,\nDialogue: 0,0:06:23.85,0:06:25.37,EN,,0,0,0,,whatever the right thing is?\nDialogue: 0,0:06:26.98,0:06:28.80,EN,,0,0,0,,So let's consider an example of a sort of thing\nDialogue: 0,0:06:28.84,0:06:30.27,EN,,0,0,0,,we might want to be able to do.\nDialogue: 0,0:06:33.07,0:06:34.51,EN,,0,0,0,,So an example might be,\nDialogue: 0,0:06:35.42,0:06:37.34,EN,,0,0,0,,that I might want to be able to define a procedure\nDialogue: 0,0:06:37.95,0:06:41.36,EN,,0,0,0,,which is a procedure of one required argument x\nDialogue: 0,0:06:42.20,0:06:45.26,EN,,0,0,0,,and a non-required -- bunch of arguments,\nDialogue: 0,0:06:45.28,0:06:47.23,EN,,0,0,0,,I don't know how many there are, called y.\nDialogue: 0,0:06:49.09,0:06:50.36,EN,,0,0,0,,So x is required,\nDialogue: 0,0:06:55.88,0:06:57.44,EN,,0,0,0,,and there are many y's,\nDialogue: 0,0:06:59.53,0:07:05.99,EN,,0,0,0,,many arguments-- y will be the list of them.\nDialogue: 0,0:07:14.48,0:07:16.06,EN,,0,0,0,,Now, with such a thing,\nDialogue: 0,0:07:16.09,0:07:17.68,EN,,0,0,0,,we might be able to say something like,\nDialogue: 0,0:07:19.02,0:07:21.98,EN,,0,0,0,,map-- I'm going to do something to every one--\nDialogue: 0,0:07:22.52,0:07:25.76,EN,,0,0,0,,of that procedure of one argument u,\nDialogue: 0,0:07:27.00,0:07:34.54,EN,,0,0,0,,which multiplies x by u, and we'll apply that to y.\nDialogue: 0,0:07:36.89,0:07:38.04,EN,,0,0,0,,I've used a dot here\nDialogue: 0,0:07:38.59,0:07:41.31,EN,,0,0,0,,to indicate that the thing after this\nDialogue: 0,0:07:42.19,0:07:44.30,EN,,0,0,0,,is a list of all the rest of the arguments.\nDialogue: 0,0:07:46.30,0:07:48.12,EN,,0,0,0,,I'm making a syntactic specification.\nDialogue: 0,0:07:53.32,0:07:54.64,EN,,0,0,0,,Now, what this depends upon,\nDialogue: 0,0:07:55.71,0:07:58.06,EN,,0,0,0,,the reason why this is sort of a reasonable thing to do,\nDialogue: 0,0:07:59.77,0:08:01.96,EN,,0,0,0,,is because this happens to be a syntax\nDialogue: 0,0:08:02.00,0:08:03.60,EN,,0,0,0,,that's used in the Lisp reader\nDialogue: 0,0:08:04.41,0:08:07.15,EN,,0,0,0,,for representing conses.\nDialogue: 0,0:08:08.94,0:08:11.08,EN,,0,0,0,,We've never introduced that before.You never see.\nDialogue: 0,0:08:11.08,0:08:12.78,EN,,0,0,0,,You may have seen when playing with the system\nDialogue: 0,0:08:13.04,0:08:14.62,EN,,0,0,0,,if you cons two things together, you get the\nDialogue: 0,0:08:14.89,0:08:18.12,EN,,0,0,0,,first, space, dot, the second, space--\nDialogue: 0,0:08:19.79,0:08:22.83,EN,,0,0,0,,the first, space, dot, space, the second\nDialogue: 0,0:08:23.08,0:08:24.64,EN,,0,0,0,,with parentheses around the whole thing.\nDialogue: 0,0:08:26.98,0:08:28.16,EN,,0,0,0,,So that, for example,\nDialogue: 0,0:08:28.97,0:08:35.04,EN,,0,0,0,,this x dot y corresponds to a pair,\nDialogue: 0,0:08:36.33,0:08:39.29,EN,,0,0,0,,which has got an x in it and a y in it.\nDialogue: 0,0:08:41.48,0:08:43.98,EN,,0,0,0,,The other notations that you've seen so far\nDialogue: 0,0:08:44.94,0:08:46.67,EN,,0,0,0,,are things like, like\nDialogue: 0,0:08:46.92,0:08:55.24,EN,,0,0,0,,a procedure of arguments x and y and z which do things\nDialogue: 0,0:08:55.71,0:08:57.63,EN,,0,0,0,,and that looks like--\nDialogue: 0,0:09:02.00,0:09:03.61,EN,,0,0,0,,Just looking at the bound variable list,\nDialogue: 0,0:09:04.22,0:09:05.29,EN,,0,0,0,,it looks like this,\nDialogue: 0,0:09:09.93,0:09:17.32,EN,,0,0,0,,x, y, z, and the empty thing.\nDialogue: 0,0:09:18.28,0:09:21.08,EN,,0,0,0,,If I have a list of arguments I wish to match this against,\nDialogue: 0,0:09:22.60,0:09:25.60,EN,,0,0,0,,I have a list of arguments one, two, three,\nDialogue: 0,0:09:25.87,0:09:27.26,EN,,0,0,0,,I want to match these against.\nDialogue: 0,0:09:28.38,0:09:37.10,EN,,0,0,0,,OK? So I might have here a list of three things,\nDialogue: 0,0:09:42.44,0:09:46.94,EN,,0,0,0,,one, two, three.\nDialogue: 0,0:09:48.99,0:09:53.16,EN,,0,0,0,,And I want to match x, y, z against one, two, three.\nDialogue: 0,0:09:54.22,0:09:56.28,EN,,0,0,0,,Well, it's clear that the one matches the x,\nDialogue: 0,0:09:56.32,0:09:58.01,EN,,0,0,0,,because I can just sort of follow the structure,\nDialogue: 0,0:09:58.86,0:10:01.56,EN,,0,0,0,,and the two matches the y,\nDialogue: 0,0:10:02.46,0:10:04.04,EN,,0,0,0,,and the three matches the z.\nDialogue: 0,0:10:05.48,0:10:09.53,EN,,0,0,0,,But now, supposing I were to compare this x dot y.\nDialogue: 0,0:10:09.55,0:10:11.84,EN,,0,0,0,,this is x dot y--\nDialogue: 0,0:10:12.51,0:10:16.91,EN,,0,0,0,,supposing I compare that with a list of three arguments, one, two, three.\nDialogue: 0,0:10:19.08,0:10:20.00,EN,,0,0,0,,Let's look at that again.\nDialogue: 0,0:10:28.00,0:10:30.32,EN,,0,0,0,,One, two, three--\nDialogue: 0,0:10:30.86,0:10:32.88,EN,,0,0,0,,Well, I can walk along here\nDialogue: 0,0:10:32.99,0:10:35.50,EN,,0,0,0,,and say, oh yes, x matches the one,\nDialogue: 0,0:10:37.56,0:10:41.84,EN,,0,0,0,,Ah, the y matches the list, which is two and three.\nDialogue: 0,0:10:43.74,0:10:46.22,EN,,0,0,0,,So the notation I'm choosing here\nDialogue: 0,0:10:46.41,0:10:50.16,EN,,0,0,0,,is one that's very natural for Lisp system.\nDialogue: 0,0:10:52.66,0:10:54.14,EN,,0,0,0,,But I'm going to choose this as a notation\nDialogue: 0,0:10:54.17,0:10:55.80,EN,,0,0,0,,for representing a bunch of arguments.\nDialogue: 0,0:10:58.29,0:11:00.09,EN,,0,0,0,,Now, there's an alternative possibility.\nDialogue: 0,0:11:00.59,0:11:02.78,EN,,0,0,0,,If I don't want to take one special out,\nDialogue: 0,0:11:03.00,0:11:05.00,EN,,0,0,0,,or two special ones out or something like that,\nDialogue: 0,0:11:06.54,0:11:07.56,EN,,0,0,0,,if I don't want to do that,\nDialogue: 0,0:11:08.78,0:11:10.44,EN,,0,0,0,,if I want to talk about\nDialogue: 0,0:11:10.52,0:11:12.52,EN,,0,0,0,,just the list of all the arguments like in addition，\nDialogue: 0,0:11:13.88,0:11:17.96,EN,,0,0,0,,well then the argument list I'm going to choose to be\nDialogue: 0,0:11:18.20,0:11:23.45,EN,,0,0,0,,that procedure of all the arguments x, which does something with x\nDialogue: 0,0:11:25.14,0:11:26.30,EN,,0,0,0,,And which, for example,\nDialogue: 0,0:11:26.81,0:11:27.96,EN,,0,0,0,,if I take the procedure,\nDialogue: 0,0:11:28.06,0:11:30.44,EN,,0,0,0,,which takes all the arguments x\nDialogue: 0,0:11:31.12,0:11:32.70,EN,,0,0,0,,and returned the list of them,\nDialogue: 0,0:11:34.81,0:11:38.67,EN,,0,0,0,,OK? That's list. That's the procedure list.\nDialogue: 0,0:11:45.85,0:11:46.67,EN,,0,0,0,,How does this work?\nDialogue: 0,0:11:46.84,0:11:50.06,EN,,0,0,0,,Well, indeed what I had as the bound variable list in this case,\nDialogue: 0,0:11:50.60,0:11:51.45,EN,,0,0,0,,whatever it is,\nDialogue: 0,0:11:51.61,0:11:53.68,EN,,0,0,0,,is being matched against a list of arguments.\nDialogue: 0,0:11:55.14,0:11:57.14,EN,,0,0,0,,This symbol now is all of the arguments.\nDialogue: 0,0:12:01.49,0:12:05.13,EN,,0,0,0,,And so this is the choice I'm making for a particular syntactic specification,\nDialogue: 0,0:12:05.64,0:12:07.63,EN,,0,0,0,,for the description of procedures\nDialogue: 0,0:12:08.04,0:12:10.56,EN,,0,0,0,,which take indefinite numbers of arguments.\nDialogue: 0,0:12:13.45,0:12:14.60,EN,,0,0,0,,There are two cases of it,\nDialogue: 0,0:12:15.40,0:12:16.35,EN,,0,0,0,,this one and this one.\nDialogue: 0,0:12:17.44,0:12:18.36,EN,,0,0,0,,And none of this.\nDialogue: 0,0:12:18.42,0:12:20.11,EN,,0,0,0,,When you make syntactic specifications,\nDialogue: 0,0:12:20.44,0:12:22.54,EN,,0,0,0,,it's important that it's unambiguous,\nDialogue: 0,0:12:23.56,0:12:27.36,EN,,0,0,0,,that neither of these can be confused with\nDialogue: 0,0:12:27.66,0:12:31.20,EN,,0,0,0,,a representation we already have, this one.\nDialogue: 0,0:12:33.61,0:12:35.82,EN,,0,0,0,,I can always tell whether I have\nDialogue: 0,0:12:36.54,0:12:39.80,EN,,0,0,0,,a fixed number of explicitly named arguments\nDialogue: 0,0:12:40.28,0:12:41.76,EN,,0,0,0,,made by these formal parameters,\nDialogue: 0,0:12:42.64,0:12:43.13,EN,,0,0,0,,or\nDialogue: 0,0:12:43.28,0:12:45.36,EN,,0,0,0,,a fixed number of named formal parameters\nDialogue: 0,0:12:45.44,0:12:48.01,EN,,0,0,0,,followed by a thing which picks up all the rest of them,\nDialogue: 0,0:12:49.42,0:12:53.52,EN,,0,0,0,,or a list of all the arguments\nDialogue: 0,0:12:53.68,0:12:56.52,EN,,0,0,0,,which will be matched against this particular formal parameter called x,\nDialogue: 0,0:12:56.99,0:12:58.84,EN,,0,0,0,,because these are syntactically distinguishable.\nDialogue: 0,0:13:02.25,0:13:04.62,EN,,0,0,0,,Many languages make terrible errors in that form\nDialogue: 0,0:13:05.04,0:13:08.03,EN,,0,0,0,,where whole segments of interpretation are cut off,\nDialogue: 0,0:13:08.64,0:13:13.92,EN,,0,0,0,,because there are syntactic ambiguities in the language.\nDialogue: 0,0:13:14.56,0:13:16.67,EN,,0,0,0,,They are the traditional problems with ALGOL like languages\nDialogue: 0,0:13:16.67,0:13:23.47,EN,,0,0,0,,having to do with the nesting of ifs in the predicate part.\nDialogue: 0,0:13:25.06,0:13:25.93,EN,,0,0,0,,In any case,\nDialogue: 0,0:13:27.52,0:13:29.44,EN,,0,0,0,,now, so I've told you about the syntax,\nDialogue: 0,0:13:30.27,0:13:34.83,EN,,0,0,0,,now, what are we going to do about the semantics of this?\nDialogue: 0,0:13:35.25,0:13:36.11,EN,,0,0,0,,How do we interpret it?\nDialogue: 0,0:13:36.59,0:13:37.96,EN,,0,0,0,,Well this is just super easy.\nDialogue: 0,0:13:38.44,0:13:42.57,EN,,0,0,0,,I'm going to modify the metacircular interpreter to do it.\nDialogue: 0,0:13:43.71,0:13:44.76,EN,,0,0,0,,And that's a one liner.\nDialogue: 0,0:13:45.98,0:13:46.57,EN,,0,0,0,,There it is.\nDialogue: 0,0:13:47.53,0:13:49.56,EN,,0,0,0,,I'm changing the way you pair things up.\nDialogue: 0,0:13:50.81,0:13:54.19,EN,,0,0,0,,OK? Here we have procedure that pairs --\nDialogue: 0,0:13:56.76,0:14:02.03,EN,,0,0,0,,Here's the procedure that pairs the\nDialogue: 0,0:14:04.81,0:14:09.56,EN,,0,0,0,,the variables, the formal parameters, with the arguments that were passed\nDialogue: 0,0:14:12.16,0:14:16.68,EN,,0,0,0,,from the last description of the metacircular interpreter.\nDialogue: 0,0:14:18.96,0:14:21.93,EN,,0,0,0,,And here's some things that are the same as they were before.\nDialogue: 0,0:14:22.67,0:14:23.23,EN,,0,0,0,,In other words,\nDialogue: 0,0:14:23.31,0:14:25.07,EN,,0,0,0,,if the list of variables is empty,\nDialogue: 0,0:14:25.52,0:14:27.31,EN,,0,0,0,,then if the list of values is empty,\nDialogue: 0,0:14:27.45,0:14:29.61,EN,,0,0,0,,then I have an empty list.\nDialogue: 0,0:14:31.05,0:14:33.00,EN,,0,0,0,,Otherwise, I have too many arguments,\nDialogue: 0,0:14:33.98,0:14:40.19,EN,,0,0,0,,If I have, that is if I have empty variables but not empty values.\nDialogue: 0,0:14:41.58,0:14:44.00,EN,,0,0,0,,If I have empty values,\nDialogue: 0,0:14:44.96,0:14:47.47,EN,,0,0,0,,OK? But the variables are not empty,\nDialogue: 0,0:14:47.48,0:14:48.56,EN,,0,0,0,,that I have too few arguments.\nDialogue: 0,0:14:48.94,0:14:51.31,EN,,0,0,0,,However if I have a variable -- the variables are a symbol--\nDialogue: 0,0:14:55.53,0:14:56.49,EN,,0,0,0,,interesting case--\nDialogue: 0,0:14:58.30,0:15:04.40,EN,,0,0,0,,then, what I should do is say, oh yes, this is the special case\nDialogue: 0,0:15:04.59,0:15:06.51,EN,,0,0,0,,that I have a symbolic tail.\nDialogue: 0,0:15:08.35,0:15:14.11,EN,,0,0,0,,OK. I have here a thing just like we looked over here.\nDialogue: 0,0:15:14.90,0:15:17.87,EN,,0,0,0,,This is a tail which is a symbol, y.\nDialogue: 0,0:15:18.63,0:15:19.39,EN,,0,0,0,,It's not a nil.\nDialogue: 0,0:15:20.73,0:15:21.72,EN,,0,0,0,,It's not the empty list.\nDialogue: 0,0:15:23.26,0:15:25.60,EN,,0,0,0,,Here's a symbolic tail that is just the very beginning of the tail.\nDialogue: 0,0:15:25.98,0:15:26.81,EN,,0,0,0,,There is nothing else.\nDialogue: 0,0:15:27.79,0:15:28.72,EN,,0,0,0,,In that case,\nDialogue: 0,0:15:29.96,0:15:37.20,EN,,0,0,0,,I wish to match that variable with all the values\nDialogue: 0,0:15:38.03,0:15:42.52,EN,,0,0,0,,and add that to the pairing that I'm making.\nDialogue: 0,0:15:44.50,0:15:46.91,EN,,0,0,0,,Otherwise, I go through the normal arrangement\nDialogue: 0,0:15:47.15,0:15:48.52,EN,,0,0,0,,of making up the whole pairing.\nDialogue: 0,0:15:52.02,0:15:53.82,EN,,0,0,0,,I suppose that's very simple.\nDialogue: 0,0:15:54.51,0:15:55.84,EN,,0,0,0,,And that's all there is to it.\nDialogue: 0,0:15:57.08,0:15:58.33,EN,,0,0,0,,And now I'll answer some questions.\nDialogue: 0,0:16:02.62,0:16:05.05,EN,,0,0,0,,The first one-- Are there any questions?\nDialogue: 0,0:16:06.60,0:16:06.94,EN,,0,0,0,,Yes?\nDialogue: 0,0:16:07.37,0:16:09.92,EN,,0,0,0,,AUDIENCE: Could you explain that third form?\nDialogue: 0,0:16:09.98,0:16:12.12,EN,,0,0,0,,PROFESSOR: Third form. This one? OK.\nDialogue: 0,0:16:12.59,0:16:14.27,EN,,0,0,0,,Well, maybe we should look at the thing\nDialogue: 0,0:16:14.30,0:16:16.24,EN,,0,0,0,,as a piece of list structure.\nDialogue: 0,0:16:18.57,0:16:22.73,EN,,0,0,0,,This is a procedure which contains a lambda.\nDialogue: 0,0:16:25.85,0:16:29.61,EN,,0,0,0,,I'm just looking at the list structure which represents this.\nDialogue: 0,0:16:31.26,0:16:32.44,EN,,0,0,0,,Here's x.\nDialogue: 0,0:16:32.73,0:16:33.98,EN,,0,0,0,,These are our symbols.\nDialogue: 0,0:16:37.41,0:16:39.58,EN,,0,0,0,,And then the body is nothing but x.\nDialogue: 0,0:16:44.84,0:16:48.75,EN,,0,0,0,,If I were looking for the bound variable list part of this procedure,\nDialogue: 0,0:16:50.09,0:16:51.58,EN,,0,0,0,,I would go looking at the CADR,\nDialogue: 0,0:16:52.14,0:16:53.16,EN,,0,0,0,,and I'd find a symbol.\nDialogue: 0,0:16:54.01,0:16:57.16,EN,,0,0,0,,So the, matcher, which is this pairup thing I just showed you,\nDialogue: 0,0:16:58.24,0:17:00.44,EN,,0,0,0,,is going to be matching a symbolic object\nDialogue: 0,0:17:01.56,0:17:04.40,EN,,0,0,0,,against a list of arguments that were passed.\nDialogue: 0,0:17:05.76,0:17:09.55,EN,,0,0,0,,And it will bind that symbol to the list of arguments.\nDialogue: 0,0:17:11.37,0:17:16.48,EN,,0,0,0,,The -- In this case, if I'm looking for it,\nDialogue: 0,0:17:16.92,0:17:20.97,EN,,0,0,0,,the match will be against this in the bound variable list position.\nDialogue: 0,0:17:24.14,0:17:26.14,EN,,0,0,0,,Now, if what this does is\nDialogue: 0,0:17:26.17,0:17:29.13,EN,,0,0,0,,it gets a list of arguments and returns it, that's list\nDialogue: 0,0:17:30.40,0:17:31.39,EN,,0,0,0,,That's the procedure is.\nDialogue: 0,0:17:34.51,0:17:35.48,EN,,0,0,0,,Oh well, thank you.\nDialogue: 0,0:17:36.14,0:17:37.28,EN,,0,0,0,,Let's take a break.\nDialogue: 0,0:17:37.83,0:17:55.36,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:17:55.36,0:17:59.02,EN,,0,0,0,,\nDialogue: 0,0:18:03.53,0:18:07.56,EN,,0,0,0,,\nDialogue: 0,0:18:07.56,0:18:11.69,EN,,0,0,0,,\nDialogue: 0,0:18:12.25,0:18:16.11,EN,,0,0,0,,\nDialogue: 0,0:18:20.86,0:18:21.61,EN,,0,0,0,,PROFESSOR: Well let's see.\nDialogue: 0,0:18:23.26,0:18:26.32,EN,,0,0,0,,Now, I'm going to tell you about a rather more substantial variation\nDialogue: 0,0:18:27.45,0:18:31.04,EN,,0,0,0,,one that's a famous variation\nDialogue: 0,0:18:31.60,0:18:36.80,EN,,0,0,0,,hat many early Lisps had.\nDialogue: 0,0:18:38.25,0:18:40.06,EN,,0,0,0,,It's called dynamic binding of variables.\nDialogue: 0,0:18:41.77,0:18:44.68,EN,,0,0,0,,And we'll investigate a little bit about that right now.\nDialogue: 0,0:18:47.62,0:18:50.16,EN,,0,0,0,,I'm going to first introduce this by showing you the sort of thing\nDialogue: 0,0:18:50.35,0:18:52.36,EN,,0,0,0,,that would make someone want this idea.\nDialogue: 0,0:18:53.74,0:18:55.23,EN,,0,0,0,,I'm not going to tell what it is yet,\nDialogue: 0,0:18:55.40,0:18:57.60,EN,,0,0,0,,I'm going to show you why you might want it.\nDialogue: 0,0:18:58.64,0:18:59.93,EN,,0,0,0,,Suppose, for example,\nDialogue: 0,0:19:00.75,0:19:02.59,EN,,0,0,0,,we looked at the sum procedure again\nDialogue: 0,0:19:05.02,0:19:06.43,EN,,0,0,0,,for summing up a bunch of things.\nDialogue: 0,0:19:08.14,0:19:09.47,EN,,0,0,0,,To be that procedure,\nDialogue: 0,0:19:09.60,0:19:10.78,EN,,0,0,0,,of a term,\nDialogue: 0,0:19:13.04,0:19:14.41,EN,,0,0,0,,lower bound,\nDialogue: 0,0:19:15.24,0:19:17.04,EN,,0,0,0,,method of computing the next index,\nDialogue: 0,0:19:17.24,0:19:18.56,EN,,0,0,0,,and upper bound,\nDialogue: 0,0:19:19.36,0:19:20.16,EN,,0,0,0,,such that,\nDialogue: 0,0:19:23.16,0:19:26.94,EN,,0,0,0,,if a is greater than b\nDialogue: 0,0:19:27.15,0:19:28.64,EN,,0,0,0,,then the result is 0,\nDialogue: 0,0:19:30.24,0:19:31.08,EN,,0,0,0,,otherwise,\nDialogue: 0,0:19:33.68,0:19:39.82,EN,,0,0,0,,it's the sum, of the term, procedure, applied to a\nDialogue: 0,0:19:40.60,0:19:44.24,EN,,0,0,0,,and the result of adding up, terms,\nDialogue: 0,0:19:47.68,0:19:52.64,EN,,0,0,0,,with the next a being the a,\nDialogue: 0,0:20:00.30,0:20:03.56,EN,,0,0,0,,the next procedure passed along,\nDialogue: 0,0:20:06.40,0:20:08.25,EN,,0,0,0,,and the upper bound being passed along.\nDialogue: 0,0:20:14.51,0:20:15.76,EN,,0,0,0,,Blink, blink, blink--\nDialogue: 0,0:20:17.82,0:20:21.45,EN,,0,0,0,,OK? Now, when I use this sum procedure,\nDialogue: 0,0:20:21.96,0:20:24.35,EN,,0,0,0,,I can use it, for example, like this.\nDialogue: 0,0:20:25.45,0:20:38.04,EN,,0,0,0,,We can define the sum of the powers to be,\nDialogue: 0,0:20:38.08,0:20:40.33,EN,,0,0,0,,for example, sum of a bunch of powers x to the n,\nDialogue: 0,0:20:41.10,0:20:45.93,EN,,0,0,0,,to be that procedure of a, b, and n--\nDialogue: 0,0:20:45.95,0:20:47.69,EN,,0,0,0,,lower bound, the upper bound, and n--\nDialogue: 0,0:20:48.06,0:20:53.34,EN,,0,0,0,,which is sum, of lambda of x,\nDialogue: 0,0:20:53.60,0:20:59.31,EN,,0,0,0,,the procedure of one argument x, which exponentiates x to the n,\nDialogue: 0,0:21:02.19,0:21:09.29,EN,,0,0,0,,with the a, the incrementer, and b, being passed along.\nDialogue: 0,0:21:11.82,0:21:15.76,EN,,0,0,0,,So we're adding up x to n, given an x.\nDialogue: 0,0:21:16.14,0:21:19.74,EN,,0,0,0,,x takes on values from a to b, incrementing by one.\nDialogue: 0,0:21:22.94,0:21:24.38,EN,,0,0,0,,I can also write the--\nDialogue: 0,0:21:27.68,0:21:28.20,EN,,0,0,0,,That's right.\nDialogue: 0,0:21:29.78,0:21:31.02,EN,,0,0,0,,Product, excuse me.\nDialogue: 0,0:21:31.91,0:21:33.36,EN,,0,0,0,,The product of a bunch of powers.\nDialogue: 0,0:21:38.08,0:21:39.12,EN,,0,0,0,,It's a strange name.\nDialogue: 0,0:21:40.02,0:21:40.80,EN,,0,0,0,,I'm going to leave it there.\nDialogue: 0,0:21:41.96,0:21:46.32,EN,,0,0,0,,Weird-- OK? I write up what I have.\nDialogue: 0,0:21:49.34,0:21:50.19,EN,,0,0,0,,I'm sure that's right.\nDialogue: 0,0:21:51.37,0:21:53.82,EN,,0,0,0,,And if I want the product of a bunch of powers--\nDialogue: 0,0:21:58.41,0:22:02.36,EN,,0,0,0,,That was 12 brain cells, that double-take.\nDialogue: 0,0:22:03.00,0:22:06.81,EN,,0,0,0,,I can for example use the procedure which is like sum,\nDialogue: 0,0:22:06.81,0:22:08.22,EN,,0,0,0,,which is for making products,\nDialogue: 0,0:22:08.56,0:22:11.05,EN,,0,0,0,,but it's similar to that, that you've seen before.\nDialogue: 0,0:22:11.45,0:22:16.38,EN,,0,0,0,,There's a procedure of three arguments again.\nDialogue: 0,0:22:17.00,0:22:25.42,EN,,0,0,0,,Which is the product of terms that are constructed, or factors in this case,\nDialogue: 0,0:22:25.66,0:22:31.60,EN,,0,0,0,,constructed from exponentiating x to the n,\nDialogue: 0,0:22:34.43,0:22:37.85,EN,,0,0,0,,where I start with a, I increment, and I go to b.\nDialogue: 0,0:22:41.53,0:22:41.88,EN,,0,0,0,,Now,\nDialogue: 0,0:22:46.83,0:22:49.50,EN,,0,0,0,,there's some sort of thing here that should disturb you immediately.\nDialogue: 0,0:22:50.75,0:22:52.01,EN,,0,0,0,,These look the same.\nDialogue: 0,0:22:53.18,0:22:55.20,EN,,0,0,0,,Why am I writing this code so many times?\nDialogue: 0,0:22:56.59,0:22:59.72,EN,,0,0,0,,Here I am, in the same boat I've been in before.\nDialogue: 0,0:23:01.00,0:23:03.15,EN,,0,0,0,,Right? Wouldn't it be nice to make an abstraction here?\nDialogue: 0,0:23:03.81,0:23:05.76,EN,,0,0,0,,What's an example of a good abstraction to make?\nDialogue: 0,0:23:05.85,0:23:07.55,EN,,0,0,0,,Well, I see some codes that's identical.\nDialogue: 0,0:23:08.47,0:23:09.32,EN,,0,0,0,,Here's one,\nDialogue: 0,0:23:09.98,0:23:11.08,EN,,0,0,0,,and here's another.\nDialogue: 0,0:23:14.45,0:23:16.22,EN,,0,0,0,,And so maybe I should be able to pull that out.\nDialogue: 0,0:23:17.09,0:23:19.23,EN,,0,0,0,,I should be able to say, oh yes,\nDialogue: 0,0:23:20.51,0:23:22.67,EN,,0,0,0,,the sum of the powers could be written in terms of\nDialogue: 0,0:23:22.88,0:23:24.52,EN,,0,0,0,,something called the nth power procedure.\nDialogue: 0,0:23:25.71,0:23:27.40,EN,,0,0,0,,Imagine somebody wanted to write\nDialogue: 0,0:23:27.74,0:23:30.03,EN,,0,0,0,,a slightly different procedure that looks like this.\nDialogue: 0,0:23:37.63,0:23:45.18,EN,,0,0,0,,The sum powers to be a procedure\nDialogue: 0,0:23:46.44,0:23:48.46,EN,,0,0,0,,of a, b, and n,\nDialogue: 0,0:23:48.75,0:23:52.27,EN,,0,0,0,,which the result of summing up the nth power.\nDialogue: 0,0:23:53.88,0:23:55.42,EN,,0,0,0,,We're going to give a name to that idea,\nDialogue: 0,0:23:58.35,0:24:02.27,EN,,0,0,0,,for starting at a, going by one, and ending at b.\nDialogue: 0,0:24:05.74,0:24:06.91,EN,,0,0,0,,And similarly,\nDialogue: 0,0:24:10.65,0:24:12.76,EN,,0,0,0,,I might want to write the product powers this way,\nDialogue: 0,0:24:12.89,0:24:15.24,EN,,0,0,0,,abstracting out this idea.\nDialogue: 0,0:24:16.27,0:24:17.37,EN,,0,0,0,,I might want this.\nDialogue: 0,0:24:22.10,0:24:23.02,EN,,0,0,0,,Product powers,\nDialogue: 0,0:24:29.48,0:24:34.94,EN,,0,0,0,,to be a procedure of a, b, and n,\nDialogue: 0,0:24:35.31,0:24:42.33,EN,,0,0,0,,which is the product of the nth power operation\nDialogue: 0,0:24:46.44,0:24:50.30,EN,,0,0,0,,on a with the incrementation and b being\nDialogue: 0,0:24:53.50,0:24:57.56,EN,,0,0,0,,being my arguments for the analogous-thing product.\nDialogue: 0,0:24:58.38,0:25:00.24,EN,,0,0,0,,And I'd like to be able to define,\nDialogue: 0,0:25:02.04,0:25:03.88,EN,,0,0,0,,I'd like to be able to define nth power--\nDialogue: 0,0:25:04.89,0:25:05.93,EN,,0,0,0,,I'll put it over here.\nDialogue: 0,0:25:12.22,0:25:12.99,EN,,0,0,0,,I'll put it at the top.\nDialogue: 0,0:25:25.41,0:25:29.04,EN,,0,0,0,,--to be, in fact, my procedure of one argument x\nDialogue: 0,0:25:29.60,0:25:34.56,EN,,0,0,0,,which is the result of exponentiating x to the n.\nDialogue: 0,0:25:35.93,0:25:36.96,EN,,0,0,0,,But I have a problem.\nDialogue: 0,0:25:38.64,0:25:39.93,EN,,0,0,0,,My environment model,\nDialogue: 0,0:25:40.57,0:25:43.23,EN,,0,0,0,,that is my means of interpretation\nDialogue: 0,0:25:44.00,0:25:45.95,EN,,0,0,0,,of interpretation for the language that we've defined so far,\nDialogue: 0,0:25:46.27,0:25:48.81,EN,,0,0,0,,does not give me a meaning for this n.\nDialogue: 0,0:25:52.76,0:25:59.26,EN,,0,0,0,,Because, as you know, the, as you know\nDialogue: 0,0:26:00.76,0:26:04.25,EN,,0,0,0,,this n is free in this procedure.\nDialogue: 0,0:26:06.41,0:26:07.98,EN,,0,0,0,,The environment model tells us\nDialogue: 0,0:26:08.60,0:26:10.20,EN,,0,0,0,,that the meaning of a free variable\nDialogue: 0,0:26:11.21,0:26:14.99,EN,,0,0,0,,is determined in the environment in which this procedure is defined.\nDialogue: 0,0:26:16.64,0:26:17.47,EN,,0,0,0,,In a way I have written it,\nDialogue: 0,0:26:17.48,0:26:19.84,EN,,0,0,0,,assuming these things are defined on the blackboard as is,\nDialogue: 0,0:26:21.64,0:26:23.63,EN,,0,0,0,,this is defined in the global environment,\nDialogue: 0,0:26:24.06,0:26:25.15,EN,,0,0,0,,where there is no n.\nDialogue: 0,0:26:25.93,0:26:27.63,EN,,0,0,0,,Therefore, n is unbound variable.\nDialogue: 0,0:26:28.72,0:26:31.66,EN,,0,0,0,,But it's perfectly clear, to most of us,\nDialogue: 0,0:26:32.60,0:26:36.32,EN,,0,0,0,,that we would like it to be this n and this n.\nDialogue: 0,0:26:38.99,0:26:42.67,EN,,0,0,0,,On the other hand, OK, it would be nice.\nDialogue: 0,0:26:42.84,0:26:44.28,EN,,0,0,0,,Certainly we've got to be careful here\nDialogue: 0,0:26:44.56,0:26:46.06,EN,,0,0,0,,of keeping this to be this,\nDialogue: 0,0:26:48.96,0:26:52.83,EN,,0,0,0,,and this one over here, wherever it is to be this one.\nDialogue: 0,0:26:57.39,0:26:59.74,EN,,0,0,0,,Well, the desire to make this work\nDialogue: 0,0:27:00.67,0:27:02.72,EN,,0,0,0,,has led to a very famous bug.\nDialogue: 0,0:27:04.65,0:27:06.04,EN,,0,0,0,,I'll tell you about the famous bug.\nDialogue: 0,0:27:07.15,0:27:09.40,EN,,0,0,0,,Look at this slide.\nDialogue: 0,0:27:10.66,0:27:12.70,EN,,0,0,0,,This is an idea called dynamic binding.\nDialogue: 0,0:27:13.99,0:27:16.91,EN,,0,0,0,,Where, instead of the free variable being interpreted\nDialogue: 0,0:27:17.76,0:27:21.23,EN,,0,0,0,,in the environment of definition of a procedure,\nDialogue: 0,0:27:22.40,0:27:25.16,EN,,0,0,0,,the free variable is interpreted as having its value\nDialogue: 0,0:27:25.44,0:27:29.31,EN,,0,0,0,,in the environment of the caller of the procedure.\nDialogue: 0,0:27:31.85,0:27:34.84,EN,,0,0,0,,So what you have is a system\nDialogue: 0,0:27:34.86,0:27:39.68,EN,,0,0,0,,where you search up the chain of callers of a particular procedure,\nDialogue: 0,0:27:40.43,0:27:42.65,EN,,0,0,0,,and, of course, in this case,\nDialogue: 0,0:27:42.84,0:27:44.30,EN,,0,0,0,,since nth power is called\nDialogue: 0,0:27:44.33,0:27:45.98,EN,,0,0,0,,from inside product whatever it is--\nDialogue: 0,0:27:46.41,0:27:48.68,EN,,0,0,0,,I had to write our own sum which is the analogous procedure--\nDialogue: 0,0:27:50.51,0:27:54.92,EN,,0,0,0,,and product is presumably called from product powers,\nDialogue: 0,0:27:55.13,0:27:56.14,EN,,0,0,0,,as you see over here,\nDialogue: 0,0:27:56.83,0:27:59.37,EN,,0,0,0,,then since product powers bind with variable n ,\nDialogue: 0,0:28:00.09,0:28:04.09,EN,,0,0,0,,then nth powers n would be derived through that chain.\nDialogue: 0,0:28:08.14,0:28:09.64,EN,,0,0,0,,Similarly, this n,\nDialogue: 0,0:28:10.11,0:28:12.01,EN,,0,0,0,,the nth power in n in this case,\nDialogue: 0,0:28:12.32,0:28:15.80,EN,,0,0,0,,would come through nth power here being called from inside sum.\nDialogue: 0,0:28:15.80,0:28:18.27,EN,,0,0,0,,You can see it being called from inside sum here.\nDialogue: 0,0:28:20.73,0:28:21.69,EN,,0,0,0,,It's called term here.\nDialogue: 0,0:28:22.90,0:28:25.72,EN,,0,0,0,,But sum was called from inside of sum powers,\nDialogue: 0,0:28:26.94,0:28:27.96,EN,,0,0,0,,which bound n.\nDialogue: 0,0:28:28.93,0:28:30.65,EN,,0,0,0,,Therefore, there would be an n available\nDialogue: 0,0:28:32.75,0:28:36.11,EN,,0,0,0,,that n to get it's value from.\nDialogue: 0,0:28:37.95,0:28:39.24,EN,,0,0,0,,This is called dynamic --\nDialogue: 0,0:28:39.28,0:28:43.10,EN,,0,0,0,,What we have below this white line plus over here\nDialogue: 0,0:28:43.31,0:28:46.04,EN,,0,0,0,,is what's called a dynamic binding view of the world.\nDialogue: 0,0:28:46.59,0:28:49.00,EN,,0,0,0,,If that works, that's a dynamic binding view.\nDialogue: 0,0:28:50.85,0:28:52.65,EN,,0,0,0,,Now, let's take a look, for example,\nDialogue: 0,0:28:54.54,0:28:55.99,EN,,0,0,0,,at just what it takes to implement that.\nDialogue: 0,0:28:55.99,0:28:56.96,EN,,0,0,0,,That's real easy.\nDialogue: 0,0:28:57.48,0:28:59.34,EN,,0,0,0,,In fact, the very first Lisps\nDialogue: 0,0:29:00.01,0:29:02.52,EN,,0,0,0,,had any form of interpretations of the free variables at all,\nDialogue: 0,0:29:03.31,0:29:05.98,EN,,0,0,0,,had dynamic binding interpretations for the free variables.\nDialogue: 0,0:29:06.40,0:29:10.14,EN,,0,0,0,,APL has dynamic binding interpretation for the free variables,\nDialogue: 0,0:29:11.68,0:29:14.32,EN,,0,0,0,,not lexical or static binding.\nDialogue: 0,0:29:15.22,0:29:17.00,EN,,0,0,0,,So, of course, the change is in eval.\nDialogue: 0,0:29:19.31,0:29:20.59,EN,,0,0,0,,And it's really in two places.\nDialogue: 0,0:29:22.78,0:29:25.61,EN,,0,0,0,,First of all, one thing we see,\nDialogue: 0,0:29:26.52,0:29:28.49,EN,,0,0,0,,is that things become a little simpler.\nDialogue: 0,0:29:29.39,0:29:33.63,EN,,0,0,0,,If I don't have to have the -- If I don't have to have the\nDialogue: 0,0:29:33.64,0:29:36.20,EN,,0,0,0,,environment be the environment of definition for procedure,\nDialogue: 0,0:29:36.44,0:29:38.04,EN,,0,0,0,,the procedure need not capture\nDialogue: 0,0:29:38.43,0:29:40.17,EN,,0,0,0,,the environment at the time it's defined.\nDialogue: 0,0:29:42.03,0:29:44.96,EN,,0,0,0,,And so if we look here at this slide,\nDialogue: 0,0:29:45.84,0:29:50.08,EN,,0,0,0,,we see that the clause for a lambda expression,\nDialogue: 0,0:29:50.73,0:29:52.43,EN,,0,0,0,,which is the way a procedure is defined,\nDialogue: 0,0:29:53.92,0:29:56.73,EN,,0,0,0,,does not make up a thing which has a type closure\nDialogue: 0,0:29:56.75,0:30:01.05,EN,,0,0,0,,and a attached environment structure.\nDialogue: 0,0:30:01.29,0:30:02.54,EN,,0,0,0,,It's just the expression itself.\nDialogue: 0,0:30:02.54,0:30:04.76,EN,,0,0,0,,And we'll decompose that some other way somewhere else.\nDialogue: 0,0:30:06.44,0:30:09.40,EN,,0,0,0,,The other thing we see is the applicator\nDialogue: 0,0:30:10.36,0:30:13.69,EN,,0,0,0,,applicator must be able to get the environment of the caller.\nDialogue: 0,0:30:14.29,0:30:17.24,EN,,0,0,0,,The caller of a procedure is right here.\nDialogue: 0,0:30:17.26,0:30:19.45,EN,,0,0,0,,If the procedure is a application--\nDialogue: 0,0:30:19.56,0:30:21.63,EN,,0,0,0,,If the expression we're evaluating is a combination,\nDialogue: 0,0:30:21.79,0:30:23.71,EN,,0,0,0,,then we're going to call a combination\nDialogue: 0,0:30:23.93,0:30:25.50,EN,,0,0,0,,then we're going to call a procedure\nDialogue: 0,0:30:25.66,0:30:27.37,EN,,0,0,0,,which is the value of the operator.\nDialogue: 0,0:30:29.84,0:30:31.44,EN,,0,0,0,,The environment of the caller\nDialogue: 0,0:30:31.98,0:30:34.51,EN,,0,0,0,,is the environment we have right here, available now.\nDialogue: 0,0:30:35.89,0:30:40.72,EN,,0,0,0,,So all I have to do is pass that environment to the applicator, to apply.\nDialogue: 0,0:30:41.49,0:30:42.75,EN,,0,0,0,,And if we look at that here,\nDialogue: 0,0:30:43.58,0:30:44.97,EN,,0,0,0,,the only change we have to make\nDialogue: 0,0:30:45.71,0:30:48.41,EN,,0,0,0,,is that fellow takes that environment\nDialogue: 0,0:30:48.78,0:30:55.68,EN,,0,0,0,,uses that environment for the purpose of extending that environment\nDialogue: 0,0:30:56.67,0:30:59.02,EN,,0,0,0,,when abiding the formal parameters\nDialogue: 0,0:30:59.02,0:31:01.37,EN,,0,0,0,,of the procedure to the arguments that were passed,\nDialogue: 0,0:31:03.08,0:31:05.98,EN,,0,0,0,,not an environment that was captured in the procedure.\nDialogue: 0,0:31:06.81,0:31:09.45,EN,,0,0,0,,The reason why the first Lisps were implemented this way,\nDialogue: 0,0:31:09.66,0:31:11.96,EN,,0,0,0,,is the sort of the obvious, accidental implementation.\nDialogue: 0,0:31:14.13,0:31:16.68,EN,,0,0,0,,And, of course, as usual, people got used to it and liked it.\nDialogue: 0,0:31:17.25,0:31:18.27,EN,,0,0,0,,And there were some people said,\nDialogue: 0,0:31:18.40,0:31:19.50,EN,,0,0,0,,this is the way to do it.\nDialogue: 0,0:31:21.59,0:31:24.09,EN,,0,0,0,,Unfortunately that causes some serious problems.\nDialogue: 0,0:31:25.40,0:31:27.24,EN,,0,0,0,,The most important, serious problem\nDialogue: 0,0:31:27.53,0:31:29.84,EN,,0,0,0,,in using dynamic binding\nDialogue: 0,0:31:31.00,0:31:33.56,EN,,0,0,0,,is there's a modularity crisis that's involved it.\nDialogue: 0,0:31:35.46,0:31:37.66,EN,,0,0,0,,If two people are working together on some big system,\nDialogue: 0,0:31:38.57,0:31:40.01,EN,,0,0,0,,then an important thing to one\nDialogue: 0,0:31:40.35,0:31:42.19,EN,,0,0,0,,is that the names used by each one\nDialogue: 0,0:31:42.99,0:31:44.58,EN,,0,0,0,,don't interfere with the names of the other.\nDialogue: 0,0:31:47.93,0:31:50.78,EN,,0,0,0,,It's important that when I invent some segment of code\nDialogue: 0,0:31:51.07,0:31:53.13,EN,,0,0,0,,that no one can make my code stop working\nDialogue: 0,0:31:53.88,0:31:56.57,EN,,0,0,0,,by using my names that I use internal to my code,\nDialogue: 0,0:31:56.75,0:31:57.71,EN,,0,0,0,,internal to his code.\nDialogue: 0,0:31:59.85,0:32:00.46,EN,,0,0,0,,However,\nDialogue: 0,0:32:01.04,0:32:05.18,EN,,0,0,0,,dynamic binding violates that particular modularity constraint in a clear way.\nDialogue: 0,0:32:06.67,0:32:08.08,EN,,0,0,0,,Consider, for example,\nDialogue: 0,0:32:09.18,0:32:10.35,EN,,0,0,0,,what happens over here.\nDialogue: 0,0:32:12.54,0:32:13.79,EN,,0,0,0,,Suppose it was the case\nDialogue: 0,0:32:15.47,0:32:19.81,EN,,0,0,0,,that I decided to change the word next.\nDialogue: 0,0:32:19.81,0:32:24.41,EN,,0,0,0,,Supposing somebody is writing, somebody is writing sum,\nDialogue: 0,0:32:25.10,0:32:26.68,EN,,0,0,0,,and somebody else is going to use sum.\nDialogue: 0,0:32:28.97,0:32:30.32,EN,,0,0,0,,The writer of sum\nDialogue: 0,0:32:30.49,0:32:32.30,EN,,0,0,0,,has a choice of what names he may use.\nDialogue: 0,0:32:33.66,0:32:34.84,EN,,0,0,0,,Let's say, I'm that writer.\nDialogue: 0,0:32:36.83,0:32:39.30,EN,,0,0,0,,Well, by gosh, just happens I didn't want to call this next.\nDialogue: 0,0:32:39.30,0:32:40.09,EN,,0,0,0,,I called it n.\nDialogue: 0,0:32:41.74,0:32:43.10,EN,,0,0,0,,So all places where you see next,\nDialogue: 0,0:32:44.28,0:32:45.26,EN,,0,0,0,,I called it n.\nDialogue: 0,0:32:48.14,0:32:48.48,EN,,0,0,0,,Whoops.\nDialogue: 0,0:32:49.94,0:32:52.22,EN,,0,0,0,,I changed nothing about the specifications of this program,\nDialogue: 0,0:32:53.32,0:32:54.86,EN,,0,0,0,,but this program stops working.\nDialogue: 0,0:32:56.11,0:32:57.96,EN,,0,0,0,,Not only that, unfortunately, this one does too.\nDialogue: 0,0:32:59.50,0:33:01.40,EN,,0,0,0,,Why do these programs stop working?\nDialogue: 0,0:33:02.26,0:33:03.24,EN,,0,0,0,,Well, it's sort of clear.\nDialogue: 0,0:33:04.48,0:33:09.29,EN,,0,0,0,,Instead of chasing out the value of the n\nDialogue: 0,0:33:09.31,0:33:13.72,EN,,0,0,0,,that occurs in nth power over here or over here,\nDialogue: 0,0:33:14.97,0:33:17.16,EN,,0,0,0,,through the environment of definition,\nDialogue: 0,0:33:17.20,0:33:19.58,EN,,0,0,0,,where this one is always linked to this one,\nDialogue: 0,0:33:19.87,0:33:21.48,EN,,0,0,0,,if it was through the environment of definition,\nDialogue: 0,0:33:21.55,0:33:23.63,EN,,0,0,0,,because here is the definition.\nDialogue: 0,0:33:24.37,0:33:26.25,EN,,0,0,0,,This lambda expression was executed\nDialogue: 0,0:33:26.59,0:33:28.59,EN,,0,0,0,,in the environment where that n was defined.\nDialogue: 0,0:33:30.70,0:33:31.84,EN,,0,0,0,,If instead of doing that,\nDialogue: 0,0:33:32.01,0:33:33.68,EN,,0,0,0,,I have to chase through the call chain,\nDialogue: 0,0:33:34.78,0:33:36.27,EN,,0,0,0,,then look what horrible thing happens.\nDialogue: 0,0:33:37.32,0:33:41.18,EN,,0,0,0,,Well, this was called from inside sum as term, term a.\nDialogue: 0,0:33:41.76,0:33:42.38,EN,,0,0,0,,term a.\nDialogue: 0,0:33:44.78,0:33:46.19,EN,,0,0,0,,I'm looking for a value of n.\nDialogue: 0,0:33:47.35,0:33:48.40,EN,,0,0,0,,Instead of getting this one,\nDialogue: 0,0:33:48.84,0:33:49.76,EN,,0,0,0,,I get that one.\nDialogue: 0,0:33:50.70,0:33:52.54,EN,,0,0,0,,So by changing the insides of this program,\nDialogue: 0,0:33:52.86,0:33:54.09,EN,,0,0,0,,this program stops working.\nDialogue: 0,0:33:56.77,0:34:00.08,EN,,0,0,0,,So I no longer have a quantifier, as I described before.\nDialogue: 0,0:34:01.12,0:34:05.13,EN,,0,0,0,,Which is a symbol -- The lambda symbol is supposed to be a quantifier.\nDialogue: 0,0:34:05.43,0:34:06.70,EN,,0,0,0,,A thing which has the property\nDialogue: 0,0:34:06.89,0:34:11.42,EN,,0,0,0,,that the names that are bound by it are unimportant,\nDialogue: 0,0:34:12.65,0:34:15.71,EN,,0,0,0,,that I can uniformly substitute any names for these\nDialogue: 0,0:34:16.92,0:34:19.98,EN,,0,0,0,,throughout this thing, so long as they don't occur in here, the new names,\nDialogue: 0,0:34:20.94,0:34:23.16,EN,,0,0,0,,and the meaning of this expression should remain unchanged.\nDialogue: 0,0:34:24.04,0:34:25.50,EN,,0,0,0,,I've just changed the meaning of the expression\nDialogue: 0,0:34:25.53,0:34:27.20,EN,,0,0,0,,by changing the one of the names.\nDialogue: 0,0:34:28.69,0:34:30.89,EN,,0,0,0,,So lambda is no longer a well defined idea.\nDialogue: 0,0:34:32.17,0:34:33.37,EN,,0,0,0,,It's a very serious problem.\nDialogue: 0,0:34:34.55,0:34:35.55,EN,,0,0,0,,So for that reason,\nDialogue: 0,0:34:36.64,0:34:42.51,EN,,0,0,0,,I and my buddies have given up this particular kind of abstraction,\nDialogue: 0,0:34:43.13,0:34:44.36,EN,,0,0,0,,which I would like to have,\nDialogue: 0,0:34:45.61,0:34:47.50,EN,,0,0,0,,in favor of a modularity principle.\nDialogue: 0,0:34:48.09,0:34:50.20,EN,,0,0,0,,But this is the kind of experiment you can do\nDialogue: 0,0:34:51.96,0:34:53.68,EN,,0,0,0,,if you want to play with these interpreters.\nDialogue: 0,0:34:54.83,0:34:56.91,EN,,0,0,0,,You can try them out this way, that way, and the other way.\nDialogue: 0,0:34:58.11,0:35:00.25,EN,,0,0,0,,You see what makes a nicer language.\nDialogue: 0,0:35:02.68,0:35:04.49,EN,,0,0,0,,So that's a very important thing to be able to do.\nDialogue: 0,0:35:04.99,0:35:06.68,EN,,0,0,0,,Now, I would like to give you a feeling\nDialogue: 0,0:35:06.72,0:35:08.49,EN,,0,0,0,,for I think the right thing to do is here.\nDialogue: 0,0:35:09.32,0:35:12.91,EN,,0,0,0,,How are you going to, how are you going to I get this kind of\nDialogue: 0,0:35:13.04,0:35:15.34,EN,,0,0,0,,of power in a lexical system?\nDialogue: 0,0:35:16.28,0:35:17.39,EN,,0,0,0,,And the answer is, of course,\nDialogue: 0,0:35:17.55,0:35:20.03,EN,,0,0,0,,what I really want is a something that makes up for me\nDialogue: 0,0:35:20.68,0:35:22.60,EN,,0,0,0,,an exponentiator for a particular n.\nDialogue: 0,0:35:23.69,0:35:24.28,EN,,0,0,0,,Given an n,\nDialogue: 0,0:35:24.32,0:35:25.66,EN,,0,0,0,,it will make me an exponentiator.\nDialogue: 0,0:35:26.28,0:35:27.40,EN,,0,0,0,,Oh, but that's easy too.\nDialogue: 0,0:35:28.17,0:35:30.57,EN,,0,0,0,,In other words, I can write my program this way.\nDialogue: 0,0:35:35.84,0:35:37.84,EN,,0,0,0,,I'm going to define a thing called PGEN,\nDialogue: 0,0:35:40.25,0:35:42.54,EN,,0,0,0,,which is a procedure of n\nDialogue: 0,0:35:43.16,0:35:45.95,EN,,0,0,0,,which produces for me an exponentiator.\nDialogue: 0,0:35:50.24,0:35:51.23,EN,,0,0,0,,--x to the n.\nDialogue: 0,0:35:56.80,0:35:57.98,EN,,0,0,0,,Given that I have that,\nDialogue: 0,0:35:58.59,0:36:00.88,EN,,0,0,0,,then I can capture the abstraction I wanted\nDialogue: 0,0:36:01.42,0:36:03.93,EN,,0,0,0,,even better, because now it's encapsulated in a way\nDialogue: 0,0:36:04.09,0:36:06.60,EN,,0,0,0,,where I can't be destroyed by a change of names.\nDialogue: 0,0:36:07.89,0:36:12.35,EN,,0,0,0,,I can define some powers\nDialogue: 0,0:36:17.28,0:36:20.70,EN,,0,0,0,,I can define some powers to be a procedure again of a, b, and n\nDialogue: 0,0:36:21.61,0:36:26.83,EN,,0,0,0,,which is the sum of the term function\nDialogue: 0,0:36:26.88,0:36:32.32,EN,,0,0,0,,generated by using this generator, PGEN, n,\nDialogue: 0,0:36:34.40,0:36:38.01,EN,,0,0,0,,with a, incrementer, and b.\nDialogue: 0,0:36:42.49,0:36:47.95,EN,,0,0,0,,And I can define the product of powers\nDialogue: 0,0:36:54.11,0:36:58.84,EN,,0,0,0,,to be a procedure of a, b, and n\nDialogue: 0,0:36:59.80,0:37:09.96,EN,,0,0,0,,which is the product PGEN, n, with a, increment, and b.\nDialogue: 0,0:37:11.28,0:37:13.28,EN,,0,0,0,,Now, of course, this is a very simple example\nDialogue: 0,0:37:13.60,0:37:16.35,EN,,0,0,0,,where this object that I'm trying to abstract over is small.\nDialogue: 0,0:37:17.28,0:37:18.83,EN,,0,0,0,,But it could be a 100 lines of code.\nDialogue: 0,0:37:20.10,0:37:23.67,EN,,0,0,0,,And so, the purpose of this is, of course, to make it simple.\nDialogue: 0,0:37:23.67,0:37:24.57,EN,,0,0,0,,I'd give a name to it,\nDialogue: 0,0:37:24.73,0:37:26.94,EN,,0,0,0,,it's just that here it's a parameterized name.\nDialogue: 0,0:37:28.20,0:37:30.27,EN,,0,0,0,,It's a name that depends upon, explicitly,\nDialogue: 0,0:37:30.49,0:37:33.63,EN,,0,0,0,,the lexically apparent value of n.\nDialogue: 0,0:37:37.13,0:37:38.59,EN,,0,0,0,,So you can think of this as a long name.\nDialogue: 0,0:37:40.21,0:37:41.58,EN,,0,0,0,,And here, I've solved my problem\nDialogue: 0,0:37:41.76,0:37:45.82,EN,,0,0,0,,by naming my... by naming the term generation\nDialogue: 0,0:37:46.12,0:37:49.22,EN,,0,0,0,,procedures within an n in them.\nDialogue: 0,0:37:55.08,0:37:55.87,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:37:57.00,0:37:58.38,EN,,0,0,0,,Oh, yes, David.\nDialogue: 0,0:37:58.57,0:38:02.27,EN,,0,0,0,,AUDIENCE: Is the only solution to um...\nDialogue: 0,0:38:03.07,0:38:06.46,EN,,0,0,0,,the problem you raise to create another procedure?\nDialogue: 0,0:38:06.47,0:38:08.92,EN,,0,0,0,,In other words, can this only work in languages that are\nDialogue: 0,0:38:08.99,0:38:11.56,EN,,0,0,0,,capable of defining objects as procedures?\nDialogue: 0,0:38:12.41,0:38:13.76,EN,,0,0,0,,PROFESSOR: Oh, I see.\nDialogue: 0,0:38:15.90,0:38:19.74,EN,,0,0,0,,My solution to making this abstraction,\nDialogue: 0,0:38:20.14,0:38:22.86,EN,,0,0,0,,when I didn't want include the procedure inside the body,\nDialogue: 0,0:38:23.26,0:38:26.81,EN,,0,0,0,,depends upon my ability to return a procedure or export one.\nDialogue: 0,0:38:27.04,0:38:27.24,EN,,0,0,0,,AUDIENCE: And that's right.\nDialogue: 0,0:38:28.19,0:38:28.88,EN,,0,0,0,,PROFESSOR: And that's right.\nDialogue: 0,0:38:29.53,0:38:31.52,EN,,0,0,0,,If I don't have that,\nDialogue: 0,0:38:32.24,0:38:35.13,EN,,0,0,0,,then I just don't have this ability to make an abstraction in a way\nDialogue: 0,0:38:35.53,0:38:41.77,EN,,0,0,0,,where I don't have possibilities of symbol conflicts that were unanticipated.\nDialogue: 0,0:38:43.00,0:38:43.48,EN,,0,0,0,,That's right.\nDialogue: 0,0:38:44.14,0:38:46.51,EN,,0,0,0,,So one of the, the essential -- I consider, I consider\nDialogue: 0,0:38:46.54,0:38:48.91,EN,,0,0,0,,being able to return the procedural value and, therefore,\nDialogue: 0,0:38:49.20,0:38:58.28,EN,,0,0,0,,and therefore, to sort of have first class procedures, in general,\nDialogue: 0,0:38:59.13,0:39:02.46,EN,,0,0,0,,as being essential to doing very good modular programming.\nDialogue: 0,0:39:03.70,0:39:06.43,EN,,0,0,0,,Now, indeed there are many other ways to skin this cat.\nDialogue: 0,0:39:07.44,0:39:09.16,EN,,0,0,0,,What you can do is take for each of the\nDialogue: 0,0:39:09.18,0:39:11.84,EN,,0,0,0,,for each of the bad things that you have to worry about,\nDialogue: 0,0:39:12.27,0:39:15.20,EN,,0,0,0,,you can make a special feature that covers that thing.\nDialogue: 0,0:39:15.84,0:39:17.12,EN,,0,0,0,,You can make a package system.\nDialogue: 0,0:39:17.74,0:39:21.16,EN,,0,0,0,,You can make a module system as in Ada, et cetera. OK?\nDialogue: 0,0:39:22.24,0:39:24.88,EN,,0,0,0,,And all of those work, or they cover little regions of it.\nDialogue: 0,0:39:26.44,0:39:28.38,EN,,0,0,0,,The thing is that returning procedures as values\nDialogue: 0,0:39:28.41,0:39:29.74,EN,,0,0,0,,cover all of those problems.\nDialogue: 0,0:39:32.68,0:39:34.60,EN,,0,0,0,,And so it's the simplest mechanism\nDialogue: 0,0:39:35.58,0:39:37.79,EN,,0,0,0,,that gives you the best modularity,\nDialogue: 0,0:39:39.21,0:39:41.31,EN,,0,0,0,,gives you all of the known modularity mechanisms.\nDialogue: 0,0:39:45.59,0:39:48.24,EN,,0,0,0,,Well, I suppose it's time for the next break, thank you.\nDialogue: 0,0:39:48.24,0:40:01.08,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:40:01.28,0:40:04.75,EN,,0,0,0,,\nDialogue: 0,0:40:25.69,0:40:29.42,EN,,0,0,0,,\nDialogue: 0,0:40:30.01,0:40:33.28,EN,,0,0,0,,\nDialogue: 0,0:40:34.17,0:40:37.61,EN,,0,0,0,,\nDialogue: 0,0:40:42.32,0:40:44.28,EN,,0,0,0,,PROFESSOR: Well, yesterday when you learned about streams,\nDialogue: 0,0:40:46.01,0:40:51.16,EN,,0,0,0,,Hal worried to you about the order of evaluation\nDialogue: 0,0:40:51.95,0:40:53.87,EN,,0,0,0,,and delayed arguments to procedures.\nDialogue: 0,0:40:55.61,0:40:58.30,EN,,0,0,0,,The way we played with streams yesterday,\nDialogue: 0,0:41:00.25,0:41:04.22,EN,,0,0,0,,it was the responsibility of the caller and the callee\nDialogue: 0,0:41:05.77,0:41:08.84,EN,,0,0,0,,both agree that an argument was delayed,\nDialogue: 0,0:41:09.42,0:41:13.44,EN,,0,0,0,,and the callee must force the argument if it needs the answer.\nDialogue: 0,0:41:15.13,0:41:17.87,EN,,0,0,0,,So there had to be a lot of hand shaking between\nDialogue: 0,0:41:18.17,0:41:24.32,EN,,0,0,0,,the designer of a procedure and user of it over delayedness.\nDialogue: 0,0:41:26.36,0:41:28.72,EN,,0,0,0,,That turns out, of course, to be a fairly bad thing,\nDialogue: 0,0:41:29.48,0:41:30.96,EN,,0,0,0,,it works all right with streams.\nDialogue: 0,0:41:31.74,0:41:32.86,EN,,0,0,0,,But as a general thing,\nDialogue: 0,0:41:32.92,0:41:36.32,EN,,0,0,0,,what you want is an idea to have a locus,\nDialogue: 0,0:41:36.46,0:41:38.49,EN,,0,0,0,,a decision, a design decision in general,\nDialogue: 0,0:41:38.89,0:41:41.28,EN,,0,0,0,,to have a place where it's made, explicitly,\nDialogue: 0,0:41:41.63,0:41:43.93,EN,,0,0,0,,and notated in a clear way.\nDialogue: 0,0:41:45.88,0:41:49.28,EN,,0,0,0,,And so it's not a very good idea to have to have an agreement,\nDialogue: 0,0:41:50.46,0:41:54.89,EN,,0,0,0,,between the person who writes a procedure and the person who calls it,\nDialogue: 0,0:41:55.08,0:41:57.98,EN,,0,0,0,,about such details as, maybe, the arguments of evaluation,\nDialogue: 0,0:41:58.43,0:41:59.50,EN,,0,0,0,,the order of evaluation.\nDialogue: 0,0:41:59.50,0:42:00.75,EN,,0,0,0,,Although, that's not so bad.\nDialogue: 0,0:42:01.02,0:42:03.95,EN,,0,0,0,,I mean, we have other such agreements like, the input's a number.\nDialogue: 0,0:42:05.20,0:42:06.08,EN,,0,0,0,,But it would be nice if\nDialogue: 0,0:42:06.35,0:42:09.20,EN,,0,0,0,,one of these guys could take responsibility, completely.\nDialogue: 0,0:42:11.02,0:42:13.31,EN,,0,0,0,,Now this is not a new idea.\nDialogue: 0,0:42:15.51,0:42:21.16,EN,,0,0,0,,ALGOL 60 had two different ways of calling a procedure.\nDialogue: 0,0:42:22.02,0:42:24.28,EN,,0,0,0,,The arguments could be passed by name or by value.\nDialogue: 0,0:42:25.59,0:42:27.48,EN,,0,0,0,,And what that meant was that\nDialogue: 0,0:42:27.63,0:42:29.72,EN,,0,0,0,,a name argument was delayed.\nDialogue: 0,0:42:31.11,0:42:32.84,EN,,0,0,0,,That when you passed an argument by name,\nDialogue: 0,0:42:33.64,0:42:36.52,EN,,0,0,0,,that its value would only be obtained\nDialogue: 0,0:42:36.96,0:42:39.55,EN,,0,0,0,,if you accessed that argument.\nDialogue: 0,0:42:42.29,0:42:44.20,EN,,0,0,0,,So what I'd like to do now is show you,\nDialogue: 0,0:42:44.43,0:42:46.96,EN,,0,0,0,,first of all, a little bit about, again,\nDialogue: 0,0:42:46.99,0:42:48.65,EN,,0,0,0,,we're going to make a modification to a language.\nDialogue: 0,0:42:50.32,0:42:51.79,EN,,0,0,0,,In this case, we're going to add a feature.\nDialogue: 0,0:42:53.37,0:42:55.05,EN,,0,0,0,,We're going to add the feature of,\nDialogue: 0,0:42:55.36,0:42:58.73,EN,,0,0,0,,by name parameters, if you will, or delayed parameters.\nDialogue: 0,0:43:00.43,0:43:04.41,EN,,0,0,0,,Because, in fact, the default in our Lisp system\nDialogue: 0,0:43:04.76,0:43:06.60,EN,,0,0,0,,is by the value of a pointer.\nDialogue: 0,0:43:08.22,0:43:09.15,EN,,0,0,0,,A pointer is copied,\nDialogue: 0,0:43:09.15,0:43:10.91,EN,,0,0,0,,but the data structure it points at is not.\nDialogue: 0,0:43:13.41,0:43:14.84,EN,,0,0,0,,But I'd like to, in fact, show you\nDialogue: 0,0:43:15.04,0:43:18.38,EN,,0,0,0,,is how you add name arguments as well.\nDialogue: 0,0:43:19.99,0:43:22.12,EN,,0,0,0,,Now again, why would we need such a thing?\nDialogue: 0,0:43:23.10,0:43:24.72,EN,,0,0,0,,Well supposing we wanted to invent\nDialogue: 0,0:43:25.24,0:43:28.44,EN,,0,0,0,,certain kinds of what otherwise would be special forms,\nDialogue: 0,0:43:28.73,0:43:29.72,EN,,0,0,0,,reserve words?\nDialogue: 0,0:43:29.72,0:43:31.48,EN,,0,0,0,,But I'd rather not take up reserve words.\nDialogue: 0,0:43:32.18,0:43:34.76,EN,,0,0,0,,I want procedures that can do things like if.\nDialogue: 0,0:43:36.36,0:43:39.42,EN,,0,0,0,,If is special, or cond, or whatever it is.\nDialogue: 0,0:43:39.42,0:43:40.43,EN,,0,0,0,,It's the same thing.\nDialogue: 0,0:43:40.59,0:43:42.86,EN,,0,0,0,,It's special in that it determines whether or not\nDialogue: 0,0:43:42.92,0:43:45.02,EN,,0,0,0,,to evaluate the consequent or the alternative\nDialogue: 0,0:43:46.22,0:43:49.76,EN,,0,0,0,,based on the value of the predicate part of an expression.\nDialogue: 0,0:43:50.84,0:43:53.12,EN,,0,0,0,,So taking the value of one thing\nDialogue: 0,0:43:53.44,0:43:55.36,EN,,0,0,0,,determines whether or not to do something else.\nDialogue: 0,0:43:57.27,0:43:58.88,EN,,0,0,0,,Whereas all the procedures like plus,\nDialogue: 0,0:43:59.15,0:44:01.20,EN,,0,0,0,,evaluate... the ones that we can define right now,\nDialogue: 0,0:44:01.42,0:44:06.56,EN,,0,0,0,,evaluate all of their arguments before application.\nDialogue: 0,0:44:08.67,0:44:09.64,EN,,0,0,0,,So, for example,\nDialogue: 0,0:44:10.46,0:44:12.41,EN,,0,0,0,,supposing I wish to be able to define something like\nDialogue: 0,0:44:15.39,0:44:18.75,EN,,0,0,0,,the reverse of if in terms of if.\nDialogue: 0,0:44:19.85,0:44:20.70,EN,,0,0,0,,Call it unless.\nDialogue: 0,0:44:24.89,0:44:27.47,EN,,0,0,0,,We've a predicate, a consequent, and an alternative.\nDialogue: 0,0:44:28.67,0:44:30.44,EN,,0,0,0,,Now what I would like to sort of be able to do is\nDialogue: 0,0:44:30.46,0:44:32.08,EN,,0,0,0,,say-- oh, I'll do it in terms of cond.\nDialogue: 0,0:44:32.64,0:44:36.72,EN,,0,0,0,,Cond, if not the predicate,\nDialogue: 0,0:44:38.96,0:44:40.32,EN,,0,0,0,,then take the consequent,\nDialogue: 0,0:44:41.58,0:44:45.63,EN,,0,0,0,,otherwise, take the alternative.\nDialogue: 0,0:44:51.29,0:44:52.76,EN,,0,0,0,,Now, what I'd like this to mean,\nDialogue: 0,0:44:53.32,0:44:55.40,EN,,0,0,0,,is supposing I do something like this.\nDialogue: 0,0:44:56.92,0:45:04.12,EN,,0,0,0,,I'd like this unless say if equals one, 0,\nDialogue: 0,0:45:05.08,0:45:06.64,EN,,0,0,0,,then the answer is two,\nDialogue: 0,0:45:07.90,0:45:11.35,EN,,0,0,0,,otherwise, the quotient of one and 0.\nDialogue: 0,0:45:15.92,0:45:18.91,EN,,0,0,0,,What I'd like that to mean is the result of substituting\nDialogue: 0,0:45:20.00,0:45:23.26,EN,,0,0,0,,equal one, 0, and the quotient of one, 0\nDialogue: 0,0:45:23.66,0:45:24.76,EN,,0,0,0,,for p, c, and a.\nDialogue: 0,0:45:25.58,0:45:27.58,EN,,0,0,0,,I'd like that to mean, and this is funny,\nDialogue: 0,0:45:28.11,0:45:30.33,EN,,0,0,0,,I'd like it to transform into or mean\nDialogue: 0,0:45:30.75,0:45:38.44,EN,,0,0,0,,cond not equal one, 0,\nDialogue: 0,0:45:40.62,0:45:42.54,EN,,0,0,0,,then the result is two,\nDialogue: 0,0:45:44.28,0:45:45.10,EN,,0,0,0,,otherwise\nDialogue: 0,0:45:48.22,0:45:51.16,EN,,0,0,0,,I want it to be the quotient one and 0.\nDialogue: 0,0:45:54.48,0:45:56.48,EN,,0,0,0,,Now, you know that if I were to type this into Lisp,\nDialogue: 0,0:45:57.74,0:45:58.59,EN,,0,0,0,,I'd get a two.\nDialogue: 0,0:45:59.97,0:46:01.32,EN,,0,0,0,,There's no problem with that.\nDialogue: 0,0:46:02.91,0:46:04.64,EN,,0,0,0,,However, if I were to type this into Lisp,\nDialogue: 0,0:46:05.28,0:46:07.79,EN,,0,0,0,,because all the arguments are evaluated before I start,\nDialogue: 0,0:46:09.12,0:46:10.73,EN,,0,0,0,,then I'm going to get an error out of this.\nDialogue: 0,0:46:13.38,0:46:15.61,EN,,0,0,0,,So that if the substitutions work at all, of course,\nDialogue: 0,0:46:16.03,0:46:16.88,EN,,0,0,0,,I would get the right answer.\nDialogue: 0,0:46:16.88,0:46:20.16,EN,,0,0,0,,But here's a case where the substitutions don't work.\nDialogue: 0,0:46:22.17,0:46:23.86,EN,,0,0,0,,I don't get the wrong answer.\nDialogue: 0,0:46:23.86,0:46:24.67,EN,,0,0,0,,I get no answer.\nDialogue: 0,0:46:24.80,0:46:25.60,EN,,0,0,0,,I get an error.\nDialogue: 0,0:46:28.42,0:46:31.21,EN,,0,0,0,,Now, however, I'd like to be able to make my definition\nDialogue: 0,0:46:31.61,0:46:32.99,EN,,0,0,0,,so that this kind of thing works.\nDialogue: 0,0:46:34.48,0:46:36.51,EN,,0,0,0,,What I want to do is say something special\nDialogue: 0,0:46:36.70,0:46:38.76,EN,,0,0,0,,about c and a.\nDialogue: 0,0:46:39.93,0:46:43.15,EN,,0,0,0,,I want them to be delayed automatically.\nDialogue: 0,0:46:44.27,0:46:48.08,EN,,0,0,0,,I don't want them to be, I don't want them to be evaluated\nDialogue: 0,0:46:48.52,0:46:49.74,EN,,0,0,0,,at the time I call.\nDialogue: 0,0:46:51.52,0:46:52.72,EN,,0,0,0,,So I'm going to make a declaration,\nDialogue: 0,0:46:52.75,0:46:55.32,EN,,0,0,0,,and then I'm going to see how to implement such a declaration.\nDialogue: 0,0:46:55.60,0:46:57.63,EN,,0,0,0,,But again, I want you to say to yourself,\nDialogue: 0,0:46:57.79,0:47:00.25,EN,,0,0,0,,oh, this is an interesting kluge he's adding in here.\nDialogue: 0,0:47:00.76,0:47:02.16,EN,,0,0,0,,A kluge, you know.\nDialogue: 0,0:47:02.25,0:47:04.72,EN,,0,0,0,,The piles of kluges make a big complicated mess.\nDialogue: 0,0:47:05.75,0:47:09.79,EN,,0,0,0,,And is this going to foul up something else that might occur.\nDialogue: 0,0:47:10.12,0:47:12.70,EN,,0,0,0,,First of all, is it syntactically unambiguous?\nDialogue: 0,0:47:13.86,0:47:15.50,EN,,0,0,0,,Well, it will be syntactically unambiguous\nDialogue: 0,0:47:15.71,0:47:16.91,EN,,0,0,0,,with what we've seen so far.\nDialogue: 0,0:47:17.84,0:47:20.76,EN,,0,0,0,,But what I'm going to do may, in fact, cause trouble.\nDialogue: 0,0:47:21.67,0:47:24.67,EN,,0,0,0,,It may be that the thing I had will conflict with\nDialogue: 0,0:47:25.15,0:47:27.10,EN,,0,0,0,,type declarations I might want to add in the future\nDialogue: 0,0:47:28.19,0:47:31.08,EN,,0,0,0,,for giving some system, some compiler or something,\nDialogue: 0,0:47:31.21,0:47:33.66,EN,,0,0,0,,the ability to optimize given the types are known.\nDialogue: 0,0:47:34.75,0:47:36.97,EN,,0,0,0,,Or it might conflict with other types of declarations\nDialogue: 0,0:47:37.00,0:47:39.71,EN,,0,0,0,,that I might want to make about the formal parameters.\nDialogue: 0,0:47:40.57,0:47:42.56,EN,,0,0,0,,So I'm not making a general mechanism here\nDialogue: 0,0:47:43.77,0:47:45.24,EN,,0,0,0,,where I can add declarations.\nDialogue: 0,0:47:45.28,0:47:46.54,EN,,0,0,0,,And I would like to be able to do that.\nDialogue: 0,0:47:46.89,0:47:48.81,EN,,0,0,0,,But I don't want to talk about that right now.\nDialogue: 0,0:47:51.01,0:47:53.88,EN,,0,0,0,,So here I'm going to do, I'm going to build a kluge.\nDialogue: 0,0:47:57.56,0:48:08.38,EN,,0,0,0,,So we're going to define unless of a predicate--\nDialogue: 0,0:48:08.81,0:48:10.27,EN,,0,0,0,,and I'm going to call these by name--\nDialogue: 0,0:48:12.78,0:48:15.28,EN,,0,0,0,,the consequent, and name the alternative.\nDialogue: 0,0:48:19.85,0:48:25.28,EN,,0,0,0,,Huh, huh-- I got caught in the corner.\nDialogue: 0,0:48:31.76,0:48:35.61,EN,,0,0,0,,If not p then the result is c,\nDialogue: 0,0:48:36.80,0:48:41.16,EN,,0,0,0,,else-- that's what I'd like.\nDialogue: 0,0:48:44.67,0:48:46.88,EN,,0,0,0,,Where I can explicitly declare\nDialogue: 0,0:48:47.55,0:48:51.65,EN,,0,0,0,,certain of the parameters to be delayed, to be computed later.\nDialogue: 0,0:48:55.60,0:48:58.48,EN,,0,0,0,,Now, this is actually a very complicated modification to an interpreter\nDialogue: 0,0:48:58.70,0:48:59.77,EN,,0,0,0,,rather than a simple one.\nDialogue: 0,0:49:00.45,0:49:03.10,EN,,0,0,0,,The ones you saw before, dynamic binding\nDialogue: 0,0:49:03.40,0:49:06.89,EN,,0,0,0,,or adding indefinite argument procedures,\nDialogue: 0,0:49:07.50,0:49:08.52,EN,,0,0,0,,is relatively simple.\nDialogue: 0,0:49:09.28,0:49:11.28,EN,,0,0,0,,But this one changes a basic strategy.\nDialogue: 0,0:49:12.32,0:49:13.39,EN,,0,0,0,,The problem here\nDialogue: 0,0:49:13.96,0:49:17.63,EN,,0,0,0,,is that our interpreter, as written\nDialogue: 0,0:49:17.96,0:49:23.40,EN,,0,0,0,,evaluates a combination by evaluating the procedure,\nDialogue: 0,0:49:24.24,0:49:25.92,EN,,0,0,0,,the operator producing the procedure,\nDialogue: 0,0:49:26.20,0:49:30.35,EN,,0,0,0,,and evaluating the operands producing the arguments,\nDialogue: 0,0:49:30.76,0:49:35.26,EN,,0,0,0,,and then doing apply of the procedure to the arguments.\nDialogue: 0,0:49:36.38,0:49:37.07,EN,,0,0,0,,However, here,\nDialogue: 0,0:49:37.36,0:49:41.48,EN,,0,0,0,,I don't want to evaluate the operands to produce the arguments\nDialogue: 0,0:49:41.74,0:49:43.66,EN,,0,0,0,,until after I examined the procedure\nDialogue: 0,0:49:44.62,0:49:46.86,EN,,0,0,0,,to see what the procedure's declarations look like.\nDialogue: 0,0:49:49.59,0:49:50.59,EN,,0,0,0,,So let's look at that.\nDialogue: 0,0:49:52.68,0:49:56.54,EN,,0,0,0,,Here we have a changed evaluator.\nDialogue: 0,0:49:57.48,0:50:01.15,EN,,0,0,0,,I'm starting with the simple lexical evaluator,\nDialogue: 0,0:50:01.72,0:50:02.65,EN,,0,0,0,,not dynamic\nDialogue: 0,0:50:04.14,0:50:08.20,EN,,0,0,0,,but we're going to have to do something sort of similar in some ways.\nDialogue: 0,0:50:09.75,0:50:11.45,EN,,0,0,0,,Because of the fact that,\nDialogue: 0,0:50:11.90,0:50:13.34,EN,,0,0,0,,if I delay a procedure--\nDialogue: 0,0:50:13.66,0:50:15.15,EN,,0,0,0,,I'm sorry-- delay an argument to a procedure,\nDialogue: 0,0:50:15.40,0:50:17.52,EN,,0,0,0,,I'm going to have to attach and environment to it.\nDialogue: 0,0:50:19.36,0:50:21.55,EN,,0,0,0,,Remember how Hal implemented delay.\nDialogue: 0,0:50:23.38,0:50:25.44,EN,,0,0,0,,Hal implemented delay as being\nDialogue: 0,0:50:25.50,0:50:27.47,EN,,0,0,0,,a procedure of no arguments\nDialogue: 0,0:50:28.56,0:50:30.52,EN,,0,0,0,,which does some expression.\nDialogue: 0,0:50:31.18,0:50:36.94,EN,,0,0,0,,That's what delay of the expression is. --of that expression.\nDialogue: 0,0:50:39.29,0:50:40.99,EN,,0,0,0,,This turned into something like this.\nDialogue: 0,0:50:44.52,0:50:46.92,EN,,0,0,0,,Now, however, if I evaluate a lambda expression,\nDialogue: 0,0:50:47.42,0:50:49.20,EN,,0,0,0,,I have to capture the environment.\nDialogue: 0,0:50:51.41,0:50:53.45,EN,,0,0,0,,The reason why is because there are\nDialogue: 0,0:50:54.60,0:50:56.32,EN,,0,0,0,,there are variables in there\nDialogue: 0,0:50:57.02,0:51:00.83,EN,,0,0,0,,who's meaning I wish to derive from the context where this was written.\nDialogue: 0,0:51:04.01,0:51:05.76,EN,,0,0,0,,So that's why a lambda does the job.\nDialogue: 0,0:51:06.62,0:51:07.50,EN,,0,0,0,,It's the right thing.\nDialogue: 0,0:51:08.07,0:51:15.12,EN,,0,0,0,,And such that the forcing of a delayed expression\nDialogue: 0,0:51:16.52,0:51:20.08,EN,,0,0,0,,was same thing as calling that with no arguments.\nDialogue: 0,0:51:21.09,0:51:22.28,EN,,0,0,0,,It's just the opposite of this.\nDialogue: 0,0:51:24.10,0:51:26.94,EN,,0,0,0,,Producing an environment of the call\nDialogue: 0,0:51:27.36,0:51:29.90,EN,,0,0,0,,which is, in fact, the environment where this was defined\nDialogue: 0,0:51:30.81,0:51:32.36,EN,,0,0,0,,with an extra frame in it that's empty.\nDialogue: 0,0:51:33.23,0:51:34.41,EN,,0,0,0,,I don't care about that.\nDialogue: 0,0:51:36.24,0:51:39.40,EN,,0,0,0,,Well, if we go back to this slide,\nDialogue: 0,0:51:40.99,0:51:43.72,EN,,0,0,0,,since it's the case, if we look at this for a second,\nDialogue: 0,0:51:44.14,0:51:46.12,EN,,0,0,0,,everything is the same as it was before\nDialogue: 0,0:51:46.35,0:51:50.65,EN,,0,0,0,,except the case of applications or combinations.\nDialogue: 0,0:51:51.98,0:51:53.71,EN,,0,0,0,,And combinations are going to do two things.\nDialogue: 0,0:51:54.68,0:51:57.79,EN,,0,0,0,,One, is I have to evaluate the procedure--\nDialogue: 0,0:51:57.92,0:51:59.88,EN,,0,0,0,,I have to get the procedure-- by evaluating the operator.\nDialogue: 0,0:52:00.70,0:52:01.69,EN,,0,0,0,,That's what you see right here.\nDialogue: 0,0:52:02.38,0:52:04.35,EN,,0,0,0,,I have to make sure that that's current,\nDialogue: 0,0:52:04.46,0:52:05.76,EN,,0,0,0,,that is not a delayed object,\nDialogue: 0,0:52:06.36,0:52:09.85,EN,,0,0,0,,and evaluate that to the point where became it's forced now.\nDialogue: 0,0:52:10.73,0:52:12.08,EN,,0,0,0,,And then I have to somehow\nDialogue: 0,0:52:12.24,0:52:17.32,EN,,0,0,0,,apply that to the, to the operands.\nDialogue: 0,0:52:18.03,0:52:19.61,EN,,0,0,0,,But I have to keep the environment,\nDialogue: 0,0:52:19.63,0:52:20.92,EN,,0,0,0,,pass that environmental along.\nDialogue: 0,0:52:21.53,0:52:23.71,EN,,0,0,0,,So some of those operands I may have to delay.\nDialogue: 0,0:52:23.71,0:52:27.53,EN,,0,0,0,,I may have to attach that environment to those operands.\nDialogue: 0,0:52:29.66,0:52:31.52,EN,,0,0,0,,This is a rather complicated thing happening here.\nDialogue: 0,0:52:32.99,0:52:34.24,EN,,0,0,0,,Looking at that in apply.\nDialogue: 0,0:52:36.40,0:52:38.72,EN,,0,0,0,,Apply, well it has a primitive procedure\nDialogue: 0,0:52:39.36,0:52:40.60,EN,,0,0,0,,thing just like before.\nDialogue: 0,0:52:42.61,0:52:44.68,EN,,0,0,0,,But the compound one is a little more interesting.\nDialogue: 0,0:52:47.25,0:52:49.52,EN,,0,0,0,,I have to evaluate the body, just as before,\nDialogue: 0,0:52:50.48,0:52:51.98,EN,,0,0,0,,in an environment which is\nDialogue: 0,0:52:52.28,0:52:54.97,EN,,0,0,0,,which is the result of binding some\nDialogue: 0,0:52:55.61,0:53:00.29,EN,,0,0,0,,formal parameters to arguments in the environment.\nDialogue: 0,0:53:00.29,0:53:01.07,EN,,0,0,0,,That's true.\nDialogue: 0,0:53:01.53,0:53:03.82,EN,,0,0,0,,The environment is the one that comes from the procedure now.\nDialogue: 0,0:53:03.82,0:53:06.65,EN,,0,0,0,,It's a lexical language, statically bound.\nDialogue: 0,0:53:08.04,0:53:11.82,EN,,0,0,0,,However, one thing I have to do is strip off the declarations\nDialogue: 0,0:53:11.84,0:53:12.84,EN,,0,0,0,,to get the names of the variables.\nDialogue: 0,0:53:12.84,0:53:15.20,EN,,0,0,0,,That's what this guy does, vnames.\nDialogue: 0,0:53:15.45,0:53:16.67,EN,,0,0,0,,And the other thing I have to do\nDialogue: 0,0:53:16.97,0:53:18.86,EN,,0,0,0,,is process these declarations,\nDialogue: 0,0:53:19.13,0:53:21.52,EN,,0,0,0,,deciding which of these operands--\nDialogue: 0,0:53:21.76,0:53:23.92,EN,,0,0,0,,that's the operands now, as opposed to the arguments--\nDialogue: 0,0:53:24.09,0:53:25.87,EN,,0,0,0,,which of these operands to evaluate,\nDialogue: 0,0:53:26.62,0:53:30.20,EN,,0,0,0,,and which of them are to be\nDialogue: 0,0:53:30.99,0:53:33.77,EN,,0,0,0,,encapsulated in delays of some sort.\nDialogue: 0,0:53:37.28,0:53:40.08,EN,,0,0,0,,The other thing you see here is that we got a primitive,\nDialogue: 0,0:53:40.60,0:53:42.38,EN,,0,0,0,,a primitive like plus,\nDialogue: 0,0:53:42.68,0:53:45.58,EN,,0,0,0,,had better get at the real operands.\nDialogue: 0,0:53:45.82,0:53:47.39,EN,,0,0,0,,So here is a place where we're going to have to force them.\nDialogue: 0,0:53:47.92,0:53:50.38,EN,,0,0,0,,And we're going to look at what evlist is going to have to do a bunch of forces.\nDialogue: 0,0:53:51.34,0:53:52.78,EN,,0,0,0,,So we have two different kinds of evlist now.\nDialogue: 0,0:53:52.78,0:53:54.09,EN,,0,0,0,,We have evlist and gevlist.\nDialogue: 0,0:53:54.52,0:53:57.16,EN,,0,0,0,,Gevlist is going to wrap delays around some things\nDialogue: 0,0:53:57.18,0:53:59.74,EN,,0,0,0,,and force others, evaluate others.\nDialogue: 0,0:53:59.87,0:54:05.85,EN,,0,0,0,,And this guy's going to do some forcing of things.\nDialogue: 0,0:54:07.90,0:54:09.16,EN,,0,0,0,,Just looking at this a little bit,\nDialogue: 0,0:54:09.69,0:54:11.98,EN,,0,0,0,,this is a game you must play for yourself, you know.\nDialogue: 0,0:54:12.25,0:54:14.67,EN,,0,0,0,,It's not something that you're going to see all possible\nDialogue: 0,0:54:14.72,0:54:18.20,EN,,0,0,0,,variations on an evaluator talking to me.\nDialogue: 0,0:54:19.52,0:54:21.24,EN,,0,0,0,,What you have to do is do this for yourself.\nDialogue: 0,0:54:21.37,0:54:23.84,EN,,0,0,0,,And after you feel this, you play this a bit,\nDialogue: 0,0:54:24.22,0:54:27.02,EN,,0,0,0,,you get to see all the possible design decisions and what they might mean,\nDialogue: 0,0:54:27.77,0:54:29.16,EN,,0,0,0,,and how they interact with each other.\nDialogue: 0,0:54:29.93,0:54:32.38,EN,,0,0,0,,So what languages might have in them.\nDialogue: 0,0:54:33.16,0:54:34.64,EN,,0,0,0,,And what are some of the consistent sets\nDialogue: 0,0:54:34.94,0:54:36.32,EN,,0,0,0,,that make a legitimate language.\nDialogue: 0,0:54:37.20,0:54:40.06,EN,,0,0,0,,Whereas what things are complicated kluges that are just piles of junk.\nDialogue: 0,0:54:41.85,0:54:44.68,EN,,0,0,0,,So evlist of course, over here, just as I said,\nDialogue: 0,0:54:44.81,0:54:46.03,EN,,0,0,0,,is a list of operands\nDialogue: 0,0:54:46.70,0:54:50.28,EN,,0,0,0,,which are going to be undelayed after evaluation.\nDialogue: 0,0:54:50.75,0:54:51.90,EN,,0,0,0,,So these are going to be forced,\nDialogue: 0,0:54:53.28,0:54:54.44,EN,,0,0,0,,whatever that's going to mean.\nDialogue: 0,0:54:56.05,0:54:58.51,EN,,0,0,0,,And gevlist, which is the next thing--\nDialogue: 0,0:55:01.26,0:55:01.85,EN,,0,0,0,,Thank you.\nDialogue: 0,0:55:04.04,0:55:06.35,EN,,0,0,0,,What we see here, uh\nDialogue: 0,0:55:07.80,0:55:09.61,EN,,0,0,0,,well there's a couple of possibilities.\nDialogue: 0,0:55:09.81,0:55:11.52,EN,,0,0,0,,Either it's a normal, ordinary thing,\nDialogue: 0,0:55:12.48,0:55:13.69,EN,,0,0,0,,a symbol sitting there\nDialogue: 0,0:55:13.74,0:55:16.20,EN,,0,0,0,,like the predicate in the unless,\nDialogue: 0,0:55:17.64,0:55:18.81,EN,,0,0,0,,and that's what we have here.\nDialogue: 0,0:55:19.39,0:55:22.49,EN,,0,0,0,,In which case, this is intended to be evaluated in applicative order.\nDialogue: 0,0:55:23.34,0:55:25.45,EN,,0,0,0,,And it's, essentially, just what we had before.\nDialogue: 0,0:55:25.63,0:55:28.84,EN,,0,0,0,,It's mapping eval down the list.\nDialogue: 0,0:55:29.95,0:55:32.14,EN,,0,0,0,,In other words, I evaluate the first expression\nDialogue: 0,0:55:32.65,0:55:37.36,EN,,0,0,0,,and continue gevlisting the CDR of the expression in the environment.\nDialogue: 0,0:55:37.93,0:55:43.20,EN,,0,0,0,,However, it's possible that this is a name parameter.\nDialogue: 0,0:55:44.00,0:55:45.05,EN,,0,0,0,,If it's a name parameter,\nDialogue: 0,0:55:45.20,0:55:46.59,EN,,0,0,0,,I want to put a delay in\nDialogue: 0,0:55:47.00,0:55:50.97,EN,,0,0,0,,which combines that expression, which I'm calling by name,\nDialogue: 0,0:55:52.14,0:55:57.74,EN,,0,0,0,,with the environment that's available at this time\nDialogue: 0,0:55:59.05,0:56:00.59,EN,,0,0,0,,and passing that as the parameter.\nDialogue: 0,0:56:02.79,0:56:05.04,EN,,0,0,0,,And this is part of the mapping process that you see here.\nDialogue: 0,0:56:09.07,0:56:11.31,EN,,0,0,0,,The only other interesting place in this procedure\nDialogue: 0,0:56:11.37,0:56:13.53,EN,,0,0,0,,in this interpreter is cond.\nDialogue: 0,0:56:14.70,0:56:15.92,EN,,0,0,0,,People tend to write this thing,\nDialogue: 0,0:56:15.93,0:56:17.24,EN,,0,0,0,,and then they leave this one out.\nDialogue: 0,0:56:18.55,0:56:19.98,EN,,0,0,0,,There's a place where you have to force.\nDialogue: 0,0:56:20.51,0:56:23.10,EN,,0,0,0,,Conditionals have to know\nDialogue: 0,0:56:24.20,0:56:25.90,EN,,0,0,0,,whether or not the answer is true or false.\nDialogue: 0,0:56:25.99,0:56:26.83,EN,,0,0,0,,It's like a primitive.\nDialogue: 0,0:56:28.55,0:56:30.56,EN,,0,0,0,,When you do a conditional, you have to force.\nDialogue: 0,0:56:31.72,0:56:33.95,EN,,0,0,0,,Now, I'm not going to look at any more of this in any detail.\nDialogue: 0,0:56:34.62,0:56:36.28,EN,,0,0,0,,It isn't very exciting.\nDialogue: 0,0:56:36.75,0:56:38.99,EN,,0,0,0,,And what's left is how you make delays.\nDialogue: 0,0:56:38.99,0:56:40.91,EN,,0,0,0,,Well, delays are data structures\nDialogue: 0,0:56:41.31,0:56:44.75,EN,,0,0,0,,which contain an expression, an environment, and a type on them.\nDialogue: 0,0:56:44.84,0:56:46.36,EN,,0,0,0,,And it says they're a thunk.\nDialogue: 0,0:56:46.96,0:56:48.46,EN,,0,0,0,,That comes from ALGOL language,\nDialogue: 0,0:56:49.07,0:56:50.81,EN,,0,0,0,,and it's claimed to be the sound of\nDialogue: 0,0:56:50.83,0:56:52.06,EN,,0,0,0,,of something being pushed on a stack.\nDialogue: 0,0:56:52.97,0:56:53.41,EN,,0,0,0,,I don't know.\nDialogue: 0,0:56:53.41,0:56:57.12,EN,,0,0,0,,I was not an ALGOLician, so or an ALGOLite or whatever,\nDialogue: 0,0:56:57.60,0:56:58.38,EN,,0,0,0,,so I don't know.\nDialogue: 0,0:56:58.74,0:56:59.64,EN,,0,0,0,,But that's what was claimed.\nDialogue: 0,0:57:00.27,0:57:01.56,EN,,0,0,0,,And undelay is something\nDialogue: 0,0:57:01.77,0:57:03.66,EN,,0,0,0,,which will recursively undelay thunks\nDialogue: 0,0:57:03.69,0:57:06.00,EN,,0,0,0,,until the thunk becomes something which isn't a thunk.\nDialogue: 0,0:57:07.72,0:57:10.94,EN,,0,0,0,,This is the way you implement a call by name like thing in ALGOL.\nDialogue: 0,0:57:12.05,0:57:13.76,EN,,0,0,0,,And that's about all there is.\nDialogue: 0,0:57:15.21,0:57:16.25,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:57:26.68,0:57:27.52,EN,,0,0,0,,AUDIENCE: Gerry?\nDialogue: 0,0:57:28.09,0:57:28.80,EN,,0,0,0,,PROFESSOR: Yes, Vesko?\nDialogue: 0,0:57:30.03,0:57:32.99,EN,,0,0,0,,AUDIENCE: I noticed you avoided calling by name\nDialogue: 0,0:57:33.44,0:57:34.89,EN,,0,0,0,,in the primitive procedures,\nDialogue: 0,0:57:36.41,0:57:38.38,EN,,0,0,0,,I was wondering what cause you have on that?\nDialogue: 0,0:57:38.41,0:57:39.21,EN,,0,0,0,,You never need that?\nDialogue: 0,0:57:40.07,0:57:41.61,EN,,0,0,0,,PROFESSOR: Vesko is asking\nDialogue: 0,0:57:42.06,0:57:46.00,EN,,0,0,0,,if it's ever reasonable to call a primitive procedure by name?\nDialogue: 0,0:57:47.14,0:57:48.70,EN,,0,0,0,,The answer is, yes.\nDialogue: 0,0:57:49.27,0:57:52.32,EN,,0,0,0,,There's one particular case where it's reasonable, actually two.\nDialogue: 0,0:57:55.53,0:57:58.27,EN,,0,0,0,,Construction of a data structure like cons\nDialogue: 0,0:57:59.02,0:58:02.00,EN,,0,0,0,,where making an array if you have arrays with any number of elements.\nDialogue: 0,0:58:03.26,0:58:07.44,EN,,0,0,0,,OK? It's unnecessary to evaluate those arguments.\nDialogue: 0,0:58:07.44,0:58:08.83,EN,,0,0,0,,All you need is promises\nDialogue: 0,0:58:09.10,0:58:10.81,EN,,0,0,0,,to evaluate those arguments if you look at them.\nDialogue: 0,0:58:11.50,0:58:15.08,EN,,0,0,0,,If I cons together a, two things,\nDialogue: 0,0:58:16.24,0:58:17.77,EN,,0,0,0,,then I could cons together the promises\nDialogue: 0,0:58:17.80,0:58:19.93,EN,,0,0,0,,just as easily as I can cons together the things.\nDialogue: 0,0:58:21.15,0:58:23.37,EN,,0,0,0,,And it's not even when I CAR CDR them\nDialogue: 0,0:58:23.39,0:58:24.30,EN,,0,0,0,,that I have to look at them.\nDialogue: 0,0:58:24.84,0:58:26.97,EN,,0,0,0,,That just gets out the promises and passes them to somebody.\nDialogue: 0,0:58:28.26,0:58:30.51,EN,,0,0,0,,That's why the lambda calculus definition, the\nDialogue: 0,0:58:30.57,0:58:34.03,EN,,0,0,0,,the Alonzo Church definition of CAR, CDR, and cons makes sense.\nDialogue: 0,0:58:34.42,0:58:36.32,EN,,0,0,0,,It's because no work is done in CAR, CDR, and cons,\nDialogue: 0,0:58:36.38,0:58:40.06,EN,,0,0,0,,it's just shuffling data, it's just routing, if you will.\nDialogue: 0,0:58:40.99,0:58:42.20,EN,,0,0,0,,However, the things that do have\nDialogue: 0,0:58:42.24,0:58:43.84,EN,,0,0,0,,to look at data are things like plus.\nDialogue: 0,0:58:45.28,0:58:46.91,EN,,0,0,0,,Because they have a look at the bits\nDialogue: 0,0:58:47.12,0:58:48.30,EN,,0,0,0,,that the numbers are made out of,\nDialogue: 0,0:58:48.32,0:58:50.44,EN,,0,0,0,,unless they're lambda calculus numbers\nDialogue: 0,0:58:50.44,0:58:51.88,EN,,0,0,0,,which are funny. OK?\nDialogue: 0,0:58:52.43,0:58:53.58,EN,,0,0,0,,They have to look at the bits to\nDialogue: 0,0:58:53.77,0:58:55.53,EN,,0,0,0,,be able to crunch them together to do the add.\nDialogue: 0,0:58:59.21,0:58:59.92,EN,,0,0,0,,So, in fact,\nDialogue: 0,0:59:00.19,0:59:02.78,EN,,0,0,0,,data constructors, data selectors,\nDialogue: 0,0:59:03.24,0:59:05.50,EN,,0,0,0,,in fact, things that side-effect data objects\nDialogue: 0,0:59:06.27,0:59:09.76,EN,,0,0,0,,don't need to do, don't need to do any forcing\nDialogue: 0,0:59:11.34,0:59:13.39,EN,,0,0,0,,in the laziest possible interpreters.\nDialogue: 0,0:59:16.46,0:59:16.99,EN,,0,0,0,,On the other hand\nDialogue: 0,0:59:17.02,0:59:18.70,EN,,0,0,0,,predicates on data structures have to.\nDialogue: 0,0:59:19.61,0:59:22.65,EN,,0,0,0,,If you want to say, is this a, is this a pair?\nDialogue: 0,0:59:23.56,0:59:24.40,EN,,0,0,0,,Or is it a symbol?\nDialogue: 0,0:59:24.64,0:59:26.57,EN,,0,0,0,,Well, you better find out. You got to look at it then.\nDialogue: 0,0:59:30.30,0:59:31.18,EN,,0,0,0,,Any other questions?\nDialogue: 0,0:59:40.05,0:59:41.61,EN,,0,0,0,,Oh, well, I suppose it's time for a break.\n"
  },
  {
    "path": "Ass/lec8a.chn+eng.ass",
    "content": "[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 3\nVideo Position: 790\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:18.27,0:00:19.68,EN,,0,0,0,,PROFESSOR: The last time we began having a look\nDialogue: 0,0:00:19.72,0:00:21.26,EN,,0,0,0,,at how languages are constructed.\nDialogue: 0,0:00:22.41,0:00:25.88,EN,,0,0,0,,Remember the main point that an evaluator for, LISP, say,\nDialogue: 0,0:00:26.08,0:00:27.58,EN,,0,0,0,,has two main elements.\nDialogue: 0,0:00:27.58,0:00:28.40,EN,,0,0,0,,There is EVAL,\nDialogue: 0,0:00:31.04,0:00:37.42,EN,,0,0,0,,and EVAL's job is to take in an expression and an environment\nDialogue: 0,0:00:38.91,0:00:44.44,EN,,0,0,0,,and turn that into a procedure and some arguments\nDialogue: 0,0:00:45.42,0:00:47.05,EN,,0,0,0,,and pass that off to APPLY.\nDialogue: 0,0:00:49.41,0:00:51.29,EN,,0,0,0,,And APPLY takes the procedure in the arguments,\nDialogue: 0,0:00:51.69,0:00:55.12,EN,,0,0,0,,turns that back into, in a general case, another expression\nDialogue: 0,0:00:55.39,0:00:57.71,EN,,0,0,0,,to be evaluated in another environment\nDialogue: 0,0:00:57.74,0:01:00.00,EN,,0,0,0,,and passes that off to EVAL, which passes it to APPLY,\nDialogue: 0,0:01:00.27,0:01:01.44,EN,,0,0,0,,and there's this whole big circle\nDialogue: 0,0:01:01.47,0:01:02.94,EN,,0,0,0,,where things go around and around and around\nDialogue: 0,0:01:03.02,0:01:06.56,EN,,0,0,0,,until you get either to some very primitive data or to a primitive procedure.\nDialogue: 0,0:01:07.74,0:01:09.24,EN,,0,0,0,,See, what this cycle has to do with\nDialogue: 0,0:01:09.44,0:01:12.57,EN,,0,0,0,,is unwinding the means of combination\nDialogue: 0,0:01:12.59,0:01:14.36,EN,,0,0,0,,and the means of abstraction in the language.\nDialogue: 0,0:01:15.02,0:01:17.72,EN,,0,0,0,,So for instance, you have a procedure in LISP--\nDialogue: 0,0:01:17.74,0:01:20.52,EN,,0,0,0,,a procedure is a general way of saying,\nDialogue: 0,0:01:20.54,0:01:22.57,EN,,0,0,0,,I want to be able to evaluate this expression\nDialogue: 0,0:01:22.67,0:01:24.41,EN,,0,0,0,,for any value of the arguments,\nDialogue: 0,0:01:25.76,0:01:27.18,EN,,0,0,0,,and that's sort of what's going on here.\nDialogue: 0,0:01:27.67,0:01:28.51,EN,,0,0,0,,That's what APPLY does.\nDialogue: 0,0:01:28.51,0:01:30.68,EN,,0,0,0,,It says the general thing coming in with the arguments\nDialogue: 0,0:01:30.72,0:01:32.70,EN,,0,0,0,,reduces to the expression that's the body,\nDialogue: 0,0:01:33.05,0:01:34.72,EN,,0,0,0,,and then if that's a compound expression\nDialogue: 0,0:01:34.83,0:01:36.46,EN,,0,0,0,,or another procedure application,\nDialogue: 0,0:01:36.78,0:01:38.44,EN,,0,0,0,,the thing will go around and around the circle.\nDialogue: 0,0:01:40.33,0:01:44.08,EN,,0,0,0,,Anyway, that's sort of the basic structure of gee, pretty much any interpreter.\nDialogue: 0,0:01:45.20,0:01:46.25,EN,,0,0,0,,The other thing that you saw\nDialogue: 0,0:01:46.28,0:01:47.66,EN,,0,0,0,,once you have the interpreter in your hands,\nDialogue: 0,0:01:47.69,0:01:49.87,EN,,0,0,0,,you have all this power to start playing with the language.\nDialogue: 0,0:01:49.87,0:01:51.52,EN,,0,0,0,,So you can make it dynamically scoped,\nDialogue: 0,0:01:51.84,0:01:54.56,EN,,0,0,0,,or you can put in normal order evaluation,\nDialogue: 0,0:01:54.59,0:01:56.48,EN,,0,0,0,,or you can add new forms to the language,\nDialogue: 0,0:01:56.86,0:01:57.50,EN,,0,0,0,,whatever you like.\nDialogue: 0,0:01:57.58,0:01:58.62,EN,,0,0,0,,Or more generally,\nDialogue: 0,0:01:58.76,0:02:01.32,EN,,0,0,0,,there's this notion of metalinguistic abstraction,\nDialogue: 0,0:02:02.64,0:02:06.01,EN,,0,0,0,,which says that part of your perspective\nDialogue: 0,0:02:07.61,0:02:10.52,EN,,0,0,0,,as an engineer, as a software engineer, but as an engineer in general\nDialogue: 0,0:02:11.39,0:02:13.88,EN,,0,0,0,,is that you can gain control of complexity\nDialogue: 0,0:02:14.96,0:02:17.16,EN,,0,0,0,,by inventing new languages sometimes.\nDialogue: 0,0:02:18.01,0:02:20.81,EN,,0,0,0,,See, one way to think about computer programming\nDialogue: 0,0:02:21.55,0:02:26.27,EN,,0,0,0,,is that it only incidentally has to do with getting a computer to do something.\nDialogue: 0,0:02:26.44,0:02:28.97,EN,,0,0,0,,Primarily what a computer program has to do with,\nDialogue: 0,0:02:29.00,0:02:32.52,EN,,0,0,0,,it's a way of expressing ideas with communicating ideas.\nDialogue: 0,0:02:33.16,0:02:34.04,EN,,0,0,0,,And sometimes\nDialogue: 0,0:02:34.89,0:02:36.62,EN,,0,0,0,,when you want to communicate new kinds of ideas,\nDialogue: 0,0:02:36.65,0:02:38.73,EN,,0,0,0,,you'd like to invent new modes of expressing that.\nDialogue: 0,0:02:39.82,0:02:44.99,EN,,0,0,0,,Well, today we're going to apply this framework to build a new language.\nDialogue: 0,0:02:45.73,0:02:48.00,EN,,0,0,0,,See, once we have the basic idea of the interpreter,\nDialogue: 0,0:02:48.03,0:02:50.27,EN,,0,0,0,,you can pretty much go build any language that you like.\nDialogue: 0,0:02:50.83,0:02:53.21,EN,,0,0,0,,So for example, we can go off and build Pascal.\nDialogue: 0,0:02:54.37,0:02:55.15,EN,,0,0,0,,And...\nDialogue: 0,0:02:56.17,0:02:58.19,EN,,0,0,0,,gee, we would worry about syntax and parsing\nDialogue: 0,0:02:58.19,0:03:00.51,EN,,0,0,0,,and various kinds of compiler optimizations,\nDialogue: 0,0:03:01.12,0:03:03.29,EN,,0,0,0,,and there are people who make honest livings doing that,\nDialogue: 0,0:03:03.85,0:03:07.60,EN,,0,0,0,,but at the level of abstraction that we're talking,\nDialogue: 0,0:03:08.04,0:03:10.99,EN,,0,0,0,,a Pascal interpreter would not look very different at all\nDialogue: 0,0:03:12.03,0:03:13.76,EN,,0,0,0,,from what you saw Gerry do last time.\nDialogue: 0,0:03:15.02,0:03:18.96,EN,,0,0,0,,Instead of that, we'll spend today building a really different language,\nDialogue: 0,0:03:20.51,0:03:22.81,EN,,0,0,0,,a language that encourages you\nDialogue: 0,0:03:23.05,0:03:26.04,EN,,0,0,0,,to think about programming not in terms of procedures,\nDialogue: 0,0:03:26.24,0:03:27.64,EN,,0,0,0,,but in a really different way.\nDialogue: 0,0:03:29.09,0:03:31.02,EN,,0,0,0,,And the lecture today is\nDialogue: 0,0:03:31.74,0:03:34.64,EN,,0,0,0,,going to be at two levels simultaneously.\nDialogue: 0,0:03:34.81,0:03:35.52,EN,,0,0,0,,On the one hand,\nDialogue: 0,0:03:35.90,0:03:37.71,EN,,0,0,0,,I'm going to show you what this language looks like,\nDialogue: 0,0:03:38.96,0:03:41.08,EN,,0,0,0,,and on the other hand, I'll show you how it's implemented.\nDialogue: 0,0:03:41.32,0:03:42.96,EN,,0,0,0,,And we'll build an implementation in LISP\nDialogue: 0,0:03:42.99,0:03:43.90,EN,,0,0,0,,and see how that works.\nDialogue: 0,0:03:44.04,0:03:48.25,EN,,0,0,0,,And you should be drawing lessons on two levels.\nDialogue: 0,0:03:48.68,0:03:53.00,EN,,0,0,0,,The first is to realize just how different a language can be.\nDialogue: 0,0:03:53.79,0:03:58.14,EN,,0,0,0,,So if you think that the jump from Fortran to LISP is a big deal,\nDialogue: 0,0:03:58.24,0:03:59.36,EN,,0,0,0,,you haven't seen anything yet.\nDialogue: 0,0:04:01.56,0:04:03.68,EN,,0,0,0,,And secondly,\nDialogue: 0,0:04:03.77,0:04:06.54,EN,,0,0,0,,you'll see that even with such a very different language,\nDialogue: 0,0:04:07.36,0:04:09.52,EN,,0,0,0,,which will turn out to not have procedures at all\nDialogue: 0,0:04:09.92,0:04:11.64,EN,,0,0,0,,and not talk about functions at all,\nDialogue: 0,0:04:12.20,0:04:15.72,EN,,0,0,0,,there will still be this basic cycle of eval and apply\nDialogue: 0,0:04:16.19,0:04:19.98,EN,,0,0,0,,that's unwinds the means of combination and the means an abstraction.\nDialogue: 0,0:04:20.95,0:04:24.68,EN,,0,0,0,,And then thirdly, as kind of a minor but elegant technical point,\nDialogue: 0,0:04:24.89,0:04:28.52,EN,,0,0,0,,you'll see a nice use of streams to avoid backtracking.\nDialogue: 0,0:04:32.33,0:04:34.40,EN,,0,0,0,,OK, well, I said that this language is very different.\nDialogue: 0,0:04:35.86,0:04:36.64,EN,,0,0,0,,To explain that,\nDialogue: 0,0:04:37.05,0:04:42.81,EN,,0,0,0,,let's go back to the very first idea that we talked about in this course,\nDialogue: 0,0:04:43.26,0:04:46.54,EN,,0,0,0,,and that was the idea of the distinction between\nDialogue: 0,0:04:46.72,0:04:49.52,EN,,0,0,0,,the declarative knowledge of mathematics--\nDialogue: 0,0:04:50.19,0:04:54.14,EN,,0,0,0,,the definition of a square root as a mathematical truth--\nDialogue: 0,0:04:55.48,0:04:59.56,EN,,0,0,0,,and the idea that computer science talks about the how to knowledge--\nDialogue: 0,0:04:59.76,0:05:04.59,EN,,0,0,0,,contrast that definition of square root with a program to compute a square root.\nDialogue: 0,0:05:05.97,0:05:07.07,EN,,0,0,0,,That's where we started off.\nDialogue: 0,0:05:08.51,0:05:09.52,EN,,0,0,0,,Well, wouldn't it be great\nDialogue: 0,0:05:09.88,0:05:12.16,EN,,0,0,0,,if you could somehow bridge this gap\nDialogue: 0,0:05:12.81,0:05:16.43,EN,,0,0,0,,and make a programming language which sort of did things,\nDialogue: 0,0:05:16.67,0:05:21.61,EN,,0,0,0,,but you talked about it in terms of truth, in declarative terms?\nDialogue: 0,0:05:22.38,0:05:25.50,EN,,0,0,0,,So that would be a programming language in which you specify facts.\nDialogue: 0,0:05:27.69,0:05:28.88,EN,,0,0,0,,You tell it what is.\nDialogue: 0,0:05:28.88,0:05:29.96,EN,,0,0,0,,You say what is true.\nDialogue: 0,0:05:30.95,0:05:33.07,EN,,0,0,0,,And then when you want an answer,\nDialogue: 0,0:05:33.21,0:05:36.38,EN,,0,0,0,,somehow the language has built into it automatically\nDialogue: 0,0:05:37.60,0:05:39.45,EN,,0,0,0,,general kinds of how to knowledge\nDialogue: 0,0:05:39.47,0:05:40.64,EN,,0,0,0,,so it can just take your facts\nDialogue: 0,0:05:40.89,0:05:42.83,EN,,0,0,0,,and it can evolve these methods on its own\nDialogue: 0,0:05:43.31,0:05:46.12,EN,,0,0,0,,using the facts you gave it and maybe some general rules of logic.\nDialogue: 0,0:05:49.33,0:05:50.54,EN,,0,0,0,,So for instance,\nDialogue: 0,0:05:52.06,0:05:55.12,EN,,0,0,0,,I might go up to this program and start telling it some things.\nDialogue: 0,0:05:56.00,0:06:07.08,EN,,0,0,0,,So I might tell it that the son of Adam is Abel.\nDialogue: 0,0:06:08.92,0:06:16.51,EN,,0,0,0,,And I might tell it that the son of Adam is Cain.\nDialogue: 0,0:06:17.66,0:06:25.08,EN,,0,0,0,,And I might tell it that the son of Cain is Enoch.\nDialogue: 0,0:06:27.79,0:06:34.89,EN,,0,0,0,,And I might tell it that the son of Enoch is Irad,\nDialogue: 0,0:06:37.02,0:06:40.72,EN,,0,0,0,,and all through the rest of our chapter whatever of Genesis,\nDialogue: 0,0:06:41.15,0:06:43.18,EN,,0,0,0,,which ends up ending in Adah, by the way,\nDialogue: 0,0:06:43.32,0:06:46.78,EN,,0,0,0,,and this shows the genealogy of Adah from Cain.\nDialogue: 0,0:06:48.44,0:06:50.67,EN,,0,0,0,,Anyway, once you tell it these facts,\nDialogue: 0,0:06:52.35,0:06:53.40,EN,,0,0,0,,you might ask it things.\nDialogue: 0,0:06:53.51,0:06:55.05,EN,,0,0,0,,You might go up to your language and say,\nDialogue: 0,0:06:56.06,0:06:59.29,EN,,0,0,0,,who's the son of Adam?\nDialogue: 0,0:07:00.42,0:07:04.91,EN,,0,0,0,,And you can very easily imagine having a little general purpose search program\nDialogue: 0,0:07:05.52,0:07:06.96,EN,,0,0,0,,which would be able to go through\nDialogue: 0,0:07:07.00,0:07:09.26,EN,,0,0,0,,and in response to that say, oh yeah, there are two answers:\nDialogue: 0,0:07:09.29,0:07:10.44,EN,,0,0,0,,the son of Adam is Abel\nDialogue: 0,0:07:10.68,0:07:12.17,EN,,0,0,0,,and the son of Adam is Cain.\nDialogue: 0,0:07:14.14,0:07:14.97,EN,,0,0,0,,Or you might say,\nDialogue: 0,0:07:15.07,0:07:16.89,EN,,0,0,0,,based on the very same facts,\nDialogue: 0,0:07:18.04,0:07:19.95,EN,,0,0,0,,who is Cain the son of?\nDialogue: 0,0:07:21.95,0:07:27.02,EN,,0,0,0,,And then you can imagine generating another slightly different search program\nDialogue: 0,0:07:27.92,0:07:29.21,EN,,0,0,0,,which would be able to go through\nDialogue: 0,0:07:29.45,0:07:33.05,EN,,0,0,0,,and checked for who is Cain, and son of,\nDialogue: 0,0:07:33.52,0:07:34.44,EN,,0,0,0,,and come up with Adam.\nDialogue: 0,0:07:35.89,0:07:36.99,EN,,0,0,0,,Or you might say,\nDialogue: 0,0:07:38.01,0:07:41.40,EN,,0,0,0,,what's the relationship between Cain and Enoch?\nDialogue: 0,0:07:42.07,0:07:45.08,EN,,0,0,0,,And again, a minor variant on that search program.\nDialogue: 0,0:07:46.34,0:07:48.16,EN,,0,0,0,,You could figure out that it said son of.\nDialogue: 0,0:07:52.88,0:07:54.92,EN,,0,0,0,,But even here in this very simple example,\nDialogue: 0,0:07:56.14,0:07:58.44,EN,,0,0,0,,what you see is that a single fact,\nDialogue: 0,0:07:58.81,0:08:01.52,EN,,0,0,0,,see, a single fact like the son of Adam is Cain\nDialogue: 0,0:08:02.84,0:08:05.52,EN,,0,0,0,,can be used to answer different kinds of questions.\nDialogue: 0,0:08:06.52,0:08:08.12,EN,,0,0,0,,You can say, who's Cain the son of,\nDialogue: 0,0:08:08.14,0:08:10.92,EN,,0,0,0,,or you can say who's the son of Adam,\nDialogue: 0,0:08:10.94,0:08:12.86,EN,,0,0,0,,or you can say what's the relation between Adam and Cain?\nDialogue: 0,0:08:12.88,0:08:14.48,EN,,0,0,0,,Those are different questions\nDialogue: 0,0:08:15.53,0:08:18.54,EN,,0,0,0,,being run by different traditional procedures\nDialogue: 0,0:08:18.68,0:08:20.72,EN,,0,0,0,,all based on the same fact.\nDialogue: 0,0:08:22.75,0:08:25.92,EN,,0,0,0,,And that's going to be the essence of the power of this programming style,\nDialogue: 0,0:08:26.91,0:08:29.50,EN,,0,0,0,,that one piece of declarative knowledge\nDialogue: 0,0:08:30.04,0:08:34.01,EN,,0,0,0,,can be used as the basis for a lot of different kinds of how-to knowledge,\nDialogue: 0,0:08:34.81,0:08:37.08,EN,,0,0,0,,as opposed to the kinds of procedures we're writing\nDialogue: 0,0:08:37.15,0:08:39.55,EN,,0,0,0,,where you sort of tell it what input you're giving in\nDialogue: 0,0:08:39.61,0:08:40.65,EN,,0,0,0,,and what answer you want.\nDialogue: 0,0:08:41.49,0:08:44.70,EN,,0,0,0,,So for instance, our square root program can perfectly well answer the question,\nDialogue: 0,0:08:44.76,0:08:47.16,EN,,0,0,0,,what's the square root of 144?\nDialogue: 0,0:08:48.90,0:08:49.77,EN,,0,0,0,,But in principle,\nDialogue: 0,0:08:49.82,0:08:52.83,EN,,0,0,0,,the mathematical definition of square root tells you other things.\nDialogue: 0,0:08:52.84,0:08:56.43,EN,,0,0,0,,Like it could say, what is 17 the square root of?\nDialogue: 0,0:08:57.59,0:08:59.71,EN,,0,0,0,,And that would be have to be answered by a different program.\nDialogue: 0,0:09:01.92,0:09:03.50,EN,,0,0,0,,So the mathematical definition,\nDialogue: 0,0:09:03.98,0:09:05.12,EN,,0,0,0,,or in general, the\nDialogue: 0,0:09:05.53,0:09:10.30,EN,,0,0,0,,the facts that you give it are somehow unbiased as to what the question is.\nDialogue: 0,0:09:10.90,0:09:12.81,EN,,0,0,0,,Whereas the programs we tend to write specifically\nDialogue: 0,0:09:12.83,0:09:14.20,EN,,0,0,0,,because they are how-to knowledge\nDialogue: 0,0:09:14.24,0:09:16.36,EN,,0,0,0,,tend to be looking for a specific answer.\nDialogue: 0,0:09:17.56,0:09:20.12,EN,,0,0,0,,So that's going to be one characteristic of what we're talking about.\nDialogue: 0,0:09:21.81,0:09:22.60,EN,,0,0,0,,We can go on.\nDialogue: 0,0:09:23.48,0:09:27.52,EN,,0,0,0,,We can imagine that we've given our language some sort of facts.\nDialogue: 0,0:09:27.71,0:09:29.61,EN,,0,0,0,,Now let's give it some rules of inference.\nDialogue: 0,0:09:30.02,0:09:31.36,EN,,0,0,0,,We can say, for instance,\nDialogue: 0,0:09:31.95,0:09:36.19,EN,,0,0,0,,if the-- make up some syntax here--\nDialogue: 0,0:09:36.44,0:09:41.53,EN,,0,0,0,,if the son of x is y--\nDialogue: 0,0:09:41.68,0:09:45.21,EN,,0,0,0,,I'll put question marks to indicate variables here--\nDialogue: 0,0:09:45.61,0:09:56.06,EN,,0,0,0,,if the son of x is y and the son of y is z,\nDialogue: 0,0:09:58.96,0:10:08.46,EN,,0,0,0,,then the grandson of x is z.\nDialogue: 0,0:10:09.32,0:10:13.40,EN,,0,0,0,,So I can imagine telling my machine that rule\nDialogue: 0,0:10:15.00,0:10:17.28,EN,,0,0,0,,and then being able to say, for instance,\nDialogue: 0,0:10:17.44,0:10:18.68,EN,,0,0,0,,who's the grandson of Adam?\nDialogue: 0,0:10:20.61,0:10:23.64,EN,,0,0,0,,Or who is Irad the grandson of?\nDialogue: 0,0:10:24.79,0:10:29.08,EN,,0,0,0,,Or deduce all grandson relationships you possibly can from this information.\nDialogue: 0,0:10:31.13,0:10:35.60,EN,,0,0,0,,We can imagine somehow the language knowing how to do that automatically.\nDialogue: 0,0:10:40.22,0:10:45.20,EN,,0,0,0,,Ok, Let me give you maybe a little bit more concrete example.\nDialogue: 0,0:10:45.77,0:10:51.95,EN,,0,0,0,,Here's a procedure that merges two sorted lists.\nDialogue: 0,0:10:53.92,0:11:00.27,EN,,0,0,0,,So x and y are two, say, lists of numbers,\nDialogue: 0,0:11:00.30,0:11:04.20,EN,,0,0,0,,lists of distinct numbers, if you like, that are in increasing order.\nDialogue: 0,0:11:04.76,0:11:07.53,EN,,0,0,0,,And what merge does is take two such lists\nDialogue: 0,0:11:07.71,0:11:10.38,EN,,0,0,0,,and combine them into a list where everything's in increasing order,\nDialogue: 0,0:11:11.21,0:11:15.00,EN,,0,0,0,,and this is a pretty easy programs\nDialogue: 0,0:11:15.02,0:11:16.14,EN,,0,0,0,,that you ought to be able to write.\nDialogue: 0,0:11:16.39,0:11:18.64,EN,,0,0,0,,It says, if x is empty, the answer is y.\nDialogue: 0,0:11:18.86,0:11:20.46,EN,,0,0,0,,If y is empty, the answer is x.\nDialogue: 0,0:11:21.18,0:11:22.99,EN,,0,0,0,,Otherwise, you compare the first two elements.\nDialogue: 0,0:11:22.99,0:11:24.46,EN,,0,0,0,,So you pick out the first thing in x\nDialogue: 0,0:11:24.84,0:11:26.01,EN,,0,0,0,,and the first thing in y,\nDialogue: 0,0:11:26.81,0:11:31.68,EN,,0,0,0,,and then depending on which of those first elements is less,\nDialogue: 0,0:11:32.83,0:11:36.60,EN,,0,0,0,,you stick the lower one on to the result a recursively merging,\nDialogue: 0,0:11:37.87,0:11:39.92,EN,,0,0,0,,either chopping the first one off x\nDialogue: 0,0:11:40.11,0:11:41.61,EN,,0,0,0,,or chopping the first one off y.\nDialogue: 0,0:11:42.40,0:11:43.96,EN,,0,0,0,,That's a standard kind of program.\nDialogue: 0,0:11:46.47,0:11:48.41,EN,,0,0,0,,Let's look at the logic.\nDialogue: 0,0:11:48.62,0:11:49.79,EN,,0,0,0,,Let's forget about the program\nDialogue: 0,0:11:50.28,0:11:52.76,EN,,0,0,0,,and look at the logic on which that procedure is based.\nDialogue: 0,0:11:53.82,0:11:55.00,EN,,0,0,0,,See, there's some logic which says,\nDialogue: 0,0:11:55.02,0:11:57.21,EN,,0,0,0,,gee, if the first one is less,\nDialogue: 0,0:11:57.53,0:12:00.00,EN,,0,0,0,,then we get the answer by sticking something onto the\nDialogue: 0,0:12:00.16,0:12:02.12,EN,,0,0,0,,the result of recursively merging the rest.\nDialogue: 0,0:12:02.84,0:12:04.09,EN,,0,0,0,,So let's try and be explicit about\nDialogue: 0,0:12:04.24,0:12:06.41,EN,,0,0,0,,what that logic is that's making the program work.\nDialogue: 0,0:12:08.30,0:12:09.44,EN,,0,0,0,,So here's one piece.\nDialogue: 0,0:12:10.13,0:12:11.53,EN,,0,0,0,,Here's the piece of the program which\nDialogue: 0,0:12:12.64,0:12:15.26,EN,,0,0,0,,recursively chops down x\nDialogue: 0,0:12:15.66,0:12:17.82,EN,,0,0,0,,if the first thing in x is smaller.\nDialogue: 0,0:12:19.98,0:12:22.54,EN,,0,0,0,,And if you want to be very explicit about what the logic is there,\nDialogue: 0,0:12:23.45,0:12:26.49,EN,,0,0,0,,what's really going on is a deduction,\nDialogue: 0,0:12:26.72,0:12:32.38,EN,,0,0,0,,which says, if you know that some list, that we'll call cdr of x, and y\nDialogue: 0,0:12:33.29,0:12:35.44,EN,,0,0,0,,merged to form z,\nDialogue: 0,0:12:37.84,0:12:41.52,EN,,0,0,0,,And you know that a is less than the first thing in y.\nDialogue: 0,0:12:43.60,0:12:48.52,EN,,0,0,0,,then you know that if you put a onto the cdr of x.\nDialogue: 0,0:12:49.74,0:12:51.85,EN,,0,0,0,,and that result and y\nDialogue: 0,0:12:52.60,0:12:54.99,EN,,0,0,0,,merge-to-form a onto z.\nDialogue: 0,0:12:55.82,0:12:58.09,EN,,0,0,0,,And what that is, that's the underlying piece of logic--\nDialogue: 0,0:12:58.72,0:12:59.95,EN,,0,0,0,,I haven't written it as a program,\nDialogue: 0,0:12:59.96,0:13:02.00,EN,,0,0,0,,I wrote it a sort of deduction\nDialogue: 0,0:13:02.03,0:13:04.89,EN,,0,0,0,,that sits underneath this particular clause\nDialogue: 0,0:13:05.21,0:13:07.26,EN,,0,0,0,,that says we can use the recursion there.\nDialogue: 0,0:13:09.41,0:13:12.78,EN,,0,0,0,,And then similar, here's the other clause just to complete it.\nDialogue: 0,0:13:14.00,0:13:15.87,EN,,0,0,0,,The other clause is based on this piece of logic,\nDialogue: 0,0:13:15.92,0:13:18.35,EN,,0,0,0,,which is almost the same and I won't go through it,\nDialogue: 0,0:13:19.00,0:13:20.35,EN,,0,0,0,,and then there's the end cases\nDialogue: 0,0:13:20.41,0:13:22.01,EN,,0,0,0,,where we tested for null,\nDialogue: 0,0:13:22.03,0:13:24.04,EN,,0,0,0,,and that's based on the idea that for any x,\nDialogue: 0,0:13:24.51,0:13:27.20,EN,,0,0,0,,x and the empty list merge to form an x,\nDialogue: 0,0:13:28.04,0:13:30.86,EN,,0,0,0,,or for any y, the empty list and y merge to form y.\nDialogue: 0,0:13:33.36,0:13:38.12,EN,,0,0,0,,OK, so there's a piece of procedure\nDialogue: 0,0:13:38.43,0:13:40.11,EN,,0,0,0,,and the logic on which it's based.\nDialogue: 0,0:13:41.74,0:13:42.97,EN,,0,0,0,,And notice a big difference.\nDialogue: 0,0:13:45.10,0:13:50.52,EN,,0,0,0,,The procedure looked like this:\nDialogue: 0,0:13:50.65,0:13:52.28,EN,,0,0,0,,it said there was a box--\nDialogue: 0,0:13:52.86,0:13:55.39,EN,,0,0,0,,and all the things we've been doing have the characteristic\nDialogue: 0,0:13:55.40,0:13:57.69,EN,,0,0,0,,we have boxes and things going in and things going out--\nDialogue: 0,0:13:58.08,0:13:59.61,EN,,0,0,0,,there was this box called merge,\nDialogue: 0,0:14:01.29,0:14:03.85,EN,,0,0,0,,and in came an x and y,\nDialogue: 0,0:14:04.44,0:14:05.37,EN,,0,0,0,,and out came an answer.\nDialogue: 0,0:14:07.63,0:14:09.48,EN,,0,0,0,,That's the character of the procedure that we wrote.\nDialogue: 0,0:14:13.02,0:14:14.66,EN,,0,0,0,,These rules don't look like that.\nDialogue: 0,0:14:14.66,0:14:16.76,EN,,0,0,0,,These rules talk about a relation.\nDialogue: 0,0:14:17.92,0:14:24.16,EN,,0,0,0,,There's some sort of relation that in those slides I called mrege-to-form.\nDialogue: 0,0:14:25.37,0:14:28.76,EN,,0,0,0,,So I said x and y merge to form z,\nDialogue: 0,0:14:29.00,0:14:32.33,EN,,0,0,0,,and somehow this is not -- this is a function.\nDialogue: 0,0:14:32.61,0:14:32.85,EN,,0,0,0,,Right?\nDialogue: 0,0:14:32.85,0:14:34.41,EN,,0,0,0,,The answer is a function of x and y,\nDialogue: 0,0:14:34.59,0:14:38.19,EN,,0,0,0,,and here what I have is a relation between three things.\nDialogue: 0,0:14:39.72,0:14:41.32,EN,,0,0,0,,And I'm not going to specify\nDialogue: 0,0:14:42.09,0:14:43.77,EN,,0,0,0,,which is the input and which is the output.\nDialogue: 0,0:14:44.20,0:14:47.40,EN,,0,0,0,,And the reason I want to say that is because in principle,\nDialogue: 0,0:14:48.64,0:14:50.83,EN,,0,0,0,,we could use exactly those same logic rules\nDialogue: 0,0:14:50.84,0:14:52.44,EN,,0,0,0,,answer a lot of different questions.\nDialogue: 0,0:14:54.57,0:14:56.30,EN,,0,0,0,,So we can say, for instance-- giving\nDialogue: 0,0:14:56.72,0:14:59.05,EN,,0,0,0,,imagine giving our machine those rules of logic.\nDialogue: 0,0:14:59.05,0:15:01.20,EN,,0,0,0,,Not the program, the underlying rules of logic.\nDialogue: 0,0:15:01.40,0:15:03.12,EN,,0,0,0,,Then it ought to be able to say--\nDialogue: 0,0:15:04.75,0:15:05.52,EN,,0,0,0,,we could ask it--\nDialogue: 0,0:15:06.73,0:15:19.18,EN,,0,0,0,,1, 3, 7 and 2, 4, 8 merge to form what?\nDialogue: 0,0:15:20.91,0:15:23.42,EN,,0,0,0,,And that's a question it ought to be able to answer.\nDialogue: 0,0:15:23.88,0:15:27.36,EN,,0,0,0,,That's exactly the same question that our Lisp procedure answered.\nDialogue: 0,0:15:28.18,0:15:30.14,EN,,0,0,0,,But the exact same rules\nDialogue: 0,0:15:30.89,0:15:34.80,EN,,0,0,0,,should also be able to answer a question like this:\nDialogue: 0,0:15:36.19,0:15:43.24,EN,,0,0,0,,1, 3, 7 and what merged to form 1, 2, 3, 4, 7, 8?\nDialogue: 0,0:15:45.56,0:15:47.80,EN,,0,0,0,,The same rules of logic can answer this,\nDialogue: 0,0:15:47.84,0:15:49.90,EN,,0,0,0,,although the procedure we wrote can't answer that question.\nDialogue: 0,0:15:50.80,0:15:52.33,EN,,0,0,0,,Or we might be able to say what\nDialogue: 0,0:15:53.71,0:16:01.12,EN,,0,0,0,,what and what else merge to form--\nDialogue: 0,0:16:04.28,0:16:12.68,EN,,0,0,0,,what and what else merge to form 1, 2, 3, 4, 7, 8?\nDialogue: 0,0:16:13.78,0:16:15.34,EN,,0,0,0,,And the thing should be able to go through,\nDialogue: 0,0:16:15.84,0:16:17.31,EN,,0,0,0,,if it really can apply that logic,\nDialogue: 0,0:16:17.79,0:16:22.54,EN,,0,0,0,,and deduce all, whatever is, 2 to the sixth answers to that question.\nDialogue: 0,0:16:25.60,0:16:27.69,EN,,0,0,0,,Cause it could be 1 and the rester, or it could be 1, 2 and the rest.\nDialogue: 0,0:16:27.69,0:16:28.75,EN,,0,0,0,,or it could be 1, 2 and the rester.\nDialogue: 0,0:16:28.79,0:16:31.53,EN,,0,0,0,,Or it could be 1 and 3 and 7 and the rest.\nDialogue: 0,0:16:32.01,0:16:33.26,EN,,0,0,0,,There's a whole bunch of answers.\nDialogue: 0,0:16:33.41,0:16:37.76,EN,,0,0,0,,And in principle, the logic should be enough to deduce that.\nDialogue: 0,0:16:38.55,0:16:42.03,EN,,0,0,0,,So there are going to be two big differences\nDialogue: 0,0:16:44.04,0:16:46.00,EN,,0,0,0,,in the kind of program we're going to look at\nDialogue: 0,0:16:46.54,0:16:48.19,EN,,0,0,0,,and not only Lisp,\nDialogue: 0,0:16:48.20,0:16:50.56,EN,,0,0,0,,but essentially all the programming you've probably done so far\nDialogue: 0,0:16:52.03,0:16:53.60,EN,,0,0,0,,in pretty much any language you can think of.\nDialogue: 0,0:16:54.15,0:16:57.79,EN,,0,0,0,,The first is, we're not going to be computing functions.\nDialogue: 0,0:17:00.62,0:17:02.01,EN,,0,0,0,,We're not going to be talking about\nDialogue: 0,0:17:02.62,0:17:04.41,EN,,0,0,0,,about things that take input and output.\nDialogue: 0,0:17:04.41,0:17:05.82,EN,,0,0,0,,We're going to be talking about relations.\nDialogue: 0,0:17:06.89,0:17:10.00,EN,,0,0,0,,And that means in principle, these relations don't have directionality.\nDialogue: 0,0:17:11.08,0:17:15.05,EN,,0,0,0,,So the knowledge that you specify to answer this question,\nDialogue: 0,0:17:16.46,0:17:18.41,EN,,0,0,0,,should be same, that same knowledge\nDialogue: 0,0:17:18.43,0:17:21.80,EN,,0,0,0,,also allow you to answer these other questions and conversely.\nDialogue: 0,0:17:26.60,0:17:29.40,EN,,0,0,0,,And the second issue is that\nDialogue: 0,0:17:29.61,0:17:31.23,EN,,0,0,0,,since we're talking about relations,\nDialogue: 0,0:17:32.32,0:17:34.44,EN,,0,0,0,,these relations don't necessarily have one answer.\nDialogue: 0,0:17:35.61,0:17:37.00,EN,,0,0,0,,So that third question down there\nDialogue: 0,0:17:37.02,0:17:38.36,EN,,0,0,0,,doesn't have a particular answer,\nDialogue: 0,0:17:38.40,0:17:39.58,EN,,0,0,0,,it has a whole bunch of answers.\nDialogue: 0,0:17:42.27,0:17:44.64,EN,,0,0,0,,Well, that's where we're going.\nDialogue: 0,0:17:44.64,0:17:45.90,EN,,0,0,0,,This style of programming,\nDialogue: 0,0:17:46.72,0:17:49.21,EN,,0,0,0,,by the way, is called logic programming,\nDialogue: 0,0:17:50.22,0:17:51.58,EN,,0,0,0,,for kind of obvious reasons.\nDialogue: 0,0:17:56.16,0:18:00.38,EN,,0,0,0,,And people who do logic programming say that --\nDialogue: 0,0:18:00.40,0:18:03.15,EN,,0,0,0,,they have this little phrase--\nDialogue: 0,0:18:03.16,0:18:04.67,EN,,0,0,0,,they say the point of logic programming\nDialogue: 0,0:18:04.76,0:18:09.00,EN,,0,0,0,,is that you use logic to express what is true,\nDialogue: 0,0:18:10.09,0:18:13.88,EN,,0,0,0,,you use logic to check whether something is true,\nDialogue: 0,0:18:14.67,0:18:17.24,EN,,0,0,0,,and you use logic to find out what is true.\nDialogue: 0,0:18:19.20,0:18:22.09,EN,,0,0,0,,The best known logic programming language,\nDialogue: 0,0:18:22.97,0:18:24.78,EN,,0,0,0,,as you probably know, is called Prolog.\nDialogue: 0,0:18:25.78,0:18:28.88,EN,,0,0,0,,The language that we're going to implement this morning\nDialogue: 0,0:18:29.82,0:18:32.32,EN,,0,0,0,,is something we call the query language,\nDialogue: 0,0:18:32.48,0:18:34.41,EN,,0,0,0,,and it essentially has the essence of prolog.\nDialogue: 0,0:18:35.32,0:18:36.73,EN,,0,0,0,,It can do about the same stuff,\nDialogue: 0,0:18:37.29,0:18:38.73,EN,,0,0,0,,although it's a lot slower\nDialogue: 0,0:18:38.73,0:18:40.01,EN,,0,0,0,,because we're going to implement it in LISP\nDialogue: 0,0:18:41.90,0:18:44.36,EN,,0,0,0,,rather than building a particular compiler.\nDialogue: 0,0:18:44.46,0:18:46.62,EN,,0,0,0,,We're going to interpret it on top of the LISP interpreter.\nDialogue: 0,0:18:47.51,0:18:49.84,EN,,0,0,0,,But other than that, it can do about the same stuff as prolog.\nDialogue: 0,0:18:49.88,0:18:52.78,EN,,0,0,0,,It has about the same power and about the same limitations.\nDialogue: 0,0:18:55.08,0:18:56.17,EN,,0,0,0,,All right, let's break for question.\nDialogue: 0,0:19:00.43,0:19:02.84,EN,,0,0,0,,AUDIENCE: Yes, could you please repeat what the three\nDialogue: 0,0:19:03.48,0:19:06.09,EN,,0,0,0,,things you use logic programming to find?\nDialogue: 0,0:19:06.72,0:19:09.84,EN,,0,0,0,,In other words, to find what is true, learn what is true-- what is the?\nDialogue: 0,0:19:09.84,0:19:10.52,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:19:10.56,0:19:15.74,EN,,0,0,0,,Sort of a logic programmer's little catechism.\nDialogue: 0,0:19:15.85,0:19:19.16,EN,,0,0,0,,You use logic to express what is true,\nDialogue: 0,0:19:20.80,0:19:21.79,EN,,0,0,0,,like these rules.\nDialogue: 0,0:19:22.61,0:19:25.56,EN,,0,0,0,,You use logic to check whether something is true,\nDialogue: 0,0:19:25.60,0:19:27.76,EN,,0,0,0,,and that's the kind of question I didn't answer here.\nDialogue: 0,0:19:28.55,0:19:29.29,EN,,0,0,0,,I might say--\nDialogue: 0,0:19:29.68,0:19:32.14,EN,,0,0,0,,another question I could put down here is to say,\nDialogue: 0,0:19:33.26,0:19:36.56,EN,,0,0,0,,is it true that 1, 3, 7 and 2, 4, 8\nDialogue: 0,0:19:36.91,0:19:40.38,EN,,0,0,0,,merge to form 1, 2, 6, 10\nDialogue: 0,0:19:41.12,0:19:44.68,EN,,0,0,0,,And that same logic should be enough to say no.\nDialogue: 0,0:19:45.69,0:19:47.93,EN,,0,0,0,,So I use logic to check what is true,\nDialogue: 0,0:19:48.28,0:19:50.48,EN,,0,0,0,,and then you also use logic to find out what's true.\nDialogue: 0,0:20:04.46,0:20:05.16,EN,,0,0,0,,Let's break.\nDialogue: 0,0:20:06.13,0:20:17.02,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:21:03.24,0:21:04.97,EN,,0,0,0,,PROFESSOR: OK, let's go ahead and\nDialogue: 0,0:21:05.84,0:21:08.44,EN,,0,0,0,,take a look at this query language and operation.\nDialogue: 0,0:21:10.52,0:21:11.84,EN,,0,0,0,,The first thing you might notice,\nDialogue: 0,0:21:12.24,0:21:14.14,EN,,0,0,0,,when I put up that little biblical database,\nDialogue: 0,0:21:14.16,0:21:17.24,EN,,0,0,0,,is that it's nice to be able to ask this language questions\nDialogue: 0,0:21:17.48,0:21:19.92,EN,,0,0,0,,in relation to some collection of facts.\nDialogue: 0,0:21:21.33,0:21:25.15,EN,,0,0,0,,So let's start off and make a little collection of facts.\nDialogue: 0,0:21:26.06,0:21:29.68,EN,,0,0,0,,This is a tiny fragment of personnel records\nDialogue: 0,0:21:30.08,0:21:32.62,EN,,0,0,0,,for a Boston high tech company,\nDialogue: 0,0:21:33.05,0:21:36.80,EN,,0,0,0,,and here's a piece of the personnel records of Ben Bitdiddle.\nDialogue: 0,0:21:37.50,0:21:41.95,EN,,0,0,0,,And Ben Bitdiddle is the computer wizard in this company,\nDialogue: 0,0:21:42.84,0:21:45.80,EN,,0,0,0,,he's the underpaid computer wizard in this company.\nDialogue: 0,0:21:46.42,0:21:48.78,EN,,0,0,0,,His supervisor is all Oliver Warbucks,\nDialogue: 0,0:21:49.28,0:21:50.70,EN,,0,0,0,,and here's his address.\nDialogue: 0,0:21:52.15,0:21:56.54,EN,,0,0,0,,So the format is we're giving this information: job, salary, supervisor, address.\nDialogue: 0,0:21:57.56,0:21:59.25,EN,,0,0,0,,And there are some other conventions.\nDialogue: 0,0:21:59.25,0:22:02.22,EN,,0,0,0,,Computer here means that Ben works in the computer division, and\nDialogue: 0,0:22:02.76,0:22:04.94,EN,,0,0,0,,his position in the computer division is wizard.\nDialogue: 0,0:22:05.66,0:22:07.15,EN,,0,0,0,,Here's somebody else.\nDialogue: 0,0:22:07.16,0:22:12.28,EN,,0,0,0,,Alyssa, Alyssa P. Hacker is a computer programmer,\nDialogue: 0,0:22:13.36,0:22:14.60,EN,,0,0,0,,and she works for Ben,\nDialogue: 0,0:22:15.21,0:22:16.54,EN,,0,0,0,,and she lives in Cambridge.\nDialogue: 0,0:22:17.55,0:22:19.42,EN,,0,0,0,,And there's another programmer who works for Ben\nDialogue: 0,0:22:20.03,0:22:21.44,EN,,0,0,0,,who's Lem E. Tweakit.\nDialogue: 0,0:22:22.82,0:22:26.73,EN,,0,0,0,,And there's a programmer trainee, who is Louis Reasoner,\nDialogue: 0,0:22:27.42,0:22:28.62,EN,,0,0,0,,and he works for Alyssa.\nDialogue: 0,0:22:30.10,0:22:35.45,EN,,0,0,0,,And the big wheel of the company doesn't work for anybody.\nDialogue: 0,0:22:36.81,0:22:38.11,EN,,0,0,0,,Right, That's Oliver Warbucks.\nDialogue: 0,0:22:38.11,0:22:39.31,EN,,0,0,0,,Anyway, what we're going to do is\nDialogue: 0,0:22:40.94,0:22:43.66,EN,,0,0,0,,is ask questions about that little world.\nDialogue: 0,0:22:44.97,0:22:48.40,EN,,0,0,0,,And that'll be a sample world that we're going to do logic in.\nDialogue: 0,0:22:51.42,0:22:54.96,EN,,0,0,0,,Let me just write up here, for probably the last time,\nDialogue: 0,0:22:55.60,0:22:58.20,EN,,0,0,0,,what I said is the very most important thing you should get out of this course,\nDialogue: 0,0:22:58.80,0:23:01.66,EN,,0,0,0,,and that is, when somebody tells you about a language,\nDialogue: 0,0:23:02.25,0:23:04.43,EN,,0,0,0,,you say, fine-- what are the primitives,\nDialogue: 0,0:23:06.12,0:23:07.79,EN,,0,0,0,,what are the means of combination,\nDialogue: 0,0:23:14.70,0:23:16.40,EN,,0,0,0,,how do you put the primitives together,\nDialogue: 0,0:23:16.67,0:23:19.37,EN,,0,0,0,,and then how do you abstract them,\nDialogue: 0,0:23:19.96,0:23:21.93,EN,,0,0,0,,how do you abstract the compound pieces\nDialogue: 0,0:23:24.68,0:23:27.58,EN,,0,0,0,,so you can use them as pieces to make something more complicated?\nDialogue: 0,0:23:29.02,0:23:30.81,EN,,0,0,0,,And we've said this a whole bunch of times already,\nDialogue: 0,0:23:31.16,0:23:32.48,EN,,0,0,0,,but it's worth saying again.\nDialogue: 0,0:23:35.00,0:23:36.67,EN,,0,0,0,,OKay? Let's start.\nDialogue: 0,0:23:36.67,0:23:37.34,EN,,0,0,0,,The primitives.\nDialogue: 0,0:23:37.77,0:23:39.44,EN,,0,0,0,,Well, there's really only one primitive,\nDialogue: 0,0:23:40.96,0:23:43.20,EN,,0,0,0,,and the primitive in this language is called a query.\nDialogue: 0,0:23:44.14,0:23:45.74,EN,,0,0,0,,A primitive query.\nDialogue: 0,0:23:46.81,0:23:48.25,EN,,0,0,0,,Let's look at some primitive queries.\nDialogue: 0,0:23:51.82,0:23:53.02,EN,,0,0,0,,Alright. Job x.\nDialogue: 0,0:23:53.10,0:23:54.81,EN,,0,0,0,,Who is a computer programmer?\nDialogue: 0,0:23:55.55,0:23:59.88,EN,,0,0,0,,Or find every fact in the database\nDialogue: 0,0:24:01.55,0:24:06.14,EN,,0,0,0,,that matches job of the x is computer programmer.\nDialogue: 0,0:24:06.64,0:24:08.01,EN,,0,0,0,,And you see a little syntax here.\nDialogue: 0,0:24:08.47,0:24:10.59,EN,,0,0,0,,Things without question marks are meant to be literal,\nDialogue: 0,0:24:11.28,0:24:13.15,EN,,0,0,0,,question mark x means that's a variable,\nDialogue: 0,0:24:13.31,0:24:15.56,EN,,0,0,0,,and this thing will match, for example,\nDialogue: 0,0:24:16.03,0:24:19.00,EN,,0,0,0,,the fact that Alyssa P. Hacker is a computer programmer,\nDialogue: 0,0:24:19.28,0:24:21.93,EN,,0,0,0,,or x is Alyssa P. Hacker.\nDialogue: 0,0:24:26.82,0:24:29.98,EN,,0,0,0,,Or more generally, I could have something with two variables in it.\nDialogue: 0,0:24:30.75,0:24:31.45,EN,,0,0,0,,I could say,\nDialogue: 0,0:24:31.60,0:24:35.88,EN,,0,0,0,,the job of x is computer something,\nDialogue: 0,0:24:39.34,0:24:41.39,EN,,0,0,0,,and that'll match computer wizard.\nDialogue: 0,0:24:42.14,0:24:44.28,EN,,0,0,0,,So there's something here: type will match wizard,\nDialogue: 0,0:24:44.92,0:24:46.46,EN,,0,0,0,,or type will match programmer,\nDialogue: 0,0:24:47.48,0:24:50.37,EN,,0,0,0,,or x might match various certain things.\nDialogue: 0,0:24:50.37,0:24:52.24,EN,,0,0,0,,So there are, in our little example,\nDialogue: 0,0:24:52.25,0:24:55.15,EN,,0,0,0,,only three facts in that database that match that query.\nDialogue: 0,0:24:59.12,0:25:02.08,EN,,0,0,0,,Let's see, just to show you some syntax, the same query,\nDialogue: 0,0:25:05.29,0:25:08.09,EN,,0,0,0,,this query doesn't match the job of x,\nDialogue: 0,0:25:09.85,0:25:11.79,EN,,0,0,0,,doesn't match Lewis Reasoner,\nDialogue: 0,0:25:11.84,0:25:13.64,EN,,0,0,0,,the reason for that is when I write something here,\nDialogue: 0,0:25:14.22,0:25:17.74,EN,,0,0,0,,what I mean is that this is going to be a list of two symbols,\nDialogue: 0,0:25:19.96,0:25:21.96,EN,,0,0,0,,of which the first is the word computer,\nDialogue: 0,0:25:22.32,0:25:23.80,EN,,0,0,0,,and the second can be anything.\nDialogue: 0,0:25:25.08,0:25:27.32,EN,,0,0,0,,And Lewis's job description here has three symbols,\nDialogue: 0,0:25:27.80,0:25:28.83,EN,,0,0,0,,so it doesn't match.\nDialogue: 0,0:25:30.34,0:25:32.19,EN,,0,0,0,,And just to show you a little bit of syntax,\nDialogue: 0,0:25:35.04,0:25:38.32,EN,,0,0,0,,the more general thing I might want to type is a thing with a dot here,\nDialogue: 0,0:25:40.17,0:25:42.92,EN,,0,0,0,,and this is just standard list notation for saying,\nDialogue: 0,0:25:43.04,0:25:43.82,EN,,0,0,0,,this is a list,\nDialogue: 0,0:25:44.12,0:25:47.32,EN,,0,0,0,,of which the first element is the word computers,\nDialogue: 0,0:25:47.58,0:25:50.22,EN,,0,0,0,,and THE REST, is something that I'll call type.\nDialogue: 0,0:25:53.73,0:25:55.50,EN,,0,0,0,,So this one would match.\nDialogue: 0,0:25:56.93,0:25:59.31,EN,,0,0,0,,Lewis's job is computer programmer trainee,\nDialogue: 0,0:25:59.44,0:26:03.29,EN,,0,0,0,,and type here would be the cdr of this list.\nDialogue: 0,0:26:03.32,0:26:05.64,EN,,0,0,0,,It would be the list programmer trainee.\nDialogue: 0,0:26:06.96,0:26:10.46,EN,,0,0,0,,And that kind of dot processing is done automatically by the LISP reader.\nDialogue: 0,0:26:15.90,0:26:17.76,EN,,0,0,0,,Well, let's actually try this.\nDialogue: 0,0:26:17.76,0:26:20.51,EN,,0,0,0,,The idea is I'm going to type in queries in this language,\nDialogue: 0,0:26:20.76,0:26:21.82,EN,,0,0,0,,and answers will come out.\nDialogue: 0,0:26:22.54,0:26:24.48,EN,,0,0,0,,Let's look at this.\nDialogue: 0,0:26:25.18,0:26:26.51,EN,,0,0,0,,I can go up and say,\nDialogue: 0,0:26:27.34,0:26:28.88,EN,,0,0,0,,who works in the computer division?\nDialogue: 0,0:26:30.00,0:26:38.22,EN,,0,0,0,,Job of x is computer dot y.\nDialogue: 0,0:26:39.73,0:26:41.48,EN,,0,0,0,,Doesn't matter what I call the dummy variables.\nDialogue: 0,0:26:42.76,0:26:44.14,EN,,0,0,0,,It says the answers to that,\nDialogue: 0,0:26:44.41,0:26:45.68,EN,,0,0,0,,and it's found four answers.\nDialogue: 0,0:26:48.65,0:26:50.09,EN,,0,0,0,,Or I can go off and say,\nDialogue: 0,0:26:50.56,0:26:52.38,EN,,0,0,0,,tell me about everybody's supervisor.\nDialogue: 0,0:26:52.81,0:26:54.88,EN,,0,0,0,,So I'll put in the query, the primitive query,\nDialogue: 0,0:26:56.52,0:26:59.39,EN,,0,0,0,,the supervisor of x is y.\nDialogue: 0,0:27:02.56,0:27:05.42,EN,,0,0,0,,There are all the supervisor relationships I know.\nDialogue: 0,0:27:05.54,0:27:08.83,EN,,0,0,0,,Or I could go type in, who lives in Cambridge?\nDialogue: 0,0:27:08.83,0:27:09.47,EN,,0,0,0,,So I can say,\nDialogue: 0,0:27:10.24,0:27:20.92,EN,,0,0,0,,the address of x is Cambridge dot anything.\nDialogue: 0,0:27:25.09,0:27:26.89,EN,,0,0,0,,And only one person lives in Cambridge.\nDialogue: 0,0:27:30.82,0:27:32.17,EN,,0,0,0,,OK, so those are primitive queries.\nDialogue: 0,0:27:32.17,0:27:34.96,EN,,0,0,0,,And you see what happens to basic interaction with the system\nDialogue: 0,0:27:35.29,0:27:39.24,EN,,0,0,0,,is you type in a query, and it types out all possible answers.\nDialogue: 0,0:27:39.62,0:27:40.65,EN,,0,0,0,,Or another way to say that:\nDialogue: 0,0:27:40.67,0:27:44.16,EN,,0,0,0,,it finds out all the possible values of those variables\nDialogue: 0,0:27:44.19,0:27:45.87,EN,,0,0,0,,x and y or t or whatever I've called them,\nDialogue: 0,0:27:46.09,0:27:52.08,EN,,0,0,0,,and it types out all ways of taking that query and instantiating it--\nDialogue: 0,0:27:52.92,0:27:55.16,EN,,0,0,0,,remember that from the rule system lecture--\nDialogue: 0,0:27:55.16,0:27:58.83,EN,,0,0,0,,instantiates the query with all possible values for those variables\nDialogue: 0,0:27:59.00,0:28:00.35,EN,,0,0,0,,and then types out all of them.\nDialogue: 0,0:28:01.00,0:28:03.35,EN,,0,0,0,,And there are a lot of ways you can arrange a logic language.\nDialogue: 0,0:28:03.35,0:28:06.01,EN,,0,0,0,,Prolog, for instance, does something slightly different.\nDialogue: 0,0:28:06.01,0:28:07.44,EN,,0,0,0,,Rather than typing back your query,\nDialogue: 0,0:28:07.76,0:28:10.78,EN,,0,0,0,,prolog would type out, x equals this and y equals that,\nDialogue: 0,0:28:10.97,0:28:12.94,EN,,0,0,0,,or x equals this and y equals that.\nDialogue: 0,0:28:13.66,0:28:15.48,EN,,0,0,0,,And that's a very surface level thing,\nDialogue: 0,0:28:15.71,0:28:17.05,EN,,0,0,0,,you can decide what you like.\nDialogue: 0,0:28:18.97,0:28:19.58,EN,,0,0,0,,OK.\nDialogue: 0,0:28:21.00,0:28:22.68,EN,,0,0,0,,Alright. So the primitives in this language?\nDialogue: 0,0:28:23.39,0:28:24.57,EN,,0,0,0,,Only one, right?\nDialogue: 0,0:28:24.57,0:28:27.23,EN,,0,0,0,,Primitive query.\nDialogue: 0,0:28:31.31,0:28:32.56,EN,,0,0,0,,Means of combination.\nDialogue: 0,0:28:34.33,0:28:37.68,EN,,0,0,0,,Let's look at some compound queries in this language.\nDialogue: 0,0:28:39.77,0:28:40.46,EN,,0,0,0,,Here's one.\nDialogue: 0,0:28:41.79,0:28:42.51,EN,,0,0,0,,This one says,\nDialogue: 0,0:28:45.05,0:28:48.22,EN,,0,0,0,,tell me all the people who work in the computer division.\nDialogue: 0,0:28:49.81,0:28:52.00,EN,,0,0,0,,Tell me all the people who work in the computer division\nDialogue: 0,0:28:52.54,0:28:53.96,EN,,0,0,0,,together with their supervisors.\nDialogue: 0,0:28:56.80,0:28:58.83,EN,,0,0,0,,Where I write that is the query is and.\nDialogue: 0,0:29:00.22,0:29:04.06,EN,,0,0,0,,And the job of the x is computer something or other.\nDialogue: 0,0:29:04.92,0:29:06.83,EN,,0,0,0,,And job of x is computer dot y.\nDialogue: 0,0:29:07.56,0:29:10.03,EN,,0,0,0,,And the supervisor of x is z.\nDialogue: 0,0:29:11.44,0:29:14.16,EN,,0,0,0,,Tell me all the people in the computer division-- that's this--\nDialogue: 0,0:29:14.30,0:29:15.88,EN,,0,0,0,,together with their supervisors.\nDialogue: 0,0:29:16.46,0:29:17.82,EN,,0,0,0,,And notice in this query\nDialogue: 0,0:29:18.67,0:29:22.41,EN,,0,0,0,,I have three variables-- x, y, and z.\nDialogue: 0,0:29:23.58,0:29:28.65,EN,,0,0,0,,And this x is supposed to be the same as that x.\nDialogue: 0,0:29:29.45,0:29:31.16,EN,,0,0,0,,So x works in the computer division,\nDialogue: 0,0:29:31.31,0:29:33.00,EN,,0,0,0,,and the supervisor of x is z.\nDialogue: 0,0:29:34.81,0:29:35.80,EN,,0,0,0,,Let's try another one.\nDialogue: 0,0:29:37.25,0:29:39.28,EN,,0,0,0,,So one means of combination is and.\nDialogue: 0,0:29:41.44,0:29:43.96,EN,,0,0,0,,Who are all the people who make more than $30,000?\nDialogue: 0,0:29:45.71,0:29:51.71,EN,,0,0,0,,And the salary of some person p is some amount a.\nDialogue: 0,0:29:54.59,0:29:57.45,EN,,0,0,0,,And when I go and look at a,\nDialogue: 0,0:29:57.48,0:30:00.12,EN,,0,0,0,,a is greater than $30,000.\nDialogue: 0,0:30:00.60,0:30:03.23,EN,,0,0,0,,And LISP value here is a little piece of interface\nDialogue: 0,0:30:04.30,0:30:10.04,EN,,0,0,0,,that interfaces the query language to the underlying LISP.\nDialogue: 0,0:30:10.60,0:30:12.72,EN,,0,0,0,,And what the LISP value allows you to do\nDialogue: 0,0:30:12.75,0:30:16.91,EN,,0,0,0,,call any LISP predicate inside a query.\nDialogue: 0,0:30:17.18,0:30:20.11,EN,,0,0,0,,So here I'm using the LISP predicate greater than, so I say LISP value.\nDialogue: 0,0:30:21.02,0:30:21.75,EN,,0,0,0,,This I say and.\nDialogue: 0,0:30:21.75,0:30:24.48,EN,,0,0,0,,So all the people whose salary is greater than $30,000.\nDialogue: 0,0:30:28.19,0:30:30.03,EN,,0,0,0,,Or here's a more complicated one.\nDialogue: 0,0:30:31.27,0:30:35.02,EN,,0,0,0,,Tell me all the people who work in the computer division\nDialogue: 0,0:30:36.25,0:30:39.36,EN,,0,0,0,,who do not have a supervisor who works in the computer division.\nDialogue: 0,0:30:42.79,0:30:45.51,EN,,0,0,0,,and x works in the computer division.\nDialogue: 0,0:30:45.51,0:30:47.32,EN,,0,0,0,,The job of x is computer dot y.\nDialogue: 0,0:30:47.78,0:30:49.24,EN,,0,0,0,,And it's not the case\nDialogue: 0,0:30:50.49,0:30:54.25,EN,,0,0,0,,that both x has a supervisor z\nDialogue: 0,0:30:55.37,0:30:57.87,EN,,0,0,0,,and the job of z is computer something or other.\nDialogue: 0,0:30:59.62,0:31:00.35,EN,,0,0,0,,All right, so again,\nDialogue: 0,0:31:00.51,0:31:02.38,EN,,0,0,0,,this x has got to be that x,\nDialogue: 0,0:31:03.20,0:31:05.76,EN,,0,0,0,,and this z is going to be that z.\nDialogue: 0,0:31:09.39,0:31:11.38,EN,,0,0,0,,And then you see another means a combination, not.\nDialogue: 0,0:31:17.71,0:31:18.67,EN,,0,0,0,,All right, well, let's look at that.\nDialogue: 0,0:31:20.88,0:31:22.08,EN,,0,0,0,,It works the same way.\nDialogue: 0,0:31:22.40,0:31:24.12,EN,,0,0,0,,I can go up to the machine and say\nDialogue: 0,0:31:26.89,0:31:35.40,EN,,0,0,0,,and the job of the x is computer dot y.\nDialogue: 0,0:31:38.84,0:31:45.95,EN,,0,0,0,,And the supervisor of x is z.\nDialogue: 0,0:31:46.83,0:31:49.53,EN,,0,0,0,,And I typed that in like a query.\nDialogue: 0,0:31:51.07,0:31:52.97,EN,,0,0,0,,And what it types back,\nDialogue: 0,0:31:54.00,0:31:58.73,EN,,0,0,0,,what you see are the queries I typed in instantiated by all possible answers.\nDialogue: 0,0:31:58.93,0:32:00.08,EN,,0,0,0,,And then you see there are a lot of answers.\nDialogue: 0,0:32:01.69,0:32:02.14,EN,,0,0,0,,All right.\nDialogue: 0,0:32:02.19,0:32:04.04,EN,,0,0,0,,So the means of combination in this language--\nDialogue: 0,0:32:05.21,0:32:06.60,EN,,0,0,0,,and this is why it's called a logic language--\nDialogue: 0,0:32:06.64,0:32:09.47,EN,,0,0,0,,are logical operations.\nDialogue: 0,0:32:09.80,0:32:15.68,EN,,0,0,0,,Means of combinations are things like AND and NOT\nDialogue: 0,0:32:15.96,0:32:17.92,EN,,0,0,0,,and there's one I didn't show you, which is OR.\nDialogue: 0,0:32:18.49,0:32:20.36,EN,,0,0,0,,And then I showed you LISP value,\nDialogue: 0,0:32:20.72,0:32:24.48,EN,,0,0,0,,which is a, not logic, of course,\nDialogue: 0,0:32:24.51,0:32:26.89,EN,,0,0,0,,but is a little special hack to interface that to LISP\nDialogue: 0,0:32:27.34,0:32:28.75,EN,,0,0,0,,so you can get more power.\nDialogue: 0,0:32:29.25,0:32:30.67,EN,,0,0,0,,Those are the means of combination.\nDialogue: 0,0:32:32.59,0:32:33.98,EN,,0,0,0,,OK, the means of abstraction.\nDialogue: 0,0:32:34.16,0:32:35.21,EN,,0,0,0,,What we'd like to do--\nDialogue: 0,0:32:38.27,0:32:41.24,EN,,0,0,0,,let's go back for second and look at that last slide.\nDialogue: 0,0:32:42.26,0:32:44.25,EN,,0,0,0,,We might like to take very complicated thing,\nDialogue: 0,0:32:44.46,0:32:48.00,EN,,0,0,0,,the idea that someone works in a division\nDialogue: 0,0:32:48.01,0:32:50.09,EN,,0,0,0,,but does not have a supervisor in the division.\nDialogue: 0,0:32:52.40,0:32:55.10,EN,,0,0,0,,And as before, name that.\nDialogue: 0,0:32:56.09,0:32:58.12,EN,,0,0,0,,Well, if someone works in a division\nDialogue: 0,0:32:58.17,0:33:00.25,EN,,0,0,0,,and does not have a supervisor who works in that division,\nDialogue: 0,0:33:00.48,0:33:01.93,EN,,0,0,0,,that means that person is a big shot.\nDialogue: 0,0:33:02.75,0:33:05.13,EN,,0,0,0,,So let's make a rule that\nDialogue: 0,0:33:06.43,0:33:09.16,EN,,0,0,0,,somebody x is a big shot in some department\nDialogue: 0,0:33:10.91,0:33:14.68,EN,,0,0,0,,if x works in the department\nDialogue: 0,0:33:16.04,0:33:20.08,EN,,0,0,0,,and it's not the case that x has a supervisor who works in the department.\nDialogue: 0,0:33:21.51,0:33:22.94,EN,,0,0,0,,So this is our means of abstraction.\nDialogue: 0,0:33:22.94,0:33:23.90,EN,,0,0,0,,This is a rule.\nDialogue: 0,0:33:26.22,0:33:27.58,EN,,0,0,0,,And a rule has three parts.\nDialogue: 0,0:33:31.00,0:33:32.48,EN,,0,0,0,,The thing that says it's a rule.\nDialogue: 0,0:33:33.40,0:33:35.48,EN,,0,0,0,,And then there's the conclusion of the rule.\nDialogue: 0,0:33:37.53,0:33:39.07,EN,,0,0,0,,And then there's the body of the rule.\nDialogue: 0,0:33:40.00,0:33:41.88,EN,,0,0,0,,And you can read this as a piece of logic which says,\nDialogue: 0,0:33:41.92,0:33:45.15,EN,,0,0,0,,if you know that the body of the rule is true,\nDialogue: 0,0:33:46.40,0:33:48.72,EN,,0,0,0,,then you can conclude that the conclusion is true.\nDialogue: 0,0:33:49.45,0:33:53.28,EN,,0,0,0,,Or in order to deduce that x is a big shot in some department,\nDialogue: 0,0:33:53.79,0:33:55.71,EN,,0,0,0,,it's enough to verify that.\nDialogue: 0,0:33:57.48,0:33:58.82,EN,,0,0,0,,So that's what rules look like.\nDialogue: 0,0:34:03.28,0:34:06.16,EN,,0,0,0,,Let's go back and look at that merge example\nDialogue: 0,0:34:06.73,0:34:07.92,EN,,0,0,0,,that I did before the break.\nDialogue: 0,0:34:08.11,0:34:10.68,EN,,0,0,0,,Let's look at how that would look in terms of rules.\nDialogue: 0,0:34:11.44,0:34:12.84,EN,,0,0,0,,I'm going to take the logic I put up\nDialogue: 0,0:34:13.08,0:34:15.50,EN,,0,0,0,,and just change it into a bunch of rules in this format.\nDialogue: 0,0:34:18.73,0:34:19.35,EN,,0,0,0,,We have a rule.\nDialogue: 0,0:34:19.35,0:34:20.96,EN,,0,0,0,,Remember, there was this thing merge-to-form.\nDialogue: 0,0:34:21.71,0:34:22.97,EN,,0,0,0,,There is a rule that says,\nDialogue: 0,0:34:26.28,0:34:29.62,EN,,0,0,0,,the empty list and y merge to form y.\nDialogue: 0,0:34:29.62,0:34:30.87,EN,,0,0,0,,This is the rule conclusion.\nDialogue: 0,0:34:33.21,0:34:35.74,EN,,0,0,0,,And notice this particular rule has no body.\nDialogue: 0,0:34:36.65,0:34:37.66,EN,,0,0,0,,And in this language,\nDialogue: 0,0:34:38.11,0:34:40.86,EN,,0,0,0,,a rule with no body is something that is always true.\nDialogue: 0,0:34:41.23,0:34:42.51,EN,,0,0,0,,You can always assume that's true.\nDialogue: 0,0:34:45.19,0:34:46.49,EN,,0,0,0,,And there was another piece of logic\nDialogue: 0,0:34:46.64,0:34:49.46,EN,,0,0,0,,that said anything in the empty list merged to form the anything.\nDialogue: 0,0:34:49.46,0:34:50.12,EN,,0,0,0,,That's this.\nDialogue: 0,0:34:50.90,0:34:53.55,EN,,0,0,0,,A rule y and the empty list merge to form y.\nDialogue: 0,0:34:55.51,0:34:58.40,EN,,0,0,0,,Those corresponded to the two end cases in our merge procedure,\nDialogue: 0,0:34:58.44,0:34:59.77,EN,,0,0,0,,but now we're talking about logic,\nDialogue: 0,0:35:00.41,0:35:01.45,EN,,0,0,0,,not about procedures.\nDialogue: 0,0:35:03.49,0:35:04.48,EN,,0,0,0,,Then we had another rule,\nDialogue: 0,0:35:04.83,0:35:08.73,EN,,0,0,0,,which said if you know how shorter things merge,\nDialogue: 0,0:35:08.91,0:35:09.83,EN,,0,0,0,,you can put them together.\nDialogue: 0,0:35:09.83,0:35:14.16,EN,,0,0,0,,So this says, if you have a list x and y and z,\nDialogue: 0,0:35:14.92,0:35:17.61,EN,,0,0,0,,and if you want to deduce that a dot x--\nDialogue: 0,0:35:17.63,0:35:19.08,EN,,0,0,0,,this means cons a onto x,\nDialogue: 0,0:35:19.48,0:35:22.36,EN,,0,0,0,,or a list whose first thing is a and whose rest is x--\nDialogue: 0,0:35:23.16,0:35:27.40,EN,,0,0,0,,so if you want to deduce that a dot x and b dot y merge to form b dot z--\nDialogue: 0,0:35:30.36,0:35:33.90,EN,,0,0,0,,that would say you merge these two lists a x and b y\nDialogue: 0,0:35:33.92,0:35:35.85,EN,,0,0,0,,and you're going to get something that starts with b--\nDialogue: 0,0:35:36.76,0:35:40.67,EN,,0,0,0,,you can deduce that if you know that it's the case\nDialogue: 0,0:35:40.91,0:35:44.48,EN,,0,0,0,,both that a dot x and y merge to form z\nDialogue: 0,0:35:45.18,0:35:47.24,EN,,0,0,0,,and a is larger than b.\nDialogue: 0,0:35:48.69,0:35:50.59,EN,,0,0,0,,So when I merge them, b will come first in the list.\nDialogue: 0,0:35:51.82,0:35:54.91,EN,,0,0,0,,That's a little translation of the logic rule\nDialogue: 0,0:35:55.24,0:35:57.18,EN,,0,0,0,,that I wrote in pseudo-English before.\nDialogue: 0,0:35:57.96,0:36:01.63,EN,,0,0,0,,And then just for completeness, here's the other case.\nDialogue: 0,0:36:02.88,0:36:05.95,EN,,0,0,0,,a dot x and b dot y merge to form a dot z\nDialogue: 0,0:36:06.08,0:36:09.16,EN,,0,0,0,,if x and b dot y merged to form z and b is larger than a.\nDialogue: 0,0:36:09.47,0:36:11.00,EN,,0,0,0,,and b is larger than a.\nDialogue: 0,0:36:12.19,0:36:15.98,EN,,0,0,0,,So that's a little program that I've typed in in this language,\nDialogue: 0,0:36:16.01,0:36:17.07,EN,,0,0,0,,and now let's look at it run.\nDialogue: 0,0:36:21.90,0:36:23.90,EN,,0,0,0,,So I typed in the merge rules before,\nDialogue: 0,0:36:24.62,0:36:25.77,EN,,0,0,0,,and I could say, ahh\nDialogue: 0,0:36:27.04,0:36:28.51,EN,,0,0,0,,I could use this like a procedure.\nDialogue: 0,0:36:28.51,0:36:38.24,EN,,0,0,0,,I could say merge to form 1 and 3 and 2 and 7.\nDialogue: 0,0:36:39.42,0:36:41.55,EN,,0,0,0,,So here I'm using it like the LISP procedure.\nDialogue: 0,0:36:43.16,0:36:44.97,EN,,0,0,0,,Now it's going to think about that for a while\nDialogue: 0,0:36:46.43,0:36:47.56,EN,,0,0,0,,and apply these rules.\nDialogue: 0,0:36:50.78,0:36:51.92,EN,,0,0,0,,So it found an answer.\nDialogue: 0,0:36:52.80,0:36:54.54,EN,,0,0,0,,Now it's going to see if there are any other answers\nDialogue: 0,0:36:55.07,0:36:57.32,EN,,0,0,0,,it doesn't know a priori there's only one answer.\nDialogue: 0,0:36:57.81,0:36:59.90,EN,,0,0,0,,So it's sitting here checking all possibilities,\nDialogue: 0,0:37:00.41,0:37:02.54,EN,,0,0,0,,and it says, no more. Done.\nDialogue: 0,0:37:03.16,0:37:05.07,EN,,0,0,0,,So there I've used those rules like a procedure.\nDialogue: 0,0:37:05.21,0:37:09.05,EN,,0,0,0,,Or remember the whole point is that I can ask different kinds of questions.\nDialogue: 0,0:37:10.22,0:37:11.07,EN,,0,0,0,,I could say\nDialogue: 0,0:37:18.56,0:37:24.59,EN,,0,0,0,,merge to form, let's see, how about 2 and a.\nDialogue: 0,0:37:24.59,0:37:27.90,EN,,0,0,0,,Some list of two elements which I know starts with 2,\nDialogue: 0,0:37:29.37,0:37:31.26,EN,,0,0,0,,and the other thing I don't know,\nDialogue: 0,0:37:33.05,0:37:35.04,EN,,0,0,0,,and x and some other list\nDialogue: 0,0:37:36.48,0:37:39.51,EN,,0,0,0,,merge to form a 1, 2, 3 and 4.\nDialogue: 0,0:37:42.76,0:37:44.11,EN,,0,0,0,,So now it's going to think about that.\nDialogue: 0,0:37:44.59,0:37:49.40,EN,,0,0,0,,It's got to find--  so it found one possibility.\nDialogue: 0,0:37:49.52,0:37:52.46,EN,,0,0,0,,It said a could be 3, and x could be the list 1, 4.\nDialogue: 0,0:37:53.72,0:37:55.16,EN,,0,0,0,,And now, again, it's got to check\nDialogue: 0,0:37:56.56,0:37:57.71,EN,,0,0,0,,because it doesn't a priori know\nDialogue: 0,0:37:57.74,0:38:00.30,EN,,0,0,0,,that there aren't any other possibilities going on.\nDialogue: 0,0:38:03.68,0:38:06.57,EN,,0,0,0,,Or like I said,\nDialogue: 0,0:38:07.00,0:38:09.84,EN,,0,0,0,,I could say something like merge to form,\nDialogue: 0,0:38:10.54,0:38:17.55,EN,,0,0,0,,like, what and what else merge to form 1, 2, 3, 4, 5?\nDialogue: 0,0:38:23.68,0:38:25.53,EN,,0,0,0,,Now it's going to think about that.\nDialogue: 0,0:38:28.49,0:38:30.31,EN,,0,0,0,,And there are a lot of answers that it might get.\nDialogue: 0,0:38:35.18,0:38:38.57,EN,,0,0,0,,And what you see is here you're really paying the price of slowness.\nDialogue: 0,0:38:42.21,0:38:43.88,EN,,0,0,0,,And kind of for three reasons.\nDialogue: 0,0:38:43.88,0:38:46.22,EN,,0,0,0,,One is that this language is doubly interpreted.\nDialogue: 0,0:38:47.63,0:38:49.72,EN,,0,0,0,,Whereas in a real implementation,\nDialogue: 0,0:38:49.76,0:38:52.04,EN,,0,0,0,,you would go compile this down to primitive operations.\nDialogue: 0,0:38:52.19,0:38:53.87,EN,,0,0,0,,The other reason is that\nDialogue: 0,0:38:53.88,0:38:58.11,EN,,0,0,0,,this particular algorithm for merges is doubly recursive.\nDialogue: 0,0:38:58.38,0:39:00.06,EN,,0,0,0,,So it's going to take a very long time.\nDialogue: 0,0:39:01.02,0:39:04.33,EN,,0,0,0,,And eventually, this is going to go through\nDialogue: 0,0:39:04.59,0:39:07.13,EN,,0,0,0,,and find-- find what?\nDialogue: 0,0:39:07.13,0:39:08.73,EN,,0,0,0,,Two to the fifth possible answers.\nDialogue: 0,0:39:12.14,0:39:14.96,EN,,0,0,0,,And you see they come out in some fairly arbitrary order,\nDialogue: 0,0:39:15.00,0:39:18.14,EN,,0,0,0,,depending on which order it's going to be trying these rules.\nDialogue: 0,0:39:20.16,0:39:22.11,EN,,0,0,0,,In fact, what we're going to do when they edit the videotape\nDialogue: 0,0:39:22.40,0:39:23.48,EN,,0,0,0,,is speed all this up.\nDialogue: 0,0:39:24.08,0:39:26.60,EN,,0,0,0,,Don't you like taking out these waits?\nDialogue: 0,0:39:26.60,0:39:28.27,EN,,0,0,0,,And don't you wish you could do that in your demos?\nDialogue: 0,0:39:29.48,0:39:34.24,EN,,0,0,0,,Anyway, it's still grinding there.\nDialogue: 0,0:39:39.22,0:39:41.12,EN,,0,0,0,,Anyway, there are 32 possibilities--\nDialogue: 0,0:39:41.13,0:39:42.63,EN,,0,0,0,,we won't wait for it to print out all of them.\nDialogue: 0,0:39:47.85,0:39:50.44,EN,,0,0,0,,OK, so the needs of abstraction in this language are rules.\nDialogue: 0,0:39:53.53,0:39:58.01,EN,,0,0,0,,So we take some bunch of things that are put together with logic\nDialogue: 0,0:39:59.12,0:40:00.08,EN,,0,0,0,,and we name them.\nDialogue: 0,0:40:00.35,0:40:03.41,EN,,0,0,0,,And you can think of that as naming a particular pattern of logic.\nDialogue: 0,0:40:03.41,0:40:04.54,EN,,0,0,0,,Or you can think of that as saying,\nDialogue: 0,0:40:04.56,0:40:06.75,EN,,0,0,0,,if you want to deduce some conclusion,\nDialogue: 0,0:40:07.90,0:40:09.52,EN,,0,0,0,,you can apply those rules of logic.\nDialogue: 0,0:40:10.66,0:40:13.20,EN,,0,0,0,,And those are three elements of this language.\nDialogue: 0,0:40:13.42,0:40:14.56,EN,,0,0,0,,Let's break now,\nDialogue: 0,0:40:14.60,0:40:16.59,EN,,0,0,0,,and then we'll talk about how it's actually implemented.\nDialogue: 0,0:40:23.61,0:40:28.84,EN,,0,0,0,,AUDIENCE: Does using LISP value primitive or whatever interfere with your means\nDialogue: 0,0:40:29.15,0:40:30.64,EN,,0,0,0,,both directions on a query?\nDialogue: 0,0:40:31.77,0:40:34.48,EN,,0,0,0,,PROFESSOR: OK, that's a-- the question is,\nDialogue: 0,0:40:35.08,0:40:36.92,EN,,0,0,0,,does using LISP value interfere\nDialogue: 0,0:40:37.53,0:40:40.09,EN,,0,0,0,,with the ability to go both directions on the query?\nDialogue: 0,0:40:40.09,0:40:42.81,EN,,0,0,0,,We haven't really talked about the implementation yet,\nDialogue: 0,0:40:43.68,0:40:45.52,EN,,0,0,0,,but the answer is, yes, it can.\nDialogue: 0,0:40:46.89,0:40:50.20,EN,,0,0,0,,In general, as we'll see at the end--\nDialogue: 0,0:40:50.22,0:40:52.17,EN,,0,0,0,,although I really won't to go into details--\nDialogue: 0,0:40:53.21,0:40:59.36,EN,,0,0,0,,it's fairly complicated, especially when you use either not or LISP value--\nDialogue: 0,0:40:59.55,0:41:02.89,EN,,0,0,0,,or actually, if you use anything besides only and,\nDialogue: 0,0:41:04.12,0:41:08.19,EN,,0,0,0,,it becomes very complicated to say when these things will work.\nDialogue: 0,0:41:08.20,0:41:10.36,EN,,0,0,0,,They won't work quite in all situations.\nDialogue: 0,0:41:10.36,0:41:13.39,EN,,0,0,0,,I'll talk about that at the end of the second half today.\nDialogue: 0,0:41:14.30,0:41:15.84,EN,,0,0,0,,But the answer to your question is, yes,\nDialogue: 0,0:41:16.19,0:41:19.21,EN,,0,0,0,,by dragging in a lot more power from LISP value,\nDialogue: 0,0:41:19.40,0:41:23.77,EN,,0,0,0,,you lose some of the principal power of logic programming.\nDialogue: 0,0:41:24.17,0:41:25.56,EN,,0,0,0,,That's a trade-off that you have to make.\nDialogue: 0,0:41:28.48,0:41:29.39,EN,,0,0,0,,OK, let's take a break.\nDialogue: 0,0:00:00.00,0:00:02.67,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.70,0:00:10.27,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:10.28,0:00:15.24,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 I\nDialogue: 0,0:00:18.27,0:00:19.68,Default,,0,0,0,,教授：上节课中 我们学习了\nDialogue: 0,0:00:19.72,0:00:21.26,Default,,0,0,0,,如何构造语言\nDialogue: 0,0:00:22.41,0:00:25.88,Default,,0,0,0,,核心点就是 像Lisp这样的求值器\nDialogue: 0,0:00:26.08,0:00:27.58,Default,,0,0,0,,有两个主要部分\nDialogue: 0,0:00:27.58,0:00:28.40,Default,,0,0,0,,一个是EVAL\nDialogue: 0,0:00:31.04,0:00:37.42,Default,,0,0,0,,EVAL接受一个表达式EXP和环境ENV\nDialogue: 0,0:00:38.91,0:00:44.44,Default,,0,0,0,,然后返回一个过程和相关的实际参数\nDialogue: 0,0:00:45.42,0:00:47.05,Default,,0,0,0,,并把它们传递给APPLY\nDialogue: 0,0:00:49.41,0:00:51.29,Default,,0,0,0,,APPLY接收这些过程和实际参数\nDialogue: 0,0:00:51.69,0:00:55.12,Default,,0,0,0,,通常来说 APPLY会返回另一个表达式\nDialogue: 0,0:00:55.39,0:00:57.71,Default,,0,0,0,,返回一个在其它环境中求值的表达式\nDialogue: 0,0:00:57.74,0:01:00.00,Default,,0,0,0,,表达式就像这样在EVAL-APPLY之间传递\nDialogue: 0,0:01:00.27,0:01:01.44,Default,,0,0,0,,这就是整个元循环\nDialogue: 0,0:01:01.47,0:01:02.94,Default,,0,0,0,,表达式在这里面循环往复\nDialogue: 0,0:01:03.02,0:01:06.56,Default,,0,0,0,,直到最后求值为基本数据或基本过程\nDialogue: 0,0:01:07.74,0:01:09.24,Default,,0,0,0,,这个循环要做的就是\nDialogue: 0,0:01:09.44,0:01:12.57,Default,,0,0,0,,把语言中的组合手段\nDialogue: 0,0:01:12.59,0:01:14.36,Default,,0,0,0,,和抽象手段展开\nDialogue: 0,0:01:15.02,0:01:17.72,Default,,0,0,0,,比如说在Lisp中 你有一个过程\nDialogue: 0,0:01:17.74,0:01:20.52,Default,,0,0,0,,定义过程是为了\nDialogue: 0,0:01:20.54,0:01:22.57,Default,,0,0,0,,让表达式的计算过程\nDialogue: 0,0:01:22.67,0:01:24.41,Default,,0,0,0,,适用于任意的参数\nDialogue: 0,0:01:25.76,0:01:27.18,Default,,0,0,0,,这就是这里面发生的事情\nDialogue: 0,0:01:27.67,0:01:28.51,Default,,0,0,0,,这就是APPLY做的事\nDialogue: 0,0:01:28.51,0:01:30.68,Default,,0,0,0,,当一个带参数的一般性表达式进入以后\nDialogue: 0,0:01:30.72,0:01:32.70,Default,,0,0,0,,它将其归约为过程体的表达式\nDialogue: 0,0:01:33.05,0:01:34.72,Default,,0,0,0,,如果归约得到的是复合表达式\nDialogue: 0,0:01:34.83,0:01:36.46,Default,,0,0,0,,或者是另外的过程应用\nDialogue: 0,0:01:36.78,0:01:38.44,Default,,0,0,0,,那么这个循环就会不断地进行\nDialogue: 0,0:01:40.33,0:01:44.08,Default,,0,0,0,,这基本上就是 -- 大部分解释器的基本结构了\nDialogue: 0,0:01:45.20,0:01:46.25,Default,,0,0,0,,另外一点就是\nDialogue: 0,0:01:46.28,0:01:47.66,Default,,0,0,0,,一旦你有了一个解释器\nDialogue: 0,0:01:47.69,0:01:49.87,Default,,0,0,0,,你就有了操作这门语言的所有能力\nDialogue: 0,0:01:49.87,0:01:51.52,Default,,0,0,0,,因此你可以让它成为动态作用域\nDialogue: 0,0:01:51.84,0:01:54.56,Default,,0,0,0,,你也可以引入正则序求值\nDialogue: 0,0:01:54.59,0:01:56.48,Default,,0,0,0,,你也可以为语言添加新的形式\nDialogue: 0,0:01:56.86,0:01:57.50,Default,,0,0,0,,想怎么样都行\nDialogue: 0,0:01:57.58,0:01:58.62,Default,,0,0,0,,或者更一般地说\nDialogue: 0,0:01:58.76,0:02:01.32,Default,,0,0,0,,这种元语言抽象的概念\nDialogue: 0,0:02:02.64,0:02:06.01,Default,,0,0,0,,它告诉我们 作为一名软件工程师\nDialogue: 0,0:02:07.61,0:02:10.52,Default,,0,0,0,,从广义的“工程师”的角度来看\nDialogue: 0,0:02:11.39,0:02:13.88,Default,,0,0,0,,有时你可以通过发明新的语言\nDialogue: 0,0:02:14.96,0:02:17.16,Default,,0,0,0,,来获得控制复杂度的能力\nDialogue: 0,0:02:18.01,0:02:20.81,Default,,0,0,0,,一种思考计算机程序设计的方法就是\nDialogue: 0,0:02:21.55,0:02:26.27,Default,,0,0,0,,它只是偶然地让计算机执行某事儿\nDialogue: 0,0:02:26.44,0:02:28.97,Default,,0,0,0,,计算机程序的主要工作却是\nDialogue: 0,0:02:29.00,0:02:32.52,Default,,0,0,0,,用来表达和交换想法\nDialogue: 0,0:02:33.16,0:02:34.04,Default,,0,0,0,,有时\nDialogue: 0,0:02:34.89,0:02:36.62,Default,,0,0,0,,当我们想要表达新的想法时\nDialogue: 0,0:02:36.65,0:02:38.73,Default,,0,0,0,,我们就想要发明新的模式来表达它们\nDialogue: 0,0:02:39.82,0:02:44.99,Default,,0,0,0,,那么 今天我们就将按照这个框架来创建新语言\nDialogue: 0,0:02:45.73,0:02:48.00,Default,,0,0,0,,一旦我们了解了解释器的基本结构\nDialogue: 0,0:02:48.03,0:02:50.27,Default,,0,0,0,,我们就可以按意愿来构造任意的语言\nDialogue: 0,0:02:50.83,0:02:53.21,Default,,0,0,0,,比如说 我们可以构造Pascal（的解释器）\nDialogue: 0,0:02:54.37,0:02:55.15,Default,,0,0,0,,以及\nDialogue: 0,0:02:56.17,0:02:58.19,Default,,0,0,0,,我们需要操心语法的表示与解析\nDialogue: 0,0:02:58.19,0:03:00.51,Default,,0,0,0,,还有一大堆的编译器优化\nDialogue: 0,0:03:01.12,0:03:03.29,Default,,0,0,0,,还有一些人会这样做\nDialogue: 0,0:03:03.85,0:03:07.60,Default,,0,0,0,,但是就在我们所讨论的抽象层次来说\nDialogue: 0,0:03:08.04,0:03:10.99,Default,,0,0,0,,一个Pascal语言的解释器看起来\nDialogue: 0,0:03:12.03,0:03:13.76,Default,,0,0,0,,跟Gerry教授上节课所讲的大同小异\nDialogue: 0,0:03:15.02,0:03:18.96,Default,,0,0,0,,但是今天 我们要构建一门与众不同的语言\nDialogue: 0,0:03:20.51,0:03:22.81,Default,,0,0,0,,这门语言\nDialogue: 0,0:03:23.05,0:03:26.04,Default,,0,0,0,,不推荐你用过程式的思维来思考程序设计\nDialogue: 0,0:03:26.24,0:03:27.64,Default,,0,0,0,,而是用一种非常不同的方式\nDialogue: 0,0:03:29.09,0:03:31.02,Default,,0,0,0,,今天的课程呢\nDialogue: 0,0:03:31.74,0:03:34.64,Default,,0,0,0,,将会在两个层次中同时进行\nDialogue: 0,0:03:34.81,0:03:35.52,Default,,0,0,0,,一方面\nDialogue: 0,0:03:35.90,0:03:37.71,Default,,0,0,0,,我会向大家介绍这门语言是如何使用的\nDialogue: 0,0:03:38.96,0:03:41.08,Default,,0,0,0,,另一方面呢 我会带领大家实现这门语言\nDialogue: 0,0:03:41.32,0:03:42.96,Default,,0,0,0,,我们将会用Lisp来实现\nDialogue: 0,0:03:42.99,0:03:43.90,Default,,0,0,0,,并观察它的运行原理\nDialogue: 0,0:03:44.04,0:03:48.25,Default,,0,0,0,,你应该在两个层次上学到知识\nDialogue: 0,0:03:48.68,0:03:53.00,Default,,0,0,0,,首先要认识到 语言之间可以有多么地“不同”\nDialogue: 0,0:03:53.79,0:03:58.14,Default,,0,0,0,,如果你认为Fortran和Lisp算是天差地别的话\nDialogue: 0,0:03:58.24,0:03:59.36,Default,,0,0,0,,那就小巫见大巫了\nDialogue: 0,0:04:01.56,0:04:03.68,Default,,0,0,0,,其次\nDialogue: 0,0:04:03.77,0:04:06.54,Default,,0,0,0,,甚至于在这门与众不同的语言中\nDialogue: 0,0:04:07.36,0:04:09.52,Default,,0,0,0,,这门既不讨论函数\nDialogue: 0,0:04:09.92,0:04:11.64,Default,,0,0,0,,也没有过程的语言中\nDialogue: 0,0:04:12.20,0:04:15.72,Default,,0,0,0,,其中也有基本的EVAL-APPLY循环\nDialogue: 0,0:04:16.19,0:04:19.98,Default,,0,0,0,,也就是对组合手段和抽象手段的展开\nDialogue: 0,0:04:20.95,0:04:24.68,Default,,0,0,0,,第三点 是一个不太重要但非常优雅的技术技巧\nDialogue: 0,0:04:24.89,0:04:28.52,Default,,0,0,0,,就是如何巧妙地使用流来避免回溯\nDialogue: 0,0:04:32.33,0:04:34.40,Default,,0,0,0,,好吧 我说过这门语言与众不同\nDialogue: 0,0:04:35.86,0:04:36.64,Default,,0,0,0,,为了解释这点\nDialogue: 0,0:04:37.05,0:04:42.81,Default,,0,0,0,,让我们回到这门课最初的理念上\nDialogue: 0,0:04:43.26,0:04:46.54,Default,,0,0,0,,就是要区别\nDialogue: 0,0:04:46.72,0:04:49.52,Default,,0,0,0,,数学中“陈述性”的知识\nDialogue: 0,0:04:50.19,0:04:54.14,Default,,0,0,0,,比如平方根的定义就是一条数学事实\nDialogue: 0,0:04:55.48,0:04:59.56,Default,,0,0,0,,而计算机科学讨论的是“如何做”的知识\nDialogue: 0,0:04:59.76,0:05:04.59,Default,,0,0,0,,“什么是平方根”和“如何计算平方根”是不同的\nDialogue: 0,0:05:05.97,0:05:07.07,Default,,0,0,0,,我们是从这里开始的\nDialogue: 0,0:05:08.51,0:05:09.52,Default,,0,0,0,,如果我们能够通过某种方式\nDialogue: 0,0:05:09.88,0:05:12.16,Default,,0,0,0,,弥合这种差距 岂不是更好么？\nDialogue: 0,0:05:12.81,0:05:16.43,Default,,0,0,0,,我们创建一门这样的语言\nDialogue: 0,0:05:16.67,0:05:21.61,Default,,0,0,0,,以声明式的方式、用数学事实来完成计算\nDialogue: 0,0:05:22.38,0:05:25.50,Default,,0,0,0,,你用这种该语言来指定事实\nDialogue: 0,0:05:27.69,0:05:28.88,Default,,0,0,0,,你告诉它\nDialogue: 0,0:05:28.88,0:05:29.96,Default,,0,0,0,,什么是事实\nDialogue: 0,0:05:30.95,0:05:33.07,Default,,0,0,0,,而当你需要一个答案时\nDialogue: 0,0:05:33.21,0:05:36.38,Default,,0,0,0,,语言已经自动地内建了\nDialogue: 0,0:05:37.60,0:05:39.45,Default,,0,0,0,,有关于“如何做”的一般性知识\nDialogue: 0,0:05:39.47,0:05:40.64,Default,,0,0,0,,这样它就可以根据你给出的事实\nDialogue: 0,0:05:40.89,0:05:42.83,Default,,0,0,0,,自行地演进这些方法\nDialogue: 0,0:05:43.31,0:05:46.12,Default,,0,0,0,,通过你给定的事实和某种一般性的逻辑规则\nDialogue: 0,0:05:49.33,0:05:50.54,Default,,0,0,0,,就比如说\nDialogue: 0,0:05:52.06,0:05:55.12,Default,,0,0,0,,我会告诉程序下述事实\nDialogue: 0,0:05:56.00,0:06:07.08,Default,,0,0,0,,我告诉它 (SON-OF ADAM ABEL)\nDialogue: 0,0:06:08.92,0:06:16.51,Default,,0,0,0,,同时告诉它 (SON-OF ADAM CAIN)\nDialogue: 0,0:06:17.66,0:06:25.08,Default,,0,0,0,,以及 (SON-OF CAIN ENOCH)\nDialogue: 0,0:06:27.79,0:06:34.89,Default,,0,0,0,,还有 (SON-OF ENOCH IRAD)\nDialogue: 0,0:06:37.02,0:06:40.72,Default,,0,0,0,,以及《创世纪》章节中的其它人物\nDialogue: 0,0:06:41.15,0:06:43.18,Default,,0,0,0,,最后终止于ADAH\nDialogue: 0,0:06:43.32,0:06:46.78,Default,,0,0,0,,这些是从ADAH到CAIN的家谱\nDialogue: 0,0:06:48.44,0:06:50.67,Default,,0,0,0,,总之 一旦你指明了这些事实\nDialogue: 0,0:06:52.35,0:06:53.40,Default,,0,0,0,,你就可以提出问题\nDialogue: 0,0:06:53.51,0:06:55.05,Default,,0,0,0,,你可以对语言系统发问\nDialogue: 0,0:06:56.06,0:06:59.29,Default,,0,0,0,,谁是ADAM的孩子？\nDialogue: 0,0:07:00.42,0:07:04.91,Default,,0,0,0,,可以很容易地想到一个通用搜索程序\nDialogue: 0,0:07:05.52,0:07:06.96,Default,,0,0,0,,它会遍历所有的事实\nDialogue: 0,0:07:07.00,0:07:09.26,Default,,0,0,0,,然后回答：“哦 有两个答案”\nDialogue: 0,0:07:09.29,0:07:10.44,Default,,0,0,0,,ABEL是ADAM的孩子\nDialogue: 0,0:07:10.68,0:07:12.17,Default,,0,0,0,,CAIN也是ADAM的孩子\nDialogue: 0,0:07:14.14,0:07:14.97,Default,,0,0,0,,你也可以这样问\nDialogue: 0,0:07:15.07,0:07:16.89,Default,,0,0,0,,基于同样的事实\nDialogue: 0,0:07:18.04,0:07:19.95,Default,,0,0,0,,CAIN是谁的孩子？\nDialogue: 0,0:07:21.95,0:07:27.02,Default,,0,0,0,,你们就会想到生成另外一个略微不同的搜索程序\nDialogue: 0,0:07:27.92,0:07:29.21,Default,,0,0,0,,它也会遍历所有的事实\nDialogue: 0,0:07:29.45,0:07:33.05,Default,,0,0,0,,检查谁的孩子是CAIN\nDialogue: 0,0:07:33.52,0:07:34.44,Default,,0,0,0,,发现结果是ADAM\nDialogue: 0,0:07:35.89,0:07:36.99,Default,,0,0,0,,你也可以问\nDialogue: 0,0:07:38.01,0:07:41.40,Default,,0,0,0,,CAIN和ENOCH之间是什么关系？\nDialogue: 0,0:07:42.07,0:07:45.08,Default,,0,0,0,,又会生成另一个略微不同的搜索程序\nDialogue: 0,0:07:46.34,0:07:48.16,Default,,0,0,0,,得到的结果是亲子关系（SON-OF）\nDialogue: 0,0:07:52.88,0:07:54.92,Default,,0,0,0,,在这个非常简单的例子中\nDialogue: 0,0:07:56.14,0:07:58.44,Default,,0,0,0,,我们发现 即使是单条事实\nDialogue: 0,0:07:58.81,0:08:01.52,Default,,0,0,0,,比如说 (SON-OF ADAM CAIN)\nDialogue: 0,0:08:02.84,0:08:05.52,Default,,0,0,0,,可以被用来回答不同种类的问题\nDialogue: 0,0:08:06.52,0:08:08.12,Default,,0,0,0,,你可以问CAIN是谁的孩子？\nDialogue: 0,0:08:08.14,0:08:10.92,Default,,0,0,0,,你也可以问ADAM的孩子是谁？\nDialogue: 0,0:08:10.94,0:08:12.86,Default,,0,0,0,,你也可以问ADAM和CAIN之间的关系是什么？\nDialogue: 0,0:08:12.88,0:08:14.48,Default,,0,0,0,,这些由不同的传统程序\nDialogue: 0,0:08:15.53,0:08:18.54,Default,,0,0,0,,所解答的不同的问题\nDialogue: 0,0:08:18.68,0:08:20.72,Default,,0,0,0,,都基于同样的事实\nDialogue: 0,0:08:22.75,0:08:25.92,Default,,0,0,0,,这正是这种程序设计风格的威力所在\nDialogue: 0,0:08:26.91,0:08:29.50,Default,,0,0,0,,也就是一条陈述性知识\nDialogue: 0,0:08:30.04,0:08:34.01,Default,,0,0,0,,可以作为大量关于“如何做”的各种知识的基础\nDialogue: 0,0:08:34.81,0:08:37.08,Default,,0,0,0,,这跟我们正在编写的过程是不同的\nDialogue: 0,0:08:37.15,0:08:39.55,Default,,0,0,0,,我们编写的过程描述了输入\nDialogue: 0,0:08:39.61,0:08:40.65,Default,,0,0,0,,以及想要的输出\nDialogue: 0,0:08:41.49,0:08:44.70,Default,,0,0,0,,比如说 我们的平方根程序可以完美地回答\nDialogue: 0,0:08:44.76,0:08:47.16,Default,,0,0,0,,144的平方根是多少？\nDialogue: 0,0:08:48.90,0:08:49.77,Default,,0,0,0,,但从原理上来说\nDialogue: 0,0:08:49.82,0:08:52.83,Default,,0,0,0,,平方根的数学定义告诉了你另外的东西\nDialogue: 0,0:08:52.84,0:08:56.43,Default,,0,0,0,,就比如说 17是谁的平方根\nDialogue: 0,0:08:57.59,0:08:59.71,Default,,0,0,0,,这就需要另外一个程序来解答\nDialogue: 0,0:09:01.92,0:09:03.50,Default,,0,0,0,,因此 数学定义\nDialogue: 0,0:09:03.98,0:09:05.12,Default,,0,0,0,,或者更一般地说\nDialogue: 0,0:09:05.53,0:09:10.30,Default,,0,0,0,,你给定的事实 对于问题是没有偏向性的\nDialogue: 0,0:09:10.90,0:09:12.81,Default,,0,0,0,,而我们倾向于编写专门的程序\nDialogue: 0,0:09:12.83,0:09:14.20,Default,,0,0,0,,因为它们是关于“如何做”的知识\nDialogue: 0,0:09:14.24,0:09:16.36,Default,,0,0,0,,倾向于寻找特定的答案\nDialogue: 0,0:09:17.56,0:09:20.12,Default,,0,0,0,,所以这是我们正在讨论的一个特点\nDialogue: 0,0:09:21.81,0:09:22.60,Default,,0,0,0,,然而我们可以更进一步\nDialogue: 0,0:09:23.48,0:09:27.52,Default,,0,0,0,,想象一下 我们可以向语言给定一些事实\nDialogue: 0,0:09:27.71,0:09:29.61,Default,,0,0,0,,现在 我们给它一些推理规则\nDialogue: 0,0:09:30.02,0:09:31.36,Default,,0,0,0,,比如说\nDialogue: 0,0:09:31.95,0:09:36.19,Default,,0,0,0,,这里 我们先用某种语法表示\nDialogue: 0,0:09:36.44,0:09:41.53,Default,,0,0,0,,如果(SON-OF ?X ?Y)成立\nDialogue: 0,0:09:41.68,0:09:45.21,Default,,0,0,0,,在这里 我用问号来标识变量\nDialogue: 0,0:09:45.61,0:09:56.06,Default,,0,0,0,,如果(SON-OF ?X ?Y)和(SON-OF ?Y ?Z)都成立\nDialogue: 0,0:09:58.96,0:10:08.46,Default,,0,0,0,,那么就有(GRANSON ?X ?Z)\nDialogue: 0,0:10:09.32,0:10:13.40,Default,,0,0,0,,想象一下 如果把这条规则告诉机器\nDialogue: 0,0:10:15.00,0:10:17.28,Default,,0,0,0,,那么我们就可以这么来询问\nDialogue: 0,0:10:17.44,0:10:18.68,Default,,0,0,0,,谁是ADAM的孙子？\nDialogue: 0,0:10:20.61,0:10:23.64,Default,,0,0,0,,或者说 IRAD是谁的孙子？\nDialogue: 0,0:10:24.79,0:10:29.08,Default,,0,0,0,,或者从这些信息中尽可能地推断出所有的祖孙关系\nDialogue: 0,0:10:31.13,0:10:35.60,Default,,0,0,0,,我们可以想象 语言知道如何自动求解\nDialogue: 0,0:10:40.22,0:10:45.20,Default,,0,0,0,,好吧 我再举一个更具体一点的例子\nDialogue: 0,0:10:45.77,0:10:51.95,Default,,0,0,0,,这是个用来合并两个有序表的过程\nDialogue: 0,0:10:53.92,0:11:00.27,Default,,0,0,0,,X和Y是两个由数字构成的表\nDialogue: 0,0:11:00.30,0:11:04.20,Default,,0,0,0,,我们可以认为它们是严格升序的表\nDialogue: 0,0:11:04.76,0:11:07.53,Default,,0,0,0,,MERGE会把这两个表\nDialogue: 0,0:11:07.71,0:11:10.38,Default,,0,0,0,,合并成一个有序的表\nDialogue: 0,0:11:11.21,0:11:15.00,Default,,0,0,0,,这个程序非常简单\nDialogue: 0,0:11:15.02,0:11:16.14,Default,,0,0,0,,你们可以轻松地写出来\nDialogue: 0,0:11:16.39,0:11:18.64,Default,,0,0,0,,也就是 如果X为空 那么结果就是Y\nDialogue: 0,0:11:18.86,0:11:20.46,Default,,0,0,0,,如果Y为空 那结果就是X\nDialogue: 0,0:11:21.18,0:11:22.99,Default,,0,0,0,,否则的话 就要比较为首的两个元素\nDialogue: 0,0:11:22.99,0:11:24.46,Default,,0,0,0,,取出X中的第一个元素\nDialogue: 0,0:11:24.84,0:11:26.01,Default,,0,0,0,,以及Y中的第一个元素\nDialogue: 0,0:11:26.81,0:11:31.68,Default,,0,0,0,,把它们当中谁是最小的那一个\nDialogue: 0,0:11:32.83,0:11:36.60,Default,,0,0,0,,CONS在递归地调用MERGE的结果上\nDialogue: 0,0:11:37.87,0:11:39.92,Default,,0,0,0,,要么就是(MERGE (CDR X) Y)\nDialogue: 0,0:11:40.11,0:11:41.61,Default,,0,0,0,,要么就是(MERGE X (CDR Y))\nDialogue: 0,0:11:42.40,0:11:43.96,Default,,0,0,0,,这是标准的程序\nDialogue: 0,0:11:46.47,0:11:48.41,Default,,0,0,0,,我们来考察下其中的逻辑\nDialogue: 0,0:11:48.62,0:11:49.79,Default,,0,0,0,,先不考虑程序\nDialogue: 0,0:11:50.28,0:11:52.76,Default,,0,0,0,,来看看这个过程所基于的逻辑\nDialogue: 0,0:11:53.82,0:11:55.00,Default,,0,0,0,,这其中的逻辑是\nDialogue: 0,0:11:55.02,0:11:57.21,Default,,0,0,0,,如果第一个元素较小\nDialogue: 0,0:11:57.53,0:12:00.00,Default,,0,0,0,,那么最后的结果就是把它\nDialogue: 0,0:12:00.16,0:12:02.12,Default,,0,0,0,,跟递归MERGE的结果CONS起来\nDialogue: 0,0:12:02.84,0:12:04.09,Default,,0,0,0,,让我们试着把\nDialogue: 0,0:12:04.24,0:12:06.41,Default,,0,0,0,,使这个程序运作的逻辑说清楚一点\nDialogue: 0,0:12:08.30,0:12:09.44,Default,,0,0,0,,这是一部分\nDialogue: 0,0:12:10.13,0:12:11.53,Default,,0,0,0,,这段程序\nDialogue: 0,0:12:12.64,0:12:15.26,Default,,0,0,0,,递归地剥离X\nDialogue: 0,0:12:15.66,0:12:17.82,Default,,0,0,0,,如果X中的首元素较小的话\nDialogue: 0,0:12:19.98,0:12:22.54,Default,,0,0,0,,如果要显式地指出其中的逻辑的话\nDialogue: 0,0:12:23.45,0:12:26.49,Default,,0,0,0,,它其实就是演绎推理\nDialogue: 0,0:12:26.72,0:12:32.38,Default,,0,0,0,,其中 如果知道表CDR-X和表Y\nDialogue: 0,0:12:33.29,0:12:35.44,Default,,0,0,0,,能够通过MERGE-TO-FORM形成Z\nDialogue: 0,0:12:37.84,0:12:41.52,Default,,0,0,0,,并且还知道A比Y中的第一个元素小\nDialogue: 0,0:12:43.60,0:12:48.52,Default,,0,0,0,,那么你就知道 如果你把A和CDR-X给CONS起来\nDialogue: 0,0:12:49.74,0:12:51.85,Default,,0,0,0,,得到的结果和Y一起\nDialogue: 0,0:12:52.60,0:12:54.99,Default,,0,0,0,,可以通过MERGE-TO-FORM形成Z\nDialogue: 0,0:12:55.82,0:12:58.09,Default,,0,0,0,,这就是它所基于的逻辑\nDialogue: 0,0:12:58.72,0:12:59.95,Default,,0,0,0,,我没有把它写成程序\nDialogue: 0,0:12:59.96,0:13:02.00,Default,,0,0,0,,我把它写成了某种演绎\nDialogue: 0,0:13:02.03,0:13:04.89,Default,,0,0,0,,正是属于这个特定子句的\nDialogue: 0,0:13:05.21,0:13:07.26,Default,,0,0,0,,它告诉我们可以在这里使用递归\nDialogue: 0,0:13:09.41,0:13:12.78,Default,,0,0,0,,同样地 这里还有些句子来补全其中的逻辑\nDialogue: 0,0:13:14.00,0:13:15.87,Default,,0,0,0,,其它的句子都是基于这些逻辑\nDialogue: 0,0:13:15.92,0:13:18.35,Default,,0,0,0,,由于它们大部分是相同的 我就不细讲了\nDialogue: 0,0:13:19.00,0:13:20.35,Default,,0,0,0,,然后就是终止条件\nDialogue: 0,0:13:20.41,0:13:22.01,Default,,0,0,0,,是用来检查NULL的\nDialogue: 0,0:13:22.03,0:13:24.04,Default,,0,0,0,,其基本想法是 对于任意的X\nDialogue: 0,0:13:24.51,0:13:27.20,Default,,0,0,0,,X和空表可以通过MERGE-TO-FORM形成X\nDialogue: 0,0:13:28.04,0:13:30.86,Default,,0,0,0,,而空表可以和任意的Y通过MERGE-TO-FORM形成Y\nDialogue: 0,0:13:33.36,0:13:38.12,Default,,0,0,0,,这就是一段过程的代码\nDialogue: 0,0:13:38.43,0:13:40.11,Default,,0,0,0,,以及它所基于的逻辑\nDialogue: 0,0:13:41.74,0:13:42.97,Default,,0,0,0,,请注意其中的巨大差异\nDialogue: 0,0:13:45.10,0:13:50.52,Default,,0,0,0,,过程看起来是像这样的：\nDialogue: 0,0:13:50.65,0:13:52.28,Default,,0,0,0,,首先这有一个盒子\nDialogue: 0,0:13:52.86,0:13:55.39,Default,,0,0,0,,我们到目前为止所做的事都有这样的特征\nDialogue: 0,0:13:55.40,0:13:57.69,Default,,0,0,0,,我们有一个盒子 有东西进去 也有东西出来\nDialogue: 0,0:13:58.08,0:13:59.61,Default,,0,0,0,,这儿有个MERGE盒子\nDialogue: 0,0:14:01.29,0:14:03.85,Default,,0,0,0,,输入是X和Y\nDialogue: 0,0:14:04.44,0:14:05.37,Default,,0,0,0,,输出ANS\nDialogue: 0,0:14:07.63,0:14:09.48,Default,,0,0,0,,这是我们所编写的程序的特征\nDialogue: 0,0:14:13.02,0:14:14.66,Default,,0,0,0,,但是规则并不像这样\nDialogue: 0,0:14:14.66,0:14:16.76,Default,,0,0,0,,规则讨论的是关系\nDialogue: 0,0:14:17.92,0:14:24.16,Default,,0,0,0,,也就是在幻灯片中我称作MERGE-TO-FORM的关系\nDialogue: 0,0:14:25.37,0:14:28.76,Default,,0,0,0,,每当我说X和Y通过MERGE-TO-FORM形成Z\nDialogue: 0,0:14:29.00,0:14:32.33,Default,,0,0,0,,这个是一个函数\nDialogue: 0,0:14:32.61,0:14:32.85,Default,,0,0,0,,对吧？\nDialogue: 0,0:14:32.85,0:14:34.41,Default,,0,0,0,,ANS是X和Y的函数\nDialogue: 0,0:14:34.59,0:14:38.19,Default,,0,0,0,,而我这里得到的是三个东西之间的关系\nDialogue: 0,0:14:39.72,0:14:41.32,Default,,0,0,0,,我不会指明\nDialogue: 0,0:14:42.09,0:14:43.77,Default,,0,0,0,,哪个是输入 哪个是输出\nDialogue: 0,0:14:44.20,0:14:47.40,Default,,0,0,0,,我之所以这么说 是因为原理上\nDialogue: 0,0:14:48.64,0:14:50.83,Default,,0,0,0,,我们可以用同样的逻辑规则\nDialogue: 0,0:14:50.84,0:14:52.44,Default,,0,0,0,,来回答相当多的问题\nDialogue: 0,0:14:54.57,0:14:56.30,Default,,0,0,0,,比如 我们可以问\nDialogue: 0,0:14:56.72,0:14:59.05,Default,,0,0,0,,想象一下 如果把这些逻辑规则输入机器\nDialogue: 0,0:14:59.05,0:15:01.20,Default,,0,0,0,,不是输入程序 而是其中依赖的逻辑\nDialogue: 0,0:15:01.40,0:15:03.12,Default,,0,0,0,,那么 它也就应该回答--\nDialogue: 0,0:15:04.75,0:15:05.52,Default,,0,0,0,,我们可以问它\nDialogue: 0,0:15:06.73,0:15:19.18,Default,,0,0,0,,(1 3 7)和(2 4 8)可以通过MERGE-TO-FORM形成什么？\nDialogue: 0,0:15:20.91,0:15:23.42,Default,,0,0,0,,机器能够回答这样的问题\nDialogue: 0,0:15:23.88,0:15:27.36,Default,,0,0,0,,这同样也是我们的Lisp程序所回答的问题\nDialogue: 0,0:15:28.18,0:15:30.14,Default,,0,0,0,,但这同样的规则\nDialogue: 0,0:15:30.89,0:15:34.80,Default,,0,0,0,,也能够回答像这样的问题：\nDialogue: 0,0:15:36.19,0:15:43.24,Default,,0,0,0,,(1 3 7)和什么能够通过MERGE-TO-FORM形成(1 2 3 4 7 8)\nDialogue: 0,0:15:45.56,0:15:47.80,Default,,0,0,0,,同样的逻辑规则也能够回答这个\nDialogue: 0,0:15:47.84,0:15:49.90,Default,,0,0,0,,但我们编写的过程却无法回答这个问题\nDialogue: 0,0:15:50.80,0:15:52.33,Default,,0,0,0,,又或者 我们可以问\nDialogue: 0,0:15:53.71,0:16:01.12,Default,,0,0,0,,什么和什么能通过MERGE-TO-FORM\nDialogue: 0,0:16:04.28,0:16:12.68,Default,,0,0,0,,哪两个东西可以通过MERGE-TO-FORM形成(1 2 3 4 7 8)？\nDialogue: 0,0:16:13.78,0:16:15.34,Default,,0,0,0,,机器能够进行遍历\nDialogue: 0,0:16:15.84,0:16:17.31,Default,,0,0,0,,如果它能应用这些逻辑规则的话\nDialogue: 0,0:16:17.79,0:16:22.54,Default,,0,0,0,,就能够推断出这个问题所有的2^6种答案\nDialogue: 0,0:16:25.60,0:16:27.69,Default,,0,0,0,,因为可以分别是 (1)和其余的\nDialogue: 0,0:16:27.69,0:16:28.75,Default,,0,0,0,,也可以是 (1 2)和其余的\nDialogue: 0,0:16:28.79,0:16:31.53,Default,,0,0,0,,也可以是(1 3 7)和其余的\nDialogue: 0,0:16:32.01,0:16:33.26,Default,,0,0,0,,有一大堆的答案\nDialogue: 0,0:16:33.41,0:16:37.76,Default,,0,0,0,,但原理上来说 逻辑能推断出所有的答案\nDialogue: 0,0:16:38.55,0:16:42.03,Default,,0,0,0,,因此这里面就有两个巨大的不同\nDialogue: 0,0:16:44.04,0:16:46.00,Default,,0,0,0,,在我们所编写的程序中\nDialogue: 0,0:16:46.54,0:16:48.19,Default,,0,0,0,,不只是Lisp程序\nDialogue: 0,0:16:48.20,0:16:50.56,Default,,0,0,0,,基本上是你们目前编写过的所有程序\nDialogue: 0,0:16:52.03,0:16:53.60,Default,,0,0,0,,用你能叫出名字的程序语言所编写的程序\nDialogue: 0,0:16:54.15,0:16:57.79,Default,,0,0,0,,首先 我们并不准备计算一个函数\nDialogue: 0,0:17:00.62,0:17:02.01,Default,,0,0,0,,我们将要讨论的东西\nDialogue: 0,0:17:02.62,0:17:04.41,Default,,0,0,0,,并不具有输入和输出\nDialogue: 0,0:17:04.41,0:17:05.82,Default,,0,0,0,,我们讨论的是关系\nDialogue: 0,0:17:06.89,0:17:10.00,Default,,0,0,0,,也就是说 原理上 关系是没有方向性的\nDialogue: 0,0:17:11.08,0:17:15.05,Default,,0,0,0,,所以你指明用来回答这个问题的知识\nDialogue: 0,0:17:16.46,0:17:18.41,Default,,0,0,0,,也同样应该能够反过来\nDialogue: 0,0:17:18.43,0:17:21.80,Default,,0,0,0,,让你回答其它的这些问题\nDialogue: 0,0:17:26.60,0:17:29.40,Default,,0,0,0,,其次则是\nDialogue: 0,0:17:29.61,0:17:31.23,Default,,0,0,0,,因为我们讨论的是关系\nDialogue: 0,0:17:32.32,0:17:34.44,Default,,0,0,0,,关系的答案并不唯一\nDialogue: 0,0:17:35.61,0:17:37.00,Default,,0,0,0,,所以在第三个问题中\nDialogue: 0,0:17:37.02,0:17:38.36,Default,,0,0,0,,并没有特定的答案\nDialogue: 0,0:17:38.40,0:17:39.58,Default,,0,0,0,,它有很多的答案\nDialogue: 0,0:17:42.27,0:17:44.64,Default,,0,0,0,,这就是我们的目标\nDialogue: 0,0:17:44.64,0:17:45.90,Default,,0,0,0,,顺便说一下\nDialogue: 0,0:17:46.72,0:17:49.21,Default,,0,0,0,,这种程序设计风格被称作逻辑式程序设计\nDialogue: 0,0:17:50.22,0:17:51.58,Default,,0,0,0,,原因是显而易见的\nDialogue: 0,0:17:56.16,0:18:00.38,Default,,0,0,0,,用逻辑式进行程序设计的那群人之间\nDialogue: 0,0:18:00.40,0:18:03.15,Default,,0,0,0,,流传着几句箴言\nDialogue: 0,0:18:03.16,0:18:04.67,Default,,0,0,0,,他们把逻辑式程序设计的要点归纳为\nDialogue: 0,0:18:04.76,0:18:09.00,Default,,0,0,0,,用逻辑来表达 什么算是“真的”\nDialogue: 0,0:18:10.09,0:18:13.88,Default,,0,0,0,,用逻辑来检测 是否是“真的”\nDialogue: 0,0:18:14.67,0:18:17.24,Default,,0,0,0,,用逻辑来找出这些“真的”\nDialogue: 0,0:18:19.20,0:18:22.09,Default,,0,0,0,,最为大家所熟知的逻辑式程序设计语言\nDialogue: 0,0:18:22.97,0:18:24.78,Default,,0,0,0,,你们可能也听过 -- 叫做Prolog\nDialogue: 0,0:18:25.78,0:18:28.88,Default,,0,0,0,,今天早上我们将要实现的这门语言\nDialogue: 0,0:18:29.82,0:18:32.32,Default,,0,0,0,,是一种查询语言\nDialogue: 0,0:18:32.48,0:18:34.41,Default,,0,0,0,,它基本上就是Prolog的本质了\nDialogue: 0,0:18:35.32,0:18:36.73,Default,,0,0,0,,它可以完成相同的工作\nDialogue: 0,0:18:37.29,0:18:38.73,Default,,0,0,0,,虽然它比Prolog慢得多\nDialogue: 0,0:18:38.73,0:18:40.01,Default,,0,0,0,,这是因为我们是通过Lisp来解释的\nDialogue: 0,0:18:41.90,0:18:44.36,Default,,0,0,0,,而非构造一个专门的编译器\nDialogue: 0,0:18:44.46,0:18:46.62,Default,,0,0,0,,对它的解释 将运行在Lisp解释器之上\nDialogue: 0,0:18:47.51,0:18:49.84,Default,,0,0,0,,除此之外 它可以完成与Prolog相同的事儿\nDialogue: 0,0:18:49.88,0:18:52.78,Default,,0,0,0,,不但同样的能力 也有同样的局限\nDialogue: 0,0:18:55.08,0:18:56.17,Default,,0,0,0,,好吧 先解答一下疑惑\nDialogue: 0,0:19:00.43,0:19:02.84,Default,,0,0,0,,学生：您能再重复一下\nDialogue: 0,0:19:03.48,0:19:06.09,Default,,0,0,0,,用逻辑去寻找的三件事么？\nDialogue: 0,0:19:06.72,0:19:09.84,Default,,0,0,0,,就是那些 找出什么为真 知道什么是真 等等\nDialogue: 0,0:19:09.84,0:19:10.52,Default,,0,0,0,,教授：好的\nDialogue: 0,0:19:10.56,0:19:15.74,Default,,0,0,0,,这算是程序员的某种“教义问答”\nDialogue: 0,0:19:15.85,0:19:19.16,Default,,0,0,0,,我们用逻辑来表达怎么算是“真的”\nDialogue: 0,0:19:20.80,0:19:21.79,Default,,0,0,0,,就像这些规则一样\nDialogue: 0,0:19:22.61,0:19:25.56,Default,,0,0,0,,我们用逻辑来检测某事是否是“真的”\nDialogue: 0,0:19:25.60,0:19:27.76,Default,,0,0,0,,但在这里我没有回答这个问题\nDialogue: 0,0:19:28.55,0:19:29.29,Default,,0,0,0,,我可以问\nDialogue: 0,0:19:29.68,0:19:32.14,Default,,0,0,0,,在这里我可以这样来问\nDialogue: 0,0:19:33.26,0:19:36.56,Default,,0,0,0,,(1 3 7)和(2 4 8)是否能够\nDialogue: 0,0:19:36.91,0:19:40.38,Default,,0,0,0,,通过MERGE-TO-FORM形成(1 2 6 19)\nDialogue: 0,0:19:41.12,0:19:44.68,Default,,0,0,0,,同样的逻辑规则会告诉我们不行\nDialogue: 0,0:19:45.69,0:19:47.93,Default,,0,0,0,,这里 我使用逻辑来检测是否为真\nDialogue: 0,0:19:48.28,0:19:50.48,Default,,0,0,0,,然后 我们也可以使用逻辑来找出为真的东西\nDialogue: 0,0:20:04.46,0:20:05.16,Default,,0,0,0,,休息一下吧\nDialogue: 0,0:20:06.13,0:20:17.02,Default,,0,0,0,,[音乐]\nDialogue: 0,0:20:17.05,0:20:20.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:20:47.59,0:20:51.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:20:51.07,0:20:55.60,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:20:55.63,0:21:00.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 I\nDialogue: 0,0:21:03.24,0:21:04.97,Default,,0,0,0,,教授：让我们继续来看一看\nDialogue: 0,0:21:05.84,0:21:08.44,Default,,0,0,0,,这个查询语言及其操作\nDialogue: 0,0:21:10.52,0:21:11.84,Default,,0,0,0,,首先需要注意到\nDialogue: 0,0:21:12.24,0:21:14.14,Default,,0,0,0,,当我建立好那个小型的圣经数据库后\nDialogue: 0,0:21:14.16,0:21:17.24,Default,,0,0,0,,我们就能够针对一系列的事实\nDialogue: 0,0:21:17.48,0:21:19.92,Default,,0,0,0,,以关系的方式来向这个语言提问\nDialogue: 0,0:21:21.33,0:21:25.15,Default,,0,0,0,,因此 我们先来陈述一些事实\nDialogue: 0,0:21:26.06,0:21:29.68,Default,,0,0,0,,这是波士顿一家高科技公司的\nDialogue: 0,0:21:30.08,0:21:32.62,Default,,0,0,0,,一小部分人事档案\nDialogue: 0,0:21:33.05,0:21:36.80,Default,,0,0,0,,这部分档案是Ben Bitdiddle的\nDialogue: 0,0:21:37.50,0:21:41.95,Default,,0,0,0,,Bitdiddle是这家公司的计算机向导\nDialogue: 0,0:21:42.84,0:21:45.80,Default,,0,0,0,,他是这家公司的低薪向导\nDialogue: 0,0:21:46.42,0:21:48.78,Default,,0,0,0,,他的上司是Oliver Warbucks\nDialogue: 0,0:21:49.28,0:21:50.70,Default,,0,0,0,,这里是他的住址\nDialogue: 0,0:21:52.15,0:21:56.54,Default,,0,0,0,,我们按照这样的格式给出信息：职务、薪水、上司、住址\nDialogue: 0,0:21:57.56,0:21:59.25,Default,,0,0,0,,还有一些其它的约定\nDialogue: 0,0:21:59.25,0:22:02.22,Default,,0,0,0,,这里的COMPUTER表示BEN在计算机分部工作\nDialogue: 0,0:22:02.76,0:22:04.94,Default,,0,0,0,,而他在这个分部的工作是向导\nDialogue: 0,0:22:05.66,0:22:07.15,Default,,0,0,0,,这里是其他人的\nDialogue: 0,0:22:07.16,0:22:12.28,Default,,0,0,0,,Alyssa P.Hacker是一名计算机程序员\nDialogue: 0,0:22:13.36,0:22:14.60,Default,,0,0,0,,她的上司是Ben\nDialogue: 0,0:22:15.21,0:22:16.54,Default,,0,0,0,,而她住在Cambridge\nDialogue: 0,0:22:17.55,0:22:19.42,Default,,0,0,0,,Ben手下的另外一个程序员\nDialogue: 0,0:22:20.03,0:22:21.44,Default,,0,0,0,,叫做Lem E. Tweakit\nDialogue: 0,0:22:22.82,0:22:26.73,Default,,0,0,0,,实习程序员 Louis Reasoner\nDialogue: 0,0:22:27.42,0:22:28.62,Default,,0,0,0,,在Alyssa手下工作\nDialogue: 0,0:22:30.10,0:22:35.45,Default,,0,0,0,,公司里的“大老板”不为任何人工作\nDialogue: 0,0:22:36.81,0:22:38.11,Default,,0,0,0,,这就是Oliver Warbucks的档案了\nDialogue: 0,0:22:38.11,0:22:39.31,Default,,0,0,0,,我们将要做的就是\nDialogue: 0,0:22:40.94,0:22:43.66,Default,,0,0,0,,对这个小型的世界提问\nDialogue: 0,0:22:44.97,0:22:48.40,Default,,0,0,0,,这将是我们进行逻辑运算的样本世界\nDialogue: 0,0:22:51.42,0:22:54.96,Default,,0,0,0,,我再最后一次强调一下\nDialogue: 0,0:22:55.60,0:22:58.20,Default,,0,0,0,,你们应该从这门课中学到的最重要的知识\nDialogue: 0,0:22:58.80,0:23:01.66,Default,,0,0,0,,也就是 当别人向你介绍语言时\nDialogue: 0,0:23:02.25,0:23:04.43,Default,,0,0,0,,你要问：“它的基本元素是什么？”\nDialogue: 0,0:23:06.12,0:23:07.79,Default,,0,0,0,,组合的手段有哪些？\nDialogue: 0,0:23:14.70,0:23:16.40,Default,,0,0,0,,如何把基本元素组织在一起\nDialogue: 0,0:23:16.67,0:23:19.37,Default,,0,0,0,,然后把它们抽象出来？\nDialogue: 0,0:23:19.96,0:23:21.93,Default,,0,0,0,,如何抽象这些复合元素\nDialogue: 0,0:23:24.68,0:23:27.58,Default,,0,0,0,,以便于你能够复用它们构造更复杂的东西？\nDialogue: 0,0:23:29.02,0:23:30.81,Default,,0,0,0,,我已经强调过很多次了\nDialogue: 0,0:23:31.16,0:23:32.48,Default,,0,0,0,,但还是值得重申一遍\nDialogue: 0,0:23:35.00,0:23:36.67,Default,,0,0,0,,记住了么？我们开始了\nDialogue: 0,0:23:36.67,0:23:37.34,Default,,0,0,0,,首先是基本元素\nDialogue: 0,0:23:37.77,0:23:39.44,Default,,0,0,0,,这其中 只有唯一的基本元素\nDialogue: 0,0:23:40.96,0:23:43.20,Default,,0,0,0,,这门语言中的基本元素就是“查询”\nDialogue: 0,0:23:44.14,0:23:45.74,Default,,0,0,0,,一条基本查询\nDialogue: 0,0:23:46.81,0:23:48.25,Default,,0,0,0,,我们先来看几条基本查询\nDialogue: 0,0:23:51.82,0:23:53.02,Default,,0,0,0,,首先 这条查询问的是\nDialogue: 0,0:23:53.10,0:23:54.81,Default,,0,0,0,,“谁是计算机程序员？”\nDialogue: 0,0:23:55.55,0:23:59.88,Default,,0,0,0,,或者可以解释为：找出数据库中\nDialogue: 0,0:24:01.55,0:24:06.14,Default,,0,0,0,,所有JOB栏为COMPUTER PROGRAMMER的事实\nDialogue: 0,0:24:06.64,0:24:08.01,Default,,0,0,0,,这里有一些小语法\nDialogue: 0,0:24:08.47,0:24:10.59,Default,,0,0,0,,不带问号的都是字面量\nDialogue: 0,0:24:11.28,0:24:13.15,Default,,0,0,0,,?X表示X是变量\nDialogue: 0,0:24:13.31,0:24:15.56,Default,,0,0,0,,而这条查询会匹配 比如说 --\nDialogue: 0,0:24:16.03,0:24:19.00,Default,,0,0,0,,Alyssa P. Hacker 是程序员\nDialogue: 0,0:24:19.28,0:24:21.93,Default,,0,0,0,,其中X为Alyssa P. Hacker这条事实\nDialogue: 0,0:24:26.82,0:24:29.98,Default,,0,0,0,,或者更一般地 我可以在一条查询中引入两个变量\nDialogue: 0,0:24:30.75,0:24:31.45,Default,,0,0,0,,我可以问\nDialogue: 0,0:24:31.60,0:24:35.88,Default,,0,0,0,,?X的JOB必须是COMPUTER ?TYPE\nDialogue: 0,0:24:39.34,0:24:41.39,Default,,0,0,0,,也就是会匹配COMPUTER WIZARD\nDialogue: 0,0:24:42.14,0:24:44.28,Default,,0,0,0,,所以这里?TYPE可能会匹配WIZARD\nDialogue: 0,0:24:44.92,0:24:46.46,Default,,0,0,0,,也可能会匹配PROGRAMMER\nDialogue: 0,0:24:47.48,0:24:50.37,Default,,0,0,0,,而?X会匹配不同的东西\nDialogue: 0,0:24:50.37,0:24:52.24,Default,,0,0,0,,但在我们的这个小例子中\nDialogue: 0,0:24:52.25,0:24:55.15,Default,,0,0,0,,数据库中只有三条事实符合那条查询\nDialogue: 0,0:24:59.12,0:25:02.08,Default,,0,0,0,,把语法说得再清楚一点 同样的查询\nDialogue: 0,0:25:05.29,0:25:08.09,Default,,0,0,0,,同样的这条指定了?X的JOB的查询\nDialogue: 0,0:25:09.85,0:25:11.79,Default,,0,0,0,,并不能够与Lewis Reasoner匹配\nDialogue: 0,0:25:11.84,0:25:13.64,Default,,0,0,0,,这是因为我这里所写的\nDialogue: 0,0:25:14.22,0:25:17.74,Default,,0,0,0,,表示要匹配的是由两个符号构成的表\nDialogue: 0,0:25:19.96,0:25:21.96,Default,,0,0,0,,其中首元素必须为单词“COMPUTER”\nDialogue: 0,0:25:22.32,0:25:23.80,Default,,0,0,0,,而第二个可以匹配任意的东西\nDialogue: 0,0:25:25.08,0:25:27.32,Default,,0,0,0,,而Lewis这里的工作描述有三个符号\nDialogue: 0,0:25:27.80,0:25:28.83,Default,,0,0,0,,因此不匹配\nDialogue: 0,0:25:30.34,0:25:32.19,Default,,0,0,0,,你们还需要知道的一种语法是\nDialogue: 0,0:25:35.04,0:25:38.32,Default,,0,0,0,,更具一般性的点记号\nDialogue: 0,0:25:40.17,0:25:42.92,Default,,0,0,0,,这个标准的表记号表示的是\nDialogue: 0,0:25:43.04,0:25:43.82,Default,,0,0,0,,首先这是一个表\nDialogue: 0,0:25:44.12,0:25:47.32,Default,,0,0,0,,它的首元素为单词“COMPUTER”\nDialogue: 0,0:25:47.58,0:25:50.22,Default,,0,0,0,,而其余的部分 我们把它们称作?TYPE\nDialogue: 0,0:25:53.73,0:25:55.50,Default,,0,0,0,,因此这条查询就会匹配上\nDialogue: 0,0:25:56.93,0:25:59.31,Default,,0,0,0,,Lewis的工作是COMPUTER PROGRAMMER TRAINEE\nDialogue: 0,0:25:59.44,0:26:03.29,Default,,0,0,0,,而?TYPE的值将会是这个表的CDR部分\nDialogue: 0,0:26:03.32,0:26:05.64,Default,,0,0,0,,也就是表(PROGRAMMER TRAINEE)\nDialogue: 0,0:26:06.96,0:26:10.46,Default,,0,0,0,,Lisp源码读取器会自动完成对点记号的处理\nDialogue: 0,0:26:15.90,0:26:17.76,Default,,0,0,0,,让我们来实际操作一下\nDialogue: 0,0:26:17.76,0:26:20.51,Default,,0,0,0,,我将向语言系统输入这些查询\nDialogue: 0,0:26:20.76,0:26:21.82,Default,,0,0,0,,然后得到结果\nDialogue: 0,0:26:22.54,0:26:24.48,Default,,0,0,0,,让我们在计算机中试试\nDialogue: 0,0:26:25.18,0:26:26.51,Default,,0,0,0,,我可以问\nDialogue: 0,0:26:27.34,0:26:28.88,Default,,0,0,0,,谁在计算机分部工作？\nDialogue: 0,0:26:30.00,0:26:38.22,Default,,0,0,0,,(JOB ?X (COMPUTER . ?Y)\nDialogue: 0,0:26:39.73,0:26:41.48,Default,,0,0,0,,哑变量的名字并不重要\nDialogue: 0,0:26:42.76,0:26:44.14,Default,,0,0,0,,查询的结果是\nDialogue: 0,0:26:44.41,0:26:45.68,Default,,0,0,0,,有四条记录\nDialogue: 0,0:26:48.65,0:26:50.09,Default,,0,0,0,,我也可以问\nDialogue: 0,0:26:50.56,0:26:52.38,Default,,0,0,0,,大家的上司都是谁？\nDialogue: 0,0:26:52.81,0:26:54.88,Default,,0,0,0,,我输入一条基本查询\nDialogue: 0,0:26:56.52,0:26:59.39,Default,,0,0,0,,(SUPERVISOR ?X ?Y)\nDialogue: 0,0:27:02.56,0:27:05.42,Default,,0,0,0,,这些都是我所知道的上下级关系\nDialogue: 0,0:27:05.54,0:27:08.83,Default,,0,0,0,,或者我也可以问：“谁住在Cambridge？”\nDialogue: 0,0:27:08.83,0:27:09.47,Default,,0,0,0,,我就这么输入：\nDialogue: 0,0:27:10.24,0:27:20.92,Default,,0,0,0,,(ADDRESS ?X (CAMBRIDGE . ?T))\nDialogue: 0,0:27:25.09,0:27:26.89,Default,,0,0,0,,只有一个人住在Cambridge\nDialogue: 0,0:27:30.82,0:27:32.17,Default,,0,0,0,,这些就是基本查询\nDialogue: 0,0:27:32.17,0:27:34.96,Default,,0,0,0,,你们看到的这些 就是与系统的基础交互\nDialogue: 0,0:27:35.29,0:27:39.24,Default,,0,0,0,,你输入一条查询 他输出所有可能的查询\nDialogue: 0,0:27:39.62,0:27:40.65,Default,,0,0,0,,换句话说 也就是\nDialogue: 0,0:27:40.67,0:27:44.16,Default,,0,0,0,,它找出这些变量所有可能的值\nDialogue: 0,0:27:44.19,0:27:45.87,Default,,0,0,0,,不管它是叫X、Y还是T\nDialogue: 0,0:27:46.09,0:27:52.08,Default,,0,0,0,,然后它输出的是用所有可行值实例化该条查询的结果\nDialogue: 0,0:27:52.92,0:27:55.16,Default,,0,0,0,,也就是规则系统那一课讲的“实例化”\nDialogue: 0,0:27:55.16,0:27:58.83,Default,,0,0,0,,用变量所有可能的值来实例化查询\nDialogue: 0,0:27:59.00,0:28:00.35,Default,,0,0,0,,然后输出所有的结果\nDialogue: 0,0:28:01.00,0:28:03.35,Default,,0,0,0,,当然 还有不同的呈现结果的方式\nDialogue: 0,0:28:03.35,0:28:06.01,Default,,0,0,0,,比如说 Prolog就有些不一样\nDialogue: 0,0:28:06.01,0:28:07.44,Default,,0,0,0,,它并不向你返回查询\nDialogue: 0,0:28:07.76,0:28:10.78,Default,,0,0,0,,Prolog会输出X=这个 Y=那个\nDialogue: 0,0:28:10.97,0:28:12.94,Default,,0,0,0,,又或者X=这个 Y=那个\nDialogue: 0,0:28:13.66,0:28:15.48,Default,,0,0,0,,这是使用界面层次的差别\nDialogue: 0,0:28:15.71,0:28:17.05,Default,,0,0,0,,你可以根据你的喜好来决定\nDialogue: 0,0:28:18.97,0:28:19.58,Default,,0,0,0,,我们继续\nDialogue: 0,0:28:21.00,0:28:22.68,Default,,0,0,0,,也就是说 这个语言中的基本元素\nDialogue: 0,0:28:23.39,0:28:24.57,Default,,0,0,0,,只有一个 对吧？\nDialogue: 0,0:28:24.57,0:28:27.23,Default,,0,0,0,,也就是基本查询\nDialogue: 0,0:28:31.31,0:28:32.56,Default,,0,0,0,,来看看组合的手段\nDialogue: 0,0:28:34.33,0:28:37.68,Default,,0,0,0,,我们来考察一下这个语言中的复合查询\nDialogue: 0,0:28:39.77,0:28:40.46,Default,,0,0,0,,比如这条\nDialogue: 0,0:28:41.79,0:28:42.51,Default,,0,0,0,,这条查询是说\nDialogue: 0,0:28:45.05,0:28:48.22,Default,,0,0,0,,列举出所有在计算机分部工作的人\nDialogue: 0,0:28:49.81,0:28:52.00,Default,,0,0,0,,在计算机分部工作的人\nDialogue: 0,0:28:52.54,0:28:53.96,Default,,0,0,0,,以及他们的上司\nDialogue: 0,0:28:56.80,0:28:58.83,Default,,0,0,0,,我使用AND来编写这条查询\nDialogue: 0,0:29:00.22,0:29:04.06,Default,,0,0,0,,(AND (JOB ?X (COMPUTER . ?Y))\nDialogue: 0,0:29:04.92,0:29:06.83,Default,,0,0,0,,(JOB ?X (COMPUTER . ?Y))\nDialogue: 0,0:29:07.56,0:29:10.03,Default,,0,0,0,,并且(SUPERVISOR ?X ?Z)\nDialogue: 0,0:29:11.44,0:29:14.16,Default,,0,0,0,,找出所有在计算机分部工作的人 -- 对应这条\nDialogue: 0,0:29:14.30,0:29:15.88,Default,,0,0,0,,以及它们的上司\nDialogue: 0,0:29:16.46,0:29:17.82,Default,,0,0,0,,注意这条查询中\nDialogue: 0,0:29:18.67,0:29:22.41,Default,,0,0,0,,我引入了三个变量 ?X ?Y 以及 ?Z\nDialogue: 0,0:29:23.58,0:29:28.65,Default,,0,0,0,,并且 这两个?X应该匹配同样的东西\nDialogue: 0,0:29:29.45,0:29:31.16,Default,,0,0,0,,?X被约束在了计算机分部中\nDialogue: 0,0:29:31.31,0:29:33.00,Default,,0,0,0,,并且?X的上司是?Z\nDialogue: 0,0:29:34.81,0:29:35.80,Default,,0,0,0,,我们再来看一条\nDialogue: 0,0:29:37.25,0:29:39.28,Default,,0,0,0,,AND算是一种组合手段\nDialogue: 0,0:29:41.44,0:29:43.96,Default,,0,0,0,,哪些人的薪水超过$30,000？\nDialogue: 0,0:29:45.71,0:29:51.71,Default,,0,0,0,,(AND (SALARY ?P ?A)\nDialogue: 0,0:29:54.59,0:29:57.45,Default,,0,0,0,,而关于?A的要求则是\nDialogue: 0,0:29:57.48,0:30:00.12,Default,,0,0,0,,(LISP-VALUE > ?A 300000)\nDialogue: 0,0:30:00.60,0:30:03.23,Default,,0,0,0,,这里的LISP-VALUE是一个接口\nDialogue: 0,0:30:04.30,0:30:10.04,Default,,0,0,0,,用来连接查询语言与其底层的Lisp\nDialogue: 0,0:30:10.60,0:30:12.72,Default,,0,0,0,,LISP-VALUE让你能够在查询\nDialogue: 0,0:30:12.75,0:30:16.91,Default,,0,0,0,,中调用任意的Lisp谓词\nDialogue: 0,0:30:17.18,0:30:20.11,Default,,0,0,0,,因为我要用Lisp中的谓词> 所以我用LISP-VALUE\nDialogue: 0,0:30:21.02,0:30:21.75,Default,,0,0,0,,所以这里我用了AND\nDialogue: 0,0:30:21.75,0:30:24.48,Default,,0,0,0,,因此这样就查询出了薪水超过$30000的人\nDialogue: 0,0:30:28.19,0:30:30.03,Default,,0,0,0,,或者这条更复杂的查询\nDialogue: 0,0:30:31.27,0:30:35.02,Default,,0,0,0,,告诉我所有那些 在计算机分部中工作\nDialogue: 0,0:30:36.25,0:30:39.36,Default,,0,0,0,,但他的上司不在计算机分部工作的人\nDialogue: 0,0:30:42.79,0:30:45.51,Default,,0,0,0,,(AND (JOB ?X (COMPUTER . ?Y))\nDialogue: 0,0:30:45.51,0:30:47.32,Default,,0,0,0,,表示?X在计算机分部工作\nDialogue: 0,0:30:47.78,0:30:49.24,Default,,0,0,0,,但是呢\nDialogue: 0,0:30:50.49,0:30:54.25,Default,,0,0,0,,?X的上司?Z\nDialogue: 0,0:30:55.37,0:30:57.87,Default,,0,0,0,,?Z的JOB不是形如(COMPUTER ...)一类的\nDialogue: 0,0:30:59.62,0:31:00.35,Default,,0,0,0,,同样的\nDialogue: 0,0:31:00.51,0:31:02.38,Default,,0,0,0,,这两个?X应该是一致的\nDialogue: 0,0:31:03.20,0:31:05.76,Default,,0,0,0,,而这两个?Z也应该是一致的\nDialogue: 0,0:31:09.39,0:31:11.38,Default,,0,0,0,,你又了解了另一种组合手段 -- NOT\nDialogue: 0,0:31:17.71,0:31:18.67,Default,,0,0,0,,好了 再让我们来试试这些\nDialogue: 0,0:31:20.88,0:31:22.08,Default,,0,0,0,,它同样起效\nDialogue: 0,0:31:22.40,0:31:24.12,Default,,0,0,0,,我可以问计算机：\nDialogue: 0,0:31:26.89,0:31:35.40,Default,,0,0,0,,(AND (JOB ?X (COMPUTER . ?Y)))\nDialogue: 0,0:31:38.84,0:31:45.95,Default,,0,0,0,,另一个条件是(SUPERVISOR ?X ?Z)\nDialogue: 0,0:31:46.83,0:31:49.53,Default,,0,0,0,,我把这条查询输入进去\nDialogue: 0,0:31:51.07,0:31:52.97,Default,,0,0,0,,计算机返回给我们的\nDialogue: 0,0:31:54.00,0:31:58.73,Default,,0,0,0,,计算机利用所有可能的答案把我的查询实例化了\nDialogue: 0,0:31:58.93,0:32:00.08,Default,,0,0,0,,你会发现有很多的答案\nDialogue: 0,0:32:01.69,0:32:02.14,Default,,0,0,0,,好\nDialogue: 0,0:32:02.19,0:32:04.04,Default,,0,0,0,,之所以把这门语言称作“逻辑语言”\nDialogue: 0,0:32:05.21,0:32:06.60,Default,,0,0,0,,是因为这门语言中的组合手段\nDialogue: 0,0:32:06.64,0:32:09.47,Default,,0,0,0,,都是逻辑运算\nDialogue: 0,0:32:09.80,0:32:15.68,Default,,0,0,0,,组合的手段有AND和NOT\nDialogue: 0,0:32:15.96,0:32:17.92,Default,,0,0,0,,以及我还没有告诉你的OR\nDialogue: 0,0:32:18.49,0:32:20.36,Default,,0,0,0,,我还告诉过你LISP-VALUE\nDialogue: 0,0:32:20.72,0:32:24.48,Default,,0,0,0,,当然 虽然它不是一个逻辑运算\nDialogue: 0,0:32:24.51,0:32:26.89,Default,,0,0,0,,但是这个特殊的小技巧把它跟Lisp连接在了一起\nDialogue: 0,0:32:27.34,0:32:28.75,Default,,0,0,0,,让你获得了更多的力量\nDialogue: 0,0:32:29.25,0:32:30.67,Default,,0,0,0,,这些就是组合手段\nDialogue: 0,0:32:32.59,0:32:33.98,Default,,0,0,0,,好 接着是抽象手段\nDialogue: 0,0:32:34.16,0:32:35.21,Default,,0,0,0,,我们想要的是\nDialogue: 0,0:32:38.27,0:32:41.24,Default,,0,0,0,,想让我们回过头来看上一张幻灯片\nDialogue: 0,0:32:42.26,0:32:44.25,Default,,0,0,0,,我们想要把一些非常复杂的东西\nDialogue: 0,0:32:44.46,0:32:48.00,Default,,0,0,0,,比如不与上司在同一部门工作\nDialogue: 0,0:32:48.01,0:32:50.09,Default,,0,0,0,,的人的这种概念\nDialogue: 0,0:32:52.40,0:32:55.10,Default,,0,0,0,,像以前一样 给它命名\nDialogue: 0,0:32:56.09,0:32:58.12,Default,,0,0,0,,如果在某个分部工作的人\nDialogue: 0,0:32:58.17,0:33:00.25,Default,,0,0,0,,他的上司却不在那个分部工作\nDialogue: 0,0:33:00.48,0:33:01.93,Default,,0,0,0,,这就意味着他是个“大腕”\nDialogue: 0,0:33:02.75,0:33:05.13,Default,,0,0,0,,这样 我们就定义一条规则指明\nDialogue: 0,0:33:06.43,0:33:09.16,Default,,0,0,0,,如果?X是某个部门的BIGSHOT\nDialogue: 0,0:33:10.91,0:33:14.68,Default,,0,0,0,,如果他在该部门工作\nDialogue: 0,0:33:16.04,0:33:20.08,Default,,0,0,0,,并且他的上司不在该部门工作\nDialogue: 0,0:33:21.51,0:33:22.94,Default,,0,0,0,,因此这就是我们的抽象手段\nDialogue: 0,0:33:22.94,0:33:23.90,Default,,0,0,0,,这是一条规则\nDialogue: 0,0:33:26.22,0:33:27.58,Default,,0,0,0,,规则由三部分构成\nDialogue: 0,0:33:31.00,0:33:32.48,Default,,0,0,0,,关键字RULE表明这是一条规则\nDialogue: 0,0:33:33.40,0:33:35.48,Default,,0,0,0,,接着是规则的结论\nDialogue: 0,0:33:37.53,0:33:39.07,Default,,0,0,0,,然后是规则的体\nDialogue: 0,0:33:40.00,0:33:41.88,Default,,0,0,0,,你可以把它解读为这样的一段逻辑：\nDialogue: 0,0:33:41.92,0:33:45.15,Default,,0,0,0,,如果你知道规则的体为真\nDialogue: 0,0:33:46.40,0:33:48.72,Default,,0,0,0,,那么你就可以推导出结论为真\nDialogue: 0,0:33:49.45,0:33:53.28,Default,,0,0,0,,或者说为了推断出?X是某个部门的“大腕”\nDialogue: 0,0:33:53.79,0:33:55.71,Default,,0,0,0,,这些条件足够验证了\nDialogue: 0,0:33:57.48,0:33:58.82,Default,,0,0,0,,这就是规则的形式\nDialogue: 0,0:34:03.28,0:34:06.16,Default,,0,0,0,,让我们回过头来看看\nDialogue: 0,0:34:06.73,0:34:07.92,Default,,0,0,0,,课间休息前我举的那个例子\nDialogue: 0,0:34:08.11,0:34:10.68,Default,,0,0,0,,我们来看看 如果用规则来描述会是什么样的\nDialogue: 0,0:34:11.44,0:34:12.84,Default,,0,0,0,,我会抽取出其中的逻辑\nDialogue: 0,0:34:13.08,0:34:15.50,Default,,0,0,0,,并将它们变为这种格式的规则\nDialogue: 0,0:34:18.73,0:34:19.35,Default,,0,0,0,,就有了下面的规则\nDialogue: 0,0:34:19.35,0:34:20.96,Default,,0,0,0,,这就是MERGE-TO-FORM的规则\nDialogue: 0,0:34:21.71,0:34:22.97,Default,,0,0,0,,这个规则是说\nDialogue: 0,0:34:26.28,0:34:29.62,Default,,0,0,0,,'()与?Y可以通过MERGE-TO-FORM形成?Y\nDialogue: 0,0:34:29.62,0:34:30.87,Default,,0,0,0,,这是规则的结论\nDialogue: 0,0:34:33.21,0:34:35.74,Default,,0,0,0,,需要注意的是 这个特定的规则没有体\nDialogue: 0,0:34:36.65,0:34:37.66,Default,,0,0,0,,在这门语言中\nDialogue: 0,0:34:38.11,0:34:40.86,Default,,0,0,0,,没有体的规则总是真的\nDialogue: 0,0:34:41.23,0:34:42.51,Default,,0,0,0,,你总是可以假设它们为真\nDialogue: 0,0:34:45.19,0:34:46.49,Default,,0,0,0,,另一条规则说的是\nDialogue: 0,0:34:46.64,0:34:49.46,Default,,0,0,0,,任意对象与空表进行MERGE-TO-FORM 得到的任然是原物\nDialogue: 0,0:34:49.46,0:34:50.12,Default,,0,0,0,,就是这条\nDialogue: 0,0:34:50.90,0:34:53.55,Default,,0,0,0,,(MERGE-TO-FORM ?Y '() ?Y)\nDialogue: 0,0:34:55.51,0:34:58.40,Default,,0,0,0,,它们对应了我们MERGE过程中的两个终止条件\nDialogue: 0,0:34:58.44,0:34:59.77,Default,,0,0,0,,但我们现在讨论的是逻辑\nDialogue: 0,0:35:00.41,0:35:01.45,Default,,0,0,0,,而非过程\nDialogue: 0,0:35:03.49,0:35:04.48,Default,,0,0,0,,我们还有另外一条规则\nDialogue: 0,0:35:04.83,0:35:08.73,Default,,0,0,0,,描述的是 如果你知道如何MERGE较短的表\nDialogue: 0,0:35:08.91,0:35:09.83,Default,,0,0,0,,那么你就可以把它们结合在一起\nDialogue: 0,0:35:09.83,0:35:14.16,Default,,0,0,0,,这条规则说：如果你有表?X、?Y以及?Z\nDialogue: 0,0:35:14.92,0:35:17.61,Default,,0,0,0,,如果你想推断出(?A . ?X)\nDialogue: 0,0:35:17.63,0:35:19.08,Default,,0,0,0,,这个记法表示(CONS ?A ?X)\nDialogue: 0,0:35:19.48,0:35:22.36,Default,,0,0,0,,或者说首元素是'A、剩余元素是'X的表\nDialogue: 0,0:35:23.16,0:35:27.40,Default,,0,0,0,,由此 如果你想推断(MERGE-TO-FROM (?A . ?X) (?B . ?Y) (?B . ?Z))\nDialogue: 0,0:35:30.36,0:35:33.90,Default,,0,0,0,,毋宁说如果你想要把表(?A ?X)和表(?B ?Y)合并得到\nDialogue: 0,0:35:33.92,0:35:35.85,Default,,0,0,0,,一个以?B为首的表\nDialogue: 0,0:35:36.76,0:35:40.67,Default,,0,0,0,,你想要推断出这个结果 就要满足\nDialogue: 0,0:35:40.91,0:35:44.48,Default,,0,0,0,,不但(MERGE-TP-FORM (?A . ?X) ?Y ?Z)\nDialogue: 0,0:35:45.18,0:35:47.24,Default,,0,0,0,,并且(LISP-VALUE > ?A ?B)\nDialogue: 0,0:35:48.69,0:35:50.59,Default,,0,0,0,,因此当我在合并它们时 ?B会首先出现在表中\nDialogue: 0,0:35:51.82,0:35:54.91,Default,,0,0,0,,这就是简单的把我之前写的伪代码\nDialogue: 0,0:35:55.24,0:35:57.18,Default,,0,0,0,,翻译成逻辑的语言\nDialogue: 0,0:35:57.96,0:36:01.63,Default,,0,0,0,,为了翻译完整 这还里有种情况\nDialogue: 0,0:36:02.88,0:36:05.95,Default,,0,0,0,,(MERGE-TO-FORM (?A . ?X) (?B . ?Y) (?A . ?Z))成立\nDialogue: 0,0:36:06.08,0:36:09.16,Default,,0,0,0,,就需要(MERGE-TO-FORM ?X (?B . ?Y) ?Z)\nDialogue: 0,0:36:09.47,0:36:11.00,Default,,0,0,0,,和(LISP-VALUE > ?B ?A)都成立\nDialogue: 0,0:36:12.19,0:36:15.98,Default,,0,0,0,,我已经把这个用逻辑语言编写的小程序输入计算机了\nDialogue: 0,0:36:16.01,0:36:17.07,Default,,0,0,0,,现在让我们来试着运行一下\nDialogue: 0,0:36:21.90,0:36:23.90,Default,,0,0,0,,由于我已经输入过MERGE-TO-FORM的规则了\nDialogue: 0,0:36:24.62,0:36:25.77,Default,,0,0,0,,我就可以\nDialogue: 0,0:36:27.04,0:36:28.51,Default,,0,0,0,,我可以像过程一样使用它\nDialogue: 0,0:36:28.51,0:36:38.24,Default,,0,0,0,,我可以问(MERGE-TO-FORM (1 3) (2 7) ?X)\nDialogue: 0,0:36:39.42,0:36:41.55,Default,,0,0,0,,这里 我把它当作一个Lisp过程来使用\nDialogue: 0,0:36:43.16,0:36:44.97,Default,,0,0,0,,它先会思考一会儿\nDialogue: 0,0:36:46.43,0:36:47.56,Default,,0,0,0,,然后应用这些规则\nDialogue: 0,0:36:50.78,0:36:51.92,Default,,0,0,0,,它找到了一个答案\nDialogue: 0,0:36:52.80,0:36:54.54,Default,,0,0,0,,现在它还要继续寻找其它的答案\nDialogue: 0,0:36:55.07,0:36:57.32,Default,,0,0,0,,因为它事先不知道这里答案只有一个\nDialogue: 0,0:36:57.81,0:36:59.90,Default,,0,0,0,,因此它就在这里检查所有的可能性\nDialogue: 0,0:37:00.41,0:37:02.54,Default,,0,0,0,,确认没有后 输出'DONE'\nDialogue: 0,0:37:03.16,0:37:05.07,Default,,0,0,0,,这里 我把它们当作过程来使用\nDialogue: 0,0:37:05.21,0:37:09.05,Default,,0,0,0,,不过要注意 我还可以问不同类型的问题\nDialogue: 0,0:37:10.22,0:37:11.07,Default,,0,0,0,,我可以问\nDialogue: 0,0:37:18.56,0:37:24.59,Default,,0,0,0,,(MERGE-TO-FORM (2 ?A)\nDialogue: 0,0:37:24.59,0:37:27.90,Default,,0,0,0,,一个我已知是以2为首的二元表\nDialogue: 0,0:37:29.37,0:37:31.26,Default,,0,0,0,,而另外一个东西是未知的\nDialogue: 0,0:37:33.05,0:37:35.04,Default,,0,0,0,,用?X来表示这个未知的表\nDialogue: 0,0:37:36.48,0:37:39.51,Default,,0,0,0,,可以通过MERGE-TO-FORM形成(1 2 3 4)\nDialogue: 0,0:37:42.76,0:37:44.11,Default,,0,0,0,,现在它将思考这个问题\nDialogue: 0,0:37:44.59,0:37:49.40,Default,,0,0,0,,它会找到 -- 它找到了一种可能\nDialogue: 0,0:37:49.52,0:37:52.46,Default,,0,0,0,,比如A=3 X=(1 4)\nDialogue: 0,0:37:53.72,0:37:55.16,Default,,0,0,0,,现在 它又要继续检查\nDialogue: 0,0:37:56.56,0:37:57.71,Default,,0,0,0,,因为它事先并不知道\nDialogue: 0,0:37:57.74,0:38:00.30,Default,,0,0,0,,这里并没有其它的可能了\nDialogue: 0,0:38:03.68,0:38:06.57,Default,,0,0,0,,或者 就像我说过的\nDialogue: 0,0:38:07.00,0:38:09.84,Default,,0,0,0,,我可以问\nDialogue: 0,0:38:10.54,0:38:17.55,Default,,0,0,0,,能够通过MERGE-TO-FORM形成(1 2 3 4 5)的?X和?Y分别是什么？\nDialogue: 0,0:38:23.68,0:38:25.53,Default,,0,0,0,,语言系统又要思考这个问题\nDialogue: 0,0:38:28.49,0:38:30.31,Default,,0,0,0,,它可能会得到很多答案\nDialogue: 0,0:38:35.18,0:38:38.57,Default,,0,0,0,,这里我们就体会到了缓慢的代价\nDialogue: 0,0:38:42.21,0:38:43.88,Default,,0,0,0,,大概是有三种原因造成这样\nDialogue: 0,0:38:43.88,0:38:46.22,Default,,0,0,0,,首先 这门语言经过了两次解释\nDialogue: 0,0:38:47.63,0:38:49.72,Default,,0,0,0,,然而在真正的实现中\nDialogue: 0,0:38:49.76,0:38:52.04,Default,,0,0,0,,你应该把这些编译成基本运算\nDialogue: 0,0:38:52.19,0:38:53.87,Default,,0,0,0,,其次就是\nDialogue: 0,0:38:53.88,0:38:58.11,Default,,0,0,0,,这个MERGE算法 是双重递归的\nDialogue: 0,0:38:58.38,0:39:00.06,Default,,0,0,0,,因此它需要花费很长的时间\nDialogue: 0,0:39:01.02,0:39:04.33,Default,,0,0,0,,最后呢 它又要遍历所有的情况\nDialogue: 0,0:39:04.59,0:39:07.13,Default,,0,0,0,,找出 -- 找出什么呢？\nDialogue: 0,0:39:07.13,0:39:08.73,Default,,0,0,0,,所有的2^5种可行解\nDialogue: 0,0:39:12.14,0:39:14.96,Default,,0,0,0,,我们发现它们以某种相当随意的顺序输出\nDialogue: 0,0:39:15.00,0:39:18.14,Default,,0,0,0,,这取决于它们用什么样的顺序尝试这些规则\nDialogue: 0,0:39:20.16,0:39:22.11,Default,,0,0,0,,事实上 在后期制作本视频时\nDialogue: 0,0:39:22.40,0:39:23.48,Default,,0,0,0,,我们将加速这段\nDialogue: 0,0:39:24.08,0:39:26.60,Default,,0,0,0,,我们就不再这里浪费时间了\nDialogue: 0,0:39:26.60,0:39:28.27,Default,,0,0,0,,课后你们可以自行尝试\nDialogue: 0,0:39:29.48,0:39:34.24,Default,,0,0,0,,好吧 它还在运行\nDialogue: 0,0:39:39.22,0:39:41.12,Default,,0,0,0,,总之 一共有32种可能\nDialogue: 0,0:39:41.13,0:39:42.63,Default,,0,0,0,,我们就不等到输出所有的结果了\nDialogue: 0,0:39:47.85,0:39:50.44,Default,,0,0,0,,因此 这门语言中的抽象手段就是RULE\nDialogue: 0,0:39:53.53,0:39:58.01,Default,,0,0,0,,我们用逻辑把事物组织在一起\nDialogue: 0,0:39:59.12,0:40:00.08,Default,,0,0,0,,并为它们命名\nDialogue: 0,0:40:00.35,0:40:03.41,Default,,0,0,0,,你们可以认为这是为一组特定的逻辑模式命名\nDialogue: 0,0:40:03.41,0:40:04.54,Default,,0,0,0,,你们可以把它想做\nDialogue: 0,0:40:04.56,0:40:06.75,Default,,0,0,0,,如果我们想要推断出某个结论\nDialogue: 0,0:40:07.90,0:40:09.52,Default,,0,0,0,,就可以应用这些逻辑规则\nDialogue: 0,0:40:10.66,0:40:13.20,Default,,0,0,0,,这些就是这门语言中的三种要素\nDialogue: 0,0:40:13.42,0:40:14.56,Default,,0,0,0,,我们先休息一会儿\nDialogue: 0,0:40:14.60,0:40:16.59,Default,,0,0,0,,然后再来讨论如何实际实现\nDialogue: 0,0:40:23.61,0:40:28.84,Default,,0,0,0,,学生：使用LISP-VALUE之类的基本过程会影响\nDialogue: 0,0:40:29.15,0:40:30.64,Default,,0,0,0,,查询的双向性吗？\nDialogue: 0,0:40:31.77,0:40:34.48,Default,,0,0,0,,教授：这个问题 -- 你问的是\nDialogue: 0,0:40:35.08,0:40:36.92,Default,,0,0,0,,使用LISP-VALUE是否会影响\nDialogue: 0,0:40:37.53,0:40:40.09,Default,,0,0,0,,双向地推断一条查询\nDialogue: 0,0:40:40.09,0:40:42.81,Default,,0,0,0,,虽然我们还没有实际讨论具体实现\nDialogue: 0,0:40:43.68,0:40:45.52,Default,,0,0,0,,但是它们确实会造成影响\nDialogue: 0,0:40:46.89,0:40:50.20,Default,,0,0,0,,通常来说 我们最后将会发现\nDialogue: 0,0:40:50.22,0:40:52.17,Default,,0,0,0,,虽然我不会讲得太细\nDialogue: 0,0:40:53.21,0:40:59.36,Default,,0,0,0,,当你使用NOT和LISP-VALUE时 会变得相当复杂\nDialogue: 0,0:40:59.55,0:41:02.89,Default,,0,0,0,,或者实际上 只要你用了除AND以外的东西\nDialogue: 0,0:41:04.12,0:41:08.19,Default,,0,0,0,,很难再说清楚这些东西是否会起效了\nDialogue: 0,0:41:08.20,0:41:10.36,Default,,0,0,0,,它们并不是在任何情况下都有效\nDialogue: 0,0:41:10.36,0:41:13.39,Default,,0,0,0,,我会在下一堂课的最后讨论这个问题\nDialogue: 0,0:41:14.30,0:41:15.84,Default,,0,0,0,,但对于你的问题来说：答案是“会影响”\nDialogue: 0,0:41:16.19,0:41:19.21,Default,,0,0,0,,用LISP-VALUE一方面从Lisp中获得了巨大威力\nDialogue: 0,0:41:19.40,0:41:23.77,Default,,0,0,0,,另一方面你失去了逻辑式程序设计的重要威力\nDialogue: 0,0:41:24.17,0:41:25.56,Default,,0,0,0,,这是你需要做出的取舍\nDialogue: 0,0:41:28.48,0:41:29.39,Default,,0,0,0,,好吧 先休息一会儿\nDialogue: 0,0:41:30.17,0:41:44.30,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:41:30.17,0:41:44.30,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP"
  },
  {
    "path": "Ass/lec8a.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:02.67,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP学习小组\\N倾情制作\nDialogue: 0,0:00:02.70,0:00:10.27,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}计算机程序的构造和解释\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.70,0:00:10.27,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:10.28,0:00:15.24,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 I\nDialogue: 0,0:00:18.27,0:00:19.68,Default,,0,0,0,,教授：上节课中 我们学习了\nDialogue: 0,0:00:19.72,0:00:21.26,Default,,0,0,0,,如何构造语言\nDialogue: 0,0:00:22.41,0:00:25.88,Default,,0,0,0,,核心点就是 像Lisp这样的求值器\nDialogue: 0,0:00:26.08,0:00:27.58,Default,,0,0,0,,有两个主要部分\nDialogue: 0,0:00:27.58,0:00:28.40,Default,,0,0,0,,一个是EVAL\nDialogue: 0,0:00:31.04,0:00:37.42,Default,,0,0,0,,EVAL接受一个表达式EXP和环境ENV\nDialogue: 0,0:00:38.91,0:00:44.44,Default,,0,0,0,,然后返回一个过程和相关的实际参数\nDialogue: 0,0:00:45.42,0:00:47.05,Default,,0,0,0,,并把它们传递给APPLY\nDialogue: 0,0:00:49.41,0:00:51.29,Default,,0,0,0,,APPLY接收这些过程和实际参数\nDialogue: 0,0:00:51.69,0:00:55.12,Default,,0,0,0,,通常来说 APPLY会返回另一个表达式\nDialogue: 0,0:00:55.39,0:00:57.71,Default,,0,0,0,,返回一个在其它环境中求值的表达式\nDialogue: 0,0:00:57.74,0:01:00.00,Default,,0,0,0,,表达式就像这样在EVAL-APPLY之间传递\nDialogue: 0,0:01:00.27,0:01:01.44,Default,,0,0,0,,这就是整个元循环\nDialogue: 0,0:01:01.47,0:01:02.94,Default,,0,0,0,,表达式在这里面循环往复\nDialogue: 0,0:01:03.02,0:01:06.56,Default,,0,0,0,,直到最后求值为基本数据或基本过程\nDialogue: 0,0:01:07.74,0:01:09.24,Default,,0,0,0,,这个循环要做的就是\nDialogue: 0,0:01:09.44,0:01:12.57,Default,,0,0,0,,把语言中的组合手段\nDialogue: 0,0:01:12.59,0:01:14.36,Default,,0,0,0,,和抽象手段展开\nDialogue: 0,0:01:15.02,0:01:17.72,Default,,0,0,0,,比如说在Lisp中 你有一个过程\nDialogue: 0,0:01:17.74,0:01:20.52,Default,,0,0,0,,定义过程是为了\nDialogue: 0,0:01:20.54,0:01:22.57,Default,,0,0,0,,让表达式的计算过程\nDialogue: 0,0:01:22.67,0:01:24.41,Default,,0,0,0,,适用于任意的参数\nDialogue: 0,0:01:25.76,0:01:27.18,Default,,0,0,0,,这就是这里面发生的事情\nDialogue: 0,0:01:27.67,0:01:28.51,Default,,0,0,0,,这就是APPLY做的事\nDialogue: 0,0:01:28.51,0:01:30.68,Default,,0,0,0,,当一个带参数的一般性表达式进入以后\nDialogue: 0,0:01:30.72,0:01:32.70,Default,,0,0,0,,它将其归约为过程体的表达式\nDialogue: 0,0:01:33.05,0:01:34.72,Default,,0,0,0,,如果归约得到的是复合表达式\nDialogue: 0,0:01:34.83,0:01:36.46,Default,,0,0,0,,或者是另外的过程应用\nDialogue: 0,0:01:36.78,0:01:38.44,Default,,0,0,0,,那么这个循环就会不断地进行\nDialogue: 0,0:01:40.33,0:01:44.08,Default,,0,0,0,,这基本上就是 -- 大部分解释器的基本结构了\nDialogue: 0,0:01:45.20,0:01:46.25,Default,,0,0,0,,另外一点就是\nDialogue: 0,0:01:46.28,0:01:47.66,Default,,0,0,0,,一旦你有了一个解释器\nDialogue: 0,0:01:47.69,0:01:49.87,Default,,0,0,0,,你就有了操作这门语言的所有能力\nDialogue: 0,0:01:49.87,0:01:51.52,Default,,0,0,0,,因此你可以让它成为动态作用域\nDialogue: 0,0:01:51.84,0:01:54.56,Default,,0,0,0,,你也可以引入正则序求值\nDialogue: 0,0:01:54.59,0:01:56.48,Default,,0,0,0,,你也可以为语言添加新的形式\nDialogue: 0,0:01:56.86,0:01:57.50,Default,,0,0,0,,想怎么样都行\nDialogue: 0,0:01:57.58,0:01:58.62,Default,,0,0,0,,或者更一般地说\nDialogue: 0,0:01:58.76,0:02:01.32,Default,,0,0,0,,这种元语言抽象的概念\nDialogue: 0,0:02:02.64,0:02:06.01,Default,,0,0,0,,它告诉我们 作为一名软件工程师\nDialogue: 0,0:02:07.61,0:02:10.52,Default,,0,0,0,,从广义的“工程师”的角度来看\nDialogue: 0,0:02:11.39,0:02:13.88,Default,,0,0,0,,有时你可以通过发明新的语言\nDialogue: 0,0:02:14.96,0:02:17.16,Default,,0,0,0,,来获得控制复杂度的能力\nDialogue: 0,0:02:18.01,0:02:20.81,Default,,0,0,0,,一种思考计算机程序设计的方法就是\nDialogue: 0,0:02:21.55,0:02:26.27,Default,,0,0,0,,它只是偶然地让计算机执行某事儿\nDialogue: 0,0:02:26.44,0:02:28.97,Default,,0,0,0,,计算机程序的主要工作却是\nDialogue: 0,0:02:29.00,0:02:32.52,Default,,0,0,0,,用来表达和交换想法\nDialogue: 0,0:02:33.16,0:02:34.04,Default,,0,0,0,,有时\nDialogue: 0,0:02:34.89,0:02:36.62,Default,,0,0,0,,当我们想要表达新的想法时\nDialogue: 0,0:02:36.65,0:02:38.73,Default,,0,0,0,,我们就想要发明新的模式来表达它们\nDialogue: 0,0:02:39.82,0:02:44.99,Default,,0,0,0,,那么 今天我们就将按照这个框架来创建新语言\nDialogue: 0,0:02:45.73,0:02:48.00,Default,,0,0,0,,一旦我们了解了解释器的基本结构\nDialogue: 0,0:02:48.03,0:02:50.27,Default,,0,0,0,,我们就可以按意愿来构造任意的语言\nDialogue: 0,0:02:50.83,0:02:53.21,Default,,0,0,0,,比如说 我们可以构造Pascal（的解释器）\nDialogue: 0,0:02:54.37,0:02:55.15,Default,,0,0,0,,以及\nDialogue: 0,0:02:56.17,0:02:58.19,Default,,0,0,0,,我们需要操心语法的表示与解析\nDialogue: 0,0:02:58.19,0:03:00.51,Default,,0,0,0,,还有一大堆的编译器优化\nDialogue: 0,0:03:01.12,0:03:03.29,Default,,0,0,0,,还有一些人会这样做\nDialogue: 0,0:03:03.85,0:03:07.60,Default,,0,0,0,,但是就在我们所讨论的抽象层次来说\nDialogue: 0,0:03:08.04,0:03:10.99,Default,,0,0,0,,一个Pascal语言的解释器看起来\nDialogue: 0,0:03:12.03,0:03:13.76,Default,,0,0,0,,跟Gerry教授上节课所讲的大同小异\nDialogue: 0,0:03:15.02,0:03:18.96,Default,,0,0,0,,但是今天 我们要构建一门与众不同的语言\nDialogue: 0,0:03:20.51,0:03:22.81,Default,,0,0,0,,这门语言\nDialogue: 0,0:03:23.05,0:03:26.04,Default,,0,0,0,,不推荐你用过程式的思维来思考程序设计\nDialogue: 0,0:03:26.24,0:03:27.64,Default,,0,0,0,,而是用一种非常不同的方式\nDialogue: 0,0:03:29.09,0:03:31.02,Default,,0,0,0,,今天的课程呢\nDialogue: 0,0:03:31.74,0:03:34.64,Default,,0,0,0,,将会在两个层次中同时进行\nDialogue: 0,0:03:34.81,0:03:35.52,Default,,0,0,0,,一方面\nDialogue: 0,0:03:35.90,0:03:37.71,Default,,0,0,0,,我会向大家介绍这门语言是如何使用的\nDialogue: 0,0:03:38.96,0:03:41.08,Default,,0,0,0,,另一方面呢 我会带领大家实现这门语言\nDialogue: 0,0:03:41.32,0:03:42.96,Default,,0,0,0,,我们将会用Lisp来实现\nDialogue: 0,0:03:42.99,0:03:43.90,Default,,0,0,0,,并观察它的运行原理\nDialogue: 0,0:03:44.04,0:03:48.25,Default,,0,0,0,,你应该在两个层次上学到知识\nDialogue: 0,0:03:48.68,0:03:53.00,Default,,0,0,0,,首先要认识到 语言之间可以有多么地“不同”\nDialogue: 0,0:03:53.79,0:03:58.14,Default,,0,0,0,,如果你认为Fortran和Lisp算是天差地别的话\nDialogue: 0,0:03:58.24,0:03:59.36,Default,,0,0,0,,那就小巫见大巫了\nDialogue: 0,0:04:01.56,0:04:03.68,Default,,0,0,0,,其次\nDialogue: 0,0:04:03.77,0:04:06.54,Default,,0,0,0,,甚至于在这门与众不同的语言中\nDialogue: 0,0:04:07.36,0:04:09.52,Default,,0,0,0,,这门既不讨论函数\nDialogue: 0,0:04:09.92,0:04:11.64,Default,,0,0,0,,也没有过程的语言中\nDialogue: 0,0:04:12.20,0:04:15.72,Default,,0,0,0,,其中也有基本的EVAL-APPLY循环\nDialogue: 0,0:04:16.19,0:04:19.98,Default,,0,0,0,,也就是对组合手段和抽象手段的展开\nDialogue: 0,0:04:20.95,0:04:24.68,Default,,0,0,0,,第三点 是一个不太重要但非常优雅的技术技巧\nDialogue: 0,0:04:24.89,0:04:28.52,Default,,0,0,0,,就是如何巧妙地使用流来避免回溯\nDialogue: 0,0:04:32.33,0:04:34.40,Default,,0,0,0,,好吧 我说过这门语言与众不同\nDialogue: 0,0:04:35.86,0:04:36.64,Default,,0,0,0,,为了解释这点\nDialogue: 0,0:04:37.05,0:04:42.81,Default,,0,0,0,,让我们回到这门课最初的理念上\nDialogue: 0,0:04:43.26,0:04:46.54,Default,,0,0,0,,就是要区别\nDialogue: 0,0:04:46.72,0:04:49.52,Default,,0,0,0,,数学中“陈述性”的知识\nDialogue: 0,0:04:50.19,0:04:54.14,Default,,0,0,0,,比如平方根的定义就是一条数学事实\nDialogue: 0,0:04:55.48,0:04:59.56,Default,,0,0,0,,而计算机科学讨论的是“如何做”的知识\nDialogue: 0,0:04:59.76,0:05:04.59,Default,,0,0,0,,“什么是平方根”和“如何计算平方根”是不同的\nDialogue: 0,0:05:05.97,0:05:07.07,Default,,0,0,0,,我们是从这里开始的\nDialogue: 0,0:05:08.51,0:05:09.52,Default,,0,0,0,,如果我们能够通过某种方式\nDialogue: 0,0:05:09.88,0:05:12.16,Default,,0,0,0,,弥合这种差距 岂不是更好么？\nDialogue: 0,0:05:12.81,0:05:16.43,Default,,0,0,0,,我们创建一门这样的语言\nDialogue: 0,0:05:16.67,0:05:21.61,Default,,0,0,0,,以声明式的方式、用数学事实来完成计算\nDialogue: 0,0:05:22.38,0:05:25.50,Default,,0,0,0,,你用这种该语言来指定事实\nDialogue: 0,0:05:27.69,0:05:28.88,Default,,0,0,0,,你告诉它\nDialogue: 0,0:05:28.88,0:05:29.96,Default,,0,0,0,,什么是事实\nDialogue: 0,0:05:30.95,0:05:33.07,Default,,0,0,0,,而当你需要一个答案时\nDialogue: 0,0:05:33.21,0:05:36.38,Default,,0,0,0,,语言已经自动地内建了\nDialogue: 0,0:05:37.60,0:05:39.45,Default,,0,0,0,,有关于“如何做”的一般性知识\nDialogue: 0,0:05:39.47,0:05:40.64,Default,,0,0,0,,这样它就可以根据你给出的事实\nDialogue: 0,0:05:40.89,0:05:42.83,Default,,0,0,0,,自行地演进这些方法\nDialogue: 0,0:05:43.31,0:05:46.12,Default,,0,0,0,,通过你给定的事实和某种一般性的逻辑规则\nDialogue: 0,0:05:49.33,0:05:50.54,Default,,0,0,0,,就比如说\nDialogue: 0,0:05:52.06,0:05:55.12,Default,,0,0,0,,我会告诉程序下述事实\nDialogue: 0,0:05:56.00,0:06:07.08,Default,,0,0,0,,我告诉它 (SON-OF ADAM ABEL)\nDialogue: 0,0:06:08.92,0:06:16.51,Default,,0,0,0,,同时告诉它 (SON-OF ADAM CAIN)\nDialogue: 0,0:06:17.66,0:06:25.08,Default,,0,0,0,,以及 (SON-OF CAIN ENOCH)\nDialogue: 0,0:06:27.79,0:06:34.89,Default,,0,0,0,,还有 (SON-OF ENOCH IRAD)\nDialogue: 0,0:06:37.02,0:06:40.72,Default,,0,0,0,,以及《创世纪》章节中的其它人物\nDialogue: 0,0:06:41.15,0:06:43.18,Default,,0,0,0,,最后终止于ADAH\nDialogue: 0,0:06:43.32,0:06:46.78,Default,,0,0,0,,这些是从ADAH到CAIN的家谱\nDialogue: 0,0:06:48.44,0:06:50.67,Default,,0,0,0,,总之 一旦你指明了这些事实\nDialogue: 0,0:06:52.35,0:06:53.40,Default,,0,0,0,,你就可以提出问题\nDialogue: 0,0:06:53.51,0:06:55.05,Default,,0,0,0,,你可以对语言系统发问\nDialogue: 0,0:06:56.06,0:06:59.29,Default,,0,0,0,,谁是ADAM的孩子？\nDialogue: 0,0:07:00.42,0:07:04.91,Default,,0,0,0,,可以很容易地想到一个通用搜索程序\nDialogue: 0,0:07:05.52,0:07:06.96,Default,,0,0,0,,它会遍历所有的事实\nDialogue: 0,0:07:07.00,0:07:09.26,Default,,0,0,0,,然后回答：“哦 有两个答案”\nDialogue: 0,0:07:09.29,0:07:10.44,Default,,0,0,0,,ABEL是ADAM的孩子\nDialogue: 0,0:07:10.68,0:07:12.17,Default,,0,0,0,,CAIN也是ADAM的孩子\nDialogue: 0,0:07:14.14,0:07:14.97,Default,,0,0,0,,你也可以这样问\nDialogue: 0,0:07:15.07,0:07:16.89,Default,,0,0,0,,基于同样的事实\nDialogue: 0,0:07:18.04,0:07:19.95,Default,,0,0,0,,CAIN是谁的孩子？\nDialogue: 0,0:07:21.95,0:07:27.02,Default,,0,0,0,,你们就会想到生成另外一个略微不同的搜索程序\nDialogue: 0,0:07:27.92,0:07:29.21,Default,,0,0,0,,它也会遍历所有的事实\nDialogue: 0,0:07:29.45,0:07:33.05,Default,,0,0,0,,检查谁的孩子是CAIN\nDialogue: 0,0:07:33.52,0:07:34.44,Default,,0,0,0,,发现结果是ADAM\nDialogue: 0,0:07:35.89,0:07:36.99,Default,,0,0,0,,你也可以问\nDialogue: 0,0:07:38.01,0:07:41.40,Default,,0,0,0,,CAIN和ENOCH之间是什么关系？\nDialogue: 0,0:07:42.07,0:07:45.08,Default,,0,0,0,,又会生成另一个略微不同的搜索程序\nDialogue: 0,0:07:46.34,0:07:48.16,Default,,0,0,0,,得到的结果是亲子关系（SON-OF）\nDialogue: 0,0:07:52.88,0:07:54.92,Default,,0,0,0,,在这个非常简单的例子中\nDialogue: 0,0:07:56.14,0:07:58.44,Default,,0,0,0,,我们发现 即使是单条事实\nDialogue: 0,0:07:58.81,0:08:01.52,Default,,0,0,0,,比如说 (SON-OF ADAM CAIN)\nDialogue: 0,0:08:02.84,0:08:05.52,Default,,0,0,0,,可以被用来回答不同种类的问题\nDialogue: 0,0:08:06.52,0:08:08.12,Default,,0,0,0,,你可以问CAIN是谁的孩子？\nDialogue: 0,0:08:08.14,0:08:10.92,Default,,0,0,0,,你也可以问ADAM的孩子是谁？\nDialogue: 0,0:08:10.94,0:08:12.86,Default,,0,0,0,,你也可以问ADAM和CAIN之间的关系是什么？\nDialogue: 0,0:08:12.88,0:08:14.48,Default,,0,0,0,,这些由不同的传统程序\nDialogue: 0,0:08:15.53,0:08:18.54,Default,,0,0,0,,所解答的不同的问题\nDialogue: 0,0:08:18.68,0:08:20.72,Default,,0,0,0,,都基于同样的事实\nDialogue: 0,0:08:22.75,0:08:25.92,Default,,0,0,0,,这正是这种程序设计风格的威力所在\nDialogue: 0,0:08:26.91,0:08:29.50,Default,,0,0,0,,也就是一条陈述性知识\nDialogue: 0,0:08:30.04,0:08:34.01,Default,,0,0,0,,可以作为大量关于“如何做”的各种知识的基础\nDialogue: 0,0:08:34.81,0:08:37.08,Default,,0,0,0,,这跟我们正在编写的过程是不同的\nDialogue: 0,0:08:37.15,0:08:39.55,Default,,0,0,0,,我们编写的过程描述了输入\nDialogue: 0,0:08:39.61,0:08:40.65,Default,,0,0,0,,以及想要的输出\nDialogue: 0,0:08:41.49,0:08:44.70,Default,,0,0,0,,比如说 我们的平方根程序可以完美地回答\nDialogue: 0,0:08:44.76,0:08:47.16,Default,,0,0,0,,144的平方根是多少？\nDialogue: 0,0:08:48.90,0:08:49.77,Default,,0,0,0,,但从原理上来说\nDialogue: 0,0:08:49.82,0:08:52.83,Default,,0,0,0,,平方根的数学定义告诉了你另外的东西\nDialogue: 0,0:08:52.84,0:08:56.43,Default,,0,0,0,,就比如说 17是谁的平方根\nDialogue: 0,0:08:57.59,0:08:59.71,Default,,0,0,0,,这就需要另外一个程序来解答\nDialogue: 0,0:09:01.92,0:09:03.50,Default,,0,0,0,,因此 数学定义\nDialogue: 0,0:09:03.98,0:09:05.12,Default,,0,0,0,,或者更一般地说\nDialogue: 0,0:09:05.53,0:09:10.30,Default,,0,0,0,,你给定的事实 对于问题是没有偏向性的\nDialogue: 0,0:09:10.90,0:09:12.81,Default,,0,0,0,,而我们倾向于编写专门的程序\nDialogue: 0,0:09:12.83,0:09:14.20,Default,,0,0,0,,因为它们是关于“如何做”的知识\nDialogue: 0,0:09:14.24,0:09:16.36,Default,,0,0,0,,倾向于寻找特定的答案\nDialogue: 0,0:09:17.56,0:09:20.12,Default,,0,0,0,,所以这是我们正在讨论的一个特点\nDialogue: 0,0:09:21.81,0:09:22.60,Default,,0,0,0,,然而我们可以更进一步\nDialogue: 0,0:09:23.48,0:09:27.52,Default,,0,0,0,,想象一下 我们可以向语言给定一些事实\nDialogue: 0,0:09:27.71,0:09:29.61,Default,,0,0,0,,现在 我们给它一些推理规则\nDialogue: 0,0:09:30.02,0:09:31.36,Default,,0,0,0,,比如说\nDialogue: 0,0:09:31.95,0:09:36.19,Default,,0,0,0,,这里 我们先用某种语法表示\nDialogue: 0,0:09:36.44,0:09:41.53,Default,,0,0,0,,如果(SON-OF ?X ?Y)成立\nDialogue: 0,0:09:41.68,0:09:45.21,Default,,0,0,0,,在这里 我用问号来标识变量\nDialogue: 0,0:09:45.61,0:09:56.06,Default,,0,0,0,,如果(SON-OF ?X ?Y)和(SON-OF ?Y ?Z)都成立\nDialogue: 0,0:09:58.96,0:10:08.46,Default,,0,0,0,,那么就有(GRANSON ?X ?Z)\nDialogue: 0,0:10:09.32,0:10:13.40,Default,,0,0,0,,想象一下 如果把这条规则告诉机器\nDialogue: 0,0:10:15.00,0:10:17.28,Default,,0,0,0,,那么我们就可以这么来询问\nDialogue: 0,0:10:17.44,0:10:18.68,Default,,0,0,0,,谁是ADAM的孙子？\nDialogue: 0,0:10:20.61,0:10:23.64,Default,,0,0,0,,或者说 IRAD是谁的孙子？\nDialogue: 0,0:10:24.79,0:10:29.08,Default,,0,0,0,,或者从这些信息中尽可能地推断出所有的祖孙关系\nDialogue: 0,0:10:31.13,0:10:35.60,Default,,0,0,0,,我们可以想象 语言知道如何自动求解\nDialogue: 0,0:10:40.22,0:10:45.20,Default,,0,0,0,,好吧 我再举一个更具体一点的例子\nDialogue: 0,0:10:45.77,0:10:51.95,Default,,0,0,0,,这是个用来合并两个有序表的过程\nDialogue: 0,0:10:53.92,0:11:00.27,Default,,0,0,0,,X和Y是两个由数字构成的表\nDialogue: 0,0:11:00.30,0:11:04.20,Default,,0,0,0,,我们可以认为它们是严格升序的表\nDialogue: 0,0:11:04.76,0:11:07.53,Default,,0,0,0,,MERGE会把这两个表\nDialogue: 0,0:11:07.71,0:11:10.38,Default,,0,0,0,,合并成一个有序的表\nDialogue: 0,0:11:11.21,0:11:15.00,Default,,0,0,0,,这个程序非常简单\nDialogue: 0,0:11:15.02,0:11:16.14,Default,,0,0,0,,你们可以轻松地写出来\nDialogue: 0,0:11:16.39,0:11:18.64,Default,,0,0,0,,也就是 如果X为空 那么结果就是Y\nDialogue: 0,0:11:18.86,0:11:20.46,Default,,0,0,0,,如果Y为空 那结果就是X\nDialogue: 0,0:11:21.18,0:11:22.99,Default,,0,0,0,,否则的话 就要比较为首的两个元素\nDialogue: 0,0:11:22.99,0:11:24.46,Default,,0,0,0,,取出X中的第一个元素\nDialogue: 0,0:11:24.84,0:11:26.01,Default,,0,0,0,,以及Y中的第一个元素\nDialogue: 0,0:11:26.81,0:11:31.68,Default,,0,0,0,,把它们当中谁是最小的那一个\nDialogue: 0,0:11:32.83,0:11:36.60,Default,,0,0,0,,CONS在递归地调用MERGE的结果上\nDialogue: 0,0:11:37.87,0:11:39.92,Default,,0,0,0,,要么就是(MERGE (CDR X) Y)\nDialogue: 0,0:11:40.11,0:11:41.61,Default,,0,0,0,,要么就是(MERGE X (CDR Y))\nDialogue: 0,0:11:42.40,0:11:43.96,Default,,0,0,0,,这是标准的程序\nDialogue: 0,0:11:46.47,0:11:48.41,Default,,0,0,0,,我们来考察下其中的逻辑\nDialogue: 0,0:11:48.62,0:11:49.79,Default,,0,0,0,,先不考虑程序\nDialogue: 0,0:11:50.28,0:11:52.76,Default,,0,0,0,,来看看这个过程所基于的逻辑\nDialogue: 0,0:11:53.82,0:11:55.00,Default,,0,0,0,,这其中的逻辑是\nDialogue: 0,0:11:55.02,0:11:57.21,Default,,0,0,0,,如果第一个元素较小\nDialogue: 0,0:11:57.53,0:12:00.00,Default,,0,0,0,,那么最后的结果就是把它\nDialogue: 0,0:12:00.16,0:12:02.12,Default,,0,0,0,,跟递归MERGE的结果CONS起来\nDialogue: 0,0:12:02.84,0:12:04.09,Default,,0,0,0,,让我们试着把\nDialogue: 0,0:12:04.24,0:12:06.41,Default,,0,0,0,,使这个程序运作的逻辑说清楚一点\nDialogue: 0,0:12:08.30,0:12:09.44,Default,,0,0,0,,这是一部分\nDialogue: 0,0:12:10.13,0:12:11.53,Default,,0,0,0,,这段程序\nDialogue: 0,0:12:12.64,0:12:15.26,Default,,0,0,0,,递归地剥离X\nDialogue: 0,0:12:15.66,0:12:17.82,Default,,0,0,0,,如果X中的首元素较小的话\nDialogue: 0,0:12:19.98,0:12:22.54,Default,,0,0,0,,如果要显式地指出其中的逻辑的话\nDialogue: 0,0:12:23.45,0:12:26.49,Default,,0,0,0,,它其实就是演绎推理\nDialogue: 0,0:12:26.72,0:12:32.38,Default,,0,0,0,,其中 如果知道表CDR-X和表Y\nDialogue: 0,0:12:33.29,0:12:35.44,Default,,0,0,0,,能够通过MERGE-TO-FORM形成Z\nDialogue: 0,0:12:37.84,0:12:41.52,Default,,0,0,0,,并且还知道A比Y中的第一个元素小\nDialogue: 0,0:12:43.60,0:12:48.52,Default,,0,0,0,,那么你就知道 如果你把A和CDR-X给CONS起来\nDialogue: 0,0:12:49.74,0:12:51.85,Default,,0,0,0,,得到的结果和Y一起\nDialogue: 0,0:12:52.60,0:12:54.99,Default,,0,0,0,,可以通过MERGE-TO-FORM形成Z\nDialogue: 0,0:12:55.82,0:12:58.09,Default,,0,0,0,,这就是它所基于的逻辑\nDialogue: 0,0:12:58.72,0:12:59.95,Default,,0,0,0,,我没有把它写成程序\nDialogue: 0,0:12:59.96,0:13:02.00,Default,,0,0,0,,我把它写成了某种演绎\nDialogue: 0,0:13:02.03,0:13:04.89,Default,,0,0,0,,正是属于这个特定子句的\nDialogue: 0,0:13:05.21,0:13:07.26,Default,,0,0,0,,它告诉我们可以在这里使用递归\nDialogue: 0,0:13:09.41,0:13:12.78,Default,,0,0,0,,同样地 这里还有些句子来补全其中的逻辑\nDialogue: 0,0:13:14.00,0:13:15.87,Default,,0,0,0,,其它的句子都是基于这些逻辑\nDialogue: 0,0:13:15.92,0:13:18.35,Default,,0,0,0,,由于它们大部分是相同的 我就不细讲了\nDialogue: 0,0:13:19.00,0:13:20.35,Default,,0,0,0,,然后就是终止条件\nDialogue: 0,0:13:20.41,0:13:22.01,Default,,0,0,0,,是用来检查NULL的\nDialogue: 0,0:13:22.03,0:13:24.04,Default,,0,0,0,,其基本想法是 对于任意的X\nDialogue: 0,0:13:24.51,0:13:27.20,Default,,0,0,0,,X和空表可以通过MERGE-TO-FORM形成X\nDialogue: 0,0:13:28.04,0:13:30.86,Default,,0,0,0,,而空表可以和任意的Y通过MERGE-TO-FORM形成Y\nDialogue: 0,0:13:33.36,0:13:38.12,Default,,0,0,0,,这就是一段过程的代码\nDialogue: 0,0:13:38.43,0:13:40.11,Default,,0,0,0,,以及它所基于的逻辑\nDialogue: 0,0:13:41.74,0:13:42.97,Default,,0,0,0,,请注意其中的巨大差异\nDialogue: 0,0:13:45.10,0:13:50.52,Default,,0,0,0,,过程看起来是像这样的：\nDialogue: 0,0:13:50.65,0:13:52.28,Default,,0,0,0,,首先这有一个盒子\nDialogue: 0,0:13:52.86,0:13:55.39,Default,,0,0,0,,我们到目前为止所做的事都有这样的特征\nDialogue: 0,0:13:55.40,0:13:57.69,Default,,0,0,0,,我们有一个盒子 有东西进去 也有东西出来\nDialogue: 0,0:13:58.08,0:13:59.61,Default,,0,0,0,,这儿有个MERGE盒子\nDialogue: 0,0:14:01.29,0:14:03.85,Default,,0,0,0,,输入是X和Y\nDialogue: 0,0:14:04.44,0:14:05.37,Default,,0,0,0,,输出ANS\nDialogue: 0,0:14:07.63,0:14:09.48,Default,,0,0,0,,这是我们所编写的程序的特征\nDialogue: 0,0:14:13.02,0:14:14.66,Default,,0,0,0,,但是规则并不像这样\nDialogue: 0,0:14:14.66,0:14:16.76,Default,,0,0,0,,规则讨论的是关系\nDialogue: 0,0:14:17.92,0:14:24.16,Default,,0,0,0,,也就是在幻灯片中我称作MERGE-TO-FORM的关系\nDialogue: 0,0:14:25.37,0:14:28.76,Default,,0,0,0,,每当我说X和Y通过MERGE-TO-FORM形成Z\nDialogue: 0,0:14:29.00,0:14:32.33,Default,,0,0,0,,这个是一个函数\nDialogue: 0,0:14:32.61,0:14:32.85,Default,,0,0,0,,对吧？\nDialogue: 0,0:14:32.85,0:14:34.41,Default,,0,0,0,,ANS是X和Y的函数\nDialogue: 0,0:14:34.59,0:14:38.19,Default,,0,0,0,,而我这里得到的是三个东西之间的关系\nDialogue: 0,0:14:39.72,0:14:41.32,Default,,0,0,0,,我不会指明\nDialogue: 0,0:14:42.09,0:14:43.77,Default,,0,0,0,,哪个是输入 哪个是输出\nDialogue: 0,0:14:44.20,0:14:47.40,Default,,0,0,0,,我之所以这么说 是因为原理上\nDialogue: 0,0:14:48.64,0:14:50.83,Default,,0,0,0,,我们可以用同样的逻辑规则\nDialogue: 0,0:14:50.84,0:14:52.44,Default,,0,0,0,,来回答相当多的问题\nDialogue: 0,0:14:54.57,0:14:56.30,Default,,0,0,0,,比如 我们可以问\nDialogue: 0,0:14:56.72,0:14:59.05,Default,,0,0,0,,想象一下 如果把这些逻辑规则输入机器\nDialogue: 0,0:14:59.05,0:15:01.20,Default,,0,0,0,,不是输入程序 而是其中依赖的逻辑\nDialogue: 0,0:15:01.40,0:15:03.12,Default,,0,0,0,,那么 它也就应该回答--\nDialogue: 0,0:15:04.75,0:15:05.52,Default,,0,0,0,,我们可以问它\nDialogue: 0,0:15:06.73,0:15:19.18,Default,,0,0,0,,(1 3 7)和(2 4 8)可以通过MERGE-TO-FORM形成什么？\nDialogue: 0,0:15:20.91,0:15:23.42,Default,,0,0,0,,机器能够回答这样的问题\nDialogue: 0,0:15:23.88,0:15:27.36,Default,,0,0,0,,这同样也是我们的Lisp程序所回答的问题\nDialogue: 0,0:15:28.18,0:15:30.14,Default,,0,0,0,,但这同样的规则\nDialogue: 0,0:15:30.89,0:15:34.80,Default,,0,0,0,,也能够回答像这样的问题：\nDialogue: 0,0:15:36.19,0:15:43.24,Default,,0,0,0,,(1 3 7)和什么能够通过MERGE-TO-FORM形成(1 2 3 4 7 8)\nDialogue: 0,0:15:45.56,0:15:47.80,Default,,0,0,0,,同样的逻辑规则也能够回答这个\nDialogue: 0,0:15:47.84,0:15:49.90,Default,,0,0,0,,但我们编写的过程却无法回答这个问题\nDialogue: 0,0:15:50.80,0:15:52.33,Default,,0,0,0,,又或者 我们可以问\nDialogue: 0,0:15:53.71,0:16:01.12,Default,,0,0,0,,什么和什么能通过MERGE-TO-FORM\nDialogue: 0,0:16:04.28,0:16:12.68,Default,,0,0,0,,哪两个东西可以通过MERGE-TO-FORM形成(1 2 3 4 7 8)？\nDialogue: 0,0:16:13.78,0:16:15.34,Default,,0,0,0,,机器能够进行遍历\nDialogue: 0,0:16:15.84,0:16:17.31,Default,,0,0,0,,如果它能应用这些逻辑规则的话\nDialogue: 0,0:16:17.79,0:16:22.54,Default,,0,0,0,,就能够推断出这个问题所有的2^6种答案\nDialogue: 0,0:16:25.60,0:16:27.69,Default,,0,0,0,,因为可以分别是 (1)和其余的\nDialogue: 0,0:16:27.69,0:16:28.75,Default,,0,0,0,,也可以是 (1 2)和其余的\nDialogue: 0,0:16:28.79,0:16:31.53,Default,,0,0,0,,也可以是(1 3 7)和其余的\nDialogue: 0,0:16:32.01,0:16:33.26,Default,,0,0,0,,有一大堆的答案\nDialogue: 0,0:16:33.41,0:16:37.76,Default,,0,0,0,,但原理上来说 逻辑能推断出所有的答案\nDialogue: 0,0:16:38.55,0:16:42.03,Default,,0,0,0,,因此这里面就有两个巨大的不同\nDialogue: 0,0:16:44.04,0:16:46.00,Default,,0,0,0,,在我们所编写的程序中\nDialogue: 0,0:16:46.54,0:16:48.19,Default,,0,0,0,,不只是Lisp程序\nDialogue: 0,0:16:48.20,0:16:50.56,Default,,0,0,0,,基本上是你们目前编写过的所有程序\nDialogue: 0,0:16:52.03,0:16:53.60,Default,,0,0,0,,用你能叫出名字的程序语言所编写的程序\nDialogue: 0,0:16:54.15,0:16:57.79,Default,,0,0,0,,首先 我们并不准备计算一个函数\nDialogue: 0,0:17:00.62,0:17:02.01,Default,,0,0,0,,我们将要讨论的东西\nDialogue: 0,0:17:02.62,0:17:04.41,Default,,0,0,0,,并不具有输入和输出\nDialogue: 0,0:17:04.41,0:17:05.82,Default,,0,0,0,,我们讨论的是关系\nDialogue: 0,0:17:06.89,0:17:10.00,Default,,0,0,0,,也就是说 原理上 关系是没有方向性的\nDialogue: 0,0:17:11.08,0:17:15.05,Default,,0,0,0,,所以你指明用来回答这个问题的知识\nDialogue: 0,0:17:16.46,0:17:18.41,Default,,0,0,0,,也同样应该能够反过来\nDialogue: 0,0:17:18.43,0:17:21.80,Default,,0,0,0,,让你回答其它的这些问题\nDialogue: 0,0:17:26.60,0:17:29.40,Default,,0,0,0,,其次则是\nDialogue: 0,0:17:29.61,0:17:31.23,Default,,0,0,0,,因为我们讨论的是关系\nDialogue: 0,0:17:32.32,0:17:34.44,Default,,0,0,0,,关系的答案并不唯一\nDialogue: 0,0:17:35.61,0:17:37.00,Default,,0,0,0,,所以在第三个问题中\nDialogue: 0,0:17:37.02,0:17:38.36,Default,,0,0,0,,并没有特定的答案\nDialogue: 0,0:17:38.40,0:17:39.58,Default,,0,0,0,,它有很多的答案\nDialogue: 0,0:17:42.27,0:17:44.64,Default,,0,0,0,,这就是我们的目标\nDialogue: 0,0:17:44.64,0:17:45.90,Default,,0,0,0,,顺便说一下\nDialogue: 0,0:17:46.72,0:17:49.21,Default,,0,0,0,,这种程序设计风格被称作逻辑式程序设计\nDialogue: 0,0:17:50.22,0:17:51.58,Default,,0,0,0,,原因是显而易见的\nDialogue: 0,0:17:56.16,0:18:00.38,Default,,0,0,0,,用逻辑式进行程序设计的那群人之间\nDialogue: 0,0:18:00.40,0:18:03.15,Default,,0,0,0,,流传着几句箴言\nDialogue: 0,0:18:03.16,0:18:04.67,Default,,0,0,0,,他们把逻辑式程序设计的要点归纳为\nDialogue: 0,0:18:04.76,0:18:09.00,Default,,0,0,0,,用逻辑来表达 什么算是“真的”\nDialogue: 0,0:18:10.09,0:18:13.88,Default,,0,0,0,,用逻辑来检测 是否是“真的”\nDialogue: 0,0:18:14.67,0:18:17.24,Default,,0,0,0,,用逻辑来找出这些“真的”\nDialogue: 0,0:18:19.20,0:18:22.09,Default,,0,0,0,,最为大家所熟知的逻辑式程序设计语言\nDialogue: 0,0:18:22.97,0:18:24.78,Default,,0,0,0,,你们可能也听过 -- 叫做Prolog\nDialogue: 0,0:18:25.78,0:18:28.88,Default,,0,0,0,,今天早上我们将要实现的这门语言\nDialogue: 0,0:18:29.82,0:18:32.32,Default,,0,0,0,,是一种查询语言\nDialogue: 0,0:18:32.48,0:18:34.41,Default,,0,0,0,,它基本上就是Prolog的本质了\nDialogue: 0,0:18:35.32,0:18:36.73,Default,,0,0,0,,它可以完成相同的工作\nDialogue: 0,0:18:37.29,0:18:38.73,Default,,0,0,0,,虽然它比Prolog慢得多\nDialogue: 0,0:18:38.73,0:18:40.01,Default,,0,0,0,,这是因为我们是通过Lisp来解释的\nDialogue: 0,0:18:41.90,0:18:44.36,Default,,0,0,0,,而非构造一个专门的编译器\nDialogue: 0,0:18:44.46,0:18:46.62,Default,,0,0,0,,对它的解释 将运行在Lisp解释器之上\nDialogue: 0,0:18:47.51,0:18:49.84,Default,,0,0,0,,除此之外 它可以完成与Prolog相同的事儿\nDialogue: 0,0:18:49.88,0:18:52.78,Default,,0,0,0,,不但同样的能力 也有同样的局限\nDialogue: 0,0:18:55.08,0:18:56.17,Default,,0,0,0,,好吧 先解答一下疑惑\nDialogue: 0,0:19:00.43,0:19:02.84,Default,,0,0,0,,学生：您能再重复一下\nDialogue: 0,0:19:03.48,0:19:06.09,Default,,0,0,0,,用逻辑去寻找的三件事么？\nDialogue: 0,0:19:06.72,0:19:09.84,Default,,0,0,0,,就是那些 找出什么为真 知道什么是真 等等\nDialogue: 0,0:19:09.84,0:19:10.52,Default,,0,0,0,,教授：好的\nDialogue: 0,0:19:10.56,0:19:15.74,Default,,0,0,0,,这算是程序员的某种“教义问答”\nDialogue: 0,0:19:15.85,0:19:19.16,Default,,0,0,0,,我们用逻辑来表达怎么算是“真的”\nDialogue: 0,0:19:20.80,0:19:21.79,Default,,0,0,0,,就像这些规则一样\nDialogue: 0,0:19:22.61,0:19:25.56,Default,,0,0,0,,我们用逻辑来检测某事是否是“真的”\nDialogue: 0,0:19:25.60,0:19:27.76,Default,,0,0,0,,但在这里我没有回答这个问题\nDialogue: 0,0:19:28.55,0:19:29.29,Default,,0,0,0,,我可以问\nDialogue: 0,0:19:29.68,0:19:32.14,Default,,0,0,0,,在这里我可以这样来问\nDialogue: 0,0:19:33.26,0:19:36.56,Default,,0,0,0,,(1 3 7)和(2 4 8)是否能够\nDialogue: 0,0:19:36.91,0:19:40.38,Default,,0,0,0,,通过MERGE-TO-FORM形成(1 2 6 19)\nDialogue: 0,0:19:41.12,0:19:44.68,Default,,0,0,0,,同样的逻辑规则会告诉我们不行\nDialogue: 0,0:19:45.69,0:19:47.93,Default,,0,0,0,,这里 我使用逻辑来检测是否为真\nDialogue: 0,0:19:48.28,0:19:50.48,Default,,0,0,0,,然后 我们也可以使用逻辑来找出为真的东西\nDialogue: 0,0:20:04.46,0:20:05.16,Default,,0,0,0,,休息一下吧\nDialogue: 0,0:20:06.13,0:20:17.02,Default,,0,0,0,,[音乐]\nDialogue: 0,0:20:17.05,0:20:20.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:20:47.59,0:20:51.02,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:20:51.07,0:20:55.60,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:20:55.63,0:21:00.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 I\nDialogue: 0,0:21:03.24,0:21:04.97,Default,,0,0,0,,教授：让我们继续来看一看\nDialogue: 0,0:21:05.84,0:21:08.44,Default,,0,0,0,,这个查询语言及其操作\nDialogue: 0,0:21:10.52,0:21:11.84,Default,,0,0,0,,首先需要注意到\nDialogue: 0,0:21:12.24,0:21:14.14,Default,,0,0,0,,当我建立好那个小型的圣经数据库后\nDialogue: 0,0:21:14.16,0:21:17.24,Default,,0,0,0,,我们就能够针对一系列的事实\nDialogue: 0,0:21:17.48,0:21:19.92,Default,,0,0,0,,以关系的方式来向这个语言提问\nDialogue: 0,0:21:21.33,0:21:25.15,Default,,0,0,0,,因此 我们先来陈述一些事实\nDialogue: 0,0:21:26.06,0:21:29.68,Default,,0,0,0,,这是波士顿一家高科技公司的\nDialogue: 0,0:21:30.08,0:21:32.62,Default,,0,0,0,,一小部分人事档案\nDialogue: 0,0:21:33.05,0:21:36.80,Default,,0,0,0,,这部分档案是Ben Bitdiddle的\nDialogue: 0,0:21:37.50,0:21:41.95,Default,,0,0,0,,Bitdiddle是这家公司的计算机向导\nDialogue: 0,0:21:42.84,0:21:45.80,Default,,0,0,0,,他是这家公司的低薪向导\nDialogue: 0,0:21:46.42,0:21:48.78,Default,,0,0,0,,他的上司是Oliver Warbucks\nDialogue: 0,0:21:49.28,0:21:50.70,Default,,0,0,0,,这里是他的住址\nDialogue: 0,0:21:52.15,0:21:56.54,Default,,0,0,0,,我们按照这样的格式给出信息：职务、薪水、上司、住址\nDialogue: 0,0:21:57.56,0:21:59.25,Default,,0,0,0,,还有一些其它的约定\nDialogue: 0,0:21:59.25,0:22:02.22,Default,,0,0,0,,这里的COMPUTER表示BEN在计算机分部工作\nDialogue: 0,0:22:02.76,0:22:04.94,Default,,0,0,0,,而他在这个分部的工作是向导\nDialogue: 0,0:22:05.66,0:22:07.15,Default,,0,0,0,,这里是其他人的\nDialogue: 0,0:22:07.16,0:22:12.28,Default,,0,0,0,,Alyssa P.Hacker是一名计算机程序员\nDialogue: 0,0:22:13.36,0:22:14.60,Default,,0,0,0,,她的上司是Ben\nDialogue: 0,0:22:15.21,0:22:16.54,Default,,0,0,0,,而她住在Cambridge\nDialogue: 0,0:22:17.55,0:22:19.42,Default,,0,0,0,,Ben手下的另外一个程序员\nDialogue: 0,0:22:20.03,0:22:21.44,Default,,0,0,0,,叫做Lem E. Tweakit\nDialogue: 0,0:22:22.82,0:22:26.73,Default,,0,0,0,,实习程序员 Louis Reasoner\nDialogue: 0,0:22:27.42,0:22:28.62,Default,,0,0,0,,在Alyssa手下工作\nDialogue: 0,0:22:30.10,0:22:35.45,Default,,0,0,0,,公司里的“大老板”不为任何人工作\nDialogue: 0,0:22:36.81,0:22:38.11,Default,,0,0,0,,这就是Oliver Warbucks的档案了\nDialogue: 0,0:22:38.11,0:22:39.31,Default,,0,0,0,,我们将要做的就是\nDialogue: 0,0:22:40.94,0:22:43.66,Default,,0,0,0,,对这个小型的世界提问\nDialogue: 0,0:22:44.97,0:22:48.40,Default,,0,0,0,,这将是我们进行逻辑运算的样本世界\nDialogue: 0,0:22:51.42,0:22:54.96,Default,,0,0,0,,我再最后一次强调一下\nDialogue: 0,0:22:55.60,0:22:58.20,Default,,0,0,0,,你们应该从这门课中学到的最重要的知识\nDialogue: 0,0:22:58.80,0:23:01.66,Default,,0,0,0,,也就是 当别人向你介绍语言时\nDialogue: 0,0:23:02.25,0:23:04.43,Default,,0,0,0,,你要问：“它的基本元素是什么？”\nDialogue: 0,0:23:06.12,0:23:07.79,Default,,0,0,0,,组合的手段有哪些？\nDialogue: 0,0:23:14.70,0:23:16.40,Default,,0,0,0,,如何把基本元素组织在一起\nDialogue: 0,0:23:16.67,0:23:19.37,Default,,0,0,0,,然后把它们抽象出来？\nDialogue: 0,0:23:19.96,0:23:21.93,Default,,0,0,0,,如何抽象这些复合元素\nDialogue: 0,0:23:24.68,0:23:27.58,Default,,0,0,0,,以便于你能够复用它们构造更复杂的东西？\nDialogue: 0,0:23:29.02,0:23:30.81,Default,,0,0,0,,我已经强调过很多次了\nDialogue: 0,0:23:31.16,0:23:32.48,Default,,0,0,0,,但还是值得重申一遍\nDialogue: 0,0:23:35.00,0:23:36.67,Default,,0,0,0,,记住了么？我们开始了\nDialogue: 0,0:23:36.67,0:23:37.34,Default,,0,0,0,,首先是基本元素\nDialogue: 0,0:23:37.77,0:23:39.44,Default,,0,0,0,,这其中 只有唯一的基本元素\nDialogue: 0,0:23:40.96,0:23:43.20,Default,,0,0,0,,这门语言中的基本元素就是“查询”\nDialogue: 0,0:23:44.14,0:23:45.74,Default,,0,0,0,,一条基本查询\nDialogue: 0,0:23:46.81,0:23:48.25,Default,,0,0,0,,我们先来看几条基本查询\nDialogue: 0,0:23:51.82,0:23:53.02,Default,,0,0,0,,首先 这条查询问的是\nDialogue: 0,0:23:53.10,0:23:54.81,Default,,0,0,0,,“谁是计算机程序员？”\nDialogue: 0,0:23:55.55,0:23:59.88,Default,,0,0,0,,或者可以解释为：找出数据库中\nDialogue: 0,0:24:01.55,0:24:06.14,Default,,0,0,0,,所有JOB栏为COMPUTER PROGRAMMER的事实\nDialogue: 0,0:24:06.64,0:24:08.01,Default,,0,0,0,,这里有一些小语法\nDialogue: 0,0:24:08.47,0:24:10.59,Default,,0,0,0,,不带问号的都是字面量\nDialogue: 0,0:24:11.28,0:24:13.15,Default,,0,0,0,,?X表示X是变量\nDialogue: 0,0:24:13.31,0:24:15.56,Default,,0,0,0,,而这条查询会匹配 比如说 --\nDialogue: 0,0:24:16.03,0:24:19.00,Default,,0,0,0,,Alyssa P. Hacker 是程序员\nDialogue: 0,0:24:19.28,0:24:21.93,Default,,0,0,0,,其中X为Alyssa P. Hacker这条事实\nDialogue: 0,0:24:26.82,0:24:29.98,Default,,0,0,0,,或者更一般地 我可以在一条查询中引入两个变量\nDialogue: 0,0:24:30.75,0:24:31.45,Default,,0,0,0,,我可以问\nDialogue: 0,0:24:31.60,0:24:35.88,Default,,0,0,0,,?X的JOB必须是COMPUTER ?TYPE\nDialogue: 0,0:24:39.34,0:24:41.39,Default,,0,0,0,,也就是会匹配COMPUTER WIZARD\nDialogue: 0,0:24:42.14,0:24:44.28,Default,,0,0,0,,所以这里?TYPE可能会匹配WIZARD\nDialogue: 0,0:24:44.92,0:24:46.46,Default,,0,0,0,,也可能会匹配PROGRAMMER\nDialogue: 0,0:24:47.48,0:24:50.37,Default,,0,0,0,,而?X会匹配不同的东西\nDialogue: 0,0:24:50.37,0:24:52.24,Default,,0,0,0,,但在我们的这个小例子中\nDialogue: 0,0:24:52.25,0:24:55.15,Default,,0,0,0,,数据库中只有三条事实符合那条查询\nDialogue: 0,0:24:59.12,0:25:02.08,Default,,0,0,0,,把语法说得再清楚一点 同样的查询\nDialogue: 0,0:25:05.29,0:25:08.09,Default,,0,0,0,,同样的这条指定了?X的JOB的查询\nDialogue: 0,0:25:09.85,0:25:11.79,Default,,0,0,0,,并不能够与Lewis Reasoner匹配\nDialogue: 0,0:25:11.84,0:25:13.64,Default,,0,0,0,,这是因为我这里所写的\nDialogue: 0,0:25:14.22,0:25:17.74,Default,,0,0,0,,表示要匹配的是由两个符号构成的表\nDialogue: 0,0:25:19.96,0:25:21.96,Default,,0,0,0,,其中首元素必须为单词“COMPUTER”\nDialogue: 0,0:25:22.32,0:25:23.80,Default,,0,0,0,,而第二个可以匹配任意的东西\nDialogue: 0,0:25:25.08,0:25:27.32,Default,,0,0,0,,而Lewis这里的工作描述有三个符号\nDialogue: 0,0:25:27.80,0:25:28.83,Default,,0,0,0,,因此不匹配\nDialogue: 0,0:25:30.34,0:25:32.19,Default,,0,0,0,,你们还需要知道的一种语法是\nDialogue: 0,0:25:35.04,0:25:38.32,Default,,0,0,0,,更具一般性的点记号\nDialogue: 0,0:25:40.17,0:25:42.92,Default,,0,0,0,,这个标准的表记号表示的是\nDialogue: 0,0:25:43.04,0:25:43.82,Default,,0,0,0,,首先这是一个表\nDialogue: 0,0:25:44.12,0:25:47.32,Default,,0,0,0,,它的首元素为单词“COMPUTER”\nDialogue: 0,0:25:47.58,0:25:50.22,Default,,0,0,0,,而其余的部分 我们把它们称作?TYPE\nDialogue: 0,0:25:53.73,0:25:55.50,Default,,0,0,0,,因此这条查询就会匹配上\nDialogue: 0,0:25:56.93,0:25:59.31,Default,,0,0,0,,Lewis的工作是COMPUTER PROGRAMMER TRAINEE\nDialogue: 0,0:25:59.44,0:26:03.29,Default,,0,0,0,,而?TYPE的值将会是这个表的CDR部分\nDialogue: 0,0:26:03.32,0:26:05.64,Default,,0,0,0,,也就是表(PROGRAMMER TRAINEE)\nDialogue: 0,0:26:06.96,0:26:10.46,Default,,0,0,0,,Lisp源码读取器会自动完成对点记号的处理\nDialogue: 0,0:26:15.90,0:26:17.76,Default,,0,0,0,,让我们来实际操作一下\nDialogue: 0,0:26:17.76,0:26:20.51,Default,,0,0,0,,我将向语言系统输入这些查询\nDialogue: 0,0:26:20.76,0:26:21.82,Default,,0,0,0,,然后得到结果\nDialogue: 0,0:26:22.54,0:26:24.48,Default,,0,0,0,,让我们在计算机中试试\nDialogue: 0,0:26:25.18,0:26:26.51,Default,,0,0,0,,我可以问\nDialogue: 0,0:26:27.34,0:26:28.88,Default,,0,0,0,,谁在计算机分部工作？\nDialogue: 0,0:26:30.00,0:26:38.22,Default,,0,0,0,,(JOB ?X (COMPUTER . ?Y)\nDialogue: 0,0:26:39.73,0:26:41.48,Default,,0,0,0,,哑变量的名字并不重要\nDialogue: 0,0:26:42.76,0:26:44.14,Default,,0,0,0,,查询的结果是\nDialogue: 0,0:26:44.41,0:26:45.68,Default,,0,0,0,,有四条记录\nDialogue: 0,0:26:48.65,0:26:50.09,Default,,0,0,0,,我也可以问\nDialogue: 0,0:26:50.56,0:26:52.38,Default,,0,0,0,,大家的上司都是谁？\nDialogue: 0,0:26:52.81,0:26:54.88,Default,,0,0,0,,我输入一条基本查询\nDialogue: 0,0:26:56.52,0:26:59.39,Default,,0,0,0,,(SUPERVISOR ?X ?Y)\nDialogue: 0,0:27:02.56,0:27:05.42,Default,,0,0,0,,这些都是我所知道的上下级关系\nDialogue: 0,0:27:05.54,0:27:08.83,Default,,0,0,0,,或者我也可以问：“谁住在Cambridge？”\nDialogue: 0,0:27:08.83,0:27:09.47,Default,,0,0,0,,我就这么输入：\nDialogue: 0,0:27:10.24,0:27:20.92,Default,,0,0,0,,(ADDRESS ?X (CAMBRIDGE . ?T))\nDialogue: 0,0:27:25.09,0:27:26.89,Default,,0,0,0,,只有一个人住在Cambridge\nDialogue: 0,0:27:30.82,0:27:32.17,Default,,0,0,0,,这些就是基本查询\nDialogue: 0,0:27:32.17,0:27:34.96,Default,,0,0,0,,你们看到的这些 就是与系统的基础交互\nDialogue: 0,0:27:35.29,0:27:39.24,Default,,0,0,0,,你输入一条查询 他输出所有可能的查询\nDialogue: 0,0:27:39.62,0:27:40.65,Default,,0,0,0,,换句话说 也就是\nDialogue: 0,0:27:40.67,0:27:44.16,Default,,0,0,0,,它找出这些变量所有可能的值\nDialogue: 0,0:27:44.19,0:27:45.87,Default,,0,0,0,,不管它是叫X、Y还是T\nDialogue: 0,0:27:46.09,0:27:52.08,Default,,0,0,0,,然后它输出的是用所有可行值实例化该条查询的结果\nDialogue: 0,0:27:52.92,0:27:55.16,Default,,0,0,0,,也就是规则系统那一课讲的“实例化”\nDialogue: 0,0:27:55.16,0:27:58.83,Default,,0,0,0,,用变量所有可能的值来实例化查询\nDialogue: 0,0:27:59.00,0:28:00.35,Default,,0,0,0,,然后输出所有的结果\nDialogue: 0,0:28:01.00,0:28:03.35,Default,,0,0,0,,当然 还有不同的呈现结果的方式\nDialogue: 0,0:28:03.35,0:28:06.01,Default,,0,0,0,,比如说 Prolog就有些不一样\nDialogue: 0,0:28:06.01,0:28:07.44,Default,,0,0,0,,它并不向你返回查询\nDialogue: 0,0:28:07.76,0:28:10.78,Default,,0,0,0,,Prolog会输出X=这个 Y=那个\nDialogue: 0,0:28:10.97,0:28:12.94,Default,,0,0,0,,又或者X=这个 Y=那个\nDialogue: 0,0:28:13.66,0:28:15.48,Default,,0,0,0,,这是使用界面层次的差别\nDialogue: 0,0:28:15.71,0:28:17.05,Default,,0,0,0,,你可以根据你的喜好来决定\nDialogue: 0,0:28:18.97,0:28:19.58,Default,,0,0,0,,我们继续\nDialogue: 0,0:28:21.00,0:28:22.68,Default,,0,0,0,,也就是说 这个语言中的基本元素\nDialogue: 0,0:28:23.39,0:28:24.57,Default,,0,0,0,,只有一个 对吧？\nDialogue: 0,0:28:24.57,0:28:27.23,Default,,0,0,0,,也就是基本查询\nDialogue: 0,0:28:31.31,0:28:32.56,Default,,0,0,0,,来看看组合的手段\nDialogue: 0,0:28:34.33,0:28:37.68,Default,,0,0,0,,我们来考察一下这个语言中的复合查询\nDialogue: 0,0:28:39.77,0:28:40.46,Default,,0,0,0,,比如这条\nDialogue: 0,0:28:41.79,0:28:42.51,Default,,0,0,0,,这条查询是说\nDialogue: 0,0:28:45.05,0:28:48.22,Default,,0,0,0,,列举出所有在计算机分部工作的人\nDialogue: 0,0:28:49.81,0:28:52.00,Default,,0,0,0,,在计算机分部工作的人\nDialogue: 0,0:28:52.54,0:28:53.96,Default,,0,0,0,,以及他们的上司\nDialogue: 0,0:28:56.80,0:28:58.83,Default,,0,0,0,,我使用AND来编写这条查询\nDialogue: 0,0:29:00.22,0:29:04.06,Default,,0,0,0,,(AND (JOB ?X (COMPUTER . ?Y))\nDialogue: 0,0:29:04.92,0:29:06.83,Default,,0,0,0,,(JOB ?X (COMPUTER . ?Y))\nDialogue: 0,0:29:07.56,0:29:10.03,Default,,0,0,0,,并且(SUPERVISOR ?X ?Z)\nDialogue: 0,0:29:11.44,0:29:14.16,Default,,0,0,0,,找出所有在计算机分部工作的人 -- 对应这条\nDialogue: 0,0:29:14.30,0:29:15.88,Default,,0,0,0,,以及它们的上司\nDialogue: 0,0:29:16.46,0:29:17.82,Default,,0,0,0,,注意这条查询中\nDialogue: 0,0:29:18.67,0:29:22.41,Default,,0,0,0,,我引入了三个变量 ?X ?Y 以及 ?Z\nDialogue: 0,0:29:23.58,0:29:28.65,Default,,0,0,0,,并且 这两个?X应该匹配同样的东西\nDialogue: 0,0:29:29.45,0:29:31.16,Default,,0,0,0,,?X被约束在了计算机分部中\nDialogue: 0,0:29:31.31,0:29:33.00,Default,,0,0,0,,并且?X的上司是?Z\nDialogue: 0,0:29:34.81,0:29:35.80,Default,,0,0,0,,我们再来看一条\nDialogue: 0,0:29:37.25,0:29:39.28,Default,,0,0,0,,AND算是一种组合手段\nDialogue: 0,0:29:41.44,0:29:43.96,Default,,0,0,0,,哪些人的薪水超过$30,000？\nDialogue: 0,0:29:45.71,0:29:51.71,Default,,0,0,0,,(AND (SALARY ?P ?A)\nDialogue: 0,0:29:54.59,0:29:57.45,Default,,0,0,0,,而关于?A的要求则是\nDialogue: 0,0:29:57.48,0:30:00.12,Default,,0,0,0,,(LISP-VALUE > ?A 300000)\nDialogue: 0,0:30:00.60,0:30:03.23,Default,,0,0,0,,这里的LISP-VALUE是一个接口\nDialogue: 0,0:30:04.30,0:30:10.04,Default,,0,0,0,,用来连接查询语言与其底层的Lisp\nDialogue: 0,0:30:10.60,0:30:12.72,Default,,0,0,0,,LISP-VALUE让你能够在查询\nDialogue: 0,0:30:12.75,0:30:16.91,Default,,0,0,0,,中调用任意的Lisp谓词\nDialogue: 0,0:30:17.18,0:30:20.11,Default,,0,0,0,,因为我要用Lisp中的谓词> 所以我用LISP-VALUE\nDialogue: 0,0:30:21.02,0:30:21.75,Default,,0,0,0,,所以这里我用了AND\nDialogue: 0,0:30:21.75,0:30:24.48,Default,,0,0,0,,因此这样就查询出了薪水超过$30000的人\nDialogue: 0,0:30:28.19,0:30:30.03,Default,,0,0,0,,或者这条更复杂的查询\nDialogue: 0,0:30:31.27,0:30:35.02,Default,,0,0,0,,告诉我所有那些 在计算机分部中工作\nDialogue: 0,0:30:36.25,0:30:39.36,Default,,0,0,0,,但他的上司不在计算机分部工作的人\nDialogue: 0,0:30:42.79,0:30:45.51,Default,,0,0,0,,(AND (JOB ?X (COMPUTER . ?Y))\nDialogue: 0,0:30:45.51,0:30:47.32,Default,,0,0,0,,表示?X在计算机分部工作\nDialogue: 0,0:30:47.78,0:30:49.24,Default,,0,0,0,,但是呢\nDialogue: 0,0:30:50.49,0:30:54.25,Default,,0,0,0,,?X的上司?Z\nDialogue: 0,0:30:55.37,0:30:57.87,Default,,0,0,0,,?Z的JOB不是形如(COMPUTER ...)一类的\nDialogue: 0,0:30:59.62,0:31:00.35,Default,,0,0,0,,同样的\nDialogue: 0,0:31:00.51,0:31:02.38,Default,,0,0,0,,这两个?X应该是一致的\nDialogue: 0,0:31:03.20,0:31:05.76,Default,,0,0,0,,而这两个?Z也应该是一致的\nDialogue: 0,0:31:09.39,0:31:11.38,Default,,0,0,0,,你又了解了另一种组合手段 -- NOT\nDialogue: 0,0:31:17.71,0:31:18.67,Default,,0,0,0,,好了 再让我们来试试这些\nDialogue: 0,0:31:20.88,0:31:22.08,Default,,0,0,0,,它同样起效\nDialogue: 0,0:31:22.40,0:31:24.12,Default,,0,0,0,,我可以问计算机：\nDialogue: 0,0:31:26.89,0:31:35.40,Default,,0,0,0,,(AND (JOB ?X (COMPUTER . ?Y)))\nDialogue: 0,0:31:38.84,0:31:45.95,Default,,0,0,0,,另一个条件是(SUPERVISOR ?X ?Z)\nDialogue: 0,0:31:46.83,0:31:49.53,Default,,0,0,0,,我把这条查询输入进去\nDialogue: 0,0:31:51.07,0:31:52.97,Default,,0,0,0,,计算机返回给我们的\nDialogue: 0,0:31:54.00,0:31:58.73,Default,,0,0,0,,计算机利用所有可能的答案把我的查询实例化了\nDialogue: 0,0:31:58.93,0:32:00.08,Default,,0,0,0,,你会发现有很多的答案\nDialogue: 0,0:32:01.69,0:32:02.14,Default,,0,0,0,,好\nDialogue: 0,0:32:02.19,0:32:04.04,Default,,0,0,0,,之所以把这门语言称作“逻辑语言”\nDialogue: 0,0:32:05.21,0:32:06.60,Default,,0,0,0,,是因为这门语言中的组合手段\nDialogue: 0,0:32:06.64,0:32:09.47,Default,,0,0,0,,都是逻辑运算\nDialogue: 0,0:32:09.80,0:32:15.68,Default,,0,0,0,,组合的手段有AND和NOT\nDialogue: 0,0:32:15.96,0:32:17.92,Default,,0,0,0,,以及我还没有告诉你的OR\nDialogue: 0,0:32:18.49,0:32:20.36,Default,,0,0,0,,我还告诉过你LISP-VALUE\nDialogue: 0,0:32:20.72,0:32:24.48,Default,,0,0,0,,当然 虽然它不是一个逻辑运算\nDialogue: 0,0:32:24.51,0:32:26.89,Default,,0,0,0,,但是这个特殊的小技巧把它跟Lisp连接在了一起\nDialogue: 0,0:32:27.34,0:32:28.75,Default,,0,0,0,,让你获得了更多的力量\nDialogue: 0,0:32:29.25,0:32:30.67,Default,,0,0,0,,这些就是组合手段\nDialogue: 0,0:32:32.59,0:32:33.98,Default,,0,0,0,,好 接着是抽象手段\nDialogue: 0,0:32:34.16,0:32:35.21,Default,,0,0,0,,我们想要的是\nDialogue: 0,0:32:38.27,0:32:41.24,Default,,0,0,0,,想让我们回过头来看上一张幻灯片\nDialogue: 0,0:32:42.26,0:32:44.25,Default,,0,0,0,,我们想要把一些非常复杂的东西\nDialogue: 0,0:32:44.46,0:32:48.00,Default,,0,0,0,,比如不与上司在同一部门工作\nDialogue: 0,0:32:48.01,0:32:50.09,Default,,0,0,0,,的人的这种概念\nDialogue: 0,0:32:52.40,0:32:55.10,Default,,0,0,0,,像以前一样 给它命名\nDialogue: 0,0:32:56.09,0:32:58.12,Default,,0,0,0,,如果在某个分部工作的人\nDialogue: 0,0:32:58.17,0:33:00.25,Default,,0,0,0,,他的上司却不在那个分部工作\nDialogue: 0,0:33:00.48,0:33:01.93,Default,,0,0,0,,这就意味着他是个“大腕”\nDialogue: 0,0:33:02.75,0:33:05.13,Default,,0,0,0,,这样 我们就定义一条规则指明\nDialogue: 0,0:33:06.43,0:33:09.16,Default,,0,0,0,,如果?X是某个部门的BIGSHOT\nDialogue: 0,0:33:10.91,0:33:14.68,Default,,0,0,0,,如果他在该部门工作\nDialogue: 0,0:33:16.04,0:33:20.08,Default,,0,0,0,,并且他的上司不在该部门工作\nDialogue: 0,0:33:21.51,0:33:22.94,Default,,0,0,0,,因此这就是我们的抽象手段\nDialogue: 0,0:33:22.94,0:33:23.90,Default,,0,0,0,,这是一条规则\nDialogue: 0,0:33:26.22,0:33:27.58,Default,,0,0,0,,规则由三部分构成\nDialogue: 0,0:33:31.00,0:33:32.48,Default,,0,0,0,,关键字RULE表明这是一条规则\nDialogue: 0,0:33:33.40,0:33:35.48,Default,,0,0,0,,接着是规则的结论\nDialogue: 0,0:33:37.53,0:33:39.07,Default,,0,0,0,,然后是规则的体\nDialogue: 0,0:33:40.00,0:33:41.88,Default,,0,0,0,,你可以把它解读为这样的一段逻辑：\nDialogue: 0,0:33:41.92,0:33:45.15,Default,,0,0,0,,如果你知道规则的体为真\nDialogue: 0,0:33:46.40,0:33:48.72,Default,,0,0,0,,那么你就可以推导出结论为真\nDialogue: 0,0:33:49.45,0:33:53.28,Default,,0,0,0,,或者说为了推断出?X是某个部门的“大腕”\nDialogue: 0,0:33:53.79,0:33:55.71,Default,,0,0,0,,这些条件足够验证了\nDialogue: 0,0:33:57.48,0:33:58.82,Default,,0,0,0,,这就是规则的形式\nDialogue: 0,0:34:03.28,0:34:06.16,Default,,0,0,0,,让我们回过头来看看\nDialogue: 0,0:34:06.73,0:34:07.92,Default,,0,0,0,,课间休息前我举的那个例子\nDialogue: 0,0:34:08.11,0:34:10.68,Default,,0,0,0,,我们来看看 如果用规则来描述会是什么样的\nDialogue: 0,0:34:11.44,0:34:12.84,Default,,0,0,0,,我会抽取出其中的逻辑\nDialogue: 0,0:34:13.08,0:34:15.50,Default,,0,0,0,,并将它们变为这种格式的规则\nDialogue: 0,0:34:18.73,0:34:19.35,Default,,0,0,0,,就有了下面的规则\nDialogue: 0,0:34:19.35,0:34:20.96,Default,,0,0,0,,这就是MERGE-TO-FORM的规则\nDialogue: 0,0:34:21.71,0:34:22.97,Default,,0,0,0,,这个规则是说\nDialogue: 0,0:34:26.28,0:34:29.62,Default,,0,0,0,,'()与?Y可以通过MERGE-TO-FORM形成?Y\nDialogue: 0,0:34:29.62,0:34:30.87,Default,,0,0,0,,这是规则的结论\nDialogue: 0,0:34:33.21,0:34:35.74,Default,,0,0,0,,需要注意的是 这个特定的规则没有体\nDialogue: 0,0:34:36.65,0:34:37.66,Default,,0,0,0,,在这门语言中\nDialogue: 0,0:34:38.11,0:34:40.86,Default,,0,0,0,,没有体的规则总是真的\nDialogue: 0,0:34:41.23,0:34:42.51,Default,,0,0,0,,你总是可以假设它们为真\nDialogue: 0,0:34:45.19,0:34:46.49,Default,,0,0,0,,另一条规则说的是\nDialogue: 0,0:34:46.64,0:34:49.46,Default,,0,0,0,,任意对象与空表进行MERGE-TO-FORM 得到的任然是原物\nDialogue: 0,0:34:49.46,0:34:50.12,Default,,0,0,0,,就是这条\nDialogue: 0,0:34:50.90,0:34:53.55,Default,,0,0,0,,(MERGE-TO-FORM ?Y '() ?Y)\nDialogue: 0,0:34:55.51,0:34:58.40,Default,,0,0,0,,它们对应了我们MERGE过程中的两个终止条件\nDialogue: 0,0:34:58.44,0:34:59.77,Default,,0,0,0,,但我们现在讨论的是逻辑\nDialogue: 0,0:35:00.41,0:35:01.45,Default,,0,0,0,,而非过程\nDialogue: 0,0:35:03.49,0:35:04.48,Default,,0,0,0,,我们还有另外一条规则\nDialogue: 0,0:35:04.83,0:35:08.73,Default,,0,0,0,,描述的是 如果你知道如何MERGE较短的表\nDialogue: 0,0:35:08.91,0:35:09.83,Default,,0,0,0,,那么你就可以把它们结合在一起\nDialogue: 0,0:35:09.83,0:35:14.16,Default,,0,0,0,,这条规则说：如果你有表?X、?Y以及?Z\nDialogue: 0,0:35:14.92,0:35:17.61,Default,,0,0,0,,如果你想推断出(?A . ?X)\nDialogue: 0,0:35:17.63,0:35:19.08,Default,,0,0,0,,这个记法表示(CONS ?A ?X)\nDialogue: 0,0:35:19.48,0:35:22.36,Default,,0,0,0,,或者说首元素是'A、剩余元素是'X的表\nDialogue: 0,0:35:23.16,0:35:27.40,Default,,0,0,0,,由此 如果你想推断(MERGE-TO-FROM (?A . ?X) (?B . ?Y) (?B . ?Z))\nDialogue: 0,0:35:30.36,0:35:33.90,Default,,0,0,0,,毋宁说如果你想要把表(?A ?X)和表(?B ?Y)合并得到\nDialogue: 0,0:35:33.92,0:35:35.85,Default,,0,0,0,,一个以?B为首的表\nDialogue: 0,0:35:36.76,0:35:40.67,Default,,0,0,0,,你想要推断出这个结果 就要满足\nDialogue: 0,0:35:40.91,0:35:44.48,Default,,0,0,0,,不但(MERGE-TP-FORM (?A . ?X) ?Y ?Z)\nDialogue: 0,0:35:45.18,0:35:47.24,Default,,0,0,0,,并且(LISP-VALUE > ?A ?B)\nDialogue: 0,0:35:48.69,0:35:50.59,Default,,0,0,0,,因此当我在合并它们时 ?B会首先出现在表中\nDialogue: 0,0:35:51.82,0:35:54.91,Default,,0,0,0,,这就是简单的把我之前写的伪代码\nDialogue: 0,0:35:55.24,0:35:57.18,Default,,0,0,0,,翻译成逻辑的语言\nDialogue: 0,0:35:57.96,0:36:01.63,Default,,0,0,0,,为了翻译完整 这还里有种情况\nDialogue: 0,0:36:02.88,0:36:05.95,Default,,0,0,0,,(MERGE-TO-FORM (?A . ?X) (?B . ?Y) (?A . ?Z))成立\nDialogue: 0,0:36:06.08,0:36:09.16,Default,,0,0,0,,就需要(MERGE-TO-FORM ?X (?B . ?Y) ?Z)\nDialogue: 0,0:36:09.47,0:36:11.00,Default,,0,0,0,,和(LISP-VALUE > ?B ?A)都成立\nDialogue: 0,0:36:12.19,0:36:15.98,Default,,0,0,0,,我已经把这个用逻辑语言编写的小程序输入计算机了\nDialogue: 0,0:36:16.01,0:36:17.07,Default,,0,0,0,,现在让我们来试着运行一下\nDialogue: 0,0:36:21.90,0:36:23.90,Default,,0,0,0,,由于我已经输入过MERGE-TO-FORM的规则了\nDialogue: 0,0:36:24.62,0:36:25.77,Default,,0,0,0,,我就可以\nDialogue: 0,0:36:27.04,0:36:28.51,Default,,0,0,0,,我可以像过程一样使用它\nDialogue: 0,0:36:28.51,0:36:38.24,Default,,0,0,0,,我可以问(MERGE-TO-FORM (1 3) (2 7) ?X)\nDialogue: 0,0:36:39.42,0:36:41.55,Default,,0,0,0,,这里 我把它当作一个Lisp过程来使用\nDialogue: 0,0:36:43.16,0:36:44.97,Default,,0,0,0,,它先会思考一会儿\nDialogue: 0,0:36:46.43,0:36:47.56,Default,,0,0,0,,然后应用这些规则\nDialogue: 0,0:36:50.78,0:36:51.92,Default,,0,0,0,,它找到了一个答案\nDialogue: 0,0:36:52.80,0:36:54.54,Default,,0,0,0,,现在它还要继续寻找其它的答案\nDialogue: 0,0:36:55.07,0:36:57.32,Default,,0,0,0,,因为它事先不知道这里答案只有一个\nDialogue: 0,0:36:57.81,0:36:59.90,Default,,0,0,0,,因此它就在这里检查所有的可能性\nDialogue: 0,0:37:00.41,0:37:02.54,Default,,0,0,0,,确认没有后 输出'DONE'\nDialogue: 0,0:37:03.16,0:37:05.07,Default,,0,0,0,,这里 我把它们当作过程来使用\nDialogue: 0,0:37:05.21,0:37:09.05,Default,,0,0,0,,不过要注意 我还可以问不同类型的问题\nDialogue: 0,0:37:10.22,0:37:11.07,Default,,0,0,0,,我可以问\nDialogue: 0,0:37:18.56,0:37:24.59,Default,,0,0,0,,(MERGE-TO-FORM (2 ?A)\nDialogue: 0,0:37:24.59,0:37:27.90,Default,,0,0,0,,一个我已知是以2为首的二元表\nDialogue: 0,0:37:29.37,0:37:31.26,Default,,0,0,0,,而另外一个东西是未知的\nDialogue: 0,0:37:33.05,0:37:35.04,Default,,0,0,0,,用?X来表示这个未知的表\nDialogue: 0,0:37:36.48,0:37:39.51,Default,,0,0,0,,可以通过MERGE-TO-FORM形成(1 2 3 4)\nDialogue: 0,0:37:42.76,0:37:44.11,Default,,0,0,0,,现在它将思考这个问题\nDialogue: 0,0:37:44.59,0:37:49.40,Default,,0,0,0,,它会找到 -- 它找到了一种可能\nDialogue: 0,0:37:49.52,0:37:52.46,Default,,0,0,0,,比如A=3 X=(1 4)\nDialogue: 0,0:37:53.72,0:37:55.16,Default,,0,0,0,,现在 它又要继续检查\nDialogue: 0,0:37:56.56,0:37:57.71,Default,,0,0,0,,因为它事先并不知道\nDialogue: 0,0:37:57.74,0:38:00.30,Default,,0,0,0,,这里并没有其它的可能了\nDialogue: 0,0:38:03.68,0:38:06.57,Default,,0,0,0,,或者 就像我说过的\nDialogue: 0,0:38:07.00,0:38:09.84,Default,,0,0,0,,我可以问\nDialogue: 0,0:38:10.54,0:38:17.55,Default,,0,0,0,,能够通过MERGE-TO-FORM形成(1 2 3 4 5)的?X和?Y分别是什么？\nDialogue: 0,0:38:23.68,0:38:25.53,Default,,0,0,0,,语言系统又要思考这个问题\nDialogue: 0,0:38:28.49,0:38:30.31,Default,,0,0,0,,它可能会得到很多答案\nDialogue: 0,0:38:35.18,0:38:38.57,Default,,0,0,0,,这里我们就体会到了缓慢的代价\nDialogue: 0,0:38:42.21,0:38:43.88,Default,,0,0,0,,大概是有三种原因造成这样\nDialogue: 0,0:38:43.88,0:38:46.22,Default,,0,0,0,,首先 这门语言经过了两次解释\nDialogue: 0,0:38:47.63,0:38:49.72,Default,,0,0,0,,然而在真正的实现中\nDialogue: 0,0:38:49.76,0:38:52.04,Default,,0,0,0,,你应该把这些编译成基本运算\nDialogue: 0,0:38:52.19,0:38:53.87,Default,,0,0,0,,其次就是\nDialogue: 0,0:38:53.88,0:38:58.11,Default,,0,0,0,,这个MERGE算法 是双重递归的\nDialogue: 0,0:38:58.38,0:39:00.06,Default,,0,0,0,,因此它需要花费很长的时间\nDialogue: 0,0:39:01.02,0:39:04.33,Default,,0,0,0,,最后呢 它又要遍历所有的情况\nDialogue: 0,0:39:04.59,0:39:07.13,Default,,0,0,0,,找出 -- 找出什么呢？\nDialogue: 0,0:39:07.13,0:39:08.73,Default,,0,0,0,,所有的2^5种可行解\nDialogue: 0,0:39:12.14,0:39:14.96,Default,,0,0,0,,我们发现它们以某种相当随意的顺序输出\nDialogue: 0,0:39:15.00,0:39:18.14,Default,,0,0,0,,这取决于它们用什么样的顺序尝试这些规则\nDialogue: 0,0:39:20.16,0:39:22.11,Default,,0,0,0,,事实上 在后期制作本视频时\nDialogue: 0,0:39:22.40,0:39:23.48,Default,,0,0,0,,我们将加速这段\nDialogue: 0,0:39:24.08,0:39:26.60,Default,,0,0,0,,我们就不再这里浪费时间了\nDialogue: 0,0:39:26.60,0:39:28.27,Default,,0,0,0,,课后你们可以自行尝试\nDialogue: 0,0:39:29.48,0:39:34.24,Default,,0,0,0,,好吧 它还在运行\nDialogue: 0,0:39:39.22,0:39:41.12,Default,,0,0,0,,总之 一共有32种可能\nDialogue: 0,0:39:41.13,0:39:42.63,Default,,0,0,0,,我们就不等到输出所有的结果了\nDialogue: 0,0:39:47.85,0:39:50.44,Default,,0,0,0,,因此 这门语言中的抽象手段就是RULE\nDialogue: 0,0:39:53.53,0:39:58.01,Default,,0,0,0,,我们用逻辑把事物组织在一起\nDialogue: 0,0:39:59.12,0:40:00.08,Default,,0,0,0,,并为它们命名\nDialogue: 0,0:40:00.35,0:40:03.41,Default,,0,0,0,,你们可以认为这是为一组特定的逻辑模式命名\nDialogue: 0,0:40:03.41,0:40:04.54,Default,,0,0,0,,你们可以把它想做\nDialogue: 0,0:40:04.56,0:40:06.75,Default,,0,0,0,,如果我们想要推断出某个结论\nDialogue: 0,0:40:07.90,0:40:09.52,Default,,0,0,0,,就可以应用这些逻辑规则\nDialogue: 0,0:40:10.66,0:40:13.20,Default,,0,0,0,,这些就是这门语言中的三种要素\nDialogue: 0,0:40:13.42,0:40:14.56,Default,,0,0,0,,我们先休息一会儿\nDialogue: 0,0:40:14.60,0:40:16.59,Default,,0,0,0,,然后再来讨论如何实际实现\nDialogue: 0,0:40:23.61,0:40:28.84,Default,,0,0,0,,学生：使用LISP-VALUE之类的基本过程会影响\nDialogue: 0,0:40:29.15,0:40:30.64,Default,,0,0,0,,查询的双向性吗？\nDialogue: 0,0:40:31.77,0:40:34.48,Default,,0,0,0,,教授：这个问题 -- 你问的是\nDialogue: 0,0:40:35.08,0:40:36.92,Default,,0,0,0,,使用LISP-VALUE是否会影响\nDialogue: 0,0:40:37.53,0:40:40.09,Default,,0,0,0,,双向地推断一条查询\nDialogue: 0,0:40:40.09,0:40:42.81,Default,,0,0,0,,虽然我们还没有实际讨论具体实现\nDialogue: 0,0:40:43.68,0:40:45.52,Default,,0,0,0,,但是它们确实会造成影响\nDialogue: 0,0:40:46.89,0:40:50.20,Default,,0,0,0,,通常来说 我们最后将会发现\nDialogue: 0,0:40:50.22,0:40:52.17,Default,,0,0,0,,虽然我不会讲得太细\nDialogue: 0,0:40:53.21,0:40:59.36,Default,,0,0,0,,当你使用NOT和LISP-VALUE时 会变得相当复杂\nDialogue: 0,0:40:59.55,0:41:02.89,Default,,0,0,0,,或者实际上 只要你用了除AND以外的东西\nDialogue: 0,0:41:04.12,0:41:08.19,Default,,0,0,0,,很难再说清楚这些东西是否会起效了\nDialogue: 0,0:41:08.20,0:41:10.36,Default,,0,0,0,,它们并不是在任何情况下都有效\nDialogue: 0,0:41:10.36,0:41:13.39,Default,,0,0,0,,我会在下一堂课的最后讨论这个问题\nDialogue: 0,0:41:14.30,0:41:15.84,Default,,0,0,0,,但对于你的问题来说：答案是“会影响”\nDialogue: 0,0:41:16.19,0:41:19.21,Default,,0,0,0,,用LISP-VALUE一方面从Lisp中获得了巨大威力\nDialogue: 0,0:41:19.40,0:41:23.77,Default,,0,0,0,,另一方面你失去了逻辑式程序设计的重要威力\nDialogue: 0,0:41:24.17,0:41:25.56,Default,,0,0,0,,这是你需要做出的取舍\nDialogue: 0,0:41:28.48,0:41:29.39,Default,,0,0,0,,好吧 先休息一会儿\nDialogue: 0,0:41:30.17,0:41:44.30,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,0:41:30.17,0:41:44.30,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec8a.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: None\n\n[Aegisub Project Garbage]\nScroll Position: 654\nActive Line: 681\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:18.27,0:00:19.68,EN,,0,0,0,,PROFESSOR: The last time we began having a look\nDialogue: 0,0:00:19.72,0:00:21.26,EN,,0,0,0,,at how languages are constructed.\nDialogue: 0,0:00:22.41,0:00:25.88,EN,,0,0,0,,Remember the main point that an evaluator for, LISP, say,\nDialogue: 0,0:00:26.08,0:00:27.58,EN,,0,0,0,,has two main elements.\nDialogue: 0,0:00:27.58,0:00:28.40,EN,,0,0,0,,There is EVAL,\nDialogue: 0,0:00:31.04,0:00:37.42,EN,,0,0,0,,and EVAL's job is to take in an expression and an environment\nDialogue: 0,0:00:38.91,0:00:44.44,EN,,0,0,0,,and turn that into a procedure and some arguments\nDialogue: 0,0:00:45.42,0:00:47.05,EN,,0,0,0,,and pass that off to APPLY.\nDialogue: 0,0:00:49.41,0:00:51.29,EN,,0,0,0,,And APPLY takes the procedure in the arguments,\nDialogue: 0,0:00:51.69,0:00:55.12,EN,,0,0,0,,turns that back into, in a general case, another expression\nDialogue: 0,0:00:55.39,0:00:57.71,EN,,0,0,0,,to be evaluated in another environment\nDialogue: 0,0:00:57.74,0:01:00.00,EN,,0,0,0,,and passes that off to EVAL, which passes it to APPLY,\nDialogue: 0,0:01:00.27,0:01:01.44,EN,,0,0,0,,and there's this whole big circle\nDialogue: 0,0:01:01.47,0:01:02.94,EN,,0,0,0,,where things go around and around and around\nDialogue: 0,0:01:03.02,0:01:06.56,EN,,0,0,0,,until you get either to some very primitive data or to a primitive procedure.\nDialogue: 0,0:01:07.74,0:01:09.24,EN,,0,0,0,,See, what this cycle has to do with\nDialogue: 0,0:01:09.44,0:01:12.57,EN,,0,0,0,,is unwinding the means of combination\nDialogue: 0,0:01:12.59,0:01:14.36,EN,,0,0,0,,and the means of abstraction in the language.\nDialogue: 0,0:01:15.02,0:01:17.72,EN,,0,0,0,,So for instance, you have a procedure in LISP--\nDialogue: 0,0:01:17.74,0:01:20.52,EN,,0,0,0,,a procedure is a general way of saying,\nDialogue: 0,0:01:20.54,0:01:22.57,EN,,0,0,0,,I want to be able to evaluate this expression\nDialogue: 0,0:01:22.67,0:01:24.41,EN,,0,0,0,,for any value of the arguments,\nDialogue: 0,0:01:25.76,0:01:27.18,EN,,0,0,0,,and that's sort of what's going on here.\nDialogue: 0,0:01:27.67,0:01:28.51,EN,,0,0,0,,That's what APPLY does.\nDialogue: 0,0:01:28.51,0:01:30.68,EN,,0,0,0,,It says the general thing coming in with the arguments\nDialogue: 0,0:01:30.72,0:01:32.70,EN,,0,0,0,,reduces to the expression that's the body,\nDialogue: 0,0:01:33.05,0:01:34.72,EN,,0,0,0,,and then if that's a compound expression\nDialogue: 0,0:01:34.83,0:01:36.46,EN,,0,0,0,,or another procedure application,\nDialogue: 0,0:01:36.78,0:01:38.44,EN,,0,0,0,,the thing will go around and around the circle.\nDialogue: 0,0:01:40.33,0:01:44.08,EN,,0,0,0,,Anyway, that's sort of the basic structure of gee, pretty much any interpreter.\nDialogue: 0,0:01:45.20,0:01:46.25,EN,,0,0,0,,The other thing that you saw\nDialogue: 0,0:01:46.28,0:01:47.66,EN,,0,0,0,,once you have the interpreter in your hands,\nDialogue: 0,0:01:47.69,0:01:49.87,EN,,0,0,0,,you have all this power to start playing with the language.\nDialogue: 0,0:01:49.87,0:01:51.52,EN,,0,0,0,,So you can make it dynamically scoped,\nDialogue: 0,0:01:51.84,0:01:54.56,EN,,0,0,0,,or you can put in normal order evaluation,\nDialogue: 0,0:01:54.59,0:01:56.48,EN,,0,0,0,,or you can add new forms to the language,\nDialogue: 0,0:01:56.86,0:01:57.50,EN,,0,0,0,,whatever you like.\nDialogue: 0,0:01:57.58,0:01:58.62,EN,,0,0,0,,Or more generally,\nDialogue: 0,0:01:58.76,0:02:01.32,EN,,0,0,0,,there's this notion of metalinguistic abstraction,\nDialogue: 0,0:02:02.64,0:02:06.01,EN,,0,0,0,,which says that part of your perspective\nDialogue: 0,0:02:07.61,0:02:10.52,EN,,0,0,0,,as an engineer, as a software engineer, but as an engineer in general\nDialogue: 0,0:02:11.39,0:02:13.88,EN,,0,0,0,,is that you can gain control of complexity\nDialogue: 0,0:02:14.96,0:02:17.16,EN,,0,0,0,,by inventing new languages sometimes.\nDialogue: 0,0:02:18.01,0:02:20.81,EN,,0,0,0,,See, one way to think about computer programming\nDialogue: 0,0:02:21.55,0:02:26.27,EN,,0,0,0,,is that it only incidentally has to do with getting a computer to do something.\nDialogue: 0,0:02:26.44,0:02:28.97,EN,,0,0,0,,Primarily what a computer program has to do with,\nDialogue: 0,0:02:29.00,0:02:32.52,EN,,0,0,0,,it's a way of expressing ideas with communicating ideas.\nDialogue: 0,0:02:33.16,0:02:34.04,EN,,0,0,0,,And sometimes\nDialogue: 0,0:02:34.89,0:02:36.62,EN,,0,0,0,,when you want to communicate new kinds of ideas,\nDialogue: 0,0:02:36.65,0:02:38.73,EN,,0,0,0,,you'd like to invent new modes of expressing that.\nDialogue: 0,0:02:39.82,0:02:44.99,EN,,0,0,0,,Well, today we're going to apply this framework to build a new language.\nDialogue: 0,0:02:45.73,0:02:48.00,EN,,0,0,0,,See, once we have the basic idea of the interpreter,\nDialogue: 0,0:02:48.03,0:02:50.27,EN,,0,0,0,,you can pretty much go build any language that you like.\nDialogue: 0,0:02:50.83,0:02:53.21,EN,,0,0,0,,So for example, we can go off and build Pascal.\nDialogue: 0,0:02:54.37,0:02:55.15,EN,,0,0,0,,And...\nDialogue: 0,0:02:56.17,0:02:58.19,EN,,0,0,0,,gee, we would worry about syntax and parsing\nDialogue: 0,0:02:58.19,0:03:00.51,EN,,0,0,0,,and various kinds of compiler optimizations,\nDialogue: 0,0:03:01.12,0:03:03.29,EN,,0,0,0,,and there are people who make honest livings doing that,\nDialogue: 0,0:03:03.85,0:03:07.60,EN,,0,0,0,,but at the level of abstraction that we're talking,\nDialogue: 0,0:03:08.04,0:03:10.99,EN,,0,0,0,,a Pascal interpreter would not look very different at all\nDialogue: 0,0:03:12.03,0:03:13.76,EN,,0,0,0,,from what you saw Gerry do last time.\nDialogue: 0,0:03:15.02,0:03:18.96,EN,,0,0,0,,Instead of that, we'll spend today building a really different language,\nDialogue: 0,0:03:20.51,0:03:22.81,EN,,0,0,0,,a language that encourages you\nDialogue: 0,0:03:23.05,0:03:26.04,EN,,0,0,0,,to think about programming not in terms of procedures,\nDialogue: 0,0:03:26.24,0:03:27.64,EN,,0,0,0,,but in a really different way.\nDialogue: 0,0:03:29.09,0:03:31.02,EN,,0,0,0,,And the lecture today is\nDialogue: 0,0:03:31.74,0:03:34.64,EN,,0,0,0,,going to be at two levels simultaneously.\nDialogue: 0,0:03:34.81,0:03:35.52,EN,,0,0,0,,On the one hand,\nDialogue: 0,0:03:35.90,0:03:37.71,EN,,0,0,0,,I'm going to show you what this language looks like,\nDialogue: 0,0:03:38.96,0:03:41.08,EN,,0,0,0,,and on the other hand, I'll show you how it's implemented.\nDialogue: 0,0:03:41.32,0:03:42.96,EN,,0,0,0,,And we'll build an implementation in LISP\nDialogue: 0,0:03:42.99,0:03:43.90,EN,,0,0,0,,and see how that works.\nDialogue: 0,0:03:44.04,0:03:48.25,EN,,0,0,0,,And you should be drawing lessons on two levels.\nDialogue: 0,0:03:48.68,0:03:53.00,EN,,0,0,0,,The first is to realize just how different a language can be.\nDialogue: 0,0:03:53.79,0:03:58.14,EN,,0,0,0,,So if you think that the jump from Fortran to LISP is a big deal,\nDialogue: 0,0:03:58.24,0:03:59.36,EN,,0,0,0,,you haven't seen anything yet.\nDialogue: 0,0:04:01.56,0:04:03.68,EN,,0,0,0,,And secondly,\nDialogue: 0,0:04:03.77,0:04:06.54,EN,,0,0,0,,you'll see that even with such a very different language,\nDialogue: 0,0:04:07.36,0:04:09.52,EN,,0,0,0,,which will turn out to not have procedures at all\nDialogue: 0,0:04:09.92,0:04:11.64,EN,,0,0,0,,and not talk about functions at all,\nDialogue: 0,0:04:12.20,0:04:15.72,EN,,0,0,0,,there will still be this basic cycle of eval and apply\nDialogue: 0,0:04:16.19,0:04:19.98,EN,,0,0,0,,that's unwinds the means of combination and the means an abstraction.\nDialogue: 0,0:04:20.95,0:04:24.68,EN,,0,0,0,,And then thirdly, as kind of a minor but elegant technical point,\nDialogue: 0,0:04:24.89,0:04:28.52,EN,,0,0,0,,you'll see a nice use of streams to avoid backtracking.\nDialogue: 0,0:04:32.33,0:04:34.40,EN,,0,0,0,,OK, well, I said that this language is very different.\nDialogue: 0,0:04:35.86,0:04:36.64,EN,,0,0,0,,To explain that,\nDialogue: 0,0:04:37.05,0:04:42.81,EN,,0,0,0,,let's go back to the very first idea that we talked about in this course,\nDialogue: 0,0:04:43.26,0:04:46.54,EN,,0,0,0,,and that was the idea of the distinction between\nDialogue: 0,0:04:46.72,0:04:49.52,EN,,0,0,0,,the declarative knowledge of mathematics--\nDialogue: 0,0:04:50.19,0:04:54.14,EN,,0,0,0,,the definition of a square root as a mathematical truth--\nDialogue: 0,0:04:55.48,0:04:59.56,EN,,0,0,0,,and the idea that computer science talks about the how to knowledge--\nDialogue: 0,0:04:59.76,0:05:04.59,EN,,0,0,0,,contrast that definition of square root with a program to compute a square root.\nDialogue: 0,0:05:05.97,0:05:07.07,EN,,0,0,0,,That's where we started off.\nDialogue: 0,0:05:08.51,0:05:09.52,EN,,0,0,0,,Well, wouldn't it be great\nDialogue: 0,0:05:09.88,0:05:12.16,EN,,0,0,0,,if you could somehow bridge this gap\nDialogue: 0,0:05:12.81,0:05:16.43,EN,,0,0,0,,and make a programming language which sort of did things,\nDialogue: 0,0:05:16.67,0:05:21.61,EN,,0,0,0,,but you talked about it in terms of truth, in declarative terms?\nDialogue: 0,0:05:22.38,0:05:25.50,EN,,0,0,0,,So that would be a programming language in which you specify facts.\nDialogue: 0,0:05:27.69,0:05:28.88,EN,,0,0,0,,You tell it what is.\nDialogue: 0,0:05:28.88,0:05:29.96,EN,,0,0,0,,You say what is true.\nDialogue: 0,0:05:30.95,0:05:33.07,EN,,0,0,0,,And then when you want an answer,\nDialogue: 0,0:05:33.21,0:05:36.38,EN,,0,0,0,,somehow the language has built into it automatically\nDialogue: 0,0:05:37.60,0:05:39.45,EN,,0,0,0,,general kinds of how to knowledge\nDialogue: 0,0:05:39.47,0:05:40.64,EN,,0,0,0,,so it can just take your facts\nDialogue: 0,0:05:40.89,0:05:42.83,EN,,0,0,0,,and it can evolve these methods on its own\nDialogue: 0,0:05:43.31,0:05:46.12,EN,,0,0,0,,using the facts you gave it and maybe some general rules of logic.\nDialogue: 0,0:05:49.33,0:05:50.54,EN,,0,0,0,,So for instance,\nDialogue: 0,0:05:52.06,0:05:55.12,EN,,0,0,0,,I might go up to this program and start telling it some things.\nDialogue: 0,0:05:56.00,0:06:07.08,EN,,0,0,0,,So I might tell it that the son of Adam is Abel.\nDialogue: 0,0:06:08.92,0:06:16.51,EN,,0,0,0,,And I might tell it that the son of Adam is Cain.\nDialogue: 0,0:06:17.66,0:06:25.08,EN,,0,0,0,,And I might tell it that the son of Cain is Enoch.\nDialogue: 0,0:06:27.79,0:06:34.89,EN,,0,0,0,,And I might tell it that the son of Enoch is Irad,\nDialogue: 0,0:06:37.02,0:06:40.72,EN,,0,0,0,,and all through the rest of our chapter whatever of Genesis,\nDialogue: 0,0:06:41.15,0:06:43.18,EN,,0,0,0,,which ends up ending in Adah, by the way,\nDialogue: 0,0:06:43.32,0:06:46.78,EN,,0,0,0,,and this shows the genealogy of Adah from Cain.\nDialogue: 0,0:06:48.44,0:06:50.67,EN,,0,0,0,,Anyway, once you tell it these facts,\nDialogue: 0,0:06:52.35,0:06:53.40,EN,,0,0,0,,you might ask it things.\nDialogue: 0,0:06:53.51,0:06:55.05,EN,,0,0,0,,You might go up to your language and say,\nDialogue: 0,0:06:56.06,0:06:59.29,EN,,0,0,0,,who's the son of Adam?\nDialogue: 0,0:07:00.42,0:07:04.91,EN,,0,0,0,,And you can very easily imagine having a little general purpose search program\nDialogue: 0,0:07:05.52,0:07:06.96,EN,,0,0,0,,which would be able to go through\nDialogue: 0,0:07:07.00,0:07:09.26,EN,,0,0,0,,and in response to that say, oh yeah, there are two answers:\nDialogue: 0,0:07:09.29,0:07:10.44,EN,,0,0,0,,the son of Adam is Abel\nDialogue: 0,0:07:10.68,0:07:12.17,EN,,0,0,0,,and the son of Adam is Cain.\nDialogue: 0,0:07:14.14,0:07:14.97,EN,,0,0,0,,Or you might say,\nDialogue: 0,0:07:15.07,0:07:16.89,EN,,0,0,0,,based on the very same facts,\nDialogue: 0,0:07:18.04,0:07:19.95,EN,,0,0,0,,who is Cain the son of?\nDialogue: 0,0:07:21.95,0:07:27.02,EN,,0,0,0,,And then you can imagine generating another slightly different search program\nDialogue: 0,0:07:27.92,0:07:29.21,EN,,0,0,0,,which would be able to go through\nDialogue: 0,0:07:29.45,0:07:33.05,EN,,0,0,0,,and checked for who is Cain, and son of,\nDialogue: 0,0:07:33.52,0:07:34.44,EN,,0,0,0,,and come up with Adam.\nDialogue: 0,0:07:35.89,0:07:36.99,EN,,0,0,0,,Or you might say,\nDialogue: 0,0:07:38.01,0:07:41.40,EN,,0,0,0,,what's the relationship between Cain and Enoch?\nDialogue: 0,0:07:42.07,0:07:45.08,EN,,0,0,0,,And again, a minor variant on that search program.\nDialogue: 0,0:07:46.34,0:07:48.16,EN,,0,0,0,,You could figure out that it said son of.\nDialogue: 0,0:07:52.88,0:07:54.92,EN,,0,0,0,,But even here in this very simple example,\nDialogue: 0,0:07:56.14,0:07:58.44,EN,,0,0,0,,what you see is that a single fact,\nDialogue: 0,0:07:58.81,0:08:01.52,EN,,0,0,0,,see, a single fact like the son of Adam is Cain\nDialogue: 0,0:08:02.84,0:08:05.52,EN,,0,0,0,,can be used to answer different kinds of questions.\nDialogue: 0,0:08:06.52,0:08:08.12,EN,,0,0,0,,You can say, who's Cain the son of,\nDialogue: 0,0:08:08.14,0:08:10.92,EN,,0,0,0,,or you can say who's the son of Adam,\nDialogue: 0,0:08:10.94,0:08:12.86,EN,,0,0,0,,or you can say what's the relation between Adam and Cain?\nDialogue: 0,0:08:12.88,0:08:14.48,EN,,0,0,0,,Those are different questions\nDialogue: 0,0:08:15.53,0:08:18.54,EN,,0,0,0,,being run by different traditional procedures\nDialogue: 0,0:08:18.68,0:08:20.72,EN,,0,0,0,,all based on the same fact.\nDialogue: 0,0:08:22.75,0:08:25.92,EN,,0,0,0,,And that's going to be the essence of the power of this programming style,\nDialogue: 0,0:08:26.91,0:08:29.50,EN,,0,0,0,,that one piece of declarative knowledge\nDialogue: 0,0:08:30.04,0:08:34.01,EN,,0,0,0,,can be used as the basis for a lot of different kinds of how-to knowledge,\nDialogue: 0,0:08:34.81,0:08:37.08,EN,,0,0,0,,as opposed to the kinds of procedures we're writing\nDialogue: 0,0:08:37.15,0:08:39.55,EN,,0,0,0,,where you sort of tell it what input you're giving in\nDialogue: 0,0:08:39.61,0:08:40.65,EN,,0,0,0,,and what answer you want.\nDialogue: 0,0:08:41.49,0:08:44.70,EN,,0,0,0,,So for instance, our square root program can perfectly well answer the question,\nDialogue: 0,0:08:44.76,0:08:47.16,EN,,0,0,0,,what's the square root of 144?\nDialogue: 0,0:08:48.90,0:08:49.77,EN,,0,0,0,,But in principle,\nDialogue: 0,0:08:49.82,0:08:52.83,EN,,0,0,0,,the mathematical definition of square root tells you other things.\nDialogue: 0,0:08:52.84,0:08:56.43,EN,,0,0,0,,Like it could say, what is 17 the square root of?\nDialogue: 0,0:08:57.59,0:08:59.71,EN,,0,0,0,,And that would be have to be answered by a different program.\nDialogue: 0,0:09:01.92,0:09:03.50,EN,,0,0,0,,So the mathematical definition,\nDialogue: 0,0:09:03.98,0:09:05.12,EN,,0,0,0,,or in general, the\nDialogue: 0,0:09:05.53,0:09:10.30,EN,,0,0,0,,the facts that you give it are somehow unbiased as to what the question is.\nDialogue: 0,0:09:10.90,0:09:12.81,EN,,0,0,0,,Whereas the programs we tend to write specifically\nDialogue: 0,0:09:12.83,0:09:14.20,EN,,0,0,0,,because they are how-to knowledge\nDialogue: 0,0:09:14.24,0:09:16.36,EN,,0,0,0,,tend to be looking for a specific answer.\nDialogue: 0,0:09:17.56,0:09:20.12,EN,,0,0,0,,So that's going to be one characteristic of what we're talking about.\nDialogue: 0,0:09:21.81,0:09:22.60,EN,,0,0,0,,We can go on.\nDialogue: 0,0:09:23.48,0:09:27.52,EN,,0,0,0,,We can imagine that we've given our language some sort of facts.\nDialogue: 0,0:09:27.71,0:09:29.61,EN,,0,0,0,,Now let's give it some rules of inference.\nDialogue: 0,0:09:30.02,0:09:31.36,EN,,0,0,0,,We can say, for instance,\nDialogue: 0,0:09:31.95,0:09:36.19,EN,,0,0,0,,if the-- make up some syntax here--\nDialogue: 0,0:09:36.44,0:09:41.53,EN,,0,0,0,,if the son of x is y--\nDialogue: 0,0:09:41.68,0:09:45.21,EN,,0,0,0,,I'll put question marks to indicate variables here--\nDialogue: 0,0:09:45.61,0:09:56.06,EN,,0,0,0,,if the son of x is y and the son of y is z,\nDialogue: 0,0:09:58.96,0:10:08.46,EN,,0,0,0,,then the grandson of x is z.\nDialogue: 0,0:10:09.32,0:10:13.40,EN,,0,0,0,,So I can imagine telling my machine that rule\nDialogue: 0,0:10:15.00,0:10:17.28,EN,,0,0,0,,and then being able to say, for instance,\nDialogue: 0,0:10:17.44,0:10:18.68,EN,,0,0,0,,who's the grandson of Adam?\nDialogue: 0,0:10:20.61,0:10:23.64,EN,,0,0,0,,Or who is Irad the grandson of?\nDialogue: 0,0:10:24.79,0:10:29.08,EN,,0,0,0,,Or deduce all grandson relationships you possibly can from this information.\nDialogue: 0,0:10:31.13,0:10:35.60,EN,,0,0,0,,We can imagine somehow the language knowing how to do that automatically.\nDialogue: 0,0:10:40.22,0:10:45.20,EN,,0,0,0,,Ok, Let me give you maybe a little bit more concrete example.\nDialogue: 0,0:10:45.77,0:10:51.95,EN,,0,0,0,,Here's a procedure that merges two sorted lists.\nDialogue: 0,0:10:53.92,0:11:00.27,EN,,0,0,0,,So x and y are two, say, lists of numbers,\nDialogue: 0,0:11:00.30,0:11:04.20,EN,,0,0,0,,lists of distinct numbers, if you like, that are in increasing order.\nDialogue: 0,0:11:04.76,0:11:07.53,EN,,0,0,0,,And what merge does is take two such lists\nDialogue: 0,0:11:07.71,0:11:10.38,EN,,0,0,0,,and combine them into a list where everything's in increasing order,\nDialogue: 0,0:11:11.21,0:11:15.00,EN,,0,0,0,,and this is a pretty easy programs\nDialogue: 0,0:11:15.02,0:11:16.14,EN,,0,0,0,,that you ought to be able to write.\nDialogue: 0,0:11:16.39,0:11:18.64,EN,,0,0,0,,It says, if x is empty, the answer is y.\nDialogue: 0,0:11:18.86,0:11:20.46,EN,,0,0,0,,If y is empty, the answer is x.\nDialogue: 0,0:11:21.18,0:11:22.99,EN,,0,0,0,,Otherwise, you compare the first two elements.\nDialogue: 0,0:11:22.99,0:11:24.46,EN,,0,0,0,,So you pick out the first thing in x\nDialogue: 0,0:11:24.84,0:11:26.01,EN,,0,0,0,,and the first thing in y,\nDialogue: 0,0:11:26.81,0:11:31.68,EN,,0,0,0,,and then depending on which of those first elements is less,\nDialogue: 0,0:11:32.83,0:11:36.60,EN,,0,0,0,,you stick the lower one on to the result a recursively merging,\nDialogue: 0,0:11:37.87,0:11:39.92,EN,,0,0,0,,either chopping the first one off x\nDialogue: 0,0:11:40.11,0:11:41.61,EN,,0,0,0,,or chopping the first one off y.\nDialogue: 0,0:11:42.40,0:11:43.96,EN,,0,0,0,,That's a standard kind of program.\nDialogue: 0,0:11:46.47,0:11:48.41,EN,,0,0,0,,Let's look at the logic.\nDialogue: 0,0:11:48.62,0:11:49.79,EN,,0,0,0,,Let's forget about the program\nDialogue: 0,0:11:50.28,0:11:52.76,EN,,0,0,0,,and look at the logic on which that procedure is based.\nDialogue: 0,0:11:53.82,0:11:55.00,EN,,0,0,0,,See, there's some logic which says,\nDialogue: 0,0:11:55.02,0:11:57.21,EN,,0,0,0,,gee, if the first one is less,\nDialogue: 0,0:11:57.53,0:12:00.00,EN,,0,0,0,,then we get the answer by sticking something onto the\nDialogue: 0,0:12:00.16,0:12:02.12,EN,,0,0,0,,the result of recursively merging the rest.\nDialogue: 0,0:12:02.84,0:12:04.09,EN,,0,0,0,,So let's try and be explicit about\nDialogue: 0,0:12:04.24,0:12:06.41,EN,,0,0,0,,what that logic is that's making the program work.\nDialogue: 0,0:12:08.30,0:12:09.44,EN,,0,0,0,,So here's one piece.\nDialogue: 0,0:12:10.13,0:12:11.53,EN,,0,0,0,,Here's the piece of the program which\nDialogue: 0,0:12:12.64,0:12:15.26,EN,,0,0,0,,recursively chops down x\nDialogue: 0,0:12:15.66,0:12:17.82,EN,,0,0,0,,if the first thing in x is smaller.\nDialogue: 0,0:12:19.98,0:12:22.54,EN,,0,0,0,,And if you want to be very explicit about what the logic is there,\nDialogue: 0,0:12:23.45,0:12:26.49,EN,,0,0,0,,what's really going on is a deduction,\nDialogue: 0,0:12:26.72,0:12:32.38,EN,,0,0,0,,which says, if you know that some list, that we'll call cdr of x, and y\nDialogue: 0,0:12:33.29,0:12:35.44,EN,,0,0,0,,merged to form z,\nDialogue: 0,0:12:37.84,0:12:41.52,EN,,0,0,0,,And you know that a is less than the first thing in y.\nDialogue: 0,0:12:43.60,0:12:48.52,EN,,0,0,0,,then you know that if you put a onto the cdr of x.\nDialogue: 0,0:12:49.74,0:12:51.85,EN,,0,0,0,,and that result and y\nDialogue: 0,0:12:52.60,0:12:54.99,EN,,0,0,0,,merge-to-form a onto z.\nDialogue: 0,0:12:55.82,0:12:58.09,EN,,0,0,0,,And what that is, that's the underlying piece of logic--\nDialogue: 0,0:12:58.72,0:12:59.95,EN,,0,0,0,,I haven't written it as a program,\nDialogue: 0,0:12:59.96,0:13:02.00,EN,,0,0,0,,I wrote it a sort of deduction\nDialogue: 0,0:13:02.03,0:13:04.89,EN,,0,0,0,,that sits underneath this particular clause\nDialogue: 0,0:13:05.21,0:13:07.26,EN,,0,0,0,,that says we can use the recursion there.\nDialogue: 0,0:13:09.41,0:13:12.78,EN,,0,0,0,,And then similar, here's the other clause just to complete it.\nDialogue: 0,0:13:14.00,0:13:15.87,EN,,0,0,0,,The other clause is based on this piece of logic,\nDialogue: 0,0:13:15.92,0:13:18.35,EN,,0,0,0,,which is almost the same and I won't go through it,\nDialogue: 0,0:13:19.00,0:13:20.35,EN,,0,0,0,,and then there's the end cases\nDialogue: 0,0:13:20.41,0:13:22.01,EN,,0,0,0,,where we tested for null,\nDialogue: 0,0:13:22.03,0:13:24.04,EN,,0,0,0,,and that's based on the idea that for any x,\nDialogue: 0,0:13:24.51,0:13:27.20,EN,,0,0,0,,x and the empty list merge to form an x,\nDialogue: 0,0:13:28.04,0:13:30.86,EN,,0,0,0,,or for any y, the empty list and y merge to form y.\nDialogue: 0,0:13:33.36,0:13:38.12,EN,,0,0,0,,OK, so there's a piece of procedure\nDialogue: 0,0:13:38.43,0:13:40.11,EN,,0,0,0,,and the logic on which it's based.\nDialogue: 0,0:13:41.74,0:13:42.97,EN,,0,0,0,,And notice a big difference.\nDialogue: 0,0:13:45.10,0:13:50.52,EN,,0,0,0,,The procedure looked like this:\nDialogue: 0,0:13:50.65,0:13:52.28,EN,,0,0,0,,it said there was a box--\nDialogue: 0,0:13:52.86,0:13:55.39,EN,,0,0,0,,and all the things we've been doing have the characteristic\nDialogue: 0,0:13:55.40,0:13:57.69,EN,,0,0,0,,we have boxes and things going in and things going out--\nDialogue: 0,0:13:58.08,0:13:59.61,EN,,0,0,0,,there was this box called merge,\nDialogue: 0,0:14:01.29,0:14:03.85,EN,,0,0,0,,and in came an x and y,\nDialogue: 0,0:14:04.44,0:14:05.37,EN,,0,0,0,,and out came an answer.\nDialogue: 0,0:14:07.63,0:14:09.48,EN,,0,0,0,,That's the character of the procedure that we wrote.\nDialogue: 0,0:14:13.02,0:14:14.66,EN,,0,0,0,,These rules don't look like that.\nDialogue: 0,0:14:14.66,0:14:16.76,EN,,0,0,0,,These rules talk about a relation.\nDialogue: 0,0:14:17.92,0:14:24.16,EN,,0,0,0,,There's some sort of relation that in those slides I called mrege-to-form.\nDialogue: 0,0:14:25.37,0:14:28.76,EN,,0,0,0,,So I said x and y merge to form z,\nDialogue: 0,0:14:29.00,0:14:32.33,EN,,0,0,0,,and somehow this is not -- this is a function.\nDialogue: 0,0:14:32.61,0:14:32.85,EN,,0,0,0,,Right?\nDialogue: 0,0:14:32.85,0:14:34.41,EN,,0,0,0,,The answer is a function of x and y,\nDialogue: 0,0:14:34.59,0:14:38.19,EN,,0,0,0,,and here what I have is a relation between three things.\nDialogue: 0,0:14:39.72,0:14:41.32,EN,,0,0,0,,And I'm not going to specify\nDialogue: 0,0:14:42.09,0:14:43.77,EN,,0,0,0,,which is the input and which is the output.\nDialogue: 0,0:14:44.20,0:14:47.40,EN,,0,0,0,,And the reason I want to say that is because in principle,\nDialogue: 0,0:14:48.64,0:14:50.83,EN,,0,0,0,,we could use exactly those same logic rules\nDialogue: 0,0:14:50.84,0:14:52.44,EN,,0,0,0,,answer a lot of different questions.\nDialogue: 0,0:14:54.57,0:14:56.30,EN,,0,0,0,,So we can say, for instance-- giving\nDialogue: 0,0:14:56.72,0:14:59.05,EN,,0,0,0,,imagine giving our machine those rules of logic.\nDialogue: 0,0:14:59.05,0:15:01.20,EN,,0,0,0,,Not the program, the underlying rules of logic.\nDialogue: 0,0:15:01.40,0:15:03.12,EN,,0,0,0,,Then it ought to be able to say--\nDialogue: 0,0:15:04.75,0:15:05.52,EN,,0,0,0,,we could ask it--\nDialogue: 0,0:15:06.73,0:15:19.18,EN,,0,0,0,,1, 3, 7 and 2, 4, 8 merge to form what?\nDialogue: 0,0:15:20.91,0:15:23.42,EN,,0,0,0,,And that's a question it ought to be able to answer.\nDialogue: 0,0:15:23.88,0:15:27.36,EN,,0,0,0,,That's exactly the same question that our Lisp procedure answered.\nDialogue: 0,0:15:28.18,0:15:30.14,EN,,0,0,0,,But the exact same rules\nDialogue: 0,0:15:30.89,0:15:34.80,EN,,0,0,0,,should also be able to answer a question like this:\nDialogue: 0,0:15:36.19,0:15:43.24,EN,,0,0,0,,1, 3, 7 and what merged to form 1, 2, 3, 4, 7, 8?\nDialogue: 0,0:15:45.56,0:15:47.80,EN,,0,0,0,,The same rules of logic can answer this,\nDialogue: 0,0:15:47.84,0:15:49.90,EN,,0,0,0,,although the procedure we wrote can't answer that question.\nDialogue: 0,0:15:50.80,0:15:52.33,EN,,0,0,0,,Or we might be able to say what\nDialogue: 0,0:15:53.71,0:16:01.12,EN,,0,0,0,,what and what else merge to form--\nDialogue: 0,0:16:04.28,0:16:12.68,EN,,0,0,0,,what and what else merge to form 1, 2, 3, 4, 7, 8?\nDialogue: 0,0:16:13.78,0:16:15.34,EN,,0,0,0,,And the thing should be able to go through,\nDialogue: 0,0:16:15.84,0:16:17.31,EN,,0,0,0,,if it really can apply that logic,\nDialogue: 0,0:16:17.79,0:16:22.54,EN,,0,0,0,,and deduce all, whatever is, 2 to the sixth answers to that question.\nDialogue: 0,0:16:25.60,0:16:27.69,EN,,0,0,0,,Cause it could be 1 and the rester, or it could be 1, 2 and the rest.\nDialogue: 0,0:16:27.69,0:16:28.75,EN,,0,0,0,,or it could be 1, 2 and the rester.\nDialogue: 0,0:16:28.79,0:16:31.53,EN,,0,0,0,,Or it could be 1 and 3 and 7 and the rest.\nDialogue: 0,0:16:32.01,0:16:33.26,EN,,0,0,0,,There's a whole bunch of answers.\nDialogue: 0,0:16:33.41,0:16:37.76,EN,,0,0,0,,And in principle, the logic should be enough to deduce that.\nDialogue: 0,0:16:38.55,0:16:42.03,EN,,0,0,0,,So there are going to be two big differences\nDialogue: 0,0:16:44.04,0:16:46.00,EN,,0,0,0,,in the kind of program we're going to look at\nDialogue: 0,0:16:46.54,0:16:48.19,EN,,0,0,0,,and not only Lisp,\nDialogue: 0,0:16:48.20,0:16:50.56,EN,,0,0,0,,but essentially all the programming you've probably done so far\nDialogue: 0,0:16:52.03,0:16:53.60,EN,,0,0,0,,in pretty much any language you can think of.\nDialogue: 0,0:16:54.15,0:16:57.79,EN,,0,0,0,,The first is, we're not going to be computing functions.\nDialogue: 0,0:17:00.62,0:17:02.01,EN,,0,0,0,,We're not going to be talking about\nDialogue: 0,0:17:02.62,0:17:04.41,EN,,0,0,0,,about things that take input and output.\nDialogue: 0,0:17:04.41,0:17:05.82,EN,,0,0,0,,We're going to be talking about relations.\nDialogue: 0,0:17:06.89,0:17:10.00,EN,,0,0,0,,And that means in principle, these relations don't have directionality.\nDialogue: 0,0:17:11.08,0:17:15.05,EN,,0,0,0,,So the knowledge that you specify to answer this question,\nDialogue: 0,0:17:16.46,0:17:18.41,EN,,0,0,0,,should be same, that same knowledge\nDialogue: 0,0:17:18.43,0:17:21.80,EN,,0,0,0,,also allow you to answer these other questions and conversely.\nDialogue: 0,0:17:26.60,0:17:29.40,EN,,0,0,0,,And the second issue is that\nDialogue: 0,0:17:29.61,0:17:31.23,EN,,0,0,0,,since we're talking about relations,\nDialogue: 0,0:17:32.32,0:17:34.44,EN,,0,0,0,,these relations don't necessarily have one answer.\nDialogue: 0,0:17:35.61,0:17:37.00,EN,,0,0,0,,So that third question down there\nDialogue: 0,0:17:37.02,0:17:38.36,EN,,0,0,0,,doesn't have a particular answer,\nDialogue: 0,0:17:38.40,0:17:39.58,EN,,0,0,0,,it has a whole bunch of answers.\nDialogue: 0,0:17:42.27,0:17:44.64,EN,,0,0,0,,Well, that's where we're going.\nDialogue: 0,0:17:44.64,0:17:45.90,EN,,0,0,0,,This style of programming,\nDialogue: 0,0:17:46.72,0:17:49.21,EN,,0,0,0,,by the way, is called logic programming,\nDialogue: 0,0:17:50.22,0:17:51.58,EN,,0,0,0,,for kind of obvious reasons.\nDialogue: 0,0:17:56.16,0:18:00.38,EN,,0,0,0,,And people who do logic programming say that --\nDialogue: 0,0:18:00.40,0:18:03.15,EN,,0,0,0,,they have this little phrase--\nDialogue: 0,0:18:03.16,0:18:04.67,EN,,0,0,0,,they say the point of logic programming\nDialogue: 0,0:18:04.76,0:18:09.00,EN,,0,0,0,,is that you use logic to express what is true,\nDialogue: 0,0:18:10.09,0:18:13.88,EN,,0,0,0,,you use logic to check whether something is true,\nDialogue: 0,0:18:14.67,0:18:17.24,EN,,0,0,0,,and you use logic to find out what is true.\nDialogue: 0,0:18:19.20,0:18:22.09,EN,,0,0,0,,The best known logic programming language,\nDialogue: 0,0:18:22.97,0:18:24.78,EN,,0,0,0,,as you probably know, is called Prolog.\nDialogue: 0,0:18:25.78,0:18:28.88,EN,,0,0,0,,The language that we're going to implement this morning\nDialogue: 0,0:18:29.82,0:18:32.32,EN,,0,0,0,,is something we call the query language,\nDialogue: 0,0:18:32.48,0:18:34.41,EN,,0,0,0,,and it essentially has the essence of prolog.\nDialogue: 0,0:18:35.32,0:18:36.73,EN,,0,0,0,,It can do about the same stuff,\nDialogue: 0,0:18:37.29,0:18:38.73,EN,,0,0,0,,although it's a lot slower\nDialogue: 0,0:18:38.73,0:18:40.01,EN,,0,0,0,,because we're going to implement it in LISP\nDialogue: 0,0:18:41.90,0:18:44.36,EN,,0,0,0,,rather than building a particular compiler.\nDialogue: 0,0:18:44.46,0:18:46.62,EN,,0,0,0,,We're going to interpret it on top of the LISP interpreter.\nDialogue: 0,0:18:47.51,0:18:49.84,EN,,0,0,0,,But other than that, it can do about the same stuff as prolog.\nDialogue: 0,0:18:49.88,0:18:52.78,EN,,0,0,0,,It has about the same power and about the same limitations.\nDialogue: 0,0:18:55.08,0:18:56.17,EN,,0,0,0,,All right, let's break for question.\nDialogue: 0,0:19:00.43,0:19:02.84,EN,,0,0,0,,AUDIENCE: Yes, could you please repeat what the three\nDialogue: 0,0:19:03.48,0:19:06.09,EN,,0,0,0,,things you use logic programming to find?\nDialogue: 0,0:19:06.72,0:19:09.84,EN,,0,0,0,,In other words, to find what is true, learn what is true-- what is the?\nDialogue: 0,0:19:09.84,0:19:10.52,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:19:10.56,0:19:15.74,EN,,0,0,0,,Sort of a logic programmer's little catechism.\nDialogue: 0,0:19:15.85,0:19:19.16,EN,,0,0,0,,You use logic to express what is true,\nDialogue: 0,0:19:20.80,0:19:21.79,EN,,0,0,0,,like these rules.\nDialogue: 0,0:19:22.61,0:19:25.56,EN,,0,0,0,,You use logic to check whether something is true,\nDialogue: 0,0:19:25.60,0:19:27.76,EN,,0,0,0,,and that's the kind of question I didn't answer here.\nDialogue: 0,0:19:28.55,0:19:29.29,EN,,0,0,0,,I might say--\nDialogue: 0,0:19:29.68,0:19:32.14,EN,,0,0,0,,another question I could put down here is to say,\nDialogue: 0,0:19:33.26,0:19:36.56,EN,,0,0,0,,is it true that 1, 3, 7 and 2, 4, 8\nDialogue: 0,0:19:36.91,0:19:40.38,EN,,0,0,0,,merge to form 1, 2, 6, 10\nDialogue: 0,0:19:41.12,0:19:44.68,EN,,0,0,0,,And that same logic should be enough to say no.\nDialogue: 0,0:19:45.69,0:19:47.93,EN,,0,0,0,,So I use logic to check what is true,\nDialogue: 0,0:19:48.28,0:19:50.48,EN,,0,0,0,,and then you also use logic to find out what's true.\nDialogue: 0,0:20:04.46,0:20:05.16,EN,,0,0,0,,Let's break.\nDialogue: 0,0:20:06.13,0:20:17.02,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:21:03.24,0:21:04.97,EN,,0,0,0,,PROFESSOR: OK, let's go ahead and\nDialogue: 0,0:21:05.84,0:21:08.44,EN,,0,0,0,,take a look at this query language and operation.\nDialogue: 0,0:21:10.52,0:21:11.84,EN,,0,0,0,,The first thing you might notice,\nDialogue: 0,0:21:12.24,0:21:14.14,EN,,0,0,0,,when I put up that little biblical database,\nDialogue: 0,0:21:14.16,0:21:17.24,EN,,0,0,0,,is that it's nice to be able to ask this language questions\nDialogue: 0,0:21:17.48,0:21:19.92,EN,,0,0,0,,in relation to some collection of facts.\nDialogue: 0,0:21:21.33,0:21:25.15,EN,,0,0,0,,So let's start off and make a little collection of facts.\nDialogue: 0,0:21:26.06,0:21:29.68,EN,,0,0,0,,This is a tiny fragment of personnel records\nDialogue: 0,0:21:30.08,0:21:32.62,EN,,0,0,0,,for a Boston high tech company,\nDialogue: 0,0:21:33.05,0:21:36.80,EN,,0,0,0,,and here's a piece of the personnel records of Ben Bitdiddle.\nDialogue: 0,0:21:37.50,0:21:41.95,EN,,0,0,0,,And Ben Bitdiddle is the computer wizard in this company,\nDialogue: 0,0:21:42.84,0:21:45.80,EN,,0,0,0,,he's the underpaid computer wizard in this company.\nDialogue: 0,0:21:46.42,0:21:48.78,EN,,0,0,0,,His supervisor is all Oliver Warbucks,\nDialogue: 0,0:21:49.28,0:21:50.70,EN,,0,0,0,,and here's his address.\nDialogue: 0,0:21:52.15,0:21:56.54,EN,,0,0,0,,So the format is we're giving this information: job, salary, supervisor, address.\nDialogue: 0,0:21:57.56,0:21:59.25,EN,,0,0,0,,And there are some other conventions.\nDialogue: 0,0:21:59.25,0:22:02.22,EN,,0,0,0,,Computer here means that Ben works in the computer division, and\nDialogue: 0,0:22:02.76,0:22:04.94,EN,,0,0,0,,his position in the computer division is wizard.\nDialogue: 0,0:22:05.66,0:22:07.15,EN,,0,0,0,,Here's somebody else.\nDialogue: 0,0:22:07.16,0:22:12.28,EN,,0,0,0,,Alyssa, Alyssa P. Hacker is a computer programmer,\nDialogue: 0,0:22:13.36,0:22:14.60,EN,,0,0,0,,and she works for Ben,\nDialogue: 0,0:22:15.21,0:22:16.54,EN,,0,0,0,,and she lives in Cambridge.\nDialogue: 0,0:22:17.55,0:22:19.42,EN,,0,0,0,,And there's another programmer who works for Ben\nDialogue: 0,0:22:20.03,0:22:21.44,EN,,0,0,0,,who's Lem E. Tweakit.\nDialogue: 0,0:22:22.82,0:22:26.73,EN,,0,0,0,,And there's a programmer trainee, who is Louis Reasoner,\nDialogue: 0,0:22:27.42,0:22:28.62,EN,,0,0,0,,and he works for Alyssa.\nDialogue: 0,0:22:30.10,0:22:35.45,EN,,0,0,0,,And the big wheel of the company doesn't work for anybody.\nDialogue: 0,0:22:36.81,0:22:38.11,EN,,0,0,0,,Right, That's Oliver Warbucks.\nDialogue: 0,0:22:38.11,0:22:39.31,EN,,0,0,0,,Anyway, what we're going to do is\nDialogue: 0,0:22:40.94,0:22:43.66,EN,,0,0,0,,is ask questions about that little world.\nDialogue: 0,0:22:44.97,0:22:48.40,EN,,0,0,0,,And that'll be a sample world that we're going to do logic in.\nDialogue: 0,0:22:51.42,0:22:54.96,EN,,0,0,0,,Let me just write up here, for probably the last time,\nDialogue: 0,0:22:55.60,0:22:58.20,EN,,0,0,0,,what I said is the very most important thing you should get out of this course,\nDialogue: 0,0:22:58.80,0:23:01.66,EN,,0,0,0,,and that is, when somebody tells you about a language,\nDialogue: 0,0:23:02.25,0:23:04.43,EN,,0,0,0,,you say, fine-- what are the primitives,\nDialogue: 0,0:23:06.12,0:23:07.79,EN,,0,0,0,,what are the means of combination,\nDialogue: 0,0:23:14.70,0:23:16.40,EN,,0,0,0,,how do you put the primitives together,\nDialogue: 0,0:23:16.67,0:23:19.37,EN,,0,0,0,,and then how do you abstract them,\nDialogue: 0,0:23:19.96,0:23:21.93,EN,,0,0,0,,how do you abstract the compound pieces\nDialogue: 0,0:23:24.68,0:23:27.58,EN,,0,0,0,,so you can use them as pieces to make something more complicated?\nDialogue: 0,0:23:29.02,0:23:30.81,EN,,0,0,0,,And we've said this a whole bunch of times already,\nDialogue: 0,0:23:31.16,0:23:32.48,EN,,0,0,0,,but it's worth saying again.\nDialogue: 0,0:23:35.00,0:23:36.67,EN,,0,0,0,,OKay? Let's start.\nDialogue: 0,0:23:36.67,0:23:37.34,EN,,0,0,0,,The primitives.\nDialogue: 0,0:23:37.77,0:23:39.44,EN,,0,0,0,,Well, there's really only one primitive,\nDialogue: 0,0:23:40.96,0:23:43.20,EN,,0,0,0,,and the primitive in this language is called a query.\nDialogue: 0,0:23:44.14,0:23:45.74,EN,,0,0,0,,A primitive query.\nDialogue: 0,0:23:46.81,0:23:48.25,EN,,0,0,0,,Let's look at some primitive queries.\nDialogue: 0,0:23:51.82,0:23:53.02,EN,,0,0,0,,Alright. Job x.\nDialogue: 0,0:23:53.10,0:23:54.81,EN,,0,0,0,,Who is a computer programmer?\nDialogue: 0,0:23:55.55,0:23:59.88,EN,,0,0,0,,Or find every fact in the database\nDialogue: 0,0:24:01.55,0:24:06.14,EN,,0,0,0,,that matches job of the x is computer programmer.\nDialogue: 0,0:24:06.64,0:24:08.01,EN,,0,0,0,,And you see a little syntax here.\nDialogue: 0,0:24:08.47,0:24:10.59,EN,,0,0,0,,Things without question marks are meant to be literal,\nDialogue: 0,0:24:11.28,0:24:13.15,EN,,0,0,0,,question mark x means that's a variable,\nDialogue: 0,0:24:13.31,0:24:15.56,EN,,0,0,0,,and this thing will match, for example,\nDialogue: 0,0:24:16.03,0:24:19.00,EN,,0,0,0,,the fact that Alyssa P. Hacker is a computer programmer,\nDialogue: 0,0:24:19.28,0:24:21.93,EN,,0,0,0,,or x is Alyssa P. Hacker.\nDialogue: 0,0:24:26.82,0:24:29.98,EN,,0,0,0,,Or more generally, I could have something with two variables in it.\nDialogue: 0,0:24:30.75,0:24:31.45,EN,,0,0,0,,I could say,\nDialogue: 0,0:24:31.60,0:24:35.88,EN,,0,0,0,,the job of x is computer something,\nDialogue: 0,0:24:39.34,0:24:41.39,EN,,0,0,0,,and that'll match computer wizard.\nDialogue: 0,0:24:42.14,0:24:44.28,EN,,0,0,0,,So there's something here: type will match wizard,\nDialogue: 0,0:24:44.92,0:24:46.46,EN,,0,0,0,,or type will match programmer,\nDialogue: 0,0:24:47.48,0:24:50.37,EN,,0,0,0,,or x might match various certain things.\nDialogue: 0,0:24:50.37,0:24:52.24,EN,,0,0,0,,So there are, in our little example,\nDialogue: 0,0:24:52.25,0:24:55.15,EN,,0,0,0,,only three facts in that database that match that query.\nDialogue: 0,0:24:59.12,0:25:02.08,EN,,0,0,0,,Let's see, just to show you some syntax, the same query,\nDialogue: 0,0:25:05.29,0:25:08.09,EN,,0,0,0,,this query doesn't match the job of x,\nDialogue: 0,0:25:09.85,0:25:11.79,EN,,0,0,0,,doesn't match Lewis Reasoner,\nDialogue: 0,0:25:11.84,0:25:13.64,EN,,0,0,0,,the reason for that is when I write something here,\nDialogue: 0,0:25:14.22,0:25:17.74,EN,,0,0,0,,what I mean is that this is going to be a list of two symbols,\nDialogue: 0,0:25:19.96,0:25:21.96,EN,,0,0,0,,of which the first is the word computer,\nDialogue: 0,0:25:22.32,0:25:23.80,EN,,0,0,0,,and the second can be anything.\nDialogue: 0,0:25:25.08,0:25:27.32,EN,,0,0,0,,And Lewis's job description here has three symbols,\nDialogue: 0,0:25:27.80,0:25:28.83,EN,,0,0,0,,so it doesn't match.\nDialogue: 0,0:25:30.34,0:25:32.19,EN,,0,0,0,,And just to show you a little bit of syntax,\nDialogue: 0,0:25:35.04,0:25:38.32,EN,,0,0,0,,the more general thing I might want to type is a thing with a dot here,\nDialogue: 0,0:25:40.17,0:25:42.92,EN,,0,0,0,,and this is just standard list notation for saying,\nDialogue: 0,0:25:43.04,0:25:43.82,EN,,0,0,0,,this is a list,\nDialogue: 0,0:25:44.12,0:25:47.32,EN,,0,0,0,,of which the first element is the word computers,\nDialogue: 0,0:25:47.58,0:25:50.22,EN,,0,0,0,,and THE REST, is something that I'll call type.\nDialogue: 0,0:25:53.73,0:25:55.50,EN,,0,0,0,,So this one would match.\nDialogue: 0,0:25:56.93,0:25:59.31,EN,,0,0,0,,Lewis's job is computer programmer trainee,\nDialogue: 0,0:25:59.44,0:26:03.29,EN,,0,0,0,,and type here would be the cdr of this list.\nDialogue: 0,0:26:03.32,0:26:05.64,EN,,0,0,0,,It would be the list programmer trainee.\nDialogue: 0,0:26:06.96,0:26:10.46,EN,,0,0,0,,And that kind of dot processing is done automatically by the LISP reader.\nDialogue: 0,0:26:15.90,0:26:17.76,EN,,0,0,0,,Well, let's actually try this.\nDialogue: 0,0:26:17.76,0:26:20.51,EN,,0,0,0,,The idea is I'm going to type in queries in this language,\nDialogue: 0,0:26:20.76,0:26:21.82,EN,,0,0,0,,and answers will come out.\nDialogue: 0,0:26:22.54,0:26:24.48,EN,,0,0,0,,Let's look at this.\nDialogue: 0,0:26:25.18,0:26:26.51,EN,,0,0,0,,I can go up and say,\nDialogue: 0,0:26:27.34,0:26:28.88,EN,,0,0,0,,who works in the computer division?\nDialogue: 0,0:26:30.00,0:26:38.22,EN,,0,0,0,,Job of x is computer dot y.\nDialogue: 0,0:26:39.73,0:26:41.48,EN,,0,0,0,,Doesn't matter what I call the dummy variables.\nDialogue: 0,0:26:42.76,0:26:44.14,EN,,0,0,0,,It says the answers to that,\nDialogue: 0,0:26:44.41,0:26:45.68,EN,,0,0,0,,and it's found four answers.\nDialogue: 0,0:26:48.65,0:26:50.09,EN,,0,0,0,,Or I can go off and say,\nDialogue: 0,0:26:50.56,0:26:52.38,EN,,0,0,0,,tell me about everybody's supervisor.\nDialogue: 0,0:26:52.81,0:26:54.88,EN,,0,0,0,,So I'll put in the query, the primitive query,\nDialogue: 0,0:26:56.52,0:26:59.39,EN,,0,0,0,,the supervisor of x is y.\nDialogue: 0,0:27:02.56,0:27:05.42,EN,,0,0,0,,There are all the supervisor relationships I know.\nDialogue: 0,0:27:05.54,0:27:08.83,EN,,0,0,0,,Or I could go type in, who lives in Cambridge?\nDialogue: 0,0:27:08.83,0:27:09.47,EN,,0,0,0,,So I can say,\nDialogue: 0,0:27:10.24,0:27:20.92,EN,,0,0,0,,the address of x is Cambridge dot anything.\nDialogue: 0,0:27:25.09,0:27:26.89,EN,,0,0,0,,And only one person lives in Cambridge.\nDialogue: 0,0:27:30.82,0:27:32.17,EN,,0,0,0,,OK, so those are primitive queries.\nDialogue: 0,0:27:32.17,0:27:34.96,EN,,0,0,0,,And you see what happens to basic interaction with the system\nDialogue: 0,0:27:35.29,0:27:39.24,EN,,0,0,0,,is you type in a query, and it types out all possible answers.\nDialogue: 0,0:27:39.62,0:27:40.65,EN,,0,0,0,,Or another way to say that:\nDialogue: 0,0:27:40.67,0:27:44.16,EN,,0,0,0,,it finds out all the possible values of those variables\nDialogue: 0,0:27:44.19,0:27:45.87,EN,,0,0,0,,x and y or t or whatever I've called them,\nDialogue: 0,0:27:46.09,0:27:52.08,EN,,0,0,0,,and it types out all ways of taking that query and instantiating it--\nDialogue: 0,0:27:52.92,0:27:55.16,EN,,0,0,0,,remember that from the rule system lecture--\nDialogue: 0,0:27:55.16,0:27:58.83,EN,,0,0,0,,instantiates the query with all possible values for those variables\nDialogue: 0,0:27:59.00,0:28:00.35,EN,,0,0,0,,and then types out all of them.\nDialogue: 0,0:28:01.00,0:28:03.35,EN,,0,0,0,,And there are a lot of ways you can arrange a logic language.\nDialogue: 0,0:28:03.35,0:28:06.01,EN,,0,0,0,,Prolog, for instance, does something slightly different.\nDialogue: 0,0:28:06.01,0:28:07.44,EN,,0,0,0,,Rather than typing back your query,\nDialogue: 0,0:28:07.76,0:28:10.78,EN,,0,0,0,,prolog would type out, x equals this and y equals that,\nDialogue: 0,0:28:10.97,0:28:12.94,EN,,0,0,0,,or x equals this and y equals that.\nDialogue: 0,0:28:13.66,0:28:15.48,EN,,0,0,0,,And that's a very surface level thing,\nDialogue: 0,0:28:15.71,0:28:17.05,EN,,0,0,0,,you can decide what you like.\nDialogue: 0,0:28:18.97,0:28:19.58,EN,,0,0,0,,OK.\nDialogue: 0,0:28:21.00,0:28:22.68,EN,,0,0,0,,Alright. So the primitives in this language?\nDialogue: 0,0:28:23.39,0:28:24.57,EN,,0,0,0,,Only one, right?\nDialogue: 0,0:28:24.57,0:28:27.23,EN,,0,0,0,,Primitive query.\nDialogue: 0,0:28:31.31,0:28:32.56,EN,,0,0,0,,Means of combination.\nDialogue: 0,0:28:34.33,0:28:37.68,EN,,0,0,0,,Let's look at some compound queries in this language.\nDialogue: 0,0:28:39.77,0:28:40.46,EN,,0,0,0,,Here's one.\nDialogue: 0,0:28:41.79,0:28:42.51,EN,,0,0,0,,This one says,\nDialogue: 0,0:28:45.05,0:28:48.22,EN,,0,0,0,,tell me all the people who work in the computer division.\nDialogue: 0,0:28:49.81,0:28:52.00,EN,,0,0,0,,Tell me all the people who work in the computer division\nDialogue: 0,0:28:52.54,0:28:53.96,EN,,0,0,0,,together with their supervisors.\nDialogue: 0,0:28:56.80,0:28:58.83,EN,,0,0,0,,Where I write that is the query is and.\nDialogue: 0,0:29:00.22,0:29:04.06,EN,,0,0,0,,And the job of the x is computer something or other.\nDialogue: 0,0:29:04.92,0:29:06.83,EN,,0,0,0,,And job of x is computer dot y.\nDialogue: 0,0:29:07.56,0:29:10.03,EN,,0,0,0,,And the supervisor of x is z.\nDialogue: 0,0:29:11.44,0:29:14.16,EN,,0,0,0,,Tell me all the people in the computer division-- that's this--\nDialogue: 0,0:29:14.30,0:29:15.88,EN,,0,0,0,,together with their supervisors.\nDialogue: 0,0:29:16.46,0:29:17.82,EN,,0,0,0,,And notice in this query\nDialogue: 0,0:29:18.67,0:29:22.41,EN,,0,0,0,,I have three variables-- x, y, and z.\nDialogue: 0,0:29:23.58,0:29:28.65,EN,,0,0,0,,And this x is supposed to be the same as that x.\nDialogue: 0,0:29:29.45,0:29:31.16,EN,,0,0,0,,So x works in the computer division,\nDialogue: 0,0:29:31.31,0:29:33.00,EN,,0,0,0,,and the supervisor of x is z.\nDialogue: 0,0:29:34.81,0:29:35.80,EN,,0,0,0,,Let's try another one.\nDialogue: 0,0:29:37.25,0:29:39.28,EN,,0,0,0,,So one means of combination is and.\nDialogue: 0,0:29:41.44,0:29:43.96,EN,,0,0,0,,Who are all the people who make more than $30,000?\nDialogue: 0,0:29:45.71,0:29:51.71,EN,,0,0,0,,And the salary of some person p is some amount a.\nDialogue: 0,0:29:54.59,0:29:57.45,EN,,0,0,0,,And when I go and look at a,\nDialogue: 0,0:29:57.48,0:30:00.12,EN,,0,0,0,,a is greater than $30,000.\nDialogue: 0,0:30:00.60,0:30:03.23,EN,,0,0,0,,And LISP value here is a little piece of interface\nDialogue: 0,0:30:04.30,0:30:10.04,EN,,0,0,0,,that interfaces the query language to the underlying LISP.\nDialogue: 0,0:30:10.60,0:30:12.72,EN,,0,0,0,,And what the LISP value allows you to do\nDialogue: 0,0:30:12.75,0:30:16.91,EN,,0,0,0,,call any LISP predicate inside a query.\nDialogue: 0,0:30:17.18,0:30:20.11,EN,,0,0,0,,So here I'm using the LISP predicate greater than, so I say LISP value.\nDialogue: 0,0:30:21.02,0:30:21.75,EN,,0,0,0,,This I say and.\nDialogue: 0,0:30:21.75,0:30:24.48,EN,,0,0,0,,So all the people whose salary is greater than $30,000.\nDialogue: 0,0:30:28.19,0:30:30.03,EN,,0,0,0,,Or here's a more complicated one.\nDialogue: 0,0:30:31.27,0:30:35.02,EN,,0,0,0,,Tell me all the people who work in the computer division\nDialogue: 0,0:30:36.25,0:30:39.36,EN,,0,0,0,,who do not have a supervisor who works in the computer division.\nDialogue: 0,0:30:42.79,0:30:45.51,EN,,0,0,0,,and x works in the computer division.\nDialogue: 0,0:30:45.51,0:30:47.32,EN,,0,0,0,,The job of x is computer dot y.\nDialogue: 0,0:30:47.78,0:30:49.24,EN,,0,0,0,,And it's not the case\nDialogue: 0,0:30:50.49,0:30:54.25,EN,,0,0,0,,that both x has a supervisor z\nDialogue: 0,0:30:55.37,0:30:57.87,EN,,0,0,0,,and the job of z is computer something or other.\nDialogue: 0,0:30:59.62,0:31:00.35,EN,,0,0,0,,All right, so again,\nDialogue: 0,0:31:00.51,0:31:02.38,EN,,0,0,0,,this x has got to be that x,\nDialogue: 0,0:31:03.20,0:31:05.76,EN,,0,0,0,,and this z is going to be that z.\nDialogue: 0,0:31:09.39,0:31:11.38,EN,,0,0,0,,And then you see another means a combination, not.\nDialogue: 0,0:31:17.71,0:31:18.67,EN,,0,0,0,,All right, well, let's look at that.\nDialogue: 0,0:31:20.88,0:31:22.08,EN,,0,0,0,,It works the same way.\nDialogue: 0,0:31:22.40,0:31:24.12,EN,,0,0,0,,I can go up to the machine and say\nDialogue: 0,0:31:26.89,0:31:35.40,EN,,0,0,0,,and the job of the x is computer dot y.\nDialogue: 0,0:31:38.84,0:31:45.95,EN,,0,0,0,,And the supervisor of x is z.\nDialogue: 0,0:31:46.83,0:31:49.53,EN,,0,0,0,,And I typed that in like a query.\nDialogue: 0,0:31:51.07,0:31:52.97,EN,,0,0,0,,And what it types back,\nDialogue: 0,0:31:54.00,0:31:58.73,EN,,0,0,0,,what you see are the queries I typed in instantiated by all possible answers.\nDialogue: 0,0:31:58.93,0:32:00.08,EN,,0,0,0,,And then you see there are a lot of answers.\nDialogue: 0,0:32:01.69,0:32:02.14,EN,,0,0,0,,All right.\nDialogue: 0,0:32:02.19,0:32:04.04,EN,,0,0,0,,So the means of combination in this language--\nDialogue: 0,0:32:05.21,0:32:06.60,EN,,0,0,0,,and this is why it's called a logic language--\nDialogue: 0,0:32:06.64,0:32:09.47,EN,,0,0,0,,are logical operations.\nDialogue: 0,0:32:09.80,0:32:15.68,EN,,0,0,0,,Means of combinations are things like AND and NOT\nDialogue: 0,0:32:15.96,0:32:17.92,EN,,0,0,0,,and there's one I didn't show you, which is OR.\nDialogue: 0,0:32:18.49,0:32:20.36,EN,,0,0,0,,And then I showed you LISP value,\nDialogue: 0,0:32:20.72,0:32:24.48,EN,,0,0,0,,which is a, not logic, of course,\nDialogue: 0,0:32:24.51,0:32:26.89,EN,,0,0,0,,but is a little special hack to interface that to LISP\nDialogue: 0,0:32:27.34,0:32:28.75,EN,,0,0,0,,so you can get more power.\nDialogue: 0,0:32:29.25,0:32:30.67,EN,,0,0,0,,Those are the means of combination.\nDialogue: 0,0:32:32.59,0:32:33.98,EN,,0,0,0,,OK, the means of abstraction.\nDialogue: 0,0:32:34.16,0:32:35.21,EN,,0,0,0,,What we'd like to do--\nDialogue: 0,0:32:38.27,0:32:41.24,EN,,0,0,0,,let's go back for second and look at that last slide.\nDialogue: 0,0:32:42.26,0:32:44.25,EN,,0,0,0,,We might like to take very complicated thing,\nDialogue: 0,0:32:44.46,0:32:48.00,EN,,0,0,0,,the idea that someone works in a division\nDialogue: 0,0:32:48.01,0:32:50.09,EN,,0,0,0,,but does not have a supervisor in the division.\nDialogue: 0,0:32:52.40,0:32:55.10,EN,,0,0,0,,And as before, name that.\nDialogue: 0,0:32:56.09,0:32:58.12,EN,,0,0,0,,Well, if someone works in a division\nDialogue: 0,0:32:58.17,0:33:00.25,EN,,0,0,0,,and does not have a supervisor who works in that division,\nDialogue: 0,0:33:00.48,0:33:01.93,EN,,0,0,0,,that means that person is a big shot.\nDialogue: 0,0:33:02.75,0:33:05.13,EN,,0,0,0,,So let's make a rule that\nDialogue: 0,0:33:06.43,0:33:09.16,EN,,0,0,0,,somebody x is a big shot in some department\nDialogue: 0,0:33:10.91,0:33:14.68,EN,,0,0,0,,if x works in the department\nDialogue: 0,0:33:16.04,0:33:20.08,EN,,0,0,0,,and it's not the case that x has a supervisor who works in the department.\nDialogue: 0,0:33:21.51,0:33:22.94,EN,,0,0,0,,So this is our means of abstraction.\nDialogue: 0,0:33:22.94,0:33:23.90,EN,,0,0,0,,This is a rule.\nDialogue: 0,0:33:26.22,0:33:27.58,EN,,0,0,0,,And a rule has three parts.\nDialogue: 0,0:33:31.00,0:33:32.48,EN,,0,0,0,,The thing that says it's a rule.\nDialogue: 0,0:33:33.40,0:33:35.48,EN,,0,0,0,,And then there's the conclusion of the rule.\nDialogue: 0,0:33:37.53,0:33:39.07,EN,,0,0,0,,And then there's the body of the rule.\nDialogue: 0,0:33:40.00,0:33:41.88,EN,,0,0,0,,And you can read this as a piece of logic which says,\nDialogue: 0,0:33:41.92,0:33:45.15,EN,,0,0,0,,if you know that the body of the rule is true,\nDialogue: 0,0:33:46.40,0:33:48.72,EN,,0,0,0,,then you can conclude that the conclusion is true.\nDialogue: 0,0:33:49.45,0:33:53.28,EN,,0,0,0,,Or in order to deduce that x is a big shot in some department,\nDialogue: 0,0:33:53.79,0:33:55.71,EN,,0,0,0,,it's enough to verify that.\nDialogue: 0,0:33:57.48,0:33:58.82,EN,,0,0,0,,So that's what rules look like.\nDialogue: 0,0:34:03.28,0:34:06.16,EN,,0,0,0,,Let's go back and look at that merge example\nDialogue: 0,0:34:06.73,0:34:07.92,EN,,0,0,0,,that I did before the break.\nDialogue: 0,0:34:08.11,0:34:10.68,EN,,0,0,0,,Let's look at how that would look in terms of rules.\nDialogue: 0,0:34:11.44,0:34:12.84,EN,,0,0,0,,I'm going to take the logic I put up\nDialogue: 0,0:34:13.08,0:34:15.50,EN,,0,0,0,,and just change it into a bunch of rules in this format.\nDialogue: 0,0:34:18.73,0:34:19.35,EN,,0,0,0,,We have a rule.\nDialogue: 0,0:34:19.35,0:34:20.96,EN,,0,0,0,,Remember, there was this thing merge-to-form.\nDialogue: 0,0:34:21.71,0:34:22.97,EN,,0,0,0,,There is a rule that says,\nDialogue: 0,0:34:26.28,0:34:29.62,EN,,0,0,0,,the empty list and y merge to form y.\nDialogue: 0,0:34:29.62,0:34:30.87,EN,,0,0,0,,This is the rule conclusion.\nDialogue: 0,0:34:33.21,0:34:35.74,EN,,0,0,0,,And notice this particular rule has no body.\nDialogue: 0,0:34:36.65,0:34:37.66,EN,,0,0,0,,And in this language,\nDialogue: 0,0:34:38.11,0:34:40.86,EN,,0,0,0,,a rule with no body is something that is always true.\nDialogue: 0,0:34:41.23,0:34:42.51,EN,,0,0,0,,You can always assume that's true.\nDialogue: 0,0:34:45.19,0:34:46.49,EN,,0,0,0,,And there was another piece of logic\nDialogue: 0,0:34:46.64,0:34:49.46,EN,,0,0,0,,that said anything in the empty list merged to form the anything.\nDialogue: 0,0:34:49.46,0:34:50.12,EN,,0,0,0,,That's this.\nDialogue: 0,0:34:50.90,0:34:53.55,EN,,0,0,0,,A rule y and the empty list merge to form y.\nDialogue: 0,0:34:55.51,0:34:58.40,EN,,0,0,0,,Those corresponded to the two end cases in our merge procedure,\nDialogue: 0,0:34:58.44,0:34:59.77,EN,,0,0,0,,but now we're talking about logic,\nDialogue: 0,0:35:00.41,0:35:01.45,EN,,0,0,0,,not about procedures.\nDialogue: 0,0:35:03.49,0:35:04.48,EN,,0,0,0,,Then we had another rule,\nDialogue: 0,0:35:04.83,0:35:08.73,EN,,0,0,0,,which said if you know how shorter things merge,\nDialogue: 0,0:35:08.91,0:35:09.83,EN,,0,0,0,,you can put them together.\nDialogue: 0,0:35:09.83,0:35:14.16,EN,,0,0,0,,So this says, if you have a list x and y and z,\nDialogue: 0,0:35:14.92,0:35:17.61,EN,,0,0,0,,and if you want to deduce that a dot x--\nDialogue: 0,0:35:17.63,0:35:19.08,EN,,0,0,0,,this means cons a onto x,\nDialogue: 0,0:35:19.48,0:35:22.36,EN,,0,0,0,,or a list whose first thing is a and whose rest is x--\nDialogue: 0,0:35:23.16,0:35:27.40,EN,,0,0,0,,so if you want to deduce that a dot x and b dot y merge to form b dot z--\nDialogue: 0,0:35:30.36,0:35:33.90,EN,,0,0,0,,that would say you merge these two lists a x and b y\nDialogue: 0,0:35:33.92,0:35:35.85,EN,,0,0,0,,and you're going to get something that starts with b--\nDialogue: 0,0:35:36.76,0:35:40.67,EN,,0,0,0,,you can deduce that if you know that it's the case\nDialogue: 0,0:35:40.91,0:35:44.48,EN,,0,0,0,,both that a dot x and y merge to form z\nDialogue: 0,0:35:45.18,0:35:47.24,EN,,0,0,0,,and a is larger than b.\nDialogue: 0,0:35:48.69,0:35:50.59,EN,,0,0,0,,So when I merge them, b will come first in the list.\nDialogue: 0,0:35:51.82,0:35:54.91,EN,,0,0,0,,That's a little translation of the logic rule\nDialogue: 0,0:35:55.24,0:35:57.18,EN,,0,0,0,,that I wrote in pseudo-English before.\nDialogue: 0,0:35:57.96,0:36:01.63,EN,,0,0,0,,And then just for completeness, here's the other case.\nDialogue: 0,0:36:02.88,0:36:05.95,EN,,0,0,0,,a dot x and b dot y merge to form a dot z\nDialogue: 0,0:36:06.08,0:36:09.16,EN,,0,0,0,,if x and b dot y merged to form z and b is larger than a.\nDialogue: 0,0:36:09.47,0:36:11.00,EN,,0,0,0,,and b is larger than a.\nDialogue: 0,0:36:12.19,0:36:15.98,EN,,0,0,0,,So that's a little program that I've typed in in this language,\nDialogue: 0,0:36:16.01,0:36:17.07,EN,,0,0,0,,and now let's look at it run.\nDialogue: 0,0:36:21.90,0:36:23.90,EN,,0,0,0,,So I typed in the merge rules before,\nDialogue: 0,0:36:24.62,0:36:25.77,EN,,0,0,0,,and I could say, ahh\nDialogue: 0,0:36:27.04,0:36:28.51,EN,,0,0,0,,I could use this like a procedure.\nDialogue: 0,0:36:28.51,0:36:38.24,EN,,0,0,0,,I could say merge to form 1 and 3 and 2 and 7.\nDialogue: 0,0:36:39.42,0:36:41.55,EN,,0,0,0,,So here I'm using it like the LISP procedure.\nDialogue: 0,0:36:43.16,0:36:44.97,EN,,0,0,0,,Now it's going to think about that for a while\nDialogue: 0,0:36:46.43,0:36:47.56,EN,,0,0,0,,and apply these rules.\nDialogue: 0,0:36:50.78,0:36:51.92,EN,,0,0,0,,So it found an answer.\nDialogue: 0,0:36:52.80,0:36:54.54,EN,,0,0,0,,Now it's going to see if there are any other answers\nDialogue: 0,0:36:55.07,0:36:57.32,EN,,0,0,0,,it doesn't know a priori there's only one answer.\nDialogue: 0,0:36:57.81,0:36:59.90,EN,,0,0,0,,So it's sitting here checking all possibilities,\nDialogue: 0,0:37:00.41,0:37:02.54,EN,,0,0,0,,and it says, no more. Done.\nDialogue: 0,0:37:03.16,0:37:05.07,EN,,0,0,0,,So there I've used those rules like a procedure.\nDialogue: 0,0:37:05.21,0:37:09.05,EN,,0,0,0,,Or remember the whole point is that I can ask different kinds of questions.\nDialogue: 0,0:37:10.22,0:37:11.07,EN,,0,0,0,,I could say\nDialogue: 0,0:37:18.56,0:37:24.59,EN,,0,0,0,,merge to form, let's see, how about 2 and a.\nDialogue: 0,0:37:24.59,0:37:27.90,EN,,0,0,0,,Some list of two elements which I know starts with 2,\nDialogue: 0,0:37:29.37,0:37:31.26,EN,,0,0,0,,and the other thing I don't know,\nDialogue: 0,0:37:33.05,0:37:35.04,EN,,0,0,0,,and x and some other list\nDialogue: 0,0:37:36.48,0:37:39.51,EN,,0,0,0,,merge to form a 1, 2, 3 and 4.\nDialogue: 0,0:37:42.76,0:37:44.11,EN,,0,0,0,,So now it's going to think about that.\nDialogue: 0,0:37:44.59,0:37:49.40,EN,,0,0,0,,It's got to find--  so it found one possibility.\nDialogue: 0,0:37:49.52,0:37:52.46,EN,,0,0,0,,It said a could be 3, and x could be the list 1, 4.\nDialogue: 0,0:37:53.72,0:37:55.16,EN,,0,0,0,,And now, again, it's got to check\nDialogue: 0,0:37:56.56,0:37:57.71,EN,,0,0,0,,because it doesn't a priori know\nDialogue: 0,0:37:57.74,0:38:00.30,EN,,0,0,0,,that there aren't any other possibilities going on.\nDialogue: 0,0:38:03.68,0:38:06.57,EN,,0,0,0,,Or like I said,\nDialogue: 0,0:38:07.00,0:38:09.84,EN,,0,0,0,,I could say something like merge to form,\nDialogue: 0,0:38:10.54,0:38:17.55,EN,,0,0,0,,like, what and what else merge to form 1, 2, 3, 4, 5?\nDialogue: 0,0:38:23.68,0:38:25.53,EN,,0,0,0,,Now it's going to think about that.\nDialogue: 0,0:38:28.49,0:38:30.31,EN,,0,0,0,,And there are a lot of answers that it might get.\nDialogue: 0,0:38:35.18,0:38:38.57,EN,,0,0,0,,And what you see is here you're really paying the price of slowness.\nDialogue: 0,0:38:42.21,0:38:43.88,EN,,0,0,0,,And kind of for three reasons.\nDialogue: 0,0:38:43.88,0:38:46.22,EN,,0,0,0,,One is that this language is doubly interpreted.\nDialogue: 0,0:38:47.63,0:38:49.72,EN,,0,0,0,,Whereas in a real implementation,\nDialogue: 0,0:38:49.76,0:38:52.04,EN,,0,0,0,,you would go compile this down to primitive operations.\nDialogue: 0,0:38:52.19,0:38:53.87,EN,,0,0,0,,The other reason is that\nDialogue: 0,0:38:53.88,0:38:58.11,EN,,0,0,0,,this particular algorithm for merges is doubly recursive.\nDialogue: 0,0:38:58.38,0:39:00.06,EN,,0,0,0,,So it's going to take a very long time.\nDialogue: 0,0:39:01.02,0:39:04.33,EN,,0,0,0,,And eventually, this is going to go through\nDialogue: 0,0:39:04.59,0:39:07.13,EN,,0,0,0,,and find-- find what?\nDialogue: 0,0:39:07.13,0:39:08.73,EN,,0,0,0,,Two to the fifth possible answers.\nDialogue: 0,0:39:12.14,0:39:14.96,EN,,0,0,0,,And you see they come out in some fairly arbitrary order,\nDialogue: 0,0:39:15.00,0:39:18.14,EN,,0,0,0,,depending on which order it's going to be trying these rules.\nDialogue: 0,0:39:20.16,0:39:22.11,EN,,0,0,0,,In fact, what we're going to do when they edit the videotape\nDialogue: 0,0:39:22.40,0:39:23.48,EN,,0,0,0,,is speed all this up.\nDialogue: 0,0:39:24.08,0:39:26.60,EN,,0,0,0,,Don't you like taking out these waits?\nDialogue: 0,0:39:26.60,0:39:28.27,EN,,0,0,0,,And don't you wish you could do that in your demos?\nDialogue: 0,0:39:29.48,0:39:34.24,EN,,0,0,0,,Anyway, it's still grinding there.\nDialogue: 0,0:39:39.22,0:39:41.12,EN,,0,0,0,,Anyway, there are 32 possibilities--\nDialogue: 0,0:39:41.13,0:39:42.63,EN,,0,0,0,,we won't wait for it to print out all of them.\nDialogue: 0,0:39:47.85,0:39:50.44,EN,,0,0,0,,OK, so the needs of abstraction in this language are rules.\nDialogue: 0,0:39:53.53,0:39:58.01,EN,,0,0,0,,So we take some bunch of things that are put together with logic\nDialogue: 0,0:39:59.12,0:40:00.08,EN,,0,0,0,,and we name them.\nDialogue: 0,0:40:00.35,0:40:03.41,EN,,0,0,0,,And you can think of that as naming a particular pattern of logic.\nDialogue: 0,0:40:03.41,0:40:04.54,EN,,0,0,0,,Or you can think of that as saying,\nDialogue: 0,0:40:04.56,0:40:06.75,EN,,0,0,0,,if you want to deduce some conclusion,\nDialogue: 0,0:40:07.90,0:40:09.52,EN,,0,0,0,,you can apply those rules of logic.\nDialogue: 0,0:40:10.66,0:40:13.20,EN,,0,0,0,,And those are three elements of this language.\nDialogue: 0,0:40:13.42,0:40:14.56,EN,,0,0,0,,Let's break now,\nDialogue: 0,0:40:14.60,0:40:16.59,EN,,0,0,0,,and then we'll talk about how it's actually implemented.\nDialogue: 0,0:40:23.61,0:40:28.84,EN,,0,0,0,,AUDIENCE: Does using LISP value primitive or whatever interfere with your means\nDialogue: 0,0:40:29.15,0:40:30.64,EN,,0,0,0,,both directions on a query?\nDialogue: 0,0:40:31.77,0:40:34.48,EN,,0,0,0,,PROFESSOR: OK, that's a-- the question is,\nDialogue: 0,0:40:35.08,0:40:36.92,EN,,0,0,0,,does using LISP value interfere\nDialogue: 0,0:40:37.53,0:40:40.09,EN,,0,0,0,,with the ability to go both directions on the query?\nDialogue: 0,0:40:40.09,0:40:42.81,EN,,0,0,0,,We haven't really talked about the implementation yet,\nDialogue: 0,0:40:43.68,0:40:45.52,EN,,0,0,0,,but the answer is, yes, it can.\nDialogue: 0,0:40:46.89,0:40:50.20,EN,,0,0,0,,In general, as we'll see at the end--\nDialogue: 0,0:40:50.22,0:40:52.17,EN,,0,0,0,,although I really won't to go into details--\nDialogue: 0,0:40:53.21,0:40:59.36,EN,,0,0,0,,it's fairly complicated, especially when you use either not or LISP value--\nDialogue: 0,0:40:59.55,0:41:02.89,EN,,0,0,0,,or actually, if you use anything besides only and,\nDialogue: 0,0:41:04.12,0:41:08.19,EN,,0,0,0,,it becomes very complicated to say when these things will work.\nDialogue: 0,0:41:08.20,0:41:10.36,EN,,0,0,0,,They won't work quite in all situations.\nDialogue: 0,0:41:10.36,0:41:13.39,EN,,0,0,0,,I'll talk about that at the end of the second half today.\nDialogue: 0,0:41:14.30,0:41:15.84,EN,,0,0,0,,But the answer to your question is, yes,\nDialogue: 0,0:41:16.19,0:41:19.21,EN,,0,0,0,,by dragging in a lot more power from LISP value,\nDialogue: 0,0:41:19.40,0:41:23.77,EN,,0,0,0,,you lose some of the principal power of logic programming.\nDialogue: 0,0:41:24.17,0:41:25.56,EN,,0,0,0,,That's a trade-off that you have to make.\nDialogue: 0,0:41:28.48,0:41:29.39,EN,,0,0,0,,OK, let's take a break.\n"
  },
  {
    "path": "Ass/lec8b.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:18.91,0:00:21.79,EN,,0,0,0,,PROFESSOR: All right, well, we've seen how the query language works.\nDialogue: 0,0:00:22.64,0:00:25.07,EN,,0,0,0,,Now, let's talk about how it's implemented.\nDialogue: 0,0:00:26.28,0:00:27.98,EN,,0,0,0,,You already pretty much can guess\nDialogue: 0,0:00:28.59,0:00:29.47,EN,,0,0,0,,what's going on there.\nDialogue: 0,0:00:29.47,0:00:31.64,EN,,0,0,0,,At the bottom of it, there's a pattern matcher.\nDialogue: 0,0:00:32.81,0:00:34.25,EN,,0,0,0,,And we looked at a pattern matcher\nDialogue: 0,0:00:34.67,0:00:36.94,EN,,0,0,0,,when we did the rule-based control language.\nDialogue: 0,0:00:38.11,0:00:40.59,EN,,0,0,0,,Just to remind you, here are some sample patterns.\nDialogue: 0,0:00:41.52,0:00:43.68,EN,,0,0,0,,This is a pattern that will match\nDialogue: 0,0:00:43.80,0:00:44.92,EN,,0,0,0,,any list of three things\nDialogue: 0,0:00:44.96,0:00:47.10,EN,,0,0,0,,which the first is a\nDialogue: 0,0:00:47.16,0:00:48.33,EN,,0,0,0,,the second is c\nDialogue: 0,0:00:48.48,0:00:50.19,EN,,0,0,0,,and the middle one can be anything.\nDialogue: 0,0:00:50.65,0:00:52.27,EN,,0,0,0,,So in this little pattern-matching syntax,\nDialogue: 0,0:00:52.30,0:00:54.05,EN,,0,0,0,,there's only one distinction you make.\nDialogue: 0,0:00:54.05,0:00:57.20,EN,,0,0,0,,There's either literal things or variables,\nDialogue: 0,0:00:57.23,0:00:58.86,EN,,0,0,0,,and variables begin with question mark.\nDialogue: 0,0:01:01.37,0:01:03.64,EN,,0,0,0,,So this matches any list of three things\nDialogue: 0,0:01:04.44,0:01:06.50,EN,,0,0,0,,of which the first is a and the second is c.\nDialogue: 0,0:01:06.50,0:01:09.00,EN,,0,0,0,,This one matches any list of three things\nDialogue: 0,0:01:10.43,0:01:12.53,EN,,0,0,0,,of which the first is the symbol job.\nDialogue: 0,0:01:12.53,0:01:13.90,EN,,0,0,0,,The second can be anything.\nDialogue: 0,0:01:14.21,0:01:15.90,EN,,0,0,0,,And the third is a list of two things\nDialogue: 0,0:01:15.95,0:01:17.72,EN,,0,0,0,,of which the first is the symbol computer\nDialogue: 0,0:01:17.88,0:01:19.42,EN,,0,0,0,,and the second can be anything.\nDialogue: 0,0:01:20.48,0:01:25.55,EN,,0,0,0,,And this one, this next one matches any list of three things,\nDialogue: 0,0:01:25.87,0:01:26.99,EN,,0,0,0,,and the only difference is,\nDialogue: 0,0:01:28.40,0:01:31.32,EN,,0,0,0,,here, the third list, the first is the symbol computer,\nDialogue: 0,0:01:31.76,0:01:33.29,EN,,0,0,0,,and then there's some rest of the list.\nDialogue: 0,0:01:35.04,0:01:37.53,EN,,0,0,0,,So this means two elements and this means arbitrary number.\nDialogue: 0,0:01:37.86,0:01:39.74,EN,,0,0,0,,And our language implementation isn't\nDialogue: 0,0:01:39.85,0:01:42.06,EN,,0,0,0,,isn't even going to have to worry about implementing this dot\nDialogue: 0,0:01:42.11,0:01:44.17,EN,,0,0,0,,because that's automatically done by Lisp's reader.\nDialogue: 0,0:01:48.34,0:01:50.31,EN,,0,0,0,,Remember matchers also have some consistency in them.\nDialogue: 0,0:01:50.31,0:01:52.32,EN,,0,0,0,,This match is a list of three things\nDialogue: 0,0:01:52.59,0:01:53.98,EN,,0,0,0,,of which the first is a.\nDialogue: 0,0:01:54.43,0:01:55.79,EN,,0,0,0,,And the second and third can be anything,\nDialogue: 0,0:01:55.80,0:01:57.08,EN,,0,0,0,,but they have to be the same thing.\nDialogue: 0,0:01:57.94,0:01:58.84,EN,,0,0,0,,They're both called x.\nDialogue: 0,0:01:59.60,0:02:01.55,EN,,0,0,0,,And this matches a list of four things\nDialogue: 0,0:02:01.96,0:02:03.26,EN,,0,0,0,,of which the first is the fourth\nDialogue: 0,0:02:03.66,0:02:05.15,EN,,0,0,0,,and the second is the same as the third.\nDialogue: 0,0:02:05.59,0:02:08.60,EN,,0,0,0,,And this last one matches any list that begins with a.\nDialogue: 0,0:02:09.68,0:02:11.05,EN,,0,0,0,,The first thing is a,\nDialogue: 0,0:02:11.23,0:02:12.56,EN,,0,0,0,,and the rest can be anything.\nDialogue: 0,0:02:14.04,0:02:16.60,EN,,0,0,0,,So that's just a review of pattern matcher syntax\nDialogue: 0,0:02:16.62,0:02:17.87,EN,,0,0,0,,that you've already seen.\nDialogue: 0,0:02:18.78,0:02:19.64,EN,,0,0,0,,And remember,\nDialogue: 0,0:02:19.79,0:02:22.28,EN,,0,0,0,,that's implemented by some procedure called match.\nDialogue: 0,0:02:24.87,0:02:36.06,EN,,0,0,0,,And match takes a pattern and some data and a dictionary.\nDialogue: 0,0:02:43.20,0:02:47.12,EN,,0,0,0,,And match asks the question\nDialogue: 0,0:02:47.79,0:02:52.64,EN,,0,0,0,,is there any way to match this pattern against this data object\nDialogue: 0,0:02:53.55,0:02:56.73,EN,,0,0,0,,subject to the bindings that are already in this dictionary?\nDialogue: 0,0:02:58.16,0:02:59.21,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:02:59.56,0:03:06.43,EN,,0,0,0,,if we're going to match the pattern x, y, y, x\nDialogue: 0,0:03:07.71,0:03:13.84,EN,,0,0,0,,against the data a, b, b, a\nDialogue: 0,0:03:15.12,0:03:20.52,EN,,0,0,0,,subject to a dictionary, that says x equals a.\nDialogue: 0,0:03:22.01,0:03:25.23,EN,,0,0,0,,Then the matcher would say, yes, that's consistent.\nDialogue: 0,0:03:25.26,0:03:27.16,EN,,0,0,0,,These match, and it's consistent\nDialogue: 0,0:03:27.80,0:03:30.20,EN,,0,0,0,,with what's in the dictionary to say that x equals a.\nDialogue: 0,0:03:30.32,0:03:31.60,EN,,0,0,0,,And the result of the match\nDialogue: 0,0:03:32.25,0:03:34.30,EN,,0,0,0,,is the extended dictionary\nDialogue: 0,0:03:34.46,0:03:37.60,EN,,0,0,0,,that says x equals a and y equals b.\nDialogue: 0,0:03:39.49,0:03:42.24,EN,,0,0,0,,So a matcher takes in pattern data dictionary,\nDialogue: 0,0:03:42.38,0:03:44.54,EN,,0,0,0,,puts out an extended dictionary if it matches,\nDialogue: 0,0:03:44.97,0:03:46.84,EN,,0,0,0,,or if it doesn't match, says that it fails.\nDialogue: 0,0:03:46.84,0:03:47.71,EN,,0,0,0,,So, for example,\nDialogue: 0,0:03:47.88,0:03:50.38,EN,,0,0,0,,if I use the same pattern here,\nDialogue: 0,0:03:50.97,0:03:55.12,EN,,0,0,0,,if I say this x, y, y, x\nDialogue: 0,0:03:55.66,0:03:58.49,EN,,0,0,0,,match a, b, b, a\nDialogue: 0,0:03:59.47,0:04:02.84,EN,,0,0,0,,with the dictionary y equals a,\nDialogue: 0,0:04:05.15,0:04:06.81,EN,,0,0,0,,then the matcher would put out fail.\nDialogue: 0,0:04:12.52,0:04:14.65,EN,,0,0,0,,Well, you've already seen the code for a pattern matcher\nDialogue: 0,0:04:15.00,0:04:16.17,EN,,0,0,0,,so I'm not going to go over it,\nDialogue: 0,0:04:16.64,0:04:19.77,EN,,0,0,0,,but it's the same thing we've been doing before.\nDialogue: 0,0:04:21.19,0:04:23.22,EN,,0,0,0,,You saw that in the system on rule-based control.\nDialogue: 0,0:04:23.22,0:04:24.56,EN,,0,0,0,,It's essentially the same matcher.\nDialogue: 0,0:04:24.95,0:04:27.66,EN,,0,0,0,,In fact, I think the syntax is a little bit simpler\nDialogue: 0,0:04:28.16,0:04:29.31,EN,,0,0,0,,because we're not worrying about\nDialogue: 0,0:04:29.40,0:04:31.40,EN,,0,0,0,,arbitrary constants and expressions and things.\nDialogue: 0,0:04:31.40,0:04:32.88,EN,,0,0,0,,There's just variables and constants.\nDialogue: 0,0:04:35.79,0:04:37.32,EN,,0,0,0,,OK, well, given that,\nDialogue: 0,0:04:38.46,0:04:39.61,EN,,0,0,0,,what's a primitive query?\nDialogue: 0,0:04:42.97,0:04:45.34,EN,,0,0,0,,Primitive query is going to be a rather complicated thing.\nDialogue: 0,0:04:46.67,0:05:03.58,EN,,0,0,0,,It's going to be-- let's think about the query job of x is d dot y.\nDialogue: 0,0:05:07.04,0:05:08.73,EN,,0,0,0,,That's a query we might type in.\nDialogue: 0,0:05:09.40,0:05:11.39,EN,,0,0,0,,That's going to be implemented in the system.\nDialogue: 0,0:05:14.14,0:05:15.66,EN,,0,0,0,,We'll think of it as this little box.\nDialogue: 0,0:05:15.70,0:05:16.80,EN,,0,0,0,,Here's the primitive query.\nDialogue: 0,0:05:18.88,0:05:20.30,EN,,0,0,0,,What this little box is going to do\nDialogue: 0,0:05:22.24,0:05:27.28,EN,,0,0,0,,is take in two streams and put out a stream.\nDialogue: 0,0:05:31.96,0:05:33.20,EN,,0,0,0,,and put out a stream.\nDialogue: 0,0:05:34.03,0:05:36.19,EN,,0,0,0,,So the shape of a primitive query\nDialogue: 0,0:05:36.51,0:05:38.46,EN,,0,0,0,,is that it's a thing where two streams come in\nDialogue: 0,0:05:38.67,0:05:39.96,EN,,0,0,0,,and one stream goes out.\nDialogue: 0,0:05:41.12,0:05:46.20,EN,,0,0,0,,What these streams are going to be is down here is the database.\nDialogue: 0,0:05:51.95,0:05:53.93,EN,,0,0,0,,So we imagine all the things in the database\nDialogue: 0,0:05:55.93,0:05:57.20,EN,,0,0,0,,sort of sitting there in a stream\nDialogue: 0,0:05:57.31,0:05:58.40,EN,,0,0,0,,and this thing sucks on them.\nDialogue: 0,0:06:00.36,0:06:02.43,EN,,0,0,0,,So what are some things that might be in the database?\nDialogue: 0,0:06:08.43,0:06:20.32,EN,,0,0,0,,Oh, job of Alyssa is something\nDialogue: 0,0:06:21.96,0:06:23.71,EN,,0,0,0,,and some other job is something.\nDialogue: 0,0:06:25.77,0:06:30.41,EN,,0,0,0,,So imagine all of the facts in the database sitting there in the stream.\nDialogue: 0,0:06:32.04,0:06:33.10,EN,,0,0,0,,That's what comes in here.\nDialogue: 0,0:06:33.36,0:06:34.52,EN,,0,0,0,,What comes in here\nDialogue: 0,0:06:34.89,0:06:36.52,EN,,0,0,0,,is a stream of dictionaries.\nDialogue: 0,0:06:38.51,0:06:41.40,EN,,0,0,0,,So one particular dictionary might say\nDialogue: 0,0:06:46.70,0:06:49.31,EN,,0,0,0,,might say y equals programmer.\nDialogue: 0,0:06:55.47,0:06:56.64,EN,,0,0,0,,Now, what the query does\nDialogue: 0,0:06:57.07,0:06:59.80,EN,,0,0,0,,when it gets in a dictionary from this stream,\nDialogue: 0,0:07:02.01,0:07:06.67,EN,,0,0,0,,it finds all possible ways of matching the query\nDialogue: 0,0:07:07.45,0:07:10.24,EN,,0,0,0,,against whatever is coming in from the database.\nDialogue: 0,0:07:11.39,0:07:12.89,EN,,0,0,0,,It looks at the query as a pattern,\nDialogue: 0,0:07:13.15,0:07:16.72,EN,,0,0,0,,matches it against any fact from the database\nDialogue: 0,0:07:16.96,0:07:21.98,EN,,0,0,0,,or all possible ways of finding and matching the database\nDialogue: 0,0:07:22.94,0:07:25.68,EN,,0,0,0,,with respect to this dictionary that's coming in.\nDialogue: 0,0:07:27.55,0:07:29.69,EN,,0,0,0,,So for each fact in the database,\nDialogue: 0,0:07:29.72,0:07:34.35,EN,,0,0,0,,it calls the matcher using the pattern, fact, and dictionary.\nDialogue: 0,0:07:35.11,0:07:37.68,EN,,0,0,0,,And every time it gets a good match,\nDialogue: 0,0:07:38.19,0:07:39.93,EN,,0,0,0,,it puts out the extended dictionary.\nDialogue: 0,0:07:40.67,0:07:42.32,EN,,0,0,0,,So, for example, if this one comes in\nDialogue: 0,0:07:43.00,0:07:44.09,EN,,0,0,0,,and it finds a match,\nDialogue: 0,0:07:44.51,0:07:45.87,EN,,0,0,0,,out will come a dictionary\nDialogue: 0,0:07:46.81,0:07:49.79,EN,,0,0,0,,that in this case will have y equals programmer\nDialogue: 0,0:07:51.52,0:07:52.97,EN,,0,0,0,,nd x equals something.\nDialogue: 0,0:07:56.54,0:07:58.75,EN,,0,0,0,,y is programmer, x is something,\nDialogue: 0,0:07:58.96,0:08:00.54,EN,,0,0,0,,and d is whatever it found.\nDialogue: 0,0:08:01.72,0:08:02.27,EN,,0,0,0,,And that's all.\nDialogue: 0,0:08:03.52,0:08:07.82,EN,,0,0,0,,And, of course, it's going to try this for every fact in the dictionary.\nDialogue: 0,0:08:07.98,0:08:09.25,EN,,0,0,0,,So it might find lots of them.\nDialogue: 0,0:08:09.56,0:08:10.59,EN,,0,0,0,,It might find another one\nDialogue: 0,0:08:11.28,0:08:17.12,EN,,0,0,0,,that says y equals programmer and x equals, and d equals.\nDialogue: 0,0:08:19.18,0:08:21.55,EN,,0,0,0,,So thats, So for one frame coming in,\nDialogue: 0,0:08:21.76,0:08:23.69,EN,,0,0,0,,it might put out-- for one dictionary coming in,\nDialogue: 0,0:08:23.72,0:08:25.24,EN,,0,0,0,,it might put out a lot of dictionaries,\nDialogue: 0,0:08:26.54,0:08:28.67,EN,,0,0,0,,or it might put out none.\nDialogue: 0,0:08:30.47,0:08:38.48,EN,,0,0,0,,It might have something that wouldn't match like x equals FOO.\nDialogue: 0,0:08:39.02,0:08:40.89,EN,,0,0,0,,This one might not match anything\nDialogue: 0,0:08:41.52,0:08:45.12,EN,,0,0,0,,in which case nothing will go into this stream corresponding to this frame.\nDialogue: 0,0:08:47.51,0:08:51.28,EN,,0,0,0,,Or what you might do is put in an empty frame,\nDialogue: 0,0:08:52.91,0:08:56.24,EN,,0,0,0,,and an empty frame says try matching all ways--\nDialogue: 0,0:08:59.87,0:09:02.33,EN,,0,0,0,,find all possible ways of matching the query\nDialogue: 0,0:09:02.57,0:09:06.14,EN,,0,0,0,,against something in the database subject to no previous restrictions.\nDialogue: 0,0:09:07.57,0:09:09.16,EN,,0,0,0,,And if you think about what that means, that's just\nDialogue: 0,0:09:10.32,0:09:13.87,EN,,0,0,0,,the computation that's done when you type in a query right off.\nDialogue: 0,0:09:14.20,0:09:15.56,EN,,0,0,0,,It tries to find all matches.\nDialogue: 0,0:09:16.65,0:09:18.83,EN,,0,0,0,,So a primitive query sets up this mechanism.\nDialogue: 0,0:09:19.37,0:09:20.57,EN,,0,0,0,,And what the language does,\nDialogue: 0,0:09:22.75,0:09:24.67,EN,,0,0,0,,when you type in the query at the top level,\nDialogue: 0,0:09:24.84,0:09:26.14,EN,,0,0,0,,it takes this mechanism,\nDialogue: 0,0:09:26.16,0:09:28.35,EN,,0,0,0,,feeds in one single empty dictionary,\nDialogue: 0,0:09:30.86,0:09:32.56,EN,,0,0,0,,and then for each thing that comes out\nDialogue: 0,0:09:33.08,0:09:35.88,EN,,0,0,0,,takes the original query\nDialogue: 0,0:09:36.56,0:09:40.44,EN,,0,0,0,,and instantiates the result with all the different dictionaries,\nDialogue: 0,0:09:40.81,0:09:44.36,EN,,0,0,0,,producing a new stream of instantiated patterns here.\nDialogue: 0,0:09:44.99,0:09:46.51,EN,,0,0,0,,And that's what gets printed on the terminal.\nDialogue: 0,0:09:48.17,0:09:51.24,EN,,0,0,0,,That's the basic mechanism going on there.\nDialogue: 0,0:09:53.51,0:09:55.48,EN,,0,0,0,,Well, why is that so complicated?\nDialogue: 0,0:09:57.71,0:10:01.00,EN,,0,0,0,,You probably can think of a lot simpler ways to arrange this match for\nDialogue: 0,0:10:01.37,0:10:04.25,EN,,0,0,0,,a primitive query rather than having all of these streams floating around.\nDialogue: 0,0:10:05.18,0:10:06.09,EN,,0,0,0,,And the answer is--\nDialogue: 0,0:10:07.15,0:10:08.51,EN,,0,0,0,,you probably guess already.\nDialogue: 0,0:10:10.86,0:10:14.09,EN,,0,0,0,,The answer is this thing extends elegantly\nDialogue: 0,0:10:14.56,0:10:16.76,EN,,0,0,0,,to implement the means of combination.\nDialogue: 0,0:10:17.79,0:10:18.80,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:10:20.65,0:10:22.47,EN,,0,0,0,,suppose I don't only want to do this.\nDialogue: 0,0:10:22.47,0:10:26.96,EN,,0,0,0,,I don't want to say who to be everybody's job description.\nDialogue: 0,0:10:27.23,0:10:28.35,EN,,0,0,0,,Suppose I want to say\nDialogue: 0,0:10:29.47,0:10:35.92,EN,,0,0,0,,to say AND the job of x is d dot y\nDialogue: 0,0:10:36.80,0:10:47.04,EN,,0,0,0,,and the supervisor of x is z.\nDialogue: 0,0:10:48.80,0:10:50.67,EN,,0,0,0,,Now, supervisor of x is z\nDialogue: 0,0:10:51.39,0:10:52.96,EN,,0,0,0,,is going to be another primitive query\nDialogue: 0,0:10:53.71,0:10:58.43,EN,,0,0,0,,that has the same shape to take in a stream of data objects,\nDialogue: 0,0:10:59.18,0:11:01.64,EN,,0,0,0,,a stream of initial dictionaries,\nDialogue: 0,0:11:01.68,0:11:05.52,EN,,0,0,0,,which are the restrictions to try and use when you match,\nDialogue: 0,0:11:05.53,0:11:07.44,EN,,0,0,0,,and it's going to put out a stream of dictionaries.\nDialogue: 0,0:11:08.70,0:11:10.80,EN,,0,0,0,,So that's what this primitive query looks like.\nDialogue: 0,0:11:11.50,0:11:12.91,EN,,0,0,0,,And how do I implement the AND?\nDialogue: 0,0:11:12.91,0:11:13.45,EN,,0,0,0,,Well, it's simple.\nDialogue: 0,0:11:13.45,0:11:14.44,EN,,0,0,0,,I just hook them together.\nDialogue: 0,0:11:14.88,0:11:16.28,EN,,0,0,0,,I take the output of this one,\nDialogue: 0,0:11:16.96,0:11:18.81,EN,,0,0,0,,and I put that to the input of that one.\nDialogue: 0,0:11:19.83,0:11:21.84,EN,,0,0,0,,And I take the dictionary here and I fan it out.\nDialogue: 0,0:11:26.57,0:11:27.96,EN,,0,0,0,,And then you see how that's going to work,\nDialogue: 0,0:11:29.05,0:11:32.44,EN,,0,0,0,,because what's going to happen is a frame will now come in here,\nDialogue: 0,0:11:32.51,0:11:36.84,EN,,0,0,0,,which has a binding for x, y, and d.\nDialogue: 0,0:11:37.92,0:11:39.28,EN,,0,0,0,,And then when this one gets it, it'll say,\nDialogue: 0,0:11:39.29,0:11:41.60,EN,,0,0,0,,oh, gee, subject to these restrictions,\nDialogue: 0,0:11:42.17,0:11:49.24,EN,,0,0,0,,which now already have values in the dictionary for y and x and d,\nDialogue: 0,0:11:51.80,0:11:53.08,EN,,0,0,0,,it looks in the database and says,\nDialogue: 0,0:11:53.12,0:11:54.92,EN,,0,0,0,,gee, can I find any supervisor facts?\nDialogue: 0,0:11:56.04,0:11:58.51,EN,,0,0,0,,And if it finds any, out will come dictionaries\nDialogue: 0,0:11:59.58,0:12:09.34,EN,,0,0,0,,which have bindings for y and x and d and z now.\nDialogue: 0,0:12:12.07,0:12:14.09,EN,,0,0,0,,And then notice that the match---\nDialogue: 0,0:12:14.19,0:12:17.24,EN,,0,0,0,,because the frames coming in here have these restrictions,\nDialogue: 0,0:12:17.61,0:12:20.28,EN,,0,0,0,,that's the thing that assures when you do the AND,\nDialogue: 0,0:12:20.49,0:12:24.62,EN,,0,0,0,,this x will mean the same thing as that x.\nDialogue: 0,0:12:26.47,0:12:28.96,EN,,0,0,0,,Because by the time something comes floating in here,\nDialogue: 0,0:12:29.96,0:12:32.65,EN,,0,0,0,,x has a value that you have to match against consistently.\nDialogue: 0,0:12:34.46,0:12:36.17,EN,,0,0,0,,And then you remember from the code from the matcher,\nDialogue: 0,0:12:36.19,0:12:38.17,EN,,0,0,0,,there was something in the way the matcher did dictionaries\nDialogue: 0,0:12:38.20,0:12:39.82,EN,,0,0,0,,that arrange consistent matches.\nDialogue: 0,0:12:40.92,0:12:41.77,EN,,0,0,0,,So there's AND.\nDialogue: 0,0:12:44.08,0:12:46.94,EN,,0,0,0,,The important point to notice is the general shape.\nDialogue: 0,0:12:48.49,0:12:51.55,EN,,0,0,0,,Look at what happened: the AND of two queries, say, P and Q.\nDialogue: 0,0:12:52.88,0:12:55.61,EN,,0,0,0,,Here's P and Q.\nDialogue: 0,0:12:57.29,0:12:58.60,EN,,0,0,0,,The AND of two queries,\nDialogue: 0,0:13:00.27,0:13:01.19,EN,,0,0,0,,well, it looks like this.\nDialogue: 0,0:13:01.19,0:13:04.44,EN,,0,0,0,,Each query takes in a stream from the database,\nDialogue: 0,0:13:04.54,0:13:05.71,EN,,0,0,0,,a stream of inputs,\nDialogue: 0,0:13:06.33,0:13:08.17,EN,,0,0,0,,and puts out a stream of outputs.\nDialogue: 0,0:13:10.23,0:13:11.72,EN,,0,0,0,,And the important point to notice\nDialogue: 0,0:13:12.20,0:13:15.02,EN,,0,0,0,,is that if I draw a box around this thing\nDialogue: 0,0:13:19.26,0:13:23.64,EN,,0,0,0,,and say this is AND of P and Q,\nDialogue: 0,0:13:25.66,0:13:30.38,EN,,0,0,0,,then that box has exactly the same overall shape.\nDialogue: 0,0:13:32.04,0:13:34.20,EN,,0,0,0,,It's something that takes in a stream from the database.\nDialogue: 0,0:13:34.20,0:13:35.74,EN,,0,0,0,,Here it's going to get fanned out inside,\nDialogue: 0,0:13:36.60,0:13:37.93,EN,,0,0,0,,but from the outside you don't see that.\nDialogue: 0,0:13:38.16,0:13:40.64,EN,,0,0,0,,It takes an input stream and puts out an output stream.\nDialogue: 0,0:13:42.06,0:13:43.16,EN,,0,0,0,,So this is AND.\nDialogue: 0,0:13:43.57,0:13:45.72,EN,,0,0,0,,And then similarly, OR would look like this.\nDialogue: 0,0:13:46.02,0:13:49.58,EN,,0,0,0,,OR would-- although I didn't show you examples of OR.\nDialogue: 0,0:13:49.84,0:13:54.70,EN,,0,0,0,,OR would say can I find all ways of matching P or Q.\nDialogue: 0,0:13:55.80,0:13:58.07,EN,,0,0,0,,So I have P and Q. Each will have their shape.\nDialogue: 0,0:14:04.46,0:14:06.68,EN,,0,0,0,,And the way OR is implemented is\nDialogue: 0,0:14:08.54,0:14:10.91,EN,,0,0,0,,I'll take my database stream.\nDialogue: 0,0:14:12.50,0:14:13.49,EN,,0,0,0,,I'll fan it out.\nDialogue: 0,0:14:13.49,0:14:16.04,EN,,0,0,0,,I'll put one into P and one into Q.\nDialogue: 0,0:14:17.44,0:14:21.98,EN,,0,0,0,,I'll take my initial query stream coming in and fan it out.\nDialogue: 0,0:14:26.75,0:14:29.16,EN,,0,0,0,,So I'll look at all the answers I might get from P\nDialogue: 0,0:14:29.29,0:14:31.08,EN,,0,0,0,,and all the answers I might get from Q,\nDialogue: 0,0:14:31.61,0:14:34.56,EN,,0,0,0,,and I'll put them through some sort of thing that appends them\nDialogue: 0,0:14:34.62,0:14:37.48,EN,,0,0,0,,or merges the result into one stream,\nDialogue: 0,0:14:39.64,0:14:40.88,EN,,0,0,0,,and that's what will come out.\nDialogue: 0,0:14:41.08,0:14:48.24,EN,,0,0,0,,And this whole thing from the outside is OR.\nDialogue: 0,0:14:52.35,0:14:54.89,EN,,0,0,0,,And again, you see it has the same overall shape\nDialogue: 0,0:14:55.07,0:14:56.54,EN,,0,0,0,,And again, you see it has the same overall shape\nDialogue: 0,0:15:01.00,0:15:01.61,EN,,0,0,0,,What's NOT?\nDialogue: 0,0:15:02.02,0:15:03.45,EN,,0,0,0,,NOT works kind of the same way.\nDialogue: 0,0:15:04.31,0:15:05.95,EN,,0,0,0,,If I have some query P,\nDialogue: 0,0:15:06.86,0:15:13.50,EN,,0,0,0,,If I have P, I take the primitive query for P.\nDialogue: 0,0:15:14.69,0:15:16.32,EN,,0,0,0,,Here, I'm going to implement NOT P.\nDialogue: 0,0:15:18.68,0:15:20.54,EN,,0,0,0,,And NOT's just going to act as a filter.\nDialogue: 0,0:15:20.72,0:15:21.95,EN,,0,0,0,,I'll take in the database\nDialogue: 0,0:15:23.84,0:15:28.28,EN,,0,0,0,,and my original stream of dictionaries coming in,\nDialogue: 0,0:15:28.78,0:15:31.53,EN,,0,0,0,,and what NOT P will do is\nDialogue: 0,0:15:31.88,0:15:37.40,EN,,0,0,0,,it will filter these guys.\nDialogue: 0,0:15:39.02,0:15:40.09,EN,,0,0,0,,And the way it will filter it,\nDialogue: 0,0:15:40.19,0:15:42.70,EN,,0,0,0,,it will say when I get in a dictionary here,\nDialogue: 0,0:15:43.42,0:15:44.65,EN,,0,0,0,,I'll find all the matches,\nDialogue: 0,0:15:44.83,0:15:46.48,EN,,0,0,0,,and if I find any, I'll throw it away.\nDialogue: 0,0:15:47.46,0:15:49.93,EN,,0,0,0,,And if I don't find any matches to something coming in here,\nDialogue: 0,0:15:50.12,0:15:51.37,EN,,0,0,0,,I'll just pass that through,\nDialogue: 0,0:15:52.40,0:15:53.55,EN,,0,0,0,,so NOT is a pure filter.\nDialogue: 0,0:15:55.34,0:15:59.98,EN,,0,0,0,,So AND is-- think of these sort of electoral resistors or something.\nDialogue: 0,0:15:59.98,0:16:01.85,EN,,0,0,0,,AND is series combination\nDialogue: 0,0:16:02.49,0:16:04.14,EN,,0,0,0,,and OR is parallel combination.\nDialogue: 0,0:16:04.96,0:16:07.46,EN,,0,0,0,,And then NOT is not going to extend any dictionaries at all.\nDialogue: 0,0:16:07.46,0:16:08.40,EN,,0,0,0,,It's just going to filter it.\nDialogue: 0,0:16:08.75,0:16:11.79,EN,,0,0,0,,It's going to throw away the ones for which it finds a way to match.\nDialogue: 0,0:16:12.64,0:16:14.19,EN,,0,0,0,,And lisp-value is sort of the same way.\nDialogue: 0,0:16:14.84,0:16:16.60,EN,,0,0,0,,The filter's a little more complicated.\nDialogue: 0,0:16:16.60,0:16:17.37,EN,,0,0,0,,It applies to predicate.\nDialogue: 0,0:16:19.93,0:16:21.64,EN,,0,0,0,,The major point to notice here,\nDialogue: 0,0:16:21.92,0:16:23.55,EN,,0,0,0,,and it's a major point we've looked at before,\nDialogue: 0,0:16:23.64,0:16:25.29,EN,,0,0,0,,is this idea of closure.\nDialogue: 0,0:16:28.22,0:16:31.80,EN,,0,0,0,,The things that we build as a means of combination\nDialogue: 0,0:16:31.95,0:16:34.51,EN,,0,0,0,,have the same overall structure\nDialogue: 0,0:16:35.69,0:16:37.58,EN,,0,0,0,,as the primitive things that we're combining.\nDialogue: 0,0:16:39.75,0:16:41.68,EN,,0,0,0,,So the AND of two things\nDialogue: 0,0:16:41.71,0:16:43.72,EN,,0,0,0,,looked at from the outside has the same shape.\nDialogue: 0,0:16:44.63,0:16:46.14,EN,,0,0,0,,And what that means is that\nDialogue: 0,0:16:46.94,0:16:50.28,EN,,0,0,0,,this box here could be an AND or an OR or a NOT or something\nDialogue: 0,0:16:50.30,0:16:54.22,EN,,0,0,0,,because it has the same shape to interface to the larger things.\nDialogue: 0,0:16:54.95,0:16:56.68,EN,,0,0,0,,It's the same thing that allowed us to get\nDialogue: 0,0:16:56.92,0:16:58.96,EN,,0,0,0,,complexity in the Escher picture language\nDialogue: 0,0:16:59.55,0:17:01.31,EN,,0,0,0,,or allows you to immediately build up these\nDialogue: 0,0:17:01.34,0:17:03.26,EN,,0,0,0,,complicated structures just out of pairs.\nDialogue: 0,0:17:03.93,0:17:04.78,EN,,0,0,0,,It's closure.\nDialogue: 0,0:17:06.28,0:17:08.06,EN,,0,0,0,,And that's the thing that\nDialogue: 0,0:17:09.64,0:17:11.72,EN,,0,0,0,,allowed me to do what by now you took for granted\nDialogue: 0,0:17:11.76,0:17:14.91,EN,,0,0,0,,I said, gee, there's a query which is AND of job and salary,\nDialogue: 0,0:17:14.91,0:17:18.80,EN,,0,0,0,,and I said, oh, there's another one, which is AND of job, a NOT of something.\nDialogue: 0,0:17:19.26,0:17:20.92,EN,,0,0,0,,The fact that I can do that is\nDialogue: 0,0:17:20.94,0:17:22.91,EN,,0,0,0,,a direct consequence of this closure principle.\nDialogue: 0,0:17:25.18,0:17:27.08,EN,,0,0,0,,OK, let's break and then we'll go on.\nDialogue: 0,0:17:29.32,0:17:30.89,EN,,0,0,0,,AUDIENCE: Where does the dictionary come from?\nDialogue: 0,0:17:30.99,0:17:36.03,EN,,0,0,0,,PROFESSOR: The dictionary comes initially from what you type in.\nDialogue: 0,0:17:36.09,0:17:37.32,EN,,0,0,0,,So when you start this up,\nDialogue: 0,0:17:39.16,0:17:41.09,EN,,0,0,0,,the first thing it does is set up this whole structure.\nDialogue: 0,0:17:41.09,0:17:42.64,EN,,0,0,0,,It puts in one empty dictionary.\nDialogue: 0,0:17:45.00,0:17:47.24,EN,,0,0,0,,And if all you have is one primitive query,\nDialogue: 0,0:17:48.24,0:17:51.10,EN,,0,0,0,,then what will come out is a bunch of dictionaries with things filled in.\nDialogue: 0,0:17:52.31,0:17:54.33,EN,,0,0,0,,The general situation that I have here\nDialogue: 0,0:17:54.51,0:17:59.71,EN,,0,0,0,,is when this is in the middle of some nest of combined things.\nDialogue: 0,0:18:01.55,0:18:02.30,EN,,0,0,0,,So by the time.\nDialogue: 0,0:18:02.38,0:18:03.79,EN,,0,0,0,,Let's look at the picture over here.\nDialogue: 0,0:18:04.38,0:18:06.73,EN,,0,0,0,,This supervisor query gets in some dictionary.\nDialogue: 0,0:18:06.73,0:18:08.03,EN,,0,0,0,,Where did this one come from?\nDialogue: 0,0:18:08.73,0:18:11.15,EN,,0,0,0,,This dictionary came from the fact that\nDialogue: 0,0:18:12.84,0:18:14.89,EN,,0,0,0,,I'm looking at the output of this primitive query.\nDialogue: 0,0:18:16.26,0:18:17.88,EN,,0,0,0,,So maybe to be very specific,\nDialogue: 0,0:18:18.35,0:18:21.72,EN,,0,0,0,,if I literally typed in just this query at the top level,\nDialogue: 0,0:18:22.27,0:18:22.92,EN,,0,0,0,,this AND,\nDialogue: 0,0:18:23.07,0:18:25.28,EN,,0,0,0,,what would actually happen is it would build this structure\nDialogue: 0,0:18:25.50,0:18:30.24,EN,,0,0,0,,and start up this whole thing with one empty dictionary.\nDialogue: 0,0:18:31.77,0:18:34.33,EN,,0,0,0,,And now this one would process, and a whole bunch of dictionaries\nDialogue: 0,0:18:34.36,0:18:37.36,EN,,0,0,0,,would come out with x, y's and d's in them.\nDialogue: 0,0:18:38.64,0:18:39.58,EN,,0,0,0,,Run it through this one.\nDialogue: 0,0:18:40.19,0:18:42.16,EN,,0,0,0,,So now that's the input to this one.\nDialogue: 0,0:18:42.16,0:18:43.72,EN,,0,0,0,,This one would now put out some other stuff.\nDialogue: 0,0:18:45.04,0:18:48.22,EN,,0,0,0,,And if this itself were buried in some larger thing,\nDialogue: 0,0:18:49.31,0:18:51.00,EN,,0,0,0,,like an OR of something,\nDialogue: 0,0:18:53.42,0:18:55.71,EN,,0,0,0,,then that would go feed into the next one.\nDialogue: 0,0:18:58.56,0:19:01.28,EN,,0,0,0,,So you initially get only one empty dictionary when you start it,\nDialogue: 0,0:19:01.68,0:19:04.08,EN,,0,0,0,,but as you're in the middle of processing these compounds things,\nDialogue: 0,0:19:04.11,0:19:06.65,EN,,0,0,0,,that's where these cascades of dictionaries start getting generated.\nDialogue: 0,0:19:07.66,0:19:12.28,EN,,0,0,0,,AUDIENCE: Dictionaries only come about as a result of using the queries?\nDialogue: 0,0:19:15.12,0:19:17.69,EN,,0,0,0,,Or do they stays, do they become--\nDialogue: 0,0:19:18.84,0:19:22.81,EN,,0,0,0,,do they stay someplace in space like the database does?\nDialogue: 0,0:19:23.68,0:19:24.98,EN,,0,0,0,,Are these temporary items?\nDialogue: 0,0:19:24.98,0:19:27.18,EN,,0,0,0,,PROFESSOR: They're created temporarily in the matcher.\nDialogue: 0,0:19:28.03,0:19:29.88,EN,,0,0,0,,Really, they're someplace in storage.\nDialogue: 0,0:19:29.88,0:19:33.02,EN,,0,0,0,,Initially, someone creates a thing called the empty dictionary\nDialogue: 0,0:19:34.22,0:19:36.80,EN,,0,0,0,,that gets initially fed to this match procedure,\nDialogue: 0,0:19:36.81,0:19:39.05,EN,,0,0,0,,and then the match procedure builds some dictionaries,\nDialogue: 0,0:19:39.07,0:19:40.27,EN,,0,0,0,,and they get passed on and on.\nDialogue: 0,0:19:40.76,0:19:42.48,EN,,0,0,0,,AUDIENCE: OK, so they'll go way after the match?\nDialogue: 0,0:19:43.64,0:19:46.25,EN,,0,0,0,,PROFESSOR: They'll go away when no one needs them again, yeah.\nDialogue: 0,0:19:51.90,0:19:53.60,EN,,0,0,0,,AUDIENCE: It appears that the AND performs\nDialogue: 0,0:19:53.63,0:19:55.37,EN,,0,0,0,,some redundant searches of the database.\nDialogue: 0,0:19:55.96,0:19:57.48,EN,,0,0,0,,If the first clause matched,\nDialogue: 0,0:19:57.50,0:19:59.90,EN,,0,0,0,,let's say, the third element and not on the first two elements,\nDialogue: 0,0:20:00.25,0:20:03.64,EN,,0,0,0,,the second clause is going to look at those first two elements again,\nDialogue: 0,0:20:04.32,0:20:06.59,EN,,0,0,0,,discarding them because they don't match.\nDialogue: 0,0:20:06.64,0:20:08.72,EN,,0,0,0,,The match is already in the dictionary.\nDialogue: 0,0:20:10.00,0:20:12.56,EN,,0,0,0,,Would it makes sense to carry the data element\nDialogue: 0,0:20:12.57,0:20:14.43,EN,,0,0,0,,from the database along with the dictionary?\nDialogue: 0,0:20:15.69,0:20:17.60,EN,,0,0,0,,PROFESSOR: Yeah, there're... Well, in general,\nDialogue: 0,0:20:17.63,0:20:19.48,EN,,0,0,0,,there are other ways to arrange this search,\nDialogue: 0,0:20:20.12,0:20:21.74,EN,,0,0,0,,and there's some analysis that you can do.\nDialogue: 0,0:20:21.74,0:20:23.16,EN,,0,0,0,,I think there's a problem in the book,\nDialogue: 0,0:20:23.87,0:20:26.65,EN,,0,0,0,,which talks about a different way that you can cascade AND\nDialogue: 0,0:20:27.00,0:20:29.20,EN,,0,0,0,,to eliminate various kinds of redundancies.\nDialogue: 0,0:20:29.85,0:20:30.72,EN,,0,0,0,,This one is meant to be--\nDialogue: 0,0:20:31.32,0:20:34.54,EN,,0,0,0,,was mainly meant to be very simple so you can see how they fit together.\nDialogue: 0,0:20:34.70,0:20:35.38,EN,,0,0,0,,But you're quite right.\nDialogue: 0,0:20:35.38,0:20:37.32,EN,,0,0,0,,There are redundancies here that you can get rid of.\nDialogue: 0,0:20:38.37,0:20:40.80,EN,,0,0,0,,That's another reason why this language is somewhat slow.\nDialogue: 0,0:20:41.19,0:20:42.70,EN,,0,0,0,,There are a lot smarter things you can do.\nDialogue: 0,0:20:42.93,0:20:46.22,EN,,0,0,0,,We're just trying to show you a very simple, in principle, implementation.\nDialogue: 0,0:20:51.22,0:20:53.23,EN,,0,0,0,,AUDIENCE: Did you model this language on Prolog,\nDialogue: 0,0:20:53.24,0:20:55.13,EN,,0,0,0,,or did it just come out looking like Prolog?\nDialogue: 0,0:21:04.96,0:21:07.08,EN,,0,0,0,,PROFESSOR: Well, Gerry insulted a whole bunch of people yesterday,\nDialogue: 0,0:21:07.24,0:21:09.92,EN,,0,0,0,,so I might as well say that the MIT attitude towards Prolog is\nDialogue: 0,0:21:10.19,0:21:12.60,EN,,0,0,0,,is something that people did in about 1971\nDialogue: 0,0:21:12.64,0:21:15.60,EN,,0,0,0,,and decided that it wasn't really the right thing and stopped.\nDialogue: 0,0:21:16.12,0:21:22.80,EN,,0,0,0,,So we modeled this on the sort of natural way that this thing was done\nDialogue: 0,0:21:22.84,0:21:24.73,EN,,0,0,0,,in about 1971,\nDialogue: 0,0:21:25.13,0:21:27.24,EN,,0,0,0,,except at that point, we didn't do it with streams.\nDialogue: 0,0:21:28.27,0:21:33.04,EN,,0,0,0,,And then we... After we were using it for about six months,\nDialogue: 0,0:21:33.08,0:21:34.91,EN,,0,0,0,,we discovered that it had all these problems,\nDialogue: 0,0:21:34.94,0:21:36.30,EN,,0,0,0,,some of which I'll talk about later.\nDialogue: 0,0:21:37.33,0:21:38.19,EN,,0,0,0,,And we said,\nDialogue: 0,0:21:38.44,0:21:39.92,EN,,0,0,0,,gee, Prolog must have fixed those,\nDialogue: 0,0:21:39.93,0:21:41.21,EN,,0,0,0,,and then we found out that it didn't.\nDialogue: 0,0:21:41.25,0:21:43.02,EN,,0,0,0,,So this does about the same thing as Prolog.\nDialogue: 0,0:21:43.60,0:21:44.95,EN,,0,0,0,,AUDIENCE: Does Prolog use streams?\nDialogue: 0,0:21:44.95,0:21:46.20,EN,,0,0,0,,PROFESSOR: No. Prolog --\nDialogue: 0,0:21:46.78,0:21:51.04,EN,,0,0,0,,In how it behaves, it behaves a lot like Prolog.\nDialogue: 0,0:21:51.04,0:21:52.96,EN,,0,0,0,,Prolog uses a backtracking strategy.\nDialogue: 0,0:21:53.80,0:21:55.71,EN,,0,0,0,,But the other thing that's really good about Prolog\nDialogue: 0,0:21:55.72,0:21:57.98,EN,,0,0,0,,that makes it a usable thing\nDialogue: 0,0:21:58.28,0:22:01.50,EN,,0,0,0,,is that there's a really very, very\nDialogue: 0,0:22:01.68,0:22:04.09,EN,,0,0,0,,there's a really very, very well-engineered compiler technology\nDialogue: 0,0:22:04.11,0:22:05.32,EN,,0,0,0,,that makes it run fast.\nDialogue: 0,0:22:06.65,0:22:10.81,EN,,0,0,0,,So although you saw the merge spitting out these answers very, very slowly,\nDialogue: 0,0:22:11.66,0:22:13.61,EN,,0,0,0,,a real Prolog will run very, very fast.\nDialogue: 0,0:22:14.70,0:22:16.48,EN,,0,0,0,,Because even though it's sort of doing this,\nDialogue: 0,0:22:16.67,0:22:20.81,EN,,0,0,0,,the real work that went into Prolog is a very, very excellent compiler effort.\nDialogue: 0,0:22:24.30,0:22:25.21,EN,,0,0,0,,Let's take a break.\nDialogue: 0,0:22:25.42,0:22:36.17,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:23:16.65,0:23:18.83,EN,,0,0,0,,We've looked at the primitive queries\nDialogue: 0,0:23:19.21,0:23:23.52,EN,,0,0,0,,and the ways that streams are used to implement the means of combination:\nDialogue: 0,0:23:23.79,0:23:25.72,EN,,0,0,0,,AND and OR and NOT.\nDialogue: 0,0:23:26.95,0:23:28.43,EN,,0,0,0,,Now, let go on to the means of abstraction.\nDialogue: 0,0:23:29.58,0:23:32.80,EN,,0,0,0,,Remember, the means of abstraction in this language are rules.\nDialogue: 0,0:23:35.15,0:23:37.79,EN,,0,0,0,,So z is a boss in division d\nDialogue: 0,0:23:39.18,0:23:43.77,EN,,0,0,0,,if there's some x who has a job in division d\nDialogue: 0,0:23:45.68,0:23:47.47,EN,,0,0,0,,and z is the supervisor of x.\nDialogue: 0,0:23:48.90,0:23:50.60,EN,,0,0,0,,That's what it means for someone to be a boss.\nDialogue: 0,0:23:52.26,0:23:53.15,EN,,0,0,0,,So, and in effect,\nDialogue: 0,0:23:53.34,0:23:55.61,EN,,0,0,0,,if you think about what we're doing with relation to this,\nDialogue: 0,0:23:56.80,0:23:57.90,EN,,0,0,0,,there's the query we wrote--\nDialogue: 0,0:23:57.93,0:24:01.90,EN,,0,0,0,,the job of x is in d and the supervisor of x is z--\nDialogue: 0,0:24:02.19,0:24:04.28,EN,,0,0,0,,what we in effect want to do is take this whole mess\nDialogue: 0,0:24:05.07,0:24:06.57,EN,,0,0,0,,and draw a box around it\nDialogue: 0,0:24:19.08,0:24:24.54,EN,,0,0,0,,and say this whole thing inside the box\nDialogue: 0,0:24:25.15,0:24:32.48,EN,,0,0,0,,is boss of z in division d.\nDialogue: 0,0:24:33.90,0:24:35.25,EN,,0,0,0,,That's in effect what we want to do.\nDialogue: 0,0:24:38.72,0:24:39.72,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:24:43.18,0:24:44.08,EN,,0,0,0,,if we've done that,\nDialogue: 0,0:24:45.00,0:24:47.84,EN,,0,0,0,,and we want to check whether or not it's true\nDialogue: 0,0:24:47.95,0:24:50.51,EN,,0,0,0,,that Ben Bitdiddle is a boss in the computer division,\nDialogue: 0,0:24:51.10,0:25:02.86,EN,,0,0,0,,so if I want to say boss of Ben Bitdiddle in the computer division,\nDialogue: 0,0:25:04.78,0:25:07.08,EN,,0,0,0,,imagine typing that in as query to the system,\nDialogue: 0,0:25:07.12,0:25:09.16,EN,,0,0,0,,in effect what we want to do\nDialogue: 0,0:25:10.67,0:25:12.92,EN,,0,0,0,,is set up a dictionary here,\nDialogue: 0,0:25:15.82,0:25:23.63,EN,,0,0,0,,which has z to Ben Bitdiddle\nDialogue: 0,0:25:28.88,0:25:33.31,EN,,0,0,0,,and d to computer.\nDialogue: 0,0:25:37.08,0:25:38.62,EN,,0,0,0,,Where did that dictionary come from?\nDialogue: 0,0:25:38.68,0:25:40.71,EN,,0,0,0,,Let's look at the slide for one second.\nDialogue: 0,0:25:40.71,0:25:43.71,EN,,0,0,0,,That dictionary came from matching the query\nDialogue: 0,0:25:44.30,0:25:46.33,EN,,0,0,0,,that said boss of Ben Bitdiddle and computer\nDialogue: 0,0:25:46.51,0:25:49.63,EN,,0,0,0,,onto the conclusion of the rule: boss of z and d.\nDialogue: 0,0:25:51.65,0:25:54.11,EN,,0,0,0,,So we match the query to the conclusion of the rule.\nDialogue: 0,0:25:54.19,0:25:55.53,EN,,0,0,0,,That gives us a dictionary,\nDialogue: 0,0:25:58.99,0:26:02.54,EN,,0,0,0,,and that's the thing that we would now like to put into this whole big thing\nDialogue: 0,0:26:02.92,0:26:05.56,EN,,0,0,0,,and process and see if anything comes out the other side.\nDialogue: 0,0:26:06.67,0:26:09.88,EN,,0,0,0,,If anything comes out, it'll be true.\nDialogue: 0,0:26:11.33,0:26:12.37,EN,,0,0,0,,That's the basic idea.\nDialogue: 0,0:26:12.37,0:26:13.24,EN,,0,0,0,,So in general,\nDialogue: 0,0:26:14.03,0:26:15.40,EN,,0,0,0,,the way we implement a rule\nDialogue: 0,0:26:15.85,0:26:18.89,EN,,0,0,0,,is we match the conclusion of the rule\nDialogue: 0,0:26:20.86,0:26:22.96,EN,,0,0,0,,against something we might want to check it's true.\nDialogue: 0,0:26:23.58,0:26:25.12,EN,,0,0,0,,That match gives us a dictionary,\nDialogue: 0,0:26:25.29,0:26:28.22,EN,,0,0,0,,and with respect to that dictionary,\nDialogue: 0,0:26:30.35,0:26:34.51,EN,,0,0,0,,we process the body of the rule.\nDialogue: 0,0:26:36.33,0:26:37.68,EN,,0,0,0,,Well, that's really all there is,\nDialogue: 0,0:26:38.64,0:26:41.44,EN,,0,0,0,,except for two technical points.\nDialogue: 0,0:26:43.04,0:26:44.32,EN,,0,0,0,,The first technical point is that\nDialogue: 0,0:26:45.74,0:26:47.26,EN,,0,0,0,,I might have said something else.\nDialogue: 0,0:26:47.51,0:26:48.41,EN,,0,0,0,,I might have said\nDialogue: 0,0:26:50.54,0:26:52.36,EN,,0,0,0,,who's the boss in the computer division?\nDialogue: 0,0:26:52.54,0:26:56.32,EN,,0,0,0,,So I might say boss of who in computer division.\nDialogue: 0,0:27:00.78,0:27:01.63,EN,,0,0,0,,And if I did that,\nDialogue: 0,0:27:02.57,0:27:04.62,EN,,0,0,0,,what I would really like to do in effect is not\nDialogue: 0,0:27:05.04,0:27:06.49,EN,,0,0,0,,is start up this dictionary\nDialogue: 0,0:27:08.35,0:27:09.88,EN,,0,0,0,,with a match that sort of says,\nDialogue: 0,0:27:09.93,0:27:11.20,EN,,0,0,0,,well, d is computer\nDialogue: 0,0:27:14.35,0:27:18.48,EN,,0,0,0,,and z is whatever who is.\nDialogue: 0,0:27:21.70,0:27:23.22,EN,,0,0,0,,And our matcher won't quite do that.\nDialogue: 0,0:27:23.22,0:27:27.00,EN,,0,0,0,,That's not quite matching a pattern against data.\nDialogue: 0,0:27:28.58,0:27:29.72,EN,,0,0,0,,It's matching two patterns\nDialogue: 0,0:27:29.74,0:27:31.58,EN,,0,0,0,,sort of saying are they consistent or not\nDialogue: 0,0:27:31.90,0:27:33.48,EN,,0,0,0,,or what ways make them consistent.\nDialogue: 0,0:27:33.48,0:27:36.43,EN,,0,0,0,,In other words, what we need is not quite a pattern matcher,\nDialogue: 0,0:27:36.96,0:27:38.91,EN,,0,0,0,,but something a little bit more general\nDialogue: 0,0:27:39.13,0:27:40.11,EN,,0,0,0,,called a unifier.\nDialogue: 0,0:27:44.42,0:27:48.06,EN,,0,0,0,,And a unifier is a slight generalization of a pattern matcher.\nDialogue: 0,0:27:49.53,0:27:52.17,EN,,0,0,0,,What a unifier does is take two patterns\nDialogue: 0,0:27:53.23,0:27:57.53,EN,,0,0,0,,and say what's the most general thing you can substitute\nDialogue: 0,0:27:58.20,0:28:00.01,EN,,0,0,0,,for the variables in those two patterns\nDialogue: 0,0:28:02.68,0:28:05.08,EN,,0,0,0,,to make them satisfy the pattern simultaneously?\nDialogue: 0,0:28:05.68,0:28:06.60,EN,,0,0,0,,Let me give you an example.\nDialogue: 0,0:28:08.86,0:28:14.49,EN,,0,0,0,,If I have the pattern two-element list, which is x and x,\nDialogue: 0,0:28:15.76,0:28:17.15,EN,,0,0,0,,so this is I have a two-element list\nDialogue: 0,0:28:17.32,0:28:18.64,EN,,0,0,0,,where both elements are the same\nDialogue: 0,0:28:18.67,0:28:20.04,EN,,0,0,0,,and otherwise I don't care what they are,\nDialogue: 0,0:28:20.40,0:28:22.83,EN,,0,0,0,,and I unify that against the pattern\nDialogue: 0,0:28:22.92,0:28:24.62,EN,,0,0,0,,that says there's a two-element list,\nDialogue: 0,0:28:24.65,0:28:27.61,EN,,0,0,0,,and the first one is a and something and c\nDialogue: 0,0:28:28.00,0:28:30.14,EN,,0,0,0,,and the second one is a and b and z,\nDialogue: 0,0:28:33.07,0:28:34.88,EN,,0,0,0,,then what the unifier should tell me is,\nDialogue: 0,0:28:34.89,0:28:36.17,EN,,0,0,0,,oh yeah, in that dictionary,\nDialogue: 0,0:28:36.35,0:28:37.96,EN,,0,0,0,,x has to be a, b, c,\nDialogue: 0,0:28:39.34,0:28:41.92,EN,,0,0,0,,and y has to be d and z has to be c.\nDialogue: 0,0:28:43.44,0:28:46.28,EN,,0,0,0,,Those are the restrictions I'd have to put on the values of x, y, and z\nDialogue: 0,0:28:46.33,0:28:47.58,EN,,0,0,0,,to make these two unify,\nDialogue: 0,0:28:48.12,0:28:50.84,EN,,0,0,0,,or in other words, to make this match x\nDialogue: 0,0:28:51.15,0:28:53.37,EN,,0,0,0,,and make this match x.\nDialogue: 0,0:28:55.28,0:28:57.76,EN,,0,0,0,,The unifier should be able to deduce that.\nDialogue: 0,0:28:58.54,0:29:01.08,EN,,0,0,0,,But the unifier may-- there are more complicated things.\nDialogue: 0,0:29:01.08,0:29:03.07,EN,,0,0,0,,I might have said something a little bit more complicated.\nDialogue: 0,0:29:03.48,0:29:05.74,EN,,0,0,0,,I might have said there's a list with two elements,\nDialogue: 0,0:29:07.00,0:29:08.28,EN,,0,0,0,,and they're both the same,\nDialogue: 0,0:29:08.86,0:29:11.15,EN,,0,0,0,,and they should unify against something of this form.\nDialogue: 0,0:29:12.65,0:29:15.36,EN,,0,0,0,,And the unifier should be able to deduce from that.\nDialogue: 0,0:29:16.89,0:29:19.57,EN,,0,0,0,,Like that y would have to be b. y would have to be b.\nDialogue: 0,0:29:19.57,0:29:22.12,EN,,0,0,0,,Because these two are the same,\nDialogue: 0,0:29:22.22,0:29:23.52,EN,,0,0,0,,so y's got to be b.\nDialogue: 0,0:29:24.34,0:29:27.53,EN,,0,0,0,,And v here would have to be a.\nDialogue: 0,0:29:28.94,0:29:30.99,EN,,0,0,0,,And z and w can be anything,\nDialogue: 0,0:29:31.00,0:29:32.43,EN,,0,0,0,,but they have to be the same thing.\nDialogue: 0,0:29:35.71,0:29:41.76,EN,,0,0,0,,And x would have to be b, followed by a, followed by whatever w\nDialogue: 0,0:29:42.83,0:29:44.68,EN,,0,0,0,,or whatever z is, which is the same.\nDialogue: 0,0:29:44.70,0:29:49.42,EN,,0,0,0,,So you see, the unifier somehow has to deduce things to unify these patterns.\nDialogue: 0,0:29:50.88,0:29:53.52,EN,,0,0,0,,So you might think there's some kind of magic deduction going on,\nDialogue: 0,0:29:54.27,0:29:55.23,EN,,0,0,0,,but there's not.\nDialogue: 0,0:29:55.85,0:29:59.88,EN,,0,0,0,,A unifier is basically a very simple modification of a pattern matcher.\nDialogue: 0,0:30:00.15,0:30:01.85,EN,,0,0,0,,And if you look in the book, you'll see something like\nDialogue: 0,0:30:02.25,0:30:06.16,EN,,0,0,0,,like three or four lines of code added to the pattern matcher you just saw\nDialogue: 0,0:30:06.49,0:30:08.17,EN,,0,0,0,,to handle the symmetric case.\nDialogue: 0,0:30:08.28,0:30:10.81,EN,,0,0,0,,Remember, the pattern matcher has a place where it says\nDialogue: 0,0:30:11.66,0:30:14.28,EN,,0,0,0,,is this variable matching a constant.\nDialogue: 0,0:30:14.98,0:30:16.42,EN,,0,0,0,,And if so, it checks in the dictionary.\nDialogue: 0,0:30:16.42,0:30:18.25,EN,,0,0,0,,There's only one other clause in the unifier,\nDialogue: 0,0:30:18.49,0:30:20.75,EN,,0,0,0,,which says is this variable matching a variable,\nDialogue: 0,0:30:22.00,0:30:23.42,EN,,0,0,0,,in which case you go look in the dictionary\nDialogue: 0,0:30:23.45,0:30:25.68,EN,,0,0,0,,and see if that's consistent with what's in the dictionary.\nDialogue: 0,0:30:27.03,0:30:31.13,EN,,0,0,0,,So all the, quote, deduction that's in this language,\nDialogue: 0,0:30:31.28,0:30:34.59,EN,,0,0,0,,if you sort of look at it, sort of sits in the rule applications,\nDialogue: 0,0:30:34.99,0:30:37.88,EN,,0,0,0,,which, if you look at that, sits in the unifier,\nDialogue: 0,0:30:38.36,0:30:40.32,EN,,0,0,0,,which, if you look at that under a microscope,\nDialogue: 0,0:30:40.56,0:30:43.96,EN,,0,0,0,,sits essentially in the pattern matcher.\nDialogue: 0,0:30:44.94,0:30:47.07,EN,,0,0,0,,There's no magic at all going on in there.\nDialogue: 0,0:30:47.41,0:30:50.25,EN,,0,0,0,,And the, quote, deduction that you see\nDialogue: 0,0:30:50.94,0:30:52.89,EN,,0,0,0,,is just the fact that there's this recursion,\nDialogue: 0,0:30:52.92,0:30:55.69,EN,,0,0,0,,which is unwinding the matches bit by bit.\nDialogue: 0,0:30:56.03,0:30:58.03,EN,,0,0,0,,So it looks like this thing is being very clever,\nDialogue: 0,0:30:58.44,0:31:00.36,EN,,0,0,0,,but in fact, it's not being very clever at all.\nDialogue: 0,0:31:02.14,0:31:04.41,EN,,0,0,0,,There are cases where a unifier might have to be clever.\nDialogue: 0,0:31:04.88,0:31:05.87,EN,,0,0,0,,Let me show you one more.\nDialogue: 0,0:31:11.07,0:31:13.36,EN,,0,0,0,,Suppose I want to unify a list of two elements,\nDialogue: 0,0:31:13.48,0:31:14.81,EN,,0,0,0,,x and x,\nDialogue: 0,0:31:17.24,0:31:22.14,EN,,0,0,0,,with a thing that says it's y followed by a dot y.\nDialogue: 0,0:31:24.37,0:31:26.12,EN,,0,0,0,,Now, if you think of what that would have to mean,\nDialogue: 0,0:31:26.86,0:31:29.71,EN,,0,0,0,,it would have to mean that x had better be the same as y,\nDialogue: 0,0:31:30.92,0:31:31.66,EN,,0,0,0,,but also\nDialogue: 0,0:31:31.82,0:31:36.16,EN,,0,0,0,,x had better be the same as a list whose first element is a and whose rest is y.\nDialogue: 0,0:31:37.33,0:31:39.45,EN,,0,0,0,,And if you think about what that would have to mean,\nDialogue: 0,0:31:42.27,0:31:44.71,EN,,0,0,0,,it would have to mean that y is the infinite list of a's.\nDialogue: 0,0:31:47.50,0:31:48.35,EN,,0,0,0,,In some sense,\nDialogue: 0,0:31:49.21,0:31:52.40,EN,,0,0,0,,in order to do that unification,\nDialogue: 0,0:31:52.60,0:31:54.84,EN,,0,0,0,,I have to solve the fixed-point equation\nDialogue: 0,0:31:55.05,0:32:01.84,EN,,0,0,0,,cons of a to y is equal to y.\nDialogue: 0,0:32:04.57,0:32:06.96,EN,,0,0,0,,And in general, I wrote a very simple one.\nDialogue: 0,0:32:07.29,0:32:08.67,EN,,0,0,0,,Really doing unification\nDialogue: 0,0:32:08.97,0:32:11.98,EN,,0,0,0,,might have to solve an arbitrary fixed-point equation:\nDialogue: 0,0:32:12.01,0:32:13.42,EN,,0,0,0,,f of y equals y.\nDialogue: 0,0:32:15.53,0:32:17.08,EN,,0,0,0,,And basically, you can't do that\nDialogue: 0,0:32:17.10,0:32:19.47,EN,,0,0,0,,and make the thing finite all the time.\nDialogue: 0,0:32:20.57,0:32:23.60,EN,,0,0,0,,So how does the logic language handle that?\nDialogue: 0,0:32:24.89,0:32:26.48,EN,,0,0,0,,The answer is it doesn't.\nDialogue: 0,0:32:27.16,0:32:28.04,EN,,0,0,0,,It just punts.\nDialogue: 0,0:32:28.73,0:32:31.07,EN,,0,0,0,,And there's a little check in the unifier,\nDialogue: 0,0:32:31.31,0:32:33.82,EN,,0,0,0,,which says, oh, is this one of the hard cases\nDialogue: 0,0:32:34.44,0:32:38.00,EN,,0,0,0,,which when I go to match things would involve solving a fixed-point equation?\nDialogue: 0,0:32:38.65,0:32:40.81,EN,,0,0,0,,And in this case, I will throw up my hands.\nDialogue: 0,0:32:42.84,0:32:44.65,EN,,0,0,0,,And if that check were not in there,\nDialogue: 0,0:32:45.00,0:32:45.88,EN,,0,0,0,,what would happen?\nDialogue: 0,0:32:47.99,0:32:49.10,EN,,0,0,0,,In most cases is\nDialogue: 0,0:32:49.13,0:32:51.31,EN,,0,0,0,,that the unifier would just go into an infinite loop.\nDialogue: 0,0:32:53.74,0:32:56.54,EN,,0,0,0,,And other logic programming languages work like that.\nDialogue: 0,0:32:56.80,0:32:58.14,EN,,0,0,0,,So there's really no magic.\nDialogue: 0,0:32:58.22,0:32:59.93,EN,,0,0,0,,The easy case is done in a matcher.\nDialogue: 0,0:33:00.10,0:33:01.58,EN,,0,0,0,,The hard case is not done at all.\nDialogue: 0,0:33:02.96,0:33:05.47,EN,,0,0,0,,And that's about the state of this technology.\nDialogue: 0,0:33:11.88,0:33:14.24,EN,,0,0,0,,OK, Let me just say again formally\nDialogue: 0,0:33:14.27,0:33:16.38,EN,,0,0,0,,how rules work now that I talked about unifiers.\nDialogue: 0,0:33:17.39,0:33:18.75,EN,,0,0,0,,So the official definition\nDialogue: 0,0:33:19.20,0:33:20.96,EN,,0,0,0,,is that to apply a rule,\nDialogue: 0,0:33:24.17,0:33:27.13,EN,,0,0,0,,we-- well, let's start using some words we've used before.\nDialogue: 0,0:33:28.27,0:33:32.01,EN,,0,0,0,,Let's talk about sticking dictionaries into\nDialogue: 0,0:33:32.88,0:33:34.78,EN,,0,0,0,,these big boxes of query things\nDialogue: 0,0:33:34.81,0:33:38.54,EN,,0,0,0,,as evaluating these large queries\nDialogue: 0,0:33:39.95,0:33:43.85,EN,,0,0,0,,relative to an environment or a frame.\nDialogue: 0,0:33:43.85,0:33:45.04,EN,,0,0,0,,So when you think of that dictionary,\nDialogue: 0,0:33:45.07,0:33:46.28,EN,,0,0,0,,what's the dictionary after all?\nDialogue: 0,0:33:46.72,0:33:48.18,EN,,0,0,0,,It's a bunch of meanings for symbols.\nDialogue: 0,0:33:48.18,0:33:50.22,EN,,0,0,0,,That's what we've been calling frames or environments.\nDialogue: 0,0:33:51.80,0:33:55.97,EN,,0,0,0,,What does it mean to do some processing relevant to an environment?\nDialogue: 0,0:33:55.97,0:33:57.42,EN,,0,0,0,,That's what we've been calling evaluation.\nDialogue: 0,0:33:58.33,0:34:01.56,EN,,0,0,0,,So we can say the way that you apply a rule\nDialogue: 0,0:34:01.92,0:34:06.16,EN,,0,0,0,,is to evaluate the rule body relative to an environment\nDialogue: 0,0:34:06.67,0:34:11.58,EN,,0,0,0,,that's formed by unifying the rule conclusion with the given query.\nDialogue: 0,0:34:13.23,0:34:14.51,EN,,0,0,0,,And the thing I want you to notice\nDialogue: 0,0:34:14.80,0:34:17.08,EN,,0,0,0,,is the complete formal similarity\nDialogue: 0,0:34:18.16,0:34:21.50,EN,,0,0,0,,to the net of circular evaluator or the substitution model.\nDialogue: 0,0:34:21.63,0:34:22.73,EN,,0,0,0,,To apply a procedure,\nDialogue: 0,0:34:22.86,0:34:28.36,EN,,0,0,0,,we evaluate the procedure body relative to an environment\nDialogue: 0,0:34:28.54,0:34:33.13,EN,,0,0,0,,that's formed by blinding the procedure parameters to the arguments.\nDialogue: 0,0:34:34.56,0:34:36.41,EN,,0,0,0,,There's a complete formal similarity there\nDialogue: 0,0:34:36.44,0:34:40.41,EN,,0,0,0,,between the rules, rule application, and procedure application\nDialogue: 0,0:34:40.57,0:34:42.30,EN,,0,0,0,,even though these things are very, very different.\nDialogue: 0,0:34:43.65,0:34:45.61,EN,,0,0,0,,And again, you have the EVAL APPLY loop.\nDialogue: 0,0:34:47.29,0:34:49.52,EN,,0,0,0,,EVAL and APPLY.\nDialogue: 0,0:34:53.39,0:34:57.39,EN,,0,0,0,,So in general, I might be processing some combined expression\nDialogue: 0,0:34:57.42,0:34:59.13,EN,,0,0,0,,that will turn into a rule application,\nDialogue: 0,0:35:00.70,0:35:03.28,EN,,0,0,0,,which will generate some dictionaries or frames or environments--\nDialogue: 0,0:35:03.31,0:35:04.72,EN,,0,0,0,,whatever you want to call them-- from match,\nDialogue: 0,0:35:05.02,0:35:08.43,EN,,0,0,0,,which will then be the input to some big compound thing like this.\nDialogue: 0,0:35:08.66,0:35:11.77,EN,,0,0,0,,This has pieces of it and may have other rule applications.\nDialogue: 0,0:35:13.58,0:35:15.68,EN,,0,0,0,,And you have essentially the same cycle\nDialogue: 0,0:35:15.72,0:35:18.68,EN,,0,0,0,,even though there's nothing here at all that looks like procedures.\nDialogue: 0,0:35:19.68,0:35:21.87,EN,,0,0,0,,It really has to do with the fact you've built a language\nDialogue: 0,0:35:22.08,0:35:25.49,EN,,0,0,0,,whose means of combination and abstraction unwind in certain ways.\nDialogue: 0,0:35:28.77,0:35:29.52,EN,,0,0,0,,And then in general,\nDialogue: 0,0:35:29.77,0:35:31.39,EN,,0,0,0,,what happens at the very top level,\nDialogue: 0,0:35:33.79,0:35:35.96,EN,,0,0,0,,you might have rules in your database also,\nDialogue: 0,0:35:36.65,0:35:38.70,EN,,0,0,0,,so things in this database might be rules.\nDialogue: 0,0:35:40.46,0:35:42.06,EN,,0,0,0,,There are ways to check that things are true.\nDialogue: 0,0:35:42.92,0:35:44.89,EN,,0,0,0,,So it might come in here and have to do a rule check.\nDialogue: 0,0:35:46.75,0:35:48.16,EN,,0,0,0,,And then there's some control structure\nDialogue: 0,0:35:48.19,0:35:50.48,EN,,0,0,0,,which says, well, you look at some rules, and you look at some data elements,\nDialogue: 0,0:35:50.51,0:35:51.80,EN,,0,0,0,,and you look at some rules and data elements,\nDialogue: 0,0:35:51.84,0:35:53.12,EN,,0,0,0,,and these fan out and out and out.\nDialogue: 0,0:35:53.35,0:35:55.48,EN,,0,0,0,,So it becomes essentially impossible\nDialogue: 0,0:35:55.68,0:35:57.69,EN,,0,0,0,,to say what order it's looking at these things in,\nDialogue: 0,0:35:58.20,0:36:00.27,EN,,0,0,0,,whether it's breadth first or depth first or anything.\nDialogue: 0,0:36:00.28,0:36:01.64,EN,,0,0,0,,And it's even more impossible\nDialogue: 0,0:36:01.66,0:36:05.58,EN,,0,0,0,,because the actual order is somehow buried in the delays of the streams.\nDialogue: 0,0:36:07.69,0:36:11.16,EN,,0,0,0,,So what's very hard to tell from this is the order in which it's scanned.\nDialogue: 0,0:36:11.27,0:36:12.16,EN,,0,0,0,,But what's true is,\nDialogue: 0,0:36:12.19,0:36:13.64,EN,,0,0,0,,because you're looking at the stream view,\nDialogue: 0,0:36:13.90,0:36:15.82,EN,,0,0,0,,is that all of them eventually get looked at.\nDialogue: 0,0:36:24.98,0:36:28.15,EN,,0,0,0,,Let me just mention one tiny technical problem.\nDialogue: 0,0:36:30.88,0:36:33.55,EN,,0,0,0,,Um Suppose I tried over here.\nDialogue: 0,0:36:37.53,0:36:41.00,EN,,0,0,0,,Suppose I tried saying boss of y is computer,\nDialogue: 0,0:36:44.22,0:36:45.78,EN,,0,0,0,,then a funny thing would happen.\nDialogue: 0,0:36:45.78,0:36:50.25,EN,,0,0,0,,As I stuck a dictionary with y in here,\nDialogue: 0,0:36:52.73,0:36:57.37,EN,,0,0,0,,I might get-- this y is not the same as that y,\nDialogue: 0,0:36:57.42,0:37:00.62,EN,,0,0,0,,which was the other piece of somebody's job description.\nDialogue: 0,0:37:01.58,0:37:03.80,EN,,0,0,0,,So if I really only did literally what I said,\nDialogue: 0,0:37:04.22,0:37:06.44,EN,,0,0,0,,we'd get some variable conflict problems.\nDialogue: 0,0:37:09.28,0:37:10.48,EN,,0,0,0,,So I lied to you a little bit.\nDialogue: 0,0:37:10.93,0:37:13.84,EN,,0,0,0,,Notice that problem is exactly a problem we've run into before.\nDialogue: 0,0:37:14.27,0:37:15.56,EN,,0,0,0,,It is precisely\nDialogue: 0,0:37:15.96,0:37:18.36,EN,,0,0,0,,the need for local variables in a language.\nDialogue: 0,0:37:19.24,0:37:21.74,EN,,0,0,0,,When I square, when I have the sum of squares,\nDialogue: 0,0:37:21.79,0:37:23.39,EN,,0,0,0,,that x had better not be that x.\nDialogue: 0,0:37:24.96,0:37:26.32,EN,,0,0,0,,That's exactly the same as\nDialogue: 0,0:37:27.39,0:37:29.77,EN,,0,0,0,,as this y had better not be that y.\nDialogue: 0,0:37:31.80,0:37:32.75,EN,,0,0,0,,And we know how to solve that.\nDialogue: 0,0:37:32.78,0:37:34.49,EN,,0,0,0,,We built -- That was this whole environment model,\nDialogue: 0,0:37:34.51,0:37:37.04,EN,,0,0,0,,and we built chains of frames and all sorts of things like that.\nDialogue: 0,0:37:37.71,0:37:39.10,EN,,0,0,0,,There's a much more brutal way to solve it.\nDialogue: 0,0:37:39.10,0:37:41.73,EN,,0,0,0,,In the query language, we didn't even do that.\nDialogue: 0,0:37:41.73,0:37:43.18,EN,,0,0,0,,We did something completely brutal.\nDialogue: 0,0:37:43.54,0:37:45.93,EN,,0,0,0,,We said every time you apply a rule,\nDialogue: 0,0:37:47.26,0:37:49.63,EN,,0,0,0,,rename consistently all the variables in the rule\nDialogue: 0,0:37:49.77,0:37:53.50,EN,,0,0,0,,to some new unique names that won't conflict with anything.\nDialogue: 0,0:37:54.04,0:37:57.10,EN,,0,0,0,,If you looked at the -- That's conceptually simpler,\nDialogue: 0,0:37:57.12,0:37:59.24,EN,,0,0,0,,but really brutal and not particularly efficient.\nDialogue: 0,0:37:59.97,0:38:01.15,EN,,0,0,0,,But notice,\nDialogue: 0,0:38:01.39,0:38:04.68,EN,,0,0,0,,we could have gotten rid of all of our environment structures\nDialogue: 0,0:38:05.50,0:38:08.72,EN,,0,0,0,,if we defined for procedures in Lisp the same thing.\nDialogue: 0,0:38:08.75,0:38:11.56,EN,,0,0,0,,If every time we applied a procedure and did the substitution model\nDialogue: 0,0:38:11.87,0:38:13.90,EN,,0,0,0,,we renamed all the variables in the procedure,\nDialogue: 0,0:38:14.19,0:38:16.28,EN,,0,0,0,,then we never would have had to worry about local variables\nDialogue: 0,0:38:16.33,0:38:17.39,EN,,0,0,0,,because they would never arise.\nDialogue: 0,0:38:19.04,0:38:20.41,EN,,0,0,0,,OK, well, that would be inefficient,\nDialogue: 0,0:38:20.91,0:38:23.04,EN,,0,0,0,,and it's inefficient here in the query language, too,\nDialogue: 0,0:38:23.29,0:38:24.59,EN,,0,0,0,,but we did it to keep it simple.\nDialogue: 0,0:38:25.61,0:38:26.67,EN,,0,0,0,,Let's break for questions.\nDialogue: 0,0:38:30.88,0:38:33.39,EN,,0,0,0,,AUDIENCE: When you started this section,\nDialogue: 0,0:38:33.40,0:38:39.60,EN,,0,0,0,,you emphasized how powerful our APPLY EVAL model was\nDialogue: 0,0:38:39.63,0:38:41.17,EN,,0,0,0,,that we could use it for any language.\nDialogue: 0,0:38:41.17,0:38:43.39,EN,,0,0,0,,And then you say we're going to have this language which is so different.\nDialogue: 0,0:38:43.95,0:38:45.13,EN,,0,0,0,,It turns out that this language,\nDialogue: 0,0:38:45.58,0:38:47.88,EN,,0,0,0,,as you just pointed out, is very much the same.\nDialogue: 0,0:38:47.88,0:38:49.85,EN,,0,0,0,,I'm wondering if you're arguing that all languages end up\nDialogue: 0,0:38:50.48,0:38:54.57,EN,,0,0,0,,coming down to this you can apply a rule or apply a procedure\nDialogue: 0,0:38:55.12,0:38:55.98,EN,,0,0,0,,or some kind of apply?\nDialogue: 0,0:38:57.07,0:38:58.88,EN,,0,0,0,,PROFESSOR: I would say that pretty much any language\nDialogue: 0,0:38:58.92,0:39:00.30,EN,,0,0,0,,where you really are building up\nDialogue: 0,0:39:00.92,0:39:04.40,EN,,0,0,0,,these means of combination and giving them simpler names\nDialogue: 0,0:39:04.70,0:39:06.86,EN,,0,0,0,,and you're saying anything of the sort, like\nDialogue: 0,0:39:07.79,0:39:09.90,EN,,0,0,0,,here's a general kind of expression,\nDialogue: 0,0:39:09.98,0:39:11.40,EN,,0,0,0,,like how to square something,\nDialogue: 0,0:39:12.03,0:39:14.20,EN,,0,0,0,,almost anything that you would call a procedure.\nDialogue: 0,0:39:14.88,0:39:15.88,EN,,0,0,0,,If that's got to have parts,\nDialogue: 0,0:39:15.90,0:39:17.24,EN,,0,0,0,,you have to unwind those parts.\nDialogue: 0,0:39:18.02,0:39:20.19,EN,,0,0,0,,You have to have some kind of organization which says\nDialogue: 0,0:39:20.57,0:39:24.03,EN,,0,0,0,,when I look at the abstract variables or tags\nDialogue: 0,0:39:24.06,0:39:27.10,EN,,0,0,0,,or whatever you want to call them that might stand for particular things,\nDialogue: 0,0:39:28.33,0:39:29.34,EN,,0,0,0,,you have to keep track of that,\nDialogue: 0,0:39:29.39,0:39:30.91,EN,,0,0,0,,and that's going to be something like an environment.\nDialogue: 0,0:39:31.72,0:39:32.54,EN,,0,0,0,,And then if you say\nDialogue: 0,0:39:32.70,0:39:35.26,EN,,0,0,0,,this part can have parts which I have to unwind,\nDialogue: 0,0:39:35.80,0:39:37.44,EN,,0,0,0,,you've got to have something like this cycle.\nDialogue: 0,0:39:39.97,0:39:43.20,EN,,0,0,0,,And lots and lots of languages have that character\nDialogue: 0,0:39:43.36,0:39:45.40,EN,,0,0,0,,as long ... when they sort of get put together in this way.\nDialogue: 0,0:39:45.59,0:39:47.20,EN,,0,0,0,,This language again really is different\nDialogue: 0,0:39:47.21,0:39:49.50,EN,,0,0,0,,because there's nothing like procedures on the outside.\nDialogue: 0,0:39:50.69,0:39:52.68,EN,,0,0,0,,When you go below the surface and you see the implementation,\nDialogue: 0,0:39:52.70,0:39:54.24,EN,,0,0,0,,of course, it starts looking the same.\nDialogue: 0,0:39:54.87,0:39:56.95,EN,,0,0,0,,But from the outside, it's a very different world view.\nDialogue: 0,0:39:56.95,0:39:58.54,EN,,0,0,0,,You're not computing functions of inputs.\nDialogue: 0,0:40:03.97,0:40:05.71,EN,,0,0,0,,AUDIENCE: You mentioned earlier that\nDialogue: 0,0:40:06.60,0:40:09.55,EN,,0,0,0,,when you build all of these rules in pattern matcher\nDialogue: 0,0:40:10.01,0:40:11.42,EN,,0,0,0,,and with the delayed action of streams,\nDialogue: 0,0:40:11.45,0:40:12.72,EN,,0,0,0,,you really have no way to know\nDialogue: 0,0:40:13.37,0:40:15.36,EN,,0,0,0,,in what order things are evaluated.\nDialogue: 0,0:40:15.58,0:40:15.94,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:40:15.94,0:40:18.28,EN,,0,0,0,,AUDIENCE: And that would indicate then that\nDialogue: 0,0:40:18.94,0:40:22.28,EN,,0,0,0,,you should only express declarative knowledge that's true for all-time,\nDialogue: 0,0:40:22.30,0:40:23.79,EN,,0,0,0,,no-time sequence built into it.\nDialogue: 0,0:40:23.95,0:40:25.47,EN,,0,0,0,,Otherwise, these things get all--\nDialogue: 0,0:40:27.39,0:40:28.76,EN,,0,0,0,,PROFESSOR: Yes. Yes.\nDialogue: 0,0:40:28.82,0:40:29.48,EN,,0,0,0,,The question is\nDialogue: 0,0:40:30.06,0:40:32.60,EN,,0,0,0,,this really is set up for doing declarative knowledge,\nDialogue: 0,0:40:33.26,0:40:34.81,EN,,0,0,0,,and as I presented it-- no\nDialogue: 0,0:40:35.71,0:40:39.56,EN,,0,0,0,,and I'll show you some of the ugly warts under this after the break.\nDialogue: 0,0:40:40.83,0:40:42.60,EN,,0,0,0,,As I presented it, it's just doing logic.\nDialogue: 0,0:40:43.07,0:40:44.52,EN,,0,0,0,,And in principle, if it were logic,\nDialogue: 0,0:40:44.54,0:40:46.81,EN,,0,0,0,,it wouldn't matter what order it's getting done.\nDialogue: 0,0:40:48.84,0:40:51.55,EN,,0,0,0,,And it's quite true\nDialogue: 0,0:40:51.60,0:40:53.61,EN,,0,0,0,,when you start doing things where you have side effects\nDialogue: 0,0:40:53.68,0:40:55.20,EN,,0,0,0,,like adding things to the database\nDialogue: 0,0:40:55.23,0:40:58.16,EN,,0,0,0,,and taking things out, and we'll see some others,\nDialogue: 0,0:40:58.75,0:41:00.83,EN,,0,0,0,,you loose that kind of control.\nDialogue: 0,0:41:01.29,0:41:02.94,EN,,0,0,0,,So, for example, contrasting with Prolog.\nDialogue: 0,0:41:02.94,0:41:05.15,EN,,0,0,0,,Say Prolog has various features\nDialogue: 0,0:41:05.16,0:41:07.79,EN,,0,0,0,,where you really exploit the order of evaluation.\nDialogue: 0,0:41:09.64,0:41:11.77,EN,,0,0,0,,And people write Prolog programs that way.\nDialogue: 0,0:41:11.77,0:41:14.04,EN,,0,0,0,,That turns out to be very complicated in Prolog,\nDialogue: 0,0:41:14.32,0:41:17.55,EN,,0,0,0,,although if you're an expert Prolog programmer, you can do it.\nDialogue: 0,0:41:18.59,0:41:20.21,EN,,0,0,0,,However, here I don't think you can do it at all.\nDialogue: 0,0:41:20.21,0:41:21.24,EN,,0,0,0,,It's very complicated\nDialogue: 0,0:41:21.72,0:41:23.64,EN,,0,0,0,,because you really are giving up control over\nDialogue: 0,0:41:23.77,0:41:25.72,EN,,0,0,0,,any prearranged order of trying things.\nDialogue: 0,0:41:27.15,0:41:30.16,EN,,0,0,0,,AUDIENCE: Now, that would indicate then that you have a functional mapping.\nDialogue: 0,0:41:30.67,0:41:32.51,EN,,0,0,0,,And when you started out this lecture,\nDialogue: 0,0:41:32.99,0:41:34.08,EN,,0,0,0,,you said that\nDialogue: 0,0:41:34.67,0:41:36.70,EN,,0,0,0,,we express the declarative knowledge which is a relation,\nDialogue: 0,0:41:37.15,0:41:38.81,EN,,0,0,0,,and we don't talk about the inputs and the outputs.\nDialogue: 0,0:41:41.21,0:41:43.37,EN,,0,0,0,,PROFESSOR: Well, there's a pun on functional, right?\nDialogue: 0,0:41:43.37,0:41:45.79,EN,,0,0,0,,There's functional in the sense of no side effects\nDialogue: 0,0:41:46.20,0:41:48.16,EN,,0,0,0,,and not depending on what order is going on.\nDialogue: 0,0:41:48.70,0:41:51.04,EN,,0,0,0,,And then there's functional in the sense of mathematical function,\nDialogue: 0,0:41:51.07,0:41:52.22,EN,,0,0,0,,which means input and output.\nDialogue: 0,0:41:52.59,0:41:54.36,EN,,0,0,0,,And it's just that pun that you're making, I think.\nDialogue: 0,0:41:56.51,0:41:58.51,EN,,0,0,0,,AUDIENCE: I'm a little unclear on what you're doing with\nDialogue: 0,0:41:58.81,0:42:00.70,EN,,0,0,0,,two statements, the two boss statements.\nDialogue: 0,0:42:01.27,0:42:05.74,EN,,0,0,0,,Is the first one building up the database\nDialogue: 0,0:42:05.76,0:42:08.08,EN,,0,0,0,,and the second one a query or--\nDialogue: 0,0:42:09.07,0:42:10.12,EN,,0,0,0,,PROFESSOR: OK, I'm sorry.\nDialogue: 0,0:42:12.44,0:42:15.16,EN,,0,0,0,,What I meant here, if I type something like this in as a query--\nDialogue: 0,0:42:16.12,0:42:18.44,EN,,0,0,0,,I should have given an example way at the very beginning.\nDialogue: 0,0:42:19.47,0:42:23.52,EN,,0,0,0,,If I type in job, Ben Bitdiddle, computer wizard,\nDialogue: 0,0:42:25.04,0:42:27.77,EN,,0,0,0,,what the processing will do is if it finds a match,\nDialogue: 0,0:42:28.30,0:42:30.28,EN,,0,0,0,,it'll find a match to that exact thing,\nDialogue: 0,0:42:30.86,0:42:33.28,EN,,0,0,0,,and it'll type out a job, Ben Bitdiddle, computer wizard.\nDialogue: 0,0:42:34.22,0:42:35.60,EN,,0,0,0,,If it doesn't find a match,\nDialogue: 0,0:42:35.69,0:42:36.75,EN,,0,0,0,,it won't find anything.\nDialogue: 0,0:42:37.40,0:42:39.55,EN,,0,0,0,,So what I should have said is the way\nDialogue: 0,0:42:39.56,0:42:42.27,EN,,0,0,0,,you use the query language to check whether something is true,\nDialogue: 0,0:42:43.40,0:42:45.77,EN,,0,0,0,,that's one of the things you want to do in logic programming,\nDialogue: 0,0:42:46.41,0:42:49.34,EN,,0,0,0,,is you type in your query and either that comes out or it doesn't.\nDialogue: 0,0:42:50.68,0:42:52.38,EN,,0,0,0,,So what I was trying to illustrate here,\nDialogue: 0,0:42:52.41,0:42:54.80,EN,,0,0,0,,I wanted to start with a very simple example\nDialogue: 0,0:42:54.83,0:42:56.62,EN,,0,0,0,,before talking about unifiers.\nDialogue: 0,0:42:57.48,0:42:58.11,EN,,0,0,0,,So what I should have said,\nDialogue: 0,0:42:58.14,0:43:00.96,EN,,0,0,0,,if I just wanted to check whether this is true,\nDialogue: 0,0:43:01.18,0:43:03.28,EN,,0,0,0,,I could type that in and see if anything came out\nDialogue: 0,0:43:05.16,0:43:06.27,EN,,0,0,0,,AUDIENCE: And then the second one--\nDialogue: 0,0:43:06.28,0:43:07.84,EN,,0,0,0,,PROFESSOR: The second one would be a real query.\nDialogue: 0,0:43:07.88,0:43:09.12,EN,,0,0,0,,AUDIENCE: A real query, yeah.\nDialogue: 0,0:43:10.77,0:43:13.10,EN,,0,0,0,,PROFESSOR: What would come out, see, it would go in here say with WHO,\nDialogue: 0,0:43:13.90,0:43:15.74,EN,,0,0,0,,and in would go frame that says z\nDialogue: 0,0:43:16.62,0:43:18.81,EN,,0,0,0,,z is bound to who and d is bound to computer.\nDialogue: 0,0:43:19.56,0:43:20.49,EN,,0,0,0,,And this will pass through,\nDialogue: 0,0:43:20.51,0:43:21.95,EN,,0,0,0,,and then by the time it got out of here,\nDialogue: 0,0:43:22.01,0:43:23.25,EN,,0,0,0,,who would pick up a binding.\nDialogue: 0,0:43:26.95,0:43:28.76,EN,,0,0,0,,AUDIENCE: On the unifying thing there,\nDialogue: 0,0:43:29.18,0:43:35.96,EN,,0,0,0,,I still am not sure what happens with who and z.\nDialogue: 0,0:43:36.46,0:43:39.58,EN,,0,0,0,,OK being unifying-- the rule here says--\nDialogue: 0,0:43:42.03,0:43:46.22,EN,,0,0,0,,OK, so you say that you can't make question mark equal to question mark who.\nDialogue: 0,0:43:46.26,0:43:48.08,EN,,0,0,0,,PROFESSOR: Right. That's what the matcher can't do.\nDialogue: 0,0:43:48.36,0:43:50.83,EN,,0,0,0,,But unifier, what this will mean to a unifier\nDialogue: 0,0:43:51.92,0:43:54.01,EN,,0,0,0,,is that there's an environment with three variables.\nDialogue: 0,0:43:56.69,0:43:57.90,EN,,0,0,0,,d here is computer.\nDialogue: 0,0:43:58.52,0:44:00.19,EN,,0,0,0,,z is whatever who is.\nDialogue: 0,0:44:01.83,0:44:05.26,EN,,0,0,0,,So if later on in the matcher routine\nDialogue: 0,0:44:07.20,0:44:10.38,EN,,0,0,0,,it said, for example, who has to be 3,\nDialogue: 0,0:44:12.06,0:44:13.66,EN,,0,0,0,,then when I looked up in the dictionary,\nDialogue: 0,0:44:14.00,0:44:16.40,EN,,0,0,0,,it will say, oh, z is 3 because it's the same as who.\nDialogue: 0,0:44:18.36,0:44:20.44,EN,,0,0,0,,And that's in some sense the only thing you need to do\nDialogue: 0,0:44:20.46,0:44:21.98,EN,,0,0,0,,to extend the unifier to a matcher.\nDialogue: 0,0:44:22.48,0:44:24.80,EN,,0,0,0,,AUDIENCE: OK, because it looked like when you were telling how to unify,\nDialogue: 0,0:44:24.83,0:44:26.96,EN,,0,0,0,,it looked like you would put the things together in such a way\nDialogue: 0,0:44:26.99,0:44:29.23,EN,,0,0,0,,that you'd actually solve and have a value for both of them.\nDialogue: 0,0:44:29.77,0:44:31.24,EN,,0,0,0,,And what it looks like now\nDialogue: 0,0:44:31.28,0:44:32.83,EN,,0,0,0,,is that you're actually pass a dictionary\nDialogue: 0,0:44:32.88,0:44:34.86,EN,,0,0,0,,with two variables and the variables are linked.\nDialogue: 0,0:44:34.88,0:44:37.23,EN,,0,0,0,,PROFESSOR: Right. It only looks like you're solving for both of them\nDialogue: 0,0:44:37.52,0:44:39.74,EN,,0,0,0,,because you're sort of looking at the whole solution at once.\nDialogue: 0,0:44:40.54,0:44:42.81,EN,,0,0,0,,If you sort of watch the thing getting built up recursively,\nDialogue: 0,0:44:42.81,0:44:43.74,EN,,0,0,0,,it's merely this.\nDialogue: 0,0:44:44.98,0:44:48.40,EN,,0,0,0,,AUDIENCE: OK, so you do pass off that dictionary with two variables?\nDialogue: 0,0:44:48.40,0:44:49.11,EN,,0,0,0,,PROFESSOR: That's right.\nDialogue: 0,0:44:49.11,0:44:49.68,EN,,0,0,0,,AUDIENCE: And link?\nDialogue: 0,0:44:50.38,0:44:52.91,EN,,0,0,0,,PROFESSOR: Right. It just looks like an ordinary dictionary.\nDialogue: 0,0:44:54.35,0:44:56.06,EN,,0,0,0,,AUDIENCE: When you're talking about the unifier,\nDialogue: 0,0:44:56.09,0:45:00.19,EN,,0,0,0,,is it that there are some cases or some points\nDialogue: 0,0:45:00.75,0:45:03.98,EN,,0,0,0,,that you are not able to unify them?\nDialogue: 0,0:45:04.03,0:45:04.30,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:45:04.97,0:45:08.46,EN,,0,0,0,,AUDIENCE: Can you just by building the rules or\nDialogue: 0,0:45:09.16,0:45:15.93,EN,,0,0,0,,writing the forms know in advance if you are going to be able to solve\nDialogue: 0,0:45:16.48,0:45:18.54,EN,,0,0,0,,to get the unification or not?\nDialogue: 0,0:45:18.76,0:45:22.94,EN,,0,0,0,,Can you add some properties either to the rules itself\nDialogue: 0,0:45:23.18,0:45:25.45,EN,,0,0,0,,or to the form that you're writing\nDialogue: 0,0:45:25.82,0:45:29.04,EN,,0,0,0,,so that you avoid the problem of not finding unification?\nDialogue: 0,0:45:29.18,0:45:31.15,EN,,0,0,0,,Well I mean, you can agree,\nDialogue: 0,0:45:31.47,0:45:35.26,EN,,0,0,0,,I think, to write in a fairly restricted way where you won't run into it.\nDialogue: 0,0:45:35.60,0:45:36.67,EN,,0,0,0,,See, because what you're getting--\nDialogue: 0,0:45:36.88,0:45:39.12,EN,,0,0,0,,see, the place where you get into problems is when you--\nDialogue: 0,0:45:39.68,0:45:44.25,EN,,0,0,0,,well, again, you're trying to match things like that\nDialogue: 0,0:45:44.59,0:45:47.20,EN,,0,0,0,,against things where these have structure,\nDialogue: 0,0:45:47.55,0:45:55.30,EN,,0,0,0,,where a, y, b, y something.\nDialogue: 0,0:45:58.98,0:46:01.48,EN,,0,0,0,,So this is the kind of place where you're going to get into trouble.\nDialogue: 0,0:46:03.07,0:46:05.80,EN,,0,0,0,,AUDIENCE: So you can do that syntactically?\nDialogue: 0,0:46:06.14,0:46:08.76,EN,,0,0,0,,PROFESSOR: So you can kind of watch your rules\nDialogue: 0,0:46:08.76,0:46:10.49,EN,,0,0,0,,in the kinds of things that your writing.\nDialogue: 0,0:46:11.90,0:46:14.08,EN,,0,0,0,,AUDIENCE: So that's the problem that the builder\nDialogue: 0,0:46:14.11,0:46:16.27,EN,,0,0,0,,of the database has to be concerned?\nDialogue: 0,0:46:16.57,0:46:17.80,EN,,0,0,0,,PROFESSOR: That's a problem.\nDialogue: 0,0:46:19.93,0:46:22.01,EN,,0,0,0,,It's a problem either-- not quite the builder of the database,\nDialogue: 0,0:46:22.04,0:46:23.61,EN,,0,0,0,,the person who is expressing the rules,\nDialogue: 0,0:46:24.01,0:46:25.31,EN,,0,0,0,,or the builder of the database.\nDialogue: 0,0:46:25.80,0:46:29.79,EN,,0,0,0,,What the unifier actually does is you can check at the next level down\nDialogue: 0,0:46:29.92,0:46:31.87,EN,,0,0,0,,when you actually get to the unifier\nDialogue: 0,0:46:32.41,0:46:34.76,EN,,0,0,0,,and you'll see in the code where it looks up in the dictionary.\nDialogue: 0,0:46:34.94,0:46:36.83,EN,,0,0,0,,If it sort of says what does y have to be?\nDialogue: 0,0:46:37.26,0:46:41.42,EN,,0,0,0,,Oh, does y have to be something that contains a y as its expression?\nDialogue: 0,0:46:41.96,0:46:43.26,EN,,0,0,0,,At that point, the unifier and say,\nDialogue: 0,0:46:43.28,0:46:46.24,EN,,0,0,0,,oh my God, I'm trying to solve a fixed-point equation.\nDialogue: 0,0:46:46.24,0:46:46.99,EN,,0,0,0,,I'll give it up here.\nDialogue: 0,0:46:48.59,0:46:51.91,EN,,0,0,0,,AUDIENCE: You make the distinction between the rules in the database.\nDialogue: 0,0:46:51.91,0:46:56.48,EN,,0,0,0,,Are the rules added to the database?\nDialogue: 0,0:46:56.95,0:46:57.36,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:46:57.87,0:46:58.87,EN,,0,0,0,,Yes, I should have said that.\nDialogue: 0,0:46:58.87,0:47:00.33,EN,,0,0,0,,One way to think about rules\nDialogue: 0,0:47:00.60,0:47:02.65,EN,,0,0,0,,is that they're just other things in the database.\nDialogue: 0,0:47:03.71,0:47:06.81,EN,,0,0,0,,So if you want to check the things that have to be checked in the database,\nDialogue: 0,0:47:06.83,0:47:09.44,EN,,0,0,0,,they're kind of virtual facts that are in the database.\nDialogue: 0,0:47:09.44,0:47:12.32,EN,,0,0,0,,AUDIENCE: But in that explanation, you made the differentiation\nDialogue: 0,0:47:12.43,0:47:17.26,EN,,0,0,0,,between database and the rules itself.\nDialogue: 0,0:47:18.23,0:47:19.90,EN,,0,0,0,,PROFESSOR: Yeah, I probably should not have done that.\nDialogue: 0,0:47:20.49,0:47:23.31,EN,,0,0,0,,The only reason to do that is in terms of the implementation.\nDialogue: 0,0:47:23.54,0:47:24.67,EN,,0,0,0,,When you look at the implementation,\nDialogue: 0,0:47:24.68,0:47:27.50,EN,,0,0,0,,there's a part which says check either primitive\nDialogue: 0,0:47:27.55,0:47:29.85,EN,,0,0,0,,assertions in the database or check rules.\nDialogue: 0,0:47:30.47,0:47:32.72,EN,,0,0,0,,And then the real reason, the real reason why\nDialogue: 0,0:47:32.78,0:47:34.56,EN,,0,0,0,,you can't tell what order things are going to come out in\nDialogue: 0,0:47:34.96,0:47:40.46,EN,,0,0,0,,is that the rules database and the data database\nDialogue: 0,0:47:40.48,0:47:43.68,EN,,0,0,0,,sort of get merged in a kind of delayed evaluation way.\nDialogue: 0,0:47:44.60,0:47:46.80,EN,,0,0,0,,And so that's what makes the order very complicated.\nDialogue: 0,0:47:55.44,0:47:56.09,EN,,0,0,0,,OK, let's break.\nDialogue: 0,0:47:56.30,0:48:09.90,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:48:33.16,0:48:35.37,EN,,0,0,0,,We've just seen how the logic language works\nDialogue: 0,0:48:35.39,0:48:36.41,EN,,0,0,0,,and how rules work.\nDialogue: 0,0:48:37.23,0:48:39.37,EN,,0,0,0,,Now, let's turn to a more profound question.\nDialogue: 0,0:48:40.12,0:48:41.28,EN,,0,0,0,,What do these things mean?\nDialogue: 0,0:48:43.18,0:48:46.86,EN,,0,0,0,,That brings us to the subtlest, most devious part\nDialogue: 0,0:48:46.99,0:48:48.67,EN,,0,0,0,,of this whole query language business,\nDialogue: 0,0:48:49.21,0:48:53.07,EN,,0,0,0,,and that is that it's not quite what it seems to be.\nDialogue: 0,0:48:53.57,0:48:56.22,EN,,0,0,0,,AND and OR and NOT\nDialogue: 0,0:48:57.02,0:48:58.88,EN,,0,0,0,,and the logical implication of rules\nDialogue: 0,0:48:59.69,0:49:06.64,EN,,0,0,0,,are not really the AND and OR and NOT and logical implication of logic.\nDialogue: 0,0:49:07.69,0:49:09.71,EN,,0,0,0,,Let me give you an example of that.\nDialogue: 0,0:49:09.91,0:49:12.22,EN,,0,0,0,,Certainly, if we have two things in logic,\nDialogue: 0,0:49:12.40,0:49:19.44,EN,,0,0,0,,it ought to be the case that AND of P and Q\nDialogue: 0,0:49:20.00,0:49:22.59,EN,,0,0,0,,is the same as AND of Q and P\nDialogue: 0,0:49:23.10,0:49:24.51,EN,,0,0,0,,and that OR of P and Q\nDialogue: 0,0:49:24.78,0:49:26.51,EN,,0,0,0,,is the same as OR of Q and P.\nDialogue: 0,0:49:28.67,0:49:30.09,EN,,0,0,0,,But let's look here.\nDialogue: 0,0:49:30.10,0:49:32.01,EN,,0,0,0,,Here's an example.\nDialogue: 0,0:49:32.18,0:49:36.16,EN,,0,0,0,,Let's talk about somebody outranking somebody else\nDialogue: 0,0:49:36.28,0:49:40.14,EN,,0,0,0,,in this our little database organization.\nDialogue: 0,0:49:40.14,0:49:42.89,EN,,0,0,0,,We'll say s is outranked by b\nDialogue: 0,0:49:44.64,0:49:48.62,EN,,0,0,0,,if or if either the supervisor of s is b\nDialogue: 0,0:49:49.63,0:49:51.07,EN,,0,0,0,,or there's some middle manager here,\nDialogue: 0,0:49:51.10,0:49:55.82,EN,,0,0,0,,that supervisor of s is m, and m is outranked by b.\nDialogue: 0,0:49:59.64,0:50:02.31,EN,,0,0,0,,So there's one way to define rule outranked by.\nDialogue: 0,0:50:02.31,0:50:04.16,EN,,0,0,0,,Or we can write exactly the same thing,\nDialogue: 0,0:50:05.08,0:50:06.91,EN,,0,0,0,,except at the bottom here,\nDialogue: 0,0:50:07.21,0:50:09.88,EN,,0,0,0,,we reversed the order of these two clauses.\nDialogue: 0,0:50:11.63,0:50:12.99,EN,,0,0,0,,And certainly if this were logic,\nDialogue: 0,0:50:13.00,0:50:14.88,EN,,0,0,0,,those ought to mean the same thing.\nDialogue: 0,0:50:16.69,0:50:17.31,EN,,0,0,0,,However,\nDialogue: 0,0:50:17.71,0:50:19.61,EN,,0,0,0,,in our particular implementation,\nDialogue: 0,0:50:19.64,0:50:22.88,EN,,0,0,0,,if you say something like who's outranked by Ben Bitdiddle,\nDialogue: 0,0:50:23.48,0:50:25.36,EN,,0,0,0,,what you'll find is that this rule\nDialogue: 0,0:50:26.76,0:50:28.72,EN,,0,0,0,,will work perfectly well and generate answers,\nDialogue: 0,0:50:30.04,0:50:31.98,EN,,0,0,0,,whereas this rule will go into an infinite loop.\nDialogue: 0,0:50:34.11,0:50:36.27,EN,,0,0,0,,And the reason for that is that\nDialogue: 0,0:50:36.33,0:50:40.33,EN,,0,0,0,,this will come in and say, oh, who's outranked by Ben Bitdiddle?\nDialogue: 0,0:50:41.92,0:50:43.53,EN,,0,0,0,,Find an s, find an s\nDialogue: 0,0:50:43.88,0:50:46.22,EN,,0,0,0,,which is outranked by b, where b is Ben Bitdiddle,\nDialogue: 0,0:50:47.50,0:50:49.63,EN,,0,0,0,,which is going to happen in it a subproblem.\nDialogue: 0,0:50:50.33,0:50:51.98,EN,,0,0,0,,Oh gee, find an m\nDialogue: 0,0:50:52.24,0:50:54.57,EN,,0,0,0,,such as m is outranked by Ben Bitdiddle\nDialogue: 0,0:50:55.61,0:50:57.36,EN,,0,0,0,,with no restrictions on m.\nDialogue: 0,0:50:58.56,0:51:00.40,EN,,0,0,0,,So this will say in order to solve this problem,\nDialogue: 0,0:51:01.42,0:51:03.29,EN,,0,0,0,,I solve exactly the same problem.\nDialogue: 0,0:51:04.57,0:51:07.23,EN,,0,0,0,,And then after I've solved that, I'll check for a supervisory relationship.\nDialogue: 0,0:51:08.00,0:51:09.16,EN,,0,0,0,,Whereas this one won't get into that,\nDialogue: 0,0:51:09.18,0:51:12.35,EN,,0,0,0,,because before it tries to find this outranked by,\nDialogue: 0,0:51:12.94,0:51:15.26,EN,,0,0,0,,it'll already have had a restriction on m here.\nDialogue: 0,0:51:18.38,0:51:20.94,EN,,0,0,0,,So these two things which ought to mean the same,\nDialogue: 0,0:51:20.99,0:51:22.67,EN,,0,0,0,,in fact, one goes into an infinite loop.\nDialogue: 0,0:51:22.86,0:51:25.04,EN,,0,0,0,,One goes, one does not.\nDialogue: 0,0:51:26.72,0:51:29.77,EN,,0,0,0,,That's a very extreme case\nDialogue: 0,0:51:29.79,0:51:32.65,EN,,0,0,0,,of a general thing that you'll find in logic programming that\nDialogue: 0,0:51:34.28,0:51:38.70,EN,,0,0,0,,if you start changing the order of the things in the ANDs or ORs,\nDialogue: 0,0:51:39.34,0:51:41.58,EN,,0,0,0,,you'll find tremendous differences in efficiency.\nDialogue: 0,0:51:42.24,0:51:43.21,EN,,0,0,0,,And we just saw\nDialogue: 0,0:51:43.55,0:51:46.54,EN,,0,0,0,,an infinitely big difference in efficiency and an infinite loop.\nDialogue: 0,0:51:49.19,0:51:51.74,EN,,0,0,0,,And there are similar things having to do order\nDialogue: 0,0:51:52.00,0:51:53.31,EN,,0,0,0,,in which you enter rules.\nDialogue: 0,0:51:54.07,0:51:56.48,EN,,0,0,0,,The order in which it happens to look at rules in the database\nDialogue: 0,0:51:56.70,0:51:59.95,EN,,0,0,0,,may vastly change the efficiency with which it gets out answers or,\nDialogue: 0,0:52:00.46,0:52:02.60,EN,,0,0,0,,in fact, send it into an infinite loop for some orderings.\nDialogue: 0,0:52:03.84,0:52:07.29,EN,,0,0,0,,And this whole thing has to do\nDialogue: 0,0:52:07.63,0:52:10.04,EN,,0,0,0,,the fact that you're checking these rules in some order.\nDialogue: 0,0:52:10.95,0:52:14.41,EN,,0,0,0,,And some rules may lead to really long paths of implication.\nDialogue: 0,0:52:14.44,0:52:16.06,EN,,0,0,0,,Others might, others might not.\nDialogue: 0,0:52:16.44,0:52:17.68,EN,,0,0,0,,And you don't know a priori\nDialogue: 0,0:52:17.72,0:52:19.16,EN,,0,0,0,,which ones are good and which ones are bad.\nDialogue: 0,0:52:19.30,0:52:21.48,EN,,0,0,0,,And there's a whole bunch of research having to do with that,\nDialogue: 0,0:52:22.16,0:52:23.76,EN,,0,0,0,,mostly having to do with thinking about\nDialogue: 0,0:52:23.95,0:52:26.97,EN,,0,0,0,,making parallel implementations of logic programming languages.\nDialogue: 0,0:52:27.32,0:52:29.90,EN,,0,0,0,,And in some sense, what you'd like to do is check all rules in parallel\nDialogue: 0,0:52:30.36,0:52:32.80,EN,,0,0,0,,and whichever ones get answers, you bubble them up. And\nDialogue: 0,0:52:33.04,0:52:34.99,EN,,0,0,0,,if some go down infinite deductive chain,\nDialogue: 0,0:52:35.02,0:52:38.25,EN,,0,0,0,,well, you just-- you know, memory is cheap and processors are cheap,\nDialogue: 0,0:52:38.28,0:52:40.49,EN,,0,0,0,,you just let them buzz for as for as long as you want.\nDialogue: 0,0:52:43.47,0:52:44.83,EN,,0,0,0,,There's a deeper problem, though,\nDialogue: 0,0:52:45.18,0:52:50.49,EN,,0,0,0,,in comparing this logic language to real logic.\nDialogue: 0,0:52:50.68,0:52:52.52,EN,,0,0,0,,The example I just showed you, it\nDialogue: 0,0:52:52.97,0:52:54.80,EN,,0,0,0,,went into an infinite loop maybe,\nDialogue: 0,0:52:55.37,0:52:56.99,EN,,0,0,0,,but at least it didn't give the wrong answer.\nDialogue: 0,0:52:58.37,0:53:03.64,EN,,0,0,0,,There's an actual deeper problem when we start comparing,\nDialogue: 0,0:53:03.68,0:53:05.24,EN,,0,0,0,,you know, seriously comparing\nDialogue: 0,0:53:05.71,0:53:08.46,EN,,0,0,0,,this logic language with real classical logic.\nDialogue: 0,0:53:09.49,0:53:12.43,EN,,0,0,0,,So let's sort of review real classical logic.\nDialogue: 0,0:53:13.71,0:53:21.04,EN,,0,0,0,,All humans are mortal.\nDialogue: 0,0:53:22.35,0:53:23.45,EN,,0,0,0,,That's pretty classical logic.\nDialogue: 0,0:53:24.39,0:53:28.67,EN,,0,0,0,,Then maybe we'll continue in the very best classical tradition.\nDialogue: 0,0:53:29.24,0:53:32.46,EN,,0,0,0,,We'll say all-- let's make it really classical.\nDialogue: 0,0:53:32.67,0:53:37.16,EN,,0,0,0,,All Greeks are human,\nDialogue: 0,0:53:40.49,0:53:46.06,EN,,0,0,0,,which has the syllogism that Socrates is a Greek.\nDialogue: 0,0:53:48.17,0:53:49.21,EN,,0,0,0,,And then what do you write here?\nDialogue: 0,0:53:49.21,0:53:51.89,EN,,0,0,0,,I think three dots, classical logic.\nDialogue: 0,0:53:51.89,0:53:54.33,EN,,0,0,0,,Therefore, then the syllogism,\nDialogue: 0,0:53:54.64,0:53:59.55,EN,,0,0,0,,Socrates is mortal.\nDialogue: 0,0:54:01.36,0:54:04.91,EN,,0,0,0,,So there's some real honest classical logic.\nDialogue: 0,0:54:05.88,0:54:11.05,EN,,0,0,0,,Let's compare that with our classical logic database.\nDialogue: 0,0:54:12.40,0:54:14.46,EN,,0,0,0,,So here's a classical logic database.\nDialogue: 0,0:54:16.27,0:54:17.48,EN,,0,0,0,,Socrates is a Greek.\nDialogue: 0,0:54:18.03,0:54:18.84,EN,,0,0,0,,Plato is a Greek.\nDialogue: 0,0:54:19.60,0:54:20.40,EN,,0,0,0,,Zeus is a Greek,\nDialogue: 0,0:54:20.84,0:54:21.98,EN,,0,0,0,,and Zeus is a god.\nDialogue: 0,0:54:24.12,0:54:29.96,EN,,0,0,0,,And all humans are mortal.\nDialogue: 0,0:54:30.54,0:54:32.12,EN,,0,0,0,,To show that something is mortal,\nDialogue: 0,0:54:32.16,0:54:33.60,EN,,0,0,0,,it's enough to show that it's human.\nDialogue: 0,0:54:34.65,0:54:35.90,EN,,0,0,0,,All humans are fallible.\nDialogue: 0,0:54:38.90,0:54:40.98,EN,,0,0,0,,And all Greeks are humans is not quite right.\nDialogue: 0,0:54:40.98,0:54:44.41,EN,,0,0,0,,This says that all Greeks who are not gods are human.\nDialogue: 0,0:54:45.71,0:54:47.04,EN,,0,0,0,,So to show something's human,\nDialogue: 0,0:54:47.07,0:54:48.89,EN,,0,0,0,,it's enough to show it's a Greek and not a god.\nDialogue: 0,0:54:49.32,0:54:52.88,EN,,0,0,0,,And the address of any Greek god is Mount Olympus.\nDialogue: 0,0:54:54.32,0:54:57.16,EN,,0,0,0,,So there's a little classical logic database.\nDialogue: 0,0:54:57.39,0:54:59.32,EN,,0,0,0,,And indeed, that would work fairly well.\nDialogue: 0,0:54:59.49,0:55:02.09,EN,,0,0,0,,If we type that in and say\nDialogue: 0,0:55:03.47,0:55:06.57,EN,,0,0,0,,is Socrates mortal or Socrates fallible or mortal?\nDialogue: 0,0:55:06.91,0:55:07.69,EN,,0,0,0,,It'll say yes.\nDialogue: 0,0:55:07.77,0:55:09.71,EN,,0,0,0,,Is Plato mortal and fallible.\nDialogue: 0,0:55:09.71,0:55:10.24,EN,,0,0,0,,It'll say yes.\nDialogue: 0,0:55:10.68,0:55:12.21,EN,,0,0,0,,If we say is Zeus mortal?\nDialogue: 0,0:55:12.21,0:55:13.23,EN,,0,0,0,,It won't find anything.\nDialogue: 0,0:55:14.90,0:55:15.96,EN,,0,0,0,,And it'll work perfectly well.\nDialogue: 0,0:55:16.54,0:55:20.12,EN,,0,0,0,,However, suppose we want to extend this.\nDialogue: 0,0:55:20.12,0:55:23.05,EN,,0,0,0,,Let's define what it means for someone to be a perfect being.\nDialogue: 0,0:55:23.82,0:55:27.21,EN,,0,0,0,,Let's say rule: a perfect being.\nDialogue: 0,0:55:34.05,0:55:35.48,EN,,0,0,0,,And I think this is right.\nDialogue: 0,0:55:35.48,0:55:38.14,EN,,0,0,0,,If you're up on your medieval scholastic philosophy,\nDialogue: 0,0:55:38.44,0:55:40.17,EN,,0,0,0,,I believe that perfect beings are ones\nDialogue: 0,0:55:40.68,0:55:42.65,EN,,0,0,0,,who were neither mortal nor fallible.\nDialogue: 0,0:55:44.10,0:55:56.84,EN,,0,0,0,,AND NOT mortal x, NOT fallible x.\nDialogue: 0,0:55:59.30,0:56:00.89,EN,,0,0,0,,So we'll define this system\nDialogue: 0,0:56:02.67,0:56:04.36,EN,,0,0,0,,to teach it what a perfect being is.\nDialogue: 0,0:56:05.79,0:56:07.69,EN,,0,0,0,,And now what we're going to do is\nDialogue: 0,0:56:08.06,0:56:10.17,EN,,0,0,0,,ask for the address of all the perfect beings.\nDialogue: 0,0:56:11.48,0:56:22.30,EN,,0,0,0,,AND the address of x is y and x is perfect.\nDialogue: 0,0:56:23.48,0:56:24.97,EN,,0,0,0,,And so what we're generating here is\nDialogue: 0,0:56:24.99,0:56:27.80,EN,,0,0,0,,the world's most exclusive mailing list.\nDialogue: 0,0:56:30.16,0:56:32.20,EN,,0,0,0,,For the address of all the perfect beings,\nDialogue: 0,0:56:32.24,0:56:33.47,EN,,0,0,0,,we might have typed this in.\nDialogue: 0,0:56:33.83,0:56:35.44,EN,,0,0,0,,Or we might type in this.\nDialogue: 0,0:56:36.24,0:56:50.57,EN,,0,0,0,,We'll say AND perfect of x and the address of x is y.\nDialogue: 0,0:56:52.06,0:56:54.96,EN,,0,0,0,,Well, suppose we type all that in and we try this query.\nDialogue: 0,0:56:55.19,0:56:56.76,EN,,0,0,0,,This query is going to give us an answer.\nDialogue: 0,0:56:57.65,0:57:00.00,EN,,0,0,0,,This query will say, yeah, Mount Olympus.\nDialogue: 0,0:57:04.23,0:57:06.57,EN,,0,0,0,,This query, in fact, is going to give us nothing.\nDialogue: 0,0:57:06.74,0:57:09.58,EN,,0,0,0,,It will say no addresses of perfect beings.\nDialogue: 0,0:57:11.64,0:57:12.51,EN,,0,0,0,,Now, why is that?\nDialogue: 0,0:57:12.51,0:57:13.44,EN,,0,0,0,,Why is there a difference?\nDialogue: 0,0:57:14.23,0:57:15.69,EN,,0,0,0,,This is not an infinite loop question.\nDialogue: 0,0:57:15.69,0:57:17.08,EN,,0,0,0,,This is a different answer question.\nDialogue: 0,0:57:19.48,0:57:20.09,EN,,0,0,0,,The reason is\nDialogue: 0,0:57:20.38,0:57:22.32,EN,,0,0,0,,that if you remember the implementation of NOT,\nDialogue: 0,0:57:23.50,0:57:24.84,EN,,0,0,0,,NOT acted as a filter.\nDialogue: 0,0:57:25.88,0:57:29.00,EN,,0,0,0,,NOT said I'm going to take some possible dictionaries,\nDialogue: 0,0:57:29.05,0:57:31.56,EN,,0,0,0,,some possible frames, some possible answers,\nDialogue: 0,0:57:31.79,0:57:33.16,EN,,0,0,0,,and filter out the ones\nDialogue: 0,0:57:33.29,0:57:34.94,EN,,0,0,0,,that happened to satisfy some condition,\nDialogue: 0,0:57:34.97,0:57:36.11,EN,,0,0,0,,and that's how I implement NOT.\nDialogue: 0,0:57:36.92,0:57:38.43,EN,,0,0,0,,If you think about what's going on here,\nDialogue: 0,0:57:40.11,0:57:42.65,EN,,0,0,0,,I'll build this query box where the address piece\nDialogue: 0,0:57:43.32,0:57:47.39,EN,,0,0,0,,the output of an address piece gets fed into a perfect piece.\nDialogue: 0,0:57:50.29,0:57:51.00,EN,,0,0,0,,What will happen is\nDialogue: 0,0:57:51.32,0:57:53.26,EN,,0,0,0,,the address piece will set up some things of\nDialogue: 0,0:57:53.32,0:57:54.83,EN,,0,0,0,,everyone whose address I know.\nDialogue: 0,0:57:55.29,0:57:57.64,EN,,0,0,0,,Those will get filtered by the NOTs inside perfect here.\nDialogue: 0,0:57:59.88,0:58:04.19,EN,,0,0,0,,So it will throw out the ones which happened to be either mortal or fallible.\nDialogue: 0,0:58:04.91,0:58:06.38,EN,,0,0,0,,In the other order what happens\nDialogue: 0,0:58:06.73,0:58:09.12,EN,,0,0,0,,is I set this up, started up with an empty frame.\nDialogue: 0,0:58:09.52,0:58:12.35,EN,,0,0,0,,The perfect in here doesn't find anything for the NOTs to filter,\nDialogue: 0,0:58:12.38,0:58:13.98,EN,,0,0,0,,so nothing comes out here at all.\nDialogue: 0,0:58:18.83,0:58:21.50,EN,,0,0,0,,And there's sort of nothing there that gets fed into the address thing.\nDialogue: 0,0:58:21.94,0:58:23.15,EN,,0,0,0,,So here, I don't get an answer.\nDialogue: 0,0:58:23.93,0:58:27.04,EN,,0,0,0,,And again, the reason for that is NOT isn't generating anything.\nDialogue: 0,0:58:27.44,0:58:28.80,EN,,0,0,0,,NOT's only throwing out things.\nDialogue: 0,0:58:29.08,0:58:30.51,EN,,0,0,0,,And if I never started up with anything,\nDialogue: 0,0:58:30.52,0:58:31.74,EN,,0,0,0,,there's nothing for it to throw out.\nDialogue: 0,0:58:32.02,0:58:33.77,EN,,0,0,0,,So out of this thing, I get the wrong answer.\nDialogue: 0,0:58:37.20,0:58:37.97,EN,,0,0,0,,How can you fix that?\nDialogue: 0,0:58:37.97,0:58:39.07,EN,,0,0,0,,Well, there are ways to fix that.\nDialogue: 0,0:58:39.36,0:58:40.91,EN,,0,0,0,,So you might say, well, that's sort of stupid.\nDialogue: 0,0:58:41.41,0:58:44.90,EN,,0,0,0,,Why are you just doing all your NOT stuff at the beginning?\nDialogue: 0,0:58:44.96,0:58:47.48,EN,,0,0,0,,The right way to implement NOT is to realize\nDialogue: 0,0:58:47.84,0:58:50.08,EN,,0,0,0,,that when you have conditions like NOT,\nDialogue: 0,0:58:50.33,0:58:52.09,EN,,0,0,0,,you should generate all your answers first,\nDialogue: 0,0:58:52.80,0:58:54.97,EN,,0,0,0,,and then with each of these dictionaries pass along\nDialogue: 0,0:58:55.52,0:58:57.85,EN,,0,0,0,,Gee, at the very end I'll do filtering.\nDialogue: 0,0:58:58.56,0:59:02.01,EN,,0,0,0,,And there are implementations of logic languages that work like that\nDialogue: 0,0:59:02.41,0:59:04.05,EN,,0,0,0,,that solve this particular problem.\nDialogue: 0,0:59:06.80,0:59:08.97,EN,,0,0,0,,However, there's a more profound problem,\nDialogue: 0,0:59:09.60,0:59:11.53,EN,,0,0,0,,which is which one of these is the right answer?\nDialogue: 0,0:59:12.53,0:59:14.24,EN,,0,0,0,,Is it Mount Olympus or is it nothing?\nDialogue: 0,0:59:15.37,0:59:18.73,EN,,0,0,0,,So you might say it's Mount Olympus,\nDialogue: 0,0:59:18.76,0:59:20.73,EN,,0,0,0,,because after all, Zeus is in that database,\nDialogue: 0,0:59:22.52,0:59:25.10,EN,,0,0,0,,and Zeus was neither mortal nor fallible.\nDialogue: 0,0:59:29.55,0:59:32.44,EN,,0,0,0,,So you might say Zeus wants to satisfy\nDialogue: 0,0:59:34.30,0:59:44.03,EN,,0,0,0,,NOT mortal Zeus or NOT fallible Zeus.\nDialogue: 0,0:59:44.12,0:59:45.85,EN,,0,0,0,,But let's actually look at that database.\nDialogue: 0,0:59:47.92,0:59:48.46,EN,,0,0,0,,Let's look at it.\nDialogue: 0,0:59:49.36,0:59:53.24,EN,,0,0,0,,There's no way-- how does it know that Zeus is not fallible?\nDialogue: 0,0:59:54.81,0:59:56.11,EN,,0,0,0,,There's nothing in there about that.\nDialogue: 0,0:59:57.93,0:59:59.66,EN,,0,0,0,,What's in there is that humans are fallible.\nDialogue: 0,1:00:02.16,1:00:04.12,EN,,0,0,0,,How does it know that Zeus is not mortal?\nDialogue: 0,1:00:04.48,1:00:05.93,EN,,0,0,0,,There's nothing in there about that.\nDialogue: 0,1:00:07.98,1:00:11.00,EN,,0,0,0,,It just said I don't have any rule, which--\nDialogue: 0,1:00:11.68,1:00:14.06,EN,,0,0,0,,see the only way I can deduce something's mortal is if it's human\nDialogue: 0,1:00:14.08,1:00:15.68,EN,,0,0,0,,and that's all it really knows about mortal.\nDialogue: 0,1:00:16.69,1:00:19.85,EN,,0,0,0,,And in fact, if you remember your classical mythology,\nDialogue: 0,1:00:19.87,1:00:23.48,EN,,0,0,0,,you know that the Greek gods were not mortal but fallible.\nDialogue: 0,1:00:25.05,1:00:28.65,EN,,0,0,0,,So the answer is not in the rules there.\nDialogue: 0,1:00:30.85,1:00:32.10,EN,,0,0,0,,See, why does it deduce that?\nDialogue: 0,1:00:34.49,1:00:38.32,EN,,0,0,0,,See, Socrates would certainly not have made this error of logic.\nDialogue: 0,1:00:40.08,1:00:42.67,EN,,0,0,0,,What NOT means in this language is not NOT.\nDialogue: 0,1:00:43.37,1:00:44.32,EN,,0,0,0,,It's not the NOT of logic.\nDialogue: 0,1:00:44.93,1:00:46.40,EN,,0,0,0,,What NOT needs in this language is\nDialogue: 0,1:00:47.16,1:00:49.96,EN,,0,0,0,,not deducible from things in the database\nDialogue: 0,1:00:50.75,1:00:53.34,EN,,0,0,0,,as opposed to not true.\nDialogue: 0,1:00:55.02,1:00:56.30,EN,,0,0,0,,That's a very big difference.\nDialogue: 0,1:00:57.30,1:00:58.64,EN,,0,0,0,,Subtle, but big.\nDialogue: 0,1:00:59.25,1:01:00.27,EN,,0,0,0,,So, in fact,\nDialogue: 0,1:01:00.76,1:01:03.92,EN,,0,0,0,,this is perfectly happy to say not anything that it doesn't know about.\nDialogue: 0,1:01:04.68,1:01:06.14,EN,,0,0,0,,So if you ask it is it not true\nDialogue: 0,1:01:06.16,1:01:07.83,EN,,0,0,0,,that Zeus likes chocolate ice cream?\nDialogue: 0,1:01:07.85,1:01:09.12,EN,,0,0,0,,It will say sure, it's not true.\nDialogue: 0,1:01:10.64,1:01:12.51,EN,,0,0,0,,Or anything else or anything it doesn't know about.\nDialogue: 0,1:01:12.59,1:01:17.34,EN,,0,0,0,,NOT means not deducible from the things you've told me.\nDialogue: 0,1:01:18.28,1:01:22.44,EN,,0,0,0,,In a world where you're identifying not deducible\nDialogue: 0,1:01:22.65,1:01:24.00,EN,,0,0,0,,with, in fact, not true,\nDialogue: 0,1:01:24.41,1:01:26.30,EN,,0,0,0,,this is called the closed world assumption.\nDialogue: 0,1:01:37.37,1:01:38.17,EN,,0,0,0,,closed world assumption.\nDialogue: 0,1:01:38.20,1:01:42.38,EN,,0,0,0,,Anything that I cannot deduce from what I know\nDialogue: 0,1:01:43.50,1:01:44.36,EN,,0,0,0,,is not true,\nDialogue: 0,1:01:46.24,1:01:48.01,EN,,0,0,0,,Right? If I don't know anything about x,\nDialogue: 0,1:01:48.22,1:01:49.21,EN,,0,0,0,,the x isn't true.\nDialogue: 0,1:01:49.29,1:01:50.33,EN,,0,0,0,,That's very dangerous.\nDialogue: 0,1:01:51.29,1:01:52.44,EN,,0,0,0,,From a logical point of view,\nDialogue: 0,1:01:52.46,1:01:53.76,EN,,0,0,0,,first of all, it doesn't really makes sense.\nDialogue: 0,1:01:54.48,1:01:56.33,EN,,0,0,0,,Because if I don't know anything about x,\nDialogue: 0,1:01:58.38,1:01:59.69,EN,,0,0,0,,I'm willing to say not x.\nDialogue: 0,1:02:00.24,1:02:03.32,EN,,0,0,0,,But am I willing to say not not x?\nDialogue: 0,1:02:03.85,1:02:05.66,EN,,0,0,0,,Well, sure, I don't know anything about that either maybe.\nDialogue: 0,1:02:06.47,1:02:08.65,EN,,0,0,0,,So not not x is not necessarily the same as x\nDialogue: 0,1:02:09.24,1:02:10.94,EN,,0,0,0,,and so on and so on and so on, so\nDialogue: 0,1:02:11.71,1:02:13.93,EN,,0,0,0,,there's some sort of funny bias in there.\nDialogue: 0,1:02:15.97,1:02:17.29,EN,,0,0,0,,So that's sort of funny.\nDialogue: 0,1:02:17.29,1:02:18.09,EN,,0,0,0,,The second thing,\nDialogue: 0,1:02:20.14,1:02:24.12,EN,,0,0,0,,if you start building up real reasoning programs based on this,\nDialogue: 0,1:02:24.70,1:02:26.11,EN,,0,0,0,,think how dangerous that is.\nDialogue: 0,1:02:27.07,1:02:32.00,EN,,0,0,0,,You're saying I know I'm in a position\nDialogue: 0,1:02:32.22,1:02:36.22,EN,,0,0,0,,to deduce everything true that's relevant to this problem.\nDialogue: 0,1:02:37.44,1:02:40.78,EN,,0,0,0,,I'm reasoning, and built into my reasoning mechanism\nDialogue: 0,1:02:41.23,1:02:44.20,EN,,0,0,0,,is the assumption that anything that I don't know\nDialogue: 0,1:02:44.24,1:02:46.27,EN,,0,0,0,,can't possibly be relevant to this problem.\nDialogue: 0,1:02:48.44,1:02:53.04,EN,,0,0,0,,Right? There are a lot of big organizations that work like that, right?\nDialogue: 0,1:02:53.16,1:02:56.83,EN,,0,0,0,,Most corporate marketing divisions work like that.\nDialogue: 0,1:02:56.83,1:02:59.12,EN,,0,0,0,,You know the consequences to that.\nDialogue: 0,1:03:00.33,1:03:03.45,EN,,0,0,0,,So it's very dangerous to start really\nDialogue: 0,1:03:03.84,1:03:06.25,EN,,0,0,0,,typing in these big logical implication systems\nDialogue: 0,1:03:07.05,1:03:09.00,EN,,0,0,0,,and going on what they say,\nDialogue: 0,1:03:09.02,1:03:11.28,EN,,0,0,0,,because they have this really limiting assumption built in.\nDialogue: 0,1:03:12.60,1:03:14.36,EN,,0,0,0,,So you have to be very, very careful about that.\nDialogue: 0,1:03:15.29,1:03:16.28,EN,,0,0,0,,And that's a deep problem.\nDialogue: 0,1:03:16.56,1:03:17.82,EN,,0,0,0,,That's not a problem about\nDialogue: 0,1:03:18.22,1:03:20.14,EN,,0,0,0,,we can make a little bit cleverer implementation\nDialogue: 0,1:03:20.16,1:03:21.85,EN,,0,0,0,,and do the filters and organize the\nDialogue: 0,1:03:22.16,1:03:23.84,EN,,0,0,0,,the infinite loops to make them go away.\nDialogue: 0,1:03:23.84,1:03:25.08,EN,,0,0,0,,It's a different kind of problem.\nDialogue: 0,1:03:25.92,1:03:26.89,EN,,0,0,0,,It's a different semantics.\nDialogue: 0,1:03:27.06,1:03:30.51,EN,,0,0,0,,So I think to wrap this up, it's fair to say\nDialogue: 0,1:03:31.34,1:03:34.43,EN,,0,0,0,,that logic programming I think is a terrifically exciting idea,\nDialogue: 0,1:03:34.60,1:03:37.00,EN,,0,0,0,,the idea that you can bridge this\nDialogue: 0,1:03:37.04,1:03:38.78,EN,,0,0,0,,gap from the imperative to the declarative,\nDialogue: 0,1:03:39.90,1:03:42.94,EN,,0,0,0,,that you can start talking about relations\nDialogue: 0,1:03:43.58,1:03:45.08,EN,,0,0,0,,and really get tremendous power\nDialogue: 0,1:03:46.09,1:03:49.48,EN,,0,0,0,,by going above the abstraction of what's my input and what's my output.\nDialogue: 0,1:03:50.56,1:03:51.53,EN,,0,0,0,,And linked to logic,\nDialogue: 0,1:03:52.46,1:03:56.46,EN,,0,0,0,,the problem is it's a goal that I think has yet to be realized.\nDialogue: 0,1:03:58.03,1:04:01.80,EN,,0,0,0,,And probably one of the very most interesting\nDialogue: 0,1:04:02.27,1:04:04.41,EN,,0,0,0,,research questions going on now in languages\nDialogue: 0,1:04:04.67,1:04:08.28,EN,,0,0,0,,is how do you somehow make a real logic language?\nDialogue: 0,1:04:09.46,1:04:11.05,EN,,0,0,0,,And secondly, how do you bridge the gap\nDialogue: 0,1:04:11.31,1:04:13.15,EN,,0,0,0,,this world of logic and relations\nDialogue: 0,1:04:13.52,1:04:16.43,EN,,0,0,0,,to the worlds of more traditional languages\nDialogue: 0,1:04:16.46,1:04:17.98,EN,,0,0,0,,and somehow combine the power of both.\nDialogue: 0,1:04:18.88,1:04:19.68,EN,,0,0,0,,OK, let's break.\nDialogue: 0,1:04:23.29,1:04:25.29,EN,,0,0,0,,AUDIENCE: Couldn't you solve that last problem\nDialogue: 0,1:04:25.29,1:04:27.74,EN,,0,0,0,,by having the extra rules that imply it?\nDialogue: 0,1:04:27.96,1:04:29.85,EN,,0,0,0,,The problem here is you have the definition of something,\nDialogue: 0,1:04:29.88,1:04:31.82,EN,,0,0,0,,but you don't have the definition of its opposite.\nDialogue: 0,1:04:32.08,1:04:33.92,EN,,0,0,0,,If you include in the database something that says\nDialogue: 0,1:04:34.14,1:04:36.89,EN,,0,0,0,,uh... something implies mortal x,\nDialogue: 0,1:04:36.99,1:04:38.70,EN,,0,0,0,,something else implies not mortal x,\nDialogue: 0,1:04:38.75,1:04:40.37,EN,,0,0,0,,haven't you basically solved the problem?\nDialogue: 0,1:04:43.37,1:04:44.14,EN,,0,0,0,,PROFESSOR: But the issue is\nDialogue: 0,1:04:44.75,1:04:46.38,EN,,0,0,0,,do you put a finite number of those in?\nDialogue: 0,1:04:48.65,1:04:53.13,EN,,0,0,0,,AUDIENCE: If things are specified always in pairs--\nDialogue: 0,1:04:53.61,1:04:57.07,EN,,0,0,0,,PROFESSOR: But the question is then what do you do about deduction?\nDialogue: 0,1:05:00.20,1:05:02.11,EN,,0,0,0,,See, you can't specify NOTs.\nDialogue: 0,1:05:03.40,1:05:04.76,EN,,0,0,0,,But the problem is, in a big system,\nDialogue: 0,1:05:04.78,1:05:07.96,EN,,0,0,0,,it turns out that might not be a finite number of things.\nDialogue: 0,1:05:12.82,1:05:15.29,EN,,0,0,0,,There are also sort of two issues.\nDialogue: 0,1:05:15.29,1:05:16.56,EN,,0,0,0,,Partly it might not be finite.\nDialogue: 0,1:05:16.69,1:05:19.39,EN,,0,0,0,,Partly it might be that's not what you want.\nDialogue: 0,1:05:21.51,1:05:24.52,EN,,0,0,0,,So a good example would be suppose I want to do connectivity.\nDialogue: 0,1:05:25.12,1:05:26.54,EN,,0,0,0,,I want a reason about connectivity.\nDialogue: 0,1:05:28.05,1:05:30.38,EN,,0,0,0,,And I'm going to tell you there's four things:\nDialogue: 0,1:05:30.40,1:05:33.74,EN,,0,0,0,,a and b and c and d.\nDialogue: 0,1:05:35.48,1:05:38.19,EN,,0,0,0,,And I'll tell you a is connected to b\nDialogue: 0,1:05:38.64,1:05:41.42,EN,,0,0,0,,and c's connected to d.\nDialogue: 0,1:05:43.20,1:05:44.80,EN,,0,0,0,,And now I'll tell you is a connected to d?\nDialogue: 0,1:05:45.05,1:05:46.03,EN,,0,0,0,,That's the question.\nDialogue: 0,1:05:46.78,1:05:48.52,EN,,0,0,0,,There's an example where I would like\nDialogue: 0,1:05:48.70,1:05:50.35,EN,,0,0,0,,something like the closed world assumption.\nDialogue: 0,1:05:54.43,1:05:55.66,EN,,0,0,0,,That's a tiny toy,\nDialogue: 0,1:05:56.24,1:05:58.30,EN,,0,0,0,,but a lot of times, I want to be able to say something like\nDialogue: 0,1:05:58.48,1:06:01.34,EN,,0,0,0,,anything that I haven't told you, assume is not true.\nDialogue: 0,1:06:04.26,1:06:06.27,EN,,0,0,0,,So it's not as simple as you only want to put in\nDialogue: 0,1:06:06.27,1:06:08.09,EN,,0,0,0,,explicit NOTs all over the place.\nDialogue: 0,1:06:09.47,1:06:12.70,EN,,0,0,0,,It's that sometimes it really isn't clear what you even want.\nDialogue: 0,1:06:14.15,1:06:17.92,EN,,0,0,0,,That having to specify both everything and not everything is too precise,\nDialogue: 0,1:06:17.93,1:06:20.00,EN,,0,0,0,,and then you get down into problems there.\nDialogue: 0,1:06:20.96,1:06:22.68,EN,,0,0,0,,But there are a lot of approaches that\nDialogue: 0,1:06:23.32,1:06:25.93,EN,,0,0,0,,you know, that explicitly put in NOTs and reason based on that.\nDialogue: 0,1:06:26.51,1:06:27.66,EN,,0,0,0,,So it's a very good idea.\nDialogue: 0,1:06:28.07,1:06:31.45,EN,,0,0,0,,It's just that then it starts becoming a little cumbersome\nDialogue: 0,1:06:31.48,1:06:33.49,EN,,0,0,0,,in the very large problems you'd like to use.\nDialogue: 0,1:06:43.46,1:06:45.96,EN,,0,0,0,,AUDIENCE: I'm not sure how directly related to the argument this is,\nDialogue: 0,1:06:46.00,1:06:47.98,EN,,0,0,0,,but one of your points was that\nDialogue: 0,1:06:48.49,1:06:50.16,EN,,0,0,0,,one of the dangers of the closed world rule is\nDialogue: 0,1:06:50.19,1:06:52.06,EN,,0,0,0,,you never really know all the things that are there.\nDialogue: 0,1:06:53.44,1:06:55.32,EN,,0,0,0,,You never really know all the parts to it.\nDialogue: 0,1:06:55.87,1:06:58.16,EN,,0,0,0,,Isn't that a major problem with any programming?\nDialogue: 0,1:06:58.16,1:06:59.64,EN,,0,0,0,,I always write programs where I\nDialogue: 0,1:06:59.90,1:07:01.56,EN,,0,0,0,,I assume that I've got all the cases,\nDialogue: 0,1:07:01.58,1:07:03.40,EN,,0,0,0,,and so I check for them all or whatever, and i\nDialogue: 0,1:07:04.06,1:07:04.99,EN,,0,0,0,,and somewhere down the road, I\nDialogue: 0,1:07:05.02,1:07:06.52,EN,,0,0,0,,I find out that I didn't check for one of them.\nDialogue: 0,1:07:07.39,1:07:08.54,EN,,0,0,0,,PROFESSOR: Well, sure, it's true.\nDialogue: 0,1:07:08.54,1:07:09.76,EN,,0,0,0,,But the problem here is\nDialogue: 0,1:07:11.96,1:07:15.47,EN,,0,0,0,,it's that assumption which is the thing that you're making\nDialogue: 0,1:07:15.48,1:07:17.34,EN,,0,0,0,,if you believe you're identifying this with logic.\nDialogue: 0,1:07:19.60,1:07:20.51,EN,,0,0,0,,So you're quite right.\nDialogue: 0,1:07:20.51,1:07:22.22,EN,,0,0,0,,It's a situation you're never in.\nDialogue: 0,1:07:22.22,1:07:24.14,EN,,0,0,0,,The problem is if you're starting to believe that\nDialogue: 0,1:07:24.17,1:07:25.44,EN,,0,0,0,,what this is doing is logic\nDialogue: 0,1:07:26.17,1:07:27.32,EN,,0,0,0,,and you look at the rules you write down\nDialogue: 0,1:07:27.34,1:07:28.89,EN,,0,0,0,,and say what can I deduce from them,\nDialogue: 0,1:07:29.53,1:07:32.80,EN,,0,0,0,,you have to be very careful to remember that NOT means something else.\nDialogue: 0,1:07:33.47,1:07:35.21,EN,,0,0,0,,And it means something else based on an assumption\nDialogue: 0,1:07:35.24,1:07:36.70,EN,,0,0,0,,which is probably not true.\nDialogue: 0,1:07:39.03,1:07:40.19,EN,,0,0,0,,AUDIENCE: Do I understand you correctly that\nDialogue: 0,1:07:40.25,1:07:41.84,EN,,0,0,0,,you cannot fix this problem\nDialogue: 0,1:07:42.25,1:07:46.08,EN,,0,0,0,,without killing off all possibilities of inference through altering NOT?\nDialogue: 0,1:07:46.54,1:07:49.80,EN,,0,0,0,,PROFESSOR: No, that's not quite right.\nDialogue: 0,1:07:52.96,1:07:55.08,EN,,0,0,0,,There are ways to do logic with real NOTs.\nDialogue: 0,1:07:56.34,1:07:58.03,EN,,0,0,0,,There are actually ways to do that.\nDialogue: 0,1:07:58.54,1:08:00.84,EN,,0,0,0,,But they're very inefficient as far as anybody knows.\nDialogue: 0,1:08:01.61,1:08:02.56,EN,,0,0,0,,And they're much more--\nDialogue: 0,1:08:04.09,1:08:06.89,EN,,0,0,0,,they don't--  the, quote, inference in here\nDialogue: 0,1:08:07.39,1:08:08.83,EN,,0,0,0,,is built into this unifier\nDialogue: 0,1:08:08.91,1:08:11.29,EN,,0,0,0,,and this pattern matching unification algorithm.\nDialogue: 0,1:08:11.98,1:08:16.19,EN,,0,0,0,,There are ways to automate real logical reasoning.\nDialogue: 0,1:08:16.59,1:08:18.19,EN,,0,0,0,,But it's not based on that,\nDialogue: 0,1:08:18.51,1:08:20.73,EN,,0,0,0,,and logic programming languages don't tend to do that\nDialogue: 0,1:08:20.75,1:08:23.85,EN,,0,0,0,,because it's very inefficient as far as anybody knows.\nDialogue: 0,1:08:29.39,1:08:30.03,EN,,0,0,0,,All right, thank you.\nDialogue: 0,0:00:00.00,0:00:02.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP 学习小组\\N倾情制作\nDialogue: 0,0:00:02.40,0:00:09.84,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.90,0:00:16.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 II\nDialogue: 0,0:00:18.91,0:00:21.79,Default,,0,0,0,,我们已经了解了查询语言的使用方式\nDialogue: 0,0:00:22.64,0:00:25.07,Default,,0,0,0,,现在该来讨论如何实现了\nDialogue: 0,0:00:26.28,0:00:27.98,Default,,0,0,0,,你们也应该能够猜到\nDialogue: 0,0:00:28.59,0:00:29.47,Default,,0,0,0,,它其中的原理了\nDialogue: 0,0:00:29.47,0:00:31.64,Default,,0,0,0,,它的最底层是一个模式匹配器\nDialogue: 0,0:00:32.81,0:00:34.25,Default,,0,0,0,,我们在《基于规则的控制语言》一课中\nDialogue: 0,0:00:34.67,0:00:36.94,Default,,0,0,0,,已经介绍过模式匹配器了\nDialogue: 0,0:00:38.11,0:00:40.59,Default,,0,0,0,,我举个例子来让你们温习一下\nDialogue: 0,0:00:41.52,0:00:43.68,Default,,0,0,0,,这个模式会匹配\nDialogue: 0,0:00:43.80,0:00:44.92,Default,,0,0,0,,一个含有三个元素的表\nDialogue: 0,0:00:44.96,0:00:47.10,Default,,0,0,0,,其中 首元素为A\nDialogue: 0,0:00:47.16,0:00:48.33,Default,,0,0,0,,其次是C\nDialogue: 0,0:00:48.48,0:00:50.19,Default,,0,0,0,,而中间可以为任意元素\nDialogue: 0,0:00:50.65,0:00:52.27,Default,,0,0,0,,所以在这个小型的模式匹配语言中\nDialogue: 0,0:00:52.30,0:00:54.05,Default,,0,0,0,,你只能区分一种类型\nDialogue: 0,0:00:54.05,0:00:57.20,Default,,0,0,0,,也就是区分字面量或者变量\nDialogue: 0,0:00:57.23,0:00:58.86,Default,,0,0,0,,以问号开头的就是变量\nDialogue: 0,0:01:01.37,0:01:03.64,Default,,0,0,0,,因此这个模式会匹配任意的三元表\nDialogue: 0,0:01:04.44,0:01:06.50,Default,,0,0,0,,只要它的首元素为A 而第三个元素为C\nDialogue: 0,0:01:06.50,0:01:09.00,Default,,0,0,0,,而这个模式匹配的三元表\nDialogue: 0,0:01:10.43,0:01:12.53,Default,,0,0,0,,它的首元素必须是符号'JOB\nDialogue: 0,0:01:12.53,0:01:13.90,Default,,0,0,0,,第二个元素为任意值\nDialogue: 0,0:01:14.21,0:01:15.90,Default,,0,0,0,,第三个元素必须是一个二元表\nDialogue: 0,0:01:15.95,0:01:17.72,Default,,0,0,0,,二元表的首元素为符号'COMPUTER\nDialogue: 0,0:01:17.88,0:01:19.42,Default,,0,0,0,,第二个元素可以为任意值\nDialogue: 0,0:01:20.48,0:01:25.55,Default,,0,0,0,,而下一条模式所匹配的三元表\nDialogue: 0,0:01:25.87,0:01:26.99,Default,,0,0,0,,区别就在于\nDialogue: 0,0:01:28.40,0:01:31.32,Default,,0,0,0,,在于第三个元素的首元素必须为符号'COMPUTER\nDialogue: 0,0:01:31.76,0:01:33.29,Default,,0,0,0,,表剩余部分可以是任意值\nDialogue: 0,0:01:35.04,0:01:37.53,Default,,0,0,0,,也就是说 上面是二元表 而下面没有限定数目\nDialogue: 0,0:01:37.86,0:01:39.74,Default,,0,0,0,,然而我们的语言实现\nDialogue: 0,0:01:39.85,0:01:42.06,Default,,0,0,0,,根本不用操心如何去实现这个点号\nDialogue: 0,0:01:42.11,0:01:44.17,Default,,0,0,0,,因为这个由Lisp读取器自动地完成\nDialogue: 0,0:01:48.34,0:01:50.31,Default,,0,0,0,,要注意 匹配器还要保持一致性\nDialogue: 0,0:01:50.31,0:01:52.32,Default,,0,0,0,,这个模式匹配一个三元表\nDialogue: 0,0:01:52.59,0:01:53.98,Default,,0,0,0,,表的首元素是A\nDialogue: 0,0:01:54.43,0:01:55.79,Default,,0,0,0,,而第二个元素和第三个元素可以是任意值\nDialogue: 0,0:01:55.80,0:01:57.08,Default,,0,0,0,,但它们必须是相同的\nDialogue: 0,0:01:57.94,0:01:58.84,Default,,0,0,0,,它们都是?X\nDialogue: 0,0:01:59.60,0:02:01.55,Default,,0,0,0,,而这个模式匹配一个四元表\nDialogue: 0,0:02:01.96,0:02:03.26,Default,,0,0,0,,其中第一个元素与第四个元素相同\nDialogue: 0,0:02:03.66,0:02:05.15,Default,,0,0,0,,而第二个元素与第三个元素相同\nDialogue: 0,0:02:05.59,0:02:08.60,Default,,0,0,0,,最后一个模式匹配以A开头的任意表\nDialogue: 0,0:02:09.68,0:02:11.05,Default,,0,0,0,,以A开头\nDialogue: 0,0:02:11.23,0:02:12.56,Default,,0,0,0,,余下的可以是任意值\nDialogue: 0,0:02:14.04,0:02:16.60,Default,,0,0,0,,这是对我们已经学习过的模式匹配语言\nDialogue: 0,0:02:16.62,0:02:17.87,Default,,0,0,0,,的一个回顾\nDialogue: 0,0:02:18.78,0:02:19.64,Default,,0,0,0,,还记得吗\nDialogue: 0,0:02:19.79,0:02:22.28,Default,,0,0,0,,这是由一个叫做MATCH的过程实现的\nDialogue: 0,0:02:24.87,0:02:36.06,Default,,0,0,0,,MATCH有三个参数：PAT、DATA以及DICTIONARY\nDialogue: 0,0:02:43.20,0:02:47.12,Default,,0,0,0,,MATCH考虑的是\nDialogue: 0,0:02:47.79,0:02:52.64,Default,,0,0,0,,利用给定DICTIONAY中的绑定\nDialogue: 0,0:02:53.55,0:02:56.73,Default,,0,0,0,,能够找到一种方法把模式与数据对象匹配起来吗？\nDialogue: 0,0:02:58.16,0:02:59.21,Default,,0,0,0,,比如说\nDialogue: 0,0:02:59.56,0:03:06.43,Default,,0,0,0,,如果我们想要把模式(?X ?Y ?Y ?X)\nDialogue: 0,0:03:07.71,0:03:13.84,Default,,0,0,0,,与数据对象(A B B A)相匹配\nDialogue: 0,0:03:15.12,0:03:20.52,Default,,0,0,0,,又给定了一个字典 X=A\nDialogue: 0,0:03:22.01,0:03:25.23,Default,,0,0,0,,MATCH就会说：“它们是一致的”\nDialogue: 0,0:03:25.26,0:03:27.16,Default,,0,0,0,,再给定的字典说 X=A 的情况下\nDialogue: 0,0:03:27.80,0:03:30.20,Default,,0,0,0,,模式与数据相匹配\nDialogue: 0,0:03:30.32,0:03:31.60,Default,,0,0,0,,而匹配的结果则是\nDialogue: 0,0:03:32.25,0:03:34.30,Default,,0,0,0,,一个扩展了的词典\nDialogue: 0,0:03:34.46,0:03:37.60,Default,,0,0,0,,其中包含 X=A Y=B\nDialogue: 0,0:03:39.49,0:03:42.24,Default,,0,0,0,,MATCH接收模式、数据以及字典\nDialogue: 0,0:03:42.38,0:03:44.54,Default,,0,0,0,,如果成功匹配就输出一个扩展后的词典\nDialogue: 0,0:03:44.97,0:03:46.84,Default,,0,0,0,,否则就报错\nDialogue: 0,0:03:46.84,0:03:47.71,Default,,0,0,0,,因此 比如说\nDialogue: 0,0:03:47.88,0:03:50.38,Default,,0,0,0,,如果我在这里使用同样的模式\nDialogue: 0,0:03:50.97,0:03:55.12,Default,,0,0,0,,如果我用模式(?X ?Y ?Y ?X)\nDialogue: 0,0:03:55.66,0:03:58.49,Default,,0,0,0,,去匹配(A B B A)\nDialogue: 0,0:03:59.47,0:04:02.84,Default,,0,0,0,,并给定词典 Y=A\nDialogue: 0,0:04:05.15,0:04:06.81,Default,,0,0,0,,那么MATCH就会输出FAIL\nDialogue: 0,0:04:12.52,0:04:14.65,Default,,0,0,0,,你们已经见过模式匹配器的代码了\nDialogue: 0,0:04:15.00,0:04:16.17,Default,,0,0,0,,我就不会再去细讲\nDialogue: 0,0:04:16.64,0:04:19.77,Default,,0,0,0,,这跟我们以前做的类似\nDialogue: 0,0:04:21.19,0:04:23.22,Default,,0,0,0,,我们在《基于规则的系统》中已经见过了\nDialogue: 0,0:04:23.22,0:04:24.56,Default,,0,0,0,,基本上是同样的匹配器\nDialogue: 0,0:04:24.95,0:04:27.66,Default,,0,0,0,,实际上 我认为这里的语法还更简单一点\nDialogue: 0,0:04:28.16,0:04:29.31,Default,,0,0,0,,因为我们不用去关心\nDialogue: 0,0:04:29.40,0:04:31.40,Default,,0,0,0,,任意变量、任意表达式之类的东西\nDialogue: 0,0:04:31.40,0:04:32.88,Default,,0,0,0,,这里面只区分变量和常量\nDialogue: 0,0:04:35.79,0:04:37.32,Default,,0,0,0,,那么 有了模式匹配器以后\nDialogue: 0,0:04:38.46,0:04:39.61,Default,,0,0,0,,基本查询又是怎么样的呢？\nDialogue: 0,0:04:42.97,0:04:45.34,Default,,0,0,0,,基本查询将会是一个相当复杂的东西\nDialogue: 0,0:04:46.67,0:05:03.58,Default,,0,0,0,,就拿查询(JOB ?X (?D . ?Y))来说\nDialogue: 0,0:05:07.04,0:05:08.73,Default,,0,0,0,,我们可能会输入这样的查询\nDialogue: 0,0:05:09.40,0:05:11.39,Default,,0,0,0,,这又将如何在系统内实现呢？\nDialogue: 0,0:05:14.14,0:05:15.66,Default,,0,0,0,,我们可以把它想做这个小盒子\nDialogue: 0,0:05:15.70,0:05:16.80,Default,,0,0,0,,这是一条基本查询\nDialogue: 0,0:05:18.88,0:05:20.30,Default,,0,0,0,,这个小盒子将会\nDialogue: 0,0:05:22.24,0:05:27.28,Default,,0,0,0,,以两条流作为输入\nDialogue: 0,0:05:31.96,0:05:33.20,Default,,0,0,0,,并输出一条流\nDialogue: 0,0:05:34.03,0:05:36.19,Default,,0,0,0,,因此一条基本查询的形状\nDialogue: 0,0:05:36.51,0:05:38.46,Default,,0,0,0,,就将是有两条输入流\nDialogue: 0,0:05:38.67,0:05:39.96,Default,,0,0,0,,和一条输出流\nDialogue: 0,0:05:41.12,0:05:46.20,Default,,0,0,0,,而这些流 来自于这里的数据库\nDialogue: 0,0:05:51.95,0:05:53.93,Default,,0,0,0,,因此我们把数据库中的所有数据\nDialogue: 0,0:05:55.93,0:05:57.20,Default,,0,0,0,,想象成一条流\nDialogue: 0,0:05:57.31,0:05:58.40,Default,,0,0,0,,而这个盒子不断地吸取\nDialogue: 0,0:06:00.36,0:06:02.43,Default,,0,0,0,,那么 数据库中有什么呢？\nDialogue: 0,0:06:08.43,0:06:20.32,Default,,0,0,0,,首先是(JOB (ALYSSA ...))\nDialogue: 0,0:06:21.96,0:06:23.71,Default,,0,0,0,,以及还有其它的JOB数据\nDialogue: 0,0:06:25.77,0:06:30.41,Default,,0,0,0,,想象一下 数据库中的所有事实都在这条流中\nDialogue: 0,0:06:32.04,0:06:33.10,Default,,0,0,0,,都到了这里\nDialogue: 0,0:06:33.36,0:06:34.52,Default,,0,0,0,,而这条流送来的\nDialogue: 0,0:06:34.89,0:06:36.52,Default,,0,0,0,,是一些字典\nDialogue: 0,0:06:38.51,0:06:41.40,Default,,0,0,0,,其中一个就可能是\nDialogue: 0,0:06:46.70,0:06:49.31,Default,,0,0,0,,Y=PROG\nDialogue: 0,0:06:55.47,0:06:56.64,Default,,0,0,0,,现在 查询工作就是要\nDialogue: 0,0:06:57.07,0:06:59.80,Default,,0,0,0,,当它从这条流中取得一个字典后\nDialogue: 0,0:07:02.01,0:07:06.67,Default,,0,0,0,,它会搜寻数据库中的东西\nDialogue: 0,0:07:07.45,0:07:10.24,Default,,0,0,0,,来尽可能产生所有匹配结果\nDialogue: 0,0:07:11.39,0:07:12.89,Default,,0,0,0,,它把查询视作一种模式\nDialogue: 0,0:07:13.15,0:07:16.72,Default,,0,0,0,,并将它们与数据库中的事实匹配起来\nDialogue: 0,0:07:16.96,0:07:21.98,Default,,0,0,0,,结合着相应的字典中的数据\nDialogue: 0,0:07:22.94,0:07:25.68,Default,,0,0,0,,找到数据库中所有匹配的结果\nDialogue: 0,0:07:27.55,0:07:29.69,Default,,0,0,0,,所以针对数据库中的每条事实\nDialogue: 0,0:07:29.72,0:07:34.35,Default,,0,0,0,,它都会调用(MATCH PAT FACT DICTIONAY)来检查\nDialogue: 0,0:07:35.11,0:07:37.68,Default,,0,0,0,,如果成功匹配\nDialogue: 0,0:07:38.19,0:07:39.93,Default,,0,0,0,,它就输出一个扩展了的字典\nDialogue: 0,0:07:40.67,0:07:42.32,Default,,0,0,0,,比如说 这里进来了一本字典\nDialogue: 0,0:07:43.00,0:07:44.09,Default,,0,0,0,,并且成功匹配\nDialogue: 0,0:07:44.51,0:07:45.87,Default,,0,0,0,,那么就会输出一本字典\nDialogue: 0,0:07:46.81,0:07:49.79,Default,,0,0,0,,本例中就是Y=PROG\nDialogue: 0,0:07:51.52,0:07:52.97,Default,,0,0,0,,X=...\nDialogue: 0,0:07:56.54,0:07:58.75,Default,,0,0,0,,Y=PROG X=...\nDialogue: 0,0:07:58.96,0:08:00.54,Default,,0,0,0,,D又是一个新的项\nDialogue: 0,0:08:01.72,0:08:02.27,Default,,0,0,0,,像这样扩展\nDialogue: 0,0:08:03.52,0:08:07.82,Default,,0,0,0,,当然 它会针对数据库中的所有事实做同样的尝试\nDialogue: 0,0:08:07.98,0:08:09.25,Default,,0,0,0,,所以就可能有很多的结果\nDialogue: 0,0:08:09.56,0:08:10.59,Default,,0,0,0,,可能会产生另一本字典\nDialogue: 0,0:08:11.28,0:08:17.12,Default,,0,0,0,,其中 Y=PROG X=... D=...\nDialogue: 0,0:08:19.18,0:08:21.55,Default,,0,0,0,,因此 对于每个输入的框架\nDialogue: 0,0:08:21.76,0:08:23.69,Default,,0,0,0,,对于每输入一本字典\nDialogue: 0,0:08:23.72,0:08:25.24,Default,,0,0,0,,它可能输出很多本字典\nDialogue: 0,0:08:26.54,0:08:28.67,Default,,0,0,0,,或者什么也不输出\nDialogue: 0,0:08:30.47,0:08:38.48,Default,,0,0,0,,可能会有一些不匹配的情况 比如X=FOO\nDialogue: 0,0:08:39.02,0:08:40.89,Default,,0,0,0,,这个条目不会匹配任何东西\nDialogue: 0,0:08:41.52,0:08:45.12,Default,,0,0,0,,就这个框架来说 不会向输出流中输出东西\nDialogue: 0,0:08:47.51,0:08:51.28,Default,,0,0,0,,或者你也可以输入一个空框架\nDialogue: 0,0:08:52.91,0:08:56.24,Default,,0,0,0,,空框架是用来\nDialogue: 0,0:08:59.87,0:09:02.33,Default,,0,0,0,,在没有任何约束的情况下\nDialogue: 0,0:09:02.57,0:09:06.14,Default,,0,0,0,,匹配数据库中所有可能的结果\nDialogue: 0,0:09:07.57,0:09:09.16,Default,,0,0,0,,这仅仅代表着\nDialogue: 0,0:09:10.32,0:09:13.87,Default,,0,0,0,,处理你输入的查询 最初所进行的计算\nDialogue: 0,0:09:14.20,0:09:15.56,Default,,0,0,0,,它试图找出所有的匹配\nDialogue: 0,0:09:16.65,0:09:18.83,Default,,0,0,0,,基本查询建立了这种机制\nDialogue: 0,0:09:19.37,0:09:20.57,Default,,0,0,0,,而语言要做的是\nDialogue: 0,0:09:22.75,0:09:24.67,Default,,0,0,0,,当你在顶层输入这条查询时\nDialogue: 0,0:09:24.84,0:09:26.14,Default,,0,0,0,,它基于这种机制\nDialogue: 0,0:09:26.16,0:09:28.35,Default,,0,0,0,,它会输入一本空的字典\nDialogue: 0,0:09:30.86,0:09:32.56,Default,,0,0,0,,而对于输出的每个东西\nDialogue: 0,0:09:33.08,0:09:35.88,Default,,0,0,0,,然后把最初的查询\nDialogue: 0,0:09:36.56,0:09:40.44,Default,,0,0,0,,用不同的字典来实例化\nDialogue: 0,0:09:40.81,0:09:44.36,Default,,0,0,0,,于是实例化后的模式就形成了一条新的流\nDialogue: 0,0:09:44.99,0:09:46.51,Default,,0,0,0,,这就是在终端上打印出来的内容\nDialogue: 0,0:09:48.17,0:09:51.24,Default,,0,0,0,,这也就是其中的基本原理\nDialogue: 0,0:09:53.51,0:09:55.48,Default,,0,0,0,,那么 这又为什么复杂呢？\nDialogue: 0,0:09:57.71,0:10:01.00,Default,,0,0,0,,除了使用这种基于流的方法\nDialogue: 0,0:10:01.37,0:10:04.25,Default,,0,0,0,,你们可以想出很多更简单的方法来组织基本查询\nDialogue: 0,0:10:05.18,0:10:06.09,Default,,0,0,0,,而答案就在于\nDialogue: 0,0:10:07.15,0:10:08.51,Default,,0,0,0,,你们可能已经在想了\nDialogue: 0,0:10:10.86,0:10:14.09,Default,,0,0,0,,答案就是 这种方法能够优雅地\nDialogue: 0,0:10:14.56,0:10:16.76,Default,,0,0,0,,实现组合手段\nDialogue: 0,0:10:17.79,0:10:18.80,Default,,0,0,0,,比如说\nDialogue: 0,0:10:20.65,0:10:22.47,Default,,0,0,0,,假设我还想实现其它的效果\nDialogue: 0,0:10:22.47,0:10:26.96,Default,,0,0,0,,我不只是想查询所有人的工作信息\nDialogue: 0,0:10:27.23,0:10:28.35,Default,,0,0,0,,假设我还想查询\nDialogue: 0,0:10:29.47,0:10:35.92,Default,,0,0,0,,(AND (JOB ?X (?D . ?Y))\nDialogue: 0,0:10:36.80,0:10:47.04,Default,,0,0,0,,(SUPERVIOSR ?X ?Z))\nDialogue: 0,0:10:48.80,0:10:50.67,Default,,0,0,0,,(SUPERVISOR ?X ?Z)这条查询\nDialogue: 0,0:10:51.39,0:10:52.96,Default,,0,0,0,,是另外的一条基本查询\nDialogue: 0,0:10:53.71,0:10:58.43,Default,,0,0,0,,它也有类似的形状——接收一条数据对象流\nDialogue: 0,0:10:59.18,0:11:01.64,Default,,0,0,0,,一条初始字典流\nDialogue: 0,0:11:01.68,0:11:05.52,Default,,0,0,0,,字典是你在进行匹配时 需要遵循的约束\nDialogue: 0,0:11:05.53,0:11:07.44,Default,,0,0,0,,然后它会输出一条字典流\nDialogue: 0,0:11:08.70,0:11:10.80,Default,,0,0,0,,这就是这条基本查询的形状\nDialogue: 0,0:11:11.50,0:11:12.91,Default,,0,0,0,,我又该如何实现AND呢？\nDialogue: 0,0:11:12.91,0:11:13.45,Default,,0,0,0,,其实很简单\nDialogue: 0,0:11:13.45,0:11:14.44,Default,,0,0,0,,把它们连接起来就好了\nDialogue: 0,0:11:14.88,0:11:16.28,Default,,0,0,0,,我把这条查询的输出\nDialogue: 0,0:11:16.96,0:11:18.81,Default,,0,0,0,,连接在这条查询的输入上\nDialogue: 0,0:11:19.83,0:11:21.84,Default,,0,0,0,,然后把这里的字典扇出开来\nDialogue: 0,0:11:26.57,0:11:27.96,Default,,0,0,0,,你们就能发现它是如何工作的了\nDialogue: 0,0:11:29.05,0:11:32.44,Default,,0,0,0,,这里会输出一个框架\nDialogue: 0,0:11:32.51,0:11:36.84,Default,,0,0,0,,其中有X、Y和D的绑定\nDialogue: 0,0:11:37.92,0:11:39.28,Default,,0,0,0,,当后面的查询接收到结果后\nDialogue: 0,0:11:39.29,0:11:41.60,Default,,0,0,0,,当它了解了这些约束后\nDialogue: 0,0:11:42.17,0:11:49.24,Default,,0,0,0,,字典中的是Y、X和D的值\nDialogue: 0,0:11:51.80,0:11:53.08,Default,,0,0,0,,它会搜寻数据库\nDialogue: 0,0:11:53.12,0:11:54.92,Default,,0,0,0,,试图找到有关SUPERVISOR关系的事实\nDialogue: 0,0:11:56.04,0:11:58.51,Default,,0,0,0,,如果找到了的话 它就会输出一些词典\nDialogue: 0,0:11:59.58,0:12:09.34,Default,,0,0,0,,其中有Y、X、D以及Z的绑定\nDialogue: 0,0:12:12.07,0:12:14.09,Default,,0,0,0,,不过要注意\nDialogue: 0,0:12:14.19,0:12:17.24,Default,,0,0,0,,因为这里输入的框架建立了约束\nDialogue: 0,0:12:17.61,0:12:20.28,Default,,0,0,0,,它保证了当你执行AND运算时\nDialogue: 0,0:12:20.49,0:12:24.62,Default,,0,0,0,,这两个X是相同的\nDialogue: 0,0:12:26.47,0:12:28.96,Default,,0,0,0,,这是因为通过这条流输出时\nDialogue: 0,0:12:29.96,0:12:32.65,Default,,0,0,0,,X已经有值了 你要确保匹配的一致性\nDialogue: 0,0:12:34.46,0:12:36.17,Default,,0,0,0,,然后我们想起在MATCH的代码中\nDialogue: 0,0:12:36.19,0:12:38.17,Default,,0,0,0,,有一种操作字典的特殊组织方法\nDialogue: 0,0:12:38.20,0:12:39.82,Default,,0,0,0,,确保了匹配的一致性\nDialogue: 0,0:12:40.92,0:12:41.77,Default,,0,0,0,,这就是AND的实现\nDialogue: 0,0:12:44.08,0:12:46.94,Default,,0,0,0,,关键是要注意它的一般性形状\nDialogue: 0,0:12:48.49,0:12:51.55,Default,,0,0,0,,我们来看看(AND P Q)\nDialogue: 0,0:12:52.88,0:12:55.61,Default,,0,0,0,,这里是P和Q\nDialogue: 0,0:12:57.29,0:12:58.60,Default,,0,0,0,,两条查询的AND\nDialogue: 0,0:13:00.27,0:13:01.19,Default,,0,0,0,,看起来像是这样\nDialogue: 0,0:13:01.19,0:13:04.44,Default,,0,0,0,,每一条查询都通过一条流连接数据库\nDialogue: 0,0:13:04.54,0:13:05.71,Default,,0,0,0,,一条输入流\nDialogue: 0,0:13:06.33,0:13:08.17,Default,,0,0,0,,并输出一条输出流\nDialogue: 0,0:13:10.23,0:13:11.72,Default,,0,0,0,,关键是要注意\nDialogue: 0,0:13:12.20,0:13:15.02,Default,,0,0,0,,如果我在它们周围画一个盒子\nDialogue: 0,0:13:19.26,0:13:23.64,Default,,0,0,0,,这就是(AND P Q)\nDialogue: 0,0:13:25.66,0:13:30.38,Default,,0,0,0,,那么这个盒子也有同样的形状\nDialogue: 0,0:13:32.04,0:13:34.20,Default,,0,0,0,,它也有一条连接数据库的流\nDialogue: 0,0:13:34.20,0:13:35.74,Default,,0,0,0,,但是在内部会扇出开来\nDialogue: 0,0:13:36.60,0:13:37.93,Default,,0,0,0,,但是在外部你看不到\nDialogue: 0,0:13:38.16,0:13:40.64,Default,,0,0,0,,它接收一个流 并输出一个流\nDialogue: 0,0:13:42.06,0:13:43.16,Default,,0,0,0,,这就是AND\nDialogue: 0,0:13:43.57,0:13:45.72,Default,,0,0,0,,类似地 OR可能看起像这样\nDialogue: 0,0:13:46.02,0:13:49.58,Default,,0,0,0,,虽然我没给你们演示过OR的用法\nDialogue: 0,0:13:49.84,0:13:54.70,Default,,0,0,0,,OR会尝试找出P或Q所有匹配的事实\nDialogue: 0,0:13:55.80,0:13:58.07,Default,,0,0,0,,P、Q两条查询都有各自的形状\nDialogue: 0,0:14:04.46,0:14:06.68,Default,,0,0,0,,OR的实现则是\nDialogue: 0,0:14:08.54,0:14:10.91,Default,,0,0,0,,我把来自于数据库的流\nDialogue: 0,0:14:12.50,0:14:13.49,Default,,0,0,0,,扇出开来\nDialogue: 0,0:14:13.49,0:14:16.04,Default,,0,0,0,,把它们分别送给P和Q\nDialogue: 0,0:14:17.44,0:14:21.98,Default,,0,0,0,,我把最初的查询流也给扇出开来\nDialogue: 0,0:14:26.75,0:14:29.16,Default,,0,0,0,,这样我不但能够得到P的所有结果\nDialogue: 0,0:14:29.29,0:14:31.08,Default,,0,0,0,,也能得到Q的所有结果\nDialogue: 0,0:14:31.61,0:14:34.56,Default,,0,0,0,,把这些输出送入某种“附加器”中\nDialogue: 0,0:14:34.62,0:14:37.48,Default,,0,0,0,,或者把它们“合并”到一条流中\nDialogue: 0,0:14:39.64,0:14:40.88,Default,,0,0,0,,然后得到输出\nDialogue: 0,0:14:41.08,0:14:48.24,Default,,0,0,0,,而从外部来看 这整个东西就是OR\nDialogue: 0,0:14:52.35,0:14:54.89,Default,,0,0,0,,同样的 当你们从外部观察它时\nDialogue: 0,0:14:55.07,0:14:56.54,Default,,0,0,0,,你会发现它具有相同的形状\nDialogue: 0,0:15:01.00,0:15:01.61,Default,,0,0,0,,NOT又如何实现呢？\nDialogue: 0,0:15:02.02,0:15:03.45,Default,,0,0,0,,NOT的原理有些类似\nDialogue: 0,0:15:04.31,0:15:05.95,Default,,0,0,0,,如果我有一条查询P\nDialogue: 0,0:15:06.86,0:15:13.50,Default,,0,0,0,,这是一条基本查询P\nDialogue: 0,0:15:14.69,0:15:16.32,Default,,0,0,0,,现在我要实现(NOT P)\nDialogue: 0,0:15:18.68,0:15:20.54,Default,,0,0,0,,NOT的作用像是一个过滤器\nDialogue: 0,0:15:20.72,0:15:21.95,Default,,0,0,0,,这里连接数据库\nDialogue: 0,0:15:23.84,0:15:28.28,Default,,0,0,0,,这里是输入的字典流\nDialogue: 0,0:15:28.78,0:15:31.53,Default,,0,0,0,,(NOT P)要做的就是\nDialogue: 0,0:15:31.88,0:15:37.40,Default,,0,0,0,,对这些东西做过滤\nDialogue: 0,0:15:39.02,0:15:40.09,Default,,0,0,0,,过滤的方法则是\nDialogue: 0,0:15:40.19,0:15:42.70,Default,,0,0,0,,如果我在这里获得了一本字典\nDialogue: 0,0:15:43.42,0:15:44.65,Default,,0,0,0,,那么我就去找所有的匹配\nDialogue: 0,0:15:44.83,0:15:46.48,Default,,0,0,0,,然后丢弃找到的结果\nDialogue: 0,0:15:47.46,0:15:49.93,Default,,0,0,0,,如果我没有在这里找到匹配\nDialogue: 0,0:15:50.12,0:15:51.37,Default,,0,0,0,,我就把它传递过去\nDialogue: 0,0:15:52.40,0:15:53.55,Default,,0,0,0,,NOT就是一个纯粹的过滤器\nDialogue: 0,0:15:55.34,0:15:59.98,Default,,0,0,0,,因此AND就类似于一个电阻\nDialogue: 0,0:15:59.98,0:16:01.85,Default,,0,0,0,,AND是串行的组合\nDialogue: 0,0:16:02.49,0:16:04.14,Default,,0,0,0,,OR是并行组合\nDialogue: 0,0:16:04.96,0:16:07.46,Default,,0,0,0,,然而NOT并不会对字典做任何扩展\nDialogue: 0,0:16:07.46,0:16:08.40,Default,,0,0,0,,它只会做过滤\nDialogue: 0,0:16:08.75,0:16:11.79,Default,,0,0,0,,它会丢弃那些能够匹配的结果\nDialogue: 0,0:16:12.64,0:16:14.19,Default,,0,0,0,,LISP-VALUE的原理类似\nDialogue: 0,0:16:14.84,0:16:16.60,Default,,0,0,0,,它的过滤器会复杂点\nDialogue: 0,0:16:16.60,0:16:17.37,Default,,0,0,0,,因为要应用到谓词上\nDialogue: 0,0:16:19.93,0:16:21.64,Default,,0,0,0,,这里需要注意的关键点是\nDialogue: 0,0:16:21.92,0:16:23.55,Default,,0,0,0,,我们之前也强调过了\nDialogue: 0,0:16:23.64,0:16:25.29,Default,,0,0,0,,就是关于“闭包性质”的思想\nDialogue: 0,0:16:28.22,0:16:31.80,Default,,0,0,0,,我们通过组合手段构建的东西\nDialogue: 0,0:16:31.95,0:16:34.51,Default,,0,0,0,,跟所使用的基本物件\nDialogue: 0,0:16:35.69,0:16:37.58,Default,,0,0,0,,有同样的结构\nDialogue: 0,0:16:39.75,0:16:41.68,Default,,0,0,0,,所以从外面看\nDialogue: 0,0:16:41.71,0:16:43.72,Default,,0,0,0,,查询的AND与基本查询结构相同\nDialogue: 0,0:16:44.63,0:16:46.14,Default,,0,0,0,,这就意味着\nDialogue: 0,0:16:46.94,0:16:50.28,Default,,0,0,0,,这里的盒子可以是AND、OR、NOT或者其它的\nDialogue: 0,0:16:50.30,0:16:54.22,Default,,0,0,0,,因为它具有相同的形状来连接更大的东西\nDialogue: 0,0:16:54.95,0:16:56.68,Default,,0,0,0,,这种思想能够让我们获得\nDialogue: 0,0:16:56.92,0:16:58.96,Default,,0,0,0,,Escher绘图语言中的那种复杂度\nDialogue: 0,0:16:59.55,0:17:01.31,Default,,0,0,0,,让你能够仅仅使用序对\nDialogue: 0,0:17:01.34,0:17:03.26,Default,,0,0,0,,构建出这些复杂结构\nDialogue: 0,0:17:03.93,0:17:04.78,Default,,0,0,0,,这就是“闭包性质”\nDialogue: 0,0:17:06.28,0:17:08.06,Default,,0,0,0,,这种性质\nDialogue: 0,0:17:09.64,0:17:11.72,Default,,0,0,0,,能够让我完成你们现在觉得理所当然的事儿\nDialogue: 0,0:17:11.76,0:17:14.91,Default,,0,0,0,,比如我可以查询(AND JOB SALARY)\nDialogue: 0,0:17:14.91,0:17:18.80,Default,,0,0,0,,当然我也可以查询(AND JOB (NOT ...))等等\nDialogue: 0,0:17:19.26,0:17:20.92,Default,,0,0,0,,这种便利是由\nDialogue: 0,0:17:20.94,0:17:22.91,Default,,0,0,0,,这种“闭包原则”直接带给我们的\nDialogue: 0,0:17:25.18,0:17:27.08,Default,,0,0,0,,好吧 提问时间\nDialogue: 0,0:17:29.32,0:17:30.89,Default,,0,0,0,,学生：字典是从哪里来的？\nDialogue: 0,0:17:30.99,0:17:36.03,Default,,0,0,0,,教授：字典最初来自于你的输入\nDialogue: 0,0:17:36.09,0:17:37.32,Default,,0,0,0,,因此当你最初进行查询时\nDialogue: 0,0:17:39.16,0:17:41.09,Default,,0,0,0,,它首先会建立起这整个结构\nDialogue: 0,0:17:41.09,0:17:42.64,Default,,0,0,0,,它先输入一个空字典\nDialogue: 0,0:17:45.00,0:17:47.24,Default,,0,0,0,,如果你只有一条基本查询的话\nDialogue: 0,0:17:48.24,0:17:51.10,Default,,0,0,0,,那么它就会输出一系列具有内容的字典\nDialogue: 0,0:17:52.31,0:17:54.33,Default,,0,0,0,,这里演示的一般性情况是\nDialogue: 0,0:17:54.51,0:17:59.71,Default,,0,0,0,,某个嵌套组合查询的中间过程\nDialogue: 0,0:18:01.55,0:18:02.30,Default,,0,0,0,,所以在那时\nDialogue: 0,0:18:02.38,0:18:03.79,Default,,0,0,0,,让我们来看看这里\nDialogue: 0,0:18:04.38,0:18:06.73,Default,,0,0,0,,这条SUPERVISOR查询得到了某本字典\nDialogue: 0,0:18:06.73,0:18:08.03,Default,,0,0,0,,这本字典来自于哪里呢？\nDialogue: 0,0:18:08.73,0:18:11.15,Default,,0,0,0,,它来自于\nDialogue: 0,0:18:12.84,0:18:14.89,Default,,0,0,0,,这条基本查询的输出\nDialogue: 0,0:18:16.26,0:18:17.88,Default,,0,0,0,,说得更具体一点\nDialogue: 0,0:18:18.35,0:18:21.72,Default,,0,0,0,,如果我最初在顶层只输入了这条查询\nDialogue: 0,0:18:22.27,0:18:22.92,Default,,0,0,0,,这整条AND查询\nDialogue: 0,0:18:23.07,0:18:25.28,Default,,0,0,0,,它实际上会构建这种结构\nDialogue: 0,0:18:25.50,0:18:30.24,Default,,0,0,0,,并使用一本空字典来启动整个过程\nDialogue: 0,0:18:31.77,0:18:34.33,Default,,0,0,0,,处理过程开始后 会产生一系列的字典\nDialogue: 0,0:18:34.36,0:18:37.36,Default,,0,0,0,,其中就有X、Y以及D\nDialogue: 0,0:18:38.64,0:18:39.58,Default,,0,0,0,,向这边传递\nDialogue: 0,0:18:40.19,0:18:42.16,Default,,0,0,0,,这就是这条查询的输入\nDialogue: 0,0:18:42.16,0:18:43.72,Default,,0,0,0,,这条查询也会生成其它的东西\nDialogue: 0,0:18:45.04,0:18:48.22,Default,,0,0,0,,如果这整个查询是构建在一个更大的查询中的话\nDialogue: 0,0:18:49.31,0:18:51.00,Default,,0,0,0,,比如说一条OR查询\nDialogue: 0,0:18:53.42,0:18:55.71,Default,,0,0,0,,那么它将输出到下一个查询中\nDialogue: 0,0:18:58.56,0:19:01.28,Default,,0,0,0,,因此最初开始处理时 只有一本空字典\nDialogue: 0,0:19:01.68,0:19:04.08,Default,,0,0,0,,但是在处理这些复合查询的过程中\nDialogue: 0,0:19:04.11,0:19:06.65,Default,,0,0,0,,会生成各种不同的字典\nDialogue: 0,0:19:07.66,0:19:12.28,Default,,0,0,0,,学生：字典都是查询的结果吗？\nDialogue: 0,0:19:15.12,0:19:17.69,Default,,0,0,0,,它们会变成\nDialogue: 0,0:19:18.84,0:19:22.81,Default,,0,0,0,,它们存储在数据库中吗？\nDialogue: 0,0:19:23.68,0:19:24.98,Default,,0,0,0,,它们是临时数据吗？\nDialogue: 0,0:19:24.98,0:19:27.18,Default,,0,0,0,,教授：它们是在MATCH过程中临时创建的\nDialogue: 0,0:19:28.03,0:19:29.88,Default,,0,0,0,,但它们实际存放在内存中\nDialogue: 0,0:19:29.88,0:19:33.02,Default,,0,0,0,,最初 某人创建了一本THE-EMPTY-DICT字典\nDialogue: 0,0:19:34.22,0:19:36.80,Default,,0,0,0,,送入这个匹配过程\nDialogue: 0,0:19:36.81,0:19:39.05,Default,,0,0,0,,MATCH过程据此构建新字典\nDialogue: 0,0:19:39.07,0:19:40.27,Default,,0,0,0,,并把它们传递下去\nDialogue: 0,0:19:40.76,0:19:42.48,Default,,0,0,0,,学生：因此匹配完成后它们就被丢弃了？\nDialogue: 0,0:19:43.64,0:19:46.25,Default,,0,0,0,,教授：实际上 当没人需要它们后（就被废料回收了）\nDialogue: 0,0:19:51.90,0:19:53.60,Default,,0,0,0,,学生：似乎AND查询对数据库\nDialogue: 0,0:19:53.63,0:19:55.37,Default,,0,0,0,,进行了一些冗余操作\nDialogue: 0,0:19:55.96,0:19:57.48,Default,,0,0,0,,如果第一条子句扫描过了\nDialogue: 0,0:19:57.50,0:19:59.90,Default,,0,0,0,,比如说前两个元素没有匹配 而第三个元素匹配了\nDialogue: 0,0:20:00.25,0:20:03.64,Default,,0,0,0,,然而第二条子句又会检查这两个元素\nDialogue: 0,0:20:04.32,0:20:06.59,Default,,0,0,0,,然后又一次丢弃这些不匹配的元素\nDialogue: 0,0:20:06.64,0:20:08.72,Default,,0,0,0,,而字典中已经有匹配的项了\nDialogue: 0,0:20:10.00,0:20:12.56,Default,,0,0,0,,如果我们把数据库中的数据\nDialogue: 0,0:20:12.57,0:20:14.43,Default,,0,0,0,,跟字典同时传递 这样可行么？\nDialogue: 0,0:20:15.69,0:20:17.60,Default,,0,0,0,,教授：实际上 通常来说\nDialogue: 0,0:20:17.63,0:20:19.48,Default,,0,0,0,,我们能够以其它方式来安排这些搜索\nDialogue: 0,0:20:20.12,0:20:21.74,Default,,0,0,0,,你也可以做一些分析\nDialogue: 0,0:20:21.74,0:20:23.16,Default,,0,0,0,,我记得书里面就有这样的习题\nDialogue: 0,0:20:23.87,0:20:26.65,Default,,0,0,0,,是考察通过安排AND子句的顺序\nDialogue: 0,0:20:27.00,0:20:29.20,Default,,0,0,0,,来消除不同类型的冗余\nDialogue: 0,0:20:29.85,0:20:30.72,Default,,0,0,0,,而这里只是为了\nDialogue: 0,0:20:31.32,0:20:34.54,Default,,0,0,0,,用非常简单的情况来向你们展示它们是如何配合的\nDialogue: 0,0:20:34.70,0:20:35.38,Default,,0,0,0,,但是你说得非常对\nDialogue: 0,0:20:35.38,0:20:37.32,Default,,0,0,0,,这些冗余是可以避免的\nDialogue: 0,0:20:38.37,0:20:40.80,Default,,0,0,0,,这也是这门语言缓慢的原因之一\nDialogue: 0,0:20:41.19,0:20:42.70,Default,,0,0,0,,你们可以让它变得更聪明\nDialogue: 0,0:20:42.93,0:20:46.22,Default,,0,0,0,,我只是为了向你们演示非常简单的、原理性的实现\nDialogue: 0,0:20:51.22,0:20:53.23,Default,,0,0,0,,学生：您是根据Prolog来建模这门语言的\nDialogue: 0,0:20:53.24,0:20:55.13,Default,,0,0,0,,还是说它只是偶然地像Prolog？\nDialogue: 0,0:21:04.96,0:21:07.08,Default,,0,0,0,,教授：Gerry教授昨天羞辱了一大堆人\nDialogue: 0,0:21:07.24,0:21:09.92,Default,,0,0,0,,我想说真实的情况是\nDialogue: 0,0:21:10.19,0:21:12.60,Default,,0,0,0,,MIT的研究人员在1971年做了类似的事\nDialogue: 0,0:21:12.64,0:21:15.60,Default,,0,0,0,,但是发现这个方向并不正确 并停止了研究\nDialogue: 0,0:21:16.12,0:21:22.80,Default,,0,0,0,,因此我们是根据查询处理的基本原理建模的\nDialogue: 0,0:21:22.84,0:21:24.73,Default,,0,0,0,,大概在1971年左右\nDialogue: 0,0:21:25.13,0:21:27.24,Default,,0,0,0,,只是说 那时候我们还没有用流来实现\nDialogue: 0,0:21:28.27,0:21:33.04,Default,,0,0,0,,然后我们 -- 但我们使用了它差不多六个月后\nDialogue: 0,0:21:33.08,0:21:34.91,Default,,0,0,0,,发现它存在各种各样的问题\nDialogue: 0,0:21:34.94,0:21:36.30,Default,,0,0,0,,稍后我会解释\nDialogue: 0,0:21:37.33,0:21:38.19,Default,,0,0,0,,然后我们就想\nDialogue: 0,0:21:38.44,0:21:39.92,Default,,0,0,0,,Prolog一定解决了这些问题\nDialogue: 0,0:21:39.93,0:21:41.21,Default,,0,0,0,,但却发现它并没有\nDialogue: 0,0:21:41.25,0:21:43.02,Default,,0,0,0,,从这种意义上来说 它确实跟Prolog一样\nDialogue: 0,0:21:43.60,0:21:44.95,Default,,0,0,0,,学生：Prolog基于流么？\nDialogue: 0,0:21:44.95,0:21:46.20,Default,,0,0,0,,教授：不 Prolog基于的是\nDialogue: 0,0:21:46.78,0:21:51.04,Default,,0,0,0,,就行为上来说 我们的语言很像Prolog\nDialogue: 0,0:21:51.04,0:21:52.96,Default,,0,0,0,,Prolog使用回溯策略\nDialogue: 0,0:21:53.80,0:21:55.71,Default,,0,0,0,,但是Prolog有一个优点非常好\nDialogue: 0,0:21:55.72,0:21:57.98,Default,,0,0,0,,也使得它变得实用\nDialogue: 0,0:21:58.28,0:22:01.50,Default,,0,0,0,,你知道吗\nDialogue: 0,0:22:01.68,0:22:04.09,Default,,0,0,0,,它们精心设计了Prolog的编译器\nDialogue: 0,0:22:04.11,0:22:05.32,Default,,0,0,0,,使得它能够高速运行\nDialogue: 0,0:22:06.65,0:22:10.81,Default,,0,0,0,,因此 虽然我们这门语言非常缓慢地输出答案\nDialogue: 0,0:22:11.66,0:22:13.61,Default,,0,0,0,,真正的Prolog程序却运行得非常快\nDialogue: 0,0:22:14.70,0:22:16.48,Default,,0,0,0,,这是因为 尽管搜索过程十分低效\nDialogue: 0,0:22:16.67,0:22:20.81,Default,,0,0,0,,Prolog卓越的编译器也会高效地完成工作\nDialogue: 0,0:22:24.30,0:22:25.21,Default,,0,0,0,,休息一下吧\nDialogue: 0,0:22:25.42,0:22:36.17,Default,,0,0,0,,[音乐]\nDialogue: 0,0:22:36.35,0:22:39.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:23:01.48,0:23:05.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:23:05.18,0:23:09.05,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:23:09.12,0:23:13.66,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 II\nDialogue: 0,0:23:16.65,0:23:18.83,Default,,0,0,0,,我们已经考察过了基本查询\nDialogue: 0,0:23:19.21,0:23:23.52,Default,,0,0,0,,以及如何使用流来实现组合手段\nDialogue: 0,0:23:23.79,0:23:25.72,Default,,0,0,0,,AND、OR以及NOT\nDialogue: 0,0:23:26.95,0:23:28.43,Default,,0,0,0,,现在 该讨论抽象手段了\nDialogue: 0,0:23:29.58,0:23:32.80,Default,,0,0,0,,回想一下 我们这门语言的抽象手段是RULE\nDialogue: 0,0:23:35.15,0:23:37.79,Default,,0,0,0,,(BOSS ?Z ?D)描述的是\nDialogue: 0,0:23:39.18,0:23:43.77,Default,,0,0,0,,如果某人在D部门工作\nDialogue: 0,0:23:45.68,0:23:47.47,Default,,0,0,0,,并且Z是X的上司\nDialogue: 0,0:23:48.90,0:23:50.60,Default,,0,0,0,,这就是所谓的“BOSS”\nDialogue: 0,0:23:52.26,0:23:53.15,Default,,0,0,0,,并且 实际上\nDialogue: 0,0:23:53.34,0:23:55.61,Default,,0,0,0,,如果我们考察一下编写的规则与这边的关系\nDialogue: 0,0:23:56.80,0:23:57.90,Default,,0,0,0,,这是我们编写的查询\nDialogue: 0,0:23:57.93,0:24:01.90,Default,,0,0,0,,这个是(JOB ?X ?D) 而这个是(SUPERVISOR ?X ?Z)\nDialogue: 0,0:24:02.19,0:24:04.28,Default,,0,0,0,,我们实际想要把这一大堆东西\nDialogue: 0,0:24:05.07,0:24:06.57,Default,,0,0,0,,用一个盒子封装起来\nDialogue: 0,0:24:19.08,0:24:24.54,Default,,0,0,0,,然后把这个盒子里的所有东西\nDialogue: 0,0:24:25.15,0:24:32.48,Default,,0,0,0,,认为是(BOSS ?Z ?D)\nDialogue: 0,0:24:33.90,0:24:35.25,Default,,0,0,0,,这是我们想要达到的效果\nDialogue: 0,0:24:38.72,0:24:39.72,Default,,0,0,0,,因此 比如说\nDialogue: 0,0:24:43.18,0:24:44.08,Default,,0,0,0,,我们这样做了过后\nDialogue: 0,0:24:45.00,0:24:47.84,Default,,0,0,0,,我们想要检查\nDialogue: 0,0:24:47.95,0:24:50.51,Default,,0,0,0,,Ben Bitdiddle是否为计算机分部的BOSS\nDialogue: 0,0:24:51.10,0:25:02.86,Default,,0,0,0,,如果我想查询 (BOSS (BITDIDDLE BEN) COMPUTER)\nDialogue: 0,0:25:04.78,0:25:07.08,Default,,0,0,0,,想象一下把这条查询输入系统\nDialogue: 0,0:25:07.12,0:25:09.16,Default,,0,0,0,,实际上发生的是\nDialogue: 0,0:25:10.67,0:25:12.92,Default,,0,0,0,,在这里先构建一本字典\nDialogue: 0,0:25:15.82,0:25:23.63,Default,,0,0,0,,其中 ?Z=BITDIDDLE\nDialogue: 0,0:25:28.88,0:25:33.31,Default,,0,0,0,,?D=COMPUTER\nDialogue: 0,0:25:37.08,0:25:38.62,Default,,0,0,0,,这个字典又是来自于哪里呢？\nDialogue: 0,0:25:38.68,0:25:40.71,Default,,0,0,0,,我们来看下幻灯片\nDialogue: 0,0:25:40.71,0:25:43.71,Default,,0,0,0,,这本字典是通过把\nDialogue: 0,0:25:44.30,0:25:46.33,Default,,0,0,0,,查询(BOSS (BITDIDDLE BEN) COMPUTER)\nDialogue: 0,0:25:46.51,0:25:49.63,Default,,0,0,0,,与规则的结论(BOSS ?Z ?D)相匹配得到\nDialogue: 0,0:25:51.65,0:25:54.11,Default,,0,0,0,,所以我们把规则的结论和查询匹配了起来\nDialogue: 0,0:25:54.19,0:25:55.53,Default,,0,0,0,,这样我们就获得了一本字典\nDialogue: 0,0:25:58.99,0:26:02.54,Default,,0,0,0,,现在我们就要把这本字典输入到这整个结构中\nDialogue: 0,0:26:02.92,0:26:05.56,Default,,0,0,0,,进行处理 并观察是否有输出\nDialogue: 0,0:26:06.67,0:26:09.88,Default,,0,0,0,,如果输出了结果 那么查询就为真\nDialogue: 0,0:26:11.33,0:26:12.37,Default,,0,0,0,,这是基本的思想\nDialogue: 0,0:26:12.37,0:26:13.24,Default,,0,0,0,,因此 通常来说\nDialogue: 0,0:26:14.03,0:26:15.40,Default,,0,0,0,,我们实现规则的方法就是\nDialogue: 0,0:26:15.85,0:26:18.89,Default,,0,0,0,,用规则的结论去匹配\nDialogue: 0,0:26:20.86,0:26:22.96,Default,,0,0,0,,假设为真的查询\nDialogue: 0,0:26:23.58,0:26:25.12,Default,,0,0,0,,这个过程会产生一本字典\nDialogue: 0,0:26:25.29,0:26:28.22,Default,,0,0,0,,在有了相关字典后\nDialogue: 0,0:26:30.35,0:26:34.51,Default,,0,0,0,,我们来处理规则的体\nDialogue: 0,0:26:36.33,0:26:37.68,Default,,0,0,0,,基本上就是这样了\nDialogue: 0,0:26:38.64,0:26:41.44,Default,,0,0,0,,但还有两个技术点\nDialogue: 0,0:26:43.04,0:26:44.32,Default,,0,0,0,,首先就是\nDialogue: 0,0:26:45.74,0:26:47.26,Default,,0,0,0,,我也可能有其它的问法\nDialogue: 0,0:26:47.51,0:26:48.41,Default,,0,0,0,,比如说\nDialogue: 0,0:26:50.54,0:26:52.36,Default,,0,0,0,,查询计算机分部的BOSS\nDialogue: 0,0:26:52.54,0:26:56.32,Default,,0,0,0,,就可以查询 (BOSS ?WHO COMPUTER)\nDialogue: 0,0:27:00.78,0:27:01.63,Default,,0,0,0,,这样做了以后\nDialogue: 0,0:27:02.57,0:27:04.62,Default,,0,0,0,,我真正想要做的\nDialogue: 0,0:27:05.04,0:27:06.49,Default,,0,0,0,,就是先建立一本字典\nDialogue: 0,0:27:08.35,0:27:09.88,Default,,0,0,0,,其中有一些约束\nDialogue: 0,0:27:09.93,0:27:11.20,Default,,0,0,0,,比如 ?D=COMPUTER\nDialogue: 0,0:27:14.35,0:27:18.48,Default,,0,0,0,,而?Z等同于?WHO\nDialogue: 0,0:27:21.70,0:27:23.22,Default,,0,0,0,,我们的匹配器不会那么做\nDialogue: 0,0:27:23.22,0:27:27.00,Default,,0,0,0,,这不是模式和数据的匹配方式\nDialogue: 0,0:27:28.58,0:27:29.72,Default,,0,0,0,,这是在匹配两个模式\nDialogue: 0,0:27:29.74,0:27:31.58,Default,,0,0,0,,并判断它们是否一致\nDialogue: 0,0:27:31.90,0:27:33.48,Default,,0,0,0,,又是什么使它们不一致\nDialogue: 0,0:27:33.48,0:27:36.43,Default,,0,0,0,,换句话说 我们需要的不是一个模式匹配器\nDialogue: 0,0:27:36.96,0:27:38.91,Default,,0,0,0,,而是一种更一般性的东西\nDialogue: 0,0:27:39.13,0:27:40.11,Default,,0,0,0,,就是“合一”算法\nDialogue: 0,0:27:44.42,0:27:48.06,Default,,0,0,0,,“合一”是更为一般化的模式匹配算法\nDialogue: 0,0:27:49.53,0:27:52.17,Default,,0,0,0,,合一算法接收两条模式\nDialogue: 0,0:27:53.23,0:27:57.53,Default,,0,0,0,,它考虑的是：可以找到哪些一般性的元素\nDialogue: 0,0:27:58.20,0:28:00.01,Default,,0,0,0,,用来代换模式中的变量\nDialogue: 0,0:28:02.68,0:28:05.08,Default,,0,0,0,,使得它俩能够同时满足\nDialogue: 0,0:28:05.68,0:28:06.60,Default,,0,0,0,,让我来举个例子\nDialogue: 0,0:28:08.86,0:28:14.49,Default,,0,0,0,,我有一个含有两个元素的模式：(?X ?X)\nDialogue: 0,0:28:15.76,0:28:17.15,Default,,0,0,0,,它描述的是一个二元表\nDialogue: 0,0:28:17.32,0:28:18.64,Default,,0,0,0,,不管元素具体是什么\nDialogue: 0,0:28:18.67,0:28:20.04,Default,,0,0,0,,但两个元素是相同的\nDialogue: 0,0:28:20.40,0:28:22.83,Default,,0,0,0,,我把它与另一个模式进行“合一”\nDialogue: 0,0:28:22.92,0:28:24.62,Default,,0,0,0,,后者描述的是一个二元表\nDialogue: 0,0:28:24.65,0:28:27.61,Default,,0,0,0,,首元素一张由A、?Y、C构成的表\nDialogue: 0,0:28:28.00,0:28:30.14,Default,,0,0,0,,而第二个元素是由A、B、?Z构成的表\nDialogue: 0,0:28:33.07,0:28:34.88,Default,,0,0,0,,那么 合一算法能够告诉我\nDialogue: 0,0:28:34.89,0:28:36.17,Default,,0,0,0,,在生成的字典中\nDialogue: 0,0:28:36.35,0:28:37.96,Default,,0,0,0,,?X必须是(A B C)\nDialogue: 0,0:28:39.34,0:28:41.92,Default,,0,0,0,,?Y必须为B ?Z必须为C\nDialogue: 0,0:28:43.44,0:28:46.28,Default,,0,0,0,,这些是我必须对X、Y以及Z施加的约束\nDialogue: 0,0:28:46.33,0:28:47.58,Default,,0,0,0,,以便让两个模式合一\nDialogue: 0,0:28:48.12,0:28:50.84,Default,,0,0,0,,或者换句话来说 让它匹配这个?X\nDialogue: 0,0:28:51.15,0:28:53.37,Default,,0,0,0,,让它匹配这个?X\nDialogue: 0,0:28:55.28,0:28:57.76,Default,,0,0,0,,合一算法需要能够推断出这些\nDialogue: 0,0:28:58.54,0:29:01.08,Default,,0,0,0,,但是合一算法也会遇到复杂的情况\nDialogue: 0,0:29:01.08,0:29:03.07,Default,,0,0,0,,我可能会询问一些复杂的查询\nDialogue: 0,0:29:03.48,0:29:05.74,Default,,0,0,0,,比如这是一个二元表\nDialogue: 0,0:29:07.00,0:29:08.28,Default,,0,0,0,,其中的元素都是相同的\nDialogue: 0,0:29:08.86,0:29:11.15,Default,,0,0,0,,它要与这个模式进行合一\nDialogue: 0,0:29:12.65,0:29:15.36,Default,,0,0,0,,合一算法也要能够从中推断出\nDialogue: 0,0:29:16.89,0:29:19.57,Default,,0,0,0,,?Y必须为B\nDialogue: 0,0:29:19.57,0:29:22.12,Default,,0,0,0,,因为这两个是一样的\nDialogue: 0,0:29:22.22,0:29:23.52,Default,,0,0,0,,因此?Y就是B\nDialogue: 0,0:29:24.34,0:29:27.53,Default,,0,0,0,,这里 ?V应该为A\nDialogue: 0,0:29:28.94,0:29:30.99,Default,,0,0,0,,只要?Z和?W取值相同\nDialogue: 0,0:29:31.00,0:29:32.43,Default,,0,0,0,,它们就可以是任意值\nDialogue: 0,0:29:35.71,0:29:41.76,Default,,0,0,0,,?X就应该是(B A ?W) 其中?W为任意值\nDialogue: 0,0:29:42.83,0:29:44.68,Default,,0,0,0,,或者是?Z -- 因为?Z和?W是一致的\nDialogue: 0,0:29:44.70,0:29:49.42,Default,,0,0,0,,发现了么 合一算法需要从这些模式中推断出信息\nDialogue: 0,0:29:50.88,0:29:53.52,Default,,0,0,0,,所以你们可能认为 这其中有某种魔法般的推理\nDialogue: 0,0:29:54.27,0:29:55.23,Default,,0,0,0,,但其实并不是\nDialogue: 0,0:29:55.85,0:29:59.88,Default,,0,0,0,,合一算法基本上只是对模式匹配的小小修改\nDialogue: 0,0:30:00.15,0:30:01.85,Default,,0,0,0,,如果你们翻阅教材 就会发现\nDialogue: 0,0:30:02.25,0:30:06.16,Default,,0,0,0,,在模式匹配算法中加入了三到四行代码\nDialogue: 0,0:30:06.49,0:30:08.17,Default,,0,0,0,,来处理对称的情况\nDialogue: 0,0:30:08.28,0:30:10.81,Default,,0,0,0,,还记得吗 模式匹配中有一处代码判断\nDialogue: 0,0:30:11.66,0:30:14.28,Default,,0,0,0,,这个变量匹配一个常量吗？\nDialogue: 0,0:30:14.98,0:30:16.42,Default,,0,0,0,,如果是的话 就在字典中进行检查\nDialogue: 0,0:30:16.42,0:30:18.25,Default,,0,0,0,,在合一算法中只有另一条子句\nDialogue: 0,0:30:18.49,0:30:20.75,Default,,0,0,0,,它判断两个变量是否相匹配\nDialogue: 0,0:30:22.00,0:30:23.42,Default,,0,0,0,,这种情况下你去查询字典\nDialogue: 0,0:30:23.45,0:30:25.68,Default,,0,0,0,,看它们在字典的约束下是否一致\nDialogue: 0,0:30:27.03,0:30:31.13,Default,,0,0,0,,因此 这门语言中的所有“推断”\nDialogue: 0,0:30:31.28,0:30:34.59,Default,,0,0,0,,你会发现它蕴含在规则应用中\nDialogue: 0,0:30:34.99,0:30:37.88,Default,,0,0,0,,更进一步地考察 你会发现在合一算法中\nDialogue: 0,0:30:38.36,0:30:40.32,Default,,0,0,0,,如果更进一步地用“显微镜”观察\nDialogue: 0,0:30:40.56,0:30:43.96,Default,,0,0,0,,基本上就在模式匹配算法中\nDialogue: 0,0:30:44.94,0:30:47.07,Default,,0,0,0,,这其中并没有什么魔法\nDialogue: 0,0:30:47.41,0:30:50.25,Default,,0,0,0,,而你们所见到的“推断”\nDialogue: 0,0:30:50.94,0:30:52.89,Default,,0,0,0,,只是因为其中的递归\nDialogue: 0,0:30:52.92,0:30:55.69,Default,,0,0,0,,它一点一点地回绕MATCH过程\nDialogue: 0,0:30:56.03,0:30:58.03,Default,,0,0,0,,它让这个过程看起来很聪明\nDialogue: 0,0:30:58.44,0:31:00.36,Default,,0,0,0,,但它实际上并不是那么聪明\nDialogue: 0,0:31:02.14,0:31:04.41,Default,,0,0,0,,当然 合一算法需要聪明地识别出一些情况\nDialogue: 0,0:31:04.88,0:31:05.87,Default,,0,0,0,,我来举个例子吧\nDialogue: 0,0:31:11.07,0:31:13.36,Default,,0,0,0,,假设我想要用一个二元表进行合一\nDialogue: 0,0:31:13.48,0:31:14.81,Default,,0,0,0,,(?X ?X)\nDialogue: 0,0:31:17.24,0:31:22.14,Default,,0,0,0,,另一个模式则是 (?Y (a . ?Y))\nDialogue: 0,0:31:24.37,0:31:26.12,Default,,0,0,0,,现在 如果你想一想它所表达的意思\nDialogue: 0,0:31:26.86,0:31:29.71,Default,,0,0,0,,它表示了?X应该跟?Y一致\nDialogue: 0,0:31:30.92,0:31:31.66,Default,,0,0,0,,同时呢\nDialogue: 0,0:31:31.82,0:31:36.16,Default,,0,0,0,,?X又应该跟(A . ?Y)相同\nDialogue: 0,0:31:37.33,0:31:39.45,Default,,0,0,0,,如果你仔细思考它成立的条件\nDialogue: 0,0:31:42.27,0:31:44.71,Default,,0,0,0,,你会发现 ?Y必须是一个由A构成的无穷表\nDialogue: 0,0:31:47.50,0:31:48.35,Default,,0,0,0,,从某种角度来说\nDialogue: 0,0:31:49.21,0:31:52.40,Default,,0,0,0,,为了完成这样的合一\nDialogue: 0,0:31:52.60,0:31:54.84,Default,,0,0,0,,我需要求解一个不动点方程\nDialogue: 0,0:31:55.05,0:32:01.84,Default,,0,0,0,,(CONS 'A Y)=Y\nDialogue: 0,0:32:04.57,0:32:06.96,Default,,0,0,0,,通常来说 --- 我这个例子很简单\nDialogue: 0,0:32:07.29,0:32:08.67,Default,,0,0,0,,但实际进行合一时\nDialogue: 0,0:32:08.97,0:32:11.98,Default,,0,0,0,,我们可能要求解一个任意的不动点方程\nDialogue: 0,0:32:12.01,0:32:13.42,Default,,0,0,0,,(F Y)=Y\nDialogue: 0,0:32:15.53,0:32:17.08,Default,,0,0,0,,你基本上不能保证\nDialogue: 0,0:32:17.10,0:32:19.47,Default,,0,0,0,,在有穷时间内找到解\nDialogue: 0,0:32:20.57,0:32:23.60,Default,,0,0,0,,我们的逻辑语言又该如何处理这类情况呢？\nDialogue: 0,0:32:24.89,0:32:26.48,Default,,0,0,0,,答案就是：“不处理”\nDialogue: 0,0:32:27.16,0:32:28.04,Default,,0,0,0,,它会撒手不干\nDialogue: 0,0:32:28.73,0:32:31.07,Default,,0,0,0,,合一算法中有一处小检查\nDialogue: 0,0:32:31.31,0:32:33.82,Default,,0,0,0,,用来判断是否为困难的情况\nDialogue: 0,0:32:34.44,0:32:38.00,Default,,0,0,0,,也就是 匹配这些东西需要求解不动点方程\nDialogue: 0,0:32:38.65,0:32:40.81,Default,,0,0,0,,遇到这类情况 我就撒手不干\nDialogue: 0,0:32:42.84,0:32:44.65,Default,,0,0,0,,如果不进行这样的检查\nDialogue: 0,0:32:45.00,0:32:45.88,Default,,0,0,0,,会发生什么情况？\nDialogue: 0,0:32:47.99,0:32:49.10,Default,,0,0,0,,大多数情况就是\nDialogue: 0,0:32:49.13,0:32:51.31,Default,,0,0,0,,合一算法会陷入无穷循环\nDialogue: 0,0:32:53.74,0:32:56.54,Default,,0,0,0,,其它的逻辑语言有类似的工作原理\nDialogue: 0,0:32:56.80,0:32:58.14,Default,,0,0,0,,因此这其中没有什么魔法\nDialogue: 0,0:32:58.22,0:32:59.93,Default,,0,0,0,,简单的情况由匹配器完成\nDialogue: 0,0:33:00.10,0:33:01.58,Default,,0,0,0,,困难的情况根本不去处理\nDialogue: 0,0:33:02.96,0:33:05.47,Default,,0,0,0,,这就是这种技术的现状\nDialogue: 0,0:33:11.88,0:33:14.24,Default,,0,0,0,,现在 我来形式化地描述一下\nDialogue: 0,0:33:14.27,0:33:16.38,Default,,0,0,0,,规则系统的运行原理 -- 也就是合一算法\nDialogue: 0,0:33:17.39,0:33:18.75,Default,,0,0,0,,因此 正式的定义就是\nDialogue: 0,0:33:19.20,0:33:20.96,Default,,0,0,0,,应用一条规则\nDialogue: 0,0:33:24.17,0:33:27.13,Default,,0,0,0,,我们需要使用一些之前的术语\nDialogue: 0,0:33:28.27,0:33:32.01,Default,,0,0,0,,我们把向查询的盒子中\nDialogue: 0,0:33:32.88,0:33:34.78,Default,,0,0,0,,塞入字典称作是\nDialogue: 0,0:33:34.81,0:33:38.54,Default,,0,0,0,,相对一个环境或者框架\nDialogue: 0,0:33:39.95,0:33:43.85,Default,,0,0,0,,对这些大型查询求值\nDialogue: 0,0:33:43.85,0:33:45.04,Default,,0,0,0,,因此 当我们谈及“字典”的时候\nDialogue: 0,0:33:45.07,0:33:46.28,Default,,0,0,0,,“字典”究竟是什么？\nDialogue: 0,0:33:46.72,0:33:48.18,Default,,0,0,0,,它是符号的一系列语义\nDialogue: 0,0:33:48.18,0:33:50.22,Default,,0,0,0,,我们把它叫做“框架”或者“环境”\nDialogue: 0,0:33:51.80,0:33:55.97,Default,,0,0,0,,根据环境进行操作 又是什么？\nDialogue: 0,0:33:55.97,0:33:57.42,Default,,0,0,0,,我们把这个叫做“求值”\nDialogue: 0,0:33:58.33,0:34:01.56,Default,,0,0,0,,因此我们就说 应用一条规则的方法是\nDialogue: 0,0:34:01.92,0:34:06.16,Default,,0,0,0,,先通过将给定的查询与规则的结论合一 得到环境\nDialogue: 0,0:34:06.67,0:34:11.58,Default,,0,0,0,,再在该环境中求值相应规则的体\nDialogue: 0,0:34:13.23,0:34:14.51,Default,,0,0,0,,我想要让你们注意的是\nDialogue: 0,0:34:14.80,0:34:17.08,Default,,0,0,0,,这非常像是\nDialogue: 0,0:34:18.16,0:34:21.50,Default,,0,0,0,,元循环求值器以及代换模型\nDialogue: 0,0:34:21.63,0:34:22.73,Default,,0,0,0,,规则的应用就是\nDialogue: 0,0:34:22.86,0:34:28.36,Default,,0,0,0,,在一个环境中求值规则的体\nDialogue: 0,0:34:28.54,0:34:33.13,Default,,0,0,0,,环境是通过将实际参数与形式参数绑定起来得到的\nDialogue: 0,0:34:34.56,0:34:36.41,Default,,0,0,0,,规则、规则的应用、过程的应用\nDialogue: 0,0:34:36.44,0:34:40.41,Default,,0,0,0,,它们在形式上完全相似\nDialogue: 0,0:34:40.57,0:34:42.30,Default,,0,0,0,,尽管它们又非常不同\nDialogue: 0,0:34:43.65,0:34:45.61,Default,,0,0,0,,再一次地出现了EVAL-APPLY循环\nDialogue: 0,0:34:47.29,0:34:49.52,Default,,0,0,0,,EVAL-APPLY\nDialogue: 0,0:34:53.39,0:34:57.39,Default,,0,0,0,,因此通常来说 我们可能会处理一些复合表达式\nDialogue: 0,0:34:57.42,0:34:59.13,Default,,0,0,0,,它们会变成规则的应用\nDialogue: 0,0:35:00.70,0:35:03.28,Default,,0,0,0,,进一步又会产生字典、框架或者环境\nDialogue: 0,0:35:03.31,0:35:04.72,Default,,0,0,0,,不管你要怎么叫它\nDialogue: 0,0:35:05.02,0:35:08.43,Default,,0,0,0,,它们随后又会作为某个大的复合对象的输入\nDialogue: 0,0:35:08.66,0:35:11.77,Default,,0,0,0,,这有它的一部分 并可能有其它规则的应用\nDialogue: 0,0:35:13.58,0:35:15.68,Default,,0,0,0,,这基本上就是相同的循环\nDialogue: 0,0:35:15.72,0:35:18.68,Default,,0,0,0,,尽管这里没有什么东西看起来像过程\nDialogue: 0,0:35:19.68,0:35:21.87,Default,,0,0,0,,这是因为我们创建的语言\nDialogue: 0,0:35:22.08,0:35:25.49,Default,,0,0,0,,它们的组合手段和抽象手段以某种方式展开\nDialogue: 0,0:35:28.77,0:35:29.52,Default,,0,0,0,,通常来说\nDialogue: 0,0:35:29.77,0:35:31.39,Default,,0,0,0,,最顶层所发生的是\nDialogue: 0,0:35:33.79,0:35:35.96,Default,,0,0,0,,数据库中也有一些规则\nDialogue: 0,0:35:36.65,0:35:38.70,Default,,0,0,0,,数据库中的数据也可能是规则\nDialogue: 0,0:35:40.46,0:35:42.06,Default,,0,0,0,,它们用来检查对象是否为真\nDialogue: 0,0:35:42.92,0:35:44.89,Default,,0,0,0,,所以这里可能会有规则检查\nDialogue: 0,0:35:46.75,0:35:48.16,Default,,0,0,0,,然后就会有一些控制结构\nDialogue: 0,0:35:48.19,0:35:50.48,Default,,0,0,0,,用来判断你访问的是规则\nDialogue: 0,0:35:50.51,0:35:51.80,Default,,0,0,0,,还是数据元素\nDialogue: 0,0:35:51.84,0:35:53.12,Default,,0,0,0,,然后不断地把它们扇出来开\nDialogue: 0,0:35:53.35,0:35:55.48,Default,,0,0,0,,所以基本上不可能说清楚\nDialogue: 0,0:35:55.68,0:35:57.69,Default,,0,0,0,,是用什么样的顺序来查询这些东西的\nDialogue: 0,0:35:58.20,0:36:00.27,Default,,0,0,0,,是广度优先还是深度优先\nDialogue: 0,0:36:00.28,0:36:01.64,Default,,0,0,0,,另外一个原因是\nDialogue: 0,0:36:01.66,0:36:05.58,Default,,0,0,0,,我们通过惰性流隐藏了实际执行顺序\nDialogue: 0,0:36:07.69,0:36:11.16,Default,,0,0,0,,因此很难说清楚它的扫描顺序\nDialogue: 0,0:36:11.27,0:36:12.16,Default,,0,0,0,,但真实的是\nDialogue: 0,0:36:12.19,0:36:13.64,Default,,0,0,0,,由于你是在流视图观察它的\nDialogue: 0,0:36:13.90,0:36:15.82,Default,,0,0,0,,而它们最终都要被扫描到\nDialogue: 0,0:36:24.98,0:36:28.15,Default,,0,0,0,,这里还有一个小小的技术问题\nDialogue: 0,0:36:30.88,0:36:33.55,Default,,0,0,0,,假设我在这里输入\nDialogue: 0,0:36:37.53,0:36:41.00,Default,,0,0,0,,假设我输入(BOSS ?Y COMPUTER)\nDialogue: 0,0:36:44.22,0:36:45.78,Default,,0,0,0,,然后就会发生一件有意思的事儿\nDialogue: 0,0:36:45.78,0:36:50.25,Default,,0,0,0,,这里的字典就有一项?Y\nDialogue: 0,0:36:52.73,0:36:57.37,Default,,0,0,0,,而这两个?Y是不相同的\nDialogue: 0,0:36:57.42,0:37:00.62,Default,,0,0,0,,后者是其它人的工作描述\nDialogue: 0,0:37:01.58,0:37:03.80,Default,,0,0,0,,因此 按照输入“照本宣科”地执行的话\nDialogue: 0,0:37:04.22,0:37:06.44,Default,,0,0,0,,我们就会遇到变量冲突的问题\nDialogue: 0,0:37:09.28,0:37:10.48,Default,,0,0,0,,所以我骗了你们一下\nDialogue: 0,0:37:10.93,0:37:13.84,Default,,0,0,0,,注意 我们之前也遇到过同样的问题\nDialogue: 0,0:37:14.27,0:37:15.56,Default,,0,0,0,,具体来说就是\nDialogue: 0,0:37:15.96,0:37:18.36,Default,,0,0,0,,一门语言需要局部变量\nDialogue: 0,0:37:19.24,0:37:21.74,Default,,0,0,0,,当我计算SQUARE和SUM-SQUARES的时候\nDialogue: 0,0:37:21.79,0:37:23.39,Default,,0,0,0,,这两个X应该是不同的\nDialogue: 0,0:37:24.96,0:37:26.32,Default,,0,0,0,,同样的道理\nDialogue: 0,0:37:27.39,0:37:29.77,Default,,0,0,0,,这两个?Y应该也不相同\nDialogue: 0,0:37:31.80,0:37:32.75,Default,,0,0,0,,我们知道该如何解决\nDialogue: 0,0:37:32.78,0:37:34.49,Default,,0,0,0,,就是引入环境模型\nDialogue: 0,0:37:34.51,0:37:37.04,Default,,0,0,0,,我们构建类似于“框架链”一类的东西\nDialogue: 0,0:37:37.71,0:37:39.10,Default,,0,0,0,,还有更加“粗暴”的解决方法\nDialogue: 0,0:37:39.10,0:37:41.73,Default,,0,0,0,,在查询语言中 我们根本不这么做\nDialogue: 0,0:37:41.73,0:37:43.18,Default,,0,0,0,,我们的解决方法非常粗暴\nDialogue: 0,0:37:43.54,0:37:45.93,Default,,0,0,0,,我们规定 每次你在应用一条规则的时候\nDialogue: 0,0:37:47.26,0:37:49.63,Default,,0,0,0,,用一个不会引起冲突的唯一名字\nDialogue: 0,0:37:49.77,0:37:53.50,Default,,0,0,0,,统一地为规则中的所有变量更名\nDialogue: 0,0:37:54.04,0:37:57.10,Default,,0,0,0,,这个从概念上来说更简单\nDialogue: 0,0:37:57.12,0:37:59.24,Default,,0,0,0,,但既粗暴 又不是很有效\nDialogue: 0,0:37:59.97,0:38:01.15,Default,,0,0,0,,但是请注意\nDialogue: 0,0:38:01.39,0:38:04.68,Default,,0,0,0,,如果我们对Lisp中定义的过程也这么处理\nDialogue: 0,0:38:05.50,0:38:08.72,Default,,0,0,0,,那么就不需要环境模型了\nDialogue: 0,0:38:08.75,0:38:11.56,Default,,0,0,0,,如果我们每次在应用一个过程的时候\nDialogue: 0,0:38:11.87,0:38:13.90,Default,,0,0,0,,我们为过程中的所有变量更名\nDialogue: 0,0:38:14.19,0:38:16.28,Default,,0,0,0,,那么我们就不需要担心局部变量了\nDialogue: 0,0:38:16.33,0:38:17.39,Default,,0,0,0,,因为它们不会出现\nDialogue: 0,0:38:19.04,0:38:20.41,Default,,0,0,0,,但这种做法比较低效\nDialogue: 0,0:38:20.91,0:38:23.04,Default,,0,0,0,,在我们的查询语言中同样也比较低效\nDialogue: 0,0:38:23.29,0:38:24.59,Default,,0,0,0,,但我们还是这样做了 并让它保持简单\nDialogue: 0,0:38:25.61,0:38:26.67,Default,,0,0,0,,有问题吗？\nDialogue: 0,0:38:30.88,0:38:33.39,Default,,0,0,0,,学生：您这一小节开始的时候\nDialogue: 0,0:38:33.40,0:38:39.60,Default,,0,0,0,,就强调APPLY-EVAL模型是多么的强大\nDialogue: 0,0:38:39.63,0:38:41.17,Default,,0,0,0,,以至于任何语言都适用\nDialogue: 0,0:38:41.17,0:38:43.39,Default,,0,0,0,,但你又说这门语言将会非常不同\nDialogue: 0,0:38:43.95,0:38:45.13,Default,,0,0,0,,但最后却发现这门语言\nDialogue: 0,0:38:45.58,0:38:47.88,Default,,0,0,0,,就像你指出的那样--也是同样的\nDialogue: 0,0:38:47.88,0:38:49.85,Default,,0,0,0,,我在想 您是否是在论证\nDialogue: 0,0:38:50.48,0:38:54.57,Default,,0,0,0,,所有的语言都可以转化成 规则或过程的应用\nDialogue: 0,0:38:55.12,0:38:55.98,Default,,0,0,0,,或者类似的\nDialogue: 0,0:38:57.07,0:38:58.88,Default,,0,0,0,,教授：可以说 几乎所有语言\nDialogue: 0,0:38:58.92,0:39:00.30,Default,,0,0,0,,我们通过组合手段构建对象\nDialogue: 0,0:39:00.92,0:39:04.40,Default,,0,0,0,,用简单的名字给它们命名\nDialogue: 0,0:39:04.70,0:39:06.86,Default,,0,0,0,,你可以把任何类似的 比如\nDialogue: 0,0:39:07.79,0:39:09.90,Default,,0,0,0,,有一种一般性的表达式\nDialogue: 0,0:39:09.98,0:39:11.40,Default,,0,0,0,,比如说如何计算某数的平方\nDialogue: 0,0:39:12.03,0:39:14.20,Default,,0,0,0,,几乎所有的东西都可以称为“过程”\nDialogue: 0,0:39:14.88,0:39:15.88,Default,,0,0,0,,如果语言中有这么一部分的话\nDialogue: 0,0:39:15.90,0:39:17.24,Default,,0,0,0,,那么你就需要能够展开它们\nDialogue: 0,0:39:18.02,0:39:20.19,Default,,0,0,0,,你需要有某种组织 使得\nDialogue: 0,0:39:20.57,0:39:24.03,Default,,0,0,0,,当你查看这些抽象变量 或者说标签的时候\nDialogue: 0,0:39:24.06,0:39:27.10,Default,,0,0,0,,它们可能代表着某些特定的东西\nDialogue: 0,0:39:28.33,0:39:29.34,Default,,0,0,0,,你必须一直跟踪它们\nDialogue: 0,0:39:29.39,0:39:30.91,Default,,0,0,0,,这就会形成类似于环境的结构\nDialogue: 0,0:39:31.72,0:39:32.54,Default,,0,0,0,,让后当你要\nDialogue: 0,0:39:32.70,0:39:35.26,Default,,0,0,0,,展开复合对象其中的一个部分的时候\nDialogue: 0,0:39:35.80,0:39:37.44,Default,,0,0,0,,你就需要EVAL-APPLY循环了\nDialogue: 0,0:39:39.97,0:39:43.20,Default,,0,0,0,,有很多很多的语言有这样的特点\nDialogue: 0,0:39:43.36,0:39:45.40,Default,,0,0,0,,它们也是按这种方式组织的\nDialogue: 0,0:39:45.59,0:39:47.20,Default,,0,0,0,,而这门语言特殊之处在于\nDialogue: 0,0:39:47.21,0:39:49.50,Default,,0,0,0,,从外界看 并没有“过程”\nDialogue: 0,0:39:50.69,0:39:52.68,Default,,0,0,0,,而当你剖开表层 深入到实现中去\nDialogue: 0,0:39:52.70,0:39:54.24,Default,,0,0,0,,当然 你会发现本质是一样的\nDialogue: 0,0:39:54.87,0:39:56.95,Default,,0,0,0,,但是从外界来看 这是一种非常不同的世界观\nDialogue: 0,0:39:56.95,0:39:58.54,Default,,0,0,0,,你没有计算输入的函数\nDialogue: 0,0:40:03.97,0:40:05.71,Default,,0,0,0,,学生：您之前提到过\nDialogue: 0,0:40:06.60,0:40:09.55,Default,,0,0,0,,当用模式匹配来实现这些规则时\nDialogue: 0,0:40:10.01,0:40:11.42,Default,,0,0,0,,由于使用了流实现延迟求值\nDialogue: 0,0:40:11.45,0:40:12.72,Default,,0,0,0,,所以没有办法知道\nDialogue: 0,0:40:13.37,0:40:15.36,Default,,0,0,0,,对象的求值顺序\nDialogue: 0,0:40:15.58,0:40:15.94,Default,,0,0,0,,教授：是这样的\nDialogue: 0,0:40:15.94,0:40:18.28,Default,,0,0,0,,学生：但这就表明\nDialogue: 0,0:40:18.94,0:40:22.28,Default,,0,0,0,,我们只能表达总是为真的陈述性知识\nDialogue: 0,0:40:22.30,0:40:23.79,Default,,0,0,0,,语言并不支持时间序列\nDialogue: 0,0:40:23.95,0:40:25.47,Default,,0,0,0,,否则的话 后果就会--\nDialogue: 0,0:40:27.39,0:40:28.76,Default,,0,0,0,,教授：是的 非常正确\nDialogue: 0,0:40:28.82,0:40:29.48,Default,,0,0,0,,问题在于\nDialogue: 0,0:40:30.06,0:40:32.60,Default,,0,0,0,,这个本来就是用来处理陈述性知识的\nDialogue: 0,0:40:33.26,0:40:34.81,Default,,0,0,0,,而就我目前所演示的来说 不支持\nDialogue: 0,0:40:35.71,0:40:39.56,Default,,0,0,0,,休息之后我会向你们揭露这其中的丑陋之处\nDialogue: 0,0:40:40.83,0:40:42.60,Default,,0,0,0,,就如我目前所展示的 它只是进行逻辑运算\nDialogue: 0,0:40:43.07,0:40:44.52,Default,,0,0,0,,原理上来说 如果我们做的是逻辑运算\nDialogue: 0,0:40:44.54,0:40:46.81,Default,,0,0,0,,用什么顺序完成并不会造成影响\nDialogue: 0,0:40:48.84,0:40:51.55,Default,,0,0,0,,但是呢\nDialogue: 0,0:40:51.60,0:40:53.61,Default,,0,0,0,,当你在进行一些具有副作用的操作的时候\nDialogue: 0,0:40:53.68,0:40:55.20,Default,,0,0,0,,比如向数据库中添加项\nDialogue: 0,0:40:55.23,0:40:58.16,Default,,0,0,0,,从中取出项 等等操作\nDialogue: 0,0:40:58.75,0:41:00.83,Default,,0,0,0,,你就丧失了这类控制\nDialogue: 0,0:41:01.29,0:41:02.94,Default,,0,0,0,,因此 这就与Prolog完全不同\nDialogue: 0,0:41:02.94,0:41:05.15,Default,,0,0,0,,Prolog有各种功能\nDialogue: 0,0:41:05.16,0:41:07.79,Default,,0,0,0,,能够让你利用求值的顺序\nDialogue: 0,0:41:09.64,0:41:11.77,Default,,0,0,0,,人们也这么来写Prolog\nDialogue: 0,0:41:11.77,0:41:14.04,Default,,0,0,0,,结果发现这样变得非常困难\nDialogue: 0,0:41:14.32,0:41:17.55,Default,,0,0,0,,但如果你是Prolog程序专家 你就可以这么做\nDialogue: 0,0:41:18.59,0:41:20.21,Default,,0,0,0,,但是我认为你们现在并不可以\nDialogue: 0,0:41:20.21,0:41:21.24,Default,,0,0,0,,它相当复杂\nDialogue: 0,0:41:21.72,0:41:23.64,Default,,0,0,0,,因为你们放弃了对事先安排的\nDialogue: 0,0:41:23.77,0:41:25.72,Default,,0,0,0,,求值顺序的控制权\nDialogue: 0,0:41:27.15,0:41:30.16,Default,,0,0,0,,学生：这就表明 当你有一个函数式映射时\nDialogue: 0,0:41:30.67,0:41:32.51,Default,,0,0,0,,而你最初在讲这门课的时候\nDialogue: 0,0:41:32.99,0:41:34.08,Default,,0,0,0,,你说过\nDialogue: 0,0:41:34.67,0:41:36.70,Default,,0,0,0,,我们在表述作为关系的陈述性知识\nDialogue: 0,0:41:37.15,0:41:38.81,Default,,0,0,0,,因为我们讨论的不是输入和输出\nDialogue: 0,0:41:41.21,0:41:43.37,Default,,0,0,0,,教授：这是关于“函数式”的双关语\nDialogue: 0,0:41:43.37,0:41:45.79,Default,,0,0,0,,一种是没有副作用\nDialogue: 0,0:41:46.20,0:41:48.16,Default,,0,0,0,,因此并不依赖于求值的顺序\nDialogue: 0,0:41:48.70,0:41:51.04,Default,,0,0,0,,还有就是数学意义上的“函数”\nDialogue: 0,0:41:51.07,0:41:52.22,Default,,0,0,0,,有关于输入和输出\nDialogue: 0,0:41:52.59,0:41:54.36,Default,,0,0,0,,我想这就是你想表达的双关\nDialogue: 0,0:41:56.51,0:41:58.51,Default,,0,0,0,,学生：我对其中两条语句不太明白\nDialogue: 0,0:41:58.81,0:42:00.70,Default,,0,0,0,,也就是那两条有关BOSS的语句\nDialogue: 0,0:42:01.27,0:42:05.74,Default,,0,0,0,,是不是 第一条查询构建了一个数据库\nDialogue: 0,0:42:05.76,0:42:08.08,Default,,0,0,0,,然后第二条查询--\nDialogue: 0,0:42:09.07,0:42:10.12,Default,,0,0,0,,教授：抱歉\nDialogue: 0,0:42:12.44,0:42:15.16,Default,,0,0,0,,这里的意思是 如果我输入这样的查询\nDialogue: 0,0:42:16.12,0:42:18.44,Default,,0,0,0,,我应该最初就给你们举这个例子\nDialogue: 0,0:42:19.47,0:42:23.52,Default,,0,0,0,,如果我输入(JOB (BITDIDDLE BEN) (COMPUTER WIZARD))\nDialogue: 0,0:42:25.04,0:42:27.77,Default,,0,0,0,,系统会找到一处事实\nDialogue: 0,0:42:28.30,0:42:30.28,Default,,0,0,0,,来完全匹配这条查询\nDialogue: 0,0:42:30.86,0:42:33.28,Default,,0,0,0,,然后输出(JOB (BITDIDDLE BEN) (COMPUTER WIZARD))\nDialogue: 0,0:42:34.22,0:42:35.60,Default,,0,0,0,,如果没找到这样的匹配\nDialogue: 0,0:42:35.69,0:42:36.75,Default,,0,0,0,,它就什么也不输出\nDialogue: 0,0:42:37.40,0:42:39.55,Default,,0,0,0,,我应该这么来表述\nDialogue: 0,0:42:39.56,0:42:42.27,Default,,0,0,0,,这门语言是用来查询某个表述是否为真\nDialogue: 0,0:42:43.40,0:42:45.77,Default,,0,0,0,,这是逻辑式编程的目的之一\nDialogue: 0,0:42:46.41,0:42:49.34,Default,,0,0,0,,输入一条查询 要么得到结果 要么没有\nDialogue: 0,0:42:50.68,0:42:52.38,Default,,0,0,0,,因此 我这里想要演示的是\nDialogue: 0,0:42:52.41,0:42:54.80,Default,,0,0,0,,我想要在介绍合一算法前\nDialogue: 0,0:42:54.83,0:42:56.62,Default,,0,0,0,,举一个简单的例子\nDialogue: 0,0:42:57.48,0:42:58.11,Default,,0,0,0,,所以 我应该说\nDialogue: 0,0:42:58.14,0:43:00.96,Default,,0,0,0,,如果我想要检查 这个是否为真\nDialogue: 0,0:43:01.18,0:43:03.28,Default,,0,0,0,,我就可以将它输入 并看有没有任何输出\nDialogue: 0,0:43:05.16,0:43:06.27,Default,,0,0,0,,学生：然后第二条查询\nDialogue: 0,0:43:06.28,0:43:07.84,Default,,0,0,0,,教授：第二条就是真正意义上的“查询”\nDialogue: 0,0:43:07.88,0:43:09.12,Default,,0,0,0,,学生：好的 真正的查询\nDialogue: 0,0:43:10.77,0:43:13.10,Default,,0,0,0,,教授：在这里它就会输出与?WHO相关的信息\nDialogue: 0,0:43:13.90,0:43:15.74,Default,,0,0,0,,就会有一个框架 存储着\nDialogue: 0,0:43:16.62,0:43:18.81,Default,,0,0,0,,?Z=?WHO ?D=COMPUTER\nDialogue: 0,0:43:19.56,0:43:20.49,Default,,0,0,0,,这个会传递下去\nDialogue: 0,0:43:20.51,0:43:21.95,Default,,0,0,0,,传递到这里的时候\nDialogue: 0,0:43:22.01,0:43:23.25,Default,,0,0,0,,?WHO就会被绑定起来\nDialogue: 0,0:43:26.95,0:43:28.76,Default,,0,0,0,,学生：在合一那里\nDialogue: 0,0:43:29.18,0:43:35.96,Default,,0,0,0,,我还是不太清楚?WHO和?Z之间发生了什么\nDialogue: 0,0:43:36.46,0:43:39.58,Default,,0,0,0,,要进行合一的话 这里的规则说\nDialogue: 0,0:43:42.03,0:43:46.22,Default,,0,0,0,,你说过 两个模式变量之间不能互相绑定\nDialogue: 0,0:43:46.26,0:43:48.08,Default,,0,0,0,,教授：模式匹配器确实不能这样\nDialogue: 0,0:43:48.36,0:43:50.83,Default,,0,0,0,,但对合一算法来说\nDialogue: 0,0:43:51.92,0:43:54.01,Default,,0,0,0,,就是一个有存储三个变量的环境\nDialogue: 0,0:43:56.69,0:43:57.90,Default,,0,0,0,,其中?D=COMPUTER\nDialogue: 0,0:43:58.52,0:44:00.19,Default,,0,0,0,,?Z=?WHO\nDialogue: 0,0:44:01.83,0:44:05.26,Default,,0,0,0,,所以在稍后的匹配过程中\nDialogue: 0,0:44:07.20,0:44:10.38,Default,,0,0,0,,如果?WHO=3\nDialogue: 0,0:44:12.06,0:44:13.66,Default,,0,0,0,,那么当我再查找字典的时候\nDialogue: 0,0:44:14.00,0:44:16.40,Default,,0,0,0,,它会告诉我 因为?Z=?WHO 所以?Z=3\nDialogue: 0,0:44:18.36,0:44:20.44,Default,,0,0,0,,从某种意义上来说 你就只需要修改这一点\nDialogue: 0,0:44:20.46,0:44:21.98,Default,,0,0,0,,就可以把合一算法变成模式匹配器\nDialogue: 0,0:44:22.48,0:44:24.80,Default,,0,0,0,,学生：但是看起来你好像告诉了它 如何进行合一\nDialogue: 0,0:44:24.83,0:44:26.96,Default,,0,0,0,,就像你已经解好了方程 准备好了值\nDialogue: 0,0:44:26.99,0:44:29.23,Default,,0,0,0,,并把它们安排成这样\nDialogue: 0,0:44:29.77,0:44:31.24,Default,,0,0,0,,现在看起来就像是\nDialogue: 0,0:44:31.28,0:44:32.83,Default,,0,0,0,,你传递了一本字典\nDialogue: 0,0:44:32.88,0:44:34.86,Default,,0,0,0,,其中的两个变量是关联起来的\nDialogue: 0,0:44:34.88,0:44:37.23,Default,,0,0,0,,教授：实际上 我们在同时求解它们\nDialogue: 0,0:44:37.52,0:44:39.74,Default,,0,0,0,,这是因为我们想要一下得到整个答案\nDialogue: 0,0:44:40.54,0:44:42.81,Default,,0,0,0,,如果你观察它们是如何被递归地构建的\nDialogue: 0,0:44:42.81,0:44:43.74,Default,,0,0,0,,基本上就是这样了\nDialogue: 0,0:44:44.98,0:44:48.40,Default,,0,0,0,,学生：也就是确实要传递含有两个变量的字典？\nDialogue: 0,0:44:48.40,0:44:49.11,Default,,0,0,0,,教授：是的\nDialogue: 0,0:44:49.11,0:44:49.68,Default,,0,0,0,,学生：然后把它们关联起来？\nDialogue: 0,0:44:50.38,0:44:52.91,Default,,0,0,0,,教授：就像通常的字典那样\nDialogue: 0,0:44:54.35,0:44:56.06,Default,,0,0,0,,学生：你在讨论合一算法的时候\nDialogue: 0,0:44:56.09,0:45:00.19,Default,,0,0,0,,你说过在某些情况下\nDialogue: 0,0:45:00.75,0:45:03.98,Default,,0,0,0,,合一不能够完成\nDialogue: 0,0:45:04.03,0:45:04.30,Default,,0,0,0,,教授：是的\nDialogue: 0,0:45:04.97,0:45:08.46,Default,,0,0,0,,学生：那么 是否可以通过编写规则\nDialogue: 0,0:45:09.16,0:45:15.93,Default,,0,0,0,,或者 写入那些事先知道可解的形式\nDialogue: 0,0:45:16.48,0:45:18.54,Default,,0,0,0,,来使得合一算法能够完成\nDialogue: 0,0:45:18.76,0:45:22.94,Default,,0,0,0,,是否可以在规则中添加一些属性\nDialogue: 0,0:45:23.18,0:45:25.45,Default,,0,0,0,,或者向输入的形式中添加属性\nDialogue: 0,0:45:25.82,0:45:29.04,Default,,0,0,0,,来避免无法进行合一的窘境\nDialogue: 0,0:45:29.18,0:45:31.15,Default,,0,0,0,,PROFESSOR: 我想 你也同意\nDialogue: 0,0:45:31.47,0:45:35.26,Default,,0,0,0,,用非常受限的方式来编写查询\nDialogue: 0,0:45:35.60,0:45:36.67,Default,,0,0,0,,看 你遇到的是\nDialogue: 0,0:45:36.88,0:45:39.12,Default,,0,0,0,,仔细看 你遇到问题是在\nDialogue: 0,0:45:39.68,0:45:44.25,Default,,0,0,0,,用像这样的东西去匹配\nDialogue: 0,0:45:44.59,0:45:47.20,Default,,0,0,0,,具有这样结构的模式时\nDialogue: 0,0:45:47.55,0:45:55.30,Default,,0,0,0,,比如((A ?Y B) ?Y)\nDialogue: 0,0:45:58.98,0:46:01.48,Default,,0,0,0,,这是你可能遇到问题的一个地方\nDialogue: 0,0:46:03.07,0:46:05.80,Default,,0,0,0,,学生：所以你可以在语法层次上处理它么？\nDialogue: 0,0:46:06.14,0:46:08.76,Default,,0,0,0,,教授：你可以在写查询时\nDialogue: 0,0:46:08.76,0:46:10.49,Default,,0,0,0,,注意你的规则\nDialogue: 0,0:46:11.90,0:46:14.08,Default,,0,0,0,,学生：这个问题应该由\nDialogue: 0,0:46:14.11,0:46:16.27,Default,,0,0,0,,数据库的构建者考虑么？\nDialogue: 0,0:46:16.57,0:46:17.80,Default,,0,0,0,,教授：这个问题\nDialogue: 0,0:46:19.93,0:46:22.01,Default,,0,0,0,,不完全是数据库的构建者\nDialogue: 0,0:46:22.04,0:46:23.61,Default,,0,0,0,,或者是表述规则的人\nDialogue: 0,0:46:24.01,0:46:25.31,Default,,0,0,0,,所需要考虑的\nDialogue: 0,0:46:25.80,0:46:29.79,Default,,0,0,0,,当你们仔细审查合一算法的代码时\nDialogue: 0,0:46:29.92,0:46:31.87,Default,,0,0,0,,你们会发现\nDialogue: 0,0:46:32.41,0:46:34.76,Default,,0,0,0,,它实际上在查询一个字典\nDialogue: 0,0:46:34.94,0:46:36.83,Default,,0,0,0,,它会问 ?Y的取值应该是什么？\nDialogue: 0,0:46:37.26,0:46:41.42,Default,,0,0,0,,?Y应该是一个含有自包含的表达式么？\nDialogue: 0,0:46:41.96,0:46:43.26,Default,,0,0,0,,这时候 合一算法就会说\nDialogue: 0,0:46:43.28,0:46:46.24,Default,,0,0,0,,哦 我正在求解一个不动点方程\nDialogue: 0,0:46:46.24,0:46:46.99,Default,,0,0,0,,我还是放弃吧\nDialogue: 0,0:46:48.59,0:46:51.91,Default,,0,0,0,,学生：你区分过数据库中的规则\nDialogue: 0,0:46:51.91,0:46:56.48,Default,,0,0,0,,这些规则是加入数据库的么？\nDialogue: 0,0:46:56.95,0:46:57.36,Default,,0,0,0,,教授：是的\nDialogue: 0,0:46:57.87,0:46:58.87,Default,,0,0,0,,我应该这么来说\nDialogue: 0,0:46:58.87,0:47:00.33,Default,,0,0,0,,你们可以把规则看作\nDialogue: 0,0:47:00.60,0:47:02.65,Default,,0,0,0,,数据库中的其它东西\nDialogue: 0,0:47:03.71,0:47:06.81,Default,,0,0,0,,如果你想要检查数据库中需要检查的东西\nDialogue: 0,0:47:06.83,0:47:09.44,Default,,0,0,0,,它们就是存在于数据库中的虚拟事实\nDialogue: 0,0:47:09.44,0:47:12.32,Default,,0,0,0,,学生：但是在这个解释中\nDialogue: 0,0:47:12.43,0:47:17.26,Default,,0,0,0,,你就已经区分了数据库和规则本身\nDialogue: 0,0:47:18.23,0:47:19.90,Default,,0,0,0,,教授：是的 我应该不这么来说\nDialogue: 0,0:47:20.49,0:47:23.31,Default,,0,0,0,,这样做的唯一理由就是实现\nDialogue: 0,0:47:23.54,0:47:24.67,Default,,0,0,0,,当你们查看具体实现时\nDialogue: 0,0:47:24.68,0:47:27.50,Default,,0,0,0,,会发现其中有部分用来检查数据库中的\nDialogue: 0,0:47:27.55,0:47:29.85,Default,,0,0,0,,基本断言或者规则\nDialogue: 0,0:47:30.47,0:47:32.72,Default,,0,0,0,,这其中的真正原因就是\nDialogue: 0,0:47:32.78,0:47:34.56,Default,,0,0,0,,你不知道查询结果是以什么顺序输出的\nDialogue: 0,0:47:34.96,0:47:40.46,Default,,0,0,0,,而规则数据库和数据数据库\nDialogue: 0,0:47:40.48,0:47:43.68,Default,,0,0,0,,是通过某种延迟求值的方式合并的\nDialogue: 0,0:47:44.60,0:47:46.80,Default,,0,0,0,,这就使得顺序变得非常复杂\nDialogue: 0,0:47:55.44,0:47:56.09,Default,,0,0,0,,那好 我们休息一下\nDialogue: 0,0:47:56.30,0:48:09.90,Default,,0,0,0,,[音乐]\nDialogue: 0,0:48:10.04,0:48:14.41,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:18.68,0:48:22.09,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:48:22.09,0:48:25.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:26.00,0:48:29.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 II\nDialogue: 0,0:48:33.16,0:48:35.37,Default,,0,0,0,,我们已经学习了逻辑式语言与\nDialogue: 0,0:48:35.39,0:48:36.41,Default,,0,0,0,,规则系统的运行原理\nDialogue: 0,0:48:37.23,0:48:39.37,Default,,0,0,0,,现在 让我们来探讨一个更加深刻的问题\nDialogue: 0,0:48:40.12,0:48:41.28,Default,,0,0,0,,来看下它们意味着什么\nDialogue: 0,0:48:43.18,0:48:46.86,Default,,0,0,0,,这把我们带入到整个查询语言中\nDialogue: 0,0:48:46.99,0:48:48.67,Default,,0,0,0,,最微妙的部分\nDialogue: 0,0:48:49.21,0:48:53.07,Default,,0,0,0,,也就是它看起来与想象中不同的地方\nDialogue: 0,0:48:53.57,0:48:56.22,Default,,0,0,0,,AND、OR以及NOT\nDialogue: 0,0:48:57.02,0:48:58.88,Default,,0,0,0,,以及规则的逻辑蕴含\nDialogue: 0,0:48:59.69,0:49:06.64,Default,,0,0,0,,并不是逻辑学中的与、或、非以及蕴含\nDialogue: 0,0:49:07.69,0:49:09.71,Default,,0,0,0,,让我来举一个实例\nDialogue: 0,0:49:09.91,0:49:12.22,Default,,0,0,0,,当然 如果我们有两个逻辑命题\nDialogue: 0,0:49:12.40,0:49:19.44,Default,,0,0,0,,那么(AND P Q)就应该\nDialogue: 0,0:49:20.00,0:49:22.59,Default,,0,0,0,,等同于(AND Q P)\nDialogue: 0,0:49:23.10,0:49:24.51,Default,,0,0,0,,而(OR P Q)就应该\nDialogue: 0,0:49:24.78,0:49:26.51,Default,,0,0,0,,等同于(OR Q P)\nDialogue: 0,0:49:28.67,0:49:30.09,Default,,0,0,0,,但我们来看看这里\nDialogue: 0,0:49:30.10,0:49:32.01,Default,,0,0,0,,这里是一个例子\nDialogue: 0,0:49:32.18,0:49:36.16,Default,,0,0,0,,来看看 在我们的数据库中\nDialogue: 0,0:49:36.28,0:49:40.14,Default,,0,0,0,,如何表示某人的级别高于他人\nDialogue: 0,0:49:40.14,0:49:42.89,Default,,0,0,0,,我们定义(OUTRANKED-BY ?S ?B)为\nDialogue: 0,0:49:44.64,0:49:48.62,Default,,0,0,0,,或者S是B的上司\nDialogue: 0,0:49:49.63,0:49:51.07,Default,,0,0,0,,或者这其中有某个中间经理M\nDialogue: 0,0:49:51.10,0:49:55.82,Default,,0,0,0,,其中S是M的上司 M的级别又比B高\nDialogue: 0,0:49:59.64,0:50:02.31,Default,,0,0,0,,这是定义OUTRANKED-BY的一种方式\nDialogue: 0,0:50:02.31,0:50:04.16,Default,,0,0,0,,或者我们可以原封不动地写过来\nDialogue: 0,0:50:05.08,0:50:06.91,Default,,0,0,0,,除了在最底部的这里\nDialogue: 0,0:50:07.21,0:50:09.88,Default,,0,0,0,,我们颠倒一下这两个子句的顺序\nDialogue: 0,0:50:11.63,0:50:12.99,Default,,0,0,0,,当然 如果它们都是逻辑表达式的话\nDialogue: 0,0:50:13.00,0:50:14.88,Default,,0,0,0,,它们应该表示的是相同的东西\nDialogue: 0,0:50:16.69,0:50:17.31,Default,,0,0,0,,然而\nDialogue: 0,0:50:17.71,0:50:19.61,Default,,0,0,0,,在我们这个特定的实现中\nDialogue: 0,0:50:19.64,0:50:22.88,Default,,0,0,0,,如果你查询(OUTRANDKED-BY ?WHO (BITDIIDLE BEN))\nDialogue: 0,0:50:23.48,0:50:25.36,Default,,0,0,0,,你会发现 这条规则\nDialogue: 0,0:50:26.76,0:50:28.72,Default,,0,0,0,,会完美地生成答案\nDialogue: 0,0:50:30.04,0:50:31.98,Default,,0,0,0,,然而 这条规则会陷入无穷循环\nDialogue: 0,0:50:34.11,0:50:36.27,Default,,0,0,0,,其中的原因就是\nDialogue: 0,0:50:36.33,0:50:40.33,Default,,0,0,0,,这条规则会问谁比BEN BITDIDDLE级别高？\nDialogue: 0,0:50:41.92,0:50:43.53,Default,,0,0,0,,它试图寻找一个S\nDialogue: 0,0:50:43.88,0:50:46.22,Default,,0,0,0,,使得S比B的级别更高 其中B是BEN BITDIDDLE\nDialogue: 0,0:50:47.50,0:50:49.63,Default,,0,0,0,,这会在一个子问题中重复出现\nDialogue: 0,0:50:50.33,0:50:51.98,Default,,0,0,0,,找到一个M\nDialogue: 0,0:50:52.24,0:50:54.57,Default,,0,0,0,,使得M的级别高于BEN BITDIDDLE\nDialogue: 0,0:50:55.61,0:50:57.36,Default,,0,0,0,,而对M没有限制\nDialogue: 0,0:50:58.56,0:51:00.40,Default,,0,0,0,,这就相当于为了解决这个问题\nDialogue: 0,0:51:01.42,0:51:03.29,Default,,0,0,0,,我就还需要求解同样的问题\nDialogue: 0,0:51:04.57,0:51:07.23,Default,,0,0,0,,在把它解出来后 我才检查SUPERVISOR关系\nDialogue: 0,0:51:08.00,0:51:09.16,Default,,0,0,0,,然而这条规则没有这样的问题\nDialogue: 0,0:51:09.18,0:51:12.35,Default,,0,0,0,,因为在它尝试找出这条OUTRANKED-BY规则之前\nDialogue: 0,0:51:12.94,0:51:15.26,Default,,0,0,0,,在这里已经对M施加过约束了\nDialogue: 0,0:51:18.38,0:51:20.94,Default,,0,0,0,,随意 这两条规则理论上是相同的\nDialogue: 0,0:51:20.99,0:51:22.67,Default,,0,0,0,,但实际上 其中一条会陷入无穷循环\nDialogue: 0,0:51:22.86,0:51:25.04,Default,,0,0,0,,而另一条不会\nDialogue: 0,0:51:26.72,0:51:29.77,Default,,0,0,0,,通过这个非常极端的例子\nDialogue: 0,0:51:29.79,0:51:32.65,Default,,0,0,0,,你会发现在逻辑式程序设计中\nDialogue: 0,0:51:34.28,0:51:38.70,Default,,0,0,0,,如果你改变了AND或OR所连接子句的顺序\nDialogue: 0,0:51:39.34,0:51:41.58,Default,,0,0,0,,你会发现效率上的巨大差异\nDialogue: 0,0:51:42.24,0:51:43.21,Default,,0,0,0,,我们刚刚就看到了\nDialogue: 0,0:51:43.55,0:51:46.54,Default,,0,0,0,,在无穷循环方面的巨大差异\nDialogue: 0,0:51:49.19,0:51:51.74,Default,,0,0,0,,同样的 这也跟输入规则\nDialogue: 0,0:51:52.00,0:51:53.31,Default,,0,0,0,,的顺序有关\nDialogue: 0,0:51:54.07,0:51:56.48,Default,,0,0,0,,向数据库查询规则的顺序\nDialogue: 0,0:51:56.70,0:51:59.95,Default,,0,0,0,,会极大程度上影响效率：比如得到答案\nDialogue: 0,0:52:00.46,0:52:02.60,Default,,0,0,0,,或者在某些顺序下陷入无穷循环\nDialogue: 0,0:52:03.84,0:52:07.29,Default,,0,0,0,,这些都跟\nDialogue: 0,0:52:07.63,0:52:10.04,Default,,0,0,0,,你检查这些规则的顺序有关\nDialogue: 0,0:52:10.95,0:52:14.41,Default,,0,0,0,,有些规则的蕴含路径会相当的长\nDialogue: 0,0:52:14.44,0:52:16.06,Default,,0,0,0,,而另外一些不会\nDialogue: 0,0:52:16.44,0:52:17.68,Default,,0,0,0,,但你事先并不知道\nDialogue: 0,0:52:17.72,0:52:19.16,Default,,0,0,0,,哪一个长 哪一个短\nDialogue: 0,0:52:19.30,0:52:21.48,Default,,0,0,0,,有很多研究都与此有关\nDialogue: 0,0:52:22.16,0:52:23.76,Default,,0,0,0,,其中大多数都是想通过\nDialogue: 0,0:52:23.95,0:52:26.97,Default,,0,0,0,,用并行的方法来实现逻辑式程序设计语言\nDialogue: 0,0:52:27.32,0:52:29.90,Default,,0,0,0,,某种意义上来说 就是并行地检查所有规则\nDialogue: 0,0:52:30.36,0:52:32.80,Default,,0,0,0,,一旦有一条搜索得到答案 就返回结果\nDialogue: 0,0:52:33.04,0:52:34.99,Default,,0,0,0,,如果某条路径陷入了无穷的推导\nDialogue: 0,0:52:35.02,0:52:38.25,Default,,0,0,0,,那么 你只需知道 内存和处理器都非常廉价\nDialogue: 0,0:52:38.28,0:52:40.49,Default,,0,0,0,,让它们根据你的需要一直搜寻就好了\nDialogue: 0,0:52:43.47,0:52:44.83,Default,,0,0,0,,尽管如此 与真正的逻辑相比\nDialogue: 0,0:52:45.18,0:52:50.49,Default,,0,0,0,,这门逻辑式语言还有一个更深刻的问题\nDialogue: 0,0:52:50.68,0:52:52.52,Default,,0,0,0,,我给你们演示的例子\nDialogue: 0,0:52:52.97,0:52:54.80,Default,,0,0,0,,只是会陷入无穷循环\nDialogue: 0,0:52:55.37,0:52:56.99,Default,,0,0,0,,但至少不会给你错误的答案\nDialogue: 0,0:52:58.37,0:53:03.64,Default,,0,0,0,,当我们开始严肃地把这门逻辑式语言\nDialogue: 0,0:53:03.68,0:53:05.24,Default,,0,0,0,,与真正的经典逻辑作比较时\nDialogue: 0,0:53:05.71,0:53:08.46,Default,,0,0,0,,就会发现其中最深层次的问题\nDialogue: 0,0:53:09.49,0:53:12.43,Default,,0,0,0,,让我们来看看真正的经典逻辑\nDialogue: 0,0:53:13.71,0:53:21.04,Default,,0,0,0,,所有的人类都是凡人\nDialogue: 0,0:53:22.35,0:53:23.45,Default,,0,0,0,,相当经典的逻辑命题\nDialogue: 0,0:53:24.39,0:53:28.67,Default,,0,0,0,,然后我们就依照最经典的传统\nDialogue: 0,0:53:29.24,0:53:32.46,Default,,0,0,0,,我们按照最传统的方式来做\nDialogue: 0,0:53:32.67,0:53:37.16,Default,,0,0,0,,所有的希腊人都是人类\nDialogue: 0,0:53:40.49,0:53:46.06,Default,,0,0,0,,苏格拉底是希腊人\nDialogue: 0,0:53:48.17,0:53:49.21,Default,,0,0,0,,然后我们又该写什么呢？\nDialogue: 0,0:53:49.21,0:53:51.89,Default,,0,0,0,,经典逻辑中有一个三点符号\nDialogue: 0,0:53:51.89,0:53:54.33,Default,,0,0,0,,因此 我们得到了一个三段论\nDialogue: 0,0:53:54.64,0:53:59.55,Default,,0,0,0,,苏格拉底是凡人\nDialogue: 0,0:54:01.36,0:54:04.91,Default,,0,0,0,,这些都是真正的经典逻辑\nDialogue: 0,0:54:05.88,0:54:11.05,Default,,0,0,0,,把它跟我们经典逻辑数据库比较一下\nDialogue: 0,0:54:12.40,0:54:14.46,Default,,0,0,0,,这是一个经典逻辑数据库\nDialogue: 0,0:54:16.27,0:54:17.48,Default,,0,0,0,,(GREEK SOCRATES)\nDialogue: 0,0:54:18.03,0:54:18.84,Default,,0,0,0,,(GREEK PLATO)\nDialogue: 0,0:54:19.60,0:54:20.40,Default,,0,0,0,,(GREEK ZEUS)\nDialogue: 0,0:54:20.84,0:54:21.98,Default,,0,0,0,,(GOD ZEUS)\nDialogue: 0,0:54:24.12,0:54:29.96,Default,,0,0,0,,所有的人类都是凡人\nDialogue: 0,0:54:30.54,0:54:32.12,Default,,0,0,0,,为了证明某人是平凡的\nDialogue: 0,0:54:32.16,0:54:33.60,Default,,0,0,0,,只需要证明他是人类\nDialogue: 0,0:54:34.65,0:54:35.90,Default,,0,0,0,,所有的人类都是不可靠的\nDialogue: 0,0:54:38.90,0:54:40.98,Default,,0,0,0,,并且说所有的希腊人都是人类 并不正确\nDialogue: 0,0:54:40.98,0:54:44.41,Default,,0,0,0,,这条规则说 所有不是神的希腊人都是人类\nDialogue: 0,0:54:45.71,0:54:47.04,Default,,0,0,0,,因此为了证明某人是人类\nDialogue: 0,0:54:47.07,0:54:48.89,Default,,0,0,0,,只需要说明他是一个希腊人 并且不是神\nDialogue: 0,0:54:49.32,0:54:52.88,Default,,0,0,0,,任何一个希腊神的住址是奥林匹斯山\nDialogue: 0,0:54:54.32,0:54:57.16,Default,,0,0,0,,这就是一个小型经典逻辑数据库\nDialogue: 0,0:54:57.39,0:54:59.32,Default,,0,0,0,,确实 它运行得相当好\nDialogue: 0,0:54:59.49,0:55:02.09,Default,,0,0,0,,如果我们向其询问\nDialogue: 0,0:55:03.47,0:55:06.57,Default,,0,0,0,,苏格拉底是凡人么 不可靠么？\nDialogue: 0,0:55:06.91,0:55:07.69,Default,,0,0,0,,它会输出：是\nDialogue: 0,0:55:07.77,0:55:09.71,Default,,0,0,0,,柏拉图是凡人并且不可靠么？\nDialogue: 0,0:55:09.71,0:55:10.24,Default,,0,0,0,,它会回答：是\nDialogue: 0,0:55:10.68,0:55:12.21,Default,,0,0,0,,如果我们问宙斯是凡人么\nDialogue: 0,0:55:12.21,0:55:13.23,Default,,0,0,0,,它什么都不会找到\nDialogue: 0,0:55:14.90,0:55:15.96,Default,,0,0,0,,运行得非常完美\nDialogue: 0,0:55:16.54,0:55:20.12,Default,,0,0,0,,然而 如果我们想要把它扩展一下\nDialogue: 0,0:55:20.12,0:55:23.05,Default,,0,0,0,,让我们来定义一下什么是“完美生命体”\nDialogue: 0,0:55:23.82,0:55:27.21,Default,,0,0,0,,我们把规则PERFECT定义为\nDialogue: 0,0:55:34.05,0:55:35.48,Default,,0,0,0,,我想这样来定义是正确的\nDialogue: 0,0:55:35.48,0:55:38.14,Default,,0,0,0,,如果你熟悉中世纪经院哲学\nDialogue: 0,0:55:38.44,0:55:40.17,Default,,0,0,0,,我想所谓“完美生命体”一定\nDialogue: 0,0:55:40.68,0:55:42.65,Default,,0,0,0,,既不是凡人 又不会不可靠\nDialogue: 0,0:55:44.10,0:55:56.84,Default,,0,0,0,,(AND (NOT (MORTAL ?X)) (NOT (FALLIBLE ?X)))\nDialogue: 0,0:55:59.30,0:56:00.89,Default,,0,0,0,,这样 我们就定义了一个规则\nDialogue: 0,0:56:02.67,0:56:04.36,Default,,0,0,0,,来告诉系统 什么是“完美生命体”\nDialogue: 0,0:56:05.79,0:56:07.69,Default,,0,0,0,,现在 我们就要\nDialogue: 0,0:56:08.06,0:56:10.17,Default,,0,0,0,,询问所有“完美生命体”的地址\nDialogue: 0,0:56:11.48,0:56:22.30,Default,,0,0,0,,(AND (ADDRESS ?X ?Y) (PERFECT ?X))\nDialogue: 0,0:56:23.48,0:56:24.97,Default,,0,0,0,,在这里 我们生成了\nDialogue: 0,0:56:24.99,0:56:27.80,Default,,0,0,0,,世界上最独有的邮件列表\nDialogue: 0,0:56:30.16,0:56:32.20,Default,,0,0,0,,为了查询所有完美生命体的地址\nDialogue: 0,0:56:32.24,0:56:33.47,Default,,0,0,0,,我们会输入像这样的查询\nDialogue: 0,0:56:33.83,0:56:35.44,Default,,0,0,0,,或者像这样输入\nDialogue: 0,0:56:36.24,0:56:50.57,Default,,0,0,0,,(AND (PERFECT ?X) (ADDRESS ?X ?Y))\nDialogue: 0,0:56:52.06,0:56:54.96,Default,,0,0,0,,假设我们把它输入进去 并尝试查询\nDialogue: 0,0:56:55.19,0:56:56.76,Default,,0,0,0,,这条查询会给我们答案\nDialogue: 0,0:56:57.65,0:57:00.00,Default,,0,0,0,,这条查询会输出：奥林匹斯山\nDialogue: 0,0:57:04.23,0:57:06.57,Default,,0,0,0,,而这条查询 什么也不会输出\nDialogue: 0,0:57:06.74,0:57:09.58,Default,,0,0,0,,它找不到完美生命体的地址\nDialogue: 0,0:57:11.64,0:57:12.51,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:57:12.51,0:57:13.44,Default,,0,0,0,,这又为什么不同？\nDialogue: 0,0:57:14.23,0:57:15.69,Default,,0,0,0,,这个问题跟无穷循环没什么关系\nDialogue: 0,0:57:15.69,0:57:17.08,Default,,0,0,0,,这个的问题是答案不相同\nDialogue: 0,0:57:19.48,0:57:20.09,Default,,0,0,0,,原因就是\nDialogue: 0,0:57:20.38,0:57:22.32,Default,,0,0,0,,如果你们还记得NOT的实现的话\nDialogue: 0,0:57:23.50,0:57:24.84,Default,,0,0,0,,NOT是作为一个过滤器\nDialogue: 0,0:57:25.88,0:57:29.00,Default,,0,0,0,,NOT会接收一本字典\nDialogue: 0,0:57:29.05,0:57:31.56,Default,,0,0,0,,里面有可行解构成的框架\nDialogue: 0,0:57:31.79,0:57:33.16,Default,,0,0,0,,然后过滤出那些\nDialogue: 0,0:57:33.29,0:57:34.94,Default,,0,0,0,,满足某个条件的解\nDialogue: 0,0:57:34.97,0:57:36.11,Default,,0,0,0,,这就是我如何实现NOT的\nDialogue: 0,0:57:36.92,0:57:38.43,Default,,0,0,0,,如果你们仔细想想其中的原理\nDialogue: 0,0:57:40.11,0:57:42.65,Default,,0,0,0,,我创建了一个查询盒子\nDialogue: 0,0:57:43.32,0:57:47.39,Default,,0,0,0,,ADDRESS盒子的输出作为了PERFECT的输入\nDialogue: 0,0:57:50.29,0:57:51.00,Default,,0,0,0,,这就使得\nDialogue: 0,0:57:51.32,0:57:53.26,Default,,0,0,0,,ADDRESS盒子会创建出\nDialogue: 0,0:57:53.32,0:57:54.83,Default,,0,0,0,,我知道地址的人\nDialogue: 0,0:57:55.29,0:57:57.64,Default,,0,0,0,,这些都会被PERFECT中的NOT给过滤掉\nDialogue: 0,0:57:59.88,0:58:04.19,Default,,0,0,0,,所以它会丢弃掉那些满足平凡的或者不可靠的数据\nDialogue: 0,0:58:04.91,0:58:06.38,Default,,0,0,0,,而对于另外一种顺序来说\nDialogue: 0,0:58:06.73,0:58:09.12,Default,,0,0,0,,我以一个空框架开始的\nDialogue: 0,0:58:09.52,0:58:12.35,Default,,0,0,0,,但是这里PERFECT没有可以给NOT过滤的东西\nDialogue: 0,0:58:12.38,0:58:13.98,Default,,0,0,0,,所以这里不会有什么输出\nDialogue: 0,0:58:18.83,0:58:21.50,Default,,0,0,0,,这也就导致没有东西输入到ADDRESS中\nDialogue: 0,0:58:21.94,0:58:23.15,Default,,0,0,0,,因此 我得不到答案\nDialogue: 0,0:58:23.93,0:58:27.04,Default,,0,0,0,,在强调一下 这是因为NOT不会生成任何东西\nDialogue: 0,0:58:27.44,0:58:28.80,Default,,0,0,0,,NOT只会丢弃数据\nDialogue: 0,0:58:29.08,0:58:30.51,Default,,0,0,0,,如果我不向NOT传递东西的话\nDialogue: 0,0:58:30.52,0:58:31.74,Default,,0,0,0,,它也就不会输出\nDialogue: 0,0:58:32.02,0:58:33.77,Default,,0,0,0,,这样我就得到了错误的答案\nDialogue: 0,0:58:37.20,0:58:37.97,Default,,0,0,0,,我们又该如何修复它呢？\nDialogue: 0,0:58:37.97,0:58:39.07,Default,,0,0,0,,当然 有很多办法\nDialogue: 0,0:58:39.36,0:58:40.91,Default,,0,0,0,,你可能认为 现在这样有点愚蠢\nDialogue: 0,0:58:41.41,0:58:44.90,Default,,0,0,0,,为什么要一开始就执行NOT呢？\nDialogue: 0,0:58:44.96,0:58:47.48,Default,,0,0,0,,想要正确地实现NOT\nDialogue: 0,0:58:47.84,0:58:50.08,Default,,0,0,0,,就是要认识到当你遇到NOT时\nDialogue: 0,0:58:50.33,0:58:52.09,Default,,0,0,0,,你应该首先生成好答案\nDialogue: 0,0:58:52.80,0:58:54.97,Default,,0,0,0,,然后通过字典把它们传递过来\nDialogue: 0,0:58:55.52,0:58:57.85,Default,,0,0,0,,然后再最后再做过滤\nDialogue: 0,0:58:58.56,0:59:02.01,Default,,0,0,0,,有些按照这种方式实现的逻辑式语言\nDialogue: 0,0:59:02.41,0:59:04.05,Default,,0,0,0,,能够解决这个问题\nDialogue: 0,0:59:06.80,0:59:08.97,Default,,0,0,0,,然而 还有一个更深刻的问题\nDialogue: 0,0:59:09.60,0:59:11.53,Default,,0,0,0,,也就是 哪个才是正确答案呢？\nDialogue: 0,0:59:12.53,0:59:14.24,Default,,0,0,0,,是奥林匹斯山 还是没有呢？\nDialogue: 0,0:59:15.37,0:59:18.73,Default,,0,0,0,,你可能会认为是奥林匹斯山\nDialogue: 0,0:59:18.76,0:59:20.73,Default,,0,0,0,,毕竟 宙斯在数据库中\nDialogue: 0,0:59:22.52,0:59:25.10,Default,,0,0,0,,宙斯不是平凡的 也不是不可靠的\nDialogue: 0,0:59:29.55,0:59:32.44,Default,,0,0,0,,因此你可能会认为宙斯满足\nDialogue: 0,0:59:34.30,0:59:44.03,Default,,0,0,0,,(NOT (MORTAL ZEUS))或者(NOT (FALLIBLE ZEUS))\nDialogue: 0,0:59:44.12,0:59:45.85,Default,,0,0,0,,但我们实际来看一看数据库\nDialogue: 0,0:59:47.92,0:59:48.46,Default,,0,0,0,,来看一下\nDialogue: 0,0:59:49.36,0:59:53.24,Default,,0,0,0,,它要如何知道宙斯不是不可靠的？\nDialogue: 0,0:59:54.81,0:59:56.11,Default,,0,0,0,,这里面没有关于它的知识\nDialogue: 0,0:59:57.93,0:59:59.66,Default,,0,0,0,,里面只能得到人类是不可靠的\nDialogue: 0,1:00:02.16,1:00:04.12,Default,,0,0,0,,它又如何知道宙斯不是不可靠的呢？\nDialogue: 0,1:00:04.48,1:00:05.93,Default,,0,0,0,,这其中没有相关的规则\nDialogue: 0,1:00:07.98,1:00:11.00,Default,,0,0,0,,它只是说 我没有这样的规则\nDialogue: 0,1:00:11.68,1:00:14.06,Default,,0,0,0,,我只能通过某人是人类来推断出他是平凡的\nDialogue: 0,1:00:14.08,1:00:15.68,Default,,0,0,0,,这也是它所知道关于“平凡”的所有东西\nDialogue: 0,1:00:16.69,1:00:19.85,Default,,0,0,0,,然而 如果你还记得古典神话的话\nDialogue: 0,1:00:19.87,1:00:23.48,Default,,0,0,0,,你就知道 古希腊众神是不平凡的 但都不可靠\nDialogue: 0,1:00:25.05,1:00:28.65,Default,,0,0,0,,所以 不能通过这些规则得到答案\nDialogue: 0,1:00:30.85,1:00:32.10,Default,,0,0,0,,但它又为什么推导出这些呢？\nDialogue: 0,1:00:34.49,1:00:38.32,Default,,0,0,0,,显然 苏格拉底不会犯这类逻辑错误\nDialogue: 0,1:00:40.08,1:00:42.67,Default,,0,0,0,,在这门语言中 NOT并不是NOT\nDialogue: 0,1:00:43.37,1:00:44.32,Default,,0,0,0,,不是逻辑非运算\nDialogue: 0,1:00:44.93,1:00:46.40,Default,,0,0,0,,这门语言中 NOT表示的是\nDialogue: 0,1:00:47.16,1:00:49.96,Default,,0,0,0,,不可以从数据库中推断出结果\nDialogue: 0,1:00:50.75,1:00:53.34,Default,,0,0,0,,而不是“非真”\nDialogue: 0,1:00:55.02,1:00:56.30,Default,,0,0,0,,完全是天壤之别\nDialogue: 0,1:00:57.30,1:00:58.64,Default,,0,0,0,,很细微 但也很巨大\nDialogue: 0,1:00:59.25,1:01:00.27,Default,,0,0,0,,因此 实际上\nDialogue: 0,1:01:00.76,1:01:03.92,Default,,0,0,0,,如果什么都不知道 最好就说NOT\nDialogue: 0,1:01:04.68,1:01:06.14,Default,,0,0,0,,如果你问它\nDialogue: 0,1:01:06.16,1:01:07.83,Default,,0,0,0,,宙斯是否喜欢巧克力冰激凌\nDialogue: 0,1:01:07.85,1:01:09.12,Default,,0,0,0,,它会说 这个查询当然非真\nDialogue: 0,1:01:10.64,1:01:12.51,Default,,0,0,0,,这些事情它都不知道\nDialogue: 0,1:01:12.59,1:01:17.34,Default,,0,0,0,,NOT表示：不能从你告知它的事实中推断出来\nDialogue: 0,1:01:18.28,1:01:22.44,Default,,0,0,0,,换句话说 你要把“无法推断出”\nDialogue: 0,1:01:22.65,1:01:24.00,Default,,0,0,0,,与“命题非真”区别开来\nDialogue: 0,1:01:24.41,1:01:26.30,Default,,0,0,0,,这被称作是“封闭世界假说”\nDialogue: 0,1:01:37.37,1:01:38.17,Default,,0,0,0,,封闭世界假说\nDialogue: 0,1:01:38.20,1:01:42.38,Default,,0,0,0,,只要结论不能通过我所知道的知识推断出来\nDialogue: 0,1:01:43.50,1:01:44.36,Default,,0,0,0,,那么就不是真的\nDialogue: 0,1:01:46.24,1:01:48.01,Default,,0,0,0,,对吧 如果我对X一无所知\nDialogue: 0,1:01:48.22,1:01:49.21,Default,,0,0,0,,那么X就非真\nDialogue: 0,1:01:49.29,1:01:50.33,Default,,0,0,0,,这相当危险\nDialogue: 0,1:01:51.29,1:01:52.44,Default,,0,0,0,,首先 从逻辑学的角度来说\nDialogue: 0,1:01:52.46,1:01:53.76,Default,,0,0,0,,它一点也说不通\nDialogue: 0,1:01:54.48,1:01:56.33,Default,,0,0,0,,因为如果我对X一无所知的话\nDialogue: 0,1:01:58.38,1:01:59.69,Default,,0,0,0,,就说X非真\nDialogue: 0,1:02:00.24,1:02:03.32,Default,,0,0,0,,但为什么不说“X非真”非真\nDialogue: 0,1:02:03.85,1:02:05.66,Default,,0,0,0,,当然 我也许对后面那个命题也一无所知\nDialogue: 0,1:02:06.47,1:02:08.65,Default,,0,0,0,,因此(NOT (NOT X))就没有必要与X一致\nDialogue: 0,1:02:09.24,1:02:10.94,Default,,0,0,0,,等等等等\nDialogue: 0,1:02:11.71,1:02:13.93,Default,,0,0,0,,因此 这里面一定有某种“偏见”\nDialogue: 0,1:02:15.97,1:02:17.29,Default,,0,0,0,,这相当有趣\nDialogue: 0,1:02:17.29,1:02:18.09,Default,,0,0,0,,第二点就是\nDialogue: 0,1:02:20.14,1:02:24.12,Default,,0,0,0,,如果你基于此 构建一个真正的推理程序\nDialogue: 0,1:02:24.70,1:02:26.11,Default,,0,0,0,,想一想是多么地危险\nDialogue: 0,1:02:27.07,1:02:32.00,Default,,0,0,0,,你说我知道我可以推断出\nDialogue: 0,1:02:32.22,1:02:36.22,Default,,0,0,0,,与这个问题有关的所有事情\nDialogue: 0,1:02:37.44,1:02:40.78,Default,,0,0,0,,因为在我推理机制的内部\nDialogue: 0,1:02:41.23,1:02:44.20,Default,,0,0,0,,会认为所有与问题有关的知识\nDialogue: 0,1:02:44.24,1:02:46.27,Default,,0,0,0,,我都已经知道了\nDialogue: 0,1:02:48.44,1:02:53.04,Default,,0,0,0,,有相当多的大型组织都像这样运作 对吧？\nDialogue: 0,1:02:53.16,1:02:56.83,Default,,0,0,0,,大多数公司的市场部门都是这样工作的。\nDialogue: 0,1:02:56.83,1:02:59.12,Default,,0,0,0,,你们也知道这样做的后果\nDialogue: 0,1:03:00.33,1:03:03.45,Default,,0,0,0,,因此 向这个大型逻辑推理系统\nDialogue: 0,1:03:03.84,1:03:06.25,Default,,0,0,0,,输入各种查询 根据输出继续工作\nDialogue: 0,1:03:07.05,1:03:09.00,Default,,0,0,0,,的做法相当危险\nDialogue: 0,1:03:09.02,1:03:11.28,Default,,0,0,0,,因为它们内建的假说非常地有限\nDialogue: 0,1:03:12.60,1:03:14.36,Default,,0,0,0,,因此你对此需要非常非常地小心\nDialogue: 0,1:03:15.29,1:03:16.28,Default,,0,0,0,,就是这么一个深层次问题\nDialogue: 0,1:03:16.56,1:03:17.82,Default,,0,0,0,,这个问题并不是\nDialogue: 0,1:03:18.22,1:03:20.14,Default,,0,0,0,,通过构建更加聪明的实现\nDialogue: 0,1:03:20.16,1:03:21.85,Default,,0,0,0,,或者通过组织无穷循环\nDialogue: 0,1:03:22.16,1:03:23.84,Default,,0,0,0,,以及过滤器就可以消除的\nDialogue: 0,1:03:23.84,1:03:25.08,Default,,0,0,0,,这是完全不同的一类问题\nDialogue: 0,1:03:25.92,1:03:26.89,Default,,0,0,0,,完全不同的语义\nDialogue: 0,1:03:27.06,1:03:30.51,Default,,0,0,0,,我想该总结一下了 平心而论\nDialogue: 0,1:03:31.34,1:03:34.43,Default,,0,0,0,,逻辑式程序设计是一个振奋人心的想法\nDialogue: 0,1:03:34.60,1:03:37.00,Default,,0,0,0,,这个想法使你能够弥合\nDialogue: 0,1:03:37.04,1:03:38.78,Default,,0,0,0,,命令式与声明式语言的鸿沟\nDialogue: 0,1:03:39.90,1:03:42.94,Default,,0,0,0,,使得你可以谈论关系\nDialogue: 0,1:03:43.58,1:03:45.08,Default,,0,0,0,,从而获得惊人的力量\nDialogue: 0,1:03:46.09,1:03:49.48,Default,,0,0,0,,让你超越输入和输出的抽象\nDialogue: 0,1:03:50.56,1:03:51.53,Default,,0,0,0,,而关于逻辑\nDialogue: 0,1:03:52.46,1:03:56.46,Default,,0,0,0,,我认为这个问题还尚未解决\nDialogue: 0,1:03:58.03,1:04:01.80,Default,,0,0,0,,也许现在语言中最令人感兴趣的\nDialogue: 0,1:04:02.27,1:04:04.41,Default,,0,0,0,,研究问题之一就是\nDialogue: 0,1:04:04.67,1:04:08.28,Default,,0,0,0,,你该如何创建一门真正的逻辑语言？\nDialogue: 0,1:04:09.46,1:04:11.05,Default,,0,0,0,,其次 你如何从\nDialogue: 0,1:04:11.31,1:04:13.15,Default,,0,0,0,,这个逻辑和关系的世界\nDialogue: 0,1:04:13.52,1:04:16.43,Default,,0,0,0,,到更传统语言的世界之间\nDialogue: 0,1:04:16.46,1:04:17.98,Default,,0,0,0,,架起桥梁并结合两者的力量\nDialogue: 0,1:04:18.88,1:04:19.68,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:04:23.29,1:04:25.29,Default,,0,0,0,,学生：你能够通过添加额外的规则\nDialogue: 0,1:04:25.29,1:04:27.74,Default,,0,0,0,,来解决最后一个问题么？\nDialogue: 0,1:04:27.96,1:04:29.85,Default,,0,0,0,,这里的困境是：你有某物的定义\nDialogue: 0,1:04:29.88,1:04:31.82,Default,,0,0,0,,但没有它对立面的定义\nDialogue: 0,1:04:32.08,1:04:33.92,Default,,0,0,0,,如果你在数据库中有\nDialogue: 0,1:04:34.14,1:04:36.89,Default,,0,0,0,,某些规则推导出(MORTAL X)\nDialogue: 0,1:04:36.99,1:04:38.70,Default,,0,0,0,,另外一些规则推导出(NOT (MORTAL X))\nDialogue: 0,1:04:38.75,1:04:40.37,Default,,0,0,0,,这不就基本上解决这个问题么？\nDialogue: 0,1:04:43.37,1:04:44.14,Default,,0,0,0,,教授：但问题就是\nDialogue: 0,1:04:44.75,1:04:46.38,Default,,0,0,0,,添加的这些规则是有穷个么？\nDialogue: 0,1:04:48.65,1:04:53.13,Default,,0,0,0,,学生：如果你同时定义正、反两面 --\nDialogue: 0,1:04:53.61,1:04:57.07,Default,,0,0,0,,教授：但问题就是 你该如何去做推断？\nDialogue: 0,1:05:00.20,1:05:02.11,Default,,0,0,0,,要知道 你不能直接定义命题的非\nDialogue: 0,1:05:03.40,1:05:04.76,Default,,0,0,0,,而问题就在于 在大型系统中\nDialogue: 0,1:05:04.78,1:05:07.96,Default,,0,0,0,,可能含有无穷个数的东西\nDialogue: 0,1:05:12.82,1:05:15.29,Default,,0,0,0,,这其中有两个问题\nDialogue: 0,1:05:15.29,1:05:16.56,Default,,0,0,0,,其一是可能有无穷项\nDialogue: 0,1:05:16.69,1:05:19.39,Default,,0,0,0,,另外是因为可能不向你想的那样\nDialogue: 0,1:05:21.51,1:05:24.52,Default,,0,0,0,,一个极好的例子 就是连通性\nDialogue: 0,1:05:25.12,1:05:26.54,Default,,0,0,0,,我想对连通性做推理\nDialogue: 0,1:05:28.05,1:05:30.38,Default,,0,0,0,,我会告诉你这有四个对象\nDialogue: 0,1:05:30.40,1:05:33.74,Default,,0,0,0,,A、B、C和D\nDialogue: 0,1:05:35.48,1:05:38.19,Default,,0,0,0,,我会告诉你A和B相连\nDialogue: 0,1:05:38.64,1:05:41.42,Default,,0,0,0,,C和D相连\nDialogue: 0,1:05:43.20,1:05:44.80,Default,,0,0,0,,然后我再告诉你A和D相连\nDialogue: 0,1:05:45.05,1:05:46.03,Default,,0,0,0,,就是这种情况\nDialogue: 0,1:05:46.78,1:05:48.52,Default,,0,0,0,,在这个例子中\nDialogue: 0,1:05:48.70,1:05:50.35,Default,,0,0,0,,我就希望有“封闭世界假说”这样的东西\nDialogue: 0,1:05:54.43,1:05:55.66,Default,,0,0,0,,这是个小玩具\nDialogue: 0,1:05:56.24,1:05:58.30,Default,,0,0,0,,但是很多时候 我都想说\nDialogue: 0,1:05:58.48,1:06:01.34,Default,,0,0,0,,我没告诉你的事 都假设非真\nDialogue: 0,1:06:04.26,1:06:06.27,Default,,0,0,0,,所以这并不是你显式地\nDialogue: 0,1:06:06.27,1:06:08.09,Default,,0,0,0,,为所有命题定义否命题就可以解决的\nDialogue: 0,1:06:09.47,1:06:12.70,Default,,0,0,0,,而是有些时候 你不清楚自己真正想要什么\nDialogue: 0,1:06:14.15,1:06:17.92,Default,,0,0,0,,同时定义原命题与否命题又太过于精细\nDialogue: 0,1:06:17.93,1:06:20.00,Default,,0,0,0,,这会使你陷入困境\nDialogue: 0,1:06:20.96,1:06:22.68,Default,,0,0,0,,但还是有很多方法\nDialogue: 0,1:06:23.32,1:06:25.93,Default,,0,0,0,,显式地定义否命题 并基于此进行推理\nDialogue: 0,1:06:26.51,1:06:27.66,Default,,0,0,0,,这个想法非常好\nDialogue: 0,1:06:28.07,1:06:31.45,Default,,0,0,0,,只是在一些复杂的大型问题中\nDialogue: 0,1:06:31.48,1:06:33.49,Default,,0,0,0,,这么做就变得有些笨重了\nDialogue: 0,1:06:43.46,1:06:45.96,Default,,0,0,0,,学生：有个论点 我不知道它和本节课的直接关系\nDialogue: 0,1:06:46.00,1:06:47.98,Default,,0,0,0,,但你想要表达的是\nDialogue: 0,1:06:48.49,1:06:50.16,Default,,0,0,0,,封闭世界假说的危害之一就是\nDialogue: 0,1:06:50.19,1:06:52.06,Default,,0,0,0,,你永远不会真正了解那里的所有事物\nDialogue: 0,1:06:53.44,1:06:55.32,Default,,0,0,0,,你永远不会知道它们的每个部分\nDialogue: 0,1:06:55.87,1:06:58.16,Default,,0,0,0,,这难道不是任何一门程序设计语言的主要问题吗？\nDialogue: 0,1:06:58.16,1:06:59.64,Default,,0,0,0,,写程序时 我总是\nDialogue: 0,1:06:59.90,1:07:01.56,Default,,0,0,0,,假设我考虑了所有的情况\nDialogue: 0,1:07:01.58,1:07:03.40,Default,,0,0,0,,然后我检查了每一种情况\nDialogue: 0,1:07:04.06,1:07:04.99,Default,,0,0,0,,然而在某处\nDialogue: 0,1:07:05.02,1:07:06.52,Default,,0,0,0,,我发现了我遗漏了其中的一个\nDialogue: 0,1:07:07.39,1:07:08.54,Default,,0,0,0,,教授：你说得很对\nDialogue: 0,1:07:08.54,1:07:09.76,Default,,0,0,0,,但这里的问题在于\nDialogue: 0,1:07:11.96,1:07:15.47,Default,,0,0,0,,对于你所做的事情\nDialogue: 0,1:07:15.48,1:07:17.34,Default,,0,0,0,,你是否认为它是逻辑问题\nDialogue: 0,1:07:19.60,1:07:20.51,Default,,0,0,0,,你说得非常正确\nDialogue: 0,1:07:20.51,1:07:22.22,Default,,0,0,0,,这是你永远不会遇到的情况\nDialogue: 0,1:07:22.22,1:07:24.14,Default,,0,0,0,,问题在于 如果你认为\nDialogue: 0,1:07:24.17,1:07:25.44,Default,,0,0,0,,你在进行逻辑式程序设计\nDialogue: 0,1:07:26.17,1:07:27.32,Default,,0,0,0,,然后审视你所编写的规则\nDialogue: 0,1:07:27.34,1:07:28.89,Default,,0,0,0,,并思考能从中推断出什么\nDialogue: 0,1:07:29.53,1:07:32.80,Default,,0,0,0,,你就需要清醒地认识到NOT具有另外的意义\nDialogue: 0,1:07:33.47,1:07:35.21,Default,,0,0,0,,它的意义基于某种假设\nDialogue: 0,1:07:35.24,1:07:36.70,Default,,0,0,0,,并且可能并不正确\nDialogue: 0,1:07:39.03,1:07:40.19,Default,,0,0,0,,学生：我不知道这样理解是否正确\nDialogue: 0,1:07:40.25,1:07:41.84,Default,,0,0,0,,也就是我们无法通过改变NOT\nDialogue: 0,1:07:42.25,1:07:46.08,Default,,0,0,0,,来消灭推断的所有可能性 从而解决这个问题？\nDialogue: 0,1:07:46.54,1:07:49.80,Default,,0,0,0,,教授：不 并不是这样\nDialogue: 0,1:07:52.96,1:07:55.08,Default,,0,0,0,,有很多种方法可以实现真正的逻辑非\nDialogue: 0,1:07:56.34,1:07:58.03,Default,,0,0,0,,实际上有很多种方法\nDialogue: 0,1:07:58.54,1:08:00.84,Default,,0,0,0,,但目前没有一个广为人知的高效算法\nDialogue: 0,1:08:01.61,1:08:02.56,Default,,0,0,0,,而且他们还--\nDialogue: 0,1:08:04.09,1:08:06.89,Default,,0,0,0,,这里所谓的“推论”\nDialogue: 0,1:08:07.39,1:08:08.83,Default,,0,0,0,,是建立在这个合一算法\nDialogue: 0,1:08:08.91,1:08:11.29,Default,,0,0,0,,以及模式匹配算法之中的\nDialogue: 0,1:08:11.98,1:08:16.19,Default,,0,0,0,,有多种方法可以实现真正的逻辑推理\nDialogue: 0,1:08:16.59,1:08:18.19,Default,,0,0,0,,但它们并不基于此\nDialogue: 0,1:08:18.51,1:08:20.73,Default,,0,0,0,,而逻辑式程序设计语言也不倾向于这么做\nDialogue: 0,1:08:20.75,1:08:23.85,Default,,0,0,0,,因为大家都知道 那样做非常低效\nDialogue: 0,1:08:29.39,1:08:30.03,Default,,0,0,0,,好吧 下课\nDialogue: 0,1:08:30.03,1:08:42.68,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:08:30.03,1:08:42.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec8b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nAudio File: ../../../../Movies/lec8b_480_muxed.mp4\nVideo File: ../../../../Movies/lec8b_480_muxed.mp4\nVideo AR Mode: 4\nVideo AR Value: 1.333333\nVideo Zoom Percent: 2.000000\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:02.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP 学习小组\\N倾情制作\nDialogue: 0,0:00:02.40,0:00:09.84,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.40,0:00:09.84,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.90,0:00:16.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 II\nDialogue: 0,0:00:18.91,0:00:21.79,Default,,0,0,0,,我们已经了解了查询语言的使用方式\nDialogue: 0,0:00:22.64,0:00:25.07,Default,,0,0,0,,现在该来讨论如何实现了\nDialogue: 0,0:00:26.28,0:00:27.98,Default,,0,0,0,,你们也应该能够猜到\nDialogue: 0,0:00:28.59,0:00:29.47,Default,,0,0,0,,它其中的原理了\nDialogue: 0,0:00:29.47,0:00:31.64,Default,,0,0,0,,它的最底层是一个模式匹配器\nDialogue: 0,0:00:32.81,0:00:34.25,Default,,0,0,0,,我们在《基于规则的控制语言》一课中\nDialogue: 0,0:00:34.67,0:00:36.94,Default,,0,0,0,,已经介绍过模式匹配器了\nDialogue: 0,0:00:38.11,0:00:40.59,Default,,0,0,0,,我举个例子来让你们温习一下\nDialogue: 0,0:00:41.52,0:00:43.68,Default,,0,0,0,,这个模式会匹配\nDialogue: 0,0:00:43.80,0:00:44.92,Default,,0,0,0,,一个含有三个元素的表\nDialogue: 0,0:00:44.96,0:00:47.10,Default,,0,0,0,,其中 首元素为A\nDialogue: 0,0:00:47.16,0:00:48.33,Default,,0,0,0,,其次是C\nDialogue: 0,0:00:48.48,0:00:50.19,Default,,0,0,0,,而中间可以为任意元素\nDialogue: 0,0:00:50.65,0:00:52.27,Default,,0,0,0,,所以在这个小型的模式匹配语言中\nDialogue: 0,0:00:52.30,0:00:54.05,Default,,0,0,0,,你只能区分一种类型\nDialogue: 0,0:00:54.05,0:00:57.20,Default,,0,0,0,,也就是区分字面量或者变量\nDialogue: 0,0:00:57.23,0:00:58.86,Default,,0,0,0,,以问号开头的就是变量\nDialogue: 0,0:01:01.37,0:01:03.64,Default,,0,0,0,,因此这个模式会匹配任意的三元表\nDialogue: 0,0:01:04.44,0:01:06.50,Default,,0,0,0,,只要它的首元素为A 而第三个元素为C\nDialogue: 0,0:01:06.50,0:01:09.00,Default,,0,0,0,,而这个模式匹配的三元表\nDialogue: 0,0:01:10.43,0:01:12.53,Default,,0,0,0,,它的首元素必须是符号'JOB\nDialogue: 0,0:01:12.53,0:01:13.90,Default,,0,0,0,,第二个元素为任意值\nDialogue: 0,0:01:14.21,0:01:15.90,Default,,0,0,0,,第三个元素必须是一个二元表\nDialogue: 0,0:01:15.95,0:01:17.72,Default,,0,0,0,,二元表的首元素为符号'COMPUTER\nDialogue: 0,0:01:17.88,0:01:19.42,Default,,0,0,0,,第二个元素可以为任意值\nDialogue: 0,0:01:20.48,0:01:25.55,Default,,0,0,0,,而下一条模式所匹配的三元表\nDialogue: 0,0:01:25.87,0:01:26.99,Default,,0,0,0,,区别就在于\nDialogue: 0,0:01:28.40,0:01:31.32,Default,,0,0,0,,在于第三个元素的首元素必须为符号'COMPUTER\nDialogue: 0,0:01:31.76,0:01:33.29,Default,,0,0,0,,表剩余部分可以是任意值\nDialogue: 0,0:01:35.04,0:01:37.53,Default,,0,0,0,,也就是说 上面是二元表 而下面没有限定数目\nDialogue: 0,0:01:37.86,0:01:39.74,Default,,0,0,0,,然而我们的语言实现\nDialogue: 0,0:01:39.85,0:01:42.06,Default,,0,0,0,,根本不用操心如何去实现这个点号\nDialogue: 0,0:01:42.11,0:01:44.17,Default,,0,0,0,,因为这个由Lisp读取器自动地完成\nDialogue: 0,0:01:48.34,0:01:50.31,Default,,0,0,0,,要注意 匹配器还要保持一致性\nDialogue: 0,0:01:50.31,0:01:52.32,Default,,0,0,0,,这个模式匹配一个三元表\nDialogue: 0,0:01:52.59,0:01:53.98,Default,,0,0,0,,表的首元素是A\nDialogue: 0,0:01:54.43,0:01:55.79,Default,,0,0,0,,而第二个元素和第三个元素可以是任意值\nDialogue: 0,0:01:55.80,0:01:57.08,Default,,0,0,0,,但它们必须是相同的\nDialogue: 0,0:01:57.94,0:01:58.84,Default,,0,0,0,,它们都是?X\nDialogue: 0,0:01:59.60,0:02:01.55,Default,,0,0,0,,而这个模式匹配一个四元表\nDialogue: 0,0:02:01.96,0:02:03.26,Default,,0,0,0,,其中第一个元素与第四个元素相同\nDialogue: 0,0:02:03.66,0:02:05.15,Default,,0,0,0,,而第二个元素与第三个元素相同\nDialogue: 0,0:02:05.59,0:02:08.60,Default,,0,0,0,,最后一个模式匹配以A开头的任意表\nDialogue: 0,0:02:09.68,0:02:11.05,Default,,0,0,0,,以A开头\nDialogue: 0,0:02:11.23,0:02:12.56,Default,,0,0,0,,余下的可以是任意值\nDialogue: 0,0:02:14.04,0:02:16.60,Default,,0,0,0,,这是对我们已经学习过的模式匹配语言\nDialogue: 0,0:02:16.62,0:02:17.87,Default,,0,0,0,,的一个回顾\nDialogue: 0,0:02:18.78,0:02:19.64,Default,,0,0,0,,还记得吗\nDialogue: 0,0:02:19.79,0:02:22.28,Default,,0,0,0,,这是由一个叫做MATCH的过程实现的\nDialogue: 0,0:02:24.87,0:02:36.06,Default,,0,0,0,,MATCH有三个参数：PAT、DATA以及DICTIONARY\nDialogue: 0,0:02:43.20,0:02:47.12,Default,,0,0,0,,MATCH考虑的是\nDialogue: 0,0:02:47.79,0:02:52.64,Default,,0,0,0,,利用给定DICTIONAY中的绑定\nDialogue: 0,0:02:53.55,0:02:56.73,Default,,0,0,0,,能够找到一种方法把模式与数据对象匹配起来吗？\nDialogue: 0,0:02:58.16,0:02:59.21,Default,,0,0,0,,比如说\nDialogue: 0,0:02:59.56,0:03:06.43,Default,,0,0,0,,如果我们想要把模式(?X ?Y ?Y ?X)\nDialogue: 0,0:03:07.71,0:03:13.84,Default,,0,0,0,,与数据对象(A B B A)相匹配\nDialogue: 0,0:03:15.12,0:03:20.52,Default,,0,0,0,,又给定了一个字典 X=A\nDialogue: 0,0:03:22.01,0:03:25.23,Default,,0,0,0,,MATCH就会说：“它们是一致的”\nDialogue: 0,0:03:25.26,0:03:27.16,Default,,0,0,0,,再给定的字典说 X=A 的情况下\nDialogue: 0,0:03:27.80,0:03:30.20,Default,,0,0,0,,模式与数据相匹配\nDialogue: 0,0:03:30.32,0:03:31.60,Default,,0,0,0,,而匹配的结果则是\nDialogue: 0,0:03:32.25,0:03:34.30,Default,,0,0,0,,一个扩展了的词典\nDialogue: 0,0:03:34.46,0:03:37.60,Default,,0,0,0,,其中包含 X=A Y=B\nDialogue: 0,0:03:39.49,0:03:42.24,Default,,0,0,0,,MATCH接收模式、数据以及字典\nDialogue: 0,0:03:42.38,0:03:44.54,Default,,0,0,0,,如果成功匹配就输出一个扩展后的词典\nDialogue: 0,0:03:44.97,0:03:46.84,Default,,0,0,0,,否则就报错\nDialogue: 0,0:03:46.84,0:03:47.71,Default,,0,0,0,,因此 比如说\nDialogue: 0,0:03:47.88,0:03:50.38,Default,,0,0,0,,如果我在这里使用同样的模式\nDialogue: 0,0:03:50.97,0:03:55.12,Default,,0,0,0,,如果我用模式(?X ?Y ?Y ?X)\nDialogue: 0,0:03:55.66,0:03:58.49,Default,,0,0,0,,去匹配(A B B A)\nDialogue: 0,0:03:59.47,0:04:02.84,Default,,0,0,0,,并给定词典 Y=A\nDialogue: 0,0:04:05.15,0:04:06.81,Default,,0,0,0,,那么MATCH就会输出FAIL\nDialogue: 0,0:04:12.52,0:04:14.65,Default,,0,0,0,,你们已经见过模式匹配器的代码了\nDialogue: 0,0:04:15.00,0:04:16.17,Default,,0,0,0,,我就不会再去细讲\nDialogue: 0,0:04:16.64,0:04:19.77,Default,,0,0,0,,这跟我们以前做的类似\nDialogue: 0,0:04:21.19,0:04:23.22,Default,,0,0,0,,我们在《基于规则的系统》中已经见过了\nDialogue: 0,0:04:23.22,0:04:24.56,Default,,0,0,0,,基本上是同样的匹配器\nDialogue: 0,0:04:24.95,0:04:27.66,Default,,0,0,0,,实际上 我认为这里的语法还更简单一点\nDialogue: 0,0:04:28.16,0:04:29.31,Default,,0,0,0,,因为我们不用去关心\nDialogue: 0,0:04:29.40,0:04:31.40,Default,,0,0,0,,任意变量、任意表达式之类的东西\nDialogue: 0,0:04:31.40,0:04:32.88,Default,,0,0,0,,这里面只区分变量和常量\nDialogue: 0,0:04:35.79,0:04:37.32,Default,,0,0,0,,那么 有了模式匹配器以后\nDialogue: 0,0:04:38.46,0:04:39.61,Default,,0,0,0,,基本查询又是怎么样的呢？\nDialogue: 0,0:04:42.97,0:04:45.34,Default,,0,0,0,,基本查询将会是一个相当复杂的东西\nDialogue: 0,0:04:46.67,0:05:03.58,Default,,0,0,0,,就拿查询(JOB ?X (?D . ?Y))来说\nDialogue: 0,0:05:07.04,0:05:08.73,Default,,0,0,0,,我们可能会输入这样的查询\nDialogue: 0,0:05:09.40,0:05:11.39,Default,,0,0,0,,这又将如何在系统内实现呢？\nDialogue: 0,0:05:14.14,0:05:15.66,Default,,0,0,0,,我们可以把它想做这个小盒子\nDialogue: 0,0:05:15.70,0:05:16.80,Default,,0,0,0,,这是一条基本查询\nDialogue: 0,0:05:18.88,0:05:20.30,Default,,0,0,0,,这个小盒子将会\nDialogue: 0,0:05:22.24,0:05:27.28,Default,,0,0,0,,以两条流作为输入\nDialogue: 0,0:05:31.96,0:05:33.20,Default,,0,0,0,,并输出一条流\nDialogue: 0,0:05:34.03,0:05:36.19,Default,,0,0,0,,因此一条基本查询的形状\nDialogue: 0,0:05:36.51,0:05:38.46,Default,,0,0,0,,就将是有两条输入流\nDialogue: 0,0:05:38.67,0:05:39.96,Default,,0,0,0,,和一条输出流\nDialogue: 0,0:05:41.12,0:05:46.20,Default,,0,0,0,,而这些流 来自于这里的数据库\nDialogue: 0,0:05:51.95,0:05:53.93,Default,,0,0,0,,因此我们把数据库中的所有数据\nDialogue: 0,0:05:55.93,0:05:57.20,Default,,0,0,0,,想象成一条流\nDialogue: 0,0:05:57.31,0:05:58.40,Default,,0,0,0,,而这个盒子不断地吸取\nDialogue: 0,0:06:00.36,0:06:02.43,Default,,0,0,0,,那么 数据库中有什么呢？\nDialogue: 0,0:06:08.43,0:06:20.32,Default,,0,0,0,,首先是(JOB (ALYSSA ...))\nDialogue: 0,0:06:21.96,0:06:23.71,Default,,0,0,0,,以及还有其它的JOB数据\nDialogue: 0,0:06:25.77,0:06:30.41,Default,,0,0,0,,想象一下 数据库中的所有事实都在这条流中\nDialogue: 0,0:06:32.04,0:06:33.10,Default,,0,0,0,,都到了这里\nDialogue: 0,0:06:33.36,0:06:34.52,Default,,0,0,0,,而这条流送来的\nDialogue: 0,0:06:34.89,0:06:36.52,Default,,0,0,0,,是一些字典\nDialogue: 0,0:06:38.51,0:06:41.40,Default,,0,0,0,,其中一个就可能是\nDialogue: 0,0:06:46.70,0:06:49.31,Default,,0,0,0,,Y=PROG\nDialogue: 0,0:06:55.47,0:06:56.64,Default,,0,0,0,,现在 查询工作就是要\nDialogue: 0,0:06:57.07,0:06:59.80,Default,,0,0,0,,当它从这条流中取得一个字典后\nDialogue: 0,0:07:02.01,0:07:06.67,Default,,0,0,0,,它会搜寻数据库中的东西\nDialogue: 0,0:07:07.45,0:07:10.24,Default,,0,0,0,,来尽可能产生所有匹配结果\nDialogue: 0,0:07:11.39,0:07:12.89,Default,,0,0,0,,它把查询视作一种模式\nDialogue: 0,0:07:13.15,0:07:16.72,Default,,0,0,0,,并将它们与数据库中的事实匹配起来\nDialogue: 0,0:07:16.96,0:07:21.98,Default,,0,0,0,,结合着相应的字典中的数据\nDialogue: 0,0:07:22.94,0:07:25.68,Default,,0,0,0,,找到数据库中所有匹配的结果\nDialogue: 0,0:07:27.55,0:07:29.69,Default,,0,0,0,,所以针对数据库中的每条事实\nDialogue: 0,0:07:29.72,0:07:34.35,Default,,0,0,0,,它都会调用(MATCH PAT FACT DICTIONAY)来检查\nDialogue: 0,0:07:35.11,0:07:37.68,Default,,0,0,0,,如果成功匹配\nDialogue: 0,0:07:38.19,0:07:39.93,Default,,0,0,0,,它就输出一个扩展了的字典\nDialogue: 0,0:07:40.67,0:07:42.32,Default,,0,0,0,,比如说 这里进来了一本字典\nDialogue: 0,0:07:43.00,0:07:44.09,Default,,0,0,0,,并且成功匹配\nDialogue: 0,0:07:44.51,0:07:45.87,Default,,0,0,0,,那么就会输出一本字典\nDialogue: 0,0:07:46.81,0:07:49.79,Default,,0,0,0,,本例中就是Y=PROG\nDialogue: 0,0:07:51.52,0:07:52.97,Default,,0,0,0,,X=...\nDialogue: 0,0:07:56.54,0:07:58.75,Default,,0,0,0,,Y=PROG X=...\nDialogue: 0,0:07:58.96,0:08:00.54,Default,,0,0,0,,D又是一个新的项\nDialogue: 0,0:08:01.72,0:08:02.27,Default,,0,0,0,,像这样扩展\nDialogue: 0,0:08:03.52,0:08:07.82,Default,,0,0,0,,当然 它会针对数据库中的所有事实做同样的尝试\nDialogue: 0,0:08:07.98,0:08:09.25,Default,,0,0,0,,所以就可能有很多的结果\nDialogue: 0,0:08:09.56,0:08:10.59,Default,,0,0,0,,可能会产生另一本字典\nDialogue: 0,0:08:11.28,0:08:17.12,Default,,0,0,0,,其中 Y=PROG X=... D=...\nDialogue: 0,0:08:19.18,0:08:21.55,Default,,0,0,0,,因此 对于每个输入的框架\nDialogue: 0,0:08:21.76,0:08:23.69,Default,,0,0,0,,对于每输入一本字典\nDialogue: 0,0:08:23.72,0:08:25.24,Default,,0,0,0,,它可能输出很多本字典\nDialogue: 0,0:08:26.54,0:08:28.67,Default,,0,0,0,,或者什么也不输出\nDialogue: 0,0:08:30.47,0:08:38.48,Default,,0,0,0,,可能会有一些不匹配的情况 比如X=FOO\nDialogue: 0,0:08:39.02,0:08:40.89,Default,,0,0,0,,这个条目不会匹配任何东西\nDialogue: 0,0:08:41.52,0:08:45.12,Default,,0,0,0,,就这个框架来说 不会向输出流中输出东西\nDialogue: 0,0:08:47.51,0:08:51.28,Default,,0,0,0,,或者你也可以输入一个空框架\nDialogue: 0,0:08:52.91,0:08:56.24,Default,,0,0,0,,空框架是用来\nDialogue: 0,0:08:59.87,0:09:02.33,Default,,0,0,0,,在没有任何约束的情况下\nDialogue: 0,0:09:02.57,0:09:06.14,Default,,0,0,0,,匹配数据库中所有可能的结果\nDialogue: 0,0:09:07.57,0:09:09.16,Default,,0,0,0,,这仅仅代表着\nDialogue: 0,0:09:10.32,0:09:13.87,Default,,0,0,0,,处理你输入的查询 最初所进行的计算\nDialogue: 0,0:09:14.20,0:09:15.56,Default,,0,0,0,,它试图找出所有的匹配\nDialogue: 0,0:09:16.65,0:09:18.83,Default,,0,0,0,,基本查询建立了这种机制\nDialogue: 0,0:09:19.37,0:09:20.57,Default,,0,0,0,,而语言要做的是\nDialogue: 0,0:09:22.75,0:09:24.67,Default,,0,0,0,,当你在顶层输入这条查询时\nDialogue: 0,0:09:24.84,0:09:26.14,Default,,0,0,0,,它基于这种机制\nDialogue: 0,0:09:26.16,0:09:28.35,Default,,0,0,0,,它会输入一本空的字典\nDialogue: 0,0:09:30.86,0:09:32.56,Default,,0,0,0,,而对于输出的每个东西\nDialogue: 0,0:09:33.08,0:09:35.88,Default,,0,0,0,,然后把最初的查询\nDialogue: 0,0:09:36.56,0:09:40.44,Default,,0,0,0,,用不同的字典来实例化\nDialogue: 0,0:09:40.81,0:09:44.36,Default,,0,0,0,,于是实例化后的模式就形成了一条新的流\nDialogue: 0,0:09:44.99,0:09:46.51,Default,,0,0,0,,这就是在终端上打印出来的内容\nDialogue: 0,0:09:48.17,0:09:51.24,Default,,0,0,0,,这也就是其中的基本原理\nDialogue: 0,0:09:53.51,0:09:55.48,Default,,0,0,0,,那么 这又为什么复杂呢？\nDialogue: 0,0:09:57.71,0:10:01.00,Default,,0,0,0,,除了使用这种基于流的方法\nDialogue: 0,0:10:01.37,0:10:04.25,Default,,0,0,0,,你们可以想出很多更简单的方法来组织基本查询\nDialogue: 0,0:10:05.18,0:10:06.09,Default,,0,0,0,,而答案就在于\nDialogue: 0,0:10:07.15,0:10:08.51,Default,,0,0,0,,你们可能已经在想了\nDialogue: 0,0:10:10.86,0:10:14.09,Default,,0,0,0,,答案就是 这种方法能够优雅地\nDialogue: 0,0:10:14.56,0:10:16.76,Default,,0,0,0,,实现组合手段\nDialogue: 0,0:10:17.79,0:10:18.80,Default,,0,0,0,,比如说\nDialogue: 0,0:10:20.65,0:10:22.47,Default,,0,0,0,,假设我还想实现其它的效果\nDialogue: 0,0:10:22.47,0:10:26.96,Default,,0,0,0,,我不只是想查询所有人的工作信息\nDialogue: 0,0:10:27.23,0:10:28.35,Default,,0,0,0,,假设我还想查询\nDialogue: 0,0:10:29.47,0:10:35.92,Default,,0,0,0,,(AND (JOB ?X (?D . ?Y))\nDialogue: 0,0:10:36.80,0:10:47.04,Default,,0,0,0,,(SUPERVIOSR ?X ?Z))\nDialogue: 0,0:10:48.80,0:10:50.67,Default,,0,0,0,,(SUPERVISOR ?X ?Z)这条查询\nDialogue: 0,0:10:51.39,0:10:52.96,Default,,0,0,0,,是另外的一条基本查询\nDialogue: 0,0:10:53.71,0:10:58.43,Default,,0,0,0,,它也有类似的形状——接收一条数据对象流\nDialogue: 0,0:10:59.18,0:11:01.64,Default,,0,0,0,,一条初始字典流\nDialogue: 0,0:11:01.68,0:11:05.52,Default,,0,0,0,,字典是你在进行匹配时 需要遵循的约束\nDialogue: 0,0:11:05.53,0:11:07.44,Default,,0,0,0,,然后它会输出一条字典流\nDialogue: 0,0:11:08.70,0:11:10.80,Default,,0,0,0,,这就是这条基本查询的形状\nDialogue: 0,0:11:11.50,0:11:12.91,Default,,0,0,0,,我又该如何实现AND呢？\nDialogue: 0,0:11:12.91,0:11:13.45,Default,,0,0,0,,其实很简单\nDialogue: 0,0:11:13.45,0:11:14.44,Default,,0,0,0,,把它们连接起来就好了\nDialogue: 0,0:11:14.88,0:11:16.28,Default,,0,0,0,,我把这条查询的输出\nDialogue: 0,0:11:16.96,0:11:18.81,Default,,0,0,0,,连接在这条查询的输入上\nDialogue: 0,0:11:19.83,0:11:21.84,Default,,0,0,0,,然后把这里的字典扇出开来\nDialogue: 0,0:11:26.57,0:11:27.96,Default,,0,0,0,,你们就能发现它是如何工作的了\nDialogue: 0,0:11:29.05,0:11:32.44,Default,,0,0,0,,这里会输出一个框架\nDialogue: 0,0:11:32.51,0:11:36.84,Default,,0,0,0,,其中有X、Y和D的绑定\nDialogue: 0,0:11:37.92,0:11:39.28,Default,,0,0,0,,当后面的查询接收到结果后\nDialogue: 0,0:11:39.29,0:11:41.60,Default,,0,0,0,,当它了解了这些约束后\nDialogue: 0,0:11:42.17,0:11:49.24,Default,,0,0,0,,字典中的是Y、X和D的值\nDialogue: 0,0:11:51.80,0:11:53.08,Default,,0,0,0,,它会搜寻数据库\nDialogue: 0,0:11:53.12,0:11:54.92,Default,,0,0,0,,试图找到有关SUPERVISOR关系的事实\nDialogue: 0,0:11:56.04,0:11:58.51,Default,,0,0,0,,如果找到了的话 它就会输出一些词典\nDialogue: 0,0:11:59.58,0:12:09.34,Default,,0,0,0,,其中有Y、X、D以及Z的绑定\nDialogue: 0,0:12:12.07,0:12:14.09,Default,,0,0,0,,不过要注意\nDialogue: 0,0:12:14.19,0:12:17.24,Default,,0,0,0,,因为这里输入的框架建立了约束\nDialogue: 0,0:12:17.61,0:12:20.28,Default,,0,0,0,,它保证了当你执行AND运算时\nDialogue: 0,0:12:20.49,0:12:24.62,Default,,0,0,0,,这两个X是相同的\nDialogue: 0,0:12:26.47,0:12:28.96,Default,,0,0,0,,这是因为通过这条流输出时\nDialogue: 0,0:12:29.96,0:12:32.65,Default,,0,0,0,,X已经有值了 你要确保匹配的一致性\nDialogue: 0,0:12:34.46,0:12:36.17,Default,,0,0,0,,然后我们想起在MATCH的代码中\nDialogue: 0,0:12:36.19,0:12:38.17,Default,,0,0,0,,有一种操作字典的特殊组织方法\nDialogue: 0,0:12:38.20,0:12:39.82,Default,,0,0,0,,确保了匹配的一致性\nDialogue: 0,0:12:40.92,0:12:41.77,Default,,0,0,0,,这就是AND的实现\nDialogue: 0,0:12:44.08,0:12:46.94,Default,,0,0,0,,关键是要注意它的一般性形状\nDialogue: 0,0:12:48.49,0:12:51.55,Default,,0,0,0,,我们来看看(AND P Q)\nDialogue: 0,0:12:52.88,0:12:55.61,Default,,0,0,0,,这里是P和Q\nDialogue: 0,0:12:57.29,0:12:58.60,Default,,0,0,0,,两条查询的AND\nDialogue: 0,0:13:00.27,0:13:01.19,Default,,0,0,0,,看起来像是这样\nDialogue: 0,0:13:01.19,0:13:04.44,Default,,0,0,0,,每一条查询都通过一条流连接数据库\nDialogue: 0,0:13:04.54,0:13:05.71,Default,,0,0,0,,一条输入流\nDialogue: 0,0:13:06.33,0:13:08.17,Default,,0,0,0,,并输出一条输出流\nDialogue: 0,0:13:10.23,0:13:11.72,Default,,0,0,0,,关键是要注意\nDialogue: 0,0:13:12.20,0:13:15.02,Default,,0,0,0,,如果我在它们周围画一个盒子\nDialogue: 0,0:13:19.26,0:13:23.64,Default,,0,0,0,,这就是(AND P Q)\nDialogue: 0,0:13:25.66,0:13:30.38,Default,,0,0,0,,那么这个盒子也有同样的形状\nDialogue: 0,0:13:32.04,0:13:34.20,Default,,0,0,0,,它也有一条连接数据库的流\nDialogue: 0,0:13:34.20,0:13:35.74,Default,,0,0,0,,但是在内部会扇出开来\nDialogue: 0,0:13:36.60,0:13:37.93,Default,,0,0,0,,但是在外部你看不到\nDialogue: 0,0:13:38.16,0:13:40.64,Default,,0,0,0,,它接收一个流 并输出一个流\nDialogue: 0,0:13:42.06,0:13:43.16,Default,,0,0,0,,这就是AND\nDialogue: 0,0:13:43.57,0:13:45.72,Default,,0,0,0,,类似地 OR可能看起像这样\nDialogue: 0,0:13:46.02,0:13:49.58,Default,,0,0,0,,虽然我没给你们演示过OR的用法\nDialogue: 0,0:13:49.84,0:13:54.70,Default,,0,0,0,,OR会尝试找出P或Q所有匹配的事实\nDialogue: 0,0:13:55.80,0:13:58.07,Default,,0,0,0,,P、Q两条查询都有各自的形状\nDialogue: 0,0:14:04.46,0:14:06.68,Default,,0,0,0,,OR的实现则是\nDialogue: 0,0:14:08.54,0:14:10.91,Default,,0,0,0,,我把来自于数据库的流\nDialogue: 0,0:14:12.50,0:14:13.49,Default,,0,0,0,,扇出开来\nDialogue: 0,0:14:13.49,0:14:16.04,Default,,0,0,0,,把它们分别送给P和Q\nDialogue: 0,0:14:17.44,0:14:21.98,Default,,0,0,0,,我把最初的查询流也给扇出开来\nDialogue: 0,0:14:26.75,0:14:29.16,Default,,0,0,0,,这样我不但能够得到P的所有结果\nDialogue: 0,0:14:29.29,0:14:31.08,Default,,0,0,0,,也能得到Q的所有结果\nDialogue: 0,0:14:31.61,0:14:34.56,Default,,0,0,0,,把这些输出送入某种“附加器”中\nDialogue: 0,0:14:34.62,0:14:37.48,Default,,0,0,0,,或者把它们“合并”到一条流中\nDialogue: 0,0:14:39.64,0:14:40.88,Default,,0,0,0,,然后得到输出\nDialogue: 0,0:14:41.08,0:14:48.24,Default,,0,0,0,,而从外部来看 这整个东西就是OR\nDialogue: 0,0:14:52.35,0:14:54.89,Default,,0,0,0,,同样的 当你们从外部观察它时\nDialogue: 0,0:14:55.07,0:14:56.54,Default,,0,0,0,,你会发现它具有相同的形状\nDialogue: 0,0:15:01.00,0:15:01.61,Default,,0,0,0,,NOT又如何实现呢？\nDialogue: 0,0:15:02.02,0:15:03.45,Default,,0,0,0,,NOT的原理有些类似\nDialogue: 0,0:15:04.31,0:15:05.95,Default,,0,0,0,,如果我有一条查询P\nDialogue: 0,0:15:06.86,0:15:13.50,Default,,0,0,0,,这是一条基本查询P\nDialogue: 0,0:15:14.69,0:15:16.32,Default,,0,0,0,,现在我要实现(NOT P)\nDialogue: 0,0:15:18.68,0:15:20.54,Default,,0,0,0,,NOT的作用像是一个过滤器\nDialogue: 0,0:15:20.72,0:15:21.95,Default,,0,0,0,,这里连接数据库\nDialogue: 0,0:15:23.84,0:15:28.28,Default,,0,0,0,,这里是输入的字典流\nDialogue: 0,0:15:28.78,0:15:31.53,Default,,0,0,0,,(NOT P)要做的就是\nDialogue: 0,0:15:31.88,0:15:37.40,Default,,0,0,0,,对这些东西做过滤\nDialogue: 0,0:15:39.02,0:15:40.09,Default,,0,0,0,,过滤的方法则是\nDialogue: 0,0:15:40.19,0:15:42.70,Default,,0,0,0,,如果我在这里获得了一本字典\nDialogue: 0,0:15:43.42,0:15:44.65,Default,,0,0,0,,那么我就去找所有的匹配\nDialogue: 0,0:15:44.83,0:15:46.48,Default,,0,0,0,,然后丢弃找到的结果\nDialogue: 0,0:15:47.46,0:15:49.93,Default,,0,0,0,,如果我没有在这里找到匹配\nDialogue: 0,0:15:50.12,0:15:51.37,Default,,0,0,0,,我就把它传递过去\nDialogue: 0,0:15:52.40,0:15:53.55,Default,,0,0,0,,NOT就是一个纯粹的过滤器\nDialogue: 0,0:15:55.34,0:15:59.98,Default,,0,0,0,,因此AND就类似于一个电阻\nDialogue: 0,0:15:59.98,0:16:01.85,Default,,0,0,0,,AND是串行的组合\nDialogue: 0,0:16:02.49,0:16:04.14,Default,,0,0,0,,OR是并行组合\nDialogue: 0,0:16:04.96,0:16:07.46,Default,,0,0,0,,然而NOT并不会对字典做任何扩展\nDialogue: 0,0:16:07.46,0:16:08.40,Default,,0,0,0,,它只会做过滤\nDialogue: 0,0:16:08.75,0:16:11.79,Default,,0,0,0,,它会丢弃那些能够匹配的结果\nDialogue: 0,0:16:12.64,0:16:14.19,Default,,0,0,0,,LISP-VALUE的原理类似\nDialogue: 0,0:16:14.84,0:16:16.60,Default,,0,0,0,,它的过滤器会复杂点\nDialogue: 0,0:16:16.60,0:16:17.37,Default,,0,0,0,,因为要应用到谓词上\nDialogue: 0,0:16:19.93,0:16:21.64,Default,,0,0,0,,这里需要注意的关键点是\nDialogue: 0,0:16:21.92,0:16:23.55,Default,,0,0,0,,我们之前也强调过了\nDialogue: 0,0:16:23.64,0:16:25.29,Default,,0,0,0,,就是关于“闭包性质”的思想\nDialogue: 0,0:16:28.22,0:16:31.80,Default,,0,0,0,,我们通过组合手段构建的东西\nDialogue: 0,0:16:31.95,0:16:34.51,Default,,0,0,0,,跟所使用的基本物件\nDialogue: 0,0:16:35.69,0:16:37.58,Default,,0,0,0,,有同样的结构\nDialogue: 0,0:16:39.75,0:16:41.68,Default,,0,0,0,,所以从外面看\nDialogue: 0,0:16:41.71,0:16:43.72,Default,,0,0,0,,查询的AND与基本查询结构相同\nDialogue: 0,0:16:44.63,0:16:46.14,Default,,0,0,0,,这就意味着\nDialogue: 0,0:16:46.94,0:16:50.28,Default,,0,0,0,,这里的盒子可以是AND、OR、NOT或者其它的\nDialogue: 0,0:16:50.30,0:16:54.22,Default,,0,0,0,,因为它具有相同的形状来连接更大的东西\nDialogue: 0,0:16:54.95,0:16:56.68,Default,,0,0,0,,这种思想能够让我们获得\nDialogue: 0,0:16:56.92,0:16:58.96,Default,,0,0,0,,Escher绘图语言中的那种复杂度\nDialogue: 0,0:16:59.55,0:17:01.31,Default,,0,0,0,,让你能够仅仅使用序对\nDialogue: 0,0:17:01.34,0:17:03.26,Default,,0,0,0,,构建出这些复杂结构\nDialogue: 0,0:17:03.93,0:17:04.78,Default,,0,0,0,,这就是“闭包性质”\nDialogue: 0,0:17:06.28,0:17:08.06,Default,,0,0,0,,这种性质\nDialogue: 0,0:17:09.64,0:17:11.72,Default,,0,0,0,,能够让我完成你们现在觉得理所当然的事儿\nDialogue: 0,0:17:11.76,0:17:14.91,Default,,0,0,0,,比如我可以查询(AND JOB SALARY)\nDialogue: 0,0:17:14.91,0:17:18.80,Default,,0,0,0,,当然我也可以查询(AND JOB (NOT ...))等等\nDialogue: 0,0:17:19.26,0:17:20.92,Default,,0,0,0,,这种便利是由\nDialogue: 0,0:17:20.94,0:17:22.91,Default,,0,0,0,,这种“闭包原则”直接带给我们的\nDialogue: 0,0:17:25.18,0:17:27.08,Default,,0,0,0,,好吧 提问时间\nDialogue: 0,0:17:29.32,0:17:30.89,Default,,0,0,0,,学生：字典是从哪里来的？\nDialogue: 0,0:17:30.99,0:17:36.03,Default,,0,0,0,,教授：字典最初来自于你的输入\nDialogue: 0,0:17:36.09,0:17:37.32,Default,,0,0,0,,因此当你最初进行查询时\nDialogue: 0,0:17:39.16,0:17:41.09,Default,,0,0,0,,它首先会建立起这整个结构\nDialogue: 0,0:17:41.09,0:17:42.64,Default,,0,0,0,,它先输入一个空字典\nDialogue: 0,0:17:45.00,0:17:47.24,Default,,0,0,0,,如果你只有一条基本查询的话\nDialogue: 0,0:17:48.24,0:17:51.10,Default,,0,0,0,,那么它就会输出一系列具有内容的字典\nDialogue: 0,0:17:52.31,0:17:54.33,Default,,0,0,0,,这里演示的一般性情况是\nDialogue: 0,0:17:54.51,0:17:59.71,Default,,0,0,0,,某个嵌套组合查询的中间过程\nDialogue: 0,0:18:01.55,0:18:02.30,Default,,0,0,0,,所以在那时\nDialogue: 0,0:18:02.38,0:18:03.79,Default,,0,0,0,,让我们来看看这里\nDialogue: 0,0:18:04.38,0:18:06.73,Default,,0,0,0,,这条SUPERVISOR查询得到了某本字典\nDialogue: 0,0:18:06.73,0:18:08.03,Default,,0,0,0,,这本字典来自于哪里呢？\nDialogue: 0,0:18:08.73,0:18:11.15,Default,,0,0,0,,它来自于\nDialogue: 0,0:18:12.84,0:18:14.89,Default,,0,0,0,,这条基本查询的输出\nDialogue: 0,0:18:16.26,0:18:17.88,Default,,0,0,0,,说得更具体一点\nDialogue: 0,0:18:18.35,0:18:21.72,Default,,0,0,0,,如果我最初在顶层只输入了这条查询\nDialogue: 0,0:18:22.27,0:18:22.92,Default,,0,0,0,,这整条AND查询\nDialogue: 0,0:18:23.07,0:18:25.28,Default,,0,0,0,,它实际上会构建这种结构\nDialogue: 0,0:18:25.50,0:18:30.24,Default,,0,0,0,,并使用一本空字典来启动整个过程\nDialogue: 0,0:18:31.77,0:18:34.33,Default,,0,0,0,,处理过程开始后 会产生一系列的字典\nDialogue: 0,0:18:34.36,0:18:37.36,Default,,0,0,0,,其中就有X、Y以及D\nDialogue: 0,0:18:38.64,0:18:39.58,Default,,0,0,0,,向这边传递\nDialogue: 0,0:18:40.19,0:18:42.16,Default,,0,0,0,,这就是这条查询的输入\nDialogue: 0,0:18:42.16,0:18:43.72,Default,,0,0,0,,这条查询也会生成其它的东西\nDialogue: 0,0:18:45.04,0:18:48.22,Default,,0,0,0,,如果这整个查询是构建在一个更大的查询中的话\nDialogue: 0,0:18:49.31,0:18:51.00,Default,,0,0,0,,比如说一条OR查询\nDialogue: 0,0:18:53.42,0:18:55.71,Default,,0,0,0,,那么它将输出到下一个查询中\nDialogue: 0,0:18:58.56,0:19:01.28,Default,,0,0,0,,因此最初开始处理时 只有一本空字典\nDialogue: 0,0:19:01.68,0:19:04.08,Default,,0,0,0,,但是在处理这些复合查询的过程中\nDialogue: 0,0:19:04.11,0:19:06.65,Default,,0,0,0,,会生成各种不同的字典\nDialogue: 0,0:19:07.66,0:19:12.28,Default,,0,0,0,,学生：字典都是查询的结果吗？\nDialogue: 0,0:19:15.12,0:19:17.69,Default,,0,0,0,,它们会变成\nDialogue: 0,0:19:18.84,0:19:22.81,Default,,0,0,0,,它们存储在数据库中吗？\nDialogue: 0,0:19:23.68,0:19:24.98,Default,,0,0,0,,它们是临时数据吗？\nDialogue: 0,0:19:24.98,0:19:27.18,Default,,0,0,0,,教授：它们是在MATCH过程中临时创建的\nDialogue: 0,0:19:28.03,0:19:29.88,Default,,0,0,0,,但它们实际存放在内存中\nDialogue: 0,0:19:29.88,0:19:33.02,Default,,0,0,0,,最初 某人创建了一本THE-EMPTY-DICT字典\nDialogue: 0,0:19:34.22,0:19:36.80,Default,,0,0,0,,送入这个匹配过程\nDialogue: 0,0:19:36.81,0:19:39.05,Default,,0,0,0,,MATCH过程据此构建新字典\nDialogue: 0,0:19:39.07,0:19:40.27,Default,,0,0,0,,并把它们传递下去\nDialogue: 0,0:19:40.76,0:19:42.48,Default,,0,0,0,,学生：因此匹配完成后它们就被丢弃了？\nDialogue: 0,0:19:43.64,0:19:46.25,Default,,0,0,0,,教授：实际上 当没人需要它们后（就被废料回收了）\nDialogue: 0,0:19:51.90,0:19:53.60,Default,,0,0,0,,学生：似乎AND查询对数据库\nDialogue: 0,0:19:53.63,0:19:55.37,Default,,0,0,0,,进行了一些冗余操作\nDialogue: 0,0:19:55.96,0:19:57.48,Default,,0,0,0,,如果第一条子句扫描过了\nDialogue: 0,0:19:57.50,0:19:59.90,Default,,0,0,0,,比如说前两个元素没有匹配 而第三个元素匹配了\nDialogue: 0,0:20:00.25,0:20:03.64,Default,,0,0,0,,然而第二条子句又会检查这两个元素\nDialogue: 0,0:20:04.32,0:20:06.59,Default,,0,0,0,,然后又一次丢弃这些不匹配的元素\nDialogue: 0,0:20:06.64,0:20:08.72,Default,,0,0,0,,而字典中已经有匹配的项了\nDialogue: 0,0:20:10.00,0:20:12.56,Default,,0,0,0,,如果我们把数据库中的数据\nDialogue: 0,0:20:12.57,0:20:14.43,Default,,0,0,0,,跟字典同时传递 这样可行么？\nDialogue: 0,0:20:15.69,0:20:17.60,Default,,0,0,0,,教授：实际上 通常来说\nDialogue: 0,0:20:17.63,0:20:19.48,Default,,0,0,0,,我们能够以其它方式来安排这些搜索\nDialogue: 0,0:20:20.12,0:20:21.74,Default,,0,0,0,,你也可以做一些分析\nDialogue: 0,0:20:21.74,0:20:23.16,Default,,0,0,0,,我记得书里面就有这样的习题\nDialogue: 0,0:20:23.87,0:20:26.65,Default,,0,0,0,,是考察通过安排AND子句的顺序\nDialogue: 0,0:20:27.00,0:20:29.20,Default,,0,0,0,,来消除不同类型的冗余\nDialogue: 0,0:20:29.85,0:20:30.72,Default,,0,0,0,,而这里只是为了\nDialogue: 0,0:20:31.32,0:20:34.54,Default,,0,0,0,,用非常简单的情况来向你们展示它们是如何配合的\nDialogue: 0,0:20:34.70,0:20:35.38,Default,,0,0,0,,但是你说得非常对\nDialogue: 0,0:20:35.38,0:20:37.32,Default,,0,0,0,,这些冗余是可以避免的\nDialogue: 0,0:20:38.37,0:20:40.80,Default,,0,0,0,,这也是这门语言缓慢的原因之一\nDialogue: 0,0:20:41.19,0:20:42.70,Default,,0,0,0,,你们可以让它变得更聪明\nDialogue: 0,0:20:42.93,0:20:46.22,Default,,0,0,0,,我只是为了向你们演示非常简单的、原理性的实现\nDialogue: 0,0:20:51.22,0:20:53.23,Default,,0,0,0,,学生：您是根据Prolog来建模这门语言的\nDialogue: 0,0:20:53.24,0:20:55.13,Default,,0,0,0,,还是说它只是偶然地像Prolog？\nDialogue: 0,0:21:04.96,0:21:07.08,Default,,0,0,0,,教授：Gerry教授昨天羞辱了一大堆人\nDialogue: 0,0:21:07.24,0:21:09.92,Default,,0,0,0,,我想说真实的情况是\nDialogue: 0,0:21:10.19,0:21:12.60,Default,,0,0,0,,MIT的研究人员在1971年做了类似的事\nDialogue: 0,0:21:12.64,0:21:15.60,Default,,0,0,0,,但是发现这个方向并不正确 并停止了研究\nDialogue: 0,0:21:16.12,0:21:22.80,Default,,0,0,0,,因此我们是根据查询处理的基本原理建模的\nDialogue: 0,0:21:22.84,0:21:24.73,Default,,0,0,0,,大概在1971年左右\nDialogue: 0,0:21:25.13,0:21:27.24,Default,,0,0,0,,只是说 那时候我们还没有用流来实现\nDialogue: 0,0:21:28.27,0:21:33.04,Default,,0,0,0,,然后我们 -- 但我们使用了它差不多六个月后\nDialogue: 0,0:21:33.08,0:21:34.91,Default,,0,0,0,,发现它存在各种各样的问题\nDialogue: 0,0:21:34.94,0:21:36.30,Default,,0,0,0,,稍后我会解释\nDialogue: 0,0:21:37.33,0:21:38.19,Default,,0,0,0,,然后我们就想\nDialogue: 0,0:21:38.44,0:21:39.92,Default,,0,0,0,,Prolog一定解决了这些问题\nDialogue: 0,0:21:39.93,0:21:41.21,Default,,0,0,0,,但却发现它并没有\nDialogue: 0,0:21:41.25,0:21:43.02,Default,,0,0,0,,从这种意义上来说 它确实跟Prolog一样\nDialogue: 0,0:21:43.60,0:21:44.95,Default,,0,0,0,,学生：Prolog基于流么？\nDialogue: 0,0:21:44.95,0:21:46.20,Default,,0,0,0,,教授：不 Prolog基于的是\nDialogue: 0,0:21:46.78,0:21:51.04,Default,,0,0,0,,就行为上来说 我们的语言很像Prolog\nDialogue: 0,0:21:51.04,0:21:52.96,Default,,0,0,0,,Prolog使用回溯策略\nDialogue: 0,0:21:53.80,0:21:55.71,Default,,0,0,0,,但是Prolog有一个优点非常好\nDialogue: 0,0:21:55.72,0:21:57.98,Default,,0,0,0,,也使得它变得实用\nDialogue: 0,0:21:58.28,0:22:01.50,Default,,0,0,0,,你知道吗\nDialogue: 0,0:22:01.68,0:22:04.09,Default,,0,0,0,,它们精心设计了Prolog的编译器\nDialogue: 0,0:22:04.11,0:22:05.32,Default,,0,0,0,,使得它能够高速运行\nDialogue: 0,0:22:06.65,0:22:10.81,Default,,0,0,0,,因此 虽然我们这门语言非常缓慢地输出答案\nDialogue: 0,0:22:11.66,0:22:13.61,Default,,0,0,0,,真正的Prolog程序却运行得非常快\nDialogue: 0,0:22:14.70,0:22:16.48,Default,,0,0,0,,这是因为 尽管搜索过程十分低效\nDialogue: 0,0:22:16.67,0:22:20.81,Default,,0,0,0,,Prolog卓越的编译器也会高效地完成工作\nDialogue: 0,0:22:24.30,0:22:25.21,Default,,0,0,0,,休息一下吧\nDialogue: 0,0:22:25.42,0:22:36.17,Default,,0,0,0,,[音乐]\nDialogue: 0,0:22:36.35,0:22:39.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:23:01.48,0:23:05.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:23:05.18,0:23:09.05,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:23:09.12,0:23:13.66,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 II\nDialogue: 0,0:23:16.65,0:23:18.83,Default,,0,0,0,,我们已经考察过了基本查询\nDialogue: 0,0:23:19.21,0:23:23.52,Default,,0,0,0,,以及如何使用流来实现组合手段\nDialogue: 0,0:23:23.79,0:23:25.72,Default,,0,0,0,,AND、OR以及NOT\nDialogue: 0,0:23:26.95,0:23:28.43,Default,,0,0,0,,现在 该讨论抽象手段了\nDialogue: 0,0:23:29.58,0:23:32.80,Default,,0,0,0,,回想一下 我们这门语言的抽象手段是RULE\nDialogue: 0,0:23:35.15,0:23:37.79,Default,,0,0,0,,(BOSS ?Z ?D)描述的是\nDialogue: 0,0:23:39.18,0:23:43.77,Default,,0,0,0,,如果某人在D部门工作\nDialogue: 0,0:23:45.68,0:23:47.47,Default,,0,0,0,,并且Z是X的上司\nDialogue: 0,0:23:48.90,0:23:50.60,Default,,0,0,0,,这就是所谓的“BOSS”\nDialogue: 0,0:23:52.26,0:23:53.15,Default,,0,0,0,,并且 实际上\nDialogue: 0,0:23:53.34,0:23:55.61,Default,,0,0,0,,如果我们考察一下编写的规则与这边的关系\nDialogue: 0,0:23:56.80,0:23:57.90,Default,,0,0,0,,这是我们编写的查询\nDialogue: 0,0:23:57.93,0:24:01.90,Default,,0,0,0,,这个是(JOB ?X ?D) 而这个是(SUPERVISOR ?X ?Z)\nDialogue: 0,0:24:02.19,0:24:04.28,Default,,0,0,0,,我们实际想要把这一大堆东西\nDialogue: 0,0:24:05.07,0:24:06.57,Default,,0,0,0,,用一个盒子封装起来\nDialogue: 0,0:24:19.08,0:24:24.54,Default,,0,0,0,,然后把这个盒子里的所有东西\nDialogue: 0,0:24:25.15,0:24:32.48,Default,,0,0,0,,认为是(BOSS ?Z ?D)\nDialogue: 0,0:24:33.90,0:24:35.25,Default,,0,0,0,,这是我们想要达到的效果\nDialogue: 0,0:24:38.72,0:24:39.72,Default,,0,0,0,,因此 比如说\nDialogue: 0,0:24:43.18,0:24:44.08,Default,,0,0,0,,我们这样做了过后\nDialogue: 0,0:24:45.00,0:24:47.84,Default,,0,0,0,,我们想要检查\nDialogue: 0,0:24:47.95,0:24:50.51,Default,,0,0,0,,Ben Bitdiddle是否为计算机分部的BOSS\nDialogue: 0,0:24:51.10,0:25:02.86,Default,,0,0,0,,如果我想查询 (BOSS (BITDIDDLE BEN) COMPUTER)\nDialogue: 0,0:25:04.78,0:25:07.08,Default,,0,0,0,,想象一下把这条查询输入系统\nDialogue: 0,0:25:07.12,0:25:09.16,Default,,0,0,0,,实际上发生的是\nDialogue: 0,0:25:10.67,0:25:12.92,Default,,0,0,0,,在这里先构建一本字典\nDialogue: 0,0:25:15.82,0:25:23.63,Default,,0,0,0,,其中 ?Z=BITDIDDLE\nDialogue: 0,0:25:28.88,0:25:33.31,Default,,0,0,0,,?D=COMPUTER\nDialogue: 0,0:25:37.08,0:25:38.62,Default,,0,0,0,,这个字典又是来自于哪里呢？\nDialogue: 0,0:25:38.68,0:25:40.71,Default,,0,0,0,,我们来看下幻灯片\nDialogue: 0,0:25:40.71,0:25:43.71,Default,,0,0,0,,这本字典是通过把\nDialogue: 0,0:25:44.30,0:25:46.33,Default,,0,0,0,,查询(BOSS (BITDIDDLE BEN) COMPUTER)\nDialogue: 0,0:25:46.51,0:25:49.63,Default,,0,0,0,,与规则的结论(BOSS ?Z ?D)相匹配得到\nDialogue: 0,0:25:51.65,0:25:54.11,Default,,0,0,0,,所以我们把规则的结论和查询匹配了起来\nDialogue: 0,0:25:54.19,0:25:55.53,Default,,0,0,0,,这样我们就获得了一本字典\nDialogue: 0,0:25:58.99,0:26:02.54,Default,,0,0,0,,现在我们就要把这本字典输入到这整个结构中\nDialogue: 0,0:26:02.92,0:26:05.56,Default,,0,0,0,,进行处理 并观察是否有输出\nDialogue: 0,0:26:06.67,0:26:09.88,Default,,0,0,0,,如果输出了结果 那么查询就为真\nDialogue: 0,0:26:11.33,0:26:12.37,Default,,0,0,0,,这是基本的思想\nDialogue: 0,0:26:12.37,0:26:13.24,Default,,0,0,0,,因此 通常来说\nDialogue: 0,0:26:14.03,0:26:15.40,Default,,0,0,0,,我们实现规则的方法就是\nDialogue: 0,0:26:15.85,0:26:18.89,Default,,0,0,0,,用规则的结论去匹配\nDialogue: 0,0:26:20.86,0:26:22.96,Default,,0,0,0,,假设为真的查询\nDialogue: 0,0:26:23.58,0:26:25.12,Default,,0,0,0,,这个过程会产生一本字典\nDialogue: 0,0:26:25.29,0:26:28.22,Default,,0,0,0,,在有了相关字典后\nDialogue: 0,0:26:30.35,0:26:34.51,Default,,0,0,0,,我们来处理规则的体\nDialogue: 0,0:26:36.33,0:26:37.68,Default,,0,0,0,,基本上就是这样了\nDialogue: 0,0:26:38.64,0:26:41.44,Default,,0,0,0,,但还有两个技术点\nDialogue: 0,0:26:43.04,0:26:44.32,Default,,0,0,0,,首先就是\nDialogue: 0,0:26:45.74,0:26:47.26,Default,,0,0,0,,我也可能有其它的问法\nDialogue: 0,0:26:47.51,0:26:48.41,Default,,0,0,0,,比如说\nDialogue: 0,0:26:50.54,0:26:52.36,Default,,0,0,0,,查询计算机分部的BOSS\nDialogue: 0,0:26:52.54,0:26:56.32,Default,,0,0,0,,就可以查询 (BOSS ?WHO COMPUTER)\nDialogue: 0,0:27:00.78,0:27:01.63,Default,,0,0,0,,这样做了以后\nDialogue: 0,0:27:02.57,0:27:04.62,Default,,0,0,0,,我真正想要做的\nDialogue: 0,0:27:05.04,0:27:06.49,Default,,0,0,0,,就是先建立一本字典\nDialogue: 0,0:27:08.35,0:27:09.88,Default,,0,0,0,,其中有一些约束\nDialogue: 0,0:27:09.93,0:27:11.20,Default,,0,0,0,,比如 ?D=COMPUTER\nDialogue: 0,0:27:14.35,0:27:18.48,Default,,0,0,0,,而?Z等同于?WHO\nDialogue: 0,0:27:21.70,0:27:23.22,Default,,0,0,0,,我们的匹配器不会那么做\nDialogue: 0,0:27:23.22,0:27:27.00,Default,,0,0,0,,这不是模式和数据的匹配方式\nDialogue: 0,0:27:28.58,0:27:29.72,Default,,0,0,0,,这是在匹配两个模式\nDialogue: 0,0:27:29.74,0:27:31.58,Default,,0,0,0,,并判断它们是否一致\nDialogue: 0,0:27:31.90,0:27:33.48,Default,,0,0,0,,又是什么使它们不一致\nDialogue: 0,0:27:33.48,0:27:36.43,Default,,0,0,0,,换句话说 我们需要的不是一个模式匹配器\nDialogue: 0,0:27:36.96,0:27:38.91,Default,,0,0,0,,而是一种更一般性的东西\nDialogue: 0,0:27:39.13,0:27:40.11,Default,,0,0,0,,就是“合一”算法\nDialogue: 0,0:27:44.42,0:27:48.06,Default,,0,0,0,,“合一”是更为一般化的模式匹配算法\nDialogue: 0,0:27:49.53,0:27:52.17,Default,,0,0,0,,合一算法接收两条模式\nDialogue: 0,0:27:53.23,0:27:57.53,Default,,0,0,0,,它考虑的是：可以找到哪些一般性的元素\nDialogue: 0,0:27:58.20,0:28:00.01,Default,,0,0,0,,用来代换模式中的变量\nDialogue: 0,0:28:02.68,0:28:05.08,Default,,0,0,0,,使得它俩能够同时满足\nDialogue: 0,0:28:05.68,0:28:06.60,Default,,0,0,0,,让我来举个例子\nDialogue: 0,0:28:08.86,0:28:14.49,Default,,0,0,0,,我有一个含有两个元素的模式：(?X ?X)\nDialogue: 0,0:28:15.76,0:28:17.15,Default,,0,0,0,,它描述的是一个二元表\nDialogue: 0,0:28:17.32,0:28:18.64,Default,,0,0,0,,不管元素具体是什么\nDialogue: 0,0:28:18.67,0:28:20.04,Default,,0,0,0,,但两个元素是相同的\nDialogue: 0,0:28:20.40,0:28:22.83,Default,,0,0,0,,我把它与另一个模式进行“合一”\nDialogue: 0,0:28:22.92,0:28:24.62,Default,,0,0,0,,后者描述的是一个二元表\nDialogue: 0,0:28:24.65,0:28:27.61,Default,,0,0,0,,首元素一张由A、?Y、C构成的表\nDialogue: 0,0:28:28.00,0:28:30.14,Default,,0,0,0,,而第二个元素是由A、B、?Z构成的表\nDialogue: 0,0:28:33.07,0:28:34.88,Default,,0,0,0,,那么 合一算法能够告诉我\nDialogue: 0,0:28:34.89,0:28:36.17,Default,,0,0,0,,在生成的字典中\nDialogue: 0,0:28:36.35,0:28:37.96,Default,,0,0,0,,?X必须是(A B C)\nDialogue: 0,0:28:39.34,0:28:41.92,Default,,0,0,0,,?Y必须为B ?Z必须为C\nDialogue: 0,0:28:43.44,0:28:46.28,Default,,0,0,0,,这些是我必须对X、Y以及Z施加的约束\nDialogue: 0,0:28:46.33,0:28:47.58,Default,,0,0,0,,以便让两个模式合一\nDialogue: 0,0:28:48.12,0:28:50.84,Default,,0,0,0,,或者换句话来说 让它匹配这个?X\nDialogue: 0,0:28:51.15,0:28:53.37,Default,,0,0,0,,让它匹配这个?X\nDialogue: 0,0:28:55.28,0:28:57.76,Default,,0,0,0,,合一算法需要能够推断出这些\nDialogue: 0,0:28:58.54,0:29:01.08,Default,,0,0,0,,但是合一算法也会遇到复杂的情况\nDialogue: 0,0:29:01.08,0:29:03.07,Default,,0,0,0,,我可能会询问一些复杂的查询\nDialogue: 0,0:29:03.48,0:29:05.74,Default,,0,0,0,,比如这是一个二元表\nDialogue: 0,0:29:07.00,0:29:08.28,Default,,0,0,0,,其中的元素都是相同的\nDialogue: 0,0:29:08.86,0:29:11.15,Default,,0,0,0,,它要与这个模式进行合一\nDialogue: 0,0:29:12.65,0:29:15.36,Default,,0,0,0,,合一算法也要能够从中推断出\nDialogue: 0,0:29:16.89,0:29:19.57,Default,,0,0,0,,?Y必须为B\nDialogue: 0,0:29:19.57,0:29:22.12,Default,,0,0,0,,因为这两个是一样的\nDialogue: 0,0:29:22.22,0:29:23.52,Default,,0,0,0,,因此?Y就是B\nDialogue: 0,0:29:24.34,0:29:27.53,Default,,0,0,0,,这里 ?V应该为A\nDialogue: 0,0:29:28.94,0:29:30.99,Default,,0,0,0,,只要?Z和?W取值相同\nDialogue: 0,0:29:31.00,0:29:32.43,Default,,0,0,0,,它们就可以是任意值\nDialogue: 0,0:29:35.71,0:29:41.76,Default,,0,0,0,,?X就应该是(B A ?W) 其中?W为任意值\nDialogue: 0,0:29:42.83,0:29:44.68,Default,,0,0,0,,或者是?Z -- 因为?Z和?W是一致的\nDialogue: 0,0:29:44.70,0:29:49.42,Default,,0,0,0,,发现了么 合一算法需要从这些模式中推断出信息\nDialogue: 0,0:29:50.88,0:29:53.52,Default,,0,0,0,,所以你们可能认为 这其中有某种魔法般的推理\nDialogue: 0,0:29:54.27,0:29:55.23,Default,,0,0,0,,但其实并不是\nDialogue: 0,0:29:55.85,0:29:59.88,Default,,0,0,0,,合一算法基本上只是对模式匹配的小小修改\nDialogue: 0,0:30:00.15,0:30:01.85,Default,,0,0,0,,如果你们翻阅教材 就会发现\nDialogue: 0,0:30:02.25,0:30:06.16,Default,,0,0,0,,在模式匹配算法中加入了三到四行代码\nDialogue: 0,0:30:06.49,0:30:08.17,Default,,0,0,0,,来处理对称的情况\nDialogue: 0,0:30:08.28,0:30:10.81,Default,,0,0,0,,还记得吗 模式匹配中有一处代码判断\nDialogue: 0,0:30:11.66,0:30:14.28,Default,,0,0,0,,这个变量匹配一个常量吗？\nDialogue: 0,0:30:14.98,0:30:16.42,Default,,0,0,0,,如果是的话 就在字典中进行检查\nDialogue: 0,0:30:16.42,0:30:18.25,Default,,0,0,0,,在合一算法中只有另一条子句\nDialogue: 0,0:30:18.49,0:30:20.75,Default,,0,0,0,,它判断两个变量是否相匹配\nDialogue: 0,0:30:22.00,0:30:23.42,Default,,0,0,0,,这种情况下你去查询字典\nDialogue: 0,0:30:23.45,0:30:25.68,Default,,0,0,0,,看它们在字典的约束下是否一致\nDialogue: 0,0:30:27.03,0:30:31.13,Default,,0,0,0,,因此 这门语言中的所有“推断”\nDialogue: 0,0:30:31.28,0:30:34.59,Default,,0,0,0,,你会发现它蕴含在规则应用中\nDialogue: 0,0:30:34.99,0:30:37.88,Default,,0,0,0,,更进一步地考察 你会发现在合一算法中\nDialogue: 0,0:30:38.36,0:30:40.32,Default,,0,0,0,,如果更进一步地用“显微镜”观察\nDialogue: 0,0:30:40.56,0:30:43.96,Default,,0,0,0,,基本上就在模式匹配算法中\nDialogue: 0,0:30:44.94,0:30:47.07,Default,,0,0,0,,这其中并没有什么魔法\nDialogue: 0,0:30:47.41,0:30:50.25,Default,,0,0,0,,而你们所见到的“推断”\nDialogue: 0,0:30:50.94,0:30:52.89,Default,,0,0,0,,只是因为其中的递归\nDialogue: 0,0:30:52.92,0:30:55.69,Default,,0,0,0,,它一点一点地回绕MATCH过程\nDialogue: 0,0:30:56.03,0:30:58.03,Default,,0,0,0,,它让这个过程看起来很聪明\nDialogue: 0,0:30:58.44,0:31:00.36,Default,,0,0,0,,但它实际上并不是那么聪明\nDialogue: 0,0:31:02.14,0:31:04.41,Default,,0,0,0,,当然 合一算法需要聪明地识别出一些情况\nDialogue: 0,0:31:04.88,0:31:05.87,Default,,0,0,0,,我来举个例子吧\nDialogue: 0,0:31:11.07,0:31:13.36,Default,,0,0,0,,假设我想要用一个二元表进行合一\nDialogue: 0,0:31:13.48,0:31:14.81,Default,,0,0,0,,(?X ?X)\nDialogue: 0,0:31:17.24,0:31:22.14,Default,,0,0,0,,另一个模式则是 (?Y (a . ?Y))\nDialogue: 0,0:31:24.37,0:31:26.12,Default,,0,0,0,,现在 如果你想一想它所表达的意思\nDialogue: 0,0:31:26.86,0:31:29.71,Default,,0,0,0,,它表示了?X应该跟?Y一致\nDialogue: 0,0:31:30.92,0:31:31.66,Default,,0,0,0,,同时呢\nDialogue: 0,0:31:31.82,0:31:36.16,Default,,0,0,0,,?X又应该跟(A . ?Y)相同\nDialogue: 0,0:31:37.33,0:31:39.45,Default,,0,0,0,,如果你仔细思考它成立的条件\nDialogue: 0,0:31:42.27,0:31:44.71,Default,,0,0,0,,你会发现 ?Y必须是一个由A构成的无穷表\nDialogue: 0,0:31:47.50,0:31:48.35,Default,,0,0,0,,从某种角度来说\nDialogue: 0,0:31:49.21,0:31:52.40,Default,,0,0,0,,为了完成这样的合一\nDialogue: 0,0:31:52.60,0:31:54.84,Default,,0,0,0,,我需要求解一个不动点方程\nDialogue: 0,0:31:55.05,0:32:01.84,Default,,0,0,0,,(CONS 'A Y)=Y\nDialogue: 0,0:32:04.57,0:32:06.96,Default,,0,0,0,,通常来说 --- 我这个例子很简单\nDialogue: 0,0:32:07.29,0:32:08.67,Default,,0,0,0,,但实际进行合一时\nDialogue: 0,0:32:08.97,0:32:11.98,Default,,0,0,0,,我们可能要求解一个任意的不动点方程\nDialogue: 0,0:32:12.01,0:32:13.42,Default,,0,0,0,,(F Y)=Y\nDialogue: 0,0:32:15.53,0:32:17.08,Default,,0,0,0,,你基本上不能保证\nDialogue: 0,0:32:17.10,0:32:19.47,Default,,0,0,0,,在有穷时间内找到解\nDialogue: 0,0:32:20.57,0:32:23.60,Default,,0,0,0,,我们的逻辑语言又该如何处理这类情况呢？\nDialogue: 0,0:32:24.89,0:32:26.48,Default,,0,0,0,,答案就是：“不处理”\nDialogue: 0,0:32:27.16,0:32:28.04,Default,,0,0,0,,它会撒手不干\nDialogue: 0,0:32:28.73,0:32:31.07,Default,,0,0,0,,合一算法中有一处小检查\nDialogue: 0,0:32:31.31,0:32:33.82,Default,,0,0,0,,用来判断是否为困难的情况\nDialogue: 0,0:32:34.44,0:32:38.00,Default,,0,0,0,,也就是 匹配这些东西需要求解不动点方程\nDialogue: 0,0:32:38.65,0:32:40.81,Default,,0,0,0,,遇到这类情况 我就撒手不干\nDialogue: 0,0:32:42.84,0:32:44.65,Default,,0,0,0,,如果不进行这样的检查\nDialogue: 0,0:32:45.00,0:32:45.88,Default,,0,0,0,,会发生什么情况？\nDialogue: 0,0:32:47.99,0:32:49.10,Default,,0,0,0,,大多数情况就是\nDialogue: 0,0:32:49.13,0:32:51.31,Default,,0,0,0,,合一算法会陷入无穷循环\nDialogue: 0,0:32:53.74,0:32:56.54,Default,,0,0,0,,其它的逻辑语言有类似的工作原理\nDialogue: 0,0:32:56.80,0:32:58.14,Default,,0,0,0,,因此这其中没有什么魔法\nDialogue: 0,0:32:58.22,0:32:59.93,Default,,0,0,0,,简单的情况由匹配器完成\nDialogue: 0,0:33:00.10,0:33:01.58,Default,,0,0,0,,困难的情况根本不去处理\nDialogue: 0,0:33:02.96,0:33:05.47,Default,,0,0,0,,这就是这种技术的现状\nDialogue: 0,0:33:11.88,0:33:14.24,Default,,0,0,0,,现在 我来形式化地描述一下\nDialogue: 0,0:33:14.27,0:33:16.38,Default,,0,0,0,,规则系统的运行原理 -- 也就是合一算法\nDialogue: 0,0:33:17.39,0:33:18.75,Default,,0,0,0,,因此 正式的定义就是\nDialogue: 0,0:33:19.20,0:33:20.96,Default,,0,0,0,,应用一条规则\nDialogue: 0,0:33:24.17,0:33:27.13,Default,,0,0,0,,我们需要使用一些之前的术语\nDialogue: 0,0:33:28.27,0:33:32.01,Default,,0,0,0,,我们把向查询的盒子中\nDialogue: 0,0:33:32.88,0:33:34.78,Default,,0,0,0,,塞入字典称作是\nDialogue: 0,0:33:34.81,0:33:38.54,Default,,0,0,0,,相对一个环境或者框架\nDialogue: 0,0:33:39.95,0:33:43.85,Default,,0,0,0,,对这些大型查询求值\nDialogue: 0,0:33:43.85,0:33:45.04,Default,,0,0,0,,因此 当我们谈及“字典”的时候\nDialogue: 0,0:33:45.07,0:33:46.28,Default,,0,0,0,,“字典”究竟是什么？\nDialogue: 0,0:33:46.72,0:33:48.18,Default,,0,0,0,,它是符号的一系列语义\nDialogue: 0,0:33:48.18,0:33:50.22,Default,,0,0,0,,我们把它叫做“框架”或者“环境”\nDialogue: 0,0:33:51.80,0:33:55.97,Default,,0,0,0,,根据环境进行操作 又是什么？\nDialogue: 0,0:33:55.97,0:33:57.42,Default,,0,0,0,,我们把这个叫做“求值”\nDialogue: 0,0:33:58.33,0:34:01.56,Default,,0,0,0,,因此我们就说 应用一条规则的方法是\nDialogue: 0,0:34:01.92,0:34:06.16,Default,,0,0,0,,先通过将给定的查询与规则的结论合一 得到环境\nDialogue: 0,0:34:06.67,0:34:11.58,Default,,0,0,0,,再在该环境中求值相应规则的体\nDialogue: 0,0:34:13.23,0:34:14.51,Default,,0,0,0,,我想要让你们注意的是\nDialogue: 0,0:34:14.80,0:34:17.08,Default,,0,0,0,,这非常像是\nDialogue: 0,0:34:18.16,0:34:21.50,Default,,0,0,0,,元循环求值器以及代换模型\nDialogue: 0,0:34:21.63,0:34:22.73,Default,,0,0,0,,规则的应用就是\nDialogue: 0,0:34:22.86,0:34:28.36,Default,,0,0,0,,在一个环境中求值规则的体\nDialogue: 0,0:34:28.54,0:34:33.13,Default,,0,0,0,,环境是通过将实际参数与形式参数绑定起来得到的\nDialogue: 0,0:34:34.56,0:34:36.41,Default,,0,0,0,,规则、规则的应用、过程的应用\nDialogue: 0,0:34:36.44,0:34:40.41,Default,,0,0,0,,它们在形式上完全相似\nDialogue: 0,0:34:40.57,0:34:42.30,Default,,0,0,0,,尽管它们又非常不同\nDialogue: 0,0:34:43.65,0:34:45.61,Default,,0,0,0,,再一次地出现了EVAL-APPLY循环\nDialogue: 0,0:34:47.29,0:34:49.52,Default,,0,0,0,,EVAL-APPLY\nDialogue: 0,0:34:53.39,0:34:57.39,Default,,0,0,0,,因此通常来说 我们可能会处理一些复合表达式\nDialogue: 0,0:34:57.42,0:34:59.13,Default,,0,0,0,,它们会变成规则的应用\nDialogue: 0,0:35:00.70,0:35:03.28,Default,,0,0,0,,进一步又会产生字典、框架或者环境\nDialogue: 0,0:35:03.31,0:35:04.72,Default,,0,0,0,,不管你要怎么叫它\nDialogue: 0,0:35:05.02,0:35:08.43,Default,,0,0,0,,它们随后又会作为某个大的复合对象的输入\nDialogue: 0,0:35:08.66,0:35:11.77,Default,,0,0,0,,这有它的一部分 并可能有其它规则的应用\nDialogue: 0,0:35:13.58,0:35:15.68,Default,,0,0,0,,这基本上就是相同的循环\nDialogue: 0,0:35:15.72,0:35:18.68,Default,,0,0,0,,尽管这里没有什么东西看起来像过程\nDialogue: 0,0:35:19.68,0:35:21.87,Default,,0,0,0,,这是因为我们创建的语言\nDialogue: 0,0:35:22.08,0:35:25.49,Default,,0,0,0,,它们的组合手段和抽象手段以某种方式展开\nDialogue: 0,0:35:28.77,0:35:29.52,Default,,0,0,0,,通常来说\nDialogue: 0,0:35:29.77,0:35:31.39,Default,,0,0,0,,最顶层所发生的是\nDialogue: 0,0:35:33.79,0:35:35.96,Default,,0,0,0,,数据库中也有一些规则\nDialogue: 0,0:35:36.65,0:35:38.70,Default,,0,0,0,,数据库中的数据也可能是规则\nDialogue: 0,0:35:40.46,0:35:42.06,Default,,0,0,0,,它们用来检查对象是否为真\nDialogue: 0,0:35:42.92,0:35:44.89,Default,,0,0,0,,所以这里可能会有规则检查\nDialogue: 0,0:35:46.75,0:35:48.16,Default,,0,0,0,,然后就会有一些控制结构\nDialogue: 0,0:35:48.19,0:35:50.48,Default,,0,0,0,,用来判断你访问的是规则\nDialogue: 0,0:35:50.51,0:35:51.80,Default,,0,0,0,,还是数据元素\nDialogue: 0,0:35:51.84,0:35:53.12,Default,,0,0,0,,然后不断地把它们扇出来开\nDialogue: 0,0:35:53.35,0:35:55.48,Default,,0,0,0,,所以基本上不可能说清楚\nDialogue: 0,0:35:55.68,0:35:57.69,Default,,0,0,0,,是用什么样的顺序来查询这些东西的\nDialogue: 0,0:35:58.20,0:36:00.27,Default,,0,0,0,,是广度优先还是深度优先\nDialogue: 0,0:36:00.28,0:36:01.64,Default,,0,0,0,,另外一个原因是\nDialogue: 0,0:36:01.66,0:36:05.58,Default,,0,0,0,,我们通过惰性流隐藏了实际执行顺序\nDialogue: 0,0:36:07.69,0:36:11.16,Default,,0,0,0,,因此很难说清楚它的扫描顺序\nDialogue: 0,0:36:11.27,0:36:12.16,Default,,0,0,0,,但真实的是\nDialogue: 0,0:36:12.19,0:36:13.64,Default,,0,0,0,,由于你是在流视图观察它的\nDialogue: 0,0:36:13.90,0:36:15.82,Default,,0,0,0,,而它们最终都要被扫描到\nDialogue: 0,0:36:24.98,0:36:28.15,Default,,0,0,0,,这里还有一个小小的技术问题\nDialogue: 0,0:36:30.88,0:36:33.55,Default,,0,0,0,,假设我在这里输入\nDialogue: 0,0:36:37.53,0:36:41.00,Default,,0,0,0,,假设我输入(BOSS ?Y COMPUTER)\nDialogue: 0,0:36:44.22,0:36:45.78,Default,,0,0,0,,然后就会发生一件有意思的事儿\nDialogue: 0,0:36:45.78,0:36:50.25,Default,,0,0,0,,这里的字典就有一项?Y\nDialogue: 0,0:36:52.73,0:36:57.37,Default,,0,0,0,,而这两个?Y是不相同的\nDialogue: 0,0:36:57.42,0:37:00.62,Default,,0,0,0,,后者是其它人的工作描述\nDialogue: 0,0:37:01.58,0:37:03.80,Default,,0,0,0,,因此 按照输入“照本宣科”地执行的话\nDialogue: 0,0:37:04.22,0:37:06.44,Default,,0,0,0,,我们就会遇到变量冲突的问题\nDialogue: 0,0:37:09.28,0:37:10.48,Default,,0,0,0,,所以我骗了你们一下\nDialogue: 0,0:37:10.93,0:37:13.84,Default,,0,0,0,,注意 我们之前也遇到过同样的问题\nDialogue: 0,0:37:14.27,0:37:15.56,Default,,0,0,0,,具体来说就是\nDialogue: 0,0:37:15.96,0:37:18.36,Default,,0,0,0,,一门语言需要局部变量\nDialogue: 0,0:37:19.24,0:37:21.74,Default,,0,0,0,,当我计算SQUARE和SUM-SQUARES的时候\nDialogue: 0,0:37:21.79,0:37:23.39,Default,,0,0,0,,这两个X应该是不同的\nDialogue: 0,0:37:24.96,0:37:26.32,Default,,0,0,0,,同样的道理\nDialogue: 0,0:37:27.39,0:37:29.77,Default,,0,0,0,,这两个?Y应该也不相同\nDialogue: 0,0:37:31.80,0:37:32.75,Default,,0,0,0,,我们知道该如何解决\nDialogue: 0,0:37:32.78,0:37:34.49,Default,,0,0,0,,就是引入环境模型\nDialogue: 0,0:37:34.51,0:37:37.04,Default,,0,0,0,,我们构建类似于“框架链”一类的东西\nDialogue: 0,0:37:37.71,0:37:39.10,Default,,0,0,0,,还有更加“粗暴”的解决方法\nDialogue: 0,0:37:39.10,0:37:41.73,Default,,0,0,0,,在查询语言中 我们根本不这么做\nDialogue: 0,0:37:41.73,0:37:43.18,Default,,0,0,0,,我们的解决方法非常粗暴\nDialogue: 0,0:37:43.54,0:37:45.93,Default,,0,0,0,,我们规定 每次你在应用一条规则的时候\nDialogue: 0,0:37:47.26,0:37:49.63,Default,,0,0,0,,用一个不会引起冲突的唯一名字\nDialogue: 0,0:37:49.77,0:37:53.50,Default,,0,0,0,,统一地为规则中的所有变量更名\nDialogue: 0,0:37:54.04,0:37:57.10,Default,,0,0,0,,这个从概念上来说更简单\nDialogue: 0,0:37:57.12,0:37:59.24,Default,,0,0,0,,但既粗暴 又不是很有效\nDialogue: 0,0:37:59.97,0:38:01.15,Default,,0,0,0,,但是请注意\nDialogue: 0,0:38:01.39,0:38:04.68,Default,,0,0,0,,如果我们对Lisp中定义的过程也这么处理\nDialogue: 0,0:38:05.50,0:38:08.72,Default,,0,0,0,,那么就不需要环境模型了\nDialogue: 0,0:38:08.75,0:38:11.56,Default,,0,0,0,,如果我们每次在应用一个过程的时候\nDialogue: 0,0:38:11.87,0:38:13.90,Default,,0,0,0,,我们为过程中的所有变量更名\nDialogue: 0,0:38:14.19,0:38:16.28,Default,,0,0,0,,那么我们就不需要担心局部变量了\nDialogue: 0,0:38:16.33,0:38:17.39,Default,,0,0,0,,因为它们不会出现\nDialogue: 0,0:38:19.04,0:38:20.41,Default,,0,0,0,,但这种做法比较低效\nDialogue: 0,0:38:20.91,0:38:23.04,Default,,0,0,0,,在我们的查询语言中同样也比较低效\nDialogue: 0,0:38:23.29,0:38:24.59,Default,,0,0,0,,但我们还是这样做了 并让它保持简单\nDialogue: 0,0:38:25.61,0:38:26.67,Default,,0,0,0,,有问题吗？\nDialogue: 0,0:38:30.88,0:38:33.39,Default,,0,0,0,,学生：您这一小节开始的时候\nDialogue: 0,0:38:33.40,0:38:39.60,Default,,0,0,0,,就强调APPLY-EVAL模型是多么的强大\nDialogue: 0,0:38:39.63,0:38:41.17,Default,,0,0,0,,以至于任何语言都适用\nDialogue: 0,0:38:41.17,0:38:43.39,Default,,0,0,0,,但你又说这门语言将会非常不同\nDialogue: 0,0:38:43.95,0:38:45.13,Default,,0,0,0,,但最后却发现这门语言\nDialogue: 0,0:38:45.58,0:38:47.88,Default,,0,0,0,,就像你指出的那样--也是同样的\nDialogue: 0,0:38:47.88,0:38:49.85,Default,,0,0,0,,我在想 您是否是在论证\nDialogue: 0,0:38:50.48,0:38:54.57,Default,,0,0,0,,所有的语言都可以转化成 规则或过程的应用\nDialogue: 0,0:38:55.12,0:38:55.98,Default,,0,0,0,,或者类似的\nDialogue: 0,0:38:57.07,0:38:58.88,Default,,0,0,0,,教授：可以说 几乎所有语言\nDialogue: 0,0:38:58.92,0:39:00.30,Default,,0,0,0,,我们通过组合手段构建对象\nDialogue: 0,0:39:00.92,0:39:04.40,Default,,0,0,0,,用简单的名字给它们命名\nDialogue: 0,0:39:04.70,0:39:06.86,Default,,0,0,0,,你可以把任何类似的 比如\nDialogue: 0,0:39:07.79,0:39:09.90,Default,,0,0,0,,有一种一般性的表达式\nDialogue: 0,0:39:09.98,0:39:11.40,Default,,0,0,0,,比如说如何计算某数的平方\nDialogue: 0,0:39:12.03,0:39:14.20,Default,,0,0,0,,几乎所有的东西都可以称为“过程”\nDialogue: 0,0:39:14.88,0:39:15.88,Default,,0,0,0,,如果语言中有这么一部分的话\nDialogue: 0,0:39:15.90,0:39:17.24,Default,,0,0,0,,那么你就需要能够展开它们\nDialogue: 0,0:39:18.02,0:39:20.19,Default,,0,0,0,,你需要有某种组织 使得\nDialogue: 0,0:39:20.57,0:39:24.03,Default,,0,0,0,,当你查看这些抽象变量 或者说标签的时候\nDialogue: 0,0:39:24.06,0:39:27.10,Default,,0,0,0,,它们可能代表着某些特定的东西\nDialogue: 0,0:39:28.33,0:39:29.34,Default,,0,0,0,,你必须一直跟踪它们\nDialogue: 0,0:39:29.39,0:39:30.91,Default,,0,0,0,,这就会形成类似于环境的结构\nDialogue: 0,0:39:31.72,0:39:32.54,Default,,0,0,0,,让后当你要\nDialogue: 0,0:39:32.70,0:39:35.26,Default,,0,0,0,,展开复合对象其中的一个部分的时候\nDialogue: 0,0:39:35.80,0:39:37.44,Default,,0,0,0,,你就需要EVAL-APPLY循环了\nDialogue: 0,0:39:39.97,0:39:43.20,Default,,0,0,0,,有很多很多的语言有这样的特点\nDialogue: 0,0:39:43.36,0:39:45.40,Default,,0,0,0,,它们也是按这种方式组织的\nDialogue: 0,0:39:45.59,0:39:47.20,Default,,0,0,0,,而这门语言特殊之处在于\nDialogue: 0,0:39:47.21,0:39:49.50,Default,,0,0,0,,从外界看 并没有“过程”\nDialogue: 0,0:39:50.69,0:39:52.68,Default,,0,0,0,,而当你剖开表层 深入到实现中去\nDialogue: 0,0:39:52.70,0:39:54.24,Default,,0,0,0,,当然 你会发现本质是一样的\nDialogue: 0,0:39:54.87,0:39:56.95,Default,,0,0,0,,但是从外界来看 这是一种非常不同的世界观\nDialogue: 0,0:39:56.95,0:39:58.54,Default,,0,0,0,,你没有计算输入的函数\nDialogue: 0,0:40:03.97,0:40:05.71,Default,,0,0,0,,学生：您之前提到过\nDialogue: 0,0:40:06.60,0:40:09.55,Default,,0,0,0,,当用模式匹配来实现这些规则时\nDialogue: 0,0:40:10.01,0:40:11.42,Default,,0,0,0,,由于使用了流实现延迟求值\nDialogue: 0,0:40:11.45,0:40:12.72,Default,,0,0,0,,所以没有办法知道\nDialogue: 0,0:40:13.37,0:40:15.36,Default,,0,0,0,,对象的求值顺序\nDialogue: 0,0:40:15.58,0:40:15.94,Default,,0,0,0,,教授：是这样的\nDialogue: 0,0:40:15.94,0:40:18.28,Default,,0,0,0,,学生：但这就表明\nDialogue: 0,0:40:18.94,0:40:22.28,Default,,0,0,0,,我们只能表达总是为真的陈述性知识\nDialogue: 0,0:40:22.30,0:40:23.79,Default,,0,0,0,,语言并不支持时间序列\nDialogue: 0,0:40:23.95,0:40:25.47,Default,,0,0,0,,否则的话 后果就会--\nDialogue: 0,0:40:27.39,0:40:28.76,Default,,0,0,0,,教授：是的 非常正确\nDialogue: 0,0:40:28.82,0:40:29.48,Default,,0,0,0,,问题在于\nDialogue: 0,0:40:30.06,0:40:32.60,Default,,0,0,0,,这个本来就是用来处理陈述性知识的\nDialogue: 0,0:40:33.26,0:40:34.81,Default,,0,0,0,,而就我目前所演示的来说 不支持\nDialogue: 0,0:40:35.71,0:40:39.56,Default,,0,0,0,,休息之后我会向你们揭露这其中的丑陋之处\nDialogue: 0,0:40:40.83,0:40:42.60,Default,,0,0,0,,就如我目前所展示的 它只是进行逻辑运算\nDialogue: 0,0:40:43.07,0:40:44.52,Default,,0,0,0,,原理上来说 如果我们做的是逻辑运算\nDialogue: 0,0:40:44.54,0:40:46.81,Default,,0,0,0,,用什么顺序完成并不会造成影响\nDialogue: 0,0:40:48.84,0:40:51.55,Default,,0,0,0,,但是呢\nDialogue: 0,0:40:51.60,0:40:53.61,Default,,0,0,0,,当你在进行一些具有副作用的操作的时候\nDialogue: 0,0:40:53.68,0:40:55.20,Default,,0,0,0,,比如向数据库中添加项\nDialogue: 0,0:40:55.23,0:40:58.16,Default,,0,0,0,,从中取出项 等等操作\nDialogue: 0,0:40:58.75,0:41:00.83,Default,,0,0,0,,你就丧失了这类控制\nDialogue: 0,0:41:01.29,0:41:02.94,Default,,0,0,0,,因此 这就与Prolog完全不同\nDialogue: 0,0:41:02.94,0:41:05.15,Default,,0,0,0,,Prolog有各种功能\nDialogue: 0,0:41:05.16,0:41:07.79,Default,,0,0,0,,能够让你利用求值的顺序\nDialogue: 0,0:41:09.64,0:41:11.77,Default,,0,0,0,,人们也这么来写Prolog\nDialogue: 0,0:41:11.77,0:41:14.04,Default,,0,0,0,,结果发现这样变得非常困难\nDialogue: 0,0:41:14.32,0:41:17.55,Default,,0,0,0,,但如果你是Prolog程序专家 你就可以这么做\nDialogue: 0,0:41:18.59,0:41:20.21,Default,,0,0,0,,但是我认为你们现在并不可以\nDialogue: 0,0:41:20.21,0:41:21.24,Default,,0,0,0,,它相当复杂\nDialogue: 0,0:41:21.72,0:41:23.64,Default,,0,0,0,,因为你们放弃了对事先安排的\nDialogue: 0,0:41:23.77,0:41:25.72,Default,,0,0,0,,求值顺序的控制权\nDialogue: 0,0:41:27.15,0:41:30.16,Default,,0,0,0,,学生：这就表明 当你有一个函数式映射时\nDialogue: 0,0:41:30.67,0:41:32.51,Default,,0,0,0,,而你最初在讲这门课的时候\nDialogue: 0,0:41:32.99,0:41:34.08,Default,,0,0,0,,你说过\nDialogue: 0,0:41:34.67,0:41:36.70,Default,,0,0,0,,我们在表述作为关系的陈述性知识\nDialogue: 0,0:41:37.15,0:41:38.81,Default,,0,0,0,,因为我们讨论的不是输入和输出\nDialogue: 0,0:41:41.21,0:41:43.37,Default,,0,0,0,,教授：这是关于“函数式”的双关语\nDialogue: 0,0:41:43.37,0:41:45.79,Default,,0,0,0,,一种是没有副作用\nDialogue: 0,0:41:46.20,0:41:48.16,Default,,0,0,0,,因此并不依赖于求值的顺序\nDialogue: 0,0:41:48.70,0:41:51.04,Default,,0,0,0,,还有就是数学意义上的“函数”\nDialogue: 0,0:41:51.07,0:41:52.22,Default,,0,0,0,,有关于输入和输出\nDialogue: 0,0:41:52.59,0:41:54.36,Default,,0,0,0,,我想这就是你想表达的双关\nDialogue: 0,0:41:56.51,0:41:58.51,Default,,0,0,0,,学生：我对其中两条语句不太明白\nDialogue: 0,0:41:58.81,0:42:00.70,Default,,0,0,0,,也就是那两条有关BOSS的语句\nDialogue: 0,0:42:01.27,0:42:05.74,Default,,0,0,0,,是不是 第一条查询构建了一个数据库\nDialogue: 0,0:42:05.76,0:42:08.08,Default,,0,0,0,,然后第二条查询--\nDialogue: 0,0:42:09.07,0:42:10.12,Default,,0,0,0,,教授：抱歉\nDialogue: 0,0:42:12.44,0:42:15.16,Default,,0,0,0,,这里的意思是 如果我输入这样的查询\nDialogue: 0,0:42:16.12,0:42:18.44,Default,,0,0,0,,我应该最初就给你们举这个例子\nDialogue: 0,0:42:19.47,0:42:23.52,Default,,0,0,0,,如果我输入(JOB (BITDIDDLE BEN) (COMPUTER WIZARD))\nDialogue: 0,0:42:25.04,0:42:27.77,Default,,0,0,0,,系统会找到一处事实\nDialogue: 0,0:42:28.30,0:42:30.28,Default,,0,0,0,,来完全匹配这条查询\nDialogue: 0,0:42:30.86,0:42:33.28,Default,,0,0,0,,然后输出(JOB (BITDIDDLE BEN) (COMPUTER WIZARD))\nDialogue: 0,0:42:34.22,0:42:35.60,Default,,0,0,0,,如果没找到这样的匹配\nDialogue: 0,0:42:35.69,0:42:36.75,Default,,0,0,0,,它就什么也不输出\nDialogue: 0,0:42:37.40,0:42:39.55,Default,,0,0,0,,我应该这么来表述\nDialogue: 0,0:42:39.56,0:42:42.27,Default,,0,0,0,,这门语言是用来查询某个表述是否为真\nDialogue: 0,0:42:43.40,0:42:45.77,Default,,0,0,0,,这是逻辑式编程的目的之一\nDialogue: 0,0:42:46.41,0:42:49.34,Default,,0,0,0,,输入一条查询 要么得到结果 要么没有\nDialogue: 0,0:42:50.68,0:42:52.38,Default,,0,0,0,,因此 我这里想要演示的是\nDialogue: 0,0:42:52.41,0:42:54.80,Default,,0,0,0,,我想要在介绍合一算法前\nDialogue: 0,0:42:54.83,0:42:56.62,Default,,0,0,0,,举一个简单的例子\nDialogue: 0,0:42:57.48,0:42:58.11,Default,,0,0,0,,所以 我应该说\nDialogue: 0,0:42:58.14,0:43:00.96,Default,,0,0,0,,如果我想要检查 这个是否为真\nDialogue: 0,0:43:01.18,0:43:03.28,Default,,0,0,0,,我就可以将它输入 并看有没有任何输出\nDialogue: 0,0:43:05.16,0:43:06.27,Default,,0,0,0,,学生：然后第二条查询\nDialogue: 0,0:43:06.28,0:43:07.84,Default,,0,0,0,,教授：第二条就是真正意义上的“查询”\nDialogue: 0,0:43:07.88,0:43:09.12,Default,,0,0,0,,学生：好的 真正的查询\nDialogue: 0,0:43:10.77,0:43:13.10,Default,,0,0,0,,教授：在这里它就会输出与?WHO相关的信息\nDialogue: 0,0:43:13.90,0:43:15.74,Default,,0,0,0,,就会有一个框架 存储着\nDialogue: 0,0:43:16.62,0:43:18.81,Default,,0,0,0,,?Z=?WHO ?D=COMPUTER\nDialogue: 0,0:43:19.56,0:43:20.49,Default,,0,0,0,,这个会传递下去\nDialogue: 0,0:43:20.51,0:43:21.95,Default,,0,0,0,,传递到这里的时候\nDialogue: 0,0:43:22.01,0:43:23.25,Default,,0,0,0,,?WHO就会被绑定起来\nDialogue: 0,0:43:26.95,0:43:28.76,Default,,0,0,0,,学生：在合一那里\nDialogue: 0,0:43:29.18,0:43:35.96,Default,,0,0,0,,我还是不太清楚?WHO和?Z之间发生了什么\nDialogue: 0,0:43:36.46,0:43:39.58,Default,,0,0,0,,要进行合一的话 这里的规则说\nDialogue: 0,0:43:42.03,0:43:46.22,Default,,0,0,0,,你说过 两个模式变量之间不能互相绑定\nDialogue: 0,0:43:46.26,0:43:48.08,Default,,0,0,0,,教授：模式匹配器确实不能这样\nDialogue: 0,0:43:48.36,0:43:50.83,Default,,0,0,0,,但对合一算法来说\nDialogue: 0,0:43:51.92,0:43:54.01,Default,,0,0,0,,就是一个有存储三个变量的环境\nDialogue: 0,0:43:56.69,0:43:57.90,Default,,0,0,0,,其中?D=COMPUTER\nDialogue: 0,0:43:58.52,0:44:00.19,Default,,0,0,0,,?Z=?WHO\nDialogue: 0,0:44:01.83,0:44:05.26,Default,,0,0,0,,所以在稍后的匹配过程中\nDialogue: 0,0:44:07.20,0:44:10.38,Default,,0,0,0,,如果?WHO=3\nDialogue: 0,0:44:12.06,0:44:13.66,Default,,0,0,0,,那么当我再查找字典的时候\nDialogue: 0,0:44:14.00,0:44:16.40,Default,,0,0,0,,它会告诉我 因为?Z=?WHO 所以?Z=3\nDialogue: 0,0:44:18.36,0:44:20.44,Default,,0,0,0,,从某种意义上来说 你就只需要修改这一点\nDialogue: 0,0:44:20.46,0:44:21.98,Default,,0,0,0,,就可以把合一算法变成模式匹配器\nDialogue: 0,0:44:22.48,0:44:24.80,Default,,0,0,0,,学生：但是看起来你好像告诉了它 如何进行合一\nDialogue: 0,0:44:24.83,0:44:26.96,Default,,0,0,0,,就像你已经解好了方程 准备好了值\nDialogue: 0,0:44:26.99,0:44:29.23,Default,,0,0,0,,并把它们安排成这样\nDialogue: 0,0:44:29.77,0:44:31.24,Default,,0,0,0,,现在看起来就像是\nDialogue: 0,0:44:31.28,0:44:32.83,Default,,0,0,0,,你传递了一本字典\nDialogue: 0,0:44:32.88,0:44:34.86,Default,,0,0,0,,其中的两个变量是关联起来的\nDialogue: 0,0:44:34.88,0:44:37.23,Default,,0,0,0,,教授：实际上 我们在同时求解它们\nDialogue: 0,0:44:37.52,0:44:39.74,Default,,0,0,0,,这是因为我们想要一下得到整个答案\nDialogue: 0,0:44:40.54,0:44:42.81,Default,,0,0,0,,如果你观察它们是如何被递归地构建的\nDialogue: 0,0:44:42.81,0:44:43.74,Default,,0,0,0,,基本上就是这样了\nDialogue: 0,0:44:44.98,0:44:48.40,Default,,0,0,0,,学生：也就是确实要传递含有两个变量的字典？\nDialogue: 0,0:44:48.40,0:44:49.11,Default,,0,0,0,,教授：是的\nDialogue: 0,0:44:49.11,0:44:49.68,Default,,0,0,0,,学生：然后把它们关联起来？\nDialogue: 0,0:44:50.38,0:44:52.91,Default,,0,0,0,,教授：就像通常的字典那样\nDialogue: 0,0:44:54.35,0:44:56.06,Default,,0,0,0,,学生：你在讨论合一算法的时候\nDialogue: 0,0:44:56.09,0:45:00.19,Default,,0,0,0,,你说过在某些情况下\nDialogue: 0,0:45:00.75,0:45:03.98,Default,,0,0,0,,合一不能够完成\nDialogue: 0,0:45:04.03,0:45:04.30,Default,,0,0,0,,教授：是的\nDialogue: 0,0:45:04.97,0:45:08.46,Default,,0,0,0,,学生：那么 是否可以通过编写规则\nDialogue: 0,0:45:09.16,0:45:15.93,Default,,0,0,0,,或者 写入那些事先知道可解的形式\nDialogue: 0,0:45:16.48,0:45:18.54,Default,,0,0,0,,来使得合一算法能够完成\nDialogue: 0,0:45:18.76,0:45:22.94,Default,,0,0,0,,是否可以在规则中添加一些属性\nDialogue: 0,0:45:23.18,0:45:25.45,Default,,0,0,0,,或者向输入的形式中添加属性\nDialogue: 0,0:45:25.82,0:45:29.04,Default,,0,0,0,,来避免无法进行合一的窘境\nDialogue: 0,0:45:29.18,0:45:31.15,Default,,0,0,0,,PROFESSOR: 我想 你也同意\nDialogue: 0,0:45:31.47,0:45:35.26,Default,,0,0,0,,用非常受限的方式来编写查询\nDialogue: 0,0:45:35.60,0:45:36.67,Default,,0,0,0,,看 你遇到的是\nDialogue: 0,0:45:36.88,0:45:39.12,Default,,0,0,0,,仔细看 你遇到问题是在\nDialogue: 0,0:45:39.68,0:45:44.25,Default,,0,0,0,,用像这样的东西去匹配\nDialogue: 0,0:45:44.59,0:45:47.20,Default,,0,0,0,,具有这样结构的模式时\nDialogue: 0,0:45:47.55,0:45:55.30,Default,,0,0,0,,比如((A ?Y B) ?Y)\nDialogue: 0,0:45:58.98,0:46:01.48,Default,,0,0,0,,这是你可能遇到问题的一个地方\nDialogue: 0,0:46:03.07,0:46:05.80,Default,,0,0,0,,学生：所以你可以在语法层次上处理它么？\nDialogue: 0,0:46:06.14,0:46:08.76,Default,,0,0,0,,教授：你可以在写查询时\nDialogue: 0,0:46:08.76,0:46:10.49,Default,,0,0,0,,注意你的规则\nDialogue: 0,0:46:11.90,0:46:14.08,Default,,0,0,0,,学生：这个问题应该由\nDialogue: 0,0:46:14.11,0:46:16.27,Default,,0,0,0,,数据库的构建者考虑么？\nDialogue: 0,0:46:16.57,0:46:17.80,Default,,0,0,0,,教授：这个问题\nDialogue: 0,0:46:19.93,0:46:22.01,Default,,0,0,0,,不完全是数据库的构建者\nDialogue: 0,0:46:22.04,0:46:23.61,Default,,0,0,0,,或者是表述规则的人\nDialogue: 0,0:46:24.01,0:46:25.31,Default,,0,0,0,,所需要考虑的\nDialogue: 0,0:46:25.80,0:46:29.79,Default,,0,0,0,,当你们仔细审查合一算法的代码时\nDialogue: 0,0:46:29.92,0:46:31.87,Default,,0,0,0,,你们会发现\nDialogue: 0,0:46:32.41,0:46:34.76,Default,,0,0,0,,它实际上在查询一个字典\nDialogue: 0,0:46:34.94,0:46:36.83,Default,,0,0,0,,它会问 ?Y的取值应该是什么？\nDialogue: 0,0:46:37.26,0:46:41.42,Default,,0,0,0,,?Y应该是一个含有自包含的表达式么？\nDialogue: 0,0:46:41.96,0:46:43.26,Default,,0,0,0,,这时候 合一算法就会说\nDialogue: 0,0:46:43.28,0:46:46.24,Default,,0,0,0,,哦 我正在求解一个不动点方程\nDialogue: 0,0:46:46.24,0:46:46.99,Default,,0,0,0,,我还是放弃吧\nDialogue: 0,0:46:48.59,0:46:51.91,Default,,0,0,0,,学生：你区分过数据库中的规则\nDialogue: 0,0:46:51.91,0:46:56.48,Default,,0,0,0,,这些规则是加入数据库的么？\nDialogue: 0,0:46:56.95,0:46:57.36,Default,,0,0,0,,教授：是的\nDialogue: 0,0:46:57.87,0:46:58.87,Default,,0,0,0,,我应该这么来说\nDialogue: 0,0:46:58.87,0:47:00.33,Default,,0,0,0,,你们可以把规则看作\nDialogue: 0,0:47:00.60,0:47:02.65,Default,,0,0,0,,数据库中的其它东西\nDialogue: 0,0:47:03.71,0:47:06.81,Default,,0,0,0,,如果你想要检查数据库中需要检查的东西\nDialogue: 0,0:47:06.83,0:47:09.44,Default,,0,0,0,,它们就是存在于数据库中的虚拟事实\nDialogue: 0,0:47:09.44,0:47:12.32,Default,,0,0,0,,学生：但是在这个解释中\nDialogue: 0,0:47:12.43,0:47:17.26,Default,,0,0,0,,你就已经区分了数据库和规则本身\nDialogue: 0,0:47:18.23,0:47:19.90,Default,,0,0,0,,教授：是的 我应该不这么来说\nDialogue: 0,0:47:20.49,0:47:23.31,Default,,0,0,0,,这样做的唯一理由就是实现\nDialogue: 0,0:47:23.54,0:47:24.67,Default,,0,0,0,,当你们查看具体实现时\nDialogue: 0,0:47:24.68,0:47:27.50,Default,,0,0,0,,会发现其中有部分用来检查数据库中的\nDialogue: 0,0:47:27.55,0:47:29.85,Default,,0,0,0,,基本断言或者规则\nDialogue: 0,0:47:30.47,0:47:32.72,Default,,0,0,0,,这其中的真正原因就是\nDialogue: 0,0:47:32.78,0:47:34.56,Default,,0,0,0,,你不知道查询结果是以什么顺序输出的\nDialogue: 0,0:47:34.96,0:47:40.46,Default,,0,0,0,,而规则数据库和数据数据库\nDialogue: 0,0:47:40.48,0:47:43.68,Default,,0,0,0,,是通过某种延迟求值的方式合并的\nDialogue: 0,0:47:44.60,0:47:46.80,Default,,0,0,0,,这就使得顺序变得非常复杂\nDialogue: 0,0:47:55.44,0:47:56.09,Default,,0,0,0,,那好 我们休息一下\nDialogue: 0,0:47:56.30,0:48:09.90,Default,,0,0,0,,[音乐]\nDialogue: 0,0:48:10.04,0:48:14.41,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:18.68,0:48:22.09,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:48:22.09,0:48:25.96,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:48:26.00,0:48:29.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}逻辑式程序设计 II\nDialogue: 0,0:48:33.16,0:48:35.37,Default,,0,0,0,,我们已经学习了逻辑式语言与\nDialogue: 0,0:48:35.39,0:48:36.41,Default,,0,0,0,,规则系统的运行原理\nDialogue: 0,0:48:37.23,0:48:39.37,Default,,0,0,0,,现在 让我们来探讨一个更加深刻的问题\nDialogue: 0,0:48:40.12,0:48:41.28,Default,,0,0,0,,来看下它们意味着什么\nDialogue: 0,0:48:43.18,0:48:46.86,Default,,0,0,0,,这把我们带入到整个查询语言中\nDialogue: 0,0:48:46.99,0:48:48.67,Default,,0,0,0,,最微妙的部分\nDialogue: 0,0:48:49.21,0:48:53.07,Default,,0,0,0,,也就是它看起来与想象中不同的地方\nDialogue: 0,0:48:53.57,0:48:56.22,Default,,0,0,0,,AND、OR以及NOT\nDialogue: 0,0:48:57.02,0:48:58.88,Default,,0,0,0,,以及规则的逻辑蕴含\nDialogue: 0,0:48:59.69,0:49:06.64,Default,,0,0,0,,并不是逻辑学中的与、或、非以及蕴含\nDialogue: 0,0:49:07.69,0:49:09.71,Default,,0,0,0,,让我来举一个实例\nDialogue: 0,0:49:09.91,0:49:12.22,Default,,0,0,0,,当然 如果我们有两个逻辑命题\nDialogue: 0,0:49:12.40,0:49:19.44,Default,,0,0,0,,那么(AND P Q)就应该\nDialogue: 0,0:49:20.00,0:49:22.59,Default,,0,0,0,,等同于(AND Q P)\nDialogue: 0,0:49:23.10,0:49:24.51,Default,,0,0,0,,而(OR P Q)就应该\nDialogue: 0,0:49:24.78,0:49:26.51,Default,,0,0,0,,等同于(OR Q P)\nDialogue: 0,0:49:28.67,0:49:30.09,Default,,0,0,0,,但我们来看看这里\nDialogue: 0,0:49:30.10,0:49:32.01,Default,,0,0,0,,这里是一个例子\nDialogue: 0,0:49:32.18,0:49:36.16,Default,,0,0,0,,来看看 在我们的数据库中\nDialogue: 0,0:49:36.28,0:49:40.14,Default,,0,0,0,,如何表示某人的级别高于他人\nDialogue: 0,0:49:40.14,0:49:42.89,Default,,0,0,0,,我们定义(OUTRANKED-BY ?S ?B)为\nDialogue: 0,0:49:44.64,0:49:48.62,Default,,0,0,0,,或者S是B的上司\nDialogue: 0,0:49:49.63,0:49:51.07,Default,,0,0,0,,或者这其中有某个中间经理M\nDialogue: 0,0:49:51.10,0:49:55.82,Default,,0,0,0,,其中S是M的上司 M的级别又比B高\nDialogue: 0,0:49:59.64,0:50:02.31,Default,,0,0,0,,这是定义OUTRANKED-BY的一种方式\nDialogue: 0,0:50:02.31,0:50:04.16,Default,,0,0,0,,或者我们可以原封不动地写过来\nDialogue: 0,0:50:05.08,0:50:06.91,Default,,0,0,0,,除了在最底部的这里\nDialogue: 0,0:50:07.21,0:50:09.88,Default,,0,0,0,,我们颠倒一下这两个子句的顺序\nDialogue: 0,0:50:11.63,0:50:12.99,Default,,0,0,0,,当然 如果它们都是逻辑表达式的话\nDialogue: 0,0:50:13.00,0:50:14.88,Default,,0,0,0,,它们应该表示的是相同的东西\nDialogue: 0,0:50:16.69,0:50:17.31,Default,,0,0,0,,然而\nDialogue: 0,0:50:17.71,0:50:19.61,Default,,0,0,0,,在我们这个特定的实现中\nDialogue: 0,0:50:19.64,0:50:22.88,Default,,0,0,0,,如果你查询(OUTRANDKED-BY ?WHO (BITDIIDLE BEN))\nDialogue: 0,0:50:23.48,0:50:25.36,Default,,0,0,0,,你会发现 这条规则\nDialogue: 0,0:50:26.76,0:50:28.72,Default,,0,0,0,,会完美地生成答案\nDialogue: 0,0:50:30.04,0:50:31.98,Default,,0,0,0,,然而 这条规则会陷入无穷循环\nDialogue: 0,0:50:34.11,0:50:36.27,Default,,0,0,0,,其中的原因就是\nDialogue: 0,0:50:36.33,0:50:40.33,Default,,0,0,0,,这条规则会问谁比BEN BITDIDDLE级别高？\nDialogue: 0,0:50:41.92,0:50:43.53,Default,,0,0,0,,它试图寻找一个S\nDialogue: 0,0:50:43.88,0:50:46.22,Default,,0,0,0,,使得S比B的级别更高 其中B是BEN BITDIDDLE\nDialogue: 0,0:50:47.50,0:50:49.63,Default,,0,0,0,,这会在一个子问题中重复出现\nDialogue: 0,0:50:50.33,0:50:51.98,Default,,0,0,0,,找到一个M\nDialogue: 0,0:50:52.24,0:50:54.57,Default,,0,0,0,,使得M的级别高于BEN BITDIDDLE\nDialogue: 0,0:50:55.61,0:50:57.36,Default,,0,0,0,,而对M没有限制\nDialogue: 0,0:50:58.56,0:51:00.40,Default,,0,0,0,,这就相当于为了解决这个问题\nDialogue: 0,0:51:01.42,0:51:03.29,Default,,0,0,0,,我就还需要求解同样的问题\nDialogue: 0,0:51:04.57,0:51:07.23,Default,,0,0,0,,在把它解出来后 我才检查SUPERVISOR关系\nDialogue: 0,0:51:08.00,0:51:09.16,Default,,0,0,0,,然而这条规则没有这样的问题\nDialogue: 0,0:51:09.18,0:51:12.35,Default,,0,0,0,,因为在它尝试找出这条OUTRANKED-BY规则之前\nDialogue: 0,0:51:12.94,0:51:15.26,Default,,0,0,0,,在这里已经对M施加过约束了\nDialogue: 0,0:51:18.38,0:51:20.94,Default,,0,0,0,,随意 这两条规则理论上是相同的\nDialogue: 0,0:51:20.99,0:51:22.67,Default,,0,0,0,,但实际上 其中一条会陷入无穷循环\nDialogue: 0,0:51:22.86,0:51:25.04,Default,,0,0,0,,而另一条不会\nDialogue: 0,0:51:26.72,0:51:29.77,Default,,0,0,0,,通过这个非常极端的例子\nDialogue: 0,0:51:29.79,0:51:32.65,Default,,0,0,0,,你会发现在逻辑式程序设计中\nDialogue: 0,0:51:34.28,0:51:38.70,Default,,0,0,0,,如果你改变了AND或OR所连接子句的顺序\nDialogue: 0,0:51:39.34,0:51:41.58,Default,,0,0,0,,你会发现效率上的巨大差异\nDialogue: 0,0:51:42.24,0:51:43.21,Default,,0,0,0,,我们刚刚就看到了\nDialogue: 0,0:51:43.55,0:51:46.54,Default,,0,0,0,,在无穷循环方面的巨大差异\nDialogue: 0,0:51:49.19,0:51:51.74,Default,,0,0,0,,同样的 这也跟输入规则\nDialogue: 0,0:51:52.00,0:51:53.31,Default,,0,0,0,,的顺序有关\nDialogue: 0,0:51:54.07,0:51:56.48,Default,,0,0,0,,向数据库查询规则的顺序\nDialogue: 0,0:51:56.70,0:51:59.95,Default,,0,0,0,,会极大程度上影响效率：比如得到答案\nDialogue: 0,0:52:00.46,0:52:02.60,Default,,0,0,0,,或者在某些顺序下陷入无穷循环\nDialogue: 0,0:52:03.84,0:52:07.29,Default,,0,0,0,,这些都跟\nDialogue: 0,0:52:07.63,0:52:10.04,Default,,0,0,0,,你检查这些规则的顺序有关\nDialogue: 0,0:52:10.95,0:52:14.41,Default,,0,0,0,,有些规则的蕴含路径会相当的长\nDialogue: 0,0:52:14.44,0:52:16.06,Default,,0,0,0,,而另外一些不会\nDialogue: 0,0:52:16.44,0:52:17.68,Default,,0,0,0,,但你事先并不知道\nDialogue: 0,0:52:17.72,0:52:19.16,Default,,0,0,0,,哪一个长 哪一个短\nDialogue: 0,0:52:19.30,0:52:21.48,Default,,0,0,0,,有很多研究都与此有关\nDialogue: 0,0:52:22.16,0:52:23.76,Default,,0,0,0,,其中大多数都是想通过\nDialogue: 0,0:52:23.95,0:52:26.97,Default,,0,0,0,,用并行的方法来实现逻辑式程序设计语言\nDialogue: 0,0:52:27.32,0:52:29.90,Default,,0,0,0,,某种意义上来说 就是并行地检查所有规则\nDialogue: 0,0:52:30.36,0:52:32.80,Default,,0,0,0,,一旦有一条搜索得到答案 就返回结果\nDialogue: 0,0:52:33.04,0:52:34.99,Default,,0,0,0,,如果某条路径陷入了无穷的推导\nDialogue: 0,0:52:35.02,0:52:38.25,Default,,0,0,0,,那么 你只需知道 内存和处理器都非常廉价\nDialogue: 0,0:52:38.28,0:52:40.49,Default,,0,0,0,,让它们根据你的需要一直搜寻就好了\nDialogue: 0,0:52:43.47,0:52:44.83,Default,,0,0,0,,尽管如此 与真正的逻辑相比\nDialogue: 0,0:52:45.18,0:52:50.49,Default,,0,0,0,,这门逻辑式语言还有一个更深刻的问题\nDialogue: 0,0:52:50.68,0:52:52.52,Default,,0,0,0,,我给你们演示的例子\nDialogue: 0,0:52:52.97,0:52:54.80,Default,,0,0,0,,只是会陷入无穷循环\nDialogue: 0,0:52:55.37,0:52:56.99,Default,,0,0,0,,但至少不会给你错误的答案\nDialogue: 0,0:52:58.37,0:53:03.64,Default,,0,0,0,,当我们开始严肃地把这门逻辑式语言\nDialogue: 0,0:53:03.68,0:53:05.24,Default,,0,0,0,,与真正的经典逻辑作比较时\nDialogue: 0,0:53:05.71,0:53:08.46,Default,,0,0,0,,就会发现其中最深层次的问题\nDialogue: 0,0:53:09.49,0:53:12.43,Default,,0,0,0,,让我们来看看真正的经典逻辑\nDialogue: 0,0:53:13.71,0:53:21.04,Default,,0,0,0,,所有的人类都是凡人\nDialogue: 0,0:53:22.35,0:53:23.45,Default,,0,0,0,,相当经典的逻辑命题\nDialogue: 0,0:53:24.39,0:53:28.67,Default,,0,0,0,,然后我们就依照最经典的传统\nDialogue: 0,0:53:29.24,0:53:32.46,Default,,0,0,0,,我们按照最传统的方式来做\nDialogue: 0,0:53:32.67,0:53:37.16,Default,,0,0,0,,所有的希腊人都是人类\nDialogue: 0,0:53:40.49,0:53:46.06,Default,,0,0,0,,苏格拉底是希腊人\nDialogue: 0,0:53:48.17,0:53:49.21,Default,,0,0,0,,然后我们又该写什么呢？\nDialogue: 0,0:53:49.21,0:53:51.89,Default,,0,0,0,,经典逻辑中有一个三点符号\nDialogue: 0,0:53:51.89,0:53:54.33,Default,,0,0,0,,因此 我们得到了一个三段论\nDialogue: 0,0:53:54.64,0:53:59.55,Default,,0,0,0,,苏格拉底是凡人\nDialogue: 0,0:54:01.36,0:54:04.91,Default,,0,0,0,,这些都是真正的经典逻辑\nDialogue: 0,0:54:05.88,0:54:11.05,Default,,0,0,0,,把它跟我们经典逻辑数据库比较一下\nDialogue: 0,0:54:12.40,0:54:14.46,Default,,0,0,0,,这是一个经典逻辑数据库\nDialogue: 0,0:54:16.27,0:54:17.48,Default,,0,0,0,,(GREEK SOCRATES)\nDialogue: 0,0:54:18.03,0:54:18.84,Default,,0,0,0,,(GREEK PLATO)\nDialogue: 0,0:54:19.60,0:54:20.40,Default,,0,0,0,,(GREEK ZEUS)\nDialogue: 0,0:54:20.84,0:54:21.98,Default,,0,0,0,,(GOD ZEUS)\nDialogue: 0,0:54:24.12,0:54:29.96,Default,,0,0,0,,所有的人类都是凡人\nDialogue: 0,0:54:30.54,0:54:32.12,Default,,0,0,0,,为了证明某人是平凡的\nDialogue: 0,0:54:32.16,0:54:33.60,Default,,0,0,0,,只需要证明他是人类\nDialogue: 0,0:54:34.65,0:54:35.90,Default,,0,0,0,,所有的人类都是不可靠的\nDialogue: 0,0:54:38.90,0:54:40.98,Default,,0,0,0,,并且说所有的希腊人都是人类 并不正确\nDialogue: 0,0:54:40.98,0:54:44.41,Default,,0,0,0,,这条规则说 所有不是神的希腊人都是人类\nDialogue: 0,0:54:45.71,0:54:47.04,Default,,0,0,0,,因此为了证明某人是人类\nDialogue: 0,0:54:47.07,0:54:48.89,Default,,0,0,0,,只需要说明他是一个希腊人 并且不是神\nDialogue: 0,0:54:49.32,0:54:52.88,Default,,0,0,0,,任何一个希腊神的住址是奥林匹斯山\nDialogue: 0,0:54:54.32,0:54:57.16,Default,,0,0,0,,这就是一个小型经典逻辑数据库\nDialogue: 0,0:54:57.39,0:54:59.32,Default,,0,0,0,,确实 它运行得相当好\nDialogue: 0,0:54:59.49,0:55:02.09,Default,,0,0,0,,如果我们向其询问\nDialogue: 0,0:55:03.47,0:55:06.57,Default,,0,0,0,,苏格拉底是凡人么 不可靠么？\nDialogue: 0,0:55:06.91,0:55:07.69,Default,,0,0,0,,它会输出：是\nDialogue: 0,0:55:07.77,0:55:09.71,Default,,0,0,0,,柏拉图是凡人并且不可靠么？\nDialogue: 0,0:55:09.71,0:55:10.24,Default,,0,0,0,,它会回答：是\nDialogue: 0,0:55:10.68,0:55:12.21,Default,,0,0,0,,如果我们问宙斯是凡人么\nDialogue: 0,0:55:12.21,0:55:13.23,Default,,0,0,0,,它什么都不会找到\nDialogue: 0,0:55:14.90,0:55:15.96,Default,,0,0,0,,运行得非常完美\nDialogue: 0,0:55:16.54,0:55:20.12,Default,,0,0,0,,然而 如果我们想要把它扩展一下\nDialogue: 0,0:55:20.12,0:55:23.05,Default,,0,0,0,,让我们来定义一下什么是“完美生命体”\nDialogue: 0,0:55:23.82,0:55:27.21,Default,,0,0,0,,我们把规则PERFECT定义为\nDialogue: 0,0:55:34.05,0:55:35.48,Default,,0,0,0,,我想这样来定义是正确的\nDialogue: 0,0:55:35.48,0:55:38.14,Default,,0,0,0,,如果你熟悉中世纪经院哲学\nDialogue: 0,0:55:38.44,0:55:40.17,Default,,0,0,0,,我想所谓“完美生命体”一定\nDialogue: 0,0:55:40.68,0:55:42.65,Default,,0,0,0,,既不是凡人 又不会不可靠\nDialogue: 0,0:55:44.10,0:55:56.84,Default,,0,0,0,,(AND (NOT (MORTAL ?X)) (NOT (FALLIBLE ?X)))\nDialogue: 0,0:55:59.30,0:56:00.89,Default,,0,0,0,,这样 我们就定义了一个规则\nDialogue: 0,0:56:02.67,0:56:04.36,Default,,0,0,0,,来告诉系统 什么是“完美生命体”\nDialogue: 0,0:56:05.79,0:56:07.69,Default,,0,0,0,,现在 我们就要\nDialogue: 0,0:56:08.06,0:56:10.17,Default,,0,0,0,,询问所有“完美生命体”的地址\nDialogue: 0,0:56:11.48,0:56:22.30,Default,,0,0,0,,(AND (ADDRESS ?X ?Y) (PERFECT ?X))\nDialogue: 0,0:56:23.48,0:56:24.97,Default,,0,0,0,,在这里 我们生成了\nDialogue: 0,0:56:24.99,0:56:27.80,Default,,0,0,0,,世界上最独有的邮件列表\nDialogue: 0,0:56:30.16,0:56:32.20,Default,,0,0,0,,为了查询所有完美生命体的地址\nDialogue: 0,0:56:32.24,0:56:33.47,Default,,0,0,0,,我们会输入像这样的查询\nDialogue: 0,0:56:33.83,0:56:35.44,Default,,0,0,0,,或者像这样输入\nDialogue: 0,0:56:36.24,0:56:50.57,Default,,0,0,0,,(AND (PERFECT ?X) (ADDRESS ?X ?Y))\nDialogue: 0,0:56:52.06,0:56:54.96,Default,,0,0,0,,假设我们把它输入进去 并尝试查询\nDialogue: 0,0:56:55.19,0:56:56.76,Default,,0,0,0,,这条查询会给我们答案\nDialogue: 0,0:56:57.65,0:57:00.00,Default,,0,0,0,,这条查询会输出：奥林匹斯山\nDialogue: 0,0:57:04.23,0:57:06.57,Default,,0,0,0,,而这条查询 什么也不会输出\nDialogue: 0,0:57:06.74,0:57:09.58,Default,,0,0,0,,它找不到完美生命体的地址\nDialogue: 0,0:57:11.64,0:57:12.51,Default,,0,0,0,,为什么会这样？\nDialogue: 0,0:57:12.51,0:57:13.44,Default,,0,0,0,,这又为什么不同？\nDialogue: 0,0:57:14.23,0:57:15.69,Default,,0,0,0,,这个问题跟无穷循环没什么关系\nDialogue: 0,0:57:15.69,0:57:17.08,Default,,0,0,0,,这个的问题是答案不相同\nDialogue: 0,0:57:19.48,0:57:20.09,Default,,0,0,0,,原因就是\nDialogue: 0,0:57:20.38,0:57:22.32,Default,,0,0,0,,如果你们还记得NOT的实现的话\nDialogue: 0,0:57:23.50,0:57:24.84,Default,,0,0,0,,NOT是作为一个过滤器\nDialogue: 0,0:57:25.88,0:57:29.00,Default,,0,0,0,,NOT会接收一本字典\nDialogue: 0,0:57:29.05,0:57:31.56,Default,,0,0,0,,里面有可行解构成的框架\nDialogue: 0,0:57:31.79,0:57:33.16,Default,,0,0,0,,然后过滤出那些\nDialogue: 0,0:57:33.29,0:57:34.94,Default,,0,0,0,,满足某个条件的解\nDialogue: 0,0:57:34.97,0:57:36.11,Default,,0,0,0,,这就是我如何实现NOT的\nDialogue: 0,0:57:36.92,0:57:38.43,Default,,0,0,0,,如果你们仔细想想其中的原理\nDialogue: 0,0:57:40.11,0:57:42.65,Default,,0,0,0,,我创建了一个查询盒子\nDialogue: 0,0:57:43.32,0:57:47.39,Default,,0,0,0,,ADDRESS盒子的输出作为了PERFECT的输入\nDialogue: 0,0:57:50.29,0:57:51.00,Default,,0,0,0,,这就使得\nDialogue: 0,0:57:51.32,0:57:53.26,Default,,0,0,0,,ADDRESS盒子会创建出\nDialogue: 0,0:57:53.32,0:57:54.83,Default,,0,0,0,,我知道地址的人\nDialogue: 0,0:57:55.29,0:57:57.64,Default,,0,0,0,,这些都会被PERFECT中的NOT给过滤掉\nDialogue: 0,0:57:59.88,0:58:04.19,Default,,0,0,0,,所以它会丢弃掉那些满足平凡的或者不可靠的数据\nDialogue: 0,0:58:04.91,0:58:06.38,Default,,0,0,0,,而对于另外一种顺序来说\nDialogue: 0,0:58:06.73,0:58:09.12,Default,,0,0,0,,我以一个空框架开始的\nDialogue: 0,0:58:09.52,0:58:12.35,Default,,0,0,0,,但是这里PERFECT没有可以给NOT过滤的东西\nDialogue: 0,0:58:12.38,0:58:13.98,Default,,0,0,0,,所以这里不会有什么输出\nDialogue: 0,0:58:18.83,0:58:21.50,Default,,0,0,0,,这也就导致没有东西输入到ADDRESS中\nDialogue: 0,0:58:21.94,0:58:23.15,Default,,0,0,0,,因此 我得不到答案\nDialogue: 0,0:58:23.93,0:58:27.04,Default,,0,0,0,,在强调一下 这是因为NOT不会生成任何东西\nDialogue: 0,0:58:27.44,0:58:28.80,Default,,0,0,0,,NOT只会丢弃数据\nDialogue: 0,0:58:29.08,0:58:30.51,Default,,0,0,0,,如果我不向NOT传递东西的话\nDialogue: 0,0:58:30.52,0:58:31.74,Default,,0,0,0,,它也就不会输出\nDialogue: 0,0:58:32.02,0:58:33.77,Default,,0,0,0,,这样我就得到了错误的答案\nDialogue: 0,0:58:37.20,0:58:37.97,Default,,0,0,0,,我们又该如何修复它呢？\nDialogue: 0,0:58:37.97,0:58:39.07,Default,,0,0,0,,当然 有很多办法\nDialogue: 0,0:58:39.36,0:58:40.91,Default,,0,0,0,,你可能认为 现在这样有点愚蠢\nDialogue: 0,0:58:41.41,0:58:44.90,Default,,0,0,0,,为什么要一开始就执行NOT呢？\nDialogue: 0,0:58:44.96,0:58:47.48,Default,,0,0,0,,想要正确地实现NOT\nDialogue: 0,0:58:47.84,0:58:50.08,Default,,0,0,0,,就是要认识到当你遇到NOT时\nDialogue: 0,0:58:50.33,0:58:52.09,Default,,0,0,0,,你应该首先生成好答案\nDialogue: 0,0:58:52.80,0:58:54.97,Default,,0,0,0,,然后通过字典把它们传递过来\nDialogue: 0,0:58:55.52,0:58:57.85,Default,,0,0,0,,然后再最后再做过滤\nDialogue: 0,0:58:58.56,0:59:02.01,Default,,0,0,0,,有些按照这种方式实现的逻辑式语言\nDialogue: 0,0:59:02.41,0:59:04.05,Default,,0,0,0,,能够解决这个问题\nDialogue: 0,0:59:06.80,0:59:08.97,Default,,0,0,0,,然而 还有一个更深刻的问题\nDialogue: 0,0:59:09.60,0:59:11.53,Default,,0,0,0,,也就是 哪个才是正确答案呢？\nDialogue: 0,0:59:12.53,0:59:14.24,Default,,0,0,0,,是奥林匹斯山 还是没有呢？\nDialogue: 0,0:59:15.37,0:59:18.73,Default,,0,0,0,,你可能会认为是奥林匹斯山\nDialogue: 0,0:59:18.76,0:59:20.73,Default,,0,0,0,,毕竟 宙斯在数据库中\nDialogue: 0,0:59:22.52,0:59:25.10,Default,,0,0,0,,宙斯不是平凡的 也不是不可靠的\nDialogue: 0,0:59:29.55,0:59:32.44,Default,,0,0,0,,因此你可能会认为宙斯满足\nDialogue: 0,0:59:34.30,0:59:44.03,Default,,0,0,0,,(NOT (MORTAL ZEUS))或者(NOT (FALLIBLE ZEUS))\nDialogue: 0,0:59:44.12,0:59:45.85,Default,,0,0,0,,但我们实际来看一看数据库\nDialogue: 0,0:59:47.92,0:59:48.46,Default,,0,0,0,,来看一下\nDialogue: 0,0:59:49.36,0:59:53.24,Default,,0,0,0,,它要如何知道宙斯不是不可靠的？\nDialogue: 0,0:59:54.81,0:59:56.11,Default,,0,0,0,,这里面没有关于它的知识\nDialogue: 0,0:59:57.93,0:59:59.66,Default,,0,0,0,,里面只能得到人类是不可靠的\nDialogue: 0,1:00:02.16,1:00:04.12,Default,,0,0,0,,它又如何知道宙斯不是不可靠的呢？\nDialogue: 0,1:00:04.48,1:00:05.93,Default,,0,0,0,,这其中没有相关的规则\nDialogue: 0,1:00:07.98,1:00:11.00,Default,,0,0,0,,它只是说 我没有这样的规则\nDialogue: 0,1:00:11.68,1:00:14.06,Default,,0,0,0,,我只能通过某人是人类来推断出他是平凡的\nDialogue: 0,1:00:14.08,1:00:15.68,Default,,0,0,0,,这也是它所知道关于“平凡”的所有东西\nDialogue: 0,1:00:16.69,1:00:19.85,Default,,0,0,0,,然而 如果你还记得古典神话的话\nDialogue: 0,1:00:19.87,1:00:23.48,Default,,0,0,0,,你就知道 古希腊众神是不平凡的 但都不可靠\nDialogue: 0,1:00:25.05,1:00:28.65,Default,,0,0,0,,所以 不能通过这些规则得到答案\nDialogue: 0,1:00:30.85,1:00:32.10,Default,,0,0,0,,但它又为什么推导出这些呢？\nDialogue: 0,1:00:34.49,1:00:38.32,Default,,0,0,0,,显然 苏格拉底不会犯这类逻辑错误\nDialogue: 0,1:00:40.08,1:00:42.67,Default,,0,0,0,,在这门语言中 NOT并不是NOT\nDialogue: 0,1:00:43.37,1:00:44.32,Default,,0,0,0,,不是逻辑非运算\nDialogue: 0,1:00:44.93,1:00:46.40,Default,,0,0,0,,这门语言中 NOT表示的是\nDialogue: 0,1:00:47.16,1:00:49.96,Default,,0,0,0,,不可以从数据库中推断出结果\nDialogue: 0,1:00:50.75,1:00:53.34,Default,,0,0,0,,而不是“非真”\nDialogue: 0,1:00:55.02,1:00:56.30,Default,,0,0,0,,完全是天壤之别\nDialogue: 0,1:00:57.30,1:00:58.64,Default,,0,0,0,,很细微 但也很巨大\nDialogue: 0,1:00:59.25,1:01:00.27,Default,,0,0,0,,因此 实际上\nDialogue: 0,1:01:00.76,1:01:03.92,Default,,0,0,0,,如果什么都不知道 最好就说NOT\nDialogue: 0,1:01:04.68,1:01:06.14,Default,,0,0,0,,如果你问它\nDialogue: 0,1:01:06.16,1:01:07.83,Default,,0,0,0,,宙斯是否喜欢巧克力冰激凌\nDialogue: 0,1:01:07.85,1:01:09.12,Default,,0,0,0,,它会说 这个查询当然非真\nDialogue: 0,1:01:10.64,1:01:12.51,Default,,0,0,0,,这些事情它都不知道\nDialogue: 0,1:01:12.59,1:01:17.34,Default,,0,0,0,,NOT表示：不能从你告知它的事实中推断出来\nDialogue: 0,1:01:18.28,1:01:22.44,Default,,0,0,0,,换句话说 你要把“无法推断出”\nDialogue: 0,1:01:22.65,1:01:24.00,Default,,0,0,0,,与“命题非真”区别开来\nDialogue: 0,1:01:24.41,1:01:26.30,Default,,0,0,0,,这被称作是“封闭世界假说”\nDialogue: 0,1:01:37.37,1:01:38.17,Default,,0,0,0,,封闭世界假说\nDialogue: 0,1:01:38.20,1:01:42.38,Default,,0,0,0,,只要结论不能通过我所知道的知识推断出来\nDialogue: 0,1:01:43.50,1:01:44.36,Default,,0,0,0,,那么就不是真的\nDialogue: 0,1:01:46.24,1:01:48.01,Default,,0,0,0,,对吧 如果我对X一无所知\nDialogue: 0,1:01:48.22,1:01:49.21,Default,,0,0,0,,那么X就非真\nDialogue: 0,1:01:49.29,1:01:50.33,Default,,0,0,0,,这相当危险\nDialogue: 0,1:01:51.29,1:01:52.44,Default,,0,0,0,,首先 从逻辑学的角度来说\nDialogue: 0,1:01:52.46,1:01:53.76,Default,,0,0,0,,它一点也说不通\nDialogue: 0,1:01:54.48,1:01:56.33,Default,,0,0,0,,因为如果我对X一无所知的话\nDialogue: 0,1:01:58.38,1:01:59.69,Default,,0,0,0,,就说X非真\nDialogue: 0,1:02:00.24,1:02:03.32,Default,,0,0,0,,但为什么不说“X非真”非真\nDialogue: 0,1:02:03.85,1:02:05.66,Default,,0,0,0,,当然 我也许对后面那个命题也一无所知\nDialogue: 0,1:02:06.47,1:02:08.65,Default,,0,0,0,,因此(NOT (NOT X))就没有必要与X一致\nDialogue: 0,1:02:09.24,1:02:10.94,Default,,0,0,0,,等等等等\nDialogue: 0,1:02:11.71,1:02:13.93,Default,,0,0,0,,因此 这里面一定有某种“偏见”\nDialogue: 0,1:02:15.97,1:02:17.29,Default,,0,0,0,,这相当有趣\nDialogue: 0,1:02:17.29,1:02:18.09,Default,,0,0,0,,第二点就是\nDialogue: 0,1:02:20.14,1:02:24.12,Default,,0,0,0,,如果你基于此 构建一个真正的推理程序\nDialogue: 0,1:02:24.70,1:02:26.11,Default,,0,0,0,,想一想是多么地危险\nDialogue: 0,1:02:27.07,1:02:32.00,Default,,0,0,0,,你说我知道我可以推断出\nDialogue: 0,1:02:32.22,1:02:36.22,Default,,0,0,0,,与这个问题有关的所有事情\nDialogue: 0,1:02:37.44,1:02:40.78,Default,,0,0,0,,因为在我推理机制的内部\nDialogue: 0,1:02:41.23,1:02:44.20,Default,,0,0,0,,会认为所有与问题有关的知识\nDialogue: 0,1:02:44.24,1:02:46.27,Default,,0,0,0,,我都已经知道了\nDialogue: 0,1:02:48.44,1:02:53.04,Default,,0,0,0,,有相当多的大型组织都像这样运作 对吧？\nDialogue: 0,1:02:53.16,1:02:56.83,Default,,0,0,0,,大多数公司的市场部门都是这样工作的。\nDialogue: 0,1:02:56.83,1:02:59.12,Default,,0,0,0,,你们也知道这样做的后果\nDialogue: 0,1:03:00.33,1:03:03.45,Default,,0,0,0,,因此 向这个大型逻辑推理系统\nDialogue: 0,1:03:03.84,1:03:06.25,Default,,0,0,0,,输入各种查询 根据输出继续工作\nDialogue: 0,1:03:07.05,1:03:09.00,Default,,0,0,0,,的做法相当危险\nDialogue: 0,1:03:09.02,1:03:11.28,Default,,0,0,0,,因为它们内建的假说非常地有限\nDialogue: 0,1:03:12.60,1:03:14.36,Default,,0,0,0,,因此你对此需要非常非常地小心\nDialogue: 0,1:03:15.29,1:03:16.28,Default,,0,0,0,,就是这么一个深层次问题\nDialogue: 0,1:03:16.56,1:03:17.82,Default,,0,0,0,,这个问题并不是\nDialogue: 0,1:03:18.22,1:03:20.14,Default,,0,0,0,,通过构建更加聪明的实现\nDialogue: 0,1:03:20.16,1:03:21.85,Default,,0,0,0,,或者通过组织无穷循环\nDialogue: 0,1:03:22.16,1:03:23.84,Default,,0,0,0,,以及过滤器就可以消除的\nDialogue: 0,1:03:23.84,1:03:25.08,Default,,0,0,0,,这是完全不同的一类问题\nDialogue: 0,1:03:25.92,1:03:26.89,Default,,0,0,0,,完全不同的语义\nDialogue: 0,1:03:27.06,1:03:30.51,Default,,0,0,0,,我想该总结一下了 平心而论\nDialogue: 0,1:03:31.34,1:03:34.43,Default,,0,0,0,,逻辑式程序设计是一个振奋人心的想法\nDialogue: 0,1:03:34.60,1:03:37.00,Default,,0,0,0,,这个想法使你能够弥合\nDialogue: 0,1:03:37.04,1:03:38.78,Default,,0,0,0,,命令式与声明式语言的鸿沟\nDialogue: 0,1:03:39.90,1:03:42.94,Default,,0,0,0,,使得你可以谈论关系\nDialogue: 0,1:03:43.58,1:03:45.08,Default,,0,0,0,,从而获得惊人的力量\nDialogue: 0,1:03:46.09,1:03:49.48,Default,,0,0,0,,让你超越输入和输出的抽象\nDialogue: 0,1:03:50.56,1:03:51.53,Default,,0,0,0,,而关于逻辑\nDialogue: 0,1:03:52.46,1:03:56.46,Default,,0,0,0,,我认为这个问题还尚未解决\nDialogue: 0,1:03:58.03,1:04:01.80,Default,,0,0,0,,也许现在语言中最令人感兴趣的\nDialogue: 0,1:04:02.27,1:04:04.41,Default,,0,0,0,,研究问题之一就是\nDialogue: 0,1:04:04.67,1:04:08.28,Default,,0,0,0,,你该如何创建一门真正的逻辑语言？\nDialogue: 0,1:04:09.46,1:04:11.05,Default,,0,0,0,,其次 你如何从\nDialogue: 0,1:04:11.31,1:04:13.15,Default,,0,0,0,,这个逻辑和关系的世界\nDialogue: 0,1:04:13.52,1:04:16.43,Default,,0,0,0,,到更传统语言的世界之间\nDialogue: 0,1:04:16.46,1:04:17.98,Default,,0,0,0,,架起桥梁并结合两者的力量\nDialogue: 0,1:04:18.88,1:04:19.68,Default,,0,0,0,,有什么问题吗？\nDialogue: 0,1:04:23.29,1:04:25.29,Default,,0,0,0,,学生：你能够通过添加额外的规则\nDialogue: 0,1:04:25.29,1:04:27.74,Default,,0,0,0,,来解决最后一个问题么？\nDialogue: 0,1:04:27.96,1:04:29.85,Default,,0,0,0,,这里的困境是：你有某物的定义\nDialogue: 0,1:04:29.88,1:04:31.82,Default,,0,0,0,,但没有它对立面的定义\nDialogue: 0,1:04:32.08,1:04:33.92,Default,,0,0,0,,如果你在数据库中有\nDialogue: 0,1:04:34.14,1:04:36.89,Default,,0,0,0,,某些规则推导出(MORTAL X)\nDialogue: 0,1:04:36.99,1:04:38.70,Default,,0,0,0,,另外一些规则推导出(NOT (MORTAL X))\nDialogue: 0,1:04:38.75,1:04:40.37,Default,,0,0,0,,这不就基本上解决这个问题么？\nDialogue: 0,1:04:43.37,1:04:44.14,Default,,0,0,0,,教授：但问题就是\nDialogue: 0,1:04:44.75,1:04:46.38,Default,,0,0,0,,添加的这些规则是有穷个么？\nDialogue: 0,1:04:48.65,1:04:53.13,Default,,0,0,0,,学生：如果你同时定义正、反两面 --\nDialogue: 0,1:04:53.61,1:04:57.07,Default,,0,0,0,,教授：但问题就是 你该如何去做推断？\nDialogue: 0,1:05:00.20,1:05:02.11,Default,,0,0,0,,要知道 你不能直接定义命题的非\nDialogue: 0,1:05:03.40,1:05:04.76,Default,,0,0,0,,而问题就在于 在大型系统中\nDialogue: 0,1:05:04.78,1:05:07.96,Default,,0,0,0,,可能含有无穷个数的东西\nDialogue: 0,1:05:12.82,1:05:15.29,Default,,0,0,0,,这其中有两个问题\nDialogue: 0,1:05:15.29,1:05:16.56,Default,,0,0,0,,其一是可能有无穷项\nDialogue: 0,1:05:16.69,1:05:19.39,Default,,0,0,0,,另外是因为可能不向你想的那样\nDialogue: 0,1:05:21.51,1:05:24.52,Default,,0,0,0,,一个极好的例子 就是连通性\nDialogue: 0,1:05:25.12,1:05:26.54,Default,,0,0,0,,我想对连通性做推理\nDialogue: 0,1:05:28.05,1:05:30.38,Default,,0,0,0,,我会告诉你这有四个对象\nDialogue: 0,1:05:30.40,1:05:33.74,Default,,0,0,0,,A、B、C和D\nDialogue: 0,1:05:35.48,1:05:38.19,Default,,0,0,0,,我会告诉你A和B相连\nDialogue: 0,1:05:38.64,1:05:41.42,Default,,0,0,0,,C和D相连\nDialogue: 0,1:05:43.20,1:05:44.80,Default,,0,0,0,,然后我再告诉你A和D相连\nDialogue: 0,1:05:45.05,1:05:46.03,Default,,0,0,0,,就是这种情况\nDialogue: 0,1:05:46.78,1:05:48.52,Default,,0,0,0,,在这个例子中\nDialogue: 0,1:05:48.70,1:05:50.35,Default,,0,0,0,,我就希望有“封闭世界假说”这样的东西\nDialogue: 0,1:05:54.43,1:05:55.66,Default,,0,0,0,,这是个小玩具\nDialogue: 0,1:05:56.24,1:05:58.30,Default,,0,0,0,,但是很多时候 我都想说\nDialogue: 0,1:05:58.48,1:06:01.34,Default,,0,0,0,,我没告诉你的事 都假设非真\nDialogue: 0,1:06:04.26,1:06:06.27,Default,,0,0,0,,所以这并不是你显式地\nDialogue: 0,1:06:06.27,1:06:08.09,Default,,0,0,0,,为所有命题定义否命题就可以解决的\nDialogue: 0,1:06:09.47,1:06:12.70,Default,,0,0,0,,而是有些时候 你不清楚自己真正想要什么\nDialogue: 0,1:06:14.15,1:06:17.92,Default,,0,0,0,,同时定义原命题与否命题又太过于精细\nDialogue: 0,1:06:17.93,1:06:20.00,Default,,0,0,0,,这会使你陷入困境\nDialogue: 0,1:06:20.96,1:06:22.68,Default,,0,0,0,,但还是有很多方法\nDialogue: 0,1:06:23.32,1:06:25.93,Default,,0,0,0,,显式地定义否命题 并基于此进行推理\nDialogue: 0,1:06:26.51,1:06:27.66,Default,,0,0,0,,这个想法非常好\nDialogue: 0,1:06:28.07,1:06:31.45,Default,,0,0,0,,只是在一些复杂的大型问题中\nDialogue: 0,1:06:31.48,1:06:33.49,Default,,0,0,0,,这么做就变得有些笨重了\nDialogue: 0,1:06:43.46,1:06:45.96,Default,,0,0,0,,学生：有个论点 我不知道它和本节课的直接关系\nDialogue: 0,1:06:46.00,1:06:47.98,Default,,0,0,0,,但你想要表达的是\nDialogue: 0,1:06:48.49,1:06:50.16,Default,,0,0,0,,封闭世界假说的危害之一就是\nDialogue: 0,1:06:50.19,1:06:52.06,Default,,0,0,0,,你永远不会真正了解那里的所有事物\nDialogue: 0,1:06:53.44,1:06:55.32,Default,,0,0,0,,你永远不会知道它们的每个部分\nDialogue: 0,1:06:55.87,1:06:58.16,Default,,0,0,0,,这难道不是任何一门程序设计语言的主要问题吗？\nDialogue: 0,1:06:58.16,1:06:59.64,Default,,0,0,0,,写程序时 我总是\nDialogue: 0,1:06:59.90,1:07:01.56,Default,,0,0,0,,假设我考虑了所有的情况\nDialogue: 0,1:07:01.58,1:07:03.40,Default,,0,0,0,,然后我检查了每一种情况\nDialogue: 0,1:07:04.06,1:07:04.99,Default,,0,0,0,,然而在某处\nDialogue: 0,1:07:05.02,1:07:06.52,Default,,0,0,0,,我发现了我遗漏了其中的一个\nDialogue: 0,1:07:07.39,1:07:08.54,Default,,0,0,0,,教授：你说得很对\nDialogue: 0,1:07:08.54,1:07:09.76,Default,,0,0,0,,但这里的问题在于\nDialogue: 0,1:07:11.96,1:07:15.47,Default,,0,0,0,,对于你所做的事情\nDialogue: 0,1:07:15.48,1:07:17.34,Default,,0,0,0,,你是否认为它是逻辑问题\nDialogue: 0,1:07:19.60,1:07:20.51,Default,,0,0,0,,你说得非常正确\nDialogue: 0,1:07:20.51,1:07:22.22,Default,,0,0,0,,这是你永远不会遇到的情况\nDialogue: 0,1:07:22.22,1:07:24.14,Default,,0,0,0,,问题在于 如果你认为\nDialogue: 0,1:07:24.17,1:07:25.44,Default,,0,0,0,,你在进行逻辑式程序设计\nDialogue: 0,1:07:26.17,1:07:27.32,Default,,0,0,0,,然后审视你所编写的规则\nDialogue: 0,1:07:27.34,1:07:28.89,Default,,0,0,0,,并思考能从中推断出什么\nDialogue: 0,1:07:29.53,1:07:32.80,Default,,0,0,0,,你就需要清醒地认识到NOT具有另外的意义\nDialogue: 0,1:07:33.47,1:07:35.21,Default,,0,0,0,,它的意义基于某种假设\nDialogue: 0,1:07:35.24,1:07:36.70,Default,,0,0,0,,并且可能并不正确\nDialogue: 0,1:07:39.03,1:07:40.19,Default,,0,0,0,,学生：我不知道这样理解是否正确\nDialogue: 0,1:07:40.25,1:07:41.84,Default,,0,0,0,,也就是我们无法通过改变NOT\nDialogue: 0,1:07:42.25,1:07:46.08,Default,,0,0,0,,来消灭推断的所有可能性 从而解决这个问题？\nDialogue: 0,1:07:46.54,1:07:49.80,Default,,0,0,0,,教授：不 并不是这样\nDialogue: 0,1:07:52.96,1:07:55.08,Default,,0,0,0,,有很多种方法可以实现真正的逻辑非\nDialogue: 0,1:07:56.34,1:07:58.03,Default,,0,0,0,,实际上有很多种方法\nDialogue: 0,1:07:58.54,1:08:00.84,Default,,0,0,0,,但目前没有一个广为人知的高效算法\nDialogue: 0,1:08:01.61,1:08:02.56,Default,,0,0,0,,而且他们还--\nDialogue: 0,1:08:04.09,1:08:06.89,Default,,0,0,0,,这里所谓的“推论”\nDialogue: 0,1:08:07.39,1:08:08.83,Default,,0,0,0,,是建立在这个合一算法\nDialogue: 0,1:08:08.91,1:08:11.29,Default,,0,0,0,,以及模式匹配算法之中的\nDialogue: 0,1:08:11.98,1:08:16.19,Default,,0,0,0,,有多种方法可以实现真正的逻辑推理\nDialogue: 0,1:08:16.59,1:08:18.19,Default,,0,0,0,,但它们并不基于此\nDialogue: 0,1:08:18.51,1:08:20.73,Default,,0,0,0,,而逻辑式程序设计语言也不倾向于这么做\nDialogue: 0,1:08:20.75,1:08:23.85,Default,,0,0,0,,因为大家都知道 那样做非常低效\nDialogue: 0,1:08:29.39,1:08:30.03,Default,,0,0,0,,好吧 下课\nDialogue: 0,1:08:30.03,1:08:42.68,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:08:30.03,1:08:42.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec8b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nActive Line: 5\nVideo Position: 984\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:18.91,0:00:21.79,EN,,0,0,0,,PROFESSOR: All right, well, we've seen how the query language works.\nDialogue: 0,0:00:22.64,0:00:25.07,EN,,0,0,0,,Now, let's talk about how it's implemented.\nDialogue: 0,0:00:26.28,0:00:27.98,EN,,0,0,0,,You already pretty much can guess\nDialogue: 0,0:00:28.59,0:00:29.47,EN,,0,0,0,,what's going on there.\nDialogue: 0,0:00:29.47,0:00:31.64,EN,,0,0,0,,At the bottom of it, there's a pattern matcher.\nDialogue: 0,0:00:32.81,0:00:34.25,EN,,0,0,0,,And we looked at a pattern matcher\nDialogue: 0,0:00:34.67,0:00:36.94,EN,,0,0,0,,when we did the rule-based control language.\nDialogue: 0,0:00:38.11,0:00:40.59,EN,,0,0,0,,Just to remind you, here are some sample patterns.\nDialogue: 0,0:00:41.52,0:00:43.68,EN,,0,0,0,,This is a pattern that will match\nDialogue: 0,0:00:43.80,0:00:44.92,EN,,0,0,0,,any list of three things\nDialogue: 0,0:00:44.96,0:00:47.10,EN,,0,0,0,,which the first is a\nDialogue: 0,0:00:47.16,0:00:48.33,EN,,0,0,0,,the second is c\nDialogue: 0,0:00:48.48,0:00:50.19,EN,,0,0,0,,and the middle one can be anything.\nDialogue: 0,0:00:50.65,0:00:52.27,EN,,0,0,0,,So in this little pattern-matching syntax,\nDialogue: 0,0:00:52.30,0:00:54.05,EN,,0,0,0,,there's only one distinction you make.\nDialogue: 0,0:00:54.05,0:00:57.20,EN,,0,0,0,,There's either literal things or variables,\nDialogue: 0,0:00:57.23,0:00:58.86,EN,,0,0,0,,and variables begin with question mark.\nDialogue: 0,0:01:01.37,0:01:03.64,EN,,0,0,0,,So this matches any list of three things\nDialogue: 0,0:01:04.44,0:01:06.50,EN,,0,0,0,,of which the first is a and the second is c.\nDialogue: 0,0:01:06.50,0:01:09.00,EN,,0,0,0,,This one matches any list of three things\nDialogue: 0,0:01:10.43,0:01:12.53,EN,,0,0,0,,of which the first is the symbol job.\nDialogue: 0,0:01:12.53,0:01:13.90,EN,,0,0,0,,The second can be anything.\nDialogue: 0,0:01:14.21,0:01:15.90,EN,,0,0,0,,And the third is a list of two things\nDialogue: 0,0:01:15.95,0:01:17.72,EN,,0,0,0,,of which the first is the symbol computer\nDialogue: 0,0:01:17.88,0:01:19.42,EN,,0,0,0,,and the second can be anything.\nDialogue: 0,0:01:20.48,0:01:25.55,EN,,0,0,0,,And this one, this next one matches any list of three things,\nDialogue: 0,0:01:25.87,0:01:26.99,EN,,0,0,0,,and the only difference is,\nDialogue: 0,0:01:28.40,0:01:31.32,EN,,0,0,0,,here, the third list, the first is the symbol computer,\nDialogue: 0,0:01:31.76,0:01:33.29,EN,,0,0,0,,and then there's some rest of the list.\nDialogue: 0,0:01:35.04,0:01:37.53,EN,,0,0,0,,So this means two elements and this means arbitrary number.\nDialogue: 0,0:01:37.86,0:01:39.74,EN,,0,0,0,,And our language implementation isn't\nDialogue: 0,0:01:39.85,0:01:42.06,EN,,0,0,0,,isn't even going to have to worry about implementing this dot\nDialogue: 0,0:01:42.11,0:01:44.17,EN,,0,0,0,,because that's automatically done by Lisp's reader.\nDialogue: 0,0:01:48.34,0:01:50.31,EN,,0,0,0,,Remember matchers also have some consistency in them.\nDialogue: 0,0:01:50.31,0:01:52.32,EN,,0,0,0,,This match is a list of three things\nDialogue: 0,0:01:52.59,0:01:53.98,EN,,0,0,0,,of which the first is a.\nDialogue: 0,0:01:54.43,0:01:55.79,EN,,0,0,0,,And the second and third can be anything,\nDialogue: 0,0:01:55.80,0:01:57.08,EN,,0,0,0,,but they have to be the same thing.\nDialogue: 0,0:01:57.94,0:01:58.84,EN,,0,0,0,,They're both called x.\nDialogue: 0,0:01:59.60,0:02:01.55,EN,,0,0,0,,And this matches a list of four things\nDialogue: 0,0:02:01.96,0:02:03.26,EN,,0,0,0,,of which the first is the fourth\nDialogue: 0,0:02:03.66,0:02:05.15,EN,,0,0,0,,and the second is the same as the third.\nDialogue: 0,0:02:05.59,0:02:08.60,EN,,0,0,0,,And this last one matches any list that begins with a.\nDialogue: 0,0:02:09.68,0:02:11.05,EN,,0,0,0,,The first thing is a,\nDialogue: 0,0:02:11.23,0:02:12.56,EN,,0,0,0,,and the rest can be anything.\nDialogue: 0,0:02:14.04,0:02:16.60,EN,,0,0,0,,So that's just a review of pattern matcher syntax\nDialogue: 0,0:02:16.62,0:02:17.87,EN,,0,0,0,,that you've already seen.\nDialogue: 0,0:02:18.78,0:02:19.64,EN,,0,0,0,,And remember,\nDialogue: 0,0:02:19.79,0:02:22.28,EN,,0,0,0,,that's implemented by some procedure called match.\nDialogue: 0,0:02:24.87,0:02:36.06,EN,,0,0,0,,And match takes a pattern and some data and a dictionary.\nDialogue: 0,0:02:43.20,0:02:47.12,EN,,0,0,0,,And match asks the question\nDialogue: 0,0:02:47.79,0:02:52.64,EN,,0,0,0,,is there any way to match this pattern against this data object\nDialogue: 0,0:02:53.55,0:02:56.73,EN,,0,0,0,,subject to the bindings that are already in this dictionary?\nDialogue: 0,0:02:58.16,0:02:59.21,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:02:59.56,0:03:06.43,EN,,0,0,0,,if we're going to match the pattern x, y, y, x\nDialogue: 0,0:03:07.71,0:03:13.84,EN,,0,0,0,,against the data a, b, b, a\nDialogue: 0,0:03:15.12,0:03:20.52,EN,,0,0,0,,subject to a dictionary, that says x equals a.\nDialogue: 0,0:03:22.01,0:03:25.23,EN,,0,0,0,,Then the matcher would say, yes, that's consistent.\nDialogue: 0,0:03:25.26,0:03:27.16,EN,,0,0,0,,These match, and it's consistent\nDialogue: 0,0:03:27.80,0:03:30.20,EN,,0,0,0,,with what's in the dictionary to say that x equals a.\nDialogue: 0,0:03:30.32,0:03:31.60,EN,,0,0,0,,And the result of the match\nDialogue: 0,0:03:32.25,0:03:34.30,EN,,0,0,0,,is the extended dictionary\nDialogue: 0,0:03:34.46,0:03:37.60,EN,,0,0,0,,that says x equals a and y equals b.\nDialogue: 0,0:03:39.49,0:03:42.24,EN,,0,0,0,,So a matcher takes in pattern data dictionary,\nDialogue: 0,0:03:42.38,0:03:44.54,EN,,0,0,0,,puts out an extended dictionary if it matches,\nDialogue: 0,0:03:44.97,0:03:46.84,EN,,0,0,0,,or if it doesn't match, says that it fails.\nDialogue: 0,0:03:46.84,0:03:47.71,EN,,0,0,0,,So, for example,\nDialogue: 0,0:03:47.88,0:03:50.38,EN,,0,0,0,,if I use the same pattern here,\nDialogue: 0,0:03:50.97,0:03:55.12,EN,,0,0,0,,if I say this x, y, y, x\nDialogue: 0,0:03:55.66,0:03:58.49,EN,,0,0,0,,match a, b, b, a\nDialogue: 0,0:03:59.47,0:04:02.84,EN,,0,0,0,,with the dictionary y equals a,\nDialogue: 0,0:04:05.15,0:04:06.81,EN,,0,0,0,,then the matcher would put out fail.\nDialogue: 0,0:04:12.52,0:04:14.65,EN,,0,0,0,,Well, you've already seen the code for a pattern matcher\nDialogue: 0,0:04:15.00,0:04:16.17,EN,,0,0,0,,so I'm not going to go over it,\nDialogue: 0,0:04:16.64,0:04:19.77,EN,,0,0,0,,but it's the same thing we've been doing before.\nDialogue: 0,0:04:21.19,0:04:23.22,EN,,0,0,0,,You saw that in the system on rule-based control.\nDialogue: 0,0:04:23.22,0:04:24.56,EN,,0,0,0,,It's essentially the same matcher.\nDialogue: 0,0:04:24.95,0:04:27.66,EN,,0,0,0,,In fact, I think the syntax is a little bit simpler\nDialogue: 0,0:04:28.16,0:04:29.31,EN,,0,0,0,,because we're not worrying about\nDialogue: 0,0:04:29.40,0:04:31.40,EN,,0,0,0,,arbitrary constants and expressions and things.\nDialogue: 0,0:04:31.40,0:04:32.88,EN,,0,0,0,,There's just variables and constants.\nDialogue: 0,0:04:35.79,0:04:37.32,EN,,0,0,0,,OK, well, given that,\nDialogue: 0,0:04:38.46,0:04:39.61,EN,,0,0,0,,what's a primitive query?\nDialogue: 0,0:04:42.97,0:04:45.34,EN,,0,0,0,,Primitive query is going to be a rather complicated thing.\nDialogue: 0,0:04:46.67,0:05:03.58,EN,,0,0,0,,It's going to be-- let's think about the query job of x is d dot y.\nDialogue: 0,0:05:07.04,0:05:08.73,EN,,0,0,0,,That's a query we might type in.\nDialogue: 0,0:05:09.40,0:05:11.39,EN,,0,0,0,,That's going to be implemented in the system.\nDialogue: 0,0:05:14.14,0:05:15.66,EN,,0,0,0,,We'll think of it as this little box.\nDialogue: 0,0:05:15.70,0:05:16.80,EN,,0,0,0,,Here's the primitive query.\nDialogue: 0,0:05:18.88,0:05:20.30,EN,,0,0,0,,What this little box is going to do\nDialogue: 0,0:05:22.24,0:05:27.28,EN,,0,0,0,,is take in two streams and put out a stream.\nDialogue: 0,0:05:31.96,0:05:33.20,EN,,0,0,0,,and put out a stream.\nDialogue: 0,0:05:34.03,0:05:36.19,EN,,0,0,0,,So the shape of a primitive query\nDialogue: 0,0:05:36.51,0:05:38.46,EN,,0,0,0,,is that it's a thing where two streams come in\nDialogue: 0,0:05:38.67,0:05:39.96,EN,,0,0,0,,and one stream goes out.\nDialogue: 0,0:05:41.12,0:05:46.20,EN,,0,0,0,,What these streams are going to be is down here is the database.\nDialogue: 0,0:05:51.95,0:05:53.93,EN,,0,0,0,,So we imagine all the things in the database\nDialogue: 0,0:05:55.93,0:05:57.20,EN,,0,0,0,,sort of sitting there in a stream\nDialogue: 0,0:05:57.31,0:05:58.40,EN,,0,0,0,,and this thing sucks on them.\nDialogue: 0,0:06:00.36,0:06:02.43,EN,,0,0,0,,So what are some things that might be in the database?\nDialogue: 0,0:06:08.43,0:06:20.32,EN,,0,0,0,,Oh, job of Alyssa is something\nDialogue: 0,0:06:21.96,0:06:23.71,EN,,0,0,0,,and some other job is something.\nDialogue: 0,0:06:25.77,0:06:30.41,EN,,0,0,0,,So imagine all of the facts in the database sitting there in the stream.\nDialogue: 0,0:06:32.04,0:06:33.10,EN,,0,0,0,,That's what comes in here.\nDialogue: 0,0:06:33.36,0:06:34.52,EN,,0,0,0,,What comes in here\nDialogue: 0,0:06:34.89,0:06:36.52,EN,,0,0,0,,is a stream of dictionaries.\nDialogue: 0,0:06:38.51,0:06:41.40,EN,,0,0,0,,So one particular dictionary might say\nDialogue: 0,0:06:46.70,0:06:49.31,EN,,0,0,0,,might say y equals programmer.\nDialogue: 0,0:06:55.47,0:06:56.64,EN,,0,0,0,,Now, what the query does\nDialogue: 0,0:06:57.07,0:06:59.80,EN,,0,0,0,,when it gets in a dictionary from this stream,\nDialogue: 0,0:07:02.01,0:07:06.67,EN,,0,0,0,,it finds all possible ways of matching the query\nDialogue: 0,0:07:07.45,0:07:10.24,EN,,0,0,0,,against whatever is coming in from the database.\nDialogue: 0,0:07:11.39,0:07:12.89,EN,,0,0,0,,It looks at the query as a pattern,\nDialogue: 0,0:07:13.15,0:07:16.72,EN,,0,0,0,,matches it against any fact from the database\nDialogue: 0,0:07:16.96,0:07:21.98,EN,,0,0,0,,or all possible ways of finding and matching the database\nDialogue: 0,0:07:22.94,0:07:25.68,EN,,0,0,0,,with respect to this dictionary that's coming in.\nDialogue: 0,0:07:27.55,0:07:29.69,EN,,0,0,0,,So for each fact in the database,\nDialogue: 0,0:07:29.72,0:07:34.35,EN,,0,0,0,,it calls the matcher using the pattern, fact, and dictionary.\nDialogue: 0,0:07:35.11,0:07:37.68,EN,,0,0,0,,And every time it gets a good match,\nDialogue: 0,0:07:38.19,0:07:39.93,EN,,0,0,0,,it puts out the extended dictionary.\nDialogue: 0,0:07:40.67,0:07:42.32,EN,,0,0,0,,So, for example, if this one comes in\nDialogue: 0,0:07:43.00,0:07:44.09,EN,,0,0,0,,and it finds a match,\nDialogue: 0,0:07:44.51,0:07:45.87,EN,,0,0,0,,out will come a dictionary\nDialogue: 0,0:07:46.81,0:07:49.79,EN,,0,0,0,,that in this case will have y equals programmer\nDialogue: 0,0:07:51.52,0:07:52.97,EN,,0,0,0,,nd x equals something.\nDialogue: 0,0:07:56.54,0:07:58.75,EN,,0,0,0,,y is programmer, x is something,\nDialogue: 0,0:07:58.96,0:08:00.54,EN,,0,0,0,,and d is whatever it found.\nDialogue: 0,0:08:01.72,0:08:02.27,EN,,0,0,0,,And that's all.\nDialogue: 0,0:08:03.52,0:08:07.82,EN,,0,0,0,,And, of course, it's going to try this for every fact in the dictionary.\nDialogue: 0,0:08:07.98,0:08:09.25,EN,,0,0,0,,So it might find lots of them.\nDialogue: 0,0:08:09.56,0:08:10.59,EN,,0,0,0,,It might find another one\nDialogue: 0,0:08:11.28,0:08:17.12,EN,,0,0,0,,that says y equals programmer and x equals, and d equals.\nDialogue: 0,0:08:19.18,0:08:21.55,EN,,0,0,0,,So thats, So for one frame coming in,\nDialogue: 0,0:08:21.76,0:08:23.69,EN,,0,0,0,,it might put out-- for one dictionary coming in,\nDialogue: 0,0:08:23.72,0:08:25.24,EN,,0,0,0,,it might put out a lot of dictionaries,\nDialogue: 0,0:08:26.54,0:08:28.67,EN,,0,0,0,,or it might put out none.\nDialogue: 0,0:08:30.47,0:08:38.48,EN,,0,0,0,,It might have something that wouldn't match like x equals FOO.\nDialogue: 0,0:08:39.02,0:08:40.89,EN,,0,0,0,,This one might not match anything\nDialogue: 0,0:08:41.52,0:08:45.12,EN,,0,0,0,,in which case nothing will go into this stream corresponding to this frame.\nDialogue: 0,0:08:47.51,0:08:51.28,EN,,0,0,0,,Or what you might do is put in an empty frame,\nDialogue: 0,0:08:52.91,0:08:56.24,EN,,0,0,0,,and an empty frame says try matching all ways--\nDialogue: 0,0:08:59.87,0:09:02.33,EN,,0,0,0,,find all possible ways of matching the query\nDialogue: 0,0:09:02.57,0:09:06.14,EN,,0,0,0,,against something in the database subject to no previous restrictions.\nDialogue: 0,0:09:07.57,0:09:09.16,EN,,0,0,0,,And if you think about what that means, that's just\nDialogue: 0,0:09:10.32,0:09:13.87,EN,,0,0,0,,the computation that's done when you type in a query right off.\nDialogue: 0,0:09:14.20,0:09:15.56,EN,,0,0,0,,It tries to find all matches.\nDialogue: 0,0:09:16.65,0:09:18.83,EN,,0,0,0,,So a primitive query sets up this mechanism.\nDialogue: 0,0:09:19.37,0:09:20.57,EN,,0,0,0,,And what the language does,\nDialogue: 0,0:09:22.75,0:09:24.67,EN,,0,0,0,,when you type in the query at the top level,\nDialogue: 0,0:09:24.84,0:09:26.14,EN,,0,0,0,,it takes this mechanism,\nDialogue: 0,0:09:26.16,0:09:28.35,EN,,0,0,0,,feeds in one single empty dictionary,\nDialogue: 0,0:09:30.86,0:09:32.56,EN,,0,0,0,,and then for each thing that comes out\nDialogue: 0,0:09:33.08,0:09:35.88,EN,,0,0,0,,takes the original query\nDialogue: 0,0:09:36.56,0:09:40.44,EN,,0,0,0,,and instantiates the result with all the different dictionaries,\nDialogue: 0,0:09:40.81,0:09:44.36,EN,,0,0,0,,producing a new stream of instantiated patterns here.\nDialogue: 0,0:09:44.99,0:09:46.51,EN,,0,0,0,,And that's what gets printed on the terminal.\nDialogue: 0,0:09:48.17,0:09:51.24,EN,,0,0,0,,That's the basic mechanism going on there.\nDialogue: 0,0:09:53.51,0:09:55.48,EN,,0,0,0,,Well, why is that so complicated?\nDialogue: 0,0:09:57.71,0:10:01.00,EN,,0,0,0,,You probably can think of a lot simpler ways to arrange this match for\nDialogue: 0,0:10:01.37,0:10:04.25,EN,,0,0,0,,a primitive query rather than having all of these streams floating around.\nDialogue: 0,0:10:05.18,0:10:06.09,EN,,0,0,0,,And the answer is--\nDialogue: 0,0:10:07.15,0:10:08.51,EN,,0,0,0,,you probably guess already.\nDialogue: 0,0:10:10.86,0:10:14.09,EN,,0,0,0,,The answer is this thing extends elegantly\nDialogue: 0,0:10:14.56,0:10:16.76,EN,,0,0,0,,to implement the means of combination.\nDialogue: 0,0:10:17.79,0:10:18.80,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:10:20.65,0:10:22.47,EN,,0,0,0,,suppose I don't only want to do this.\nDialogue: 0,0:10:22.47,0:10:26.96,EN,,0,0,0,,I don't want to say who to be everybody's job description.\nDialogue: 0,0:10:27.23,0:10:28.35,EN,,0,0,0,,Suppose I want to say\nDialogue: 0,0:10:29.47,0:10:35.92,EN,,0,0,0,,to say AND the job of x is d dot y\nDialogue: 0,0:10:36.80,0:10:47.04,EN,,0,0,0,,and the supervisor of x is z.\nDialogue: 0,0:10:48.80,0:10:50.67,EN,,0,0,0,,Now, supervisor of x is z\nDialogue: 0,0:10:51.39,0:10:52.96,EN,,0,0,0,,is going to be another primitive query\nDialogue: 0,0:10:53.71,0:10:58.43,EN,,0,0,0,,that has the same shape to take in a stream of data objects,\nDialogue: 0,0:10:59.18,0:11:01.64,EN,,0,0,0,,a stream of initial dictionaries,\nDialogue: 0,0:11:01.68,0:11:05.52,EN,,0,0,0,,which are the restrictions to try and use when you match,\nDialogue: 0,0:11:05.53,0:11:07.44,EN,,0,0,0,,and it's going to put out a stream of dictionaries.\nDialogue: 0,0:11:08.70,0:11:10.80,EN,,0,0,0,,So that's what this primitive query looks like.\nDialogue: 0,0:11:11.50,0:11:12.91,EN,,0,0,0,,And how do I implement the AND?\nDialogue: 0,0:11:12.91,0:11:13.45,EN,,0,0,0,,Well, it's simple.\nDialogue: 0,0:11:13.45,0:11:14.44,EN,,0,0,0,,I just hook them together.\nDialogue: 0,0:11:14.88,0:11:16.28,EN,,0,0,0,,I take the output of this one,\nDialogue: 0,0:11:16.96,0:11:18.81,EN,,0,0,0,,and I put that to the input of that one.\nDialogue: 0,0:11:19.83,0:11:21.84,EN,,0,0,0,,And I take the dictionary here and I fan it out.\nDialogue: 0,0:11:26.57,0:11:27.96,EN,,0,0,0,,And then you see how that's going to work,\nDialogue: 0,0:11:29.05,0:11:32.44,EN,,0,0,0,,because what's going to happen is a frame will now come in here,\nDialogue: 0,0:11:32.51,0:11:36.84,EN,,0,0,0,,which has a binding for x, y, and d.\nDialogue: 0,0:11:37.92,0:11:39.28,EN,,0,0,0,,And then when this one gets it, it'll say,\nDialogue: 0,0:11:39.29,0:11:41.60,EN,,0,0,0,,oh, gee, subject to these restrictions,\nDialogue: 0,0:11:42.17,0:11:49.24,EN,,0,0,0,,which now already have values in the dictionary for y and x and d,\nDialogue: 0,0:11:51.80,0:11:53.08,EN,,0,0,0,,it looks in the database and says,\nDialogue: 0,0:11:53.12,0:11:54.92,EN,,0,0,0,,gee, can I find any supervisor facts?\nDialogue: 0,0:11:56.04,0:11:58.51,EN,,0,0,0,,And if it finds any, out will come dictionaries\nDialogue: 0,0:11:59.58,0:12:09.34,EN,,0,0,0,,which have bindings for y and x and d and z now.\nDialogue: 0,0:12:12.07,0:12:14.09,EN,,0,0,0,,And then notice that the match---\nDialogue: 0,0:12:14.19,0:12:17.24,EN,,0,0,0,,because the frames coming in here have these restrictions,\nDialogue: 0,0:12:17.61,0:12:20.28,EN,,0,0,0,,that's the thing that assures when you do the AND,\nDialogue: 0,0:12:20.49,0:12:24.62,EN,,0,0,0,,this x will mean the same thing as that x.\nDialogue: 0,0:12:26.47,0:12:28.96,EN,,0,0,0,,Because by the time something comes floating in here,\nDialogue: 0,0:12:29.96,0:12:32.65,EN,,0,0,0,,x has a value that you have to match against consistently.\nDialogue: 0,0:12:34.46,0:12:36.17,EN,,0,0,0,,And then you remember from the code from the matcher,\nDialogue: 0,0:12:36.19,0:12:38.17,EN,,0,0,0,,there was something in the way the matcher did dictionaries\nDialogue: 0,0:12:38.20,0:12:39.82,EN,,0,0,0,,that arrange consistent matches.\nDialogue: 0,0:12:40.92,0:12:41.77,EN,,0,0,0,,So there's AND.\nDialogue: 0,0:12:44.08,0:12:46.94,EN,,0,0,0,,The important point to notice is the general shape.\nDialogue: 0,0:12:48.49,0:12:51.55,EN,,0,0,0,,Look at what happened: the AND of two queries, say, P and Q.\nDialogue: 0,0:12:52.88,0:12:55.61,EN,,0,0,0,,Here's P and Q.\nDialogue: 0,0:12:57.29,0:12:58.60,EN,,0,0,0,,The AND of two queries,\nDialogue: 0,0:13:00.27,0:13:01.19,EN,,0,0,0,,well, it looks like this.\nDialogue: 0,0:13:01.19,0:13:04.44,EN,,0,0,0,,Each query takes in a stream from the database,\nDialogue: 0,0:13:04.54,0:13:05.71,EN,,0,0,0,,a stream of inputs,\nDialogue: 0,0:13:06.33,0:13:08.17,EN,,0,0,0,,and puts out a stream of outputs.\nDialogue: 0,0:13:10.23,0:13:11.72,EN,,0,0,0,,And the important point to notice\nDialogue: 0,0:13:12.20,0:13:15.02,EN,,0,0,0,,is that if I draw a box around this thing\nDialogue: 0,0:13:19.26,0:13:23.64,EN,,0,0,0,,and say this is AND of P and Q,\nDialogue: 0,0:13:25.66,0:13:30.38,EN,,0,0,0,,then that box has exactly the same overall shape.\nDialogue: 0,0:13:32.04,0:13:34.20,EN,,0,0,0,,It's something that takes in a stream from the database.\nDialogue: 0,0:13:34.20,0:13:35.74,EN,,0,0,0,,Here it's going to get fanned out inside,\nDialogue: 0,0:13:36.60,0:13:37.93,EN,,0,0,0,,but from the outside you don't see that.\nDialogue: 0,0:13:38.16,0:13:40.64,EN,,0,0,0,,It takes an input stream and puts out an output stream.\nDialogue: 0,0:13:42.06,0:13:43.16,EN,,0,0,0,,So this is AND.\nDialogue: 0,0:13:43.57,0:13:45.72,EN,,0,0,0,,And then similarly, OR would look like this.\nDialogue: 0,0:13:46.02,0:13:49.58,EN,,0,0,0,,OR would-- although I didn't show you examples of OR.\nDialogue: 0,0:13:49.84,0:13:54.70,EN,,0,0,0,,OR would say can I find all ways of matching P or Q.\nDialogue: 0,0:13:55.80,0:13:58.07,EN,,0,0,0,,So I have P and Q. Each will have their shape.\nDialogue: 0,0:14:04.46,0:14:06.68,EN,,0,0,0,,And the way OR is implemented is\nDialogue: 0,0:14:08.54,0:14:10.91,EN,,0,0,0,,I'll take my database stream.\nDialogue: 0,0:14:12.50,0:14:13.49,EN,,0,0,0,,I'll fan it out.\nDialogue: 0,0:14:13.49,0:14:16.04,EN,,0,0,0,,I'll put one into P and one into Q.\nDialogue: 0,0:14:17.44,0:14:21.98,EN,,0,0,0,,I'll take my initial query stream coming in and fan it out.\nDialogue: 0,0:14:26.75,0:14:29.16,EN,,0,0,0,,So I'll look at all the answers I might get from P\nDialogue: 0,0:14:29.29,0:14:31.08,EN,,0,0,0,,and all the answers I might get from Q,\nDialogue: 0,0:14:31.61,0:14:34.56,EN,,0,0,0,,and I'll put them through some sort of thing that appends them\nDialogue: 0,0:14:34.62,0:14:37.48,EN,,0,0,0,,or merges the result into one stream,\nDialogue: 0,0:14:39.64,0:14:40.88,EN,,0,0,0,,and that's what will come out.\nDialogue: 0,0:14:41.08,0:14:48.24,EN,,0,0,0,,And this whole thing from the outside is OR.\nDialogue: 0,0:14:52.35,0:14:54.89,EN,,0,0,0,,And again, you see it has the same overall shape\nDialogue: 0,0:14:55.07,0:14:56.54,EN,,0,0,0,,And again, you see it has the same overall shape\nDialogue: 0,0:15:01.00,0:15:01.61,EN,,0,0,0,,What's NOT?\nDialogue: 0,0:15:02.02,0:15:03.45,EN,,0,0,0,,NOT works kind of the same way.\nDialogue: 0,0:15:04.31,0:15:05.95,EN,,0,0,0,,If I have some query P,\nDialogue: 0,0:15:06.86,0:15:13.50,EN,,0,0,0,,If I have P, I take the primitive query for P.\nDialogue: 0,0:15:14.69,0:15:16.32,EN,,0,0,0,,Here, I'm going to implement NOT P.\nDialogue: 0,0:15:18.68,0:15:20.54,EN,,0,0,0,,And NOT's just going to act as a filter.\nDialogue: 0,0:15:20.72,0:15:21.95,EN,,0,0,0,,I'll take in the database\nDialogue: 0,0:15:23.84,0:15:28.28,EN,,0,0,0,,and my original stream of dictionaries coming in,\nDialogue: 0,0:15:28.78,0:15:31.53,EN,,0,0,0,,and what NOT P will do is\nDialogue: 0,0:15:31.88,0:15:37.40,EN,,0,0,0,,it will filter these guys.\nDialogue: 0,0:15:39.02,0:15:40.09,EN,,0,0,0,,And the way it will filter it,\nDialogue: 0,0:15:40.19,0:15:42.70,EN,,0,0,0,,it will say when I get in a dictionary here,\nDialogue: 0,0:15:43.42,0:15:44.65,EN,,0,0,0,,I'll find all the matches,\nDialogue: 0,0:15:44.83,0:15:46.48,EN,,0,0,0,,and if I find any, I'll throw it away.\nDialogue: 0,0:15:47.46,0:15:49.93,EN,,0,0,0,,And if I don't find any matches to something coming in here,\nDialogue: 0,0:15:50.12,0:15:51.37,EN,,0,0,0,,I'll just pass that through,\nDialogue: 0,0:15:52.40,0:15:53.55,EN,,0,0,0,,so NOT is a pure filter.\nDialogue: 0,0:15:55.34,0:15:59.98,EN,,0,0,0,,So AND is-- think of these sort of electoral resistors or something.\nDialogue: 0,0:15:59.98,0:16:01.85,EN,,0,0,0,,AND is series combination\nDialogue: 0,0:16:02.49,0:16:04.14,EN,,0,0,0,,and OR is parallel combination.\nDialogue: 0,0:16:04.96,0:16:07.46,EN,,0,0,0,,And then NOT is not going to extend any dictionaries at all.\nDialogue: 0,0:16:07.46,0:16:08.40,EN,,0,0,0,,It's just going to filter it.\nDialogue: 0,0:16:08.75,0:16:11.79,EN,,0,0,0,,It's going to throw away the ones for which it finds a way to match.\nDialogue: 0,0:16:12.64,0:16:14.19,EN,,0,0,0,,And lisp-value is sort of the same way.\nDialogue: 0,0:16:14.84,0:16:16.60,EN,,0,0,0,,The filter's a little more complicated.\nDialogue: 0,0:16:16.60,0:16:17.37,EN,,0,0,0,,It applies to predicate.\nDialogue: 0,0:16:19.93,0:16:21.64,EN,,0,0,0,,The major point to notice here,\nDialogue: 0,0:16:21.92,0:16:23.55,EN,,0,0,0,,and it's a major point we've looked at before,\nDialogue: 0,0:16:23.64,0:16:25.29,EN,,0,0,0,,is this idea of closure.\nDialogue: 0,0:16:28.22,0:16:31.80,EN,,0,0,0,,The things that we build as a means of combination\nDialogue: 0,0:16:31.95,0:16:34.51,EN,,0,0,0,,have the same overall structure\nDialogue: 0,0:16:35.69,0:16:37.58,EN,,0,0,0,,as the primitive things that we're combining.\nDialogue: 0,0:16:39.75,0:16:41.68,EN,,0,0,0,,So the AND of two things\nDialogue: 0,0:16:41.71,0:16:43.72,EN,,0,0,0,,looked at from the outside has the same shape.\nDialogue: 0,0:16:44.63,0:16:46.14,EN,,0,0,0,,And what that means is that\nDialogue: 0,0:16:46.94,0:16:50.28,EN,,0,0,0,,this box here could be an AND or an OR or a NOT or something\nDialogue: 0,0:16:50.30,0:16:54.22,EN,,0,0,0,,because it has the same shape to interface to the larger things.\nDialogue: 0,0:16:54.95,0:16:56.68,EN,,0,0,0,,It's the same thing that allowed us to get\nDialogue: 0,0:16:56.92,0:16:58.96,EN,,0,0,0,,complexity in the Escher picture language\nDialogue: 0,0:16:59.55,0:17:01.31,EN,,0,0,0,,or allows you to immediately build up these\nDialogue: 0,0:17:01.34,0:17:03.26,EN,,0,0,0,,complicated structures just out of pairs.\nDialogue: 0,0:17:03.93,0:17:04.78,EN,,0,0,0,,It's closure.\nDialogue: 0,0:17:06.28,0:17:08.06,EN,,0,0,0,,And that's the thing that\nDialogue: 0,0:17:09.64,0:17:11.72,EN,,0,0,0,,allowed me to do what by now you took for granted\nDialogue: 0,0:17:11.76,0:17:14.91,EN,,0,0,0,,I said, gee, there's a query which is AND of job and salary,\nDialogue: 0,0:17:14.91,0:17:18.80,EN,,0,0,0,,and I said, oh, there's another one, which is AND of job, a NOT of something.\nDialogue: 0,0:17:19.26,0:17:20.92,EN,,0,0,0,,The fact that I can do that is\nDialogue: 0,0:17:20.94,0:17:22.91,EN,,0,0,0,,a direct consequence of this closure principle.\nDialogue: 0,0:17:25.18,0:17:27.08,EN,,0,0,0,,OK, let's break and then we'll go on.\nDialogue: 0,0:17:29.32,0:17:30.89,EN,,0,0,0,,AUDIENCE: Where does the dictionary come from?\nDialogue: 0,0:17:30.99,0:17:36.03,EN,,0,0,0,,PROFESSOR: The dictionary comes initially from what you type in.\nDialogue: 0,0:17:36.09,0:17:37.32,EN,,0,0,0,,So when you start this up,\nDialogue: 0,0:17:39.16,0:17:41.09,EN,,0,0,0,,the first thing it does is set up this whole structure.\nDialogue: 0,0:17:41.09,0:17:42.64,EN,,0,0,0,,It puts in one empty dictionary.\nDialogue: 0,0:17:45.00,0:17:47.24,EN,,0,0,0,,And if all you have is one primitive query,\nDialogue: 0,0:17:48.24,0:17:51.10,EN,,0,0,0,,then what will come out is a bunch of dictionaries with things filled in.\nDialogue: 0,0:17:52.31,0:17:54.33,EN,,0,0,0,,The general situation that I have here\nDialogue: 0,0:17:54.51,0:17:59.71,EN,,0,0,0,,is when this is in the middle of some nest of combined things.\nDialogue: 0,0:18:01.55,0:18:02.30,EN,,0,0,0,,So by the time.\nDialogue: 0,0:18:02.38,0:18:03.79,EN,,0,0,0,,Let's look at the picture over here.\nDialogue: 0,0:18:04.38,0:18:06.73,EN,,0,0,0,,This supervisor query gets in some dictionary.\nDialogue: 0,0:18:06.73,0:18:08.03,EN,,0,0,0,,Where did this one come from?\nDialogue: 0,0:18:08.73,0:18:11.15,EN,,0,0,0,,This dictionary came from the fact that\nDialogue: 0,0:18:12.84,0:18:14.89,EN,,0,0,0,,I'm looking at the output of this primitive query.\nDialogue: 0,0:18:16.26,0:18:17.88,EN,,0,0,0,,So maybe to be very specific,\nDialogue: 0,0:18:18.35,0:18:21.72,EN,,0,0,0,,if I literally typed in just this query at the top level,\nDialogue: 0,0:18:22.27,0:18:22.92,EN,,0,0,0,,this AND,\nDialogue: 0,0:18:23.07,0:18:25.28,EN,,0,0,0,,what would actually happen is it would build this structure\nDialogue: 0,0:18:25.50,0:18:30.24,EN,,0,0,0,,and start up this whole thing with one empty dictionary.\nDialogue: 0,0:18:31.77,0:18:34.33,EN,,0,0,0,,And now this one would process, and a whole bunch of dictionaries\nDialogue: 0,0:18:34.36,0:18:37.36,EN,,0,0,0,,would come out with x, y's and d's in them.\nDialogue: 0,0:18:38.64,0:18:39.58,EN,,0,0,0,,Run it through this one.\nDialogue: 0,0:18:40.19,0:18:42.16,EN,,0,0,0,,So now that's the input to this one.\nDialogue: 0,0:18:42.16,0:18:43.72,EN,,0,0,0,,This one would now put out some other stuff.\nDialogue: 0,0:18:45.04,0:18:48.22,EN,,0,0,0,,And if this itself were buried in some larger thing,\nDialogue: 0,0:18:49.31,0:18:51.00,EN,,0,0,0,,like an OR of something,\nDialogue: 0,0:18:53.42,0:18:55.71,EN,,0,0,0,,then that would go feed into the next one.\nDialogue: 0,0:18:58.56,0:19:01.28,EN,,0,0,0,,So you initially get only one empty dictionary when you start it,\nDialogue: 0,0:19:01.68,0:19:04.08,EN,,0,0,0,,but as you're in the middle of processing these compounds things,\nDialogue: 0,0:19:04.11,0:19:06.65,EN,,0,0,0,,that's where these cascades of dictionaries start getting generated.\nDialogue: 0,0:19:07.66,0:19:12.28,EN,,0,0,0,,AUDIENCE: Dictionaries only come about as a result of using the queries?\nDialogue: 0,0:19:15.12,0:19:17.69,EN,,0,0,0,,Or do they stays, do they become--\nDialogue: 0,0:19:18.84,0:19:22.81,EN,,0,0,0,,do they stay someplace in space like the database does?\nDialogue: 0,0:19:23.68,0:19:24.98,EN,,0,0,0,,Are these temporary items?\nDialogue: 0,0:19:24.98,0:19:27.18,EN,,0,0,0,,PROFESSOR: They're created temporarily in the matcher.\nDialogue: 0,0:19:28.03,0:19:29.88,EN,,0,0,0,,Really, they're someplace in storage.\nDialogue: 0,0:19:29.88,0:19:33.02,EN,,0,0,0,,Initially, someone creates a thing called the empty dictionary\nDialogue: 0,0:19:34.22,0:19:36.80,EN,,0,0,0,,that gets initially fed to this match procedure,\nDialogue: 0,0:19:36.81,0:19:39.05,EN,,0,0,0,,and then the match procedure builds some dictionaries,\nDialogue: 0,0:19:39.07,0:19:40.27,EN,,0,0,0,,and they get passed on and on.\nDialogue: 0,0:19:40.76,0:19:42.48,EN,,0,0,0,,AUDIENCE: OK, so they'll go way after the match?\nDialogue: 0,0:19:43.64,0:19:46.25,EN,,0,0,0,,PROFESSOR: They'll go away when no one needs them again, yeah.\nDialogue: 0,0:19:51.90,0:19:53.60,EN,,0,0,0,,AUDIENCE: It appears that the AND performs\nDialogue: 0,0:19:53.63,0:19:55.37,EN,,0,0,0,,some redundant searches of the database.\nDialogue: 0,0:19:55.96,0:19:57.48,EN,,0,0,0,,If the first clause matched,\nDialogue: 0,0:19:57.50,0:19:59.90,EN,,0,0,0,,let's say, the third element and not on the first two elements,\nDialogue: 0,0:20:00.25,0:20:03.64,EN,,0,0,0,,the second clause is going to look at those first two elements again,\nDialogue: 0,0:20:04.32,0:20:06.59,EN,,0,0,0,,discarding them because they don't match.\nDialogue: 0,0:20:06.64,0:20:08.72,EN,,0,0,0,,The match is already in the dictionary.\nDialogue: 0,0:20:10.00,0:20:12.56,EN,,0,0,0,,Would it makes sense to carry the data element\nDialogue: 0,0:20:12.57,0:20:14.43,EN,,0,0,0,,from the database along with the dictionary?\nDialogue: 0,0:20:15.69,0:20:17.60,EN,,0,0,0,,PROFESSOR: Yeah, there're... Well, in general,\nDialogue: 0,0:20:17.63,0:20:19.48,EN,,0,0,0,,there are other ways to arrange this search,\nDialogue: 0,0:20:20.12,0:20:21.74,EN,,0,0,0,,and there's some analysis that you can do.\nDialogue: 0,0:20:21.74,0:20:23.16,EN,,0,0,0,,I think there's a problem in the book,\nDialogue: 0,0:20:23.87,0:20:26.65,EN,,0,0,0,,which talks about a different way that you can cascade AND\nDialogue: 0,0:20:27.00,0:20:29.20,EN,,0,0,0,,to eliminate various kinds of redundancies.\nDialogue: 0,0:20:29.85,0:20:30.72,EN,,0,0,0,,This one is meant to be--\nDialogue: 0,0:20:31.32,0:20:34.54,EN,,0,0,0,,was mainly meant to be very simple so you can see how they fit together.\nDialogue: 0,0:20:34.70,0:20:35.38,EN,,0,0,0,,But you're quite right.\nDialogue: 0,0:20:35.38,0:20:37.32,EN,,0,0,0,,There are redundancies here that you can get rid of.\nDialogue: 0,0:20:38.37,0:20:40.80,EN,,0,0,0,,That's another reason why this language is somewhat slow.\nDialogue: 0,0:20:41.19,0:20:42.70,EN,,0,0,0,,There are a lot smarter things you can do.\nDialogue: 0,0:20:42.93,0:20:46.22,EN,,0,0,0,,We're just trying to show you a very simple, in principle, implementation.\nDialogue: 0,0:20:51.22,0:20:53.23,EN,,0,0,0,,AUDIENCE: Did you model this language on Prolog,\nDialogue: 0,0:20:53.24,0:20:55.13,EN,,0,0,0,,or did it just come out looking like Prolog?\nDialogue: 0,0:21:04.96,0:21:07.08,EN,,0,0,0,,PROFESSOR: Well, Gerry insulted a whole bunch of people yesterday,\nDialogue: 0,0:21:07.24,0:21:09.92,EN,,0,0,0,,so I might as well say that the MIT attitude towards Prolog is\nDialogue: 0,0:21:10.19,0:21:12.60,EN,,0,0,0,,is something that people did in about 1971\nDialogue: 0,0:21:12.64,0:21:15.60,EN,,0,0,0,,and decided that it wasn't really the right thing and stopped.\nDialogue: 0,0:21:16.12,0:21:22.80,EN,,0,0,0,,So we modeled this on the sort of natural way that this thing was done\nDialogue: 0,0:21:22.84,0:21:24.73,EN,,0,0,0,,in about 1971,\nDialogue: 0,0:21:25.13,0:21:27.24,EN,,0,0,0,,except at that point, we didn't do it with streams.\nDialogue: 0,0:21:28.27,0:21:33.04,EN,,0,0,0,,And then we... After we were using it for about six months,\nDialogue: 0,0:21:33.08,0:21:34.91,EN,,0,0,0,,we discovered that it had all these problems,\nDialogue: 0,0:21:34.94,0:21:36.30,EN,,0,0,0,,some of which I'll talk about later.\nDialogue: 0,0:21:37.33,0:21:38.19,EN,,0,0,0,,And we said,\nDialogue: 0,0:21:38.44,0:21:39.92,EN,,0,0,0,,gee, Prolog must have fixed those,\nDialogue: 0,0:21:39.93,0:21:41.21,EN,,0,0,0,,and then we found out that it didn't.\nDialogue: 0,0:21:41.25,0:21:43.02,EN,,0,0,0,,So this does about the same thing as Prolog.\nDialogue: 0,0:21:43.60,0:21:44.95,EN,,0,0,0,,AUDIENCE: Does Prolog use streams?\nDialogue: 0,0:21:44.95,0:21:46.20,EN,,0,0,0,,PROFESSOR: No. Prolog --\nDialogue: 0,0:21:46.78,0:21:51.04,EN,,0,0,0,,In how it behaves, it behaves a lot like Prolog.\nDialogue: 0,0:21:51.04,0:21:52.96,EN,,0,0,0,,Prolog uses a backtracking strategy.\nDialogue: 0,0:21:53.80,0:21:55.71,EN,,0,0,0,,But the other thing that's really good about Prolog\nDialogue: 0,0:21:55.72,0:21:57.98,EN,,0,0,0,,that makes it a usable thing\nDialogue: 0,0:21:58.28,0:22:01.50,EN,,0,0,0,,is that there's a really very, very\nDialogue: 0,0:22:01.68,0:22:04.09,EN,,0,0,0,,there's a really very, very well-engineered compiler technology\nDialogue: 0,0:22:04.11,0:22:05.32,EN,,0,0,0,,that makes it run fast.\nDialogue: 0,0:22:06.65,0:22:10.81,EN,,0,0,0,,So although you saw the merge spitting out these answers very, very slowly,\nDialogue: 0,0:22:11.66,0:22:13.61,EN,,0,0,0,,a real Prolog will run very, very fast.\nDialogue: 0,0:22:14.70,0:22:16.48,EN,,0,0,0,,Because even though it's sort of doing this,\nDialogue: 0,0:22:16.67,0:22:20.81,EN,,0,0,0,,the real work that went into Prolog is a very, very excellent compiler effort.\nDialogue: 0,0:22:24.30,0:22:25.21,EN,,0,0,0,,Let's take a break.\nDialogue: 0,0:22:25.42,0:22:36.17,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:23:16.65,0:23:18.83,EN,,0,0,0,,We've looked at the primitive queries\nDialogue: 0,0:23:19.21,0:23:23.52,EN,,0,0,0,,and the ways that streams are used to implement the means of combination:\nDialogue: 0,0:23:23.79,0:23:25.72,EN,,0,0,0,,AND and OR and NOT.\nDialogue: 0,0:23:26.95,0:23:28.43,EN,,0,0,0,,Now, let go on to the means of abstraction.\nDialogue: 0,0:23:29.58,0:23:32.80,EN,,0,0,0,,Remember, the means of abstraction in this language are rules.\nDialogue: 0,0:23:35.15,0:23:37.79,EN,,0,0,0,,So z is a boss in division d\nDialogue: 0,0:23:39.18,0:23:43.77,EN,,0,0,0,,if there's some x who has a job in division d\nDialogue: 0,0:23:45.68,0:23:47.47,EN,,0,0,0,,and z is the supervisor of x.\nDialogue: 0,0:23:48.90,0:23:50.60,EN,,0,0,0,,That's what it means for someone to be a boss.\nDialogue: 0,0:23:52.26,0:23:53.15,EN,,0,0,0,,So, and in effect,\nDialogue: 0,0:23:53.34,0:23:55.61,EN,,0,0,0,,if you think about what we're doing with relation to this,\nDialogue: 0,0:23:56.80,0:23:57.90,EN,,0,0,0,,there's the query we wrote--\nDialogue: 0,0:23:57.93,0:24:01.90,EN,,0,0,0,,the job of x is in d and the supervisor of x is z--\nDialogue: 0,0:24:02.19,0:24:04.28,EN,,0,0,0,,what we in effect want to do is take this whole mess\nDialogue: 0,0:24:05.07,0:24:06.57,EN,,0,0,0,,and draw a box around it\nDialogue: 0,0:24:19.08,0:24:24.54,EN,,0,0,0,,and say this whole thing inside the box\nDialogue: 0,0:24:25.15,0:24:32.48,EN,,0,0,0,,is boss of z in division d.\nDialogue: 0,0:24:33.90,0:24:35.25,EN,,0,0,0,,That's in effect what we want to do.\nDialogue: 0,0:24:38.72,0:24:39.72,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:24:43.18,0:24:44.08,EN,,0,0,0,,if we've done that,\nDialogue: 0,0:24:45.00,0:24:47.84,EN,,0,0,0,,and we want to check whether or not it's true\nDialogue: 0,0:24:47.95,0:24:50.51,EN,,0,0,0,,that Ben Bitdiddle is a boss in the computer division,\nDialogue: 0,0:24:51.10,0:25:02.86,EN,,0,0,0,,so if I want to say boss of Ben Bitdiddle in the computer division,\nDialogue: 0,0:25:04.78,0:25:07.08,EN,,0,0,0,,imagine typing that in as query to the system,\nDialogue: 0,0:25:07.12,0:25:09.16,EN,,0,0,0,,in effect what we want to do\nDialogue: 0,0:25:10.67,0:25:12.92,EN,,0,0,0,,is set up a dictionary here,\nDialogue: 0,0:25:15.82,0:25:23.63,EN,,0,0,0,,which has z to Ben Bitdiddle\nDialogue: 0,0:25:28.88,0:25:33.31,EN,,0,0,0,,and d to computer.\nDialogue: 0,0:25:37.08,0:25:38.62,EN,,0,0,0,,Where did that dictionary come from?\nDialogue: 0,0:25:38.68,0:25:40.71,EN,,0,0,0,,Let's look at the slide for one second.\nDialogue: 0,0:25:40.71,0:25:43.71,EN,,0,0,0,,That dictionary came from matching the query\nDialogue: 0,0:25:44.30,0:25:46.33,EN,,0,0,0,,that said boss of Ben Bitdiddle and computer\nDialogue: 0,0:25:46.51,0:25:49.63,EN,,0,0,0,,onto the conclusion of the rule: boss of z and d.\nDialogue: 0,0:25:51.65,0:25:54.11,EN,,0,0,0,,So we match the query to the conclusion of the rule.\nDialogue: 0,0:25:54.19,0:25:55.53,EN,,0,0,0,,That gives us a dictionary,\nDialogue: 0,0:25:58.99,0:26:02.54,EN,,0,0,0,,and that's the thing that we would now like to put into this whole big thing\nDialogue: 0,0:26:02.92,0:26:05.56,EN,,0,0,0,,and process and see if anything comes out the other side.\nDialogue: 0,0:26:06.67,0:26:09.88,EN,,0,0,0,,If anything comes out, it'll be true.\nDialogue: 0,0:26:11.33,0:26:12.37,EN,,0,0,0,,That's the basic idea.\nDialogue: 0,0:26:12.37,0:26:13.24,EN,,0,0,0,,So in general,\nDialogue: 0,0:26:14.03,0:26:15.40,EN,,0,0,0,,the way we implement a rule\nDialogue: 0,0:26:15.85,0:26:18.89,EN,,0,0,0,,is we match the conclusion of the rule\nDialogue: 0,0:26:20.86,0:26:22.96,EN,,0,0,0,,against something we might want to check it's true.\nDialogue: 0,0:26:23.58,0:26:25.12,EN,,0,0,0,,That match gives us a dictionary,\nDialogue: 0,0:26:25.29,0:26:28.22,EN,,0,0,0,,and with respect to that dictionary,\nDialogue: 0,0:26:30.35,0:26:34.51,EN,,0,0,0,,we process the body of the rule.\nDialogue: 0,0:26:36.33,0:26:37.68,EN,,0,0,0,,Well, that's really all there is,\nDialogue: 0,0:26:38.64,0:26:41.44,EN,,0,0,0,,except for two technical points.\nDialogue: 0,0:26:43.04,0:26:44.32,EN,,0,0,0,,The first technical point is that\nDialogue: 0,0:26:45.74,0:26:47.26,EN,,0,0,0,,I might have said something else.\nDialogue: 0,0:26:47.51,0:26:48.41,EN,,0,0,0,,I might have said\nDialogue: 0,0:26:50.54,0:26:52.36,EN,,0,0,0,,who's the boss in the computer division?\nDialogue: 0,0:26:52.54,0:26:56.32,EN,,0,0,0,,So I might say boss of who in computer division.\nDialogue: 0,0:27:00.78,0:27:01.63,EN,,0,0,0,,And if I did that,\nDialogue: 0,0:27:02.57,0:27:04.62,EN,,0,0,0,,what I would really like to do in effect is not\nDialogue: 0,0:27:05.04,0:27:06.49,EN,,0,0,0,,is start up this dictionary\nDialogue: 0,0:27:08.35,0:27:09.88,EN,,0,0,0,,with a match that sort of says,\nDialogue: 0,0:27:09.93,0:27:11.20,EN,,0,0,0,,well, d is computer\nDialogue: 0,0:27:14.35,0:27:18.48,EN,,0,0,0,,and z is whatever who is.\nDialogue: 0,0:27:21.70,0:27:23.22,EN,,0,0,0,,And our matcher won't quite do that.\nDialogue: 0,0:27:23.22,0:27:27.00,EN,,0,0,0,,That's not quite matching a pattern against data.\nDialogue: 0,0:27:28.58,0:27:29.72,EN,,0,0,0,,It's matching two patterns\nDialogue: 0,0:27:29.74,0:27:31.58,EN,,0,0,0,,sort of saying are they consistent or not\nDialogue: 0,0:27:31.90,0:27:33.48,EN,,0,0,0,,or what ways make them consistent.\nDialogue: 0,0:27:33.48,0:27:36.43,EN,,0,0,0,,In other words, what we need is not quite a pattern matcher,\nDialogue: 0,0:27:36.96,0:27:38.91,EN,,0,0,0,,but something a little bit more general\nDialogue: 0,0:27:39.13,0:27:40.11,EN,,0,0,0,,called a unifier.\nDialogue: 0,0:27:44.42,0:27:48.06,EN,,0,0,0,,And a unifier is a slight generalization of a pattern matcher.\nDialogue: 0,0:27:49.53,0:27:52.17,EN,,0,0,0,,What a unifier does is take two patterns\nDialogue: 0,0:27:53.23,0:27:57.53,EN,,0,0,0,,and say what's the most general thing you can substitute\nDialogue: 0,0:27:58.20,0:28:00.01,EN,,0,0,0,,for the variables in those two patterns\nDialogue: 0,0:28:02.68,0:28:05.08,EN,,0,0,0,,to make them satisfy the pattern simultaneously?\nDialogue: 0,0:28:05.68,0:28:06.60,EN,,0,0,0,,Let me give you an example.\nDialogue: 0,0:28:08.86,0:28:14.49,EN,,0,0,0,,If I have the pattern two-element list, which is x and x,\nDialogue: 0,0:28:15.76,0:28:17.15,EN,,0,0,0,,so this is I have a two-element list\nDialogue: 0,0:28:17.32,0:28:18.64,EN,,0,0,0,,where both elements are the same\nDialogue: 0,0:28:18.67,0:28:20.04,EN,,0,0,0,,and otherwise I don't care what they are,\nDialogue: 0,0:28:20.40,0:28:22.83,EN,,0,0,0,,and I unify that against the pattern\nDialogue: 0,0:28:22.92,0:28:24.62,EN,,0,0,0,,that says there's a two-element list,\nDialogue: 0,0:28:24.65,0:28:27.61,EN,,0,0,0,,and the first one is a and something and c\nDialogue: 0,0:28:28.00,0:28:30.14,EN,,0,0,0,,and the second one is a and b and z,\nDialogue: 0,0:28:33.07,0:28:34.88,EN,,0,0,0,,then what the unifier should tell me is,\nDialogue: 0,0:28:34.89,0:28:36.17,EN,,0,0,0,,oh yeah, in that dictionary,\nDialogue: 0,0:28:36.35,0:28:37.96,EN,,0,0,0,,x has to be a, b, c,\nDialogue: 0,0:28:39.34,0:28:41.92,EN,,0,0,0,,and y has to be d and z has to be c.\nDialogue: 0,0:28:43.44,0:28:46.28,EN,,0,0,0,,Those are the restrictions I'd have to put on the values of x, y, and z\nDialogue: 0,0:28:46.33,0:28:47.58,EN,,0,0,0,,to make these two unify,\nDialogue: 0,0:28:48.12,0:28:50.84,EN,,0,0,0,,or in other words, to make this match x\nDialogue: 0,0:28:51.15,0:28:53.37,EN,,0,0,0,,and make this match x.\nDialogue: 0,0:28:55.28,0:28:57.76,EN,,0,0,0,,The unifier should be able to deduce that.\nDialogue: 0,0:28:58.54,0:29:01.08,EN,,0,0,0,,But the unifier may-- there are more complicated things.\nDialogue: 0,0:29:01.08,0:29:03.07,EN,,0,0,0,,I might have said something a little bit more complicated.\nDialogue: 0,0:29:03.48,0:29:05.74,EN,,0,0,0,,I might have said there's a list with two elements,\nDialogue: 0,0:29:07.00,0:29:08.28,EN,,0,0,0,,and they're both the same,\nDialogue: 0,0:29:08.86,0:29:11.15,EN,,0,0,0,,and they should unify against something of this form.\nDialogue: 0,0:29:12.65,0:29:15.36,EN,,0,0,0,,And the unifier should be able to deduce from that.\nDialogue: 0,0:29:16.89,0:29:19.57,EN,,0,0,0,,Like that y would have to be b. y would have to be b.\nDialogue: 0,0:29:19.57,0:29:22.12,EN,,0,0,0,,Because these two are the same,\nDialogue: 0,0:29:22.22,0:29:23.52,EN,,0,0,0,,so y's got to be b.\nDialogue: 0,0:29:24.34,0:29:27.53,EN,,0,0,0,,And v here would have to be a.\nDialogue: 0,0:29:28.94,0:29:30.99,EN,,0,0,0,,And z and w can be anything,\nDialogue: 0,0:29:31.00,0:29:32.43,EN,,0,0,0,,but they have to be the same thing.\nDialogue: 0,0:29:35.71,0:29:41.76,EN,,0,0,0,,And x would have to be b, followed by a, followed by whatever w\nDialogue: 0,0:29:42.83,0:29:44.68,EN,,0,0,0,,or whatever z is, which is the same.\nDialogue: 0,0:29:44.70,0:29:49.42,EN,,0,0,0,,So you see, the unifier somehow has to deduce things to unify these patterns.\nDialogue: 0,0:29:50.88,0:29:53.52,EN,,0,0,0,,So you might think there's some kind of magic deduction going on,\nDialogue: 0,0:29:54.27,0:29:55.23,EN,,0,0,0,,but there's not.\nDialogue: 0,0:29:55.85,0:29:59.88,EN,,0,0,0,,A unifier is basically a very simple modification of a pattern matcher.\nDialogue: 0,0:30:00.15,0:30:01.85,EN,,0,0,0,,And if you look in the book, you'll see something like\nDialogue: 0,0:30:02.25,0:30:06.16,EN,,0,0,0,,like three or four lines of code added to the pattern matcher you just saw\nDialogue: 0,0:30:06.49,0:30:08.17,EN,,0,0,0,,to handle the symmetric case.\nDialogue: 0,0:30:08.28,0:30:10.81,EN,,0,0,0,,Remember, the pattern matcher has a place where it says\nDialogue: 0,0:30:11.66,0:30:14.28,EN,,0,0,0,,is this variable matching a constant.\nDialogue: 0,0:30:14.98,0:30:16.42,EN,,0,0,0,,And if so, it checks in the dictionary.\nDialogue: 0,0:30:16.42,0:30:18.25,EN,,0,0,0,,There's only one other clause in the unifier,\nDialogue: 0,0:30:18.49,0:30:20.75,EN,,0,0,0,,which says is this variable matching a variable,\nDialogue: 0,0:30:22.00,0:30:23.42,EN,,0,0,0,,in which case you go look in the dictionary\nDialogue: 0,0:30:23.45,0:30:25.68,EN,,0,0,0,,and see if that's consistent with what's in the dictionary.\nDialogue: 0,0:30:27.03,0:30:31.13,EN,,0,0,0,,So all the, quote, deduction that's in this language,\nDialogue: 0,0:30:31.28,0:30:34.59,EN,,0,0,0,,if you sort of look at it, sort of sits in the rule applications,\nDialogue: 0,0:30:34.99,0:30:37.88,EN,,0,0,0,,which, if you look at that, sits in the unifier,\nDialogue: 0,0:30:38.36,0:30:40.32,EN,,0,0,0,,which, if you look at that under a microscope,\nDialogue: 0,0:30:40.56,0:30:43.96,EN,,0,0,0,,sits essentially in the pattern matcher.\nDialogue: 0,0:30:44.94,0:30:47.07,EN,,0,0,0,,There's no magic at all going on in there.\nDialogue: 0,0:30:47.41,0:30:50.25,EN,,0,0,0,,And the, quote, deduction that you see\nDialogue: 0,0:30:50.94,0:30:52.89,EN,,0,0,0,,is just the fact that there's this recursion,\nDialogue: 0,0:30:52.92,0:30:55.69,EN,,0,0,0,,which is unwinding the matches bit by bit.\nDialogue: 0,0:30:56.03,0:30:58.03,EN,,0,0,0,,So it looks like this thing is being very clever,\nDialogue: 0,0:30:58.44,0:31:00.36,EN,,0,0,0,,but in fact, it's not being very clever at all.\nDialogue: 0,0:31:02.14,0:31:04.41,EN,,0,0,0,,There are cases where a unifier might have to be clever.\nDialogue: 0,0:31:04.88,0:31:05.87,EN,,0,0,0,,Let me show you one more.\nDialogue: 0,0:31:11.07,0:31:13.36,EN,,0,0,0,,Suppose I want to unify a list of two elements,\nDialogue: 0,0:31:13.48,0:31:14.81,EN,,0,0,0,,x and x,\nDialogue: 0,0:31:17.24,0:31:22.14,EN,,0,0,0,,with a thing that says it's y followed by a dot y.\nDialogue: 0,0:31:24.37,0:31:26.12,EN,,0,0,0,,Now, if you think of what that would have to mean,\nDialogue: 0,0:31:26.86,0:31:29.71,EN,,0,0,0,,it would have to mean that x had better be the same as y,\nDialogue: 0,0:31:30.92,0:31:31.66,EN,,0,0,0,,but also\nDialogue: 0,0:31:31.82,0:31:36.16,EN,,0,0,0,,x had better be the same as a list whose first element is a and whose rest is y.\nDialogue: 0,0:31:37.33,0:31:39.45,EN,,0,0,0,,And if you think about what that would have to mean,\nDialogue: 0,0:31:42.27,0:31:44.71,EN,,0,0,0,,it would have to mean that y is the infinite list of a's.\nDialogue: 0,0:31:47.50,0:31:48.35,EN,,0,0,0,,In some sense,\nDialogue: 0,0:31:49.21,0:31:52.40,EN,,0,0,0,,in order to do that unification,\nDialogue: 0,0:31:52.60,0:31:54.84,EN,,0,0,0,,I have to solve the fixed-point equation\nDialogue: 0,0:31:55.05,0:32:01.84,EN,,0,0,0,,cons of a to y is equal to y.\nDialogue: 0,0:32:04.57,0:32:06.96,EN,,0,0,0,,And in general, I wrote a very simple one.\nDialogue: 0,0:32:07.29,0:32:08.67,EN,,0,0,0,,Really doing unification\nDialogue: 0,0:32:08.97,0:32:11.98,EN,,0,0,0,,might have to solve an arbitrary fixed-point equation:\nDialogue: 0,0:32:12.01,0:32:13.42,EN,,0,0,0,,f of y equals y.\nDialogue: 0,0:32:15.53,0:32:17.08,EN,,0,0,0,,And basically, you can't do that\nDialogue: 0,0:32:17.10,0:32:19.47,EN,,0,0,0,,and make the thing finite all the time.\nDialogue: 0,0:32:20.57,0:32:23.60,EN,,0,0,0,,So how does the logic language handle that?\nDialogue: 0,0:32:24.89,0:32:26.48,EN,,0,0,0,,The answer is it doesn't.\nDialogue: 0,0:32:27.16,0:32:28.04,EN,,0,0,0,,It just punts.\nDialogue: 0,0:32:28.73,0:32:31.07,EN,,0,0,0,,And there's a little check in the unifier,\nDialogue: 0,0:32:31.31,0:32:33.82,EN,,0,0,0,,which says, oh, is this one of the hard cases\nDialogue: 0,0:32:34.44,0:32:38.00,EN,,0,0,0,,which when I go to match things would involve solving a fixed-point equation?\nDialogue: 0,0:32:38.65,0:32:40.81,EN,,0,0,0,,And in this case, I will throw up my hands.\nDialogue: 0,0:32:42.84,0:32:44.65,EN,,0,0,0,,And if that check were not in there,\nDialogue: 0,0:32:45.00,0:32:45.88,EN,,0,0,0,,what would happen?\nDialogue: 0,0:32:47.99,0:32:49.10,EN,,0,0,0,,In most cases is\nDialogue: 0,0:32:49.13,0:32:51.31,EN,,0,0,0,,that the unifier would just go into an infinite loop.\nDialogue: 0,0:32:53.74,0:32:56.54,EN,,0,0,0,,And other logic programming languages work like that.\nDialogue: 0,0:32:56.80,0:32:58.14,EN,,0,0,0,,So there's really no magic.\nDialogue: 0,0:32:58.22,0:32:59.93,EN,,0,0,0,,The easy case is done in a matcher.\nDialogue: 0,0:33:00.10,0:33:01.58,EN,,0,0,0,,The hard case is not done at all.\nDialogue: 0,0:33:02.96,0:33:05.47,EN,,0,0,0,,And that's about the state of this technology.\nDialogue: 0,0:33:11.88,0:33:14.24,EN,,0,0,0,,OK, Let me just say again formally\nDialogue: 0,0:33:14.27,0:33:16.38,EN,,0,0,0,,how rules work now that I talked about unifiers.\nDialogue: 0,0:33:17.39,0:33:18.75,EN,,0,0,0,,So the official definition\nDialogue: 0,0:33:19.20,0:33:20.96,EN,,0,0,0,,is that to apply a rule,\nDialogue: 0,0:33:24.17,0:33:27.13,EN,,0,0,0,,we-- well, let's start using some words we've used before.\nDialogue: 0,0:33:28.27,0:33:32.01,EN,,0,0,0,,Let's talk about sticking dictionaries into\nDialogue: 0,0:33:32.88,0:33:34.78,EN,,0,0,0,,these big boxes of query things\nDialogue: 0,0:33:34.81,0:33:38.54,EN,,0,0,0,,as evaluating these large queries\nDialogue: 0,0:33:39.95,0:33:43.85,EN,,0,0,0,,relative to an environment or a frame.\nDialogue: 0,0:33:43.85,0:33:45.04,EN,,0,0,0,,So when you think of that dictionary,\nDialogue: 0,0:33:45.07,0:33:46.28,EN,,0,0,0,,what's the dictionary after all?\nDialogue: 0,0:33:46.72,0:33:48.18,EN,,0,0,0,,It's a bunch of meanings for symbols.\nDialogue: 0,0:33:48.18,0:33:50.22,EN,,0,0,0,,That's what we've been calling frames or environments.\nDialogue: 0,0:33:51.80,0:33:55.97,EN,,0,0,0,,What does it mean to do some processing relevant to an environment?\nDialogue: 0,0:33:55.97,0:33:57.42,EN,,0,0,0,,That's what we've been calling evaluation.\nDialogue: 0,0:33:58.33,0:34:01.56,EN,,0,0,0,,So we can say the way that you apply a rule\nDialogue: 0,0:34:01.92,0:34:06.16,EN,,0,0,0,,is to evaluate the rule body relative to an environment\nDialogue: 0,0:34:06.67,0:34:11.58,EN,,0,0,0,,that's formed by unifying the rule conclusion with the given query.\nDialogue: 0,0:34:13.23,0:34:14.51,EN,,0,0,0,,And the thing I want you to notice\nDialogue: 0,0:34:14.80,0:34:17.08,EN,,0,0,0,,is the complete formal similarity\nDialogue: 0,0:34:18.16,0:34:21.50,EN,,0,0,0,,to the net of circular evaluator or the substitution model.\nDialogue: 0,0:34:21.63,0:34:22.73,EN,,0,0,0,,To apply a procedure,\nDialogue: 0,0:34:22.86,0:34:28.36,EN,,0,0,0,,we evaluate the procedure body relative to an environment\nDialogue: 0,0:34:28.54,0:34:33.13,EN,,0,0,0,,that's formed by blinding the procedure parameters to the arguments.\nDialogue: 0,0:34:34.56,0:34:36.41,EN,,0,0,0,,There's a complete formal similarity there\nDialogue: 0,0:34:36.44,0:34:40.41,EN,,0,0,0,,between the rules, rule application, and procedure application\nDialogue: 0,0:34:40.57,0:34:42.30,EN,,0,0,0,,even though these things are very, very different.\nDialogue: 0,0:34:43.65,0:34:45.61,EN,,0,0,0,,And again, you have the EVAL APPLY loop.\nDialogue: 0,0:34:47.29,0:34:49.52,EN,,0,0,0,,EVAL and APPLY.\nDialogue: 0,0:34:53.39,0:34:57.39,EN,,0,0,0,,So in general, I might be processing some combined expression\nDialogue: 0,0:34:57.42,0:34:59.13,EN,,0,0,0,,that will turn into a rule application,\nDialogue: 0,0:35:00.70,0:35:03.28,EN,,0,0,0,,which will generate some dictionaries or frames or environments--\nDialogue: 0,0:35:03.31,0:35:04.72,EN,,0,0,0,,whatever you want to call them-- from match,\nDialogue: 0,0:35:05.02,0:35:08.43,EN,,0,0,0,,which will then be the input to some big compound thing like this.\nDialogue: 0,0:35:08.66,0:35:11.77,EN,,0,0,0,,This has pieces of it and may have other rule applications.\nDialogue: 0,0:35:13.58,0:35:15.68,EN,,0,0,0,,And you have essentially the same cycle\nDialogue: 0,0:35:15.72,0:35:18.68,EN,,0,0,0,,even though there's nothing here at all that looks like procedures.\nDialogue: 0,0:35:19.68,0:35:21.87,EN,,0,0,0,,It really has to do with the fact you've built a language\nDialogue: 0,0:35:22.08,0:35:25.49,EN,,0,0,0,,whose means of combination and abstraction unwind in certain ways.\nDialogue: 0,0:35:28.77,0:35:29.52,EN,,0,0,0,,And then in general,\nDialogue: 0,0:35:29.77,0:35:31.39,EN,,0,0,0,,what happens at the very top level,\nDialogue: 0,0:35:33.79,0:35:35.96,EN,,0,0,0,,you might have rules in your database also,\nDialogue: 0,0:35:36.65,0:35:38.70,EN,,0,0,0,,so things in this database might be rules.\nDialogue: 0,0:35:40.46,0:35:42.06,EN,,0,0,0,,There are ways to check that things are true.\nDialogue: 0,0:35:42.92,0:35:44.89,EN,,0,0,0,,So it might come in here and have to do a rule check.\nDialogue: 0,0:35:46.75,0:35:48.16,EN,,0,0,0,,And then there's some control structure\nDialogue: 0,0:35:48.19,0:35:50.48,EN,,0,0,0,,which says, well, you look at some rules, and you look at some data elements,\nDialogue: 0,0:35:50.51,0:35:51.80,EN,,0,0,0,,and you look at some rules and data elements,\nDialogue: 0,0:35:51.84,0:35:53.12,EN,,0,0,0,,and these fan out and out and out.\nDialogue: 0,0:35:53.35,0:35:55.48,EN,,0,0,0,,So it becomes essentially impossible\nDialogue: 0,0:35:55.68,0:35:57.69,EN,,0,0,0,,to say what order it's looking at these things in,\nDialogue: 0,0:35:58.20,0:36:00.27,EN,,0,0,0,,whether it's breadth first or depth first or anything.\nDialogue: 0,0:36:00.28,0:36:01.64,EN,,0,0,0,,And it's even more impossible\nDialogue: 0,0:36:01.66,0:36:05.58,EN,,0,0,0,,because the actual order is somehow buried in the delays of the streams.\nDialogue: 0,0:36:07.69,0:36:11.16,EN,,0,0,0,,So what's very hard to tell from this is the order in which it's scanned.\nDialogue: 0,0:36:11.27,0:36:12.16,EN,,0,0,0,,But what's true is,\nDialogue: 0,0:36:12.19,0:36:13.64,EN,,0,0,0,,because you're looking at the stream view,\nDialogue: 0,0:36:13.90,0:36:15.82,EN,,0,0,0,,is that all of them eventually get looked at.\nDialogue: 0,0:36:24.98,0:36:28.15,EN,,0,0,0,,Let me just mention one tiny technical problem.\nDialogue: 0,0:36:30.88,0:36:33.55,EN,,0,0,0,,Um Suppose I tried over here.\nDialogue: 0,0:36:37.53,0:36:41.00,EN,,0,0,0,,Suppose I tried saying boss of y is computer,\nDialogue: 0,0:36:44.22,0:36:45.78,EN,,0,0,0,,then a funny thing would happen.\nDialogue: 0,0:36:45.78,0:36:50.25,EN,,0,0,0,,As I stuck a dictionary with y in here,\nDialogue: 0,0:36:52.73,0:36:57.37,EN,,0,0,0,,I might get-- this y is not the same as that y,\nDialogue: 0,0:36:57.42,0:37:00.62,EN,,0,0,0,,which was the other piece of somebody's job description.\nDialogue: 0,0:37:01.58,0:37:03.80,EN,,0,0,0,,So if I really only did literally what I said,\nDialogue: 0,0:37:04.22,0:37:06.44,EN,,0,0,0,,we'd get some variable conflict problems.\nDialogue: 0,0:37:09.28,0:37:10.48,EN,,0,0,0,,So I lied to you a little bit.\nDialogue: 0,0:37:10.93,0:37:13.84,EN,,0,0,0,,Notice that problem is exactly a problem we've run into before.\nDialogue: 0,0:37:14.27,0:37:15.56,EN,,0,0,0,,It is precisely\nDialogue: 0,0:37:15.96,0:37:18.36,EN,,0,0,0,,the need for local variables in a language.\nDialogue: 0,0:37:19.24,0:37:21.74,EN,,0,0,0,,When I square, when I have the sum of squares,\nDialogue: 0,0:37:21.79,0:37:23.39,EN,,0,0,0,,that x had better not be that x.\nDialogue: 0,0:37:24.96,0:37:26.32,EN,,0,0,0,,That's exactly the same as\nDialogue: 0,0:37:27.39,0:37:29.77,EN,,0,0,0,,as this y had better not be that y.\nDialogue: 0,0:37:31.80,0:37:32.75,EN,,0,0,0,,And we know how to solve that.\nDialogue: 0,0:37:32.78,0:37:34.49,EN,,0,0,0,,We built -- That was this whole environment model,\nDialogue: 0,0:37:34.51,0:37:37.04,EN,,0,0,0,,and we built chains of frames and all sorts of things like that.\nDialogue: 0,0:37:37.71,0:37:39.10,EN,,0,0,0,,There's a much more brutal way to solve it.\nDialogue: 0,0:37:39.10,0:37:41.73,EN,,0,0,0,,In the query language, we didn't even do that.\nDialogue: 0,0:37:41.73,0:37:43.18,EN,,0,0,0,,We did something completely brutal.\nDialogue: 0,0:37:43.54,0:37:45.93,EN,,0,0,0,,We said every time you apply a rule,\nDialogue: 0,0:37:47.26,0:37:49.63,EN,,0,0,0,,rename consistently all the variables in the rule\nDialogue: 0,0:37:49.77,0:37:53.50,EN,,0,0,0,,to some new unique names that won't conflict with anything.\nDialogue: 0,0:37:54.04,0:37:57.10,EN,,0,0,0,,If you looked at the -- That's conceptually simpler,\nDialogue: 0,0:37:57.12,0:37:59.24,EN,,0,0,0,,but really brutal and not particularly efficient.\nDialogue: 0,0:37:59.97,0:38:01.15,EN,,0,0,0,,But notice,\nDialogue: 0,0:38:01.39,0:38:04.68,EN,,0,0,0,,we could have gotten rid of all of our environment structures\nDialogue: 0,0:38:05.50,0:38:08.72,EN,,0,0,0,,if we defined for procedures in Lisp the same thing.\nDialogue: 0,0:38:08.75,0:38:11.56,EN,,0,0,0,,If every time we applied a procedure and did the substitution model\nDialogue: 0,0:38:11.87,0:38:13.90,EN,,0,0,0,,we renamed all the variables in the procedure,\nDialogue: 0,0:38:14.19,0:38:16.28,EN,,0,0,0,,then we never would have had to worry about local variables\nDialogue: 0,0:38:16.33,0:38:17.39,EN,,0,0,0,,because they would never arise.\nDialogue: 0,0:38:19.04,0:38:20.41,EN,,0,0,0,,OK, well, that would be inefficient,\nDialogue: 0,0:38:20.91,0:38:23.04,EN,,0,0,0,,and it's inefficient here in the query language, too,\nDialogue: 0,0:38:23.29,0:38:24.59,EN,,0,0,0,,but we did it to keep it simple.\nDialogue: 0,0:38:25.61,0:38:26.67,EN,,0,0,0,,Let's break for questions.\nDialogue: 0,0:38:30.88,0:38:33.39,EN,,0,0,0,,AUDIENCE: When you started this section,\nDialogue: 0,0:38:33.40,0:38:39.60,EN,,0,0,0,,you emphasized how powerful our APPLY EVAL model was\nDialogue: 0,0:38:39.63,0:38:41.17,EN,,0,0,0,,that we could use it for any language.\nDialogue: 0,0:38:41.17,0:38:43.39,EN,,0,0,0,,And then you say we're going to have this language which is so different.\nDialogue: 0,0:38:43.95,0:38:45.13,EN,,0,0,0,,It turns out that this language,\nDialogue: 0,0:38:45.58,0:38:47.88,EN,,0,0,0,,as you just pointed out, is very much the same.\nDialogue: 0,0:38:47.88,0:38:49.85,EN,,0,0,0,,I'm wondering if you're arguing that all languages end up\nDialogue: 0,0:38:50.48,0:38:54.57,EN,,0,0,0,,coming down to this you can apply a rule or apply a procedure\nDialogue: 0,0:38:55.12,0:38:55.98,EN,,0,0,0,,or some kind of apply?\nDialogue: 0,0:38:57.07,0:38:58.88,EN,,0,0,0,,PROFESSOR: I would say that pretty much any language\nDialogue: 0,0:38:58.92,0:39:00.30,EN,,0,0,0,,where you really are building up\nDialogue: 0,0:39:00.92,0:39:04.40,EN,,0,0,0,,these means of combination and giving them simpler names\nDialogue: 0,0:39:04.70,0:39:06.86,EN,,0,0,0,,and you're saying anything of the sort, like\nDialogue: 0,0:39:07.79,0:39:09.90,EN,,0,0,0,,here's a general kind of expression,\nDialogue: 0,0:39:09.98,0:39:11.40,EN,,0,0,0,,like how to square something,\nDialogue: 0,0:39:12.03,0:39:14.20,EN,,0,0,0,,almost anything that you would call a procedure.\nDialogue: 0,0:39:14.88,0:39:15.88,EN,,0,0,0,,If that's got to have parts,\nDialogue: 0,0:39:15.90,0:39:17.24,EN,,0,0,0,,you have to unwind those parts.\nDialogue: 0,0:39:18.02,0:39:20.19,EN,,0,0,0,,You have to have some kind of organization which says\nDialogue: 0,0:39:20.57,0:39:24.03,EN,,0,0,0,,when I look at the abstract variables or tags\nDialogue: 0,0:39:24.06,0:39:27.10,EN,,0,0,0,,or whatever you want to call them that might stand for particular things,\nDialogue: 0,0:39:28.33,0:39:29.34,EN,,0,0,0,,you have to keep track of that,\nDialogue: 0,0:39:29.39,0:39:30.91,EN,,0,0,0,,and that's going to be something like an environment.\nDialogue: 0,0:39:31.72,0:39:32.54,EN,,0,0,0,,And then if you say\nDialogue: 0,0:39:32.70,0:39:35.26,EN,,0,0,0,,this part can have parts which I have to unwind,\nDialogue: 0,0:39:35.80,0:39:37.44,EN,,0,0,0,,you've got to have something like this cycle.\nDialogue: 0,0:39:39.97,0:39:43.20,EN,,0,0,0,,And lots and lots of languages have that character\nDialogue: 0,0:39:43.36,0:39:45.40,EN,,0,0,0,,as long ... when they sort of get put together in this way.\nDialogue: 0,0:39:45.59,0:39:47.20,EN,,0,0,0,,This language again really is different\nDialogue: 0,0:39:47.21,0:39:49.50,EN,,0,0,0,,because there's nothing like procedures on the outside.\nDialogue: 0,0:39:50.69,0:39:52.68,EN,,0,0,0,,When you go below the surface and you see the implementation,\nDialogue: 0,0:39:52.70,0:39:54.24,EN,,0,0,0,,of course, it starts looking the same.\nDialogue: 0,0:39:54.87,0:39:56.95,EN,,0,0,0,,But from the outside, it's a very different world view.\nDialogue: 0,0:39:56.95,0:39:58.54,EN,,0,0,0,,You're not computing functions of inputs.\nDialogue: 0,0:40:03.97,0:40:05.71,EN,,0,0,0,,AUDIENCE: You mentioned earlier that\nDialogue: 0,0:40:06.60,0:40:09.55,EN,,0,0,0,,when you build all of these rules in pattern matcher\nDialogue: 0,0:40:10.01,0:40:11.42,EN,,0,0,0,,and with the delayed action of streams,\nDialogue: 0,0:40:11.45,0:40:12.72,EN,,0,0,0,,you really have no way to know\nDialogue: 0,0:40:13.37,0:40:15.36,EN,,0,0,0,,in what order things are evaluated.\nDialogue: 0,0:40:15.58,0:40:15.94,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:40:15.94,0:40:18.28,EN,,0,0,0,,AUDIENCE: And that would indicate then that\nDialogue: 0,0:40:18.94,0:40:22.28,EN,,0,0,0,,you should only express declarative knowledge that's true for all-time,\nDialogue: 0,0:40:22.30,0:40:23.79,EN,,0,0,0,,no-time sequence built into it.\nDialogue: 0,0:40:23.95,0:40:25.47,EN,,0,0,0,,Otherwise, these things get all--\nDialogue: 0,0:40:27.39,0:40:28.76,EN,,0,0,0,,PROFESSOR: Yes. Yes.\nDialogue: 0,0:40:28.82,0:40:29.48,EN,,0,0,0,,The question is\nDialogue: 0,0:40:30.06,0:40:32.60,EN,,0,0,0,,this really is set up for doing declarative knowledge,\nDialogue: 0,0:40:33.26,0:40:34.81,EN,,0,0,0,,and as I presented it-- no\nDialogue: 0,0:40:35.71,0:40:39.56,EN,,0,0,0,,and I'll show you some of the ugly warts under this after the break.\nDialogue: 0,0:40:40.83,0:40:42.60,EN,,0,0,0,,As I presented it, it's just doing logic.\nDialogue: 0,0:40:43.07,0:40:44.52,EN,,0,0,0,,And in principle, if it were logic,\nDialogue: 0,0:40:44.54,0:40:46.81,EN,,0,0,0,,it wouldn't matter what order it's getting done.\nDialogue: 0,0:40:48.84,0:40:51.55,EN,,0,0,0,,And it's quite true\nDialogue: 0,0:40:51.60,0:40:53.61,EN,,0,0,0,,when you start doing things where you have side effects\nDialogue: 0,0:40:53.68,0:40:55.20,EN,,0,0,0,,like adding things to the database\nDialogue: 0,0:40:55.23,0:40:58.16,EN,,0,0,0,,and taking things out, and we'll see some others,\nDialogue: 0,0:40:58.75,0:41:00.83,EN,,0,0,0,,you loose that kind of control.\nDialogue: 0,0:41:01.29,0:41:02.94,EN,,0,0,0,,So, for example, contrasting with Prolog.\nDialogue: 0,0:41:02.94,0:41:05.15,EN,,0,0,0,,Say Prolog has various features\nDialogue: 0,0:41:05.16,0:41:07.79,EN,,0,0,0,,where you really exploit the order of evaluation.\nDialogue: 0,0:41:09.64,0:41:11.77,EN,,0,0,0,,And people write Prolog programs that way.\nDialogue: 0,0:41:11.77,0:41:14.04,EN,,0,0,0,,That turns out to be very complicated in Prolog,\nDialogue: 0,0:41:14.32,0:41:17.55,EN,,0,0,0,,although if you're an expert Prolog programmer, you can do it.\nDialogue: 0,0:41:18.59,0:41:20.21,EN,,0,0,0,,However, here I don't think you can do it at all.\nDialogue: 0,0:41:20.21,0:41:21.24,EN,,0,0,0,,It's very complicated\nDialogue: 0,0:41:21.72,0:41:23.64,EN,,0,0,0,,because you really are giving up control over\nDialogue: 0,0:41:23.77,0:41:25.72,EN,,0,0,0,,any prearranged order of trying things.\nDialogue: 0,0:41:27.15,0:41:30.16,EN,,0,0,0,,AUDIENCE: Now, that would indicate then that you have a functional mapping.\nDialogue: 0,0:41:30.67,0:41:32.51,EN,,0,0,0,,And when you started out this lecture,\nDialogue: 0,0:41:32.99,0:41:34.08,EN,,0,0,0,,you said that\nDialogue: 0,0:41:34.67,0:41:36.70,EN,,0,0,0,,we express the declarative knowledge which is a relation,\nDialogue: 0,0:41:37.15,0:41:38.81,EN,,0,0,0,,and we don't talk about the inputs and the outputs.\nDialogue: 0,0:41:41.21,0:41:43.37,EN,,0,0,0,,PROFESSOR: Well, there's a pun on functional, right?\nDialogue: 0,0:41:43.37,0:41:45.79,EN,,0,0,0,,There's functional in the sense of no side effects\nDialogue: 0,0:41:46.20,0:41:48.16,EN,,0,0,0,,and not depending on what order is going on.\nDialogue: 0,0:41:48.70,0:41:51.04,EN,,0,0,0,,And then there's functional in the sense of mathematical function,\nDialogue: 0,0:41:51.07,0:41:52.22,EN,,0,0,0,,which means input and output.\nDialogue: 0,0:41:52.59,0:41:54.36,EN,,0,0,0,,And it's just that pun that you're making, I think.\nDialogue: 0,0:41:56.51,0:41:58.51,EN,,0,0,0,,AUDIENCE: I'm a little unclear on what you're doing with\nDialogue: 0,0:41:58.81,0:42:00.70,EN,,0,0,0,,two statements, the two boss statements.\nDialogue: 0,0:42:01.27,0:42:05.74,EN,,0,0,0,,Is the first one building up the database\nDialogue: 0,0:42:05.76,0:42:08.08,EN,,0,0,0,,and the second one a query or--\nDialogue: 0,0:42:09.07,0:42:10.12,EN,,0,0,0,,PROFESSOR: OK, I'm sorry.\nDialogue: 0,0:42:12.44,0:42:15.16,EN,,0,0,0,,What I meant here, if I type something like this in as a query--\nDialogue: 0,0:42:16.12,0:42:18.44,EN,,0,0,0,,I should have given an example way at the very beginning.\nDialogue: 0,0:42:19.47,0:42:23.52,EN,,0,0,0,,If I type in job, Ben Bitdiddle, computer wizard,\nDialogue: 0,0:42:25.04,0:42:27.77,EN,,0,0,0,,what the processing will do is if it finds a match,\nDialogue: 0,0:42:28.30,0:42:30.28,EN,,0,0,0,,it'll find a match to that exact thing,\nDialogue: 0,0:42:30.86,0:42:33.28,EN,,0,0,0,,and it'll type out a job, Ben Bitdiddle, computer wizard.\nDialogue: 0,0:42:34.22,0:42:35.60,EN,,0,0,0,,If it doesn't find a match,\nDialogue: 0,0:42:35.69,0:42:36.75,EN,,0,0,0,,it won't find anything.\nDialogue: 0,0:42:37.40,0:42:39.55,EN,,0,0,0,,So what I should have said is the way\nDialogue: 0,0:42:39.56,0:42:42.27,EN,,0,0,0,,you use the query language to check whether something is true,\nDialogue: 0,0:42:43.40,0:42:45.77,EN,,0,0,0,,that's one of the things you want to do in logic programming,\nDialogue: 0,0:42:46.41,0:42:49.34,EN,,0,0,0,,is you type in your query and either that comes out or it doesn't.\nDialogue: 0,0:42:50.68,0:42:52.38,EN,,0,0,0,,So what I was trying to illustrate here,\nDialogue: 0,0:42:52.41,0:42:54.80,EN,,0,0,0,,I wanted to start with a very simple example\nDialogue: 0,0:42:54.83,0:42:56.62,EN,,0,0,0,,before talking about unifiers.\nDialogue: 0,0:42:57.48,0:42:58.11,EN,,0,0,0,,So what I should have said,\nDialogue: 0,0:42:58.14,0:43:00.96,EN,,0,0,0,,if I just wanted to check whether this is true,\nDialogue: 0,0:43:01.18,0:43:03.28,EN,,0,0,0,,I could type that in and see if anything came out\nDialogue: 0,0:43:05.16,0:43:06.27,EN,,0,0,0,,AUDIENCE: And then the second one--\nDialogue: 0,0:43:06.28,0:43:07.84,EN,,0,0,0,,PROFESSOR: The second one would be a real query.\nDialogue: 0,0:43:07.88,0:43:09.12,EN,,0,0,0,,AUDIENCE: A real query, yeah.\nDialogue: 0,0:43:10.77,0:43:13.10,EN,,0,0,0,,PROFESSOR: What would come out, see, it would go in here say with WHO,\nDialogue: 0,0:43:13.90,0:43:15.74,EN,,0,0,0,,and in would go frame that says z\nDialogue: 0,0:43:16.62,0:43:18.81,EN,,0,0,0,,z is bound to who and d is bound to computer.\nDialogue: 0,0:43:19.56,0:43:20.49,EN,,0,0,0,,And this will pass through,\nDialogue: 0,0:43:20.51,0:43:21.95,EN,,0,0,0,,and then by the time it got out of here,\nDialogue: 0,0:43:22.01,0:43:23.25,EN,,0,0,0,,who would pick up a binding.\nDialogue: 0,0:43:26.95,0:43:28.76,EN,,0,0,0,,AUDIENCE: On the unifying thing there,\nDialogue: 0,0:43:29.18,0:43:35.96,EN,,0,0,0,,I still am not sure what happens with who and z.\nDialogue: 0,0:43:36.46,0:43:39.58,EN,,0,0,0,,OK being unifying-- the rule here says--\nDialogue: 0,0:43:42.03,0:43:46.22,EN,,0,0,0,,OK, so you say that you can't make question mark equal to question mark who.\nDialogue: 0,0:43:46.26,0:43:48.08,EN,,0,0,0,,PROFESSOR: Right. That's what the matcher can't do.\nDialogue: 0,0:43:48.36,0:43:50.83,EN,,0,0,0,,But unifier, what this will mean to a unifier\nDialogue: 0,0:43:51.92,0:43:54.01,EN,,0,0,0,,is that there's an environment with three variables.\nDialogue: 0,0:43:56.69,0:43:57.90,EN,,0,0,0,,d here is computer.\nDialogue: 0,0:43:58.52,0:44:00.19,EN,,0,0,0,,z is whatever who is.\nDialogue: 0,0:44:01.83,0:44:05.26,EN,,0,0,0,,So if later on in the matcher routine\nDialogue: 0,0:44:07.20,0:44:10.38,EN,,0,0,0,,it said, for example, who has to be 3,\nDialogue: 0,0:44:12.06,0:44:13.66,EN,,0,0,0,,then when I looked up in the dictionary,\nDialogue: 0,0:44:14.00,0:44:16.40,EN,,0,0,0,,it will say, oh, z is 3 because it's the same as who.\nDialogue: 0,0:44:18.36,0:44:20.44,EN,,0,0,0,,And that's in some sense the only thing you need to do\nDialogue: 0,0:44:20.46,0:44:21.98,EN,,0,0,0,,to extend the unifier to a matcher.\nDialogue: 0,0:44:22.48,0:44:24.80,EN,,0,0,0,,AUDIENCE: OK, because it looked like when you were telling how to unify,\nDialogue: 0,0:44:24.83,0:44:26.96,EN,,0,0,0,,it looked like you would put the things together in such a way\nDialogue: 0,0:44:26.99,0:44:29.23,EN,,0,0,0,,that you'd actually solve and have a value for both of them.\nDialogue: 0,0:44:29.77,0:44:31.24,EN,,0,0,0,,And what it looks like now\nDialogue: 0,0:44:31.28,0:44:32.83,EN,,0,0,0,,is that you're actually pass a dictionary\nDialogue: 0,0:44:32.88,0:44:34.86,EN,,0,0,0,,with two variables and the variables are linked.\nDialogue: 0,0:44:34.88,0:44:37.23,EN,,0,0,0,,PROFESSOR: Right. It only looks like you're solving for both of them\nDialogue: 0,0:44:37.52,0:44:39.74,EN,,0,0,0,,because you're sort of looking at the whole solution at once.\nDialogue: 0,0:44:40.54,0:44:42.81,EN,,0,0,0,,If you sort of watch the thing getting built up recursively,\nDialogue: 0,0:44:42.81,0:44:43.74,EN,,0,0,0,,it's merely this.\nDialogue: 0,0:44:44.98,0:44:48.40,EN,,0,0,0,,AUDIENCE: OK, so you do pass off that dictionary with two variables?\nDialogue: 0,0:44:48.40,0:44:49.11,EN,,0,0,0,,PROFESSOR: That's right.\nDialogue: 0,0:44:49.11,0:44:49.68,EN,,0,0,0,,AUDIENCE: And link?\nDialogue: 0,0:44:50.38,0:44:52.91,EN,,0,0,0,,PROFESSOR: Right. It just looks like an ordinary dictionary.\nDialogue: 0,0:44:54.35,0:44:56.06,EN,,0,0,0,,AUDIENCE: When you're talking about the unifier,\nDialogue: 0,0:44:56.09,0:45:00.19,EN,,0,0,0,,is it that there are some cases or some points\nDialogue: 0,0:45:00.75,0:45:03.98,EN,,0,0,0,,that you are not able to unify them?\nDialogue: 0,0:45:04.03,0:45:04.30,EN,,0,0,0,,PROFESSOR: Right.\nDialogue: 0,0:45:04.97,0:45:08.46,EN,,0,0,0,,AUDIENCE: Can you just by building the rules or\nDialogue: 0,0:45:09.16,0:45:15.93,EN,,0,0,0,,writing the forms know in advance if you are going to be able to solve\nDialogue: 0,0:45:16.48,0:45:18.54,EN,,0,0,0,,to get the unification or not?\nDialogue: 0,0:45:18.76,0:45:22.94,EN,,0,0,0,,Can you add some properties either to the rules itself\nDialogue: 0,0:45:23.18,0:45:25.45,EN,,0,0,0,,or to the form that you're writing\nDialogue: 0,0:45:25.82,0:45:29.04,EN,,0,0,0,,so that you avoid the problem of not finding unification?\nDialogue: 0,0:45:29.18,0:45:31.15,EN,,0,0,0,,Well I mean, you can agree,\nDialogue: 0,0:45:31.47,0:45:35.26,EN,,0,0,0,,I think, to write in a fairly restricted way where you won't run into it.\nDialogue: 0,0:45:35.60,0:45:36.67,EN,,0,0,0,,See, because what you're getting--\nDialogue: 0,0:45:36.88,0:45:39.12,EN,,0,0,0,,see, the place where you get into problems is when you--\nDialogue: 0,0:45:39.68,0:45:44.25,EN,,0,0,0,,well, again, you're trying to match things like that\nDialogue: 0,0:45:44.59,0:45:47.20,EN,,0,0,0,,against things where these have structure,\nDialogue: 0,0:45:47.55,0:45:55.30,EN,,0,0,0,,where a, y, b, y something.\nDialogue: 0,0:45:58.98,0:46:01.48,EN,,0,0,0,,So this is the kind of place where you're going to get into trouble.\nDialogue: 0,0:46:03.07,0:46:05.80,EN,,0,0,0,,AUDIENCE: So you can do that syntactically?\nDialogue: 0,0:46:06.14,0:46:08.76,EN,,0,0,0,,PROFESSOR: So you can kind of watch your rules\nDialogue: 0,0:46:08.76,0:46:10.49,EN,,0,0,0,,in the kinds of things that your writing.\nDialogue: 0,0:46:11.90,0:46:14.08,EN,,0,0,0,,AUDIENCE: So that's the problem that the builder\nDialogue: 0,0:46:14.11,0:46:16.27,EN,,0,0,0,,of the database has to be concerned?\nDialogue: 0,0:46:16.57,0:46:17.80,EN,,0,0,0,,PROFESSOR: That's a problem.\nDialogue: 0,0:46:19.93,0:46:22.01,EN,,0,0,0,,It's a problem either-- not quite the builder of the database,\nDialogue: 0,0:46:22.04,0:46:23.61,EN,,0,0,0,,the person who is expressing the rules,\nDialogue: 0,0:46:24.01,0:46:25.31,EN,,0,0,0,,or the builder of the database.\nDialogue: 0,0:46:25.80,0:46:29.79,EN,,0,0,0,,What the unifier actually does is you can check at the next level down\nDialogue: 0,0:46:29.92,0:46:31.87,EN,,0,0,0,,when you actually get to the unifier\nDialogue: 0,0:46:32.41,0:46:34.76,EN,,0,0,0,,and you'll see in the code where it looks up in the dictionary.\nDialogue: 0,0:46:34.94,0:46:36.83,EN,,0,0,0,,If it sort of says what does y have to be?\nDialogue: 0,0:46:37.26,0:46:41.42,EN,,0,0,0,,Oh, does y have to be something that contains a y as its expression?\nDialogue: 0,0:46:41.96,0:46:43.26,EN,,0,0,0,,At that point, the unifier and say,\nDialogue: 0,0:46:43.28,0:46:46.24,EN,,0,0,0,,oh my God, I'm trying to solve a fixed-point equation.\nDialogue: 0,0:46:46.24,0:46:46.99,EN,,0,0,0,,I'll give it up here.\nDialogue: 0,0:46:48.59,0:46:51.91,EN,,0,0,0,,AUDIENCE: You make the distinction between the rules in the database.\nDialogue: 0,0:46:51.91,0:46:56.48,EN,,0,0,0,,Are the rules added to the database?\nDialogue: 0,0:46:56.95,0:46:57.36,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:46:57.87,0:46:58.87,EN,,0,0,0,,Yes, I should have said that.\nDialogue: 0,0:46:58.87,0:47:00.33,EN,,0,0,0,,One way to think about rules\nDialogue: 0,0:47:00.60,0:47:02.65,EN,,0,0,0,,is that they're just other things in the database.\nDialogue: 0,0:47:03.71,0:47:06.81,EN,,0,0,0,,So if you want to check the things that have to be checked in the database,\nDialogue: 0,0:47:06.83,0:47:09.44,EN,,0,0,0,,they're kind of virtual facts that are in the database.\nDialogue: 0,0:47:09.44,0:47:12.32,EN,,0,0,0,,AUDIENCE: But in that explanation, you made the differentiation\nDialogue: 0,0:47:12.43,0:47:17.26,EN,,0,0,0,,between database and the rules itself.\nDialogue: 0,0:47:18.23,0:47:19.90,EN,,0,0,0,,PROFESSOR: Yeah, I probably should not have done that.\nDialogue: 0,0:47:20.49,0:47:23.31,EN,,0,0,0,,The only reason to do that is in terms of the implementation.\nDialogue: 0,0:47:23.54,0:47:24.67,EN,,0,0,0,,When you look at the implementation,\nDialogue: 0,0:47:24.68,0:47:27.50,EN,,0,0,0,,there's a part which says check either primitive\nDialogue: 0,0:47:27.55,0:47:29.85,EN,,0,0,0,,assertions in the database or check rules.\nDialogue: 0,0:47:30.47,0:47:32.72,EN,,0,0,0,,And then the real reason, the real reason why\nDialogue: 0,0:47:32.78,0:47:34.56,EN,,0,0,0,,you can't tell what order things are going to come out in\nDialogue: 0,0:47:34.96,0:47:40.46,EN,,0,0,0,,is that the rules database and the data database\nDialogue: 0,0:47:40.48,0:47:43.68,EN,,0,0,0,,sort of get merged in a kind of delayed evaluation way.\nDialogue: 0,0:47:44.60,0:47:46.80,EN,,0,0,0,,And so that's what makes the order very complicated.\nDialogue: 0,0:47:55.44,0:47:56.09,EN,,0,0,0,,OK, let's break.\nDialogue: 0,0:47:56.30,0:48:09.90,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:48:10.04,0:48:14.41,EN,,0,0,0,,\nDialogue: 0,0:48:18.68,0:48:22.09,EN,,0,0,0,,\nDialogue: 0,0:48:22.09,0:48:25.96,EN,,0,0,0,,\nDialogue: 0,0:48:26.00,0:48:29.87,EN,,0,0,0,,\nDialogue: 0,0:48:33.16,0:48:35.37,EN,,0,0,0,,We've just seen how the logic language works\nDialogue: 0,0:48:35.39,0:48:36.41,EN,,0,0,0,,and how rules work.\nDialogue: 0,0:48:37.23,0:48:39.37,EN,,0,0,0,,Now, let's turn to a more profound question.\nDialogue: 0,0:48:40.12,0:48:41.28,EN,,0,0,0,,What do these things mean?\nDialogue: 0,0:48:43.18,0:48:46.86,EN,,0,0,0,,That brings us to the subtlest, most devious part\nDialogue: 0,0:48:46.99,0:48:48.67,EN,,0,0,0,,of this whole query language business,\nDialogue: 0,0:48:49.21,0:48:53.07,EN,,0,0,0,,and that is that it's not quite what it seems to be.\nDialogue: 0,0:48:53.57,0:48:56.22,EN,,0,0,0,,AND and OR and NOT\nDialogue: 0,0:48:57.02,0:48:58.88,EN,,0,0,0,,and the logical implication of rules\nDialogue: 0,0:48:59.69,0:49:06.64,EN,,0,0,0,,are not really the AND and OR and NOT and logical implication of logic.\nDialogue: 0,0:49:07.69,0:49:09.71,EN,,0,0,0,,Let me give you an example of that.\nDialogue: 0,0:49:09.91,0:49:12.22,EN,,0,0,0,,Certainly, if we have two things in logic,\nDialogue: 0,0:49:12.40,0:49:19.44,EN,,0,0,0,,it ought to be the case that AND of P and Q\nDialogue: 0,0:49:20.00,0:49:22.59,EN,,0,0,0,,is the same as AND of Q and P\nDialogue: 0,0:49:23.10,0:49:24.51,EN,,0,0,0,,and that OR of P and Q\nDialogue: 0,0:49:24.78,0:49:26.51,EN,,0,0,0,,is the same as OR of Q and P.\nDialogue: 0,0:49:28.67,0:49:30.09,EN,,0,0,0,,But let's look here.\nDialogue: 0,0:49:30.10,0:49:32.01,EN,,0,0,0,,Here's an example.\nDialogue: 0,0:49:32.18,0:49:36.16,EN,,0,0,0,,Let's talk about somebody outranking somebody else\nDialogue: 0,0:49:36.28,0:49:40.14,EN,,0,0,0,,in this our little database organization.\nDialogue: 0,0:49:40.14,0:49:42.89,EN,,0,0,0,,We'll say s is outranked by b\nDialogue: 0,0:49:44.64,0:49:48.62,EN,,0,0,0,,if or if either the supervisor of s is b\nDialogue: 0,0:49:49.63,0:49:51.07,EN,,0,0,0,,or there's some middle manager here,\nDialogue: 0,0:49:51.10,0:49:55.82,EN,,0,0,0,,that supervisor of s is m, and m is outranked by b.\nDialogue: 0,0:49:59.64,0:50:02.31,EN,,0,0,0,,So there's one way to define rule outranked by.\nDialogue: 0,0:50:02.31,0:50:04.16,EN,,0,0,0,,Or we can write exactly the same thing,\nDialogue: 0,0:50:05.08,0:50:06.91,EN,,0,0,0,,except at the bottom here,\nDialogue: 0,0:50:07.21,0:50:09.88,EN,,0,0,0,,we reversed the order of these two clauses.\nDialogue: 0,0:50:11.63,0:50:12.99,EN,,0,0,0,,And certainly if this were logic,\nDialogue: 0,0:50:13.00,0:50:14.88,EN,,0,0,0,,those ought to mean the same thing.\nDialogue: 0,0:50:16.69,0:50:17.31,EN,,0,0,0,,However,\nDialogue: 0,0:50:17.71,0:50:19.61,EN,,0,0,0,,in our particular implementation,\nDialogue: 0,0:50:19.64,0:50:22.88,EN,,0,0,0,,if you say something like who's outranked by Ben Bitdiddle,\nDialogue: 0,0:50:23.48,0:50:25.36,EN,,0,0,0,,what you'll find is that this rule\nDialogue: 0,0:50:26.76,0:50:28.72,EN,,0,0,0,,will work perfectly well and generate answers,\nDialogue: 0,0:50:30.04,0:50:31.98,EN,,0,0,0,,whereas this rule will go into an infinite loop.\nDialogue: 0,0:50:34.11,0:50:36.27,EN,,0,0,0,,And the reason for that is that\nDialogue: 0,0:50:36.33,0:50:40.33,EN,,0,0,0,,this will come in and say, oh, who's outranked by Ben Bitdiddle?\nDialogue: 0,0:50:41.92,0:50:43.53,EN,,0,0,0,,Find an s, find an s\nDialogue: 0,0:50:43.88,0:50:46.22,EN,,0,0,0,,which is outranked by b, where b is Ben Bitdiddle,\nDialogue: 0,0:50:47.50,0:50:49.63,EN,,0,0,0,,which is going to happen in it a subproblem.\nDialogue: 0,0:50:50.33,0:50:51.98,EN,,0,0,0,,Oh gee, find an m\nDialogue: 0,0:50:52.24,0:50:54.57,EN,,0,0,0,,such as m is outranked by Ben Bitdiddle\nDialogue: 0,0:50:55.61,0:50:57.36,EN,,0,0,0,,with no restrictions on m.\nDialogue: 0,0:50:58.56,0:51:00.40,EN,,0,0,0,,So this will say in order to solve this problem,\nDialogue: 0,0:51:01.42,0:51:03.29,EN,,0,0,0,,I solve exactly the same problem.\nDialogue: 0,0:51:04.57,0:51:07.23,EN,,0,0,0,,And then after I've solved that, I'll check for a supervisory relationship.\nDialogue: 0,0:51:08.00,0:51:09.16,EN,,0,0,0,,Whereas this one won't get into that,\nDialogue: 0,0:51:09.18,0:51:12.35,EN,,0,0,0,,because before it tries to find this outranked by,\nDialogue: 0,0:51:12.94,0:51:15.26,EN,,0,0,0,,it'll already have had a restriction on m here.\nDialogue: 0,0:51:18.38,0:51:20.94,EN,,0,0,0,,So these two things which ought to mean the same,\nDialogue: 0,0:51:20.99,0:51:22.67,EN,,0,0,0,,in fact, one goes into an infinite loop.\nDialogue: 0,0:51:22.86,0:51:25.04,EN,,0,0,0,,One goes, one does not.\nDialogue: 0,0:51:26.72,0:51:29.77,EN,,0,0,0,,That's a very extreme case\nDialogue: 0,0:51:29.79,0:51:32.65,EN,,0,0,0,,of a general thing that you'll find in logic programming that\nDialogue: 0,0:51:34.28,0:51:38.70,EN,,0,0,0,,if you start changing the order of the things in the ANDs or ORs,\nDialogue: 0,0:51:39.34,0:51:41.58,EN,,0,0,0,,you'll find tremendous differences in efficiency.\nDialogue: 0,0:51:42.24,0:51:43.21,EN,,0,0,0,,And we just saw\nDialogue: 0,0:51:43.55,0:51:46.54,EN,,0,0,0,,an infinitely big difference in efficiency and an infinite loop.\nDialogue: 0,0:51:49.19,0:51:51.74,EN,,0,0,0,,And there are similar things having to do order\nDialogue: 0,0:51:52.00,0:51:53.31,EN,,0,0,0,,in which you enter rules.\nDialogue: 0,0:51:54.07,0:51:56.48,EN,,0,0,0,,The order in which it happens to look at rules in the database\nDialogue: 0,0:51:56.70,0:51:59.95,EN,,0,0,0,,may vastly change the efficiency with which it gets out answers or,\nDialogue: 0,0:52:00.46,0:52:02.60,EN,,0,0,0,,in fact, send it into an infinite loop for some orderings.\nDialogue: 0,0:52:03.84,0:52:07.29,EN,,0,0,0,,And this whole thing has to do\nDialogue: 0,0:52:07.63,0:52:10.04,EN,,0,0,0,,the fact that you're checking these rules in some order.\nDialogue: 0,0:52:10.95,0:52:14.41,EN,,0,0,0,,And some rules may lead to really long paths of implication.\nDialogue: 0,0:52:14.44,0:52:16.06,EN,,0,0,0,,Others might, others might not.\nDialogue: 0,0:52:16.44,0:52:17.68,EN,,0,0,0,,And you don't know a priori\nDialogue: 0,0:52:17.72,0:52:19.16,EN,,0,0,0,,which ones are good and which ones are bad.\nDialogue: 0,0:52:19.30,0:52:21.48,EN,,0,0,0,,And there's a whole bunch of research having to do with that,\nDialogue: 0,0:52:22.16,0:52:23.76,EN,,0,0,0,,mostly having to do with thinking about\nDialogue: 0,0:52:23.95,0:52:26.97,EN,,0,0,0,,making parallel implementations of logic programming languages.\nDialogue: 0,0:52:27.32,0:52:29.90,EN,,0,0,0,,And in some sense, what you'd like to do is check all rules in parallel\nDialogue: 0,0:52:30.36,0:52:32.80,EN,,0,0,0,,and whichever ones get answers, you bubble them up. And\nDialogue: 0,0:52:33.04,0:52:34.99,EN,,0,0,0,,if some go down infinite deductive chain,\nDialogue: 0,0:52:35.02,0:52:38.25,EN,,0,0,0,,well, you just-- you know, memory is cheap and processors are cheap,\nDialogue: 0,0:52:38.28,0:52:40.49,EN,,0,0,0,,you just let them buzz for as for as long as you want.\nDialogue: 0,0:52:43.47,0:52:44.83,EN,,0,0,0,,There's a deeper problem, though,\nDialogue: 0,0:52:45.18,0:52:50.49,EN,,0,0,0,,in comparing this logic language to real logic.\nDialogue: 0,0:52:50.68,0:52:52.52,EN,,0,0,0,,The example I just showed you, it\nDialogue: 0,0:52:52.97,0:52:54.80,EN,,0,0,0,,went into an infinite loop maybe,\nDialogue: 0,0:52:55.37,0:52:56.99,EN,,0,0,0,,but at least it didn't give the wrong answer.\nDialogue: 0,0:52:58.37,0:53:03.64,EN,,0,0,0,,There's an actual deeper problem when we start comparing,\nDialogue: 0,0:53:03.68,0:53:05.24,EN,,0,0,0,,you know, seriously comparing\nDialogue: 0,0:53:05.71,0:53:08.46,EN,,0,0,0,,this logic language with real classical logic.\nDialogue: 0,0:53:09.49,0:53:12.43,EN,,0,0,0,,So let's sort of review real classical logic.\nDialogue: 0,0:53:13.71,0:53:21.04,EN,,0,0,0,,All humans are mortal.\nDialogue: 0,0:53:22.35,0:53:23.45,EN,,0,0,0,,That's pretty classical logic.\nDialogue: 0,0:53:24.39,0:53:28.67,EN,,0,0,0,,Then maybe we'll continue in the very best classical tradition.\nDialogue: 0,0:53:29.24,0:53:32.46,EN,,0,0,0,,We'll say all-- let's make it really classical.\nDialogue: 0,0:53:32.67,0:53:37.16,EN,,0,0,0,,All Greeks are human,\nDialogue: 0,0:53:40.49,0:53:46.06,EN,,0,0,0,,which has the syllogism that Socrates is a Greek.\nDialogue: 0,0:53:48.17,0:53:49.21,EN,,0,0,0,,And then what do you write here?\nDialogue: 0,0:53:49.21,0:53:51.89,EN,,0,0,0,,I think three dots, classical logic.\nDialogue: 0,0:53:51.89,0:53:54.33,EN,,0,0,0,,Therefore, then the syllogism,\nDialogue: 0,0:53:54.64,0:53:59.55,EN,,0,0,0,,Socrates is mortal.\nDialogue: 0,0:54:01.36,0:54:04.91,EN,,0,0,0,,So there's some real honest classical logic.\nDialogue: 0,0:54:05.88,0:54:11.05,EN,,0,0,0,,Let's compare that with our classical logic database.\nDialogue: 0,0:54:12.40,0:54:14.46,EN,,0,0,0,,So here's a classical logic database.\nDialogue: 0,0:54:16.27,0:54:17.48,EN,,0,0,0,,Socrates is a Greek.\nDialogue: 0,0:54:18.03,0:54:18.84,EN,,0,0,0,,Plato is a Greek.\nDialogue: 0,0:54:19.60,0:54:20.40,EN,,0,0,0,,Zeus is a Greek,\nDialogue: 0,0:54:20.84,0:54:21.98,EN,,0,0,0,,and Zeus is a god.\nDialogue: 0,0:54:24.12,0:54:29.96,EN,,0,0,0,,And all humans are mortal.\nDialogue: 0,0:54:30.54,0:54:32.12,EN,,0,0,0,,To show that something is mortal,\nDialogue: 0,0:54:32.16,0:54:33.60,EN,,0,0,0,,it's enough to show that it's human.\nDialogue: 0,0:54:34.65,0:54:35.90,EN,,0,0,0,,All humans are fallible.\nDialogue: 0,0:54:38.90,0:54:40.98,EN,,0,0,0,,And all Greeks are humans is not quite right.\nDialogue: 0,0:54:40.98,0:54:44.41,EN,,0,0,0,,This says that all Greeks who are not gods are human.\nDialogue: 0,0:54:45.71,0:54:47.04,EN,,0,0,0,,So to show something's human,\nDialogue: 0,0:54:47.07,0:54:48.89,EN,,0,0,0,,it's enough to show it's a Greek and not a god.\nDialogue: 0,0:54:49.32,0:54:52.88,EN,,0,0,0,,And the address of any Greek god is Mount Olympus.\nDialogue: 0,0:54:54.32,0:54:57.16,EN,,0,0,0,,So there's a little classical logic database.\nDialogue: 0,0:54:57.39,0:54:59.32,EN,,0,0,0,,And indeed, that would work fairly well.\nDialogue: 0,0:54:59.49,0:55:02.09,EN,,0,0,0,,If we type that in and say\nDialogue: 0,0:55:03.47,0:55:06.57,EN,,0,0,0,,is Socrates mortal or Socrates fallible or mortal?\nDialogue: 0,0:55:06.91,0:55:07.69,EN,,0,0,0,,It'll say yes.\nDialogue: 0,0:55:07.77,0:55:09.71,EN,,0,0,0,,Is Plato mortal and fallible.\nDialogue: 0,0:55:09.71,0:55:10.24,EN,,0,0,0,,It'll say yes.\nDialogue: 0,0:55:10.68,0:55:12.21,EN,,0,0,0,,If we say is Zeus mortal?\nDialogue: 0,0:55:12.21,0:55:13.23,EN,,0,0,0,,It won't find anything.\nDialogue: 0,0:55:14.90,0:55:15.96,EN,,0,0,0,,And it'll work perfectly well.\nDialogue: 0,0:55:16.54,0:55:20.12,EN,,0,0,0,,However, suppose we want to extend this.\nDialogue: 0,0:55:20.12,0:55:23.05,EN,,0,0,0,,Let's define what it means for someone to be a perfect being.\nDialogue: 0,0:55:23.82,0:55:27.21,EN,,0,0,0,,Let's say rule: a perfect being.\nDialogue: 0,0:55:34.05,0:55:35.48,EN,,0,0,0,,And I think this is right.\nDialogue: 0,0:55:35.48,0:55:38.14,EN,,0,0,0,,If you're up on your medieval scholastic philosophy,\nDialogue: 0,0:55:38.44,0:55:40.17,EN,,0,0,0,,I believe that perfect beings are ones\nDialogue: 0,0:55:40.68,0:55:42.65,EN,,0,0,0,,who were neither mortal nor fallible.\nDialogue: 0,0:55:44.10,0:55:56.84,EN,,0,0,0,,AND NOT mortal x, NOT fallible x.\nDialogue: 0,0:55:59.30,0:56:00.89,EN,,0,0,0,,So we'll define this system\nDialogue: 0,0:56:02.67,0:56:04.36,EN,,0,0,0,,to teach it what a perfect being is.\nDialogue: 0,0:56:05.79,0:56:07.69,EN,,0,0,0,,And now what we're going to do is\nDialogue: 0,0:56:08.06,0:56:10.17,EN,,0,0,0,,ask for the address of all the perfect beings.\nDialogue: 0,0:56:11.48,0:56:22.30,EN,,0,0,0,,AND the address of x is y and x is perfect.\nDialogue: 0,0:56:23.48,0:56:24.97,EN,,0,0,0,,And so what we're generating here is\nDialogue: 0,0:56:24.99,0:56:27.80,EN,,0,0,0,,the world's most exclusive mailing list.\nDialogue: 0,0:56:30.16,0:56:32.20,EN,,0,0,0,,For the address of all the perfect beings,\nDialogue: 0,0:56:32.24,0:56:33.47,EN,,0,0,0,,we might have typed this in.\nDialogue: 0,0:56:33.83,0:56:35.44,EN,,0,0,0,,Or we might type in this.\nDialogue: 0,0:56:36.24,0:56:50.57,EN,,0,0,0,,We'll say AND perfect of x and the address of x is y.\nDialogue: 0,0:56:52.06,0:56:54.96,EN,,0,0,0,,Well, suppose we type all that in and we try this query.\nDialogue: 0,0:56:55.19,0:56:56.76,EN,,0,0,0,,This query is going to give us an answer.\nDialogue: 0,0:56:57.65,0:57:00.00,EN,,0,0,0,,This query will say, yeah, Mount Olympus.\nDialogue: 0,0:57:04.23,0:57:06.57,EN,,0,0,0,,This query, in fact, is going to give us nothing.\nDialogue: 0,0:57:06.74,0:57:09.58,EN,,0,0,0,,It will say no addresses of perfect beings.\nDialogue: 0,0:57:11.64,0:57:12.51,EN,,0,0,0,,Now, why is that?\nDialogue: 0,0:57:12.51,0:57:13.44,EN,,0,0,0,,Why is there a difference?\nDialogue: 0,0:57:14.23,0:57:15.69,EN,,0,0,0,,This is not an infinite loop question.\nDialogue: 0,0:57:15.69,0:57:17.08,EN,,0,0,0,,This is a different answer question.\nDialogue: 0,0:57:19.48,0:57:20.09,EN,,0,0,0,,The reason is\nDialogue: 0,0:57:20.38,0:57:22.32,EN,,0,0,0,,that if you remember the implementation of NOT,\nDialogue: 0,0:57:23.50,0:57:24.84,EN,,0,0,0,,NOT acted as a filter.\nDialogue: 0,0:57:25.88,0:57:29.00,EN,,0,0,0,,NOT said I'm going to take some possible dictionaries,\nDialogue: 0,0:57:29.05,0:57:31.56,EN,,0,0,0,,some possible frames, some possible answers,\nDialogue: 0,0:57:31.79,0:57:33.16,EN,,0,0,0,,and filter out the ones\nDialogue: 0,0:57:33.29,0:57:34.94,EN,,0,0,0,,that happened to satisfy some condition,\nDialogue: 0,0:57:34.97,0:57:36.11,EN,,0,0,0,,and that's how I implement NOT.\nDialogue: 0,0:57:36.92,0:57:38.43,EN,,0,0,0,,If you think about what's going on here,\nDialogue: 0,0:57:40.11,0:57:42.65,EN,,0,0,0,,I'll build this query box where the address piece\nDialogue: 0,0:57:43.32,0:57:47.39,EN,,0,0,0,,the output of an address piece gets fed into a perfect piece.\nDialogue: 0,0:57:50.29,0:57:51.00,EN,,0,0,0,,What will happen is\nDialogue: 0,0:57:51.32,0:57:53.26,EN,,0,0,0,,the address piece will set up some things of\nDialogue: 0,0:57:53.32,0:57:54.83,EN,,0,0,0,,everyone whose address I know.\nDialogue: 0,0:57:55.29,0:57:57.64,EN,,0,0,0,,Those will get filtered by the NOTs inside perfect here.\nDialogue: 0,0:57:59.88,0:58:04.19,EN,,0,0,0,,So it will throw out the ones which happened to be either mortal or fallible.\nDialogue: 0,0:58:04.91,0:58:06.38,EN,,0,0,0,,In the other order what happens\nDialogue: 0,0:58:06.73,0:58:09.12,EN,,0,0,0,,is I set this up, started up with an empty frame.\nDialogue: 0,0:58:09.52,0:58:12.35,EN,,0,0,0,,The perfect in here doesn't find anything for the NOTs to filter,\nDialogue: 0,0:58:12.38,0:58:13.98,EN,,0,0,0,,so nothing comes out here at all.\nDialogue: 0,0:58:18.83,0:58:21.50,EN,,0,0,0,,And there's sort of nothing there that gets fed into the address thing.\nDialogue: 0,0:58:21.94,0:58:23.15,EN,,0,0,0,,So here, I don't get an answer.\nDialogue: 0,0:58:23.93,0:58:27.04,EN,,0,0,0,,And again, the reason for that is NOT isn't generating anything.\nDialogue: 0,0:58:27.44,0:58:28.80,EN,,0,0,0,,NOT's only throwing out things.\nDialogue: 0,0:58:29.08,0:58:30.51,EN,,0,0,0,,And if I never started up with anything,\nDialogue: 0,0:58:30.52,0:58:31.74,EN,,0,0,0,,there's nothing for it to throw out.\nDialogue: 0,0:58:32.02,0:58:33.77,EN,,0,0,0,,So out of this thing, I get the wrong answer.\nDialogue: 0,0:58:37.20,0:58:37.97,EN,,0,0,0,,How can you fix that?\nDialogue: 0,0:58:37.97,0:58:39.07,EN,,0,0,0,,Well, there are ways to fix that.\nDialogue: 0,0:58:39.36,0:58:40.91,EN,,0,0,0,,So you might say, well, that's sort of stupid.\nDialogue: 0,0:58:41.41,0:58:44.90,EN,,0,0,0,,Why are you just doing all your NOT stuff at the beginning?\nDialogue: 0,0:58:44.96,0:58:47.48,EN,,0,0,0,,The right way to implement NOT is to realize\nDialogue: 0,0:58:47.84,0:58:50.08,EN,,0,0,0,,that when you have conditions like NOT,\nDialogue: 0,0:58:50.33,0:58:52.09,EN,,0,0,0,,you should generate all your answers first,\nDialogue: 0,0:58:52.80,0:58:54.97,EN,,0,0,0,,and then with each of these dictionaries pass along\nDialogue: 0,0:58:55.52,0:58:57.85,EN,,0,0,0,,Gee, at the very end I'll do filtering.\nDialogue: 0,0:58:58.56,0:59:02.01,EN,,0,0,0,,And there are implementations of logic languages that work like that\nDialogue: 0,0:59:02.41,0:59:04.05,EN,,0,0,0,,that solve this particular problem.\nDialogue: 0,0:59:06.80,0:59:08.97,EN,,0,0,0,,However, there's a more profound problem,\nDialogue: 0,0:59:09.60,0:59:11.53,EN,,0,0,0,,which is which one of these is the right answer?\nDialogue: 0,0:59:12.53,0:59:14.24,EN,,0,0,0,,Is it Mount Olympus or is it nothing?\nDialogue: 0,0:59:15.37,0:59:18.73,EN,,0,0,0,,So you might say it's Mount Olympus,\nDialogue: 0,0:59:18.76,0:59:20.73,EN,,0,0,0,,because after all, Zeus is in that database,\nDialogue: 0,0:59:22.52,0:59:25.10,EN,,0,0,0,,and Zeus was neither mortal nor fallible.\nDialogue: 0,0:59:29.55,0:59:32.44,EN,,0,0,0,,So you might say Zeus wants to satisfy\nDialogue: 0,0:59:34.30,0:59:44.03,EN,,0,0,0,,NOT mortal Zeus or NOT fallible Zeus.\nDialogue: 0,0:59:44.12,0:59:45.85,EN,,0,0,0,,But let's actually look at that database.\nDialogue: 0,0:59:47.92,0:59:48.46,EN,,0,0,0,,Let's look at it.\nDialogue: 0,0:59:49.36,0:59:53.24,EN,,0,0,0,,There's no way-- how does it know that Zeus is not fallible?\nDialogue: 0,0:59:54.81,0:59:56.11,EN,,0,0,0,,There's nothing in there about that.\nDialogue: 0,0:59:57.93,0:59:59.66,EN,,0,0,0,,What's in there is that humans are fallible.\nDialogue: 0,1:00:02.16,1:00:04.12,EN,,0,0,0,,How does it know that Zeus is not mortal?\nDialogue: 0,1:00:04.48,1:00:05.93,EN,,0,0,0,,There's nothing in there about that.\nDialogue: 0,1:00:07.98,1:00:11.00,EN,,0,0,0,,It just said I don't have any rule, which--\nDialogue: 0,1:00:11.68,1:00:14.06,EN,,0,0,0,,see the only way I can deduce something's mortal is if it's human\nDialogue: 0,1:00:14.08,1:00:15.68,EN,,0,0,0,,and that's all it really knows about mortal.\nDialogue: 0,1:00:16.69,1:00:19.85,EN,,0,0,0,,And in fact, if you remember your classical mythology,\nDialogue: 0,1:00:19.87,1:00:23.48,EN,,0,0,0,,you know that the Greek gods were not mortal but fallible.\nDialogue: 0,1:00:25.05,1:00:28.65,EN,,0,0,0,,So the answer is not in the rules there.\nDialogue: 0,1:00:30.85,1:00:32.10,EN,,0,0,0,,See, why does it deduce that?\nDialogue: 0,1:00:34.49,1:00:38.32,EN,,0,0,0,,See, Socrates would certainly not have made this error of logic.\nDialogue: 0,1:00:40.08,1:00:42.67,EN,,0,0,0,,What NOT means in this language is not NOT.\nDialogue: 0,1:00:43.37,1:00:44.32,EN,,0,0,0,,It's not the NOT of logic.\nDialogue: 0,1:00:44.93,1:00:46.40,EN,,0,0,0,,What NOT needs in this language is\nDialogue: 0,1:00:47.16,1:00:49.96,EN,,0,0,0,,not deducible from things in the database\nDialogue: 0,1:00:50.75,1:00:53.34,EN,,0,0,0,,as opposed to not true.\nDialogue: 0,1:00:55.02,1:00:56.30,EN,,0,0,0,,That's a very big difference.\nDialogue: 0,1:00:57.30,1:00:58.64,EN,,0,0,0,,Subtle, but big.\nDialogue: 0,1:00:59.25,1:01:00.27,EN,,0,0,0,,So, in fact,\nDialogue: 0,1:01:00.76,1:01:03.92,EN,,0,0,0,,this is perfectly happy to say not anything that it doesn't know about.\nDialogue: 0,1:01:04.68,1:01:06.14,EN,,0,0,0,,So if you ask it is it not true\nDialogue: 0,1:01:06.16,1:01:07.83,EN,,0,0,0,,that Zeus likes chocolate ice cream?\nDialogue: 0,1:01:07.85,1:01:09.12,EN,,0,0,0,,It will say sure, it's not true.\nDialogue: 0,1:01:10.64,1:01:12.51,EN,,0,0,0,,Or anything else or anything it doesn't know about.\nDialogue: 0,1:01:12.59,1:01:17.34,EN,,0,0,0,,NOT means not deducible from the things you've told me.\nDialogue: 0,1:01:18.28,1:01:22.44,EN,,0,0,0,,In a world where you're identifying not deducible\nDialogue: 0,1:01:22.65,1:01:24.00,EN,,0,0,0,,with, in fact, not true,\nDialogue: 0,1:01:24.41,1:01:26.30,EN,,0,0,0,,this is called the closed world assumption.\nDialogue: 0,1:01:37.37,1:01:38.17,EN,,0,0,0,,closed world assumption.\nDialogue: 0,1:01:38.20,1:01:42.38,EN,,0,0,0,,Anything that I cannot deduce from what I know\nDialogue: 0,1:01:43.50,1:01:44.36,EN,,0,0,0,,is not true,\nDialogue: 0,1:01:46.24,1:01:48.01,EN,,0,0,0,,Right? If I don't know anything about x,\nDialogue: 0,1:01:48.22,1:01:49.21,EN,,0,0,0,,the x isn't true.\nDialogue: 0,1:01:49.29,1:01:50.33,EN,,0,0,0,,That's very dangerous.\nDialogue: 0,1:01:51.29,1:01:52.44,EN,,0,0,0,,From a logical point of view,\nDialogue: 0,1:01:52.46,1:01:53.76,EN,,0,0,0,,first of all, it doesn't really makes sense.\nDialogue: 0,1:01:54.48,1:01:56.33,EN,,0,0,0,,Because if I don't know anything about x,\nDialogue: 0,1:01:58.38,1:01:59.69,EN,,0,0,0,,I'm willing to say not x.\nDialogue: 0,1:02:00.24,1:02:03.32,EN,,0,0,0,,But am I willing to say not not x?\nDialogue: 0,1:02:03.85,1:02:05.66,EN,,0,0,0,,Well, sure, I don't know anything about that either maybe.\nDialogue: 0,1:02:06.47,1:02:08.65,EN,,0,0,0,,So not not x is not necessarily the same as x\nDialogue: 0,1:02:09.24,1:02:10.94,EN,,0,0,0,,and so on and so on and so on, so\nDialogue: 0,1:02:11.71,1:02:13.93,EN,,0,0,0,,there's some sort of funny bias in there.\nDialogue: 0,1:02:15.97,1:02:17.29,EN,,0,0,0,,So that's sort of funny.\nDialogue: 0,1:02:17.29,1:02:18.09,EN,,0,0,0,,The second thing,\nDialogue: 0,1:02:20.14,1:02:24.12,EN,,0,0,0,,if you start building up real reasoning programs based on this,\nDialogue: 0,1:02:24.70,1:02:26.11,EN,,0,0,0,,think how dangerous that is.\nDialogue: 0,1:02:27.07,1:02:32.00,EN,,0,0,0,,You're saying I know I'm in a position\nDialogue: 0,1:02:32.22,1:02:36.22,EN,,0,0,0,,to deduce everything true that's relevant to this problem.\nDialogue: 0,1:02:37.44,1:02:40.78,EN,,0,0,0,,I'm reasoning, and built into my reasoning mechanism\nDialogue: 0,1:02:41.23,1:02:44.20,EN,,0,0,0,,is the assumption that anything that I don't know\nDialogue: 0,1:02:44.24,1:02:46.27,EN,,0,0,0,,can't possibly be relevant to this problem.\nDialogue: 0,1:02:48.44,1:02:53.04,EN,,0,0,0,,Right? There are a lot of big organizations that work like that, right?\nDialogue: 0,1:02:53.16,1:02:56.83,EN,,0,0,0,,Most corporate marketing divisions work like that.\nDialogue: 0,1:02:56.83,1:02:59.12,EN,,0,0,0,,You know the consequences to that.\nDialogue: 0,1:03:00.33,1:03:03.45,EN,,0,0,0,,So it's very dangerous to start really\nDialogue: 0,1:03:03.84,1:03:06.25,EN,,0,0,0,,typing in these big logical implication systems\nDialogue: 0,1:03:07.05,1:03:09.00,EN,,0,0,0,,and going on what they say,\nDialogue: 0,1:03:09.02,1:03:11.28,EN,,0,0,0,,because they have this really limiting assumption built in.\nDialogue: 0,1:03:12.60,1:03:14.36,EN,,0,0,0,,So you have to be very, very careful about that.\nDialogue: 0,1:03:15.29,1:03:16.28,EN,,0,0,0,,And that's a deep problem.\nDialogue: 0,1:03:16.56,1:03:17.82,EN,,0,0,0,,That's not a problem about\nDialogue: 0,1:03:18.22,1:03:20.14,EN,,0,0,0,,we can make a little bit cleverer implementation\nDialogue: 0,1:03:20.16,1:03:21.85,EN,,0,0,0,,and do the filters and organize the\nDialogue: 0,1:03:22.16,1:03:23.84,EN,,0,0,0,,the infinite loops to make them go away.\nDialogue: 0,1:03:23.84,1:03:25.08,EN,,0,0,0,,It's a different kind of problem.\nDialogue: 0,1:03:25.92,1:03:26.89,EN,,0,0,0,,It's a different semantics.\nDialogue: 0,1:03:27.06,1:03:30.51,EN,,0,0,0,,So I think to wrap this up, it's fair to say\nDialogue: 0,1:03:31.34,1:03:34.43,EN,,0,0,0,,that logic programming I think is a terrifically exciting idea,\nDialogue: 0,1:03:34.60,1:03:37.00,EN,,0,0,0,,the idea that you can bridge this\nDialogue: 0,1:03:37.04,1:03:38.78,EN,,0,0,0,,gap from the imperative to the declarative,\nDialogue: 0,1:03:39.90,1:03:42.94,EN,,0,0,0,,that you can start talking about relations\nDialogue: 0,1:03:43.58,1:03:45.08,EN,,0,0,0,,and really get tremendous power\nDialogue: 0,1:03:46.09,1:03:49.48,EN,,0,0,0,,by going above the abstraction of what's my input and what's my output.\nDialogue: 0,1:03:50.56,1:03:51.53,EN,,0,0,0,,And linked to logic,\nDialogue: 0,1:03:52.46,1:03:56.46,EN,,0,0,0,,the problem is it's a goal that I think has yet to be realized.\nDialogue: 0,1:03:58.03,1:04:01.80,EN,,0,0,0,,And probably one of the very most interesting\nDialogue: 0,1:04:02.27,1:04:04.41,EN,,0,0,0,,research questions going on now in languages\nDialogue: 0,1:04:04.67,1:04:08.28,EN,,0,0,0,,is how do you somehow make a real logic language?\nDialogue: 0,1:04:09.46,1:04:11.05,EN,,0,0,0,,And secondly, how do you bridge the gap\nDialogue: 0,1:04:11.31,1:04:13.15,EN,,0,0,0,,this world of logic and relations\nDialogue: 0,1:04:13.52,1:04:16.43,EN,,0,0,0,,to the worlds of more traditional languages\nDialogue: 0,1:04:16.46,1:04:17.98,EN,,0,0,0,,and somehow combine the power of both.\nDialogue: 0,1:04:18.88,1:04:19.68,EN,,0,0,0,,OK, let's break.\nDialogue: 0,1:04:23.29,1:04:25.29,EN,,0,0,0,,AUDIENCE: Couldn't you solve that last problem\nDialogue: 0,1:04:25.29,1:04:27.74,EN,,0,0,0,,by having the extra rules that imply it?\nDialogue: 0,1:04:27.96,1:04:29.85,EN,,0,0,0,,The problem here is you have the definition of something,\nDialogue: 0,1:04:29.88,1:04:31.82,EN,,0,0,0,,but you don't have the definition of its opposite.\nDialogue: 0,1:04:32.08,1:04:33.92,EN,,0,0,0,,If you include in the database something that says\nDialogue: 0,1:04:34.14,1:04:36.89,EN,,0,0,0,,uh... something implies mortal x,\nDialogue: 0,1:04:36.99,1:04:38.70,EN,,0,0,0,,something else implies not mortal x,\nDialogue: 0,1:04:38.75,1:04:40.37,EN,,0,0,0,,haven't you basically solved the problem?\nDialogue: 0,1:04:43.37,1:04:44.14,EN,,0,0,0,,PROFESSOR: But the issue is\nDialogue: 0,1:04:44.75,1:04:46.38,EN,,0,0,0,,do you put a finite number of those in?\nDialogue: 0,1:04:48.65,1:04:53.13,EN,,0,0,0,,AUDIENCE: If things are specified always in pairs--\nDialogue: 0,1:04:53.61,1:04:57.07,EN,,0,0,0,,PROFESSOR: But the question is then what do you do about deduction?\nDialogue: 0,1:05:00.20,1:05:02.11,EN,,0,0,0,,See, you can't specify NOTs.\nDialogue: 0,1:05:03.40,1:05:04.76,EN,,0,0,0,,But the problem is, in a big system,\nDialogue: 0,1:05:04.78,1:05:07.96,EN,,0,0,0,,it turns out that might not be a finite number of things.\nDialogue: 0,1:05:12.82,1:05:15.29,EN,,0,0,0,,There are also sort of two issues.\nDialogue: 0,1:05:15.29,1:05:16.56,EN,,0,0,0,,Partly it might not be finite.\nDialogue: 0,1:05:16.69,1:05:19.39,EN,,0,0,0,,Partly it might be that's not what you want.\nDialogue: 0,1:05:21.51,1:05:24.52,EN,,0,0,0,,So a good example would be suppose I want to do connectivity.\nDialogue: 0,1:05:25.12,1:05:26.54,EN,,0,0,0,,I want a reason about connectivity.\nDialogue: 0,1:05:28.05,1:05:30.38,EN,,0,0,0,,And I'm going to tell you there's four things:\nDialogue: 0,1:05:30.40,1:05:33.74,EN,,0,0,0,,a and b and c and d.\nDialogue: 0,1:05:35.48,1:05:38.19,EN,,0,0,0,,And I'll tell you a is connected to b\nDialogue: 0,1:05:38.64,1:05:41.42,EN,,0,0,0,,and c's connected to d.\nDialogue: 0,1:05:43.20,1:05:44.80,EN,,0,0,0,,And now I'll tell you is a connected to d?\nDialogue: 0,1:05:45.05,1:05:46.03,EN,,0,0,0,,That's the question.\nDialogue: 0,1:05:46.78,1:05:48.52,EN,,0,0,0,,There's an example where I would like\nDialogue: 0,1:05:48.70,1:05:50.35,EN,,0,0,0,,something like the closed world assumption.\nDialogue: 0,1:05:54.43,1:05:55.66,EN,,0,0,0,,That's a tiny toy,\nDialogue: 0,1:05:56.24,1:05:58.30,EN,,0,0,0,,but a lot of times, I want to be able to say something like\nDialogue: 0,1:05:58.48,1:06:01.34,EN,,0,0,0,,anything that I haven't told you, assume is not true.\nDialogue: 0,1:06:04.26,1:06:06.27,EN,,0,0,0,,So it's not as simple as you only want to put in\nDialogue: 0,1:06:06.27,1:06:08.09,EN,,0,0,0,,explicit NOTs all over the place.\nDialogue: 0,1:06:09.47,1:06:12.70,EN,,0,0,0,,It's that sometimes it really isn't clear what you even want.\nDialogue: 0,1:06:14.15,1:06:17.92,EN,,0,0,0,,That having to specify both everything and not everything is too precise,\nDialogue: 0,1:06:17.93,1:06:20.00,EN,,0,0,0,,and then you get down into problems there.\nDialogue: 0,1:06:20.96,1:06:22.68,EN,,0,0,0,,But there are a lot of approaches that\nDialogue: 0,1:06:23.32,1:06:25.93,EN,,0,0,0,,you know, that explicitly put in NOTs and reason based on that.\nDialogue: 0,1:06:26.51,1:06:27.66,EN,,0,0,0,,So it's a very good idea.\nDialogue: 0,1:06:28.07,1:06:31.45,EN,,0,0,0,,It's just that then it starts becoming a little cumbersome\nDialogue: 0,1:06:31.48,1:06:33.49,EN,,0,0,0,,in the very large problems you'd like to use.\nDialogue: 0,1:06:43.46,1:06:45.96,EN,,0,0,0,,AUDIENCE: I'm not sure how directly related to the argument this is,\nDialogue: 0,1:06:46.00,1:06:47.98,EN,,0,0,0,,but one of your points was that\nDialogue: 0,1:06:48.49,1:06:50.16,EN,,0,0,0,,one of the dangers of the closed world rule is\nDialogue: 0,1:06:50.19,1:06:52.06,EN,,0,0,0,,you never really know all the things that are there.\nDialogue: 0,1:06:53.44,1:06:55.32,EN,,0,0,0,,You never really know all the parts to it.\nDialogue: 0,1:06:55.87,1:06:58.16,EN,,0,0,0,,Isn't that a major problem with any programming?\nDialogue: 0,1:06:58.16,1:06:59.64,EN,,0,0,0,,I always write programs where I\nDialogue: 0,1:06:59.90,1:07:01.56,EN,,0,0,0,,I assume that I've got all the cases,\nDialogue: 0,1:07:01.58,1:07:03.40,EN,,0,0,0,,and so I check for them all or whatever, and i\nDialogue: 0,1:07:04.06,1:07:04.99,EN,,0,0,0,,and somewhere down the road, I\nDialogue: 0,1:07:05.02,1:07:06.52,EN,,0,0,0,,I find out that I didn't check for one of them.\nDialogue: 0,1:07:07.39,1:07:08.54,EN,,0,0,0,,PROFESSOR: Well, sure, it's true.\nDialogue: 0,1:07:08.54,1:07:09.76,EN,,0,0,0,,But the problem here is\nDialogue: 0,1:07:11.96,1:07:15.47,EN,,0,0,0,,it's that assumption which is the thing that you're making\nDialogue: 0,1:07:15.48,1:07:17.34,EN,,0,0,0,,if you believe you're identifying this with logic.\nDialogue: 0,1:07:19.60,1:07:20.51,EN,,0,0,0,,So you're quite right.\nDialogue: 0,1:07:20.51,1:07:22.22,EN,,0,0,0,,It's a situation you're never in.\nDialogue: 0,1:07:22.22,1:07:24.14,EN,,0,0,0,,The problem is if you're starting to believe that\nDialogue: 0,1:07:24.17,1:07:25.44,EN,,0,0,0,,what this is doing is logic\nDialogue: 0,1:07:26.17,1:07:27.32,EN,,0,0,0,,and you look at the rules you write down\nDialogue: 0,1:07:27.34,1:07:28.89,EN,,0,0,0,,and say what can I deduce from them,\nDialogue: 0,1:07:29.53,1:07:32.80,EN,,0,0,0,,you have to be very careful to remember that NOT means something else.\nDialogue: 0,1:07:33.47,1:07:35.21,EN,,0,0,0,,And it means something else based on an assumption\nDialogue: 0,1:07:35.24,1:07:36.70,EN,,0,0,0,,which is probably not true.\nDialogue: 0,1:07:39.03,1:07:40.19,EN,,0,0,0,,AUDIENCE: Do I understand you correctly that\nDialogue: 0,1:07:40.25,1:07:41.84,EN,,0,0,0,,you cannot fix this problem\nDialogue: 0,1:07:42.25,1:07:46.08,EN,,0,0,0,,without killing off all possibilities of inference through altering NOT?\nDialogue: 0,1:07:46.54,1:07:49.80,EN,,0,0,0,,PROFESSOR: No, that's not quite right.\nDialogue: 0,1:07:52.96,1:07:55.08,EN,,0,0,0,,There are ways to do logic with real NOTs.\nDialogue: 0,1:07:56.34,1:07:58.03,EN,,0,0,0,,There are actually ways to do that.\nDialogue: 0,1:07:58.54,1:08:00.84,EN,,0,0,0,,But they're very inefficient as far as anybody knows.\nDialogue: 0,1:08:01.61,1:08:02.56,EN,,0,0,0,,And they're much more--\nDialogue: 0,1:08:04.09,1:08:06.89,EN,,0,0,0,,they don't--  the, quote, inference in here\nDialogue: 0,1:08:07.39,1:08:08.83,EN,,0,0,0,,is built into this unifier\nDialogue: 0,1:08:08.91,1:08:11.29,EN,,0,0,0,,and this pattern matching unification algorithm.\nDialogue: 0,1:08:11.98,1:08:16.19,EN,,0,0,0,,There are ways to automate real logical reasoning.\nDialogue: 0,1:08:16.59,1:08:18.19,EN,,0,0,0,,But it's not based on that,\nDialogue: 0,1:08:18.51,1:08:20.73,EN,,0,0,0,,and logic programming languages don't tend to do that\nDialogue: 0,1:08:20.75,1:08:23.85,EN,,0,0,0,,because it's very inefficient as far as anybody knows.\nDialogue: 0,1:08:29.39,1:08:30.03,EN,,0,0,0,,All right, thank you.\n"
  },
  {
    "path": "Ass/lec9a.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 2346\nActive Line: 2352\nVideo Position: 109459\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:12.03,0:00:14.03,EN,,0,0,0,,Register Machines\nDialogue: 0,0:00:17.26,0:00:19.07,EN,,0,0,0,,PROFESSOR: Well, up 'til now, I suppose,\nDialogue: 0,0:00:19.32,0:00:23.93,EN,,0,0,0,,we've been learning about a lot of techniques for\nDialogue: 0,0:00:24.09,0:00:28.83,EN,,0,0,0,,organizing big programs, symbolic manipulation a bit,\nDialogue: 0,0:00:30.84,0:00:35.60,EN,,0,0,0,,some of the technology that you use for establishing languages,\nDialogue: 0,0:00:35.63,0:00:36.78,EN,,0,0,0,,one in terms of another,\nDialogue: 0,0:00:37.10,0:00:39.92,EN,,0,0,0,,which is used for organizing very large programs.\nDialogue: 0,0:00:39.96,0:00:42.30,EN,,0,0,0,,In fact, the nicest programs I know\nDialogue: 0,0:00:42.44,0:00:44.43,EN,,0,0,0,,look more like a pile of languages\nDialogue: 0,0:00:44.91,0:00:47.96,EN,,0,0,0,,than like a decomposition of a problem into parts.\nDialogue: 0,0:00:49.90,0:00:51.45,EN,,0,0,0,,Well, I suppose at this point,\nDialogue: 0,0:00:52.08,0:00:53.58,EN,,0,0,0,,there are still, however, a few mysteries\nDialogue: 0,0:00:53.61,0:00:55.32,EN,,0,0,0,,about how this sort of stuff works.\nDialogue: 0,0:00:56.26,0:00:59.68,EN,,0,0,0,,And so what we'd like to do now is\nDialogue: 0,0:01:00.03,0:01:02.60,EN,,0,0,0,,diverge from the plan of\nDialogue: 0,0:01:02.96,0:01:05.42,EN,,0,0,0,,telling you how to organize big programs,\nDialogue: 0,0:01:05.45,0:01:08.19,EN,,0,0,0,,and rather tell you something about the mechanisms\nDialogue: 0,0:01:08.52,0:01:11.71,EN,,0,0,0,,by which these things can be made to work.\nDialogue: 0,0:01:12.19,0:01:14.83,EN,,0,0,0,,The main reason for this is\nDialogue: 0,0:01:15.80,0:01:17.87,EN,,0,0,0,,demystification, if you will,\nDialogue: 0,0:01:18.65,0:01:20.54,EN,,0,0,0,,that we have a lot of mysteries left,\nDialogue: 0,0:01:21.08,0:01:25.48,EN,,0,0,0,,like exactly how it is the case that a program is controlled,\nDialogue: 0,0:01:26.08,0:01:30.38,EN,,0,0,0,,how a computer knows what the next thing to do is,\nDialogue: 0,0:01:30.52,0:01:31.74,EN,,0,0,0,,or something like that.\nDialogue: 0,0:01:32.43,0:01:35.56,EN,,0,0,0,,And what I'd like to do now is make that clear to you\nDialogue: 0,0:01:35.85,0:01:39.10,EN,,0,0,0,,that even if you've never played with a physical computer before,\nDialogue: 0,0:01:39.56,0:01:43.50,EN,,0,0,0,,the mechanism is really very simple,\nDialogue: 0,0:01:44.33,0:01:46.35,EN,,0,0,0,,and that you can understand it completely with no trouble.\nDialogue: 0,0:01:47.65,0:01:51.24,EN,,0,0,0,,So I'd like to start by imagining that we--\nDialogue: 0,0:01:51.32,0:01:52.91,EN,,0,0,0,,well, the way we're going to do this, by the way,\nDialogue: 0,0:01:52.96,0:01:55.80,EN,,0,0,0,,is we're going to take some very simple Lisp programs,\nDialogue: 0,0:01:56.54,0:01:58.12,EN,,0,0,0,,very simple Lisp programs,\nDialogue: 0,0:01:59.04,0:02:00.62,EN,,0,0,0,,and transform them into hardware.\nDialogue: 0,0:02:02.16,0:02:04.16,EN,,0,0,0,,I'm not going to worry about some intermediate step\nDialogue: 0,0:02:04.70,0:02:07.45,EN,,0,0,0,,of going through some existing computer machine language\nDialogue: 0,0:02:07.47,0:02:09.05,EN,,0,0,0,,and then showing you how that computer works,\nDialogue: 0,0:02:09.82,0:02:12.00,EN,,0,0,0,,because that's not as illuminating.\nDialogue: 0,0:02:12.75,0:02:14.17,EN,,0,0,0,,So what I'm really going to show you\nDialogue: 0,0:02:14.51,0:02:17.48,EN,,0,0,0,,is how a piece of machinery can be built\nDialogue: 0,0:02:18.03,0:02:22.04,EN,,0,0,0,,to do a job that you have written down as a program.\nDialogue: 0,0:02:22.04,0:02:24.03,EN,,0,0,0,,That program is, in fact, a description of a machine.\nDialogue: 0,0:02:25.76,0:02:27.69,EN,,0,0,0,,We're going to start with a very simple program,\nDialogue: 0,0:02:28.09,0:02:30.81,EN,,0,0,0,,proceed to show you some simple mechanisms,\nDialogue: 0,0:02:31.39,0:02:33.68,EN,,0,0,0,,proceed to a few more complicated programs,\nDialogue: 0,0:02:34.30,0:02:37.42,EN,,0,0,0,,and then later show you a not very complicated program,\nDialogue: 0,0:02:37.44,0:02:41.23,EN,,0,0,0,,how the evaluator transforms into a piece of hardware.\nDialogue: 0,0:02:41.23,0:02:42.06,EN,,0,0,0,,And of course at that point,\nDialogue: 0,0:02:42.08,0:02:44.08,EN,,0,0,0,,you have made the universal transition\nDialogue: 0,0:02:44.22,0:02:46.88,EN,,0,0,0,,and can execute any program imaginable\nDialogue: 0,0:02:47.16,0:02:48.80,EN,,0,0,0,,with a piece of well-defined hardware.\nDialogue: 0,0:02:51.72,0:02:52.91,EN,,0,0,0,,Well, let's start up now,\nDialogue: 0,0:02:53.05,0:02:55.31,EN,,0,0,0,,give you a real concrete feeling for this sort of thing.\nDialogue: 0,0:02:55.44,0:02:57.66,EN,,0,0,0,,Let's start with a very simple program.\nDialogue: 0,0:02:59.60,0:03:00.85,EN,,0,0,0,,Here's Euclid's algorithm.\nDialogue: 0,0:03:03.88,0:03:07.00,EN,,0,0,0,,It's actually a little bit more modern than Euclid's algorithm.\nDialogue: 0,0:03:07.02,0:03:10.09,EN,,0,0,0,,Euclid's algorithm for computing the greatest common divisor of two numbers\nDialogue: 0,0:03:10.41,0:03:13.60,EN,,0,0,0,,was invented 350 BC, I think.\nDialogue: 0,0:03:14.30,0:03:15.69,EN,,0,0,0,,It's the oldest known algorithm.\nDialogue: 0,0:03:19.32,0:03:23.34,EN,,0,0,0,,But here we're going to talk about GCD of A and B,\nDialogue: 0,0:03:23.36,0:03:25.61,EN,,0,0,0,,the Greatest Common Divisor or two numbers, A and B.\nDialogue: 0,0:03:26.20,0:03:28.91,EN,,0,0,0,,And the algorithm is extremely simple.\nDialogue: 0,0:03:29.50,0:03:31.08,EN,,0,0,0,,If B is 0,\nDialogue: 0,0:03:34.16,0:03:36.83,EN,,0,0,0,,then the result is going to be A.\nDialogue: 0,0:03:37.52,0:03:43.61,EN,,0,0,0,,Otherwise, the result is the GCD of B\nDialogue: 0,0:03:44.49,0:03:53.39,EN,,0,0,0,,and the remainder when A is divided by B.\nDialogue: 0,0:03:58.53,0:04:01.90,EN,,0,0,0,,So this we have here is a very simple iterative process.\nDialogue: 0,0:04:02.03,0:04:04.08,EN,,0,0,0,,This a simple recursive procedure,\nDialogue: 0,0:04:04.38,0:04:07.53,EN,,0,0,0,,recursively defined procedure, recursive definition,\nDialogue: 0,0:04:07.71,0:04:09.26,EN,,0,0,0,,which yields an iterative process.\nDialogue: 0,0:04:09.95,0:04:12.46,EN,,0,0,0,,And the way it works is that every step,\nDialogue: 0,0:04:12.80,0:04:15.10,EN,,0,0,0,,it determines whether B was zero.\nDialogue: 0,0:04:16.24,0:04:18.80,EN,,0,0,0,,And if B is 0, we got the answer in A.\nDialogue: 0,0:04:19.63,0:04:22.46,EN,,0,0,0,,Otherwise, we make another step\nDialogue: 0,0:04:22.49,0:04:23.87,EN,,0,0,0,,where A is the old B,\nDialogue: 0,0:04:23.88,0:04:27.04,EN,,0,0,0,,and B is the remainder of the old A divided by the old B.\nDialogue: 0,0:04:28.76,0:04:29.55,EN,,0,0,0,,Very simple.\nDialogue: 0,0:04:31.11,0:04:32.72,EN,,0,0,0,,Now this, I've already told you\nDialogue: 0,0:04:32.99,0:04:34.86,EN,,0,0,0,,some of the mechanism by just saying it that way.\nDialogue: 0,0:04:34.86,0:04:35.90,EN,,0,0,0,,I said it in time.\nDialogue: 0,0:04:36.36,0:04:37.72,EN,,0,0,0,,I said there are certain steps,\nDialogue: 0,0:04:38.14,0:04:39.32,EN,,0,0,0,,and that, in fact,\nDialogue: 0,0:04:39.52,0:04:40.86,EN,,0,0,0,,one of the things you can see here\nDialogue: 0,0:04:41.18,0:04:43.69,EN,,0,0,0,,is that one of the reasons why this is iterative\nDialogue: 0,0:04:43.95,0:04:47.68,EN,,0,0,0,,is nothing is needed of the last step to get the answer.\nDialogue: 0,0:04:49.44,0:04:55.29,EN,,0,0,0,,All of the information that's needed to run this algorithm is in A and B.\nDialogue: 0,0:04:55.74,0:04:57.80,EN,,0,0,0,,It has two well-defined state variables.\nDialogue: 0,0:05:00.47,0:05:02.33,EN,,0,0,0,,So I'm going to define a machine for you\nDialogue: 0,0:05:03.98,0:05:05.55,EN,,0,0,0,,can compute you GCDs.\nDialogue: 0,0:05:06.56,0:05:07.12,EN,,0,0,0,,Now let's see.\nDialogue: 0,0:05:07.12,0:05:11.28,EN,,0,0,0,,Every computer that's ever been made that's a single-process computer,\nDialogue: 0,0:05:11.80,0:05:14.08,EN,,0,0,0,,as opposed to a multiprocessor of some sort,\nDialogue: 0,0:05:15.04,0:05:16.59,EN,,0,0,0,,is made according to the same plan.\nDialogue: 0,0:05:17.84,0:05:19.53,EN,,0,0,0,,The plan is the computer has two parts,\nDialogue: 0,0:05:20.57,0:05:22.35,EN,,0,0,0,,a part called the datapaths,\nDialogue: 0,0:05:23.10,0:05:24.36,EN,,0,0,0,,and a part called the controller.\nDialogue: 0,0:05:25.91,0:05:29.28,EN,,0,0,0,,The datapaths correspond to a calculator that you might have.\nDialogue: 0,0:05:29.71,0:05:31.87,EN,,0,0,0,,It contains certain registers that remember things,\nDialogue: 0,0:05:31.90,0:05:33.13,EN,,0,0,0,,and you've all used calculators.\nDialogue: 0,0:05:33.56,0:05:35.34,EN,,0,0,0,,It has some buttons on it and some lights.\nDialogue: 0,0:05:37.03,0:05:38.49,EN,,0,0,0,,And so by pushing the various buttons,\nDialogue: 0,0:05:38.52,0:05:41.34,EN,,0,0,0,,you can cause operations to happen inside there among the registers,\nDialogue: 0,0:05:41.87,0:05:43.48,EN,,0,0,0,,and some of the results to be displayed.\nDialogue: 0,0:05:45.16,0:05:46.25,EN,,0,0,0,,That's completely mechanical.\nDialogue: 0,0:05:46.25,0:05:49.55,EN,,0,0,0,,You could imagine that box has no intelligence in it.\nDialogue: 0,0:05:50.90,0:05:53.28,EN,,0,0,0,,Now it might be very impressive that it can produce the sine of a number,\nDialogue: 0,0:05:53.53,0:05:58.97,EN,,0,0,0,,but that at least is apparently possibly mechanical.\nDialogue: 0,0:05:58.97,0:06:01.71,EN,,0,0,0,,At least, I could open that up in the same way I'm about to open GCD.\nDialogue: 0,0:06:02.69,0:06:04.36,EN,,0,0,0,,So this may have a whole computer inside of it,\nDialogue: 0,0:06:04.68,0:06:05.69,EN,,0,0,0,,but that's not interesting.\nDialogue: 0,0:06:05.94,0:06:07.10,EN,,0,0,0,,Addition is certainly simple.\nDialogue: 0,0:06:08.20,0:06:09.84,EN,,0,0,0,,That can be done without any further mechanism.\nDialogue: 0,0:06:10.89,0:06:15.64,EN,,0,0,0,,Now also, if we were to look at the other half, the controller,\nDialogue: 0,0:06:15.93,0:06:17.39,EN,,0,0,0,,that's a part that's dumb, too.\nDialogue: 0,0:06:18.19,0:06:19.16,EN,,0,0,0,,It pushes the buttons.\nDialogue: 0,0:06:20.35,0:06:21.52,EN,,0,0,0,,It pushes them according to the sequence,\nDialogue: 0,0:06:21.55,0:06:22.84,EN,,0,0,0,,which is written down on a piece of paper,\nDialogue: 0,0:06:24.27,0:06:25.64,EN,,0,0,0,,and observes the lights.\nDialogue: 0,0:06:26.29,0:06:29.44,EN,,0,0,0,,And every so often, it comes to a place in a sequence that says,\nDialogue: 0,0:06:29.47,0:06:32.37,EN,,0,0,0,,if light A is on, do this sequence.\nDialogue: 0,0:06:32.37,0:06:33.85,EN,,0,0,0,,Otherwise, do that sequence.\nDialogue: 0,0:06:34.62,0:06:37.45,EN,,0,0,0,,And thereby, there's no complexity there either.\nDialogue: 0,0:06:38.35,0:06:39.32,EN,,0,0,0,,Well, let's just draw that\nDialogue: 0,0:06:39.34,0:06:40.57,EN,,0,0,0,,and see what we feel about that.\nDialogue: 0,0:06:42.51,0:06:44.84,EN,,0,0,0,,So for computing GCDs,\nDialogue: 0,0:06:45.88,0:06:49.52,EN,,0,0,0,,what I want you to think about is that there are these registers.\nDialogue: 0,0:06:50.56,0:06:53.02,EN,,0,0,0,,A register is a place where I store a number, in this case.\nDialogue: 0,0:06:53.52,0:06:54.65,EN,,0,0,0,,And this one's called a.\nDialogue: 0,0:06:56.81,0:06:58.70,EN,,0,0,0,,And then there's another one for storing b.\nDialogue: 0,0:07:03.17,0:07:05.45,EN,,0,0,0,,Now we have to see what things we can do with these registers,\nDialogue: 0,0:07:05.98,0:07:08.73,EN,,0,0,0,,and they're not entirely obvious what you can do with them.\nDialogue: 0,0:07:09.84,0:07:11.72,EN,,0,0,0,,Well, we have to see what things we need to do with them.\nDialogue: 0,0:07:11.82,0:07:13.87,EN,,0,0,0,,We're looking at the problem we're trying to solve.\nDialogue: 0,0:07:14.03,0:07:16.09,EN,,0,0,0,,One of the important things for designing a computer,\nDialogue: 0,0:07:17.10,0:07:19.58,EN,,0,0,0,,which I think most designers don't do,\nDialogue: 0,0:07:20.20,0:07:21.88,EN,,0,0,0,,is you stay the problem you want to solve\nDialogue: 0,0:07:22.62,0:07:25.18,EN,,0,0,0,,and then use what you learn from studying the problem you want to solve\nDialogue: 0,0:07:25.44,0:07:27.28,EN,,0,0,0,,to put in the mechanisms needed to solve it\nDialogue: 0,0:07:27.53,0:07:28.70,EN,,0,0,0,,in the computer you're building,\nDialogue: 0,0:07:28.81,0:07:30.08,EN,,0,0,0,,no more no less.\nDialogue: 0,0:07:32.14,0:07:33.96,EN,,0,0,0,,Now it may be that the problem you're trying to solve\nDialogue: 0,0:07:34.24,0:07:35.40,EN,,0,0,0,,is everybody's problem,\nDialogue: 0,0:07:36.06,0:07:37.58,EN,,0,0,0,,in which case you have to build in a universal\nDialogue: 0,0:07:37.60,0:07:39.29,EN,,0,0,0,,interpreter of some language.\nDialogue: 0,0:07:40.19,0:07:42.32,EN,,0,0,0,,But you shouldn't put any more in than required\nDialogue: 0,0:07:42.35,0:07:44.25,EN,,0,0,0,,to build the universal interpreter of some language.\nDialogue: 0,0:07:44.44,0:07:45.85,EN,,0,0,0,,We'll worry about that in a second.\nDialogue: 0,0:07:47.23,0:07:49.93,EN,,0,0,0,,OK, going back to here, let's see.\nDialogue: 0,0:07:49.93,0:07:51.24,EN,,0,0,0,,What do we have to be able to do?\nDialogue: 0,0:07:51.79,0:07:54.14,EN,,0,0,0,,Well, somehow, we have to be able to get B into A.\nDialogue: 0,0:07:56.08,0:07:59.60,EN,,0,0,0,,We have to be able to get the old value of B into the value of A.\nDialogue: 0,0:08:00.38,0:08:03.32,EN,,0,0,0,,So we have to have some path by which stuff can flow\nDialogue: 0,0:08:03.34,0:08:04.76,EN,,0,0,0,,whatever this information is,\nDialogue: 0,0:08:05.37,0:08:06.57,EN,,0,0,0,,OK? from b to a.\nDialogue: 0,0:08:07.39,0:08:09.26,EN,,0,0,0,,I'm going to draw that with by an arrow\nDialogue: 0,0:08:09.52,0:08:12.62,EN,,0,0,0,,saying that it is possible to move the contents of b into a,\nDialogue: 0,0:08:12.96,0:08:14.57,EN,,0,0,0,,replacing the value of a.\nDialogue: 0,0:08:15.12,0:08:16.73,EN,,0,0,0,,And there's a little button here which you push\nDialogue: 0,0:08:17.48,0:08:18.56,EN,,0,0,0,,which allows that to happen.\nDialogue: 0,0:08:19.71,0:08:20.78,EN,,0,0,0,,That's what the little x is here.\nDialogue: 0,0:08:23.07,0:08:23.93,EN,,0,0,0,,Now it's also the case\nDialogue: 0,0:08:23.95,0:08:26.28,EN,,0,0,0,,that I have to be able to compute the remainder of a and b.\nDialogue: 0,0:08:27.00,0:08:28.49,EN,,0,0,0,,Now that may be a complicated mess.\nDialogue: 0,0:08:28.86,0:08:30.86,EN,,0,0,0,,On the other hand, I'm going to make it a small box.\nDialogue: 0,0:08:31.96,0:08:33.92,EN,,0,0,0,,If we have to, we may open up that box\nDialogue: 0,0:08:34.12,0:08:35.63,EN,,0,0,0,,and look inside and see what it is.\nDialogue: 0,0:08:37.77,0:08:39.16,EN,,0,0,0,,So here, I'm going to have a little box,\nDialogue: 0,0:08:39.20,0:08:40.38,EN,,0,0,0,,which I'm going to draw this way,\nDialogue: 0,0:08:43.16,0:08:44.38,EN,,0,0,0,,which we'll call the remainder.\nDialogue: 0,0:08:46.44,0:08:48.60,EN,,0,0,0,,And it's going to take in a.\nDialogue: 0,0:08:50.91,0:08:52.16,EN,,0,0,0,,That's going to take in b.\nDialogue: 0,0:08:54.37,0:08:56.51,EN,,0,0,0,,And it's going to put out something,\nDialogue: 0,0:08:58.89,0:09:00.46,EN,,0,0,0,,the remainder of a divided by b.\nDialogue: 0,0:09:02.29,0:09:03.61,EN,,0,0,0,,Another thing we have to see here is\nDialogue: 0,0:09:03.64,0:09:06.06,EN,,0,0,0,,that we have to be able to test whether b is equal to 0.\nDialogue: 0,0:09:08.00,0:09:09.66,EN,,0,0,0,,Well, that means somebody's got to be looking at--\nDialogue: 0,0:09:10.00,0:09:12.30,EN,,0,0,0,,a thing that's looking at the value of b.\nDialogue: 0,0:09:13.39,0:09:14.40,EN,,0,0,0,,I have a light bulb here\nDialogue: 0,0:09:15.85,0:09:17.39,EN,,0,0,0,,which lights up if b equals 0.\nDialogue: 0,0:09:21.11,0:09:22.01,EN,,0,0,0,,That's its job.\nDialogue: 0,0:09:24.03,0:09:26.78,EN,,0,0,0,,And finally, I suppose, because of the fact\nDialogue: 0,0:09:26.96,0:09:30.43,EN,,0,0,0,,that we want the new value of a to be the old value of b,\nDialogue: 0,0:09:30.46,0:09:34.41,EN,,0,0,0,,and simultaneously the new value of b to be something I've done with a,\nDialogue: 0,0:09:35.28,0:09:37.60,EN,,0,0,0,,and if I plan to make my machine\nDialogue: 0,0:09:37.80,0:09:39.74,EN,,0,0,0,,such that everything happens one at a time,\nDialogue: 0,0:09:40.20,0:09:41.40,EN,,0,0,0,,one motion at a time,\nDialogue: 0,0:09:41.61,0:09:43.42,EN,,0,0,0,,and I can't put two numbers in a register,\nDialogue: 0,0:09:44.03,0:09:46.30,EN,,0,0,0,,then I have to have another place to put one while I'm interchanging.\nDialogue: 0,0:09:49.29,0:09:49.60,EN,,0,0,0,,OK?\nDialogue: 0,0:09:50.00,0:09:51.85,EN,,0,0,0,,I can't interchange the two things in my hands,\nDialogue: 0,0:09:52.11,0:09:53.72,EN,,0,0,0,,unless I either put two in one hand\nDialogue: 0,0:09:53.72,0:09:55.13,EN,,0,0,0,,and then pull it back the other way,\nDialogue: 0,0:09:55.50,0:09:56.91,EN,,0,0,0,,or unless I put one down,\nDialogue: 0,0:09:57.02,0:09:58.68,EN,,0,0,0,,pick it up, and put the other one, like that\nDialogue: 0,0:09:59.64,0:10:00.94,EN,,0,0,0,,unless I'm a juggler,\nDialogue: 0,0:10:01.66,0:10:03.50,EN,,0,0,0,,which I'm not, as you can see,\nDialogue: 0,0:10:04.65,0:10:07.36,EN,,0,0,0,,in which case I have a possibility of timing errors.\nDialogue: 0,0:10:08.85,0:10:11.04,EN,,0,0,0,,In fact, much of the type of computer design\nDialogue: 0,0:10:11.07,0:10:12.68,EN,,0,0,0,,people do involves timing errors,\nDialogue: 0,0:10:13.12,0:10:15.00,EN,,0,0,0,,of some potential timing errors,\nDialogue: 0,0:10:15.24,0:10:16.43,EN,,0,0,0,,which I don't much like.\nDialogue: 0,0:10:17.34,0:10:18.64,EN,,0,0,0,,But. So for that reason,\nDialogue: 0,0:10:18.68,0:10:21.21,EN,,0,0,0,,I have to have a place to put the third thing down\nDialogue: 0,0:10:22.06,0:10:23.29,EN,,0,0,0,,the second one of them down.\nDialogue: 0,0:10:23.41,0:10:24.72,EN,,0,0,0,,So I have a place called t,\nDialogue: 0,0:10:24.75,0:10:26.84,EN,,0,0,0,,which is a register just for temporary, t,\nDialogue: 0,0:10:28.59,0:10:29.63,EN,,0,0,0,,with a button on it.\nDialogue: 0,0:10:30.47,0:10:31.88,EN,,0,0,0,,And then I'll take the result of that,\nDialogue: 0,0:10:31.90,0:10:34.14,EN,,0,0,0,,since I have to take that and put into b, over here,\nDialogue: 0,0:10:34.68,0:10:36.73,EN,,0,0,0,,we'll take the result of that and go like this,\nDialogue: 0,0:10:38.41,0:10:39.30,EN,,0,0,0,,and a button here.\nDialogue: 0,0:10:42.43,0:10:45.84,EN,,0,0,0,,So that's the datapaths of a GCD machine.\nDialogue: 0,0:10:47.60,0:10:48.57,EN,,0,0,0,,Now what's the controller?\nDialogue: 0,0:10:49.74,0:10:51.28,EN,,0,0,0,,Controller's a very simple thing, too.\nDialogue: 0,0:10:52.28,0:10:53.26,EN,,0,0,0,,The machine has a state.\nDialogue: 0,0:10:54.38,0:10:57.72,EN,,0,0,0,,The way I like to visualize that is that I've got a maze.\nDialogue: 0,0:10:59.01,0:11:03.20,EN,,0,0,0,,And the maze has a bunch of places connected by directed arrows.\nDialogue: 0,0:11:04.43,0:11:05.60,EN,,0,0,0,,And what I have is a marble,\nDialogue: 0,0:11:06.46,0:11:09.07,EN,,0,0,0,,which represents the state of the controller.\nDialogue: 0,0:11:10.74,0:11:12.27,EN,,0,0,0,,The marble rolls around in the maze.\nDialogue: 0,0:11:13.74,0:11:17.15,EN,,0,0,0,,Of course, this analogy breaks down for energy reasons.\nDialogue: 0,0:11:17.15,0:11:19.08,EN,,0,0,0,,I sometimes have to pump the marble up to the top,\nDialogue: 0,0:11:19.12,0:11:21.85,EN,,0,0,0,,because it's going to otherwise be a perpetual motion machine.\nDialogue: 0,0:11:22.00,0:11:23.32,EN,,0,0,0,,But not worrying about that,\nDialogue: 0,0:11:23.90,0:11:25.90,EN,,0,0,0,,this is not a physical analogy.\nDialogue: 0,0:11:26.08,0:11:27.42,EN,,0,0,0,,This marble rolls around.\nDialogue: 0,0:11:27.68,0:11:29.56,EN,,0,0,0,,And every time it rolls around certain bumpers,\nDialogue: 0,0:11:29.68,0:11:30.97,EN,,0,0,0,,like in a pinball machine,\nDialogue: 0,0:11:31.26,0:11:32.60,EN,,0,0,0,,it pushes one of these buttons.\nDialogue: 0,0:11:34.83,0:11:37.50,EN,,0,0,0,,And every so often, it comes to a place, which is a division,\nDialogue: 0,0:11:38.62,0:11:39.68,EN,,0,0,0,,where it has to make a choice.\nDialogue: 0,0:11:40.25,0:11:42.36,EN,,0,0,0,,And there's a flap, which is controlled by this.\nDialogue: 0,0:11:46.00,0:11:48.82,EN,,0,0,0,,So that's a really mechanical way of thinking about it.\nDialogue: 0,0:11:48.82,0:11:51.05,EN,,0,0,0,,Of course, controllers not these days, are not built that way\nDialogue: 0,0:11:51.08,0:11:51.84,EN,,0,0,0,,in real computers.\nDialogue: 0,0:11:51.84,0:11:56.01,EN,,0,0,0,,They're built with a little bit of ROM and a state register.\nDialogue: 0,0:11:56.61,0:11:58.73,EN,,0,0,0,,But there was a time, like the DEC PDP-6,\nDialogue: 0,0:11:59.29,0:12:01.02,EN,,0,0,0,,where that's how you built the controller of a machine.\nDialogue: 0,0:12:01.80,0:12:03.61,EN,,0,0,0,,There was a bit that ran around the delay line,\nDialogue: 0,0:12:05.69,0:12:08.14,EN,,0,0,0,,and it triggered things as it went by.\nDialogue: 0,0:12:08.58,0:12:10.70,EN,,0,0,0,,And it would come back to the beginning and get fed round again.\nDialogue: 0,0:12:11.99,0:12:13.72,EN,,0,0,0,,And of course, there were all sorts of great bugs you could have\nDialogue: 0,0:12:13.74,0:12:17.67,EN,,0,0,0,,like two bits going around, two marbles.\nDialogue: 0,0:12:17.67,0:12:19.26,EN,,0,0,0,,And then the machine has lost its marbles.\nDialogue: 0,0:12:19.45,0:12:20.20,EN,,0,0,0,,That happens, too.\nDialogue: 0,0:12:20.98,0:12:21.58,EN,,0,0,0,,Oh, well.\nDialogue: 0,0:12:22.27,0:12:24.22,EN,,0,0,0,,So anyway, for this machine,\nDialogue: 0,0:12:24.27,0:12:25.48,EN,,0,0,0,,what I have to do is the following.\nDialogue: 0,0:12:25.80,0:12:27.74,EN,,0,0,0,,I'm going to start my maze here.\nDialogue: 0,0:12:30.52,0:12:32.73,EN,,0,0,0,,And the first thing I've got to do,\nDialogue: 0,0:12:33.76,0:12:36.75,EN,,0,0,0,,is in a notation which many of you are familiar with,\nDialogue: 0,0:12:37.07,0:12:39.85,EN,,0,0,0,,is b equal to zero, a test.\nDialogue: 0,0:12:41.50,0:12:43.79,EN,,0,0,0,,And there's a possibility, either yes,\nDialogue: 0,0:12:43.93,0:12:45.58,EN,,0,0,0,,in which case I'm done.\nDialogue: 0,0:12:49.79,0:12:51.26,EN,,0,0,0,,Otherwise, if no,\nDialogue: 0,0:12:52.70,0:12:54.32,EN,,0,0,0,,then I'm going have to roll over some bumpers.\nDialogue: 0,0:12:55.00,0:12:56.46,EN,,0,0,0,,I'm going to do it in the following order.\nDialogue: 0,0:12:57.42,0:13:03.40,EN,,0,0,0,,I want to, I want to do this interchange game.\nDialogue: 0,0:13:04.05,0:13:05.80,EN,,0,0,0,,Now first, since I need both a and b,\nDialogue: 0,0:13:06.32,0:13:08.57,EN,,0,0,0,,but then the first-- and this is not necessary--\nDialogue: 0,0:13:08.65,0:13:09.72,EN,,0,0,0,,I want to collect this.\nDialogue: 0,0:13:11.07,0:13:12.62,EN,,0,0,0,,This is the thing that's going to go into b.\nDialogue: 0,0:13:13.24,0:13:14.03,EN,,0,0,0,,So I'm going to say,\nDialogue: 0,0:13:14.28,0:13:16.27,EN,,0,0,0,,take this, which depends upon both a and b,\nDialogue: 0,0:13:16.36,0:13:18.67,EN,,0,0,0,,and put the remainder into here.\nDialogue: 0,0:13:19.15,0:13:20.33,EN,,0,0,0,,So I'm going to push this button first.\nDialogue: 0,0:13:21.53,0:13:24.43,EN,,0,0,0,,Then, I'm going to transfer b to a,\nDialogue: 0,0:13:24.44,0:13:25.60,EN,,0,0,0,,push that button,\nDialogue: 0,0:13:25.82,0:13:27.63,EN,,0,0,0,,and then I transfer the temporary into b,\nDialogue: 0,0:13:28.76,0:13:29.42,EN,,0,0,0,,push that button.\nDialogue: 0,0:13:32.03,0:13:34.97,EN,,0,0,0,,So a very sequential machine,\nDialogue: 0,0:13:35.39,0:13:36.52,EN,,0,0,0,,it's very inefficient.\nDialogue: 0,0:13:37.75,0:13:39.05,EN,,0,0,0,,But that's fine right now.\nDialogue: 0,0:13:39.81,0:13:40.97,EN,,0,0,0,,We're going to name the buttons,\nDialogue: 0,0:13:41.47,0:13:42.72,EN,,0,0,0,,t gets remainder.\nDialogue: 0,0:13:46.75,0:13:48.73,EN,,0,0,0,,a gets b.\nDialogue: 0,0:13:50.03,0:13:54.81,EN,,0,0,0,,And b gets t.\nDialogue: 0,0:13:55.47,0:13:57.63,EN,,0,0,0,,And then I'm going to go around here\nDialogue: 0,0:13:58.78,0:13:59.88,EN,,0,0,0,,and it's to go back to start.\nDialogue: 0,0:14:01.62,0:14:03.87,EN,,0,0,0,,And if you look, what are we seeing here?\nDialogue: 0,0:14:03.87,0:14:04.91,EN,,0,0,0,,We're seeing the various--\nDialogue: 0,0:14:05.05,0:14:07.16,EN,,0,0,0,,what I really have is some sort of mechanical connection,\nDialogue: 0,0:14:07.42,0:14:13.63,EN,,0,0,0,,where t gets r controls this thing.\nDialogue: 0,0:14:16.83,0:14:21.48,EN,,0,0,0,,And I have here that a gets b controls this fellow over here,\nDialogue: 0,0:14:26.96,0:14:28.12,EN,,0,0,0,,and this fellow over here.\nDialogue: 0,0:14:28.12,0:14:31.08,EN,,0,0,0,,Boy, that's absolutely pessimal,\nDialogue: 0,0:14:31.48,0:14:32.48,EN,,0,0,0,,the inverse of optimal.\nDialogue: 0,0:14:32.63,0:14:34.59,EN,,0,0,0,,Every line heads across every other line the way I drew it.\nDialogue: 0,0:14:38.54,0:14:41.15,EN,,0,0,0,,I suppose this goes here, b gets t.\nDialogue: 0,0:14:45.69,0:14:47.95,EN,,0,0,0,,Now I'd like to run this machine.\nDialogue: 0,0:14:48.04,0:14:49.34,EN,,0,0,0,,But before I run the machine,\nDialogue: 0,0:14:49.37,0:14:51.40,EN,,0,0,0,,I want to write down a description of this controller,\nDialogue: 0,0:14:51.63,0:14:52.81,EN,,0,0,0,,just so you can see that these things,\nDialogue: 0,0:14:52.84,0:14:55.63,EN,,0,0,0,,of course, as usual, can be written down in some nice language,\nDialogue: 0,0:14:56.08,0:14:58.08,EN,,0,0,0,,so that we don't have to always draw these diagrams.\nDialogue: 0,0:14:58.36,0:15:00.68,EN,,0,0,0,,One of the problems with diagrams is that they take up a lot of space.\nDialogue: 0,0:15:00.89,0:15:01.98,EN,,0,0,0,,And for a machine this small,\nDialogue: 0,0:15:02.00,0:15:03.05,EN,,0,0,0,,it takes two blackboards.\nDialogue: 0,0:15:03.22,0:15:05.24,EN,,0,0,0,,For a machine that's the evaluator machine,\nDialogue: 0,0:15:05.40,0:15:07.10,EN,,0,0,0,,I have trouble putting it into this room,\nDialogue: 0,0:15:07.95,0:15:09.16,EN,,0,0,0,,even though it isn't very big.\nDialogue: 0,0:15:09.90,0:15:11.28,EN,,0,0,0,,So I'm going to make a little language for this\nDialogue: 0,0:15:11.29,0:15:12.51,EN,,0,0,0,,that's just a description of that,\nDialogue: 0,0:15:13.10,0:15:23.29,EN,,0,0,0,,saying define a machine we'll call GCD.\nDialogue: 0,0:15:24.42,0:15:25.66,EN,,0,0,0,,Of course, once we have something like this,\nDialogue: 0,0:15:25.68,0:15:26.83,EN,,0,0,0,,we have a simulator for it.\nDialogue: 0,0:15:27.22,0:15:29.42,EN,,0,0,0,,And the reason why we want to build a language in this form,\nDialogue: 0,0:15:29.56,0:15:32.94,EN,,0,0,0,,is because all of a sudden we can manipulate these expressions that I'm writing down.\nDialogue: 0,0:15:33.21,0:15:34.91,EN,,0,0,0,,And then of course I can write things I can\nDialogue: 0,0:15:35.29,0:15:38.16,EN,,0,0,0,,algebraically manipulate these things, simulate them\nDialogue: 0,0:15:38.20,0:15:39.96,EN,,0,0,0,,all that sort of things that I might want to do,\nDialogue: 0,0:15:40.12,0:15:42.59,EN,,0,0,0,,perhaps transform them as a layout, who knows.\nDialogue: 0,0:15:43.63,0:15:48.38,EN,,0,0,0,,Once I have a nice representation of registers,\nDialogue: 0,0:15:48.51,0:15:49.61,EN,,0,0,0,,it has certain registers,\nDialogue: 0,0:15:53.00,0:15:55.64,EN,,0,0,0,,which we can call A, B, and T.\nDialogue: 0,0:15:56.75,0:15:57.80,EN,,0,0,0,,And there's a controller.\nDialogue: 0,0:16:02.19,0:16:04.46,EN,,0,0,0,,Actually, a better language, which would be more explicit,\nDialogue: 0,0:16:04.49,0:16:06.97,EN,,0,0,0,,would be one which named every button\nDialogue: 0,0:16:08.14,0:16:10.17,EN,,0,0,0,,also and said what it did.\nDialogue: 0,0:16:10.42,0:16:11.37,EN,,0,0,0,,Like, this button\nDialogue: 0,0:16:11.55,0:16:14.19,EN,,0,0,0,,causes the contents of T to go to the contents of B.\nDialogue: 0,0:16:15.10,0:16:16.09,EN,,0,0,0,,Well I don't want to do that,\nDialogue: 0,0:16:16.11,0:16:17.95,EN,,0,0,0,,because it's actually harder to read to do that,\nDialogue: 0,0:16:18.20,0:16:19.34,EN,,0,0,0,,and it takes up more space.\nDialogue: 0,0:16:19.51,0:16:22.36,EN,,0,0,0,,So I'm going to have that in the instructions written in the controller.\nDialogue: 0,0:16:23.29,0:16:25.24,EN,,0,0,0,,It's going to be implicit what the operations are.\nDialogue: 0,0:16:26.32,0:16:28.57,EN,,0,0,0,,They can be deduced by reading these\nDialogue: 0,0:16:29.16,0:16:31.39,EN,,0,0,0,,and collecting together all the different things that can be done.\nDialogue: 0,0:16:31.69,0:16:33.50,EN,,0,0,0,,We look and see, see...\nDialogue: 0,0:16:33.50,0:16:34.70,EN,,0,0,0,,Well, let's just look at what these things are.\nDialogue: 0,0:16:35.71,0:16:37.29,EN,,0,0,0,,There's a little loop that we go around\nDialogue: 0,0:16:38.24,0:16:40.20,EN,,0,0,0,,which says branch,\nDialogue: 0,0:16:42.64,0:16:46.46,EN,,0,0,0,,this is the representation of the little flap\nDialogue: 0,0:16:46.89,0:16:48.49,EN,,0,0,0,,that decides which way you go here,\nDialogue: 0,0:16:49.10,0:16:58.00,EN,,0,0,0,,if 0, OK, fetch of B, the contents of B,\nDialogue: 0,0:16:58.65,0:17:00.06,EN,,0,0,0,,and if the contents of B is 0,\nDialogue: 0,0:17:00.32,0:17:01.72,EN,,0,0,0,,then go to a place called done.\nDialogue: 0,0:17:03.64,0:17:05.29,EN,,0,0,0,,Now, one thing you're seeing here,\nDialogue: 0,0:17:05.29,0:17:07.40,EN,,0,0,0,,this looks very much like a traditional computer language.\nDialogue: 0,0:17:08.17,0:17:09.55,EN,,0,0,0,,And what you're seeing here\nDialogue: 0,0:17:10.03,0:17:12.00,EN,,0,0,0,,is things like labels\nDialogue: 0,0:17:12.99,0:17:16.86,EN,,0,0,0,,that represent places in a sequence written down as a sequence.\nDialogue: 0,0:17:17.60,0:17:18.94,EN,,0,0,0,,The reason why they're needed\nDialogue: 0,0:17:19.48,0:17:21.15,EN,,0,0,0,,is because over here,\nDialogue: 0,0:17:21.45,0:17:22.81,EN,,0,0,0,,I've written something with loops.\nDialogue: 0,0:17:23.32,0:17:26.11,EN,,0,0,0,,But if I'm writing English text, or something like that,\nDialogue: 0,0:17:26.44,0:17:28.09,EN,,0,0,0,,it's hard to refer to a place.\nDialogue: 0,0:17:28.58,0:17:29.53,EN,,0,0,0,,I don't have arrows.\nDialogue: 0,0:17:30.80,0:17:33.02,EN,,0,0,0,,Arrows are represented by giving names\nDialogue: 0,0:17:33.05,0:17:34.44,EN,,0,0,0,,to the places where the arrows terminate,\nDialogue: 0,0:17:34.57,0:17:36.28,EN,,0,0,0,,and then referring to them by those names.\nDialogue: 0,0:17:37.40,0:17:38.59,EN,,0,0,0,,Now this is just an encoding.\nDialogue: 0,0:17:39.86,0:17:41.88,EN,,0,0,0,,There's nothing magical about things like that.\nDialogue: 0,0:17:43.15,0:17:44.96,EN,,0,0,0,,Next thing we're going to do is we're going to say,\nDialogue: 0,0:17:45.02,0:17:46.84,EN,,0,0,0,,how do we do T gets R?\nDialogue: 0,0:17:47.45,0:17:49.76,EN,,0,0,0,,Oh, that's easy enough, assign.\nDialogue: 0,0:17:52.19,0:17:55.55,EN,,0,0,0,,We assign to T the remainder.\nDialogue: 0,0:17:56.32,0:17:59.24,EN,,0,0,0,,Assign is the name of the button.\nDialogue: 0,0:18:01.47,0:18:02.64,EN,,0,0,0,,That's the button-pusher.\nDialogue: 0,0:18:03.14,0:18:04.97,EN,,0,0,0,,Assign to T the remainder,\nDialogue: 0,0:18:04.99,0:18:06.76,EN,,0,0,0,,and here's the representation of the operation,\nDialogue: 0,0:18:11.74,0:18:17.53,EN,,0,0,0,,when we divide the fetch of A by the fetch of B.\nDialogue: 0,0:18:23.85,0:18:30.99,EN,,0,0,0,,And we're also going to assign to A the fetch of B,\nDialogue: 0,0:18:34.99,0:18:47.88,EN,,0,0,0,,assign to B the result of getting the contents of T.\nDialogue: 0,0:18:49.61,0:18:51.85,EN,,0,0,0,,And now I have to refer to the beginning here.\nDialogue: 0,0:18:53.18,0:18:55.92,EN,,0,0,0,,I see, why don't I call that loop like I have here?\nDialogue: 0,0:19:04.09,0:19:07.04,EN,,0,0,0,,OK? So that's that reference to that arrow.\nDialogue: 0,0:19:07.61,0:19:08.95,EN,,0,0,0,,And when we're done, we're done.\nDialogue: 0,0:19:09.02,0:19:13.07,EN,,0,0,0,,We go to here, which is the end of the thing.\nDialogue: 0,0:19:15.26,0:19:17.04,EN,,0,0,0,,So here's just a written representation\nDialogue: 0,0:19:17.69,0:19:20.86,EN,,0,0,0,,of this fragment of machinery that we've drawn here.\nDialogue: 0,0:19:21.66,0:19:24.84,EN,,0,0,0,,Now the next thing I'd like to do is run this.\nDialogue: 0,0:19:25.49,0:19:26.65,EN,,0,0,0,,I want us to feel it running.\nDialogue: 0,0:19:27.62,0:19:29.80,EN,,0,0,0,,Never done this before, you got to do it once.\nDialogue: 0,0:19:31.01,0:19:32.62,EN,,0,0,0,,So let's take a particular problem.\nDialogue: 0,0:19:33.10,0:19:34.70,EN,,0,0,0,,Suppose we want to compute the GCD\nDialogue: 0,0:19:35.04,0:19:40.68,EN,,0,0,0,,of a equals 30 and b equals 42.\nDialogue: 0,0:19:42.21,0:19:44.92,EN,,0,0,0,,I have no idea what that is right now.\nDialogue: 0,0:19:45.86,0:19:47.60,EN,,0,0,0,,But a 30 and b is 42.\nDialogue: 0,0:19:50.96,0:19:52.09,EN,,0,0,0,,So that's how I start this thing up.\nDialogue: 0,0:19:52.60,0:19:53.90,EN,,0,0,0,,Well, what's the first thing I do?\nDialogue: 0,0:19:54.24,0:19:56.86,EN,,0,0,0,,I say is B equal to 0, no.\nDialogue: 0,0:19:57.59,0:20:02.11,EN,,0,0,0,,Then assign to T the remainder of the fetch of A and the fetch of B.\nDialogue: 0,0:20:02.80,0:20:07.60,EN,,0,0,0,,Well the remainder of 30 when divided by 42 is itself 30.\nDialogue: 0,0:20:11.13,0:20:12.03,EN,,0,0,0,,Push that button.\nDialogue: 0,0:20:12.92,0:20:15.10,EN,,0,0,0,,Now the marble has rolled to here.\nDialogue: 0,0:20:17.10,0:20:18.06,EN,,0,0,0,,A gets B.\nDialogue: 0,0:20:19.02,0:20:20.76,EN,,0,0,0,,That pushes this button.\nDialogue: 0,0:20:21.22,0:20:22.54,EN,,0,0,0,,So 42 moves into here.\nDialogue: 0,0:20:26.59,0:20:27.60,EN,,0,0,0,,B gets T.\nDialogue: 0,0:20:28.36,0:20:29.34,EN,,0,0,0,,Push that button.\nDialogue: 0,0:20:29.87,0:20:30.96,EN,,0,0,0,,The 30 goes here.\nDialogue: 0,0:20:32.57,0:20:33.69,EN,,0,0,0,,Let met just interchange them.\nDialogue: 0,0:20:34.66,0:20:38.27,EN,,0,0,0,,Now let's see, go back to the beginning.\nDialogue: 0,0:20:38.64,0:20:39.72,EN,,0,0,0,,B 0, no.\nDialogue: 0,0:20:40.19,0:20:41.50,EN,,0,0,0,,T gets the remainder.\nDialogue: 0,0:20:43.23,0:20:46.30,EN,,0,0,0,,I suppose the remainder when dividing 42 by 30 is 12.\nDialogue: 0,0:20:47.24,0:20:48.30,EN,,0,0,0,,I push that one.\nDialogue: 0,0:20:48.53,0:20:51.40,EN,,0,0,0,,Next thing I do is allow the 30 to go to here,\nDialogue: 0,0:20:53.90,0:20:55.95,EN,,0,0,0,,push this one, allow the 12 to go to here.\nDialogue: 0,0:20:58.41,0:21:00.38,EN,,0,0,0,,OK? Go around this thing.\nDialogue: 0,0:21:00.38,0:21:01.31,EN,,0,0,0,,Is that done?\nDialogue: 0,0:21:01.53,0:21:02.12,EN,,0,0,0,,No.\nDialogue: 0,0:21:02.36,0:21:08.22,EN,,0,0,0,,How about-- so now I have to find out the remainder of 30 divided by 12.\nDialogue: 0,0:21:08.85,0:21:10.67,EN,,0,0,0,,And I believe that's 6.\nDialogue: 0,0:21:12.42,0:21:15.13,EN,,0,0,0,,So 6 goes here on this button push.\nDialogue: 0,0:21:16.20,0:21:18.25,EN,,0,0,0,,Then the next thing I push is this one,\nDialogue: 0,0:21:18.30,0:21:19.61,EN,,0,0,0,,which the 12 goes into here.\nDialogue: 0,0:21:23.73,0:21:25.09,EN,,0,0,0,,Then I push this button.\nDialogue: 0,0:21:25.09,0:21:26.00,EN,,0,0,0,,The 6 gets into here.\nDialogue: 0,0:21:29.85,0:21:31.68,EN,,0,0,0,,Is 6 equal to 0?\nDialogue: 0,0:21:31.88,0:21:32.49,EN,,0,0,0,,No.\nDialogue: 0,0:21:33.42,0:21:33.98,EN,,0,0,0,,OK.\nDialogue: 0,0:21:34.38,0:21:36.80,EN,,0,0,0,,So then at that point,\nDialogue: 0,0:21:36.89,0:21:38.12,EN,,0,0,0,,the next thing to do is divide it.\nDialogue: 0,0:21:38.14,0:21:39.80,EN,,0,0,0,,Ooh, this has got a remainder of 0.\nDialogue: 0,0:21:40.66,0:21:41.74,EN,,0,0,0,,Looks like we're almost done.\nDialogue: 0,0:21:42.36,0:21:44.36,EN,,0,0,0,,Move the 6 over here next.\nDialogue: 0,0:21:47.00,0:21:48.27,EN,,0,0,0,,0 over here.\nDialogue: 0,0:21:49.09,0:21:50.20,EN,,0,0,0,,Is the answer 0?\nDialogue: 0,0:21:50.20,0:21:50.73,EN,,0,0,0,,Yes.\nDialogue: 0,0:21:51.34,0:21:53.36,EN,,0,0,0,,B is 0, therefore the answer is in A.\nDialogue: 0,0:21:54.28,0:21:55.76,EN,,0,0,0,,The answer is 6.\nDialogue: 0,0:21:56.61,0:21:57.61,EN,,0,0,0,,And indeed that's right,\nDialogue: 0,0:21:57.63,0:21:59.47,EN,,0,0,0,,because if we look at the original problem,\nDialogue: 0,0:22:00.08,0:22:06.64,EN,,0,0,0,,what we have is 30 is 2 times 3 times 5,\nDialogue: 0,0:22:07.00,0:22:11.12,EN,,0,0,0,,and 42 is 2 times 3 times 7.\nDialogue: 0,0:22:11.67,0:22:14.11,EN,,0,0,0,,So the greatest common divisor is 2 times 3,\nDialogue: 0,0:22:14.20,0:22:15.08,EN,,0,0,0,,which is 6.\nDialogue: 0,0:22:18.38,0:22:20.56,EN,,0,0,0,,Now normally, we write one other little line here,\nDialogue: 0,0:22:20.59,0:22:22.52,EN,,0,0,0,,just to make it a little bit clearer,\nDialogue: 0,0:22:22.89,0:22:27.71,EN,,0,0,0,,which is that we leave in a connection saying\nDialogue: 0,0:22:27.85,0:22:31.01,EN,,0,0,0,,that this light is the guy that that flap looks at.\nDialogue: 0,0:22:34.00,0:22:37.32,EN,,0,0,0,,Of course, any real machine has a lot more\nDialogue: 0,0:22:37.85,0:22:40.00,EN,,0,0,0,,complicated things in it than what I've just shown you.\nDialogue: 0,0:22:41.35,0:22:47.16,EN,,0,0,0,,Let's look for a second at the first still store.\nDialogue: 0,0:22:47.98,0:22:48.81,EN,,0,0,0,,Wow.\nDialogue: 0,0:22:50.19,0:22:52.43,EN,,0,0,0,,Well you see, for example, one thing we might want to do\nDialogue: 0,0:22:52.65,0:22:55.85,EN,,0,0,0,,is worry about the operations that are of IO form.\nDialogue: 0,0:22:56.84,0:23:01.42,EN,,0,0,0,,And we may have to collect something from the outside.\nDialogue: 0,0:23:01.98,0:23:03.93,EN,,0,0,0,,So a state machine that we might have,\nDialogue: 0,0:23:04.30,0:23:07.02,EN,,0,0,0,,the controller may have to,\nDialogue: 0,0:23:07.26,0:23:10.56,EN,,0,0,0,,may have to, for example, get a value from something\nDialogue: 0,0:23:10.78,0:23:12.41,EN,,0,0,0,,and put register a to load it up.\nDialogue: 0,0:23:13.49,0:23:15.92,EN,,0,0,0,,I have to master load up register b with another value.\nDialogue: 0,0:23:17.07,0:23:18.60,EN,,0,0,0,,And then later, when I'm done,\nDialogue: 0,0:23:18.99,0:23:20.52,EN,,0,0,0,,I might want to print the answer out.\nDialogue: 0,0:23:21.20,0:23:25.23,EN,,0,0,0,,And of course, that might be either simple or complicated.\nDialogue: 0,0:23:26.09,0:23:28.03,EN,,0,0,0,,I'm writing, assuming print is very simple,\nDialogue: 0,0:23:28.09,0:23:29.29,EN,,0,0,0,,and read is very simple.\nDialogue: 0,0:23:29.88,0:23:31.08,EN,,0,0,0,,But in fact, in the real world,\nDialogue: 0,0:23:31.12,0:23:32.89,EN,,0,0,0,,those are very complicated operations,\nDialogue: 0,0:23:33.08,0:23:35.52,EN,,0,0,0,,fairly, usually much, much larger and more complicated\nDialogue: 0,0:23:35.55,0:23:38.33,EN,,0,0,0,,than the thing you're doing as your problem you're trying to solve.\nDialogue: 0,0:23:41.67,0:23:43.90,EN,,0,0,0,,On the other hand, I can remember a time when,\nDialogue: 0,0:23:44.89,0:23:48.78,EN,,0,0,0,,I remember using IBM 7090 computer of sorts,\nDialogue: 0,0:23:49.05,0:23:53.04,EN,,0,0,0,,where things like read and write of a single object,\nDialogue: 0,0:23:53.08,0:23:54.62,EN,,0,0,0,,a single number, a number,\nDialogue: 0,0:23:55.84,0:23:58.54,EN,,0,0,0,,is a primitive operation of the IO controller.\nDialogue: 0,0:23:59.63,0:24:02.04,EN,,0,0,0,,OK? And so we have that kind of thing in there.\nDialogue: 0,0:24:02.33,0:24:04.67,EN,,0,0,0,,And in such a machine,\nDialogue: 0,0:24:05.44,0:24:06.89,EN,,0,0,0,,well, what are we really doing?\nDialogue: 0,0:24:07.12,0:24:11.60,EN,,0,0,0,,We're just saying that there's a source over here called \"read\"\nDialogue: 0,0:24:12.20,0:24:14.46,EN,,0,0,0,,which is an operation which always has a value.\nDialogue: 0,0:24:14.66,0:24:17.13,EN,,0,0,0,,We have to think about this as always having a value\nDialogue: 0,0:24:17.21,0:24:19.84,EN,,0,0,0,,which can be gated into either register a or b.\nDialogue: 0,0:24:21.66,0:24:23.23,EN,,0,0,0,,And print is some sort of thing\nDialogue: 0,0:24:23.37,0:24:25.02,EN,,0,0,0,,which when you gate it appropriately,\nDialogue: 0,0:24:25.24,0:24:26.43,EN,,0,0,0,,when you push the button on it,\nDialogue: 0,0:24:26.65,0:24:29.61,EN,,0,0,0,,will cause a print of the value that's currently in register a.\nDialogue: 0,0:24:31.66,0:24:32.73,EN,,0,0,0,,Nothing very exciting.\nDialogue: 0,0:24:33.32,0:24:35.20,EN,,0,0,0,,So that's one sort of thing you might want to have.\nDialogue: 0,0:24:35.88,0:24:38.32,EN,,0,0,0,,But these are also other things that are a little bit worrisome.\nDialogue: 0,0:24:38.32,0:24:40.67,EN,,0,0,0,,Like I've used here some complicated mechanisms.\nDialogue: 0,0:24:41.05,0:24:42.48,EN,,0,0,0,,What you see here is remainder.\nDialogue: 0,0:24:43.85,0:24:44.44,EN,,0,0,0,,What is that?\nDialogue: 0,0:24:44.69,0:24:46.41,EN,,0,0,0,,That may not be so obvious how to compute.\nDialogue: 0,0:24:46.92,0:24:48.92,EN,,0,0,0,,It may be something which when you open it up,\nDialogue: 0,0:24:49.48,0:24:50.62,EN,,0,0,0,,you get a whole machine.\nDialogue: 0,0:24:51.84,0:24:53.66,EN,,0,0,0,,OK? In fact, that's true.\nDialogue: 0,0:24:54.54,0:24:59.15,EN,,0,0,0,,For example, if I write down the program for remainder,\nDialogue: 0,0:24:59.44,0:25:02.44,EN,,0,0,0,,the simplest program for it is by repeated subtraction.\nDialogue: 0,0:25:04.78,0:25:05.95,EN,,0,0,0,,Because of course, division can be done\nDialogue: 0,0:25:05.96,0:25:08.99,EN,,0,0,0,,by repeated subtraction of numbers, of integers.\nDialogue: 0,0:25:09.80,0:25:23.58,EN,,0,0,0,,So the remainder of N divided by D\nDialogue: 0,0:25:24.99,0:25:31.44,EN,,0,0,0,,is nothing more than if N is less than D,\nDialogue: 0,0:25:32.24,0:25:33.66,EN,,0,0,0,,then the result is N.\nDialogue: 0,0:25:34.30,0:25:35.90,EN,,0,0,0,,Otherwise, it's the remainder\nDialogue: 0,0:25:41.15,0:25:47.60,EN,,0,0,0,,when we subtract D from N with respect to D,\nDialogue: 0,0:25:48.27,0:25:49.32,EN,,0,0,0,,when divided by D.\nDialogue: 0,0:25:51.28,0:25:55.05,EN,,0,0,0,,Gee, this looks just like the GCD program.\nDialogue: 0,0:25:56.89,0:25:59.48,EN,,0,0,0,,Of course, it's not a very nice way to do remainders.\nDialogue: 0,0:25:59.75,0:26:00.91,EN,,0,0,0,,You'd really want to use something like\nDialogue: 0,0:26:00.92,0:26:05.42,EN,,0,0,0,,binary notation and shift and things like that in a practical computer.\nDialogue: 0,0:26:05.55,0:26:06.97,EN,,0,0,0,,But the point of that is\nDialogue: 0,0:26:07.13,0:26:08.48,EN,,0,0,0,,that if I open this thing up,\nDialogue: 0,0:26:08.92,0:26:10.64,EN,,0,0,0,,I might find inside of it a computer.\nDialogue: 0,0:26:11.88,0:26:12.99,EN,,0,0,0,,Oh, we know how to do that.\nDialogue: 0,0:26:13.51,0:26:14.33,EN,,0,0,0,,We just made one.\nDialogue: 0,0:26:15.64,0:26:17.10,EN,,0,0,0,,And it could be another thing just like this.\nDialogue: 0,0:26:17.40,0:26:18.06,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:26:18.08,0:26:20.00,EN,,0,0,0,,we might want to make a more efficient\nDialogue: 0,0:26:20.01,0:26:21.68,EN,,0,0,0,,or better-structured machine,\nDialogue: 0,0:26:21.85,0:26:23.96,EN,,0,0,0,,or maybe make use of some of the registers more than once,\nDialogue: 0,0:26:24.00,0:26:27.05,EN,,0,0,0,,or some horrible mess like that that hardware designers like to do,\nDialogue: 0,0:26:27.31,0:26:28.60,EN,,0,0,0,,and for very good reasons.\nDialogue: 0,0:26:29.25,0:26:31.56,EN,,0,0,0,,So for example, here's a machine that you see,\nDialogue: 0,0:26:32.52,0:26:34.91,EN,,0,0,0,,which you're not supposed to be able to read.\nDialogue: 0,0:26:35.05,0:26:37.52,EN,,0,0,0,,It's a little bit complicated. OK?\nDialogue: 0,0:26:37.52,0:26:39.87,EN,,0,0,0,,But what it is is the integration of\nDialogue: 0,0:26:40.09,0:26:43.82,EN,,0,0,0,,remainder into the GCD machine.\nDialogue: 0,0:26:44.46,0:26:46.02,EN,,0,0,0,,And it takes, in fact, no more registers.\nDialogue: 0,0:26:46.02,0:26:48.62,EN,,0,0,0,,There are three registers in the datapaths. OK?\nDialogue: 0,0:26:49.05,0:26:50.64,EN,,0,0,0,,But now there's a subtractor.\nDialogue: 0,0:26:51.55,0:26:52.99,EN,,0,0,0,,There are two things that are tested.\nDialogue: 0,0:26:53.02,0:26:55.07,EN,,0,0,0,,Is b equal to 0,\nDialogue: 0,0:26:55.23,0:26:56.56,EN,,0,0,0,,or is t less than b?\nDialogue: 0,0:26:57.25,0:26:59.45,EN,,0,0,0,,And then the controller, which you see over here,\nDialogue: 0,0:27:00.22,0:27:01.76,EN,,0,0,0,,is not much more complicated.\nDialogue: 0,0:27:01.85,0:27:03.87,EN,,0,0,0,,But it has two loops in it,\nDialogue: 0,0:27:04.52,0:27:08.33,EN,,0,0,0,,one of which is the main one for doing the GCD,\nDialogue: 0,0:27:08.40,0:27:10.14,EN,,0,0,0,,and one of which is the subtraction loop\nDialogue: 0,0:27:10.43,0:27:12.80,EN,,0,0,0,,for doing the remainder sub-operation.\nDialogue: 0,0:27:14.03,0:27:15.80,EN,,0,0,0,,And there are ways, of course, of,\nDialogue: 0,0:27:15.96,0:27:18.68,EN,,0,0,0,,if you think about it, taking the remainder program.\nDialogue: 0,0:27:19.92,0:27:21.71,EN,,0,0,0,,If I take remainder, as you see over there\nDialogue: 0,0:27:21.72,0:27:22.83,EN,,0,0,0,,as a lambda expression,\nDialogue: 0,0:27:23.56,0:27:27.02,EN,,0,0,0,,substitute it in for remainder over here in the GCD program,\nDialogue: 0,0:27:28.20,0:27:30.12,EN,,0,0,0,,OK, then do some simplification\nDialogue: 0,0:27:30.32,0:27:33.66,EN,,0,0,0,,by substituting a and b for remainder in there,\nDialogue: 0,0:27:34.46,0:27:35.95,EN,,0,0,0,,then I can unwind this loop.\nDialogue: 0,0:27:36.63,0:27:39.42,EN,,0,0,0,,And I can get this piece of machinery\nDialogue: 0,0:27:40.73,0:27:42.94,EN,,0,0,0,,by basically, a little bit of simplification\nDialogue: 0,0:27:43.36,0:27:45.21,EN,,0,0,0,,algebraic simplification on the lambda expressions.\nDialogue: 0,0:27:48.55,0:27:51.20,EN,,0,0,0,,So I suppose you've seen your first very simple machines now.\nDialogue: 0,0:27:51.95,0:27:53.28,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:28:02.70,0:28:03.10,EN,,0,0,0,,Good.\nDialogue: 0,0:28:05.36,0:28:06.54,EN,,0,0,0,,This looks easy, doesn't it?\nDialogue: 0,0:28:10.14,0:28:11.32,EN,,0,0,0,,Thank you. I suppose, take a break.\nDialogue: 0,0:28:12.54,0:28:24.94,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:28:47.93,0:28:48.70,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:28:49.37,0:28:52.46,EN,,0,0,0,,Now you know how to make an iterative procedure,\nDialogue: 0,0:28:52.54,0:28:54.54,EN,,0,0,0,,or a procedure that yields an iterative process,\nDialogue: 0,0:28:55.18,0:28:56.52,EN,,0,0,0,,turn into a machine.\nDialogue: 0,0:28:57.77,0:29:00.04,EN,,0,0,0,,I suppose the next thing we want to do is worry about things\nDialogue: 0,0:29:00.54,0:29:02.30,EN,,0,0,0,,that reveal recursive processes.\nDialogue: 0,0:29:02.81,0:29:05.05,EN,,0,0,0,,So let's play with a simple factorial procedure.\nDialogue: 0,0:29:11.20,0:29:16.94,EN,,0,0,0,,We define factorial of N to be\nDialogue: 0,0:29:19.63,0:29:24.25,EN,,0,0,0,,if n is 1, the result is 1,\nDialogue: 0,0:29:24.62,0:29:27.69,EN,,0,0,0,,using 1 right now to decrease the amount of work I have to do to simulate it,\nDialogue: 0,0:29:28.12,0:29:33.94,EN,,0,0,0,,else it's times N factorial N minus 1.\nDialogue: 0,0:29:42.52,0:29:46.04,EN,,0,0,0,,And what's different with this program, as you know,\nDialogue: 0,0:29:46.65,0:29:50.36,EN,,0,0,0,,is that after I've computed factorial of N minus 1 here,\nDialogue: 0,0:29:50.67,0:29:52.26,EN,,0,0,0,,I have to do something to the result.\nDialogue: 0,0:29:52.26,0:29:53.68,EN,,0,0,0,,I have to multiply it by N.\nDialogue: 0,0:29:56.00,0:30:00.67,EN,,0,0,0,,So the only way I can visualize what this machine is doing,\nDialogue: 0,0:30:01.08,0:30:02.01,EN,,0,0,0,,because of the fact--\nDialogue: 0,0:30:02.35,0:30:03.18,EN,,0,0,0,,think of it this way,\nDialogue: 0,0:30:03.36,0:30:04.94,EN,,0,0,0,,that I have a machine out here\nDialogue: 0,0:30:05.08,0:30:08.11,EN,,0,0,0,,which somehow needs a factorial machine in order to compute its answer.\nDialogue: 0,0:30:09.32,0:30:11.16,EN,,0,0,0,,But this machine, the outer machine,\nDialogue: 0,0:30:11.20,0:30:13.02,EN,,0,0,0,,has to exist before and after\nDialogue: 0,0:30:13.92,0:30:15.72,EN,,0,0,0,,the factorial machine, which is inside.\nDialogue: 0,0:30:16.80,0:30:17.90,EN,,0,0,0,,Whereas in the iterative case,\nDialogue: 0,0:30:18.75,0:30:20.52,EN,,0,0,0,,the outer machine doesn't need to exist\nDialogue: 0,0:30:20.91,0:30:24.01,EN,,0,0,0,,after the inner machine is running,\nDialogue: 0,0:30:24.83,0:30:26.16,EN,,0,0,0,,because you never need to go back\nDialogue: 0,0:30:26.19,0:30:27.53,EN,,0,0,0,,to the outer machine to do anything.\nDialogue: 0,0:30:28.64,0:30:30.06,EN,,0,0,0,,So here we have a problem\nDialogue: 0,0:30:30.27,0:30:30.97,EN,,0,0,0,,where we have a machine\nDialogue: 0,0:30:31.00,0:30:32.73,EN,,0,0,0,,which has the same machine inside of it,\nDialogue: 0,0:30:33.87,0:30:35.52,EN,,0,0,0,,an infinitely large machine.\nDialogue: 0,0:30:40.39,0:30:43.12,EN,,0,0,0,,And it's got other things inside of it, like a multiplier,\nDialogue: 0,0:30:44.76,0:30:46.03,EN,,0,0,0,,which takes some inputs,\nDialogue: 0,0:30:46.27,0:30:47.77,EN,,0,0,0,,and there's a minus 1 box,\nDialogue: 0,0:30:48.12,0:30:49.31,EN,,0,0,0,,and things like that.\nDialogue: 0,0:30:50.69,0:30:53.72,EN,,0,0,0,,You know, You can imagine that's what it looks like.\nDialogue: 0,0:30:54.37,0:30:56.76,EN,,0,0,0,,But the important thing is that here I have\nDialogue: 0,0:30:57.02,0:30:58.70,EN,,0,0,0,,something that happens before and after,\nDialogue: 0,0:30:58.78,0:31:01.60,EN,,0,0,0,,in the outer machine, the execution of the inner machine.\nDialogue: 0,0:31:02.54,0:31:04.08,EN,,0,0,0,,So this machine has to have a life.\nDialogue: 0,0:31:05.47,0:31:11.44,EN,,0,0,0,,It has to exist on both times sides of this machine.\nDialogue: 0,0:31:13.49,0:31:15.80,EN,,0,0,0,,So somehow, I have to have a place to store\nDialogue: 0,0:31:16.19,0:31:18.19,EN,,0,0,0,,the things that this thing needs to run.\nDialogue: 0,0:31:20.03,0:31:22.09,EN,,0,0,0,,Infinite objects don't exist in the real world.\nDialogue: 0,0:31:24.14,0:31:25.58,EN,,0,0,0,,What we have to do is arrange an illusion\nDialogue: 0,0:31:26.12,0:31:27.48,EN,,0,0,0,,that we have an infinite object,\nDialogue: 0,0:31:27.98,0:31:29.77,EN,,0,0,0,,we have an infinite amount of hardware somewhere.\nDialogue: 0,0:31:31.83,0:31:35.34,EN,,0,0,0,,Now of course, illusion's all that really matters.\nDialogue: 0,0:31:36.28,0:31:37.37,EN,,0,0,0,,If we can arrange\nDialogue: 0,0:31:38.00,0:31:39.84,EN,,0,0,0,,that every time you look at some infinite object,\nDialogue: 0,0:31:39.88,0:31:42.96,EN,,0,0,0,,the part of it that you look at is there,\nDialogue: 0,0:31:44.49,0:31:46.04,EN,,0,0,0,,then it's as infinite as you need it to be.\nDialogue: 0,0:31:47.39,0:31:49.44,EN,,0,0,0,,And of course, one of the things we might want to do,\nDialogue: 0,0:31:49.82,0:31:52.49,EN,,0,0,0,,just look at this thing over here,\nDialogue: 0,0:31:53.00,0:31:54.97,EN,,0,0,0,,is the organization that we've had so far\nDialogue: 0,0:31:56.04,0:31:57.64,EN,,0,0,0,,organization that we've had so far\nDialogue: 0,0:31:57.92,0:32:01.37,EN,,0,0,0,,involves having a part of the machine,\nDialogue: 0,0:32:01.40,0:32:02.33,EN,,0,0,0,,which is the controller,\nDialogue: 0,0:32:03.18,0:32:04.46,EN,,0,0,0,,which sits right over here,\nDialogue: 0,0:32:04.78,0:32:07.61,EN,,0,0,0,,which is perfectly finite and very simple.\nDialogue: 0,0:32:09.17,0:32:10.44,EN,,0,0,0,,We have some datapaths,\nDialogue: 0,0:32:10.46,0:32:12.75,EN,,0,0,0,,which consist of registers and operators.\nDialogue: 0,0:32:13.08,0:32:15.20,EN,,0,0,0,,And what I propose to do here is decompose\nDialogue: 0,0:32:15.48,0:32:16.96,EN,,0,0,0,,the machine into two parts,\nDialogue: 0,0:32:17.36,0:32:19.79,EN,,0,0,0,,such that there is a part which is fundamentally finite,\nDialogue: 0,0:32:20.78,0:32:23.53,EN,,0,0,0,,and some part where a certain amount of infinite stuff can be kept.\nDialogue: 0,0:32:24.23,0:32:25.90,EN,,0,0,0,,On the other hand this is very simple\nDialogue: 0,0:32:26.41,0:32:28.72,EN,,0,0,0,,and really isn't infinite, but it's just very large.\nDialogue: 0,0:32:29.43,0:32:30.40,EN,,0,0,0,,But it's so simple\nDialogue: 0,0:32:30.52,0:32:32.92,EN,,0,0,0,,that it could be cheaply reproduced in such large amounts,\nDialogue: 0,0:32:34.09,0:32:34.92,EN,,0,0,0,,we call it memory,\nDialogue: 0,0:32:35.95,0:32:39.07,EN,,0,0,0,,OK? that we can make a structure called a stack out of it\nDialogue: 0,0:32:39.40,0:32:41.23,EN,,0,0,0,,which will allow us to, in fact,\nDialogue: 0,0:32:41.45,0:32:43.63,EN,,0,0,0,,simulate the existence of an infinite machine\nDialogue: 0,0:32:43.64,0:32:46.96,EN,,0,0,0,,which is made out of a recursive nest of many machines.\nDialogue: 0,0:32:48.34,0:32:50.43,EN,,0,0,0,,And the way it's going to work is that\nDialogue: 0,0:32:50.56,0:32:52.97,EN,,0,0,0,,we're going to store in this place called the stack\nDialogue: 0,0:32:54.30,0:32:57.58,EN,,0,0,0,,the information required after the inner machine runs\nDialogue: 0,0:32:59.18,0:33:01.07,EN,,0,0,0,,to resume the operation of the outer machine.\nDialogue: 0,0:33:03.84,0:33:05.48,EN,,0,0,0,,So it will remember\nDialogue: 0,0:33:05.63,0:33:07.95,EN,,0,0,0,,the important things about the life of the outer machine\nDialogue: 0,0:33:08.04,0:33:10.30,EN,,0,0,0,,that will be needed for this computation.\nDialogue: 0,0:33:11.39,0:33:12.48,EN,,0,0,0,,Since, of course,\nDialogue: 0,0:33:12.75,0:33:16.33,EN,,0,0,0,,these machines are nested in a recursive manner,\nDialogue: 0,0:33:18.33,0:33:23.39,EN,,0,0,0,,then in fact the stack will only be accessed in a manner\nDialogue: 0,0:33:23.45,0:33:26.44,EN,,0,0,0,,which is the last thing that goes in is the first thing that comes out.\nDialogue: 0,0:33:29.33,0:33:30.64,EN,,0,0,0,,So we'll only need to access\nDialogue: 0,0:33:30.80,0:33:32.52,EN,,0,0,0,,some little part of this stack memory.\nDialogue: 0,0:33:34.93,0:33:35.92,EN,,0,0,0,,OK, well, let's do it.\nDialogue: 0,0:33:36.81,0:33:38.41,EN,,0,0,0,,I'm going to build you a datapath now,\nDialogue: 0,0:33:38.44,0:33:39.68,EN,,0,0,0,,and I'm going to write the controller.\nDialogue: 0,0:33:40.37,0:33:42.86,EN,,0,0,0,,And then we're going to execute this to see how you do it.\nDialogue: 0,0:33:43.51,0:33:46.88,EN,,0,0,0,,So the factorial machine isn't so bad.\nDialogue: 0,0:33:47.90,0:33:50.16,EN,,0,0,0,,It's going to have a register called the value,\nDialogue: 0,0:33:52.22,0:33:53.88,EN,,0,0,0,,where the answer is going to be stored,\nDialogue: 0,0:33:54.89,0:33:56.67,EN,,0,0,0,,and a registered called N,\nDialogue: 0,0:33:59.85,0:34:04.16,EN,,0,0,0,,which is where the number I'm taking factorial will be stored, factorial of.\nDialogue: 0,0:34:04.51,0:34:06.57,EN,,0,0,0,,And it will be necessary in some instances\nDialogue: 0,0:34:07.48,0:34:10.52,EN,,0,0,0,,to connect VAL to N.\nDialogue: 0,0:34:11.74,0:34:15.63,EN,,0,0,0,,In fact, one nice case of this is if I just said over here,\nDialogue: 0,0:34:16.38,0:34:19.53,EN,,0,0,0,,N, because that would be right for N equal 1N.\nDialogue: 0,0:34:20.09,0:34:23.26,EN,,0,0,0,,And I could just move the answer over there if that's important.\nDialogue: 0,0:34:23.90,0:34:25.55,EN,,0,0,0,,I'm not worried about that right now.\nDialogue: 0,0:34:26.98,0:34:28.60,EN,,0,0,0,,And there are things I have to be able to do.\nDialogue: 0,0:34:29.06,0:34:31.02,EN,,0,0,0,,Like I have to be able to, as we see here,\nDialogue: 0,0:34:31.21,0:34:34.67,EN,,0,0,0,,multiply N by something in VAL,\nDialogue: 0,0:34:34.91,0:34:37.45,EN,,0,0,0,,because VAL is the result of computing factorial.\nDialogue: 0,0:34:38.68,0:34:40.44,EN,,0,0,0,,And I have to put the result back into VAL.\nDialogue: 0,0:34:41.48,0:34:42.65,EN,,0,0,0,,So here we can see\nDialogue: 0,0:34:42.83,0:34:46.43,EN,,0,0,0,,that the result of computing a factorial\nDialogue: 0,0:34:46.57,0:34:49.20,EN,,0,0,0,,is N times the result of computing a factorial.\nDialogue: 0,0:34:50.69,0:34:53.77,EN,,0,0,0,,VAL will be the representation of the answer of the inner factorial.\nDialogue: 0,0:34:55.19,0:35:00.25,EN,,0,0,0,,And so I'm going to have to have a multiplier here,\nDialogue: 0,0:35:02.36,0:35:07.18,EN,,0,0,0,,which is going to sample the value of N and the value of VAL\nDialogue: 0,0:35:08.64,0:35:15.60,EN,,0,0,0,,OK? and put the result back into VAL like that.\nDialogue: 0,0:35:17.17,0:35:19.39,EN,,0,0,0,,I'm also going to have to be able to see if N is 1.\nDialogue: 0,0:35:21.32,0:35:22.38,EN,,0,0,0,,So I need a light bulb.\nDialogue: 0,0:35:28.20,0:35:30.40,EN,,0,0,0,,And I suppose the other thing I'm going to need to have\nDialogue: 0,0:35:31.02,0:35:32.84,EN,,0,0,0,,is a way of decrementing N.\nDialogue: 0,0:35:34.84,0:35:36.09,EN,,0,0,0,,So I'm going to have a decrementer,\nDialogue: 0,0:35:38.19,0:35:41.39,EN,,0,0,0,,which takes N and is going to put back the result into N.\nDialogue: 0,0:35:46.62,0:35:48.40,EN,,0,0,0,,That's pretty much what I need in my machine.\nDialogue: 0,0:35:49.55,0:35:51.64,EN,,0,0,0,,Now, there's a little bit else I need.\nDialogue: 0,0:35:52.30,0:35:53.58,EN,,0,0,0,,It's a little bit more complicated,\nDialogue: 0,0:35:55.16,0:35:56.88,EN,,0,0,0,,because I'm also going to need a way to store,\nDialogue: 0,0:35:57.16,0:35:59.69,EN,,0,0,0,,to save away, the things that are going to be needed\nDialogue: 0,0:36:01.02,0:36:03.07,EN,,0,0,0,,for resuming the computation of a factorial\nDialogue: 0,0:36:03.10,0:36:04.89,EN,,0,0,0,,after I've done a sub-factorial.\nDialogue: 0,0:36:06.25,0:36:06.86,EN,,0,0,0,,What's that?\nDialogue: 0,0:36:07.23,0:36:08.73,EN,,0,0,0,,One thing I need is N.\nDialogue: 0,0:36:09.85,0:36:12.04,EN,,0,0,0,,So I'm going to build here a thing called a stack.\nDialogue: 0,0:36:14.70,0:36:15.77,EN,,0,0,0,,The stack is\nDialogue: 0,0:36:17.98,0:36:24.97,EN,,0,0,0,,a bunch of stuff that I'm going to write in sequentially.\nDialogue: 0,0:36:27.15,0:36:28.59,EN,,0,0,0,,I don't know how long it is.\nDialogue: 0,0:36:29.15,0:36:31.48,EN,,0,0,0,,The longer it is, the better my illusion of infinity.\nDialogue: 0,0:36:33.23,0:36:35.56,EN,,0,0,0,,And I'm going to have to have a way of getting stuff\nDialogue: 0,0:36:35.60,0:36:37.02,EN,,0,0,0,,out of N and into the stack\nDialogue: 0,0:36:38.12,0:36:39.08,EN,,0,0,0,,and vice versa.\nDialogue: 0,0:36:39.93,0:36:41.74,EN,,0,0,0,,So I'm going to need a connection like this,\nDialogue: 0,0:36:44.41,0:36:45.48,EN,,0,0,0,,which is two-way,\nDialogue: 0,0:36:50.44,0:36:52.22,EN,,0,0,0,,whereby I can save the value of N\nDialogue: 0,0:36:52.24,0:36:55.50,EN,,0,0,0,,and then restore it some other time through that connection.\nDialogue: 0,0:36:56.04,0:36:56.84,EN,,0,0,0,,This is the stack.\nDialogue: 0,0:36:58.10,0:37:01.71,EN,,0,0,0,,I also need a way of remembering\nDialogue: 0,0:37:01.84,0:37:07.72,EN,,0,0,0,,where I was in the computation of factorial in the outer program.\nDialogue: 0,0:37:08.53,0:37:10.06,EN,,0,0,0,,Now in the case of this machine,\nDialogue: 0,0:37:10.76,0:37:13.34,EN,,0,0,0,,it isn't very much a problem.\nDialogue: 0,0:37:14.17,0:37:16.24,EN,,0,0,0,,Factorial always returns,\nDialogue: 0,0:37:16.86,0:37:19.07,EN,,0,0,0,,has to go back to the place where we multiply by N,\nDialogue: 0,0:37:19.34,0:37:20.72,EN,,0,0,0,,except for the last time,\nDialogue: 0,0:37:21.15,0:37:23.02,EN,,0,0,0,,when it has to return to whatever needs the factorial\nDialogue: 0,0:37:23.04,0:37:24.04,EN,,0,0,0,,or go to done or stop.\nDialogue: 0,0:37:25.66,0:37:26.67,EN,,0,0,0,,However, in general,\nDialogue: 0,0:37:27.16,0:37:28.73,EN,,0,0,0,,I'm going to have to remember where I have been,\nDialogue: 0,0:37:29.13,0:37:31.24,EN,,0,0,0,,because I might have computed factorial from somewhere else.\nDialogue: 0,0:37:32.08,0:37:34.89,EN,,0,0,0,,I have to go back to that place and continue there.\nDialogue: 0,0:37:36.07,0:37:38.00,EN,,0,0,0,,So I'm going to have to have some way of taking the place\nDialogue: 0,0:37:38.01,0:37:40.86,EN,,0,0,0,,where the marble is in the finite state controller,\nDialogue: 0,0:37:41.32,0:37:42.64,EN,,0,0,0,,the state of the controller,\nDialogue: 0,0:37:44.22,0:37:46.35,EN,,0,0,0,,and storing that in the stack as well.\nDialogue: 0,0:37:47.40,0:37:49.10,EN,,0,0,0,,And I'm going to have to have ways of restoring that\nDialogue: 0,0:37:49.45,0:37:51.12,EN,,0,0,0,,back to the state of the-- the marble.\nDialogue: 0,0:37:52.14,0:37:54.28,EN,,0,0,0,,So I have to have something that moves the marble to the right place.\nDialogue: 0,0:37:54.70,0:37:56.52,EN,,0,0,0,,Well, we're going to have a place which is the marble now.\nDialogue: 0,0:37:57.87,0:37:59.34,EN,,0,0,0,,And it's called the continue register,\nDialogue: 0,0:38:03.61,0:38:04.52,EN,,0,0,0,,called continue,\nDialogue: 0,0:38:09.16,0:38:10.68,EN,,0,0,0,,which is the place to put the marble\nDialogue: 0,0:38:11.00,0:38:13.05,EN,,0,0,0,,next time I go to continue.\nDialogue: 0,0:38:14.91,0:38:15.92,EN,,0,0,0,,That's what that's for.\nDialogue: 0,0:38:16.14,0:38:18.48,EN,,0,0,0,,And so there's got to be some path from that into the controller.\nDialogue: 0,0:38:22.91,0:38:27.12,EN,,0,0,0,,I also have to have some way of saving that on the stack.\nDialogue: 0,0:38:29.45,0:38:33.10,EN,,0,0,0,,And I have to have some way of setting that up to have various constants,\nDialogue: 0,0:38:34.01,0:38:35.69,EN,,0,0,0,,a certain fixed number of constants.\nDialogue: 0,0:38:36.86,0:38:38.20,EN,,0,0,0,,And that's very easy to arrange.\nDialogue: 0,0:38:38.84,0:38:40.14,EN,,0,0,0,,So let's have some constants here.\nDialogue: 0,0:38:40.18,0:38:41.50,EN,,0,0,0,,We'll call this one after-fact.\nDialogue: 0,0:38:47.32,0:38:48.75,EN,,0,0,0,,And that's a constant\nDialogue: 0,0:38:48.84,0:38:51.50,EN,,0,0,0,,which will get into the continue register,\nDialogue: 0,0:38:52.59,0:38:54.43,EN,,0,0,0,,and also another one called fact-done.\nDialogue: 0,0:39:05.21,0:39:07.82,EN,,0,0,0,,So this is the machine I want to build.\nDialogue: 0,0:39:08.13,0:39:09.48,EN,,0,0,0,,That's its datapaths, at least.\nDialogue: 0,0:39:09.92,0:39:11.69,EN,,0,0,0,,And it mixes a little with the controller here,\nDialogue: 0,0:39:11.85,0:39:14.59,EN,,0,0,0,,because of the fact that I have to remember where I was\nDialogue: 0,0:39:14.70,0:39:16.35,EN,,0,0,0,,and restore myself to that place.\nDialogue: 0,0:39:17.30,0:39:19.93,EN,,0,0,0,,But let's write the program now which represents the controller.\nDialogue: 0,0:39:20.39,0:39:23.47,EN,,0,0,0,,I'm not going to write the define machine thing and the register list,\nDialogue: 0,0:39:23.48,0:39:24.89,EN,,0,0,0,,because that's not very interesting.\nDialogue: 0,0:39:25.13,0:39:27.79,EN,,0,0,0,,I'm just going to write down the sequence of instructions\nDialogue: 0,0:39:27.82,0:39:29.02,EN,,0,0,0,,that constitute the controller.\nDialogue: 0,0:39:31.48,0:39:41.85,EN,,0,0,0,,So we have assign, to set up, continue to done.\nDialogue: 0,0:39:45.15,0:39:45.82,EN,,0,0,0,,We have a loop\nDialogue: 0,0:39:47.34,0:39:56.08,EN,,0,0,0,,which says branch if equal 1 fetch N,\nDialogue: 0,0:40:00.94,0:40:04.11,EN,,0,0,0,,if N is 1, then go to the base step of the induction,\nDialogue: 0,0:40:06.06,0:40:07.20,EN,,0,0,0,,the simple case.\nDialogue: 0,0:40:08.05,0:40:08.76,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:40:08.88,0:40:10.84,EN,,0,0,0,,I have to remember the things that are necessary\nDialogue: 0,0:40:10.88,0:40:13.84,EN,,0,0,0,,to perform a sub-factorial.\nDialogue: 0,0:40:14.67,0:40:16.75,EN,,0,0,0,,I'm going to go over here, and I have to perform a sub-factorial.\nDialogue: 0,0:40:17.57,0:40:19.29,EN,,0,0,0,,So I have to remember what's needed to do that\nDialogue: 0,0:40:19.71,0:40:22.52,EN,,0,0,0,,remember what's needed after I will be done with that.\nDialogue: 0,0:40:24.00,0:40:25.51,EN,,0,0,0,,See, I'm about to do something terrible.\nDialogue: 0,0:40:25.72,0:40:27.39,EN,,0,0,0,,I'm about to change the value of N.\nDialogue: 0,0:40:28.57,0:40:30.40,EN,,0,0,0,,But this guy has to know the old value of N.\nDialogue: 0,0:40:32.14,0:40:33.64,EN,,0,0,0,,But in order to make the sub-factorial work,\nDialogue: 0,0:40:33.66,0:40:34.92,EN,,0,0,0,,I have to change the value of N.\nDialogue: 0,0:40:35.60,0:40:37.10,EN,,0,0,0,,So I have to remember the old value.\nDialogue: 0,0:40:38.00,0:40:39.60,EN,,0,0,0,,And I also have to remember where I've been.\nDialogue: 0,0:40:40.85,0:40:42.32,EN,,0,0,0,,So I save up continue.\nDialogue: 0,0:40:47.70,0:40:51.29,EN,,0,0,0,,And this is an instruction that says, put something in the stack.\nDialogue: 0,0:40:53.12,0:40:55.53,EN,,0,0,0,,Save the contents of the continuation register,\nDialogue: 0,0:40:56.51,0:40:58.00,EN,,0,0,0,,which in this case is done,\nDialogue: 0,0:40:58.88,0:41:00.25,EN,,0,0,0,,because later I'm going to change that, too,\nDialogue: 0,0:41:00.27,0:41:02.78,EN,,0,0,0,,because I need to go back to after-fact, as well.\nDialogue: 0,0:41:03.55,0:41:04.19,EN,,0,0,0,,We'll see that.\nDialogue: 0,0:41:05.04,0:41:09.71,EN,,0,0,0,,We save N, because I'm going to need that for later.\nDialogue: 0,0:41:10.38,0:41:20.54,EN,,0,0,0,,Assign to N the decrement of fetch N.\nDialogue: 0,0:41:23.26,0:41:28.97,EN,,0,0,0,,Assign continue,\nDialogue: 0,0:41:32.12,0:41:33.42,EN,,0,0,0,,we're going to look at this now,\nDialogue: 0,0:41:34.06,0:41:35.61,EN,,0,0,0,,to after, we'll call it.\nDialogue: 0,0:41:37.69,0:41:38.70,EN,,0,0,0,,That's a good name for this,\nDialogue: 0,0:41:38.73,0:41:40.65,EN,,0,0,0,,a little bit easier and shorter, and fits in here.\nDialogue: 0,0:41:53.36,0:41:54.64,EN,,0,0,0,,Now look what I'm doing here.\nDialogue: 0,0:41:55.33,0:41:57.02,EN,,0,0,0,,I'm saying, if the answer is 1,\nDialogue: 0,0:41:58.72,0:41:59.66,EN,,0,0,0,,OK, I'm done.\nDialogue: 0,0:42:00.46,0:42:01.66,EN,,0,0,0,,I'm going to have to just get the answer.\nDialogue: 0,0:42:02.15,0:42:04.88,EN,,0,0,0,,Otherwise, I'm going to save the continuation, save N,\nDialogue: 0,0:42:05.77,0:42:07.32,EN,,0,0,0,,make N one less than N,\nDialogue: 0,0:42:07.60,0:42:09.63,EN,,0,0,0,,remember I'm going to come back to someplace else,\nDialogue: 0,0:42:09.64,0:42:11.48,EN,,0,0,0,,and go back and start doing another factorial.\nDialogue: 0,0:42:13.50,0:42:15.74,EN,,0,0,0,,OK? However, I've got a different machine in me now.\nDialogue: 0,0:42:16.05,0:42:18.38,EN,,0,0,0,,N is 1, and continue is something else.\nDialogue: 0,0:42:22.11,0:42:23.21,EN,,0,0,0,,N is N minus 1.\nDialogue: 0,0:42:23.77,0:42:25.28,EN,,0,0,0,,Now after I'm done with that,\nDialogue: 0,0:42:26.94,0:42:27.76,EN,,0,0,0,,I can go there.\nDialogue: 0,0:42:28.66,0:42:30.46,EN,,0,0,0,,I will restore the old value of N,\nDialogue: 0,0:42:32.68,0:42:36.56,EN,,0,0,0,,which is the opposite of this save over here.\nDialogue: 0,0:42:38.36,0:42:39.88,EN,,0,0,0,,I will restore the continuation.\nDialogue: 0,0:42:49.66,0:42:52.57,EN,,0,0,0,,I will then go to here.\nDialogue: 0,0:42:54.32,0:43:00.86,EN,,0,0,0,,I will assign to the VAL register\nDialogue: 0,0:43:01.16,0:43:08.13,EN,,0,0,0,,the product of N and fetch VAL.\nDialogue: 0,0:43:13.44,0:43:18.30,EN,,0,0,0,,VAL fetch product assign.\nDialogue: 0,0:43:19.79,0:43:21.44,EN,,0,0,0,,And then I will be done.\nDialogue: 0,0:43:21.44,0:43:25.68,EN,,0,0,0,,I will have my answer to the sub-factorial in VAL.\nDialogue: 0,0:43:26.57,0:43:27.37,EN,,0,0,0,,At that point,\nDialogue: 0,0:43:27.66,0:43:28.75,EN,,0,0,0,,I'm going to return\nDialogue: 0,0:43:29.28,0:43:31.61,EN,,0,0,0,,by going to the place where the continuation is pointing.\nDialogue: 0,0:43:33.64,0:43:35.77,EN,,0,0,0,,That says, go to fetch continue.\nDialogue: 0,0:43:45.87,0:43:47.40,EN,,0,0,0,,And then I have finally a base step,\nDialogue: 0,0:43:49.31,0:43:50.51,EN,,0,0,0,,which is the immediate answer.\nDialogue: 0,0:43:50.68,0:43:56.88,EN,,0,0,0,,Assign to VAL fetch N,\nDialogue: 0,0:44:01.36,0:44:02.75,EN,,0,0,0,,and go to fetch continue.\nDialogue: 0,0:44:12.67,0:44:13.55,EN,,0,0,0,,And then I'm done.\nDialogue: 0,0:44:18.64,0:44:21.21,EN,,0,0,0,,Now let's see how this executes on a very simple case,\nDialogue: 0,0:44:22.51,0:44:23.53,EN,,0,0,0,,because then we'll see\nDialogue: 0,0:44:23.66,0:44:26.52,EN,,0,0,0,,the use of this stack to do the job we need.\nDialogue: 0,0:44:26.89,0:44:28.22,EN,,0,0,0,,This is statically what it's doing,\nDialogue: 0,0:44:28.22,0:44:29.80,EN,,0,0,0,,but we have look dynamically at this.\nDialogue: 0,0:44:31.34,0:44:32.09,EN,,0,0,0,,So let's see.\nDialogue: 0,0:44:32.30,0:44:34.56,EN,,0,0,0,,First thing we do is continue gets done.\nDialogue: 0,0:44:36.73,0:44:38.09,EN,,0,0,0,,The way that happened is I pushed this.\nDialogue: 0,0:44:38.30,0:44:39.60,EN,,0,0,0,,Let's call that done the way I have it.\nDialogue: 0,0:44:46.22,0:44:47.03,EN,,0,0,0,,I push that button.\nDialogue: 0,0:44:47.03,0:44:48.11,EN,,0,0,0,,Done goes into there.\nDialogue: 0,0:44:48.95,0:44:53.71,EN,,0,0,0,,Now I also have to set this thing up to have an initial value.\nDialogue: 0,0:44:53.85,0:44:58.08,EN,,0,0,0,,Let's consider a factorial of three,\nDialogue: 0,0:44:58.38,0:44:59.24,EN,,0,0,0,,a simple case.\nDialogue: 0,0:45:00.54,0:45:04.04,EN,,0,0,0,,And we're going to start out with our stack growing over here.\nDialogue: 0,0:45:05.90,0:45:07.76,EN,,0,0,0,,Stacks have their own little internal state\nDialogue: 0,0:45:07.79,0:45:09.05,EN,,0,0,0,,saying where they are,\nDialogue: 0,0:45:09.80,0:45:11.64,EN,,0,0,0,,where the next place I'm going to write is.\nDialogue: 0,0:45:12.77,0:45:14.59,EN,,0,0,0,,So now we say, is N 1?\nDialogue: 0,0:45:14.76,0:45:15.71,EN,,0,0,0,,The answer is no.\nDialogue: 0,0:45:16.11,0:45:18.56,EN,,0,0,0,,So now I'm going to save continue, bang.\nDialogue: 0,0:45:19.15,0:45:20.65,EN,,0,0,0,,Now that done goes in here.\nDialogue: 0,0:45:22.08,0:45:23.55,EN,,0,0,0,,And this moves to here,\nDialogue: 0,0:45:24.88,0:45:26.14,EN,,0,0,0,,the next place I'm going to write.\nDialogue: 0,0:45:26.66,0:45:28.78,EN,,0,0,0,,Save N 3.\nDialogue: 0,0:45:29.95,0:45:30.32,EN,,0,0,0,,OK?\nDialogue: 0,0:45:30.67,0:45:33.61,EN,,0,0,0,,Assign to N the decrement of N.\nDialogue: 0,0:45:33.96,0:45:35.37,EN,,0,0,0,,That means I've pushed this button.\nDialogue: 0,0:45:35.94,0:45:37.32,EN,,0,0,0,,This becomes 2.\nDialogue: 0,0:45:38.73,0:45:42.28,EN,,0,0,0,,OK? Assign to continue aft.\nDialogue: 0,0:45:42.58,0:45:43.61,EN,,0,0,0,,So I've pushed that button.\nDialogue: 0,0:45:43.61,0:45:44.54,EN,,0,0,0,,Aft goes in here.\nDialogue: 0,0:45:49.14,0:45:53.93,EN,,0,0,0,,OK, now go to loop, bang, so up to here.\nDialogue: 0,0:45:54.83,0:45:57.08,EN,,0,0,0,,Is N 1? No\nDialogue: 0,0:45:57.78,0:45:59.23,EN,,0,0,0,,So I have to save continue.\nDialogue: 0,0:45:59.49,0:46:00.27,EN,,0,0,0,,What's continue?\nDialogue: 0,0:46:00.60,0:46:01.53,EN,,0,0,0,,Continue is aft.\nDialogue: 0,0:46:01.53,0:46:02.32,EN,,0,0,0,,Push this button.\nDialogue: 0,0:46:02.78,0:46:03.95,EN,,0,0,0,,So this moves to here.\nDialogue: 0,0:46:08.49,0:46:09.74,EN,,0,0,0,,I have to save N.\nDialogue: 0,0:46:10.51,0:46:12.12,EN,,0,0,0,,N is over here. I got to 2.\nDialogue: 0,0:46:12.28,0:46:13.37,EN,,0,0,0,,Push that button.\nDialogue: 0,0:46:13.85,0:46:15.24,EN,,0,0,0,,So a 2 gets written there.\nDialogue: 0,0:46:16.05,0:46:17.64,EN,,0,0,0,,And then this thing moves down here.\nDialogue: 0,0:46:20.06,0:46:22.60,EN,,0,0,0,,OK, save N. Assign N to the decrement of N.\nDialogue: 0,0:46:24.60,0:46:25.46,EN,,0,0,0,,This becomes a 1.\nDialogue: 0,0:46:29.24,0:46:30.54,EN,,0,0,0,,Assign continue to aft.\nDialogue: 0,0:46:31.37,0:46:34.48,EN,,0,0,0,,A-F-T gets written there again.\nDialogue: 0,0:46:34.96,0:46:35.64,EN,,0,0,0,,Go to loop.\nDialogue: 0,0:46:36.52,0:46:37.74,EN,,0,0,0,,Is N equal to 1?\nDialogue: 0,0:46:37.93,0:46:39.52,EN,,0,0,0,,Oh, yes, the answer is 1.\nDialogue: 0,0:46:41.04,0:46:43.26,EN,,0,0,0,,OK, go to base step.\nDialogue: 0,0:46:44.16,0:46:45.77,EN,,0,0,0,,Assign to VAL fetch of N.\nDialogue: 0,0:46:46.56,0:46:50.72,EN,,0,0,0,,Bang, 1 gets put in there. OK?\nDialogue: 0,0:46:51.10,0:46:52.20,EN,,0,0,0,,Go to fetch continue.\nDialogue: 0,0:46:52.20,0:46:53.53,EN,,0,0,0,,So we look in continue.\nDialogue: 0,0:46:53.68,0:46:56.06,EN,,0,0,0,,Basically, I'm pushing a button over here that goes to the controller.\nDialogue: 0,0:46:56.67,0:46:58.28,EN,,0,0,0,,The continue becomes aft,\nDialogue: 0,0:46:58.32,0:47:00.25,EN,,0,0,0,,and all of a sudden, the program's running here.\nDialogue: 0,0:47:02.64,0:47:05.63,EN,,0,0,0,,I now have to restore the outer version of factorial.\nDialogue: 0,0:47:06.65,0:47:07.55,EN,,0,0,0,,So we go here.\nDialogue: 0,0:47:07.55,0:47:09.48,EN,,0,0,0,,We say, restore N.\nDialogue: 0,0:47:10.32,0:47:13.04,EN,,0,0,0,,So restore N means take the contents that's here.\nDialogue: 0,0:47:13.94,0:47:18.17,EN,,0,0,0,,Push this button, and it goes into here, 2,\nDialogue: 0,0:47:18.56,0:47:20.04,EN,,0,0,0,,and the pointer moves up.\nDialogue: 0,0:47:21.98,0:47:24.49,EN,,0,0,0,,Restore continue, pretty easy.\nDialogue: 0,0:47:24.81,0:47:26.49,EN,,0,0,0,,Go push this button.\nDialogue: 0,0:47:27.02,0:47:28.92,EN,,0,0,0,,And then aft gets written in here again.\nDialogue: 0,0:47:31.28,0:47:32.64,EN,,0,0,0,,That means this thing moves up.\nDialogue: 0,0:47:32.64,0:47:35.19,EN,,0,0,0,,I've gotten rid of something else on my stack.\nDialogue: 0,0:47:42.24,0:47:43.47,EN,,0,0,0,,Right, then I go to here,\nDialogue: 0,0:47:43.87,0:47:47.15,EN,,0,0,0,,which says, assign to VAL the product of N and VAL.\nDialogue: 0,0:47:47.85,0:47:50.57,EN,,0,0,0,,So I push this button over here, bang.\nDialogue: 0,0:47:50.97,0:47:52.91,EN,,0,0,0,,2 times 1 gives me a 2,\nDialogue: 0,0:47:54.01,0:47:54.75,EN,,0,0,0,,get written there.\nDialogue: 0,0:47:55.76,0:47:57.20,EN,,0,0,0,,OK? Go to fetch continue.\nDialogue: 0,0:47:57.54,0:47:59.85,EN,,0,0,0,,Continue is aft. I go to aft.\nDialogue: 0,0:48:01.15,0:48:03.88,EN,,0,0,0,,OK? Aft says restore N.\nDialogue: 0,0:48:04.36,0:48:05.72,EN,,0,0,0,,Do your restore N,\nDialogue: 0,0:48:05.87,0:48:08.44,EN,,0,0,0,,means I take the value over here, which is 3,\nDialogue: 0,0:48:09.24,0:48:10.33,EN,,0,0,0,,push this up to here,\nDialogue: 0,0:48:10.60,0:48:15.50,EN,,0,0,0,,and move it into here, N.\nDialogue: 0,0:48:16.25,0:48:17.34,EN,,0,0,0,,Now it's pushing that button.\nDialogue: 0,0:48:18.01,0:48:19.90,EN,,0,0,0,,The next thing I do is restore continue.\nDialogue: 0,0:48:20.20,0:48:22.20,EN,,0,0,0,,Continue is now going to become done.\nDialogue: 0,0:48:22.83,0:48:26.78,EN,,0,0,0,,So this moves up here when I push this button.\nDialogue: 0,0:48:27.13,0:48:29.72,EN,,0,0,0,,Done may or may be there anymore,\nDialogue: 0,0:48:29.72,0:48:31.55,EN,,0,0,0,,I'm not interested, but it certainly is here.\nDialogue: 0,0:48:35.80,0:48:38.12,EN,,0,0,0,,Next thing I do is assign to VAL\nDialogue: 0,0:48:38.43,0:48:40.76,EN,,0,0,0,,the product of the fetch of N and the fetch of VAL.\nDialogue: 0,0:48:41.44,0:48:44.30,EN,,0,0,0,,That's pushing this button over here, bang.\nDialogue: 0,0:48:44.30,0:48:45.77,EN,,0,0,0,,2 times 3 is 6.\nDialogue: 0,0:48:46.52,0:48:47.87,EN,,0,0,0,,So I get a 6 over here.\nDialogue: 0,0:48:50.97,0:48:53.40,EN,,0,0,0,,OK? And go to fetch continue,\nDialogue: 0,0:48:53.48,0:48:54.83,EN,,0,0,0,,whoops, I go to done, and I'm done.\nDialogue: 0,0:48:55.02,0:48:56.09,EN,,0,0,0,,And my answer is 6,\nDialogue: 0,0:48:56.60,0:48:57.82,EN,,0,0,0,,as you can see in the VAL register.\nDialogue: 0,0:48:58.95,0:48:59.82,EN,,0,0,0,,And in fact,\nDialogue: 0,0:49:00.91,0:49:03.34,EN,,0,0,0,,the stack is in the state it originally was in.\nDialogue: 0,0:49:08.20,0:49:10.70,EN,,0,0,0,,Now there's a bit of discipline in using these things like stacks\nDialogue: 0,0:49:11.20,0:49:12.27,EN,,0,0,0,,that we have to be careful of.\nDialogue: 0,0:49:13.62,0:49:15.52,EN,,0,0,0,,And we'll see that in the next segment.\nDialogue: 0,0:49:16.26,0:49:18.46,EN,,0,0,0,,But first I want to ask if there are any questions for this.\nDialogue: 0,0:49:28.56,0:49:29.64,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:49:30.17,0:49:30.63,EN,,0,0,0,,Yes, Ron.\nDialogue: 0,0:49:30.63,0:49:33.37,EN,,0,0,0,,AUDIENCE: What happens when you roll off the end of the stack with--\nDialogue: 0,0:49:33.39,0:49:34.62,EN,,0,0,0,,PROFESSOR: What do you mean, roll off of?\nDialogue: 0,0:49:35.03,0:49:37.50,EN,,0,0,0,,AUDIENCE: Well, the largest number-- a larger starting point of N\nDialogue: 0,0:49:37.52,0:49:38.72,EN,,0,0,0,,requires more memory, correct?\nDialogue: 0,0:49:38.86,0:49:39.44,EN,,0,0,0,,PROFESSOR: Oh, yes.\nDialogue: 0,0:49:39.44,0:49:41.12,EN,,0,0,0,,Well, I need to have a long enough stack.\nDialogue: 0,0:49:41.53,0:49:43.20,EN,,0,0,0,,You say, what if I violate my illusion?\nDialogue: 0,0:49:43.84,0:49:44.12,EN,,0,0,0,,AUDIENCE: Yes.\nDialogue: 0,0:49:44.55,0:49:46.73,EN,,0,0,0,,PROFESSOR: Well, then the magic doesn't work. OK?\nDialogue: 0,0:49:47.96,0:49:51.00,EN,,0,0,0,,The truth of the matter is that every machine is finite.\nDialogue: 0,0:49:51.64,0:49:53.72,EN,,0,0,0,,And for a procedure like this,\nDialogue: 0,0:49:54.17,0:49:58.86,EN,,0,0,0,,there's a limit to the number of sub-factorials I could have.\nDialogue: 0,0:49:59.95,0:50:02.48,EN,,0,0,0,,Remember when we were doing the y-operator a while ago,\nDialogue: 0,0:50:02.80,0:50:06.22,EN,,0,0,0,,we pointed out that there was a sequence of exponentiation procedures,\nDialogue: 0,0:50:06.25,0:50:08.09,EN,,0,0,0,,each of which was a little better than the previous one.\nDialogue: 0,0:50:08.72,0:50:11.60,EN,,0,0,0,,Well, we're now seeing how we implement that mathematical idea.\nDialogue: 0,0:50:13.09,0:50:14.19,EN,,0,0,0,,The limiting process\nDialogue: 0,0:50:14.35,0:50:16.33,EN,,0,0,0,,is only so good as as far as you take the limit.\nDialogue: 0,0:50:17.99,0:50:19.42,EN,,0,0,0,,If you think about it, what am I using here?\nDialogue: 0,0:50:19.42,0:50:22.65,EN,,0,0,0,,I'm using about two chunks, pieces of memory\nDialogue: 0,0:50:23.04,0:50:27.07,EN,,0,0,0,,for iteration for every recursion of this process.\nDialogue: 0,0:50:29.10,0:50:31.71,EN,,0,0,0,,If we try to compute factorial of 10,000,\nDialogue: 0,0:50:31.72,0:50:32.81,EN,,0,0,0,,that's not a lot of memory.\nDialogue: 0,0:50:33.18,0:50:34.68,EN,,0,0,0,,On the other hand, it's an awful big number.\nDialogue: 0,0:50:35.95,0:50:38.41,EN,,0,0,0,,So the question is, is that a valuable thing in this case.\nDialogue: 0,0:50:39.18,0:50:42.19,EN,,0,0,0,,But it really turns out not to be a terrible limit,\nDialogue: 0,0:50:42.22,0:50:43.53,EN,,0,0,0,,because memory is el cheapo,\nDialogue: 0,0:50:44.16,0:50:45.34,EN,,0,0,0,,and people are pretty expensive.\nDialogue: 0,0:50:48.13,0:50:50.22,EN,,0,0,0,,OK, thank you, let's take a break.\nDialogue: 0,0:50:50.78,0:51:07.60,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:51:56.11,0:51:57.04,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:51:58.70,0:52:03.37,EN,,0,0,0,,What I've shown you now is how to do a simple iterative process\nDialogue: 0,0:52:03.69,0:52:05.31,EN,,0,0,0,,and a simple recursive process.\nDialogue: 0,0:52:05.64,0:52:08.68,EN,,0,0,0,,I just want to summarize the design of simple machines\nDialogue: 0,0:52:09.63,0:52:11.12,EN,,0,0,0,,for specific applications\nDialogue: 0,0:52:11.21,0:52:13.58,EN,,0,0,0,,by showing you a little bit more complicated design,\nDialogue: 0,0:52:13.96,0:52:17.13,EN,,0,0,0,,that of a thing that does doubly recursive Fibonacci,\nDialogue: 0,0:52:17.23,0:52:19.88,EN,,0,0,0,,because it will indicate to us, and we'll understand,\nDialogue: 0,0:52:20.04,0:52:22.68,EN,,0,0,0,,a bit about the conventions required\nDialogue: 0,0:52:22.76,0:52:25.04,EN,,0,0,0,,for making stacks operate correctly.\nDialogue: 0,0:52:26.40,0:52:27.11,EN,,0,0,0,,So let's see.\nDialogue: 0,0:52:27.11,0:52:28.27,EN,,0,0,0,,I'm just going to write down, first of all,\nDialogue: 0,0:52:28.30,0:52:29.71,EN,,0,0,0,,the program I'm going to translate.\nDialogue: 0,0:52:34.15,0:52:36.52,EN,,0,0,0,,I need a Fibonacci procedure,\nDialogue: 0,0:52:39.23,0:52:41.58,EN,,0,0,0,,it's very simple, which says, if\nDialogue: 0,0:52:44.60,0:52:48.56,EN,,0,0,0,,N is less than 2, the result is N,\nDialogue: 0,0:52:49.26,0:52:55.34,EN,,0,0,0,,otherwise it's the sum of Fib of N minus 1\nDialogue: 0,0:52:58.44,0:52:59.85,EN,,0,0,0,,and Fib of N minus 2.\nDialogue: 0,0:53:07.05,0:53:09.29,EN,,0,0,0,,That's the plan I have here.\nDialogue: 0,0:53:09.29,0:53:12.56,EN,,0,0,0,,And we're just going to write down the controller for such a machine.\nDialogue: 0,0:53:13.07,0:53:15.53,EN,,0,0,0,,We're going to assume that there are registers, N,\nDialogue: 0,0:53:15.56,0:53:19.15,EN,,0,0,0,,which holds the number we're taking Fibonacci of,\nDialogue: 0,0:53:19.82,0:53:21.80,EN,,0,0,0,,VAL, which is where the answer is going to get put,\nDialogue: 0,0:53:22.17,0:53:24.97,EN,,0,0,0,,and continue, which is the thing that's linked to the controller,\nDialogue: 0,0:53:26.11,0:53:26.81,EN,,0,0,0,,like before.\nDialogue: 0,0:53:26.96,0:53:29.21,EN,,0,0,0,,But I'm not going to draw another physical datapath,\nDialogue: 0,0:53:31.53,0:53:34.00,EN,,0,0,0,,because it's pretty much the same as the last one you've seen.\nDialogue: 0,0:53:34.36,0:53:37.84,EN,,0,0,0,,And of course, one of the most amazing things about computation\nDialogue: 0,0:53:38.75,0:53:39.88,EN,,0,0,0,,is that after a while,\nDialogue: 0,0:53:40.08,0:53:41.93,EN,,0,0,0,,you build up a little more features and a few more features,\nDialogue: 0,0:53:41.95,0:53:43.32,EN,,0,0,0,,and all of the sudden, you've got everything you need.\nDialogue: 0,0:53:44.75,0:53:47.60,EN,,0,0,0,,So it's remarkable that it just gets there so fast.\nDialogue: 0,0:53:48.17,0:53:50.84,EN,,0,0,0,,I don't need much more to make a universal computer.\nDialogue: 0,0:53:51.81,0:53:54.68,EN,,0,0,0,,But in any case, let's look at the controller for the Fibonacci thing.\nDialogue: 0,0:53:55.06,0:53:57.07,EN,,0,0,0,,First thing I want to do is\nDialogue: 0,0:53:57.32,0:54:02.52,EN,,0,0,0,,start the thing up by assign to continue\nDialogue: 0,0:54:07.13,0:54:10.28,EN,,0,0,0,,a place called done, called Fib-done here.\nDialogue: 0,0:54:14.14,0:54:15.53,EN,,0,0,0,,So that means that somewhere over here,\nDialogue: 0,0:54:15.55,0:54:18.48,EN,,0,0,0,,I'm going to have a label, Fib-done,\nDialogue: 0,0:54:19.71,0:54:21.10,EN,,0,0,0,,which is the place where I go\nDialogue: 0,0:54:21.23,0:54:22.44,EN,,0,0,0,,when I want the machine to stop.\nDialogue: 0,0:54:24.00,0:54:24.86,EN,,0,0,0,,That's what that is.\nDialogue: 0,0:54:25.92,0:54:26.89,EN,,0,0,0,,And I'm going to make up a loop.\nDialogue: 0,0:54:31.11,0:54:34.25,EN,,0,0,0,,It's a place I'm going to go to in order to start up computing a Fib.\nDialogue: 0,0:54:35.47,0:54:36.86,EN,,0,0,0,,Whatever is in N at this point,\nDialogue: 0,0:54:37.39,0:54:38.99,EN,,0,0,0,,Fibonacci will be computed of,\nDialogue: 0,0:54:39.13,0:54:42.01,EN,,0,0,0,,and we will return to the place specified by continue.\nDialogue: 0,0:54:44.80,0:54:48.40,EN,,0,0,0,,So what you're going to see here at this place,\nDialogue: 0,0:54:48.44,0:54:50.48,EN,,0,0,0,,what I want here is the contract\nDialogue: 0,0:54:50.97,0:54:54.25,EN,,0,0,0,,that says, I'm going to write this with a comment syntax,\nDialogue: 0,0:54:54.57,0:55:00.99,EN,,0,0,0,,the contract is N contains arg, the argument.\nDialogue: 0,0:55:02.10,0:55:09.82,EN,,0,0,0,,Continue is the recipient.\nDialogue: 0,0:55:13.36,0:55:14.29,EN,,0,0,0,,And that's where it is.\nDialogue: 0,0:55:15.71,0:55:18.96,EN,,0,0,0,,At this point, if I ever go to this place,\nDialogue: 0,0:55:19.24,0:55:21.04,EN,,0,0,0,,I'm expecting this to be true,\nDialogue: 0,0:55:21.52,0:55:23.32,EN,,0,0,0,,the argument for computing the Fibonacci.\nDialogue: 0,0:55:24.82,0:55:26.83,EN,,0,0,0,,Now the next thing I want to do is to branch.\nDialogue: 0,0:55:30.22,0:55:32.22,EN,,0,0,0,,And if N is less than 2--\nDialogue: 0,0:55:35.07,0:55:37.44,EN,,0,0,0,,by the way, I'm using what looks like Lisp syntax.\nDialogue: 0,0:55:38.73,0:55:39.63,EN,,0,0,0,,This is not Lisp.\nDialogue: 0,0:55:41.31,0:55:42.38,EN,,0,0,0,,This does not run.\nDialogue: 0,0:55:42.75,0:55:45.47,EN,,0,0,0,,What I'm writing here does not run as a simple Lisp program.\nDialogue: 0,0:55:46.12,0:55:49.31,EN,,0,0,0,,This is a representation of another language.\nDialogue: 0,0:55:49.71,0:55:52.25,EN,,0,0,0,,The reason I'm using the syntax of parentheses and so on\nDialogue: 0,0:55:52.40,0:55:54.70,EN,,0,0,0,,is because I tend to use a Lisp system\nDialogue: 0,0:55:55.32,0:55:57.34,EN,,0,0,0,,to write an interpreter for this\nDialogue: 0,0:55:57.82,0:55:59.18,EN,,0,0,0,,which allows me to simulate\nDialogue: 0,0:55:59.29,0:56:00.91,EN,,0,0,0,,the machine I'm trying to build.\nDialogue: 0,0:56:03.38,0:56:06.24,EN,,0,0,0,,I don't want to confuse this to think that this is Lisp code.\nDialogue: 0,0:56:06.94,0:56:08.60,EN,,0,0,0,,It's just I'm using a lot of the pieces of Lisp.\nDialogue: 0,0:56:09.51,0:56:10.84,EN,,0,0,0,,I'm embedding a language in Lisp,\nDialogue: 0,0:56:11.02,0:56:12.44,EN,,0,0,0,,using Lisp as pieces\nDialogue: 0,0:56:12.72,0:56:15.12,EN,,0,0,0,,to make my process of making my simulator easy.\nDialogue: 0,0:56:16.62,0:56:18.56,EN,,0,0,0,,So I'm inheriting from Lisp all of its properties.\nDialogue: 0,0:56:19.10,0:56:21.53,EN,,0,0,0,,Fetch of N 2,\nDialogue: 0,0:56:21.77,0:56:23.72,EN,,0,0,0,,I want to go to a place called immediate answer.\nDialogue: 0,0:56:26.20,0:56:27.29,EN,,0,0,0,,It's the base step.\nDialogue: 0,0:56:33.15,0:56:34.35,EN,,0,0,0,,Now, that's somewhere over here,\nDialogue: 0,0:56:35.92,0:56:36.89,EN,,0,0,0,,just above done.\nDialogue: 0,0:56:37.75,0:56:38.64,EN,,0,0,0,,And we'll see it later.\nDialogue: 0,0:56:39.42,0:56:40.70,EN,,0,0,0,,Now, in the general case,\nDialogue: 0,0:56:40.72,0:56:42.44,EN,,0,0,0,,which is the part I'm going to write down now,\nDialogue: 0,0:56:43.13,0:56:44.19,EN,,0,0,0,,let's just do it.\nDialogue: 0,0:56:44.91,0:56:48.20,EN,,0,0,0,,Well, first of all, I'm going to have to call Fibonacci twice.\nDialogue: 0,0:56:49.42,0:56:52.54,EN,,0,0,0,,In each case-- well, in one case at least,\nDialogue: 0,0:56:52.78,0:56:53.95,EN,,0,0,0,,I'm going to have to know what to do\nDialogue: 0,0:56:53.96,0:56:55.36,EN,,0,0,0,,to come back and do the next one.\nDialogue: 0,0:56:56.31,0:56:58.36,EN,,0,0,0,,I have to remember,\nDialogue: 0,0:56:59.20,0:57:01.23,EN,,0,0,0,,have I done the first Fib,\nDialogue: 0,0:57:01.26,0:57:02.54,EN,,0,0,0,,or have I done the second one?\nDialogue: 0,0:57:04.50,0:57:07.04,EN,,0,0,0,,Do I have to come back to the place where I do the second Fib,\nDialogue: 0,0:57:07.07,0:57:09.08,EN,,0,0,0,,or do I have to come back to the place where I do the add?\nDialogue: 0,0:57:10.12,0:57:12.11,EN,,0,0,0,,In both cases I going to need, I don't\nDialogue: 0,0:57:12.14,0:57:14.46,EN,,0,0,0,,In the first case, over the first Fibonacci,\nDialogue: 0,0:57:14.51,0:57:16.98,EN,,0,0,0,,I'm going to need the value of N for computing for the second one.\nDialogue: 0,0:57:19.84,0:57:21.58,EN,,0,0,0,,So I have to store some of these things up.\nDialogue: 0,0:57:23.36,0:57:24.89,EN,,0,0,0,,So first I'm going to save continue.\nDialogue: 0,0:57:26.19,0:57:27.32,EN,,0,0,0,,That's who needs the answer.\nDialogue: 0,0:57:31.32,0:57:32.46,EN,,0,0,0,,And the reason I'm doing that\nDialogue: 0,0:57:32.48,0:57:34.20,EN,,0,0,0,,is because I'm about to assign continue\nDialogue: 0,0:57:40.11,0:57:44.32,EN,,0,0,0,,to the place which is the place I want to go to after.\nDialogue: 0,0:57:46.83,0:57:50.27,EN,,0,0,0,,Let's call it Fib-N-minus-1,\nDialogue: 0,0:57:51.04,0:57:53.76,EN,,0,0,0,,big long name, classic Lisp name.\nDialogue: 0,0:57:57.36,0:58:00.22,EN,,0,0,0,,Because I'm going to compute the first Fib of N minus 1,\nDialogue: 0,0:58:00.84,0:58:01.72,EN,,0,0,0,,and then after that,\nDialogue: 0,0:58:01.72,0:58:03.29,EN,,0,0,0,,I want to come back and do something else.\nDialogue: 0,0:58:03.96,0:58:06.52,EN,,0,0,0,,That's the place I want to go to after I've done\nDialogue: 0,0:58:07.55,0:58:09.48,EN,,0,0,0,,the first Fibonacci calculation.\nDialogue: 0,0:58:11.52,0:58:13.13,EN,,0,0,0,,And I want to do a save of N,\nDialogue: 0,0:58:14.41,0:58:17.26,EN,,0,0,0,,because I'm going to need it later, after that.\nDialogue: 0,0:58:19.13,0:58:20.54,EN,,0,0,0,,Now I'm going to, at this point,\nDialogue: 0,0:58:20.67,0:58:22.84,EN,,0,0,0,,get ready to do the Fibonacci of N minus 1.\nDialogue: 0,0:58:23.02,0:58:33.95,EN,,0,0,0,,So assign to N the difference of the fetch of N and 1.\nDialogue: 0,0:58:38.11,0:58:40.27,EN,,0,0,0,,Now I'm ready to go back to doing the Fib loop.\nDialogue: 0,0:58:47.18,0:58:49.87,EN,,0,0,0,,Do I have... Have I satisfied my contract?\nDialogue: 0,0:58:50.40,0:58:51.50,EN,,0,0,0,,And the answer is yes.\nDialogue: 0,0:58:51.77,0:58:55.12,EN,,0,0,0,,N contains N minus 1, which is what I need.\nDialogue: 0,0:58:56.43,0:59:00.09,EN,,0,0,0,,OK? Continue contains a place I want to go to when I'm done\nDialogue: 0,0:59:01.28,0:59:03.07,EN,,0,0,0,,with calculating FIB N minus 1.\nDialogue: 0,0:59:04.10,0:59:05.44,EN,,0,0,0,,So I've satisfied the contract.\nDialogue: 0,0:59:05.44,0:59:09.02,EN,,0,0,0,,And therefore, I can write down here a tag, after, a label,\nDialogue: 0,0:59:11.47,0:59:17.56,EN,,0,0,0,,after-Fib-N-minus-1.\nDialogue: 0,0:59:20.49,0:59:21.63,EN,,0,0,0,,Now what am I going to do here?\nDialogue: 0,0:59:22.69,0:59:23.61,EN,,0,0,0,,Here's a place\nDialogue: 0,0:59:23.95,0:59:26.75,EN,,0,0,0,,where I now have to get ready to do Fib of N minus 2.\nDialogue: 0,0:59:29.27,0:59:30.72,EN,,0,0,0,,But in order to do a Fib of N minus 2,\nDialogue: 0,0:59:30.75,0:59:31.63,EN,,0,0,0,,look, I don't know.\nDialogue: 0,0:59:31.78,0:59:33.40,EN,,0,0,0,,I've clobbered my N over here.\nDialogue: 0,0:59:33.81,0:59:35.47,EN,,0,0,0,,And presumably my N is counted down\nDialogue: 0,0:59:37.85,0:59:38.80,EN,,0,0,0,,all the way to 1 or 0 or something at this point.\nDialogue: 0,0:59:39.78,0:59:42.51,EN,,0,0,0,,So I don't know what the value of N in the N register is.\nDialogue: 0,0:59:43.03,0:59:44.75,EN,,0,0,0,,I want the value of N that was on the stack\nDialogue: 0,0:59:44.80,0:59:46.00,EN,,0,0,0,,that I saved over here\nDialogue: 0,0:59:46.17,0:59:47.88,EN,,0,0,0,,so that could restore it over here.\nDialogue: 0,0:59:49.52,0:59:51.02,EN,,0,0,0,,I saved up the value of N,\nDialogue: 0,0:59:51.15,0:59:54.49,EN,,0,0,0,,which is this value of N at this point,\nDialogue: 0,0:59:54.89,0:59:57.37,EN,,0,0,0,,so that I could restore it after computing Fib of N minus 1,\nDialogue: 0,0:59:57.53,0:59:59.36,EN,,0,0,0,,so that I could count that down to N minus 2\nDialogue: 0,0:59:59.39,1:00:00.86,EN,,0,0,0,,and then compute Fib of N minus 2.\nDialogue: 0,1:00:01.81,1:00:02.75,EN,,0,0,0,,So let's restore that.\nDialogue: 0,1:00:08.83,1:00:09.77,EN,,0,0,0,,Restore of N.\nDialogue: 0,1:00:11.13,1:00:15.98,EN,,0,0,0,,Now I'm about to do something which is superstitious,\nDialogue: 0,1:00:16.00,1:00:17.40,EN,,0,0,0,,and we will remove it shortly.\nDialogue: 0,1:00:18.52,1:00:20.48,EN,,0,0,0,,I am about to finish the sequence\nDialogue: 0,1:00:20.59,1:00:23.44,EN,,0,0,0,,of doing the subroutine call, if you will.\nDialogue: 0,1:00:24.80,1:00:25.95,EN,,0,0,0,,I'm going to say, well,\nDialogue: 0,1:00:26.06,1:00:27.90,EN,,0,0,0,,I also saved up the continuation,\nDialogue: 0,1:00:28.48,1:00:30.43,EN,,0,0,0,,since I'm going to restore it now.\nDialogue: 0,1:00:31.60,1:00:32.60,EN,,0,0,0,,But actually, I don't have to,\nDialogue: 0,1:00:32.64,1:00:33.55,EN,,0,0,0,,because I'm not going to need it.\nDialogue: 0,1:00:34.61,1:00:35.72,EN,,0,0,0,,We'll fix that in a second.\nDialogue: 0,1:00:36.26,1:00:37.95,EN,,0,0,0,,So we'll do a restore of continue,\nDialogue: 0,1:00:46.04,1:00:48.02,EN,,0,0,0,,which is what I would in general need to do.\nDialogue: 0,1:00:48.02,1:00:49.23,EN,,0,0,0,,And we're just going to see whats called\nDialogue: 0,1:00:49.31,1:00:52.14,EN,,0,0,0,,what you would call in the compiler world a peephole optimization,\nDialogue: 0,1:00:52.27,1:00:53.72,EN,,0,0,0,,which says, whoops, you didn't have to do that.\nDialogue: 0,1:00:55.42,1:00:57.10,EN,,0,0,0,,OK, so the next thing I see here\nDialogue: 0,1:00:58.46,1:01:02.28,EN,,0,0,0,,is that I have to get ready now to do Fibonacci of N minus 2.\nDialogue: 0,1:01:02.77,1:01:04.49,EN,,0,0,0,,But I don't have to save N anymore.\nDialogue: 0,1:01:05.05,1:01:06.72,EN,,0,0,0,,The reason why I don't have to save N anymore\nDialogue: 0,1:01:06.80,1:01:09.34,EN,,0,0,0,,is because I don't need N after I've done Fib of N minus 2,\nDialogue: 0,1:01:09.36,1:01:10.72,EN,,0,0,0,,because the next thing I do is add.\nDialogue: 0,1:01:13.54,1:01:15.85,EN,,0,0,0,,So I'm just going to set up my N that way.\nDialogue: 0,1:01:16.60,1:01:28.99,EN,,0,0,0,,Assign N minus difference of fetch N and 2.\nDialogue: 0,1:01:31.85,1:01:34.01,EN,,0,0,0,,Now I have to finish the setup\nDialogue: 0,1:01:34.27,1:01:36.73,EN,,0,0,0,,for calling Fibonacci of N minus 2.\nDialogue: 0,1:01:36.95,1:01:38.33,EN,,0,0,0,,Well, I have to save up continue\nDialogue: 0,1:01:44.22,1:01:49.02,EN,,0,0,0,,and assign continue, continue,\nDialogue: 0,1:01:52.30,1:01:59.95,EN,,0,0,0,,to the place which is after Fib N 2,\nDialogue: 0,1:02:02.57,1:02:04.03,EN,,0,0,0,,that place over here somewhere.\nDialogue: 0,1:02:05.32,1:02:07.23,EN,,0,0,0,,However, I've got to be very careful.\nDialogue: 0,1:02:08.65,1:02:11.42,EN,,0,0,0,,The old value, the value of Fib of N minus 1,\nDialogue: 0,1:02:12.06,1:02:13.12,EN,,0,0,0,,I'm going to need later.\nDialogue: 0,1:02:15.30,1:02:17.37,EN,,0,0,0,,The value of Fibonacci of N minus 1,\nDialogue: 0,1:02:17.61,1:02:18.48,EN,,0,0,0,,I'm going to need.\nDialogue: 0,1:02:18.78,1:02:19.80,EN,,0,0,0,,And I can't clobber it,\nDialogue: 0,1:02:21.07,1:02:23.60,EN,,0,0,0,,because I'm going to have to add it to the value of Fib of N minus 2.\nDialogue: 0,1:02:24.15,1:02:25.88,EN,,0,0,0,,That's in the value register, so I'm going to save it.\nDialogue: 0,1:02:27.79,1:02:32.60,EN,,0,0,0,,So I have to save this right now, save up VAL.\nDialogue: 0,1:02:33.78,1:02:35.44,EN,,0,0,0,,And now I can go off to my subroutine,\nDialogue: 0,1:02:36.67,1:02:39.54,EN,,0,0,0,,go to Fib loop.\nDialogue: 0,1:02:44.22,1:02:46.57,EN,,0,0,0,,Now before I go any further\nDialogue: 0,1:02:46.80,1:02:49.36,EN,,0,0,0,,and finish this program,\nDialogue: 0,1:02:49.39,1:02:51.05,EN,,0,0,0,,I just want to look at this segment so far\nDialogue: 0,1:02:51.23,1:02:56.00,EN,,0,0,0,,and see, oh yes, there's a sequence of instructions here, if you will\nDialogue: 0,1:02:57.84,1:02:59.08,EN,,0,0,0,,that I can do something about.\nDialogue: 0,1:03:01.58,1:03:03.20,EN,,0,0,0,,Here I have a restore of continue,\nDialogue: 0,1:03:04.25,1:03:05.48,EN,,0,0,0,,a save of continue,\nDialogue: 0,1:03:06.01,1:03:07.40,EN,,0,0,0,,and then an assign of continue,\nDialogue: 0,1:03:08.70,1:03:10.64,EN,,0,0,0,,with no other references to continue in between.\nDialogue: 0,1:03:13.84,1:03:15.48,EN,,0,0,0,,The restore followed by the save\nDialogue: 0,1:03:15.50,1:03:16.67,EN,,0,0,0,,leaves the stack unchanged.\nDialogue: 0,1:03:19.09,1:03:21.72,EN,,0,0,0,,The only difference is that I set the continue register to a value,\nDialogue: 0,1:03:21.96,1:03:23.28,EN,,0,0,0,,which is the value that was on the stack.\nDialogue: 0,1:03:24.33,1:03:25.79,EN,,0,0,0,,Since I now clobber that value,\nDialogue: 0,1:03:26.44,1:03:27.93,EN,,0,0,0,,as in it was never referenced,\nDialogue: 0,1:03:28.59,1:03:30.09,EN,,0,0,0,,these instructions are unnecessary.\nDialogue: 0,1:03:31.76,1:03:35.39,EN,,0,0,0,,So we will remove these.\nDialogue: 0,1:03:38.88,1:03:40.78,EN,,0,0,0,,But I couldn't have seen that unless I had written them down.\nDialogue: 0,1:03:43.78,1:03:44.72,EN,,0,0,0,,Was that really true?\nDialogue: 0,1:03:45.77,1:03:46.60,EN,,0,0,0,,Well, I don't know.\nDialogue: 0,1:03:48.61,1:03:52.91,EN,,0,0,0,,OK, so we've now gone off to compute Fibonacci of N minus 2.\nDialogue: 0,1:03:53.66,1:03:54.59,EN,,0,0,0,,So after that,\nDialogue: 0,1:04:02.96,1:04:03.85,EN,,0,0,0,,what are we going to do?\nDialogue: 0,1:04:05.07,1:04:06.76,EN,,0,0,0,,Well, I suppose the first thing we have to do--\nDialogue: 0,1:04:06.99,1:04:07.88,EN,,0,0,0,,we've got two things.\nDialogue: 0,1:04:07.96,1:04:10.49,EN,,0,0,0,,We've got a thing in the value register which is now valuable.\nDialogue: 0,1:04:10.92,1:04:11.98,EN,,0,0,0,,We also have a thing on the stack\nDialogue: 0,1:04:12.04,1:04:13.63,EN,,0,0,0,,can be restored into the value register.\nDialogue: 0,1:04:14.81,1:04:16.57,EN,,0,0,0,,And what I have to be careful with now\nDialogue: 0,1:04:16.88,1:04:18.99,EN,,0,0,0,,is I want to shuffle this right so I can do the multiply.\nDialogue: 0,1:04:19.47,1:04:21.24,EN,,0,0,0,,Now there are various conventions I might use,\nDialogue: 0,1:04:21.47,1:04:23.52,EN,,0,0,0,,but I'm going to be very picky and say,\nDialogue: 0,1:04:23.55,1:04:25.88,EN,,0,0,0,,I'm only going to restore into a register I've saved from.\nDialogue: 0,1:04:26.74,1:04:28.28,EN,,0,0,0,,If that's the case, I have to do a shuffle here.\nDialogue: 0,1:04:29.24,1:04:31.84,EN,,0,0,0,,It's the same problem with how many hands I have.\nDialogue: 0,1:04:32.68,1:04:37.13,EN,,0,0,0,,So I'm going to assign to N,\nDialogue: 0,1:04:37.16,1:04:39.37,EN,,0,0,0,,because I'm not going to need N anymore, N is useless,\nDialogue: 0,1:04:39.92,1:04:41.21,EN,,0,0,0,,the current value of VAL,\nDialogue: 0,1:04:45.21,1:04:47.34,EN,,0,0,0,,which was the value of Fib of N minus 2.\nDialogue: 0,1:04:52.95,1:04:56.35,EN,,0,0,0,,And I'm going to restore the value register now.\nDialogue: 0,1:05:01.85,1:05:03.92,EN,,0,0,0,,This restore matches this save.\nDialogue: 0,1:05:05.58,1:05:08.83,EN,,0,0,0,,And if you're very careful and examine very carefully what goes on,\nDialogue: 0,1:05:09.21,1:05:11.96,EN,,0,0,0,,OK? restores and saves are always matched.\nDialogue: 0,1:05:13.84,1:05:15.15,EN,,0,0,0,,Now there's an outstanding save,\nDialogue: 0,1:05:15.18,1:05:16.38,EN,,0,0,0,,of course, that we have to get rid of soon.\nDialogue: 0,1:05:19.00,1:05:20.59,EN,,0,0,0,,And so I restored the value register.\nDialogue: 0,1:05:20.94,1:05:22.57,EN,,0,0,0,,Now I restore the continue one,\nDialogue: 0,1:05:31.15,1:05:32.40,EN,,0,0,0,,which matches this one,\nDialogue: 0,1:05:34.80,1:05:37.85,EN,,0,0,0,,dot, dot, dot, dot, dot, dot, dot, down to here,\nDialogue: 0,1:05:40.59,1:05:42.46,EN,,0,0,0,,Now restoring that continuation.\nDialogue: 0,1:05:42.86,1:05:45.71,EN,,0,0,0,,That continuation is a continuation of Fib of N,\nDialogue: 0,1:05:46.46,1:05:47.84,EN,,0,0,0,,which is the problem I was trying to solve,\nDialogue: 0,1:05:47.85,1:05:49.32,EN,,0,0,0,,a major problem I'm trying to solve.\nDialogue: 0,1:05:49.98,1:05:52.35,EN,,0,0,0,,So that's the guy I have to go back to who wants Fib of N.\nDialogue: 0,1:05:52.54,1:05:54.03,EN,,0,0,0,,I saved them all the way up here\nDialogue: 0,1:05:54.16,1:05:56.60,EN,,0,0,0,,when I realized N was not less than 2.\nDialogue: 0,1:05:57.36,1:05:59.07,EN,,0,0,0,,And so I had to do a complicated operation.\nDialogue: 0,1:06:00.84,1:06:02.57,EN,,0,0,0,,Now I've got everything I need to do it.\nDialogue: 0,1:06:03.24,1:06:04.36,EN,,0,0,0,,So I'm going to restore that,\nDialogue: 0,1:06:05.42,1:06:21.08,EN,,0,0,0,,assign to VAL the sum of fetch VAL and fetch of N\nDialogue: 0,1:06:27.44,1:06:28.60,EN,,0,0,0,,and go to continue.\nDialogue: 0,1:06:38.26,1:06:44.78,EN,,0,0,0,,So now I've returned from computing Fibonacci of N,\nDialogue: 0,1:06:45.39,1:06:46.57,EN,,0,0,0,,the general case.\nDialogue: 0,1:06:47.11,1:06:50.60,EN,,0,0,0,,Now what's left is we have to fix up a few details,\nDialogue: 0,1:06:50.99,1:06:55.53,EN,,0,0,0,,like there's the base case of this induction, immediate answer,\nDialogue: 0,1:07:02.54,1:07:06.59,EN,,0,0,0,,as, which is nothing more than\nDialogue: 0,1:07:06.60,1:07:11.85,EN,,0,0,0,,assign to VAL fetch of N,\nDialogue: 0,1:07:13.64,1:07:15.47,EN,,0,0,0,,because N was less than 2,\nDialogue: 0,1:07:15.50,1:07:16.89,EN,,0,0,0,,and therefore, the answer is N\nDialogue: 0,1:07:16.99,1:07:18.19,EN,,0,0,0,,in our original program,\nDialogue: 0,1:07:19.23,1:07:26.48,EN,,0,0,0,,and return continue--\nDialogue: 0,1:07:31.24,1:07:36.13,EN,,0,0,0,,bobble, bobble almost-- and finally Fib done.\nDialogue: 0,1:07:43.46,1:07:45.64,EN,,0,0,0,,So that's a fairly complicated program.\nDialogue: 0,1:07:45.64,1:07:47.34,EN,,0,0,0,,And the reason I wanted you see to that\nDialogue: 0,1:07:47.50,1:07:49.21,EN,,0,0,0,,is because I want you to see the particular\nDialogue: 0,1:07:49.45,1:07:52.67,EN,,0,0,0,,flavors of stack discipline that I was obeying.\nDialogue: 0,1:07:53.32,1:07:55.21,EN,,0,0,0,,It was first of all, I don't want to save anything\nDialogue: 0,1:07:56.92,1:07:58.12,EN,,0,0,0,,that I'm not going to need later.\nDialogue: 0,1:08:00.57,1:08:01.85,EN,,0,0,0,,I was being very careful.\nDialogue: 0,1:08:01.85,1:08:02.91,EN,,0,0,0,,And it's very important.\nDialogue: 0,1:08:03.94,1:08:06.52,EN,,0,0,0,,And there are all sorts of other disciplines people make\nDialogue: 0,1:08:07.37,1:08:09.61,EN,,0,0,0,,with frames and things like that of some sort,\nDialogue: 0,1:08:10.19,1:08:11.39,EN,,0,0,0,,where you save all sorts of junk\nDialogue: 0,1:08:11.40,1:08:12.64,EN,,0,0,0,,you're not going to need later and restore it\nDialogue: 0,1:08:12.67,1:08:15.26,EN,,0,0,0,,because, in some sense, it's easier to do that.\nDialogue: 0,1:08:15.83,1:08:17.40,EN,,0,0,0,,That's going to lead to various disasters,\nDialogue: 0,1:08:18.59,1:08:20.25,EN,,0,0,0,,which we'll see a little later.\nDialogue: 0,1:08:21.44,1:08:24.24,EN,,0,0,0,,It's crucial to save exactly what you're going to need later.\nDialogue: 0,1:08:26.89,1:08:28.01,EN,,0,0,0,,It's an important idea.\nDialogue: 0,1:08:29.87,1:08:33.36,EN,,0,0,0,,And the responsibility of that is whoever saves something\nDialogue: 0,1:08:33.76,1:08:35.32,EN,,0,0,0,,is the guy who restores it, because he needs it.\nDialogue: 0,1:08:36.93,1:08:38.54,EN,,0,0,0,,And in such discipline,\nDialogue: 0,1:08:38.86,1:08:40.76,EN,,0,0,0,,you can see what things are unnecessary,\nDialogue: 0,1:08:43.45,1:08:44.73,EN,,0,0,0,,operations that are unimportant.\nDialogue: 0,1:08:47.15,1:08:50.40,EN,,0,0,0,,Now, one other thing I want to tell you about is very simple\nDialogue: 0,1:08:51.66,1:08:54.67,EN,,0,0,0,,is that, of course, the picture you see is not the whole picture.\nDialogue: 0,1:08:55.35,1:08:56.68,EN,,0,0,0,,Supposing I had systems\nDialogue: 0,1:08:56.80,1:09:01.52,EN,,0,0,0,,had things like other operations, CAR, CDR, CONS,\nDialogue: 0,1:09:03.53,1:09:05.60,EN,,0,0,0,,building a vector\nDialogue: 0,1:09:05.88,1:09:07.32,EN,,0,0,0,,and referencing the nth element of it,\nDialogue: 0,1:09:08.30,1:09:09.21,EN,,0,0,0,,or things like that.\nDialogue: 0,1:09:10.40,1:09:13.60,EN,,0,0,0,,Well, at this level of detail, whatever it is,\nDialogue: 0,1:09:13.87,1:09:17.85,EN,,0,0,0,,we can conceptualize those as primitive operations in the datapath.\nDialogue: 0,1:09:18.75,1:09:21.95,EN,,0,0,0,,In other words, we could say that some machine that, for example, has\nDialogue: 0,1:09:22.32,1:09:24.11,EN,,0,0,0,,has the append machine,\nDialogue: 0,1:09:24.20,1:09:26.46,EN,,0,0,0,,which has to do cons of the CAR of x\nDialogue: 0,1:09:26.64,1:09:29.80,EN,,0,0,0,,with the append of the CDR of x and y,\nDialogue: 0,1:09:29.88,1:09:33.18,EN,,0,0,0,,well, gee, that's exactly the same as the factorial structure.\nDialogue: 0,1:09:33.63,1:09:35.29,EN,,0,0,0,,Well, it's got about the same structure.\nDialogue: 0,1:09:36.54,1:09:37.27,EN,,0,0,0,,And what do we have?\nDialogue: 0,1:09:37.27,1:09:39.39,EN,,0,0,0,,We have some sort of things in it\nDialogue: 0,1:09:39.76,1:09:42.48,EN,,0,0,0,,which may be registers, x and y,\nDialogue: 0,1:09:42.51,1:09:45.12,EN,,0,0,0,,and then x has to somehow move to y sometimes,\nDialogue: 0,1:09:45.28,1:09:46.75,EN,,0,0,0,,x has to get the value of y.\nDialogue: 0,1:09:46.93,1:09:50.11,EN,,0,0,0,,And then we may have to be able to do something which is a cons.\nDialogue: 0,1:09:51.70,1:09:57.74,EN,,0,0,0,,I don't remember if I need to like this is in this system,\nDialogue: 0,1:09:57.76,1:10:01.10,EN,,0,0,0,,but cons is sort of like subtract or add or something.\nDialogue: 0,1:10:01.42,1:10:02.70,EN,,0,0,0,,It combines two things,\nDialogue: 0,1:10:02.73,1:10:04.27,EN,,0,0,0,,producing a thing which is the cons,\nDialogue: 0,1:10:04.51,1:10:06.49,EN,,0,0,0,,which we may then think goes into there.\nDialogue: 0,1:10:07.60,1:10:09.72,EN,,0,0,0,,And then maybe a thing called the CAR,\nDialogue: 0,1:10:12.88,1:10:16.22,EN,,0,0,0,,which will produce-- I can get the CAR or something.\nDialogue: 0,1:10:16.92,1:10:19.55,EN,,0,0,0,,And maybe I can get the CDR of something, and so on.\nDialogue: 0,1:10:20.15,1:10:22.30,EN,,0,0,0,,But we shouldn't be too afraid of saying things this way,\nDialogue: 0,1:10:22.92,1:10:24.24,EN,,0,0,0,,because the worst that could happen\nDialogue: 0,1:10:24.94,1:10:26.41,EN,,0,0,0,,is if we open up cons,\nDialogue: 0,1:10:27.31,1:10:29.82,EN,,0,0,0,,what we're going to find is some machine.\nDialogue: 0,1:10:31.88,1:10:34.44,EN,,0,0,0,,And cons may in fact overlap with CAR and CDR, and it always does,\nDialogue: 0,1:10:35.50,1:10:38.12,EN,,0,0,0,,in the same way that plus and minus overlap,\nDialogue: 0,1:10:38.57,1:10:39.85,EN,,0,0,0,,and really the same business.\nDialogue: 0,1:10:41.21,1:10:42.60,EN,,0,0,0,,CONS, CAR, and CDR are going to overlap,\nDialogue: 0,1:10:42.62,1:10:44.52,EN,,0,0,0,,and we're going to find a little controller,\nDialogue: 0,1:10:45.50,1:10:46.54,EN,,0,0,0,,a little datapath,\nDialogue: 0,1:10:48.03,1:10:49.64,EN,,0,0,0,,which may have some registers in it,\nDialogue: 0,1:10:50.00,1:10:52.86,EN,,0,0,0,,some stuff like that.\nDialogue: 0,1:10:53.30,1:10:54.41,EN,,0,0,0,,And maybe inside it,\nDialogue: 0,1:10:54.43,1:10:56.16,EN,,0,0,0,,there may also be an infinite part,\nDialogue: 0,1:10:56.46,1:10:58.70,EN,,0,0,0,,a part that's semi-infinite or something,\nDialogue: 0,1:10:58.81,1:11:00.65,EN,,0,0,0,,which is a lot of very uniform stuff,\nDialogue: 0,1:11:00.96,1:11:02.03,EN,,0,0,0,,which we'll call memory.\nDialogue: 0,1:11:06.57,1:11:08.83,EN,,0,0,0,,And I wouldn't be so horrified if that were the way it works.\nDialogue: 0,1:11:09.33,1:11:11.07,EN,,0,0,0,,In fact, it does, and we'll talk about that later.\nDialogue: 0,1:11:13.32,1:11:14.57,EN,,0,0,0,,So are there any questions?\nDialogue: 0,1:11:24.34,1:11:25.80,EN,,0,0,0,,Gee, what an unquestioning audience.\nDialogue: 0,1:11:28.67,1:11:30.33,EN,,0,0,0,,Suppose I tell you a horrible pile of lies.\nDialogue: 0,1:11:39.69,1:11:40.38,EN,,0,0,0,,OK.\nDialogue: 0,1:11:41.99,1:11:42.52,EN,,0,0,0,,Well, thank you.\nDialogue: 0,1:11:42.52,1:11:43.28,EN,,0,0,0,,Let's take our break.\nDialogue: 0,0:00:00.03,0:00:02.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP 学习小组\\N倾情制作\nDialogue: 0,0:00:02.04,0:00:09.09,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.21,0:00:13.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}寄存机器\nDialogue: 0,0:00:17.26,0:00:19.07,Default,,0,0,0,,教授：我认为 到目前为止\nDialogue: 0,0:00:19.32,0:00:23.93,Default,,0,0,0,,我们已经学习了很多关于\nDialogue: 0,0:00:24.09,0:00:28.83,Default,,0,0,0,,组织程序以及操纵符号的技术\nDialogue: 0,0:00:30.84,0:00:35.60,Default,,0,0,0,,以及用来构建语言的技术\nDialogue: 0,0:00:35.63,0:00:36.78,Default,,0,0,0,,用一门语言去创建另一门语言\nDialogue: 0,0:00:37.10,0:00:39.92,Default,,0,0,0,,这在组织大型程序时非常有用\nDialogue: 0,0:00:39.96,0:00:42.30,Default,,0,0,0,,实际上 我所知的最好的程序\nDialogue: 0,0:00:42.44,0:00:44.43,Default,,0,0,0,,看起来更像是一堆语言\nDialogue: 0,0:00:44.91,0:00:47.96,Default,,0,0,0,,而不是将问题分解成若干部分\nDialogue: 0,0:00:49.90,0:00:51.45,Default,,0,0,0,,我想 此时此刻\nDialogue: 0,0:00:52.08,0:00:53.58,Default,,0,0,0,,关于这类东西的工作方式\nDialogue: 0,0:00:53.61,0:00:55.32,Default,,0,0,0,,仍然存在一些谜团\nDialogue: 0,0:00:56.26,0:00:59.68,Default,,0,0,0,,因此 我现在需要\nDialogue: 0,0:01:00.03,0:01:02.60,Default,,0,0,0,,偏离原先的计划\nDialogue: 0,0:01:02.96,0:01:05.42,Default,,0,0,0,,不再继续讲解如何组织大型程序\nDialogue: 0,0:01:05.45,0:01:08.19,Default,,0,0,0,,而是告诉你一些关于\nDialogue: 0,0:01:08.52,0:01:11.71,Default,,0,0,0,,使这些事情可以起作用的机制\nDialogue: 0,0:01:12.19,0:01:14.83,Default,,0,0,0,,这样做的主要是为了\nDialogue: 0,0:01:15.80,0:01:17.87,Default,,0,0,0,,揭秘\nDialogue: 0,0:01:18.65,0:01:20.54,Default,,0,0,0,,剩下的很多谜团\nDialogue: 0,0:01:21.08,0:01:25.48,Default,,0,0,0,,比如说 如何控制程序的运行\nDialogue: 0,0:01:26.08,0:01:30.38,Default,,0,0,0,,计算机如何知晓下一步的动作\nDialogue: 0,0:01:30.52,0:01:31.74,Default,,0,0,0,,等等等等\nDialogue: 0,0:01:32.43,0:01:35.56,Default,,0,0,0,,我现在就要让你们清楚地知道\nDialogue: 0,0:01:35.85,0:01:39.10,Default,,0,0,0,,就算你之前没有使用过计算机\nDialogue: 0,0:01:39.56,0:01:43.50,Default,,0,0,0,,但这种机制非常简单\nDialogue: 0,0:01:44.33,0:01:46.35,Default,,0,0,0,,你可以毫无问题地理解它\nDialogue: 0,0:01:47.65,0:01:51.24,Default,,0,0,0,,好吧 我们先来想象一个 --\nDialogue: 0,0:01:51.32,0:01:52.91,Default,,0,0,0,,先说明一下 我们采用的方法是\nDialogue: 0,0:01:52.96,0:01:55.80,Default,,0,0,0,,把一些非常简单的Lisp程序\nDialogue: 0,0:01:56.54,0:01:58.12,Default,,0,0,0,,真的非常简单\nDialogue: 0,0:01:59.04,0:02:00.62,Default,,0,0,0,,把它们转换成硬件\nDialogue: 0,0:02:02.16,0:02:04.16,Default,,0,0,0,,我不会考虑一些中间步骤\nDialogue: 0,0:02:04.70,0:02:07.45,Default,,0,0,0,,比如转换成某种现有的机器语言\nDialogue: 0,0:02:07.47,0:02:09.05,Default,,0,0,0,,然后来解释计算机是如何工作的\nDialogue: 0,0:02:09.82,0:02:12.00,Default,,0,0,0,,因为那不太明显\nDialogue: 0,0:02:12.75,0:02:14.17,Default,,0,0,0,,所以我真正要向你展示的是\nDialogue: 0,0:02:14.51,0:02:17.48,Default,,0,0,0,,如何构建一台机器来完成\nDialogue: 0,0:02:18.03,0:02:22.04,Default,,0,0,0,,一项由你写的程序所描述的工作\nDialogue: 0,0:02:22.04,0:02:24.03,Default,,0,0,0,,而程序呢 实际上就是一个机器的描述\nDialogue: 0,0:02:25.76,0:02:27.69,Default,,0,0,0,,我们从一个非常简单的程序开始\nDialogue: 0,0:02:28.09,0:02:30.81,Default,,0,0,0,,然后演示一些简单的机制\nDialogue: 0,0:02:31.39,0:02:33.68,Default,,0,0,0,,进而用更复杂的程序\nDialogue: 0,0:02:34.30,0:02:37.42,Default,,0,0,0,,然后又演示一个不那么复杂的程序\nDialogue: 0,0:02:37.44,0:02:41.23,Default,,0,0,0,,来演示求值器是如何变成硬件的\nDialogue: 0,0:02:41.23,0:02:42.06,Default,,0,0,0,,当然 到那个时候\nDialogue: 0,0:02:42.08,0:02:44.08,Default,,0,0,0,,你就有了通用的转换算法\nDialogue: 0,0:02:44.22,0:02:46.88,Default,,0,0,0,,并且可以用一个定义明确的硬件\nDialogue: 0,0:02:47.16,0:02:48.80,Default,,0,0,0,,来执行任何可以想象的程序\nDialogue: 0,0:02:51.72,0:02:52.91,Default,,0,0,0,,那么 现在让我们开始\nDialogue: 0,0:02:53.05,0:02:55.31,Default,,0,0,0,,给你们关于这些东西的具体感觉\nDialogue: 0,0:02:55.44,0:02:57.66,Default,,0,0,0,,我们先从一个非常简单的程序开始\nDialogue: 0,0:02:59.60,0:03:00.85,Default,,0,0,0,,这是欧几里得算法\nDialogue: 0,0:03:03.88,0:03:07.00,Default,,0,0,0,,它实际上比欧几里德算法更现代一些\nDialogue: 0,0:03:07.02,0:03:10.09,Default,,0,0,0,,我想 用来计算两数最大公约数的欧几里得算法\nDialogue: 0,0:03:10.41,0:03:13.60,Default,,0,0,0,,是在公元前350年发明的\nDialogue: 0,0:03:14.30,0:03:15.69,Default,,0,0,0,,它是已知最古老的算法\nDialogue: 0,0:03:19.32,0:03:23.34,Default,,0,0,0,,我们先定义(GCD A B)\nDialogue: 0,0:03:23.36,0:03:25.61,Default,,0,0,0,,也就是用来计算A、B两数的最大公约数\nDialogue: 0,0:03:26.20,0:03:28.91,Default,,0,0,0,,这个算法相当简单\nDialogue: 0,0:03:29.50,0:03:31.08,Default,,0,0,0,,如果B等于0\nDialogue: 0,0:03:34.16,0:03:36.83,Default,,0,0,0,,那么结果就是A\nDialogue: 0,0:03:37.52,0:03:43.61,Default,,0,0,0,,否则结果就是 (GCD B\nDialogue: 0,0:03:44.49,0:03:53.39,Default,,0,0,0,,(REMAINDER A B))\nDialogue: 0,0:03:58.53,0:04:01.90,Default,,0,0,0,,这里 我们定义了一个简单的迭代过程\nDialogue: 0,0:04:02.03,0:04:04.08,Default,,0,0,0,,这是一个简单的递归过程\nDialogue: 0,0:04:04.38,0:04:07.53,Default,,0,0,0,,也可以说这个过程是递归地定义的\nDialogue: 0,0:04:07.71,0:04:09.26,Default,,0,0,0,,但它产生的计算过程是迭代的\nDialogue: 0,0:04:09.95,0:04:12.46,Default,,0,0,0,,它的原理是 在每一步\nDialogue: 0,0:04:12.80,0:04:15.10,Default,,0,0,0,,判断B是否为0\nDialogue: 0,0:04:16.24,0:04:18.80,Default,,0,0,0,,如果B为0 那么A的值就是我们的答案\nDialogue: 0,0:04:19.63,0:04:22.46,Default,,0,0,0,,否则就进入下一个步骤\nDialogue: 0,0:04:22.49,0:04:23.87,Default,,0,0,0,,其中A就变成旧的B\nDialogue: 0,0:04:23.88,0:04:27.04,Default,,0,0,0,,而B的值 是A旧值除B旧值的余数\nDialogue: 0,0:04:28.76,0:04:29.55,Default,,0,0,0,,非常简单\nDialogue: 0,0:04:31.11,0:04:32.72,Default,,0,0,0,,现在 我已经通过这种方式\nDialogue: 0,0:04:32.99,0:04:34.86,Default,,0,0,0,,告诉了你一些机制\nDialogue: 0,0:04:34.86,0:04:35.90,Default,,0,0,0,,我是按时序告诉你们的\nDialogue: 0,0:04:36.36,0:04:37.72,Default,,0,0,0,,我说 其中有特定的步骤\nDialogue: 0,0:04:38.14,0:04:39.32,Default,,0,0,0,,并且实际上\nDialogue: 0,0:04:39.52,0:04:40.86,Default,,0,0,0,,你可以在这里知道\nDialogue: 0,0:04:41.18,0:04:43.69,Default,,0,0,0,,为什么这个过程是迭代的\nDialogue: 0,0:04:43.95,0:04:47.68,Default,,0,0,0,,是因为最后一步无需额外信息来得到答案\nDialogue: 0,0:04:49.44,0:04:55.29,Default,,0,0,0,,所有运行此算法所需的信息都在A和B中\nDialogue: 0,0:04:55.74,0:04:57.80,Default,,0,0,0,,它有两个定义明确的状态变量\nDialogue: 0,0:05:00.47,0:05:02.33,Default,,0,0,0,,现在 我就要给你们定义一台机器\nDialogue: 0,0:05:03.98,0:05:05.55,Default,,0,0,0,,用来计算GCD\nDialogue: 0,0:05:06.56,0:05:07.12,Default,,0,0,0,,我们来看看\nDialogue: 0,0:05:07.12,0:05:11.28,Default,,0,0,0,,每台制造的计算机都是单进程计算机\nDialogue: 0,0:05:11.80,0:05:14.08,Default,,0,0,0,,而不是某种多处理器\nDialogue: 0,0:05:15.04,0:05:16.59,Default,,0,0,0,,都是按照相同的方案制定的\nDialogue: 0,0:05:17.84,0:05:19.53,Default,,0,0,0,,这种方案就是：计算机由两部分组成\nDialogue: 0,0:05:20.57,0:05:22.35,Default,,0,0,0,,一部分叫数据通路\nDialogue: 0,0:05:23.10,0:05:24.36,Default,,0,0,0,,而另一部分叫控制器\nDialogue: 0,0:05:25.91,0:05:29.28,Default,,0,0,0,,数据通路相当于你可能有的计算器\nDialogue: 0,0:05:29.71,0:05:31.87,Default,,0,0,0,,它有一些寄存器 能够存储数据\nDialogue: 0,0:05:31.90,0:05:33.13,Default,,0,0,0,,你们都用过计算器\nDialogue: 0,0:05:33.56,0:05:35.34,Default,,0,0,0,,它上面有一些按钮和指示灯\nDialogue: 0,0:05:37.03,0:05:38.49,Default,,0,0,0,,通过按下不同的按钮\nDialogue: 0,0:05:38.52,0:05:41.34,Default,,0,0,0,,你可以使操作在寄存器内发生\nDialogue: 0,0:05:41.87,0:05:43.48,Default,,0,0,0,,并显示计算结果\nDialogue: 0,0:05:45.16,0:05:46.25,Default,,0,0,0,,它是完全机械式的\nDialogue: 0,0:05:46.25,0:05:49.55,Default,,0,0,0,,你可以认为那个盒子没有任何智能\nDialogue: 0,0:05:50.90,0:05:53.28,Default,,0,0,0,,它能计算一个数的正弦也许令人吃惊\nDialogue: 0,0:05:53.53,0:05:58.97,Default,,0,0,0,,但它显然是机械式的\nDialogue: 0,0:05:58.97,0:06:01.71,Default,,0,0,0,,至少 我可以像打开GCD机器一样打开它\nDialogue: 0,0:06:02.69,0:06:04.36,Default,,0,0,0,,也就是说 它其中可能有一整台计算机\nDialogue: 0,0:06:04.68,0:06:05.69,Default,,0,0,0,,但这并不有趣\nDialogue: 0,0:06:05.94,0:06:07.10,Default,,0,0,0,,加法相当简单\nDialogue: 0,0:06:08.20,0:06:09.84,Default,,0,0,0,,不借助额外机制就可以完成\nDialogue: 0,0:06:10.89,0:06:15.64,Default,,0,0,0,,现在 如果我们来看另外的一部分：控制器\nDialogue: 0,0:06:15.93,0:06:17.39,Default,,0,0,0,,这一部分也非常简单\nDialogue: 0,0:06:18.19,0:06:19.16,Default,,0,0,0,,它负责按下按钮\nDialogue: 0,0:06:20.35,0:06:21.52,Default,,0,0,0,,它根据指令序列来按按钮\nDialogue: 0,0:06:21.55,0:06:22.84,Default,,0,0,0,,指令是写在纸上的\nDialogue: 0,0:06:24.27,0:06:25.64,Default,,0,0,0,,控制器还会观察指示灯\nDialogue: 0,0:06:26.29,0:06:29.44,Default,,0,0,0,,而且每隔一段 它就会来到指令序列中的一处\nDialogue: 0,0:06:29.47,0:06:32.37,Default,,0,0,0,,如果指示灯A亮 则执行某段指令\nDialogue: 0,0:06:32.37,0:06:33.85,Default,,0,0,0,,否则执行另外的指令\nDialogue: 0,0:06:34.62,0:06:37.45,Default,,0,0,0,,因此 这其中也没有什么复杂的\nDialogue: 0,0:06:38.35,0:06:39.32,Default,,0,0,0,,那么 让我们来画一下\nDialogue: 0,0:06:39.34,0:06:40.57,Default,,0,0,0,,然后来感受一下它\nDialogue: 0,0:06:42.51,0:06:44.84,Default,,0,0,0,,为了计算GCD\nDialogue: 0,0:06:45.88,0:06:49.52,Default,,0,0,0,,你们要知道：这其中有一些寄存器\nDialogue: 0,0:06:50.56,0:06:53.02,Default,,0,0,0,,这里 寄存器就是一个存储数值的地方\nDialogue: 0,0:06:53.52,0:06:54.65,Default,,0,0,0,,这个寄存器存储的是A\nDialogue: 0,0:06:56.81,0:06:58.70,Default,,0,0,0,,而另外的这个存储的是B\nDialogue: 0,0:07:03.17,0:07:05.45,Default,,0,0,0,,现在我们来看看 有了这些寄存器后能做什么\nDialogue: 0,0:07:05.98,0:07:08.73,Default,,0,0,0,,至于你能利用它做什么 并不是很明显\nDialogue: 0,0:07:09.84,0:07:11.72,Default,,0,0,0,,那么 我们必须看看需要用它们做什么\nDialogue: 0,0:07:11.82,0:07:13.87,Default,,0,0,0,,我们来看看尝试求解的问题\nDialogue: 0,0:07:14.03,0:07:16.09,Default,,0,0,0,,计算机设计的一个要点就是\nDialogue: 0,0:07:17.10,0:07:19.58,Default,,0,0,0,,我想大多数设计师都不会照做\nDialogue: 0,0:07:20.20,0:07:21.88,Default,,0,0,0,,也就是专注于待解的问题\nDialogue: 0,0:07:22.62,0:07:25.18,Default,,0,0,0,,然后使用你研究问题所学到的东西\nDialogue: 0,0:07:25.44,0:07:27.28,Default,,0,0,0,,把那些求解问题所需要的机制\nDialogue: 0,0:07:27.53,0:07:28.70,Default,,0,0,0,,融入正在构建的计算机中\nDialogue: 0,0:07:28.81,0:07:30.08,Default,,0,0,0,,不多也不少\nDialogue: 0,0:07:32.14,0:07:33.96,Default,,0,0,0,,现在 可能你所要解决的问题\nDialogue: 0,0:07:34.24,0:07:35.40,Default,,0,0,0,,是大家共有的问题\nDialogue: 0,0:07:36.06,0:07:37.58,Default,,0,0,0,,这种情况下你需要构建\nDialogue: 0,0:07:37.60,0:07:39.29,Default,,0,0,0,,某种语言的通用解释器\nDialogue: 0,0:07:40.19,0:07:42.32,Default,,0,0,0,,但是你添加的机制不能比\nDialogue: 0,0:07:42.35,0:07:44.25,Default,,0,0,0,,想构建的语言解释器的需求多\nDialogue: 0,0:07:44.44,0:07:45.85,Default,,0,0,0,,这一点 我们稍后来讨论\nDialogue: 0,0:07:47.23,0:07:49.93,Default,,0,0,0,,好了 让我们回到这里\nDialogue: 0,0:07:49.93,0:07:51.24,Default,,0,0,0,,我们必须能够做什么？\nDialogue: 0,0:07:51.79,0:07:54.14,Default,,0,0,0,,首先 我们能把B的值赋给A\nDialogue: 0,0:07:56.08,0:07:59.60,Default,,0,0,0,,我们要能够把B的旧值赋给A\nDialogue: 0,0:08:00.38,0:08:03.32,Default,,0,0,0,,因此 我们需要某种能够让数据流通的“路径”\nDialogue: 0,0:08:03.34,0:08:04.76,Default,,0,0,0,,而不管数据具体是什么\nDialogue: 0,0:08:05.37,0:08:06.57,Default,,0,0,0,,从B到A的通路\nDialogue: 0,0:08:07.39,0:08:09.26,Default,,0,0,0,,我箭头来指示\nDialogue: 0,0:08:09.52,0:08:12.62,Default,,0,0,0,,我们能够把B的值赋给A\nDialogue: 0,0:08:12.96,0:08:14.57,Default,,0,0,0,,从而替换A的旧值\nDialogue: 0,0:08:15.12,0:08:16.73,Default,,0,0,0,,当你按下这里的按钮后\nDialogue: 0,0:08:17.48,0:08:18.56,Default,,0,0,0,,就能够实现这个效果\nDialogue: 0,0:08:19.71,0:08:20.78,Default,,0,0,0,,这个按钮就在这里\nDialogue: 0,0:08:23.07,0:08:23.93,Default,,0,0,0,,同样的\nDialogue: 0,0:08:23.95,0:08:26.28,Default,,0,0,0,,我还需要能够计算A除B的余数\nDialogue: 0,0:08:27.00,0:08:28.49,Default,,0,0,0,,这可能混乱而又复杂\nDialogue: 0,0:08:28.86,0:08:30.86,Default,,0,0,0,,但另一方面 我会把它放到一个小盒子中\nDialogue: 0,0:08:31.96,0:08:33.92,Default,,0,0,0,,如果有必要的话 我们可以打开那个盒子\nDialogue: 0,0:08:34.12,0:08:35.63,Default,,0,0,0,,看看其中有些什么\nDialogue: 0,0:08:37.77,0:08:39.16,Default,,0,0,0,,这就是那个小盒子\nDialogue: 0,0:08:39.20,0:08:40.38,Default,,0,0,0,,我这么来画它\nDialogue: 0,0:08:43.16,0:08:44.38,Default,,0,0,0,,我把它叫做REM\nDialogue: 0,0:08:46.44,0:08:48.60,Default,,0,0,0,,它接受A\nDialogue: 0,0:08:50.91,0:08:52.16,Default,,0,0,0,,同时也要接受B\nDialogue: 0,0:08:54.37,0:08:56.51,Default,,0,0,0,,它有一个输出\nDialogue: 0,0:08:58.89,0:09:00.46,Default,,0,0,0,,也就是A除以B的余数\nDialogue: 0,0:09:02.29,0:09:03.61,Default,,0,0,0,,在这里 我们同样需要能够\nDialogue: 0,0:09:03.64,0:09:06.06,Default,,0,0,0,,判断B是否等于0\nDialogue: 0,0:09:08.00,0:09:09.66,Default,,0,0,0,,也就是说 总得有个东西\nDialogue: 0,0:09:10.00,0:09:12.30,Default,,0,0,0,,去查询B的值\nDialogue: 0,0:09:13.39,0:09:14.40,Default,,0,0,0,,这是一个指示灯\nDialogue: 0,0:09:15.85,0:09:17.39,Default,,0,0,0,,当B等于0时 它就会点亮\nDialogue: 0,0:09:21.11,0:09:22.01,Default,,0,0,0,,它就是干这个的\nDialogue: 0,0:09:24.03,0:09:26.78,Default,,0,0,0,,最后 因为我们希望\nDialogue: 0,0:09:26.96,0:09:30.43,Default,,0,0,0,,A的新值是B的旧值\nDialogue: 0,0:09:30.46,0:09:34.41,Default,,0,0,0,,同时B的新值是有关于A的\nDialogue: 0,0:09:35.28,0:09:37.60,Default,,0,0,0,,如果我打算让机器\nDialogue: 0,0:09:37.80,0:09:39.74,Default,,0,0,0,,一次只发生一件事\nDialogue: 0,0:09:40.20,0:09:41.40,Default,,0,0,0,,一次执行一个动作\nDialogue: 0,0:09:41.61,0:09:43.42,Default,,0,0,0,,并且我不能在一个寄存器中放两个数字\nDialogue: 0,0:09:44.03,0:09:46.30,Default,,0,0,0,,那么进行互换时 必须有另外的地方放置一个数字\nDialogue: 0,0:09:49.29,0:09:49.60,Default,,0,0,0,,对吧？\nDialogue: 0,0:09:50.00,0:09:51.85,Default,,0,0,0,,我不能同时交换两手的东西\nDialogue: 0,0:09:52.11,0:09:53.72,Default,,0,0,0,,除非我一手拿两个\nDialogue: 0,0:09:53.72,0:09:55.13,Default,,0,0,0,,然后从中取另外一个\nDialogue: 0,0:09:55.50,0:09:56.91,Default,,0,0,0,,或者我先放下一个\nDialogue: 0,0:09:57.02,0:09:58.68,Default,,0,0,0,,取得另一个后再像这样捡起来\nDialogue: 0,0:09:59.64,0:10:00.94,Default,,0,0,0,,除非我是耍杂技的\nDialogue: 0,0:10:01.66,0:10:03.50,Default,,0,0,0,,当然正如大家所见 我并不是\nDialogue: 0,0:10:04.65,0:10:07.36,Default,,0,0,0,,这种情况下 我就会遇到时序错误\nDialogue: 0,0:10:08.85,0:10:11.04,Default,,0,0,0,,事实上 人们所做的许多类型的计算机设计\nDialogue: 0,0:10:11.07,0:10:12.68,Default,,0,0,0,,都遇到了时序错误\nDialogue: 0,0:10:13.12,0:10:15.00,Default,,0,0,0,,或者潜在的时序错误\nDialogue: 0,0:10:15.24,0:10:16.43,Default,,0,0,0,,我不太喜欢这种错误\nDialogue: 0,0:10:17.34,0:10:18.64,Default,,0,0,0,,因此 出于这个原因\nDialogue: 0,0:10:18.68,0:10:21.21,Default,,0,0,0,,我需要有一个地方来放置\nDialogue: 0,0:10:22.06,0:10:23.29,Default,,0,0,0,,其中的一个元素\nDialogue: 0,0:10:23.41,0:10:24.72,Default,,0,0,0,,因此 这里有一个寄存器\nDialogue: 0,0:10:24.75,0:10:26.84,Default,,0,0,0,,用来存放临时值T\nDialogue: 0,0:10:28.59,0:10:29.63,Default,,0,0,0,,上面有一个按钮\nDialogue: 0,0:10:30.47,0:10:31.88,Default,,0,0,0,,我会使用它的结果\nDialogue: 0,0:10:31.90,0:10:34.14,Default,,0,0,0,,因为我需要把这个结果送入B\nDialogue: 0,0:10:34.68,0:10:36.73,Default,,0,0,0,,我们会把结果像这样给送过来\nDialogue: 0,0:10:38.41,0:10:39.30,Default,,0,0,0,,这里同样有一个按钮\nDialogue: 0,0:10:42.43,0:10:45.84,Default,,0,0,0,,这就是GCD机器的数据通路\nDialogue: 0,0:10:47.60,0:10:48.57,Default,,0,0,0,,那么 控制器又是怎样的呢？\nDialogue: 0,0:10:49.74,0:10:51.28,Default,,0,0,0,,控制器同样很简单\nDialogue: 0,0:10:52.28,0:10:53.26,Default,,0,0,0,,机器具有状态\nDialogue: 0,0:10:54.38,0:10:57.72,Default,,0,0,0,,我喜欢形象地把它们比作迷宫\nDialogue: 0,0:10:59.01,0:11:03.20,Default,,0,0,0,,这个迷宫的各处是通过直接的箭头连接的\nDialogue: 0,0:11:04.43,0:11:05.60,Default,,0,0,0,,而我有一颗弹珠\nDialogue: 0,0:11:06.46,0:11:09.07,Default,,0,0,0,,它代表了控制器的状态\nDialogue: 0,0:11:10.74,0:11:12.27,Default,,0,0,0,,弹珠在迷宫中四处滚动\nDialogue: 0,0:11:13.74,0:11:17.15,Default,,0,0,0,,当然 这种类比因能量的原因而不成立\nDialogue: 0,0:11:17.15,0:11:19.08,Default,,0,0,0,,有时我不得不将弹珠泵到顶部\nDialogue: 0,0:11:19.12,0:11:21.85,Default,,0,0,0,,不然它就会成为一台永动机\nDialogue: 0,0:11:22.00,0:11:23.32,Default,,0,0,0,,但不用担心那么多\nDialogue: 0,0:11:23.90,0:11:25.90,Default,,0,0,0,,这并不是一个物理比喻\nDialogue: 0,0:11:26.08,0:11:27.42,Default,,0,0,0,,弹珠到处滚动\nDialogue: 0,0:11:27.68,0:11:29.56,Default,,0,0,0,,就像弹球机一样\nDialogue: 0,0:11:29.68,0:11:30.97,Default,,0,0,0,,每次当它滚动到一些缓冲器时\nDialogue: 0,0:11:31.26,0:11:32.60,Default,,0,0,0,,它就会按下这些按钮\nDialogue: 0,0:11:34.83,0:11:37.50,Default,,0,0,0,,它也会经常来到一个分支区域\nDialogue: 0,0:11:38.62,0:11:39.68,Default,,0,0,0,,它要在这里做选择\nDialogue: 0,0:11:40.25,0:11:42.36,Default,,0,0,0,,然后有一个由这个组件控制的挡板\nDialogue: 0,0:11:46.00,0:11:48.82,Default,,0,0,0,,所以这是一个非常机械化的思考方式\nDialogue: 0,0:11:48.82,0:11:51.05,Default,,0,0,0,,当然 真实计算机中的控制器\nDialogue: 0,0:11:51.08,0:11:51.84,Default,,0,0,0,,并不是这样的\nDialogue: 0,0:11:51.84,0:11:56.01,Default,,0,0,0,,而是由一些ROM和状态寄存器构成\nDialogue: 0,0:11:56.61,0:11:58.73,Default,,0,0,0,,但曾几何时 像DEC、PDP-6这些个机器\nDialogue: 0,0:11:59.29,0:12:01.02,Default,,0,0,0,,它们的控制器就是我们说的那样\nDialogue: 0,0:12:01.80,0:12:03.61,Default,,0,0,0,,延迟线上有一些比特信息\nDialogue: 0,0:12:05.69,0:12:08.14,Default,,0,0,0,,它随着时间的推移而触发事件\nDialogue: 0,0:12:08.58,0:12:10.70,Default,,0,0,0,,然后回到开始并再次轮回\nDialogue: 0,0:12:11.99,0:12:13.72,Default,,0,0,0,,当然 还有各种各样的错误\nDialogue: 0,0:12:13.74,0:12:17.67,Default,,0,0,0,,比如两个比特的信息 -- 对应两个弹珠\nDialogue: 0,0:12:17.67,0:12:19.26,Default,,0,0,0,,机器也会丢失弹珠\nDialogue: 0,0:12:19.45,0:12:20.20,Default,,0,0,0,,这也会发生\nDialogue: 0,0:12:20.98,0:12:21.58,Default,,0,0,0,,好吧\nDialogue: 0,0:12:22.27,0:12:24.22,Default,,0,0,0,,无论如何 对于这台机器\nDialogue: 0,0:12:24.27,0:12:25.48,Default,,0,0,0,,我想要这么来做\nDialogue: 0,0:12:25.80,0:12:27.74,Default,,0,0,0,,迷宫从这里开始\nDialogue: 0,0:12:30.52,0:12:32.73,Default,,0,0,0,,我首先要做的是\nDialogue: 0,0:12:33.76,0:12:36.75,Default,,0,0,0,,用一个你们非常熟悉的流程图记号\nDialogue: 0,0:12:37.07,0:12:39.85,Default,,0,0,0,,这是一个判断：B是否为0\nDialogue: 0,0:12:41.50,0:12:43.79,Default,,0,0,0,,如果判断为是的话\nDialogue: 0,0:12:43.93,0:12:45.58,Default,,0,0,0,,那我就做完了\nDialogue: 0,0:12:49.79,0:12:51.26,Default,,0,0,0,,否则的话\nDialogue: 0,0:12:52.70,0:12:54.32,Default,,0,0,0,,我就不得不滚动一些缓冲器\nDialogue: 0,0:12:55.00,0:12:56.46,Default,,0,0,0,,按照下列顺序执行\nDialogue: 0,0:12:57.42,0:13:03.40,Default,,0,0,0,,我想向这样来做一个互换游戏\nDialogue: 0,0:13:04.05,0:13:05.80,Default,,0,0,0,,首先 因为我需要A和B\nDialogue: 0,0:13:06.32,0:13:08.57,Default,,0,0,0,,但首先 -- 虽然并不是必要的\nDialogue: 0,0:13:08.65,0:13:09.72,Default,,0,0,0,,我需要先把它们收集起来\nDialogue: 0,0:13:11.07,0:13:12.62,Default,,0,0,0,,这里的值要送入到B中\nDialogue: 0,0:13:13.24,0:13:14.03,Default,,0,0,0,,因此 我会说\nDialogue: 0,0:13:14.28,0:13:16.27,Default,,0,0,0,,用A和B的值来计算这个\nDialogue: 0,0:13:16.36,0:13:18.67,Default,,0,0,0,,并把算得的余数放到这里\nDialogue: 0,0:13:19.15,0:13:20.33,Default,,0,0,0,,因此 我首先要按下这个按钮\nDialogue: 0,0:13:21.53,0:13:24.43,Default,,0,0,0,,然后我要把B的值送入A\nDialogue: 0,0:13:24.44,0:13:25.60,Default,,0,0,0,,通过按这个钮来实现\nDialogue: 0,0:13:25.82,0:13:27.63,Default,,0,0,0,,然后我再把临时值送入B\nDialogue: 0,0:13:28.76,0:13:29.42,Default,,0,0,0,,通过这个按钮实现\nDialogue: 0,0:13:32.03,0:13:34.97,Default,,0,0,0,,这是一个相当时序化的机器\nDialogue: 0,0:13:35.39,0:13:36.52,Default,,0,0,0,,它非常的低效\nDialogue: 0,0:13:37.75,0:13:39.05,Default,,0,0,0,,但目前来说还好\nDialogue: 0,0:13:39.81,0:13:40.97,Default,,0,0,0,,我们来为按钮命名\nDialogue: 0,0:13:41.47,0:13:42.72,Default,,0,0,0,,T←R\nDialogue: 0,0:13:46.75,0:13:48.73,Default,,0,0,0,,A←B\nDialogue: 0,0:13:50.03,0:13:54.81,Default,,0,0,0,,B←T\nDialogue: 0,0:13:55.47,0:13:57.63,Default,,0,0,0,,然后我要来到这里\nDialogue: 0,0:13:58.78,0:13:59.88,Default,,0,0,0,,也就是回到开始的地方\nDialogue: 0,0:14:01.62,0:14:03.87,Default,,0,0,0,,在这里 我们看到了什么？\nDialogue: 0,0:14:03.87,0:14:04.91,Default,,0,0,0,,我们看到各种各样的 --\nDialogue: 0,0:14:05.05,0:14:07.16,Default,,0,0,0,,我们真正拥有的是某种机械连接\nDialogue: 0,0:14:07.42,0:14:13.63,Default,,0,0,0,,其中T←R控制了这个东西\nDialogue: 0,0:14:16.83,0:14:21.48,Default,,0,0,0,,A←B控制了这个东西\nDialogue: 0,0:14:26.96,0:14:28.12,Default,,0,0,0,,而这里的这个东西\nDialogue: 0,0:14:28.12,0:14:31.08,Default,,0,0,0,,同学们 这简直太恶劣了\nDialogue: 0,0:14:31.48,0:14:32.48,Default,,0,0,0,,一点也没有优化\nDialogue: 0,0:14:32.63,0:14:34.59,Default,,0,0,0,,我画的所有线条都相互交叉\nDialogue: 0,0:14:38.54,0:14:41.15,Default,,0,0,0,,我想B←T控制的是这个\nDialogue: 0,0:14:45.69,0:14:47.95,Default,,0,0,0,,现在 我就要运行这台机器了\nDialogue: 0,0:14:48.04,0:14:49.34,Default,,0,0,0,,但是在我运行它之前\nDialogue: 0,0:14:49.37,0:14:51.40,Default,,0,0,0,,我想写下它的控制器的描述\nDialogue: 0,0:14:51.63,0:14:52.81,Default,,0,0,0,,以便使你们相信\nDialogue: 0,0:14:52.84,0:14:55.63,Default,,0,0,0,,这些东西可以组织成某种良好的语言\nDialogue: 0,0:14:56.08,0:14:58.08,Default,,0,0,0,,这样我们就不必总是像这样画图\nDialogue: 0,0:14:58.36,0:15:00.68,Default,,0,0,0,,图示的缺陷之一 就是占用了太多空间\nDialogue: 0,0:15:00.89,0:15:01.98,Default,,0,0,0,,对于这样的一个小型机器来说\nDialogue: 0,0:15:02.00,0:15:03.05,Default,,0,0,0,,它占用了两块黑板\nDialogue: 0,0:15:03.22,0:15:05.24,Default,,0,0,0,,而一台求值器机器\nDialogue: 0,0:15:05.40,0:15:07.10,Default,,0,0,0,,我就很难将它画在这间屋子里了\nDialogue: 0,0:15:07.95,0:15:09.16,Default,,0,0,0,,尽管它还不是非常大\nDialogue: 0,0:15:09.90,0:15:11.28,Default,,0,0,0,,因此我要为它构造一门小型语言\nDialogue: 0,0:15:11.29,0:15:12.51,Default,,0,0,0,,用来描述这个机器\nDialogue: 0,0:15:13.10,0:15:23.29,Default,,0,0,0,,(DEFIME-MACHINE GCD\nDialogue: 0,0:15:24.42,0:15:25.66,Default,,0,0,0,,当然 一旦我们有了像这样的描述\nDialogue: 0,0:15:25.68,0:15:26.83,Default,,0,0,0,,我们就能够模拟该机器\nDialogue: 0,0:15:27.22,0:15:29.42,Default,,0,0,0,,我之所以想构建这种形式的语言\nDialogue: 0,0:15:29.56,0:15:32.94,Default,,0,0,0,,是因为我们能够立即操纵这些表达式\nDialogue: 0,0:15:33.21,0:15:34.91,Default,,0,0,0,,因此 我也就能够\nDialogue: 0,0:15:35.29,0:15:38.16,Default,,0,0,0,,代数地操作 或者模拟这些东西\nDialogue: 0,0:15:38.20,0:15:39.96,Default,,0,0,0,,以及各种各样我想进行的操作\nDialogue: 0,0:15:40.12,0:15:42.59,Default,,0,0,0,,或者还可以把它们转换成布局图 谁知道呢？\nDialogue: 0,0:15:43.63,0:15:48.38,Default,,0,0,0,,一旦我有了寄存器的良好表示\nDialogue: 0,0:15:48.51,0:15:49.61,Default,,0,0,0,,它有一些寄存器\nDialogue: 0,0:15:53.00,0:15:55.64,Default,,0,0,0,,记作(REGISTERS A B T)\nDialogue: 0,0:15:56.75,0:15:57.80,Default,,0,0,0,,它还有控制器\nDialogue: 0,0:16:02.19,0:16:04.46,Default,,0,0,0,,实际上 更好的做法是让它更显式一些\nDialogue: 0,0:16:04.49,0:16:06.97,Default,,0,0,0,,也就是说 为每一个按钮命名\nDialogue: 0,0:16:08.14,0:16:10.17,Default,,0,0,0,,并指明它们的操作\nDialogue: 0,0:16:10.42,0:16:11.37,Default,,0,0,0,,比如说这个按钮\nDialogue: 0,0:16:11.55,0:16:14.19,Default,,0,0,0,,会让T的值送入到B中\nDialogue: 0,0:16:15.10,0:16:16.09,Default,,0,0,0,,但我却不想这么做\nDialogue: 0,0:16:16.11,0:16:17.95,Default,,0,0,0,,因为这样会让代码难以阅读\nDialogue: 0,0:16:18.20,0:16:19.34,Default,,0,0,0,,也会占用更多空间\nDialogue: 0,0:16:19.51,0:16:22.36,Default,,0,0,0,,所以我会把相关的指令写在控制器中\nDialogue: 0,0:16:23.29,0:16:25.24,Default,,0,0,0,,这样就隐式地指明了具体的操作\nDialogue: 0,0:16:26.32,0:16:28.57,Default,,0,0,0,,可以通过阅读代码推断出来\nDialogue: 0,0:16:29.16,0:16:31.39,Default,,0,0,0,,并收集所有可以完成的不同事情\nDialogue: 0,0:16:31.69,0:16:33.50,Default,,0,0,0,,我们来看一看\nDialogue: 0,0:16:33.50,0:16:34.70,Default,,0,0,0,,我们来看下这些东西是什么吧\nDialogue: 0,0:16:35.71,0:16:37.29,Default,,0,0,0,,首先是一个循环\nDialogue: 0,0:16:38.24,0:16:40.20,Default,,0,0,0,,先是一条分支指令\nDialogue: 0,0:16:42.64,0:16:46.46,Default,,0,0,0,,这个就对应了机器中的小挡板\nDialogue: 0,0:16:46.89,0:16:48.49,Default,,0,0,0,,它决定了你在此处的走向\nDialogue: 0,0:16:49.10,0:16:58.00,Default,,0,0,0,,判断 -- 取B的值 并判断是否为0\nDialogue: 0,0:16:58.65,0:17:00.06,Default,,0,0,0,,如果B的值是0\nDialogue: 0,0:17:00.32,0:17:01.72,Default,,0,0,0,,那么就跳转到一个叫DONE的地方\nDialogue: 0,0:17:03.64,0:17:05.29,Default,,0,0,0,,现在 你们在这里看到的是\nDialogue: 0,0:17:05.29,0:17:07.40,Default,,0,0,0,,这个看起来非常像传统计算机语言\nDialogue: 0,0:17:08.17,0:17:09.55,Default,,0,0,0,,但你们所见的是\nDialogue: 0,0:17:10.03,0:17:12.00,Default,,0,0,0,,一些个标签\nDialogue: 0,0:17:12.99,0:17:16.86,Default,,0,0,0,,它们代表着存放了一系列指令的地方\nDialogue: 0,0:17:17.60,0:17:18.94,Default,,0,0,0,,之所以需要它们\nDialogue: 0,0:17:19.48,0:17:21.15,Default,,0,0,0,,是因为在这里\nDialogue: 0,0:17:21.45,0:17:22.81,Default,,0,0,0,,我表达了“循环”的概念\nDialogue: 0,0:17:23.32,0:17:26.11,Default,,0,0,0,,但是如果我是在写英文之类的文本\nDialogue: 0,0:17:26.44,0:17:28.09,Default,,0,0,0,,就很难去引用一个位置\nDialogue: 0,0:17:28.58,0:17:29.53,Default,,0,0,0,,我没有箭头\nDialogue: 0,0:17:30.80,0:17:33.02,Default,,0,0,0,,箭头是通过\nDialogue: 0,0:17:33.05,0:17:34.44,Default,,0,0,0,,给箭头所指的地方命名来表示的\nDialogue: 0,0:17:34.57,0:17:36.28,Default,,0,0,0,,并通过名字来引用\nDialogue: 0,0:17:37.40,0:17:38.59,Default,,0,0,0,,这只是一种编码\nDialogue: 0,0:17:39.86,0:17:41.88,Default,,0,0,0,,而不是某种魔法\nDialogue: 0,0:17:43.15,0:17:44.96,Default,,0,0,0,,接下来我们要做的是\nDialogue: 0,0:17:45.02,0:17:46.84,Default,,0,0,0,,我们如何来实现T←R\nDialogue: 0,0:17:47.45,0:17:49.76,Default,,0,0,0,,非常简单 用ASSIGN\nDialogue: 0,0:17:52.19,0:17:55.55,Default,,0,0,0,,我们把余数赋值给T\nDialogue: 0,0:17:56.32,0:17:59.24,Default,,0,0,0,,ASSIGN就是按钮的名字\nDialogue: 0,0:18:01.47,0:18:02.64,Default,,0,0,0,,就是按按钮的家伙\nDialogue: 0,0:18:03.14,0:18:04.97,Default,,0,0,0,,把余数赋给T\nDialogue: 0,0:18:04.99,0:18:06.76,Default,,0,0,0,,这个操作是这样表示的\nDialogue: 0,0:18:11.74,0:18:17.53,Default,,0,0,0,,取A、B的值 相除得到余数\nDialogue: 0,0:18:23.85,0:18:30.99,Default,,0,0,0,,同时 我们也要取B的值 赋给A\nDialogue: 0,0:18:34.99,0:18:47.88,Default,,0,0,0,,再取T的值赋给B\nDialogue: 0,0:18:49.61,0:18:51.85,Default,,0,0,0,,现在 我需要引用这个开头\nDialogue: 0,0:18:53.18,0:18:55.92,Default,,0,0,0,,呃 我为什么不把这里叫做LOOP呢？\nDialogue: 0,0:19:04.09,0:19:07.04,Default,,0,0,0,,这就是如何引用这个箭头\nDialogue: 0,0:19:07.61,0:19:08.95,Default,,0,0,0,,当执行到DONE时 就完成了所有操作\nDialogue: 0,0:19:09.02,0:19:13.07,Default,,0,0,0,,我们来到了这里 所有指令的结尾\nDialogue: 0,0:19:15.26,0:19:17.04,Default,,0,0,0,,这段文字化描述的就是\nDialogue: 0,0:19:17.69,0:19:20.86,Default,,0,0,0,,我们在这里画的一小部分机器\nDialogue: 0,0:19:21.66,0:19:24.84,Default,,0,0,0,,下面 我就要运行它\nDialogue: 0,0:19:25.49,0:19:26.65,Default,,0,0,0,,我想让你们感受一下它的运行\nDialogue: 0,0:19:27.62,0:19:29.80,Default,,0,0,0,,从来没有做过这个 你必须做一次\nDialogue: 0,0:19:31.01,0:19:32.62,Default,,0,0,0,,让我们以一个具体的问题来演示\nDialogue: 0,0:19:33.10,0:19:34.70,Default,,0,0,0,,假设我们想要计算\nDialogue: 0,0:19:35.04,0:19:40.68,Default,,0,0,0,,30和42的最大公约数\nDialogue: 0,0:19:42.21,0:19:44.92,Default,,0,0,0,,我现在不知道结果是多少\nDialogue: 0,0:19:45.86,0:19:47.60,Default,,0,0,0,,但我知道A=30而B=42\nDialogue: 0,0:19:50.96,0:19:52.09,Default,,0,0,0,,我就这么着开始\nDialogue: 0,0:19:52.60,0:19:53.90,Default,,0,0,0,,那么 我首先要做些什么呢？\nDialogue: 0,0:19:54.24,0:19:56.86,Default,,0,0,0,,我先判断B是否为0：否\nDialogue: 0,0:19:57.59,0:20:02.11,Default,,0,0,0,,然后计算A除B的余数 并赋给T\nDialogue: 0,0:20:02.80,0:20:07.60,Default,,0,0,0,,当然 30除以42的余数就是30自己\nDialogue: 0,0:20:11.13,0:20:12.03,Default,,0,0,0,,按下那个按钮\nDialogue: 0,0:20:12.92,0:20:15.10,Default,,0,0,0,,现在弹珠就滚动到了这里\nDialogue: 0,0:20:17.10,0:20:18.06,Default,,0,0,0,,A←B\nDialogue: 0,0:20:19.02,0:20:20.76,Default,,0,0,0,,又按下了这个按钮\nDialogue: 0,0:20:21.22,0:20:22.54,Default,,0,0,0,,因此42来到了这里\nDialogue: 0,0:20:26.59,0:20:27.60,Default,,0,0,0,,B←T\nDialogue: 0,0:20:28.36,0:20:29.34,Default,,0,0,0,,按下了这个按钮\nDialogue: 0,0:20:29.87,0:20:30.96,Default,,0,0,0,,30来到了这里\nDialogue: 0,0:20:32.57,0:20:33.69,Default,,0,0,0,,这样我就交换了它们\nDialogue: 0,0:20:34.66,0:20:38.27,Default,,0,0,0,,我们再来看看 回到开始\nDialogue: 0,0:20:38.64,0:20:39.72,Default,,0,0,0,,B为0么？不\nDialogue: 0,0:20:40.19,0:20:41.50,Default,,0,0,0,,将余数赋给T\nDialogue: 0,0:20:43.23,0:20:46.30,Default,,0,0,0,,我想 42除以30的余数是12\nDialogue: 0,0:20:47.24,0:20:48.30,Default,,0,0,0,,按下这个钮\nDialogue: 0,0:20:48.53,0:20:51.40,Default,,0,0,0,,下面 我想让30来到这里\nDialogue: 0,0:20:53.90,0:20:55.95,Default,,0,0,0,,按下这个钮 让12来到这里\nDialogue: 0,0:20:58.41,0:21:00.38,Default,,0,0,0,,然后继续\nDialogue: 0,0:21:00.38,0:21:01.31,Default,,0,0,0,,程序执行完了么？\nDialogue: 0,0:21:01.53,0:21:02.12,Default,,0,0,0,,并没有\nDialogue: 0,0:21:02.36,0:21:08.22,Default,,0,0,0,,现在 我需要求解30除以12的余数\nDialogue: 0,0:21:08.85,0:21:10.67,Default,,0,0,0,,我想答案是6\nDialogue: 0,0:21:12.42,0:21:15.13,Default,,0,0,0,,按下这个钮 6就到了这里\nDialogue: 0,0:21:16.20,0:21:18.25,Default,,0,0,0,,然后我又按下这个钮\nDialogue: 0,0:21:18.30,0:21:19.61,Default,,0,0,0,,这就让12来到了这里\nDialogue: 0,0:21:23.73,0:21:25.09,Default,,0,0,0,,然后我又按下这个按钮\nDialogue: 0,0:21:25.09,0:21:26.00,Default,,0,0,0,,6就来到了这里\nDialogue: 0,0:21:29.85,0:21:31.68,Default,,0,0,0,,6等于0么？\nDialogue: 0,0:21:31.88,0:21:32.49,Default,,0,0,0,,不等于\nDialogue: 0,0:21:33.42,0:21:33.98,Default,,0,0,0,,好的\nDialogue: 0,0:21:34.38,0:21:36.80,Default,,0,0,0,,因此这时\nDialogue: 0,0:21:36.89,0:21:38.12,Default,,0,0,0,,接下来又要计算余数\nDialogue: 0,0:21:38.14,0:21:39.80,Default,,0,0,0,,哦 这个的余数是0\nDialogue: 0,0:21:40.66,0:21:41.74,Default,,0,0,0,,看起来我们就快完成了\nDialogue: 0,0:21:42.36,0:21:44.36,Default,,0,0,0,,将6从这里挪到这里\nDialogue: 0,0:21:47.00,0:21:48.27,Default,,0,0,0,,0移动到这里\nDialogue: 0,0:21:49.09,0:21:50.20,Default,,0,0,0,,0等于0么？\nDialogue: 0,0:21:50.20,0:21:50.73,Default,,0,0,0,,是的\nDialogue: 0,0:21:51.34,0:21:53.36,Default,,0,0,0,,B的值等于0 因此答案就是A的值\nDialogue: 0,0:21:54.28,0:21:55.76,Default,,0,0,0,,因此答案就是6\nDialogue: 0,0:21:56.61,0:21:57.61,Default,,0,0,0,,这确实是正确的答案\nDialogue: 0,0:21:57.63,0:21:59.47,Default,,0,0,0,,因为如果我们回过头审视最初的问题\nDialogue: 0,0:22:00.08,0:22:06.64,Default,,0,0,0,,我们知道30=2×3×5\nDialogue: 0,0:22:07.00,0:22:11.12,Default,,0,0,0,,42=2×3×7\nDialogue: 0,0:22:11.67,0:22:14.11,Default,,0,0,0,,因此最大公约数就是2×3\nDialogue: 0,0:22:14.20,0:22:15.08,Default,,0,0,0,,也就是6\nDialogue: 0,0:22:18.38,0:22:20.56,Default,,0,0,0,,我们通常在这里画另外一条线\nDialogue: 0,0:22:20.59,0:22:22.52,Default,,0,0,0,,为了使它更清晰一点\nDialogue: 0,0:22:22.89,0:22:27.71,Default,,0,0,0,,在这两者之间建立了联系\nDialogue: 0,0:22:27.85,0:22:31.01,Default,,0,0,0,,小挡板需要根据这个指示灯来工作\nDialogue: 0,0:22:34.00,0:22:37.32,Default,,0,0,0,,当然 跟我给你们展示的东西相比\nDialogue: 0,0:22:37.85,0:22:40.00,Default,,0,0,0,,真实计算机的组件更加复杂\nDialogue: 0,0:22:41.35,0:22:47.16,Default,,0,0,0,,让我们来看看第一张幻灯片\nDialogue: 0,0:22:47.98,0:22:48.81,Default,,0,0,0,,哇\nDialogue: 0,0:22:50.19,0:22:52.43,Default,,0,0,0,,我们看到 我们想要做的就是\nDialogue: 0,0:22:52.65,0:22:55.85,Default,,0,0,0,,IO形式的操作\nDialogue: 0,0:22:56.84,0:23:01.42,Default,,0,0,0,,我们需要从外部搜集一些东西\nDialogue: 0,0:23:01.98,0:23:03.93,Default,,0,0,0,,因此 对我们的状态机器来说\nDialogue: 0,0:23:04.30,0:23:07.02,Default,,0,0,0,,它们的控制器\nDialogue: 0,0:23:07.26,0:23:10.56,Default,,0,0,0,,可能会从某处取得某值\nDialogue: 0,0:23:10.78,0:23:12.41,Default,,0,0,0,,将它们放入寄存器并从中读取\nDialogue: 0,0:23:13.49,0:23:15.92,Default,,0,0,0,,我还可以把另外的值加载到寄存器B中\nDialogue: 0,0:23:17.07,0:23:18.60,Default,,0,0,0,,稍后 当执行完毕后\nDialogue: 0,0:23:18.99,0:23:20.52,Default,,0,0,0,,我想要输出结果\nDialogue: 0,0:23:21.20,0:23:25.23,Default,,0,0,0,,当然 答案或简单或复杂\nDialogue: 0,0:23:26.09,0:23:28.03,Default,,0,0,0,,我写代码的时候 总假设PRINT很简单\nDialogue: 0,0:23:28.09,0:23:29.29,Default,,0,0,0,,READ也很简单\nDialogue: 0,0:23:29.88,0:23:31.08,Default,,0,0,0,,但实际上 在真实世界中\nDialogue: 0,0:23:31.12,0:23:32.89,Default,,0,0,0,,这些都是非常复杂的操作\nDialogue: 0,0:23:33.08,0:23:35.52,Default,,0,0,0,,跟你尝试求解的问题相比\nDialogue: 0,0:23:35.55,0:23:38.33,Default,,0,0,0,,它们通常更加庞大而复杂\nDialogue: 0,0:23:41.67,0:23:43.90,Default,,0,0,0,,另一方面 我犹记得\nDialogue: 0,0:23:44.89,0:23:48.78,Default,,0,0,0,,使用IBM 7090一类的计算机的时候\nDialogue: 0,0:23:49.05,0:23:53.04,Default,,0,0,0,,它的READ和WRITE只能操作单个对象\nDialogue: 0,0:23:53.08,0:23:54.62,Default,,0,0,0,,也就是一个数字\nDialogue: 0,0:23:55.84,0:23:58.54,Default,,0,0,0,,这就是一个基本的IO操作\nDialogue: 0,0:23:59.63,0:24:02.04,Default,,0,0,0,,我们这里有同样的操作\nDialogue: 0,0:24:02.33,0:24:04.67,Default,,0,0,0,,在这样的一台机器中\nDialogue: 0,0:24:05.44,0:24:06.89,Default,,0,0,0,,我们实际上在做什么？\nDialogue: 0,0:24:07.12,0:24:11.60,Default,,0,0,0,,我们看到 这个叫做“READ”的组件是数据源头\nDialogue: 0,0:24:12.20,0:24:14.46,Default,,0,0,0,,这个操作总是返回一个值\nDialogue: 0,0:24:14.66,0:24:17.13,Default,,0,0,0,,我们可以把它看做 总是返回一个值\nDialogue: 0,0:24:17.21,0:24:19.84,Default,,0,0,0,,它可以赋给寄存器A或B\nDialogue: 0,0:24:21.66,0:24:23.23,Default,,0,0,0,,而PRINT这个过程呢\nDialogue: 0,0:24:23.37,0:24:25.02,Default,,0,0,0,,当你正确连接它的时候\nDialogue: 0,0:24:25.24,0:24:26.43,Default,,0,0,0,,当你按下上面的按钮\nDialogue: 0,0:24:26.65,0:24:29.61,Default,,0,0,0,,就会打印出当前寄存器A中的值\nDialogue: 0,0:24:31.66,0:24:32.73,Default,,0,0,0,,这非常普通\nDialogue: 0,0:24:33.32,0:24:35.20,Default,,0,0,0,,这是我们想要的一种功能\nDialogue: 0,0:24:35.88,0:24:38.32,Default,,0,0,0,,但这里还有些其它事情需要我们担忧\nDialogue: 0,0:24:38.32,0:24:40.67,Default,,0,0,0,,比如说 这里我使用了一些复杂的机制\nDialogue: 0,0:24:41.05,0:24:42.48,Default,,0,0,0,,我们这里有REMAINDER组件\nDialogue: 0,0:24:43.85,0:24:44.44,Default,,0,0,0,,这是个什么东西呢？\nDialogue: 0,0:24:44.69,0:24:46.41,Default,,0,0,0,,求取余数的计算过程并不是那么“显然”\nDialogue: 0,0:24:46.92,0:24:48.92,Default,,0,0,0,,如果我们把这个组件给拆开\nDialogue: 0,0:24:49.48,0:24:50.62,Default,,0,0,0,,就会得到一整台机器\nDialogue: 0,0:24:51.84,0:24:53.66,Default,,0,0,0,,事实就是这样的\nDialogue: 0,0:24:54.54,0:24:59.15,Default,,0,0,0,,举例来说 如果要编程实现REMAINDER\nDialogue: 0,0:24:59.44,0:25:02.44,Default,,0,0,0,,最简单的算法就是 不断地做减法\nDialogue: 0,0:25:04.78,0:25:05.95,Default,,0,0,0,,这是因为 除法可以通过\nDialogue: 0,0:25:05.96,0:25:08.99,Default,,0,0,0,,对整数不断做减法来实现\nDialogue: 0,0:25:09.80,0:25:23.58,Default,,0,0,0,,N除以D的余数不外乎就是\nDialogue: 0,0:25:24.99,0:25:31.44,Default,,0,0,0,,如果N小于D的话\nDialogue: 0,0:25:32.24,0:25:33.66,Default,,0,0,0,,答案就是N\nDialogue: 0,0:25:34.30,0:25:35.90,Default,,0,0,0,,否则的话就是\nDialogue: 0,0:25:41.15,0:25:47.60,Default,,0,0,0,,N先减去D\nDialogue: 0,0:25:48.27,0:25:49.32,Default,,0,0,0,,再除以D的余数\nDialogue: 0,0:25:51.28,0:25:55.05,Default,,0,0,0,,天啊 这个看起来就像是GCD程序\nDialogue: 0,0:25:56.89,0:25:59.48,Default,,0,0,0,,当然 这个不是求余数的最优算法\nDialogue: 0,0:25:59.75,0:26:00.91,Default,,0,0,0,,在实际中 你应该使用那些\nDialogue: 0,0:26:00.92,0:26:05.42,Default,,0,0,0,,二进制运算、移位运算等操作\nDialogue: 0,0:26:05.55,0:26:06.97,Default,,0,0,0,,但关键点就是\nDialogue: 0,0:26:07.13,0:26:08.48,Default,,0,0,0,,如果我把这些组件打开\nDialogue: 0,0:26:08.92,0:26:10.64,Default,,0,0,0,,我可能会发现其中有一台计算机\nDialogue: 0,0:26:11.88,0:26:12.99,Default,,0,0,0,,现在我们就知道它的原理了\nDialogue: 0,0:26:13.51,0:26:14.33,Default,,0,0,0,,因为我们就造过一台\nDialogue: 0,0:26:15.64,0:26:17.10,Default,,0,0,0,,这些个机器都大同小异\nDialogue: 0,0:26:17.40,0:26:18.06,Default,,0,0,0,,另外一方面\nDialogue: 0,0:26:18.08,0:26:20.00,Default,,0,0,0,,我们可能想要构建一台更高效\nDialogue: 0,0:26:20.01,0:26:21.68,Default,,0,0,0,,组织更精良的机器\nDialogue: 0,0:26:21.85,0:26:23.96,Default,,0,0,0,,比如说 多次利用其中的寄存器\nDialogue: 0,0:26:24.00,0:26:27.05,Default,,0,0,0,,或者是硬件设计者能想到的其它可怕混乱\nDialogue: 0,0:26:27.31,0:26:28.60,Default,,0,0,0,,等等原因\nDialogue: 0,0:26:29.25,0:26:31.56,Default,,0,0,0,,比如说 你们所见的这台机器\nDialogue: 0,0:26:32.52,0:26:34.91,Default,,0,0,0,,不是让你们去细读它的结构的\nDialogue: 0,0:26:35.05,0:26:37.52,Default,,0,0,0,,它有些复杂 对吧？\nDialogue: 0,0:26:37.52,0:26:39.87,Default,,0,0,0,,但它实际上是\nDialogue: 0,0:26:40.09,0:26:43.82,Default,,0,0,0,,整合了REMAINDER的GCD机器\nDialogue: 0,0:26:44.46,0:26:46.02,Default,,0,0,0,,并且实际上 它没有多余的寄存器\nDialogue: 0,0:26:46.02,0:26:48.62,Default,,0,0,0,,数据通路上有三个寄存器\nDialogue: 0,0:26:49.05,0:26:50.64,Default,,0,0,0,,但现在 这里有个减法器\nDialogue: 0,0:26:51.55,0:26:52.99,Default,,0,0,0,,又有两个东西被测试\nDialogue: 0,0:26:53.02,0:26:55.07,Default,,0,0,0,,B等于0么？\nDialogue: 0,0:26:55.23,0:26:56.56,Default,,0,0,0,,T小于B么？\nDialogue: 0,0:26:57.25,0:26:59.45,Default,,0,0,0,,而至于这一块的控制器\nDialogue: 0,0:27:00.22,0:27:01.76,Default,,0,0,0,,并不会更加复杂\nDialogue: 0,0:27:01.85,0:27:03.87,Default,,0,0,0,,它有两个循环\nDialogue: 0,0:27:04.52,0:27:08.33,Default,,0,0,0,,最主要的循环是计算GCD的\nDialogue: 0,0:27:08.40,0:27:10.14,Default,,0,0,0,,而另一条是减法循环\nDialogue: 0,0:27:10.43,0:27:12.80,Default,,0,0,0,,是用来计算余数的子操作\nDialogue: 0,0:27:14.03,0:27:15.80,Default,,0,0,0,,当然 还有一种思考方式\nDialogue: 0,0:27:15.96,0:27:18.68,Default,,0,0,0,,就是把求余数程序\nDialogue: 0,0:27:19.92,0:27:21.71,Default,,0,0,0,,如果我把那边的REMAINDER机器\nDialogue: 0,0:27:21.72,0:27:22.83,Default,,0,0,0,,当作LAMBDA表达式\nDialogue: 0,0:27:23.56,0:27:27.02,Default,,0,0,0,,代换到GCD程序的REMAINDER中\nDialogue: 0,0:27:28.20,0:27:30.12,Default,,0,0,0,,然后再做一些化简\nDialogue: 0,0:27:30.32,0:27:33.66,Default,,0,0,0,,代换其中的A和B\nDialogue: 0,0:27:34.46,0:27:35.95,Default,,0,0,0,,那么 我就可以展开这个循环\nDialogue: 0,0:27:36.63,0:27:39.42,Default,,0,0,0,,那么我就可以通过\nDialogue: 0,0:27:40.73,0:27:42.94,Default,,0,0,0,,LAMBDA表达式的基本代数化简\nDialogue: 0,0:27:43.36,0:27:45.21,Default,,0,0,0,,来得到这台机器\nDialogue: 0,0:27:48.55,0:27:51.20,Default,,0,0,0,,我想 你们已经见识了一个非常简单的机器了\nDialogue: 0,0:27:51.95,0:27:53.28,Default,,0,0,0,,有什么疑问么？\nDialogue: 0,0:28:02.70,0:28:03.10,Default,,0,0,0,,很好\nDialogue: 0,0:28:05.36,0:28:06.54,Default,,0,0,0,,看起来很容易 难道不是吗？\nDialogue: 0,0:28:10.14,0:28:11.32,Default,,0,0,0,,好吧 休息一下 谢谢大家\nDialogue: 0,0:28:12.54,0:28:24.94,Default,,0,0,0,,[音乐]\nDialogue: 0,0:28:25.13,0:28:28.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:31.37,0:28:34.70,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:28:34.76,0:28:38.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:38.00,0:28:43.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}寄存机器\nDialogue: 0,0:28:47.93,0:28:48.70,Default,,0,0,0,,教授：好吧\nDialogue: 0,0:28:49.37,0:28:52.46,Default,,0,0,0,,现在 你们已经知道如何去把迭代过程\nDialogue: 0,0:28:52.54,0:28:54.54,Default,,0,0,0,,或者是产生迭代计算的过程\nDialogue: 0,0:28:55.18,0:28:56.52,Default,,0,0,0,,变成一台机器\nDialogue: 0,0:28:57.77,0:29:00.04,Default,,0,0,0,,我想 接下来我们就应该考虑\nDialogue: 0,0:29:00.54,0:29:02.30,Default,,0,0,0,,如何来处理递归过程了\nDialogue: 0,0:29:02.81,0:29:05.05,Default,,0,0,0,,我们先从一个简单的阶乘过程开始\nDialogue: 0,0:29:11.20,0:29:16.94,Default,,0,0,0,,(DEFINE (FACT N)\nDialogue: 0,0:29:19.63,0:29:24.25,Default,,0,0,0,,如果N=1 那么结果就是1\nDialogue: 0,0:29:24.62,0:29:27.69,Default,,0,0,0,,为了减少模拟它的工作量 我就使用1\nDialogue: 0,0:29:28.12,0:29:33.94,Default,,0,0,0,,否则结果就是(* N (FACT (- N 1)))\nDialogue: 0,0:29:42.52,0:29:46.04,Default,,0,0,0,,正如你们所知 这个程序的不同之处在于\nDialogue: 0,0:29:46.65,0:29:50.36,Default,,0,0,0,,这里 我在计算(FACT (- N 1))之后\nDialogue: 0,0:29:50.67,0:29:52.26,Default,,0,0,0,,我要对结果做一些运算\nDialogue: 0,0:29:52.26,0:29:53.68,Default,,0,0,0,,我要将它与N相乘\nDialogue: 0,0:29:56.00,0:30:00.67,Default,,0,0,0,,将这台机器可视化的唯一途径就是\nDialogue: 0,0:30:01.08,0:30:02.01,Default,,0,0,0,,首先 由于--\nDialogue: 0,0:30:02.35,0:30:03.18,Default,,0,0,0,,请你们这么来想\nDialogue: 0,0:30:03.36,0:30:04.94,Default,,0,0,0,,这里 我有一台机器\nDialogue: 0,0:30:05.08,0:30:08.11,Default,,0,0,0,,而这台机器又需要某个阶乘机器来计算结果\nDialogue: 0,0:30:09.32,0:30:11.16,Default,,0,0,0,,但外面的这台机器\nDialogue: 0,0:30:11.20,0:30:13.02,Default,,0,0,0,,又需要在调用内部阶乘机器\nDialogue: 0,0:30:13.92,0:30:15.72,Default,,0,0,0,,的前后都要存在\nDialogue: 0,0:30:16.80,0:30:17.90,Default,,0,0,0,,然而在迭代情况中\nDialogue: 0,0:30:18.75,0:30:20.52,Default,,0,0,0,,外面的机器不需要\nDialogue: 0,0:30:20.91,0:30:24.01,Default,,0,0,0,,在内部机器运行后保持存在\nDialogue: 0,0:30:24.83,0:30:26.16,Default,,0,0,0,,这是因为你不需要回到\nDialogue: 0,0:30:26.19,0:30:27.53,Default,,0,0,0,,外部机器来进行其它操作\nDialogue: 0,0:30:28.64,0:30:30.06,Default,,0,0,0,,因此 我们这里的问题是\nDialogue: 0,0:30:30.27,0:30:30.97,Default,,0,0,0,,我们的机器内部\nDialogue: 0,0:30:31.00,0:30:32.73,Default,,0,0,0,,有一个同样的机器\nDialogue: 0,0:30:33.87,0:30:35.52,Default,,0,0,0,,一台无穷大的机器\nDialogue: 0,0:30:40.39,0:30:43.12,Default,,0,0,0,,这里面也有其它的东西 比如乘法器\nDialogue: 0,0:30:44.76,0:30:46.03,Default,,0,0,0,,它接收输入\nDialogue: 0,0:30:46.27,0:30:47.77,Default,,0,0,0,,这是-1操作\nDialogue: 0,0:30:48.12,0:30:49.31,Default,,0,0,0,,等等\nDialogue: 0,0:30:50.69,0:30:53.72,Default,,0,0,0,,你们可以想象 -- 它就是这个样子的\nDialogue: 0,0:30:54.37,0:30:56.76,Default,,0,0,0,,但重要之处就在于\nDialogue: 0,0:30:57.02,0:30:58.70,Default,,0,0,0,,内部机器执行之前与执行之后\nDialogue: 0,0:30:58.78,0:31:01.60,Default,,0,0,0,,外部机器中都进行了一些运算\nDialogue: 0,0:31:02.54,0:31:04.08,Default,,0,0,0,,因此这台机器必须有“生命”\nDialogue: 0,0:31:05.47,0:31:11.44,Default,,0,0,0,,外部机器需要在内部机器的两个时间点保持存在\nDialogue: 0,0:31:13.49,0:31:15.80,Default,,0,0,0,,因此 我就需要有一个地方来保存\nDialogue: 0,0:31:16.19,0:31:18.19,Default,,0,0,0,,维持外部机器运转的数据\nDialogue: 0,0:31:20.03,0:31:22.09,Default,,0,0,0,,现实世界中不存在无穷的对象\nDialogue: 0,0:31:24.14,0:31:25.58,Default,,0,0,0,,我们要做的就是营造一种假象\nDialogue: 0,0:31:26.12,0:31:27.48,Default,,0,0,0,,一种无穷对象的假象\nDialogue: 0,0:31:27.98,0:31:29.77,Default,,0,0,0,,我们在某处有无穷的硬件资源\nDialogue: 0,0:31:31.83,0:31:35.34,Default,,0,0,0,,现在 这个假象非常重要\nDialogue: 0,0:31:36.28,0:31:37.37,Default,,0,0,0,,如果我们能保证\nDialogue: 0,0:31:38.00,0:31:39.84,Default,,0,0,0,,每次当你查看某个无穷对象时\nDialogue: 0,0:31:39.88,0:31:42.96,Default,,0,0,0,,你所要观察的那部分存在\nDialogue: 0,0:31:44.49,0:31:46.04,Default,,0,0,0,,那么就不需要实际上的“无穷”\nDialogue: 0,0:31:47.39,0:31:49.44,Default,,0,0,0,,当然 这里面我们想做的就是\nDialogue: 0,0:31:49.82,0:31:52.49,Default,,0,0,0,,来看下这里的东西\nDialogue: 0,0:31:53.00,0:31:54.97,Default,,0,0,0,,这是我们目前为止的结构\nDialogue: 0,0:31:56.04,0:31:57.64,Default,,0,0,0,,这些结构呢\nDialogue: 0,0:31:57.92,0:32:01.37,Default,,0,0,0,,是机器的几大部分\nDialogue: 0,0:32:01.40,0:32:02.33,Default,,0,0,0,,比如控制器\nDialogue: 0,0:32:03.18,0:32:04.46,Default,,0,0,0,,它在这里\nDialogue: 0,0:32:04.78,0:32:07.61,Default,,0,0,0,,它相当简单 并且是有穷的\nDialogue: 0,0:32:09.17,0:32:10.44,Default,,0,0,0,,我们还有数据通路\nDialogue: 0,0:32:10.46,0:32:12.75,Default,,0,0,0,,它由寄存器和运算器组成\nDialogue: 0,0:32:13.08,0:32:15.20,Default,,0,0,0,,现在我提议\nDialogue: 0,0:32:15.48,0:32:16.96,Default,,0,0,0,,把机器分成两部分\nDialogue: 0,0:32:17.36,0:32:19.79,Default,,0,0,0,,这样 其中一部分全部是有穷的\nDialogue: 0,0:32:20.78,0:32:23.53,Default,,0,0,0,,而另一部分 可以保存无穷数据中的一部分\nDialogue: 0,0:32:24.23,0:32:25.90,Default,,0,0,0,,换句话说 这部分也非常简单\nDialogue: 0,0:32:26.41,0:32:28.72,Default,,0,0,0,,但并非无穷 只是非常大而已\nDialogue: 0,0:32:29.43,0:32:30.40,Default,,0,0,0,,但它非常简单\nDialogue: 0,0:32:30.52,0:32:32.92,Default,,0,0,0,,以至于能够廉价地大量生产\nDialogue: 0,0:32:34.09,0:32:34.92,Default,,0,0,0,,它就是内存\nDialogue: 0,0:32:35.95,0:32:39.07,Default,,0,0,0,,我们可以利用它来构造栈结构\nDialogue: 0,0:32:39.40,0:32:41.23,Default,,0,0,0,,事实上 这就使得我们\nDialogue: 0,0:32:41.45,0:32:43.63,Default,,0,0,0,,能够模拟无穷机器的存在\nDialogue: 0,0:32:43.64,0:32:46.96,Default,,0,0,0,,也就是那些递归嵌套的机器\nDialogue: 0,0:32:48.34,0:32:50.43,Default,,0,0,0,,而它的原理则是\nDialogue: 0,0:32:50.56,0:32:52.97,Default,,0,0,0,,我们要在栈上存放必要的信息\nDialogue: 0,0:32:54.30,0:32:57.58,Default,,0,0,0,,用于内部机器执行完毕后\nDialogue: 0,0:32:59.18,0:33:01.07,Default,,0,0,0,,继续外部机器的操作\nDialogue: 0,0:33:03.84,0:33:05.48,Default,,0,0,0,,因此它会记住\nDialogue: 0,0:33:05.63,0:33:07.95,Default,,0,0,0,,关于外部机器生命期的重要数据\nDialogue: 0,0:33:08.04,0:33:10.30,Default,,0,0,0,,这些是进行计算所必需的\nDialogue: 0,0:33:11.39,0:33:12.48,Default,,0,0,0,,当然\nDialogue: 0,0:33:12.75,0:33:16.33,Default,,0,0,0,,由于这些机器是通过递归的方式嵌套的\nDialogue: 0,0:33:18.33,0:33:23.39,Default,,0,0,0,,因此 栈的存取方式也会是\nDialogue: 0,0:33:23.45,0:33:26.44,Default,,0,0,0,,也会是后进先出的\nDialogue: 0,0:33:29.33,0:33:30.64,Default,,0,0,0,,因此我们只需要存取\nDialogue: 0,0:33:30.80,0:33:32.52,Default,,0,0,0,,这个栈内存的一小部分\nDialogue: 0,0:33:34.93,0:33:35.92,Default,,0,0,0,,好吧 让我们来试一试\nDialogue: 0,0:33:36.81,0:33:38.41,Default,,0,0,0,,我已经给你们画好了数据通路\nDialogue: 0,0:33:38.44,0:33:39.68,Default,,0,0,0,,现在该布置控制器了\nDialogue: 0,0:33:40.37,0:33:42.86,Default,,0,0,0,,然后我们来运行一下 观察实际工作原理\nDialogue: 0,0:33:43.51,0:33:46.88,Default,,0,0,0,,还好阶乘机器不是特别的复杂\nDialogue: 0,0:33:47.90,0:33:50.16,Default,,0,0,0,,它有一个VAL寄存器\nDialogue: 0,0:33:52.22,0:33:53.88,Default,,0,0,0,,这是用来存储答案的\nDialogue: 0,0:33:54.89,0:33:56.67,Default,,0,0,0,,还有一个寄存器N\nDialogue: 0,0:33:59.85,0:34:04.16,Default,,0,0,0,,它里面存储的是要计算阶乘的数\nDialogue: 0,0:34:04.51,0:34:06.57,Default,,0,0,0,,为了满足某些情况\nDialogue: 0,0:34:07.48,0:34:10.52,Default,,0,0,0,,我们要连接VAL和N\nDialogue: 0,0:34:11.74,0:34:15.63,Default,,0,0,0,,事实上 如果我在这里返回N\nDialogue: 0,0:34:16.38,0:34:19.53,Default,,0,0,0,,也是正确的 因为这时N就等于1\nDialogue: 0,0:34:20.09,0:34:23.26,Default,,0,0,0,,这样的话 我就可以把结果移动过去\nDialogue: 0,0:34:23.90,0:34:25.55,Default,,0,0,0,,但我现在不考虑这个问题\nDialogue: 0,0:34:26.98,0:34:28.60,Default,,0,0,0,,我还需要做一些事情\nDialogue: 0,0:34:29.06,0:34:31.02,Default,,0,0,0,,就像我们在这里看到的 我们还需要\nDialogue: 0,0:34:31.21,0:34:34.67,Default,,0,0,0,,用VAL的值乘以N\nDialogue: 0,0:34:34.91,0:34:37.45,Default,,0,0,0,,因为VAL是计算阶乘的结果\nDialogue: 0,0:34:38.68,0:34:40.44,Default,,0,0,0,,我需要把算得的结果送回VAL\nDialogue: 0,0:34:41.48,0:34:42.65,Default,,0,0,0,,所以这里我们看到\nDialogue: 0,0:34:42.83,0:34:46.43,Default,,0,0,0,,N的阶乘就是\nDialogue: 0,0:34:46.57,0:34:49.20,Default,,0,0,0,,N乘以某个阶乘\nDialogue: 0,0:34:50.69,0:34:53.77,Default,,0,0,0,,而VAL就代表了内部阶乘的结果\nDialogue: 0,0:34:55.19,0:35:00.25,Default,,0,0,0,,因此 在这里我需要有一个乘法器\nDialogue: 0,0:35:02.36,0:35:07.18,Default,,0,0,0,,它的参数有：N以及VAL\nDialogue: 0,0:35:08.64,0:35:15.60,Default,,0,0,0,,并且 像这样把计算结果送回VAL\nDialogue: 0,0:35:17.17,0:35:19.39,Default,,0,0,0,,我也需要知道N是否为1\nDialogue: 0,0:35:21.32,0:35:22.38,Default,,0,0,0,,因此我需要一个指示灯\nDialogue: 0,0:35:28.20,0:35:30.40,Default,,0,0,0,,另外 我想我还需要\nDialogue: 0,0:35:31.02,0:35:32.84,Default,,0,0,0,,一个组件来减小N\nDialogue: 0,0:35:34.84,0:35:36.09,Default,,0,0,0,,所以这里有一个递减器\nDialogue: 0,0:35:38.19,0:35:41.39,Default,,0,0,0,,它接收参数N 将结果送回N\nDialogue: 0,0:35:46.62,0:35:48.40,Default,,0,0,0,,这基本上就是我的机器所需要的东西了\nDialogue: 0,0:35:49.55,0:35:51.64,Default,,0,0,0,,然而 我还需要一些个东西\nDialogue: 0,0:35:52.30,0:35:53.58,Default,,0,0,0,,一个稍微复杂一点的东西\nDialogue: 0,0:35:55.16,0:35:56.88,Default,,0,0,0,,因为我需要有一种方式能够存储\nDialogue: 0,0:35:57.16,0:35:59.69,Default,,0,0,0,,必要的一些信息\nDialogue: 0,0:36:01.02,0:36:03.07,Default,,0,0,0,,以便计算完子阶乘后\nDialogue: 0,0:36:03.10,0:36:04.89,Default,,0,0,0,,恢复原始阶乘的计算\nDialogue: 0,0:36:06.25,0:36:06.86,Default,,0,0,0,,需要哪些信息呢?\nDialogue: 0,0:36:07.23,0:36:08.73,Default,,0,0,0,,首先就是N\nDialogue: 0,0:36:09.85,0:36:12.04,Default,,0,0,0,,因此 我要在这里构造一个栈\nDialogue: 0,0:36:14.70,0:36:15.77,Default,,0,0,0,,所谓的栈就是\nDialogue: 0,0:36:17.98,0:36:24.97,Default,,0,0,0,,一大堆连续的空间\nDialogue: 0,0:36:27.15,0:36:28.59,Default,,0,0,0,,我不知道它到底有多深\nDialogue: 0,0:36:29.15,0:36:31.48,Default,,0,0,0,,栈越深 无穷的假象营造得就越好\nDialogue: 0,0:36:33.23,0:36:35.56,Default,,0,0,0,,我还需要有一种方法 能够把\nDialogue: 0,0:36:35.60,0:36:37.02,Default,,0,0,0,,N中的值放入栈中\nDialogue: 0,0:36:38.12,0:36:39.08,Default,,0,0,0,,反过来也是\nDialogue: 0,0:36:39.93,0:36:41.74,Default,,0,0,0,,因此我需要一条像这样的连接\nDialogue: 0,0:36:44.41,0:36:45.48,Default,,0,0,0,,它是双向的\nDialogue: 0,0:36:50.44,0:36:52.22,Default,,0,0,0,,通过它 我就可以在某个时间\nDialogue: 0,0:36:52.24,0:36:55.50,Default,,0,0,0,,把N的值存储起来\nDialogue: 0,0:36:56.04,0:36:56.84,Default,,0,0,0,,这就是栈\nDialogue: 0,0:36:58.10,0:37:01.71,Default,,0,0,0,,我还需要一种方法来记住\nDialogue: 0,0:37:01.84,0:37:07.72,Default,,0,0,0,,我现在计算到外部程序的哪个地方了\nDialogue: 0,0:37:08.53,0:37:10.06,Default,,0,0,0,,现在 对于这台机器来说\nDialogue: 0,0:37:10.76,0:37:13.34,Default,,0,0,0,,这并不是什么问题\nDialogue: 0,0:37:14.17,0:37:16.24,Default,,0,0,0,,FACT总是返回在\nDialogue: 0,0:37:16.86,0:37:19.07,Default,,0,0,0,,一个跟N相乘的地方\nDialogue: 0,0:37:19.34,0:37:20.72,Default,,0,0,0,,除了最后的一次\nDialogue: 0,0:37:21.15,0:37:23.02,Default,,0,0,0,,它返回到需要FACT最终答案的地方\nDialogue: 0,0:37:23.04,0:37:24.04,Default,,0,0,0,,或者是'DONE、'STOP之类的\nDialogue: 0,0:37:25.66,0:37:26.67,Default,,0,0,0,,然而 通常来说\nDialogue: 0,0:37:27.16,0:37:28.73,Default,,0,0,0,,我需要记住我去过哪些地方\nDialogue: 0,0:37:29.13,0:37:31.24,Default,,0,0,0,,因为 我可能从其它地方调用FACT\nDialogue: 0,0:37:32.08,0:37:34.89,Default,,0,0,0,,我需要返回到那个地方 并从那里继续\nDialogue: 0,0:37:36.07,0:37:38.00,Default,,0,0,0,,因此 我需要有一种方法能够\nDialogue: 0,0:37:38.01,0:37:40.86,Default,,0,0,0,,记住有穷状态控制器中弹珠的位置\nDialogue: 0,0:37:41.32,0:37:42.64,Default,,0,0,0,,也就是控制器的状态\nDialogue: 0,0:37:44.22,0:37:46.35,Default,,0,0,0,,并将它存储在栈中\nDialogue: 0,0:37:47.40,0:37:49.10,Default,,0,0,0,,我也需要有一种方法\nDialogue: 0,0:37:49.45,0:37:51.12,Default,,0,0,0,,能够恢复弹珠的状态\nDialogue: 0,0:37:52.14,0:37:54.28,Default,,0,0,0,,因此 我需要有一种将弹珠归位的能力\nDialogue: 0,0:37:54.70,0:37:56.52,Default,,0,0,0,,现在 我们有一个地方用于存储弹珠\nDialogue: 0,0:37:57.87,0:37:59.34,Default,,0,0,0,,它被称作“继续”寄存器\nDialogue: 0,0:38:03.61,0:38:04.52,Default,,0,0,0,,记作CONTINUE\nDialogue: 0,0:38:09.16,0:38:10.68,Default,,0,0,0,,下一次调用(GOTO CONTINUE)时\nDialogue: 0,0:38:11.00,0:38:13.05,Default,,0,0,0,,弹珠就会去向这个地方\nDialogue: 0,0:38:14.91,0:38:15.92,Default,,0,0,0,,它就是用来干这个的\nDialogue: 0,0:38:16.14,0:38:18.48,Default,,0,0,0,,因此 它和控制器之间应该有一条通路\nDialogue: 0,0:38:22.91,0:38:27.12,Default,,0,0,0,,我也能够将它存储在栈上\nDialogue: 0,0:38:29.45,0:38:33.10,Default,,0,0,0,,我也能够把它设置成各种常量\nDialogue: 0,0:38:34.01,0:38:35.69,Default,,0,0,0,,某一些常量\nDialogue: 0,0:38:36.86,0:38:38.20,Default,,0,0,0,,这非常容易实现\nDialogue: 0,0:38:38.84,0:38:40.14,Default,,0,0,0,,我们现在这里设一些常量\nDialogue: 0,0:38:40.18,0:38:41.50,Default,,0,0,0,,我们把这个记作AFTER-FACT\nDialogue: 0,0:38:47.32,0:38:48.75,Default,,0,0,0,,这个常量\nDialogue: 0,0:38:48.84,0:38:51.50,Default,,0,0,0,,会送入CONTINUE寄存器\nDialogue: 0,0:38:52.59,0:38:54.43,Default,,0,0,0,,另外一个寄存器是FACT-DONE\nDialogue: 0,0:39:05.21,0:39:07.82,Default,,0,0,0,,这就是我想要构建的机器\nDialogue: 0,0:39:08.13,0:39:09.48,Default,,0,0,0,,至少是数据通路部分\nDialogue: 0,0:39:09.92,0:39:11.69,Default,,0,0,0,,这里还混合了一些控制器\nDialogue: 0,0:39:11.85,0:39:14.59,Default,,0,0,0,,这是因为我需要记住我当前的位置\nDialogue: 0,0:39:14.70,0:39:16.35,Default,,0,0,0,,并将我恢复到该位置\nDialogue: 0,0:39:17.30,0:39:19.93,Default,,0,0,0,,现在 让我们来编写控制器对应的程序\nDialogue: 0,0:39:20.39,0:39:23.47,Default,,0,0,0,,我就把DEFINE-MACHINE和寄存器列表给省略了\nDialogue: 0,0:39:23.48,0:39:24.89,Default,,0,0,0,,因为它们无关紧要\nDialogue: 0,0:39:25.13,0:39:27.79,Default,,0,0,0,,我就直接写那些跟控制器有关的\nDialogue: 0,0:39:27.82,0:39:29.02,Default,,0,0,0,,指令序列\nDialogue: 0,0:39:31.48,0:39:41.85,Default,,0,0,0,,首先是(ASSIGN CONTINUE DONE)\nDialogue: 0,0:39:45.15,0:39:45.82,Default,,0,0,0,,然后是一个循环\nDialogue: 0,0:39:47.34,0:39:56.08,Default,,0,0,0,,先判断 如果1=N 那么就跳转\nDialogue: 0,0:40:00.94,0:40:04.11,Default,,0,0,0,,那么就进入归纳的基本步骤\nDialogue: 0,0:40:06.06,0:40:07.20,Default,,0,0,0,,也就是最简单的情况\nDialogue: 0,0:40:08.05,0:40:08.76,Default,,0,0,0,,否则的话\nDialogue: 0,0:40:08.88,0:40:10.84,Default,,0,0,0,,我就要记住那些\nDialogue: 0,0:40:10.88,0:40:13.84,Default,,0,0,0,,计算子阶乘所必须的信息\nDialogue: 0,0:40:14.67,0:40:16.75,Default,,0,0,0,,我需要来带这里 以便计算子阶乘\nDialogue: 0,0:40:17.57,0:40:19.29,Default,,0,0,0,,所以我需要记住 完成它需要些什么\nDialogue: 0,0:40:19.71,0:40:22.52,Default,,0,0,0,,需要记住我计算完之后需要哪些东西\nDialogue: 0,0:40:24.00,0:40:25.51,Default,,0,0,0,,看到了吗 我要做些糟糕的事儿\nDialogue: 0,0:40:25.72,0:40:27.39,Default,,0,0,0,,我要去修改N的值\nDialogue: 0,0:40:28.57,0:40:30.40,Default,,0,0,0,,但是它又需要记住N的旧值\nDialogue: 0,0:40:32.14,0:40:33.64,Default,,0,0,0,,但是为了计算子阶乘\nDialogue: 0,0:40:33.66,0:40:34.92,Default,,0,0,0,,我又需要修改N的值\nDialogue: 0,0:40:35.60,0:40:37.10,Default,,0,0,0,,因此 我就得记住N的旧值\nDialogue: 0,0:40:38.00,0:40:39.60,Default,,0,0,0,,我也需要记住我的位置\nDialogue: 0,0:40:40.85,0:40:42.32,Default,,0,0,0,,因此 我保存CONTINUE的值\nDialogue: 0,0:40:47.70,0:40:51.29,Default,,0,0,0,,这条指令 就是用来将数据入栈的\nDialogue: 0,0:40:53.12,0:40:55.53,Default,,0,0,0,,将CONTINUE寄存器的值保存起来\nDialogue: 0,0:40:56.51,0:40:58.00,Default,,0,0,0,,在本例中也就是DONE\nDialogue: 0,0:40:58.88,0:41:00.25,Default,,0,0,0,,因为稍后我也会修改它\nDialogue: 0,0:41:00.27,0:41:02.78,Default,,0,0,0,,因为我也需要回到AFTER-FACT\nDialogue: 0,0:41:03.55,0:41:04.19,Default,,0,0,0,,我们来看看\nDialogue: 0,0:41:05.04,0:41:09.71,Default,,0,0,0,,我们需要存储N 因为稍后会用到\nDialogue: 0,0:41:10.38,0:41:20.54,Default,,0,0,0,,(ASSIGN N (-1+ (FETCH N)))\nDialogue: 0,0:41:23.26,0:41:28.97,Default,,0,0,0,,(ASSIGN CONTINUE ...\nDialogue: 0,0:41:32.12,0:41:33.42,Default,,0,0,0,,我看一下 --\nDialogue: 0,0:41:34.06,0:41:35.61,Default,,0,0,0,,AFT)\nDialogue: 0,0:41:37.69,0:41:38.70,Default,,0,0,0,,这个名字很好\nDialogue: 0,0:41:38.73,0:41:40.65,Default,,0,0,0,,因为它短小精炼 很适合用在这里\nDialogue: 0,0:41:53.36,0:41:54.64,Default,,0,0,0,,现在 来看看我怎么做\nDialogue: 0,0:41:55.33,0:41:57.02,Default,,0,0,0,,我说 如果ANSWER是1的话\nDialogue: 0,0:41:58.72,0:41:59.66,Default,,0,0,0,,那程序就结束了\nDialogue: 0,0:42:00.46,0:42:01.66,Default,,0,0,0,,我只需要取得这个答案\nDialogue: 0,0:42:02.15,0:42:04.88,Default,,0,0,0,,否则我就要保存当前的继续以及N的值\nDialogue: 0,0:42:05.77,0:42:07.32,Default,,0,0,0,,然后让N减1\nDialogue: 0,0:42:07.60,0:42:09.63,Default,,0,0,0,,注意 我先要跳转到某处\nDialogue: 0,0:42:09.64,0:42:11.48,Default,,0,0,0,,然后来到这里 计算另外的阶乘\nDialogue: 0,0:42:13.50,0:42:15.74,Default,,0,0,0,,然而 这之中又有了另外的机器\nDialogue: 0,0:42:16.05,0:42:18.38,Default,,0,0,0,,其中N=1 CONTINUE是其它值\nDialogue: 0,0:42:22.11,0:42:23.21,Default,,0,0,0,,N=N-1\nDialogue: 0,0:42:23.77,0:42:25.28,Default,,0,0,0,,再我完成这个之后\nDialogue: 0,0:42:26.94,0:42:27.76,Default,,0,0,0,,我会来到这里\nDialogue: 0,0:42:28.66,0:42:30.46,Default,,0,0,0,,我会恢复N的旧值\nDialogue: 0,0:42:32.68,0:42:36.56,Default,,0,0,0,,也就是这里SAVE的逆运算\nDialogue: 0,0:42:38.36,0:42:39.88,Default,,0,0,0,,然后恢复CONTINUE\nDialogue: 0,0:42:49.66,0:42:52.57,Default,,0,0,0,,然后我又会来到这里\nDialogue: 0,0:42:54.32,0:43:00.86,Default,,0,0,0,,(ASSIGN VAL\nDialogue: 0,0:43:01.16,0:43:08.13,Default,,0,0,0,,(* (FETCH N) (FETCH VAL)))\nDialogue: 0,0:43:13.44,0:43:18.30,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:43:19.79,0:43:21.44,Default,,0,0,0,,这样操作就完成了\nDialogue: 0,0:43:21.44,0:43:25.68,Default,,0,0,0,,子阶乘的结果就存储在了VAL中\nDialogue: 0,0:43:26.57,0:43:27.37,Default,,0,0,0,,这个时候\nDialogue: 0,0:43:27.66,0:43:28.75,Default,,0,0,0,,我就要返回到\nDialogue: 0,0:43:29.28,0:43:31.61,Default,,0,0,0,,CONTINUE所指向的地方\nDialogue: 0,0:43:33.64,0:43:35.77,Default,,0,0,0,,也就是(GOTO (FETCH CONTINUE))\nDialogue: 0,0:43:45.87,0:43:47.40,Default,,0,0,0,,最后就是基本情况的那步\nDialogue: 0,0:43:49.31,0:43:50.51,Default,,0,0,0,,也就是一个立即值\nDialogue: 0,0:43:50.68,0:43:56.88,Default,,0,0,0,,(ASSIGN VAL (FETCH N))\nDialogue: 0,0:44:01.36,0:44:02.75,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,0:44:12.67,0:44:13.55,Default,,0,0,0,,这样我就完成了\nDialogue: 0,0:44:18.64,0:44:21.21,Default,,0,0,0,,现在 我们用一个非常简单的例子来运行一下\nDialogue: 0,0:44:22.51,0:44:23.53,Default,,0,0,0,,因为这样我们就将看到\nDialogue: 0,0:44:23.66,0:44:26.52,Default,,0,0,0,,栈是如何帮助我们完成计算的\nDialogue: 0,0:44:26.89,0:44:28.22,Default,,0,0,0,,这是计算的静态描述\nDialogue: 0,0:44:28.22,0:44:29.80,Default,,0,0,0,,我们需要动态地观察它\nDialogue: 0,0:44:31.34,0:44:32.09,Default,,0,0,0,,因此 让我们来看看\nDialogue: 0,0:44:32.30,0:44:34.56,Default,,0,0,0,,首先我们要把CONTINUE设置为DONE\nDialogue: 0,0:44:36.73,0:44:38.09,Default,,0,0,0,,这是我通过按下这个钮来实现的\nDialogue: 0,0:44:38.30,0:44:39.60,Default,,0,0,0,,我们还是把它记作DONE吧\nDialogue: 0,0:44:46.22,0:44:47.03,Default,,0,0,0,,我按下这个按钮\nDialogue: 0,0:44:47.03,0:44:48.11,Default,,0,0,0,,DONE就进到了这里\nDialogue: 0,0:44:48.95,0:44:53.71,Default,,0,0,0,,现在 我还要为这些东西设置初始值\nDialogue: 0,0:44:53.85,0:44:58.08,Default,,0,0,0,,让我们考虑3的阶乘\nDialogue: 0,0:44:58.38,0:44:59.24,Default,,0,0,0,,这个例子非常简单\nDialogue: 0,0:45:00.54,0:45:04.04,Default,,0,0,0,,我们的栈从这里开始增长\nDialogue: 0,0:45:05.90,0:45:07.76,Default,,0,0,0,,栈有它们自己的内部状态\nDialogue: 0,0:45:07.79,0:45:09.05,Default,,0,0,0,,用来标识栈顶位置\nDialogue: 0,0:45:09.80,0:45:11.64,Default,,0,0,0,,也就是下一个可写位置\nDialogue: 0,0:45:12.77,0:45:14.59,Default,,0,0,0,,现在我们问 N=1么？\nDialogue: 0,0:45:14.76,0:45:15.71,Default,,0,0,0,,当然不等于\nDialogue: 0,0:45:16.11,0:45:18.56,Default,,0,0,0,,因此现在我要保存CONTINUE\nDialogue: 0,0:45:19.15,0:45:20.65,Default,,0,0,0,,现在 DONE就来到了这里\nDialogue: 0,0:45:22.08,0:45:23.55,Default,,0,0,0,,然后 这个指针移动到了这里\nDialogue: 0,0:45:24.88,0:45:26.14,Default,,0,0,0,,下次我要把数据写到这里\nDialogue: 0,0:45:26.66,0:45:28.78,Default,,0,0,0,,保存N的值--也就是3\nDialogue: 0,0:45:29.95,0:45:30.32,Default,,0,0,0,,对吧？\nDialogue: 0,0:45:30.67,0:45:33.61,Default,,0,0,0,,N←N-1\nDialogue: 0,0:45:33.96,0:45:35.37,Default,,0,0,0,,也就是说 我得按下这个钮\nDialogue: 0,0:45:35.94,0:45:37.32,Default,,0,0,0,,这就变成了2\nDialogue: 0,0:45:38.73,0:45:42.28,Default,,0,0,0,,COUNTINUE←AFT\nDialogue: 0,0:45:42.58,0:45:43.61,Default,,0,0,0,,因此我要按下这个钮\nDialogue: 0,0:45:43.61,0:45:44.54,Default,,0,0,0,,AFT就进入了这里\nDialogue: 0,0:45:49.14,0:45:53.93,Default,,0,0,0,,然后 跳转到LOOP 我们就来到了这里\nDialogue: 0,0:45:54.83,0:45:57.08,Default,,0,0,0,,N=1么？当然不\nDialogue: 0,0:45:57.78,0:45:59.23,Default,,0,0,0,,因此我又要保存CONTINUE\nDialogue: 0,0:45:59.49,0:46:00.27,Default,,0,0,0,,CONTINUE的值是什么呢？\nDialogue: 0,0:46:00.60,0:46:01.53,Default,,0,0,0,,目前是AFT\nDialogue: 0,0:46:01.53,0:46:02.32,Default,,0,0,0,,按下这个按钮\nDialogue: 0,0:46:02.78,0:46:03.95,Default,,0,0,0,,这个指针移动到了这里\nDialogue: 0,0:46:08.49,0:46:09.74,Default,,0,0,0,,我还要保存N\nDialogue: 0,0:46:10.51,0:46:12.12,Default,,0,0,0,,N在那里 它的值是2\nDialogue: 0,0:46:12.28,0:46:13.37,Default,,0,0,0,,按下这个按钮\nDialogue: 0,0:46:13.85,0:46:15.24,Default,,0,0,0,,2就进入了这里\nDialogue: 0,0:46:16.05,0:46:17.64,Default,,0,0,0,,然后这个指针移动到了这里\nDialogue: 0,0:46:20.06,0:46:22.60,Default,,0,0,0,,保存N之后 又赋N←N-1\nDialogue: 0,0:46:24.60,0:46:25.46,Default,,0,0,0,,它就变成了1\nDialogue: 0,0:46:29.24,0:46:30.54,Default,,0,0,0,,CONTINUE←AFT\nDialogue: 0,0:46:31.37,0:46:34.48,Default,,0,0,0,,AFT又进入了这里\nDialogue: 0,0:46:34.96,0:46:35.64,Default,,0,0,0,,然后又跳转到LOOP\nDialogue: 0,0:46:36.52,0:46:37.74,Default,,0,0,0,,N等于1么？\nDialogue: 0,0:46:37.93,0:46:39.52,Default,,0,0,0,,是的 那么答案就是1\nDialogue: 0,0:46:41.04,0:46:43.26,Default,,0,0,0,,跳转到BASE那一步\nDialogue: 0,0:46:44.16,0:46:45.77,Default,,0,0,0,,(ASSIGN VAL (FETCH N))\nDialogue: 0,0:46:46.56,0:46:50.72,Default,,0,0,0,,按下这个 1就进入到了这里\nDialogue: 0,0:46:51.10,0:46:52.20,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,0:46:52.20,0:46:53.53,Default,,0,0,0,,来看下CONTINUE寄存器\nDialogue: 0,0:46:53.68,0:46:56.06,Default,,0,0,0,,基本上来说 我按下这里的按钮 进入到控制器\nDialogue: 0,0:46:56.67,0:46:58.28,Default,,0,0,0,,CONTINUE寄存器就变成了AFT\nDialogue: 0,0:46:58.32,0:47:00.25,Default,,0,0,0,,这样一下子 程序就运行到了这里\nDialogue: 0,0:47:02.64,0:47:05.63,Default,,0,0,0,,现在 我就需要恢复外部的阶乘了\nDialogue: 0,0:47:06.65,0:47:07.55,Default,,0,0,0,,因此我们来到这里\nDialogue: 0,0:47:07.55,0:47:09.48,Default,,0,0,0,,我们先要恢复N\nDialogue: 0,0:47:10.32,0:47:13.04,Default,,0,0,0,,这就意味着 我们要使用这里的内容\nDialogue: 0,0:47:13.94,0:47:18.17,Default,,0,0,0,,按下这个按钮 2就会来到这里\nDialogue: 0,0:47:18.56,0:47:20.04,Default,,0,0,0,,然后指针会向上移动\nDialogue: 0,0:47:21.98,0:47:24.49,Default,,0,0,0,,恢复CONTINUE寄存器也非常简单\nDialogue: 0,0:47:24.81,0:47:26.49,Default,,0,0,0,,来按下这个按钮\nDialogue: 0,0:47:27.02,0:47:28.92,Default,,0,0,0,,然后 AFT又一次进入到这里\nDialogue: 0,0:47:31.28,0:47:32.64,Default,,0,0,0,,同时 这个指针也要上移\nDialogue: 0,0:47:32.64,0:47:35.19,Default,,0,0,0,,这样就避开了栈上的其它东西\nDialogue: 0,0:47:42.24,0:47:43.47,Default,,0,0,0,,然后我来到这里\nDialogue: 0,0:47:43.87,0:47:47.15,Default,,0,0,0,,也就是(ASSIGN VAL (* N VAL))\nDialogue: 0,0:47:47.85,0:47:50.57,Default,,0,0,0,,然后我按下这个按钮\nDialogue: 0,0:47:50.97,0:47:52.91,Default,,0,0,0,,2乘以1等于2\nDialogue: 0,0:47:54.01,0:47:54.75,Default,,0,0,0,,我写到这里\nDialogue: 0,0:47:55.76,0:47:57.20,Default,,0,0,0,,然后是(GOTO (FETCH CONTINUE))\nDialogue: 0,0:47:57.54,0:47:59.85,Default,,0,0,0,,CONTINUE现在是AFT 我跳转到AFT\nDialogue: 0,0:48:01.15,0:48:03.88,Default,,0,0,0,,AFT首先要恢复N\nDialogue: 0,0:48:04.36,0:48:05.72,Default,,0,0,0,,恢复N指的是\nDialogue: 0,0:48:05.87,0:48:08.44,Default,,0,0,0,,我把这里的值 也就是3\nDialogue: 0,0:48:09.24,0:48:10.33,Default,,0,0,0,,按下这里的按钮\nDialogue: 0,0:48:10.60,0:48:15.50,Default,,0,0,0,,然后把它放到这里 N\nDialogue: 0,0:48:16.25,0:48:17.34,Default,,0,0,0,,然后 我们按下这个钮\nDialogue: 0,0:48:18.01,0:48:19.90,Default,,0,0,0,,接下来我就要恢复CONTINUE\nDialogue: 0,0:48:20.20,0:48:22.20,Default,,0,0,0,,CONTINUE寄存器现在成为了DONE\nDialogue: 0,0:48:22.83,0:48:26.78,Default,,0,0,0,,当我按下这个钮后 指针就移动到了这里\nDialogue: 0,0:48:27.13,0:48:29.72,Default,,0,0,0,,DONE可能从此之后不在这里了\nDialogue: 0,0:48:29.72,0:48:31.55,Default,,0,0,0,,对此我并不感兴趣 但它现在一定在这里\nDialogue: 0,0:48:35.80,0:48:38.12,Default,,0,0,0,,下一步 我将要把VAL赋值为\nDialogue: 0,0:48:38.43,0:48:40.76,Default,,0,0,0,,N乘以VAL的值\nDialogue: 0,0:48:41.44,0:48:44.30,Default,,0,0,0,,按下这里的按钮就可以实现\nDialogue: 0,0:48:44.30,0:48:45.77,Default,,0,0,0,,2乘以3等于6\nDialogue: 0,0:48:46.52,0:48:47.87,Default,,0,0,0,,所以这里我就得到了6\nDialogue: 0,0:48:50.97,0:48:53.40,Default,,0,0,0,,下一步是(GOTO (FETCH CONTINUE))\nDialogue: 0,0:48:53.48,0:48:54.83,Default,,0,0,0,,哦 跳转到DONE 这样我就完成了\nDialogue: 0,0:48:55.02,0:48:56.09,Default,,0,0,0,,最后的答案是6\nDialogue: 0,0:48:56.60,0:48:57.82,Default,,0,0,0,,你们可以在VAL寄存器中看到\nDialogue: 0,0:48:58.95,0:48:59.82,Default,,0,0,0,,事实上\nDialogue: 0,0:49:00.91,0:49:03.34,Default,,0,0,0,,栈又回到了它初始的状态\nDialogue: 0,0:49:08.20,0:49:10.70,Default,,0,0,0,,在使用像栈这样的东西中 有一些原则\nDialogue: 0,0:49:11.20,0:49:12.27,Default,,0,0,0,,我们需要注意\nDialogue: 0,0:49:13.62,0:49:15.52,Default,,0,0,0,,我们会在下一小节中介绍\nDialogue: 0,0:49:16.26,0:49:18.46,Default,,0,0,0,,但首先 对于这一小节所讲的内容\nDialogue: 0,0:49:28.56,0:49:29.64,Default,,0,0,0,,有什么问题么？\nDialogue: 0,0:49:30.17,0:49:30.63,Default,,0,0,0,,Ron 请讲\nDialogue: 0,0:49:30.63,0:49:33.37,Default,,0,0,0,,学生：当你越过了栈的顶端会怎样--\nDialogue: 0,0:49:33.39,0:49:34.62,Default,,0,0,0,,教授：你所谓的“越过”是指什么？\nDialogue: 0,0:49:35.03,0:49:37.50,Default,,0,0,0,,学生：如果我们的N是一个很大的数\nDialogue: 0,0:49:37.52,0:49:38.72,Default,,0,0,0,,就需要更多的内存 对吧？\nDialogue: 0,0:49:38.86,0:49:39.44,Default,,0,0,0,,教授：是的\nDialogue: 0,0:49:39.44,0:49:41.12,Default,,0,0,0,,这样 我就需要一个足够大的栈\nDialogue: 0,0:49:41.53,0:49:43.20,Default,,0,0,0,,你想问 如果破坏了无穷存储的假象会发生什么？\nDialogue: 0,0:49:43.84,0:49:44.12,Default,,0,0,0,,学生：是的\nDialogue: 0,0:49:44.55,0:49:46.73,Default,,0,0,0,,教授：那么 这些魔法就不再起效了\nDialogue: 0,0:49:47.96,0:49:51.00,Default,,0,0,0,,真相就是 任何机器都是有穷的\nDialogue: 0,0:49:51.64,0:49:53.72,Default,,0,0,0,,而对于像这样的过程\nDialogue: 0,0:49:54.17,0:49:58.86,Default,,0,0,0,,我只能进行有限数量的子阶乘计算\nDialogue: 0,0:49:59.95,0:50:02.48,Default,,0,0,0,,想一想 我们之前讲解的Y组合子\nDialogue: 0,0:50:02.80,0:50:06.22,Default,,0,0,0,,我们指出 存在一系列的指数过程\nDialogue: 0,0:50:06.25,0:50:08.09,Default,,0,0,0,,其中每一个都要比前一个更精准\nDialogue: 0,0:50:08.72,0:50:11.60,Default,,0,0,0,,现在 我们看到了如何实现这个数学理念\nDialogue: 0,0:50:13.09,0:50:14.19,Default,,0,0,0,,这个取极限的过程\nDialogue: 0,0:50:14.35,0:50:16.33,Default,,0,0,0,,只有当你取到极限时才足够精准\nDialogue: 0,0:50:17.99,0:50:19.42,Default,,0,0,0,,如果你仔细想想 我这里用了什么\nDialogue: 0,0:50:19.42,0:50:22.65,Default,,0,0,0,,对于这个过程的每一次递归\nDialogue: 0,0:50:23.04,0:50:27.07,Default,,0,0,0,,我用了大概两块内存\nDialogue: 0,0:50:29.10,0:50:31.71,Default,,0,0,0,,如果我们尝试计算10000的阶乘\nDialogue: 0,0:50:31.72,0:50:32.81,Default,,0,0,0,,这并不会花掉很多内存\nDialogue: 0,0:50:33.18,0:50:34.68,Default,,0,0,0,,虽然这是一个很大的数\nDialogue: 0,0:50:35.95,0:50:38.41,Default,,0,0,0,,因此 实际的问题就是值不值得\nDialogue: 0,0:50:39.18,0:50:42.19,Default,,0,0,0,,但这并不是这种实现的局限\nDialogue: 0,0:50:42.22,0:50:43.53,Default,,0,0,0,,因为内存非常低廉\nDialogue: 0,0:50:44.16,0:50:45.34,Default,,0,0,0,,但人力资源却相当昂贵\nDialogue: 0,0:50:48.13,0:50:50.22,Default,,0,0,0,,好吧 我们先休息一下 谢谢大家\nDialogue: 0,0:50:50.78,0:51:07.60,Default,,0,0,0,,[音乐]\nDialogue: 0,0:51:07.60,0:51:12.19,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:51:39.93,0:51:43.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:51:43.71,0:51:47.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:51:47.93,0:51:53.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}寄存机器\nDialogue: 0,0:51:56.11,0:51:57.04,Default,,0,0,0,,教授：我们讲解了\nDialogue: 0,0:51:58.70,0:52:03.37,Default,,0,0,0,,如果进行简单的迭代计算\nDialogue: 0,0:52:03.69,0:52:05.31,Default,,0,0,0,,以及简单的递归计算\nDialogue: 0,0:52:05.64,0:52:08.68,Default,,0,0,0,,我只想通过向你们展示一些针对特定应用的\nDialogue: 0,0:52:09.63,0:52:11.12,Default,,0,0,0,,更加复杂的设计\nDialogue: 0,0:52:11.21,0:52:13.58,Default,,0,0,0,,来总结简单机器的设计\nDialogue: 0,0:52:13.96,0:52:17.13,Default,,0,0,0,,也就是同时递归地调用两个斐波那契函数\nDialogue: 0,0:52:17.23,0:52:19.88,Default,,0,0,0,,因为它会向我们表明 并且我们会理解\nDialogue: 0,0:52:20.04,0:52:22.68,Default,,0,0,0,,一些关于栈正常工作\nDialogue: 0,0:52:22.76,0:52:25.04,Default,,0,0,0,,所需要遵守的约定\nDialogue: 0,0:52:26.40,0:52:27.11,Default,,0,0,0,,现在 让我们来看看\nDialogue: 0,0:52:27.11,0:52:28.27,Default,,0,0,0,,先让我在黑板上写下\nDialogue: 0,0:52:28.30,0:52:29.71,Default,,0,0,0,,将要翻译的程序\nDialogue: 0,0:52:34.15,0:52:36.52,Default,,0,0,0,,这是一个斐波那契过程\nDialogue: 0,0:52:39.23,0:52:41.58,Default,,0,0,0,,它非常的简单\nDialogue: 0,0:52:44.60,0:52:48.56,Default,,0,0,0,,如果N小于2 那么结果就是N\nDialogue: 0,0:52:49.26,0:52:55.34,Default,,0,0,0,,否则就是(FIB (- N 1))加上\nDialogue: 0,0:52:58.44,0:52:59.85,Default,,0,0,0,,(FIB (- N 2))\nDialogue: 0,0:53:07.05,0:53:09.29,Default,,0,0,0,,这就是我的计划\nDialogue: 0,0:53:09.29,0:53:12.56,Default,,0,0,0,,现在 我们要来写下这台机器的控制器\nDialogue: 0,0:53:13.07,0:53:15.53,Default,,0,0,0,,首先 我们假设有一个寄存器N\nDialogue: 0,0:53:15.56,0:53:19.15,Default,,0,0,0,,里面存放的是斐波那契函数的自变量\nDialogue: 0,0:53:19.82,0:53:21.80,Default,,0,0,0,,而计算结果会存放在VAL寄存器中\nDialogue: 0,0:53:22.17,0:53:24.97,Default,,0,0,0,,CONTINUE寄存器会和控制器相连\nDialogue: 0,0:53:26.11,0:53:26.81,Default,,0,0,0,,就跟之前一样\nDialogue: 0,0:53:26.96,0:53:29.21,Default,,0,0,0,,但我不会再去画数据通路了\nDialogue: 0,0:53:31.53,0:53:34.00,Default,,0,0,0,,因为它和之前的那个差不多\nDialogue: 0,0:53:34.36,0:53:37.84,Default,,0,0,0,,当然 关于计算的最神奇的事情之一\nDialogue: 0,0:53:38.75,0:53:39.88,Default,,0,0,0,,就是一段时间后\nDialogue: 0,0:53:40.08,0:53:41.93,Default,,0,0,0,,你构建了一个又一个的小功能\nDialogue: 0,0:53:41.95,0:53:43.32,Default,,0,0,0,,你就一下子拥有了需要的一切\nDialogue: 0,0:53:44.75,0:53:47.60,Default,,0,0,0,,这种效率是非常了不起的\nDialogue: 0,0:53:48.17,0:53:50.84,Default,,0,0,0,,构造制作一台通用计算机不需要太多的东西\nDialogue: 0,0:53:51.81,0:53:54.68,Default,,0,0,0,,总之 我们来看看斐波那契机器的控制器\nDialogue: 0,0:53:55.06,0:53:57.07,Default,,0,0,0,,我首先要做的是\nDialogue: 0,0:53:57.32,0:54:02.52,Default,,0,0,0,,通过为CONTINUE寄存器赋值\nDialogue: 0,0:54:07.13,0:54:10.28,Default,,0,0,0,,赋FIB-DONE来启动计算\nDialogue: 0,0:54:14.14,0:54:15.53,Default,,0,0,0,,这就意味着在这里\nDialogue: 0,0:54:15.55,0:54:18.48,Default,,0,0,0,,我需要有一个标签 FIB-DONE\nDialogue: 0,0:54:19.71,0:54:21.10,Default,,0,0,0,,当我来到这个地方后\nDialogue: 0,0:54:21.23,0:54:22.44,Default,,0,0,0,,机器就停止了\nDialogue: 0,0:54:24.00,0:54:24.86,Default,,0,0,0,,这就是这个标签的作用\nDialogue: 0,0:54:25.92,0:54:26.89,Default,,0,0,0,,然后我要创建一个循环\nDialogue: 0,0:54:31.11,0:54:34.25,Default,,0,0,0,,我要来到这里来启动FIB的计算\nDialogue: 0,0:54:35.47,0:54:36.86,Default,,0,0,0,,无论这时 N等于多少\nDialogue: 0,0:54:37.39,0:54:38.99,Default,,0,0,0,,斐波那契函数都会被计算\nDialogue: 0,0:54:39.13,0:54:42.01,Default,,0,0,0,,然后会返回到由CONTINUE寄存器指向的地方\nDialogue: 0,0:54:44.80,0:54:48.40,Default,,0,0,0,,因此你们将在这里看到\nDialogue: 0,0:54:48.44,0:54:50.48,Default,,0,0,0,,我想要在做一个约定\nDialogue: 0,0:54:50.97,0:54:54.25,Default,,0,0,0,,我用注释的形式来说明这个约定\nDialogue: 0,0:54:54.57,0:55:00.99,Default,,0,0,0,,也就是N中存储的是参数\nDialogue: 0,0:55:02.10,0:55:09.82,Default,,0,0,0,,而CONTINUE存储的是接收者\nDialogue: 0,0:55:13.36,0:55:14.29,Default,,0,0,0,,这个约定就是这样的\nDialogue: 0,0:55:15.71,0:55:18.96,Default,,0,0,0,,因此每当我来到这里\nDialogue: 0,0:55:19.24,0:55:21.04,Default,,0,0,0,,我希望这个约定是成立的\nDialogue: 0,0:55:21.52,0:55:23.32,Default,,0,0,0,,这些计算斐波那契函数所需要的参数\nDialogue: 0,0:55:24.82,0:55:26.83,Default,,0,0,0,,接下来我想做的是分支\nDialogue: 0,0:55:30.22,0:55:32.22,Default,,0,0,0,,如果N小于2\nDialogue: 0,0:55:35.07,0:55:37.44,Default,,0,0,0,,随便说一下 我使用的语法看起来像Lisp\nDialogue: 0,0:55:38.73,0:55:39.63,Default,,0,0,0,,但它并不是Lisp\nDialogue: 0,0:55:41.31,0:55:42.38,Default,,0,0,0,,它们运行不起来\nDialogue: 0,0:55:42.75,0:55:45.47,Default,,0,0,0,,我在这里写的并不是一个简单的Lisp程序\nDialogue: 0,0:55:46.12,0:55:49.31,Default,,0,0,0,,这是另一门语言的表示形式\nDialogue: 0,0:55:49.71,0:55:52.25,Default,,0,0,0,,我之所以使用这种满是括号的语法\nDialogue: 0,0:55:52.40,0:55:54.70,Default,,0,0,0,,是因为我刚好使用Lisp系统\nDialogue: 0,0:55:55.32,0:55:57.34,Default,,0,0,0,,来为这门语言编写解释器\nDialogue: 0,0:55:57.82,0:55:59.18,Default,,0,0,0,,这就使得我们能够模拟\nDialogue: 0,0:55:59.29,0:56:00.91,Default,,0,0,0,,我想要构建的机器\nDialogue: 0,0:56:03.38,0:56:06.24,Default,,0,0,0,,我不想让你们感到困惑 认为这是Lisp代码\nDialogue: 0,0:56:06.94,0:56:08.60,Default,,0,0,0,,只是我用了很多Lisp组件\nDialogue: 0,0:56:09.51,0:56:10.84,Default,,0,0,0,,我在Lisp中嵌入了一门语言\nDialogue: 0,0:56:11.02,0:56:12.44,Default,,0,0,0,,把Lisp当作组件\nDialogue: 0,0:56:12.72,0:56:15.12,Default,,0,0,0,,这样就能让我的模拟工作变得简单\nDialogue: 0,0:56:16.62,0:56:18.56,Default,,0,0,0,,我从Lisp中继承了这些属性\nDialogue: 0,0:56:19.10,0:56:21.53,Default,,0,0,0,,(FETCH N) 2)\nDialogue: 0,0:56:21.77,0:56:23.72,Default,,0,0,0,,成立的话 我想要跳转到IMMEDIATE-ANSWER这个地方\nDialogue: 0,0:56:26.20,0:56:27.29,Default,,0,0,0,,这是基本步骤\nDialogue: 0,0:56:33.15,0:56:34.35,Default,,0,0,0,,它对应在这里\nDialogue: 0,0:56:35.92,0:56:36.89,Default,,0,0,0,,也就是在FIB-DONE的上方\nDialogue: 0,0:56:37.75,0:56:38.64,Default,,0,0,0,,我们稍后就会看到\nDialogue: 0,0:56:39.42,0:56:40.70,Default,,0,0,0,,现在 对于一般情况来说\nDialogue: 0,0:56:40.72,0:56:42.44,Default,,0,0,0,,也就是我现在要写的\nDialogue: 0,0:56:43.13,0:56:44.19,Default,,0,0,0,,是这样的\nDialogue: 0,0:56:44.91,0:56:48.20,Default,,0,0,0,,首先呢 我需要调用斐波那契函数两次\nDialogue: 0,0:56:49.42,0:56:52.54,Default,,0,0,0,,在每一次中 -- 至少在其中一次\nDialogue: 0,0:56:52.78,0:56:53.95,Default,,0,0,0,,我得需要知道该怎么做\nDialogue: 0,0:56:53.96,0:56:55.36,Default,,0,0,0,,才能回过头来进行另外一个计算\nDialogue: 0,0:56:56.31,0:56:58.36,Default,,0,0,0,,我需要记住\nDialogue: 0,0:56:59.20,0:57:01.23,Default,,0,0,0,,我计算完第一个FIB了么？\nDialogue: 0,0:57:01.26,0:57:02.54,Default,,0,0,0,,或者第二个也计算完了？\nDialogue: 0,0:57:04.50,0:57:07.04,Default,,0,0,0,,我是该返回到计算第二个FIB的地方\nDialogue: 0,0:57:07.07,0:57:09.08,Default,,0,0,0,,还是回到执行ADD的地方\nDialogue: 0,0:57:10.12,0:57:12.11,Default,,0,0,0,,无论哪种情况 我都需要--\nDialogue: 0,0:57:12.14,0:57:14.46,Default,,0,0,0,,在第一个计算第一个FIB时\nDialogue: 0,0:57:14.51,0:57:16.98,Default,,0,0,0,,我需要保存N的值 来计算第二个FIB\nDialogue: 0,0:57:19.84,0:57:21.58,Default,,0,0,0,,因此我要把这些东西保存起来\nDialogue: 0,0:57:23.36,0:57:24.89,Default,,0,0,0,,首先要保存CONTINUE\nDialogue: 0,0:57:26.19,0:57:27.32,Default,,0,0,0,,也就是答案的接收者\nDialogue: 0,0:57:31.32,0:57:32.46,Default,,0,0,0,,我之所以要这么做\nDialogue: 0,0:57:32.48,0:57:34.20,Default,,0,0,0,,是因为我现在要把CONTINUE赋值为\nDialogue: 0,0:57:40.11,0:57:44.32,Default,,0,0,0,,我待会儿想要返回的地方\nDialogue: 0,0:57:46.83,0:57:50.27,Default,,0,0,0,,我们把它叫做AFTER-FIB-N-1\nDialogue: 0,0:57:51.04,0:57:53.76,Default,,0,0,0,,这个长名字 非常具有Lisp的命名特点\nDialogue: 0,0:57:57.36,0:58:00.22,Default,,0,0,0,,这是因为我先要计算第一个(FIB (- N 1))\nDialogue: 0,0:58:00.84,0:58:01.72,Default,,0,0,0,,计算完成之后\nDialogue: 0,0:58:01.72,0:58:03.29,Default,,0,0,0,,我想要回过头来做些其它事\nDialogue: 0,0:58:03.96,0:58:06.52,Default,,0,0,0,,而AFTER-FIB-N-1这个地方\nDialogue: 0,0:58:07.55,0:58:09.48,Default,,0,0,0,,就是我计算完第一个FIB后应该返回的地方\nDialogue: 0,0:58:11.52,0:58:13.13,Default,,0,0,0,,接下来我要保存N\nDialogue: 0,0:58:14.41,0:58:17.26,Default,,0,0,0,,因为我稍后需要用到它\nDialogue: 0,0:58:19.13,0:58:20.54,Default,,0,0,0,,在这里 我就已经\nDialogue: 0,0:58:20.67,0:58:22.84,Default,,0,0,0,,准备好计算(FIB (- N 1))了\nDialogue: 0,0:58:23.02,0:58:33.95,Default,,0,0,0,,(ASSIGN N (- (FETCH N) 1))\nDialogue: 0,0:58:38.11,0:58:40.27,Default,,0,0,0,,现在 该跳转到FIB-LOOP了\nDialogue: 0,0:58:47.18,0:58:49.87,Default,,0,0,0,,我满足我立下的约定么？\nDialogue: 0,0:58:50.40,0:58:51.50,Default,,0,0,0,,答案是是的\nDialogue: 0,0:58:51.77,0:58:55.12,Default,,0,0,0,,N现在存储的是N-1 这是我需要的\nDialogue: 0,0:58:56.43,0:59:00.09,Default,,0,0,0,,而CONTINUE包含的是计算完成后 返回的目的地\nDialogue: 0,0:59:01.28,0:59:03.07,Default,,0,0,0,,也就是计算(FIB (- N 1))完成之后\nDialogue: 0,0:59:04.10,0:59:05.44,Default,,0,0,0,,因此我满足了这些约定\nDialogue: 0,0:59:05.44,0:59:09.02,Default,,0,0,0,,因此 我就可以在这里写下一个标签\nDialogue: 0,0:59:11.47,0:59:17.56,Default,,0,0,0,,AFTER-FIB-N-1\nDialogue: 0,0:59:20.49,0:59:21.63,Default,,0,0,0,,在这里 我又该做些什么呢？\nDialogue: 0,0:59:22.69,0:59:23.61,Default,,0,0,0,,在这里\nDialogue: 0,0:59:23.95,0:59:26.75,Default,,0,0,0,,我已经准备好去计算(FIB (- N 2))了\nDialogue: 0,0:59:29.27,0:59:30.72,Default,,0,0,0,,但是为了计算(FIB (- N 2))\nDialogue: 0,0:59:30.75,0:59:31.63,Default,,0,0,0,,首先 我不知道\nDialogue: 0,0:59:31.78,0:59:33.40,Default,,0,0,0,,这里 我已经改变了N\nDialogue: 0,0:59:33.81,0:59:35.47,Default,,0,0,0,,或者在这个时候 我的N总是不断地\nDialogue: 0,0:59:37.85,0:59:38.80,Default,,0,0,0,,向1或者0递减\nDialogue: 0,0:59:39.78,0:59:42.51,Default,,0,0,0,,所以我不知道N寄存器中存储的到底是什么\nDialogue: 0,0:59:43.03,0:59:44.75,Default,,0,0,0,,我想要保存在栈中的N的值\nDialogue: 0,0:59:44.80,0:59:46.00,Default,,0,0,0,,也就是我在这里保存的值\nDialogue: 0,0:59:46.17,0:59:47.88,Default,,0,0,0,,这样我就可以在这里恢复它\nDialogue: 0,0:59:49.52,0:59:51.02,Default,,0,0,0,,我在这里存储的N\nDialogue: 0,0:59:51.15,0:59:54.49,Default,,0,0,0,,是这个时间点N的值\nDialogue: 0,0:59:54.89,0:59:57.37,Default,,0,0,0,,因此计算完(FIB (- N 1))之后我可以恢复它\nDialogue: 0,0:59:57.53,0:59:59.36,Default,,0,0,0,,这样的话 我就可以计算(- N 2)\nDialogue: 0,0:59:59.39,1:00:00.86,Default,,0,0,0,,然后就可以计算(FIB (- N 2))的值\nDialogue: 0,1:00:01.81,1:00:02.75,Default,,0,0,0,,现在让我们来恢复它\nDialogue: 0,1:00:08.83,1:00:09.77,Default,,0,0,0,,(RESTORE N)\nDialogue: 0,1:00:11.13,1:00:15.98,Default,,0,0,0,,现在我要做一件很教条的事\nDialogue: 0,1:00:16.00,1:00:17.40,Default,,0,0,0,,我们会尽快将其删除\nDialogue: 0,1:00:18.52,1:00:20.48,Default,,0,0,0,,如果你们愿意的话\nDialogue: 0,1:00:20.59,1:00:23.44,Default,,0,0,0,,我将要结束子过程调用\nDialogue: 0,1:00:24.80,1:00:25.95,Default,,0,0,0,,接下来我会说\nDialogue: 0,1:00:26.06,1:00:27.90,Default,,0,0,0,,因为我保存了CONTINUE\nDialogue: 0,1:00:28.48,1:00:30.43,Default,,0,0,0,,现在就要去恢复它\nDialogue: 0,1:00:31.60,1:00:32.60,Default,,0,0,0,,但实际上 我并不需要这么做\nDialogue: 0,1:00:32.64,1:00:33.55,Default,,0,0,0,,因为我并不需要用到它\nDialogue: 0,1:00:34.61,1:00:35.72,Default,,0,0,0,,我们稍后会修正它\nDialogue: 0,1:00:36.26,1:00:37.95,Default,,0,0,0,,现在我们来恢复CONTINUE\nDialogue: 0,1:00:46.04,1:00:48.02,Default,,0,0,0,,通常来说 我都会这么做\nDialogue: 0,1:00:48.02,1:00:49.23,Default,,0,0,0,,我们将要看到\nDialogue: 0,1:00:49.31,1:00:52.14,Default,,0,0,0,,编译器领域中的“窥孔优化”\nDialogue: 0,1:00:52.27,1:00:53.72,Default,,0,0,0,,来帮我们消除这个不必要的步骤\nDialogue: 0,1:00:55.42,1:00:57.10,Default,,0,0,0,,因此 我即将要做的就是\nDialogue: 0,1:00:58.46,1:01:02.28,Default,,0,0,0,,准备好计算(FIB (- N 2))\nDialogue: 0,1:01:02.77,1:01:04.49,Default,,0,0,0,,但是我不再需要保存N了\nDialogue: 0,1:01:05.05,1:01:06.72,Default,,0,0,0,,原因就是\nDialogue: 0,1:01:06.80,1:01:09.34,Default,,0,0,0,,计算完(FIB (- N 2))之后 我就不需要N了\nDialogue: 0,1:01:09.36,1:01:10.72,Default,,0,0,0,,因为 我接下来要做的就是ADD\nDialogue: 0,1:01:13.54,1:01:15.85,Default,,0,0,0,,因此 我会这么来设置N\nDialogue: 0,1:01:16.60,1:01:28.99,Default,,0,0,0,,(ASSIGN N (- (FETCH N) 2))\nDialogue: 0,1:01:31.85,1:01:34.01,Default,,0,0,0,,现在我需要结束\nDialogue: 0,1:01:34.27,1:01:36.73,Default,,0,0,0,,调用(FIB (- N 2))的设置过程了\nDialogue: 0,1:01:36.95,1:01:38.33,Default,,0,0,0,,我需要保存CONTINUE\nDialogue: 0,1:01:44.22,1:01:49.02,Default,,0,0,0,,然后把CONTINUE赋值为\nDialogue: 0,1:01:52.30,1:01:59.95,Default,,0,0,0,,AFTER-FIB-N-2\nDialogue: 0,1:02:02.57,1:02:04.03,Default,,0,0,0,,对应了那边代码的某处\nDialogue: 0,1:02:05.32,1:02:07.23,Default,,0,0,0,,然而 我需要非常小心\nDialogue: 0,1:02:08.65,1:02:11.42,Default,,0,0,0,,而(FIB (- N 1))的值\nDialogue: 0,1:02:12.06,1:02:13.12,Default,,0,0,0,,我稍后会用到\nDialogue: 0,1:02:15.30,1:02:17.37,Default,,0,0,0,,(FIB (- N 1))的值\nDialogue: 0,1:02:17.61,1:02:18.48,Default,,0,0,0,,我需要它的值\nDialogue: 0,1:02:18.78,1:02:19.80,Default,,0,0,0,,我不能去改变它\nDialogue: 0,1:02:21.07,1:02:23.60,Default,,0,0,0,,因为我需要用它来加上(FIB (- N 2))\nDialogue: 0,1:02:24.15,1:02:25.88,Default,,0,0,0,,它是存放在寄存器中的 因此我需要保存它\nDialogue: 0,1:02:27.79,1:02:32.60,Default,,0,0,0,,所以现在我要用(SAVE VAL)来保存它\nDialogue: 0,1:02:33.78,1:02:35.44,Default,,0,0,0,,现在我就可以调用子过程了\nDialogue: 0,1:02:36.67,1:02:39.54,Default,,0,0,0,,(GOTO FIB-LOOP)\nDialogue: 0,1:02:44.22,1:02:46.57,Default,,0,0,0,,现在 在进行更进一步计算之前\nDialogue: 0,1:02:46.80,1:02:49.36,Default,,0,0,0,,在结束这个程序之前\nDialogue: 0,1:02:49.39,1:02:51.05,Default,,0,0,0,,我想审视一下目前的代码片段\nDialogue: 0,1:02:51.23,1:02:56.00,Default,,0,0,0,,这里有一系列的指令\nDialogue: 0,1:02:57.84,1:02:59.08,Default,,0,0,0,,我可以对它们进行某些操作\nDialogue: 0,1:03:01.58,1:03:03.20,Default,,0,0,0,,这里 我有一个操作用来恢复CONTINUE\nDialogue: 0,1:03:04.25,1:03:05.48,Default,,0,0,0,,一个操作用来保存CONTINUE\nDialogue: 0,1:03:06.01,1:03:07.40,Default,,0,0,0,,然后给CONTINUE赋值\nDialogue: 0,1:03:08.70,1:03:10.64,Default,,0,0,0,,但这之中没有CONTINUE的其它引用\nDialogue: 0,1:03:13.84,1:03:15.48,Default,,0,0,0,,恢复之后又保存\nDialogue: 0,1:03:15.50,1:03:16.67,Default,,0,0,0,,使得栈没有被修改\nDialogue: 0,1:03:19.09,1:03:21.72,Default,,0,0,0,,唯一的区别就是 我给CONTINUE寄存器赋了值\nDialogue: 0,1:03:21.96,1:03:23.28,Default,,0,0,0,,一个存放在栈上的值\nDialogue: 0,1:03:24.33,1:03:25.79,Default,,0,0,0,,由于我现在改变了这个值\nDialogue: 0,1:03:26.44,1:03:27.93,Default,,0,0,0,,但这之间并没有引用这个值\nDialogue: 0,1:03:28.59,1:03:30.09,Default,,0,0,0,,这些指令就是不必要的\nDialogue: 0,1:03:31.76,1:03:35.39,Default,,0,0,0,,因此我们会移除它们\nDialogue: 0,1:03:38.88,1:03:40.78,Default,,0,0,0,,但我只有先把它们写出来 才会发现这个情况\nDialogue: 0,1:03:43.78,1:03:44.72,Default,,0,0,0,,真是这样吗？\nDialogue: 0,1:03:45.77,1:03:46.60,Default,,0,0,0,,我并不知道\nDialogue: 0,1:03:48.61,1:03:52.91,Default,,0,0,0,,现在 我们要开始计算(FIB (- N 2))了\nDialogue: 0,1:03:53.66,1:03:54.59,Default,,0,0,0,,计算完毕后\nDialogue: 0,1:04:02.96,1:04:03.85,Default,,0,0,0,,我们又要做什么呢？\nDialogue: 0,1:04:05.07,1:04:06.76,Default,,0,0,0,,我想 我们首先要做的就是\nDialogue: 0,1:04:06.99,1:04:07.88,Default,,0,0,0,,我们有两件事要做\nDialogue: 0,1:04:07.96,1:04:10.49,Default,,0,0,0,,目前VAL寄存器中的值 是有意义的\nDialogue: 0,1:04:10.92,1:04:11.98,Default,,0,0,0,,然而 栈上也有一个数据\nDialogue: 0,1:04:12.04,1:04:13.63,Default,,0,0,0,,需要恢复到VAL寄存器中\nDialogue: 0,1:04:14.81,1:04:16.57,Default,,0,0,0,,现在我需要非常小心的是\nDialogue: 0,1:04:16.88,1:04:18.99,Default,,0,0,0,,正确地给它们排序 以便计算乘法\nDialogue: 0,1:04:19.47,1:04:21.24,Default,,0,0,0,,现在 我可能会使用不同的约定\nDialogue: 0,1:04:21.47,1:04:23.52,Default,,0,0,0,,但我现在会采用非常挑剔的一种\nDialogue: 0,1:04:23.55,1:04:25.88,Default,,0,0,0,,栈上数据来自于哪个寄存器 就恢复到那个寄存器中\nDialogue: 0,1:04:26.74,1:04:28.28,Default,,0,0,0,,如果是这样的话 在这里我就要进行洗牌\nDialogue: 0,1:04:29.24,1:04:31.84,Default,,0,0,0,,这跟我有多少只手是同样的问题\nDialogue: 0,1:04:32.68,1:04:37.13,Default,,0,0,0,,现在我要给N赋值\nDialogue: 0,1:04:37.16,1:04:39.37,Default,,0,0,0,,因为我现在不再需要N了 N是无用的\nDialogue: 0,1:04:39.92,1:04:41.21,Default,,0,0,0,,获取当前VAL寄存器的值\nDialogue: 0,1:04:45.21,1:04:47.34,Default,,0,0,0,,也就是(FIB (- N 2))的值\nDialogue: 0,1:04:52.95,1:04:56.35,Default,,0,0,0,,现在 我就要恢复VAL寄存器了\nDialogue: 0,1:05:01.85,1:05:03.92,Default,,0,0,0,,这个RESTORE匹配这里的SAVE\nDialogue: 0,1:05:05.58,1:05:08.83,Default,,0,0,0,,如果你非常仔细地研究发生了什么\nDialogue: 0,1:05:09.21,1:05:11.96,Default,,0,0,0,,会发现 RESTORE和SAVE总是成对的\nDialogue: 0,1:05:13.84,1:05:15.15,Default,,0,0,0,,现在 这里有个额外的SAVE\nDialogue: 0,1:05:15.18,1:05:16.38,Default,,0,0,0,,当然 我们很快就会消灭它\nDialogue: 0,1:05:19.00,1:05:20.59,Default,,0,0,0,,恢复完VAL寄存器后\nDialogue: 0,1:05:20.94,1:05:22.57,Default,,0,0,0,,我就要恢复CONTINUE寄存器了\nDialogue: 0,1:05:31.15,1:05:32.40,Default,,0,0,0,,它匹配了这个\nDialogue: 0,1:05:34.80,1:05:37.85,Default,,0,0,0,,从这里到这里\nDialogue: 0,1:05:40.59,1:05:42.46,Default,,0,0,0,,这样就恢复了继续\nDialogue: 0,1:05:42.86,1:05:45.71,Default,,0,0,0,,这个表达式继续是由(FIB N)产生的\nDialogue: 0,1:05:46.46,1:05:47.84,Default,,0,0,0,,也就是我正尝试求解的\nDialogue: 0,1:05:47.85,1:05:49.32,Default,,0,0,0,,最主要的问题\nDialogue: 0,1:05:49.98,1:05:52.35,Default,,0,0,0,,我需要把(FIB N)的答案返回给这个继续\nDialogue: 0,1:05:52.54,1:05:54.03,Default,,0,0,0,,在我意识到N并不小于2之前\nDialogue: 0,1:05:54.16,1:05:56.60,Default,,0,0,0,,我一直保存着它们\nDialogue: 0,1:05:57.36,1:05:59.07,Default,,0,0,0,,因此 我需要进行一个复杂的运算\nDialogue: 0,1:06:00.84,1:06:02.57,Default,,0,0,0,,现在万事俱备\nDialogue: 0,1:06:03.24,1:06:04.36,Default,,0,0,0,,因此我要恢复它们\nDialogue: 0,1:06:05.42,1:06:21.08,Default,,0,0,0,,(ASSIGN VAL (+ (FETCH VAL) (FETCH N)))\nDialogue: 0,1:06:27.44,1:06:28.60,Default,,0,0,0,,然后跳转到CONTINUE\nDialogue: 0,1:06:38.26,1:06:44.78,Default,,0,0,0,,然后我就从(FIB N)中返回了出来\nDialogue: 0,1:06:45.39,1:06:46.57,Default,,0,0,0,,也就是FIB的一般情况\nDialogue: 0,1:06:47.11,1:06:50.60,Default,,0,0,0,,现在还有一些细节 需要我们填充\nDialogue: 0,1:06:50.99,1:06:55.53,Default,,0,0,0,,比如归纳的基本情况：可以立即得到答案\nDialogue: 0,1:07:02.54,1:07:06.59,Default,,0,0,0,,这不过就是\nDialogue: 0,1:07:06.60,1:07:11.85,Default,,0,0,0,,(ASSIGN VAL (FETCH N)\nDialogue: 0,1:07:13.64,1:07:15.47,Default,,0,0,0,,因为N小于2\nDialogue: 0,1:07:15.50,1:07:16.89,Default,,0,0,0,,因此答案就是N\nDialogue: 0,1:07:16.99,1:07:18.19,Default,,0,0,0,,跟源程序是一致的\nDialogue: 0,1:07:19.23,1:07:26.48,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,1:07:31.24,1:07:36.13,Default,,0,0,0,,最后就结束了\nDialogue: 0,1:07:43.46,1:07:45.64,Default,,0,0,0,,这是个相当复杂的程序\nDialogue: 0,1:07:45.64,1:07:47.34,Default,,0,0,0,,我之所以给你们演示这个程序\nDialogue: 0,1:07:47.50,1:07:49.21,Default,,0,0,0,,是因为我想让你们见识\nDialogue: 0,1:07:49.45,1:07:52.67,Default,,0,0,0,,我所遵守的栈使用准则\nDialogue: 0,1:07:53.32,1:07:55.21,Default,,0,0,0,,第一点就是 我不想保存那些\nDialogue: 0,1:07:56.92,1:07:58.12,Default,,0,0,0,,稍后不需要的值\nDialogue: 0,1:08:00.57,1:08:01.85,Default,,0,0,0,,我非常地小心\nDialogue: 0,1:08:01.85,1:08:02.91,Default,,0,0,0,,这非常重要\nDialogue: 0,1:08:03.94,1:08:06.52,Default,,0,0,0,,当然 人们还制定了其它的准则\nDialogue: 0,1:08:07.37,1:08:09.61,Default,,0,0,0,,来操作栈帧之类的东西\nDialogue: 0,1:08:10.19,1:08:11.39,Default,,0,0,0,,这些准则中 那些不再需要的东西\nDialogue: 0,1:08:11.40,1:08:12.64,Default,,0,0,0,,也需要保存并恢复\nDialogue: 0,1:08:12.67,1:08:15.26,Default,,0,0,0,,因为从某种意义上来说 这样做更容易些\nDialogue: 0,1:08:15.83,1:08:17.40,Default,,0,0,0,,但这会带来各种灾难\nDialogue: 0,1:08:18.59,1:08:20.25,Default,,0,0,0,,我们稍后就会见识一些\nDialogue: 0,1:08:21.44,1:08:24.24,Default,,0,0,0,,只保存那些你稍后需要的值 这很关键\nDialogue: 0,1:08:26.89,1:08:28.01,Default,,0,0,0,,这是非常重要的理念\nDialogue: 0,1:08:29.87,1:08:33.36,Default,,0,0,0,,无论谁保存了一个值 都应该由他来恢复\nDialogue: 0,1:08:33.76,1:08:35.32,Default,,0,0,0,,因为他需要这个值\nDialogue: 0,1:08:36.93,1:08:38.54,Default,,0,0,0,,在这样的准则中\nDialogue: 0,1:08:38.86,1:08:40.76,Default,,0,0,0,,你可以发现哪些数据是不必要的\nDialogue: 0,1:08:43.45,1:08:44.73,Default,,0,0,0,,哪些操作又是不重要的\nDialogue: 0,1:08:47.15,1:08:50.40,Default,,0,0,0,,我还想告诉你们\nDialogue: 0,1:08:51.66,1:08:54.67,Default,,0,0,0,,当然 你们看到的并不是全部的图景\nDialogue: 0,1:08:55.35,1:08:56.68,Default,,0,0,0,,假设我的系统中\nDialogue: 0,1:08:56.80,1:09:01.52,Default,,0,0,0,,具有像CAR、CDR、CONS这样的运算\nDialogue: 0,1:09:03.53,1:09:05.60,Default,,0,0,0,,或者创建一个向量\nDialogue: 0,1:09:05.88,1:09:07.32,Default,,0,0,0,,并引用它的第N个元素\nDialogue: 0,1:09:08.30,1:09:09.21,Default,,0,0,0,,等等运算\nDialogue: 0,1:09:10.40,1:09:13.60,Default,,0,0,0,,然而 就在这个层次的细节来说\nDialogue: 0,1:09:13.87,1:09:17.85,Default,,0,0,0,,我们可以在数据通路中把它们视为基本运算\nDialogue: 0,1:09:18.75,1:09:21.95,Default,,0,0,0,,换句话说 我们可以认为 有一台机器\nDialogue: 0,1:09:22.32,1:09:24.11,Default,,0,0,0,,包含了APPEND机器\nDialogue: 0,1:09:24.20,1:09:26.46,Default,,0,0,0,,它通过(CONS (CAR X)\nDialogue: 0,1:09:26.64,1:09:29.80,Default,,0,0,0,,(APPEND (CDR X) Y)来实现\nDialogue: 0,1:09:29.88,1:09:33.18,Default,,0,0,0,,哦 天啊 这就跟阶乘机器有相同的结构\nDialogue: 0,1:09:33.63,1:09:35.29,Default,,0,0,0,,当然 它有相同的结构\nDialogue: 0,1:09:36.54,1:09:37.27,Default,,0,0,0,,我们有什么呢？\nDialogue: 0,1:09:37.27,1:09:39.39,Default,,0,0,0,,我们有某种东西 其中有\nDialogue: 0,1:09:39.76,1:09:42.48,Default,,0,0,0,,诸如X、Y之类的寄存器\nDialogue: 0,1:09:42.51,1:09:45.12,Default,,0,0,0,,有时X会移动到Y中\nDialogue: 0,1:09:45.28,1:09:46.75,Default,,0,0,0,,或者X会取得Y的值\nDialogue: 0,1:09:46.93,1:09:50.11,Default,,0,0,0,,我们或许要需要能够进行CONS运算\nDialogue: 0,1:09:51.70,1:09:57.74,Default,,0,0,0,,我记不清这个系统中是否需要这样的东西\nDialogue: 0,1:09:57.76,1:10:01.10,Default,,0,0,0,,但CONS有点类似于减法器或加法器之类的东西\nDialogue: 0,1:10:01.42,1:10:02.70,Default,,0,0,0,,它把两个东西结合起来\nDialogue: 0,1:10:02.73,1:10:04.27,Default,,0,0,0,,然后产生一个序对\nDialogue: 0,1:10:04.51,1:10:06.49,Default,,0,0,0,,然后会把输出结果送入到这里\nDialogue: 0,1:10:07.60,1:10:09.72,Default,,0,0,0,,可能还有一个叫做CAR的组件\nDialogue: 0,1:10:12.88,1:10:16.22,Default,,0,0,0,,它的结果是 -- 某个东西的CAR部分\nDialogue: 0,1:10:16.92,1:10:19.55,Default,,0,0,0,,我还可以取得某物的CDR部分 等等\nDialogue: 0,1:10:20.15,1:10:22.30,Default,,0,0,0,,但我们不应该害怕这么说\nDialogue: 0,1:10:22.92,1:10:24.24,Default,,0,0,0,,因为最坏的情况不过\nDialogue: 0,1:10:24.94,1:10:26.41,Default,,0,0,0,,当我们打开CONS后\nDialogue: 0,1:10:27.31,1:10:29.82,Default,,0,0,0,,会发现其中存在某台机器\nDialogue: 0,1:10:31.88,1:10:34.44,Default,,0,0,0,,CONS可能会与CAR和CDR有所重叠\nDialogue: 0,1:10:35.50,1:10:38.12,Default,,0,0,0,,就像加法和减法有所重叠一样\nDialogue: 0,1:10:38.57,1:10:39.85,Default,,0,0,0,,它们本质上都是一样的\nDialogue: 0,1:10:41.21,1:10:42.60,Default,,0,0,0,,CONS、CAR和CDR将会有所重叠\nDialogue: 0,1:10:42.62,1:10:44.52,Default,,0,0,0,,我们会发现其中有小型控制器\nDialogue: 0,1:10:45.50,1:10:46.54,Default,,0,0,0,,小型的数据通路\nDialogue: 0,1:10:48.03,1:10:49.64,Default,,0,0,0,,其中还有一些寄存器\nDialogue: 0,1:10:50.00,1:10:52.86,Default,,0,0,0,,一些其它的像这样的东西\nDialogue: 0,1:10:53.30,1:10:54.41,Default,,0,0,0,,并且 也许在这之中\nDialogue: 0,1:10:54.43,1:10:56.16,Default,,0,0,0,,可能也有无穷的部分\nDialogue: 0,1:10:56.46,1:10:58.70,Default,,0,0,0,,又或者是半无穷的 之类的\nDialogue: 0,1:10:58.81,1:11:00.65,Default,,0,0,0,,这些都是统一的东西\nDialogue: 0,1:11:00.96,1:11:02.03,Default,,0,0,0,,也就是我们所谓的“内存”\nDialogue: 0,1:11:06.57,1:11:08.83,Default,,0,0,0,,有限的内存也能无穷地存储 对此我一点也不吃惊\nDialogue: 0,1:11:09.33,1:11:11.07,Default,,0,0,0,,实际上它就是这样的 我们之后就会了解\nDialogue: 0,1:11:13.32,1:11:14.57,Default,,0,0,0,,那么 有什么疑问么？\nDialogue: 0,1:11:24.34,1:11:25.80,Default,,0,0,0,,天啊！你们都一言不发\nDialogue: 0,1:11:28.67,1:11:30.33,Default,,0,0,0,,假设我说得都是谎言吧！\nDialogue: 0,1:11:39.69,1:11:40.38,Default,,0,0,0,,好吧\nDialogue: 0,1:11:41.99,1:11:42.52,Default,,0,0,0,,谢谢大家\nDialogue: 0,1:11:42.52,1:11:43.28,Default,,0,0,0,,我们下课吧！\nDialogue: 0,1:11:44.23,1:11:55.15,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:11:44.23,1:11:55.15,Default,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec9a.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 1258\nActive Line: 1269\nVideo Position: 128947\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.03,0:00:02.04,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP 学习小组\\N倾情制作\nDialogue: 0,0:00:02.04,0:00:09.09,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:02.04,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.21,0:00:13.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}寄存机器\nDialogue: 0,0:00:17.26,0:00:19.07,Default,,0,0,0,,教授：我认为 到目前为止\nDialogue: 0,0:00:19.32,0:00:23.93,Default,,0,0,0,,我们已经学习了很多关于\nDialogue: 0,0:00:24.09,0:00:28.83,Default,,0,0,0,,组织程序以及操纵符号的技术\nDialogue: 0,0:00:30.84,0:00:35.60,Default,,0,0,0,,以及用来构建语言的技术\nDialogue: 0,0:00:35.63,0:00:36.78,Default,,0,0,0,,用一门语言去创建另一门语言\nDialogue: 0,0:00:37.10,0:00:39.92,Default,,0,0,0,,这在组织大型程序时非常有用\nDialogue: 0,0:00:39.96,0:00:42.30,Default,,0,0,0,,实际上 我所知的最好的程序\nDialogue: 0,0:00:42.44,0:00:44.43,Default,,0,0,0,,看起来更像是一堆语言\nDialogue: 0,0:00:44.91,0:00:47.96,Default,,0,0,0,,而不是将问题分解成若干部分\nDialogue: 0,0:00:49.90,0:00:51.45,Default,,0,0,0,,我想 此时此刻\nDialogue: 0,0:00:52.08,0:00:53.58,Default,,0,0,0,,关于这类东西的工作方式\nDialogue: 0,0:00:53.61,0:00:55.32,Default,,0,0,0,,仍然存在一些谜团\nDialogue: 0,0:00:56.26,0:00:59.68,Default,,0,0,0,,因此 我现在需要\nDialogue: 0,0:01:00.03,0:01:02.60,Default,,0,0,0,,偏离原先的计划\nDialogue: 0,0:01:02.96,0:01:05.42,Default,,0,0,0,,不再继续讲解如何组织大型程序\nDialogue: 0,0:01:05.45,0:01:08.19,Default,,0,0,0,,而是告诉你一些关于\nDialogue: 0,0:01:08.52,0:01:11.71,Default,,0,0,0,,使这些事情可以起作用的机制\nDialogue: 0,0:01:12.19,0:01:14.83,Default,,0,0,0,,这样做的主要是为了\nDialogue: 0,0:01:15.80,0:01:17.87,Default,,0,0,0,,揭秘\nDialogue: 0,0:01:18.65,0:01:20.54,Default,,0,0,0,,剩下的很多谜团\nDialogue: 0,0:01:21.08,0:01:25.48,Default,,0,0,0,,比如说 如何控制程序的运行\nDialogue: 0,0:01:26.08,0:01:30.38,Default,,0,0,0,,计算机如何知晓下一步的动作\nDialogue: 0,0:01:30.52,0:01:31.74,Default,,0,0,0,,等等等等\nDialogue: 0,0:01:32.43,0:01:35.56,Default,,0,0,0,,我现在就要让你们清楚地知道\nDialogue: 0,0:01:35.85,0:01:39.10,Default,,0,0,0,,就算你之前没有使用过计算机\nDialogue: 0,0:01:39.56,0:01:43.50,Default,,0,0,0,,但这种机制非常简单\nDialogue: 0,0:01:44.33,0:01:46.35,Default,,0,0,0,,你可以毫无问题地理解它\nDialogue: 0,0:01:47.65,0:01:51.24,Default,,0,0,0,,好吧 我们先来想象一个 --\nDialogue: 0,0:01:51.32,0:01:52.91,Default,,0,0,0,,先说明一下 我们采用的方法是\nDialogue: 0,0:01:52.96,0:01:55.80,Default,,0,0,0,,把一些非常简单的Lisp程序\nDialogue: 0,0:01:56.54,0:01:58.12,Default,,0,0,0,,真的非常简单\nDialogue: 0,0:01:59.04,0:02:00.62,Default,,0,0,0,,把它们转换成硬件\nDialogue: 0,0:02:02.16,0:02:04.16,Default,,0,0,0,,我不会考虑一些中间步骤\nDialogue: 0,0:02:04.70,0:02:07.45,Default,,0,0,0,,比如转换成某种现有的机器语言\nDialogue: 0,0:02:07.47,0:02:09.05,Default,,0,0,0,,然后来解释计算机是如何工作的\nDialogue: 0,0:02:09.82,0:02:12.00,Default,,0,0,0,,因为那不太明显\nDialogue: 0,0:02:12.75,0:02:14.17,Default,,0,0,0,,所以我真正要向你展示的是\nDialogue: 0,0:02:14.51,0:02:17.48,Default,,0,0,0,,如何构建一台机器来完成\nDialogue: 0,0:02:18.03,0:02:22.04,Default,,0,0,0,,一项由你写的程序所描述的工作\nDialogue: 0,0:02:22.04,0:02:24.03,Default,,0,0,0,,而程序呢 实际上就是一个机器的描述\nDialogue: 0,0:02:25.76,0:02:27.69,Default,,0,0,0,,我们从一个非常简单的程序开始\nDialogue: 0,0:02:28.09,0:02:30.81,Default,,0,0,0,,然后演示一些简单的机制\nDialogue: 0,0:02:31.39,0:02:33.68,Default,,0,0,0,,进而用更复杂的程序\nDialogue: 0,0:02:34.30,0:02:37.42,Default,,0,0,0,,然后又演示一个不那么复杂的程序\nDialogue: 0,0:02:37.44,0:02:41.23,Default,,0,0,0,,来演示求值器是如何变成硬件的\nDialogue: 0,0:02:41.23,0:02:42.06,Default,,0,0,0,,当然 到那个时候\nDialogue: 0,0:02:42.08,0:02:44.08,Default,,0,0,0,,你就有了通用的转换算法\nDialogue: 0,0:02:44.22,0:02:46.88,Default,,0,0,0,,并且可以用一个定义明确的硬件\nDialogue: 0,0:02:47.16,0:02:48.80,Default,,0,0,0,,来执行任何可以想象的程序\nDialogue: 0,0:02:51.72,0:02:52.91,Default,,0,0,0,,那么 现在让我们开始\nDialogue: 0,0:02:53.05,0:02:55.31,Default,,0,0,0,,给你们关于这些东西的具体感觉\nDialogue: 0,0:02:55.44,0:02:57.66,Default,,0,0,0,,我们先从一个非常简单的程序开始\nDialogue: 0,0:02:59.60,0:03:00.85,Default,,0,0,0,,这是欧几里得算法\nDialogue: 0,0:03:03.88,0:03:07.00,Default,,0,0,0,,它实际上比欧几里德算法更现代一些\nDialogue: 0,0:03:07.02,0:03:10.09,Default,,0,0,0,,我想 用来计算两数最大公约数的欧几里得算法\nDialogue: 0,0:03:10.41,0:03:13.60,Default,,0,0,0,,是在公元前350年发明的\nDialogue: 0,0:03:14.30,0:03:15.69,Default,,0,0,0,,它是已知最古老的算法\nDialogue: 0,0:03:19.32,0:03:23.34,Default,,0,0,0,,我们先定义(GCD A B)\nDialogue: 0,0:03:23.36,0:03:25.61,Default,,0,0,0,,也就是用来计算A、B两数的最大公约数\nDialogue: 0,0:03:26.20,0:03:28.91,Default,,0,0,0,,这个算法相当简单\nDialogue: 0,0:03:29.50,0:03:31.08,Default,,0,0,0,,如果B等于0\nDialogue: 0,0:03:34.16,0:03:36.83,Default,,0,0,0,,那么结果就是A\nDialogue: 0,0:03:37.52,0:03:43.61,Default,,0,0,0,,否则结果就是 (GCD B\nDialogue: 0,0:03:44.49,0:03:53.39,Default,,0,0,0,,(REMAINDER A B))\nDialogue: 0,0:03:58.53,0:04:01.90,Default,,0,0,0,,这里 我们定义了一个简单的迭代过程\nDialogue: 0,0:04:02.03,0:04:04.08,Default,,0,0,0,,这是一个简单的递归过程\nDialogue: 0,0:04:04.38,0:04:07.53,Default,,0,0,0,,也可以说这个过程是递归地定义的\nDialogue: 0,0:04:07.71,0:04:09.26,Default,,0,0,0,,但它产生的计算过程是迭代的\nDialogue: 0,0:04:09.95,0:04:12.46,Default,,0,0,0,,它的原理是 在每一步\nDialogue: 0,0:04:12.80,0:04:15.10,Default,,0,0,0,,判断B是否为0\nDialogue: 0,0:04:16.24,0:04:18.80,Default,,0,0,0,,如果B为0 那么A的值就是我们的答案\nDialogue: 0,0:04:19.63,0:04:22.46,Default,,0,0,0,,否则就进入下一个步骤\nDialogue: 0,0:04:22.49,0:04:23.87,Default,,0,0,0,,其中A就变成旧的B\nDialogue: 0,0:04:23.88,0:04:27.04,Default,,0,0,0,,而B的值 是A旧值除B旧值的余数\nDialogue: 0,0:04:28.76,0:04:29.55,Default,,0,0,0,,非常简单\nDialogue: 0,0:04:31.11,0:04:32.72,Default,,0,0,0,,现在 我已经通过这种方式\nDialogue: 0,0:04:32.99,0:04:34.86,Default,,0,0,0,,告诉了你一些机制\nDialogue: 0,0:04:34.86,0:04:35.90,Default,,0,0,0,,我是按时序告诉你们的\nDialogue: 0,0:04:36.36,0:04:37.72,Default,,0,0,0,,我说 其中有特定的步骤\nDialogue: 0,0:04:38.14,0:04:39.32,Default,,0,0,0,,并且实际上\nDialogue: 0,0:04:39.52,0:04:40.86,Default,,0,0,0,,你可以在这里知道\nDialogue: 0,0:04:41.18,0:04:43.69,Default,,0,0,0,,为什么这个过程是迭代的\nDialogue: 0,0:04:43.95,0:04:47.68,Default,,0,0,0,,是因为最后一步无需额外信息来得到答案\nDialogue: 0,0:04:49.44,0:04:55.29,Default,,0,0,0,,所有运行此算法所需的信息都在A和B中\nDialogue: 0,0:04:55.74,0:04:57.80,Default,,0,0,0,,它有两个定义明确的状态变量\nDialogue: 0,0:05:00.47,0:05:02.33,Default,,0,0,0,,现在 我就要给你们定义一台机器\nDialogue: 0,0:05:03.98,0:05:05.55,Default,,0,0,0,,用来计算GCD\nDialogue: 0,0:05:06.56,0:05:07.12,Default,,0,0,0,,我们来看看\nDialogue: 0,0:05:07.12,0:05:11.28,Default,,0,0,0,,每台制造的计算机都是单进程计算机\nDialogue: 0,0:05:11.80,0:05:14.08,Default,,0,0,0,,而不是某种多处理器\nDialogue: 0,0:05:15.04,0:05:16.59,Default,,0,0,0,,都是按照相同的方案制定的\nDialogue: 0,0:05:17.84,0:05:19.53,Default,,0,0,0,,这种方案就是：计算机由两部分组成\nDialogue: 0,0:05:20.57,0:05:22.35,Default,,0,0,0,,一部分叫数据通路\nDialogue: 0,0:05:23.10,0:05:24.36,Default,,0,0,0,,而另一部分叫控制器\nDialogue: 0,0:05:25.91,0:05:29.28,Default,,0,0,0,,数据通路相当于你可能有的计算器\nDialogue: 0,0:05:29.71,0:05:31.87,Default,,0,0,0,,它有一些寄存器 能够存储数据\nDialogue: 0,0:05:31.90,0:05:33.13,Default,,0,0,0,,你们都用过计算器\nDialogue: 0,0:05:33.56,0:05:35.34,Default,,0,0,0,,它上面有一些按钮和指示灯\nDialogue: 0,0:05:37.03,0:05:38.49,Default,,0,0,0,,通过按下不同的按钮\nDialogue: 0,0:05:38.52,0:05:41.34,Default,,0,0,0,,你可以使操作在寄存器内发生\nDialogue: 0,0:05:41.87,0:05:43.48,Default,,0,0,0,,并显示计算结果\nDialogue: 0,0:05:45.16,0:05:46.25,Default,,0,0,0,,它是完全机械式的\nDialogue: 0,0:05:46.25,0:05:49.55,Default,,0,0,0,,你可以认为那个盒子没有任何智能\nDialogue: 0,0:05:50.90,0:05:53.28,Default,,0,0,0,,它能计算一个数的正弦也许令人吃惊\nDialogue: 0,0:05:53.53,0:05:58.97,Default,,0,0,0,,但它显然是机械式的\nDialogue: 0,0:05:58.97,0:06:01.71,Default,,0,0,0,,至少 我可以像打开GCD机器一样打开它\nDialogue: 0,0:06:02.69,0:06:04.36,Default,,0,0,0,,也就是说 它其中可能有一整台计算机\nDialogue: 0,0:06:04.68,0:06:05.69,Default,,0,0,0,,但这并不有趣\nDialogue: 0,0:06:05.94,0:06:07.10,Default,,0,0,0,,加法相当简单\nDialogue: 0,0:06:08.20,0:06:09.84,Default,,0,0,0,,不借助额外机制就可以完成\nDialogue: 0,0:06:10.89,0:06:15.64,Default,,0,0,0,,现在 如果我们来看另外的一部分：控制器\nDialogue: 0,0:06:15.93,0:06:17.39,Default,,0,0,0,,这一部分也非常简单\nDialogue: 0,0:06:18.19,0:06:19.16,Default,,0,0,0,,它负责按下按钮\nDialogue: 0,0:06:20.35,0:06:21.52,Default,,0,0,0,,它根据指令序列来按按钮\nDialogue: 0,0:06:21.55,0:06:22.84,Default,,0,0,0,,指令是写在纸上的\nDialogue: 0,0:06:24.27,0:06:25.64,Default,,0,0,0,,控制器还会观察指示灯\nDialogue: 0,0:06:26.29,0:06:29.44,Default,,0,0,0,,而且每隔一段 它就会来到指令序列中的一处\nDialogue: 0,0:06:29.47,0:06:32.37,Default,,0,0,0,,如果指示灯A亮 则执行某段指令\nDialogue: 0,0:06:32.37,0:06:33.85,Default,,0,0,0,,否则执行另外的指令\nDialogue: 0,0:06:34.62,0:06:37.45,Default,,0,0,0,,因此 这其中也没有什么复杂的\nDialogue: 0,0:06:38.35,0:06:39.32,Default,,0,0,0,,那么 让我们来画一下\nDialogue: 0,0:06:39.34,0:06:40.57,Default,,0,0,0,,然后来感受一下它\nDialogue: 0,0:06:42.51,0:06:44.84,Default,,0,0,0,,为了计算GCD\nDialogue: 0,0:06:45.88,0:06:49.52,Default,,0,0,0,,你们要知道：这其中有一些寄存器\nDialogue: 0,0:06:50.56,0:06:53.02,Default,,0,0,0,,这里 寄存器就是一个存储数值的地方\nDialogue: 0,0:06:53.52,0:06:54.65,Default,,0,0,0,,这个寄存器存储的是A\nDialogue: 0,0:06:56.81,0:06:58.70,Default,,0,0,0,,而另外的这个存储的是B\nDialogue: 0,0:07:03.17,0:07:05.45,Default,,0,0,0,,现在我们来看看 有了这些寄存器后能做什么\nDialogue: 0,0:07:05.98,0:07:08.73,Default,,0,0,0,,至于你能利用它做什么 并不是很明显\nDialogue: 0,0:07:09.84,0:07:11.72,Default,,0,0,0,,那么 我们必须看看需要用它们做什么\nDialogue: 0,0:07:11.82,0:07:13.87,Default,,0,0,0,,我们来看看尝试求解的问题\nDialogue: 0,0:07:14.03,0:07:16.09,Default,,0,0,0,,计算机设计的一个要点就是\nDialogue: 0,0:07:17.10,0:07:19.58,Default,,0,0,0,,我想大多数设计师都不会照做\nDialogue: 0,0:07:20.20,0:07:21.88,Default,,0,0,0,,也就是专注于待解的问题\nDialogue: 0,0:07:22.62,0:07:25.18,Default,,0,0,0,,然后使用你研究问题所学到的东西\nDialogue: 0,0:07:25.44,0:07:27.28,Default,,0,0,0,,把那些求解问题所需要的机制\nDialogue: 0,0:07:27.53,0:07:28.70,Default,,0,0,0,,融入正在构建的计算机中\nDialogue: 0,0:07:28.81,0:07:30.08,Default,,0,0,0,,不多也不少\nDialogue: 0,0:07:32.14,0:07:33.96,Default,,0,0,0,,现在 可能你所要解决的问题\nDialogue: 0,0:07:34.24,0:07:35.40,Default,,0,0,0,,是大家共有的问题\nDialogue: 0,0:07:36.06,0:07:37.58,Default,,0,0,0,,这种情况下你需要构建\nDialogue: 0,0:07:37.60,0:07:39.29,Default,,0,0,0,,某种语言的通用解释器\nDialogue: 0,0:07:40.19,0:07:42.32,Default,,0,0,0,,但是你添加的机制不能比\nDialogue: 0,0:07:42.35,0:07:44.25,Default,,0,0,0,,想构建的语言解释器的需求多\nDialogue: 0,0:07:44.44,0:07:45.85,Default,,0,0,0,,这一点 我们稍后来讨论\nDialogue: 0,0:07:47.23,0:07:49.93,Default,,0,0,0,,好了 让我们回到这里\nDialogue: 0,0:07:49.93,0:07:51.24,Default,,0,0,0,,我们必须能够做什么？\nDialogue: 0,0:07:51.79,0:07:54.14,Default,,0,0,0,,首先 我们能把B的值赋给A\nDialogue: 0,0:07:56.08,0:07:59.60,Default,,0,0,0,,我们要能够把B的旧值赋给A\nDialogue: 0,0:08:00.38,0:08:03.32,Default,,0,0,0,,因此 我们需要某种能够让数据流通的“路径”\nDialogue: 0,0:08:03.34,0:08:04.76,Default,,0,0,0,,而不管数据具体是什么\nDialogue: 0,0:08:05.37,0:08:06.57,Default,,0,0,0,,从B到A的通路\nDialogue: 0,0:08:07.39,0:08:09.26,Default,,0,0,0,,我箭头来指示\nDialogue: 0,0:08:09.52,0:08:12.62,Default,,0,0,0,,我们能够把B的值赋给A\nDialogue: 0,0:08:12.96,0:08:14.57,Default,,0,0,0,,从而替换A的旧值\nDialogue: 0,0:08:15.12,0:08:16.73,Default,,0,0,0,,当你按下这里的按钮后\nDialogue: 0,0:08:17.48,0:08:18.56,Default,,0,0,0,,就能够实现这个效果\nDialogue: 0,0:08:19.71,0:08:20.78,Default,,0,0,0,,这个按钮就在这里\nDialogue: 0,0:08:23.07,0:08:23.93,Default,,0,0,0,,同样的\nDialogue: 0,0:08:23.95,0:08:26.28,Default,,0,0,0,,我还需要能够计算A除B的余数\nDialogue: 0,0:08:27.00,0:08:28.49,Default,,0,0,0,,这可能混乱而又复杂\nDialogue: 0,0:08:28.86,0:08:30.86,Default,,0,0,0,,但另一方面 我会把它放到一个小盒子中\nDialogue: 0,0:08:31.96,0:08:33.92,Default,,0,0,0,,如果有必要的话 我们可以打开那个盒子\nDialogue: 0,0:08:34.12,0:08:35.63,Default,,0,0,0,,看看其中有些什么\nDialogue: 0,0:08:37.77,0:08:39.16,Default,,0,0,0,,这就是那个小盒子\nDialogue: 0,0:08:39.20,0:08:40.38,Default,,0,0,0,,我这么来画它\nDialogue: 0,0:08:43.16,0:08:44.38,Default,,0,0,0,,我把它叫做REM\nDialogue: 0,0:08:46.44,0:08:48.60,Default,,0,0,0,,它接受A\nDialogue: 0,0:08:50.91,0:08:52.16,Default,,0,0,0,,同时也要接受B\nDialogue: 0,0:08:54.37,0:08:56.51,Default,,0,0,0,,它有一个输出\nDialogue: 0,0:08:58.89,0:09:00.46,Default,,0,0,0,,也就是A除以B的余数\nDialogue: 0,0:09:02.29,0:09:03.61,Default,,0,0,0,,在这里 我们同样需要能够\nDialogue: 0,0:09:03.64,0:09:06.06,Default,,0,0,0,,判断B是否等于0\nDialogue: 0,0:09:08.00,0:09:09.66,Default,,0,0,0,,也就是说 总得有个东西\nDialogue: 0,0:09:10.00,0:09:12.30,Default,,0,0,0,,去查询B的值\nDialogue: 0,0:09:13.39,0:09:14.40,Default,,0,0,0,,这是一个指示灯\nDialogue: 0,0:09:15.85,0:09:17.39,Default,,0,0,0,,当B等于0时 它就会点亮\nDialogue: 0,0:09:21.11,0:09:22.01,Default,,0,0,0,,它就是干这个的\nDialogue: 0,0:09:24.03,0:09:26.78,Default,,0,0,0,,最后 因为我们希望\nDialogue: 0,0:09:26.96,0:09:30.43,Default,,0,0,0,,A的新值是B的旧值\nDialogue: 0,0:09:30.46,0:09:34.41,Default,,0,0,0,,同时B的新值是有关于A的\nDialogue: 0,0:09:35.28,0:09:37.60,Default,,0,0,0,,如果我打算让机器\nDialogue: 0,0:09:37.80,0:09:39.74,Default,,0,0,0,,一次只发生一件事\nDialogue: 0,0:09:40.20,0:09:41.40,Default,,0,0,0,,一次执行一个动作\nDialogue: 0,0:09:41.61,0:09:43.42,Default,,0,0,0,,并且我不能在一个寄存器中放两个数字\nDialogue: 0,0:09:44.03,0:09:46.30,Default,,0,0,0,,那么进行互换时 必须有另外的地方放置一个数字\nDialogue: 0,0:09:49.29,0:09:49.60,Default,,0,0,0,,对吧？\nDialogue: 0,0:09:50.00,0:09:51.85,Default,,0,0,0,,我不能同时交换两手的东西\nDialogue: 0,0:09:52.11,0:09:53.72,Default,,0,0,0,,除非我一手拿两个\nDialogue: 0,0:09:53.72,0:09:55.13,Default,,0,0,0,,然后从中取另外一个\nDialogue: 0,0:09:55.50,0:09:56.91,Default,,0,0,0,,或者我先放下一个\nDialogue: 0,0:09:57.02,0:09:58.68,Default,,0,0,0,,取得另一个后再像这样捡起来\nDialogue: 0,0:09:59.64,0:10:00.94,Default,,0,0,0,,除非我是耍杂技的\nDialogue: 0,0:10:01.66,0:10:03.50,Default,,0,0,0,,当然正如大家所见 我并不是\nDialogue: 0,0:10:04.65,0:10:07.36,Default,,0,0,0,,这种情况下 我就会遇到时序错误\nDialogue: 0,0:10:08.85,0:10:11.04,Default,,0,0,0,,事实上 人们所做的许多类型的计算机设计\nDialogue: 0,0:10:11.07,0:10:12.68,Default,,0,0,0,,都遇到了时序错误\nDialogue: 0,0:10:13.12,0:10:15.00,Default,,0,0,0,,或者潜在的时序错误\nDialogue: 0,0:10:15.24,0:10:16.43,Default,,0,0,0,,我不太喜欢这种错误\nDialogue: 0,0:10:17.34,0:10:18.64,Default,,0,0,0,,因此 出于这个原因\nDialogue: 0,0:10:18.68,0:10:21.21,Default,,0,0,0,,我需要有一个地方来放置\nDialogue: 0,0:10:22.06,0:10:23.29,Default,,0,0,0,,其中的一个元素\nDialogue: 0,0:10:23.41,0:10:24.72,Default,,0,0,0,,因此 这里有一个寄存器\nDialogue: 0,0:10:24.75,0:10:26.84,Default,,0,0,0,,用来存放临时值T\nDialogue: 0,0:10:28.59,0:10:29.63,Default,,0,0,0,,上面有一个按钮\nDialogue: 0,0:10:30.47,0:10:31.88,Default,,0,0,0,,我会使用它的结果\nDialogue: 0,0:10:31.90,0:10:34.14,Default,,0,0,0,,因为我需要把这个结果送入B\nDialogue: 0,0:10:34.68,0:10:36.73,Default,,0,0,0,,我们会把结果像这样给送过来\nDialogue: 0,0:10:38.41,0:10:39.30,Default,,0,0,0,,这里同样有一个按钮\nDialogue: 0,0:10:42.43,0:10:45.84,Default,,0,0,0,,这就是GCD机器的数据通路\nDialogue: 0,0:10:47.60,0:10:48.57,Default,,0,0,0,,那么 控制器又是怎样的呢？\nDialogue: 0,0:10:49.74,0:10:51.28,Default,,0,0,0,,控制器同样很简单\nDialogue: 0,0:10:52.28,0:10:53.26,Default,,0,0,0,,机器具有状态\nDialogue: 0,0:10:54.38,0:10:57.72,Default,,0,0,0,,我喜欢形象地把它们比作迷宫\nDialogue: 0,0:10:59.01,0:11:03.20,Default,,0,0,0,,这个迷宫的各处是通过直接的箭头连接的\nDialogue: 0,0:11:04.43,0:11:05.60,Default,,0,0,0,,而我有一颗弹珠\nDialogue: 0,0:11:06.46,0:11:09.07,Default,,0,0,0,,它代表了控制器的状态\nDialogue: 0,0:11:10.74,0:11:12.27,Default,,0,0,0,,弹珠在迷宫中四处滚动\nDialogue: 0,0:11:13.74,0:11:17.15,Default,,0,0,0,,当然 这种类比因能量的原因而不成立\nDialogue: 0,0:11:17.15,0:11:19.08,Default,,0,0,0,,有时我不得不将弹珠泵到顶部\nDialogue: 0,0:11:19.12,0:11:21.85,Default,,0,0,0,,不然它就会成为一台永动机\nDialogue: 0,0:11:22.00,0:11:23.32,Default,,0,0,0,,但不用担心那么多\nDialogue: 0,0:11:23.90,0:11:25.90,Default,,0,0,0,,这并不是一个物理比喻\nDialogue: 0,0:11:26.08,0:11:27.42,Default,,0,0,0,,弹珠到处滚动\nDialogue: 0,0:11:27.68,0:11:29.56,Default,,0,0,0,,就像弹球机一样\nDialogue: 0,0:11:29.68,0:11:30.97,Default,,0,0,0,,每次当它滚动到一些缓冲器时\nDialogue: 0,0:11:31.26,0:11:32.60,Default,,0,0,0,,它就会按下这些按钮\nDialogue: 0,0:11:34.83,0:11:37.50,Default,,0,0,0,,它也会经常来到一个分支区域\nDialogue: 0,0:11:38.62,0:11:39.68,Default,,0,0,0,,它要在这里做选择\nDialogue: 0,0:11:40.25,0:11:42.36,Default,,0,0,0,,然后有一个由这个组件控制的挡板\nDialogue: 0,0:11:46.00,0:11:48.82,Default,,0,0,0,,所以这是一个非常机械化的思考方式\nDialogue: 0,0:11:48.82,0:11:51.05,Default,,0,0,0,,当然 真实计算机中的控制器\nDialogue: 0,0:11:51.08,0:11:51.84,Default,,0,0,0,,并不是这样的\nDialogue: 0,0:11:51.84,0:11:56.01,Default,,0,0,0,,而是由一些ROM和状态寄存器构成\nDialogue: 0,0:11:56.61,0:11:58.73,Default,,0,0,0,,但曾几何时 像DEC、PDP-6这些个机器\nDialogue: 0,0:11:59.29,0:12:01.02,Default,,0,0,0,,它们的控制器就是我们说的那样\nDialogue: 0,0:12:01.80,0:12:03.61,Default,,0,0,0,,延迟线上有一些比特信息\nDialogue: 0,0:12:05.69,0:12:08.14,Default,,0,0,0,,它随着时间的推移而触发事件\nDialogue: 0,0:12:08.58,0:12:10.70,Default,,0,0,0,,然后回到开始并再次轮回\nDialogue: 0,0:12:11.99,0:12:13.72,Default,,0,0,0,,当然 还有各种各样的错误\nDialogue: 0,0:12:13.74,0:12:17.67,Default,,0,0,0,,比如两个比特的信息 -- 对应两个弹珠\nDialogue: 0,0:12:17.67,0:12:19.26,Default,,0,0,0,,机器也会丢失弹珠\nDialogue: 0,0:12:19.45,0:12:20.20,Default,,0,0,0,,这也会发生\nDialogue: 0,0:12:20.98,0:12:21.58,Default,,0,0,0,,好吧\nDialogue: 0,0:12:22.27,0:12:24.22,Default,,0,0,0,,无论如何 对于这台机器\nDialogue: 0,0:12:24.27,0:12:25.48,Default,,0,0,0,,我想要这么来做\nDialogue: 0,0:12:25.80,0:12:27.74,Default,,0,0,0,,迷宫从这里开始\nDialogue: 0,0:12:30.52,0:12:32.73,Default,,0,0,0,,我首先要做的是\nDialogue: 0,0:12:33.76,0:12:36.75,Default,,0,0,0,,用一个你们非常熟悉的流程图记号\nDialogue: 0,0:12:37.07,0:12:39.85,Default,,0,0,0,,这是一个判断：B是否为0\nDialogue: 0,0:12:41.50,0:12:43.79,Default,,0,0,0,,如果判断为是的话\nDialogue: 0,0:12:43.93,0:12:45.58,Default,,0,0,0,,那我就做完了\nDialogue: 0,0:12:49.79,0:12:51.26,Default,,0,0,0,,否则的话\nDialogue: 0,0:12:52.70,0:12:54.32,Default,,0,0,0,,我就不得不滚动一些缓冲器\nDialogue: 0,0:12:55.00,0:12:56.46,Default,,0,0,0,,按照下列顺序执行\nDialogue: 0,0:12:57.42,0:13:03.40,Default,,0,0,0,,我想向这样来做一个互换游戏\nDialogue: 0,0:13:04.05,0:13:05.80,Default,,0,0,0,,首先 因为我需要A和B\nDialogue: 0,0:13:06.32,0:13:08.57,Default,,0,0,0,,但首先 -- 虽然并不是必要的\nDialogue: 0,0:13:08.65,0:13:09.72,Default,,0,0,0,,我需要先把它们收集起来\nDialogue: 0,0:13:11.07,0:13:12.62,Default,,0,0,0,,这里的值要送入到B中\nDialogue: 0,0:13:13.24,0:13:14.03,Default,,0,0,0,,因此 我会说\nDialogue: 0,0:13:14.28,0:13:16.27,Default,,0,0,0,,用A和B的值来计算这个\nDialogue: 0,0:13:16.36,0:13:18.67,Default,,0,0,0,,并把算得的余数放到这里\nDialogue: 0,0:13:19.15,0:13:20.33,Default,,0,0,0,,因此 我首先要按下这个按钮\nDialogue: 0,0:13:21.53,0:13:24.43,Default,,0,0,0,,然后我要把B的值送入A\nDialogue: 0,0:13:24.44,0:13:25.60,Default,,0,0,0,,通过按这个钮来实现\nDialogue: 0,0:13:25.82,0:13:27.63,Default,,0,0,0,,然后我再把临时值送入B\nDialogue: 0,0:13:28.76,0:13:29.42,Default,,0,0,0,,通过这个按钮实现\nDialogue: 0,0:13:32.03,0:13:34.97,Default,,0,0,0,,这是一个相当时序化的机器\nDialogue: 0,0:13:35.39,0:13:36.52,Default,,0,0,0,,它非常的低效\nDialogue: 0,0:13:37.75,0:13:39.05,Default,,0,0,0,,但目前来说还好\nDialogue: 0,0:13:39.81,0:13:40.97,Default,,0,0,0,,我们来为按钮命名\nDialogue: 0,0:13:41.47,0:13:42.72,Default,,0,0,0,,T←R\nDialogue: 0,0:13:46.75,0:13:48.73,Default,,0,0,0,,A←B\nDialogue: 0,0:13:50.03,0:13:54.81,Default,,0,0,0,,B←T\nDialogue: 0,0:13:55.47,0:13:57.63,Default,,0,0,0,,然后我要来到这里\nDialogue: 0,0:13:58.78,0:13:59.88,Default,,0,0,0,,也就是回到开始的地方\nDialogue: 0,0:14:01.62,0:14:03.87,Default,,0,0,0,,在这里 我们看到了什么？\nDialogue: 0,0:14:03.87,0:14:04.91,Default,,0,0,0,,我们看到各种各样的 --\nDialogue: 0,0:14:05.05,0:14:07.16,Default,,0,0,0,,我们真正拥有的是某种机械连接\nDialogue: 0,0:14:07.42,0:14:13.63,Default,,0,0,0,,其中T←R控制了这个东西\nDialogue: 0,0:14:16.83,0:14:21.48,Default,,0,0,0,,A←B控制了这个东西\nDialogue: 0,0:14:26.96,0:14:28.12,Default,,0,0,0,,而这里的这个东西\nDialogue: 0,0:14:28.12,0:14:31.08,Default,,0,0,0,,同学们 这简直太恶劣了\nDialogue: 0,0:14:31.48,0:14:32.48,Default,,0,0,0,,一点也没有优化\nDialogue: 0,0:14:32.63,0:14:34.59,Default,,0,0,0,,我画的所有线条都相互交叉\nDialogue: 0,0:14:38.54,0:14:41.15,Default,,0,0,0,,我想B←T控制的是这个\nDialogue: 0,0:14:45.69,0:14:47.95,Default,,0,0,0,,现在 我就要运行这台机器了\nDialogue: 0,0:14:48.04,0:14:49.34,Default,,0,0,0,,但是在我运行它之前\nDialogue: 0,0:14:49.37,0:14:51.40,Default,,0,0,0,,我想写下它的控制器的描述\nDialogue: 0,0:14:51.63,0:14:52.81,Default,,0,0,0,,以便使你们相信\nDialogue: 0,0:14:52.84,0:14:55.63,Default,,0,0,0,,这些东西可以组织成某种良好的语言\nDialogue: 0,0:14:56.08,0:14:58.08,Default,,0,0,0,,这样我们就不必总是像这样画图\nDialogue: 0,0:14:58.36,0:15:00.68,Default,,0,0,0,,图示的缺陷之一 就是占用了太多空间\nDialogue: 0,0:15:00.89,0:15:01.98,Default,,0,0,0,,对于这样的一个小型机器来说\nDialogue: 0,0:15:02.00,0:15:03.05,Default,,0,0,0,,它占用了两块黑板\nDialogue: 0,0:15:03.22,0:15:05.24,Default,,0,0,0,,而一台求值器机器\nDialogue: 0,0:15:05.40,0:15:07.10,Default,,0,0,0,,我就很难将它画在这间屋子里了\nDialogue: 0,0:15:07.95,0:15:09.16,Default,,0,0,0,,尽管它还不是非常大\nDialogue: 0,0:15:09.90,0:15:11.28,Default,,0,0,0,,因此我要为它构造一门小型语言\nDialogue: 0,0:15:11.29,0:15:12.51,Default,,0,0,0,,用来描述这个机器\nDialogue: 0,0:15:13.10,0:15:23.29,Default,,0,0,0,,(DEFIME-MACHINE GCD\nDialogue: 0,0:15:24.42,0:15:25.66,Default,,0,0,0,,当然 一旦我们有了像这样的描述\nDialogue: 0,0:15:25.68,0:15:26.83,Default,,0,0,0,,我们就能够模拟该机器\nDialogue: 0,0:15:27.22,0:15:29.42,Default,,0,0,0,,我之所以想构建这种形式的语言\nDialogue: 0,0:15:29.56,0:15:32.94,Default,,0,0,0,,是因为我们能够立即操纵这些表达式\nDialogue: 0,0:15:33.21,0:15:34.91,Default,,0,0,0,,因此 我也就能够\nDialogue: 0,0:15:35.29,0:15:38.16,Default,,0,0,0,,代数地操作 或者模拟这些东西\nDialogue: 0,0:15:38.20,0:15:39.96,Default,,0,0,0,,以及各种各样我想进行的操作\nDialogue: 0,0:15:40.12,0:15:42.59,Default,,0,0,0,,或者还可以把它们转换成布局图 谁知道呢？\nDialogue: 0,0:15:43.63,0:15:48.38,Default,,0,0,0,,一旦我有了寄存器的良好表示\nDialogue: 0,0:15:48.51,0:15:49.61,Default,,0,0,0,,它有一些寄存器\nDialogue: 0,0:15:53.00,0:15:55.64,Default,,0,0,0,,记作(REGISTERS A B T)\nDialogue: 0,0:15:56.75,0:15:57.80,Default,,0,0,0,,它还有控制器\nDialogue: 0,0:16:02.19,0:16:04.46,Default,,0,0,0,,实际上 更好的做法是让它更显式一些\nDialogue: 0,0:16:04.49,0:16:06.97,Default,,0,0,0,,也就是说 为每一个按钮命名\nDialogue: 0,0:16:08.14,0:16:10.17,Default,,0,0,0,,并指明它们的操作\nDialogue: 0,0:16:10.42,0:16:11.37,Default,,0,0,0,,比如说这个按钮\nDialogue: 0,0:16:11.55,0:16:14.19,Default,,0,0,0,,会让T的值送入到B中\nDialogue: 0,0:16:15.10,0:16:16.09,Default,,0,0,0,,但我却不想这么做\nDialogue: 0,0:16:16.11,0:16:17.95,Default,,0,0,0,,因为这样会让代码难以阅读\nDialogue: 0,0:16:18.20,0:16:19.34,Default,,0,0,0,,也会占用更多空间\nDialogue: 0,0:16:19.51,0:16:22.36,Default,,0,0,0,,所以我会把相关的指令写在控制器中\nDialogue: 0,0:16:23.29,0:16:25.24,Default,,0,0,0,,这样就隐式地指明了具体的操作\nDialogue: 0,0:16:26.32,0:16:28.57,Default,,0,0,0,,可以通过阅读代码推断出来\nDialogue: 0,0:16:29.16,0:16:31.39,Default,,0,0,0,,并收集所有可以完成的不同事情\nDialogue: 0,0:16:31.69,0:16:33.50,Default,,0,0,0,,我们来看一看\nDialogue: 0,0:16:33.50,0:16:34.70,Default,,0,0,0,,我们来看下这些东西是什么吧\nDialogue: 0,0:16:35.71,0:16:37.29,Default,,0,0,0,,首先是一个循环\nDialogue: 0,0:16:38.24,0:16:40.20,Default,,0,0,0,,先是一条分支指令\nDialogue: 0,0:16:42.64,0:16:46.46,Default,,0,0,0,,这个就对应了机器中的小挡板\nDialogue: 0,0:16:46.89,0:16:48.49,Default,,0,0,0,,它决定了你在此处的走向\nDialogue: 0,0:16:49.10,0:16:58.00,Default,,0,0,0,,判断 -- 取B的值 并判断是否为0\nDialogue: 0,0:16:58.65,0:17:00.06,Default,,0,0,0,,如果B的值是0\nDialogue: 0,0:17:00.32,0:17:01.72,Default,,0,0,0,,那么就跳转到一个叫DONE的地方\nDialogue: 0,0:17:03.64,0:17:05.29,Default,,0,0,0,,现在 你们在这里看到的是\nDialogue: 0,0:17:05.29,0:17:07.40,Default,,0,0,0,,这个看起来非常像传统计算机语言\nDialogue: 0,0:17:08.17,0:17:09.55,Default,,0,0,0,,但你们所见的是\nDialogue: 0,0:17:10.03,0:17:12.00,Default,,0,0,0,,一些个标签\nDialogue: 0,0:17:12.99,0:17:16.86,Default,,0,0,0,,它们代表着存放了一系列指令的地方\nDialogue: 0,0:17:17.60,0:17:18.94,Default,,0,0,0,,之所以需要它们\nDialogue: 0,0:17:19.48,0:17:21.15,Default,,0,0,0,,是因为在这里\nDialogue: 0,0:17:21.45,0:17:22.81,Default,,0,0,0,,我表达了“循环”的概念\nDialogue: 0,0:17:23.32,0:17:26.11,Default,,0,0,0,,但是如果我是在写英文之类的文本\nDialogue: 0,0:17:26.44,0:17:28.09,Default,,0,0,0,,就很难去引用一个位置\nDialogue: 0,0:17:28.58,0:17:29.53,Default,,0,0,0,,我没有箭头\nDialogue: 0,0:17:30.80,0:17:33.02,Default,,0,0,0,,箭头是通过\nDialogue: 0,0:17:33.05,0:17:34.44,Default,,0,0,0,,给箭头所指的地方命名来表示的\nDialogue: 0,0:17:34.57,0:17:36.28,Default,,0,0,0,,并通过名字来引用\nDialogue: 0,0:17:37.40,0:17:38.59,Default,,0,0,0,,这只是一种编码\nDialogue: 0,0:17:39.86,0:17:41.88,Default,,0,0,0,,而不是某种魔法\nDialogue: 0,0:17:43.15,0:17:44.96,Default,,0,0,0,,接下来我们要做的是\nDialogue: 0,0:17:45.02,0:17:46.84,Default,,0,0,0,,我们如何来实现T←R\nDialogue: 0,0:17:47.45,0:17:49.76,Default,,0,0,0,,非常简单 用ASSIGN\nDialogue: 0,0:17:52.19,0:17:55.55,Default,,0,0,0,,我们把余数赋值给T\nDialogue: 0,0:17:56.32,0:17:59.24,Default,,0,0,0,,ASSIGN就是按钮的名字\nDialogue: 0,0:18:01.47,0:18:02.64,Default,,0,0,0,,就是按按钮的家伙\nDialogue: 0,0:18:03.14,0:18:04.97,Default,,0,0,0,,把余数赋给T\nDialogue: 0,0:18:04.99,0:18:06.76,Default,,0,0,0,,这个操作是这样表示的\nDialogue: 0,0:18:11.74,0:18:17.53,Default,,0,0,0,,取A、B的值 相除得到余数\nDialogue: 0,0:18:23.85,0:18:30.99,Default,,0,0,0,,同时 我们也要取B的值 赋给A\nDialogue: 0,0:18:34.99,0:18:47.88,Default,,0,0,0,,再取T的值赋给B\nDialogue: 0,0:18:49.61,0:18:51.85,Default,,0,0,0,,现在 我需要引用这个开头\nDialogue: 0,0:18:53.18,0:18:55.92,Default,,0,0,0,,呃 我为什么不把这里叫做LOOP呢？\nDialogue: 0,0:19:04.09,0:19:07.04,Default,,0,0,0,,这就是如何引用这个箭头\nDialogue: 0,0:19:07.61,0:19:08.95,Default,,0,0,0,,当执行到DONE时 就完成了所有操作\nDialogue: 0,0:19:09.02,0:19:13.07,Default,,0,0,0,,我们来到了这里 所有指令的结尾\nDialogue: 0,0:19:15.26,0:19:17.04,Default,,0,0,0,,这段文字化描述的就是\nDialogue: 0,0:19:17.69,0:19:20.86,Default,,0,0,0,,我们在这里画的一小部分机器\nDialogue: 0,0:19:21.66,0:19:24.84,Default,,0,0,0,,下面 我就要运行它\nDialogue: 0,0:19:25.49,0:19:26.65,Default,,0,0,0,,我想让你们感受一下它的运行\nDialogue: 0,0:19:27.62,0:19:29.80,Default,,0,0,0,,从来没有做过这个 你必须做一次\nDialogue: 0,0:19:31.01,0:19:32.62,Default,,0,0,0,,让我们以一个具体的问题来演示\nDialogue: 0,0:19:33.10,0:19:34.70,Default,,0,0,0,,假设我们想要计算\nDialogue: 0,0:19:35.04,0:19:40.68,Default,,0,0,0,,30和42的最大公约数\nDialogue: 0,0:19:42.21,0:19:44.92,Default,,0,0,0,,我现在不知道结果是多少\nDialogue: 0,0:19:45.86,0:19:47.60,Default,,0,0,0,,但我知道A=30而B=42\nDialogue: 0,0:19:50.96,0:19:52.09,Default,,0,0,0,,我就这么着开始\nDialogue: 0,0:19:52.60,0:19:53.90,Default,,0,0,0,,那么 我首先要做些什么呢？\nDialogue: 0,0:19:54.24,0:19:56.86,Default,,0,0,0,,我先判断B是否为0：否\nDialogue: 0,0:19:57.59,0:20:02.11,Default,,0,0,0,,然后计算A除B的余数 并赋给T\nDialogue: 0,0:20:02.80,0:20:07.60,Default,,0,0,0,,当然 30除以42的余数就是30自己\nDialogue: 0,0:20:11.13,0:20:12.03,Default,,0,0,0,,按下那个按钮\nDialogue: 0,0:20:12.92,0:20:15.10,Default,,0,0,0,,现在弹珠就滚动到了这里\nDialogue: 0,0:20:17.10,0:20:18.06,Default,,0,0,0,,A←B\nDialogue: 0,0:20:19.02,0:20:20.76,Default,,0,0,0,,又按下了这个按钮\nDialogue: 0,0:20:21.22,0:20:22.54,Default,,0,0,0,,因此42来到了这里\nDialogue: 0,0:20:26.59,0:20:27.60,Default,,0,0,0,,B←T\nDialogue: 0,0:20:28.36,0:20:29.34,Default,,0,0,0,,按下了这个按钮\nDialogue: 0,0:20:29.87,0:20:30.96,Default,,0,0,0,,30来到了这里\nDialogue: 0,0:20:32.57,0:20:33.69,Default,,0,0,0,,这样我就交换了它们\nDialogue: 0,0:20:34.66,0:20:38.27,Default,,0,0,0,,我们再来看看 回到开始\nDialogue: 0,0:20:38.64,0:20:39.72,Default,,0,0,0,,B为0么？不\nDialogue: 0,0:20:40.19,0:20:41.50,Default,,0,0,0,,将余数赋给T\nDialogue: 0,0:20:43.23,0:20:46.30,Default,,0,0,0,,我想 42除以30的余数是12\nDialogue: 0,0:20:47.24,0:20:48.30,Default,,0,0,0,,按下这个钮\nDialogue: 0,0:20:48.53,0:20:51.40,Default,,0,0,0,,下面 我想让30来到这里\nDialogue: 0,0:20:53.90,0:20:55.95,Default,,0,0,0,,按下这个钮 让12来到这里\nDialogue: 0,0:20:58.41,0:21:00.38,Default,,0,0,0,,然后继续\nDialogue: 0,0:21:00.38,0:21:01.31,Default,,0,0,0,,程序执行完了么？\nDialogue: 0,0:21:01.53,0:21:02.12,Default,,0,0,0,,并没有\nDialogue: 0,0:21:02.36,0:21:08.22,Default,,0,0,0,,现在 我需要求解30除以12的余数\nDialogue: 0,0:21:08.85,0:21:10.67,Default,,0,0,0,,我想答案是6\nDialogue: 0,0:21:12.42,0:21:15.13,Default,,0,0,0,,按下这个钮 6就到了这里\nDialogue: 0,0:21:16.20,0:21:18.25,Default,,0,0,0,,然后我又按下这个钮\nDialogue: 0,0:21:18.30,0:21:19.61,Default,,0,0,0,,这就让12来到了这里\nDialogue: 0,0:21:23.73,0:21:25.09,Default,,0,0,0,,然后我又按下这个按钮\nDialogue: 0,0:21:25.09,0:21:26.00,Default,,0,0,0,,6就来到了这里\nDialogue: 0,0:21:29.85,0:21:31.68,Default,,0,0,0,,6等于0么？\nDialogue: 0,0:21:31.88,0:21:32.49,Default,,0,0,0,,不等于\nDialogue: 0,0:21:33.42,0:21:33.98,Default,,0,0,0,,好的\nDialogue: 0,0:21:34.38,0:21:36.80,Default,,0,0,0,,因此这时\nDialogue: 0,0:21:36.89,0:21:38.12,Default,,0,0,0,,接下来又要计算余数\nDialogue: 0,0:21:38.14,0:21:39.80,Default,,0,0,0,,哦 这个的余数是0\nDialogue: 0,0:21:40.66,0:21:41.74,Default,,0,0,0,,看起来我们就快完成了\nDialogue: 0,0:21:42.36,0:21:44.36,Default,,0,0,0,,将6从这里挪到这里\nDialogue: 0,0:21:47.00,0:21:48.27,Default,,0,0,0,,0移动到这里\nDialogue: 0,0:21:49.09,0:21:50.20,Default,,0,0,0,,0等于0么？\nDialogue: 0,0:21:50.20,0:21:50.73,Default,,0,0,0,,是的\nDialogue: 0,0:21:51.34,0:21:53.36,Default,,0,0,0,,B的值等于0 因此答案就是A的值\nDialogue: 0,0:21:54.28,0:21:55.76,Default,,0,0,0,,因此答案就是6\nDialogue: 0,0:21:56.61,0:21:57.61,Default,,0,0,0,,这确实是正确的答案\nDialogue: 0,0:21:57.63,0:21:59.47,Default,,0,0,0,,因为如果我们回过头审视最初的问题\nDialogue: 0,0:22:00.08,0:22:06.64,Default,,0,0,0,,我们知道30=2×3×5\nDialogue: 0,0:22:07.00,0:22:11.12,Default,,0,0,0,,42=2×3×7\nDialogue: 0,0:22:11.67,0:22:14.11,Default,,0,0,0,,因此最大公约数就是2×3\nDialogue: 0,0:22:14.20,0:22:15.08,Default,,0,0,0,,也就是6\nDialogue: 0,0:22:18.38,0:22:20.56,Default,,0,0,0,,我们通常在这里画另外一条线\nDialogue: 0,0:22:20.59,0:22:22.52,Default,,0,0,0,,为了使它更清晰一点\nDialogue: 0,0:22:22.89,0:22:27.71,Default,,0,0,0,,在这两者之间建立了联系\nDialogue: 0,0:22:27.85,0:22:31.01,Default,,0,0,0,,小挡板需要根据这个指示灯来工作\nDialogue: 0,0:22:34.00,0:22:37.32,Default,,0,0,0,,当然 跟我给你们展示的东西相比\nDialogue: 0,0:22:37.85,0:22:40.00,Default,,0,0,0,,真实计算机的组件更加复杂\nDialogue: 0,0:22:41.35,0:22:47.16,Default,,0,0,0,,让我们来看看第一张幻灯片\nDialogue: 0,0:22:47.98,0:22:48.81,Default,,0,0,0,,哇\nDialogue: 0,0:22:50.19,0:22:52.43,Default,,0,0,0,,我们看到 我们想要做的就是\nDialogue: 0,0:22:52.65,0:22:55.85,Default,,0,0,0,,IO形式的操作\nDialogue: 0,0:22:56.84,0:23:01.42,Default,,0,0,0,,我们需要从外部搜集一些东西\nDialogue: 0,0:23:01.98,0:23:03.93,Default,,0,0,0,,因此 对我们的状态机器来说\nDialogue: 0,0:23:04.30,0:23:07.02,Default,,0,0,0,,它们的控制器\nDialogue: 0,0:23:07.26,0:23:10.56,Default,,0,0,0,,可能会从某处取得某值\nDialogue: 0,0:23:10.78,0:23:12.41,Default,,0,0,0,,将它们放入寄存器并从中读取\nDialogue: 0,0:23:13.49,0:23:15.92,Default,,0,0,0,,我还可以把另外的值加载到寄存器B中\nDialogue: 0,0:23:17.07,0:23:18.60,Default,,0,0,0,,稍后 当执行完毕后\nDialogue: 0,0:23:18.99,0:23:20.52,Default,,0,0,0,,我想要输出结果\nDialogue: 0,0:23:21.20,0:23:25.23,Default,,0,0,0,,当然 答案或简单或复杂\nDialogue: 0,0:23:26.09,0:23:28.03,Default,,0,0,0,,我写代码的时候 总假设PRINT很简单\nDialogue: 0,0:23:28.09,0:23:29.29,Default,,0,0,0,,READ也很简单\nDialogue: 0,0:23:29.88,0:23:31.08,Default,,0,0,0,,但实际上 在真实世界中\nDialogue: 0,0:23:31.12,0:23:32.89,Default,,0,0,0,,这些都是非常复杂的操作\nDialogue: 0,0:23:33.08,0:23:35.52,Default,,0,0,0,,跟你尝试求解的问题相比\nDialogue: 0,0:23:35.55,0:23:38.33,Default,,0,0,0,,它们通常更加庞大而复杂\nDialogue: 0,0:23:41.67,0:23:43.90,Default,,0,0,0,,另一方面 我犹记得\nDialogue: 0,0:23:44.89,0:23:48.78,Default,,0,0,0,,使用IBM 7090一类的计算机的时候\nDialogue: 0,0:23:49.05,0:23:53.04,Default,,0,0,0,,它的READ和WRITE只能操作单个对象\nDialogue: 0,0:23:53.08,0:23:54.62,Default,,0,0,0,,也就是一个数字\nDialogue: 0,0:23:55.84,0:23:58.54,Default,,0,0,0,,这就是一个基本的IO操作\nDialogue: 0,0:23:59.63,0:24:02.04,Default,,0,0,0,,我们这里有同样的操作\nDialogue: 0,0:24:02.33,0:24:04.67,Default,,0,0,0,,在这样的一台机器中\nDialogue: 0,0:24:05.44,0:24:06.89,Default,,0,0,0,,我们实际上在做什么？\nDialogue: 0,0:24:07.12,0:24:11.60,Default,,0,0,0,,我们看到 这个叫做“READ”的组件是数据源头\nDialogue: 0,0:24:12.20,0:24:14.46,Default,,0,0,0,,这个操作总是返回一个值\nDialogue: 0,0:24:14.66,0:24:17.13,Default,,0,0,0,,我们可以把它看做 总是返回一个值\nDialogue: 0,0:24:17.21,0:24:19.84,Default,,0,0,0,,它可以赋给寄存器A或B\nDialogue: 0,0:24:21.66,0:24:23.23,Default,,0,0,0,,而PRINT这个过程呢\nDialogue: 0,0:24:23.37,0:24:25.02,Default,,0,0,0,,当你正确连接它的时候\nDialogue: 0,0:24:25.24,0:24:26.43,Default,,0,0,0,,当你按下上面的按钮\nDialogue: 0,0:24:26.65,0:24:29.61,Default,,0,0,0,,就会打印出当前寄存器A中的值\nDialogue: 0,0:24:31.66,0:24:32.73,Default,,0,0,0,,这非常普通\nDialogue: 0,0:24:33.32,0:24:35.20,Default,,0,0,0,,这是我们想要的一种功能\nDialogue: 0,0:24:35.88,0:24:38.32,Default,,0,0,0,,但这里还有些其它事情需要我们担忧\nDialogue: 0,0:24:38.32,0:24:40.67,Default,,0,0,0,,比如说 这里我使用了一些复杂的机制\nDialogue: 0,0:24:41.05,0:24:42.48,Default,,0,0,0,,我们这里有REMAINDER组件\nDialogue: 0,0:24:43.85,0:24:44.44,Default,,0,0,0,,这是个什么东西呢？\nDialogue: 0,0:24:44.69,0:24:46.41,Default,,0,0,0,,求取余数的计算过程并不是那么“显然”\nDialogue: 0,0:24:46.92,0:24:48.92,Default,,0,0,0,,如果我们把这个组件给拆开\nDialogue: 0,0:24:49.48,0:24:50.62,Default,,0,0,0,,就会得到一整台机器\nDialogue: 0,0:24:51.84,0:24:53.66,Default,,0,0,0,,事实就是这样的\nDialogue: 0,0:24:54.54,0:24:59.15,Default,,0,0,0,,举例来说 如果要编程实现REMAINDER\nDialogue: 0,0:24:59.44,0:25:02.44,Default,,0,0,0,,最简单的算法就是 不断地做减法\nDialogue: 0,0:25:04.78,0:25:05.95,Default,,0,0,0,,这是因为 除法可以通过\nDialogue: 0,0:25:05.96,0:25:08.99,Default,,0,0,0,,对整数不断做减法来实现\nDialogue: 0,0:25:09.80,0:25:23.58,Default,,0,0,0,,N除以D的余数不外乎就是\nDialogue: 0,0:25:24.99,0:25:31.44,Default,,0,0,0,,如果N小于D的话\nDialogue: 0,0:25:32.24,0:25:33.66,Default,,0,0,0,,答案就是N\nDialogue: 0,0:25:34.30,0:25:35.90,Default,,0,0,0,,否则的话就是\nDialogue: 0,0:25:41.15,0:25:47.60,Default,,0,0,0,,N先减去D\nDialogue: 0,0:25:48.27,0:25:49.32,Default,,0,0,0,,再除以D的余数\nDialogue: 0,0:25:51.28,0:25:55.05,Default,,0,0,0,,天啊 这个看起来就像是GCD程序\nDialogue: 0,0:25:56.89,0:25:59.48,Default,,0,0,0,,当然 这个不是求余数的最优算法\nDialogue: 0,0:25:59.75,0:26:00.91,Default,,0,0,0,,在实际中 你应该使用那些\nDialogue: 0,0:26:00.92,0:26:05.42,Default,,0,0,0,,二进制运算、移位运算等操作\nDialogue: 0,0:26:05.55,0:26:06.97,Default,,0,0,0,,但关键点就是\nDialogue: 0,0:26:07.13,0:26:08.48,Default,,0,0,0,,如果我把这些组件打开\nDialogue: 0,0:26:08.92,0:26:10.64,Default,,0,0,0,,我可能会发现其中有一台计算机\nDialogue: 0,0:26:11.88,0:26:12.99,Default,,0,0,0,,现在我们就知道它的原理了\nDialogue: 0,0:26:13.51,0:26:14.33,Default,,0,0,0,,因为我们就造过一台\nDialogue: 0,0:26:15.64,0:26:17.10,Default,,0,0,0,,这些个机器都大同小异\nDialogue: 0,0:26:17.40,0:26:18.06,Default,,0,0,0,,另外一方面\nDialogue: 0,0:26:18.08,0:26:20.00,Default,,0,0,0,,我们可能想要构建一台更高效\nDialogue: 0,0:26:20.01,0:26:21.68,Default,,0,0,0,,组织更精良的机器\nDialogue: 0,0:26:21.85,0:26:23.96,Default,,0,0,0,,比如说 多次利用其中的寄存器\nDialogue: 0,0:26:24.00,0:26:27.05,Default,,0,0,0,,或者是硬件设计者能想到的其它可怕混乱\nDialogue: 0,0:26:27.31,0:26:28.60,Default,,0,0,0,,等等原因\nDialogue: 0,0:26:29.25,0:26:31.56,Default,,0,0,0,,比如说 你们所见的这台机器\nDialogue: 0,0:26:32.52,0:26:34.91,Default,,0,0,0,,不是让你们去细读它的结构的\nDialogue: 0,0:26:35.05,0:26:37.52,Default,,0,0,0,,它有些复杂 对吧？\nDialogue: 0,0:26:37.52,0:26:39.87,Default,,0,0,0,,但它实际上是\nDialogue: 0,0:26:40.09,0:26:43.82,Default,,0,0,0,,整合了REMAINDER的GCD机器\nDialogue: 0,0:26:44.46,0:26:46.02,Default,,0,0,0,,并且实际上 它没有多余的寄存器\nDialogue: 0,0:26:46.02,0:26:48.62,Default,,0,0,0,,数据通路上有三个寄存器\nDialogue: 0,0:26:49.05,0:26:50.64,Default,,0,0,0,,但现在 这里有个减法器\nDialogue: 0,0:26:51.55,0:26:52.99,Default,,0,0,0,,又有两个东西被测试\nDialogue: 0,0:26:53.02,0:26:55.07,Default,,0,0,0,,B等于0么？\nDialogue: 0,0:26:55.23,0:26:56.56,Default,,0,0,0,,T小于B么？\nDialogue: 0,0:26:57.25,0:26:59.45,Default,,0,0,0,,而至于这一块的控制器\nDialogue: 0,0:27:00.22,0:27:01.76,Default,,0,0,0,,并不会更加复杂\nDialogue: 0,0:27:01.85,0:27:03.87,Default,,0,0,0,,它有两个循环\nDialogue: 0,0:27:04.52,0:27:08.33,Default,,0,0,0,,最主要的循环是计算GCD的\nDialogue: 0,0:27:08.40,0:27:10.14,Default,,0,0,0,,而另一条是减法循环\nDialogue: 0,0:27:10.43,0:27:12.80,Default,,0,0,0,,是用来计算余数的子操作\nDialogue: 0,0:27:14.03,0:27:15.80,Default,,0,0,0,,当然 还有一种思考方式\nDialogue: 0,0:27:15.96,0:27:18.68,Default,,0,0,0,,就是把求余数程序\nDialogue: 0,0:27:19.92,0:27:21.71,Default,,0,0,0,,如果我把那边的REMAINDER机器\nDialogue: 0,0:27:21.72,0:27:22.83,Default,,0,0,0,,当作LAMBDA表达式\nDialogue: 0,0:27:23.56,0:27:27.02,Default,,0,0,0,,代换到GCD程序的REMAINDER中\nDialogue: 0,0:27:28.20,0:27:30.12,Default,,0,0,0,,然后再做一些化简\nDialogue: 0,0:27:30.32,0:27:33.66,Default,,0,0,0,,代换其中的A和B\nDialogue: 0,0:27:34.46,0:27:35.95,Default,,0,0,0,,那么 我就可以展开这个循环\nDialogue: 0,0:27:36.63,0:27:39.42,Default,,0,0,0,,那么我就可以通过\nDialogue: 0,0:27:40.73,0:27:42.94,Default,,0,0,0,,LAMBDA表达式的基本代数化简\nDialogue: 0,0:27:43.36,0:27:45.21,Default,,0,0,0,,来得到这台机器\nDialogue: 0,0:27:48.55,0:27:51.20,Default,,0,0,0,,我想 你们已经见识了一个非常简单的机器了\nDialogue: 0,0:27:51.95,0:27:53.28,Default,,0,0,0,,有什么疑问么？\nDialogue: 0,0:28:02.70,0:28:03.10,Default,,0,0,0,,很好\nDialogue: 0,0:28:05.36,0:28:06.54,Default,,0,0,0,,看起来很容易 难道不是吗？\nDialogue: 0,0:28:10.14,0:28:11.32,Default,,0,0,0,,好吧 休息一下 谢谢大家\nDialogue: 0,0:28:12.54,0:28:24.94,Default,,0,0,0,,[音乐]\nDialogue: 0,0:28:25.13,0:28:28.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:31.37,0:28:34.70,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:28:34.76,0:28:38.00,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:28:38.00,0:28:43.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}寄存机器\nDialogue: 0,0:28:47.93,0:28:48.70,Default,,0,0,0,,教授：好吧\nDialogue: 0,0:28:49.37,0:28:52.46,Default,,0,0,0,,现在 你们已经知道如何去把迭代过程\nDialogue: 0,0:28:52.54,0:28:54.54,Default,,0,0,0,,或者是产生迭代计算的过程\nDialogue: 0,0:28:55.18,0:28:56.52,Default,,0,0,0,,变成一台机器\nDialogue: 0,0:28:57.77,0:29:00.04,Default,,0,0,0,,我想 接下来我们就应该考虑\nDialogue: 0,0:29:00.54,0:29:02.30,Default,,0,0,0,,如何来处理递归过程了\nDialogue: 0,0:29:02.81,0:29:05.05,Default,,0,0,0,,我们先从一个简单的阶乘过程开始\nDialogue: 0,0:29:11.20,0:29:16.94,Default,,0,0,0,,(DEFINE (FACT N)\nDialogue: 0,0:29:19.63,0:29:24.25,Default,,0,0,0,,如果N=1 那么结果就是1\nDialogue: 0,0:29:24.62,0:29:27.69,Default,,0,0,0,,为了减少模拟它的工作量 我就使用1\nDialogue: 0,0:29:28.12,0:29:33.94,Default,,0,0,0,,否则结果就是(* N (FACT (- N 1)))\nDialogue: 0,0:29:42.52,0:29:46.04,Default,,0,0,0,,正如你们所知 这个程序的不同之处在于\nDialogue: 0,0:29:46.65,0:29:50.36,Default,,0,0,0,,这里 我在计算(FACT (- N 1))之后\nDialogue: 0,0:29:50.67,0:29:52.26,Default,,0,0,0,,我要对结果做一些运算\nDialogue: 0,0:29:52.26,0:29:53.68,Default,,0,0,0,,我要将它与N相乘\nDialogue: 0,0:29:56.00,0:30:00.67,Default,,0,0,0,,将这台机器可视化的唯一途径就是\nDialogue: 0,0:30:01.08,0:30:02.01,Default,,0,0,0,,首先 由于--\nDialogue: 0,0:30:02.35,0:30:03.18,Default,,0,0,0,,请你们这么来想\nDialogue: 0,0:30:03.36,0:30:04.94,Default,,0,0,0,,这里 我有一台机器\nDialogue: 0,0:30:05.08,0:30:08.11,Default,,0,0,0,,而这台机器又需要某个阶乘机器来计算结果\nDialogue: 0,0:30:09.32,0:30:11.16,Default,,0,0,0,,但外面的这台机器\nDialogue: 0,0:30:11.20,0:30:13.02,Default,,0,0,0,,又需要在调用内部阶乘机器\nDialogue: 0,0:30:13.92,0:30:15.72,Default,,0,0,0,,的前后都要存在\nDialogue: 0,0:30:16.80,0:30:17.90,Default,,0,0,0,,然而在迭代情况中\nDialogue: 0,0:30:18.75,0:30:20.52,Default,,0,0,0,,外面的机器不需要\nDialogue: 0,0:30:20.91,0:30:24.01,Default,,0,0,0,,在内部机器运行后保持存在\nDialogue: 0,0:30:24.83,0:30:26.16,Default,,0,0,0,,这是因为你不需要回到\nDialogue: 0,0:30:26.19,0:30:27.53,Default,,0,0,0,,外部机器来进行其它操作\nDialogue: 0,0:30:28.64,0:30:30.06,Default,,0,0,0,,因此 我们这里的问题是\nDialogue: 0,0:30:30.27,0:30:30.97,Default,,0,0,0,,我们的机器内部\nDialogue: 0,0:30:31.00,0:30:32.73,Default,,0,0,0,,有一个同样的机器\nDialogue: 0,0:30:33.87,0:30:35.52,Default,,0,0,0,,一台无穷大的机器\nDialogue: 0,0:30:40.39,0:30:43.12,Default,,0,0,0,,这里面也有其它的东西 比如乘法器\nDialogue: 0,0:30:44.76,0:30:46.03,Default,,0,0,0,,它接收输入\nDialogue: 0,0:30:46.27,0:30:47.77,Default,,0,0,0,,这是-1操作\nDialogue: 0,0:30:48.12,0:30:49.31,Default,,0,0,0,,等等\nDialogue: 0,0:30:50.69,0:30:53.72,Default,,0,0,0,,你们可以想象 -- 它就是这个样子的\nDialogue: 0,0:30:54.37,0:30:56.76,Default,,0,0,0,,但重要之处就在于\nDialogue: 0,0:30:57.02,0:30:58.70,Default,,0,0,0,,内部机器执行之前与执行之后\nDialogue: 0,0:30:58.78,0:31:01.60,Default,,0,0,0,,外部机器中都进行了一些运算\nDialogue: 0,0:31:02.54,0:31:04.08,Default,,0,0,0,,因此这台机器必须有“生命”\nDialogue: 0,0:31:05.47,0:31:11.44,Default,,0,0,0,,外部机器需要在内部机器的两个时间点保持存在\nDialogue: 0,0:31:13.49,0:31:15.80,Default,,0,0,0,,因此 我就需要有一个地方来保存\nDialogue: 0,0:31:16.19,0:31:18.19,Default,,0,0,0,,维持外部机器运转的数据\nDialogue: 0,0:31:20.03,0:31:22.09,Default,,0,0,0,,现实世界中不存在无穷的对象\nDialogue: 0,0:31:24.14,0:31:25.58,Default,,0,0,0,,我们要做的就是营造一种假象\nDialogue: 0,0:31:26.12,0:31:27.48,Default,,0,0,0,,一种无穷对象的假象\nDialogue: 0,0:31:27.98,0:31:29.77,Default,,0,0,0,,我们在某处有无穷的硬件资源\nDialogue: 0,0:31:31.83,0:31:35.34,Default,,0,0,0,,现在 这个假象非常重要\nDialogue: 0,0:31:36.28,0:31:37.37,Default,,0,0,0,,如果我们能保证\nDialogue: 0,0:31:38.00,0:31:39.84,Default,,0,0,0,,每次当你查看某个无穷对象时\nDialogue: 0,0:31:39.88,0:31:42.96,Default,,0,0,0,,你所要观察的那部分存在\nDialogue: 0,0:31:44.49,0:31:46.04,Default,,0,0,0,,那么就不需要实际上的“无穷”\nDialogue: 0,0:31:47.39,0:31:49.44,Default,,0,0,0,,当然 这里面我们想做的就是\nDialogue: 0,0:31:49.82,0:31:52.49,Default,,0,0,0,,来看下这里的东西\nDialogue: 0,0:31:53.00,0:31:54.97,Default,,0,0,0,,这是我们目前为止的结构\nDialogue: 0,0:31:56.04,0:31:57.64,Default,,0,0,0,,这些结构呢\nDialogue: 0,0:31:57.92,0:32:01.37,Default,,0,0,0,,是机器的几大部分\nDialogue: 0,0:32:01.40,0:32:02.33,Default,,0,0,0,,比如控制器\nDialogue: 0,0:32:03.18,0:32:04.46,Default,,0,0,0,,它在这里\nDialogue: 0,0:32:04.78,0:32:07.61,Default,,0,0,0,,它相当简单 并且是有穷的\nDialogue: 0,0:32:09.17,0:32:10.44,Default,,0,0,0,,我们还有数据通路\nDialogue: 0,0:32:10.46,0:32:12.75,Default,,0,0,0,,它由寄存器和运算器组成\nDialogue: 0,0:32:13.08,0:32:15.20,Default,,0,0,0,,现在我提议\nDialogue: 0,0:32:15.48,0:32:16.96,Default,,0,0,0,,把机器分成两部分\nDialogue: 0,0:32:17.36,0:32:19.79,Default,,0,0,0,,这样 其中一部分全部是有穷的\nDialogue: 0,0:32:20.78,0:32:23.53,Default,,0,0,0,,而另一部分 可以保存无穷数据中的一部分\nDialogue: 0,0:32:24.23,0:32:25.90,Default,,0,0,0,,换句话说 这部分也非常简单\nDialogue: 0,0:32:26.41,0:32:28.72,Default,,0,0,0,,但并非无穷 只是非常大而已\nDialogue: 0,0:32:29.43,0:32:30.40,Default,,0,0,0,,但它非常简单\nDialogue: 0,0:32:30.52,0:32:32.92,Default,,0,0,0,,以至于能够廉价地大量生产\nDialogue: 0,0:32:34.09,0:32:34.92,Default,,0,0,0,,它就是内存\nDialogue: 0,0:32:35.95,0:32:39.07,Default,,0,0,0,,我们可以利用它来构造栈结构\nDialogue: 0,0:32:39.40,0:32:41.23,Default,,0,0,0,,事实上 这就使得我们\nDialogue: 0,0:32:41.45,0:32:43.63,Default,,0,0,0,,能够模拟无穷机器的存在\nDialogue: 0,0:32:43.64,0:32:46.96,Default,,0,0,0,,也就是那些递归嵌套的机器\nDialogue: 0,0:32:48.34,0:32:50.43,Default,,0,0,0,,而它的原理则是\nDialogue: 0,0:32:50.56,0:32:52.97,Default,,0,0,0,,我们要在栈上存放必要的信息\nDialogue: 0,0:32:54.30,0:32:57.58,Default,,0,0,0,,用于内部机器执行完毕后\nDialogue: 0,0:32:59.18,0:33:01.07,Default,,0,0,0,,继续外部机器的操作\nDialogue: 0,0:33:03.84,0:33:05.48,Default,,0,0,0,,因此它会记住\nDialogue: 0,0:33:05.63,0:33:07.95,Default,,0,0,0,,关于外部机器生命期的重要数据\nDialogue: 0,0:33:08.04,0:33:10.30,Default,,0,0,0,,这些是进行计算所必需的\nDialogue: 0,0:33:11.39,0:33:12.48,Default,,0,0,0,,当然\nDialogue: 0,0:33:12.75,0:33:16.33,Default,,0,0,0,,由于这些机器是通过递归的方式嵌套的\nDialogue: 0,0:33:18.33,0:33:23.39,Default,,0,0,0,,因此 栈的存取方式也会是\nDialogue: 0,0:33:23.45,0:33:26.44,Default,,0,0,0,,也会是后进先出的\nDialogue: 0,0:33:29.33,0:33:30.64,Default,,0,0,0,,因此我们只需要存取\nDialogue: 0,0:33:30.80,0:33:32.52,Default,,0,0,0,,这个栈内存的一小部分\nDialogue: 0,0:33:34.93,0:33:35.92,Default,,0,0,0,,好吧 让我们来试一试\nDialogue: 0,0:33:36.81,0:33:38.41,Default,,0,0,0,,我已经给你们画好了数据通路\nDialogue: 0,0:33:38.44,0:33:39.68,Default,,0,0,0,,现在该布置控制器了\nDialogue: 0,0:33:40.37,0:33:42.86,Default,,0,0,0,,然后我们来运行一下 观察实际工作原理\nDialogue: 0,0:33:43.51,0:33:46.88,Default,,0,0,0,,还好阶乘机器不是特别的复杂\nDialogue: 0,0:33:47.90,0:33:50.16,Default,,0,0,0,,它有一个VAL寄存器\nDialogue: 0,0:33:52.22,0:33:53.88,Default,,0,0,0,,这是用来存储答案的\nDialogue: 0,0:33:54.89,0:33:56.67,Default,,0,0,0,,还有一个寄存器N\nDialogue: 0,0:33:59.85,0:34:04.16,Default,,0,0,0,,它里面存储的是要计算阶乘的数\nDialogue: 0,0:34:04.51,0:34:06.57,Default,,0,0,0,,为了满足某些情况\nDialogue: 0,0:34:07.48,0:34:10.52,Default,,0,0,0,,我们要连接VAL和N\nDialogue: 0,0:34:11.74,0:34:15.63,Default,,0,0,0,,事实上 如果我在这里返回N\nDialogue: 0,0:34:16.38,0:34:19.53,Default,,0,0,0,,也是正确的 因为这时N就等于1\nDialogue: 0,0:34:20.09,0:34:23.26,Default,,0,0,0,,这样的话 我就可以把结果移动过去\nDialogue: 0,0:34:23.90,0:34:25.55,Default,,0,0,0,,但我现在不考虑这个问题\nDialogue: 0,0:34:26.98,0:34:28.60,Default,,0,0,0,,我还需要做一些事情\nDialogue: 0,0:34:29.06,0:34:31.02,Default,,0,0,0,,就像我们在这里看到的 我们还需要\nDialogue: 0,0:34:31.21,0:34:34.67,Default,,0,0,0,,用VAL的值乘以N\nDialogue: 0,0:34:34.91,0:34:37.45,Default,,0,0,0,,因为VAL是计算阶乘的结果\nDialogue: 0,0:34:38.68,0:34:40.44,Default,,0,0,0,,我需要把算得的结果送回VAL\nDialogue: 0,0:34:41.48,0:34:42.65,Default,,0,0,0,,所以这里我们看到\nDialogue: 0,0:34:42.83,0:34:46.43,Default,,0,0,0,,N的阶乘就是\nDialogue: 0,0:34:46.57,0:34:49.20,Default,,0,0,0,,N乘以某个阶乘\nDialogue: 0,0:34:50.69,0:34:53.77,Default,,0,0,0,,而VAL就代表了内部阶乘的结果\nDialogue: 0,0:34:55.19,0:35:00.25,Default,,0,0,0,,因此 在这里我需要有一个乘法器\nDialogue: 0,0:35:02.36,0:35:07.18,Default,,0,0,0,,它的参数有：N以及VAL\nDialogue: 0,0:35:08.64,0:35:15.60,Default,,0,0,0,,并且 像这样把计算结果送回VAL\nDialogue: 0,0:35:17.17,0:35:19.39,Default,,0,0,0,,我也需要知道N是否为1\nDialogue: 0,0:35:21.32,0:35:22.38,Default,,0,0,0,,因此我需要一个指示灯\nDialogue: 0,0:35:28.20,0:35:30.40,Default,,0,0,0,,另外 我想我还需要\nDialogue: 0,0:35:31.02,0:35:32.84,Default,,0,0,0,,一个组件来减小N\nDialogue: 0,0:35:34.84,0:35:36.09,Default,,0,0,0,,所以这里有一个递减器\nDialogue: 0,0:35:38.19,0:35:41.39,Default,,0,0,0,,它接收参数N 将结果送回N\nDialogue: 0,0:35:46.62,0:35:48.40,Default,,0,0,0,,这基本上就是我的机器所需要的东西了\nDialogue: 0,0:35:49.55,0:35:51.64,Default,,0,0,0,,然而 我还需要一些个东西\nDialogue: 0,0:35:52.30,0:35:53.58,Default,,0,0,0,,一个稍微复杂一点的东西\nDialogue: 0,0:35:55.16,0:35:56.88,Default,,0,0,0,,因为我需要有一种方式能够存储\nDialogue: 0,0:35:57.16,0:35:59.69,Default,,0,0,0,,必要的一些信息\nDialogue: 0,0:36:01.02,0:36:03.07,Default,,0,0,0,,以便计算完子阶乘后\nDialogue: 0,0:36:03.10,0:36:04.89,Default,,0,0,0,,恢复原始阶乘的计算\nDialogue: 0,0:36:06.25,0:36:06.86,Default,,0,0,0,,需要哪些信息呢?\nDialogue: 0,0:36:07.23,0:36:08.73,Default,,0,0,0,,首先就是N\nDialogue: 0,0:36:09.85,0:36:12.04,Default,,0,0,0,,因此 我要在这里构造一个栈\nDialogue: 0,0:36:14.70,0:36:15.77,Default,,0,0,0,,所谓的栈就是\nDialogue: 0,0:36:17.98,0:36:24.97,Default,,0,0,0,,一大堆连续的空间\nDialogue: 0,0:36:27.15,0:36:28.59,Default,,0,0,0,,我不知道它到底有多深\nDialogue: 0,0:36:29.15,0:36:31.48,Default,,0,0,0,,栈越深 无穷的假象营造得就越好\nDialogue: 0,0:36:33.23,0:36:35.56,Default,,0,0,0,,我还需要有一种方法 能够把\nDialogue: 0,0:36:35.60,0:36:37.02,Default,,0,0,0,,N中的值放入栈中\nDialogue: 0,0:36:38.12,0:36:39.08,Default,,0,0,0,,反过来也是\nDialogue: 0,0:36:39.93,0:36:41.74,Default,,0,0,0,,因此我需要一条像这样的连接\nDialogue: 0,0:36:44.41,0:36:45.48,Default,,0,0,0,,它是双向的\nDialogue: 0,0:36:50.44,0:36:52.22,Default,,0,0,0,,通过它 我就可以在某个时间\nDialogue: 0,0:36:52.24,0:36:55.50,Default,,0,0,0,,把N的值存储起来\nDialogue: 0,0:36:56.04,0:36:56.84,Default,,0,0,0,,这就是栈\nDialogue: 0,0:36:58.10,0:37:01.71,Default,,0,0,0,,我还需要一种方法来记住\nDialogue: 0,0:37:01.84,0:37:07.72,Default,,0,0,0,,我现在计算到外部程序的哪个地方了\nDialogue: 0,0:37:08.53,0:37:10.06,Default,,0,0,0,,现在 对于这台机器来说\nDialogue: 0,0:37:10.76,0:37:13.34,Default,,0,0,0,,这并不是什么问题\nDialogue: 0,0:37:14.17,0:37:16.24,Default,,0,0,0,,FACT总是返回在\nDialogue: 0,0:37:16.86,0:37:19.07,Default,,0,0,0,,一个跟N相乘的地方\nDialogue: 0,0:37:19.34,0:37:20.72,Default,,0,0,0,,除了最后的一次\nDialogue: 0,0:37:21.15,0:37:23.02,Default,,0,0,0,,它返回到需要FACT最终答案的地方\nDialogue: 0,0:37:23.04,0:37:24.04,Default,,0,0,0,,或者是'DONE、'STOP之类的\nDialogue: 0,0:37:25.66,0:37:26.67,Default,,0,0,0,,然而 通常来说\nDialogue: 0,0:37:27.16,0:37:28.73,Default,,0,0,0,,我需要记住我去过哪些地方\nDialogue: 0,0:37:29.13,0:37:31.24,Default,,0,0,0,,因为 我可能从其它地方调用FACT\nDialogue: 0,0:37:32.08,0:37:34.89,Default,,0,0,0,,我需要返回到那个地方 并从那里继续\nDialogue: 0,0:37:36.07,0:37:38.00,Default,,0,0,0,,因此 我需要有一种方法能够\nDialogue: 0,0:37:38.01,0:37:40.86,Default,,0,0,0,,记住有穷状态控制器中弹珠的位置\nDialogue: 0,0:37:41.32,0:37:42.64,Default,,0,0,0,,也就是控制器的状态\nDialogue: 0,0:37:44.22,0:37:46.35,Default,,0,0,0,,并将它存储在栈中\nDialogue: 0,0:37:47.40,0:37:49.10,Default,,0,0,0,,我也需要有一种方法\nDialogue: 0,0:37:49.45,0:37:51.12,Default,,0,0,0,,能够恢复弹珠的状态\nDialogue: 0,0:37:52.14,0:37:54.28,Default,,0,0,0,,因此 我需要有一种将弹珠归位的能力\nDialogue: 0,0:37:54.70,0:37:56.52,Default,,0,0,0,,现在 我们有一个地方用于存储弹珠\nDialogue: 0,0:37:57.87,0:37:59.34,Default,,0,0,0,,它被称作“继续”寄存器\nDialogue: 0,0:38:03.61,0:38:04.52,Default,,0,0,0,,记作CONTINUE\nDialogue: 0,0:38:09.16,0:38:10.68,Default,,0,0,0,,下一次调用(GOTO CONTINUE)时\nDialogue: 0,0:38:11.00,0:38:13.05,Default,,0,0,0,,弹珠就会去向这个地方\nDialogue: 0,0:38:14.91,0:38:15.92,Default,,0,0,0,,它就是用来干这个的\nDialogue: 0,0:38:16.14,0:38:18.48,Default,,0,0,0,,因此 它和控制器之间应该有一条通路\nDialogue: 0,0:38:22.91,0:38:27.12,Default,,0,0,0,,我也能够将它存储在栈上\nDialogue: 0,0:38:29.45,0:38:33.10,Default,,0,0,0,,我也能够把它设置成各种常量\nDialogue: 0,0:38:34.01,0:38:35.69,Default,,0,0,0,,某一些常量\nDialogue: 0,0:38:36.86,0:38:38.20,Default,,0,0,0,,这非常容易实现\nDialogue: 0,0:38:38.84,0:38:40.14,Default,,0,0,0,,我们现在这里设一些常量\nDialogue: 0,0:38:40.18,0:38:41.50,Default,,0,0,0,,我们把这个记作AFTER-FACT\nDialogue: 0,0:38:47.32,0:38:48.75,Default,,0,0,0,,这个常量\nDialogue: 0,0:38:48.84,0:38:51.50,Default,,0,0,0,,会送入CONTINUE寄存器\nDialogue: 0,0:38:52.59,0:38:54.43,Default,,0,0,0,,另外一个寄存器是FACT-DONE\nDialogue: 0,0:39:05.21,0:39:07.82,Default,,0,0,0,,这就是我想要构建的机器\nDialogue: 0,0:39:08.13,0:39:09.48,Default,,0,0,0,,至少是数据通路部分\nDialogue: 0,0:39:09.92,0:39:11.69,Default,,0,0,0,,这里还混合了一些控制器\nDialogue: 0,0:39:11.85,0:39:14.59,Default,,0,0,0,,这是因为我需要记住我当前的位置\nDialogue: 0,0:39:14.70,0:39:16.35,Default,,0,0,0,,并将我恢复到该位置\nDialogue: 0,0:39:17.30,0:39:19.93,Default,,0,0,0,,现在 让我们来编写控制器对应的程序\nDialogue: 0,0:39:20.39,0:39:23.47,Default,,0,0,0,,我就把DEFINE-MACHINE和寄存器列表给省略了\nDialogue: 0,0:39:23.48,0:39:24.89,Default,,0,0,0,,因为它们无关紧要\nDialogue: 0,0:39:25.13,0:39:27.79,Default,,0,0,0,,我就直接写那些跟控制器有关的\nDialogue: 0,0:39:27.82,0:39:29.02,Default,,0,0,0,,指令序列\nDialogue: 0,0:39:31.48,0:39:41.85,Default,,0,0,0,,首先是(ASSIGN CONTINUE DONE)\nDialogue: 0,0:39:45.15,0:39:45.82,Default,,0,0,0,,然后是一个循环\nDialogue: 0,0:39:47.34,0:39:56.08,Default,,0,0,0,,先判断 如果1=N 那么就跳转\nDialogue: 0,0:40:00.94,0:40:04.11,Default,,0,0,0,,那么就进入归纳的基本步骤\nDialogue: 0,0:40:06.06,0:40:07.20,Default,,0,0,0,,也就是最简单的情况\nDialogue: 0,0:40:08.05,0:40:08.76,Default,,0,0,0,,否则的话\nDialogue: 0,0:40:08.88,0:40:10.84,Default,,0,0,0,,我就要记住那些\nDialogue: 0,0:40:10.88,0:40:13.84,Default,,0,0,0,,计算子阶乘所必须的信息\nDialogue: 0,0:40:14.67,0:40:16.75,Default,,0,0,0,,我需要来带这里 以便计算子阶乘\nDialogue: 0,0:40:17.57,0:40:19.29,Default,,0,0,0,,所以我需要记住 完成它需要些什么\nDialogue: 0,0:40:19.71,0:40:22.52,Default,,0,0,0,,需要记住我计算完之后需要哪些东西\nDialogue: 0,0:40:24.00,0:40:25.51,Default,,0,0,0,,看到了吗 我要做些糟糕的事儿\nDialogue: 0,0:40:25.72,0:40:27.39,Default,,0,0,0,,我要去修改N的值\nDialogue: 0,0:40:28.57,0:40:30.40,Default,,0,0,0,,但是它又需要记住N的旧值\nDialogue: 0,0:40:32.14,0:40:33.64,Default,,0,0,0,,但是为了计算子阶乘\nDialogue: 0,0:40:33.66,0:40:34.92,Default,,0,0,0,,我又需要修改N的值\nDialogue: 0,0:40:35.60,0:40:37.10,Default,,0,0,0,,因此 我就得记住N的旧值\nDialogue: 0,0:40:38.00,0:40:39.60,Default,,0,0,0,,我也需要记住我的位置\nDialogue: 0,0:40:40.85,0:40:42.32,Default,,0,0,0,,因此 我保存CONTINUE的值\nDialogue: 0,0:40:47.70,0:40:51.29,Default,,0,0,0,,这条指令 就是用来将数据入栈的\nDialogue: 0,0:40:53.12,0:40:55.53,Default,,0,0,0,,将CONTINUE寄存器的值保存起来\nDialogue: 0,0:40:56.51,0:40:58.00,Default,,0,0,0,,在本例中也就是DONE\nDialogue: 0,0:40:58.88,0:41:00.25,Default,,0,0,0,,因为稍后我也会修改它\nDialogue: 0,0:41:00.27,0:41:02.78,Default,,0,0,0,,因为我也需要回到AFTER-FACT\nDialogue: 0,0:41:03.55,0:41:04.19,Default,,0,0,0,,我们来看看\nDialogue: 0,0:41:05.04,0:41:09.71,Default,,0,0,0,,我们需要存储N 因为稍后会用到\nDialogue: 0,0:41:10.38,0:41:20.54,Default,,0,0,0,,(ASSIGN N (-1+ (FETCH N)))\nDialogue: 0,0:41:23.26,0:41:28.97,Default,,0,0,0,,(ASSIGN CONTINUE ...\nDialogue: 0,0:41:32.12,0:41:33.42,Default,,0,0,0,,我看一下 --\nDialogue: 0,0:41:34.06,0:41:35.61,Default,,0,0,0,,AFT)\nDialogue: 0,0:41:37.69,0:41:38.70,Default,,0,0,0,,这个名字很好\nDialogue: 0,0:41:38.73,0:41:40.65,Default,,0,0,0,,因为它短小精炼 很适合用在这里\nDialogue: 0,0:41:53.36,0:41:54.64,Default,,0,0,0,,现在 来看看我怎么做\nDialogue: 0,0:41:55.33,0:41:57.02,Default,,0,0,0,,我说 如果ANSWER是1的话\nDialogue: 0,0:41:58.72,0:41:59.66,Default,,0,0,0,,那程序就结束了\nDialogue: 0,0:42:00.46,0:42:01.66,Default,,0,0,0,,我只需要取得这个答案\nDialogue: 0,0:42:02.15,0:42:04.88,Default,,0,0,0,,否则我就要保存当前的继续以及N的值\nDialogue: 0,0:42:05.77,0:42:07.32,Default,,0,0,0,,然后让N减1\nDialogue: 0,0:42:07.60,0:42:09.63,Default,,0,0,0,,注意 我先要跳转到某处\nDialogue: 0,0:42:09.64,0:42:11.48,Default,,0,0,0,,然后来到这里 计算另外的阶乘\nDialogue: 0,0:42:13.50,0:42:15.74,Default,,0,0,0,,然而 这之中又有了另外的机器\nDialogue: 0,0:42:16.05,0:42:18.38,Default,,0,0,0,,其中N=1 CONTINUE是其它值\nDialogue: 0,0:42:22.11,0:42:23.21,Default,,0,0,0,,N=N-1\nDialogue: 0,0:42:23.77,0:42:25.28,Default,,0,0,0,,再我完成这个之后\nDialogue: 0,0:42:26.94,0:42:27.76,Default,,0,0,0,,我会来到这里\nDialogue: 0,0:42:28.66,0:42:30.46,Default,,0,0,0,,我会恢复N的旧值\nDialogue: 0,0:42:32.68,0:42:36.56,Default,,0,0,0,,也就是这里SAVE的逆运算\nDialogue: 0,0:42:38.36,0:42:39.88,Default,,0,0,0,,然后恢复CONTINUE\nDialogue: 0,0:42:49.66,0:42:52.57,Default,,0,0,0,,然后我又会来到这里\nDialogue: 0,0:42:54.32,0:43:00.86,Default,,0,0,0,,(ASSIGN VAL\nDialogue: 0,0:43:01.16,0:43:08.13,Default,,0,0,0,,(* (FETCH N) (FETCH VAL)))\nDialogue: 0,0:43:13.44,0:43:18.30,Default,,0,0,0,,（闭合括号中）\nDialogue: 0,0:43:19.79,0:43:21.44,Default,,0,0,0,,这样操作就完成了\nDialogue: 0,0:43:21.44,0:43:25.68,Default,,0,0,0,,子阶乘的结果就存储在了VAL中\nDialogue: 0,0:43:26.57,0:43:27.37,Default,,0,0,0,,这个时候\nDialogue: 0,0:43:27.66,0:43:28.75,Default,,0,0,0,,我就要返回到\nDialogue: 0,0:43:29.28,0:43:31.61,Default,,0,0,0,,CONTINUE所指向的地方\nDialogue: 0,0:43:33.64,0:43:35.77,Default,,0,0,0,,也就是(GOTO (FETCH CONTINUE))\nDialogue: 0,0:43:45.87,0:43:47.40,Default,,0,0,0,,最后就是基本情况的那步\nDialogue: 0,0:43:49.31,0:43:50.51,Default,,0,0,0,,也就是一个立即值\nDialogue: 0,0:43:50.68,0:43:56.88,Default,,0,0,0,,(ASSIGN VAL (FETCH N))\nDialogue: 0,0:44:01.36,0:44:02.75,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,0:44:12.67,0:44:13.55,Default,,0,0,0,,这样我就完成了\nDialogue: 0,0:44:18.64,0:44:21.21,Default,,0,0,0,,现在 我们用一个非常简单的例子来运行一下\nDialogue: 0,0:44:22.51,0:44:23.53,Default,,0,0,0,,因为这样我们就将看到\nDialogue: 0,0:44:23.66,0:44:26.52,Default,,0,0,0,,栈是如何帮助我们完成计算的\nDialogue: 0,0:44:26.89,0:44:28.22,Default,,0,0,0,,这是计算的静态描述\nDialogue: 0,0:44:28.22,0:44:29.80,Default,,0,0,0,,我们需要动态地观察它\nDialogue: 0,0:44:31.34,0:44:32.09,Default,,0,0,0,,因此 让我们来看看\nDialogue: 0,0:44:32.30,0:44:34.56,Default,,0,0,0,,首先我们要把CONTINUE设置为DONE\nDialogue: 0,0:44:36.73,0:44:38.09,Default,,0,0,0,,这是我通过按下这个钮来实现的\nDialogue: 0,0:44:38.30,0:44:39.60,Default,,0,0,0,,我们还是把它记作DONE吧\nDialogue: 0,0:44:46.22,0:44:47.03,Default,,0,0,0,,我按下这个按钮\nDialogue: 0,0:44:47.03,0:44:48.11,Default,,0,0,0,,DONE就进到了这里\nDialogue: 0,0:44:48.95,0:44:53.71,Default,,0,0,0,,现在 我还要为这些东西设置初始值\nDialogue: 0,0:44:53.85,0:44:58.08,Default,,0,0,0,,让我们考虑3的阶乘\nDialogue: 0,0:44:58.38,0:44:59.24,Default,,0,0,0,,这个例子非常简单\nDialogue: 0,0:45:00.54,0:45:04.04,Default,,0,0,0,,我们的栈从这里开始增长\nDialogue: 0,0:45:05.90,0:45:07.76,Default,,0,0,0,,栈有它们自己的内部状态\nDialogue: 0,0:45:07.79,0:45:09.05,Default,,0,0,0,,用来标识栈顶位置\nDialogue: 0,0:45:09.80,0:45:11.64,Default,,0,0,0,,也就是下一个可写位置\nDialogue: 0,0:45:12.77,0:45:14.59,Default,,0,0,0,,现在我们问 N=1么？\nDialogue: 0,0:45:14.76,0:45:15.71,Default,,0,0,0,,当然不等于\nDialogue: 0,0:45:16.11,0:45:18.56,Default,,0,0,0,,因此现在我要保存CONTINUE\nDialogue: 0,0:45:19.15,0:45:20.65,Default,,0,0,0,,现在 DONE就来到了这里\nDialogue: 0,0:45:22.08,0:45:23.55,Default,,0,0,0,,然后 这个指针移动到了这里\nDialogue: 0,0:45:24.88,0:45:26.14,Default,,0,0,0,,下次我要把数据写到这里\nDialogue: 0,0:45:26.66,0:45:28.78,Default,,0,0,0,,保存N的值--也就是3\nDialogue: 0,0:45:29.95,0:45:30.32,Default,,0,0,0,,对吧？\nDialogue: 0,0:45:30.67,0:45:33.61,Default,,0,0,0,,N←N-1\nDialogue: 0,0:45:33.96,0:45:35.37,Default,,0,0,0,,也就是说 我得按下这个钮\nDialogue: 0,0:45:35.94,0:45:37.32,Default,,0,0,0,,这就变成了2\nDialogue: 0,0:45:38.73,0:45:42.28,Default,,0,0,0,,COUNTINUE←AFT\nDialogue: 0,0:45:42.58,0:45:43.61,Default,,0,0,0,,因此我要按下这个钮\nDialogue: 0,0:45:43.61,0:45:44.54,Default,,0,0,0,,AFT就进入了这里\nDialogue: 0,0:45:49.14,0:45:53.93,Default,,0,0,0,,然后 跳转到LOOP 我们就来到了这里\nDialogue: 0,0:45:54.83,0:45:57.08,Default,,0,0,0,,N=1么？当然不\nDialogue: 0,0:45:57.78,0:45:59.23,Default,,0,0,0,,因此我又要保存CONTINUE\nDialogue: 0,0:45:59.49,0:46:00.27,Default,,0,0,0,,CONTINUE的值是什么呢？\nDialogue: 0,0:46:00.60,0:46:01.53,Default,,0,0,0,,目前是AFT\nDialogue: 0,0:46:01.53,0:46:02.32,Default,,0,0,0,,按下这个按钮\nDialogue: 0,0:46:02.78,0:46:03.95,Default,,0,0,0,,这个指针移动到了这里\nDialogue: 0,0:46:08.49,0:46:09.74,Default,,0,0,0,,我还要保存N\nDialogue: 0,0:46:10.51,0:46:12.12,Default,,0,0,0,,N在那里 它的值是2\nDialogue: 0,0:46:12.28,0:46:13.37,Default,,0,0,0,,按下这个按钮\nDialogue: 0,0:46:13.85,0:46:15.24,Default,,0,0,0,,2就进入了这里\nDialogue: 0,0:46:16.05,0:46:17.64,Default,,0,0,0,,然后这个指针移动到了这里\nDialogue: 0,0:46:20.06,0:46:22.60,Default,,0,0,0,,保存N之后 又赋N←N-1\nDialogue: 0,0:46:24.60,0:46:25.46,Default,,0,0,0,,它就变成了1\nDialogue: 0,0:46:29.24,0:46:30.54,Default,,0,0,0,,CONTINUE←AFT\nDialogue: 0,0:46:31.37,0:46:34.48,Default,,0,0,0,,AFT又进入了这里\nDialogue: 0,0:46:34.96,0:46:35.64,Default,,0,0,0,,然后又跳转到LOOP\nDialogue: 0,0:46:36.52,0:46:37.74,Default,,0,0,0,,N等于1么？\nDialogue: 0,0:46:37.93,0:46:39.52,Default,,0,0,0,,是的 那么答案就是1\nDialogue: 0,0:46:41.04,0:46:43.26,Default,,0,0,0,,跳转到BASE那一步\nDialogue: 0,0:46:44.16,0:46:45.77,Default,,0,0,0,,(ASSIGN VAL (FETCH N))\nDialogue: 0,0:46:46.56,0:46:50.72,Default,,0,0,0,,按下这个 1就进入到了这里\nDialogue: 0,0:46:51.10,0:46:52.20,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,0:46:52.20,0:46:53.53,Default,,0,0,0,,来看下CONTINUE寄存器\nDialogue: 0,0:46:53.68,0:46:56.06,Default,,0,0,0,,基本上来说 我按下这里的按钮 进入到控制器\nDialogue: 0,0:46:56.67,0:46:58.28,Default,,0,0,0,,CONTINUE寄存器就变成了AFT\nDialogue: 0,0:46:58.32,0:47:00.25,Default,,0,0,0,,这样一下子 程序就运行到了这里\nDialogue: 0,0:47:02.64,0:47:05.63,Default,,0,0,0,,现在 我就需要恢复外部的阶乘了\nDialogue: 0,0:47:06.65,0:47:07.55,Default,,0,0,0,,因此我们来到这里\nDialogue: 0,0:47:07.55,0:47:09.48,Default,,0,0,0,,我们先要恢复N\nDialogue: 0,0:47:10.32,0:47:13.04,Default,,0,0,0,,这就意味着 我们要使用这里的内容\nDialogue: 0,0:47:13.94,0:47:18.17,Default,,0,0,0,,按下这个按钮 2就会来到这里\nDialogue: 0,0:47:18.56,0:47:20.04,Default,,0,0,0,,然后指针会向上移动\nDialogue: 0,0:47:21.98,0:47:24.49,Default,,0,0,0,,恢复CONTINUE寄存器也非常简单\nDialogue: 0,0:47:24.81,0:47:26.49,Default,,0,0,0,,来按下这个按钮\nDialogue: 0,0:47:27.02,0:47:28.92,Default,,0,0,0,,然后 AFT又一次进入到这里\nDialogue: 0,0:47:31.28,0:47:32.64,Default,,0,0,0,,同时 这个指针也要上移\nDialogue: 0,0:47:32.64,0:47:35.19,Default,,0,0,0,,这样就避开了栈上的其它东西\nDialogue: 0,0:47:42.24,0:47:43.47,Default,,0,0,0,,然后我来到这里\nDialogue: 0,0:47:43.87,0:47:47.15,Default,,0,0,0,,也就是(ASSIGN VAL (* N VAL))\nDialogue: 0,0:47:47.85,0:47:50.57,Default,,0,0,0,,然后我按下这个按钮\nDialogue: 0,0:47:50.97,0:47:52.91,Default,,0,0,0,,2乘以1等于2\nDialogue: 0,0:47:54.01,0:47:54.75,Default,,0,0,0,,我写到这里\nDialogue: 0,0:47:55.76,0:47:57.20,Default,,0,0,0,,然后是(GOTO (FETCH CONTINUE))\nDialogue: 0,0:47:57.54,0:47:59.85,Default,,0,0,0,,CONTINUE现在是AFT 我跳转到AFT\nDialogue: 0,0:48:01.15,0:48:03.88,Default,,0,0,0,,AFT首先要恢复N\nDialogue: 0,0:48:04.36,0:48:05.72,Default,,0,0,0,,恢复N指的是\nDialogue: 0,0:48:05.87,0:48:08.44,Default,,0,0,0,,我把这里的值 也就是3\nDialogue: 0,0:48:09.24,0:48:10.33,Default,,0,0,0,,按下这里的按钮\nDialogue: 0,0:48:10.60,0:48:15.50,Default,,0,0,0,,然后把它放到这里 N\nDialogue: 0,0:48:16.25,0:48:17.34,Default,,0,0,0,,然后 我们按下这个钮\nDialogue: 0,0:48:18.01,0:48:19.90,Default,,0,0,0,,接下来我就要恢复CONTINUE\nDialogue: 0,0:48:20.20,0:48:22.20,Default,,0,0,0,,CONTINUE寄存器现在成为了DONE\nDialogue: 0,0:48:22.83,0:48:26.78,Default,,0,0,0,,当我按下这个钮后 指针就移动到了这里\nDialogue: 0,0:48:27.13,0:48:29.72,Default,,0,0,0,,DONE可能从此之后不在这里了\nDialogue: 0,0:48:29.72,0:48:31.55,Default,,0,0,0,,对此我并不感兴趣 但它现在一定在这里\nDialogue: 0,0:48:35.80,0:48:38.12,Default,,0,0,0,,下一步 我将要把VAL赋值为\nDialogue: 0,0:48:38.43,0:48:40.76,Default,,0,0,0,,N乘以VAL的值\nDialogue: 0,0:48:41.44,0:48:44.30,Default,,0,0,0,,按下这里的按钮就可以实现\nDialogue: 0,0:48:44.30,0:48:45.77,Default,,0,0,0,,2乘以3等于6\nDialogue: 0,0:48:46.52,0:48:47.87,Default,,0,0,0,,所以这里我就得到了6\nDialogue: 0,0:48:50.97,0:48:53.40,Default,,0,0,0,,下一步是(GOTO (FETCH CONTINUE))\nDialogue: 0,0:48:53.48,0:48:54.83,Default,,0,0,0,,哦 跳转到DONE 这样我就完成了\nDialogue: 0,0:48:55.02,0:48:56.09,Default,,0,0,0,,最后的答案是6\nDialogue: 0,0:48:56.60,0:48:57.82,Default,,0,0,0,,你们可以在VAL寄存器中看到\nDialogue: 0,0:48:58.95,0:48:59.82,Default,,0,0,0,,事实上\nDialogue: 0,0:49:00.91,0:49:03.34,Default,,0,0,0,,栈又回到了它初始的状态\nDialogue: 0,0:49:08.20,0:49:10.70,Default,,0,0,0,,在使用像栈这样的东西中 有一些原则\nDialogue: 0,0:49:11.20,0:49:12.27,Default,,0,0,0,,我们需要注意\nDialogue: 0,0:49:13.62,0:49:15.52,Default,,0,0,0,,我们会在下一小节中介绍\nDialogue: 0,0:49:16.26,0:49:18.46,Default,,0,0,0,,但首先 对于这一小节所讲的内容\nDialogue: 0,0:49:28.56,0:49:29.64,Default,,0,0,0,,有什么问题么？\nDialogue: 0,0:49:30.17,0:49:30.63,Default,,0,0,0,,Ron 请讲\nDialogue: 0,0:49:30.63,0:49:33.37,Default,,0,0,0,,学生：当你越过了栈的顶端会怎样--\nDialogue: 0,0:49:33.39,0:49:34.62,Default,,0,0,0,,教授：你所谓的“越过”是指什么？\nDialogue: 0,0:49:35.03,0:49:37.50,Default,,0,0,0,,学生：如果我们的N是一个很大的数\nDialogue: 0,0:49:37.52,0:49:38.72,Default,,0,0,0,,就需要更多的内存 对吧？\nDialogue: 0,0:49:38.86,0:49:39.44,Default,,0,0,0,,教授：是的\nDialogue: 0,0:49:39.44,0:49:41.12,Default,,0,0,0,,这样 我就需要一个足够大的栈\nDialogue: 0,0:49:41.53,0:49:43.20,Default,,0,0,0,,你想问 如果破坏了无穷存储的假象会发生什么？\nDialogue: 0,0:49:43.84,0:49:44.12,Default,,0,0,0,,学生：是的\nDialogue: 0,0:49:44.55,0:49:46.73,Default,,0,0,0,,教授：那么 这些魔法就不再起效了\nDialogue: 0,0:49:47.96,0:49:51.00,Default,,0,0,0,,真相就是 任何机器都是有穷的\nDialogue: 0,0:49:51.64,0:49:53.72,Default,,0,0,0,,而对于像这样的过程\nDialogue: 0,0:49:54.17,0:49:58.86,Default,,0,0,0,,我只能进行有限数量的子阶乘计算\nDialogue: 0,0:49:59.95,0:50:02.48,Default,,0,0,0,,想一想 我们之前讲解的Y组合子\nDialogue: 0,0:50:02.80,0:50:06.22,Default,,0,0,0,,我们指出 存在一系列的指数过程\nDialogue: 0,0:50:06.25,0:50:08.09,Default,,0,0,0,,其中每一个都要比前一个更精准\nDialogue: 0,0:50:08.72,0:50:11.60,Default,,0,0,0,,现在 我们看到了如何实现这个数学理念\nDialogue: 0,0:50:13.09,0:50:14.19,Default,,0,0,0,,这个取极限的过程\nDialogue: 0,0:50:14.35,0:50:16.33,Default,,0,0,0,,只有当你取到极限时才足够精准\nDialogue: 0,0:50:17.99,0:50:19.42,Default,,0,0,0,,如果你仔细想想 我这里用了什么\nDialogue: 0,0:50:19.42,0:50:22.65,Default,,0,0,0,,对于这个过程的每一次递归\nDialogue: 0,0:50:23.04,0:50:27.07,Default,,0,0,0,,我用了大概两块内存\nDialogue: 0,0:50:29.10,0:50:31.71,Default,,0,0,0,,如果我们尝试计算10000的阶乘\nDialogue: 0,0:50:31.72,0:50:32.81,Default,,0,0,0,,这并不会花掉很多内存\nDialogue: 0,0:50:33.18,0:50:34.68,Default,,0,0,0,,虽然这是一个很大的数\nDialogue: 0,0:50:35.95,0:50:38.41,Default,,0,0,0,,因此 实际的问题就是值不值得\nDialogue: 0,0:50:39.18,0:50:42.19,Default,,0,0,0,,但这并不是这种实现的局限\nDialogue: 0,0:50:42.22,0:50:43.53,Default,,0,0,0,,因为内存非常低廉\nDialogue: 0,0:50:44.16,0:50:45.34,Default,,0,0,0,,但人力资源却相当昂贵\nDialogue: 0,0:50:48.13,0:50:50.22,Default,,0,0,0,,好吧 我们先休息一下 谢谢大家\nDialogue: 0,0:50:50.78,0:51:07.60,Default,,0,0,0,,[音乐]\nDialogue: 0,0:51:07.60,0:51:12.19,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:51:39.93,0:51:43.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:51:43.71,0:51:47.93,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:51:47.93,0:51:53.08,Declare,,0,0,0,,{\\an2\\fad(500,500)}寄存机器\nDialogue: 0,0:51:56.11,0:51:57.04,Default,,0,0,0,,教授：我们讲解了\nDialogue: 0,0:51:58.70,0:52:03.37,Default,,0,0,0,,如果进行简单的迭代计算\nDialogue: 0,0:52:03.69,0:52:05.31,Default,,0,0,0,,以及简单的递归计算\nDialogue: 0,0:52:05.64,0:52:08.68,Default,,0,0,0,,我只想通过向你们展示一些针对特定应用的\nDialogue: 0,0:52:09.63,0:52:11.12,Default,,0,0,0,,更加复杂的设计\nDialogue: 0,0:52:11.21,0:52:13.58,Default,,0,0,0,,来总结简单机器的设计\nDialogue: 0,0:52:13.96,0:52:17.13,Default,,0,0,0,,也就是同时递归地调用两个斐波那契函数\nDialogue: 0,0:52:17.23,0:52:19.88,Default,,0,0,0,,因为它会向我们表明 并且我们会理解\nDialogue: 0,0:52:20.04,0:52:22.68,Default,,0,0,0,,一些关于栈正常工作\nDialogue: 0,0:52:22.76,0:52:25.04,Default,,0,0,0,,所需要遵守的约定\nDialogue: 0,0:52:26.40,0:52:27.11,Default,,0,0,0,,现在 让我们来看看\nDialogue: 0,0:52:27.11,0:52:28.27,Default,,0,0,0,,先让我在黑板上写下\nDialogue: 0,0:52:28.30,0:52:29.71,Default,,0,0,0,,将要翻译的程序\nDialogue: 0,0:52:34.15,0:52:36.52,Default,,0,0,0,,这是一个斐波那契过程\nDialogue: 0,0:52:39.23,0:52:41.58,Default,,0,0,0,,它非常的简单\nDialogue: 0,0:52:44.60,0:52:48.56,Default,,0,0,0,,如果N小于2 那么结果就是N\nDialogue: 0,0:52:49.26,0:52:55.34,Default,,0,0,0,,否则就是(FIB (- N 1))加上\nDialogue: 0,0:52:58.44,0:52:59.85,Default,,0,0,0,,(FIB (- N 2))\nDialogue: 0,0:53:07.05,0:53:09.29,Default,,0,0,0,,这就是我的计划\nDialogue: 0,0:53:09.29,0:53:12.56,Default,,0,0,0,,现在 我们要来写下这台机器的控制器\nDialogue: 0,0:53:13.07,0:53:15.53,Default,,0,0,0,,首先 我们假设有一个寄存器N\nDialogue: 0,0:53:15.56,0:53:19.15,Default,,0,0,0,,里面存放的是斐波那契函数的自变量\nDialogue: 0,0:53:19.82,0:53:21.80,Default,,0,0,0,,而计算结果会存放在VAL寄存器中\nDialogue: 0,0:53:22.17,0:53:24.97,Default,,0,0,0,,CONTINUE寄存器会和控制器相连\nDialogue: 0,0:53:26.11,0:53:26.81,Default,,0,0,0,,就跟之前一样\nDialogue: 0,0:53:26.96,0:53:29.21,Default,,0,0,0,,但我不会再去画数据通路了\nDialogue: 0,0:53:31.53,0:53:34.00,Default,,0,0,0,,因为它和之前的那个差不多\nDialogue: 0,0:53:34.36,0:53:37.84,Default,,0,0,0,,当然 关于计算的最神奇的事情之一\nDialogue: 0,0:53:38.75,0:53:39.88,Default,,0,0,0,,就是一段时间后\nDialogue: 0,0:53:40.08,0:53:41.93,Default,,0,0,0,,你构建了一个又一个的小功能\nDialogue: 0,0:53:41.95,0:53:43.32,Default,,0,0,0,,你就一下子拥有了需要的一切\nDialogue: 0,0:53:44.75,0:53:47.60,Default,,0,0,0,,这种效率是非常了不起的\nDialogue: 0,0:53:48.17,0:53:50.84,Default,,0,0,0,,构造制作一台通用计算机不需要太多的东西\nDialogue: 0,0:53:51.81,0:53:54.68,Default,,0,0,0,,总之 我们来看看斐波那契机器的控制器\nDialogue: 0,0:53:55.06,0:53:57.07,Default,,0,0,0,,我首先要做的是\nDialogue: 0,0:53:57.32,0:54:02.52,Default,,0,0,0,,通过为CONTINUE寄存器赋值\nDialogue: 0,0:54:07.13,0:54:10.28,Default,,0,0,0,,赋FIB-DONE来启动计算\nDialogue: 0,0:54:14.14,0:54:15.53,Default,,0,0,0,,这就意味着在这里\nDialogue: 0,0:54:15.55,0:54:18.48,Default,,0,0,0,,我需要有一个标签 FIB-DONE\nDialogue: 0,0:54:19.71,0:54:21.10,Default,,0,0,0,,当我来到这个地方后\nDialogue: 0,0:54:21.23,0:54:22.44,Default,,0,0,0,,机器就停止了\nDialogue: 0,0:54:24.00,0:54:24.86,Default,,0,0,0,,这就是这个标签的作用\nDialogue: 0,0:54:25.92,0:54:26.89,Default,,0,0,0,,然后我要创建一个循环\nDialogue: 0,0:54:31.11,0:54:34.25,Default,,0,0,0,,我要来到这里来启动FIB的计算\nDialogue: 0,0:54:35.47,0:54:36.86,Default,,0,0,0,,无论这时 N等于多少\nDialogue: 0,0:54:37.39,0:54:38.99,Default,,0,0,0,,斐波那契函数都会被计算\nDialogue: 0,0:54:39.13,0:54:42.01,Default,,0,0,0,,然后会返回到由CONTINUE寄存器指向的地方\nDialogue: 0,0:54:44.80,0:54:48.40,Default,,0,0,0,,因此你们将在这里看到\nDialogue: 0,0:54:48.44,0:54:50.48,Default,,0,0,0,,我想要在做一个约定\nDialogue: 0,0:54:50.97,0:54:54.25,Default,,0,0,0,,我用注释的形式来说明这个约定\nDialogue: 0,0:54:54.57,0:55:00.99,Default,,0,0,0,,也就是N中存储的是参数\nDialogue: 0,0:55:02.10,0:55:09.82,Default,,0,0,0,,而CONTINUE存储的是接收者\nDialogue: 0,0:55:13.36,0:55:14.29,Default,,0,0,0,,这个约定就是这样的\nDialogue: 0,0:55:15.71,0:55:18.96,Default,,0,0,0,,因此每当我来到这里\nDialogue: 0,0:55:19.24,0:55:21.04,Default,,0,0,0,,我希望这个约定是成立的\nDialogue: 0,0:55:21.52,0:55:23.32,Default,,0,0,0,,这些计算斐波那契函数所需要的参数\nDialogue: 0,0:55:24.82,0:55:26.83,Default,,0,0,0,,接下来我想做的是分支\nDialogue: 0,0:55:30.22,0:55:32.22,Default,,0,0,0,,如果N小于2\nDialogue: 0,0:55:35.07,0:55:37.44,Default,,0,0,0,,随便说一下 我使用的语法看起来像Lisp\nDialogue: 0,0:55:38.73,0:55:39.63,Default,,0,0,0,,但它并不是Lisp\nDialogue: 0,0:55:41.31,0:55:42.38,Default,,0,0,0,,它们运行不起来\nDialogue: 0,0:55:42.75,0:55:45.47,Default,,0,0,0,,我在这里写的并不是一个简单的Lisp程序\nDialogue: 0,0:55:46.12,0:55:49.31,Default,,0,0,0,,这是另一门语言的表示形式\nDialogue: 0,0:55:49.71,0:55:52.25,Default,,0,0,0,,我之所以使用这种满是括号的语法\nDialogue: 0,0:55:52.40,0:55:54.70,Default,,0,0,0,,是因为我刚好使用Lisp系统\nDialogue: 0,0:55:55.32,0:55:57.34,Default,,0,0,0,,来为这门语言编写解释器\nDialogue: 0,0:55:57.82,0:55:59.18,Default,,0,0,0,,这就使得我们能够模拟\nDialogue: 0,0:55:59.29,0:56:00.91,Default,,0,0,0,,我想要构建的机器\nDialogue: 0,0:56:03.38,0:56:06.24,Default,,0,0,0,,我不想让你们感到困惑 认为这是Lisp代码\nDialogue: 0,0:56:06.94,0:56:08.60,Default,,0,0,0,,只是我用了很多Lisp组件\nDialogue: 0,0:56:09.51,0:56:10.84,Default,,0,0,0,,我在Lisp中嵌入了一门语言\nDialogue: 0,0:56:11.02,0:56:12.44,Default,,0,0,0,,把Lisp当作组件\nDialogue: 0,0:56:12.72,0:56:15.12,Default,,0,0,0,,这样就能让我的模拟工作变得简单\nDialogue: 0,0:56:16.62,0:56:18.56,Default,,0,0,0,,我从Lisp中继承了这些属性\nDialogue: 0,0:56:19.10,0:56:21.53,Default,,0,0,0,,(FETCH N) 2)\nDialogue: 0,0:56:21.77,0:56:23.72,Default,,0,0,0,,成立的话 我想要跳转到IMMEDIATE-ANSWER这个地方\nDialogue: 0,0:56:26.20,0:56:27.29,Default,,0,0,0,,这是基本步骤\nDialogue: 0,0:56:33.15,0:56:34.35,Default,,0,0,0,,它对应在这里\nDialogue: 0,0:56:35.92,0:56:36.89,Default,,0,0,0,,也就是在FIB-DONE的上方\nDialogue: 0,0:56:37.75,0:56:38.64,Default,,0,0,0,,我们稍后就会看到\nDialogue: 0,0:56:39.42,0:56:40.70,Default,,0,0,0,,现在 对于一般情况来说\nDialogue: 0,0:56:40.72,0:56:42.44,Default,,0,0,0,,也就是我现在要写的\nDialogue: 0,0:56:43.13,0:56:44.19,Default,,0,0,0,,是这样的\nDialogue: 0,0:56:44.91,0:56:48.20,Default,,0,0,0,,首先呢 我需要调用斐波那契函数两次\nDialogue: 0,0:56:49.42,0:56:52.54,Default,,0,0,0,,在每一次中 -- 至少在其中一次\nDialogue: 0,0:56:52.78,0:56:53.95,Default,,0,0,0,,我得需要知道该怎么做\nDialogue: 0,0:56:53.96,0:56:55.36,Default,,0,0,0,,才能回过头来进行另外一个计算\nDialogue: 0,0:56:56.31,0:56:58.36,Default,,0,0,0,,我需要记住\nDialogue: 0,0:56:59.20,0:57:01.23,Default,,0,0,0,,我计算完第一个FIB了么？\nDialogue: 0,0:57:01.26,0:57:02.54,Default,,0,0,0,,或者第二个也计算完了？\nDialogue: 0,0:57:04.50,0:57:07.04,Default,,0,0,0,,我是该返回到计算第二个FIB的地方\nDialogue: 0,0:57:07.07,0:57:09.08,Default,,0,0,0,,还是回到执行ADD的地方\nDialogue: 0,0:57:10.12,0:57:12.11,Default,,0,0,0,,无论哪种情况 我都需要--\nDialogue: 0,0:57:12.14,0:57:14.46,Default,,0,0,0,,在第一个计算第一个FIB时\nDialogue: 0,0:57:14.51,0:57:16.98,Default,,0,0,0,,我需要保存N的值 来计算第二个FIB\nDialogue: 0,0:57:19.84,0:57:21.58,Default,,0,0,0,,因此我要把这些东西保存起来\nDialogue: 0,0:57:23.36,0:57:24.89,Default,,0,0,0,,首先要保存CONTINUE\nDialogue: 0,0:57:26.19,0:57:27.32,Default,,0,0,0,,也就是答案的接收者\nDialogue: 0,0:57:31.32,0:57:32.46,Default,,0,0,0,,我之所以要这么做\nDialogue: 0,0:57:32.48,0:57:34.20,Default,,0,0,0,,是因为我现在要把CONTINUE赋值为\nDialogue: 0,0:57:40.11,0:57:44.32,Default,,0,0,0,,我待会儿想要返回的地方\nDialogue: 0,0:57:46.83,0:57:50.27,Default,,0,0,0,,我们把它叫做AFTER-FIB-N-1\nDialogue: 0,0:57:51.04,0:57:53.76,Default,,0,0,0,,这个长名字 非常具有Lisp的命名特点\nDialogue: 0,0:57:57.36,0:58:00.22,Default,,0,0,0,,这是因为我先要计算第一个(FIB (- N 1))\nDialogue: 0,0:58:00.84,0:58:01.72,Default,,0,0,0,,计算完成之后\nDialogue: 0,0:58:01.72,0:58:03.29,Default,,0,0,0,,我想要回过头来做些其它事\nDialogue: 0,0:58:03.96,0:58:06.52,Default,,0,0,0,,而AFTER-FIB-N-1这个地方\nDialogue: 0,0:58:07.55,0:58:09.48,Default,,0,0,0,,就是我计算完第一个FIB后应该返回的地方\nDialogue: 0,0:58:11.52,0:58:13.13,Default,,0,0,0,,接下来我要保存N\nDialogue: 0,0:58:14.41,0:58:17.26,Default,,0,0,0,,因为我稍后需要用到它\nDialogue: 0,0:58:19.13,0:58:20.54,Default,,0,0,0,,在这里 我就已经\nDialogue: 0,0:58:20.67,0:58:22.84,Default,,0,0,0,,准备好计算(FIB (- N 1))了\nDialogue: 0,0:58:23.02,0:58:33.95,Default,,0,0,0,,(ASSIGN N (- (FETCH N) 1))\nDialogue: 0,0:58:38.11,0:58:40.27,Default,,0,0,0,,现在 该跳转到FIB-LOOP了\nDialogue: 0,0:58:47.18,0:58:49.87,Default,,0,0,0,,我满足我立下的约定么？\nDialogue: 0,0:58:50.40,0:58:51.50,Default,,0,0,0,,答案是是的\nDialogue: 0,0:58:51.77,0:58:55.12,Default,,0,0,0,,N现在存储的是N-1 这是我需要的\nDialogue: 0,0:58:56.43,0:59:00.09,Default,,0,0,0,,而CONTINUE包含的是计算完成后 返回的目的地\nDialogue: 0,0:59:01.28,0:59:03.07,Default,,0,0,0,,也就是计算(FIB (- N 1))完成之后\nDialogue: 0,0:59:04.10,0:59:05.44,Default,,0,0,0,,因此我满足了这些约定\nDialogue: 0,0:59:05.44,0:59:09.02,Default,,0,0,0,,因此 我就可以在这里写下一个标签\nDialogue: 0,0:59:11.47,0:59:17.56,Default,,0,0,0,,AFTER-FIB-N-1\nDialogue: 0,0:59:20.49,0:59:21.63,Default,,0,0,0,,在这里 我又该做些什么呢？\nDialogue: 0,0:59:22.69,0:59:23.61,Default,,0,0,0,,在这里\nDialogue: 0,0:59:23.95,0:59:26.75,Default,,0,0,0,,我已经准备好去计算(FIB (- N 2))了\nDialogue: 0,0:59:29.27,0:59:30.72,Default,,0,0,0,,但是为了计算(FIB (- N 2))\nDialogue: 0,0:59:30.75,0:59:31.63,Default,,0,0,0,,首先 我不知道\nDialogue: 0,0:59:31.78,0:59:33.40,Default,,0,0,0,,这里 我已经改变了N\nDialogue: 0,0:59:33.81,0:59:35.47,Default,,0,0,0,,或者在这个时候 我的N总是不断地\nDialogue: 0,0:59:37.85,0:59:38.80,Default,,0,0,0,,向1或者0递减\nDialogue: 0,0:59:39.78,0:59:42.51,Default,,0,0,0,,所以我不知道N寄存器中存储的到底是什么\nDialogue: 0,0:59:43.03,0:59:44.75,Default,,0,0,0,,我想要保存在栈中的N的值\nDialogue: 0,0:59:44.80,0:59:46.00,Default,,0,0,0,,也就是我在这里保存的值\nDialogue: 0,0:59:46.17,0:59:47.88,Default,,0,0,0,,这样我就可以在这里恢复它\nDialogue: 0,0:59:49.52,0:59:51.02,Default,,0,0,0,,我在这里存储的N\nDialogue: 0,0:59:51.15,0:59:54.49,Default,,0,0,0,,是这个时间点N的值\nDialogue: 0,0:59:54.89,0:59:57.37,Default,,0,0,0,,因此计算完(FIB (- N 1))之后我可以恢复它\nDialogue: 0,0:59:57.53,0:59:59.36,Default,,0,0,0,,这样的话 我就可以计算(- N 2)\nDialogue: 0,0:59:59.39,1:00:00.86,Default,,0,0,0,,然后就可以计算(FIB (- N 2))的值\nDialogue: 0,1:00:01.81,1:00:02.75,Default,,0,0,0,,现在让我们来恢复它\nDialogue: 0,1:00:08.83,1:00:09.77,Default,,0,0,0,,(RESTORE N)\nDialogue: 0,1:00:11.13,1:00:15.98,Default,,0,0,0,,现在我要做一件很教条的事\nDialogue: 0,1:00:16.00,1:00:17.40,Default,,0,0,0,,我们会尽快将其删除\nDialogue: 0,1:00:18.52,1:00:20.48,Default,,0,0,0,,如果你们愿意的话\nDialogue: 0,1:00:20.59,1:00:23.44,Default,,0,0,0,,我将要结束子过程调用\nDialogue: 0,1:00:24.80,1:00:25.95,Default,,0,0,0,,接下来我会说\nDialogue: 0,1:00:26.06,1:00:27.90,Default,,0,0,0,,因为我保存了CONTINUE\nDialogue: 0,1:00:28.48,1:00:30.43,Default,,0,0,0,,现在就要去恢复它\nDialogue: 0,1:00:31.60,1:00:32.60,Default,,0,0,0,,但实际上 我并不需要这么做\nDialogue: 0,1:00:32.64,1:00:33.55,Default,,0,0,0,,因为我并不需要用到它\nDialogue: 0,1:00:34.61,1:00:35.72,Default,,0,0,0,,我们稍后会修正它\nDialogue: 0,1:00:36.26,1:00:37.95,Default,,0,0,0,,现在我们来恢复CONTINUE\nDialogue: 0,1:00:46.04,1:00:48.02,Default,,0,0,0,,通常来说 我都会这么做\nDialogue: 0,1:00:48.02,1:00:49.23,Default,,0,0,0,,我们将要看到\nDialogue: 0,1:00:49.31,1:00:52.14,Default,,0,0,0,,编译器领域中的“窥孔优化”\nDialogue: 0,1:00:52.27,1:00:53.72,Default,,0,0,0,,来帮我们消除这个不必要的步骤\nDialogue: 0,1:00:55.42,1:00:57.10,Default,,0,0,0,,因此 我即将要做的就是\nDialogue: 0,1:00:58.46,1:01:02.28,Default,,0,0,0,,准备好计算(FIB (- N 2))\nDialogue: 0,1:01:02.77,1:01:04.49,Default,,0,0,0,,但是我不再需要保存N了\nDialogue: 0,1:01:05.05,1:01:06.72,Default,,0,0,0,,原因就是\nDialogue: 0,1:01:06.80,1:01:09.34,Default,,0,0,0,,计算完(FIB (- N 2))之后 我就不需要N了\nDialogue: 0,1:01:09.36,1:01:10.72,Default,,0,0,0,,因为 我接下来要做的就是ADD\nDialogue: 0,1:01:13.54,1:01:15.85,Default,,0,0,0,,因此 我会这么来设置N\nDialogue: 0,1:01:16.60,1:01:28.99,Default,,0,0,0,,(ASSIGN N (- (FETCH N) 2))\nDialogue: 0,1:01:31.85,1:01:34.01,Default,,0,0,0,,现在我需要结束\nDialogue: 0,1:01:34.27,1:01:36.73,Default,,0,0,0,,调用(FIB (- N 2))的设置过程了\nDialogue: 0,1:01:36.95,1:01:38.33,Default,,0,0,0,,我需要保存CONTINUE\nDialogue: 0,1:01:44.22,1:01:49.02,Default,,0,0,0,,然后把CONTINUE赋值为\nDialogue: 0,1:01:52.30,1:01:59.95,Default,,0,0,0,,AFTER-FIB-N-2\nDialogue: 0,1:02:02.57,1:02:04.03,Default,,0,0,0,,对应了那边代码的某处\nDialogue: 0,1:02:05.32,1:02:07.23,Default,,0,0,0,,然而 我需要非常小心\nDialogue: 0,1:02:08.65,1:02:11.42,Default,,0,0,0,,而(FIB (- N 1))的值\nDialogue: 0,1:02:12.06,1:02:13.12,Default,,0,0,0,,我稍后会用到\nDialogue: 0,1:02:15.30,1:02:17.37,Default,,0,0,0,,(FIB (- N 1))的值\nDialogue: 0,1:02:17.61,1:02:18.48,Default,,0,0,0,,我需要它的值\nDialogue: 0,1:02:18.78,1:02:19.80,Default,,0,0,0,,我不能去改变它\nDialogue: 0,1:02:21.07,1:02:23.60,Default,,0,0,0,,因为我需要用它来加上(FIB (- N 2))\nDialogue: 0,1:02:24.15,1:02:25.88,Default,,0,0,0,,它是存放在寄存器中的 因此我需要保存它\nDialogue: 0,1:02:27.79,1:02:32.60,Default,,0,0,0,,所以现在我要用(SAVE VAL)来保存它\nDialogue: 0,1:02:33.78,1:02:35.44,Default,,0,0,0,,现在我就可以调用子过程了\nDialogue: 0,1:02:36.67,1:02:39.54,Default,,0,0,0,,(GOTO FIB-LOOP)\nDialogue: 0,1:02:44.22,1:02:46.57,Default,,0,0,0,,现在 在进行更进一步计算之前\nDialogue: 0,1:02:46.80,1:02:49.36,Default,,0,0,0,,在结束这个程序之前\nDialogue: 0,1:02:49.39,1:02:51.05,Default,,0,0,0,,我想审视一下目前的代码片段\nDialogue: 0,1:02:51.23,1:02:56.00,Default,,0,0,0,,这里有一系列的指令\nDialogue: 0,1:02:57.84,1:02:59.08,Default,,0,0,0,,我可以对它们进行某些操作\nDialogue: 0,1:03:01.58,1:03:03.20,Default,,0,0,0,,这里 我有一个操作用来恢复CONTINUE\nDialogue: 0,1:03:04.25,1:03:05.48,Default,,0,0,0,,一个操作用来保存CONTINUE\nDialogue: 0,1:03:06.01,1:03:07.40,Default,,0,0,0,,然后给CONTINUE赋值\nDialogue: 0,1:03:08.70,1:03:10.64,Default,,0,0,0,,但这之中没有CONTINUE的其它引用\nDialogue: 0,1:03:13.84,1:03:15.48,Default,,0,0,0,,恢复之后又保存\nDialogue: 0,1:03:15.50,1:03:16.67,Default,,0,0,0,,使得栈没有被修改\nDialogue: 0,1:03:19.09,1:03:21.72,Default,,0,0,0,,唯一的区别就是 我给CONTINUE寄存器赋了值\nDialogue: 0,1:03:21.96,1:03:23.28,Default,,0,0,0,,一个存放在栈上的值\nDialogue: 0,1:03:24.33,1:03:25.79,Default,,0,0,0,,由于我现在改变了这个值\nDialogue: 0,1:03:26.44,1:03:27.93,Default,,0,0,0,,但这之间并没有引用这个值\nDialogue: 0,1:03:28.59,1:03:30.09,Default,,0,0,0,,这些指令就是不必要的\nDialogue: 0,1:03:31.76,1:03:35.39,Default,,0,0,0,,因此我们会移除它们\nDialogue: 0,1:03:38.88,1:03:40.78,Default,,0,0,0,,但我只有先把它们写出来 才会发现这个情况\nDialogue: 0,1:03:43.78,1:03:44.72,Default,,0,0,0,,真是这样吗？\nDialogue: 0,1:03:45.77,1:03:46.60,Default,,0,0,0,,我并不知道\nDialogue: 0,1:03:48.61,1:03:52.91,Default,,0,0,0,,现在 我们要开始计算(FIB (- N 2))了\nDialogue: 0,1:03:53.66,1:03:54.59,Default,,0,0,0,,计算完毕后\nDialogue: 0,1:04:02.96,1:04:03.85,Default,,0,0,0,,我们又要做什么呢？\nDialogue: 0,1:04:05.07,1:04:06.76,Default,,0,0,0,,我想 我们首先要做的就是\nDialogue: 0,1:04:06.99,1:04:07.88,Default,,0,0,0,,我们有两件事要做\nDialogue: 0,1:04:07.96,1:04:10.49,Default,,0,0,0,,目前VAL寄存器中的值 是有意义的\nDialogue: 0,1:04:10.92,1:04:11.98,Default,,0,0,0,,然而 栈上也有一个数据\nDialogue: 0,1:04:12.04,1:04:13.63,Default,,0,0,0,,需要恢复到VAL寄存器中\nDialogue: 0,1:04:14.81,1:04:16.57,Default,,0,0,0,,现在我需要非常小心的是\nDialogue: 0,1:04:16.88,1:04:18.99,Default,,0,0,0,,正确地给它们排序 以便计算乘法\nDialogue: 0,1:04:19.47,1:04:21.24,Default,,0,0,0,,现在 我可能会使用不同的约定\nDialogue: 0,1:04:21.47,1:04:23.52,Default,,0,0,0,,但我现在会采用非常挑剔的一种\nDialogue: 0,1:04:23.55,1:04:25.88,Default,,0,0,0,,栈上数据来自于哪个寄存器 就恢复到那个寄存器中\nDialogue: 0,1:04:26.74,1:04:28.28,Default,,0,0,0,,如果是这样的话 在这里我就要进行洗牌\nDialogue: 0,1:04:29.24,1:04:31.84,Default,,0,0,0,,这跟我有多少只手是同样的问题\nDialogue: 0,1:04:32.68,1:04:37.13,Default,,0,0,0,,现在我要给N赋值\nDialogue: 0,1:04:37.16,1:04:39.37,Default,,0,0,0,,因为我现在不再需要N了 N是无用的\nDialogue: 0,1:04:39.92,1:04:41.21,Default,,0,0,0,,获取当前VAL寄存器的值\nDialogue: 0,1:04:45.21,1:04:47.34,Default,,0,0,0,,也就是(FIB (- N 2))的值\nDialogue: 0,1:04:52.95,1:04:56.35,Default,,0,0,0,,现在 我就要恢复VAL寄存器了\nDialogue: 0,1:05:01.85,1:05:03.92,Default,,0,0,0,,这个RESTORE匹配这里的SAVE\nDialogue: 0,1:05:05.58,1:05:08.83,Default,,0,0,0,,如果你非常仔细地研究发生了什么\nDialogue: 0,1:05:09.21,1:05:11.96,Default,,0,0,0,,会发现 RESTORE和SAVE总是成对的\nDialogue: 0,1:05:13.84,1:05:15.15,Default,,0,0,0,,现在 这里有个额外的SAVE\nDialogue: 0,1:05:15.18,1:05:16.38,Default,,0,0,0,,当然 我们很快就会消灭它\nDialogue: 0,1:05:19.00,1:05:20.59,Default,,0,0,0,,恢复完VAL寄存器后\nDialogue: 0,1:05:20.94,1:05:22.57,Default,,0,0,0,,我就要恢复CONTINUE寄存器了\nDialogue: 0,1:05:31.15,1:05:32.40,Default,,0,0,0,,它匹配了这个\nDialogue: 0,1:05:34.80,1:05:37.85,Default,,0,0,0,,从这里到这里\nDialogue: 0,1:05:40.59,1:05:42.46,Default,,0,0,0,,这样就恢复了继续\nDialogue: 0,1:05:42.86,1:05:45.71,Default,,0,0,0,,这个表达式继续是由(FIB N)产生的\nDialogue: 0,1:05:46.46,1:05:47.84,Default,,0,0,0,,也就是我正尝试求解的\nDialogue: 0,1:05:47.85,1:05:49.32,Default,,0,0,0,,最主要的问题\nDialogue: 0,1:05:49.98,1:05:52.35,Default,,0,0,0,,我需要把(FIB N)的答案返回给这个继续\nDialogue: 0,1:05:52.54,1:05:54.03,Default,,0,0,0,,在我意识到N并不小于2之前\nDialogue: 0,1:05:54.16,1:05:56.60,Default,,0,0,0,,我一直保存着它们\nDialogue: 0,1:05:57.36,1:05:59.07,Default,,0,0,0,,因此 我需要进行一个复杂的运算\nDialogue: 0,1:06:00.84,1:06:02.57,Default,,0,0,0,,现在万事俱备\nDialogue: 0,1:06:03.24,1:06:04.36,Default,,0,0,0,,因此我要恢复它们\nDialogue: 0,1:06:05.42,1:06:21.08,Default,,0,0,0,,(ASSIGN VAL (+ (FETCH VAL) (FETCH N)))\nDialogue: 0,1:06:27.44,1:06:28.60,Default,,0,0,0,,然后跳转到CONTINUE\nDialogue: 0,1:06:38.26,1:06:44.78,Default,,0,0,0,,然后我就从(FIB N)中返回了出来\nDialogue: 0,1:06:45.39,1:06:46.57,Default,,0,0,0,,也就是FIB的一般情况\nDialogue: 0,1:06:47.11,1:06:50.60,Default,,0,0,0,,现在还有一些细节 需要我们填充\nDialogue: 0,1:06:50.99,1:06:55.53,Default,,0,0,0,,比如归纳的基本情况：可以立即得到答案\nDialogue: 0,1:07:02.54,1:07:06.59,Default,,0,0,0,,这不过就是\nDialogue: 0,1:07:06.60,1:07:11.85,Default,,0,0,0,,(ASSIGN VAL (FETCH N)\nDialogue: 0,1:07:13.64,1:07:15.47,Default,,0,0,0,,因为N小于2\nDialogue: 0,1:07:15.50,1:07:16.89,Default,,0,0,0,,因此答案就是N\nDialogue: 0,1:07:16.99,1:07:18.19,Default,,0,0,0,,跟源程序是一致的\nDialogue: 0,1:07:19.23,1:07:26.48,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,1:07:31.24,1:07:36.13,Default,,0,0,0,,最后就结束了\nDialogue: 0,1:07:43.46,1:07:45.64,Default,,0,0,0,,这是个相当复杂的程序\nDialogue: 0,1:07:45.64,1:07:47.34,Default,,0,0,0,,我之所以给你们演示这个程序\nDialogue: 0,1:07:47.50,1:07:49.21,Default,,0,0,0,,是因为我想让你们见识\nDialogue: 0,1:07:49.45,1:07:52.67,Default,,0,0,0,,我所遵守的栈使用准则\nDialogue: 0,1:07:53.32,1:07:55.21,Default,,0,0,0,,第一点就是 我不想保存那些\nDialogue: 0,1:07:56.92,1:07:58.12,Default,,0,0,0,,稍后不需要的值\nDialogue: 0,1:08:00.57,1:08:01.85,Default,,0,0,0,,我非常地小心\nDialogue: 0,1:08:01.85,1:08:02.91,Default,,0,0,0,,这非常重要\nDialogue: 0,1:08:03.94,1:08:06.52,Default,,0,0,0,,当然 人们还制定了其它的准则\nDialogue: 0,1:08:07.37,1:08:09.61,Default,,0,0,0,,来操作栈帧之类的东西\nDialogue: 0,1:08:10.19,1:08:11.39,Default,,0,0,0,,这些准则中 那些不再需要的东西\nDialogue: 0,1:08:11.40,1:08:12.64,Default,,0,0,0,,也需要保存并恢复\nDialogue: 0,1:08:12.67,1:08:15.26,Default,,0,0,0,,因为从某种意义上来说 这样做更容易些\nDialogue: 0,1:08:15.83,1:08:17.40,Default,,0,0,0,,但这会带来各种灾难\nDialogue: 0,1:08:18.59,1:08:20.25,Default,,0,0,0,,我们稍后就会见识一些\nDialogue: 0,1:08:21.44,1:08:24.24,Default,,0,0,0,,只保存那些你稍后需要的值 这很关键\nDialogue: 0,1:08:26.89,1:08:28.01,Default,,0,0,0,,这是非常重要的理念\nDialogue: 0,1:08:29.87,1:08:33.36,Default,,0,0,0,,无论谁保存了一个值 都应该由他来恢复\nDialogue: 0,1:08:33.76,1:08:35.32,Default,,0,0,0,,因为他需要这个值\nDialogue: 0,1:08:36.93,1:08:38.54,Default,,0,0,0,,在这样的准则中\nDialogue: 0,1:08:38.86,1:08:40.76,Default,,0,0,0,,你可以发现哪些数据是不必要的\nDialogue: 0,1:08:43.45,1:08:44.73,Default,,0,0,0,,哪些操作又是不重要的\nDialogue: 0,1:08:47.15,1:08:50.40,Default,,0,0,0,,我还想告诉你们\nDialogue: 0,1:08:51.66,1:08:54.67,Default,,0,0,0,,当然 你们看到的并不是全部的图景\nDialogue: 0,1:08:55.35,1:08:56.68,Default,,0,0,0,,假设我的系统中\nDialogue: 0,1:08:56.80,1:09:01.52,Default,,0,0,0,,具有像CAR、CDR、CONS这样的运算\nDialogue: 0,1:09:03.53,1:09:05.60,Default,,0,0,0,,或者创建一个向量\nDialogue: 0,1:09:05.88,1:09:07.32,Default,,0,0,0,,并引用它的第N个元素\nDialogue: 0,1:09:08.30,1:09:09.21,Default,,0,0,0,,等等运算\nDialogue: 0,1:09:10.40,1:09:13.60,Default,,0,0,0,,然而 就在这个层次的细节来说\nDialogue: 0,1:09:13.87,1:09:17.85,Default,,0,0,0,,我们可以在数据通路中把它们视为基本运算\nDialogue: 0,1:09:18.75,1:09:21.95,Default,,0,0,0,,换句话说 我们可以认为 有一台机器\nDialogue: 0,1:09:22.32,1:09:24.11,Default,,0,0,0,,包含了APPEND机器\nDialogue: 0,1:09:24.20,1:09:26.46,Default,,0,0,0,,它通过(CONS (CAR X)\nDialogue: 0,1:09:26.64,1:09:29.80,Default,,0,0,0,,(APPEND (CDR X) Y)来实现\nDialogue: 0,1:09:29.88,1:09:33.18,Default,,0,0,0,,哦 天啊 这就跟阶乘机器有相同的结构\nDialogue: 0,1:09:33.63,1:09:35.29,Default,,0,0,0,,当然 它有相同的结构\nDialogue: 0,1:09:36.54,1:09:37.27,Default,,0,0,0,,我们有什么呢？\nDialogue: 0,1:09:37.27,1:09:39.39,Default,,0,0,0,,我们有某种东西 其中有\nDialogue: 0,1:09:39.76,1:09:42.48,Default,,0,0,0,,诸如X、Y之类的寄存器\nDialogue: 0,1:09:42.51,1:09:45.12,Default,,0,0,0,,有时X会移动到Y中\nDialogue: 0,1:09:45.28,1:09:46.75,Default,,0,0,0,,或者X会取得Y的值\nDialogue: 0,1:09:46.93,1:09:50.11,Default,,0,0,0,,我们或许要需要能够进行CONS运算\nDialogue: 0,1:09:51.70,1:09:57.74,Default,,0,0,0,,我记不清这个系统中是否需要这样的东西\nDialogue: 0,1:09:57.76,1:10:01.10,Default,,0,0,0,,但CONS有点类似于减法器或加法器之类的东西\nDialogue: 0,1:10:01.42,1:10:02.70,Default,,0,0,0,,它把两个东西结合起来\nDialogue: 0,1:10:02.73,1:10:04.27,Default,,0,0,0,,然后产生一个序对\nDialogue: 0,1:10:04.51,1:10:06.49,Default,,0,0,0,,然后会把输出结果送入到这里\nDialogue: 0,1:10:07.60,1:10:09.72,Default,,0,0,0,,可能还有一个叫做CAR的组件\nDialogue: 0,1:10:12.88,1:10:16.22,Default,,0,0,0,,它的结果是 -- 某个东西的CAR部分\nDialogue: 0,1:10:16.92,1:10:19.55,Default,,0,0,0,,我还可以取得某物的CDR部分 等等\nDialogue: 0,1:10:20.15,1:10:22.30,Default,,0,0,0,,但我们不应该害怕这么说\nDialogue: 0,1:10:22.92,1:10:24.24,Default,,0,0,0,,因为最坏的情况不过\nDialogue: 0,1:10:24.94,1:10:26.41,Default,,0,0,0,,当我们打开CONS后\nDialogue: 0,1:10:27.31,1:10:29.82,Default,,0,0,0,,会发现其中存在某台机器\nDialogue: 0,1:10:31.88,1:10:34.44,Default,,0,0,0,,CONS可能会与CAR和CDR有所重叠\nDialogue: 0,1:10:35.50,1:10:38.12,Default,,0,0,0,,就像加法和减法有所重叠一样\nDialogue: 0,1:10:38.57,1:10:39.85,Default,,0,0,0,,它们本质上都是一样的\nDialogue: 0,1:10:41.21,1:10:42.60,Default,,0,0,0,,CONS、CAR和CDR将会有所重叠\nDialogue: 0,1:10:42.62,1:10:44.52,Default,,0,0,0,,我们会发现其中有小型控制器\nDialogue: 0,1:10:45.50,1:10:46.54,Default,,0,0,0,,小型的数据通路\nDialogue: 0,1:10:48.03,1:10:49.64,Default,,0,0,0,,其中还有一些寄存器\nDialogue: 0,1:10:50.00,1:10:52.86,Default,,0,0,0,,一些其它的像这样的东西\nDialogue: 0,1:10:53.30,1:10:54.41,Default,,0,0,0,,并且 也许在这之中\nDialogue: 0,1:10:54.43,1:10:56.16,Default,,0,0,0,,可能也有无穷的部分\nDialogue: 0,1:10:56.46,1:10:58.70,Default,,0,0,0,,又或者是半无穷的 之类的\nDialogue: 0,1:10:58.81,1:11:00.65,Default,,0,0,0,,这些都是统一的东西\nDialogue: 0,1:11:00.96,1:11:02.03,Default,,0,0,0,,也就是我们所谓的“内存”\nDialogue: 0,1:11:06.57,1:11:08.83,Default,,0,0,0,,有限的内存也能无穷地存储 对此我一点也不吃惊\nDialogue: 0,1:11:09.33,1:11:11.07,Default,,0,0,0,,实际上它就是这样的 我们之后就会了解\nDialogue: 0,1:11:13.32,1:11:14.57,Default,,0,0,0,,那么 有什么疑问么？\nDialogue: 0,1:11:24.34,1:11:25.80,Default,,0,0,0,,天啊！你们都一言不发\nDialogue: 0,1:11:28.67,1:11:30.33,Default,,0,0,0,,假设我说得都是谎言吧！\nDialogue: 0,1:11:39.69,1:11:40.38,Default,,0,0,0,,好吧\nDialogue: 0,1:11:41.99,1:11:42.52,Default,,0,0,0,,谢谢大家\nDialogue: 0,1:11:42.52,1:11:43.28,Default,,0,0,0,,我们下课吧！\nDialogue: 0,1:11:44.23,1:11:55.15,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:11:44.23,1:11:55.15,Default,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec9a.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: EN Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 535\nActive Line: 539\nVideo Position: 51787\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:12.03,0:00:14.03,EN,,0,0,0,,Register Machines\nDialogue: 0,0:00:17.26,0:00:19.07,EN,,0,0,0,,PROFESSOR: Well, up 'til now, I suppose,\nDialogue: 0,0:00:19.32,0:00:23.93,EN,,0,0,0,,we've been learning about a lot of techniques for\nDialogue: 0,0:00:24.09,0:00:28.83,EN,,0,0,0,,organizing big programs, symbolic manipulation a bit,\nDialogue: 0,0:00:30.84,0:00:35.60,EN,,0,0,0,,some of the technology that you use for establishing languages,\nDialogue: 0,0:00:35.63,0:00:36.78,EN,,0,0,0,,one in terms of another,\nDialogue: 0,0:00:37.10,0:00:39.92,EN,,0,0,0,,which is used for organizing very large programs.\nDialogue: 0,0:00:39.96,0:00:42.30,EN,,0,0,0,,In fact, the nicest programs I know\nDialogue: 0,0:00:42.44,0:00:44.43,EN,,0,0,0,,look more like a pile of languages\nDialogue: 0,0:00:44.91,0:00:47.96,EN,,0,0,0,,than like a decomposition of a problem into parts.\nDialogue: 0,0:00:49.90,0:00:51.45,EN,,0,0,0,,Well, I suppose at this point,\nDialogue: 0,0:00:52.08,0:00:53.58,EN,,0,0,0,,there are still, however, a few mysteries\nDialogue: 0,0:00:53.61,0:00:55.32,EN,,0,0,0,,about how this sort of stuff works.\nDialogue: 0,0:00:56.26,0:00:59.68,EN,,0,0,0,,And so what we'd like to do now is\nDialogue: 0,0:01:00.03,0:01:02.60,EN,,0,0,0,,diverge from the plan of\nDialogue: 0,0:01:02.96,0:01:05.42,EN,,0,0,0,,telling you how to organize big programs,\nDialogue: 0,0:01:05.45,0:01:08.19,EN,,0,0,0,,and rather tell you something about the mechanisms\nDialogue: 0,0:01:08.52,0:01:11.71,EN,,0,0,0,,by which these things can be made to work.\nDialogue: 0,0:01:12.19,0:01:14.83,EN,,0,0,0,,The main reason for this is\nDialogue: 0,0:01:15.80,0:01:17.87,EN,,0,0,0,,demystification, if you will,\nDialogue: 0,0:01:18.65,0:01:20.54,EN,,0,0,0,,that we have a lot of mysteries left,\nDialogue: 0,0:01:21.08,0:01:25.48,EN,,0,0,0,,like exactly how it is the case that a program is controlled,\nDialogue: 0,0:01:26.08,0:01:30.38,EN,,0,0,0,,how a computer knows what the next thing to do is,\nDialogue: 0,0:01:30.52,0:01:31.74,EN,,0,0,0,,or something like that.\nDialogue: 0,0:01:32.43,0:01:35.56,EN,,0,0,0,,And what I'd like to do now is make that clear to you\nDialogue: 0,0:01:35.85,0:01:39.10,EN,,0,0,0,,that even if you've never played with a physical computer before,\nDialogue: 0,0:01:39.56,0:01:43.50,EN,,0,0,0,,the mechanism is really very simple,\nDialogue: 0,0:01:44.33,0:01:46.35,EN,,0,0,0,,and that you can understand it completely with no trouble.\nDialogue: 0,0:01:47.65,0:01:51.24,EN,,0,0,0,,So I'd like to start by imagining that we--\nDialogue: 0,0:01:51.32,0:01:52.91,EN,,0,0,0,,well, the way we're going to do this, by the way,\nDialogue: 0,0:01:52.96,0:01:55.80,EN,,0,0,0,,is we're going to take some very simple Lisp programs,\nDialogue: 0,0:01:56.54,0:01:58.12,EN,,0,0,0,,very simple Lisp programs,\nDialogue: 0,0:01:59.04,0:02:00.62,EN,,0,0,0,,and transform them into hardware.\nDialogue: 0,0:02:02.16,0:02:04.16,EN,,0,0,0,,I'm not going to worry about some intermediate step\nDialogue: 0,0:02:04.70,0:02:07.45,EN,,0,0,0,,of going through some existing computer machine language\nDialogue: 0,0:02:07.47,0:02:09.05,EN,,0,0,0,,and then showing you how that computer works,\nDialogue: 0,0:02:09.82,0:02:12.00,EN,,0,0,0,,because that's not as illuminating.\nDialogue: 0,0:02:12.75,0:02:14.17,EN,,0,0,0,,So what I'm really going to show you\nDialogue: 0,0:02:14.51,0:02:17.48,EN,,0,0,0,,is how a piece of machinery can be built\nDialogue: 0,0:02:18.03,0:02:22.04,EN,,0,0,0,,to do a job that you have written down as a program.\nDialogue: 0,0:02:22.04,0:02:24.03,EN,,0,0,0,,That program is, in fact, a description of a machine.\nDialogue: 0,0:02:25.76,0:02:27.69,EN,,0,0,0,,We're going to start with a very simple program,\nDialogue: 0,0:02:28.09,0:02:30.81,EN,,0,0,0,,proceed to show you some simple mechanisms,\nDialogue: 0,0:02:31.39,0:02:33.68,EN,,0,0,0,,proceed to a few more complicated programs,\nDialogue: 0,0:02:34.30,0:02:37.42,EN,,0,0,0,,and then later show you a not very complicated program,\nDialogue: 0,0:02:37.44,0:02:41.23,EN,,0,0,0,,how the evaluator transforms into a piece of hardware.\nDialogue: 0,0:02:41.23,0:02:42.06,EN,,0,0,0,,And of course at that point,\nDialogue: 0,0:02:42.08,0:02:44.08,EN,,0,0,0,,you have made the universal transition\nDialogue: 0,0:02:44.22,0:02:46.88,EN,,0,0,0,,and can execute any program imaginable\nDialogue: 0,0:02:47.16,0:02:48.80,EN,,0,0,0,,with a piece of well-defined hardware.\nDialogue: 0,0:02:51.72,0:02:52.91,EN,,0,0,0,,Well, let's start up now,\nDialogue: 0,0:02:53.05,0:02:55.31,EN,,0,0,0,,give you a real concrete feeling for this sort of thing.\nDialogue: 0,0:02:55.44,0:02:57.66,EN,,0,0,0,,Let's start with a very simple program.\nDialogue: 0,0:02:59.60,0:03:00.85,EN,,0,0,0,,Here's Euclid's algorithm.\nDialogue: 0,0:03:03.88,0:03:07.00,EN,,0,0,0,,It's actually a little bit more modern than Euclid's algorithm.\nDialogue: 0,0:03:07.02,0:03:10.09,EN,,0,0,0,,Euclid's algorithm for computing the greatest common divisor of two numbers\nDialogue: 0,0:03:10.41,0:03:13.60,EN,,0,0,0,,was invented 350 BC, I think.\nDialogue: 0,0:03:14.30,0:03:15.69,EN,,0,0,0,,It's the oldest known algorithm.\nDialogue: 0,0:03:19.32,0:03:23.34,EN,,0,0,0,,But here we're going to talk about GCD of A and B,\nDialogue: 0,0:03:23.36,0:03:25.61,EN,,0,0,0,,the Greatest Common Divisor or two numbers, A and B.\nDialogue: 0,0:03:26.20,0:03:28.91,EN,,0,0,0,,And the algorithm is extremely simple.\nDialogue: 0,0:03:29.50,0:03:31.08,EN,,0,0,0,,If B is 0,\nDialogue: 0,0:03:34.16,0:03:36.83,EN,,0,0,0,,then the result is going to be A.\nDialogue: 0,0:03:37.52,0:03:43.61,EN,,0,0,0,,Otherwise, the result is the GCD of B\nDialogue: 0,0:03:44.49,0:03:53.39,EN,,0,0,0,,and the remainder when A is divided by B.\nDialogue: 0,0:03:58.53,0:04:01.90,EN,,0,0,0,,So this we have here is a very simple iterative process.\nDialogue: 0,0:04:02.03,0:04:04.08,EN,,0,0,0,,This a simple recursive procedure,\nDialogue: 0,0:04:04.38,0:04:07.53,EN,,0,0,0,,recursively defined procedure, recursive definition,\nDialogue: 0,0:04:07.71,0:04:09.26,EN,,0,0,0,,which yields an iterative process.\nDialogue: 0,0:04:09.95,0:04:12.46,EN,,0,0,0,,And the way it works is that every step,\nDialogue: 0,0:04:12.80,0:04:15.10,EN,,0,0,0,,it determines whether B was zero.\nDialogue: 0,0:04:16.24,0:04:18.80,EN,,0,0,0,,And if B is 0, we got the answer in A.\nDialogue: 0,0:04:19.63,0:04:22.46,EN,,0,0,0,,Otherwise, we make another step\nDialogue: 0,0:04:22.49,0:04:23.87,EN,,0,0,0,,where A is the old B,\nDialogue: 0,0:04:23.88,0:04:27.04,EN,,0,0,0,,and B is the remainder of the old A divided by the old B.\nDialogue: 0,0:04:28.76,0:04:29.55,EN,,0,0,0,,Very simple.\nDialogue: 0,0:04:31.11,0:04:32.72,EN,,0,0,0,,Now this, I've already told you\nDialogue: 0,0:04:32.99,0:04:34.86,EN,,0,0,0,,some of the mechanism by just saying it that way.\nDialogue: 0,0:04:34.86,0:04:35.90,EN,,0,0,0,,I said it in time.\nDialogue: 0,0:04:36.36,0:04:37.72,EN,,0,0,0,,I said there are certain steps,\nDialogue: 0,0:04:38.14,0:04:39.32,EN,,0,0,0,,and that, in fact,\nDialogue: 0,0:04:39.52,0:04:40.86,EN,,0,0,0,,one of the things you can see here\nDialogue: 0,0:04:41.18,0:04:43.69,EN,,0,0,0,,is that one of the reasons why this is iterative\nDialogue: 0,0:04:43.95,0:04:47.68,EN,,0,0,0,,is nothing is needed of the last step to get the answer.\nDialogue: 0,0:04:49.44,0:04:55.29,EN,,0,0,0,,All of the information that's needed to run this algorithm is in A and B.\nDialogue: 0,0:04:55.74,0:04:57.80,EN,,0,0,0,,It has two well-defined state variables.\nDialogue: 0,0:05:00.47,0:05:02.33,EN,,0,0,0,,So I'm going to define a machine for you\nDialogue: 0,0:05:03.98,0:05:05.55,EN,,0,0,0,,can compute you GCDs.\nDialogue: 0,0:05:06.56,0:05:07.12,EN,,0,0,0,,Now let's see.\nDialogue: 0,0:05:07.12,0:05:11.28,EN,,0,0,0,,Every computer that's ever been made that's a single-process computer,\nDialogue: 0,0:05:11.80,0:05:14.08,EN,,0,0,0,,as opposed to a multiprocessor of some sort,\nDialogue: 0,0:05:15.04,0:05:16.59,EN,,0,0,0,,is made according to the same plan.\nDialogue: 0,0:05:17.84,0:05:19.53,EN,,0,0,0,,The plan is the computer has two parts,\nDialogue: 0,0:05:20.57,0:05:22.35,EN,,0,0,0,,a part called the datapaths,\nDialogue: 0,0:05:23.10,0:05:24.36,EN,,0,0,0,,and a part called the controller.\nDialogue: 0,0:05:25.91,0:05:29.28,EN,,0,0,0,,The datapaths correspond to a calculator that you might have.\nDialogue: 0,0:05:29.71,0:05:31.87,EN,,0,0,0,,It contains certain registers that remember things,\nDialogue: 0,0:05:31.90,0:05:33.13,EN,,0,0,0,,and you've all used calculators.\nDialogue: 0,0:05:33.56,0:05:35.34,EN,,0,0,0,,It has some buttons on it and some lights.\nDialogue: 0,0:05:37.03,0:05:38.49,EN,,0,0,0,,And so by pushing the various buttons,\nDialogue: 0,0:05:38.52,0:05:41.34,EN,,0,0,0,,you can cause operations to happen inside there among the registers,\nDialogue: 0,0:05:41.87,0:05:43.48,EN,,0,0,0,,and some of the results to be displayed.\nDialogue: 0,0:05:45.16,0:05:46.25,EN,,0,0,0,,That's completely mechanical.\nDialogue: 0,0:05:46.25,0:05:49.55,EN,,0,0,0,,You could imagine that box has no intelligence in it.\nDialogue: 0,0:05:50.90,0:05:53.28,EN,,0,0,0,,Now it might be very impressive that it can produce the sine of a number,\nDialogue: 0,0:05:53.53,0:05:58.97,EN,,0,0,0,,but that at least is apparently possibly mechanical.\nDialogue: 0,0:05:58.97,0:06:01.71,EN,,0,0,0,,At least, I could open that up in the same way I'm about to open GCD.\nDialogue: 0,0:06:02.69,0:06:04.36,EN,,0,0,0,,So this may have a whole computer inside of it,\nDialogue: 0,0:06:04.68,0:06:05.69,EN,,0,0,0,,but that's not interesting.\nDialogue: 0,0:06:05.94,0:06:07.10,EN,,0,0,0,,Addition is certainly simple.\nDialogue: 0,0:06:08.20,0:06:09.84,EN,,0,0,0,,That can be done without any further mechanism.\nDialogue: 0,0:06:10.89,0:06:15.64,EN,,0,0,0,,Now also, if we were to look at the other half, the controller,\nDialogue: 0,0:06:15.93,0:06:17.39,EN,,0,0,0,,that's a part that's dumb, too.\nDialogue: 0,0:06:18.19,0:06:19.16,EN,,0,0,0,,It pushes the buttons.\nDialogue: 0,0:06:20.35,0:06:21.52,EN,,0,0,0,,It pushes them according to the sequence,\nDialogue: 0,0:06:21.55,0:06:22.84,EN,,0,0,0,,which is written down on a piece of paper,\nDialogue: 0,0:06:24.27,0:06:25.64,EN,,0,0,0,,and observes the lights.\nDialogue: 0,0:06:26.29,0:06:29.44,EN,,0,0,0,,And every so often, it comes to a place in a sequence that says,\nDialogue: 0,0:06:29.47,0:06:32.37,EN,,0,0,0,,if light A is on, do this sequence.\nDialogue: 0,0:06:32.37,0:06:33.85,EN,,0,0,0,,Otherwise, do that sequence.\nDialogue: 0,0:06:34.62,0:06:37.45,EN,,0,0,0,,And thereby, there's no complexity there either.\nDialogue: 0,0:06:38.35,0:06:39.32,EN,,0,0,0,,Well, let's just draw that\nDialogue: 0,0:06:39.34,0:06:40.57,EN,,0,0,0,,and see what we feel about that.\nDialogue: 0,0:06:42.51,0:06:44.84,EN,,0,0,0,,So for computing GCDs,\nDialogue: 0,0:06:45.88,0:06:49.52,EN,,0,0,0,,what I want you to think about is that there are these registers.\nDialogue: 0,0:06:50.56,0:06:53.02,EN,,0,0,0,,A register is a place where I store a number, in this case.\nDialogue: 0,0:06:53.52,0:06:54.65,EN,,0,0,0,,And this one's called a.\nDialogue: 0,0:06:56.81,0:06:58.70,EN,,0,0,0,,And then there's another one for storing b.\nDialogue: 0,0:07:03.17,0:07:05.45,EN,,0,0,0,,Now we have to see what things we can do with these registers,\nDialogue: 0,0:07:05.98,0:07:08.73,EN,,0,0,0,,and they're not entirely obvious what you can do with them.\nDialogue: 0,0:07:09.84,0:07:11.72,EN,,0,0,0,,Well, we have to see what things we need to do with them.\nDialogue: 0,0:07:11.82,0:07:13.87,EN,,0,0,0,,We're looking at the problem we're trying to solve.\nDialogue: 0,0:07:14.03,0:07:16.09,EN,,0,0,0,,One of the important things for designing a computer,\nDialogue: 0,0:07:17.10,0:07:19.58,EN,,0,0,0,,which I think most designers don't do,\nDialogue: 0,0:07:20.20,0:07:21.88,EN,,0,0,0,,is you stay the problem you want to solve\nDialogue: 0,0:07:22.62,0:07:25.18,EN,,0,0,0,,and then use what you learn from studying the problem you want to solve\nDialogue: 0,0:07:25.44,0:07:27.28,EN,,0,0,0,,to put in the mechanisms needed to solve it\nDialogue: 0,0:07:27.53,0:07:28.70,EN,,0,0,0,,in the computer you're building,\nDialogue: 0,0:07:28.81,0:07:30.08,EN,,0,0,0,,no more no less.\nDialogue: 0,0:07:32.14,0:07:33.96,EN,,0,0,0,,Now it may be that the problem you're trying to solve\nDialogue: 0,0:07:34.24,0:07:35.40,EN,,0,0,0,,is everybody's problem,\nDialogue: 0,0:07:36.06,0:07:37.58,EN,,0,0,0,,in which case you have to build in a universal\nDialogue: 0,0:07:37.60,0:07:39.29,EN,,0,0,0,,interpreter of some language.\nDialogue: 0,0:07:40.19,0:07:42.32,EN,,0,0,0,,But you shouldn't put any more in than required\nDialogue: 0,0:07:42.35,0:07:44.25,EN,,0,0,0,,to build the universal interpreter of some language.\nDialogue: 0,0:07:44.44,0:07:45.85,EN,,0,0,0,,We'll worry about that in a second.\nDialogue: 0,0:07:47.23,0:07:49.93,EN,,0,0,0,,OK, going back to here, let's see.\nDialogue: 0,0:07:49.93,0:07:51.24,EN,,0,0,0,,What do we have to be able to do?\nDialogue: 0,0:07:51.79,0:07:54.14,EN,,0,0,0,,Well, somehow, we have to be able to get B into A.\nDialogue: 0,0:07:56.08,0:07:59.60,EN,,0,0,0,,We have to be able to get the old value of B into the value of A.\nDialogue: 0,0:08:00.38,0:08:03.32,EN,,0,0,0,,So we have to have some path by which stuff can flow\nDialogue: 0,0:08:03.34,0:08:04.76,EN,,0,0,0,,whatever this information is,\nDialogue: 0,0:08:05.37,0:08:06.57,EN,,0,0,0,,OK? from b to a.\nDialogue: 0,0:08:07.39,0:08:09.26,EN,,0,0,0,,I'm going to draw that with by an arrow\nDialogue: 0,0:08:09.52,0:08:12.62,EN,,0,0,0,,saying that it is possible to move the contents of b into a,\nDialogue: 0,0:08:12.96,0:08:14.57,EN,,0,0,0,,replacing the value of a.\nDialogue: 0,0:08:15.12,0:08:16.73,EN,,0,0,0,,And there's a little button here which you push\nDialogue: 0,0:08:17.48,0:08:18.56,EN,,0,0,0,,which allows that to happen.\nDialogue: 0,0:08:19.71,0:08:20.78,EN,,0,0,0,,That's what the little x is here.\nDialogue: 0,0:08:23.07,0:08:23.93,EN,,0,0,0,,Now it's also the case\nDialogue: 0,0:08:23.95,0:08:26.28,EN,,0,0,0,,that I have to be able to compute the remainder of a and b.\nDialogue: 0,0:08:27.00,0:08:28.49,EN,,0,0,0,,Now that may be a complicated mess.\nDialogue: 0,0:08:28.86,0:08:30.86,EN,,0,0,0,,On the other hand, I'm going to make it a small box.\nDialogue: 0,0:08:31.96,0:08:33.92,EN,,0,0,0,,If we have to, we may open up that box\nDialogue: 0,0:08:34.12,0:08:35.63,EN,,0,0,0,,and look inside and see what it is.\nDialogue: 0,0:08:37.77,0:08:39.16,EN,,0,0,0,,So here, I'm going to have a little box,\nDialogue: 0,0:08:39.20,0:08:40.38,EN,,0,0,0,,which I'm going to draw this way,\nDialogue: 0,0:08:43.16,0:08:44.38,EN,,0,0,0,,which we'll call the remainder.\nDialogue: 0,0:08:46.44,0:08:48.60,EN,,0,0,0,,And it's going to take in a.\nDialogue: 0,0:08:50.91,0:08:52.16,EN,,0,0,0,,That's going to take in b.\nDialogue: 0,0:08:54.37,0:08:56.51,EN,,0,0,0,,And it's going to put out something,\nDialogue: 0,0:08:58.89,0:09:00.46,EN,,0,0,0,,the remainder of a divided by b.\nDialogue: 0,0:09:02.29,0:09:03.61,EN,,0,0,0,,Another thing we have to see here is\nDialogue: 0,0:09:03.64,0:09:06.06,EN,,0,0,0,,that we have to be able to test whether b is equal to 0.\nDialogue: 0,0:09:08.00,0:09:09.66,EN,,0,0,0,,Well, that means somebody's got to be looking at--\nDialogue: 0,0:09:10.00,0:09:12.30,EN,,0,0,0,,a thing that's looking at the value of b.\nDialogue: 0,0:09:13.39,0:09:14.40,EN,,0,0,0,,I have a light bulb here\nDialogue: 0,0:09:15.85,0:09:17.39,EN,,0,0,0,,which lights up if b equals 0.\nDialogue: 0,0:09:21.11,0:09:22.01,EN,,0,0,0,,That's its job.\nDialogue: 0,0:09:24.03,0:09:26.78,EN,,0,0,0,,And finally, I suppose, because of the fact\nDialogue: 0,0:09:26.96,0:09:30.43,EN,,0,0,0,,that we want the new value of a to be the old value of b,\nDialogue: 0,0:09:30.46,0:09:34.41,EN,,0,0,0,,and simultaneously the new value of b to be something I've done with a,\nDialogue: 0,0:09:35.28,0:09:37.60,EN,,0,0,0,,and if I plan to make my machine\nDialogue: 0,0:09:37.80,0:09:39.74,EN,,0,0,0,,such that everything happens one at a time,\nDialogue: 0,0:09:40.20,0:09:41.40,EN,,0,0,0,,one motion at a time,\nDialogue: 0,0:09:41.61,0:09:43.42,EN,,0,0,0,,and I can't put two numbers in a register,\nDialogue: 0,0:09:44.03,0:09:46.30,EN,,0,0,0,,then I have to have another place to put one while I'm interchanging.\nDialogue: 0,0:09:49.29,0:09:49.60,EN,,0,0,0,,OK?\nDialogue: 0,0:09:50.00,0:09:51.85,EN,,0,0,0,,I can't interchange the two things in my hands,\nDialogue: 0,0:09:52.11,0:09:53.72,EN,,0,0,0,,unless I either put two in one hand\nDialogue: 0,0:09:53.72,0:09:55.13,EN,,0,0,0,,and then pull it back the other way,\nDialogue: 0,0:09:55.50,0:09:56.91,EN,,0,0,0,,or unless I put one down,\nDialogue: 0,0:09:57.02,0:09:58.68,EN,,0,0,0,,pick it up, and put the other one, like that\nDialogue: 0,0:09:59.64,0:10:00.94,EN,,0,0,0,,unless I'm a juggler,\nDialogue: 0,0:10:01.66,0:10:03.50,EN,,0,0,0,,which I'm not, as you can see,\nDialogue: 0,0:10:04.65,0:10:07.36,EN,,0,0,0,,in which case I have a possibility of timing errors.\nDialogue: 0,0:10:08.85,0:10:11.04,EN,,0,0,0,,In fact, much of the type of computer design\nDialogue: 0,0:10:11.07,0:10:12.68,EN,,0,0,0,,people do involves timing errors,\nDialogue: 0,0:10:13.12,0:10:15.00,EN,,0,0,0,,of some potential timing errors,\nDialogue: 0,0:10:15.24,0:10:16.43,EN,,0,0,0,,which I don't much like.\nDialogue: 0,0:10:17.34,0:10:18.64,EN,,0,0,0,,But. So for that reason,\nDialogue: 0,0:10:18.68,0:10:21.21,EN,,0,0,0,,I have to have a place to put the third thing down\nDialogue: 0,0:10:22.06,0:10:23.29,EN,,0,0,0,,the second one of them down.\nDialogue: 0,0:10:23.41,0:10:24.72,EN,,0,0,0,,So I have a place called t,\nDialogue: 0,0:10:24.75,0:10:26.84,EN,,0,0,0,,which is a register just for temporary, t,\nDialogue: 0,0:10:28.59,0:10:29.63,EN,,0,0,0,,with a button on it.\nDialogue: 0,0:10:30.47,0:10:31.88,EN,,0,0,0,,And then I'll take the result of that,\nDialogue: 0,0:10:31.90,0:10:34.14,EN,,0,0,0,,since I have to take that and put into b, over here,\nDialogue: 0,0:10:34.68,0:10:36.73,EN,,0,0,0,,we'll take the result of that and go like this,\nDialogue: 0,0:10:38.41,0:10:39.30,EN,,0,0,0,,and a button here.\nDialogue: 0,0:10:42.43,0:10:45.84,EN,,0,0,0,,So that's the datapaths of a GCD machine.\nDialogue: 0,0:10:47.60,0:10:48.57,EN,,0,0,0,,Now what's the controller?\nDialogue: 0,0:10:49.74,0:10:51.28,EN,,0,0,0,,Controller's a very simple thing, too.\nDialogue: 0,0:10:52.28,0:10:53.26,EN,,0,0,0,,The machine has a state.\nDialogue: 0,0:10:54.38,0:10:57.72,EN,,0,0,0,,The way I like to visualize that is that I've got a maze.\nDialogue: 0,0:10:59.01,0:11:03.20,EN,,0,0,0,,And the maze has a bunch of places connected by directed arrows.\nDialogue: 0,0:11:04.43,0:11:05.60,EN,,0,0,0,,And what I have is a marble,\nDialogue: 0,0:11:06.46,0:11:09.07,EN,,0,0,0,,which represents the state of the controller.\nDialogue: 0,0:11:10.74,0:11:12.27,EN,,0,0,0,,The marble rolls around in the maze.\nDialogue: 0,0:11:13.74,0:11:17.15,EN,,0,0,0,,Of course, this analogy breaks down for energy reasons.\nDialogue: 0,0:11:17.15,0:11:19.08,EN,,0,0,0,,I sometimes have to pump the marble up to the top,\nDialogue: 0,0:11:19.12,0:11:21.85,EN,,0,0,0,,because it's going to otherwise be a perpetual motion machine.\nDialogue: 0,0:11:22.00,0:11:23.32,EN,,0,0,0,,But not worrying about that,\nDialogue: 0,0:11:23.90,0:11:25.90,EN,,0,0,0,,this is not a physical analogy.\nDialogue: 0,0:11:26.08,0:11:27.42,EN,,0,0,0,,This marble rolls around.\nDialogue: 0,0:11:27.68,0:11:29.56,EN,,0,0,0,,And every time it rolls around certain bumpers,\nDialogue: 0,0:11:29.68,0:11:30.97,EN,,0,0,0,,like in a pinball machine,\nDialogue: 0,0:11:31.26,0:11:32.60,EN,,0,0,0,,it pushes one of these buttons.\nDialogue: 0,0:11:34.83,0:11:37.50,EN,,0,0,0,,And every so often, it comes to a place, which is a division,\nDialogue: 0,0:11:38.62,0:11:39.68,EN,,0,0,0,,where it has to make a choice.\nDialogue: 0,0:11:40.25,0:11:42.36,EN,,0,0,0,,And there's a flap, which is controlled by this.\nDialogue: 0,0:11:46.00,0:11:48.82,EN,,0,0,0,,So that's a really mechanical way of thinking about it.\nDialogue: 0,0:11:48.82,0:11:51.05,EN,,0,0,0,,Of course, controllers not these days, are not built that way\nDialogue: 0,0:11:51.08,0:11:51.84,EN,,0,0,0,,in real computers.\nDialogue: 0,0:11:51.84,0:11:56.01,EN,,0,0,0,,They're built with a little bit of ROM and a state register.\nDialogue: 0,0:11:56.61,0:11:58.73,EN,,0,0,0,,But there was a time, like the DEC PDP-6,\nDialogue: 0,0:11:59.29,0:12:01.02,EN,,0,0,0,,where that's how you built the controller of a machine.\nDialogue: 0,0:12:01.80,0:12:03.61,EN,,0,0,0,,There was a bit that ran around the delay line,\nDialogue: 0,0:12:05.69,0:12:08.14,EN,,0,0,0,,and it triggered things as it went by.\nDialogue: 0,0:12:08.58,0:12:10.70,EN,,0,0,0,,And it would come back to the beginning and get fed round again.\nDialogue: 0,0:12:11.99,0:12:13.72,EN,,0,0,0,,And of course, there were all sorts of great bugs you could have\nDialogue: 0,0:12:13.74,0:12:17.67,EN,,0,0,0,,like two bits going around, two marbles.\nDialogue: 0,0:12:17.67,0:12:19.26,EN,,0,0,0,,And then the machine has lost its marbles.\nDialogue: 0,0:12:19.45,0:12:20.20,EN,,0,0,0,,That happens, too.\nDialogue: 0,0:12:20.98,0:12:21.58,EN,,0,0,0,,Oh, well.\nDialogue: 0,0:12:22.27,0:12:24.22,EN,,0,0,0,,So anyway, for this machine,\nDialogue: 0,0:12:24.27,0:12:25.48,EN,,0,0,0,,what I have to do is the following.\nDialogue: 0,0:12:25.80,0:12:27.74,EN,,0,0,0,,I'm going to start my maze here.\nDialogue: 0,0:12:30.52,0:12:32.73,EN,,0,0,0,,And the first thing I've got to do,\nDialogue: 0,0:12:33.76,0:12:36.75,EN,,0,0,0,,is in a notation which many of you are familiar with,\nDialogue: 0,0:12:37.07,0:12:39.85,EN,,0,0,0,,is b equal to zero, a test.\nDialogue: 0,0:12:41.50,0:12:43.79,EN,,0,0,0,,And there's a possibility, either yes,\nDialogue: 0,0:12:43.93,0:12:45.58,EN,,0,0,0,,in which case I'm done.\nDialogue: 0,0:12:49.79,0:12:51.26,EN,,0,0,0,,Otherwise, if no,\nDialogue: 0,0:12:52.70,0:12:54.32,EN,,0,0,0,,then I'm going have to roll over some bumpers.\nDialogue: 0,0:12:55.00,0:12:56.46,EN,,0,0,0,,I'm going to do it in the following order.\nDialogue: 0,0:12:57.42,0:13:03.40,EN,,0,0,0,,I want to, I want to do this interchange game.\nDialogue: 0,0:13:04.05,0:13:05.80,EN,,0,0,0,,Now first, since I need both a and b,\nDialogue: 0,0:13:06.32,0:13:08.57,EN,,0,0,0,,but then the first-- and this is not necessary--\nDialogue: 0,0:13:08.65,0:13:09.72,EN,,0,0,0,,I want to collect this.\nDialogue: 0,0:13:11.07,0:13:12.62,EN,,0,0,0,,This is the thing that's going to go into b.\nDialogue: 0,0:13:13.24,0:13:14.03,EN,,0,0,0,,So I'm going to say,\nDialogue: 0,0:13:14.28,0:13:16.27,EN,,0,0,0,,take this, which depends upon both a and b,\nDialogue: 0,0:13:16.36,0:13:18.67,EN,,0,0,0,,and put the remainder into here.\nDialogue: 0,0:13:19.15,0:13:20.33,EN,,0,0,0,,So I'm going to push this button first.\nDialogue: 0,0:13:21.53,0:13:24.43,EN,,0,0,0,,Then, I'm going to transfer b to a,\nDialogue: 0,0:13:24.44,0:13:25.60,EN,,0,0,0,,push that button,\nDialogue: 0,0:13:25.82,0:13:27.63,EN,,0,0,0,,and then I transfer the temporary into b,\nDialogue: 0,0:13:28.76,0:13:29.42,EN,,0,0,0,,push that button.\nDialogue: 0,0:13:32.03,0:13:34.97,EN,,0,0,0,,So a very sequential machine,\nDialogue: 0,0:13:35.39,0:13:36.52,EN,,0,0,0,,it's very inefficient.\nDialogue: 0,0:13:37.75,0:13:39.05,EN,,0,0,0,,But that's fine right now.\nDialogue: 0,0:13:39.81,0:13:40.97,EN,,0,0,0,,We're going to name the buttons,\nDialogue: 0,0:13:41.47,0:13:42.72,EN,,0,0,0,,t gets remainder.\nDialogue: 0,0:13:46.75,0:13:48.73,EN,,0,0,0,,a gets b.\nDialogue: 0,0:13:50.03,0:13:54.81,EN,,0,0,0,,And b gets t.\nDialogue: 0,0:13:55.47,0:13:57.63,EN,,0,0,0,,And then I'm going to go around here\nDialogue: 0,0:13:58.78,0:13:59.88,EN,,0,0,0,,and it's to go back to start.\nDialogue: 0,0:14:01.62,0:14:03.87,EN,,0,0,0,,And if you look, what are we seeing here?\nDialogue: 0,0:14:03.87,0:14:04.91,EN,,0,0,0,,We're seeing the various--\nDialogue: 0,0:14:05.05,0:14:07.16,EN,,0,0,0,,what I really have is some sort of mechanical connection,\nDialogue: 0,0:14:07.42,0:14:13.63,EN,,0,0,0,,where t gets r controls this thing.\nDialogue: 0,0:14:16.83,0:14:21.48,EN,,0,0,0,,And I have here that a gets b controls this fellow over here,\nDialogue: 0,0:14:26.96,0:14:28.12,EN,,0,0,0,,and this fellow over here.\nDialogue: 0,0:14:28.12,0:14:31.08,EN,,0,0,0,,Boy, that's absolutely pessimal,\nDialogue: 0,0:14:31.48,0:14:32.48,EN,,0,0,0,,the inverse of optimal.\nDialogue: 0,0:14:32.63,0:14:34.59,EN,,0,0,0,,Every line heads across every other line the way I drew it.\nDialogue: 0,0:14:38.54,0:14:41.15,EN,,0,0,0,,I suppose this goes here, b gets t.\nDialogue: 0,0:14:45.69,0:14:47.95,EN,,0,0,0,,Now I'd like to run this machine.\nDialogue: 0,0:14:48.04,0:14:49.34,EN,,0,0,0,,But before I run the machine,\nDialogue: 0,0:14:49.37,0:14:51.40,EN,,0,0,0,,I want to write down a description of this controller,\nDialogue: 0,0:14:51.63,0:14:52.81,EN,,0,0,0,,just so you can see that these things,\nDialogue: 0,0:14:52.84,0:14:55.63,EN,,0,0,0,,of course, as usual, can be written down in some nice language,\nDialogue: 0,0:14:56.08,0:14:58.08,EN,,0,0,0,,so that we don't have to always draw these diagrams.\nDialogue: 0,0:14:58.36,0:15:00.68,EN,,0,0,0,,One of the problems with diagrams is that they take up a lot of space.\nDialogue: 0,0:15:00.89,0:15:01.98,EN,,0,0,0,,And for a machine this small,\nDialogue: 0,0:15:02.00,0:15:03.05,EN,,0,0,0,,it takes two blackboards.\nDialogue: 0,0:15:03.22,0:15:05.24,EN,,0,0,0,,For a machine that's the evaluator machine,\nDialogue: 0,0:15:05.40,0:15:07.10,EN,,0,0,0,,I have trouble putting it into this room,\nDialogue: 0,0:15:07.95,0:15:09.16,EN,,0,0,0,,even though it isn't very big.\nDialogue: 0,0:15:09.90,0:15:11.28,EN,,0,0,0,,So I'm going to make a little language for this\nDialogue: 0,0:15:11.29,0:15:12.51,EN,,0,0,0,,that's just a description of that,\nDialogue: 0,0:15:13.10,0:15:23.29,EN,,0,0,0,,saying define a machine we'll call GCD.\nDialogue: 0,0:15:24.42,0:15:25.66,EN,,0,0,0,,Of course, once we have something like this,\nDialogue: 0,0:15:25.68,0:15:26.83,EN,,0,0,0,,we have a simulator for it.\nDialogue: 0,0:15:27.22,0:15:29.42,EN,,0,0,0,,And the reason why we want to build a language in this form,\nDialogue: 0,0:15:29.56,0:15:32.94,EN,,0,0,0,,is because all of a sudden we can manipulate these expressions that I'm writing down.\nDialogue: 0,0:15:33.21,0:15:34.91,EN,,0,0,0,,And then of course I can write things I can\nDialogue: 0,0:15:35.29,0:15:38.16,EN,,0,0,0,,algebraically manipulate these things, simulate them\nDialogue: 0,0:15:38.20,0:15:39.96,EN,,0,0,0,,all that sort of things that I might want to do,\nDialogue: 0,0:15:40.12,0:15:42.59,EN,,0,0,0,,perhaps transform them as a layout, who knows.\nDialogue: 0,0:15:43.63,0:15:48.38,EN,,0,0,0,,Once I have a nice representation of registers,\nDialogue: 0,0:15:48.51,0:15:49.61,EN,,0,0,0,,it has certain registers,\nDialogue: 0,0:15:53.00,0:15:55.64,EN,,0,0,0,,which we can call A, B, and T.\nDialogue: 0,0:15:56.75,0:15:57.80,EN,,0,0,0,,And there's a controller.\nDialogue: 0,0:16:02.19,0:16:04.46,EN,,0,0,0,,Actually, a better language, which would be more explicit,\nDialogue: 0,0:16:04.49,0:16:06.97,EN,,0,0,0,,would be one which named every button\nDialogue: 0,0:16:08.14,0:16:10.17,EN,,0,0,0,,also and said what it did.\nDialogue: 0,0:16:10.42,0:16:11.37,EN,,0,0,0,,Like, this button\nDialogue: 0,0:16:11.55,0:16:14.19,EN,,0,0,0,,causes the contents of T to go to the contents of B.\nDialogue: 0,0:16:15.10,0:16:16.09,EN,,0,0,0,,Well I don't want to do that,\nDialogue: 0,0:16:16.11,0:16:17.95,EN,,0,0,0,,because it's actually harder to read to do that,\nDialogue: 0,0:16:18.20,0:16:19.34,EN,,0,0,0,,and it takes up more space.\nDialogue: 0,0:16:19.51,0:16:22.36,EN,,0,0,0,,So I'm going to have that in the instructions written in the controller.\nDialogue: 0,0:16:23.29,0:16:25.24,EN,,0,0,0,,It's going to be implicit what the operations are.\nDialogue: 0,0:16:26.32,0:16:28.57,EN,,0,0,0,,They can be deduced by reading these\nDialogue: 0,0:16:29.16,0:16:31.39,EN,,0,0,0,,and collecting together all the different things that can be done.\nDialogue: 0,0:16:31.69,0:16:33.50,EN,,0,0,0,,We look and see, see...\nDialogue: 0,0:16:33.50,0:16:34.70,EN,,0,0,0,,Well, let's just look at what these things are.\nDialogue: 0,0:16:35.71,0:16:37.29,EN,,0,0,0,,There's a little loop that we go around\nDialogue: 0,0:16:38.24,0:16:40.20,EN,,0,0,0,,which says branch,\nDialogue: 0,0:16:42.64,0:16:46.46,EN,,0,0,0,,this is the representation of the little flap\nDialogue: 0,0:16:46.89,0:16:48.49,EN,,0,0,0,,that decides which way you go here,\nDialogue: 0,0:16:49.10,0:16:58.00,EN,,0,0,0,,if 0, OK, fetch of B, the contents of B,\nDialogue: 0,0:16:58.65,0:17:00.06,EN,,0,0,0,,and if the contents of B is 0,\nDialogue: 0,0:17:00.32,0:17:01.72,EN,,0,0,0,,then go to a place called done.\nDialogue: 0,0:17:03.64,0:17:05.29,EN,,0,0,0,,Now, one thing you're seeing here,\nDialogue: 0,0:17:05.29,0:17:07.40,EN,,0,0,0,,this looks very much like a traditional computer language.\nDialogue: 0,0:17:08.17,0:17:09.55,EN,,0,0,0,,And what you're seeing here\nDialogue: 0,0:17:10.03,0:17:12.00,EN,,0,0,0,,is things like labels\nDialogue: 0,0:17:12.99,0:17:16.86,EN,,0,0,0,,that represent places in a sequence written down as a sequence.\nDialogue: 0,0:17:17.60,0:17:18.94,EN,,0,0,0,,The reason why they're needed\nDialogue: 0,0:17:19.48,0:17:21.15,EN,,0,0,0,,is because over here,\nDialogue: 0,0:17:21.45,0:17:22.81,EN,,0,0,0,,I've written something with loops.\nDialogue: 0,0:17:23.32,0:17:26.11,EN,,0,0,0,,But if I'm writing English text, or something like that,\nDialogue: 0,0:17:26.44,0:17:28.09,EN,,0,0,0,,it's hard to refer to a place.\nDialogue: 0,0:17:28.58,0:17:29.53,EN,,0,0,0,,I don't have arrows.\nDialogue: 0,0:17:30.80,0:17:33.02,EN,,0,0,0,,Arrows are represented by giving names\nDialogue: 0,0:17:33.05,0:17:34.44,EN,,0,0,0,,to the places where the arrows terminate,\nDialogue: 0,0:17:34.57,0:17:36.28,EN,,0,0,0,,and then referring to them by those names.\nDialogue: 0,0:17:37.40,0:17:38.59,EN,,0,0,0,,Now this is just an encoding.\nDialogue: 0,0:17:39.86,0:17:41.88,EN,,0,0,0,,There's nothing magical about things like that.\nDialogue: 0,0:17:43.15,0:17:44.96,EN,,0,0,0,,Next thing we're going to do is we're going to say,\nDialogue: 0,0:17:45.02,0:17:46.84,EN,,0,0,0,,how do we do T gets R?\nDialogue: 0,0:17:47.45,0:17:49.76,EN,,0,0,0,,Oh, that's easy enough, assign.\nDialogue: 0,0:17:52.19,0:17:55.55,EN,,0,0,0,,We assign to T the remainder.\nDialogue: 0,0:17:56.32,0:17:59.24,EN,,0,0,0,,Assign is the name of the button.\nDialogue: 0,0:18:01.47,0:18:02.64,EN,,0,0,0,,That's the button-pusher.\nDialogue: 0,0:18:03.14,0:18:04.97,EN,,0,0,0,,Assign to T the remainder,\nDialogue: 0,0:18:04.99,0:18:06.76,EN,,0,0,0,,and here's the representation of the operation,\nDialogue: 0,0:18:11.74,0:18:17.53,EN,,0,0,0,,when we divide the fetch of A by the fetch of B.\nDialogue: 0,0:18:23.85,0:18:30.99,EN,,0,0,0,,And we're also going to assign to A the fetch of B,\nDialogue: 0,0:18:34.99,0:18:47.88,EN,,0,0,0,,assign to B the result of getting the contents of T.\nDialogue: 0,0:18:49.61,0:18:51.85,EN,,0,0,0,,And now I have to refer to the beginning here.\nDialogue: 0,0:18:53.18,0:18:55.92,EN,,0,0,0,,I see, why don't I call that loop like I have here?\nDialogue: 0,0:19:04.09,0:19:07.04,EN,,0,0,0,,OK? So that's that reference to that arrow.\nDialogue: 0,0:19:07.61,0:19:08.95,EN,,0,0,0,,And when we're done, we're done.\nDialogue: 0,0:19:09.02,0:19:13.07,EN,,0,0,0,,We go to here, which is the end of the thing.\nDialogue: 0,0:19:15.26,0:19:17.04,EN,,0,0,0,,So here's just a written representation\nDialogue: 0,0:19:17.69,0:19:20.86,EN,,0,0,0,,of this fragment of machinery that we've drawn here.\nDialogue: 0,0:19:21.66,0:19:24.84,EN,,0,0,0,,Now the next thing I'd like to do is run this.\nDialogue: 0,0:19:25.49,0:19:26.65,EN,,0,0,0,,I want us to feel it running.\nDialogue: 0,0:19:27.62,0:19:29.80,EN,,0,0,0,,Never done this before, you got to do it once.\nDialogue: 0,0:19:31.01,0:19:32.62,EN,,0,0,0,,So let's take a particular problem.\nDialogue: 0,0:19:33.10,0:19:34.70,EN,,0,0,0,,Suppose we want to compute the GCD\nDialogue: 0,0:19:35.04,0:19:40.68,EN,,0,0,0,,of a equals 30 and b equals 42.\nDialogue: 0,0:19:42.21,0:19:44.92,EN,,0,0,0,,I have no idea what that is right now.\nDialogue: 0,0:19:45.86,0:19:47.60,EN,,0,0,0,,But a 30 and b is 42.\nDialogue: 0,0:19:50.96,0:19:52.09,EN,,0,0,0,,So that's how I start this thing up.\nDialogue: 0,0:19:52.60,0:19:53.90,EN,,0,0,0,,Well, what's the first thing I do?\nDialogue: 0,0:19:54.24,0:19:56.86,EN,,0,0,0,,I say is B equal to 0, no.\nDialogue: 0,0:19:57.59,0:20:02.11,EN,,0,0,0,,Then assign to T the remainder of the fetch of A and the fetch of B.\nDialogue: 0,0:20:02.80,0:20:07.60,EN,,0,0,0,,Well the remainder of 30 when divided by 42 is itself 30.\nDialogue: 0,0:20:11.13,0:20:12.03,EN,,0,0,0,,Push that button.\nDialogue: 0,0:20:12.92,0:20:15.10,EN,,0,0,0,,Now the marble has rolled to here.\nDialogue: 0,0:20:17.10,0:20:18.06,EN,,0,0,0,,A gets B.\nDialogue: 0,0:20:19.02,0:20:20.76,EN,,0,0,0,,That pushes this button.\nDialogue: 0,0:20:21.22,0:20:22.54,EN,,0,0,0,,So 42 moves into here.\nDialogue: 0,0:20:26.59,0:20:27.60,EN,,0,0,0,,B gets T.\nDialogue: 0,0:20:28.36,0:20:29.34,EN,,0,0,0,,Push that button.\nDialogue: 0,0:20:29.87,0:20:30.96,EN,,0,0,0,,The 30 goes here.\nDialogue: 0,0:20:32.57,0:20:33.69,EN,,0,0,0,,Let met just interchange them.\nDialogue: 0,0:20:34.66,0:20:38.27,EN,,0,0,0,,Now let's see, go back to the beginning.\nDialogue: 0,0:20:38.64,0:20:39.72,EN,,0,0,0,,B 0, no.\nDialogue: 0,0:20:40.19,0:20:41.50,EN,,0,0,0,,T gets the remainder.\nDialogue: 0,0:20:43.23,0:20:46.30,EN,,0,0,0,,I suppose the remainder when dividing 42 by 30 is 12.\nDialogue: 0,0:20:47.24,0:20:48.30,EN,,0,0,0,,I push that one.\nDialogue: 0,0:20:48.53,0:20:51.40,EN,,0,0,0,,Next thing I do is allow the 30 to go to here,\nDialogue: 0,0:20:53.90,0:20:55.95,EN,,0,0,0,,push this one, allow the 12 to go to here.\nDialogue: 0,0:20:58.41,0:21:00.38,EN,,0,0,0,,OK? Go around this thing.\nDialogue: 0,0:21:00.38,0:21:01.31,EN,,0,0,0,,Is that done?\nDialogue: 0,0:21:01.53,0:21:02.12,EN,,0,0,0,,No.\nDialogue: 0,0:21:02.36,0:21:08.22,EN,,0,0,0,,How about-- so now I have to find out the remainder of 30 divided by 12.\nDialogue: 0,0:21:08.85,0:21:10.67,EN,,0,0,0,,And I believe that's 6.\nDialogue: 0,0:21:12.42,0:21:15.13,EN,,0,0,0,,So 6 goes here on this button push.\nDialogue: 0,0:21:16.20,0:21:18.25,EN,,0,0,0,,Then the next thing I push is this one,\nDialogue: 0,0:21:18.30,0:21:19.61,EN,,0,0,0,,which the 12 goes into here.\nDialogue: 0,0:21:23.73,0:21:25.09,EN,,0,0,0,,Then I push this button.\nDialogue: 0,0:21:25.09,0:21:26.00,EN,,0,0,0,,The 6 gets into here.\nDialogue: 0,0:21:29.85,0:21:31.68,EN,,0,0,0,,Is 6 equal to 0?\nDialogue: 0,0:21:31.88,0:21:32.49,EN,,0,0,0,,No.\nDialogue: 0,0:21:33.42,0:21:33.98,EN,,0,0,0,,OK.\nDialogue: 0,0:21:34.38,0:21:36.80,EN,,0,0,0,,So then at that point,\nDialogue: 0,0:21:36.89,0:21:38.12,EN,,0,0,0,,the next thing to do is divide it.\nDialogue: 0,0:21:38.14,0:21:39.80,EN,,0,0,0,,Ooh, this has got a remainder of 0.\nDialogue: 0,0:21:40.66,0:21:41.74,EN,,0,0,0,,Looks like we're almost done.\nDialogue: 0,0:21:42.36,0:21:44.36,EN,,0,0,0,,Move the 6 over here next.\nDialogue: 0,0:21:47.00,0:21:48.27,EN,,0,0,0,,0 over here.\nDialogue: 0,0:21:49.09,0:21:50.20,EN,,0,0,0,,Is the answer 0?\nDialogue: 0,0:21:50.20,0:21:50.73,EN,,0,0,0,,Yes.\nDialogue: 0,0:21:51.34,0:21:53.36,EN,,0,0,0,,B is 0, therefore the answer is in A.\nDialogue: 0,0:21:54.28,0:21:55.76,EN,,0,0,0,,The answer is 6.\nDialogue: 0,0:21:56.61,0:21:57.61,EN,,0,0,0,,And indeed that's right,\nDialogue: 0,0:21:57.63,0:21:59.47,EN,,0,0,0,,because if we look at the original problem,\nDialogue: 0,0:22:00.08,0:22:06.64,EN,,0,0,0,,what we have is 30 is 2 times 3 times 5,\nDialogue: 0,0:22:07.00,0:22:11.12,EN,,0,0,0,,and 42 is 2 times 3 times 7.\nDialogue: 0,0:22:11.67,0:22:14.11,EN,,0,0,0,,So the greatest common divisor is 2 times 3,\nDialogue: 0,0:22:14.20,0:22:15.08,EN,,0,0,0,,which is 6.\nDialogue: 0,0:22:18.38,0:22:20.56,EN,,0,0,0,,Now normally, we write one other little line here,\nDialogue: 0,0:22:20.59,0:22:22.52,EN,,0,0,0,,just to make it a little bit clearer,\nDialogue: 0,0:22:22.89,0:22:27.71,EN,,0,0,0,,which is that we leave in a connection saying\nDialogue: 0,0:22:27.85,0:22:31.01,EN,,0,0,0,,that this light is the guy that that flap looks at.\nDialogue: 0,0:22:34.00,0:22:37.32,EN,,0,0,0,,Of course, any real machine has a lot more\nDialogue: 0,0:22:37.85,0:22:40.00,EN,,0,0,0,,complicated things in it than what I've just shown you.\nDialogue: 0,0:22:41.35,0:22:47.16,EN,,0,0,0,,Let's look for a second at the first still store.\nDialogue: 0,0:22:47.98,0:22:48.81,EN,,0,0,0,,Wow.\nDialogue: 0,0:22:50.19,0:22:52.43,EN,,0,0,0,,Well you see, for example, one thing we might want to do\nDialogue: 0,0:22:52.65,0:22:55.85,EN,,0,0,0,,is worry about the operations that are of IO form.\nDialogue: 0,0:22:56.84,0:23:01.42,EN,,0,0,0,,And we may have to collect something from the outside.\nDialogue: 0,0:23:01.98,0:23:03.93,EN,,0,0,0,,So a state machine that we might have,\nDialogue: 0,0:23:04.30,0:23:07.02,EN,,0,0,0,,the controller may have to,\nDialogue: 0,0:23:07.26,0:23:10.56,EN,,0,0,0,,may have to, for example, get a value from something\nDialogue: 0,0:23:10.78,0:23:12.41,EN,,0,0,0,,and put register a to load it up.\nDialogue: 0,0:23:13.49,0:23:15.92,EN,,0,0,0,,I have to master load up register b with another value.\nDialogue: 0,0:23:17.07,0:23:18.60,EN,,0,0,0,,And then later, when I'm done,\nDialogue: 0,0:23:18.99,0:23:20.52,EN,,0,0,0,,I might want to print the answer out.\nDialogue: 0,0:23:21.20,0:23:25.23,EN,,0,0,0,,And of course, that might be either simple or complicated.\nDialogue: 0,0:23:26.09,0:23:28.03,EN,,0,0,0,,I'm writing, assuming print is very simple,\nDialogue: 0,0:23:28.09,0:23:29.29,EN,,0,0,0,,and read is very simple.\nDialogue: 0,0:23:29.88,0:23:31.08,EN,,0,0,0,,But in fact, in the real world,\nDialogue: 0,0:23:31.12,0:23:32.89,EN,,0,0,0,,those are very complicated operations,\nDialogue: 0,0:23:33.08,0:23:35.52,EN,,0,0,0,,fairly, usually much, much larger and more complicated\nDialogue: 0,0:23:35.55,0:23:38.33,EN,,0,0,0,,than the thing you're doing as your problem you're trying to solve.\nDialogue: 0,0:23:41.67,0:23:43.90,EN,,0,0,0,,On the other hand, I can remember a time when,\nDialogue: 0,0:23:44.89,0:23:48.78,EN,,0,0,0,,I remember using IBM 7090 computer of sorts,\nDialogue: 0,0:23:49.05,0:23:53.04,EN,,0,0,0,,where things like read and write of a single object,\nDialogue: 0,0:23:53.08,0:23:54.62,EN,,0,0,0,,a single number, a number,\nDialogue: 0,0:23:55.84,0:23:58.54,EN,,0,0,0,,is a primitive operation of the IO controller.\nDialogue: 0,0:23:59.63,0:24:02.04,EN,,0,0,0,,OK? And so we have that kind of thing in there.\nDialogue: 0,0:24:02.33,0:24:04.67,EN,,0,0,0,,And in such a machine,\nDialogue: 0,0:24:05.44,0:24:06.89,EN,,0,0,0,,well, what are we really doing?\nDialogue: 0,0:24:07.12,0:24:11.60,EN,,0,0,0,,We're just saying that there's a source over here called \"read\"\nDialogue: 0,0:24:12.20,0:24:14.46,EN,,0,0,0,,which is an operation which always has a value.\nDialogue: 0,0:24:14.66,0:24:17.13,EN,,0,0,0,,We have to think about this as always having a value\nDialogue: 0,0:24:17.21,0:24:19.84,EN,,0,0,0,,which can be gated into either register a or b.\nDialogue: 0,0:24:21.66,0:24:23.23,EN,,0,0,0,,And print is some sort of thing\nDialogue: 0,0:24:23.37,0:24:25.02,EN,,0,0,0,,which when you gate it appropriately,\nDialogue: 0,0:24:25.24,0:24:26.43,EN,,0,0,0,,when you push the button on it,\nDialogue: 0,0:24:26.65,0:24:29.61,EN,,0,0,0,,will cause a print of the value that's currently in register a.\nDialogue: 0,0:24:31.66,0:24:32.73,EN,,0,0,0,,Nothing very exciting.\nDialogue: 0,0:24:33.32,0:24:35.20,EN,,0,0,0,,So that's one sort of thing you might want to have.\nDialogue: 0,0:24:35.88,0:24:38.32,EN,,0,0,0,,But these are also other things that are a little bit worrisome.\nDialogue: 0,0:24:38.32,0:24:40.67,EN,,0,0,0,,Like I've used here some complicated mechanisms.\nDialogue: 0,0:24:41.05,0:24:42.48,EN,,0,0,0,,What you see here is remainder.\nDialogue: 0,0:24:43.85,0:24:44.44,EN,,0,0,0,,What is that?\nDialogue: 0,0:24:44.69,0:24:46.41,EN,,0,0,0,,That may not be so obvious how to compute.\nDialogue: 0,0:24:46.92,0:24:48.92,EN,,0,0,0,,It may be something which when you open it up,\nDialogue: 0,0:24:49.48,0:24:50.62,EN,,0,0,0,,you get a whole machine.\nDialogue: 0,0:24:51.84,0:24:53.66,EN,,0,0,0,,OK? In fact, that's true.\nDialogue: 0,0:24:54.54,0:24:59.15,EN,,0,0,0,,For example, if I write down the program for remainder,\nDialogue: 0,0:24:59.44,0:25:02.44,EN,,0,0,0,,the simplest program for it is by repeated subtraction.\nDialogue: 0,0:25:04.78,0:25:05.95,EN,,0,0,0,,Because of course, division can be done\nDialogue: 0,0:25:05.96,0:25:08.99,EN,,0,0,0,,by repeated subtraction of numbers, of integers.\nDialogue: 0,0:25:09.80,0:25:23.58,EN,,0,0,0,,So the remainder of N divided by D\nDialogue: 0,0:25:24.99,0:25:31.44,EN,,0,0,0,,is nothing more than if N is less than D,\nDialogue: 0,0:25:32.24,0:25:33.66,EN,,0,0,0,,then the result is N.\nDialogue: 0,0:25:34.30,0:25:35.90,EN,,0,0,0,,Otherwise, it's the remainder\nDialogue: 0,0:25:41.15,0:25:47.60,EN,,0,0,0,,when we subtract D from N with respect to D,\nDialogue: 0,0:25:48.27,0:25:49.32,EN,,0,0,0,,when divided by D.\nDialogue: 0,0:25:51.28,0:25:55.05,EN,,0,0,0,,Gee, this looks just like the GCD program.\nDialogue: 0,0:25:56.89,0:25:59.48,EN,,0,0,0,,Of course, it's not a very nice way to do remainders.\nDialogue: 0,0:25:59.75,0:26:00.91,EN,,0,0,0,,You'd really want to use something like\nDialogue: 0,0:26:00.92,0:26:05.42,EN,,0,0,0,,binary notation and shift and things like that in a practical computer.\nDialogue: 0,0:26:05.55,0:26:06.97,EN,,0,0,0,,But the point of that is\nDialogue: 0,0:26:07.13,0:26:08.48,EN,,0,0,0,,that if I open this thing up,\nDialogue: 0,0:26:08.92,0:26:10.64,EN,,0,0,0,,I might find inside of it a computer.\nDialogue: 0,0:26:11.88,0:26:12.99,EN,,0,0,0,,Oh, we know how to do that.\nDialogue: 0,0:26:13.51,0:26:14.33,EN,,0,0,0,,We just made one.\nDialogue: 0,0:26:15.64,0:26:17.10,EN,,0,0,0,,And it could be another thing just like this.\nDialogue: 0,0:26:17.40,0:26:18.06,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:26:18.08,0:26:20.00,EN,,0,0,0,,we might want to make a more efficient\nDialogue: 0,0:26:20.01,0:26:21.68,EN,,0,0,0,,or better-structured machine,\nDialogue: 0,0:26:21.85,0:26:23.96,EN,,0,0,0,,or maybe make use of some of the registers more than once,\nDialogue: 0,0:26:24.00,0:26:27.05,EN,,0,0,0,,or some horrible mess like that that hardware designers like to do,\nDialogue: 0,0:26:27.31,0:26:28.60,EN,,0,0,0,,and for very good reasons.\nDialogue: 0,0:26:29.25,0:26:31.56,EN,,0,0,0,,So for example, here's a machine that you see,\nDialogue: 0,0:26:32.52,0:26:34.91,EN,,0,0,0,,which you're not supposed to be able to read.\nDialogue: 0,0:26:35.05,0:26:37.52,EN,,0,0,0,,It's a little bit complicated. OK?\nDialogue: 0,0:26:37.52,0:26:39.87,EN,,0,0,0,,But what it is is the integration of\nDialogue: 0,0:26:40.09,0:26:43.82,EN,,0,0,0,,remainder into the GCD machine.\nDialogue: 0,0:26:44.46,0:26:46.02,EN,,0,0,0,,And it takes, in fact, no more registers.\nDialogue: 0,0:26:46.02,0:26:48.62,EN,,0,0,0,,There are three registers in the datapaths. OK?\nDialogue: 0,0:26:49.05,0:26:50.64,EN,,0,0,0,,But now there's a subtractor.\nDialogue: 0,0:26:51.55,0:26:52.99,EN,,0,0,0,,There are two things that are tested.\nDialogue: 0,0:26:53.02,0:26:55.07,EN,,0,0,0,,Is b equal to 0,\nDialogue: 0,0:26:55.23,0:26:56.56,EN,,0,0,0,,or is t less than b?\nDialogue: 0,0:26:57.25,0:26:59.45,EN,,0,0,0,,And then the controller, which you see over here,\nDialogue: 0,0:27:00.22,0:27:01.76,EN,,0,0,0,,is not much more complicated.\nDialogue: 0,0:27:01.85,0:27:03.87,EN,,0,0,0,,But it has two loops in it,\nDialogue: 0,0:27:04.52,0:27:08.33,EN,,0,0,0,,one of which is the main one for doing the GCD,\nDialogue: 0,0:27:08.40,0:27:10.14,EN,,0,0,0,,and one of which is the subtraction loop\nDialogue: 0,0:27:10.43,0:27:12.80,EN,,0,0,0,,for doing the remainder sub-operation.\nDialogue: 0,0:27:14.03,0:27:15.80,EN,,0,0,0,,And there are ways, of course, of,\nDialogue: 0,0:27:15.96,0:27:18.68,EN,,0,0,0,,if you think about it, taking the remainder program.\nDialogue: 0,0:27:19.92,0:27:21.71,EN,,0,0,0,,If I take remainder, as you see over there\nDialogue: 0,0:27:21.72,0:27:22.83,EN,,0,0,0,,as a lambda expression,\nDialogue: 0,0:27:23.56,0:27:27.02,EN,,0,0,0,,substitute it in for remainder over here in the GCD program,\nDialogue: 0,0:27:28.20,0:27:30.12,EN,,0,0,0,,OK, then do some simplification\nDialogue: 0,0:27:30.32,0:27:33.66,EN,,0,0,0,,by substituting a and b for remainder in there,\nDialogue: 0,0:27:34.46,0:27:35.95,EN,,0,0,0,,then I can unwind this loop.\nDialogue: 0,0:27:36.63,0:27:39.42,EN,,0,0,0,,And I can get this piece of machinery\nDialogue: 0,0:27:40.73,0:27:42.94,EN,,0,0,0,,by basically, a little bit of simplification\nDialogue: 0,0:27:43.36,0:27:45.21,EN,,0,0,0,,algebraic simplification on the lambda expressions.\nDialogue: 0,0:27:48.55,0:27:51.20,EN,,0,0,0,,So I suppose you've seen your first very simple machines now.\nDialogue: 0,0:27:51.95,0:27:53.28,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:28:02.70,0:28:03.10,EN,,0,0,0,,Good.\nDialogue: 0,0:28:05.36,0:28:06.54,EN,,0,0,0,,This looks easy, doesn't it?\nDialogue: 0,0:28:10.14,0:28:11.32,EN,,0,0,0,,Thank you. I suppose, take a break.\nDialogue: 0,0:28:12.54,0:28:24.94,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:28:47.93,0:28:48.70,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:28:49.37,0:28:52.46,EN,,0,0,0,,Now you know how to make an iterative procedure,\nDialogue: 0,0:28:52.54,0:28:54.54,EN,,0,0,0,,or a procedure that yields an iterative process,\nDialogue: 0,0:28:55.18,0:28:56.52,EN,,0,0,0,,turn into a machine.\nDialogue: 0,0:28:57.77,0:29:00.04,EN,,0,0,0,,I suppose the next thing we want to do is worry about things\nDialogue: 0,0:29:00.54,0:29:02.30,EN,,0,0,0,,that reveal recursive processes.\nDialogue: 0,0:29:02.81,0:29:05.05,EN,,0,0,0,,So let's play with a simple factorial procedure.\nDialogue: 0,0:29:11.20,0:29:16.94,EN,,0,0,0,,We define factorial of N to be\nDialogue: 0,0:29:19.63,0:29:24.25,EN,,0,0,0,,if n is 1, the result is 1,\nDialogue: 0,0:29:24.62,0:29:27.69,EN,,0,0,0,,using 1 right now to decrease the amount of work I have to do to simulate it,\nDialogue: 0,0:29:28.12,0:29:33.94,EN,,0,0,0,,else it's times N factorial N minus 1.\nDialogue: 0,0:29:42.52,0:29:46.04,EN,,0,0,0,,And what's different with this program, as you know,\nDialogue: 0,0:29:46.65,0:29:50.36,EN,,0,0,0,,is that after I've computed factorial of N minus 1 here,\nDialogue: 0,0:29:50.67,0:29:52.26,EN,,0,0,0,,I have to do something to the result.\nDialogue: 0,0:29:52.26,0:29:53.68,EN,,0,0,0,,I have to multiply it by N.\nDialogue: 0,0:29:56.00,0:30:00.67,EN,,0,0,0,,So the only way I can visualize what this machine is doing,\nDialogue: 0,0:30:01.08,0:30:02.01,EN,,0,0,0,,because of the fact--\nDialogue: 0,0:30:02.35,0:30:03.18,EN,,0,0,0,,think of it this way,\nDialogue: 0,0:30:03.36,0:30:04.94,EN,,0,0,0,,that I have a machine out here\nDialogue: 0,0:30:05.08,0:30:08.11,EN,,0,0,0,,which somehow needs a factorial machine in order to compute its answer.\nDialogue: 0,0:30:09.32,0:30:11.16,EN,,0,0,0,,But this machine, the outer machine,\nDialogue: 0,0:30:11.20,0:30:13.02,EN,,0,0,0,,has to exist before and after\nDialogue: 0,0:30:13.92,0:30:15.72,EN,,0,0,0,,the factorial machine, which is inside.\nDialogue: 0,0:30:16.80,0:30:17.90,EN,,0,0,0,,Whereas in the iterative case,\nDialogue: 0,0:30:18.75,0:30:20.52,EN,,0,0,0,,the outer machine doesn't need to exist\nDialogue: 0,0:30:20.91,0:30:24.01,EN,,0,0,0,,after the inner machine is running,\nDialogue: 0,0:30:24.83,0:30:26.16,EN,,0,0,0,,because you never need to go back\nDialogue: 0,0:30:26.19,0:30:27.53,EN,,0,0,0,,to the outer machine to do anything.\nDialogue: 0,0:30:28.64,0:30:30.06,EN,,0,0,0,,So here we have a problem\nDialogue: 0,0:30:30.27,0:30:30.97,EN,,0,0,0,,where we have a machine\nDialogue: 0,0:30:31.00,0:30:32.73,EN,,0,0,0,,which has the same machine inside of it,\nDialogue: 0,0:30:33.87,0:30:35.52,EN,,0,0,0,,an infinitely large machine.\nDialogue: 0,0:30:40.39,0:30:43.12,EN,,0,0,0,,And it's got other things inside of it, like a multiplier,\nDialogue: 0,0:30:44.76,0:30:46.03,EN,,0,0,0,,which takes some inputs,\nDialogue: 0,0:30:46.27,0:30:47.77,EN,,0,0,0,,and there's a minus 1 box,\nDialogue: 0,0:30:48.12,0:30:49.31,EN,,0,0,0,,and things like that.\nDialogue: 0,0:30:50.69,0:30:53.72,EN,,0,0,0,,You know, You can imagine that's what it looks like.\nDialogue: 0,0:30:54.37,0:30:56.76,EN,,0,0,0,,But the important thing is that here I have\nDialogue: 0,0:30:57.02,0:30:58.70,EN,,0,0,0,,something that happens before and after,\nDialogue: 0,0:30:58.78,0:31:01.60,EN,,0,0,0,,in the outer machine, the execution of the inner machine.\nDialogue: 0,0:31:02.54,0:31:04.08,EN,,0,0,0,,So this machine has to have a life.\nDialogue: 0,0:31:05.47,0:31:11.44,EN,,0,0,0,,It has to exist on both times sides of this machine.\nDialogue: 0,0:31:13.49,0:31:15.80,EN,,0,0,0,,So somehow, I have to have a place to store\nDialogue: 0,0:31:16.19,0:31:18.19,EN,,0,0,0,,the things that this thing needs to run.\nDialogue: 0,0:31:20.03,0:31:22.09,EN,,0,0,0,,Infinite objects don't exist in the real world.\nDialogue: 0,0:31:24.14,0:31:25.58,EN,,0,0,0,,What we have to do is arrange an illusion\nDialogue: 0,0:31:26.12,0:31:27.48,EN,,0,0,0,,that we have an infinite object,\nDialogue: 0,0:31:27.98,0:31:29.77,EN,,0,0,0,,we have an infinite amount of hardware somewhere.\nDialogue: 0,0:31:31.83,0:31:35.34,EN,,0,0,0,,Now of course, illusion's all that really matters.\nDialogue: 0,0:31:36.28,0:31:37.37,EN,,0,0,0,,If we can arrange\nDialogue: 0,0:31:38.00,0:31:39.84,EN,,0,0,0,,that every time you look at some infinite object,\nDialogue: 0,0:31:39.88,0:31:42.96,EN,,0,0,0,,the part of it that you look at is there,\nDialogue: 0,0:31:44.49,0:31:46.04,EN,,0,0,0,,then it's as infinite as you need it to be.\nDialogue: 0,0:31:47.39,0:31:49.44,EN,,0,0,0,,And of course, one of the things we might want to do,\nDialogue: 0,0:31:49.82,0:31:52.49,EN,,0,0,0,,just look at this thing over here,\nDialogue: 0,0:31:53.00,0:31:54.97,EN,,0,0,0,,is the organization that we've had so far\nDialogue: 0,0:31:56.04,0:31:57.64,EN,,0,0,0,,organization that we've had so far\nDialogue: 0,0:31:57.92,0:32:01.37,EN,,0,0,0,,involves having a part of the machine,\nDialogue: 0,0:32:01.40,0:32:02.33,EN,,0,0,0,,which is the controller,\nDialogue: 0,0:32:03.18,0:32:04.46,EN,,0,0,0,,which sits right over here,\nDialogue: 0,0:32:04.78,0:32:07.61,EN,,0,0,0,,which is perfectly finite and very simple.\nDialogue: 0,0:32:09.17,0:32:10.44,EN,,0,0,0,,We have some datapaths,\nDialogue: 0,0:32:10.46,0:32:12.75,EN,,0,0,0,,which consist of registers and operators.\nDialogue: 0,0:32:13.08,0:32:15.20,EN,,0,0,0,,And what I propose to do here is decompose\nDialogue: 0,0:32:15.48,0:32:16.96,EN,,0,0,0,,the machine into two parts,\nDialogue: 0,0:32:17.36,0:32:19.79,EN,,0,0,0,,such that there is a part which is fundamentally finite,\nDialogue: 0,0:32:20.78,0:32:23.53,EN,,0,0,0,,and some part where a certain amount of infinite stuff can be kept.\nDialogue: 0,0:32:24.23,0:32:25.90,EN,,0,0,0,,On the other hand this is very simple\nDialogue: 0,0:32:26.41,0:32:28.72,EN,,0,0,0,,and really isn't infinite, but it's just very large.\nDialogue: 0,0:32:29.43,0:32:30.40,EN,,0,0,0,,But it's so simple\nDialogue: 0,0:32:30.52,0:32:32.92,EN,,0,0,0,,that it could be cheaply reproduced in such large amounts,\nDialogue: 0,0:32:34.09,0:32:34.92,EN,,0,0,0,,we call it memory,\nDialogue: 0,0:32:35.95,0:32:39.07,EN,,0,0,0,,OK? that we can make a structure called a stack out of it\nDialogue: 0,0:32:39.40,0:32:41.23,EN,,0,0,0,,which will allow us to, in fact,\nDialogue: 0,0:32:41.45,0:32:43.63,EN,,0,0,0,,simulate the existence of an infinite machine\nDialogue: 0,0:32:43.64,0:32:46.96,EN,,0,0,0,,which is made out of a recursive nest of many machines.\nDialogue: 0,0:32:48.34,0:32:50.43,EN,,0,0,0,,And the way it's going to work is that\nDialogue: 0,0:32:50.56,0:32:52.97,EN,,0,0,0,,we're going to store in this place called the stack\nDialogue: 0,0:32:54.30,0:32:57.58,EN,,0,0,0,,the information required after the inner machine runs\nDialogue: 0,0:32:59.18,0:33:01.07,EN,,0,0,0,,to resume the operation of the outer machine.\nDialogue: 0,0:33:03.84,0:33:05.48,EN,,0,0,0,,So it will remember\nDialogue: 0,0:33:05.63,0:33:07.95,EN,,0,0,0,,the important things about the life of the outer machine\nDialogue: 0,0:33:08.04,0:33:10.30,EN,,0,0,0,,that will be needed for this computation.\nDialogue: 0,0:33:11.39,0:33:12.48,EN,,0,0,0,,Since, of course,\nDialogue: 0,0:33:12.75,0:33:16.33,EN,,0,0,0,,these machines are nested in a recursive manner,\nDialogue: 0,0:33:18.33,0:33:23.39,EN,,0,0,0,,then in fact the stack will only be accessed in a manner\nDialogue: 0,0:33:23.45,0:33:26.44,EN,,0,0,0,,which is the last thing that goes in is the first thing that comes out.\nDialogue: 0,0:33:29.33,0:33:30.64,EN,,0,0,0,,So we'll only need to access\nDialogue: 0,0:33:30.80,0:33:32.52,EN,,0,0,0,,some little part of this stack memory.\nDialogue: 0,0:33:34.93,0:33:35.92,EN,,0,0,0,,OK, well, let's do it.\nDialogue: 0,0:33:36.81,0:33:38.41,EN,,0,0,0,,I'm going to build you a datapath now,\nDialogue: 0,0:33:38.44,0:33:39.68,EN,,0,0,0,,and I'm going to write the controller.\nDialogue: 0,0:33:40.37,0:33:42.86,EN,,0,0,0,,And then we're going to execute this to see how you do it.\nDialogue: 0,0:33:43.51,0:33:46.88,EN,,0,0,0,,So the factorial machine isn't so bad.\nDialogue: 0,0:33:47.90,0:33:50.16,EN,,0,0,0,,It's going to have a register called the value,\nDialogue: 0,0:33:52.22,0:33:53.88,EN,,0,0,0,,where the answer is going to be stored,\nDialogue: 0,0:33:54.89,0:33:56.67,EN,,0,0,0,,and a registered called N,\nDialogue: 0,0:33:59.85,0:34:04.16,EN,,0,0,0,,which is where the number I'm taking factorial will be stored, factorial of.\nDialogue: 0,0:34:04.51,0:34:06.57,EN,,0,0,0,,And it will be necessary in some instances\nDialogue: 0,0:34:07.48,0:34:10.52,EN,,0,0,0,,to connect VAL to N.\nDialogue: 0,0:34:11.74,0:34:15.63,EN,,0,0,0,,In fact, one nice case of this is if I just said over here,\nDialogue: 0,0:34:16.38,0:34:19.53,EN,,0,0,0,,N, because that would be right for N equal 1N.\nDialogue: 0,0:34:20.09,0:34:23.26,EN,,0,0,0,,And I could just move the answer over there if that's important.\nDialogue: 0,0:34:23.90,0:34:25.55,EN,,0,0,0,,I'm not worried about that right now.\nDialogue: 0,0:34:26.98,0:34:28.60,EN,,0,0,0,,And there are things I have to be able to do.\nDialogue: 0,0:34:29.06,0:34:31.02,EN,,0,0,0,,Like I have to be able to, as we see here,\nDialogue: 0,0:34:31.21,0:34:34.67,EN,,0,0,0,,multiply N by something in VAL,\nDialogue: 0,0:34:34.91,0:34:37.45,EN,,0,0,0,,because VAL is the result of computing factorial.\nDialogue: 0,0:34:38.68,0:34:40.44,EN,,0,0,0,,And I have to put the result back into VAL.\nDialogue: 0,0:34:41.48,0:34:42.65,EN,,0,0,0,,So here we can see\nDialogue: 0,0:34:42.83,0:34:46.43,EN,,0,0,0,,that the result of computing a factorial\nDialogue: 0,0:34:46.57,0:34:49.20,EN,,0,0,0,,is N times the result of computing a factorial.\nDialogue: 0,0:34:50.69,0:34:53.77,EN,,0,0,0,,VAL will be the representation of the answer of the inner factorial.\nDialogue: 0,0:34:55.19,0:35:00.25,EN,,0,0,0,,And so I'm going to have to have a multiplier here,\nDialogue: 0,0:35:02.36,0:35:07.18,EN,,0,0,0,,which is going to sample the value of N and the value of VAL\nDialogue: 0,0:35:08.64,0:35:15.60,EN,,0,0,0,,OK? and put the result back into VAL like that.\nDialogue: 0,0:35:17.17,0:35:19.39,EN,,0,0,0,,I'm also going to have to be able to see if N is 1.\nDialogue: 0,0:35:21.32,0:35:22.38,EN,,0,0,0,,So I need a light bulb.\nDialogue: 0,0:35:28.20,0:35:30.40,EN,,0,0,0,,And I suppose the other thing I'm going to need to have\nDialogue: 0,0:35:31.02,0:35:32.84,EN,,0,0,0,,is a way of decrementing N.\nDialogue: 0,0:35:34.84,0:35:36.09,EN,,0,0,0,,So I'm going to have a decrementer,\nDialogue: 0,0:35:38.19,0:35:41.39,EN,,0,0,0,,which takes N and is going to put back the result into N.\nDialogue: 0,0:35:46.62,0:35:48.40,EN,,0,0,0,,That's pretty much what I need in my machine.\nDialogue: 0,0:35:49.55,0:35:51.64,EN,,0,0,0,,Now, there's a little bit else I need.\nDialogue: 0,0:35:52.30,0:35:53.58,EN,,0,0,0,,It's a little bit more complicated,\nDialogue: 0,0:35:55.16,0:35:56.88,EN,,0,0,0,,because I'm also going to need a way to store,\nDialogue: 0,0:35:57.16,0:35:59.69,EN,,0,0,0,,to save away, the things that are going to be needed\nDialogue: 0,0:36:01.02,0:36:03.07,EN,,0,0,0,,for resuming the computation of a factorial\nDialogue: 0,0:36:03.10,0:36:04.89,EN,,0,0,0,,after I've done a sub-factorial.\nDialogue: 0,0:36:06.25,0:36:06.86,EN,,0,0,0,,What's that?\nDialogue: 0,0:36:07.23,0:36:08.73,EN,,0,0,0,,One thing I need is N.\nDialogue: 0,0:36:09.85,0:36:12.04,EN,,0,0,0,,So I'm going to build here a thing called a stack.\nDialogue: 0,0:36:14.70,0:36:15.77,EN,,0,0,0,,The stack is\nDialogue: 0,0:36:17.98,0:36:24.97,EN,,0,0,0,,a bunch of stuff that I'm going to write in sequentially.\nDialogue: 0,0:36:27.15,0:36:28.59,EN,,0,0,0,,I don't know how long it is.\nDialogue: 0,0:36:29.15,0:36:31.48,EN,,0,0,0,,The longer it is, the better my illusion of infinity.\nDialogue: 0,0:36:33.23,0:36:35.56,EN,,0,0,0,,And I'm going to have to have a way of getting stuff\nDialogue: 0,0:36:35.60,0:36:37.02,EN,,0,0,0,,out of N and into the stack\nDialogue: 0,0:36:38.12,0:36:39.08,EN,,0,0,0,,and vice versa.\nDialogue: 0,0:36:39.93,0:36:41.74,EN,,0,0,0,,So I'm going to need a connection like this,\nDialogue: 0,0:36:44.41,0:36:45.48,EN,,0,0,0,,which is two-way,\nDialogue: 0,0:36:50.44,0:36:52.22,EN,,0,0,0,,whereby I can save the value of N\nDialogue: 0,0:36:52.24,0:36:55.50,EN,,0,0,0,,and then restore it some other time through that connection.\nDialogue: 0,0:36:56.04,0:36:56.84,EN,,0,0,0,,This is the stack.\nDialogue: 0,0:36:58.10,0:37:01.71,EN,,0,0,0,,I also need a way of remembering\nDialogue: 0,0:37:01.84,0:37:07.72,EN,,0,0,0,,where I was in the computation of factorial in the outer program.\nDialogue: 0,0:37:08.53,0:37:10.06,EN,,0,0,0,,Now in the case of this machine,\nDialogue: 0,0:37:10.76,0:37:13.34,EN,,0,0,0,,it isn't very much a problem.\nDialogue: 0,0:37:14.17,0:37:16.24,EN,,0,0,0,,Factorial always returns,\nDialogue: 0,0:37:16.86,0:37:19.07,EN,,0,0,0,,has to go back to the place where we multiply by N,\nDialogue: 0,0:37:19.34,0:37:20.72,EN,,0,0,0,,except for the last time,\nDialogue: 0,0:37:21.15,0:37:23.02,EN,,0,0,0,,when it has to return to whatever needs the factorial\nDialogue: 0,0:37:23.04,0:37:24.04,EN,,0,0,0,,or go to done or stop.\nDialogue: 0,0:37:25.66,0:37:26.67,EN,,0,0,0,,However, in general,\nDialogue: 0,0:37:27.16,0:37:28.73,EN,,0,0,0,,I'm going to have to remember where I have been,\nDialogue: 0,0:37:29.13,0:37:31.24,EN,,0,0,0,,because I might have computed factorial from somewhere else.\nDialogue: 0,0:37:32.08,0:37:34.89,EN,,0,0,0,,I have to go back to that place and continue there.\nDialogue: 0,0:37:36.07,0:37:38.00,EN,,0,0,0,,So I'm going to have to have some way of taking the place\nDialogue: 0,0:37:38.01,0:37:40.86,EN,,0,0,0,,where the marble is in the finite state controller,\nDialogue: 0,0:37:41.32,0:37:42.64,EN,,0,0,0,,the state of the controller,\nDialogue: 0,0:37:44.22,0:37:46.35,EN,,0,0,0,,and storing that in the stack as well.\nDialogue: 0,0:37:47.40,0:37:49.10,EN,,0,0,0,,And I'm going to have to have ways of restoring that\nDialogue: 0,0:37:49.45,0:37:51.12,EN,,0,0,0,,back to the state of the-- the marble.\nDialogue: 0,0:37:52.14,0:37:54.28,EN,,0,0,0,,So I have to have something that moves the marble to the right place.\nDialogue: 0,0:37:54.70,0:37:56.52,EN,,0,0,0,,Well, we're going to have a place which is the marble now.\nDialogue: 0,0:37:57.87,0:37:59.34,EN,,0,0,0,,And it's called the continue register,\nDialogue: 0,0:38:03.61,0:38:04.52,EN,,0,0,0,,called continue,\nDialogue: 0,0:38:09.16,0:38:10.68,EN,,0,0,0,,which is the place to put the marble\nDialogue: 0,0:38:11.00,0:38:13.05,EN,,0,0,0,,next time I go to continue.\nDialogue: 0,0:38:14.91,0:38:15.92,EN,,0,0,0,,That's what that's for.\nDialogue: 0,0:38:16.14,0:38:18.48,EN,,0,0,0,,And so there's got to be some path from that into the controller.\nDialogue: 0,0:38:22.91,0:38:27.12,EN,,0,0,0,,I also have to have some way of saving that on the stack.\nDialogue: 0,0:38:29.45,0:38:33.10,EN,,0,0,0,,And I have to have some way of setting that up to have various constants,\nDialogue: 0,0:38:34.01,0:38:35.69,EN,,0,0,0,,a certain fixed number of constants.\nDialogue: 0,0:38:36.86,0:38:38.20,EN,,0,0,0,,And that's very easy to arrange.\nDialogue: 0,0:38:38.84,0:38:40.14,EN,,0,0,0,,So let's have some constants here.\nDialogue: 0,0:38:40.18,0:38:41.50,EN,,0,0,0,,We'll call this one after-fact.\nDialogue: 0,0:38:47.32,0:38:48.75,EN,,0,0,0,,And that's a constant\nDialogue: 0,0:38:48.84,0:38:51.50,EN,,0,0,0,,which will get into the continue register,\nDialogue: 0,0:38:52.59,0:38:54.43,EN,,0,0,0,,and also another one called fact-done.\nDialogue: 0,0:39:05.21,0:39:07.82,EN,,0,0,0,,So this is the machine I want to build.\nDialogue: 0,0:39:08.13,0:39:09.48,EN,,0,0,0,,That's its datapaths, at least.\nDialogue: 0,0:39:09.92,0:39:11.69,EN,,0,0,0,,And it mixes a little with the controller here,\nDialogue: 0,0:39:11.85,0:39:14.59,EN,,0,0,0,,because of the fact that I have to remember where I was\nDialogue: 0,0:39:14.70,0:39:16.35,EN,,0,0,0,,and restore myself to that place.\nDialogue: 0,0:39:17.30,0:39:19.93,EN,,0,0,0,,But let's write the program now which represents the controller.\nDialogue: 0,0:39:20.39,0:39:23.47,EN,,0,0,0,,I'm not going to write the define machine thing and the register list,\nDialogue: 0,0:39:23.48,0:39:24.89,EN,,0,0,0,,because that's not very interesting.\nDialogue: 0,0:39:25.13,0:39:27.79,EN,,0,0,0,,I'm just going to write down the sequence of instructions\nDialogue: 0,0:39:27.82,0:39:29.02,EN,,0,0,0,,that constitute the controller.\nDialogue: 0,0:39:31.48,0:39:41.85,EN,,0,0,0,,So we have assign, to set up, continue to done.\nDialogue: 0,0:39:45.15,0:39:45.82,EN,,0,0,0,,We have a loop\nDialogue: 0,0:39:47.34,0:39:56.08,EN,,0,0,0,,which says branch if equal 1 fetch N,\nDialogue: 0,0:40:00.94,0:40:04.11,EN,,0,0,0,,if N is 1, then go to the base step of the induction,\nDialogue: 0,0:40:06.06,0:40:07.20,EN,,0,0,0,,the simple case.\nDialogue: 0,0:40:08.05,0:40:08.76,EN,,0,0,0,,Otherwise,\nDialogue: 0,0:40:08.88,0:40:10.84,EN,,0,0,0,,I have to remember the things that are necessary\nDialogue: 0,0:40:10.88,0:40:13.84,EN,,0,0,0,,to perform a sub-factorial.\nDialogue: 0,0:40:14.67,0:40:16.75,EN,,0,0,0,,I'm going to go over here, and I have to perform a sub-factorial.\nDialogue: 0,0:40:17.57,0:40:19.29,EN,,0,0,0,,So I have to remember what's needed to do that\nDialogue: 0,0:40:19.71,0:40:22.52,EN,,0,0,0,,remember what's needed after I will be done with that.\nDialogue: 0,0:40:24.00,0:40:25.51,EN,,0,0,0,,See, I'm about to do something terrible.\nDialogue: 0,0:40:25.72,0:40:27.39,EN,,0,0,0,,I'm about to change the value of N.\nDialogue: 0,0:40:28.57,0:40:30.40,EN,,0,0,0,,But this guy has to know the old value of N.\nDialogue: 0,0:40:32.14,0:40:33.64,EN,,0,0,0,,But in order to make the sub-factorial work,\nDialogue: 0,0:40:33.66,0:40:34.92,EN,,0,0,0,,I have to change the value of N.\nDialogue: 0,0:40:35.60,0:40:37.10,EN,,0,0,0,,So I have to remember the old value.\nDialogue: 0,0:40:38.00,0:40:39.60,EN,,0,0,0,,And I also have to remember where I've been.\nDialogue: 0,0:40:40.85,0:40:42.32,EN,,0,0,0,,So I save up continue.\nDialogue: 0,0:40:47.70,0:40:51.29,EN,,0,0,0,,And this is an instruction that says, put something in the stack.\nDialogue: 0,0:40:53.12,0:40:55.53,EN,,0,0,0,,Save the contents of the continuation register,\nDialogue: 0,0:40:56.51,0:40:58.00,EN,,0,0,0,,which in this case is done,\nDialogue: 0,0:40:58.88,0:41:00.25,EN,,0,0,0,,because later I'm going to change that, too,\nDialogue: 0,0:41:00.27,0:41:02.78,EN,,0,0,0,,because I need to go back to after-fact, as well.\nDialogue: 0,0:41:03.55,0:41:04.19,EN,,0,0,0,,We'll see that.\nDialogue: 0,0:41:05.04,0:41:09.71,EN,,0,0,0,,We save N, because I'm going to need that for later.\nDialogue: 0,0:41:10.38,0:41:20.54,EN,,0,0,0,,Assign to N the decrement of fetch N.\nDialogue: 0,0:41:23.26,0:41:28.97,EN,,0,0,0,,Assign continue,\nDialogue: 0,0:41:32.12,0:41:33.42,EN,,0,0,0,,we're going to look at this now,\nDialogue: 0,0:41:34.06,0:41:35.61,EN,,0,0,0,,to after, we'll call it.\nDialogue: 0,0:41:37.69,0:41:38.70,EN,,0,0,0,,That's a good name for this,\nDialogue: 0,0:41:38.73,0:41:40.65,EN,,0,0,0,,a little bit easier and shorter, and fits in here.\nDialogue: 0,0:41:53.36,0:41:54.64,EN,,0,0,0,,Now look what I'm doing here.\nDialogue: 0,0:41:55.33,0:41:57.02,EN,,0,0,0,,I'm saying, if the answer is 1,\nDialogue: 0,0:41:58.72,0:41:59.66,EN,,0,0,0,,OK, I'm done.\nDialogue: 0,0:42:00.46,0:42:01.66,EN,,0,0,0,,I'm going to have to just get the answer.\nDialogue: 0,0:42:02.15,0:42:04.88,EN,,0,0,0,,Otherwise, I'm going to save the continuation, save N,\nDialogue: 0,0:42:05.77,0:42:07.32,EN,,0,0,0,,make N one less than N,\nDialogue: 0,0:42:07.60,0:42:09.63,EN,,0,0,0,,remember I'm going to come back to someplace else,\nDialogue: 0,0:42:09.64,0:42:11.48,EN,,0,0,0,,and go back and start doing another factorial.\nDialogue: 0,0:42:13.50,0:42:15.74,EN,,0,0,0,,OK? However, I've got a different machine in me now.\nDialogue: 0,0:42:16.05,0:42:18.38,EN,,0,0,0,,N is 1, and continue is something else.\nDialogue: 0,0:42:22.11,0:42:23.21,EN,,0,0,0,,N is N minus 1.\nDialogue: 0,0:42:23.77,0:42:25.28,EN,,0,0,0,,Now after I'm done with that,\nDialogue: 0,0:42:26.94,0:42:27.76,EN,,0,0,0,,I can go there.\nDialogue: 0,0:42:28.66,0:42:30.46,EN,,0,0,0,,I will restore the old value of N,\nDialogue: 0,0:42:32.68,0:42:36.56,EN,,0,0,0,,which is the opposite of this save over here.\nDialogue: 0,0:42:38.36,0:42:39.88,EN,,0,0,0,,I will restore the continuation.\nDialogue: 0,0:42:49.66,0:42:52.57,EN,,0,0,0,,I will then go to here.\nDialogue: 0,0:42:54.32,0:43:00.86,EN,,0,0,0,,I will assign to the VAL register\nDialogue: 0,0:43:01.16,0:43:08.13,EN,,0,0,0,,the product of N and fetch VAL.\nDialogue: 0,0:43:13.44,0:43:18.30,EN,,0,0,0,,VAL fetch product assign.\nDialogue: 0,0:43:19.79,0:43:21.44,EN,,0,0,0,,And then I will be done.\nDialogue: 0,0:43:21.44,0:43:25.68,EN,,0,0,0,,I will have my answer to the sub-factorial in VAL.\nDialogue: 0,0:43:26.57,0:43:27.37,EN,,0,0,0,,At that point,\nDialogue: 0,0:43:27.66,0:43:28.75,EN,,0,0,0,,I'm going to return\nDialogue: 0,0:43:29.28,0:43:31.61,EN,,0,0,0,,by going to the place where the continuation is pointing.\nDialogue: 0,0:43:33.64,0:43:35.77,EN,,0,0,0,,That says, go to fetch continue.\nDialogue: 0,0:43:45.87,0:43:47.40,EN,,0,0,0,,And then I have finally a base step,\nDialogue: 0,0:43:49.31,0:43:50.51,EN,,0,0,0,,which is the immediate answer.\nDialogue: 0,0:43:50.68,0:43:56.88,EN,,0,0,0,,Assign to VAL fetch N,\nDialogue: 0,0:44:01.36,0:44:02.75,EN,,0,0,0,,and go to fetch continue.\nDialogue: 0,0:44:12.67,0:44:13.55,EN,,0,0,0,,And then I'm done.\nDialogue: 0,0:44:18.64,0:44:21.21,EN,,0,0,0,,Now let's see how this executes on a very simple case,\nDialogue: 0,0:44:22.51,0:44:23.53,EN,,0,0,0,,because then we'll see\nDialogue: 0,0:44:23.66,0:44:26.52,EN,,0,0,0,,the use of this stack to do the job we need.\nDialogue: 0,0:44:26.89,0:44:28.22,EN,,0,0,0,,This is statically what it's doing,\nDialogue: 0,0:44:28.22,0:44:29.80,EN,,0,0,0,,but we have look dynamically at this.\nDialogue: 0,0:44:31.34,0:44:32.09,EN,,0,0,0,,So let's see.\nDialogue: 0,0:44:32.30,0:44:34.56,EN,,0,0,0,,First thing we do is continue gets done.\nDialogue: 0,0:44:36.73,0:44:38.09,EN,,0,0,0,,The way that happened is I pushed this.\nDialogue: 0,0:44:38.30,0:44:39.60,EN,,0,0,0,,Let's call that done the way I have it.\nDialogue: 0,0:44:46.22,0:44:47.03,EN,,0,0,0,,I push that button.\nDialogue: 0,0:44:47.03,0:44:48.11,EN,,0,0,0,,Done goes into there.\nDialogue: 0,0:44:48.95,0:44:53.71,EN,,0,0,0,,Now I also have to set this thing up to have an initial value.\nDialogue: 0,0:44:53.85,0:44:58.08,EN,,0,0,0,,Let's consider a factorial of three,\nDialogue: 0,0:44:58.38,0:44:59.24,EN,,0,0,0,,a simple case.\nDialogue: 0,0:45:00.54,0:45:04.04,EN,,0,0,0,,And we're going to start out with our stack growing over here.\nDialogue: 0,0:45:05.90,0:45:07.76,EN,,0,0,0,,Stacks have their own little internal state\nDialogue: 0,0:45:07.79,0:45:09.05,EN,,0,0,0,,saying where they are,\nDialogue: 0,0:45:09.80,0:45:11.64,EN,,0,0,0,,where the next place I'm going to write is.\nDialogue: 0,0:45:12.77,0:45:14.59,EN,,0,0,0,,So now we say, is N 1?\nDialogue: 0,0:45:14.76,0:45:15.71,EN,,0,0,0,,The answer is no.\nDialogue: 0,0:45:16.11,0:45:18.56,EN,,0,0,0,,So now I'm going to save continue, bang.\nDialogue: 0,0:45:19.15,0:45:20.65,EN,,0,0,0,,Now that done goes in here.\nDialogue: 0,0:45:22.08,0:45:23.55,EN,,0,0,0,,And this moves to here,\nDialogue: 0,0:45:24.88,0:45:26.14,EN,,0,0,0,,the next place I'm going to write.\nDialogue: 0,0:45:26.66,0:45:28.78,EN,,0,0,0,,Save N 3.\nDialogue: 0,0:45:29.95,0:45:30.32,EN,,0,0,0,,OK?\nDialogue: 0,0:45:30.67,0:45:33.61,EN,,0,0,0,,Assign to N the decrement of N.\nDialogue: 0,0:45:33.96,0:45:35.37,EN,,0,0,0,,That means I've pushed this button.\nDialogue: 0,0:45:35.94,0:45:37.32,EN,,0,0,0,,This becomes 2.\nDialogue: 0,0:45:38.73,0:45:42.28,EN,,0,0,0,,OK? Assign to continue aft.\nDialogue: 0,0:45:42.58,0:45:43.61,EN,,0,0,0,,So I've pushed that button.\nDialogue: 0,0:45:43.61,0:45:44.54,EN,,0,0,0,,Aft goes in here.\nDialogue: 0,0:45:49.14,0:45:53.93,EN,,0,0,0,,OK, now go to loop, bang, so up to here.\nDialogue: 0,0:45:54.83,0:45:57.08,EN,,0,0,0,,Is N 1? No\nDialogue: 0,0:45:57.78,0:45:59.23,EN,,0,0,0,,So I have to save continue.\nDialogue: 0,0:45:59.49,0:46:00.27,EN,,0,0,0,,What's continue?\nDialogue: 0,0:46:00.60,0:46:01.53,EN,,0,0,0,,Continue is aft.\nDialogue: 0,0:46:01.53,0:46:02.32,EN,,0,0,0,,Push this button.\nDialogue: 0,0:46:02.78,0:46:03.95,EN,,0,0,0,,So this moves to here.\nDialogue: 0,0:46:08.49,0:46:09.74,EN,,0,0,0,,I have to save N.\nDialogue: 0,0:46:10.51,0:46:12.12,EN,,0,0,0,,N is over here. I got to 2.\nDialogue: 0,0:46:12.28,0:46:13.37,EN,,0,0,0,,Push that button.\nDialogue: 0,0:46:13.85,0:46:15.24,EN,,0,0,0,,So a 2 gets written there.\nDialogue: 0,0:46:16.05,0:46:17.64,EN,,0,0,0,,And then this thing moves down here.\nDialogue: 0,0:46:20.06,0:46:22.60,EN,,0,0,0,,OK, save N. Assign N to the decrement of N.\nDialogue: 0,0:46:24.60,0:46:25.46,EN,,0,0,0,,This becomes a 1.\nDialogue: 0,0:46:29.24,0:46:30.54,EN,,0,0,0,,Assign continue to aft.\nDialogue: 0,0:46:31.37,0:46:34.48,EN,,0,0,0,,A-F-T gets written there again.\nDialogue: 0,0:46:34.96,0:46:35.64,EN,,0,0,0,,Go to loop.\nDialogue: 0,0:46:36.52,0:46:37.74,EN,,0,0,0,,Is N equal to 1?\nDialogue: 0,0:46:37.93,0:46:39.52,EN,,0,0,0,,Oh, yes, the answer is 1.\nDialogue: 0,0:46:41.04,0:46:43.26,EN,,0,0,0,,OK, go to base step.\nDialogue: 0,0:46:44.16,0:46:45.77,EN,,0,0,0,,Assign to VAL fetch of N.\nDialogue: 0,0:46:46.56,0:46:50.72,EN,,0,0,0,,Bang, 1 gets put in there. OK?\nDialogue: 0,0:46:51.10,0:46:52.20,EN,,0,0,0,,Go to fetch continue.\nDialogue: 0,0:46:52.20,0:46:53.53,EN,,0,0,0,,So we look in continue.\nDialogue: 0,0:46:53.68,0:46:56.06,EN,,0,0,0,,Basically, I'm pushing a button over here that goes to the controller.\nDialogue: 0,0:46:56.67,0:46:58.28,EN,,0,0,0,,The continue becomes aft,\nDialogue: 0,0:46:58.32,0:47:00.25,EN,,0,0,0,,and all of a sudden, the program's running here.\nDialogue: 0,0:47:02.64,0:47:05.63,EN,,0,0,0,,I now have to restore the outer version of factorial.\nDialogue: 0,0:47:06.65,0:47:07.55,EN,,0,0,0,,So we go here.\nDialogue: 0,0:47:07.55,0:47:09.48,EN,,0,0,0,,We say, restore N.\nDialogue: 0,0:47:10.32,0:47:13.04,EN,,0,0,0,,So restore N means take the contents that's here.\nDialogue: 0,0:47:13.94,0:47:18.17,EN,,0,0,0,,Push this button, and it goes into here, 2,\nDialogue: 0,0:47:18.56,0:47:20.04,EN,,0,0,0,,and the pointer moves up.\nDialogue: 0,0:47:21.98,0:47:24.49,EN,,0,0,0,,Restore continue, pretty easy.\nDialogue: 0,0:47:24.81,0:47:26.49,EN,,0,0,0,,Go push this button.\nDialogue: 0,0:47:27.02,0:47:28.92,EN,,0,0,0,,And then aft gets written in here again.\nDialogue: 0,0:47:31.28,0:47:32.64,EN,,0,0,0,,That means this thing moves up.\nDialogue: 0,0:47:32.64,0:47:35.19,EN,,0,0,0,,I've gotten rid of something else on my stack.\nDialogue: 0,0:47:42.24,0:47:43.47,EN,,0,0,0,,Right, then I go to here,\nDialogue: 0,0:47:43.87,0:47:47.15,EN,,0,0,0,,which says, assign to VAL the product of N and VAL.\nDialogue: 0,0:47:47.85,0:47:50.57,EN,,0,0,0,,So I push this button over here, bang.\nDialogue: 0,0:47:50.97,0:47:52.91,EN,,0,0,0,,2 times 1 gives me a 2,\nDialogue: 0,0:47:54.01,0:47:54.75,EN,,0,0,0,,get written there.\nDialogue: 0,0:47:55.76,0:47:57.20,EN,,0,0,0,,OK? Go to fetch continue.\nDialogue: 0,0:47:57.54,0:47:59.85,EN,,0,0,0,,Continue is aft. I go to aft.\nDialogue: 0,0:48:01.15,0:48:03.88,EN,,0,0,0,,OK? Aft says restore N.\nDialogue: 0,0:48:04.36,0:48:05.72,EN,,0,0,0,,Do your restore N,\nDialogue: 0,0:48:05.87,0:48:08.44,EN,,0,0,0,,means I take the value over here, which is 3,\nDialogue: 0,0:48:09.24,0:48:10.33,EN,,0,0,0,,push this up to here,\nDialogue: 0,0:48:10.60,0:48:15.50,EN,,0,0,0,,and move it into here, N.\nDialogue: 0,0:48:16.25,0:48:17.34,EN,,0,0,0,,Now it's pushing that button.\nDialogue: 0,0:48:18.01,0:48:19.90,EN,,0,0,0,,The next thing I do is restore continue.\nDialogue: 0,0:48:20.20,0:48:22.20,EN,,0,0,0,,Continue is now going to become done.\nDialogue: 0,0:48:22.83,0:48:26.78,EN,,0,0,0,,So this moves up here when I push this button.\nDialogue: 0,0:48:27.13,0:48:29.72,EN,,0,0,0,,Done may or may be there anymore,\nDialogue: 0,0:48:29.72,0:48:31.55,EN,,0,0,0,,I'm not interested, but it certainly is here.\nDialogue: 0,0:48:35.80,0:48:38.12,EN,,0,0,0,,Next thing I do is assign to VAL\nDialogue: 0,0:48:38.43,0:48:40.76,EN,,0,0,0,,the product of the fetch of N and the fetch of VAL.\nDialogue: 0,0:48:41.44,0:48:44.30,EN,,0,0,0,,That's pushing this button over here, bang.\nDialogue: 0,0:48:44.30,0:48:45.77,EN,,0,0,0,,2 times 3 is 6.\nDialogue: 0,0:48:46.52,0:48:47.87,EN,,0,0,0,,So I get a 6 over here.\nDialogue: 0,0:48:50.97,0:48:53.40,EN,,0,0,0,,OK? And go to fetch continue,\nDialogue: 0,0:48:53.48,0:48:54.83,EN,,0,0,0,,whoops, I go to done, and I'm done.\nDialogue: 0,0:48:55.02,0:48:56.09,EN,,0,0,0,,And my answer is 6,\nDialogue: 0,0:48:56.60,0:48:57.82,EN,,0,0,0,,as you can see in the VAL register.\nDialogue: 0,0:48:58.95,0:48:59.82,EN,,0,0,0,,And in fact,\nDialogue: 0,0:49:00.91,0:49:03.34,EN,,0,0,0,,the stack is in the state it originally was in.\nDialogue: 0,0:49:08.20,0:49:10.70,EN,,0,0,0,,Now there's a bit of discipline in using these things like stacks\nDialogue: 0,0:49:11.20,0:49:12.27,EN,,0,0,0,,that we have to be careful of.\nDialogue: 0,0:49:13.62,0:49:15.52,EN,,0,0,0,,And we'll see that in the next segment.\nDialogue: 0,0:49:16.26,0:49:18.46,EN,,0,0,0,,But first I want to ask if there are any questions for this.\nDialogue: 0,0:49:28.56,0:49:29.64,EN,,0,0,0,,Are there any questions?\nDialogue: 0,0:49:30.17,0:49:30.63,EN,,0,0,0,,Yes, Ron.\nDialogue: 0,0:49:30.63,0:49:33.37,EN,,0,0,0,,AUDIENCE: What happens when you roll off the end of the stack with--\nDialogue: 0,0:49:33.39,0:49:34.62,EN,,0,0,0,,PROFESSOR: What do you mean, roll off of?\nDialogue: 0,0:49:35.03,0:49:37.50,EN,,0,0,0,,AUDIENCE: Well, the largest number-- a larger starting point of N\nDialogue: 0,0:49:37.52,0:49:38.72,EN,,0,0,0,,requires more memory, correct?\nDialogue: 0,0:49:38.86,0:49:39.44,EN,,0,0,0,,PROFESSOR: Oh, yes.\nDialogue: 0,0:49:39.44,0:49:41.12,EN,,0,0,0,,Well, I need to have a long enough stack.\nDialogue: 0,0:49:41.53,0:49:43.20,EN,,0,0,0,,You say, what if I violate my illusion?\nDialogue: 0,0:49:43.84,0:49:44.12,EN,,0,0,0,,AUDIENCE: Yes.\nDialogue: 0,0:49:44.55,0:49:46.73,EN,,0,0,0,,PROFESSOR: Well, then the magic doesn't work. OK?\nDialogue: 0,0:49:47.96,0:49:51.00,EN,,0,0,0,,The truth of the matter is that every machine is finite.\nDialogue: 0,0:49:51.64,0:49:53.72,EN,,0,0,0,,And for a procedure like this,\nDialogue: 0,0:49:54.17,0:49:58.86,EN,,0,0,0,,there's a limit to the number of sub-factorials I could have.\nDialogue: 0,0:49:59.95,0:50:02.48,EN,,0,0,0,,Remember when we were doing the y-operator a while ago,\nDialogue: 0,0:50:02.80,0:50:06.22,EN,,0,0,0,,we pointed out that there was a sequence of exponentiation procedures,\nDialogue: 0,0:50:06.25,0:50:08.09,EN,,0,0,0,,each of which was a little better than the previous one.\nDialogue: 0,0:50:08.72,0:50:11.60,EN,,0,0,0,,Well, we're now seeing how we implement that mathematical idea.\nDialogue: 0,0:50:13.09,0:50:14.19,EN,,0,0,0,,The limiting process\nDialogue: 0,0:50:14.35,0:50:16.33,EN,,0,0,0,,is only so good as as far as you take the limit.\nDialogue: 0,0:50:17.99,0:50:19.42,EN,,0,0,0,,If you think about it, what am I using here?\nDialogue: 0,0:50:19.42,0:50:22.65,EN,,0,0,0,,I'm using about two chunks, pieces of memory\nDialogue: 0,0:50:23.04,0:50:27.07,EN,,0,0,0,,for iteration for every recursion of this process.\nDialogue: 0,0:50:29.10,0:50:31.71,EN,,0,0,0,,If we try to compute factorial of 10,000,\nDialogue: 0,0:50:31.72,0:50:32.81,EN,,0,0,0,,that's not a lot of memory.\nDialogue: 0,0:50:33.18,0:50:34.68,EN,,0,0,0,,On the other hand, it's an awful big number.\nDialogue: 0,0:50:35.95,0:50:38.41,EN,,0,0,0,,So the question is, is that a valuable thing in this case.\nDialogue: 0,0:50:39.18,0:50:42.19,EN,,0,0,0,,But it really turns out not to be a terrible limit,\nDialogue: 0,0:50:42.22,0:50:43.53,EN,,0,0,0,,because memory is el cheapo,\nDialogue: 0,0:50:44.16,0:50:45.34,EN,,0,0,0,,and people are pretty expensive.\nDialogue: 0,0:50:48.13,0:50:50.22,EN,,0,0,0,,OK, thank you, let's take a break.\nDialogue: 0,0:50:50.78,0:51:07.60,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:51:56.11,0:51:57.04,EN,,0,0,0,,PROFESSOR: Well, let's see.\nDialogue: 0,0:51:58.70,0:52:03.37,EN,,0,0,0,,What I've shown you now is how to do a simple iterative process\nDialogue: 0,0:52:03.69,0:52:05.31,EN,,0,0,0,,and a simple recursive process.\nDialogue: 0,0:52:05.64,0:52:08.68,EN,,0,0,0,,I just want to summarize the design of simple machines\nDialogue: 0,0:52:09.63,0:52:11.12,EN,,0,0,0,,for specific applications\nDialogue: 0,0:52:11.21,0:52:13.58,EN,,0,0,0,,by showing you a little bit more complicated design,\nDialogue: 0,0:52:13.96,0:52:17.13,EN,,0,0,0,,that of a thing that does doubly recursive Fibonacci,\nDialogue: 0,0:52:17.23,0:52:19.88,EN,,0,0,0,,because it will indicate to us, and we'll understand,\nDialogue: 0,0:52:20.04,0:52:22.68,EN,,0,0,0,,a bit about the conventions required\nDialogue: 0,0:52:22.76,0:52:25.04,EN,,0,0,0,,for making stacks operate correctly.\nDialogue: 0,0:52:26.40,0:52:27.11,EN,,0,0,0,,So let's see.\nDialogue: 0,0:52:27.11,0:52:28.27,EN,,0,0,0,,I'm just going to write down, first of all,\nDialogue: 0,0:52:28.30,0:52:29.71,EN,,0,0,0,,the program I'm going to translate.\nDialogue: 0,0:52:34.15,0:52:36.52,EN,,0,0,0,,I need a Fibonacci procedure,\nDialogue: 0,0:52:39.23,0:52:41.58,EN,,0,0,0,,it's very simple, which says, if\nDialogue: 0,0:52:44.60,0:52:48.56,EN,,0,0,0,,N is less than 2, the result is N,\nDialogue: 0,0:52:49.26,0:52:55.34,EN,,0,0,0,,otherwise it's the sum of Fib of N minus 1\nDialogue: 0,0:52:58.44,0:52:59.85,EN,,0,0,0,,and Fib of N minus 2.\nDialogue: 0,0:53:07.05,0:53:09.29,EN,,0,0,0,,That's the plan I have here.\nDialogue: 0,0:53:09.29,0:53:12.56,EN,,0,0,0,,And we're just going to write down the controller for such a machine.\nDialogue: 0,0:53:13.07,0:53:15.53,EN,,0,0,0,,We're going to assume that there are registers, N,\nDialogue: 0,0:53:15.56,0:53:19.15,EN,,0,0,0,,which holds the number we're taking Fibonacci of,\nDialogue: 0,0:53:19.82,0:53:21.80,EN,,0,0,0,,VAL, which is where the answer is going to get put,\nDialogue: 0,0:53:22.17,0:53:24.97,EN,,0,0,0,,and continue, which is the thing that's linked to the controller,\nDialogue: 0,0:53:26.11,0:53:26.81,EN,,0,0,0,,like before.\nDialogue: 0,0:53:26.96,0:53:29.21,EN,,0,0,0,,But I'm not going to draw another physical datapath,\nDialogue: 0,0:53:31.53,0:53:34.00,EN,,0,0,0,,because it's pretty much the same as the last one you've seen.\nDialogue: 0,0:53:34.36,0:53:37.84,EN,,0,0,0,,And of course, one of the most amazing things about computation\nDialogue: 0,0:53:38.75,0:53:39.88,EN,,0,0,0,,is that after a while,\nDialogue: 0,0:53:40.08,0:53:41.93,EN,,0,0,0,,you build up a little more features and a few more features,\nDialogue: 0,0:53:41.95,0:53:43.32,EN,,0,0,0,,and all of the sudden, you've got everything you need.\nDialogue: 0,0:53:44.75,0:53:47.60,EN,,0,0,0,,So it's remarkable that it just gets there so fast.\nDialogue: 0,0:53:48.17,0:53:50.84,EN,,0,0,0,,I don't need much more to make a universal computer.\nDialogue: 0,0:53:51.81,0:53:54.68,EN,,0,0,0,,But in any case, let's look at the controller for the Fibonacci thing.\nDialogue: 0,0:53:55.06,0:53:57.07,EN,,0,0,0,,First thing I want to do is\nDialogue: 0,0:53:57.32,0:54:02.52,EN,,0,0,0,,start the thing up by assign to continue\nDialogue: 0,0:54:07.13,0:54:10.28,EN,,0,0,0,,a place called done, called Fib-done here.\nDialogue: 0,0:54:14.14,0:54:15.53,EN,,0,0,0,,So that means that somewhere over here,\nDialogue: 0,0:54:15.55,0:54:18.48,EN,,0,0,0,,I'm going to have a label, Fib-done,\nDialogue: 0,0:54:19.71,0:54:21.10,EN,,0,0,0,,which is the place where I go\nDialogue: 0,0:54:21.23,0:54:22.44,EN,,0,0,0,,when I want the machine to stop.\nDialogue: 0,0:54:24.00,0:54:24.86,EN,,0,0,0,,That's what that is.\nDialogue: 0,0:54:25.92,0:54:26.89,EN,,0,0,0,,And I'm going to make up a loop.\nDialogue: 0,0:54:31.11,0:54:34.25,EN,,0,0,0,,It's a place I'm going to go to in order to start up computing a Fib.\nDialogue: 0,0:54:35.47,0:54:36.86,EN,,0,0,0,,Whatever is in N at this point,\nDialogue: 0,0:54:37.39,0:54:38.99,EN,,0,0,0,,Fibonacci will be computed of,\nDialogue: 0,0:54:39.13,0:54:42.01,EN,,0,0,0,,and we will return to the place specified by continue.\nDialogue: 0,0:54:44.80,0:54:48.40,EN,,0,0,0,,So what you're going to see here at this place,\nDialogue: 0,0:54:48.44,0:54:50.48,EN,,0,0,0,,what I want here is the contract\nDialogue: 0,0:54:50.97,0:54:54.25,EN,,0,0,0,,that says, I'm going to write this with a comment syntax,\nDialogue: 0,0:54:54.57,0:55:00.99,EN,,0,0,0,,the contract is N contains arg, the argument.\nDialogue: 0,0:55:02.10,0:55:09.82,EN,,0,0,0,,Continue is the recipient.\nDialogue: 0,0:55:13.36,0:55:14.29,EN,,0,0,0,,And that's where it is.\nDialogue: 0,0:55:15.71,0:55:18.96,EN,,0,0,0,,At this point, if I ever go to this place,\nDialogue: 0,0:55:19.24,0:55:21.04,EN,,0,0,0,,I'm expecting this to be true,\nDialogue: 0,0:55:21.52,0:55:23.32,EN,,0,0,0,,the argument for computing the Fibonacci.\nDialogue: 0,0:55:24.82,0:55:26.83,EN,,0,0,0,,Now the next thing I want to do is to branch.\nDialogue: 0,0:55:30.22,0:55:32.22,EN,,0,0,0,,And if N is less than 2--\nDialogue: 0,0:55:35.07,0:55:37.44,EN,,0,0,0,,by the way, I'm using what looks like Lisp syntax.\nDialogue: 0,0:55:38.73,0:55:39.63,EN,,0,0,0,,This is not Lisp.\nDialogue: 0,0:55:41.31,0:55:42.38,EN,,0,0,0,,This does not run.\nDialogue: 0,0:55:42.75,0:55:45.47,EN,,0,0,0,,What I'm writing here does not run as a simple Lisp program.\nDialogue: 0,0:55:46.12,0:55:49.31,EN,,0,0,0,,This is a representation of another language.\nDialogue: 0,0:55:49.71,0:55:52.25,EN,,0,0,0,,The reason I'm using the syntax of parentheses and so on\nDialogue: 0,0:55:52.40,0:55:54.70,EN,,0,0,0,,is because I tend to use a Lisp system\nDialogue: 0,0:55:55.32,0:55:57.34,EN,,0,0,0,,to write an interpreter for this\nDialogue: 0,0:55:57.82,0:55:59.18,EN,,0,0,0,,which allows me to simulate\nDialogue: 0,0:55:59.29,0:56:00.91,EN,,0,0,0,,the machine I'm trying to build.\nDialogue: 0,0:56:03.38,0:56:06.24,EN,,0,0,0,,I don't want to confuse this to think that this is Lisp code.\nDialogue: 0,0:56:06.94,0:56:08.60,EN,,0,0,0,,It's just I'm using a lot of the pieces of Lisp.\nDialogue: 0,0:56:09.51,0:56:10.84,EN,,0,0,0,,I'm embedding a language in Lisp,\nDialogue: 0,0:56:11.02,0:56:12.44,EN,,0,0,0,,using Lisp as pieces\nDialogue: 0,0:56:12.72,0:56:15.12,EN,,0,0,0,,to make my process of making my simulator easy.\nDialogue: 0,0:56:16.62,0:56:18.56,EN,,0,0,0,,So I'm inheriting from Lisp all of its properties.\nDialogue: 0,0:56:19.10,0:56:21.53,EN,,0,0,0,,Fetch of N 2,\nDialogue: 0,0:56:21.77,0:56:23.72,EN,,0,0,0,,I want to go to a place called immediate answer.\nDialogue: 0,0:56:26.20,0:56:27.29,EN,,0,0,0,,It's the base step.\nDialogue: 0,0:56:33.15,0:56:34.35,EN,,0,0,0,,Now, that's somewhere over here,\nDialogue: 0,0:56:35.92,0:56:36.89,EN,,0,0,0,,just above done.\nDialogue: 0,0:56:37.75,0:56:38.64,EN,,0,0,0,,And we'll see it later.\nDialogue: 0,0:56:39.42,0:56:40.70,EN,,0,0,0,,Now, in the general case,\nDialogue: 0,0:56:40.72,0:56:42.44,EN,,0,0,0,,which is the part I'm going to write down now,\nDialogue: 0,0:56:43.13,0:56:44.19,EN,,0,0,0,,let's just do it.\nDialogue: 0,0:56:44.91,0:56:48.20,EN,,0,0,0,,Well, first of all, I'm going to have to call Fibonacci twice.\nDialogue: 0,0:56:49.42,0:56:52.54,EN,,0,0,0,,In each case-- well, in one case at least,\nDialogue: 0,0:56:52.78,0:56:53.95,EN,,0,0,0,,I'm going to have to know what to do\nDialogue: 0,0:56:53.96,0:56:55.36,EN,,0,0,0,,to come back and do the next one.\nDialogue: 0,0:56:56.31,0:56:58.36,EN,,0,0,0,,I have to remember,\nDialogue: 0,0:56:59.20,0:57:01.23,EN,,0,0,0,,have I done the first Fib,\nDialogue: 0,0:57:01.26,0:57:02.54,EN,,0,0,0,,or have I done the second one?\nDialogue: 0,0:57:04.50,0:57:07.04,EN,,0,0,0,,Do I have to come back to the place where I do the second Fib,\nDialogue: 0,0:57:07.07,0:57:09.08,EN,,0,0,0,,or do I have to come back to the place where I do the add?\nDialogue: 0,0:57:10.12,0:57:12.11,EN,,0,0,0,,In both cases I going to need, I don't\nDialogue: 0,0:57:12.14,0:57:14.46,EN,,0,0,0,,In the first case, over the first Fibonacci,\nDialogue: 0,0:57:14.51,0:57:16.98,EN,,0,0,0,,I'm going to need the value of N for computing for the second one.\nDialogue: 0,0:57:19.84,0:57:21.58,EN,,0,0,0,,So I have to store some of these things up.\nDialogue: 0,0:57:23.36,0:57:24.89,EN,,0,0,0,,So first I'm going to save continue.\nDialogue: 0,0:57:26.19,0:57:27.32,EN,,0,0,0,,That's who needs the answer.\nDialogue: 0,0:57:31.32,0:57:32.46,EN,,0,0,0,,And the reason I'm doing that\nDialogue: 0,0:57:32.48,0:57:34.20,EN,,0,0,0,,is because I'm about to assign continue\nDialogue: 0,0:57:40.11,0:57:44.32,EN,,0,0,0,,to the place which is the place I want to go to after.\nDialogue: 0,0:57:46.83,0:57:50.27,EN,,0,0,0,,Let's call it Fib-N-minus-1,\nDialogue: 0,0:57:51.04,0:57:53.76,EN,,0,0,0,,big long name, classic Lisp name.\nDialogue: 0,0:57:57.36,0:58:00.22,EN,,0,0,0,,Because I'm going to compute the first Fib of N minus 1,\nDialogue: 0,0:58:00.84,0:58:01.72,EN,,0,0,0,,and then after that,\nDialogue: 0,0:58:01.72,0:58:03.29,EN,,0,0,0,,I want to come back and do something else.\nDialogue: 0,0:58:03.96,0:58:06.52,EN,,0,0,0,,That's the place I want to go to after I've done\nDialogue: 0,0:58:07.55,0:58:09.48,EN,,0,0,0,,the first Fibonacci calculation.\nDialogue: 0,0:58:11.52,0:58:13.13,EN,,0,0,0,,And I want to do a save of N,\nDialogue: 0,0:58:14.41,0:58:17.26,EN,,0,0,0,,because I'm going to need it later, after that.\nDialogue: 0,0:58:19.13,0:58:20.54,EN,,0,0,0,,Now I'm going to, at this point,\nDialogue: 0,0:58:20.67,0:58:22.84,EN,,0,0,0,,get ready to do the Fibonacci of N minus 1.\nDialogue: 0,0:58:23.02,0:58:33.95,EN,,0,0,0,,So assign to N the difference of the fetch of N and 1.\nDialogue: 0,0:58:38.11,0:58:40.27,EN,,0,0,0,,Now I'm ready to go back to doing the Fib loop.\nDialogue: 0,0:58:47.18,0:58:49.87,EN,,0,0,0,,Do I have... Have I satisfied my contract?\nDialogue: 0,0:58:50.40,0:58:51.50,EN,,0,0,0,,And the answer is yes.\nDialogue: 0,0:58:51.77,0:58:55.12,EN,,0,0,0,,N contains N minus 1, which is what I need.\nDialogue: 0,0:58:56.43,0:59:00.09,EN,,0,0,0,,OK? Continue contains a place I want to go to when I'm done\nDialogue: 0,0:59:01.28,0:59:03.07,EN,,0,0,0,,with calculating FIB N minus 1.\nDialogue: 0,0:59:04.10,0:59:05.44,EN,,0,0,0,,So I've satisfied the contract.\nDialogue: 0,0:59:05.44,0:59:09.02,EN,,0,0,0,,And therefore, I can write down here a tag, after, a label,\nDialogue: 0,0:59:11.47,0:59:17.56,EN,,0,0,0,,after-Fib-N-minus-1.\nDialogue: 0,0:59:20.49,0:59:21.63,EN,,0,0,0,,Now what am I going to do here?\nDialogue: 0,0:59:22.69,0:59:23.61,EN,,0,0,0,,Here's a place\nDialogue: 0,0:59:23.95,0:59:26.75,EN,,0,0,0,,where I now have to get ready to do Fib of N minus 2.\nDialogue: 0,0:59:29.27,0:59:30.72,EN,,0,0,0,,But in order to do a Fib of N minus 2,\nDialogue: 0,0:59:30.75,0:59:31.63,EN,,0,0,0,,look, I don't know.\nDialogue: 0,0:59:31.78,0:59:33.40,EN,,0,0,0,,I've clobbered my N over here.\nDialogue: 0,0:59:33.81,0:59:35.47,EN,,0,0,0,,And presumably my N is counted down\nDialogue: 0,0:59:37.85,0:59:38.80,EN,,0,0,0,,all the way to 1 or 0 or something at this point.\nDialogue: 0,0:59:39.78,0:59:42.51,EN,,0,0,0,,So I don't know what the value of N in the N register is.\nDialogue: 0,0:59:43.03,0:59:44.75,EN,,0,0,0,,I want the value of N that was on the stack\nDialogue: 0,0:59:44.80,0:59:46.00,EN,,0,0,0,,that I saved over here\nDialogue: 0,0:59:46.17,0:59:47.88,EN,,0,0,0,,so that could restore it over here.\nDialogue: 0,0:59:49.52,0:59:51.02,EN,,0,0,0,,I saved up the value of N,\nDialogue: 0,0:59:51.15,0:59:54.49,EN,,0,0,0,,which is this value of N at this point,\nDialogue: 0,0:59:54.89,0:59:57.37,EN,,0,0,0,,so that I could restore it after computing Fib of N minus 1,\nDialogue: 0,0:59:57.53,0:59:59.36,EN,,0,0,0,,so that I could count that down to N minus 2\nDialogue: 0,0:59:59.39,1:00:00.86,EN,,0,0,0,,and then compute Fib of N minus 2.\nDialogue: 0,1:00:01.81,1:00:02.75,EN,,0,0,0,,So let's restore that.\nDialogue: 0,1:00:08.83,1:00:09.77,EN,,0,0,0,,Restore of N.\nDialogue: 0,1:00:11.13,1:00:15.98,EN,,0,0,0,,Now I'm about to do something which is superstitious,\nDialogue: 0,1:00:16.00,1:00:17.40,EN,,0,0,0,,and we will remove it shortly.\nDialogue: 0,1:00:18.52,1:00:20.48,EN,,0,0,0,,I am about to finish the sequence\nDialogue: 0,1:00:20.59,1:00:23.44,EN,,0,0,0,,of doing the subroutine call, if you will.\nDialogue: 0,1:00:24.80,1:00:25.95,EN,,0,0,0,,I'm going to say, well,\nDialogue: 0,1:00:26.06,1:00:27.90,EN,,0,0,0,,I also saved up the continuation,\nDialogue: 0,1:00:28.48,1:00:30.43,EN,,0,0,0,,since I'm going to restore it now.\nDialogue: 0,1:00:31.60,1:00:32.60,EN,,0,0,0,,But actually, I don't have to,\nDialogue: 0,1:00:32.64,1:00:33.55,EN,,0,0,0,,because I'm not going to need it.\nDialogue: 0,1:00:34.61,1:00:35.72,EN,,0,0,0,,We'll fix that in a second.\nDialogue: 0,1:00:36.26,1:00:37.95,EN,,0,0,0,,So we'll do a restore of continue,\nDialogue: 0,1:00:46.04,1:00:48.02,EN,,0,0,0,,which is what I would in general need to do.\nDialogue: 0,1:00:48.02,1:00:49.23,EN,,0,0,0,,And we're just going to see whats called\nDialogue: 0,1:00:49.31,1:00:52.14,EN,,0,0,0,,what you would call in the compiler world a peephole optimization,\nDialogue: 0,1:00:52.27,1:00:53.72,EN,,0,0,0,,which says, whoops, you didn't have to do that.\nDialogue: 0,1:00:55.42,1:00:57.10,EN,,0,0,0,,OK, so the next thing I see here\nDialogue: 0,1:00:58.46,1:01:02.28,EN,,0,0,0,,is that I have to get ready now to do Fibonacci of N minus 2.\nDialogue: 0,1:01:02.77,1:01:04.49,EN,,0,0,0,,But I don't have to save N anymore.\nDialogue: 0,1:01:05.05,1:01:06.72,EN,,0,0,0,,The reason why I don't have to save N anymore\nDialogue: 0,1:01:06.80,1:01:09.34,EN,,0,0,0,,is because I don't need N after I've done Fib of N minus 2,\nDialogue: 0,1:01:09.36,1:01:10.72,EN,,0,0,0,,because the next thing I do is add.\nDialogue: 0,1:01:13.54,1:01:15.85,EN,,0,0,0,,So I'm just going to set up my N that way.\nDialogue: 0,1:01:16.60,1:01:28.99,EN,,0,0,0,,Assign N minus difference of fetch N and 2.\nDialogue: 0,1:01:31.85,1:01:34.01,EN,,0,0,0,,Now I have to finish the setup\nDialogue: 0,1:01:34.27,1:01:36.73,EN,,0,0,0,,for calling Fibonacci of N minus 2.\nDialogue: 0,1:01:36.95,1:01:38.33,EN,,0,0,0,,Well, I have to save up continue\nDialogue: 0,1:01:44.22,1:01:49.02,EN,,0,0,0,,and assign continue, continue,\nDialogue: 0,1:01:52.30,1:01:59.95,EN,,0,0,0,,to the place which is after Fib N 2,\nDialogue: 0,1:02:02.57,1:02:04.03,EN,,0,0,0,,that place over here somewhere.\nDialogue: 0,1:02:05.32,1:02:07.23,EN,,0,0,0,,However, I've got to be very careful.\nDialogue: 0,1:02:08.65,1:02:11.42,EN,,0,0,0,,The old value, the value of Fib of N minus 1,\nDialogue: 0,1:02:12.06,1:02:13.12,EN,,0,0,0,,I'm going to need later.\nDialogue: 0,1:02:15.30,1:02:17.37,EN,,0,0,0,,The value of Fibonacci of N minus 1,\nDialogue: 0,1:02:17.61,1:02:18.48,EN,,0,0,0,,I'm going to need.\nDialogue: 0,1:02:18.78,1:02:19.80,EN,,0,0,0,,And I can't clobber it,\nDialogue: 0,1:02:21.07,1:02:23.60,EN,,0,0,0,,because I'm going to have to add it to the value of Fib of N minus 2.\nDialogue: 0,1:02:24.15,1:02:25.88,EN,,0,0,0,,That's in the value register, so I'm going to save it.\nDialogue: 0,1:02:27.79,1:02:32.60,EN,,0,0,0,,So I have to save this right now, save up VAL.\nDialogue: 0,1:02:33.78,1:02:35.44,EN,,0,0,0,,And now I can go off to my subroutine,\nDialogue: 0,1:02:36.67,1:02:39.54,EN,,0,0,0,,go to Fib loop.\nDialogue: 0,1:02:44.22,1:02:46.57,EN,,0,0,0,,Now before I go any further\nDialogue: 0,1:02:46.80,1:02:49.36,EN,,0,0,0,,and finish this program,\nDialogue: 0,1:02:49.39,1:02:51.05,EN,,0,0,0,,I just want to look at this segment so far\nDialogue: 0,1:02:51.23,1:02:56.00,EN,,0,0,0,,and see, oh yes, there's a sequence of instructions here, if you will\nDialogue: 0,1:02:57.84,1:02:59.08,EN,,0,0,0,,that I can do something about.\nDialogue: 0,1:03:01.58,1:03:03.20,EN,,0,0,0,,Here I have a restore of continue,\nDialogue: 0,1:03:04.25,1:03:05.48,EN,,0,0,0,,a save of continue,\nDialogue: 0,1:03:06.01,1:03:07.40,EN,,0,0,0,,and then an assign of continue,\nDialogue: 0,1:03:08.70,1:03:10.64,EN,,0,0,0,,with no other references to continue in between.\nDialogue: 0,1:03:13.84,1:03:15.48,EN,,0,0,0,,The restore followed by the save\nDialogue: 0,1:03:15.50,1:03:16.67,EN,,0,0,0,,leaves the stack unchanged.\nDialogue: 0,1:03:19.09,1:03:21.72,EN,,0,0,0,,The only difference is that I set the continue register to a value,\nDialogue: 0,1:03:21.96,1:03:23.28,EN,,0,0,0,,which is the value that was on the stack.\nDialogue: 0,1:03:24.33,1:03:25.79,EN,,0,0,0,,Since I now clobber that value,\nDialogue: 0,1:03:26.44,1:03:27.93,EN,,0,0,0,,as in it was never referenced,\nDialogue: 0,1:03:28.59,1:03:30.09,EN,,0,0,0,,these instructions are unnecessary.\nDialogue: 0,1:03:31.76,1:03:35.39,EN,,0,0,0,,So we will remove these.\nDialogue: 0,1:03:38.88,1:03:40.78,EN,,0,0,0,,But I couldn't have seen that unless I had written them down.\nDialogue: 0,1:03:43.78,1:03:44.72,EN,,0,0,0,,Was that really true?\nDialogue: 0,1:03:45.77,1:03:46.60,EN,,0,0,0,,Well, I don't know.\nDialogue: 0,1:03:48.61,1:03:52.91,EN,,0,0,0,,OK, so we've now gone off to compute Fibonacci of N minus 2.\nDialogue: 0,1:03:53.66,1:03:54.59,EN,,0,0,0,,So after that,\nDialogue: 0,1:04:02.96,1:04:03.85,EN,,0,0,0,,what are we going to do?\nDialogue: 0,1:04:05.07,1:04:06.76,EN,,0,0,0,,Well, I suppose the first thing we have to do--\nDialogue: 0,1:04:06.99,1:04:07.88,EN,,0,0,0,,we've got two things.\nDialogue: 0,1:04:07.96,1:04:10.49,EN,,0,0,0,,We've got a thing in the value register which is now valuable.\nDialogue: 0,1:04:10.92,1:04:11.98,EN,,0,0,0,,We also have a thing on the stack\nDialogue: 0,1:04:12.04,1:04:13.63,EN,,0,0,0,,can be restored into the value register.\nDialogue: 0,1:04:14.81,1:04:16.57,EN,,0,0,0,,And what I have to be careful with now\nDialogue: 0,1:04:16.88,1:04:18.99,EN,,0,0,0,,is I want to shuffle this right so I can do the multiply.\nDialogue: 0,1:04:19.47,1:04:21.24,EN,,0,0,0,,Now there are various conventions I might use,\nDialogue: 0,1:04:21.47,1:04:23.52,EN,,0,0,0,,but I'm going to be very picky and say,\nDialogue: 0,1:04:23.55,1:04:25.88,EN,,0,0,0,,I'm only going to restore into a register I've saved from.\nDialogue: 0,1:04:26.74,1:04:28.28,EN,,0,0,0,,If that's the case, I have to do a shuffle here.\nDialogue: 0,1:04:29.24,1:04:31.84,EN,,0,0,0,,It's the same problem with how many hands I have.\nDialogue: 0,1:04:32.68,1:04:37.13,EN,,0,0,0,,So I'm going to assign to N,\nDialogue: 0,1:04:37.16,1:04:39.37,EN,,0,0,0,,because I'm not going to need N anymore, N is useless,\nDialogue: 0,1:04:39.92,1:04:41.21,EN,,0,0,0,,the current value of VAL,\nDialogue: 0,1:04:45.21,1:04:47.34,EN,,0,0,0,,which was the value of Fib of N minus 2.\nDialogue: 0,1:04:52.95,1:04:56.35,EN,,0,0,0,,And I'm going to restore the value register now.\nDialogue: 0,1:05:01.85,1:05:03.92,EN,,0,0,0,,This restore matches this save.\nDialogue: 0,1:05:05.58,1:05:08.83,EN,,0,0,0,,And if you're very careful and examine very carefully what goes on,\nDialogue: 0,1:05:09.21,1:05:11.96,EN,,0,0,0,,OK? restores and saves are always matched.\nDialogue: 0,1:05:13.84,1:05:15.15,EN,,0,0,0,,Now there's an outstanding save,\nDialogue: 0,1:05:15.18,1:05:16.38,EN,,0,0,0,,of course, that we have to get rid of soon.\nDialogue: 0,1:05:19.00,1:05:20.59,EN,,0,0,0,,And so I restored the value register.\nDialogue: 0,1:05:20.94,1:05:22.57,EN,,0,0,0,,Now I restore the continue one,\nDialogue: 0,1:05:31.15,1:05:32.40,EN,,0,0,0,,which matches this one,\nDialogue: 0,1:05:34.80,1:05:37.85,EN,,0,0,0,,dot, dot, dot, dot, dot, dot, dot, down to here,\nDialogue: 0,1:05:40.59,1:05:42.46,EN,,0,0,0,,Now restoring that continuation.\nDialogue: 0,1:05:42.86,1:05:45.71,EN,,0,0,0,,That continuation is a continuation of Fib of N,\nDialogue: 0,1:05:46.46,1:05:47.84,EN,,0,0,0,,which is the problem I was trying to solve,\nDialogue: 0,1:05:47.85,1:05:49.32,EN,,0,0,0,,a major problem I'm trying to solve.\nDialogue: 0,1:05:49.98,1:05:52.35,EN,,0,0,0,,So that's the guy I have to go back to who wants Fib of N.\nDialogue: 0,1:05:52.54,1:05:54.03,EN,,0,0,0,,I saved them all the way up here\nDialogue: 0,1:05:54.16,1:05:56.60,EN,,0,0,0,,when I realized N was not less than 2.\nDialogue: 0,1:05:57.36,1:05:59.07,EN,,0,0,0,,And so I had to do a complicated operation.\nDialogue: 0,1:06:00.84,1:06:02.57,EN,,0,0,0,,Now I've got everything I need to do it.\nDialogue: 0,1:06:03.24,1:06:04.36,EN,,0,0,0,,So I'm going to restore that,\nDialogue: 0,1:06:05.42,1:06:21.08,EN,,0,0,0,,assign to VAL the sum of fetch VAL and fetch of N\nDialogue: 0,1:06:27.44,1:06:28.60,EN,,0,0,0,,and go to continue.\nDialogue: 0,1:06:38.26,1:06:44.78,EN,,0,0,0,,So now I've returned from computing Fibonacci of N,\nDialogue: 0,1:06:45.39,1:06:46.57,EN,,0,0,0,,the general case.\nDialogue: 0,1:06:47.11,1:06:50.60,EN,,0,0,0,,Now what's left is we have to fix up a few details,\nDialogue: 0,1:06:50.99,1:06:55.53,EN,,0,0,0,,like there's the base case of this induction, immediate answer,\nDialogue: 0,1:07:02.54,1:07:06.59,EN,,0,0,0,,as, which is nothing more than\nDialogue: 0,1:07:06.60,1:07:11.85,EN,,0,0,0,,assign to VAL fetch of N,\nDialogue: 0,1:07:13.64,1:07:15.47,EN,,0,0,0,,because N was less than 2,\nDialogue: 0,1:07:15.50,1:07:16.89,EN,,0,0,0,,and therefore, the answer is N\nDialogue: 0,1:07:16.99,1:07:18.19,EN,,0,0,0,,in our original program,\nDialogue: 0,1:07:19.23,1:07:26.48,EN,,0,0,0,,and return continue--\nDialogue: 0,1:07:31.24,1:07:36.13,EN,,0,0,0,,bobble, bobble almost-- and finally Fib done.\nDialogue: 0,1:07:43.46,1:07:45.64,EN,,0,0,0,,So that's a fairly complicated program.\nDialogue: 0,1:07:45.64,1:07:47.34,EN,,0,0,0,,And the reason I wanted you see to that\nDialogue: 0,1:07:47.50,1:07:49.21,EN,,0,0,0,,is because I want you to see the particular\nDialogue: 0,1:07:49.45,1:07:52.67,EN,,0,0,0,,flavors of stack discipline that I was obeying.\nDialogue: 0,1:07:53.32,1:07:55.21,EN,,0,0,0,,It was first of all, I don't want to save anything\nDialogue: 0,1:07:56.92,1:07:58.12,EN,,0,0,0,,that I'm not going to need later.\nDialogue: 0,1:08:00.57,1:08:01.85,EN,,0,0,0,,I was being very careful.\nDialogue: 0,1:08:01.85,1:08:02.91,EN,,0,0,0,,And it's very important.\nDialogue: 0,1:08:03.94,1:08:06.52,EN,,0,0,0,,And there are all sorts of other disciplines people make\nDialogue: 0,1:08:07.37,1:08:09.61,EN,,0,0,0,,with frames and things like that of some sort,\nDialogue: 0,1:08:10.19,1:08:11.39,EN,,0,0,0,,where you save all sorts of junk\nDialogue: 0,1:08:11.40,1:08:12.64,EN,,0,0,0,,you're not going to need later and restore it\nDialogue: 0,1:08:12.67,1:08:15.26,EN,,0,0,0,,because, in some sense, it's easier to do that.\nDialogue: 0,1:08:15.83,1:08:17.40,EN,,0,0,0,,That's going to lead to various disasters,\nDialogue: 0,1:08:18.59,1:08:20.25,EN,,0,0,0,,which we'll see a little later.\nDialogue: 0,1:08:21.44,1:08:24.24,EN,,0,0,0,,It's crucial to save exactly what you're going to need later.\nDialogue: 0,1:08:26.89,1:08:28.01,EN,,0,0,0,,It's an important idea.\nDialogue: 0,1:08:29.87,1:08:33.36,EN,,0,0,0,,And the responsibility of that is whoever saves something\nDialogue: 0,1:08:33.76,1:08:35.32,EN,,0,0,0,,is the guy who restores it, because he needs it.\nDialogue: 0,1:08:36.93,1:08:38.54,EN,,0,0,0,,And in such discipline,\nDialogue: 0,1:08:38.86,1:08:40.76,EN,,0,0,0,,you can see what things are unnecessary,\nDialogue: 0,1:08:43.45,1:08:44.73,EN,,0,0,0,,operations that are unimportant.\nDialogue: 0,1:08:47.15,1:08:50.40,EN,,0,0,0,,Now, one other thing I want to tell you about is very simple\nDialogue: 0,1:08:51.66,1:08:54.67,EN,,0,0,0,,is that, of course, the picture you see is not the whole picture.\nDialogue: 0,1:08:55.35,1:08:56.68,EN,,0,0,0,,Supposing I had systems\nDialogue: 0,1:08:56.80,1:09:01.52,EN,,0,0,0,,had things like other operations, CAR, CDR, CONS,\nDialogue: 0,1:09:03.53,1:09:05.60,EN,,0,0,0,,building a vector\nDialogue: 0,1:09:05.88,1:09:07.32,EN,,0,0,0,,and referencing the nth element of it,\nDialogue: 0,1:09:08.30,1:09:09.21,EN,,0,0,0,,or things like that.\nDialogue: 0,1:09:10.40,1:09:13.60,EN,,0,0,0,,Well, at this level of detail, whatever it is,\nDialogue: 0,1:09:13.87,1:09:17.85,EN,,0,0,0,,we can conceptualize those as primitive operations in the datapath.\nDialogue: 0,1:09:18.75,1:09:21.95,EN,,0,0,0,,In other words, we could say that some machine that, for example, has\nDialogue: 0,1:09:22.32,1:09:24.11,EN,,0,0,0,,has the append machine,\nDialogue: 0,1:09:24.20,1:09:26.46,EN,,0,0,0,,which has to do cons of the CAR of x\nDialogue: 0,1:09:26.64,1:09:29.80,EN,,0,0,0,,with the append of the CDR of x and y,\nDialogue: 0,1:09:29.88,1:09:33.18,EN,,0,0,0,,well, gee, that's exactly the same as the factorial structure.\nDialogue: 0,1:09:33.63,1:09:35.29,EN,,0,0,0,,Well, it's got about the same structure.\nDialogue: 0,1:09:36.54,1:09:37.27,EN,,0,0,0,,And what do we have?\nDialogue: 0,1:09:37.27,1:09:39.39,EN,,0,0,0,,We have some sort of things in it\nDialogue: 0,1:09:39.76,1:09:42.48,EN,,0,0,0,,which may be registers, x and y,\nDialogue: 0,1:09:42.51,1:09:45.12,EN,,0,0,0,,and then x has to somehow move to y sometimes,\nDialogue: 0,1:09:45.28,1:09:46.75,EN,,0,0,0,,x has to get the value of y.\nDialogue: 0,1:09:46.93,1:09:50.11,EN,,0,0,0,,And then we may have to be able to do something which is a cons.\nDialogue: 0,1:09:51.70,1:09:57.74,EN,,0,0,0,,I don't remember if I need to like this is in this system,\nDialogue: 0,1:09:57.76,1:10:01.10,EN,,0,0,0,,but cons is sort of like subtract or add or something.\nDialogue: 0,1:10:01.42,1:10:02.70,EN,,0,0,0,,It combines two things,\nDialogue: 0,1:10:02.73,1:10:04.27,EN,,0,0,0,,producing a thing which is the cons,\nDialogue: 0,1:10:04.51,1:10:06.49,EN,,0,0,0,,which we may then think goes into there.\nDialogue: 0,1:10:07.60,1:10:09.72,EN,,0,0,0,,And then maybe a thing called the CAR,\nDialogue: 0,1:10:12.88,1:10:16.22,EN,,0,0,0,,which will produce-- I can get the CAR or something.\nDialogue: 0,1:10:16.92,1:10:19.55,EN,,0,0,0,,And maybe I can get the CDR of something, and so on.\nDialogue: 0,1:10:20.15,1:10:22.30,EN,,0,0,0,,But we shouldn't be too afraid of saying things this way,\nDialogue: 0,1:10:22.92,1:10:24.24,EN,,0,0,0,,because the worst that could happen\nDialogue: 0,1:10:24.94,1:10:26.41,EN,,0,0,0,,is if we open up cons,\nDialogue: 0,1:10:27.31,1:10:29.82,EN,,0,0,0,,what we're going to find is some machine.\nDialogue: 0,1:10:31.88,1:10:34.44,EN,,0,0,0,,And cons may in fact overlap with CAR and CDR, and it always does,\nDialogue: 0,1:10:35.50,1:10:38.12,EN,,0,0,0,,in the same way that plus and minus overlap,\nDialogue: 0,1:10:38.57,1:10:39.85,EN,,0,0,0,,and really the same business.\nDialogue: 0,1:10:41.21,1:10:42.60,EN,,0,0,0,,CONS, CAR, and CDR are going to overlap,\nDialogue: 0,1:10:42.62,1:10:44.52,EN,,0,0,0,,and we're going to find a little controller,\nDialogue: 0,1:10:45.50,1:10:46.54,EN,,0,0,0,,a little datapath,\nDialogue: 0,1:10:48.03,1:10:49.64,EN,,0,0,0,,which may have some registers in it,\nDialogue: 0,1:10:50.00,1:10:52.86,EN,,0,0,0,,some stuff like that.\nDialogue: 0,1:10:53.30,1:10:54.41,EN,,0,0,0,,And maybe inside it,\nDialogue: 0,1:10:54.43,1:10:56.16,EN,,0,0,0,,there may also be an infinite part,\nDialogue: 0,1:10:56.46,1:10:58.70,EN,,0,0,0,,a part that's semi-infinite or something,\nDialogue: 0,1:10:58.81,1:11:00.65,EN,,0,0,0,,which is a lot of very uniform stuff,\nDialogue: 0,1:11:00.96,1:11:02.03,EN,,0,0,0,,which we'll call memory.\nDialogue: 0,1:11:06.57,1:11:08.83,EN,,0,0,0,,And I wouldn't be so horrified if that were the way it works.\nDialogue: 0,1:11:09.33,1:11:11.07,EN,,0,0,0,,In fact, it does, and we'll talk about that later.\nDialogue: 0,1:11:13.32,1:11:14.57,EN,,0,0,0,,So are there any questions?\nDialogue: 0,1:11:24.34,1:11:25.80,EN,,0,0,0,,Gee, what an unquestioning audience.\nDialogue: 0,1:11:28.67,1:11:30.33,EN,,0,0,0,,Suppose I tell you a horrible pile of lies.\nDialogue: 0,1:11:39.69,1:11:40.38,EN,,0,0,0,,OK.\nDialogue: 0,1:11:41.99,1:11:42.52,EN,,0,0,0,,Well, thank you.\nDialogue: 0,1:11:42.52,1:11:43.28,EN,,0,0,0,,Let's take our break.\n"
  },
  {
    "path": "Ass/lec9b.chn+eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:16.30,0:00:18.08,EN,,0,0,0,,PROFESSOR: Well, I hope you appreciate that we have\nDialogue: 0,0:00:20.01,0:00:22.73,EN,,0,0,0,,we have inducted you into some real magic,\nDialogue: 0,0:00:24.20,0:00:27.24,EN,,0,0,0,,the magic of building languages\nDialogue: 0,0:00:27.42,0:00:28.72,EN,,0,0,0,,really building new languages.\nDialogue: 0,0:00:29.69,0:00:30.40,EN,,0,0,0,,What have we looked at?\nDialogue: 0,0:00:30.43,0:00:32.78,EN,,0,0,0,,We've looked at an Escher picture language.\nDialogue: 0,0:00:38.92,0:00:41.15,EN,,0,0,0,,OK? this language invented by Peter Henderson.\nDialogue: 0,0:00:42.01,0:00:46.49,EN,,0,0,0,,We looked at digital logic language.\nDialogue: 0,0:00:53.16,0:00:55.55,EN,,0,0,0,,Let's see.We've looked at the query language.\nDialogue: 0,0:00:59.70,0:01:00.78,EN,,0,0,0,,And the thing you should realize is,\nDialogue: 0,0:01:00.81,0:01:03.10,EN,,0,0,0,,even though these were toy examples,\nDialogue: 0,0:01:04.70,0:01:07.61,EN,,0,0,0,,they really are the kernels of really useful things.\nDialogue: 0,0:01:08.25,0:01:09.48,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:01:10.12,0:01:11.18,EN,,0,0,0,,the Escher picture language\nDialogue: 0,0:01:11.20,0:01:14.33,EN,,0,0,0,,was taken byHenry Wu, who's a student at MIT,\nDialogue: 0,0:01:14.88,0:01:16.43,EN,,0,0,0,,and developed into a real\nDialogue: 0,0:01:16.97,0:01:19.45,EN,,0,0,0,,language for laying out PC boards,\nDialogue: 0,0:01:20.35,0:01:22.56,EN,,0,0,0,,based just on extending those structures.\nDialogue: 0,0:01:23.24,0:01:24.65,EN,,0,0,0,,And the digital logic language,\nDialogue: 0,0:01:24.68,0:01:26.08,EN,,0,0,0,,Gerry mentioned when he showed it to you,\nDialogue: 0,0:01:26.43,0:01:29.92,EN,,0,0,0,,was really extended to be used as the basis for a simulator\nDialogue: 0,0:01:30.85,0:01:32.96,EN,,0,0,0,,that was used to design a real computer.\nDialogue: 0,0:01:33.46,0:01:34.32,EN,,0,0,0,,And the query language,\nDialogue: 0,0:01:34.35,0:01:36.44,EN,,0,0,0,,of course, is kind of the germ of prolog.\nDialogue: 0,0:01:37.51,0:01:39.07,EN,,0,0,0,,So we built all of these languages,\nDialogue: 0,0:01:39.55,0:01:40.65,EN,,0,0,0,,they're all based on LISP.\nDialogue: 0,0:01:43.63,0:01:44.59,EN,,0,0,0,,A lot of people ask\nDialogue: 0,0:01:45.27,0:01:48.73,EN,,0,0,0,,what particular problems is LISP good for solving for?\nDialogue: 0,0:01:48.75,0:01:49.93,EN,,0,0,0,,The answer is LISP is not...\nDialogue: 0,0:01:50.33,0:01:52.65,EN,,0,0,0,,LISP is not good for solving any particular problems.\nDialogue: 0,0:01:53.53,0:01:54.60,EN,,0,0,0,,What LISP is good for\nDialogue: 0,0:01:54.73,0:01:57.15,EN,,0,0,0,,is constructing within it the right language\nDialogue: 0,0:01:57.18,0:01:58.57,EN,,0,0,0,,to solve the problems you want to solve,\nDialogue: 0,0:01:59.17,0:02:00.44,EN,,0,0,0,,and that's how you should think about it.\nDialogue: 0,0:02:01.47,0:02:03.39,EN,,0,0,0,,So all of these languages were based on LISP.\nDialogue: 0,0:02:04.57,0:02:05.72,EN,,0,0,0,,Now, what's LISP based on?\nDialogue: 0,0:02:06.97,0:02:07.88,EN,,0,0,0,,Where's that come from?\nDialogue: 0,0:02:07.90,0:02:09.40,EN,,0,0,0,,Well, we looked at that too.\nDialogue: 0,0:02:09.58,0:02:16.09,EN,,0,0,0,,We looked at the meta-circular evaluator\nDialogue: 0,0:02:21.53,0:02:23.40,EN,,0,0,0,,the meta-circular evaluator and sort of said\nDialogue: 0,0:02:23.42,0:02:25.76,EN,,0,0,0,,well, LISP is based on LISP.\nDialogue: 0,0:02:25.80,0:02:27.48,EN,,0,0,0,,And when we start looking at that,\nDialogue: 0,0:02:28.27,0:02:29.95,EN,,0,0,0,,we've got to do some real magic, right?\nDialogue: 0,0:02:29.95,0:02:31.74,EN,,0,0,0,,So what does that mean, right?\nDialogue: 0,0:02:31.74,0:02:34.96,EN,,0,0,0,,Y operators, and fixed points,\nDialogue: 0,0:02:35.76,0:02:38.33,EN,,0,0,0,,and the idea that what this means is\nDialogue: 0,0:02:38.36,0:02:41.44,EN,,0,0,0,,that LISP is somehow the fixed-point equation for the\nDialogue: 0,0:02:42.20,0:02:45.42,EN,,0,0,0,,for this funny set of things which are defined in terms of themselves.\nDialogue: 0,0:02:47.40,0:02:48.56,EN,,0,0,0,,Now, it's real magic.\nDialogue: 0,0:02:49.07,0:02:52.35,EN,,0,0,0,,Well, today, for a final piece of magic,\nDialogue: 0,0:02:52.62,0:02:54.03,EN,,0,0,0,,we're going to make all the magic go away.\nDialogue: 0,0:03:06.80,0:03:07.98,EN,,0,0,0,,We already know how to do that.\nDialogue: 0,0:03:09.77,0:03:10.76,EN,,0,0,0,,The idea is, we're going to take\nDialogue: 0,0:03:11.13,0:03:12.73,EN,,0,0,0,,the register machine architecture\nDialogue: 0,0:03:13.36,0:03:15.50,EN,,0,0,0,,and show how to implement LISP on terms of that.\nDialogue: 0,0:03:15.50,0:03:17.93,EN,,0,0,0,,And, remember, the idea of the register machine\nDialogue: 0,0:03:19.60,0:03:24.68,EN,,0,0,0,,is that there's a fixed and finite part of the machine.\nDialogue: 0,0:03:24.72,0:03:26.12,EN,,0,0,0,,There's a finite-state controller,\nDialogue: 0,0:03:26.12,0:03:27.87,EN,,0,0,0,,which dose particular thing\nDialogue: 0,0:03:27.88,0:03:29.31,EN,,0,0,0,,with a particular amount of hardware.\nDialogue: 0,0:03:30.51,0:03:31.74,EN,,0,0,0,,There are particular data paths,\nDialogue: 0,0:03:31.76,0:03:33.24,EN,,0,0,0,,the operation the machine does\nDialogue: 0,0:03:33.55,0:03:35.29,EN,,0,0,0,,And then, in order to implement recursion\nDialogue: 0,0:03:35.53,0:03:37.60,EN,,0,0,0,,and sustain the illusion of infinity,\nDialogue: 0,0:03:37.82,0:03:39.77,EN,,0,0,0,,there's some large amount of memory, which is the stack.\nDialogue: 0,0:03:42.06,0:03:43.72,EN,,0,0,0,,So, if we implement LISP\nDialogue: 0,0:03:43.92,0:03:45.50,EN,,0,0,0,,in terms of a register machine,\nDialogue: 0,0:03:47.02,0:03:48.35,EN,,0,0,0,,then everything ought to become,\nDialogue: 0,0:03:48.40,0:03:49.85,EN,,0,0,0,,at this point,completely concrete.\nDialogue: 0,0:03:49.85,0:03:51.23,EN,,0,0,0,,All the magic should go away.\nDialogue: 0,0:03:51.65,0:03:53.52,EN,,0,0,0,,And, by the end of this talk,\nDialogue: 0,0:03:53.53,0:03:54.78,EN,,0,0,0,,I want you get the feeling\nDialogue: 0,0:03:55.14,0:03:59.05,EN,,0,0,0,,that, as opposed to this very mysterious meta-circular evaluator\nDialogue: 0,0:03:59.67,0:04:02.60,EN,,0,0,0,,that a LISP evaluator really is something that's concrete enough\nDialogue: 0,0:04:02.85,0:04:04.57,EN,,0,0,0,,that you can hold in the palm of your hand.\nDialogue: 0,0:04:04.76,0:04:06.24,EN,,0,0,0,,You should be able to imagine holding\nDialogue: 0,0:04:06.57,0:04:07.90,EN,,0,0,0,,holding a LISP interpreter there.\nDialogue: 0,0:04:09.63,0:04:10.94,EN,,0,0,0,,All right, how are we going to do this?\nDialogue: 0,0:04:10.95,0:04:12.76,EN,,0,0,0,,We already have all the ingredients.\nDialogue: 0,0:04:13.96,0:04:17.45,EN,,0,0,0,,See, what you learned last time from Gerry\nDialogue: 0,0:04:17.60,0:04:21.47,EN,,0,0,0,,is how to take any particular couple of LISP procedures.\nDialogue: 0,0:04:22.60,0:04:24.28,EN,,0,0,0,,and hand-translate them\nDialogue: 0,0:04:24.75,0:04:26.67,EN,,0,0,0,,into something that runs on a register machine.\nDialogue: 0,0:04:28.20,0:04:30.52,EN,,0,0,0,,So, to implement all of LISP on a register machine,\nDialogue: 0,0:04:30.57,0:04:31.44,EN,,0,0,0,,all we have to do\nDialogue: 0,0:04:31.69,0:04:33.45,EN,,0,0,0,,is take the particular procedures\nDialogue: 0,0:04:33.68,0:04:35.42,EN,,0,0,0,,that are the meta-circular evaluator\nDialogue: 0,0:04:36.17,0:04:38.11,EN,,0,0,0,,and hand-translate them for a register machine.\nDialogue: 0,0:04:39.04,0:04:40.25,EN,,0,0,0,,And that does all of LISP\nDialogue: 0,0:04:42.14,0:04:43.00,EN,,0,0,0,,Right? So, in principle,\nDialogue: 0,0:04:43.02,0:04:44.43,EN,,0,0,0,,we already know how to do this.\nDialogue: 0,0:04:45.38,0:04:46.54,EN,,0,0,0,,And, indeed, it's going to be no\nDialogue: 0,0:04:46.68,0:04:48.86,EN,,0,0,0,,no different, in kind,\nDialogue: 0,0:04:50.00,0:04:53.40,EN,,0,0,0,,from in say recursive factorial\nDialogue: 0,0:04:53.42,0:04:54.67,EN,,0,0,0,,or recursive Fibonacci.\nDialogue: 0,0:04:54.67,0:04:56.00,EN,,0,0,0,,It's just bigger and there's more of it.\nDialogue: 0,0:04:56.84,0:04:58.03,EN,,0,0,0,,So it'd just be more details,\nDialogue: 0,0:04:58.04,0:04:59.66,EN,,0,0,0,,but nothing really conceptually new.\nDialogue: 0,0:05:01.48,0:05:03.02,EN,,0,0,0,,And also, when we've done that,\nDialogue: 0,0:05:03.08,0:05:04.76,EN,,0,0,0,,and the thing is completely explicit,\nDialogue: 0,0:05:04.87,0:05:06.91,EN,,0,0,0,,and we see how to implement LISP\nDialogue: 0,0:05:06.94,0:05:10.08,EN,,0,0,0,,in terms of the actual sequential register operations,\nDialogue: 0,0:05:10.16,0:05:11.63,EN,,0,0,0,,that's going to be our final\nDialogue: 0,0:05:11.95,0:05:14.16,EN,,0,0,0,,most explicit model of LISP in this course.\nDialogue: 0,0:05:14.81,0:05:16.95,EN,,0,0,0,,And, remember, that's a progression through this course.\nDialogue: 0,0:05:16.95,0:05:18.25,EN,,0,0,0,,We started out with substitution,\nDialogue: 0,0:05:18.28,0:05:19.58,EN,,0,0,0,,which is sort of like algebra.\nDialogue: 0,0:05:20.24,0:05:21.87,EN,,0,0,0,,And then we went to the environment model,\nDialogue: 0,0:05:21.88,0:05:24.00,EN,,0,0,0,,which talked about the actual frames\nDialogue: 0,0:05:24.03,0:05:25.31,EN,,0,0,0,,and how they got linked together.\nDialogue: 0,0:05:26.32,0:05:27.88,EN,,0,0,0,,And then we made that more concrete\nDialogue: 0,0:05:27.90,0:05:29.36,EN,,0,0,0,,in the meta-circular evaluator.\nDialogue: 0,0:05:31.05,0:05:31.64,EN,,0,0,0,,There are things\nDialogue: 0,0:05:31.87,0:05:33.98,EN,,0,0,0,,the meta-circular evaluator doesn't tell us.\nDialogue: 0,0:05:34.36,0:05:35.34,EN,,0,0,0,,You should realize that.\nDialogue: 0,0:05:36.09,0:05:38.64,EN,,0,0,0,,For instance, it left unanswered the question\nDialogue: 0,0:05:38.73,0:05:42.67,EN,,0,0,0,,of how a procedure, like recursive factorial here,\nDialogue: 0,0:05:45.17,0:05:47.13,EN,,0,0,0,,somehow takes space that grows.\nDialogue: 0,0:05:47.21,0:05:47.98,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:05:48.16,0:05:51.94,EN,,0,0,0,,a procedure which also looks syntactically recursive,\nDialogue: 0,0:05:52.11,0:05:55.07,EN,,0,0,0,,called fact-iter, somehow doesn't take space.\nDialogue: 0,0:05:55.10,0:05:59.16,EN,,0,0,0,,We justify that it doesn't need to take space\nDialogue: 0,0:06:00.50,0:06:01.96,EN,,0,0,0,,by showing the substitution model.\nDialogue: 0,0:06:01.96,0:06:02.94,EN,,0,0,0,,But we didn't really say\nDialogue: 0,0:06:03.42,0:06:06.76,EN,,0,0,0,,how it happens that the machine manages to do that,\nDialogue: 0,0:06:07.31,0:06:08.91,EN,,0,0,0,,that that has to do with the details\nDialogue: 0,0:06:09.02,0:06:11.12,EN,,0,0,0,,of how arguments are passed to procedures\nDialogue: 0,0:06:12.48,0:06:13.69,EN,,0,0,0,,And that's the thing we didn't see\nDialogue: 0,0:06:13.71,0:06:15.34,EN,,0,0,0,,in the meta-circular evaluator\nDialogue: 0,0:06:15.36,0:06:17.40,EN,,0,0,0,,precisely because the way arguments\nDialogue: 0,0:06:17.42,0:06:19.20,EN,,0,0,0,,got passed to procedures in this LISP\nDialogue: 0,0:06:19.70,0:06:20.59,EN,,0,0,0,,depended on\nDialogue: 0,0:06:21.02,0:06:23.50,EN,,0,0,0,,the way arguments got passed to procedures in this LISP.\nDialogue: 0,0:06:25.87,0:06:29.02,EN,,0,0,0,,But, now, that's going to become extremely explicit.\nDialogue: 0,0:06:30.74,0:06:31.12,EN,,0,0,0,,OK.\nDialogue: 0,0:06:31.23,0:06:34.30,EN,,0,0,0,,Well, before going on to the evaluator,\nDialogue: 0,0:06:34.36,0:06:35.53,EN,,0,0,0,,let me just give you a sense of\nDialogue: 0,0:06:35.55,0:06:37.00,EN,,0,0,0,,what a whole LISP system looks like\nDialogue: 0,0:06:37.60,0:06:39.36,EN,,0,0,0,,so you can see the parts we're going to talk about\nDialogue: 0,0:06:39.40,0:06:40.81,EN,,0,0,0,,and the parts we're not going to talk about.\nDialogue: 0,0:06:43.18,0:06:47.42,EN,,0,0,0,,Let's see, over here is a happy LISP user,\nDialogue: 0,0:06:48.67,0:06:52.65,EN,,0,0,0,,and the LISP user is talking to something called the reader.\nDialogue: 0,0:07:00.36,0:07:01.53,EN,,0,0,0,,The reader's job in life\nDialogue: 0,0:07:01.95,0:07:13.23,EN,,0,0,0,,is to take characters from the user\nDialogue: 0,0:07:14.17,0:07:16.62,EN,,0,0,0,,and turn them into data structures\nDialogue: 0,0:07:17.20,0:07:19.37,EN,,0,0,0,,in something called a list structure memory.\nDialogue: 0,0:07:30.00,0:07:31.72,EN,,0,0,0,,All right, so the reader is going to take\nDialogue: 0,0:07:32.65,0:07:33.95,EN,,0,0,0,,symbols, parentheses,\nDialogue: 0,0:07:34.48,0:07:37.12,EN,,0,0,0,,and A's and B's, and 1s and 3s that you type in,\nDialogue: 0,0:07:37.18,0:07:39.04,EN,,0,0,0,,and turn these into actual list structure:\nDialogue: 0,0:07:39.15,0:07:40.54,EN,,0,0,0,,pairs, and pointers, and things.\nDialogue: 0,0:07:42.35,0:07:43.92,EN,,0,0,0,,And so, by the time evaluator is going,\nDialogue: 0,0:07:43.93,0:07:45.10,EN,,0,0,0,,there are no characters in the world.\nDialogue: 0,0:07:45.85,0:07:48.16,EN,,0,0,0,,And, of course, in more modern Lisp systems, there's\nDialogue: 0,0:07:49.00,0:07:50.44,EN,,0,0,0,,there's sort a big morass here\nDialogue: 0,0:07:50.44,0:07:52.17,EN,,0,0,0,,that might sit between the user and the reader:\nDialogue: 0,0:07:52.41,0:07:54.52,EN,,0,0,0,,you know, Windows systems, in top levels,\nDialogue: 0,0:07:54.77,0:07:56.03,EN,,0,0,0,,and mice, and all kinds of things.\nDialogue: 0,0:07:56.28,0:07:58.20,EN,,0,0,0,,But conceptually, characters are coming in.\nDialogue: 0,0:07:59.93,0:08:04.32,EN,,0,0,0,,All right, the reader transforms these into pointers\nDialogue: 0,0:08:05.56,0:08:07.28,EN,,0,0,0,,pointers to stuff in this memory,\nDialogue: 0,0:08:08.27,0:08:10.94,EN,,0,0,0,,and that's what the evaluator sees\nDialogue: 0,0:08:15.55,0:08:16.04,EN,,0,0,0,,OK?\nDialogue: 0,0:08:17.02,0:08:18.88,EN,,0,0,0,,The evaluator has a bunch of helpers.\nDialogue: 0,0:08:19.78,0:08:23.16,EN,,0,0,0,,It has all possible primitive operators you might want.\nDialogue: 0,0:08:23.16,0:08:24.91,EN,,0,0,0,,So there's a completely separate box,\nDialogue: 0,0:08:28.40,0:08:30.25,EN,,0,0,0,,a floating point unit,\nDialogue: 0,0:08:32.22,0:08:34.40,EN,,0,0,0,,or all sorts of things, which do the primitive operators.\nDialogue: 0,0:08:35.39,0:08:37.68,EN,,0,0,0,,there's and, if you want more special primitives,\nDialogue: 0,0:08:37.71,0:08:39.02,EN,,0,0,0,,you build more primitive operators,\nDialogue: 0,0:08:39.05,0:08:40.48,EN,,0,0,0,,but they're separate from the evaluator.\nDialogue: 0,0:08:42.08,0:08:43.77,EN,,0,0,0,,The evaluator finally gets an answer\nDialogue: 0,0:08:45.16,0:08:46.76,EN,,0,0,0,,and communicates that to the printer.\nDialogue: 0,0:08:50.62,0:08:52.01,EN,,0,0,0,,And now, the printer's job in life\nDialogue: 0,0:08:52.01,0:08:54.54,EN,,0,0,0,,is this list structure coming from the evaluator,\nDialogue: 0,0:08:55.39,0:08:56.99,EN,,0,0,0,,and turn it back into characters,\nDialogue: 0,0:09:01.85,0:09:04.07,EN,,0,0,0,,and communicate them to the user through\nDialogue: 0,0:09:04.28,0:09:05.66,EN,,0,0,0,,whatever interface there is.\nDialogue: 0,0:09:08.05,0:09:11.23,EN,,0,0,0,,OK. Well, today, what we're going to talk about is this evaluator.\nDialogue: 0,0:09:12.67,0:09:15.20,EN,,0,0,0,,The primitive operators have nothing particular to do with LISP,\nDialogue: 0,0:09:15.20,0:09:18.14,EN,,0,0,0,,they're however you like to implement primitive operations.\nDialogue: 0,0:09:19.36,0:09:22.18,EN,,0,0,0,,The reader and printer are actually complicated,\nDialogue: 0,0:09:22.18,0:09:23.55,EN,,0,0,0,,but we're not going to talk about them.\nDialogue: 0,0:09:24.68,0:09:27.10,EN,,0,0,0,,They sort of have to do with details of how you might build\nDialogue: 0,0:09:27.10,0:09:28.92,EN,,0,0,0,,build up list structure from characters.\nDialogue: 0,0:09:29.90,0:09:31.18,EN,,0,0,0,,So that is a long story,\nDialogue: 0,0:09:31.18,0:09:32.32,EN,,0,0,0,,but we're not going to talk about it,\nDialogue: 0,0:09:32.49,0:09:33.69,EN,,0,0,0,,the list structure memory,\nDialogue: 0,0:09:34.36,0:09:35.63,EN,,0,0,0,,we'll talk about next time.\nDialogue: 0,0:09:36.93,0:09:39.72,EN,,0,0,0,,So, pretty much, except for the details of reading and printing,\nDialogue: 0,0:09:40.12,0:09:41.71,EN,,0,0,0,,the only mystery that's going to be left\nDialogue: 0,0:09:41.72,0:09:43.05,EN,,0,0,0,,after you see the evaluator\nDialogue: 0,0:09:43.25,0:09:45.85,EN,,0,0,0,,is how you build list structure on conventional memories.\nDialogue: 0,0:09:46.65,0:09:48.20,EN,,0,0,0,,But we'll worry about that next time too.\nDialogue: 0,0:09:50.58,0:09:51.04,EN,,0,0,0,,OK.\nDialogue: 0,0:09:53.34,0:09:56.11,EN,,0,0,0,,Well, let's start talking about the evaluator.\nDialogue: 0,0:09:56.20,0:09:58.32,EN,,0,0,0,,The one that we're going to show you,\nDialogue: 0,0:09:58.49,0:10:01.12,EN,,0,0,0,,of course, is not, I think, nothing special about it.\nDialogue: 0,0:10:01.15,0:10:04.56,EN,,0,0,0,,It's just a particular register machine that runs LISP.\nDialogue: 0,0:10:04.81,0:10:06.09,EN,,0,0,0,,And it has seven registers,\nDialogue: 0,0:10:07.88,0:10:09.26,EN,,0,0,0,,and here are the seven registers.\nDialogue: 0,0:10:09.89,0:10:12.38,EN,,0,0,0,,There's a register, called EXP\nDialogue: 0,0:10:14.12,0:10:15.53,EN,,0,0,0,,and its job is to hold\nDialogue: 0,0:10:16.36,0:10:18.03,EN,,0,0,0,,the expression to be evaluated.\nDialogue: 0,0:10:18.37,0:10:19.80,EN,,0,0,0,,And by that, I mean\nDialogue: 0,0:10:20.38,0:10:21.64,EN,,0,0,0,,it's going to hold a pointer\nDialogue: 0,0:10:22.03,0:10:23.55,EN,,0,0,0,,to someplace in list structure memory\nDialogue: 0,0:10:23.56,0:10:25.32,EN,,0,0,0,,the expression to be evaluated.\nDialogue: 0,0:10:26.55,0:10:27.82,EN,,0,0,0,,There's a register, called ENV,\nDialogue: 0,0:10:28.88,0:10:30.28,EN,,0,0,0,,which holds the environment\nDialogue: 0,0:10:31.00,0:10:33.05,EN,,0,0,0,,in which this expression is to be evaluated.\nDialogue: 0,0:10:34.07,0:10:35.02,EN,,0,0,0,,And, again, I made a pointer.\nDialogue: 0,0:10:35.02,0:10:36.75,EN,,0,0,0,,The environment is some data structure.\nDialogue: 0,0:10:38.24,0:10:40.14,EN,,0,0,0,,There's a register, called FUN, which will\nDialogue: 0,0:10:40.75,0:10:42.54,EN,,0,0,0,,which will hold the procedure to be applied\nDialogue: 0,0:10:42.57,0:10:43.96,EN,,0,0,0,,when you go to apply a procedure.\nDialogue: 0,0:10:44.56,0:10:46.24,EN,,0,0,0,,A register, called ARGL,\nDialogue: 0,0:10:47.36,0:10:49.34,EN,,0,0,0,,which holds the list of evaluated arguments.\nDialogue: 0,0:10:50.54,0:10:51.60,EN,,0,0,0,,What you can start seeing here is\nDialogue: 0,0:10:51.63,0:10:53.14,EN,,0,0,0,,the basic structure of the evaluator.\nDialogue: 0,0:10:53.14,0:10:54.49,EN,,0,0,0,,Remember how evaluators work.\nDialogue: 0,0:10:54.49,0:10:56.62,EN,,0,0,0,,There's a piece that takes expressions and environments,\nDialogue: 0,0:10:57.67,0:10:59.71,EN,,0,0,0,,and there's a piece that takes functions\nDialogue: 0,0:10:59.74,0:11:02.14,EN,,0,0,0,,or procedures and arguments.\nDialogue: 0,0:11:03.48,0:11:06.30,EN,,0,0,0,,And going back and forth around here is the eval/apply loop.\nDialogue: 0,0:11:07.40,0:11:09.69,EN,,0,0,0,,So those are the basic pieces of the eval and apply.\nDialogue: 0,0:11:10.20,0:11:10.99,EN,,0,0,0,,Then there's some other things,\nDialogue: 0,0:11:11.00,0:11:11.61,EN,,0,0,0,,there's continue.\nDialogue: 0,0:11:11.61,0:11:15.34,EN,,0,0,0,,You just saw before how the continue register is used to\nDialogue: 0,0:11:15.34,0:11:18.04,EN,,0,0,0,,implement recursion and stack discipline.\nDialogue: 0,0:11:18.94,0:11:20.68,EN,,0,0,0,,There's a register that's going to hold the\nDialogue: 0,0:11:20.94,0:11:22.52,EN,,0,0,0,,result of some evaluation.\nDialogue: 0,0:11:24.14,0:11:24.89,EN,,0,0,0,,And then, besides that,\nDialogue: 0,0:11:24.89,0:11:26.43,EN,,0,0,0,,there's one temporary register,\nDialogue: 0,0:11:26.70,0:11:27.29,EN,,0,0,0,,called UNEV,\nDialogue: 0,0:11:27.29,0:11:29.04,EN,,0,0,0,,which typically, in the evaluator,\nDialogue: 0,0:11:29.28,0:11:32.72,EN,,0,0,0,,is going to be used to hold temporary pieces of the\nDialogue: 0,0:11:32.89,0:11:33.95,EN,,0,0,0,,expression you're working on,\nDialogue: 0,0:11:33.95,0:11:35.72,EN,,0,0,0,,which you haven't gotten around to evaluate yet\nDialogue: 0,0:11:36.97,0:11:39.82,EN,,0,0,0,,Right? So there's my machine: a seven-register machine.\nDialogue: 0,0:11:40.96,0:11:42.98,EN,,0,0,0,,And, of course, you might want to make a machine with\nDialogue: 0,0:11:42.98,0:11:44.96,EN,,0,0,0,,a lot more registers to get better performance,\nDialogue: 0,0:11:44.97,0:11:47.05,EN,,0,0,0,,but this is just a tiny, minimal one.\nDialogue: 0,0:11:48.48,0:11:49.58,EN,,0,0,0,,Well, how about the data paths?\nDialogue: 0,0:11:49.78,0:11:53.66,EN,,0,0,0,,This machine has a lot of special operations for LISP.\nDialogue: 0,0:11:55.10,0:11:58.08,EN,,0,0,0,,So, here are some typical data paths.\nDialogue: 0,0:12:00.12,0:12:01.04,EN,,0,0,0,,A typical one might be,\nDialogue: 0,0:12:01.37,0:12:03.40,EN,,0,0,0,,oh, assign to the VAL register\nDialogue: 0,0:12:03.40,0:12:04.80,EN,,0,0,0,,the contents of the EXP register.\nDialogue: 0,0:12:05.71,0:12:08.01,EN,,0,0,0,,That's in terms of those diagrams you saw,\nDialogue: 0,0:12:08.03,0:12:10.81,EN,,0,0,0,,that's a little button on some arrow.\nDialogue: 0,0:12:11.90,0:12:13.13,EN,,0,0,0,,Here's a more complicated one.\nDialogue: 0,0:12:13.69,0:12:14.80,EN,,0,0,0,,It says branch,\nDialogue: 0,0:12:15.23,0:12:19.58,EN,,0,0,0,,if the thing in the expression register is a conditional\nDialogue: 0,0:12:20.49,0:12:22.72,EN,,0,0,0,,to some label here, called the ev-conditional.\nDialogue: 0,0:12:23.80,0:12:26.23,EN,,0,0,0,,And you can imagine this implemented in a lot of different ways.\nDialogue: 0,0:12:26.23,0:12:28.36,EN,,0,0,0,,You might imagine this conditional test\nDialogue: 0,0:12:28.36,0:12:29.98,EN,,0,0,0,,as a special purpose sub-routine,\nDialogue: 0,0:12:30.60,0:12:33.95,EN,,0,0,0,,and conditional might be represented as some data abstraction\nDialogue: 0,0:12:33.96,0:12:36.00,EN,,0,0,0,,that you don't care about at this level of detail.\nDialogue: 0,0:12:36.61,0:12:37.98,EN,,0,0,0,,So that might be done as a sub-routine.\nDialogue: 0,0:12:37.98,0:12:40.67,EN,,0,0,0,,This might be a machine with hardware-types,\nDialogue: 0,0:12:40.90,0:12:44.04,EN,,0,0,0,,and conditional might be testing some bits for a particular code.\nDialogue: 0,0:12:45.35,0:12:46.41,EN,,0,0,0,,There are all sorts of ways that's\nDialogue: 0,0:12:46.41,0:12:48.48,EN,,0,0,0,,beneath the level of abstraction we're looking at.\nDialogue: 0,0:12:50.19,0:12:51.71,EN,,0,0,0,,Another kind of operation,\nDialogue: 0,0:12:51.71,0:12:53.24,EN,,0,0,0,,and there are a lot of different operations\nDialogue: 0,0:12:53.24,0:12:56.65,EN,,0,0,0,,assigned to EXP, the first clause of what's in EXP.\nDialogue: 0,0:12:56.84,0:12:58.89,EN,,0,0,0,,This might be part of processing a conditional.\nDialogue: 0,0:12:59.26,0:13:01.80,EN,,0,0,0,,And, again, first clause is some selector\nDialogue: 0,0:13:03.07,0:13:04.48,EN,,0,0,0,,whose details we don't care about.\nDialogue: 0,0:13:04.49,0:13:06.46,EN,,0,0,0,,And you can, again, imagine that as a sub-routine\nDialogue: 0,0:13:06.46,0:13:07.90,EN,,0,0,0,,which'll do some list operations,\nDialogue: 0,0:13:08.22,0:13:09.18,EN,,0,0,0,,or you can imagine that as\nDialogue: 0,0:13:09.18,0:13:10.73,EN,,0,0,0,,something that's built directly into hardware.\nDialogue: 0,0:13:12.17,0:13:13.71,EN,,0,0,0,,The reason I keep saying you can imagine it\nDialogue: 0,0:13:14.03,0:13:15.22,EN,,0,0,0,,built directly into hardware\nDialogue: 0,0:13:15.22,0:13:17.80,EN,,0,0,0,,is even though there are a lot of operations,\nDialogue: 0,0:13:18.36,0:13:19.74,EN,,0,0,0,,there are still a fixed number of them.\nDialogue: 0,0:13:20.12,0:13:21.80,EN,,0,0,0,,I forget how many, maybe 150.\nDialogue: 0,0:13:22.37,0:13:25.39,EN,,0,0,0,,So, it's plausible to think of building these directly into hardware.\nDialogue: 0,0:13:26.41,0:13:27.68,EN,,0,0,0,,Here's a more complicated one.\nDialogue: 0,0:13:28.27,0:13:29.47,EN,,0,0,0,,You can see this has to do with\nDialogue: 0,0:13:29.47,0:13:31.10,EN,,0,0,0,,looking up the values of variables.\nDialogue: 0,0:13:31.50,0:13:33.28,EN,,0,0,0,,It says assign to the VAL register\nDialogue: 0,0:13:33.45,0:13:36.91,EN,,0,0,0,,the result of looking up the variable value\nDialogue: 0,0:13:36.99,0:13:38.52,EN,,0,0,0,,of some particular expression,\nDialogue: 0,0:13:39.18,0:13:40.30,EN,,0,0,0,,which, in this case, is supposed to be\nDialogue: 0,0:13:40.33,0:13:42.00,EN,,0,0,0,,a variable in some environment.\nDialogue: 0,0:13:42.80,0:13:44.68,EN,,0,0,0,,And this'll be some operation\nDialogue: 0,0:13:45.21,0:13:47.50,EN,,0,0,0,,that search through the environment structure,\nDialogue: 0,0:13:47.52,0:13:48.97,EN,,0,0,0,,however it is represented,\nDialogue: 0,0:13:49.37,0:13:50.91,EN,,0,0,0,,and goes and looks up that variable.\nDialogue: 0,0:13:52.17,0:13:53.95,EN,,0,0,0,,And, again, that's below the level of detail\nDialogue: 0,0:13:53.96,0:13:54.86,EN,,0,0,0,,that we're thinking about.\nDialogue: 0,0:13:54.89,0:13:57.30,EN,,0,0,0,,This is... this has to do with the details of\nDialogue: 0,0:13:57.55,0:13:59.44,EN,,0,0,0,,the data structures for representing environments.\nDialogue: 0,0:14:00.07,0:14:01.21,EN,,0,0,0,,But, anyway, there is this\nDialogue: 0,0:14:01.31,0:14:03.47,EN,,0,0,0,,there is this fixed and finite number\nDialogue: 0,0:14:04.11,0:14:06.08,EN,,0,0,0,,of operations in the register machine.\nDialogue: 0,0:14:08.50,0:14:11.60,EN,,0,0,0,,Well, what's its overall structure?\nDialogue: 0,0:14:11.72,0:14:13.23,EN,,0,0,0,,Those are some typical operations.\nDialogue: 0,0:14:14.76,0:14:16.33,EN,,0,0,0,,Remember what we have to do,\nDialogue: 0,0:14:16.44,0:14:18.40,EN,,0,0,0,,we have to take the meta-circular evaluator--\nDialogue: 0,0:14:20.43,0:14:22.76,EN,,0,0,0,,and here's a piece of the meta-circular evaluator.\nDialogue: 0,0:14:22.76,0:14:26.89,EN,,0,0,0,,This is the one using abstract syntax that's in the book.\nDialogue: 0,0:14:28.22,0:14:31.53,EN,,0,0,0,,It's a little bit different from the one that Gerry shows you.\nDialogue: 0,0:14:33.50,0:14:35.10,EN,,0,0,0,,And the main thing\nDialogue: 0,0:14:35.13,0:14:37.87,EN,,0,0,0,,to remember about the evaluator is that\nDialogue: 0,0:14:37.87,0:14:40.96,EN,,0,0,0,,it's doing some sort of case analysis on the kinds of expressions:\nDialogue: 0,0:14:43.76,0:14:45.90,EN,,0,0,0,,so if it's either self-evaluated, or quoted,\nDialogue: 0,0:14:45.92,0:14:46.86,EN,,0,0,0,,or whatever else.\nDialogue: 0,0:14:48.56,0:14:50.57,EN,,0,0,0,,And then, in the general case where\nDialogue: 0,0:14:50.86,0:14:52.96,EN,,0,0,0,,the expression it's looking at is an application,\nDialogue: 0,0:14:53.55,0:14:55.36,EN,,0,0,0,,there's some tricky recursions going on.\nDialogue: 0,0:14:55.75,0:14:59.36,EN,,0,0,0,,First of all, eval has to call itself\nDialogue: 0,0:14:59.79,0:15:01.45,EN,,0,0,0,,both to evaluate the operator\nDialogue: 0,0:15:02.14,0:15:04.04,EN,,0,0,0,,and to evaluate all the operands.\nDialogue: 0,0:15:05.88,0:15:07.40,EN,,0,0,0,,So there's this sort of red recursion\nDialogue: 0,0:15:07.63,0:15:09.28,EN,,0,0,0,,of values walking down the tree\nDialogue: 0,0:15:10.94,0:15:12.27,EN,,0,0,0,,that's sort of the easy recursion.\nDialogue: 0,0:15:12.27,0:15:14.44,EN,,0,0,0,,That's just eval walking down this tree of expressions.\nDialogue: 0,0:15:14.75,0:15:15.53,EN,,0,0,0,,Then, in the evaluator,\nDialogue: 0,0:15:15.53,0:15:16.46,EN,,0,0,0,,there's a hard recursion.\nDialogue: 0,0:15:16.49,0:15:17.92,EN,,0,0,0,,There's the red to green.\nDialogue: 0,0:15:18.00,0:15:19.66,EN,,0,0,0,,Eval calls apply.\nDialogue: 0,0:15:22.47,0:15:26.45,EN,,0,0,0,,That's the case where evaluating a procedure argument\nDialogue: 0,0:15:26.45,0:15:28.72,EN,,0,0,0,,reduces to applying the procedure\nDialogue: 0,0:15:28.94,0:15:29.93,EN,,0,0,0,,to the list of arguments.\nDialogue: 0,0:15:30.37,0:15:31.76,EN,,0,0,0,,And then, apply comes over here.\nDialogue: 0,0:15:34.77,0:15:36.67,EN,,0,0,0,,Apply takes a procedure and arguments\nDialogue: 0,0:15:37.65,0:15:39.45,EN,,0,0,0,,and, in the general case\nDialogue: 0,0:15:39.48,0:15:40.81,EN,,0,0,0,,where there's a compound procedure,\nDialogue: 0,0:15:41.05,0:15:42.19,EN,,0,0,0,,apply goes around and\nDialogue: 0,0:15:42.25,0:15:43.15,EN,,0,0,0,,green calls red.\nDialogue: 0,0:15:43.34,0:15:46.44,EN,,0,0,0,,Eval-- Apply comes around and calls eval again.\nDialogue: 0,0:15:48.17,0:15:49.79,EN,,0,0,0,,Eval's the body of the procedure\nDialogue: 0,0:15:50.24,0:15:52.59,EN,,0,0,0,,in the result of extending the environment\nDialogue: 0,0:15:53.69,0:15:55.28,EN,,0,0,0,,with the parameters of the procedure\nDialogue: 0,0:15:55.48,0:15:56.92,EN,,0,0,0,,by binding the arguments.\nDialogue: 0,0:15:59.62,0:16:00.62,EN,,0,0,0,,Except in the primitive case,\nDialogue: 0,0:16:00.64,0:16:02.52,EN,,0,0,0,,where it just calls something else primitive-apply\nDialogue: 0,0:16:02.73,0:16:04.70,EN,,0,0,0,,which is not really the business of the evaluator.\nDialogue: 0,0:16:05.98,0:16:07.47,EN,,0,0,0,,So this sort of red to green,\nDialogue: 0,0:16:07.47,0:16:08.40,EN,,0,0,0,,to red to green,\nDialogue: 0,0:16:09.79,0:16:12.72,EN,,0,0,0,,Right? That's the that's the eval/apply loop,\nDialogue: 0,0:16:14.06,0:16:15.74,EN,,0,0,0,,and that's the thing that we're going to want to see\nDialogue: 0,0:16:16.19,0:16:17.72,EN,,0,0,0,,in the evaluator.\nDialogue: 0,0:16:19.69,0:16:21.07,EN,,0,0,0,,Well, it won't surprise you at all that\nDialogue: 0,0:16:21.07,0:16:23.52,EN,,0,0,0,,the two big pieces of this evaluator\nDialogue: 0,0:16:25.34,0:16:27.04,EN,,0,0,0,,are correspond to eval and apply.\nDialogue: 0,0:16:27.47,0:16:29.44,EN,,0,0,0,,There's a piece called eval-dispatch,\nDialogue: 0,0:16:29.60,0:16:31.20,EN,,0,0,0,,and a piece called apply-dispatch.\nDialogue: 0,0:16:32.00,0:16:34.09,EN,,0,0,0,,And, before we get into the details of the code,\nDialogue: 0,0:16:34.20,0:16:35.76,EN,,0,0,0,,the way to understand this is to think,\nDialogue: 0,0:16:36.09,0:16:39.02,EN,,0,0,0,,again, in terms of these pieces of evaluator\nDialogue: 0,0:16:39.02,0:16:40.97,EN,,0,0,0,,having contracts with the rest of the world.\nDialogue: 0,0:16:41.87,0:16:43.18,EN,,0,0,0,,What do they do from the outside\nDialogue: 0,0:16:43.20,0:16:45.50,EN,,0,0,0,,before getting into the grungy details?\nDialogue: 0,0:16:45.78,0:16:49.32,EN,,0,0,0,,Well, the contract for eval-dispatch--\nDialogue: 0,0:16:50.01,0:16:51.40,EN,,0,0,0,,remember, it corresponds to eval.\nDialogue: 0,0:16:51.55,0:16:54.10,EN,,0,0,0,,It's got to evaluate an expression in an environment.\nDialogue: 0,0:16:54.10,0:16:55.88,EN,,0,0,0,,So, in particular, what this one is going to do,\nDialogue: 0,0:16:56.52,0:16:58.68,EN,,0,0,0,,eval-dispatch will assume that, when you call it,\nDialogue: 0,0:16:59.68,0:17:01.48,EN,,0,0,0,,that the expression you want to evaluate\nDialogue: 0,0:17:01.48,0:17:02.52,EN,,0,0,0,,is in the EXP register.\nDialogue: 0,0:17:03.64,0:17:07.39,EN,,0,0,0,,The environment in which you want the evaluation\nDialogue: 0,0:17:07.45,0:17:09.05,EN,,0,0,0,,to take place is in the ENV register.\nDialogue: 0,0:17:09.56,0:17:10.67,EN,,0,0,0,,And continue tells you\nDialogue: 0,0:17:10.84,0:17:12.46,EN,,0,0,0,,the place where the machine should go next\nDialogue: 0,0:17:12.52,0:17:13.92,EN,,0,0,0,,when the evaluation is done.\nDialogue: 0,0:17:17.28,0:17:19.18,EN,,0,0,0,,Eval-dispatch's contract is that\nDialogue: 0,0:17:19.28,0:17:21.26,EN,,0,0,0,,it'll actually perform that evaluation,\nDialogue: 0,0:17:21.40,0:17:22.46,EN,,0,0,0,,and, at the end of which,\nDialogue: 0,0:17:23.28,0:17:25.63,EN,,0,0,0,,it'll end up at the place specified by continue.\nDialogue: 0,0:17:26.61,0:17:29.16,EN,,0,0,0,,The result of the evaluation will be in the VAL register.\nDialogue: 0,0:17:29.82,0:17:30.96,EN,,0,0,0,,And it just warns you,\nDialogue: 0,0:17:30.99,0:17:32.91,EN,,0,0,0,,it makes no promises about\nDialogue: 0,0:17:32.96,0:17:34.60,EN,,0,0,0,,what happens to rest the registers.\nDialogue: 0,0:17:35.23,0:17:36.81,EN,,0,0,0,,All other registers might be destroyed.\nDialogue: 0,0:17:37.49,0:17:40.14,EN,,0,0,0,,So, there's one piece, OK?\nDialogue: 0,0:17:41.55,0:17:43.48,EN,,0,0,0,,Together, the pieces, apply-dispatch\nDialogue: 0,0:17:43.52,0:17:44.92,EN,,0,0,0,,that corresponds to apply,\nDialogue: 0,0:17:46.09,0:17:48.43,EN,,0,0,0,,it's got to apply a procedure to some arguments,\nDialogue: 0,0:17:48.73,0:17:51.43,EN,,0,0,0,,so it assumes that this register, ARGL,\nDialogue: 0,0:17:51.68,0:17:53.77,EN,,0,0,0,,contains a list of the evaluated arguments.\nDialogue: 0,0:17:54.54,0:17:55.96,EN,,0,0,0,,FUN contains the procedure.\nDialogue: 0,0:17:57.22,0:17:58.83,EN,,0,0,0,,Those correspond to the arguments to\nDialogue: 0,0:17:58.94,0:18:01.36,EN,,0,0,0,,the apply procedure in the meta-circular evaluator.\nDialogue: 0,0:18:03.97,0:18:06.04,EN,,0,0,0,,And apply, in this particular evaluator,\nDialogue: 0,0:18:06.06,0:18:07.58,EN,,0,0,0,,we're going to use a discipline which says\nDialogue: 0,0:18:07.72,0:18:08.97,EN,,0,0,0,,the place that apply\nDialogue: 0,0:18:09.47,0:18:11.20,EN,,0,0,0,,the place the machine should go to next\nDialogue: 0,0:18:11.79,0:18:13.45,EN,,0,0,0,,when apply is done, is at the moment\nDialogue: 0,0:18:13.55,0:18:15.92,EN,,0,0,0,,apply-dispatch is called at the top of the stack\nDialogue: 0,0:18:17.07,0:18:21.24,EN,,0,0,0,,that's just discipline for the way this particular machine's organized.\nDialogue: 0,0:18:21.84,0:18:23.70,EN,,0,0,0,,And now apply's contract is given all that.\nDialogue: 0,0:18:23.93,0:18:25.37,EN,,0,0,0,,It'll perform the application.\nDialogue: 0,0:18:25.54,0:18:27.85,EN,,0,0,0,,The result of that application will end up in VAL.\nDialogue: 0,0:18:28.89,0:18:29.95,EN,,0,0,0,,The stack will be popped.\nDialogue: 0,0:18:31.12,0:18:31.66,EN,,0,0,0,,And, again,\nDialogue: 0,0:18:31.71,0:18:34.03,EN,,0,0,0,,the contents of all the other registers may be destroyed.\nDialogue: 0,0:18:34.84,0:18:37.82,EN,,0,0,0,,All right? So that's the basic organization of this machine.\nDialogue: 0,0:18:38.99,0:18:41.50,EN,,0,0,0,,Let's break for a little bit and see if there are any questions\nDialogue: 0,0:18:41.52,0:18:42.70,EN,,0,0,0,,and then we'll do a real example.\nDialogue: 0,0:18:43.53,0:19:08.11,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:19:08.14,0:19:13.47,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:19:33.10,0:19:35.87,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:19:35.87,0:19:40.38,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:19:47.85,0:19:49.95,EN,,0,0,0,,Well, let's take the register machine now,\nDialogue: 0,0:19:50.41,0:19:51.77,EN,,0,0,0,,and actually step through,\nDialogue: 0,0:19:52.27,0:19:56.94,EN,,0,0,0,,and really, in real detail,\nDialogue: 0,0:19:57.07,0:19:58.52,EN,,0,0,0,,so you see completely concrete\nDialogue: 0,0:19:58.86,0:20:01.24,EN,,0,0,0,,how some expressions are evaluated,\nDialogue: 0,0:20:03.15,0:20:06.86,EN,,0,0,0,,Alright? So, let's start with a very simple expression.\nDialogue: 0,0:20:07.45,0:20:13.52,EN,,0,0,0,,Let's evaluate the expression 1.\nDialogue: 0,0:20:18.77,0:20:20.40,EN,,0,0,0,,And we need an environment,\nDialogue: 0,0:20:20.43,0:20:22.35,EN,,0,0,0,,so let's imagine that somewhere there's an environment\nDialogue: 0,0:20:22.38,0:20:23.39,EN,,0,0,0,,we'll call it E0.\nDialogue: 0,0:20:30.06,0:20:34.56,EN,,0,0,0,,And just, since we'll use these later,\nDialogue: 0,0:20:35.62,0:20:37.04,EN,,0,0,0,,we obviously don't really need anything\nDialogue: 0,0:20:37.07,0:20:37.93,EN,,0,0,0,,to evaluate 1.\nDialogue: 0,0:20:38.36,0:20:39.45,EN,,0,0,0,,But, just for reference later,\nDialogue: 0,0:20:39.45,0:20:40.94,EN,,0,0,0,,let's assume that E0 has in it\nDialogue: 0,0:20:41.44,0:20:43.15,EN,,0,0,0,,an X that's bound to 3\nDialogue: 0,0:20:43.72,0:20:45.37,EN,,0,0,0,,and a Y that's bound to 4,\nDialogue: 0,0:20:48.27,0:20:48.78,EN,,0,0,0,,OK?\nDialogue: 0,0:20:49.14,0:20:50.12,EN,,0,0,0,,And now what we're going to do\nDialogue: 0,0:20:50.51,0:20:54.59,EN,,0,0,0,,is we're going to evaluate 1 in this environment\nDialogue: 0,0:20:55.74,0:20:58.54,EN,,0,0,0,,and so the ENV register has a pointer\nDialogue: 0,0:20:59.65,0:21:01.04,EN,,0,0,0,,to this environment, E0, all right?\nDialogue: 0,0:21:03.31,0:21:05.65,EN,,0,0,0,,Right? So let's watch that thing go.\nDialogue: 0,0:21:05.65,0:21:07.26,EN,,0,0,0,,What I'm going to do is step through the code.\nDialogue: 0,0:21:08.26,0:21:10.00,EN,,0,0,0,,And, let's see, I'll be the controller.\nDialogue: 0,0:21:10.04,0:21:10.80,EN,,0,0,0,,And now what I need,\nDialogue: 0,0:21:11.02,0:21:12.49,EN,,0,0,0,,since this gets rather complicated,\nDialogue: 0,0:21:12.98,0:21:16.83,EN,,0,0,0,,is a very little execution unit.\nDialogue: 0,0:21:16.83,0:21:18.16,EN,,0,0,0,,So here's the execution unit, OK?\nDialogue: 0,0:21:22.62,0:21:23.12,EN,,0,0,0,,OK.\nDialogue: 0,0:21:28.59,0:21:29.96,EN,,0,0,0,,All right, now we're going to start.\nDialogue: 0,0:21:30.53,0:21:32.48,EN,,0,0,0,,We're going to start the machine at eval-dispatch。\nDialogue: 0,0:21:33.26,0:21:34.62,EN,,0,0,0,,Right? That's the beginning of this.\nDialogue: 0,0:21:35.87,0:21:38.75,EN,,0,0,0,,Eval-dispatch is going to look at the expression and dispatch,\nDialogue: 0,0:21:39.32,0:21:40.06,EN,,0,0,0,,just like eval\nDialogue: 0,0:21:40.87,0:21:42.00,EN,,0,0,0,,where we look at the very first thing.\nDialogue: 0,0:21:42.04,0:21:47.95,EN,,0,0,0,,We branch on whether or not this expression is self-evaluating.\nDialogue: 0,0:21:47.95,0:21:49.96,EN,,0,0,0,,Self-evaluating is some abstraction\nDialogue: 0,0:21:49.96,0:21:51.10,EN,,0,0,0,,we put into the machine--\nDialogue: 0,0:21:52.22,0:21:53.51,EN,,0,0,0,,it's going to be true for numbers--\nDialogue: 0,0:21:53.64,0:21:55.52,EN,,0,0,0,,to a place called ev-self-eval,\nDialogue: 0,0:21:56.77,0:21:58.20,EN,,0,0,0,,So me, being the controller,\nDialogue: 0,0:21:58.22,0:21:59.55,EN,,0,0,0,,looks at ev-self-eval,\nDialogue: 0,0:22:00.06,0:22:01.07,EN,,0,0,0,,so we'll go over to there.\nDialogue: 0,0:22:02.60,0:22:04.76,EN,,0,0,0,,Ev-self-eval says fine,\nDialogue: 0,0:22:06.54,0:22:09.90,EN,,0,0,0,,assign to val whatever is in the expression unit.\nDialogue: 0,0:22:15.24,0:22:16.51,EN,,0,0,0,,And I have a bug\nDialogue: 0,0:22:17.93,0:22:20.59,EN,,0,0,0,,because what I didn't do when I initialized this machine\nDialogue: 0,0:22:21.62,0:22:22.89,EN,,0,0,0,,is also say what's supposed\nDialogue: 0,0:22:22.91,0:22:24.19,EN,,0,0,0,,to happen when it's done,\nDialogue: 0,0:22:24.65,0:22:26.83,EN,,0,0,0,,so I should have started out the machine\nDialogue: 0,0:22:27.37,0:22:29.85,EN,,0,0,0,,with done being in the continue register,\nDialogue: 0,0:22:31.18,0:22:33.26,EN,,0,0,0,,OK? So we assign to VAL.\nDialogue: 0,0:22:33.37,0:22:35.56,EN,,0,0,0,,And now go to fetch of continue,\nDialogue: 0,0:22:35.63,0:22:36.56,EN,,0,0,0,,and now change--\nDialogue: 0,0:22:38.09,0:22:38.60,EN,,0,0,0,,OK.\nDialogue: 0,0:22:40.00,0:22:41.16,EN,,0,0,0,,OK, let's try something harder.\nDialogue: 0,0:22:42.16,0:22:43.45,EN,,0,0,0,,Let's reset the machine here,\nDialogue: 0,0:22:44.86,0:22:50.88,EN,,0,0,0,,and we'll put in the expression register, X, OK?\nDialogue: 0,0:22:56.71,0:22:58.20,EN,,0,0,0,,Start again at eval-dispatch.\nDialogue: 0,0:22:59.61,0:23:01.69,EN,,0,0,0,,Check, is it self-evaluating?\nDialogue: 0,0:23:01.69,0:23:02.03,EN,,0,0,0,,No.\nDialogue: 0,0:23:02.65,0:23:03.61,EN,,0,0,0,,Is it a variable?\nDialogue: 0,0:23:04.63,0:23:05.02,EN,,0,0,0,,Yes.\nDialogue: 0,0:23:05.56,0:23:07.07,EN,,0,0,0,,We go off to ev-variable.\nDialogue: 0,0:23:08.38,0:23:10.97,EN,,0,0,0,,It says assign to VAL,\nDialogue: 0,0:23:12.13,0:23:15.69,EN,,0,0,0,,look up the variable value in the expression register\nDialogue: 0,0:23:21.23,0:23:22.91,EN,,0,0,0,,Go to fetch of continue.\nDialogue: 0,0:23:23.96,0:23:24.48,EN,,0,0,0,,PROFESSOR: Done.\nDialogue: 0,0:23:27.61,0:23:28.09,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:23:29.31,0:23:30.76,EN,,0,0,0,,Alright, Well, that's the basic idea. Those're\nDialogue: 0,0:23:31.33,0:23:32.65,EN,,0,0,0,,That's a simple operation of the machine.\nDialogue: 0,0:23:32.68,0:23:35.07,EN,,0,0,0,,Now, let's actually do something a little bit more interesting.\nDialogue: 0,0:23:36.07,0:23:38.64,EN,,0,0,0,,Let's look at the expression\nDialogue: 0,0:23:43.58,0:23:47.93,EN,,0,0,0,,the sum of x and y.\nDialogue: 0,0:23:49.69,0:23:51.28,EN,,0,0,0,,OK. And now we'll see how you start\nDialogue: 0,0:23:52.41,0:23:54.01,EN,,0,0,0,,unrolling these expression trees.\nDialogue: 0,0:23:57.13,0:23:58.68,EN,,0,0,0,,Well, start again at eval-dispatch.\nDialogue: 0,0:24:04.61,0:24:05.80,EN,,0,0,0,,Self-evaluating?\nDialogue: 0,0:24:05.95,0:24:06.52,EN,,0,0,0,,No.\nDialogue: 0,0:24:06.70,0:24:07.71,EN,,0,0,0,,Variable? No.\nDialogue: 0,0:24:07.82,0:24:08.99,EN,,0,0,0,,All the other special forms\nDialogue: 0,0:24:08.99,0:24:10.12,EN,,0,0,0,,which I didn't write down,\nDialogue: 0,0:24:10.27,0:24:12.48,EN,,0,0,0,,like quote, and lambda, and set, and whatever,\nDialogue: 0,0:24:12.48,0:24:13.08,EN,,0,0,0,,it's none of those.\nDialogue: 0,0:24:13.26,0:24:14.73,EN,,0,0,0,,It turns out to be an application,\nDialogue: 0,0:24:15.88,0:24:17.42,EN,,0,0,0,,so we go off to ev-application.\nDialogue: 0,0:24:19.97,0:24:24.94,EN,,0,0,0,,Ev-application, remember what it's going to do overall.\nDialogue: 0,0:24:25.58,0:24:28.19,EN,,0,0,0,,It is going to evaluate the operator.\nDialogue: 0,0:24:28.27,0:24:31.40,EN,,0,0,0,,It's going to evaluate the arguments,\nDialogue: 0,0:24:32.36,0:24:34.30,EN,,0,0,0,,and then it's going to go apply them.\nDialogue: 0,0:24:35.06,0:24:36.09,EN,,0,0,0,,So, before we start,\nDialogue: 0,0:24:36.94,0:24:37.88,EN,,0,0,0,,since we're being very literal,\nDialogue: 0,0:24:37.88,0:24:38.88,EN,,0,0,0,,we'd better remember that,\nDialogue: 0,0:24:39.07,0:24:40.54,EN,,0,0,0,,somewhere in this environment,\nDialogue: 0,0:24:40.57,0:24:42.36,EN,,0,0,0,,it's linked to another environment\nDialogue: 0,0:24:43.98,0:24:44.94,EN,,0,0,0,,in which plus\nDialogue: 0,0:24:45.72,0:24:49.16,EN,,0,0,0,,is bound to the primitive procedure plus\nDialogue: 0,0:24:51.63,0:24:54.03,EN,,0,0,0,,before we get an unknown variable in our machine.\nDialogue: 0,0:24:55.34,0:24:56.84,EN,,0,0,0,,OK, so we're at ev-application.\nDialogue: 0,0:24:59.85,0:25:04.32,EN,,0,0,0,,OK, assign to UNEV the operands\nDialogue: 0,0:25:04.92,0:25:06.89,EN,,0,0,0,,of what's in the expression register.\nDialogue: 0,0:25:07.61,0:25:08.83,EN,,0,0,0,,OK. Those are the operands.\nDialogue: 0,0:25:09.23,0:25:11.66,EN,,0,0,0,,UNEV's a temporary register\nDialogue: 0,0:25:11.68,0:25:12.59,EN,,0,0,0,,where we're going to save them.\nDialogue: 0,0:25:13.22,0:25:13.86,EN,,0,0,0,,PROFESSOR: I'm assigning.\nDialogue: 0,0:25:14.28,0:25:16.62,EN,,0,0,0,,PROFESSOR: Assign to EXP the operator.\nDialogue: 0,0:25:18.07,0:25:20.09,EN,,0,0,0,,Now, notice we've destroyed that expression in EXP,\nDialogue: 0,0:25:21.84,0:25:23.61,EN,,0,0,0,,but the piece that we need is now in UNEV.\nDialogue: 0,0:25:25.82,0:25:26.81,EN,,0,0,0,,Now, we're going to get set up to\nDialogue: 0,0:25:26.81,0:25:28.59,EN,,0,0,0,,to recursively evaluate the operator.\nDialogue: 0,0:25:28.75,0:25:31.69,EN,,0,0,0,,Save the continue register on the stack.\nDialogue: 0,0:25:34.86,0:25:36.09,EN,,0,0,0,,Save the environment.\nDialogue: 0,0:25:40.48,0:25:41.69,EN,,0,0,0,,Save UNEV.\nDialogue: 0,0:25:49.53,0:25:54.64,EN,,0,0,0,,OK, assign to continue a label called eval-args.\nDialogue: 0,0:26:01.40,0:26:01.95,EN,,0,0,0,,Now, what have we done?\nDialogue: 0,0:26:01.95,0:26:04.38,EN,,0,0,0,,We've set up for a recursive call.\nDialogue: 0,0:26:04.38,0:26:05.88,EN,,0,0,0,,We're about to go to eval-dispatch.\nDialogue: 0,0:26:06.28,0:26:08.83,EN,,0,0,0,,We've set up for a recursive call to eval-dispatch.\nDialogue: 0,0:26:10.23,0:26:10.86,EN,,0,0,0,,What did we do?\nDialogue: 0,0:26:11.02,0:26:13.64,EN,,0,0,0,,We took the things we're going to need later,\nDialogue: 0,0:26:14.48,0:26:15.98,EN,,0,0,0,,those operands that were in UNEV;\nDialogue: 0,0:26:16.36,0:26:18.99,EN,,0,0,0,,the environment in which we're going to eventually have to,\nDialogue: 0,0:26:19.16,0:26:20.72,EN,,0,0,0,,maybe, evaluate those operands;\nDialogue: 0,0:26:22.28,0:26:23.93,EN,,0,0,0,,the place we eventually want to go to,\nDialogue: 0,0:26:23.95,0:26:25.07,EN,,0,0,0,,which, in this case, was done;\nDialogue: 0,0:26:25.34,0:26:26.70,EN,,0,0,0,,we've saved them on the stack.\nDialogue: 0,0:26:27.10,0:26:28.41,EN,,0,0,0,,The reason we saved them on the stack\nDialogue: 0,0:26:28.43,0:26:30.67,EN,,0,0,0,,is because eval-dispatch makes no promises\nDialogue: 0,0:26:30.94,0:26:32.54,EN,,0,0,0,,about what registers it may destroy.\nDialogue: 0,0:26:33.55,0:26:35.02,EN,,0,0,0,,So all that stuff is saved on the stack.\nDialogue: 0,0:26:35.02,0:26:36.91,EN,,0,0,0,,Now, we've set up eval-dispatch's contract.\nDialogue: 0,0:26:37.38,0:26:38.75,EN,,0,0,0,,There's a new expression,\nDialogue: 0,0:26:38.78,0:26:40.04,EN,,0,0,0,,which is the operator plus;\nDialogue: 0,0:26:41.07,0:26:41.95,EN,,0,0,0,,a new environment,\nDialogue: 0,0:26:41.98,0:26:43.60,EN,,0,0,0,,although, in this case, it's the same one;\nDialogue: 0,0:26:44.25,0:26:45.87,EN,,0,0,0,,and a new place to go to when you're done,\nDialogue: 0,0:26:45.87,0:26:46.91,EN,,0,0,0,,which is eval-args.\nDialogue: 0,0:26:47.60,0:26:48.13,EN,,0,0,0,,So that's set up.\nDialogue: 0,0:26:48.13,0:26:49.68,EN,,0,0,0,,Now, we're going to go off to eval-dispatch.\nDialogue: 0,0:26:50.89,0:26:52.36,EN,,0,0,0,,Here we are back at eval-dispatch.\nDialogue: 0,0:26:53.05,0:26:54.40,EN,,0,0,0,,It's not self-evaluating.\nDialogue: 0,0:26:54.44,0:26:55.47,EN,,0,0,0,,Oh, it's a variable,\nDialogue: 0,0:26:56.32,0:26:58.06,EN,,0,0,0,,so we'd better go off to ev-variable,\nDialogue: 0,0:26:59.79,0:27:02.65,EN,,0,0,0,,Right? Ev-variable is assigned to VAL.\nDialogue: 0,0:27:02.70,0:27:06.33,EN,,0,0,0,,Look up the variable value of the expression,\nDialogue: 0,0:27:08.49,0:27:10.75,EN,,0,0,0,,OK? So VAL is the primitive procedure plus.\nDialogue: 0,0:27:13.37,0:27:15.16,EN,,0,0,0,,And go to fetch of continue.\nDialogue: 0,0:27:15.23,0:27:16.11,EN,,0,0,0,,PROFESSOR: Eval-args.\nDialogue: 0,0:27:16.20,0:27:18.73,EN,,0,0,0,,PROFESSOR: Right, which is now eval-args not done.\nDialogue: 0,0:27:19.42,0:27:21.26,EN,,0,0,0,,So we come back here at eval-args,\nDialogue: 0,0:27:22.16,0:27:23.02,EN,,0,0,0,,and what do we do?\nDialogue: 0,0:27:23.07,0:27:24.84,EN,,0,0,0,,We're going to restore the stuff that we saved,\nDialogue: 0,0:27:25.20,0:27:26.57,EN,,0,0,0,,so we restore UNEV.\nDialogue: 0,0:27:29.21,0:27:31.69,EN,,0,0,0,,And notice, there, it wasn't necessary,\nDialogue: 0,0:27:31.74,0:27:32.90,EN,,0,0,0,,although, in general, it would be.\nDialogue: 0,0:27:32.90,0:27:35.16,EN,,0,0,0,,It might be some arbitrary evaluation that happened.\nDialogue: 0,0:27:35.43,0:27:36.70,EN,,0,0,0,,We restore ENV.\nDialogue: 0,0:27:47.87,0:27:52.04,EN,,0,0,0,,OK, we assign to FUN fetch of VAL.\nDialogue: 0,0:27:59.95,0:28:02.81,EN,,0,0,0,,OK, now, we're going to go off and start evaluating some arguments.\nDialogue: 0,0:28:04.34,0:28:06.48,EN,,0,0,0,,Well, first thing we'd better do is save FUN\nDialogue: 0,0:28:07.42,0:28:10.62,EN,,0,0,0,,because some arbitrary stuff might happen in that evaluation.\nDialogue: 0,0:28:15.33,0:28:16.88,EN,,0,0,0,,We initialize the argument list.\nDialogue: 0,0:28:16.91,0:28:19.29,EN,,0,0,0,,Assign to argl an empty argument list,\nDialogue: 0,0:28:20.88,0:28:22.17,EN,,0,0,0,,and go to eval-arg-loop,\nDialogue: 0,0:28:24.86,0:28:26.27,EN,,0,0,0,,At eval-arg-loop,\nDialogue: 0,0:28:27.77,0:28:31.53,EN,,0,0,0,,the idea of this is we're going to evaluate the pieces of the\nDialogue: 0,0:28:31.61,0:28:33.37,EN,,0,0,0,,expressions that are in UNEV, one by one,\nDialogue: 0,0:28:33.54,0:28:35.68,EN,,0,0,0,,and move them from unevaluated in UNEV\nDialogue: 0,0:28:35.90,0:28:37.26,EN,,0,0,0,,to evaluated in the arg list.\nDialogue: 0,0:28:37.84,0:28:39.18,EN,,0,0,0,,OK. So we save argl.\nDialogue: 0,0:28:43.95,0:28:47.26,EN,,0,0,0,,We assign to EXP the first operand\nDialogue: 0,0:28:47.37,0:28:48.38,EN,,0,0,0,,of the stuff in UNEV.\nDialogue: 0,0:28:53.77,0:28:55.89,EN,,0,0,0,,Now, we check and see if that was the last operand.\nDialogue: 0,0:28:55.89,0:28:56.91,EN,,0,0,0,,In this case, it is not.\nDialogue: 0,0:28:58.99,0:29:01.55,EN,,0,0,0,,So we save the environment.\nDialogue: 0,0:29:08.00,0:29:10.06,EN,,0,0,0,,We save UNEV\nDialogue: 0,0:29:11.61,0:29:13.50,EN,,0,0,0,,because those are all things we might need later.\nDialogue: 0,0:29:13.50,0:29:14.40,EN,,0,0,0,,We're going to need the environment\nDialogue: 0,0:29:14.44,0:29:15.64,EN,,0,0,0,,to do some more evaluations.\nDialogue: 0,0:29:15.80,0:29:16.60,EN,,0,0,0,,We're going to need UNEV\nDialogue: 0,0:29:16.62,0:29:19.20,EN,,0,0,0,,to look at what the rest of those arguments were.\nDialogue: 0,0:29:20.34,0:29:21.55,EN,,0,0,0,,We're going to assign continue\nDialogue: 0,0:29:21.56,0:29:24.44,EN,,0,0,0,,a place called accumulate-args, or accumulate-arg.\nDialogue: 0,0:29:31.13,0:29:34.01,EN,,0,0,0,,OK, now, we've set up for another call to eval-dispatch,\nDialogue: 0,0:29:37.07,0:29:38.54,EN,,0,0,0,,All right, now, let me short-circuit this\nDialogue: 0,0:29:39.12,0:29:41.09,EN,,0,0,0,,so we don't go through the details of eval-dispatch.\nDialogue: 0,0:29:41.09,0:29:42.64,EN,,0,0,0,,Eval-dispatch's contract says\nDialogue: 0,0:29:42.97,0:29:45.00,EN,,0,0,0,,i'm going to end up,\nDialogue: 0,0:29:45.13,0:29:45.96,EN,,0,0,0,,the world will end up,\nDialogue: 0,0:29:46.03,0:29:48.20,EN,,0,0,0,,with the value of evaluating this expression\nDialogue: 0,0:29:48.24,0:29:50.27,EN,,0,0,0,,in this environment in the VAL register,\nDialogue: 0,0:29:50.27,0:29:51.07,EN,,0,0,0,,and I'll end up there.\nDialogue: 0,0:29:51.32,0:29:52.62,EN,,0,0,0,,So we short-circuit all of this,\nDialogue: 0,0:29:54.43,0:29:56.36,EN,,0,0,0,,and a 3 ends up in VAL.\nDialogue: 0,0:29:58.01,0:29:59.76,EN,,0,0,0,,And, when we return from eval-dispatch,\nDialogue: 0,0:29:59.76,0:30:01.76,EN,,0,0,0,,we're going to return to accumulate-arg.\nDialogue: 0,0:30:02.30,0:30:03.23,EN,,0,0,0,,PROFESSOR: Accumulate-arg.\nDialogue: 0,0:30:06.22,0:30:08.20,EN,,0,0,0,,PROFESSOR: With 3 in the VAL register, OK?\nDialogue: 0,0:30:08.72,0:30:10.59,EN,,0,0,0,,So that short-circuited that evaluation.\nDialogue: 0,0:30:10.65,0:30:11.32,EN,,0,0,0,,Now, what do we do?\nDialogue: 0,0:30:11.32,0:30:13.68,EN,,0,0,0,,We're going to go back and look at the rest of the arguments,\nDialogue: 0,0:30:13.68,0:30:14.83,EN,,0,0,0,,so we restore UNEV.\nDialogue: 0,0:30:17.51,0:30:19.00,EN,,0,0,0,,We restore ENV.\nDialogue: 0,0:30:25.79,0:30:27.05,EN,,0,0,0,,We restore argl.\nDialogue: 0,0:30:28.65,0:30:29.17,EN,,0,0,0,,One thing.\nDialogue: 0,0:30:30.06,0:30:31.45,EN,,0,0,0,,PROFESSOR: Oops! Parity error.\nDialogue: 0,0:30:33.76,0:30:34.83,EN,,0,0,0,,PROFESSOR: Restore argl.\nDialogue: 0,0:30:45.57,0:30:49.76,EN,,0,0,0,,OK, we assign to argl consing on\nDialogue: 0,0:30:50.65,0:30:52.64,EN,,0,0,0,,fetch of the value register to what's in argl.\nDialogue: 0,0:30:59.36,0:31:02.96,EN,,0,0,0,,OK, we assign to UNEV the rest of the operands\nDialogue: 0,0:31:03.34,0:31:04.52,EN,,0,0,0,,in fetch of UNEV,\nDialogue: 0,0:31:08.91,0:31:10.76,EN,,0,0,0,,and we go back to eval-arg-loop.\nDialogue: 0,0:31:11.51,0:31:12.28,EN,,0,0,0,,PROFESSOR: Eval-arg-loop.\nDialogue: 0,0:31:12.28,0:31:12.86,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:31:15.88,0:31:17.08,EN,,0,0,0,,Now, we're about to do the next argument,\nDialogue: 0,0:31:17.58,0:31:19.31,EN,,0,0,0,,so the first thing we do is save argl.\nDialogue: 0,0:31:25.40,0:31:28.27,EN,,0,0,0,,OK, we assign to EXP the first operand\nDialogue: 0,0:31:29.15,0:31:30.81,EN,,0,0,0,,of fetch of UNEV.\nDialogue: 0,0:31:34.72,0:31:37.02,EN,,0,0,0,,OK, we test and see if that's the last operand.\nDialogue: 0,0:31:37.02,0:31:38.00,EN,,0,0,0,,In this case, it is\nDialogue: 0,0:31:39.08,0:31:40.27,EN,,0,0,0,,so we're going to go to a special place\nDialogue: 0,0:31:40.28,0:31:42.06,EN,,0,0,0,,that says evaluate the last argument\nDialogue: 0,0:31:43.37,0:31:45.07,EN,,0,0,0,,because, notice,after evaluating the argument,\nDialogue: 0,0:31:45.10,0:31:46.62,EN,,0,0,0,,we don't need the environment any more.\nDialogue: 0,0:31:47.64,0:31:48.78,EN,,0,0,0,,That's going to be the difference.\nDialogue: 0,0:31:50.25,0:31:51.85,EN,,0,0,0,,So here, at eval-last-arg,\nDialogue: 0,0:31:52.24,0:31:54.92,EN,,0,0,0,,which is assigned to continue accumulate-last-arg,\nDialogue: 0,0:32:04.27,0:32:06.90,EN,,0,0,0,,now, we're set up again for eval-dispatch.\nDialogue: 0,0:32:06.90,0:32:08.51,EN,,0,0,0,,We've got a place to go to when we're done.\nDialogue: 0,0:32:08.62,0:32:09.84,EN,,0,0,0,,We've got an expression.\nDialogue: 0,0:32:09.84,0:32:10.80,EN,,0,0,0,,We've got an environment.\nDialogue: 0,0:32:11.33,0:32:13.64,EN,,0,0,0,,OK, so we'll short-circuit the call to eval-dispatch.\nDialogue: 0,0:32:14.37,0:32:16.41,EN,,0,0,0,,And what'll happen is there's a y there,\nDialogue: 0,0:32:16.70,0:32:18.56,EN,,0,0,0,,it's 4 in that environment,\nDialogue: 0,0:32:18.60,0:32:20.09,EN,,0,0,0,,so VAL will end up with 4 in it.\nDialogue: 0,0:32:21.06,0:32:22.86,EN,,0,0,0,,And, then, we're going to end up at accumulate-last-arg, OK?\nDialogue: 0,0:32:25.45,0:32:26.91,EN,,0,0,0,,So, at accumulate-last-arg,\nDialogue: 0,0:32:29.28,0:32:30.52,EN,,0,0,0,,we restore argl.\nDialogue: 0,0:32:37.69,0:32:42.76,EN,,0,0,0,,We assign to argl, we assign to argl cons,\nDialogue: 0,0:32:43.60,0:32:45.83,EN,,0,0,0,,of fetch of the new value onto it,\nDialogue: 0,0:32:45.93,0:32:47.39,EN,,0,0,0,,so we cons a 4 onto that.\nDialogue: 0,0:32:49.85,0:32:52.52,EN,,0,0,0,,We restore what was saved in the function register.\nDialogue: 0,0:32:53.77,0:32:54.99,EN,,0,0,0,,And notice, in this case,\nDialogue: 0,0:32:55.00,0:32:56.27,EN,,0,0,0,,it had not been destroyed,\nDialogue: 0,0:32:56.38,0:32:57.72,EN,,0,0,0,,but in general, it will be.\nDialogue: 0,0:32:59.13,0:33:01.50,EN,,0,0,0,,And now, we're ready to go off to apply-dispatch,\nDialogue: 0,0:33:02.65,0:33:04.40,EN,,0,0,0,,Alright? So we've just gone through the eval.\nDialogue: 0,0:33:04.51,0:33:05.85,EN,,0,0,0,,We evaluated the argument,\nDialogue: 0,0:33:06.46,0:33:07.98,EN,,0,0,0,,the operator, and the arguments,\nDialogue: 0,0:33:07.98,0:33:09.24,EN,,0,0,0,,and now, we're about to apply them.\nDialogue: 0,0:33:09.58,0:33:11.37,EN,,0,0,0,,So we come off to apply-dispatch here\nDialogue: 0,0:33:18.03,0:33:19.29,EN,,0,0,0,,We come off to apply-dispatch,\nDialogue: 0,0:33:21.05,0:33:22.41,EN,,0,0,0,,and we're going to check whether it's a primitive\nDialogue: 0,0:33:22.41,0:33:23.45,EN,,0,0,0,,or a compound procedure.\nDialogue: 0,0:33:23.64,0:33:24.20,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:33:24.54,0:33:24.83,EN,,0,0,0,,PROFESSOR: All right.\nDialogue: 0,0:33:24.89,0:33:26.52,EN,,0,0,0,,So, in this case, it's a primitive procedure,\nDialogue: 0,0:33:27.45,0:33:28.91,EN,,0,0,0,,and we go off to primitive-apply.\nDialogue: 0,0:33:29.79,0:33:31.36,EN,,0,0,0,,So we go off to primitive-apply,\nDialogue: 0,0:33:33.71,0:33:35.37,EN,,0,0,0,,that says assign to VAL\nDialogue: 0,0:33:35.69,0:33:38.25,EN,,0,0,0,,result of applying primitive procedure\nDialogue: 0,0:33:38.36,0:33:40.30,EN,,0,0,0,,of the function to the argument list.\nDialogue: 0,0:33:41.31,0:33:42.43,EN,,0,0,0,,PROFESSOR: I don't know how to add.\nDialogue: 0,0:33:42.54,0:33:43.80,EN,,0,0,0,,I'm just an execution unit.\nDialogue: 0,0:33:44.14,0:33:45.35,EN,,0,0,0,,PROFESSOR: Well, I don't know how to add either.\nDialogue: 0,0:33:45.35,0:33:46.51,EN,,0,0,0,,I'm just the evaluator,\nDialogue: 0,0:33:47.08,0:33:48.36,EN,,0,0,0,,so we need a primitive operator.\nDialogue: 0,0:33:48.36,0:33:49.72,EN,,0,0,0,,Let's see, so the primitive operator,\nDialogue: 0,0:33:49.76,0:33:52.36,EN,,0,0,0,,What's the... what's the sum of 3 and 4?\nDialogue: 0,0:33:52.86,0:33:53.32,EN,,0,0,0,,AUDIENCE: 7.\nDialogue: 0,0:33:53.71,0:33:54.65,EN,,0,0,0,,PROFESSOR: OK, 7.\nDialogue: 0,0:33:55.32,0:33:55.99,EN,,0,0,0,,PROFESSOR: Thank you.\nDialogue: 0,0:33:59.20,0:34:00.60,EN,,0,0,0,,PROFESSOR: Now, we restore continue,\nDialogue: 0,0:34:11.58,0:34:12.90,EN,,0,0,0,,and we go to fetch of continue.\nDialogue: 0,0:34:13.07,0:34:13.47,EN,,0,0,0,,PROFESSOR: Done.\nDialogue: 0,0:34:14.20,0:34:14.67,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:34:14.92,0:34:18.41,EN,,0,0,0,,Well, that was in as much detail as you will ever see.\nDialogue: 0,0:34:18.41,0:34:20.19,EN,,0,0,0,,We'll never do it in as much detail again.\nDialogue: 0,0:34:21.59,0:34:23.92,EN,,0,0,0,,One very important thing to notice\nDialogue: 0,0:34:24.91,0:34:27.55,EN,,0,0,0,,is that we just executed a recursive procedure,\nDialogue: 0,0:34:29.56,0:34:31.17,EN,,0,0,0,,Right? This whole thing, we used a stack\nDialogue: 0,0:34:31.17,0:34:32.75,EN,,0,0,0,,and the evaluator was recursive.\nDialogue: 0,0:34:33.07,0:34:35.88,EN,,0,0,0,,A lot of people think the reason that you need a stack\nDialogue: 0,0:34:36.48,0:34:37.85,EN,,0,0,0,,and recursion in an evaluator\nDialogue: 0,0:34:37.87,0:34:38.97,EN,,0,0,0,,is because you might be\nDialogue: 0,0:34:39.09,0:34:42.15,EN,,0,0,0,,evaluating recursive procedures like factorial or Fibonacci.\nDialogue: 0,0:34:42.15,0:34:42.92,EN,,0,0,0,,It's not true.\nDialogue: 0,0:34:43.67,0:34:44.99,EN,,0,0,0,,So you notice we did recursion here,\nDialogue: 0,0:34:45.00,0:34:46.86,EN,,0,0,0,,and all we evaluated was (+ x y)\nDialogue: 0,0:34:47.77,0:34:50.65,EN,,0,0,0,,Right? The reason that you need recursion in the evaluator\nDialogue: 0,0:34:50.96,0:34:52.97,EN,,0,0,0,,is because the evaluation process,\nDialogue: 0,0:34:52.99,0:34:54.06,EN,,0,0,0,,itself, is recursive.\nDialogue: 0,0:34:54.45,0:34:56.17,EN,,0,0,0,,Right? It's not because the procedure\nDialogue: 0,0:34:56.32,0:34:58.09,EN,,0,0,0,,that you might be evaluating in LISP\nDialogue: 0,0:34:58.12,0:34:59.27,EN,,0,0,0,,is a recursive procedure.\nDialogue: 0,0:34:59.27,0:35:00.52,EN,,0,0,0,,So that's an important thing\nDialogue: 0,0:35:00.52,0:35:02.14,EN,,0,0,0,,that people get confused about a lot.\nDialogue: 0,0:35:03.01,0:35:04.27,EN,,0,0,0,,The other thing to notice is that,\nDialogue: 0,0:35:04.27,0:35:05.64,EN,,0,0,0,,when we're done here,\nDialogue: 0,0:35:06.28,0:35:07.12,EN,,0,0,0,,we're really done.\nDialogue: 0,0:35:07.12,0:35:08.49,EN,,0,0,0,,Not only are we at done,\nDialogue: 0,0:35:09.45,0:35:13.23,EN,,0,0,0,,but there's no accumulated stuff on the stack,\nDialogue: 0,0:35:13.60,0:35:15.71,EN,,0,0,0,,Right? The machine is back to its initial state.\nDialogue: 0,0:35:17.00,0:35:18.75,EN,,0,0,0,,So that's part of what it means to be done.\nDialogue: 0,0:35:19.71,0:35:21.04,EN,,0,0,0,,Another way to say that is\nDialogue: 0,0:35:22.72,0:35:26.04,EN,,0,0,0,,the evaluation process has reduced\nDialogue: 0,0:35:26.41,0:35:28.32,EN,,0,0,0,,the expression, plus X, Y,\nDialogue: 0,0:35:30.54,0:35:32.78,EN,,0,0,0,,to the value here, 7.\nDialogue: 0,0:35:33.24,0:35:35.45,EN,,0,0,0,,And by reduced, I mean a very particular thing.\nDialogue: 0,0:35:36.01,0:35:38.18,EN,,0,0,0,,It means that there's nothing left on the stack.\nDialogue: 0,0:35:38.18,0:35:40.36,EN,,0,0,0,,The machine is now in the same state,\nDialogue: 0,0:35:40.92,0:35:42.65,EN,,0,0,0,,except there's something in the value register.\nDialogue: 0,0:35:42.72,0:35:44.52,EN,,0,0,0,,It's not part of a sub-problem of anything.\nDialogue: 0,0:35:44.52,0:35:45.63,EN,,0,0,0,,There's nothing to go back to.\nDialogue: 0,0:35:46.12,0:35:46.96,EN,,0,0,0,,OK. Let's break.\nDialogue: 0,0:35:50.16,0:35:50.76,EN,,0,0,0,,Question?\nDialogue: 0,0:35:51.08,0:35:54.02,EN,,0,0,0,,AUDIENCE: The question here, in the stack,\nDialogue: 0,0:35:54.02,0:35:55.82,EN,,0,0,0,,is because the data may be recursive.\nDialogue: 0,0:35:56.20,0:35:58.75,EN,,0,0,0,,You may have embedded expressions, for instance.\nDialogue: 0,0:35:59.31,0:36:02.08,EN,,0,0,0,,PROFESSOR: Yes, because you might have embedded expressions.\nDialogue: 0,0:36:02.08,0:36:04.77,EN,,0,0,0,,But, again, don't confuse that\nDialogue: 0,0:36:04.77,0:36:07.98,EN,,0,0,0,,with what people sometimes mean by the data may be recursive,\nDialogue: 0,0:36:08.00,0:36:10.35,EN,,0,0,0,,which is to say you have these list-structured,\nDialogue: 0,0:36:11.04,0:36:12.93,EN,,0,0,0,,recursive data list operations.\nDialogue: 0,0:36:12.93,0:36:13.96,EN,,0,0,0,,That has nothing to do with it.\nDialogue: 0,0:36:13.98,0:36:16.16,EN,,0,0,0,,It's simply that the expressions contain sub-expressions.\nDialogue: 0,0:36:20.04,0:36:23.52,EN,,0,0,0,,AUDIENCE: Why is it that the order of the arguments in the arg list got reversed?\nDialogue: 0,0:36:23.55,0:36:25.29,EN,,0,0,0,,PROFESSOR: Ah! Yes, I should've mentioned that.\nDialogue: 0,0:36:27.26,0:36:29.07,EN,,0,0,0,,Here, the reason the order is reversed--\nDialogue: 0,0:36:32.78,0:36:35.37,EN,,0,0,0,,it's a question of what you mean by reversed.\nDialogue: 0,0:36:36.05,0:36:39.90,EN,,0,0,0,,I believe it was Newton.\nDialogue: 0,0:36:40.91,0:36:42.41,EN,,0,0,0,,In the very early part of optics,\nDialogue: 0,0:36:42.43,0:36:43.26,EN,,0,0,0,,people realized\nDialogue: 0,0:36:43.61,0:36:45.36,EN,,0,0,0,,that when you look through the lens of your eye,\nDialogue: 0,0:36:45.50,0:36:46.73,EN,,0,0,0,,the image was up-side down.\nDialogue: 0,0:36:46.73,0:36:48.04,EN,,0,0,0,,And there was a lot of argument about\nDialogue: 0,0:36:48.04,0:36:50.48,EN,,0,0,0,,why that didn't mean you saw things up-side down.\nDialogue: 0,0:36:51.28,0:36:52.65,EN,,0,0,0,,So it's sort of the same issue.\nDialogue: 0,0:36:52.86,0:36:53.90,EN,,0,0,0,,Reversed from what?\nDialogue: 0,0:36:54.81,0:36:56.24,EN,,0,0,0,,So we just need some convention.\nDialogue: 0,0:36:56.59,0:37:00.35,EN,,0,0,0,,So all we.. The reason that they're coming at 4, 3\nDialogue: 0,0:37:00.80,0:37:02.49,EN,,0,0,0,,is because taking UNEV\nDialogue: 0,0:37:02.52,0:37:04.03,EN,,0,0,0,,and consing the result onto argl.\nDialogue: 0,0:37:04.52,0:37:06.68,EN,,0,0,0,,So you have to realize you've made that convention.\nDialogue: 0,0:37:06.86,0:37:09.37,EN,,0,0,0,,The place that you have to realize that--\nDialogue: 0,0:37:09.98,0:37:11.23,EN,,0,0,0,,well, there's actually two places.\nDialogue: 0,0:37:11.23,0:37:12.91,EN,,0,0,0,,One is in apply-primitive-operator,\nDialogue: 0,0:37:12.91,0:37:14.06,EN,,0,0,0,,which has to realize that\nDialogue: 0,0:37:15.12,0:37:16.75,EN,,0,0,0,,the arguments to primitives go in,\nDialogue: 0,0:37:16.78,0:37:18.72,EN,,0,0,0,,the opposite order from the way you're writing them down.\nDialogue: 0,0:37:19.49,0:37:21.00,EN,,0,0,0,,And the other one is, we'll see later\nDialogue: 0,0:37:21.07,0:37:23.80,EN,,0,0,0,,when you actually go to bind a function's parameters,\nDialogue: 0,0:37:24.01,0:37:25.74,EN,,0,0,0,,you should realize the arguments are going to come in\nDialogue: 0,0:37:25.74,0:37:28.54,EN,,0,0,0,,from the opposite order of the variables to which you're binding them.\nDialogue: 0,0:37:28.87,0:37:30.17,EN,,0,0,0,,So, if you just keep track of that,\nDialogue: 0,0:37:31.08,0:37:31.83,EN,,0,0,0,,there's no problem.\nDialogue: 0,0:37:31.83,0:37:33.69,EN,,0,0,0,,Also, this is completely arbitrary\nDialogue: 0,0:37:33.90,0:37:34.96,EN,,0,0,0,,because, if we'd done,\nDialogue: 0,0:37:35.10,0:37:37.15,EN,,0,0,0,,say, an iteration through a vector assigning them,\nDialogue: 0,0:37:37.42,0:37:38.73,EN,,0,0,0,,they might come out in the other order.\nDialogue: 0,0:37:40.41,0:37:42.04,EN,,0,0,0,,OK. So it's just a convention of the way\nDialogue: 0,0:37:42.06,0:37:43.53,EN,,0,0,0,,this particular evaluator works.\nDialogue: 0,0:37:45.39,0:37:46.24,EN,,0,0,0,,All right, let's take a break.\nDialogue: 0,0:37:46.33,0:38:02.44,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:38:02.44,0:38:07.64,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:38:28.62,0:38:32.51,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:38:32.51,0:38:35.68,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:38:41.84,0:38:45.31,EN,,0,0,0,,Professor: We just saw evaluating an expression\nDialogue: 0,0:38:45.60,0:38:47.08,EN,,0,0,0,,and, of course, that was very simple one. But\nDialogue: 0,0:38:48.81,0:38:50.24,EN,,0,0,0,,in essence, it would be no different\nDialogue: 0,0:38:50.24,0:38:52.03,EN,,0,0,0,,if it was some big nested expression,\nDialogue: 0,0:38:52.03,0:38:54.57,EN,,0,0,0,,so there would just be deeper recursion on the stack.\nDialogue: 0,0:38:55.13,0:38:56.03,EN,,0,0,0,,But what I want to do now\nDialogue: 0,0:38:56.04,0:38:56.91,EN,,0,0,0,,is show you the last piece.\nDialogue: 0,0:38:56.92,0:38:59.82,EN,,0,0,0,,I want to walk you around this eval and apply loop,\nDialogue: 0,0:39:01.01,0:39:02.81,EN,,0,0,0,,That's the thing we haven't seen, really.\nDialogue: 0,0:39:03.00,0:39:04.75,EN,,0,0,0,,We haven't seen any compound procedures\nDialogue: 0,0:39:05.20,0:39:07.79,EN,,0,0,0,,where evalutation of procedure reduces to\nDialogue: 0,0:39:07.92,0:39:10.11,EN,,0,0,0,,where applying of procedure reduces to\nDialogue: 0,0:39:10.12,0:39:11.64,EN,,0,0,0,,evaluating the body of the procedure,\nDialogue: 0,0:39:12.44,0:39:15.88,EN,,0,0,0,,so let's just suppose we had this.\nDialogue: 0,0:39:15.93,0:39:17.44,EN,,0,0,0,,Suppose we were looking at the procedure\nDialogue: 0,0:39:18.07,0:39:31.60,EN,,0,0,0,,define F of A and B to be the sum of A and B.\nDialogue: 0,0:39:33.99,0:39:37.32,EN,,0,0,0,,So, as we typed in that procedure previously,\nDialogue: 0,0:39:37.69,0:39:41.64,EN,,0,0,0,,and now we're going to evaluate F of X and Y\nDialogue: 0,0:39:42.27,0:39:44.20,EN,,0,0,0,,again, in this environment, E,0,\nDialogue: 0,0:39:44.35,0:39:47.02,EN,,0,0,0,,where X is bound to 3 and Y is bound to 4.\nDialogue: 0,0:39:50.78,0:39:52.11,EN,,0,0,0,,When the defined is executed,\nDialogue: 0,0:39:52.12,0:39:53.69,EN,,0,0,0,,remember, there's a lambda here,\nDialogue: 0,0:39:53.82,0:39:55.53,EN,,0,0,0,,and lambdas create procedures.\nDialogue: 0,0:39:55.95,0:39:58.49,EN,,0,0,0,,And, basically, what will happen is,\nDialogue: 0,0:39:59.63,0:40:00.68,EN,,0,0,0,,in E0,\nDialogue: 0,0:40:01.00,0:40:02.65,EN,,0,0,0,,we'll end up with a binding for F,\nDialogue: 0,0:40:03.56,0:40:05.61,EN,,0,0,0,,which will say F is a procedure,\nDialogue: 0,0:40:07.15,0:40:11.28,EN,,0,0,0,,and its args are A and B,\nDialogue: 0,0:40:12.57,0:40:16.19,EN,,0,0,0,,and its body is plus a,b.\nDialogue: 0,0:40:18.11,0:40:20.99,EN,,0,0,0,,So that's what the environment would have looked like\nDialogue: 0,0:40:21.21,0:40:22.52,EN,,0,0,0,,had we made that definition.\nDialogue: 0,0:40:24.22,0:40:27.28,EN,,0,0,0,,Then, when we go to evaluate F of X and Y,\nDialogue: 0,0:40:28.80,0:40:30.89,EN,,0,0,0,,we'll go through exactly the same process\nDialogue: 0,0:40:31.02,0:40:31.85,EN,,0,0,0,,that we did before.\nDialogue: 0,0:40:31.88,0:40:33.09,EN,,0,0,0,,It's even the same expression.\nDialogue: 0,0:40:33.28,0:40:34.38,EN,,0,0,0,,The only difference is that\nDialogue: 0,0:40:34.40,0:40:36.64,EN,,0,0,0,,F, instead of having primitive \"plus\" in it\nDialogue: 0,0:40:37.24,0:40:38.99,EN,,0,0,0,,will have this thing.\nDialogue: 0,0:40:41.04,0:40:43.60,EN,,0,0,0,,And so we'll go through exactly the same process,\nDialogue: 0,0:40:43.60,0:40:44.92,EN,,0,0,0,,except this time, when we end up\nDialogue: 0,0:40:45.26,0:40:47.42,EN,,0,0,0,,at apply-dispatch,\nDialogue: 0,0:40:47.86,0:40:50.28,EN,,0,0,0,,the function register, instead of having primitive plus,\nDialogue: 0,0:40:50.44,0:40:53.58,EN,,0,0,0,,will have a thing that will represent it saying procedure,\nDialogue: 0,0:40:54.30,0:40:59.00,EN,,0,0,0,,where the args are A and B,\nDialogue: 0,0:41:00.64,0:41:06.27,EN,,0,0,0,,and the body is plus A, B.\nDialogue: 0,0:41:07.87,0:41:09.92,EN,,0,0,0,,And, again, what I mean, by its ENV,\nDialogue: 0,0:41:09.96,0:41:11.12,EN,,0,0,0,,I mean there's a pointer to it,\nDialogue: 0,0:41:11.24,0:41:13.07,EN,,0,0,0,,so don't worry that I'm writing a lot of stuff there.\nDialogue: 0,0:41:13.28,0:41:15.63,EN,,0,0,0,,There's a pointer to this procedure data structure.\nDialogue: 0,0:41:17.17,0:41:19.77,EN,,0,0,0,,OK, so, we're in exactly the same situation.\nDialogue: 0,0:41:20.27,0:41:22.43,EN,,0,0,0,,We get to apply-dispatch,\nDialogue: 0,0:41:23.98,0:41:26.48,EN,,0,0,0,,so, here, we come to apply-dispatch.\nDialogue: 0,0:41:26.48,0:41:28.73,EN,,0,0,0,,Last time, we branched off to a primitive procedure.\nDialogue: 0,0:41:30.01,0:41:30.70,EN,,0,0,0,,Here, it says oh,\nDialogue: 0,0:41:30.84,0:41:32.80,EN,,0,0,0,,we now have a compound procedure,\nDialogue: 0,0:41:34.55,0:41:36.60,EN,,0,0,0,,so we're going to go off to compound-apply.\nDialogue: 0,0:41:38.47,0:41:39.92,EN,,0,0,0,,Now, what's compound-apply?\nDialogue: 0,0:41:41.92,0:41:44.54,EN,,0,0,0,,Well, remember what the meta-circular evaluator did?\nDialogue: 0,0:41:45.09,0:41:47.40,EN,,0,0,0,,Compound-apply said we're going to evaluate\nDialogue: 0,0:41:49.90,0:41:51.60,EN,,0,0,0,,the body of the procedure\nDialogue: 0,0:41:52.94,0:41:54.12,EN,,0,0,0,,in some new environment.\nDialogue: 0,0:41:54.12,0:41:55.87,EN,,0,0,0,,Where does that new environment come from?\nDialogue: 0,0:41:56.73,0:42:01.36,EN,,0,0,0,,We take the environment that was packaged with the procedure,\nDialogue: 0,0:42:03.02,0:42:05.79,EN,,0,0,0,,we bind the parameters of the procedure\nDialogue: 0,0:42:06.00,0:42:07.63,EN,,0,0,0,,to the arguments that we're passing in,\nDialogue: 0,0:42:09.75,0:42:11.95,EN,,0,0,0,,and use that as a new frame to extend\nDialogue: 0,0:42:12.59,0:42:13.79,EN,,0,0,0,,the procedure environment.\nDialogue: 0,0:42:14.99,0:42:16.08,EN,,0,0,0,,And that's the environment\nDialogue: 0,0:42:16.30,0:42:18.88,EN,,0,0,0,,in which we evaluate the procedure body,\nDialogue: 0,0:42:20.12,0:42:24.47,EN,,0,0,0,,Right? That's going around the apply/eval loop.\nDialogue: 0,0:42:24.47,0:42:26.25,EN,,0,0,0,,That's apply coming back to call eval,\nDialogue: 0,0:42:32.86,0:42:34.92,EN,,0,0,0,,So, now, that's all we have to do in compound-apply.\nDialogue: 0,0:42:36.78,0:42:37.72,EN,,0,0,0,,What are we going to do?\nDialogue: 0,0:42:37.72,0:42:40.97,EN,,0,0,0,,We're going to manufacture a new environment.\nDialogue: 0,0:42:43.55,0:42:45.64,EN,,0,0,0,,And we're going to manufacture a new environment that,\nDialogue: 0,0:42:46.76,0:42:48.11,EN,,0,0,0,,let's see, that we'll call E1.\nDialogue: 0,0:42:52.90,0:42:55.63,EN,,0,0,0,,E1 is going to be some environment where the\nDialogue: 0,0:42:57.31,0:42:59.15,EN,,0,0,0,,where the parameters of the procedure,\nDialogue: 0,0:42:59.21,0:43:03.26,EN,,0,0,0,,Nwhere A is bound to 3, and B is bound to 4,\nDialogue: 0,0:43:04.27,0:43:05.76,EN,,0,0,0,,and it's linked to E0\nDialogue: 0,0:43:05.76,0:43:08.08,EN,,0,0,0,,because that's where f is defined.\nDialogue: 0,0:43:09.27,0:43:10.27,EN,,0,0,0,,And, in this environment,\nDialogue: 0,0:43:10.27,0:43:11.96,EN,,0,0,0,,we're going to evaluate the body of the procedure.\nDialogue: 0,0:43:12.05,0:43:14.48,EN,,0,0,0,,So let's look at that, we're going\nDialogue: 0,0:43:16.52,0:43:18.32,EN,,0,0,0,,Here we are at compound-apply,\nDialogue: 0,0:43:20.30,0:43:23.47,EN,,0,0,0,,which says assign to the expression register\nDialogue: 0,0:43:24.50,0:43:25.98,EN,,0,0,0,,the body of the procedure\nDialogue: 0,0:43:25.98,0:43:27.26,EN,,0,0,0,,that's in the function register.\nDialogue: 0,0:43:28.38,0:43:30.64,EN,,0,0,0,,So I assign to the expression register\nDialogue: 0,0:43:31.29,0:43:32.33,EN,,0,0,0,,the procedure body,\nDialogue: 0,0:43:40.75,0:43:41.10,EN,,0,0,0,,OK?\nDialogue: 0,0:43:42.64,0:43:44.97,EN,,0,0,0,,That's going to be evaluated in an environment\nDialogue: 0,0:43:45.82,0:43:48.32,EN,,0,0,0,,which is formed by making some bindings\nDialogue: 0,0:43:51.30,0:43:53.67,EN,,0,0,0,,using information determined by the procedure--\nDialogue: 0,0:43:53.67,0:43:56.25,EN,,0,0,0,,that's what's in FUN-- and the argument list.\nDialogue: 0,0:43:57.80,0:44:00.00,EN,,0,0,0,,And let's not worry about exactly what that does,\nDialogue: 0,0:44:00.08,0:44:01.63,EN,,0,0,0,,but you can see the information's there.\nDialogue: 0,0:44:01.93,0:44:03.32,EN,,0,0,0,,So make bindings will say oh,\nDialogue: 0,0:44:04.04,0:44:07.90,EN,,0,0,0,,the procedure, itself, had an environment attached to it.\nDialogue: 0,0:44:07.96,0:44:09.32,EN,,0,0,0,,I didn't write that quite here.\nDialogue: 0,0:44:09.36,0:44:10.56,EN,,0,0,0,,I should've said in environment\nDialogue: 0,0:44:11.30,0:44:12.73,EN,,0,0,0,,because every procedure gets built\nDialogue: 0,0:44:12.76,0:44:13.44,EN,,0,0,0,,with an environment.\nDialogue: 0,0:44:13.66,0:44:14.83,EN,,0,0,0,,So, from that environment,\nDialogue: 0,0:44:15.68,0:44:16.35,EN,,0,0,0,,it knows\nDialogue: 0,0:44:16.60,0:44:18.65,EN,,0,0,0,,what the procedure's definition environment is.\nDialogue: 0,0:44:19.29,0:44:20.75,EN,,0,0,0,,It knows what the arguments are.\nDialogue: 0,0:44:21.83,0:44:22.49,EN,,0,0,0,,It looks at argl,\nDialogue: 0,0:44:22.49,0:44:24.28,EN,,0,0,0,,and then you see a reversal convention here.\nDialogue: 0,0:44:24.28,0:44:26.62,EN,,0,0,0,,It just has to know that argl is reversed,\nDialogue: 0,0:44:27.06,0:44:28.81,EN,,0,0,0,,and it builds this frame, E,1.\nDialogue: 0,0:44:29.99,0:44:31.08,EN,,0,0,0,,All right, so, let's assume that\nDialogue: 0,0:44:31.10,0:44:32.92,EN,,0,0,0,,that's what make bindings returns,\nDialogue: 0,0:44:33.36,0:44:36.22,EN,,0,0,0,,so it assigns to ENV this thing, E,1.\nDialogue: 0,0:44:41.34,0:44:42.54,EN,,0,0,0,,The next thing it says\nDialogue: 0,0:44:43.95,0:44:45.84,EN,,0,0,0,,is restore continue.\nDialogue: 0,0:44:46.89,0:44:48.19,EN,,0,0,0,,Remember what continue was here?\nDialogue: 0,0:44:48.76,0:44:50.43,EN,,0,0,0,,It got put up in the last segment.\nDialogue: 0,0:44:52.24,0:44:54.02,EN,,0,0,0,,Continue got stored.\nDialogue: 0,0:44:54.02,0:44:55.18,EN,,0,0,0,,That was the original done,\nDialogue: 0,0:44:55.32,0:44:56.56,EN,,0,0,0,,which said what are you going to do\nDialogue: 0,0:44:56.73,0:44:59.44,EN,,0,0,0,,after you're done with this particular application?\nDialogue: 0,0:45:00.14,0:45:01.72,EN,,0,0,0,,It was one of the very first things that happened\nDialogue: 0,0:45:01.76,0:45:03.18,EN,,0,0,0,,when we evaluated the application.\nDialogue: 0,0:45:03.88,0:45:05.87,EN,,0,0,0,,And now, finally, we're going to restore continue.\nDialogue: 0,0:45:06.86,0:45:09.55,EN,,0,0,0,,Remember apply-dispatch's contract.\nDialogue: 0,0:45:09.58,0:45:11.20,EN,,0,0,0,,It assumes that where it should go to next\nDialogue: 0,0:45:11.23,0:45:11.98,EN,,0,0,0,,was on the stack,\nDialogue: 0,0:45:12.03,0:45:13.12,EN,,0,0,0,,and there it was on the stack.\nDialogue: 0,0:45:13.59,0:45:14.76,EN,,0,0,0,,Continue has done,\nDialogue: 0,0:45:17.82,0:45:19.90,EN,,0,0,0,,and now we're going to go back to eval-dispatch.\nDialogue: 0,0:45:19.94,0:45:20.84,EN,,0,0,0,,We're set up again.\nDialogue: 0,0:45:20.97,0:45:24.41,EN,,0,0,0,,We have an expression, an environment, and a place to go to.\nDialogue: 0,0:45:25.80,0:45:26.89,EN,,0,0,0,,We're not going to go through that\nDialogue: 0,0:45:27.88,0:45:29.55,EN,,0,0,0,,because it's sort of the same expression.\nDialogue: 0,0:45:35.40,0:45:37.79,EN,,0,0,0,,OK, but the thing, again, to notice\nDialogue: 0,0:45:37.82,0:45:38.73,EN,,0,0,0,,is, at this point,\nDialogue: 0,0:45:39.34,0:45:43.72,EN,,0,0,0,,we have reduced the original expression, F,X,Y,\nDialogue: 0,0:45:44.64,0:45:47.92,EN,,0,0,0,,We've reduced evaluating F,X,Y in environment E,0\nDialogue: 0,0:45:48.89,0:45:52.67,EN,,0,0,0,,to evaluate plus A, B in E,1.\nDialogue: 0,0:45:52.78,0:45:55.92,EN,,0,0,0,,And notice, nothing's on the stack, right?\nDialogue: 0,0:45:56.11,0:45:56.83,EN,,0,0,0,,It's a reduction.\nDialogue: 0,0:45:56.84,0:45:59.80,EN,,0,0,0,,At this point, the machine does not contain,\nDialogue: 0,0:45:59.84,0:46:01.20,EN,,0,0,0,,as part of its state,\nDialogue: 0,0:46:01.76,0:46:03.71,EN,,0,0,0,,the fact that it's in the middle of evaluating\nDialogue: 0,0:46:03.72,0:46:04.88,EN,,0,0,0,,some procedure called f,\nDialogue: 0,0:46:05.49,0:46:06.28,EN,,0,0,0,,that's gone,\nDialogue: 0,0:46:07.66,0:46:09.55,EN,,0,0,0,,Right? There's no accumulated state?\nDialogue: 0,0:46:13.07,0:46:14.37,EN,,0,0,0,,Again, that's a very important idea.\nDialogue: 0,0:46:14.37,0:46:16.33,EN,,0,0,0,,That's the meaning of,\nDialogue: 0,0:46:16.76,0:46:18.39,EN,,0,0,0,,when we used to write in the substitution model,\nDialogue: 0,0:46:18.39,0:46:20.86,EN,,0,0,0,,this expression reduces to that expression.\nDialogue: 0,0:46:21.35,0:46:22.66,EN,,0,0,0,,And you don't have to remember anything.\nDialogue: 0,0:46:22.66,0:46:24.50,EN,,0,0,0,,And here, you see the meaning of reduction.\nDialogue: 0,0:46:24.56,0:46:26.16,EN,,0,0,0,,At this point, there is nothing on the stack.\nDialogue: 0,0:46:31.59,0:46:33.63,EN,,0,0,0,,See, that has very important consequences.\nDialogue: 0,0:46:35.24,0:46:37.90,EN,,0,0,0,,Let's go back and look at iterative factorial,\nDialogue: 0,0:46:40.42,0:46:42.76,EN,,0,0,0,,all right? Remember, this was some sort of loop\nDialogue: 0,0:46:44.01,0:46:44.88,EN,,0,0,0,,and doing iter.\nDialogue: 0,0:46:45.13,0:46:47.36,EN,,0,0,0,,And we kept saying that's an iterative procedure,\nDialogue: 0,0:46:49.26,0:46:53.84,EN,,0,0,0,,And what we wrote, remember,\nDialogue: 0,0:46:58.44,0:47:03.13,EN,,0,0,0,,are things like, we said,\nDialogue: 0,0:47:04.35,0:47:11.07,EN,,0,0,0,,fact-iter of 5.\nDialogue: 0,0:47:12.36,0:47:18.67,EN,,0,0,0,,We wrote things like reduces to iter of 1, and 1, and 5,\nDialogue: 0,0:47:19.03,0:47:25.15,EN,,0,0,0,,which reduces to iter of 1, and 2, and 5,\nDialogue: 0,0:47:25.32,0:47:27.07,EN,,0,0,0,,and so on, and so on, and so on.\nDialogue: 0,0:47:27.07,0:47:28.17,EN,,0,0,0,,And we kept saying well, look,\nDialogue: 0,0:47:28.17,0:47:30.35,EN,,0,0,0,,you don't have to build up any storage to do that.\nDialogue: 0,0:47:31.72,0:47:32.73,EN,,0,0,0,,And we waved our hands,\nDialogue: 0,0:47:32.75,0:47:34.59,EN,,0,0,0,,and said in principle, there's no storage needed.\nDialogue: 0,0:47:35.04,0:47:36.17,EN,,0,0,0,,Now, you see no storage needed.\nDialogue: 0,0:47:36.17,0:47:39.09,EN,,0,0,0,,Each of these is a real reduction, right?\nDialogue: 0,0:47:39.09,0:47:42.60,EN,,0,0,0,,As you walk through these expressions,\nDialogue: 0,0:47:47.30,0:47:50.51,EN,,0,0,0,,As you walk through these expressions,\nDialogue: 0,0:47:50.83,0:47:51.37,EN,,0,0,0,,what you'll see\nDialogue: 0,0:47:51.37,0:47:52.81,EN,,0,0,0,,are these expressions on the stack\nDialogue: 0,0:47:53.75,0:47:55.64,EN,,0,0,0,,in some particular environment,\nDialogue: 0,0:47:56.42,0:48:00.02,EN,,0,0,0,,and then these expressions, sorry, in the EXP register\nDialogue: 0,0:48:00.02,0:48:01.50,EN,,0,0,0,,in some particular environment.\nDialogue: 0,0:48:01.57,0:48:02.19,EN,,0,0,0,,And, at each point,\nDialogue: 0,0:48:02.19,0:48:04.00,EN,,0,0,0,,there'll be no accumulated stuff on the stack\nDialogue: 0,0:48:04.36,0:48:05.68,EN,,0,0,0,,because each one's a real reduction.\nDialogue: 0,0:48:09.28,0:48:10.51,EN,,0,0,0,,All right, so, for example,\nDialogue: 0,0:48:10.58,0:48:12.51,EN,,0,0,0,,just to go through it in a little bit more care,\nDialogue: 0,0:48:13.46,0:48:16.88,EN,,0,0,0,,if I start out with an expression that says something like,\nDialogue: 0,0:48:22.44,0:48:34.25,EN,,0,0,0,,oh, say, fact-iter of 5 in some environment\nDialogue: 0,0:48:42.11,0:48:46.30,EN,,0,0,0,,that will, at some point, create an environment\nDialogue: 0,0:48:46.81,0:48:48.38,EN,,0,0,0,,in which n is down to 5.\nDialogue: 0,0:48:51.47,0:48:52.01,EN,,0,0,0,,Let's call that--\nDialogue: 0,0:48:55.68,0:48:56.59,EN,,0,0,0,,And, at some point,\nDialogue: 0,0:48:56.89,0:49:02.56,EN,,0,0,0,,the machine will reduce this whole thing\nDialogue: 0,0:49:02.91,0:49:04.35,EN,,0,0,0,,to a thing that says that's really\nDialogue: 0,0:49:04.76,0:49:09.85,EN,,0,0,0,,iter of 1, and 1, and n,\nDialogue: 0,0:49:10.68,0:49:13.72,EN,,0,0,0,,evaluated in this environment, E,1\nDialogue: 0,0:49:15.87,0:49:17.16,EN,,0,0,0,,with nothing on the stack.\nDialogue: 0,0:49:17.16,0:49:19.55,EN,,0,0,0,,See, at this moment, the machine is not remembering\nDialogue: 0,0:49:20.71,0:49:22.50,EN,,0,0,0,,that evaluating this expression, iter--\nDialogue: 0,0:49:25.00,0:49:25.63,EN,,0,0,0,,which is the loop--\nDialogue: 0,0:49:25.79,0:49:28.57,EN,,0,0,0,,is part of this thing called iterative factorial.\nDialogue: 0,0:49:29.68,0:49:30.59,EN,,0,0,0,,It's not remembering that.\nDialogue: 0,0:49:30.59,0:49:33.17,EN,,0,0,0,,It's just reducing the expression to that, right?\nDialogue: 0,0:49:33.17,0:49:36.56,EN,,0,0,0,,If we look again at the body of iterative factorial,\nDialogue: 0,0:49:38.05,0:49:41.08,EN,,0,0,0,,this expression has reduced to that expression.\nDialogue: 0,0:49:42.81,0:49:43.87,EN,,0,0,0,,Oh, I shouldn't have the n there.\nDialogue: 0,0:49:46.59,0:49:47.74,EN,,0,0,0,,It's a slightly different convention\nDialogue: 0,0:49:47.74,0:49:49.13,EN,,0,0,0,,from the slide to the program.\nDialogue: 0,0:49:53.34,0:49:56.25,EN,,0,0,0,,And, then, what's the body of iter?\nDialogue: 0,0:49:56.28,0:49:57.40,EN,,0,0,0,,Well, iter's going to be an if,\nDialogue: 0,0:49:58.75,0:50:00.19,EN,,0,0,0,,and I won't go through the details of if.\nDialogue: 0,0:50:00.24,0:50:01.63,EN,,0,0,0,,It'll evaluate the predicate.\nDialogue: 0,0:50:02.40,0:50:03.71,EN,,0,0,0,,In this case, it'll be false.\nDialogue: 0,0:50:03.81,0:50:08.64,EN,,0,0,0,,And this iter will now reduce to the expression\nDialogue: 0,0:50:09.85,0:50:20.20,EN,,0,0,0,,iter of whatever it says, star, counter product, and--\nDialogue: 0,0:50:21.62,0:50:22.24,EN,,0,0,0,,what does it say--\nDialogue: 0,0:50:22.68,0:50:24.56,EN,,0,0,0,,plus counter 1\nDialogue: 0,0:50:28.72,0:50:31.42,EN,,0,0,0,,in some other environment, by this time, E,2,\nDialogue: 0,0:50:32.97,0:50:35.98,EN,,0,0,0,,where E,2 will be set up having bindings\nDialogue: 0,0:50:36.49,0:50:39.39,EN,,0,0,0,,for product and counter.\nDialogue: 0,0:50:42.92,0:50:44.33,EN,,0,0,0,,And it'll reduce to that.\nDialogue: 0,0:50:44.94,0:50:46.04,EN,,0,0,0,,Right? It won't be remembering\nDialogue: 0,0:50:46.06,0:50:48.75,EN,,0,0,0,,that it's part of something that it has to return to.\nDialogue: 0,0:50:49.34,0:50:50.43,EN,,0,0,0,,And when iter calls iter again,\nDialogue: 0,0:50:50.44,0:50:52.56,EN,,0,0,0,,it'll reduce to another thing that looks like this\nDialogue: 0,0:50:53.05,0:50:54.68,EN,,0,0,0,,in some environment, E,3,\nDialogue: 0,0:50:54.83,0:50:56.67,EN,,0,0,0,,which has new bindings for product and counter.\nDialogue: 0,0:50:58.80,0:51:05.29,EN,,0,0,0,,OK? So, if you're wondering,\nDialogue: 0,0:51:06.09,0:51:07.53,EN,,0,0,0,,if you've always been queasy about\nDialogue: 0,0:51:08.25,0:51:10.67,EN,,0,0,0,,about how it is we've been saying those procedures\nDialogue: 0,0:51:10.67,0:51:12.45,EN,,0,0,0,,that look syntactically recursive,\nDialogue: 0,0:51:13.20,0:51:15.69,EN,,0,0,0,,are, in fact, iterative,\nDialogue: 0,0:51:15.87,0:51:17.24,EN,,0,0,0,,run in constant space,\nDialogue: 0,0:51:18.40,0:51:19.75,EN,,0,0,0,,well, I don't know if this makes you less queasy,\nDialogue: 0,0:51:19.75,0:51:21.23,EN,,0,0,0,,but at least it shows you what's happening.\nDialogue: 0,0:51:21.23,0:51:22.81,EN,,0,0,0,,There really isn't any buildup there.\nDialogue: 0,0:51:25.91,0:51:27.58,EN,,0,0,0,,Now, you might ask well, is there buildup\nDialogue: 0,0:51:27.98,0:51:30.08,EN,,0,0,0,,in principle in these environment frames?\nDialogue: 0,0:51:31.71,0:51:32.37,EN,,0,0,0,,And the answer is yeah,\nDialogue: 0,0:51:32.40,0:51:33.84,EN,,0,0,0,,you have to make these new environment frames,\nDialogue: 0,0:51:33.84,0:51:35.26,EN,,0,0,0,,but you don't have to hang onto them\nDialogue: 0,0:51:35.42,0:51:36.19,EN,,0,0,0,,when you're done.\nDialogue: 0,0:51:36.44,0:51:37.61,EN,,0,0,0,,They can be garbage collected,\nDialogue: 0,0:51:37.92,0:51:39.47,EN,,0,0,0,,or the space can be reused automatically.\nDialogue: 0,0:51:40.72,0:51:42.99,EN,,0,0,0,,But you see the control structure of the evaluator\nDialogue: 0,0:51:43.25,0:51:46.12,EN,,0,0,0,,is really using this idea that you actually have a reduction,\nDialogue: 0,0:51:47.02,0:51:49.29,EN,,0,0,0,,so these procedures really are iterative procedures.\nDialogue: 0,0:51:50.13,0:51:51.38,EN,,0,0,0,,All right, let's stop for questions.\nDialogue: 0,0:52:02.68,0:52:03.23,EN,,0,0,0,,All right, let's break.\nDialogue: 0,0:52:04.12,0:52:24.56,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:52:24.60,0:52:29.69,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:52:35.20,0:52:38.36,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:52:38.36,0:52:42.14,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:52:48.77,0:52:51.55,EN,,0,0,0,,PROFESSOR: Let me contrast the iterative procedure\nDialogue: 0,0:52:52.77,0:52:54.89,EN,,0,0,0,,just so you'll see where space does build up\nDialogue: 0,0:52:55.12,0:52:56.14,EN,,0,0,0,,with a recursive procedure,\nDialogue: 0,0:52:56.17,0:52:57.29,EN,,0,0,0,,so you can see the difference.\nDialogue: 0,0:52:58.03,0:53:01.20,EN,,0,0,0,,Let's look at the evaluation of recursive factorial.\nDialogue: 0,0:53:02.65,0:53:05.53,EN,,0,0,0,,So, here's fact-recursive,\nDialogue: 0,0:53:05.55,0:53:07.22,EN,,0,0,0,,or standard factorial definition.\nDialogue: 0,0:53:07.22,0:53:10.01,EN,,0,0,0,,We said this one is still a recursive procedure,\nDialogue: 0,0:53:10.01,0:53:12.57,EN,,0,0,0,,but this is actually a recursive process.\nDialogue: 0,0:53:13.75,0:53:16.56,EN,,0,0,0,,And then, just to link it back to the way we started,\nDialogue: 0,0:53:16.83,0:53:20.53,EN,,0,0,0,,we said oh, you can see that it's going to be recursive process\nDialogue: 0,0:53:20.53,0:53:21.82,EN,,0,0,0,,by the substitution model\nDialogue: 0,0:53:22.36,0:53:28.00,EN,,0,0,0,,because, if I say recursive factorial of 5,\nDialogue: 0,0:53:30.45,0:53:34.94,EN,,0,0,0,,that turns into 5 times--\nDialogue: 0,0:53:36.28,0:53:37.82,EN,,0,0,0,,what is it, fact-rec, or record fact--\nDialogue: 0,0:53:42.62,0:53:47.93,EN,,0,0,0,,5 times recursive factorial of 4,\nDialogue: 0,0:53:49.66,0:53:58.22,EN,,0,0,0,,which turns into 5 times 4 times fact-rec of 3,\nDialogue: 0,0:54:00.22,0:54:08.60,EN,,0,0,0,,which returns into 5 times 4 times 3 times\nDialogue: 0,0:54:13.45,0:54:15.31,EN,,0,0,0,,and so on, right?\nDialogue: 0,0:54:15.39,0:54:17.39,EN,,0,0,0,,The idea is there was this chain of stuff building up,\nDialogue: 0,0:54:18.10,0:54:20.06,EN,,0,0,0,,which justified, in the substitution model,\nDialogue: 0,0:54:20.08,0:54:21.28,EN,,0,0,0,,the fact that it's recursive.\nDialogue: 0,0:54:21.52,0:54:24.18,EN,,0,0,0,,And now, let's actually see that chain of stuff build up\nDialogue: 0,0:54:24.18,0:54:25.29,EN,,0,0,0,,and where it is in the machine, OK?\nDialogue: 0,0:54:27.68,0:54:29.95,EN,,0,0,0,,All right, well, let's imagine we're going to start out again.\nDialogue: 0,0:54:30.44,0:54:40.01,EN,,0,0,0,,We'll tell it to evaluate recursive factorial of 5\nDialogue: 0,0:54:41.45,0:54:43.39,EN,,0,0,0,,in some environment, again, E0, where\nDialogue: 0,0:54:45.08,0:54:48.97,EN,,0,0,0,,where recursive factorial is defined, OK?\nDialogue: 0,0:54:49.55,0:54:51.23,EN,,0,0,0,,Well, now we know what's eventually going to happen.\nDialogue: 0,0:54:52.25,0:54:53.64,EN,,0,0,0,,This is going to come along,\nDialogue: 0,0:54:53.92,0:54:55.64,EN,,0,0,0,,it'll evaluate those things,\nDialogue: 0,0:54:55.68,0:54:56.99,EN,,0,0,0,,figure out it's a procedure,\nDialogue: 0,0:54:57.18,0:55:00.16,EN,,0,0,0,,build somewhere over here an environment, E1,\nDialogue: 0,0:55:00.88,0:55:03.69,EN,,0,0,0,,which has n bound to 5,\nDialogue: 0,0:55:04.33,0:55:06.54,EN,,0,0,0,,which hangs off of E0,\nDialogue: 0,0:55:07.80,0:55:08.97,EN,,0,0,0,,which would be, presumably,\nDialogue: 0,0:55:08.99,0:55:12.30,EN,,0,0,0,,the definition environment of recursive factorial.\nDialogue: 0,0:55:14.11,0:55:15.74,EN,,0,0,0,,OK? And, in this environment,\nDialogue: 0,0:55:15.76,0:55:17.48,EN,,0,0,0,,it's going to go off and evaluate the body.\nDialogue: 0,0:55:19.67,0:55:25.92,EN,,0,0,0,,So, again, the evaluation here will reduce to\nDialogue: 0,0:55:27.00,0:55:28.92,EN,,0,0,0,,evaluating the body in E1.\nDialogue: 0,0:55:30.16,0:55:31.34,EN,,0,0,0,,That's going to look at an if,\nDialogue: 0,0:55:32.17,0:55:33.53,EN,,0,0,0,,and I won't go through the details of if.\nDialogue: 0,0:55:33.53,0:55:34.88,EN,,0,0,0,,It'll look at the predicate.\nDialogue: 0,0:55:34.88,0:55:37.53,EN,,0,0,0,,It'll decide it eventually has to evaluate the alternative.\nDialogue: 0,0:55:37.84,0:55:40.41,EN,,0,0,0,,So this whole thing, again, will reduce to\nDialogue: 0,0:55:41.30,0:55:45.53,EN,,0,0,0,,the alternative of recursive factorial,\nDialogue: 0,0:55:45.82,0:55:46.97,EN,,0,0,0,,the alternative clause,\nDialogue: 0,0:55:47.23,0:55:51.16,EN,,0,0,0,,which says that this whole thing reduces to times n\nDialogue: 0,0:55:53.07,0:55:59.96,EN,,0,0,0,,of recursive factorial of n minus 1\nDialogue: 0,0:56:03.48,0:56:05.55,EN,,0,0,0,,in the environment E1\nDialogue: 0,0:56:08.38,0:56:10.91,EN,,0,0,0,,OK? So the original expression, now, is going to reduce\nDialogue: 0,0:56:11.04,0:56:12.52,EN,,0,0,0,,to evaluating that expression, all right?\nDialogue: 0,0:56:13.75,0:56:16.28,EN,,0,0,0,,OK? Now we have an application.\nDialogue: 0,0:56:16.28,0:56:17.63,EN,,0,0,0,,We did an application before.\nDialogue: 0,0:56:18.22,0:56:20.25,EN,,0,0,0,,Remember what happens in an application?\nDialogue: 0,0:56:20.36,0:56:21.69,EN,,0,0,0,,The first thing you do is you go off and you\nDialogue: 0,0:56:21.74,0:56:24.81,EN,,0,0,0,,you save the value of the continue register on the stack.\nDialogue: 0,0:56:25.35,0:56:27.18,EN,,0,0,0,,So the stack here is going to have done in it.\nDialogue: 0,0:56:29.98,0:56:32.88,EN,,0,0,0,,And then you're going to set up to evaluate the sub-parts.\nDialogue: 0,0:56:35.00,0:56:37.20,EN,,0,0,0,,OK? So here we go off to evaluate the sub-parts.\nDialogue: 0,0:56:39.47,0:56:41.45,EN,,0,0,0,,First thing we're going to do is evaluate the operator.\nDialogue: 0,0:56:44.60,0:56:46.32,EN,,0,0,0,,What happens when we evaluate an operator?\nDialogue: 0,0:56:47.25,0:56:48.99,EN,,0,0,0,,Well, we arrange things so that\nDialogue: 0,0:56:49.00,0:56:51.04,EN,,0,0,0,,the operator ends up in the expression register.\nDialogue: 0,0:56:51.48,0:56:53.15,EN,,0,0,0,,The environments in the ENV register\nDialogue: 0,0:56:53.66,0:56:54.60,EN,,0,0,0,,continue someplace\nDialogue: 0,0:56:54.62,0:56:56.22,EN,,0,0,0,,where we're going to go evaluate the arguments.\nDialogue: 0,0:56:56.59,0:56:57.37,EN,,0,0,0,,And, on the stack,\nDialogue: 0,0:56:57.40,0:56:59.29,EN,,0,0,0,,we've saved the original continue,\nDialogue: 0,0:56:59.52,0:57:01.02,EN,,0,0,0,,which is where we wanted to be when we're all done.\nDialogue: 0,0:57:01.72,0:57:02.86,EN,,0,0,0,,And then the things we needed\nDialogue: 0,0:57:03.58,0:57:05.80,EN,,0,0,0,,when we're going to get done evaluating the operator,\nDialogue: 0,0:57:05.90,0:57:07.66,EN,,0,0,0,,the things we'll need to evaluate the arguments,\nDialogue: 0,0:57:07.69,0:57:12.01,EN,,0,0,0,,namely the environment and those arguments,\nDialogue: 0,0:57:12.14,0:57:13.44,EN,,0,0,0,,those unevaluated arguments,\nDialogue: 0,0:57:14.20,0:57:15.62,EN,,0,0,0,,so there they are sitting on the stack.\nDialogue: 0,0:57:15.62,0:57:18.59,EN,,0,0,0,,And we're about to go off to evaluate the operator.\nDialogue: 0,0:57:23.26,0:57:26.73,EN,,0,0,0,,Well, when we return from this particular call--\nDialogue: 0,0:57:26.92,0:57:28.64,EN,,0,0,0,,so we're about to call eval-dispatch here--\nDialogue: 0,0:57:29.38,0:57:30.83,EN,,0,0,0,,when we return from this call,\nDialogue: 0,0:57:31.45,0:57:32.70,EN,,0,0,0,,the value of that operator,\nDialogue: 0,0:57:32.73,0:57:33.52,EN,,0,0,0,,which, in this case,\nDialogue: 0,0:57:33.55,0:57:35.44,EN,,0,0,0,,is going to be the primitive multiplier procedure,\nDialogue: 0,0:57:36.44,0:57:37.93,EN,,0,0,0,,will end up in the FUN register.\nDialogue: 0,0:57:43.02,0:57:44.53,EN,,0,0,0,,We're going to evaluate some arguments.\nDialogue: 0,0:57:44.53,0:57:45.85,EN,,0,0,0,,They will evaluate n here.\nDialogue: 0,0:57:47.73,0:57:49.87,EN,,0,0,0,,That'll give us 5, in this case.\nDialogue: 0,0:57:50.25,0:57:52.04,EN,,0,0,0,,We're going to put that in the argl register,\nDialogue: 0,0:57:53.00,0:57:55.88,EN,,0,0,0,,and then we'll go off to evaluate the second operand.\nDialogue: 0,0:57:57.46,0:58:00.48,EN,,0,0,0,,So, at the point where we go off to evaluate the second operand--\nDialogue: 0,0:58:00.52,0:58:02.19,EN,,0,0,0,,and I'll skip details like computing,\nDialogue: 0,0:58:02.20,0:58:03.58,EN,,0,0,0,,N minus 1, and all of that--\nDialogue: 0,0:58:03.71,0:58:05.88,EN,,0,0,0,,but, when we go off to evaluate the second operand,\nDialogue: 0,0:58:06.62,0:58:10.44,EN,,0,0,0,,that will eventually reduce to another call to fact-recursive.\nDialogue: 0,0:58:12.00,0:58:14.20,EN,,0,0,0,,And, what we've got on the stack here is\nDialogue: 0,0:58:16.52,0:58:19.94,EN,,0,0,0,,the operator from that combination that we're going to use it in\nDialogue: 0,0:58:20.12,0:58:21.07,EN,,0,0,0,,and the other argument.\nDialogue: 0,0:58:23.40,0:58:27.61,EN,,0,0,0,,OK? So, now, we're set up for another call\nDialogue: 0,0:58:28.49,0:58:29.69,EN,,0,0,0,,to recursive factorial.\nDialogue: 0,0:58:30.20,0:58:31.43,EN,,0,0,0,,And, when we're done with this one,\nDialogue: 0,0:58:31.56,0:58:33.64,EN,,0,0,0,,we're going to go to accumulate the last arg.\nDialogue: 0,0:58:34.12,0:58:35.20,EN,,0,0,0,,and remember what that'll do?\nDialogue: 0,0:58:35.20,0:58:35.93,EN,,0,0,0,,That'll say oh,\nDialogue: 0,0:58:36.45,0:58:39.28,EN,,0,0,0,,whatever the result of this has to get combined with that,\nDialogue: 0,0:58:39.28,0:58:40.40,EN,,0,0,0,,and we're going to multiply them.\nDialogue: 0,0:58:41.69,0:58:42.38,EN,,0,0,0,,But, notice now,\nDialogue: 0,0:58:42.73,0:58:44.81,EN,,0,0,0,,we're at another recursive factorial.\nDialogue: 0,0:58:45.72,0:58:48.92,EN,,0,0,0,,We're about to call eval-dispatch again,\nDialogue: 0,0:58:49.32,0:58:50.60,EN,,0,0,0,,except we haven't really reduced it\nDialogue: 0,0:58:50.64,0:58:52.08,EN,,0,0,0,,because there's stuff on the stack now.\nDialogue: 0,0:58:53.70,0:58:55.39,EN,,0,0,0,,The stuff on the stack says oh, when you get back,\nDialogue: 0,0:58:55.40,0:58:57.52,EN,,0,0,0,,you'd better multiply it by the 5 you had hanging there.\nDialogue: 0,0:58:58.43,0:59:05.77,EN,,0,0,0,,So, when we go off to make another call,\nDialogue: 0,0:59:07.12,0:59:08.84,EN,,0,0,0,,we evaluate the n minus 1.\nDialogue: 0,0:59:09.30,0:59:11.05,EN,,0,0,0,,That gives us another environment which\nDialogue: 0,0:59:11.25,0:59:13.84,EN,,0,0,0,,in which the new n's going to be down to 4.\nDialogue: 0,0:59:14.60,0:59:16.22,EN,,0,0,0,,And we're about to call eval-dispatch again.\nDialogue: 0,0:59:19.20,0:59:20.22,EN,,0,0,0,,We get another call.\nDialogue: 0,0:59:21.35,0:59:24.44,EN,,0,0,0,,That 4 is going to end up in the same situation.\nDialogue: 0,0:59:26.04,0:59:28.62,EN,,0,0,0,,We'll end up with another call to fact-recursive n.\nDialogue: 0,0:59:30.02,0:59:32.68,EN,,0,0,0,,And sitting on the stack will be the stuff from the original one\nDialogue: 0,0:59:32.88,0:59:34.51,EN,,0,0,0,,and, now, the subsidiary one we're doing.\nDialogue: 0,0:59:35.36,0:59:36.91,EN,,0,0,0,,And both of them are waiting for the same thing.\nDialogue: 0,0:59:36.91,0:59:39.16,EN,,0,0,0,,They're going to go to accumulate a last argument.\nDialogue: 0,0:59:40.51,0:59:42.94,EN,,0,0,0,,And then, of course, when we go to the fourth call,\nDialogue: 0,0:59:43.25,0:59:44.38,EN,,0,0,0,,the same thing happens.\nDialogue: 0,0:59:45.64,0:59:47.07,EN,,0,0,0,,And this goes on, and on, and on.\nDialogue: 0,0:59:47.30,0:59:48.60,EN,,0,0,0,,And what you see here on the stack,\nDialogue: 0,0:59:50.30,0:59:52.22,EN,,0,0,0,,exactly what's sitting here on the stack,\nDialogue: 0,0:59:52.22,0:59:54.59,EN,,0,0,0,,the thing that says times and 5.\nDialogue: 0,0:59:54.96,0:59:56.40,EN,,0,0,0,,And what you're going to do with that\nDialogue: 0,0:59:56.59,0:59:58.54,EN,,0,0,0,,accumulate that into a last argument.\nDialogue: 0,1:00:00.47,1:00:02.01,EN,,0,0,0,,That's exactly this, right?\nDialogue: 0,1:00:02.01,1:00:04.75,EN,,0,0,0,,This is exactly where that stuff is hanging.\nDialogue: 0,1:00:05.65,1:00:10.65,EN,,0,0,0,,Effectively, the operator you're going to apply,\nDialogue: 0,1:00:11.72,1:00:14.30,EN,,0,0,0,,the other argument that it's got\nDialogue: 0,1:00:14.32,1:00:15.79,EN,,0,0,0,,to be multiplied by when you get back\nDialogue: 0,1:00:15.80,1:00:16.91,EN,,0,0,0,,and sort of the parentheses,\nDialogue: 0,1:00:16.94,1:00:18.96,EN,,0,0,0,,which says yeah, what you wanted to do was accumulate them.\nDialogue: 0,1:00:19.62,1:00:21.88,EN,,0,0,0,,So, you see, the substitution model is not such a lie.\nDialogue: 0,1:00:22.56,1:00:23.63,EN,,0,0,0,,That really is, in some sense,\nDialogue: 0,1:00:23.64,1:00:25.31,EN,,0,0,0,,what's sitting right on the stack.\nDialogue: 0,1:00:29.37,1:00:30.40,EN,,0,0,0,,All right, so that,\nDialogue: 0,1:00:30.81,1:00:32.48,EN,,0,0,0,,in some sense, should explain for you,\nDialogue: 0,1:00:33.26,1:00:34.52,EN,,0,0,0,,or at least convince you,\nDialogue: 0,1:00:35.93,1:00:38.72,EN,,0,0,0,,that somehow, this evaluator is managing\nDialogue: 0,1:00:40.06,1:00:42.86,EN,,0,0,0,,to take these procedures and execute some of them iteratively\nDialogue: 0,1:00:42.95,1:00:44.25,EN,,0,0,0,,and some of them recursively,\nDialogue: 0,1:00:45.26,1:00:47.45,EN,,0,0,0,,even though, as syntactically,\nDialogue: 0,1:00:47.45,1:00:49.05,EN,,0,0,0,,they look like recursive procedures.\nDialogue: 0,1:00:49.40,1:00:50.64,EN,,0,0,0,,How's it managing to do that?\nDialogue: 0,1:00:50.66,1:00:53.72,EN,,0,0,0,,Well, the basic reason it's managing to do that\nDialogue: 0,1:00:53.80,1:00:55.68,EN,,0,0,0,,is the evaluator is set up\nDialogue: 0,1:00:56.04,1:00:59.26,EN,,0,0,0,,to save only what it needs later.\nDialogue: 0,1:01:01.09,1:01:04.25,EN,,0,0,0,,So, for example, at the point where you've reduced\nDialogue: 0,1:01:04.67,1:01:07.39,EN,,0,0,0,,evaluating an expression and an environment\nDialogue: 0,1:01:07.87,1:01:09.87,EN,,0,0,0,,to applying a procedure to some arguments,\nDialogue: 0,1:01:10.52,1:01:12.49,EN,,0,0,0,,it doesn't need that original environment anymore\nDialogue: 0,1:01:13.37,1:01:16.65,EN,,0,0,0,,because any environment stuff will be packaged inside the procedures\nDialogue: 0,1:01:17.88,1:01:19.36,EN,,0,0,0,,where the application's going to happen.\nDialogue: 0,1:01:20.75,1:01:21.61,EN,,0,0,0,,All right, similarly,\nDialogue: 0,1:01:21.63,1:01:23.65,EN,,0,0,0,,when you're going along evaluating an argument list,\nDialogue: 0,1:01:23.65,1:01:25.20,EN,,0,0,0,,when you've finished evaluating the list,\nDialogue: 0,1:01:25.91,1:01:28.03,EN,,0,0,0,,when you're finished evaluating the last argument,\nDialogue: 0,1:01:28.20,1:01:31.61,EN,,0,0,0,,you don't need that argument list any more, right?\nDialogue: 0,1:01:31.63,1:01:32.94,EN,,0,0,0,,And you don't need the environment where\nDialogue: 0,1:01:33.04,1:01:34.64,EN,,0,0,0,,those arguments would be evaluated.\nDialogue: 0,1:01:36.69,1:01:40.89,EN,,0,0,0,,So the basic reason that this interpreter is being so smart\nDialogue: 0,1:01:40.89,1:01:42.88,EN,,0,0,0,,is that it's not being smart at all, it's being stupid.\nDialogue: 0,1:01:43.05,1:01:45.74,EN,,0,0,0,,It's just saying I'm only going to save what I really need.\nDialogue: 0,1:01:48.70,1:01:51.00,EN,,0,0,0,,Well, let me show you here.\nDialogue: 0,1:01:53.07,1:01:57.20,EN,,0,0,0,,Here's the actual thing that's making a tail recursive.\nDialogue: 0,1:01:58.31,1:02:00.20,EN,,0,0,0,,Remember, it's the restore of continue.\nDialogue: 0,1:02:00.22,1:02:06.94,EN,,0,0,0,,It's saying when I go off to evaluate the procedure body,\nDialogue: 0,1:02:08.96,1:02:11.00,EN,,0,0,0,,I should tell eval to come back to\nDialogue: 0,1:02:11.25,1:02:12.54,EN,,0,0,0,,the place where that original\nDialogue: 0,1:02:12.54,1:02:14.25,EN,,0,0,0,,evaluation was supposed to come back to.\nDialogue: 0,1:02:15.17,1:02:15.95,EN,,0,0,0,,So, in some sense,\nDialogue: 0,1:02:16.17,1:02:18.84,EN,,0,0,0,,you want to say what's the actual line that makes tail recursive\nDialogue: 0,1:02:18.89,1:02:19.44,EN,,0,0,0,,It's that one.\nDialogue: 0,1:02:19.92,1:02:21.53,EN,,0,0,0,,If I wanted to build a non-\nDialogue: 0,1:02:21.77,1:02:24.80,EN,,0,0,0,,tail recursive evaluator, for some strange reason,\nDialogue: 0,1:02:25.69,1:02:26.86,EN,,0,0,0,,all I would need to do\nDialogue: 0,1:02:27.12,1:02:29.29,EN,,0,0,0,,is, instead of restoring continue at this point,\nDialogue: 0,1:02:30.06,1:02:31.66,EN,,0,0,0,,I'd set up a label down here\nDialogue: 0,1:02:32.75,1:02:36.25,EN,,0,0,0,,called, \"Where to come back after you've finished applying the procedure.\"\nDialogue: 0,1:02:37.64,1:02:39.71,EN,,0,0,0,,Instead, I'd set continue to that.\nDialogue: 0,1:02:39.92,1:02:41.21,EN,,0,0,0,,I'd go to eval-dispatch,\nDialogue: 0,1:02:41.40,1:02:43.21,EN,,0,0,0,,and then eval-dispatch would come back here.\nDialogue: 0,1:02:43.79,1:02:44.30,EN,,0,0,0,,At that point,\nDialogue: 0,1:02:44.32,1:02:45.28,EN,,0,0,0,,I would restore continue\nDialogue: 0,1:02:45.29,1:02:46.52,EN,,0,0,0,,and go to the original one.\nDialogue: 0,1:02:47.92,1:02:51.00,EN,,0,0,0,,So here, the only consequence of that\nDialogue: 0,1:02:51.15,1:02:52.68,EN,,0,0,0,,would be to make it non-tail recursive.\nDialogue: 0,1:02:52.84,1:02:54.62,EN,,0,0,0,,It would give you exactly the same answers,\nDialogue: 0,1:02:54.72,1:02:57.02,EN,,0,0,0,,except if you did that iterative factorial\nDialogue: 0,1:02:57.05,1:02:58.36,EN,,0,0,0,,and all those iterative procedures,\nDialogue: 0,1:02:58.60,1:02:59.80,EN,,0,0,0,,it would execute recursively.\nDialogue: 0,1:03:03.04,1:03:05.40,EN,,0,0,0,,Well, I lied to you a little bit, but just a little bit,\nDialogue: 0,1:03:05.76,1:03:06.99,EN,,0,0,0,,because I showed you a slightly\nDialogue: 0,1:03:07.02,1:03:08.33,EN,,0,0,0,,over-simplified evaluator\nDialogue: 0,1:03:08.72,1:03:10.38,EN,,0,0,0,,where it assumes that each procedure --\nDialogue: 0,1:03:11.36,1:03:13.66,EN,,0,0,0,,each procedure body has only one expression.\nDialogue: 0,1:03:13.89,1:03:14.54,EN,,0,0,0,,Remember, in general,\nDialogue: 0,1:03:14.56,1:03:16.57,EN,,0,0,0,,a procedure has a sequence of expressions in it.\nDialogue: 0,1:03:17.87,1:03:20.49,EN,,0,0,0,,So there's nothing really conceptually new.\nDialogue: 0,1:03:20.49,1:03:22.28,EN,,0,0,0,,Let me just show you the actual evaluator\nDialogue: 0,1:03:22.89,1:03:24.73,EN,,0,0,0,,that handles sequences of expressions.\nDialogue: 0,1:03:28.47,1:03:29.74,EN,,0,0,0,,This is compound-apply now,\nDialogue: 0,1:03:29.74,1:03:31.31,EN,,0,0,0,,and the only difference from the old one\nDialogue: 0,1:03:32.07,1:03:34.33,EN,,0,0,0,,is that, instead of going off to eval directly,\nDialogue: 0,1:03:35.98,1:03:38.03,EN,,0,0,0,,it takes the whole body of the procedure,\nDialogue: 0,1:03:38.03,1:03:40.15,EN,,0,0,0,,which, in this case, is a sequence of expressions,\nDialogue: 0,1:03:40.28,1:03:41.71,EN,,0,0,0,,and goes off to eval-sequence.\nDialogue: 0,1:03:42.60,1:03:45.32,EN,,0,0,0,,And eval-sequence is a little loop\nDialogue: 0,1:03:46.83,1:03:49.98,EN,,0,0,0,,that, basically, does these evaluations one at a time.\nDialogue: 0,1:03:52.63,1:03:53.85,EN,,0,0,0,,So it does an evaluation.\nDialogue: 0,1:03:53.90,1:03:54.94,EN,,0,0,0,,Says oh, when I come back,\nDialogue: 0,1:03:54.97,1:03:56.86,EN,,0,0,0,,I'd better come back here to do the next one.\nDialogue: 0,1:03:58.44,1:03:59.29,EN,,0,0,0,,And, when I'm all done,\nDialogue: 0,1:03:59.29,1:04:01.02,EN,,0,0,0,,when I want to get the last expression,\nDialogue: 0,1:04:01.31,1:04:03.28,EN,,0,0,0,,I just restore my continue\nDialogue: 0,1:04:03.92,1:04:05.28,EN,,0,0,0,,and go off to eval-dispatch.\nDialogue: 0,1:04:06.41,1:04:08.20,EN,,0,0,0,,And, again, if you wanted for some reason\nDialogue: 0,1:04:08.20,1:04:10.35,EN,,0,0,0,,to break tail recursion in this evaluator,\nDialogue: 0,1:04:10.64,1:04:13.71,EN,,0,0,0,,all you need to do is not handle the last expression, especially.\nDialogue: 0,1:04:14.90,1:04:17.34,EN,,0,0,0,,Just say, after you've done the last expression,\nDialogue: 0,1:04:17.36,1:04:18.65,EN,,0,0,0,,come back to some other place\nDialogue: 0,1:04:19.15,1:04:20.68,EN,,0,0,0,,after which you restore continue.\nDialogue: 0,1:04:21.90,1:04:23.26,EN,,0,0,0,,And, for some reason,\nDialogue: 0,1:04:23.26,1:04:25.74,EN,,0,0,0,,a lot of LISP evaluators tended to work that way.\nDialogue: 0,1:04:26.55,1:04:28.44,EN,,0,0,0,,And the only consequence of that is that\nDialogue: 0,1:04:28.86,1:04:30.72,EN,,0,0,0,,iterative procedures built up stack.\nDialogue: 0,1:04:31.88,1:04:33.61,EN,,0,0,0,,And it's not clear why that happened.\nDialogue: 0,1:04:35.92,1:04:37.98,EN,,0,0,0,,All right. Well, let me just sort of summarize,\nDialogue: 0,1:04:38.09,1:04:39.60,EN,,0,0,0,,since this is a lot of details\nDialogue: 0,1:04:39.98,1:04:41.04,EN,,0,0,0,,in a big program.\nDialogue: 0,1:04:41.12,1:04:42.25,EN,,0,0,0,,But the main point is that\nDialogue: 0,1:04:43.04,1:04:43.87,EN,,0,0,0,,it's no different,\nDialogue: 0,1:04:44.04,1:04:46.08,EN,,0,0,0,,conceptually, from translating any other program.\nDialogue: 0,1:04:47.06,1:04:48.06,EN,,0,0,0,,And the main idea is that\nDialogue: 0,1:04:48.06,1:04:50.28,EN,,0,0,0,,we have this universal evaluator program,\nDialogue: 0,1:04:50.33,1:04:51.71,EN,,0,0,0,,the meta-circular evaluator.\nDialogue: 0,1:04:51.87,1:04:53.07,EN,,0,0,0,,If we translate that into LISP,\nDialogue: 0,1:04:53.10,1:04:53.95,EN,,0,0,0,,then we have all of LISP.\nDialogue: 0,1:04:54.33,1:04:55.15,EN,,0,0,0,,And that's all we did.\nDialogue: 0,1:04:57.98,1:04:59.68,EN,,0,0,0,,The second point is that the magic's gone away.\nDialogue: 0,1:04:59.68,1:05:01.97,EN,,0,0,0,,There should be no more magic in this whole system, right?\nDialogue: 0,1:05:01.97,1:05:07.79,EN,,0,0,0,,In principle, it should all be very clear\nDialogue: 0,1:05:07.82,1:05:10.08,EN,,0,0,0,,except, maybe, for how list structured memory works,\nDialogue: 0,1:05:10.80,1:05:11.80,EN,,0,0,0,,and we'll see that later.\nDialogue: 0,1:05:12.64,1:05:14.20,EN,,0,0,0,,But that's not very hard.\nDialogue: 0,1:05:15.45,1:05:16.35,EN,,0,0,0,,The third point is that\nDialogue: 0,1:05:16.35,1:05:17.52,EN,,0,0,0,,all this tail recursion\nDialogue: 0,1:05:18.24,1:05:21.96,EN,,0,0,0,,came from the discipline of eval being very careful\nDialogue: 0,1:05:22.55,1:05:24.51,EN,,0,0,0,,to save only what it needs next time.\nDialogue: 0,1:05:25.87,1:05:27.72,EN,,0,0,0,,It's not some arbitrary thing\nDialogue: 0,1:05:27.76,1:05:29.86,EN,,0,0,0,,where we're saying well, whenever we call a sub-routine,\nDialogue: 0,1:05:29.86,1:05:32.16,EN,,0,0,0,,we'll save all the registers in the world and come back?\nDialogue: 0,1:05:33.94,1:05:36.49,EN,,0,0,0,,See, sometimes it pays to really worry about efficiency.\nDialogue: 0,1:05:37.15,1:05:39.96,EN,,0,0,0,,And, when you're down in the guts of your evaluator machine,\nDialogue: 0,1:05:40.45,1:05:42.56,EN,,0,0,0,,it really pays to think about things like that\nDialogue: 0,1:05:42.56,1:05:43.96,EN,,0,0,0,,because it makes big consequences.\nDialogue: 0,1:05:45.23,1:05:47.69,EN,,0,0,0,,Well, I hope what this has done\nDialogue: 0,1:05:47.90,1:05:52.30,EN,,0,0,0,,is really made the evaluator seem concrete.\nDialogue: 0,1:05:52.56,1:05:53.90,EN,,0,0,0,,I hope you really believe\nDialogue: 0,1:05:54.32,1:05:56.27,EN,,0,0,0,,that somebody could hold a LISP\nDialogue: 0,1:05:56.84,1:05:58.56,EN,,0,0,0,,LISP evaluator in the palm of their hand.\nDialogue: 0,1:05:59.07,1:06:00.49,EN,,0,0,0,,Maybe to help you believe that, here's a\nDialogue: 0,1:06:00.80,1:06:01.96,EN,,0,0,0,,here's a LISP evaluator\nDialogue: 0,1:06:02.54,1:06:04.06,EN,,0,0,0,,that I'm holding the palm of my hand.\nDialogue: 0,1:06:06.16,1:06:10.56,EN,,0,0,0,,And this is a chip which is actually\nDialogue: 0,1:06:10.89,1:06:13.70,EN,,0,0,0,,quite a bit more complicated than the evaluator I showed you.\nDialogue: 0,1:06:16.86,1:06:19.20,EN,,0,0,0,,Uh.. maybe, here's a better picture of it.\nDialogue: 0,1:06:22.07,1:06:22.57,EN,,0,0,0,,What there is,\nDialogue: 0,1:06:22.60,1:06:24.38,EN,,0,0,0,,is you can see the same overall structure.\nDialogue: 0,1:06:24.73,1:06:25.93,EN,,0,0,0,,This is a register array.\nDialogue: 0,1:06:26.80,1:06:27.71,EN,,0,0,0,,These are the data paths.\nDialogue: 0,1:06:27.72,1:06:29.07,EN,,0,0,0,,Here's a finite state controller.\nDialogue: 0,1:06:29.80,1:06:31.04,EN,,0,0,0,,And again, finite state,\nDialogue: 0,1:06:31.96,1:06:32.80,EN,,0,0,0,,that's all there is.\nDialogue: 0,1:06:32.81,1:06:34.16,EN,,0,0,0,,And somewhere there's external memory\nDialogue: 0,1:06:34.16,1:06:35.23,EN,,0,0,0,,that'll worry about things.\nDialogue: 0,1:06:35.75,1:06:37.63,EN,,0,0,0,,And this particular one is very complicated\nDialogue: 0,1:06:37.64,1:06:39.16,EN,,0,0,0,,because it's trying to run LISP fast.\nDialogue: 0,1:06:39.66,1:06:42.97,EN,,0,0,0,,And it has some very, very fast parallel operations in there\nDialogue: 0,1:06:43.07,1:06:46.32,EN,,0,0,0,,like, if you want to index into an array,\nDialogue: 0,1:06:46.70,1:06:50.40,EN,,0,0,0,,simultaneously check that the index is an integer,\nDialogue: 0,1:06:50.43,1:06:52.86,EN,,0,0,0,,check that it doesn't exceed the array bands,\nDialogue: 0,1:06:53.04,1:06:55.02,EN,,0,0,0,,and go off and do the memory access,\nDialogue: 0,1:06:55.05,1:06:56.70,EN,,0,0,0,,and do all those things simultaneously.\nDialogue: 0,1:06:57.12,1:06:58.40,EN,,0,0,0,,And then, later, if they're all OK,\nDialogue: 0,1:06:58.44,1:06:59.96,EN,,0,0,0,,actually get the value there.\nDialogue: 0,1:07:00.42,1:07:02.46,EN,,0,0,0,,So there are a lot of complicated operations\nDialogue: 0,1:07:02.48,1:07:04.65,EN,,0,0,0,,in these data paths for making LISP run in parallel.\nDialogue: 0,1:07:05.26,1:07:08.41,EN,,0,0,0,,It's a completely non-risk\nDialogue: 0,1:07:08.76,1:07:10.36,EN,,0,0,0,,philosophy of evaluating LISP.\nDialogue: 0,1:07:10.64,1:07:13.20,EN,,0,0,0,,And then, this microcode is pretty complicated.\nDialogue: 0,1:07:13.45,1:07:17.56,EN,,0,0,0,,Let's see, there's what?\nDialogue: 0,1:07:17.60,1:07:21.10,EN,,0,0,0,,There's about 389 instructions of\nDialogue: 0,1:07:21.68,1:07:23.85,EN,,0,0,0,,of 220-bit microcode sitting here\nDialogue: 0,1:07:24.07,1:07:27.94,EN,,0,0,0,,because these are very complicated data paths.\nDialogue: 0,1:07:27.94,1:07:32.25,EN,,0,0,0,,And the whole thing has about 89,000 transistors, OK?\nDialogue: 0,1:07:33.56,1:07:36.86,EN,,0,0,0,,OK. Well, I hope that that takes away a lot of the mystery.\nDialogue: 0,1:07:37.97,1:07:39.24,EN,,0,0,0,,Maybe somebody wants to look at this.\nDialogue: 0,1:07:46.14,1:07:46.89,EN,,0,0,0,,OK. Let's stop.\nDialogue: 0,1:07:56.46,1:07:56.75,EN,,0,0,0,,Questions?\nDialogue: 0,1:07:59.00,1:08:00.42,EN,,0,0,0,,AUDIENCE: OK, now, it sounds like what you're saying is that,\nDialogue: 0,1:08:00.42,1:08:03.48,EN,,0,0,0,,with the restore continue put in the proper place,\nDialogue: 0,1:08:03.58,1:08:09.42,EN,,0,0,0,,that procedures that would invoke a recursive process\nDialogue: 0,1:08:09.42,1:08:11.95,EN,,0,0,0,,now invoke an iterative process\nDialogue: 0,1:08:12.67,1:08:15.36,EN,,0,0,0,,just by the way that the eval-sequence source?\nDialogue: 0,1:08:15.60,1:08:17.54,EN,,0,0,0,,PROFESSOR: I think the way I'd prefer to put it is that,\nDialogue: 0,1:08:17.54,1:08:19.82,EN,,0,0,0,,with restore continue put in the wrong place,\nDialogue: 0,1:08:20.55,1:08:25.48,EN,,0,0,0,,you can cause any syntactically-looking recursive procedure,\nDialogue: 0,1:08:25.52,1:08:27.28,EN,,0,0,0,,in fact, to build up stack as it runs.\nDialogue: 0,1:08:28.64,1:08:30.52,EN,,0,0,0,,But there's no reason for that,\nDialogue: 0,1:08:33.15,1:08:35.12,EN,,0,0,0,,so you might want to play around with it.\nDialogue: 0,1:08:35.15,1:08:38.09,EN,,0,0,0,,You can just switch around two or three instructions\nDialogue: 0,1:08:38.18,1:08:40.78,EN,,0,0,0,,in the way compound-apply comes back,\nDialogue: 0,1:08:41.31,1:08:43.26,EN,,0,0,0,,and you'll get something which isn't tail recursive.\nDialogue: 0,1:08:45.06,1:08:46.14,EN,,0,0,0,,But the thing I wanted to emphasize\nDialogue: 0,1:08:46.16,1:08:47.40,EN,,0,0,0,,is there's no magic. there's no\nDialogue: 0,1:08:47.67,1:08:48.57,EN,,0,0,0,,It's not as if\nDialogue: 0,1:08:49.31,1:08:52.17,EN,,0,0,0,,there's some very clever pre-processing program\nDialogue: 0,1:08:52.65,1:08:55.45,EN,,0,0,0,,that's looking at this procedure, factorial iter,\nDialogue: 0,1:08:55.47,1:08:56.73,EN,,0,0,0,,and say oh, gee, um\nDialogue: 0,1:08:57.42,1:08:58.86,EN,,0,0,0,,I really notice that\nDialogue: 0,1:08:58.88,1:09:01.13,EN,,0,0,0,,I don't have to push stack in order to do this.\nDialogue: 0,1:09:01.13,1:09:02.88,EN,,0,0,0,,Some people think that that's what's going on.\nDialogue: 0,1:09:03.76,1:09:05.38,EN,,0,0,0,,It's something much, much more dumb than that,\nDialogue: 0,1:09:05.38,1:09:07.50,EN,,0,0,0,,it's this one place you're putting the restore instruction.\nDialogue: 0,1:09:08.56,1:09:09.79,EN,,0,0,0,,It's just automatic.\nDialogue: 0,1:09:14.72,1:09:17.55,EN,,0,0,0,,AUDIENCE: But that's not affecting the time complexity is it?\nDialogue: 0,1:09:17.58,1:09:17.87,EN,,0,0,0,,PROFESSOR: No.\nDialogue: 0,1:09:18.60,1:09:21.77,EN,,0,0,0,,AUDIENCE: It's just that it's handling it recursively\nDialogue: 0,1:09:21.80,1:09:23.02,EN,,0,0,0,,instead of iteratively.\nDialogue: 0,1:09:23.02,1:09:27.34,EN,,0,0,0,,But, in terms of the order of time it takes to finish the operation,\nDialogue: 0,1:09:27.37,1:09:29.22,EN,,0,0,0,,it's the same one way or the other, right?\nDialogue: 0,1:09:29.47,1:09:29.76,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,1:09:29.79,1:09:32.68,EN,,0,0,0,,Tail recursion is not going to change the time complexity of anything\nDialogue: 0,1:09:32.72,1:09:33.29,EN,,0,0,0,,because, in some sense,\nDialogue: 0,1:09:33.34,1:09:35.15,EN,,0,0,0,,it's the same algorithm that's going on.\nDialogue: 0,1:09:36.02,1:09:39.37,EN,,0,0,0,,What it's doing is really making this thing run as an iteration.\nDialogue: 0,1:09:41.00,1:09:42.64,EN,,0,0,0,,Right? Not going to run out of memory\nDialogue: 0,1:09:42.68,1:09:44.22,EN,,0,0,0,,you know counting up to a giant number\nDialogue: 0,1:09:44.75,1:09:46.40,EN,,0,0,0,,simply because the stack would get pushed.\nDialogue: 0,1:09:48.35,1:09:50.24,EN,,0,0,0,,See, the thing you really have to believe is that,\nDialogue: 0,1:09:50.56,1:09:51.13,EN,,0,0,0,,when we write--\nDialogue: 0,1:09:51.64,1:09:53.78,EN,,0,0,0,,see, we've been writing all these things called iterations,\nDialogue: 0,1:09:53.93,1:09:57.99,EN,,0,0,0,,infinite loops, define loop to be called loop.\nDialogue: 0,1:10:00.32,1:10:03.36,EN,,0,0,0,,That's is as much an iteration\nDialogue: 0,1:10:03.65,1:10:05.66,EN,,0,0,0,,you know as if we wrote do forever loop.\nDialogue: 0,1:10:07.63,1:10:09.28,EN,,0,0,0,,It's just syntactic sugar as the difference.\nDialogue: 0,1:10:09.28,1:10:11.32,EN,,0,0,0,,These things are real, honest to god, iterations?\nDialogue: 0,1:10:14.73,1:10:16.08,EN,,0,0,0,,They don't change the time complexity,\nDialogue: 0,1:10:16.11,1:10:18.53,EN,,0,0,0,,but they turn them into real iterations.\nDialogue: 0,1:10:21.68,1:10:23.80,EN,,0,0,0,,All right, thank you.\nDialogue: 0,0:00:00.03,0:00:00.97,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP 学习小组\\N倾情制作\nDialogue: 0,0:00:01.05,0:00:09.09,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N刘殊君\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.21,0:00:13.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}显示控制求值器\nDialogue: 0,0:00:16.30,0:00:18.08,Default,,0,0,0,,教授：我想大家已经意识到\nDialogue: 0,0:00:20.01,0:00:22.73,Default,,0,0,0,,我们介绍了一些真正的魔法\nDialogue: 0,0:00:24.20,0:00:27.24,Default,,0,0,0,,创造新语言的魔法\nDialogue: 0,0:00:27.42,0:00:28.72,Default,,0,0,0,,用来创造全新的语言\nDialogue: 0,0:00:29.69,0:00:30.40,Default,,0,0,0,,我们学了些什么？\nDialogue: 0,0:00:30.43,0:00:32.78,Default,,0,0,0,,我们学习了一门用来操作图片的Escher的语言\nDialogue: 0,0:00:38.92,0:00:41.15,Default,,0,0,0,,这门语言由Peter Henderson发明\nDialogue: 0,0:00:42.01,0:00:46.49,Default,,0,0,0,,我们还学习了数字逻辑语言\nDialogue: 0,0:00:53.16,0:00:55.55,Default,,0,0,0,,以及 我们还学习了查询语言\nDialogue: 0,0:00:59.70,0:01:00.78,Default,,0,0,0,,然而你需要明白的是\nDialogue: 0,0:01:00.81,0:01:03.10,Default,,0,0,0,,尽管它们都是“玩具级”的语言示例\nDialogue: 0,0:01:04.70,0:01:07.61,Default,,0,0,0,,但也确实是实用工具的核心\nDialogue: 0,0:01:08.25,0:01:09.48,Default,,0,0,0,,比如说\nDialogue: 0,0:01:10.12,0:01:11.18,Default,,0,0,0,,Escher图片语言\nDialogue: 0,0:01:11.20,0:01:14.33,Default,,0,0,0,,就被MIT的学生Henry Wu拿去\nDialogue: 0,0:01:14.88,0:01:16.43,Default,,0,0,0,,开发成了一门用于\nDialogue: 0,0:01:16.97,0:01:19.45,Default,,0,0,0,,为电路板布局的语言\nDialogue: 0,0:01:20.35,0:01:22.56,Default,,0,0,0,,它就是在这些结构上扩展而来\nDialogue: 0,0:01:23.24,0:01:24.65,Default,,0,0,0,,至于数字逻辑语言\nDialogue: 0,0:01:24.68,0:01:26.08,Default,,0,0,0,,Gerry教授在上课的时候也提到过\nDialogue: 0,0:01:26.43,0:01:29.92,Default,,0,0,0,,它被扩展为了一个仿真器的基础\nDialogue: 0,0:01:30.85,0:01:32.96,Default,,0,0,0,,用来设计真实的计算机\nDialogue: 0,0:01:33.46,0:01:34.32,Default,,0,0,0,,至于查询语言\nDialogue: 0,0:01:34.35,0:01:36.44,Default,,0,0,0,,当然就是Prolog语言的一种核心\nDialogue: 0,0:01:37.51,0:01:39.07,Default,,0,0,0,,我们构造的这些语言\nDialogue: 0,0:01:39.55,0:01:40.65,Default,,0,0,0,,全都是用Lisp编写\nDialogue: 0,0:01:43.63,0:01:44.59,Default,,0,0,0,,很多人问\nDialogue: 0,0:01:45.27,0:01:48.73,Default,,0,0,0,,Lisp适合用来解决哪一类问题？\nDialogue: 0,0:01:48.75,0:01:49.93,Default,,0,0,0,,答案就是\nDialogue: 0,0:01:50.33,0:01:52.65,Default,,0,0,0,,Lisp不适合解决任何一类问题\nDialogue: 0,0:01:53.53,0:01:54.60,Default,,0,0,0,,Lisp擅长的是\nDialogue: 0,0:01:54.73,0:01:57.15,Default,,0,0,0,,用它来构造一门合适的语言\nDialogue: 0,0:01:57.18,0:01:58.57,Default,,0,0,0,,来解决你的问题\nDialogue: 0,0:01:59.17,0:02:00.44,Default,,0,0,0,,你应该像这样看待Lisp\nDialogue: 0,0:02:01.47,0:02:03.39,Default,,0,0,0,,那么既然这些语言都基于Lisp\nDialogue: 0,0:02:04.57,0:02:05.72,Default,,0,0,0,,那Lisp又基于什么？\nDialogue: 0,0:02:06.97,0:02:07.88,Default,,0,0,0,,它又从何而来？\nDialogue: 0,0:02:07.90,0:02:09.40,Default,,0,0,0,,这个我们也学过\nDialogue: 0,0:02:09.58,0:02:16.09,Default,,0,0,0,,我们学过元循环求值器\nDialogue: 0,0:02:21.53,0:02:23.40,Default,,0,0,0,,学习了元循环求值器后 我们说\nDialogue: 0,0:02:23.42,0:02:25.76,Default,,0,0,0,,Lisp就是基于Lisp的\nDialogue: 0,0:02:25.80,0:02:27.48,Default,,0,0,0,,而当我们研究它的时候\nDialogue: 0,0:02:28.27,0:02:29.95,Default,,0,0,0,,我们必须得施展一些真正的魔法 对吧？\nDialogue: 0,0:02:29.95,0:02:31.74,Default,,0,0,0,,这又是什么意思呢？\nDialogue: 0,0:02:31.74,0:02:34.96,Default,,0,0,0,,Y算子、不动点\nDialogue: 0,0:02:35.76,0:02:38.33,Default,,0,0,0,,以及这样的一个观念--\nDialogue: 0,0:02:38.36,0:02:41.44,Default,,0,0,0,,Lisp实际上是一个方程的不动点\nDialogue: 0,0:02:42.20,0:02:45.42,Default,,0,0,0,,一个通过自身来定义的有趣方程\nDialogue: 0,0:02:47.40,0:02:48.56,Default,,0,0,0,,这确实是神奇的魔法\nDialogue: 0,0:02:49.07,0:02:52.35,Default,,0,0,0,,那么今天 作为魔法的最后一步\nDialogue: 0,0:02:52.62,0:02:54.03,Default,,0,0,0,,我们要把它们通通消除掉\nDialogue: 0,0:03:06.80,0:03:07.98,Default,,0,0,0,,我们已经知道怎么做了\nDialogue: 0,0:03:09.77,0:03:10.76,Default,,0,0,0,,核心要思想是\nDialogue: 0,0:03:11.13,0:03:12.73,Default,,0,0,0,,将Lisp语言\nDialogue: 0,0:03:13.36,0:03:15.50,Default,,0,0,0,,实现在使用寄存器架构的机器上\nDialogue: 0,0:03:15.50,0:03:17.93,Default,,0,0,0,,回想一下 寄存器机器的关键之处在于\nDialogue: 0,0:03:19.60,0:03:24.68,Default,,0,0,0,,机器的一部分是确定且有穷的\nDialogue: 0,0:03:24.72,0:03:26.12,Default,,0,0,0,,它有一个有穷状态控制器\nDialogue: 0,0:03:26.12,0:03:27.87,Default,,0,0,0,,它用特定的硬件\nDialogue: 0,0:03:27.88,0:03:29.31,Default,,0,0,0,,去完成特定的事情\nDialogue: 0,0:03:30.51,0:03:31.74,Default,,0,0,0,,其中还有一些运算所需的\nDialogue: 0,0:03:31.76,0:03:33.24,Default,,0,0,0,,特殊数据通路\nDialogue: 0,0:03:33.55,0:03:35.29,Default,,0,0,0,,然后 为了实现递归\nDialogue: 0,0:03:35.53,0:03:37.60,Default,,0,0,0,,并且维持无穷的假象\nDialogue: 0,0:03:37.82,0:03:39.77,Default,,0,0,0,,还使用了一种称作“栈”的大内存\nDialogue: 0,0:03:42.06,0:03:43.72,Default,,0,0,0,,所以如果我们在\nDialogue: 0,0:03:43.92,0:03:45.50,Default,,0,0,0,,寄存器机器上实现了Lisp\nDialogue: 0,0:03:47.02,0:03:48.35,Default,,0,0,0,,那么这个时候\nDialogue: 0,0:03:48.40,0:03:49.85,Default,,0,0,0,,所有的东西都会完全具体化\nDialogue: 0,0:03:49.85,0:03:51.23,Default,,0,0,0,,所有的魔法都会消除\nDialogue: 0,0:03:51.65,0:03:53.52,Default,,0,0,0,,这堂课结束时\nDialogue: 0,0:03:53.53,0:03:54.78,Default,,0,0,0,,我想让你感觉到\nDialogue: 0,0:03:55.14,0:03:59.05,Default,,0,0,0,,相对于神秘的元循环求值器\nDialogue: 0,0:03:59.67,0:04:02.60,Default,,0,0,0,,Lisp求值器是非常具体的东西\nDialogue: 0,0:04:02.85,0:04:04.57,Default,,0,0,0,,你甚至可以把它放在手心中\nDialogue: 0,0:04:04.76,0:04:06.24,Default,,0,0,0,,你可以想象一下\nDialogue: 0,0:04:06.57,0:04:07.90,Default,,0,0,0,,手里拿着一个Lisp解释器的情景\nDialogue: 0,0:04:09.63,0:04:10.94,Default,,0,0,0,,好 那我们怎么做呢？\nDialogue: 0,0:04:10.95,0:04:12.76,Default,,0,0,0,,所有的原料都已经齐全\nDialogue: 0,0:04:13.96,0:04:17.45,Default,,0,0,0,,上节课Gerry教了你们\nDialogue: 0,0:04:17.60,0:04:21.47,Default,,0,0,0,,对一个任意的Lisp过程\nDialogue: 0,0:04:22.60,0:04:24.28,Default,,0,0,0,,如何手动地把它们\nDialogue: 0,0:04:24.75,0:04:26.67,Default,,0,0,0,,翻译成在寄存器机器上运行的代码\nDialogue: 0,0:04:28.20,0:04:30.52,Default,,0,0,0,,那么 要在寄存器机器上实现Lisp本身\nDialogue: 0,0:04:30.57,0:04:31.44,Default,,0,0,0,,我们只需要\nDialogue: 0,0:04:31.69,0:04:33.45,Default,,0,0,0,,把最关键的过程\nDialogue: 0,0:04:33.68,0:04:35.42,Default,,0,0,0,,也就是元循环求值器\nDialogue: 0,0:04:36.17,0:04:38.11,Default,,0,0,0,,手工翻译成寄存器机器的代码\nDialogue: 0,0:04:39.04,0:04:40.25,Default,,0,0,0,,这就实现了整个Lisp\nDialogue: 0,0:04:42.14,0:04:43.00,Default,,0,0,0,,因此 我们已经知道了\nDialogue: 0,0:04:43.02,0:04:44.43,Default,,0,0,0,,实现的原理\nDialogue: 0,0:04:45.38,0:04:46.54,Default,,0,0,0,,而且实际上\nDialogue: 0,0:04:46.68,0:04:48.86,Default,,0,0,0,,这跟翻译\nDialogue: 0,0:04:50.00,0:04:53.40,Default,,0,0,0,,递归版的阶乘或斐波那契数列\nDialogue: 0,0:04:53.42,0:04:54.67,Default,,0,0,0,,没什么区别\nDialogue: 0,0:04:54.67,0:04:56.00,Default,,0,0,0,,只是它规模更大 代码更多\nDialogue: 0,0:04:56.84,0:04:58.03,Default,,0,0,0,,只是包含了更多细节\nDialogue: 0,0:04:58.04,0:04:59.66,Default,,0,0,0,,但是没有任何新的概念\nDialogue: 0,0:05:01.48,0:05:03.02,Default,,0,0,0,,当我们完成这个以后\nDialogue: 0,0:05:03.08,0:05:04.76,Default,,0,0,0,,所有的东西都变得明确了\nDialogue: 0,0:05:04.87,0:05:06.91,Default,,0,0,0,,当我们看到如何用一系列的\nDialogue: 0,0:05:06.94,0:05:10.08,Default,,0,0,0,,寄存器操作来实现Lisp之后\nDialogue: 0,0:05:10.16,0:05:11.63,Default,,0,0,0,,它就成为了我们整个课程中\nDialogue: 0,0:05:11.95,0:05:14.16,Default,,0,0,0,,最明确的Lisp模型\nDialogue: 0,0:05:14.81,0:05:16.95,Default,,0,0,0,,回忆一下 这个过程贯穿了整个课程\nDialogue: 0,0:05:16.95,0:05:18.25,Default,,0,0,0,,我们先从代换模型开始\nDialogue: 0,0:05:18.28,0:05:19.58,Default,,0,0,0,,它和代数有点相似\nDialogue: 0,0:05:20.24,0:05:21.87,Default,,0,0,0,,然后学习了环境模型\nDialogue: 0,0:05:21.88,0:05:24.00,Default,,0,0,0,,它引入了“框架”的概念\nDialogue: 0,0:05:24.03,0:05:25.31,Default,,0,0,0,,以及框架之间的关联\nDialogue: 0,0:05:26.32,0:05:27.88,Default,,0,0,0,,然后我们在元循环求值器中\nDialogue: 0,0:05:27.90,0:05:29.36,Default,,0,0,0,,把它变得更具体了\nDialogue: 0,0:05:31.05,0:05:31.64,Default,,0,0,0,,但是有的事情\nDialogue: 0,0:05:31.87,0:05:33.98,Default,,0,0,0,,元循环求值器没有告诉我们\nDialogue: 0,0:05:34.36,0:05:35.34,Default,,0,0,0,,你应该认识到这点\nDialogue: 0,0:05:36.09,0:05:38.64,Default,,0,0,0,,比如说 我们还不知道\nDialogue: 0,0:05:38.73,0:05:42.67,Default,,0,0,0,,像这里的递归阶乘过程\nDialogue: 0,0:05:45.17,0:05:47.13,Default,,0,0,0,,为何不断地申请新的空间\nDialogue: 0,0:05:47.21,0:05:47.98,Default,,0,0,0,,另一方面\nDialogue: 0,0:05:48.16,0:05:51.94,Default,,0,0,0,,一个语法上看起来像是递归的过程\nDialogue: 0,0:05:52.11,0:05:55.07,Default,,0,0,0,,比如FACT-ITER 并不占用栈空间\nDialogue: 0,0:05:55.10,0:05:59.16,Default,,0,0,0,,我们通过代换模型来证明\nDialogue: 0,0:06:00.50,0:06:01.96,Default,,0,0,0,,它不占用空间\nDialogue: 0,0:06:01.96,0:06:02.94,Default,,0,0,0,,但我们并没有说清楚\nDialogue: 0,0:06:03.42,0:06:06.76,Default,,0,0,0,,机器是如何做到这一点的\nDialogue: 0,0:06:07.31,0:06:08.91,Default,,0,0,0,,这涉及到一些细节\nDialogue: 0,0:06:09.02,0:06:11.12,Default,,0,0,0,,比如参数是如何传递给过程的\nDialogue: 0,0:06:12.48,0:06:13.69,Default,,0,0,0,,这是我们在元循环求值器中\nDialogue: 0,0:06:13.71,0:06:15.34,Default,,0,0,0,,没有看到的\nDialogue: 0,0:06:15.36,0:06:17.40,Default,,0,0,0,,完全是因为在所实现的Lisp中\nDialogue: 0,0:06:17.42,0:06:19.20,Default,,0,0,0,,把参数传递给过程的方式\nDialogue: 0,0:06:19.70,0:06:20.59,Default,,0,0,0,,取决于\nDialogue: 0,0:06:21.02,0:06:23.50,Default,,0,0,0,,外部Lisp的传参方式\nDialogue: 0,0:06:25.87,0:06:29.02,Default,,0,0,0,,但现在 这一点将变得非常明确\nDialogue: 0,0:06:30.74,0:06:31.12,Default,,0,0,0,,好\nDialogue: 0,0:06:31.23,0:06:34.30,Default,,0,0,0,,在开始研究求值器之前\nDialogue: 0,0:06:34.36,0:06:35.53,Default,,0,0,0,,我先让你们感受一下\nDialogue: 0,0:06:35.55,0:06:37.00,Default,,0,0,0,,一个完整Lisp系统是怎么样的\nDialogue: 0,0:06:37.60,0:06:39.36,Default,,0,0,0,,这样你就可以知道 我们要讨论哪部分\nDialogue: 0,0:06:39.40,0:06:40.81,Default,,0,0,0,,不讨论哪些部分\nDialogue: 0,0:06:43.18,0:06:47.42,Default,,0,0,0,,首先 这里有一个快乐的Lisp用户\nDialogue: 0,0:06:48.67,0:06:52.65,Default,,0,0,0,,他正在和一个叫做读取器的东西交流\nDialogue: 0,0:07:00.36,0:07:01.53,Default,,0,0,0,,读取器的工作是\nDialogue: 0,0:07:01.95,0:07:13.23,Default,,0,0,0,,读取用户输入的字符串\nDialogue: 0,0:07:14.17,0:07:16.62,Default,,0,0,0,,把它们转化成一种称作\nDialogue: 0,0:07:17.20,0:07:19.37,Default,,0,0,0,,表结构内存的数据结构\nDialogue: 0,0:07:30.00,0:07:31.72,Default,,0,0,0,,读取器会读取--\nDialogue: 0,0:07:32.65,0:07:33.95,Default,,0,0,0,,你敲出来的符号、括号\nDialogue: 0,0:07:34.48,0:07:37.12,Default,,0,0,0,,A和B、1和3这些东西\nDialogue: 0,0:07:37.18,0:07:39.04,Default,,0,0,0,,并把它们变成表结构\nDialogue: 0,0:07:39.15,0:07:40.54,Default,,0,0,0,,变成序对、指针等等\nDialogue: 0,0:07:42.35,0:07:43.92,Default,,0,0,0,,所以当求值器运行的时候\nDialogue: 0,0:07:43.93,0:07:45.10,Default,,0,0,0,,环境里已经不存在原始字符了\nDialogue: 0,0:07:45.85,0:07:48.16,Default,,0,0,0,,当然 在更现代的Lisp系统中\nDialogue: 0,0:07:49.00,0:07:50.44,Default,,0,0,0,,可能还有一大团东西\nDialogue: 0,0:07:50.44,0:07:52.17,Default,,0,0,0,,存在于在读取器和用户之间\nDialogue: 0,0:07:52.41,0:07:54.52,Default,,0,0,0,,最顶层首先是视窗系统\nDialogue: 0,0:07:54.77,0:07:56.03,Default,,0,0,0,,以及鼠标之类的东西\nDialogue: 0,0:07:56.28,0:07:58.20,Default,,0,0,0,,但从概念上来说 都是在输入字符\nDialogue: 0,0:07:59.93,0:08:04.32,Default,,0,0,0,,总之 读取器把它们都变成指针\nDialogue: 0,0:08:05.56,0:08:07.28,Default,,0,0,0,,指向内存中的对象\nDialogue: 0,0:08:08.27,0:08:10.94,Default,,0,0,0,,这是求值器的所能看到的东西\nDialogue: 0,0:08:15.55,0:08:16.04,Default,,0,0,0,,明白吗？\nDialogue: 0,0:08:17.02,0:08:18.88,Default,,0,0,0,,求值器有一些辅助函数\nDialogue: 0,0:08:19.78,0:08:23.16,Default,,0,0,0,,包括你需要的所有基本运算\nDialogue: 0,0:08:23.16,0:08:24.91,Default,,0,0,0,,也就是说这里另有一盒子东西\nDialogue: 0,0:08:28.40,0:08:30.25,Default,,0,0,0,,比如浮点单元\nDialogue: 0,0:08:32.22,0:08:34.40,Default,,0,0,0,,或者其它类似的东西来执行这些运算\nDialogue: 0,0:08:35.39,0:08:37.68,Default,,0,0,0,,如果你需要支持更多的基本运算\nDialogue: 0,0:08:37.71,0:08:39.02,Default,,0,0,0,,你就实现更多的运算符执行器\nDialogue: 0,0:08:39.05,0:08:40.48,Default,,0,0,0,,但它们和求值器都是分离的\nDialogue: 0,0:08:42.08,0:08:43.77,Default,,0,0,0,,求值器最终算出结果\nDialogue: 0,0:08:45.16,0:08:46.76,Default,,0,0,0,,并且把它们告诉打印程序\nDialogue: 0,0:08:50.62,0:08:52.01,Default,,0,0,0,,现在 打印程序的任务就是\nDialogue: 0,0:08:52.01,0:08:54.54,Default,,0,0,0,,从求值器取得这个表结构\nDialogue: 0,0:08:55.39,0:08:56.99,Default,,0,0,0,,再把它们变回字符\nDialogue: 0,0:09:01.85,0:09:04.07,Default,,0,0,0,,然后通过某种界面\nDialogue: 0,0:09:04.28,0:09:05.66,Default,,0,0,0,,展示给用户\nDialogue: 0,0:09:08.05,0:09:11.23,Default,,0,0,0,,那么 今天我们要讨论的是这个求值器\nDialogue: 0,0:09:12.67,0:09:15.20,Default,,0,0,0,,基本运算和Lisp没有什么特别的关系\nDialogue: 0,0:09:15.20,0:09:18.14,Default,,0,0,0,,它们只取决于你怎么实现基本运算\nDialogue: 0,0:09:19.36,0:09:22.18,Default,,0,0,0,,读取器和打印程序实际上很复杂\nDialogue: 0,0:09:22.18,0:09:23.55,Default,,0,0,0,,但是我们不去讨论它们\nDialogue: 0,0:09:24.68,0:09:27.10,Default,,0,0,0,,从字符构建表的过程中\nDialogue: 0,0:09:27.10,0:09:28.92,Default,,0,0,0,,它们需要处理很多细节\nDialogue: 0,0:09:29.90,0:09:31.18,Default,,0,0,0,,说来话长\nDialogue: 0,0:09:31.18,0:09:32.32,Default,,0,0,0,,我们就不讨论它了\nDialogue: 0,0:09:32.49,0:09:33.69,Default,,0,0,0,,关于表结构内存\nDialogue: 0,0:09:34.36,0:09:35.63,Default,,0,0,0,,我们下次再来讨论\nDialogue: 0,0:09:36.93,0:09:39.72,Default,,0,0,0,,那么去除了读取和打印的细节\nDialogue: 0,0:09:40.12,0:09:41.71,Default,,0,0,0,,关于这个求值器\nDialogue: 0,0:09:41.72,0:09:43.05,Default,,0,0,0,,所剩下的唯一谜团\nDialogue: 0,0:09:43.25,0:09:45.85,Default,,0,0,0,,几乎就只有怎么在传统内存上构建表结构了\nDialogue: 0,0:09:46.65,0:09:48.20,Default,,0,0,0,,不过我们把那也放到下次来讨论\nDialogue: 0,0:09:50.58,0:09:51.04,Default,,0,0,0,,好\nDialogue: 0,0:09:53.34,0:09:56.11,Default,,0,0,0,,那么 我们先来看看这个求值器\nDialogue: 0,0:09:56.20,0:09:58.32,Default,,0,0,0,,我将要展示的这个求值器\nDialogue: 0,0:09:58.49,0:10:01.12,Default,,0,0,0,,我想 它并没有什么特别的\nDialogue: 0,0:10:01.15,0:10:04.56,Default,,0,0,0,,它只是一台专门运行Lisp的寄存器机器\nDialogue: 0,0:10:04.81,0:10:06.09,Default,,0,0,0,,它有七个寄存器\nDialogue: 0,0:10:07.88,0:10:09.26,Default,,0,0,0,,这是它的七个寄存器\nDialogue: 0,0:10:09.89,0:10:12.38,Default,,0,0,0,,这个寄存器叫EXP\nDialogue: 0,0:10:14.12,0:10:15.53,Default,,0,0,0,,它的任务是存放\nDialogue: 0,0:10:16.36,0:10:18.03,Default,,0,0,0,,将要被求值的表达式\nDialogue: 0,0:10:18.37,0:10:19.80,Default,,0,0,0,,具体来说\nDialogue: 0,0:10:20.38,0:10:21.64,Default,,0,0,0,,它存放的是一个指针\nDialogue: 0,0:10:22.03,0:10:23.55,Default,,0,0,0,,指针指向存放着求值的表达式\nDialogue: 0,0:10:23.56,0:10:25.32,Default,,0,0,0,,的一处表结构内存\nDialogue: 0,0:10:26.55,0:10:27.82,Default,,0,0,0,,还有一个叫做ENV的寄存器\nDialogue: 0,0:10:28.88,0:10:30.28,Default,,0,0,0,,它存放着环境\nDialogue: 0,0:10:31.00,0:10:33.05,Default,,0,0,0,,也就是表达式的求值环境\nDialogue: 0,0:10:34.07,0:10:35.02,Default,,0,0,0,,同样的 这也是一个指针\nDialogue: 0,0:10:35.02,0:10:36.75,Default,,0,0,0,,环境是一种数据结构\nDialogue: 0,0:10:38.24,0:10:40.14,Default,,0,0,0,,这个叫做FUN的寄存器--\nDialogue: 0,0:10:40.75,0:10:42.54,Default,,0,0,0,,当你在应用一个过程时\nDialogue: 0,0:10:42.57,0:10:43.96,Default,,0,0,0,,它会存放这个过程\nDialogue: 0,0:10:44.56,0:10:46.24,Default,,0,0,0,,还有寄存器ARGL\nDialogue: 0,0:10:47.36,0:10:49.34,Default,,0,0,0,,它存放的是已求值的参数\nDialogue: 0,0:10:50.54,0:10:51.60,Default,,0,0,0,,从这里开始你能看到\nDialogue: 0,0:10:51.63,0:10:53.14,Default,,0,0,0,,求值器的基本构造\nDialogue: 0,0:10:53.14,0:10:54.49,Default,,0,0,0,,回忆一下它是怎么工作的\nDialogue: 0,0:10:54.49,0:10:56.62,Default,,0,0,0,,对这一块输入表达式和环境\nDialogue: 0,0:10:57.67,0:10:59.71,Default,,0,0,0,,而这一块接收函数\nDialogue: 0,0:10:59.74,0:11:02.14,Default,,0,0,0,,或者说 过程以及参数\nDialogue: 0,0:11:03.48,0:11:06.30,Default,,0,0,0,,EVAL-APPLY循环使用这些寄存器工作\nDialogue: 0,0:11:07.40,0:11:09.69,Default,,0,0,0,,所以这些是EVAL-APPLY的基本组成部分\nDialogue: 0,0:11:10.20,0:11:10.99,Default,,0,0,0,,还有一些别的东西\nDialogue: 0,0:11:11.00,0:11:11.61,Default,,0,0,0,,比如CONTINUE寄存器\nDialogue: 0,0:11:11.61,0:11:15.34,Default,,0,0,0,,你之前已经见过CONTINUE寄存器\nDialogue: 0,0:11:15.34,0:11:18.04,Default,,0,0,0,,是如何实现递归以及栈操作的\nDialogue: 0,0:11:18.94,0:11:20.68,Default,,0,0,0,,还有个寄存器用来存放\nDialogue: 0,0:11:20.94,0:11:22.52,Default,,0,0,0,,某个求值的结果\nDialogue: 0,0:11:24.14,0:11:24.89,Default,,0,0,0,,然后 除了这些以外\nDialogue: 0,0:11:24.89,0:11:26.43,Default,,0,0,0,,还有一个临时寄存器\nDialogue: 0,0:11:26.70,0:11:27.29,Default,,0,0,0,,它就是UNEV\nDialogue: 0,0:11:27.29,0:11:29.04,Default,,0,0,0,,一般来讲 在求值器中\nDialogue: 0,0:11:29.28,0:11:32.72,Default,,0,0,0,,它是用来存放正在求值的表达式\nDialogue: 0,0:11:32.89,0:11:33.95,Default,,0,0,0,,的临时部分\nDialogue: 0,0:11:33.95,0:11:35.72,Default,,0,0,0,,就是那些尚未求值的部分\nDialogue: 0,0:11:36.97,0:11:39.82,Default,,0,0,0,,那么 这就是我的七寄存器机器\nDialogue: 0,0:11:40.96,0:11:42.98,Default,,0,0,0,,当然 你可能想造一台\nDialogue: 0,0:11:42.98,0:11:44.96,Default,,0,0,0,,有更多寄存器的机器 来取得更好性能\nDialogue: 0,0:11:44.97,0:11:47.05,Default,,0,0,0,,但我们这个只是一台小型机器\nDialogue: 0,0:11:48.48,0:11:49.58,Default,,0,0,0,,那么数据通路呢？\nDialogue: 0,0:11:49.78,0:11:53.66,Default,,0,0,0,,这台机器有很多专为Lisp设计的运算\nDialogue: 0,0:11:55.10,0:11:58.08,Default,,0,0,0,,这里有几条典型的数据通路\nDialogue: 0,0:12:00.12,0:12:01.04,Default,,0,0,0,,其中一条可能是\nDialogue: 0,0:12:01.37,0:12:03.40,Default,,0,0,0,,将EXP寄存器的值\nDialogue: 0,0:12:03.40,0:12:04.80,Default,,0,0,0,,赋给VAL寄存器\nDialogue: 0,0:12:05.71,0:12:08.01,Default,,0,0,0,,用我们之前的数据通路图来说\nDialogue: 0,0:12:08.03,0:12:10.81,Default,,0,0,0,,就是一条箭头上的小按钮\nDialogue: 0,0:12:11.90,0:12:13.13,Default,,0,0,0,,这还有一个更复杂的\nDialogue: 0,0:12:13.69,0:12:14.80,Default,,0,0,0,,它判断\nDialogue: 0,0:12:15.23,0:12:19.58,Default,,0,0,0,,如果EXP寄存器的内容是COND语句\nDialogue: 0,0:12:20.49,0:12:22.72,Default,,0,0,0,,那么这里就会跳转到EV-COND标号处\nDialogue: 0,0:12:23.80,0:12:26.23,Default,,0,0,0,,你可以想象出很多种实现它的方法\nDialogue: 0,0:12:26.23,0:12:28.36,Default,,0,0,0,,你可以把这个判断看作是\nDialogue: 0,0:12:28.36,0:12:29.98,Default,,0,0,0,,一个特殊意图的子过程\nDialogue: 0,0:12:30.60,0:12:33.95,Default,,0,0,0,,而条件被表示成某种数据抽象\nDialogue: 0,0:12:33.96,0:12:36.00,Default,,0,0,0,,你在这个层面上不用考虑它\nDialogue: 0,0:12:36.61,0:12:37.98,Default,,0,0,0,,那么它可以用子过程实现\nDialogue: 0,0:12:37.98,0:12:40.67,Default,,0,0,0,,如果机器通过硬件来判断表达式类型\nDialogue: 0,0:12:40.90,0:12:44.04,Default,,0,0,0,,那么某些特定比特就代表了COND语句\nDialogue: 0,0:12:45.35,0:12:46.41,Default,,0,0,0,,有很多种实现办法\nDialogue: 0,0:12:46.41,0:12:48.48,Default,,0,0,0,,它们都低于我们关注的这一层抽象\nDialogue: 0,0:12:50.19,0:12:51.71,Default,,0,0,0,,然后还有另一种操作\nDialogue: 0,0:12:51.71,0:12:53.24,Default,,0,0,0,,以及其它很多操作\nDialogue: 0,0:12:53.24,0:12:56.65,Default,,0,0,0,,把EXP的第一个子句赋值给EXP\nDialogue: 0,0:12:56.84,0:12:58.89,Default,,0,0,0,,这可能是处理COND语句的一部分\nDialogue: 0,0:12:59.26,0:13:01.80,Default,,0,0,0,,同样 FIRST-SELECTOR这个选择子\nDialogue: 0,0:13:03.07,0:13:04.48,Default,,0,0,0,,我们也不需要关心它的细节\nDialogue: 0,0:13:04.49,0:13:06.46,Default,,0,0,0,,同样可以把那也看成一个子过程\nDialogue: 0,0:13:06.46,0:13:07.90,Default,,0,0,0,,用来进行一些表操作\nDialogue: 0,0:13:08.22,0:13:09.18,Default,,0,0,0,,或者你也可以想象成\nDialogue: 0,0:13:09.18,0:13:10.73,Default,,0,0,0,,一个直接构建在硬件中的东西\nDialogue: 0,0:13:12.17,0:13:13.71,Default,,0,0,0,,我之所以强调\nDialogue: 0,0:13:14.03,0:13:15.22,Default,,0,0,0,,你可以把它想象成硬件直接实现\nDialogue: 0,0:13:15.22,0:13:17.80,Default,,0,0,0,,是因为尽管有很多的运算\nDialogue: 0,0:13:18.36,0:13:19.74,Default,,0,0,0,,但也它们的数量也是固定的\nDialogue: 0,0:13:20.12,0:13:21.80,Default,,0,0,0,,我记不清有多少 大概有150个\nDialogue: 0,0:13:22.37,0:13:25.39,Default,,0,0,0,,所以假设用硬件实现它们是合理的\nDialogue: 0,0:13:26.41,0:13:27.68,Default,,0,0,0,,而这一条更加复杂\nDialogue: 0,0:13:28.27,0:13:29.47,Default,,0,0,0,,你会发现 这条涉及到\nDialogue: 0,0:13:29.47,0:13:31.10,Default,,0,0,0,,查找变量的值\nDialogue: 0,0:13:31.50,0:13:33.28,Default,,0,0,0,,它会查找某条表达式中\nDialogue: 0,0:13:33.45,0:13:36.91,Default,,0,0,0,,某个变量的值\nDialogue: 0,0:13:36.99,0:13:38.52,Default,,0,0,0,,并赋值给VAL寄存器\nDialogue: 0,0:13:39.18,0:13:40.30,Default,,0,0,0,,在本例中 也就是\nDialogue: 0,0:13:40.33,0:13:42.00,Default,,0,0,0,,在某个环境中查找变量\nDialogue: 0,0:13:42.80,0:13:44.68,Default,,0,0,0,,然后这个操作\nDialogue: 0,0:13:45.21,0:13:47.50,Default,,0,0,0,,会搜索整个环境结构\nDialogue: 0,0:13:47.52,0:13:48.97,Default,,0,0,0,,无论环境是如何表示的\nDialogue: 0,0:13:49.37,0:13:50.91,Default,,0,0,0,,并查找该变量\nDialogue: 0,0:13:52.17,0:13:53.95,Default,,0,0,0,,同样 它也不在我们思考的\nDialogue: 0,0:13:53.96,0:13:54.86,Default,,0,0,0,,的抽象层面上\nDialogue: 0,0:13:54.89,0:13:57.30,Default,,0,0,0,,它需要处理的细节是\nDialogue: 0,0:13:57.55,0:13:59.44,Default,,0,0,0,,用来表示环境的数据结构\nDialogue: 0,0:14:00.07,0:14:01.21,Default,,0,0,0,,但是不管怎么说\nDialogue: 0,0:14:01.31,0:14:03.47,Default,,0,0,0,,这就是这台寄存器机器的\nDialogue: 0,0:14:04.11,0:14:06.08,Default,,0,0,0,,有穷数量的固定操作\nDialogue: 0,0:14:08.50,0:14:11.60,Default,,0,0,0,,那么 它的整体结构是什么样子的？\nDialogue: 0,0:14:11.72,0:14:13.23,Default,,0,0,0,,这有几个典型的运算\nDialogue: 0,0:14:14.76,0:14:16.33,Default,,0,0,0,,想一想 我们要做什么\nDialogue: 0,0:14:16.44,0:14:18.40,Default,,0,0,0,,我们需要把元循环求值器\nDialogue: 0,0:14:20.43,0:14:22.76,Default,,0,0,0,,这就是元循环求值器的一部分\nDialogue: 0,0:14:22.76,0:14:26.89,Default,,0,0,0,,这是书中使用抽象代码的版本\nDialogue: 0,0:14:28.22,0:14:31.53,Default,,0,0,0,,它和Gerry教授给你们展示的有些不同\nDialogue: 0,0:14:33.50,0:14:35.10,Default,,0,0,0,,关于求值器\nDialogue: 0,0:14:35.13,0:14:37.87,Default,,0,0,0,,主要需要记住的是\nDialogue: 0,0:14:37.87,0:14:40.96,Default,,0,0,0,,它是某种针对表达式类型的分情况分析\nDialogue: 0,0:14:43.76,0:14:45.90,Default,,0,0,0,,看它是否为自求值的 或被引用的\nDialogue: 0,0:14:45.92,0:14:46.86,Default,,0,0,0,,或是别的什么\nDialogue: 0,0:14:48.56,0:14:50.57,Default,,0,0,0,,而在大部分情况下\nDialogue: 0,0:14:50.86,0:14:52.96,Default,,0,0,0,,它处理的是一个过程应用\nDialogue: 0,0:14:53.55,0:14:55.36,Default,,0,0,0,,那么里面有一些技巧性的递归过程\nDialogue: 0,0:14:55.75,0:14:59.36,Default,,0,0,0,,首先 EVAL要调用它自己\nDialogue: 0,0:14:59.79,0:15:01.45,Default,,0,0,0,,来求值运算符以及\nDialogue: 0,0:15:02.14,0:15:04.04,Default,,0,0,0,,所有的运算对象\nDialogue: 0,0:15:05.88,0:15:07.40,Default,,0,0,0,,因此这些标红线的地方\nDialogue: 0,0:15:07.63,0:15:09.28,Default,,0,0,0,,就是某种在语法树上的递归\nDialogue: 0,0:15:10.94,0:15:12.27,Default,,0,0,0,,这是很简单的递归\nDialogue: 0,0:15:12.27,0:15:14.44,Default,,0,0,0,,只是EVAL在递归地遍历语法树\nDialogue: 0,0:15:14.75,0:15:15.53,Default,,0,0,0,,然后在求值器中\nDialogue: 0,0:15:15.53,0:15:16.46,Default,,0,0,0,,有一个复杂的递归\nDialogue: 0,0:15:16.49,0:15:17.92,Default,,0,0,0,,由绿线到红线的递归\nDialogue: 0,0:15:18.00,0:15:19.66,Default,,0,0,0,,由EVAL调用APPLY\nDialogue: 0,0:15:22.47,0:15:26.45,Default,,0,0,0,,也就是把过程调用\nDialogue: 0,0:15:26.45,0:15:28.72,Default,,0,0,0,,归约为了 将过程应用在\nDialogue: 0,0:15:28.94,0:15:29.93,Default,,0,0,0,,实参表上\nDialogue: 0,0:15:30.37,0:15:31.76,Default,,0,0,0,,然后请看APPLY\nDialogue: 0,0:15:34.77,0:15:36.67,Default,,0,0,0,,APPLY需要过程PROC和参数ARGS\nDialogue: 0,0:15:37.65,0:15:39.45,Default,,0,0,0,,一般情况下\nDialogue: 0,0:15:39.48,0:15:40.81,Default,,0,0,0,,PROC都是一个复合过程\nDialogue: 0,0:15:41.05,0:15:42.19,Default,,0,0,0,,随着APPLY不断被调用\nDialogue: 0,0:15:42.25,0:15:43.15,Default,,0,0,0,,绿线处会调用红线处\nDialogue: 0,0:15:43.34,0:15:46.44,Default,,0,0,0,,APPLY被调用并再次调用EVAL\nDialogue: 0,0:15:48.17,0:15:49.79,Default,,0,0,0,,EVAL会求值过程体\nDialogue: 0,0:15:50.24,0:15:52.59,Default,,0,0,0,,基于一个扩展了的环境\nDialogue: 0,0:15:53.69,0:15:55.28,Default,,0,0,0,,这个环境通过将过程的形式参数\nDialogue: 0,0:15:55.48,0:15:56.92,Default,,0,0,0,,与实际参数绑定起来而得\nDialogue: 0,0:15:59.62,0:16:00.62,Default,,0,0,0,,而对于最基本的情况\nDialogue: 0,0:16:00.64,0:16:02.52,Default,,0,0,0,,它会调用PRIMITIVE-APPLY过程\nDialogue: 0,0:16:02.73,0:16:04.70,Default,,0,0,0,,而那又不是求值器的工作了\nDialogue: 0,0:16:05.98,0:16:07.47,Default,,0,0,0,,那么像这样从红到绿\nDialogue: 0,0:16:07.47,0:16:08.40,Default,,0,0,0,,又到红又到绿\nDialogue: 0,0:16:09.79,0:16:12.72,Default,,0,0,0,,这就是EVAL-APPLY循环\nDialogue: 0,0:16:14.06,0:16:15.74,Default,,0,0,0,,这就是我们在求值器中\nDialogue: 0,0:16:16.19,0:16:17.72,Default,,0,0,0,,想要看到的东西\nDialogue: 0,0:16:19.69,0:16:21.07,Default,,0,0,0,,这样 你不会惊异于\nDialogue: 0,0:16:21.07,0:16:23.52,Default,,0,0,0,,这个求值器的两大部分\nDialogue: 0,0:16:25.34,0:16:27.04,Default,,0,0,0,,对应于EVAL-APPLY\nDialogue: 0,0:16:27.47,0:16:29.44,Default,,0,0,0,,一个部分叫EVAL-DISPATCH\nDialogue: 0,0:16:29.60,0:16:31.20,Default,,0,0,0,,另一部分叫做APPLY-DISPATCH\nDialogue: 0,0:16:32.00,0:16:34.09,Default,,0,0,0,,在我们关注代码细节之前\nDialogue: 0,0:16:34.20,0:16:35.76,Default,,0,0,0,,理解它们的方法就是\nDialogue: 0,0:16:36.09,0:16:39.02,Default,,0,0,0,,假设这些求值器的各个部分\nDialogue: 0,0:16:39.02,0:16:40.97,Default,,0,0,0,,和这个世界中其它的部分有一些约定\nDialogue: 0,0:16:41.87,0:16:43.18,Default,,0,0,0,,在进入这些肮脏的细节前\nDialogue: 0,0:16:43.20,0:16:45.50,Default,,0,0,0,,它们在外部做了什么？\nDialogue: 0,0:16:45.78,0:16:49.32,Default,,0,0,0,,针对EVAL-DISPATCH的约定\nDialogue: 0,0:16:50.01,0:16:51.40,Default,,0,0,0,,还记得吗 它对应的是EVAL\nDialogue: 0,0:16:51.55,0:16:54.10,Default,,0,0,0,,它要在环境中求值一个表达式\nDialogue: 0,0:16:54.10,0:16:55.88,Default,,0,0,0,,那么 这部分要做的就是\nDialogue: 0,0:16:56.52,0:16:58.68,Default,,0,0,0,,EVAL-DISPATCH会假设当你调用它的时候\nDialogue: 0,0:16:59.68,0:17:01.48,Default,,0,0,0,,你想要求值的表达式\nDialogue: 0,0:17:01.48,0:17:02.52,Default,,0,0,0,,就存放在EXP寄存器中\nDialogue: 0,0:17:03.64,0:17:07.39,Default,,0,0,0,,而求值所基于的环境\nDialogue: 0,0:17:07.45,0:17:09.05,Default,,0,0,0,,则存放在ENV环境中\nDialogue: 0,0:17:09.56,0:17:10.67,Default,,0,0,0,,而CONTINUE寄存器用来指示\nDialogue: 0,0:17:10.84,0:17:12.46,Default,,0,0,0,,当求值完成后\nDialogue: 0,0:17:12.52,0:17:13.92,Default,,0,0,0,,机器需要去向何方\nDialogue: 0,0:17:17.28,0:17:19.18,Default,,0,0,0,,EVAL-DISPATCH的约定实际上就是\nDialogue: 0,0:17:19.28,0:17:21.26,Default,,0,0,0,,它会执行实际的求值\nDialogue: 0,0:17:21.40,0:17:22.46,Default,,0,0,0,,并且在求值结束后\nDialogue: 0,0:17:23.28,0:17:25.63,Default,,0,0,0,,它会转到由CONTINUE寄存器指定的位置\nDialogue: 0,0:17:26.61,0:17:29.16,Default,,0,0,0,,求值的结果会存放在VAL寄存器中\nDialogue: 0,0:17:29.82,0:17:30.96,Default,,0,0,0,,需要提醒的是\nDialogue: 0,0:17:30.99,0:17:32.91,Default,,0,0,0,,它对其余的寄存器\nDialogue: 0,0:17:32.96,0:17:34.60,Default,,0,0,0,,不做任何承诺\nDialogue: 0,0:17:35.23,0:17:36.81,Default,,0,0,0,,其它所有的寄存器都可能被修改\nDialogue: 0,0:17:37.49,0:17:40.14,Default,,0,0,0,,那么这是一部分\nDialogue: 0,0:17:41.55,0:17:43.48,Default,,0,0,0,,这些部分一块构成了APPLY-DISPATCH\nDialogue: 0,0:17:43.52,0:17:44.92,Default,,0,0,0,,它们对应了APPLY\nDialogue: 0,0:17:46.09,0:17:48.43,Default,,0,0,0,,用来把一个过程应用在一些参数上\nDialogue: 0,0:17:48.73,0:17:51.43,Default,,0,0,0,,因此它假设ARGL寄存器\nDialogue: 0,0:17:51.68,0:17:53.77,Default,,0,0,0,,存放着求值后的参数列表\nDialogue: 0,0:17:54.54,0:17:55.96,Default,,0,0,0,,FUN寄存器存放着那个过程\nDialogue: 0,0:17:57.22,0:17:58.83,Default,,0,0,0,,它们对应于元循环求值器中的\nDialogue: 0,0:17:58.94,0:18:01.36,Default,,0,0,0,,参数应用部分\nDialogue: 0,0:18:03.97,0:18:06.04,Default,,0,0,0,,在我们的这个求值器中\nDialogue: 0,0:18:06.06,0:18:07.58,Default,,0,0,0,,我们APPLY时采用的约定是\nDialogue: 0,0:18:07.72,0:18:08.97,Default,,0,0,0,,当APPLY完成后--\nDialogue: 0,0:18:09.47,0:18:11.20,Default,,0,0,0,,机器应该跳转到\nDialogue: 0,0:18:11.79,0:18:13.45,Default,,0,0,0,,的下一个地方应该是\nDialogue: 0,0:18:13.55,0:18:15.92,Default,,0,0,0,,APPLY-DISPATCH被调用时的栈顶元素\nDialogue: 0,0:18:17.07,0:18:21.24,Default,,0,0,0,,这只是针对这台机器的约定\nDialogue: 0,0:18:21.84,0:18:23.70,Default,,0,0,0,,现在已经给出了APPLY的所有约定\nDialogue: 0,0:18:23.93,0:18:25.37,Default,,0,0,0,,它会去执行应用\nDialogue: 0,0:18:25.54,0:18:27.85,Default,,0,0,0,,这个应用的结果将会保存在VAL寄存器中\nDialogue: 0,0:18:28.89,0:18:29.95,Default,,0,0,0,,栈会被弹出\nDialogue: 0,0:18:31.12,0:18:31.66,Default,,0,0,0,,同样的\nDialogue: 0,0:18:31.71,0:18:34.03,Default,,0,0,0,,其它所有寄存器的内容都可能被修改\nDialogue: 0,0:18:34.84,0:18:37.82,Default,,0,0,0,,那么 这就是这台机器的基本结构\nDialogue: 0,0:18:38.99,0:18:41.50,Default,,0,0,0,,我们先课间休息一下\nDialogue: 0,0:18:41.52,0:18:42.70,Default,,0,0,0,,然后再来研究一个真实的例子\nDialogue: 0,0:18:43.53,0:19:08.11,Default,,0,0,0,,[音乐]\nDialogue: 0,0:19:08.14,0:19:13.47,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:19:33.10,0:19:35.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:19:35.87,0:19:40.38,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:19:40.38,0:19:45.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}显式控制求值器\nDialogue: 0,0:19:47.85,0:19:49.95,Default,,0,0,0,,现在 我们来研究一下这台寄存器机器\nDialogue: 0,0:19:50.41,0:19:51.77,Default,,0,0,0,,我们一步一步地跟进\nDialogue: 0,0:19:52.27,0:19:56.94,Default,,0,0,0,,具体到每一处细节\nDialogue: 0,0:19:57.07,0:19:58.52,Default,,0,0,0,,这样你就能完全具体地看到\nDialogue: 0,0:19:58.86,0:20:01.24,Default,,0,0,0,,表达式是如何求值的\nDialogue: 0,0:20:03.15,0:20:06.86,Default,,0,0,0,,那么我们从一个非常简单的表达式开始\nDialogue: 0,0:20:07.45,0:20:13.52,Default,,0,0,0,,我们要求值的表达式只有一个1\nDialogue: 0,0:20:18.77,0:20:20.40,Default,,0,0,0,,我们需要一个环境\nDialogue: 0,0:20:20.43,0:20:22.35,Default,,0,0,0,,因此我们假设某处有一个环境\nDialogue: 0,0:20:22.38,0:20:23.39,Default,,0,0,0,,我们把它记作E0\nDialogue: 0,0:20:30.06,0:20:34.56,Default,,0,0,0,,由于我们之后也要用到它\nDialogue: 0,0:20:35.62,0:20:37.04,Default,,0,0,0,,而且显然不需要任何东西\nDialogue: 0,0:20:37.07,0:20:37.93,Default,,0,0,0,,就可以求值1\nDialogue: 0,0:20:38.36,0:20:39.45,Default,,0,0,0,,但是为了方便以后引用\nDialogue: 0,0:20:39.45,0:20:40.94,Default,,0,0,0,,我们假设环境E0中有\nDialogue: 0,0:20:41.44,0:20:43.15,Default,,0,0,0,,X=3\nDialogue: 0,0:20:43.72,0:20:45.37,Default,,0,0,0,,Y=4\nDialogue: 0,0:20:48.27,0:20:48.78,Default,,0,0,0,,好吗？\nDialogue: 0,0:20:49.14,0:20:50.12,Default,,0,0,0,,现在 我们要做的就是\nDialogue: 0,0:20:50.51,0:20:54.59,Default,,0,0,0,,在这个环境中求值表达式1\nDialogue: 0,0:20:55.74,0:20:58.54,Default,,0,0,0,,这样 ENV寄存器就存放了一个指针\nDialogue: 0,0:20:59.65,0:21:01.04,Default,,0,0,0,,指向这个环境E0\nDialogue: 0,0:21:03.31,0:21:05.65,Default,,0,0,0,,那么我们来看它是怎么进行的\nDialogue: 0,0:21:05.65,0:21:07.26,Default,,0,0,0,,我要步步跟进代码\nDialogue: 0,0:21:08.26,0:21:10.00,Default,,0,0,0,,这样的话 我会充当控制器\nDialogue: 0,0:21:10.04,0:21:10.80,Default,,0,0,0,,现在我需要的是--\nDialogue: 0,0:21:11.02,0:21:12.49,Default,,0,0,0,,由于这台机器已经变得相当复杂\nDialogue: 0,0:21:12.98,0:21:16.83,Default,,0,0,0,,我需要一个小小的执行单元\nDialogue: 0,0:21:16.83,0:21:18.16,Default,,0,0,0,,那么请上我们的执行单元\nDialogue: 0,0:21:22.62,0:21:23.12,Default,,0,0,0,,好的\nDialogue: 0,0:21:28.59,0:21:29.96,Default,,0,0,0,,好 现在我们要开始了\nDialogue: 0,0:21:30.53,0:21:32.48,Default,,0,0,0,,我们要从EVAL-DISPATCH启动机器\nDialogue: 0,0:21:33.26,0:21:34.62,Default,,0,0,0,,这是整个过程的开始\nDialogue: 0,0:21:35.87,0:21:38.75,Default,,0,0,0,,EVAL-DISPATCH会查看表达式并进行分派\nDialogue: 0,0:21:39.32,0:21:40.06,Default,,0,0,0,,就像EVAL\nDialogue: 0,0:21:40.87,0:21:42.00,Default,,0,0,0,,先从第一句看起\nDialogue: 0,0:21:42.04,0:21:47.95,Default,,0,0,0,,先判断表达式是不是自求值的\nDialogue: 0,0:21:47.95,0:21:49.96,Default,,0,0,0,,SELF-EVALUATING?是我们放入机器的\nDialogue: 0,0:21:49.96,0:21:51.10,Default,,0,0,0,,一个抽象过程\nDialogue: 0,0:21:52.22,0:21:53.51,Default,,0,0,0,,它对于数字1来说为真\nDialogue: 0,0:21:53.64,0:21:55.52,Default,,0,0,0,,因此跳转的目的是EV-SELF-EVAL\nDialogue: 0,0:21:56.77,0:21:58.20,Default,,0,0,0,,那么我作为控制器\nDialogue: 0,0:21:58.22,0:21:59.55,Default,,0,0,0,,会去查看EV-SELF-EVAL\nDialogue: 0,0:22:00.06,0:22:01.07,Default,,0,0,0,,所以我们要跳到那里\nDialogue: 0,0:22:02.60,0:22:04.76,Default,,0,0,0,,EV-SELF-EAVL的代码是--\nDialogue: 0,0:22:06.54,0:22:09.90,Default,,0,0,0,,把EXP寄存器的值赋值给VAL寄存器\nDialogue: 0,0:22:15.24,0:22:16.51,Default,,0,0,0,,我遇到一个BUG\nDialogue: 0,0:22:17.93,0:22:20.59,Default,,0,0,0,,因为我初始化机器的时候没有做一件事情\nDialogue: 0,0:22:21.62,0:22:22.89,Default,,0,0,0,,也就是指定当它执行完毕后\nDialogue: 0,0:22:22.91,0:22:24.19,Default,,0,0,0,,应该做什么\nDialogue: 0,0:22:24.65,0:22:26.83,Default,,0,0,0,,所以在启动机器的时候\nDialogue: 0,0:22:27.37,0:22:29.85,Default,,0,0,0,,应该将CONTINUE寄存器设置为DONE\nDialogue: 0,0:22:31.18,0:22:33.26,Default,,0,0,0,,所以我们给VAL赋值\nDialogue: 0,0:22:33.37,0:22:35.56,Default,,0,0,0,,然后执行(GOTO (FETCH CONTINUE))\nDialogue: 0,0:22:35.63,0:22:36.56,Default,,0,0,0,,并且修改--\nDialogue: 0,0:22:38.09,0:22:38.60,Default,,0,0,0,,好\nDialogue: 0,0:22:40.00,0:22:41.16,Default,,0,0,0,,好 我们来看一个更复杂的\nDialogue: 0,0:22:42.16,0:22:43.45,Default,,0,0,0,,我们先重置机器\nDialogue: 0,0:22:44.86,0:22:50.88,Default,,0,0,0,,然后把X放入EXP寄存器中\nDialogue: 0,0:22:56.71,0:22:58.20,Default,,0,0,0,,重新从EVAL-DISPATCH开始\nDialogue: 0,0:22:59.61,0:23:01.69,Default,,0,0,0,,先检查它是自求值的么？\nDialogue: 0,0:23:01.69,0:23:02.03,Default,,0,0,0,,不是\nDialogue: 0,0:23:02.65,0:23:03.61,Default,,0,0,0,,它是变量吗\nDialogue: 0,0:23:04.63,0:23:05.02,Default,,0,0,0,,是的\nDialogue: 0,0:23:05.56,0:23:07.07,Default,,0,0,0,,我们跳转到EV-VARIABLE\nDialogue: 0,0:23:08.38,0:23:10.97,Default,,0,0,0,,它说：查找EXP寄存器中变量的值\nDialogue: 0,0:23:12.13,0:23:15.69,Default,,0,0,0,,并把它赋值给VAL寄存器\nDialogue: 0,0:23:21.23,0:23:22.91,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,0:23:23.96,0:23:24.48,Default,,0,0,0,,Sussman教授：DONE\nDialogue: 0,0:23:27.61,0:23:28.09,Default,,0,0,0,,Abelson教授：好\nDialogue: 0,0:23:29.31,0:23:30.76,Default,,0,0,0,,这些都是最基本的理念\nDialogue: 0,0:23:31.33,0:23:32.65,Default,,0,0,0,,这是这台机器上的简单运算\nDialogue: 0,0:23:32.68,0:23:35.07,Default,,0,0,0,,现在 我们来做些有意义的事情\nDialogue: 0,0:23:36.07,0:23:38.64,Default,,0,0,0,,我们看这条表达式\nDialogue: 0,0:23:43.58,0:23:47.93,Default,,0,0,0,,(+ X Y)\nDialogue: 0,0:23:49.69,0:23:51.28,Default,,0,0,0,,现在我们会看到\nDialogue: 0,0:23:52.41,0:23:54.01,Default,,0,0,0,,如何展开这些表达式树\nDialogue: 0,0:23:57.13,0:23:58.68,Default,,0,0,0,,我们再次从EVAL-DISPATCH开始\nDialogue: 0,0:24:04.61,0:24:05.80,Default,,0,0,0,,是自求值的吗？\nDialogue: 0,0:24:05.95,0:24:06.52,Default,,0,0,0,,不是\nDialogue: 0,0:24:06.70,0:24:07.71,Default,,0,0,0,,是变量吗？不是\nDialogue: 0,0:24:07.82,0:24:08.99,Default,,0,0,0,,它也不是我在这里\nDialogue: 0,0:24:08.99,0:24:10.12,Default,,0,0,0,,没有列出的特殊形式\nDialogue: 0,0:24:10.27,0:24:12.48,Default,,0,0,0,,比如引用、LAMBDA、SET! 等等\nDialogue: 0,0:24:12.48,0:24:13.08,Default,,0,0,0,,它都不是\nDialogue: 0,0:24:13.26,0:24:14.73,Default,,0,0,0,,它是一个过程应用\nDialogue: 0,0:24:15.88,0:24:17.42,Default,,0,0,0,,所以我们要跳转到EV-APPLICATION\nDialogue: 0,0:24:19.97,0:24:24.94,Default,,0,0,0,,回忆一下EV-APPLICATION要做什么\nDialogue: 0,0:24:25.58,0:24:28.19,Default,,0,0,0,,它先要求值运算符\nDialogue: 0,0:24:28.27,0:24:31.40,Default,,0,0,0,,然后求值运算对象\nDialogue: 0,0:24:32.36,0:24:34.30,Default,,0,0,0,,然后再进行应用\nDialogue: 0,0:24:35.06,0:24:36.09,Default,,0,0,0,,所以在我们开始之前\nDialogue: 0,0:24:36.94,0:24:37.88,Default,,0,0,0,,由于我们是严格按照代码来执行的\nDialogue: 0,0:24:37.88,0:24:38.88,Default,,0,0,0,,我们最好记住\nDialogue: 0,0:24:39.07,0:24:40.54,Default,,0,0,0,,在这个环境中的某处\nDialogue: 0,0:24:40.57,0:24:42.36,Default,,0,0,0,,连接到了另一个环境\nDialogue: 0,0:24:43.98,0:24:44.94,Default,,0,0,0,,其中符号'+\nDialogue: 0,0:24:45.72,0:24:49.16,Default,,0,0,0,,跟基本的加法过程绑定在了一起\nDialogue: 0,0:24:51.63,0:24:54.03,Default,,0,0,0,,这样 求值+时就不会导致“变量未定义”\nDialogue: 0,0:24:55.34,0:24:56.84,Default,,0,0,0,,现在我们来到了EV-APPLICATION\nDialogue: 0,0:24:59.85,0:25:04.32,Default,,0,0,0,,把EXP寄存器对应的运算对象\nDialogue: 0,0:25:04.92,0:25:06.89,Default,,0,0,0,,赋值给UNEV寄存器\nDialogue: 0,0:25:07.61,0:25:08.83,Default,,0,0,0,,这些是运算对象\nDialogue: 0,0:25:09.23,0:25:11.66,Default,,0,0,0,,UNEV这个临时寄存器\nDialogue: 0,0:25:11.68,0:25:12.59,Default,,0,0,0,,就是用来暂存它们的\nDialogue: 0,0:25:13.22,0:25:13.86,Default,,0,0,0,,Sussman教授：我正在赋值\nDialogue: 0,0:25:14.28,0:25:16.62,Default,,0,0,0,,Abelson教授：把运算符赋值给EXP寄存器\nDialogue: 0,0:25:18.07,0:25:20.09,Default,,0,0,0,,注意 现在我们已经修改了EXP中的表达式\nDialogue: 0,0:25:21.84,0:25:23.61,Default,,0,0,0,,但是我们需要的部分在UNEV中\nDialogue: 0,0:25:25.82,0:25:26.81,Default,,0,0,0,,现在 我们要准备好\nDialogue: 0,0:25:26.81,0:25:28.59,Default,,0,0,0,,去递归地求值运算符\nDialogue: 0,0:25:28.75,0:25:31.69,Default,,0,0,0,,把CONTINUE寄存器保存在栈上\nDialogue: 0,0:25:34.86,0:25:36.09,Default,,0,0,0,,保存ENV\nDialogue: 0,0:25:40.48,0:25:41.69,Default,,0,0,0,,保存UNEV\nDialogue: 0,0:25:49.53,0:25:54.64,Default,,0,0,0,,把标号EVAL-ARGS赋值给CONTINUE寄存器\nDialogue: 0,0:26:01.40,0:26:01.95,Default,,0,0,0,,我们做了什么\nDialogue: 0,0:26:01.95,0:26:04.38,Default,,0,0,0,,我们为递归调用做了必要的准备\nDialogue: 0,0:26:04.38,0:26:05.88,Default,,0,0,0,,我们要开始执行EVAL-DISPATCH\nDialogue: 0,0:26:06.28,0:26:08.83,Default,,0,0,0,,我们为递归调用EVAL-DISPATCH做好了准备\nDialogue: 0,0:26:10.23,0:26:10.86,Default,,0,0,0,,我们做了哪些事情\nDialogue: 0,0:26:11.02,0:26:13.64,Default,,0,0,0,,我们把之后要用到的东西\nDialogue: 0,0:26:14.48,0:26:15.98,Default,,0,0,0,,也就是UNEV中的运算对象\nDialogue: 0,0:26:16.36,0:26:18.99,Default,,0,0,0,,以及我们最终求值运算对象时\nDialogue: 0,0:26:19.16,0:26:20.72,Default,,0,0,0,,会用到的环境\nDialogue: 0,0:26:22.28,0:26:23.93,Default,,0,0,0,,以及我们最终想要去的位置\nDialogue: 0,0:26:23.95,0:26:25.07,Default,,0,0,0,,本例中 也就是DONE\nDialogue: 0,0:26:25.34,0:26:26.70,Default,,0,0,0,,我们把它们保存在栈上\nDialogue: 0,0:26:27.10,0:26:28.41,Default,,0,0,0,,我们之所以把它们保存在栈上\nDialogue: 0,0:26:28.43,0:26:30.67,Default,,0,0,0,,是因为EVAL-DISPATCH并不会保证\nDialogue: 0,0:26:30.94,0:26:32.54,Default,,0,0,0,,不会去修改这些寄存器\nDialogue: 0,0:26:33.55,0:26:35.02,Default,,0,0,0,,那么所有这些东西都存在了栈上\nDialogue: 0,0:26:35.02,0:26:36.91,Default,,0,0,0,,现在我们满足了EVAL-DISPATCH的约定\nDialogue: 0,0:26:37.38,0:26:38.75,Default,,0,0,0,,这是一条新的表达式\nDialogue: 0,0:26:38.78,0:26:40.04,Default,,0,0,0,,也就是+运算符\nDialogue: 0,0:26:41.07,0:26:41.95,Default,,0,0,0,,以及一个新的环境\nDialogue: 0,0:26:41.98,0:26:43.60,Default,,0,0,0,,尽管在本例中是同一个环境\nDialogue: 0,0:26:44.25,0:26:45.87,Default,,0,0,0,,以及在完成后要返回的位置\nDialogue: 0,0:26:45.87,0:26:46.91,Default,,0,0,0,,也就是EVAL-ARGS\nDialogue: 0,0:26:47.60,0:26:48.13,Default,,0,0,0,,这样就满足了\nDialogue: 0,0:26:48.13,0:26:49.68,Default,,0,0,0,,现在我们来执行EVAL-DISPATCH\nDialogue: 0,0:26:50.89,0:26:52.36,Default,,0,0,0,,我们回到了EVAL-DISPATCH\nDialogue: 0,0:26:53.05,0:26:54.40,Default,,0,0,0,,它不是自求值的\nDialogue: 0,0:26:54.44,0:26:55.47,Default,,0,0,0,,但它是一个变量\nDialogue: 0,0:26:56.32,0:26:58.06,Default,,0,0,0,,因此我们最好跳转到EV-VARIABLE\nDialogue: 0,0:26:59.79,0:27:02.65,Default,,0,0,0,,EV-VARIABLE首先要给VAL赋值\nDialogue: 0,0:27:02.70,0:27:06.33,Default,,0,0,0,,查找表达式中变量的值\nDialogue: 0,0:27:08.49,0:27:10.75,Default,,0,0,0,,那么VAL寄存器中应该是基本的加法运算\nDialogue: 0,0:27:13.37,0:27:15.16,Default,,0,0,0,,然后(GOTO (FETCH CONTINUE))\nDialogue: 0,0:27:15.23,0:27:16.11,Default,,0,0,0,,Sussman教授：它是EVAL-ARGS\nDialogue: 0,0:27:16.20,0:27:18.73,Default,,0,0,0,,Abelson教授：现在它是EVAL-ARGS而不是DONE了\nDialogue: 0,0:27:19.42,0:27:21.26,Default,,0,0,0,,然后我们来到EVAL-ARGS\nDialogue: 0,0:27:22.16,0:27:23.02,Default,,0,0,0,,看看它要做什么\nDialogue: 0,0:27:23.07,0:27:24.84,Default,,0,0,0,,我们要恢复之前保存的东西\nDialogue: 0,0:27:25.20,0:27:26.57,Default,,0,0,0,,因此调用(RESTORE UNEV)\nDialogue: 0,0:27:29.21,0:27:31.69,Default,,0,0,0,,注意 这里并不是必要的\nDialogue: 0,0:27:31.74,0:27:32.90,Default,,0,0,0,,但通常来说都会有这么一步\nDialogue: 0,0:27:32.90,0:27:35.16,Default,,0,0,0,,它可以是任意的求值过程\nDialogue: 0,0:27:35.43,0:27:36.70,Default,,0,0,0,,恢复ENV寄存器\nDialogue: 0,0:27:47.87,0:27:52.04,Default,,0,0,0,,然后把(FETCH VAL)赋值给FUN\nDialogue: 0,0:27:59.95,0:28:02.81,Default,,0,0,0,,现在我们要开始求值参数了\nDialogue: 0,0:28:04.34,0:28:06.48,Default,,0,0,0,,首先 我们最好把FUN寄存器保存起来\nDialogue: 0,0:28:07.42,0:28:10.62,Default,,0,0,0,,因为求值过程中可能发生任何事情\nDialogue: 0,0:28:15.33,0:28:16.88,Default,,0,0,0,,我们初始化参数列表\nDialogue: 0,0:28:16.91,0:28:19.29,Default,,0,0,0,,给ARGL赋值一个空的参数列表\nDialogue: 0,0:28:20.88,0:28:22.17,Default,,0,0,0,,然后跳转到EVAL-ARG-LOOP\nDialogue: 0,0:28:24.86,0:28:26.27,Default,,0,0,0,,在EVAL-ARG-LOOP中\nDialogue: 0,0:28:27.77,0:28:31.53,Default,,0,0,0,,我们想要去一条一条的求值\nDialogue: 0,0:28:31.61,0:28:33.37,Default,,0,0,0,,UNEV中的表达式\nDialogue: 0,0:28:33.54,0:28:35.68,Default,,0,0,0,,然后把它们从UNEV中的待求值表\nDialogue: 0,0:28:35.90,0:28:37.26,Default,,0,0,0,,移动到ARGL中的已求值表中\nDialogue: 0,0:28:37.84,0:28:39.18,Default,,0,0,0,,然后我们保存ARGL\nDialogue: 0,0:28:43.95,0:28:47.26,Default,,0,0,0,,然后我们把UNEV中的第一个运算对象\nDialogue: 0,0:28:47.37,0:28:48.38,Default,,0,0,0,,赋值给EXP\nDialogue: 0,0:28:53.77,0:28:55.89,Default,,0,0,0,,然后我们检查它是否为最后一个运算对象\nDialogue: 0,0:28:55.89,0:28:56.91,Default,,0,0,0,,在这里 它还不是\nDialogue: 0,0:28:58.99,0:29:01.55,Default,,0,0,0,,然后我们保存环境\nDialogue: 0,0:29:08.00,0:29:10.06,Default,,0,0,0,,我们之所以保存UNEV\nDialogue: 0,0:29:11.61,0:29:13.50,Default,,0,0,0,,是因为稍后我们可能会需要它们\nDialogue: 0,0:29:13.50,0:29:14.40,Default,,0,0,0,,我们需要环境\nDialogue: 0,0:29:14.44,0:29:15.64,Default,,0,0,0,,来进行一些求值\nDialogue: 0,0:29:15.80,0:29:16.60,Default,,0,0,0,,我们需要UNEV寄存器来指示\nDialogue: 0,0:29:16.62,0:29:19.20,Default,,0,0,0,,其余的待求值参数\nDialogue: 0,0:29:20.34,0:29:21.55,Default,,0,0,0,,我们要把CONTINUE寄存器赋值为\nDialogue: 0,0:29:21.56,0:29:24.44,Default,,0,0,0,,ACCUMULATE-ARG这个标号\nDialogue: 0,0:29:31.13,0:29:34.01,Default,,0,0,0,,现在 我们已经准备好再次调用EVAL-DISPATCH了\nDialogue: 0,0:29:37.07,0:29:38.54,Default,,0,0,0,,现在让我把这个短路掉\nDialogue: 0,0:29:39.12,0:29:41.09,Default,,0,0,0,,这里我们不跟进EVAL-DISPATCH的细节\nDialogue: 0,0:29:41.09,0:29:42.64,Default,,0,0,0,,EVAL-DISPATCH的约定说：\nDialogue: 0,0:29:42.97,0:29:45.00,Default,,0,0,0,,我的调用完成后\nDialogue: 0,0:29:45.13,0:29:45.96,Default,,0,0,0,,整个机器的状态会变为\nDialogue: 0,0:29:46.03,0:29:48.20,Default,,0,0,0,,也就是在ENV环境中求值EXP表达式\nDialogue: 0,0:29:48.24,0:29:50.27,Default,,0,0,0,,求值结果会保存在VAL寄存器中\nDialogue: 0,0:29:50.27,0:29:51.07,Default,,0,0,0,,结束状态就是这样\nDialogue: 0,0:29:51.32,0:29:52.62,Default,,0,0,0,,那么我们把这些全都省略掉\nDialogue: 0,0:29:54.43,0:29:56.36,Default,,0,0,0,,最后VAL的内容是3\nDialogue: 0,0:29:58.01,0:29:59.76,Default,,0,0,0,,并且当我们从EVAL-DISPATCH返回的时候\nDialogue: 0,0:29:59.76,0:30:01.76,Default,,0,0,0,,我们会返回到ACCUMULAT-ARG这里\nDialogue: 0,0:30:02.30,0:30:03.23,Default,,0,0,0,,Sussman教授：跳转到ACCUMULATE-ARG\nDialogue: 0,0:30:06.22,0:30:08.20,Default,,0,0,0,,Abelson教授：VAL寄存器里是3 对吧？\nDialogue: 0,0:30:08.72,0:30:10.59,Default,,0,0,0,,我们跳过了求值的细节\nDialogue: 0,0:30:10.65,0:30:11.32,Default,,0,0,0,,现在我们要做什么？\nDialogue: 0,0:30:11.32,0:30:13.68,Default,,0,0,0,,我们返回继续看剩下的参数\nDialogue: 0,0:30:13.68,0:30:14.83,Default,,0,0,0,,我们恢复UNEV\nDialogue: 0,0:30:17.51,0:30:19.00,Default,,0,0,0,,恢复ENV\nDialogue: 0,0:30:25.79,0:30:27.05,Default,,0,0,0,,然后恢复ARGL\nDialogue: 0,0:30:28.65,0:30:29.17,Default,,0,0,0,,这件事\nDialogue: 0,0:30:30.06,0:30:31.45,Default,,0,0,0,,Sussman教授：糟糕 奇偶错误\nDialogue: 0,0:30:33.76,0:30:34.83,Default,,0,0,0,,Abelson教授：恢复ARGL\nDialogue: 0,0:30:45.57,0:30:49.76,Default,,0,0,0,,然后 我们把VAL寄存器和ARGL给CONS起来\nDialogue: 0,0:30:50.65,0:30:52.64,Default,,0,0,0,,然后赋值给ARGL寄存器\nDialogue: 0,0:30:59.36,0:31:02.96,Default,,0,0,0,,我们把UNEV中剩余的运算对象\nDialogue: 0,0:31:03.34,0:31:04.52,Default,,0,0,0,,赋值给UNEV\nDialogue: 0,0:31:08.91,0:31:10.76,Default,,0,0,0,,然后我们返回到EVAL-ARG-LOOP\nDialogue: 0,0:31:11.51,0:31:12.28,Default,,0,0,0,,Sussman教授：EVAL-ARG-LOOP\nDialogue: 0,0:31:12.28,0:31:12.86,Default,,0,0,0,,Abelson教授：好\nDialogue: 0,0:31:15.88,0:31:17.08,Default,,0,0,0,,现在我们处理下一个参数\nDialogue: 0,0:31:17.58,0:31:19.31,Default,,0,0,0,,所以首先我们要保存ARGL\nDialogue: 0,0:31:25.40,0:31:28.27,Default,,0,0,0,,然后我们把UNEV中的第一个运算对象\nDialogue: 0,0:31:29.15,0:31:30.81,Default,,0,0,0,,赋给EXP\nDialogue: 0,0:31:34.72,0:31:37.02,Default,,0,0,0,,然后我们检查它是否为最后一个运算对象\nDialogue: 0,0:31:37.02,0:31:38.00,Default,,0,0,0,,这里它是最后一个\nDialogue: 0,0:31:39.08,0:31:40.27,Default,,0,0,0,,所以我们跳到一个特殊的地方\nDialogue: 0,0:31:40.28,0:31:42.06,Default,,0,0,0,,来求值最后一个参数\nDialogue: 0,0:31:43.37,0:31:45.07,Default,,0,0,0,,因为请注意 在求值这个参数之后\nDialogue: 0,0:31:45.10,0:31:46.62,Default,,0,0,0,,我们就不再需要这个环境了\nDialogue: 0,0:31:47.64,0:31:48.78,Default,,0,0,0,,这就是区别\nDialogue: 0,0:31:50.25,0:31:51.85,Default,,0,0,0,,在这里 在EVAL-LAST-ARG这里\nDialogue: 0,0:31:52.24,0:31:54.92,Default,,0,0,0,,CONTINUE被赋值为了ACCUMULATE-LAST-ARG\nDialogue: 0,0:32:04.27,0:32:06.90,Default,,0,0,0,,现在我们再次为EVAL-DISPATCH做准备\nDialogue: 0,0:32:06.90,0:32:08.51,Default,,0,0,0,,我们有一个完成时要跳转的目的地\nDialogue: 0,0:32:08.62,0:32:09.84,Default,,0,0,0,,我们有一条表达式\nDialogue: 0,0:32:09.84,0:32:10.80,Default,,0,0,0,,还有一个环境\nDialogue: 0,0:32:11.33,0:32:13.64,Default,,0,0,0,,好 那么我们略过对EVAL-DISPATCH的调用\nDialogue: 0,0:32:14.37,0:32:16.41,Default,,0,0,0,,现在情况是这里有一个Y\nDialogue: 0,0:32:16.70,0:32:18.56,Default,,0,0,0,,在这个环境中 它的值是4\nDialogue: 0,0:32:18.60,0:32:20.09,Default,,0,0,0,,所以最终VAL寄存器将会是4\nDialogue: 0,0:32:21.06,0:32:22.86,Default,,0,0,0,,然后我们就要以ACCUMULATE-LAST-ARG结束了\nDialogue: 0,0:32:25.45,0:32:26.91,Default,,0,0,0,,因此 在ACCUMULATE-LAST-ARG中\nDialogue: 0,0:32:29.28,0:32:30.52,Default,,0,0,0,,我们恢复ARGL寄存器\nDialogue: 0,0:32:37.69,0:32:42.76,Default,,0,0,0,,我们把ARGL赋值为\nDialogue: 0,0:32:43.60,0:32:45.83,Default,,0,0,0,,将一个新值CONS在它上面的结果\nDialogue: 0,0:32:45.93,0:32:47.39,Default,,0,0,0,,所以我们在它的旧值前CONS一个4\nDialogue: 0,0:32:49.85,0:32:52.52,Default,,0,0,0,,我们恢复FUN寄存器中的内容\nDialogue: 0,0:32:53.77,0:32:54.99,Default,,0,0,0,,需要注意的是 在则个例子中\nDialogue: 0,0:32:55.00,0:32:56.27,Default,,0,0,0,,FUN寄存器还没有被修改过\nDialogue: 0,0:32:56.38,0:32:57.72,Default,,0,0,0,,但是通常来说 它会的\nDialogue: 0,0:32:59.13,0:33:01.50,Default,,0,0,0,,现在 我们将要调用APPLY-DISPATCH\nDialogue: 0,0:33:02.65,0:33:04.40,Default,,0,0,0,,所以我们刚刚步步跟进了EVAL过程\nDialogue: 0,0:33:04.51,0:33:05.85,Default,,0,0,0,,我们求值了运算符\nDialogue: 0,0:33:06.46,0:33:07.98,Default,,0,0,0,,以及实际参数\nDialogue: 0,0:33:07.98,0:33:09.24,Default,,0,0,0,,现在我们要应用它们了\nDialogue: 0,0:33:09.58,0:33:11.37,Default,,0,0,0,,因此 我们来到APPLY-DISPATCH这里\nDialogue: 0,0:33:18.03,0:33:19.29,Default,,0,0,0,,这是APPLY-DISPATCH的代码\nDialogue: 0,0:33:21.05,0:33:22.41,Default,,0,0,0,,我们要检查它是一个基本过程\nDialogue: 0,0:33:22.41,0:33:23.45,Default,,0,0,0,,还是一个复合过程\nDialogue: 0,0:33:23.64,0:33:24.20,Default,,0,0,0,,Sussman教授：基本过程\nDialogue: 0,0:33:24.54,0:33:24.83,Default,,0,0,0,,Abelson教授：好的\nDialogue: 0,0:33:24.89,0:33:26.52,Default,,0,0,0,,这里 它是一个基本过程\nDialogue: 0,0:33:27.45,0:33:28.91,Default,,0,0,0,,因此 我们跳转到PRIMITIVE-APPLY\nDialogue: 0,0:33:29.79,0:33:31.36,Default,,0,0,0,,我们来到PRIMITIVE-APPLY\nDialogue: 0,0:33:33.71,0:33:35.37,Default,,0,0,0,,它说：把VAL赋值为\nDialogue: 0,0:33:35.69,0:33:38.25,Default,,0,0,0,,把基本过程\nDialogue: 0,0:33:38.36,0:33:40.30,Default,,0,0,0,,应用在参数表的结果\nDialogue: 0,0:33:41.31,0:33:42.43,Default,,0,0,0,,Sussman教授：我不知道怎么做加法\nDialogue: 0,0:33:42.54,0:33:43.80,Default,,0,0,0,,我只是一个执行单元\nDialogue: 0,0:33:44.14,0:33:45.35,Default,,0,0,0,,Abelson教授：我也不知道\nDialogue: 0,0:33:45.35,0:33:46.51,Default,,0,0,0,,我只是一个求值器\nDialogue: 0,0:33:47.08,0:33:48.36,Default,,0,0,0,,因此 我们需要一个基本运算执行器\nDialogue: 0,0:33:48.36,0:33:49.72,Default,,0,0,0,,那么 请问基本运算执行器\nDialogue: 0,0:33:49.76,0:33:52.36,Default,,0,0,0,,3+4等于多少？\nDialogue: 0,0:33:52.86,0:33:53.32,Default,,0,0,0,,学生：7\nDialogue: 0,0:33:53.71,0:33:54.65,Default,,0,0,0,,Abelson教授：好 是7\nDialogue: 0,0:33:55.32,0:33:55.99,Default,,0,0,0,,Sussman教授：谢谢\nDialogue: 0,0:33:59.20,0:34:00.60,Default,,0,0,0,,Abelson教授：现在 我们恢复CONTINUE\nDialogue: 0,0:34:11.58,0:34:12.90,Default,,0,0,0,,执行(GOTO (FETCH CONTINUE))\nDialogue: 0,0:34:13.07,0:34:13.47,Default,,0,0,0,,Sussman教授：'DONE\nDialogue: 0,0:34:14.20,0:34:14.67,Default,,0,0,0,,Abelson教授：好\nDialogue: 0,0:34:14.92,0:34:18.41,Default,,0,0,0,,这些是你能看到的最细致的过程了\nDialogue: 0,0:34:18.41,0:34:20.19,Default,,0,0,0,,我们再也不会讲得这么细了\nDialogue: 0,0:34:21.59,0:34:23.92,Default,,0,0,0,,有一件重要的事需要注意\nDialogue: 0,0:34:24.91,0:34:27.55,Default,,0,0,0,,我们刚刚执行了一个递归过程\nDialogue: 0,0:34:29.56,0:34:31.17,Default,,0,0,0,,我们在整个过程中使用了栈\nDialogue: 0,0:34:31.17,0:34:32.75,Default,,0,0,0,,而且求值器是递归的\nDialogue: 0,0:34:33.07,0:34:35.88,Default,,0,0,0,,有很多人以为在求值器中\nDialogue: 0,0:34:36.48,0:34:37.85,Default,,0,0,0,,会用到栈和递归\nDialogue: 0,0:34:37.87,0:34:38.97,Default,,0,0,0,,或许是因为\nDialogue: 0,0:34:39.09,0:34:42.15,Default,,0,0,0,,回去求值像阶乘或者FIB那样的递归过程\nDialogue: 0,0:34:42.15,0:34:42.92,Default,,0,0,0,,这并不正确\nDialogue: 0,0:34:43.67,0:34:44.99,Default,,0,0,0,,注意 我们在这里进行了递归\nDialogue: 0,0:34:45.00,0:34:46.86,Default,,0,0,0,,而仅仅是去求值(+ X Y)\nDialogue: 0,0:34:47.77,0:34:50.65,Default,,0,0,0,,在求值器中需要递归 实际上是因为\nDialogue: 0,0:34:50.96,0:34:52.97,Default,,0,0,0,,是因为求值过程本身\nDialogue: 0,0:34:52.99,0:34:54.06,Default,,0,0,0,,就是递归的\nDialogue: 0,0:34:54.45,0:34:56.17,Default,,0,0,0,,并不是因为你在Lisp中\nDialogue: 0,0:34:56.32,0:34:58.09,Default,,0,0,0,,要求值的那个过程\nDialogue: 0,0:34:58.12,0:34:59.27,Default,,0,0,0,,是一个递归过程\nDialogue: 0,0:34:59.27,0:35:00.52,Default,,0,0,0,,这一点很重要\nDialogue: 0,0:35:00.52,0:35:02.14,Default,,0,0,0,,人们经常在这里被弄糊涂\nDialogue: 0,0:35:03.01,0:35:04.27,Default,,0,0,0,,另一点要注意的是\nDialogue: 0,0:35:04.27,0:35:05.64,Default,,0,0,0,,我们在这里完成之后\nDialogue: 0,0:35:06.28,0:35:07.12,Default,,0,0,0,,真正完成以后\nDialogue: 0,0:35:07.12,0:35:08.49,Default,,0,0,0,,不仅仅是指我们在'DONE这个标号\nDialogue: 0,0:35:09.45,0:35:13.23,Default,,0,0,0,,栈上也没有累积的东西了\nDialogue: 0,0:35:13.60,0:35:15.71,Default,,0,0,0,,对吧？机器又回到了它的初始状态\nDialogue: 0,0:35:17.00,0:35:18.75,Default,,0,0,0,,那就是“完成”的其中一部分意义\nDialogue: 0,0:35:19.71,0:35:21.04,Default,,0,0,0,,换句话说就是\nDialogue: 0,0:35:22.72,0:35:26.04,Default,,0,0,0,,整个求值过程是把\nDialogue: 0,0:35:26.41,0:35:28.32,Default,,0,0,0,,(+ X Y)这条表达式\nDialogue: 0,0:35:30.54,0:35:32.78,Default,,0,0,0,,归约为这里的7\nDialogue: 0,0:35:33.24,0:35:35.45,Default,,0,0,0,,我所指的“归约”有特殊的意义\nDialogue: 0,0:35:36.01,0:35:38.18,Default,,0,0,0,,也就是栈上没剩下任何东西了\nDialogue: 0,0:35:38.18,0:35:40.36,Default,,0,0,0,,机器现在与初始状态相同\nDialogue: 0,0:35:40.92,0:35:42.65,Default,,0,0,0,,只是VAL寄存器里有一些东西\nDialogue: 0,0:35:42.72,0:35:44.52,Default,,0,0,0,,它不是任何问题的子问题\nDialogue: 0,0:35:44.52,0:35:45.63,Default,,0,0,0,,不需要返回到其它地方\nDialogue: 0,0:35:46.12,0:35:46.96,Default,,0,0,0,,好 这节课就讲到这里\nDialogue: 0,0:35:50.16,0:35:50.76,Default,,0,0,0,,有问题吗\nDialogue: 0,0:35:51.08,0:35:54.02,Default,,0,0,0,,学生：关于栈有一个问题\nDialogue: 0,0:35:54.02,0:35:55.82,Default,,0,0,0,,由于数据有可能是递归的\nDialogue: 0,0:35:56.20,0:35:58.75,Default,,0,0,0,,例如 嵌套的表达式\nDialogue: 0,0:35:59.31,0:36:02.08,Default,,0,0,0,,教授：是的 因为你可能遇到嵌套的表达式\nDialogue: 0,0:36:02.08,0:36:04.77,Default,,0,0,0,,但是再说一遍 不要搞混\nDialogue: 0,0:36:04.77,0:36:07.98,Default,,0,0,0,,有时候人们说数据是递归的\nDialogue: 0,0:36:08.00,0:36:10.35,Default,,0,0,0,,他们说的是对于这些表结构的\nDialogue: 0,0:36:11.04,0:36:12.93,Default,,0,0,0,,一些递归运算\nDialogue: 0,0:36:12.93,0:36:13.96,Default,,0,0,0,,那和这没有关系\nDialogue: 0,0:36:13.98,0:36:16.16,Default,,0,0,0,,这只是包含子表达式的表达式而已\nDialogue: 0,0:36:20.04,0:36:23.52,Default,,0,0,0,,学生：为什么ARGL中参数的顺序是反过来的\nDialogue: 0,0:36:23.55,0:36:25.29,Default,,0,0,0,,教授：对 我应该提一嘴这个\nDialogue: 0,0:36:27.26,0:36:29.07,Default,,0,0,0,,之所以在这里把顺序反过来\nDialogue: 0,0:36:32.78,0:36:35.37,Default,,0,0,0,,你首先定义怎么算“逆序”\nDialogue: 0,0:36:36.05,0:36:39.90,Default,,0,0,0,,我记得应该是牛顿\nDialogue: 0,0:36:40.91,0:36:42.41,Default,,0,0,0,,在光学发展的很早期\nDialogue: 0,0:36:42.43,0:36:43.26,Default,,0,0,0,,人们意识到\nDialogue: 0,0:36:43.61,0:36:45.36,Default,,0,0,0,,当你用眼睛通过透镜看东西的时候\nDialogue: 0,0:36:45.50,0:36:46.73,Default,,0,0,0,,图像是上下颠倒的\nDialogue: 0,0:36:46.73,0:36:48.04,Default,,0,0,0,,当时有很多的争论说\nDialogue: 0,0:36:48.04,0:36:50.48,Default,,0,0,0,,为什么不能是你眼睛平时看见的都是上下颠倒的\nDialogue: 0,0:36:51.28,0:36:52.65,Default,,0,0,0,,这实际上是一样的道理\nDialogue: 0,0:36:52.86,0:36:53.90,Default,,0,0,0,,和什么相比反过来了\nDialogue: 0,0:36:54.81,0:36:56.24,Default,,0,0,0,,我们只是需要一个约定\nDialogue: 0,0:36:56.59,0:37:00.35,Default,,0,0,0,,它们作为(4 3)出现的原因是\nDialogue: 0,0:37:00.80,0:37:02.49,Default,,0,0,0,,是因为我们从UNEV中取出东西\nDialogue: 0,0:37:02.52,0:37:04.03,Default,,0,0,0,,并且把它CONS到了ARGL上面\nDialogue: 0,0:37:04.52,0:37:06.68,Default,,0,0,0,,那么你要意识到你已经做了这个约定\nDialogue: 0,0:37:06.86,0:37:09.37,Default,,0,0,0,,你需要意识到这点的地方有\nDialogue: 0,0:37:09.98,0:37:11.23,Default,,0,0,0,,实际上有两个地方\nDialogue: 0,0:37:11.23,0:37:12.91,Default,,0,0,0,,首先是在APPLY-PRIMITIVE-OPERATOR\nDialogue: 0,0:37:12.91,0:37:14.06,Default,,0,0,0,,你要意识到\nDialogue: 0,0:37:15.12,0:37:16.75,Default,,0,0,0,,参数传入基本运算的顺序\nDialogue: 0,0:37:16.78,0:37:18.72,Default,,0,0,0,,是和你的书写顺序相反的\nDialogue: 0,0:37:19.49,0:37:21.00,Default,,0,0,0,,我们之后会在另外一处看到\nDialogue: 0,0:37:21.07,0:37:23.80,Default,,0,0,0,,当你实际绑定绑定函数的形式参数时\nDialogue: 0,0:37:24.01,0:37:25.74,Default,,0,0,0,,你要意识到参数进入的顺序\nDialogue: 0,0:37:25.74,0:37:28.54,Default,,0,0,0,,和你要绑定这些变量时的顺序相反\nDialogue: 0,0:37:28.87,0:37:30.17,Default,,0,0,0,,所以如果你注意这些\nDialogue: 0,0:37:31.08,0:37:31.83,Default,,0,0,0,,就没有问题了\nDialogue: 0,0:37:31.83,0:37:33.69,Default,,0,0,0,,同样 这完全是随意的\nDialogue: 0,0:37:33.90,0:37:34.96,Default,,0,0,0,,因为如果我们做了一个\nDialogue: 0,0:37:35.10,0:37:37.15,Default,,0,0,0,,比如 给向量的各个维度赋值的迭代\nDialogue: 0,0:37:37.42,0:37:38.73,Default,,0,0,0,,它们可能会以其它顺序输出\nDialogue: 0,0:37:40.41,0:37:42.04,Default,,0,0,0,,那么这只是这个求值器\nDialogue: 0,0:37:42.06,0:37:43.53,Default,,0,0,0,,工作时的一个约定\nDialogue: 0,0:37:45.39,0:37:46.24,Default,,0,0,0,,好 我们休息一下\nDialogue: 0,0:37:46.33,0:38:02.44,Default,,0,0,0,,[音乐]\nDialogue: 0,0:38:02.44,0:38:07.64,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:38:28.62,0:38:32.51,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:38:32.51,0:38:35.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:38:35.68,0:38:39.61,Declare,,0,0,0,,{\\an2\\fad(500,500)}显式控制求值器\nDialogue: 0,0:38:41.84,0:38:45.31,Default,,0,0,0,,教授：我们已经学习了表达式的求值\nDialogue: 0,0:38:45.60,0:38:47.08,Default,,0,0,0,,虽然这只是一个非常简单的例子\nDialogue: 0,0:38:48.81,0:38:50.24,Default,,0,0,0,,但从本质上来说\nDialogue: 0,0:38:50.24,0:38:52.03,Default,,0,0,0,,它跟那些大型嵌套表达式没什么不同\nDialogue: 0,0:38:52.03,0:38:54.57,Default,,0,0,0,,后者只是在栈上递归得更深而已\nDialogue: 0,0:38:55.13,0:38:56.03,Default,,0,0,0,,我现在要为你们\nDialogue: 0,0:38:56.04,0:38:56.91,Default,,0,0,0,,讲解最后一部分\nDialogue: 0,0:38:56.92,0:38:59.82,Default,,0,0,0,,我要带着你们观察EVAL-APPLY循环\nDialogue: 0,0:39:01.01,0:39:02.81,Default,,0,0,0,,我们还没有仔细研究过它\nDialogue: 0,0:39:03.00,0:39:04.75,Default,,0,0,0,,我们还没有见过一个复合程序\nDialogue: 0,0:39:05.20,0:39:07.79,Default,,0,0,0,,对它的求值会归约为\nDialogue: 0,0:39:07.92,0:39:10.11,Default,,0,0,0,,对一个过程的应用\nDialogue: 0,0:39:10.12,0:39:11.64,Default,,0,0,0,,进而是对过程体的求值\nDialogue: 0,0:39:12.44,0:39:15.88,Default,,0,0,0,,因此 假设我们有这个\nDialogue: 0,0:39:15.93,0:39:17.44,Default,,0,0,0,,假设我们正在考察\nDialogue: 0,0:39:18.07,0:39:31.60,Default,,0,0,0,,(DEFINE (F A B) (+ A B)\nDialogue: 0,0:39:33.99,0:39:37.32,Default,,0,0,0,,假设我们预先定义好了这个过程\nDialogue: 0,0:39:37.69,0:39:41.64,Default,,0,0,0,,现在 我们将要求值(F X Y)\nDialogue: 0,0:39:42.27,0:39:44.20,Default,,0,0,0,,基于的环境是E0\nDialogue: 0,0:39:44.35,0:39:47.02,Default,,0,0,0,,其中X=3 Y=4\nDialogue: 0,0:39:50.78,0:39:52.11,Default,,0,0,0,,当执行DEFINE的时候\nDialogue: 0,0:39:52.12,0:39:53.69,Default,,0,0,0,,还记得么 这里是一个LAMBDA\nDialogue: 0,0:39:53.82,0:39:55.53,Default,,0,0,0,,LAMBDA会创建一个过程\nDialogue: 0,0:39:55.95,0:39:58.49,Default,,0,0,0,,基本上 会发生的事情是\nDialogue: 0,0:39:59.63,0:40:00.68,Default,,0,0,0,,在环境E0中\nDialogue: 0,0:40:01.00,0:40:02.65,Default,,0,0,0,,我们会得到F的绑定\nDialogue: 0,0:40:03.56,0:40:05.61,Default,,0,0,0,,它指出F是一个过程\nDialogue: 0,0:40:07.15,0:40:11.28,Default,,0,0,0,,这个过程的参数是A和B\nDialogue: 0,0:40:12.57,0:40:16.19,Default,,0,0,0,,而过程体是(+ A B)\nDialogue: 0,0:40:18.11,0:40:20.99,Default,,0,0,0,,这就是环境大概的样子\nDialogue: 0,0:40:21.21,0:40:22.52,Default,,0,0,0,,我们之前就定义过了\nDialogue: 0,0:40:24.22,0:40:27.28,Default,,0,0,0,,然后 我们去求值(F X Y)\nDialogue: 0,0:40:28.80,0:40:30.89,Default,,0,0,0,,我们会仔细地解释每一步\nDialogue: 0,0:40:31.02,0:40:31.85,Default,,0,0,0,,就像之前那样\nDialogue: 0,0:40:31.88,0:40:33.09,Default,,0,0,0,,不会跳过重复的表达式\nDialogue: 0,0:40:33.28,0:40:34.38,Default,,0,0,0,,唯一的不同是\nDialogue: 0,0:40:34.40,0:40:36.64,Default,,0,0,0,,它的内部不再是基本的“+”过程\nDialogue: 0,0:40:37.24,0:40:38.99,Default,,0,0,0,,它还有这个东西\nDialogue: 0,0:40:41.04,0:40:43.60,Default,,0,0,0,,因此我们要进行相同的过程\nDialogue: 0,0:40:43.60,0:40:44.92,Default,,0,0,0,,只不过这次\nDialogue: 0,0:40:45.26,0:40:47.42,Default,,0,0,0,,当我们停在APPLY-DISPATCH时\nDialogue: 0,0:40:47.86,0:40:50.28,Default,,0,0,0,,FUN寄存器中不再是基本的“+”过程\nDialogue: 0,0:40:50.44,0:40:53.58,Default,,0,0,0,,而是一个代表过程的东西\nDialogue: 0,0:40:54.30,0:40:59.00,Default,,0,0,0,,其中参数为A和B\nDialogue: 0,0:41:00.64,0:41:06.27,Default,,0,0,0,,过程体是(+ A B)\nDialogue: 0,0:41:07.87,0:41:09.92,Default,,0,0,0,,再强调一下 我所谓的ENV\nDialogue: 0,0:41:09.96,0:41:11.12,Default,,0,0,0,,是一个指向环境的指针\nDialogue: 0,0:41:11.24,0:41:13.07,Default,,0,0,0,,所以不用担心我在这里写了很多东西\nDialogue: 0,0:41:13.28,0:41:15.63,Default,,0,0,0,,这是一个指向代表过程的数据结构的指针\nDialogue: 0,0:41:17.17,0:41:19.77,Default,,0,0,0,,因此 我们现在面临着相同的情况\nDialogue: 0,0:41:20.27,0:41:22.43,Default,,0,0,0,,我们来到了APPLY-DISPATCH\nDialogue: 0,0:41:23.98,0:41:26.48,Default,,0,0,0,,这是APPLY-DISPATCH的代码\nDialogue: 0,0:41:26.48,0:41:28.73,Default,,0,0,0,,上一次 我们分支跳转到了一个基本过程\nDialogue: 0,0:41:30.01,0:41:30.70,Default,,0,0,0,,然而这一次\nDialogue: 0,0:41:30.84,0:41:32.80,Default,,0,0,0,,我们遇到的是一个复合过程\nDialogue: 0,0:41:34.55,0:41:36.60,Default,,0,0,0,,因此我们要跳转到COMPOUND-APPLY\nDialogue: 0,0:41:38.47,0:41:39.92,Default,,0,0,0,,COMPOUND-APPLY又是怎样定义的呢？\nDialogue: 0,0:41:41.92,0:41:44.54,Default,,0,0,0,,还记得元循环求值器是怎么做的么？\nDialogue: 0,0:41:45.09,0:41:47.40,Default,,0,0,0,,COMPOUND-APPLY的执行步骤则是\nDialogue: 0,0:41:49.90,0:41:51.60,Default,,0,0,0,,在一个新的环境中\nDialogue: 0,0:41:52.94,0:41:54.12,Default,,0,0,0,,求值一个过程的体\nDialogue: 0,0:41:54.12,0:41:55.87,Default,,0,0,0,,这个新的环境来自于哪里呢？\nDialogue: 0,0:41:56.73,0:42:01.36,Default,,0,0,0,,我们把跟过程一同打包的环境\nDialogue: 0,0:42:03.02,0:42:05.79,Default,,0,0,0,,我们把过程的形式参数\nDialogue: 0,0:42:06.00,0:42:07.63,Default,,0,0,0,,同传递进来的实际参数给绑定起来\nDialogue: 0,0:42:09.75,0:42:11.95,Default,,0,0,0,,把这个作为新的框架\nDialogue: 0,0:42:12.59,0:42:13.79,Default,,0,0,0,,来扩展过程附带的环境\nDialogue: 0,0:42:14.99,0:42:16.08,Default,,0,0,0,,我们就是在这个环境中\nDialogue: 0,0:42:16.30,0:42:18.88,Default,,0,0,0,,求值过程的体\nDialogue: 0,0:42:20.12,0:42:24.47,Default,,0,0,0,,对吧？这就是APPLY-EVAL循环做的事\nDialogue: 0,0:42:24.47,0:42:26.25,Default,,0,0,0,,这就是APPLY回过头来调用EVAL\nDialogue: 0,0:42:32.86,0:42:34.92,Default,,0,0,0,,因此 这就是我们要在COMPOUND-APPLY中要做的所有事\nDialogue: 0,0:42:36.78,0:42:37.72,Default,,0,0,0,,要怎么来实现呢？\nDialogue: 0,0:42:37.72,0:42:40.97,Default,,0,0,0,,我们要构造一个新的环境\nDialogue: 0,0:42:43.55,0:42:45.64,Default,,0,0,0,,而我们构造的这个新环境呢\nDialogue: 0,0:42:46.76,0:42:48.11,Default,,0,0,0,,我们把它记作E1\nDialogue: 0,0:42:52.90,0:42:55.63,Default,,0,0,0,,E1这个环境呢\nDialogue: 0,0:42:57.31,0:42:59.15,Default,,0,0,0,,存储了过程的参数绑定\nDialogue: 0,0:42:59.21,0:43:03.26,Default,,0,0,0,,其中A=3 B=4\nDialogue: 0,0:43:04.27,0:43:05.76,Default,,0,0,0,,并且它跟E0相连\nDialogue: 0,0:43:05.76,0:43:08.08,Default,,0,0,0,,这是因为 F就是在E0中定义的\nDialogue: 0,0:43:09.27,0:43:10.27,Default,,0,0,0,,因此 在这个环境中\nDialogue: 0,0:43:10.27,0:43:11.96,Default,,0,0,0,,我们要来求值过程的体\nDialogue: 0,0:43:12.05,0:43:14.48,Default,,0,0,0,,让我们来看一看\nDialogue: 0,0:43:16.52,0:43:18.32,Default,,0,0,0,,我们来看COMPOUND-APPLY的代码\nDialogue: 0,0:43:20.30,0:43:23.47,Default,,0,0,0,,首先是给EXP寄存器赋值\nDialogue: 0,0:43:24.50,0:43:25.98,Default,,0,0,0,,所赋的值是FUN寄存器\nDialogue: 0,0:43:25.98,0:43:27.26,Default,,0,0,0,,所指向过程的体\nDialogue: 0,0:43:28.38,0:43:30.64,Default,,0,0,0,,这样 我就将过程的体\nDialogue: 0,0:43:31.29,0:43:32.33,Default,,0,0,0,,赋值给了EXP寄存器\nDialogue: 0,0:43:40.75,0:43:41.10,Default,,0,0,0,,对吧？\nDialogue: 0,0:43:42.64,0:43:44.97,Default,,0,0,0,,而这将在某个环境中求值\nDialogue: 0,0:43:45.82,0:43:48.32,Default,,0,0,0,,这个环境是通过将FUN寄存器\nDialogue: 0,0:43:51.30,0:43:53.67,Default,,0,0,0,,所指向的过程中的形式参数\nDialogue: 0,0:43:53.67,0:43:56.25,Default,,0,0,0,,与实际参数绑定起来 得到的\nDialogue: 0,0:43:57.80,0:44:00.00,Default,,0,0,0,,我们先不要关系它的具体细节\nDialogue: 0,0:44:00.08,0:44:01.63,Default,,0,0,0,,你可以知道它的最后结果\nDialogue: 0,0:44:01.93,0:44:03.32,Default,,0,0,0,,因此MAKE-BINDINGS会说\nDialogue: 0,0:44:04.04,0:44:07.90,Default,,0,0,0,,过程本身就附带有一个环境\nDialogue: 0,0:44:07.96,0:44:09.32,Default,,0,0,0,,在这里 我没有写出来\nDialogue: 0,0:44:09.36,0:44:10.56,Default,,0,0,0,,但我应该说过它有一个环境\nDialogue: 0,0:44:11.30,0:44:12.73,Default,,0,0,0,,因为每个过程在构造时\nDialogue: 0,0:44:12.76,0:44:13.44,Default,,0,0,0,,都有一个环境\nDialogue: 0,0:44:13.66,0:44:14.83,Default,,0,0,0,,因此 通过这个环境\nDialogue: 0,0:44:15.68,0:44:16.35,Default,,0,0,0,,它能够知道\nDialogue: 0,0:44:16.60,0:44:18.65,Default,,0,0,0,,定义该过程时的环境是怎样的\nDialogue: 0,0:44:19.29,0:44:20.75,Default,,0,0,0,,它知道实际参数是什么\nDialogue: 0,0:44:21.83,0:44:22.49,Default,,0,0,0,,它查看ARGL\nDialogue: 0,0:44:22.49,0:44:24.28,Default,,0,0,0,,然后你会在这里看到逆序的约定\nDialogue: 0,0:44:24.28,0:44:26.62,Default,,0,0,0,,它需要知道ARGL是逆序的\nDialogue: 0,0:44:27.06,0:44:28.81,Default,,0,0,0,,然后它构造了这个框架 E1\nDialogue: 0,0:44:29.99,0:44:31.08,Default,,0,0,0,,因此我们假设\nDialogue: 0,0:44:31.10,0:44:32.92,Default,,0,0,0,,MAKE-BINDINGS返回的就是这些东西\nDialogue: 0,0:44:33.36,0:44:36.22,Default,,0,0,0,,然后 它把E1赋值给ENV\nDialogue: 0,0:44:41.34,0:44:42.54,Default,,0,0,0,,下一步就是\nDialogue: 0,0:44:43.95,0:44:45.84,Default,,0,0,0,,恢复CONTINUE\nDialogue: 0,0:44:46.89,0:44:48.19,Default,,0,0,0,,还记得CONTINUE之前是什么吗？\nDialogue: 0,0:44:48.76,0:44:50.43,Default,,0,0,0,,在最后一段中\nDialogue: 0,0:44:52.24,0:44:54.02,Default,,0,0,0,,CONTINUE被保存了\nDialogue: 0,0:44:54.02,0:44:55.18,Default,,0,0,0,,它的值是最初的'DONE\nDialogue: 0,0:44:55.32,0:44:56.56,Default,,0,0,0,,这代表了\nDialogue: 0,0:44:56.73,0:44:59.44,Default,,0,0,0,,在完成这项特定应用后要做的事\nDialogue: 0,0:45:00.14,0:45:01.72,Default,,0,0,0,,这是在求值整个应用时\nDialogue: 0,0:45:01.76,0:45:03.18,Default,,0,0,0,,最先发生的事儿\nDialogue: 0,0:45:03.88,0:45:05.87,Default,,0,0,0,,现在 我们要恢复CONTINUE了\nDialogue: 0,0:45:06.86,0:45:09.55,Default,,0,0,0,,还记得APPLY-DISPATCH的约定么？\nDialogue: 0,0:45:09.58,0:45:11.20,Default,,0,0,0,,它假设下一步的跳转目标\nDialogue: 0,0:45:11.23,0:45:11.98,Default,,0,0,0,,已经存放在栈上了\nDialogue: 0,0:45:12.03,0:45:13.12,Default,,0,0,0,,并且 这里确实存放在栈上了\nDialogue: 0,0:45:13.59,0:45:14.76,Default,,0,0,0,,CONTINUE被赋值成了DONE\nDialogue: 0,0:45:17.82,0:45:19.90,Default,,0,0,0,,现在我们要回到EVAL-DISPATCH了\nDialogue: 0,0:45:19.94,0:45:20.84,Default,,0,0,0,,我们要再次进行寄存器设置\nDialogue: 0,0:45:20.97,0:45:24.41,Default,,0,0,0,,我们有表达式、环境、下一步\nDialogue: 0,0:45:25.80,0:45:26.89,Default,,0,0,0,,我不会再细讲了\nDialogue: 0,0:45:27.88,0:45:29.55,Default,,0,0,0,,因为它基本上就是相同的表达式\nDialogue: 0,0:45:35.40,0:45:37.79,Default,,0,0,0,,但是需要注意的是\nDialogue: 0,0:45:37.82,0:45:38.73,Default,,0,0,0,,在这个时候\nDialogue: 0,0:45:39.34,0:45:43.72,Default,,0,0,0,,我们已经归约了原始表达式(F X Y)\nDialogue: 0,0:45:44.64,0:45:47.92,Default,,0,0,0,,通过在E0中求值(F X Y)\nDialogue: 0,0:45:48.89,0:45:52.67,Default,,0,0,0,,将其归约为在E1中求值(+ A B)\nDialogue: 0,0:45:52.78,0:45:55.92,Default,,0,0,0,,要注意 栈上并没有什么东西 对吧？\nDialogue: 0,0:45:56.11,0:45:56.83,Default,,0,0,0,,这是一个归约\nDialogue: 0,0:45:56.84,0:45:59.80,Default,,0,0,0,,这个时候 机器的状态中\nDialogue: 0,0:45:59.84,0:46:01.20,Default,,0,0,0,,并没有包含\nDialogue: 0,0:46:01.76,0:46:03.71,Default,,0,0,0,,它是求值过程F的\nDialogue: 0,0:46:03.72,0:46:04.88,Default,,0,0,0,,中间状态的事实\nDialogue: 0,0:46:05.49,0:46:06.28,Default,,0,0,0,,它消失了\nDialogue: 0,0:46:07.66,0:46:09.55,Default,,0,0,0,,这里面没有积累的状态\nDialogue: 0,0:46:13.07,0:46:14.37,Default,,0,0,0,,注意 这个思想非常重要\nDialogue: 0,0:46:14.37,0:46:16.33,Default,,0,0,0,,这意味着\nDialogue: 0,0:46:16.76,0:46:18.39,Default,,0,0,0,,当我们使用代换模型时\nDialogue: 0,0:46:18.39,0:46:20.86,Default,,0,0,0,,一条表达式会归约到另一条表达式\nDialogue: 0,0:46:21.35,0:46:22.66,Default,,0,0,0,,而你不需要记住任何东西\nDialogue: 0,0:46:22.66,0:46:24.50,Default,,0,0,0,,这里 你就见到了归约的真谛\nDialogue: 0,0:46:24.56,0:46:26.16,Default,,0,0,0,,这个时候 栈上没有任何东西\nDialogue: 0,0:46:31.59,0:46:33.63,Default,,0,0,0,,这样就有一个非常重要的结果\nDialogue: 0,0:46:35.24,0:46:37.90,Default,,0,0,0,,让我们回过头来看看迭代式阶乘\nDialogue: 0,0:46:40.42,0:46:42.76,Default,,0,0,0,,还记得吗？这是某种循环\nDialogue: 0,0:46:44.01,0:46:44.88,Default,,0,0,0,,用来进行迭代\nDialogue: 0,0:46:45.13,0:46:47.36,Default,,0,0,0,,我们不断强调 它是一个迭代过程\nDialogue: 0,0:46:49.26,0:46:53.84,Default,,0,0,0,,还记得吗\nDialogue: 0,0:46:58.44,0:47:03.13,Default,,0,0,0,,我们使用它的时候\nDialogue: 0,0:47:04.35,0:47:11.07,Default,,0,0,0,,是像(FACT-ITER 5)这样调用它的\nDialogue: 0,0:47:12.36,0:47:18.67,Default,,0,0,0,,然后我们把它归约成(ITER 1 1 5)\nDialogue: 0,0:47:19.03,0:47:25.15,Default,,0,0,0,,然后它归约成(ITER 1 2 5)\nDialogue: 0,0:47:25.32,0:47:27.07,Default,,0,0,0,,等等等等\nDialogue: 0,0:47:27.07,0:47:28.17,Default,,0,0,0,,然后我们又说 看\nDialogue: 0,0:47:28.17,0:47:30.35,Default,,0,0,0,,为了实现这个效果 不需要存储任何东西\nDialogue: 0,0:47:31.72,0:47:32.73,Default,,0,0,0,,我们摆了摆手 说\nDialogue: 0,0:47:32.75,0:47:34.59,Default,,0,0,0,,“原则上 这不需要任何存储”\nDialogue: 0,0:47:35.04,0:47:36.17,Default,,0,0,0,,现在你们发现 确实不需要\nDialogue: 0,0:47:36.17,0:47:39.09,Default,,0,0,0,,这里的每一步都是真正的归约 对吧？\nDialogue: 0,0:47:39.09,0:47:42.60,Default,,0,0,0,,随着你求值这些表达式\nDialogue: 0,0:47:47.30,0:47:50.51,Default,,0,0,0,,在求值这些表达式的过程中\nDialogue: 0,0:47:50.83,0:47:51.37,Default,,0,0,0,,你会发现\nDialogue: 0,0:47:51.37,0:47:52.81,Default,,0,0,0,,栈上的这些表达式\nDialogue: 0,0:47:53.75,0:47:55.64,Default,,0,0,0,,都在一个特定的环境中\nDialogue: 0,0:47:56.42,0:48:00.02,Default,,0,0,0,,抱歉 是EXP寄存器中的表达式\nDialogue: 0,0:48:00.02,0:48:01.50,Default,,0,0,0,,是在某个特定的环境中\nDialogue: 0,0:48:01.57,0:48:02.19,Default,,0,0,0,,并且 在每一步\nDialogue: 0,0:48:02.19,0:48:04.00,Default,,0,0,0,,栈上不会积累任何东西\nDialogue: 0,0:48:04.36,0:48:05.68,Default,,0,0,0,,因为每一步都是真正的归约\nDialogue: 0,0:48:09.28,0:48:10.51,Default,,0,0,0,,因此 举例来说\nDialogue: 0,0:48:10.58,0:48:12.51,Default,,0,0,0,,说得更仔细一点\nDialogue: 0,0:48:13.46,0:48:16.88,Default,,0,0,0,,如果我从这样的一条表达式开始\nDialogue: 0,0:48:22.44,0:48:34.25,Default,,0,0,0,,比如说 在某个环境中计算(FACT-ITER 5)\nDialogue: 0,0:48:42.11,0:48:46.30,Default,,0,0,0,,它将在某个时刻创建一个环境\nDialogue: 0,0:48:46.81,0:48:48.38,Default,,0,0,0,,其中N=5\nDialogue: 0,0:48:51.47,0:48:52.01,Default,,0,0,0,,我们把它写下来\nDialogue: 0,0:48:55.68,0:48:56.59,Default,,0,0,0,,然后 在某个时候\nDialogue: 0,0:48:56.89,0:49:02.56,Default,,0,0,0,,机器会归约这整个东西\nDialogue: 0,0:49:02.91,0:49:04.35,Default,,0,0,0,,将它归约为\nDialogue: 0,0:49:04.76,0:49:09.85,Default,,0,0,0,,(ITER 1 1 N)\nDialogue: 0,0:49:10.68,0:49:13.72,Default,,0,0,0,,然后在环境E1中求值这条表达式\nDialogue: 0,0:49:15.87,0:49:17.16,Default,,0,0,0,,而不在栈上存放任何东西\nDialogue: 0,0:49:17.16,0:49:19.55,Default,,0,0,0,,看到了么 这时机器并不会记住\nDialogue: 0,0:49:20.71,0:49:22.50,Default,,0,0,0,,求值这条ITER表达式--\nDialogue: 0,0:49:25.00,0:49:25.63,Default,,0,0,0,,也就是某种循环--\nDialogue: 0,0:49:25.79,0:49:28.57,Default,,0,0,0,,并不是FACT-ITER的一部分\nDialogue: 0,0:49:29.68,0:49:30.59,Default,,0,0,0,,它不会记住这个事实\nDialogue: 0,0:49:30.59,0:49:33.17,Default,,0,0,0,,它只是归约了该表达式\nDialogue: 0,0:49:33.17,0:49:36.56,Default,,0,0,0,,如果我们再来看迭代式阶乘的体\nDialogue: 0,0:49:38.05,0:49:41.08,Default,,0,0,0,,这条表达式归约为了这条表达式\nDialogue: 0,0:49:42.81,0:49:43.87,Default,,0,0,0,,哦 这里漏了一个N\nDialogue: 0,0:49:46.59,0:49:47.74,Default,,0,0,0,,幻灯片中的约定\nDialogue: 0,0:49:47.74,0:49:49.13,Default,,0,0,0,,和实际程序中稍有不同\nDialogue: 0,0:49:53.34,0:49:56.25,Default,,0,0,0,,那么 ITER的体又是什么？\nDialogue: 0,0:49:56.28,0:49:57.40,Default,,0,0,0,,ITER的体首先是一个IF--\nDialogue: 0,0:49:58.75,0:50:00.19,Default,,0,0,0,,我不会再深入IF语句的细节了\nDialogue: 0,0:50:00.24,0:50:01.63,Default,,0,0,0,,它会对谓词求值\nDialogue: 0,0:50:02.40,0:50:03.71,Default,,0,0,0,,本例中 会返回FALSE\nDialogue: 0,0:50:03.81,0:50:08.64,Default,,0,0,0,,然后这里的ITER会归约为表达式--\nDialogue: 0,0:50:09.85,0:50:20.20,Default,,0,0,0,,(ITER (* COUNTER PRODUCT)\nDialogue: 0,0:50:21.62,0:50:22.24,Default,,0,0,0,,按照它代码写的--\nDialogue: 0,0:50:22.68,0:50:24.56,Default,,0,0,0,,(+ COUNTER 1))\nDialogue: 0,0:50:28.72,0:50:31.42,Default,,0,0,0,,在另外的一个环境E2中求值\nDialogue: 0,0:50:32.97,0:50:35.98,Default,,0,0,0,,其中 E2会记录着\nDialogue: 0,0:50:36.49,0:50:39.39,Default,,0,0,0,,PRODUCT和COUNTER的值\nDialogue: 0,0:50:42.92,0:50:44.33,Default,,0,0,0,,它会被归约为这条语句\nDialogue: 0,0:50:44.94,0:50:46.04,Default,,0,0,0,,它不会记得\nDialogue: 0,0:50:46.06,0:50:48.75,Default,,0,0,0,,它是一个需要返回到某处的一部分\nDialogue: 0,0:50:49.34,0:50:50.43,Default,,0,0,0,,当ITER再次调用ITER时\nDialogue: 0,0:50:50.44,0:50:52.56,Default,,0,0,0,,它会归约为另一个像这样的东西\nDialogue: 0,0:50:53.05,0:50:54.68,Default,,0,0,0,,只是会在新环境E3中\nDialogue: 0,0:50:54.83,0:50:56.67,Default,,0,0,0,,里面有关于PRODUCT和COUNTER新的绑定\nDialogue: 0,0:50:58.80,0:51:05.29,Default,,0,0,0,,因此 如果你想知道\nDialogue: 0,0:51:06.09,0:51:07.53,Default,,0,0,0,,如果你一直感到不安\nDialogue: 0,0:51:08.25,0:51:10.67,Default,,0,0,0,,不知道为什么我们说这些过程\nDialogue: 0,0:51:10.67,0:51:12.45,Default,,0,0,0,,虽然从语法上看起来是递归的\nDialogue: 0,0:51:13.20,0:51:15.69,Default,,0,0,0,,但实际上是迭代的\nDialogue: 0,0:51:15.87,0:51:17.24,Default,,0,0,0,,可以在常量空间中运行\nDialogue: 0,0:51:18.40,0:51:19.75,Default,,0,0,0,,我不知道这么说是否打消了你们的疑虑\nDialogue: 0,0:51:19.75,0:51:21.23,Default,,0,0,0,,但至少让你们知道发生了什么\nDialogue: 0,0:51:21.23,0:51:22.81,Default,,0,0,0,,这其中没有任何构造\nDialogue: 0,0:51:25.91,0:51:27.58,Default,,0,0,0,,但你也会说 这里面还是有一些构造\nDialogue: 0,0:51:27.98,0:51:30.08,Default,,0,0,0,,从原则上来说 我们也构造了环境框架\nDialogue: 0,0:51:31.71,0:51:32.37,Default,,0,0,0,,答案则是\nDialogue: 0,0:51:32.40,0:51:33.84,Default,,0,0,0,,你确实需要构建这些环境框架\nDialogue: 0,0:51:33.84,0:51:35.26,Default,,0,0,0,,但是 等你求值完毕后\nDialogue: 0,0:51:35.42,0:51:36.19,Default,,0,0,0,,不必保留它们\nDialogue: 0,0:51:36.44,0:51:37.61,Default,,0,0,0,,它们可以被废料收集\nDialogue: 0,0:51:37.92,0:51:39.47,Default,,0,0,0,,这些空间也可以被自动地重用\nDialogue: 0,0:51:40.72,0:51:42.99,Default,,0,0,0,,但你们可以看到求值器控制流\nDialogue: 0,0:51:43.25,0:51:46.12,Default,,0,0,0,,的中心思想就是进行归约\nDialogue: 0,0:51:47.02,0:51:49.29,Default,,0,0,0,,因此这些过程实际上是迭代过程\nDialogue: 0,0:51:50.13,0:51:51.38,Default,,0,0,0,,好吧 有什么问题么？\nDialogue: 0,0:52:02.68,0:52:03.23,Default,,0,0,0,,好吧 课件休息吧\nDialogue: 0,0:52:04.12,0:52:24.56,Default,,0,0,0,,[音乐]\nDialogue: 0,0:52:24.60,0:52:29.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:52:35.20,0:52:38.36,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:52:38.36,0:52:42.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:52:42.14,0:52:46.44,Declare,,0,0,0,,{\\an2\\fad(500,500)}显示控制求值器\nDialogue: 0,0:52:48.77,0:52:51.55,Default,,0,0,0,,教授：跟迭代过程形成对比的是\nDialogue: 0,0:52:52.77,0:52:54.89,Default,,0,0,0,,确实会占用空间的\nDialogue: 0,0:52:55.12,0:52:56.14,Default,,0,0,0,,递归过程\nDialogue: 0,0:52:56.17,0:52:57.29,Default,,0,0,0,,你们可以看到其中的区别\nDialogue: 0,0:52:58.03,0:53:01.20,Default,,0,0,0,,让我们来看看递归式阶乘的求值\nDialogue: 0,0:53:02.65,0:53:05.53,Default,,0,0,0,,这里的FACT-REC\nDialogue: 0,0:53:05.55,0:53:07.22,Default,,0,0,0,,就是阶乘的标准定义\nDialogue: 0,0:53:07.22,0:53:10.01,Default,,0,0,0,,这个当然是一个递归过程\nDialogue: 0,0:53:10.01,0:53:12.57,Default,,0,0,0,,它的计算过程也是递归的\nDialogue: 0,0:53:13.75,0:53:16.56,Default,,0,0,0,,然后 只要把它和我们开始的方式联系起来\nDialogue: 0,0:53:16.83,0:53:20.53,Default,,0,0,0,,我们会通过代换模型发现\nDialogue: 0,0:53:20.53,0:53:21.82,Default,,0,0,0,,这是一个递归过程\nDialogue: 0,0:53:22.36,0:53:28.00,Default,,0,0,0,,因为 如果我调用(REC-FACT 5)\nDialogue: 0,0:53:30.45,0:53:34.94,Default,,0,0,0,,会变成(* 5\nDialogue: 0,0:53:36.28,0:53:37.82,Default,,0,0,0,,哦 这里是FACT-REC\nDialogue: 0,0:53:42.62,0:53:47.93,Default,,0,0,0,,(* 5 (FACT-REC 4))\nDialogue: 0,0:53:49.66,0:53:58.22,Default,,0,0,0,,又会变成(* 5 (* 4 (FACT-REC 3)))\nDialogue: 0,0:54:00.22,0:54:08.60,Default,,0,0,0,,又会变成(* 5 (* 4 (* 3 (* ...\nDialogue: 0,0:54:13.45,0:54:15.31,Default,,0,0,0,,以此类推\nDialogue: 0,0:54:15.39,0:54:17.39,Default,,0,0,0,,关键点就是 有一条链条被不断构造出来\nDialogue: 0,0:54:18.10,0:54:20.06,Default,,0,0,0,,这就在代换模型中证明了\nDialogue: 0,0:54:20.08,0:54:21.28,Default,,0,0,0,,FACT-REC是递归的\nDialogue: 0,0:54:21.52,0:54:24.18,Default,,0,0,0,,现在 让我们来看看这条构造起来的链条\nDialogue: 0,0:54:24.18,0:54:25.29,Default,,0,0,0,,它又是在机器中的什么地方？\nDialogue: 0,0:54:27.68,0:54:29.95,Default,,0,0,0,,好吧 让我们想象一下要从哪里开始\nDialogue: 0,0:54:30.44,0:54:40.01,Default,,0,0,0,,我们告诉机器 求值(FACT-REC 5)\nDialogue: 0,0:54:41.45,0:54:43.39,Default,,0,0,0,,基于的环境是E0\nDialogue: 0,0:54:45.08,0:54:48.97,Default,,0,0,0,,也就是定义FACT-REC时的环境\nDialogue: 0,0:54:49.55,0:54:51.23,Default,,0,0,0,,现在 我们知道最终要发生什么\nDialogue: 0,0:54:52.25,0:54:53.64,Default,,0,0,0,,首先\nDialogue: 0,0:54:53.92,0:54:55.64,Default,,0,0,0,,它会对这些东西求值\nDialogue: 0,0:54:55.68,0:54:56.99,Default,,0,0,0,,发现它是一个过程\nDialogue: 0,0:54:57.18,0:55:00.16,Default,,0,0,0,,在这里创建一个新环境E1\nDialogue: 0,0:55:00.88,0:55:03.69,Default,,0,0,0,,其中N=5\nDialogue: 0,0:55:04.33,0:55:06.54,Default,,0,0,0,,并且与E0相连\nDialogue: 0,0:55:07.80,0:55:08.97,Default,,0,0,0,,这个E0也就是\nDialogue: 0,0:55:08.99,0:55:12.30,Default,,0,0,0,,定义FACT-REC的那个环境\nDialogue: 0,0:55:14.11,0:55:15.74,Default,,0,0,0,,然后 在E1这个环境中\nDialogue: 0,0:55:15.76,0:55:17.48,Default,,0,0,0,,求值过程的体\nDialogue: 0,0:55:19.67,0:55:25.92,Default,,0,0,0,,因此 在这里求值会归约为\nDialogue: 0,0:55:27.00,0:55:28.92,Default,,0,0,0,,在E1中求值过程的体\nDialogue: 0,0:55:30.16,0:55:31.34,Default,,0,0,0,,这就需要求值IF语句\nDialogue: 0,0:55:32.17,0:55:33.53,Default,,0,0,0,,而我不会讲解IF语句的细节\nDialogue: 0,0:55:33.53,0:55:34.88,Default,,0,0,0,,IF语句会求值谓词\nDialogue: 0,0:55:34.88,0:55:37.53,Default,,0,0,0,,最后发现需要求值ELSE子句\nDialogue: 0,0:55:37.84,0:55:40.41,Default,,0,0,0,,因此 这里的整个部分 会归约为\nDialogue: 0,0:55:41.30,0:55:45.53,Default,,0,0,0,,FACT-REC的ELSE子句\nDialogue: 0,0:55:45.82,0:55:46.97,Default,,0,0,0,,也就是谓词为假的部分\nDialogue: 0,0:55:47.23,0:55:51.16,Default,,0,0,0,,整个表达式就归约为了(* N\nDialogue: 0,0:55:53.07,0:55:59.96,Default,,0,0,0,,(FACT-REC (- N 1))\nDialogue: 0,0:56:03.48,0:56:05.55,Default,,0,0,0,,求值的环境是E1\nDialogue: 0,0:56:08.38,0:56:10.91,Default,,0,0,0,,因此 最初的表达式现在就会归约为\nDialogue: 0,0:56:11.04,0:56:12.52,Default,,0,0,0,,求值这样的一个表达式\nDialogue: 0,0:56:13.75,0:56:16.28,Default,,0,0,0,,而现在 我们面对的是一个应用\nDialogue: 0,0:56:16.28,0:56:17.63,Default,,0,0,0,,我们之前求值过应用\nDialogue: 0,0:56:18.22,0:56:20.25,Default,,0,0,0,,还记得要怎么求值应用么？\nDialogue: 0,0:56:20.36,0:56:21.69,Default,,0,0,0,,正式求值一个应用之前\nDialogue: 0,0:56:21.74,0:56:24.81,Default,,0,0,0,,你需要把CONTINUE寄存器的值保存在栈上\nDialogue: 0,0:56:25.35,0:56:27.18,Default,,0,0,0,,此时 栈上会有一个值'DONE\nDialogue: 0,0:56:29.98,0:56:32.88,Default,,0,0,0,,接下来 你要为求值子部分做准备\nDialogue: 0,0:56:35.00,0:56:37.20,Default,,0,0,0,,因此 我们在这里开始求值子部分\nDialogue: 0,0:56:39.47,0:56:41.45,Default,,0,0,0,,首先要做的是求值运算符\nDialogue: 0,0:56:44.60,0:56:46.32,Default,,0,0,0,,运算符是怎样求值的呢？\nDialogue: 0,0:56:47.25,0:56:48.99,Default,,0,0,0,,我们通过一些手段\nDialogue: 0,0:56:49.00,0:56:51.04,Default,,0,0,0,,将EXP寄存器指向运算符对应的过程\nDialogue: 0,0:56:51.48,0:56:53.15,Default,,0,0,0,,并且让ENV寄存器指向求值的环境\nDialogue: 0,0:56:53.66,0:56:54.60,Default,,0,0,0,,而把CONTINUE寄存器赋值为\nDialogue: 0,0:56:54.62,0:56:56.22,Default,,0,0,0,,用于求值参数的EVAL-ARGS\nDialogue: 0,0:56:56.59,0:56:57.37,Default,,0,0,0,,并且 我们把\nDialogue: 0,0:56:57.40,0:56:59.29,Default,,0,0,0,,CONTINUE的原始值保存在栈上\nDialogue: 0,0:56:59.52,0:57:01.02,Default,,0,0,0,,我们完成所有工作后 就会跳转到这个地方\nDialogue: 0,0:57:01.72,0:57:02.86,Default,,0,0,0,,在我们求值完运算符后\nDialogue: 0,0:57:03.58,0:57:05.80,Default,,0,0,0,,需要做的则是\nDialogue: 0,0:57:05.90,0:57:07.66,Default,,0,0,0,,求值对实际参数进行求值\nDialogue: 0,0:57:07.69,0:57:12.01,Default,,0,0,0,,也就是这个环境和这些参数\nDialogue: 0,0:57:12.14,0:57:13.44,Default,,0,0,0,,这些尚未求值的实际参数\nDialogue: 0,0:57:14.20,0:57:15.62,Default,,0,0,0,,它们现在都还在栈上\nDialogue: 0,0:57:15.62,0:57:18.59,Default,,0,0,0,,我们现在就要先来求值运算符\nDialogue: 0,0:57:23.26,0:57:26.73,Default,,0,0,0,,当我们从这个调用返回时\nDialogue: 0,0:57:26.92,0:57:28.64,Default,,0,0,0,,在这里 我们将要去调用EVAL-DISPATCH\nDialogue: 0,0:57:29.38,0:57:30.83,Default,,0,0,0,,当我们从这个调用返回时\nDialogue: 0,0:57:31.45,0:57:32.70,Default,,0,0,0,,这个运算符所对应的值\nDialogue: 0,0:57:32.73,0:57:33.52,Default,,0,0,0,,在本例中\nDialogue: 0,0:57:33.55,0:57:35.44,Default,,0,0,0,,也就是基本的乘法过程\nDialogue: 0,0:57:36.44,0:57:37.93,Default,,0,0,0,,会存放在FUN寄存器中\nDialogue: 0,0:57:43.02,0:57:44.53,Default,,0,0,0,,我们要去求值实际参数\nDialogue: 0,0:57:44.53,0:57:45.85,Default,,0,0,0,,现在这里求值N\nDialogue: 0,0:57:47.73,0:57:49.87,Default,,0,0,0,,本例中 会返回5\nDialogue: 0,0:57:50.25,0:57:52.04,Default,,0,0,0,,然后我们会把它放入ARGL寄存器\nDialogue: 0,0:57:53.00,0:57:55.88,Default,,0,0,0,,然后我们会去求值第二个运算对象\nDialogue: 0,0:57:57.46,0:58:00.48,Default,,0,0,0,,就在我们准备求值第二个运算对象之时\nDialogue: 0,0:58:00.52,0:58:02.19,Default,,0,0,0,,我会省略计算\nDialogue: 0,0:58:02.20,0:58:03.58,Default,,0,0,0,,(- N 1)之类的细节\nDialogue: 0,0:58:03.71,0:58:05.88,Default,,0,0,0,,但是 当我们去求值第二个运算对象时\nDialogue: 0,0:58:06.62,0:58:10.44,Default,,0,0,0,,会最终归约为对FACT-REC的另一个调用\nDialogue: 0,0:58:12.00,0:58:14.20,Default,,0,0,0,,现在 我们在栈上有\nDialogue: 0,0:58:16.52,0:58:19.94,Default,,0,0,0,,来自于这个组合式的运算符\nDialogue: 0,0:58:20.12,0:58:21.07,Default,,0,0,0,,以及其它的参数\nDialogue: 0,0:58:23.40,0:58:27.61,Default,,0,0,0,,现在 我们已经准备好\nDialogue: 0,0:58:28.49,0:58:29.69,Default,,0,0,0,,去调用另外的FACT-REC了\nDialogue: 0,0:58:30.20,0:58:31.43,Default,,0,0,0,,而让我们完成了这个调用以后\nDialogue: 0,0:58:31.56,0:58:33.64,Default,,0,0,0,,我们就要跳转到ACCUMULATE-LAST-ARG\nDialogue: 0,0:58:34.12,0:58:35.20,Default,,0,0,0,,还记得这是做什么的么？\nDialogue: 0,0:58:35.20,0:58:35.93,Default,,0,0,0,,它会说\nDialogue: 0,0:58:36.45,0:58:39.28,Default,,0,0,0,,我们会把这个调用的结果\nDialogue: 0,0:58:39.28,0:58:40.40,Default,,0,0,0,,和这个5相乘\nDialogue: 0,0:58:41.69,0:58:42.38,Default,,0,0,0,,但是请注意\nDialogue: 0,0:58:42.73,0:58:44.81,Default,,0,0,0,,我们现在处于另一个递归阶乘中\nDialogue: 0,0:58:45.72,0:58:48.92,Default,,0,0,0,,我们又要再次调用EVAL-DISPATCH\nDialogue: 0,0:58:49.32,0:58:50.60,Default,,0,0,0,,然而我们并没有真正地“归约”它\nDialogue: 0,0:58:50.64,0:58:52.08,Default,,0,0,0,,因为现在栈上还有东西\nDialogue: 0,0:58:53.70,0:58:55.39,Default,,0,0,0,,栈上的这些东西说：“当你返回时”\nDialogue: 0,0:58:55.40,0:58:57.52,Default,,0,0,0,,你最好把结果和放在这里的5相乘\nDialogue: 0,0:58:58.43,0:59:05.77,Default,,0,0,0,,所以当我们进行另外的调用\nDialogue: 0,0:59:07.12,0:59:08.84,Default,,0,0,0,,求值(- N 1)\nDialogue: 0,0:59:09.30,0:59:11.05,Default,,0,0,0,,这会返回给我们另一个环境\nDialogue: 0,0:59:11.25,0:59:13.84,Default,,0,0,0,,其中N的新值为4\nDialogue: 0,0:59:14.60,0:59:16.22,Default,,0,0,0,,然后又将调用EVAL-DISPATCH\nDialogue: 0,0:59:19.20,0:59:20.22,Default,,0,0,0,,我们又创建了另一个调用\nDialogue: 0,0:59:21.35,0:59:24.44,Default,,0,0,0,,这个4又会遇到相同的情况\nDialogue: 0,0:59:26.04,0:59:28.62,Default,,0,0,0,,我们最后会遇到对(FACT-REC N)的又一次调用\nDialogue: 0,0:59:30.02,0:59:32.68,Default,,0,0,0,,而这时候 栈上会有从最初的调用\nDialogue: 0,0:59:32.88,0:59:34.51,Default,,0,0,0,,到最近一次调用的东西\nDialogue: 0,0:59:35.36,0:59:36.91,Default,,0,0,0,,它们都在等待同一个东西\nDialogue: 0,0:59:36.91,0:59:39.16,Default,,0,0,0,,它们都要跳转到ACCUMULATE-LAST-ARG\nDialogue: 0,0:59:40.51,0:59:42.94,Default,,0,0,0,,当然 当我们进行第四次调用时\nDialogue: 0,0:59:43.25,0:59:44.38,Default,,0,0,0,,会发生同样的事\nDialogue: 0,0:59:45.64,0:59:47.07,Default,,0,0,0,,如此往复\nDialogue: 0,0:59:47.30,0:59:48.60,Default,,0,0,0,,在这里 你在栈上看到的\nDialogue: 0,0:59:50.30,0:59:52.22,Default,,0,0,0,,栈上面实际存放的是\nDialogue: 0,0:59:52.22,0:59:54.59,Default,,0,0,0,,基本过程*以及5\nDialogue: 0,0:59:54.96,0:59:56.40,Default,,0,0,0,,而你要把它用来\nDialogue: 0,0:59:56.59,0:59:58.54,Default,,0,0,0,,调用ACCUMULATE-LAST-ARG\nDialogue: 0,1:00:00.47,1:00:02.01,Default,,0,0,0,,就是这样 对吧？\nDialogue: 0,1:00:02.01,1:00:04.75,Default,,0,0,0,,这跟它们在表达式中的顺序是一致的\nDialogue: 0,1:00:05.65,1:00:10.65,Default,,0,0,0,,实际上 你将要应用的运算符\nDialogue: 0,1:00:11.72,1:00:14.30,Default,,0,0,0,,以及当你返回时\nDialogue: 0,1:00:14.32,1:00:15.79,Default,,0,0,0,,需要去求积的参数\nDialogue: 0,1:00:15.80,1:00:16.91,Default,,0,0,0,,以及这里的括号\nDialogue: 0,1:00:16.94,1:00:18.96,Default,,0,0,0,,都在告诉你 在对它们进行积累\nDialogue: 0,1:00:19.62,1:00:21.88,Default,,0,0,0,,因此 你可以看到代换模型并不是这样的谎言\nDialogue: 0,1:00:22.56,1:00:23.63,Default,,0,0,0,,从某种意义上来说 它实际上是\nDialogue: 0,1:00:23.64,1:00:25.31,Default,,0,0,0,,存在于栈上的那些东西\nDialogue: 0,1:00:29.37,1:00:30.40,Default,,0,0,0,,好吧 从某种意义上来说\nDialogue: 0,1:00:30.81,1:00:32.48,Default,,0,0,0,,应该给你们解释了\nDialogue: 0,1:00:33.26,1:00:34.52,Default,,0,0,0,,或者 至少让你们相信\nDialogue: 0,1:00:35.93,1:00:38.72,Default,,0,0,0,,求值器会通过某些方式\nDialogue: 0,1:00:40.06,1:00:42.86,Default,,0,0,0,,迭代地去求值某些过程\nDialogue: 0,1:00:42.95,1:00:44.25,Default,,0,0,0,,而递归地去求值另外的过程\nDialogue: 0,1:00:45.26,1:00:47.45,Default,,0,0,0,,尽管从语法上看\nDialogue: 0,1:00:47.45,1:00:49.05,Default,,0,0,0,,它们都是递归过程\nDialogue: 0,1:00:49.40,1:00:50.64,Default,,0,0,0,,它又是如何做到的呢？\nDialogue: 0,1:00:50.66,1:00:53.72,Default,,0,0,0,,其中的基本原因就是\nDialogue: 0,1:00:53.80,1:00:55.68,Default,,0,0,0,,求值器被设置为\nDialogue: 0,1:00:56.04,1:00:59.26,Default,,0,0,0,,只保存那些稍后会用到的东西\nDialogue: 0,1:01:01.09,1:01:04.25,Default,,0,0,0,,比如说 当你在把\nDialogue: 0,1:01:04.67,1:01:07.39,Default,,0,0,0,,在一个环境中求值表达式归约为\nDialogue: 0,1:01:07.87,1:01:09.87,Default,,0,0,0,,将某个过程应用在参数上时\nDialogue: 0,1:01:10.52,1:01:12.49,Default,,0,0,0,,它就不再需要最初的环境了\nDialogue: 0,1:01:13.37,1:01:16.65,Default,,0,0,0,,因为所需要的环境信息都被打包到\nDialogue: 0,1:01:17.88,1:01:19.36,Default,,0,0,0,,需要应用的那个过程中了\nDialogue: 0,1:01:20.75,1:01:21.61,Default,,0,0,0,,同样 类似地\nDialogue: 0,1:01:21.63,1:01:23.65,Default,,0,0,0,,当你求值一个参数表时\nDialogue: 0,1:01:23.65,1:01:25.20,Default,,0,0,0,,当你完成对表的求值时\nDialogue: 0,1:01:25.91,1:01:28.03,Default,,0,0,0,,当你求值完最后一个参数时\nDialogue: 0,1:01:28.20,1:01:31.61,Default,,0,0,0,,你就不再需要这个参数表了 对吧？\nDialogue: 0,1:01:31.63,1:01:32.94,Default,,0,0,0,,你也就不再需要\nDialogue: 0,1:01:33.04,1:01:34.64,Default,,0,0,0,,求值这些参数所需的环境了\nDialogue: 0,1:01:36.69,1:01:40.89,Default,,0,0,0,,所以这个解释器如此“智能”的根本原因\nDialogue: 0,1:01:40.89,1:01:42.88,Default,,0,0,0,,根本不是因为它“智能” 只是因为它老实\nDialogue: 0,1:01:43.05,1:01:45.74,Default,,0,0,0,,它的原则就是：“只保存那些需要的”\nDialogue: 0,1:01:48.70,1:01:51.00,Default,,0,0,0,,这里 让我来给你们展示\nDialogue: 0,1:01:53.07,1:01:57.20,Default,,0,0,0,,这是致使尾递归的根本原因\nDialogue: 0,1:01:58.31,1:02:00.20,Default,,0,0,0,,要记住 (RESOTRE CONTINUE)这条代码\nDialogue: 0,1:02:00.22,1:02:06.94,Default,,0,0,0,,它指的是 当我去求值过程体的时候\nDialogue: 0,1:02:08.96,1:02:11.00,Default,,0,0,0,,我应该告诉EVAL返回到\nDialogue: 0,1:02:11.25,1:02:12.54,Default,,0,0,0,,最初的求值\nDialogue: 0,1:02:12.54,1:02:14.25,Default,,0,0,0,,应该返回的地方\nDialogue: 0,1:02:15.17,1:02:15.95,Default,,0,0,0,,因此 从某种角度来说\nDialogue: 0,1:02:16.17,1:02:18.84,Default,,0,0,0,,你想知道是哪一行代码致使了尾递归\nDialogue: 0,1:02:18.89,1:02:19.44,Default,,0,0,0,,那么就是这一行\nDialogue: 0,1:02:19.92,1:02:21.53,Default,,0,0,0,,出于某些奇怪的原因\nDialogue: 0,1:02:21.77,1:02:24.80,Default,,0,0,0,,如果我想构建一个没有尾递归的求值器\nDialogue: 0,1:02:25.69,1:02:26.86,Default,,0,0,0,,我需要做的就是\nDialogue: 0,1:02:27.12,1:02:29.29,Default,,0,0,0,,在这里先不要去恢复CONTINUE\nDialogue: 0,1:02:30.06,1:02:31.66,Default,,0,0,0,,而是在这里建立一个标号\nDialogue: 0,1:02:32.75,1:02:36.25,Default,,0,0,0,,用来标识完成过程应用后的返回位置\nDialogue: 0,1:02:37.64,1:02:39.71,Default,,0,0,0,,而我会把CONTINUE设置为这个标号\nDialogue: 0,1:02:39.92,1:02:41.21,Default,,0,0,0,,然后跳转到EVAL-DISPATCH\nDialogue: 0,1:02:41.40,1:02:43.21,Default,,0,0,0,,然后EVAL-DISPATCH会回到这里\nDialogue: 0,1:02:43.79,1:02:44.30,Default,,0,0,0,,而这时\nDialogue: 0,1:02:44.32,1:02:45.28,Default,,0,0,0,,我会恢复CONTINUE\nDialogue: 0,1:02:45.29,1:02:46.52,Default,,0,0,0,,并回到最初的返回位置\nDialogue: 0,1:02:47.92,1:02:51.00,Default,,0,0,0,,因此 这里唯一的后果就是\nDialogue: 0,1:02:51.15,1:02:52.68,Default,,0,0,0,,解释器不再是尾递归的了\nDialogue: 0,1:02:52.84,1:02:54.62,Default,,0,0,0,,它会给你完全相同的答案\nDialogue: 0,1:02:54.72,1:02:57.02,Default,,0,0,0,,只是当你执行迭代式阶乘\nDialogue: 0,1:02:57.05,1:02:58.36,Default,,0,0,0,,或者其它迭代过程时\nDialogue: 0,1:02:58.60,1:02:59.80,Default,,0,0,0,,它都会递归地去执行\nDialogue: 0,1:03:03.04,1:03:05.40,Default,,0,0,0,,然而 我对你们撒了一个小谎\nDialogue: 0,1:03:05.76,1:03:06.99,Default,,0,0,0,,因为我演示的\nDialogue: 0,1:03:07.02,1:03:08.33,Default,,0,0,0,,一个有些过于简化的解释器\nDialogue: 0,1:03:08.72,1:03:10.38,Default,,0,0,0,,这个解释器假设每个过程\nDialogue: 0,1:03:11.36,1:03:13.66,Default,,0,0,0,,只含有一条表达式\nDialogue: 0,1:03:13.89,1:03:14.54,Default,,0,0,0,,还记得吗 通常来说\nDialogue: 0,1:03:14.56,1:03:16.57,Default,,0,0,0,,过程的体是多条表达式组成的序列\nDialogue: 0,1:03:17.87,1:03:20.49,Default,,0,0,0,,所以没有什么新概念\nDialogue: 0,1:03:20.49,1:03:22.28,Default,,0,0,0,,让我来展示一下实际的求值器\nDialogue: 0,1:03:22.89,1:03:24.73,Default,,0,0,0,,是怎么来处理表达式序列的\nDialogue: 0,1:03:28.47,1:03:29.74,Default,,0,0,0,,这是现在的COMPOUND-APPLY\nDialogue: 0,1:03:29.74,1:03:31.31,Default,,0,0,0,,和之前的唯一不同是\nDialogue: 0,1:03:32.07,1:03:34.33,Default,,0,0,0,,它不再直接地跳转到EVAL\nDialogue: 0,1:03:35.98,1:03:38.03,Default,,0,0,0,,它先获取整个过程的体\nDialogue: 0,1:03:38.03,1:03:40.15,Default,,0,0,0,,在本例中 也就是表达式序列\nDialogue: 0,1:03:40.28,1:03:41.71,Default,,0,0,0,,然后跳转到EVAL-SEQUENCE\nDialogue: 0,1:03:42.60,1:03:45.32,Default,,0,0,0,,EVAL-SEQUENCE是一个小型的循环\nDialogue: 0,1:03:46.83,1:03:49.98,Default,,0,0,0,,然后每次求值一条表达式\nDialogue: 0,1:03:52.63,1:03:53.85,Default,,0,0,0,,就是这样来求值的--\nDialogue: 0,1:03:53.90,1:03:54.94,Default,,0,0,0,,当它求值完一条表达式后\nDialogue: 0,1:03:54.97,1:03:56.86,Default,,0,0,0,,会跳转到这里 去求值下一条\nDialogue: 0,1:03:58.44,1:03:59.29,Default,,0,0,0,,当我完成了所有的求值后\nDialogue: 0,1:03:59.29,1:04:01.02,Default,,0,0,0,,我想要跳转到LAST-EXP\nDialogue: 0,1:04:01.31,1:04:03.28,Default,,0,0,0,,我就只需要恢复CONTINUE寄存器\nDialogue: 0,1:04:03.92,1:04:05.28,Default,,0,0,0,,然后跳转到EVAL-DISPATCH\nDialogue: 0,1:04:06.41,1:04:08.20,Default,,0,0,0,,同样的 如果你想要在这种求值器中\nDialogue: 0,1:04:08.20,1:04:10.35,Default,,0,0,0,,破坏尾递归机制\nDialogue: 0,1:04:10.64,1:04:13.71,Default,,0,0,0,,你只需要在LAST-EXP中不做特殊处理即可\nDialogue: 0,1:04:14.90,1:04:17.34,Default,,0,0,0,,也就是说 当你处理完最后一条表达式\nDialogue: 0,1:04:17.36,1:04:18.65,Default,,0,0,0,,你跳转到另外一个地方\nDialogue: 0,1:04:19.15,1:04:20.68,Default,,0,0,0,,在那个地方去恢复CONTINUE\nDialogue: 0,1:04:21.90,1:04:23.26,Default,,0,0,0,,出于某些原因\nDialogue: 0,1:04:23.26,1:04:25.74,Default,,0,0,0,,很多Lisp求值器倾向于这么做\nDialogue: 0,1:04:26.55,1:04:28.44,Default,,0,0,0,,这样做的后果就是\nDialogue: 0,1:04:28.86,1:04:30.72,Default,,0,0,0,,迭代式过程也会使栈增长\nDialogue: 0,1:04:31.88,1:04:33.61,Default,,0,0,0,,还不清楚为什么会这样\nDialogue: 0,1:04:35.92,1:04:37.98,Default,,0,0,0,,好吧 我稍微来总结一下\nDialogue: 0,1:04:38.09,1:04:39.60,Default,,0,0,0,,毕竟这是一个大程序\nDialogue: 0,1:04:39.98,1:04:41.04,Default,,0,0,0,,又有很多细节\nDialogue: 0,1:04:41.12,1:04:42.25,Default,,0,0,0,,但关键点就是\nDialogue: 0,1:04:43.04,1:04:43.87,Default,,0,0,0,,从概念上来说\nDialogue: 0,1:04:44.04,1:04:46.08,Default,,0,0,0,,这跟翻译其它程序没什么不同\nDialogue: 0,1:04:47.06,1:04:48.06,Default,,0,0,0,,核心思想就是\nDialogue: 0,1:04:48.06,1:04:50.28,Default,,0,0,0,,我们已经有了通用求值器程序\nDialogue: 0,1:04:50.33,1:04:51.71,Default,,0,0,0,,一个元循环求值器\nDialogue: 0,1:04:51.87,1:04:53.07,Default,,0,0,0,,如果我们把它翻译为了Lisp\nDialogue: 0,1:04:53.10,1:04:53.95,Default,,0,0,0,,那么我们就有了Lisp的所有东西\nDialogue: 0,1:04:54.33,1:04:55.15,Default,,0,0,0,,我们就是这么来做的\nDialogue: 0,1:04:57.98,1:04:59.68,Default,,0,0,0,,第二点则是 魔法消失了\nDialogue: 0,1:04:59.68,1:05:01.97,Default,,0,0,0,,这整个系统不再神秘了 对吧？\nDialogue: 0,1:05:01.97,1:05:07.79,Default,,0,0,0,,原则上来说 这应该相当清楚了\nDialogue: 0,1:05:07.82,1:05:10.08,Default,,0,0,0,,只是还不太了解表结构的内存管理\nDialogue: 0,1:05:10.80,1:05:11.80,Default,,0,0,0,,我们后面会讲\nDialogue: 0,1:05:12.64,1:05:14.20,Default,,0,0,0,,这也并不困难\nDialogue: 0,1:05:15.45,1:05:16.35,Default,,0,0,0,,第三点就是\nDialogue: 0,1:05:16.35,1:05:17.52,Default,,0,0,0,,所有的这些尾递归\nDialogue: 0,1:05:18.24,1:05:21.96,Default,,0,0,0,,来自于严格的求值纪律\nDialogue: 0,1:05:22.55,1:05:24.51,Default,,0,0,0,,也就是只保存那些后面会用到的东西\nDialogue: 0,1:05:25.87,1:05:27.72,Default,,0,0,0,,而不是一些比较随意的原则\nDialogue: 0,1:05:27.76,1:05:29.86,Default,,0,0,0,,比如 无论什么时候我们调用一个子过程\nDialogue: 0,1:05:29.86,1:05:32.16,Default,,0,0,0,,我们会保存所有的寄存器并且返回\nDialogue: 0,1:05:33.94,1:05:36.49,Default,,0,0,0,,有些时候为了提效 这样做很值得\nDialogue: 0,1:05:37.15,1:05:39.96,Default,,0,0,0,,当你研究求值机器的内部原理时\nDialogue: 0,1:05:40.45,1:05:42.56,Default,,0,0,0,,这类东西就很值得去研究\nDialogue: 0,1:05:42.56,1:05:43.96,Default,,0,0,0,,因为它会带来显著的不同\nDialogue: 0,1:05:45.23,1:05:47.69,Default,,0,0,0,,我想现在基本上已经\nDialogue: 0,1:05:47.90,1:05:52.30,Default,,0,0,0,,把这个求值器讲得很清楚了\nDialogue: 0,1:05:52.56,1:05:53.90,Default,,0,0,0,,我希望你们能相信\nDialogue: 0,1:05:54.32,1:05:56.27,Default,,0,0,0,,真的有人能够\nDialogue: 0,1:05:56.84,1:05:58.56,Default,,0,0,0,,将一个Lisp求值器放在掌心之中\nDialogue: 0,1:05:59.07,1:06:00.49,Default,,0,0,0,,为了让你们死心塌地\nDialogue: 0,1:06:00.80,1:06:01.96,Default,,0,0,0,,我给你们看一个Lisp求值器\nDialogue: 0,1:06:02.54,1:06:04.06,Default,,0,0,0,,它就在我的手掌中\nDialogue: 0,1:06:06.16,1:06:10.56,Default,,0,0,0,,这块求值器芯片实际上\nDialogue: 0,1:06:10.89,1:06:13.70,Default,,0,0,0,,比我给你们展示的求值器还要复杂\nDialogue: 0,1:06:16.86,1:06:19.20,Default,,0,0,0,,这张图片效果更好\nDialogue: 0,1:06:22.07,1:06:22.57,Default,,0,0,0,,在这上面\nDialogue: 0,1:06:22.60,1:06:24.38,Default,,0,0,0,,你可以看到相同的宏观结构\nDialogue: 0,1:06:24.73,1:06:25.93,Default,,0,0,0,,这是寄存器阵列\nDialogue: 0,1:06:26.80,1:06:27.71,Default,,0,0,0,,这些是数据通路\nDialogue: 0,1:06:27.72,1:06:29.07,Default,,0,0,0,,这里有是有穷状态控制器\nDialogue: 0,1:06:29.80,1:06:31.04,Default,,0,0,0,,再强调一下 是有穷状态\nDialogue: 0,1:06:31.96,1:06:32.80,Default,,0,0,0,,全都在这里了\nDialogue: 0,1:06:32.81,1:06:34.16,Default,,0,0,0,,在另外的地方还有外部存储\nDialogue: 0,1:06:34.16,1:06:35.23,Default,,0,0,0,,用来存储数据\nDialogue: 0,1:06:35.75,1:06:37.63,Default,,0,0,0,,而这块芯片非常复杂\nDialogue: 0,1:06:37.64,1:06:39.16,Default,,0,0,0,,是因为它尝试更快地运行Lisp\nDialogue: 0,1:06:39.66,1:06:42.97,Default,,0,0,0,,它具有非常非常之快的并行运算\nDialogue: 0,1:06:43.07,1:06:46.32,Default,,0,0,0,,比如说 如果你想要索引一个数组\nDialogue: 0,1:06:46.70,1:06:50.40,Default,,0,0,0,,同时又要检查该索引是否为一个整数\nDialogue: 0,1:06:50.43,1:06:52.86,Default,,0,0,0,,以及该索引没有越界\nDialogue: 0,1:06:53.04,1:06:55.02,Default,,0,0,0,,同时还要进行内存存取\nDialogue: 0,1:06:55.05,1:06:56.70,Default,,0,0,0,,它会同时进行这些事\nDialogue: 0,1:06:57.12,1:06:58.40,Default,,0,0,0,,如果这些操作都没有问题的话\nDialogue: 0,1:06:58.44,1:06:59.96,Default,,0,0,0,,最终就会在这里得到结果\nDialogue: 0,1:07:00.42,1:07:02.46,Default,,0,0,0,,因此 数据通路中大量的\nDialogue: 0,1:07:02.48,1:07:04.65,Default,,0,0,0,,复杂运算使得Lisp能够并行运行\nDialogue: 0,1:07:05.26,1:07:08.41,Default,,0,0,0,,这完全是求值Lisp的\nDialogue: 0,1:07:08.76,1:07:10.36,Default,,0,0,0,,一种无冒险的哲学\nDialogue: 0,1:07:10.64,1:07:13.20,Default,,0,0,0,,并且 这个的微指令也相当复杂\nDialogue: 0,1:07:13.45,1:07:17.56,Default,,0,0,0,,让我先看一看\nDialogue: 0,1:07:17.60,1:07:21.10,Default,,0,0,0,,这其中有大概389条\nDialogue: 0,1:07:21.68,1:07:23.85,Default,,0,0,0,,220比特的微指令\nDialogue: 0,1:07:24.07,1:07:27.94,Default,,0,0,0,,只因为这些数据通路非常复杂\nDialogue: 0,1:07:27.94,1:07:32.25,Default,,0,0,0,,整个芯片大概有89,000支晶体管\nDialogue: 0,1:07:33.56,1:07:36.86,Default,,0,0,0,,好吧 我希望通过这节课解答了大部分疑惑\nDialogue: 0,1:07:37.97,1:07:39.24,Default,,0,0,0,,也许你们想看一看这块芯片\nDialogue: 0,1:07:46.14,1:07:46.89,Default,,0,0,0,,好吧 先讲到这里\nDialogue: 0,1:07:56.46,1:07:56.75,Default,,0,0,0,,有问题吗？\nDialogue: 0,1:07:59.00,1:08:00.42,Default,,0,0,0,,学生：您所讲的 听起来像是\nDialogue: 0,1:08:00.42,1:08:03.48,Default,,0,0,0,,如果把(RESTORE CONTINUE)放在合适的地方\nDialogue: 0,1:08:03.58,1:08:09.42,Default,,0,0,0,,这样之前递归求值的过程\nDialogue: 0,1:08:09.42,1:08:11.95,Default,,0,0,0,,现在就会变成迭代求值的\nDialogue: 0,1:08:12.67,1:08:15.36,Default,,0,0,0,,（意义不明）\nDialogue: 0,1:08:15.60,1:08:17.54,Default,,0,0,0,,教授：我想我应该这么来说\nDialogue: 0,1:08:17.54,1:08:19.82,Default,,0,0,0,,如果把(RESTORE CONTINUE)放在了错误的位置\nDialogue: 0,1:08:20.55,1:08:25.48,Default,,0,0,0,,你就会让那些语法上看起来像递归的过程\nDialogue: 0,1:08:25.52,1:08:27.28,Default,,0,0,0,,在运行的时候不断地扩张栈\nDialogue: 0,1:08:28.64,1:08:30.52,Default,,0,0,0,,但这样是没有原因的\nDialogue: 0,1:08:33.15,1:08:35.12,Default,,0,0,0,,你可以自己去试一试\nDialogue: 0,1:08:35.15,1:08:38.09,Default,,0,0,0,,你可以在COMPOND-APPLY返回后\nDialogue: 0,1:08:38.18,1:08:40.78,Default,,0,0,0,,交换两、三条语句的顺序\nDialogue: 0,1:08:41.31,1:08:43.26,Default,,0,0,0,,那么你得到的就不再是尾递归了\nDialogue: 0,1:08:45.06,1:08:46.14,Default,,0,0,0,,我只是想强调\nDialogue: 0,1:08:46.16,1:08:47.40,Default,,0,0,0,,这其中没有什么魔法\nDialogue: 0,1:08:47.67,1:08:48.57,Default,,0,0,0,,这并不是\nDialogue: 0,1:08:49.31,1:08:52.17,Default,,0,0,0,,有什么智能的预处理程序\nDialogue: 0,1:08:52.65,1:08:55.45,Default,,0,0,0,,它会分析FACT-ITER这个程序\nDialogue: 0,1:08:55.47,1:08:56.73,Default,,0,0,0,,然后说\nDialogue: 0,1:08:57.42,1:08:58.86,Default,,0,0,0,,我注意到\nDialogue: 0,1:08:58.88,1:09:01.13,Default,,0,0,0,,完成这个调用 不需要我进行压栈\nDialogue: 0,1:09:01.13,1:09:02.88,Default,,0,0,0,,但是有些人是这么认为的\nDialogue: 0,1:09:03.76,1:09:05.38,Default,,0,0,0,,而是一种比这个还要蠢的机制\nDialogue: 0,1:09:05.38,1:09:07.50,Default,,0,0,0,,就是在合适的地方插入RESTORE指令\nDialogue: 0,1:09:08.56,1:09:09.79,Default,,0,0,0,,就可以自动地实现\nDialogue: 0,1:09:14.72,1:09:17.55,Default,,0,0,0,,学生：但这不会影响到时间复杂度 对吧？\nDialogue: 0,1:09:17.58,1:09:17.87,Default,,0,0,0,,教授：不会\nDialogue: 0,1:09:18.60,1:09:21.77,Default,,0,0,0,,学生：它不会迭代地处理\nDialogue: 0,1:09:21.80,1:09:23.02,Default,,0,0,0,,而是会递归地处理\nDialogue: 0,1:09:23.02,1:09:27.34,Default,,0,0,0,,但就从完成这两个运算的时间来说\nDialogue: 0,1:09:27.37,1:09:29.22,Default,,0,0,0,,它们都是相同的 对吧？\nDialogue: 0,1:09:29.47,1:09:29.76,Default,,0,0,0,,教授 ：是的\nDialogue: 0,1:09:29.79,1:09:32.68,Default,,0,0,0,,尾递归不会改变任何东西的时间复杂度\nDialogue: 0,1:09:32.72,1:09:33.29,Default,,0,0,0,,因为 从某种意义上来说\nDialogue: 0,1:09:33.34,1:09:35.15,Default,,0,0,0,,两者都是相同的算法\nDialogue: 0,1:09:36.02,1:09:39.37,Default,,0,0,0,,它只是让这个过程迭代地运行\nDialogue: 0,1:09:41.00,1:09:42.64,Default,,0,0,0,,这样 当参数很大时\nDialogue: 0,1:09:42.68,1:09:44.22,Default,,0,0,0,,它不会耗尽所有的内存\nDialogue: 0,1:09:44.75,1:09:46.40,Default,,0,0,0,,因为这其中没有压栈\nDialogue: 0,1:09:48.35,1:09:50.24,Default,,0,0,0,,事实上 你们需要相信\nDialogue: 0,1:09:50.56,1:09:51.13,Default,,0,0,0,,当我们编写--\nDialogue: 0,1:09:51.64,1:09:53.78,Default,,0,0,0,,我们一直把这些代码称作“迭代”\nDialogue: 0,1:09:53.93,1:09:57.99,Default,,0,0,0,,把(DEFINE (LOOP) (LOOP))称作无穷循环\nDialogue: 0,1:10:00.32,1:10:03.36,Default,,0,0,0,,这就是一个迭代\nDialogue: 0,1:10:03.65,1:10:05.66,Default,,0,0,0,,跟我们用DO语句来写无穷循环是一样的\nDialogue: 0,1:10:07.63,1:10:09.28,Default,,0,0,0,,它们只是语法上不同而已\nDialogue: 0,1:10:09.28,1:10:11.32,Default,,0,0,0,,它们实际上都是迭代\nDialogue: 0,1:10:14.73,1:10:16.08,Default,,0,0,0,,它们并不改变时间复杂度\nDialogue: 0,1:10:16.11,1:10:18.53,Default,,0,0,0,,但是它会把它们变成真正的迭代\nDialogue: 0,1:10:21.68,1:10:23.80,Default,,0,0,0,,好吧 下课\nDialogue: 0,1:10:24.25,1:10:40.73,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:10:24.25,1:10:40.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec9b.chn.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[Aegisub Project Garbage]\nScroll Position: 707\nActive Line: 1394\nVideo Position: 126316\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.03,0:00:00.97,Declare,,0,0,0,,{\\an2\\fad(500,500)}Learning-SICP 学习小组\\N倾情制作\nDialogue: 0,0:00:01.05,0:00:09.09,title,,0,0,0,,{\\fad(600,800)\\pos(324,32)}《计算机程序的构造和解释》\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(110.666,403.334)}翻译&&时间轴\\N邓雄飞\\N刘殊君\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(534.666,404)}压制&&特效\\N邓雄飞\\N（Dysprosium）\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(574.667,277.333)}校对\\N邓雄飞\nDialogue: 0,0:00:01.05,0:00:09.09,staff,,0,0,0,,{\\fad(600,800)\\pos(89.334,273.333)}特别感谢\\N裘宗燕教授\nDialogue: 0,0:00:09.21,0:00:13.12,Declare,,0,0,0,,{\\an2\\fad(500,500)}显示控制求值器\nDialogue: 0,0:00:16.30,0:00:18.08,Default,,0,0,0,,教授：我想大家已经意识到\nDialogue: 0,0:00:20.01,0:00:22.73,Default,,0,0,0,,我们介绍了一些真正的魔法\nDialogue: 0,0:00:24.20,0:00:27.24,Default,,0,0,0,,创造新语言的魔法\nDialogue: 0,0:00:27.42,0:00:28.72,Default,,0,0,0,,用来创造全新的语言\nDialogue: 0,0:00:29.69,0:00:30.40,Default,,0,0,0,,我们学了些什么？\nDialogue: 0,0:00:30.43,0:00:32.78,Default,,0,0,0,,我们学习了一门用来操作图片的Escher的语言\nDialogue: 0,0:00:38.92,0:00:41.15,Default,,0,0,0,,这门语言由Peter Henderson发明\nDialogue: 0,0:00:42.01,0:00:46.49,Default,,0,0,0,,我们还学习了数字逻辑语言\nDialogue: 0,0:00:53.16,0:00:55.55,Default,,0,0,0,,以及 我们还学习了查询语言\nDialogue: 0,0:00:59.70,0:01:00.78,Default,,0,0,0,,然而你需要明白的是\nDialogue: 0,0:01:00.81,0:01:03.10,Default,,0,0,0,,尽管它们都是“玩具级”的语言示例\nDialogue: 0,0:01:04.70,0:01:07.61,Default,,0,0,0,,但也确实是实用工具的核心\nDialogue: 0,0:01:08.25,0:01:09.48,Default,,0,0,0,,比如说\nDialogue: 0,0:01:10.12,0:01:11.18,Default,,0,0,0,,Escher图片语言\nDialogue: 0,0:01:11.20,0:01:14.33,Default,,0,0,0,,就被MIT的学生Henry Wu拿去\nDialogue: 0,0:01:14.88,0:01:16.43,Default,,0,0,0,,开发成了一门用于\nDialogue: 0,0:01:16.97,0:01:19.45,Default,,0,0,0,,为电路板布局的语言\nDialogue: 0,0:01:20.35,0:01:22.56,Default,,0,0,0,,它就是在这些结构上扩展而来\nDialogue: 0,0:01:23.24,0:01:24.65,Default,,0,0,0,,至于数字逻辑语言\nDialogue: 0,0:01:24.68,0:01:26.08,Default,,0,0,0,,Gerry教授在上课的时候也提到过\nDialogue: 0,0:01:26.43,0:01:29.92,Default,,0,0,0,,它被扩展为了一个仿真器的基础\nDialogue: 0,0:01:30.85,0:01:32.96,Default,,0,0,0,,用来设计真实的计算机\nDialogue: 0,0:01:33.46,0:01:34.32,Default,,0,0,0,,至于查询语言\nDialogue: 0,0:01:34.35,0:01:36.44,Default,,0,0,0,,当然就是Prolog语言的一种核心\nDialogue: 0,0:01:37.51,0:01:39.07,Default,,0,0,0,,我们构造的这些语言\nDialogue: 0,0:01:39.55,0:01:40.65,Default,,0,0,0,,全都是用Lisp编写\nDialogue: 0,0:01:43.63,0:01:44.59,Default,,0,0,0,,很多人问\nDialogue: 0,0:01:45.27,0:01:48.73,Default,,0,0,0,,Lisp适合用来解决哪一类问题？\nDialogue: 0,0:01:48.75,0:01:49.93,Default,,0,0,0,,答案就是\nDialogue: 0,0:01:50.33,0:01:52.65,Default,,0,0,0,,Lisp不适合解决任何一类问题\nDialogue: 0,0:01:53.53,0:01:54.60,Default,,0,0,0,,Lisp擅长的是\nDialogue: 0,0:01:54.73,0:01:57.15,Default,,0,0,0,,用它来构造一门合适的语言\nDialogue: 0,0:01:57.18,0:01:58.57,Default,,0,0,0,,来解决你的问题\nDialogue: 0,0:01:59.17,0:02:00.44,Default,,0,0,0,,你应该像这样看待Lisp\nDialogue: 0,0:02:01.47,0:02:03.39,Default,,0,0,0,,那么既然这些语言都基于Lisp\nDialogue: 0,0:02:04.57,0:02:05.72,Default,,0,0,0,,那Lisp又基于什么？\nDialogue: 0,0:02:06.97,0:02:07.88,Default,,0,0,0,,它又从何而来？\nDialogue: 0,0:02:07.90,0:02:09.40,Default,,0,0,0,,这个我们也学过\nDialogue: 0,0:02:09.58,0:02:16.09,Default,,0,0,0,,我们学过元循环求值器\nDialogue: 0,0:02:21.53,0:02:23.40,Default,,0,0,0,,学习了元循环求值器后 我们说\nDialogue: 0,0:02:23.42,0:02:25.76,Default,,0,0,0,,Lisp就是基于Lisp的\nDialogue: 0,0:02:25.80,0:02:27.48,Default,,0,0,0,,而当我们研究它的时候\nDialogue: 0,0:02:28.27,0:02:29.95,Default,,0,0,0,,我们必须得施展一些真正的魔法 对吧？\nDialogue: 0,0:02:29.95,0:02:31.74,Default,,0,0,0,,这又是什么意思呢？\nDialogue: 0,0:02:31.74,0:02:34.96,Default,,0,0,0,,Y算子、不动点\nDialogue: 0,0:02:35.76,0:02:38.33,Default,,0,0,0,,以及这样的一个观念--\nDialogue: 0,0:02:38.36,0:02:41.44,Default,,0,0,0,,Lisp实际上是一个方程的不动点\nDialogue: 0,0:02:42.20,0:02:45.42,Default,,0,0,0,,一个通过自身来定义的有趣方程\nDialogue: 0,0:02:47.40,0:02:48.56,Default,,0,0,0,,这确实是神奇的魔法\nDialogue: 0,0:02:49.07,0:02:52.35,Default,,0,0,0,,那么今天 作为魔法的最后一步\nDialogue: 0,0:02:52.62,0:02:54.03,Default,,0,0,0,,我们要把它们通通消除掉\nDialogue: 0,0:03:06.80,0:03:07.98,Default,,0,0,0,,我们已经知道怎么做了\nDialogue: 0,0:03:09.77,0:03:10.76,Default,,0,0,0,,核心要思想是\nDialogue: 0,0:03:11.13,0:03:12.73,Default,,0,0,0,,将Lisp语言\nDialogue: 0,0:03:13.36,0:03:15.50,Default,,0,0,0,,实现在使用寄存器架构的机器上\nDialogue: 0,0:03:15.50,0:03:17.93,Default,,0,0,0,,回想一下 寄存器机器的关键之处在于\nDialogue: 0,0:03:19.60,0:03:24.68,Default,,0,0,0,,机器的一部分是确定且有穷的\nDialogue: 0,0:03:24.72,0:03:26.12,Default,,0,0,0,,它有一个有穷状态控制器\nDialogue: 0,0:03:26.12,0:03:27.87,Default,,0,0,0,,它用特定的硬件\nDialogue: 0,0:03:27.88,0:03:29.31,Default,,0,0,0,,去完成特定的事情\nDialogue: 0,0:03:30.51,0:03:31.74,Default,,0,0,0,,其中还有一些运算所需的\nDialogue: 0,0:03:31.76,0:03:33.24,Default,,0,0,0,,特殊数据通路\nDialogue: 0,0:03:33.55,0:03:35.29,Default,,0,0,0,,然后 为了实现递归\nDialogue: 0,0:03:35.53,0:03:37.60,Default,,0,0,0,,并且维持无穷的假象\nDialogue: 0,0:03:37.82,0:03:39.77,Default,,0,0,0,,还使用了一种称作“栈”的大内存\nDialogue: 0,0:03:42.06,0:03:43.72,Default,,0,0,0,,所以如果我们在\nDialogue: 0,0:03:43.92,0:03:45.50,Default,,0,0,0,,寄存器机器上实现了Lisp\nDialogue: 0,0:03:47.02,0:03:48.35,Default,,0,0,0,,那么这个时候\nDialogue: 0,0:03:48.40,0:03:49.85,Default,,0,0,0,,所有的东西都会完全具体化\nDialogue: 0,0:03:49.85,0:03:51.23,Default,,0,0,0,,所有的魔法都会消除\nDialogue: 0,0:03:51.65,0:03:53.52,Default,,0,0,0,,这堂课结束时\nDialogue: 0,0:03:53.53,0:03:54.78,Default,,0,0,0,,我想让你感觉到\nDialogue: 0,0:03:55.14,0:03:59.05,Default,,0,0,0,,相对于神秘的元循环求值器\nDialogue: 0,0:03:59.67,0:04:02.60,Default,,0,0,0,,Lisp求值器是非常具体的东西\nDialogue: 0,0:04:02.85,0:04:04.57,Default,,0,0,0,,你甚至可以把它放在手心中\nDialogue: 0,0:04:04.76,0:04:06.24,Default,,0,0,0,,你可以想象一下\nDialogue: 0,0:04:06.57,0:04:07.90,Default,,0,0,0,,手里拿着一个Lisp解释器的情景\nDialogue: 0,0:04:09.63,0:04:10.94,Default,,0,0,0,,好 那我们怎么做呢？\nDialogue: 0,0:04:10.95,0:04:12.76,Default,,0,0,0,,所有的原料都已经齐全\nDialogue: 0,0:04:13.96,0:04:17.45,Default,,0,0,0,,上节课Gerry教了你们\nDialogue: 0,0:04:17.60,0:04:21.47,Default,,0,0,0,,对一个任意的Lisp过程\nDialogue: 0,0:04:22.60,0:04:24.28,Default,,0,0,0,,如何手动地把它们\nDialogue: 0,0:04:24.75,0:04:26.67,Default,,0,0,0,,翻译成在寄存器机器上运行的代码\nDialogue: 0,0:04:28.20,0:04:30.52,Default,,0,0,0,,那么 要在寄存器机器上实现Lisp本身\nDialogue: 0,0:04:30.57,0:04:31.44,Default,,0,0,0,,我们只需要\nDialogue: 0,0:04:31.69,0:04:33.45,Default,,0,0,0,,把最关键的过程\nDialogue: 0,0:04:33.68,0:04:35.42,Default,,0,0,0,,也就是元循环求值器\nDialogue: 0,0:04:36.17,0:04:38.11,Default,,0,0,0,,手工翻译成寄存器机器的代码\nDialogue: 0,0:04:39.04,0:04:40.25,Default,,0,0,0,,这就实现了整个Lisp\nDialogue: 0,0:04:42.14,0:04:43.00,Default,,0,0,0,,因此 我们已经知道了\nDialogue: 0,0:04:43.02,0:04:44.43,Default,,0,0,0,,实现的原理\nDialogue: 0,0:04:45.38,0:04:46.54,Default,,0,0,0,,而且实际上\nDialogue: 0,0:04:46.68,0:04:48.86,Default,,0,0,0,,这跟翻译\nDialogue: 0,0:04:50.00,0:04:53.40,Default,,0,0,0,,递归版的阶乘或斐波那契数列\nDialogue: 0,0:04:53.42,0:04:54.67,Default,,0,0,0,,没什么区别\nDialogue: 0,0:04:54.67,0:04:56.00,Default,,0,0,0,,只是它规模更大 代码更多\nDialogue: 0,0:04:56.84,0:04:58.03,Default,,0,0,0,,只是包含了更多细节\nDialogue: 0,0:04:58.04,0:04:59.66,Default,,0,0,0,,但是没有任何新的概念\nDialogue: 0,0:05:01.48,0:05:03.02,Default,,0,0,0,,当我们完成这个以后\nDialogue: 0,0:05:03.08,0:05:04.76,Default,,0,0,0,,所有的东西都变得明确了\nDialogue: 0,0:05:04.87,0:05:06.91,Default,,0,0,0,,当我们看到如何用一系列的\nDialogue: 0,0:05:06.94,0:05:10.08,Default,,0,0,0,,寄存器操作来实现Lisp之后\nDialogue: 0,0:05:10.16,0:05:11.63,Default,,0,0,0,,它就成为了我们整个课程中\nDialogue: 0,0:05:11.95,0:05:14.16,Default,,0,0,0,,最明确的Lisp模型\nDialogue: 0,0:05:14.81,0:05:16.95,Default,,0,0,0,,回忆一下 这个过程贯穿了整个课程\nDialogue: 0,0:05:16.95,0:05:18.25,Default,,0,0,0,,我们先从代换模型开始\nDialogue: 0,0:05:18.28,0:05:19.58,Default,,0,0,0,,它和代数有点相似\nDialogue: 0,0:05:20.24,0:05:21.87,Default,,0,0,0,,然后学习了环境模型\nDialogue: 0,0:05:21.88,0:05:24.00,Default,,0,0,0,,它引入了“框架”的概念\nDialogue: 0,0:05:24.03,0:05:25.31,Default,,0,0,0,,以及框架之间的关联\nDialogue: 0,0:05:26.32,0:05:27.88,Default,,0,0,0,,然后我们在元循环求值器中\nDialogue: 0,0:05:27.90,0:05:29.36,Default,,0,0,0,,把它变得更具体了\nDialogue: 0,0:05:31.05,0:05:31.64,Default,,0,0,0,,但是有的事情\nDialogue: 0,0:05:31.87,0:05:33.98,Default,,0,0,0,,元循环求值器没有告诉我们\nDialogue: 0,0:05:34.36,0:05:35.34,Default,,0,0,0,,你应该认识到这点\nDialogue: 0,0:05:36.09,0:05:38.64,Default,,0,0,0,,比如说 我们还不知道\nDialogue: 0,0:05:38.73,0:05:42.67,Default,,0,0,0,,像这里的递归阶乘过程\nDialogue: 0,0:05:45.17,0:05:47.13,Default,,0,0,0,,为何不断地申请新的空间\nDialogue: 0,0:05:47.21,0:05:47.98,Default,,0,0,0,,另一方面\nDialogue: 0,0:05:48.16,0:05:51.94,Default,,0,0,0,,一个语法上看起来像是递归的过程\nDialogue: 0,0:05:52.11,0:05:55.07,Default,,0,0,0,,比如FACT-ITER 并不占用栈空间\nDialogue: 0,0:05:55.10,0:05:59.16,Default,,0,0,0,,我们通过代换模型来证明\nDialogue: 0,0:06:00.50,0:06:01.96,Default,,0,0,0,,它不占用空间\nDialogue: 0,0:06:01.96,0:06:02.94,Default,,0,0,0,,但我们并没有说清楚\nDialogue: 0,0:06:03.42,0:06:06.76,Default,,0,0,0,,机器是如何做到这一点的\nDialogue: 0,0:06:07.31,0:06:08.91,Default,,0,0,0,,这涉及到一些细节\nDialogue: 0,0:06:09.02,0:06:11.12,Default,,0,0,0,,比如参数是如何传递给过程的\nDialogue: 0,0:06:12.48,0:06:13.69,Default,,0,0,0,,这是我们在元循环求值器中\nDialogue: 0,0:06:13.71,0:06:15.34,Default,,0,0,0,,没有看到的\nDialogue: 0,0:06:15.36,0:06:17.40,Default,,0,0,0,,完全是因为在所实现的Lisp中\nDialogue: 0,0:06:17.42,0:06:19.20,Default,,0,0,0,,把参数传递给过程的方式\nDialogue: 0,0:06:19.70,0:06:20.59,Default,,0,0,0,,取决于\nDialogue: 0,0:06:21.02,0:06:23.50,Default,,0,0,0,,外部Lisp的传参方式\nDialogue: 0,0:06:25.87,0:06:29.02,Default,,0,0,0,,但现在 这一点将变得非常明确\nDialogue: 0,0:06:30.74,0:06:31.12,Default,,0,0,0,,好\nDialogue: 0,0:06:31.23,0:06:34.30,Default,,0,0,0,,在开始研究求值器之前\nDialogue: 0,0:06:34.36,0:06:35.53,Default,,0,0,0,,我先让你们感受一下\nDialogue: 0,0:06:35.55,0:06:37.00,Default,,0,0,0,,一个完整Lisp系统是怎么样的\nDialogue: 0,0:06:37.60,0:06:39.36,Default,,0,0,0,,这样你就可以知道 我们要讨论哪部分\nDialogue: 0,0:06:39.40,0:06:40.81,Default,,0,0,0,,不讨论哪些部分\nDialogue: 0,0:06:43.18,0:06:47.42,Default,,0,0,0,,首先 这里有一个快乐的Lisp用户\nDialogue: 0,0:06:48.67,0:06:52.65,Default,,0,0,0,,他正在和一个叫做读取器的东西交流\nDialogue: 0,0:07:00.36,0:07:01.53,Default,,0,0,0,,读取器的工作是\nDialogue: 0,0:07:01.95,0:07:13.23,Default,,0,0,0,,读取用户输入的字符串\nDialogue: 0,0:07:14.17,0:07:16.62,Default,,0,0,0,,把它们转化成一种称作\nDialogue: 0,0:07:17.20,0:07:19.37,Default,,0,0,0,,表结构内存的数据结构\nDialogue: 0,0:07:30.00,0:07:31.72,Default,,0,0,0,,读取器会读取--\nDialogue: 0,0:07:32.65,0:07:33.95,Default,,0,0,0,,你敲出来的符号、括号\nDialogue: 0,0:07:34.48,0:07:37.12,Default,,0,0,0,,A和B、1和3这些东西\nDialogue: 0,0:07:37.18,0:07:39.04,Default,,0,0,0,,并把它们变成表结构\nDialogue: 0,0:07:39.15,0:07:40.54,Default,,0,0,0,,变成序对、指针等等\nDialogue: 0,0:07:42.35,0:07:43.92,Default,,0,0,0,,所以当求值器运行的时候\nDialogue: 0,0:07:43.93,0:07:45.10,Default,,0,0,0,,环境里已经不存在原始字符了\nDialogue: 0,0:07:45.85,0:07:48.16,Default,,0,0,0,,当然 在更现代的Lisp系统中\nDialogue: 0,0:07:49.00,0:07:50.44,Default,,0,0,0,,可能还有一大团东西\nDialogue: 0,0:07:50.44,0:07:52.17,Default,,0,0,0,,存在于在读取器和用户之间\nDialogue: 0,0:07:52.41,0:07:54.52,Default,,0,0,0,,最顶层首先是视窗系统\nDialogue: 0,0:07:54.77,0:07:56.03,Default,,0,0,0,,以及鼠标之类的东西\nDialogue: 0,0:07:56.28,0:07:58.20,Default,,0,0,0,,但从概念上来说 都是在输入字符\nDialogue: 0,0:07:59.93,0:08:04.32,Default,,0,0,0,,总之 读取器把它们都变成指针\nDialogue: 0,0:08:05.56,0:08:07.28,Default,,0,0,0,,指向内存中的对象\nDialogue: 0,0:08:08.27,0:08:10.94,Default,,0,0,0,,这是求值器的所能看到的东西\nDialogue: 0,0:08:15.55,0:08:16.04,Default,,0,0,0,,明白吗？\nDialogue: 0,0:08:17.02,0:08:18.88,Default,,0,0,0,,求值器有一些辅助函数\nDialogue: 0,0:08:19.78,0:08:23.16,Default,,0,0,0,,包括你需要的所有基本运算\nDialogue: 0,0:08:23.16,0:08:24.91,Default,,0,0,0,,也就是说这里另有一盒子东西\nDialogue: 0,0:08:28.40,0:08:30.25,Default,,0,0,0,,比如浮点单元\nDialogue: 0,0:08:32.22,0:08:34.40,Default,,0,0,0,,或者其它类似的东西来执行这些运算\nDialogue: 0,0:08:35.39,0:08:37.68,Default,,0,0,0,,如果你需要支持更多的基本运算\nDialogue: 0,0:08:37.71,0:08:39.02,Default,,0,0,0,,你就实现更多的运算符执行器\nDialogue: 0,0:08:39.05,0:08:40.48,Default,,0,0,0,,但它们和求值器都是分离的\nDialogue: 0,0:08:42.08,0:08:43.77,Default,,0,0,0,,求值器最终算出结果\nDialogue: 0,0:08:45.16,0:08:46.76,Default,,0,0,0,,并且把它们告诉打印程序\nDialogue: 0,0:08:50.62,0:08:52.01,Default,,0,0,0,,现在 打印程序的任务就是\nDialogue: 0,0:08:52.01,0:08:54.54,Default,,0,0,0,,从求值器取得这个表结构\nDialogue: 0,0:08:55.39,0:08:56.99,Default,,0,0,0,,再把它们变回字符\nDialogue: 0,0:09:01.85,0:09:04.07,Default,,0,0,0,,然后通过某种界面\nDialogue: 0,0:09:04.28,0:09:05.66,Default,,0,0,0,,展示给用户\nDialogue: 0,0:09:08.05,0:09:11.23,Default,,0,0,0,,那么 今天我们要讨论的是这个求值器\nDialogue: 0,0:09:12.67,0:09:15.20,Default,,0,0,0,,基本运算和Lisp没有什么特别的关系\nDialogue: 0,0:09:15.20,0:09:18.14,Default,,0,0,0,,它们只取决于你怎么实现基本运算\nDialogue: 0,0:09:19.36,0:09:22.18,Default,,0,0,0,,读取器和打印程序实际上很复杂\nDialogue: 0,0:09:22.18,0:09:23.55,Default,,0,0,0,,但是我们不去讨论它们\nDialogue: 0,0:09:24.68,0:09:27.10,Default,,0,0,0,,从字符构建表的过程中\nDialogue: 0,0:09:27.10,0:09:28.92,Default,,0,0,0,,它们需要处理很多细节\nDialogue: 0,0:09:29.90,0:09:31.18,Default,,0,0,0,,说来话长\nDialogue: 0,0:09:31.18,0:09:32.32,Default,,0,0,0,,我们就不讨论它了\nDialogue: 0,0:09:32.49,0:09:33.69,Default,,0,0,0,,关于表结构内存\nDialogue: 0,0:09:34.36,0:09:35.63,Default,,0,0,0,,我们下次再来讨论\nDialogue: 0,0:09:36.93,0:09:39.72,Default,,0,0,0,,那么去除了读取和打印的细节\nDialogue: 0,0:09:40.12,0:09:41.71,Default,,0,0,0,,关于这个求值器\nDialogue: 0,0:09:41.72,0:09:43.05,Default,,0,0,0,,所剩下的唯一谜团\nDialogue: 0,0:09:43.25,0:09:45.85,Default,,0,0,0,,几乎就只有怎么在传统内存上构建表结构了\nDialogue: 0,0:09:46.65,0:09:48.20,Default,,0,0,0,,不过我们把那也放到下次来讨论\nDialogue: 0,0:09:50.58,0:09:51.04,Default,,0,0,0,,好\nDialogue: 0,0:09:53.34,0:09:56.11,Default,,0,0,0,,那么 我们先来看看这个求值器\nDialogue: 0,0:09:56.20,0:09:58.32,Default,,0,0,0,,我将要展示的这个求值器\nDialogue: 0,0:09:58.49,0:10:01.12,Default,,0,0,0,,我想 它并没有什么特别的\nDialogue: 0,0:10:01.15,0:10:04.56,Default,,0,0,0,,它只是一台专门运行Lisp的寄存器机器\nDialogue: 0,0:10:04.81,0:10:06.09,Default,,0,0,0,,它有七个寄存器\nDialogue: 0,0:10:07.88,0:10:09.26,Default,,0,0,0,,这是它的七个寄存器\nDialogue: 0,0:10:09.89,0:10:12.38,Default,,0,0,0,,这个寄存器叫EXP\nDialogue: 0,0:10:14.12,0:10:15.53,Default,,0,0,0,,它的任务是存放\nDialogue: 0,0:10:16.36,0:10:18.03,Default,,0,0,0,,将要被求值的表达式\nDialogue: 0,0:10:18.37,0:10:19.80,Default,,0,0,0,,具体来说\nDialogue: 0,0:10:20.38,0:10:21.64,Default,,0,0,0,,它存放的是一个指针\nDialogue: 0,0:10:22.03,0:10:23.55,Default,,0,0,0,,指针指向存放着求值的表达式\nDialogue: 0,0:10:23.56,0:10:25.32,Default,,0,0,0,,的一处表结构内存\nDialogue: 0,0:10:26.55,0:10:27.82,Default,,0,0,0,,还有一个叫做ENV的寄存器\nDialogue: 0,0:10:28.88,0:10:30.28,Default,,0,0,0,,它存放着环境\nDialogue: 0,0:10:31.00,0:10:33.05,Default,,0,0,0,,也就是表达式的求值环境\nDialogue: 0,0:10:34.07,0:10:35.02,Default,,0,0,0,,同样的 这也是一个指针\nDialogue: 0,0:10:35.02,0:10:36.75,Default,,0,0,0,,环境是一种数据结构\nDialogue: 0,0:10:38.24,0:10:40.14,Default,,0,0,0,,这个叫做FUN的寄存器--\nDialogue: 0,0:10:40.75,0:10:42.54,Default,,0,0,0,,当你在应用一个过程时\nDialogue: 0,0:10:42.57,0:10:43.96,Default,,0,0,0,,它会存放这个过程\nDialogue: 0,0:10:44.56,0:10:46.24,Default,,0,0,0,,还有寄存器ARGL\nDialogue: 0,0:10:47.36,0:10:49.34,Default,,0,0,0,,它存放的是已求值的参数\nDialogue: 0,0:10:50.54,0:10:51.60,Default,,0,0,0,,从这里开始你能看到\nDialogue: 0,0:10:51.63,0:10:53.14,Default,,0,0,0,,求值器的基本构造\nDialogue: 0,0:10:53.14,0:10:54.49,Default,,0,0,0,,回忆一下它是怎么工作的\nDialogue: 0,0:10:54.49,0:10:56.62,Default,,0,0,0,,对这一块输入表达式和环境\nDialogue: 0,0:10:57.67,0:10:59.71,Default,,0,0,0,,而这一块接收函数\nDialogue: 0,0:10:59.74,0:11:02.14,Default,,0,0,0,,或者说 过程以及参数\nDialogue: 0,0:11:03.48,0:11:06.30,Default,,0,0,0,,EVAL-APPLY循环使用这些寄存器工作\nDialogue: 0,0:11:07.40,0:11:09.69,Default,,0,0,0,,所以这些是EVAL-APPLY的基本组成部分\nDialogue: 0,0:11:10.20,0:11:10.99,Default,,0,0,0,,还有一些别的东西\nDialogue: 0,0:11:11.00,0:11:11.61,Default,,0,0,0,,比如CONTINUE寄存器\nDialogue: 0,0:11:11.61,0:11:15.34,Default,,0,0,0,,你之前已经见过CONTINUE寄存器\nDialogue: 0,0:11:15.34,0:11:18.04,Default,,0,0,0,,是如何实现递归以及栈操作的\nDialogue: 0,0:11:18.94,0:11:20.68,Default,,0,0,0,,还有个寄存器用来存放\nDialogue: 0,0:11:20.94,0:11:22.52,Default,,0,0,0,,某个求值的结果\nDialogue: 0,0:11:24.14,0:11:24.89,Default,,0,0,0,,然后 除了这些以外\nDialogue: 0,0:11:24.89,0:11:26.43,Default,,0,0,0,,还有一个临时寄存器\nDialogue: 0,0:11:26.70,0:11:27.29,Default,,0,0,0,,它就是UNEV\nDialogue: 0,0:11:27.29,0:11:29.04,Default,,0,0,0,,一般来讲 在求值器中\nDialogue: 0,0:11:29.28,0:11:32.72,Default,,0,0,0,,它是用来存放正在求值的表达式\nDialogue: 0,0:11:32.89,0:11:33.95,Default,,0,0,0,,的临时部分\nDialogue: 0,0:11:33.95,0:11:35.72,Default,,0,0,0,,就是那些尚未求值的部分\nDialogue: 0,0:11:36.97,0:11:39.82,Default,,0,0,0,,那么 这就是我的七寄存器机器\nDialogue: 0,0:11:40.96,0:11:42.98,Default,,0,0,0,,当然 你可能想造一台\nDialogue: 0,0:11:42.98,0:11:44.96,Default,,0,0,0,,有更多寄存器的机器 来取得更好性能\nDialogue: 0,0:11:44.97,0:11:47.05,Default,,0,0,0,,但我们这个只是一台小型机器\nDialogue: 0,0:11:48.48,0:11:49.58,Default,,0,0,0,,那么数据通路呢？\nDialogue: 0,0:11:49.78,0:11:53.66,Default,,0,0,0,,这台机器有很多专为Lisp设计的运算\nDialogue: 0,0:11:55.10,0:11:58.08,Default,,0,0,0,,这里有几条典型的数据通路\nDialogue: 0,0:12:00.12,0:12:01.04,Default,,0,0,0,,其中一条可能是\nDialogue: 0,0:12:01.37,0:12:03.40,Default,,0,0,0,,将EXP寄存器的值\nDialogue: 0,0:12:03.40,0:12:04.80,Default,,0,0,0,,赋给VAL寄存器\nDialogue: 0,0:12:05.71,0:12:08.01,Default,,0,0,0,,用我们之前的数据通路图来说\nDialogue: 0,0:12:08.03,0:12:10.81,Default,,0,0,0,,就是一条箭头上的小按钮\nDialogue: 0,0:12:11.90,0:12:13.13,Default,,0,0,0,,这还有一个更复杂的\nDialogue: 0,0:12:13.69,0:12:14.80,Default,,0,0,0,,它判断\nDialogue: 0,0:12:15.23,0:12:19.58,Default,,0,0,0,,如果EXP寄存器的内容是COND语句\nDialogue: 0,0:12:20.49,0:12:22.72,Default,,0,0,0,,那么这里就会跳转到EV-COND标号处\nDialogue: 0,0:12:23.80,0:12:26.23,Default,,0,0,0,,你可以想象出很多种实现它的方法\nDialogue: 0,0:12:26.23,0:12:28.36,Default,,0,0,0,,你可以把这个判断看作是\nDialogue: 0,0:12:28.36,0:12:29.98,Default,,0,0,0,,一个特殊意图的子过程\nDialogue: 0,0:12:30.60,0:12:33.95,Default,,0,0,0,,而条件被表示成某种数据抽象\nDialogue: 0,0:12:33.96,0:12:36.00,Default,,0,0,0,,你在这个层面上不用考虑它\nDialogue: 0,0:12:36.61,0:12:37.98,Default,,0,0,0,,那么它可以用子过程实现\nDialogue: 0,0:12:37.98,0:12:40.67,Default,,0,0,0,,如果机器通过硬件来判断表达式类型\nDialogue: 0,0:12:40.90,0:12:44.04,Default,,0,0,0,,那么某些特定比特就代表了COND语句\nDialogue: 0,0:12:45.35,0:12:46.41,Default,,0,0,0,,有很多种实现办法\nDialogue: 0,0:12:46.41,0:12:48.48,Default,,0,0,0,,它们都低于我们关注的这一层抽象\nDialogue: 0,0:12:50.19,0:12:51.71,Default,,0,0,0,,然后还有另一种操作\nDialogue: 0,0:12:51.71,0:12:53.24,Default,,0,0,0,,以及其它很多操作\nDialogue: 0,0:12:53.24,0:12:56.65,Default,,0,0,0,,把EXP的第一个子句赋值给EXP\nDialogue: 0,0:12:56.84,0:12:58.89,Default,,0,0,0,,这可能是处理COND语句的一部分\nDialogue: 0,0:12:59.26,0:13:01.80,Default,,0,0,0,,同样 FIRST-SELECTOR这个选择子\nDialogue: 0,0:13:03.07,0:13:04.48,Default,,0,0,0,,我们也不需要关心它的细节\nDialogue: 0,0:13:04.49,0:13:06.46,Default,,0,0,0,,同样可以把那也看成一个子过程\nDialogue: 0,0:13:06.46,0:13:07.90,Default,,0,0,0,,用来进行一些表操作\nDialogue: 0,0:13:08.22,0:13:09.18,Default,,0,0,0,,或者你也可以想象成\nDialogue: 0,0:13:09.18,0:13:10.73,Default,,0,0,0,,一个直接构建在硬件中的东西\nDialogue: 0,0:13:12.17,0:13:13.71,Default,,0,0,0,,我之所以强调\nDialogue: 0,0:13:14.03,0:13:15.22,Default,,0,0,0,,你可以把它想象成硬件直接实现\nDialogue: 0,0:13:15.22,0:13:17.80,Default,,0,0,0,,是因为尽管有很多的运算\nDialogue: 0,0:13:18.36,0:13:19.74,Default,,0,0,0,,但也它们的数量也是固定的\nDialogue: 0,0:13:20.12,0:13:21.80,Default,,0,0,0,,我记不清有多少 大概有150个\nDialogue: 0,0:13:22.37,0:13:25.39,Default,,0,0,0,,所以假设用硬件实现它们是合理的\nDialogue: 0,0:13:26.41,0:13:27.68,Default,,0,0,0,,而这一条更加复杂\nDialogue: 0,0:13:28.27,0:13:29.47,Default,,0,0,0,,你会发现 这条涉及到\nDialogue: 0,0:13:29.47,0:13:31.10,Default,,0,0,0,,查找变量的值\nDialogue: 0,0:13:31.50,0:13:33.28,Default,,0,0,0,,它会查找某条表达式中\nDialogue: 0,0:13:33.45,0:13:36.91,Default,,0,0,0,,某个变量的值\nDialogue: 0,0:13:36.99,0:13:38.52,Default,,0,0,0,,并赋值给VAL寄存器\nDialogue: 0,0:13:39.18,0:13:40.30,Default,,0,0,0,,在本例中 也就是\nDialogue: 0,0:13:40.33,0:13:42.00,Default,,0,0,0,,在某个环境中查找变量\nDialogue: 0,0:13:42.80,0:13:44.68,Default,,0,0,0,,然后这个操作\nDialogue: 0,0:13:45.21,0:13:47.50,Default,,0,0,0,,会搜索整个环境结构\nDialogue: 0,0:13:47.52,0:13:48.97,Default,,0,0,0,,无论环境是如何表示的\nDialogue: 0,0:13:49.37,0:13:50.91,Default,,0,0,0,,并查找该变量\nDialogue: 0,0:13:52.17,0:13:53.95,Default,,0,0,0,,同样 它也不在我们思考的\nDialogue: 0,0:13:53.96,0:13:54.86,Default,,0,0,0,,的抽象层面上\nDialogue: 0,0:13:54.89,0:13:57.30,Default,,0,0,0,,它需要处理的细节是\nDialogue: 0,0:13:57.55,0:13:59.44,Default,,0,0,0,,用来表示环境的数据结构\nDialogue: 0,0:14:00.07,0:14:01.21,Default,,0,0,0,,但是不管怎么说\nDialogue: 0,0:14:01.31,0:14:03.47,Default,,0,0,0,,这就是这台寄存器机器的\nDialogue: 0,0:14:04.11,0:14:06.08,Default,,0,0,0,,有穷数量的固定操作\nDialogue: 0,0:14:08.50,0:14:11.60,Default,,0,0,0,,那么 它的整体结构是什么样子的？\nDialogue: 0,0:14:11.72,0:14:13.23,Default,,0,0,0,,这有几个典型的运算\nDialogue: 0,0:14:14.76,0:14:16.33,Default,,0,0,0,,想一想 我们要做什么\nDialogue: 0,0:14:16.44,0:14:18.40,Default,,0,0,0,,我们需要把元循环求值器\nDialogue: 0,0:14:20.43,0:14:22.76,Default,,0,0,0,,这就是元循环求值器的一部分\nDialogue: 0,0:14:22.76,0:14:26.89,Default,,0,0,0,,这是书中使用抽象代码的版本\nDialogue: 0,0:14:28.22,0:14:31.53,Default,,0,0,0,,它和Gerry教授给你们展示的有些不同\nDialogue: 0,0:14:33.50,0:14:35.10,Default,,0,0,0,,关于求值器\nDialogue: 0,0:14:35.13,0:14:37.87,Default,,0,0,0,,主要需要记住的是\nDialogue: 0,0:14:37.87,0:14:40.96,Default,,0,0,0,,它是某种针对表达式类型的分情况分析\nDialogue: 0,0:14:43.76,0:14:45.90,Default,,0,0,0,,看它是否为自求值的 或被引用的\nDialogue: 0,0:14:45.92,0:14:46.86,Default,,0,0,0,,或是别的什么\nDialogue: 0,0:14:48.56,0:14:50.57,Default,,0,0,0,,而在大部分情况下\nDialogue: 0,0:14:50.86,0:14:52.96,Default,,0,0,0,,它处理的是一个过程应用\nDialogue: 0,0:14:53.55,0:14:55.36,Default,,0,0,0,,那么里面有一些技巧性的递归过程\nDialogue: 0,0:14:55.75,0:14:59.36,Default,,0,0,0,,首先 EVAL要调用它自己\nDialogue: 0,0:14:59.79,0:15:01.45,Default,,0,0,0,,来求值运算符以及\nDialogue: 0,0:15:02.14,0:15:04.04,Default,,0,0,0,,所有的运算对象\nDialogue: 0,0:15:05.88,0:15:07.40,Default,,0,0,0,,因此这些标红线的地方\nDialogue: 0,0:15:07.63,0:15:09.28,Default,,0,0,0,,就是某种在语法树上的递归\nDialogue: 0,0:15:10.94,0:15:12.27,Default,,0,0,0,,这是很简单的递归\nDialogue: 0,0:15:12.27,0:15:14.44,Default,,0,0,0,,只是EVAL在递归地遍历语法树\nDialogue: 0,0:15:14.75,0:15:15.53,Default,,0,0,0,,然后在求值器中\nDialogue: 0,0:15:15.53,0:15:16.46,Default,,0,0,0,,有一个复杂的递归\nDialogue: 0,0:15:16.49,0:15:17.92,Default,,0,0,0,,由绿线到红线的递归\nDialogue: 0,0:15:18.00,0:15:19.66,Default,,0,0,0,,由EVAL调用APPLY\nDialogue: 0,0:15:22.47,0:15:26.45,Default,,0,0,0,,也就是把过程调用\nDialogue: 0,0:15:26.45,0:15:28.72,Default,,0,0,0,,归约为了 将过程应用在\nDialogue: 0,0:15:28.94,0:15:29.93,Default,,0,0,0,,实参表上\nDialogue: 0,0:15:30.37,0:15:31.76,Default,,0,0,0,,然后请看APPLY\nDialogue: 0,0:15:34.77,0:15:36.67,Default,,0,0,0,,APPLY需要过程PROC和参数ARGS\nDialogue: 0,0:15:37.65,0:15:39.45,Default,,0,0,0,,一般情况下\nDialogue: 0,0:15:39.48,0:15:40.81,Default,,0,0,0,,PROC都是一个复合过程\nDialogue: 0,0:15:41.05,0:15:42.19,Default,,0,0,0,,随着APPLY不断被调用\nDialogue: 0,0:15:42.25,0:15:43.15,Default,,0,0,0,,绿线处会调用红线处\nDialogue: 0,0:15:43.34,0:15:46.44,Default,,0,0,0,,APPLY被调用并再次调用EVAL\nDialogue: 0,0:15:48.17,0:15:49.79,Default,,0,0,0,,EVAL会求值过程体\nDialogue: 0,0:15:50.24,0:15:52.59,Default,,0,0,0,,基于一个扩展了的环境\nDialogue: 0,0:15:53.69,0:15:55.28,Default,,0,0,0,,这个环境通过将过程的形式参数\nDialogue: 0,0:15:55.48,0:15:56.92,Default,,0,0,0,,与实际参数绑定起来而得\nDialogue: 0,0:15:59.62,0:16:00.62,Default,,0,0,0,,而对于最基本的情况\nDialogue: 0,0:16:00.64,0:16:02.52,Default,,0,0,0,,它会调用PRIMITIVE-APPLY过程\nDialogue: 0,0:16:02.73,0:16:04.70,Default,,0,0,0,,而那又不是求值器的工作了\nDialogue: 0,0:16:05.98,0:16:07.47,Default,,0,0,0,,那么像这样从红到绿\nDialogue: 0,0:16:07.47,0:16:08.40,Default,,0,0,0,,又到红又到绿\nDialogue: 0,0:16:09.79,0:16:12.72,Default,,0,0,0,,这就是EVAL-APPLY循环\nDialogue: 0,0:16:14.06,0:16:15.74,Default,,0,0,0,,这就是我们在求值器中\nDialogue: 0,0:16:16.19,0:16:17.72,Default,,0,0,0,,想要看到的东西\nDialogue: 0,0:16:19.69,0:16:21.07,Default,,0,0,0,,这样 你不会惊异于\nDialogue: 0,0:16:21.07,0:16:23.52,Default,,0,0,0,,这个求值器的两大部分\nDialogue: 0,0:16:25.34,0:16:27.04,Default,,0,0,0,,对应于EVAL-APPLY\nDialogue: 0,0:16:27.47,0:16:29.44,Default,,0,0,0,,一个部分叫EVAL-DISPATCH\nDialogue: 0,0:16:29.60,0:16:31.20,Default,,0,0,0,,另一部分叫做APPLY-DISPATCH\nDialogue: 0,0:16:32.00,0:16:34.09,Default,,0,0,0,,在我们关注代码细节之前\nDialogue: 0,0:16:34.20,0:16:35.76,Default,,0,0,0,,理解它们的方法就是\nDialogue: 0,0:16:36.09,0:16:39.02,Default,,0,0,0,,假设这些求值器的各个部分\nDialogue: 0,0:16:39.02,0:16:40.97,Default,,0,0,0,,和这个世界中其它的部分有一些约定\nDialogue: 0,0:16:41.87,0:16:43.18,Default,,0,0,0,,在进入这些肮脏的细节前\nDialogue: 0,0:16:43.20,0:16:45.50,Default,,0,0,0,,它们在外部做了什么？\nDialogue: 0,0:16:45.78,0:16:49.32,Default,,0,0,0,,针对EVAL-DISPATCH的约定\nDialogue: 0,0:16:50.01,0:16:51.40,Default,,0,0,0,,还记得吗 它对应的是EVAL\nDialogue: 0,0:16:51.55,0:16:54.10,Default,,0,0,0,,它要在环境中求值一个表达式\nDialogue: 0,0:16:54.10,0:16:55.88,Default,,0,0,0,,那么 这部分要做的就是\nDialogue: 0,0:16:56.52,0:16:58.68,Default,,0,0,0,,EVAL-DISPATCH会假设当你调用它的时候\nDialogue: 0,0:16:59.68,0:17:01.48,Default,,0,0,0,,你想要求值的表达式\nDialogue: 0,0:17:01.48,0:17:02.52,Default,,0,0,0,,就存放在EXP寄存器中\nDialogue: 0,0:17:03.64,0:17:07.39,Default,,0,0,0,,而求值所基于的环境\nDialogue: 0,0:17:07.45,0:17:09.05,Default,,0,0,0,,则存放在ENV环境中\nDialogue: 0,0:17:09.56,0:17:10.67,Default,,0,0,0,,而CONTINUE寄存器用来指示\nDialogue: 0,0:17:10.84,0:17:12.46,Default,,0,0,0,,当求值完成后\nDialogue: 0,0:17:12.52,0:17:13.92,Default,,0,0,0,,机器需要去向何方\nDialogue: 0,0:17:17.28,0:17:19.18,Default,,0,0,0,,EVAL-DISPATCH的约定实际上就是\nDialogue: 0,0:17:19.28,0:17:21.26,Default,,0,0,0,,它会执行实际的求值\nDialogue: 0,0:17:21.40,0:17:22.46,Default,,0,0,0,,并且在求值结束后\nDialogue: 0,0:17:23.28,0:17:25.63,Default,,0,0,0,,它会转到由CONTINUE寄存器指定的位置\nDialogue: 0,0:17:26.61,0:17:29.16,Default,,0,0,0,,求值的结果会存放在VAL寄存器中\nDialogue: 0,0:17:29.82,0:17:30.96,Default,,0,0,0,,需要提醒的是\nDialogue: 0,0:17:30.99,0:17:32.91,Default,,0,0,0,,它对其余的寄存器\nDialogue: 0,0:17:32.96,0:17:34.60,Default,,0,0,0,,不做任何承诺\nDialogue: 0,0:17:35.23,0:17:36.81,Default,,0,0,0,,其它所有的寄存器都可能被修改\nDialogue: 0,0:17:37.49,0:17:40.14,Default,,0,0,0,,那么这是一部分\nDialogue: 0,0:17:41.55,0:17:43.48,Default,,0,0,0,,这些部分一块构成了APPLY-DISPATCH\nDialogue: 0,0:17:43.52,0:17:44.92,Default,,0,0,0,,它们对应了APPLY\nDialogue: 0,0:17:46.09,0:17:48.43,Default,,0,0,0,,用来把一个过程应用在一些参数上\nDialogue: 0,0:17:48.73,0:17:51.43,Default,,0,0,0,,因此它假设ARGL寄存器\nDialogue: 0,0:17:51.68,0:17:53.77,Default,,0,0,0,,存放着求值后的参数列表\nDialogue: 0,0:17:54.54,0:17:55.96,Default,,0,0,0,,FUN寄存器存放着那个过程\nDialogue: 0,0:17:57.22,0:17:58.83,Default,,0,0,0,,它们对应于元循环求值器中的\nDialogue: 0,0:17:58.94,0:18:01.36,Default,,0,0,0,,参数应用部分\nDialogue: 0,0:18:03.97,0:18:06.04,Default,,0,0,0,,在我们的这个求值器中\nDialogue: 0,0:18:06.06,0:18:07.58,Default,,0,0,0,,我们APPLY时采用的约定是\nDialogue: 0,0:18:07.72,0:18:08.97,Default,,0,0,0,,当APPLY完成后--\nDialogue: 0,0:18:09.47,0:18:11.20,Default,,0,0,0,,机器应该跳转到\nDialogue: 0,0:18:11.79,0:18:13.45,Default,,0,0,0,,的下一个地方应该是\nDialogue: 0,0:18:13.55,0:18:15.92,Default,,0,0,0,,APPLY-DISPATCH被调用时的栈顶元素\nDialogue: 0,0:18:17.07,0:18:21.24,Default,,0,0,0,,这只是针对这台机器的约定\nDialogue: 0,0:18:21.84,0:18:23.70,Default,,0,0,0,,现在已经给出了APPLY的所有约定\nDialogue: 0,0:18:23.93,0:18:25.37,Default,,0,0,0,,它会去执行应用\nDialogue: 0,0:18:25.54,0:18:27.85,Default,,0,0,0,,这个应用的结果将会保存在VAL寄存器中\nDialogue: 0,0:18:28.89,0:18:29.95,Default,,0,0,0,,栈会被弹出\nDialogue: 0,0:18:31.12,0:18:31.66,Default,,0,0,0,,同样的\nDialogue: 0,0:18:31.71,0:18:34.03,Default,,0,0,0,,其它所有寄存器的内容都可能被修改\nDialogue: 0,0:18:34.84,0:18:37.82,Default,,0,0,0,,那么 这就是这台机器的基本结构\nDialogue: 0,0:18:38.99,0:18:41.50,Default,,0,0,0,,我们先课间休息一下\nDialogue: 0,0:18:41.52,0:18:42.70,Default,,0,0,0,,然后再来研究一个真实的例子\nDialogue: 0,0:18:43.53,0:19:08.11,Default,,0,0,0,,[音乐]\nDialogue: 0,0:19:08.14,0:19:13.47,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:19:33.10,0:19:35.87,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:19:35.87,0:19:40.38,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:19:40.38,0:19:45.29,Declare,,0,0,0,,{\\an2\\fad(500,500)}显式控制求值器\nDialogue: 0,0:19:47.85,0:19:49.95,Default,,0,0,0,,现在 我们来研究一下这台寄存器机器\nDialogue: 0,0:19:50.41,0:19:51.77,Default,,0,0,0,,我们一步一步地跟进\nDialogue: 0,0:19:52.27,0:19:56.94,Default,,0,0,0,,具体到每一处细节\nDialogue: 0,0:19:57.07,0:19:58.52,Default,,0,0,0,,这样你就能完全具体地看到\nDialogue: 0,0:19:58.86,0:20:01.24,Default,,0,0,0,,表达式是如何求值的\nDialogue: 0,0:20:03.15,0:20:06.86,Default,,0,0,0,,那么我们从一个非常简单的表达式开始\nDialogue: 0,0:20:07.45,0:20:13.52,Default,,0,0,0,,我们要求值的表达式只有一个1\nDialogue: 0,0:20:18.77,0:20:20.40,Default,,0,0,0,,我们需要一个环境\nDialogue: 0,0:20:20.43,0:20:22.35,Default,,0,0,0,,因此我们假设某处有一个环境\nDialogue: 0,0:20:22.38,0:20:23.39,Default,,0,0,0,,我们把它记作E0\nDialogue: 0,0:20:30.06,0:20:34.56,Default,,0,0,0,,由于我们之后也要用到它\nDialogue: 0,0:20:35.62,0:20:37.04,Default,,0,0,0,,而且显然不需要任何东西\nDialogue: 0,0:20:37.07,0:20:37.93,Default,,0,0,0,,就可以求值1\nDialogue: 0,0:20:38.36,0:20:39.45,Default,,0,0,0,,但是为了方便以后引用\nDialogue: 0,0:20:39.45,0:20:40.94,Default,,0,0,0,,我们假设环境E0中有\nDialogue: 0,0:20:41.44,0:20:43.15,Default,,0,0,0,,X=3\nDialogue: 0,0:20:43.72,0:20:45.37,Default,,0,0,0,,Y=4\nDialogue: 0,0:20:48.27,0:20:48.78,Default,,0,0,0,,好吗？\nDialogue: 0,0:20:49.14,0:20:50.12,Default,,0,0,0,,现在 我们要做的就是\nDialogue: 0,0:20:50.51,0:20:54.59,Default,,0,0,0,,在这个环境中求值表达式1\nDialogue: 0,0:20:55.74,0:20:58.54,Default,,0,0,0,,这样 ENV寄存器就存放了一个指针\nDialogue: 0,0:20:59.65,0:21:01.04,Default,,0,0,0,,指向这个环境E0\nDialogue: 0,0:21:03.31,0:21:05.65,Default,,0,0,0,,那么我们来看它是怎么进行的\nDialogue: 0,0:21:05.65,0:21:07.26,Default,,0,0,0,,我要步步跟进代码\nDialogue: 0,0:21:08.26,0:21:10.00,Default,,0,0,0,,这样的话 我会充当控制器\nDialogue: 0,0:21:10.04,0:21:10.80,Default,,0,0,0,,现在我需要的是--\nDialogue: 0,0:21:11.02,0:21:12.49,Default,,0,0,0,,由于这台机器已经变得相当复杂\nDialogue: 0,0:21:12.98,0:21:16.83,Default,,0,0,0,,我需要一个小小的执行单元\nDialogue: 0,0:21:16.83,0:21:18.16,Default,,0,0,0,,那么请上我们的执行单元\nDialogue: 0,0:21:22.62,0:21:23.12,Default,,0,0,0,,好的\nDialogue: 0,0:21:28.59,0:21:29.96,Default,,0,0,0,,好 现在我们要开始了\nDialogue: 0,0:21:30.53,0:21:32.48,Default,,0,0,0,,我们要从EVAL-DISPATCH启动机器\nDialogue: 0,0:21:33.26,0:21:34.62,Default,,0,0,0,,这是整个过程的开始\nDialogue: 0,0:21:35.87,0:21:38.75,Default,,0,0,0,,EVAL-DISPATCH会查看表达式并进行分派\nDialogue: 0,0:21:39.32,0:21:40.06,Default,,0,0,0,,就像EVAL\nDialogue: 0,0:21:40.87,0:21:42.00,Default,,0,0,0,,先从第一句看起\nDialogue: 0,0:21:42.04,0:21:47.95,Default,,0,0,0,,先判断表达式是不是自求值的\nDialogue: 0,0:21:47.95,0:21:49.96,Default,,0,0,0,,SELF-EVALUATING?是我们放入机器的\nDialogue: 0,0:21:49.96,0:21:51.10,Default,,0,0,0,,一个抽象过程\nDialogue: 0,0:21:52.22,0:21:53.51,Default,,0,0,0,,它对于数字1来说为真\nDialogue: 0,0:21:53.64,0:21:55.52,Default,,0,0,0,,因此跳转的目的是EV-SELF-EVAL\nDialogue: 0,0:21:56.77,0:21:58.20,Default,,0,0,0,,那么我作为控制器\nDialogue: 0,0:21:58.22,0:21:59.55,Default,,0,0,0,,会去查看EV-SELF-EVAL\nDialogue: 0,0:22:00.06,0:22:01.07,Default,,0,0,0,,所以我们要跳到那里\nDialogue: 0,0:22:02.60,0:22:04.76,Default,,0,0,0,,EV-SELF-EAVL的代码是--\nDialogue: 0,0:22:06.54,0:22:09.90,Default,,0,0,0,,把EXP寄存器的值赋值给VAL寄存器\nDialogue: 0,0:22:15.24,0:22:16.51,Default,,0,0,0,,我遇到一个BUG\nDialogue: 0,0:22:17.93,0:22:20.59,Default,,0,0,0,,因为我初始化机器的时候没有做一件事情\nDialogue: 0,0:22:21.62,0:22:22.89,Default,,0,0,0,,也就是指定当它执行完毕后\nDialogue: 0,0:22:22.91,0:22:24.19,Default,,0,0,0,,应该做什么\nDialogue: 0,0:22:24.65,0:22:26.83,Default,,0,0,0,,所以在启动机器的时候\nDialogue: 0,0:22:27.37,0:22:29.85,Default,,0,0,0,,应该将CONTINUE寄存器设置为DONE\nDialogue: 0,0:22:31.18,0:22:33.26,Default,,0,0,0,,所以我们给VAL赋值\nDialogue: 0,0:22:33.37,0:22:35.56,Default,,0,0,0,,然后执行(GOTO (FETCH CONTINUE))\nDialogue: 0,0:22:35.63,0:22:36.56,Default,,0,0,0,,并且修改--\nDialogue: 0,0:22:38.09,0:22:38.60,Default,,0,0,0,,好\nDialogue: 0,0:22:40.00,0:22:41.16,Default,,0,0,0,,好 我们来看一个更复杂的\nDialogue: 0,0:22:42.16,0:22:43.45,Default,,0,0,0,,我们先重置机器\nDialogue: 0,0:22:44.86,0:22:50.88,Default,,0,0,0,,然后把X放入EXP寄存器中\nDialogue: 0,0:22:56.71,0:22:58.20,Default,,0,0,0,,重新从EVAL-DISPATCH开始\nDialogue: 0,0:22:59.61,0:23:01.69,Default,,0,0,0,,先检查它是自求值的么？\nDialogue: 0,0:23:01.69,0:23:02.03,Default,,0,0,0,,不是\nDialogue: 0,0:23:02.65,0:23:03.61,Default,,0,0,0,,它是变量吗\nDialogue: 0,0:23:04.63,0:23:05.02,Default,,0,0,0,,是的\nDialogue: 0,0:23:05.56,0:23:07.07,Default,,0,0,0,,我们跳转到EV-VARIABLE\nDialogue: 0,0:23:08.38,0:23:10.97,Default,,0,0,0,,它说：查找EXP寄存器中变量的值\nDialogue: 0,0:23:12.13,0:23:15.69,Default,,0,0,0,,并把它赋值给VAL寄存器\nDialogue: 0,0:23:21.23,0:23:22.91,Default,,0,0,0,,(GOTO (FETCH CONTINUE))\nDialogue: 0,0:23:23.96,0:23:24.48,Default,,0,0,0,,Sussman教授：DONE\nDialogue: 0,0:23:27.61,0:23:28.09,Default,,0,0,0,,Abelson教授：好\nDialogue: 0,0:23:29.31,0:23:30.76,Default,,0,0,0,,这些都是最基本的理念\nDialogue: 0,0:23:31.33,0:23:32.65,Default,,0,0,0,,这是这台机器上的简单运算\nDialogue: 0,0:23:32.68,0:23:35.07,Default,,0,0,0,,现在 我们来做些有意义的事情\nDialogue: 0,0:23:36.07,0:23:38.64,Default,,0,0,0,,我们看这条表达式\nDialogue: 0,0:23:43.58,0:23:47.93,Default,,0,0,0,,(+ X Y)\nDialogue: 0,0:23:49.69,0:23:51.28,Default,,0,0,0,,现在我们会看到\nDialogue: 0,0:23:52.41,0:23:54.01,Default,,0,0,0,,如何展开这些表达式树\nDialogue: 0,0:23:57.13,0:23:58.68,Default,,0,0,0,,我们再次从EVAL-DISPATCH开始\nDialogue: 0,0:24:04.61,0:24:05.80,Default,,0,0,0,,是自求值的吗？\nDialogue: 0,0:24:05.95,0:24:06.52,Default,,0,0,0,,不是\nDialogue: 0,0:24:06.70,0:24:07.71,Default,,0,0,0,,是变量吗？不是\nDialogue: 0,0:24:07.82,0:24:08.99,Default,,0,0,0,,它也不是我在这里\nDialogue: 0,0:24:08.99,0:24:10.12,Default,,0,0,0,,没有列出的特殊形式\nDialogue: 0,0:24:10.27,0:24:12.48,Default,,0,0,0,,比如引用、LAMBDA、SET! 等等\nDialogue: 0,0:24:12.48,0:24:13.08,Default,,0,0,0,,它都不是\nDialogue: 0,0:24:13.26,0:24:14.73,Default,,0,0,0,,它是一个过程应用\nDialogue: 0,0:24:15.88,0:24:17.42,Default,,0,0,0,,所以我们要跳转到EV-APPLICATION\nDialogue: 0,0:24:19.97,0:24:24.94,Default,,0,0,0,,回忆一下EV-APPLICATION要做什么\nDialogue: 0,0:24:25.58,0:24:28.19,Default,,0,0,0,,它先要求值运算符\nDialogue: 0,0:24:28.27,0:24:31.40,Default,,0,0,0,,然后求值运算对象\nDialogue: 0,0:24:32.36,0:24:34.30,Default,,0,0,0,,然后再进行应用\nDialogue: 0,0:24:35.06,0:24:36.09,Default,,0,0,0,,所以在我们开始之前\nDialogue: 0,0:24:36.94,0:24:37.88,Default,,0,0,0,,由于我们是严格按照代码来执行的\nDialogue: 0,0:24:37.88,0:24:38.88,Default,,0,0,0,,我们最好记住\nDialogue: 0,0:24:39.07,0:24:40.54,Default,,0,0,0,,在这个环境中的某处\nDialogue: 0,0:24:40.57,0:24:42.36,Default,,0,0,0,,连接到了另一个环境\nDialogue: 0,0:24:43.98,0:24:44.94,Default,,0,0,0,,其中符号'+\nDialogue: 0,0:24:45.72,0:24:49.16,Default,,0,0,0,,跟基本的加法过程绑定在了一起\nDialogue: 0,0:24:51.63,0:24:54.03,Default,,0,0,0,,这样 求值+时就不会导致“变量未定义”\nDialogue: 0,0:24:55.34,0:24:56.84,Default,,0,0,0,,现在我们来到了EV-APPLICATION\nDialogue: 0,0:24:59.85,0:25:04.32,Default,,0,0,0,,把EXP寄存器对应的运算对象\nDialogue: 0,0:25:04.92,0:25:06.89,Default,,0,0,0,,赋值给UNEV寄存器\nDialogue: 0,0:25:07.61,0:25:08.83,Default,,0,0,0,,这些是运算对象\nDialogue: 0,0:25:09.23,0:25:11.66,Default,,0,0,0,,UNEV这个临时寄存器\nDialogue: 0,0:25:11.68,0:25:12.59,Default,,0,0,0,,就是用来暂存它们的\nDialogue: 0,0:25:13.22,0:25:13.86,Default,,0,0,0,,Sussman教授：我正在赋值\nDialogue: 0,0:25:14.28,0:25:16.62,Default,,0,0,0,,Abelson教授：把运算符赋值给EXP寄存器\nDialogue: 0,0:25:18.07,0:25:20.09,Default,,0,0,0,,注意 现在我们已经修改了EXP中的表达式\nDialogue: 0,0:25:21.84,0:25:23.61,Default,,0,0,0,,但是我们需要的部分在UNEV中\nDialogue: 0,0:25:25.82,0:25:26.81,Default,,0,0,0,,现在 我们要准备好\nDialogue: 0,0:25:26.81,0:25:28.59,Default,,0,0,0,,去递归地求值运算符\nDialogue: 0,0:25:28.75,0:25:31.69,Default,,0,0,0,,把CONTINUE寄存器保存在栈上\nDialogue: 0,0:25:34.86,0:25:36.09,Default,,0,0,0,,保存ENV\nDialogue: 0,0:25:40.48,0:25:41.69,Default,,0,0,0,,保存UNEV\nDialogue: 0,0:25:49.53,0:25:54.64,Default,,0,0,0,,把标号EVAL-ARGS赋值给CONTINUE寄存器\nDialogue: 0,0:26:01.40,0:26:01.95,Default,,0,0,0,,我们做了什么\nDialogue: 0,0:26:01.95,0:26:04.38,Default,,0,0,0,,我们为递归调用做了必要的准备\nDialogue: 0,0:26:04.38,0:26:05.88,Default,,0,0,0,,我们要开始执行EVAL-DISPATCH\nDialogue: 0,0:26:06.28,0:26:08.83,Default,,0,0,0,,我们为递归调用EVAL-DISPATCH做好了准备\nDialogue: 0,0:26:10.23,0:26:10.86,Default,,0,0,0,,我们做了哪些事情\nDialogue: 0,0:26:11.02,0:26:13.64,Default,,0,0,0,,我们把之后要用到的东西\nDialogue: 0,0:26:14.48,0:26:15.98,Default,,0,0,0,,也就是UNEV中的运算对象\nDialogue: 0,0:26:16.36,0:26:18.99,Default,,0,0,0,,以及我们最终求值运算对象时\nDialogue: 0,0:26:19.16,0:26:20.72,Default,,0,0,0,,会用到的环境\nDialogue: 0,0:26:22.28,0:26:23.93,Default,,0,0,0,,以及我们最终想要去的位置\nDialogue: 0,0:26:23.95,0:26:25.07,Default,,0,0,0,,本例中 也就是DONE\nDialogue: 0,0:26:25.34,0:26:26.70,Default,,0,0,0,,我们把它们保存在栈上\nDialogue: 0,0:26:27.10,0:26:28.41,Default,,0,0,0,,我们之所以把它们保存在栈上\nDialogue: 0,0:26:28.43,0:26:30.67,Default,,0,0,0,,是因为EVAL-DISPATCH并不会保证\nDialogue: 0,0:26:30.94,0:26:32.54,Default,,0,0,0,,不会去修改这些寄存器\nDialogue: 0,0:26:33.55,0:26:35.02,Default,,0,0,0,,那么所有这些东西都存在了栈上\nDialogue: 0,0:26:35.02,0:26:36.91,Default,,0,0,0,,现在我们满足了EVAL-DISPATCH的约定\nDialogue: 0,0:26:37.38,0:26:38.75,Default,,0,0,0,,这是一条新的表达式\nDialogue: 0,0:26:38.78,0:26:40.04,Default,,0,0,0,,也就是+运算符\nDialogue: 0,0:26:41.07,0:26:41.95,Default,,0,0,0,,以及一个新的环境\nDialogue: 0,0:26:41.98,0:26:43.60,Default,,0,0,0,,尽管在本例中是同一个环境\nDialogue: 0,0:26:44.25,0:26:45.87,Default,,0,0,0,,以及在完成后要返回的位置\nDialogue: 0,0:26:45.87,0:26:46.91,Default,,0,0,0,,也就是EVAL-ARGS\nDialogue: 0,0:26:47.60,0:26:48.13,Default,,0,0,0,,这样就满足了\nDialogue: 0,0:26:48.13,0:26:49.68,Default,,0,0,0,,现在我们来执行EVAL-DISPATCH\nDialogue: 0,0:26:50.89,0:26:52.36,Default,,0,0,0,,我们回到了EVAL-DISPATCH\nDialogue: 0,0:26:53.05,0:26:54.40,Default,,0,0,0,,它不是自求值的\nDialogue: 0,0:26:54.44,0:26:55.47,Default,,0,0,0,,但它是一个变量\nDialogue: 0,0:26:56.32,0:26:58.06,Default,,0,0,0,,因此我们最好跳转到EV-VARIABLE\nDialogue: 0,0:26:59.79,0:27:02.65,Default,,0,0,0,,EV-VARIABLE首先要给VAL赋值\nDialogue: 0,0:27:02.70,0:27:06.33,Default,,0,0,0,,查找表达式中变量的值\nDialogue: 0,0:27:08.49,0:27:10.75,Default,,0,0,0,,那么VAL寄存器中应该是基本的加法运算\nDialogue: 0,0:27:13.37,0:27:15.16,Default,,0,0,0,,然后(GOTO (FETCH CONTINUE))\nDialogue: 0,0:27:15.23,0:27:16.11,Default,,0,0,0,,Sussman教授：它是EVAL-ARGS\nDialogue: 0,0:27:16.20,0:27:18.73,Default,,0,0,0,,Abelson教授：现在它是EVAL-ARGS而不是DONE了\nDialogue: 0,0:27:19.42,0:27:21.26,Default,,0,0,0,,然后我们来到EVAL-ARGS\nDialogue: 0,0:27:22.16,0:27:23.02,Default,,0,0,0,,看看它要做什么\nDialogue: 0,0:27:23.07,0:27:24.84,Default,,0,0,0,,我们要恢复之前保存的东西\nDialogue: 0,0:27:25.20,0:27:26.57,Default,,0,0,0,,因此调用(RESTORE UNEV)\nDialogue: 0,0:27:29.21,0:27:31.69,Default,,0,0,0,,注意 这里并不是必要的\nDialogue: 0,0:27:31.74,0:27:32.90,Default,,0,0,0,,但通常来说都会有这么一步\nDialogue: 0,0:27:32.90,0:27:35.16,Default,,0,0,0,,它可以是任意的求值过程\nDialogue: 0,0:27:35.43,0:27:36.70,Default,,0,0,0,,恢复ENV寄存器\nDialogue: 0,0:27:47.87,0:27:52.04,Default,,0,0,0,,然后把(FETCH VAL)赋值给FUN\nDialogue: 0,0:27:59.95,0:28:02.81,Default,,0,0,0,,现在我们要开始求值参数了\nDialogue: 0,0:28:04.34,0:28:06.48,Default,,0,0,0,,首先 我们最好把FUN寄存器保存起来\nDialogue: 0,0:28:07.42,0:28:10.62,Default,,0,0,0,,因为求值过程中可能发生任何事情\nDialogue: 0,0:28:15.33,0:28:16.88,Default,,0,0,0,,我们初始化参数列表\nDialogue: 0,0:28:16.91,0:28:19.29,Default,,0,0,0,,给ARGL赋值一个空的参数列表\nDialogue: 0,0:28:20.88,0:28:22.17,Default,,0,0,0,,然后跳转到EVAL-ARG-LOOP\nDialogue: 0,0:28:24.86,0:28:26.27,Default,,0,0,0,,在EVAL-ARG-LOOP中\nDialogue: 0,0:28:27.77,0:28:31.53,Default,,0,0,0,,我们想要去一条一条的求值\nDialogue: 0,0:28:31.61,0:28:33.37,Default,,0,0,0,,UNEV中的表达式\nDialogue: 0,0:28:33.54,0:28:35.68,Default,,0,0,0,,然后把它们从UNEV中的待求值表\nDialogue: 0,0:28:35.90,0:28:37.26,Default,,0,0,0,,移动到ARGL中的已求值表中\nDialogue: 0,0:28:37.84,0:28:39.18,Default,,0,0,0,,然后我们保存ARGL\nDialogue: 0,0:28:43.95,0:28:47.26,Default,,0,0,0,,然后我们把UNEV中的第一个运算对象\nDialogue: 0,0:28:47.37,0:28:48.38,Default,,0,0,0,,赋值给EXP\nDialogue: 0,0:28:53.77,0:28:55.89,Default,,0,0,0,,然后我们检查它是否为最后一个运算对象\nDialogue: 0,0:28:55.89,0:28:56.91,Default,,0,0,0,,在这里 它还不是\nDialogue: 0,0:28:58.99,0:29:01.55,Default,,0,0,0,,然后我们保存环境\nDialogue: 0,0:29:08.00,0:29:10.06,Default,,0,0,0,,我们之所以保存UNEV\nDialogue: 0,0:29:11.61,0:29:13.50,Default,,0,0,0,,是因为稍后我们可能会需要它们\nDialogue: 0,0:29:13.50,0:29:14.40,Default,,0,0,0,,我们需要环境\nDialogue: 0,0:29:14.44,0:29:15.64,Default,,0,0,0,,来进行一些求值\nDialogue: 0,0:29:15.80,0:29:16.60,Default,,0,0,0,,我们需要UNEV寄存器来指示\nDialogue: 0,0:29:16.62,0:29:19.20,Default,,0,0,0,,其余的待求值参数\nDialogue: 0,0:29:20.34,0:29:21.55,Default,,0,0,0,,我们要把CONTINUE寄存器赋值为\nDialogue: 0,0:29:21.56,0:29:24.44,Default,,0,0,0,,ACCUMULATE-ARG这个标号\nDialogue: 0,0:29:31.13,0:29:34.01,Default,,0,0,0,,现在 我们已经准备好再次调用EVAL-DISPATCH了\nDialogue: 0,0:29:37.07,0:29:38.54,Default,,0,0,0,,现在让我把这个短路掉\nDialogue: 0,0:29:39.12,0:29:41.09,Default,,0,0,0,,这里我们不跟进EVAL-DISPATCH的细节\nDialogue: 0,0:29:41.09,0:29:42.64,Default,,0,0,0,,EVAL-DISPATCH的约定说：\nDialogue: 0,0:29:42.97,0:29:45.00,Default,,0,0,0,,我的调用完成后\nDialogue: 0,0:29:45.13,0:29:45.96,Default,,0,0,0,,整个机器的状态会变为\nDialogue: 0,0:29:46.03,0:29:48.20,Default,,0,0,0,,也就是在ENV环境中求值EXP表达式\nDialogue: 0,0:29:48.24,0:29:50.27,Default,,0,0,0,,求值结果会保存在VAL寄存器中\nDialogue: 0,0:29:50.27,0:29:51.07,Default,,0,0,0,,结束状态就是这样\nDialogue: 0,0:29:51.32,0:29:52.62,Default,,0,0,0,,那么我们把这些全都省略掉\nDialogue: 0,0:29:54.43,0:29:56.36,Default,,0,0,0,,最后VAL的内容是3\nDialogue: 0,0:29:58.01,0:29:59.76,Default,,0,0,0,,并且当我们从EVAL-DISPATCH返回的时候\nDialogue: 0,0:29:59.76,0:30:01.76,Default,,0,0,0,,我们会返回到ACCUMULAT-ARG这里\nDialogue: 0,0:30:02.30,0:30:03.23,Default,,0,0,0,,Sussman教授：跳转到ACCUMULATE-ARG\nDialogue: 0,0:30:06.22,0:30:08.20,Default,,0,0,0,,Abelson教授：VAL寄存器里是3 对吧？\nDialogue: 0,0:30:08.72,0:30:10.59,Default,,0,0,0,,我们跳过了求值的细节\nDialogue: 0,0:30:10.65,0:30:11.32,Default,,0,0,0,,现在我们要做什么？\nDialogue: 0,0:30:11.32,0:30:13.68,Default,,0,0,0,,我们返回继续看剩下的参数\nDialogue: 0,0:30:13.68,0:30:14.83,Default,,0,0,0,,我们恢复UNEV\nDialogue: 0,0:30:17.51,0:30:19.00,Default,,0,0,0,,恢复ENV\nDialogue: 0,0:30:25.79,0:30:27.05,Default,,0,0,0,,然后恢复ARGL\nDialogue: 0,0:30:28.65,0:30:29.17,Default,,0,0,0,,这件事\nDialogue: 0,0:30:30.06,0:30:31.45,Default,,0,0,0,,Sussman教授：糟糕 奇偶错误\nDialogue: 0,0:30:33.76,0:30:34.83,Default,,0,0,0,,Abelson教授：恢复ARGL\nDialogue: 0,0:30:45.57,0:30:49.76,Default,,0,0,0,,然后 我们把VAL寄存器和ARGL给CONS起来\nDialogue: 0,0:30:50.65,0:30:52.64,Default,,0,0,0,,然后赋值给ARGL寄存器\nDialogue: 0,0:30:59.36,0:31:02.96,Default,,0,0,0,,我们把UNEV中剩余的运算对象\nDialogue: 0,0:31:03.34,0:31:04.52,Default,,0,0,0,,赋值给UNEV\nDialogue: 0,0:31:08.91,0:31:10.76,Default,,0,0,0,,然后我们返回到EVAL-ARG-LOOP\nDialogue: 0,0:31:11.51,0:31:12.28,Default,,0,0,0,,Sussman教授：EVAL-ARG-LOOP\nDialogue: 0,0:31:12.28,0:31:12.86,Default,,0,0,0,,Abelson教授：好\nDialogue: 0,0:31:15.88,0:31:17.08,Default,,0,0,0,,现在我们处理下一个参数\nDialogue: 0,0:31:17.58,0:31:19.31,Default,,0,0,0,,所以首先我们要保存ARGL\nDialogue: 0,0:31:25.40,0:31:28.27,Default,,0,0,0,,然后我们把UNEV中的第一个运算对象\nDialogue: 0,0:31:29.15,0:31:30.81,Default,,0,0,0,,赋给EXP\nDialogue: 0,0:31:34.72,0:31:37.02,Default,,0,0,0,,然后我们检查它是否为最后一个运算对象\nDialogue: 0,0:31:37.02,0:31:38.00,Default,,0,0,0,,这里它是最后一个\nDialogue: 0,0:31:39.08,0:31:40.27,Default,,0,0,0,,所以我们跳到一个特殊的地方\nDialogue: 0,0:31:40.28,0:31:42.06,Default,,0,0,0,,来求值最后一个参数\nDialogue: 0,0:31:43.37,0:31:45.07,Default,,0,0,0,,因为请注意 在求值这个参数之后\nDialogue: 0,0:31:45.10,0:31:46.62,Default,,0,0,0,,我们就不再需要这个环境了\nDialogue: 0,0:31:47.64,0:31:48.78,Default,,0,0,0,,这就是区别\nDialogue: 0,0:31:50.25,0:31:51.85,Default,,0,0,0,,在这里 在EVAL-LAST-ARG这里\nDialogue: 0,0:31:52.24,0:31:54.92,Default,,0,0,0,,CONTINUE被赋值为了ACCUMULATE-LAST-ARG\nDialogue: 0,0:32:04.27,0:32:06.90,Default,,0,0,0,,现在我们再次为EVAL-DISPATCH做准备\nDialogue: 0,0:32:06.90,0:32:08.51,Default,,0,0,0,,我们有一个完成时要跳转的目的地\nDialogue: 0,0:32:08.62,0:32:09.84,Default,,0,0,0,,我们有一条表达式\nDialogue: 0,0:32:09.84,0:32:10.80,Default,,0,0,0,,还有一个环境\nDialogue: 0,0:32:11.33,0:32:13.64,Default,,0,0,0,,好 那么我们略过对EVAL-DISPATCH的调用\nDialogue: 0,0:32:14.37,0:32:16.41,Default,,0,0,0,,现在情况是这里有一个Y\nDialogue: 0,0:32:16.70,0:32:18.56,Default,,0,0,0,,在这个环境中 它的值是4\nDialogue: 0,0:32:18.60,0:32:20.09,Default,,0,0,0,,所以最终VAL寄存器将会是4\nDialogue: 0,0:32:21.06,0:32:22.86,Default,,0,0,0,,然后我们就要以ACCUMULATE-LAST-ARG结束了\nDialogue: 0,0:32:25.45,0:32:26.91,Default,,0,0,0,,因此 在ACCUMULATE-LAST-ARG中\nDialogue: 0,0:32:29.28,0:32:30.52,Default,,0,0,0,,我们恢复ARGL寄存器\nDialogue: 0,0:32:37.69,0:32:42.76,Default,,0,0,0,,我们把ARGL赋值为\nDialogue: 0,0:32:43.60,0:32:45.83,Default,,0,0,0,,将一个新值CONS在它上面的结果\nDialogue: 0,0:32:45.93,0:32:47.39,Default,,0,0,0,,所以我们在它的旧值前CONS一个4\nDialogue: 0,0:32:49.85,0:32:52.52,Default,,0,0,0,,我们恢复FUN寄存器中的内容\nDialogue: 0,0:32:53.77,0:32:54.99,Default,,0,0,0,,需要注意的是 在则个例子中\nDialogue: 0,0:32:55.00,0:32:56.27,Default,,0,0,0,,FUN寄存器还没有被修改过\nDialogue: 0,0:32:56.38,0:32:57.72,Default,,0,0,0,,但是通常来说 它会的\nDialogue: 0,0:32:59.13,0:33:01.50,Default,,0,0,0,,现在 我们将要调用APPLY-DISPATCH\nDialogue: 0,0:33:02.65,0:33:04.40,Default,,0,0,0,,所以我们刚刚步步跟进了EVAL过程\nDialogue: 0,0:33:04.51,0:33:05.85,Default,,0,0,0,,我们求值了运算符\nDialogue: 0,0:33:06.46,0:33:07.98,Default,,0,0,0,,以及实际参数\nDialogue: 0,0:33:07.98,0:33:09.24,Default,,0,0,0,,现在我们要应用它们了\nDialogue: 0,0:33:09.58,0:33:11.37,Default,,0,0,0,,因此 我们来到APPLY-DISPATCH这里\nDialogue: 0,0:33:18.03,0:33:19.29,Default,,0,0,0,,这是APPLY-DISPATCH的代码\nDialogue: 0,0:33:21.05,0:33:22.41,Default,,0,0,0,,我们要检查它是一个基本过程\nDialogue: 0,0:33:22.41,0:33:23.45,Default,,0,0,0,,还是一个复合过程\nDialogue: 0,0:33:23.64,0:33:24.20,Default,,0,0,0,,Sussman教授：基本过程\nDialogue: 0,0:33:24.54,0:33:24.83,Default,,0,0,0,,Abelson教授：好的\nDialogue: 0,0:33:24.89,0:33:26.52,Default,,0,0,0,,这里 它是一个基本过程\nDialogue: 0,0:33:27.45,0:33:28.91,Default,,0,0,0,,因此 我们跳转到PRIMITIVE-APPLY\nDialogue: 0,0:33:29.79,0:33:31.36,Default,,0,0,0,,我们来到PRIMITIVE-APPLY\nDialogue: 0,0:33:33.71,0:33:35.37,Default,,0,0,0,,它说：把VAL赋值为\nDialogue: 0,0:33:35.69,0:33:38.25,Default,,0,0,0,,把基本过程\nDialogue: 0,0:33:38.36,0:33:40.30,Default,,0,0,0,,应用在参数表的结果\nDialogue: 0,0:33:41.31,0:33:42.43,Default,,0,0,0,,Sussman教授：我不知道怎么做加法\nDialogue: 0,0:33:42.54,0:33:43.80,Default,,0,0,0,,我只是一个执行单元\nDialogue: 0,0:33:44.14,0:33:45.35,Default,,0,0,0,,Abelson教授：我也不知道\nDialogue: 0,0:33:45.35,0:33:46.51,Default,,0,0,0,,我只是一个求值器\nDialogue: 0,0:33:47.08,0:33:48.36,Default,,0,0,0,,因此 我们需要一个基本运算执行器\nDialogue: 0,0:33:48.36,0:33:49.72,Default,,0,0,0,,那么 请问基本运算执行器\nDialogue: 0,0:33:49.76,0:33:52.36,Default,,0,0,0,,3+4等于多少？\nDialogue: 0,0:33:52.86,0:33:53.32,Default,,0,0,0,,学生：7\nDialogue: 0,0:33:53.71,0:33:54.65,Default,,0,0,0,,Abelson教授：好 是7\nDialogue: 0,0:33:55.32,0:33:55.99,Default,,0,0,0,,Sussman教授：谢谢\nDialogue: 0,0:33:59.20,0:34:00.60,Default,,0,0,0,,Abelson教授：现在 我们恢复CONTINUE\nDialogue: 0,0:34:11.58,0:34:12.90,Default,,0,0,0,,执行(GOTO (FETCH CONTINUE))\nDialogue: 0,0:34:13.07,0:34:13.47,Default,,0,0,0,,Sussman教授：'DONE\nDialogue: 0,0:34:14.20,0:34:14.67,Default,,0,0,0,,Abelson教授：好\nDialogue: 0,0:34:14.92,0:34:18.41,Default,,0,0,0,,这些是你能看到的最细致的过程了\nDialogue: 0,0:34:18.41,0:34:20.19,Default,,0,0,0,,我们再也不会讲得这么细了\nDialogue: 0,0:34:21.59,0:34:23.92,Default,,0,0,0,,有一件重要的事需要注意\nDialogue: 0,0:34:24.91,0:34:27.55,Default,,0,0,0,,我们刚刚执行了一个递归过程\nDialogue: 0,0:34:29.56,0:34:31.17,Default,,0,0,0,,我们在整个过程中使用了栈\nDialogue: 0,0:34:31.17,0:34:32.75,Default,,0,0,0,,而且求值器是递归的\nDialogue: 0,0:34:33.07,0:34:35.88,Default,,0,0,0,,有很多人以为在求值器中\nDialogue: 0,0:34:36.48,0:34:37.85,Default,,0,0,0,,会用到栈和递归\nDialogue: 0,0:34:37.87,0:34:38.97,Default,,0,0,0,,或许是因为\nDialogue: 0,0:34:39.09,0:34:42.15,Default,,0,0,0,,回去求值像阶乘或者FIB那样的递归过程\nDialogue: 0,0:34:42.15,0:34:42.92,Default,,0,0,0,,这并不正确\nDialogue: 0,0:34:43.67,0:34:44.99,Default,,0,0,0,,注意 我们在这里进行了递归\nDialogue: 0,0:34:45.00,0:34:46.86,Default,,0,0,0,,而仅仅是去求值(+ X Y)\nDialogue: 0,0:34:47.77,0:34:50.65,Default,,0,0,0,,在求值器中需要递归 实际上是因为\nDialogue: 0,0:34:50.96,0:34:52.97,Default,,0,0,0,,是因为求值过程本身\nDialogue: 0,0:34:52.99,0:34:54.06,Default,,0,0,0,,就是递归的\nDialogue: 0,0:34:54.45,0:34:56.17,Default,,0,0,0,,并不是因为你在Lisp中\nDialogue: 0,0:34:56.32,0:34:58.09,Default,,0,0,0,,要求值的那个过程\nDialogue: 0,0:34:58.12,0:34:59.27,Default,,0,0,0,,是一个递归过程\nDialogue: 0,0:34:59.27,0:35:00.52,Default,,0,0,0,,这一点很重要\nDialogue: 0,0:35:00.52,0:35:02.14,Default,,0,0,0,,人们经常在这里被弄糊涂\nDialogue: 0,0:35:03.01,0:35:04.27,Default,,0,0,0,,另一点要注意的是\nDialogue: 0,0:35:04.27,0:35:05.64,Default,,0,0,0,,我们在这里完成之后\nDialogue: 0,0:35:06.28,0:35:07.12,Default,,0,0,0,,真正完成以后\nDialogue: 0,0:35:07.12,0:35:08.49,Default,,0,0,0,,不仅仅是指我们在'DONE这个标号\nDialogue: 0,0:35:09.45,0:35:13.23,Default,,0,0,0,,栈上也没有累积的东西了\nDialogue: 0,0:35:13.60,0:35:15.71,Default,,0,0,0,,对吧？机器又回到了它的初始状态\nDialogue: 0,0:35:17.00,0:35:18.75,Default,,0,0,0,,那就是“完成”的其中一部分意义\nDialogue: 0,0:35:19.71,0:35:21.04,Default,,0,0,0,,换句话说就是\nDialogue: 0,0:35:22.72,0:35:26.04,Default,,0,0,0,,整个求值过程是把\nDialogue: 0,0:35:26.41,0:35:28.32,Default,,0,0,0,,(+ X Y)这条表达式\nDialogue: 0,0:35:30.54,0:35:32.78,Default,,0,0,0,,归约为这里的7\nDialogue: 0,0:35:33.24,0:35:35.45,Default,,0,0,0,,我所指的“归约”有特殊的意义\nDialogue: 0,0:35:36.01,0:35:38.18,Default,,0,0,0,,也就是栈上没剩下任何东西了\nDialogue: 0,0:35:38.18,0:35:40.36,Default,,0,0,0,,机器现在与初始状态相同\nDialogue: 0,0:35:40.92,0:35:42.65,Default,,0,0,0,,只是VAL寄存器里有一些东西\nDialogue: 0,0:35:42.72,0:35:44.52,Default,,0,0,0,,它不是任何问题的子问题\nDialogue: 0,0:35:44.52,0:35:45.63,Default,,0,0,0,,不需要返回到其它地方\nDialogue: 0,0:35:46.12,0:35:46.96,Default,,0,0,0,,好 这节课就讲到这里\nDialogue: 0,0:35:50.16,0:35:50.76,Default,,0,0,0,,有问题吗\nDialogue: 0,0:35:51.08,0:35:54.02,Default,,0,0,0,,学生：关于栈有一个问题\nDialogue: 0,0:35:54.02,0:35:55.82,Default,,0,0,0,,由于数据有可能是递归的\nDialogue: 0,0:35:56.20,0:35:58.75,Default,,0,0,0,,例如 嵌套的表达式\nDialogue: 0,0:35:59.31,0:36:02.08,Default,,0,0,0,,教授：是的 因为你可能遇到嵌套的表达式\nDialogue: 0,0:36:02.08,0:36:04.77,Default,,0,0,0,,但是再说一遍 不要搞混\nDialogue: 0,0:36:04.77,0:36:07.98,Default,,0,0,0,,有时候人们说数据是递归的\nDialogue: 0,0:36:08.00,0:36:10.35,Default,,0,0,0,,他们说的是对于这些表结构的\nDialogue: 0,0:36:11.04,0:36:12.93,Default,,0,0,0,,一些递归运算\nDialogue: 0,0:36:12.93,0:36:13.96,Default,,0,0,0,,那和这没有关系\nDialogue: 0,0:36:13.98,0:36:16.16,Default,,0,0,0,,这只是包含子表达式的表达式而已\nDialogue: 0,0:36:20.04,0:36:23.52,Default,,0,0,0,,学生：为什么ARGL中参数的顺序是反过来的\nDialogue: 0,0:36:23.55,0:36:25.29,Default,,0,0,0,,教授：对 我应该提一嘴这个\nDialogue: 0,0:36:27.26,0:36:29.07,Default,,0,0,0,,之所以在这里把顺序反过来\nDialogue: 0,0:36:32.78,0:36:35.37,Default,,0,0,0,,你首先定义怎么算“逆序”\nDialogue: 0,0:36:36.05,0:36:39.90,Default,,0,0,0,,我记得应该是牛顿\nDialogue: 0,0:36:40.91,0:36:42.41,Default,,0,0,0,,在光学发展的很早期\nDialogue: 0,0:36:42.43,0:36:43.26,Default,,0,0,0,,人们意识到\nDialogue: 0,0:36:43.61,0:36:45.36,Default,,0,0,0,,当你用眼睛通过透镜看东西的时候\nDialogue: 0,0:36:45.50,0:36:46.73,Default,,0,0,0,,图像是上下颠倒的\nDialogue: 0,0:36:46.73,0:36:48.04,Default,,0,0,0,,当时有很多的争论说\nDialogue: 0,0:36:48.04,0:36:50.48,Default,,0,0,0,,为什么不能是你眼睛平时看见的都是上下颠倒的\nDialogue: 0,0:36:51.28,0:36:52.65,Default,,0,0,0,,这实际上是一样的道理\nDialogue: 0,0:36:52.86,0:36:53.90,Default,,0,0,0,,和什么相比反过来了\nDialogue: 0,0:36:54.81,0:36:56.24,Default,,0,0,0,,我们只是需要一个约定\nDialogue: 0,0:36:56.59,0:37:00.35,Default,,0,0,0,,它们作为(4 3)出现的原因是\nDialogue: 0,0:37:00.80,0:37:02.49,Default,,0,0,0,,是因为我们从UNEV中取出东西\nDialogue: 0,0:37:02.52,0:37:04.03,Default,,0,0,0,,并且把它CONS到了ARGL上面\nDialogue: 0,0:37:04.52,0:37:06.68,Default,,0,0,0,,那么你要意识到你已经做了这个约定\nDialogue: 0,0:37:06.86,0:37:09.37,Default,,0,0,0,,你需要意识到这点的地方有\nDialogue: 0,0:37:09.98,0:37:11.23,Default,,0,0,0,,实际上有两个地方\nDialogue: 0,0:37:11.23,0:37:12.91,Default,,0,0,0,,首先是在APPLY-PRIMITIVE-OPERATOR\nDialogue: 0,0:37:12.91,0:37:14.06,Default,,0,0,0,,你要意识到\nDialogue: 0,0:37:15.12,0:37:16.75,Default,,0,0,0,,参数传入基本运算的顺序\nDialogue: 0,0:37:16.78,0:37:18.72,Default,,0,0,0,,是和你的书写顺序相反的\nDialogue: 0,0:37:19.49,0:37:21.00,Default,,0,0,0,,我们之后会在另外一处看到\nDialogue: 0,0:37:21.07,0:37:23.80,Default,,0,0,0,,当你实际绑定绑定函数的形式参数时\nDialogue: 0,0:37:24.01,0:37:25.74,Default,,0,0,0,,你要意识到参数进入的顺序\nDialogue: 0,0:37:25.74,0:37:28.54,Default,,0,0,0,,和你要绑定这些变量时的顺序相反\nDialogue: 0,0:37:28.87,0:37:30.17,Default,,0,0,0,,所以如果你注意这些\nDialogue: 0,0:37:31.08,0:37:31.83,Default,,0,0,0,,就没有问题了\nDialogue: 0,0:37:31.83,0:37:33.69,Default,,0,0,0,,同样 这完全是随意的\nDialogue: 0,0:37:33.90,0:37:34.96,Default,,0,0,0,,因为如果我们做了一个\nDialogue: 0,0:37:35.10,0:37:37.15,Default,,0,0,0,,比如 给向量的各个维度赋值的迭代\nDialogue: 0,0:37:37.42,0:37:38.73,Default,,0,0,0,,它们可能会以其它顺序输出\nDialogue: 0,0:37:40.41,0:37:42.04,Default,,0,0,0,,那么这只是这个求值器\nDialogue: 0,0:37:42.06,0:37:43.53,Default,,0,0,0,,工作时的一个约定\nDialogue: 0,0:37:45.39,0:37:46.24,Default,,0,0,0,,好 我们休息一下\nDialogue: 0,0:37:46.33,0:38:02.44,Default,,0,0,0,,[音乐]\nDialogue: 0,0:38:02.44,0:38:07.64,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:38:28.62,0:38:32.51,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:38:32.51,0:38:35.68,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:38:35.68,0:38:39.61,Declare,,0,0,0,,{\\an2\\fad(500,500)}显式控制求值器\nDialogue: 0,0:38:41.84,0:38:45.31,Default,,0,0,0,,教授：我们已经学习了表达式的求值\nDialogue: 0,0:38:45.60,0:38:47.08,Default,,0,0,0,,虽然这只是一个非常简单的例子\nDialogue: 0,0:38:48.81,0:38:50.24,Default,,0,0,0,,但从本质上来说\nDialogue: 0,0:38:50.24,0:38:52.03,Default,,0,0,0,,它跟那些大型嵌套表达式没什么不同\nDialogue: 0,0:38:52.03,0:38:54.57,Default,,0,0,0,,后者只是在栈上递归得更深而已\nDialogue: 0,0:38:55.13,0:38:56.03,Default,,0,0,0,,我现在要为你们\nDialogue: 0,0:38:56.04,0:38:56.91,Default,,0,0,0,,讲解最后一部分\nDialogue: 0,0:38:56.92,0:38:59.82,Default,,0,0,0,,我要带着你们观察EVAL-APPLY循环\nDialogue: 0,0:39:01.01,0:39:02.81,Default,,0,0,0,,我们还没有仔细研究过它\nDialogue: 0,0:39:03.00,0:39:04.75,Default,,0,0,0,,我们还没有见过一个复合程序\nDialogue: 0,0:39:05.20,0:39:07.79,Default,,0,0,0,,对它的求值会归约为\nDialogue: 0,0:39:07.92,0:39:10.11,Default,,0,0,0,,对一个过程的应用\nDialogue: 0,0:39:10.12,0:39:11.64,Default,,0,0,0,,进而是对过程体的求值\nDialogue: 0,0:39:12.44,0:39:15.88,Default,,0,0,0,,因此 假设我们有这个\nDialogue: 0,0:39:15.93,0:39:17.44,Default,,0,0,0,,假设我们正在考察\nDialogue: 0,0:39:18.07,0:39:31.60,Default,,0,0,0,,(DEFINE (F A B) (+ A B)\nDialogue: 0,0:39:33.99,0:39:37.32,Default,,0,0,0,,假设我们预先定义好了这个过程\nDialogue: 0,0:39:37.69,0:39:41.64,Default,,0,0,0,,现在 我们将要求值(F X Y)\nDialogue: 0,0:39:42.27,0:39:44.20,Default,,0,0,0,,基于的环境是E0\nDialogue: 0,0:39:44.35,0:39:47.02,Default,,0,0,0,,其中X=3 Y=4\nDialogue: 0,0:39:50.78,0:39:52.11,Default,,0,0,0,,当执行DEFINE的时候\nDialogue: 0,0:39:52.12,0:39:53.69,Default,,0,0,0,,还记得么 这里是一个LAMBDA\nDialogue: 0,0:39:53.82,0:39:55.53,Default,,0,0,0,,LAMBDA会创建一个过程\nDialogue: 0,0:39:55.95,0:39:58.49,Default,,0,0,0,,基本上 会发生的事情是\nDialogue: 0,0:39:59.63,0:40:00.68,Default,,0,0,0,,在环境E0中\nDialogue: 0,0:40:01.00,0:40:02.65,Default,,0,0,0,,我们会得到F的绑定\nDialogue: 0,0:40:03.56,0:40:05.61,Default,,0,0,0,,它指出F是一个过程\nDialogue: 0,0:40:07.15,0:40:11.28,Default,,0,0,0,,这个过程的参数是A和B\nDialogue: 0,0:40:12.57,0:40:16.19,Default,,0,0,0,,而过程体是(+ A B)\nDialogue: 0,0:40:18.11,0:40:20.99,Default,,0,0,0,,这就是环境大概的样子\nDialogue: 0,0:40:21.21,0:40:22.52,Default,,0,0,0,,我们之前就定义过了\nDialogue: 0,0:40:24.22,0:40:27.28,Default,,0,0,0,,然后 我们去求值(F X Y)\nDialogue: 0,0:40:28.80,0:40:30.89,Default,,0,0,0,,我们会仔细地解释每一步\nDialogue: 0,0:40:31.02,0:40:31.85,Default,,0,0,0,,就像之前那样\nDialogue: 0,0:40:31.88,0:40:33.09,Default,,0,0,0,,不会跳过重复的表达式\nDialogue: 0,0:40:33.28,0:40:34.38,Default,,0,0,0,,唯一的不同是\nDialogue: 0,0:40:34.40,0:40:36.64,Default,,0,0,0,,它的内部不再是基本的“+”过程\nDialogue: 0,0:40:37.24,0:40:38.99,Default,,0,0,0,,它还有这个东西\nDialogue: 0,0:40:41.04,0:40:43.60,Default,,0,0,0,,因此我们要进行相同的过程\nDialogue: 0,0:40:43.60,0:40:44.92,Default,,0,0,0,,只不过这次\nDialogue: 0,0:40:45.26,0:40:47.42,Default,,0,0,0,,当我们停在APPLY-DISPATCH时\nDialogue: 0,0:40:47.86,0:40:50.28,Default,,0,0,0,,FUN寄存器中不再是基本的“+”过程\nDialogue: 0,0:40:50.44,0:40:53.58,Default,,0,0,0,,而是一个代表过程的东西\nDialogue: 0,0:40:54.30,0:40:59.00,Default,,0,0,0,,其中参数为A和B\nDialogue: 0,0:41:00.64,0:41:06.27,Default,,0,0,0,,过程体是(+ A B)\nDialogue: 0,0:41:07.87,0:41:09.92,Default,,0,0,0,,再强调一下 我所谓的ENV\nDialogue: 0,0:41:09.96,0:41:11.12,Default,,0,0,0,,是一个指向环境的指针\nDialogue: 0,0:41:11.24,0:41:13.07,Default,,0,0,0,,所以不用担心我在这里写了很多东西\nDialogue: 0,0:41:13.28,0:41:15.63,Default,,0,0,0,,这是一个指向代表过程的数据结构的指针\nDialogue: 0,0:41:17.17,0:41:19.77,Default,,0,0,0,,因此 我们现在面临着相同的情况\nDialogue: 0,0:41:20.27,0:41:22.43,Default,,0,0,0,,我们来到了APPLY-DISPATCH\nDialogue: 0,0:41:23.98,0:41:26.48,Default,,0,0,0,,这是APPLY-DISPATCH的代码\nDialogue: 0,0:41:26.48,0:41:28.73,Default,,0,0,0,,上一次 我们分支跳转到了一个基本过程\nDialogue: 0,0:41:30.01,0:41:30.70,Default,,0,0,0,,然而这一次\nDialogue: 0,0:41:30.84,0:41:32.80,Default,,0,0,0,,我们遇到的是一个复合过程\nDialogue: 0,0:41:34.55,0:41:36.60,Default,,0,0,0,,因此我们要跳转到COMPOUND-APPLY\nDialogue: 0,0:41:38.47,0:41:39.92,Default,,0,0,0,,COMPOUND-APPLY又是怎样定义的呢？\nDialogue: 0,0:41:41.92,0:41:44.54,Default,,0,0,0,,还记得元循环求值器是怎么做的么？\nDialogue: 0,0:41:45.09,0:41:47.40,Default,,0,0,0,,COMPOUND-APPLY的执行步骤则是\nDialogue: 0,0:41:49.90,0:41:51.60,Default,,0,0,0,,在一个新的环境中\nDialogue: 0,0:41:52.94,0:41:54.12,Default,,0,0,0,,求值一个过程的体\nDialogue: 0,0:41:54.12,0:41:55.87,Default,,0,0,0,,这个新的环境来自于哪里呢？\nDialogue: 0,0:41:56.73,0:42:01.36,Default,,0,0,0,,我们把跟过程一同打包的环境\nDialogue: 0,0:42:03.02,0:42:05.79,Default,,0,0,0,,我们把过程的形式参数\nDialogue: 0,0:42:06.00,0:42:07.63,Default,,0,0,0,,同传递进来的实际参数给绑定起来\nDialogue: 0,0:42:09.75,0:42:11.95,Default,,0,0,0,,把这个作为新的框架\nDialogue: 0,0:42:12.59,0:42:13.79,Default,,0,0,0,,来扩展过程附带的环境\nDialogue: 0,0:42:14.99,0:42:16.08,Default,,0,0,0,,我们就是在这个环境中\nDialogue: 0,0:42:16.30,0:42:18.88,Default,,0,0,0,,求值过程的体\nDialogue: 0,0:42:20.12,0:42:24.47,Default,,0,0,0,,对吧？这就是APPLY-EVAL循环做的事\nDialogue: 0,0:42:24.47,0:42:26.25,Default,,0,0,0,,这就是APPLY回过头来调用EVAL\nDialogue: 0,0:42:32.86,0:42:34.92,Default,,0,0,0,,因此 这就是我们要在COMPOUND-APPLY中要做的所有事\nDialogue: 0,0:42:36.78,0:42:37.72,Default,,0,0,0,,要怎么来实现呢？\nDialogue: 0,0:42:37.72,0:42:40.97,Default,,0,0,0,,我们要构造一个新的环境\nDialogue: 0,0:42:43.55,0:42:45.64,Default,,0,0,0,,而我们构造的这个新环境呢\nDialogue: 0,0:42:46.76,0:42:48.11,Default,,0,0,0,,我们把它记作E1\nDialogue: 0,0:42:52.90,0:42:55.63,Default,,0,0,0,,E1这个环境呢\nDialogue: 0,0:42:57.31,0:42:59.15,Default,,0,0,0,,存储了过程的参数绑定\nDialogue: 0,0:42:59.21,0:43:03.26,Default,,0,0,0,,其中A=3 B=4\nDialogue: 0,0:43:04.27,0:43:05.76,Default,,0,0,0,,并且它跟E0相连\nDialogue: 0,0:43:05.76,0:43:08.08,Default,,0,0,0,,这是因为 F就是在E0中定义的\nDialogue: 0,0:43:09.27,0:43:10.27,Default,,0,0,0,,因此 在这个环境中\nDialogue: 0,0:43:10.27,0:43:11.96,Default,,0,0,0,,我们要来求值过程的体\nDialogue: 0,0:43:12.05,0:43:14.48,Default,,0,0,0,,让我们来看一看\nDialogue: 0,0:43:16.52,0:43:18.32,Default,,0,0,0,,我们来看COMPOUND-APPLY的代码\nDialogue: 0,0:43:20.30,0:43:23.47,Default,,0,0,0,,首先是给EXP寄存器赋值\nDialogue: 0,0:43:24.50,0:43:25.98,Default,,0,0,0,,所赋的值是FUN寄存器\nDialogue: 0,0:43:25.98,0:43:27.26,Default,,0,0,0,,所指向过程的体\nDialogue: 0,0:43:28.38,0:43:30.64,Default,,0,0,0,,这样 我就将过程的体\nDialogue: 0,0:43:31.29,0:43:32.33,Default,,0,0,0,,赋值给了EXP寄存器\nDialogue: 0,0:43:40.75,0:43:41.10,Default,,0,0,0,,对吧？\nDialogue: 0,0:43:42.64,0:43:44.97,Default,,0,0,0,,而这将在某个环境中求值\nDialogue: 0,0:43:45.82,0:43:48.32,Default,,0,0,0,,这个环境是通过将FUN寄存器\nDialogue: 0,0:43:51.30,0:43:53.67,Default,,0,0,0,,所指向的过程中的形式参数\nDialogue: 0,0:43:53.67,0:43:56.25,Default,,0,0,0,,与实际参数绑定起来 得到的\nDialogue: 0,0:43:57.80,0:44:00.00,Default,,0,0,0,,我们先不要关系它的具体细节\nDialogue: 0,0:44:00.08,0:44:01.63,Default,,0,0,0,,你可以知道它的最后结果\nDialogue: 0,0:44:01.93,0:44:03.32,Default,,0,0,0,,因此MAKE-BINDINGS会说\nDialogue: 0,0:44:04.04,0:44:07.90,Default,,0,0,0,,过程本身就附带有一个环境\nDialogue: 0,0:44:07.96,0:44:09.32,Default,,0,0,0,,在这里 我没有写出来\nDialogue: 0,0:44:09.36,0:44:10.56,Default,,0,0,0,,但我应该说过它有一个环境\nDialogue: 0,0:44:11.30,0:44:12.73,Default,,0,0,0,,因为每个过程在构造时\nDialogue: 0,0:44:12.76,0:44:13.44,Default,,0,0,0,,都有一个环境\nDialogue: 0,0:44:13.66,0:44:14.83,Default,,0,0,0,,因此 通过这个环境\nDialogue: 0,0:44:15.68,0:44:16.35,Default,,0,0,0,,它能够知道\nDialogue: 0,0:44:16.60,0:44:18.65,Default,,0,0,0,,定义该过程时的环境是怎样的\nDialogue: 0,0:44:19.29,0:44:20.75,Default,,0,0,0,,它知道实际参数是什么\nDialogue: 0,0:44:21.83,0:44:22.49,Default,,0,0,0,,它查看ARGL\nDialogue: 0,0:44:22.49,0:44:24.28,Default,,0,0,0,,然后你会在这里看到逆序的约定\nDialogue: 0,0:44:24.28,0:44:26.62,Default,,0,0,0,,它需要知道ARGL是逆序的\nDialogue: 0,0:44:27.06,0:44:28.81,Default,,0,0,0,,然后它构造了这个框架 E1\nDialogue: 0,0:44:29.99,0:44:31.08,Default,,0,0,0,,因此我们假设\nDialogue: 0,0:44:31.10,0:44:32.92,Default,,0,0,0,,MAKE-BINDINGS返回的就是这些东西\nDialogue: 0,0:44:33.36,0:44:36.22,Default,,0,0,0,,然后 它把E1赋值给ENV\nDialogue: 0,0:44:41.34,0:44:42.54,Default,,0,0,0,,下一步就是\nDialogue: 0,0:44:43.95,0:44:45.84,Default,,0,0,0,,恢复CONTINUE\nDialogue: 0,0:44:46.89,0:44:48.19,Default,,0,0,0,,还记得CONTINUE之前是什么吗？\nDialogue: 0,0:44:48.76,0:44:50.43,Default,,0,0,0,,在最后一段中\nDialogue: 0,0:44:52.24,0:44:54.02,Default,,0,0,0,,CONTINUE被保存了\nDialogue: 0,0:44:54.02,0:44:55.18,Default,,0,0,0,,它的值是最初的'DONE\nDialogue: 0,0:44:55.32,0:44:56.56,Default,,0,0,0,,这代表了\nDialogue: 0,0:44:56.73,0:44:59.44,Default,,0,0,0,,在完成这项特定应用后要做的事\nDialogue: 0,0:45:00.14,0:45:01.72,Default,,0,0,0,,这是在求值整个应用时\nDialogue: 0,0:45:01.76,0:45:03.18,Default,,0,0,0,,最先发生的事儿\nDialogue: 0,0:45:03.88,0:45:05.87,Default,,0,0,0,,现在 我们要恢复CONTINUE了\nDialogue: 0,0:45:06.86,0:45:09.55,Default,,0,0,0,,还记得APPLY-DISPATCH的约定么？\nDialogue: 0,0:45:09.58,0:45:11.20,Default,,0,0,0,,它假设下一步的跳转目标\nDialogue: 0,0:45:11.23,0:45:11.98,Default,,0,0,0,,已经存放在栈上了\nDialogue: 0,0:45:12.03,0:45:13.12,Default,,0,0,0,,并且 这里确实存放在栈上了\nDialogue: 0,0:45:13.59,0:45:14.76,Default,,0,0,0,,CONTINUE被赋值成了DONE\nDialogue: 0,0:45:17.82,0:45:19.90,Default,,0,0,0,,现在我们要回到EVAL-DISPATCH了\nDialogue: 0,0:45:19.94,0:45:20.84,Default,,0,0,0,,我们要再次进行寄存器设置\nDialogue: 0,0:45:20.97,0:45:24.41,Default,,0,0,0,,我们有表达式、环境、下一步\nDialogue: 0,0:45:25.80,0:45:26.89,Default,,0,0,0,,我不会再细讲了\nDialogue: 0,0:45:27.88,0:45:29.55,Default,,0,0,0,,因为它基本上就是相同的表达式\nDialogue: 0,0:45:35.40,0:45:37.79,Default,,0,0,0,,但是需要注意的是\nDialogue: 0,0:45:37.82,0:45:38.73,Default,,0,0,0,,在这个时候\nDialogue: 0,0:45:39.34,0:45:43.72,Default,,0,0,0,,我们已经归约了原始表达式(F X Y)\nDialogue: 0,0:45:44.64,0:45:47.92,Default,,0,0,0,,通过在E0中求值(F X Y)\nDialogue: 0,0:45:48.89,0:45:52.67,Default,,0,0,0,,将其归约为在E1中求值(+ A B)\nDialogue: 0,0:45:52.78,0:45:55.92,Default,,0,0,0,,要注意 栈上并没有什么东西 对吧？\nDialogue: 0,0:45:56.11,0:45:56.83,Default,,0,0,0,,这是一个归约\nDialogue: 0,0:45:56.84,0:45:59.80,Default,,0,0,0,,这个时候 机器的状态中\nDialogue: 0,0:45:59.84,0:46:01.20,Default,,0,0,0,,并没有包含\nDialogue: 0,0:46:01.76,0:46:03.71,Default,,0,0,0,,它是求值过程F的\nDialogue: 0,0:46:03.72,0:46:04.88,Default,,0,0,0,,中间状态的事实\nDialogue: 0,0:46:05.49,0:46:06.28,Default,,0,0,0,,它消失了\nDialogue: 0,0:46:07.66,0:46:09.55,Default,,0,0,0,,这里面没有积累的状态\nDialogue: 0,0:46:13.07,0:46:14.37,Default,,0,0,0,,注意 这个思想非常重要\nDialogue: 0,0:46:14.37,0:46:16.33,Default,,0,0,0,,这意味着\nDialogue: 0,0:46:16.76,0:46:18.39,Default,,0,0,0,,当我们使用代换模型时\nDialogue: 0,0:46:18.39,0:46:20.86,Default,,0,0,0,,一条表达式会归约到另一条表达式\nDialogue: 0,0:46:21.35,0:46:22.66,Default,,0,0,0,,而你不需要记住任何东西\nDialogue: 0,0:46:22.66,0:46:24.50,Default,,0,0,0,,这里 你就见到了归约的真谛\nDialogue: 0,0:46:24.56,0:46:26.16,Default,,0,0,0,,这个时候 栈上没有任何东西\nDialogue: 0,0:46:31.59,0:46:33.63,Default,,0,0,0,,这样就有一个非常重要的结果\nDialogue: 0,0:46:35.24,0:46:37.90,Default,,0,0,0,,让我们回过头来看看迭代式阶乘\nDialogue: 0,0:46:40.42,0:46:42.76,Default,,0,0,0,,还记得吗？这是某种循环\nDialogue: 0,0:46:44.01,0:46:44.88,Default,,0,0,0,,用来进行迭代\nDialogue: 0,0:46:45.13,0:46:47.36,Default,,0,0,0,,我们不断强调 它是一个迭代过程\nDialogue: 0,0:46:49.26,0:46:53.84,Default,,0,0,0,,还记得吗\nDialogue: 0,0:46:58.44,0:47:03.13,Default,,0,0,0,,我们使用它的时候\nDialogue: 0,0:47:04.35,0:47:11.07,Default,,0,0,0,,是像(FACT-ITER 5)这样调用它的\nDialogue: 0,0:47:12.36,0:47:18.67,Default,,0,0,0,,然后我们把它归约成(ITER 1 1 5)\nDialogue: 0,0:47:19.03,0:47:25.15,Default,,0,0,0,,然后它归约成(ITER 1 2 5)\nDialogue: 0,0:47:25.32,0:47:27.07,Default,,0,0,0,,等等等等\nDialogue: 0,0:47:27.07,0:47:28.17,Default,,0,0,0,,然后我们又说 看\nDialogue: 0,0:47:28.17,0:47:30.35,Default,,0,0,0,,为了实现这个效果 不需要存储任何东西\nDialogue: 0,0:47:31.72,0:47:32.73,Default,,0,0,0,,我们摆了摆手 说\nDialogue: 0,0:47:32.75,0:47:34.59,Default,,0,0,0,,“原则上 这不需要任何存储”\nDialogue: 0,0:47:35.04,0:47:36.17,Default,,0,0,0,,现在你们发现 确实不需要\nDialogue: 0,0:47:36.17,0:47:39.09,Default,,0,0,0,,这里的每一步都是真正的归约 对吧？\nDialogue: 0,0:47:39.09,0:47:42.60,Default,,0,0,0,,随着你求值这些表达式\nDialogue: 0,0:47:47.30,0:47:50.51,Default,,0,0,0,,在求值这些表达式的过程中\nDialogue: 0,0:47:50.83,0:47:51.37,Default,,0,0,0,,你会发现\nDialogue: 0,0:47:51.37,0:47:52.81,Default,,0,0,0,,栈上的这些表达式\nDialogue: 0,0:47:53.75,0:47:55.64,Default,,0,0,0,,都在一个特定的环境中\nDialogue: 0,0:47:56.42,0:48:00.02,Default,,0,0,0,,抱歉 是EXP寄存器中的表达式\nDialogue: 0,0:48:00.02,0:48:01.50,Default,,0,0,0,,是在某个特定的环境中\nDialogue: 0,0:48:01.57,0:48:02.19,Default,,0,0,0,,并且 在每一步\nDialogue: 0,0:48:02.19,0:48:04.00,Default,,0,0,0,,栈上不会积累任何东西\nDialogue: 0,0:48:04.36,0:48:05.68,Default,,0,0,0,,因为每一步都是真正的归约\nDialogue: 0,0:48:09.28,0:48:10.51,Default,,0,0,0,,因此 举例来说\nDialogue: 0,0:48:10.58,0:48:12.51,Default,,0,0,0,,说得更仔细一点\nDialogue: 0,0:48:13.46,0:48:16.88,Default,,0,0,0,,如果我从这样的一条表达式开始\nDialogue: 0,0:48:22.44,0:48:34.25,Default,,0,0,0,,比如说 在某个环境中计算(FACT-ITER 5)\nDialogue: 0,0:48:42.11,0:48:46.30,Default,,0,0,0,,它将在某个时刻创建一个环境\nDialogue: 0,0:48:46.81,0:48:48.38,Default,,0,0,0,,其中N=5\nDialogue: 0,0:48:51.47,0:48:52.01,Default,,0,0,0,,我们把它写下来\nDialogue: 0,0:48:55.68,0:48:56.59,Default,,0,0,0,,然后 在某个时候\nDialogue: 0,0:48:56.89,0:49:02.56,Default,,0,0,0,,机器会归约这整个东西\nDialogue: 0,0:49:02.91,0:49:04.35,Default,,0,0,0,,将它归约为\nDialogue: 0,0:49:04.76,0:49:09.85,Default,,0,0,0,,(ITER 1 1 N)\nDialogue: 0,0:49:10.68,0:49:13.72,Default,,0,0,0,,然后在环境E1中求值这条表达式\nDialogue: 0,0:49:15.87,0:49:17.16,Default,,0,0,0,,而不在栈上存放任何东西\nDialogue: 0,0:49:17.16,0:49:19.55,Default,,0,0,0,,看到了么 这时机器并不会记住\nDialogue: 0,0:49:20.71,0:49:22.50,Default,,0,0,0,,求值这条ITER表达式--\nDialogue: 0,0:49:25.00,0:49:25.63,Default,,0,0,0,,也就是某种循环--\nDialogue: 0,0:49:25.79,0:49:28.57,Default,,0,0,0,,并不是FACT-ITER的一部分\nDialogue: 0,0:49:29.68,0:49:30.59,Default,,0,0,0,,它不会记住这个事实\nDialogue: 0,0:49:30.59,0:49:33.17,Default,,0,0,0,,它只是归约了该表达式\nDialogue: 0,0:49:33.17,0:49:36.56,Default,,0,0,0,,如果我们再来看迭代式阶乘的体\nDialogue: 0,0:49:38.05,0:49:41.08,Default,,0,0,0,,这条表达式归约为了这条表达式\nDialogue: 0,0:49:42.81,0:49:43.87,Default,,0,0,0,,哦 这里漏了一个N\nDialogue: 0,0:49:46.59,0:49:47.74,Default,,0,0,0,,幻灯片中的约定\nDialogue: 0,0:49:47.74,0:49:49.13,Default,,0,0,0,,和实际程序中稍有不同\nDialogue: 0,0:49:53.34,0:49:56.25,Default,,0,0,0,,那么 ITER的体又是什么？\nDialogue: 0,0:49:56.28,0:49:57.40,Default,,0,0,0,,ITER的体首先是一个IF--\nDialogue: 0,0:49:58.75,0:50:00.19,Default,,0,0,0,,我不会再深入IF语句的细节了\nDialogue: 0,0:50:00.24,0:50:01.63,Default,,0,0,0,,它会对谓词求值\nDialogue: 0,0:50:02.40,0:50:03.71,Default,,0,0,0,,本例中 会返回FALSE\nDialogue: 0,0:50:03.81,0:50:08.64,Default,,0,0,0,,然后这里的ITER会归约为表达式--\nDialogue: 0,0:50:09.85,0:50:20.20,Default,,0,0,0,,(ITER (* COUNTER PRODUCT)\nDialogue: 0,0:50:21.62,0:50:22.24,Default,,0,0,0,,按照它代码写的--\nDialogue: 0,0:50:22.68,0:50:24.56,Default,,0,0,0,,(+ COUNTER 1))\nDialogue: 0,0:50:28.72,0:50:31.42,Default,,0,0,0,,在另外的一个环境E2中求值\nDialogue: 0,0:50:32.97,0:50:35.98,Default,,0,0,0,,其中 E2会记录着\nDialogue: 0,0:50:36.49,0:50:39.39,Default,,0,0,0,,PRODUCT和COUNTER的值\nDialogue: 0,0:50:42.92,0:50:44.33,Default,,0,0,0,,它会被归约为这条语句\nDialogue: 0,0:50:44.94,0:50:46.04,Default,,0,0,0,,它不会记得\nDialogue: 0,0:50:46.06,0:50:48.75,Default,,0,0,0,,它是一个需要返回到某处的一部分\nDialogue: 0,0:50:49.34,0:50:50.43,Default,,0,0,0,,当ITER再次调用ITER时\nDialogue: 0,0:50:50.44,0:50:52.56,Default,,0,0,0,,它会归约为另一个像这样的东西\nDialogue: 0,0:50:53.05,0:50:54.68,Default,,0,0,0,,只是会在新环境E3中\nDialogue: 0,0:50:54.83,0:50:56.67,Default,,0,0,0,,里面有关于PRODUCT和COUNTER新的绑定\nDialogue: 0,0:50:58.80,0:51:05.29,Default,,0,0,0,,因此 如果你想知道\nDialogue: 0,0:51:06.09,0:51:07.53,Default,,0,0,0,,如果你一直感到不安\nDialogue: 0,0:51:08.25,0:51:10.67,Default,,0,0,0,,不知道为什么我们说这些过程\nDialogue: 0,0:51:10.67,0:51:12.45,Default,,0,0,0,,虽然从语法上看起来是递归的\nDialogue: 0,0:51:13.20,0:51:15.69,Default,,0,0,0,,但实际上是迭代的\nDialogue: 0,0:51:15.87,0:51:17.24,Default,,0,0,0,,可以在常量空间中运行\nDialogue: 0,0:51:18.40,0:51:19.75,Default,,0,0,0,,我不知道这么说是否打消了你们的疑虑\nDialogue: 0,0:51:19.75,0:51:21.23,Default,,0,0,0,,但至少让你们知道发生了什么\nDialogue: 0,0:51:21.23,0:51:22.81,Default,,0,0,0,,这其中没有任何构造\nDialogue: 0,0:51:25.91,0:51:27.58,Default,,0,0,0,,但你也会说 这里面还是有一些构造\nDialogue: 0,0:51:27.98,0:51:30.08,Default,,0,0,0,,从原则上来说 我们也构造了环境框架\nDialogue: 0,0:51:31.71,0:51:32.37,Default,,0,0,0,,答案则是\nDialogue: 0,0:51:32.40,0:51:33.84,Default,,0,0,0,,你确实需要构建这些环境框架\nDialogue: 0,0:51:33.84,0:51:35.26,Default,,0,0,0,,但是 等你求值完毕后\nDialogue: 0,0:51:35.42,0:51:36.19,Default,,0,0,0,,不必保留它们\nDialogue: 0,0:51:36.44,0:51:37.61,Default,,0,0,0,,它们可以被废料收集\nDialogue: 0,0:51:37.92,0:51:39.47,Default,,0,0,0,,这些空间也可以被自动地重用\nDialogue: 0,0:51:40.72,0:51:42.99,Default,,0,0,0,,但你们可以看到求值器控制流\nDialogue: 0,0:51:43.25,0:51:46.12,Default,,0,0,0,,的中心思想就是进行归约\nDialogue: 0,0:51:47.02,0:51:49.29,Default,,0,0,0,,因此这些过程实际上是迭代过程\nDialogue: 0,0:51:50.13,0:51:51.38,Default,,0,0,0,,好吧 有什么问题么？\nDialogue: 0,0:52:02.68,0:52:03.23,Default,,0,0,0,,好吧 课件休息吧\nDialogue: 0,0:52:04.12,0:52:24.56,Default,,0,0,0,,[音乐]\nDialogue: 0,0:52:24.60,0:52:29.69,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:52:35.20,0:52:38.36,Declare,,0,0,0,,{\\an2\\fad(500,500)}讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nDialogue: 0,0:52:38.36,0:52:42.14,Declare,,0,0,0,,{\\an2\\fad(500,500)}《计算机程序的构造和解释》\nDialogue: 0,0:52:42.14,0:52:46.44,Declare,,0,0,0,,{\\an2\\fad(500,500)}显示控制求值器\nDialogue: 0,0:52:48.77,0:52:51.55,Default,,0,0,0,,教授：跟迭代过程形成对比的是\nDialogue: 0,0:52:52.77,0:52:54.89,Default,,0,0,0,,确实会占用空间的\nDialogue: 0,0:52:55.12,0:52:56.14,Default,,0,0,0,,递归过程\nDialogue: 0,0:52:56.17,0:52:57.29,Default,,0,0,0,,你们可以看到其中的区别\nDialogue: 0,0:52:58.03,0:53:01.20,Default,,0,0,0,,让我们来看看递归式阶乘的求值\nDialogue: 0,0:53:02.65,0:53:05.53,Default,,0,0,0,,这里的FACT-REC\nDialogue: 0,0:53:05.55,0:53:07.22,Default,,0,0,0,,就是阶乘的标准定义\nDialogue: 0,0:53:07.22,0:53:10.01,Default,,0,0,0,,这个当然是一个递归过程\nDialogue: 0,0:53:10.01,0:53:12.57,Default,,0,0,0,,它的计算过程也是递归的\nDialogue: 0,0:53:13.75,0:53:16.56,Default,,0,0,0,,然后 只要把它和我们开始的方式联系起来\nDialogue: 0,0:53:16.83,0:53:20.53,Default,,0,0,0,,我们会通过代换模型发现\nDialogue: 0,0:53:20.53,0:53:21.82,Default,,0,0,0,,这是一个递归过程\nDialogue: 0,0:53:22.36,0:53:28.00,Default,,0,0,0,,因为 如果我调用(REC-FACT 5)\nDialogue: 0,0:53:30.45,0:53:34.94,Default,,0,0,0,,会变成(* 5\nDialogue: 0,0:53:36.28,0:53:37.82,Default,,0,0,0,,哦 这里是FACT-REC\nDialogue: 0,0:53:42.62,0:53:47.93,Default,,0,0,0,,(* 5 (FACT-REC 4))\nDialogue: 0,0:53:49.66,0:53:58.22,Default,,0,0,0,,又会变成(* 5 (* 4 (FACT-REC 3)))\nDialogue: 0,0:54:00.22,0:54:08.60,Default,,0,0,0,,又会变成(* 5 (* 4 (* 3 (* ...\nDialogue: 0,0:54:13.45,0:54:15.31,Default,,0,0,0,,以此类推\nDialogue: 0,0:54:15.39,0:54:17.39,Default,,0,0,0,,关键点就是 有一条链条被不断构造出来\nDialogue: 0,0:54:18.10,0:54:20.06,Default,,0,0,0,,这就在代换模型中证明了\nDialogue: 0,0:54:20.08,0:54:21.28,Default,,0,0,0,,FACT-REC是递归的\nDialogue: 0,0:54:21.52,0:54:24.18,Default,,0,0,0,,现在 让我们来看看这条构造起来的链条\nDialogue: 0,0:54:24.18,0:54:25.29,Default,,0,0,0,,它又是在机器中的什么地方？\nDialogue: 0,0:54:27.68,0:54:29.95,Default,,0,0,0,,好吧 让我们想象一下要从哪里开始\nDialogue: 0,0:54:30.44,0:54:40.01,Default,,0,0,0,,我们告诉机器 求值(FACT-REC 5)\nDialogue: 0,0:54:41.45,0:54:43.39,Default,,0,0,0,,基于的环境是E0\nDialogue: 0,0:54:45.08,0:54:48.97,Default,,0,0,0,,也就是定义FACT-REC时的环境\nDialogue: 0,0:54:49.55,0:54:51.23,Default,,0,0,0,,现在 我们知道最终要发生什么\nDialogue: 0,0:54:52.25,0:54:53.64,Default,,0,0,0,,首先\nDialogue: 0,0:54:53.92,0:54:55.64,Default,,0,0,0,,它会对这些东西求值\nDialogue: 0,0:54:55.68,0:54:56.99,Default,,0,0,0,,发现它是一个过程\nDialogue: 0,0:54:57.18,0:55:00.16,Default,,0,0,0,,在这里创建一个新环境E1\nDialogue: 0,0:55:00.88,0:55:03.69,Default,,0,0,0,,其中N=5\nDialogue: 0,0:55:04.33,0:55:06.54,Default,,0,0,0,,并且与E0相连\nDialogue: 0,0:55:07.80,0:55:08.97,Default,,0,0,0,,这个E0也就是\nDialogue: 0,0:55:08.99,0:55:12.30,Default,,0,0,0,,定义FACT-REC的那个环境\nDialogue: 0,0:55:14.11,0:55:15.74,Default,,0,0,0,,然后 在E1这个环境中\nDialogue: 0,0:55:15.76,0:55:17.48,Default,,0,0,0,,求值过程的体\nDialogue: 0,0:55:19.67,0:55:25.92,Default,,0,0,0,,因此 在这里求值会归约为\nDialogue: 0,0:55:27.00,0:55:28.92,Default,,0,0,0,,在E1中求值过程的体\nDialogue: 0,0:55:30.16,0:55:31.34,Default,,0,0,0,,这就需要求值IF语句\nDialogue: 0,0:55:32.17,0:55:33.53,Default,,0,0,0,,而我不会讲解IF语句的细节\nDialogue: 0,0:55:33.53,0:55:34.88,Default,,0,0,0,,IF语句会求值谓词\nDialogue: 0,0:55:34.88,0:55:37.53,Default,,0,0,0,,最后发现需要求值ELSE子句\nDialogue: 0,0:55:37.84,0:55:40.41,Default,,0,0,0,,因此 这里的整个部分 会归约为\nDialogue: 0,0:55:41.30,0:55:45.53,Default,,0,0,0,,FACT-REC的ELSE子句\nDialogue: 0,0:55:45.82,0:55:46.97,Default,,0,0,0,,也就是谓词为假的部分\nDialogue: 0,0:55:47.23,0:55:51.16,Default,,0,0,0,,整个表达式就归约为了(* N\nDialogue: 0,0:55:53.07,0:55:59.96,Default,,0,0,0,,(FACT-REC (- N 1))\nDialogue: 0,0:56:03.48,0:56:05.55,Default,,0,0,0,,求值的环境是E1\nDialogue: 0,0:56:08.38,0:56:10.91,Default,,0,0,0,,因此 最初的表达式现在就会归约为\nDialogue: 0,0:56:11.04,0:56:12.52,Default,,0,0,0,,求值这样的一个表达式\nDialogue: 0,0:56:13.75,0:56:16.28,Default,,0,0,0,,而现在 我们面对的是一个应用\nDialogue: 0,0:56:16.28,0:56:17.63,Default,,0,0,0,,我们之前求值过应用\nDialogue: 0,0:56:18.22,0:56:20.25,Default,,0,0,0,,还记得要怎么求值应用么？\nDialogue: 0,0:56:20.36,0:56:21.69,Default,,0,0,0,,正式求值一个应用之前\nDialogue: 0,0:56:21.74,0:56:24.81,Default,,0,0,0,,你需要把CONTINUE寄存器的值保存在栈上\nDialogue: 0,0:56:25.35,0:56:27.18,Default,,0,0,0,,此时 栈上会有一个值'DONE\nDialogue: 0,0:56:29.98,0:56:32.88,Default,,0,0,0,,接下来 你要为求值子部分做准备\nDialogue: 0,0:56:35.00,0:56:37.20,Default,,0,0,0,,因此 我们在这里开始求值子部分\nDialogue: 0,0:56:39.47,0:56:41.45,Default,,0,0,0,,首先要做的是求值运算符\nDialogue: 0,0:56:44.60,0:56:46.32,Default,,0,0,0,,运算符是怎样求值的呢？\nDialogue: 0,0:56:47.25,0:56:48.99,Default,,0,0,0,,我们通过一些手段\nDialogue: 0,0:56:49.00,0:56:51.04,Default,,0,0,0,,将EXP寄存器指向运算符对应的过程\nDialogue: 0,0:56:51.48,0:56:53.15,Default,,0,0,0,,并且让ENV寄存器指向求值的环境\nDialogue: 0,0:56:53.66,0:56:54.60,Default,,0,0,0,,而把CONTINUE寄存器赋值为\nDialogue: 0,0:56:54.62,0:56:56.22,Default,,0,0,0,,用于求值参数的EVAL-ARGS\nDialogue: 0,0:56:56.59,0:56:57.37,Default,,0,0,0,,并且 我们把\nDialogue: 0,0:56:57.40,0:56:59.29,Default,,0,0,0,,CONTINUE的原始值保存在栈上\nDialogue: 0,0:56:59.52,0:57:01.02,Default,,0,0,0,,我们完成所有工作后 就会跳转到这个地方\nDialogue: 0,0:57:01.72,0:57:02.86,Default,,0,0,0,,在我们求值完运算符后\nDialogue: 0,0:57:03.58,0:57:05.80,Default,,0,0,0,,需要做的则是\nDialogue: 0,0:57:05.90,0:57:07.66,Default,,0,0,0,,求值对实际参数进行求值\nDialogue: 0,0:57:07.69,0:57:12.01,Default,,0,0,0,,也就是这个环境和这些参数\nDialogue: 0,0:57:12.14,0:57:13.44,Default,,0,0,0,,这些尚未求值的实际参数\nDialogue: 0,0:57:14.20,0:57:15.62,Default,,0,0,0,,它们现在都还在栈上\nDialogue: 0,0:57:15.62,0:57:18.59,Default,,0,0,0,,我们现在就要先来求值运算符\nDialogue: 0,0:57:23.26,0:57:26.73,Default,,0,0,0,,当我们从这个调用返回时\nDialogue: 0,0:57:26.92,0:57:28.64,Default,,0,0,0,,在这里 我们将要去调用EVAL-DISPATCH\nDialogue: 0,0:57:29.38,0:57:30.83,Default,,0,0,0,,当我们从这个调用返回时\nDialogue: 0,0:57:31.45,0:57:32.70,Default,,0,0,0,,这个运算符所对应的值\nDialogue: 0,0:57:32.73,0:57:33.52,Default,,0,0,0,,在本例中\nDialogue: 0,0:57:33.55,0:57:35.44,Default,,0,0,0,,也就是基本的乘法过程\nDialogue: 0,0:57:36.44,0:57:37.93,Default,,0,0,0,,会存放在FUN寄存器中\nDialogue: 0,0:57:43.02,0:57:44.53,Default,,0,0,0,,我们要去求值实际参数\nDialogue: 0,0:57:44.53,0:57:45.85,Default,,0,0,0,,现在这里求值N\nDialogue: 0,0:57:47.73,0:57:49.87,Default,,0,0,0,,本例中 会返回5\nDialogue: 0,0:57:50.25,0:57:52.04,Default,,0,0,0,,然后我们会把它放入ARGL寄存器\nDialogue: 0,0:57:53.00,0:57:55.88,Default,,0,0,0,,然后我们会去求值第二个运算对象\nDialogue: 0,0:57:57.46,0:58:00.48,Default,,0,0,0,,就在我们准备求值第二个运算对象之时\nDialogue: 0,0:58:00.52,0:58:02.19,Default,,0,0,0,,我会省略计算\nDialogue: 0,0:58:02.20,0:58:03.58,Default,,0,0,0,,(- N 1)之类的细节\nDialogue: 0,0:58:03.71,0:58:05.88,Default,,0,0,0,,但是 当我们去求值第二个运算对象时\nDialogue: 0,0:58:06.62,0:58:10.44,Default,,0,0,0,,会最终归约为对FACT-REC的另一个调用\nDialogue: 0,0:58:12.00,0:58:14.20,Default,,0,0,0,,现在 我们在栈上有\nDialogue: 0,0:58:16.52,0:58:19.94,Default,,0,0,0,,来自于这个组合式的运算符\nDialogue: 0,0:58:20.12,0:58:21.07,Default,,0,0,0,,以及其它的参数\nDialogue: 0,0:58:23.40,0:58:27.61,Default,,0,0,0,,现在 我们已经准备好\nDialogue: 0,0:58:28.49,0:58:29.69,Default,,0,0,0,,去调用另外的FACT-REC了\nDialogue: 0,0:58:30.20,0:58:31.43,Default,,0,0,0,,而让我们完成了这个调用以后\nDialogue: 0,0:58:31.56,0:58:33.64,Default,,0,0,0,,我们就要跳转到ACCUMULATE-LAST-ARG\nDialogue: 0,0:58:34.12,0:58:35.20,Default,,0,0,0,,还记得这是做什么的么？\nDialogue: 0,0:58:35.20,0:58:35.93,Default,,0,0,0,,它会说\nDialogue: 0,0:58:36.45,0:58:39.28,Default,,0,0,0,,我们会把这个调用的结果\nDialogue: 0,0:58:39.28,0:58:40.40,Default,,0,0,0,,和这个5相乘\nDialogue: 0,0:58:41.69,0:58:42.38,Default,,0,0,0,,但是请注意\nDialogue: 0,0:58:42.73,0:58:44.81,Default,,0,0,0,,我们现在处于另一个递归阶乘中\nDialogue: 0,0:58:45.72,0:58:48.92,Default,,0,0,0,,我们又要再次调用EVAL-DISPATCH\nDialogue: 0,0:58:49.32,0:58:50.60,Default,,0,0,0,,然而我们并没有真正地“归约”它\nDialogue: 0,0:58:50.64,0:58:52.08,Default,,0,0,0,,因为现在栈上还有东西\nDialogue: 0,0:58:53.70,0:58:55.39,Default,,0,0,0,,栈上的这些东西说：“当你返回时”\nDialogue: 0,0:58:55.40,0:58:57.52,Default,,0,0,0,,你最好把结果和放在这里的5相乘\nDialogue: 0,0:58:58.43,0:59:05.77,Default,,0,0,0,,所以当我们进行另外的调用\nDialogue: 0,0:59:07.12,0:59:08.84,Default,,0,0,0,,求值(- N 1)\nDialogue: 0,0:59:09.30,0:59:11.05,Default,,0,0,0,,这会返回给我们另一个环境\nDialogue: 0,0:59:11.25,0:59:13.84,Default,,0,0,0,,其中N的新值为4\nDialogue: 0,0:59:14.60,0:59:16.22,Default,,0,0,0,,然后又将调用EVAL-DISPATCH\nDialogue: 0,0:59:19.20,0:59:20.22,Default,,0,0,0,,我们又创建了另一个调用\nDialogue: 0,0:59:21.35,0:59:24.44,Default,,0,0,0,,这个4又会遇到相同的情况\nDialogue: 0,0:59:26.04,0:59:28.62,Default,,0,0,0,,我们最后会遇到对(FACT-REC N)的又一次调用\nDialogue: 0,0:59:30.02,0:59:32.68,Default,,0,0,0,,而这时候 栈上会有从最初的调用\nDialogue: 0,0:59:32.88,0:59:34.51,Default,,0,0,0,,到最近一次调用的东西\nDialogue: 0,0:59:35.36,0:59:36.91,Default,,0,0,0,,它们都在等待同一个东西\nDialogue: 0,0:59:36.91,0:59:39.16,Default,,0,0,0,,它们都要跳转到ACCUMULATE-LAST-ARG\nDialogue: 0,0:59:40.51,0:59:42.94,Default,,0,0,0,,当然 当我们进行第四次调用时\nDialogue: 0,0:59:43.25,0:59:44.38,Default,,0,0,0,,会发生同样的事\nDialogue: 0,0:59:45.64,0:59:47.07,Default,,0,0,0,,如此往复\nDialogue: 0,0:59:47.30,0:59:48.60,Default,,0,0,0,,在这里 你在栈上看到的\nDialogue: 0,0:59:50.30,0:59:52.22,Default,,0,0,0,,栈上面实际存放的是\nDialogue: 0,0:59:52.22,0:59:54.59,Default,,0,0,0,,基本过程*以及5\nDialogue: 0,0:59:54.96,0:59:56.40,Default,,0,0,0,,而你要把它用来\nDialogue: 0,0:59:56.59,0:59:58.54,Default,,0,0,0,,调用ACCUMULATE-LAST-ARG\nDialogue: 0,1:00:00.47,1:00:02.01,Default,,0,0,0,,就是这样 对吧？\nDialogue: 0,1:00:02.01,1:00:04.75,Default,,0,0,0,,这跟它们在表达式中的顺序是一致的\nDialogue: 0,1:00:05.65,1:00:10.65,Default,,0,0,0,,实际上 你将要应用的运算符\nDialogue: 0,1:00:11.72,1:00:14.30,Default,,0,0,0,,以及当你返回时\nDialogue: 0,1:00:14.32,1:00:15.79,Default,,0,0,0,,需要去求积的参数\nDialogue: 0,1:00:15.80,1:00:16.91,Default,,0,0,0,,以及这里的括号\nDialogue: 0,1:00:16.94,1:00:18.96,Default,,0,0,0,,都在告诉你 在对它们进行积累\nDialogue: 0,1:00:19.62,1:00:21.88,Default,,0,0,0,,因此 你可以看到代换模型并不是这样的谎言\nDialogue: 0,1:00:22.56,1:00:23.63,Default,,0,0,0,,从某种意义上来说 它实际上是\nDialogue: 0,1:00:23.64,1:00:25.31,Default,,0,0,0,,存在于栈上的那些东西\nDialogue: 0,1:00:29.37,1:00:30.40,Default,,0,0,0,,好吧 从某种意义上来说\nDialogue: 0,1:00:30.81,1:00:32.48,Default,,0,0,0,,应该给你们解释了\nDialogue: 0,1:00:33.26,1:00:34.52,Default,,0,0,0,,或者 至少让你们相信\nDialogue: 0,1:00:35.93,1:00:38.72,Default,,0,0,0,,求值器会通过某些方式\nDialogue: 0,1:00:40.06,1:00:42.86,Default,,0,0,0,,迭代地去求值某些过程\nDialogue: 0,1:00:42.95,1:00:44.25,Default,,0,0,0,,而递归地去求值另外的过程\nDialogue: 0,1:00:45.26,1:00:47.45,Default,,0,0,0,,尽管从语法上看\nDialogue: 0,1:00:47.45,1:00:49.05,Default,,0,0,0,,它们都是递归过程\nDialogue: 0,1:00:49.40,1:00:50.64,Default,,0,0,0,,它又是如何做到的呢？\nDialogue: 0,1:00:50.66,1:00:53.72,Default,,0,0,0,,其中的基本原因就是\nDialogue: 0,1:00:53.80,1:00:55.68,Default,,0,0,0,,求值器被设置为\nDialogue: 0,1:00:56.04,1:00:59.26,Default,,0,0,0,,只保存那些稍后会用到的东西\nDialogue: 0,1:01:01.09,1:01:04.25,Default,,0,0,0,,比如说 当你在把\nDialogue: 0,1:01:04.67,1:01:07.39,Default,,0,0,0,,在一个环境中求值表达式归约为\nDialogue: 0,1:01:07.87,1:01:09.87,Default,,0,0,0,,将某个过程应用在参数上时\nDialogue: 0,1:01:10.52,1:01:12.49,Default,,0,0,0,,它就不再需要最初的环境了\nDialogue: 0,1:01:13.37,1:01:16.65,Default,,0,0,0,,因为所需要的环境信息都被打包到\nDialogue: 0,1:01:17.88,1:01:19.36,Default,,0,0,0,,需要应用的那个过程中了\nDialogue: 0,1:01:20.75,1:01:21.61,Default,,0,0,0,,同样 类似地\nDialogue: 0,1:01:21.63,1:01:23.65,Default,,0,0,0,,当你求值一个参数表时\nDialogue: 0,1:01:23.65,1:01:25.20,Default,,0,0,0,,当你完成对表的求值时\nDialogue: 0,1:01:25.91,1:01:28.03,Default,,0,0,0,,当你求值完最后一个参数时\nDialogue: 0,1:01:28.20,1:01:31.61,Default,,0,0,0,,你就不再需要这个参数表了 对吧？\nDialogue: 0,1:01:31.63,1:01:32.94,Default,,0,0,0,,你也就不再需要\nDialogue: 0,1:01:33.04,1:01:34.64,Default,,0,0,0,,求值这些参数所需的环境了\nDialogue: 0,1:01:36.69,1:01:40.89,Default,,0,0,0,,所以这个解释器如此“智能”的根本原因\nDialogue: 0,1:01:40.89,1:01:42.88,Default,,0,0,0,,根本不是因为它“智能” 只是因为它老实\nDialogue: 0,1:01:43.05,1:01:45.74,Default,,0,0,0,,它的原则就是：“只保存那些需要的”\nDialogue: 0,1:01:48.70,1:01:51.00,Default,,0,0,0,,这里 让我来给你们展示\nDialogue: 0,1:01:53.07,1:01:57.20,Default,,0,0,0,,这是致使尾递归的根本原因\nDialogue: 0,1:01:58.31,1:02:00.20,Default,,0,0,0,,要记住 (RESOTRE CONTINUE)这条代码\nDialogue: 0,1:02:00.22,1:02:06.94,Default,,0,0,0,,它指的是 当我去求值过程体的时候\nDialogue: 0,1:02:08.96,1:02:11.00,Default,,0,0,0,,我应该告诉EVAL返回到\nDialogue: 0,1:02:11.25,1:02:12.54,Default,,0,0,0,,最初的求值\nDialogue: 0,1:02:12.54,1:02:14.25,Default,,0,0,0,,应该返回的地方\nDialogue: 0,1:02:15.17,1:02:15.95,Default,,0,0,0,,因此 从某种角度来说\nDialogue: 0,1:02:16.17,1:02:18.84,Default,,0,0,0,,你想知道是哪一行代码致使了尾递归\nDialogue: 0,1:02:18.89,1:02:19.44,Default,,0,0,0,,那么就是这一行\nDialogue: 0,1:02:19.92,1:02:21.53,Default,,0,0,0,,出于某些奇怪的原因\nDialogue: 0,1:02:21.77,1:02:24.80,Default,,0,0,0,,如果我想构建一个没有尾递归的求值器\nDialogue: 0,1:02:25.69,1:02:26.86,Default,,0,0,0,,我需要做的就是\nDialogue: 0,1:02:27.12,1:02:29.29,Default,,0,0,0,,在这里先不要去恢复CONTINUE\nDialogue: 0,1:02:30.06,1:02:31.66,Default,,0,0,0,,而是在这里建立一个标号\nDialogue: 0,1:02:32.75,1:02:36.25,Default,,0,0,0,,用来标识完成过程应用后的返回位置\nDialogue: 0,1:02:37.64,1:02:39.71,Default,,0,0,0,,而我会把CONTINUE设置为这个标号\nDialogue: 0,1:02:39.92,1:02:41.21,Default,,0,0,0,,然后跳转到EVAL-DISPATCH\nDialogue: 0,1:02:41.40,1:02:43.21,Default,,0,0,0,,然后EVAL-DISPATCH会回到这里\nDialogue: 0,1:02:43.79,1:02:44.30,Default,,0,0,0,,而这时\nDialogue: 0,1:02:44.32,1:02:45.28,Default,,0,0,0,,我会恢复CONTINUE\nDialogue: 0,1:02:45.29,1:02:46.52,Default,,0,0,0,,并回到最初的返回位置\nDialogue: 0,1:02:47.92,1:02:51.00,Default,,0,0,0,,因此 这里唯一的后果就是\nDialogue: 0,1:02:51.15,1:02:52.68,Default,,0,0,0,,解释器不再是尾递归的了\nDialogue: 0,1:02:52.84,1:02:54.62,Default,,0,0,0,,它会给你完全相同的答案\nDialogue: 0,1:02:54.72,1:02:57.02,Default,,0,0,0,,只是当你执行迭代式阶乘\nDialogue: 0,1:02:57.05,1:02:58.36,Default,,0,0,0,,或者其它迭代过程时\nDialogue: 0,1:02:58.60,1:02:59.80,Default,,0,0,0,,它都会递归地去执行\nDialogue: 0,1:03:03.04,1:03:05.40,Default,,0,0,0,,然而 我对你们撒了一个小谎\nDialogue: 0,1:03:05.76,1:03:06.99,Default,,0,0,0,,因为我演示的\nDialogue: 0,1:03:07.02,1:03:08.33,Default,,0,0,0,,一个有些过于简化的解释器\nDialogue: 0,1:03:08.72,1:03:10.38,Default,,0,0,0,,这个解释器假设每个过程\nDialogue: 0,1:03:11.36,1:03:13.66,Default,,0,0,0,,只含有一条表达式\nDialogue: 0,1:03:13.89,1:03:14.54,Default,,0,0,0,,还记得吗 通常来说\nDialogue: 0,1:03:14.56,1:03:16.57,Default,,0,0,0,,过程的体是多条表达式组成的序列\nDialogue: 0,1:03:17.87,1:03:20.49,Default,,0,0,0,,所以没有什么新概念\nDialogue: 0,1:03:20.49,1:03:22.28,Default,,0,0,0,,让我来展示一下实际的求值器\nDialogue: 0,1:03:22.89,1:03:24.73,Default,,0,0,0,,是怎么来处理表达式序列的\nDialogue: 0,1:03:28.47,1:03:29.74,Default,,0,0,0,,这是现在的COMPOUND-APPLY\nDialogue: 0,1:03:29.74,1:03:31.31,Default,,0,0,0,,和之前的唯一不同是\nDialogue: 0,1:03:32.07,1:03:34.33,Default,,0,0,0,,它不再直接地跳转到EVAL\nDialogue: 0,1:03:35.98,1:03:38.03,Default,,0,0,0,,它先获取整个过程的体\nDialogue: 0,1:03:38.03,1:03:40.15,Default,,0,0,0,,在本例中 也就是表达式序列\nDialogue: 0,1:03:40.28,1:03:41.71,Default,,0,0,0,,然后跳转到EVAL-SEQUENCE\nDialogue: 0,1:03:42.60,1:03:45.32,Default,,0,0,0,,EVAL-SEQUENCE是一个小型的循环\nDialogue: 0,1:03:46.83,1:03:49.98,Default,,0,0,0,,然后每次求值一条表达式\nDialogue: 0,1:03:52.63,1:03:53.85,Default,,0,0,0,,就是这样来求值的--\nDialogue: 0,1:03:53.90,1:03:54.94,Default,,0,0,0,,当它求值完一条表达式后\nDialogue: 0,1:03:54.97,1:03:56.86,Default,,0,0,0,,会跳转到这里 去求值下一条\nDialogue: 0,1:03:58.44,1:03:59.29,Default,,0,0,0,,当我完成了所有的求值后\nDialogue: 0,1:03:59.29,1:04:01.02,Default,,0,0,0,,我想要跳转到LAST-EXP\nDialogue: 0,1:04:01.31,1:04:03.28,Default,,0,0,0,,我就只需要恢复CONTINUE寄存器\nDialogue: 0,1:04:03.92,1:04:05.28,Default,,0,0,0,,然后跳转到EVAL-DISPATCH\nDialogue: 0,1:04:06.41,1:04:08.20,Default,,0,0,0,,同样的 如果你想要在这种求值器中\nDialogue: 0,1:04:08.20,1:04:10.35,Default,,0,0,0,,破坏尾递归机制\nDialogue: 0,1:04:10.64,1:04:13.71,Default,,0,0,0,,你只需要在LAST-EXP中不做特殊处理即可\nDialogue: 0,1:04:14.90,1:04:17.34,Default,,0,0,0,,也就是说 当你处理完最后一条表达式\nDialogue: 0,1:04:17.36,1:04:18.65,Default,,0,0,0,,你跳转到另外一个地方\nDialogue: 0,1:04:19.15,1:04:20.68,Default,,0,0,0,,在那个地方去恢复CONTINUE\nDialogue: 0,1:04:21.90,1:04:23.26,Default,,0,0,0,,出于某些原因\nDialogue: 0,1:04:23.26,1:04:25.74,Default,,0,0,0,,很多Lisp求值器倾向于这么做\nDialogue: 0,1:04:26.55,1:04:28.44,Default,,0,0,0,,这样做的后果就是\nDialogue: 0,1:04:28.86,1:04:30.72,Default,,0,0,0,,迭代式过程也会使栈增长\nDialogue: 0,1:04:31.88,1:04:33.61,Default,,0,0,0,,还不清楚为什么会这样\nDialogue: 0,1:04:35.92,1:04:37.98,Default,,0,0,0,,好吧 我稍微来总结一下\nDialogue: 0,1:04:38.09,1:04:39.60,Default,,0,0,0,,毕竟这是一个大程序\nDialogue: 0,1:04:39.98,1:04:41.04,Default,,0,0,0,,又有很多细节\nDialogue: 0,1:04:41.12,1:04:42.25,Default,,0,0,0,,但关键点就是\nDialogue: 0,1:04:43.04,1:04:43.87,Default,,0,0,0,,从概念上来说\nDialogue: 0,1:04:44.04,1:04:46.08,Default,,0,0,0,,这跟翻译其它程序没什么不同\nDialogue: 0,1:04:47.06,1:04:48.06,Default,,0,0,0,,核心思想就是\nDialogue: 0,1:04:48.06,1:04:50.28,Default,,0,0,0,,我们已经有了通用求值器程序\nDialogue: 0,1:04:50.33,1:04:51.71,Default,,0,0,0,,一个元循环求值器\nDialogue: 0,1:04:51.87,1:04:53.07,Default,,0,0,0,,如果我们把它翻译为了Lisp\nDialogue: 0,1:04:53.10,1:04:53.95,Default,,0,0,0,,那么我们就有了Lisp的所有东西\nDialogue: 0,1:04:54.33,1:04:55.15,Default,,0,0,0,,我们就是这么来做的\nDialogue: 0,1:04:57.98,1:04:59.68,Default,,0,0,0,,第二点则是 魔法消失了\nDialogue: 0,1:04:59.68,1:05:01.97,Default,,0,0,0,,这整个系统不再神秘了 对吧？\nDialogue: 0,1:05:01.97,1:05:07.79,Default,,0,0,0,,原则上来说 这应该相当清楚了\nDialogue: 0,1:05:07.82,1:05:10.08,Default,,0,0,0,,只是还不太了解表结构的内存管理\nDialogue: 0,1:05:10.80,1:05:11.80,Default,,0,0,0,,我们后面会讲\nDialogue: 0,1:05:12.64,1:05:14.20,Default,,0,0,0,,这也并不困难\nDialogue: 0,1:05:15.45,1:05:16.35,Default,,0,0,0,,第三点就是\nDialogue: 0,1:05:16.35,1:05:17.52,Default,,0,0,0,,所有的这些尾递归\nDialogue: 0,1:05:18.24,1:05:21.96,Default,,0,0,0,,来自于严格的求值纪律\nDialogue: 0,1:05:22.55,1:05:24.51,Default,,0,0,0,,也就是只保存那些后面会用到的东西\nDialogue: 0,1:05:25.87,1:05:27.72,Default,,0,0,0,,而不是一些比较随意的原则\nDialogue: 0,1:05:27.76,1:05:29.86,Default,,0,0,0,,比如 无论什么时候我们调用一个子过程\nDialogue: 0,1:05:29.86,1:05:32.16,Default,,0,0,0,,我们会保存所有的寄存器并且返回\nDialogue: 0,1:05:33.94,1:05:36.49,Default,,0,0,0,,有些时候为了提效 这样做很值得\nDialogue: 0,1:05:37.15,1:05:39.96,Default,,0,0,0,,当你研究求值机器的内部原理时\nDialogue: 0,1:05:40.45,1:05:42.56,Default,,0,0,0,,这类东西就很值得去研究\nDialogue: 0,1:05:42.56,1:05:43.96,Default,,0,0,0,,因为它会带来显著的不同\nDialogue: 0,1:05:45.23,1:05:47.69,Default,,0,0,0,,我想现在基本上已经\nDialogue: 0,1:05:47.90,1:05:52.30,Default,,0,0,0,,把这个求值器讲得很清楚了\nDialogue: 0,1:05:52.56,1:05:53.90,Default,,0,0,0,,我希望你们能相信\nDialogue: 0,1:05:54.32,1:05:56.27,Default,,0,0,0,,真的有人能够\nDialogue: 0,1:05:56.84,1:05:58.56,Default,,0,0,0,,将一个Lisp求值器放在掌心之中\nDialogue: 0,1:05:59.07,1:06:00.49,Default,,0,0,0,,为了让你们死心塌地\nDialogue: 0,1:06:00.80,1:06:01.96,Default,,0,0,0,,我给你们看一个Lisp求值器\nDialogue: 0,1:06:02.54,1:06:04.06,Default,,0,0,0,,它就在我的手掌中\nDialogue: 0,1:06:06.16,1:06:10.56,Default,,0,0,0,,这块求值器芯片实际上\nDialogue: 0,1:06:10.89,1:06:13.70,Default,,0,0,0,,比我给你们展示的求值器还要复杂\nDialogue: 0,1:06:16.86,1:06:19.20,Default,,0,0,0,,这张图片效果更好\nDialogue: 0,1:06:22.07,1:06:22.57,Default,,0,0,0,,在这上面\nDialogue: 0,1:06:22.60,1:06:24.38,Default,,0,0,0,,你可以看到相同的宏观结构\nDialogue: 0,1:06:24.73,1:06:25.93,Default,,0,0,0,,这是寄存器阵列\nDialogue: 0,1:06:26.80,1:06:27.71,Default,,0,0,0,,这些是数据通路\nDialogue: 0,1:06:27.72,1:06:29.07,Default,,0,0,0,,这里有是有穷状态控制器\nDialogue: 0,1:06:29.80,1:06:31.04,Default,,0,0,0,,再强调一下 是有穷状态\nDialogue: 0,1:06:31.96,1:06:32.80,Default,,0,0,0,,全都在这里了\nDialogue: 0,1:06:32.81,1:06:34.16,Default,,0,0,0,,在另外的地方还有外部存储\nDialogue: 0,1:06:34.16,1:06:35.23,Default,,0,0,0,,用来存储数据\nDialogue: 0,1:06:35.75,1:06:37.63,Default,,0,0,0,,而这块芯片非常复杂\nDialogue: 0,1:06:37.64,1:06:39.16,Default,,0,0,0,,是因为它尝试更快地运行Lisp\nDialogue: 0,1:06:39.66,1:06:42.97,Default,,0,0,0,,它具有非常非常之快的并行运算\nDialogue: 0,1:06:43.07,1:06:46.32,Default,,0,0,0,,比如说 如果你想要索引一个数组\nDialogue: 0,1:06:46.70,1:06:50.40,Default,,0,0,0,,同时又要检查该索引是否为一个整数\nDialogue: 0,1:06:50.43,1:06:52.86,Default,,0,0,0,,以及该索引没有越界\nDialogue: 0,1:06:53.04,1:06:55.02,Default,,0,0,0,,同时还要进行内存存取\nDialogue: 0,1:06:55.05,1:06:56.70,Default,,0,0,0,,它会同时进行这些事\nDialogue: 0,1:06:57.12,1:06:58.40,Default,,0,0,0,,如果这些操作都没有问题的话\nDialogue: 0,1:06:58.44,1:06:59.96,Default,,0,0,0,,最终就会在这里得到结果\nDialogue: 0,1:07:00.42,1:07:02.46,Default,,0,0,0,,因此 数据通路中大量的\nDialogue: 0,1:07:02.48,1:07:04.65,Default,,0,0,0,,复杂运算使得Lisp能够并行运行\nDialogue: 0,1:07:05.26,1:07:08.41,Default,,0,0,0,,这完全是求值Lisp的\nDialogue: 0,1:07:08.76,1:07:10.36,Default,,0,0,0,,一种无冒险的哲学\nDialogue: 0,1:07:10.64,1:07:13.20,Default,,0,0,0,,并且 这个的微指令也相当复杂\nDialogue: 0,1:07:13.45,1:07:17.56,Default,,0,0,0,,让我先看一看\nDialogue: 0,1:07:17.60,1:07:21.10,Default,,0,0,0,,这其中有大概389条\nDialogue: 0,1:07:21.68,1:07:23.85,Default,,0,0,0,,220比特的微指令\nDialogue: 0,1:07:24.07,1:07:27.94,Default,,0,0,0,,只因为这些数据通路非常复杂\nDialogue: 0,1:07:27.94,1:07:32.25,Default,,0,0,0,,整个芯片大概有89,000支晶体管\nDialogue: 0,1:07:33.56,1:07:36.86,Default,,0,0,0,,好吧 我希望通过这节课解答了大部分疑惑\nDialogue: 0,1:07:37.97,1:07:39.24,Default,,0,0,0,,也许你们想看一看这块芯片\nDialogue: 0,1:07:46.14,1:07:46.89,Default,,0,0,0,,好吧 先讲到这里\nDialogue: 0,1:07:56.46,1:07:56.75,Default,,0,0,0,,有问题吗？\nDialogue: 0,1:07:59.00,1:08:00.42,Default,,0,0,0,,学生：您所讲的 听起来像是\nDialogue: 0,1:08:00.42,1:08:03.48,Default,,0,0,0,,如果把(RESTORE CONTINUE)放在合适的地方\nDialogue: 0,1:08:03.58,1:08:09.42,Default,,0,0,0,,这样之前递归求值的过程\nDialogue: 0,1:08:09.42,1:08:11.95,Default,,0,0,0,,现在就会变成迭代求值的\nDialogue: 0,1:08:12.67,1:08:15.36,Default,,0,0,0,,（意义不明）\nDialogue: 0,1:08:15.60,1:08:17.54,Default,,0,0,0,,教授：我想我应该这么来说\nDialogue: 0,1:08:17.54,1:08:19.82,Default,,0,0,0,,如果把(RESTORE CONTINUE)放在了错误的位置\nDialogue: 0,1:08:20.55,1:08:25.48,Default,,0,0,0,,你就会让那些语法上看起来像递归的过程\nDialogue: 0,1:08:25.52,1:08:27.28,Default,,0,0,0,,在运行的时候不断地扩张栈\nDialogue: 0,1:08:28.64,1:08:30.52,Default,,0,0,0,,但这样是没有原因的\nDialogue: 0,1:08:33.15,1:08:35.12,Default,,0,0,0,,你可以自己去试一试\nDialogue: 0,1:08:35.15,1:08:38.09,Default,,0,0,0,,你可以在COMPOND-APPLY返回后\nDialogue: 0,1:08:38.18,1:08:40.78,Default,,0,0,0,,交换两、三条语句的顺序\nDialogue: 0,1:08:41.31,1:08:43.26,Default,,0,0,0,,那么你得到的就不再是尾递归了\nDialogue: 0,1:08:45.06,1:08:46.14,Default,,0,0,0,,我只是想强调\nDialogue: 0,1:08:46.16,1:08:47.40,Default,,0,0,0,,这其中没有什么魔法\nDialogue: 0,1:08:47.67,1:08:48.57,Default,,0,0,0,,这并不是\nDialogue: 0,1:08:49.31,1:08:52.17,Default,,0,0,0,,有什么智能的预处理程序\nDialogue: 0,1:08:52.65,1:08:55.45,Default,,0,0,0,,它会分析FACT-ITER这个程序\nDialogue: 0,1:08:55.47,1:08:56.73,Default,,0,0,0,,然后说\nDialogue: 0,1:08:57.42,1:08:58.86,Default,,0,0,0,,我注意到\nDialogue: 0,1:08:58.88,1:09:01.13,Default,,0,0,0,,完成这个调用 不需要我进行压栈\nDialogue: 0,1:09:01.13,1:09:02.88,Default,,0,0,0,,但是有些人是这么认为的\nDialogue: 0,1:09:03.76,1:09:05.38,Default,,0,0,0,,而是一种比这个还要蠢的机制\nDialogue: 0,1:09:05.38,1:09:07.50,Default,,0,0,0,,就是在合适的地方插入RESTORE指令\nDialogue: 0,1:09:08.56,1:09:09.79,Default,,0,0,0,,就可以自动地实现\nDialogue: 0,1:09:14.72,1:09:17.55,Default,,0,0,0,,学生：但这不会影响到时间复杂度 对吧？\nDialogue: 0,1:09:17.58,1:09:17.87,Default,,0,0,0,,教授：不会\nDialogue: 0,1:09:18.60,1:09:21.77,Default,,0,0,0,,学生：它不会迭代地处理\nDialogue: 0,1:09:21.80,1:09:23.02,Default,,0,0,0,,而是会递归地处理\nDialogue: 0,1:09:23.02,1:09:27.34,Default,,0,0,0,,但就从完成这两个运算的时间来说\nDialogue: 0,1:09:27.37,1:09:29.22,Default,,0,0,0,,它们都是相同的 对吧？\nDialogue: 0,1:09:29.47,1:09:29.76,Default,,0,0,0,,教授 ：是的\nDialogue: 0,1:09:29.79,1:09:32.68,Default,,0,0,0,,尾递归不会改变任何东西的时间复杂度\nDialogue: 0,1:09:32.72,1:09:33.29,Default,,0,0,0,,因为 从某种意义上来说\nDialogue: 0,1:09:33.34,1:09:35.15,Default,,0,0,0,,两者都是相同的算法\nDialogue: 0,1:09:36.02,1:09:39.37,Default,,0,0,0,,它只是让这个过程迭代地运行\nDialogue: 0,1:09:41.00,1:09:42.64,Default,,0,0,0,,这样 当参数很大时\nDialogue: 0,1:09:42.68,1:09:44.22,Default,,0,0,0,,它不会耗尽所有的内存\nDialogue: 0,1:09:44.75,1:09:46.40,Default,,0,0,0,,因为这其中没有压栈\nDialogue: 0,1:09:48.35,1:09:50.24,Default,,0,0,0,,事实上 你们需要相信\nDialogue: 0,1:09:50.56,1:09:51.13,Default,,0,0,0,,当我们编写--\nDialogue: 0,1:09:51.64,1:09:53.78,Default,,0,0,0,,我们一直把这些代码称作“迭代”\nDialogue: 0,1:09:53.93,1:09:57.99,Default,,0,0,0,,把(DEFINE (LOOP) (LOOP))称作无穷循环\nDialogue: 0,1:10:00.32,1:10:03.36,Default,,0,0,0,,这就是一个迭代\nDialogue: 0,1:10:03.65,1:10:05.66,Default,,0,0,0,,跟我们用DO语句来写无穷循环是一样的\nDialogue: 0,1:10:07.63,1:10:09.28,Default,,0,0,0,,它们只是语法上不同而已\nDialogue: 0,1:10:09.28,1:10:11.32,Default,,0,0,0,,它们实际上都是迭代\nDialogue: 0,1:10:14.73,1:10:16.08,Default,,0,0,0,,它们并不改变时间复杂度\nDialogue: 0,1:10:16.11,1:10:18.53,Default,,0,0,0,,但是它会把它们变成真正的迭代\nDialogue: 0,1:10:21.68,1:10:23.80,Default,,0,0,0,,好吧 下课\nDialogue: 0,1:10:24.25,1:10:40.73,Declare,,0,0,0,,{\\fad(500,500)}MIT OpenCourseWare\\Nhttp://ocw.mit.edu\nDialogue: 0,1:10:24.25,1:10:40.73,Declare,,0,0,0,,{\\an2\\fad(500,500)}本项目主页\\Nhttps://github.com/DeathKing/Learning-SICP\n"
  },
  {
    "path": "Ass/lec9b.eng.ass",
    "content": "﻿[Script Info]\n; Script generated by Aegisub 3.2.2\n; http://www.aegisub.org/\nTitle: Default Aegisub file\nScriptType: v4.00+\nWrapStyle: 0\nScaledBorderAndShadow: yes\nYCbCr Matrix: TV.601\nPlayResX: 640\nPlayResY: 480\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: EN,Calisto MT,21,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\nStyle: Declare,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,0,8,10,10,10,1\nStyle: staff,微软雅黑,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,2,5,10,10,10,1\nStyle: title,微软雅黑,35,&H001D64D9,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,1,5,10,10,10,1\nStyle: Default,雅黑宋体,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1,0,2,10,10,30,1\n\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:16.30,0:00:18.08,EN,,0,0,0,,PROFESSOR: Well, I hope you appreciate that we have\nDialogue: 0,0:00:20.01,0:00:22.73,EN,,0,0,0,,we have inducted you into some real magic,\nDialogue: 0,0:00:24.20,0:00:27.24,EN,,0,0,0,,the magic of building languages\nDialogue: 0,0:00:27.42,0:00:28.72,EN,,0,0,0,,really building new languages.\nDialogue: 0,0:00:29.69,0:00:30.40,EN,,0,0,0,,What have we looked at?\nDialogue: 0,0:00:30.43,0:00:32.78,EN,,0,0,0,,We've looked at an Escher picture language.\nDialogue: 0,0:00:38.92,0:00:41.15,EN,,0,0,0,,OK? this language invented by Peter Henderson.\nDialogue: 0,0:00:42.01,0:00:46.49,EN,,0,0,0,,We looked at digital logic language.\nDialogue: 0,0:00:53.16,0:00:55.55,EN,,0,0,0,,Let's see.We've looked at the query language.\nDialogue: 0,0:00:59.70,0:01:00.78,EN,,0,0,0,,And the thing you should realize is,\nDialogue: 0,0:01:00.81,0:01:03.10,EN,,0,0,0,,even though these were toy examples,\nDialogue: 0,0:01:04.70,0:01:07.61,EN,,0,0,0,,they really are the kernels of really useful things.\nDialogue: 0,0:01:08.25,0:01:09.48,EN,,0,0,0,,So, for instance,\nDialogue: 0,0:01:10.12,0:01:11.18,EN,,0,0,0,,the Escher picture language\nDialogue: 0,0:01:11.20,0:01:14.33,EN,,0,0,0,,was taken byHenry Wu, who's a student at MIT,\nDialogue: 0,0:01:14.88,0:01:16.43,EN,,0,0,0,,and developed into a real\nDialogue: 0,0:01:16.97,0:01:19.45,EN,,0,0,0,,language for laying out PC boards,\nDialogue: 0,0:01:20.35,0:01:22.56,EN,,0,0,0,,based just on extending those structures.\nDialogue: 0,0:01:23.24,0:01:24.65,EN,,0,0,0,,And the digital logic language,\nDialogue: 0,0:01:24.68,0:01:26.08,EN,,0,0,0,,Gerry mentioned when he showed it to you,\nDialogue: 0,0:01:26.43,0:01:29.92,EN,,0,0,0,,was really extended to be used as the basis for a simulator\nDialogue: 0,0:01:30.85,0:01:32.96,EN,,0,0,0,,that was used to design a real computer.\nDialogue: 0,0:01:33.46,0:01:34.32,EN,,0,0,0,,And the query language,\nDialogue: 0,0:01:34.35,0:01:36.44,EN,,0,0,0,,of course, is kind of the germ of prolog.\nDialogue: 0,0:01:37.51,0:01:39.07,EN,,0,0,0,,So we built all of these languages,\nDialogue: 0,0:01:39.55,0:01:40.65,EN,,0,0,0,,they're all based on LISP.\nDialogue: 0,0:01:43.63,0:01:44.59,EN,,0,0,0,,A lot of people ask\nDialogue: 0,0:01:45.27,0:01:48.73,EN,,0,0,0,,what particular problems is LISP good for solving for?\nDialogue: 0,0:01:48.75,0:01:49.93,EN,,0,0,0,,The answer is LISP is not...\nDialogue: 0,0:01:50.33,0:01:52.65,EN,,0,0,0,,LISP is not good for solving any particular problems.\nDialogue: 0,0:01:53.53,0:01:54.60,EN,,0,0,0,,What LISP is good for\nDialogue: 0,0:01:54.73,0:01:57.15,EN,,0,0,0,,is constructing within it the right language\nDialogue: 0,0:01:57.18,0:01:58.57,EN,,0,0,0,,to solve the problems you want to solve,\nDialogue: 0,0:01:59.17,0:02:00.44,EN,,0,0,0,,and that's how you should think about it.\nDialogue: 0,0:02:01.47,0:02:03.39,EN,,0,0,0,,So all of these languages were based on LISP.\nDialogue: 0,0:02:04.57,0:02:05.72,EN,,0,0,0,,Now, what's LISP based on?\nDialogue: 0,0:02:06.97,0:02:07.88,EN,,0,0,0,,Where's that come from?\nDialogue: 0,0:02:07.90,0:02:09.40,EN,,0,0,0,,Well, we looked at that too.\nDialogue: 0,0:02:09.58,0:02:16.09,EN,,0,0,0,,We looked at the meta-circular evaluator\nDialogue: 0,0:02:21.53,0:02:23.40,EN,,0,0,0,,the meta-circular evaluator and sort of said\nDialogue: 0,0:02:23.42,0:02:25.76,EN,,0,0,0,,well, LISP is based on LISP.\nDialogue: 0,0:02:25.80,0:02:27.48,EN,,0,0,0,,And when we start looking at that,\nDialogue: 0,0:02:28.27,0:02:29.95,EN,,0,0,0,,we've got to do some real magic, right?\nDialogue: 0,0:02:29.95,0:02:31.74,EN,,0,0,0,,So what does that mean, right?\nDialogue: 0,0:02:31.74,0:02:34.96,EN,,0,0,0,,Y operators, and fixed points,\nDialogue: 0,0:02:35.76,0:02:38.33,EN,,0,0,0,,and the idea that what this means is\nDialogue: 0,0:02:38.36,0:02:41.44,EN,,0,0,0,,that LISP is somehow the fixed-point equation for the\nDialogue: 0,0:02:42.20,0:02:45.42,EN,,0,0,0,,for this funny set of things which are defined in terms of themselves.\nDialogue: 0,0:02:47.40,0:02:48.56,EN,,0,0,0,,Now, it's real magic.\nDialogue: 0,0:02:49.07,0:02:52.35,EN,,0,0,0,,Well, today, for a final piece of magic,\nDialogue: 0,0:02:52.62,0:02:54.03,EN,,0,0,0,,we're going to make all the magic go away.\nDialogue: 0,0:03:06.80,0:03:07.98,EN,,0,0,0,,We already know how to do that.\nDialogue: 0,0:03:09.77,0:03:10.76,EN,,0,0,0,,The idea is, we're going to take\nDialogue: 0,0:03:11.13,0:03:12.73,EN,,0,0,0,,the register machine architecture\nDialogue: 0,0:03:13.36,0:03:15.50,EN,,0,0,0,,and show how to implement LISP on terms of that.\nDialogue: 0,0:03:15.50,0:03:17.93,EN,,0,0,0,,And, remember, the idea of the register machine\nDialogue: 0,0:03:19.60,0:03:24.68,EN,,0,0,0,,is that there's a fixed and finite part of the machine.\nDialogue: 0,0:03:24.72,0:03:26.12,EN,,0,0,0,,There's a finite-state controller,\nDialogue: 0,0:03:26.12,0:03:27.87,EN,,0,0,0,,which dose particular thing\nDialogue: 0,0:03:27.88,0:03:29.31,EN,,0,0,0,,with a particular amount of hardware.\nDialogue: 0,0:03:30.51,0:03:31.74,EN,,0,0,0,,There are particular data paths,\nDialogue: 0,0:03:31.76,0:03:33.24,EN,,0,0,0,,the operation the machine does\nDialogue: 0,0:03:33.55,0:03:35.29,EN,,0,0,0,,And then, in order to implement recursion\nDialogue: 0,0:03:35.53,0:03:37.60,EN,,0,0,0,,and sustain the illusion of infinity,\nDialogue: 0,0:03:37.82,0:03:39.77,EN,,0,0,0,,there's some large amount of memory, which is the stack.\nDialogue: 0,0:03:42.06,0:03:43.72,EN,,0,0,0,,So, if we implement LISP\nDialogue: 0,0:03:43.92,0:03:45.50,EN,,0,0,0,,in terms of a register machine,\nDialogue: 0,0:03:47.02,0:03:48.35,EN,,0,0,0,,then everything ought to become,\nDialogue: 0,0:03:48.40,0:03:49.85,EN,,0,0,0,,at this point,completely concrete.\nDialogue: 0,0:03:49.85,0:03:51.23,EN,,0,0,0,,All the magic should go away.\nDialogue: 0,0:03:51.65,0:03:53.52,EN,,0,0,0,,And, by the end of this talk,\nDialogue: 0,0:03:53.53,0:03:54.78,EN,,0,0,0,,I want you get the feeling\nDialogue: 0,0:03:55.14,0:03:59.05,EN,,0,0,0,,that, as opposed to this very mysterious meta-circular evaluator\nDialogue: 0,0:03:59.67,0:04:02.60,EN,,0,0,0,,that a LISP evaluator really is something that's concrete enough\nDialogue: 0,0:04:02.85,0:04:04.57,EN,,0,0,0,,that you can hold in the palm of your hand.\nDialogue: 0,0:04:04.76,0:04:06.24,EN,,0,0,0,,You should be able to imagine holding\nDialogue: 0,0:04:06.57,0:04:07.90,EN,,0,0,0,,holding a LISP interpreter there.\nDialogue: 0,0:04:09.63,0:04:10.94,EN,,0,0,0,,All right, how are we going to do this?\nDialogue: 0,0:04:10.95,0:04:12.76,EN,,0,0,0,,We already have all the ingredients.\nDialogue: 0,0:04:13.96,0:04:17.45,EN,,0,0,0,,See, what you learned last time from Gerry\nDialogue: 0,0:04:17.60,0:04:21.47,EN,,0,0,0,,is how to take any particular couple of LISP procedures.\nDialogue: 0,0:04:22.60,0:04:24.28,EN,,0,0,0,,and hand-translate them\nDialogue: 0,0:04:24.75,0:04:26.67,EN,,0,0,0,,into something that runs on a register machine.\nDialogue: 0,0:04:28.20,0:04:30.52,EN,,0,0,0,,So, to implement all of LISP on a register machine,\nDialogue: 0,0:04:30.57,0:04:31.44,EN,,0,0,0,,all we have to do\nDialogue: 0,0:04:31.69,0:04:33.45,EN,,0,0,0,,is take the particular procedures\nDialogue: 0,0:04:33.68,0:04:35.42,EN,,0,0,0,,that are the meta-circular evaluator\nDialogue: 0,0:04:36.17,0:04:38.11,EN,,0,0,0,,and hand-translate them for a register machine.\nDialogue: 0,0:04:39.04,0:04:40.25,EN,,0,0,0,,And that does all of LISP\nDialogue: 0,0:04:42.14,0:04:43.00,EN,,0,0,0,,Right? So, in principle,\nDialogue: 0,0:04:43.02,0:04:44.43,EN,,0,0,0,,we already know how to do this.\nDialogue: 0,0:04:45.38,0:04:46.54,EN,,0,0,0,,And, indeed, it's going to be no\nDialogue: 0,0:04:46.68,0:04:48.86,EN,,0,0,0,,no different, in kind,\nDialogue: 0,0:04:50.00,0:04:53.40,EN,,0,0,0,,from in say recursive factorial\nDialogue: 0,0:04:53.42,0:04:54.67,EN,,0,0,0,,or recursive Fibonacci.\nDialogue: 0,0:04:54.67,0:04:56.00,EN,,0,0,0,,It's just bigger and there's more of it.\nDialogue: 0,0:04:56.84,0:04:58.03,EN,,0,0,0,,So it'd just be more details,\nDialogue: 0,0:04:58.04,0:04:59.66,EN,,0,0,0,,but nothing really conceptually new.\nDialogue: 0,0:05:01.48,0:05:03.02,EN,,0,0,0,,And also, when we've done that,\nDialogue: 0,0:05:03.08,0:05:04.76,EN,,0,0,0,,and the thing is completely explicit,\nDialogue: 0,0:05:04.87,0:05:06.91,EN,,0,0,0,,and we see how to implement LISP\nDialogue: 0,0:05:06.94,0:05:10.08,EN,,0,0,0,,in terms of the actual sequential register operations,\nDialogue: 0,0:05:10.16,0:05:11.63,EN,,0,0,0,,that's going to be our final\nDialogue: 0,0:05:11.95,0:05:14.16,EN,,0,0,0,,most explicit model of LISP in this course.\nDialogue: 0,0:05:14.81,0:05:16.95,EN,,0,0,0,,And, remember, that's a progression through this course.\nDialogue: 0,0:05:16.95,0:05:18.25,EN,,0,0,0,,We started out with substitution,\nDialogue: 0,0:05:18.28,0:05:19.58,EN,,0,0,0,,which is sort of like algebra.\nDialogue: 0,0:05:20.24,0:05:21.87,EN,,0,0,0,,And then we went to the environment model,\nDialogue: 0,0:05:21.88,0:05:24.00,EN,,0,0,0,,which talked about the actual frames\nDialogue: 0,0:05:24.03,0:05:25.31,EN,,0,0,0,,and how they got linked together.\nDialogue: 0,0:05:26.32,0:05:27.88,EN,,0,0,0,,And then we made that more concrete\nDialogue: 0,0:05:27.90,0:05:29.36,EN,,0,0,0,,in the meta-circular evaluator.\nDialogue: 0,0:05:31.05,0:05:31.64,EN,,0,0,0,,There are things\nDialogue: 0,0:05:31.87,0:05:33.98,EN,,0,0,0,,the meta-circular evaluator doesn't tell us.\nDialogue: 0,0:05:34.36,0:05:35.34,EN,,0,0,0,,You should realize that.\nDialogue: 0,0:05:36.09,0:05:38.64,EN,,0,0,0,,For instance, it left unanswered the question\nDialogue: 0,0:05:38.73,0:05:42.67,EN,,0,0,0,,of how a procedure, like recursive factorial here,\nDialogue: 0,0:05:45.17,0:05:47.13,EN,,0,0,0,,somehow takes space that grows.\nDialogue: 0,0:05:47.21,0:05:47.98,EN,,0,0,0,,On the other hand,\nDialogue: 0,0:05:48.16,0:05:51.94,EN,,0,0,0,,a procedure which also looks syntactically recursive,\nDialogue: 0,0:05:52.11,0:05:55.07,EN,,0,0,0,,called fact-iter, somehow doesn't take space.\nDialogue: 0,0:05:55.10,0:05:59.16,EN,,0,0,0,,We justify that it doesn't need to take space\nDialogue: 0,0:06:00.50,0:06:01.96,EN,,0,0,0,,by showing the substitution model.\nDialogue: 0,0:06:01.96,0:06:02.94,EN,,0,0,0,,But we didn't really say\nDialogue: 0,0:06:03.42,0:06:06.76,EN,,0,0,0,,how it happens that the machine manages to do that,\nDialogue: 0,0:06:07.31,0:06:08.91,EN,,0,0,0,,that that has to do with the details\nDialogue: 0,0:06:09.02,0:06:11.12,EN,,0,0,0,,of how arguments are passed to procedures\nDialogue: 0,0:06:12.48,0:06:13.69,EN,,0,0,0,,And that's the thing we didn't see\nDialogue: 0,0:06:13.71,0:06:15.34,EN,,0,0,0,,in the meta-circular evaluator\nDialogue: 0,0:06:15.36,0:06:17.40,EN,,0,0,0,,precisely because the way arguments\nDialogue: 0,0:06:17.42,0:06:19.20,EN,,0,0,0,,got passed to procedures in this LISP\nDialogue: 0,0:06:19.70,0:06:20.59,EN,,0,0,0,,depended on\nDialogue: 0,0:06:21.02,0:06:23.50,EN,,0,0,0,,the way arguments got passed to procedures in this LISP.\nDialogue: 0,0:06:25.87,0:06:29.02,EN,,0,0,0,,But, now, that's going to become extremely explicit.\nDialogue: 0,0:06:30.74,0:06:31.12,EN,,0,0,0,,OK.\nDialogue: 0,0:06:31.23,0:06:34.30,EN,,0,0,0,,Well, before going on to the evaluator,\nDialogue: 0,0:06:34.36,0:06:35.53,EN,,0,0,0,,let me just give you a sense of\nDialogue: 0,0:06:35.55,0:06:37.00,EN,,0,0,0,,what a whole LISP system looks like\nDialogue: 0,0:06:37.60,0:06:39.36,EN,,0,0,0,,so you can see the parts we're going to talk about\nDialogue: 0,0:06:39.40,0:06:40.81,EN,,0,0,0,,and the parts we're not going to talk about.\nDialogue: 0,0:06:43.18,0:06:47.42,EN,,0,0,0,,Let's see, over here is a happy LISP user,\nDialogue: 0,0:06:48.67,0:06:52.65,EN,,0,0,0,,and the LISP user is talking to something called the reader.\nDialogue: 0,0:07:00.36,0:07:01.53,EN,,0,0,0,,The reader's job in life\nDialogue: 0,0:07:01.95,0:07:13.23,EN,,0,0,0,,is to take characters from the user\nDialogue: 0,0:07:14.17,0:07:16.62,EN,,0,0,0,,and turn them into data structures\nDialogue: 0,0:07:17.20,0:07:19.37,EN,,0,0,0,,in something called a list structure memory.\nDialogue: 0,0:07:30.00,0:07:31.72,EN,,0,0,0,,All right, so the reader is going to take\nDialogue: 0,0:07:32.65,0:07:33.95,EN,,0,0,0,,symbols, parentheses,\nDialogue: 0,0:07:34.48,0:07:37.12,EN,,0,0,0,,and A's and B's, and 1s and 3s that you type in,\nDialogue: 0,0:07:37.18,0:07:39.04,EN,,0,0,0,,and turn these into actual list structure:\nDialogue: 0,0:07:39.15,0:07:40.54,EN,,0,0,0,,pairs, and pointers, and things.\nDialogue: 0,0:07:42.35,0:07:43.92,EN,,0,0,0,,And so, by the time evaluator is going,\nDialogue: 0,0:07:43.93,0:07:45.10,EN,,0,0,0,,there are no characters in the world.\nDialogue: 0,0:07:45.85,0:07:48.16,EN,,0,0,0,,And, of course, in more modern Lisp systems, there's\nDialogue: 0,0:07:49.00,0:07:50.44,EN,,0,0,0,,there's sort a big morass here\nDialogue: 0,0:07:50.44,0:07:52.17,EN,,0,0,0,,that might sit between the user and the reader:\nDialogue: 0,0:07:52.41,0:07:54.52,EN,,0,0,0,,you know, Windows systems, in top levels,\nDialogue: 0,0:07:54.77,0:07:56.03,EN,,0,0,0,,and mice, and all kinds of things.\nDialogue: 0,0:07:56.28,0:07:58.20,EN,,0,0,0,,But conceptually, characters are coming in.\nDialogue: 0,0:07:59.93,0:08:04.32,EN,,0,0,0,,All right, the reader transforms these into pointers\nDialogue: 0,0:08:05.56,0:08:07.28,EN,,0,0,0,,pointers to stuff in this memory,\nDialogue: 0,0:08:08.27,0:08:10.94,EN,,0,0,0,,and that's what the evaluator sees\nDialogue: 0,0:08:15.55,0:08:16.04,EN,,0,0,0,,OK?\nDialogue: 0,0:08:17.02,0:08:18.88,EN,,0,0,0,,The evaluator has a bunch of helpers.\nDialogue: 0,0:08:19.78,0:08:23.16,EN,,0,0,0,,It has all possible primitive operators you might want.\nDialogue: 0,0:08:23.16,0:08:24.91,EN,,0,0,0,,So there's a completely separate box,\nDialogue: 0,0:08:28.40,0:08:30.25,EN,,0,0,0,,a floating point unit,\nDialogue: 0,0:08:32.22,0:08:34.40,EN,,0,0,0,,or all sorts of things, which do the primitive operators.\nDialogue: 0,0:08:35.39,0:08:37.68,EN,,0,0,0,,there's and, if you want more special primitives,\nDialogue: 0,0:08:37.71,0:08:39.02,EN,,0,0,0,,you build more primitive operators,\nDialogue: 0,0:08:39.05,0:08:40.48,EN,,0,0,0,,but they're separate from the evaluator.\nDialogue: 0,0:08:42.08,0:08:43.77,EN,,0,0,0,,The evaluator finally gets an answer\nDialogue: 0,0:08:45.16,0:08:46.76,EN,,0,0,0,,and communicates that to the printer.\nDialogue: 0,0:08:50.62,0:08:52.01,EN,,0,0,0,,And now, the printer's job in life\nDialogue: 0,0:08:52.01,0:08:54.54,EN,,0,0,0,,is this list structure coming from the evaluator,\nDialogue: 0,0:08:55.39,0:08:56.99,EN,,0,0,0,,and turn it back into characters,\nDialogue: 0,0:09:01.85,0:09:04.07,EN,,0,0,0,,and communicate them to the user through\nDialogue: 0,0:09:04.28,0:09:05.66,EN,,0,0,0,,whatever interface there is.\nDialogue: 0,0:09:08.05,0:09:11.23,EN,,0,0,0,,OK. Well, today, what we're going to talk about is this evaluator.\nDialogue: 0,0:09:12.67,0:09:15.20,EN,,0,0,0,,The primitive operators have nothing particular to do with LISP,\nDialogue: 0,0:09:15.20,0:09:18.14,EN,,0,0,0,,they're however you like to implement primitive operations.\nDialogue: 0,0:09:19.36,0:09:22.18,EN,,0,0,0,,The reader and printer are actually complicated,\nDialogue: 0,0:09:22.18,0:09:23.55,EN,,0,0,0,,but we're not going to talk about them.\nDialogue: 0,0:09:24.68,0:09:27.10,EN,,0,0,0,,They sort of have to do with details of how you might build\nDialogue: 0,0:09:27.10,0:09:28.92,EN,,0,0,0,,build up list structure from characters.\nDialogue: 0,0:09:29.90,0:09:31.18,EN,,0,0,0,,So that is a long story,\nDialogue: 0,0:09:31.18,0:09:32.32,EN,,0,0,0,,but we're not going to talk about it,\nDialogue: 0,0:09:32.49,0:09:33.69,EN,,0,0,0,,the list structure memory,\nDialogue: 0,0:09:34.36,0:09:35.63,EN,,0,0,0,,we'll talk about next time.\nDialogue: 0,0:09:36.93,0:09:39.72,EN,,0,0,0,,So, pretty much, except for the details of reading and printing,\nDialogue: 0,0:09:40.12,0:09:41.71,EN,,0,0,0,,the only mystery that's going to be left\nDialogue: 0,0:09:41.72,0:09:43.05,EN,,0,0,0,,after you see the evaluator\nDialogue: 0,0:09:43.25,0:09:45.85,EN,,0,0,0,,is how you build list structure on conventional memories.\nDialogue: 0,0:09:46.65,0:09:48.20,EN,,0,0,0,,But we'll worry about that next time too.\nDialogue: 0,0:09:50.58,0:09:51.04,EN,,0,0,0,,OK.\nDialogue: 0,0:09:53.34,0:09:56.11,EN,,0,0,0,,Well, let's start talking about the evaluator.\nDialogue: 0,0:09:56.20,0:09:58.32,EN,,0,0,0,,The one that we're going to show you,\nDialogue: 0,0:09:58.49,0:10:01.12,EN,,0,0,0,,of course, is not, I think, nothing special about it.\nDialogue: 0,0:10:01.15,0:10:04.56,EN,,0,0,0,,It's just a particular register machine that runs LISP.\nDialogue: 0,0:10:04.81,0:10:06.09,EN,,0,0,0,,And it has seven registers,\nDialogue: 0,0:10:07.88,0:10:09.26,EN,,0,0,0,,and here are the seven registers.\nDialogue: 0,0:10:09.89,0:10:12.38,EN,,0,0,0,,There's a register, called EXP\nDialogue: 0,0:10:14.12,0:10:15.53,EN,,0,0,0,,and its job is to hold\nDialogue: 0,0:10:16.36,0:10:18.03,EN,,0,0,0,,the expression to be evaluated.\nDialogue: 0,0:10:18.37,0:10:19.80,EN,,0,0,0,,And by that, I mean\nDialogue: 0,0:10:20.38,0:10:21.64,EN,,0,0,0,,it's going to hold a pointer\nDialogue: 0,0:10:22.03,0:10:23.55,EN,,0,0,0,,to someplace in list structure memory\nDialogue: 0,0:10:23.56,0:10:25.32,EN,,0,0,0,,the expression to be evaluated.\nDialogue: 0,0:10:26.55,0:10:27.82,EN,,0,0,0,,There's a register, called ENV,\nDialogue: 0,0:10:28.88,0:10:30.28,EN,,0,0,0,,which holds the environment\nDialogue: 0,0:10:31.00,0:10:33.05,EN,,0,0,0,,in which this expression is to be evaluated.\nDialogue: 0,0:10:34.07,0:10:35.02,EN,,0,0,0,,And, again, I made a pointer.\nDialogue: 0,0:10:35.02,0:10:36.75,EN,,0,0,0,,The environment is some data structure.\nDialogue: 0,0:10:38.24,0:10:40.14,EN,,0,0,0,,There's a register, called FUN, which will\nDialogue: 0,0:10:40.75,0:10:42.54,EN,,0,0,0,,which will hold the procedure to be applied\nDialogue: 0,0:10:42.57,0:10:43.96,EN,,0,0,0,,when you go to apply a procedure.\nDialogue: 0,0:10:44.56,0:10:46.24,EN,,0,0,0,,A register, called ARGL,\nDialogue: 0,0:10:47.36,0:10:49.34,EN,,0,0,0,,which holds the list of evaluated arguments.\nDialogue: 0,0:10:50.54,0:10:51.60,EN,,0,0,0,,What you can start seeing here is\nDialogue: 0,0:10:51.63,0:10:53.14,EN,,0,0,0,,the basic structure of the evaluator.\nDialogue: 0,0:10:53.14,0:10:54.49,EN,,0,0,0,,Remember how evaluators work.\nDialogue: 0,0:10:54.49,0:10:56.62,EN,,0,0,0,,There's a piece that takes expressions and environments,\nDialogue: 0,0:10:57.67,0:10:59.71,EN,,0,0,0,,and there's a piece that takes functions\nDialogue: 0,0:10:59.74,0:11:02.14,EN,,0,0,0,,or procedures and arguments.\nDialogue: 0,0:11:03.48,0:11:06.30,EN,,0,0,0,,And going back and forth around here is the eval/apply loop.\nDialogue: 0,0:11:07.40,0:11:09.69,EN,,0,0,0,,So those are the basic pieces of the eval and apply.\nDialogue: 0,0:11:10.20,0:11:10.99,EN,,0,0,0,,Then there's some other things,\nDialogue: 0,0:11:11.00,0:11:11.61,EN,,0,0,0,,there's continue.\nDialogue: 0,0:11:11.61,0:11:15.34,EN,,0,0,0,,You just saw before how the continue register is used to\nDialogue: 0,0:11:15.34,0:11:18.04,EN,,0,0,0,,implement recursion and stack discipline.\nDialogue: 0,0:11:18.94,0:11:20.68,EN,,0,0,0,,There's a register that's going to hold the\nDialogue: 0,0:11:20.94,0:11:22.52,EN,,0,0,0,,result of some evaluation.\nDialogue: 0,0:11:24.14,0:11:24.89,EN,,0,0,0,,And then, besides that,\nDialogue: 0,0:11:24.89,0:11:26.43,EN,,0,0,0,,there's one temporary register,\nDialogue: 0,0:11:26.70,0:11:27.29,EN,,0,0,0,,called UNEV,\nDialogue: 0,0:11:27.29,0:11:29.04,EN,,0,0,0,,which typically, in the evaluator,\nDialogue: 0,0:11:29.28,0:11:32.72,EN,,0,0,0,,is going to be used to hold temporary pieces of the\nDialogue: 0,0:11:32.89,0:11:33.95,EN,,0,0,0,,expression you're working on,\nDialogue: 0,0:11:33.95,0:11:35.72,EN,,0,0,0,,which you haven't gotten around to evaluate yet\nDialogue: 0,0:11:36.97,0:11:39.82,EN,,0,0,0,,Right? So there's my machine: a seven-register machine.\nDialogue: 0,0:11:40.96,0:11:42.98,EN,,0,0,0,,And, of course, you might want to make a machine with\nDialogue: 0,0:11:42.98,0:11:44.96,EN,,0,0,0,,a lot more registers to get better performance,\nDialogue: 0,0:11:44.97,0:11:47.05,EN,,0,0,0,,but this is just a tiny, minimal one.\nDialogue: 0,0:11:48.48,0:11:49.58,EN,,0,0,0,,Well, how about the data paths?\nDialogue: 0,0:11:49.78,0:11:53.66,EN,,0,0,0,,This machine has a lot of special operations for LISP.\nDialogue: 0,0:11:55.10,0:11:58.08,EN,,0,0,0,,So, here are some typical data paths.\nDialogue: 0,0:12:00.12,0:12:01.04,EN,,0,0,0,,A typical one might be,\nDialogue: 0,0:12:01.37,0:12:03.40,EN,,0,0,0,,oh, assign to the VAL register\nDialogue: 0,0:12:03.40,0:12:04.80,EN,,0,0,0,,the contents of the EXP register.\nDialogue: 0,0:12:05.71,0:12:08.01,EN,,0,0,0,,That's in terms of those diagrams you saw,\nDialogue: 0,0:12:08.03,0:12:10.81,EN,,0,0,0,,that's a little button on some arrow.\nDialogue: 0,0:12:11.90,0:12:13.13,EN,,0,0,0,,Here's a more complicated one.\nDialogue: 0,0:12:13.69,0:12:14.80,EN,,0,0,0,,It says branch,\nDialogue: 0,0:12:15.23,0:12:19.58,EN,,0,0,0,,if the thing in the expression register is a conditional\nDialogue: 0,0:12:20.49,0:12:22.72,EN,,0,0,0,,to some label here, called the ev-conditional.\nDialogue: 0,0:12:23.80,0:12:26.23,EN,,0,0,0,,And you can imagine this implemented in a lot of different ways.\nDialogue: 0,0:12:26.23,0:12:28.36,EN,,0,0,0,,You might imagine this conditional test\nDialogue: 0,0:12:28.36,0:12:29.98,EN,,0,0,0,,as a special purpose sub-routine,\nDialogue: 0,0:12:30.60,0:12:33.95,EN,,0,0,0,,and conditional might be represented as some data abstraction\nDialogue: 0,0:12:33.96,0:12:36.00,EN,,0,0,0,,that you don't care about at this level of detail.\nDialogue: 0,0:12:36.61,0:12:37.98,EN,,0,0,0,,So that might be done as a sub-routine.\nDialogue: 0,0:12:37.98,0:12:40.67,EN,,0,0,0,,This might be a machine with hardware-types,\nDialogue: 0,0:12:40.90,0:12:44.04,EN,,0,0,0,,and conditional might be testing some bits for a particular code.\nDialogue: 0,0:12:45.35,0:12:46.41,EN,,0,0,0,,There are all sorts of ways that's\nDialogue: 0,0:12:46.41,0:12:48.48,EN,,0,0,0,,beneath the level of abstraction we're looking at.\nDialogue: 0,0:12:50.19,0:12:51.71,EN,,0,0,0,,Another kind of operation,\nDialogue: 0,0:12:51.71,0:12:53.24,EN,,0,0,0,,and there are a lot of different operations\nDialogue: 0,0:12:53.24,0:12:56.65,EN,,0,0,0,,assigned to EXP, the first clause of what's in EXP.\nDialogue: 0,0:12:56.84,0:12:58.89,EN,,0,0,0,,This might be part of processing a conditional.\nDialogue: 0,0:12:59.26,0:13:01.80,EN,,0,0,0,,And, again, first clause is some selector\nDialogue: 0,0:13:03.07,0:13:04.48,EN,,0,0,0,,whose details we don't care about.\nDialogue: 0,0:13:04.49,0:13:06.46,EN,,0,0,0,,And you can, again, imagine that as a sub-routine\nDialogue: 0,0:13:06.46,0:13:07.90,EN,,0,0,0,,which'll do some list operations,\nDialogue: 0,0:13:08.22,0:13:09.18,EN,,0,0,0,,or you can imagine that as\nDialogue: 0,0:13:09.18,0:13:10.73,EN,,0,0,0,,something that's built directly into hardware.\nDialogue: 0,0:13:12.17,0:13:13.71,EN,,0,0,0,,The reason I keep saying you can imagine it\nDialogue: 0,0:13:14.03,0:13:15.22,EN,,0,0,0,,built directly into hardware\nDialogue: 0,0:13:15.22,0:13:17.80,EN,,0,0,0,,is even though there are a lot of operations,\nDialogue: 0,0:13:18.36,0:13:19.74,EN,,0,0,0,,there are still a fixed number of them.\nDialogue: 0,0:13:20.12,0:13:21.80,EN,,0,0,0,,I forget how many, maybe 150.\nDialogue: 0,0:13:22.37,0:13:25.39,EN,,0,0,0,,So, it's plausible to think of building these directly into hardware.\nDialogue: 0,0:13:26.41,0:13:27.68,EN,,0,0,0,,Here's a more complicated one.\nDialogue: 0,0:13:28.27,0:13:29.47,EN,,0,0,0,,You can see this has to do with\nDialogue: 0,0:13:29.47,0:13:31.10,EN,,0,0,0,,looking up the values of variables.\nDialogue: 0,0:13:31.50,0:13:33.28,EN,,0,0,0,,It says assign to the VAL register\nDialogue: 0,0:13:33.45,0:13:36.91,EN,,0,0,0,,the result of looking up the variable value\nDialogue: 0,0:13:36.99,0:13:38.52,EN,,0,0,0,,of some particular expression,\nDialogue: 0,0:13:39.18,0:13:40.30,EN,,0,0,0,,which, in this case, is supposed to be\nDialogue: 0,0:13:40.33,0:13:42.00,EN,,0,0,0,,a variable in some environment.\nDialogue: 0,0:13:42.80,0:13:44.68,EN,,0,0,0,,And this'll be some operation\nDialogue: 0,0:13:45.21,0:13:47.50,EN,,0,0,0,,that search through the environment structure,\nDialogue: 0,0:13:47.52,0:13:48.97,EN,,0,0,0,,however it is represented,\nDialogue: 0,0:13:49.37,0:13:50.91,EN,,0,0,0,,and goes and looks up that variable.\nDialogue: 0,0:13:52.17,0:13:53.95,EN,,0,0,0,,And, again, that's below the level of detail\nDialogue: 0,0:13:53.96,0:13:54.86,EN,,0,0,0,,that we're thinking about.\nDialogue: 0,0:13:54.89,0:13:57.30,EN,,0,0,0,,This is... this has to do with the details of\nDialogue: 0,0:13:57.55,0:13:59.44,EN,,0,0,0,,the data structures for representing environments.\nDialogue: 0,0:14:00.07,0:14:01.21,EN,,0,0,0,,But, anyway, there is this\nDialogue: 0,0:14:01.31,0:14:03.47,EN,,0,0,0,,there is this fixed and finite number\nDialogue: 0,0:14:04.11,0:14:06.08,EN,,0,0,0,,of operations in the register machine.\nDialogue: 0,0:14:08.50,0:14:11.60,EN,,0,0,0,,Well, what's its overall structure?\nDialogue: 0,0:14:11.72,0:14:13.23,EN,,0,0,0,,Those are some typical operations.\nDialogue: 0,0:14:14.76,0:14:16.33,EN,,0,0,0,,Remember what we have to do,\nDialogue: 0,0:14:16.44,0:14:18.40,EN,,0,0,0,,we have to take the meta-circular evaluator--\nDialogue: 0,0:14:20.43,0:14:22.76,EN,,0,0,0,,and here's a piece of the meta-circular evaluator.\nDialogue: 0,0:14:22.76,0:14:26.89,EN,,0,0,0,,This is the one using abstract syntax that's in the book.\nDialogue: 0,0:14:28.22,0:14:31.53,EN,,0,0,0,,It's a little bit different from the one that Gerry shows you.\nDialogue: 0,0:14:33.50,0:14:35.10,EN,,0,0,0,,And the main thing\nDialogue: 0,0:14:35.13,0:14:37.87,EN,,0,0,0,,to remember about the evaluator is that\nDialogue: 0,0:14:37.87,0:14:40.96,EN,,0,0,0,,it's doing some sort of case analysis on the kinds of expressions:\nDialogue: 0,0:14:43.76,0:14:45.90,EN,,0,0,0,,so if it's either self-evaluated, or quoted,\nDialogue: 0,0:14:45.92,0:14:46.86,EN,,0,0,0,,or whatever else.\nDialogue: 0,0:14:48.56,0:14:50.57,EN,,0,0,0,,And then, in the general case where\nDialogue: 0,0:14:50.86,0:14:52.96,EN,,0,0,0,,the expression it's looking at is an application,\nDialogue: 0,0:14:53.55,0:14:55.36,EN,,0,0,0,,there's some tricky recursions going on.\nDialogue: 0,0:14:55.75,0:14:59.36,EN,,0,0,0,,First of all, eval has to call itself\nDialogue: 0,0:14:59.79,0:15:01.45,EN,,0,0,0,,both to evaluate the operator\nDialogue: 0,0:15:02.14,0:15:04.04,EN,,0,0,0,,and to evaluate all the operands.\nDialogue: 0,0:15:05.88,0:15:07.40,EN,,0,0,0,,So there's this sort of red recursion\nDialogue: 0,0:15:07.63,0:15:09.28,EN,,0,0,0,,of values walking down the tree\nDialogue: 0,0:15:10.94,0:15:12.27,EN,,0,0,0,,that's sort of the easy recursion.\nDialogue: 0,0:15:12.27,0:15:14.44,EN,,0,0,0,,That's just eval walking down this tree of expressions.\nDialogue: 0,0:15:14.75,0:15:15.53,EN,,0,0,0,,Then, in the evaluator,\nDialogue: 0,0:15:15.53,0:15:16.46,EN,,0,0,0,,there's a hard recursion.\nDialogue: 0,0:15:16.49,0:15:17.92,EN,,0,0,0,,There's the red to green.\nDialogue: 0,0:15:18.00,0:15:19.66,EN,,0,0,0,,Eval calls apply.\nDialogue: 0,0:15:22.47,0:15:26.45,EN,,0,0,0,,That's the case where evaluating a procedure argument\nDialogue: 0,0:15:26.45,0:15:28.72,EN,,0,0,0,,reduces to applying the procedure\nDialogue: 0,0:15:28.94,0:15:29.93,EN,,0,0,0,,to the list of arguments.\nDialogue: 0,0:15:30.37,0:15:31.76,EN,,0,0,0,,And then, apply comes over here.\nDialogue: 0,0:15:34.77,0:15:36.67,EN,,0,0,0,,Apply takes a procedure and arguments\nDialogue: 0,0:15:37.65,0:15:39.45,EN,,0,0,0,,and, in the general case\nDialogue: 0,0:15:39.48,0:15:40.81,EN,,0,0,0,,where there's a compound procedure,\nDialogue: 0,0:15:41.05,0:15:42.19,EN,,0,0,0,,apply goes around and\nDialogue: 0,0:15:42.25,0:15:43.15,EN,,0,0,0,,green calls red.\nDialogue: 0,0:15:43.34,0:15:46.44,EN,,0,0,0,,Eval-- Apply comes around and calls eval again.\nDialogue: 0,0:15:48.17,0:15:49.79,EN,,0,0,0,,Eval's the body of the procedure\nDialogue: 0,0:15:50.24,0:15:52.59,EN,,0,0,0,,in the result of extending the environment\nDialogue: 0,0:15:53.69,0:15:55.28,EN,,0,0,0,,with the parameters of the procedure\nDialogue: 0,0:15:55.48,0:15:56.92,EN,,0,0,0,,by binding the arguments.\nDialogue: 0,0:15:59.62,0:16:00.62,EN,,0,0,0,,Except in the primitive case,\nDialogue: 0,0:16:00.64,0:16:02.52,EN,,0,0,0,,where it just calls something else primitive-apply\nDialogue: 0,0:16:02.73,0:16:04.70,EN,,0,0,0,,which is not really the business of the evaluator.\nDialogue: 0,0:16:05.98,0:16:07.47,EN,,0,0,0,,So this sort of red to green,\nDialogue: 0,0:16:07.47,0:16:08.40,EN,,0,0,0,,to red to green,\nDialogue: 0,0:16:09.79,0:16:12.72,EN,,0,0,0,,Right? That's the that's the eval/apply loop,\nDialogue: 0,0:16:14.06,0:16:15.74,EN,,0,0,0,,and that's the thing that we're going to want to see\nDialogue: 0,0:16:16.19,0:16:17.72,EN,,0,0,0,,in the evaluator.\nDialogue: 0,0:16:19.69,0:16:21.07,EN,,0,0,0,,Well, it won't surprise you at all that\nDialogue: 0,0:16:21.07,0:16:23.52,EN,,0,0,0,,the two big pieces of this evaluator\nDialogue: 0,0:16:25.34,0:16:27.04,EN,,0,0,0,,are correspond to eval and apply.\nDialogue: 0,0:16:27.47,0:16:29.44,EN,,0,0,0,,There's a piece called eval-dispatch,\nDialogue: 0,0:16:29.60,0:16:31.20,EN,,0,0,0,,and a piece called apply-dispatch.\nDialogue: 0,0:16:32.00,0:16:34.09,EN,,0,0,0,,And, before we get into the details of the code,\nDialogue: 0,0:16:34.20,0:16:35.76,EN,,0,0,0,,the way to understand this is to think,\nDialogue: 0,0:16:36.09,0:16:39.02,EN,,0,0,0,,again, in terms of these pieces of evaluator\nDialogue: 0,0:16:39.02,0:16:40.97,EN,,0,0,0,,having contracts with the rest of the world.\nDialogue: 0,0:16:41.87,0:16:43.18,EN,,0,0,0,,What do they do from the outside\nDialogue: 0,0:16:43.20,0:16:45.50,EN,,0,0,0,,before getting into the grungy details?\nDialogue: 0,0:16:45.78,0:16:49.32,EN,,0,0,0,,Well, the contract for eval-dispatch--\nDialogue: 0,0:16:50.01,0:16:51.40,EN,,0,0,0,,remember, it corresponds to eval.\nDialogue: 0,0:16:51.55,0:16:54.10,EN,,0,0,0,,It's got to evaluate an expression in an environment.\nDialogue: 0,0:16:54.10,0:16:55.88,EN,,0,0,0,,So, in particular, what this one is going to do,\nDialogue: 0,0:16:56.52,0:16:58.68,EN,,0,0,0,,eval-dispatch will assume that, when you call it,\nDialogue: 0,0:16:59.68,0:17:01.48,EN,,0,0,0,,that the expression you want to evaluate\nDialogue: 0,0:17:01.48,0:17:02.52,EN,,0,0,0,,is in the EXP register.\nDialogue: 0,0:17:03.64,0:17:07.39,EN,,0,0,0,,The environment in which you want the evaluation\nDialogue: 0,0:17:07.45,0:17:09.05,EN,,0,0,0,,to take place is in the ENV register.\nDialogue: 0,0:17:09.56,0:17:10.67,EN,,0,0,0,,And continue tells you\nDialogue: 0,0:17:10.84,0:17:12.46,EN,,0,0,0,,the place where the machine should go next\nDialogue: 0,0:17:12.52,0:17:13.92,EN,,0,0,0,,when the evaluation is done.\nDialogue: 0,0:17:17.28,0:17:19.18,EN,,0,0,0,,Eval-dispatch's contract is that\nDialogue: 0,0:17:19.28,0:17:21.26,EN,,0,0,0,,it'll actually perform that evaluation,\nDialogue: 0,0:17:21.40,0:17:22.46,EN,,0,0,0,,and, at the end of which,\nDialogue: 0,0:17:23.28,0:17:25.63,EN,,0,0,0,,it'll end up at the place specified by continue.\nDialogue: 0,0:17:26.61,0:17:29.16,EN,,0,0,0,,The result of the evaluation will be in the VAL register.\nDialogue: 0,0:17:29.82,0:17:30.96,EN,,0,0,0,,And it just warns you,\nDialogue: 0,0:17:30.99,0:17:32.91,EN,,0,0,0,,it makes no promises about\nDialogue: 0,0:17:32.96,0:17:34.60,EN,,0,0,0,,what happens to rest the registers.\nDialogue: 0,0:17:35.23,0:17:36.81,EN,,0,0,0,,All other registers might be destroyed.\nDialogue: 0,0:17:37.49,0:17:40.14,EN,,0,0,0,,So, there's one piece, OK?\nDialogue: 0,0:17:41.55,0:17:43.48,EN,,0,0,0,,Together, the pieces, apply-dispatch\nDialogue: 0,0:17:43.52,0:17:44.92,EN,,0,0,0,,that corresponds to apply,\nDialogue: 0,0:17:46.09,0:17:48.43,EN,,0,0,0,,it's got to apply a procedure to some arguments,\nDialogue: 0,0:17:48.73,0:17:51.43,EN,,0,0,0,,so it assumes that this register, ARGL,\nDialogue: 0,0:17:51.68,0:17:53.77,EN,,0,0,0,,contains a list of the evaluated arguments.\nDialogue: 0,0:17:54.54,0:17:55.96,EN,,0,0,0,,FUN contains the procedure.\nDialogue: 0,0:17:57.22,0:17:58.83,EN,,0,0,0,,Those correspond to the arguments to\nDialogue: 0,0:17:58.94,0:18:01.36,EN,,0,0,0,,the apply procedure in the meta-circular evaluator.\nDialogue: 0,0:18:03.97,0:18:06.04,EN,,0,0,0,,And apply, in this particular evaluator,\nDialogue: 0,0:18:06.06,0:18:07.58,EN,,0,0,0,,we're going to use a discipline which says\nDialogue: 0,0:18:07.72,0:18:08.97,EN,,0,0,0,,the place that apply\nDialogue: 0,0:18:09.47,0:18:11.20,EN,,0,0,0,,the place the machine should go to next\nDialogue: 0,0:18:11.79,0:18:13.45,EN,,0,0,0,,when apply is done, is at the moment\nDialogue: 0,0:18:13.55,0:18:15.92,EN,,0,0,0,,apply-dispatch is called at the top of the stack\nDialogue: 0,0:18:17.07,0:18:21.24,EN,,0,0,0,,that's just discipline for the way this particular machine's organized.\nDialogue: 0,0:18:21.84,0:18:23.70,EN,,0,0,0,,And now apply's contract is given all that.\nDialogue: 0,0:18:23.93,0:18:25.37,EN,,0,0,0,,It'll perform the application.\nDialogue: 0,0:18:25.54,0:18:27.85,EN,,0,0,0,,The result of that application will end up in VAL.\nDialogue: 0,0:18:28.89,0:18:29.95,EN,,0,0,0,,The stack will be popped.\nDialogue: 0,0:18:31.12,0:18:31.66,EN,,0,0,0,,And, again,\nDialogue: 0,0:18:31.71,0:18:34.03,EN,,0,0,0,,the contents of all the other registers may be destroyed.\nDialogue: 0,0:18:34.84,0:18:37.82,EN,,0,0,0,,All right? So that's the basic organization of this machine.\nDialogue: 0,0:18:38.99,0:18:41.50,EN,,0,0,0,,Let's break for a little bit and see if there are any questions\nDialogue: 0,0:18:41.52,0:18:42.70,EN,,0,0,0,,and then we'll do a real example.\nDialogue: 0,0:18:43.53,0:19:08.11,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:19:08.14,0:19:13.47,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:19:33.10,0:19:35.87,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:19:35.87,0:19:40.38,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:19:47.85,0:19:49.95,EN,,0,0,0,,Well, let's take the register machine now,\nDialogue: 0,0:19:50.41,0:19:51.77,EN,,0,0,0,,and actually step through,\nDialogue: 0,0:19:52.27,0:19:56.94,EN,,0,0,0,,and really, in real detail,\nDialogue: 0,0:19:57.07,0:19:58.52,EN,,0,0,0,,so you see completely concrete\nDialogue: 0,0:19:58.86,0:20:01.24,EN,,0,0,0,,how some expressions are evaluated,\nDialogue: 0,0:20:03.15,0:20:06.86,EN,,0,0,0,,Alright? So, let's start with a very simple expression.\nDialogue: 0,0:20:07.45,0:20:13.52,EN,,0,0,0,,Let's evaluate the expression 1.\nDialogue: 0,0:20:18.77,0:20:20.40,EN,,0,0,0,,And we need an environment,\nDialogue: 0,0:20:20.43,0:20:22.35,EN,,0,0,0,,so let's imagine that somewhere there's an environment\nDialogue: 0,0:20:22.38,0:20:23.39,EN,,0,0,0,,we'll call it E0.\nDialogue: 0,0:20:30.06,0:20:34.56,EN,,0,0,0,,And just, since we'll use these later,\nDialogue: 0,0:20:35.62,0:20:37.04,EN,,0,0,0,,we obviously don't really need anything\nDialogue: 0,0:20:37.07,0:20:37.93,EN,,0,0,0,,to evaluate 1.\nDialogue: 0,0:20:38.36,0:20:39.45,EN,,0,0,0,,But, just for reference later,\nDialogue: 0,0:20:39.45,0:20:40.94,EN,,0,0,0,,let's assume that E0 has in it\nDialogue: 0,0:20:41.44,0:20:43.15,EN,,0,0,0,,an X that's bound to 3\nDialogue: 0,0:20:43.72,0:20:45.37,EN,,0,0,0,,and a Y that's bound to 4,\nDialogue: 0,0:20:48.27,0:20:48.78,EN,,0,0,0,,OK?\nDialogue: 0,0:20:49.14,0:20:50.12,EN,,0,0,0,,And now what we're going to do\nDialogue: 0,0:20:50.51,0:20:54.59,EN,,0,0,0,,is we're going to evaluate 1 in this environment\nDialogue: 0,0:20:55.74,0:20:58.54,EN,,0,0,0,,and so the ENV register has a pointer\nDialogue: 0,0:20:59.65,0:21:01.04,EN,,0,0,0,,to this environment, E0, all right?\nDialogue: 0,0:21:03.31,0:21:05.65,EN,,0,0,0,,Right? So let's watch that thing go.\nDialogue: 0,0:21:05.65,0:21:07.26,EN,,0,0,0,,What I'm going to do is step through the code.\nDialogue: 0,0:21:08.26,0:21:10.00,EN,,0,0,0,,And, let's see, I'll be the controller.\nDialogue: 0,0:21:10.04,0:21:10.80,EN,,0,0,0,,And now what I need,\nDialogue: 0,0:21:11.02,0:21:12.49,EN,,0,0,0,,since this gets rather complicated,\nDialogue: 0,0:21:12.98,0:21:16.83,EN,,0,0,0,,is a very little execution unit.\nDialogue: 0,0:21:16.83,0:21:18.16,EN,,0,0,0,,So here's the execution unit, OK?\nDialogue: 0,0:21:22.62,0:21:23.12,EN,,0,0,0,,OK.\nDialogue: 0,0:21:28.59,0:21:29.96,EN,,0,0,0,,All right, now we're going to start.\nDialogue: 0,0:21:30.53,0:21:32.48,EN,,0,0,0,,We're going to start the machine at eval-dispatch。\nDialogue: 0,0:21:33.26,0:21:34.62,EN,,0,0,0,,Right? That's the beginning of this.\nDialogue: 0,0:21:35.87,0:21:38.75,EN,,0,0,0,,Eval-dispatch is going to look at the expression and dispatch,\nDialogue: 0,0:21:39.32,0:21:40.06,EN,,0,0,0,,just like eval\nDialogue: 0,0:21:40.87,0:21:42.00,EN,,0,0,0,,where we look at the very first thing.\nDialogue: 0,0:21:42.04,0:21:47.95,EN,,0,0,0,,We branch on whether or not this expression is self-evaluating.\nDialogue: 0,0:21:47.95,0:21:49.96,EN,,0,0,0,,Self-evaluating is some abstraction\nDialogue: 0,0:21:49.96,0:21:51.10,EN,,0,0,0,,we put into the machine--\nDialogue: 0,0:21:52.22,0:21:53.51,EN,,0,0,0,,it's going to be true for numbers--\nDialogue: 0,0:21:53.64,0:21:55.52,EN,,0,0,0,,to a place called ev-self-eval,\nDialogue: 0,0:21:56.77,0:21:58.20,EN,,0,0,0,,So me, being the controller,\nDialogue: 0,0:21:58.22,0:21:59.55,EN,,0,0,0,,looks at ev-self-eval,\nDialogue: 0,0:22:00.06,0:22:01.07,EN,,0,0,0,,so we'll go over to there.\nDialogue: 0,0:22:02.60,0:22:04.76,EN,,0,0,0,,Ev-self-eval says fine,\nDialogue: 0,0:22:06.54,0:22:09.90,EN,,0,0,0,,assign to val whatever is in the expression unit.\nDialogue: 0,0:22:15.24,0:22:16.51,EN,,0,0,0,,And I have a bug\nDialogue: 0,0:22:17.93,0:22:20.59,EN,,0,0,0,,because what I didn't do when I initialized this machine\nDialogue: 0,0:22:21.62,0:22:22.89,EN,,0,0,0,,is also say what's supposed\nDialogue: 0,0:22:22.91,0:22:24.19,EN,,0,0,0,,to happen when it's done,\nDialogue: 0,0:22:24.65,0:22:26.83,EN,,0,0,0,,so I should have started out the machine\nDialogue: 0,0:22:27.37,0:22:29.85,EN,,0,0,0,,with done being in the continue register,\nDialogue: 0,0:22:31.18,0:22:33.26,EN,,0,0,0,,OK? So we assign to VAL.\nDialogue: 0,0:22:33.37,0:22:35.56,EN,,0,0,0,,And now go to fetch of continue,\nDialogue: 0,0:22:35.63,0:22:36.56,EN,,0,0,0,,and now change--\nDialogue: 0,0:22:38.09,0:22:38.60,EN,,0,0,0,,OK.\nDialogue: 0,0:22:40.00,0:22:41.16,EN,,0,0,0,,OK, let's try something harder.\nDialogue: 0,0:22:42.16,0:22:43.45,EN,,0,0,0,,Let's reset the machine here,\nDialogue: 0,0:22:44.86,0:22:50.88,EN,,0,0,0,,and we'll put in the expression register, X, OK?\nDialogue: 0,0:22:56.71,0:22:58.20,EN,,0,0,0,,Start again at eval-dispatch.\nDialogue: 0,0:22:59.61,0:23:01.69,EN,,0,0,0,,Check, is it self-evaluating?\nDialogue: 0,0:23:01.69,0:23:02.03,EN,,0,0,0,,No.\nDialogue: 0,0:23:02.65,0:23:03.61,EN,,0,0,0,,Is it a variable?\nDialogue: 0,0:23:04.63,0:23:05.02,EN,,0,0,0,,Yes.\nDialogue: 0,0:23:05.56,0:23:07.07,EN,,0,0,0,,We go off to ev-variable.\nDialogue: 0,0:23:08.38,0:23:10.97,EN,,0,0,0,,It says assign to VAL,\nDialogue: 0,0:23:12.13,0:23:15.69,EN,,0,0,0,,look up the variable value in the expression register\nDialogue: 0,0:23:21.23,0:23:22.91,EN,,0,0,0,,Go to fetch of continue.\nDialogue: 0,0:23:23.96,0:23:24.48,EN,,0,0,0,,PROFESSOR: Done.\nDialogue: 0,0:23:27.61,0:23:28.09,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:23:29.31,0:23:30.76,EN,,0,0,0,,Alright, Well, that's the basic idea. Those're\nDialogue: 0,0:23:31.33,0:23:32.65,EN,,0,0,0,,That's a simple operation of the machine.\nDialogue: 0,0:23:32.68,0:23:35.07,EN,,0,0,0,,Now, let's actually do something a little bit more interesting.\nDialogue: 0,0:23:36.07,0:23:38.64,EN,,0,0,0,,Let's look at the expression\nDialogue: 0,0:23:43.58,0:23:47.93,EN,,0,0,0,,the sum of x and y.\nDialogue: 0,0:23:49.69,0:23:51.28,EN,,0,0,0,,OK. And now we'll see how you start\nDialogue: 0,0:23:52.41,0:23:54.01,EN,,0,0,0,,unrolling these expression trees.\nDialogue: 0,0:23:57.13,0:23:58.68,EN,,0,0,0,,Well, start again at eval-dispatch.\nDialogue: 0,0:24:04.61,0:24:05.80,EN,,0,0,0,,Self-evaluating?\nDialogue: 0,0:24:05.95,0:24:06.52,EN,,0,0,0,,No.\nDialogue: 0,0:24:06.70,0:24:07.71,EN,,0,0,0,,Variable? No.\nDialogue: 0,0:24:07.82,0:24:08.99,EN,,0,0,0,,All the other special forms\nDialogue: 0,0:24:08.99,0:24:10.12,EN,,0,0,0,,which I didn't write down,\nDialogue: 0,0:24:10.27,0:24:12.48,EN,,0,0,0,,like quote, and lambda, and set, and whatever,\nDialogue: 0,0:24:12.48,0:24:13.08,EN,,0,0,0,,it's none of those.\nDialogue: 0,0:24:13.26,0:24:14.73,EN,,0,0,0,,It turns out to be an application,\nDialogue: 0,0:24:15.88,0:24:17.42,EN,,0,0,0,,so we go off to ev-application.\nDialogue: 0,0:24:19.97,0:24:24.94,EN,,0,0,0,,Ev-application, remember what it's going to do overall.\nDialogue: 0,0:24:25.58,0:24:28.19,EN,,0,0,0,,It is going to evaluate the operator.\nDialogue: 0,0:24:28.27,0:24:31.40,EN,,0,0,0,,It's going to evaluate the arguments,\nDialogue: 0,0:24:32.36,0:24:34.30,EN,,0,0,0,,and then it's going to go apply them.\nDialogue: 0,0:24:35.06,0:24:36.09,EN,,0,0,0,,So, before we start,\nDialogue: 0,0:24:36.94,0:24:37.88,EN,,0,0,0,,since we're being very literal,\nDialogue: 0,0:24:37.88,0:24:38.88,EN,,0,0,0,,we'd better remember that,\nDialogue: 0,0:24:39.07,0:24:40.54,EN,,0,0,0,,somewhere in this environment,\nDialogue: 0,0:24:40.57,0:24:42.36,EN,,0,0,0,,it's linked to another environment\nDialogue: 0,0:24:43.98,0:24:44.94,EN,,0,0,0,,in which plus\nDialogue: 0,0:24:45.72,0:24:49.16,EN,,0,0,0,,is bound to the primitive procedure plus\nDialogue: 0,0:24:51.63,0:24:54.03,EN,,0,0,0,,before we get an unknown variable in our machine.\nDialogue: 0,0:24:55.34,0:24:56.84,EN,,0,0,0,,OK, so we're at ev-application.\nDialogue: 0,0:24:59.85,0:25:04.32,EN,,0,0,0,,OK, assign to UNEV the operands\nDialogue: 0,0:25:04.92,0:25:06.89,EN,,0,0,0,,of what's in the expression register.\nDialogue: 0,0:25:07.61,0:25:08.83,EN,,0,0,0,,OK. Those are the operands.\nDialogue: 0,0:25:09.23,0:25:11.66,EN,,0,0,0,,UNEV's a temporary register\nDialogue: 0,0:25:11.68,0:25:12.59,EN,,0,0,0,,where we're going to save them.\nDialogue: 0,0:25:13.22,0:25:13.86,EN,,0,0,0,,PROFESSOR: I'm assigning.\nDialogue: 0,0:25:14.28,0:25:16.62,EN,,0,0,0,,PROFESSOR: Assign to EXP the operator.\nDialogue: 0,0:25:18.07,0:25:20.09,EN,,0,0,0,,Now, notice we've destroyed that expression in EXP,\nDialogue: 0,0:25:21.84,0:25:23.61,EN,,0,0,0,,but the piece that we need is now in UNEV.\nDialogue: 0,0:25:25.82,0:25:26.81,EN,,0,0,0,,Now, we're going to get set up to\nDialogue: 0,0:25:26.81,0:25:28.59,EN,,0,0,0,,to recursively evaluate the operator.\nDialogue: 0,0:25:28.75,0:25:31.69,EN,,0,0,0,,Save the continue register on the stack.\nDialogue: 0,0:25:34.86,0:25:36.09,EN,,0,0,0,,Save the environment.\nDialogue: 0,0:25:40.48,0:25:41.69,EN,,0,0,0,,Save UNEV.\nDialogue: 0,0:25:49.53,0:25:54.64,EN,,0,0,0,,OK, assign to continue a label called eval-args.\nDialogue: 0,0:26:01.40,0:26:01.95,EN,,0,0,0,,Now, what have we done?\nDialogue: 0,0:26:01.95,0:26:04.38,EN,,0,0,0,,We've set up for a recursive call.\nDialogue: 0,0:26:04.38,0:26:05.88,EN,,0,0,0,,We're about to go to eval-dispatch.\nDialogue: 0,0:26:06.28,0:26:08.83,EN,,0,0,0,,We've set up for a recursive call to eval-dispatch.\nDialogue: 0,0:26:10.23,0:26:10.86,EN,,0,0,0,,What did we do?\nDialogue: 0,0:26:11.02,0:26:13.64,EN,,0,0,0,,We took the things we're going to need later,\nDialogue: 0,0:26:14.48,0:26:15.98,EN,,0,0,0,,those operands that were in UNEV;\nDialogue: 0,0:26:16.36,0:26:18.99,EN,,0,0,0,,the environment in which we're going to eventually have to,\nDialogue: 0,0:26:19.16,0:26:20.72,EN,,0,0,0,,maybe, evaluate those operands;\nDialogue: 0,0:26:22.28,0:26:23.93,EN,,0,0,0,,the place we eventually want to go to,\nDialogue: 0,0:26:23.95,0:26:25.07,EN,,0,0,0,,which, in this case, was done;\nDialogue: 0,0:26:25.34,0:26:26.70,EN,,0,0,0,,we've saved them on the stack.\nDialogue: 0,0:26:27.10,0:26:28.41,EN,,0,0,0,,The reason we saved them on the stack\nDialogue: 0,0:26:28.43,0:26:30.67,EN,,0,0,0,,is because eval-dispatch makes no promises\nDialogue: 0,0:26:30.94,0:26:32.54,EN,,0,0,0,,about what registers it may destroy.\nDialogue: 0,0:26:33.55,0:26:35.02,EN,,0,0,0,,So all that stuff is saved on the stack.\nDialogue: 0,0:26:35.02,0:26:36.91,EN,,0,0,0,,Now, we've set up eval-dispatch's contract.\nDialogue: 0,0:26:37.38,0:26:38.75,EN,,0,0,0,,There's a new expression,\nDialogue: 0,0:26:38.78,0:26:40.04,EN,,0,0,0,,which is the operator plus;\nDialogue: 0,0:26:41.07,0:26:41.95,EN,,0,0,0,,a new environment,\nDialogue: 0,0:26:41.98,0:26:43.60,EN,,0,0,0,,although, in this case, it's the same one;\nDialogue: 0,0:26:44.25,0:26:45.87,EN,,0,0,0,,and a new place to go to when you're done,\nDialogue: 0,0:26:45.87,0:26:46.91,EN,,0,0,0,,which is eval-args.\nDialogue: 0,0:26:47.60,0:26:48.13,EN,,0,0,0,,So that's set up.\nDialogue: 0,0:26:48.13,0:26:49.68,EN,,0,0,0,,Now, we're going to go off to eval-dispatch.\nDialogue: 0,0:26:50.89,0:26:52.36,EN,,0,0,0,,Here we are back at eval-dispatch.\nDialogue: 0,0:26:53.05,0:26:54.40,EN,,0,0,0,,It's not self-evaluating.\nDialogue: 0,0:26:54.44,0:26:55.47,EN,,0,0,0,,Oh, it's a variable,\nDialogue: 0,0:26:56.32,0:26:58.06,EN,,0,0,0,,so we'd better go off to ev-variable,\nDialogue: 0,0:26:59.79,0:27:02.65,EN,,0,0,0,,Right? Ev-variable is assigned to VAL.\nDialogue: 0,0:27:02.70,0:27:06.33,EN,,0,0,0,,Look up the variable value of the expression,\nDialogue: 0,0:27:08.49,0:27:10.75,EN,,0,0,0,,OK? So VAL is the primitive procedure plus.\nDialogue: 0,0:27:13.37,0:27:15.16,EN,,0,0,0,,And go to fetch of continue.\nDialogue: 0,0:27:15.23,0:27:16.11,EN,,0,0,0,,PROFESSOR: Eval-args.\nDialogue: 0,0:27:16.20,0:27:18.73,EN,,0,0,0,,PROFESSOR: Right, which is now eval-args not done.\nDialogue: 0,0:27:19.42,0:27:21.26,EN,,0,0,0,,So we come back here at eval-args,\nDialogue: 0,0:27:22.16,0:27:23.02,EN,,0,0,0,,and what do we do?\nDialogue: 0,0:27:23.07,0:27:24.84,EN,,0,0,0,,We're going to restore the stuff that we saved,\nDialogue: 0,0:27:25.20,0:27:26.57,EN,,0,0,0,,so we restore UNEV.\nDialogue: 0,0:27:29.21,0:27:31.69,EN,,0,0,0,,And notice, there, it wasn't necessary,\nDialogue: 0,0:27:31.74,0:27:32.90,EN,,0,0,0,,although, in general, it would be.\nDialogue: 0,0:27:32.90,0:27:35.16,EN,,0,0,0,,It might be some arbitrary evaluation that happened.\nDialogue: 0,0:27:35.43,0:27:36.70,EN,,0,0,0,,We restore ENV.\nDialogue: 0,0:27:47.87,0:27:52.04,EN,,0,0,0,,OK, we assign to FUN fetch of VAL.\nDialogue: 0,0:27:59.95,0:28:02.81,EN,,0,0,0,,OK, now, we're going to go off and start evaluating some arguments.\nDialogue: 0,0:28:04.34,0:28:06.48,EN,,0,0,0,,Well, first thing we'd better do is save FUN\nDialogue: 0,0:28:07.42,0:28:10.62,EN,,0,0,0,,because some arbitrary stuff might happen in that evaluation.\nDialogue: 0,0:28:15.33,0:28:16.88,EN,,0,0,0,,We initialize the argument list.\nDialogue: 0,0:28:16.91,0:28:19.29,EN,,0,0,0,,Assign to argl an empty argument list,\nDialogue: 0,0:28:20.88,0:28:22.17,EN,,0,0,0,,and go to eval-arg-loop,\nDialogue: 0,0:28:24.86,0:28:26.27,EN,,0,0,0,,At eval-arg-loop,\nDialogue: 0,0:28:27.77,0:28:31.53,EN,,0,0,0,,the idea of this is we're going to evaluate the pieces of the\nDialogue: 0,0:28:31.61,0:28:33.37,EN,,0,0,0,,expressions that are in UNEV, one by one,\nDialogue: 0,0:28:33.54,0:28:35.68,EN,,0,0,0,,and move them from unevaluated in UNEV\nDialogue: 0,0:28:35.90,0:28:37.26,EN,,0,0,0,,to evaluated in the arg list.\nDialogue: 0,0:28:37.84,0:28:39.18,EN,,0,0,0,,OK. So we save argl.\nDialogue: 0,0:28:43.95,0:28:47.26,EN,,0,0,0,,We assign to EXP the first operand\nDialogue: 0,0:28:47.37,0:28:48.38,EN,,0,0,0,,of the stuff in UNEV.\nDialogue: 0,0:28:53.77,0:28:55.89,EN,,0,0,0,,Now, we check and see if that was the last operand.\nDialogue: 0,0:28:55.89,0:28:56.91,EN,,0,0,0,,In this case, it is not.\nDialogue: 0,0:28:58.99,0:29:01.55,EN,,0,0,0,,So we save the environment.\nDialogue: 0,0:29:08.00,0:29:10.06,EN,,0,0,0,,We save UNEV\nDialogue: 0,0:29:11.61,0:29:13.50,EN,,0,0,0,,because those are all things we might need later.\nDialogue: 0,0:29:13.50,0:29:14.40,EN,,0,0,0,,We're going to need the environment\nDialogue: 0,0:29:14.44,0:29:15.64,EN,,0,0,0,,to do some more evaluations.\nDialogue: 0,0:29:15.80,0:29:16.60,EN,,0,0,0,,We're going to need UNEV\nDialogue: 0,0:29:16.62,0:29:19.20,EN,,0,0,0,,to look at what the rest of those arguments were.\nDialogue: 0,0:29:20.34,0:29:21.55,EN,,0,0,0,,We're going to assign continue\nDialogue: 0,0:29:21.56,0:29:24.44,EN,,0,0,0,,a place called accumulate-args, or accumulate-arg.\nDialogue: 0,0:29:31.13,0:29:34.01,EN,,0,0,0,,OK, now, we've set up for another call to eval-dispatch,\nDialogue: 0,0:29:37.07,0:29:38.54,EN,,0,0,0,,All right, now, let me short-circuit this\nDialogue: 0,0:29:39.12,0:29:41.09,EN,,0,0,0,,so we don't go through the details of eval-dispatch.\nDialogue: 0,0:29:41.09,0:29:42.64,EN,,0,0,0,,Eval-dispatch's contract says\nDialogue: 0,0:29:42.97,0:29:45.00,EN,,0,0,0,,i'm going to end up,\nDialogue: 0,0:29:45.13,0:29:45.96,EN,,0,0,0,,the world will end up,\nDialogue: 0,0:29:46.03,0:29:48.20,EN,,0,0,0,,with the value of evaluating this expression\nDialogue: 0,0:29:48.24,0:29:50.27,EN,,0,0,0,,in this environment in the VAL register,\nDialogue: 0,0:29:50.27,0:29:51.07,EN,,0,0,0,,and I'll end up there.\nDialogue: 0,0:29:51.32,0:29:52.62,EN,,0,0,0,,So we short-circuit all of this,\nDialogue: 0,0:29:54.43,0:29:56.36,EN,,0,0,0,,and a 3 ends up in VAL.\nDialogue: 0,0:29:58.01,0:29:59.76,EN,,0,0,0,,And, when we return from eval-dispatch,\nDialogue: 0,0:29:59.76,0:30:01.76,EN,,0,0,0,,we're going to return to accumulate-arg.\nDialogue: 0,0:30:02.30,0:30:03.23,EN,,0,0,0,,PROFESSOR: Accumulate-arg.\nDialogue: 0,0:30:06.22,0:30:08.20,EN,,0,0,0,,PROFESSOR: With 3 in the VAL register, OK?\nDialogue: 0,0:30:08.72,0:30:10.59,EN,,0,0,0,,So that short-circuited that evaluation.\nDialogue: 0,0:30:10.65,0:30:11.32,EN,,0,0,0,,Now, what do we do?\nDialogue: 0,0:30:11.32,0:30:13.68,EN,,0,0,0,,We're going to go back and look at the rest of the arguments,\nDialogue: 0,0:30:13.68,0:30:14.83,EN,,0,0,0,,so we restore UNEV.\nDialogue: 0,0:30:17.51,0:30:19.00,EN,,0,0,0,,We restore ENV.\nDialogue: 0,0:30:25.79,0:30:27.05,EN,,0,0,0,,We restore argl.\nDialogue: 0,0:30:28.65,0:30:29.17,EN,,0,0,0,,One thing.\nDialogue: 0,0:30:30.06,0:30:31.45,EN,,0,0,0,,PROFESSOR: Oops! Parity error.\nDialogue: 0,0:30:33.76,0:30:34.83,EN,,0,0,0,,PROFESSOR: Restore argl.\nDialogue: 0,0:30:45.57,0:30:49.76,EN,,0,0,0,,OK, we assign to argl consing on\nDialogue: 0,0:30:50.65,0:30:52.64,EN,,0,0,0,,fetch of the value register to what's in argl.\nDialogue: 0,0:30:59.36,0:31:02.96,EN,,0,0,0,,OK, we assign to UNEV the rest of the operands\nDialogue: 0,0:31:03.34,0:31:04.52,EN,,0,0,0,,in fetch of UNEV,\nDialogue: 0,0:31:08.91,0:31:10.76,EN,,0,0,0,,and we go back to eval-arg-loop.\nDialogue: 0,0:31:11.51,0:31:12.28,EN,,0,0,0,,PROFESSOR: Eval-arg-loop.\nDialogue: 0,0:31:12.28,0:31:12.86,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:31:15.88,0:31:17.08,EN,,0,0,0,,Now, we're about to do the next argument,\nDialogue: 0,0:31:17.58,0:31:19.31,EN,,0,0,0,,so the first thing we do is save argl.\nDialogue: 0,0:31:25.40,0:31:28.27,EN,,0,0,0,,OK, we assign to EXP the first operand\nDialogue: 0,0:31:29.15,0:31:30.81,EN,,0,0,0,,of fetch of UNEV.\nDialogue: 0,0:31:34.72,0:31:37.02,EN,,0,0,0,,OK, we test and see if that's the last operand.\nDialogue: 0,0:31:37.02,0:31:38.00,EN,,0,0,0,,In this case, it is\nDialogue: 0,0:31:39.08,0:31:40.27,EN,,0,0,0,,so we're going to go to a special place\nDialogue: 0,0:31:40.28,0:31:42.06,EN,,0,0,0,,that says evaluate the last argument\nDialogue: 0,0:31:43.37,0:31:45.07,EN,,0,0,0,,because, notice,after evaluating the argument,\nDialogue: 0,0:31:45.10,0:31:46.62,EN,,0,0,0,,we don't need the environment any more.\nDialogue: 0,0:31:47.64,0:31:48.78,EN,,0,0,0,,That's going to be the difference.\nDialogue: 0,0:31:50.25,0:31:51.85,EN,,0,0,0,,So here, at eval-last-arg,\nDialogue: 0,0:31:52.24,0:31:54.92,EN,,0,0,0,,which is assigned to continue accumulate-last-arg,\nDialogue: 0,0:32:04.27,0:32:06.90,EN,,0,0,0,,now, we're set up again for eval-dispatch.\nDialogue: 0,0:32:06.90,0:32:08.51,EN,,0,0,0,,We've got a place to go to when we're done.\nDialogue: 0,0:32:08.62,0:32:09.84,EN,,0,0,0,,We've got an expression.\nDialogue: 0,0:32:09.84,0:32:10.80,EN,,0,0,0,,We've got an environment.\nDialogue: 0,0:32:11.33,0:32:13.64,EN,,0,0,0,,OK, so we'll short-circuit the call to eval-dispatch.\nDialogue: 0,0:32:14.37,0:32:16.41,EN,,0,0,0,,And what'll happen is there's a y there,\nDialogue: 0,0:32:16.70,0:32:18.56,EN,,0,0,0,,it's 4 in that environment,\nDialogue: 0,0:32:18.60,0:32:20.09,EN,,0,0,0,,so VAL will end up with 4 in it.\nDialogue: 0,0:32:21.06,0:32:22.86,EN,,0,0,0,,And, then, we're going to end up at accumulate-last-arg, OK?\nDialogue: 0,0:32:25.45,0:32:26.91,EN,,0,0,0,,So, at accumulate-last-arg,\nDialogue: 0,0:32:29.28,0:32:30.52,EN,,0,0,0,,we restore argl.\nDialogue: 0,0:32:37.69,0:32:42.76,EN,,0,0,0,,We assign to argl, we assign to argl cons,\nDialogue: 0,0:32:43.60,0:32:45.83,EN,,0,0,0,,of fetch of the new value onto it,\nDialogue: 0,0:32:45.93,0:32:47.39,EN,,0,0,0,,so we cons a 4 onto that.\nDialogue: 0,0:32:49.85,0:32:52.52,EN,,0,0,0,,We restore what was saved in the function register.\nDialogue: 0,0:32:53.77,0:32:54.99,EN,,0,0,0,,And notice, in this case,\nDialogue: 0,0:32:55.00,0:32:56.27,EN,,0,0,0,,it had not been destroyed,\nDialogue: 0,0:32:56.38,0:32:57.72,EN,,0,0,0,,but in general, it will be.\nDialogue: 0,0:32:59.13,0:33:01.50,EN,,0,0,0,,And now, we're ready to go off to apply-dispatch,\nDialogue: 0,0:33:02.65,0:33:04.40,EN,,0,0,0,,Alright? So we've just gone through the eval.\nDialogue: 0,0:33:04.51,0:33:05.85,EN,,0,0,0,,We evaluated the argument,\nDialogue: 0,0:33:06.46,0:33:07.98,EN,,0,0,0,,the operator, and the arguments,\nDialogue: 0,0:33:07.98,0:33:09.24,EN,,0,0,0,,and now, we're about to apply them.\nDialogue: 0,0:33:09.58,0:33:11.37,EN,,0,0,0,,So we come off to apply-dispatch here\nDialogue: 0,0:33:18.03,0:33:19.29,EN,,0,0,0,,We come off to apply-dispatch,\nDialogue: 0,0:33:21.05,0:33:22.41,EN,,0,0,0,,and we're going to check whether it's a primitive\nDialogue: 0,0:33:22.41,0:33:23.45,EN,,0,0,0,,or a compound procedure.\nDialogue: 0,0:33:23.64,0:33:24.20,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,0:33:24.54,0:33:24.83,EN,,0,0,0,,PROFESSOR: All right.\nDialogue: 0,0:33:24.89,0:33:26.52,EN,,0,0,0,,So, in this case, it's a primitive procedure,\nDialogue: 0,0:33:27.45,0:33:28.91,EN,,0,0,0,,and we go off to primitive-apply.\nDialogue: 0,0:33:29.79,0:33:31.36,EN,,0,0,0,,So we go off to primitive-apply,\nDialogue: 0,0:33:33.71,0:33:35.37,EN,,0,0,0,,that says assign to VAL\nDialogue: 0,0:33:35.69,0:33:38.25,EN,,0,0,0,,result of applying primitive procedure\nDialogue: 0,0:33:38.36,0:33:40.30,EN,,0,0,0,,of the function to the argument list.\nDialogue: 0,0:33:41.31,0:33:42.43,EN,,0,0,0,,PROFESSOR: I don't know how to add.\nDialogue: 0,0:33:42.54,0:33:43.80,EN,,0,0,0,,I'm just an execution unit.\nDialogue: 0,0:33:44.14,0:33:45.35,EN,,0,0,0,,PROFESSOR: Well, I don't know how to add either.\nDialogue: 0,0:33:45.35,0:33:46.51,EN,,0,0,0,,I'm just the evaluator,\nDialogue: 0,0:33:47.08,0:33:48.36,EN,,0,0,0,,so we need a primitive operator.\nDialogue: 0,0:33:48.36,0:33:49.72,EN,,0,0,0,,Let's see, so the primitive operator,\nDialogue: 0,0:33:49.76,0:33:52.36,EN,,0,0,0,,What's the... what's the sum of 3 and 4?\nDialogue: 0,0:33:52.86,0:33:53.32,EN,,0,0,0,,AUDIENCE: 7.\nDialogue: 0,0:33:53.71,0:33:54.65,EN,,0,0,0,,PROFESSOR: OK, 7.\nDialogue: 0,0:33:55.32,0:33:55.99,EN,,0,0,0,,PROFESSOR: Thank you.\nDialogue: 0,0:33:59.20,0:34:00.60,EN,,0,0,0,,PROFESSOR: Now, we restore continue,\nDialogue: 0,0:34:11.58,0:34:12.90,EN,,0,0,0,,and we go to fetch of continue.\nDialogue: 0,0:34:13.07,0:34:13.47,EN,,0,0,0,,PROFESSOR: Done.\nDialogue: 0,0:34:14.20,0:34:14.67,EN,,0,0,0,,PROFESSOR: OK.\nDialogue: 0,0:34:14.92,0:34:18.41,EN,,0,0,0,,Well, that was in as much detail as you will ever see.\nDialogue: 0,0:34:18.41,0:34:20.19,EN,,0,0,0,,We'll never do it in as much detail again.\nDialogue: 0,0:34:21.59,0:34:23.92,EN,,0,0,0,,One very important thing to notice\nDialogue: 0,0:34:24.91,0:34:27.55,EN,,0,0,0,,is that we just executed a recursive procedure,\nDialogue: 0,0:34:29.56,0:34:31.17,EN,,0,0,0,,Right? This whole thing, we used a stack\nDialogue: 0,0:34:31.17,0:34:32.75,EN,,0,0,0,,and the evaluator was recursive.\nDialogue: 0,0:34:33.07,0:34:35.88,EN,,0,0,0,,A lot of people think the reason that you need a stack\nDialogue: 0,0:34:36.48,0:34:37.85,EN,,0,0,0,,and recursion in an evaluator\nDialogue: 0,0:34:37.87,0:34:38.97,EN,,0,0,0,,is because you might be\nDialogue: 0,0:34:39.09,0:34:42.15,EN,,0,0,0,,evaluating recursive procedures like factorial or Fibonacci.\nDialogue: 0,0:34:42.15,0:34:42.92,EN,,0,0,0,,It's not true.\nDialogue: 0,0:34:43.67,0:34:44.99,EN,,0,0,0,,So you notice we did recursion here,\nDialogue: 0,0:34:45.00,0:34:46.86,EN,,0,0,0,,and all we evaluated was (+ x y)\nDialogue: 0,0:34:47.77,0:34:50.65,EN,,0,0,0,,Right? The reason that you need recursion in the evaluator\nDialogue: 0,0:34:50.96,0:34:52.97,EN,,0,0,0,,is because the evaluation process,\nDialogue: 0,0:34:52.99,0:34:54.06,EN,,0,0,0,,itself, is recursive.\nDialogue: 0,0:34:54.45,0:34:56.17,EN,,0,0,0,,Right? It's not because the procedure\nDialogue: 0,0:34:56.32,0:34:58.09,EN,,0,0,0,,that you might be evaluating in LISP\nDialogue: 0,0:34:58.12,0:34:59.27,EN,,0,0,0,,is a recursive procedure.\nDialogue: 0,0:34:59.27,0:35:00.52,EN,,0,0,0,,So that's an important thing\nDialogue: 0,0:35:00.52,0:35:02.14,EN,,0,0,0,,that people get confused about a lot.\nDialogue: 0,0:35:03.01,0:35:04.27,EN,,0,0,0,,The other thing to notice is that,\nDialogue: 0,0:35:04.27,0:35:05.64,EN,,0,0,0,,when we're done here,\nDialogue: 0,0:35:06.28,0:35:07.12,EN,,0,0,0,,we're really done.\nDialogue: 0,0:35:07.12,0:35:08.49,EN,,0,0,0,,Not only are we at done,\nDialogue: 0,0:35:09.45,0:35:13.23,EN,,0,0,0,,but there's no accumulated stuff on the stack,\nDialogue: 0,0:35:13.60,0:35:15.71,EN,,0,0,0,,Right? The machine is back to its initial state.\nDialogue: 0,0:35:17.00,0:35:18.75,EN,,0,0,0,,So that's part of what it means to be done.\nDialogue: 0,0:35:19.71,0:35:21.04,EN,,0,0,0,,Another way to say that is\nDialogue: 0,0:35:22.72,0:35:26.04,EN,,0,0,0,,the evaluation process has reduced\nDialogue: 0,0:35:26.41,0:35:28.32,EN,,0,0,0,,the expression, plus X, Y,\nDialogue: 0,0:35:30.54,0:35:32.78,EN,,0,0,0,,to the value here, 7.\nDialogue: 0,0:35:33.24,0:35:35.45,EN,,0,0,0,,And by reduced, I mean a very particular thing.\nDialogue: 0,0:35:36.01,0:35:38.18,EN,,0,0,0,,It means that there's nothing left on the stack.\nDialogue: 0,0:35:38.18,0:35:40.36,EN,,0,0,0,,The machine is now in the same state,\nDialogue: 0,0:35:40.92,0:35:42.65,EN,,0,0,0,,except there's something in the value register.\nDialogue: 0,0:35:42.72,0:35:44.52,EN,,0,0,0,,It's not part of a sub-problem of anything.\nDialogue: 0,0:35:44.52,0:35:45.63,EN,,0,0,0,,There's nothing to go back to.\nDialogue: 0,0:35:46.12,0:35:46.96,EN,,0,0,0,,OK. Let's break.\nDialogue: 0,0:35:50.16,0:35:50.76,EN,,0,0,0,,Question?\nDialogue: 0,0:35:51.08,0:35:54.02,EN,,0,0,0,,AUDIENCE: The question here, in the stack,\nDialogue: 0,0:35:54.02,0:35:55.82,EN,,0,0,0,,is because the data may be recursive.\nDialogue: 0,0:35:56.20,0:35:58.75,EN,,0,0,0,,You may have embedded expressions, for instance.\nDialogue: 0,0:35:59.31,0:36:02.08,EN,,0,0,0,,PROFESSOR: Yes, because you might have embedded expressions.\nDialogue: 0,0:36:02.08,0:36:04.77,EN,,0,0,0,,But, again, don't confuse that\nDialogue: 0,0:36:04.77,0:36:07.98,EN,,0,0,0,,with what people sometimes mean by the data may be recursive,\nDialogue: 0,0:36:08.00,0:36:10.35,EN,,0,0,0,,which is to say you have these list-structured,\nDialogue: 0,0:36:11.04,0:36:12.93,EN,,0,0,0,,recursive data list operations.\nDialogue: 0,0:36:12.93,0:36:13.96,EN,,0,0,0,,That has nothing to do with it.\nDialogue: 0,0:36:13.98,0:36:16.16,EN,,0,0,0,,It's simply that the expressions contain sub-expressions.\nDialogue: 0,0:36:20.04,0:36:23.52,EN,,0,0,0,,AUDIENCE: Why is it that the order of the arguments in the arg list got reversed?\nDialogue: 0,0:36:23.55,0:36:25.29,EN,,0,0,0,,PROFESSOR: Ah! Yes, I should've mentioned that.\nDialogue: 0,0:36:27.26,0:36:29.07,EN,,0,0,0,,Here, the reason the order is reversed--\nDialogue: 0,0:36:32.78,0:36:35.37,EN,,0,0,0,,it's a question of what you mean by reversed.\nDialogue: 0,0:36:36.05,0:36:39.90,EN,,0,0,0,,I believe it was Newton.\nDialogue: 0,0:36:40.91,0:36:42.41,EN,,0,0,0,,In the very early part of optics,\nDialogue: 0,0:36:42.43,0:36:43.26,EN,,0,0,0,,people realized\nDialogue: 0,0:36:43.61,0:36:45.36,EN,,0,0,0,,that when you look through the lens of your eye,\nDialogue: 0,0:36:45.50,0:36:46.73,EN,,0,0,0,,the image was up-side down.\nDialogue: 0,0:36:46.73,0:36:48.04,EN,,0,0,0,,And there was a lot of argument about\nDialogue: 0,0:36:48.04,0:36:50.48,EN,,0,0,0,,why that didn't mean you saw things up-side down.\nDialogue: 0,0:36:51.28,0:36:52.65,EN,,0,0,0,,So it's sort of the same issue.\nDialogue: 0,0:36:52.86,0:36:53.90,EN,,0,0,0,,Reversed from what?\nDialogue: 0,0:36:54.81,0:36:56.24,EN,,0,0,0,,So we just need some convention.\nDialogue: 0,0:36:56.59,0:37:00.35,EN,,0,0,0,,So all we.. The reason that they're coming at 4, 3\nDialogue: 0,0:37:00.80,0:37:02.49,EN,,0,0,0,,is because taking UNEV\nDialogue: 0,0:37:02.52,0:37:04.03,EN,,0,0,0,,and consing the result onto argl.\nDialogue: 0,0:37:04.52,0:37:06.68,EN,,0,0,0,,So you have to realize you've made that convention.\nDialogue: 0,0:37:06.86,0:37:09.37,EN,,0,0,0,,The place that you have to realize that--\nDialogue: 0,0:37:09.98,0:37:11.23,EN,,0,0,0,,well, there's actually two places.\nDialogue: 0,0:37:11.23,0:37:12.91,EN,,0,0,0,,One is in apply-primitive-operator,\nDialogue: 0,0:37:12.91,0:37:14.06,EN,,0,0,0,,which has to realize that\nDialogue: 0,0:37:15.12,0:37:16.75,EN,,0,0,0,,the arguments to primitives go in,\nDialogue: 0,0:37:16.78,0:37:18.72,EN,,0,0,0,,the opposite order from the way you're writing them down.\nDialogue: 0,0:37:19.49,0:37:21.00,EN,,0,0,0,,And the other one is, we'll see later\nDialogue: 0,0:37:21.07,0:37:23.80,EN,,0,0,0,,when you actually go to bind a function's parameters,\nDialogue: 0,0:37:24.01,0:37:25.74,EN,,0,0,0,,you should realize the arguments are going to come in\nDialogue: 0,0:37:25.74,0:37:28.54,EN,,0,0,0,,from the opposite order of the variables to which you're binding them.\nDialogue: 0,0:37:28.87,0:37:30.17,EN,,0,0,0,,So, if you just keep track of that,\nDialogue: 0,0:37:31.08,0:37:31.83,EN,,0,0,0,,there's no problem.\nDialogue: 0,0:37:31.83,0:37:33.69,EN,,0,0,0,,Also, this is completely arbitrary\nDialogue: 0,0:37:33.90,0:37:34.96,EN,,0,0,0,,because, if we'd done,\nDialogue: 0,0:37:35.10,0:37:37.15,EN,,0,0,0,,say, an iteration through a vector assigning them,\nDialogue: 0,0:37:37.42,0:37:38.73,EN,,0,0,0,,they might come out in the other order.\nDialogue: 0,0:37:40.41,0:37:42.04,EN,,0,0,0,,OK. So it's just a convention of the way\nDialogue: 0,0:37:42.06,0:37:43.53,EN,,0,0,0,,this particular evaluator works.\nDialogue: 0,0:37:45.39,0:37:46.24,EN,,0,0,0,,All right, let's take a break.\nDialogue: 0,0:37:46.33,0:38:02.44,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:38:02.44,0:38:07.64,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:38:28.62,0:38:32.51,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:38:32.51,0:38:35.68,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:38:41.84,0:38:45.31,EN,,0,0,0,,Professor: We just saw evaluating an expression\nDialogue: 0,0:38:45.60,0:38:47.08,EN,,0,0,0,,and, of course, that was very simple one. But\nDialogue: 0,0:38:48.81,0:38:50.24,EN,,0,0,0,,in essence, it would be no different\nDialogue: 0,0:38:50.24,0:38:52.03,EN,,0,0,0,,if it was some big nested expression,\nDialogue: 0,0:38:52.03,0:38:54.57,EN,,0,0,0,,so there would just be deeper recursion on the stack.\nDialogue: 0,0:38:55.13,0:38:56.03,EN,,0,0,0,,But what I want to do now\nDialogue: 0,0:38:56.04,0:38:56.91,EN,,0,0,0,,is show you the last piece.\nDialogue: 0,0:38:56.92,0:38:59.82,EN,,0,0,0,,I want to walk you around this eval and apply loop,\nDialogue: 0,0:39:01.01,0:39:02.81,EN,,0,0,0,,That's the thing we haven't seen, really.\nDialogue: 0,0:39:03.00,0:39:04.75,EN,,0,0,0,,We haven't seen any compound procedures\nDialogue: 0,0:39:05.20,0:39:07.79,EN,,0,0,0,,where evalutation of procedure reduces to\nDialogue: 0,0:39:07.92,0:39:10.11,EN,,0,0,0,,where applying of procedure reduces to\nDialogue: 0,0:39:10.12,0:39:11.64,EN,,0,0,0,,evaluating the body of the procedure,\nDialogue: 0,0:39:12.44,0:39:15.88,EN,,0,0,0,,so let's just suppose we had this.\nDialogue: 0,0:39:15.93,0:39:17.44,EN,,0,0,0,,Suppose we were looking at the procedure\nDialogue: 0,0:39:18.07,0:39:31.60,EN,,0,0,0,,define F of A and B to be the sum of A and B.\nDialogue: 0,0:39:33.99,0:39:37.32,EN,,0,0,0,,So, as we typed in that procedure previously,\nDialogue: 0,0:39:37.69,0:39:41.64,EN,,0,0,0,,and now we're going to evaluate F of X and Y\nDialogue: 0,0:39:42.27,0:39:44.20,EN,,0,0,0,,again, in this environment, E,0,\nDialogue: 0,0:39:44.35,0:39:47.02,EN,,0,0,0,,where X is bound to 3 and Y is bound to 4.\nDialogue: 0,0:39:50.78,0:39:52.11,EN,,0,0,0,,When the defined is executed,\nDialogue: 0,0:39:52.12,0:39:53.69,EN,,0,0,0,,remember, there's a lambda here,\nDialogue: 0,0:39:53.82,0:39:55.53,EN,,0,0,0,,and lambdas create procedures.\nDialogue: 0,0:39:55.95,0:39:58.49,EN,,0,0,0,,And, basically, what will happen is,\nDialogue: 0,0:39:59.63,0:40:00.68,EN,,0,0,0,,in E0,\nDialogue: 0,0:40:01.00,0:40:02.65,EN,,0,0,0,,we'll end up with a binding for F,\nDialogue: 0,0:40:03.56,0:40:05.61,EN,,0,0,0,,which will say F is a procedure,\nDialogue: 0,0:40:07.15,0:40:11.28,EN,,0,0,0,,and its args are A and B,\nDialogue: 0,0:40:12.57,0:40:16.19,EN,,0,0,0,,and its body is plus a,b.\nDialogue: 0,0:40:18.11,0:40:20.99,EN,,0,0,0,,So that's what the environment would have looked like\nDialogue: 0,0:40:21.21,0:40:22.52,EN,,0,0,0,,had we made that definition.\nDialogue: 0,0:40:24.22,0:40:27.28,EN,,0,0,0,,Then, when we go to evaluate F of X and Y,\nDialogue: 0,0:40:28.80,0:40:30.89,EN,,0,0,0,,we'll go through exactly the same process\nDialogue: 0,0:40:31.02,0:40:31.85,EN,,0,0,0,,that we did before.\nDialogue: 0,0:40:31.88,0:40:33.09,EN,,0,0,0,,It's even the same expression.\nDialogue: 0,0:40:33.28,0:40:34.38,EN,,0,0,0,,The only difference is that\nDialogue: 0,0:40:34.40,0:40:36.64,EN,,0,0,0,,F, instead of having primitive \"plus\" in it\nDialogue: 0,0:40:37.24,0:40:38.99,EN,,0,0,0,,will have this thing.\nDialogue: 0,0:40:41.04,0:40:43.60,EN,,0,0,0,,And so we'll go through exactly the same process,\nDialogue: 0,0:40:43.60,0:40:44.92,EN,,0,0,0,,except this time, when we end up\nDialogue: 0,0:40:45.26,0:40:47.42,EN,,0,0,0,,at apply-dispatch,\nDialogue: 0,0:40:47.86,0:40:50.28,EN,,0,0,0,,the function register, instead of having primitive plus,\nDialogue: 0,0:40:50.44,0:40:53.58,EN,,0,0,0,,will have a thing that will represent it saying procedure,\nDialogue: 0,0:40:54.30,0:40:59.00,EN,,0,0,0,,where the args are A and B,\nDialogue: 0,0:41:00.64,0:41:06.27,EN,,0,0,0,,and the body is plus A, B.\nDialogue: 0,0:41:07.87,0:41:09.92,EN,,0,0,0,,And, again, what I mean, by its ENV,\nDialogue: 0,0:41:09.96,0:41:11.12,EN,,0,0,0,,I mean there's a pointer to it,\nDialogue: 0,0:41:11.24,0:41:13.07,EN,,0,0,0,,so don't worry that I'm writing a lot of stuff there.\nDialogue: 0,0:41:13.28,0:41:15.63,EN,,0,0,0,,There's a pointer to this procedure data structure.\nDialogue: 0,0:41:17.17,0:41:19.77,EN,,0,0,0,,OK, so, we're in exactly the same situation.\nDialogue: 0,0:41:20.27,0:41:22.43,EN,,0,0,0,,We get to apply-dispatch,\nDialogue: 0,0:41:23.98,0:41:26.48,EN,,0,0,0,,so, here, we come to apply-dispatch.\nDialogue: 0,0:41:26.48,0:41:28.73,EN,,0,0,0,,Last time, we branched off to a primitive procedure.\nDialogue: 0,0:41:30.01,0:41:30.70,EN,,0,0,0,,Here, it says oh,\nDialogue: 0,0:41:30.84,0:41:32.80,EN,,0,0,0,,we now have a compound procedure,\nDialogue: 0,0:41:34.55,0:41:36.60,EN,,0,0,0,,so we're going to go off to compound-apply.\nDialogue: 0,0:41:38.47,0:41:39.92,EN,,0,0,0,,Now, what's compound-apply?\nDialogue: 0,0:41:41.92,0:41:44.54,EN,,0,0,0,,Well, remember what the meta-circular evaluator did?\nDialogue: 0,0:41:45.09,0:41:47.40,EN,,0,0,0,,Compound-apply said we're going to evaluate\nDialogue: 0,0:41:49.90,0:41:51.60,EN,,0,0,0,,the body of the procedure\nDialogue: 0,0:41:52.94,0:41:54.12,EN,,0,0,0,,in some new environment.\nDialogue: 0,0:41:54.12,0:41:55.87,EN,,0,0,0,,Where does that new environment come from?\nDialogue: 0,0:41:56.73,0:42:01.36,EN,,0,0,0,,We take the environment that was packaged with the procedure,\nDialogue: 0,0:42:03.02,0:42:05.79,EN,,0,0,0,,we bind the parameters of the procedure\nDialogue: 0,0:42:06.00,0:42:07.63,EN,,0,0,0,,to the arguments that we're passing in,\nDialogue: 0,0:42:09.75,0:42:11.95,EN,,0,0,0,,and use that as a new frame to extend\nDialogue: 0,0:42:12.59,0:42:13.79,EN,,0,0,0,,the procedure environment.\nDialogue: 0,0:42:14.99,0:42:16.08,EN,,0,0,0,,And that's the environment\nDialogue: 0,0:42:16.30,0:42:18.88,EN,,0,0,0,,in which we evaluate the procedure body,\nDialogue: 0,0:42:20.12,0:42:24.47,EN,,0,0,0,,Right? That's going around the apply/eval loop.\nDialogue: 0,0:42:24.47,0:42:26.25,EN,,0,0,0,,That's apply coming back to call eval,\nDialogue: 0,0:42:32.86,0:42:34.92,EN,,0,0,0,,So, now, that's all we have to do in compound-apply.\nDialogue: 0,0:42:36.78,0:42:37.72,EN,,0,0,0,,What are we going to do?\nDialogue: 0,0:42:37.72,0:42:40.97,EN,,0,0,0,,We're going to manufacture a new environment.\nDialogue: 0,0:42:43.55,0:42:45.64,EN,,0,0,0,,And we're going to manufacture a new environment that,\nDialogue: 0,0:42:46.76,0:42:48.11,EN,,0,0,0,,let's see, that we'll call E1.\nDialogue: 0,0:42:52.90,0:42:55.63,EN,,0,0,0,,E1 is going to be some environment where the\nDialogue: 0,0:42:57.31,0:42:59.15,EN,,0,0,0,,where the parameters of the procedure,\nDialogue: 0,0:42:59.21,0:43:03.26,EN,,0,0,0,,Nwhere A is bound to 3, and B is bound to 4,\nDialogue: 0,0:43:04.27,0:43:05.76,EN,,0,0,0,,and it's linked to E0\nDialogue: 0,0:43:05.76,0:43:08.08,EN,,0,0,0,,because that's where f is defined.\nDialogue: 0,0:43:09.27,0:43:10.27,EN,,0,0,0,,And, in this environment,\nDialogue: 0,0:43:10.27,0:43:11.96,EN,,0,0,0,,we're going to evaluate the body of the procedure.\nDialogue: 0,0:43:12.05,0:43:14.48,EN,,0,0,0,,So let's look at that, we're going\nDialogue: 0,0:43:16.52,0:43:18.32,EN,,0,0,0,,Here we are at compound-apply,\nDialogue: 0,0:43:20.30,0:43:23.47,EN,,0,0,0,,which says assign to the expression register\nDialogue: 0,0:43:24.50,0:43:25.98,EN,,0,0,0,,the body of the procedure\nDialogue: 0,0:43:25.98,0:43:27.26,EN,,0,0,0,,that's in the function register.\nDialogue: 0,0:43:28.38,0:43:30.64,EN,,0,0,0,,So I assign to the expression register\nDialogue: 0,0:43:31.29,0:43:32.33,EN,,0,0,0,,the procedure body,\nDialogue: 0,0:43:40.75,0:43:41.10,EN,,0,0,0,,OK?\nDialogue: 0,0:43:42.64,0:43:44.97,EN,,0,0,0,,That's going to be evaluated in an environment\nDialogue: 0,0:43:45.82,0:43:48.32,EN,,0,0,0,,which is formed by making some bindings\nDialogue: 0,0:43:51.30,0:43:53.67,EN,,0,0,0,,using information determined by the procedure--\nDialogue: 0,0:43:53.67,0:43:56.25,EN,,0,0,0,,that's what's in FUN-- and the argument list.\nDialogue: 0,0:43:57.80,0:44:00.00,EN,,0,0,0,,And let's not worry about exactly what that does,\nDialogue: 0,0:44:00.08,0:44:01.63,EN,,0,0,0,,but you can see the information's there.\nDialogue: 0,0:44:01.93,0:44:03.32,EN,,0,0,0,,So make bindings will say oh,\nDialogue: 0,0:44:04.04,0:44:07.90,EN,,0,0,0,,the procedure, itself, had an environment attached to it.\nDialogue: 0,0:44:07.96,0:44:09.32,EN,,0,0,0,,I didn't write that quite here.\nDialogue: 0,0:44:09.36,0:44:10.56,EN,,0,0,0,,I should've said in environment\nDialogue: 0,0:44:11.30,0:44:12.73,EN,,0,0,0,,because every procedure gets built\nDialogue: 0,0:44:12.76,0:44:13.44,EN,,0,0,0,,with an environment.\nDialogue: 0,0:44:13.66,0:44:14.83,EN,,0,0,0,,So, from that environment,\nDialogue: 0,0:44:15.68,0:44:16.35,EN,,0,0,0,,it knows\nDialogue: 0,0:44:16.60,0:44:18.65,EN,,0,0,0,,what the procedure's definition environment is.\nDialogue: 0,0:44:19.29,0:44:20.75,EN,,0,0,0,,It knows what the arguments are.\nDialogue: 0,0:44:21.83,0:44:22.49,EN,,0,0,0,,It looks at argl,\nDialogue: 0,0:44:22.49,0:44:24.28,EN,,0,0,0,,and then you see a reversal convention here.\nDialogue: 0,0:44:24.28,0:44:26.62,EN,,0,0,0,,It just has to know that argl is reversed,\nDialogue: 0,0:44:27.06,0:44:28.81,EN,,0,0,0,,and it builds this frame, E,1.\nDialogue: 0,0:44:29.99,0:44:31.08,EN,,0,0,0,,All right, so, let's assume that\nDialogue: 0,0:44:31.10,0:44:32.92,EN,,0,0,0,,that's what make bindings returns,\nDialogue: 0,0:44:33.36,0:44:36.22,EN,,0,0,0,,so it assigns to ENV this thing, E,1.\nDialogue: 0,0:44:41.34,0:44:42.54,EN,,0,0,0,,The next thing it says\nDialogue: 0,0:44:43.95,0:44:45.84,EN,,0,0,0,,is restore continue.\nDialogue: 0,0:44:46.89,0:44:48.19,EN,,0,0,0,,Remember what continue was here?\nDialogue: 0,0:44:48.76,0:44:50.43,EN,,0,0,0,,It got put up in the last segment.\nDialogue: 0,0:44:52.24,0:44:54.02,EN,,0,0,0,,Continue got stored.\nDialogue: 0,0:44:54.02,0:44:55.18,EN,,0,0,0,,That was the original done,\nDialogue: 0,0:44:55.32,0:44:56.56,EN,,0,0,0,,which said what are you going to do\nDialogue: 0,0:44:56.73,0:44:59.44,EN,,0,0,0,,after you're done with this particular application?\nDialogue: 0,0:45:00.14,0:45:01.72,EN,,0,0,0,,It was one of the very first things that happened\nDialogue: 0,0:45:01.76,0:45:03.18,EN,,0,0,0,,when we evaluated the application.\nDialogue: 0,0:45:03.88,0:45:05.87,EN,,0,0,0,,And now, finally, we're going to restore continue.\nDialogue: 0,0:45:06.86,0:45:09.55,EN,,0,0,0,,Remember apply-dispatch's contract.\nDialogue: 0,0:45:09.58,0:45:11.20,EN,,0,0,0,,It assumes that where it should go to next\nDialogue: 0,0:45:11.23,0:45:11.98,EN,,0,0,0,,was on the stack,\nDialogue: 0,0:45:12.03,0:45:13.12,EN,,0,0,0,,and there it was on the stack.\nDialogue: 0,0:45:13.59,0:45:14.76,EN,,0,0,0,,Continue has done,\nDialogue: 0,0:45:17.82,0:45:19.90,EN,,0,0,0,,and now we're going to go back to eval-dispatch.\nDialogue: 0,0:45:19.94,0:45:20.84,EN,,0,0,0,,We're set up again.\nDialogue: 0,0:45:20.97,0:45:24.41,EN,,0,0,0,,We have an expression, an environment, and a place to go to.\nDialogue: 0,0:45:25.80,0:45:26.89,EN,,0,0,0,,We're not going to go through that\nDialogue: 0,0:45:27.88,0:45:29.55,EN,,0,0,0,,because it's sort of the same expression.\nDialogue: 0,0:45:35.40,0:45:37.79,EN,,0,0,0,,OK, but the thing, again, to notice\nDialogue: 0,0:45:37.82,0:45:38.73,EN,,0,0,0,,is, at this point,\nDialogue: 0,0:45:39.34,0:45:43.72,EN,,0,0,0,,we have reduced the original expression, F,X,Y,\nDialogue: 0,0:45:44.64,0:45:47.92,EN,,0,0,0,,We've reduced evaluating F,X,Y in environment E,0\nDialogue: 0,0:45:48.89,0:45:52.67,EN,,0,0,0,,to evaluate plus A, B in E,1.\nDialogue: 0,0:45:52.78,0:45:55.92,EN,,0,0,0,,And notice, nothing's on the stack, right?\nDialogue: 0,0:45:56.11,0:45:56.83,EN,,0,0,0,,It's a reduction.\nDialogue: 0,0:45:56.84,0:45:59.80,EN,,0,0,0,,At this point, the machine does not contain,\nDialogue: 0,0:45:59.84,0:46:01.20,EN,,0,0,0,,as part of its state,\nDialogue: 0,0:46:01.76,0:46:03.71,EN,,0,0,0,,the fact that it's in the middle of evaluating\nDialogue: 0,0:46:03.72,0:46:04.88,EN,,0,0,0,,some procedure called f,\nDialogue: 0,0:46:05.49,0:46:06.28,EN,,0,0,0,,that's gone,\nDialogue: 0,0:46:07.66,0:46:09.55,EN,,0,0,0,,Right? There's no accumulated state?\nDialogue: 0,0:46:13.07,0:46:14.37,EN,,0,0,0,,Again, that's a very important idea.\nDialogue: 0,0:46:14.37,0:46:16.33,EN,,0,0,0,,That's the meaning of,\nDialogue: 0,0:46:16.76,0:46:18.39,EN,,0,0,0,,when we used to write in the substitution model,\nDialogue: 0,0:46:18.39,0:46:20.86,EN,,0,0,0,,this expression reduces to that expression.\nDialogue: 0,0:46:21.35,0:46:22.66,EN,,0,0,0,,And you don't have to remember anything.\nDialogue: 0,0:46:22.66,0:46:24.50,EN,,0,0,0,,And here, you see the meaning of reduction.\nDialogue: 0,0:46:24.56,0:46:26.16,EN,,0,0,0,,At this point, there is nothing on the stack.\nDialogue: 0,0:46:31.59,0:46:33.63,EN,,0,0,0,,See, that has very important consequences.\nDialogue: 0,0:46:35.24,0:46:37.90,EN,,0,0,0,,Let's go back and look at iterative factorial,\nDialogue: 0,0:46:40.42,0:46:42.76,EN,,0,0,0,,all right? Remember, this was some sort of loop\nDialogue: 0,0:46:44.01,0:46:44.88,EN,,0,0,0,,and doing iter.\nDialogue: 0,0:46:45.13,0:46:47.36,EN,,0,0,0,,And we kept saying that's an iterative procedure,\nDialogue: 0,0:46:49.26,0:46:53.84,EN,,0,0,0,,And what we wrote, remember,\nDialogue: 0,0:46:58.44,0:47:03.13,EN,,0,0,0,,are things like, we said,\nDialogue: 0,0:47:04.35,0:47:11.07,EN,,0,0,0,,fact-iter of 5.\nDialogue: 0,0:47:12.36,0:47:18.67,EN,,0,0,0,,We wrote things like reduces to iter of 1, and 1, and 5,\nDialogue: 0,0:47:19.03,0:47:25.15,EN,,0,0,0,,which reduces to iter of 1, and 2, and 5,\nDialogue: 0,0:47:25.32,0:47:27.07,EN,,0,0,0,,and so on, and so on, and so on.\nDialogue: 0,0:47:27.07,0:47:28.17,EN,,0,0,0,,And we kept saying well, look,\nDialogue: 0,0:47:28.17,0:47:30.35,EN,,0,0,0,,you don't have to build up any storage to do that.\nDialogue: 0,0:47:31.72,0:47:32.73,EN,,0,0,0,,And we waved our hands,\nDialogue: 0,0:47:32.75,0:47:34.59,EN,,0,0,0,,and said in principle, there's no storage needed.\nDialogue: 0,0:47:35.04,0:47:36.17,EN,,0,0,0,,Now, you see no storage needed.\nDialogue: 0,0:47:36.17,0:47:39.09,EN,,0,0,0,,Each of these is a real reduction, right?\nDialogue: 0,0:47:39.09,0:47:42.60,EN,,0,0,0,,As you walk through these expressions,\nDialogue: 0,0:47:47.30,0:47:50.51,EN,,0,0,0,,As you walk through these expressions,\nDialogue: 0,0:47:50.83,0:47:51.37,EN,,0,0,0,,what you'll see\nDialogue: 0,0:47:51.37,0:47:52.81,EN,,0,0,0,,are these expressions on the stack\nDialogue: 0,0:47:53.75,0:47:55.64,EN,,0,0,0,,in some particular environment,\nDialogue: 0,0:47:56.42,0:48:00.02,EN,,0,0,0,,and then these expressions, sorry, in the EXP register\nDialogue: 0,0:48:00.02,0:48:01.50,EN,,0,0,0,,in some particular environment.\nDialogue: 0,0:48:01.57,0:48:02.19,EN,,0,0,0,,And, at each point,\nDialogue: 0,0:48:02.19,0:48:04.00,EN,,0,0,0,,there'll be no accumulated stuff on the stack\nDialogue: 0,0:48:04.36,0:48:05.68,EN,,0,0,0,,because each one's a real reduction.\nDialogue: 0,0:48:09.28,0:48:10.51,EN,,0,0,0,,All right, so, for example,\nDialogue: 0,0:48:10.58,0:48:12.51,EN,,0,0,0,,just to go through it in a little bit more care,\nDialogue: 0,0:48:13.46,0:48:16.88,EN,,0,0,0,,if I start out with an expression that says something like,\nDialogue: 0,0:48:22.44,0:48:34.25,EN,,0,0,0,,oh, say, fact-iter of 5 in some environment\nDialogue: 0,0:48:42.11,0:48:46.30,EN,,0,0,0,,that will, at some point, create an environment\nDialogue: 0,0:48:46.81,0:48:48.38,EN,,0,0,0,,in which n is down to 5.\nDialogue: 0,0:48:51.47,0:48:52.01,EN,,0,0,0,,Let's call that--\nDialogue: 0,0:48:55.68,0:48:56.59,EN,,0,0,0,,And, at some point,\nDialogue: 0,0:48:56.89,0:49:02.56,EN,,0,0,0,,the machine will reduce this whole thing\nDialogue: 0,0:49:02.91,0:49:04.35,EN,,0,0,0,,to a thing that says that's really\nDialogue: 0,0:49:04.76,0:49:09.85,EN,,0,0,0,,iter of 1, and 1, and n,\nDialogue: 0,0:49:10.68,0:49:13.72,EN,,0,0,0,,evaluated in this environment, E,1\nDialogue: 0,0:49:15.87,0:49:17.16,EN,,0,0,0,,with nothing on the stack.\nDialogue: 0,0:49:17.16,0:49:19.55,EN,,0,0,0,,See, at this moment, the machine is not remembering\nDialogue: 0,0:49:20.71,0:49:22.50,EN,,0,0,0,,that evaluating this expression, iter--\nDialogue: 0,0:49:25.00,0:49:25.63,EN,,0,0,0,,which is the loop--\nDialogue: 0,0:49:25.79,0:49:28.57,EN,,0,0,0,,is part of this thing called iterative factorial.\nDialogue: 0,0:49:29.68,0:49:30.59,EN,,0,0,0,,It's not remembering that.\nDialogue: 0,0:49:30.59,0:49:33.17,EN,,0,0,0,,It's just reducing the expression to that, right?\nDialogue: 0,0:49:33.17,0:49:36.56,EN,,0,0,0,,If we look again at the body of iterative factorial,\nDialogue: 0,0:49:38.05,0:49:41.08,EN,,0,0,0,,this expression has reduced to that expression.\nDialogue: 0,0:49:42.81,0:49:43.87,EN,,0,0,0,,Oh, I shouldn't have the n there.\nDialogue: 0,0:49:46.59,0:49:47.74,EN,,0,0,0,,It's a slightly different convention\nDialogue: 0,0:49:47.74,0:49:49.13,EN,,0,0,0,,from the slide to the program.\nDialogue: 0,0:49:53.34,0:49:56.25,EN,,0,0,0,,And, then, what's the body of iter?\nDialogue: 0,0:49:56.28,0:49:57.40,EN,,0,0,0,,Well, iter's going to be an if,\nDialogue: 0,0:49:58.75,0:50:00.19,EN,,0,0,0,,and I won't go through the details of if.\nDialogue: 0,0:50:00.24,0:50:01.63,EN,,0,0,0,,It'll evaluate the predicate.\nDialogue: 0,0:50:02.40,0:50:03.71,EN,,0,0,0,,In this case, it'll be false.\nDialogue: 0,0:50:03.81,0:50:08.64,EN,,0,0,0,,And this iter will now reduce to the expression\nDialogue: 0,0:50:09.85,0:50:20.20,EN,,0,0,0,,iter of whatever it says, star, counter product, and--\nDialogue: 0,0:50:21.62,0:50:22.24,EN,,0,0,0,,what does it say--\nDialogue: 0,0:50:22.68,0:50:24.56,EN,,0,0,0,,plus counter 1\nDialogue: 0,0:50:28.72,0:50:31.42,EN,,0,0,0,,in some other environment, by this time, E,2,\nDialogue: 0,0:50:32.97,0:50:35.98,EN,,0,0,0,,where E,2 will be set up having bindings\nDialogue: 0,0:50:36.49,0:50:39.39,EN,,0,0,0,,for product and counter.\nDialogue: 0,0:50:42.92,0:50:44.33,EN,,0,0,0,,And it'll reduce to that.\nDialogue: 0,0:50:44.94,0:50:46.04,EN,,0,0,0,,Right? It won't be remembering\nDialogue: 0,0:50:46.06,0:50:48.75,EN,,0,0,0,,that it's part of something that it has to return to.\nDialogue: 0,0:50:49.34,0:50:50.43,EN,,0,0,0,,And when iter calls iter again,\nDialogue: 0,0:50:50.44,0:50:52.56,EN,,0,0,0,,it'll reduce to another thing that looks like this\nDialogue: 0,0:50:53.05,0:50:54.68,EN,,0,0,0,,in some environment, E,3,\nDialogue: 0,0:50:54.83,0:50:56.67,EN,,0,0,0,,which has new bindings for product and counter.\nDialogue: 0,0:50:58.80,0:51:05.29,EN,,0,0,0,,OK? So, if you're wondering,\nDialogue: 0,0:51:06.09,0:51:07.53,EN,,0,0,0,,if you've always been queasy about\nDialogue: 0,0:51:08.25,0:51:10.67,EN,,0,0,0,,about how it is we've been saying those procedures\nDialogue: 0,0:51:10.67,0:51:12.45,EN,,0,0,0,,that look syntactically recursive,\nDialogue: 0,0:51:13.20,0:51:15.69,EN,,0,0,0,,are, in fact, iterative,\nDialogue: 0,0:51:15.87,0:51:17.24,EN,,0,0,0,,run in constant space,\nDialogue: 0,0:51:18.40,0:51:19.75,EN,,0,0,0,,well, I don't know if this makes you less queasy,\nDialogue: 0,0:51:19.75,0:51:21.23,EN,,0,0,0,,but at least it shows you what's happening.\nDialogue: 0,0:51:21.23,0:51:22.81,EN,,0,0,0,,There really isn't any buildup there.\nDialogue: 0,0:51:25.91,0:51:27.58,EN,,0,0,0,,Now, you might ask well, is there buildup\nDialogue: 0,0:51:27.98,0:51:30.08,EN,,0,0,0,,in principle in these environment frames?\nDialogue: 0,0:51:31.71,0:51:32.37,EN,,0,0,0,,And the answer is yeah,\nDialogue: 0,0:51:32.40,0:51:33.84,EN,,0,0,0,,you have to make these new environment frames,\nDialogue: 0,0:51:33.84,0:51:35.26,EN,,0,0,0,,but you don't have to hang onto them\nDialogue: 0,0:51:35.42,0:51:36.19,EN,,0,0,0,,when you're done.\nDialogue: 0,0:51:36.44,0:51:37.61,EN,,0,0,0,,They can be garbage collected,\nDialogue: 0,0:51:37.92,0:51:39.47,EN,,0,0,0,,or the space can be reused automatically.\nDialogue: 0,0:51:40.72,0:51:42.99,EN,,0,0,0,,But you see the control structure of the evaluator\nDialogue: 0,0:51:43.25,0:51:46.12,EN,,0,0,0,,is really using this idea that you actually have a reduction,\nDialogue: 0,0:51:47.02,0:51:49.29,EN,,0,0,0,,so these procedures really are iterative procedures.\nDialogue: 0,0:51:50.13,0:51:51.38,EN,,0,0,0,,All right, let's stop for questions.\nDialogue: 0,0:52:02.68,0:52:03.23,EN,,0,0,0,,All right, let's break.\nDialogue: 0,0:52:04.12,0:52:24.56,EN,,0,0,0,,[JESU, JOY OF MAN'S DESIRING]\nDialogue: 0,0:52:24.60,0:52:29.69,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:52:35.20,0:52:38.36,EN,,0,0,0,,By: Prof. Harold Abelson && Sussman Jay Sussman\nDialogue: 0,0:52:38.36,0:52:42.14,EN,,0,0,0,,The Structure And Interpretation of Computer Programs\nDialogue: 0,0:52:48.77,0:52:51.55,EN,,0,0,0,,PROFESSOR: Let me contrast the iterative procedure\nDialogue: 0,0:52:52.77,0:52:54.89,EN,,0,0,0,,just so you'll see where space does build up\nDialogue: 0,0:52:55.12,0:52:56.14,EN,,0,0,0,,with a recursive procedure,\nDialogue: 0,0:52:56.17,0:52:57.29,EN,,0,0,0,,so you can see the difference.\nDialogue: 0,0:52:58.03,0:53:01.20,EN,,0,0,0,,Let's look at the evaluation of recursive factorial.\nDialogue: 0,0:53:02.65,0:53:05.53,EN,,0,0,0,,So, here's fact-recursive,\nDialogue: 0,0:53:05.55,0:53:07.22,EN,,0,0,0,,or standard factorial definition.\nDialogue: 0,0:53:07.22,0:53:10.01,EN,,0,0,0,,We said this one is still a recursive procedure,\nDialogue: 0,0:53:10.01,0:53:12.57,EN,,0,0,0,,but this is actually a recursive process.\nDialogue: 0,0:53:13.75,0:53:16.56,EN,,0,0,0,,And then, just to link it back to the way we started,\nDialogue: 0,0:53:16.83,0:53:20.53,EN,,0,0,0,,we said oh, you can see that it's going to be recursive process\nDialogue: 0,0:53:20.53,0:53:21.82,EN,,0,0,0,,by the substitution model\nDialogue: 0,0:53:22.36,0:53:28.00,EN,,0,0,0,,because, if I say recursive factorial of 5,\nDialogue: 0,0:53:30.45,0:53:34.94,EN,,0,0,0,,that turns into 5 times--\nDialogue: 0,0:53:36.28,0:53:37.82,EN,,0,0,0,,what is it, fact-rec, or record fact--\nDialogue: 0,0:53:42.62,0:53:47.93,EN,,0,0,0,,5 times recursive factorial of 4,\nDialogue: 0,0:53:49.66,0:53:58.22,EN,,0,0,0,,which turns into 5 times 4 times fact-rec of 3,\nDialogue: 0,0:54:00.22,0:54:08.60,EN,,0,0,0,,which returns into 5 times 4 times 3 times\nDialogue: 0,0:54:13.45,0:54:15.31,EN,,0,0,0,,and so on, right?\nDialogue: 0,0:54:15.39,0:54:17.39,EN,,0,0,0,,The idea is there was this chain of stuff building up,\nDialogue: 0,0:54:18.10,0:54:20.06,EN,,0,0,0,,which justified, in the substitution model,\nDialogue: 0,0:54:20.08,0:54:21.28,EN,,0,0,0,,the fact that it's recursive.\nDialogue: 0,0:54:21.52,0:54:24.18,EN,,0,0,0,,And now, let's actually see that chain of stuff build up\nDialogue: 0,0:54:24.18,0:54:25.29,EN,,0,0,0,,and where it is in the machine, OK?\nDialogue: 0,0:54:27.68,0:54:29.95,EN,,0,0,0,,All right, well, let's imagine we're going to start out again.\nDialogue: 0,0:54:30.44,0:54:40.01,EN,,0,0,0,,We'll tell it to evaluate recursive factorial of 5\nDialogue: 0,0:54:41.45,0:54:43.39,EN,,0,0,0,,in some environment, again, E0, where\nDialogue: 0,0:54:45.08,0:54:48.97,EN,,0,0,0,,where recursive factorial is defined, OK?\nDialogue: 0,0:54:49.55,0:54:51.23,EN,,0,0,0,,Well, now we know what's eventually going to happen.\nDialogue: 0,0:54:52.25,0:54:53.64,EN,,0,0,0,,This is going to come along,\nDialogue: 0,0:54:53.92,0:54:55.64,EN,,0,0,0,,it'll evaluate those things,\nDialogue: 0,0:54:55.68,0:54:56.99,EN,,0,0,0,,figure out it's a procedure,\nDialogue: 0,0:54:57.18,0:55:00.16,EN,,0,0,0,,build somewhere over here an environment, E1,\nDialogue: 0,0:55:00.88,0:55:03.69,EN,,0,0,0,,which has n bound to 5,\nDialogue: 0,0:55:04.33,0:55:06.54,EN,,0,0,0,,which hangs off of E0,\nDialogue: 0,0:55:07.80,0:55:08.97,EN,,0,0,0,,which would be, presumably,\nDialogue: 0,0:55:08.99,0:55:12.30,EN,,0,0,0,,the definition environment of recursive factorial.\nDialogue: 0,0:55:14.11,0:55:15.74,EN,,0,0,0,,OK? And, in this environment,\nDialogue: 0,0:55:15.76,0:55:17.48,EN,,0,0,0,,it's going to go off and evaluate the body.\nDialogue: 0,0:55:19.67,0:55:25.92,EN,,0,0,0,,So, again, the evaluation here will reduce to\nDialogue: 0,0:55:27.00,0:55:28.92,EN,,0,0,0,,evaluating the body in E1.\nDialogue: 0,0:55:30.16,0:55:31.34,EN,,0,0,0,,That's going to look at an if,\nDialogue: 0,0:55:32.17,0:55:33.53,EN,,0,0,0,,and I won't go through the details of if.\nDialogue: 0,0:55:33.53,0:55:34.88,EN,,0,0,0,,It'll look at the predicate.\nDialogue: 0,0:55:34.88,0:55:37.53,EN,,0,0,0,,It'll decide it eventually has to evaluate the alternative.\nDialogue: 0,0:55:37.84,0:55:40.41,EN,,0,0,0,,So this whole thing, again, will reduce to\nDialogue: 0,0:55:41.30,0:55:45.53,EN,,0,0,0,,the alternative of recursive factorial,\nDialogue: 0,0:55:45.82,0:55:46.97,EN,,0,0,0,,the alternative clause,\nDialogue: 0,0:55:47.23,0:55:51.16,EN,,0,0,0,,which says that this whole thing reduces to times n\nDialogue: 0,0:55:53.07,0:55:59.96,EN,,0,0,0,,of recursive factorial of n minus 1\nDialogue: 0,0:56:03.48,0:56:05.55,EN,,0,0,0,,in the environment E1\nDialogue: 0,0:56:08.38,0:56:10.91,EN,,0,0,0,,OK? So the original expression, now, is going to reduce\nDialogue: 0,0:56:11.04,0:56:12.52,EN,,0,0,0,,to evaluating that expression, all right?\nDialogue: 0,0:56:13.75,0:56:16.28,EN,,0,0,0,,OK? Now we have an application.\nDialogue: 0,0:56:16.28,0:56:17.63,EN,,0,0,0,,We did an application before.\nDialogue: 0,0:56:18.22,0:56:20.25,EN,,0,0,0,,Remember what happens in an application?\nDialogue: 0,0:56:20.36,0:56:21.69,EN,,0,0,0,,The first thing you do is you go off and you\nDialogue: 0,0:56:21.74,0:56:24.81,EN,,0,0,0,,you save the value of the continue register on the stack.\nDialogue: 0,0:56:25.35,0:56:27.18,EN,,0,0,0,,So the stack here is going to have done in it.\nDialogue: 0,0:56:29.98,0:56:32.88,EN,,0,0,0,,And then you're going to set up to evaluate the sub-parts.\nDialogue: 0,0:56:35.00,0:56:37.20,EN,,0,0,0,,OK? So here we go off to evaluate the sub-parts.\nDialogue: 0,0:56:39.47,0:56:41.45,EN,,0,0,0,,First thing we're going to do is evaluate the operator.\nDialogue: 0,0:56:44.60,0:56:46.32,EN,,0,0,0,,What happens when we evaluate an operator?\nDialogue: 0,0:56:47.25,0:56:48.99,EN,,0,0,0,,Well, we arrange things so that\nDialogue: 0,0:56:49.00,0:56:51.04,EN,,0,0,0,,the operator ends up in the expression register.\nDialogue: 0,0:56:51.48,0:56:53.15,EN,,0,0,0,,The environments in the ENV register\nDialogue: 0,0:56:53.66,0:56:54.60,EN,,0,0,0,,continue someplace\nDialogue: 0,0:56:54.62,0:56:56.22,EN,,0,0,0,,where we're going to go evaluate the arguments.\nDialogue: 0,0:56:56.59,0:56:57.37,EN,,0,0,0,,And, on the stack,\nDialogue: 0,0:56:57.40,0:56:59.29,EN,,0,0,0,,we've saved the original continue,\nDialogue: 0,0:56:59.52,0:57:01.02,EN,,0,0,0,,which is where we wanted to be when we're all done.\nDialogue: 0,0:57:01.72,0:57:02.86,EN,,0,0,0,,And then the things we needed\nDialogue: 0,0:57:03.58,0:57:05.80,EN,,0,0,0,,when we're going to get done evaluating the operator,\nDialogue: 0,0:57:05.90,0:57:07.66,EN,,0,0,0,,the things we'll need to evaluate the arguments,\nDialogue: 0,0:57:07.69,0:57:12.01,EN,,0,0,0,,namely the environment and those arguments,\nDialogue: 0,0:57:12.14,0:57:13.44,EN,,0,0,0,,those unevaluated arguments,\nDialogue: 0,0:57:14.20,0:57:15.62,EN,,0,0,0,,so there they are sitting on the stack.\nDialogue: 0,0:57:15.62,0:57:18.59,EN,,0,0,0,,And we're about to go off to evaluate the operator.\nDialogue: 0,0:57:23.26,0:57:26.73,EN,,0,0,0,,Well, when we return from this particular call--\nDialogue: 0,0:57:26.92,0:57:28.64,EN,,0,0,0,,so we're about to call eval-dispatch here--\nDialogue: 0,0:57:29.38,0:57:30.83,EN,,0,0,0,,when we return from this call,\nDialogue: 0,0:57:31.45,0:57:32.70,EN,,0,0,0,,the value of that operator,\nDialogue: 0,0:57:32.73,0:57:33.52,EN,,0,0,0,,which, in this case,\nDialogue: 0,0:57:33.55,0:57:35.44,EN,,0,0,0,,is going to be the primitive multiplier procedure,\nDialogue: 0,0:57:36.44,0:57:37.93,EN,,0,0,0,,will end up in the FUN register.\nDialogue: 0,0:57:43.02,0:57:44.53,EN,,0,0,0,,We're going to evaluate some arguments.\nDialogue: 0,0:57:44.53,0:57:45.85,EN,,0,0,0,,They will evaluate n here.\nDialogue: 0,0:57:47.73,0:57:49.87,EN,,0,0,0,,That'll give us 5, in this case.\nDialogue: 0,0:57:50.25,0:57:52.04,EN,,0,0,0,,We're going to put that in the argl register,\nDialogue: 0,0:57:53.00,0:57:55.88,EN,,0,0,0,,and then we'll go off to evaluate the second operand.\nDialogue: 0,0:57:57.46,0:58:00.48,EN,,0,0,0,,So, at the point where we go off to evaluate the second operand--\nDialogue: 0,0:58:00.52,0:58:02.19,EN,,0,0,0,,and I'll skip details like computing,\nDialogue: 0,0:58:02.20,0:58:03.58,EN,,0,0,0,,N minus 1, and all of that--\nDialogue: 0,0:58:03.71,0:58:05.88,EN,,0,0,0,,but, when we go off to evaluate the second operand,\nDialogue: 0,0:58:06.62,0:58:10.44,EN,,0,0,0,,that will eventually reduce to another call to fact-recursive.\nDialogue: 0,0:58:12.00,0:58:14.20,EN,,0,0,0,,And, what we've got on the stack here is\nDialogue: 0,0:58:16.52,0:58:19.94,EN,,0,0,0,,the operator from that combination that we're going to use it in\nDialogue: 0,0:58:20.12,0:58:21.07,EN,,0,0,0,,and the other argument.\nDialogue: 0,0:58:23.40,0:58:27.61,EN,,0,0,0,,OK? So, now, we're set up for another call\nDialogue: 0,0:58:28.49,0:58:29.69,EN,,0,0,0,,to recursive factorial.\nDialogue: 0,0:58:30.20,0:58:31.43,EN,,0,0,0,,And, when we're done with this one,\nDialogue: 0,0:58:31.56,0:58:33.64,EN,,0,0,0,,we're going to go to accumulate the last arg.\nDialogue: 0,0:58:34.12,0:58:35.20,EN,,0,0,0,,and remember what that'll do?\nDialogue: 0,0:58:35.20,0:58:35.93,EN,,0,0,0,,That'll say oh,\nDialogue: 0,0:58:36.45,0:58:39.28,EN,,0,0,0,,whatever the result of this has to get combined with that,\nDialogue: 0,0:58:39.28,0:58:40.40,EN,,0,0,0,,and we're going to multiply them.\nDialogue: 0,0:58:41.69,0:58:42.38,EN,,0,0,0,,But, notice now,\nDialogue: 0,0:58:42.73,0:58:44.81,EN,,0,0,0,,we're at another recursive factorial.\nDialogue: 0,0:58:45.72,0:58:48.92,EN,,0,0,0,,We're about to call eval-dispatch again,\nDialogue: 0,0:58:49.32,0:58:50.60,EN,,0,0,0,,except we haven't really reduced it\nDialogue: 0,0:58:50.64,0:58:52.08,EN,,0,0,0,,because there's stuff on the stack now.\nDialogue: 0,0:58:53.70,0:58:55.39,EN,,0,0,0,,The stuff on the stack says oh, when you get back,\nDialogue: 0,0:58:55.40,0:58:57.52,EN,,0,0,0,,you'd better multiply it by the 5 you had hanging there.\nDialogue: 0,0:58:58.43,0:59:05.77,EN,,0,0,0,,So, when we go off to make another call,\nDialogue: 0,0:59:07.12,0:59:08.84,EN,,0,0,0,,we evaluate the n minus 1.\nDialogue: 0,0:59:09.30,0:59:11.05,EN,,0,0,0,,That gives us another environment which\nDialogue: 0,0:59:11.25,0:59:13.84,EN,,0,0,0,,in which the new n's going to be down to 4.\nDialogue: 0,0:59:14.60,0:59:16.22,EN,,0,0,0,,And we're about to call eval-dispatch again.\nDialogue: 0,0:59:19.20,0:59:20.22,EN,,0,0,0,,We get another call.\nDialogue: 0,0:59:21.35,0:59:24.44,EN,,0,0,0,,That 4 is going to end up in the same situation.\nDialogue: 0,0:59:26.04,0:59:28.62,EN,,0,0,0,,We'll end up with another call to fact-recursive n.\nDialogue: 0,0:59:30.02,0:59:32.68,EN,,0,0,0,,And sitting on the stack will be the stuff from the original one\nDialogue: 0,0:59:32.88,0:59:34.51,EN,,0,0,0,,and, now, the subsidiary one we're doing.\nDialogue: 0,0:59:35.36,0:59:36.91,EN,,0,0,0,,And both of them are waiting for the same thing.\nDialogue: 0,0:59:36.91,0:59:39.16,EN,,0,0,0,,They're going to go to accumulate a last argument.\nDialogue: 0,0:59:40.51,0:59:42.94,EN,,0,0,0,,And then, of course, when we go to the fourth call,\nDialogue: 0,0:59:43.25,0:59:44.38,EN,,0,0,0,,the same thing happens.\nDialogue: 0,0:59:45.64,0:59:47.07,EN,,0,0,0,,And this goes on, and on, and on.\nDialogue: 0,0:59:47.30,0:59:48.60,EN,,0,0,0,,And what you see here on the stack,\nDialogue: 0,0:59:50.30,0:59:52.22,EN,,0,0,0,,exactly what's sitting here on the stack,\nDialogue: 0,0:59:52.22,0:59:54.59,EN,,0,0,0,,the thing that says times and 5.\nDialogue: 0,0:59:54.96,0:59:56.40,EN,,0,0,0,,And what you're going to do with that\nDialogue: 0,0:59:56.59,0:59:58.54,EN,,0,0,0,,accumulate that into a last argument.\nDialogue: 0,1:00:00.47,1:00:02.01,EN,,0,0,0,,That's exactly this, right?\nDialogue: 0,1:00:02.01,1:00:04.75,EN,,0,0,0,,This is exactly where that stuff is hanging.\nDialogue: 0,1:00:05.65,1:00:10.65,EN,,0,0,0,,Effectively, the operator you're going to apply,\nDialogue: 0,1:00:11.72,1:00:14.30,EN,,0,0,0,,the other argument that it's got\nDialogue: 0,1:00:14.32,1:00:15.79,EN,,0,0,0,,to be multiplied by when you get back\nDialogue: 0,1:00:15.80,1:00:16.91,EN,,0,0,0,,and sort of the parentheses,\nDialogue: 0,1:00:16.94,1:00:18.96,EN,,0,0,0,,which says yeah, what you wanted to do was accumulate them.\nDialogue: 0,1:00:19.62,1:00:21.88,EN,,0,0,0,,So, you see, the substitution model is not such a lie.\nDialogue: 0,1:00:22.56,1:00:23.63,EN,,0,0,0,,That really is, in some sense,\nDialogue: 0,1:00:23.64,1:00:25.31,EN,,0,0,0,,what's sitting right on the stack.\nDialogue: 0,1:00:29.37,1:00:30.40,EN,,0,0,0,,All right, so that,\nDialogue: 0,1:00:30.81,1:00:32.48,EN,,0,0,0,,in some sense, should explain for you,\nDialogue: 0,1:00:33.26,1:00:34.52,EN,,0,0,0,,or at least convince you,\nDialogue: 0,1:00:35.93,1:00:38.72,EN,,0,0,0,,that somehow, this evaluator is managing\nDialogue: 0,1:00:40.06,1:00:42.86,EN,,0,0,0,,to take these procedures and execute some of them iteratively\nDialogue: 0,1:00:42.95,1:00:44.25,EN,,0,0,0,,and some of them recursively,\nDialogue: 0,1:00:45.26,1:00:47.45,EN,,0,0,0,,even though, as syntactically,\nDialogue: 0,1:00:47.45,1:00:49.05,EN,,0,0,0,,they look like recursive procedures.\nDialogue: 0,1:00:49.40,1:00:50.64,EN,,0,0,0,,How's it managing to do that?\nDialogue: 0,1:00:50.66,1:00:53.72,EN,,0,0,0,,Well, the basic reason it's managing to do that\nDialogue: 0,1:00:53.80,1:00:55.68,EN,,0,0,0,,is the evaluator is set up\nDialogue: 0,1:00:56.04,1:00:59.26,EN,,0,0,0,,to save only what it needs later.\nDialogue: 0,1:01:01.09,1:01:04.25,EN,,0,0,0,,So, for example, at the point where you've reduced\nDialogue: 0,1:01:04.67,1:01:07.39,EN,,0,0,0,,evaluating an expression and an environment\nDialogue: 0,1:01:07.87,1:01:09.87,EN,,0,0,0,,to applying a procedure to some arguments,\nDialogue: 0,1:01:10.52,1:01:12.49,EN,,0,0,0,,it doesn't need that original environment anymore\nDialogue: 0,1:01:13.37,1:01:16.65,EN,,0,0,0,,because any environment stuff will be packaged inside the procedures\nDialogue: 0,1:01:17.88,1:01:19.36,EN,,0,0,0,,where the application's going to happen.\nDialogue: 0,1:01:20.75,1:01:21.61,EN,,0,0,0,,All right, similarly,\nDialogue: 0,1:01:21.63,1:01:23.65,EN,,0,0,0,,when you're going along evaluating an argument list,\nDialogue: 0,1:01:23.65,1:01:25.20,EN,,0,0,0,,when you've finished evaluating the list,\nDialogue: 0,1:01:25.91,1:01:28.03,EN,,0,0,0,,when you're finished evaluating the last argument,\nDialogue: 0,1:01:28.20,1:01:31.61,EN,,0,0,0,,you don't need that argument list any more, right?\nDialogue: 0,1:01:31.63,1:01:32.94,EN,,0,0,0,,And you don't need the environment where\nDialogue: 0,1:01:33.04,1:01:34.64,EN,,0,0,0,,those arguments would be evaluated.\nDialogue: 0,1:01:36.69,1:01:40.89,EN,,0,0,0,,So the basic reason that this interpreter is being so smart\nDialogue: 0,1:01:40.89,1:01:42.88,EN,,0,0,0,,is that it's not being smart at all, it's being stupid.\nDialogue: 0,1:01:43.05,1:01:45.74,EN,,0,0,0,,It's just saying I'm only going to save what I really need.\nDialogue: 0,1:01:48.70,1:01:51.00,EN,,0,0,0,,Well, let me show you here.\nDialogue: 0,1:01:53.07,1:01:57.20,EN,,0,0,0,,Here's the actual thing that's making a tail recursive.\nDialogue: 0,1:01:58.31,1:02:00.20,EN,,0,0,0,,Remember, it's the restore of continue.\nDialogue: 0,1:02:00.22,1:02:06.94,EN,,0,0,0,,It's saying when I go off to evaluate the procedure body,\nDialogue: 0,1:02:08.96,1:02:11.00,EN,,0,0,0,,I should tell eval to come back to\nDialogue: 0,1:02:11.25,1:02:12.54,EN,,0,0,0,,the place where that original\nDialogue: 0,1:02:12.54,1:02:14.25,EN,,0,0,0,,evaluation was supposed to come back to.\nDialogue: 0,1:02:15.17,1:02:15.95,EN,,0,0,0,,So, in some sense,\nDialogue: 0,1:02:16.17,1:02:18.84,EN,,0,0,0,,you want to say what's the actual line that makes tail recursive\nDialogue: 0,1:02:18.89,1:02:19.44,EN,,0,0,0,,It's that one.\nDialogue: 0,1:02:19.92,1:02:21.53,EN,,0,0,0,,If I wanted to build a non-\nDialogue: 0,1:02:21.77,1:02:24.80,EN,,0,0,0,,tail recursive evaluator, for some strange reason,\nDialogue: 0,1:02:25.69,1:02:26.86,EN,,0,0,0,,all I would need to do\nDialogue: 0,1:02:27.12,1:02:29.29,EN,,0,0,0,,is, instead of restoring continue at this point,\nDialogue: 0,1:02:30.06,1:02:31.66,EN,,0,0,0,,I'd set up a label down here\nDialogue: 0,1:02:32.75,1:02:36.25,EN,,0,0,0,,called, \"Where to come back after you've finished applying the procedure.\"\nDialogue: 0,1:02:37.64,1:02:39.71,EN,,0,0,0,,Instead, I'd set continue to that.\nDialogue: 0,1:02:39.92,1:02:41.21,EN,,0,0,0,,I'd go to eval-dispatch,\nDialogue: 0,1:02:41.40,1:02:43.21,EN,,0,0,0,,and then eval-dispatch would come back here.\nDialogue: 0,1:02:43.79,1:02:44.30,EN,,0,0,0,,At that point,\nDialogue: 0,1:02:44.32,1:02:45.28,EN,,0,0,0,,I would restore continue\nDialogue: 0,1:02:45.29,1:02:46.52,EN,,0,0,0,,and go to the original one.\nDialogue: 0,1:02:47.92,1:02:51.00,EN,,0,0,0,,So here, the only consequence of that\nDialogue: 0,1:02:51.15,1:02:52.68,EN,,0,0,0,,would be to make it non-tail recursive.\nDialogue: 0,1:02:52.84,1:02:54.62,EN,,0,0,0,,It would give you exactly the same answers,\nDialogue: 0,1:02:54.72,1:02:57.02,EN,,0,0,0,,except if you did that iterative factorial\nDialogue: 0,1:02:57.05,1:02:58.36,EN,,0,0,0,,and all those iterative procedures,\nDialogue: 0,1:02:58.60,1:02:59.80,EN,,0,0,0,,it would execute recursively.\nDialogue: 0,1:03:03.04,1:03:05.40,EN,,0,0,0,,Well, I lied to you a little bit, but just a little bit,\nDialogue: 0,1:03:05.76,1:03:06.99,EN,,0,0,0,,because I showed you a slightly\nDialogue: 0,1:03:07.02,1:03:08.33,EN,,0,0,0,,over-simplified evaluator\nDialogue: 0,1:03:08.72,1:03:10.38,EN,,0,0,0,,where it assumes that each procedure --\nDialogue: 0,1:03:11.36,1:03:13.66,EN,,0,0,0,,each procedure body has only one expression.\nDialogue: 0,1:03:13.89,1:03:14.54,EN,,0,0,0,,Remember, in general,\nDialogue: 0,1:03:14.56,1:03:16.57,EN,,0,0,0,,a procedure has a sequence of expressions in it.\nDialogue: 0,1:03:17.87,1:03:20.49,EN,,0,0,0,,So there's nothing really conceptually new.\nDialogue: 0,1:03:20.49,1:03:22.28,EN,,0,0,0,,Let me just show you the actual evaluator\nDialogue: 0,1:03:22.89,1:03:24.73,EN,,0,0,0,,that handles sequences of expressions.\nDialogue: 0,1:03:28.47,1:03:29.74,EN,,0,0,0,,This is compound-apply now,\nDialogue: 0,1:03:29.74,1:03:31.31,EN,,0,0,0,,and the only difference from the old one\nDialogue: 0,1:03:32.07,1:03:34.33,EN,,0,0,0,,is that, instead of going off to eval directly,\nDialogue: 0,1:03:35.98,1:03:38.03,EN,,0,0,0,,it takes the whole body of the procedure,\nDialogue: 0,1:03:38.03,1:03:40.15,EN,,0,0,0,,which, in this case, is a sequence of expressions,\nDialogue: 0,1:03:40.28,1:03:41.71,EN,,0,0,0,,and goes off to eval-sequence.\nDialogue: 0,1:03:42.60,1:03:45.32,EN,,0,0,0,,And eval-sequence is a little loop\nDialogue: 0,1:03:46.83,1:03:49.98,EN,,0,0,0,,that, basically, does these evaluations one at a time.\nDialogue: 0,1:03:52.63,1:03:53.85,EN,,0,0,0,,So it does an evaluation.\nDialogue: 0,1:03:53.90,1:03:54.94,EN,,0,0,0,,Says oh, when I come back,\nDialogue: 0,1:03:54.97,1:03:56.86,EN,,0,0,0,,I'd better come back here to do the next one.\nDialogue: 0,1:03:58.44,1:03:59.29,EN,,0,0,0,,And, when I'm all done,\nDialogue: 0,1:03:59.29,1:04:01.02,EN,,0,0,0,,when I want to get the last expression,\nDialogue: 0,1:04:01.31,1:04:03.28,EN,,0,0,0,,I just restore my continue\nDialogue: 0,1:04:03.92,1:04:05.28,EN,,0,0,0,,and go off to eval-dispatch.\nDialogue: 0,1:04:06.41,1:04:08.20,EN,,0,0,0,,And, again, if you wanted for some reason\nDialogue: 0,1:04:08.20,1:04:10.35,EN,,0,0,0,,to break tail recursion in this evaluator,\nDialogue: 0,1:04:10.64,1:04:13.71,EN,,0,0,0,,all you need to do is not handle the last expression, especially.\nDialogue: 0,1:04:14.90,1:04:17.34,EN,,0,0,0,,Just say, after you've done the last expression,\nDialogue: 0,1:04:17.36,1:04:18.65,EN,,0,0,0,,come back to some other place\nDialogue: 0,1:04:19.15,1:04:20.68,EN,,0,0,0,,after which you restore continue.\nDialogue: 0,1:04:21.90,1:04:23.26,EN,,0,0,0,,And, for some reason,\nDialogue: 0,1:04:23.26,1:04:25.74,EN,,0,0,0,,a lot of LISP evaluators tended to work that way.\nDialogue: 0,1:04:26.55,1:04:28.44,EN,,0,0,0,,And the only consequence of that is that\nDialogue: 0,1:04:28.86,1:04:30.72,EN,,0,0,0,,iterative procedures built up stack.\nDialogue: 0,1:04:31.88,1:04:33.61,EN,,0,0,0,,And it's not clear why that happened.\nDialogue: 0,1:04:35.92,1:04:37.98,EN,,0,0,0,,All right. Well, let me just sort of summarize,\nDialogue: 0,1:04:38.09,1:04:39.60,EN,,0,0,0,,since this is a lot of details\nDialogue: 0,1:04:39.98,1:04:41.04,EN,,0,0,0,,in a big program.\nDialogue: 0,1:04:41.12,1:04:42.25,EN,,0,0,0,,But the main point is that\nDialogue: 0,1:04:43.04,1:04:43.87,EN,,0,0,0,,it's no different,\nDialogue: 0,1:04:44.04,1:04:46.08,EN,,0,0,0,,conceptually, from translating any other program.\nDialogue: 0,1:04:47.06,1:04:48.06,EN,,0,0,0,,And the main idea is that\nDialogue: 0,1:04:48.06,1:04:50.28,EN,,0,0,0,,we have this universal evaluator program,\nDialogue: 0,1:04:50.33,1:04:51.71,EN,,0,0,0,,the meta-circular evaluator.\nDialogue: 0,1:04:51.87,1:04:53.07,EN,,0,0,0,,If we translate that into LISP,\nDialogue: 0,1:04:53.10,1:04:53.95,EN,,0,0,0,,then we have all of LISP.\nDialogue: 0,1:04:54.33,1:04:55.15,EN,,0,0,0,,And that's all we did.\nDialogue: 0,1:04:57.98,1:04:59.68,EN,,0,0,0,,The second point is that the magic's gone away.\nDialogue: 0,1:04:59.68,1:05:01.97,EN,,0,0,0,,There should be no more magic in this whole system, right?\nDialogue: 0,1:05:01.97,1:05:07.79,EN,,0,0,0,,In principle, it should all be very clear\nDialogue: 0,1:05:07.82,1:05:10.08,EN,,0,0,0,,except, maybe, for how list structured memory works,\nDialogue: 0,1:05:10.80,1:05:11.80,EN,,0,0,0,,and we'll see that later.\nDialogue: 0,1:05:12.64,1:05:14.20,EN,,0,0,0,,But that's not very hard.\nDialogue: 0,1:05:15.45,1:05:16.35,EN,,0,0,0,,The third point is that\nDialogue: 0,1:05:16.35,1:05:17.52,EN,,0,0,0,,all this tail recursion\nDialogue: 0,1:05:18.24,1:05:21.96,EN,,0,0,0,,came from the discipline of eval being very careful\nDialogue: 0,1:05:22.55,1:05:24.51,EN,,0,0,0,,to save only what it needs next time.\nDialogue: 0,1:05:25.87,1:05:27.72,EN,,0,0,0,,It's not some arbitrary thing\nDialogue: 0,1:05:27.76,1:05:29.86,EN,,0,0,0,,where we're saying well, whenever we call a sub-routine,\nDialogue: 0,1:05:29.86,1:05:32.16,EN,,0,0,0,,we'll save all the registers in the world and come back?\nDialogue: 0,1:05:33.94,1:05:36.49,EN,,0,0,0,,See, sometimes it pays to really worry about efficiency.\nDialogue: 0,1:05:37.15,1:05:39.96,EN,,0,0,0,,And, when you're down in the guts of your evaluator machine,\nDialogue: 0,1:05:40.45,1:05:42.56,EN,,0,0,0,,it really pays to think about things like that\nDialogue: 0,1:05:42.56,1:05:43.96,EN,,0,0,0,,because it makes big consequences.\nDialogue: 0,1:05:45.23,1:05:47.69,EN,,0,0,0,,Well, I hope what this has done\nDialogue: 0,1:05:47.90,1:05:52.30,EN,,0,0,0,,is really made the evaluator seem concrete.\nDialogue: 0,1:05:52.56,1:05:53.90,EN,,0,0,0,,I hope you really believe\nDialogue: 0,1:05:54.32,1:05:56.27,EN,,0,0,0,,that somebody could hold a LISP\nDialogue: 0,1:05:56.84,1:05:58.56,EN,,0,0,0,,LISP evaluator in the palm of their hand.\nDialogue: 0,1:05:59.07,1:06:00.49,EN,,0,0,0,,Maybe to help you believe that, here's a\nDialogue: 0,1:06:00.80,1:06:01.96,EN,,0,0,0,,here's a LISP evaluator\nDialogue: 0,1:06:02.54,1:06:04.06,EN,,0,0,0,,that I'm holding the palm of my hand.\nDialogue: 0,1:06:06.16,1:06:10.56,EN,,0,0,0,,And this is a chip which is actually\nDialogue: 0,1:06:10.89,1:06:13.70,EN,,0,0,0,,quite a bit more complicated than the evaluator I showed you.\nDialogue: 0,1:06:16.86,1:06:19.20,EN,,0,0,0,,Uh.. maybe, here's a better picture of it.\nDialogue: 0,1:06:22.07,1:06:22.57,EN,,0,0,0,,What there is,\nDialogue: 0,1:06:22.60,1:06:24.38,EN,,0,0,0,,is you can see the same overall structure.\nDialogue: 0,1:06:24.73,1:06:25.93,EN,,0,0,0,,This is a register array.\nDialogue: 0,1:06:26.80,1:06:27.71,EN,,0,0,0,,These are the data paths.\nDialogue: 0,1:06:27.72,1:06:29.07,EN,,0,0,0,,Here's a finite state controller.\nDialogue: 0,1:06:29.80,1:06:31.04,EN,,0,0,0,,And again, finite state,\nDialogue: 0,1:06:31.96,1:06:32.80,EN,,0,0,0,,that's all there is.\nDialogue: 0,1:06:32.81,1:06:34.16,EN,,0,0,0,,And somewhere there's external memory\nDialogue: 0,1:06:34.16,1:06:35.23,EN,,0,0,0,,that'll worry about things.\nDialogue: 0,1:06:35.75,1:06:37.63,EN,,0,0,0,,And this particular one is very complicated\nDialogue: 0,1:06:37.64,1:06:39.16,EN,,0,0,0,,because it's trying to run LISP fast.\nDialogue: 0,1:06:39.66,1:06:42.97,EN,,0,0,0,,And it has some very, very fast parallel operations in there\nDialogue: 0,1:06:43.07,1:06:46.32,EN,,0,0,0,,like, if you want to index into an array,\nDialogue: 0,1:06:46.70,1:06:50.40,EN,,0,0,0,,simultaneously check that the index is an integer,\nDialogue: 0,1:06:50.43,1:06:52.86,EN,,0,0,0,,check that it doesn't exceed the array bands,\nDialogue: 0,1:06:53.04,1:06:55.02,EN,,0,0,0,,and go off and do the memory access,\nDialogue: 0,1:06:55.05,1:06:56.70,EN,,0,0,0,,and do all those things simultaneously.\nDialogue: 0,1:06:57.12,1:06:58.40,EN,,0,0,0,,And then, later, if they're all OK,\nDialogue: 0,1:06:58.44,1:06:59.96,EN,,0,0,0,,actually get the value there.\nDialogue: 0,1:07:00.42,1:07:02.46,EN,,0,0,0,,So there are a lot of complicated operations\nDialogue: 0,1:07:02.48,1:07:04.65,EN,,0,0,0,,in these data paths for making LISP run in parallel.\nDialogue: 0,1:07:05.26,1:07:08.41,EN,,0,0,0,,It's a completely non-risk\nDialogue: 0,1:07:08.76,1:07:10.36,EN,,0,0,0,,philosophy of evaluating LISP.\nDialogue: 0,1:07:10.64,1:07:13.20,EN,,0,0,0,,And then, this microcode is pretty complicated.\nDialogue: 0,1:07:13.45,1:07:17.56,EN,,0,0,0,,Let's see, there's what?\nDialogue: 0,1:07:17.60,1:07:21.10,EN,,0,0,0,,There's about 389 instructions of\nDialogue: 0,1:07:21.68,1:07:23.85,EN,,0,0,0,,of 220-bit microcode sitting here\nDialogue: 0,1:07:24.07,1:07:27.94,EN,,0,0,0,,because these are very complicated data paths.\nDialogue: 0,1:07:27.94,1:07:32.25,EN,,0,0,0,,And the whole thing has about 89,000 transistors, OK?\nDialogue: 0,1:07:33.56,1:07:36.86,EN,,0,0,0,,OK. Well, I hope that that takes away a lot of the mystery.\nDialogue: 0,1:07:37.97,1:07:39.24,EN,,0,0,0,,Maybe somebody wants to look at this.\nDialogue: 0,1:07:46.14,1:07:46.89,EN,,0,0,0,,OK. Let's stop.\nDialogue: 0,1:07:56.46,1:07:56.75,EN,,0,0,0,,Questions?\nDialogue: 0,1:07:59.00,1:08:00.42,EN,,0,0,0,,AUDIENCE: OK, now, it sounds like what you're saying is that,\nDialogue: 0,1:08:00.42,1:08:03.48,EN,,0,0,0,,with the restore continue put in the proper place,\nDialogue: 0,1:08:03.58,1:08:09.42,EN,,0,0,0,,that procedures that would invoke a recursive process\nDialogue: 0,1:08:09.42,1:08:11.95,EN,,0,0,0,,now invoke an iterative process\nDialogue: 0,1:08:12.67,1:08:15.36,EN,,0,0,0,,just by the way that the eval-sequence source?\nDialogue: 0,1:08:15.60,1:08:17.54,EN,,0,0,0,,PROFESSOR: I think the way I'd prefer to put it is that,\nDialogue: 0,1:08:17.54,1:08:19.82,EN,,0,0,0,,with restore continue put in the wrong place,\nDialogue: 0,1:08:20.55,1:08:25.48,EN,,0,0,0,,you can cause any syntactically-looking recursive procedure,\nDialogue: 0,1:08:25.52,1:08:27.28,EN,,0,0,0,,in fact, to build up stack as it runs.\nDialogue: 0,1:08:28.64,1:08:30.52,EN,,0,0,0,,But there's no reason for that,\nDialogue: 0,1:08:33.15,1:08:35.12,EN,,0,0,0,,so you might want to play around with it.\nDialogue: 0,1:08:35.15,1:08:38.09,EN,,0,0,0,,You can just switch around two or three instructions\nDialogue: 0,1:08:38.18,1:08:40.78,EN,,0,0,0,,in the way compound-apply comes back,\nDialogue: 0,1:08:41.31,1:08:43.26,EN,,0,0,0,,and you'll get something which isn't tail recursive.\nDialogue: 0,1:08:45.06,1:08:46.14,EN,,0,0,0,,But the thing I wanted to emphasize\nDialogue: 0,1:08:46.16,1:08:47.40,EN,,0,0,0,,is there's no magic. there's no\nDialogue: 0,1:08:47.67,1:08:48.57,EN,,0,0,0,,It's not as if\nDialogue: 0,1:08:49.31,1:08:52.17,EN,,0,0,0,,there's some very clever pre-processing program\nDialogue: 0,1:08:52.65,1:08:55.45,EN,,0,0,0,,that's looking at this procedure, factorial iter,\nDialogue: 0,1:08:55.47,1:08:56.73,EN,,0,0,0,,and say oh, gee, um\nDialogue: 0,1:08:57.42,1:08:58.86,EN,,0,0,0,,I really notice that\nDialogue: 0,1:08:58.88,1:09:01.13,EN,,0,0,0,,I don't have to push stack in order to do this.\nDialogue: 0,1:09:01.13,1:09:02.88,EN,,0,0,0,,Some people think that that's what's going on.\nDialogue: 0,1:09:03.76,1:09:05.38,EN,,0,0,0,,It's something much, much more dumb than that,\nDialogue: 0,1:09:05.38,1:09:07.50,EN,,0,0,0,,it's this one place you're putting the restore instruction.\nDialogue: 0,1:09:08.56,1:09:09.79,EN,,0,0,0,,It's just automatic.\nDialogue: 0,1:09:14.72,1:09:17.55,EN,,0,0,0,,AUDIENCE: But that's not affecting the time complexity is it?\nDialogue: 0,1:09:17.58,1:09:17.87,EN,,0,0,0,,PROFESSOR: No.\nDialogue: 0,1:09:18.60,1:09:21.77,EN,,0,0,0,,AUDIENCE: It's just that it's handling it recursively\nDialogue: 0,1:09:21.80,1:09:23.02,EN,,0,0,0,,instead of iteratively.\nDialogue: 0,1:09:23.02,1:09:27.34,EN,,0,0,0,,But, in terms of the order of time it takes to finish the operation,\nDialogue: 0,1:09:27.37,1:09:29.22,EN,,0,0,0,,it's the same one way or the other, right?\nDialogue: 0,1:09:29.47,1:09:29.76,EN,,0,0,0,,PROFESSOR: Yes.\nDialogue: 0,1:09:29.79,1:09:32.68,EN,,0,0,0,,Tail recursion is not going to change the time complexity of anything\nDialogue: 0,1:09:32.72,1:09:33.29,EN,,0,0,0,,because, in some sense,\nDialogue: 0,1:09:33.34,1:09:35.15,EN,,0,0,0,,it's the same algorithm that's going on.\nDialogue: 0,1:09:36.02,1:09:39.37,EN,,0,0,0,,What it's doing is really making this thing run as an iteration.\nDialogue: 0,1:09:41.00,1:09:42.64,EN,,0,0,0,,Right? Not going to run out of memory\nDialogue: 0,1:09:42.68,1:09:44.22,EN,,0,0,0,,you know counting up to a giant number\nDialogue: 0,1:09:44.75,1:09:46.40,EN,,0,0,0,,simply because the stack would get pushed.\nDialogue: 0,1:09:48.35,1:09:50.24,EN,,0,0,0,,See, the thing you really have to believe is that,\nDialogue: 0,1:09:50.56,1:09:51.13,EN,,0,0,0,,when we write--\nDialogue: 0,1:09:51.64,1:09:53.78,EN,,0,0,0,,see, we've been writing all these things called iterations,\nDialogue: 0,1:09:53.93,1:09:57.99,EN,,0,0,0,,infinite loops, define loop to be called loop.\nDialogue: 0,1:10:00.32,1:10:03.36,EN,,0,0,0,,That's is as much an iteration\nDialogue: 0,1:10:03.65,1:10:05.66,EN,,0,0,0,,you know as if we wrote do forever loop.\nDialogue: 0,1:10:07.63,1:10:09.28,EN,,0,0,0,,It's just syntactic sugar as the difference.\nDialogue: 0,1:10:09.28,1:10:11.32,EN,,0,0,0,,These things are real, honest to god, iterations?\nDialogue: 0,1:10:14.73,1:10:16.08,EN,,0,0,0,,They don't change the time complexity,\nDialogue: 0,1:10:16.11,1:10:18.53,EN,,0,0,0,,but they turn them into real iterations.\nDialogue: 0,1:10:21.68,1:10:23.80,EN,,0,0,0,,All right, thank you.\n"
  },
  {
    "path": "Preface/pre1.txt",
    "content": "心智的活动，除了尽力产生各种简单的认识之外，主要表现在如下三个方面：1）将若干简单认识组合为一个复合认识，由此产生出各种复杂的认识。2）将两个认识放在一起对照，不管它们如何简单或者复杂，在这样做时并不将它们合而为一。由此得到有关它们的相互关系的认识。3）将有关认识与那些在实际中和它们同在的所有其他认识隔离开，这就是抽象，所有具有普遍性的认识都是这样得到的。\nJohn Locke, An Essay Concerning Human Understanding\n（有关人类理解的随笔，1690）\n\n\n\nThe acts of the mind, wherein it exerts its power over simple ideas, are chiefly these three: 1. Combining several simple ideas into one compound one, and thus all complex ideas are made. 2. The second is bringing two ideas, whether simple or complex, together, and setting them by one another so as to take a view of them at once, without uniting them into one, by which it gets all its ideas of relations. 3. The third is separating them from all other ideas that accompany them in their real existence: this is called abstraction, and thus all its general ideas are made.\nJohn Locke, An Essay Concerning Human Understanding\n(1690)"
  },
  {
    "path": "Preface/pre2.txt",
    "content": "现在到了数学抽象中最关键的一步：让我们忘记这些符号所表示的对象。……（数学家）不应在这里停步，有许多操作可以应用与这些符号，而根本不必考虑它们到底代表着什么东西。\nHermann Weyl, The Mathematical Way of Thinking\n(思维的数学方式)\n\n\n\nWe now come to the decisive step of mathematical abstraction: we forget about what the symbols stand for. ...[The mathematician] need not be idle; there are many operations which he may carry out with these symbols, without ever having to look at the things they stand for.\nHermann Weyl, The Mathematical Way of Thinking\n"
  },
  {
    "path": "Preface/pre3.txt",
    "content": "即使在变化中，它也丝毫未变。\n——赫拉克立特（Heraclitus）\n\n变得越多，它就越是原来的样子。\n——阿尔芬斯·卡尔（Alphonse Karr）\n\n\n\n(Even while it changes, it stands still.)\nHeraclitus\n\nPlus ça change, plus c'est la même chose.\nAlphonse Karr"
  },
  {
    "path": "Preface/pre4.txt",
    "content": "用普通的话来说，这个咒语就是——阿巴拉卡达巴拉，芝麻开门，而且还有另外的东西——在一个故事里的咒语在另一故事里就不灵了。真正的魔力在于知道哪个咒语有用，在什么时候，用于做什么，其诀窍就在于学会有关的诀窍。\n而这些咒语也是用我们的字母表里的字母拼出来的，这个字母表中不过是几十个可以用笔画出来的弯弯曲线。这就是最关键的！而那些珍宝也是如此，如果我们能将它们拿到手中的话！这就像是说，就像通向珍宝的钥匙就是珍宝！\n——John Barth, Chimera（奇想）\n\n\n\n... It's in words that the magic is -- Abracadabra, Open Sesame, and the rest -- but the magic words in one story aren't magical in the next. The real magic is to understand which words work, and when, and for what; the trick is to learn the trick.\n... And those words are made from the letters of our alphabet: a couple-dozen squiggles we can draw with the pen. This is the key! And the treasure, too, if we can only get our hands on it! It's as if -- as if the key to the treasure is the treasure!\nJohn Barth, Chimera"
  },
  {
    "path": "Preface/pre5.txt",
    "content": "我的目的是想说明，这一天空机器并不是一种天赐造物或者生命体，它只不过是钟表一类的机械装置（而那些相信钟表有灵魂的人却将这一工作说成是其创造者的荣耀），在很大程度上，这里多种多样的运动都是由最简单的物质力量产生的，就像钟表里所有活动都是由一个发条产生的一样。\n——约翰尼斯·开普勒（给Herwart von Hohenburg的信，1605）\n\n\n\nMy aim is to show that the heavenly machine is not a kind of divine, live being, but a kind of clockwork (and he who believes that a clock has soul attributes the maker's glory to the work), insofar as nearly all the manifold motions are caused by a most simple and material force, just as all motions of the clock are caused by a single weight.\nJohannes Kepler (letter to Herwart von Hohenburg, 1605)"
  },
  {
    "path": "README.md",
    "content": "# 《计算机程序的结构和解释》公开课 翻译项目\n\n<img height=\"20px\" src=\"https://user-images.githubusercontent.com/895809/47278305-6d793380-d5fa-11e8-89f2-7c8862027997.png\" alt=\"MIT OCW\"> [MIT OpenCourseWare](https://ocw.mit.edu/index.htm)　　　　　　<img height=\"20px\" src=\"https://avatars2.githubusercontent.com/u/36149682?s=200&v=4\" alt=\"HIT IBMTC\"> [哈尔滨工业大学 IBM技术中心](https://github.com/HIT-IBMTC)　　　　　　<img height=\"20px\" src=\"https://user-images.githubusercontent.com/895809/47278313-7cf87c80-d5fa-11e8-9ca8-0f5f19c1d31e.jpg\" alt=\"HIT PT\"> [哈尔滨工业大学 清影PT](https://hitpt.org/index.php)\n\n<p align=\"center\">\n  <img src=\"http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/wizard.jpg\" alt=\"SICP\"/>\n</p>\n\n《计算机程序的构造和解释》系列公开课，视频是两位作者（Harold Abelson、Gerald Jay Sussman）在1986年7月给**Hewlett-Packard**公司员工培训时的录像。你可以在[这里](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/)获得这门课程的视频。\n\n这门课程只提供了英文字幕，本项目旨在将这些英文字幕翻译为中文，方便广大的`Scheme/Lisp`学习者。\n\n## 教辅资料\n\n这里收集了一些有用的学习资料，包括SICP原书、Scheme新手教程、教学环境搭建、相关拓展习题等资料。\n\n| 教学辅导 | 环境配置 | 深入阅读 |\n| ------- | ------ | ------- |\n| [SICP原书全文·英文](https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html) |[MIT Scheme基本使用](http://www.math.pku.edu.cn/teachers/qiuzy/progtech/scheme/mit_scheme.htm)|[程序设计语言理论资料汇编](https://steshaw.org/plt/) |\n| [SICP原书PDF版·英文](https://github.com/sarabander/sicp-pdf) | [PLT Scheme的基本使用](http://www.math.pku.edu.cn/teachers/qiuzy/progtech/scheme/plt_scheme.htm) | [程序设计语言研究资料](http://www.cs.cmu.edu/afs/cs.cmu.edu/user/mleone/web/language-research.html) |\n| [Scheme入门教程·中文](https://github.com/DeathKing/yast-cn) | [DrRacket 的安装与配置](https://zhuanlan.zhihu.com/p/37056659) | [程序设计语言与逻辑研究领域经典论文](http://www.cs.cmu.edu/~crary/819-f09/) |\n| [MIT 6.945/6.905 课程作业](http://groups.csail.mit.edu/mac/users/gjs/6.945/assignments.html) | [Racket 常见问题](https://syntacticlosure.github.io/) | [Oleg's FTP](http://okmij.org/ftp/) |\n\nSICP的习题解答可参考 SchemeWiki 的 [SICP Solutions](http://community.schemewiki.org/?SICP-Solutions) 页面。如果您在学习过程中遇到任何疑问，欢迎使用 [Issues](https://github.com/DeathKing/Learning-SICP/issues) 功能提问。\n\n## 视频地址\n\n<table>\n  <tr>\n    <th  colspan=\"5\"><a href=\"https://learningsicp.github.io/\">🏠 主页</a></th>\n  </tr>\n  <tr>\n    <td>🎥 播放列表</td>\n    <td><a href=\"https://v.youku.com/v_show/id_XNTEzMDAyMTU2.html?f=18958522\">优酷</a></td>\n    <td><a href=\"https://www.youtube.com/playlist?list=PLkEwH_Z2WOlppy8oUfrGwFVlOuKyo3RO_\">YouTube</a></td>\n    <td><a href=\"https://www.bilibili.com/video/av8515129/\">BiliBili</a></td>\n    <td><a href=\"https://www.acfun.cn/v/ac10517890\">AcFun</a></td>\n  </tr>\n  <tr>\n    <td >📂 网盘</td>\n    <td colspan=\"2\"><a href=\"https://pan.baidu.com/s/1o78bsYA\">百度网盘</a></td>\n    <td colspan=\"2\"><a href=\"https://drive.google.com/drive/folders/12yryTD9HPpa5zjIpTmYawl6-8VrISxIE?usp=sharing\">Google Drive</a></td>\n  </tr>\n</table>\n\n> **注意**  \n> * 由于 MKV 格式的视频文件需要额外安装字幕，我们不再提供 MKV 格式的视频；\n> * 中国大陆以外的用户，可尝试通过Google Drive下载以获得更高的下载速度。\n\n| 编号 | 标题 | 下载地址 | 译者 |\n| ---- | ---- |:-----------------------:| ---- |\n| Lec1a | 《Lisp概览》 | [ [优酷] ](https://v.youku.com/v_show/id_XNTEzMDAyMTU2.html) [ [YouTube] ](https://youtu.be/IcZSFewqr9k) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=1) [ [MP4] ](https://pan.baidu.com/s/109WuY4ONSZddFXyE2hQGwg) | [DeathKing](https://github.com/DeathKing) |\n| Lec1b | 《计算过程》 | [ [优酷] ](https://v.youku.com/v_show/id_XNTMxODY1NTg4.html) [ [YouTube] ](https://youtu.be/WuK9NmA3aq0) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=2) [ [MP4] ](https://pan.baidu.com/s/1C3muRwhMdK8yioHWw5P-1Q) | [ChingfanTsou](https://github.com/ChingfanTsou) |\n| Lec2a | 《高阶过程》 | [ [优酷] ](https://v.youku.com/v_show/id_XNzAzNjI1NjU2.html) [ [YouTube] ](https://youtu.be/mrgcGvOI1bs) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=3) [ [MP4] ](https://pan.baidu.com/s/1MHiHVHfwq6x8rylBVDGV0A) | [endyul](https://github.com/endyul) |\n| Lec2b | 《复合数据》 | [ [优酷] ](https://v.youku.com/v_show/id_XNzAzNjg4Mjk2.html) [ [YouTube] ](https://youtu.be/ufTdeiz9dMw) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=4) [ [MP4] ](https://pan.baidu.com/s/1DfX7DJ_pMd7AtMlJwqyoRg) | [DeathKing](https://github.com/DeathKing) |\n| Lec3a | 《Henderson-Escher的例子》 | [ [优酷] ](https://v.youku.com/v_show/id_XODk4NjUwODMy.html) [ [YouTube] ](https://youtu.be/YCR03O5EUdI) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=5) [ [MP4] ](https://pan.baidu.com/s/1bOJvDO) | [DeathKing](https://github.com/DeathKing), [Michael Savior](https://github.com/mut0u) |\n| Lec3b | 《符号化求导系统：引用》 | [ [优酷] ](https://v.youku.com/v_show/id_XODk4NjUwODA0.html) [ [YouTube] ](https://youtu.be/cgGbiMptQM0) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=6) [ [MP4] ](https://pan.baidu.com/s/1mhS2EV2) | [DeathKing](https://github.com/DeathKing) |\n| Lec4a | 《模式匹配：基于规则的代换》 | [ [优酷] ](https://v.youku.com/v_show/id_XMTM4NTY5NzE3Ng.html) [ [YouTube] ](https://youtu.be/zSxepaPtNQY) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=7) [ [MP4] ](https://pan.baidu.com/s/1U9E33yRr5mIqrdTOjnJeGA) | [DeathKing](https://github.com/DeathKing), [Michael Savior](https://github.com/mut0u) |\n| Lec4b | 《通用运算符》 | [ [优酷] ](https://v.youku.com/v_show/id_XMTQ3NDEwODUyNA==.html) [ [YouTube] ](https://youtu.be/RlfZridRcw0) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=8) [ [MP4] ](https://pan.baidu.com/s/1vAv8Hi46f9ku2y7LHPpzzw) | [rtmagic](https://github.com/rtmagic) |\n| Lec5a | 《赋值，状态和副作用》 | [ [优酷] ](https://v.youku.com/v_show/id_XMTczMjIxNTM2NA==.html) [ [YouTube] ](https://youtu.be/ozss6dvq7ZU) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=9) [ [MP4] ](https://pan.baidu.com/s/1boWiMWB) | [Windfarer](https://github.com/Windfarer) |\n| Lec5b | 《计算对象》 | [ [优酷] ](https://v.youku.com/v_show/id_XMjY0NzE3NzQ2MA==.html) [ [YouTube] ](https://youtu.be/2Iz7agtk614) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=10) [ [MP4] ](https://pan.baidu.com/s/1c1FRLIg) | [DreamAndDead](https://github.com/DreamAndDead) |\n| Lec6a | 《流 I》 | [ [优酷] ](https://v.youku.com/v_show/id_XMjg4NTkwNzU3Ng==.html) [ [YouTube] ](https://youtu.be/z7jvvATswFE) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=11) [ [MP4] ](https://pan.baidu.com/s/1pLlvcLH) | [DreamAndDead](https://github.com/DreamAndDead) |\n| Lec6b | 《流 II》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzAyMjI0MjAzNg==.html) [ [YouTube] ](https://youtu.be/0lQ6fThLhYw) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=12) [ [MP4] ](https://pan.baidu.com/s/1b3kbWq) | [DreamAndDead](https://github.com/DreamAndDead) |\n| Lec7a | 《元循环求值器 I》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzAzODg2ODczNg==.html) [ [YouTube] ](https://youtu.be/RXUqgWJES0w) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=13) [ [MP4] ](https://pan.baidu.com/s/1kV1M0ab) | [DeathKing](https://github.com/DeathKing), [DreamAndDead](https://github.com/DreamAndDead) |\n| Lec7b | 《元循环求值器 II》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzA2NDQ5MjkxMg==.html) [ [YouTube] ](https://youtu.be/HNaAEv8Xjx8) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=14) [ [MP4] ](https://pan.baidu.com/s/1qYBgrIO) | [DeathKing](https://github.com/DeathKing), [DreamAndDead](https://github.com/DreamAndDead) |\n| Lec8a | 《逻辑式程序设计 I》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzIyODg0NTEwNA==.html) [ [YouTube] ](https://youtu.be/VNH95lmCHdE) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=15) [ [MP4] ](https://pan.baidu.com/s/1dFlOqrB) | [DeathKing](https://github.com/DeathKing) |\n| Lec8b | 《逻辑式程序设计 II》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzQ4MDA1OTE3Mg==.html) [ [YouTube] ](https://youtu.be/mcik1gEEyqA) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=16) [ [MP4] ](https://pan.baidu.com/s/1MN5ZDrnnKeE0XeMqAY6x0Q) | [DeathKing](https://github.com/DeathKing) |\n| Lec9a | 《寄存机器》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzU3MzA5Mzg0OA==.html) [ [YouTube] ](https://youtu.be/oR2PwG0xh_g) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=17) [ [MP4] ](https://pan.baidu.com/s/1AFM6__x4oGq3XtI_fa3ZGQ) | [DeathKing](https://github.com/DeathKing) |\n| Lec9b | 《显式控制求值器》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzcxMDAzMTA1Mg==.html) [ [YouTube] ](https://youtu.be/mrRcB4uY75M) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=18) [ [MP4] ](https://pan.baidu.com/s/1bHhuJdEQyE9Fyw06Y6tOZw) | [DeathKing](https://github.com/DeathKing), [rtmagic](https://github.com/rtmagic) |\n| Lec10a | 《编译》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzYyNTcxNDYwOA==.html) [ [YouTube] ](https://youtu.be/vBEkYVrtfBE) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=19) [ [MP4] ](https://pan.baidu.com/s/1IWkeR7gM5jiVFPMVhdZ4fg) | [Windfarer](https://github.com/Windfarer) |\n| Lec10b | 《存储分配与垃圾收集》 | [ [优酷] ](https://v.youku.com/v_show/id_XMzc3NjI4MzQ4NA==.html) [ [YouTube] ](https://youtu.be/HNjPAzmSho8) [ [bilibili] ](https://www.bilibili.com/video/av8515129?p=20) [ [MP4] ](https://pan.baidu.com/s/1LKoXNWFD9lFclgNKeCBxsg) | [Windfarer](https://github.com/Windfarer) |\n\n## 加入我们\n\n+ Learning-SICP 主群：97747648\n+ Learning-SICP 2 群：573877085\n\n（加群请注明理由，否则一概拒绝）\n\n## 声明与致谢\n\n我们由衷感谢 Harold Abelson 及 Gerald Jay Sussman 教授为我们讲授这一门公开课，感谢 [MIT OCW](http://ocw.mit.edu ) 项目允许我们以 Creative Commons 的方式分发本课的中译版本，以下是原课中的许可与声明。\n\n> http://ocw.mit.edu  \n> License: Creative Commons Attribution-Noncommercial-Share Alike.  \n> `Eric Grimson`, `Peter Szolovits`, and `Trevor Darrell`,   \n> 6.001 Structure and Interpretation of Computer Programs, Spring 2005.  \n> (Massachusetts Institute of Technology: MIT OpenCourseWare).  \n"
  },
  {
    "path": "SrtCN/lec10a.eng.srt",
    "content": "﻿1\n00:00:05,580 --> 00:00:20,180\n[MUSIC PLAYING]\n\n2\n00:00:20,180 --> 00:00:36,640\nPROFESSOR: Last time, we took a look at an explicit control evaluator for Lisp, and that bridged the gap between all these high-level languages like Lisp and the query language and all of that stuff, bridged the gap between that and a conventional register machine.\n\n3\n00:00:36,640 --> 00:00:55,340\nAnd in fact, you can think of the explicit control evaluator either as, say, the code for a Lisp interpreter if you wanted to implement it in the assembly language of some conventional register transfer machine, or, if you like, you can think of it as the microcode of some machine that's going to be specially designed to run Lisp.\n\n4\n00:00:55,340 --> 00:01:08,230\nIn either case, what we're doing is we're taking a machine that speaks some low-level language, and we're raising the machine to a high-level language like Lisp by writing an interpreter.\n\n5\n00:01:08,230 --> 00:01:23,910\nSo for instance, here, conceptually, is a special purpose machine for computing factorials.\n\n6\n00:01:23,910 --> 00:01:29,000\nIt takes in five and puts out 120.\n\n7\n00:01:29,000 --> 00:01:42,410\nAnd what this special purpose machine is is actually a Lisp interpreter that's configured itself to run factorials, because you fit into it a description of the factorial machine.\n\n8\n00:01:42,410 --> 00:01:43,610\nSo that's what an interpreter is.\n\n9\n00:01:43,610 --> 00:01:50,120\nIt configures itself to emulate a machine whose description you read in.\n\n10\n00:01:50,120 --> 00:01:52,110\nNow, inside the Lisp interpreter, what's that?\n\n11\n00:01:52,110 --> 00:02:03,410\nWell, that might be your general register language interpreter that configures itself to behave like a Lisp interpreter, because you put in a whole bunch of instructions in register language.\n\n12\n00:02:03,410 --> 00:02:07,070\nThis is the explicit control evaluator.\n\n13\n00:02:07,070 --> 00:02:12,780\nAnd then it also has some sort of library, a library of primitive operators and Lisp operations and all sorts of things like that.\n\n14\n00:02:12,780 --> 00:02:17,350\nThat's the general strategy of interpretation.\n\n15\n00:02:17,350 --> 00:02:25,430\nAnd the point is, what we're doing is we're writing an interpreter to raise the machine to the level of the programs that we want to write.\n\n16\n00:02:25,430 --> 00:02:29,030\nWell, there's another strategy, a different one, which is compilation.\n\n17\n00:02:29,030 --> 00:02:31,090\nCompilation's a little bit different.\n\n18\n00:02:31,090 --> 00:02:47,870\nHere--here we might have produced a special purpose machine for, for computing factorials, starting with some sort of machine that speaks register language, except we're going to do a different strategy.\n\n19\n00:02:47,870 --> 00:02:51,680\nWe take our factorial program.\n\n20\n00:02:51,680 --> 00:02:53,780\nWe use that as the source code into a compiler.\n\n21\n00:02:53,780 --> 00:02:59,926\nWhat the compiler will do is translate that factorial program into some register machine language.\n\n22\n00:02:59,926 --> 00:03:06,760\nAnd this will now be not the explicit control evaluator for Lisp, this will be some register language for computing factorials.\n\n23\n00:03:06,760 --> 00:03:10,460\nSo this is the translation of that.\n\n24\n00:03:10,460 --> 00:03:19,970\nThat will go into some sort of loader which will combine this code with code selected from the library to do things like primitive multiplication.\n\n25\n00:03:19,970 --> 00:03:28,320\nAnd then we'll produce a load module which configures the register language machine to be a special purpose factorial machine.\n\n26\n00:03:28,320 --> 00:03:29,905\nSo that's a, that's a different strategy.\n\n27\n00:03:29,905 --> 00:03:35,360\nIn interpretation, we're raising the machine to the level of our language, like Lisp.\n\n28\n00:03:35,360 --> 00:03:42,040\nIn compilation, we're taking our program and lowering it to the language that's spoken by the machine.\n\n29\n00:03:42,040 --> 00:03:44,280\nWell, how do these two strategies compare?\n\n30\n00:03:44,280 --> 00:03:50,140\nThe compiler can produce code that will execute more efficiently.\n\n31\n00:03:52,490 --> 00:04:10,260\nThe essential reason for that is that if you think about the register operations that are running, the interpreter has to produce register operations which, in principle, are going to be general enough to execute any Lisp procedure.\n\n32\n00:04:10,260 --> 00:04:20,209\nWhereas the compiler only has to worry about producing a special bunch of register operations for, for doing the particular Lisp procedure that you've compiled.\n\n33\n00:04:20,209 --> 00:04:31,160\nOr another way to say that is that the interpreter is a general purpose simulator, that when you read in a Lisp procedure, then those can simulate the program described by that, by that procedure.\n\n34\n00:04:31,160 --> 00:04:40,000\nSo the interpreter is worrying about making a general purpose simulator, whereas the compiler, in effect, is configuring the thing to be the machine that the interpreter would have been simulating.\n\n35\n00:04:40,000 --> 00:04:41,340\nSo the compiler can be faster.\n\n36\n00:04:52,830 --> 00:04:59,340\nOn the other hand, the interpreter is a nicer environment for debugging.\n\n37\n00:04:59,340 --> 00:05:02,960\nAnd the reason for that is that we've got the source code actually there.\n\n38\n00:05:02,960 --> 00:05:03,740\nWe're interpreting it.\n\n39\n00:05:03,740 --> 00:05:06,010\nThat's what we're working with.\n\n40\n00:05:06,010 --> 00:05:07,880\nAnd we also have the library around.\n\n41\n00:05:07,880 --> 00:05:11,140\nSee, the interpreter--the library sitting there is part of the interpreter.\n\n42\n00:05:11,140 --> 00:05:14,830\nThe compiler only pulls out from the library what it needs to run the program.\n\n43\n00:05:14,830 --> 00:05:29,670\nSo if you're in the middle of debugging, and you might like to write a little extra program to examine some run time data structure or to produce some computation that you didn't think of when you wrote the program, the interpreter can do that perfectly well, whereas the compiler can't.\n\n44\n00:05:29,670 --> 00:05:31,850\nSo there are sort of dual, dual advantages.\n\n45\n00:05:31,850 --> 00:05:34,720\nThe compiler will produce code that executes faster.\n\n46\n00:05:34,720 --> 00:05:39,030\nThe interpreter is a better environment for debugging.\n\n47\n00:05:39,030 --> 00:05:46,930\nAnd most Lisp systems end up having both, end up being configured so you have an interpreter that you use when you're developing your code.\n\n48\n00:05:46,930 --> 00:05:49,060\nThen you can speed it up by compiling.\n\n49\n00:05:49,060 --> 00:05:54,810\nAnd very often, you can arrange that compiled code and interpreted code can call each other.\n\n50\n00:05:54,810 --> 00:05:55,700\nWe'll see how to do that.\n\n51\n00:05:55,700 --> 00:05:56,950\nThat's not hard.\n\n52\n00:06:01,040 --> 00:06:14,320\nIn fact, the way we'll--  in the compiler we're going to make, the way we'll arrange for compiled coding and interpreted code to call, to call each other, is that we'll have the compiler use exactly the same register conventions as the interpreter.\n\n53\n00:06:18,680 --> 00:06:25,490\nWell, the idea of a compiler is very much like the idea of an interpreter or evaluator.\n\n54\n00:06:25,490 --> 00:06:27,070\nIt's the same thing.\n\n55\n00:06:27,070 --> 00:06:33,840\nSee, the evaluator walks over the code and performs some register operations.\n\n56\n00:06:33,840 --> 00:06:37,040\nThat's what we did yesterday.\n\n57\n00:06:37,040 --> 00:06:48,890\nWell, the compiler essentially would like to walk over the code and produce the register operations that the evaluator would have done were it evaluating the thing.\n\n58\n00:06:48,890 --> 00:06:58,330\nAnd that gives us a model for how to implement a zeroth-order compiler, a very bad compiler but essentially a compiler.\n\n59\n00:06:58,330 --> 00:07:07,550\nA model for doing that is you just take the evaluator, you run it over the code, but instead of executing the actual operations, you just save them away.\n\n60\n00:07:07,550 --> 00:07:08,820\nAnd that's your compiled code.\n\n61\n00:07:08,820 --> 00:07:10,140\nSo let me give you an example of that.\n\n62\n00:07:15,130 --> 00:07:18,010\nSuppose we're going to compile--suppose we want to compile the expression f of x.\n\n63\n00:07:25,100 --> 00:07:30,170\nSo let's assume that we've got f of x in the x register and something in the environment register.\n\n64\n00:07:30,170 --> 00:07:31,745\nAnd now imagine starting up the evaluator.\n\n65\n00:07:34,560 --> 00:07:38,000\nWell, it looks at the expression and it sees that it's an application.\n\n66\n00:07:38,000 --> 00:07:44,980\nAnd it branches to a place in the evaluator code we saw called ev-application.\n\n67\n00:07:47,230 --> 00:07:48,190\nAnd then it begins.\n\n68\n00:07:48,190 --> 00:07:54,410\nIt stores away the operands and unev, and then it's going to put the operator in exp, and it's going to go recursively evaluate it.\n\n69\n00:07:54,410 --> 00:07:56,385\nThat's the process that we walk through.\n\n70\n00:07:56,385 --> 00:08:00,200\nAnd if you start looking at the code, you start seeing some register operations.\n\n71\n00:08:00,200 --> 00:08:06,770\nYou see assign to unev the operands, assign to exp the operator, save the environment, generate that, and so on.\n\n72\n00:08:10,310 --> 00:08:20,860\nWell, if we look on the overhead here, we can see, we can see those operations starting to be produced.\n\n73\n00:08:20,860 --> 00:08:24,910\nHere's sort of the first real operation that the evaluator would have done.\n\n74\n00:08:24,910 --> 00:08:34,740\nIt pulls the operands out of the exp register and assigns it to unev. And then it assigns something to the expression register, and it saves continue, and it saves env.\n\n75\n00:08:34,740 --> 00:08:42,010\nAnd all I'm doing here is writing down the register assignments that the evaluator would have done in executing that code.\n\n76\n00:08:42,010 --> 00:08:44,280\nAnd can zoom out a little bit.\n\n77\n00:08:44,280 --> 00:08:49,430\nAltogether, there are about 19 operations there.\n\n78\n00:08:49,430 --> 00:08:57,940\nAnd this is the--this will be the piece of code up until the point where the evaluator branches off to apply-dispatch.\n\n79\n00:08:57,940 --> 00:09:01,450\nAnd in fact, in this compiler, we're not going to worry about apply-dispatch at all.\n\n80\n00:09:01,450 --> 00:09:06,160\nWe're going to have everything--we're going to have both interpreted code and compiled code.\n\n81\n00:09:06,160 --> 00:09:10,240\nAlways evaluate procedures, always apply procedures by going to apply-dispatch.\n\n82\n00:09:10,240 --> 00:09:13,970\nThat will easily allow interpreted code and compiled code to call each other.\n\n83\n00:09:18,330 --> 00:09:21,220\nWell, in principle, that's all we need to do.\n\n84\n00:09:21,220 --> 00:09:22,620\nYou just run the evaluator.\n\n85\n00:09:22,620 --> 00:09:24,320\nSo the compiler's a lot like the evaluator.\n\n86\n00:09:24,320 --> 00:09:29,480\nYou run it, except it stashes away these operations instead of actually executing them.\n\n87\n00:09:29,480 --> 00:09:32,680\nWell, that's not, that's not quite true.\n\n88\n00:09:32,680 --> 00:09:36,370\nThere's only one little lie in that.\n\n89\n00:09:36,370 --> 00:09:40,480\nWhat you have to worry about is if you have a, a predicate.\n\n90\n00:09:40,480 --> 00:09:51,400\nIf you have some kind of test you want to do, obviously, at the point when you're compiling it, you don't know which branch of these--of a conditional like this you're going to do.\n\n91\n00:09:51,400 --> 00:09:55,010\nSo you can't say which one the evaluator would have done.\n\n92\n00:09:55,010 --> 00:09:57,190\nSo all you do there is very simple.\n\n93\n00:09:57,190 --> 00:09:58,985\nYou compile both branches.\n\n94\n00:09:58,985 --> 00:10:02,050\nSo you compile a structure that looks like this.\n\n95\n00:10:02,050 --> 00:10:18,140\nThat'll compile into something that says, the code, the code for P. And it puts its results in, say, the val register.\n\n96\n00:10:18,140 --> 00:10:24,770\nSo you walk the interpreter over the predicate and make sure that the result would go into the val register.\n\n97\n00:10:24,770 --> 00:10:38,670\nAnd then you compile an instruction that says, branch if, if val is true, to a place we'll call label one.\n\n98\n00:10:44,950 --> 00:11:04,920\nThen we, we will put the code for B to walk the interpreter--walk the interpreter over B. And then go to put in an instruction that says, go to the next thing, whatever, whatever was supposed to happen after this thing was done.\n\n99\n00:11:04,920 --> 00:11:06,900\nYou put in that instruction.\n\n100\n00:11:06,900 --> 00:11:08,280\nAnd here you put label one.\n\n101\n00:11:11,521 --> 00:11:25,870\nAnd here you put the code for A. And you put go to next thing.\n\n102\n00:11:31,420 --> 00:11:33,090\nSo that's how you treat a conditional.\n\n103\n00:11:33,090 --> 00:11:35,890\nYou generate a little block like that.\n\n104\n00:11:35,890 --> 00:11:42,310\nAnd other than that, this zeroth-order compiler is the same as the evaluator.\n\n105\n00:11:42,310 --> 00:11:46,380\nIt's just stashing away the instructions instead of executing them.\n\n106\n00:11:46,380 --> 00:11:50,120\nThat seems pretty simple, but we've gained something by that.\n\n107\n00:11:50,120 --> 00:11:53,630\nSee, already that's going to be more efficient than the evaluator.\n\n108\n00:11:53,630 --> 00:12:04,740\nBecause, if you watch the evaluator run, it's not only generating the register operations we wrote down, it's also doing things to decide which ones to generate.\n\n109\n00:12:04,740 --> 00:12:16,780\nSo the very first thing it does, say, here for instance, is go do some tests and decide that this is an application, and then branch off to the place that, that handles applications.\n\n110\n00:12:16,780 --> 00:12:25,580\nIn other words, what the evaluator's doing is simultaneously analyzing the code to see what to do, and running these operations.\n\n111\n00:12:25,580 --> 00:12:34,900\nAnd when you-- if you run the evaluator a million times, that analysis phase happens a million times, whereas in the compiler, it's happened once, and then you just have the register operations themselves.\n\n112\n00:12:39,730 --> 00:12:44,550\nOk, that's a, a zeroth-order compiler, but it is a wretched, wretched compiler.\n\n113\n00:12:44,550 --> 00:12:47,200\nIt's really dumb.\n\n114\n00:12:47,200 --> 00:12:52,040\nLet's--let's go back and, and look at this overhead.\n\n115\n00:12:52,040 --> 00:12:56,020\nSo look at look at some of the operations this thing is doing.\n\n116\n00:12:56,020 --> 00:13:03,710\nWe're supposedly looking at the operations and interpreting f of x.\n\n117\n00:13:03,710 --> 00:13:05,220\nNow, look here what it's doing.\n\n118\n00:13:05,220 --> 00:13:13,850\nFor example, here it assigns to exp the operator in fetch of exp.\n\n119\n00:13:13,850 --> 00:13:23,310\nBut see, there's no reason to do that, because this is-- the compiler knows that the operator, fetch of exp, is f right here.\n\n120\n00:13:23,310 --> 00:13:25,850\nSo there's no reason why this instruction should say that.\n\n121\n00:13:25,850 --> 00:13:29,580\nIt should say, we'll assign to exp, f.\n\n122\n00:13:29,580 --> 00:13:32,000\nOr in fact, you don't need exp at all.\n\n123\n00:13:32,000 --> 00:13:33,670\nThere's no reason it should have exp at all.\n\n124\n00:13:33,670 --> 00:13:35,170\nWhat, what did exp get used for?\n\n125\n00:13:35,170 --> 00:13:48,620\nWell, if we come down here, we're going to assign to val, look up the stuff in exp in the environment.\n\n126\n00:13:48,620 --> 00:13:58,850\nSo what we really should do is get rid of the exp register altogether, and just change this instruction to say, assign to val, look up the variable value of the symbol f in the environment.\n\n127\n00:14:01,100 --> 00:14:09,150\nSimilarly, back up here, we don't need unev at all, because we know what the operands of fetch of exp are for this piece of code.\n\n128\n00:14:09,150 --> 00:14:10,630\nIt's the, it's the list x.\n\n129\n00:14:13,270 --> 00:14:19,660\nSo in some sense, you don't want unev and exp at all.\n\n130\n00:14:19,660 --> 00:14:25,230\nSee, what they really are in some sense, those aren't registers of the actual machine that's supposed to run.\n\n131\n00:14:25,230 --> 00:14:30,760\nThose are registers that have to do with arranging the thing that can simulate that machine.\n\n132\n00:14:30,760 --> 00:14:39,510\nSo they're always going to hold expressions which, from the compiler's point of view, are just constants, so can be put right into the code.\n\n133\n00:14:39,510 --> 00:14:44,000\nSo you can forget about all the operations worrying about exp and unev and just use those constants.\n\n134\n00:14:44,000 --> 00:14:50,510\nSimilarly, again, if we go, go back and look here, there are things like assign to continue eval-args.\n\n135\n00:14:53,890 --> 00:14:55,440\nNow, that has nothing to do with anything.\n\n136\n00:14:55,440 --> 00:15:06,920\nThat was just the evaluator keeping track of where it should go next, to evaluate the arguments in some, in some application.\n\n137\n00:15:06,920 --> 00:15:15,220\nBut of course, that's irrelevant to the compiler, because you--  the analysis phase will have already done that.\n\n138\n00:15:15,220 --> 00:15:17,680\nSo this is completely irrelevant.\n\n139\n00:15:17,680 --> 00:15:26,120\nSo a lot of these, these assignments to continue have not to do where the running machine is supposed to continue in keeping track of its state.\n\n140\n00:15:26,120 --> 00:15:30,080\nIt has to, to do with where the evaluator analysis should continue, and those are completely irrelevant.\n\n141\n00:15:30,080 --> 00:15:31,330\nSo we can get rid of them.\n\n142\n00:15:44,330 --> 00:16:08,540\nOk, well, if we, if we simply do that, make those kinds of optimizations, get rid, get rid of worrying about exp and unev, and get rid of these irrelevant register assignments to continue, then we can take this literal code, these sort of 19 instructions that the, that the evaluator would have done, and then replace them.\n\n143\n00:16:08,540 --> 00:16:09,865\nLet's look at the, at the slide.\n\n144\n00:16:13,490 --> 00:16:15,180\nReplace them by--we get rid of about half of them.\n\n145\n00:16:18,370 --> 00:16:25,200\nAnd again, this is just sort of filtering what the evaluator would have done by getting rid of the irrelevant stuff.\n\n146\n00:16:25,200 --> 00:16:35,470\nAnd you see, for instance, here the--where the evaluator said, assign val, look up variable value, fetch of exp, here we have put in the constant f.\n\n147\n00:16:35,470 --> 00:16:37,020\nHere we've put in the constant x.\n\n148\n00:16:39,770 --> 00:16:43,860\nSo there's a, there's a little better compiler.\n\n149\n00:16:43,860 --> 00:16:47,930\nIt's still pretty dumb.\n\n150\n00:16:47,930 --> 00:16:50,560\nIt's still doing a lot of dumb things.\n\n151\n00:16:50,560 --> 00:17:03,430\nAgain, if we go look at the slide again, look at the very beginning here, we see a save the environment, assign something to the val register, and restore the environment.\n\n152\n00:17:03,430 --> 00:17:05,030\nWhere'd that come from?\n\n153\n00:17:05,030 --> 00:17:11,160\nThat came from the evaluator back here saying, oh, I'm in the middle of evaluating an application.\n\n154\n00:17:11,160 --> 00:17:15,940\nSo I'm going to recursively call eval dispatch.\n\n155\n00:17:15,940 --> 00:17:19,849\nSo I'd better save the thing I'm going to need later, which is the environment.\n\n156\n00:17:19,849 --> 00:17:23,520\nThis was the result of recursively calling eval dispatch.\n\n157\n00:17:23,520 --> 00:17:26,540\nIt was evaluating the symbol f in that case.\n\n158\n00:17:26,540 --> 00:17:31,380\nThen it came back from eval dispatch, restored the environment.\n\n159\n00:17:31,380 --> 00:17:38,740\nBut in fact, the actual thing it ended up doing in the evaluation is not going to hurt the environment at all.\n\n160\n00:17:38,740 --> 00:17:42,170\nSo there's no reason to be saving the environment and restoring the environment here.\n\n161\n00:17:46,020 --> 00:17:58,090\nSimilarly, here I'm saving the argument list. That's a piece of the argument evaluation loop, saving the argument list, and here you restore it.\n\n162\n00:17:58,090 --> 00:18:04,090\nBut the actual thing that you ended up doing didn't trash the argument list. So there was no reason to save it.\n\n163\n00:18:08,690 --> 00:18:23,180\nSo another way to say, another way to say that is that the, the evaluator has to be maximally pessimistic, because as far from its point of view it's just going off to evaluate something.\n\n164\n00:18:23,180 --> 00:18:26,200\nSo it better save what it's going to need later.\n\n165\n00:18:26,200 --> 00:18:32,140\nBut once you've done the analysis, the compiler is in a position to say, well, what actually did I need to save?\n\n166\n00:18:32,140 --> 00:18:39,950\nAnd doesn't need to do any-- it doesn't need to be as careful as the evaluator, because it knows what it actually needs.\n\n167\n00:18:39,950 --> 00:18:49,400\nWell, in any case, if we do that and eliminate all those redundant saves and restores, then we can get it down to this.\n\n168\n00:18:49,400 --> 00:19:00,070\nAnd you see there are actually only three instructions that we actually need, down from the initial 11 or so, or the initial 20 or so in the original one.\n\n169\n00:19:00,070 --> 00:19:04,870\nAnd that's just saying, of those register operations, which ones did we actually need?\n\n170\n00:19:09,490 --> 00:19:13,450\nLet me just sort of summarize that in another way, just to show you in a little better picture.\n\n171\n00:19:16,010 --> 00:19:20,530\nHere's a picture of starting-- This is looking at all the saves and restores.\n\n172\n00:19:23,770 --> 00:19:38,160\nSo here's the expression, f of x, and then this traces through, on the bottom here, the various places in the evaluator that were passed when the evaluation happened.\n\n173\n00:19:38,160 --> 00:19:40,250\nAnd then here, here you see arrows.\n\n174\n00:19:40,250 --> 00:19:42,320\nArrow down means register saved.\n\n175\n00:19:42,320 --> 00:19:46,860\nSo the first thing that happened is the environment got saved.\n\n176\n00:19:46,860 --> 00:19:48,305\nAnd over here, the environment got restored.\n\n177\n00:19:52,380 --> 00:19:56,220\nAnd these-- so there are all the pairs of stack operations.\n\n178\n00:19:56,220 --> 00:20:03,320\nNow, if you go ahead and say, well, let's remember that we don't--that unev, for instance, is a completely useless register.\n\n179\n00:20:07,550 --> 00:20:13,020\nAnd if we use the constant structure of the code, well, we don't need, we don't need to save unev. We don't need unev at all.\n\n180\n00:20:16,220 --> 00:20:23,860\nAnd then, depending on how we set up the discipline of the--of calling other things that apply, we may or may not need to save continue.\n\n181\n00:20:27,360 --> 00:20:28,800\nThat's the first step I did.\n\n182\n00:20:28,800 --> 00:20:32,960\nAnd then we can look and see what's actually, what's actually needed.\n\n183\n00:20:32,960 --> 00:20:40,040\nSee, we don't-- didn't really need to save env or cross-evaluating f, because it wouldn't, it wouldn't trash it.\n\n184\n00:20:40,040 --> 00:21:03,320\nSo if we take advantage of that, and see the evaluation of f here, doesn't really need to worry about, about hurting env. And similarly, the evaluation of x here, when the evaluator did that it said, oh, I'd better preserve the function register around that, because I might need it later.\n\n185\n00:21:03,320 --> 00:21:07,140\nAnd I better preserve the argument list.\n\n186\n00:21:07,140 --> 00:21:12,730\nWhereas the compiler is now in a position to know, well, we didn't really need to save-- to do those saves and restores.\n\n187\n00:21:12,730 --> 00:21:19,670\nSo in fact, all of the stack operations done by the evaluator turned out to be unnecessary or overly pessimistic.\n\n188\n00:21:19,670 --> 00:21:21,390\nAnd the compiler is in a position to know that.\n\n189\n00:21:27,470 --> 00:21:29,980\nWell that's the basic idea.\n\n190\n00:21:29,980 --> 00:21:40,460\nWe take the evaluator, we eliminate the things that you don't need, that in some sense have nothing to do with the compiler at all, just the evaluator, and then you see which stack operations are unnecessary.\n\n191\n00:21:40,460 --> 00:21:45,130\nThat's the basic structure of the compiler that's described in the book.\n\n192\n00:21:45,130 --> 00:21:51,280\nLet me just show you how that examples a little bit too simple.\n\n193\n00:21:51,280 --> 00:21:55,765\nTo see how you, how you actually save a lot, let's look at a little bit more complicated expression.\n\n194\n00:21:58,330 --> 00:22:03,542\nF of G of X and 1.\n\n195\n00:22:03,542 --> 00:22:06,410\nAnd I'm not going to go through all the code.\n\n196\n00:22:06,410 --> 00:22:09,830\nThere's a, there's a fair pile of it.\n\n197\n00:22:09,830 --> 00:22:17,270\nI think there are, there are something like 16 pairs of register saves and restores as the evaluator walks through that.\n\n198\n00:22:17,270 --> 00:22:20,680\nHere's a diagram of them.\n\n199\n00:22:20,680 --> 00:22:21,060\nLet's see.\n\n200\n00:22:21,060 --> 00:22:24,210\nYou see what's going on.\n\n201\n00:22:24,210 --> 00:22:26,480\nYou start out by--the evaluator says, oh, I'm about to do an application.\n\n202\n00:22:26,480 --> 00:22:28,010\nI'll preserve the environment.\n\n203\n00:22:28,010 --> 00:22:30,261\nI'll restore it here.\n\n204\n00:22:30,261 --> 00:22:33,900\nThen I'm about to do the first operand.\n\n205\n00:22:36,790 --> 00:22:38,970\nHere it recursively goes to the evaluator.\n\n206\n00:22:38,970 --> 00:22:46,740\nThe evaluator says, oh, this is an application, I'll save the environment, do the operator of that combination, restore it here.\n\n207\n00:22:46,740 --> 00:22:51,720\nThis save--this restore matches that save. And so on.\n\n208\n00:22:51,720 --> 00:22:57,240\nThere's unev here, which turns out to be completely unnecessary, continues getting bumped around here.\n\n209\n00:22:57,240 --> 00:23:05,330\nThe function register is getting, getting saved across the first operands, across the operands.\n\n210\n00:23:05,330 --> 00:23:06,680\nAll sorts of things are going on.\n\n211\n00:23:06,680 --> 00:23:14,320\nBut if you say, well, what of those really were the business of the compiler as opposed to the evaluator, you get rid of a whole bunch.\n\n212\n00:23:14,320 --> 00:23:34,570\nAnd then on top of that, if you say things like, the evaluation of F doesn't hurt the environment register, or simply looking up the symbol X, you don't have to protect the function register against that.\n\n213\n00:23:34,570 --> 00:23:37,530\nSo you come down to just a couple of, a couple of pairs here.\n\n214\n00:23:40,280 --> 00:23:42,160\nAnd still, you can do a little better.\n\n215\n00:23:42,160 --> 00:23:44,962\nLook what's going on here with the environment register.\n\n216\n00:23:44,962 --> 00:23:52,600\nThe environment register comes along and says, oh, here's a combination.\n\n217\n00:23:54,280 --> 00:23:58,580\nThis evaluator, by the way, doesn't know anything about G.\n\n218\n00:23:58,580 --> 00:24:15,540\nSo here it says, so it says, I'd better save the environment register, because evaluating G might be some arbitrary piece of code that would trash it, and I'm going to need it later, after this argument, for doing the second argument.\n\n219\n00:24:15,540 --> 00:24:22,550\nSo that's why this one didn't go away, because the compiler made no assumptions about what G would do.\n\n220\n00:24:22,550 --> 00:24:27,710\nOn the other hand, if you look at what the second argument is, that's just looking up one.\n\n221\n00:24:27,710 --> 00:24:30,810\nThat doesn't need this environment register.\n\n222\n00:24:30,810 --> 00:24:32,070\nSo there's no reason to save it.\n\n223\n00:24:32,070 --> 00:24:35,020\nSo in fact, you can get rid of that one, too.\n\n224\n00:24:35,020 --> 00:24:45,170\nAnd from this whole pile of, of register operations, if you simply do a little bit of reasoning like that, you get down to, I think, just two pairs of saves and restores.\n\n225\n00:24:45,170 --> 00:24:56,650\nAnd those, in fact, could go away further if you, if you knew something about G.\n\n226\n00:24:56,650 --> 00:25:03,310\nSo again, the general idea is that the reason the compiler can be better is that the interpreter doesn't know what it's about to encounter.\n\n227\n00:25:03,310 --> 00:25:07,750\nIt has to be maximally pessimistic in saving things to protect itself.\n\n228\n00:25:07,750 --> 00:25:13,410\nThe compiler only has to deal with what actually had to be saved.\n\n229\n00:25:13,410 --> 00:25:17,920\nAnd there are two reasons that something might not have to be saved.\n\n230\n00:25:17,920 --> 00:25:24,210\nOne is that what you're protecting it against, in fact, didn't trash the register, like it was just a variable look-up.\n\n231\n00:25:24,210 --> 00:25:30,800\nAnd the other one is, that the thing that you were saving it for might turn out not to actually need it.\n\n232\n00:25:30,800 --> 00:25:38,260\nSo those are the two basic pieces of knowledge that the compiler can take advantage of in making the code more efficient.\n\n233\n00:25:44,570 --> 00:25:45,820\nLet's break for questions.\n\n234\n00:25:51,280 --> 00:25:56,350\nAUDIENCE: You kept saying that the uneval register, unev register didn't need to be used at all.\n\n235\n00:25:56,350 --> 00:25:58,590\nDoes that mean that you could just map a six-register machine?\n\n236\n00:25:58,590 --> 00:26:01,860\nOr is that, in this particular example, it didn't need to be used?\n\n237\n00:26:01,860 --> 00:26:07,580\nPROFESSOR: For the compiler, you could generate code for the six-register, five, right?\n\n238\n00:26:07,580 --> 00:26:08,930\nBecause that exp goes away also.\n\n239\n00:26:11,750 --> 00:26:17,380\nAssuming--yeah, you can get rid of both exp and unev, because, see, those are data structures of the evaluator.\n\n240\n00:26:17,380 --> 00:26:21,410\nThose are all things that would be constants from the point of view of the compiler.\n\n241\n00:26:21,410 --> 00:26:29,330\nThe only thing is this particular compiler is set up so that interpreted code and compiled code can coexist.\n\n242\n00:26:29,330 --> 00:26:39,920\nSo the way to think about it is, is maybe you build a chip which is the evaluator, and what the compiler might do is generate code for that chip.\n\n243\n00:26:39,920 --> 00:26:41,550\nIt just wouldn't use two of the registers.\n\n244\n00:26:51,158 --> 00:26:53,326\nAll right, let's take a break.\n\n245\n00:26:53,326 --> 00:27:28,576\n[MUSIC PLAYING]\n\n246\n00:27:28,576 --> 00:27:32,900\nWe just looked at what the compiler is supposed to do.\n\n247\n00:27:32,900 --> 00:27:38,120\nNow let's very briefly look at how, how this gets accomplished.\n\n248\n00:27:38,120 --> 00:27:39,600\nAnd I'm going to give no details.\n\n249\n00:27:39,600 --> 00:27:43,440\nThere's, there's a giant pile of code in the book that gives all the details.\n\n250\n00:27:43,440 --> 00:27:49,590\nBut what I want to do is just show you the, the essential idea here.\n\n251\n00:27:49,590 --> 00:27:51,450\nWorry about the details some other time.\n\n252\n00:27:51,450 --> 00:27:58,900\nLet's imagine that we're compiling an expression that looks like there's some operator, and there are two arguments.\n\n253\n00:28:03,660 --> 00:28:08,940\nNow, the-- what's the code that the compiler should generate?\n\n254\n00:28:08,940 --> 00:28:14,192\nWell, first of all, it should recursively go off and compile the operator.\n\n255\n00:28:14,192 --> 00:28:18,650\nSo it says, I'll compile the operator.\n\n256\n00:28:21,250 --> 00:28:28,400\nAnd where I'm going to need that is to be in the function register, eventually.\n\n257\n00:28:28,400 --> 00:28:38,890\nSo I'll compile some instructions that will compile the operator and end up with the result in the function register.\n\n258\n00:28:45,420 --> 00:28:55,140\nThe next thing it's going to do, another piece is to say, well, I have to compile the first argument.\n\n259\n00:28:55,140 --> 00:28:58,100\nSo it calls itself recursively.\n\n260\n00:28:58,100 --> 00:29:03,010\nAnd let's say the result will go into val.\n\n261\n00:29:09,150 --> 00:29:35,430\nAnd then what it's going to need to do is start setting up the argument list. So it'll say, assign to argl cons of fetch-- so it generates this literal instruction-- fetch of val onto empty list.\n\n262\n00:29:35,430 --> 00:29:43,950\nHowever, it might have to work--  when it gets here, it's going to need the environment.\n\n263\n00:29:43,950 --> 00:29:49,030\nIt's going to need whatever environment was here in order to do this evaluation of the first argument.\n\n264\n00:29:49,030 --> 00:30:01,220\nSo it has to ensure that the compilation of this operand, or it has to protect the function register against whatever might happen in the compilation of this operand.\n\n265\n00:30:01,220 --> 00:30:12,650\nSo it puts a note here and says, oh, this piece should be done preserving the environment register.\n\n266\n00:30:17,350 --> 00:30:27,930\nSimilarly, here, after it gets done compiling the first operand, it's going to say, I better compile-- I'm going to need to know the environment for the second operand.\n\n267\n00:30:27,930 --> 00:30:50,760\nSo it puts a little note here, saying, yeah, this is also done preserving env. Now it goes on and says, well, the next chunk of code is the one that's going to compile the second argument.\n\n268\n00:30:50,760 --> 00:30:59,360\nAnd let's say it'll compile it with a targeted to val, as they say.\n\n269\n00:31:03,940 --> 00:31:34,060\nAnd then it'll generate the literal instruction, building up the argument list. So it'll say, assign to argl cons of the new value it just got onto the old argument list.\n\n270\n00:31:34,060 --> 00:31:43,510\nHowever, in order to have the old argument list, it better have arranged that the argument list didn't get trashed by whatever happened in here.\n\n271\n00:31:43,510 --> 00:31:51,400\nSo it puts a little note here and says, oh, this has to be done preserving argl.\n\n272\n00:31:54,380 --> 00:31:58,090\nNow it's got the argument list set up.\n\n273\n00:31:58,090 --> 00:32:02,520\nAnd it's all ready to go to apply dispatch.\n\n274\n00:32:06,450 --> 00:32:10,440\nIt generates this literal instruction.\n\n275\n00:32:14,990 --> 00:32:29,600\nBecause now it's got the arguments in argl and the operator in fun, but wait, it's only got the operator in fun if it had ensured that this block of code didn't trash what was in the function register.\n\n276\n00:32:29,600 --> 00:32:40,710\nSo it puts a little note here and says, oh, yes, all this stuff here had better be done preserving the function register.\n\n277\n00:32:46,110 --> 00:32:53,432\nSo that's the little--so when it starts ticking--so basically, what the compiler does is append a whole bunch of code sequences.\n\n278\n00:32:53,432 --> 00:33:02,560\nSee, what it's got in it is little primitive pieces of things, like how to look up a symbol, how to do a conditional.\n\n279\n00:33:02,560 --> 00:33:05,530\nThose are all little pieces of things.\n\n280\n00:33:05,530 --> 00:33:08,810\nAnd then it appends them together in this sort of discipline.\n\n281\n00:33:08,810 --> 00:33:13,140\nSo the basic means of combining things is to append two code sequences.\n\n282\n00:33:21,610 --> 00:33:22,860\nThat's what's going on here.\n\n283\n00:33:25,690 --> 00:33:27,590\nAnd it's a little bit tricky.\n\n284\n00:33:27,590 --> 00:33:35,670\nThe idea is that it appends two code sequences, taking care to preserve a register.\n\n285\n00:33:35,670 --> 00:33:39,250\nSo the actual append operation looks like this.\n\n286\n00:33:39,250 --> 00:33:44,450\nWhat it wants to do is say, if-- here's what it means to append two code sequences.\n\n287\n00:33:44,450 --> 00:33:54,720\nSo if sequence one needs register-- I should change this.\n\n288\n00:33:54,720 --> 00:34:03,815\nAppend sequence one to sequence two, preserving some register.\n\n289\n00:34:08,370 --> 00:34:11,080\nLet me say, and.\n\n290\n00:34:11,080 --> 00:34:13,719\nSo it's clear that sequence one comes first.\n\n291\n00:34:13,719 --> 00:34:43,380\nSo if sequence two needs the register and sequence one modifies the register, then the instructions that the compiler spits out are, save the register.\n\n292\n00:34:43,380 --> 00:34:44,440\nHere's the code.\n\n293\n00:34:44,440 --> 00:34:45,280\nYou generate this code.\n\n294\n00:34:45,280 --> 00:34:53,389\nSave the register, and then you put out the recursively compiled stuff for sequence one.\n\n295\n00:34:53,389 --> 00:34:54,639\nAnd then you restore the register.\n\n296\n00:35:00,440 --> 00:35:07,330\nAnd then you put out the recursively compiled stuff for sequence two.\n\n297\n00:35:07,330 --> 00:35:09,610\nThat's in the case where you need to do it.\n\n298\n00:35:09,610 --> 00:35:15,430\nSequence two actually needs the register, and sequence one actually clobbers it.\n\n299\n00:35:15,430 --> 00:35:16,320\nSo that's sort of if.\n\n300\n00:35:16,320 --> 00:35:28,240\nOtherwise, all you spit out is sequence one followed by sequence two.\n\n301\n00:35:28,240 --> 00:35:36,960\nSo that's the basic operation for sticking together these bits of code fragments, these bits of instructions into a sequence.\n\n302\n00:35:36,960 --> 00:35:59,550\nAnd you see, from this point of view, the difference between the interpreter and the compiler, in some sense, is that where the compiler has these preserving notes, and says, maybe I'll actually generate the saves and restores and maybe I won't, the interpreter being maximally pessimistic always has a save and restore here.\n\n303\n00:35:59,550 --> 00:36:04,140\nThat's the essential difference.\n\n304\n00:36:04,140 --> 00:36:12,025\nWell, in order to do this, of course, the compiler needs some theory of what code sequences need and modifier registers.\n\n305\n00:36:14,330 --> 00:36:27,120\nSo the tiny little fragments that you put in, like the basic primitive code fragments, say, what are the operations that you do when you look up a variable?\n\n306\n00:36:27,120 --> 00:36:32,900\nWhat are the sequence of things that you do when you compile a constant or apply a function?\n\n307\n00:36:32,900 --> 00:36:36,850\nThose have little notations in there about what they need and what they modify.\n\n308\n00:36:38,760 --> 00:36:44,330\nSo the bottom-level data structures-- Well, I'll say this.\n\n309\n00:36:44,330 --> 00:36:48,070\nA code sequence to the compiler looks like this.\n\n310\n00:36:48,070 --> 00:36:50,945\nIt has the actual sequence of instructions.\n\n311\n00:36:55,780 --> 00:37:02,195\nAnd then, along with it, there's the set of registers modified.\n\n312\n00:37:10,630 --> 00:37:12,335\nAnd then there's the set of registers needed.\n\n313\n00:37:19,910 --> 00:37:25,965\nSo that's the information the compiler has that it draws on in order to be able to do this operation.\n\n314\n00:37:29,420 --> 00:37:30,650\nAnd where do those come from?\n\n315\n00:37:30,650 --> 00:37:37,230\nWell, those come from, you might expect, for the very primitive ones, we're going to put them in by hand.\n\n316\n00:37:37,230 --> 00:37:42,080\nAnd then, when we combine two sequences, we'll figure out what these things should be.\n\n317\n00:37:42,080 --> 00:37:48,460\nSo for example, a very primitive one, let's see.\n\n318\n00:37:48,460 --> 00:37:51,790\nHow about doing a register assignment.\n\n319\n00:37:51,790 --> 00:37:56,040\nSo a primitive sequence might say, oh, it's code fragment.\n\n320\n00:37:56,040 --> 00:38:03,050\nIts code instruction is assigned to R1, fetch of R2.\n\n321\n00:38:03,050 --> 00:38:05,000\nSo this is an example.\n\n322\n00:38:05,000 --> 00:38:08,510\nThat might be an example of a sequence of instructions.\n\n323\n00:38:08,510 --> 00:38:20,670\nAnd along with that, it'll say, oh, what I need to remember is that that modifies R1, and then it needs R2.\n\n324\n00:38:24,630 --> 00:38:31,030\nSo when you're first building this compiler, you put in little fragments of stuff like that.\n\n325\n00:38:31,030 --> 00:38:50,950\nAnd now, when it combines two sequences, if I'm going to combine, let's say, sequence one, that modifies a bunch of registers M1, and needs a bunch of registers N1.\n\n326\n00:38:54,940 --> 00:39:00,800\nAnd I'm going to combine that with sequence two.\n\n327\n00:39:00,800 --> 00:39:09,570\nThat modifies a bunch of registers M2, and needs a bunch of registers N2.\n\n328\n00:39:12,590 --> 00:39:15,035\nThen, well, we can reason it out.\n\n329\n00:39:15,035 --> 00:39:27,760\nThe new code fragment, sequence one, and-- followed by sequence two, well, what's it going to modify?\n\n330\n00:39:27,760 --> 00:39:33,990\nThe things that it will modify are the things that are modified either by sequence one or sequence two.\n\n331\n00:39:33,990 --> 00:39:40,530\nSo the union of these two sets are what the new thing modifies.\n\n332\n00:39:40,530 --> 00:39:47,870\nAnd then you say, well, what is this--what registers is it going to need?\n\n333\n00:39:47,870 --> 00:39:52,790\nIt's going to need the things that are, first of all, needed by sequence one.\n\n334\n00:39:52,790 --> 00:39:55,250\nSo what it needs is sequence one.\n\n335\n00:39:55,250 --> 00:39:59,760\nAnd then, well, not quite all of the ones that are needed by sequence one.\n\n336\n00:39:59,760 --> 00:40:08,070\nWhat it needs are the ones that are needed by sequence two that have not been set up by sequence one.\n\n337\n00:40:08,070 --> 00:40:19,370\nSo it's sort of the union of the things that sequence two needs minus the ones that sequence one modifies.\n\n338\n00:40:19,370 --> 00:40:20,910\nBecause it worries about setting them up.\n\n339\n00:40:24,230 --> 00:40:26,740\nSo there's the basic structure of the compiler.\n\n340\n00:40:26,740 --> 00:40:34,010\nThe way you do register optimizations is you have some strategies for what needs to be preserved.\n\n341\n00:40:34,010 --> 00:40:35,450\nThat depends on a data structure.\n\n342\n00:40:35,450 --> 00:40:39,080\nWell, it depends on the operation of what it means to put things together.\n\n343\n00:40:39,080 --> 00:40:48,900\nPreserving something, that depends on knowing what registers are needed and modified by these code fragments.\n\n344\n00:40:48,900 --> 00:40:57,350\nThat depends on having little data structures, which say, a code sequence is the actual instructions, what they modify and what they need.\n\n345\n00:40:57,350 --> 00:41:00,240\nThat comes from, at the primitive level, building it in.\n\n346\n00:41:00,240 --> 00:41:04,850\nAt the primitive level, it's going to be completely obvious what something needs and modifies.\n\n347\n00:41:04,850 --> 00:41:15,010\nPlus, this particular way that says, when I build up bigger ones, here's how I generate the new set of registers modified and the new set of registers needed.\n\n348\n00:41:15,010 --> 00:41:17,810\nAnd that's the whole-- well, I shouldn't say that's the whole thing.\n\n349\n00:41:17,810 --> 00:41:21,860\nThat's the whole thing except for about 30 pages of details in the book.\n\n350\n00:41:21,860 --> 00:41:28,880\nBut it is a perfectly usable rudimentary compiler.\n\n351\n00:41:28,880 --> 00:41:31,390\nLet me kind of show you what it does.\n\n352\n00:41:31,390 --> 00:41:36,330\nSuppose we start out with recursive factorial.\n\n353\n00:41:36,330 --> 00:41:38,590\nAnd these slides are going to be much too small to read.\n\n354\n00:41:38,590 --> 00:41:41,620\nI just want to flash through the code and show you about how much it is.\n\n355\n00:41:44,460 --> 00:41:48,740\nThat starts out with--here's a first block of it, where it compiles a procedure entry and does a bunch of assignments.\n\n356\n00:41:48,740 --> 00:41:56,830\nAnd this thing is basically up through the part where it sets up to do the predicate and test whether the predicate's true.\n\n357\n00:41:56,830 --> 00:42:04,210\nThe second part is what results from-- in the recursive call to fact of n minus one.\n\n358\n00:42:04,210 --> 00:42:09,890\nAnd this last part is coming back from that and then taking care of the constant case.\n\n359\n00:42:09,890 --> 00:42:13,760\nSo that's about how much code it would produce for factorial.\n\n360\n00:42:13,760 --> 00:42:18,380\nWe could make this compiler much, much better, of course.\n\n361\n00:42:18,380 --> 00:42:26,990\nThe main way we could make it better is to allow the compiler to make any assumptions at all about what happens when you call a procedure.\n\n362\n00:42:26,990 --> 00:42:36,030\nSo this compiler, for instance, doesn't even know, say, that multiplication is something that could be coded in line.\n\n363\n00:42:36,030 --> 00:42:37,670\nInstead, it sets up this whole mechanism.\n\n364\n00:42:37,670 --> 00:42:38,920\nIt goes to apply-dispatch.\n\n365\n00:42:41,430 --> 00:42:49,170\nThat's a tremendous waste, because what you do every time you go to apply-dispatch is you have to concept this argument list, because it's a very general thing you're going to.\n\n366\n00:42:49,170 --> 00:42:53,830\nIn any real compiler, of course, you're going to have registers for holding arguments.\n\n367\n00:42:53,830 --> 00:43:02,442\nAnd you're going to start preserving and saving the way you use those registers similar to the same strategy here.\n\n368\n00:43:02,442 --> 00:43:08,940\nSo that's probably the very main way that this particular compiler in the book could be fixed.\n\n369\n00:43:08,940 --> 00:43:14,490\nThere are other things like looking up variable values and making more efficient primitive operations and all sorts of things.\n\n370\n00:43:14,490 --> 00:43:19,780\nEssentially, a good Lisp compiler can absorb an arbitrary amount of effort.\n\n371\n00:43:19,780 --> 00:43:34,520\nAnd probably one of the reasons that Lisp is slow with compared to languages like FORTRAN is that, if you look over history at the amount of effort that's gone into building Lisp compilers, it's nowhere near the amount of effort that's gone into FORTRAN compilers.\n\n372\n00:43:34,520 --> 00:43:38,250\nAnd maybe that's something that will change over the next couple of years.\n\n373\n00:43:38,250 --> 00:43:39,500\nOK, let's break.\n\n374\n00:43:43,950 --> 00:43:45,200\nQuestions?\n\n375\n00:43:48,370 --> 00:44:00,720\nAUDIENCE: One of the very first classes-- I don't know if it was during class or after class- you showed me the, say, addition has a primitive that we don't see, and-percent add or something like that.\n\n376\n00:44:00,720 --> 00:44:08,540\nIs that because, if you're doing inline code you'd want to just do it for two operators, operands?\n\n377\n00:44:08,540 --> 00:44:12,800\nBut if you had more operands, you'd want to do something special?\n\n378\n00:44:12,800 --> 00:44:15,980\nPROFESSOR: Yeah, you're looking in the actual scheme implementation.\n\n379\n00:44:15,980 --> 00:44:17,880\nThere's a plus, and a plus is some operator.\n\n380\n00:44:17,880 --> 00:44:24,640\nAnd then if you go look inside the code for plus, you see something called-- I forget-- and-percent plus or something like that.\n\n381\n00:44:24,640 --> 00:44:28,540\nAnd what's going on there is that particular kind of optimization.\n\n382\n00:44:28,540 --> 00:44:31,770\nBecause, see, general plus takes an arbitrary number of arguments.\n\n383\n00:44:34,750 --> 00:44:44,880\nSo the most general plus says, oh, if I have an argument list, I'd better cons it up in some list and then figure out how many there were or something like that.\n\n384\n00:44:44,880 --> 00:44:49,200\nThat's terribly inefficient, especially since most of the time you're probably adding two numbers.\n\n385\n00:44:49,200 --> 00:44:58,170\nYou don't want to really have to cons this argument list. So what you'd like to do is build the code for plus with a bunch of entries.\n\n386\n00:44:58,170 --> 00:45:00,170\nSo most of what it's doing is the same.\n\n387\n00:45:00,170 --> 00:45:04,640\nHowever, there might be a special entry that you'd go to if you knew there were only two arguments.\n\n388\n00:45:04,640 --> 00:45:05,910\nAnd those you'll put in registers.\n\n389\n00:45:05,910 --> 00:45:09,080\nThey won't be in an argument list and you won't have to [UNINTELLIGIBLE].\n\n390\n00:45:09,080 --> 00:45:12,570\nThat's how a lot of these things work.\n\n391\n00:45:12,570 --> 00:45:13,948\nOK, let's take a break.\n\n392\n00:45:13,948 --> 00:45:15,696\n[MUSIC PLAYING]\n\n"
  },
  {
    "path": "SrtCN/lec10a.srt",
    "content": "﻿1\n00:00:00,016 --> 00:00:05,024\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:05,376 --> 00:00:07,840\n翻译&&时间轴：杨启钊（windfarer）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:07,840 --> 00:00:09,840\n特别感谢：裘宗燕教授\n\n4\n00:00:09,840 --> 00:00:11,840\n计算机程序的构造和解释\n\n5\n00:00:11,840 --> 00:00:13,840\n编译\nCompilation\n\n6\n00:00:19,360 --> 00:00:22,650\n教授: 上节课 我们学习了\nPROFESSOR: Last time, we took a look at\n\n7\n00:00:22,650 --> 00:00:25,675\n一个显式控制的Lisp求值器\nan explicit control evaluator for Lisp\n\n8\n00:00:25,670 --> 00:00:28,976\n它弥合了像Lisp\nand that bridged the gap between all these high-level languages\n\n9\n00:00:29,056 --> 00:00:32,144\n或者查询语言之类的高级语言\nlike Lisp and query language all that stuff\n\n10\n00:00:32,500 --> 00:00:36,160\n与传统寄存器机器之间的鸿沟\nbridged the gap between that and a conventional register machine.\n\n11\n00:00:36,700 --> 00:00:40,144\n事实上 你可以将显式控制求值器\nAnd in fact, you can think of the explicit control evaluator\n\n12\n00:00:40,160 --> 00:00:44,384\n看作是 在一台常见的\neither as, say the code for a Lisp interpreter\n\n13\n00:00:44,400 --> 00:00:45,950\n寄存机器上实现的\nif you wanted to implement it in the\n\n14\n00:00:46,525 --> 00:00:49,500\nLisp求值器的汇编代码\nassembly language of some conventional register transfer machine,\n\n15\n00:00:49,500 --> 00:00:51,504\n或者 你可以把它看做是\nor, if you like, you can think of it as the microcode\n\n16\n00:00:52,080 --> 00:00:54,560\n某台专门运行Lisp的机器的微程序\nof some machine that's going to be specially designed to run Lisp.\n\n17\n00:00:55,200 --> 00:00:55,925\n无论是那种情况\nIn either case,\n\n18\n00:00:55,920 --> 00:00:58,688\n我们都是把一台\nNwhat we're doing is we're taking a machine\n\n19\n00:00:58,944 --> 00:01:00,512\n处理低级语言的机器\nthat speaks some low-level language\n\n20\n00:01:01,420 --> 00:01:03,328\n抬高到一个层次\nand we're raising the machine\n\n21\n00:01:03,376 --> 00:01:04,880\n以便处理像Lisp这样的高级语言\nto a high-level language like Lisp\n\n22\n00:01:05,360 --> 00:01:06,352\n这是通过编写解释器来实现的\nby writing an interpreter.\n\n23\n00:01:08,220 --> 00:01:09,584\n来看个例子\nSo for instance\n\n24\n00:01:11,820 --> 00:01:13,776\n这里 从概念上来说\nhere, conceptually,\n\n25\n00:01:18,016 --> 00:01:19,470\n从概念上来说 这是一台\nhere conceptually is a\n\n26\n00:01:20,544 --> 00:01:23,440\n专用于计算阶乘的机器\na special purpose machine for computing factorials.\n\n27\n00:01:24,090 --> 00:01:27,392\n输入5 输出120\nIt takes in five and puts out 120.\n\n28\n00:01:28,920 --> 00:01:30,832\n这个专用机器实际上\nAnd what this special purpose machine is\n\n29\n00:01:30,970 --> 00:01:32,720\n是一个Lisp解释器\nactually a Lisp interpreter\n\n30\n00:01:33,500 --> 00:01:36,176\n它将自己配置为计算阶乘\nthat's configured itself to run factorials\n\n31\n00:01:38,350 --> 00:01:40,992\n因为你向它送入了一台阶乘机器的描述\nbecause you feed into it a description of the factorial machine.\n\n32\n00:01:42,125 --> 00:01:43,700\n这就是解释器\nSo that's what an interpreter is.\n\n33\n00:01:43,700 --> 00:01:45,664\n它将自己配置为\nIt configures itself to\n\n34\n00:01:46,370 --> 00:01:49,248\n模拟你所输入描述的机器\nemulate a machine whose description you read in.\n\n35\n00:01:50,070 --> 00:01:51,936\n那么 在Lisp解释器里是什么?\nNow, inside the Lisp interpreter, what's that?\n\n36\n00:01:52,040 --> 00:01:55,440\n里面可能是通用的寄存器语言解释器\nWell, that might be your general register language interpreter\n\n37\n00:01:56,987 --> 00:02:00,180\n它将自己配置成像Lisp解释器那样\nthat configures itself to behave like a Lisp interpreter\n\n38\n00:02:00,180 --> 00:02:02,032\n因为你输入了一系列用寄存器语言\nbecause you put in a whole bunch of instructions\n\n39\n00:02:02,128 --> 00:02:03,040\n编写的指令\nin register language.\n\n40\n00:02:03,370 --> 00:02:05,168\n这就是显式控制求值器\nThis is the explicit control evaluator.\n\n41\n00:02:07,050 --> 00:02:08,704\n它里面也有一些库\nAnd then it also has some sort of library\n\n42\n00:02:08,730 --> 00:02:11,088\n由基本运算符和Lisp运算\na library of primitive operators and Lisp operations\n\n43\n00:02:11,120 --> 00:02:12,288\n等等要素组成\nall sorts of things like that.\n\n44\n00:02:12,750 --> 00:02:16,896\n这是解释执行的一般策略\nThat's the general strategy of interpretation.\n\n45\n00:02:17,320 --> 00:02:18,512\n事实上 我们所做的是\nAnd the point is, what we're doing\n\n46\n00:02:18,608 --> 00:02:20,140\n通过编写解释器\nis we're writing an interpreter\n\n47\n00:02:21,620 --> 00:02:23,408\n将机器抬升到\nto raise the machine\n\n48\n00:02:23,424 --> 00:02:25,240\n我们程序所在的层次\nto the level of the programs that we want to write.\n\n49\n00:02:25,240 --> 00:02:26,720\n当然 还有另外一种策略\nWell, there's another strategy\n\n50\n00:02:27,424 --> 00:02:28,896\n这种不同的策略就是编译\na different one, which is compilation.\n\n51\n00:02:29,040 --> 00:02:30,432\n编译有一些不同\nCompilation's a little bit different.\n\n52\n00:02:31,040 --> 00:02:31,504\n这里\nHere--\n\n53\n00:02:33,370 --> 00:02:34,752\n我们可能已经实现了\nhere we might have produced\n\n54\n00:02:35,679 --> 00:02:38,525\n一个特定用途的机器\na special purpose machine for,\n\n55\n00:02:38,624 --> 00:02:39,984\n用来计算阶乘\nfor computing factorials\n\n56\n00:02:43,625 --> 00:02:46,260\n从某种使用寄存器语言的机器开始\nstarting with some sort of machine that speaks register language\n\n57\n00:02:46,260 --> 00:02:47,720\n但是 我们将让它执行不同的策略\nexcept we're going to do a different strategy.\n\n58\n00:02:47,720 --> 00:02:50,384\n把我们的阶乘程序\nWe take our factorial program.\n\n59\n00:02:51,550 --> 00:02:53,920\n作为源代码输入编译器\nWe use that as the source code into a compiler.\n\n60\n00:02:53,920 --> 00:02:55,150\n编译器就会\nWhat the compiler will do\n\n61\n00:02:55,150 --> 00:02:57,625\n把这个阶乘程序\nis translate that factorial program\n\n62\n00:02:57,620 --> 00:02:59,072\n翻译成某种寄存器机器语言\ninto some register machine language.\n\n63\n00:03:00,250 --> 00:03:03,400\n现在它并不是Lisp的显式控制求值器\nAnd this will now be not the explicit control evaluator for Lisp\n\n64\n00:03:03,400 --> 00:03:06,176\n而是某种用来计算阶乘的寄存器语言\nthis will be some register language for computing factorials.\n\n65\n00:03:06,496 --> 00:03:08,368\n这就是翻译的过程\nSo this is the translation of that.\n\n66\n00:03:10,544 --> 00:03:12,416\n它将进入某种加载器\nThat will go into some sort of loader\n\n67\n00:03:13,350 --> 00:03:15,216\n它会把这些代码\nwhich will combine this code\n\n68\n00:03:15,312 --> 00:03:16,848\n和从程序库中选取的代码\nwith code selected from the library\n\n69\n00:03:16,864 --> 00:03:18,656\n比如乘法运算等 结合在一起\nto do things like primitive multiplication.\n\n70\n00:03:19,820 --> 00:03:21,696\n随后我们将生成一个加载模块\nAnd then we'll produce a load module\n\n71\n00:03:22,225 --> 00:03:25,060\n它把寄存器语言机器配置成\nwhich configures the register language machine\n\n72\n00:03:25,060 --> 00:03:27,248\n一个专门用来计算阶乘的机器\nto be a special purpose factorial machine.\n\n73\n00:03:28,125 --> 00:03:30,220\n这就是不同的策略\nSo that's a, that's a different strategy.\n\n74\n00:03:30,220 --> 00:03:31,225\n在解释中\nIn interpretation,\n\n75\n00:03:31,220 --> 00:03:32,016\n我们把机器\nwe're raising\n\n76\n00:03:32,912 --> 00:03:35,232\n抬升到Lisp语言的层次\nthe machine to the level of our language, like Lisp.\n\n77\n00:03:35,320 --> 00:03:36,340\n而在编译中\nIn compilation\n\n78\n00:03:36,340 --> 00:03:38,432\n我们将我们的程序下降到\nwe're taking our program and lowering\n\n79\n00:03:38,480 --> 00:03:40,560\n机器语言的层次\nit to the language that's spoken by the machine.\n\n80\n00:03:41,968 --> 00:03:43,840\n那么 这两个策略有什么区别呢?\nWell, how do these two strategies compare?\n\n81\n00:03:44,300 --> 00:03:49,424\n编译器可以生成执行起来更有效率的代码\nThe compiler can produce code that will execute more efficiently.\n\n82\n00:03:52,050 --> 00:03:53,904\n主要原因是\nThe essential reason for that\n\n83\n00:03:54,170 --> 00:03:58,896\n如果你考虑运行中的寄存器操作\nis that if you think about the register operations that are running\n\n84\n00:04:01,920 --> 00:04:04,496\n解释器需要生成寄存器的操作\nthe interpreter has to produce register operations\n\n85\n00:04:04,970 --> 00:04:06,752\n从原则上来讲 它需要足够通用\nwhich, in principle, are going to be general enough\n\n86\n00:04:07,328 --> 00:04:08,944\n以支持任何Lisp过程的执行\nto execute any Lisp procedure.\n\n87\n00:04:10,220 --> 00:04:12,256\n而编译器只需要\nWhereas the compiler only has to worry about\n\n88\n00:04:12,272 --> 00:04:14,920\n生成一组特定的寄存器操作\nproducing a special bunch of register operations for\n\n89\n00:04:15,520 --> 00:04:18,224\n用来执行你所编译的那部分特定的Lisp过程\nfor doing the particular Lisp procedure that you've compiled.\n\n90\n00:04:20,175 --> 00:04:21,200\n换一种说法\nOr another way to say that\n\n91\n00:04:21,200 --> 00:04:25,312\n解释器是一种通用的模拟器\nis that the interpreter is a general purpose simulator\n\n92\n00:04:25,925 --> 00:04:27,580\n当你输入一个Lisp过程时\nthat when you read in a Lisp procedure\n\n93\n00:04:27,580 --> 00:04:31,325\n它们就会模拟那个过程所描述的程序\nthen those can simulate the program described by that, by that procedure.\n\n94\n00:04:31,320 --> 00:04:33,872\n所以解释器旨在成为一个通用模拟器\nSo the interpreter is worrying about making a general purpose simulator\n\n95\n00:04:34,620 --> 00:04:35,968\n而编译器 实际上\nwhereas the compiler, in effect,\n\n96\n00:04:36,000 --> 00:04:37,680\n只需要将东西配置成\nis configuring the thing to be the machine\n\n97\n00:04:37,712 --> 00:04:39,344\n解释器将要去模拟的机器\nthat the interpreter would have been simulating.\n\n98\n00:04:40,020 --> 00:04:41,344\n所以编译器可以运行得更快\nSo the compiler can be faster.\n\n99\n00:04:52,550 --> 00:04:53,648\n另一方面\nOK, On the other hand\n\n100\n00:04:55,970 --> 00:04:58,288\n解释器更适合用来排查错误\nthe interpreter is a nicer environment for debugging.\n\n101\n00:04:59,438 --> 00:05:01,250\n这是因为\nAnd the reason for that is that we've got the\n\n102\n00:05:01,575 --> 00:05:03,020\n我们的源代码实际上就在那里\nthe source code actually there.\n\n103\n00:05:03,020 --> 00:05:04,816\n我们正在解释它们\nWe're interpreting it That's what we're working with.\n\n104\n00:05:05,870 --> 00:05:07,696\n并且库也在其中\nAnd we also have the library around.\n\n105\n00:05:07,900 --> 00:05:10,896\n看 库是解释器的一部分\nSee, the interpreter--the library sitting there is part of the interpreter.\n\n106\n00:05:11,300 --> 00:05:13,168\n而编译器只会拉取\nThe compiler only pulls out from the library\n\n107\n00:05:13,200 --> 00:05:14,560\n运行程序所需要的代码\nwhat it needs to run the program.\n\n108\n00:05:14,870 --> 00:05:17,008\n所以 如果你在排查错误的途中\nSo if you're in the middle of debugging\n\n109\n00:05:18,000 --> 00:05:20,720\n你想写一些额外的代码\nand you might like to write a little extra program\n\n110\n00:05:20,800 --> 00:05:22,570\n来考察运行过程中的数据类型\nto examine some run time data structure\n\n111\n00:05:23,050 --> 00:05:24,256\n或者做一些\nor to produce some computation\n\n112\n00:05:24,304 --> 00:05:25,920\n在写程序时没有想到的计算\nthat you didn't think of when you wrote the program\n\n113\n00:05:25,952 --> 00:05:27,536\n解释器可以完美搞定这些\nthe interpreter can do that perfectly well\n\n114\n00:05:28,050 --> 00:05:29,216\n而编译器不行\nwhereas the compiler can't.\n\n115\n00:05:29,625 --> 00:05:31,900\n所以它们各有优点\nSo there are sort of dual, dual advantages.\n\n116\n00:05:31,900 --> 00:05:34,480\n编译器将生成运行更快的代码\nThe compiler will produce code that executes faster.\n\n117\n00:05:34,850 --> 00:05:37,024\n而解释器是一种更适合排错的环境\nThe interpreter is a better environment for debugging.\n\n118\n00:05:38,950 --> 00:05:41,408\n大多数Lisp系统最终将二者都实现了\nAnd most Lisp systems end up having both\n\n119\n00:05:42,920 --> 00:05:45,232\n这样你就可以在开发阶段\nend up being configured so you have an interpreter\n\n120\n00:05:45,248 --> 00:05:47,080\n可以使用解释器\nthat you use when you're developing your code.\n\n121\n00:05:47,080 --> 00:05:48,624\n随后通过编译加速代码的运行\nThen you can speed it up by compiling.\n\n122\n00:05:49,020 --> 00:05:50,032\n并且通常\nAnd very often,\n\n123\n00:05:50,048 --> 00:05:51,680\n你能够让被编译的代码\nyou can arrange that compiled code\n\n124\n00:05:51,696 --> 00:05:53,568\n和被解释的代码互相调用\nand interpreted code can call each other.\n\n125\n00:05:54,600 --> 00:05:56,336\n我们将学习如何做到 其实不难\nWe'll see how to do that, That's not hard.\n\n126\n00:05:59,270 --> 00:05:59,856\n好\nOK\n\n127\n00:06:00,970 --> 00:06:02,096\n事实上\nIn fact, the way we'll--\n\n128\n00:06:04,304 --> 00:06:05,750\n在我们将要构建的编译器中\nin the compiler we're going to make\n\n129\n00:06:05,750 --> 00:06:07,584\n我们实现编译的代码和解释的代码\nthe way we'll arrange for compiled coding\n\n130\n00:06:07,584 --> 00:06:09,456\n互相调用的方式是\nand interpreted code to call to call each other\n\n131\n00:06:09,900 --> 00:06:12,064\n我们让编译器和解释器使用\nis that we'll have the compiler use exactly\n\n132\n00:06:12,112 --> 00:06:14,400\n使用完全一致的寄存器约定\nthe same register conventions as the interpreter.\n\n133\n00:06:18,420 --> 00:06:21,728\n编译器的理念\nWell, the idea of a compiler\n\n134\n00:06:21,760 --> 00:06:25,744\n与解释器或求值器的理念很像\nis very much like the idea of an interpreter or evaluator.\n\n135\n00:06:25,870 --> 00:06:26,464\n它们是相同的\nIt's the same thing.\n\n136\n00:06:27,050 --> 00:06:29,392\n求值器遍历代码\nSee, the evaluator walks over the code\n\n137\n00:06:29,820 --> 00:06:32,352\n产生一些寄存器操作\nand performs some register operations.\n\n138\n00:06:33,650 --> 00:06:34,976\n就是我们昨天做的事情\nThat's what we did yesterday.\n\n139\n00:06:37,100 --> 00:06:40,272\n而编译器会读取代码\nWell, the compiler essentially would like to walk over the code\n\n140\n00:06:40,520 --> 00:06:43,008\n生成一些进行求值时\nand produce the register operations\n\n141\n00:06:43,040 --> 00:06:44,672\n求值器会进行的\nthat the evaluator would have done\n\n142\n00:06:45,232 --> 00:06:46,640\n相关寄存器操作\nwere it evaluating the thing.\n\n143\n00:06:48,600 --> 00:06:49,952\n这就给我们提供了一个模型\nAnd that gives us some model\n\n144\n00:06:50,608 --> 00:06:53,776\n来实现一个零阶编译器\nfor how to implement a zeroth-order compiler\n\n145\n00:06:55,300 --> 00:06:58,320\n一个很差劲但是能用的编译器\na very bad compiler but essentially a compiler.\n\n146\n00:06:58,320 --> 00:06:59,328\n这种模型就是\nA model for doing that\n\n147\n00:06:59,360 --> 00:07:00,592\n你用求值器\nis you just take the evaluator,\n\n148\n00:07:00,688 --> 00:07:01,888\n把代码跑一遍\nyou run it over the code\n\n149\n00:07:02,800 --> 00:07:06,060\n但不去执行实际的操作\nbut instead of executing the actual operations\n\n150\n00:07:06,060 --> 00:07:07,152\n只是把它们保存下来\nyou just save them away.\n\n151\n00:07:07,550 --> 00:07:08,825\n那就是你编译后的代码\nAnd that's your compiled code.\n\n152\n00:07:08,820 --> 00:07:10,240\n让我举个例子\nSo let me give you an example of that.\n\n153\n00:07:12,700 --> 00:07:14,144\n假设我们要编译\nSuppose we're going to compile--\n\n154\n00:07:15,100 --> 00:07:17,904\n编译(F X) 这个表达式\nSuppose we want to compile the expression f of x.\n\n155\n00:07:25,070 --> 00:07:25,968\n我们假设\nSo let's assume that\n\n156\n00:07:25,960 --> 00:07:28,064\nEXP寄存器中保存着(F X)\nwe've got f of x in the exp register\n\n157\n00:07:28,064 --> 00:07:29,552\n而ENV寄存器又保存着其它东西\nand something in the environment register.\n\n158\n00:07:30,100 --> 00:07:32,208\n想象我们启动了求值器\nAnd now imagine starting up the evaluator.\n\n159\n00:07:34,608 --> 00:07:35,712\n它读取了表达式\nWell, it looks at the expression\n\n160\n00:07:35,712 --> 00:07:37,360\n判断它是一个应用\nand it sees that it's an application.\n\n161\n00:07:37,920 --> 00:07:41,904\n它分支到求值器代码中的一个地方\nAnd it branches to a place in the\n\n162\n00:07:42,520 --> 00:07:45,152\n我们之前见过的叫EV-APPLICATION的地方\nin the evaluator code we saw called ev-application.\n\n163\n00:07:47,120 --> 00:07:48,128\n然后继续处理\nAnd then it begins.\n\n164\n00:07:48,160 --> 00:07:50,080\n恢复运算对象和UNEV\nIt stores away the operands and unev\n\n165\n00:07:50,080 --> 00:07:52,448\n然后之后它将运算符放在EXP寄存器中\nand then it's going to put the operator in exp,\n\n166\n00:07:52,480 --> 00:07:54,272\n递归地对它求值\nand it's going to go recursively evaluate it.\n\n167\n00:07:54,470 --> 00:07:56,080\n这就是我们经历的过程\nThat's the process that we walk through.\n\n168\n00:07:56,670 --> 00:07:57,840\n如果你看代码\nAnd if you start looking at the code,\n\n169\n00:07:57,872 --> 00:07:59,744\n会看到一些寄存器操作\nyou start seeing some register operations.\n\n170\n00:08:00,200 --> 00:08:02,300\n你会看到将运算对象赋值给UNEV寄存器\nYou see assign to unev the operands\n\n171\n00:08:02,300 --> 00:08:03,952\n把运算符赋值给EXP\nassign to exp the operator,\n\n172\n00:08:04,096 --> 00:08:06,208\n保存环境、生成新环境 等等\nsave the environment, generate that, and so on.\n\n173\n00:08:10,220 --> 00:08:11,936\n如果我们来看下这里的投影\nWell, if we look on the overhead here\n\n174\n00:08:15,750 --> 00:08:19,584\n我们会看到产生的这些操作\nwe can see those operations starting to be produced.\n\n175\n00:08:20,820 --> 00:08:22,528\n这是求值器实际要进行的\nHere's sort of the first real operation\n\n176\n00:08:22,720 --> 00:08:24,800\n第一个操作\nthat the evaluator would have done.\n\n177\n00:08:25,000 --> 00:08:27,200\n它将运算对象从EXP寄存器里取出来\nIt pulls the operands out of the exp register\n\n178\n00:08:27,470 --> 00:08:28,624\n并将它赋值给UNEV\nand assigns it to unev.\n\n179\n00:08:30,030 --> 00:08:32,272\n然后它给EXP寄存器赋了某个值\nAnd then it assigns something to the expression register,\n\n180\n00:08:32,304 --> 00:08:33,460\n然后保存CONTINUE\nand it saves continue\n\n181\n00:08:33,460 --> 00:08:34,620\n保存ENV\nand it saves env.\n\n182\n00:08:34,620 --> 00:08:38,656\n我在这里就只是寄存器赋值\nAnd all I'm doing here is writing down the register assignments\n\n183\n00:08:39,570 --> 00:08:42,320\n这就是求值器求值代码时进行的操作\nthat the evaluator would have done in executing that code.\n\n184\n00:08:42,770 --> 00:08:43,792\n我们缩小画面看看\nAnd can zoom out a little bit.\n\n185\n00:08:44,300 --> 00:08:47,136\n总计有19个操作\nAltogether, there are about 19 operations there.\n\n186\n00:08:49,400 --> 00:08:51,648\n这些代码\nAnd this is the--this will be the piece of code\n\n187\n00:08:52,050 --> 00:08:53,904\n对应着\nup until the point where\n\n188\n00:08:54,752 --> 00:08:57,100\n求值器跳转到APPLY-DISPATCH代码之前\nthe evaluator branches off to apply-dispatch.\n\n189\n00:08:57,860 --> 00:08:59,168\n事实上 在这个编译器中\nAnd in fact, in this compiler\n\n190\n00:08:59,200 --> 00:09:01,184\n我们不需要再关心APPLY-DISPATCH了\nwe're not going to worry about apply-dispatch at all.\n\n191\n00:09:01,300 --> 00:09:02,112\n我们有所有东西\nWe're going to have everything\n\n192\n00:09:02,352 --> 00:09:05,040\n我们拥有解释后和编译后的所有代码\nwe're going to have both interpreted code and compiled code.\n\n193\n00:09:06,075 --> 00:09:07,611\n通常求值过程\nAlways evaluate procedures,\n\n194\n00:09:07,610 --> 00:09:09,856\n是由APPLY-DISPATCH处理的\nalways apply procedures by going to apply-dispatch.\n\n195\n00:09:10,270 --> 00:09:12,320\n这将让被解释后代码与编译后代码\nThat will easily allow interpreted code and\n\n196\n00:09:12,368 --> 00:09:13,712\n很容易互相调用\ncompiled code to call each other.\n\n197\n00:09:18,270 --> 00:09:19,872\n从原理上来说 这样做足矣\nWell, in principle, that's all we need to do.\n\n198\n00:09:21,050 --> 00:09:22,660\n只需运行求值器\nYou just run the evaluator.\n\n199\n00:09:22,660 --> 00:09:24,500\n因而编译器非常像求值器\nSo the compiler's a lot like the evaluator.\n\n200\n00:09:24,500 --> 00:09:26,475\n你运行它 唯一不同是你把操作存下来\nYou run it, except it stashes away these operations\n\n201\n00:09:26,470 --> 00:09:28,400\n而不是实际执行它们\ninstead of actually executing them.\n\n202\n00:09:29,350 --> 00:09:31,392\n这其实不完全正确\nWell, that's not, that's not quite true. there's\n\n203\n00:09:32,910 --> 00:09:34,992\n这里面我们撒了个小谎\nThere's only one little lie in that.\n\n204\n00:09:36,240 --> 00:09:39,296\n你需要关心的是：如果有个谓词\nWhat you have to worry about is if you have a, a predicate.\n\n205\n00:09:40,120 --> 00:09:42,160\n如果你要进行某种测试\nIf you have some kind of test you want to do\n\n206\n00:09:43,450 --> 00:09:46,032\n显然 在你编译时\nobviously, at the point when you're compiling it\n\n207\n00:09:46,520 --> 00:09:47,984\n你不知道这些分支中\nyou don't know which branch of these--\n\n208\n00:09:48,320 --> 00:09:50,144\n哪条分支会被执行\nof a conditional like this you're going to do.\n\n209\n00:09:51,130 --> 00:09:53,920\n所以你不能确定求值器将对哪个求值\nSo you can't say which one the evaluator would have done.\n\n210\n00:09:54,909 --> 00:09:57,125\n因此在这里就很简单\nSo all you do there is very simple.\n\n211\n00:09:57,120 --> 00:09:58,496\n你把两个分支全编译了\nYou compile both branches.\n\n212\n00:09:59,328 --> 00:10:01,296\n因此你编译出一个这样的结构\nSo you compile a structure that looks like this.\n\n213\n00:10:02,000 --> 00:10:03,984\n它们都会被编译成\nThat'll compile into something that says,\n\n214\n00:10:05,312 --> 00:10:09,152\n首先是P的代码\nthe code, the code for P.\n\n215\n00:10:10,710 --> 00:10:16,512\n它把结果存入VAL寄存器\nAnd it puts its results in, say, the val register.\n\n216\n00:10:18,170 --> 00:10:20,640\n解释器对谓词求值\nSo you walk the interpreter over the predicate\n\n217\n00:10:21,350 --> 00:10:24,192\n并保证结果会放到VAL寄存器中\nand make sure that the result would go into the val register.\n\n218\n00:10:24,703 --> 00:10:27,220\n随后你编译一条指令\nAnd then you compile an instruction that says\n\n219\n00:10:27,220 --> 00:10:33,792\n如果VAL是TRUE\nbranch if, if val is true\n\n220\n00:10:37,170 --> 00:10:38,752\n就转到LABEL1这个地方\nto a place we'll call label one.\n\n221\n00:10:44,970 --> 00:10:47,520\n然后我们写下B的代码\nThen we, we will put the code for B\n\n222\n00:10:49,420 --> 00:10:52,320\n让解释器对B进行求值\nto walk the interpreter--walk the interpreter over B.\n\n223\n00:10:53,620 --> 00:10:57,216\n然后写一句指令\nAnd then go to put in an instruction that says,\n\n224\n00:10:57,232 --> 00:10:58,752\n用来跳转到下一条指令\ngo to the next thing, whatever\n\n225\n00:11:02,200 --> 00:11:04,560\n就是它结束之后要去的地方\nwhatever was supposed to happen after this thing was done.\n\n226\n00:11:04,950 --> 00:11:06,096\n你放入那个指令\nYou put in that instruction.\n\n227\n00:11:06,880 --> 00:11:08,624\n这里你写下LABEL1\nAnd here you put label one.\n\n228\n00:11:12,120 --> 00:11:13,808\n这里写A的代码\nAnd here you put the code for A.\n\n229\n00:11:19,470 --> 00:11:25,856\n然后又是跳转到下一条指令\nAnd you put go to next thing.\n\n230\n00:11:31,420 --> 00:11:32,880\n这就是处理条件分支的办法\nSo that's how you treat a conditional.\n\n231\n00:11:32,980 --> 00:11:34,656\n你生成一小段这样的代码\nYou generate a little block like that.\n\n232\n00:11:35,750 --> 00:11:38,128\n除此之外\nAnd other than that\n\n233\n00:11:38,950 --> 00:11:41,552\n这个零阶编译器与求值器一模一样\nthis zeroth-order compiler is the same as the evaluator.\n\n234\n00:11:42,550 --> 00:11:45,120\n它只是把指令存起来 而不执行它们\nIt's just stashing away the instructions instead of executing them.\n\n235\n00:11:46,550 --> 00:11:47,600\n看起来很简单\nThat seems pretty simple,\n\n236\n00:11:47,648 --> 00:11:49,088\n但我们已经取得了某些收获\nbut we've gained something by that.\n\n237\n00:11:50,120 --> 00:11:52,624\n它会比求值器更有效率\nSee, already that's going to be more efficient than the evaluator.\n\n238\n00:11:53,520 --> 00:11:56,144\n因为 如果你观察求值器的运行\nBecause, if you watch the evaluator run\n\n239\n00:11:56,350 --> 00:12:01,056\n它并不只是进行寄存器操作\nit's not only generating the register operations we wrote down\n\n240\n00:12:01,270 --> 00:12:03,504\n它还会决定执行哪个\nit's also doing things to decide which ones to generate.\n\n241\n00:12:04,700 --> 00:12:07,232\n它做的第一件事就是\nSo the very first thing it does, say here\n\n242\n00:12:07,925 --> 00:12:09,775\n以它为例 就是进行某些测试\nhere for instance, is go do some tests\n\n243\n00:12:09,770 --> 00:12:11,568\n确定它是一个应用\nand decide that this is an application\n\n244\n00:12:13,570 --> 00:12:15,056\n然后就跳转到\nand then branch off to the place that,\n\n245\n00:12:15,392 --> 00:12:16,624\n处理应用的地方去\nthat handles applications.\n\n246\n00:12:16,620 --> 00:12:18,448\n换句话说 求值器做的事情是\nIn other words, what the evaluator's doing\n\n247\n00:12:18,620 --> 00:12:22,768\n分析代码需要进行的运算\nis simultaneously analyzing the code to see what to do\n\n248\n00:12:23,470 --> 00:12:24,992\n同时并执行它们\nand running these operations.\n\n249\n00:12:25,550 --> 00:12:28,280\n当你运行求值器一百万次\nAnd when you-- if you run the evaluator a million times\n\n250\n00:12:28,280 --> 00:12:30,304\n这个分析过程就进行一百万次\nthat analysis phase happens a million times\n\n251\n00:12:30,850 --> 00:12:32,580\n而在编译器中 它只会进行一次\nwhereas in the compiler, it's happened once\n\n252\n00:12:32,580 --> 00:12:34,816\n之后就只有寄存器操作了\nand then you just have the register operations themselves.\n\n253\n00:12:39,200 --> 00:12:41,680\n这就是零阶编译器了\nOk, that's a, a zeroth-order compiler\n\n254\n00:12:41,800 --> 00:12:44,048\n但它是个拙劣的编译器\nbut it is a wretched, wretched compiler.\n\n255\n00:12:44,450 --> 00:12:45,280\n它挺蠢的\nIt's really dumb.\n\n256\n00:12:46,900 --> 00:12:48,416\n让我们回过头来\nLet's--let's go back and,\n\n257\n00:12:49,888 --> 00:12:50,976\n看看这张投影\nand look at this overhead.\n\n258\n00:12:52,020 --> 00:12:55,296\n看看这个东西做的一些操作\nSo look at look at some of the operations this thing is doing.\n\n259\n00:12:55,850 --> 00:12:56,880\n我们想看看\nWe're supposedly\n\n260\n00:12:59,728 --> 00:13:02,288\n在解释(F  X)时的操作\nlooking at the operations in interpreting f of x.\n\n261\n00:13:03,520 --> 00:13:04,848\n这里就是它做了什么\nNow, look here what it's doing.\n\n262\n00:13:05,170 --> 00:13:06,112\n举个例子 这里\nFor example, here\n\n263\n00:13:07,150 --> 00:13:11,984\n它将(OPERATOR (FETCH EXP))赋值给EXP\nit assigns to exp the operator in fetch of exp.\n\n264\n00:13:13,750 --> 00:13:15,872\n其实没必要这样做\nBut see, there's no reason to do that, because this is--\n\n265\n00:13:16,220 --> 00:13:17,472\n因为编译器知道\nthe compiler knows\n\n266\n00:13:17,660 --> 00:13:21,840\n(OPERATOR (FETCH EXP))的值就是F\nthat the operator, fetch of exp,  is f right here.\n\n267\n00:13:23,350 --> 00:13:25,568\n因此这个指令没理由存在\nSo there's no reason why this instruction should say that.\n\n268\n00:13:25,700 --> 00:13:28,880\n应该改为：要把F赋值给EXP\nIt should say, we'll assign to exp, f.\n\n269\n00:13:29,450 --> 00:13:31,088\n或者实际上 你完全不需要EXP\nOr in fact, you don't need exp at all.\n\n270\n00:13:31,875 --> 00:13:33,560\n没有理由需要EXP\nThere's no reason it should have exp at all.\n\n271\n00:13:33,560 --> 00:13:35,168\nEXP是用来做什么的?\nWhat, what did exp get used for?\n\n272\n00:13:35,184 --> 00:13:36,330\n我们看这里\nWell, if we come down here\n\n273\n00:13:40,770 --> 00:13:42,208\n我们对VAL赋值\nwe're going to assign to val\n\n274\n00:13:43,050 --> 00:13:47,344\n在环境里的EXP里寻找东西\nlook up the stuff in exp in the environment.\n\n275\n00:13:48,680 --> 00:13:49,536\n因此 我们实际上是要\nSo what we really should do\n\n276\n00:13:49,552 --> 00:13:51,540\n替换掉所有的EXP寄存器\nget rid of the exp register altogether\n\n277\n00:13:51,540 --> 00:13:53,328\n把这个指令修改为\nand just change this instruction to say,\n\n278\n00:13:53,344 --> 00:13:54,160\n给VAL赋值\nassign to val\n\n279\n00:13:54,450 --> 00:13:56,064\n在环境中查找\nlook up the variable value\n\n280\n00:13:56,368 --> 00:13:58,400\n符号F的值\nof the symbol f in the environment.\n\n281\n00:14:01,090 --> 00:14:01,776\n类似地\nSimilarly\n\n282\n00:14:02,570 --> 00:14:04,272\n回到这里 我们也完全不需要UNEV\nback up here, we don't need unev at all\n\n283\n00:14:04,720 --> 00:14:05,792\n因为我们知道\nbecause we know\n\n284\n00:14:06,225 --> 00:14:09,160\n因为我们知道 (FETCH EXP)取出的运算对象\nwhat the operands of fetch of exp are for this piece of code.\n\n285\n00:14:09,160 --> 00:14:10,624\n就是'(X)\nIt's the, it's the list x.\n\n286\n00:14:13,250 --> 00:14:14,064\n从某种意义上来说\nSo in some sense\n\n287\n00:14:16,170 --> 00:14:19,392\n你完全不需要UNEV和EXP\nyou don't want unev and exp at all.\n\n288\n00:14:19,670 --> 00:14:21,056\n看看它们实际上是什么\nSee, what they really are in some sense,\n\n289\n00:14:21,088 --> 00:14:25,300\n它们不是实际运行机器的寄存器\nthose aren't registers of the actual machine that's supposed to run.\n\n290\n00:14:25,300 --> 00:14:26,400\n它们实际上是\nThose are registers\n\n291\n00:14:26,608 --> 00:14:29,504\n为了模拟该机器的而设置的寄存器\nthat have to do with arranging the thing that can simulate that machine.\n\n292\n00:14:30,720 --> 00:14:33,776\n所以它们保存一些表达式\nSo they're always going to hold expressions\n\n293\n00:14:34,000 --> 00:14:36,048\n以编译器的视角看来\nwhich from the compiler's point of view,\n\n294\n00:14:36,064 --> 00:14:36,816\n它们就是常量\nare just constants,\n\n295\n00:14:36,950 --> 00:14:38,480\n因此可以直接把它们放到代码中\nso can be put right into the code.\n\n296\n00:14:39,470 --> 00:14:41,344\n你可以忘掉那些关于\nSo you can forget about all the operations\n\n297\n00:14:41,360 --> 00:14:42,544\nEXP和UNEV的操作\nworrying about exp and unev\n\n298\n00:14:42,576 --> 00:14:43,776\n只用那些常量\nand just use those constants.\n\n299\n00:14:44,025 --> 00:14:48,000\n与之相似 如果我们回顾这里\nSimilarly, again, if we go, go back and look here\n\n300\n00:14:48,000 --> 00:14:51,328\n有像(ASSIGN CONTINUE EVAL-ARGS)之类的语句\nthere are things like assign to continue eval-args.\n\n301\n00:14:53,750 --> 00:14:55,392\n现在 它和任何东西都没有关系\nNow, that has nothing to do with anything.\n\n302\n00:14:55,620 --> 00:14:57,760\n它只是求值器\nThat was just the evaluator\n\n303\n00:14:58,080 --> 00:15:00,176\n维护了下一步需要去哪\nkeeping track of where it should go next\n\n304\n00:15:02,700 --> 00:15:05,968\n在某些应用中对参数进行求值\nto evaluate the arguments in some, in some application.\n\n305\n00:15:06,825 --> 00:15:08,650\n当然 这与编译器没关系\nBut of course, that's irrelevant to the compiler,\n\n306\n00:15:08,650 --> 00:15:13,888\n因为这个分析过程已经被编译器做完了\nbecause you-- the analysis phase will have already done that.\n\n307\n00:15:15,050 --> 00:15:16,832\n所以编译后的代码完全不需要它\nSo this is completely irrelevant.\n\n308\n00:15:17,700 --> 00:15:19,328\n因此许多向CONTINUE寄存器\nSo a lot of these, these assignments\n\n309\n00:15:19,328 --> 00:15:21,300\n赋值的操作都是无用的\nto continue have not to do\n\n310\n00:15:21,300 --> 00:15:24,624\n运行着的机器留着它们\nwhere the running machine is supposed to continue\n\n311\n00:15:24,640 --> 00:15:25,776\n是为了跟踪它的状态\nin keeping track of its state.\n\n312\n00:15:26,075 --> 00:15:28,725\n是为了知道求值器的下一步分析\nIt has to, to do with where the evaluator analysis should continue\n\n313\n00:15:28,720 --> 00:15:30,032\n而它们是完全无关的\nand those are completely irrelevant.\n\n314\n00:15:30,064 --> 00:15:31,232\n因此我们可以去掉它们\nSo we can get rid of them.\n\n315\n00:15:43,900 --> 00:15:45,984\n那么 如果我们简单地\nOk, well, if we, if we simply do that,\n\n316\n00:15:46,160 --> 00:15:47,750\n进行这类优化\nmake those kinds of optimizations\n\n317\n00:15:47,750 --> 00:15:51,648\n不再考虑EXP和UNEV\nget rid, get rid of worrying about exp and unev\n\n318\n00:15:51,750 --> 00:15:56,224\n去掉这些无关的寄存器赋值\nand get rid of these irrelevant register assignments to continue\n\n319\n00:15:57,250 --> 00:15:59,968\n我们就可以找到这些代码\nthen we can take this literal code\n\n320\n00:16:01,480 --> 00:16:06,208\n也就是求值器会执行的这19条指令\nthese sort of 19 instructions that the evaluator would have done\n\n321\n00:16:06,912 --> 00:16:08,128\n给替换掉\nand then replace them.\n\n322\n00:16:08,360 --> 00:16:10,336\n请看幻灯片\nLet's look at the, at the slide.\n\n323\n00:16:12,270 --> 00:16:15,344\n我们去掉了大概一半\nReplace them by--we get rid of about half of them.\n\n324\n00:16:18,288 --> 00:16:20,752\n同样 这就是某种过滤\nAnd again, this is just sort of filtering\n\n325\n00:16:21,070 --> 00:16:24,464\n把无关的东西去掉\nwhat the evaluator would have done by getting rid of the irrelevant stuff.\n\n326\n00:16:25,170 --> 00:16:26,224\n你们看 比如说\nAnd you see, for instance\n\n327\n00:16:27,470 --> 00:16:29,664\n这里 求值器说\nhere the--where the evaluator said,\n\n328\n00:16:29,680 --> 00:16:32,432\n(ASSIGN VAL (LOOKUP 'F (FETCH ENV)))\nassign val, look up variable value, fetch of exp\n\n329\n00:16:32,464 --> 00:16:34,224\n这里 我们放入了一个常量F\nhere we have put in the constant f.\n\n330\n00:16:35,440 --> 00:16:37,024\n这里又放了一个常量X\nHere we've put in the constant x.\n\n331\n00:16:40,020 --> 00:16:42,416\n因此 这个编译器又稍微好一点\nSo there's a, there's a little better compiler.\n\n332\n00:16:43,790 --> 00:16:46,768\n但它还是比较蠢\nIt's still pretty dumb.\n\n333\n00:16:47,950 --> 00:16:49,584\n它仍会做很多蠢事\nIt's still doing a lot of dumb things.\n\n334\n00:16:50,450 --> 00:16:52,528\n我们再看幻灯片\nAgain, if we go look at the slide again\n\n335\n00:16:52,880 --> 00:16:53,936\n看最开头的地方\nlook at the very beginning here\n\n336\n00:16:56,340 --> 00:16:58,176\n我们调用(SAVE ENV)保存环境\nwe see a save the environment\n\n337\n00:16:59,350 --> 00:17:01,728\n然后给VAL寄存器赋某个值\nassign something to the val register\n\n338\n00:17:01,800 --> 00:17:03,350\n然后恢复环境\nand restore the environment.\n\n339\n00:17:03,350 --> 00:17:04,416\n它是从哪来的\nWhere'd that come from?\n\n340\n00:17:04,910 --> 00:17:07,104\n它来自求值器的这个地方\nThat came from the evaluator back here saying\n\n341\n00:17:07,152 --> 00:17:10,288\n哦 我在正在对一个应用求值\noh, I'm in the middle of evaluating an application.\n\n342\n00:17:11,100 --> 00:17:14,688\n因此我要递归调用EVAL-DISPATCH\nSo I'm going to recursively call eval dispatch.\n\n343\n00:17:15,872 --> 00:17:17,984\n我最好把接下来要用到的东西\nSo I'd better save the thing I'm going to need later,\n\n344\n00:17:17,984 --> 00:17:19,088\n保存到环境中\nwhich is the environment.\n\n345\n00:17:19,770 --> 00:17:22,864\n这就是递归调用EVAL-DISPATCH的结果\nThis was the result of recursively calling eval dispatch.\n\n346\n00:17:23,472 --> 00:17:25,776\n刚才那个例子就是对符号F求值的结果\nIt was evaluating the symbol f in that case.\n\n347\n00:17:26,500 --> 00:17:28,272\n从EVAL-DISPATCH中返回\nThen it came back from eval dispatch,\n\n348\n00:17:28,288 --> 00:17:29,664\n将环境恢复\nrestored the environment.\n\n349\n00:17:31,250 --> 00:17:32,288\n但是实际上\nBut in fact,\n\n350\n00:17:32,590 --> 00:17:35,888\n这个求值过程中 所进行的操作\nthe actual thing it ended up doing in the evaluation\n\n351\n00:17:35,920 --> 00:17:37,712\n完全不会影响环境\nis not going to hurt the environment at all.\n\n352\n00:17:38,670 --> 00:17:40,800\n所以这里没必要先保存环境\nSo there's no reason to be saving the environment\n\n353\n00:17:40,848 --> 00:17:42,220\n再恢复环境\nand restoring the environment here.\n\n354\n00:17:45,670 --> 00:17:46,624\n与之类似\nSimilarly\n\n355\n00:17:49,792 --> 00:17:51,392\n这里 我们保存了参数表\nhere I'm saving the argument list.\n\n356\n00:17:53,070 --> 00:17:55,808\n那是一个求值参数的循环\nThat's a piece of the argument evaluation loop,\n\n357\n00:17:55,824 --> 00:17:56,864\n先保存参数表\nsaving the argument list\n\n358\n00:17:57,200 --> 00:17:58,032\n然后在这里恢复\nand here you restore it.\n\n359\n00:17:58,080 --> 00:18:00,512\n但事实上最后\nBut the actual thing that you ended up doing\n\n360\n00:18:00,800 --> 00:18:02,288\n并没有变更参数表\ndidn't trash the argument list.\n\n361\n00:18:02,840 --> 00:18:04,176\n所以不需要保存它\nSo there was no reason to save it.\n\n362\n00:18:08,650 --> 00:18:12,880\n换种方式来说\nSo another way to say, another way to say that\n\n363\n00:18:13,770 --> 00:18:14,800\n怎么说呢\nis that the,\n\n364\n00:18:16,432 --> 00:18:19,136\n求值器需要最大限度地保持悲观\nthe evaluator has to be maximally pessimistic\n\n365\n00:18:19,870 --> 00:18:21,072\n因为 从它的视角来看\nbecause as far from its point of view\n\n366\n00:18:21,088 --> 00:18:23,060\n只知道接下来是要对某些东西进行求值\nit's just going off to evaluate something.\n\n367\n00:18:23,248 --> 00:18:24,976\n所以最好把稍后要用的都存下来\nSo it better save what it's going to need later.\n\n368\n00:18:26,120 --> 00:18:27,792\n一旦你完成了分析\nBut once you've done the analysis,\n\n369\n00:18:27,824 --> 00:18:29,680\n从编译器的角度就会考虑\nthe compiler is in a position to say\n\n370\n00:18:29,728 --> 00:18:31,472\n哪些是我真正需要存下来的?\nwell, what actually did I need to save?\n\n371\n00:18:32,120 --> 00:18:33,312\n我们需要去 --\nAnd doesn't need to do any--\n\n372\n00:18:33,424 --> 00:18:37,300\n它不需要像求值器一样小心翼翼\nit doesn't need to be as careful as the evaluator\n\n373\n00:18:37,300 --> 00:18:38,800\n因为它知道 实际需要什么\nbecause it knows what it actually needs\n\n374\n00:18:39,690 --> 00:18:41,168\n无论如何 如果我们完成了优化\nWell, in any case, if we do that\n\n375\n00:18:42,500 --> 00:18:45,712\n消除掉所有多余的保存和恢复\nand eliminate all those redundant saves and restores\n\n376\n00:18:46,400 --> 00:18:49,056\n那么我们可以得到这样的结果\nthen we can get it down to this.\n\n377\n00:18:49,900 --> 00:18:51,536\n我们可以发现\nAnd you see there are actually only three\n\n378\n00:18:51,648 --> 00:18:53,712\n只有三条指令是必须的\nonly three instructions that we actually need\n\n379\n00:18:54,070 --> 00:18:55,728\n从刚才的11条指令优化成这样\ndown from the initial 11 or so\n\n380\n00:18:55,970 --> 00:18:58,816\n或是从原始的20条指令优化而来\nor the initial 20 or so in the original one.\n\n381\n00:18:59,870 --> 00:19:00,928\n这告诉我们\nAnd that's just saying,\n\n382\n00:19:01,120 --> 00:19:03,184\n对于这些寄存器操作\nof those register operations\n\n383\n00:19:03,270 --> 00:19:04,944\n哪些是必需的?\nwhich ones did we actually need?\n\n384\n00:19:09,420 --> 00:19:11,744\n让我换个方式来总结一下\nLet me just sort of summarize that in another way,\n\n385\n00:19:11,744 --> 00:19:13,488\n我先给你们看一张图\njust to show you in a little better picture.\n\n386\n00:19:16,000 --> 00:19:17,520\n这张图片\nHere's a picture of starting--\n\n387\n00:19:18,770 --> 00:19:20,816\n展示了所有的保存和恢复\nThis is looking at all the saves and restores.\n\n388\n00:19:23,500 --> 00:19:25,232\n这里是表达式(F X)\nSo here's the expression, f of x\n\n389\n00:19:25,320 --> 00:19:27,872\n在下面这里\nand then this traces through, on the bottom here\n\n390\n00:19:28,750 --> 00:19:31,808\n是对求值器中各种地方的跟踪\nthe various places in the evaluator\n\n391\n00:19:34,975 --> 00:19:38,040\n在求值发生时会使用这些地方\nthat were passed when the evaluation happened.\n\n392\n00:19:38,040 --> 00:19:40,016\n在这里 你可以看到箭头\nAnd then here, here you see arrows.\n\n393\n00:19:40,220 --> 00:19:42,080\n下箭头代表寄存器的保存\nArrow down means register saved.\n\n394\n00:19:42,400 --> 00:19:44,848\n所以最先保存的是ENV寄存器\nSo the first thing that happened is the environment got saved.\n\n395\n00:19:46,820 --> 00:19:48,688\n然后 在这里恢复ENV\nAnd over here, the environment got restored.\n\n396\n00:19:52,384 --> 00:19:54,540\n这些都是成对的栈操作\nso there are all the pairs of stack operations.\n\n397\n00:19:56,120 --> 00:19:57,568\n如果你更进一步\nNow, if you go ahead and say\n\n398\n00:19:58,125 --> 00:20:00,780\n我们记得\nwell, let's remember that we don't--that unev\n\n399\n00:20:00,896 --> 00:20:03,024\nUNEV是个完全没用的寄存器\nfor instance, is a completely useless register.\n\n400\n00:20:07,800 --> 00:20:09,780\n如果我们用固定结构的代码\nAnd if we use the constant structure of the code\n\n401\n00:20:09,780 --> 00:20:12,528\n就不需要保存UNEV 因为完全用不上\nwell, we don't need, we don't need to save unev.\n\n402\n00:20:16,200 --> 00:20:19,152\n然后 根据我们约定的\nAnd then, depending on how we set up the discipline of the--\n\n403\n00:20:19,160 --> 00:20:21,888\n应用过程的准则\nof calling other things that apply,\n\n404\n00:20:21,888 --> 00:20:23,850\n我们会选择是否保存CONTINUE\nwe may or may not need to save continue.\n\n405\n00:20:27,400 --> 00:20:28,740\n这就是我们做的第一件事\nThat's the first step I did.\n\n406\n00:20:28,740 --> 00:20:30,512\n然后我们可以看看\nAnd then we can look and see what's actually,\n\n407\n00:20:31,712 --> 00:20:32,704\n实际需要些什么\nwhat's actually needed.\n\n408\n00:20:33,070 --> 00:20:35,568\n其实在求值F的过程中\nSee, we don't-- didn't really need to save env\n\n409\n00:20:36,040 --> 00:20:37,824\n我们不需要保存ENV\nacross-evaluating f\n\n410\n00:20:38,088 --> 00:20:39,920\n因为它不会被破坏\nbecause it wouldn't, it wouldn't trash it.\n\n411\n00:20:39,920 --> 00:20:41,312\n因此 如果我们利用这点\nSo if we take advantage of that\n\n412\n00:20:44,120 --> 00:20:47,568\n这里对F的求值\nand see the evaluation of f here\n\n413\n00:20:48,570 --> 00:20:50,448\n完全不需要担心\ndoesn't really need to worry about,\n\n414\n00:20:51,616 --> 00:20:52,600\n会破坏ENV\nabout hurting env.\n\n415\n00:20:52,600 --> 00:20:54,944\n类似地 这里对X的求值\nAnd similarly, the evaluation of x here\n\n416\n00:20:57,170 --> 00:20:58,896\n当求值器进行求值时 它会说\nwhen the evaluator did that it said\n\n417\n00:20:58,912 --> 00:21:01,648\n我最好保存好与之有关的FUN寄存器\nOh, I'd better preserve the function register around that\n\n418\n00:21:02,072 --> 00:21:03,220\n因为后面也许会用得着\nbecause I might need it later.\n\n419\n00:21:03,280 --> 00:21:04,896\n我最好也保存参数表\nAnd I better preserve the argument list.\n\n420\n00:21:06,900 --> 00:21:09,056\n然而 在这如果是编译器的话\nWhereas the compiler is now in a position to know\n\n421\n00:21:09,050 --> 00:21:10,384\n实际需要哪些寄存器\nwell, we didn't really need to save--\n\n422\n00:21:10,528 --> 00:21:11,840\n从而进行相关的保存与恢复\nto do those saves and restores.\n\n423\n00:21:12,700 --> 00:21:16,096\n事实上 这里求值器做的所有栈操作\nSo in fact, all of the stack operations done by the evaluator\n\n424\n00:21:16,320 --> 00:21:19,584\n都证明是过于悲观而不必要\nturned out to be unnecessary or overly pessimistic.\n\n425\n00:21:19,620 --> 00:21:21,456\n而编译器在这里是知道这一点的\nAnd the compiler is in a position to know that.\n\n426\n00:21:27,350 --> 00:21:28,480\n这是最基础的想法\nWell that's the basic idea.\n\n427\n00:21:29,800 --> 00:21:31,000\n我们把求值器\nWe take the evaluator\n\n428\n00:21:31,000 --> 00:21:33,240\n剔除那些不需要的东西\nwe eliminate the things that you don't need\n\n429\n00:21:33,240 --> 00:21:35,240\n去除那些对于编译器完全无用的东西\nthat in some sense have nothing to do with the compiler at all\n\n430\n00:21:35,240 --> 00:21:36,192\n只保留求值的部分\njust the evaluator\n\n431\n00:21:37,408 --> 00:21:40,400\n然后你可以看到哪些栈操作是不必要的\nand then you see which stack operations are unnecessary.\n\n432\n00:21:40,820 --> 00:21:43,760\n这就是书中所描述的编译器\nThat's the basic structure of the compiler that's\n\n433\n00:21:43,856 --> 00:21:45,040\n的基本结构\nthat's described in the book.\n\n434\n00:21:45,040 --> 00:21:47,008\n我给你们展示一下这\nLet me just show you how a\n\n435\n00:21:47,760 --> 00:21:49,680\n这个简单的例子\nthat examples a little bit too simple.\n\n436\n00:21:51,200 --> 00:21:53,264\n为了说清楚 多余的东西是怎样保存的\nTo see how you, how you actually save a lot\n\n437\n00:21:53,296 --> 00:21:56,064\n我们来看一个稍复杂的表达式\nlet's look at a little bit more complicated expression.\n\n438\n00:21:58,150 --> 00:22:01,936\n(F (G X) 1)\n(F (G X) 1)\n\n439\n00:22:03,870 --> 00:22:05,520\n我们不会讲解所有的代码\nAnd I'm not going to go through all the code.\n\n440\n00:22:06,400 --> 00:22:08,560\n因为代码有点多\nThere's a, there's a fair pile of it.\n\n441\n00:22:09,725 --> 00:22:12,350\n我认为在求值器在处理它时\nI think there are, there are something like 16\n\n442\n00:22:12,350 --> 00:22:14,672\n大概会产生\n16 pairs of register saves and restores\n\n443\n00:22:14,704 --> 00:22:16,256\n16对保存-恢复操作\nas the evaluator walks through that.\n\n444\n00:22:17,000 --> 00:22:18,576\n这有一张图表\nHere's a diagram of them.\n\n445\n00:22:20,570 --> 00:22:21,952\n演示了其中的过程\nLet's see. You see what's going on.\n\n446\n00:22:22,970 --> 00:22:23,904\n你从这里开始--\nYou start out by--\n\n447\n00:22:24,250 --> 00:22:26,624\n求值器说：“我要求值一个应用”\nthe evaluator says, oh, I'm about to do an application.\n\n448\n00:22:26,900 --> 00:22:29,136\n在这里保存ENV 又在这里恢复\nI'll preserve the environment. I'll restore it here.\n\n449\n00:22:30,650 --> 00:22:34,448\n然后处理第一个运算对象\nThen I'm about to do the first operand.\n\n450\n00:22:36,816 --> 00:22:39,280\n这是求值器的递归调用\nHere it recursively goes to the evaluator.\n\n451\n00:22:39,280 --> 00:22:40,896\n求值器发现 这是一个应用\nThe evaluator says, oh, this is an application,\n\n452\n00:22:40,912 --> 00:22:42,100\n又会保存环境\nI'll save the environment\n\n453\n00:22:42,100 --> 00:22:44,976\n求值组合式的运算符 然后在这里恢复环境\ndo the operator of that combination, restore it here.\n\n454\n00:22:45,800 --> 00:22:48,928\n这个恢复匹配的是这个保存操作\nThis save--this restore matches that save.\n\n455\n00:22:49,770 --> 00:22:50,784\n以此类推\nAnd so on.\n\n456\n00:22:51,650 --> 00:22:52,512\n这里的UNEV\nThere's unev here,\n\n457\n00:22:52,528 --> 00:22:54,620\n完全没有必要存在\nwhich turns out to be completely unnecessary\n\n458\n00:22:54,970 --> 00:22:56,608\nCONTINUE寄存器不断地被保存-恢复\ncontinues getting bumped around here.\n\n459\n00:22:57,420 --> 00:23:00,416\n而FUN寄存器则是在\nThe function register is getting, getting saved\n\n460\n00:23:00,784 --> 00:23:04,368\n处理运算对象期间被保存\nacross the first operands, across the operands.\n\n461\n00:23:05,100 --> 00:23:06,528\n这类的事情一直在发生\nAll sorts of things are going on.\n\n462\n00:23:06,782 --> 00:23:09,390\n但如果你问 跟求值器相比\nBut if you say, well, what of those really were the business of\n\n463\n00:23:09,872 --> 00:23:11,664\n编译器究竟要做什么？\nthe compiler as opposed to the evaluator\n\n464\n00:23:12,270 --> 00:23:13,552\n你会去掉一大堆东西\nyou get rid of a whole bunch.\n\n465\n00:23:14,300 --> 00:23:16,640\n在这个的基础上 如果你说\nAnd then on top of that, if you say things like\n\n466\n00:23:19,400 --> 00:23:22,544\n对F的求值不会修改ENV寄存器\nthe evaluation of F doesn't hurt the environment register,\n\n467\n00:23:23,820 --> 00:23:26,512\n或者对符号X的查找\nor simply looking up the symbol X,\n\n468\n00:23:29,280 --> 00:23:32,096\n不需要特别保护FUN寄存器\nyou don't have to protect the function register against that.\n\n469\n00:23:34,300 --> 00:23:37,600\n就得到了只有几对的保存-恢复操作\nSo you come down to just a couple of, a couple of pairs here.\n\n470\n00:23:40,250 --> 00:23:42,275\n然而 你还可以再优化一下\nAnd still, you can do a little better.\n\n471\n00:23:42,275 --> 00:23:44,330\n看看这里的ENV寄存器发生了什么\nLook what's going on here with the environment register.\n\n472\n00:23:45,210 --> 00:23:47,392\n我们观察ENV寄存器的操作 发现\nThe environment register comes along and says, oh,\n\n473\n00:23:51,000 --> 00:23:52,256\n这是一个组合式\nhere's a combination.\n\n474\n00:23:54,336 --> 00:23:55,696\n而这个求值器\nThis evaluator, by the way,\n\n475\n00:23:55,780 --> 00:23:57,270\n对G一无所知\ndoesn't know anything about G.\n\n476\n00:23:58,570 --> 00:24:00,736\n所以在这 它说\nSo here it says, so it says,\n\n477\n00:24:01,296 --> 00:24:03,456\n我最好保存ENV寄存器\nI'd better save the environment register,\n\n478\n00:24:03,968 --> 00:24:05,424\n因为对G的求值\nbecause evaluating G might be\n\n479\n00:24:05,424 --> 00:24:07,424\n可能会修改ENV寄存器的值\nsome arbitrary piece of code that would trash it\n\n480\n00:24:07,550 --> 00:24:09,456\n而我稍后可能会需要它\nand I'm going to need it later,\n\n481\n00:24:10,176 --> 00:24:11,408\n在这个参数之后\nafter this argument,\n\n482\n00:24:12,224 --> 00:24:13,376\n在处理第二个参数的时候\nfor doing the second argument.\n\n483\n00:24:15,600 --> 00:24:17,248\n这就是为什么它没被优化掉\nSo that's why this one didn't go away,\n\n484\n00:24:19,075 --> 00:24:22,540\n因为编译器没有对G将要做的事情做任何假设\nbecause the compiler made no assumptions about what G would do.\n\n485\n00:24:22,540 --> 00:24:23,600\n另一方面\nOn the other hand,\n\n486\n00:24:24,610 --> 00:24:26,528\n如果你看看这里的第二个参数\nif you look at what the second argument is,\n\n487\n00:24:26,640 --> 00:24:27,700\n它只是查找“1”这个常量\nthat's just looking up one.\n\n488\n00:24:27,700 --> 00:24:29,600\n这不需要ENV寄存器\nThat doesn't need this environment register.\n\n489\n00:24:30,770 --> 00:24:32,048\n因此没必要保存它\nSo there's no reason to save it.\n\n490\n00:24:32,064 --> 00:24:33,776\n事实上 你也可以把这个也去掉\nSo in fact, you can get rid of that one, too.\n\n491\n00:24:34,850 --> 00:24:37,810\n这一堆寄存器操作\nAnd from this whole pile of, of register operations,\n\n492\n00:24:37,984 --> 00:24:40,080\n如果你像这样简单地推理的话\nif you simply do a little bit of reasoning like that,\n\n493\n00:24:40,550 --> 00:24:43,056\n只会剩下两对保存-恢复操作\nyou get down to, I think, just two pairs of saves and restores.\n\n494\n00:24:45,104 --> 00:24:46,976\n而这些 如果你知道关于G的某些信息的话\nAnd those, in fact, could go away further if you,\n\n495\n00:24:47,520 --> 00:24:49,088\n可以进一步优化\nif you knew something about G.\n\n496\n00:24:56,270 --> 00:24:57,856\n基本的理念是\nSo again, the general idea\n\n497\n00:24:57,950 --> 00:24:59,980\n编译器之所以更好\nis that the reason the compiler can be better\n\n498\n00:24:59,980 --> 00:25:02,560\n是因为解释器对于将要处理的东西一无所知\nis that the interpreter doesn't know what it's about to encounter.\n\n499\n00:25:03,250 --> 00:25:05,040\n它不得不以最悲观的方式保存东西\nIt has to be maximally pessimistic\n\n500\n00:25:05,056 --> 00:25:06,704\n来保护它自己\nto protect itself.\n\n501\n00:25:07,900 --> 00:25:08,768\n而编译器\nThe compiler\n\n502\n00:25:09,488 --> 00:25:12,384\n只需要保存实际需要的东西\nonly has to deal with what actually had to be saved.\n\n503\n00:25:13,370 --> 00:25:15,200\n某个东西是否需要保存\nAnd there are two reasons that something\n\n504\n00:25:15,248 --> 00:25:17,370\n有两种原因\nmight not have to be saved.\n\n505\n00:25:17,820 --> 00:25:18,700\n一种是\nOne is that\n\n506\n00:25:18,700 --> 00:25:19,824\n你保护的东西\nwhat you're protecting it against,\n\n507\n00:25:19,952 --> 00:25:21,440\n不会修改寄存器\nin fact, didn't trash the register,\n\n508\n00:25:22,080 --> 00:25:23,584\n例如 变量查找\nlike it was just a variable look-up.\n\n509\n00:25:24,120 --> 00:25:25,200\n另一种原因是\nAnd the other one is,\n\n510\n00:25:25,320 --> 00:25:27,104\n你所保存的东西\nthat the thing that you were saving it for\n\n511\n00:25:28,288 --> 00:25:29,920\n最后并不会被用到\nmight turn out not to actually need it.\n\n512\n00:25:30,810 --> 00:25:34,272\n因此 编译器正是利用了\nSo those are the two basic pieces of knowledge\n\n513\n00:25:34,304 --> 00:25:35,880\n这两条基本原则\nthat the compiler can take advantage of\n\n514\n00:25:36,272 --> 00:25:37,760\n来让代码变得更高效的\nin making the code more efficient.\n\n515\n00:25:44,270 --> 00:25:45,328\n有什么问题吗？\nLet's break for questions.\n\n516\n00:25:51,200 --> 00:25:53,100\n学生: 你一直在说UNEV寄存器\nAUDIENCE: You kept saying that the uneval register,\n\n517\n00:25:53,130 --> 00:25:56,400\nUNEV寄存器完全不会被用到\nunev register didn't need to be used at all.\n\n518\n00:25:56,416 --> 00:25:58,688\n是否意味着 机器只需要6个寄存器足矣？\nDoes that mean that you could just map a six-register machine?\n\n519\n00:25:58,700 --> 00:26:00,080\n或者是说 在这个特定的例子里\nOr is that, in this particular example,\n\n520\n00:26:00,112 --> 00:26:01,180\n它没有被用到？\nit didn't need to be used?\n\n521\n00:26:01,725 --> 00:26:02,810\n教授: 对于编译器\nPROFESSOR: For the compiler,\n\n522\n00:26:04,310 --> 00:26:07,424\n你可以生成6个或5个寄存器的代码\nyou could generate code for the six-register, five, right?\n\n523\n00:26:07,568 --> 00:26:09,024\n因为EXP寄存器也没有用到\nBecause that exp goes away also.\n\n524\n00:26:09,408 --> 00:26:14,570\n是的 你可以把EXP和UNEV都去掉\nAssuming--yeah, you can get rid of both exp and unev\n\n525\n00:26:14,575 --> 00:26:16,875\n因为这些是求值器的数据结构\nbecause, see, those are data structures of the evaluator.\n\n526\n00:26:17,360 --> 00:26:19,360\n以编译器的视角来看\nThose are all things that would be constants\n\n527\n00:26:19,392 --> 00:26:20,870\n这些东西都是常量\nfrom the point of view of the compiler.\n\n528\n00:26:21,650 --> 00:26:22,448\n关键在于\nThe only thing is\n\n529\n00:26:22,480 --> 00:26:24,592\n这个特定编译器是被构造出来的\nthis particular compiler is set up\n\n530\n00:26:24,790 --> 00:26:27,920\n因此被解释的代码和被编译的代码可以共存\nso that interpreted code and compiled code can coexist.\n\n531\n00:26:29,320 --> 00:26:30,720\n可以这样看待它\nSo the way to think about it is,\n\n532\n00:26:30,970 --> 00:26:32,290\n你构建了一个芯片\nis maybe you build a chip\n\n533\n00:26:34,300 --> 00:26:35,500\n它就是求值器\nwhich is the evaluator,\n\n534\n00:26:35,880 --> 00:26:37,280\n而编译器可以做的就是\nand what the compiler might do\n\n535\n00:26:37,312 --> 00:26:39,024\n为这个芯片生成代码\nis generate code for that chip.\n\n536\n00:26:40,400 --> 00:26:41,904\n只是它不会用到两个寄存器而已\nIt just wouldn't use two of the registers.\n\n537\n00:26:51,520 --> 00:26:52,470\n好 休息一会\nAll right, let's take a break.\n\n538\n00:26:53,550 --> 00:27:07,184\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n539\n00:27:07,370 --> 00:27:11,424\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n540\n00:27:14,570 --> 00:27:18,128\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n541\n00:27:18,170 --> 00:27:22,080\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n542\n00:27:22,220 --> 00:27:26,480\n编译\nCompilation\n\n543\n00:27:29,216 --> 00:27:32,432\n我们刚才研究了编译器应该要做什么\nWe just looked at what the compiler is supposed to do.\n\n544\n00:27:32,780 --> 00:27:36,048\n现在我们来简略地看看\nNow let's very briefly look at how,\n\n545\n00:27:36,150 --> 00:27:37,472\n这些目标如何达成\nhow this gets accomplished.\n\n546\n00:27:38,260 --> 00:27:39,584\n而我不会给出细节\nAnd I'm going to give no details.\n\n547\n00:27:39,600 --> 00:27:42,176\n在书中有一大堆代码\nThere's, there's a giant pile of code in the book\n\n548\n00:27:42,224 --> 00:27:43,420\n展示了所有细节\nthat gives all the details.\n\n549\n00:27:43,456 --> 00:27:45,310\n我要做的 是给你们展示\nBut what I want to do is just show you the,\n\n550\n00:27:45,968 --> 00:27:47,264\n其中的关键思想\nthe essential idea here.\n\n551\n00:27:49,490 --> 00:27:51,360\n换个时间再来关心细节\nWorry about the details some other time.\n\n552\n00:27:51,510 --> 00:27:55,300\n设想我们正在编译一条表达式\nLet's imagine that we're compiling an expression\n\n553\n00:27:55,300 --> 00:27:57,010\n这里有一些运算符\nthat looks like there's some operator\n\n554\n00:27:57,480 --> 00:27:58,560\n和两个参数\nand there are two arguments.\n\n555\n00:28:03,560 --> 00:28:04,240\n现在\nNow, the--\n\n556\n00:28:06,275 --> 00:28:08,140\n这个编译器会生成什么代码?\nwhat's the code that the compiler should generate?\n\n557\n00:28:08,850 --> 00:28:09,780\n首先\nWell, first of all,\n\n558\n00:28:09,830 --> 00:28:11,200\n它会递归运行\nit should recursively go off\n\n559\n00:28:11,900 --> 00:28:13,280\n编译运算符\nand compile the operator.\n\n560\n00:28:14,370 --> 00:28:19,024\n它说 我要编译运算符\nSo it says, I'll compile the operator.\n\n561\n00:28:21,160 --> 00:28:24,544\n最后我需要让它们的结果\nAnd where I'm going to need that\n\n562\n00:28:24,848 --> 00:28:27,950\n存放在FUN寄存器中\nis to be in the function register, eventually.\n\n563\n00:28:28,420 --> 00:28:29,600\n所以我编译一些指令\nSo I'll compile some instructions\n\n564\n00:28:29,648 --> 00:28:31,568\n它们会编译运算符\nthat will compile the operator\n\n565\n00:28:31,690 --> 00:28:38,624\n最后把结果放在FUN寄存器中\nand end up with the result in the function register.\n\n566\n00:28:45,510 --> 00:28:46,940\n接下来我要做的是\nThe next thing it's going to do,\n\n567\n00:28:47,710 --> 00:28:49,680\n另一个代码片段则说\nanother piece is to say,\n\n568\n00:28:49,680 --> 00:28:55,175\n我要编译第一个参数\nI have to compile the first argument.\n\n569\n00:28:55,170 --> 00:28:56,800\n因此它递归调地用自己\nSo it calls itself recursively.\n\n570\n00:28:58,040 --> 00:29:03,360\n而结果会被放在VAL中\nAnd let's say the result will go into val.\n\n571\n00:29:09,070 --> 00:29:10,750\n接下来需要做的是\nAnd then what it's going to need to do is\n\n572\n00:29:10,750 --> 00:29:12,260\n建立起参数表\nstart setting up the argument list.\n\n573\n00:29:12,950 --> 00:29:25,504\n(ASSIGN ARGL (CONS (FETCH --\nSo it'll say, assign to argl cons of fetch--\n\n574\n00:29:25,552 --> 00:29:27,104\n它会生成这些代码\nso it generates this literal instruction--\n\n575\n00:29:27,504 --> 00:29:32,512\n(FETCH VAL) '()))\nfetch of val onto empty list.\n\n576\n00:29:35,000 --> 00:29:36,050\n然而\nHowever,\n\n577\n00:29:37,990 --> 00:29:40,610\n当它到这里时\nit might have to work--  when it gets here,\n\n578\n00:29:41,325 --> 00:29:42,820\n它可能需要环境\nit's going to need the environment.\n\n579\n00:29:43,950 --> 00:29:45,296\n它需要环境\nIt's going to need whatever environment was here\n\n580\n00:29:45,328 --> 00:29:48,210\n这是求值第一个参数所需要的\nin order to do this evaluation of the first argument.\n\n581\n00:29:49,040 --> 00:29:51,184\n因此 它需要保证\nSo it has to ensure that\n\n582\n00:29:51,920 --> 00:29:53,760\n对运算对象的编译\nthe compilation of this operand,\n\n583\n00:29:55,320 --> 00:29:57,850\n或者说它需要保护FUN寄存器\nor it has to protect the function register\n\n584\n00:29:58,016 --> 00:30:00,980\n来应对编译运算对象时发生的各种情况\nagainst whatever might happen in the compilation of this operand.\n\n585\n00:30:01,300 --> 00:30:03,080\n因此它在这做了个标注说\nSo it puts a note here and says, oh,\n\n586\n00:30:03,370 --> 00:30:12,896\n这个片段需要保护ENV寄存器\nthis piece should be done preserving the environment register.\n\n587\n00:30:17,390 --> 00:30:18,448\n与之类似 这里\nSimilarly, here,\n\n588\n00:30:21,024 --> 00:30:23,300\n在完成第一个运算对象的编译后\nafter it gets done compiling the first operand,\n\n589\n00:30:23,570 --> 00:30:24,672\n它会说 我最好--\nit's going to say, I'd better--\n\n590\n00:30:24,710 --> 00:30:27,925\n我需要知道第二个运算对象的环境\nI'm going to need to know the environment for the second operand.\n\n591\n00:30:27,925 --> 00:30:29,460\n所以它在这做了个标注\nSo it puts a little note here, saying,\n\n592\n00:30:29,710 --> 00:30:35,968\n这里也需要保护ENV\nyeah, this is also done preserving env.\n\n593\n00:30:39,420 --> 00:30:41,020\n现在它继续运行\nNow it goes on and says, well,\n\n594\n00:30:41,120 --> 00:30:42,832\n下一段代码\nthe next chunk of code\n\n595\n00:30:43,312 --> 00:30:49,744\n是要编译第二个参数\nis the one that's going to compile the second argument.\n\n596\n00:30:50,820 --> 00:30:52,640\n它将会\nAnd let's say\n\n597\n00:30:52,992 --> 00:30:59,280\n把编译的结果按约定放入到VAL中\nAnd let's say it'll compile it with a targeted to val, as they say.\n\n598\n00:31:03,860 --> 00:31:06,704\n随后它会生成一条指令\nAnd then it'll generate the literal instruction,\n\n599\n00:31:07,840 --> 00:31:09,250\n从而建立起参数表\nbuilding up the argument list.\n\n600\n00:31:09,550 --> 00:31:15,280\n(ASSIGN ARGL\nSo it'll say, assign to argl\n\n601\n00:31:20,224 --> 00:31:28,944\n(CONS (FETCH VAL) (FETCH ARGL))\ncons of the new value it just got onto the old argument list.\n\n602\n00:31:33,970 --> 00:31:34,640\n然而\nHowever,\n\n603\n00:31:34,810 --> 00:31:36,580\n为了取得旧的参数表\nin order to have the old argument list,\n\n604\n00:31:37,150 --> 00:31:40,992\n它最好保证这期间发生的任何事情\nit better have arranged that the argument list didn't get trashed\n\n605\n00:31:41,300 --> 00:31:42,690\n都不影响旧的参数表\nby whatever happened in here.\n\n606\n00:31:43,500 --> 00:31:45,170\n因此它在这做了个标注说\nSo it puts a little note here and says,\n\n607\n00:31:45,344 --> 00:31:51,648\n哦 这里需要保护ARGL\noh, this has to be done preserving argl.\n\n608\n00:31:54,160 --> 00:31:56,030\n现在参数表就建立好了\nNow it's got the argument list set up.\n\n609\n00:31:58,016 --> 00:32:02,864\n现在可以准备去APPLY-DISPATCH了\nAnd it's all ready to go to apply dispatch.\n\n610\n00:32:07,020 --> 00:32:10,800\n它生成了这条指令\nIt generates this literal instruction.\n\n611\n00:32:15,190 --> 00:32:17,370\n因为现在参数都在ARGL中\nBecause now it's got the arguments in argl\n\n612\n00:32:18,150 --> 00:32:20,590\n运算符在FUN中\nand the operator in fun,\n\n613\n00:32:20,590 --> 00:32:22,890\n如果只是单纯地把运算符放到FUN寄存器中\nbut wait, it's only got the operator in fun\n\n614\n00:32:23,270 --> 00:32:26,640\n就需要它保证这块代码\nif it had ensured that this block of code\n\n615\n00:32:27,096 --> 00:32:29,270\n不会破坏FUN寄存器里的东西\ndidn't trash what was in the function register.\n\n616\n00:32:29,670 --> 00:32:31,248\n所以它在这做了个标注说\nSo it puts a little note here and says,\n\n617\n00:32:31,550 --> 00:32:32,736\n这里的所有东西\noh, yes, all this stuff here\n\n618\n00:32:34,880 --> 00:32:40,736\n最好能够在保护FUN寄存器的情况下完成\nhad better be done preserving the function register.\n\n619\n00:32:43,710 --> 00:32:46,150\n所以这就是--\nSo that's the little--so when it starts ticking--\n\n620\n00:32:46,150 --> 00:32:47,104\n基本上来说\nso basically, what the\n\n621\n00:32:48,200 --> 00:32:50,240\n编译器所做的就是\nwhat the compiler does is\n\n622\n00:32:50,544 --> 00:32:52,460\n追加一大堆的代码\nappend a whole bunch of code sequences.\n\n623\n00:32:53,500 --> 00:32:58,832\n而这些代码之中都是一些基本运算\nSee, what it's got in it is little primitive pieces of things\n\n624\n00:32:58,864 --> 00:33:00,128\n比如符号查找\nlike how to look up a symbol,\n\n625\n00:33:01,440 --> 00:33:02,608\n条件分支的处理\nhow to do a conditional.\n\n626\n00:33:02,640 --> 00:33:05,440\n都是一些琐碎的事情\nThose are all little pieces of things.\n\n627\n00:33:05,440 --> 00:33:07,990\n然后按照这种准则将它们追加到一起\nAnd then it appends them together in this sort of discipline.\n\n628\n00:33:08,780 --> 00:33:10,790\n因此 组合的基本手段就是\nSo the basic means of combining things\n\n629\n00:33:10,864 --> 00:33:13,184\n将一段代码追加到另一段的后面\nis to append two code sequences.\n\n630\n00:33:21,550 --> 00:33:22,864\n就是这里发生的事情\nThat's what's going on here.\n\n631\n00:33:25,580 --> 00:33:27,240\n这有点取巧\nAnd it's a little bit tricky.\n\n632\n00:33:27,560 --> 00:33:30,370\n向一段代码后面追加代码的思路是\nThe idea is that it appends two code sequences,\n\n633\n00:33:31,600 --> 00:33:33,760\n小心保护寄存器\ntaking care to preserve a register.\n\n634\n00:33:35,630 --> 00:33:37,930\n追加操作看起来像这样\nSo the actual append operation looks like this.\n\n635\n00:33:39,150 --> 00:33:40,656\n它要做的是\nWhat it wants to do is say, if--\n\n636\n00:33:41,200 --> 00:33:44,110\n代码的追加是这么来做的\nhere's what it means to append two code sequences.\n\n637\n00:33:44,530 --> 00:33:53,632\n如果SEQ1需要寄存器--\nSo if sequence one needs register--\n\n638\n00:33:53,664 --> 00:33:54,720\n我应该改一下这个\nI should change this.\n\n639\n00:33:54,725 --> 00:33:56,870\n在SEQ1后面追加SEQ2\nAppend sequence one to sequence two,\n\n640\n00:33:57,420 --> 00:34:03,968\n并保护一些寄存器\npreserving some register.\n\n641\n00:34:08,525 --> 00:34:09,910\n这里改成AND\nLet me say, and.\n\n642\n00:34:11,360 --> 00:34:13,030\n这样的话前后顺序就清楚了\nSo it's clear that sequence one comes first.\n\n643\n00:34:13,888 --> 00:34:19,870\n如果SEQ2需要寄存器\nSo if sequence two needs the register\n\n644\n00:34:21,120 --> 00:34:27,856\n而SEQ1又修改了寄存器\nand sequence one modifies the register,\n\n645\n00:34:33,680 --> 00:34:36,304\n那么编译器生成的指令是\nthen the instructions that the compiler spits out,\n\n646\n00:34:36,976 --> 00:34:41,344\n保存寄存器\nare save the register.\n\n647\n00:34:43,025 --> 00:34:44,190\n这就是代码\nHere's the code.\n\n648\n00:34:44,350 --> 00:34:45,350\n生成这段代码\nYou generate this code.\n\n649\n00:34:45,350 --> 00:34:46,288\n保存寄存器\nSave the register,\n\n650\n00:34:46,725 --> 00:34:52,975\n然后写下递归编译SEQ1的结果\nand then you put out the recursively compiled stuff for sequence one.\n\n651\n00:34:53,300 --> 00:34:54,848\n然后恢复寄存器\nAnd then you restore the register.\n\n652\n00:35:00,520 --> 00:35:03,920\n再写下递归编译\nAnd then you put out the recursively compiled stuff\n\n653\n00:35:04,464 --> 00:35:05,472\nSEQ2的结果\nfor sequence two.\n\n654\n00:35:07,075 --> 00:35:09,625\n这就是你需要做的\nThat's in the case where you need to do it.\n\n655\n00:35:09,625 --> 00:35:11,820\n实际上SEQ2需要寄存器\nSequence two actually needs the register,\n\n656\n00:35:11,820 --> 00:35:13,744\n而SEQ1改动了它\nand sequence one actually clobbers it.\n\n657\n00:35:15,120 --> 00:35:17,072\n否则的话\nSo that's sort of if. Otherwise,\n\n658\n00:35:20,500 --> 00:35:26,576\n得到的就是SEQ1后面跟着SEQ2\nall you spit out is sequence one followed by sequence two.\n\n659\n00:35:28,170 --> 00:35:30,304\n这就是把两个代码片段\nSo that's the basic operation\n\n660\n00:35:30,592 --> 00:35:33,520\n连接到一起的基本操作\nfor sticking together these bits of code fragments,\n\n661\n00:35:33,935 --> 00:35:35,935\n把这些指令组合成序列\nthese bits of instructions into a sequence.\n\n662\n00:35:36,890 --> 00:35:38,870\n我们可以发现 从这个角度看\nAnd you see, from this point of view,\n\n663\n00:35:40,940 --> 00:35:45,960\n解释器和编译器的区别\nthe difference between the interpreter and the compiler, in some sense,\n\n664\n00:35:46,825 --> 00:35:49,340\n是编译器有保护寄存器的标注\nis that where the compiler has these preserving notes,\n\n665\n00:35:50,140 --> 00:35:52,224\n上面记录着\nand says, maybe I'll actually generate the\n\n666\n00:35:52,496 --> 00:35:54,220\n是否需要生成保存-恢复代码\nsaves and restores and maybe I won't,\n\n667\n00:35:55,190 --> 00:35:57,248\n而解释器会以最悲观的方式处理\nthe interpreter being maximally pessimistic\n\n668\n00:35:57,280 --> 00:35:58,900\n总是会进行保存-恢复\nalways has a save and restore here.\n\n669\n00:36:00,768 --> 00:36:01,930\n这就是关键的区别\nThat's the essential difference.\n\n670\n00:36:04,160 --> 00:36:06,050\n为了实现这个\nWell, in order to do this, of course,\n\n671\n00:36:06,650 --> 00:36:09,408\n编译器需要一些理论\nthe compiler needs some theory of\n\n672\n00:36:09,568 --> 00:36:11,968\n来确定代码序列会需要、又会修改哪些寄存器\nwhat code sequences need and modifier registers.\n\n673\n00:36:14,260 --> 00:36:17,280\n所以你放入的小片段\nSo the tiny little fragments that you put in, like\n\n674\n00:36:17,480 --> 00:36:21,008\n例如这段基础代码\nthe basic primitive code fragments,\n\n675\n00:36:22,740 --> 00:36:24,592\n当你查找一个变量时\nsay, what are the operations that you do\n\n676\n00:36:24,928 --> 00:36:26,048\n进行了哪些操作？\nwhen you look up a variable?\n\n677\n00:36:26,890 --> 00:36:29,024\n你又是做了些什么\nWhat are the sequence of things that you do\n\n678\n00:36:29,056 --> 00:36:30,688\n来编译一个常量\nwhen you compile a constant\n\n679\n00:36:30,976 --> 00:36:32,100\n或者应用一个函数\nor apply a function?\n\n680\n00:36:32,970 --> 00:36:34,480\n它们都会带有一些标注\nThose have little notations in there\n\n681\n00:36:34,672 --> 00:36:36,464\n说明了它们需要的和修改的寄存器\nabout what they need and what they modify.\n\n682\n00:36:38,780 --> 00:36:41,500\n所以底层的数据结构\nSo the bottom-level data structures--\n\n683\n00:36:42,660 --> 00:36:44,330\n我会这样讲\nWell, I'll say this.\n\n684\n00:36:44,390 --> 00:36:47,910\n传递给编译器的代码序列大概是这样\nA code sequence to the compiler looks like this.\n\n685\n00:36:48,070 --> 00:36:51,424\n它里面有实际的指令序列\nIt has the actual sequence of instructions.\n\n686\n00:36:55,670 --> 00:36:56,816\n跟它一起的还有\nAnd then, along with it,\n\n687\n00:36:57,184 --> 00:37:02,608\n一组被修改的寄存器\nthere's the set of registers modified.\n\n688\n00:37:10,540 --> 00:37:12,608\n还有一组需要的寄存器\nAnd then there's the set of registers needed.\n\n689\n00:37:20,000 --> 00:37:22,464\n为了能够执行此操作\nSo that's the information the compiler has\n\n690\n00:37:23,000 --> 00:37:26,416\n编译器必须要掌握这些信息\nthat it draws on in order to be able to do this operation.\n\n691\n00:37:29,300 --> 00:37:31,088\n它们从哪来呢\nAnd where do those come from? Well.\n\n692\n00:37:32,910 --> 00:37:34,496\n它们来自于--你们可能也想到了\nWell, those come from, you might expect,\n\n693\n00:37:34,512 --> 00:37:35,536\n对于那些最基本的片段\nfor the very primitive ones,\n\n694\n00:37:35,552 --> 00:37:36,840\n我们会手工添加\nwe're going to put them in by hand.\n\n695\n00:37:37,240 --> 00:37:38,864\n然后 当我们组合两个序列时\nAnd then, when we combine two sequences,\n\n696\n00:37:38,896 --> 00:37:41,020\n我们会计算出这两个集合\nwe'll figure out what these things should be.\n\n697\n00:37:42,160 --> 00:37:44,128\n举一个非常基本的例子\nSo for example, a very primitive one, let's see.\n\n698\n00:37:48,430 --> 00:37:51,408\n例如做一个寄存器赋值\nHow about doing a register assignment.\n\n699\n00:37:51,770 --> 00:37:53,504\n因此 基本代码片段会说\nSo a primitive sequence might say,\n\n700\n00:37:53,520 --> 00:37:56,220\n噢 它是个代码片段\noh, it's code fragment.\n\n701\n00:37:56,225 --> 00:38:03,175\n代码的指令部分是(ASSIGN R1 (FETCH R2))\nIts code instruction is assigned to R1, fetch of R2.\n\n702\n00:38:03,170 --> 00:38:04,272\n这个例子就是这样的\nSo this is an example.\n\n703\n00:38:05,425 --> 00:38:08,520\n一段指令序列大概就是这样\nThat might be an example of a sequence of instructions.\n\n704\n00:38:08,770 --> 00:38:10,530\n和它在一起的是\nAnd along with that, it'll say, Oh\n\n705\n00:38:10,640 --> 00:38:15,760\n它需要记得修改了R1\noh, what I need to remember is that that modifies R1\n\n706\n00:38:18,600 --> 00:38:21,168\n然后它需要R2\nand then it needs R2.\n\n707\n00:38:24,690 --> 00:38:26,992\n因此当你开始构建编译器时\nSo when you're first building this compiler,\n\n708\n00:38:27,100 --> 00:38:29,350\n你放入这样的一个片段\nyou put in little fragments of stuff like that.\n\n709\n00:38:30,950 --> 00:38:33,200\n当它组合两个序列时\nAnd now, when it combines two sequences,\n\n710\n00:38:36,704 --> 00:38:38,048\n我要组合\nif I'm going to combine,\n\n711\n00:38:38,920 --> 00:38:41,584\n代码片段S1\nlet's say, sequence one,\n\n712\n00:38:42,880 --> 00:38:47,168\n修改了一组寄存器M1\nthat modifies a bunch of registers M1,\n\n713\n00:38:48,450 --> 00:38:51,420\n并且需要一组寄存器N1\nand needs a bunch of registers N1.\n\n714\n00:38:54,850 --> 00:38:59,488\n并且我要把它和序列S2组合到一起\nAnd I'm going to combine that with sequence two.\n\n715\n00:39:00,810 --> 00:39:05,968\n后者修改了一组寄存器M2\nThat modifies a bunch of registers M2,\n\n716\n00:39:07,110 --> 00:39:10,000\n并且需要一组寄存器N2\nand needs a bunch of registers N2.\n\n717\n00:39:12,440 --> 00:39:14,830\n这样我们就能得出结果\nThen, well, we can reason it out.\n\n718\n00:39:15,110 --> 00:39:16,320\n新的代码片段是这样的\nThe new code fragment,\n\n719\n00:39:17,184 --> 00:39:21,824\n指令序列S1后面跟着S2\nsequence one, and-- followed by sequence two,\n\n720\n00:39:24,090 --> 00:39:26,450\n它要修改什么?\nwell, what's it going to modify?\n\n721\n00:39:27,800 --> 00:39:29,184\n它要修改的是\nThe things that it will modify are the things\n\n722\n00:39:29,200 --> 00:39:32,688\n被S1或者被S2修改的寄存器\nthat are modified either by sequence one or sequence two.\n\n723\n00:39:34,000 --> 00:39:36,352\nN1和N2的并集\nSo the union of these two\n\n724\n00:39:37,680 --> 00:39:39,640\n就是新的修改集\nsets are what the new thing modifies.\n\n725\n00:39:40,460 --> 00:39:41,790\n然后你问\nAnd then you say, well, what is this--\n\n726\n00:39:44,660 --> 00:39:46,416\n又需要哪些寄存器？\nwhat registers is it going to need?\n\n727\n00:39:47,950 --> 00:39:49,776\n需要这些寄存器的是\nIt's going to need the things that are,\n\n728\n00:39:49,930 --> 00:39:51,850\n首先 一定是序列S1需要的\nfirst of all, needed by sequence one.\n\n729\n00:39:52,912 --> 00:39:54,496\n因此必然有N1\nSo what it needs is sequence one.\n\n730\n00:39:55,190 --> 00:39:58,288\n然后 并不是N2里面的所有元素\nAnd then, well, not quite all of the ones\n\n731\n00:39:58,320 --> 00:39:59,616\n我们都需要\nthat are needed by sequence two.\n\n732\n00:39:59,750 --> 00:40:03,490\n新的修改集需要N2中那些\nWhat it needs are the ones that are needed by sequence two\n\n733\n00:40:03,880 --> 00:40:06,880\n没有被S1修改过的寄存器\nthat have not been set up by sequence one.\n\n734\n00:40:08,140 --> 00:40:09,728\n所以 这个并集是N1并上\nSo it's sort of the union of\n\n735\n00:40:11,664 --> 00:40:13,408\n序列S2的需要集N2\nthe things that sequence two needs\n\n736\n00:40:14,512 --> 00:40:18,528\n减去序列S1的修改集M1\nminus the ones that sequence one modifies.\n\n737\n00:40:19,310 --> 00:40:20,880\n因为它关心的是如何设置它们\nBecause it worries about setting them up.\n\n738\n00:40:23,950 --> 00:40:26,260\n这就是编译器的基本结构\nSo there's the basic structure of the compiler.\n\n739\n00:40:26,700 --> 00:40:29,824\n我们进行寄存器优化的方式是\nThe way you do register optimizations is you\n\n740\n00:40:30,220 --> 00:40:32,704\n一些策略来应对需要保护的东西\nyou have some strategies for what needs to be preserved.\n\n741\n00:40:34,100 --> 00:40:35,632\n这取决于数据结构\nThat depends on a data structure.\n\n742\n00:40:35,728 --> 00:40:38,512\n这取决于将东西组合在一起的操作\nWell, it depends on the operation of what it means to put things together.\n\n743\n00:40:39,030 --> 00:40:41,632\n想知道要保护哪些东西\nPreserving something, that depends on knowing\n\n744\n00:40:41,930 --> 00:40:47,280\n就需要知道这段代码需要以及修改的寄存器\nwhat registers are needed and modified by these code fragments.\n\n745\n00:40:48,750 --> 00:40:51,260\n这就需要我们有一个数据结构\nThat depends on having little data structures,\n\n746\n00:40:51,424 --> 00:40:55,430\n它不但要存放实际的指令序列\nwhich say, a code sequence is the actual instructions,\n\n747\n00:40:55,600 --> 00:40:57,330\n它修改了什么 又需要什么\nwhat they modify and what they need.\n\n748\n00:40:57,330 --> 00:40:59,776\n这些信息来自于--最基本的情况是内置的\nThat comes from, at the primitive level, building it in.\n\n749\n00:40:59,790 --> 00:41:01,360\n对于最基本的情况\nAt the primitive level,\n\n750\n00:41:01,376 --> 00:41:02,528\n我们可以容易地知道\nit's going to be completely obvious\n\n751\n00:41:03,008 --> 00:41:04,448\n需要哪些寄存器 又修改了哪些\nwhat something needs and modifies.\n\n752\n00:41:04,820 --> 00:41:05,350\n另外\nPlus,\n\n753\n00:41:05,440 --> 00:41:08,608\n利用这个特定的方法构建复杂指令时\nthis particular way that says, when I build up bigger ones,\n\n754\n00:41:09,280 --> 00:41:11,890\n我们可以像这样生成新的修改集\nhere's how I generate the new set of registers modified\n\n755\n00:41:11,930 --> 00:41:13,370\n以及新的需要集\nand the new set of registers needed.\n\n756\n00:41:15,275 --> 00:41:17,770\n这就是全部的内容 -- 我不该这么说\nAnd that's the whole-- well, I shouldn't say that's the whole thing.\n\n757\n00:41:17,770 --> 00:41:19,344\n这就是书里面大概30页的细节\nThat's the whole thing except for about\n\n758\n00:41:19,744 --> 00:41:21,870\n的核心内容了\nabout 30 pages of details in the book.\n\n759\n00:41:22,310 --> 00:41:27,690\n但它是一个完全可用的初级编译器\nBut it is a perfectly usable rudimentary compiler.\n\n760\n00:41:28,760 --> 00:41:31,376\n让我给你展示一下它能做什么\nLet me kind of show you what it does.\n\n761\n00:41:31,392 --> 00:41:35,568\n假设我们从一个递归阶乘开始\nSuppose we start out with recursive factorial.\n\n762\n00:41:36,208 --> 00:41:38,608\n这些幻灯片的字太小不适合阅读\nAnd these slides are going to be much too small to read.\n\n763\n00:41:38,600 --> 00:41:39,792\n我只想快速翻一下代码\nI just want to flash through the code\n\n764\n00:41:39,792 --> 00:41:41,280\n让你们看看它有多少代码\nand show you about how much it is.\n\n765\n00:41:42,250 --> 00:41:43,296\n代码从这开始--\nThat starts out with--\n\n766\n00:41:44,320 --> 00:41:45,680\n这是代码的第一部分\nhere's a first block of it,\n\n767\n00:41:45,950 --> 00:41:47,680\n这里编译了一个过程入口\nwhere it compiles a procedure entry\n\n768\n00:41:47,696 --> 00:41:48,736\n并进行了一些赋值操作\nand does a bunch of assignments.\n\n769\n00:41:48,752 --> 00:41:51,488\n这基本上对应了解释器中\nAnd this thing is basically up through the part where\n\n770\n00:41:52,650 --> 00:41:53,904\n进行判断之前的部分\nsets up to do the predicate\n\n771\n00:41:54,310 --> 00:41:56,590\n并判断谓词是否成立\nand test whether the predicate's true.\n\n772\n00:41:56,970 --> 00:41:57,856\n第二部分是\nThe second part\n\n773\n00:41:58,460 --> 00:42:03,730\n递归调用N-1的阶乘的结果\nis what results from-- in the recursive call to fact of n minus one.\n\n774\n00:42:04,120 --> 00:42:05,056\n最后一部分是\nAnd this last part\n\n775\n00:42:06,070 --> 00:42:07,488\n从那里返回\nis coming back from that\n\n776\n00:42:07,872 --> 00:42:09,900\n并处理递归的基本情况\nand then taking care of the constant case.\n\n777\n00:42:09,900 --> 00:42:13,168\n这就是编译阶乘会生成的代码量\nSo that's about how much code it would produce for factorial.\n\n778\n00:42:13,720 --> 00:42:17,696\n当然 我们可以把这个编译器做得更好\nWe could make this compiler much, much better, of course.\n\n779\n00:42:18,675 --> 00:42:21,240\n优化它的主要方式是\nThe main way we could make it better is\n\n780\n00:42:21,240 --> 00:42:24,000\n当你调用一个过程时\nto allow the compiler to make any assumptions at all\n\n781\n00:42:24,352 --> 00:42:26,272\n允许编译器做任何假设\nabout what happens when you call a procedure.\n\n782\n00:42:26,970 --> 00:42:28,288\n举例来说\nSo this compiler, for instance,\n\n783\n00:42:28,300 --> 00:42:32,320\n这个编译器甚至不知道\ndoesn't even know, say, that multiplication\n\n784\n00:42:33,120 --> 00:42:36,140\n乘法可以被内联执行\nyou say, is something that could be coded in line.\n\n785\n00:42:36,144 --> 00:42:37,872\n它则会自行构建起整个机制\nInstead, it sets up this whole mechanism.\n\n786\n00:42:38,000 --> 00:42:39,344\n进行APPLY-DISPATCH\nIt goes to apply-dispatch.\n\n787\n00:42:41,370 --> 00:42:42,496\n这是极大的浪费\nThat's a tremendous waste,\n\n788\n00:42:42,544 --> 00:42:45,020\n因为 每当你进行APPLY-DISPATCH时\nbecause what you do every time you go to apply-dispatch\n\n789\n00:42:45,020 --> 00:42:46,800\n你都要关心这个参数表\nis you have to concern about this argument list,\n\n790\n00:42:47,400 --> 00:42:49,104\n因为它是个很普遍的操作\nbecause it's a very general thing you're going to.\n\n791\n00:42:49,136 --> 00:42:51,072\n在任何真实的编译器中\nIn any real compiler, of course,\n\n792\n00:42:51,088 --> 00:42:53,296\n你会有寄存器来暂存参数\nyou're going to have registers for holding arguments.\n\n793\n00:42:53,770 --> 00:42:55,312\n你要开始保护\nAnd you're going to start preserving\n\n794\n00:42:56,380 --> 00:42:58,050\n保存这些寄存器\nsaving the way you use those registers\n\n795\n00:42:58,050 --> 00:43:01,616\n和这里的策略相近\nsimilar to the same strategy here.\n\n796\n00:43:02,850 --> 00:43:05,936\n因此 我们可能主要通过这个方法\nSo that's probably the very main way\n\n797\n00:43:05,952 --> 00:43:08,300\n来优化书中这个特定的编译器\nthis particular compiler in the book could be fixed.\n\n798\n00:43:08,690 --> 00:43:09,700\n还有其它的一些方法\nThere are other things like\n\n799\n00:43:09,700 --> 00:43:11,824\n比如查找变量的值\nlooking up variable values and\n\n800\n00:43:11,830 --> 00:43:13,872\n使用更高效的基本操作\nmaking more efficient primitive operations,\n\n801\n00:43:13,888 --> 00:43:14,560\n等等方法\nand all sorts of things.\n\n802\n00:43:14,590 --> 00:43:16,608\n本质上来说 一个好的Lisp编译器\nEssentially, a good Lisp compiler\n\n803\n00:43:16,624 --> 00:43:18,496\n可以吸收任意数量的努力\ncan absorb an arbitrary amount of effort.\n\n804\n00:43:19,720 --> 00:43:21,632\n可能这其中的一个原因是\nAnd probably one of the reasons\n\n805\n00:43:21,890 --> 00:43:23,040\n跟FORTRAN这类语言相比\nLisp is slow\n\n806\n00:43:23,632 --> 00:43:25,440\nLisp就要慢一些\nwith compared to languages like FORTRAN\n\n807\n00:43:25,900 --> 00:43:28,192\n如果你回头审视历史\nis that, if you look over history\n\n808\n00:43:28,224 --> 00:43:31,120\n会发现人们为构建Lisp编译器而呕心沥血\nthe amount of effort that's gone into building Lisp compilers,\n\n809\n00:43:31,160 --> 00:43:32,352\n但也远远没有接近\nit's nowhere near the amount of effort\n\n810\n00:43:32,368 --> 00:43:33,900\n构建FORTRAN编译器的工作量\nthat's gone into FORTRAN compilers.\n\n811\n00:43:34,430 --> 00:43:35,792\n在接下来的几年\nAnd maybe that's something that will\n\n812\n00:43:35,920 --> 00:43:37,680\n情况可能会发生变化\nthat will change over the next couple of years.\n\n813\n00:43:38,000 --> 00:43:38,832\n好吧 就讲到这里\nOK, let's break.\n\n814\n00:43:43,800 --> 00:43:44,650\n有问题吗\nQuestions?\n\n815\n00:43:48,270 --> 00:43:49,950\n学生: 很早的一个课时里--\nAUDIENCE: One of the very first classes--\n\n816\n00:43:49,950 --> 00:43:51,408\n我不记得是课上还是课后--\nI don't know if it was during class or after class-\n\n817\n00:43:51,470 --> 00:43:53,888\n你向我们展示了\nyou showed me the, the\n\n818\n00:43:54,000 --> 00:43:57,520\nADD操作有一些我们看不到的基本运算\nsay, addition has a primitive that we don't see,\n\n819\n00:43:57,696 --> 00:43:59,216\n类似于ADD%之类的\nand-percent add or something like that.\n\n820\n00:43:59,825 --> 00:44:01,650\n这是因为\nIs that because,\n\n821\n00:44:01,650 --> 00:44:02,608\n你想把代码内联为\nif you're doing inline code\n\n822\n00:44:02,608 --> 00:44:08,192\n专门针对二元运算对象的运算么？\nyou'd want to just do it for two operators, operands?\n\n823\n00:44:08,700 --> 00:44:10,256\n但如果你有更多的运算对象\nBut if you had more operands,\n\n824\n00:44:10,288 --> 00:44:11,472\n你会做什么特殊的事情吗？\nyou'd want to do something special?\n\n825\n00:44:12,710 --> 00:44:16,048\n教授: 你看的是Scheme的实际实现\nPROFESSOR: Yeah, you're looking in the actual scheme implementation.\n\n826\n00:44:16,064 --> 00:44:17,840\n其中有一个‘+’ 这是一个运算符\nThere's a plus, and a plus is some operator.\n\n827\n00:44:17,904 --> 00:44:20,190\n如果你看‘+’的源代码\nAnd then if you go look inside the code for plus,\n\n828\n00:44:20,336 --> 00:44:21,376\n你会看到一些叫做--\nyou see something called--\n\n829\n00:44:21,570 --> 00:44:24,144\n我记不清了--可能叫ADD%、PLUS之类的东西\nI forget-- and-percent plus or something like that.\n\n830\n00:44:24,550 --> 00:44:25,792\n这里所进行的\nAnd what's going on there is\n\n831\n00:44:25,792 --> 00:44:27,920\n就是你说的那种优化\nis that particular kind of optimization.\n\n832\n00:44:28,470 --> 00:44:31,872\n因为 广义的‘+’接受任意数量的参数\nBecause, see, general plus takes an arbitrary number of arguments.\n\n833\n00:44:35,020 --> 00:44:36,384\n所以 广义加法\nSo the most general plus\n\n834\n00:44:36,760 --> 00:44:38,256\n会说：如果我有一个参数表\nsays, oh, if I have an argument list,\n\n835\n00:44:38,288 --> 00:44:40,624\n我最好将它们用CONS连接到表里\nI'd better cons it up in some list\n\n836\n00:44:41,630 --> 00:44:44,144\n并指出有多少个参数\nand then figure out how many there were or something like that.\n\n837\n00:44:44,720 --> 00:44:46,160\n这样效率非常低下\nThat's terribly inefficient,\n\n838\n00:44:46,810 --> 00:44:49,250\n因为大部分时间你在把两个数相加\nespecially since most of the time you're probably adding two numbers.\n\n839\n00:44:49,250 --> 00:44:51,248\n你不必把整个参数表连接到一起\nYou don't want to really have to cons this argument list.\n\n840\n00:44:52,048 --> 00:44:53,936\n所以你想做的是\nSo what you'd like to do is build\n\n841\n00:44:55,664 --> 00:44:57,712\n构建把一堆东西相加的代码\nthe code for plus with a bunch of entries.\n\n842\n00:44:58,150 --> 00:45:00,176\n所以它做的大部分事情是一样的\nSo most of what it's doing is the same.\n\n843\n00:45:00,490 --> 00:45:01,952\n但这里可能有个特殊的入口\nHowever, there might be a special entry\n\n844\n00:45:01,984 --> 00:45:03,920\n如果你知道只有两个参数\nthat you'd go to if you knew there were only two arguments.\n\n845\n00:45:04,560 --> 00:45:05,875\n你会把它们放到寄存器中\nAnd those you'll put in registers.\n\n846\n00:45:05,870 --> 00:45:06,976\n它们不需要参数表\nthey won't be in an argument list\n\n847\n00:45:06,992 --> 00:45:07,984\n你也不必用CONS连接它们\nand you won't have to CONS.\n\n848\n00:45:08,675 --> 00:45:10,425\n这就是这些东西工作的原理\nThat's how a lot of these things work.\n\n849\n00:45:12,300 --> 00:45:13,725\n好吧 下课吧\nOK, let's take a break.\n\n850\n00:45:14,100 --> 00:45:36,688\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n851\n00:45:36,688 --> 00:45:38,680\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n852\n00:45:38,680 --> 00:45:42,976\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec10b.eng.srt",
    "content": "﻿1\n00:00:04,970 --> 00:00:06,535\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n2\n00:00:18,910 --> 00:00:24,440\nPROFESSOR: Well, there's one bit of mystery left, which I'd like to get rid of right now.\n\n3\n00:00:24,440 --> 00:00:33,660\nAnd that's that we've been blithely doing things like cons assuming there's always another one.\n\n4\n00:00:33,660 --> 00:00:40,020\nThat we've been doing these things like car-ing and cdr-ing and assuming that we had some idea how this can be done.\n\n5\n00:00:40,020 --> 00:00:45,780\nNow indeed we said that that's equivalent to having procedures.\n\n6\n00:00:45,780 --> 00:00:53,010\nBut that doesn't really solve the problem, because the procedure need all sorts of complicated mechanisms like environment structures and things like that to work.\n\n7\n00:00:53,010 --> 00:00:59,380\nAnd those were ultimately made out of conses in the model that we had, so that really doesn't solve the problem.\n\n8\n00:00:59,380 --> 00:01:04,760\nNow the problem here is the glue the data structure's made out of.\n\n9\n00:01:04,760 --> 00:01:07,370\nWhat kind of possible thing could it be?\n\n10\n00:01:07,370 --> 00:01:16,980\nWe've been showing you things like a machine, a computer that has a controller, and some registers, and maybe a stack.\n\n11\n00:01:16,980 --> 00:01:20,570\nAnd we haven't said anything about, for example, larger memory.\n\n12\n00:01:20,570 --> 00:01:23,740\nAnd I think that's what we have to worry about right now.\n\n13\n00:01:23,740 --> 00:01:34,800\nBut just to make it perfectly clear that this is an inessential, purely implementational thing, I'd like to show you, for example, how you can do it all with the numbers.\n\n14\n00:01:34,800 --> 00:01:37,590\nThat's an easy one.\n\n15\n00:01:37,590 --> 00:01:54,320\nFamous fellow by the name of Godel, a logician at the end of the 1930s, invented a very clever way of encoding the complicated expressions as numbers.\n\n16\n00:01:54,320 --> 00:01:59,660\nFor example-- I'm not saying exactly what Godel's scheme is, because he didn't use words like cons.\n\n17\n00:01:59,660 --> 00:02:03,090\nHe had other kinds of ways of combining to make expressions.\n\n18\n00:02:03,090 --> 00:02:07,920\nBut he said, I'm going to assign a number to every algebraic expression.\n\n19\n00:02:07,920 --> 00:02:12,470\nAnd the way I'm going to manufacture these numbers is by combining the numbers of the parts.\n\n20\n00:02:12,470 --> 00:02:46,130\nSo for example, what we were doing our world, we could say that if objects are represented by numbers, then cons of x and y could be represented by 2 to the x times 2 to the y.\n\n21\n00:02:46,130 --> 00:02:49,560\nBecause then we could extract the parts.\n\n22\n00:02:49,560 --> 00:03:06,690\nWe could say, for example, that then car of, say, x is the number of factors of 2 in x.\n\n23\n00:03:06,690 --> 00:03:10,690\nAnd of course cdr is the same thing.\n\n24\n00:03:10,690 --> 00:03:16,510\nIt's the number of factors of 3 in x.\n\n25\n00:03:16,510 --> 00:03:27,950\nNow this is a perfectly reasonable scheme, except for the fact that the numbers rapidly get to be much larger in number of digits than the number of protons in the universe.\n\n26\n00:03:27,950 --> 00:03:33,430\nSo there's no easy way to use this scheme other than the theoretical one.\n\n27\n00:03:33,430 --> 00:03:38,450\nOn the other hand, there are other ways of representing these things.\n\n28\n00:03:38,450 --> 00:03:44,010\nWe have been thinking in terms of little boxes.\n\n29\n00:03:44,010 --> 00:03:50,280\nWe've been thinking about our cons structures as looking sort of like this.\n\n30\n00:03:50,280 --> 00:03:53,610\nThey're little pigeon holes with things in them.\n\n31\n00:03:53,610 --> 00:03:57,210\nAnd of course we arrange them in little trees.\n\n32\n00:03:57,210 --> 00:04:09,380\nI wish that the semiconductor manufacturers would supply me with something appropriate for this, but actually what they do supply me with is a linear memory.\n\n33\n00:04:09,380 --> 00:04:17,720\nMemory is sort of a big pile of pigeonholes, pigeonholes like this.\n\n34\n00:04:17,720 --> 00:04:23,390\nEach of which can hold a certain sized object, a fixed size object.\n\n35\n00:04:23,390 --> 00:04:28,550\nSo, for example, a complicated list with 25 elements won't fit in one of these.\n\n36\n00:04:28,550 --> 00:04:30,600\nHowever, each of these is indexed by an address.\n\n37\n00:04:33,970 --> 00:04:38,060\nSo the address might be zero here, one here, two here, three here, and so on.\n\n38\n00:04:38,060 --> 00:04:40,400\nThat we write these down as numbers is unimportant.\n\n39\n00:04:40,400 --> 00:04:44,970\nWhat matters is that they're distinct as a way to get to the next one.\n\n40\n00:04:44,970 --> 00:04:49,530\nAnd inside of each of these, we can stuff something into these pigeonholes.\n\n41\n00:04:49,530 --> 00:04:53,550\nThat's what memory is like, for those of you who haven't built a computer.\n\n42\n00:04:56,690 --> 00:05:03,290\nNow the problem is how are we going to impose on this type of structure, this nice tree structure.\n\n43\n00:05:03,290 --> 00:05:06,630\nWell it's not very hard, and there have been numerous schemes involved in this.\n\n44\n00:05:06,630 --> 00:05:21,706\nThe most important one is to say, well assuming that the semiconductor manufacturer allows me to arrange my memory so that one of these pigeonholes is big enough to hold the address of another I haven't made.\n\n45\n00:05:21,706 --> 00:05:30,390\nNow it actually has to be a little bit bigger because I have to also install or store some information as to a tag which describes the kind of thing that's there.\n\n46\n00:05:30,390 --> 00:05:32,350\nAnd we'll see that in a second.\n\n47\n00:05:32,350 --> 00:05:43,770\nAnd of course if the semiconductor manufacturer doesn't arrange it so I can do that, then of course I can, with some cleverness, arrange combinations of these to fit together in that way.\n\n48\n00:05:43,770 --> 00:05:51,740\nSo we're going to have to imagine imposing this complicated tree structure on our nice linear memory.\n\n49\n00:05:51,740 --> 00:05:59,490\nIf we look at the first still store, we see a classic scheme for doing that.\n\n50\n00:05:59,490 --> 00:06:05,980\nIt's a standard way of representing Lisp structures in a linear memory.\n\n51\n00:06:05,980 --> 00:06:12,030\nWhat we do is we divide this memory into two parts.\n\n52\n00:06:12,030 --> 00:06:17,580\nAn array called the cars, and an array called the cdrs.\n\n53\n00:06:17,580 --> 00:06:22,560\nNow whether those happen to be sequential addresses or whatever, it's not important.\n\n54\n00:06:22,560 --> 00:06:25,800\nThat's somebody's implementation details.\n\n55\n00:06:25,800 --> 00:06:28,960\nBut there are two arrays here.\n\n56\n00:06:28,960 --> 00:06:34,840\nLinear arrays indexed by sequential indices like this.\n\n57\n00:06:34,840 --> 00:06:41,430\nWhat is stored in each of these pigeonholes is a typed object.\n\n58\n00:06:41,430 --> 00:06:47,790\nAnd what we have here are types which begin with letters like p, standing for a pair.\n\n59\n00:06:47,790 --> 00:06:50,040\nOr n, standing for a number.\n\n60\n00:06:50,040 --> 00:07:06,430\nOr e, standing for an empty list. The end of the list. And so if we wish to represent an object like this, the list beginning with 1, 2 and then having a 3 and a 4 as its second and third elements.\n\n61\n00:07:06,430 --> 00:07:12,610\nA list containing a list as its first part and then two numbers as a second and third parts.\n\n62\n00:07:12,610 --> 00:07:17,320\nThen of course we draw it sort of like this these days, in box-and-pointer notation.\n\n63\n00:07:17,320 --> 00:07:28,390\nAnd you see, these are the three cells that have as their car pointer the object which is either 1, 2 or 3 or 4.\n\n64\n00:07:28,390 --> 00:07:35,940\nAnd then of course the 1, 2, the car of this entire structure, is itself a substructure which contains a sublist like that.\n\n65\n00:07:35,940 --> 00:07:41,880\nWhat I'm about to do is put down places which are-- I'm going to assign indices.\n\n66\n00:07:41,880 --> 00:07:46,850\nLike this 1, over here, represents the index of this cell.\n\n67\n00:07:49,850 --> 00:08:02,000\nBut that pointer that we see here is a reference to the pair of pigeonholes in the cars and the cdrs that are labeled by 1 in my linear memory down here.\n\n68\n00:08:02,000 --> 00:08:12,220\nSo if I wish to impose this structure on my linear memory, what I do is I say, oh yes, why don't we drop this into cell 1?\n\n69\n00:08:12,220 --> 00:08:12,660\nI pick one.\n\n70\n00:08:12,660 --> 00:08:14,270\nThere's 1.\n\n71\n00:08:14,270 --> 00:08:17,950\nAnd that says that its car, I'm going to assign it to be a pair.\n\n72\n00:08:17,950 --> 00:08:22,590\nIt's a pair, which is in index 5.\n\n73\n00:08:22,590 --> 00:08:28,340\nAnd the cdr, which is this one over here, is a pair which I'm going to stick into place 2.\n\n74\n00:08:28,340 --> 00:08:30,890\np2.\n\n75\n00:08:30,890 --> 00:08:32,950\nAnd take a look at p2.\n\n76\n00:08:32,950 --> 00:08:39,520\nOh yes, well p2 is a thing whose car is the number 3, so as you see, an n3.\n\n77\n00:08:39,520 --> 00:08:46,640\nAnd whose cdr, over here, is a pair, which lives in place 4.\n\n78\n00:08:46,640 --> 00:08:48,650\nSo that's what this p4 is.\n\n79\n00:08:48,650 --> 00:08:59,170\np4 is a number whose value is 4 in its car and whose cdr is an empty list right there.\n\n80\n00:08:59,170 --> 00:09:00,690\nAnd that ends it.\n\n81\n00:09:00,690 --> 00:09:11,620\nSo this is the traditional way of representing this kind of binary tree in a linear memory.\n\n82\n00:09:11,620 --> 00:09:18,440\nNow the next question, of course, that we might want to worry about is just a little bit of implementation.\n\n83\n00:09:18,440 --> 00:09:30,140\nThat means that when I write procedures of the form assigned a, [UNINTELLIGIBLE] procedures-- lines of register machine code of the form assigned a, the car of [UNINTELLIGIBLE]\n\n84\n00:09:30,140 --> 00:09:38,740\nb, what I really mean is addressing these elements.\n\n85\n00:09:38,740 --> 00:09:44,470\nAnd so we're going to think of that as a abbreviation for it.\n\n86\n00:09:44,470 --> 00:09:49,140\nNow of course in order to write that down I'm going to introduce some sort of a structure called a vector.\n\n87\n00:09:52,120 --> 00:09:58,710\nAnd we're going to have something which will reference a vector, just so we can write it down.\n\n88\n00:09:58,710 --> 00:10:03,970\nWhich takes the name of the vector, or the-- I don't think that name is the right word.\n\n89\n00:10:03,970 --> 00:10:16,280\nWhich takes the vector and the index, and I have to have a way of setting one of those with something called a vector set, I don't really care.\n\n90\n00:10:16,280 --> 00:10:26,470\nBut let's look, for example, at then that kind of implementation of car and cdr.\n\n91\n00:10:26,470 --> 00:10:44,490\nSo for example if I happen to have a register b, which contains the type index of a pair, and therefore it is the pointer to a pair, then I could take the car of that and if I-- write this down-- I might put that in register a.\n\n92\n00:10:44,490 --> 00:11:02,650\nWhat that really is is a representation of the assign to a, the value of vector reffing-- or array indexing, if you will-- or something, the cars object-- whatever that is-- with the index, b.\n\n93\n00:11:02,650 --> 00:11:11,840\nAnd similarly for cdr. And we can do the same thing for assignment to data structures, if we need to do that sort of thing at all.\n\n94\n00:11:11,840 --> 00:11:14,580\nIt's not too hard to build that.\n\n95\n00:11:14,580 --> 00:11:18,010\nWell now the next question is how are we going to do allocation.\n\n96\n00:11:18,010 --> 00:11:21,550\nAnd every so often I say I want a cons.\n\n97\n00:11:21,550 --> 00:11:23,790\nNow conses don't grow on trees.\n\n98\n00:11:23,790 --> 00:11:25,340\nOr maybe they should.\n\n99\n00:11:25,340 --> 00:11:29,980\nBut I have to have some way of getting the next one.\n\n100\n00:11:29,980 --> 00:11:35,630\nI have to have some idea of if their memory is unused that I might want to allocate from.\n\n101\n00:11:35,630 --> 00:11:37,380\nAnd there are many schemes for doing this.\n\n102\n00:11:37,380 --> 00:11:42,100\nAnd the particular thing I'm showing you right now is not essential.\n\n103\n00:11:42,100 --> 00:11:44,960\nHowever it's convenient and has been done many times.\n\n104\n00:11:44,960 --> 00:11:47,660\nOne scheme's was called the free list allocation scheme.\n\n105\n00:11:47,660 --> 00:11:56,960\nWhat that means is that all of the free memory that there is in the world is linked together in a linked list, just like all the other stuff.\n\n106\n00:11:56,960 --> 00:12:06,030\nAnd whenever you need a free cell to make a new cons, you grab the first, one make the free list be the cdr of it, and then allocate that.\n\n107\n00:12:06,030 --> 00:12:09,530\nAnd so what that looks like is something like this.\n\n108\n00:12:09,530 --> 00:12:18,510\nHere we have the free list starting in 6.\n\n109\n00:12:18,510 --> 00:12:24,860\nAnd what that is is a pointer-off to say 8.\n\n110\n00:12:24,860 --> 00:12:28,870\nSo what it says is, this one is free and the next one is an 8.\n\n111\n00:12:28,870 --> 00:12:33,930\nThis one is free and the next one is in 3, the next one that's free.\n\n112\n00:12:33,930 --> 00:12:37,680\nThat one's free and the next one is in 0.\n\n113\n00:12:37,680 --> 00:12:40,940\nThat one's free and the next one's in 15.\n\n114\n00:12:40,940 --> 00:12:42,780\nSomething like that.\n\n115\n00:12:42,780 --> 00:12:46,400\nWe can imagine having such a structure.\n\n116\n00:12:46,400 --> 00:12:53,940\nGiven that we have something like that, then it's possible to just get one when you need it.\n\n117\n00:12:53,940 --> 00:12:59,320\nAnd so a program for doing cons, this is what cons might turn into.\n\n118\n00:12:59,320 --> 00:13:25,680\nTo assign to a register A the result of cons-ing, a B onto C, the value in this containing B and the value containing C, what we have to do is get the current [? type ?] ahead of the freelist, make the free list be its cdr. Then we have to change the cars to be the thing we're making up to be in A to be the B, the thing in B.\n\n119\n00:13:25,680 --> 00:13:36,650\nAnd we have to make change the cdrs of the thing that's in A to be C. And then what we have in A is the right new frob, whatever it is.\n\n120\n00:13:36,650 --> 00:13:40,470\nThe object that we want.\n\n121\n00:13:40,470 --> 00:13:53,510\nNow there's a little bit of a cheat here that I haven't told you about, which is somewhere around here I haven't set that I've the type of the thing that I'm cons-ing up to be a pair, and I ought to.\n\n122\n00:13:53,510 --> 00:13:59,810\nSo there should be some sort of bits here are being set, and I just haven't written that down.\n\n123\n00:13:59,810 --> 00:14:03,100\nWe could have arranged it, of course, for the free lift to be made out of pairs.\n\n124\n00:14:03,100 --> 00:14:06,430\nAnd so then there's no problem with that.\n\n125\n00:14:06,430 --> 00:14:17,540\nBut that sort of-- again, an inessential detail in a way some particular programmer or architect or whatever might manufacture his machine or Lisp system.\n\n126\n00:14:17,540 --> 00:14:43,430\nSo for example, just looking at this, to allocate given that I had already the structure that you saw before, supposing I wanted to allocate a new cell, which is going to be representation of list one, one, two, where already one two was the car of the list we were playing with before.\n\n127\n00:14:43,430 --> 00:14:44,780\nWell that's not so hard.\n\n128\n00:14:44,780 --> 00:14:49,530\nI stored that one and one, so p1 one is the representation of this.\n\n129\n00:14:49,530 --> 00:14:51,690\nThis is p5.\n\n130\n00:14:51,690 --> 00:14:54,070\nThat's going to be the cdr of this.\n\n131\n00:14:54,070 --> 00:14:57,780\nNow we're going to pull something off the free list, but remember the free list started at six.\n\n132\n00:14:57,780 --> 00:15:02,890\nThe new free list after this allocation is eight, a free list beginning at eight.\n\n133\n00:15:02,890 --> 00:15:13,330\nAnd of course in six now we have a number one, which is what we wanted, with its cdr being the pair starting in location five.\n\n134\n00:15:13,330 --> 00:15:16,810\nAnd that's no big deal.\n\n135\n00:15:16,810 --> 00:15:25,080\nSo the only problem really remaining here is, well, I don't have an infinitely large memory.\n\n136\n00:15:25,080 --> 00:15:38,000\nIf I do this for a little while, say, for example, supposing it takes me a microsecond to do a cons, and I have a million cons memory then I'm only going to run out in a second, and that's pretty bad.\n\n137\n00:15:38,000 --> 00:15:44,300\nSo what we do to prevent that disaster, that ecological disaster, talk about right after questions.\n\n138\n00:15:44,300 --> 00:15:45,550\nAre there any questions?\n\n139\n00:15:51,500 --> 00:15:52,030\nYes.\n\n140\n00:15:52,030 --> 00:16:04,930\nAUDIENCE: In the environment diagrams that we were drawing we would use the body of procedures, and you would eventually wind up with things that were no longer useful in that structure.\n\n141\n00:16:04,930 --> 00:16:06,890\nHow is that represented?\n\n142\n00:16:06,890 --> 00:16:09,180\nPROFESSOR: There's two problems here.\n\n143\n00:16:09,180 --> 00:16:13,870\nOne you were asking is that material becomes useless.\n\n144\n00:16:13,870 --> 00:16:14,920\nWe'll talk about that in a second.\n\n145\n00:16:14,920 --> 00:16:18,100\nThat has to do with how to prevent ecological disasters.\n\n146\n00:16:18,100 --> 00:16:21,820\nIf I make a lot of garbage I have to somehow be able to clean up after myself.\n\n147\n00:16:21,820 --> 00:16:23,430\nAnd we'll talk about that in a second.\n\n148\n00:16:23,430 --> 00:16:27,210\nThe other question you're asking is how you represent the environments, I think.\n\n149\n00:16:27,210 --> 00:16:27,600\nAUDIENCE: Yes.\n\n150\n00:16:27,600 --> 00:16:28,190\nPROFESSOR: OK.\n\n151\n00:16:28,190 --> 00:16:30,860\nAnd the environment structures can be represented in arbitrary ways.\n\n152\n00:16:30,860 --> 00:16:31,780\nThere are lots of them.\n\n153\n00:16:31,780 --> 00:16:33,630\nI mean, here I'm just telling you about list cells.\n\n154\n00:16:33,630 --> 00:16:41,080\nOf course every real system has vectors of arbitrary length as well as the vectors of length, too, which represent list cells.\n\n155\n00:16:41,080 --> 00:16:58,290\nAnd the environment structures that one uses in a professionally written Lisp system tend to be vectors which contain a number of elements approximately equal to the number of arguments-- a little bit more because you need certain glue.\n\n156\n00:16:58,290 --> 00:17:00,360\nSo remember, the environment [UNINTELLIGIBLE]\n\n157\n00:17:00,360 --> 00:17:00,740\nframes.\n\n158\n00:17:00,740 --> 00:17:03,980\nThe frames are constructed by applying a procedure.\n\n159\n00:17:03,980 --> 00:17:11,270\nIn doing so, an allocation is made of a place which is the number of arguments long plus [? unglue ?]\n\n160\n00:17:11,270 --> 00:17:13,859\nthat gets linked into a chain.\n\n161\n00:17:13,859 --> 00:17:15,660\nIt's just like algol at that level.\n\n162\n00:17:19,810 --> 00:17:21,060\nThere any other questions?\n\n163\n00:17:23,700 --> 00:17:23,920\nOK.\n\n164\n00:17:23,920 --> 00:17:26,106\nThank you, and let's take a short break.\n\n165\n00:17:26,106 --> 00:17:27,699\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n166\n00:18:12,270 --> 00:18:19,420\nPROFESSOR: Well, as I just said, computer memories supplied by the semiconductor manufacturers are finite.\n\n167\n00:18:19,420 --> 00:18:21,620\nAnd that's quite a pity.\n\n168\n00:18:21,620 --> 00:18:24,030\nIt might not always be that way.\n\n169\n00:18:24,030 --> 00:18:28,860\nJust for a quick calculation, you can see that it's possible that if [? memory ?]\n\n170\n00:18:28,860 --> 00:18:39,450\nprices keep going at the rate they're going that if you still took a microsecond second to do a cons, then-- first of all, everybody should know that there's about pi times ten to the seventh seconds in a year.\n\n171\n00:18:39,450 --> 00:18:43,940\nAnd so that would be ten to the seventh plus ten to the sixth is ten to the thirteenth.\n\n172\n00:18:43,940 --> 00:18:47,520\nSo there's maybe ten to the fourteenth conses in the life of a machine.\n\n173\n00:18:47,520 --> 00:18:54,020\nIf there was ten to the fourteenth words of memory on your machine, you'd never run out.\n\n174\n00:18:54,020 --> 00:18:56,310\nAnd that's not completely unreasonable.\n\n175\n00:18:56,310 --> 00:18:58,460\nTen to the fourteenth is not a very large number.\n\n176\n00:19:03,860 --> 00:19:05,180\nI don't think it is.\n\n177\n00:19:05,180 --> 00:19:08,700\nBut then again I like to play with astronomy.\n\n178\n00:19:08,700 --> 00:19:12,930\nIt's at least ten to the eighteenth centimeters between us and the nearest star.\n\n179\n00:19:12,930 --> 00:19:24,200\nBut the thing I'm about to worry about is, at least in the current economic state of affairs, ten to the fourteenth pieces of memory is expensive.\n\n180\n00:19:24,200 --> 00:19:28,120\nAnd so I suppose what we have to do is make do with much smaller.\n\n181\n00:19:28,120 --> 00:19:35,800\nMemories Now in general we want to have an illusion of infinity.\n\n182\n00:19:35,800 --> 00:19:40,100\nAll we need to do is arrange it so that whenever you look, the thing is there.\n\n183\n00:19:42,670 --> 00:19:45,105\nThat's really an important idea.\n\n184\n00:19:49,540 --> 00:19:55,280\nA person or a computer lives only a finite amount of time and can only take a finite number of looks at something.\n\n185\n00:19:55,280 --> 00:19:58,190\nAnd so you really only need a finite amount of stuff.\n\n186\n00:19:58,190 --> 00:20:06,900\nBut you have to arrange it so no matter how much there is, how much you really claim there is, there's always enough stuff so that when you take a look, it's there.\n\n187\n00:20:06,900 --> 00:20:08,750\nAnd so you only need a finite amount.\n\n188\n00:20:08,750 --> 00:20:11,630\nBut let's see.\n\n189\n00:20:11,630 --> 00:20:19,410\nOne problem is, as was brought up, that there are possible ways that there is lots of stuff that we make that we don't need.\n\n190\n00:20:19,410 --> 00:20:22,760\nAnd we could recycle the material out of which its made.\n\n191\n00:20:22,760 --> 00:20:30,470\nAn example is the fact that we're building environment structures, and we do so every time we call a procedure.\n\n192\n00:20:30,470 --> 00:20:32,810\nWe have built in it a environment frame.\n\n193\n00:20:32,810 --> 00:20:36,730\nThat environment frame doesn't necessarily have a very long lifetime.\n\n194\n00:20:36,730 --> 00:20:42,850\nIts lifetime, meaning its usefulness, may exist only over the invocation of the procedure.\n\n195\n00:20:42,850 --> 00:20:58,530\nOr if the procedure exports another procedure by returning it as a value and that procedure is defined inside of it, well then the lifetime of the frame of the outer procedure still is only the lifetime of the procedure which was exported.\n\n196\n00:20:58,530 --> 00:21:01,960\nAnd so ultimately, a lot of that is garbage.\n\n197\n00:21:01,960 --> 00:21:05,370\nThere are other ways of producing garbage as well.\n\n198\n00:21:05,370 --> 00:21:07,240\nUsers produce garbage.\n\n199\n00:21:07,240 --> 00:21:10,930\nAn example of user garbage is something like this.\n\n200\n00:21:10,930 --> 00:21:28,160\nIf we write a program to, for example, append two lists together, well one way to do it is to reverse the first list onto the empty list and reverse that onto the second list. Now that's not terribly bad way of doing it.\n\n201\n00:21:28,160 --> 00:21:41,010\nAnd however, the intermediate result, which is the reversal of the first list as done by this program, is never going to be accessed ever again after it's copied back on to the second.\n\n202\n00:21:41,010 --> 00:21:43,580\nIt's an intermediate result.\n\n203\n00:21:43,580 --> 00:21:48,600\nIt's going to be hard to ever see how anybody would ever be able to access it.\n\n204\n00:21:48,600 --> 00:21:51,050\nIn fact, it will go away.\n\n205\n00:21:51,050 --> 00:21:58,800\nNow if we make a lot of garbage like that, and we should be allowed to, then there's got to be some way to reclaim that garbage.\n\n206\n00:21:58,800 --> 00:22:17,410\nWell, what I'd like to tell you about now is a very clever technique whereby a Lisp system can prove a small theorem every so often on the [? forum, ?] the following piece of junk will never be accessed again.\n\n207\n00:22:17,410 --> 00:22:21,400\nIt can have no affect on the future of the computation.\n\n208\n00:22:21,400 --> 00:22:24,920\nIt's actually based on a very simple idea.\n\n209\n00:22:24,920 --> 00:22:28,570\nWe've designed our computers to look sort of like this.\n\n210\n00:22:28,570 --> 00:22:35,280\nThere's some data path, which contains the registers.\n\n211\n00:22:35,280 --> 00:22:42,610\nThere are things like x, and env, and val, and so on.\n\n212\n00:22:42,610 --> 00:22:50,240\nAnd there's one here called stack, some sort which points off to a structure somewhere, which is the stack.\n\n213\n00:22:50,240 --> 00:22:51,740\nAnd we'll worry about that in a second.\n\n214\n00:22:51,740 --> 00:22:56,730\nThere's some finite controller, finite state machine controller.\n\n215\n00:22:56,730 --> 00:23:04,260\nAnd there's some control signals that go this way and predicate results that come this way, not the interesting part.\n\n216\n00:23:04,260 --> 00:23:10,460\nThere's some sort of structured memory, which I just told you how to make, which may contain a stack.\n\n217\n00:23:10,460 --> 00:23:13,450\nI didn't tell you how to make things of arbitrary shape, only pairs.\n\n218\n00:23:13,450 --> 00:23:20,360\nBut in fact with what I've told you can simulate a stack by a big list. I don't plan to do that, it's not a nice way to do it.\n\n219\n00:23:20,360 --> 00:23:22,990\nBut we could have something like that.\n\n220\n00:23:22,990 --> 00:23:27,470\nWe have all sorts of little data structures in here that are hooked together in funny ways.\n\n221\n00:23:30,115 --> 00:23:32,560\nThey connect to other things.\n\n222\n00:23:32,560 --> 00:23:33,250\nAnd so on.\n\n223\n00:23:33,250 --> 00:23:37,190\nAnd ultimately things up there are pointers to these.\n\n224\n00:23:37,190 --> 00:23:44,910\nThe things that are in the registers are pointers off to the data structures that live in this Lisp structure memory.\n\n225\n00:23:44,910 --> 00:23:55,550\nNow the truth of the matter is that the entire consciousness of this machine is in these registers.\n\n226\n00:23:55,550 --> 00:24:15,070\nThere is no possible way that the machine, if done correctly, if built correctly, can access anything in this Lisp structure memory unless the thing in that Lisp structure memory is connected by a sequence of data structures to the registers.\n\n227\n00:24:15,070 --> 00:24:22,280\nIf it's accessible by legitimate data structure selectors from the pointers that are stored in these registers.\n\n228\n00:24:22,280 --> 00:24:24,940\nThings like array references, perhaps.\n\n229\n00:24:24,940 --> 00:24:28,790\nOr cons cell references, cars and cdrs.\n\n230\n00:24:28,790 --> 00:24:32,740\nBut I can't just talk about a random place in this memory, because I can't get to it.\n\n231\n00:24:32,740 --> 00:24:38,985\nThese are being arbitrary names I'm not allowed to count, at least as I'm evaluating expressions.\n\n232\n00:24:41,620 --> 00:24:47,160\nIf that's the case then there's a very simple theorem to be proved.\n\n233\n00:24:47,160 --> 00:25:00,750\nWhich is, if I start with all lead pointers that are in all these registers and recursively chase out, marking all the places I can get to by selectors, then eventually I mark everything they can be gotten to.\n\n234\n00:25:00,750 --> 00:25:05,560\nAnything which is not so marked is garbage and can be recycled.\n\n235\n00:25:05,560 --> 00:25:07,200\nVery simple.\n\n236\n00:25:07,200 --> 00:25:11,180\nCannot affect the future of the computation.\n\n237\n00:25:11,180 --> 00:25:16,616\nSo let me show you that in a particular example.\n\n238\n00:25:16,616 --> 00:25:23,640\nNow that means I'm going to have to append to my description of the list structure a mark.\n\n239\n00:25:23,640 --> 00:25:29,080\nAnd so here, for example, is a Lisp structured memory.\n\n240\n00:25:29,080 --> 00:25:38,590\nAnd in this Lisp structured memory is a Lisp structure beginning in a place I'm going to call--  this is the root.\n\n241\n00:25:38,590 --> 00:25:40,120\nNow it doesn't really have to have a root.\n\n242\n00:25:40,120 --> 00:25:42,670\nIt could be a bunch of them, like all the registers.\n\n243\n00:25:42,670 --> 00:25:51,850\nBut I could cleverly arrange it so all the registers, all the things that are in old registers are also at the right moment put into this root structure, and then we've got one pointer to it.\n\n244\n00:25:51,850 --> 00:25:54,570\nI don't really care.\n\n245\n00:25:54,570 --> 00:25:58,720\nSo the idea is we're going to cons up stuff until our free list is empty.\n\n246\n00:25:58,720 --> 00:26:00,950\nWe've run out of things.\n\n247\n00:26:00,950 --> 00:26:07,850\nNow we're going to do this process of proving the theorem that a certain percentage of the memory has got crap in it.\n\n248\n00:26:07,850 --> 00:26:14,570\nAnd then we're going to recycle that to grow new trees, a standard use of such garbage.\n\n249\n00:26:17,090 --> 00:26:18,840\nSo in any case, what do we have here?\n\n250\n00:26:18,840 --> 00:26:27,502\nWell we have some data structure which starts out over here one.\n\n251\n00:26:27,502 --> 00:26:33,980\nAnd in fact it has a car in five, and its cdr is in two.\n\n252\n00:26:33,980 --> 00:26:36,700\nAnd all the marks start out at zero.\n\n253\n00:26:36,700 --> 00:26:39,920\nWell let's start marking, just to play this game.\n\n254\n00:26:39,920 --> 00:26:42,540\nOK.\n\n255\n00:26:42,540 --> 00:26:48,390\nSo for example, since I can access one from the root I will mark that.\n\n256\n00:26:48,390 --> 00:26:50,960\nLet me mark it.\n\n257\n00:26:50,960 --> 00:26:52,430\nBang.\n\n258\n00:26:52,430 --> 00:26:54,560\nThat's marked.\n\n259\n00:26:54,560 --> 00:27:01,450\nNow since I have a five here I can go to five and see, well I'll mark that.\n\n260\n00:27:01,450 --> 00:27:01,760\nBang.\n\n261\n00:27:01,760 --> 00:27:02,900\nThat's useful stuff.\n\n262\n00:27:02,900 --> 00:27:08,700\nBut five references as a number in its car, I'm not interested in marking numbers but its cdr is seven.\n\n263\n00:27:08,700 --> 00:27:10,450\nSo I can mark that.\n\n264\n00:27:10,450 --> 00:27:12,260\nBang.\n\n265\n00:27:12,260 --> 00:27:17,120\nSeven is the empty list, the only thing that references, and it's got a number in its car.\n\n266\n00:27:17,120 --> 00:27:19,490\nNot interesting.\n\n267\n00:27:19,490 --> 00:27:20,500\nWell now let's go back here.\n\n268\n00:27:20,500 --> 00:27:21,650\nI forgot about something.\n\n269\n00:27:21,650 --> 00:27:22,840\nTwo.\n\n270\n00:27:22,840 --> 00:27:30,370\nSee in other words, if I'm looking at cell one, cell one contains a two right over here.\n\n271\n00:27:30,370 --> 00:27:31,730\nA reference to two.\n\n272\n00:27:31,730 --> 00:27:35,700\nThat means I should go mark two.\n\n273\n00:27:35,700 --> 00:27:37,140\nBang.\n\n274\n00:27:37,140 --> 00:27:38,960\nTwo contains a reference to four.\n\n275\n00:27:38,960 --> 00:27:43,780\nIt's got a number in its car, I'm not interested in that, so I'm going to go mark that.\n\n276\n00:27:43,780 --> 00:27:51,400\nFour refers to seven through its car, and is empty in its cdr, but I've already marked that one so I don't have to mark it again.\n\n277\n00:27:51,400 --> 00:27:55,000\nThis is all the accessible structure from that place.\n\n278\n00:27:55,000 --> 00:27:58,710\nSimple recursive mark algorithm.\n\n279\n00:27:58,710 --> 00:28:04,920\nNow there are some unhappinesses about that algorithm, and we can worry about that a second.\n\n280\n00:28:04,920 --> 00:28:14,220\nBut basically you'll see that all the things that have not been marked are places that are free, and I could recycle.\n\n281\n00:28:14,220 --> 00:28:21,180\nSo the next stage after that is going to be to scan through all of my memory, looking for things that are not marked.\n\n282\n00:28:21,180 --> 00:28:28,770\nEvery time I come across a marked thing I unmark it, and every time I come across an unmarked thing I'm going to link it together in my free list.\n\n283\n00:28:28,770 --> 00:28:32,120\nClassic, very simple algorithm.\n\n284\n00:28:32,120 --> 00:28:33,840\nSo let's see.\n\n285\n00:28:33,840 --> 00:28:34,770\nIs that very simple?\n\n286\n00:28:34,770 --> 00:28:35,570\nYes it is.\n\n287\n00:28:35,570 --> 00:28:40,090\nI'm not going to go through the code in any detail, but I just want to show you about how long it is.\n\n288\n00:28:40,090 --> 00:28:42,490\nLet's look at the mark phase.\n\n289\n00:28:42,490 --> 00:28:45,060\nHere's the first part of the mark phase.\n\n290\n00:28:45,060 --> 00:28:48,280\nWe pick up the root.\n\n291\n00:28:48,280 --> 00:28:52,380\nWe're going to use that as a recursive procedure call.\n\n292\n00:28:52,380 --> 00:28:57,380\nWe're going to sweep from there, after when we're done with marking.\n\n293\n00:28:57,380 --> 00:29:05,500\nAnd then we're going to do a little couple of instructions that do this checking out on the marks and changing the marks and things like that, according to the algorithm I've just shown you.\n\n294\n00:29:05,500 --> 00:29:06,470\nIt comes out here.\n\n295\n00:29:06,470 --> 00:29:10,660\nYou have to mark the cars of things and you also have to be able to mark the cdrs of things.\n\n296\n00:29:10,660 --> 00:29:14,370\nThat's the entire mark phase.\n\n297\n00:29:14,370 --> 00:29:16,590\nI'll just tell you a little story about this.\n\n298\n00:29:16,590 --> 00:29:26,740\nThe old DEC PDP-6 computer, this was the way that the mark-sweep garbage collection, as it was, was written.\n\n299\n00:29:26,740 --> 00:29:39,280\nThe program was so small that with the data that it needed, with the registers that it needed to manipulate the memory, it fit into the fast registers of the machine, which were 16.\n\n300\n00:29:39,280 --> 00:29:39,800\nThe whole program.\n\n301\n00:29:39,800 --> 00:29:43,170\nAnd you could execute instructions in the fast registers.\n\n302\n00:29:43,170 --> 00:29:48,870\nSo it's an extremely small program, and it could run very fast.\n\n303\n00:29:48,870 --> 00:30:03,410\nNow unfortunately, of course, this program, because the fact that it's recursive in the way that you do something first and then you do something after that, you have to work on the cars and then the cdrs, it requires auxiliary memory.\n\n304\n00:30:03,410 --> 00:30:08,260\nSo Lisp systems-- those requires a stack for marking.\n\n305\n00:30:08,260 --> 00:30:19,930\nLisp systems that are built this way have a limit to the depth of recursion you can have in data structures in either the car or the cdr, and that doesn't work very nicely.\n\n306\n00:30:19,930 --> 00:30:23,180\nOn the other hand, you never notice it if it's big enough.\n\n307\n00:30:23,180 --> 00:30:33,560\nAnd that's certainly been the case for most Maclisp, for example, which ran Macsyma where you could deal with expressions of thousands of elements long.\n\n308\n00:30:33,560 --> 00:30:39,490\nThese are algebraic expressions with thousand of terms. And there's no problem with that.\n\n309\n00:30:39,490 --> 00:30:42,190\nSuch, the garbage collector does work.\n\n310\n00:30:42,190 --> 00:30:55,380\nOn the other hand, there's a very clever modification to this algorithm, which I will not describe, by Peter Deutsch and Schorr and Waite-- Herb Schorr from IBM and Waite, who I don't know.\n\n311\n00:30:55,380 --> 00:31:07,520\nThat algorithm allows you to build-- you do can do this without auxiliary memory, by remembering as you walk the data structures where you came from by reversing the pointers as you go down and crawling up the reverse pointers as you go up.\n\n312\n00:31:07,520 --> 00:31:09,130\nIt's a rather tricky algorithm.\n\n313\n00:31:09,130 --> 00:31:14,350\nThe first time you write it-- or in fact, the first three times you write it it has a terrible bug in it.\n\n314\n00:31:14,350 --> 00:31:18,110\nAnd it's also rather slow, because it's complicated.\n\n315\n00:31:18,110 --> 00:31:24,580\nIt takes about six times as many memory references to do the sorts of things that we're talking about.\n\n316\n00:31:24,580 --> 00:31:31,510\nWell now once I've done this marking phase, and I get into a position where things look like this, let's look-- yes.\n\n317\n00:31:31,510 --> 00:31:35,590\nHere we have the mark done, just as I did it.\n\n318\n00:31:35,590 --> 00:31:37,330\nNow we have to perform the sweep phase.\n\n319\n00:31:37,330 --> 00:31:39,820\nAnd I described to you what this sweep is like.\n\n320\n00:31:39,820 --> 00:31:46,836\nI'm going to walk down from one end of memory or the other, I don't care where, scanning every cell that's in the memory.\n\n321\n00:31:46,836 --> 00:31:57,500\nAnd as I scan these cells, I'm going to link them together, if they are free, into the free list. And if they're not free, I'm going to unmark them so the marks become zero.\n\n322\n00:31:57,500 --> 00:32:00,460\nAnd in fact what I get-- well the program is not very complicated.\n\n323\n00:32:00,460 --> 00:32:02,780\nIt looks sort of like this-- it's a little longer.\n\n324\n00:32:02,780 --> 00:32:04,820\nHere's the first piece of it.\n\n325\n00:32:04,820 --> 00:32:06,710\nThis one's coming down from the top of memory.\n\n326\n00:32:06,710 --> 00:32:09,580\nI don't want you to try to understand this at this point.\n\n327\n00:32:09,580 --> 00:32:11,030\nIt's rather simple.\n\n328\n00:32:11,030 --> 00:32:15,970\nIt's a very simple algorithm, but there's pieces of it that just sort of look like this.\n\n329\n00:32:15,970 --> 00:32:18,600\nThey're all sort of obvious.\n\n330\n00:32:18,600 --> 00:32:22,310\nAnd after we've done the sweep, we get an answer that looks like that.\n\n331\n00:32:25,330 --> 00:32:29,590\nNow there are some disadvantages with mark-sweep algorithms of this sort.\n\n332\n00:32:29,590 --> 00:32:31,940\nSerious ones.\n\n333\n00:32:31,940 --> 00:32:36,498\nOne important disadvantage is that your memories get larger and larger.\n\n334\n00:32:36,498 --> 00:32:46,360\nAs you say, address spaces get larger and larger, you're willing to represent more and more stuff, then it gets very costly to scan all of memory.\n\n335\n00:32:46,360 --> 00:32:50,490\nWhat you'd really like to do is only scan useful stuff.\n\n336\n00:32:50,490 --> 00:33:00,370\nIt would even be better if you realized that some stuff was known to be good and useful, and you don't have to look at it more than once or twice.\n\n337\n00:33:00,370 --> 00:33:01,550\nOr very rarely.\n\n338\n00:33:01,550 --> 00:33:11,910\nWhereas other stuff that you're not so sure about, you can look at more detail every time you want to do this, want to garbage collect.\n\n339\n00:33:11,910 --> 00:33:15,660\nWell there are algorithms that are organized in this way.\n\n340\n00:33:15,660 --> 00:33:22,800\nLet me tell you about a famous old algorithm which allows you only look at the part of memory which is known to be useful.\n\n341\n00:33:22,800 --> 00:33:26,310\nAnd which happens to be the fastest known garbage collector algorithm.\n\n342\n00:33:26,310 --> 00:33:30,150\nThis is the Minsky-Feinchel-Yochelson garbage collector algorithm.\n\n343\n00:33:30,150 --> 00:33:48,480\nIt was invented by Minsky in 1961 or '60 or something, for the RLE PDP-1 Lisp, which had 4,096 words of list memory, and a drum.\n\n344\n00:33:48,480 --> 00:33:53,380\nAnd the whole idea was to garbage collect this terrible memory.\n\n345\n00:33:53,380 --> 00:34:06,350\nWhat Minsky realized was the easiest way to do this is to scan the memory in the same sense, walking the good structure, copying it out into the drum, compacted.\n\n346\n00:34:06,350 --> 00:34:12,300\nAnd then when we were done copying it all out, then you swap that back into your memory.\n\n347\n00:34:12,300 --> 00:34:17,030\nNow whether or you not use a drum, or another piece of memory, or something like that isn't important.\n\n348\n00:34:17,030 --> 00:34:20,350\nIn fact, I don't think people use drums anymore for anything.\n\n349\n00:34:20,350 --> 00:34:30,270\nBut this algorithm basically depends upon having about twice as much address space as you're actually using.\n\n350\n00:34:30,270 --> 00:34:37,110\nAnd so what you have is some, initially, some mixture of useful data and garbage.\n\n351\n00:34:37,110 --> 00:34:38,560\nSo this is called fromspace.\n\n352\n00:34:45,179 --> 00:34:47,800\nAnd this is a mixture of crud.\n\n353\n00:34:47,800 --> 00:34:52,000\nSome of it's important and some of it isn't.\n\n354\n00:34:52,000 --> 00:34:58,240\nNow there's another place which is hopefully big enough, if we recall, tospace, which is where we're copying to.\n\n355\n00:35:01,590 --> 00:35:04,970\nAnd what happens is-- and I'm not going to go through this detail.\n\n356\n00:35:04,970 --> 00:35:07,590\nIt's in our book quite explicitly.\n\n357\n00:35:07,590 --> 00:35:11,030\nThere's a root point where you start from.\n\n358\n00:35:11,030 --> 00:35:14,600\nAnd the idea is that you start with the root.\n\n359\n00:35:14,600 --> 00:35:22,810\nYou copy the first thing you see, the first thing that the root points at, to the beginning of tospace.\n\n360\n00:35:22,810 --> 00:35:27,560\nThe first thing is a pair or something like, a data structure.\n\n361\n00:35:27,560 --> 00:35:37,800\nYou then also leave behind a broken heart saying, I moved this object from here to here, giving the place where it moved to.\n\n362\n00:35:37,800 --> 00:35:46,760\nThis is called a broken heart because a friend of mine who implemented one of these in 1966 was a very romantic character and called it a broken heart.\n\n363\n00:35:49,580 --> 00:35:57,840\nBut in any case, the next thing you do is now you have a new free pointer which is here, and you start scanning.\n\n364\n00:35:57,840 --> 00:36:00,235\nYou scan this data structure you just copied.\n\n365\n00:36:00,235 --> 00:36:04,000\nAnd every time you encounter a pointer in it, you treat it as if it was the root pointer here.\n\n366\n00:36:04,000 --> 00:36:05,170\nOh, I'm sorry.\n\n367\n00:36:05,170 --> 00:36:09,220\nThe other thing you do is you now move the root pointer to there.\n\n368\n00:36:09,220 --> 00:36:14,110\nSo now you scan this, and everything you see you treat as it were the root pointer.\n\n369\n00:36:14,110 --> 00:36:18,510\nSo if you see something, well it points up into there somewhere.\n\n370\n00:36:18,510 --> 00:36:21,780\nIs it pointing at a thing which you've not copied yet?\n\n371\n00:36:21,780 --> 00:36:23,880\nIs there a broken heart there?\n\n372\n00:36:23,880 --> 00:36:30,620\nIf there's a broken heart there and it's something you have copied, you've just replaced this pointer with the thing a broken heart points at.\n\n373\n00:36:30,620 --> 00:36:34,430\nIf this thing has not been copied, you copy it to the next place over here.\n\n374\n00:36:34,430 --> 00:36:43,670\nMove your free pointer over here, and then leave a broken heart behind and scan.\n\n375\n00:36:43,670 --> 00:36:50,140\nAnd eventually when the scant pointer hits the free pointer, everything in memory has been copied.\n\n376\n00:36:50,140 --> 00:36:54,470\nAnd then there's a whole bunch of empty space up here, which you could either make into a free list, if that's what you want to do.\n\n377\n00:36:54,470 --> 00:36:56,270\nBut generally you don't in this kind of system.\n\n378\n00:36:56,270 --> 00:37:00,910\nIn this system you sequentially allocate your memory.\n\n379\n00:37:00,910 --> 00:37:06,790\nThat is a very, very nice algorithm, and sort of the one we use in the scheme that you've been using.\n\n380\n00:37:06,790 --> 00:37:12,400\nAnd it's expected-- I believe no one has found a faster algorithm than that.\n\n381\n00:37:12,400 --> 00:37:22,010\nThere are very simple modifications to this algorithm invented by Henry Baker which allow one to run this algorithm in real time, meaning you don't have to stop to garbage collect.\n\n382\n00:37:22,010 --> 00:37:34,640\nBut you could interleave the consing that the machine does when its running with steps of the garbage collection process, so that the garbage collector's distributed, and the machine doesn't have to stop, and garbage collecting can start.\n\n383\n00:37:34,640 --> 00:37:44,460\nOf course in the case of machines with virtual memory where a lot of it is in inaccessible places, this becomes a very expensive process.\n\n384\n00:37:44,460 --> 00:37:49,190\nAnd there have been numerous attempts to make this much better.\n\n385\n00:37:49,190 --> 00:38:08,340\nThere is a nice paper, for those of you who are interested, by Moon and other people which describes a modification to the incremental Minsky-Feinchel-Yochelson algorithm, and modification the Baker algorithm which is more efficient for virtual memory systems.\n\n386\n00:38:08,340 --> 00:38:12,840\nWell I think now the mystery to this is sort of gone.\n\n387\n00:38:12,840 --> 00:38:14,090\nAnd I'd like to see if there are any questions.\n\n388\n00:38:19,780 --> 00:38:20,810\nYes.\n\n389\n00:38:20,810 --> 00:38:31,880\nAUDIENCE: I saw one of you run the garbage collector on the systems upstairs, and it seemed to me to run extremely fast. Did the whole thing take-- does it sweep through all of memory?\n\n390\n00:38:31,880 --> 00:38:32,510\nPROFESSOR: No.\n\n391\n00:38:32,510 --> 00:38:37,320\nIt swept through exactly what was needed to copy the useful structure.\n\n392\n00:38:37,320 --> 00:38:40,030\nIt's a copying collector.\n\n393\n00:38:40,030 --> 00:38:56,800\nAnd it is very fast. On the whole, I suppose to copy-- in a Bobcat-- to copy, I think, a three megabyte thing or something is less than a second, real time.\n\n394\n00:38:56,800 --> 00:39:05,400\nReally, these are very small programs. One thing you should realise is that garbage collectors have to be small.\n\n395\n00:39:05,400 --> 00:39:11,340\nNot because they have to be fast, but because no one can debug a complicated garbage collector.\n\n396\n00:39:11,340 --> 00:39:18,350\nA garbage collector, if it doesn't work, will trash your memory in such a way that you cannot figure out what the hell happened.\n\n397\n00:39:18,350 --> 00:39:20,660\nYou need an audit trail.\n\n398\n00:39:20,660 --> 00:39:23,740\nBecause it rearranges everything, and how do you know what happened there?\n\n399\n00:39:23,740 --> 00:39:31,970\nSo this is the only kind of program that it really, seriously matters if you stare at it long enough so you believe that it works.\n\n400\n00:39:31,970 --> 00:39:35,100\nAnd sort of prove it to yourself.\n\n401\n00:39:35,100 --> 00:39:36,940\nSo there's no way to debug it.\n\n402\n00:39:36,940 --> 00:39:41,690\nAnd that takes it being small enough so you can hold it in your head.\n\n403\n00:39:41,690 --> 00:39:45,020\nGarbage collectors are special in this way.\n\n404\n00:39:45,020 --> 00:39:52,430\nSo every reasonable garbage collector has gotten small, and generally small programs are fast. Yes.\n\n405\n00:39:52,430 --> 00:39:54,510\nAUDIENCE: Can you repeat the name of this technique once again?\n\n406\n00:39:54,510 --> 00:39:58,420\nPROFESSOR: That's the Minsky-Feinchel-Yochelson garbage collector.\n\n407\n00:39:58,420 --> 00:39:59,340\nAUDIENCE: You got that?\n\n408\n00:39:59,340 --> 00:40:02,210\nPROFESSOR: Minsky invented it in '61 for the RLE PDP-1.\n\n409\n00:40:02,210 --> 00:40:19,570\nA version of it was developed and elaborated to be used in Multics Maclisp by Feinchel and Yochelson in somewhere around 1968 or '69.\n\n410\n00:40:19,570 --> 00:40:20,650\nOK.\n\n411\n00:40:20,650 --> 00:40:22,640\nLet's take a break.\n\n412\n00:40:22,640 --> 00:40:24,184\n[MUSIC: \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n413\n00:41:17,310 --> 00:41:26,740\nPROFESSOR: Well we've come to the end of this subject, and we've already shown you a universal machine which is down to evaluator.\n\n414\n00:41:26,740 --> 00:41:30,420\nIt's down to the level of detail you could imagine you could make one.\n\n415\n00:41:30,420 --> 00:41:39,180\nThis is a particular implementation of Lisp, built on one of those scheme chips that was talked about yesterday, sitting over here.\n\n416\n00:41:39,180 --> 00:41:45,010\nThis is mostly interface to somebody's memory with a little bit of timing and other such stuff.\n\n417\n00:41:45,010 --> 00:41:50,610\nBut this fellow actually ran Lisp at a fairly reasonable rate, as interpretive.\n\n418\n00:41:50,610 --> 00:41:56,500\nIt ran Lisp as fast as a DEC PDP-10 back in 1979.\n\n419\n00:41:56,500 --> 00:41:59,870\nAnd so it's gotten pretty hardware.\n\n420\n00:41:59,870 --> 00:42:02,470\nPretty concrete.\n\n421\n00:42:02,470 --> 00:42:07,370\nWe've also downed you a bit with the things you can compute.\n\n422\n00:42:07,370 --> 00:42:11,850\nBut is it the case that there are things we can't compute?\n\n423\n00:42:11,850 --> 00:42:18,190\nAnd so I'd like to end this with showing you some things that you'd like be able to compute that you can't.\n\n424\n00:42:18,190 --> 00:42:22,720\nThe answer is yes, there are things you can't compute.\n\n425\n00:42:22,720 --> 00:42:34,630\nFor example, something you'd really like is-- if you're writing [UNINTELLIGIBLE], you'd like a program that would check that the thing you're going to do will work.\n\n426\n00:42:34,630 --> 00:42:36,080\nWouldn't that be nice?\n\n427\n00:42:36,080 --> 00:42:43,190\nYou'd like something that would catch infinite loops, for example, in programs that were written by users.\n\n428\n00:42:43,190 --> 00:42:50,990\nBut in general you can't write such a program that will read any program and determine whether or not it's an infinite loop.\n\n429\n00:42:50,990 --> 00:42:51,685\nLet me show you that.\n\n430\n00:42:51,685 --> 00:42:53,340\nIt's a little bit of a minor mathematics.\n\n431\n00:42:58,780 --> 00:43:02,620\nLet's imagine that we just had a mathematical function before we start.\n\n432\n00:43:02,620 --> 00:43:14,230\nAnd there is one, called s, which takes a procedure and its argument, a.\n\n433\n00:43:19,320 --> 00:43:26,632\nAnd what s does is it determines whether or not it's safe to run p on a.\n\n434\n00:43:26,632 --> 00:43:45,330\nAnd what I mean by that is this: it's true if p applied to a will converge to a value without an error.\n\n435\n00:43:52,365 --> 00:44:06,890\nAnd it's false if p of a loops forever or makes an error.\n\n436\n00:44:15,000 --> 00:44:18,780\nNow that's surely a function.\n\n437\n00:44:18,780 --> 00:44:28,440\nThere is some for every procedure and for every argument you could give it that is either true or false that it converges without making an error.\n\n438\n00:44:28,440 --> 00:44:31,770\nAnd you could make a giant table of them.\n\n439\n00:44:31,770 --> 00:44:37,430\nBut the question is, can you write a procedure that compute the values of this function?\n\n440\n00:44:37,430 --> 00:44:39,720\nWell let's assume that we can.\n\n441\n00:44:39,720 --> 00:44:59,990\nSuppose that we have a procedure called \"safe\" that computes the value of s.\n\n442\n00:45:12,170 --> 00:45:19,760\nNow I'm going to show you by several methods that you can't do this.\n\n443\n00:45:19,760 --> 00:45:23,810\nThe easiest one, or the first one, let's define a procedure called diag1.\n\n444\n00:45:23,810 --> 00:45:44,780\nGiven that we have safe, we can define diag1 to be the procedure of one argument, p, which has the following properties.\n\n445\n00:45:44,780 --> 00:45:55,870\nIf if it's safe to apply p to itself, then I wish to have an infinite loop.\n\n446\n00:45:59,330 --> 00:46:00,715\nOtherwise I'm going to return 3.\n\n447\n00:46:03,680 --> 00:46:04,470\nRemember it was 42.\n\n448\n00:46:04,470 --> 00:46:07,060\nWhat's the answer to the big question?\n\n449\n00:46:07,060 --> 00:46:08,525\nWhere of course we know what an infinite loop is.\n\n450\n00:46:12,050 --> 00:46:18,430\nInfinite loop, to be a procedure of no arguments, which is that nice lambda calculus loop.\n\n451\n00:46:18,430 --> 00:46:24,680\nLambda of x, x of x, applied to lambda of x, x of x.\n\n452\n00:46:24,680 --> 00:46:26,550\nSo there's nothing left to the imagination here.\n\n453\n00:46:29,830 --> 00:46:32,500\nWell let's see what the story is.\n\n454\n00:46:32,500 --> 00:46:43,180\nI'm supposing it's the case that we worry about the procedure called diag1 applied to diag1.\n\n455\n00:46:45,860 --> 00:46:49,970\nWell what could it possibly be?\n\n456\n00:46:49,970 --> 00:46:51,390\nWell I don't know.\n\n457\n00:46:51,390 --> 00:46:57,310\nWe're going to substitute diag1 for p in the body here.\n\n458\n00:46:57,310 --> 00:47:00,220\nWell is it safe to compute diag1 of diag1?\n\n459\n00:47:00,220 --> 00:47:00,780\nI don't know.\n\n460\n00:47:00,780 --> 00:47:03,400\nThere are two possibilities.\n\n461\n00:47:03,400 --> 00:47:08,490\nIf it's safe to compute diag1 of diag1 that means it shouldn't loop.\n\n462\n00:47:08,490 --> 00:47:10,560\nThat means I go to here, but then I produce an infinite loop.\n\n463\n00:47:10,560 --> 00:47:12,210\nSo it can't be safe.\n\n464\n00:47:12,210 --> 00:47:16,020\nBut if it's not safe to compute diag1 of diag1 then the answer to this is 3.\n\n465\n00:47:16,020 --> 00:47:20,530\nBut that's diag1 of diag1, so it had to be safe.\n\n466\n00:47:20,530 --> 00:47:27,470\nSo therefore by contradiction you cannot produce safe.\n\n467\n00:47:27,470 --> 00:47:32,820\nFor those of you who were boggled by that one I'm going to say it again, in a different way.\n\n468\n00:47:32,820 --> 00:47:35,530\nListen to one more alternative.\n\n469\n00:47:35,530 --> 00:47:36,780\nLet's define diag2.\n\n470\n00:47:39,840 --> 00:47:45,260\nThese are named diag because of Cantor's diagonal argument.\n\n471\n00:47:45,260 --> 00:48:00,190\nThese are instances of a famous argument which was originally used by Cantor in the late part of the last century to prove that the real numbers were not countable, that there are too many real numbers to be counted by integers.\n\n472\n00:48:00,190 --> 00:48:05,260\nThat there are more points on a line, for example, than there are counting numbers.\n\n473\n00:48:05,260 --> 00:48:08,440\nIt may or may not be obvious, and I don't want to get into that now.\n\n474\n00:48:10,900 --> 00:48:15,820\nBut diag2 is again a procedure of one argument p.\n\n475\n00:48:15,820 --> 00:48:38,960\nIt's almost the same as the previous one, which is, if it's safe to compute p on p, then I'm going to produce--  then I want to compute some other things other than p of p.\n\n476\n00:48:38,960 --> 00:48:40,210\nOtherwise I'm going to put out false.\n\n477\n00:48:43,600 --> 00:48:48,880\nWhere other then it says, whatever p of p, I'm going to put out something else.\n\n478\n00:48:48,880 --> 00:48:53,890\nI can give you an example of a definition of other than which I think works.\n\n479\n00:48:53,890 --> 00:48:55,640\nLet's see.\n\n480\n00:48:55,640 --> 00:48:56,330\nYes.\n\n481\n00:48:56,330 --> 00:49:15,720\nWhere other than be a procedure of one argument x which says, if its eq x to, say, quote a, then the answer is quote b.\n\n482\n00:49:15,720 --> 00:49:16,970\nOtherwise it's quote a.\n\n483\n00:49:20,090 --> 00:49:25,350\nThat always produces something which is not what its argument is.\n\n484\n00:49:25,350 --> 00:49:26,540\nThat's all it is.\n\n485\n00:49:26,540 --> 00:49:28,250\nThat's all I wanted.\n\n486\n00:49:28,250 --> 00:49:30,640\nWell now let's consider this one, diag2 of diag2.\n\n487\n00:49:38,220 --> 00:49:39,560\nWell look.\n\n488\n00:49:39,560 --> 00:49:47,470\nThis only does something dangerous, like calling p of p, if it's safe to do so.\n\n489\n00:49:47,470 --> 00:49:57,225\nSo if safe defined at all, if you can define such a procedure, safe, then this procedure is always defined and therefore safe on any inputs.\n\n490\n00:50:01,540 --> 00:50:11,770\nSo diag2 of diag2 must reduce to other than diag2 of diag2.\n\n491\n00:50:15,496 --> 00:50:22,950\nAnd that doesn't make sense, so we have a contradiction, and therefore we can't define safe.\n\n492\n00:50:22,950 --> 00:50:32,260\nI just waned to do that twice, slightly differently, so you wouldn't feel that the first one was a trick.\n\n493\n00:50:32,260 --> 00:50:37,300\nThey may be both tricks, but they're at least slightly different.\n\n494\n00:50:37,300 --> 00:50:40,080\nSo I suppose that pretty much wraps it up.\n\n495\n00:50:40,080 --> 00:50:46,720\nI've just proved what we call the halting theorem, and I suppose with that we're going to halt.\n\n496\n00:50:46,720 --> 00:50:47,970\nI hope you have a good time.\n\n497\n00:50:50,900 --> 00:50:53,300\nAre there any questions?\n\n498\n00:50:53,300 --> 00:50:53,810\nYes.\n\n499\n00:50:53,810 --> 00:50:56,940\nAUDIENCE: What is the value of s of diag1?\n\n500\n00:50:56,940 --> 00:50:57,430\nPROFESSOR: Of what?\n\n501\n00:50:57,430 --> 00:51:00,120\nAUDIENCE: S of diag1.\n\n502\n00:51:00,120 --> 00:51:02,620\nIf you said s is a function and we can [INTERPOSING VOICES]\n\n503\n00:51:02,620 --> 00:51:03,870\nPROFESSOR: Oh, I don't know.\n\n504\n00:51:03,870 --> 00:51:04,350\nI don't know.\n\n505\n00:51:04,350 --> 00:51:06,850\nIt's a function, but I don't know how to compute it.\n\n506\n00:51:06,850 --> 00:51:08,610\nI can't do it.\n\n507\n00:51:08,610 --> 00:51:11,530\nI'm just a machine, too.\n\n508\n00:51:11,530 --> 00:51:12,210\nRight?\n\n509\n00:51:12,210 --> 00:51:18,580\nThere's no machine that in principle-- it might be that in that particular case you just asked, with some thinking I could figure it out.\n\n510\n00:51:18,580 --> 00:51:23,780\nBut in general I can't compute the value of s any better than any other machine can.\n\n511\n00:51:23,780 --> 00:51:29,580\nThere is such a function, it's just that no machine can be built to compute it.\n\n512\n00:51:29,580 --> 00:51:35,350\nNow there's a way of saying that that should not be surprising.\n\n513\n00:51:35,350 --> 00:51:44,600\nGoing through this-- I mean, I don't have time to do this here, but the number of functions is very large.\n\n514\n00:51:44,600 --> 00:51:54,720\nIf there's a certain number of answers possible and a certain number of inputs possible, then it's the number of answers raised to the number inputs is the number of possible functions.\n\n515\n00:51:54,720 --> 00:51:55,970\nOn one variable.\n\n516\n00:51:58,150 --> 00:52:05,480\nNow that's always bigger than the thing you're raising to, the exponent.\n\n517\n00:52:05,480 --> 00:52:17,840\nThe number of functions is larger than the number of programs that one can write, by an infinity counting argument.\n\n518\n00:52:17,840 --> 00:52:19,475\nAnd it's much larger.\n\n519\n00:52:19,475 --> 00:52:26,280\nSo there must be a lot of functions that can't be computed by programs.\n\n520\n00:52:26,280 --> 00:52:30,640\nAUDIENCE: A few moments ago you were talking about specifications and automatic generation of solutions.\n\n521\n00:52:30,640 --> 00:52:33,360\nDo you see any steps between specifications and solutions?\n\n522\n00:52:37,250 --> 00:52:38,720\nPROFESSOR: Steps between.\n\n523\n00:52:38,720 --> 00:52:45,205\nYou mean, you're saying, how you go about constructing devices given that have specifications for the device?\n\n524\n00:52:45,205 --> 00:52:45,500\nSure.\n\n525\n00:52:45,500 --> 00:52:52,430\nAUDIENCE: There's a lot of software engineering that goes through specifications through many layers of design and then implementation.\n\n526\n00:52:52,430 --> 00:52:52,850\nPROFESSOR: Yes?\n\n527\n00:52:52,850 --> 00:52:55,600\nAUDIENCE: I was curious if you think that's realistic.\n\n528\n00:52:55,600 --> 00:52:58,100\nPROFESSOR: Well I think that some of it's realistic and some of it isn't.\n\n529\n00:52:58,100 --> 00:53:07,160\nI mean, surely if I want to build an electrical filter and I have a rather interesting possibility.\n\n530\n00:53:07,160 --> 00:53:19,906\nSupposing I want to build a thing that matches some power output to the radio transmitter, to some antenna.\n\n531\n00:53:19,906 --> 00:53:23,230\nAnd I'm really out of this power-- it's output tube out here.\n\n532\n00:53:23,230 --> 00:53:25,920\nAnd the problem is that they have different impedances.\n\n533\n00:53:25,920 --> 00:53:27,550\nI want them to match the impedances.\n\n534\n00:53:27,550 --> 00:53:32,780\nI also want to make a filter in there which is going to get rid of some harmonic radiation.\n\n535\n00:53:32,780 --> 00:53:38,860\nWell one old-fashioned technique for doing this is called image impedances, or something like that.\n\n536\n00:53:38,860 --> 00:53:43,300\nAnd what you do is you say you have a basic module called an L-section.\n\n537\n00:53:43,300 --> 00:53:44,550\nLooks like this.\n\n538\n00:53:47,080 --> 00:54:02,110\nIf I happen to connect this to some resistance, r, and if I make this impedance x, xl, and if it happens to be q times r, then this produces a low pass filter with a q square plus one impedance match.\n\n539\n00:54:02,110 --> 00:54:03,120\nJust what I need.\n\n540\n00:54:03,120 --> 00:54:06,510\nBecause now I can take two of these, hook them together like this.\n\n541\n00:54:11,660 --> 00:54:18,290\nOK, and I take another one and I'll hook them together like that.\n\n542\n00:54:18,290 --> 00:54:20,320\nAnd I have two L-sections hooked together.\n\n543\n00:54:20,320 --> 00:54:25,530\nAnd this will step the impedance down to one that I know, and this will step it up to one I know.\n\n544\n00:54:25,530 --> 00:54:28,090\nEach of these is a low pass filter getting rid of some harmonics.\n\n545\n00:54:28,090 --> 00:54:30,270\nIt's good filter, it's called a pie-section filter.\n\n546\n00:54:30,270 --> 00:54:31,700\nGreat.\n\n547\n00:54:31,700 --> 00:54:38,620\nExcept for the fact that in doing what I just did, I've made a terrible inefficiency in this system.\n\n548\n00:54:38,620 --> 00:54:41,620\nI've made two coils where I should have made one.\n\n549\n00:54:41,620 --> 00:54:55,350\nAnd the problem with most software engineering art is that there's no mechanism, other than peephole optimization and compilers, for getting rid of the redundant parts that are constructed when doing top down design.\n\n550\n00:54:55,350 --> 00:55:01,110\nIt's even worse, there are lots of very important structures that you can't construct at all this way.\n\n551\n00:55:01,110 --> 00:55:05,710\nSo I think that the standard top down design is a rather shallow business.\n\n552\n00:55:05,710 --> 00:55:08,315\nDoesn't really capture what people want to do in design.\n\n553\n00:55:08,315 --> 00:55:10,100\nI'll give you another electrical example.\n\n554\n00:55:10,100 --> 00:55:17,220\nElectrical examples are so much clearer than computational examples, because computation examples require a certain degree of complexity to explain them.\n\n555\n00:55:17,220 --> 00:55:27,530\nBut one of my favorite examples in the electrical world is how would I ever come up with the output stage of this inter-stage connection in an IF amplifier.\n\n556\n00:55:27,530 --> 00:55:32,410\nIt's a little transistor here, and let's see.\n\n557\n00:55:32,410 --> 00:55:44,850\nWell I'm going to have a tank, and I'm going to hook this up to, say, I'm going to link-couple that to the input of the next stage.\n\n558\n00:55:44,850 --> 00:55:53,170\nHere's a perfectly plausible plan-- well except for the fact that since I put that going up I should make that going that way.\n\n559\n00:55:53,170 --> 00:55:57,270\nHere's a perfectly plausible plan for a-- no I shouldn't.\n\n560\n00:55:57,270 --> 00:55:57,940\nI'm dumb.\n\n561\n00:55:57,940 --> 00:55:59,690\nExcuse me.\n\n562\n00:55:59,690 --> 00:56:00,730\nDoesn't matter.\n\n563\n00:56:00,730 --> 00:56:01,540\nThe point is [UNINTELLIGIBLE]\n\n564\n00:56:01,540 --> 00:56:02,560\nplan for a couple [UNINTELLIGIBLE]\n\n565\n00:56:02,560 --> 00:56:04,590\nstages together.\n\n566\n00:56:04,590 --> 00:56:07,620\nNow what the problem is is what's this hierarchically?\n\n567\n00:56:07,620 --> 00:56:09,480\nIt's not one thing.\n\n568\n00:56:09,480 --> 00:56:11,990\nHierarchically it doesn't make any sense at all.\n\n569\n00:56:11,990 --> 00:56:26,460\nIt's the inductance of a tuned circuit, it's the primary of a transformer, and it's also the DC path by which bias conditions get to the collector of that transistor.\n\n570\n00:56:26,460 --> 00:56:34,530\nAnd there's no simple top-down design that's going to produce a structure like that with so many overlapping uses for a particular thing.\n\n571\n00:56:34,530 --> 00:56:44,950\nPlaying Scrabble, where you have to do triple word scores, or whatever, is not so easy in top-down design strategy.\n\n572\n00:56:44,950 --> 00:56:52,140\nYet most of real engineering is based on getting the most oomph for effort.\n\n573\n00:56:52,140 --> 00:56:54,860\nAnd that's what you're seeing here.\n\n574\n00:56:54,860 --> 00:56:55,550\nYeah?\n\n575\n00:56:55,550 --> 00:56:56,810\nAUDIENCE: Is this the last question?\n\n576\n00:57:00,282 --> 00:57:18,640\n[LAUGHTER]\n\n577\n00:57:18,640 --> 00:57:19,890\nPROFESSOR: Apparently so.\n\n578\n00:57:23,240 --> 00:57:26,092\nThank you.\n\n579\n00:57:26,092 --> 00:57:39,040\n[APPLAUSE]\n\n580\n00:57:39,040 --> 00:57:40,633\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n"
  },
  {
    "path": "SrtCN/lec10b.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:00,720\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:00,720 --> 00:00:02,720\n翻译&&时间轴：杨启钊（windfarer）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:02,720 --> 00:00:04,725\n特别感谢：裘宗燕教授\n\n4\n00:00:04,720 --> 00:00:11,808\n计算机程序的构造和解释\n\n5\n00:00:11,888 --> 00:00:18,112\n存储分配与垃圾收集\n\n6\n00:00:18,910 --> 00:00:20,612\n教授: 接下来我要解开\nPROFESSOR: Well, there's one bit of mystery left,\n\n7\n00:00:21,168 --> 00:00:23,360\n目前仅剩的谜团\nwhich I'd like to get rid of right now.\n\n8\n00:00:24,440 --> 00:00:28,804\n我们能毫无顾虑地进行CONS\nAnd that's that we've been blithely doing things like cons\n\n9\n00:00:30,000 --> 00:00:31,620\n就好像空间足够多一样\nassuming there's always another one.\n\n10\n00:00:32,800 --> 00:00:36,320\n我们总是在使用\nThat we've been doing these things like\n\n11\n00:00:36,510 --> 00:00:37,440\nCAR和CDR\ncar-ing and cdr-ing\n\n12\n00:00:37,470 --> 00:00:38,720\n并假设知道我们知道\nand assuming that we had some idea\n\n13\n00:00:38,752 --> 00:00:39,740\n它们是如何实现的\nhow this can be done.\n\n14\n00:00:40,020 --> 00:00:40,675\n事实上\nNow indeed\n\n15\n00:00:41,075 --> 00:00:44,403\n我们认为它们是基本过程\nwe said that that's equivalent to having procedures.\n\n16\n00:00:45,376 --> 00:00:47,570\n但这没有真正解决问题\nOK? But that doesn't really solve the problem,\n\n17\n00:00:47,730 --> 00:00:50,256\n因为过程依赖各种复杂的机制\nbecause the procedure need all sorts of complicated mechanisms\n\n18\n00:00:50,272 --> 00:00:51,376\n需要诸如环境结构之类的东西\nlike environment structures\n\n19\n00:00:51,640 --> 00:00:52,768\n才能运行起来\nand things like that to work.\n\n20\n00:00:53,010 --> 00:00:54,890\n而归根结底它们也是\nAnd those were ultimately made out of conses\n\n21\n00:00:54,890 --> 00:00:56,425\n由CONS之类的东西构成的\nin the model that we had,\n\n22\n00:00:56,700 --> 00:00:58,473\n这的确没有解决问题\nso that really doesn't solve the problem.\n\n23\n00:00:59,380 --> 00:01:01,136\n目前的问题是\nNow the problem here is\n\n24\n00:01:01,312 --> 00:01:03,970\n粘合这些数据结构的是什么东西？\nis the glue the data structure's made out of.\n\n25\n00:01:04,760 --> 00:01:06,409\n它可能是怎样的一个东西?\nWhat kind of possible thing could it be?\n\n26\n00:01:07,040 --> 00:01:10,460\n我们已经见过了一台机器\nOK? We've been showing you things like a machine,\n\n27\n00:01:10,460 --> 00:01:13,968\n一台计算机具有一个控制器\na computer that has a controller,\n\n28\n00:01:14,275 --> 00:01:15,450\n和一些寄存器\nand some registers,\n\n29\n00:01:15,450 --> 00:01:16,475\n还可能有一个栈\nand maybe a stack.\n\n30\n00:01:16,980 --> 00:01:18,128\n但是我们还没提到一些东西\nAnd we haven't said anything about,\n\n31\n00:01:18,160 --> 00:01:19,950\n例如 大内存\nfor example, larger memory.\n\n32\n00:01:20,570 --> 00:01:22,382\n我想 现在是时候讨论它们了\nAnd I think that's what we have to worry about right now.\n\n33\n00:01:23,740 --> 00:01:26,560\n但是先要说清楚\nBut just to make it perfectly clear\n\n34\n00:01:26,592 --> 00:01:27,888\n这个并不是必须的\nthat this is an inessential,\n\n35\n00:01:28,825 --> 00:01:30,791\n只是一些实现上的细节\npurely implementational thing,\n\n36\n00:01:31,100 --> 00:01:32,600\n让我举个例子\nI'd like to show you, for example,\n\n37\n00:01:32,600 --> 00:01:34,208\n如何用数字来表示这些东西\nhow you can do it all with the numbers.\n\n38\n00:01:35,232 --> 00:01:36,820\n有个比较简单的方法\nThat's an easy one.\n\n39\n00:01:37,590 --> 00:01:39,000\n一位著名的逻辑学家 哥德尔\nFamous fellow by the name of Godel,\n\n40\n00:01:44,096 --> 00:01:46,016\n在20世纪30年代末\na logician at the end of the 1930s,\n\n41\n00:01:46,384 --> 00:01:48,700\n发明了一个很巧妙的方法\ninvented a very clever way\n\n42\n00:01:48,700 --> 00:01:52,275\n能够把复杂的表达式\nof encoding the complicated expressions\n\n43\n00:01:52,816 --> 00:01:53,520\n表示成数字\nas numbers.\n\n44\n00:01:54,320 --> 00:01:55,050\n例如\nFor example--\n\n45\n00:01:55,050 --> 00:01:58,000\n我不会照搬哥德尔的方法\nI'm not saying exactly what Godel's scheme is,\n\n46\n00:01:58,000 --> 00:01:59,488\n因为他没有使用CONS之类的术语\nbecause he didn't use words like cons.\n\n47\n00:01:59,660 --> 00:02:00,608\n他使用了其它的组合手段\nHe had other kinds of\n\n48\n00:02:00,912 --> 00:02:02,600\n来编码表达式\nof ways of combining to make expressions.\n\n49\n00:02:03,090 --> 00:02:03,888\n他的思路是\nBut he said,\n\n50\n00:02:03,920 --> 00:02:06,816\n用不同数字分别代表每个代数式\nI'm going to assign a number to every algebraic expression.\n\n51\n00:02:07,920 --> 00:02:09,725\n通过组合各个部分的数字\nAnd the way I'm going to manufacture these numbers\n\n52\n00:02:09,725 --> 00:02:11,650\n来形成新的表达式\nis by combining the numbers of the parts.\n\n53\n00:02:12,470 --> 00:02:13,456\n举例来说\nSo for example,\n\n54\n00:02:13,625 --> 00:02:15,350\n我们在创造世界的时候\nwhat we were doing our world,\n\n55\n00:02:15,350 --> 00:02:18,016\n如果用数字\nwe could say that if objects\n\n56\n00:02:20,784 --> 00:02:22,220\n来表示对象\nare represented by numbers,\n\n57\n00:02:30,670 --> 00:02:37,936\n那么(CONS X Y)\nthen cons of x and y\n\n58\n00:02:38,040 --> 00:02:41,072\n就可以表示为\ncould be represented by,\n\n59\n00:02:41,552 --> 00:02:43,770\n2^X * 3^Y\n2 to the x times 3 to the y.\n\n60\n00:02:46,130 --> 00:02:48,032\n因为这样我们还能取出它的每一部分\nBecause then we could extract the parts.\n\n61\n00:02:49,560 --> 00:02:50,976\n举例来说\nWe could say, for example,\n\n62\n00:02:51,184 --> 00:02:55,888\n(CAR X)\nthat then car of, say, x\n\n63\n00:02:56,550 --> 00:03:05,184\n就是X中因数2的个数\nis the number of factors of 2 in x.\n\n64\n00:03:06,690 --> 00:03:08,784\n当然(CDR X)是一样的\nOK? And of course cdr is the same thing.\n\n65\n00:03:10,690 --> 00:03:15,579\n它就X中因数3的个数\nIt's the number of factors of 3 in x.\n\n66\n00:03:16,510 --> 00:03:18,651\n这是个非常合理的方案\nNow this is a perfectly reasonable scheme,\n\n67\n00:03:19,100 --> 00:03:20,112\n只不过就是\nexcept for the fact that\n\n68\n00:03:20,120 --> 00:03:22,528\n数字的位数\nthe numbers rapidly get to be much larger\n\n69\n00:03:22,832 --> 00:03:23,980\n会急剧地增大\nin number of digits\n\n70\n00:03:24,320 --> 00:03:26,550\n甚至比宇宙中的粒子还多\nthan the number of protons in the universe.\n\n71\n00:03:27,950 --> 00:03:29,888\n所以除了在理论中\nSo there's no easy way to use this scheme\n\n72\n00:03:29,904 --> 00:03:31,216\n没有实现这种方案的好办法\nother than the theoretical one.\n\n73\n00:03:33,430 --> 00:03:34,486\n另一方面\nOn the other hand,\n\n74\n00:03:35,125 --> 00:03:37,558\n也有其它的表示方式\nthere are other ways of representing these things.\n\n75\n00:03:38,450 --> 00:03:40,016\n我们把它们表示为\nWe have been thinking in terms\n\n76\n00:03:40,256 --> 00:03:42,420\n一些小盒子\nof little boxes, boxes.\n\n77\n00:03:43,320 --> 00:03:46,432\n我们把CONS结构\nWe've been thinking about our cons structures\n\n78\n00:03:46,500 --> 00:03:48,054\n想象为这样的东西\nas looking sort of like this.\n\n79\n00:03:50,280 --> 00:03:52,576\n它们是里面装着东西的小隔间\nThey're little pigeon holes with things in them.\n\n80\n00:03:53,568 --> 00:03:55,470\n这些格子组成一个树\nAnd of course we arrange them in little trees.\n\n81\n00:03:57,210 --> 00:03:59,975\n我希望半导体制造商\nI wish that the semiconductor manufacturers\n\n82\n00:03:59,975 --> 00:04:02,075\n能够提供适配这样需求的芯片\nwould supply me with something appropriate for this,\n\n83\n00:04:02,700 --> 00:04:03,760\n但事实上\nbut actually\n\n84\n00:04:03,850 --> 00:04:05,312\n他们提供给我的却是\nwhat they do supply me with\n\n85\n00:04:06,208 --> 00:04:07,960\n线性的内存\nis a linear memory.\n\n86\n00:04:09,380 --> 00:04:13,467\n内存是一串小隔间\nMemory is sort of a big pile of pigeonholes,\n\n87\n00:04:15,120 --> 00:04:16,340\n像这样的小隔间\npigeonholes like this.\n\n88\n00:04:17,720 --> 00:04:20,251\n每个小隔间里可以保存确定大小的对象\nEach of which can hold a certain sized object,\n\n89\n00:04:20,944 --> 00:04:22,200\n一个尺寸固定的对象\na fixed size object.\n\n90\n00:04:23,390 --> 00:04:24,075\n例如\nSo, for example,\n\n91\n00:04:24,070 --> 00:04:25,664\n一个含25个元素的表\na complicated list with 25 elements\n\n92\n00:04:25,664 --> 00:04:26,640\n就放不进这里\nwon't fit in one of these.\n\n93\n00:04:28,550 --> 00:04:29,264\n然而 它们中的每一个\nHowever, each of these\n\n94\n00:04:29,296 --> 00:04:30,880\n都是由地址索引的\nis indexed by an address.\n\n95\n00:04:33,970 --> 00:04:34,992\n因此它们的地址可能是\nSo the address might be\n\n96\n00:04:35,024 --> 00:04:35,500\n这里是0\nzero here,\n\n97\n00:04:35,500 --> 00:04:36,225\n这里是1\none here,\n\n98\n00:04:36,225 --> 00:04:36,700\n这里是2\ntwo here,\n\n99\n00:04:36,700 --> 00:04:37,250\n这里是3\nthree here,\n\n100\n00:04:37,250 --> 00:04:37,944\n以此类推\nand so on.\n\n101\n00:04:38,060 --> 00:04:40,400\n这里写的数字并不重要\nThat we write these down as numbers is unimportant.\n\n102\n00:04:40,400 --> 00:04:41,680\n重要的是 它们不重复\nWhat matters is that they're distinct\n\n103\n00:04:41,950 --> 00:04:43,425\n有了它们就能找到下一个在哪\nas a way to get to the next one.\n\n104\n00:04:44,970 --> 00:04:46,144\n在其中每一个小隔间里面\nAnd inside of each of these,\n\n105\n00:04:46,366 --> 00:04:49,110\n我们可以把东西放进去\nwe can stuff something into these pigeonholes.\n\n106\n00:04:49,530 --> 00:04:50,774\n对于没有造过计算机的我们来说\nThat's what memory is like,\n\n107\n00:04:51,020 --> 00:04:53,664\n内存就是这样子的\nfor those of you who haven't built a computer.\n\n108\n00:04:54,150 --> 00:04:54,650\n现在\nNow.\n\n109\n00:04:56,690 --> 00:04:57,536\n现在的问题是\nNow the problem is\n\n110\n00:04:57,536 --> 00:04:59,970\n如何用这样的结构\nhow are we going to impose on this type of structure,\n\n111\n00:05:00,425 --> 00:05:01,725\n来实现这个树形结构\nthis nice tree structure.\n\n112\n00:05:03,290 --> 00:05:04,575\n其实并不难\nWell it's not very hard,\n\n113\n00:05:04,575 --> 00:05:06,350\n已经有大量的方案来做这个了\nand there have been numerous schemes involved in this.\n\n114\n00:05:06,875 --> 00:05:08,800\n最重要的一个方案是\nThe most important one is to say,\n\n115\n00:05:08,800 --> 00:05:11,184\n假设半导体制造商\nwell assuming that the semiconductor manufacturer\n\n116\n00:05:11,200 --> 00:05:13,904\n允许我安排自己的内存\nallows me to arrange my memory\n\n117\n00:05:13,984 --> 00:05:15,770\n使得其中每个小隔间都足够大\nso that one of these pigeonholes is big enough\n\n118\n00:05:16,280 --> 00:05:18,208\n能够装得下另一个的地址\nto hold the address of another\n\n119\n00:05:19,350 --> 00:05:20,831\n我需要这么来安排\nOK. I have been made.\n\n120\n00:05:22,050 --> 00:05:23,456\n事实上它需要更大一点\nNow it actually has to be a little bit bigger\n\n121\n00:05:23,480 --> 00:05:27,520\n因为我还要在里面存放一些信息\nbecause I have to also install or store some information\n\n122\n00:05:27,568 --> 00:05:30,096\n它标示了这里面是什么东西\nas to a tag which describes the kind of thing that's there.\n\n123\n00:05:30,390 --> 00:05:31,647\n我们过一会就能看到\nAnd we'll see that in a second.\n\n124\n00:05:32,620 --> 00:05:34,400\n当然 如果半导体制造商\nAnd of course if the semiconductor manufacturer\n\n125\n00:05:34,432 --> 00:05:35,888\n没有这么来制造\ndoesn't arrange it so I can do that,\n\n126\n00:05:36,080 --> 00:05:38,448\n我就需要用一些机智的方式\nthen of course I can, with some cleverness,\n\n127\n00:05:38,575 --> 00:05:41,823\n把它们组合起来以供使用\narrange combinations of these to fit together in that way.\n\n128\n00:05:43,770 --> 00:05:47,050\n我们想象一下\nSo we're going to have to imagine\n\n129\n00:05:47,050 --> 00:05:49,546\n把这个复杂的树形结构\nimposing this complicated tree structure\n\n130\n00:05:49,546 --> 00:05:51,200\n塞进线性内存里\non our nice linear memory.\n\n131\n00:05:51,740 --> 00:05:54,475\n我们来看第一张幻灯片\nIf we look at the first still store,\n\n132\n00:05:54,475 --> 00:05:58,304\n可以看到一个传统的实现方案\nwe see a classic scheme for doing that.\n\n133\n00:05:59,490 --> 00:06:02,625\n它是把表结构放入线性内存\nIt's a standard way of representing list structures\n\n134\n00:06:03,225 --> 00:06:05,875\n的标准方式\nin a linear memory.\n\n135\n00:06:06,275 --> 00:06:08,325\n我们把这块内存\nWhat we do is we divide this memory\n\n136\n00:06:08,880 --> 00:06:11,120\n分为两部分\ninto two parts.\n\n137\n00:06:12,030 --> 00:06:13,427\n一个叫THE-CARS的数组\nAn array called the cars,\n\n138\n00:06:14,450 --> 00:06:15,888\n一个叫THE-CDRS的数组\nand an array called the cdrs.\n\n139\n00:06:17,580 --> 00:06:18,864\n无论它们是\nNow whether those happen to be\n\n140\n00:06:18,880 --> 00:06:21,040\n顺序的地址或是其它的\nsequential addresses or whatever,\n\n141\n00:06:21,120 --> 00:06:22,000\n其实并不重要\nit's not important.\n\n142\n00:06:22,875 --> 00:06:25,203\n这是实现细节了\nThat's somebody's implementation details.\n\n143\n00:06:25,800 --> 00:06:28,403\n但有两个数组\nBut there are two arrays here.\n\n144\n00:06:28,960 --> 00:06:30,368\n线性数组是由\nLinear arrays indexed\n\n145\n00:06:30,464 --> 00:06:32,590\n顺序的下标索引的\nby sequential indices like this.\n\n146\n00:06:34,840 --> 00:06:36,851\n每个小格子里存的\nWhat is stored in each of these pigeonholes\n\n147\n00:06:37,467 --> 00:06:39,859\n是一个带类型的对象\nis a typed object.\n\n148\n00:06:41,430 --> 00:06:42,575\n这里的类型\nAnd what we have here\n\n149\n00:06:42,570 --> 00:06:45,712\n以字母P开头\nare types which begin with letters like p,\n\n150\n00:06:45,712 --> 00:06:46,576\n表示序对\nstanding for a pair.\n\n151\n00:06:47,790 --> 00:06:49,375\n以N开头 表示数字\nOr n, standing for a number.\n\n152\n00:06:50,040 --> 00:06:52,255\nE开头 表示空表\nOr e, standing for an empty list.\n\n153\n00:06:54,813 --> 00:06:55,839\n也就是表尾标志\nThe end of the list.\n\n154\n00:06:57,020 --> 00:06:58,592\n如果我们想表示\nAnd so if we wish to represent\n\n155\n00:06:58,992 --> 00:06:59,970\n这样一个对象\nan object like this,\n\n156\n00:07:00,016 --> 00:07:02,160\n首元素为(1 2)\nthe list beginning with 1, 2\n\n157\n00:07:02,650 --> 00:07:04,016\n然后3、4分别作为\nand then having a 3 and a 4\n\n158\n00:07:04,016 --> 00:07:05,500\n它的第二和第三个元素\nand then having a 3 and a 4 as its second and third elements.\n\n159\n00:07:06,430 --> 00:07:08,831\n这个表的第一部分也是一个表\nA list containing a list as its first part\n\n160\n00:07:09,350 --> 00:07:10,650\n后面接着是两个数字\nand then two numbers\n\n161\n00:07:10,650 --> 00:07:12,000\n分别为第二和第三部分\nas a second and third parts.\n\n162\n00:07:12,870 --> 00:07:14,816\n现在我们用盒子-指针表示法\nThen of course we draw it sort of like this these days,\n\n163\n00:07:14,848 --> 00:07:16,670\n来描绘它\nin box-and-pointer notation.\n\n164\n00:07:17,320 --> 00:07:18,000\n你能发现\nAnd you see,\n\n165\n00:07:18,000 --> 00:07:20,048\n这里有三个单元\nthese are the three cells\n\n166\n00:07:20,256 --> 00:07:22,016\n它们的CAR指针\nthat have as their car pointer\n\n167\n00:07:22,275 --> 00:07:27,104\n分别指向对象(1 2)、3以及4\nthe object which is either 1, 2 or 3 or 4.\n\n168\n00:07:28,390 --> 00:07:29,750\n当然这个(1 2)\nAnd then of course the 1, 2,\n\n169\n00:07:29,750 --> 00:07:31,325\n即整个结构的CAR\nthe car of this entire structure,\n\n170\n00:07:31,320 --> 00:07:32,656\n本身就是一个子结构\nis itself a substructure\n\n171\n00:07:32,880 --> 00:07:34,752\n包含一个像这样的子表\nwhich contains a sublist like that.\n\n172\n00:07:35,940 --> 00:07:37,072\n我要做的是\nWhat I'm about to do\n\n173\n00:07:37,200 --> 00:07:39,920\n就是按照下标\nis put down places which are--\n\n174\n00:07:39,952 --> 00:07:41,460\n把它们放进去\nI'm going to assign indices.\n\n175\n00:07:41,840 --> 00:07:43,408\n像这里的1\nLike this 1, over here,\n\n176\n00:07:43,560 --> 00:07:47,056\n代表了这个格子的下标\nrepresents the index of this cell.\n\n177\n00:07:49,850 --> 00:07:51,475\n这里的指针\nBut that pointer that we see here\n\n178\n00:07:52,370 --> 00:07:54,864\n是对THE-CARS\nis a reference to the\n\n179\n00:07:55,072 --> 00:07:57,296\n和THE-CDRS里的小格子的引用\npair of pigeonholes in the cars and the cdrs\n\n180\n00:07:57,400 --> 00:07:58,675\n它在我的线性内存中\nthat are labeled by 1\n\n181\n00:07:58,768 --> 00:08:00,336\n被标记为1的地方\nin my linear memory down here.\n\n182\n00:08:02,000 --> 00:08:04,064\n如果我想把这个结构\nSo if I wish to impose this structure\n\n183\n00:08:04,160 --> 00:08:05,264\n塞进线性内存中\non my linear memory,\n\n184\n00:08:05,850 --> 00:08:07,525\n要做的是\nwhat I do is I say, oh yes,\n\n185\n00:08:07,520 --> 00:08:11,888\n把它放进格子1中\nwhy don't we drop this into cell 1?\n\n186\n00:08:11,952 --> 00:08:12,660\n我要选取1号格子\nWell I said, I pick 1.\n\n187\n00:08:12,660 --> 00:08:13,856\n这个就是1号格子\nThere's 1. OK?\n\n188\n00:08:14,270 --> 00:08:16,225\n这是它的CAR\nAnd that says that its car,\n\n189\n00:08:16,220 --> 00:08:17,744\n我要把它赋值给一个序对\nI'm going to assign it to be a pair.\n\n190\n00:08:17,950 --> 00:08:18,725\n这个序对\nIt's a pair,\n\n191\n00:08:20,025 --> 00:08:21,555\n序号是5\nwhich is in index 5.\n\n192\n00:08:22,590 --> 00:08:23,900\n它的CDR\nAnd the cdr,\n\n193\n00:08:23,900 --> 00:08:25,139\n就是这个\nwhich is this one over here,\n\n194\n00:08:25,390 --> 00:08:26,135\n它是个序对\nis a pair\n\n195\n00:08:26,135 --> 00:08:27,700\n我会把它放到2的位置\nwhich I'm going to stick into place 2.\n\n196\n00:08:28,340 --> 00:08:28,980\n即P2\np2.\n\n197\n00:08:30,890 --> 00:08:32,950\n我们看P2\nAnd take a look at p2.\n\n198\n00:08:32,950 --> 00:08:34,725\nP2的CAR\nOh yes, well p2 is a thing\n\n199\n00:08:34,900 --> 00:08:37,225\n是数字3\nwhose car is the number 3,\n\n200\n00:08:37,344 --> 00:08:38,640\n如你所见N3\nso as you see, an n3.\n\n201\n00:08:39,520 --> 00:08:41,524\n这里 它的CDR\nAnd whose cdr, over here,\n\n202\n00:08:41,727 --> 00:08:43,400\n是一个序对\nis a pair,\n\n203\n00:08:43,975 --> 00:08:45,812\n在位置4\nwhich lives in place 4.\n\n204\n00:08:46,640 --> 00:08:47,796\n这就是P4\nSo that's what this p4 is.\n\n205\n00:08:48,650 --> 00:08:51,167\nP4是一个数字\np4 is a number\n\n206\n00:08:51,850 --> 00:08:53,876\n它的CAR部分是数字4\nwhose value is 4 in its car\n\n207\n00:08:54,608 --> 00:08:55,650\n它的CDR\nand whose cdr\n\n208\n00:08:55,840 --> 00:08:58,480\n是个空表 就在这儿\nis an empty list right there.\n\n209\n00:08:59,170 --> 00:08:59,904\n这个表就结束了\nAnd that ends it.\n\n210\n00:09:00,690 --> 00:09:04,576\n这就是在线性内存中\nSo this is the traditional way of representing\n\n211\n00:09:04,900 --> 00:09:09,552\n表示二叉树的传统方式\nthis kind of binary tree in a linear memory.\n\n212\n00:09:11,620 --> 00:09:15,100\n那么 下一个问题是\nNow the next question, of course,\n\n213\n00:09:15,100 --> 00:09:16,368\n我们需要关心\nthat we might want to worry about\n\n214\n00:09:16,608 --> 00:09:18,192\n如何去实现\nis just a little bit of implementation.\n\n215\n00:09:18,440 --> 00:09:20,336\n这意味着当我写下一个过程\nThat means that when I write procedures\n\n216\n00:09:20,368 --> 00:09:23,620\n用来给A赋值时\nof the form assigned a,\n\n217\n00:09:24,544 --> 00:09:27,104\n使用寄存机器的代码来编写的\nlines of register machine code\n\n218\n00:09:27,216 --> 00:09:30,140\n(ASSIGN A (FETCH B))\nof the form assigned a, the car of fetch of b,\n\n219\n00:09:30,848 --> 00:09:31,856\n我实际上想做的是\nwhat I really mean\n\n220\n00:09:31,975 --> 00:09:37,100\n定位这些元素\nis addressing these elements.\n\n221\n00:09:38,740 --> 00:09:40,256\n那段机器代码只是\nAnd so we're going to think of that as\n\n222\n00:09:40,688 --> 00:09:42,944\n这个复杂过程的简写\na abbreviation for it.\n\n223\n00:09:44,470 --> 00:09:46,336\n当然 为了把它“写下来”\nNow of course in order to write that down\n\n224\n00:09:46,350 --> 00:09:48,592\n我要引入一种\nI'm going to introduce some sort of a structure\n\n225\n00:09:48,624 --> 00:09:49,424\n称为“向量”的结构\ncalled a vector.\n\n226\n00:09:52,120 --> 00:09:53,312\n我们得有一种东西\nAnd we're going to have something which will\n\n227\n00:09:53,480 --> 00:09:54,544\n用来引用向量\nreference a vector,\n\n228\n00:09:56,840 --> 00:09:58,512\n这样我们就能把它写下来\njust so we can write it down.\n\n229\n00:09:58,710 --> 00:10:00,224\n它的参数之一是向量的名字\nWhich takes the name of the vector,\n\n230\n00:10:01,025 --> 00:10:03,970\n我觉得这个名字起得不太靠谱\nor the-- I don't think that name is the right word.\n\n231\n00:10:03,970 --> 00:10:09,400\n它接受VECTOR和INDEX两个参数\nWhich takes the vector and the index,\n\n232\n00:10:11,200 --> 00:10:13,056\n我可以用VECTOR-SET!\nand I have to have a way of setting one of those\n\n233\n00:10:13,104 --> 00:10:14,272\n来为其中的分量赋值\nwith something called a vector set,\n\n234\n00:10:14,657 --> 00:10:15,608\n我不太在意\nI don't really care.\n\n235\n00:10:16,280 --> 00:10:17,550\n我们来看一看\nBut let's look, for example,\n\n236\n00:10:18,113 --> 00:10:20,425\n在这种实现中\nat then that kind of implementation\n\n237\n00:10:21,250 --> 00:10:23,182\nCAR和CDR是什么样子的\nof car and cdr.\n\n238\n00:10:26,470 --> 00:10:28,416\n比如说 如果我刚好有\nSo for example if I happen to have\n\n239\n00:10:28,880 --> 00:10:30,800\n一个寄存器B\na register b,\n\n240\n00:10:31,150 --> 00:10:34,640\n它存了一个序对的下标\nwhich contains the type index of a pair,\n\n241\n00:10:35,950 --> 00:10:38,800\n即它是指向一个序对的指针\nand therefore it is the pointer to a pair,\n\n242\n00:10:39,350 --> 00:10:40,850\n我可以取它的CAR\nthen I could take the car of that and\n\n243\n00:10:41,552 --> 00:10:44,110\n存到寄存器A里面\nOK if I-- write this down-- I might put that in register a.\n\n244\n00:10:44,490 --> 00:10:46,864\n事实上它是\nWhat that really is is a representation of\n\n245\n00:10:47,375 --> 00:10:50,191\n把A赋值为--\nthe assign to a,\n\n246\n00:10:50,190 --> 00:10:51,920\n引用向量的一个分量--\nthe value of vector reffing--\n\n247\n00:10:52,800 --> 00:10:55,248\n或者你可以把它叫做索引一个数组\nor array indexing, if you will-- or something,\n\n248\n00:10:55,420 --> 00:10:57,632\n目标向量为THE-CARS\nthe cars object--\n\n249\n00:10:58,400 --> 00:11:00,928\n而目标分量是B\nwhatever that is-- with the index, b.\n\n250\n00:11:02,650 --> 00:11:03,632\nCDR的操作也类似\nAnd similarly for cdr.\n\n251\n00:11:04,100 --> 00:11:05,725\n我们可以用同样的方式\nAnd we can do the same thing\n\n252\n00:11:05,904 --> 00:11:08,320\n来对数据结构赋值\nfor assignment to data structures,\n\n253\n00:11:08,925 --> 00:11:10,925\n如果我们需要这么做的话\nIf we need to do that sort of things at all.\n\n254\n00:11:11,840 --> 00:11:13,808\n构建这个并不太难\nIt's not too hard to build that.\n\n255\n00:11:14,580 --> 00:11:15,728\n下一个问题是\nWell now the next question is\n\n256\n00:11:15,728 --> 00:11:17,000\n我们如何分配它们\nhow are we going to do allocation.\n\n257\n00:11:18,010 --> 00:11:20,138\n我们经常需要一个新的序对\nAnd every so often I say I want a cons.\n\n258\n00:11:21,400 --> 00:11:23,424\n当然 CONS并没有长在树上\nNow conses don't grow on trees.\n\n259\n00:11:23,790 --> 00:11:24,816\n或许它们应该那样\nOr maybe they should.\n\n260\n00:11:25,340 --> 00:11:26,560\n我必须得有某种方法\nBut I have to have some way\n\n261\n00:11:26,704 --> 00:11:28,970\n来获得一个可用的序对\nI have to have some way of getting the next one.\n\n262\n00:11:29,980 --> 00:11:31,475\n我需要某种方案\nI have to have some idea of\n\n263\n00:11:31,470 --> 00:11:33,040\n当内存不再使用的时候\nif their memory is unused\n\n264\n00:11:33,690 --> 00:11:35,056\n我可以重新分配它们\nthat I might want to allocate from.\n\n265\n00:11:35,630 --> 00:11:37,380\n有很多方案可以实现这一点\nAnd there are many schemes for doing this.\n\n266\n00:11:37,380 --> 00:11:39,072\n现在我给你们展示的这个东西\nAnd the particular thing I'm showing you right now\n\n267\n00:11:39,232 --> 00:11:40,450\n并是不必要的\nis not essential.\n\n268\n00:11:42,100 --> 00:11:43,184\n然而它很方便\nHowever it's convenient\n\n269\n00:11:43,200 --> 00:11:44,448\n并且被实现很多次了\nand has been done many times.\n\n270\n00:11:44,608 --> 00:11:47,200\n其中一种基于“空闲表”的分配方案\nIt's one schemes called the free list allocation scheme.\n\n271\n00:11:47,660 --> 00:11:48,684\n它的意思就是\nWhat that means is\n\n272\n00:11:48,680 --> 00:11:51,120\n世界上所有的空闲内存\nthat all of the free memory that there is in the world\n\n273\n00:11:51,550 --> 00:11:53,088\n都连在一个链表中\nis linked together in a linked list,\n\n274\n00:11:54,550 --> 00:11:56,224\n就像其它东西一样\njust like all the other stuff.\n\n275\n00:11:56,960 --> 00:11:59,075\n每当你需要一个新的格子\nAnd whenever you need a free cell\n\n276\n00:11:59,070 --> 00:12:00,128\n来进行CONS的时候\nto make a new cons,\n\n277\n00:12:00,950 --> 00:12:02,264\n你选择第一个格子\nyou grab the first one\n\n278\n00:12:02,264 --> 00:12:03,825\n将它的CDR指向空闲表\nmake the free list be the cdr of it,\n\n279\n00:12:04,325 --> 00:12:05,553\n然后分配它\nand then allocate that.\n\n280\n00:12:06,030 --> 00:12:08,325\n就像这样\nAnd so what that looks like is something like this.\n\n281\n00:12:09,530 --> 00:12:13,328\n这里 我们的空闲表\nHere we have the free list\n\n282\n00:12:13,952 --> 00:12:16,810\n就是从6开始\nstarting in 6.\n\n283\n00:12:18,510 --> 00:12:23,472\n它是一个指向8的指针\nAnd what that is is a pointer-off to say 8.\n\n284\n00:12:24,860 --> 00:12:25,628\n它表示\nSo what it says is,\n\n285\n00:12:25,628 --> 00:12:26,553\n当前这个是空闲的\nthis one is free\n\n286\n00:12:26,553 --> 00:12:27,953\n下一个在位置8\nand the next one is an 8.\n\n287\n00:12:28,870 --> 00:12:29,881\n这个是空闲的\nThis one is free\n\n288\n00:12:30,048 --> 00:12:32,080\n下一个在位置3\nand the next one is in 3,\n\n289\n00:12:32,320 --> 00:12:33,450\n下一个是空闲的\nthe next one that's free.\n\n290\n00:12:33,930 --> 00:12:34,950\n这个是空闲的\nThat one's free\n\n291\n00:12:35,040 --> 00:12:37,680\n下一个在位置0\nand the next one is in 0.\n\n292\n00:12:37,872 --> 00:12:38,496\n这个是空闲的\nThat one's free\n\n293\n00:12:38,528 --> 00:12:39,824\n下一个在位置15\nand the next one's in 15.\n\n294\n00:12:40,940 --> 00:12:41,840\n以此类推\nSomething like that.\n\n295\n00:12:42,780 --> 00:12:44,640\n我们可以想象有这样的结构\nWe can imagine having such a structure.\n\n296\n00:12:46,400 --> 00:12:48,032\n一旦我们有了这样的机制\nGiven that we have something like that,\n\n297\n00:12:49,456 --> 00:12:50,920\n那么当你需要空间的时候\nthen it's possible to\n\n298\n00:12:50,920 --> 00:12:52,224\n就能获取一个\njust get one when you need it.\n\n299\n00:12:53,825 --> 00:12:56,466\n那些使用了CONS的程序\nAnd so a program for doing cons,\n\n300\n00:12:57,450 --> 00:12:59,136\n内存可能就是像这样的\nthis is what cons might turn into.\n\n301\n00:12:59,320 --> 00:13:02,573\n把B和C进行CONS之后的值\nTo assign to a register A the result of cons-ing,\n\n302\n00:13:02,950 --> 00:13:05,825\n赋值给A寄存器\na B onto C,\n\n303\n00:13:06,200 --> 00:13:09,040\n结果包括B和C\nthe value in this containing B and the value containing C,\n\n304\n00:13:09,270 --> 00:13:10,528\n我们要做的是\nwhat we have to do is\n\n305\n00:13:10,560 --> 00:13:12,240\n把当前的尾部格子 即空闲表的前个格子\nget the current tail ahead of the freelist,\n\n306\n00:13:12,475 --> 00:13:14,300\n让它的CDR指向空闲表\nmake the free list be its cdr.\n\n307\n00:13:15,640 --> 00:13:18,336\n我们要把THE-CARS中\nThen we have to change the cars\n\n308\n00:13:18,410 --> 00:13:22,496\n由A索引的格子\nto be the thing we're making up to be in A\n\n309\n00:13:23,136 --> 00:13:25,450\n修改为B中的内容\nto be the B, the thing in B.\n\n310\n00:13:25,900 --> 00:13:28,656\nTHE-CDRS中由A索引的格子\nAnd we have to make change the cdrs of\n\n311\n00:13:29,200 --> 00:13:31,720\n修改为C的值\nthe thing that's in A to be C.\n\n312\n00:13:33,200 --> 00:13:34,768\n现在A所指的格子里面\nAnd then what we have in A\n\n313\n00:13:34,784 --> 00:13:36,650\n就是新构建好的对象了\nis the right new frob, whatever it is.\n\n314\n00:13:36,816 --> 00:13:37,920\n这就是我们要的对象\nThe object that we want.\n\n315\n00:13:40,470 --> 00:13:42,500\n我之前告诉过你们\nNow there's a little bit of\n\n316\n00:13:42,500 --> 00:13:43,975\n这里撒了个谎\na cheat here that I haven't told you about,\n\n317\n00:13:43,970 --> 00:13:45,328\n也就是在这里的某处\nwhich is somewhere around here\n\n318\n00:13:45,536 --> 00:13:47,320\n我本来应该\nI haven't set the type of the thing that I've\n\n319\n00:13:48,450 --> 00:13:50,480\n把我CONS起来的对象\nthe type of the thing\n\n320\n00:13:50,510 --> 00:13:51,872\n设置为序对类型\nthat I'm cons-ing up to be a pair,\n\n321\n00:13:52,304 --> 00:13:53,050\n但我没有\nand I ought to.\n\n322\n00:13:53,510 --> 00:13:56,576\n因此这里应该需要设置一些比特位\nSo there should be some sort of bits here are being set,\n\n323\n00:13:56,608 --> 00:13:57,760\n我只是还没把它写下来\nand I just haven't written that down.\n\n324\n00:13:59,810 --> 00:14:00,864\n当然 这个很好实现\nWe could have arranged it, of course,\n\n325\n00:14:00,896 --> 00:14:02,450\n因为空闲表本来就是用序对实现的\nfor the free list to be made out of pairs.\n\n326\n00:14:03,100 --> 00:14:04,882\n因此这是没问题的\nAnd so then there's no problem with that.\n\n327\n00:14:06,430 --> 00:14:07,744\n但这也就是--\nBut that sort of--\n\n328\n00:14:07,824 --> 00:14:09,920\n这些都是无关紧要的细节\nagain, an inessential detail in a way\n\n329\n00:14:10,220 --> 00:14:12,880\n取决于那些想要自制\nsome particular programmer or architect\n\n330\n00:14:12,920 --> 00:14:14,272\n计算机或Lisp系统的\nor whatever might manufacture\n\n331\n00:14:14,336 --> 00:14:16,680\n程序员或架构师\nhis machine or Lisp system.\n\n332\n00:14:17,540 --> 00:14:18,711\n例如\nSo for example,\n\n333\n00:14:19,075 --> 00:14:20,247\n看这个\njust looking at this,\n\n334\n00:14:20,650 --> 00:14:23,456\n假设我们要为\nto allocate\n\n335\n00:14:23,550 --> 00:14:26,834\n这个之前见过的数据结构分配空间\ngiven that I had already the structure that you saw before,\n\n336\n00:14:27,216 --> 00:14:30,260\n假设我要分配一个新格子\nsupposing I wanted to allocate a new cell,\n\n337\n00:14:30,550 --> 00:14:36,617\n来表示表(1 1 2)\nwhich is going to be representation of list one, one, two,\n\n338\n00:14:37,240 --> 00:14:39,872\n其中(1 2)又是\nwhere already one two was the car\n\n339\n00:14:40,288 --> 00:14:42,160\n之前一个表的CAR元素\nof the list we were playing with before.\n\n340\n00:14:43,430 --> 00:14:44,450\n这不怎么难\nWell that's not so hard.\n\n341\n00:14:44,780 --> 00:14:46,200\n我用1号单元来存放数字“1”\nI stored that one in one,\n\n342\n00:14:46,200 --> 00:14:49,175\n那么P1表示的就是这个单元\nso p1 one is the representation of this.\n\n343\n00:14:49,530 --> 00:14:50,839\n这个是P5\nThis is p5.\n\n344\n00:14:51,675 --> 00:14:53,512\n它是应该是这个的CDR\nThat's going to be the cdr of this.\n\n345\n00:14:54,070 --> 00:14:55,525\n现在我们要从空闲表中取出一些东西\nNow we're going to pull something off the free list,\n\n346\n00:14:55,525 --> 00:14:57,303\n空闲表现在是从6开始的\nbut remember the free list started at six.\n\n347\n00:14:57,780 --> 00:15:00,183\n而在分配之后 空闲表将从8开始\nThe new free list after this allocation is eight,\n\n348\n00:15:00,600 --> 00:15:02,551\n一个从8开始的空闲表\na free list beginning at eight.\n\n349\n00:15:02,890 --> 00:15:03,520\n当然\nAnd of course\n\n350\n00:15:03,720 --> 00:15:06,048\n现在6里面是数字1\nin six now we have a number one,\n\n351\n00:15:06,150 --> 00:15:07,104\n就是我们想要的\nwhich is what we wanted,\n\n352\n00:15:07,392 --> 00:15:11,560\n它的CDR是在位置5的序对\nwith its cdr being the pair starting in location five.\n\n353\n00:15:13,330 --> 00:15:14,506\n没费多少力气\nAnd that's no big deal.\n\n354\n00:15:16,810 --> 00:15:20,450\n这里依然存在的一个问题是\nSo the only problem really remaining here is,\n\n355\n00:15:21,000 --> 00:15:23,402\n我们没有无限大的内存\nwell, I don't have an infinitely large memory.\n\n356\n00:15:25,080 --> 00:15:26,666\n如果我像这么操作了一会儿\nIf I do this for a little while,\n\n357\n00:15:27,250 --> 00:15:28,000\n比如说\nsay, for example,\n\n358\n00:15:28,016 --> 00:15:30,144\n假设进行一次CONS花费1微秒\nsupposing it takes me a microsecond to do a cons,\n\n359\n00:15:30,600 --> 00:15:32,975\n如果要进行一百万次CONS\nand I have a million cons memory\n\n360\n00:15:33,600 --> 00:15:35,279\n那么我就要消耗1秒钟的时间\nthen I'm only going to run out in a second,\n\n361\n00:15:35,950 --> 00:15:37,007\n这就很糟糕了\nand that's pretty bad.\n\n362\n00:15:38,000 --> 00:15:40,625\n如何预防这样的灾难\nSo what we do to prevent that disaster,\n\n363\n00:15:40,625 --> 00:15:42,191\n这种生态灾难\nthat ecological disaster,\n\n364\n00:15:42,600 --> 00:15:44,300\n在提问环节之后我们再继续讨论\ntalk about right after questions.\n\n365\n00:15:44,300 --> 00:15:45,263\n有人要提问吗?\nAre there any questions?\n\n366\n00:15:51,500 --> 00:15:51,696\n请讲\nYes.\n\n367\n00:15:52,030 --> 00:15:54,675\n学生：在环境图表中\nAUDIENCE: In the environment diagrams that we were drawing\n\n368\n00:15:54,675 --> 00:15:58,250\n我们画了过程体\nwe would use the body of procedures,\n\n369\n00:15:58,250 --> 00:16:00,672\n但是在过程应用结束后\nand you would eventually wind up with\n\n370\n00:16:00,800 --> 00:16:03,600\n这些环境中的东西就不再有用了\nthings that were no longer useful in that structure.\n\n371\n00:16:03,600 --> 00:16:04,160\n教授：说得很对\nPROFESSOR: Yes, madam.\n\n372\n00:16:04,930 --> 00:16:06,672\n学生：它是如何表示的？\nAUDIENCE: How is that represented?\n\n373\n00:16:06,768 --> 00:16:08,750\n教授：这其实是两个问题\nPROFESSOR: There's two problems here. OK?\n\n374\n00:16:09,180 --> 00:16:10,250\n第一个问题是\nOne you were asking\n\n375\n00:16:10,250 --> 00:16:13,438\n材料没用了\nis that material becomes useless.\n\n376\n00:16:13,870 --> 00:16:14,920\n我们稍后就会讲\nWe'll talk about that in a second.\n\n377\n00:16:14,920 --> 00:16:17,008\n如何预防生态灾难\nThat has to do with how to prevent ecological disasters.\n\n378\n00:16:17,632 --> 00:16:19,200\n如果我制造了一堆垃圾\nRight? If I make a lot of garbage\n\n379\n00:16:19,200 --> 00:16:21,399\n我需要自己清理掉\nI have to somehow be able to clean up after myself.\n\n380\n00:16:21,820 --> 00:16:22,976\n我们一会儿就要讲\nAnd we'll talk about that in a second.\n\n381\n00:16:23,430 --> 00:16:24,575\n第二个问题\nThe other question you're asking\n\n382\n00:16:24,575 --> 00:16:27,210\n你问的是如何表示环境\nis how you represent the environments, I think.\n\n383\n00:16:27,280 --> 00:16:27,600\n学生：对\nAUDIENCE: Yes.\n\n384\n00:16:27,600 --> 00:16:28,190\n教授：好\nPROFESSOR: OK.\n\n385\n00:16:28,190 --> 00:16:30,624\n环境结构能够以任意的方式表示\nAnd the environment structures can be represented in arbitrary ways.\n\n386\n00:16:30,928 --> 00:16:31,780\n有很多种表示方式\nThere are lots of them.\n\n387\n00:16:31,780 --> 00:16:33,344\n这里 我只讲了基于表结构的内存\nI mean, here I'm just telling you about list cells.\n\n388\n00:16:33,630 --> 00:16:34,925\n当然 每个真实的系统\nOf course every real system\n\n389\n00:16:34,925 --> 00:16:36,725\n都有任意长度的向量\nhas vectors of arbitrary length\n\n390\n00:16:36,720 --> 00:16:39,152\n也有固定长度的向量\nas well as the vectors of length, too,\n\n391\n00:16:39,312 --> 00:16:40,512\n它们都可以作为内存的表示方法\nwhich represent list cells.\n\n392\n00:16:41,080 --> 00:16:44,909\n在一个专业的Lisp系统中\nAnd the environment structures that one uses in a\n\n393\n00:16:44,900 --> 00:16:46,992\n环境结构是用\nprofessionally written Lisp system\n\n394\n00:16:47,300 --> 00:16:49,699\n向量表示的\ntend to be vectors\n\n395\n00:16:49,699 --> 00:16:51,925\n它所包含的元素的数量\nwhich contain a number of elements approximately\n\n396\n00:16:51,925 --> 00:16:54,601\n比参数的个数稍微多一点\nequal to the number of arguments-- a little bit more\n\n397\n00:16:55,350 --> 00:16:56,864\n因为你需要某种“粘合剂”\nbecause you need sort of glue.\n\n398\n00:16:57,408 --> 00:17:00,740\n记住环境是在框架里的\nOK? So remember, the environment is in a frame.\n\n399\n00:17:00,740 --> 00:17:03,980\n框架是应用过程时被构建出来的\nThe frames are constructed by applying a procedure.\n\n400\n00:17:03,980 --> 00:17:04,784\n这种情况下\nIn doing so,\n\n401\n00:17:04,800 --> 00:17:07,600\n所分配的空间大小为\nan allocation is made of a place\n\n402\n00:17:07,648 --> 00:17:11,270\n实际参数加上“粘合剂”占用的空间\nwhich is the number of arguments long plus some glue\n\n403\n00:17:11,270 --> 00:17:12,713\n然后将它连接到某条链上\nthat gets linked into a chain.\n\n404\n00:17:13,325 --> 00:17:15,660\n在这个层次上 和ALGOL差不多\nIt's just like algol at that level.\n\n405\n00:17:19,810 --> 00:17:20,725\n还有其它问题吗?\nThere any other questions?\n\n406\n00:17:23,700 --> 00:17:23,920\n好\nOK.\n\n407\n00:17:23,920 --> 00:17:25,552\n谢谢 我们休息一下\nThank you, and let's take a short break.\n\n408\n00:17:26,350 --> 00:17:45,488\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n409\n00:17:45,530 --> 00:17:50,016\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n410\n00:17:55,740 --> 00:17:59,040\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Sussman Jay Sussman\n\n411\n00:17:59,130 --> 00:18:04,224\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n412\n00:18:04,320 --> 00:18:09,870\n存储分配与垃圾收集\nStorage Allocation & Garbage Collection\n\n413\n00:18:12,270 --> 00:18:14,240\n教授：如同我刚才说过的那样\nPROFESSOR: Well, as I just said,\n\n414\n00:18:14,550 --> 00:18:15,504\n半导体厂商\ncomputer memories\n\n415\n00:18:15,824 --> 00:18:17,968\n所生产的计算机内存\nsupplied by the semiconductor manufacturers\n\n416\n00:18:18,160 --> 00:18:19,000\n容量是有限的\nare finite.\n\n417\n00:18:19,420 --> 00:18:20,408\n这的确很可惜\nAnd that's quite a pity.\n\n418\n00:18:21,620 --> 00:18:23,352\n但它也可能不总是这样\nIt might not always be that way.\n\n419\n00:18:24,030 --> 00:18:25,408\n简单算一下\nJust for a quick calculation,\n\n420\n00:18:25,440 --> 00:18:28,860\n你可以看到 如果内存的价格\nyou can see that it's possible that if memory's\n\n421\n00:18:28,860 --> 00:18:30,800\n继续保持当前的趋势的话\nprices keep going at the rate they're going\n\n422\n00:18:31,220 --> 00:18:33,680\n如果你执行CONS的时候也只需要1微秒\nthat if you still took a microsecond second to do a cons,\n\n423\n00:18:34,425 --> 00:18:35,900\n那么 首先大家知道\nthen-- first of all, everybody\n\n424\n00:18:35,900 --> 00:18:37,072\n一年大约有\nshould know that there's about pi\n\n425\n00:18:37,104 --> 00:18:38,860\nPI*10^7秒\ntimes ten to the seventh seconds in a year.\n\n426\n00:18:39,450 --> 00:18:41,120\n那么就有\nAnd so that would be\n\n427\n00:18:41,504 --> 00:18:42,730\n10^6乘以10^7\nten to the seventh plus ten to the sixth\n\n428\n00:18:42,733 --> 00:18:43,940\n也就是10^13\nis ten to the thirteenth.\n\n429\n00:18:43,940 --> 00:18:45,506\n那么在机器的一生中\nSo there's maybe ten to the fourteenth conses\n\n430\n00:18:45,506 --> 00:18:46,800\n就能有10^14个CONS\nin the life of a machine.\n\n431\n00:18:47,520 --> 00:18:49,408\n如果你的机器上\nIf there was ten to the fourteenth words of memory\n\n432\n00:18:49,680 --> 00:18:50,570\n有10^14个字的内存\non your machine,\n\n433\n00:18:51,200 --> 00:18:52,160\n你就永远不会用完\nyou'd never run out.\n\n434\n00:18:53,040 --> 00:18:53,856\n这样就会……\nOK so that will be,\n\n435\n00:18:53,952 --> 00:18:55,760\n这并不是完全没有道理\nAnd that's not completely unreasonable.\n\n436\n00:18:56,310 --> 00:18:58,460\n10^14次方不是个非常大的数字\nTen to the fourteenth is not a very large number.\n\n437\n00:19:01,450 --> 00:19:04,704\n我不觉得它是个很大的数字\nEven for... I don't think it is.\n\n438\n00:19:05,180 --> 00:19:07,392\n但我喜欢在天文学领域进行比较\nBut then again I like to play with astronomy.\n\n439\n00:19:07,930 --> 00:19:11,040\n距离我们最近的星星\nIt's at least ten to the eighteenth centimeters\n\n440\n00:19:11,104 --> 00:19:12,450\n至少有10^18次方厘米远\nbetween us and the nearest star.\n\n441\n00:19:12,930 --> 00:19:18,850\n我担心的是\nBut the thing I'm about to worry about is,\n\n442\n00:19:19,150 --> 00:19:21,275\n至少以现在的经济状况\nat least in the current economic state of affairs,\n\n443\n00:19:21,275 --> 00:19:23,575\n10^14大小的内存很贵\nten to the fourteenth pieces of memory is expensive.\n\n444\n00:19:24,200 --> 00:19:26,624\n因此我认为我们需要\nAnd so I suppose what we have to do\n\n445\n00:19:26,816 --> 00:19:28,512\n适应更小的内存\nis make do with much smaller memories.\n\n446\n00:19:30,020 --> 00:19:30,592\n现在\nNow\n\n447\n00:19:32,848 --> 00:19:35,072\n广义地说 我们营造一种无限内存的假象\nin general we want to have an illusion of infinity.\n\n448\n00:19:35,800 --> 00:19:37,225\n我们需要整理它\nAll we need to do is arrange it\n\n449\n00:19:37,825 --> 00:19:39,689\n以便在我们需要内存的时候就能获得它\nso that whenever you look, the thing is there.\n\n450\n00:19:41,920 --> 00:19:45,550\n这个想法非常重要\nThat's, that's really an important idea.\n\n451\n00:19:49,540 --> 00:19:51,975\n人或者计算机只能存在有限的时间\nA person or a computer lives only a finite amount of time\n\n452\n00:19:52,325 --> 00:19:54,599\n只能看有限的东西\nand can only take a finite number of looks at something.\n\n453\n00:19:55,280 --> 00:19:57,375\n因此你只需要有限的东西\nAnd so you really only need a finite amount of stuff.\n\n454\n00:19:58,190 --> 00:19:59,000\n只要你合理地安排它们\nBut you have to arrange it\n\n455\n00:19:59,000 --> 00:20:00,383\n使得不管实际有多少内存\nso no matter how much there is,\n\n456\n00:20:00,773 --> 00:20:03,461\n你要求这里有多少\nhow much you really claim there is,\n\n457\n00:20:03,461 --> 00:20:04,749\n当你去看的时候\nthere's always enough stuff\n\n458\n00:20:04,749 --> 00:20:06,900\n总有足够的东西\nso that when you take a look, it's there.\n\n459\n00:20:06,900 --> 00:20:08,157\n因此你只需要有限的数量\nAnd so you only need a finite amount.\n\n460\n00:20:08,750 --> 00:20:09,949\n我们来看看\nBut let's see.\n\n461\n00:20:11,630 --> 00:20:13,328\n我们之前提过一个问题\nOne problem is, as was brought up,\n\n462\n00:20:13,925 --> 00:20:15,450\n在很多情况下\nthat there are possible ways\n\n463\n00:20:15,720 --> 00:20:17,840\n我们制造了大量\nthat there is lots of stuff\n\n464\n00:20:17,888 --> 00:20:19,168\n不需要的东西\nthat we make that we don't need.\n\n465\n00:20:19,410 --> 00:20:21,813\n我们可以进行回收再利用\nAnd we could recycle the material out of which its made.\n\n466\n00:20:22,625 --> 00:20:23,533\n举个例子\nAn example\n\n467\n00:20:24,150 --> 00:20:25,792\n事实上\nfor is, is the fact\n\n468\n00:20:25,792 --> 00:20:28,400\n当我们调用一个过程的时候\nwhen we're building environment structures,\n\n469\n00:20:28,400 --> 00:20:30,470\n都会构建环境结构\nand we do so every time we call a procedure.\n\n470\n00:20:30,470 --> 00:20:32,565\n我们把它构建在一个环境框架中\nWe have built in it a environment frame.\n\n471\n00:20:33,140 --> 00:20:34,032\n这个环境框架\nThat environment frame\n\n472\n00:20:34,224 --> 00:20:36,070\n不用存在很长时间\ndoesn't necessarily have a very long lifetime.\n\n473\n00:20:36,730 --> 00:20:38,699\n只有在进行过程调用的时候\nIts lifetime, meaning its usefulness,\n\n474\n00:20:39,425 --> 00:20:42,603\n它的存在才是有用的\nmay exist only over the invocation of the procedure.\n\n475\n00:20:42,850 --> 00:20:45,275\n如果过程把另一个过程\nOr if the procedure exports another procedure\n\n476\n00:20:45,270 --> 00:20:46,672\n作为返回值返回\nby returning it as a value\n\n477\n00:20:46,875 --> 00:20:48,525\n并且这个过程是在它的内部定义的\nand that procedure is defined inside of it,\n\n478\n00:20:48,520 --> 00:20:50,800\n那么外层过程的\nwell then the lifetime of the\n\n479\n00:20:51,072 --> 00:20:53,392\n存活时间仍然是\nframe of the outer procedure still is\n\n480\n00:20:53,500 --> 00:20:56,128\n被返回的过程的\nonly the lifetime of the procedure\n\n481\n00:20:57,024 --> 00:20:57,900\n存活时间\nwhich was exported.\n\n482\n00:20:58,530 --> 00:20:59,575\n最终\nAnd so ultimately,\n\n483\n00:20:59,575 --> 00:21:00,972\n就会制造很多垃圾\na lot of that is garbage.\n\n484\n00:21:01,960 --> 00:21:04,108\n还有其它的途径可以制造垃圾\nThere are other ways of producing garbage as well.\n\n485\n00:21:05,370 --> 00:21:06,675\n用户也会制造垃圾\nUsers produce garbage.\n\n486\n00:21:07,240 --> 00:21:08,075\n举例来说\nAn example of\n\n487\n00:21:08,075 --> 00:21:10,225\n用户制造的垃圾像是这样\nuser garbage is something like this.\n\n488\n00:21:10,930 --> 00:21:14,000\n如果我们写个程序\nIf we write a program to, for example,\n\n489\n00:21:14,000 --> 00:21:15,800\n把两个表连接到一起\nappend two lists together,\n\n490\n00:21:16,050 --> 00:21:18,144\n唯一的办法是\nwell one way to do it is to\n\n491\n00:21:18,325 --> 00:21:21,375\n把第一个表逆序塞到空表中\nreverse the first list onto the empty list\n\n492\n00:21:21,375 --> 00:21:23,725\n再把新表逆序塞到第二个表中\nand reverse that onto the second list.\n\n493\n00:21:24,703 --> 00:21:26,925\n这种解法并不是很糟糕\nNow that's not terribly bad way of doing it.\n\n494\n00:21:28,160 --> 00:21:28,850\n然而\nAnd however,\n\n495\n00:21:28,850 --> 00:21:30,096\n程序所生成的\nthe intermediate result,\n\n496\n00:21:30,112 --> 00:21:32,020\n中间结果\nwhich is the reversal of the first list\n\n497\n00:21:33,875 --> 00:21:35,576\n即第一个表的逆序表\nas done by this program,\n\n498\n00:21:36,700 --> 00:21:38,525\n在它被复制到第二个表之后\nis never going to be accessed ever again\n\n499\n00:21:38,525 --> 00:21:40,568\n就再也不会被用到了\nafter it's copied back on to the second.\n\n500\n00:21:41,010 --> 00:21:42,232\n它是个中间结果\nIt's an intermediate result.\n\n501\n00:21:43,580 --> 00:21:45,432\n它很难被找到\nIt's going to be hard to ever see\n\n502\n00:21:46,075 --> 00:21:48,056\n没有人能访问到它\nhow anybody would ever be able to access it.\n\n503\n00:21:48,600 --> 00:21:49,848\n事实上 它会消失掉\nIn fact, it will go away.\n\n504\n00:21:51,050 --> 00:21:52,900\n如果我们像这样制造了大量的垃圾\nNow if we make a lot of garbage like that,\n\n505\n00:21:52,900 --> 00:21:54,200\n系统也应该允许我们这么干\nand we should be allowed to,\n\n506\n00:21:54,800 --> 00:21:57,296\n但应该有某些方法去回收这些垃圾\nthen there's got to be some way to reclaim that garbage.\n\n507\n00:21:58,800 --> 00:22:00,900\n现在 我要告诉你\nWell, what I'd like to tell you about now\n\n508\n00:22:01,700 --> 00:22:03,775\n一个非常聪明的技巧\nis a very clever technique\n\n509\n00:22:04,320 --> 00:22:07,584\n一个Lisp系统\nwhereby a Lisp system\n\n510\n00:22:07,952 --> 00:22:11,216\n通常可以证明一条小定理\ncan prove a small theorem every so often\n\n511\n00:22:11,296 --> 00:22:13,504\n也就是 某段内存中的值\non the form the following piece of junk\n\n512\n00:22:14,720 --> 00:22:16,096\n之后不再会被用到\nwill never be accessed again.\n\n513\n00:22:17,410 --> 00:22:19,809\n它对以后的计算没有任何影响\nIt can have no affect on the future of the computation.\n\n514\n00:22:21,400 --> 00:22:23,616\n事实上 这基于一个很简单的想法\nIt's actually based on a very simple idea.\n\n515\n00:22:24,725 --> 00:22:28,065\n我们已经把计算机设计成这个样子\nWe've designed our computers to look sort of like this.\n\n516\n00:22:28,950 --> 00:22:30,672\n有一些数据通路\nThere's some data path,\n\n517\n00:22:31,872 --> 00:22:33,408\n其中有寄存器\nwhich contains the registers.\n\n518\n00:22:34,920 --> 00:22:38,048\n有EXP、ENV\nYou know, there are things like exp, and env,\n\n519\n00:22:39,040 --> 00:22:42,192\n和VAL之类的寄存器\nand val, and so on.\n\n520\n00:22:42,610 --> 00:22:44,025\n这里有个叫STACK的东西\nAnd there's one here called stack,\n\n521\n00:22:46,020 --> 00:22:49,456\n某种指向一个结构的东西\nsome sort which points off to a structure somewhere,\n\n522\n00:22:49,504 --> 00:22:50,224\n它是个栈\nwhich is the stack.\n\n523\n00:22:50,240 --> 00:22:51,488\n我们过一会再研究它\nAnd we'll worry about that in a second.\n\n524\n00:22:51,648 --> 00:22:53,620\n这里有一些\nThere's some finite controller,\n\n525\n00:22:54,380 --> 00:22:56,576\n有穷状态控制器\nfinite state machine controller.\n\n526\n00:22:56,730 --> 00:22:59,513\n控制信号在这之间流通\nAnd there's some control signals that go this way and\n\n527\n00:22:59,800 --> 00:23:01,440\n比如谓词的返回结果\npredicate results that come this way,\n\n528\n00:23:01,872 --> 00:23:03,136\n这部分并不太有趣\nnot the interesting part.\n\n529\n00:23:03,350 --> 00:23:06,512\n这里有某种结构化的内存\nThere's some sort of structured memory,\n\n530\n00:23:06,806 --> 00:23:08,271\n我刚才给你讲过如何构建它\nwhich I just told you how to make,\n\n531\n00:23:08,270 --> 00:23:10,176\n它可能包括一个栈\nwhich may contain a stack.\n\n532\n00:23:10,460 --> 00:23:11,488\n我没有告诉你如何把东西\nI didn't tell you how to make things\n\n533\n00:23:11,488 --> 00:23:12,430\n构建成任意形状\nof arbitrary shape,\n\n534\n00:23:12,560 --> 00:23:13,392\n只有序对\nonly pairs.\n\n535\n00:23:13,600 --> 00:23:14,208\n但事实上\nBut in fact\n\n536\n00:23:14,350 --> 00:23:15,440\n我告诉过你\nwith what I've told you can\n\n537\n00:23:15,472 --> 00:23:16,960\n可以用一张大表来模拟栈\nwith what I've told you can simulate a stack by a big list.\n\n538\n00:23:17,775 --> 00:23:18,850\n我没准备干这个\nI don't plan to do that,\n\n539\n00:23:18,850 --> 00:23:20,016\n这不是个好办法\nit's not a nice way to do it.\n\n540\n00:23:20,360 --> 00:23:22,608\n但是我们可以有这样一个东西\nBut we could have something like that.\n\n541\n00:23:22,990 --> 00:23:25,280\n这里有各种数据结构\nWe have all sorts of little data structures in here\n\n542\n00:23:25,647 --> 00:23:27,750\n它们通过有趣的方式互相连接\nthat are hooked together in funny ways.\n\n543\n00:23:30,115 --> 00:23:32,025\n它们和其它东西连接到一起\nThey connect to other things.\n\n544\n00:23:32,560 --> 00:23:33,250\n以此类推\nAnd so on.\n\n545\n00:23:33,250 --> 00:23:34,225\n归根结底\nAnd ultimately\n\n546\n00:23:34,455 --> 00:23:37,190\n这里的东西是指向这里的指针\nthings up there are pointers to these.\n\n547\n00:23:37,190 --> 00:23:38,873\n寄存器里的指针\nThe things that are in the registers\n\n548\n00:23:39,400 --> 00:23:41,408\n指向的是表结构内存中\nare pointers off to the data structures\n\n549\n00:23:41,440 --> 00:23:43,088\n数据结构\nthat live in this list structure memory.\n\n550\n00:23:44,910 --> 00:23:49,808\n现在 我们的问题是\nNow the truth of the matter is\n\n551\n00:23:51,050 --> 00:23:52,560\n机器的整个意识\nthat the entire consciousness\n\n552\n00:23:52,576 --> 00:23:53,920\n是在寄存器里的\nof this machine is in these registers.\n\n553\n00:23:55,760 --> 00:23:58,512\n如果这个机器\nThere is no possible way that the machine,\n\n554\n00:23:58,750 --> 00:24:01,072\n构建得正确的话\nif done correctly, if built correctly,\n\n555\n00:24:01,374 --> 00:24:03,418\n它无法访问表结构内存中任何的东西\ncan access anything in this list structure memory\n\n556\n00:24:04,570 --> 00:24:07,056\n除非这个表结构内存中的数据\nunless the thing in that list structure memory is\n\n557\n00:24:08,090 --> 00:24:10,880\n通过一系列的数据结构\nis connected by a sequence of data structures\n\n558\n00:24:11,648 --> 00:24:13,060\n与寄存器相连接\nto the registers.\n\n559\n00:24:15,070 --> 00:24:15,984\n如果它能够\nIf it's accessible\n\n560\n00:24:16,224 --> 00:24:18,310\n被合法的数据结构选择函数访问到\nby legitimate data structure selectors\n\n561\n00:24:19,080 --> 00:24:21,120\n通过寄存器里保存的指针能够访问它\nfrom the pointers that are stored in these registers.\n\n562\n00:24:22,280 --> 00:24:24,464\n比如说 数组引用\nThings like array references, perhaps.\n\n563\n00:24:24,940 --> 00:24:27,920\n或者针对序对的引用--CAR或者CDR\nOr cons cell references, cars and cdrs.\n\n564\n00:24:29,088 --> 00:24:30,950\n但我不能随意访问内存中的位置\nBut I can't just talk about a random place in this memory,\n\n565\n00:24:30,950 --> 00:24:31,950\n因为我找不到它\nbecause I can't get to it.\n\n566\n00:24:32,740 --> 00:24:34,904\n至少在我求值某条表达式的时候\nThese are being arbitrary names I'm not allowed to count,\n\n567\n00:24:37,000 --> 00:24:39,168\n我是不允许去访问那个任意名字的\nat least as I'm evaluating expressions.\n\n568\n00:24:41,620 --> 00:24:42,576\n如果是这样的话\nIf that's the case\n\n569\n00:24:43,270 --> 00:24:45,072\n就可以证明一个简单的理论\nthen there's a very simple theorem to be proved.\n\n570\n00:24:47,160 --> 00:24:47,696\n就是说\nWhich is,\n\n571\n00:24:47,900 --> 00:24:50,520\n如果我从这些寄存器指向的地方开始\nif I start with all lead pointers that are in all these registers\n\n572\n00:24:51,164 --> 00:24:52,550\n递归地遍历\nand recursively chase out,\n\n573\n00:24:52,825 --> 00:24:56,150\n标记选择函数所有能访问到内存\nmarking all the places I can get to by selectors,\n\n574\n00:24:56,900 --> 00:24:59,400\n最终就能标记所有能访问的东西\nthen eventually I mark everything they can be gotten to.\n\n575\n00:25:00,650 --> 00:25:02,699\n任何未标记的都是垃圾\nAnything which is not so marked is garbage\n\n576\n00:25:02,699 --> 00:25:03,750\n它们可以被回收\nand can be recycled.\n\n577\n00:25:05,560 --> 00:25:06,208\n非常简单\nVery simple.\n\n578\n00:25:07,200 --> 00:25:09,100\n不会影响之后的计算\nCannot affect the future of the computation.\n\n579\n00:25:11,180 --> 00:25:12,848\n我来举一个\nSo let me show you that in a particular\n\n580\n00:25:13,936 --> 00:25:15,750\n具体的例子\nin a particular example.\n\n581\n00:25:17,120 --> 00:25:19,376\n在此之前 需要给我的表结构内存\nNow that means I'm going to have to append to my\n\n582\n00:25:19,696 --> 00:25:22,080\n添加一个叫MARK的标志位\ndescription of the list structure a mark.\n\n583\n00:25:23,640 --> 00:25:24,896\n因此 在这里\nAnd so here, for example,\n\n584\n00:25:25,376 --> 00:25:27,280\n就有一个表结构内存\nis a list structured memory.\n\n585\n00:25:29,080 --> 00:25:30,320\n这块表内存中\nAnd in this list structured memory\n\n586\n00:25:30,336 --> 00:25:31,330\n存放了一个表数据结构\nis a list structure\n\n587\n00:25:31,330 --> 00:25:33,952\n我们把这个起始位置\nbeginning in a place I'm going to call--\n\n588\n00:25:35,870 --> 00:25:36,624\n称为“根”\nthis is the root.\n\n589\n00:25:38,590 --> 00:25:40,120\n不一定只有一个根\nNow it doesn't really have to have a root.\n\n590\n00:25:40,120 --> 00:25:41,950\n与寄存器类似 可以有很多这种东西\nIt could be a bunch of them, like all the registers.\n\n591\n00:25:42,670 --> 00:25:43,984\n但我可以巧妙地安排它们\nBut I could cleverly arrange it\n\n592\n00:25:44,138 --> 00:25:46,300\n把所有在旧寄存器里的东西\nso all the registers, all the things that are in old registers\n\n593\n00:25:46,300 --> 00:25:47,776\n在何时的时间点\nare also at the right moment\n\n594\n00:25:48,288 --> 00:25:50,460\n放入到这个根结构中\nput into this root structure,\n\n595\n00:25:50,460 --> 00:25:51,850\n然后用一个指针指向它\nand then we've got one pointer to it.\n\n596\n00:25:51,850 --> 00:25:52,675\n这不是重点\nI don't really care.\n\n597\n00:25:54,570 --> 00:25:55,632\n思路就是\nSo the idea is\n\n598\n00:25:55,648 --> 00:25:56,656\n我们要不断地进行CONS\nwe're going to cons up stuff\n\n599\n00:25:56,672 --> 00:25:58,016\n直到空闲表为空\nuntil our free list is empty.\n\n600\n00:25:58,720 --> 00:25:59,675\n这样就用尽了所有空间\nWe've run out of things.\n\n601\n00:26:00,950 --> 00:26:04,475\n现在我们要证明这个理论\nNow we're going to do this process of proving the theorem\n\n602\n00:26:04,470 --> 00:26:05,904\n也就是一部分的内存\nthat a certain percentage of the memory\n\n603\n00:26:05,952 --> 00:26:06,900\n已经没有用了\nis got crap in it.\n\n604\n00:26:07,850 --> 00:26:09,152\n然后我们要回收它\nAnd then we're going to recycle that\n\n605\n00:26:09,787 --> 00:26:10,875\n构建一个新的树\nto grow new trees,\n\n606\n00:26:12,192 --> 00:26:14,570\n这是这些垃圾的标准使用方式\na standard use of such garbage.\n\n607\n00:26:17,090 --> 00:26:18,640\n那么我们要做什么呢?\nSo in any case, what do we have here?\n\n608\n00:26:18,840 --> 00:26:20,784\n从P5这个位置开始\nWell we have some data structure\n\n609\n00:26:20,896 --> 00:26:24,270\n存了一些数据结构\nwhich starts out over here in p5.\n\n610\n00:26:25,150 --> 00:26:26,750\n说错了--是从1开始\nSorry, and it will start at one\n\n611\n00:26:27,270 --> 00:26:28,512\n事实上\nAnd in fact\n\n612\n00:26:28,896 --> 00:26:32,200\n它的CAR部分存放在P5这个位置\nit has a car in p5,\n\n613\n00:26:32,272 --> 00:26:33,584\n而CDR部分存在在P2这个位置\nand its cdr is in two.\n\n614\n00:26:33,980 --> 00:26:35,648\n最开始 所有的标记都是0\nAnd all the marks start out at zero.\n\n615\n00:26:36,700 --> 00:26:39,000\n我们要开始标记了\nWell let's start marking, just to play this game.\n\n616\n00:26:39,920 --> 00:26:40,525\n好\nOK.\n\n617\n00:26:42,540 --> 00:26:44,272\n例如\nSo for example,\n\n618\n00:26:44,475 --> 00:26:46,950\n因为我可以从根访问到位置P1\nsince I can access one from the root\n\n619\n00:26:46,950 --> 00:26:47,824\n我就标记一下\nI will mark that.\n\n620\n00:26:48,390 --> 00:26:49,175\n我来标一下\nLet me mark it.\n\n621\n00:26:50,960 --> 00:26:51,450\n好了\nBang.\n\n622\n00:26:52,224 --> 00:26:52,944\n这个被标记了\nThat's marked.\n\n623\n00:26:54,416 --> 00:26:57,510\n因为它指向位置P5\nOK. Now since I have a five here\n\n624\n00:26:57,648 --> 00:26:58,640\n所以我来到了5号格子\nI can go to five\n\n625\n00:26:59,025 --> 00:27:00,725\n然后 我要标记这个\nand see, well I'll mark that.\n\n626\n00:27:01,450 --> 00:27:01,760\n标好了\nBang.\n\n627\n00:27:01,760 --> 00:27:02,600\n这个笔真好用\nThat's useful stuff.\n\n628\n00:27:02,900 --> 00:27:05,104\n但是5号位置的CAR部分是一个数字\nBut five references as a number in its car,\n\n629\n00:27:05,270 --> 00:27:06,656\n我对标记数字不感兴趣\nI'm not interested in marking numbers\n\n630\n00:27:06,912 --> 00:27:08,170\n但它的CDR部分是P7\nbut its cdr is seven.\n\n631\n00:27:08,700 --> 00:27:09,750\n所以我可以标记它\nSo I can mark that.\n\n632\n00:27:10,450 --> 00:27:10,816\n又标好了\nBang.\n\n633\n00:27:11,808 --> 00:27:13,400\nP7的CDR部分是空表\nOK? Seven is the empty list,\n\n634\n00:27:13,675 --> 00:27:15,100\n而它唯一所引用的元素则是\nthe only thing that references,\n\n635\n00:27:15,595 --> 00:27:17,120\n它的CAR部分是个数字\nand it's got a number in its car.\n\n636\n00:27:17,120 --> 00:27:17,850\n我对它不感兴趣\nNot interesting.\n\n637\n00:27:19,490 --> 00:27:20,500\n让我们回到这里\nWell now let's go back here.\n\n638\n00:27:20,500 --> 00:27:21,650\n我忘记了一些事情\nI forgot about something.\n\n639\n00:27:21,650 --> 00:27:22,175\nP2\nTwo.\n\n640\n00:27:22,840 --> 00:27:24,850\n换句话说 如果我看1号格子\nSee in other words, if I'm looking at cell one,\n\n641\n00:27:25,425 --> 00:27:29,450\n1号格子的CDR部分指向P2\ncell one contains a two right over here.\n\n642\n00:27:30,370 --> 00:27:31,300\n一个指向P2的引用\nA reference to two.\n\n643\n00:27:32,016 --> 00:27:34,970\n这意味着我应该标记P2\nThat means I should go mark two.\n\n644\n00:27:35,700 --> 00:27:36,275\n好了\nBang.\n\n645\n00:27:37,140 --> 00:27:38,896\nP2包含了了一个到P4的引用\nTwo contains a reference to four.\n\n646\n00:27:39,136 --> 00:27:40,270\n而P2的CAR部分是个数字\nIt's got a number in its car,\n\n647\n00:27:40,279 --> 00:27:41,200\n我对它不感兴趣\nI'm not interested in that\n\n648\n00:27:41,475 --> 00:27:42,600\n所以我要标记P4\nso I'm going to go mark that.\n\n649\n00:27:43,780 --> 00:27:46,100\nP4的CAR部分引用了P7\nFour refers to seven through its car,\n\n650\n00:27:46,750 --> 00:27:48,176\n它的CDR是空的\nand is empty in its cdr,\n\n651\n00:27:48,475 --> 00:27:49,576\n但由于我已经标记过P7了\nbut I've already marked that one\n\n652\n00:27:49,576 --> 00:27:50,750\n就不再次标记它了\nso I don't have to mark it again.\n\n653\n00:27:51,400 --> 00:27:53,056\n这就是这个地方\nThis is all the accessible structure\n\n654\n00:27:53,072 --> 00:27:53,870\n所能访问的所有单元\nfrom that place.\n\n655\n00:27:55,000 --> 00:27:56,575\n很简单的递归标记算法\nSimple recursive mark algorithm.\n\n656\n00:27:58,710 --> 00:28:01,792\n这个算法有一些不足的地方\nNow there are some unhappinesses about that algorithm,\n\n657\n00:28:01,900 --> 00:28:04,025\n我们稍后会说\nand we can worry about that a second.\n\n658\n00:28:04,920 --> 00:28:06,160\n但基本上你能看到\nBut basically you'll see\n\n659\n00:28:06,192 --> 00:28:07,850\n所有没被标记的地方\nthat all the things that have not been marked\n\n660\n00:28:09,625 --> 00:28:11,504\n都是无用的\nare places that are free,\n\n661\n00:28:11,500 --> 00:28:12,416\n可以回收\nand I could recycle.\n\n662\n00:28:14,250 --> 00:28:15,750\n所以下一步就是\nSo the next stage after that is going to be\n\n663\n00:28:15,750 --> 00:28:17,050\n扫描整个内存\nto scan through all of my memory,\n\n664\n00:28:17,945 --> 00:28:20,350\n寻找未被标记的格子\nlooking for things that are not marked.\n\n665\n00:28:21,180 --> 00:28:22,450\n每当遇到一个已标记的格子\nEvery time I come across a marked thing\n\n666\n00:28:22,450 --> 00:28:23,225\n就把标记去掉\nI unmark it,\n\n667\n00:28:23,220 --> 00:28:24,864\n每当遇到未标记的格子时\nand every time I come across an unmarked thing\n\n668\n00:28:25,072 --> 00:28:27,820\n我就把它连接到我的空闲表中\nI'm going to link it together in my free list.\n\n669\n00:28:28,770 --> 00:28:30,300\n传统而且非常简单的算法\nClassic, very simple algorithm.\n\n670\n00:28:32,120 --> 00:28:33,100\n我们来看看\nSo let's see.\n\n671\n00:28:33,840 --> 00:28:34,770\n它很简单吗?\nIs that very simple?\n\n672\n00:28:34,770 --> 00:28:35,424\n是的\nYes it is.\n\n673\n00:28:35,570 --> 00:28:37,792\n我不会深入代码细节\nI'm not going to go through the code in any detail,\n\n674\n00:28:38,009 --> 00:28:39,650\n只是想给你看看它有多长\nbut I just want to show you about how long it is.\n\n675\n00:28:40,090 --> 00:28:41,100\n看这个标记阶段\nLet's look at the mark phase.\n\n676\n00:28:41,728 --> 00:28:43,984\n这是标记阶段的第一部分\nHere's the first part of the mark phase.\n\n677\n00:28:45,060 --> 00:28:46,000\n我们找到根\nWe pick up the root.\n\n678\n00:28:46,320 --> 00:28:47,520\n我们要\nWe're going to do some\n\n679\n00:28:47,675 --> 00:28:51,050\n对它进行递归过程调用\nWe're going to use that as a recursive procedure call.\n\n680\n00:28:52,380 --> 00:28:54,475\n当我们完成标记之后\nWe're going to sweep from there,\n\n681\n00:28:54,775 --> 00:28:56,950\n就从这里开始清除\nafter when we're done with marking.\n\n682\n00:28:57,380 --> 00:28:59,792\n然后我们将执行一些指令\nAnd then we're going to do a little couple of instructions\n\n683\n00:28:59,808 --> 00:29:01,360\n来检查这些标记\nthat do this checking out on the marks\n\n684\n00:29:01,392 --> 00:29:03,070\n或者更改这些标记\nand changing the marks and things like that,\n\n685\n00:29:03,075 --> 00:29:04,900\n按照我刚才讲的那个算法进行\naccording to the algorithm I've just shown you.\n\n686\n00:29:05,232 --> 00:29:06,470\n代码在这里\nOK? It comes out here.\n\n687\n00:29:06,470 --> 00:29:07,650\n你需要标记它们的CAR\nYou have to mark the cars of things\n\n688\n00:29:07,875 --> 00:29:10,212\n也需要标记它们的CDR\nand you also have to be able to mark the cdrs of things.\n\n689\n00:29:10,660 --> 00:29:12,100\n这就是整个标记阶段\nThat's the entire mark phase.\n\n690\n00:29:14,370 --> 00:29:16,164\n我给你讲个关于它的小故事\nI'll just tell you a little story about this.\n\n691\n00:29:16,590 --> 00:29:19,375\n古董货DEC PDP-6计算机\nThe old DEC PDP-6 computer,\n\n692\n00:29:20,930 --> 00:29:22,096\n它上面的\nthis was the way that\n\n693\n00:29:22,352 --> 00:29:24,850\n标记-清除垃圾回收系统就是这么写的\nthe mark-sweep garbage collection, as it was, was written.\n\n694\n00:29:26,912 --> 00:29:28,400\n程序很短\nThe program was so small\n\n695\n00:29:29,257 --> 00:29:31,600\n以至于它需要的数据\nthat with the data that it needed,\n\n696\n00:29:32,201 --> 00:29:34,875\n以及用来操作内存的所需的寄存器\nwith the registers that it needed to manipulate the memory,\n\n697\n00:29:36,160 --> 00:29:38,144\n都能够放入到计算机的\nit fit into the fast registers of the machine,\n\n698\n00:29:38,160 --> 00:29:38,970\n16个快速寄存器中\nwhich were 16.\n\n699\n00:29:39,280 --> 00:29:39,800\n整个程序\nThe whole program.\n\n700\n00:29:40,016 --> 00:29:42,016\n你可以在快速寄存器里执行指令\nAnd you could execute instructions in the fast registers.\n\n701\n00:29:43,170 --> 00:29:44,832\n所以这是个非常小的程序\nSo it's an extremely small program,\n\n702\n00:29:45,850 --> 00:29:46,880\n它跑得飞快\nand it could run very fast.\n\n703\n00:29:48,870 --> 00:29:51,300\n然而很不幸\nNow unfortunately, of course,\n\n704\n00:29:51,610 --> 00:29:54,025\n因为这个程序是递归的\nthis program, because the fact that it's recursive\n\n705\n00:29:54,800 --> 00:29:57,552\n因为你需要先做某件事儿\nin the way that you do something first\n\n706\n00:29:57,552 --> 00:29:58,992\n然后再去做另外一件事儿\nand then you do something after that,\n\n707\n00:29:59,210 --> 00:30:00,880\n你得先处理CAR 再处理CDR\nyou have to work on the cars and then the cdrs,\n\n708\n00:30:01,150 --> 00:30:02,750\n这就需要辅助内存\nit requires auxiliary memory.\n\n709\n00:30:03,410 --> 00:30:05,232\n所以Lisp系统\nSo Lisp systems--\n\n710\n00:30:05,440 --> 00:30:07,420\n需要一个栈来进行标记\nthose requires a stack for marking.\n\n711\n00:30:08,260 --> 00:30:11,050\nLisp系统通过这样的方式\nLisp systems that are built this way\n\n712\n00:30:11,570 --> 00:30:14,160\n限制了你在数据结构上\nhave a limit to the depth of recursion you can have\n\n713\n00:30:14,425 --> 00:30:17,375\n进行CAR或者CDR递归的深度\nin data structures in either the car or the cdr,\n\n714\n00:30:17,817 --> 00:30:19,350\n这并不太靠谱\nand that doesn't work very nicely.\n\n715\n00:30:19,930 --> 00:30:20,608\n另外一方面\nOn the other hand,\n\n716\n00:30:20,640 --> 00:30:22,128\n当它足够大的时候你不会发现\nyou never notice it if it's big enough.\n\n717\n00:30:23,180 --> 00:30:25,136\n例如 这样的情况\nAnd that's certainly been\n\n718\n00:30:25,552 --> 00:30:28,176\n发生在大多数MacLisp系统上\nthe case for most Maclisp, for example,\n\n719\n00:30:28,690 --> 00:30:29,888\n在它上面运行的Macsyma\nwhich ran Macsyma\n\n720\n00:30:29,960 --> 00:30:31,104\n允许你处理\nwhere you could deal with expressions\n\n721\n00:30:31,104 --> 00:30:32,720\n有成千上万个元素的表达式\nof thousands of elements long.\n\n722\n00:30:33,560 --> 00:30:36,025\n有很多代数式有大量的项\nThese are algebraic expressions with thousand of terms.\n\n723\n00:30:36,825 --> 00:30:38,100\n这没什么问题\nAnd there's no problem with that.\n\n724\n00:30:39,490 --> 00:30:40,825\n垃圾回收器能正常工作\nSuch, the garbage collector does work.\n\n725\n00:30:42,190 --> 00:30:42,925\n另一方面\nOn the other hand,\n\n726\n00:30:42,925 --> 00:30:45,375\n这个算法有个很精妙的修改版\nthere's a very clever modification to this algorithm,\n\n727\n00:30:45,375 --> 00:30:46,475\n但我不会去讲\nwhich I will not describe,\n\n728\n00:30:46,800 --> 00:30:48,220\n它是由Peter Deutsch\nby Peter Deutsch and Schorr and Waite--\n\n729\n00:30:48,640 --> 00:30:51,824\n来自IBM的Herb Schorr\nand Schorr and Waite, Herb Schorr from IBM\n\n730\n00:30:51,872 --> 00:30:53,520\n和我不太认识的Waite所提出\nand Waite who I don't know.\n\n731\n00:30:54,016 --> 00:30:56,512\n这个算法\nWhrere... That algorithm\n\n732\n00:30:56,670 --> 00:30:57,792\n可以不使用\nallows you build\n\n733\n00:30:57,840 --> 00:30:59,550\n额外的辅助内存\nyou do can do this without auxiliary memory,\n\n734\n00:31:00,500 --> 00:31:02,800\n只需要在遍历整个数据结构的时候\nby remembering as you walk the data structures\n\n735\n00:31:02,975 --> 00:31:05,525\n记住你是从哪里来的并反转指针\nwhere you came from by reversing the pointers as you go down\n\n736\n00:31:05,525 --> 00:31:07,520\n回溯的时候 再去反转这个指针\nand crawling up the reverse pointers as you go up.\n\n737\n00:31:07,792 --> 00:31:08,992\n这是个很取巧的算法\nIt's a rather tricky algorithm.\n\n738\n00:31:09,130 --> 00:31:10,240\n你第一次写它的时候\nThe first time you write it--\n\n739\n00:31:10,256 --> 00:31:11,712\n事实上 你前三次写它的时候\nor in fact, the first three times you write it it\n\n740\n00:31:11,712 --> 00:31:12,720\n都会遇到严重的BUG\nit has a terrible bug in it.\n\n741\n00:31:14,350 --> 00:31:16,725\n也可能奇慢无比\nAnd it's also about, it's quite rather slow,\n\n742\n00:31:16,725 --> 00:31:17,675\n因为这个算法太复杂了\nbecause it's complicated.\n\n743\n00:31:18,110 --> 00:31:20,304\n它用了大概六倍的内存引用\nIt takes about six times as many memory references\n\n744\n00:31:20,850 --> 00:31:23,225\n来完成我们刚才讨论的任务\nto do the sorts of things that we're talking about.\n\n745\n00:31:24,580 --> 00:31:27,075\n一旦我完成了标记阶段\nWell now once I've done this marking phase,\n\n746\n00:31:27,500 --> 00:31:30,128\n我们就面临着这样的状况\nand I get into a position where things look like this,\n\n747\n00:31:30,176 --> 00:31:31,264\n请看\nlet's look-- yes.\n\n748\n00:31:31,510 --> 00:31:34,032\n这里完成了标记工作\nHere we have the mark done,\n\n749\n00:31:34,080 --> 00:31:35,008\n和我刚才描述的一样\njust as I did it.\n\n750\n00:31:35,590 --> 00:31:37,330\n现在我们要进行清除阶段\nNow we have to perform the sweep phase.\n\n751\n00:31:37,600 --> 00:31:39,320\n我刚才已经讲过如何清除了\nAnd I described to you what this sweep is like.\n\n752\n00:31:39,820 --> 00:31:42,348\n我要从内存的一端开始\nI'm going to walk down from one end of memory or the other,\n\n753\n00:31:42,340 --> 00:31:43,344\n哪一端都可以\nI don't care where,\n\n754\n00:31:43,628 --> 00:31:46,175\n扫描内存中的每个格子\nscanning every cell that's in the memory.\n\n755\n00:31:47,175 --> 00:31:48,675\n在扫描的同时\nAnd as I scan these cells,\n\n756\n00:31:49,200 --> 00:31:50,976\n如果是空闲内存\nI'm going to link them together,\n\n757\n00:31:50,992 --> 00:31:52,840\n就把它们连接到空闲表中\nif they are free, into the free list.\n\n758\n00:31:53,150 --> 00:31:54,050\n如果它们不是空闲内存\nAnd if they're not free,\n\n759\n00:31:54,050 --> 00:31:56,075\n我就把它们的标记清除掉\nI'm going to unmark them so the marks become zero.\n\n760\n00:31:57,500 --> 00:31:58,576\n事实上\nAnd in fact what I get--\n\n761\n00:31:58,700 --> 00:32:00,460\n最终的程序并不很复杂\nwell the program is not very complicated.\n\n762\n00:32:00,460 --> 00:32:02,225\n它只是变长了一些\nIt looks sort of like this-- it's a little longer.\n\n763\n00:32:02,780 --> 00:32:04,175\n这是第一部分\nHere's the first piece of it.\n\n764\n00:32:04,820 --> 00:32:06,710\n它从内存的顶端向下遍历\nThis one's coming down from the top of memory.\n\n765\n00:32:06,710 --> 00:32:09,580\n我不期望你现在就搞懂它\nI don't want you to try to understand this at this point.\n\n766\n00:32:09,580 --> 00:32:10,550\n它挺简单的\nIt's rather simple.\n\n767\n00:32:11,030 --> 00:32:12,525\n这是个非常简单的算法\nIt's a very simple algorithm,\n\n768\n00:32:13,075 --> 00:32:15,970\n其中的一段代码像是这样\nbut there's pieces of it that just sort of look like this.\n\n769\n00:32:15,970 --> 00:32:17,375\n非常显而易见\nThey're all sort of obvious.\n\n770\n00:32:18,600 --> 00:32:20,080\n在清理结束后\nAnd after we've done the sweep,\n\n771\n00:32:20,300 --> 00:32:21,776\n我们就得到了像这样的结果\nwe get an answer that looks like that.\n\n772\n00:32:25,330 --> 00:32:26,544\n这种标记-清除算法\nNow there are some disadvantages\n\n773\n00:32:26,560 --> 00:32:28,208\n有一些缺点\nwith mark-sweep algorithms of this sort.\n\n774\n00:32:29,590 --> 00:32:30,350\n最严重的一个是\nSerious ones.\n\n775\n00:32:31,450 --> 00:32:33,203\n最严重的缺点是\nOne important disadvantage is\n\n776\n00:32:33,203 --> 00:32:34,975\n当你的内存越来越大\nthat your memories get larger and larger.\n\n777\n00:32:36,826 --> 00:32:38,875\n地址空间也就会越来越大\nAs you say, address spaces get larger and larger,\n\n778\n00:32:38,875 --> 00:32:40,800\n你想用它存更多东西\nyou're willing to represent more and more stuff,\n\n779\n00:32:41,370 --> 00:32:44,528\n那么扫描整个内存就会非常耗时\nthen it gets very costly to scan all of memory.\n\n780\n00:32:46,360 --> 00:32:47,392\n你真正想做的是\nWhat you'd really like to do\n\n781\n00:32:47,408 --> 00:32:48,688\n只扫描有用的东西\nis only scan useful stuff.\n\n782\n00:32:50,490 --> 00:32:51,550\n这样就会好一点\nIt would even be better\n\n783\n00:32:52,070 --> 00:32:53,904\n如果你意识到\nif you realized that some stuff\n\n784\n00:32:54,480 --> 00:32:57,720\n哪些东西已知是有用的\nwas known to be good and useful,\n\n785\n00:32:58,283 --> 00:33:00,370\n你就没必要去多次检查它\nand you don't have to look at it more than once or twice.\n\n786\n00:33:00,370 --> 00:33:01,200\n或者不用经常去检查它\nOr very rarely.\n\n787\n00:33:01,550 --> 00:33:04,325\n对于那些你不太确定的\nWhereas other stuff that you're not so sure about,\n\n788\n00:33:05,000 --> 00:33:06,224\n你可以在每次需要的时候\nyou can look at more detail\n\n789\n00:33:07,100 --> 00:33:08,750\n进行仔细检查\nevery time you want to do this,\n\n790\n00:33:09,931 --> 00:33:10,850\n也就是垃圾收集的时候\nwant to garbage collect.\n\n791\n00:33:11,910 --> 00:33:13,744\n这些算法\nWell there are algorithms\n\n792\n00:33:13,760 --> 00:33:15,100\n就是用了这样的方法\nthat are organized in this way.\n\n793\n00:33:15,660 --> 00:33:18,160\n我要介绍一个著名的古老算法\nLet me tell you about a famous old algorithm\n\n794\n00:33:18,280 --> 00:33:19,472\n这种算法允许你\nwhich allows you only look at\n\n795\n00:33:19,504 --> 00:33:21,370\n只检查内存中已知是有用的部分\nthe part of memory which is known to be useful.\n\n796\n00:33:23,120 --> 00:33:23,856\n这让它成为了\nAnd which happens to be\n\n797\n00:33:23,872 --> 00:33:25,290\n目前已知最快的垃圾收集算法\nthe fastest known garbage collector algorithm.\n\n798\n00:33:26,310 --> 00:33:29,450\n它就是 Minsky-Fenichel-Yochelson 垃圾收集算法\nThis is the Minsky-Fenichel-Yochelson garbage collector algorithm.\n\n799\n00:33:30,400 --> 00:33:33,184\n它是由Minsky\nIt was invented by Minsky\n\n800\n00:33:33,200 --> 00:33:36,064\n在1960、61年左右发明的\nin 1961 or '60 or something,\n\n801\n00:33:36,520 --> 00:33:40,480\n当时是给RLE PDP-1 Lisp用的\nfor the RLE PDP-1 Lisp,\n\n802\n00:33:40,512 --> 00:33:43,440\n这个机器只有4096个字的线性内存\nwhich had 4,096 words of list memory,\n\n803\n00:33:45,792 --> 00:33:46,768\n还有个磁鼓\nand a drum.\n\n804\n00:33:48,480 --> 00:33:49,392\n为了能够\nAnd the whole idea\n\n805\n00:33:50,032 --> 00:33:51,870\n在这种恶劣的条件下进行垃圾收集\nwas to garbage collect this terrible memory.\n\n806\n00:33:53,050 --> 00:33:54,352\nMinsky意识到\nWhat Minsky realized\n\n807\n00:33:54,384 --> 00:33:55,620\n达成目的最容易的方法是\nwas the easiest way to do this\n\n808\n00:33:56,200 --> 00:33:58,475\n在扫描内存的同时\nis to scan the memory in the same sense,\n\n809\n00:33:58,475 --> 00:34:00,600\n遍历那些好的数据结构\nwalking the good structure,\n\n810\n00:34:01,575 --> 00:34:03,525\n把它复制到磁鼓中\ncopying it out into the drum,\n\n811\n00:34:04,700 --> 00:34:05,475\n压缩一下\ncompacted.\n\n812\n00:34:06,350 --> 00:34:08,864\n之后把它们复制出来\nAnd then when we were done copying it all out,\n\n813\n00:34:09,127 --> 00:34:10,900\n并把它们交换回内存里\nthen you swap that back into your memory.\n\n814\n00:34:12,300 --> 00:34:13,680\n不管是使用的是磁鼓\nNow whether or you not use a drum,\n\n815\n00:34:13,728 --> 00:34:14,710\n或者其它的内存\nor another piece of memory,\n\n816\n00:34:14,710 --> 00:34:16,425\n这都不重要\nor something like that isn't important.\n\n817\n00:34:17,030 --> 00:34:17,424\n事实上\nIn fact,\n\n818\n00:34:17,440 --> 00:34:19,600\n我觉得现在应该没人用磁鼓了吧\nI don't think people use drums anymore for anything.\n\n819\n00:34:20,350 --> 00:34:23,776\n但这个算法基本上\nBut this algorithm basically\n\n820\n00:34:24,032 --> 00:34:25,420\n要依赖于\ndepends upon having\n\n821\n00:34:25,420 --> 00:34:27,424\n大约两倍于\nabout twice as much address space\n\n822\n00:34:27,488 --> 00:34:28,570\n你实际使用的内存\nyou're actually using.\n\n823\n00:34:30,270 --> 00:34:32,960\n最开始的情况是\nAnd so what you have is some, initially,\n\n824\n00:34:33,125 --> 00:34:36,600\n有用的数据和垃圾混在了一起\nsome mixture of useful data and garbage.\n\n825\n00:34:37,110 --> 00:34:38,975\n它被称为FROMSPACE\nSo this is called fromspace.\n\n826\n00:34:45,179 --> 00:34:47,050\n这是CRUD的混合\nAnd this is a mixture of crud.\n\n827\n00:34:47,872 --> 00:34:49,792\n有些是有用的 有些没有用\nSome of it's important and some of it isn't.\n\n828\n00:34:52,000 --> 00:34:53,856\n现在还有另外一块空间\nNow there's another place\n\n829\n00:34:54,176 --> 00:34:55,616\n它需要足够大\nwhich is hopefully big enough,\n\n830\n00:34:55,770 --> 00:34:57,008\n这个地方叫TOSPACE\nif we recall, tospace,\n\n831\n00:34:57,123 --> 00:34:58,240\n要把东西复制进去\nwhich is where we're copying to.\n\n832\n00:35:01,590 --> 00:35:02,600\n接下来会发生的是\nAnd what happens is--\n\n833\n00:35:02,600 --> 00:35:04,064\n我不会深入细节\nand I'm not going to go through this detail.\n\n834\n00:35:04,160 --> 00:35:07,070\n书上写得很清楚了\nIt's in our book quite explicitly.\n\n835\n00:35:07,590 --> 00:35:10,400\n这里有一个根节点\nThere's a root point where you start from.\n\n836\n00:35:11,030 --> 00:35:14,300\n你从根节点开始\nAnd the idea is that you start with the root.\n\n837\n00:35:14,600 --> 00:35:16,425\n复制你看到的第一个东西\nYou copy the first thing you see,\n\n838\n00:35:17,830 --> 00:35:19,376\n根指针指向的第一个东西\nthe first thing that the root points at,\n\n839\n00:35:19,750 --> 00:35:21,312\n复制到TOSPACE的头部\nto the beginning of tospace.\n\n840\n00:35:22,810 --> 00:35:24,128\n这些东西一般是一个序对\nThe first thing is a pair\n\n841\n00:35:24,160 --> 00:35:25,600\n或者是类似的数据结构\nor something like, a data structure.\n\n842\n00:35:27,560 --> 00:35:30,192\n然后在那里留下\nYou then also leave behind\n\n843\n00:35:30,384 --> 00:35:31,568\n一颗“破碎的心”\na broken heart saying,\n\n844\n00:35:31,775 --> 00:35:35,743\n表示我把东西从这里移动到了这里\nI moved this object from here to here,\n\n845\n00:35:35,743 --> 00:35:37,050\n指示了移动的目的地\ngiving the place where it moved to.\n\n846\n00:35:37,800 --> 00:35:39,650\n叫作破碎的心是因为\nThis is called a broken heart because\n\n847\n00:35:39,650 --> 00:35:40,784\n我的一个朋友\na friend of mine who implemented\n\n848\n00:35:40,784 --> 00:35:43,392\n在1966年实现了这个算法\none of these in 1966\n\n849\n00:35:43,825 --> 00:35:45,262\n而他是个文艺青年\nwas a very romantic character\n\n850\n00:35:45,262 --> 00:35:46,760\n就取名叫“破碎的心”\nand called it a broken heart.\n\n851\n00:35:49,580 --> 00:35:50,544\n不论如何\nBut in any case,\n\n852\n00:35:51,150 --> 00:35:52,720\n接下来要做的是\nthe next thing you do\n\n853\n00:35:52,940 --> 00:35:55,008\nFREE指针现在指向这里\nis now you have a new free pointer which is here,\n\n854\n00:35:55,170 --> 00:35:56,384\n然后开始扫描\nand you start scanning.\n\n855\n00:35:56,880 --> 00:35:59,680\n扫描这个刚复制过来的数据结构\nYou scan this data structure you just copied.\n\n856\n00:36:00,551 --> 00:36:02,195\n每当你遇到其中的指针\nAnd every time you encounter a pointer in it,\n\n857\n00:36:02,190 --> 00:36:03,920\n你把它当作是这里的根指针\nyou treat it as if it was the root pointer here.\n\n858\n00:36:04,000 --> 00:36:04,592\n哦 不好意思\nOh, I'm sorry.\n\n859\n00:36:04,600 --> 00:36:05,696\n我们还需要做的是\nThe other thing you do\n\n860\n00:36:05,712 --> 00:36:07,088\n你将根指针移动到这里\nis you now move the root pointer to there.\n\n861\n00:36:09,220 --> 00:36:10,175\n因此在扫描的过程中\nSo now you scan this,\n\n862\n00:36:10,170 --> 00:36:10,992\n把遇到的每个指针\nand everything you see\n\n863\n00:36:11,008 --> 00:36:12,416\n都可以当作是ROOT指针\nyou treat as it were the root pointer.\n\n864\n00:36:14,110 --> 00:36:15,450\n如果你遇到了某个指针\nSo if you see something,\n\n865\n00:36:15,450 --> 00:36:17,400\n指向了这里的某个地方\nwell it points up into there somewhere.\n\n866\n00:36:18,510 --> 00:36:19,920\n它指向的东西\nIs it pointing at a thing\n\n867\n00:36:19,936 --> 00:36:20,992\n你复制过了吗？\nwhich you've not copied yet?\n\n868\n00:36:21,780 --> 00:36:22,875\n这里是“破碎的心”吗\nIs there a broken heart there?\n\n869\n00:36:23,880 --> 00:36:24,844\n如果那里是破碎的心\nIf there's a broken heart there\n\n870\n00:36:24,840 --> 00:36:26,112\n就说明那里的东西复制过了\nand it's something you have copied,\n\n871\n00:36:26,200 --> 00:36:27,344\n只需要用破碎的心所指向的地址\nyou've just replaced this pointer\n\n872\n00:36:27,360 --> 00:36:28,750\n来替换它指针即可\nwith the thing a broken heart points at.\n\n873\n00:36:29,820 --> 00:36:32,032\n如果它还没被复制\nIf this thing has not been copied,\n\n874\n00:36:32,120 --> 00:36:34,080\n你把它复制到这里\nyou copy it to the next place over here.\n\n875\n00:36:34,430 --> 00:36:35,950\n把FREE指针移到这里\nMove your free pointer over here,\n\n876\n00:36:37,050 --> 00:36:40,608\n然后在那里放置一颗破碎的心\nand then leave a broken heart behind\n\n877\n00:36:41,050 --> 00:36:41,800\n继续扫描\nand scan.\n\n878\n00:36:43,670 --> 00:36:46,400\n最终SCAN指针追上了FREE指针\nAnd eventually when the scant pointer hits the free pointer,\n\n879\n00:36:46,825 --> 00:36:48,525\n内存里的所有东西都被复制了\neverything in memory has been copied.\n\n880\n00:36:50,140 --> 00:36:51,040\n这样这里就剩下了\nAnd then there's a whole bunch\n\n881\n00:36:51,056 --> 00:36:51,950\n大量的空闲空间\nof empty space up here,\n\n882\n00:36:51,960 --> 00:36:53,280\n如果你需要的话\nwhich you could either make into a free list,\n\n883\n00:36:53,312 --> 00:36:54,470\n你可以把它组织为空闲表\nif that's what you want to do.\n\n884\n00:36:54,470 --> 00:36:56,270\n但这种系统通常不这么来做\nBut generally you don't in this kind of system.\n\n885\n00:36:56,270 --> 00:36:59,150\n这类系统中 内存是顺序分配的\nIn this system you sequentially allocate your memory.\n\n886\n00:37:00,910 --> 00:37:02,480\n这是个非常 非常好的算法\nThat is a very, very nice algorithm,\n\n887\n00:37:02,970 --> 00:37:04,576\n你们现在使用的Scheme系统中\nand sort of the one we use in the\n\n888\n00:37:04,672 --> 00:37:05,970\n就使用了这种算法\nthe scheme that you've been using.\n\n889\n00:37:06,790 --> 00:37:09,475\n它应该是--\nAnd it's known to be... it's expected--\n\n890\n00:37:09,470 --> 00:37:10,864\n我相信还没有人发现\nI believe no one has found\n\n891\n00:37:10,896 --> 00:37:12,120\n比它跑得更快的算法\na faster algorithm than that.\n\n892\n00:37:12,400 --> 00:37:14,850\n有一些对这个算法的简单修改\nThere are very simple modifications to this algorithm\n\n893\n00:37:14,850 --> 00:37:16,775\n由Henry Baker发明\ninvented by Henry Baker\n\n894\n00:37:17,175 --> 00:37:20,311\n它让你能实时运行这个算法\nwhich allow one to run this algorithm in real time,\n\n895\n00:37:20,310 --> 00:37:21,920\n也就是说进行回收时不需要暂停程序\nmeaning you don't have to stop to garbage collect.\n\n896\n00:37:22,144 --> 00:37:24,336\n你能够让机器运行时\nBut you could interleave the consing\n\n897\n00:37:24,368 --> 00:37:26,176\n进行的各种CONS操作\nthat the machine does when its running\n\n898\n00:37:26,327 --> 00:37:28,400\n与垃圾回收过程交错进行\nwith steps of the garbage collection process,\n\n899\n00:37:28,850 --> 00:37:31,200\n垃圾回收器是分散的\nso that the thing, the garbage collector's distributed\n\n900\n00:37:31,200 --> 00:37:32,192\n机器不需要停下来\nand the machine doesn't have to stop,\n\n901\n00:37:32,416 --> 00:37:33,475\n再让垃圾回收开始运作\nand garbage collecting can start.\n\n902\n00:37:34,640 --> 00:37:37,872\n当然 在使用虚拟内存的机器中\nOf course in the case of machines with virtual memory\n\n903\n00:37:38,900 --> 00:37:41,200\n有很多内存无法访问\nwhere a lot of it is in inaccessible places,\n\n904\n00:37:41,509 --> 00:37:43,600\n这会让整个过程变得耗时\nthis becomes a very expensive process.\n\n905\n00:37:44,280 --> 00:37:46,432\n有很多人尝试\nAnd there have been numerous\n\n906\n00:37:47,168 --> 00:37:48,650\n将它改进得更好\nattempts to make this much better.\n\n907\n00:37:49,190 --> 00:37:51,152\n对于感兴趣的同学\nThere is a nice paper,\n\n908\n00:37:51,168 --> 00:37:52,416\n这有一篇论文\nfor those of you who are interested,\n\n909\n00:37:52,640 --> 00:37:54,272\n作者是Moon等人\nby Moon and other people\n\n910\n00:37:54,650 --> 00:37:56,896\n这篇论文描述了\nwhich describes a modification to\n\n911\n00:37:56,928 --> 00:37:59,440\n增量式Minsky-Fenichel-Yochelson算法\nthe incremental Minsky-Fenichel-Yochelson algorithm,\n\n912\n00:37:59,510 --> 00:38:01,200\n和Baker算法的修改\nand modification the Baker algorithm\n\n913\n00:38:01,420 --> 00:38:06,544\n让使用虚拟内存的系统更加高效\nwhich is more efficient for virtual memory systems.\n\n914\n00:38:08,272 --> 00:38:12,320\n现在最后一个谜团也解开了\nWell I think now the mystery to this is sort of gone.\n\n915\n00:38:12,840 --> 00:38:14,090\n有什么疑惑吗？\nAnd I'd like to see if there are any questions.\n\n916\n00:38:19,780 --> 00:38:19,952\n请讲\nYes.\n\n917\n00:38:20,600 --> 00:38:23,584\n学生：我在楼上的系统上\nAUDIENCE: I saw one of you run the garbage collector\n\n918\n00:38:23,648 --> 00:38:25,050\n你们运行垃圾收集器的时候\non the systems upstairs,\n\n919\n00:38:25,930 --> 00:38:27,880\n它看起来跑得飞快\nand it seemed to me to run extremely fast.\n\n920\n00:38:27,968 --> 00:38:28,400\n教授：是的\nPROFESSOR: Yes\n\n921\n00:38:28,490 --> 00:38:29,520\n学生：整个过程花费了--\nAUDIENCE: Did the whole thing take--\n\n922\n00:38:30,112 --> 00:38:31,880\n它真的扫描了整个内存吗？\ndoes it sweep through all of memory?\n\n923\n00:38:31,880 --> 00:38:32,224\n教授：没有\nPROFESSOR: No.\n\n924\n00:38:32,250 --> 00:38:34,112\n它只扫描了那些需要的\nIt swept through exactly what was needed\n\n925\n00:38:34,336 --> 00:38:35,632\n去复制那些有用的数据结构\nto copy the useful structure.\n\n926\n00:38:37,320 --> 00:38:38,360\n它是个复制收集器\nIt's a copying collector.\n\n927\n00:38:38,448 --> 00:38:38,912\n学生：好吧\nAUDIENCE: OK.\n\n928\n00:38:39,300 --> 00:38:40,880\n教授：但它确实很快\nPROFESSOR: And it's rather... it is very fast.\n\n929\n00:38:41,850 --> 00:38:45,888\n整体来说 我想如果要复制\nOn the whole, I suppose to copy in a Bobcat\n\n930\n00:38:47,120 --> 00:38:51,568\n一个大约3MB的东西\nto copy, I think, a three megabyte thing or something\n\n931\n00:38:52,430 --> 00:38:53,240\n将在一秒内完成\nis less than a second,\n\n932\n00:38:55,008 --> 00:38:55,696\n而且是实时的\nreal time\n\n933\n00:38:56,544 --> 00:38:58,464\n它们是非常小的程序\nReally, these are very small programs.\n\n934\n00:38:58,620 --> 00:39:01,504\n你需要注意到的一件事是\nOne thing you should realise is that\n\n935\n00:39:02,913 --> 00:39:04,400\n垃圾收集器必须要小\ngarbage collectors have to be small.\n\n936\n00:39:05,400 --> 00:39:07,100\n不是因为它们需要运行得快\nNot because they have to be fast,\n\n937\n00:39:07,900 --> 00:39:09,232\n因为没有人能够调试\nbut because no one can debug\n\n938\n00:39:09,264 --> 00:39:10,480\n复杂的垃圾收集器\na complicated garbage collector.\n\n939\n00:39:11,340 --> 00:39:12,912\n如果一个垃圾收集器不能正常工作\nA garbage collector, if it doesn't work,\n\n940\n00:39:14,049 --> 00:39:15,933\n它会把你的内存搞得一团糟\nwill trash your memory in such a way\n\n941\n00:39:15,930 --> 00:39:17,392\n而你却束手无策\nthat you cannot figure out what the hell happened.\n\n942\n00:39:18,350 --> 00:39:19,675\n你需要跟踪审计\nYou need an audit trail.\n\n943\n00:39:20,660 --> 00:39:22,016\n因为它把所有东西都换了位置\nBecause it rearranges everything,\n\n944\n00:39:22,048 --> 00:39:23,248\n你需要知道那里发生了什么\nand how do you know what happened there?\n\n945\n00:39:23,740 --> 00:39:26,587\n所以这是唯一一种\nSo this is the only kind of program that\n\n946\n00:39:26,920 --> 00:39:28,400\n真正非常重要的程序\nit really, seriously matters\n\n947\n00:39:28,540 --> 00:39:29,792\n如果你盯着它看足够久\nif you stare at it long enough\n\n948\n00:39:29,824 --> 00:39:31,070\n那么你就相信它有效\nso you believe that it works.\n\n949\n00:39:31,344 --> 00:39:33,360\n这意味着某种“自我证明”\nThat means and sort of prove it to yourself.\n\n950\n00:39:33,920 --> 00:39:36,112\n因此我们无法对它进行查错\nAnd that, that... So there's no way to debug it.\n\n951\n00:39:36,940 --> 00:39:38,960\n这意味着它需要足够小\nAnd that takes it being small enough\n\n952\n00:39:38,960 --> 00:39:39,975\n你的大脑能够思考它的工作情况\nso you can hold it in your head.\n\n953\n00:39:41,456 --> 00:39:43,904\n正因如此 垃圾收集器十分特殊\nSo garbage collectors are special in this way.\n\n954\n00:39:45,020 --> 00:39:47,120\n所以实用的垃圾收集器一定要短小\nSo every reasonable garbage collector has gotten small,\n\n955\n00:39:47,136 --> 00:39:48,450\n而通常短小的程序运行得就快\nand generally small programs are fast.\n\n956\n00:39:52,050 --> 00:39:52,430\n请讲\nYes.\n\n957\n00:39:52,430 --> 00:39:54,510\n学生：您能再重复一遍这个技术的名字吗?\nAUDIENCE: Can you repeat the name of this technique once again?\n\n958\n00:39:54,688 --> 00:39:56,920\n教授：Minsky-Fenichel-Yochelson垃圾回收器\nPROFESSOR: That's the Minsky-Fenichel-Yochelson garbage collector.\n\n959\n00:39:57,888 --> 00:39:58,432\n学生：什么?\nAUDIENCE: You got that?\n\n960\n00:39:59,000 --> 00:40:00,784\n教授：Minsky在1961年\nPROFESSOR: Minsky invented it in '61\n\n961\n00:40:00,816 --> 00:40:02,210\n为RLE PDP-1设计了这个算法\nfor the RLE PDP-1.\n\n962\n00:40:02,210 --> 00:40:06,176\nFenichel和Yochelson改进并精化了算法\nA version of it was developed and elaborated\n\n963\n00:40:06,450 --> 00:40:10,275\n将它用在了Multics平台的MacLisp中\nto be used in Multics Maclisp by Fenichel and Yochelson\n\n964\n00:40:11,378 --> 00:40:14,750\n那时大约是1968或者1969年\nin somewhere around 1968 or '69.\n\n965\n00:40:19,570 --> 00:40:21,360\n好吧 我们休息一下\nOK. Let's take a break.\n\n966\n00:40:22,640 --> 00:40:32,368\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n967\n00:40:32,416 --> 00:40:36,192\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n968\n00:41:03,150 --> 00:41:07,184\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Sussman Jay Sussman\n\n969\n00:41:07,200 --> 00:41:10,176\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n970\n00:41:10,208 --> 00:41:14,224\n计算的极限\nNot Everything Can Be Computed\n\n971\n00:41:17,310 --> 00:41:19,675\n教授：我们已经到课程的最后一部分了\nPROFESSOR: Well we've come to the end of this subject,\n\n972\n00:41:20,080 --> 00:41:23,850\n我已经给你们展示了一台通用机器\nand we've already shown you a universal machine\n\n973\n00:41:24,475 --> 00:41:26,740\n它被简化为求值器\nwhich is down to evaluator.\n\n974\n00:41:27,025 --> 00:41:28,388\n它被简化到\nIt's down to the level of detail\n\n975\n00:41:28,388 --> 00:41:29,675\n你自己也能构造出来\nyou could imagine you could make one.\n\n976\n00:41:30,192 --> 00:41:33,320\n这是一个特定的Lisp实现\nThis is a particular implementation of Lisp,\n\n977\n00:41:33,900 --> 00:41:36,016\n它是用\nbuilt on one of those\n\n978\n00:41:36,160 --> 00:41:38,050\n昨天讲过的Scheme芯片制作的\nscheme chips that was talked about yesterday,\n\n979\n00:41:38,208 --> 00:41:38,912\n就是这个\nsitting over here.\n\n980\n00:41:39,350 --> 00:41:42,000\n这基本上就是暴露给他人内存的接口了\nThis is mostly interface to somebody's memory\n\n981\n00:41:42,600 --> 00:41:44,750\n里面有节拍发生器等组件\nwith a little bit of timing and other such stuff.\n\n982\n00:41:45,225 --> 00:41:47,250\n尽管是解释执行\nBut this fellow actually ran Lisp\n\n983\n00:41:47,775 --> 00:41:50,175\n但它们运行Lisp的速度还算不错\nat a fairly reasonable rate, as interpretive.\n\n984\n00:41:50,610 --> 00:41:53,825\n它跑得像1979年的\nIt ran Lisp as fast as a DEC PDP-10\n\n985\n00:41:54,225 --> 00:41:55,650\nDEC PDP-10一样快\nback in 1979.\n\n986\n00:41:56,500 --> 00:41:59,675\n作为一个十足的硬件\nAnd so it's gotten pretty hardware.\n\n987\n00:42:00,020 --> 00:42:00,896\n算是十分“实在”了\nPretty concrete.\n\n988\n00:42:02,470 --> 00:42:04,704\n我们为你们讲解了一些\nWe've also downed you a bit\n\n989\n00:42:04,720 --> 00:42:06,070\n可以被计算的东西\nwith the things you can compute.\n\n990\n00:42:07,370 --> 00:42:08,768\n但我们是否可能遇到\nBut is it the case that\n\n991\n00:42:09,328 --> 00:42:10,550\n我们无法计算的情况？\nthere are things we can't compute?\n\n992\n00:42:11,850 --> 00:42:13,500\n课程的最后\nAnd so I'd like to end this with\n\n993\n00:42:13,750 --> 00:42:15,872\n我想展示一些你认为可以被计算\nshowing you some things that you'd like be able to compute\n\n994\n00:42:16,608 --> 00:42:17,220\n但实际上不能的东西\nthat you can't.\n\n995\n00:42:18,190 --> 00:42:19,456\n实际上\nThe answer is yes,\n\n996\n00:42:19,456 --> 00:42:20,820\n确实有我们无法计算的东西\nthere are things you can't compute.\n\n997\n00:42:22,720 --> 00:42:23,471\n例如\nFor example,\n\n998\n00:42:24,450 --> 00:42:25,825\n我们想要这样的一种东西\nsomething you'd really like is--\n\n999\n00:42:27,800 --> 00:42:29,360\n当我们在编写编译器时\nif you're writing a compiler\n\n1000\n00:42:29,775 --> 00:42:31,425\n你想用一个程序检查\nyou'd like a program that would check\n\n1001\n00:42:32,000 --> 00:42:33,975\n你的代码能否正常运行\nthat the thing you're going to do will work.\n\n1002\n00:42:34,630 --> 00:42:35,400\n这不是很棒吗?\nWouldn't that be nice?\n\n1003\n00:42:36,080 --> 00:42:37,875\n你希望能够捕获死循环\nYou'd like something that would catch infinite loops,\n\n1004\n00:42:37,870 --> 00:42:38,544\n例如\nfor example,\n\n1005\n00:42:39,450 --> 00:42:42,425\n用户编写的程序里的死循环\nin programs that were written by users.\n\n1006\n00:42:43,190 --> 00:42:45,125\n但通常来说 你写不出这样的程序\nBut in general you can't write such a program\n\n1007\n00:42:45,350 --> 00:42:46,496\n它读取某个程序\nthat will read any program\n\n1008\n00:42:46,512 --> 00:42:47,456\n并检测它\nand determine whether or not\n\n1009\n00:42:48,350 --> 00:42:49,300\n是不是死循环\nit's an infinite loop.\n\n1010\n00:42:50,990 --> 00:42:51,712\n我来展示一下\nLet me show you that.\n\n1011\n00:42:51,760 --> 00:42:53,808\n这个需要涉及到数学知识\nIt's a little bit of a minor mathematics.\n\n1012\n00:42:58,780 --> 00:42:59,650\n设想\nLet's imagine\n\n1013\n00:43:00,050 --> 00:43:01,781\n在我们开始之前\nthat we just had a mathematical function\n\n1014\n00:43:01,781 --> 00:43:02,620\n有一个数学函数\nbefore we start.\n\n1015\n00:43:02,620 --> 00:43:03,425\n这里就有一个\nAnd there is one,\n\n1016\n00:43:03,840 --> 00:43:04,672\n记作S\ncalled s,\n\n1017\n00:43:05,475 --> 00:43:07,546\n它接受一个过程\nwhich takes a procedure\n\n1018\n00:43:12,640 --> 00:43:14,230\n和它的参数A\nand its argument, a.\n\n1019\n00:43:19,175 --> 00:43:20,525\nS所做的是\nAnd what s does\n\n1020\n00:43:21,650 --> 00:43:24,014\n检测以A为参数运行P时\nis it determines whether or not\n\n1021\n00:43:24,014 --> 00:43:25,975\n是否安全\nit's safe to run p on a.\n\n1022\n00:43:26,900 --> 00:43:28,175\n换句话说就是\nAnd what I mean by that is this:\n\n1023\n00:43:28,768 --> 00:43:35,120\n如果(P A)\nit's true if p applied to a\n\n1024\n00:43:35,625 --> 00:43:36,740\n在没有出错的情况下\nwill converge\n\n1025\n00:43:41,400 --> 00:43:42,450\n能够返回一个值\nto a value\n\n1026\n00:43:44,350 --> 00:43:45,330\n那么S就为TRUE\nwithout an error.\n\n1027\n00:43:52,700 --> 00:43:53,680\n但如果(P A)\nAnd it's false\n\n1028\n00:43:56,100 --> 00:43:57,040\n是死循环\nif p of a\n\n1029\n00:43:59,675 --> 00:44:00,765\n或者抛出错误\nloops forever\n\n1030\n00:44:05,875 --> 00:44:06,950\n那么S就为FALSE\nor makes an error.\n\n1031\n00:44:15,232 --> 00:44:17,220\n这确实是个函数\nNow that's surely a function.\n\n1032\n00:44:18,780 --> 00:44:20,725\n对于你输入的任何过程\nThere is some for every procedure\n\n1033\n00:44:21,200 --> 00:44:22,850\n或者任何参数\nand for every argument you could give it\n\n1034\n00:44:23,920 --> 00:44:25,456\n它只能返回TRUE或FALSE\nthat is either true or false\n\n1035\n00:44:25,925 --> 00:44:27,850\n它会返回一个值而且不会报错\nthat it converges without making an error.\n\n1036\n00:44:28,440 --> 00:44:30,150\n你可以为它们画一张巨大的表格\nAnd you could make a giant table of them.\n\n1037\n00:44:32,225 --> 00:44:32,925\n但问题是\nBut the question is,\n\n1038\n00:44:32,925 --> 00:44:34,093\n你能写一个过程\ncan you write a procedure\n\n1039\n00:44:34,093 --> 00:44:35,925\n来计算这个函数的值吗?\nthat compute the values of this function?\n\n1040\n00:44:37,430 --> 00:44:38,928\n假设我们能做到\nWell let's assume that we can.\n\n1041\n00:44:39,720 --> 00:44:40,550\n假设\nSuppose\n\n1042\n00:44:44,336 --> 00:44:45,584\n我们有个过程\nthat we have a procedure\n\n1043\n00:44:48,550 --> 00:44:52,736\n一个叫作SAFE?的过程\nprocedure called \"safe\"\n\n1044\n00:44:56,544 --> 00:44:59,900\n它能计算S的值\nthat computes the value of s.\n\n1045\n00:45:12,656 --> 00:45:14,896\n现在我要用几种方法\nNow I'm going to show you by several methods\n\n1046\n00:45:15,900 --> 00:45:18,512\n证明你做不到\nthat you can't do this.\n\n1047\n00:45:19,760 --> 00:45:20,626\n最简单的一个\nThe easiest one,\n\n1048\n00:45:20,620 --> 00:45:21,280\n或者说第一个\nor the first one,\n\n1049\n00:45:21,312 --> 00:45:23,450\n我们定义一个叫DIAG1的过程\nlet's define a procedure called diag1.\n\n1050\n00:45:23,760 --> 00:45:24,864\n给定了SAFE?过程\nGiven that we have safe,\n\n1051\n00:45:25,200 --> 00:45:26,993\n我们可以把DIAG1定义为\nwe can define diag1\n\n1052\n00:45:34,425 --> 00:45:35,550\n把DIAG1定义为\ndiag1\n\n1053\n00:45:37,824 --> 00:45:41,600\n只含有参数P的过程\nto be the procedure of one argument, p,\n\n1054\n00:45:42,450 --> 00:45:44,050\n它有着这样的属性\nwhich has the following properties.\n\n1055\n00:45:44,780 --> 00:45:50,675\n如果(SAFE? P P)为真\nIf it's safe to apply p to itself,\n\n1056\n00:45:53,325 --> 00:45:55,325\n那么我就主动陷入死循环\nthen I wish to have an infinite loop.\n\n1057\n00:45:59,225 --> 00:46:00,925\n否则我会返回3\nOtherwise I'm going to return 3.\n\n1058\n00:46:03,680 --> 00:46:04,470\n它也可能是42\nMaybe it was 42.\n\n1059\n00:46:04,470 --> 00:46:06,425\n宇宙的终极答案是什么?\nWhat's the answer to the big question?\n\n1060\n00:46:07,060 --> 00:46:08,875\n我们当然知道死循环是什么\nWhere of course we know what an infinite loop is.\n\n1061\n00:46:12,050 --> 00:46:12,964\n死循环INF是\nInfinite loop,\n\n1062\n00:46:13,825 --> 00:46:16,025\n一个无参过程\nto be a procedure of no arguments,\n\n1063\n00:46:16,025 --> 00:46:18,075\n这是一个极好的LAMBADA演算循环\nwhich is that nice lambda calculus loop.\n\n1064\n00:46:18,352 --> 00:46:20,448\n(LAMBDA (X) (X X))\nLambda of x,\n\n1065\n00:46:21,300 --> 00:46:24,680\n应用到(LAMBDA (X) (X X))\napplied to lambda of x, x of x.\n\n1066\n00:46:24,680 --> 00:46:26,550\n没什么想象的余地了\nSo there's nothing left to the imagination here.\n\n1067\n00:46:29,830 --> 00:46:31,175\n我们来看下会发生什么\nWell let's see what the story is.\n\n1068\n00:46:32,500 --> 00:46:33,908\n我假设\nI'm supposing it's the case\n\n1069\n00:46:35,450 --> 00:46:38,772\n我们考虑\nthat we worry about the procedure\n\n1070\n00:46:39,000 --> 00:46:43,450\n把DIAG1应用到DIAG1上\ncalled diag1 applied to diag1.\n\n1071\n00:46:46,275 --> 00:46:47,775\n那会发生什么呢?\nWell what could it possibly be?\n\n1072\n00:46:49,970 --> 00:46:51,390\n我不知道\nWell I don't know.\n\n1073\n00:46:51,390 --> 00:46:53,213\n将DIAG1代换为\nWe're going to substitute diag1\n\n1074\n00:46:53,550 --> 00:46:55,500\nP的过程体\nfor p in the body here.\n\n1075\n00:46:57,310 --> 00:47:00,220\n(SAFE? DIAG1 DIAG1)会返回什么呢？\nWell is it safe to compute diag1 of diag1?\n\n1076\n00:47:00,220 --> 00:47:00,780\n我不知道\nI don't know.\n\n1077\n00:47:00,780 --> 00:47:01,825\n有两种可能\nThere are two possibilities.\n\n1078\n00:47:03,400 --> 00:47:05,501\n如果计算(DIAG1 DIAG1)是安全的\nIf it's safe to compute diag1 of diag1\n\n1079\n00:47:05,920 --> 00:47:06,896\n这意味着没有死循环\nthat means it shouldn't loop.\n\n1080\n00:47:08,490 --> 00:47:09,225\n那么我就要来到这里\nThat means I go to here,\n\n1081\n00:47:09,225 --> 00:47:10,350\n但是随即我就陷入了死循环\nbut then I produce an infinite loop.\n\n1082\n00:47:10,560 --> 00:47:11,575\n所以它不是安全的\nSo it can't be safe.\n\n1083\n00:47:12,210 --> 00:47:14,781\n但如果计算(DIAG1 DIAG1)不安全\nBut if it's not safe to compute diag1 of diag1\n\n1084\n00:47:14,900 --> 00:47:16,020\n那么它的结果是3\nthen the answer to this is 3.\n\n1085\n00:47:16,020 --> 00:47:17,267\n但是调用(DIAG1 DIAG1)又必须能够返回\nBut that's diag1 of diag1,\n\n1086\n00:47:17,260 --> 00:47:17,936\n所以它必须安全才行\nso it had to be safe.\n\n1087\n00:47:20,530 --> 00:47:23,600\n因此 通过归纳出这个矛盾\nSo therefore by contradiction\n\n1088\n00:47:24,325 --> 00:47:26,300\n我们无法写出这个SAFE?过程\nyou cannot produce safe.\n\n1089\n00:47:27,400 --> 00:47:29,805\n如果大家没有听明白这种表述\nFor those of you who were boggled by that one\n\n1090\n00:47:30,250 --> 00:47:32,150\n我换个方式再讲一遍\nI'm going to say it again, in a different way.\n\n1091\n00:47:32,820 --> 00:47:34,000\n请听另一个版本\nListen to one more alternative.\n\n1092\n00:47:35,530 --> 00:47:36,950\n我们定义DIAG2\nLet's define diag2.\n\n1093\n00:47:39,840 --> 00:47:41,600\n取名叫DIAG是因为\nThese are named diag because\n\n1094\n00:47:42,650 --> 00:47:44,725\n它来源于康托尔的对角论证法\nof Cantor's diagonal argument.\n\n1095\n00:47:45,000 --> 00:47:47,050\n这些事例最初都来自于\nThese are instances of\n\n1096\n00:47:47,050 --> 00:47:49,056\n一个著名的论证\na famous argument which was originally used by\n\n1097\n00:47:49,450 --> 00:47:52,650\n也就是康托尔在19世纪末\nCantor in the late part of the last century\n\n1098\n00:47:52,775 --> 00:47:56,106\n证明了实数是不可数的\nto prove that the real numbers were not countable,\n\n1099\n00:47:56,670 --> 00:47:58,000\n整数与实数\nthat there are too many real numbers\n\n1100\n00:47:58,064 --> 00:47:59,420\n无法形成一一映射\nto be counted by integers.\n\n1101\n00:48:00,190 --> 00:48:01,741\n数轴上的点\nThat there are more points on a line,\n\n1102\n00:48:01,741 --> 00:48:02,500\n举例来说\nfor example,\n\n1103\n00:48:02,506 --> 00:48:04,425\n比数轴上的刻度还要多\nthan there are counting numbers.\n\n1104\n00:48:05,260 --> 00:48:06,858\n这或许不是个显而易见的结论\nIt may or may not be obvious,\n\n1105\n00:48:06,858 --> 00:48:08,175\n但我不想深入讨论这个\nand I don't want to get into that now.\n\n1106\n00:48:10,900 --> 00:48:12,450\n但是DIAG2\nBut diag2\n\n1107\n00:48:13,300 --> 00:48:15,820\n也是一个参数为P的单参过程\nis again a procedure of one argument p.\n\n1108\n00:48:15,820 --> 00:48:17,475\n这几乎与之前的例子相同\nIt's almost the same as the previous one,\n\n1109\n00:48:17,725 --> 00:48:24,323\n如果计算(P P)是安全的\nwhich is, if it's safe to compute p on p,\n\n1110\n00:48:25,175 --> 00:48:26,675\n那么我就要\nthen I'm going to produce--\n\n1111\n00:48:27,260 --> 00:48:28,144\n哦 漏了一个IF\nOops, if\n\n1112\n00:48:29,312 --> 00:48:31,020\n那么我就去计算\nthen I want to compute\n\n1113\n00:48:31,570 --> 00:48:37,584\n一些(P P)之外的东西\nsome other things\n\n1114\n00:48:38,960 --> 00:48:40,210\n否则我就返回FALSE\nOtherwise I'm going to put out false.\n\n1115\n00:48:43,600 --> 00:48:45,300\n这里的OTHER-THAN意思是\nWhere other then it says,\n\n1116\n00:48:45,472 --> 00:48:46,350\n不管这个(P P)是什么\nwhatever p of p,\n\n1117\n00:48:46,352 --> 00:48:47,475\n我都返回一些别的东西\nI'm going to put out something else.\n\n1118\n00:48:48,880 --> 00:48:50,032\n我来给出一个\nI can give you an example of\n\n1119\n00:48:50,075 --> 00:48:51,525\nOTHER-THAN的一个定义\na definition of other than\n\n1120\n00:48:51,600 --> 00:48:52,570\n我觉得它是可用的\nwhich I think works.\n\n1121\n00:48:53,890 --> 00:48:54,512\n来看看\nLet's see.\n\n1122\n00:48:55,640 --> 00:48:56,080\n好\nYes.\n\n1123\n00:48:56,330 --> 00:48:57,266\n定义OTHER-THAN\nWhere other than\n\n1124\n00:49:04,030 --> 00:49:06,112\n参数为X的单参过程\nbe a procedure of one argument x\n\n1125\n00:49:06,576 --> 00:49:07,260\n过程体是\nwhich says,\n\n1126\n00:49:08,050 --> 00:49:12,961\n如果(EQ? X 'A)\nif its eq x to, say, quote a,\n\n1127\n00:49:13,472 --> 00:49:15,070\n那么结果是'B\nthen the answer is quote b.\n\n1128\n00:49:15,720 --> 00:49:16,800\n否则结果是'A\nOtherwise it's quote a.\n\n1129\n00:49:20,272 --> 00:49:21,900\n这样无论参数是什么\nThat always produces something\n\n1130\n00:49:22,075 --> 00:49:23,450\n返回值跟参数总是不相同的\nwhich is not what its argument is.\n\n1131\n00:49:25,200 --> 00:49:26,120\n就是这样了\nThat's all it is.\n\n1132\n00:49:26,540 --> 00:49:27,375\n这就是我要的\nThat's all I wanted.\n\n1133\n00:49:28,250 --> 00:49:29,587\n我们考虑一下这个\nWell now let's consider this one,\n\n1134\n00:49:29,587 --> 00:49:31,150\n(DIAG2 DIAG2)\ndiag2 of diag2.\n\n1135\n00:49:38,288 --> 00:49:38,944\n看\nWell look.\n\n1136\n00:49:39,950 --> 00:49:41,725\n这个东西会做些危险的事情\nThis only does something dangerous,\n\n1137\n00:49:42,000 --> 00:49:43,450\n比如求值(P P)\nlike calling p of p,\n\n1138\n00:49:44,750 --> 00:49:45,950\n如果它是安全的\nif it's safe to do so.\n\n1139\n00:49:47,470 --> 00:49:49,168\n如果SAFE?能够被定义的话\nSo if safe defined at all,\n\n1140\n00:49:50,300 --> 00:49:52,496\n如果你能定义SAFE?过程\nif you can define such a procedure, safe,\n\n1141\n00:49:52,975 --> 00:49:54,325\n那么这个过程\nthen this procedure\n\n1142\n00:49:54,608 --> 00:49:56,400\n也就顺理成章地是安全的\nis always defined and therefore safe\n\n1143\n00:49:56,525 --> 00:49:57,225\n对于任意输入来说都是\non any inputs.\n\n1144\n00:50:01,540 --> 00:50:03,504\n那么(DIAG2 DIAG2)\nSo diag2 of diag2\n\n1145\n00:50:03,875 --> 00:50:12,200\n就会返回(OTHER-THAN (DIAG2 DIAG2))\nmust reduce to other than diag2 of diag2.\n\n1146\n00:50:15,825 --> 00:50:16,975\n这说不通\nAnd that doesn't make sense,\n\n1147\n00:50:17,800 --> 00:50:19,024\n又产生了悖论\nso we have a contradiction,\n\n1148\n00:50:19,850 --> 00:50:21,575\n因此我们不能定义SAFE?\nand therefore we can't define safe.\n\n1149\n00:50:22,950 --> 00:50:24,237\n我只想这样证明两次\nI just waned to do that twice,\n\n1150\n00:50:24,784 --> 00:50:25,820\n有些许不同\nslightly differently,\n\n1151\n00:50:26,848 --> 00:50:27,900\n你不会感到\nso you wouldn't feel\n\n1152\n00:50:29,072 --> 00:50:30,864\n第一个证明是个把戏\nthat the first one was a trick.\n\n1153\n00:50:32,544 --> 00:50:33,450\n它们可能都是把戏\nThey may be both tricks,\n\n1154\n00:50:33,800 --> 00:50:35,152\n但它们稍微有些不同\nbut they're at least slightly different.\n\n1155\n00:50:37,300 --> 00:50:39,200\n因此 我想这就基本上讲清楚了\nSo I suppose that pretty much wraps it up.\n\n1156\n00:50:40,032 --> 00:50:41,970\n我们刚刚证明了所谓的“停机问题”\nI've just proved what we call the halting theorem,\n\n1157\n00:50:43,000 --> 00:50:44,704\n我想 本课程也即将画上句号\nand I suppose with that we're going to halt.\n\n1158\n00:50:46,720 --> 00:50:47,632\n希望你们有所收获\nI hope you have a good time.\n\n1159\n00:50:50,900 --> 00:50:51,765\n有什么问题吗?\nAre there any questions?\n\n1160\n00:50:53,300 --> 00:50:53,568\n请讲\nYes.\n\n1161\n00:50:53,810 --> 00:50:56,275\n学生: (S DIAG1)的值是什么?\nAUDIENCE: What is the value of s of diag1?\n\n1162\n00:50:56,750 --> 00:50:57,232\n教授: 什么的值?\nPROFESSOR: Of what?\n\n1163\n00:50:57,504 --> 00:50:58,800\n学生: (S DIAG1)的值\nAUDIENCE: S of diag1.\n\n1164\n00:51:00,120 --> 00:51:02,208\n如果你说S是个函数 我们就可以--\nIf you said s is a function, and then we can\n\n1165\n00:51:02,304 --> 00:51:03,632\n教授: 噢 我不知道啊\nPROFESSOR: Oh, I don't know.\n\n1166\n00:51:03,870 --> 00:51:04,350\n我不知道\nI don't know.\n\n1167\n00:51:04,350 --> 00:51:04,882\n它是一个函数\nIt's a function,\n\n1168\n00:51:04,880 --> 00:51:05,856\n但我不知道如何计算它\nbut I don't know how to compute it.\n\n1169\n00:51:06,800 --> 00:51:08,000\n我做不到\nI can't do it.\n\n1170\n00:51:08,610 --> 00:51:09,648\n我也只是个机器\nI'm just a machine, too.\n\n1171\n00:51:11,530 --> 00:51:11,888\n对吧?\nRight?\n\n1172\n00:51:11,904 --> 00:51:13,370\n原则上来说\nAnd there's no machine\n\n1173\n00:51:13,375 --> 00:51:14,050\n没有机器\nthat in principle--\n\n1174\n00:51:14,475 --> 00:51:16,875\n当然 也有可能会处在你刚才问的那个情况中\nit might be that in that particular case you just asked,\n\n1175\n00:51:16,870 --> 00:51:18,320\n花点时间还是可以计算出来\nwith some thinking I could figure it out.\n\n1176\n00:51:18,580 --> 00:51:19,375\n但通常情况下\nBut in general\n\n1177\n00:51:19,600 --> 00:51:21,050\n我无法计算S的值\nI can't compute the value of s\n\n1178\n00:51:21,050 --> 00:51:22,525\n别的机器也做不到\nany better than any other machine can.\n\n1179\n00:51:23,780 --> 00:51:24,925\n存在这样一个函数\nThere is such a function,\n\n1180\n00:51:25,925 --> 00:51:28,000\n没有任何机器能够计算它\nit's just that no machine can be built to compute it.\n\n1181\n00:51:29,580 --> 00:51:30,050\n现在\nNow\n\n1182\n00:51:30,672 --> 00:51:33,675\n我这么来说也不会让你们吃惊\nthere's a way of saying that that should not be surprising.\n\n1183\n00:51:35,225 --> 00:51:36,250\n来想一想\nGoing through this--\n\n1184\n00:51:36,250 --> 00:51:38,362\n现在我没有时间给你们展示\nI mean, I don't have time to do this here,\n\n1185\n00:51:38,450 --> 00:51:43,000\n但这样的函数非常多\nbut the number of functions is very large.\n\n1186\n00:51:44,400 --> 00:51:47,584\n如果有一定量的可能输入\nIf there's a certain number of answers possible\n\n1187\n00:51:47,754 --> 00:51:49,626\n和一定量可能的结果\nand a certain number of inputs possible,\n\n1188\n00:51:49,875 --> 00:51:51,800\n那么结果数量的输入数量次幂\nthen it's the number of answers raised to the number inputs\n\n1189\n00:51:51,800 --> 00:51:53,200\n就是可能的函数的数量\nis the number of possible functions.\n\n1190\n00:51:54,500 --> 00:51:55,488\n这还是单参的函数\nOn one variable.\n\n1191\n00:51:56,510 --> 00:51:59,248\n而多参函数的个数\nNow that's always bigger\n\n1192\n00:52:00,090 --> 00:52:03,216\n又比这个幂次方\nthan the thing you're raising to,\n\n1193\n00:52:03,584 --> 00:52:04,320\n这个指数还要大\nthe exponent.\n\n1194\n00:52:05,480 --> 00:52:09,800\n函数的数量\nThe number of functions is larger\n\n1195\n00:52:09,950 --> 00:52:12,725\n比一个人能写出的\nthan the number of programs\n\n1196\n00:52:13,306 --> 00:52:14,100\n程序的数量更多\nthat one can write,\n\n1197\n00:52:14,825 --> 00:52:16,450\n因为有无穷多的参数\nby an infinity counting argument.\n\n1198\n00:52:17,575 --> 00:52:19,000\n可能会更多\nAnd it's much larger.\n\n1199\n00:52:19,475 --> 00:52:22,124\n所以不可计算的函数数量\nSo there must be a lot of functions\n\n1200\n00:52:22,120 --> 00:52:23,488\n一定会非常多\nthat can't be computed by programs.\n\n1201\n00:52:25,920 --> 00:52:26,592\n学生：不久前\nAUDIENCE: A few moments ago\n\n1202\n00:52:26,640 --> 00:52:28,256\n你讲了规范\nyou were talking about specifications\n\n1203\n00:52:28,304 --> 00:52:30,048\n和自动生成解决方案\nand automatic generation of solutions.\n\n1204\n00:52:30,640 --> 00:52:31,616\n您觉得通过规范\nDo you see any steps\n\n1205\n00:52:31,824 --> 00:52:33,360\n能够生成解决方案么？\nbetween specifications and solutions?\n\n1206\n00:52:37,250 --> 00:52:38,225\n教授：“生成”\nPROFESSOR: Steps between.\n\n1207\n00:52:38,720 --> 00:52:39,375\n你是说\nYou mean, you're saying,\n\n1208\n00:52:39,375 --> 00:52:42,603\n如何按照规范\nhow you go about constructing\n\n1209\n00:52:42,600 --> 00:52:44,784\n构建相应的装置吗?\ndevices given that have specifications for the device?\n\n1210\n00:52:45,056 --> 00:52:48,360\n学生：软件工程中有很多\nAUDIENCE: There's a lot of software engineering\n\n1211\n00:52:48,361 --> 00:52:49,900\n层次化的设计\nthat goes through specifications through\n\n1212\n00:52:49,900 --> 00:52:51,900\n并进行实现的规范\nmany layers of design and then implementation.\n\n1213\n00:52:52,430 --> 00:52:52,850\n教授：是的\nPROFESSOR: Yes?\n\n1214\n00:52:52,850 --> 00:52:53,700\n学生：我很好奇\nAUDIENCE: I was curious\n\n1215\n00:52:53,700 --> 00:52:54,625\n您觉得这现实吗?\nif you think that's realistic.\n\n1216\n00:52:55,600 --> 00:52:57,175\n教授：我觉得其中一些是现实的\nPROFESSOR: Well I think that some of it's realistic\n\n1217\n00:52:57,175 --> 00:52:58,100\n另一些不现实\nand some of it isn't.\n\n1218\n00:52:58,100 --> 00:53:00,320\n如果你想制造一个滤波器\nI mean, surely if I want to build an electrical filter\n\n1219\n00:53:01,175 --> 00:53:07,160\n我这有个挺有趣的例子\nand I have a rather interesting possibility.\n\n1220\n00:53:07,160 --> 00:53:09,424\n假设我想制造一个东西\nSupposing I want to build a thing that matches\n\n1221\n00:53:09,648 --> 00:53:14,070\n把无线电发射器的输出\nthat matches some power output to the radio transmitter,\n\n1222\n00:53:14,475 --> 00:53:18,750\n连接到某条天线上\nto some antenna.\n\n1223\n00:53:19,900 --> 00:53:21,472\n我先把它引出来\nAnd I'm really out of this power--\n\n1224\n00:53:21,488 --> 00:53:23,040\n这里是输出管线\nit's output tube out here.\n\n1225\n00:53:23,230 --> 00:53:25,264\n问题是它们的阻抗不同\nAnd the problem is that they have different impedances.\n\n1226\n00:53:25,920 --> 00:53:27,550\n我希望能够匹配阻抗\nI want them to match the impedances.\n\n1227\n00:53:27,550 --> 00:53:28,976\n我也想在其中加入一个滤波器\nI also want to make a filter in there\n\n1228\n00:53:29,150 --> 00:53:31,712\n用来过滤一些谐波辐射\nwhich is going to get rid of some harmonic radiation.\n\n1229\n00:53:32,780 --> 00:53:36,638\n一种老派的技术叫作\nWell one old-fashioned technique for doing this is called\n\n1230\n00:53:36,820 --> 00:53:38,672\n“影像阻抗”之类的东西\nimage impedances, or something like that.\n\n1231\n00:53:38,860 --> 00:53:39,500\n你要做的是\nAnd what you do\n\n1232\n00:53:39,500 --> 00:53:40,850\n你有个基础的模块\nis you say you have a basic module\n\n1233\n00:53:40,850 --> 00:53:42,750\n称为L型滤波器\ncalled an L-section.\n\n1234\n00:53:43,300 --> 00:53:43,984\n就像这样\nLooks like this.\n\n1235\n00:53:47,080 --> 00:53:49,800\n如果把它连接到某些电阻R上\nIf I happen to connect this to some resistance, r,\n\n1236\n00:53:50,050 --> 00:53:52,600\n如果我把它的阻抗记作X_L\nand if I make this impedance x, xl,\n\n1237\n00:53:52,720 --> 00:53:55,200\n而它的值刚好又等于Q*R\nand if it happens to be q times r,\n\n1238\n00:53:55,264 --> 00:53:58,520\n这就成了一个低通滤波器\nthen this produces a low pass filter\n\n1239\n00:53:58,520 --> 00:54:00,720\n有Q^2+1的等效阻抗\nwith a q square plus one impedance match.\n\n1240\n00:54:02,110 --> 00:54:02,864\n这就是我想要的\nJust what I need.\n\n1241\n00:54:03,120 --> 00:54:04,288\n因为这样我就可以\nBecause now I can take two of these,\n\n1242\n00:54:04,304 --> 00:54:05,088\n把它们匹配到一起了\nhook them together\n\n1243\n00:54:05,824 --> 00:54:06,384\n就像这样\nlike this.\n\n1244\n00:54:11,660 --> 00:54:13,150\n我拿来另一个\nOK, and I take another one\n\n1245\n00:54:16,000 --> 00:54:17,456\n想这样把它们连到一起\nand I'll hook them together like that.\n\n1246\n00:54:18,290 --> 00:54:19,950\n有两个L型滤波器连接起来\nAnd I have two L-sections hooked together.\n\n1247\n00:54:20,320 --> 00:54:23,070\n这能让它的阻抗降到我知道的值\nAnd this will step the impedance down to one that I know,\n\n1248\n00:54:23,375 --> 00:54:25,225\n让它的阻抗升到我知道的值\nand this will step it up to one I know.\n\n1249\n00:54:25,530 --> 00:54:26,640\n这两个低通滤波器\nEach of these is a low pass filter\n\n1250\n00:54:26,672 --> 00:54:27,824\n都过滤掉了一些谐波\ngetting rid of some harmonics.\n\n1251\n00:54:28,090 --> 00:54:29,072\n这是个不错的滤波器\nIt's good filter,\n\n1252\n00:54:29,072 --> 00:54:30,270\n这就是π型滤波器\nit's called a pie-section filter.\n\n1253\n00:54:30,270 --> 00:54:30,624\n很好\nGreat.\n\n1254\n00:54:31,700 --> 00:54:34,096\n除了实际上\nExcept for the fact that in doing what I just did,\n\n1255\n00:54:34,128 --> 00:54:37,850\n我在系统里放了些无用的东西\nI've made a terrible inefficiency in this system.\n\n1256\n00:54:38,620 --> 00:54:39,600\n我在本该只用一个的地方\nI've made two coils\n\n1257\n00:54:39,616 --> 00:54:40,592\n用了两个线圈\nwhere I should have made one.\n\n1258\n00:54:41,620 --> 00:54:44,600\n在大多数软件工程技艺中\nAnd the problem with most software engineering art\n\n1259\n00:54:44,890 --> 00:54:46,880\n在人工优化和编译之外\nis that there's no mechanism,\n\n1260\n00:54:46,928 --> 00:54:48,656\n不存在一种机制\nother than people optimization and compilers,\n\n1261\n00:54:48,800 --> 00:54:51,344\n能在自顶向下的设计中\nfor getting rid of the redundant parts\n\n1262\n00:54:51,344 --> 00:54:53,550\n去掉冗余的部分\nthat are constructed when doing top down design.\n\n1263\n00:54:55,350 --> 00:54:56,076\n或许会更糟\nIt's even worse,\n\n1264\n00:54:56,070 --> 00:54:57,584\n有很多重要的结构\nthere are lots of very important structures\n\n1265\n00:54:57,600 --> 00:54:59,020\n你无法采用这种方式构建\nthat you can't construct at all this way.\n\n1266\n00:55:01,110 --> 00:55:03,535\n我觉得标准的自上而下的设计方式\nSo I think that the standard top down design\n\n1267\n00:55:03,535 --> 00:55:04,875\n是一种很短视的手段\nis a rather shallow business.\n\n1268\n00:55:05,710 --> 00:55:06,600\n它不会真的抓到\nDoesn't really capture\n\n1269\n00:55:06,600 --> 00:55:08,100\n设计者真正想要的结果\nwhat people want to do in design.\n\n1270\n00:55:08,315 --> 00:55:10,100\n我再举一个电子学的例子\nI'll give you another electrical example.\n\n1271\n00:55:10,100 --> 00:55:11,750\n电子学的例子\nElectrical examples are so much clearer\n\n1272\n00:55:11,900 --> 00:55:13,136\n要比计算的例子直观得多\nthan computational examples,\n\n1273\n00:55:13,168 --> 00:55:14,784\n因为计算的例子\nbecause computation examples require\n\n1274\n00:55:14,800 --> 00:55:16,520\n解释起来比较复杂\na certain degree of complexity to explain them.\n\n1275\n00:55:17,220 --> 00:55:19,168\n在电子学世界中\nBut one of my favorite examples\n\n1276\n00:55:19,168 --> 00:55:20,040\n我最喜欢的例子之一是\nin the electrical world\n\n1277\n00:55:20,600 --> 00:55:22,800\n是如何设计中频放大器中\nis how would I ever come up with the output stage\n\n1278\n00:55:23,280 --> 00:55:26,550\n输入级和输出级的连接方式\nof this inter-stage connection in an IF amplifier.\n\n1279\n00:55:27,530 --> 00:55:29,440\n这是一个三极管\nIt's a little transistor here,\n\n1280\n00:55:29,520 --> 00:55:31,500\n我们来看看\nand let's see.\n\n1281\n00:55:32,410 --> 00:55:33,400\n这有个LC震荡电路\nWell I'm going to have a tank,\n\n1282\n00:55:36,450 --> 00:55:39,175\n我要把它\nand I'm going to hook this up to, say,\n\n1283\n00:55:41,375 --> 00:55:43,975\n把它与下一级的输入线圈耦合在一起\nI'm going to link-couple that to the input of the next stage.\n\n1284\n00:55:44,368 --> 00:55:47,470\n这是个完美的可行方案\nHere's a perfectly plausible plan--\n\n1285\n00:55:48,225 --> 00:55:50,875\n除了我这个电流方向画错了\nwell except for the fact that since I put that going up\n\n1286\n00:55:50,875 --> 00:55:52,925\n电流应该是这个方向\nI should make that going that way. OK?\n\n1287\n00:55:53,170 --> 00:55:55,456\n这是个完美的可行方案\nHere's a perfectly plausible plan for a--\n\n1288\n00:55:55,984 --> 00:55:56,576\n不对\nno I shouldn't.\n\n1289\n00:55:57,120 --> 00:55:57,792\n我犯蠢了\nI'm dumb.\n\n1290\n00:55:58,400 --> 00:55:59,075\n对不起\nExcuse me.\n\n1291\n00:55:59,690 --> 00:56:00,425\n这不重要\nDoesn't matter.\n\n1292\n00:56:00,730 --> 00:56:01,540\n关键在于这是一个\nThe point is it's a perfect\n\n1293\n00:56:01,540 --> 00:56:03,425\n把两级耦合起来的完美方案\nplan for a couple two stages together.\n\n1294\n00:56:04,544 --> 00:56:06,920\n分层来看时会产生什么问题?\nNow what the problem is what's this hierarchically?\n\n1295\n00:56:07,620 --> 00:56:08,800\n它就不是同一个东西了\nIt's not one thing.\n\n1296\n00:56:09,480 --> 00:56:11,990\n当分层来看时它就没有任何意义了\nHierarchically it doesn't make any sense at all.\n\n1297\n00:56:11,990 --> 00:56:14,325\n这是一个调谐电路的电感\nIt's the inductance of a tuned circuit,\n\n1298\n00:56:15,550 --> 00:56:18,025\n这是变压器的初级线圈\nit's the primary of a transformer,\n\n1299\n00:56:19,100 --> 00:56:21,825\n这是直流的通路\nand it's also the DC path by\n\n1300\n00:56:21,825 --> 00:56:23,575\n它是三极管的集电极\nwhich bias conditions get to the\n\n1301\n00:56:23,575 --> 00:56:25,100\n的偏置条件\ncollector of that transistor.\n\n1302\n00:56:26,460 --> 00:56:28,352\n没有任何简单的自顶向下设计\nAnd there's no simple top-down design\n\n1303\n00:56:28,384 --> 00:56:30,170\n能够得到这样的结构\nthat's going to produce a structure like that\n\n1304\n00:56:30,225 --> 00:56:34,025\n对于同一个东西有大量的复用\nwith so many overlapping uses for a particular thing.\n\n1305\n00:56:34,530 --> 00:56:36,729\n玩拼字游戏\nPlaying Scrabble,\n\n1306\n00:56:36,960 --> 00:56:39,888\n当你要完成三倍分数的词时\nwhere you have to do triple word scores, or whatever,\n\n1307\n00:56:40,496 --> 00:56:43,600\n自顶向下的设计策略并不容易\nis not so easy in top-down design strategy.\n\n1308\n00:56:44,950 --> 00:56:47,088\n然而 大多数实际的工程学都是\nYet most of real engineering is based on\n\n1309\n00:56:47,360 --> 00:56:50,700\n秉承着“尽其力而为之”\non getting the most oomph for effort.\n\n1310\n00:56:52,140 --> 00:56:53,525\n那就是你所看到的东西\nAnd that's what you're seeing here.\n\n1311\n00:56:54,860 --> 00:56:55,550\n嗯？\nYeah?\n\n1312\n00:56:55,550 --> 00:56:56,810\n学生：这是最后一个问题吗?\nAUDIENCE: Is this the last question?\n\n1313\n00:57:00,280 --> 00:57:02,032\n[笑声]\n[LAUGHTER]\n\n1314\n00:57:18,640 --> 00:57:19,632\n教授：看起来是\nPROFESSOR: Apparently so.\n\n1315\n00:57:23,575 --> 00:57:24,125\n谢谢大家\nThank you.\n\n1316\n00:57:25,300 --> 00:57:36,500\n[掌声]\n[APPLAUSE]\n\n1317\n00:57:39,040 --> 00:58:52,200\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n1318\n00:58:52,200 --> 00:58:54,200\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n1319\n00:58:54,200 --> 00:58:56,200\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n1320\n00:58:56,200 --> 00:58:58,200\n你所知道的有关计算的东西，其他人也都能学到。绝不要认为似乎成功计算的钥匙就掌握在你的手里。你所掌握的，也是我认为并希望的，也就是智慧：那种看到这一机器比你第一次站在它面前时能做得更多的能力，这样你才能将它向前推进。\nAlan J. Perlis\n\n"
  },
  {
    "path": "SrtCN/lec1a.srt",
    "content": "﻿1\r\n00:00:01,100 --> 00:00:04,500\r\n哈尔滨工业大学 IBM技术中心\r\n倾情制作\r\n\r\n2\r\n00:00:04,600 --> 00:00:09,400\r\n压制&&特效：蔡钟敏（Tacitus）\r\n字幕&&时间轴：邓雄飞（Dysprosium）\r\n\r\n3\r\n00:00:09,500 --> 00:00:13,000\r\n特别感谢：裘宗燕\r\n\r\n4\r\n00:00:14,264 --> 00:00:17,440\r\n欢迎大家来一起学习这门计算机科学的基础课程\r\nI'd like to welcome you to this course on computer science.\r\n\r\n5\r\n00:00:27,952 --> 00:00:29,408\r\n事实上 以这样的方式来表述并不恰当\r\nActually, that's a terrible way to start.\r\n\r\n6\r\n00:00:29,408 --> 00:00:31,890\r\n于此来说 计算机科学是个糟糕的名字\r\nComputer science is a terrible name for this business.\r\n\r\n7\r\n00:00:32,384 --> 00:00:33,856\r\n首先 它不算是一门科学\r\nFirst of all, it's not a science.\r\n\r\n8\r\n00:00:35,472 --> 00:00:39,020\r\n它更应该被称为工程或者是艺术\r\nIt might be engineering or it might be art,\r\n\r\n9\r\n00:00:39,648 --> 00:00:42,464\r\n但我们实际上会发现 这个所谓的计算机科学\r\nbut we'll actually see that computer so-called science\r\n\r\n10\r\n00:00:42,480 --> 00:00:44,528\r\n却与魔法一样的有众多神奇之处\r\nactually has a lot in common with magic,\r\n\r\n11\r\n00:00:44,560 --> 00:00:45,904\r\n这些将会在课程中一一体现\r\nand we'll see that in this course.\r\n\r\n12\r\n00:00:46,832 --> 00:00:47,776\r\n所以 不能称其为一门科学\r\nSo it's not a science.\r\n\r\n13\r\n00:00:48,648 --> 00:00:51,854\r\n这门学科和“计算机”也并非紧密相关\r\nIt's also not really very much about computers.\r\n\r\n14\r\n00:00:52,944 --> 00:00:55,024\r\n类似的 就像我们说\r\nAnd it's not about computers in the same sense\r\n\r\n15\r\n00:00:55,024 --> 00:00:59,600\r\n物理学中并不仅仅有关粒子加速器\r\nthat physics is not really about particle accelerators,\r\n\r\n16\r\n00:01:00,352 --> 00:01:05,136\r\n生物学中并不全然是显微镜和培养皿一样\r\nand biology is not really about microscopes and petri dishes.\r\n\r\n17\r\n00:01:06,010 --> 00:01:09,800\r\n同理\r\nAnd it's not about computers in the same sense\r\n\r\n18\r\n00:01:09,860 --> 00:01:14,432\r\n几何学中也并不全是介绍如何使用测量仪器\r\nthat geometry is not really about using surveying instruments.\r\n\r\n19\r\n00:01:16,032 --> 00:01:18,560\r\n事实上 计算机科学和几何学\r\nIn fact, there's a lot of commonality\r\n\r\n20\r\n00:01:18,880 --> 00:01:21,000\r\n有很多共性\r\nbetween computer science and geometry.\r\n\r\n21\r\n00:01:21,000 --> 00:01:22,213\r\n首先 几何学\r\nGeometry, first of all,\r\n\r\n22\r\n00:01:22,579 --> 00:01:24,535\r\n只是另一个有个糟糕名字的学科\r\nis another subject with a lousy name.\r\n\r\n23\r\n00:01:25,136 --> 00:01:27,400\r\n这个名字来自于Gaia 意为土地\r\nThe name comes from Gaia, meaning the Earth,\r\n\r\n24\r\n00:01:27,450 --> 00:01:28,640\r\n以及metron 意为测量\r\nand metron, meaning to measure.\r\n\r\n25\r\n00:01:29,376 --> 00:01:32,944\r\n几何学最初意为测地或者勘探\r\nGeometry originally meant measuring the Earth or surveying.\r\n\r\n26\r\n00:01:33,920 --> 00:01:36,440\r\n这是因为数千年前的埃及祭司\r\nAnd the reason for that was that, thousands of years ago,\r\n\r\n27\r\n00:01:37,248 --> 00:01:41,248\r\n为了计算如何去修复年年被尼罗河的洪水\r\nthe Egyptian priesthood developed the rudiments of geometry\r\n\r\n28\r\n00:01:42,144 --> 00:01:45,888\r\n所毁坏的牧田边界\r\nin order to figure out how to restore the boundaries of fields\r\n\r\n29\r\n00:01:45,888 --> 00:01:45,904\r\n而建立了几何学基础\r\nthat were destroyed in the annual flooding of the Nile.\r\n\r\n30\r\n00:01:45,904 --> 00:01:48,240\r\n而建立了几何学基础\r\nthat were destroyed in the annual flooding of the Nile.\r\n\r\n31\r\n00:01:49,024 --> 00:01:50,208\r\n而对出于这个目的的埃及人来说\r\nAnd to the Egyptians who did that,\r\n\r\n32\r\n00:01:50,208 --> 00:01:53,488\r\n几何学的确是掌握对测量仪器的使用\r\ngeometry really was the use of surveying instruments.\r\n\r\n33\r\n00:01:55,184 --> 00:01:58,100\r\n现在 我们以为计算机科学就是介绍计算机的使用\r\nNow, the reason that we think computer science is about computers\r\n\r\n34\r\n00:01:58,120 --> 00:02:02,048\r\n就正如埃及人认为\r\nis pretty much the same reason that the Egyptians thought geometry\r\n\r\n35\r\n00:02:02,064 --> 00:02:03,650\r\n几何学是介绍如何使用测量仪器的\r\nwas about surveying instruments.\r\n\r\n36\r\n00:02:04,140 --> 00:02:06,928\r\n换句话说 任何一门学科起步的时候\r\nAnd that is, when some field is just getting started\r\n\r\n37\r\n00:02:06,940 --> 00:02:09,410\r\n你都对它了解不深\r\nand you don't really understand it very well,\r\n\r\n38\r\n00:02:10,656 --> 00:02:16,192\r\n这很容易使你混淆所做的事与所用之物\r\nit's very easy to confuse the essence of what you're doing with the tools that you use.\r\n\r\n39\r\n00:02:17,200 --> 00:02:19,856\r\n确实 就绝对规模来说\r\nAnd indeed, on some absolute scale of things,\r\n\r\n40\r\n00:02:19,856 --> 00:02:24,370\r\n我们对计算机科学的实质的了解\r\nwe probably know less about the essence of computer science\r\n\r\n41\r\n00:02:24,384 --> 00:02:27,040\r\n比埃及人对几何学的了解还少\r\nthan the ancient Egyptians really knew about geometry.\r\n\r\n42\r\n00:02:29,808 --> 00:02:32,192\r\n那么 我所谓的计算机科学的本质是什么呢\r\nWell, what do I mean by the essence of computer science?\r\n\r\n43\r\n00:02:32,208 --> 00:02:33,960\r\n我所谓的几何学本质又是什么呢\r\nWhat do I mean by the essence of geometry?\r\n\r\n44\r\n00:02:33,968 --> 00:02:36,000\r\n看 可以确认的是 古埃及人确实使用测量仪器\r\nSee, it's certainly true that these Egyptians went off\r\n\r\n45\r\n00:02:36,016 --> 00:02:37,220\r\n并且已经消失多年\r\nand used surveying instruments,\r\n\r\n46\r\n00:02:37,248 --> 00:02:41,104\r\n但当我们在几千年后回过头来重新审视这段历史\r\nbut when we look back on them after a couple of thousand years,\r\n\r\n47\r\n00:02:41,120 --> 00:02:41,408\r\n我们会说\r\nwe say,\r\n\r\n48\r\n00:02:41,424 --> 00:02:43,190\r\n天啊 看他们在做什么\r\ngee, what they were doing,\r\n\r\n49\r\n00:02:43,264 --> 00:02:45,030\r\n他们的工作是多么的重要\r\nthe important stuff they were doing,\r\n\r\n50\r\n00:02:45,170 --> 00:02:50,000\r\n已经开始对时间和空间进行形式化表述\r\nwas to begin to formalize notions about space and time,\r\n\r\n51\r\n00:02:51,136 --> 00:02:57,080\r\n并归纳出一套讨论数学真理的形式化方法\r\nto start a way of talking about mathematical truths formally.\r\n\r\n52\r\n00:02:57,568 --> 00:02:59,168\r\n这直接导致了公理化方法\r\nThat led to the axiomatic method.\r\n\r\n53\r\n00:02:59,168 --> 00:03:02,080\r\n以及各种现代数学的产生\r\nThat led to sort of all of modern mathematics,\r\n\r\n54\r\n00:03:03,712 --> 00:03:06,450\r\n同时也指明了一种精确讨论\r\nfiguring out a way to talk precisely about\r\n\r\n55\r\n00:03:06,800 --> 00:03:09,740\r\n所谓的描述真理的陈述性知识的方法\r\nso-called declarative knowledge, what is true.\r\n\r\n56\r\n00:03:12,000 --> 00:03:15,808\r\n与此相似的 我认为未来人们会回过头来审视并说\r\nWell, similarly, I think in the future people will look back and say,\r\n\r\n57\r\n00:03:15,824 --> 00:03:18,912\r\n啊 这些20世纪的原始人\r\nyes, those primitives in the 20th century were fiddling around\r\n\r\n58\r\n00:03:18,912 --> 00:03:20,750\r\n不务正业地玩弄着叫计算机的小玩意\r\nwith these gadgets called computers,\r\n\r\n59\r\n00:03:21,328 --> 00:03:25,800\r\n但它们真正在做的是开始学习\r\nbut really what they were doing is starting to learn\r\n\r\n60\r\n00:03:25,808 --> 00:03:32,100\r\n如何去对计算过程进行形式化表述\r\nhow to formalize intuitions about process,\r\n\r\n61\r\n00:03:32,192 --> 00:03:33,680\r\n如何去解决问题\r\nhow to do things,\r\n\r\n62\r\n00:03:38,576 --> 00:03:50,800\r\n并结合两者发展一套对问题处理过程精确表述的方法\r\nstarting to develop a way to talk precisely about how-to knowledge,\r\n\r\n63\r\n00:03:51,312 --> 00:03:55,580\r\n这与讨论真理的几何学形成了对照\r\nas opposed to geometry that talks about what is true.\r\n\r\n64\r\n00:03:56,080 --> 00:03:58,120\r\n让我给你们举个例子吧\r\nLet me give you an example of that.\r\n\r\n65\r\n00:04:01,856 --> 00:04:02,240\r\n来瞧瞧\r\nLet's take a look\r\n\r\n66\r\n00:04:02,256 --> 00:04:09,376\r\n数学中是这样来定义平方根的:\r\nHere is a piece of mathematics that says what a square root is.\r\n\r\n67\r\n00:04:09,648 --> 00:04:13,900\r\n定义X的平方根Y是这样一个数\r\nThe square root of X is the number Y,\r\n\r\n68\r\n00:04:15,536 --> 00:04:19,936\r\nY的平方等于X 且Y大于等于0\r\nsuch that Y squared is equal to X and Y is greater than 0.\r\n\r\n69\r\n00:04:19,984 --> 00:04:22,050\r\n这是一个很好的定义\r\nNow, that's a fine piece of mathematics,\r\n\r\n70\r\n00:04:22,432 --> 00:04:24,800\r\n但它只告诉了你平方根是什么\r\nbut just telling you what a square root is\r\n\r\n71\r\n00:04:25,184 --> 00:04:29,840\r\n却没有告诉你如何去求取一个平方根\r\ndoesn't really say anything about how you might go out and find one.\r\n\r\n72\r\n00:04:30,976 --> 00:04:35,456\r\n那么我们将其与一条指令性知识做比较\r\nSo let's contrast that with a piece of imperative knowledge,\r\n\r\n73\r\n00:04:36,688 --> 00:04:39,472\r\n你如何去求取一个平方根\r\nhow you might go out and find a square root.\r\n\r\n74\r\n00:04:39,504 --> 00:04:45,296\r\n事实上 这来自于埃及 不太久远的埃及\r\nThis, in fact, also comes from Egypt, not ancient, ancient Egypt.\r\n\r\n75\r\n00:04:45,310 --> 00:04:48,430\r\n亚历山大的Heron提出的一个算法\r\nThis is an algorithm due to Heron of Alexandria,\r\n\r\n76\r\n00:04:49,456 --> 00:04:52,320\r\n称作连续取均值求平方根法\r\ncalled how to find a square root by successive averaging.\r\n\r\n77\r\n00:04:52,448 --> 00:04:54,688\r\n这个算法是说\r\nAnd what it says is that,\r\n\r\n78\r\n00:04:54,704 --> 00:04:57,616\r\n为了算出平方根\r\nin order to find a square root,\r\n\r\n79\r\n00:05:02,896 --> 00:05:07,880\r\n首先你应该给出一个猜测值guess 并不断改进\r\nyou make a guess, you improve that guess --\r\n\r\n80\r\n00:05:09,744 --> 00:05:10,992\r\n改进的方法是通过\r\nand the way you improve the guess\r\n\r\n81\r\n00:05:11,008 --> 00:05:13,500\r\n不断求猜测值guess与X/guess的平均值\r\nis to average the guess and X over the guess,\r\n\r\n82\r\n00:05:13,968 --> 00:05:15,152\r\n我们稍后将会讨论\r\nand we'll talk a little bit later about\r\n\r\n83\r\n00:05:15,168 --> 00:05:16,670\r\n为什么这是合理的\r\nwhy that's a reasonable thing--\r\n\r\n84\r\n00:05:16,690 --> 00:05:18,920\r\n通过不断改进 直到它足够精确\r\nand you keep improving the guess until it's good enough.\r\n\r\n85\r\n00:05:19,280 --> 00:05:20,400\r\n这就是实现方法\r\nThat's a method.\r\n\r\n86\r\n00:05:20,540 --> 00:05:24,208\r\n这也是如何完成一项工作与\r\nThat's how to do something as opposed to\r\n\r\n87\r\n00:05:24,272 --> 00:05:26,880\r\n其对应的陈述性知识的对照\r\ndeclarative knowledge that says what you're looking for.\r\n\r\n88\r\n00:05:27,600 --> 00:05:29,310\r\n这就是一个过程\r\nThat's a process.\r\n\r\n89\r\n00:05:33,952 --> 00:05:37,808\r\n那么 通常来说什么是过程呢？\r\nWell, what's a process in general?\r\n\r\n90\r\n00:05:38,560 --> 00:05:39,690\r\n这定义起来非常困难\r\nIt's kind of hard to say.\r\n\r\n91\r\n00:05:39,712 --> 00:05:43,270\r\n你可以将它象征性地看成一个活在计算机内\r\nYou can think of it as like a magical spirit\r\n\r\n92\r\n00:05:44,320 --> 00:05:46,880\r\n并且可以完成一些操作的精灵\r\nthat sort of lives in the computer and does something.\r\n\r\n93\r\n00:05:47,568 --> 00:05:53,664\r\n一些被称为程序的规则模式\r\nAnd the thing that directs a process is\r\n\r\n94\r\n00:05:53,680 --> 00:05:57,530\r\n指导着这类过程的进行\r\na pattern of rules called a procedure.\r\n\r\n95\r\n00:06:01,536 --> 00:06:04,280\r\n程序可以被认为是符咒\r\nSo procedures are the spells, if you like,\r\n\r\n96\r\n00:06:04,784 --> 00:06:08,950\r\n使用程序来控制这些精灵完成一些操作就叫做过程\r\nthat control these magical spirits that are the processes.\r\n\r\n97\r\n00:06:10,304 --> 00:06:12,304\r\n你们知道人人都需要一门魔法语言\r\nI guess you know everyone needs a magical language,\r\n\r\n98\r\n00:06:12,320 --> 00:06:14,100\r\n那些魔术师 真正的魔术师 用远古的阿卡狄亚语\r\nand sorcerers, real sorcerers,\r\n\r\n99\r\n00:06:14,128 --> 00:06:18,140\r\n或者苏美尔语 或者巴比伦语 或者其它的\r\nuse ancient Arcadian or Sumerian or Babylonian or whatever.\r\n\r\n100\r\n00:06:18,176 --> 00:06:19,640\r\n而我们将用一门叫Lisp的魔法语言\r\nWe're going to conjure our spirits\r\n\r\n101\r\n00:06:19,680 --> 00:06:22,260\r\n来召唤出我们的精灵\r\nin a magical language called Lisp,\r\n\r\n102\r\n00:06:23,920 --> 00:06:27,568\r\n这门语言是被设计用来\r\nwhich is a language designed for talking about,\r\n\r\n103\r\n00:06:28,128 --> 00:06:31,390\r\n编写如咒语版的程序 来指导过程的进行\r\nfor casting the spells that are procedures to direct the processes.\r\n\r\n104\r\n00:06:31,424 --> 00:06:33,460\r\n学习Lisp非常容易\r\nNow, it's very easy to learn Lisp.\r\n\r\n105\r\n00:06:33,520 --> 00:06:35,536\r\n事实上 我会在几分钟内教会你\r\nIn fact, in a few minutes, I'm going to teach you,\r\n\r\n106\r\n00:06:35,552 --> 00:06:36,710\r\n整个Lisp\r\nessentially, all of Lisp.\r\n\r\n107\r\n00:06:36,926 --> 00:06:38,515\r\n及其所有的规则\r\nI'm going to teach you, essentially, all of the rules.\r\n\r\n108\r\n00:06:40,320 --> 00:06:43,200\r\n你不必感到很惊讶\r\nAnd you shouldn't find that particularly surprising.\r\n\r\n109\r\n00:06:43,240 --> 00:06:45,424\r\n这就像你在学习象棋时\r\nThat's sort of like saying it's very easy\r\n\r\n110\r\n00:06:45,456 --> 00:06:46,560\r\n认为象棋的规则十分简单一样\r\nto learn the rules of chess.\r\n\r\n111\r\n00:06:46,592 --> 00:06:47,680\r\n事实也如此 几分钟内\r\nAnd indeed, in a few minutes,\r\n\r\n112\r\n00:06:47,728 --> 00:06:49,250\r\n你可以与任何人谈论象棋的规则\r\nyou can tell somebody the rules of chess.\r\n\r\n113\r\n00:06:50,368 --> 00:06:51,792\r\n但是 这全然不等同于说\r\nBut of course, that's very different from\r\n\r\n114\r\n00:06:51,808 --> 00:06:54,928\r\n你所知道这些规则所蕴含的东西\r\nsaying you understand the implications of those rules\r\n\r\n115\r\n00:06:54,970 --> 00:06:57,600\r\n以及如何利用这些规则去成为象棋大师\r\nand how to use those rules to become a masterful chess player.\r\n\r\n116\r\n00:06:58,048 --> 00:06:59,370\r\nLisp也是如此\r\nWell, Lisp is the same way.\r\n\r\n117\r\n00:06:59,968 --> 00:07:01,730\r\n我将在几分钟内道清规则\r\nWe're going to state the rules in a few minutes,\r\n\r\n118\r\n00:07:01,910 --> 00:07:03,104\r\n这说起来非常容易\r\nand it'll be very easy to see.\r\n\r\n119\r\n00:07:03,170 --> 00:07:06,640\r\n但真正困难的是如何运用这些规则\r\nBut what's really hard is going to be the implications of those rules,\r\n\r\n120\r\n00:07:06,870 --> 00:07:10,010\r\n以及你如何利用这些规则成为编程大师\r\nhow you exploit those rules to be a master programmer.\r\n\r\n121\r\n00:07:11,610 --> 00:07:14,848\r\n这些规则的应用将占据我们\r\nAnd the implications of those rules are going to take us the,\r\n\r\n122\r\n00:07:14,860 --> 00:07:18,110\r\n余下的课程 甚至更多\r\nwell, the whole rest of the subject and, of course, way beyond.\r\n\r\n123\r\n00:07:21,008 --> 00:07:22,660\r\n所以 在计算机科学中\r\nOK, so in computer science,\r\n\r\n124\r\n00:07:24,048 --> 00:07:25,744\r\n我们的任务则是\r\nwe're in the business of\r\n\r\n125\r\n00:07:25,760 --> 00:07:30,130\r\n形式化这种如有关“怎么做”的指令性知识\r\nformalizing this sort of how-to imperative knowledge,\r\n\r\n126\r\n00:07:30,176 --> 00:07:31,650\r\n并将之付诸实际\r\nhow to do stuff.\r\n\r\n127\r\n00:07:32,928 --> 00:07:34,944\r\n这也便是计算机科学的真正的议题\r\nAnd the real issues of computer science are, of course,\r\n\r\n128\r\n00:07:34,960 --> 00:07:37,910\r\n当然 并不是告诉人们如何去求平方根\r\nnot telling people how to do square roots.\r\n\r\n129\r\n00:07:38,640 --> 00:07:39,616\r\n因为如果那是计算机科学的全部的的话\r\nBecause if that was all it was,\r\n\r\n130\r\n00:07:39,648 --> 00:07:40,896\r\n就不会有什么大问题了\r\nthere wouldn't be no big deal.\r\n\r\n131\r\n00:07:41,120 --> 00:07:43,600\r\n真正的问题来自于当我们尝试\r\nThe real problems come when we try to\r\n\r\n132\r\n00:07:43,632 --> 00:07:45,710\r\n构建非常非常大的系统时\r\nbuild very, very large systems,\r\n\r\n133\r\n00:07:46,160 --> 00:07:49,080\r\n程序可能会长达数千页\r\ncomputer programs that are thousands of pages long,\r\n\r\n134\r\n00:07:49,136 --> 00:07:53,536\r\n长得没有人能马上将其装入脑中\r\nso long that nobody can really hold them in their heads all at once.\r\n\r\n135\r\n00:07:54,288 --> 00:07:58,360\r\n而使这些得以实现则是因为\r\nAnd the only reason that that's possible is because\r\n\r\n136\r\n00:07:58,410 --> 00:08:18,528\r\n我们有在大系统中控制复杂度的技术\r\nthere are techniques for controlling the complexity of these large systems.\r\n\r\n137\r\n00:08:19,850 --> 00:08:22,240\r\n这些控制复杂度的技术\r\nAnd these techniques that are controlling complexity\r\n\r\n138\r\n00:08:22,272 --> 00:08:23,728\r\n正是我们课程所讨论的\r\nare what this course is really about.\r\n\r\n139\r\n00:08:24,208 --> 00:08:25,024\r\n从某种意义上来说\r\nAnd in some sense,\r\n\r\n140\r\n00:08:25,056 --> 00:08:27,020\r\n这也正是计算机科学的关键所在\r\nthat's really what computer science is about.\r\n\r\n141\r\n00:08:29,180 --> 00:08:31,440\r\n这样说听起来或许很奇怪\r\nNow, that may seem like a very strange thing to say.\r\n\r\n142\r\n00:08:31,472 --> 00:08:35,168\r\n毕竟 除了计算机科学家外\r\nBecause after all, a lot of people besides computer scientists\r\n\r\n143\r\n00:08:35,200 --> 00:08:37,370\r\n仍然有很多人在做复杂度控制相关的工作\r\ndeal with controlling complexity.\r\n\r\n144\r\n00:08:37,390 --> 00:08:40,570\r\n一个航班就是一个非常复杂的系统\r\nA large airliner is an extremely complex system,\r\n\r\n145\r\n00:08:41,376 --> 00:08:43,344\r\n设计它的航空工程师\r\nand the aeronautical engineers who design that\r\n\r\n146\r\n00:08:43,600 --> 00:08:45,680\r\n便在处理这个巨大的复杂度\r\nare dealing with immense complexity.\r\n\r\n147\r\n00:08:46,640 --> 00:08:49,740\r\n但这种复杂度又与\r\nBut there's a difference between that kind of complexity\r\n\r\n148\r\n00:08:50,304 --> 00:08:52,150\r\n计算机科学中的（复杂度）有别\r\nand what we deal with in computer science.\r\n\r\n149\r\n00:08:54,736 --> 00:08:57,280\r\n从某种意义上来说\r\nAnd that is that computer science,\r\n\r\n150\r\n00:08:57,344 --> 00:08:59,648\r\n因为计算机科学不是“现实”的\r\nin some sense, isn't real.\r\n\r\n151\r\n00:09:02,240 --> 00:09:06,170\r\n例如 当一名工程师设计物理系统时\r\nYou see, when an engineer is designing a physical system,\r\n\r\n152\r\n00:09:06,690 --> 00:09:08,040\r\n这些都是由实在的物理部件构成\r\nthat's made out of real parts.\r\n\r\n153\r\n00:09:08,950 --> 00:09:10,736\r\n负责的该工作的工程师\r\nThe engineers who worry about that\r\n\r\n154\r\n00:09:11,400 --> 00:09:16,208\r\n就得对付系统中的公差、近似值以及噪声\r\nhave to address problems of tolerance and approximation and noise in the system.\r\n\r\n155\r\n00:09:16,224 --> 00:09:18,576\r\n譬如说 作为一名电气工程师\r\nSo for example, as an electrical engineer,\r\n\r\n156\r\n00:09:18,640 --> 00:09:21,264\r\n可以很容易的做一个单极放大器\r\nI can go off and easily build a one-stage amplifier\r\n\r\n157\r\n00:09:21,280 --> 00:09:22,580\r\n或者是一个双极放大器\r\nor a two-stage amplifier,\r\n\r\n158\r\n00:09:22,960 --> 00:09:24,944\r\n也可想象将其大量串联\r\nand I can imagine cascading a lot of them\r\n\r\n159\r\n00:09:25,008 --> 00:09:26,464\r\n来建造一个百万极的放大器\r\nto build a million-stage amplifier.\r\n\r\n160\r\n00:09:26,540 --> 00:09:28,304\r\n但这样做是不可行的\r\nBut it's ridiculous to build such a thing,\r\n\r\n161\r\n00:09:28,530 --> 00:09:31,700\r\n因为在远没到百万数量级的时候\r\nbecause long before the millionth stage,\r\n\r\n162\r\n00:09:31,710 --> 00:09:34,112\r\n这种组合方法打从头产生的热噪声\r\nthe thermal noise in those components way at the beginning\r\n\r\n163\r\n00:09:34,120 --> 00:09:36,352\r\n会慢慢增强 并使得我们的幸苦付之一炬\r\nis going to get amplified and make the whole thing meaningless.\r\n\r\n164\r\n00:09:38,650 --> 00:09:42,670\r\n计算机科学处理的是理想化组件\r\nComputer science deals with idealized components.\r\n\r\n165\r\n00:09:43,670 --> 00:09:47,184\r\n我们对将要结合在一起的\r\nWe know as much as we want about these little program\r\n\r\n166\r\n00:09:47,200 --> 00:09:49,110\r\n程序和数据了如指掌\r\nand data pieces that we're fitting things together.\r\n\r\n167\r\n00:09:51,456 --> 00:09:52,752\r\n我们不需要去关心公差\r\nWe don't have to worry about tolerance.\r\n\r\n168\r\n00:09:52,760 --> 00:09:56,540\r\n也就是说 在构建大系统时\r\nAnd that means that, in building a large program,\r\n\r\n169\r\n00:09:57,680 --> 00:09:59,580\r\n在我理想和现实之间\r\nthere's not all that much difference\r\n\r\n170\r\n00:09:59,900 --> 00:10:03,730\r\n并不没有太大的不同\r\nbetween what I can build and what I can imagine,\r\n\r\n171\r\n00:10:05,088 --> 00:10:07,152\r\n因为这些部分都是抽象单元\r\nbecause the parts are these abstract entities\r\n\r\n172\r\n00:10:07,184 --> 00:10:09,872\r\n可以随心所欲的组合\r\nthat I know as much as I want.\r\n\r\n173\r\n00:10:09,888 --> 00:10:11,940\r\n可以据目前所知而自由构建\r\nI know about them as precisely as I'd like.\r\n\r\n174\r\n00:10:13,008 --> 00:10:15,050\r\n就是与其它的工程不同之处\r\nSo as opposed to other kinds of engineering,\r\n\r\n175\r\n00:10:15,210 --> 00:10:16,976\r\n（在其它的工程中）对你所构建系统的约束\r\nwhere the constraints on what you can build\r\n\r\n176\r\n00:10:16,990 --> 00:10:18,450\r\n来自于物理系统以及\r\nare the constraints of physical systems,\r\n\r\n177\r\n00:10:18,490 --> 00:10:20,576\r\n物理定律 噪声 近似值等\r\nthe constraints of physics and noise and approximation,\r\n\r\n178\r\n00:10:20,760 --> 00:10:25,152\r\n而建立大型软件系统时所施加的约束\r\nthe constraints imposed in building large software systems\r\n\r\n179\r\n00:10:25,190 --> 00:10:27,130\r\n就是对我们大脑的限制\r\nare the limitations of our own minds.\r\n\r\n180\r\n00:10:28,670 --> 00:10:29,536\r\n从这个角度来看\r\nSo in that sense,\r\n\r\n181\r\n00:10:29,550 --> 00:10:33,220\r\n计算机科学就像是工程中的一种抽象形式\r\ncomputer science is like an abstract form of engineering.\r\n\r\n182\r\n00:10:33,350 --> 00:10:35,280\r\n在这种工程中 我们忽略\r\nIt's the kind of engineering where you ignore\r\n\r\n183\r\n00:10:35,310 --> 00:10:37,570\r\n现实所施加的约束\r\nthe constraints that are imposed by reality.\r\n\r\n184\r\n00:10:41,520 --> 00:10:45,700\r\n那么 这其中有哪些技术呢\r\nWell, what are some of these techniques?\r\n\r\n185\r\n00:10:45,830 --> 00:10:47,940\r\n计算机科学中并没有特别的技术\r\nThey're not special to computer science.\r\n\r\n186\r\n00:10:49,940 --> 00:10:52,100\r\n第一个技术是在很多工程中都使用的\r\nFirst technique, which is used in all of engineering,\r\n\r\n187\r\n00:10:52,910 --> 00:10:58,464\r\n被称为“黑盒抽象”的方法\r\nis a kind of abstraction called black-box abstraction.\r\n\r\n188\r\n00:11:07,264 --> 00:11:12,130\r\n即将一些东西组合并封装起来\r\nTake something and build a box about it.\r\n\r\n189\r\n00:11:13,920 --> 00:11:19,648\r\n以之前我们提到的求取平方根的方法为例\r\nLet's see, for example, if we looked at that square root method,\r\n\r\n190\r\n00:11:22,190 --> 00:11:28,080\r\n我将这些操作视为一个“盒子”\r\nI might want to take that and build a box.\r\n\r\n191\r\n00:11:29,440 --> 00:11:37,072\r\n也就是说 为了找到X的平方根\r\nThat sort of says, to find the square root of X.\r\n\r\n192\r\n00:11:38,416 --> 00:11:40,820\r\n或许会有一系列的复杂规则\r\nAnd that might be a whole complicated set of rules.\r\n\r\n193\r\n00:11:42,192 --> 00:11:46,240\r\n我们将规则封装 输入数据即可获得结果\r\nAnd that might end up being a kind of thing where I can put in,\r\n\r\n194\r\n00:11:46,368 --> 00:11:49,610\r\n比如说 输入36 然后说36的平方根是多少呢\r\nsay, 36 and say, what's the square root of 36?\r\n\r\n195\r\n00:11:49,808 --> 00:11:51,010\r\n则给出结果 6\r\nAnd out comes 6.\r\n\r\n196\r\n00:11:53,440 --> 00:11:55,776\r\n重点是\r\nAnd the important thing is that\r\n\r\n197\r\n00:11:55,790 --> 00:11:59,584\r\n通过这样的设计\r\nI'd like to design that so that\r\n\r\n198\r\n00:11:59,612 --> 00:12:03,633\r\n可以方便他人的使用\r\nif George comes along and would like to compute,\r\n\r\n199\r\n00:12:04,656 --> 00:12:08,928\r\n例如Goerge想计算A的平方根加上B的平方根\r\nsay, the square root of A plus the square root of B,\r\n\r\n200\r\n00:12:10,896 --> 00:12:13,936\r\n他无需了解“盒子”内部的构成\r\nhe can take this thing and use it as a module\r\n\r\n201\r\n00:12:13,984 --> 00:12:15,296\r\n而直接可以以模块的形式使用它\r\nwithout having to look inside\r\n\r\n202\r\n00:12:15,328 --> 00:12:16,864\r\n也可以利用它去构建新的“盒子”\r\nand build something that looks like this,\r\n\r\n203\r\n00:12:18,000 --> 00:12:23,750\r\n例如构建一个 A和B以及一个平方根和或者另一个平方根盒子\r\nlike an A and a B and a square root box and another square root box\r\n\r\n204\r\n00:12:24,080 --> 00:12:33,420\r\n然后将这些结果加在一起并输出答案\r\nand then something that adds that would put out the answer.\r\n\r\n205\r\n00:12:33,510 --> 00:12:37,700\r\n如你所见 就我想实现的功能的层面来看\r\nAnd you can see, just from the fact that I want to do that,\r\n\r\n206\r\n00:12:38,470 --> 00:12:39,970\r\n对于George来说\r\nis from George's point of view,\r\n\r\n207\r\n00:12:40,060 --> 00:12:42,650\r\n盒子内部是什么样并不重要\r\nthe internals of what's in here should not be important.\r\n\r\n208\r\n00:12:43,740 --> 00:12:46,800\r\n例如 以下这些说法都没什么问题\r\nSo for instance, it shouldn't matter that, when I wrote this,\r\n\r\n209\r\n00:12:46,820 --> 00:12:49,984\r\n我说求X的平方根\r\nI said I want to find the square root of X.\r\n\r\n210\r\n00:12:50,160 --> 00:12:51,820\r\n也可以说计算Y的平方根\r\nI could have said the square root of Y,\r\n\r\n211\r\n00:12:52,272 --> 00:12:55,170\r\n或者其它任何数的平方根\r\nor the square root of A, or anything at all\r\n\r\n212\r\n00:12:56,256 --> 00:13:01,904\r\n黑盒抽象的基本规则是\r\nThat's the fundamental notion of putting something in a box\r\n\r\n213\r\n00:13:03,088 --> 00:13:05,990\r\n将处理过程放入盒子里以隐藏细节\r\nusing black-box abstraction to suppress detail.\r\n\r\n214\r\n00:13:07,152 --> 00:13:10,540\r\n这样做的原因则是你可以脱身去构建更大的盒子\r\nAnd the reason for that is you want to go off and build bigger boxes.\r\n\r\n215\r\n00:13:11,600 --> 00:13:14,128\r\n现在 除了隐藏细节外\r\nNow, there's another reason for doing black-box abstraction\r\n\r\n216\r\n00:13:14,140 --> 00:13:17,968\r\n使用黑盒抽象还有另外一个原因\r\nother than you want to suppress detail for building bigger boxes.\r\n\r\n217\r\n00:13:18,030 --> 00:13:24,576\r\n有的时候 你想要用你的方法去完成一件事\r\nSometimes you want to say that your way of doing something,\r\n\r\n218\r\n00:13:24,590 --> 00:13:26,430\r\n你的方法\r\nyour how-to method,\r\n\r\n219\r\n00:13:27,990 --> 00:13:30,340\r\n就是一个通法的具体实例\r\nis an instance of a more general thing,\r\n\r\n220\r\n00:13:30,710 --> 00:13:34,120\r\n同时 你也希望你的表述方式能够具有普遍性\r\nand you'd like your language to be able to express that generality.\r\n\r\n221\r\n00:13:35,120 --> 00:13:37,488\r\n我们接着用实例来说明\r\nLet me show you another example\r\n\r\n222\r\n00:13:37,520 --> 00:13:38,416\r\n继续刚才关于平方根的讨论\r\nsticking with square roots.\r\n\r\n223\r\n00:13:38,448 --> 00:13:41,712\r\n让我们回过头再来看看\r\nLet's go back and take another look at that slide\r\n\r\n224\r\n00:13:41,744 --> 00:13:43,300\r\n求平方根的算法\r\nwith the square root algorithm on it.\r\n\r\n225\r\n00:13:43,712 --> 00:13:45,170\r\n想一想之前是怎么说的\r\nRemember what that says.\r\n\r\n226\r\n00:13:45,344 --> 00:13:49,376\r\n为了求解 首先要作出猜测\r\nThat says, in order to do something, I make a guess,\r\n\r\n227\r\n00:13:50,176 --> 00:13:54,390\r\n然后基于这个猜测 做出持续不断的改进\r\nand I improve that guess, and I sort of keep improving that guess.\r\n\r\n228\r\n00:13:55,216 --> 00:13:59,690\r\n因此就存在一个找到某个到结果的通用方法\r\nSo there's the general strategy of, I'm looking for something,\r\n\r\n229\r\n00:14:00,704 --> 00:14:03,550\r\n就是持续不断地改进结果\r\nand the way I find it is that I keep improving it.\r\n\r\n230\r\n00:14:03,712 --> 00:14:09,800\r\n求取不动点的方法有很多\r\nNow, that's a particular case of another kind of strategy\r\n\r\n231\r\n00:14:10,528 --> 00:14:12,780\r\n这种方法只是其中的一个特例\r\nfor finding a fixed point of something.\r\n\r\n232\r\n00:14:14,128 --> 00:14:16,140\r\n每个函数都有一个不动点\r\nSo you have a fixed point of a function.\r\n\r\n233\r\n00:14:16,688 --> 00:14:25,580\r\n函数的不动点是一个值\r\nA fixed point of a function is something, is a value.\r\n\r\n234\r\n00:14:25,680 --> 00:14:31,340\r\nF的不动点Y满足F(Y)=Y\r\nA fixed point of a function F is a value Y, such that F of Y equals Y.\r\n\r\n235\r\n00:14:32,528 --> 00:14:40,448\r\n首先要做是做出一个猜测\r\nAnd the way I might do that is start with a guess.\r\n\r\n236\r\n00:14:41,552 --> 00:14:45,408\r\n在迭代函数F时不会改变的东西则是我们所求的结果\r\nAnd then if I want something that doesn't change when I keep applying F,\r\n\r\n237\r\n00:14:45,510 --> 00:14:49,008\r\n我会不断迭代函数F直到结果不会有很大改变\r\nis I'll keep applying F over and over until that result doesn't change very much.\r\n\r\n238\r\n00:14:49,600 --> 00:14:51,480\r\n这就是一个通法\r\nSo there's a general strategy.\r\n\r\n239\r\n00:14:51,792 --> 00:14:55,728\r\n因此 为了计算X的平方根\r\nAnd then, for example, to compute the square root of X,\r\n\r\n240\r\n00:14:55,792 --> 00:15:03,000\r\n我可以试着找到Y与X/Y的平均值函数的不动点\r\nI can try and find a fixed point of the function which takes Y to the average of X/Y.\r\n\r\n241\r\n00:15:03,104 --> 00:15:07,072\r\n因为如果我真有一个等于X平方根的Y\r\nAnd the idea that is that if I really had Y equal to the square root of X,\r\n\r\n242\r\n00:15:07,568 --> 00:15:11,350\r\n那么Y和X/Y应为同一值\r\nthen Y and X/Y would be the same value.\r\n\r\n243\r\n00:15:11,552 --> 00:15:13,450\r\n它们俩都是X的平方根\r\nThey'd both be the square root of X,\r\n\r\n244\r\n00:15:14,416 --> 00:15:18,400\r\n因为X除根号X得根号X\r\nbecause X over the square root of X is the square root of X.\r\n\r\n245\r\n00:15:18,640 --> 00:15:21,390\r\n如果平均值Y等于X的平方根\r\nAnd so the average if Y were equal to the square of X,\r\n\r\n246\r\n00:15:21,808 --> 00:15:24,760\r\n那么这个平均值就不会改变\r\nthen the average wouldn't change.\r\n\r\n247\r\n00:15:25,536 --> 00:15:28,480\r\n因此X的平方根即是某一特定函数的不动点\r\nSo the square root of X is a fixed point of that particular function.\r\n\r\n248\r\n00:15:29,648 --> 00:15:33,408\r\n现在 我将要描述\r\nNow, what I'd like to have, I'd like to express\r\n\r\n249\r\n00:15:33,536 --> 00:15:35,970\r\n寻找不动点的通法\r\nthe general strategy for finding fixed points.\r\n\r\n250\r\n00:15:36,128 --> 00:15:39,680\r\n我所希望做的就是\r\nSo what I might imagine doing, is to find,\r\n\r\n251\r\n00:15:40,576 --> 00:15:46,000\r\n用我自己的语言定义一个可以获得不动点的“盒子”\r\nis to be able to use my language to define a box that says \"fixed point,\"\r\n\r\n252\r\n00:15:49,136 --> 00:15:51,740\r\n正如我可以定义一个输出平方根的盒子一样\r\njust like I could make a box that says \"square root.\"\r\n\r\n253\r\n00:15:51,760 --> 00:15:54,736\r\n我想要用自己的语言来表述\r\nAnd I'd like to be able to express this in my language.\r\n\r\n254\r\n00:15:55,632 --> 00:16:00,928\r\n因此 对于这种“怎么做”的指令性知识\r\nSo I'd like to express not only the imperative how-to knowledge\r\n\r\n255\r\n00:16:00,976 --> 00:16:02,768\r\n我不仅是想表达具体应该如何求平方根\r\nof a particular thing like square root,\r\n\r\n256\r\n00:16:03,136 --> 00:16:05,152\r\n我也希望能够表述更加通用问题\r\nbut I'd like to be able to express the imperative knowledge\r\n\r\n257\r\n00:16:05,216 --> 00:16:07,820\r\n例如 怎么求取不动点\r\nof how to do a general thing like how to find fixed point.\r\n\r\n258\r\n00:16:09,376 --> 00:16:11,808\r\n让我们再回过头来看看之前的幻灯片\r\nAnd in fact, let's go back and look at that slide again.\r\n\r\n259\r\n00:16:14,576 --> 00:16:22,832\r\n不但如何去求取一个不动点\r\nSee, not only is this a piece of imperative knowledge,\r\n\r\n260\r\n00:16:22,880 --> 00:16:24,870\r\n是一种指令性知识\r\nhow to find a fixed point,\r\n\r\n261\r\n00:16:25,808 --> 00:16:26,944\r\n在这下面 这里\r\nbut over here on the bottom,\r\n\r\n262\r\n00:16:26,976 --> 00:16:29,870\r\n这儿还有另一种指令性知识 说的是\r\nthere's another piece of imperative knowledge which says,\r\n\r\n263\r\n00:16:29,968 --> 00:16:35,400\r\n计算平方根的一种方法就是应用找不动点的方法\r\none way to compute square root is to apply this general fixed point method.\r\n\r\n264\r\n00:16:35,728 --> 00:16:38,440\r\n如果 也想要表述这种指令性知识\r\nSo I'd like to also be able to express that imperative knowledge.\r\n\r\n265\r\n00:16:39,296 --> 00:16:40,256\r\n那结果会是什么样呢？\r\nWhat would that look like?\r\n\r\n266\r\n00:16:40,288 --> 00:16:44,450\r\n这个不动点盒子可能会是这样\r\nThat would say, this fixed point box is such that\r\n\r\n267\r\n00:16:45,310 --> 00:16:57,760\r\n如果我输入一个函数 该函数从Y映射到Y和X/Y的平均值\r\nif I input to it the function that takes Y to the average of Y and X/Y,\r\n\r\n268\r\n00:16:59,328 --> 00:17:05,780\r\n然后我们将会得到求不动点的盒子就是求平方根的一个方法\r\nthen what should come out of that fixed point box is a method for finding square roots.\r\n\r\n269\r\n00:17:08,464 --> 00:17:09,792\r\n因此在这些我们构建的盒子中\r\nSo in these boxes we're building,\r\n\r\n270\r\n00:17:09,824 --> 00:17:14,624\r\n输入和输出都不局限于数字\r\nwe're not only building boxes that you input numbers and output numbers,\r\n\r\n271\r\n00:17:15,952 --> 00:17:18,090\r\n我们将要构建能够\r\nwe're going to be building in boxes that,\r\n\r\n272\r\n00:17:18,220 --> 00:17:20,896\r\n找到平方根计算方法的盒子\r\nin effect, compute methods like finding square root.\r\n\r\n273\r\n00:17:21,776 --> 00:17:25,408\r\n我输入的是一个函数\r\nAnd my take is their inputs functions,\r\n\r\n274\r\n00:17:26,048 --> 00:17:28,840\r\n比如Y映射到Y和X/Y的平均值的函数\r\nlike Y goes to the average of Y and X/Y.\r\n\r\n275\r\n00:17:29,264 --> 00:17:31,040\r\n我们之所以采用这种方式是希望\r\nThe reason we want to do that,\r\n\r\n276\r\n00:17:31,760 --> 00:17:35,152\r\n输入是一个过程 输出也是一个过程\r\nthe reason this is a procedure, will end up being a procedure,\r\n\r\n277\r\n00:17:35,184 --> 00:17:38,160\r\n如我们所见 一个过程输出了另一个过程\r\nas we'll see, whose value is another procedure,\r\n\r\n278\r\n00:17:38,864 --> 00:17:40,650\r\n之所以这样做是因为\r\nthe reason we want to do that is because\r\n\r\n279\r\n00:17:41,072 --> 00:17:45,820\r\n我们将通过程序来讨论指令性知识\r\nprocedures are going to be our ways of talking about imperative knowledge.\r\n\r\n280\r\n00:17:47,552 --> 00:17:49,488\r\n这种处理方式很强大\r\nAnd the way to make that very powerful is\r\n\r\n281\r\n00:17:49,488 --> 00:17:51,680\r\n我们将可以基于此来讨论其它类型的知识\r\nto be able to talk about other kinds of knowledge.\r\n\r\n282\r\n00:17:52,976 --> 00:17:56,070\r\n实际上 我们讨论的是一种生成过程的过程\r\nSo here is a procedure that, in effect, talks about another procedure,\r\n\r\n283\r\n00:17:56,656 --> 00:17:59,890\r\n一种生成通法的通法\r\na general strategy that itself talks about general strategies.\r\n\r\n284\r\n00:18:03,120 --> 00:18:07,790\r\n那么 我们将主要讨论三个主题的内容\r\nWell, our first topic in this course--\r\n\r\n285\r\n00:18:07,808 --> 00:18:09,248\r\n而首个主题则是\r\nthere'll be three major topics--\r\n\r\n286\r\n00:18:09,296 --> 00:18:10,496\r\n黑盒抽象\r\nwill be black-box abstraction.\r\n\r\n287\r\n00:18:10,528 --> 00:18:12,864\r\n让我们稍稍深入一点\r\nLet's look at that in a little bit more detail.\r\n\r\n288\r\n00:18:14,672 --> 00:18:23,590\r\n我们将讨论\r\nWhat we're going to do is we will start out talking about\r\n\r\n289\r\n00:18:23,632 --> 00:18:26,270\r\nLisp是如何通过基本对象建立起来的\r\nhow Lisp is built up out of primitive objects.\r\n\r\n290\r\n00:18:26,912 --> 00:18:28,750\r\n以及Lisp的构成\r\nWhat does the language supply with us?\r\n\r\n291\r\n00:18:29,040 --> 00:18:33,136\r\n接下来 将会涉及到一些基本过程和基础数据\r\nAnd we'll see that there are primitive procedures and primitive data.\r\n\r\n292\r\n00:18:35,712 --> 00:18:36,592\r\n然后我们将会看到\r\nThen we're going to see,\r\n\r\n293\r\n00:18:36,608 --> 00:18:38,320\r\n我们如何使用这些基本对象\r\nhow do you take those primitives and\r\n\r\n294\r\n00:18:38,368 --> 00:18:40,310\r\n并把它们组合起来构建更复杂的东西\r\ncombine them to make more complicated things,\r\n\r\n295\r\n00:18:41,008 --> 00:18:42,470\r\n及相应的组合方法\r\nmeans of combination?\r\n\r\n296\r\n00:18:42,752 --> 00:18:45,850\r\n后续将讨论各种进行组合的方法以及\r\nAnd what we'll see is that there are ways of putting things together,\r\n\r\n297\r\n00:18:46,000 --> 00:18:50,032\r\n如何用基本过程来构建更复杂的过程\r\nputting primitive procedures together to make more complicated procedures.\r\n\r\n298\r\n00:18:50,512 --> 00:18:53,980\r\n同时 我们也将看到如何将基本数据组合成复合数据\r\nAnd we'll see how to put primitive data together to make compound data.\r\n\r\n299\r\n00:18:55,760 --> 00:18:58,896\r\n然后我们将会介绍如何对复合数据\r\nThen we'll say, well, having made those compounds things,\r\n\r\n300\r\n00:18:59,344 --> 00:19:00,848\r\n如何将它们抽象出来\r\nhow do you abstract them?\r\n\r\n301\r\n00:19:02,464 --> 00:19:04,528\r\n如何用黑盒对它们进行封装\r\nHow do you put those black boxes around them\r\n\r\n302\r\n00:19:04,592 --> 00:19:07,280\r\n使得你可以将它们作为组件用于更复杂的东西\r\nso you can use them as components in more complex things?\r\n\r\n303\r\n00:19:07,712 --> 00:19:10,480\r\n我们会发现这些都是通过定义程序\r\nAnd we'll see that's done by defining procedures and\r\n\r\n304\r\n00:19:11,072 --> 00:19:14,340\r\n以及一种处理复合数据的数据抽象技术完成的\r\na technique for dealing with compound data called data abstraction.\r\n\r\n305\r\n00:19:15,168 --> 00:19:16,910\r\n最重要的是\r\nAnd then, what's maybe the most important thing,\r\n\r\n306\r\n00:19:17,472 --> 00:19:21,040\r\n我们可以从中了解到专家是如何工作的\r\nis going from just the rules to how does an expert work?\r\n\r\n307\r\n00:19:21,168 --> 00:19:26,672\r\n对于找不动点的方法来讲\r\nHow do you express common patterns of doing things, like saying, well,\r\n\r\n308\r\n00:19:26,704 --> 00:19:28,192\r\n找平方根的方式是它的一个特例\r\nthere's a general method of fixed point and\r\n\r\n309\r\n00:19:28,240 --> 00:19:30,420\r\n你如何表述完成工作中所存在的通用模式呢？\r\nsquare root is a particular case of that?\r\n\r\n310\r\n00:19:31,456 --> 00:19:33,968\r\n我们将会使用\r\nAnd we're going to use--\r\n\r\n311\r\n00:19:34,144 --> 00:19:35,184\r\n之前已经提到过的\r\nI've already hinted at it--\r\n\r\n312\r\n00:19:35,216 --> 00:19:36,850\r\n某种叫做高阶过程的东西\r\nsomething called higher-order procedures,\r\n\r\n313\r\n00:19:36,896 --> 00:19:41,600\r\n也就是说 它的输入、输出和它本身都是过程\r\nnamely procedures whose inputs and outputs are themselves procedures.\r\n\r\n314\r\n00:19:42,512 --> 00:19:44,416\r\n我们将会看到一些有趣的东西\r\nAnd then we'll also see something very interesting.\r\n\r\n315\r\n00:19:44,416 --> 00:19:48,040\r\n随着学习的深入 将会越发抽象\r\nWe'll see, as we go further and further on and become more abstract,\r\n\r\n316\r\n00:19:48,352 --> 00:19:49,860\r\n那么将会发现\r\nthere'll be very--\r\n\r\n317\r\n00:19:49,980 --> 00:19:53,168\r\n我们认为是数据和我们认为是过程之间的\r\nwell, the line between what we consider to be data and\r\n\r\n318\r\n00:19:53,184 --> 00:19:57,350\r\n分界线将变得模糊到难以置信的程度\r\nwhat we consider to be procedures is going to blur at an incredible rate.\r\n\r\n319\r\n00:20:02,448 --> 00:20:06,670\r\n这便是我们的第一个主题 黑盒抽象\r\nWell, that's our first subject, black-box abstraction.\r\n\r\n320\r\n00:20:06,672 --> 00:20:08,170\r\n让我们来看看第二个主题\r\nLet's look at the second topic.\r\n\r\n321\r\n00:20:10,656 --> 00:20:13,430\r\n这样说吧\r\nI can introduce it like this.\r\n\r\n322\r\n00:20:13,440 --> 00:20:17,640\r\n假设我想表达某个想法\r\nSee, suppose I want to express the idea--\r\n\r\n323\r\n00:20:18,976 --> 00:20:22,064\r\n请注意 我们讨论的是想法\r\nremember, we're talking about ideas--\r\n\r\n324\r\n00:20:22,464 --> 00:20:25,088\r\n比如说\r\nsuppose I want to express the idea that\r\n\r\n325\r\n00:20:25,968 --> 00:20:34,672\r\n我想将某个元素与另两个元素之和相乘\r\nI can take something and multiply it by the sum of two other things.\r\n\r\n326\r\n00:20:35,648 --> 00:20:37,480\r\n举例来说\r\nSo for example, I might say,\r\n\r\n327\r\n00:20:37,664 --> 00:20:41,070\r\n我用1和3（之和）乘2 得8\r\nif I had 1 and 3 and multiply that by 2, I get 8.\r\n\r\n328\r\n00:20:41,584 --> 00:20:44,660\r\n但我这里想讨论的是关于线性组合的基本想法\r\nBut I'm talking about the general idea of what's called linear combination,\r\n\r\n329\r\n00:20:44,992 --> 00:20:47,530\r\n是说你可以将两个元素的和乘以另一个元素\r\nthat you can add two things and multiply them by something else.\r\n\r\n330\r\n00:20:48,832 --> 00:20:50,560\r\n在数集内思考这个问题是很容易的\r\nIt's very easy when I think about it for numbers,\r\n\r\n331\r\n00:20:50,608 --> 00:20:54,960\r\n但假设我想将这个想法应用于\r\nbut suppose I also want to use that same idea to think about,\r\n\r\n332\r\n00:20:55,632 --> 00:20:58,130\r\n对两向量a1和a2相加\r\nI could add two vectors, a1 and a2,\r\n\r\n333\r\n00:20:59,440 --> 00:21:02,816\r\n乘以某一因子x然后得到另一向量\r\nand then scale them by some factor x and get another vector.\r\n\r\n334\r\n00:21:02,880 --> 00:21:09,300\r\n我甚至可以说 若a1和a2皆为多项式\r\nOr I might say, I want to think about a1 and a2 as being polynomials,\r\n\r\n335\r\n00:21:10,620 --> 00:21:13,456\r\n我想对这两个多项式求和\r\nand I might want to add those two polynomials and\r\n\r\n336\r\n00:21:13,472 --> 00:21:16,416\r\n然后乘以2得到一个多项式\r\nthen multiply them by 2 to get a more complicated one.\r\n\r\n337\r\n00:21:19,710 --> 00:21:23,380\r\n同理 a1或a2也可以是电信号\r\nOr a1 and a2 might be electrical signals,\r\n\r\n338\r\n00:21:24,110 --> 00:21:27,328\r\n我想将二个信号加和\r\nand I might want to think about summing those two electrical signals and\r\n\r\n339\r\n00:21:27,360 --> 00:21:29,824\r\n并将结果放入一个放大器\r\nthen putting the whole thing through an amplifier,\r\n\r\n340\r\n00:21:29,824 --> 00:21:29,830\r\n用一个类似于2的因子乘以它们\r\nmultiplying it by some factor of 2 or something.\r\n并将结果放入一个放大器\r\nthen putting the whole thing through an amplifier,\r\n\r\n341\r\n00:21:29,830 --> 00:21:32,580\r\n用一个类似于2的因子乘以它们\r\nmultiplying it by some factor of 2 or something.\r\n\r\n342\r\n00:21:33,376 --> 00:21:36,480\r\n这种想法的基本点是 我希望用一个通用记号表示它们\r\nThe idea is I want to think about the general notion of that.\r\n\r\n343\r\n00:21:37,872 --> 00:21:44,976\r\n假如我们的语言可以很好的表述这类想法\r\nNow, if our language is going to be good language for expressing those kind of general ideas,\r\n\r\n344\r\n00:21:46,624 --> 00:21:48,864\r\n如果真可以这样的话\r\nif I really, really can do that,\r\n\r\n345\r\n00:21:50,208 --> 00:21:51,648\r\n我将会以这样的方式表述\r\nI'd like to be able to say\r\n\r\n346\r\n00:21:54,544 --> 00:21:59,960\r\n用x乘以a1和a2的和\r\nI'm going to multiply by x the sum of a1 and a2,\r\n\r\n347\r\n00:22:02,352 --> 00:22:04,624\r\n更进一步 我希望做更抽象更基本的表述\r\nand I'd like that to express the general idea of\r\n\r\n348\r\n00:22:05,584 --> 00:22:08,784\r\n使其可以适应各个不同类型的a1和a2\r\nall different kinds of things that a1 and a2 could be.\r\n\r\n349\r\n00:22:09,584 --> 00:22:11,136\r\n现在回过头来想想 似乎有点问题\r\nNow, if you think about that, there's a problem,\r\n\r\n350\r\n00:22:11,136 --> 00:22:15,728\r\n毕竟 对两个数字和两个多项式进行加和运算\r\nbecause after all, the actual primitive operations\r\n\r\n351\r\n00:22:15,760 --> 00:22:17,888\r\n所用的基本操作\r\nthat go on in the machine are obviously going to be different\r\n\r\n352\r\n00:22:17,936 --> 00:22:22,530\r\n在机器内部显然是不同的\r\nif I'm adding two numbers than if I'm adding two polynomials,\r\n\r\n353\r\n00:22:22,848 --> 00:22:27,040\r\n对两个电信号或声波加和也有同样的问题\r\nor if I'm adding the representation of two electrical signals or wave forms.\r\n\r\n354\r\n00:22:27,440 --> 00:22:32,080\r\n无论怎样 对不同类型的元素进行求和运算\r\nSomewhere, there has to be the knowledge of the kinds of various things\r\n\r\n355\r\n00:22:32,420 --> 00:22:33,808\r\n总是需要使用不同的方法\r\nthat you can add and the ways of adding them.\r\n\r\n356\r\n00:22:36,640 --> 00:22:38,192\r\n现在 为了构建这样一个系统\r\nNow, to construct such a system,\r\n\r\n357\r\n00:22:38,336 --> 00:22:40,224\r\n我们将如何使用这些知识呢？\r\nthe question is, where do I put that knowledge?\r\n\r\n358\r\n00:22:40,752 --> 00:22:43,968\r\n如何在各种方法中进行选择？\r\nHow do I think about the different kinds of choices I have?\r\n\r\n359\r\n00:22:44,112 --> 00:22:47,970\r\n而如果明天George又想出了一种新类型的对象\r\nAnd if tomorrow George comes up with a new kind of object\r\n\r\n360\r\n00:22:48,000 --> 00:22:49,872\r\n并将它用于加和以及乘积\r\nthat might be added and multiplied,\r\n\r\n361\r\n00:22:50,560 --> 00:22:52,870\r\n我又该如何把这个新类型引入到系统中\r\nhow do I add George's new object to the system\r\n\r\n362\r\n00:22:53,072 --> 00:22:55,230\r\n而且能够做到不把已有的系统弄得一团糟？\r\nwithout screwing up everything that was already there?\r\n\r\n363\r\n00:22:57,360 --> 00:23:00,096\r\n这便是我们的第二大主题\r\nWell, that's going to be the second big topic,\r\n\r\n364\r\n00:23:00,128 --> 00:23:02,710\r\n控制复杂度的方法\r\nthe way of controlling that kind of complexity.\r\n\r\n365\r\n00:23:03,392 --> 00:23:07,980\r\n我们实现的方法是按照约定来实现相应的接口\r\nAnd the way you do that is by establishing conventional interfaces,\r\n\r\n366\r\n00:23:16,992 --> 00:23:19,760\r\n并以此将各部分组合起来\r\nagreed upon ways of plugging things together.\r\n\r\n367\r\n00:23:19,808 --> 00:23:21,590\r\n就如同电气工程中\r\nJust like in electrical engineering,\r\n\r\n368\r\n00:23:22,496 --> 00:23:24,944\r\n人们为连接器规定标准阻抗\r\npeople have standard impedances for connectors,\r\n\r\n369\r\n00:23:25,712 --> 00:23:28,176\r\n如果用符合这个标准的东西来构建系统\r\nand then you know if you build something with one of those standard impedances,\r\n\r\n370\r\n00:23:28,224 --> 00:23:29,952\r\n你就知道你可以把各个部件组合在一起\r\nyou can plug it together with something else.\r\n\r\n371\r\n00:23:32,336 --> 00:23:35,230\r\n这就是我们将要讨论的第二个主题：约定接口\r\nSo that's going to be our second large topic, conventional interfaces.\r\n\r\n372\r\n00:23:35,280 --> 00:23:40,496\r\n如我之前提到的\r\nWhat we're going to see is, first, we're going to talk about the problem of generic operations,\r\n\r\n373\r\n00:23:40,528 --> 00:23:41,776\r\n接下来我们将讨论通用操作中的问题\r\nwhich is the one I alluded to,\r\n\r\n374\r\n00:23:42,144 --> 00:23:46,832\r\n例如对各种不同类型数据进行均适用的加法操作\r\nthings like \"plus\" that have to work with all different kinds of data.\r\n\r\n375\r\n00:23:52,160 --> 00:23:54,128\r\n随后则会讨论通用操作\r\nSo we talk about generic operations.\r\n\r\n376\r\n00:23:54,160 --> 00:23:56,544\r\n然后我们将讨论大型架构问题\r\nThen we're going to talk about really large-scale structures.\r\n\r\n377\r\n00:23:57,872 --> 00:24:00,380\r\n如果通过对现实世界的复杂系统建模\r\nHow do you put together very large programs\r\n\r\n378\r\n00:24:00,576 --> 00:24:04,440\r\n来构建大型程序\r\nthat model the kinds of complex systems in the real world that you'd like to model?\r\n\r\n379\r\n00:24:05,088 --> 00:24:06,080\r\n我们将看到 在构建这样的系统时\r\nAnd what we're going to see is that\r\n\r\n380\r\n00:24:06,128 --> 00:24:11,360\r\n有两种非常重要的方法\r\nthere are two very important metaphors for putting together such systems.\r\n\r\n381\r\n00:24:11,408 --> 00:24:13,456\r\n其一是面向对象编程\r\nOne is called object-oriented programming,\r\n\r\n382\r\n00:24:13,648 --> 00:24:18,496\r\n在这种模式中 你把你的系统想象成一个社区\r\nwhere you sort of think of your system as a kind of society\r\n\r\n383\r\n00:24:18,928 --> 00:24:21,910\r\n社区中的各个部分都是通过相互间传递消息联系起来的\r\nfull of little things that interact by sending information between them.\r\n\r\n384\r\n00:24:22,992 --> 00:24:27,360\r\n其二是关于聚集的操作 称作“流”\r\nAnd then the second one is operations on aggregates, called streams,\r\n\r\n385\r\n00:24:27,536 --> 00:24:31,056\r\n使用这种方式构建大型系统\r\nwhere you think of a large system put together kind of\r\n\r\n386\r\n00:24:31,056 --> 00:24:34,840\r\n类似于电气工程师构造大型电气系统\r\nlike a signal processing engineer puts together a large electrical system.\r\n\r\n387\r\n00:24:38,480 --> 00:24:40,048\r\n这就是我们的第二个话题\r\nThat's going to be our second topic.\r\n\r\n388\r\n00:24:42,928 --> 00:24:45,488\r\n现在 我们将要讨论第三个话题\r\nNow, the third thing we're going to come to,\r\n\r\n389\r\n00:24:45,504 --> 00:24:49,250\r\n控制复杂度的第三个技术\r\nthe third basic technique for controlling complexity,\r\n\r\n390\r\n00:24:49,296 --> 00:24:50,496\r\n便是定义新的语言\r\nis making new languages.\r\n\r\n391\r\n00:24:51,248 --> 00:24:54,976\r\n因为有时 当你有点受不了设计的复杂度时\r\nBecause sometimes, when you're sort of overwhelmed by the complexity of a design,\r\n\r\n392\r\n00:24:55,024 --> 00:24:59,240\r\n你可以通过定义一门新的语言来控制系统复杂度\r\nthe way that you control that complexity is to pick a new design language.\r\n\r\n393\r\n00:25:00,960 --> 00:25:05,152\r\n新语言的设计意图是为了强调系统的某个方面\r\nAnd the purpose of the new design language will be to highlight different aspects of the system.\r\n\r\n394\r\n00:25:05,344 --> 00:25:08,912\r\n它一方面隐藏了部分细节 另一方面则但强调一些其他的细节\r\nIt will suppress some kinds of details and emphasize other kinds of details.\r\n\r\n395\r\n00:25:12,544 --> 00:25:15,488\r\n这部分将是课程中最神奇的部分\r\nThis is going to be the most magical part of the course.\r\n\r\n396\r\n00:25:15,584 --> 00:25:20,750\r\n我们将开始于构建新的计算机语言\r\nWe're going to start out by actually looking at the technology for building new computer languages.\r\n\r\n397\r\n00:25:21,376 --> 00:25:25,850\r\n实际上我们首先要完成的工作已经内建于Lisp之中了\r\nThe first thing we're going to do is actually build in Lisp.\r\n\r\n398\r\n00:25:28,784 --> 00:25:33,570\r\n我们将展现如何用Lisp来解释Lisp\r\nWe're going to express in Lisp the process of interpreting Lisp itself.\r\n\r\n399\r\n00:25:33,840 --> 00:25:36,496\r\n这是一个非常类似于自循环的过程\r\nAnd that's going to be a very sort of self-circular thing.\r\n\r\n400\r\n00:25:36,510 --> 00:25:39,472\r\n这与（Lisp中）一个神奇的符号有关\r\nThere's a little mystical symbol that has to do with that.\r\n\r\n401\r\n00:25:40,528 --> 00:25:45,936\r\n解释Lisp的步骤是\r\nThe process of interpreting Lisp is sort of a giant wheel of two processes,\r\n\r\n402\r\n00:25:46,128 --> 00:25:47,264\r\n应用和求值——这两大步骤的轮转\r\napply and eval,\r\n\r\n403\r\n00:25:47,440 --> 00:25:50,420\r\n这两者不断地互相交替进行\r\nwhich sort of constantly reduce expressions to each other.\r\n\r\n404\r\n00:25:52,096 --> 00:25:53,792\r\n接下来 我们将看到其余神奇的东西\r\nThen we're going to see all sorts of other magical things.\r\n\r\n405\r\n00:25:53,808 --> 00:25:56,400\r\n譬如另一种魔法符号\r\nHere's another magical symbol.\r\n\r\n406\r\n00:25:56,672 --> 00:26:01,070\r\n一种叫做Y运算符的东西\r\nThis is sort of the Y operator,\r\n\r\n407\r\n00:26:01,100 --> 00:26:06,000\r\n某种意义上 它在过程式语言中用于 表达无限\r\nwhich is, in some sense, the expression of infinity inside our procedural language.\r\n\r\n408\r\n00:26:06,064 --> 00:26:06,992\r\n我们也会谈论到它\r\nWe'll take a look at that.\r\n\r\n409\r\n00:26:07,952 --> 00:26:13,280\r\n总之 这部分课程被称作“元语言抽象”\r\nIn any case, this section of the course is called Metalinguistic Abstraction,\r\n\r\n410\r\n00:26:15,728 --> 00:26:25,780\r\n主要讨论如何构建一门新语言\r\nabstracting by talking about how you construct new languages.\r\n\r\n411\r\n00:26:29,776 --> 00:26:35,264\r\n如我所言 我们将从了解解释的过程开始\r\nAs I said, we're going to start out by looking at the process of interpretation.\r\n\r\n412\r\n00:26:35,296 --> 00:26:41,670\r\n随后则一起讨论应用-求值循环和构建Lisp\r\nWe're going to look at this apply-eval loop, and build Lisp.\r\n\r\n413\r\n00:26:41,712 --> 00:26:43,720\r\n你将发现这种方法具有相当的普遍性\r\nThen, just to show you that this is very general,\r\n\r\n414\r\n00:26:43,920 --> 00:26:47,810\r\n我们将用同样的技术去构建一门全完不同的语言\r\nwe're going to use exactly the same technology to build a very different kind of language,\r\n\r\n415\r\n00:26:48,080 --> 00:26:49,860\r\n一种所谓的逻辑编程语言\r\na so-called logic programming language,\r\n\r\n416\r\n00:26:50,080 --> 00:26:54,380\r\n一种无关具有输入和输出的过程\r\nwhere you don't really talk about procedures at all that have inputs and outputs.\r\n\r\n417\r\n00:26:54,416 --> 00:26:56,800\r\n而仅关注元素之间关系的语言\r\nWhat you do is talk about relations between things.\r\n\r\n418\r\n00:26:56,864 --> 00:27:03,470\r\n最终 我们将讨论如何将这些东西\r\nAnd then finally, we're going to talk about how you implement these things very concretely\r\n\r\n419\r\n00:27:03,504 --> 00:27:05,152\r\n实实在在的实现在简单的机器上\r\non the very simplest kind of machines.\r\n\r\n420\r\n00:27:05,200 --> 00:27:07,940\r\n比如说这个\r\nWe'll see something like this.\r\n\r\n421\r\n00:27:08,688 --> 00:27:11,690\r\n如图所示的芯片\r\nThis is a picture of a chip,\r\n\r\n422\r\n00:27:11,712 --> 00:27:17,024\r\n就是我们在硬件部分谈及的Lisp解释器\r\nwhich is the Lisp interpreter that we will be talking about then in hardware.\r\n\r\n423\r\n00:27:20,432 --> 00:27:23,340\r\n这三大主题就是本课的提纲\r\nWell, there's an outline of the course, three big topics.\r\n\r\n424\r\n00:27:24,432 --> 00:27:28,960\r\n黑盒抽象 约定接口 元语言抽象\r\nBlack-box abstraction, conventional interfaces, metalinguistic abstraction.\r\n\r\n425\r\n00:27:31,136 --> 00:27:33,120\r\n好 先休息一会儿 然后正式开始\r\nNow, let's take a break now and then we'll get started.\r\n\r\n426\r\n00:27:51,744 --> 00:28:02,976\r\n[音乐]\r\n[JESU, JOY OF MAN'S DESIRING]\r\n\r\n427\r\n00:28:03,472 --> 00:28:06,390\r\n现在让我们正式开始学习Lisp\r\nLet's actually start in learning Lisp now.\r\n\r\n428\r\n00:28:07,616 --> 00:28:10,304\r\n事实上 我们将开始学习一些非常重要的内容\r\nActually, we'll start out by learning something much more important,\r\n\r\n429\r\n00:28:10,352 --> 00:28:13,888\r\n在这门课程中最重要的 不是Lisp本身\r\nmaybe the very most important thing in this course, which is not Lisp,\r\n\r\n430\r\n00:28:13,936 --> 00:28:17,960\r\n而是一种的通用框架体系\r\nin particular, of course, but rather a general framework\r\n\r\n431\r\n00:28:18,176 --> 00:28:21,440\r\n我们用它来组织我之前提到的语言\r\nfor thinking about languages that I already alluded to.\r\n\r\n432\r\n00:28:21,671 --> 00:28:24,650\r\n当有人要向你展示一门新语言\r\nWhen somebody tells you they're going to show you a language,\r\n\r\n433\r\n00:28:24,688 --> 00:28:25,712\r\n你应该问他\r\nwhat you should say is,\r\n\r\n434\r\n00:28:25,744 --> 00:28:32,420\r\n（构成语言的）基本元素有哪些？\r\nwhat I'd like you to tell me is what are the primitive elements?\r\n\r\n435\r\n00:28:37,056 --> 00:28:38,330\r\n这门语言使用哪些基本元素？\r\nWhat does the language come with?\r\n\r\n436\r\n00:28:38,512 --> 00:28:43,088\r\n你是如何将这些元素组合在一起的？\r\nThen, what are the ways you put those together?\r\n\r\n437\r\n00:28:43,232 --> 00:28:46,976\r\n组合的方法是什么？\r\nWhat are the means of combination?\r\n\r\n438\r\n00:28:49,728 --> 00:28:53,730\r\n允许你将这些基本元素整合在一起\r\nWhat are the things that allow you to take these primitive elements\r\n\r\n439\r\n00:28:53,920 --> 00:28:56,064\r\n以构建更大的对象的又是什么？\r\nand build bigger things out of them?\r\n\r\n440\r\n00:28:57,568 --> 00:28:59,168\r\n把东西构建在一起的方法是什么？\r\nWhat are the ways of putting things together?\r\n\r\n441\r\n00:29:00,944 --> 00:29:05,248\r\n以及 抽象的方法是什么？\r\nAnd then, what are the means of abstraction?\r\n\r\n442\r\n00:29:07,904 --> 00:29:16,400\r\n我们如何利用这些元素并把它们封装成盒子？\r\nHow do we take those complicated things and draw those boxes around them?\r\n\r\n443\r\n00:29:16,432 --> 00:29:19,216\r\n我们如何为它们命名使得我们可以\r\nHow do we name them so that we can now use them\r\n\r\n444\r\n00:29:19,232 --> 00:29:23,408\r\n把它们当作基本元素来用于构建更复杂的东西？\r\nas if they were primitive elements in making still more complex things?\r\n\r\n445\r\n00:29:23,440 --> 00:29:25,216\r\n等等 等等 等等\r\nAnd so on, and so on, and so on.\r\n\r\n446\r\n00:29:26,448 --> 00:29:27,632\r\n因此 当有人告诉你\r\nSo when someone says to you, gee,\r\n\r\n447\r\n00:29:27,648 --> 00:29:29,104\r\n嘿 我发明了一种新的计算机语言\r\nI have a great new computer language,\r\n\r\n448\r\n00:29:30,416 --> 00:29:34,256\r\n你不应该问 用你的语言编写求逆矩阵需要多少代码\r\nyou don't say, how many characters does it take to invert a matrix?\r\n\r\n449\r\n00:29:35,280 --> 00:29:36,432\r\n这是风马牛不相及的\r\nIt's irrelevant.\r\n\r\n450\r\n00:29:36,944 --> 00:29:41,850\r\n如果该语言没有内建了矩阵或者类似的东西\r\nWhat you say is, if the language did not come with matrices built in\r\n\r\n451\r\n00:29:41,888 --> 00:29:42,928\r\n那你就应该问他\r\nor with something else built in,\r\n\r\n452\r\n00:29:42,928 --> 00:29:45,584\r\n应该如何构建矩阵？\r\nhow could I then build that thing?\r\n\r\n453\r\n00:29:45,600 --> 00:29:48,020\r\n如何通过组合来构建？\r\nWhat are the means of combination which would allow me to do that?\r\n\r\n454\r\n00:29:48,176 --> 00:29:50,260\r\n如何对其进行抽象\r\nAnd then, what are the means of abstraction\r\n\r\n455\r\n00:29:51,232 --> 00:29:53,760\r\n把它作为基本元素\r\nwhich allow me then to use those as elements\r\n\r\n456\r\n00:29:53,776 --> 00:29:56,070\r\n来构建更复杂的东西？\r\nin making more complicated things yet?\r\n\r\n457\r\n00:29:58,304 --> 00:30:04,160\r\n我们将了解到Lisp的一些基本数据和基本过程\r\nWell, we're going to see that Lisp has some primitive data and some primitive procedures.\r\n\r\n458\r\n00:30:04,800 --> 00:30:07,056\r\n好吧 这次是真的开始了\r\nIn fact, let's really start.\r\n\r\n459\r\n00:30:07,104 --> 00:30:14,448\r\n这里有一个Lisp的基本数据 数字3\r\nAnd here's a piece of primitive data in Lisp, number 3.\r\n\r\n460\r\n00:30:15,824 --> 00:30:19,420\r\n事实上 如果打破沙锅问到底的话 这不是数字3\r\nActually, if I'm being very pedantic, that's not the number 3.\r\n\r\n461\r\n00:30:19,488 --> 00:30:25,120\r\n这只是一个符号 用以代表柏拉图观念下的数字3的\r\nThat's some symbol that represents Plato's concept of the number 3.\r\n\r\n462\r\n00:30:26,224 --> 00:30:28,480\r\n这又是另一个\r\nAnd here's another.\r\n\r\n463\r\n00:30:30,032 --> 00:30:35,616\r\n这个是Lisp中又一个基本数据 17.4\r\nHere's some more primitive data in Lisp, 17.4.\r\n\r\n464\r\n00:30:35,632 --> 00:30:38,976\r\n又或者说 代表17.4\r\nOr actually, some representation of 17.4.\r\n\r\n465\r\n00:30:40,544 --> 00:30:44,032\r\n这儿还有一个5\r\nAnd here's another one, 5.\r\n\r\n466\r\n00:30:46,416 --> 00:30:51,760\r\n然后这儿又有一个内建于Lisp的基本对象“+”\r\nHere's another primitive object that's built in Lisp, addition.\r\n\r\n467\r\n00:30:51,808 --> 00:30:55,232\r\n如果又要继续深究的话\r\nActually, to use the same kind of pedantic--\r\n\r\n468\r\n00:30:55,264 --> 00:31:00,020\r\n这只是一个名字 代表对元素进行加和的基本方法而已\r\nthis is a name for the primitive method of adding things.\r\n\r\n469\r\n00:31:00,080 --> 00:31:02,080\r\n就像这个是柏拉图式的3\r\nJust like this is a name for Plato's number 3,\r\n\r\n470\r\n00:31:02,160 --> 00:31:08,870\r\n这也只是一个代表柏拉图观念下的将某些元素加和起来\r\nthis is a name for Plato's concept of how you add things.\r\n\r\n471\r\n00:31:09,872 --> 00:31:11,530\r\n这些都是基本元素\r\nSo those are some primitive elements.\r\n\r\n472\r\n00:31:11,696 --> 00:31:13,310\r\n我可以将它们放在一起\r\nI can put them together.\r\n\r\n473\r\n00:31:13,696 --> 00:31:17,840\r\n我可以说 3加17.4加5的和是多少\r\nI can say, gee, what's the sum of 3 and 17.4 and 5?\r\n\r\n474\r\n00:31:18,240 --> 00:31:20,864\r\n这等同于说\r\nAnd the way I do that is to say,\r\n\r\n475\r\n00:31:20,880 --> 00:31:27,264\r\n让我们把求和运算符应用于这三个数\r\nlet's apply the sum operator to these three numbers.\r\n\r\n476\r\n00:31:27,296 --> 00:31:30,700\r\n我可以得到什么呢 是8 是17 还是25.4\r\nAnd I should get, what? 8, 17. 25.4.\r\n\r\n477\r\n00:31:33,984 --> 00:31:37,600\r\n因此 我可以问Lisp这个的值是多少\r\nSo I should be able to ask Lisp what the value of this is,\r\n\r\n478\r\n00:31:38,496 --> 00:31:40,320\r\n（表达式）返回25.4\r\nand it will return 25.4.\r\n\r\n479\r\n00:31:43,136 --> 00:31:44,384\r\n介绍一些术语吧\r\nLet's introduce some names.\r\n\r\n480\r\n00:31:44,432 --> 00:31:51,024\r\n我所写的这些东西就叫做组合式\r\nThis thing that I typed is called a combination.\r\n\r\n481\r\n00:31:56,432 --> 00:32:01,490\r\n通常 一个组合式是由运算符\r\nAnd a combination consists, in general, of applying an operator--\r\n\r\n482\r\n00:32:02,944 --> 00:32:04,272\r\n这些就是运算符\r\nso this is an operator--\r\n\r\n483\r\n00:32:09,264 --> 00:32:11,600\r\n和应用该运算符的运算对象组成\r\nto some operands.\r\n\r\n484\r\n00:32:12,800 --> 00:32:14,096\r\n这些是运算对象\r\nThese are the operands.\r\n\r\n485\r\n00:32:21,440 --> 00:32:23,340\r\n当然 我可以完成更复杂的事\r\nAnd of course, I can make more complex things.\r\n\r\n486\r\n00:32:23,376 --> 00:32:28,110\r\n我可以使之更复杂是因为 这些运算对象\r\nThe reason I can get complexity out of this is because the operands themselves,\r\n\r\n487\r\n00:32:29,072 --> 00:32:30,640\r\n通常来说 也可以是组合式\r\nin general, can be combinations.\r\n\r\n488\r\n00:32:30,704 --> 00:32:44,020\r\n比如 3加上5乘以6乘以8乘以2的积的和是多少\r\nSo for instance, I could say, what is the sum of 3 and the product of 5 and 6 and 8 and 2?\r\n\r\n489\r\n00:32:45,216 --> 00:32:51,712\r\n而我应该得到 我算一下 30 40 43\r\nAnd I should get-- let's see-- 30, 40, 43.\r\n\r\n490\r\n00:32:52,288 --> 00:32:54,368\r\n因此Lisp会返回这个表达式的值是43\r\nSo Lisp should tell me that that's 43.\r\n\r\n491\r\n00:32:56,112 --> 00:33:02,352\r\n后续我们将看到构造组合式是组合的基本需求\r\nForming combinations is the basic needs of combination that we'll be looking at.\r\n\r\n492\r\n00:33:04,208 --> 00:33:08,770\r\n你所看到的这些语法\r\nAnd then, well, you see some syntax here.\r\n\r\n493\r\n00:33:10,112 --> 00:33:12,592\r\n就是Lisp用的所谓的前缀表示法\r\nLisp uses what's called prefix notation,\r\n\r\n494\r\n00:33:15,776 --> 00:33:24,760\r\n意即操作符在操作数的左端\r\nwhich means that the operator is written to the left of the operands.\r\n\r\n495\r\n00:33:25,024 --> 00:33:26,032\r\n这只是个约定\r\nIt's just a convention.\r\n\r\n496\r\n00:33:27,216 --> 00:33:29,320\r\n注意 这些都被括起来了\r\nAnd notice, it's fully parenthesized.\r\n\r\n497\r\n00:33:29,632 --> 00:33:31,872\r\n这些括号使得它们区别开来\r\nAnd the parentheses make it completely unambiguous.\r\n\r\n498\r\n00:33:31,872 --> 00:33:36,544\r\n因此只要看看这个 我就可以知道这个是运算符\r\nSo by looking at this, I can see that there's the operator,\r\n\r\n499\r\n00:33:36,560 --> 00:33:40,540\r\n以及这有1个 2个 3个 4个运算对象\r\nand there are 1, 2, 3, 4 operands.\r\n\r\n500\r\n00:33:41,936 --> 00:33:47,520\r\n而且我也可以发现第二个运算对象是个组合式\r\nAnd I can see that the second operand here is itself some combination\r\n\r\n501\r\n00:33:48,432 --> 00:33:51,100\r\n该组合式有一个运算符和两个运算对象\r\nthat has one operator and two operands.\r\n\r\n502\r\n00:33:51,984 --> 00:33:53,824\r\nLisp中的括号 有点或者非常不同于\r\nParentheses in Lisp are a little bit,\r\n\r\n503\r\n00:33:54,160 --> 00:33:57,260\r\n通常数学中的括号\r\nor are very unlike parentheses in conventional mathematics.\r\n\r\n504\r\n00:33:57,328 --> 00:33:59,664\r\n数学中 我们常将其用于分组\r\nIn mathematics, we sort of use them to mean grouping,\r\n\r\n505\r\n00:34:00,768 --> 00:34:03,300\r\n如果有时你忘了闭合括号 但其他人能理解你的意图\r\nand it sort of doesn't hurt if sometimes you leave out parentheses\r\n\r\n506\r\n00:34:03,328 --> 00:34:05,110\r\n这也无关紧要\r\nif people understand that that's a group.\r\n\r\n507\r\n00:34:05,312 --> 00:34:08,064\r\n通常的 你多加了括号也无所谓\r\nAnd in general, it doesn't hurt if you put in extra parentheses,\r\n\r\n508\r\n00:34:08,416 --> 00:34:10,496\r\n因为这样只会使得分组更加明确\r\nbecause that maybe makes the grouping more distinct.\r\n\r\n509\r\n00:34:10,512 --> 00:34:11,328\r\nLisp可不像这样\r\nLisp is not like that.\r\n\r\n510\r\n00:34:12,672 --> 00:34:14,928\r\nLisp中你既不能不闭合括号\r\nIn Lisp, you cannot leave out parentheses,\r\n\r\n511\r\n00:34:15,936 --> 00:34:18,112\r\n亦不能添加多余的括号\r\nand you cannot put in extra parentheses,\r\n\r\n512\r\n00:34:18,880 --> 00:34:20,832\r\n因为加括号总是意味着\r\nbecause putting in parentheses always means,\r\n\r\n513\r\n00:34:20,928 --> 00:34:26,600\r\n确切的来说 所括之物是一个组合式\r\nexactly and precisely, this is a combination which has meaning,\r\n\r\n514\r\n00:34:26,640 --> 00:34:28,368\r\n表示将运算符应用于运算对象\r\napplying operators to operands.\r\n\r\n515\r\n00:34:28,592 --> 00:34:32,176\r\n如果我不闭合这个括号\r\nAnd if I left this out, if I left those parentheses out,\r\n\r\n516\r\n00:34:32,208 --> 00:34:33,510\r\n这个就变成其它的意思了\r\nit would mean something else.\r\n\r\n517\r\n00:34:34,960 --> 00:34:36,800\r\n事实上 我们可以这么来理解这个问题\r\nIn fact, the way to think about this,\r\n\r\n518\r\n00:34:36,960 --> 00:34:41,200\r\n把我写的这些东西想作一个树\r\nis really what I'm doing when I write something like this is writing a tree.\r\n\r\n519\r\n00:34:41,920 --> 00:34:46,850\r\n这个组合式实际上是一个树 树具有一个“+”\r\nSo this combination is a tree that has a plus and\r\n\r\n520\r\n00:34:46,928 --> 00:34:54,016\r\n以及 一个3和一些其它的东西和一个8 还有一个2\r\nthen a 3 and then a something else and an 8 and a 2.\r\n\r\n521\r\n00:34:54,032 --> 00:34:55,904\r\n而这里的其它的东西\r\nAnd then this something else here is\r\n\r\n522\r\n00:34:55,904 --> 00:35:02,770\r\n它本身是一个有一个“*”一个5和一个6的子树\r\nitself a little subtree that has a star and a 5 and a 6.\r\n\r\n523\r\n00:35:03,504 --> 00:35:05,088\r\n我们可以这样认为\r\nAnd the way to think of that is, really,\r\n\r\n524\r\n00:35:05,104 --> 00:35:08,550\r\n我们只是在构建这些树而已\r\nwhat's going on are we're writing these trees,\r\n\r\n525\r\n00:35:08,768 --> 00:35:14,656\r\n括号只是将这种二维结构写作线性字符串\r\nand parentheses are just a way to write this two-dimensional structure\r\n\r\n526\r\n00:35:15,344 --> 00:35:16,896\r\n的一种方法罢了\r\nas a linear character string.\r\n\r\n527\r\n00:35:18,784 --> 00:35:23,360\r\n因为至少在Lisp发明时 人们还在用电传打字机或者打孔卡\r\nBecause at least when Lisp first started and people had teletypes or punch cards or whatever,\r\n\r\n528\r\n00:35:23,728 --> 00:35:25,150\r\n这种记法方便多了\r\nthis was more convenient.\r\n\r\n529\r\n00:35:25,520 --> 00:35:30,070\r\n如果Lisp是在当下被发明的 语法可能会像树那样\r\nMaybe if Lisp started today, the syntax of Lisp would look like that.\r\n\r\n530\r\n00:35:31,312 --> 00:35:34,620\r\n那么 让我们看看在计算机里面它究竟是什么样\r\nWell, let's look at what that actually looks like on the computer.\r\n\r\n531\r\n00:35:35,840 --> 00:35:38,928\r\n这里有个Lisp解释套件\r\nHere I have a Lisp interaction set up.\r\n\r\n532\r\n00:35:38,960 --> 00:35:39,984\r\n这是个编辑器\r\nThere's a editor.\r\n\r\n533\r\n00:35:40,688 --> 00:35:44,410\r\n我将要在上方写一些表达式并让Lisp对其求值\r\nAnd on the top, I'm going to type some values and ask Lisp what they are.\r\n\r\n534\r\n00:35:44,672 --> 00:35:46,300\r\n比如 我可以问Lisp\r\nSo for instance, I can say to Lisp,\r\n\r\n535\r\n00:35:46,384 --> 00:35:48,080\r\n这个符号的值是多少\r\nwhat's the value of that symbol?\r\n\r\n536\r\n00:35:48,992 --> 00:35:50,050\r\n我键入3\r\nThat's 3.\r\n\r\n537\r\n00:35:50,128 --> 00:35:51,750\r\n然后叫Lisp对其求值\r\nAnd I ask Lisp to evaluate it.\r\n\r\n538\r\n00:35:51,872 --> 00:35:54,320\r\n然后你就会看到Lisp在下面返回了一些信息\r\nAnd there you see Lisp has returned on the bottom,\r\n\r\n539\r\n00:35:54,944 --> 00:35:56,390\r\n这个值就是3\r\nand said, oh yeah, that's 3.\r\n\r\n540\r\n00:35:57,136 --> 00:36:04,510\r\n我也可以问 3加上4加上8的和是多少\r\nOr I can say, what's the sum of 3 and 4 and 8?\r\n\r\n541\r\n00:36:06,000 --> 00:36:07,600\r\n键入这个组合式\r\nWhat's that combination?\r\n\r\n542\r\n00:36:08,480 --> 00:36:10,210\r\n让Lisp对其求值\r\nAnd ask Lisp to evaluate it.\r\n\r\n543\r\n00:36:14,048 --> 00:36:15,232\r\n返回15\r\nThat's 15.\r\n\r\n544\r\n00:36:16,128 --> 00:36:18,352\r\n我可以键入一些更复杂的东西\r\nOr I can type in something more complicated.\r\n\r\n545\r\n00:36:18,800 --> 00:36:33,690\r\n将3乘以7加19.5的和的乘积求和得多少\r\nI can say, what's the sum of the product of 3 and the sum of 7 and 19.5?\r\n\r\n546\r\n00:36:34,768 --> 00:36:37,552\r\n你会发现Lisp内建了一些功能\r\nAnd you'll notice here that Lisp has something built in\r\n\r\n547\r\n00:36:37,568 --> 00:36:39,312\r\n帮你跟踪这些括号\r\nthat helps me keep track of all these parentheses.\r\n\r\n548\r\n00:36:39,328 --> 00:36:41,680\r\n看我键入下一个右圆括号\r\nWatch as I type the next closed parentheses,\r\n\r\n549\r\n00:36:41,760 --> 00:36:44,560\r\n用于闭合以“*”开头的那个组合式\r\nwhich is going to close the combination starting with the star.\r\n\r\n550\r\n00:36:45,072 --> 00:36:46,850\r\n开头的那个左括号会闪一下\r\nThe opening one will flash.\r\n\r\n551\r\n00:36:47,312 --> 00:36:49,240\r\n我把这些括号擦去 再示范一次\r\nHere, I'll rub those out and do it again.\r\n\r\n552\r\n00:36:49,696 --> 00:36:52,250\r\n键入右括号 闭合了“+”组合式\r\nType close, and you see that closes the plus.\r\n\r\n553\r\n00:36:53,136 --> 00:36:55,968\r\n再键入右括号 闭合了“*”组合式\r\nClose again, that closes the star.\r\n\r\n554\r\n00:36:57,456 --> 00:37:00,310\r\n现在我又回到了加 我将它们与4相加\r\nNow I'm back to the sum, and maybe I'm going to add that all to 4.\r\n\r\n555\r\n00:37:01,216 --> 00:37:02,240\r\n闭合了“+”组合式\r\nThat closes the plus.\r\n\r\n556\r\n00:37:02,288 --> 00:37:06,624\r\n现在我补全了组合式 然后我问Lisp它们的值是多少\r\nNow I have a complete combination, and I can ask Lisp for the value of that.\r\n\r\n557\r\n00:37:06,816 --> 00:37:11,216\r\n这种内建于各种Lisp系统的\r\nThat kind of paren balancing is something that's built into\r\n\r\n558\r\n00:37:11,312 --> 00:37:12,840\r\n括号匹配工具帮你跟进（括号匹配）\r\na lot of Lisp systems to help you keep track,\r\n\r\n559\r\n00:37:12,912 --> 00:37:16,100\r\n因为手工闭合这些括号太辛苦了\r\nbecause it is kind of hard just by hand doing all these parentheses.\r\n\r\n560\r\n00:37:16,368 --> 00:37:20,752\r\n这又是另外一种保持括号跟进的约定\r\nThere's another kind of convention for keeping track of parentheses.\r\n\r\n561\r\n00:37:20,800 --> 00:37:23,232\r\n我另外写一个复杂的组合式\r\nLet me write another complicated combination.\r\n\r\n562\r\n00:37:24,320 --> 00:37:33,552\r\n将3和5的积与某个元素求和\r\nLet's take the sum of the product of 3 and 5 and add that to something.\r\n\r\n563\r\n00:37:33,584 --> 00:37:34,784\r\n现在我将要缩进\r\nAnd now what I'm going to do is\r\n\r\n564\r\n00:37:34,832 --> 00:37:39,408\r\n使得这些运算对象都是垂直书写的\r\nI'm going to indent so that the operands are written vertically.\r\n\r\n565\r\n00:37:39,856 --> 00:37:45,200\r\n将这些加上47乘以\r\nWhich the sum of that and the product of 47 and--\r\n\r\n566\r\n00:37:46,576 --> 00:37:54,144\r\n恩…… 47乘以20和6.8的差\r\nlet's say the product of 47 with a difference of 20 and 6.8.\r\n\r\n567\r\n00:37:54,176 --> 00:37:56,640\r\n意即从20中减去6.8\r\nThat means subtract 6.8 from 20.\r\n\r\n568\r\n00:37:58,528 --> 00:37:59,744\r\n然后 这个括号闭合了\r\nAnd then you see the parentheses close.\r\n\r\n569\r\n00:37:59,776 --> 00:38:03,020\r\n闭合“-” 闭合“*”\r\nClose the minus. Close the star.\r\n\r\n570\r\n00:38:03,312 --> 00:38:04,976\r\n现在 我们再写一个运算符\r\nAnd now let's get another operator.\r\n\r\n571\r\n00:38:04,992 --> 00:38:09,040\r\nLisp编辑器自动缩进到正确的位置\r\nYou see the Lisp editor here is indenting to the right position automatically\r\n\r\n572\r\n00:38:09,952 --> 00:38:11,056\r\n来帮助我保持跟进\r\nto help me keep track.\r\n\r\n573\r\n00:38:12,160 --> 00:38:13,648\r\n我再示范一次\r\nI'll do that again.\r\n\r\n574\r\n00:38:13,680 --> 00:38:15,440\r\n这样就又闭合了最后一个括号\r\nI'll close that last parentheses again.\r\n\r\n575\r\n00:38:15,808 --> 00:38:17,260\r\n它匹配了这个“+”（的括号）\r\nYou see it balances the plus.\r\n\r\n576\r\n00:38:19,952 --> 00:38:22,190\r\n现在我想问 这个的值是多少\r\nNow I can say, what's the value of that?\r\n\r\n577\r\n00:38:23,424 --> 00:38:28,832\r\n因此 这两件事 缩进到正确的位置\r\nSo those two things, indenting to the right level,\r\n\r\n578\r\n00:38:28,864 --> 00:38:30,410\r\n也就是所谓的美观的输出\r\nwhich is called pretty printing,\r\n\r\n579\r\n00:38:31,104 --> 00:38:33,136\r\n以及闭合提示\r\nand flashing parentheses,\r\n\r\n580\r\n00:38:33,440 --> 00:38:37,280\r\n是许多Lisp系统所内建用于帮你保持跟进的工具\r\nare two things that a lot of Lisp systems have built in to help you keep track.\r\n\r\n581\r\n00:38:37,312 --> 00:38:38,560\r\n你应该学习如何使用它们\r\nAnd you should learn how to use them.\r\n\r\n582\r\n00:38:41,072 --> 00:38:42,720\r\n好 这些都是基本的内容\r\nOk, those are the primitives.\r\n\r\n583\r\n00:38:44,288 --> 00:38:45,860\r\n这就是一种组合的方法\r\nThere's a means of combination.\r\n\r\n584\r\n00:38:45,888 --> 00:38:47,488\r\n现在让我们来看看抽象的方法\r\nNow let's go up to the means of abstraction.\r\n\r\n585\r\n00:38:48,992 --> 00:38:53,390\r\n我希望我能够写一些像这样的组合式\r\nI'd like to be able to take the idea that I do some combination like this,\r\n\r\n586\r\n00:38:53,408 --> 00:38:55,320\r\n将它抽象化并给它命名\r\nand abstract it and give it a simple name,\r\n\r\n587\r\n00:38:55,360 --> 00:38:56,810\r\n使得我可以将其作为一个（我们语言的）元素\r\nso I can use that as an element.\r\n\r\n588\r\n00:38:56,864 --> 00:38:59,472\r\n在Lisp中 我可以用“define”来实现\r\nAnd I do that in Lisp with \"define.\"\r\n\r\n589\r\n00:39:00,720 --> 00:39:01,980\r\n比如说\r\nSo I can say, for example,\r\n\r\n590\r\n00:39:02,288 --> 00:39:14,608\r\n定义A为5乘以5\r\ndefine A to be the product of 5 and 5.\r\n\r\n591\r\n00:39:17,952 --> 00:39:21,904\r\n现在我可以问Lisp\r\nAnd now I could say, for example, to Lisp,\r\n\r\n592\r\n00:39:21,936 --> 00:39:25,568\r\nA和A的乘积是多少\r\nwhat is the product of A and A?\r\n\r\n593\r\n00:39:26,736 --> 00:39:29,360\r\n这个是25所以这个就是625\r\nAnd this should be 25, and this should be 625.\r\n\r\n594\r\n00:39:31,520 --> 00:39:35,560\r\n但更重要的则是 我现在可以使用A\r\nAnd then, crucial thing, I can now use A--\r\n\r\n595\r\n00:39:35,760 --> 00:39:37,470\r\n我已经在这个组合式里面用过了\r\nhere I've used it in a combination--\r\n\r\n596\r\n00:39:37,968 --> 00:39:43,104\r\n但我也可以在更复杂的组合式里面使用它\r\nbut I could use that in other more complicated things that I name in turn.\r\n\r\n597\r\n00:39:43,136 --> 00:39:50,480\r\n我也可以说 定义B为\r\nSo I could say, define B to be the sum of,\r\n\r\n598\r\n00:39:50,528 --> 00:39:57,008\r\nA与5乘以A的积的和\r\nwe'll say, A and the product of 5 and A.\r\n\r\n599\r\n00:39:58,992 --> 00:40:00,272\r\n闭合“+”\r\nAnd then close the plus.\r\n\r\n600\r\n00:40:03,008 --> 00:40:05,408\r\n让我们来看看它在计算机中是怎样的吧\r\nLet's take a look at that on the computer and see how that looks.\r\n\r\n601\r\n00:40:06,832 --> 00:40:10,230\r\n我就像黑板上写的那样键入就可以了\r\nSo I'll just type what I wrote on the board.\r\n\r\n602\r\n00:40:10,384 --> 00:40:21,280\r\n我告诉Lisp\r\nI could say, define A to be the product of 5 and 5.\r\n\r\n603\r\n00:40:23,296 --> 00:40:24,930\r\n定义A为5乘以5的积\r\nAnd I'll tell that to Lisp.\r\n\r\n604\r\n00:40:25,072 --> 00:40:28,490\r\n注意Lisp在下方回应了一个A\r\nAnd notice what Lisp responded there with was an A in the bottom.\r\n\r\n605\r\n00:40:28,640 --> 00:40:30,930\r\n通常来说 你如果在Lisp中键入了一个定义\r\nIn general, when you type in a definition in Lisp,\r\n\r\n606\r\n00:40:31,056 --> 00:40:34,570\r\n它返回被定义的符号\r\nit responds with the symbol being defined.\r\n\r\n607\r\n00:40:35,184 --> 00:40:39,216\r\n现在我问Lisp A乘以A的积是多少\r\nNow I could say to Lisp, what is the product of A and A?\r\n\r\n608\r\n00:40:42,368 --> 00:40:43,888\r\nLisp返回625\r\nAnd it says that's 625.\r\n\r\n609\r\n00:40:45,600 --> 00:40:59,890\r\n我也可以定义B为A加上5乘以A的积的和\r\nI can define B to be the sum of A and the product of 5 and A.\r\n\r\n610\r\n00:41:00,032 --> 00:41:05,250\r\n闭合“*” 闭合“+” 闭合“define”\r\nClose a paren closes the star.  Close the plus. Close the \"define.\"\r\n\r\n611\r\n00:41:07,184 --> 00:41:09,920\r\nLisp在下方正常返回B\r\nLisp says, OK, B, there on the bottom.\r\n\r\n612\r\n00:41:10,592 --> 00:41:12,790\r\n现在我可以问Lisp B的值是多少\r\nAnd now I can say to Lisp, what's the value of B?\r\n\r\n613\r\n00:41:16,736 --> 00:41:18,432\r\n我也可以问一些更复杂的事\r\nAnd I can say something more complicated,\r\n\r\n614\r\n00:41:18,480 --> 00:41:26,240\r\n比如A加上B除以5的商的和是多少\r\nlike what's the sum of A and the quotient of B and 5?\r\n\r\n615\r\n00:41:26,288 --> 00:41:29,808\r\n这个“/”是另一个基本运算符 代表除\r\nThat slash is divide, another primitive operator.\r\n\r\n616\r\n00:41:29,936 --> 00:41:32,330\r\n我让B除以5 并加在A上\r\nI've divided B by 5, added it to A.\r\n\r\n617\r\n00:41:33,200 --> 00:41:34,784\r\nLisp正常返回55\r\nLisp says, OK, that's 55.\r\n\r\n618\r\n00:41:36,120 --> 00:41:37,472\r\n就像这样\r\nSo there's what it looks like.\r\n\r\n619\r\n00:41:39,376 --> 00:41:42,950\r\n这是定义东西的基本方法\r\nThere's the basic means of defining something.\r\n\r\n620\r\n00:41:42,992 --> 00:41:48,570\r\n这是最简单的命名方法 但并不是很强大\r\nIt's the simplest kind of naming, but it's not really very powerful.\r\n\r\n621\r\n00:41:49,616 --> 00:41:51,152\r\n注意我们讨论的是通用方法\r\nSee, what I'd really like to name--\r\n\r\n622\r\n00:41:51,392 --> 00:41:52,928\r\n因此我真正想定义的是\r\nremember, we're talking about general methods--\r\n\r\n623\r\n00:41:53,120 --> 00:41:57,232\r\n一种通用方法 可以\r\nI'd like to name, oh, the general idea that, for example,\r\n\r\n624\r\n00:41:57,664 --> 00:42:17,088\r\n得到 5乘5 6乘6 1001乘1001 1001.7乘1001.7\r\nI could multiply 5 by 5, or 6 by 6, or 1,001 by 1,001, 1,001.7 by 1,001.7.\r\n\r\n625\r\n00:42:17,312 --> 00:42:23,712\r\n我想给一个数与其自身相乘这种想法一个名字\r\nI'd like to be able to name the general idea of multiplying something by itself.\r\n\r\n626\r\n00:42:28,032 --> 00:42:29,664\r\n你应该知道 这叫做平方\r\nWell, you know what that is. That's called squaring.\r\n\r\n627\r\n00:42:31,248 --> 00:42:35,184\r\n而在Lisp中我应该这样实现\r\nAnd the way I can do that in Lisp is I can say,\r\n\r\n628\r\n00:42:37,520 --> 00:42:55,808\r\n定义 square某个叫x的东西 为 将x乘以x自己\r\ndefine to square something x, multiply x by itself.\r\n\r\n629\r\n00:42:57,424 --> 00:43:00,672\r\n定义完毕后 我可以问Lisp\r\nAnd then having done that, I could say to Lisp,\r\n\r\n630\r\n00:43:00,672 --> 00:43:05,040\r\n比如 10的平方是多少\r\nfor example, what's the square of 10?\r\n\r\n631\r\n00:43:06,224 --> 00:43:07,424\r\nLisp返回100\r\nAnd Lisp will say 100.\r\n\r\n632\r\n00:43:10,256 --> 00:43:13,790\r\n让我们深入讨论一下\r\nSo now let's actually look at that a little more closely.\r\n\r\n633\r\n00:43:14,848 --> 00:43:16,430\r\n这儿是square的定义\r\nRight, there's the definition of square.\r\n\r\n634\r\n00:43:17,056 --> 00:43:22,100\r\nsquare某个元素 即是将该元素进行自乘\r\nTo square something, multiply it by itself.\r\n\r\n635\r\n00:43:23,248 --> 00:43:24,896\r\n这里的x\r\nYou see this x here.\r\n\r\n636\r\n00:43:25,840 --> 00:43:27,360\r\n应该算是一种代词\r\nThat x is kind of a pronoun,\r\n\r\n637\r\n00:43:27,424 --> 00:43:29,080\r\n指代了我要做平方的元素\r\nwhich is the something that I'm going to square.\r\n\r\n638\r\n00:43:31,040 --> 00:43:36,960\r\n实际上我将其乘以x 即是乘以它自己\r\nAnd what I do with it is I multiply x, I multiply it by itself.\r\n\r\n639\r\n00:43:41,776 --> 00:43:47,820\r\n这些就是定义一个过程的记法\r\nOK. So there's the notation for defining a procedure.\r\n\r\n640\r\n00:43:47,840 --> 00:43:49,840\r\n这样说可能把你搞糊涂了\r\nActually, this is a little bit confusing,\r\n\r\n641\r\n00:43:50,368 --> 00:43:53,520\r\n因为这就像我在用square一样\r\nbecause this is sort of how I might use square.\r\n\r\n642\r\n00:43:53,552 --> 00:43:56,352\r\n但如果我说x的平方根或者10的平方根\r\nAnd I say square root of x or square root of 10,\r\n\r\n643\r\n00:43:57,104 --> 00:44:00,360\r\n并没有说清楚我对什么做了定义\r\nbut it's not making it very clear that I'm actually naming something.\r\n\r\n644\r\n00:44:02,656 --> 00:44:04,464\r\n所以让我换个方式来进行定义\r\nSo let me write this definition in another way\r\n\r\n645\r\n00:44:05,296 --> 00:44:07,760\r\n这样可以清楚的看到定义的具体内容\r\nthat makes it a little bit more clear that I'm naming something.\r\n\r\n646\r\n00:44:08,096 --> 00:44:28,944\r\n我定义“square”为“(lambda (x) (* x x))”\r\nI'll say, \"define\" square to be lambda of x times xx.\r\n\r\n647\r\n00:44:36,112 --> 00:44:41,600\r\n这里 我定义square就像我某命名为A一样\r\nHere, I'm naming something square, just like over here, I'm naming something A.\r\n\r\n648\r\n00:44:42,784 --> 00:44:44,272\r\n我定义square\r\nThe thing that I'm naming square--\r\n\r\n649\r\n00:44:44,304 --> 00:44:47,940\r\n这里 我把这个组合式的值命名为A\r\nhere, the thing I named A was the value of this combination.\r\n\r\n650\r\n00:44:48,848 --> 00:44:51,968\r\n在这里 我把这个东西命名为square\r\nHere, the thing that I'm naming square is this thing\r\n\r\n651\r\n00:44:51,984 --> 00:44:52,992\r\n以lambda开头\r\nthat begins with lambda,\r\n\r\n652\r\n00:44:53,008 --> 00:44:56,320\r\nlambda在Lisp中用以构建一个过程\r\nand lambda is Lisp's way of saying make a procedure.\r\n\r\n653\r\n00:44:59,792 --> 00:45:02,464\r\n请仔细看一下幻灯片上的内容\r\nLet's look at that more closely on the slide.\r\n\r\n654\r\n00:45:03,820 --> 00:45:05,360\r\n这个定义读作\r\nThe way I read that definition is to say,\r\n\r\n655\r\n00:45:05,408 --> 00:45:09,880\r\n将square定义为\r\nI define square to be make a procedure--\r\n\r\n656\r\n00:45:12,336 --> 00:45:13,520\r\n一个由lambda构造的\r\nthat's what the lambda is--\r\n\r\n657\r\n00:45:13,616 --> 00:45:17,040\r\n一个有带有参数x的过程\r\nmake a procedure with an argument named x.\r\n\r\n658\r\n00:45:18,816 --> 00:45:23,648\r\n而该过程返回将x自乘的结果\r\nAnd what it does is return the results of multiplying x by itself.\r\n\r\n659\r\n00:45:24,528 --> 00:45:32,672\r\n一般来讲 这是最佳的定义方式\r\nNow, in general, we're going to be using this top form of defining,\r\n\r\n660\r\n00:45:32,960 --> 00:45:34,752\r\n因为这个更加方便一点\r\njust because it's a little bit more convenient.\r\n\r\n661\r\n00:45:34,752 --> 00:45:34,768\r\n但是也别忘了它实质上也是这个\r\nBut don't lose sight of the fact that it's really this.\r\n因为这个更加方便一点\r\njust because it's a little bit more convenient.\r\n\r\n662\r\n00:45:34,768 --> 00:45:38,224\r\n但是也别忘了它实质上也是这个\r\nBut don't lose sight of the fact that it's really this.\r\n\r\n663\r\n00:45:38,416 --> 00:45:40,960\r\n事实上 就Lisp解释器而言\r\nIn fact, as far as the Lisp interpreter's concerned,\r\n\r\n664\r\n00:45:41,168 --> 00:45:45,104\r\n这两种方法没有区别\r\nthere's no difference between typing this to it and typing this to it.\r\n\r\n665\r\n00:45:46,064 --> 00:45:52,848\r\n换句话说 这只是一种语法糖\r\nAnd there's a word for that, sort of syntactic sugar.\r\n\r\n666\r\n00:45:53,968 --> 00:45:55,350\r\n语法糖的意思就是\r\nWhat syntactic sugar means,\r\n\r\n667\r\n00:45:55,904 --> 00:46:00,384\r\n这种形式输入更方便一些\r\nit's having somewhat more convenient surface forms for typing something.\r\n\r\n668\r\n00:46:00,672 --> 00:46:05,664\r\n这只是这下面的有lambda的表达式的语法糖而已\r\nSo this is just really syntactic sugar for this underlying Greek thing with the lambda.\r\n\r\n669\r\n00:46:06,864 --> 00:46:10,176\r\n你应该记住\r\nAnd the reason you should remember that is don't forget that,\r\n\r\n670\r\n00:46:10,352 --> 00:46:13,420\r\n当我这样写的时候 其实是在对某个东西进行命名\r\nwhen I write something like this, I'm really naming something.\r\n\r\n671\r\n00:46:14,016 --> 00:46:15,776\r\n我将其命名为square\r\nI'm naming something square,\r\n\r\n672\r\n00:46:15,792 --> 00:46:19,456\r\nsquare代表一个构建好的过程\r\nand the something that I'm naming square is a procedure that's getting constructed.\r\n\r\n673\r\n00:46:20,752 --> 00:46:23,456\r\n让我们看看在计算机里面又是 怎样的吧\r\nWell, let's look at that on the computer, too.\r\n\r\n674\r\n00:46:24,336 --> 00:46:35,504\r\n定义“(square x)”为x乘以x的积\r\nSo I'll come and I'll say, define square of x to be times xx.\r\n\r\n675\r\n00:46:49,200 --> 00:46:51,872\r\n将它送入Lisp\r\nNow I'll tell Lisp that.\r\n\r\n676\r\n00:46:53,040 --> 00:46:53,472\r\n返回square\r\nIt says \"square.\"\r\n\r\n677\r\n00:46:53,488 --> 00:46:55,840\r\n现在 我已经将某个东西命名为square了\r\nSee, I've named something \"square.\"\r\n\r\n678\r\n00:46:56,000 --> 00:47:02,430\r\n完毕后 我就可以问Lisp 1001的平方是多少\r\nNow, having done that, I can ask Lisp for, what's the square of 1,001?\r\n\r\n679\r\n00:47:04,816 --> 00:47:17,248\r\n或者更通常的来说 我可以问 5加上7的和的平方是多少\r\nOr in general, I could say, what's the square of the sum of 5 and 7?\r\n\r\n680\r\n00:47:22,368 --> 00:47:24,500\r\n12的平方是144\r\nThe square of 12's 144.\r\n\r\n681\r\n00:47:24,624 --> 00:47:28,416\r\n在某些组合式中我亦可把square当作一个元素\r\nOr I can use square itself as an element in some combination.\r\n\r\n682\r\n00:47:28,432 --> 00:47:37,056\r\n3的平方加上4的平方的和是多少\r\nI can say, what's the sum of the square of 3 and the square of 4?\r\n\r\n683\r\n00:47:42,080 --> 00:47:43,648\r\n9加上16得25\r\n9 and 16 is 25.\r\n\r\n684\r\n00:47:44,464 --> 00:47:50,096\r\n我可以将square作为元素用于更复杂的式子\r\nOr I can use square as an element in some much more complicated thing.\r\n\r\n685\r\n00:47:50,144 --> 00:48:00,064\r\n比如 1001的平方点的平方的平方是多少\r\nI can say, what's the square of, the sqare of, the square of 1,001?\r\n\r\n686\r\n00:48:07,440 --> 00:48:10,180\r\n这就是1001点的平方的平方的平方\r\nAnd there's the square of the square of the square of 1,001.\r\n\r\n687\r\n00:48:10,752 --> 00:48:15,008\r\n我也可以问Lisp square本身是什么\r\nOr I can say to Lisp, what is square itself?\r\n\r\n688\r\n00:48:15,232 --> 00:48:16,710\r\n它的值是是什么\r\nWhat's the value of that?\r\n\r\n689\r\n00:48:16,992 --> 00:48:21,690\r\nLisp用一种约定的方法告诉我这是一个过程\r\nAnd Lisp returns some conventional way of telling me that that's a procedure.\r\n\r\n690\r\n00:48:21,824 --> 00:48:23,536\r\n它返回 复合过程square\r\nIt says, \"compound procedure square.\"\r\n\r\n691\r\n00:48:23,808 --> 00:48:27,470\r\n记住 square的值是一个过程\r\nRemember, the value of square is this procedure,\r\n\r\n692\r\n00:48:28,704 --> 00:48:30,448\r\n而那些用星号和括号的记法\r\nand the thing with the stars and the brackets\r\n\r\n693\r\n00:48:30,656 --> 00:48:34,330\r\n只是Lisp用来描述这个过程的约定\r\nare just Lisp's conventional way of describing that.\r\n\r\n694\r\n00:48:35,664 --> 00:48:40,880\r\n让我们再看两个关于define的例子\r\nLet's look at two more examples of defining.\r\n\r\n695\r\n00:48:44,464 --> 00:48:46,464\r\n这有两个过程\r\nHere are two more procedures.\r\n\r\n696\r\n00:48:46,912 --> 00:48:52,390\r\n定义x和y的平均值为x加上y的和除以2的商\r\nI can define the average of x and y to be the sum of x and y divided by 2.\r\n\r\n697\r\n00:48:54,224 --> 00:49:01,040\r\n以及定义好平方和平均值后 我可以定义均方\r\nOr having had average and mean square, having had average and square,\r\n\r\n698\r\n00:49:01,200 --> 00:49:04,260\r\n我可以用它们来讨论某元素的均方\r\nI can use that to talk about the mean square of something,\r\n\r\n699\r\n00:49:04,464 --> 00:49:08,810\r\n即x的平方与y的平方的平均值\r\nwhich is the average of the square of x and the square of y.\r\n\r\n700\r\n00:49:10,528 --> 00:49:13,184\r\n当定义好它们后 我可以问\r\nSo for example, having done that, I could say,\r\n\r\n701\r\n00:49:13,216 --> 00:49:24,432\r\n2和3的均方是多少\r\nwhat's the mean square of 2 and 3?\r\n\r\n702\r\n00:49:24,784 --> 00:49:29,790\r\n我将会得到 4和9的平均值 即6.5\r\nAnd I should get the average of 4 and 9, which is 6.5.\r\n\r\n703\r\n00:49:32,400 --> 00:49:36,192\r\n关键点在于 定义了square后\r\nThe key thing here is that, having defined square,\r\n\r\n704\r\n00:49:36,192 --> 00:49:38,224\r\n我可以把它当作一个基本元素来使用\r\nI can use it as if it were primitive.\r\n\r\n705\r\n00:49:40,960 --> 00:49:42,624\r\n因此在这里\r\nSo if we look here on the slide,\r\n\r\n706\r\n00:49:44,208 --> 00:49:45,296\r\n我在讨论均方的时候\r\nif I look at mean square,\r\n\r\n707\r\n00:49:46,848 --> 00:49:52,112\r\n从这点来说 定义均方的人没有必要知道\r\nthe person defining mean square doesn't have to know, at this point,\r\n\r\n708\r\n00:49:52,160 --> 00:49:55,312\r\n究竟square是由语言内建支持\r\nwhether square was something built into the language\r\n\r\n709\r\n00:49:56,496 --> 00:49:58,480\r\n还是自定义的过程\r\nor whether it was a procedure that was defined.\r\n\r\n710\r\n00:49:59,280 --> 00:50:00,832\r\n这是Lisp的关键之一\r\nAnd that's a key thing in Lisp,\r\n\r\n711\r\n00:50:01,850 --> 00:50:07,072\r\n你无法准确区别\r\nthat you do not make arbitrary distinctions between things\r\n\r\n712\r\n00:50:07,088 --> 00:50:11,370\r\n哪些是语言的基本对象 哪些是语言的内建支持\r\nthat happen to be primitive in the language and things that happen to be built in.\r\n\r\n713\r\n00:50:12,384 --> 00:50:14,288\r\n用户使用时则无需关心这些\r\nA person using that shouldn't even have to know.\r\n\r\n714\r\n00:50:14,480 --> 00:50:18,064\r\n你自己构建的东西看起来就像是语言自带的基本对象\r\nSo the things you construct get used with all the power and flexibility\r\n\r\n715\r\n00:50:18,064 --> 00:50:19,088\r\n具有同样的能力和灵活性\r\nas if they were primitives.\r\n\r\n716\r\n00:50:19,120 --> 00:50:22,128\r\n大家可以在课后上机做做测试\r\nIn fact, you can drive that home by looking on the computer one more time.\r\n\r\n717\r\n00:50:24,304 --> 00:50:25,856\r\n我们接下来讨论一下“+”吧\r\nWe talked about plus.\r\n\r\n718\r\n00:50:26,272 --> 00:50:29,648\r\n好的 让我们在计算机中看看\r\nAnd in fact, if I come here on the computer screen and say,\r\n\r\n719\r\n00:50:29,664 --> 00:50:31,888\r\n“+”的值是什么\r\nwhat is the value of plus?\r\n\r\n720\r\n00:50:33,952 --> 00:50:36,752\r\n注意Lisp在下面的输出\r\nNotice what Lisp types out. On the bottom there, it typed out,\r\n\r\n721\r\n00:50:36,800 --> 00:50:38,368\r\n复合过程“+”\r\n\"compound procedure plus.\"\r\n\r\n722\r\n00:50:39,440 --> 00:50:41,840\r\n因为在此系统中\r\nBecause, in this system,\r\n\r\n723\r\n00:50:41,888 --> 00:50:45,040\r\n“+”运算符是一个复合过程\r\nit turns out that the addition operator is itself a compound procedure.\r\n\r\n724\r\n00:50:45,520 --> 00:50:47,520\r\n但如果我不输入进去做下测试 你永远不会知道\r\nAnd if I didn't just type that in, you'd never know that,\r\n\r\n725\r\n00:50:47,616 --> 00:50:49,232\r\n所以这没什么不同\r\nand it wouldn't make any difference anyway.\r\n\r\n726\r\n00:50:49,392 --> 00:50:50,064\r\n我们并不关心这些\r\nWe don't care.\r\n\r\n727\r\n00:50:50,112 --> 00:50:52,940\r\n它比我们日常处理的问题更加抽象一些\r\nIt's below the level of the abstraction that we're dealing with.\r\n\r\n728\r\n00:50:53,728 --> 00:50:58,660\r\n其关键点在于你无法分辨出\r\nSo the key thing is you cannot tell, should not be able to tell, in general,\r\n\r\n729\r\n00:50:58,720 --> 00:51:03,370\r\n内建元素与复合元素之间的不同\r\nthe difference between things that are built in and things that are compound.\r\n\r\n730\r\n00:51:03,392 --> 00:51:03,936\r\n为什么会这样呢？\r\nWhy is that?\r\n\r\n731\r\n00:51:03,936 --> 00:51:07,620\r\n因为复合元素经过了一次抽象封装 (以致于无法分辨)\r\nBecause the things that are compound have an abstraction wrapper wrapped around them.\r\n\r\n732\r\n00:51:08,608 --> 00:51:11,168\r\n我们已经介绍了Lisp的大多数元素了\r\nWe've seen almost all the elements of Lisp now.\r\n\r\n733\r\n00:51:12,224 --> 00:51:14,080\r\n还有一个需要进行讨论的\r\nThere's only one more we have to look at,\r\n\r\n734\r\n00:51:14,128 --> 00:51:16,080\r\n就是如何进行分情况分析\r\nand that is how to make a case analysis.\r\n\r\n735\r\n00:51:16,144 --> 00:51:17,250\r\n举个例子\r\nLet me show you what I mean.\r\n\r\n736\r\n00:51:18,512 --> 00:51:23,632\r\n让我们考虑绝对值函数的数学定义\r\nWe might want to think about the mathematical definition of the absolute value functions.\r\n\r\n737\r\n00:51:23,664 --> 00:51:29,580\r\n我或许会说x的绝对值这样是一个函数\r\nI might say the absolute value of x is the function\r\n\r\n738\r\n00:51:29,712 --> 00:51:36,790\r\n若x小于0 则为-x\r\nwhich has the property that it's negative of x. For x less than 0,\r\n\r\n739\r\n00:51:37,472 --> 00:51:40,680\r\n若x等于0 则为0\r\nit's 0 for x equal to 0.\r\n\r\n740\r\n00:51:42,192 --> 00:51:46,170\r\n若x大于0 则就是x\r\nAnd it's x for x greater than 0.\r\n\r\n741\r\n00:51:48,704 --> 00:51:51,456\r\n而Lisp则有一套分情况分析方法\r\nAnd Lisp has a way of making case analyses.\r\n\r\n742\r\n00:51:51,664 --> 00:51:53,408\r\n以绝对值定义为例 我给大家说明一下\r\nLet me define for you absolute value.\r\n\r\n743\r\n00:51:55,104 --> 00:52:01,960\r\n定义绝对值为 x是有多种情况的\r\nSay define the absolute value of x is conditional.\r\n\r\n744\r\n00:52:02,576 --> 00:52:05,220\r\n这就是分情况分析\r\nThis means case analysis, COND.\r\n\r\n745\r\n00:52:08,784 --> 00:52:18,640\r\n如果x小于0 则结果为-x\r\nIf x is less than 0, the answer is negate x.\r\n\r\n746\r\n00:52:22,544 --> 00:52:24,430\r\n我这里写的是一个子句\r\nWhat I've written here is a clause.\r\n\r\n747\r\n00:52:24,544 --> 00:52:35,090\r\n这整个是一个由两部分组成的条件表达式\r\nThis whole thing is a conditional clause, and it has two parts.\r\n\r\n748\r\n00:52:35,904 --> 00:52:44,250\r\n这个部分叫做谓词或者条件\r\nThis part here is a predicate or a condition.\r\n\r\n749\r\n00:52:44,384 --> 00:52:45,456\r\n这就是一种情况（条件）\r\nThat's a condition.\r\n\r\n750\r\n00:52:45,664 --> 00:52:47,840\r\n用以表达条件的东西叫做谓词\r\nAnd the condition is expressed by something called a predicate,\r\n\r\n751\r\n00:52:47,888 --> 00:52:50,600\r\nLisp中的谓词是一种\r\nand a predicate in Lisp is some sort of thing\r\n\r\n752\r\n00:52:50,928 --> 00:52:52,420\r\n可以返回true或者false的东西\r\nthat returns either true or false.\r\n\r\n753\r\n00:52:53,088 --> 00:52:55,680\r\n比如说“小于”是Lisp中的一个基本过程\r\nAnd you see Lisp has a primitive procedure, less-than,\r\n\r\n754\r\n00:52:56,848 --> 00:52:58,630\r\n它返回true或者false\r\nthat tests whether something is true or false.\r\n\r\n755\r\n00:53:00,090 --> 00:53:05,872\r\n子句其余部分为一个动作或者需要做的事\r\nAnd the other part of a clause is an action or a thing to do,\r\n\r\n756\r\n00:53:06,480 --> 00:53:07,696\r\n本例中为true\r\nin the case where that's true.\r\n\r\n757\r\n00:53:07,728 --> 00:53:09,360\r\n在这里 我则是取x的相反数\r\nAnd here, what I'm doing is negating x.\r\n\r\n758\r\n00:53:09,632 --> 00:53:13,960\r\n有趣的是 Lisp中减运算符符与相反数运算符相同\r\nThe negation operator, the minus sign in Lisp is a little bit funny.\r\n\r\n759\r\n00:53:14,112 --> 00:53:17,980\r\n如果有两个及两个以上的参数\r\nIf there's two or more arguments,\r\n\r\n760\r\n00:53:18,130 --> 00:53:22,048\r\n正如我们看到的 假设刚好有两个参数 就从第一个中减去第二个\r\nif there's two arguments it subtracts the second one from the first, and we saw that.\r\n\r\n761\r\n00:53:22,080 --> 00:53:23,680\r\n如果只有一个参数 则取其相反数\r\nAnd if there's one argument, it negates it.\r\n\r\n762\r\n00:53:24,688 --> 00:53:27,420\r\n这与前面相符合\r\nSo this corresponds to that.\r\n\r\n763\r\n00:53:27,424 --> 00:53:29,240\r\n这又是一个COND子句\r\nAnd then there's another COND clause.\r\n\r\n764\r\n00:53:30,192 --> 00:53:35,424\r\n这是说 在x等于0的时候 结果为0\r\nIt says, in the case where x is equal to 0, the answer is 0.\r\n\r\n765\r\n00:53:37,504 --> 00:53:44,300\r\n在x大于0的时候 结果为x\r\nAnd in the case where x is greater than 0, the answer is x.\r\n\r\n766\r\n00:53:44,880 --> 00:53:48,930\r\n闭合子句 闭合COND 闭合define\r\nClose that clause. Close the COND. Close the definition.\r\n\r\n767\r\n00:53:49,120 --> 00:53:50,848\r\n这就是绝对值的定义\r\nAnd there's the definition of absolute value.\r\n\r\n768\r\n00:53:50,864 --> 00:53:53,216\r\n你会发现分情况分析\r\nAnd you see it's the case analysis that looks very much\r\n\r\n769\r\n00:53:53,216 --> 00:53:55,590\r\n与数学中所用的非常相似\r\nlike the case analysis you use in mathematics.\r\n\r\n770\r\n00:53:57,696 --> 00:54:02,624\r\n当然还有一些不常用的受限的分情况分析方法\r\nThere's a somewhat different way of writing a restricted case analysis.\r\n\r\n771\r\n00:54:02,624 --> 00:54:05,792\r\n很多时候 你在进行分情况分析时只有一种情况\r\nOften, you have a case analysis where you only have one case,\r\n\r\n772\r\n00:54:06,480 --> 00:54:07,620\r\n你首先进行测试\r\nwhere you test something,\r\n\r\n773\r\n00:54:07,888 --> 00:54:10,300\r\n然后根据返回的为true或false来决定如何处理\r\nand then depending on whether it's true or false, you do something.\r\n\r\n774\r\n00:54:10,560 --> 00:54:15,450\r\n这是另外一种定义绝对值的方法\r\nAnd here's another definition of absolute value\r\n\r\n775\r\n00:54:15,552 --> 00:54:16,740\r\n但看起来是几乎一样的\r\nwhich looks almost the same,\r\n\r\n776\r\n00:54:17,216 --> 00:54:22,112\r\n像这样 如果x小于0 结果则为x的相反数\r\nwhich says, if x is less than 0, the result is negate x.\r\n\r\n777\r\n00:54:23,960 --> 00:54:25,520\r\n否则 结果即为x\r\nOtherwise, the answer is x.\r\n\r\n778\r\n00:54:25,600 --> 00:54:26,800\r\n我们将会大量的使用“if”\r\nAnd we'll be using \"if\" a lot.\r\n\r\n779\r\n00:54:26,848 --> 00:54:28,688\r\n再次声明\r\nBut again, the thing to remember is that\r\n\r\n780\r\n00:54:28,688 --> 00:54:32,256\r\n你们在这里看到的绝对值形式\r\nthis form of absolute value that you're looking at here,\r\n\r\n781\r\n00:54:33,856 --> 00:54:36,530\r\n和我在黑板上写的那种\r\nand then this one over here that I wrote on the board,\r\n\r\n782\r\n00:54:37,072 --> 00:54:38,352\r\n本质上是一样的\r\nare essentially the same.\r\n\r\n783\r\n00:54:38,640 --> 00:54:41,810\r\n而“if”和“COND”则是——\r\nAnd \"if\" and COND are-- well, whichever way you like it.\r\n\r\n784\r\n00:54:41,856 --> 00:54:44,000\r\n你可以把“COND”当做“if”的语法糖\r\nYou can think of COND as syntactic sugar for \"if\",\r\n\r\n785\r\n00:54:44,544 --> 00:54:46,912\r\n或者“if”是“COND”的语法糖\r\nor you can think of \"if\" as syntactic sugar for COND,\r\n\r\n786\r\n00:54:46,944 --> 00:54:48,200\r\n这没什么区别\r\nand it doesn't make any difference.\r\n\r\n787\r\n00:54:48,768 --> 00:54:50,900\r\nLisp系统的设计者会从中会选择一个\r\nThe person implementing a Lisp system will pick one\r\n\r\n788\r\n00:54:50,944 --> 00:54:52,528\r\n然后依照这个来实现另外一个\r\nand implement the other in terms of that.\r\n\r\n789\r\n00:54:52,704 --> 00:54:54,224\r\n你首先实现哪一个都无所谓\r\nAnd it doesn't matter which one you pick.\r\n\r\n790\r\n00:55:01,824 --> 00:55:04,910\r\n让我们停下来 解决几点疑问\r\nWhy don't we break now, and then take some questions.\r\n\r\n791\r\n00:55:05,248 --> 00:55:09,632\r\n为什么我有时用define时\r\nHow come sometimes when I write define,\r\n\r\n792\r\n00:55:10,640 --> 00:55:14,300\r\n我在这里使用了一个左括号\r\nI put an open paren here and say,\r\n\r\n793\r\n00:55:14,368 --> 00:55:16,000\r\n输入 define (XXX\r\ndefine open paren something or other,\r\n\r\n794\r\n00:55:16,416 --> 00:55:20,368\r\n而有时我这样写时却没加左括号\r\nand sometimes when I write this, I don't put an open paren?\r\n\r\n795\r\n00:55:21,616 --> 00:55:26,784\r\n是因为你所见的\r\nThe answer is, this particular form of \"define\",\r\n\r\n796\r\n00:55:26,816 --> 00:55:28,960\r\n这种“define”表达式\r\nwhere you say define some expression,\r\n\r\n797\r\n00:55:29,024 --> 00:55:31,680\r\n对于定义过程来讲是非常特殊\r\nis this very special thing for defining procedures.\r\n\r\n798\r\n00:55:33,168 --> 00:55:39,760\r\n再次强调 这实际上是说我定义这个叫square的符号为这个\r\nBut again, what it really means is I'm defining this symbol, square, to be that.\r\n\r\n799\r\n00:55:41,008 --> 00:55:45,536\r\n你所知道的则是 你先写一个“define”\r\nSo the way you should think about it is what \"define\" does is you write \"define\",\r\n\r\n800\r\n00:55:46,704 --> 00:55:49,616\r\n然后你再写一个符号 没有左括号\r\nand the second thing you write is the symbol here-- no open paren--\r\n\r\n801\r\n00:55:49,728 --> 00:55:51,040\r\n这是你将要定义的符号\r\nthe symbol you're defining\r\n\r\n802\r\n00:55:51,632 --> 00:55:53,250\r\n这又是你要将其定义为什么\r\nand what you're defining it to be.\r\n\r\n803\r\n00:55:54,208 --> 00:55:57,104\r\n就像这儿和这儿\r\nThat's like here and like here.\r\n\r\n804\r\n00:55:57,168 --> 00:55:59,840\r\n这是“define”的基本使用方法\r\nThat's sort of the basic way you use \"define.\"\r\n\r\n805\r\n00:56:00,672 --> 00:56:03,200\r\n然而 这种特殊的语法技巧\r\nAnd then, there's this special syntactic trick\r\n\r\n806\r\n00:56:03,840 --> 00:56:06,592\r\n使得你可以定义像这样的过程\r\nwhich allows you to define procedures that look like this.\r\n\r\n807\r\n00:56:07,728 --> 00:56:11,040\r\n因此区别就在于你是否定义了一个过程\r\nSo the difference is, it's whether or not you're defining a procedure.\r\n\r\n808\r\n00:56:12,464 --> 00:56:37,152\r\n[音乐]\r\n[JESU, JOY OF MAN'S DESIRING]\r\n\r\n809\r\n00:56:37,600 --> 00:56:41,536\r\n信不信由你 你们已经学了足够多的Lisp的知识了\r\nWell, believe it or not, you actually now know enough Lisp\r\n\r\n810\r\n00:56:42,336 --> 00:56:44,976\r\n现在你基本上可以编写\r\nto write essentially any numerical procedure\r\n\r\n811\r\n00:56:45,808 --> 00:56:49,184\r\nFORTRAN、Basic或者其它语言中一样的\r\nthat you'd write in a language like FORTRAN or Basic or whatever,\r\n\r\n812\r\n00:56:49,216 --> 00:56:50,560\r\n数值计算过程了\r\nor, essentially, any other language.\r\n\r\n813\r\n00:56:51,600 --> 00:56:54,310\r\n或许你会说 这不可能\r\nAnd you're probably saying, that's not believable,\r\n\r\n814\r\n00:56:54,368 --> 00:56:56,208\r\n因为你知道这些语言有\r\nbecause you know that these languages have things\r\n\r\n815\r\n00:56:56,208 --> 00:56:59,770\r\n像“for”语句和“do-until-while”语句的东西\r\nlike \"for statements\", and \"do until while\" or something.\r\n\r\n816\r\n00:57:00,544 --> 00:57:04,144\r\n实际上这些我们一点也用不着\r\nBut we don't really need any of that.\r\n\r\n817\r\n00:57:04,608 --> 00:57:06,680\r\n本课中我们一点也不会使用这些东西\r\nIn fact, we're not going to use any of that in this course.\r\n\r\n818\r\n00:57:07,808 --> 00:57:09,712\r\n我给你们来个下马威\r\nLet me show you.\r\n\r\n819\r\n00:57:09,808 --> 00:57:13,168\r\n回过头来看看平方根\r\nAgain, looking back at square root,\r\n\r\n820\r\n00:57:13,200 --> 00:57:18,580\r\n让我们看看亚历山大的Heron提出的平方根算法\r\nlet's go back to this square root algorithm of Heron of Alexandria.\r\n\r\n821\r\n00:57:18,640 --> 00:57:19,520\r\n想想它是怎么说的\r\nRemember what that said.\r\n\r\n822\r\n00:57:19,616 --> 00:57:23,220\r\n算法说 为了找到X的平方根的近似值\r\nIt said, to find an approximation to the square root of X,\r\n\r\n823\r\n00:57:24,624 --> 00:57:25,712\r\n你做出猜测\r\nyou make a guess,\r\n\r\n824\r\n00:57:27,008 --> 00:57:31,430\r\n然后通过取guess和X/guess的平均数来改进猜测\r\nyou improve that guess by averaging the guess and X over the guess.\r\n\r\n825\r\n00:57:32,496 --> 00:57:35,616\r\n你不断改进猜测 直到这个猜测足够好\r\nYou keep improving that until the guess is good enough.\r\n\r\n826\r\n00:57:36,272 --> 00:57:37,984\r\n我已经提到过这种想法\r\nI already alluded to the idea.\r\n\r\n827\r\n00:57:38,112 --> 00:57:41,792\r\n这种想法是说 如果你最初采用的猜测\r\nThe idea is that, if the initial guess that you took\r\n\r\n828\r\n00:57:42,592 --> 00:57:46,460\r\n真真切切的等于X的平方根\r\nwas actually equal to the square root of X,\r\n\r\n829\r\n00:57:46,704 --> 00:57:49,616\r\n那么G就会等于X/G\r\nthen G here would be equal to X/G.\r\n\r\n830\r\n00:57:52,448 --> 00:57:54,880\r\n如果你算出平方根 对其取平均数并不会改变它\r\nSo if you hit the square root, averaging them wouldn't change it.\r\n\r\n831\r\n00:57:55,248 --> 00:57:59,170\r\n如果你所采用的G比X的平方根大\r\nIf the G that you picked was larger than the square root of X,\r\n\r\n832\r\n00:57:59,936 --> 00:58:02,490\r\n那么X/G就会比X的平方根小\r\nthen X/G will be smaller than the square root of X,\r\n\r\n833\r\n00:58:02,768 --> 00:58:04,928\r\n因此当你取G与X/G的平均值时\r\nso that when you average G and X/G,\r\n\r\n834\r\n00:58:05,184 --> 00:58:07,120\r\n就得到了两者之间的某数\r\nyou get something in between.\r\n\r\n835\r\n00:58:08,512 --> 00:58:12,500\r\n同理 若你采用的G过小 答案则会过大\r\nSo if you pick a G that's too small, your answer will be too large.\r\n\r\n836\r\n00:58:12,672 --> 00:58:14,368\r\n如果你采用了一个太大的G\r\nIf you pick a G that's too large,\r\n\r\n837\r\n00:58:15,872 --> 00:58:17,616\r\n如果你的G比X的平方根还要大的话\r\nif your G is larger than the square root of X\r\n\r\n838\r\n00:58:17,632 --> 00:58:19,904\r\nX/G就会比X的平方根还要小\r\nand X/G will be smaller than the square root of X.\r\n\r\n839\r\n00:58:20,784 --> 00:58:23,200\r\n因此取平均值使得你总可以得到两者间的某数\r\nSo averaging always gives you something in between.\r\n\r\n840\r\n00:58:24,080 --> 00:58:27,680\r\n这不是毫无意义的 它表明\r\nAnd then, it's not quite trivial, but it's possible to show that,\r\n\r\n841\r\n00:58:27,728 --> 00:58:31,310\r\n事实上 如果G只差X的平方根一点的话\r\nin fact, if G misses the square root of X by a little bit,\r\n\r\n842\r\n00:58:31,360 --> 00:58:37,540\r\nG和X/G的平均值就会慢慢的向X的平方根靠近\r\nthe average of G and X/G will actually keep getting closer to the square root of X.\r\n\r\n843\r\n00:58:37,584 --> 00:58:38,544\r\n只要你不断的这样做\r\nSo if you keep doing this enough,\r\n\r\n844\r\n00:58:38,976 --> 00:58:40,736\r\n最终就可以不断地靠近\r\nyou'll eventually get as close as you want.\r\n\r\n845\r\n00:58:41,264 --> 00:58:42,400\r\n另外一个事实则是\r\nAnd then there's another fact,\r\n\r\n846\r\n00:58:42,576 --> 00:58:47,200\r\n你总可以使用1作为一个初始猜测值来开始计算\r\nthat you can always start out this process by using 1 as an initial guess.\r\n\r\n847\r\n00:58:48,784 --> 00:58:50,900\r\n它总是朝X的平方根聚拢\r\nAnd it'll always converge to the square root of X.\r\n\r\n848\r\n00:58:51,792 --> 00:58:56,320\r\n这就是亚历山大的Heron的连续求平均值法\r\nSo that's this method of successive averaging due to Heron of Alexandria.\r\n\r\n849\r\n00:58:56,368 --> 00:58:58,760\r\n让我们在Lisp中实现\r\nLet's write it in Lisp.\r\n\r\n850\r\n00:59:00,120 --> 00:59:02,160\r\n中心思想是\r\nWell, the central idea is,\r\n\r\n851\r\n00:59:02,208 --> 00:59:06,740\r\n尝试将guess作为X的平方根的一个猜想意味着什么\r\nwhat does it mean to try a guess for the square root of X?\r\n\r\n852\r\n00:59:07,856 --> 00:59:08,928\r\n我来编码\r\nLet's write that.\r\n\r\n853\r\n00:59:09,344 --> 00:59:24,576\r\n定义（try guess x）\r\nSo we'll say, define to try a guess for the square root of X,\r\n\r\n854\r\n00:59:26,000 --> 00:59:27,790\r\n我们该如何做 我们会说\r\nwhat do we do? We'll say,\r\n\r\n855\r\n00:59:27,840 --> 00:59:44,816\r\n如果猜测精确到可以作为X的平方根\r\nif the guess is good enough to be a guess for the square root of X,\r\n\r\n856\r\n00:59:46,096 --> 00:59:49,070\r\n那么我们就可以将这个猜测作为答案\r\nthen, as an answer, we'll take the guess.\r\n\r\n857\r\n00:59:51,168 --> 00:59:56,560\r\n否则 我们就会尝试改进猜测\r\nOtherwise, we will try the improved guess.\r\n\r\n858\r\n00:59:57,744 --> 01:00:03,792\r\n我们将通过改进这个猜测来作为X的平方根\r\nWe'll improve that guess for the square root of X,\r\n\r\n859\r\n01:00:04,816 --> 01:00:08,880\r\n并尝试是否为X平方根\r\nand we'll try that as a guess for the square root of X.\r\n\r\n860\r\n01:00:08,912 --> 01:00:12,512\r\n闭合try 闭合if 闭合define\r\nClose the \"try.\" Close the \"if.\" Close the \"define.\"\r\n\r\n861\r\n01:00:12,864 --> 01:00:14,368\r\n这就是我们如何尝试一个猜测\r\nSo that's how we try a guess.\r\n\r\n862\r\n01:00:15,408 --> 01:00:17,150\r\n然后 这个过程的下一步是说\r\nAnd then, the next part of the process said,\r\n\r\n863\r\n01:00:17,280 --> 01:00:21,450\r\n为了计算平方根\r\nin order to compute square roots, we'll say,\r\n\r\n864\r\n01:00:21,488 --> 01:00:29,728\r\n定义计算X的平方根为\r\ndefine to compute the square root of X,\r\n\r\n865\r\n01:00:30,352 --> 01:00:35,344\r\n从1作为X的平方根的一个猜测开始尝试\r\nwe will try 1 as a guess for the square root of X.\r\n\r\n866\r\n01:00:36,976 --> 01:00:39,140\r\n我们必须定义一些其它的东西\r\nWell, we have to define a couple more things.\r\n\r\n867\r\n01:00:39,632 --> 01:00:42,912\r\n我们必须说明 一个猜测如何才叫“足够好”\r\nWe have to say, how is a guess good enough?\r\n\r\n868\r\n01:00:43,392 --> 01:00:44,848\r\n我们又该如何改进这个猜测\r\nAnd how do we improve a guess?\r\n\r\n869\r\n01:00:45,408 --> 01:00:46,656\r\n那么让我们来看看\r\nSo let's look at that.\r\n\r\n870\r\n01:00:46,944 --> 01:00:53,792\r\n而改进一个X的平方根的一个猜测的算法则是\r\nThe algorithm to improve a guess for the square root of X,\r\n\r\n871\r\n01:00:54,192 --> 01:00:56,736\r\n取平均数\r\nwe average-- that was the algorithm--\r\n\r\n872\r\n01:00:56,736 --> 01:01:01,712\r\n我们取guess和X/guess的平均数\r\nwe average the guess with the quotient of dividing X by the guess.\r\n\r\n873\r\n01:01:02,544 --> 01:01:04,128\r\n这就是我们如何改进一个猜测\r\nThat's how we improve a guess.\r\n\r\n874\r\n01:01:05,408 --> 01:01:08,352\r\n为了确定一个猜测是否足够精确 我们需要做一下规定\r\nAnd to tell whether a guess is good enough, well, we have to decide something.\r\n\r\n875\r\n01:01:08,416 --> 01:01:10,912\r\n假设这个是X的平方根的一个猜测\r\nThis is supposed to be a guess for the square root of X,\r\n\r\n876\r\n01:01:10,928 --> 01:01:13,584\r\n你可能做的一件事就是\r\nso one possible thing you can do is say,\r\n\r\n877\r\n01:01:13,616 --> 01:01:15,620\r\n当你采用这个猜测并将其平方\r\nwhen you take that guess and square it,\r\n\r\n878\r\n01:01:16,192 --> 01:01:17,968\r\n你会得到一个非常接近于X的数\r\ndo you get something very close to X?\r\n\r\n879\r\n01:01:18,144 --> 01:01:20,650\r\n而表达这个想法的一种方式是\r\nSo one way to say that is to say,\r\n\r\n880\r\n01:01:20,672 --> 01:01:23,860\r\n我们用X减去guess的平方\r\nI square the guess, subtract X from that,\r\n\r\n881\r\n01:01:24,704 --> 01:01:26,700\r\n并且确认所得结果的绝对值是否\r\nand see if the absolute value of that\r\n\r\n882\r\n01:01:26,752 --> 01:01:31,600\r\n比一个由你规定的很小的数还要小\r\nwhole thing is less than some small number, which depends on my purposes.\r\n\r\n883\r\n01:01:34,256 --> 01:01:40,970\r\n因此 我们就有了计算X的平方根的一整套过程\r\nSo there's a complete procedure for how to compute the square root of X.\r\n\r\n884\r\n01:01:41,024 --> 01:01:43,088\r\n我们再来深入观察一下这个结构\r\nLet's look at the structure of that a little bit.\r\n\r\n885\r\n01:01:47,392 --> 01:01:48,672\r\n我搞定了整件事\r\nI have the whole thing.\r\n\r\n886\r\n01:01:48,700 --> 01:01:54,992\r\n我有一个用于计算X的平方根的记号\r\nI have the notion of how to compute a square root.\r\n\r\n887\r\n01:01:55,088 --> 01:01:56,432\r\n这是一种模块\r\nThat's some kind of module.\r\n\r\n888\r\n01:01:56,608 --> 01:01:58,016\r\n也是一种黑盒\r\nThat's some kind of black box.\r\n\r\n889\r\n01:01:58,272 --> 01:02:07,570\r\n它的定义依赖于如何尝试将一个猜测值作为X的平方根\r\nIt's defined in terms of how to try a guess for the square root of X.\r\n\r\n890\r\n01:02:08,864 --> 01:02:13,650\r\n定义try是用来\r\n\"Try\" is defined in terms of, well,\r\n\r\n891\r\n01:02:14,160 --> 01:02:17,584\r\n确认某数是否足够精确以及如何去改进该数\r\ntelling whether something is good enough and telling how to improve something.\r\n\r\n892\r\n01:02:18,288 --> 01:02:19,232\r\n这是good-enogh?\r\nSo good enough.\r\n\r\n893\r\n01:02:19,440 --> 01:02:28,400\r\ntry的定义依赖于good-enough?和improve\r\n\"Try\" is defined in terms of \"good enough\" and \"improve\".\r\n\r\n894\r\n01:02:30,512 --> 01:02:32,110\r\n让我们来看看我填入了些什么\r\nAnd let's see what else I fill in.\r\n\r\n895\r\n01:02:32,264 --> 01:02:33,844\r\n如果我向下拓展这棵树\r\nWell, I'll go down this tree.\r\n\r\n896\r\n01:02:34,288 --> 01:02:38,048\r\ngood-enough?的定义依赖于abs和square\r\n\"Good enough\" was defined in terms of absolute value, and square.\r\n\r\n897\r\n01:02:40,528 --> 01:02:43,680\r\n而improve的定义依赖于averaging\r\nAnd improve was defined in terms of something called averaging\r\n\r\n898\r\n01:02:44,720 --> 01:02:46,256\r\n而其它的都是一些基本运算符\r\nand then some other primitive operator.\r\n\r\n899\r\n01:02:46,272 --> 01:02:48,432\r\n平方根的定义依赖于try\r\nSquare root's defined in terms of \"try\".\r\n\r\n900\r\n01:02:48,432 --> 01:02:52,864\r\ntry的定义依赖于good-enough?和improve\r\n\"Try\" is defined in terms of \"good enough\" and \"improve\",\r\n\r\n901\r\n01:02:53,568 --> 01:02:54,944\r\n甚至依赖于try本身\r\nbut also \"try\" itself.\r\n\r\n902\r\n01:02:55,136 --> 01:03:00,416\r\n因此try也按照它如何应用于自身而进行定义\r\nSo \"try\" is also defined in terms of how to try itself.\r\n\r\n903\r\n01:03:02,304 --> 01:03:04,272\r\n额 这可能会使你有点糊涂\r\nWell, that may give you some problems.\r\n\r\n904\r\n01:03:04,272 --> 01:03:07,712\r\n你的高中几何老师或许告诉过你\r\nYour high school geometry teacher probably told you\r\n\r\n905\r\n01:03:08,224 --> 01:03:12,128\r\n用一个东西自己去定义自己是很不对的\r\nthat it's naughty to try and define things in terms of themselves,\r\n\r\n906\r\n01:03:12,432 --> 01:03:13,472\r\n因为这根本行不通\r\nbecause it doesn't make sense.\r\n\r\n907\r\n01:03:13,472 --> 01:03:14,272\r\n这（种说法）是错的\r\nBut that's false.\r\n\r\n908\r\n01:03:15,584 --> 01:03:19,232\r\n有时候用一个东西自己来定义自己非常有意义\r\nSometimes it makes perfect sense to define things in terms of themselves.\r\n\r\n909\r\n01:03:19,712 --> 01:03:23,930\r\n我们来看看这个例子\r\nAnd this is the case. And we can look at that.\r\n\r\n910\r\n01:03:23,936 --> 01:03:26,448\r\n假设我问Lisp：2的平方根是多少\r\nWe could write down what this means, and say,\r\n\r\n911\r\n01:03:26,464 --> 01:03:29,888\r\n我们可以写出它究竟是什么意思\r\nsuppose I asked Lisp what the square root of 2 is.\r\n\r\n912\r\n01:03:32,208 --> 01:03:34,220\r\n2的平方根是什么意思\r\nWhat's the square root of 2 mean?\r\n\r\n913\r\n01:03:35,344 --> 01:03:43,168\r\n意思就是我将用1作为2的平方根的一个猜测\r\nWell, that means I try 1 as a guess for the square root of 2.\r\n\r\n914\r\n01:03:46,528 --> 01:03:50,470\r\n然后我考虑 对于2的平方根来说 1是一个足够好的猜测么\r\nNow I look. I say, gee, is 1 a good enough guess for the square root of 2?\r\n\r\n915\r\n01:03:51,200 --> 01:03:53,240\r\n这取决于good-enough?是如何判断的\r\nAnd that depends on the test that \"good enough\" does.\r\n\r\n916\r\n01:03:54,160 --> 01:03:56,112\r\n本例中 good-enough?会说\r\nAnd in this case, \"good enough\" will say,\r\n\r\n917\r\n01:03:56,208 --> 01:03:58,600\r\n不 对于2的平方根来说 1不是一个足够好的猜测\r\nno, 1 is not a good enough guess for the square root of 2.\r\n\r\n918\r\n01:03:59,344 --> 01:04:07,770\r\n因此我会继续说 我试试一个改进值\r\nSo that will reduce to saying, I have to try an improved--\r\n\r\n919\r\n01:04:08,192 --> 01:04:12,180\r\n改进猜测值1\r\nimprove 1 as a guess for the square root of 2,\r\n\r\n920\r\n01:04:14,704 --> 01:04:17,010\r\n然后将其作为2的平方根的一个猜测\r\nand try that as a guess for the square root of 2.\r\n\r\n921\r\n01:04:18,688 --> 01:04:21,620\r\n改进猜测值1用作2的平方根\r\nImproving 1 as a guess for the square root of 2\r\n\r\n922\r\n01:04:21,648 --> 01:04:24,630\r\n也就是说我取1和2/1的平均值\r\nmeans I average 1 and 2 divided by 1.\r\n\r\n923\r\n01:04:26,656 --> 01:04:28,656\r\n因此我们将取平均数\r\nSo this is going to be average.\r\n\r\n924\r\n01:04:29,136 --> 01:04:38,990\r\n这段代码将会取1和2/1的平均数\r\nThis piece here will be the average of 1 and the quotient of 2 by 1.\r\n\r\n925\r\n01:04:40,384 --> 01:04:42,300\r\n那么这段代码\r\nThat's this piece here.\r\n\r\n926\r\n01:04:43,408 --> 01:04:46,270\r\n我算算 结果是1.5\r\nAnd I'm gonna try... And this is 1.5.\r\n\r\n927\r\n01:04:48,624 --> 01:04:53,952\r\n因此这个(sqrt 2)归约到(try 1 2)\r\nSo this square root of 2 reduces to trying 1 for the square root of 2,\r\n\r\n928\r\n01:04:54,112 --> 01:05:04,380\r\n然后归约到(try 1.5 2)\r\nwhich reduces to trying 1.5 as a guess for the square root of 2.\r\n\r\n929\r\n01:05:05,584 --> 01:05:07,616\r\n因此这行得通\r\nSo that makes sense.\r\n\r\n930\r\n01:05:07,664 --> 01:05:09,072\r\n让我们看下剩下的步骤\r\nLet's look at the rest of the process.\r\n\r\n931\r\n01:05:09,280 --> 01:05:14,550\r\n如果我尝试1.5 则会归约到\r\nIf I try 1.5, that reduces.\r\n\r\n932\r\n01:05:14,560 --> 01:05:18,608\r\n1.5作为2的平方根的猜测 并不是足够好\r\n1.5 turns out to be not good enough as a guess for the square root of 2.\r\n\r\n933\r\n01:05:19,776 --> 01:05:21,552\r\n然后又归约到\r\nSo that reduces to trying the average of\r\n\r\n934\r\n01:05:21,568 --> 01:05:25,720\r\n(try (average 1.5 (/ 2 1.5)))\r\n1.5 and 2 divided by 1.5 as a guess for the square root of 2.\r\n\r\n935\r\n01:05:27,840 --> 01:05:29,920\r\n平均值是1.333\r\nThat average turns out to be 1.333.\r\n\r\n936\r\n01:05:30,736 --> 01:05:34,790\r\n然后整个事又归约到(try 1.3333 2)\r\nSo this whole thing reduces to trying 1.333 as a guess for the square root of 2.\r\n\r\n937\r\n01:05:34,832 --> 01:05:35,616\r\n如此进行下去\r\nAnd then so on.\r\n\r\n938\r\n01:05:37,568 --> 01:05:41,216\r\n然后又归约到(good-enough? 1.4)或者其它的\r\nThat reduces to another called a \"good enough\", 1.4 something or other.\r\n\r\n939\r\n01:05:41,280 --> 01:05:44,020\r\n然后这个（步骤）会持续进行到\r\nAnd then it keeps going until the process finally stops\r\n\r\n940\r\n01:05:44,400 --> 01:05:47,472\r\ngood-enough?认为足够好了才停止\r\nwith something that \"good enough\" thinks is good enough, which,\r\n\r\n941\r\n01:05:47,520 --> 01:05:50,832\r\n本例中 是1.4242或者其它的东西\r\nin this case, is 1.4142 something or other.\r\n\r\n942\r\n01:05:52,064 --> 01:05:55,600\r\n因此这个这个过程运行得非常完美\r\nSo the process makes perfect sense.\r\n\r\n943\r\n01:05:59,488 --> 01:06:02,656\r\n这种定义方法叫做“递归定义”\r\nThis, by the way, is called a recursive definition.\r\n\r\n944\r\n01:06:13,952 --> 01:06:20,510\r\n进行递归定义将会给你带来无穷威力\r\nAnd the ability to make recursive definitions is a source of incredible power.\r\n\r\n945\r\n01:06:21,504 --> 01:06:22,608\r\n之前我已提到过\r\nAnd as you can already see I've hinted at,\r\n\r\n946\r\n01:06:22,640 --> 01:06:26,768\r\n递归定义可以在不增加任何负担的前提下\r\nit's the thing that effectively allows you to do these infinite computations\r\n\r\n947\r\n01:06:26,800 --> 01:06:28,380\r\n仅仅通过调用过程 在达到条件之前\r\nthat go on until something is true,\r\n\r\n948\r\n01:06:29,280 --> 01:06:33,216\r\n完成无限次的计算\r\nwithout having any other constricts other than the ability to call a procedure.\r\n\r\n949\r\n01:06:35,520 --> 01:06:37,020\r\n还有一点要说明的\r\nWell, let's see, there's one more thing.\r\n\r\n950\r\n01:06:37,264 --> 01:06:43,760\r\n我再在这里给你们演示另外一种平方根的定义方法\r\nLet me show you a variant of this definition of square root here on the slide.\r\n\r\n951\r\n01:06:43,984 --> 01:06:47,712\r\n这两种方法看起来像是一样的\r\nHere's sort of the same thing.\r\n\r\n952\r\n01:06:47,952 --> 01:06:51,040\r\n在这儿 我把improve、good-enough?、try的定义\r\nWhat I've done here is packaged the definitions of\r\n\r\n953\r\n01:06:51,072 --> 01:06:55,712\r\n全都封装在了sqrt里面\r\n\"improve\" and \"good enough\" and \"try\" inside \"square root\".\r\n\r\n954\r\n01:06:56,304 --> 01:07:00,544\r\n因此实际上 我们构建了一个平方根盒子\r\nSo, in effect, what I've done is I've built a square root box.\r\n\r\n955\r\n01:07:01,360 --> 01:07:08,080\r\n我构建了一个其它人可以使用的平方根盒子\r\nSo I've built a box that's the square root procedure that someone can use.\r\n\r\n956\r\n01:07:08,128 --> 01:07:11,024\r\n它们输入36 然后（盒子）输出6\r\nThey might put in 36 and get out 6.\r\n\r\n957\r\n01:07:11,360 --> 01:07:13,380\r\n但是 盒子里面封装的过程\r\nAnd then, packaged inside this box\r\n\r\n958\r\n01:07:13,712 --> 01:07:23,400\r\n就是try、good-enough?和improve的定义\r\nare the definitions of \"try\" and \"good enough\" and \"improve.\"\r\n\r\n959\r\n01:07:26,336 --> 01:07:27,904\r\n它们都隐藏在盒子里面\r\nSo they're hidden inside this box.\r\n\r\n960\r\n01:07:27,952 --> 01:07:30,310\r\n这样做是因为\r\nAnd the reason for doing that is that,\r\n\r\n961\r\n01:07:30,736 --> 01:07:32,400\r\n如果有人正在使用这个平方根\r\nif someone's using this square root,\r\n\r\n962\r\n01:07:32,768 --> 01:07:34,288\r\n如果George正在使用这个平方根\r\nif George is using this square root,\r\n\r\n963\r\n01:07:34,304 --> 01:07:36,910\r\nGeorge并不会关心\r\nGeorge probably doesn't care very much that,\r\n\r\n964\r\n01:07:37,840 --> 01:07:39,584\r\n当我在实现平方根时\r\nwhen I implemented square root,\r\n\r\n965\r\n01:07:39,760 --> 01:07:44,000\r\n我定义了盒子内的那些try、good-enough?和improve过程\r\nI had things inside there called \"try\" and \"good enough\" and \"improve\".\r\n\r\n966\r\n01:07:45,952 --> 01:07:48,880\r\n事实上 Harry可能会实现一个也具有\r\nAnd in fact, Harry might have a cube root procedure\r\n\r\n967\r\n01:07:48,928 --> 01:07:50,512\r\ntry、good-enough?和improve的立方根盒子\r\nthat has \"try\" and \"good enough\" and \"improve\".\r\n\r\n968\r\n01:07:50,992 --> 01:07:52,896\r\n因此 为了不让整个系统变得混乱\r\nAnd in order to not get the whole system confused,\r\n\r\n969\r\n01:07:52,912 --> 01:07:57,216\r\nHarry最好把这些内部过程封装在它的立方根过程里\r\nit'd be good for Harry to package his internal procedures inside his cube root procedure.\r\n\r\n970\r\n01:07:57,952 --> 01:07:59,616\r\n这个叫做块结构\r\nWell, this is called block structure,\r\n\r\n971\r\n01:07:59,872 --> 01:08:08,510\r\n这是把东西打包到定义内部的一种方法\r\nthis particular way of packaging internals inside of a definition.\r\n\r\n972\r\n01:08:09,520 --> 01:08:12,512\r\n让我们回过头来再看看\r\nAnd let's go back and look at the slide again.\r\n\r\n973\r\n01:08:12,672 --> 01:08:18,128\r\n这种过程的定义读作 定义“sqrt”为\r\nThe way to read this kind of procedure is to say, to define \"square root\",\r\n\r\n974\r\n01:08:19,424 --> 01:08:21,392\r\n那么 在其内部\r\nwell, inside that definition,\r\n\r\n975\r\n01:08:21,680 --> 01:08:25,040\r\n我们已有improve的定义\r\nI'll have the definition of an \"improve\" and\r\n\r\n976\r\n01:08:25,110 --> 01:08:28,432\r\n我们已有good-enough?和try的定义\r\nthe definition of \"good enough\" and the definition of \"try.\"\r\n\r\n977\r\n01:08:29,280 --> 01:08:31,930\r\n以及这些定义的实体\r\nAnd then, subject to those definitions,\r\n\r\n978\r\n01:08:32,032 --> 01:08:34,624\r\n我求平方根的定义实体是从1开始尝试\r\nthe way I do square root is to try 1.\r\n\r\n979\r\n01:08:35,630 --> 01:08:38,880\r\n注意这里 我不必将X当做参数传递\r\nAnd notice here, I don't have to say 1 as a guess for the square root of X,\r\n\r\n980\r\n01:08:39,424 --> 01:08:41,872\r\n因为它们都在平方根内部\r\nbecause since it's all inside the square root,\r\n\r\n981\r\n01:08:42,391 --> 01:08:44,201\r\n它相当于已知这个X了\r\nit sort of has this X known.\r\n\r\n982\r\n01:08:53,616 --> 01:08:55,920\r\n我来总结下\r\nLet me summarize.\r\n\r\n983\r\n01:08:56,048 --> 01:08:59,040\r\n我们从表述指令性知识\r\nWe started out with the idea that\r\n\r\n984\r\n01:08:59,060 --> 01:09:02,736\r\n开始学习\r\nwhat we're going to be doing is expressing imperative knowledge.\r\n\r\n985\r\n01:09:04,544 --> 01:09:09,296\r\n这张幻灯片总结了一些关于Lisp的知识\r\nAnd in fact, here's a slide that summarizes the way we looked at Lisp.\r\n\r\n986\r\n01:09:09,296 --> 01:09:14,670\r\n我们从基本元素如“+”和“*”开始\r\nWe started out by looking at some primitive elements in addition and multiplication,\r\n\r\n987\r\n01:09:15,408 --> 01:09:19,056\r\n一些用于测试某物小于或等于的谓词\r\nsome predicates for testing whether something is less-than or something's equal.\r\n\r\n988\r\n01:09:19,072 --> 01:09:22,544\r\n事实上 我们正在使用的系统掩盖了很多细节\r\nAnd in fact, we saw really sneakily in the system we're actually using,\r\n\r\n989\r\n01:09:22,576 --> 01:09:25,408\r\n这些并不是系统的基本元素 但这无所谓\r\nthese aren't actually primitives, but it doesn't matter.\r\n\r\n990\r\n01:09:26,176 --> 01:09:28,144\r\n重要的是我们会把它们当作是基本元素\r\nWhat matters is we're going to use them as if they're primitives.\r\n\r\n991\r\n01:09:28,160 --> 01:09:29,360\r\n我们不会去研究系统的内部\r\nWe're not going to look inside.\r\n\r\n992\r\n01:09:29,840 --> 01:09:32,700\r\n我们也有一些基本数据和一些数\r\nWe also have some primitive data and some numbers.\r\n\r\n993\r\n01:09:34,176 --> 01:09:37,216\r\n我们学习了合成的手段 组合的手段\r\nWe saw some means of composition, means of combination,\r\n\r\n994\r\n01:09:37,290 --> 01:09:40,928\r\n用运算符和运算对象合成函数\r\nthe basic one being composing functions and\r\n\r\n995\r\n01:09:40,960 --> 01:09:43,312\r\n和构建组合式的基本方法\r\nbuilding combinations with operators and operands.\r\n\r\n996\r\n01:09:44,368 --> 01:09:47,980\r\n还有一些像是“COND”、“if”和“define”的东西\r\nAnd there were some other things, like COND and \"if\" and \"define\".\r\n\r\n997\r\n01:09:50,848 --> 01:09:53,248\r\n具体来说 关于“define”的重点则是\r\nBut the main thing about \"define,\" in particular,\r\n\r\n998\r\n01:09:53,424 --> 01:09:55,264\r\n它是一种进行抽象的方法\r\nwas that it was the means of abstraction.\r\n\r\n999\r\n01:09:55,280 --> 01:09:57,250\r\n它是我们为某物命名的方法\r\nIt was the way that we name things.\r\n\r\n1000\r\n01:09:57,340 --> 01:09:59,856\r\n我们之前提到过  从这里也可以看出来\r\nYou can also see from this slide not only where we've been,\r\n\r\n1001\r\n01:10:01,120 --> 01:10:05,830\r\n有时候 我们需要研究如何通过组合基本数据来得到复合数据\r\nAt some point, we'll have to talk about how you combine primitive data to get compound data,\r\n\r\n1002\r\n01:10:06,112 --> 01:10:11,584\r\n以及如何抽象数据 使得你可以在一个更大的环境中\r\nand how you abstract data so you can use large globs of data\r\n\r\n1003\r\n01:10:11,616 --> 01:10:12,624\r\n将其当作基本数据使用\r\nas if they were primitive.\r\n\r\n1004\r\n01:10:13,456 --> 01:10:15,424\r\n这也是我们的目的所在\r\nSo that's where we're going.\r\n\r\n1005\r\n01:10:15,936 --> 01:10:21,600\r\n在我们讨论这个问题之前 下节课我们首先将会讨论\r\nBut before we do that, for the next couple of lectures we're going to be talking about,\r\n\r\n1006\r\n01:10:22,816 --> 01:10:26,310\r\n我们编写的过程与机器内部\r\nfirst of all, how it is that you make a link\r\n\r\n1007\r\n01:10:26,432 --> 01:10:30,320\r\n进程之间的联系\r\nbetween these procedures we write and the processes that happen in the machine.\r\n\r\n1008\r\n01:10:31,696 --> 01:10:35,530\r\n接着 我们将跳出小规模的计算问题\r\nAnd then, how it is that you start using the power of Lisp\r\n\r\n1009\r\n01:10:35,936 --> 01:10:39,328\r\n来学习如何发挥Lisp的威力\r\nto talk not only about these individual little computations,\r\n\r\n1010\r\n01:10:39,637 --> 01:10:43,701\r\n来解决更加通用的计算问题\r\nbut about general conventional methods of doing things.\r\n\r\n1011\r\n01:10:44,368 --> 01:10:45,720\r\n好了 大家还有什么问题么\r\nOK, are there any questions?\r\n\r\n1012\r\n01:10:46,304 --> 01:10:51,820\r\n学生：在定义A时 如果我们用一个括号将A括起来\r\nAUDIENCE: Yes. If we defined A using parentheses instead of as we did,\r\n\r\n1013\r\n01:10:51,872 --> 01:10:53,050\r\n会与不使用括号不同么？\r\nwhat would be the difference?\r\n\r\n1014\r\n01:10:53,152 --> 01:10:56,432\r\n教授：如果我这样写\r\nPROFESSOR: If I wrote this, if I wrote that,\r\n\r\n1015\r\n01:10:57,088 --> 01:11:01,680\r\n我则会是定义一个过程并命名为A\r\nwhat I would be doing is defining a procedure named A.\r\n\r\n1016\r\n01:11:02,768 --> 01:11:06,400\r\n本例中 这个过程没有参数\r\nIn this case, a procedure of no arguments, which,\r\n\r\n1017\r\n01:11:06,400 --> 01:11:09,160\r\n而当我运行它 则会返回5乘以5\r\nwhen I ran it, would give me back 5 times 5.\r\n\r\n1018\r\n01:11:10,624 --> 01:11:11,840\r\n学生：它们俩完成了相同的事\r\nAUDIENCE: Right. I mean, you come up with the same thing,\r\n\r\n1019\r\n01:11:11,872 --> 01:11:13,470\r\n但本质上是否相同？\r\nexcept for you really got a different--\r\n\r\n1020\r\n01:11:13,600 --> 01:11:16,180\r\n教授：好 的确会有不同 之前的那一个\r\nPROFESSOR: Right. And the difference would be, in the old one--\r\n\r\n1021\r\n01:11:16,576 --> 01:11:17,904\r\n我还是在这里写清楚一点吧\r\nLet me be a little bit clearer here.\r\n\r\n1022\r\n01:11:18,688 --> 01:11:22,992\r\n我们还是把这个叫做A\r\nLet's call this A, like here.\r\n\r\n1023\r\n01:11:23,680 --> 01:11:27,312\r\n作为对比 我们假装这里有一个\r\nAnd pretend here, just for contrast, I wrote,\r\n\r\n1024\r\n01:11:27,344 --> 01:11:37,110\r\n我定义D为5乘以5\r\ndefine D to be the product of 5 and 5.\r\n\r\n1025\r\n01:11:39,776 --> 01:11:41,120\r\n这两者的区别则是\r\nAnd the difference between those,\r\n\r\n1026\r\n01:11:41,510 --> 01:11:43,792\r\n让我们看看它们在Lisp解释器中是怎样的\r\nlet's think about interactions with the Lisp interpreter.\r\n\r\n1027\r\n01:11:45,296 --> 01:11:48,680\r\n我在Lisp中键入A 返回25\r\nI could type in A and Lisp would return 25.\r\n\r\n1028\r\n01:11:52,384 --> 01:11:57,360\r\n如果我仅仅键入D\r\nI could type in D, if I just typed in D,\r\n\r\n1029\r\n01:11:58,048 --> 01:12:05,104\r\nLisp返回复合过程D\r\nLisp would return compound procedure D,\r\n\r\n1030\r\n01:12:06,672 --> 01:12:08,680\r\n因为D就是一个过程\r\nbecause that's what it is. It's a procedure.\r\n\r\n1031\r\n01:12:09,248 --> 01:12:12,144\r\n我可以运行D 我可以问运行D的结果是什么\r\nI could run D. I could say, what's the value of running D?\r\n\r\n1032\r\n01:12:12,144 --> 01:12:14,780\r\n这是一个没有运算数的组合式\r\nHere is a combination with no operands.\r\n\r\n1033\r\n01:12:16,000 --> 01:12:18,620\r\n我考虑到它没有运算数 所以我在D后面没有键入任何东西\r\nI see there are no operands. I didn't put any after D.\r\n\r\n1034\r\n01:12:18,944 --> 01:12:20,890\r\nLisp则会说结果是25\r\nAnd it would say, oh, that's 25.\r\n\r\n1035\r\n01:12:22,560 --> 01:12:29,072\r\n我再说周全一点 如果我键入 A的运行结果是多少\r\nOr I could say, just for completeness, if I typed in, what's the value of running A?\r\n\r\n1036\r\n01:12:29,090 --> 01:12:30,120\r\n只能得到一个错误\r\nI get an error.\r\n\r\n1037\r\n01:12:31,344 --> 01:12:34,848\r\n跟这里的错误一样\r\nThe error would be the same one as over there.\r\n\r\n1038\r\n01:12:34,880 --> 01:12:40,060\r\n这个错误是因为 A的值——25\r\nIt'd be the error would say, sorry, 25, which is the value of A,\r\n\r\n1039\r\n01:12:40,112 --> 01:12:42,790\r\n并不是我可以应用于某物的运算符\r\nis not an operator that I can apply to something.\r\n\r\n1040\r\n01:12:43,392 --> 01:12:48,432\r\nMIT OpenCourseWare\r\nhttp://ocw.mit.edu\r\n\r\n1041\r\n01:12:48,688 --> 01:12:54,416\r\n本项目主页\r\nhttps://github.com/FoOTOo/Learning-SICP\r\n\r\n"
  },
  {
    "path": "SrtCN/lec1b.srt",
    "content": "﻿1\n00:00:01,840 --> 00:00:02,800\n哈尔滨工业大学 IBM技术中心\n倾情制作\n\n2\n00:00:02,800 --> 00:00:04,800\n压制&&特效：蔡钟毓（JohnTitor）\n字幕&&时间轴：曹竞帆（ChingfanTsou）\n\n3\n00:00:04,800 --> 00:00:06,800\n特别感谢：裘宗燕教授\n校对：匿名\n\n4\n00:00:08,920 --> 00:00:13,080\n过程及计算过程：\n代换模型\n\n5\n00:00:14,160 --> 00:00:14,700\n大家好\nHi.\n\n6\n00:00:15,960 --> 00:00:17,820\n大家都已经知道 程序员的工作\nYou've seen that the job of a programmer\n\n7\n00:00:19,060 --> 00:00:22,080\n就是设计出能够达成特定目标的程序\nis to design processes that accomplish particular goals,\n\n8\n00:00:23,400 --> 00:00:25,200\n比如求出一个数的平方根\nsuch as finding the square roots of numbers,\n\n9\n00:00:25,940 --> 00:00:27,720\n或者其它一些你想要做的事\nor other sorts of things you might want to do.\n\n10\n00:00:28,460 --> 00:00:30,140\n目前为止我们还没介绍别的什么东西\nWe haven't introduced anything else yet.\n\n11\n00:00:31,760 --> 00:00:32,370\n当然了\nOf course,\n\n12\n00:00:32,380 --> 00:00:35,310\n程序员完成工作的方式就是构造“咒语”\nthe way in which a programmer does this is by constructing spells,\n\n13\n00:00:36,080 --> 00:00:39,960\n通过过程和表达式构造出来的“咒语”\nwhich are constructed out of procedures and expressions.\n\n14\n00:00:40,700 --> 00:00:45,380\n这些“咒语”一定程度上指明了\nAnd that these spells are somehow direct a process\n\n15\n00:00:45,480 --> 00:00:47,680\n程序员想要的达成目标的方式\nto accomplish the goal that was intended by the programmer.\n\n16\n00:00:48,840 --> 00:00:50,660\n程序员为了使整个过程变得高效\nIn order for the programmer to do this effectively,\n\n17\n00:00:50,940 --> 00:00:52,660\n必须理解他写下的代码\nhe has to understand the relationship\n\n18\n00:00:52,880 --> 00:00:54,730\n这些“咒语”\nbetween the particular things that he writes,\n\n19\n00:00:54,800 --> 00:00:55,940\n和他想要控制的程序的行为\nthese particular spells,\n\n20\n00:00:56,200 --> 00:00:59,020\n之间的联系\nand the behavior of the process that he's attempting to control.\n\n21\n00:01:01,300 --> 00:01:03,180\n所以我们在这门课中要做的就是试图\nSo what we're doing this lecture is attempt to\n\n22\n00:01:03,180 --> 00:01:06,000\n以尽可能清晰的方式建立这样的联系\nestablish that connection in as clear a way as possible.\n\n23\n00:01:07,260 --> 00:01:09,330\n我们尤其要理解\nWhat we will particularly do is understand\n\n24\n00:01:09,330 --> 00:01:13,390\n特定过程和表达式的模式\nhow particular patterns of procedures and expressions\n\n25\n00:01:14,280 --> 00:01:16,210\n将会导致怎样的特定程序执行模式\ncause particular patterns of execution,\n\n26\n00:01:16,460 --> 00:01:19,000\n和计算过程的特定的行为\nparticular behaviors from the processes.\n\n27\n00:01:22,100 --> 00:01:23,230\n让我们开始吧\nLet's get down to that.\n\n28\n00:01:23,860 --> 00:01:25,770\n我将会从一个非常简单的程序开始\nI'm going to start with a very simple program.\n\n29\n00:01:27,920 --> 00:01:31,000\n这是一个计算两个数的平方和的程序\nThis is a program to compute the sum of the squares of two numbers.\n\n30\n00:01:33,320 --> 00:01:44,600\n我们将x和y的平方和定义为\nAnd we'll define the sum of the squares of x and y to be\n\n31\n00:01:45,700 --> 00:01:49,720\nx的平方\nthe sum of the square of x\n\n32\n00:01:49,720 --> 00:01:50,780\n我这么写\n-- I'm going to write it that way--\n\n33\n00:01:51,440 --> 00:01:53,630\n加上y的平方的和\nand the square of y,\n\n34\n00:01:56,260 --> 00:02:11,000\n这里的x的平方是指x和x的乘积\nwhere the square of x is the product of x and x.\n\n35\n00:02:13,840 --> 00:02:16,080\n现在 设想这么一件事\nNow,supposing I were to say something to this,\n\n36\n00:02:16,780 --> 00:02:19,970\n比如 在这个程序这么定义好之后\nlike,to the system after having defined these things,\n\n37\n00:02:20,180 --> 00:02:24,300\n跟据定义的形式 求3和4的平方和\nof the form,the sum of the squares of 3 and 4,\n\n38\n00:02:25,240 --> 00:02:28,560\n我希望得到25\nI am hoping that I will get out a 25.\n\n39\n00:02:29,120 --> 00:02:30,610\n因为3的平方是9\nBecause the square of 3 is 9,\n\n40\n00:02:30,610 --> 00:02:31,880\n4的平方是16\nand the square of 4 is 16,\n\n41\n00:02:32,580 --> 00:02:33,970\n它们的和是25\nand 25 is the sum of those.\n\n42\n00:02:34,980 --> 00:02:35,960\n但这都是怎么回事呢\nBut how does that happen?\n\n43\n00:02:36,380 --> 00:02:39,660\n如果我们要理解程序的执行以及它的控制方法\nIf we're going to understand processes and how we control them,\n\n44\n00:02:39,660 --> 00:02:45,060\n那么我们就得把过程的机制\nthen we have to have a mapping from the mechanisms of this procedure\n\n45\n00:02:45,680 --> 00:02:48,260\n与过程执行时所产生的行为对应起来\ninto the way in which these processes behave.\n\n46\n00:02:49,160 --> 00:02:50,720\n我们将要得到的是一个正式的\nWhat we're going to have is a formal,\n\n47\n00:02:50,960 --> 00:02:53,140\n或者说半正式的机械的模型\nor semi-formal mechanical model,\n\n48\n00:02:53,820 --> 00:02:57,280\n你要理解计算机如何事实上 大体上实现这个机制\nwhereby you understand how a machine could,in fact,in principle,do this.\n\n49\n00:02:57,600 --> 00:03:00,060\n不论实际的计算机究竟是怎么实现的\nWhether or not the actual machine really does\n\n50\n00:03:00,080 --> 00:03:02,720\n我此刻要告诉你们的都与实际的实现完全没有关系\nwhat I'm about to tell you is completely irrelevant at this moment.\n\n51\n00:03:03,490 --> 00:03:04,920\n实际上 这是一个工程模型\nIn fact,this is an engineering model\n\n52\n00:03:05,440 --> 00:03:07,630\n就好像电阻\nin the same way that,electrical resistor,\n\n53\n00:03:07,840 --> 00:03:09,810\n我们写出一个模型V=IR\nwe write down a model v equals i r,\n\n54\n00:03:10,360 --> 00:03:11,410\n这大致正确\nit's approximately true.\n\n55\n00:03:12,020 --> 00:03:13,060\n但不完全正确的\nIt's not really true.\n\n56\n00:03:13,540 --> 00:03:15,450\n当电流通过电阻时 电阻会增加\nIf I put up current through the resistor it goes boom.\n\n57\n00:03:16,560 --> 00:03:19,820\n所以电压并不总与电流成线性关系\nSo the voltage is not always proportional to the current,\n\n58\n00:03:20,120 --> 00:03:23,220\n但是对于部分情况来说这个模型是适用的\nbut for some purposes the model is appropriate.\n\n59\n00:03:23,860 --> 00:03:26,260\n比如我们将要介绍的这个模型\nIn particular,the model we're going to describe right now,\n\n60\n00:03:26,260 --> 00:03:27,850\n我把这个模型称作代换模型\nwhich I call the substitution model,\n\n61\n00:03:28,180 --> 00:03:30,280\n这是我们能接触到的最简单的模型\nis the simplest model that we have\n\n62\n00:03:30,500 --> 00:03:33,020\n它可以帮助我们理解过程和程序执行的原理\nfor understanding how procedures work and how processes work.\n\n63\n00:03:33,770 --> 00:03:35,470\n以及过程如何使得程序执行\nHow procedures yield processes.\n\n64\n00:03:36,000 --> 00:03:38,110\n代换模型 对接下来几天\nAnd that substitution model will be accurate\n\n65\n00:03:38,240 --> 00:03:40,770\n我们将要接触到的东西都是适用的\nfor most of the things we'll be dealing with in the next few days.\n\n66\n00:03:41,580 --> 00:03:45,490\n但最终 幻想总会破灭\nBut eventually,it will become impossible to sustain the illusion\n\n67\n00:03:45,500 --> 00:03:46,250\n如果你认为计算机实际就是这么工作的\nthat that's the way the machine works,\n\n68\n00:03:46,490 --> 00:03:49,600\n并且我们将要学习其它的更特殊的模型\nand we'll go to other more specific and particular models\n\n69\n00:03:49,920 --> 00:03:51,020\n届时会讨论更多的细节\nthat will show more detail.\n\n70\n00:03:53,200 --> 00:03:57,640\n好了 接下来 我们来看下\nOK,well,the first thing,of course,is we say,\n\n71\n00:03:57,640 --> 00:03:58,780\n黑板上的这些内容\nwhat are the things we have here?\n\n72\n00:03:58,780 --> 00:04:00,030\n这里已经有了一些神秘的符号\nWe have some cryptic symbols.\n\n73\n00:04:00,900 --> 00:04:03,770\n这些神秘的符号是由几块组成的\nAnd these cryptic symbols are made out of pieces.\n\n74\n00:04:04,090 --> 00:04:05,380\n还有几种表达式\nThere are kinds of expressions.\n\n75\n00:04:05,720 --> 00:04:08,100\n现在我们看一看都有哪些类型的表达式\nSo let's write down here the kinds of expressions there are.\n\n76\n00:04:17,580 --> 00:04:18,180\n有\nAnd we have--\n\n77\n00:04:18,260 --> 00:04:20,180\n首先有数字\nand so far I see things like numbers.\n\n78\n00:04:25,060 --> 00:04:27,550\n有像那样的符号\nI see things like symbols like that.\n\n79\n00:04:31,790 --> 00:04:34,940\n我们之前见过Lambda表达式\nWe have seen things before like lambda expressions,\n\n80\n00:04:34,940 --> 00:04:36,760\n当然了没出现在黑板上 先撇开不谈\nbut they're not here.I'm going to leave them out.\n\n81\n00:04:36,800 --> 00:04:39,260\nLambda表达式 稍后再讨论\nLambda expressions,we'll worry about them later.\n\n82\n00:04:44,500 --> 00:04:45,640\n还有定义\nThings like definitions.\n\n83\n00:04:51,550 --> 00:04:52,660\n还有条件表达式\nThings like conditionals.\n\n84\n00:04:58,040 --> 00:05:00,050\n最后还有组合式\nAnd finally,things like combinations.\n\n85\n00:05:06,660 --> 00:05:09,050\n这些表达式\nThese kinds of expressions are\n\n86\n00:05:10,090 --> 00:05:14,090\n我们稍后再讨论 它们是特殊形式\n-- I'll worry about later-- these are special forms.\n\n87\n00:05:14,740 --> 00:05:16,920\n它们有一些专门的规则\nThere are particular rules for each of these.\n\n88\n00:05:17,320 --> 00:05:20,420\n然而我要告诉你们的是 处理通常情况的规则\nI'm going to tell you,however,the rules for doing a general case.\n\n89\n00:05:20,750 --> 00:05:22,370\n通常是怎样对一个组合式求值的\nHow does one evaluate a combination?\n\n90\n00:05:23,200 --> 00:05:24,370\n因为 实际上 在黑板的那边\nBecause,in fact,over here,\n\n91\n00:05:24,760 --> 00:05:27,800\n全都是一些组合式以及一些符号和数字\nall I really have are combinations and some symbols and numbers.\n\n92\n00:05:28,990 --> 00:05:30,610\n而简单的 比如一个数字\nAnd the simple things like a number,well,\n\n93\n00:05:30,610 --> 00:05:32,090\n求值的结果就是这个数字所代表的数值\nit will evaluate to itself.\n\n94\n00:05:33,000 --> 00:05:34,680\n在我将要介绍的模型中\nIn the model I will have for you,\n\n95\n00:05:34,700 --> 00:05:35,860\n符号的概念将不会出现\nthe symbols will disappear.\n\n96\n00:05:36,810 --> 00:05:39,450\n只有当你需要了解\nThey won't be there at the time when you need them,\n\n97\n00:05:39,450 --> 00:05:40,970\n当你需要真正理解它的时候才讨论\nwhen you need to get at them.\n\n98\n00:05:41,420 --> 00:05:43,530\n所以我只需要向大家讲解\nSo the only thing I really have to explain to you is,\n\n99\n00:05:43,530 --> 00:05:44,850\n如何对组合式求值\nhow do we evaluate combinations?\n\n100\n00:05:47,950 --> 00:05:49,010\n好吧 继续\nOK,let's see\n\n101\n00:05:50,010 --> 00:05:52,540\n先看下第一张幻灯片\nSo first I want to get the first slide.\n\n102\n00:05:53,310 --> 00:05:58,440\n这是对一个表达式求值的规则\nHere is the rule for evaluating an application.\n\n103\n00:06:01,040 --> 00:06:06,140\n我们看到这条规则指出\nWhat we have is a rule that says,\n\n104\n00:06:06,140 --> 00:06:07,050\n要对一个组合式求值\nto evaluate a combination,\n\n105\n00:06:07,050 --> 00:06:08,900\n主要有三个部分\nthere are two parts,three parts to the rule.\n\n106\n00:06:09,540 --> 00:06:11,790\n组合式有若干个部分\nThe combination has several parts.\n\n107\n00:06:12,020 --> 00:06:15,090\n有运算符和运算对象\nIt has operators and it has operands.\n\n108\n00:06:16,420 --> 00:06:19,060\n运算符返回一个过程\nThe operator returns into a procedure.\n\n109\n00:06:19,810 --> 00:06:20,910\n也就是说如果我们对运算符求值\nIf we evaluate the operator,\n\n110\n00:06:20,930 --> 00:06:21,890\n结果是一个过程\nwe will get a procedure.\n\n111\n00:06:22,100 --> 00:06:23,200\n比如你们也看到了\nAnd you saw,for example,\n\n112\n00:06:23,200 --> 00:06:24,980\n我向计算机输入一个“+”\nhow I'll type \"+\" at the machine\n\n113\n00:06:24,980 --> 00:06:27,170\n然后产生了一些复合的过程以及其它的一些东西\nand out came compound procedure something or other.\n\n114\n00:06:28,520 --> 00:06:30,260\n而对运算对象求值就会得到参数\nAnd the operands produce arguments.\n\n115\n00:06:31,620 --> 00:06:35,250\n一旦我们完成了对运算符的求值得到了一个过程\nOnce we've gotten the operator evaluated to get a procedure,\n\n116\n00:06:35,250 --> 00:06:37,540\n并且对运算对象也完成求值得到了参数\nand the argument is evaluated to get argument\n\n117\n00:06:37,550 --> 00:06:39,090\n也就是运算对象作为参数的值\n-- the operand's value to get arguments--\n\n118\n00:06:39,090 --> 00:06:41,170\n我们通过复制过程体\nwe apply the procedure to these arguments\n\n119\n00:06:41,880 --> 00:06:43,950\n来将其应用到这些参数上\nby copying the body of the procedure,\n\n120\n00:06:44,240 --> 00:06:46,940\n用术语来说 过程体指的就是定义这个过程的表达式\nwhich is the expression that the procedure is defined in terms of.\n\n121\n00:06:47,220 --> 00:06:48,570\n接下来要做的是\nWhat is it supposed to do?\n\n122\n00:06:49,280 --> 00:06:53,950\n用求得的实际参数代换过程的形式参数\nSubstituting the argument supplied for the formal parameters of the procedure,\n\n123\n00:06:54,680 --> 00:06:56,220\n形式参数就是\nthe formal parameters being the names\n\n124\n00:06:56,220 --> 00:06:58,220\n过程定义中声明的变量名\ndefined by the declaration of the procedure.\n\n125\n00:06:58,760 --> 00:07:00,850\n然后我们对产生的新过程体求值\nThen we evaluate the resulting new body,\n\n126\n00:07:01,020 --> 00:07:04,770\n这个新过程体是由将代换模型应用到之前的过程体而产生的\nthe body resulting from copying the old body with the substitutions made.\n\n127\n00:07:06,990 --> 00:07:08,270\n这个规则非常简单\nIt's a very simple rule,\n\n128\n00:07:09,370 --> 00:07:11,650\n并且我们会非常形式化地应用这个规则一段时间\nand we're going to do it very formally for a little while.\n\n129\n00:07:11,980 --> 00:07:14,420\n因为接下来几节课\nBecause for the next few lectures,\n\n130\n00:07:14,730 --> 00:07:15,740\n我想让各位做的是\nwhat I want you to do is to say,\n\n131\n00:07:15,740 --> 00:07:18,930\n如果有什么不能理解的\nif I don't understand something,if I don't understand something,\n\n132\n00:07:19,280 --> 00:07:20,930\n就直接机械化地应用这个规则\nbe very mechanical and do this.\n\n133\n00:07:23,570 --> 00:07:24,160\n接下来\nSo let's see.\n\n134\n00:07:25,970 --> 00:07:27,630\n考虑这么一个求值过程\nLet's consider a particular evaluation,\n\n135\n00:07:27,740 --> 00:07:28,990\n之前讨论过的\nthe one we were talking about before.\n\n136\n00:07:29,210 --> 00:07:32,960\n3和4的平方和\nThe sum of the squares of 3 and 4.\n\n137\n00:07:35,560 --> 00:07:36,660\n这是什么意思呢\nWhat does that mean?\n\n138\n00:07:36,660 --> 00:07:37,760\n这是说\nIt says,take\n\n139\n00:07:38,260 --> 00:07:40,660\n其实 我已经知道求平方的过程是怎样的\n-- well,I could find out what's on the square--\n\n140\n00:07:40,660 --> 00:07:41,860\n是某个过程\nit's some procedure,\n\n141\n00:07:42,140 --> 00:07:43,710\n但我并不关心这个过程的具体表述\nand I'm not going to worry about the representation,\n\n142\n00:07:43,710 --> 00:07:45,710\n并且我也不会在黑板上写出来\nand I'm not going to write it on the blackboard for you.\n\n143\n00:07:46,810 --> 00:07:48,530\n还有3 代表某个数字\nAnd I have that 3,represents some number,\n\n144\n00:07:49,250 --> 00:07:51,360\n但如果要我重复这个数字\nbut if I have to repeat that number,\n\n145\n00:07:51,360 --> 00:07:52,280\n我并不知道这个数字是什么\nI can't tell you the number.\n\n146\n00:07:52,410 --> 00:07:54,190\n这个数字本身是抽象的\nThe number itself is some abstract thing.\n\n147\n00:07:54,490 --> 00:07:55,860\n只知道有个数词能代表它\nThere's a numeral which represents it,\n\n148\n00:07:55,890 --> 00:07:56,690\n我把这个它叫作3\nwhich I'll call 3,\n\n149\n00:07:56,960 --> 00:07:59,000\n并且会在代换中用到它\nand I'll use that in my substitution.\n\n150\n00:07:59,370 --> 00:08:01,400\n4也是个数字\nAnd 4 is also a number.\n\n151\n00:08:01,570 --> 00:08:07,680\n我在这个过程体中用3代换x 用4代换y\nI'm going to substitute 3 for x and 4 for y in the body of this procedure\n\n152\n00:08:07,680 --> 00:08:08,570\n看黑板这里\nthat you see over here.\n\n153\n00:08:09,170 --> 00:08:10,580\n这是过程体\nHere's the body of the procedure.\n\n154\n00:08:11,180 --> 00:08:13,780\n它关联到这个组合式\nIt corresponds to this combination,\n\n155\n00:08:13,790 --> 00:08:14,520\n这个组合式是个求和过程\nwhich is an addition.\n\n156\n00:08:17,160 --> 00:08:18,480\n而它就转化成这样一个过程\nSo what that reduces to,\n\n157\n00:08:18,820 --> 00:08:19,870\n我们把这个转化\nas a reduction step,\n\n158\n00:08:19,870 --> 00:08:20,370\n称为归约\nwe call it,\n\n159\n00:08:20,670 --> 00:08:28,740\n这样就变成了求3和4的平方和\nit's the sum of the square of 3 and the square of 4.\n\n160\n00:08:30,000 --> 00:08:33,710\n接下来我要做的是\nNow,what's the next step I have to do here?\n\n161\n00:08:33,710 --> 00:08:35,710\n对它求值\nI say,well,I have to evaluate this.\n\n162\n00:08:35,710 --> 00:08:37,010\n根据之前给出的求值规则\nAccording to my rule,\n\n163\n00:08:37,010 --> 00:08:40,640\n就是各位刚刚在幻灯片上看到的\nwhich you just saw on that overhead or slide,\n\n164\n00:08:41,410 --> 00:08:45,780\n我们要对运算对象求值\nwhat we had was that we have to evaluate the operands\n\n165\n00:08:45,930 --> 00:08:47,080\n就是这些运算对象\n-- and here are the operands,\n\n166\n00:08:47,340 --> 00:08:49,080\n这是第一个运算对象 这是第二个运算对象\nhere's one and here's the next operand--\n\n167\n00:08:49,400 --> 00:08:50,770\n我们还得对运算符求值\nand how we have to evaluate procedure.\n\n168\n00:08:50,770 --> 00:08:51,850\n对它们求值的顺序无关紧要\nThe order doesn't matter.\n\n169\n00:08:52,510 --> 00:08:55,710\n然后我们要应用这个过程\nAnd then we're going to apply the procedure,\n\n170\n00:08:55,710 --> 00:08:56,280\n即求和过程\nwhich is plus,\n\n171\n00:08:56,280 --> 00:08:58,620\n然后很神奇的 不知怎么回事就能得到答案\nand magically somehow that's going to produce the answer.\n\n172\n00:08:58,880 --> 00:09:01,050\n我不会深究求和过程的实现\nI'm not to open up plus and look inside of it.\n\n173\n00:09:02,140 --> 00:09:04,500\n然而 为了对运算对象求值\nHowever,in order to evaluate the operand,\n\n174\n00:09:04,510 --> 00:09:05,970\n我们采用任意一种顺序来求值\nlet's pick some arbitrary order and do them.\n\n175\n00:09:06,430 --> 00:09:07,580\n我会从右到左求值\nI'm going to go from right to left.\n\n176\n00:09:08,190 --> 00:09:09,840\n好了 为了对这个运算对象求值\nWell,in order to evaluate this operand,\n\n177\n00:09:09,840 --> 00:09:13,410\n我得用同样的规则对这运算对象的每个部分求值\nI have to evaluate the parts of it by the same rule.\n\n178\n00:09:13,970 --> 00:09:15,850\n首先需要弄清楚求平方是什么\nAnd the parts are I have to find out what square is--\n\n179\n00:09:15,850 --> 00:09:16,580\n是某个过程\nit's some procedure,\n\n180\n00:09:16,580 --> 00:09:18,120\n有个形式参数x\nwhich has a formal parameter x.\n\n181\n00:09:19,180 --> 00:09:22,580\n然后还有个运算对象是4\nAnd also,I have an operand which is 4,\n\n182\n00:09:23,560 --> 00:09:27,550\n用4代换求平方过程的形式参数x\nwhich I have to substitute for x in the body of square.\n\n183\n00:09:28,410 --> 00:09:30,370\n接下来基本上可以这么说\nSo the next step is basically to say that\n\n184\n00:09:30,370 --> 00:09:38,180\n这就变成了求3的平方以及4与4乘积的和\nthis is the sum of the square of 3 and the product of 4 and 4.\n\n185\n00:09:40,600 --> 00:09:43,710\n当然了 还可以接着深入分析乘法\nOf course,I could open up asterisk if I liked\n\n186\n00:09:43,720 --> 00:09:45,970\n这个求乘积的操作\n-- the multiplication operation--\n\n187\n00:09:46,680 --> 00:09:47,480\n但现在这个不重要\nbut I'm not going to do that.\n\n188\n00:09:47,500 --> 00:09:48,610\n先把乘法过程看作是基本过程\nI'm going to consider that primitive.\n\n189\n00:09:49,790 --> 00:09:53,250\n其实 如果你深究计算机的抽象层次\nSo,and,of course,at any level of detail,if you look inside this machine,\n\n190\n00:09:53,250 --> 00:09:54,320\n你会发现无论在具体哪一个层次\nyou're going to find that\n\n191\n00:09:54,320 --> 00:09:56,820\n在其下都还有若干个你不清楚的抽象层次\nthere's multiple levels below that that you don't know about.\n\n192\n00:09:57,980 --> 00:10:00,650\n但我们必须明白要学会忽略细节\nBut one of the things we have to learn how to do is ignore details.\n\n193\n00:10:01,980 --> 00:10:03,960\n理解复杂事物的关键是\nThe key to understanding complicated things\n\n194\n00:10:04,280 --> 00:10:08,290\n避免不必要的观察 计算和思考\nis to know what not to look at and what not compute and what not to think.\n\n195\n00:10:09,260 --> 00:10:10,840\n所以对这个乘法过程的细节我们不深入研究\nSo we're going to stop this one here and say,\n\n196\n00:10:10,840 --> 00:10:13,560\n就直接看作两个数的乘积\noh,yes,this is the product of two things.\n\n197\n00:10:13,970 --> 00:10:15,000\n现在把两个4乘起来\nWe're going to do it now.\n\n198\n00:10:15,660 --> 00:10:22,320\n于是就有3的平方与16的和\nSo this is nothing more than the sum of the square of 3 and 16.\n\n199\n00:10:22,960 --> 00:10:25,640\n还有一个求平方的表达式要求值\nAnd now I have another thing I have to evaluate,\n\n200\n00:10:27,010 --> 00:10:28,120\n注意这是3的平方\nbut that square of 3,\n\n201\n00:10:28,120 --> 00:10:29,080\n这与之前求4的平方是一个过程\nwell,it's the same thing.\n\n202\n00:10:29,080 --> 00:10:35,200\n于是整个表达式就变成了求3和3乘积与16的和\nThat's the sum of the product of 3 and 3 and 16,\n\n203\n00:10:35,960 --> 00:10:41,810\n也就是求9和16的和 结果是25\nwhich is the sum of 9 and 16,which is 25.\n\n204\n00:10:44,500 --> 00:10:48,570\n大家现在看到了应用代换模型的基本方法\nSo now you see the basic method of doing substitutions.\n\n205\n00:10:49,800 --> 00:10:51,730\n但我提醒大家\nAnd I warn you that\n\n206\n00:10:52,110 --> 00:10:55,410\n代换模型并不能准确描述计算机实际的运行方式\nthis is not a perfect description of what the computer does.\n\n207\n00:10:56,800 --> 00:10:58,200\n但这个模型对于接下来几节课我们要讨论的问题\nBut it's a good enough description\n\n208\n00:10:58,200 --> 00:11:02,000\n已经可以描述得足够清楚\nfor the problems that we're going to have in the next few lectures\n\n209\n00:11:02,510 --> 00:11:04,120\n你可以先认为这是正确的\nthat you should think about this religiously.\n\n210\n00:11:04,820 --> 00:11:07,230\n认为计算机就是这么运行的\nAnd this is how the machine works for now.\n\n211\n00:11:07,520 --> 00:11:08,920\n之后我们的讨论会变得更加严谨\nLater we'll get more detailed.\n\n212\n00:11:11,700 --> 00:11:12,280\n好了 现在可以看到\nNow,of course,\n\n213\n00:11:12,280 --> 00:11:15,020\n我在这个例子中采用了从右到左的求值顺序\nI made a specific choice of the order of evaluation here.\n\n214\n00:11:15,530 --> 00:11:16,530\n当然还有别的选择\nThere are other possibilities.\n\n215\n00:11:17,020 --> 00:11:20,580\n如果我们回过头来再看幻灯片\nIf we go back to this,ah,to the telestrator here\n\n216\n00:11:20,580 --> 00:11:21,870\n上所写的代换模型应用规则\nand look at the substitution rule,\n\n217\n00:11:22,800 --> 00:11:25,650\n可以发现刚才我对运算符求值得到了一个过程\nwe see that I evaluated the operator to get the procedures,\n\n218\n00:11:25,900 --> 00:11:28,690\n对运算对象求值得到了过程的实际参数\nand I evaluated the operands to get the arguments first,\n\n219\n00:11:28,690 --> 00:11:29,950\n然后才将参数应用到过程\nbefore I do the application.\n\n220\n00:11:30,730 --> 00:11:32,030\n这样做是完全可行的\nIt's entirely possible,\n\n221\n00:11:32,030 --> 00:11:34,650\n还有别的求值顺序比如正则序求值\nand there are alternate rules called normal order evaluation\n\n222\n00:11:35,020 --> 00:11:37,470\n应用正则序你可以先用表达式去代换\nwhereby you can do the substitution of the expressions\n\n223\n00:11:37,470 --> 00:11:44,640\n将其作为过程的形式参数的运算对象 然后再求值\nwhich are the operands for the formal parameters inside the body first.\n\n224\n00:11:45,970 --> 00:11:47,650\n这么做会得到同样的答案\nAnd you'll get also the same answer.\n\n225\n00:11:48,560 --> 00:11:50,110\n但是现在 考虑到实际情况\nBut right now,for concreteness,\n\n226\n00:11:50,110 --> 00:11:52,240\n因为计算机实际是这么运行的\nand because this is the way our machine really does it,\n\n227\n00:11:52,900 --> 00:11:54,000\n我还是会给出在黑板上演示的方式\nI'm going to give you this rule,\n\n228\n00:11:54,000 --> 00:11:55,130\n这种方式给出了明确的顺序\nwhich has a particular order.\n\n229\n00:11:56,120 --> 00:11:58,140\n当然了这些顺序一定程度上也是灵活可变的\nBut that order is to some extent arbitrary,too.\n\n230\n00:11:59,620 --> 00:12:01,340\n归根到底\nIn the long run,in the long run,\n\n231\n00:12:01,340 --> 00:12:03,760\n采用哪种求值顺序来理解\n都有各自的依据\nthere are some reasons why you might pick one order or another,\n\n232\n00:12:03,760 --> 00:12:05,760\n以后我们会继续讨论这个问题\nand we'll get to that later in the subject.\n\n233\n00:12:11,930 --> 00:12:15,130\n好了 为了让大家理解这都是怎么回事\nOK,well now the only other thing I have to tell you about\n\n234\n00:12:15,150 --> 00:12:16,420\n还需要给大家介绍一个东西\nejust to understand what's going on\n\n235\n00:12:16,440 --> 00:12:18,670\n来看幻灯片上对条件表达式的解释\nis let's look at the rule for conditionals.\n\n236\n00:12:19,470 --> 00:12:21,620\n条件表达式很简单\nConditionals are very simple,\n\n237\n00:12:22,490 --> 00:12:25,440\n我给大家详细解释一下\nand I'd like to examine this.\n\n238\n00:12:26,890 --> 00:12:31,380\n条件表达式就是if表达式\nA conditional is something that is if\n\n239\n00:12:31,980 --> 00:12:33,380\n当然还有cond表达式\n-- there's also cond of course--\n\n240\n00:12:33,570 --> 00:12:35,700\n我会把条件表达式各部分的名称都写下来\nbut I'm going to give names to the parts of the expression.\n\n241\n00:12:35,700 --> 00:12:36,490\n首先有一个判断表达式\nThere's a predicate,\n\n242\n00:12:38,080 --> 00:12:40,050\n这是个求值结果为真或假的表达式\nwhich is a thing that is either true or false.\n\n243\n00:12:41,010 --> 00:12:42,010\n然后有一个结果子句\nAnd there's a consequent,\n\n244\n00:12:45,600 --> 00:12:47,490\n当判断表达式的结果为真就对这个表达式求值\nwhich is the thing you do if the predicate is true.\n\n245\n00:12:48,010 --> 00:12:49,020\n还有个选择表达式\nAnd there's an alternative,\n\n246\n00:12:52,520 --> 00:12:54,610\n当判断表达式结果为假\n就对这个表达式求值\nwhich is the thing you do if the predicate is false.\n\n247\n00:12:55,090 --> 00:12:56,350\n顺便提一句\nIt's important,by the way,\n\n248\n00:12:56,760 --> 00:12:59,960\n知道事物各部分的名称\nto get names for,to get names for,\n\n249\n00:13:00,260 --> 00:13:01,390\n或者表达式各部分的名称\nthe parts of things,\n\n250\n00:13:01,390 --> 00:13:02,730\n很重要\nor the parts of expressions.\n\n251\n00:13:03,420 --> 00:13:05,660\n每个“魔法师”都会告诉你\nOne of the things that every sorcerer will tell you\n\n252\n00:13:05,690 --> 00:13:07,140\n如果你能叫出一个“精灵”的名字\nis if you have the name of a spirit,\n\n253\n00:13:07,140 --> 00:13:08,110\n你就有控制它的能力\nyou have power over it.\n\n254\n00:13:10,050 --> 00:13:11,080\n所以你得掌握这些名称\nSo you have to learn these names\n\n255\n00:13:11,080 --> 00:13:12,560\n以便之后的讨论\nso that we can discuss these things.\n\n256\n00:13:13,370 --> 00:13:15,410\n现在我们有了一个判断表达式\nSo here we have a predicate,\n\n257\n00:13:15,410 --> 00:13:16,100\n一个结果表达式\na consequent,\n\n258\n00:13:16,100 --> 00:13:16,810\n还有个选择表达式\nand an alternative.\n\n259\n00:13:17,420 --> 00:13:21,060\n用这些名称 我们发现对于一个if表达式\nAnd,using such words,we see that an if expression,\n\n260\n00:13:21,360 --> 00:13:23,500\n关键的问题是对判断表达式的求值\nthe problems you evaluate to the predicate expression,\n\n261\n00:13:24,360 --> 00:13:25,580\n如果结果为真\nif that yields true,\n\n262\n00:13:26,840 --> 00:13:28,860\n就对结果表达式求值\nthen you then go on to evaluate the consequent.\n\n263\n00:13:29,280 --> 00:13:31,920\n否则 就对选择表达式求值\nOtherwise,you evaluate the alternative expression.\n\n264\n00:13:34,530 --> 00:13:35,840\n我想通过一个具体的程序\nSo I'd like to illustrate that\n\n265\n00:13:36,170 --> 00:13:42,250\n来进一步说明这个问题\nnow in the context of a particular,of a particular,little program.\n\n266\n00:13:43,200 --> 00:13:45,280\n就写一个我们会经常遇到的程序吧\nGoing to write down a program which we're going to see many times.\n\n267\n00:13:51,470 --> 00:13:58,430\n这是由皮亚诺算术定义的求x和y之和的过程\nThis is the sum of x and y done by what's called Peano arithmetic,\n\n268\n00:13:58,430 --> 00:14:00,430\n其实就是加1和减1\nwhich is all we're doing is incrementing and decrementing.\n\n269\n00:14:01,500 --> 00:14:02,660\n来看看这个\nAnd we're going to see this for a little bit.\n\n270\n00:14:02,660 --> 00:14:03,980\n这是个非常重要的程序\nIt's a very important program.\n\n271\n00:14:06,020 --> 00:14:07,120\n如果x等于0\nIf x equals 0,\n\n272\n00:14:09,680 --> 00:14:11,260\n那么结果就是y\nthen the result is y.\n\n273\n00:14:11,580 --> 00:14:12,270\n否则\nOtherwise,\n\n274\n00:14:12,270 --> 00:14:20,350\n结果就是x减1与y加1的和\nthis is the sum of the decrement of x and the increment of y.\n\n275\n00:14:23,220 --> 00:14:26,110\n以后我们会继续研究这个加法过程\nWe're going to look at this a lot more in the future.\n\n276\n00:14:27,580 --> 00:14:28,740\n现在看前面\nLet's look at the overhead.\n\n277\n00:14:28,980 --> 00:14:31,090\n现在有了这么个过程\nSo here we have this procedure,\n\n278\n00:14:31,090 --> 00:14:33,180\n我们看看怎么应用代换模型\nand we're going to look at how we do the substitutions,\n\n279\n00:14:33,180 --> 00:14:34,270\n以及代换的顺序\nthe sequence of substitutions.\n\n280\n00:14:35,760 --> 00:14:37,700\n我现在想要求3和4的和\nWell,I'm going to try and add together 3 and 4.\n\n281\n00:14:38,280 --> 00:14:40,200\n根据我演示给大家步骤\nWell,using the first rule that I showed you,\n\n282\n00:14:40,420 --> 00:14:43,900\n第一步 在过程体中\nwe substitute 3 for x and 4 four y\n\n283\n00:14:44,180 --> 00:14:45,620\n用3代换x 用4代换y\nin the body of this procedure.\n\n284\n00:14:45,800 --> 00:14:47,360\n过程体\nThe body of the procedure is the thing\n\n285\n00:14:47,360 --> 00:14:49,690\n由if表达式开始 在这儿结束\nthat begins with if and finishes over here.\n\n286\n00:14:51,020 --> 00:14:51,940\n于是我们就有了\nSo what we get is,\n\n287\n00:14:51,940 --> 00:14:53,390\n如果3是0\nof course,if 3 is 0,\n\n288\n00:14:53,390 --> 00:14:54,600\n那么结果就是4\nthen the result is 4.\n\n289\n00:14:55,570 --> 00:14:56,350\n否则\nOtherwise,\n\n290\n00:14:56,450 --> 00:14:58,360\n结果就是3减1\nit's the sum of the decrement of 3\n\n291\n00:14:58,360 --> 00:14:59,320\n与4加1的和\nand the increment of 4.\n\n292\n00:15:01,080 --> 00:15:02,490\n但这部份我不会去管它\nBut I'm not going to worry about these yet\n\n293\n00:15:03,020 --> 00:15:04,820\n因为3不等于0\nbecause 3 is not 0.\n\n294\n00:15:05,290 --> 00:15:06,540\n于是答案不是4\nSo the answer is not 4.\n\n295\n00:15:07,970 --> 00:15:08,430\n因此\nTherefore,\n\n296\n00:15:08,450 --> 00:15:10,960\n于是整个if表达式就可以归约成\nthis if reduces to\n\n297\n00:15:10,960 --> 00:15:12,610\n对这个表达式的求值\nan evaluation of the expression,\n\n298\n00:15:12,850 --> 00:15:14,010\n求3减1\nthe sum to the decrement of 3\n\n299\n00:15:14,010 --> 00:15:14,920\n与4加1的和\nand the increment of 4.\n\n300\n00:15:16,580 --> 00:15:17,800\n继续求值\nContinuing with my evaluation,\n\n301\n00:15:17,800 --> 00:15:19,800\n先认为加1的过程是基本过程\nthe increment I presume to be primitive,\n\n302\n00:15:20,380 --> 00:15:21,800\n然后就有了5\nand so I get a 5 there.\n\n303\n00:15:22,680 --> 00:15:24,530\n同样把减1也认为是基本过程\nOK,and then the decrement is also primitive,\n\n304\n00:15:24,530 --> 00:15:25,330\n然后就有了2\nand I get a 2.\n\n305\n00:15:25,680 --> 00:15:28,080\n于是我把问题化简了\nAnd so I change the problem into a simpler problem.\n\n306\n00:15:28,080 --> 00:15:30,080\n不是3加4的问题了\nInstead of adding 3 to 4,\n\n307\n00:15:30,840 --> 00:15:32,080\n而是2加5的问题了\nI'm adding 2 to 5.\n\n308\n00:15:33,130 --> 00:15:34,600\n为什么这样就变简单了呢\nThe reason why this is a simpler problem\n\n309\n00:15:34,600 --> 00:15:37,310\n因为我在减小x\nis because I'm counting down on x,\n\n310\n00:15:37,780 --> 00:15:40,160\n最终x会变为0\nand eventually,then,x will be 0.\n\n311\n00:15:43,070 --> 00:15:44,990\n这就是代换模型了\nSo,so much for the substitution rule.\n\n312\n00:15:45,690 --> 00:15:46,420\n通常来讲\nIn general,\n\n313\n00:15:46,420 --> 00:15:48,900\n在对if表达式使用代换模型的时候\nI'm not going to write down intermediate steps\n\n314\n00:15:48,900 --> 00:15:50,900\n我不会写下所有中间步骤\nwhen using substitutions having to do with ifs,\n\n315\n00:15:51,500 --> 00:15:54,660\n因为这么做只能把事情复杂化\nbecause they just expand things to become complicated.\n\n316\n00:15:55,120 --> 00:15:56,400\n我们要做的是\nWhat we will be doing is saying,\n\n317\n00:15:56,400 --> 00:15:58,190\n把求3和4的和\noh,yes,the sum of 3 and 4\n\n318\n00:15:58,190 --> 00:16:00,780\n归约到求2和5的和\nresults in the sum of 2 and 5\n\n319\n00:16:01,390 --> 00:16:02,920\n在那之后\nand reduces to the sum of 2 and 5.\n\n320\n00:16:03,160 --> 00:16:06,040\n归约到求1和6的和\nwhich,in fact,reduces to the sum of 1 and 6,\n\n321\n00:16:06,740 --> 00:16:09,700\n最后归约到求0和7的和\nwhich reduces to the sum of 0 and 7\n\n322\n00:16:09,700 --> 00:16:10,360\n看这儿\nover here,\n\n323\n00:16:10,860 --> 00:16:11,960\n最后归约到7\nwhich reduces to a 7.\n\n324\n00:16:13,730 --> 00:16:14,680\n这就是我们想要的结果\nThat's what we're going to be seeing.\n\n325\n00:16:16,180 --> 00:16:17,850\n现在 各位对第一部分的内容有疑问么\nAre there any questions for the first segment yet?\n\n326\n00:16:20,180 --> 00:16:20,680\n有吗\nYes?\n\n327\n00:16:21,010 --> 00:16:23,530\n学生 你用了1+过程和-1+过程\nSTUDENT: You're using 1 plus and minus 1 plus\n\n328\n00:16:23,530 --> 00:16:25,460\n它们都是基本过程么\nAre those primitive operations?\n\n329\n00:16:25,460 --> 00:16:26,100\n教授 是的\nPROFESSOR: Yes\n\n330\n00:16:26,410 --> 00:16:28,450\n你们在这门课中要明白的是\nOne of the things you're going to be seeing in this subject\n\n331\n00:16:28,970 --> 00:16:32,110\n我绝对不会考虑\nis I'm going to,without thinking about it,\n\n332\n00:16:32,260 --> 00:16:35,680\n给大家介绍越来越多的基本过程\nintroduce more and more primitive operations\n\n333\n00:16:35,920 --> 00:16:37,710\n可以假定\nThere's presumably some large library\n\n334\n00:16:37,710 --> 00:16:39,260\n有一些庞大的基本过程的程序库\nof primitive operations somewhere.\n\n335\n00:16:39,450 --> 00:16:41,100\n不用过分追究这些基本过程\nBut it doesn't matter that they're primitive--\n\n336\n00:16:41,100 --> 00:16:43,100\n可能有一些手册有这些基本过程的索引 便于我们查找\nthere may be some manual that lists them all.\n\n337\n00:16:43,100 --> 00:16:44,860\n如果我向你解释基本过程的作用 你应该说\nIf I tell you what they do,you should say,\n\n338\n00:16:44,860 --> 00:16:46,300\n啊 是这样 我明白它们的作用了\noh,yes,I know what they do.\n\n339\n00:16:46,660 --> 00:16:48,300\n比如 这个减1的过程\nSo one of them is the decrementor\n\n340\n00:16:48,670 --> 00:16:49,490\n-1+\n-- minus 1 plus--\n\n341\n00:16:49,790 --> 00:16:50,890\n另一个加1的过程\nand the other operation is increment,\n\n342\n00:16:50,890 --> 00:16:51,780\n1+\nwhich is 1 plus.\n\n343\n00:16:53,140 --> 00:16:53,480\n谢谢大家\nThank you.\n\n344\n00:16:53,490 --> 00:16:54,900\n第一部分结束\nThat's the end of the first segment.\n\n345\n00:17:05,540 --> 00:17:19,170\n[音乐]\n[MUSIC PLAYING BY J.S. BACH]\n\n346\n00:17:19,310 --> 00:17:21,540\n教授 现在我们有了一个合理的 机械的方式\nPROFESSOR: Now that we have a reasonably mechanical way\n\n347\n00:17:21,540 --> 00:17:27,300\n去理解一个由过程\nof understanding how a program made out of procedures\n\n348\n00:17:27,300 --> 00:17:30,700\n和表达式组成的程序是如何演化成计算过程的\nand expressions evolves a process,\n\n349\n00:17:31,160 --> 00:17:32,700\n我想要大家培养出一些直觉\nI'd like to develop some intuition\n\n350\n00:17:33,460 --> 00:17:37,150\n有关程序如何演化成计算过程的直觉\nabout how particular programs evolve particular processes,\n\n351\n00:17:37,380 --> 00:17:39,150\n有关程序到底是什么“形状”的直觉\nwhat the shapes of programs have to be\n\n352\n00:17:39,150 --> 00:17:41,150\n这样才能产生特定“形状”的计算过程\nin order to get particular shaped processes.\n\n353\n00:17:42,430 --> 00:17:46,000\n这让我想到了 画面预览\nThis is a question about,really,pre-visualizing.\n\n354\n00:17:47,140 --> 00:17:48,670\n这是个摄影专业术语\nThat's a word from photography.\n\n355\n00:17:48,670 --> 00:17:51,020\n我曾经对摄影十分着迷\nI used to be interested in photography a lot,\n\n356\n00:17:51,890 --> 00:17:53,700\n你会发现\nand one of the things you discover\n\n357\n00:17:53,700 --> 00:17:55,250\n初学摄影的时候\nwhen you start trying to learn about photography\n\n358\n00:17:55,250 --> 00:17:57,860\n你很想成为一名有创意的摄影师\nis that you say,gee,I'd like to be a creative photographer.\n\n359\n00:17:58,520 --> 00:18:00,100\n我知道怎么做 按快门\nNow,I know the rules,I push buttons,\n\n360\n00:18:00,100 --> 00:18:02,800\n调整光圈什么的\nand I adjust the aperture and things like that.\n\n361\n00:18:03,140 --> 00:18:06,320\n但要想有创意\nBut the key to being a creative person,partly,\n\n362\n00:18:06,320 --> 00:18:09,400\n一定程度上靠的是能在一定层次上进行分析\nis to be able to do analysis at some level.\n\n363\n00:18:09,400 --> 00:18:12,540\n比如 在按下快门前\nTo say,how do I know what it is\n\n364\n00:18:12,540 --> 00:18:15,320\n我怎么知道交卷上最终是怎样的画面呢\nthat I'm going to get on the film before I push the button.\n\n365\n00:18:16,920 --> 00:18:18,770\n我能在心中\nCan I imagine in my mind\n\n366\n00:18:20,290 --> 00:18:23,340\n非常准确清晰地刻画出拍好的照片么\nthe resulting image very precisely and clearly\n\n367\n00:18:24,970 --> 00:18:27,700\n那精心地取景\nas a consequence of the particular framing,\n\n368\n00:18:27,700 --> 00:18:29,120\n仔细地调整光圈\nof the aperture I choose,\n\n369\n00:18:29,120 --> 00:18:30,140\n仔细地对焦\nof the focus,\n\n370\n00:18:30,140 --> 00:18:31,210\n而拍出来的照片\nand things like that?\n\n371\n00:18:32,480 --> 00:18:35,070\n一定程度来说 这就是摄影的艺术\nThat's part of the art of doing this sort of thing.\n\n372\n00:18:35,600 --> 00:18:38,480\n而要掌握摄影的艺术牵涉到许多方面\nAnd a lot of that involves,learning a lot of that\n\n373\n00:18:38,480 --> 00:18:40,050\n比如曝光试验片\ninvolves things like test strips.\n\n374\n00:18:40,580 --> 00:18:42,400\n比如拍摄非常几张简单的画面\nYou take very simple images\n\n375\n00:18:42,970 --> 00:18:46,050\n每张都有不同的影像密度\nthat have varying degrees of density in them,for example,\n\n376\n00:18:46,340 --> 00:18:49,330\n然后把它们打印在一张纸上\nand examine what those look like on a piece of paper\n\n377\n00:18:49,330 --> 00:18:50,190\n观察它们都有什么不同\nwhen you print them out.\n\n378\n00:18:51,180 --> 00:18:53,520\n你能发现实际可见的对比度\nYou find out what is the range of contrasts\n\n379\n00:18:53,520 --> 00:18:54,610\n都是怎样的范围内\nthat you can actually see.\n\n380\n00:18:55,470 --> 00:18:56,880\n还能发现 从实际角度来讲\nAnd what,in a real scene,\n\n381\n00:18:56,880 --> 00:18:59,160\n都是哪些因素与同一张照片中不同层次\nwould correspond to the various levels\n\n382\n00:18:59,160 --> 00:19:03,640\n不同区块的影像密度的产生有关\nand zones that you have of density in an image.\n\n383\n00:19:05,020 --> 00:19:08,540\n今天这节课我就想让大家看一些特别的 “曝光试验片”\nWell,today I want to look at some very particular test strips,\n\n384\n00:19:09,290 --> 00:19:12,280\n下面通过幻灯片来看第一张\nand I suppose one of them I see here is up on the telestrator,\n\n385\n00:19:12,280 --> 00:19:14,040\n请看\nso we should switch to that.\n\n386\n00:19:14,810 --> 00:19:18,840\n有两个非常非常重要的程序\nThere's a very important,very important pair of programs\n\n387\n00:19:18,840 --> 00:19:24,050\n用来理解在程序执行时\nfor understanding what's going on in the evolution of a process\n\n388\n00:19:24,190 --> 00:19:25,600\n计算过程中的求值都是怎样的\nby the execution of a program.\n\n389\n00:19:26,900 --> 00:19:30,010\n大家看到的是两个几乎相同的过程\nWhat we have here are two procedures that are almost identical.\n\n390\n00:19:32,110 --> 00:19:34,580\n基本上没有区别\nAlmost no difference between them at all.\n\n391\n00:19:35,080 --> 00:19:37,260\n只有几个字符不同\nIt's a few characters that distinguish them.\n\n392\n00:19:38,610 --> 00:19:41,010\n这两个过程表示的是 两种不同的求两数之和的方法\nThese are two ways of adding numbers together.\n\n393\n00:19:42,110 --> 00:19:43,010\n第一个\nThe first one,\n\n394\n00:19:43,610 --> 00:19:45,700\n看这里\nwhich you see here,\n\n395\n00:19:46,170 --> 00:19:48,900\n是求两数之和\nthe first one is the sum of two numbers\n\n396\n00:19:48,900 --> 00:19:49,940\n和我们上节课讲到的一样\n-- just what we did before--\n\n397\n00:19:50,440 --> 00:19:51,650\n如果第一个参数是0\nis if the first one is 0,\n\n398\n00:19:51,650 --> 00:19:52,960\n第二个参数就是答案\nit's the answer of the second one.\n\n399\n00:19:53,210 --> 00:19:53,840\n否则\nOtherwise,\n\n400\n00:19:53,840 --> 00:19:55,840\n就是第一个参数减1\nit's the sum of the decrement of the first\n\n401\n00:19:55,840 --> 00:19:56,940\n和第二个参数加1的和\nand the increment of the second.\n\n402\n00:19:57,610 --> 00:20:03,360\n你可以这么考虑 有两堆弹珠\nAnd you may think of that as having two piles,having two piles.\n\n403\n00:20:04,090 --> 00:20:07,180\n把这两堆加在一块儿形成新的一堆的办法就是\nAnd the way I'm adding these numbers together to make a third pile is by\n\n404\n00:20:07,180 --> 00:20:09,180\n把弹珠从一堆挪到另一堆去\nmoving marbles from one to the other.\n\n405\n00:20:10,130 --> 00:20:11,070\n仅此而已\nNothing more than that.\n\n406\n00:20:11,290 --> 00:20:12,850\n最终 有一堆会被搬空\nAnd eventually,when I run out of one\n\n407\n00:20:12,850 --> 00:20:13,900\n另一堆就是加和的结果了\nthen the other is the sum.\n\n408\n00:20:15,330 --> 00:20:19,240\n然而 第二个过程不是这样做的\nHowever,the second procedure here doesn't do it that way.\n\n409\n00:20:20,340 --> 00:20:22,380\n它是这样做的 如果第一个参数是0\nIt says if the first number is 0,\n\n410\n00:20:22,380 --> 00:20:23,550\n答案就是第二个\nthen the answer is the second.\n\n411\n00:20:24,020 --> 00:20:24,530\n否则\nOtherwise,\n\n412\n00:20:24,530 --> 00:20:26,990\n答案就是 第一个参数减1\nit's the increment of the sum\n\n413\n00:20:26,990 --> 00:20:28,900\n和第二个参数的和\nof the decrement of the first number\n\n414\n00:20:28,900 --> 00:20:29,560\n然后再加1\nand the second.\n\n415\n00:20:31,020 --> 00:20:32,010\n这种方式就是\nSo what this says is\n\n416\n00:20:32,020 --> 00:20:36,490\n把第一个参数减1和第二个数加起来\nadd together,add together the decrement of the first number and the second\n\n417\n00:20:36,490 --> 00:20:38,320\n毫无疑问 简化了问题\n-- a simpler problem,no doubt--\n\n418\n00:20:38,320 --> 00:20:41,540\n然后把这个和再加1\nand then change that result to increment it.\n\n419\n00:20:42,780 --> 00:20:46,060\n这就意味着如果你用两堆弹珠的方式来思考\nAnd so this means that if you think about this in terms of piles,\n\n420\n00:20:46,480 --> 00:20:50,100\n就是说 我左手右手各有一堆弹珠\nit means I'm holding in my hand the things to be added later.\n\n421\n00:20:51,450 --> 00:20:53,020\n然后我要把它们加在一起\nAnd then I'm going to add them in.\n\n422\n00:20:53,610 --> 00:20:56,060\n然后我慢慢地把其中一堆搬空\nAs I slowly decrease one pile to 0,\n\n423\n00:20:56,430 --> 00:20:57,710\n然后把这些拿出来的弹珠\nI've got what's left here,\n\n424\n00:20:57,710 --> 00:20:58,890\n再放回另一堆弹珠中\nand then I'm going to add them back.\n\n425\n00:20:59,960 --> 00:21:01,170\n两种不同的加法\nTwo different ways of adding.\n\n426\n00:21:02,160 --> 00:21:04,200\n关于这两个程序 有趣的是\nThe nice thing about these two programs\n\n427\n00:21:04,460 --> 00:21:05,850\n它们几乎一样\nis that they're almost identical.\n\n428\n00:21:06,450 --> 00:21:08,260\n唯一的区别是把加1这个过程放哪儿\nThe only thing is where I put the increment.\n\n429\n00:21:09,140 --> 00:21:10,570\n把几个字符挪挪地方\nA couple of characters moved around.\n\n430\n00:21:11,490 --> 00:21:14,280\n现在我想弄明白\nNow I want to understand,I want to understand the kind of behavior\n\n431\n00:21:14,760 --> 00:21:16,820\n我们会从这两个程序中看到怎样的行为\nwe're going to get from each of these programs.\n\n432\n00:21:17,330 --> 00:21:19,040\n加深大家对这个问题的印象\nJust to get them firmly in your mind\n\n433\n00:21:19,280 --> 00:21:21,680\n我通常不想这么谨慎\n-- I usually don't want to be this careful--\n\n434\n00:21:21,680 --> 00:21:23,610\n但是还是要加深大家的印象\nbut just to get them firmly in your mind,\n\n435\n00:21:23,610 --> 00:21:25,330\n我在黑板上把程序再写一遍\nI'm going to write the programs again on the blackboard,\n\n436\n00:21:25,330 --> 00:21:27,100\n然后我会演化出一个计算过程\nand then I'm going to evolve a process.\n\n437\n00:21:27,770 --> 00:21:29,100\n大家都注意观察 看看是怎么回事\nAnd you're going to see what happens.\n\n438\n00:21:29,460 --> 00:21:31,340\n看看过程演化是怎样的“形状”\nWe're going to look at the shape of the process\n\n439\n00:21:31,340 --> 00:21:32,740\n这是程序导致的一个结果\nas a consequence of the program.\n\n440\n00:21:34,040 --> 00:21:35,730\n我们从这个程序开始\nSo the program we started with is this:\n\n441\n00:21:40,510 --> 00:21:44,160\n求x与y的和\nthe sum of x and y says\n\n442\n00:21:44,160 --> 00:21:49,410\n如果x等于0\nif x is 0,\n\n443\n00:21:49,410 --> 00:21:50,670\n那么答案就是y\nthen the result is y.\n\n444\n00:21:50,670 --> 00:21:51,520\n否则\nOtherwise,\n\n445\n00:21:51,520 --> 00:21:58,220\n答案就是x减1和y加1的和\nit's the sum of the decrement of x and the increment of y.\n\n446\n00:22:01,260 --> 00:22:05,490\n现在 假设我们要求3与4的和\nNow,supposing we wish to do this addition of 3 and 4,\n\n447\n00:22:06,610 --> 00:22:09,120\n3与4的和\nthe sum of 3 and 4,\n\n448\n00:22:09,530 --> 00:22:10,300\n接下来呢\nwell,what is that?\n\n449\n00:22:10,530 --> 00:22:13,690\n我要代换这两个参数\nIt says that I have to substitute the arguments\n\n450\n00:22:14,030 --> 00:22:16,040\n代换过程定义中的形式参数\nfor the formal parameters in the body.\n\n451\n00:22:17,380 --> 00:22:18,920\n我在脑海中想像这个过程\nI'm doing that in my mind.\n\n452\n00:22:19,560 --> 00:22:20,660\n然后说 啊 这样\nAnd I say,oh,yes,\n\n453\n00:22:20,660 --> 00:22:21,920\n3代换了x\n3 is substituted for x,\n\n454\n00:22:21,920 --> 00:22:23,280\n但3不是0\nbut 3 is not 0,\n\n455\n00:22:24,650 --> 00:22:27,000\n于是直接进入这一部分\nso I'm going to go directly to this part\n\n456\n00:22:27,000 --> 00:22:30,400\n然后只用关心这一部分就行\nand write down the simplified consequent here.\n\n457\n00:22:30,400 --> 00:22:31,980\n因为我只关心加法过程的行为\nBecause I'm really interested in the behavior of addition.\n\n458\n00:22:33,100 --> 00:22:33,840\n好了 接下来\nWell,what is that?\n\n459\n00:22:34,080 --> 00:22:37,760\n就变成了求2和5的过程\nThat therefore turns into the sum of 2 and 5.\n\n460\n00:22:38,400 --> 00:22:38,610\n换句话说\nIn other words,\n\n461\n00:22:38,610 --> 00:22:40,270\n我把这个问题归约成这个问题\nI've reduced this problem to this problem.\n\n462\n00:22:41,410 --> 00:22:46,280\n然后我又把这个问题化归约成求1和6的和\nThen I reduce this problem to the sum of 1 and 6,\n\n463\n00:22:47,220 --> 00:22:49,340\n再接着归约\nand then,going around again once,\n\n464\n00:22:49,600 --> 00:22:52,480\n就有了0和7的和\nI get the sum of 0 and 7.\n\n465\n00:22:52,970 --> 00:22:54,930\n于是x就等于0了\nAnd that's one where x equals 0\n\n466\n00:22:54,930 --> 00:22:56,220\n答案是y\nso the result is y,\n\n467\n00:22:56,220 --> 00:22:58,220\n也就是7\nand so I write down here a 7.\n\n468\n00:22:59,920 --> 00:23:02,780\n这就是这个程序把3和4相加\nSo this is the behavior of the process evolved\n\n469\n00:23:02,780 --> 00:23:05,360\n而演化出的计算过程的行为\nby trying to add together 3 and 4 with this program.\n\n470\n00:23:07,390 --> 00:23:08,680\n另一个程序\nFor the other program,\n\n471\n00:23:09,630 --> 00:23:10,610\n写在这边\nwhich is over here,\n\n472\n00:23:17,800 --> 00:23:22,250\n如此定义x与y的和\nI will define the sum of x and y.\n\n473\n00:23:23,360 --> 00:23:23,980\n怎么定义的呢\nAnd what is it?\n\n474\n00:23:26,480 --> 00:23:29,170\n如果x是0\nIf x is 0,\n\n475\n00:23:29,620 --> 00:23:30,810\n答案就是y\nthen the result is y\n\n476\n00:23:30,810 --> 00:23:31,630\n这和上一个程序一样\n-- almost the same--\n\n477\n00:23:31,630 --> 00:23:34,800\n否则就是x减1与y的和\notherwise the increment of the sum\n\n478\n00:23:35,550 --> 00:23:40,260\n再加上1\nof the decrement of x and y.\n\n479\n00:23:47,370 --> 00:23:54,640\n写错了 黑板不能自动匹配括号\nNo.I don't have my balancer in front of me.\n\n480\n00:23:56,080 --> 00:23:57,330\n好了 接下来\nOK,well,let's do it now.\n\n481\n00:23:58,800 --> 00:24:00,100\n求3与4的和\nThe sum of 3 and 4.\n\n482\n00:24:01,160 --> 00:24:02,690\n其实这样更有趣 来看\nWell,this is actually a little more interesting.\n\n483\n00:24:03,310 --> 00:24:05,630\n3当然不等于0 和之前一样\nOf course,3 is not 0 as before,\n\n484\n00:24:06,160 --> 00:24:12,130\n于是答案就是 x减1与y的和再加1\nso that results in the increment of the sum of the decrement of x,\n\n485\n00:24:12,130 --> 00:24:14,260\n也就是2与4的和\nwhich is 2 and 4,\n\n486\n00:24:15,800 --> 00:24:22,650\n接着变成 1与\nwhich is the increment of the sum of 1 and--\n\n487\n00:24:22,850 --> 00:24:24,990\n噢 弄错了 加1再加1\nwhoops: the increment of the increment.\n\n488\n00:24:25,650 --> 00:24:29,170\n现在要做的是计算这一部分\nWhat I have to do now is compute what this means.\n\n489\n00:24:29,470 --> 00:24:30,590\n我要对这一部分求值\nI have to evaluate this.\n\n490\n00:24:30,810 --> 00:24:31,720\n也就是\nOr what that is,\n\n491\n00:24:31,870 --> 00:24:34,720\n用2和4代换x和y的结果\nthe result of substituting 2 and 4 for x and y here.\n\n492\n00:24:35,200 --> 00:24:40,840\n变成了1与4的和再加1\nBut that is the increment of the sum of 1 and 4,\n\n493\n00:24:43,490 --> 00:24:45,920\n现在我得展开这部份\nwhich is-- well,now I have to expand this.\n\n494\n00:24:47,160 --> 00:24:51,230\n啊 然后就变成了0与4的和加1加1\nAh,but that's the increment of the increment\n\n495\n00:24:53,520 --> 00:24:56,130\n再加1\nof the increment of the sum of 0 and 4.\n\n496\n00:24:59,390 --> 00:25:02,380\n现在来看看都能做些什么\nAh,but now I'm beginning to find things I can do.\n\n497\n00:25:02,860 --> 00:25:06,850\n加1加1再加1\nThe increment of the increment of the increment of--\n\n498\n00:25:06,850 --> 00:25:08,590\n0和4的和是4\nwell,the sum of 0 and 4 is 4.\n\n499\n00:25:12,030 --> 00:25:13,610\n4加1是5\nThe increment of 4 is 5.\n\n500\n00:25:14,560 --> 00:25:18,760\n这就变成了5加1再加1\nSo this is the increment of the increment of 5,\n\n501\n00:25:20,180 --> 00:25:23,200\n也就是6再加1\nwhich is the increment of 6,\n\n502\n00:25:23,900 --> 00:25:24,970\n最后答案就是7\nwhich is 7.\n\n503\n00:25:26,100 --> 00:25:28,060\n两种不同的求和方法\nTwo different ways of computing sums.\n\n504\n00:25:29,540 --> 00:25:30,330\n现在来看看\nNow,let's see.\n\n505\n00:25:31,260 --> 00:25:33,260\n这两种计算过程有不同的“形状”\nThese processes have very different shapes.\n\n506\n00:25:33,920 --> 00:25:35,400\n我想让各位去感受这些“形状”\nI want you to feel these shapes.\n\n507\n00:25:36,350 --> 00:25:38,370\n这种感觉很关键\nIt's the feeling for the shapes that matters.\n\n508\n00:25:40,340 --> 00:25:42,030\n从这里我们能发现什么\nWhat's some things we can see about this?\n\n509\n00:25:42,660 --> 00:25:44,120\n不知怎么回事 这个有点“直”\nWell somehow this is sort of straight.\n\n510\n00:25:45,250 --> 00:25:46,600\n就这样一路直着下来\nIt goes this way-- straight.\n\n511\n00:25:47,340 --> 00:25:51,930\n右边界并没有特别的变化\nThis right edge doesn't vary particularly in size.\n\n512\n00:25:53,770 --> 00:25:54,700\n而这边这个呢\nWhereas this one,\n\n513\n00:25:54,990 --> 00:25:58,320\n右边界先变大又变小\nI see that this thing gets bigger and then it gets smaller.\n\n514\n00:26:00,910 --> 00:26:02,620\n我还不知道这意味着什么\nSo I don't know what that means yet,\n\n515\n00:26:02,620 --> 00:26:03,630\n我们看到的是什么\nbut what are we seeing?\n\n516\n00:26:03,630 --> 00:26:05,900\n是不知怎么回事\nWe're seeing here that somehow\n\n517\n00:26:07,170 --> 00:26:10,940\n这些加1的过程先展开后收缩\nthese increments are expanding out and then contracting back.\n\n518\n00:26:12,760 --> 00:26:14,570\n我构造出一个推迟进行的操作的链条\nI'm building up a bunch of them to do later.\n\n519\n00:26:16,090 --> 00:26:17,070\n我不能马上求值\nI can't do them now.\n\n520\n00:26:18,720 --> 00:26:19,860\n有的过程需要推迟\nThere's things to be deferred.\n\n521\n00:26:21,400 --> 00:26:22,160\n好了 我们继续\nWell,let's see,\n\n522\n00:26:22,670 --> 00:26:24,290\n我可以想象一个抽象的计算机\nI can imagine an abstract machine.\n\n523\n00:26:24,290 --> 00:26:25,480\n也许能制造一些实际的计算机\nThere's some physical machine,\n\n524\n00:26:25,480 --> 00:26:26,840\n能像我这样求值\nperhaps,that could be built to do it,\n\n525\n00:26:26,840 --> 00:26:30,010\n能像我演示给大家的一样执行程序\nwhich,in fact,executes these programs exactly as I tell you,\n\n526\n00:26:30,010 --> 00:26:32,850\n像这样代换字符串\nsubstituting character strings in like this.\n\n527\n00:26:34,210 --> 00:26:35,080\n这样的计算机\nSuch a machine,\n\n528\n00:26:35,780 --> 00:26:38,750\n计算中的步骤与计算所花费的时间近似相等\nthe number of such steps is an approximation of the amount of time it takes.\n\n529\n00:26:39,730 --> 00:26:40,830\n用纵轴表示时间\nSo this way is time.\n\n530\n00:26:43,630 --> 00:26:46,420\n横轴的宽度表示\nAnd the width of the thing is\n\n531\n00:26:46,970 --> 00:26:49,700\n进行计算需要保存的信息量\nhow much I have to remember in order to continue the process.\n\n532\n00:26:50,110 --> 00:26:51,150\n也就是表示进行计算所需要的空间\nAnd this much is space.\n\n533\n00:26:53,540 --> 00:26:56,180\n我们看到的是一个计算过程\nAnd what we see here is a process\n\n534\n00:26:57,090 --> 00:27:00,910\n其时间消耗正比于参数x\nthat takes a time which is proportional to the argument x.\n\n535\n00:27:02,420 --> 00:27:04,350\n因为如果我让x增大一倍\nBecause if I made x larger by 1,\n\n536\n00:27:04,350 --> 00:27:05,520\n就得把这个表示时间的纵轴再加长一倍\nthen I'd had an extra line.\n\n537\n00:27:08,480 --> 00:27:12,260\n于是这就是个计算过程 它的空间 抱歉 时间\nSo this is a process which is space-- sorry-- time.\n\n538\n00:27:14,520 --> 00:27:19,160\n这个计算过程消耗的时间为O(x)\nThe time of this process is what we say order of x.\n\n539\n00:27:20,540 --> 00:27:24,890\n也就是正比于x\nThat means it is proportional to x by some constant of proportionality\n\n540\n00:27:24,890 --> 00:27:27,150\n不要刻意追究这个常比例系数是多少\nand I'm not particularly interested in what the constant is.\n\n541\n00:27:28,360 --> 00:27:29,530\n我们还会发现\nThe other thing we see here\n\n542\n00:27:29,540 --> 00:27:32,280\n这个计算过程消耗的空间是固定不变的\nis that the amount of space this takes up is constant.\n\n543\n00:27:33,370 --> 00:27:34,530\n即与1成正比\nit's proportional to 1.\n\n544\n00:27:35,200 --> 00:27:40,420\n于是这个计算过程的空间复杂度就是O(1)的\nSo the space complexity of this is order of 1.\n\n545\n00:27:41,710 --> 00:27:43,360\n对这样的计算过程我们有个名字\nWe have a name for such a process.\n\n546\n00:27:43,870 --> 00:27:45,810\n叫迭代计算过程\nSuch a process is called an iteration.\n\n547\n00:27:50,800 --> 00:27:51,900\n关键的地方\nAnd what matters here\n\n548\n00:27:51,900 --> 00:27:55,820\n不是什么我设计的\nis not that some particular machine I designed here\n\n549\n00:27:56,450 --> 00:27:57,960\n之前提到的\nand talked to you about\n\n550\n00:27:57,960 --> 00:27:59,320\n代换字符计算机\nand called a substitution machine\n\n551\n00:27:59,320 --> 00:28:00,720\n或者 代换模型\nor whatever-- substitution model--\n\n552\n00:28:01,060 --> 00:28:03,880\n怎么设法在常数空间复杂度内完成计算过程\nmanaged to do this in constant space.\n\n553\n00:28:04,220 --> 00:28:06,090\n关键的地方是这给出了一个界限\nWhat really matters is this tells us a bound.\n\n554\n00:28:06,750 --> 00:28:09,200\n任何计算机 都应该在常数空间复杂度内完成计算过程\nAny machine could do this in constant space.\n\n555\n00:28:09,360 --> 00:28:12,030\n这个过程代表的算法\nThis algorithm represented by this procedure\n\n556\n00:28:12,440 --> 00:28:14,030\n在常数空间复杂度内是可执行的\nis executable in constant space.\n\n557\n00:28:14,840 --> 00:28:17,330\n当然了这种说法忽略了一些细节\nNow,of course,the model is ignoring some things,\n\n558\n00:28:17,630 --> 00:28:18,640\n却量化了一些东西\nstandard sorts of things.\n\n559\n00:28:18,640 --> 00:28:21,980\n忽略了比如数值越大越消耗空间等等\nLike numbers that are bigger take up more space and so on.\n\n560\n00:28:21,980 --> 00:28:24,010\n但那确实是抽象过程中我要忽略的一个层次\nBut that's a level of abstraction at which I'm cutting off.\n\n561\n00:28:24,010 --> 00:28:24,920\n如何表示数值\nHow do you represent numbers?\n\n562\n00:28:24,920 --> 00:28:26,640\n我假定所有的数值都具有同样的字长\nI'm considering every number to be the same size.\n\n563\n00:28:27,710 --> 00:28:31,420\n事实上数值的字长的增长 和它们占用的存储空间的增长都非常缓慢\nAnd numbers grow slowly for the amount of space they take up and their size.\n\n564\n00:28:33,860 --> 00:28:36,680\n而这个算法的复杂度就不同了\nNow,this algorithm is different in its complexity.\n\n565\n00:28:37,390 --> 00:28:38,680\n我们看到\nAs we can see here,\n\n566\n00:28:40,370 --> 00:28:43,210\n这个算法时间复杂度\nthis algorithm has a time complexity\n\n567\n00:28:44,680 --> 00:28:48,560\n也是正比于输入参数x的\nwhich is also proportional to the input argument x.\n\n568\n00:28:49,130 --> 00:28:51,610\n因为如果我把这个3再加1\nThat's because if I were to add 1 to 3,\n\n569\n00:28:51,610 --> 00:28:53,320\n如果我把问题规模扩大\nif I made a larger problem\n\n570\n00:28:53,320 --> 00:28:54,980\n扩大了1\nwhich is larger by 1 here,\n\n571\n00:28:54,980 --> 00:28:56,170\n那我就要在上面再加一行\nthen I'd add a line at the top\n\n572\n00:28:56,170 --> 00:28:57,290\n在底下再加一行\nand I'd add a line at the bottom.\n\n573\n00:29:00,280 --> 00:29:01,980\n而且事实上这是个常量\nAnd the fact that it's a constant amount,\n\n574\n00:29:01,980 --> 00:29:04,050\n就像这个计算过程的步骤数是那个的两倍\nlike this is twice as many lines as that\n\n575\n00:29:04,290 --> 00:29:06,600\n我不会关心这个层次的细节 也不会关心那个常量\nis not interesting at the level of detail I'm talking about right now.\n\n576\n00:29:07,730 --> 00:29:12,020\n所以这个计算过程的时间复杂度也是O(x)\nSo this is a time complexity order of the input argument x.\n\n577\n00:29:12,640 --> 00:29:13,950\n而空间复杂度呢\nAnd space complexity,\n\n578\n00:29:15,880 --> 00:29:17,060\n这个比较有趣\nwell,this is more interesting.\n\n579\n00:29:17,390 --> 00:29:19,970\n有一些东西是固定不变的\nI happen to have some overhead,\n\n580\n00:29:20,180 --> 00:29:21,000\n比如这些\nwhich you see over here,\n\n581\n00:29:21,000 --> 00:29:22,720\n是近似保持不变的\nwhich is constant approximately.\n\n582\n00:29:23,290 --> 00:29:24,090\n是常量的\nConstant overhead.\n\n583\n00:29:24,340 --> 00:29:27,210\n但也有一些增加和减少\nBut then I have something which increases and decreases\n\n584\n00:29:27,210 --> 00:29:29,460\n是正比于参数x的\nand is proportional to the input argument x.\n\n585\n00:29:29,710 --> 00:29:31,060\n输入参数x是3\nThe input argument x is 3.\n\n586\n00:29:31,060 --> 00:29:34,690\n也就是这里为何有3个推迟操作的加1过程\nThat's why there are three deferred increments sitting around here.\n\n587\n00:29:36,360 --> 00:29:36,650\n发现了么\nSee?\n\n588\n00:29:37,400 --> 00:29:40,060\n于是这个计算过程的空间复杂度也是O(x)的\nSo the space complexity here is also order x.\n\n589\n00:29:41,400 --> 00:29:43,150\n这种计算过程\nAnd this kind of process,\n\n590\n00:29:43,410 --> 00:29:44,640\n给它取个名字\nnamed for the kind of process,\n\n591\n00:29:44,640 --> 00:29:45,850\n是递归计算过程\nthis is a recursion.\n\n592\n00:29:50,410 --> 00:29:51,280\n更准确地来说\nA linear recursion\n\n593\n00:29:51,280 --> 00:29:51,870\n是线性递归计算过程\nI will call it.\n\n594\n00:29:54,600 --> 00:29:56,680\n因为它的时间和空间复杂度\nbecause of the fact that it's proportional\n\n595\n00:29:56,680 --> 00:29:58,520\n都是正比于输入参数的\nto the input argument in both time and space.\n\n596\n00:30:01,360 --> 00:30:03,070\n那么这个就可以称为一个线性迭代过程\nThis could have been a linear iteration.\n\n597\n00:30:13,630 --> 00:30:15,070\n那么 这两种计算过程的本质是什么\nSo then what's the essence of this matter?\n\n598\n00:30:16,190 --> 00:30:17,780\n不太容易看出来\nThis matter isn't so obvious.\n\n599\n00:30:18,750 --> 00:30:19,690\n可能还有别的模型\nMaybe there are other models\n\n600\n00:30:19,690 --> 00:30:21,630\n可以用来描述\nby which we can describe the differences\n\n601\n00:30:21,630 --> 00:30:23,390\n迭代和递归计算过程的不同之处\nbetween iterative and recursive processes.\n\n602\n00:30:23,390 --> 00:30:24,410\n但这就有些困难了\nBecause this is hard now.\n\n603\n00:30:25,150 --> 00:30:25,390\n记住\nRemember,\n\n604\n00:30:25,390 --> 00:30:27,140\n这两种计算过程都是递归定义的\nwe have-- those are both recursive definitions.\n\n605\n00:30:28,010 --> 00:30:28,940\n我们看到的是\nWhat we're seeing there\n\n606\n00:30:29,980 --> 00:30:31,380\n两种过程在定义上都使用了递归\nare both recursive definitions,\n\n607\n00:30:31,680 --> 00:30:34,370\n也就是两个过程的定义中都引用了该过程本身\ndefinitions that refer to the thing being defined in the definition.\n\n608\n00:30:35,050 --> 00:30:36,620\n但是它们却产生了不同“形状”的计算过程\nBut they lead to different shape processes.\n\n609\n00:30:37,440 --> 00:30:41,250\n过程定义是递归的\nThere's nothing special about the fact\n\n610\n00:30:41,250 --> 00:30:42,540\n而产生的计算过程也是递归的\nthat the definition is recursive\n\n611\n00:30:42,540 --> 00:30:44,170\n这没什么特别的\nthat leads to a recursive process.\n\n612\n00:30:45,770 --> 00:30:49,490\n好了 来看看另一种有趣的解释\nOK.Let's think of another model.\n\n613\n00:30:49,850 --> 00:30:51,490\n我会和大家谈谈 官僚主义\nI'm going to talk to you about bureaucracy.\n\n614\n00:30:52,620 --> 00:30:54,290\n官僚主义 挺有趣儿的\nBureaucracy is sort of interesting.\n\n615\n00:30:54,650 --> 00:30:58,890\n在幻灯片上我们看到有关迭代计算过程的解释\nHere we see on a slide an iteration.\n\n616\n00:31:00,120 --> 00:31:02,220\n迭代是一种挺好玩儿的计算过程\nAn iteration is sort of a fun kind of process.\n\n617\n00:31:03,820 --> 00:31:06,210\n想象一下有个叫GJS的家伙\nImagine that there's a fellow called GJS\n\n618\n00:31:06,330 --> 00:31:07,160\n也就是我\n-- that stands for me--\n\n619\n00:31:08,400 --> 00:31:09,260\n遇到了一个问题\nand he's got a problem:\n\n620\n00:31:09,260 --> 00:31:10,770\n他想求3与4的和\nhe wants to add together 3 and 4.\n\n621\n00:31:13,010 --> 00:31:14,820\n这个家伙想把3和4加一块儿\nThis fella here wants to add together 3 and 4.\n\n622\n00:31:16,260 --> 00:31:17,170\n他打算这么办\nWell,the way he's going to do it\n\n623\n00:31:17,170 --> 00:31:17,900\n他挺懒的\n-- he's lazy--\n\n624\n00:31:18,260 --> 00:31:20,180\n他想找别人帮忙\nis he's going to find somebody else to help him do it.\n\n625\n00:31:21,060 --> 00:31:22,210\n他是这样找人帮忙的\nThe way he finds someone else to--\n\n626\n00:31:22,210 --> 00:31:24,210\n他找了个人帮忙 对他说\nhe finds someone else to help him do it and says,\n\n627\n00:31:24,210 --> 00:31:25,970\n算出3和4的和\nwell,give me the answer to 3 and 4\n\n628\n00:31:26,010 --> 00:31:27,260\n然后把答案返回给我\nand return the result to me.\n\n629\n00:31:28,010 --> 00:31:30,180\n他写了一张小纸条递给这个人然后说\nHe makes a little piece of paper and says,\n\n630\n00:31:30,460 --> 00:31:31,770\n给 这是一张纸条\nhere,here's a piece of paper--\n\n631\n00:31:31,770 --> 00:31:32,620\n你去解决这个问题\nyou go ahead and solve this problem\n\n632\n00:31:32,620 --> 00:31:33,800\n然后把答案返回给我\nand give the result back to me.\n\n633\n00:31:35,480 --> 00:31:36,000\n而这个找来帮忙的家伙呢\nAnd this guy,\n\n634\n00:31:36,000 --> 00:31:36,930\n也很懒\nof course,is lazy,too.\n\n635\n00:31:38,010 --> 00:31:39,630\n他可不想再看见这张小纸条了\nHe doesn't want to see this piece of paper again.\n\n636\n00:31:40,960 --> 00:31:42,210\n他说 啊 好吧\nHe says,oh,yes,\n\n637\n00:31:44,450 --> 00:31:45,480\n然后出了个新问题\nproduce a new problem\n\n638\n00:31:45,480 --> 00:31:46,940\n是求2和5的和\nwhich is the sum of 2 ad 5\n\n639\n00:31:46,940 --> 00:31:49,120\n并把答案返回给GJS\nand return the result back to GJS.\n\n640\n00:31:50,080 --> 00:31:51,210\n我不想再看见这张纸条了\nI don't want to see it again.\n\n641\n00:31:52,000 --> 00:31:53,700\n这个家伙不想再看见这张纸条了\nThis guy does not want to see this piece of paper.\n\n642\n00:31:55,860 --> 00:31:59,940\n于是就出了一个新问题\nAnd then this fellow makes a new problem,\n\n643\n00:32:00,260 --> 00:32:02,030\n也就是求1与6的和的问题\nwhich is the addition of the sum of 1 and 6,\n\n644\n00:32:02,030 --> 00:32:04,260\n他又把纸条传给了这个家伙 并说到\nand he give it to this fella and says,\n\n645\n00:32:04,260 --> 00:32:06,820\n算出答案然后把答案告诉GJS\nproduce that answer and returned it to GJS.\n\n646\n00:32:08,100 --> 00:32:09,740\n那个家伙又接着出了个新问题\nAnd that produces a problem,\n\n647\n00:32:09,740 --> 00:32:11,310\n求0与7的和\nwhich is to add together 0 and 7\n\n648\n00:32:11,310 --> 00:32:13,090\n然后把答案返回给GJS\nand give the result to GJS.\n\n649\n00:32:13,810 --> 00:32:15,010\n最后这个家伙直接说\nThis fella finally just says,\n\n650\n00:32:15,010 --> 00:32:16,120\n啊 好吧 答案是7\noh,yeah,the answer is 7,\n\n651\n00:32:16,120 --> 00:32:17,340\n然后把答案返回给了GJS\nand sends it back to GJS.\n\n652\n00:32:18,140 --> 00:32:19,170\n迭代计算过程就是这样的\nThat's what an iteration is.\n\n653\n00:32:19,870 --> 00:32:20,800\n相对而言\nBy contrast,\n\n654\n00:32:21,260 --> 00:32:23,570\n递归计算过程就有些不同了\na recursion is a slightly different kind of process.\n\n655\n00:32:26,060 --> 00:32:27,610\n它更加“官僚主义”\nThis one involves more bureaucracy.\n\n656\n00:32:28,140 --> 00:32:29,380\n它使得更多的人变得忙碌\nIt keeps more people busy.\n\n657\n00:32:30,190 --> 00:32:31,900\n更多的人被雇佣\nIt keeps more people employed.\n\n658\n00:32:32,400 --> 00:32:34,860\n当然了能增加就业也许更好\nPerhaps it's better for that reason.\n\n659\n00:32:35,600 --> 00:32:36,160\n请看幻灯片\nBut here it is:\n\n660\n00:32:36,160 --> 00:32:38,160\n我想要知道3与4的和\nI want the answer to the problem 3 and 4.\n\n661\n00:32:38,520 --> 00:32:39,900\n于是写了张纸条 说到\nSo I make a piece of paper that says,\n\n662\n00:32:39,900 --> 00:32:40,990\n把答案返回给我\ngive the result back to me.\n\n663\n00:32:42,840 --> 00:32:43,610\n然后我把纸条给了这个家伙\nGive it to this fella.\n\n664\n00:32:44,330 --> 00:32:45,080\n这个家伙说\nThis fellow says,\n\n665\n00:32:45,220 --> 00:32:45,860\n好吧我会记得\noh,yes,I will remember\n\n666\n00:32:46,440 --> 00:32:48,170\n一会儿要加1\nthat I have to add later,\n\n667\n00:32:49,040 --> 00:32:51,560\n而我又得知道2加4的和是多少\nand I want to get the answer the problem 2 plus 4,\n\n668\n00:32:52,020 --> 00:32:54,740\n于是把这个问题给了Harry\ngive that one to Harry,\n\n669\n00:32:54,740 --> 00:32:57,040\n然后把结果返回给我 Joe\nand have the results sent back to me-- I'm Joe.\n\n670\n00:32:58,520 --> 00:33:00,260\n一旦Harry返回了答案\nWhen the answer comes back from Harry,\n\n671\n00:33:00,260 --> 00:33:01,050\n也就是6\nwhich is a 6,\n\n672\n00:33:01,300 --> 00:33:02,500\n我就会把答案加1\nI will then do the increment\n\n673\n00:33:04,120 --> 00:33:05,650\n然后把结果返回给GJS\nand give that 7 back to GJS.\n\n674\n00:33:07,290 --> 00:33:09,050\n大家可以发现 在递归计算过程中 需要保留的纸条\nSo there are more pieces of paper outstanding\n\n675\n00:33:09,660 --> 00:33:12,290\n比迭代计算过程的多\nin the recursive process than the iteration.\n\n676\n00:33:16,540 --> 00:33:18,660\n还有一种方法可以用来理解迭代计算过程\nThere's another way to think about what an iteration is\n\n677\n00:33:19,300 --> 00:33:20,990\n以及迭代计算过程和递归计算过程的不同之处\nand the difference between an iteration and a recursion.\n\n678\n00:33:21,420 --> 00:33:22,760\n问题的关键在于\nYou see,the question is,\n\n679\n00:33:22,760 --> 00:33:24,780\n有多少东西是不可见的\nhow much stuff is under the table?\n\n680\n00:33:26,000 --> 00:33:27,550\n如果我要停止\nsomething,if I were to stop--\n\n681\n00:33:28,360 --> 00:33:32,130\n假设我现在要关闭计算机\nsupposing I were to kill this computer right now,OK?\n\n682\n00:33:32,130 --> 00:33:35,180\n此时我丢失了事务的状态\nAnd at this point I lose the state of affairs,\n\n683\n00:33:36,680 --> 00:33:38,690\n但我能接着进行运算\nwell,I could continue the computation from this point\n\n684\n00:33:39,390 --> 00:33:44,290\n因为继续运算所需要的所有信息都在参数变量中\ncause everything I need to continue the computation is in the variables\n\n685\n00:33:44,290 --> 00:33:48,540\n即程序员编写过程时定义的变量\nthat were defined in the procedure that the programmer wrote for me.\n\n686\n00:33:49,440 --> 00:33:53,810\n迭代计算过程能用明确的变量 保存计算过程中的状态\nAn iteration is a system that has all of its state in explicit variables.\n\n687\n00:33:56,670 --> 00:34:00,020\n这一点递归计算过程就不同\nWhereas the recursion is not quite the same.\n\n688\n00:34:00,940 --> 00:34:04,040\n如果我弄丢了这堆垃圾\nIf I were to lose this pile of junk over here\n\n689\n00:34:04,880 --> 00:34:06,850\n那就只剩下求1与4的和了\nand all I was left with was the sum of 1 and 4,\n\n690\n00:34:07,000 --> 00:34:09,530\n这些信息不足以继续\nthat's not enough information to continue the process\n\n691\n00:34:09,530 --> 00:34:11,870\n从初始的求3与4的和的问题\nof computing out the 7 from the original problem\n\n692\n00:34:11,870 --> 00:34:13,130\n求出7的计算过程\nof adding together 3 of 4.\n\n693\n00:34:14,580 --> 00:34:18,350\n除了保存在过程中的\nBesides the information that's in the variables\n\n694\n00:34:19,290 --> 00:34:21,420\n形式参数变量中的信息\nof the formal parameters of the program,\n\n695\n00:34:22,830 --> 00:34:25,920\n计算机还保存了一些不可见的信息\nthere is also information under the table belonging to the computer,\n\n696\n00:34:26,500 --> 00:34:28,280\n也就是都有哪些过程被推迟计算了\nwhich is what things have been deferred for later.\n\n697\n00:34:30,100 --> 00:34:30,680\n当然了\nAnd,of course,\n\n698\n00:34:30,930 --> 00:34:32,680\n有个实际的比喻\nthere's a physical analogy to this,\n\n699\n00:34:33,220 --> 00:34:37,080\n比如微分方程\nwhich is in differential equations,for example,\n\n700\n00:34:37,740 --> 00:34:40,560\n当我们说到画一个圆的时候\nwhen we talk about something like drawing a circle.\n\n701\n00:34:41,760 --> 00:34:42,990\n试图画一个圆\nTry to draw a circle,\n\n702\n00:34:42,990 --> 00:34:46,030\n你从一个微分方程中解得它\nyou make that out of a differential equation\n\n703\n00:34:46,030 --> 00:34:52,440\n即状态的改变是我当前状态的一个函数\nwhich says the change in my state as a function of my current state.\n\n704\n00:34:52,890 --> 00:34:56,920\n于是如果我当前的状态由y和x的特定值表征\nSo if my current state corresponds to particular values of y and x\n\n705\n00:34:57,630 --> 00:35:01,100\n那么我就能求出一个导数 表征状态如何改变\nthen I can compute from them a derivative which says how the state must change.\n\n706\n00:35:03,150 --> 00:35:03,570\n并且 实际上\nAnd,in fact\n\n707\n00:35:03,580 --> 00:35:05,630\n大家可以看出这是一个圆\nthis,you can see this was a circle\n\n708\n00:35:06,010 --> 00:35:09,760\n因为如果碰巧\nbecause if I happen to be,\n\n709\n00:35:09,760 --> 00:35:11,100\n在这个点\nsay,at this place over here,\n\n710\n00:35:11,770 --> 00:35:15,500\n比如在(1,0)这个点\nat (1,0),for example\n\n711\n00:35:15,530 --> 00:35:16,210\n在这个图像上\non this graph,\n\n712\n00:35:16,730 --> 00:35:22,180\n那就是说y的导数是x\nthen it means that the derivative of y is x,\n\n713\n00:35:22,240 --> 00:35:23,160\n我们也看见了\nwhich we see over here.\n\n714\n00:35:23,160 --> 00:35:24,040\n是1\nThat's 1,\n\n715\n00:35:24,040 --> 00:35:25,100\n接着向上走\nso I'm going up.\n\n716\n00:35:25,780 --> 00:35:28,640\nx的导数是-y\nAnd the derivative of x is minus y,\n\n717\n00:35:28,640 --> 00:35:29,700\n意味着要走回来\nwhich means I'm going backwards.\n\n718\n00:35:30,860 --> 00:35:32,520\n实际在这点什么也没做\nI'm actually doing nothing at this point,\n\n719\n00:35:32,680 --> 00:35:36,220\n然后开始走回来使y增加\nthen I start going backwards as y increases.\n\n720\n00:35:37,720 --> 00:35:39,440\n这样就画出了一个圆\nSo that's how you make a circle.\n\n721\n00:35:39,720 --> 00:35:41,940\n有趣的是\nAnd the interesting thing to see is\n\n722\n00:35:41,940 --> 00:35:44,900\n这儿有一个程序能用这种方法画出一个圆\na little program that will draw a circle by this method.\n\n723\n00:35:44,940 --> 00:35:46,180\n实际上 不会画一出一个圆\nActually,this won't draw a circle\n\n724\n00:35:46,200 --> 00:35:48,320\n因为这个程序实际是一个积分器\nbecause it's a forward oil or integrator\n\n725\n00:35:48,320 --> 00:35:50,480\n并且最终会陷入死循环\nand will eventually spiral out and all that.\n\n726\n00:35:50,480 --> 00:35:52,900\n但陷入死循环前还是能画出一个圆的\nBut it'll draw a circle for a while before it starts spiraling.\n\n727\n00:35:54,080 --> 00:35:55,920\n然而 我们在这儿看到的是两个表征状态的变量\nHowever,what we see here is two state variables,\n\n728\n00:35:55,920 --> 00:35:56,660\nx和y\nx and y.\n\n729\n00:35:57,740 --> 00:35:59,220\n还有个迭代计算过程表明\nAnd there's an iteration that says,\n\n730\n00:35:59,600 --> 00:36:00,520\n要画一个圆\nin order to circle,\n\n731\n00:36:00,760 --> 00:36:01,740\n已经有了x和y\ngiven an x and y,\n\n732\n00:36:02,100 --> 00:36:04,520\n我想要的是x和y的下一组取值以用来画圆\nwhat I want is to circle with the next values of x and y\n\n733\n00:36:04,520 --> 00:36:08,580\n也就是x原有的值减去y和dt的乘积\nbeing the old value of x decrement by y times dt\n\n734\n00:36:08,580 --> 00:36:09,760\ndt就是时间变化\nwhere dt is the time step\n\n735\n00:36:10,320 --> 00:36:15,780\n还有y原有的值加上x的dt的乘积\nand the old value of y being implemented by x times dt,\n\n736\n00:36:16,080 --> 00:36:17,780\n然后就得到了x和y的新的取值\ngiving me the new values of x and y.\n\n737\n00:36:21,160 --> 00:36:22,940\n好了 现在大家对于两种不同的计算过程的感觉\nSo now you have a feeling\n\n738\n00:36:23,620 --> 00:36:25,740\n应该都有了一个直观的感觉\nfor at least two different kinds of processes\n\n739\n00:36:26,920 --> 00:36:29,720\n而这两种计算过程却可能是由几乎相同的程序产生的\nthat can be evolved by almost the same program.\n\n740\n00:36:32,300 --> 00:36:34,560\n像这样做了一点扰动分析之后\nAnd with a little bit of perturbation analysis like this,\n\n741\n00:36:35,340 --> 00:36:37,880\n如何小小地修改一下程序观察计算过程是怎样变化的\nhow you change a program a little bit and see how the process changes,\n\n742\n00:36:38,680 --> 00:36:39,800\n这样才能有直观的感受\nthat's how we get some intuition.\n\n743\n00:36:41,620 --> 00:36:43,080\n之后我们就会用到这样的直观感受\nPretty soon we're going to use that intuition\n\n744\n00:36:43,520 --> 00:36:45,180\n来构建大型的 恼人的 复杂的系统\nto build big,hairy,complicated systems.\n\n745\n00:36:46,360 --> 00:36:46,800\n谢谢\nThank you.\n\n746\n00:36:56,880 --> 00:37:06,660\n[音乐]\n[MUSIC PLAYING BY J.S.BACH]\n\n747\n00:37:06,660 --> 00:37:06,920\n教授 好了\nPROFESSOR: Well,\n\n748\n00:37:06,920 --> 00:37:11,100\n各位之前已经见过一次 对若干程序的简单的扰动分析\nyou've just seen a simple perturbational analysis of some programs.\n\n749\n00:37:11,600 --> 00:37:14,300\n我拿一个程序与另一个很相似的程序进行比较\nI took a program that was very similar to another program\n\n750\n00:37:14,300 --> 00:37:17,340\n观察他们如何演化出计算过程\nand looked at them both and saw how they evolved processes.\n\n751\n00:37:18,220 --> 00:37:19,520\n我想再给大家介绍点不同的东西\nI want to show you some variety\n\n752\n00:37:19,520 --> 00:37:22,720\n向大家展示程序可能具有的 别的一些计算过程和“形状”\nby showing you some other processes and shapes they may have.\n\n753\n00:37:24,280 --> 00:37:25,860\n同样地 我们将要举例非常简单的程序\nAgain,we're going to take very simple things,\n\n754\n00:37:26,140 --> 00:37:27,860\n简单到你都不想写的程序\nprograms that you wouldn't want to ever write.\n\n755\n00:37:29,040 --> 00:37:30,460\n那可能是最糟糕的方式\nThey would be probably the worst way\n\n756\n00:37:31,420 --> 00:37:33,060\n去进行一些计算过程\nof computing some of the things we're going to compute.\n\n757\n00:37:33,740 --> 00:37:35,060\n但我还是要展示给大家\nBut I'm just going to show you these things\n\n758\n00:37:35,400 --> 00:37:36,520\n是想要展现\nfor the purpose of feeling out\n\n759\n00:37:37,420 --> 00:37:41,320\n一个程序如何\nhow a program represents itself\n\n760\n00:37:41,600 --> 00:37:44,520\n在计算过程的求值中表现出自己的相应规则\nas the rule for the evolution of a process.\n\n761\n00:37:46,760 --> 00:37:48,800\n考虑一个有趣的问题\nSo let's consider a fun thing,\n\n762\n00:37:48,800 --> 00:37:49,920\n斐波那契数列\nthe Fibonacci numbers.\n\n763\n00:37:50,400 --> 00:37:52,020\n大家可能已经知道斐波那契数列了\nYou probably know about the Fibonacci numbers.\n\n764\n00:37:53,000 --> 00:37:54,280\n我记不清是谁了\nSomebody,I can't remember who,\n\n765\n00:37:54,660 --> 00:37:59,060\n有一个人对兔群的繁殖问题很感兴趣\nwas interested in the growth of piles of rabbits.\n\n766\n00:37:59,920 --> 00:38:01,140\n不管怎样\nAnd for some reason or other,\n\n767\n00:38:01,380 --> 00:38:04,820\n我们都知道兔群趋向于指数式增长\nthe piles of rabbits tend to grow exponentially,as we know.\n\n768\n00:38:05,520 --> 00:38:08,620\n对于这个过程我们有个不错的模型来解释\nAnd we have a nice model for this process,\n\n769\n00:38:08,620 --> 00:38:11,520\n由两个数开始算起\nis that we start with two numbers,\n\n770\n00:38:11,520 --> 00:38:12,360\n0和1\n0 and 1.\n\n771\n00:38:13,420 --> 00:38:16,560\n之后的每个数都是前两个数之和\nAnd then every number after this is the sum of the two previous.\n\n772\n00:38:17,840 --> 00:38:19,600\n于是接下来就是1\nSo we have here a 1.\n\n773\n00:38:20,100 --> 00:38:21,900\n然后这两数之和就是2\nThen the sum of these two is 2.\n\n774\n00:38:22,380 --> 00:38:23,900\n那两数之和是3\nThe sum of those two is 3.\n\n775\n00:38:24,300 --> 00:38:25,900\n那两数之和是5\nThe sum of those two is 5.\n\n776\n00:38:26,400 --> 00:38:27,900\n那两数之和是8\nThe sum of those two is 8.\n\n777\n00:38:28,280 --> 00:38:30,540\n那两数之和是13\nThe sum of those two is 13.\n\n778\n00:38:31,360 --> 00:38:33,260\n这是21\nThis is 21.\n\n779\n00:38:34,360 --> 00:38:37,740\n34 55\n34.55.\n\n780\n00:38:38,000 --> 00:38:38,520\n等等\nEt cetera.\n\n781\n00:38:40,300 --> 00:38:41,900\n如果给这些数字标上序号\nIf we start numbering these numbers,\n\n782\n00:38:42,360 --> 00:38:43,720\n第0个\nsay this is the zeroth one,\n\n783\n00:38:43,720 --> 00:38:44,380\n第1个\nthe first one,\n\n784\n00:38:44,380 --> 00:38:45,060\n第2个\nthe second one,\n\n785\n00:38:45,060 --> 00:38:45,620\n第3个\nthe third one,\n\n786\n00:38:45,620 --> 00:38:46,580\n第4个\nthe fourth one,\n\n787\n00:38:46,580 --> 00:38:47,040\n等等\net cetera.\n\n788\n00:38:47,420 --> 00:38:48,420\n这是第10个\nThis is the 10th one,\n\n789\n00:38:49,000 --> 00:38:50,040\n第10个斐波那契数\nthe 10th Fibonacci number.\n\n790\n00:38:51,620 --> 00:38:53,000\n这些数字增长很快\nThese numbers grow very fast\n\n791\n00:38:54,620 --> 00:38:55,360\n就像兔子们一样\nJust like rabbits.\n\n792\n00:38:55,640 --> 00:38:56,760\n为什么兔群是这样增长的呢\nWhy rabbits grow this way\n\n793\n00:38:56,760 --> 00:38:58,140\n我不会瞎猜\nI'm not going to hazard a guess.\n\n794\n00:38:59,320 --> 00:39:00,960\n接下来我要为大家展示\nNow,I'm going to try to write for you\n\n795\n00:39:01,280 --> 00:39:05,260\n写一个极简单的程序来计算斐波那契数\nthe very simplest program that computes Fibonacci numbers.\n\n796\n00:39:07,040 --> 00:39:09,620\n我想要的是一个程序\nIt's,ah,what I want is a program that,\n\n797\n00:39:09,620 --> 00:39:11,160\n输入一个n\ngiven an n,\n\n798\n00:39:12,320 --> 00:39:13,900\n就能输出第n个斐波那契数\nwill produce for me Fibonacci event.\n\n799\n00:39:17,860 --> 00:39:22,320\n我就写在这儿了\nOK?I'll write it right here.\n\n800\n00:39:27,860 --> 00:39:30,740\n想要得到第n个斐波那契数\nI want the Fibonacci of n,\n\n801\n00:39:30,740 --> 00:39:32,500\n也就是说 这是那个n\nwhich means the-- this is the n,\n\n802\n00:39:33,860 --> 00:39:34,880\n这是第n个斐波那契数\nand this is Fibonacci of n.\n\n803\n00:39:36,080 --> 00:39:37,080\n我这么写\nAnd here's the story.\n\n804\n00:39:37,400 --> 00:39:42,280\n如果n小于2\nIf n is less than 2,\n\n805\n00:39:42,740 --> 00:39:43,940\n那么答案就是n\nthen the result is n.\n\n806\n00:39:45,060 --> 00:39:46,040\n因为此时斐波那契数和序号相等\nBecause that's what these are.\n\n807\n00:39:46,920 --> 00:39:47,660\n这是最开始的规定\nThat's how you start it up.\n\n808\n00:39:48,700 --> 00:39:49,420\n否则\nOtherwise,\n\n809\n00:39:49,760 --> 00:39:55,180\n答案就是第n-1个斐波那契数\nthe result is the sum of Fib of n minus 1\n\n810\n00:39:58,220 --> 00:40:00,420\n和第n-2个斐波那契数的和\nand the Fibonacci number,n minus 2.\n\n811\n00:40:10,220 --> 00:40:11,260\n这是个很简单的\nSo this is a very simple,\n\n812\n00:40:11,440 --> 00:40:12,680\n很直接的\ndirect specification\n\n813\n00:40:12,960 --> 00:40:14,900\n求斐波那契数的实现\nof the description of Fibonacci numbers\n\n814\n00:40:15,540 --> 00:40:17,140\n就是根据斐波那契数的定义直接写出这个过程\nthat I gave you when I introduced those numbers.\n\n815\n00:40:19,260 --> 00:40:21,940\n用最简单可行的方式 直接描述了定义中的递归关系\nIt represents the recurrence relation in the simplest possible way.\n\n816\n00:40:23,260 --> 00:40:24,720\n现在 我们又如何解释这个过程呢\nNow,how do we use such a thing?\n\n817\n00:40:25,080 --> 00:40:25,980\n我们来分析一下这个过程所演化出的计算过程\nLet's draw this process.\n\n818\n00:40:26,840 --> 00:40:27,980\n让我们来看看这个过程都做了些什么\nLet's figure out what this does.\n\n819\n00:40:29,240 --> 00:40:32,080\n举一个简单的例子 求第4个斐波那契数\nLet's consider something very simple by computing Fibonacci of 4.\n\n820\n00:40:35,840 --> 00:40:37,020\n要求第4个斐波那契数\nTo compute Fibonacci of 4,\n\n821\n00:40:37,020 --> 00:40:37,620\n我应该怎么做呢\nwhat do I do?\n\n822\n00:40:38,720 --> 00:40:41,960\n根据过程的定义 4并不比2小\nWell,it says I have-- it's not less than 2.\n\n823\n00:40:42,740 --> 00:40:44,320\n因此答案就是两个数之和\nTherefore it's the sum of two things\n\n824\n00:40:45,160 --> 00:40:47,000\n然后 我又要求出\nWell,in order to compute that I have to compute,then,\n\n825\n00:40:47,460 --> 00:40:52,520\n第3个和第2个斐波那契数\nFibonacci of 3 and Fibonacci of 2\n\n826\n00:40:56,880 --> 00:40:58,620\n要求出第3个斐波那契数\nIn order to compute Fibonacci of 3,\n\n827\n00:40:58,960 --> 00:41:04,020\n我就得求出第2个斐波那契数和第1个斐波那契数\nI have to compute Fibonacci of 2 and Fibonacci of 1.\n\n828\n00:41:07,640 --> 00:41:09,280\n而为了求出第2个斐波那契数\nIn order to compute Fibonacci of 2,\n\n829\n00:41:09,800 --> 00:41:12,140\n就得求出第1个和第0个斐波那契数\nI have to compute Fibonacci of 1 and Fibonacci of 0.\n\n830\n00:41:16,500 --> 00:41:17,900\n要求第1个斐波那契数\nIn order to compute Fibonacci of 1,\n\n831\n00:41:17,900 --> 00:41:18,960\n答案就是1\nwell,the answer is 1.\n\n832\n00:41:19,880 --> 00:41:24,520\n这正是递归的边界条件\nThat's from the base case of this recursion.\n\n833\n00:41:25,740 --> 00:41:28,140\n而第0个斐波那契数\nAnd in order to compute Fibonacci of 0,\n\n834\n00:41:28,140 --> 00:41:29,080\n是0\nwell,that answer is 0,\n\n835\n00:41:29,080 --> 00:41:29,860\n也是递归的边界条件\nfrom the same base.\n\n836\n00:41:30,100 --> 00:41:31,660\n然后这儿有个1\nAnd here is a 1.\n\n837\n00:41:32,800 --> 00:41:36,140\n第2个斐波那契数就是第1个斐波那契数\nAnd Fibonacci of 2 is really the sum of Fibonacci of 1.\n\n838\n00:41:38,300 --> 00:41:39,220\n和第0个斐波那契数的和\nAnd Fib of 0,\n\n839\n00:41:40,580 --> 00:41:41,440\n分别求出它们\nin order to compute that,\n\n840\n00:41:41,480 --> 00:41:42,180\n就有了一个1\nI get a 1,\n\n841\n00:41:42,840 --> 00:41:43,860\n和一个0\nand here I've got a 0.\n\n842\n00:41:46,680 --> 00:41:47,500\n我画出了一棵树\nI've built a tree.\n\n843\n00:41:49,880 --> 00:41:52,440\n通过这棵树我们能看出一些结果\nNow,we can observe some things about this tree.\n\n844\n00:41:53,300 --> 00:41:53,920\n我们能发现为何\nWe can see why\n\n845\n00:41:53,920 --> 00:41:55,540\n这是个非常糟糕的\nthis is an extremely bad way\n\n846\n00:41:55,540 --> 00:41:56,720\n求斐波那契数的办法\nto compute Fibonacci numbers.\n\n847\n00:41:58,120 --> 00:42:00,020\n因为 为了求第4个斐波那契数\nBecause in order to compute Fibonacci of 4,\n\n848\n00:42:00,180 --> 00:42:02,740\n就得求两次第2个斐波那契数\nI had to compute Fibonacci of 2's sub-tree twice.\n\n849\n00:42:07,300 --> 00:42:09,000\n实际上 如果再多求一个斐波那契数\nIn fact,in order to add one more,\n\n850\n00:42:09,400 --> 00:42:11,000\n假设我想要求第5个斐波那契数\nsupposing I want to do Fibonacci of 5,\n\n851\n00:42:12,480 --> 00:42:13,540\n那我要做的就是\nwhat I really have to do then\n\n852\n00:42:13,540 --> 00:42:16,180\n求第4个斐波那契数和第3个斐波那契数的和\nis compute Fibonacci of 4 plus Fibonacci of 3.\n\n853\n00:42:17,760 --> 00:42:20,900\n但第3个斐波那契数已经求过一遍了\nBut Fibonacci of 3's sub-tree has already been built.\n\n854\n00:42:24,500 --> 00:42:29,200\n整个递归树描述了一个 指数时间复杂度的递归计算过程\nThis is a prescription for a process that's exponential in time.\n\n855\n00:42:30,220 --> 00:42:31,100\n只要多求一个斐波那契数\nTo add 1,\n\n856\n00:42:31,360 --> 00:42:32,800\n时间复杂度就得乘上一个数\nI have to multiply by something\n\n857\n00:42:32,800 --> 00:42:33,920\n因为多求一个斐波那契数 需要把已经计算过的过程\nbecause I take a proportion\n\n858\n00:42:33,920 --> 00:42:34,660\n再计算一次\nof the existing thing\n\n859\n00:42:34,660 --> 00:42:38,660\n时间复杂度就成比例地急剧增长\nand add it to itself to add one more step.\n\n860\n00:42:40,200 --> 00:42:47,760\n于是这个过程的时间复杂度就是\nSo this is a thing whose time complexity is order of\n\n861\n00:42:47,940 --> 00:42:50,600\n实际上就是O(Fib(n)) （Fib(n)指第n个斐波那契数）\n-- actually,it turns out to be Fibonacci-- of n.\n\n862\n00:42:55,940 --> 00:42:58,240\n这个过程的时间复杂度就是按斐波那契数列增长\nThere's a thing that grows exactly at Fibonacci numbers.\n\n863\n00:43:00,760 --> 00:43:01,560\n这很恐怖\nIt's a horrible thing.\n\n864\n00:43:02,240 --> 00:43:03,040\n你都不想这么求斐波那契数\nYou wouldn't want to do it.\n\n865\n00:43:03,440 --> 00:43:05,180\n时间复杂度这么增长\nThe reason why the time has to grow that way\n\n866\n00:43:05,180 --> 00:43:06,680\n是因为在这个模型中\nis because we're presuming in the model\n\n867\n00:43:06,680 --> 00:43:08,140\n之前给出的代换模型\n--the substitution model that I gave you,\n\n868\n00:43:08,140 --> 00:43:09,580\n我没在这儿形式化地应用代换模型\nwhich I'm not doing formally here,\n\n869\n00:43:10,280 --> 00:43:13,200\n只是简单地表示了一下\nI sort of now spit it out in a simple way--\n\n870\n00:43:14,000 --> 00:43:16,200\n我们假设所有事情都是按顺序完成的\nbut presuming that everything is done sequentially.\n\n871\n00:43:17,560 --> 00:43:21,180\n即这个递归树中每个节点都会被检查\nThat every one of these nodes in this tree has to be examined.\n\n872\n00:43:24,420 --> 00:43:25,580\n于是 由于树的节点数\nAnd so since the number of nodes\n\n873\n00:43:25,580 --> 00:43:27,660\n是按指数增长的\nin this tree grows exponentially,\n\n874\n00:43:28,080 --> 00:43:30,020\n因为要多求一个斐波那契数\nbecause I add a proportion of the existing nodes\n\n875\n00:43:30,760 --> 00:43:32,440\n就要把已经遍历过的节点再遍历一遍\nto the nodes I already have to add 1,\n\n876\n00:43:33,880 --> 00:43:36,800\n然后就发现时间复杂度呈爆炸式的指数增长\nthen I know I've got an exponential explosion here.\n\n877\n00:43:38,460 --> 00:43:39,840\n现在 再来考虑\nNow,let's see if we can think of\n\n878\n00:43:39,840 --> 00:43:41,200\n这个过程的空间复杂度\nhow much space this takes up.\n\n879\n00:43:44,160 --> 00:43:45,180\n空间复杂度不算太高\nWell,it's not so bad.\n\n880\n00:43:45,800 --> 00:43:47,360\n它主要取决于我们要记录多少信息\nIt depends on how much we have to remember\n\n881\n00:43:47,360 --> 00:43:48,620\n才能使整个计算过程得以持续进行\nin order to continue this thing running.\n\n882\n00:43:50,280 --> 00:43:51,220\n这个并不难\nWell,that's not so hard.\n\n883\n00:43:51,500 --> 00:43:52,220\n从这里看出\nIt says,gee,\n\n884\n00:43:52,400 --> 00:43:54,220\n想要知道我现在处于树中的什么位置\nin order to know where I am in this tree,\n\n885\n00:43:54,340 --> 00:43:55,880\n就要记录一条回到根节点的路径\nI have to have a path back to the root.\n\n886\n00:43:56,720 --> 00:43:57,160\n也就是说\nIn other words,\n\n887\n00:43:57,340 --> 00:43:57,800\n为了\nin order to--\n\n888\n00:43:57,800 --> 00:43:58,720\n考虑一下路径\nlet's consider the path.\n\n889\n00:43:58,720 --> 00:43:59,680\n我要把这个过程执行一遍\nI would have to execute this.\n\n890\n00:44:00,400 --> 00:44:01,180\n我说 啊 好吧\nI'd say,oh,yes\n\n891\n00:44:01,180 --> 00:44:02,220\n我向下走到这儿\nI'm going to go down here.\n\n892\n00:44:02,580 --> 00:44:03,940\n不用管方向\nI don't care which direction I go.\n\n893\n00:44:04,620 --> 00:44:05,660\n我这么走\nI have to do this.\n\n894\n00:44:06,100 --> 00:44:06,880\n这么走\nI have to then do this.\n\n895\n00:44:06,880 --> 00:44:08,880\n用一种有趣的方式遍历这棵树\nI have to traverse this tree in a sort of funny way.\n\n896\n00:44:11,660 --> 00:44:13,180\n又接着走这条有趣的小路\nI'm going to walk this nice little path.\n\n897\n00:44:13,580 --> 00:44:14,680\n回到了这里\nI come back to here.\n\n898\n00:44:15,400 --> 00:44:17,420\n好了我已经记住接下来要去哪儿了\nWell,I've got to remember where I'm going to be next.\n\n899\n00:44:18,180 --> 00:44:19,200\n我记在心里了\nI've got to keep that in mind.\n\n900\n00:44:19,800 --> 00:44:20,860\n于是我得知道已经遍历过的节点\nSo I have to know what I've done.\n\n901\n00:44:20,860 --> 00:44:22,020\n还得知道未遍历的节点\nI have to know what's left.\n\n902\n00:44:22,400 --> 00:44:25,600\n为了计算出第4个斐波那契数\nIn order to compute Fibonacci of 4,\n\n903\n00:44:25,600 --> 00:44:27,600\n某一时刻我会向下走到这儿\nat some point I'm going to have to be down here.\n\n904\n00:44:28,260 --> 00:44:29,740\n我还要记得\nAnd I have to remember\n\n905\n00:44:30,080 --> 00:44:31,360\n要回到这儿\nthat I have to go back to here\n\n906\n00:44:31,540 --> 00:44:32,960\n又回到这儿做一次加法\nand then go back to here to do an addition.\n\n907\n00:44:33,380 --> 00:44:34,420\n然后又走到这儿做一次加法\nAnd then go back to here to do an addition\n\n908\n00:44:34,420 --> 00:44:35,440\n之前还需要检查这个尚未检查的节点\nto something I haven't touched yet.\n\n909\n00:44:37,880 --> 00:44:40,340\n消耗的空间就是路径的长度\nThe amount of space that takes up is the path,\n\n910\n00:44:40,340 --> 00:44:41,160\n最长路径的长度\nthe longest path.\n\n911\n00:44:42,400 --> 00:44:43,360\n它有多长\nHow long it is.\n\n912\n00:44:45,620 --> 00:44:46,860\n长度就是n\nAnd that grows as n.\n\n913\n00:44:48,080 --> 00:44:48,860\n于是消耗的空间\nSo the space\n\n914\n00:44:50,640 --> 00:44:53,620\n因为那是树的最长下降深度\n-- because that's the length of the deepest line through the tree--\n\n915\n00:44:54,280 --> 00:44:56,220\n空间复杂度就是O(n)\nthe space is order of n.\n\n916\n00:44:58,880 --> 00:44:59,920\n可以看出这个过程时空效率都很低\nIt's a pretty bad process.\n\n917\n00:45:08,660 --> 00:45:10,260\n我想让各位获得的是\nNow,one thing I want to see from this\n\n918\n00:45:11,860 --> 00:45:13,520\n一种直观的感觉\nis a feeling\n\n919\n00:45:13,540 --> 00:45:14,440\n关于整个计算过程的直观感觉\nof what's going on here.\n\n920\n00:45:15,380 --> 00:45:16,560\n为何\nWhy are there--\n\n921\n00:45:17,140 --> 00:45:19,420\n这个程序是如何与整个计算过程联系起来的\nhow is this program related to this process?\n\n922\n00:45:20,800 --> 00:45:21,620\n在这儿 我们看到了什么\nWell,what are we seeing here?\n\n923\n00:45:21,800 --> 00:45:22,820\n这个程序实际上\nThere really are\n\n924\n00:45:23,740 --> 00:45:25,640\n只做了两件事\nonly two sorts of things this program does.\n\n925\n00:45:27,080 --> 00:45:28,620\n这个程序由两条规则组成\nThis program consists of two rules,\n\n926\n00:45:28,620 --> 00:45:29,100\n假如你也这么认为的话\nif you will.\n\n927\n00:45:29,560 --> 00:45:31,700\n第一条规则是 第n个斐波那契数\nOne rule that says Fibonacci of n\n\n928\n00:45:32,200 --> 00:45:36,200\n就是这里求和过程的结果\nis this sum that you see over here,\n\n929\n00:45:37,240 --> 00:45:39,400\n对应递归树中这样的一个节点\nwhich is a node that's shaped like this.\n\n930\n00:45:41,900 --> 00:45:44,880\n它指出要把整个过程分为两部分\nIt says that I break up something into two parts.\n\n931\n00:45:46,340 --> 00:45:49,340\n在有的情况下 看这里\nUnder some condition,under some condition over here\n\n932\n00:45:49,860 --> 00:45:51,040\nn比2大\nthat n is greater than 2,\n\n933\n00:45:56,500 --> 00:45:56,520\n比2小\nLess than 2.\n\n934\n00:45:56,520 --> 00:45:57,040\n递归树中对应节点就分为两部分\nthen the node breaks up into two parts.\n比2小\nLess than 2.\n\n935\n00:45:57,580 --> 00:45:58,560\n不 比2大 是的\nNo.Greater than 2.Yes.\n\n936\n00:46:01,600 --> 00:46:03,600\n还有一种可能\nThe other possibility is that\n\n937\n00:46:03,600 --> 00:46:05,140\n有的归约导致节点没有分成两部分\nI have a reduction that looks like this.\n\n938\n00:46:08,920 --> 00:46:09,780\n也就是这样的情况\nAnd that's this case.\n\n939\n00:46:10,960 --> 00:46:11,740\n如果比2小\nIf it's less than 2,\n\n940\n00:46:11,740 --> 00:46:12,780\n答案就是n本身\nthe answer is n itself.\n\n941\n00:46:14,200 --> 00:46:15,200\n我们在这儿看到的是\nSo what we're seeing here is that\n\n942\n00:46:15,360 --> 00:46:16,860\n构建起的计算过程\nthe process that got built\n\n943\n00:46:17,440 --> 00:46:18,740\n局部来看 每个节点\nlocally at every place\n\n944\n00:46:19,260 --> 00:46:20,440\n都是这条规则的实际体现\nis an instance of this rule.\n\n945\n00:46:21,920 --> 00:46:23,220\n这里是规则的一次实际体现\nHere's one instance of the rule.\n\n946\n00:46:23,800 --> 00:46:25,220\n这里是规则的又一次实际体现\nHere is another instance of the rule.\n\n947\n00:46:26,080 --> 00:46:27,380\n人们之所以认为\nAnd the reason why people think of\n\n948\n00:46:27,380 --> 00:46:29,260\n编程很难 确实挺难的\nprogramming as being hard,of course,\n\n949\n00:46:29,900 --> 00:46:32,160\n是因为编程实际是在编写一种通用规则\nis because you're writing down a general rule,\n\n950\n00:46:34,720 --> 00:46:36,340\n这种通用规则会被应用于很多实际情况\nwhich is going to be used for lots of instances,\n\n951\n00:46:37,000 --> 00:46:38,200\n而某一个特定的实际情况\nthat a particular instance--\n\n952\n00:46:38,840 --> 00:46:41,540\n而编写好的程序会为你处理每种特定的实际情况\nit's going to control each particular instance for you.\n\n953\n00:46:43,560 --> 00:46:44,640\n你必须写出这样的程序\nYou've got to write down something\n\n954\n00:46:44,640 --> 00:46:47,180\n它是通用的 并且考虑到变量\nthat's a general and in terms of variables,\n\n955\n00:46:47,180 --> 00:46:48,160\n你要考虑那些变量\nand you have to think of all the things\n\n956\n00:46:48,160 --> 00:46:49,540\n所有可能的取值\nthat could possibly fit in those variables,\n\n957\n00:46:49,800 --> 00:46:50,760\n所有这些最终都必须通向\nand all those have to lead to\n\n958\n00:46:50,760 --> 00:46:52,180\n你想要实现的计算过程\nthe process you want to work.\n\n959\n00:46:53,200 --> 00:46:55,400\n局部看来 你又得把计算过程分成\nLocally,you have to break up your process\n\n960\n00:46:56,100 --> 00:46:58,240\n可以表示出来的若干部分\ninto things that can be represented\n\n961\n00:46:58,240 --> 00:47:00,340\n考虑到这些非常特定的局部规则\nin terms of these very specific local rules.\n\n962\n00:47:03,220 --> 00:47:03,800\n好了 来看一下\nWell,let's see.\n\n963\n00:47:04,660 --> 00:47:06,800\n斐波那契数 当然了 不太有趣\nFibonaccis are,of course,not much fun.\n\n964\n00:47:07,820 --> 00:47:08,440\n不 其实还是挺有趣的\nYes,they are.\n\n965\n00:47:09,160 --> 00:47:10,920\n大家还会学习黄金分割等概念\nYou get something called the golden ratio,\n\n966\n00:47:12,100 --> 00:47:14,060\n并且说不定什么时候我们还有可能接触 更多的类似的东西\nand we may even see a lot of that some time.\n\n967\n00:47:15,080 --> 00:47:16,140\n好了 下面来讨论另一件事\nWell,let's talk about another thing.\n\n968\n00:47:16,600 --> 00:47:19,640\n有个很有名的游戏叫汉诺塔\nThere's a famous game called the Towers of Hanoi,\n\n969\n00:47:19,640 --> 00:47:20,280\n举这个例子是因为我教会大家\nbecause I want to teach you\n\n970\n00:47:20,280 --> 00:47:21,980\n如何递归地思考问题\nhow to think about things recursively.\n\n971\n00:47:23,860 --> 00:47:25,940\n游戏是这样的\nThe problem is this one:\n\n972\n00:47:26,860 --> 00:47:28,040\n我有一堆盘子\nI have a bunch of disks,\n\n973\n00:47:29,040 --> 00:47:30,060\n又有几根柱子\nI have a bunch of spikes,\n\n974\n00:47:31,500 --> 00:47:34,300\n传说在遥远的东方某地\nand it's rumored that somewhere in the Orient\n\n975\n00:47:35,100 --> 00:47:36,760\n有一个有64个盘子的汉诺塔\nthere is a 64-high tower,\n\n976\n00:47:37,080 --> 00:47:39,100\n僧侣们每天的工作就是\nand the job of various monks or something\n\n977\n00:47:39,200 --> 00:47:40,600\n移动盘子从一个柱子到另一个\nis to move these spikes\n\n978\n00:47:40,600 --> 00:47:41,860\n移动的规则很复杂\nin some complicated pattern\n\n979\n00:47:42,040 --> 00:47:44,540\n然后最终这些盘子\nso eventually-- these disks--\n\n980\n00:47:44,940 --> 00:47:48,520\n最终我把所有的盘子\nso eventually I moved all of the disks\n\n981\n00:47:48,660 --> 00:47:49,840\n从一个柱子移到了另一个柱子\nfrom one spike to the other.\n\n982\n00:47:50,380 --> 00:47:51,540\n如果有64个盘子\nAnd if it's 64 high,\n\n983\n00:47:52,000 --> 00:47:54,180\n就要移动2的64次方（减1 译者注）次\nand it's going to take 2 to the 64th moves,\n\n984\n00:47:54,980 --> 00:47:56,180\n要花费很长时间\nthen it's a long time.\n\n985\n00:47:57,820 --> 00:48:01,500\n僧侣们声称盘子移完之时即是宇宙终结之时\nThey claim that the universe ends when this is done.\n\n986\n00:48:03,420 --> 00:48:04,060\n好了\nWell,let's see.\n\n987\n00:48:05,580 --> 00:48:08,120\n构造一个递归过程的方法其实很简单\nThe way in which you would construct a recursive process\n\n988\n00:48:08,720 --> 00:48:09,660\n就是“想当然”\nis by wishful thinking.\n\n989\n00:48:11,580 --> 00:48:12,440\n你们要相信\nYou have to believe.\n\n990\n00:48:14,340 --> 00:48:15,240\n这个主意\nSo,the idea.\n\n991\n00:48:15,320 --> 00:48:18,360\n假如我想把这一堆盘子从这儿移到这儿\nSupposing I want to move this pile from here to here,\n\n992\n00:48:19,500 --> 00:48:21,360\n从1号柱移动到2号柱\nfrom spike one to spike two,\n\n993\n00:48:23,460 --> 00:48:24,540\n好吧 其实不怎么难\nwell,that's not so hard.\n\n994\n00:48:25,100 --> 00:48:26,540\n假如 不知怎么回事\nSee,supposing somehow,\n\n995\n00:48:27,000 --> 00:48:27,780\n好像有魔法在作用\nby some magic--\n\n996\n00:48:27,860 --> 00:48:28,860\n因为有个更简单的问题\nbecause I've got a simpler problem\n\n997\n00:48:29,020 --> 00:48:30,600\n我把3个盘子移到这里\n-- I move a three-high pile to here--\n\n998\n00:48:30,860 --> 00:48:32,000\n一次只能移动一个盘子\nI can only move one disk at a time,\n\n999\n00:48:32,000 --> 00:48:32,960\n不管我是怎么做到的\nso I don't even think how I did it.\n\n1000\n00:48:33,640 --> 00:48:34,800\n但假设我做到了\nBut supposing I could do that,\n\n1001\n00:48:36,300 --> 00:48:38,080\n那我只用拿起这个盘子\nwell,then I could just pick up this disk\n\n1002\n00:48:38,080 --> 00:48:38,680\n把它移到这里\nand move it here.\n\n1003\n00:48:41,140 --> 00:48:42,520\n现在问题就简单了\nAnd now I have a simple problem,\n\n1004\n00:48:42,620 --> 00:48:43,940\n把这3个盘子移到这里\nI have to move a three-high tower to here,\n\n1005\n00:48:44,680 --> 00:48:45,420\n之前已经做过了\nwhich is no problem.\n\n1006\n00:48:45,780 --> 00:48:47,780\n于是通过两次对3个盘子的移动\nSo by two moves of a three high tower\n\n1007\n00:48:47,780 --> 00:48:49,180\n再加上1次对一个盘子的移动\nplus one move of a single object.\n\n1008\n00:48:50,700 --> 00:48:52,760\n我就能把整堆盘子从这儿移动到这儿\nI can move the tower from here to here.\n\n1009\n00:48:55,260 --> 00:48:56,440\n不管怎样\nNow,whether or not--\n\n1010\n00:48:57,180 --> 00:48:58,440\n不管探究到什么程度\nthis is not obvious\n\n1011\n00:48:59,240 --> 00:49:00,980\n都不能明显看出整个过程是正确的\nin any deep way that this works.\n\n1012\n00:49:02,360 --> 00:49:02,980\n还有 为什么呢\nAnd why?\n\n1013\n00:49:03,900 --> 00:49:06,520\n为什么我就能假设\nNow why is it the case that I can presume,maybe,\n\n1014\n00:49:06,640 --> 00:49:07,920\n假设我能把成功移动这三个盘子\nthat I can move the three-high tower.\n\n1015\n00:49:11,080 --> 00:49:12,260\n好吧 这是因为\nWell the answer is because\n\n1016\n00:49:12,540 --> 00:49:13,660\n我总能减小问题的规模\nI'm always counting down,\n\n1017\n00:49:14,080 --> 00:49:15,960\n然后最终是0个盘子的移动问题\nand eventually I get down to zero-high tower,\n\n1018\n00:49:16,200 --> 00:49:17,800\n0个盘子不需要移动\nand a zero-high tower requires no moves.\n\n1019\n00:49:19,800 --> 00:49:21,680\n现在可以写出整个过程的算法了\nSo let's write the algorithm for that.\n\n1020\n00:49:23,820 --> 00:49:24,400\n很简单\nVery easy.\n\n1021\n00:49:26,120 --> 00:49:28,720\n我会给这些柱子编号\nI'm going to label these towers with numbers,\n\n1022\n00:49:28,720 --> 00:49:30,120\n但它们各自编号成什么无关紧要\nbut it doesn't matter what they're labelled with.\n\n1023\n00:49:30,780 --> 00:49:32,800\n问题就是把n个盘子\nAnd the problem is to move an n-high tower\n\n1024\n00:49:33,800 --> 00:49:36,440\n从一个起始柱移到终点柱\nfrom a spike called From to a spike called To\n\n1025\n00:49:36,620 --> 00:49:38,240\n另一个柱子作为中转 称作中转柱\nwith a particular spike called Spare.\n\n1026\n00:49:39,520 --> 00:49:40,200\n这就是主要的过程\nThat's what we're going to do.\n\n1027\n00:49:48,700 --> 00:49:52,120\n用这个我非形式化描述的算法\nUsing the algorithm I informally described to you,\n\n1028\n00:49:52,720 --> 00:50:01,700\n把n个盘子从起始柱移到终点柱 另一个柱子作为中转\nmove of a n-high tower from From to To with a Spare.\n\n1029\n00:50:05,940 --> 00:50:08,480\n接着就有两种情况了\nWell,I've got two cases,\n\n1030\n00:50:09,220 --> 00:50:10,480\n就要分析都是怎样的情况\nand this is a case analysis,\n\n1031\n00:50:10,940 --> 00:50:14,360\n就像之前所做的分析一样\njust like it is in all the other things we've done.\n\n1032\n00:50:20,920 --> 00:50:21,840\n如果n等于0 那么\nIf n is 0,then\n\n1033\n00:50:22,780 --> 00:50:24,940\n我会输出一些东西 输出\"Done\"\n-- I'm going to put out some answers-- Done,we'll say.\n\n1034\n00:50:26,560 --> 00:50:27,560\n我不知道那代表什么意思\nI don't know what that means\n\n1035\n00:50:29,360 --> 00:50:31,160\n因为我们也不会遇到这样的情况\nBecause we'll never use that answer for anything.\n\n1036\n00:50:31,640 --> 00:50:32,620\n我们还是会移动盘子的\nWe're going to do these moves.\n\n1037\n00:50:34,000 --> 00:50:34,380\n否则\nElse.\n\n1038\n00:50:36,280 --> 00:50:37,320\n就移动一次\nI'm going to do a move.\n\n1039\n00:50:39,900 --> 00:50:42,360\n移动少于n个盘子\nMove a tower of height less than n,\n\n1040\n00:50:44,160 --> 00:50:46,300\n也就是n-1个盘子\nthe decrement of n height.\n\n1041\n00:50:47,740 --> 00:50:50,080\n把它们移到中转柱上\nNow,I'm going to move it to the Spare tower.\n\n1042\n00:50:50,720 --> 00:50:51,720\n整体的思想就是\nThe whole idea now\n\n1043\n00:50:52,020 --> 00:50:53,880\n把它们从这里移到这里\nis to move this from here to here,\n\n1044\n00:50:54,940 --> 00:50:55,600\n移到中转柱\nto the Spare tower\n\n1045\n00:50:55,860 --> 00:50:57,160\n从起始柱到中转柱\n-- so from From to Spare--\n\n1046\n00:51:02,340 --> 00:51:04,380\n用终点柱作为中转\nusing To as a spare tower.\n\n1047\n00:51:08,560 --> 00:51:10,080\n之后某个时候\nLater,somewhere later,\n\n1048\n00:51:10,080 --> 00:51:14,800\n我就会移动之前的那n个盘子\nI'm going to move that same n-high tower,\n\n1049\n00:51:15,240 --> 00:51:16,160\n在那之前已经完成了这个盘子的移动\nafter I've done this.\n\n1050\n00:51:17,340 --> 00:51:20,200\n要移动n个盘子同样的道理就要上面的n-1个盘子\nGoing to move that same n minus one-high tower\n\n1051\n00:51:20,620 --> 00:51:23,540\n从中转柱移到终点柱\nfrom the Spare tower to the To tower\n\n1052\n00:51:23,940 --> 00:51:25,860\n用起始柱作为中转\nusing the From tower as my spare.\n\n1053\n00:51:29,060 --> 00:51:39,040\n编写成代码就是从中转柱移动到终点柱\nSo the Spare tower to the To tower\n\n1054\n00:51:40,040 --> 00:51:44,140\n用起始柱作为中转\nusing the From as the spare.\n\n1055\n00:51:48,440 --> 00:51:49,580\n当进行到这种情况\nAll I have to do now\n\n1056\n00:51:50,020 --> 00:51:51,840\n剩下要做的事情就是\nis when I've gotten it in this condition,\n\n1057\n00:51:52,100 --> 00:51:55,080\n现在就是这种情况\nbetween these two moves of a whole tower\n\n1058\n00:51:56,260 --> 00:51:57,420\n在两次移动同一堆盘子之间\n-- I've got it into that condition--\n\n1059\n00:51:57,580 --> 00:52:00,480\n只需移动一个盘子\nnow I just have to move one disk.\n\n1060\n00:52:02,820 --> 00:52:03,380\n所以我想要说的就是\nSo I'm going to say that\n\n1061\n00:52:03,380 --> 00:52:04,300\n有个什么过程输出一条信息 表示做了一次盘子的移动\nsome things are printing a move\n\n1062\n00:52:04,300 --> 00:52:05,200\n不管这个过程具体怎么实现的\nand I don't care how it works.\n\n1063\n00:52:11,340 --> 00:52:13,900\n把盘子从起始柱移动到终点柱\nFrom to To.\n\n1064\n00:52:17,420 --> 00:52:19,780\n现在大家就能明白为何我在这个时候举这样一个例子\nNow,you see the reason why I'm bringing this up\n\n1065\n00:52:19,780 --> 00:52:23,060\n是因为在某种程度上\nat this moment is this is an almost identical program\n\n1066\n00:52:23,060 --> 00:52:25,060\n这个程序和之前这个程序几乎一样\nto this one in some sense.\n\n1067\n00:52:26,600 --> 00:52:28,940\n尽管它们所求解的问题不一样\nIt's not computing the same mathematical quantity,\n\n1068\n00:52:29,240 --> 00:52:30,940\n演化出的递归树也不尽相同\nit's not exactly the same tree,\n\n1069\n00:52:31,220 --> 00:52:32,320\n但不管怎样都会在计算过程中演化出一棵递归树\nbut it's going to produce a tree.\n\n1070\n00:52:34,300 --> 00:52:36,180\n移动这些盘子的过程\nThe general way of making these moves\n\n1071\n00:52:36,920 --> 00:52:39,580\n会导致生成一棵指数树\nis going to lead to an exponential tree.\n\n1072\n00:52:41,380 --> 00:52:43,060\n好了 接下来试着来移动4个盘子\nWell,let's do this four-high.\n\n1073\n00:52:44,100 --> 00:52:47,220\n我还是得看着小抄来移盘子\nI have my little crib sheet here\n\n1074\n00:52:49,240 --> 00:52:50,400\n不然会弄错\notherwise I get confused.\n\n1075\n00:52:54,360 --> 00:52:56,480\n好了 下面形式化地提出这个问题\nWell,what I'm going to put in is the question of\n\n1076\n00:52:56,700 --> 00:53:05,400\n把4个摞在一起的盘子\nmove a tower of height four\n\n1077\n00:53:06,240 --> 00:53:08,500\n从1号柱子移动到2号\nfrom one to spike two\n\n1078\n00:53:08,660 --> 00:53:10,460\n用3号柱子作为中转\nusing spike three as a spare.\n\n1079\n00:53:11,680 --> 00:53:12,720\n这就是接下来我要做的\nThat's all I'm really going to do.\n\n1080\n00:53:13,860 --> 00:53:15,140\n好吧 开始吧\nYou know,let's just do it.\n\n1081\n00:53:15,140 --> 00:53:16,120\n我不打算写出\nI'm not going to worry about\n\n1082\n00:53:16,120 --> 00:53:17,580\n过程执行的具体步骤\nwriting out the trace of this.\n\n1083\n00:53:17,620 --> 00:53:18,540\n你自己可以做到\nYou can do that yourself\n\n1084\n00:53:19,560 --> 00:53:20,380\n因为那很简单\nbecause it's very simple.\n\n1085\n00:53:21,620 --> 00:53:24,580\n我要把1号柱子上的一个盘子移动到3号柱子上\nI'm going to move disk one to disk three.\n\n1086\n00:53:26,300 --> 00:53:28,100\n这是怎么回事呢\nAnd how do I get to move disk one to disk three?\n\n1087\n00:53:28,280 --> 00:53:28,940\n我怎么知道要这么做呢\nHow do I know that?\n\n1088\n00:53:29,180 --> 00:53:30,820\n好吧 我想还是得查看一下程序执行的具体步骤\nWell,I suppose I have to look at the trace a little bit.\n\n1089\n00:53:32,420 --> 00:53:33,220\n才能明白我这是在做什么\nWhat am I doing here?\n\n1090\n00:53:33,520 --> 00:53:34,440\n好吧 这个不等于\nWell,and this is not--\n\n1091\n00:53:34,440 --> 00:53:35,340\nn不等于0\nn is not zero.\n\n1092\n00:53:36,400 --> 00:53:37,860\n那我看一下这里过程的定义\nSo I'm going to look down here.\n\n1093\n00:53:38,340 --> 00:53:40,220\n这得需要两次移动\nThis is going to require doing two moves.\n\n1094\n00:53:40,640 --> 00:53:41,680\n只观察第一次吧\nI'm only going to look at the first one.\n\n1095\n00:53:41,940 --> 00:53:43,160\n第一次是说把\nIt's going to require moving--\n\n1096\n00:53:47,500 --> 00:53:48,880\n我怎么写成了移动一座塔\nwhy do I have move tower?\n\n1097\n00:53:48,880 --> 00:53:50,340\n塔可不好移\nIt makes it harder for me to move.\n\n1098\n00:53:52,580 --> 00:53:56,280\n我要移动摞成一摞的3个盘子\nI'm going to move a three-high tower\n\n1099\n00:53:57,560 --> 00:53:59,460\n从起始柱\nfrom the From place,\n\n1100\n00:53:59,580 --> 00:54:00,340\n也就是4号柱（教授不小心犯错 译者注）\nwhich is four,\n\n1101\n00:54:01,400 --> 00:54:02,160\n移动到中转柱\nto the Spare,\n\n1102\n00:54:02,320 --> 00:54:03,140\n即2号柱\nwhich is two,\n\n1103\n00:54:03,900 --> 00:54:06,400\n用3号柱\nusing three as my\n\n1104\n00:54:07,960 --> 00:54:09,800\n不 用 用\n-- no,using,using--\n\n1105\n00:54:09,980 --> 00:54:15,740\n学生 [听不清]\nSTUDENT: [INAUDIBLE PHRASE]\n\n1106\n00:54:15,820 --> 00:54:16,920\n教授 啊 是这样 抱歉\nPROFESSOR: Yes,I'm sorry.\n\n1107\n00:54:17,540 --> 00:54:18,880\n从2号柱\nFrom two--\n\n1108\n00:54:19,340 --> 00:54:25,680\n从1号柱到3号柱用2号柱作为中转\nfrom one to three using two as my spare.\n\n1109\n00:54:25,900 --> 00:54:26,200\n这就对了\nThat's right.\n\n1110\n00:54:27,140 --> 00:54:31,200\n之后这儿还有一次移动\nAnd then there's another move over here afterwards.\n\n1111\n00:54:32,800 --> 00:54:33,580\n现在可以说\nSo now I say,\n\n1112\n00:54:33,880 --> 00:54:34,320\n啊 是的\noh,yes,\n\n1113\n00:54:34,420 --> 00:54:37,880\n接下来还得把之上两个盘子\nthat requires me moving a two-high tower\n\n1114\n00:54:38,680 --> 00:54:42,140\n从1号柱移动到2号柱 用3号柱作为中转\nfrom one to two using three as a spare.\n\n1115\n00:54:43,000 --> 00:54:43,960\n同样的还得再移一次\nAnd so,are the same,\n\n1116\n00:54:44,580 --> 00:54:45,980\n接下来 又要移动\nand that's going to require me moving\n\n1117\n00:54:47,540 --> 00:54:52,000\n一个盘子 从1号柱到2号柱\na one-high tower from one to three\n\n1118\n00:54:52,180 --> 00:54:53,220\n用2号柱作为中转\nusing two as a spare.\n\n1119\n00:54:57,500 --> 00:54:59,300\n好了 当然之后还得再移一次\nWell,and then there's lots of other things to be done.\n\n1120\n00:55:03,260 --> 00:55:05,080\n于是我把1个盘子\nSo I move my one-high tower\n\n1121\n00:55:06,160 --> 00:55:09,220\n从1号柱移动到3号柱 用2号柱作为中转\nfrom one to three using two as a spare,\n\n1122\n00:55:09,220 --> 00:55:10,300\n实际上没用到2号柱\nwhich I didn't do anything with.\n\n1123\n00:55:11,140 --> 00:55:12,800\n好了 整个过程还是非常简单的\nWell,this thing just proceeds very simply.\n\n1124\n00:55:15,300 --> 00:55:16,660\n接下来我把这个盘子从1号柱移到2号柱\nI move this from one to two.\n\n1125\n00:55:17,360 --> 00:55:19,260\n然后把这个盘子从3号柱移动到2号柱\nAnd I move this disk from three to two.\n\n1126\n00:55:20,980 --> 00:55:22,120\n其实我不想移了\nAnd I don't really want to do it,\n\n1127\n00:55:22,520 --> 00:55:23,800\n但还得继续 从1到3\nbut I move from one to three.\n\n1128\n00:55:24,680 --> 00:55:26,480\n然后从2到1\nThen I move two to one.\n\n1129\n00:55:29,040 --> 00:55:30,400\n从2到3\nThen I move two to three.\n\n1130\n00:55:31,940 --> 00:55:34,900\n从1到3\nThen one to three.\n\n1131\n00:55:35,940 --> 00:55:36,820\n1到2\nOne to two.\n\n1132\n00:55:39,360 --> 00:55:41,040\n3到2\nThree to two.\n\n1133\n00:55:41,800 --> 00:55:42,560\n3到1\nThree to one.\n\n1134\n00:55:44,060 --> 00:55:45,540\n当然了这是因为我之前已经准备好了\nThis all got worked out beforehand,of course.\n\n1135\n00:55:46,040 --> 00:55:46,700\n2到1\nTwo to one.\n\n1136\n00:55:47,480 --> 00:55:48,980\n3到2\nThree to two.\n\n1137\n00:55:49,780 --> 00:55:51,420\n1到3\nOne to three.\n\n1138\n00:55:52,920 --> 00:55:54,040\n学生： [听不清]\nSTUDENT: [INAUDIBLE PHRASE].\n\n1139\n00:55:54,060 --> 00:55:54,840\n教授：噢 从1到3\nPROFESSOR: Oh,one to three.\n\n1140\n00:55:54,840 --> 00:55:55,780\n抱歉 谢谢提醒\nExcuse me.Thank you.\n\n1141\n00:55:56,080 --> 00:55:56,840\n1到2\nOne to two.\n\n1142\n00:55:58,720 --> 00:56:01,520\n然后3到2 呼\nAnd then three to two.Whew.\n\n1143\n00:56:03,880 --> 00:56:05,920\n现在请大家思考\nNow what I'd like you to think about,\n\n1144\n00:56:07,120 --> 00:56:08,820\n你们刚才看到的是解决这个问题的递归算法\nyou just saw a recursive algorithm for doing this,\n\n1145\n00:56:09,100 --> 00:56:10,340\n显然要耗费指数级的时间\nand it takes exponential time,of course.\n\n1146\n00:56:11,120 --> 00:56:12,220\n不知道是否有别的算法\nNow,I don't know if there's any algorithm\n\n1147\n00:56:12,220 --> 00:56:14,060\n不用耗费指数级的时间 它一定会耗费指数级的时间\nthat doesn't take exponential time-- it has to.\n\n1148\n00:56:14,440 --> 00:56:15,920\n因为我每次只能移动一个盘子\nAs I'm doing one operation\n\n1149\n00:56:15,920 --> 00:56:17,240\n每次只能移动一个盘子\n-- I can only move one thing at a time--\n\n1150\n00:56:17,540 --> 00:56:19,240\n没有什么算法不用耗费指数级的时间\nthere's no algorithm that's not going to take exponential time.\n\n1151\n00:56:21,420 --> 00:56:22,640\n但是 你能写出迭代的算法\nBut can you write an iterative algorithm\n\n1152\n00:56:23,640 --> 00:56:25,160\n而不是递归的算法么\nrather than a recursive algorithm for doing this?\n\n1153\n00:56:28,360 --> 00:56:30,260\n我一直爱琢磨\nOne of the sort of little things I like to think about\n\n1154\n00:56:32,320 --> 00:56:34,840\n能否给出一个算法\nCan you write one that,\n\n1155\n00:56:35,040 --> 00:56:39,060\n不是像我描述的这样\nin fact,doesn't break this problem\n\n1156\n00:56:39,080 --> 00:56:40,560\n把一个问题分解成两个子问题\ninto two sub-problems the way I described,\n\n1157\n00:56:41,020 --> 00:56:43,200\n而是用一个更局部的规则\nbut rather proceeds a step at a time\n\n1158\n00:56:43,260 --> 00:56:44,800\n一次演化出整个计算过程\nusing a more local rule.\n\n1159\n00:56:47,760 --> 00:56:48,480\n那可能会很有趣\nThat might be fun.\n\n1160\n00:56:50,340 --> 00:56:51,720\n谢谢大家 第三部分结束\nThank you so much for the third segment.\n\n1161\n00:56:55,880 --> 00:56:56,380\n有什么问题要问么\nAre there questions?\n\n1162\n00:56:57,400 --> 00:56:58,280\n学生 我想知道有没有什么办法\nSTUDENT: I wonder if there's a way\n\n1163\n00:56:58,280 --> 00:57:01,660\n能减小递归过程的代价\nto reduce a tree or recursion problem,\n\n1164\n00:57:02,060 --> 00:57:05,660\n能否把中间过程\nhow do you save the intermediate work\n\n1165\n00:57:05,760 --> 00:57:08,180\n计算出的斐波那契数保存下来\nyou have done in computing the Fibonacci number?\n\n1166\n00:57:09,000 --> 00:57:10,100\n教授 呃 好吧 实际上\nPROFESSOR: Oh,well,in fact,one way,that\n\n1167\n00:57:11,200 --> 00:57:13,120\n你刚才说的就是一种办法\none of the ways to do is what you just said.\n\n1168\n00:57:13,580 --> 00:57:16,500\n你说  把中间过程的结果保存下来 是吧\nYou said,I save the intermediate work.OK?\n\n1169\n00:57:16,620 --> 00:57:18,360\n好的 我告诉你\nWell,let me tell you\n\n1170\n00:57:18,940 --> 00:57:20,100\n再次说一下 我们后面会见到\n-- this,again,we'll see later--\n\n1171\n00:57:20,720 --> 00:57:21,820\n但现在假设就是这种情形\nbut suppose it's the case\n\n1172\n00:57:22,360 --> 00:57:24,060\n不论何时做怎样的计算\nthat anytime I compute anything,\n\n1173\n00:57:24,340 --> 00:57:25,720\n所有的这些斐波那契数\nany one of these Fibonacci numbers,\n\n1174\n00:57:26,400 --> 00:57:27,620\n我记录一个表\nI remember the table\n\n1175\n00:57:27,900 --> 00:57:28,920\n在表中查询\nthat takes only linear time\n\n1176\n00:57:28,920 --> 00:57:31,580\n只用线性的时间\nto look up the answer.\n\n1177\n00:57:32,720 --> 00:57:33,660\n如果我已经计算过了\nThen if I ever see it again,\n\n1178\n00:57:33,660 --> 00:57:35,340\n就不再递归地求解了\ninstead of doing the expansional tree,\n\n1179\n00:57:35,620 --> 00:57:36,100\n是直接在表中查询\nI look it up.\n\n1180\n00:57:36,700 --> 00:57:37,940\n我把问题\nI've just transformed my problem\n\n1181\n00:57:38,780 --> 00:57:39,840\n变得简单多了\ninto a problem that's much simpler.\n\n1182\n00:57:40,980 --> 00:57:41,620\n当然\nNow,of course,\n\n1183\n00:57:42,260 --> 00:57:43,560\n这种方法已经被使用了\nthere are the way to do this,as well.\n\n1184\n00:57:44,240 --> 00:57:45,340\n这种方法叫作记忆化\nThat one's called memoization,\n\n1185\n00:57:45,340 --> 00:57:47,620\n这学期你们就会遇到\nand you'll see it sometime later in this term.\n\n1186\n00:57:48,240 --> 00:57:53,280\n但我认为还有个方法是线性时间复杂度的\nBut I suppose there's a very simple linear time and,\n\n1187\n00:57:53,360 --> 00:57:55,920\n实际上 是用迭代模型计算斐波那契数\nin fact,iterative model for computing Fibonaccis,\n\n1188\n00:57:56,660 --> 00:57:58,200\n这也是需要各位坐下来仔细思考的\nand that's another thing you should sit down and work out.\n\n1189\n00:58:00,080 --> 00:58:00,720\n这很重要\nThat's important.\n\n1190\n00:58:01,260 --> 00:58:02,620\n明白怎么运用迭代模型很重要\nIt's important to see how to do this.\n\n1191\n00:58:05,200 --> 00:58:06,060\n希望大家多练习一下\nI want you to practice.\n\n1192\n00:58:06,500 --> 00:58:08,100\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n1193\n00:58:08,100 --> 00:58:10,240\n本项目主页\nhttps://github.com/FoOTOo/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec2a.srt",
    "content": "﻿1\r\n00:00:00,000 --> 00:00:05,000\r\n哈尔滨工业大学 IBM技术中心\r\n倾情制作\r\n\r\n2\r\n00:00:05,100 --> 00:00:10,000\r\n压制&&特效：蔡钟毓（JohnTitor）\r\n翻译：徐梓翔（Dyul）\r\n\r\n3\r\n00:00:10,000 --> 00:00:15,000\r\n特别感谢：裘宗燕教授\r\n时间&&轴校对：邓雄飞（Dysprosium）\r\n\r\n4\r\n00:00:15,800 --> 00:00:20,500\r\n高阶过程\r\nHigher-order Procedures\r\n\r\n5\r\n00:00:25,280 --> 00:00:26,580\r\n教授：昨天的内容还算容易\r\nPROFESSOR: Well, yesterday was easy.\r\n\r\n6\r\n00:00:27,600 --> 00:00:29,440\r\n你们了解到了所有的编程规则\r\nYou learned all of the rules of programming\r\n\r\n7\r\n00:00:30,740 --> 00:00:33,440\r\n那些几乎是所有的规则了\r\nand lived Almost all of them.\r\n\r\n8\r\n00:00:34,600 --> 00:00:37,100\r\n所以此刻 你们算得上是所谓的---\r\nAnd so at this point, you're now certified programmers\r\n\r\n9\r\n00:00:38,060 --> 00:00:38,740\r\n合格的程序员了\r\n-- it says.\r\n\r\n10\r\n00:00:39,700 --> 00:00:43,860\r\n不过 我觉得其实是 啊...\r\nHowever, I suppose what we did is we, aah,\r\n\r\n11\r\n00:00:46,720 --> 00:00:50,660\r\n其实只是给你们尝了点甜头\r\nsort of got you a little bit of into an easy state.\r\n\r\n12\r\n00:00:51,280 --> 00:00:54,840\r\n此时此刻 你可能还在认为这门课就像\r\nHere, you still believe it's possible that this might be programming\r\n\r\n13\r\n00:00:54,840 --> 00:00:57,640\r\n用BASIC语言或者Pascal语言的某种奇葩语法写程序\r\nin BASIC or Pascal with just a funny syntax.\r\n\r\n14\r\n00:00:59,140 --> 00:01:04,440\r\n然而就在今天 这种错觉将会被颠覆\r\nToday, that illusion-- or you can no longer support that belief.\r\n\r\n15\r\n00:01:04,780 --> 00:01:07,140\r\n我们即将做的事 就是要彻底粉碎这种想法\r\nWhat we're going to do today is going to completely smash that.\r\n\r\n16\r\n00:01:08,080 --> 00:01:13,420\r\n接下来 我会先在黑板上写一些程序\r\nSo let's start out by writing a few programs on the blackboard\r\n\r\n17\r\n00:01:13,420 --> 00:01:15,020\r\n它们之间有很多相似之处\r\nthat have a lot in common with each other\r\n\r\n18\r\n00:01:15,960 --> 00:01:18,360\r\n我们要做的是尝试将它们抽象出来\r\nWhat we're going to do is try to make them abstractions\r\n\r\n19\r\n00:01:18,820 --> 00:01:22,960\r\n这过程并不如在其它大多数语言中那么显而易见\r\nthat are not ones that are easy to make in most languages.\r\n\r\n20\r\n00:01:23,740 --> 00:01:25,080\r\n让我们先从其它语言也能完成的\r\nLet's start with some very simple ones\r\n\r\n21\r\n00:01:25,080 --> 00:01:26,520\r\n简单的例子开始\r\nthat you can make in most languages.\r\n\r\n22\r\n00:01:27,640 --> 00:01:33,680\r\n假设 我有一个求和一组整数的数学表达式\r\nSupposing I want to write the mathematical expression which adds up a bunch of integers.\r\n\r\n23\r\n00:01:34,140 --> 00:01:41,100\r\n比如 我写下的这个表达式 以I为索引 求和从A到B的整数\r\nSo if I wanted to write down and say the sum from i equal a to b on i.\r\n\r\n24\r\n00:01:41,100 --> 00:01:44,820\r\n你们知道用数学公式可以很方便地计算出它的结果\r\nNow, you know that that's an easy thing to compute in a closed form for it,\r\n\r\n25\r\n00:01:44,820 --> 00:01:45,760\r\n但我的重点不在此\r\nand I'm not interested in that.\r\n\r\n26\r\n00:01:45,760 --> 00:01:48,180\r\n我想要写一个能够求和那些整数程序\r\nBut I'm going to write a program that adds up those integers.\r\n\r\n27\r\n00:01:48,960 --> 00:01:52,880\r\n我们能够很容易地想到\r\nWell, that's rather easy to do to say\r\n\r\n28\r\n00:01:53,300 --> 00:02:07,400\r\n定义求和从A到B的整数的过程SUM-INT为\r\nI want to define the sum of the integers from a to b to be\r\n\r\n29\r\n00:02:07,780 --> 00:02:10,640\r\n接下来有两种可能性\r\nwell, it's the following two possibilities.\r\n\r\n30\r\n00:02:10,900 --> 00:02:13,420\r\n如果A大于B\r\nIf a is greater than b,\r\n\r\n31\r\n00:02:15,100 --> 00:02:18,220\r\n毋庸置疑 答案就是0\r\nwell, then there's nothing to be done and the answer is zero.\r\n\r\n32\r\n00:02:18,980 --> 00:02:21,220\r\n你要以递归的方式思考问题\r\nThis is how you're going to have to think recursively.\r\n\r\n33\r\n00:02:22,160 --> 00:02:25,020\r\n比如 假如我知道某个简单情形的答案\r\nYou're going to say if I have an easy case that I know the answer to,\r\n\r\n34\r\n00:02:25,140 --> 00:02:25,980\r\n就可以直接将其作为结果\r\njust write it down.\r\n\r\n35\r\n00:02:26,220 --> 00:02:30,420\r\n否则 我就需要将这个问题简化\r\nOtherwise, I'm going to try to reduce this problem to a simpler problem.\r\n\r\n36\r\n00:02:30,620 --> 00:02:31,560\r\n比如在这个程序里\r\nAnd maybe in this case,\r\n\r\n37\r\n00:02:31,560 --> 00:02:33,240\r\n我要简化出一个子问题\r\nI'm going to make a subproblem of the simpler problem\r\n\r\n38\r\n00:02:33,240 --> 00:02:34,620\r\n然后再做一些工作从而得出结果\r\nand then do something to the result.\r\n\r\n39\r\n00:02:35,160 --> 00:02:38,700\r\n所以针对这个程序 最简单的处理方式是\r\nSo the easiest way to do this is say that\r\n\r\n40\r\n00:02:38,700 --> 00:02:43,340\r\n将下标 在这里是A\r\nI'm going to add the index, which in this case is a,\r\n\r\n41\r\n00:02:44,520 --> 00:02:57,500\r\n加上A+1到B的整数的求和结果\r\nto the result of adding up the integers from a plus 1 to b.\r\n\r\n42\r\n00:03:02,360 --> 00:03:04,860\r\n现在你们应该都能看懂这个定义了\r\nNow, at this point, you should have no trouble looking at such a definition.\r\n\r\n43\r\n00:03:05,740 --> 00:03:09,860\r\n实际上 总的来说 要想得出这个过程定义还是有一些困难的\r\nIndeed, coming up with such a thing might be a little hard in synthesis,\r\n\r\n44\r\n00:03:10,180 --> 00:03:12,500\r\n但要想读明白还是比较容易的\r\nbut being able to read it at this point should be easy.\r\n\r\n45\r\n00:03:13,400 --> 00:03:15,880\r\n现在我想告诉你们的是\r\nAnd what it says to you is, well,\r\n\r\n46\r\n00:03:16,440 --> 00:03:18,960\r\n这个是我想要求解的子问题\r\nhere is the subproblem I'm going to solve.\r\n\r\n47\r\n00:03:19,120 --> 00:03:21,560\r\n我要求和的是\r\nI'm going to try to add up the integers,\r\n\r\n48\r\n00:03:21,880 --> 00:03:25,540\r\n比整个问题的规模少一的整数序列\r\none fewer integer than I added up for the the whole problem.\r\n\r\n49\r\n00:03:26,440 --> 00:03:28,100\r\n接下来需要求和的整数序列的数目会一个个减少\r\nI'm adding up the one fewer one,\r\n\r\n50\r\n00:03:28,820 --> 00:03:32,680\r\n最后 当这个子问题求解完毕后 只要再加上a\r\nand that subproblem, once I've solved it, I'm going to add a to that,\r\n\r\n51\r\n00:03:34,200 --> 00:03:35,920\r\n就能得到整个问题的答案了\r\nand that will be the answer to this problem.\r\n\r\n52\r\n00:03:38,140 --> 00:03:40,400\r\n并且 这里的最简单的情形 我不用做任何处理\r\nAnd the simplest case, I don't have to do any work.\r\n\r\n53\r\n00:03:41,560 --> 00:03:45,160\r\n接下来 我要给出另一个类似的简单问题---\r\nNow, I'm also going to write down another simple one just like this,\r\n\r\n54\r\n00:03:46,260 --> 00:03:53,400\r\n以I为下标 求和A到B的整数的平方的数学表达式\r\nwhich is the mathematical expression, the sum of the square from i equal a to b.\r\n\r\n55\r\n00:03:55,340 --> 00:03:58,060\r\n同样的 这个程序也很简单\r\nAnd again, it's a very simple program.\r\n\r\n56\r\n00:04:11,180 --> 00:04:13,060\r\n实际上 这个程序一开始和刚才是一样的\r\nAnd indeed, it starts the same way.\r\n\r\n57\r\n00:04:16,220 --> 00:04:19,820\r\n如果A大于B 那么答案就是0\r\nIf a is greater than b, then the answer is zero.\r\n\r\n58\r\n00:04:20,820 --> 00:04:25,980\r\n显然 你会发现我又把这部分重复写了一遍\r\nAnd, of course, we're beginning to see that there's something wrong with me writing this down again.\r\n\r\n59\r\n00:04:27,280 --> 00:04:28,860\r\n这段程序和之前是相同的\r\nIt's the same program.\r\n\r\n60\r\n00:04:29,320 --> 00:04:45,900\r\n这里是A的平方加上A+1到B的平方和\r\nIt's the sum of the square of a and the sum of the square of the increment and b.\r\n\r\n61\r\n00:04:50,440 --> 00:04:54,480\r\n现在 你们再看看这两个程序 它们几乎是完全一样的\r\nNow, if you look at these things, these programs are almost identical.\r\n\r\n62\r\n00:04:56,000 --> 00:04:58,860\r\n并没有太大区别\r\nThere's not much to distinguish them.\r\n\r\n63\r\n00:04:59,760 --> 00:05:04,240\r\n它们有相同的条件表达式、谓词和CONSEQUENCE子句\r\nThey have the same first clause of the conditional and the same predicate and the same consequence,\r\n\r\n64\r\n00:05:05,580 --> 00:05:07,880\r\nALTERNATIVE子句也非常地相似\r\nand the alternatives are very similar, too.\r\n\r\n65\r\n00:05:08,660 --> 00:05:16,220\r\n事实上 唯一区别是 这里是A 而这里是A的平方\r\nThey only differ by the fact that where here I have a, here, I have the square of a.\r\n\r\n66\r\n00:05:17,200 --> 00:05:21,620\r\n另一个区别 有些无关紧要\r\nThe only other difference, but this one's sort of unessential\r\n\r\n67\r\n00:05:21,740 --> 00:05:23,860\r\n是这个过程的名字是SUM-INT\r\nis in the name of this procedure is sum int,\r\n\r\n68\r\n00:05:24,540 --> 00:05:26,460\r\n而这个过程的名字是SUM-SQUARE\r\nwhereas the name of the procedure is sum square.\r\n\r\n69\r\n00:05:27,420 --> 00:05:31,140\r\n所以这两个程序的区别微乎其微\r\nSo the things that vary between these two are very small.\r\n\r\n70\r\n00:05:32,760 --> 00:05:36,360\r\n现在来看 如果你重复地写了相同的东西\r\nNow, wherever you see yourself writing the same thing down more than once,\r\n\r\n71\r\n00:05:36,840 --> 00:05:38,740\r\n这就有些问题 你并不应该那样做\r\nthere's something wrong, and you shouldn't be doing it.\r\n\r\n72\r\n00:05:39,800 --> 00:05:43,940\r\n问题并不在于你重复的劳动带来时间浪费\r\nAnd the reason is not because it's a waste of time to write something down more than once.\r\n\r\n73\r\n00:05:45,000 --> 00:05:48,900\r\n而是在于里面的一些思想 非常简单的思想\r\nIt's because there's some idea here, a very simple idea,\r\n\r\n74\r\n00:05:50,260 --> 00:05:55,160\r\n与求和记法相关的思想 就是这一部分\r\nwhich has to do with the sigma notation-- this much--\r\n\r\n75\r\n00:05:56,820 --> 00:05:59,400\r\n其并不依赖于我待求和的内容\r\nnot depending upon what it is I'm adding up.\r\n\r\n76\r\n00:06:01,280 --> 00:06:05,900\r\n无论何时 当要设计一个复杂的系统并且要弄明白它时\r\nAnd I would like to be able to-- always, whenever trying to make complicated systems and understand them,\r\n\r\n77\r\n00:06:06,220 --> 00:06:09,440\r\n将问题拆分成尽量多的模块是很重要的\r\nit's crucial to divide the things up into as many pieces as I can,\r\n\r\n78\r\n00:06:09,640 --> 00:06:11,100\r\n并且每一个模块要能够被独立地解释\r\neach of which I understand separately.\r\n\r\n79\r\n00:06:12,640 --> 00:06:16,200\r\n我知道在不依赖具体内容的情况下 把东西加起来的方法\r\nI would like to understand the way of adding things up independently of what it is I'm adding up\r\n\r\n80\r\n00:06:17,040 --> 00:06:22,320\r\n这样我就只需要做一次调试 做一次分析\r\nso I can do that having debugged it once and understood it once\r\n\r\n81\r\n00:06:23,360 --> 00:06:27,300\r\n还能够与其他用户分享这段程序\r\nand having been able to share that among many different uses of it.\r\n\r\n82\r\n00:06:29,040 --> 00:06:30,420\r\n接下来 我有另外一个例子\r\nHere, we have another example.\r\n\r\n83\r\n00:06:31,520 --> 00:06:38,800\r\n这是莱布尼茨公式 用来求π/8的值\r\nThis is Leibnitz's formula for finding pi over 8.\r\n\r\n84\r\n00:06:39,940 --> 00:06:43,500\r\n这一团糟的式子是什么意思？\r\nIt's a funny, ugly mess. What is it?\r\n\r\n85\r\n00:06:43,500 --> 00:06:54,220\r\n大致是1/(1*3)+1/(5*7)+1/(7*9)+...这样子\r\nIt's something like 1 over 1 times 3 plus 1 over 5 times 7 plus 1 over 9 times 11 plus--\r\n\r\n86\r\n00:06:54,220 --> 00:07:00,960\r\n有趣的是 根据一些证明 它将收敛到π/8\r\nand for some reason, things like this tend to have interesting values like pi over 8.\r\n\r\n87\r\n00:07:01,740 --> 00:07:04,020\r\n我们能发现什么？\r\nBut what do we see here?\r\n\r\n88\r\n00:07:04,020 --> 00:07:06,980\r\n这个程序或多或少和之前的程序相同\r\nIt's the same program or almost the same program.\r\n\r\n89\r\n00:07:07,460 --> 00:07:08,920\r\n也是一个求和过程 对吧？\r\nIt's a sum. Okay?\r\n\r\n90\r\n00:07:08,920 --> 00:07:16,300\r\n这个表达里有一些细微的差别 它的递增的值是4\r\nSo we're seeing the figure notation, although over here, we're dealing with incrementing by 4\r\n\r\n91\r\n00:07:16,620 --> 00:07:18,040\r\n只是细微的差别而已\r\nso it's a slightly different problem,\r\n\r\n92\r\n00:07:18,200 --> 00:07:23,580\r\n所以我们需要在这里将A加4 就在这里\r\nwhich means that over here, I have to change a by 4, as you see right over here.\r\n\r\n93\r\n00:07:25,080 --> 00:07:26,200\r\n不再是加1了\r\nIt's not by 1.\r\n\r\n94\r\n00:07:27,920 --> 00:07:28,960\r\n当然 另一个区别是\r\nThe other thing, of course,\r\n\r\n95\r\n00:07:29,260 --> 00:07:33,960\r\n在之前的求平方和的程序里 求和项是平方值\r\nis that the thing that's represented by square in the previous sum of squares,\r\n\r\n96\r\n00:07:33,960 --> 00:07:35,640\r\n求整数和的程序里 求和项是整数本身\r\nor a when adding up the integers.\r\n\r\n97\r\n00:07:36,020 --> 00:07:38,380\r\n在这里 我用了不同的求和项\r\nWell, here, I have a different thing I'm adding up, a different term,\r\n\r\n98\r\n00:07:38,680 --> 00:07:43,060\r\n即1 / (A * (A + 2))\r\nwhich is 1 over a times a plus 2.\r\n\r\n99\r\n00:07:43,940 --> 00:07:45,740\r\n但是 其余部分的程序是相同的\r\nBut the rest of this program is identical.\r\n\r\n100\r\n00:07:48,140 --> 00:07:50,800\r\n总之 每当我们发现有一些过程是相同的\r\nWell, any time we have a bunch of things like this that are identical,\r\n\r\n101\r\n00:07:51,360 --> 00:07:54,240\r\n我们就需要做一些抽象来概括它们\r\nwe're going to have to come up with some sort of abstraction to cover them.\r\n\r\n102\r\n00:07:55,580 --> 00:08:00,460\r\n回想一下 到目前为止 你们学到的只是一些语法规则\r\nIf you think about this, what you've learned so far is the rules of some language,\r\n\r\n103\r\n00:08:00,520 --> 00:08:07,600\r\n一些基本表达式 组合的方法 抽象的方法 大概就是这些\r\nsome primitive, some means of combination, almost all of them, the means of abstraction, almost all of them.\r\n\r\n104\r\n00:08:09,360 --> 00:08:11,700\r\n但是 你们还没学到的是 使用的公共模式\r\nBut what you haven't learned is common patterns of usage.\r\n\r\n105\r\n00:08:12,880 --> 00:08:15,120\r\n大多时候 你要学习的是一门语言习惯用法\r\nNow, most of the time, you learn idioms when learning a language,\r\n\r\n106\r\n00:08:15,120 --> 00:08:19,820\r\n它是一种有价值的公共模式\r\nwhich is a common pattern that mean things that are useful to know in a flash.\r\n\r\n107\r\n00:08:20,780 --> 00:08:23,160\r\n如果你是一个经验丰富的FORTRAN程序员\r\nAnd if you build a great number of them, if you're a FORTRAN programmer,\r\n\r\n108\r\n00:08:23,160 --> 00:08:26,420\r\n你肯定知道\r\nof course, everybody knows how to-- what do you do,\r\n\r\n109\r\n00:08:27,240 --> 00:08:30,260\r\n比如 如何求某个数列中的最大值\r\nfor example, to get an integer which is the biggest integer in something.\r\n\r\n110\r\n00:08:30,860 --> 00:08:32,080\r\n这是经典的问题\r\nIt's a classic thing.\r\n\r\n111\r\n00:08:32,220 --> 00:08:33,420\r\n每个FORTRAN程序员都知道怎么做\r\nEvery FORTRAN programmer knows how to do that.\r\n\r\n112\r\n00:08:33,880 --> 00:08:36,820\r\n如果你不知道的话 你可能会陷于困境并花很长的时间想出答案\r\nAnd if you don't know that, you're in real hot water because it takes a long time to think it out.\r\n\r\n113\r\n00:08:37,700 --> 00:08:38,380\r\n然而\r\nHowever,\r\n\r\n114\r\n00:08:39,380 --> 00:08:41,780\r\n在这门语言中我们想展示给你的\r\none of the things you can do in this language that we're showing you\r\n\r\n115\r\n00:08:41,980 --> 00:08:45,600\r\n不是\"鱼\" 而是\"渔\"\r\nis not only do you know something like that, but you give the knowledge of that a name.\r\n\r\n116\r\n00:08:48,040 --> 00:08:50,040\r\n这就是我们接下来要做的事\r\nAnd so that's what we're going to be going after right now.\r\n\r\n117\r\n00:08:53,020 --> 00:08:55,460\r\n好吧 让我们先看看这些程序的共同点\r\nOK, well, let's see what these things have in common.\r\n\r\n118\r\n00:08:58,060 --> 00:09:02,680\r\n在这里我们有一个看似一般的模式\r\nRight over here we have what appears to be a general pattern,\r\n\r\n119\r\n00:09:04,040 --> 00:09:07,020\r\n它概括了到目前为止所有的例子\r\na general pattern which covers all of the cases we've seen so far.\r\n\r\n120\r\n00:09:09,380 --> 00:09:13,100\r\n这里定义了一个求和过程\r\nThere is a sum procedure, which is being defined.\r\n\r\n121\r\n00:09:14,380 --> 00:09:18,040\r\n它有两个参数 代表求和的下界和上界\r\nIt has two arguments, which are a lower bound and an upper bound.\r\n\r\n122\r\n00:09:19,380 --> 00:09:22,980\r\n首先判断下界是否大于上界\r\nThe lower bound is tested to be greater than the upper bound,\r\n\r\n123\r\n00:09:22,980 --> 00:09:26,680\r\n如果下界大于上界的话 结果就是0\r\nand if it is greater, then the result is zero.\r\n\r\n124\r\n00:09:27,200 --> 00:09:31,080\r\n否则 我们要对下界做一些处理\r\nOtherwise, we're going to do something to the lower bound,\r\n\r\n125\r\n00:09:31,080 --> 00:09:33,540\r\n也就是下标\r\nwhich is the index of the conversation,\r\n\r\n126\r\n00:09:34,200 --> 00:09:40,540\r\n将处理后的结果与后面这个过程的结果递归地相加\r\nand add that result to the result of following the procedure recursively\r\n\r\n127\r\n00:09:41,300 --> 00:09:45,340\r\n这个过程的参数是NEXT操作处理后的下界\r\non our lower bound incremented by some next operation\r\n\r\n128\r\n00:09:47,560 --> 00:09:49,400\r\n以及与之前相同的上界\r\nwith the same upper bound as I had before.\r\n\r\n129\r\n00:09:53,380 --> 00:09:56,760\r\n这即是公共模式\r\nSo this is a general pattern,\r\n\r\n130\r\n00:09:57,540 --> 00:10:00,980\r\n我想给这个公共模式命名\r\nand what I'd like to do is be able to name this general pattern a bit.\r\n\r\n131\r\n00:10:03,180 --> 00:10:04,120\r\n这还挺简单\r\nWell, that's sort of easy,\r\n\r\n132\r\n00:10:05,000 --> 00:10:08,020\r\n因为我要做的是...\r\nbecause one of the things I'm going to do right now is--\r\n\r\n133\r\n00:10:08,020 --> 00:10:10,020\r\n数字不是非常特殊的东西\r\nthere's nothing very special about numbers.\r\n\r\n134\r\n00:10:11,340 --> 00:10:13,100\r\n数字仅仅是一种数据\r\nNumbers are just one kind of data.\r\n\r\n135\r\n00:10:14,280 --> 00:10:20,300\r\n为各种数据命名看上去也是很合理的事情\r\nIt seems to be perfectly reasonable to give all sorts of names to all kinds of data,\r\n\r\n136\r\n00:10:21,000 --> 00:10:22,140\r\n比如说 “过程”\r\nfor example, procedures.\r\n\r\n137\r\n00:10:22,700 --> 00:10:25,680\r\n并且当今很多语言都允许使用过程参数\r\nAnd now many languages allow you have procedural arguments,\r\n\r\n138\r\n00:10:25,900 --> 00:10:28,460\r\n现在 我们即将讨论过程参数\r\nand right now, we're going to talk about procedural arguments.\r\n\r\n139\r\n00:10:29,020 --> 00:10:30,100\r\n它们很容易处理\r\nThey're very easy to deal with.\r\n\r\n140\r\n00:10:30,860 --> 00:10:33,880\r\n我们首先不去考虑过程参数 来做一些很特别的事情\r\nAnd shortly, we'll do some remarkable things that are not like procedural arguments.\r\n\r\n141\r\n00:10:35,420 --> 00:10:41,700\r\n这里 定义我们的求和记法\r\nSo here, we'll define our sigma notation.\r\n\r\n142\r\n00:10:42,780 --> 00:10:59,740\r\n过程名叫做SUM 参数为TERM A NEXT和B\r\nThis is called sum and it takes a term, an A, a next term, and B as arguments.\r\n\r\n143\r\n00:10:59,740 --> 00:11:00,900\r\n所以 它有四个参数\r\nSo it takes four arguments,\r\n\r\n144\r\n00:11:02,460 --> 00:11:05,520\r\n这里我写成小写没有特殊的含义\r\nand there was nothing particularly special about me writing this in lowercase.\r\n\r\n145\r\n00:11:06,020 --> 00:11:09,440\r\n我不希望它迷惑你 所以我现在把它改成大写\r\nI hope that it doesn't confuse you, so I'll write it in uppercase right now.\r\n\r\n146\r\n00:11:09,780 --> 00:11:10,680\r\n机器并不关心大小写\r\nThe machine doesn't care.\r\n\r\n147\r\n00:11:14,140 --> 00:11:17,860\r\n但这两个参数并不同 它们不是数字\r\nBut these two arguments are different. These are not numbers.\r\n\r\n148\r\n00:11:18,840 --> 00:11:22,140\r\n它们是对数字进行计算的过程\r\nThese are going to be procedures for computing something given a number.\r\n\r\n149\r\n00:11:23,300 --> 00:11:25,700\r\nTERM是这样一个过程 提供它一个下标\r\nTerm will be a procedure which, when given an index,\r\n\r\n150\r\n00:11:26,140 --> 00:11:28,660\r\nTERM会计算出这个下标所对应的项的值\r\nproduce the value of the term for that index.\r\n\r\n151\r\n00:11:29,440 --> 00:11:32,420\r\nNEXT过程会根据一个下标计算下一个下标\r\nNext will be given an index, which will produce the next index.\r\n\r\n152\r\n00:11:33,560 --> 00:11:34,740\r\n这是用来计数的\r\nThis will be for counting.\r\n\r\n153\r\n00:11:35,540 --> 00:11:36,720\r\n这很简单\r\nAnd it's very simple.\r\n\r\n154\r\n00:11:40,060 --> 00:11:41,740\r\n就是字面的意思\r\nIt's exactly what you see.\r\n\r\n155\r\n00:11:42,900 --> 00:11:50,800\r\n如果A大于B 结果就是0\r\nIf A is greater than B, then the result is 0.\r\n\r\n156\r\n00:11:51,820 --> 00:12:10,000\r\n否则 结果是(TERM A)与(SUM TERM (NEXT A)...)的和\r\nOtherwise, it's the sum of term applied to A and the sum of term, next index.\r\n\r\n157\r\n00:12:15,120 --> 00:12:16,140\r\n我换个方式写\r\nLet me write it this way.\r\n\r\n158\r\n00:12:29,580 --> 00:12:31,660\r\n现在 首先我要你们看一些东西\r\nNow, I'd like you to see something, first of all.\r\n\r\n159\r\n00:12:31,820 --> 00:12:33,640\r\n我写到黑板这 然后写不下了\r\nI was writing here, and I ran out of space.\r\n\r\n160\r\n00:12:34,740 --> 00:12:38,640\r\n于是我使用了缩进 依据的是整齐打印规则\r\nWhat I did is I start indenting according to the Pretty-printing rule,\r\n\r\n161\r\n00:12:38,640 --> 00:12:41,980\r\n意思是我把过程的每个参数对齐\r\nwhich says that I align all of the arguments of the procedure\r\n\r\n162\r\n00:12:43,360 --> 00:12:45,280\r\n这样我就能看清它们的层次\r\nso I can see which ones go together.\r\n\r\n163\r\n00:12:46,600 --> 00:12:48,400\r\n这是我刚才无意识地做下的\r\nAnd this is just something I do automatically,\r\n\r\n164\r\n00:12:49,080 --> 00:12:50,220\r\n并且我也希望你们学会这样做\r\nand I want you to learn how to do that, too,\r\n\r\n165\r\n00:12:50,220 --> 00:12:51,940\r\n这样你的程序就便于阅读和理解\r\nso your programs can be read and understood.\r\n\r\n166\r\n00:12:53,800 --> 00:12:56,900\r\n现在 看看我们有什么\r\nHowever, what do we have here?\r\n\r\n167\r\n00:12:57,200 --> 00:13:02,100\r\n我们有四个参数：过程、下界的下标、\r\nWe have four arguments: the procedure, the lower index- - lower bound index--\r\n\r\n168\r\n00:13:03,260 --> 00:13:06,180\r\n获得下一个下标的方法 以及上界\r\nthe way to get the next index, and the upper bound.\r\n\r\n169\r\n00:13:08,440 --> 00:13:14,300\r\n在递归调用的部分实际上传递的是同一个过程\r\nWhat's passed along on the recursive call is indeed the same procedure\r\n\r\n170\r\n00:13:14,960 --> 00:13:16,120\r\n因为我再一次需要它了\r\nbecause I'm going to need it again,\r\n\r\n171\r\n00:13:17,120 --> 00:13:20,140\r\n下一个下标 是用NEXT过程计算出的\r\nthe next index, which is using the next procedure to compute it,\r\n\r\n172\r\n00:13:20,840 --> 00:13:24,100\r\n计算下一个下标的过程 我也单独地需要 因为这两者是不同的\r\nthe procedure for computing next, which I also have to have separately, and that's different.\r\n\r\n173\r\n00:13:24,820 --> 00:13:28,200\r\n计算下一个下标的过程与下一个下标是不同的\r\nThe procedure for computing next is different from the next index,\r\n\r\n174\r\n00:13:28,680 --> 00:13:30,920\r\n下一个下标是NEXT过程应用于上一个下标所产生的结果\r\nwhich is the result of using next on the last index.\r\n\r\n175\r\n00:13:31,960 --> 00:13:33,800\r\n最后我也需要传递上界\r\nAnd I also have to pass along the upper bound.\r\n\r\n176\r\n00:13:36,600 --> 00:13:45,300\r\n于是 这就囊括了所有的这些 以及我们写过的其它的漂亮的程序\r\nSo this captures both of these and the other nice program that we are playing with.\r\n\r\n177\r\n00:13:47,440 --> 00:13:55,860\r\n利用这个 我们就可以很容易地写出SUM的原始实例程序\r\nSo using this, we can write down the original program as instances of sum very simply.\r\n\r\n178\r\n00:14:08,700 --> 00:14:10,000\r\nA和B\r\nA and B.\r\n\r\n179\r\n00:14:15,260 --> 00:14:20,180\r\n好吧 我在这需要一个IDENTITY过程 因为...\r\nWell, I'm going to need an identity procedure here because ,ahh,\r\n\r\n180\r\n00:14:25,520 --> 00:14:31,740\r\n整数的求和需要我在这里对每一个整数计算一次TERM\r\nthe sum of the integers requires me to in this case compute a term for every integer,\r\n\r\n181\r\n00:14:32,060 --> 00:14:34,380\r\n但是这个TERM过程并不对这个整数做任何改变\r\nbut the term procedure doesn't want to do anything to that integer.\r\n\r\n182\r\n00:14:35,240 --> 00:14:37,920\r\n所以关于A的IDENTITY过程结果就是A\r\nSo the identity procedure on A is A\r\n\r\n183\r\n00:14:39,000 --> 00:14:40,280\r\n写成X或者其它的符号也没关系\r\nor X or whatever,\r\n\r\n184\r\n00:14:40,840 --> 00:14:46,400\r\n接下来 将IDENTITY作为SUM的TERM过程\r\nand I want to say the sum of using identity of the term procedure\r\n\r\n185\r\n00:14:52,040 --> 00:14:53,860\r\n用A作为初始下标\r\nand using A as the initial index\r\n\r\n186\r\n00:14:55,300 --> 00:15:00,780\r\n1+过程用来获取下一个下标\r\nand the incrementer being the way to get the next index\r\n\r\n187\r\n00:15:01,620 --> 00:15:06,360\r\nB作为上界\r\nand B being the high bound, the upper bound.\r\n\r\n188\r\n00:15:07,460 --> 00:15:12,340\r\n这个过程与这里的SUM-INT过程工作方式相同\r\nThis procedure does exactly the same as the sum of the integers over here,\r\n\r\n189\r\n00:15:12,580 --> 00:15:13,720\r\n计算出的答案也相同\r\ncomputes the same answer.\r\n\r\n190\r\n00:15:17,200 --> 00:15:20,220\r\n现在 值得注意的一点是\r\nNow, one thing you should see, of course,\r\n\r\n191\r\n00:15:20,620 --> 00:15:25,380\r\n这里的形式参数写成什么都无所谓\r\nis that there's nothing very special over here about what I used as the formal parameter.\r\n\r\n192\r\n00:15:25,380 --> 00:15:28,800\r\n比如 我可以把它写成X 也没关系\r\nI could have, for example, written this X. It doesn't matter.\r\n\r\n193\r\n00:15:29,060 --> 00:15:34,240\r\n注意到这个X和那个X并不冲突\r\nI just wanted you to see that this name does not conflict with this one at all.\r\n\r\n194\r\n00:15:34,620 --> 00:15:35,820\r\n这是一个内部名称\r\nIt's an internal name.\r\n\r\n195\r\n00:15:37,480 --> 00:15:41,060\r\n对于第二个过程---平方和 它甚至更简单一些\r\nFor the second procedure here, the sum of the squares, it's even a little bit easier.\r\n\r\n196\r\n00:15:53,280 --> 00:15:58,020\r\n我们需要做的仅仅是将平方项加起来\r\nAnd what do we have to do? Nothing more than add up the squares,\r\n\r\n197\r\n00:16:00,740 --> 00:16:05,500\r\n这个过程会对每个下标生效\r\nthis is the procedure that each index will be given, will be given each-- yes.\r\n\r\n198\r\n00:16:06,180 --> 00:16:09,220\r\n每个下标使用这个过程来产生一个项\r\nEach index will have this done to it to get the term.\r\n\r\n199\r\n00:16:09,940 --> 00:16:12,420\r\n它对应了那里的TERM\r\nThat's the thing that maps against term over here.\r\n\r\n200\r\n00:16:13,140 --> 00:16:14,840\r\n然后将A作为下界\r\nThen I have A as the lower bound,\r\n\r\n201\r\n00:16:16,300 --> 00:16:19,300\r\n1+过程作为产生下一个项的方法\r\nthe incrementer as the next term method,\r\n\r\n202\r\n00:16:19,700 --> 00:16:21,140\r\nB作为上界\r\nand B as the upper bound.\r\n\r\n203\r\n00:16:26,520 --> 00:16:29,120\r\n最后 来看看之前的PI-SUM过程\r\nAnd finally, just for the thing that we did about pi sums,\r\n\r\n204\r\n00:16:30,740 --> 00:16:32,560\r\nPI-SUM是...\r\npi sums are sort of--\r\n\r\n205\r\n00:16:32,880 --> 00:16:36,240\r\n用这种方法考虑的话 它简单到明显不过了\r\nwell, it's even easier to think about them this way because I don't have to think.\r\n\r\n206\r\n00:16:36,240 --> 00:16:41,980\r\n其实只要把累加的每一项从累加过程中独立出来\r\nWhat I'm doing is separating the thing I'm adding up from the method of doing the addition.\r\n\r\n207\r\n00:16:42,720 --> 00:16:57,880\r\n来看看 比如说(PI-SUM A B)这个过程\r\nAnd so we have here, for example, pi sum A B of the sum of things.\r\n\r\n208\r\n00:16:59,480 --> 00:17:03,900\r\n我接下来想要写出这个TERM过程 但不给它命名\r\nI'm going to write the terms procedure here explicitly without giving it a name.\r\n\r\n209\r\n00:17:05,180 --> 00:17:06,700\r\n用匿名的方式\r\nThis is done anonymously.\r\n\r\n210\r\n00:17:06,700 --> 00:17:11,460\r\n如果我只是想一次性的使用它 我并不需要给它一个名字\r\nI don't necessarily have to give a name to something if I just want to use it once.\r\n\r\n211\r\n00:17:12,360 --> 00:17:18,640\r\n当然 我可以写出某个表达式来产生一个过程\r\nAnd, of course, I can write sort of a expression that produces a procedure.\r\n\r\n212\r\n00:17:19,180 --> 00:17:23,820\r\n我这里使用希腊字母的λ 而不是L-A-M-B-D-A的全拼\r\nI'm going to write the Greek lambda letter here instead of L-A-M-B-D-A in general\r\n\r\n213\r\n00:17:24,000 --> 00:17:26,480\r\n免得占用太多黑板的空间\r\nto avoid taking up a lot of space on blackboards.\r\n\r\n214\r\n00:17:26,760 --> 00:17:29,160\r\n可惜 我们的键盘上没有λ键\r\nBut unfortunately, we don't have lambda keys on our keyboards.\r\n\r\n215\r\n00:17:29,560 --> 00:17:33,340\r\n或许我们可以说服工业界的朋友意识到（λ键的）重要性\r\nMaybe we can convince our friends in the computer industry that this is an important.\r\n\r\n216\r\n00:17:33,560 --> 00:17:45,220\r\n该LAMBADA过程以I为参数 操作是1除以I与I+2的积\r\nLambda of i is the quotient of 1 and the product of i and the sum of i 2,\r\n\r\n217\r\n00:17:51,840 --> 00:17:53,120\r\n下标从A开始\r\nstarting at a\r\n\r\n218\r\n00:17:53,480 --> 00:18:02,600\r\n递增方法是以I为参数 将I+4的过程\r\nwith the way of incrementing being that procedure of an index i, which adds i to 4,\r\n\r\n219\r\n00:18:05,980 --> 00:18:09,420\r\nB作为上界\r\nand b being the upper bound.\r\n\r\n220\r\n00:18:11,960 --> 00:18:20,060\r\n你可以看到这种记法 将过程用作过程参数\r\nSo you can see that this notation, the invention of the procedure that takes a procedural argument,\r\n\r\n221\r\n00:18:20,460 --> 00:18:24,300\r\n允许我们将很多过程组合成一个\r\nallows us to compress a lot of these procedures into one thing.\r\n\r\n222\r\n00:18:26,040 --> 00:18:30,680\r\n这个过程 SUM 蕴含着一系列的思想\r\nThis procedure, sums, covers a whole bunch of ideas.\r\n\r\n223\r\n00:18:32,300 --> 00:18:33,740\r\n现在思考一下为什么这是很重要的？\r\nNow, just why is this important?\r\n\r\n224\r\n00:18:34,240 --> 00:18:38,960\r\n它帮助我们将一个问题拆分成两个 实际上 它做到了这点\r\nI tried to say before that it helps us divide a problem into two pieces, and indeed, it does,\r\n\r\n225\r\n00:18:40,740 --> 00:18:44,620\r\n比如说 如果某个人提出了另一个实现这个的方法\r\nfor example, if someone came up with a different way of implementing this,\r\n\r\n226\r\n00:18:45,920 --> 00:18:47,800\r\n当然 确实有一个\r\nwhich, of course, one might.\r\n\r\n227\r\n00:18:49,600 --> 00:18:51,920\r\n比如 一个SUM过程的迭代实现\r\nHere, for example, an iterative implementation of sum.\r\n\r\n228\r\n00:18:55,500 --> 00:19:00,840\r\n迭代实现在某种程度上也许比递归实现更好\r\nIterative implementation for some reason might be better than the recursive implementation.\r\n\r\n229\r\n00:19:03,100 --> 00:19:04,840\r\n但是它还是有很大不同的\r\nBut the important thing is that it's different.\r\n\r\n230\r\n00:19:05,980 --> 00:19:11,700\r\n如果我现在用黑板上左边的那种方法实现了我的程序\r\nNow, supposing I had written my program this way that you see on the blackboard on the left.\r\n\r\n231\r\n00:19:14,100 --> 00:19:15,480\r\n是的 左边那个程序\r\nThat's correct, the left.\r\n\r\n232\r\n00:19:17,340 --> 00:19:20,000\r\n后来 我想要改变“求和”这个方法\r\nWell, then if I want to change the method of addition,\r\n\r\n233\r\n00:19:21,440 --> 00:19:23,280\r\n我就不得不修改这里的每一个程序\r\nthen I'd have to change each of these.\r\n\r\n234\r\n00:19:24,740 --> 00:19:28,780\r\n然而 如果我用这里这个方法来实现的话\r\nWhereas if I write them like this that you see here,\r\n\r\n235\r\n00:19:29,480 --> 00:19:32,940\r\n那么“求和”这个方法就被封装在了SUM过程里\r\nthen the method by which I did the addition is encapsulated in the procedure sum.\r\n\r\n236\r\n00:19:34,460 --> 00:19:38,400\r\n这个分解允许我只需修改程序的一部分\r\nThat decomposition allows me to independently change one part of the program\r\n\r\n237\r\n00:19:39,340 --> 00:19:46,140\r\n而不改变用于处理其它问题的那些部分\r\nand prove it perhaps without changing the other part that was written for some of the other cases.\r\n\r\n238\r\n00:19:50,280 --> 00:19:51,340\r\n谢谢 大家有问题吗？\r\nThank you. Are there any questions?\r\n\r\n239\r\n00:19:51,960 --> 00:19:52,480\r\n那位男士\r\nYes, sir.\r\n\r\n240\r\n00:19:52,560 --> 00:19:54,500\r\n观众：A后面的值会被一个一个遍历的吗……\r\nAUDIENCE: Would you go over next A and next again on--\r\n\r\n241\r\n00:19:54,720 --> 00:19:56,020\r\n教授：是的\r\nPROFESSOR: Yes. It's the same problem.\r\n\r\n242\r\n00:19:56,020 --> 00:19:58,680\r\n我确信你们需要花一些时间来想明白\r\nI'm sure you're going to-- you're going to have to work on this.\r\n\r\n243\r\n00:19:58,680 --> 00:20:01,540\r\n如果你第一次见到这种写法的话可能会很困惑\r\nThis is hard the first time you've ever seen something like this.\r\n\r\n244\r\n00:20:01,980 --> 00:20:07,220\r\n这里的过程是可以命名为一个变量\r\nWhat I have here is a-- procedures can be named by variables.\r\n\r\n245\r\n00:20:09,980 --> 00:20:11,180\r\n“过程”这个概念并没有特殊的地方\r\nProcedures are not special.\r\n\r\n246\r\n00:20:12,300 --> 00:20:15,420\r\n实际上SUM-SQ也只不过是一个变量 会产生一个值\r\nActually, sum square is a variable, which has gotten a value,\r\n\r\n247\r\n00:20:16,720 --> 00:20:17,580\r\n这就是过程\r\nwhich is a procedure.\r\n\r\n248\r\n00:20:18,200 --> 00:20:21,160\r\n这里其实是定义SUM-SQ为一个参数为A、B的LAMBDA过程\r\nThis is define sum square to be lambda of A and B something.\r\n\r\n249\r\n00:20:22,880 --> 00:20:23,980\r\n所以过程可以被命名\r\nSo the procedure can be named.\r\n\r\n250\r\n00:20:24,300 --> 00:20:30,080\r\n那样的话 过程就可以被作为参数传递于过程之间\r\nTherefore, they can be passed from one to another, one procedure to another, as arguments.\r\n\r\n251\r\n00:20:31,020 --> 00:20:35,600\r\n在这里 我们做的就是把TERM过程作为参数传递给SUM\r\nWell, what we're doing here is we're passing the procedure term as an argument to sum\r\n\r\n252\r\n00:20:36,780 --> 00:20:39,440\r\n在下一层的递归中也会用到它\r\njust when we get it around in the next recursive.\r\n\r\n253\r\n00:20:41,040 --> 00:20:46,680\r\n同样地 我们也将NEXT过程作为参数传递了\r\nHere, we're passing the procedure next as an argument also.\r\n\r\n254\r\n00:20:47,200 --> 00:20:49,180\r\n然而 在这里我们是使用了NEXT过程\r\nHowever, here we're using the procedure next.\r\n\r\n255\r\n00:20:49,540 --> 00:20:50,860\r\n括号体现了这一点\r\nThat's what the parentheses mean.\r\n\r\n256\r\n00:20:51,300 --> 00:20:55,400\r\n我们将NEXT过程应用于变量A来获得A的下一个值\r\nWe're applying next to A to get the next value of A.\r\n\r\n257\r\n00:20:56,200 --> 00:20:57,920\r\n如果你想知道NEXT过程映射出了什么\r\nIf you look at what next is mapped against,\r\n\r\n258\r\n00:20:57,920 --> 00:21:00,520\r\n你可以这样来考虑\r\nremember that the way you think about this is\r\n\r\n259\r\n00:21:00,520 --> 00:21:04,620\r\n用实际参数代换过程体中的形式参数\r\nthat you substitute the arguments for the formal parameters in the body.\r\n\r\n260\r\n00:21:06,040 --> 00:21:09,800\r\n如果你还是困惑的话 就像这样想吧\r\nIf you're ever confused, think of the thing that way.\r\n\r\n261\r\n00:21:10,080 --> 00:21:13,540\r\n比如在SUM-INT过程中\r\nWell, over here, with sum of the integers.\r\n\r\n262\r\n00:21:14,320 --> 00:21:17,040\r\n我用IDENTITY过程代换TERM过程\r\nI substitute identity for a term\r\n\r\n263\r\n00:21:19,380 --> 00:21:24,420\r\n用1+增量过程代换过程体中的NEXT过程\r\nand 1 plus the incrementer for next in the body.\r\n\r\n264\r\n00:21:25,660 --> 00:21:29,460\r\n在这里我将IDENTITY过程应用于了A\r\nWell, the identity procedure on A is what I get here.\r\n\r\n265\r\n00:21:30,100 --> 00:21:31,760\r\nIDENTITY过程会被继续传递\r\nIdentity is being passed along,\r\n\r\n266\r\n00:21:33,740 --> 00:21:38,200\r\n在这里 我将1+过程应用于了A\r\nand here, I have increment 1 plus being applied to A\r\n\r\n267\r\n00:21:39,740 --> 00:21:41,220\r\n并且1+过程也被传递下去\r\nand 1 plus is being passed along.\r\n\r\n268\r\n00:21:42,520 --> 00:21:45,400\r\n清楚这个情况了吗？\r\nDoes that clarify the situation?\r\n\r\n269\r\n00:21:45,600 --> 00:21:50,640\r\n观众：我们也可以显式地定义那两个过程 然后再传递它们\r\nAUDIENCE: We could also define explicitly those two functions, then pass them.\r\n\r\n270\r\n00:21:50,640 --> 00:21:51,320\r\n教授：当然可以\r\nPROFESSOR: Sure.\r\n\r\n271\r\n00:21:51,320 --> 00:21:55,380\r\n我们的确可以命名这些过程 就如我这里做的一样\r\nWhat we can do is we could have given names to them, just like I did here.\r\n\r\n272\r\n00:21:55,380 --> 00:21:58,500\r\n实际上 我在这里提供了很多种方式给你们\r\nIn fact, I gave you various ways so you could see it, a variety.\r\n\r\n273\r\n00:21:58,500 --> 00:22:03,140\r\n在这里 我定义了这个过程 并传递了它的名字\r\nHere, I define the thing which I passed the name of.\r\n\r\n274\r\n00:22:03,220 --> 00:22:06,560\r\n我用它的名字来引用它\r\nI referenced it by its name.\r\n\r\n275\r\n00:22:07,400 --> 00:22:11,020\r\n实际上这个过程的参数是X 结果也是X\r\nBut the thing is, in fact, that procedure, one argument X, which is X.\r\n\r\n276\r\n00:22:12,100 --> 00:22:15,780\r\nIDENTITY过程实际上相当于(LAMBDA (x) x)\r\nAnd the identity procedure is just lambda of X X.\r\n\r\n277\r\n00:22:17,600 --> 00:22:19,520\r\n这里就是这样的\r\nAnd that's what you're seeing here.\r\n\r\n278\r\n00:22:20,020 --> 00:22:26,420\r\n在这里 我就给你们写出了它的经典用法\r\nHere, I happened to just write its canonical name there for you to see.\r\n\r\n279\r\n00:22:31,760 --> 00:22:33,020\r\n让我们休息5分钟吧\r\nIs it OK if we take our five-minute break?\r\n\r\n280\r\n00:22:35,820 --> 00:22:47,240\r\n[音乐]\r\n[JESU, JOY OF MAN'S DESIRING]\r\n\r\n281\r\n00:23:00,260 --> 00:23:04,500\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n282\r\n00:23:04,620 --> 00:23:07,700\r\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\r\nBy: Prof. Harold Abelson && Gerald Jay Sussman\r\n\r\n283\r\n00:23:08,560 --> 00:23:12,120\r\n高阶过程\r\nHigher-order Procedures\r\n\r\n284\r\n00:23:15,360 --> 00:23:18,760\r\n正如我说的 计算机用于满足人们的需求\r\nAs I said, computers to make people happy,\r\n\r\n285\r\n00:23:18,920 --> 00:23:20,440\r\n而不是让人去满足计算机的需求\r\nnot people to make computers happy.\r\n\r\n286\r\n00:23:20,640 --> 00:23:23,980\r\n我们介绍抽象概念的大部分原因\r\nAnd for the most part, the reason why we introduce all this abstraction stuff\r\n\r\n287\r\n00:23:24,220 --> 00:23:28,080\r\n是为了让程序更易写易读\r\nis to make it so that programs can be more easily written and more easily read.\r\n\r\n288\r\n00:23:30,160 --> 00:23:33,580\r\n让我们用一些关于抽象的例子\r\nLet's try to understand what's the most complicated program we've seen so far\r\n\r\n289\r\n00:23:34,040 --> 00:23:37,140\r\n来理解目前为止我们见到的最复杂的程序\r\nusing a little bit of this abstraction stuff.\r\n\r\n290\r\n00:23:37,940 --> 00:23:39,700\r\n请看幻灯片\r\nIf you look at the slide,\r\n\r\n291\r\n00:23:39,960 --> 00:23:49,080\r\n这是我们昨天介绍的Heron法 用于计算平方根\r\nthis is the Heron of Alexandria's method of computing square roots that we saw yesterday.\r\n\r\n292\r\n00:23:51,300 --> 00:23:53,880\r\n看一下这个程序\r\nAnd let's see.\r\n\r\n293\r\n00:23:56,060 --> 00:24:01,180\r\n不管怎样 这个程序有一些复杂\r\nWell, in any case, this program is a little complicated.\r\n\r\n294\r\n00:24:01,700 --> 00:24:03,720\r\n现在这种情况下\r\nAnd at the current state of your thinking,\r\n\r\n295\r\n00:24:03,900 --> 00:24:05,240\r\n你肯定不会看着这个程序说\r\nyou just can't look at that and say,\r\n\r\n296\r\n00:24:05,240 --> 00:24:08,940\r\n哦 这个程序的目的真是显而易见\r\noh, this obviously means something very clear.\r\n\r\n297\r\n00:24:10,000 --> 00:24:14,540\r\n它到底在计算什么一点都不明显\r\nIt's not obvious from looking at the program what it's computing.\r\n\r\n298\r\n00:24:16,040 --> 00:24:19,540\r\n在TRY过程里有一些循环\r\nThere's some loop here inside try,\r\n\r\n299\r\n00:24:20,260 --> 00:24:24,200\r\n循环在对Y的IMPROVE应用TRY过程\r\nand a loop does something about trying the improvement of y.\r\n\r\n300\r\n00:24:25,800 --> 00:24:28,720\r\n还有一个叫IMPROVE的什么东西\r\nThere's something called improve,\r\n\r\n301\r\n00:24:29,120 --> 00:24:32,500\r\n做了一些关于AVERAGE和除法的什么工作\r\nwhich does some averaging and quotienting and things like that.\r\n\r\n302\r\n00:24:33,020 --> 00:24:34,580\r\n但是它到底在做什么？\r\nBut what's the real idea?\r\n\r\n303\r\n00:24:34,580 --> 00:24:36,720\r\n我们可以弄明白这个程序的目的吗？\r\nCan we make it clear what the idea is?\r\n\r\n304\r\n00:24:38,360 --> 00:24:39,680\r\n我认为可以\r\nWell, I think we can.\r\n\r\n305\r\n00:24:41,260 --> 00:24:44,940\r\n我们可以用之前学到的关于抽象的知识\r\nI think we can use abstraction that we have learned about so far\r\n\r\n306\r\n00:24:45,380 --> 00:24:47,700\r\n来说明它到底在干什么\r\nto clarify what's going on.\r\n\r\n307\r\n00:24:48,520 --> 00:24:56,460\r\n现在 我们在数学上有一个对平方根结果的更好猜测\r\nNow, what we have mathematically is a procedure for improving a guess for square roots.\r\n\r\n308\r\n00:24:57,480 --> 00:25:04,180\r\n如果Y是平方根的一个猜测值 那么我们有一个函数F\r\nAnd if y is a guess for a square root, then what we want to get we'll call a function f.\r\n\r\n309\r\n00:25:04,300 --> 00:25:05,700\r\n用来改进猜测值\r\nThis is the means of improvement.\r\n\r\n310\r\n00:25:06,400 --> 00:25:13,360\r\n我用(Y+X/Y)/2的结果\r\nI want to get y plus x/y over 2,\r\n\r\n311\r\n00:25:14,140 --> 00:25:22,200\r\n作为改进的平方根猜测值\r\nso the average of y and x divided by y as the improved value for the square root of x\r\n\r\n312\r\n00:25:23,840 --> 00:25:37,000\r\n值得注意的一点是 F对根号X的求值结果就是根号X\r\nsuch that-- one thing you can notice about this function f is that f of the square root of f is in fact the square root of x.\r\n\r\n313\r\n00:25:38,680 --> 00:25:42,500\r\n因为 如果在这里我将Y替换成根号X\r\nthere, if I take the square root of x and substitute it for y here,\r\n\r\n314\r\n00:25:43,120 --> 00:25:46,820\r\n将会得到根号X加上X与根号X的商\r\nI see the square root of x plus x divided by the square of x, which is the square root of x.\r\n\r\n315\r\n00:25:47,200 --> 00:25:50,200\r\n是2倍根号X除以2 结果就是根号x\r\nThat's 2 times the square root of x divided by 2, is the square root of x.\r\n\r\n316\r\n00:25:50,920 --> 00:26:12,300\r\n所以 实际上我们在寻找函数F的一个不动点\r\nSo, in fact, what we're really looking for is we're looking for a fixed point, a fixed point of the function f.\r\n\r\n317\r\n00:26:16,920 --> 00:26:21,240\r\n不动点就是一个值\r\nA fixed point is a place which has the property\r\n\r\n318\r\n00:26:21,980 --> 00:26:24,560\r\n将其应用到函数中得到的还是原来的值\r\nthat if you put it into the function, you get the same value out.\r\n\r\n319\r\n00:26:27,180 --> 00:26:29,680\r\n假设你在上一堂很无聊的课\r\nNow, I suppose if I were giving some nice, boring lecture,\r\n\r\n320\r\n00:26:29,680 --> 00:26:35,080\r\n碰巧你面前有一个HP-35计算器\r\nand you happened to have in front of you an HP-35 desk calculator\r\n\r\n321\r\n00:26:35,080 --> 00:26:36,920\r\n我过去就在无聊的课上用过\r\nlike I used to have when I went to boring lectures.\r\n\r\n322\r\n00:26:37,680 --> 00:26:39,500\r\n如果你觉得无事可干\r\nAnd if you think it was really boring,\r\n\r\n323\r\n00:26:39,500 --> 00:26:45,520\r\n你可以进入弧度模式 不停地按COS键 按COS键 按COS键……\r\nyou put it into radians mode, and you hit cosine, and you hit cosine, and you hit cosine.\r\n\r\n324\r\n00:26:45,760 --> 00:26:50,400\r\n最终 你将会停在大概是0.734这个值\r\nAnd eventually, you end up with 0.734 or something like that. 0.743\r\n\r\n325\r\n00:26:50,460 --> 00:26:51,960\r\n我记不太清了\r\nI don't remember what exactly,\r\n\r\n326\r\n00:26:52,160 --> 00:26:53,780\r\n越来越接近那个值\r\nand it gets closer and closer to that.\r\n\r\n327\r\n00:26:54,540 --> 00:27:00,620\r\n你可以通过迭代的方法找到一些函数的不动点\r\nSome functions have the property that you can find their fixed point by iterating the function,\r\n\r\n328\r\n00:27:02,700 --> 00:27:07,520\r\n实际上在Heron法中发生的就是这个过程\r\nand that's essentially what's happening in the square root program by Heron's method.\r\n\r\n329\r\n00:27:11,180 --> 00:27:13,600\r\n看看我们能不能实现这个想法\r\nSo let's see if we can write that down, that idea.\r\n\r\n330\r\n00:27:14,800 --> 00:27:17,040\r\n现在我不打算讲如何计算出不动点\r\nNow, I'm not going to say how I compute fixed points yet.\r\n\r\n331\r\n00:27:17,220 --> 00:27:18,560\r\n那可以有很多种方法\r\nThere might be more than one way.\r\n\r\n332\r\n00:27:19,200 --> 00:27:23,560\r\n首先让我们回到刚才的话题上\r\nBut the first thing to do is I'm going to say what I just said.\r\n\r\n333\r\n00:27:23,860 --> 00:27:27,020\r\n回到平方根这个问题上\r\nI'm going to say it specifically, the square root.\r\n\r\n334\r\n00:27:31,800 --> 00:27:45,360\r\nX的平方根是一个过程的不动点\r\nThe square root of x is the fixed point of that procedure\r\n\r\n335\r\n00:27:47,660 --> 00:28:02,140\r\n这个过程以Y作为参数 计算出X/Y和Y的平均值\r\nwhich takes an argument y and averages of x divided by y with y.\r\n\r\n336\r\n00:28:05,160 --> 00:28:09,200\r\n并且假定初始不动点的猜测值为1\r\nAnd we're going to start up with the initial guess for the fixed point of 1.\r\n\r\n337\r\n00:28:09,480 --> 00:28:10,800\r\n初始值为几都无所谓\r\nIt doesn't matter where it starts.\r\n\r\n338\r\n00:28:11,400 --> 00:28:13,620\r\n理论上证明过了\r\nA theorem having to do with square roots.\r\n\r\n339\r\n00:28:18,280 --> 00:28:22,080\r\n在这里我仅仅是按愿望思维写出了程序\r\nSo what you're seeing here is I'm just trying to write out by wishful thinking.\r\n\r\n340\r\n00:28:22,180 --> 00:28:24,360\r\n我并不知道求不动点的具体细节\r\nI don't know how I'm going to make fixed point happen.\r\n\r\n341\r\n00:28:24,360 --> 00:28:25,460\r\n这点我们接下来再涉及\r\nWe'll worry about that later.\r\n\r\n342\r\n00:28:25,900 --> 00:28:30,900\r\n假如我写出了一个求这个过程的不动点的函数\r\nBut if somehow I had a way of finding the fixed point of the function computed by this procedure,\r\n\r\n343\r\n00:28:32,440 --> 00:28:35,980\r\n那么我就能得到平方根的值了\r\nthen I would have-- that would be the square root that I'm looking for.\r\n\r\n344\r\n00:28:39,160 --> 00:28:42,700\r\n现在 我们来看看如何求不动点\r\nOK, well, now let's see how we're going to write-- how we're going to come up with fixed points.\r\n\r\n345\r\n00:28:43,060 --> 00:28:44,600\r\n实际上这很简单\r\nWell, it's very simple, actually.\r\n\r\n346\r\n00:28:44,600 --> 00:28:47,640\r\n我先写出一个简单的版本便于大家理解\r\nI'm going to write an abbreviated version here just so we understand it.\r\n\r\n347\r\n00:29:00,060 --> 00:29:02,300\r\n我要找到函数F的不动点A\r\nI'm going to find the fixed point of a function f--\r\n\r\n348\r\n00:29:02,940 --> 00:29:08,240\r\n在这个过程里 求不动点的函数我们命名为F\r\nactually, the fixed point of the function computed by the procedure whose name will be f in this procedure.\r\n\r\n349\r\n00:29:09,620 --> 00:29:14,520\r\n接下来 需要一个具体的值开始计算\r\nHow's that? A long sentence-- starting with a particular starting value.\r\n\r\n350\r\n00:29:19,520 --> 00:29:21,580\r\n在过程内部需要一些循环\r\nWell, I'm going to have a little loop inside here,\r\n\r\n351\r\n00:29:22,020 --> 00:29:25,120\r\n代表了不停地在计算器上按键的过程\r\nwhich is going to push the button on the calculator repeatedly,\r\n\r\n352\r\n00:29:25,460 --> 00:29:27,380\r\n期待它最终会收敛到一点\r\nhoping that it will eventually converge.\r\n\r\n353\r\n00:29:28,600 --> 00:29:35,780\r\n内部的循环我们定义为内部过程\r\nAnd we will say here internal loops are written by defining internal procedures.\r\n\r\n354\r\n00:29:38,980 --> 00:29:42,520\r\n在这里 我需要确定我是否找到了我需要的值\r\nWell, one thing I'm going to have to do is I'm going to have to say whether I'm done.\r\n\r\n355\r\n00:29:43,160 --> 00:29:45,140\r\n我将要考察\r\nAnd the way I'm going to decide when I'm done is when\r\n\r\n356\r\n00:29:45,200 --> 00:29:48,660\r\n新旧两值是否接近得无法区分\r\nthe old value and the new value are close enough so I can't distinguish them anymore.\r\n\r\n357\r\n00:29:50,360 --> 00:29:55,540\r\n相当于你在计算器上看到结果的变化最终超出了精度范围\r\nThat's the standard thing you do on the calculator unless you look at more precision, and eventually, you run out of precision.\r\n\r\n358\r\n00:29:57,420 --> 00:30:02,940\r\n所以 这里需要旧值和新值\r\nSo the old value and new value,\r\n\r\n359\r\n00:30:05,400 --> 00:30:10,380\r\n并且如果它们足够接近\r\nand I'm going to stay here if I can't distinguish them if they're close enough,\r\n\r\n360\r\n00:30:14,800 --> 00:30:16,640\r\n接下来的操作我马上会提到\r\nand we'll have to worry about what that is soon.\r\n\r\n361\r\n00:30:20,320 --> 00:30:22,620\r\n如果旧值和新值足够接近的话\r\nThe old value and the new value are close enough to each other\r\n\r\n362\r\n00:30:22,620 --> 00:30:24,080\r\n我们就选择新值作为结果\r\nand let's pick the new value as the answer.\r\n\r\n363\r\n00:30:25,400 --> 00:30:28,500\r\n否则 我继续迭代这个过程\r\nOtherwise, I'm going to iterate around again\r\n\r\n364\r\n00:30:31,000 --> 00:30:36,360\r\n将当前的新值作为下一轮的旧值\r\nwith the next value of old being the current value of new\r\n\r\n365\r\n00:30:38,260 --> 00:30:42,960\r\n将f作用于新值的结果作为下一轮的新值\r\nand the next value of new being the result of calling f on new.\r\n\r\n366\r\n00:30:53,680 --> 00:30:57,900\r\n相当于我不停地按下计算器的键\r\nAnd so this is my iteration loop that pushes the button on the calculator.\r\n\r\n367\r\n00:30:58,240 --> 00:31:01,760\r\n我可以想象计算器中有两个寄存器：旧与新\r\nI basically think of it as having two registers on the calculator: old and new.\r\n\r\n368\r\n00:31:02,420 --> 00:31:07,100\r\n在每一步中 新值成为旧值 F作用后的新值成为新的新值\r\nAnd in each step, new becomes old, and new gets F of new.\r\n\r\n369\r\n00:31:08,700 --> 00:31:10,940\r\n这就是得到下一个猜测值的方法\r\nSo this is the thing where I'm getting the next value.\r\n\r\n370\r\n00:31:12,720 --> 00:31:21,720\r\n现在 我传入两个值来调用这个方法\r\nAnd now, I'm going to start this thing up by giving two values.\r\n\r\n371\r\n00:31:28,060 --> 00:31:31,200\r\n我详细地在黑板上写出了每一个步骤\r\nI wrote down on the blackboard to be slow so you can see this.\r\n\r\n372\r\n00:31:31,680 --> 00:31:35,340\r\n这是你们第一次见到这么复杂的程序\r\nThis is the first time you've seen something quite this complicated, I think.\r\n\r\n373\r\n00:31:37,380 --> 00:31:48,920\r\n我们还是需要在幻灯片上看一下整个程序\r\nHowever, we might want to see the whole thing over here in this transparency or slide or whatever.\r\n\r\n374\r\n00:31:50,100 --> 00:31:57,680\r\n这里详细地写出了程序所有需要的细节\r\nWhat we have is all of the details that are required to make this thing work.\r\n\r\n375\r\n00:31:58,080 --> 00:32:02,700\r\n在这里 我在CLOSE-ENUF?过程里给出了误差\r\nI have a way of getting a tolerance for a close enough procedure, which we see here.\r\n\r\n376\r\n00:32:02,980 --> 00:32:06,180\r\nCLOSE-ENUF?过程确定U和V是否足够接近\r\nThe close enough procedure, it tests whether u and v are close enough\r\n\r\n377\r\n00:32:06,700 --> 00:32:12,140\r\n通过比较U和V的差是否小于一个给定的误差实现\r\nby seeing if the absolute value of the difference in u and v is less than the given tolerance, OK?\r\n\r\n378\r\n00:32:12,140 --> 00:32:14,620\r\n这里是我刚才在黑板上写出的循环定义\r\nAnd here is the iteration loop that I just wrote on the blackboard\r\n\r\n379\r\n00:32:15,500 --> 00:32:18,260\r\n它的初始化调用在这\r\nand the initialization for it, which is right there.\r\n\r\n380\r\n00:32:21,340 --> 00:32:22,180\r\n非常简单\r\nIt's very simple.\r\n\r\n381\r\n00:32:33,840 --> 00:32:35,720\r\n其实 我还没有说完\r\nBut let's see. I haven't told you enough.\r\n\r\n382\r\n00:32:36,160 --> 00:32:37,760\r\n实际上这个程序可以更简单\r\nIt's actually easier than this.\r\n\r\n383\r\n00:32:39,320 --> 00:32:42,620\r\n对于这个问题 在我讲述的内容背后隐含着更多的原理支撑\r\nThere is more structure to this problem than I've already told you.\r\n\r\n384\r\n00:32:42,620 --> 00:32:44,620\r\n比如为什么这个方法可行\r\nLike why should this work?\r\n\r\n385\r\n00:32:45,340 --> 00:32:46,680\r\n为什么它会收敛\r\nWhy should it converge?\r\n\r\n386\r\n00:32:47,620 --> 00:32:51,220\r\n在这个程序的背后有复杂的数学原理支撑\r\nThere's a hairy theorem in mathematics tied up in what I've written here.\r\n\r\n387\r\n00:32:52,320 --> 00:32:58,260\r\n为什么我可以认为迭代计算(Y+X/Y)/2的值就能得到正确的结果\r\nWhy is it that I should assume that by iterating averaging the quotient of x and y and y that I should get the right answer?\r\n\r\n388\r\n00:32:59,820 --> 00:33:00,820\r\n这些问题的答案都不明显\r\nIt isn't so obvious.\r\n\r\n389\r\n00:33:03,120 --> 00:33:10,240\r\n当然 除此之外 还会有其他的计算不动点的方法 也能得到平方根的值\r\nSurely there are other things, other procedures, which compute functions whose fixed points would also be the square root.\r\n\r\n390\r\n00:33:11,680 --> 00:33:18,620\r\n比如 很明显的 函数G\r\nFor example, the obvious one will be a new function g,\r\n\r\n391\r\n00:33:19,980 --> 00:33:25,720\r\n它将Y映射为X/Y\r\nwhich maps y to x/y.\r\n\r\n392\r\n00:33:27,560 --> 00:33:28,620\r\n这甚至更简单\r\nThat's even simpler.\r\n\r\n393\r\n00:33:30,580 --> 00:33:33,260\r\n函数g的不动点显然也是平方根的值\r\nThe fixed point of g is surely the square root also,\r\n\r\n394\r\n00:33:33,800 --> 00:33:35,120\r\n并且它使更为简单的过程\r\nand it's a simpler procedure.\r\n\r\n395\r\n00:33:36,960 --> 00:33:38,200\r\n为什么我不使用这种方法呢？\r\nWhy am I not using it?\r\n\r\n396\r\n00:33:38,560 --> 00:33:39,880\r\n显而易见\r\nWell, I suppose you know.\r\n\r\n397\r\n00:33:40,100 --> 00:33:41,220\r\n假设X是2\r\nSupposing x is 2\r\n\r\n398\r\n00:33:41,320 --> 00:33:42,480\r\n并且猜测的初值是1\r\nand I start out with 1,\r\n\r\n399\r\n00:33:42,780 --> 00:33:46,980\r\n我将2除以1 得到2\r\nand if I divide 1 into 2, I get 2.\r\n\r\n400\r\n00:33:47,300 --> 00:33:49,200\r\n然后我将2除以2 得到1\r\nAnd then if I divide 2 into 2, I get 1.\r\n\r\n401\r\n00:33:49,200 --> 00:33:52,120\r\n再将2除以1得到2 2除以2得到1……\r\nIf I divide 1 into 2, I get 2, and 2 into 2, I get 1,\r\n\r\n402\r\n00:33:52,120 --> 00:33:53,820\r\n这样 我永远也接近不了2的平方根\r\nand I never get any closer to the square root.\r\n\r\n403\r\n00:33:55,140 --> 00:33:56,100\r\n它在真实值上下摆动\r\nIt is oscillates.\r\n\r\n404\r\n00:33:59,080 --> 00:34:01,600\r\n实际上 这相当于一个信号处理系统\r\nSo what we have is a signal processing system,\r\n\r\n405\r\n00:34:02,600 --> 00:34:05,500\r\n一个振荡的电路\r\nan electrical circuit which is oscillating,\r\n\r\n406\r\n00:34:05,500 --> 00:34:07,160\r\n我想要减小振荡的振幅\r\nand I want to damp out these oscillations.\r\n\r\n407\r\n00:34:10,140 --> 00:34:11,000\r\n当然 我可以做到这点\r\nWell, I can do that.\r\n\r\n408\r\n00:34:11,500 --> 00:34:14,440\r\n在这里 我实际上用到的是平均值\r\nSee, what I'm really doing here when I'm taking my average,\r\n\r\n409\r\n00:34:14,680 --> 00:34:18,040\r\n计算的是某个振荡的均值\r\nthe average is averaging the last two values of something which oscillates,\r\n\r\n410\r\n00:34:18,680 --> 00:34:19,800\r\n得到了中间的某个值\r\ngetting something in between.\r\n\r\n411\r\n00:34:21,060 --> 00:34:24,940\r\n传统的方法是在信号处理系统中添加阻尼\r\nThe classic way is damping out oscillations in a signal processing system.\r\n\r\n412\r\n00:34:28,140 --> 00:34:32,540\r\n为什么我们不把刚才讲的策略用一种更清晰的方式表达呢？\r\nSo why don't we write down the strategy that I just said in a more clear way?\r\n\r\n413\r\n00:34:34,180 --> 00:34:35,240\r\n其实 这并不那么复杂\r\nWell, that's easy enough.\r\n\r\n414\r\n00:34:38,960 --> 00:34:46,260\r\n定义(SQRT X)为\r\nI'm going to define the square root of x to be\r\n\r\n415\r\n00:34:47,080 --> 00:34:56,380\r\n用平均阻尼的方法得到的某个过程的不动点\r\na fixed point of the procedure resulting from average damping.\r\n\r\n416\r\n00:34:58,120 --> 00:35:01,340\r\n即将AVERAGE-DAMP应用于过程\r\nSo I have a procedure resulting from average damp\r\n\r\n417\r\n00:35:10,000 --> 00:35:20,340\r\n(λ (y) (/ x y))\r\nof the procedure, that procedure of y, which divides x by y\r\n\r\n418\r\n00:35:24,560 --> 00:35:25,420\r\n初始猜测值为1\r\nstarting out at 1.\r\n\r\n419\r\n00:35:29,500 --> 00:35:32,560\r\nAVERAGE-DAMP是一个特殊的过程\r\nAh, but average damp is a special procedure\r\n\r\n420\r\n00:35:32,940 --> 00:35:34,560\r\n它的参数是一个过程\r\nthat's going to take a procedure as its argument\r\n\r\n421\r\n00:35:34,800 --> 00:35:36,460\r\n其返回值也是一个过程\r\nand return a procedure as its value.\r\n\r\n422\r\n00:35:37,700 --> 00:35:39,460\r\n具体来说\r\nIt's a generalization that says\r\n\r\n423\r\n00:35:39,800 --> 00:35:40,860\r\n给定一个过程\r\ngiven a procedure,\r\n\r\n424\r\n00:35:41,500 --> 00:35:42,940\r\n它产生出另一个过程\r\nit's the thing which produces a procedure\r\n\r\n425\r\n00:35:43,000 --> 00:35:45,940\r\n用于计算出某一个值在给定的过程作用下\r\nwhich averages the last value\r\n\r\n426\r\n00:35:46,400 --> 00:35:48,500\r\n结果与它原来的平均值\r\nand the value before and after running the procedure.\r\n\r\n427\r\n00:35:50,980 --> 00:35:53,660\r\n你可以在任何需要平均阻尼技术的地方使用它\r\nYou can use it for anything if you want to damp out oscillations.\r\n\r\n428\r\n00:35:54,560 --> 00:35:55,640\r\n我们把它编写出来\r\nSo let's write that down.\r\n\r\n429\r\n00:35:56,460 --> 00:35:57,160\r\n这很简单\r\nIt's very easy.\r\n\r\n430\r\n00:36:00,640 --> 00:36:01,920\r\n在语法上\r\nAnd stylistically here,\r\n\r\n431\r\n00:36:02,100 --> 00:36:03,720\r\n我要使用LAMBDA表达式\r\nI'm going to use lambda notation\r\n\r\n432\r\n00:36:04,200 --> 00:36:07,860\r\n因为当你的处理对象是过程的时候\r\nbecause it's much easier to think when you're dealing with procedure, the mid-line procedures,\r\n\r\n433\r\n00:36:07,860 --> 00:36:10,520\r\n这种记法会更易于你的理解\r\nto understand that the procedures are the objects I'm dealing with,\r\n\r\n434\r\n00:36:10,860 --> 00:36:13,080\r\n所以在这里我打算使用LAMBDA表达式\r\nso I'm going to use lambda notation here.\r\n\r\n435\r\n00:36:13,420 --> 00:36:15,020\r\n我并不是经常使用它\r\nNot always. I don't always use it,\r\n\r\n436\r\n00:36:15,640 --> 00:36:21,700\r\n但用在这个过程里来阐明自己的想法是非常合适的\r\nbut very specifically here to expand on that idea, to elucidate it.\r\n\r\n437\r\n00:36:28,440 --> 00:36:30,260\r\nAVERAGE-DAMP这个过程\r\nWell, average damp is a procedure,\r\n\r\n438\r\n00:36:31,720 --> 00:36:35,420\r\n将一个过程作为自己的参数 记作F\r\nwhich takes a procedure as its argument, which we will call f.\r\n\r\n439\r\n00:36:37,180 --> 00:36:38,060\r\n它产生什么呢？\r\nAnd what does it produce?\r\n\r\n440\r\n00:36:38,280 --> 00:36:44,100\r\n这个过程产生的是一个过程\r\nIt produces as its value-- the body of this procedure is a thing which produces a procedure,\r\n\r\n441\r\n00:36:44,240 --> 00:36:46,060\r\n产生的过程主体从这里开始\r\nthe construct of the procedures right here,\r\n\r\n442\r\n00:36:46,620 --> 00:36:48,480\r\n拥有一个参数X\r\nof one argument x,\r\n\r\n443\r\n00:36:49,900 --> 00:37:00,000\r\n并计算出F(X)和X的平均值\r\nwhich averages f of x with x.\r\n\r\n444\r\n00:37:10,200 --> 00:37:11,940\r\n这是一个很神奇的过程\r\nThis is a very special thing.\r\n\r\n445\r\n00:37:12,940 --> 00:37:19,320\r\n我猜这是你们第一次见到一个过程产生出另一个过程作为其结果\r\nI think for the first time you're seeing a procedure which produces a procedure as its value.\r\n\r\n446\r\n00:37:21,980 --> 00:37:25,660\r\n这个过程接受了过程F 做了一些工作\r\nThis procedure takes the procedure f and does something to it\r\n\r\n447\r\n00:37:25,920 --> 00:37:28,340\r\n产生出一个新的过程 拥有一个参数X\r\nto produce a new procedure of one argument x,\r\n\r\n448\r\n00:37:29,140 --> 00:37:30,660\r\n计算出F...\r\nwhich averages f\r\n\r\n449\r\n00:37:30,660 --> 00:37:31,200\r\n这里的F\r\n-- this f--\r\n\r\n450\r\n00:37:31,460 --> 00:37:33,860\r\nF(X)和X的平均值\r\napplied to x and x itself.\r\n\r\n451\r\n00:37:35,640 --> 00:37:37,200\r\n在代码的这个部分\r\nUsing the context here,\r\n\r\n452\r\n00:37:37,660 --> 00:37:42,760\r\n我将AVERAGE-DAMP应用到过程X/Y上\r\nI apply average damping to the procedure, which just divides x by y.\r\n\r\n453\r\n00:37:44,340 --> 00:37:45,100\r\n就是个除法\r\nIt's a division.\r\n\r\n454\r\n00:37:48,160 --> 00:37:49,760\r\n接着再找到这个过程的不动点\r\nAnd I'm finding to fixed point of that,\r\n\r\n455\r\n00:37:50,180 --> 00:37:54,440\r\n这个写法更清晰的阐明了整个过程 较之于先前这里的写法\r\nand that's a clearer way of writing down what I wrote down over here,\r\n\r\n456\r\n00:37:55,520 --> 00:37:56,480\r\n我找找...\r\nwherever it was.\r\n\r\n457\r\n00:37:57,280 --> 00:37:57,820\r\n先前这里的写法\r\nHere,\r\n\r\n458\r\n00:37:59,140 --> 00:38:00,880\r\n因为它做出了更进一步的抽象\r\nbecause it tells why I am writing this down.\r\n\r\n459\r\n00:38:04,740 --> 00:38:11,860\r\n我希望以上这些能在一定程度上阐明Heron法\r\nI suppose this to some extent really clarifies what Heron of Alexandria was up to.\r\n\r\n460\r\n00:38:14,000 --> 00:38:15,560\r\n先到此为止吧 有什么问题吗？\r\nI suppose I'll stop now. Are there any questions?\r\n\r\n461\r\n00:38:17,900 --> 00:38:19,480\r\n观众：在你定义AVERAGE-DAMP过程的时候\r\nAUDIENCE: So when you define average damp,\r\n\r\n462\r\n00:38:19,500 --> 00:38:23,340\r\n不需要给F一个变量吗？\r\ndon't you need to have a variable on f?\r\n\r\n463\r\n00:38:24,700 --> 00:38:28,240\r\n教授：啊 你的问题是...\r\nPROFESSOR: Ah, the question was, and here we're having-- again,\r\n\r\n464\r\n00:38:28,240 --> 00:38:29,480\r\n你应该已经了解语法了\r\nyou've got to learn about the syntax.\r\n\r\n465\r\n00:38:29,480 --> 00:38:32,480\r\n你的问题是当定义AVERAGE-DAMP的时候\r\nThe question was when defining average damp,\r\n\r\n466\r\n00:38:32,920 --> 00:38:36,920\r\n是否需要给F一个变量？\r\ndon't you have to have a variable defined with f?\r\n\r\n467\r\n00:38:37,640 --> 00:38:39,840\r\n你的意思是提供F的形式参数？\r\nWhat you are asking about is the formal parameter of f?\r\n\r\n468\r\n00:38:40,040 --> 00:38:40,400\r\n观众：是的\r\nAUDIENCE: Yeah.\r\n\r\n469\r\n00:38:40,820 --> 00:38:41,540\r\n教授：好的\r\nPROFESSOR: OK.\r\n\r\n470\r\n00:38:42,640 --> 00:38:44,140\r\nF的形式参数其实是在这里\r\nThe formal parameter of f is here.\r\n\r\n471\r\n00:38:44,780 --> 00:38:46,620\r\nF的形式参数...\r\nThe formal parameter of f--\r\n\r\n472\r\n00:38:47,400 --> 00:38:49,180\r\n观众：我指的是AVERAGE-DAMP的形式参数\r\nAUDIENCE: The formal parameter of average damp.\r\n\r\n473\r\n00:38:49,840 --> 00:38:54,100\r\n教授：F在这里被应用到了一个参数上 对吗？\r\nPROFESSOR: F is being used to apply it to an argument, right?\r\n\r\n474\r\n00:38:54,100 --> 00:38:56,480\r\n实际上F确实需要一个形式参数\r\nIt's indeed true that f must have a formal parameter.\r\n\r\n475\r\n00:38:57,320 --> 00:38:59,480\r\n我们来找一下F的形式参数在哪\r\nLet's find out what f's formal parameter is.\r\n\r\n476\r\n00:39:00,020 --> 00:39:01,760\r\n观众：我想问的是AVERAGE-DAMP的形式参数\r\nAUDIENCE: The formal parameter of average damp.\r\n\r\n477\r\n00:39:02,020 --> 00:39:04,160\r\n教授：哦 f应该是AVERAGE-DAMP的形式参数\r\nPROFESSOR: Oh, f is the formal parameter of average damp.\r\n\r\n478\r\n00:39:04,240 --> 00:39:04,960\r\n抱歉\r\nI'm sorry.\r\n\r\n479\r\n00:39:05,120 --> 00:39:07,040\r\n你被一些语法混淆了\r\nYou're just confusing a syntactic thing.\r\n\r\n480\r\n00:39:07,440 --> 00:39:09,120\r\n我应该用换一种方式写\r\nI could have written this the other way.\r\n\r\n481\r\n00:39:10,080 --> 00:39:11,300\r\n我已经明白你的问题了\r\nActually, I didn't understand your question.\r\n\r\n482\r\n00:39:12,120 --> 00:39:13,620\r\n我应该用这种方式写\r\nOf course, I could have written it this other way.\r\n\r\n483\r\n00:39:19,120 --> 00:39:20,400\r\n它们是一样的\r\nThose are identical notations.\r\n\r\n484\r\n00:39:21,120 --> 00:39:25,540\r\n这是另一种写法\r\nThis is a different way of writing this.\r\n\r\n485\r\n00:39:31,260 --> 00:39:32,880\r\n你得习惯这种LAMBDA记法\r\nYou're going to have to get used to lambda notation\r\n\r\n486\r\n00:39:32,880 --> 00:39:33,860\r\n我以后也会使用\r\nbecause I'm going to use it.\r\n\r\n487\r\n00:39:35,100 --> 00:39:36,100\r\n在这里\r\nWhat it says here,\r\n\r\n488\r\n00:39:36,580 --> 00:39:39,860\r\n我定义了AVERAGE-DAMP这个过程\r\nI'm defining the name average damp\r\n\r\n489\r\n00:39:40,060 --> 00:39:43,220\r\n来给这个拥有一个参数F的过程命名\r\nto name the procedure whose of one argument f.\r\n\r\n490\r\n00:39:44,160 --> 00:39:46,760\r\n这个F就是AVERAGE-DAMP过程的形式参数\r\nThat's the formal parameter of the procedure average damp.\r\n\r\n491\r\n00:39:48,840 --> 00:39:55,260\r\n这个DEFINE的作用是赋予这个名字一个值\r\nWhat define does is it says give this name a value.\r\n\r\n492\r\n00:39:56,380 --> 00:39:57,760\r\n这里就是这个值\r\nHere is the value of for it.\r\n\r\n493\r\n00:40:00,940 --> 00:40:03,300\r\n这是个有趣的语法\r\nThat there happens to be a funny syntax\r\n\r\n494\r\n00:40:04,140 --> 00:40:08,040\r\n在一些情况下能带来一些便利\r\nto make that easier in some cases is purely convenience.\r\n\r\n495\r\n00:40:10,580 --> 00:40:12,240\r\n我在这里使用这种写法的原因\r\nBut the reason why I wrote it this way here\r\n\r\n496\r\n00:40:12,460 --> 00:40:15,800\r\n是为了强调我处理的过程\r\nis to emphasize that I'm dealing with a procedure\r\n\r\n497\r\n00:40:15,840 --> 00:40:17,020\r\n接受了一个过程作为参数\r\nthat takes a procedure as its argument\r\n\r\n498\r\n00:40:17,020 --> 00:40:18,780\r\n并且产生出另一个过程作为值\r\nand produces a procedure as its value.\r\n\r\n499\r\n00:40:23,220 --> 00:40:25,460\r\n观众：我不太理解你为什么使用两次LAMBDA\r\nAUDIENCE: I don't understand why you use lambda twice.\r\n\r\n500\r\n00:40:25,460 --> 00:40:28,900\r\n难道不能使用一个LAMBDA 以F和X作为参数吗？\r\nCan you just use one lambda and take two arguments f and x?\r\n\r\n501\r\n00:40:28,900 --> 00:40:29,260\r\n教授：不能\r\nPROFESSOR: No.\r\n\r\n502\r\n00:40:29,260 --> 00:40:29,900\r\n观众：不能？\r\nAUDIENCE: You can't?\r\n\r\n503\r\n00:40:29,900 --> 00:40:31,440\r\n教授：不 那是不同的东西了\r\nPROFESSOR: No, that would be a different thing.\r\n\r\n504\r\n00:40:32,020 --> 00:40:33,840\r\n如果我在这里写成\r\nIf I were to write the procedure\r\n\r\n505\r\n00:40:34,240 --> 00:40:37,720\r\n(λ (F X) (AVERAGE (F X) X))\r\nlambda of f and x, the average of f of x and x,\r\n\r\n506\r\n00:40:38,440 --> 00:40:42,160\r\n那么它就不能接受一个过程作为参数\r\nthat would not be something which would be allowed to take a procedure as an argument\r\n\r\n507\r\n00:40:42,160 --> 00:40:43,800\r\n并且产生一个过程作为值了\r\nand produce a procedure as its value.\r\n\r\n508\r\n00:40:44,260 --> 00:40:47,860\r\n它就成为接受一个参数以及一个数字作为它的参数\r\nThat would be a thing that takes a procedure as its argument and numbers its argument\r\n\r\n509\r\n00:40:48,040 --> 00:40:49,240\r\n并且产生出的是一个新的数\r\nand produces a new number.\r\n\r\n510\r\n00:40:50,480 --> 00:40:52,260\r\n而在这里我需要一个过程\r\nBut what I'm producing here is a procedure\r\n\r\n511\r\n00:40:52,260 --> 00:40:54,920\r\n来作为这个过程的参数\r\nto fit in the procedure slot over here,\r\n\r\n512\r\n00:40:54,920 --> 00:40:56,920\r\n并且在这里使用\r\nwhich is going to be used over here.\r\n\r\n513\r\n00:40:58,480 --> 00:40:59,940\r\n所以数字必须来自这里\r\nSo the number has to come from here.\r\n\r\n514\r\n00:41:01,220 --> 00:41:03,540\r\n最后直到这里才用上X\r\nThis is the thing that's going to eventually end up in the x.\r\n\r\n515\r\n00:41:04,080 --> 00:41:04,860\r\n如果你仍然很迷惑\r\nAnd if you're confused,\r\n\r\n516\r\n00:41:04,860 --> 00:41:08,520\r\n你可以自己做一些代换\r\nyou should do some substitution and see for yourself.\r\n\r\n517\r\n00:41:11,580 --> 00:41:11,980\r\n你说\r\nYes?\r\n\r\n518\r\n00:41:12,400 --> 00:41:15,740\r\n观众：你可以展示一下如何不用LAMBDA表达式\r\nAUDIENCE: Will you please show the definition for average damp\r\n\r\n519\r\n00:41:15,740 --> 00:41:18,420\r\n来定义AVERAGE-DAMP过程吗？\r\nwithout using lambda notation in both cases.\r\n\r\n520\r\n00:41:18,960 --> 00:41:21,080\r\n教授：那样就无法如此简练地实现了\r\nPROFESSOR: I can't make a very simple one like that.\r\n\r\n521\r\n00:41:21,080 --> 00:41:22,220\r\n我来定义给你看\r\nLet me do it for you, though.\r\n\r\n522\r\n00:41:22,220 --> 00:41:24,220\r\n我可以很容易地去掉这个LAMBDA\r\nI can get rid of this lambda easily.\r\n\r\n523\r\n00:41:26,160 --> 00:41:27,680\r\n我不希望...\r\nI don't want to be--\r\n\r\n524\r\n00:41:32,400 --> 00:41:33,700\r\n好吧 我说谎了\r\nactually, I'm lying to you.\r\n\r\n525\r\n00:41:33,700 --> 00:41:35,460\r\n我不想照你那样去实现\r\nI don't want to do what you want\r\n\r\n526\r\n00:41:36,080 --> 00:41:37,860\r\n因为这会远比你想象的复杂\r\nbecause I think it's more confusing than you think.\r\n\r\n527\r\n00:41:38,520 --> 00:41:40,140\r\n我就不去实现你的想法了\r\nI'm not going to write what you want.\r\n\r\n528\r\n00:41:54,960 --> 00:41:56,200\r\n这里得起个名字\r\nSo we'll have to get a name.\r\n\r\n529\r\n00:41:56,200 --> 00:42:00,100\r\n(FOO x)为...\r\nFOO of x to be\r\n\r\n530\r\n00:42:05,220 --> 00:42:09,500\r\n...(F x)和X\r\nof F of x and x\r\n\r\n531\r\n00:42:11,420 --> 00:42:13,280\r\n返回值是FOO\r\nand return as a value FOO.\r\n\r\n532\r\n00:42:16,920 --> 00:42:18,120\r\n这个是等价的写法\r\nThis is equivalent,\r\n\r\n533\r\n00:42:19,020 --> 00:42:20,560\r\n但我还得另写一个冗余的变量名\r\nbut I've had to make an arbitrary name up.\r\n\r\n534\r\n00:42:21,280 --> 00:42:23,860\r\n这两个是等价的 但没有使用LAMBDA\r\nThis is equivalent to this without any lambdas.\r\n\r\n535\r\n00:42:26,280 --> 00:42:30,920\r\nLAMBDA非常适合于需要匿名过程的地方\r\nLambda is very convenient for naming anonymous procedures.\r\n\r\n536\r\n00:42:30,920 --> 00:42:32,200\r\n用它来代表一些匿名的事物\r\nIt's the anonymous name of something.\r\n\r\n537\r\n00:42:33,660 --> 00:42:39,160\r\n其实存在着更优美的解决方法\r\nNow, if you really want to know a cute way of doing this,\r\n\r\n538\r\n00:42:39,300 --> 00:42:40,220\r\n我们以后会提到\r\nwe'll talk about it later.\r\n\r\n539\r\n00:42:41,380 --> 00:42:44,260\r\n匿名过程的定义还是必要的\r\nWe're going to have to define the anonymous procedure.\r\n\r\n540\r\n00:42:44,780 --> 00:42:45,640\r\n还有问题吗？\r\nAny other questions?\r\n\r\n541\r\n00:42:49,100 --> 00:42:50,480\r\n休息一下吧\r\nAnd so we go for our break again.\r\n\r\n542\r\n00:42:53,880 --> 00:43:00,940\r\n[音乐]\r\n[JESU, JOY OF MAN'S DESIRING]\r\n\r\n543\r\n00:43:01,340 --> 00:43:05,180\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n544\r\n00:43:05,260 --> 00:43:10,000\r\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\r\nBy: Prof. Harold Abelson && Gerald Jay Sussman\r\n\r\n545\r\n00:43:16,400 --> 00:43:20,540\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n546\r\n00:43:20,660 --> 00:43:24,480\r\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\r\nBy: Prof. Harold Abelson && Gerald Jay Sussman\r\n\r\n547\r\n00:43:24,640 --> 00:43:28,340\r\n高阶过程\r\nHigher-order Procedures\r\n\r\n548\r\n00:43:31,360 --> 00:43:36,120\r\n我们现在已经了解了如何使用高阶过程\r\nSo now we've seen how to use high-order procedures, they're called.\r\n\r\n549\r\n00:43:36,120 --> 00:43:39,520\r\n用来接受过程参数和产生过程结果\r\nThat's procedures that take procedural arguments and produce procedural values\r\n\r\n550\r\n00:43:40,140 --> 00:43:44,780\r\n来帮助我们阐明和抽象一些复杂的过程\r\nto help us clarify and abstract some otherwise complicated processes.\r\n\r\n551\r\n00:43:46,060 --> 00:43:48,520\r\n我现在打算用它来做一些更有趣的事情\r\nI suppose what I'd like to do now is have a bit of fun with that\r\n\r\n552\r\n00:43:49,320 --> 00:43:52,900\r\n也同时作为练习\r\nand sort of a little practice as well.\r\n\r\n553\r\n00:43:53,720 --> 00:43:55,920\r\n我们来更深入地研究一下SQRT过程\r\nSo let's play with this square root thing even more.\r\n\r\n554\r\n00:43:55,920 --> 00:43:58,620\r\n详尽地剖析和理解其中的工作方式\r\nLet's elaborate it and understand what's going on\r\n\r\n555\r\n00:43:59,200 --> 00:44:01,800\r\n并且利用一下它的代码结构\r\nand make use of this kind of programming style.\r\n\r\n556\r\n00:44:03,940 --> 00:44:07,500\r\n有件事你们已经知道\r\nOne thing that you might know is\r\n\r\n557\r\n00:44:07,500 --> 00:44:09,720\r\n有一个通用的方法叫做牛顿法\r\nthere is a general method called Newton's method\r\n\r\n558\r\n00:44:10,640 --> 00:44:13,780\r\n用来计算函数的根\r\nfor the purpose of which is to find the roots--\r\n\r\n559\r\n00:44:14,480 --> 00:44:17,780\r\n也就是函数的零点\r\nthat's the zeroes-- of functions.\r\n\r\n560\r\n00:44:18,740 --> 00:44:19,800\r\n举个例子\r\nSo, for example,\r\n\r\n561\r\n00:44:20,700 --> 00:44:37,060\r\n求Y 使得F(Y)等于0\r\nto find a y such that f of y equals 0,\r\n\r\n562\r\n00:44:37,880 --> 00:44:39,340\r\n首先要从一个猜测值开始\r\nwe start with some guess.\r\n\r\n563\r\n00:44:40,000 --> 00:44:40,960\r\n这就是牛顿法\r\nThis is Newton's method.\r\n\r\n564\r\n00:44:50,960 --> 00:44:53,720\r\n将初始的猜测值命名为Y0\r\nAnd the guess we start with we'll call y0,\r\n\r\n565\r\n00:44:54,840 --> 00:44:59,180\r\n然后我们迭代地计算下面这个表达式\r\nand then we will iterate the following expression.\r\n\r\n566\r\n00:45:00,580 --> 00:45:02,340\r\nYn+1\r\ny n plus 1--\r\n\r\n567\r\n00:45:02,340 --> 00:45:03,760\r\n这是另外一个方程\r\nthis is a difference equation--\r\n\r\n568\r\n00:45:04,460 --> 00:45:10,040\r\n等于Yn-F(Yn)\r\nis yn minus f of yn\r\n\r\n569\r\n00:45:12,000 --> 00:45:17,660\r\n除以F对Y的导数\r\nover the derivative with respect to y of f\r\n\r\n570\r\n00:45:18,260 --> 00:45:21,760\r\n在Y=Yn点处的值\r\nevaluated at y equal yn.\r\n\r\n571\r\n00:45:22,840 --> 00:45:24,180\r\n非常奇怪的式子\r\nVery strange notation.\r\n\r\n572\r\n00:45:25,580 --> 00:45:29,340\r\n我得说...\r\nI must say ugh.\r\n\r\n573\r\n00:45:30,600 --> 00:45:34,620\r\nf对y的求导得到的是一个函数\r\nThe derivative of f with respect to y is a function.\r\n\r\n574\r\n00:45:35,340 --> 00:45:37,420\r\n感觉上会有些麻烦\r\nI'm having a little bit of unhappiness with that,\r\n\r\n575\r\n00:45:37,840 --> 00:45:38,660\r\n不过没关系\r\nbut that's all right.\r\n\r\n576\r\n00:45:39,140 --> 00:45:40,900\r\n在用程序语言表达以后\r\nIt turns out in the programming language world,\r\n\r\n577\r\n00:45:40,980 --> 00:45:42,160\r\n会变得非常清晰\r\nthe notation is much clearer.\r\n\r\n578\r\n00:45:43,560 --> 00:45:44,480\r\n这是什么？\r\nNow, what is this?\r\n\r\n579\r\n00:45:45,700 --> 00:45:46,860\r\n这就是所谓的牛顿法\r\nPeople call it Newton's method.\r\n\r\n580\r\n00:45:46,900 --> 00:45:52,180\r\n它用来计算函数F的根\r\nIt's a method for finding the roots of the function f.\r\n\r\n581\r\n00:45:53,860 --> 00:45:57,300\r\n当收敛的时候 它会计算得很快\r\nAnd it, of course, sometimes converges, and when it does, it does so very fast.\r\n\r\n582\r\n00:45:57,980 --> 00:46:00,340\r\n不过有时是不收敛的\r\nAnd sometimes, it doesn't converge, and,\r\n\r\n583\r\n00:46:00,580 --> 00:46:02,260\r\n那样我们就需要做一些其它的工作\r\noh well, we have to do something else.\r\n\r\n584\r\n00:46:02,760 --> 00:46:05,640\r\n先让我们来讨论一下用牛顿法计算平方根\r\nBut let's talk about square root by Newton's method.\r\n\r\n585\r\n00:46:06,760 --> 00:46:08,320\r\n这会很有趣\r\nWell, that's rather interesting.\r\n\r\n586\r\n00:46:08,320 --> 00:46:10,380\r\n我们先使用一下之前用到过的方法\r\nLet's do exactly the same thing we did last time:\r\n\r\n587\r\n00:46:10,560 --> 00:46:11,900\r\n按愿望思维的方法\r\na bit of wishful thinking.\r\n\r\n588\r\n00:46:13,020 --> 00:46:14,800\r\n假设我们已经实现了牛顿法\r\nWe will apply Newton's method,\r\n\r\n589\r\n00:46:14,980 --> 00:46:16,420\r\n可以直接使用它\r\nassuming we knew how to do it.\r\n\r\n590\r\n00:46:17,840 --> 00:46:19,200\r\n事实上你还并未实现\r\nYou don't know how to do it yet.\r\n\r\n591\r\n00:46:20,300 --> 00:46:21,140\r\n让我们开始吧\r\nWell, let's go.\r\n\r\n592\r\n00:46:24,880 --> 00:46:26,780\r\n这里要写什么？(SQRT X)\r\nWhat do I have here? The square root of x.\r\n\r\n593\r\n00:46:31,000 --> 00:46:39,040\r\n将牛顿法应用到某个作用在Y上的过程上\r\nIt's Newton's method applied to a procedure which will represent that function of y,\r\n\r\n594\r\n00:46:39,040 --> 00:46:40,500\r\n这个过程用于计算Y对应的函数值\r\nwhich computes that function of y.\r\n\r\n595\r\n00:46:42,100 --> 00:46:45,820\r\n这个过程参数是Y\r\nWell, that procedure is that procedure of y,\r\n\r\n596\r\n00:46:46,840 --> 00:46:51,400\r\n计算出X和根号Y的差\r\nwhich is the difference between x and the square of y.\r\n\r\n597\r\n00:46:59,660 --> 00:47:05,880\r\n实际上 如果存在Y使得这个式子等于0\r\nIndeed, if I had a value of y for which this was zero,\r\n\r\n598\r\n00:47:07,020 --> 00:47:09,740\r\n那么Y就是X的平方根\r\nthen y would be the square root of x.\r\n\r\n599\r\n00:47:13,340 --> 00:47:13,940\r\n明白吗？\r\nSee that?\r\n\r\n600\r\n00:47:15,160 --> 00:47:18,700\r\n接下来 我令其从1开始尝试\r\nOK, I'm going to start this out searching at 1.\r\n\r\n601\r\n00:47:18,880 --> 00:47:24,080\r\n这完全是一个随意写下的猜测值\r\nAgain, completely arbitrary property of square roots that I can do that.\r\n\r\n602\r\n00:47:24,700 --> 00:47:30,280\r\n现在的问题是 牛顿法应该如何实现？\r\nNow, how am I going to compute Newton's method?\r\n\r\n603\r\n00:47:31,160 --> 00:47:32,620\r\n方法的过程在这里书写了\r\nWell, this is the method I have it right here.\r\n\r\n604\r\n00:47:33,860 --> 00:47:39,580\r\n实际上 我所做的是寻找某个过程的不动点\r\nIn fact, what I'm doing is looking for a fixed point of some procedure.\r\n\r\n605\r\n00:47:40,940 --> 00:47:44,320\r\n这个过程包含了一些复杂的表达式\r\nThis procedure involves some complicated expressions\r\n\r\n606\r\n00:47:44,660 --> 00:47:46,740\r\n和一些其它的怪东西\r\nin terms of other complicated things.\r\n\r\n607\r\n00:47:47,140 --> 00:47:48,400\r\n我就是要找到这个式子的不动点\r\nWell, I'm trying to find the fixed point of this.\r\n\r\n608\r\n00:47:48,400 --> 00:47:52,060\r\n我要找到某个Y的值\r\nI want to find the values of y,\r\n\r\n609\r\n00:47:52,300 --> 00:47:55,440\r\n使得在这里带入这个值后 得到的是相同的值\r\nwhich if I put y in here, I get the same value out here\r\n\r\n610\r\n00:47:56,580 --> 00:47:58,400\r\n考虑在一定的误差范围内\r\nup to some degree of accuracy.\r\n\r\n611\r\n00:47:59,740 --> 00:48:03,400\r\n好在我已经有一个计算不动点的过程了\r\nWell, I already have a fixed point process around to do that.\r\n\r\n612\r\n00:48:04,600 --> 00:48:07,300\r\n我们在这里开始定义牛顿法\r\nAnd so, let's just define Newton's method over here.\r\n\r\n613\r\n00:48:19,640 --> 00:48:21,920\r\n这个过程需要一个函数和一个猜测值\r\nA procedure which computes a function and a guess,\r\n\r\n614\r\n00:48:24,440 --> 00:48:25,340\r\n初始的猜测值\r\ninitial guess.\r\n\r\n615\r\n00:48:26,180 --> 00:48:28,100\r\n我接下来要做一件事\r\nNow, I'm going to have to do something here.\r\n\r\n616\r\n00:48:28,520 --> 00:48:32,520\r\n要计算出函数的导数\r\nI'm going to need the derivative of the function.\r\n\r\n617\r\n00:48:32,860 --> 00:48:35,100\r\n我需要一个过程来计算出函数的导数\r\nI'm going to need a procedure which computes the derivative\r\n\r\n618\r\n00:48:36,120 --> 00:48:39,140\r\n给出的函数由过程F来计算\r\nof the function computed by the given a procedure f.\r\n\r\n619\r\n00:48:41,700 --> 00:48:43,780\r\n我接下来会讲的很仔细\r\nI'm trying to be very careful about what I'm saying.\r\n\r\n620\r\n00:48:44,160 --> 00:48:45,860\r\n我不想混淆“过程”和“函数”这两个词\r\nI don't want to mix up the word procedure and function.\r\n\r\n621\r\n00:48:45,860 --> 00:48:47,180\r\n函数是数学术语\r\nFunction is a mathematical word.\r\n\r\n622\r\n00:48:47,880 --> 00:48:52,160\r\n将一个值映射到另一个值\r\nIt says I'm mapping from values to other values,\r\n\r\n623\r\n00:48:52,420 --> 00:48:53,360\r\n有序偶的集合之类的\r\na set of ordered pairs.\r\n\r\n624\r\n00:48:55,060 --> 00:48:58,100\r\n但有时我也会不小心说岔\r\nBut sometimes, I'll accidentally mix those up.\r\n\r\n625\r\n00:48:59,800 --> 00:49:01,540\r\n而过程是用来计算函数的\r\nProcedures compute functions.\r\n\r\n626\r\n00:49:07,360 --> 00:49:10,220\r\n我将dF定义为...\r\nSo I'm going to define the derivative of f\r\n\r\n627\r\n00:49:10,820 --> 00:49:12,720\r\n再使用一下按愿望思维\r\nto be by wishful thinking again.\r\n\r\n628\r\n00:49:12,720 --> 00:49:13,560\r\n先不管具体如何实现\r\nI don't know how I'm going to do it.\r\n\r\n629\r\n00:49:14,360 --> 00:49:15,540\r\n我们之后再讨论\r\nLet's worry about that later--\r\n\r\n630\r\n00:49:18,360 --> 00:49:19,020\r\nF的导数\r\nof F.\r\n\r\n631\r\n00:49:20,160 --> 00:49:21,560\r\nF是一个过程\r\nSo if F is a procedure,\r\n\r\n632\r\n00:49:23,280 --> 00:49:26,320\r\n在这里的情况指的是开根号\r\nwhich happens to be this one over here for a square root,\r\n\r\n633\r\n00:49:28,780 --> 00:49:31,780\r\ndF就是其的导数\r\nthen DF will be the derivative of it,\r\n\r\n634\r\n00:49:31,920 --> 00:49:35,500\r\n也就是由过程F计算的函数的导函数\r\nwhich is also the derivative of the function computed by that procedure.\r\n\r\n635\r\n00:49:35,500 --> 00:49:40,620\r\ndF就是一个计算由过程F计算的函数的导数过程\r\nDF will be a procedure that computes the derivative of the function computed by the procedure F.\r\n\r\n636\r\n00:49:41,840 --> 00:49:44,520\r\n定义好这个之后 我就要来寻找一个不动点\r\nAnd then given that, I will just go looking for a fixed point.\r\n\r\n637\r\n00:49:51,380 --> 00:49:53,160\r\n我要寻找的不动点是什么的呢？\r\nWhat is the fixed point I'm looking for?\r\n\r\n638\r\n00:49:53,300 --> 00:49:56,440\r\n这个过程有一个参数X\r\nIt's the one for that procedure of one argument x,\r\n\r\n639\r\n00:49:57,060 --> 00:50:00,000\r\n计算出X减...\r\nwhich I compute by subtracting x.\r\n\r\n640\r\n00:50:00,100 --> 00:50:02,680\r\nX是先前的值 相当于那里的Yn\r\nThat's the old-- that's the yn here.\r\n\r\n641\r\n00:50:04,480 --> 00:50:11,560\r\nF(X)和dF(X)的商\r\nThe quotient of f of x and df of x,\r\n\r\n642\r\n00:50:20,180 --> 00:50:21,540\r\n从原始的猜测值开始\r\nstarting out with the original guess.\r\n\r\n643\r\n00:50:29,440 --> 00:50:31,020\r\n整个看上去很简单\r\nThat's all very simple.\r\n\r\n644\r\n00:50:32,180 --> 00:50:34,220\r\n现在 我还有一个部分没有写\r\nNow, I have one part left that I haven't written,\r\n\r\n645\r\n00:50:34,220 --> 00:50:37,380\r\n我先需要你们回顾一下我整个的实现流程\r\nand I want you to see the process by which I write these things,\r\n\r\n646\r\n00:50:37,380 --> 00:50:38,520\r\n这在实际经验中是很实用的\r\nbecause this is really true.\r\n\r\n647\r\n00:50:39,820 --> 00:50:41,940\r\n首先我拥有数学的猜想\r\nI start out with some mathematical idea, perhaps.\r\n\r\n648\r\n00:50:42,220 --> 00:50:45,480\r\n通过按愿望思维\r\nBy wishful thinking, I assume\r\n\r\n649\r\n00:50:46,280 --> 00:50:49,200\r\n我假设我已经拥有了一些魔法可以实现一些过程\r\nthat by some magic I can do something that I have a name for.\r\n\r\n650\r\n00:50:50,580 --> 00:50:52,320\r\n先不关心到底如何去实现它们\r\nI'm not going to worry about how I do it yet.\r\n\r\n651\r\n00:50:54,500 --> 00:50:55,860\r\n然后再继续\r\nThen I go walking down here and say, well,\r\n\r\n652\r\n00:50:55,860 --> 00:50:59,060\r\n通过这些魔法 我大致实现了整个过程\r\nby some magic, I'm somehow going to figure how to do that,\r\n\r\n653\r\n00:51:00,540 --> 00:51:01,960\r\n即使还未实现某些方法\r\nbut I'm going to write my program anyway.\r\n\r\n654\r\n00:51:03,880 --> 00:51:06,220\r\n这种按愿望思维 对于工程来说是很重要的\r\nWishful thinking, essential to good engineering,\r\n\r\n655\r\n00:51:07,380 --> 00:51:09,700\r\n同样 对于计算机科学也是很重要的\r\nand certainly essential to a good computer science.\r\n\r\n656\r\n00:51:12,000 --> 00:51:16,560\r\n那么 有多少人想让你的计算机运行得更快？\r\nSo anyway, how many of you wished that your computer ran faster?\r\n\r\n657\r\n00:51:20,900 --> 00:51:22,520\r\n求导过程的实现并不会很困难\r\nWell, the derivative isn't so bad either.\r\n\r\n658\r\n00:51:23,060 --> 00:51:24,280\r\n有点类似于AVERAGE-DAMP过程\r\nSort of like average damping.\r\n\r\n659\r\n00:51:28,980 --> 00:51:35,340\r\nDERIV求导过程接受一个用于计算函数值的过程\r\nThe derivative is a procedure that takes a procedure that computes a function as its argument,\r\n\r\n660\r\n00:51:36,960 --> 00:51:41,000\r\n然后产生一个过程\r\nand it produces a procedure that computes a function,\r\n\r\n661\r\n00:51:41,180 --> 00:51:42,720\r\n接受一个参数X\r\nwhich needs one argument x.\r\n\r\n662\r\n00:51:43,700 --> 00:51:45,080\r\n你们应该都清楚导数的定义\r\nWell, you all know this definition.\r\n\r\n663\r\n00:51:45,900 --> 00:51:48,400\r\n是(F(X + dX) - F(X)) / dX  对吗？\r\nIt's f of x plus delta x minus f of x over delta x, right?\r\n\r\n664\r\n00:51:48,720 --> 00:51:49,860\r\ndX是一个很小的值\r\nFor some small delta x.\r\n\r\n665\r\n00:51:50,480 --> 00:52:10,180\r\n即(/ (- (F (+ X dX)) (F X)) dX)\r\nSo that's the quotient of the difference of f of the sum of x and dx minus f point x divided by dx.\r\n\r\n666\r\n00:52:18,040 --> 00:52:21,800\r\n我希望括号没有匹配错误\r\nI think the thing was lining up correctly when I balanced the parentheses.\r\n\r\n667\r\n00:52:24,760 --> 00:52:25,840\r\n我希望你们看一下这个\r\nNow, I want you to look at this.\r\n\r\n668\r\n00:52:26,660 --> 00:52:27,460\r\n仔细的观察一下\r\nJust look.\r\n\r\n669\r\n00:52:30,880 --> 00:52:32,620\r\n我应该还没定义dX\r\nI suppose I haven't told you what dx is.\r\n\r\n670\r\n00:52:32,860 --> 00:52:35,420\r\n我会在其它某个地方写下\r\nSomewhere in the world I'm going to have to write down\r\n\r\n671\r\n00:52:44,240 --> 00:52:45,340\r\n这样的定义\r\nsomething like that.\r\n\r\n672\r\n00:52:45,760 --> 00:52:46,780\r\n这无关紧要\r\nI'm not interested.\r\n\r\n673\r\n00:52:47,820 --> 00:52:53,680\r\n这个过程接受一个过程然后产生出一个近似过程\r\nThis is a procedure which takes a procedure and produces an approximation,\r\n\r\n674\r\n00:52:53,680 --> 00:52:56,480\r\n这个近似过程用于计算出某个函数的导数\r\na procedure that computes an approximation of the derivative\r\n\r\n675\r\n00:52:56,540 --> 00:52:58,540\r\n函数是由给定的过程计算的\r\nof the function computed by the procedure given\r\n\r\n676\r\n00:53:00,860 --> 00:53:03,000\r\n其中使用了大家熟悉的求导方法\r\nby the standard methods that you all know and love.\r\n\r\n677\r\n00:53:04,360 --> 00:53:10,440\r\n也许这并不是一个很好的估算导数的方法\r\nNow, it may not be the case that doing this operation is such a good way of approximating a derivative.\r\n\r\n678\r\n00:53:11,020 --> 00:53:14,700\r\n数值分析学家可能会跳出来对我说\r\nNumerical analysts here should jump on me and say\r\n\r\n679\r\n00:53:14,700 --> 00:53:15,360\r\n不要那样做！\r\ndon't do that.\r\n\r\n680\r\n00:53:16,320 --> 00:53:18,700\r\n计算机求导确实会带来一定的误差\r\nComputing derivatives produces noisy answers, which is true.\r\n\r\n681\r\n00:53:19,960 --> 00:53:23,460\r\n然而这只是用于理解整个过程\r\nHowever, this again is for the sake of understanding.\r\n\r\n682\r\n00:53:24,380 --> 00:53:25,320\r\n回顾一下\r\nLook what we've got.\r\n\r\n683\r\n00:53:26,180 --> 00:53:29,520\r\n我们首先起手于一个复杂的数学方法\r\nWe started out with what is apparently a mathematically complex thing.\r\n\r\n684\r\n00:53:30,820 --> 00:53:32,560\r\n写满的几个黑板中\r\nand in a few blackboards full,\r\n\r\n685\r\n00:53:33,760 --> 00:53:36,840\r\n我们试图将这个求根号的问题分解\r\nwe managed to decompose the problem of computing square roots\r\n\r\n686\r\n00:53:36,840 --> 00:53:42,300\r\n通过你们在数值课程中学到的牛顿法\r\nby the way you were taught in your college calculus class-- Newton's method--\r\n\r\n687\r\n00:53:43,380 --> 00:53:44,540\r\n分解以后就能很容易处理了\r\nso that it can be understood.\r\n\r\n688\r\n00:53:45,480 --> 00:53:46,220\r\n变得清晰了\r\nIt's clear.\r\n\r\n689\r\n00:53:47,400 --> 00:53:49,780\r\n看一下求解的整个结构\r\nLet's look at the structure of what it is we've got.\r\n\r\n690\r\n00:53:51,160 --> 00:53:52,580\r\n请看一下幻灯片\r\nLet's look at this slide.\r\n\r\n691\r\n00:53:54,580 --> 00:54:04,140\r\n这是黑板上描述的程序的流程图\r\nThis is a diagram of the machine described by the program on the blackboard.\r\n\r\n692\r\n00:54:05,440 --> 00:54:06,960\r\n描述了机器执行的过程\r\nThere's a machine described here.\r\n\r\n693\r\n00:54:08,520 --> 00:54:09,440\r\n有哪些部分呢？\r\nAnd what have I got?\r\n\r\n694\r\n00:54:10,240 --> 00:54:16,540\r\n这个部分代表了牛顿法中的函数F\r\nOver here is the Newton's method function f\r\n\r\n695\r\n00:54:16,840 --> 00:54:19,040\r\n写在了黑板的最左面\r\nthat we have on the left-most blackboard.\r\n\r\n696\r\n00:54:20,180 --> 00:54:22,520\r\n它接受了一个参数Y\r\nIt's the thing that takes an argument called y\r\n\r\n697\r\n00:54:22,780 --> 00:54:27,160\r\n计算出X与根号Y的差\r\nand puts out the difference between x and the square of y,\r\n\r\n698\r\n00:54:29,560 --> 00:54:35,980\r\n通过某种魔法 X作为自由变量从外部进入\r\nwhere x is some sort of free variable that comes in from the outside by some magic.\r\n\r\n699\r\n00:54:37,700 --> 00:54:41,500\r\n所以square-root过程需要获取到X的值\r\nSo the square root routine picks up an x,\r\n\r\n700\r\n00:54:42,180 --> 00:54:43,640\r\n并给定这个过程\r\nand builds this procedure,\r\n\r\n701\r\n00:54:45,280 --> 00:54:48,120\r\nX就被替换到内部的过程中\r\nwhich I have the x rolled up in it by substitution.\r\n\r\n702\r\n00:54:49,720 --> 00:54:54,780\r\n云中的这个过程被作为参数F\r\nNow, this procedure in the cloud is fed in as the f\r\n\r\n703\r\n00:54:58,080 --> 00:55:01,280\r\n传递进这个框中的牛顿法\r\ninto the Newton's method which is here, this box.\r\n\r\n704\r\n00:55:04,580 --> 00:55:07,900\r\nF在这里有两个去向\r\nThe f is fanned out.\r\n\r\n705\r\n00:55:08,400 --> 00:55:10,380\r\n一是被用作参数传递\r\nPart of it goes into something else,\r\n\r\n706\r\n00:55:10,900 --> 00:55:14,220\r\n二是被应用到求导过程中 再将求导结果传递\r\nand the other part of it goes through a derivative process into something else\r\n\r\n707\r\n00:55:14,980 --> 00:55:17,140\r\n来产生一个新的过程\r\nto produce a procedure,\r\n\r\n708\r\n00:55:17,720 --> 00:55:23,360\r\n产生出的过程作为计算牛顿法的迭代函数的过程\r\nwhich computes the function which is the iteration function of Newton's method\r\n\r\n709\r\n00:55:23,360 --> 00:55:24,640\r\n最后将其应用到求不动点的方法上\r\nwhen we use the fixed point method.\r\n\r\n710\r\n00:55:27,120 --> 00:55:29,000\r\n所以这个过程\r\nSo this procedure,\r\n\r\n711\r\n00:55:29,940 --> 00:55:32,420\r\n通过代换使用了（F和dF）\r\nwhich contains it by substitution--\r\n\r\n712\r\n00:55:32,560 --> 00:55:38,340\r\n记住 是这里的牛顿法构造出了这个过程\r\nremember, Newton's method over here, Newton's method builds this procedure,\r\n\r\n713\r\n00:55:39,320 --> 00:55:43,060\r\n并且是在牛顿法中定义了F和dF\r\nand Newton's method has in it defined f and df,\r\n\r\n714\r\n00:55:44,640 --> 00:55:47,300\r\n所以 F和dF在这里被捕获\r\nso those are captured over here: f and df.\r\n\r\n715\r\n00:55:48,600 --> 00:55:49,900\r\n利用这个过程\r\nStarting with this procedure,\r\n\r\n716\r\n00:55:50,440 --> 00:55:52,680\r\n传递进FIXED-POINT过程里\r\nI can now feed this to the fixed point process\r\n\r\n717\r\n00:55:53,220 --> 00:55:56,840\r\n再利用从SQRT外传递进的初始的猜测值\r\nwithin an initial guess coming out from the outside from square root\r\n\r\n718\r\n00:55:58,140 --> 00:55:59,580\r\n来计算出X的平方根\r\nto produce the square root of x.\r\n\r\n719\r\n00:56:03,340 --> 00:56:05,820\r\n于是我们就制造出了一个强大的引擎\r\nSo what we've built is a very powerful engine,\r\n\r\n720\r\n00:56:06,600 --> 00:56:09,260\r\n通过它我们可以制造出类似的优美的东西\r\nwhich allows us to make nice things like this.\r\n\r\n721\r\n00:56:11,240 --> 00:56:19,160\r\n最后 我想使用Chris Strachey提出的一个基本思想作为结束\r\nNow, I want to end this with basically an idea of Chris Strachey,\r\n\r\n722\r\n00:56:19,600 --> 00:56:22,540\r\n他是计算机科学之父之一\r\none of the grandfathers of computer science.\r\n\r\n723\r\n00:56:22,900 --> 00:56:25,180\r\n他是一位逻辑学家 大概...\r\nHe's a logician who lived in the--\r\n\r\n724\r\n00:56:27,040 --> 00:56:29,700\r\n大概10到15年前他去世了\r\nI suppose about 10 years ago or 15 years ago, he died.\r\n\r\n725\r\n00:56:29,860 --> 00:56:31,340\r\n我记不太清了\r\nI don't remember exactly when.\r\n\r\n726\r\n00:56:31,500 --> 00:56:34,240\r\n他是指称语义学的发明者之一\r\nHe's one of the inventors of something called denotational semantics.\r\n\r\n727\r\n00:56:34,600 --> 00:56:42,320\r\n他是将过程或是函数视为程序设计语言中的第一级元素的最主要的提倡者\r\nHe was a great advocate of making procedures or functions first-class citizens in a programming language.\r\n\r\n728\r\n00:56:43,540 --> 00:56:48,660\r\n这些是程序设计语言中的第一级元素的某些权利或者特权\r\nSo here's the rights and privileges of first-class citizens in a programming language.\r\n\r\n729\r\n00:56:50,140 --> 00:56:52,080\r\n如果你想要做出任何你想要做出的抽象\r\nIt allows you to make any abstraction you like\r\n\r\n730\r\n00:56:52,540 --> 00:56:55,460\r\n那么将函数视为第一级元素是必须的\r\nif you have functions as first-class citizens.\r\n\r\n731\r\n00:56:57,260 --> 00:57:00,060\r\n第一级元素必须能够可以用变量命名\r\nThe first-class citizens must be able to be named by variables.\r\n\r\n732\r\n00:57:01,840 --> 00:57:03,660\r\n你们已经见过我这样做过很多次\r\nAnd you're seeing me doing that all the time.\r\n\r\n733\r\n00:57:04,000 --> 00:57:08,200\r\n这里是将某个过程作为变量命名的例子\r\nHere's a nice variable which names a procedure which computes something.\r\n\r\n734\r\n00:57:12,820 --> 00:57:15,040\r\n他们必须可以被提供给过程作为参数\r\nThey have to be passed as arguments to procedures.\r\n\r\n735\r\n00:57:15,040 --> 00:57:16,020\r\n我们之前见过这种情况了\r\nWe've certainly seen that.\r\n\r\n736\r\n00:57:18,160 --> 00:57:20,940\r\n他们可以由过程作为结果返回\r\nWe have to be able to return them as values from procedures.\r\n\r\n737\r\n00:57:22,840 --> 00:57:24,320\r\n我们也应该见过了\r\nAnd I suppose we've seen that.\r\n\r\n738\r\n00:57:24,740 --> 00:57:27,040\r\n我们还没有见过关于数据结构的内容\r\nWe haven't yet seen anything about data structures.\r\n\r\n739\r\n00:57:27,600 --> 00:57:28,440\r\n我们之后会讨论的\r\nWe will soon,\r\n\r\n740\r\n00:57:29,140 --> 00:57:33,140\r\n这也是作为程序设计语言的第一级元素必要的性质\r\nbut it's also the case that in order to have a first-class citizen in a programming language,\r\n\r\n741\r\n00:57:33,520 --> 00:57:35,980\r\n它们可以包含在数据结构中\r\nthe object has to be allowed to be part of a data structure.\r\n\r\n742\r\n00:57:36,760 --> 00:57:37,880\r\n我们马上就会见到\r\nWe're going to see that soon.\r\n\r\n743\r\n00:57:39,040 --> 00:57:40,320\r\n所以就先到此为止吧\r\nSo I just want to close with this\r\n\r\n744\r\n00:57:40,820 --> 00:57:46,380\r\n我们见识到了像过程这样的第一级元素\r\nand say having things like procedures as first-class data structures, first-class data,\r\n\r\n745\r\n00:57:46,960 --> 00:57:49,800\r\n可以带来如此强大的抽象能力\r\nallows one to make powerful abstractions,\r\n\r\n746\r\n00:57:50,220 --> 00:57:53,720\r\n像牛顿法这样的通用方法可以被非常清晰地编写出来\r\nwhich encode general methods like Newton's method in very clear way.\r\n\r\n747\r\n00:57:54,380 --> 00:57:55,280\r\n有什么问题吗？\r\nAre there any questions?\r\n\r\n748\r\n00:57:56,960 --> 00:57:57,440\r\n请\r\nYes.\r\n\r\n749\r\n00:57:57,980 --> 00:58:01,920\r\n观众：(DERIV F)可以直接写到FIXED-POINT方法中取代dF吗\r\nAUDIENCE: Could you put derivative instead of df directly in the fixed point?\r\n\r\n750\r\n00:58:02,120 --> 00:58:02,700\r\n教授：哦 当然\r\nPROFESSOR: Oh, sure.\r\n\r\n751\r\n00:58:03,420 --> 00:58:07,400\r\n当然可以直接把(DERIV F)放到这里\r\nYes, I could have put deriv of f right here,\r\n\r\n752\r\n00:58:08,180 --> 00:58:09,080\r\n没有问题\r\nno question.\r\n\r\n753\r\n00:58:11,360 --> 00:58:13,320\r\n每当你见到定义了什么东西\r\nAny time you see something defined,\r\n\r\n754\r\n00:58:14,180 --> 00:58:17,240\r\n你就可以直接把定义写到这里\r\nyou can put the thing that the definition is there\r\n\r\n755\r\n00:58:18,380 --> 00:58:19,320\r\n你会得到相同的结果\r\nand you should get the same result.\r\n\r\n756\r\n00:58:20,620 --> 00:58:22,700\r\n实际上 那样就会看上去很有趣\r\nIn fact, what that would look like, it's interesting.\r\n\r\n757\r\n00:58:22,700 --> 00:58:23,040\r\n观众：LAMBDA\r\nAUDIENCE: Lambda.\r\n\r\n758\r\n00:58:23,240 --> 00:58:23,660\r\n教授：嗯？\r\nPROFESSOR: Huh?\r\n\r\n759\r\n00:58:23,760 --> 00:58:25,300\r\n观众：你可以把LAMBDA表达式写在那\r\nAUDIENCE: You could put the lambda expression in there.\r\n\r\n760\r\n00:58:25,480 --> 00:58:28,340\r\n教授：我也可以把(DERIV F)写在这\r\nPROFESSOR: I could also put derivative of f here.\r\n\r\n761\r\n00:58:29,940 --> 00:58:30,820\r\n这看上去会很有意思\r\nIt would look interesting\r\n\r\n762\r\n00:58:31,100 --> 00:58:36,620\r\n即((DERIV F) X)\r\nbecause of the open paren, open paren, deriv of f, closed paren on an x.\r\n\r\n763\r\n00:58:38,140 --> 00:58:41,840\r\n那样就会冗余地重复计算导数\r\nNow, that would have the bad property of computing the derivative many times,\r\n\r\n764\r\n00:58:42,480 --> 00:58:43,840\r\n因为每当我执行这个过程的时候\r\nbecause every time I would run this procedure,\r\n\r\n765\r\n00:58:43,840 --> 00:58:45,120\r\n都要重新计算导数\r\nI would compute the derivative again.\r\n\r\n766\r\n00:58:47,840 --> 00:58:51,800\r\n这里的两个左括号都有意义\r\nHowever, the two open parens here both would be meaningful.\r\n\r\n767\r\n00:58:52,100 --> 00:58:54,960\r\n我希望你们理解这里细节的语法\r\nI want you to understand syntactically that that's a sensible thing.\r\n\r\n768\r\n00:58:55,820 --> 00:58:57,460\r\n如果我重写这个程序\r\nBecause if was to rewrite this program--\r\n\r\n769\r\n00:58:57,460 --> 00:58:58,920\r\n在这里按照你的想法重写\r\nand I should do it right here just so you see\r\n\r\n770\r\n00:58:59,760 --> 00:59:00,800\r\n这个问题问得好\r\nbecause that's a good question--\r\n\r\n771\r\n00:59:10,200 --> 00:59:12,260\r\n...F和GUESS\r\nof F and guess\r\n\r\n772\r\n00:59:15,800 --> 00:59:26,080\r\n结果是求参数为X\r\nto be fixed point of that procedure of one argument x,\r\n\r\n773\r\n00:59:26,380 --> 00:59:44,720\r\n结果为(- X (/ (F X)((DERIV F) X)))的过程的不动点\r\nwhich subtracts from x the quotient of F applied to x and the deriv of F applied to x.\r\n\r\n774\r\n00:59:52,940 --> 00:59:54,220\r\n这里是GUESS\r\nUm, This is guess.\r\n\r\n775\r\n00:59:59,500 --> 01:00:01,420\r\n这是一个完全正确的程序\r\nThis is a perfectly legitimate program,\r\n\r\n776\r\n01:00:02,260 --> 01:00:03,540\r\n因为在这里...\r\nbecause what I have here--\r\n\r\n777\r\n01:00:03,860 --> 01:00:05,300\r\n记住求值规则\r\nremember the evaluation rule.\r\n\r\n778\r\n01:00:05,780 --> 01:00:09,040\r\n求值规则是求值每个组合式的所有部分\r\nThe evaluation rule is evaluate all of the parts of the combination:\r\n\r\n779\r\n01:00:09,040 --> 01:00:11,040\r\n包括运算符和运算对象\r\nthe operator and the operands.\r\n\r\n780\r\n01:00:11,720 --> 01:00:14,640\r\n这是这个组合式的运算符\r\nThis is the operator of this combination.\r\n\r\n781\r\n01:00:16,540 --> 01:00:22,120\r\n求值这个运算符会产生F的导数\r\nEvaluating this operator will, of course, produce the derivative of F.\r\n\r\n782\r\n01:00:28,080 --> 01:00:31,160\r\n观众：甚者 是否可以在那里写成LAMBDA表达式\r\nAUDIENCE: To get it one step further, you could put the lambda expression there, too.\r\n\r\n783\r\n01:00:31,220 --> 01:00:32,020\r\n教授：哦当然\r\nPROFESSOR: Oh, of course.\r\n\r\n784\r\n01:00:32,780 --> 01:00:35,720\r\n每当我在某处使用了定义好的东西\r\nAny time I take something which is define,\r\n\r\n785\r\n01:00:35,720 --> 01:00:40,760\r\n我也可以将其替换成它定义的具体内容\r\nI can put the thing it's defined to be in the place where the thing defined is.\r\n\r\n786\r\n01:00:41,960 --> 01:00:44,820\r\n不用去区分哪个是被定义项 哪个是定义项\r\nI can't remember which is definiens and which is definiendum.\r\n\r\n787\r\n01:00:45,460 --> 01:00:51,600\r\n每当我在思考如何在课堂上向新手解释这个问题\r\nWhen I'm trying to figure out how to do a lecture about this in a freshman class,\r\n\r\n788\r\n01:00:51,600 --> 01:00:55,120\r\n我觉得这种概念游戏是很有意思的\r\nI use such words and tell everybody it's fun to tell their friends.\r\n\r\n789\r\n01:00:59,200 --> 01:01:00,040\r\n那么就到此为止吧\r\nOK, I think that's it.\r\n\r\n790\r\n01:01:01,700 --> 01:01:08,220\r\nMIT OpenCourseWare\r\nhttp://ocw.mit.edu\r\n\r\n791\r\n01:01:08,300 --> 01:01:17,940\r\n本项目主页\r\nhttps://github.com/FoOTOo/Learning-SICP\r\n\r\n"
  },
  {
    "path": "SrtCN/lec2b.srt",
    "content": "﻿1\r\n00:00:00,000 --> 00:00:04,000\r\n哈尔滨工业大学 IBM技术中心\r\n倾情制作\r\n\r\n2\r\n00:00:04,100 --> 00:00:08,000\r\n压制&&特效：蔡钟毓（JohnTitor）\r\n翻译&&时间轴：邓雄飞（Dysprosium）\r\n\r\n3\r\n00:00:08,100 --> 00:00:12,000\r\n特别感谢：裘宗燕教授\r\n校对：邓雄飞（Dysprosium）\r\n\r\n4\r\n00:00:13,000 --> 00:00:16,500\r\n复合数据\r\nCompound Data\r\n\r\n5\r\n00:00:21,720 --> 00:00:25,020\r\n到目前为止 这门课都在讨论过程\r\nWell, so far in this course we've been talking about procedures,\r\n\r\n6\r\n00:00:25,920 --> 00:00:27,900\r\n我想提醒大家 我们介绍的这个框架\r\nand then just to remind you of this framework\r\n\r\n7\r\n00:00:29,040 --> 00:00:30,840\r\n是用来讨论语言的\r\nthat we introduced for talking about languages,\r\n\r\n8\r\n00:00:30,840 --> 00:00:34,800\r\n我们讨论内建于系统中的基本元素\r\nwe talked about the primitive things that are built into the system.\r\n\r\n9\r\n00:00:35,540 --> 00:00:37,620\r\n我们介绍了一些组合的方法\r\nWe mentioned some means of combination\r\n\r\n10\r\n00:00:38,660 --> 00:00:41,540\r\n这些方法用来组合基本元素 使你能够构造更复杂的东西\r\nby which you take the primitive thingsand you make more complicated things.\r\n\r\n11\r\n00:00:42,200 --> 00:00:43,960\r\n然后我们讨论了抽象的方法\r\nAnd then we talked about the means of abstraction,\r\n\r\n12\r\n00:00:43,960 --> 00:00:46,220\r\n你如何去取用这些复杂的东西\r\nhow you can take those complicated things and name them\r\n\r\n13\r\n00:00:46,560 --> 00:00:48,220\r\n给它们命名 这样就可以像简单单元那样使用\r\nso you can use them as simple building blocks.\r\n\r\n14\r\n00:00:49,320 --> 00:00:51,560\r\n上节课最后 我们甚至做了更超前的东西\r\nAnd then last time you saw we went even beyond that.\r\n\r\n15\r\n00:00:51,560 --> 00:00:54,140\r\n我们看到 通过使用高阶过程\r\nWe saw that by using higher order procedures,\r\n\r\n16\r\n00:00:55,200 --> 00:00:57,800\r\n我们甚至可以表达计算的通用方法\r\nyou can actually express general methods for computing things.\r\n\r\n17\r\n00:00:57,800 --> 00:01:02,160\r\n这就像求不动点的方法和牛顿法\r\nLike the method of doing something by fixed points, or Newton's method,\r\n\r\n18\r\n00:01:02,940 --> 00:01:05,500\r\n你可以通过组合这些抽象的方法\r\nand so the incredible expressive power you can get\r\n\r\n19\r\n00:01:05,760 --> 00:01:08,280\r\n来得到这种难以置信的表达力\r\njust by combining these means of abstraction.\r\n\r\n20\r\n00:01:08,280 --> 00:01:11,820\r\n这样做的中心点是\r\nAnd the crucial idea in all of this is\r\n\r\n21\r\n00:01:11,820 --> 00:01:14,220\r\n我们要构建一个层次系统\r\nthe one that we build a layered system.\r\n\r\n22\r\n00:01:14,900 --> 00:01:15,940\r\n譬如说\r\nSo for instance,\r\n\r\n23\r\n00:01:16,180 --> 00:01:18,080\r\n如果我们编写平方根过程\r\nif we're writing the square root procedure,\r\n\r\n24\r\n00:01:20,880 --> 00:01:25,920\r\n而这个平方根过程又用到了一个叫GOOD-ENOUGH的过程\r\nsomewhere the square root procedure uses a procedure called good-enough,\r\n\r\n25\r\n00:01:31,080 --> 00:01:35,060\r\n而这两者之间就有某种抽象屏障\r\nand between those there is some sort of abstraction boundary.\r\n\r\n26\r\n00:01:37,640 --> 00:01:40,980\r\n这大概就像是我们开始编写平方根程序\r\nIt's almost as if we go out and in writing square root,\r\n\r\n27\r\n00:01:40,980 --> 00:01:43,640\r\n先要与George订好“契约”\r\nwe go and make a contract with George,\r\n\r\n28\r\n00:01:44,760 --> 00:01:46,940\r\n告诉他 他的工作是编写GOOD-ENOUGH过程\r\nand tell George that his job is to write good-enough,\r\n\r\n29\r\n00:01:48,660 --> 00:01:50,320\r\n因此只要GOOD-ENOUGH按我们的预期运作\r\nand so long as good-enough works,\r\n\r\n30\r\n00:01:50,320 --> 00:01:51,460\r\n我们就不管它是如何运作的\r\nwe don't care what it does.\r\n\r\n31\r\n00:01:52,320 --> 00:01:54,220\r\n我们不关心（它的内部）实现\r\nWe don't care exactly how it's implemented.\r\n\r\n32\r\n00:01:54,220 --> 00:01:58,880\r\n实现层面是Goerge操心的 和我们无关\r\nThere are levels of detail here that are George's concern and not ours.\r\n\r\n33\r\n00:02:00,100 --> 00:02:00,900\r\n又比如\r\nSo for instance,\r\n\r\n34\r\n00:02:00,900 --> 00:02:05,440\r\nGeorge可能用了Harry写的绝对值过程\r\nGeorge might use an absolute value procedure that's written by Harry,\r\n\r\n35\r\n00:02:06,240 --> 00:02:07,440\r\n但我们不会去关心这些\r\nand we don't much care about that\r\n\r\n36\r\n00:02:07,440 --> 00:02:09,940\r\n我们甚至可能还不知道有Harry这号人\r\nor even know that, maybe, Harry exists.\r\n\r\n37\r\n00:02:13,500 --> 00:02:16,320\r\n关键就是 当我们在构造东西时\r\nSo the crucial idea is that when we're building things,\r\n\r\n38\r\n00:02:16,320 --> 00:02:23,740\r\n我们将构造整体的任务划分为了实现部件的任务\r\nwe divorce the task of building things from the task of implementing the parts.\r\n\r\n39\r\n00:02:26,340 --> 00:02:28,740\r\n当然 在一个大型系统中\r\nAnd in a large system, of course,\r\n\r\n40\r\n00:02:28,740 --> 00:02:30,580\r\n我们有像这样的抽象屏障\r\nwe have abstraction barriers like this\r\n\r\n41\r\n00:02:30,920 --> 00:02:32,580\r\n在很高很高很高层次上的抽象屏障\r\nat lots, and lots, and lots of levels.\r\n\r\n42\r\n00:02:33,780 --> 00:02:35,980\r\n这也是我们到目前为止一直在使用的思想\r\nAnd that's the idea that we've been using so far\r\n\r\n43\r\n00:02:35,980 --> 00:02:37,740\r\n贯彻到每次编写过程之中\r\nover and over in implementing procedures.\r\n\r\n44\r\n00:02:37,740 --> 00:02:42,360\r\n言归正传 我们将要在数据中看到同样的问题\r\nWell, now what we're going to do is look at the same issues for data.\r\n\r\n45\r\n00:02:43,760 --> 00:02:46,100\r\n我们发现系统中有基本数据\r\nWe're going to see that the system has primitive data.\r\n\r\n46\r\n00:02:46,100 --> 00:02:47,180\r\n实际上我们已经注意了\r\nIn fact, we've already seen that.\r\n\r\n47\r\n00:02:47,180 --> 00:02:48,960\r\n我们已经讨论了作为基本对象的数\r\nWe've talked about numbers as primitive data.\r\n\r\n48\r\n00:02:49,940 --> 00:02:52,120\r\n我们将看到适用于数据的组合方法\r\nAnd then we're going to see their means of combination for data.\r\n\r\n49\r\n00:02:52,120 --> 00:02:55,620\r\n有一种“胶水” 能让你把基本数据粘合在一起\r\nThere's glue that allows you to put primitive data together\r\n\r\n50\r\n00:02:56,040 --> 00:02:58,720\r\n来构造一种更复杂的符合数据\r\nto make more complicated, kind of compound data.\r\n\r\n51\r\n00:02:59,160 --> 00:03:03,700\r\n然后我们将看到一种抽象方法学\r\nAnd then we're going to see a methodology for abstraction\r\n\r\n52\r\n00:03:04,600 --> 00:03:06,040\r\n这种方法十分好用 尤其是\r\nthat's a very good thing to use\r\n\r\n53\r\n00:03:06,040 --> 00:03:08,480\r\n当你用简易的数据构造复杂数据时\r\nwhen you start building up data in terms of simpler data.\r\n\r\n54\r\n00:03:08,480 --> 00:03:12,560\r\n再次强调 中心思想是要建立层次化的系统\r\nAnd again, the key idea is that you're going to build the system in layers\r\n\r\n55\r\n00:03:13,420 --> 00:03:17,860\r\n建立抽象屏障将细节隔离在底层\r\nand set up abstraction barriers that isolate the details at the lower layers\r\n\r\n56\r\n00:03:19,560 --> 00:03:21,280\r\n将细节与你所工作的高层环境隔离开\r\nfrom the thing that's going on at the upper layers.\r\n\r\n57\r\n00:03:21,280 --> 00:03:24,120\r\n底层的细节 底层的思想 都不重要\r\nThe details at the lower layers, the ideas, they won't matter.\r\n\r\n58\r\n00:03:24,920 --> 00:03:26,260\r\n那是George该操心的\r\nThey're going to be George's concern\r\n\r\n59\r\n00:03:26,520 --> 00:03:28,160\r\n因为他跟我们“订好契约”\r\nbecause he signed this contract with us\r\n\r\n60\r\n00:03:28,480 --> 00:03:30,560\r\n他负责实现这些行为\r\nfor how the stuff that he implements behaves,\r\n\r\n61\r\n00:03:31,640 --> 00:03:34,120\r\n怎么实现都是他的事\r\nand how he implements the thing is his problem.\r\n\r\n62\r\n00:03:35,960 --> 00:03:37,360\r\n好了 来看一个实例吧\r\nAll right, well let's look at an example.\r\n\r\n63\r\n00:03:37,480 --> 00:03:40,320\r\n我们将会讨论一个系统\r\nAnd the example I'm going to talk about is a system\r\n\r\n64\r\n00:03:40,400 --> 00:03:42,560\r\n一个在有理数域上做算术运算的系统\r\nthat does arithmetic on rational numbers.\r\n\r\n65\r\n00:03:42,560 --> 00:03:44,300\r\n我现在所想到的是\r\nAnd what I have in mind is that\r\n\r\n66\r\n00:03:44,660 --> 00:03:46,520\r\n计算机中应该有某种东西\r\nwe should have something in the computer\r\n\r\n67\r\n00:03:46,860 --> 00:03:50,340\r\n使得我们可以查询\r\nthat allows us to ask it,\r\n\r\n68\r\n00:03:50,340 --> 00:03:55,160\r\n类似于 1/2加上1/4的和是多少\r\nlike, what's the sum of 1/2 and 1/4,\r\n\r\n69\r\n00:03:55,520 --> 00:04:01,220\r\n系统说 是3/4\r\nand somehow the system should say, yeah, that's 3/4.\r\n\r\n70\r\n00:04:02,520 --> 00:04:09,400\r\n我们也可以查询3/4乘以2/3的积\r\nOr we should be able to say what's 3/4 times 2/3,\r\n\r\n71\r\n00:04:10,720 --> 00:04:13,400\r\n系统因该能够回答 结果是1/2\r\nand the system should be able to say, yeah, that's 1/2.\r\n\r\n72\r\n00:04:16,100 --> 00:04:17,700\r\n对吧？ 你知道我想表达的意思\r\nRight? And you know what I have in mind.\r\n\r\n73\r\n00:04:17,700 --> 00:04:20,240\r\n我不太确定你们是多久掌握这些运算的\r\nAnd you also know how to do this from, I don't know,\r\n\r\n74\r\n00:04:20,240 --> 00:04:21,480\r\n五年级或者六年级吧？\r\nfifth grade or sixth grade.\r\n\r\n75\r\n00:04:21,900 --> 00:04:23,420\r\n这里的一些公式说\r\nThere are these formulas that say\r\n\r\n76\r\n00:04:23,420 --> 00:04:28,020\r\n如果有形式为分子除以分母的分数\r\nif I have some fraction which is a numerator over a denominator,\r\n\r\n77\r\n00:04:28,200 --> 00:04:31,100\r\n而如果我要将这个分数与另一个分数相加的话\r\nand I want to add that to some other fraction\r\n\r\n78\r\n00:04:31,360 --> 00:04:34,600\r\n当然 这个分数也是分子除以分母\r\nwhich is another numerator over another denominator,\r\n\r\n79\r\n00:04:34,980 --> 00:04:38,380\r\n那么结果将会是 第一个分数的分子\r\nthen the answer is the numerator of the first\r\n\r\n80\r\n00:04:39,020 --> 00:04:40,980\r\n乘以第二个分数的分母\r\ntimes the denominator of the second,\r\n\r\n81\r\n00:04:41,680 --> 00:04:46,300\r\n加上第二个分数的分子乘以第一个分数的分母\r\nplus the numerator of the second times the denominator of the first.\r\n\r\n82\r\n00:04:48,100 --> 00:04:49,380\r\n当然 这只是答案的分子\r\nThat's the numerator of the answer,\r\n\r\n83\r\n00:04:49,380 --> 00:04:52,860\r\n答案的分母是两个分数的分母之积\r\nand the denominator is the product of the two denominators.\r\n\r\n84\r\n00:04:52,860 --> 00:04:57,040\r\n对吧？ 这大概就是五、六年级课程的分数算术\r\nRight? So there's something from fifth or sixth grade fraction arithmetic.\r\n\r\n85\r\n00:04:57,040 --> 00:04:59,360\r\n类似地 如果我想要将两个数乘起来\r\nAnd then similarly, if I want to multiply two things,\r\n\r\n86\r\n00:04:59,360 --> 00:05:04,600\r\nN1除以D1的商 乘以 N2除以D2的商\r\nn1 over d1 multiplied by n2 over d2\r\n\r\n87\r\n00:05:05,460 --> 00:05:10,600\r\n就是两个分数的分子之积除以两个分母之积的商\r\nis the product of the numerators over the product of the denominators.\r\n\r\n88\r\n00:05:14,020 --> 00:05:15,160\r\n所以这些都不构成问题\r\nSo it's no problem at all,\r\n\r\n89\r\n00:05:16,380 --> 00:05:17,860\r\n当然 理解这些\r\nbut it's absolutely no problem to\r\n\r\n90\r\n00:05:18,420 --> 00:05:20,580\r\n你想进行的分数运算\r\nthink about what computation you want to make\r\n\r\n91\r\n00:05:20,580 --> 00:05:22,480\r\n是完全没问题的\r\nin adding and multiplying these fractions.\r\n\r\n92\r\n00:05:23,460 --> 00:05:26,840\r\n但是当我们实现这个功能的时候 我们似乎遗漏了什么\r\nBut as soon as we go to implement it, we run up across something.\r\n\r\n93\r\n00:05:27,560 --> 00:05:31,560\r\n我们连有理数都没有\r\nWe don't have what a rational number is.\r\n\r\n94\r\n00:05:32,960 --> 00:05:38,220\r\n系统只提供给我们了单个数字 比如5和3\r\nso we said that the system gives us individuals number so we can have 5 and 3,\r\n\r\n95\r\n00:05:38,840 --> 00:05:42,700\r\n但我们没法去表达\r\nbut somehow we don't have a way of\r\n\r\n96\r\n00:05:43,180 --> 00:05:46,820\r\n一个同时具有3和4的东西\r\nsaying there's a thing that has both a 3 and a 4 in it,\r\n\r\n97\r\n00:05:47,380 --> 00:05:49,340\r\n或者同时具有2和3的东西\r\nor both a 2 and a 3.\r\n\r\n98\r\n00:05:49,340 --> 00:05:53,220\r\n但只要我们去想象\r\nIt's almost as if we'd like to imagine\r\n\r\n99\r\n00:05:53,380 --> 00:05:55,640\r\n我们就会看到一些云彩\r\nthat somehow there are these clouds,\r\n\r\n100\r\n00:05:57,280 --> 00:06:01,840\r\n某个云彩不知咋的就有分子和分母\r\nand a cloud somehow has both a numerator and a denominator in it,\r\n\r\n101\r\n00:06:02,060 --> 00:06:03,960\r\n这就是我们想让拥有的功能\r\nand that's what we'd like to work in terms of.\r\n\r\n102\r\n00:06:06,500 --> 00:06:07,980\r\n那么 我们要怎么解决这个问题呢？\r\nWell, how are we going to solve that problem?\r\n\r\n103\r\n00:06:07,980 --> 00:06:13,100\r\n我们将使用一种强大的设计策略来解决这个问题\r\nWe're going to solve that problem by using this incredibly powerful design strategy\r\n\r\n104\r\n00:06:13,520 --> 00:06:15,560\r\n这种策略我们已经反复使用过了\r\nthat you've already seen us use over and over.\r\n\r\n105\r\n00:06:16,180 --> 00:06:18,160\r\n这就是按愿望思维的策略\r\nAnd that's the strategy of wishful thinking.\r\n\r\n106\r\n00:06:25,340 --> 00:06:27,340\r\n假设现在还没有任何过程\r\nJust like before when we didn't have a procedure,\r\n\r\n107\r\n00:06:27,340 --> 00:06:30,380\r\n我们就想象确实存在着某个过程\r\nwe said, well, let's imagine that that procedure already exists.\r\n\r\n108\r\n00:06:30,980 --> 00:06:34,040\r\n那么 我们就来想象我们有了这些（有理数）云彩吧\r\nWe'll say, well, let's imagine that we have these clouds.\r\n\r\n109\r\n00:06:35,720 --> 00:06:37,820\r\n更准确一点来说\r\nNow more precisely what I mean is\r\n\r\n110\r\n00:06:38,820 --> 00:06:43,180\r\n让我们假设我们有了三个过程\r\nlet's imagine that we have three procedures，\r\n\r\n111\r\n00:06:43,960 --> 00:06:45,240\r\n其一为MAKE-RAT\r\none called MAKE-RAT.\r\n\r\n112\r\n00:06:47,340 --> 00:06:53,120\r\nMAKE-RAT有两个参数\r\nMAKE-RAT is going to take as arguments two numbers,\r\n\r\n113\r\n00:06:54,200 --> 00:06:55,820\r\n我们分别把它们叫作分子和分母\r\nso I'll call them numerator and denominator,\r\n\r\n114\r\n00:06:57,620 --> 00:07:03,400\r\n它给我们返回一朵——我们需要的云彩\r\nand it'll return for us a cloud-- one of these clouds.\r\n\r\n115\r\n00:07:04,860 --> 00:07:06,420\r\n我并不知道云彩是什么\r\nI don't really know what a cloud is.\r\n\r\n116\r\n00:07:06,660 --> 00:07:09,160\r\n无论MAKE-RAT返回什么 那都是它的事\r\nIt's whatever MAKE-RAT returns, that's its business.\r\n\r\n117\r\n00:07:11,060 --> 00:07:11,960\r\n并且我们会说\r\nAnd then we're going to say,\r\n\r\n118\r\n00:07:12,080 --> 00:07:13,520\r\n假设我们有了这样的一个云彩\r\nsuppose we've got one of these clouds,\r\n\r\n119\r\n00:07:13,780 --> 00:07:15,740\r\n我们有个叫NUMER的过程\r\nwe have a procedure called NUMER,\r\n\r\n120\r\n00:07:16,720 --> 00:07:19,900\r\n这个过程需要我们传递具有N和D的云彩\r\nwhich takes in a cloud that has an n and a d in it,\r\n\r\n121\r\n00:07:19,920 --> 00:07:21,820\r\n不管这个云彩是什么 我也不知道这个云彩是什么\r\nwhatever a cloud is, and I don't know what it is,\r\n\r\n122\r\n00:07:22,780 --> 00:07:24,440\r\n但NUMER过程会返回（云彩的）分子部分\r\nand returns for us the numerator part.\r\n\r\n123\r\n00:07:26,760 --> 00:07:28,900\r\n我们也会假设我们有个叫DENOM的过程\r\nAnd then we'll assume we have a procedure DENOM,\r\n\r\n124\r\n00:07:30,820 --> 00:07:33,560\r\n该过程需要我们传递一个云彩 不管云彩是什么\r\nwhich again takes in a cloud, whatever a cloud is,\r\n\r\n125\r\n00:07:34,880 --> 00:07:37,480\r\n并返回（云彩的）分母部分\r\nand returns for us the denominator part.\r\n\r\n126\r\n00:07:37,480 --> 00:07:42,480\r\n就像之前我们构造平方根过程一样\r\nThis is just like before, when if we're building a square root,\r\n\r\n127\r\n00:07:42,560 --> 00:07:43,860\r\n我们假设我们有GOOD-ENOUGH过程\r\nwe assume that we have good-enough.\r\n\r\n128\r\n00:07:45,020 --> 00:07:48,520\r\n对吧？ 我们会找到George 对他说\r\nRight? And what we'll say is, we'll go find George, and we'll say to George,\r\n\r\n129\r\n00:07:48,700 --> 00:07:50,780\r\n那么 你的任务就是实现这三个过程\r\nwell, it's your business to make us these procedures.\r\n\r\n130\r\n00:07:51,920 --> 00:07:54,440\r\n你选择如何实现这些云彩 就是你的事了\r\nAnd how you choose to implement these clouds, that's your problem.\r\n\r\n131\r\n00:07:54,660 --> 00:07:55,380\r\n我们不想深究\r\nWe don't want to know.\r\n\r\n132\r\n00:07:58,500 --> 00:08:02,100\r\n这样 把这些杂事都推给George后\r\nWell, having pushed this task off onto George,\r\n\r\n133\r\n00:08:03,120 --> 00:08:05,080\r\n完成其它部分就相当容易了\r\nthen it's pretty easy to do the other part.\r\n\r\n134\r\n00:08:05,080 --> 00:08:08,180\r\n一旦我们有了这些云彩后 编写那些\r\nOnce we've got the clouds, it's pretty easy to write the thing\r\n\r\n135\r\n00:08:08,180 --> 00:08:10,500\r\n把有理数加起来的程序就变得容易多了\r\nthat does say addition of rational numbers.\r\n\r\n136\r\n00:08:11,340 --> 00:08:17,980\r\n你可以定义 这么说吧 定义+RAT\r\nYou can just say define, well, let's say +RAT.\r\n\r\n137\r\n00:08:22,080 --> 00:08:27,660\r\n定义+RAT过程 该过程需要两个有理数参数 X和Y\r\nDefine +RAT, which will take in two rational numbers, x and y.\r\n\r\n138\r\n00:08:27,760 --> 00:08:30,340\r\nX和Y就是这些云彩\r\nx and y are each these clouds.\r\n\r\n139\r\n00:08:31,520 --> 00:08:32,460\r\n这个过程干些啥呢？\r\nAnd what does it do? Well\r\n\r\n140\r\n00:08:32,760 --> 00:08:35,580\r\n它将返回给我们一个有理数\r\nit's going to return for us a rational number.\r\n\r\n141\r\n00:08:39,980 --> 00:08:41,340\r\n这个有理数是怎么得来的呢？\r\nWhat rational number is it? Well,\r\n\r\n142\r\n00:08:41,880 --> 00:08:43,220\r\n依据这里的公式\r\nwe've got the formulas there.\r\n\r\n143\r\n00:08:43,340 --> 00:08:45,760\r\n答案的分子的一部分为\r\nThe numerator of it is the sum of\r\n\r\n144\r\n00:08:47,020 --> 00:08:56,340\r\nX的分子与Y的分母之积\r\nthe product of the numerator of x and the denominator of y.\r\n\r\n145\r\n00:09:02,220 --> 00:09:03,360\r\n这只是答案的分子的一部分\r\nIt's one thing in the sum.\r\n\r\n146\r\n00:09:03,600 --> 00:09:06,180\r\n结果的分子剩下的一部分是\r\nAnd the other thing in the numerator is\r\n\r\n147\r\n00:09:06,260 --> 00:09:16,960\r\nY的分子与X的分母之积\r\nthe product of the numerator of y and the denominator of x.\r\n\r\n148\r\n00:09:18,800 --> 00:09:20,080\r\n闭合* 闭合+\r\nThe star, close the plus.\r\n\r\n149\r\n00:09:20,500 --> 00:09:23,380\r\n好了 这是MAKE-RAT的第一个参数\r\nRight, that's the first argument to MAKE-RAT,\r\n\r\n150\r\n00:09:23,380 --> 00:09:25,380\r\n这是我将要构造的云彩的分子\r\nwhich is the numerator of the thing I'm constructing.\r\n\r\n151\r\n00:09:26,220 --> 00:09:28,460\r\n而MAKE-RAT剩下的参数\r\nAnd then the rest of the thing goes into MAKE-RAT is\r\n\r\n152\r\n00:09:28,460 --> 00:09:30,340\r\n则是答案的分母\r\nthe denominator of the answer,\r\n\r\n153\r\n00:09:30,380 --> 00:09:40,860\r\n也就是X的分母乘以Y的分母\r\nwhich is the product of the denominator of x and the denominator of y.\r\n\r\n154\r\n00:09:41,960 --> 00:09:42,600\r\n像这样\r\nLike that.\r\n\r\n155\r\n00:09:45,440 --> 00:09:51,320\r\n好 这就是对有理数加法的一个模拟\r\nOK? So there is the analog of doing rational number addition.\r\n\r\n156\r\n00:09:51,380 --> 00:09:54,780\r\n在假设我们有了这些云彩后 就变得完全没有问题\r\nAnd it's no problem at all, assuming that we have these clouds.\r\n\r\n157\r\n00:09:59,000 --> 00:10:02,060\r\n当然 我们可以用同样的方法把它们乘起来\r\nAnd of course, we can do multiplication in the same way.\r\n\r\n158\r\n00:10:05,240 --> 00:10:11,900\r\n我们把将两个有理数乘起来定义为*RAT过程\r\nDefine how to get the product of two rational numbers, call it *RAT.\r\n\r\n159\r\n00:10:12,800 --> 00:10:16,140\r\n该过程需要两朵云彩 X和Y\r\nTakes in two of these clouds, x and y,\r\n\r\n160\r\n00:10:19,540 --> 00:10:21,540\r\n返回一个用MAKE-RAT构造的有理数\r\nit returns a rational number, MAKE-RAT,\r\n\r\n161\r\n00:10:24,280 --> 00:10:27,460\r\n这个有理数的分子是\r\nwhose numerator is the product of the numerators--\r\n\r\n162\r\n00:10:30,040 --> 00:10:36,220\r\nX的分子与Y的分子之积\r\nnumerator of x times the numerator of y.\r\n\r\n163\r\n00:10:37,820 --> 00:10:40,780\r\n而这个有理数的分母则是\r\nAnd the denominator of the thing it's going to return\r\n\r\n164\r\n00:10:41,200 --> 00:10:42,780\r\nX的分母与Y的分母之积\r\nis the product of the denominators.\r\n\r\n165\r\n00:10:57,120 --> 00:11:01,520\r\n好了 现在就差告诉你这些云彩是什么了\r\nWell, except that I haven't told you what these clouds are,\r\n\r\n166\r\n00:11:02,560 --> 00:11:04,860\r\n所有操作都是围绕它展开的 看到我做了什么吗？\r\nthat's all there is to it. See, what did I do?\r\n\r\n167\r\n00:11:04,960 --> 00:11:09,180\r\n我按照我的愿望假设我有一种新的数据类型\r\nI assumed by wishful thinking that I had a new kind of data object.\r\n\r\n168\r\n00:11:09,940 --> 00:11:15,100\r\n特别地 我假设我有创建这些数据类型的能力\r\nAnd in particular, I assumed I had ways of creating these data objects.\r\n\r\n169\r\n00:11:15,920 --> 00:11:17,780\r\n这里的MAKE-RAT就创建了一个新的数据类型\r\nMAKE-RAT creates one of these things.\r\n\r\n170\r\n00:11:17,780 --> 00:11:18,940\r\n这叫作“构造函数”\r\nThis is called a constructor.\r\n\r\n171\r\n00:11:25,300 --> 00:11:28,980\r\n我现在有了可以构造这些数据类型的东西了\r\nAll right, I have a thing that constructs such data objects.\r\n\r\n172\r\n00:11:29,380 --> 00:11:34,200\r\n然后我假设我有某些东西 有了这些东西后\r\nAnd then I assume I have things that, having made these things,\r\n\r\n173\r\n00:11:34,200 --> 00:11:37,680\r\n我就有从中抽取部分信息的方法了 这些叫作“选择函数”\r\nI have ways of getting the parts out. Those are called selectors.\r\n\r\n174\r\n00:11:42,460 --> 00:11:44,540\r\n说得更正式一点 就是说\r\nAnd so formally, what I said is I assumed\r\n\r\n175\r\n00:11:44,540 --> 00:11:48,660\r\n我假设有了用于处理这些数据类型的构造函数和选择函数\r\nI had procedures that are constructors and selectors for these data objects,\r\n\r\n176\r\n00:11:48,660 --> 00:11:49,940\r\n我就可以靠它们来编程了\r\nand then I went off and used them.\r\n\r\n177\r\n00:11:51,700 --> 00:11:55,580\r\n这就好比我说假设我有GOOD-ENOUGH?过程\r\nThat's no different in kind from saying I assume I have a procedure GOOD-ENOUGH?,\r\n\r\n178\r\n00:11:56,000 --> 00:11:57,800\r\n并用它来实现平方根这种做法\r\nand I go use it to implement square root.\r\n\r\n179\r\n00:12:00,420 --> 00:12:01,840\r\n好 在我们继续之前\r\nOK, well before we go on,\r\n\r\n180\r\n00:12:04,520 --> 00:12:08,020\r\n让我们来想想 为什么我们首先就在这个地方实现了这些东西？\r\nlet's ask the question of why do we want to do this in the first place?\r\n\r\n181\r\n00:12:08,360 --> 00:12:12,200\r\n为什么我们需要一个像+RAT这样的过程\r\nSee, why do we want a procedure like, like +RAT\r\n\r\n182\r\n00:12:13,260 --> 00:12:19,280\r\n一个需要两个有理数作为参数并返回一个有理数的过程\r\nthat takes in two rational numbers and returns a rational number?\r\n\r\n183\r\n00:12:19,960 --> 00:12:22,620\r\n换一种想法就是 我们实现的是这里的这个公式\r\nSee, another way to think about this is, well, here's this formula.\r\n\r\n184\r\n00:12:24,780 --> 00:12:28,760\r\n这里我也实现了用于加和两个有理数的东西\r\nAnd I've also got to implement something that adds rational numbers.\r\n\r\n185\r\n00:12:29,520 --> 00:12:31,680\r\n再换一种想法就是 这有这么一个东西\r\nOne other way to think about is, well, there's this thing,\r\n\r\n186\r\n00:12:31,860 --> 00:12:35,660\r\n可以让我输入四个数 N1 D1 N2 D2\r\nand I type in four numbers, an n1, and a d1, and an n2, and a d2.\r\n\r\n187\r\n00:12:36,240 --> 00:12:38,020\r\n然后这个东西就修改机器里的寄存器\r\nAnd it sets some registers in the machine\r\n\r\n188\r\n00:12:38,300 --> 00:12:42,120\r\n来代表分子和分母\r\nto a, this numerator and this denominator.\r\n\r\n189\r\n00:12:42,120 --> 00:12:42,920\r\n所以你大概会问\r\nSo I might say, well,\r\n\r\n190\r\n00:12:43,020 --> 00:12:45,600\r\n你为什么不用四个分别代表分子和分母的数\r\nwhy don't I just add rational numbers by I type in four numbers,\r\n\r\n191\r\n00:12:45,740 --> 00:12:46,880\r\n来做有理数加法\r\nnumerators and denominators,\r\n\r\n192\r\n00:12:46,880 --> 00:12:49,340\r\n这个加法返回两个数 分别代表分子和分母\r\nand get out two numbers, which is a numerator and a denominator.\r\n\r\n193\r\n00:12:50,480 --> 00:12:54,840\r\n我们为什么要像这样构造“云彩”？\r\nWhy are we worrying about building things like this anyway?\r\n\r\n194\r\n00:12:58,380 --> 00:12:59,700\r\n呃 那是因为\r\nWell, the answer is,\r\n\r\n195\r\n00:12:59,820 --> 00:13:05,720\r\n假设你想表达像这样的东西\r\nsuppose you want to think about expressing something like this,\r\n\r\n196\r\n00:13:05,780 --> 00:13:11,740\r\n假设我想表达让两个有理数\r\nsuppose I'd like to express the idea of taking two rational numbers,\r\n\r\n197\r\n00:13:12,980 --> 00:13:21,340\r\nX加Y的和 乘以 另外两个有理数S、T的和\r\nx plus y, say, and multiplying that by the sum of two other rational numbers.\r\n\r\n198\r\n00:13:23,300 --> 00:13:27,380\r\n然而 当我有了像+RAT和*RAT这样的东西后\r\nWell, the way I do it, having things like +RAT and *RAT,\r\n\r\n199\r\n00:13:28,200 --> 00:13:33,520\r\n我就会将其考虑为乘积\r\nis I'd say, oh yeah, what that is is just the product.\r\n\r\n200\r\n00:13:33,600 --> 00:13:49,060\r\n就是将*RAT应用于X和Y的和以及S和T的和上\r\nThat's *RAT of the sum of x and y and the sum of s and t.\r\n\r\n201\r\n00:13:51,260 --> 00:13:55,320\r\n我就得到了一个表达式 如果不考虑语法的话\r\nSo except for syntax, I get an expression\r\n\r\n202\r\n00:13:55,620 --> 00:13:59,200\r\n这个表达式看起来像是按照数学思想表达的\r\nthat looks like the way I want to think about it mathematically.\r\n\r\n203\r\n00:13:59,540 --> 00:14:03,420\r\n我说这有两个数 这个东西代表了这两个数的和\r\nI want to say there are two numbers. There's a thing which is the sum of them,\r\n\r\n204\r\n00:14:05,300 --> 00:14:07,360\r\n然而这个东西又代表了另两个数的和\r\nand there's a thing which is the sum of these two.\r\n\r\n205\r\n00:14:08,000 --> 00:14:10,440\r\n就是这个和这个\r\nThat's this and this.\r\n\r\n206\r\n00:14:10,440 --> 00:14:11,700\r\n然后我把它们乘起来\r\nAnd then I multiply them.\r\n\r\n207\r\n00:14:12,200 --> 00:14:14,200\r\n所以我有了一个和这里的表达式相匹配的表达式\r\nSo I get an expression that matches this expression.\r\n\r\n208\r\n00:14:14,200 --> 00:14:16,680\r\n而如果我用其它的方式去表达 我说\r\nIf I did the other thing, if I said, well,\r\n\r\n209\r\n00:14:16,680 --> 00:14:20,160\r\n我向机器传递四个数\r\nthe way I want to think about this is I type into my machine four numbers,\r\n\r\n210\r\n00:14:20,320 --> 00:14:22,860\r\n四个分别代表X和Y的分子、分母的数\r\nwhich are the numerators and the denominators of x and y,\r\n\r\n211\r\n00:14:23,800 --> 00:14:28,000\r\n然后又是四个分别代表S和T的分子、分母的数\r\nand then four more numbers, which are the numerators and denominators of s and t.\r\n\r\n212\r\n00:14:28,780 --> 00:14:30,780\r\n我现在又该干什么呢？\r\nAnd then what I'd be sitting with is, well, what would I do?\r\n\r\n213\r\n00:14:31,000 --> 00:14:34,560\r\n我把这些加起来 然后我们就得到了两个临时变量\r\nI'd add these, and somehow I'd have to have two temporary variables,\r\n\r\n214\r\n00:14:35,240 --> 00:14:37,440\r\n分别代表了和的分子、分母\r\nwhich are the numerators and denominators of this sum,\r\n\r\n215\r\n00:14:37,960 --> 00:14:39,600\r\n我又得去找个地方把它们存储起来\r\nand I'd go off and store them someplace.\r\n\r\n216\r\n00:14:42,140 --> 00:14:44,200\r\n然后到了这里 我又传入了四个数\r\nAnd then I'd go over here, I'd type in four more numbers,\r\n\r\n217\r\n00:14:44,200 --> 00:14:45,960\r\n我得到了两个临时变量\r\nI'd get two more temporary variables,\r\n\r\n218\r\n00:14:46,480 --> 00:14:48,720\r\n分别代表了S和T之和的分子和分母\r\nwhich are the numerators and denominators of s and t.\r\n\r\n219\r\n00:14:49,820 --> 00:14:52,860\r\n最后 我通过把它们乘起来来将其结合在一起\r\nAnd then finally, I put those together by multiplying them.\r\n\r\n220\r\n00:14:54,620 --> 00:14:56,120\r\n如你所见 麻烦出来了\r\nYou see, what's starting to happen,\r\n\r\n221\r\n00:14:56,140 --> 00:14:57,700\r\n这里满是临时变量\r\nthere are all these temporary variables,\r\n\r\n222\r\n00:14:58,180 --> 00:15:02,780\r\n这些应该是这些有理数内部的“内脏”吧\r\nwhich are sort of the guts of the internals of these rational numbers\r\n\r\n223\r\n00:15:02,780 --> 00:15:04,900\r\n但却显露在我们的系统中\r\nthat start hanging out all over the system.\r\n\r\n224\r\n00:15:05,860 --> 00:15:08,240\r\n当然 随着表达式变得越来越复杂\r\nAnd of course, if I had more and more complicated expressions,\r\n\r\n225\r\n00:15:08,240 --> 00:15:11,500\r\n这些“内脏”就会显露得越来越多 使我编程时感到困惑\r\nthere'd be more and more guts hanging out that confuse my programming.\r\n\r\n226\r\n00:15:12,620 --> 00:15:15,540\r\n像这样写程序的人\r\nAnd those of you who sort of programmed things like that,\r\n\r\n227\r\n00:15:15,540 --> 00:15:18,140\r\n你只是在用汇编语言的思想来加和两数\r\nwhere you're just adding numbers in assembly language,\r\n\r\n228\r\n00:15:18,140 --> 00:15:21,060\r\n你也发现 你突然之间需要关注这些临时变量了\r\nyou sort of see you have to suddenly be concerned with these temporary variables.\r\n\r\n229\r\n00:15:22,680 --> 00:15:29,200\r\n而这些对我大脑造成的困惑 要比对编程造成的困惑更严重\r\nBut more importantly than confusing my programming, they're going to confuse my mind.\r\n\r\n230\r\n00:15:29,620 --> 00:15:31,480\r\n而编程的本质就是\r\nBecause the whole name of this game\r\n\r\n231\r\n00:15:33,140 --> 00:15:35,420\r\n我们希望程序设计语言能够表达\r\nis that we'd like the programming language\r\n\r\n232\r\n00:15:36,820 --> 00:15:39,100\r\n我们脑中的概念\r\nto express the concepts that we have in our heads,\r\n\r\n233\r\n00:15:39,320 --> 00:15:41,780\r\n有理数就是这些概念\r\nlike rational numbers are things that you can add\r\n\r\n234\r\n00:15:42,620 --> 00:15:44,540\r\n我们可以先把它们加起来然后再乘起来\r\nand then take that result and multiply them.\r\n\r\n235\r\n00:15:48,360 --> 00:15:49,300\r\n有疑问吗？\r\nLet's break for questions.\r\n\r\n236\r\n00:15:57,380 --> 00:15:57,780\r\n恩\r\nYeah?\r\n\r\n237\r\n00:15:59,680 --> 00:16:01,480\r\n学生：我不太明白为什么\r\nAUDIENCE: Ya, I don't quite see the need-\r\n\r\n238\r\n00:16:01,480 --> 00:16:04,140\r\n我们既然有MAKE-RAT过程了\r\nwhen we had MAKE-RAT with the numerator and denominator,\r\n\r\n239\r\n00:16:04,140 --> 00:16:08,440\r\n我们传递两个参数作为分子和分母来构造一朵云彩\r\nwe had to have the numerator and denominator to pass as parameters to create the cloud,\r\n\r\n240\r\n00:16:08,440 --> 00:16:11,040\r\n但最后我们又从中将这些东西原原本本地给抽取出来\r\nand then we extracted to get back what we had to have originally.\r\n\r\n241\r\n00:16:11,360 --> 00:16:11,980\r\n教授：是这样的\r\nPROFESSOR: That's right.\r\n\r\n242\r\n00:16:13,380 --> 00:16:16,600\r\n我们的问题是 既然我们是用分子和分母构造云彩\r\nSo the question is, I sort of have the numerator and the denominator,\r\n\r\n243\r\n00:16:17,080 --> 00:16:21,720\r\n但我为什么又想从云彩里面把它们取出来呢？\r\nwhy am I worrying about having the cloud given that I have to get the pieces out?\r\n\r\n244\r\n00:16:23,280 --> 00:16:26,640\r\n这个是我在后面提到过的 不过让先说下吧\r\nThat's sort of what I tried to say at the end, but let me try and say it again,\r\n\r\n245\r\n00:16:26,640 --> 00:16:28,040\r\n这个问题非常关键\r\nbecause that's really the crucial question.\r\n\r\n246\r\n00:16:29,260 --> 00:16:32,980\r\n关键点就是 我想让分子和分母\r\nThe point is, I want to carry this numerator and denominator around\r\n\r\n247\r\n00:16:34,100 --> 00:16:35,220\r\n总是在绑一起\r\ntogether all the time.\r\n\r\n248\r\n00:16:36,840 --> 00:16:38,740\r\n我完完全全知道\r\nAnd it's almost as if I want to know,\r\n\r\n249\r\n00:16:38,740 --> 00:16:40,640\r\n这里面有分子和分母\r\nyeah, there's a numerator and denominator in there,\r\n\r\n250\r\n00:16:40,640 --> 00:16:44,940\r\n同样的 我也想表达\r\nbut also, I would like to say, fine,\r\n\r\n251\r\n00:16:45,400 --> 00:16:48,640\r\n但是 从另一个角度来看 这就是X\r\nbut from another point of view, that's x.\r\n\r\n252\r\n00:16:49,860 --> 00:16:52,460\r\n我可以取用X 我给它命名为X 我就可以控制它了\r\nAnd I carry x around, and I name it as x, and I hold it.\r\n\r\n253\r\n00:16:52,680 --> 00:16:55,160\r\n然后我就可以说 X加上Y的和\r\nAnd I can say things like, the sum of x and y,\r\n\r\n254\r\n00:16:55,800 --> 00:16:58,540\r\n我只考虑一个X的时候 使用两个数来代表分子、分母并无大碍\r\nrather than just have-- see, it's not so bad when I only think about x,\r\n\r\n255\r\n00:16:59,260 --> 00:17:01,300\r\n但是当我有10个有理数时\r\nbut if I have a system with 10 rational numbers,\r\n\r\n256\r\n00:17:01,600 --> 00:17:03,500\r\n如果我不把它们联系起来\r\nsuddenly I have 20 numerators and denominators,\r\n\r\n257\r\n00:17:03,920 --> 00:17:06,220\r\n我一下子就有了20个不必要的分子和分母\r\nwhich are not necessarily-- if I don't link them,\r\n\r\n258\r\n00:17:06,220 --> 00:17:09,900\r\n它们只是20个没有以一种特定方式联系起来的任意数而已\r\nthen it's just 20 arbitrary numbers that are not linked in any particular way.\r\n\r\n259\r\n00:17:10,080 --> 00:17:13,100\r\n这就像是说\r\nIt's a lot like saying, well,\r\n\r\n260\r\n00:17:13,100 --> 00:17:15,260\r\n我要把这些过程体的指令\r\nI have these instructions that are the body of the procedures,\r\n\r\n261\r\n00:17:15,260 --> 00:17:17,220\r\n把它们封装起来作为一个过程\r\nwhy do I want to package them and say it's the procedure?\r\n\r\n262\r\n00:17:17,620 --> 00:17:18,820\r\n这是一码子事儿\r\nIt's exactly the same idea.\r\n\r\n263\r\n00:17:30,800 --> 00:17:34,100\r\n没问题了 好吧\r\nNo more? OK.\r\n\r\n264\r\n00:17:34,560 --> 00:17:36,460\r\n那休息一下 活动一下吧 [听不清]\r\nLet's break, let's just stretch and get somebody-- [INAUDIBLE]\r\n\r\n265\r\n00:17:37,880 --> 00:17:43,240\r\n[音乐]\r\n[JESU, JOY OF MAN'S DESIRING]\r\n\r\n266\r\n00:17:45,380 --> 00:17:50,320\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n267\r\n00:17:50,580 --> 00:17:55,440\r\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\r\nBy: Prof. Harold Abelson && Gerald Jay Sussman\r\n\r\n268\r\n00:18:09,000 --> 00:18:16,680\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n269\r\n00:18:18,800 --> 00:18:22,020\r\n复合数据\r\nCompound Data\r\n\r\n270\r\n00:18:26,700 --> 00:18:30,460\r\n好吧 回到我们的有理数算术系统来\r\nOK, well, we've been working on this rational number arithmetic system,\r\n\r\n271\r\n00:18:31,700 --> 00:18:35,240\r\n而我们做的 最重要的是\r\nand then what we did, the important thing about what we did,\r\n\r\n272\r\n00:18:35,320 --> 00:18:38,300\r\n我们我们把这个问题分解为了两部分\r\nis we thought about the problem by breaking it into two pieces.\r\n\r\n273\r\n00:18:39,780 --> 00:18:42,460\r\n我们假设跟George“订好契约”\r\nWe said, assume there is this contract with George,\r\n\r\n274\r\n00:18:43,040 --> 00:18:46,320\r\nGeorge已经给出了如何去构造这些云彩\r\nand George has figured out the way to how to construct these clouds,\r\n\r\n275\r\n00:18:47,640 --> 00:18:51,260\r\n他向我们提供了一个作为构造函数的MAKE-RAT过程\r\nprovided us procedures MAKE-RAT, which was a constructor,\r\n\r\n276\r\n00:18:51,740 --> 00:18:54,600\r\n相应的 用于提取分子和分母的选择函数\r\nand selectors, which are numerator and denominator.\r\n\r\n277\r\n00:18:54,660 --> 00:18:55,460\r\n然后 我们用这些东西\r\nAnd then in terms of that,\r\n\r\n278\r\n00:18:55,460 --> 00:18:59,060\r\n我们实现了有理数的加法和乘法\r\nwe went off and implemented addition and multiplication of rational numbers.\r\n\r\n279\r\n00:19:00,220 --> 00:19:02,420\r\n好了 我们来看看George面临的问题吧\r\nWell, now let's go look at George's problem.\r\n\r\n280\r\n00:19:03,100 --> 00:19:07,200\r\n我们如何来把分子和分母给封装起来\r\nHow can we go and package together a numerator and a denominator\r\n\r\n281\r\n00:19:07,200 --> 00:19:08,540\r\n并把它们放在“云彩”里\r\nand actually make one of these clouds?\r\n\r\n282\r\n00:19:09,020 --> 00:19:11,160\r\n我们需要的是一种胶水\r\nSee, what we need is a kind of glue,\r\n\r\n283\r\n00:19:12,440 --> 00:19:16,940\r\n一种可以让我们把数据结合在一起的胶水\r\nkind of a glue that, a glue for data objects that allows us to put things together.\r\n\r\n284\r\n00:19:17,740 --> 00:19:20,460\r\n幸而Lisp提供了这样的胶水\r\nAnd Lisp provides such a glue,\r\n\r\n285\r\n00:19:21,680 --> 00:19:24,160\r\n我们把它叫作“表结构”\r\nand that glue is called list structure.\r\n\r\n286\r\n00:19:30,000 --> 00:19:33,060\r\n表结构是一种将数据粘合在一起的工具\r\nList structure is a way of gluing things together,\r\n\r\n287\r\n00:19:35,200 --> 00:19:36,080\r\n说得更准确一点\r\nand more precisely,\r\n\r\n288\r\n00:19:36,280 --> 00:19:41,260\r\n就是Lisp提供了一种构造序对的方法\r\nLisp provides a way of constructing things called pairs.\r\n\r\n289\r\n00:19:44,660 --> 00:19:50,800\r\nLisp里面有一个叫CONS的基本过程\r\nThere's a primitive operator in Lisp called CONS.\r\n\r\n290\r\n00:19:52,120 --> 00:19:53,140\r\n让我们来看一下\r\nWe can take a look at it.\r\n\r\n291\r\n00:19:54,900 --> 00:19:56,940\r\n这个就是CONS\r\nThere's a thing called CONS.\r\n\r\n292\r\n00:19:59,620 --> 00:20:04,160\r\nCONS是一个运算符 它需要两个参数X和Y\r\nCons is an operator which takes in two arguments called x and y,\r\n\r\n293\r\n00:20:06,180 --> 00:20:08,400\r\n它返回给我们一种叫作“序对”的东西\r\nand it returns for us a thing called a pair.\r\n\r\n294\r\n00:20:11,220 --> 00:20:17,760\r\n而所谓的“序对” 就是具有“首部分”和“次部分”\r\nAll right, so a thing called a pair that has a first part a second part.\r\n\r\n295\r\n00:20:21,540 --> 00:20:23,120\r\n这也解释了为什么CONS需要两个参数\r\nSo CONS takes two objects.\r\n\r\n296\r\n00:20:25,080 --> 00:20:26,140\r\n如果我们有一个序对的话\r\nThere's a thing called a pair.\r\n\r\n297\r\n00:20:26,460 --> 00:20:31,140\r\nX就是首部分 而Y就是次部分\r\nThe first part of the cons is X, and the second part of the cons is Y.\r\n\r\n298\r\n00:20:31,140 --> 00:20:32,120\r\n这就是它的构造方式\r\nAnd that's what it builds.\r\n\r\n299\r\n00:20:33,760 --> 00:20:36,220\r\n我们同样也有把东西取出来的方法\r\nAnd then we also assume we have ways of getting things out.\r\n\r\n300\r\n00:20:36,520 --> 00:20:38,880\r\n给定一个序对 我们有一个叫CAR的东西\r\nIf you're given a pair, there's a thing called CAR,\r\n\r\n301\r\n00:20:41,600 --> 00:20:45,240\r\n使得 序对P的CAR就是序对P的首部分\r\nand car of a pair, P, gives you out the first part of the pair, P.\r\n\r\n302\r\n00:20:46,320 --> 00:20:47,280\r\n也有一个叫CDR的东西\r\nAnd there's a thing called CDR,\r\n\r\n303\r\n00:20:47,780 --> 00:20:51,620\r\n使得序对P的CDR 就是序对P的次部分\r\nand CDR of the pair, P, gives you the second part of the pair, p.\r\n\r\n304\r\n00:20:54,440 --> 00:20:56,020\r\n这些就是我们构造数据的方法\r\nOK, so that's how we construct things.\r\n\r\n305\r\n00:20:56,460 --> 00:21:01,900\r\n在将这些数据用图画表示时 我们也有一种俗成的方法\r\nThere's also a conventional way of drawing pictures of these things.\r\n\r\n306\r\n00:21:02,480 --> 00:21:11,260\r\n这类似于我们用俗成的方法书写柏拉图概念下的2\r\nJust like we write down that as the conventional way of writing Plato's idea of two,\r\n\r\n307\r\n00:21:13,440 --> 00:21:20,920\r\n我们像这样画个图来表示 (CONS 2 3)\r\nthe way we could draw a diagram to represent cons of two and three is like this.\r\n\r\n308\r\n00:21:21,600 --> 00:21:22,580\r\n先画个小盒子\r\nWe draw a little box.\r\n\r\n309\r\n00:21:23,860 --> 00:21:25,600\r\n这个就是我们讨论的（序对）\r\nAnd so here's the box we're talking about,\r\n\r\n310\r\n00:21:26,300 --> 00:21:28,320\r\n盒子“放出”两个箭头\r\nand this box has two arrows coming out of it.\r\n\r\n311\r\n00:21:29,620 --> 00:21:34,560\r\n我们说 这个序对的首部分是2\r\nAnd say the first part of this pair is 2,\r\n\r\n312\r\n00:21:34,800 --> 00:21:36,520\r\n而这个序对的次部分是3\r\nand the second part of this pair is 3.\r\n\r\n313\r\n00:21:37,920 --> 00:21:44,960\r\n这种记法叫作“盒子—指针”记法\r\nAnd this notation has a name, it's called box and pointer notation.\r\n\r\n314\r\n00:21:55,220 --> 00:21:56,940\r\n顺带一提 我现在就来说说\r\nOk, By the way, let me say right now\r\n\r\n315\r\n00:21:57,140 --> 00:21:58,400\r\n困惑了很多人的一点\r\nthat a lot of people get confused\r\n\r\n316\r\n00:21:58,400 --> 00:22:03,240\r\n我画这些指针时 重要的仅仅是指针的指向\r\nthat there's some significance to the geometric way I drew these pointers, the directions.\r\n\r\n317\r\n00:22:03,240 --> 00:22:05,960\r\n一些人可能会认为 如果我这样画箭头\r\nLike some people think it'd be different if I took this pointer\r\n\r\n318\r\n00:22:05,960 --> 00:22:08,360\r\n并把3放在这里 结果会不一样\r\nand turned it up here, and put the 3 out here.\r\n\r\n319\r\n00:22:08,360 --> 00:22:10,660\r\n这实际上是没区别的 能理解吗？\r\nThat has no significance. Right?\r\n\r\n320\r\n00:22:11,200 --> 00:22:14,700\r\n只不过是在这一大堆的箭头、指针和盒子中\r\nIt's merely you have a bunch of arrows, these pointers, and the boxes.\r\n\r\n321\r\n00:22:14,700 --> 00:22:16,840\r\n唯一的区别就在于它们是如何联接的\r\nThe only issue is how they're connected,\r\n\r\n322\r\n00:22:16,840 --> 00:22:21,300\r\n而不是我把它们怎么放置 譬如向上放 向下放 或者交叉放\r\nnot the geometric arrangement of whether I write the pointer across, or up, or down.\r\n\r\n323\r\n00:22:23,220 --> 00:22:24,720\r\n关于它们为什么叫做表结构\r\nNow it's completely un-obvious,\r\n\r\n324\r\n00:22:25,720 --> 00:22:27,680\r\n或许现在就完全不清楚了\r\nprobably, why that's called list structure.\r\n\r\n325\r\n00:22:28,500 --> 00:22:31,560\r\n我们今天不会讨论这个问题 我们下次再讨论吧\r\nWe're not actually going to talk about that today. We'll see that next time.\r\n\r\n326\r\n00:22:37,620 --> 00:22:40,920\r\n所以 我们可以用CONS构造序对\r\nSo those are pairs, there's CONS that constructs them.\r\n\r\n327\r\n00:22:41,480 --> 00:22:44,920\r\n我准确地知道CONS、CAR和CDR的行为是\r\nAnd what I'm going to know about CONS, and CAR, and CDR,\r\n\r\n328\r\n00:22:45,260 --> 00:22:49,320\r\n如果我有任意的X和Y\r\nis precisely that if I have any X and Y,\r\n\r\n329\r\n00:22:50,240 --> 00:22:52,280\r\n对任意的X和Y\r\nright, if I have any things X and Y,\r\n\r\n330\r\n00:22:53,680 --> 00:22:55,980\r\n我可以用CONS来构造一个序对\r\nand I use CONS to construct a pair,\r\n\r\n331\r\n00:22:59,000 --> 00:23:03,140\r\n那么该序对的CAR就是X 就是我的构造时的一个输入\r\nthen the CAR of that pair is going to be X, the thing I put in,\r\n\r\n332\r\n00:23:03,600 --> 00:23:05,700\r\n而该序对的CDR就是Y\r\nand the CDR of that pair is going to be Y.\r\n\r\n333\r\n00:23:07,260 --> 00:23:10,660\r\n这就是CONS、CAR、CDR这些运算符的行为\r\nThat's the behavior of these operators, CONS, CAR, and CDR.\r\n\r\n334\r\n00:23:12,020 --> 00:23:15,740\r\n有了这些东西 George构造有理数就明了多了\r\nGiven them, it's pretty clear how George can go off and construct his rational numbers.\r\n\r\n335\r\n00:23:17,200 --> 00:23:18,480\r\n言归正传 George要——\r\nAfter all, all he has to do--\r\n\r\n336\r\n00:23:19,000 --> 00:23:22,720\r\n记得吗 George的任务是实现MAKE-RAT、NUMER、DENOM过程\r\nremember George's problem was to implement MAKE-RAT, numerator, and denom.\r\n\r\n337\r\n00:23:23,020 --> 00:23:36,180\r\nGeorge这样编写代码  (DEFINE (MAKE-RAT N D)\r\nSo all George has to do is say define MAKE-RAT of some N and a D--\r\n\r\n338\r\n00:23:36,640 --> 00:23:38,640\r\n就是将CONS应用于这二者\r\nWell, all I have to do is CONS them.\r\n\r\n339\r\n00:23:40,580 --> 00:23:42,520\r\n也就是(CONS N D)\r\nThat's CONS of N and D.\r\n\r\n340\r\n00:23:45,220 --> 00:23:46,900\r\n而如果我想取出分子\r\nAnd then if I want to get the numerator out,\r\n\r\n341\r\n00:23:47,440 --> 00:23:59,140\r\n代码我这样写 (DEFINE (NUMER X)\r\nI would say define the numerator, numer, of some rational number, X.\r\n\r\n342\r\n00:23:59,960 --> 00:24:02,000\r\n如果我们是用序对来实现有理数的话\r\nIf the rational number's implemented as a pair,\r\n\r\n343\r\n00:24:02,440 --> 00:24:04,320\r\n我只需要用CAR来获得X的首部分\r\nthen all I have to do is get out the CAR of X.\r\n\r\n344\r\n00:24:06,240 --> 00:24:18,860\r\n类似的 DENOM就是用CDR运算符了\r\nAnd then similarly, define the denom is going to be the cdr,\r\n\r\n345\r\n00:24:19,020 --> 00:24:21,000\r\n也就是我用于构造序对的另一个数据\r\nthe other thing I put into the pair.\r\n\r\n346\r\n00:24:26,700 --> 00:24:27,640\r\n我们现在就是在干这件事\r\nWell, now we're in business.\r\n\r\n347\r\n00:24:28,400 --> 00:24:32,860\r\n这就是有理数的一种实现\r\nThat's a complete implementation of rational numbers.\r\n\r\n348\r\n00:24:33,460 --> 00:24:34,900\r\n我们来实践一下 假设我想要\r\nLet's use it. Suppose I want to say,\r\n\r\n349\r\n00:24:35,780 --> 00:24:43,080\r\n我想要求取1/2加上1/4 并观察系统是怎么运作的\r\nso I want to think about how to add 1/2 plus 1/4 and watch the system work.\r\n\r\n350\r\n00:24:43,080 --> 00:24:50,340\r\n那么 我或许会定义一个A\r\nWell, the way I'd use that is I'd say, well, maybe define A.\r\n\r\n351\r\n00:24:50,380 --> 00:24:51,760\r\n我需要构造一个1/2\r\nI have to make a 1/2.\r\n\r\n352\r\n00:24:52,760 --> 00:24:56,780\r\n也就是一个分子为1 分母为2的有理数\r\nWell, that's a rational number with numerator 1 and denominator 2,\r\n\r\n353\r\n00:24:59,320 --> 00:25:02,540\r\n也就是 A为(MAKE-RAT 1 2)\r\nso a will be MAKE-RAT of 1 and 2.\r\n\r\n354\r\n00:25:05,280 --> 00:25:07,160\r\n然后我来构造1/4\r\nAnd then I'll construct the 1/4.\r\n\r\n355\r\n00:25:07,260 --> 00:25:20,220\r\n我定义B为(MAKE-RAT 1 4)\r\nI'll say define B to be MAKE-RAT of 1 and 4.\r\n\r\n356\r\n00:25:23,360 --> 00:25:24,860\r\n如果我想解得答案的话\r\nAnd if I'd like to look at the answer--\r\n\r\n357\r\n00:25:25,060 --> 00:25:28,100\r\n先假设我们没有一个专门用于打印有理数的东西\r\nwell, assuming I don't have a special thing that prints rational numbers,\r\n\r\n358\r\n00:25:28,100 --> 00:25:29,020\r\n我可以自己编写一个\r\nor I could make one--\r\n\r\n359\r\n00:25:29,740 --> 00:25:31,380\r\n比如说 我可以这样写\r\nI could say, for instance,\r\n\r\n360\r\n00:25:31,380 --> 00:25:43,740\r\n定义答案为(+RAT A B)\r\ndefine the answer to be +RAT of A and B,\r\n\r\n361\r\n00:25:45,980 --> 00:25:47,100\r\n那么我就可以问 答案是多少？\r\nand now I can say, what's the answer?\r\n\r\n362\r\n00:25:47,100 --> 00:25:50,120\r\n答案的分子和分母分别是多少？\r\nWhat are the numerators and denominators of the answer?\r\n\r\n363\r\n00:25:50,640 --> 00:26:00,280\r\n因此 我把1/2和1/4加起来后 我会问 答案的分子是多少？\r\nSo if I'm adding 1/2 and 1/4, I'll say, what is the numerator of the answer?\r\n\r\n364\r\n00:26:03,880 --> 00:26:10,260\r\n系统就就会打印出 6\r\nAnd the system is going to type out, well, 6.\r\n\r\n365\r\n00:26:10,560 --> 00:26:11,240\r\n糟糕了\r\nBad news.\r\n\r\n366\r\n00:26:12,860 --> 00:26:14,960\r\n而如果我问答案的分母是多少\r\nAnd if I say what's the denominator of the answer,\r\n\r\n367\r\n00:26:22,340 --> 00:26:24,480\r\n系统就就会打印出8\r\nthe system's going to type out 8.\r\n\r\n368\r\n00:26:26,100 --> 00:26:28,740\r\n我们本来希望能得到\r\nSo instead of what I would really like,\r\n\r\n369\r\n00:26:29,560 --> 00:26:32,380\r\n1/2加1/4是3/4\r\nwhich is for it to say that 1/2 and 1/4 is 3/4,\r\n\r\n370\r\n00:26:35,200 --> 00:26:38,340\r\n但这台愚蠢的机器却说 不 应该是6/8\r\nthis foolish machine is going to say, no, it's 6/8.\r\n\r\n371\r\n00:26:40,100 --> 00:26:41,480\r\n恩 这的确有点糟糕\r\nWell, that's sort of bad news.\r\n\r\n372\r\n00:26:43,040 --> 00:26:43,880\r\n问题在哪里呢？\r\nWhere's the bug?\r\n\r\n373\r\n00:26:46,940 --> 00:26:48,400\r\n是什么导致的呢？\r\nWhy does it do that, after all?\r\n\r\n374\r\n00:26:48,400 --> 00:26:51,040\r\n问题出在+RAT上\r\nWell, it's the way that we just had +RAT.\r\n\r\n375\r\n00:26:51,040 --> 00:26:56,620\r\n+RAT只是把A的分子和B分母之积与\r\n+RAT just took the-- it said you add the numerator times the denominator,\r\n\r\n376\r\n00:26:57,860 --> 00:27:00,100\r\nB的分子和A的分母之积加在一起\r\nyou add that to the numerator times the denominator,\r\n\r\n377\r\n00:27:00,440 --> 00:27:02,420\r\n并把它们除以两分母之积\r\nand put that over the product of the two denominators,\r\n\r\n378\r\n00:27:02,420 --> 00:27:03,580\r\n这就是为什么得到6/8的原因\r\nand that's why you get 6/8.\r\n\r\n379\r\n00:27:05,560 --> 00:27:09,680\r\n那么 我们的+RAT实现有什么问题呢？\r\nSo what was wrong with our implementation of +RAT?\r\n\r\n380\r\n00:27:10,260 --> 00:27:13,720\r\n我们在此之前所做的有理数算术又有什么错误呢？\r\nWhat's wrong with that rational number arithmetic stuff that we did before the break?\r\n\r\n381\r\n00:27:15,500 --> 00:27:17,940\r\n当然 从一方面来看 这一点都没有错\r\nWell, the answer is one way to look at it is absolutely nothing's wrong.\r\n\r\n382\r\n00:27:19,360 --> 00:27:21,120\r\n这其实是一个相当好的实现\r\nThat's perfectly good implementation.\r\n\r\n383\r\n00:27:21,120 --> 00:27:26,900\r\n这个实现完完全全遵守了分数加法法则\r\nIt follows the sixth grade, fifth grade mathematic for adding fractions.\r\n\r\n384\r\n00:27:29,620 --> 00:27:31,820\r\n我们可以这样说 这就是George的问题了\r\nOne thing we can say is, well, that's George's problem.\r\n\r\n385\r\n00:27:32,980 --> 00:27:37,560\r\n如果George只是简单地通过把分子和分母放在一起\r\nLike, boy, wasn't George dumb to say that he can make a rational number\r\n\r\n386\r\n00:27:37,800 --> 00:27:40,780\r\n来构造有理数的话 岂不是站不住脚？\r\nsimply by sticking together the numerator and the denominator?\r\n\r\n387\r\n00:27:42,480 --> 00:27:46,460\r\n在构造有理数时 如果George把这些东西化到最简\r\nWouldn't it be better for George, when he made a rational number,\r\n\r\n388\r\n00:27:47,640 --> 00:27:49,240\r\n难道不是会跟好一点吗？\r\nto reduce the stuff to lowest terms?\r\n\r\n389\r\n00:27:51,080 --> 00:27:55,540\r\n我想说的是 对George来说\r\nAnd what I mean is, wouldn't it be better for George,\r\n\r\n390\r\n00:27:55,540 --> 00:28:01,800\r\n用这个版本的MAKE-RAT 难道会比幻灯片上的这个好么？\r\ninstead of using this version of MAKE-RAT, to use this one on the slide?\r\n\r\n391\r\n00:28:03,160 --> 00:28:06,660\r\n不是简单地通过CONS 把N和D结合起来\r\nOr instead of just saying CONS together N and D,\r\n\r\n392\r\n00:28:07,240 --> 00:28:11,680\r\n我们先寻找N和D的最大公约数\r\nwhat you do is compute the greatest common divisor of N and D,\r\n\r\n393\r\n00:28:12,420 --> 00:28:14,000\r\n我们用GCD过程来找\r\nand GCD is the procedure which,\r\n\r\n394\r\n00:28:14,700 --> 00:28:16,040\r\n我们只需知道GCD是一个基本过程\r\nwell, for all we care is a primitive,\r\n\r\n395\r\n00:28:16,040 --> 00:28:18,520\r\n它返回的是两个数的最大公约数\r\nwhich computes the greatest common divisor of two numbers.\r\n\r\n396\r\n00:28:20,700 --> 00:28:22,900\r\n因此 这种构造有理数的方法就是\r\nSo the way I can construct a rational number is\r\n\r\n397\r\n00:28:24,160 --> 00:28:26,520\r\n先找到两数的最大公约数\r\nget the greatest common divisor of the two numbers,\r\n\r\n398\r\n00:28:26,520 --> 00:28:27,580\r\n先用G来表示吧\r\nand I'm going to call that G,\r\n\r\n399\r\n00:28:29,920 --> 00:28:33,720\r\n不是简单通过CONS结合N、D 而是先让它们除以G\r\nand then instead of consing together N and D, I'll divide them through.\r\n\r\n400\r\n00:28:33,720 --> 00:28:38,940\r\n然后我再用CONS结合N/G和D/G的商\r\nI'll CONS together the quotient of N by the the GCD and the quotient of D by the GCD.\r\n\r\n401\r\n00:28:40,400 --> 00:28:42,600\r\n这样就把我们的有理数化到了最简\r\nAnd that will reduce the rational number to lowest terms.\r\n\r\n402\r\n00:28:43,740 --> 00:28:53,600\r\n因此 当我在做加法时 当+RAT调用MAKE-RAT过程时\r\nSo that when, when I do this addition, when +RAT calls MAKE-RAT--\r\n\r\n403\r\n00:28:53,980 --> 00:28:56,320\r\n+RAT的定义里面有对MAKE-RAT的调用\r\nand for the definition of +RAT it had a MAKE-RAT in there--\r\n\r\n404\r\n00:28:57,400 --> 00:28:59,240\r\n因此 当+RAT构造有理数时\r\njust by the fact that it's constructing that,\r\n\r\n405\r\n00:28:59,240 --> 00:29:01,440\r\nMAKE-RAT就自动将其化为最简了\r\nthe thing will get reduced to lowest terms automatically.\r\n\r\n406\r\n00:29:08,780 --> 00:29:13,460\r\n好了 这就是一个完整的系统\r\nOK, that is a complete system.\r\n\r\n407\r\n00:29:14,640 --> 00:29:16,900\r\n让我们来看看我们完成的这个有理数算术系统吧\r\nFor rational number arithmetic, let's look at what we've done.\r\n\r\n408\r\n00:29:19,240 --> 00:29:22,480\r\n好吧 我们说过我们想要构造一个有理数算术系统\r\nAll right, we said we want to build rational number arithmetic,\r\n\r\n409\r\n00:29:25,220 --> 00:29:27,920\r\n我们实现了+RAT\r\nand we had a thing called +RAT. We implemented that.\r\n\r\n410\r\n00:29:29,620 --> 00:29:33,200\r\n我也给你们展示了*RAT的实现\r\nAnd I showed you multiplying rational numbers, and\r\n\r\n411\r\n00:29:34,100 --> 00:29:35,200\r\n虽然我并没有去实现-RAT\r\nalthough I didn't put them up there,\r\n\r\n412\r\n00:29:35,200 --> 00:29:38,280\r\n就姑且假设我们实现了-RAT吧\r\npresumably we'd like to have something that subtracts rational numbers,\r\n\r\n413\r\n00:29:38,960 --> 00:29:40,500\r\n事实上有些东西我并不知道\r\nand I don't know, all sorts of things.\r\n\r\n414\r\n00:29:40,500 --> 00:29:42,220\r\n比如通过除法来判断相等\r\nThings that test equality in division,\r\n\r\n415\r\n00:29:42,220 --> 00:29:45,140\r\n或者用某种特定方式打印有理数的函数\r\nand maybe things that print rational numbers in some particular way.\r\n\r\n416\r\n00:29:45,820 --> 00:29:49,960\r\n我们用序对的方式实现了它们\r\nAnd we implemented those in terms of pairs.\r\n\r\n417\r\n00:29:52,440 --> 00:29:54,600\r\n序对、CONS、CAR和CDR 这些都是内建于Lisp中的\r\nThese pairs, CONS, CAR, and CDR that are built into Lisp.\r\n\r\n418\r\n00:29:55,560 --> 00:30:03,840\r\n而两者之间最重要的则是 这个和这个\r\nBut the important thing is that between these and these,\r\n\r\n419\r\n00:30:04,680 --> 00:30:09,240\r\n我们在其间构筑了一道抽象屏障 一个抽象层\r\nwe set up an abstraction barrier. We set up a layer of abstraction.\r\n\r\n420\r\n00:30:16,960 --> 00:30:18,640\r\n那么 “抽象层”又是什么呢？\r\nAnd what was that layer of abstraction?\r\n\r\n421\r\n00:30:18,640 --> 00:30:22,340\r\n准确的说 构造函数和选择函数就是抽象层\r\nThat layer of abstraction was precisely the constructor and the selectors.\r\n\r\n422\r\n00:30:25,420 --> 00:30:34,360\r\nMAKE-RAT、NUMER、DENOM就是抽象层\r\nThis layer was MAKE-RAT, and NUMER, and DENOM.\r\n\r\n423\r\n00:30:38,620 --> 00:30:42,920\r\n这种方法学 也就是我们的做法\r\nThis methodology, another way to say what it's doing,\r\n\r\n424\r\n00:30:43,120 --> 00:30:51,000\r\n就是“分离” 分离对象的使用方法\r\nis that we are separating, we are separating the way something is used,\r\n\r\n425\r\n00:30:53,240 --> 00:30:55,000\r\n我们把数据对象的使用\r\nseparating the use of data objects,\r\n\r\n426\r\n00:30:56,140 --> 00:30:59,040\r\n和它们的表示分离开来\r\nfrom the representation of data objects.\r\n\r\n427\r\n00:31:07,060 --> 00:31:12,040\r\n就目前来说 我们有了使用有理数做计算的方法\r\nSo up here, we have the way that rational numbers are used, do arithmetic on them.\r\n\r\n428\r\n00:31:12,220 --> 00:31:14,760\r\n在这儿 我们有它们表示的方法\r\nDown here, we have the way that they're represented,\r\n\r\n429\r\n00:31:14,760 --> 00:31:16,300\r\n它们通过这条边界分隔开\r\nand they're separated by this boundary.\r\n\r\n430\r\n00:31:17,480 --> 00:31:19,500\r\n这条边界就是构造函数和选择函数\r\nThe boundary is the constructors and selectors.\r\n\r\n431\r\n00:31:23,440 --> 00:31:25,420\r\n这种方法学有个名字\r\nAnd this methodology has a name.\r\n\r\n432\r\n00:31:25,420 --> 00:31:26,960\r\n叫做数据抽象\r\nThis is called data abstraction.\r\n\r\n433\r\n00:31:35,880 --> 00:31:39,760\r\n数据抽象是一种通过假定的构造函数和选择函数将数据对象\r\nData abstraction is sort of the programming methodology of setting up data objects\r\n\r\n434\r\n00:31:39,760 --> 00:31:44,080\r\n与它的表示分隔开来的编程方法学\r\nby postulating constructors and selectors to isolate use from representation.\r\n\r\n435\r\n00:31:47,140 --> 00:31:50,420\r\n我们也完全可以不这样做 这又有什么干系呢？\r\nWell, so what? I mean, after all, we didn't have to do it this way.\r\n\r\n436\r\n00:31:51,580 --> 00:31:55,000\r\n当然就算不用任何复合对象\r\nIt's perfectly possible to do rational number addition\r\n\r\n437\r\n00:31:55,000 --> 00:31:56,800\r\n做有理数加法也是完全可行的\r\nwithout having any compound data objects,\r\n\r\n438\r\n00:31:56,800 --> 00:31:59,560\r\n幻灯片上就是一个例子\r\nand here on the slide is one example.\r\n\r\n439\r\n00:31:59,560 --> 00:32:02,620\r\n我们当然可以这样定义+RAT\r\nWe certainly could have defined +RAT,\r\n\r\n440\r\n00:32:02,820 --> 00:32:05,920\r\n它需要两个参数X和Y\r\nwhich takes in things x and y,\r\n\r\n441\r\n00:32:05,920 --> 00:32:08,940\r\n而我们会问 这些有理数到底是什么呢？\r\nand we'll say, well what are these rational numbers really?\r\n\r\n442\r\n00:32:09,380 --> 00:32:11,160\r\n实质上 它们只是序对\r\nSo really, they're just pairs,\r\n\r\n443\r\n00:32:11,680 --> 00:32:13,960\r\n分子是序对的CAR部分 分母是CDR部分\r\nand the numerator's the car and the denominator's the cdr.\r\n\r\n444\r\n00:32:14,180 --> 00:32:18,800\r\n我们要做的 就是取出X的CAR部分乘以Y的CDR部分\r\nSo what we'll do is we'll take the car of x times the cdr of y,\r\n\r\n445\r\n00:32:21,920 --> 00:32:22,760\r\n并把它们乘起来\r\nmultiply them.\r\n\r\n446\r\n00:32:23,020 --> 00:32:26,600\r\n取出Y的CAR部分和CDR部分相乘 再与之前的结果相加\r\nTake the car of y times the cdr of x, multiply them.Add them.\r\n\r\n447\r\n00:32:28,340 --> 00:32:31,080\r\n取出X的CDR部分乘以Y的CDR部分\r\nTake the cdr of x and the cdr of y, multiply them,\r\n\r\n448\r\n00:32:31,300 --> 00:32:32,540\r\n并把最终结果构造起来\r\nand then constitute together.\r\n\r\n449\r\n00:32:33,900 --> 00:32:36,700\r\n这其实是一样的\r\nWell, that sort of does the same thing.\r\n\r\n450\r\n00:32:41,080 --> 00:32:44,000\r\n但这种方法忽略了把对象归约到最低阶项的问题\r\nBut this ignores the problem of reducing things to lowest terms,\r\n\r\n451\r\n00:32:44,000 --> 00:32:46,620\r\n让我们花点时间 仔细思考一下\r\nbut let's not worry about that for a minute.\r\n\r\n452\r\n00:32:47,400 --> 00:32:48,920\r\n我们为什么不这样做呢？\r\nBut so what? Why don't we do it that way?\r\n\r\n453\r\n00:32:50,420 --> 00:32:52,920\r\n对吧 毕竟这样看起来会少定义很多过程\r\nRight? After all, there are sort of fewer procedures to define,\r\n\r\n454\r\n00:32:52,920 --> 00:32:54,360\r\n并且更加直白\r\nand it's a lot more straightforward.\r\n\r\n455\r\n00:32:55,080 --> 00:33:00,600\r\n它省去了很多我们关于“数据抽象”的“自以为是”的方法\r\nAh It saves all this self-righteous BS about talking about data abstraction.\r\n\r\n456\r\n00:33:00,600 --> 00:33:01,660\r\n而我们就不是这样做的\r\nWe just sort of do it.\r\n\r\n457\r\n00:33:01,900 --> 00:33:04,660\r\n我的意思是这样或许会稍微高效一点\r\nI mean, who knows, maybe it's even marginally more efficient\r\n\r\n458\r\n00:33:04,660 --> 00:33:06,900\r\n如果我们用的编译器对此有优化的话\r\ndepending on whatever compiler were using for this.\r\n\r\n459\r\n00:33:07,460 --> 00:33:11,920\r\n而将数据的使用与表示分离开来的意图是什么呢？\r\nWhat's the point of isolating the use from the representation?\r\n\r\n460\r\n00:33:13,660 --> 00:33:16,840\r\n这就将回到命名的记号了\r\nWell, it goes back to this notion of naming.\r\n\r\n461\r\n00:33:16,840 --> 00:33:21,180\r\n还记得吗 编程中最重要的原理\r\nRemember, one of the most important principles in programming\r\n\r\n462\r\n00:33:21,180 --> 00:33:25,180\r\n和魔法中最重要的原理是一样的 对吧？\r\nis the same as one of the most important principles in sorcery, all right?\r\n\r\n463\r\n00:33:25,180 --> 00:33:28,600\r\n如果你知道某个精灵的名字 你就可以控制它\r\nThat's if you have the name of the spirit, you get control over it.\r\n\r\n464\r\n00:33:30,000 --> 00:33:31,860\r\n如果你回过头来看幻灯片\r\nAnd if you go back and look at the slide,\r\n\r\n465\r\n00:33:33,380 --> 00:33:35,680\r\n你会发现这里我们就有一个+RAT\r\nyou see what's in there is we have this thing +RAT,\r\n\r\n466\r\n00:33:36,580 --> 00:33:40,900\r\n如果我们有+RAT -RAT *RAT 或者和这些类似的过程\r\nbut nowhere in the system, if I have a +RAT and a -RAT and a *RAT,\r\n\r\n467\r\n00:33:40,900 --> 00:33:42,060\r\n但在这个系统的任何地方\r\nand things that look like that,\r\n\r\n468\r\n00:33:42,060 --> 00:33:50,460\r\n我无法找出任何一个有理数\r\nnowhere in the system do I have a thing that I can point at which is a rational number.\r\n\r\n469\r\n00:33:53,240 --> 00:33:55,900\r\n在像这样的一个系统中 我并没有\r\nI don't have, in a system like that,\r\n\r\n470\r\n00:33:56,800 --> 00:33:59,720\r\n没有一个有理数的概念实体\r\nthe idea of rational number as a conceptual entity.\r\n\r\n471\r\n00:34:01,480 --> 00:34:02,960\r\n那么 这样做的优势是什么呢？\r\nWell, what's the advantage of that?\r\n\r\n472\r\n00:34:03,920 --> 00:34:08,000\r\n把有理数的概念和实体分离开来\r\nWhat's the advantage of isolating the idea of rational numbers as a conceptual entity,\r\n\r\n473\r\n00:34:08,000 --> 00:34:11,420\r\n然后用MAKE-RAT、NUMER、DENOM来控制它们有什么优势么？\r\nand really naming it with make-RAT, numerator, and denominator.\r\n\r\n474\r\n00:34:13,000 --> 00:34:19,180\r\n优势之一就是你可以使用其它的方法表示（数据）\r\nWell, one advantage is you might want to have alternative representations.\r\n\r\n475\r\n00:34:20,420 --> 00:34:23,320\r\n之前我不是给你们看过\r\nSee, before I showed you that one way George can solve this\r\n\r\n476\r\n00:34:24,080 --> 00:34:26,560\r\nGeorge解决分数化简的方法么？\r\nthings not reduced to lowest terms problem,\r\n\r\n477\r\n00:34:26,560 --> 00:34:28,180\r\n当他在构建有理数时\r\nis when you build a rational number,\r\n\r\n478\r\n00:34:28,780 --> 00:34:30,780\r\n将分子分母同时除以最大公约数\r\nyou divide up by the greatest common denominator.\r\n\r\n479\r\n00:34:30,780 --> 00:34:35,960\r\n另一种解决办法在这里\r\nAnother way to do that is shown over here.\r\n\r\n480\r\n00:34:36,300 --> 00:34:38,840\r\n我可以用另一种方法表示有理数\r\nI can have an alternative representation for rational numbers\r\n\r\n481\r\n00:34:39,020 --> 00:34:41,560\r\n也就是直接使用CONS来构建有理数\r\nwhere when you make a rational number, you just cons them.\r\n\r\n482\r\n00:34:43,120 --> 00:34:45,420\r\n而当你在析取去分子时\r\nHowever, when you go to select out the numerator,\r\n\r\n483\r\n00:34:45,720 --> 00:34:51,260\r\n在那个时候再计算分子分母的最大公约数\r\nat that point you compute the gcd of the stuff that's sitting in that pair,\r\n\r\n484\r\n00:34:52,000 --> 00:34:53,580\r\n然后再用分子除以这个最大公约数\r\nand divide out by the gcd.\r\n\r\n485\r\n00:34:57,480 --> 00:34:59,400\r\n类似地 当我析取分母时\r\nAnd similarly, when I get the denominator,\r\n\r\n486\r\n00:35:00,740 --> 00:35:04,760\r\n当我在析取出分母时 我将它除以最大公约数\r\nat that point when I go to get the denominator, I'll divide out by the gcd.\r\n\r\n487\r\n00:35:05,260 --> 00:35:07,360\r\n所以在旧的表示法中\r\nSo the difference would be in the old representation,\r\n\r\n488\r\n00:35:08,540 --> 00:35:10,200\r\n当ANS在这里被构造时\r\nwhen ans was constructed here,\r\n\r\n489\r\n00:35:11,080 --> 00:35:13,680\r\n在第一种方法中 也就是6和8\r\nsay what's 6 and 8, in the first way,\r\n\r\n490\r\n00:35:14,100 --> 00:35:16,940\r\n在6和8被装入表中时 它们已经被化到最简\r\nthe 6 and 8 would have got reduced when they got stuck into that pair,\r\n\r\n491\r\n00:35:16,940 --> 00:35:18,480\r\n析取分子会得到3\r\nnumerator would select out 3.\r\n\r\n492\r\n00:35:20,040 --> 00:35:21,440\r\n而在我给你们展示的方法中\r\nAnd in the way I just showed you, well,\r\n\r\n493\r\n00:35:21,800 --> 00:35:24,300\r\n我们放入的是6和8\r\nans would get 6 and 8 put in,\r\n\r\n494\r\n00:35:24,780 --> 00:35:26,880\r\n然后在我析取分子时会进行一些计算\r\nand then at the point where I said numerator,\r\n\r\n495\r\n00:35:27,320 --> 00:35:30,360\r\n使得我得到3而非6\r\nsome computation would get done to put out 3 instead of 6.\r\n\r\n496\r\n00:35:32,280 --> 00:35:33,920\r\n这就是我可以使用的两种不同方法\r\nSo those are two different ways I might do it.\r\n\r\n497\r\n00:35:33,920 --> 00:35:34,880\r\n哪种更好呢？\r\nWhich one's better?\r\n\r\n498\r\n00:35:37,200 --> 00:35:38,320\r\n这得看情况 对吧？\r\nWell, it depends, right?\r\n\r\n499\r\n00:35:38,320 --> 00:35:41,640\r\n如果我的系统中我经常构造有理数\r\nIf I'm making a system where I am mostly constructing rational numbers\r\n\r\n500\r\n00:35:41,640 --> 00:35:42,780\r\n而不常去析取它们\r\nand hardly ever looking at them,\r\n\r\n501\r\n00:35:42,780 --> 00:35:46,660\r\n那么在构造它们时就最好不要化简\r\nthen it's probably better not to do that gcd computation when I construct them.\r\n\r\n502\r\n00:35:47,840 --> 00:35:51,500\r\n如果在我的系统中 比起构造 我更经常去析取它们\r\nIf I'm doing a system where I look at things a lot more than I construct them,\r\n\r\n503\r\n00:35:51,720 --> 00:35:54,840\r\n那在构造时就将它们化简就一劳永逸了\r\nthen it's probably better to do the work when I construct them.\r\n\r\n504\r\n00:35:56,940 --> 00:35:58,020\r\n这得视情况做出选择\r\nSo there's a choice there.\r\n\r\n505\r\n00:35:58,020 --> 00:36:02,320\r\n但真正的问题是 在你实现这些有理数时\r\nBut the real issue is that you might not be able to decide\r\n\r\n506\r\n00:36:04,220 --> 00:36:06,440\r\n没法决定要用哪种表示法\r\nat the moment you're worrying about these rational numbers.\r\n\r\n507\r\n00:36:07,320 --> 00:36:10,220\r\n通常来说 作为一名系统设计师\r\nSee, in general, as systems designers,\r\n\r\n508\r\n00:36:13,040 --> 00:36:16,740\r\n你被强迫去做出 关于如何解决问题的决定\r\nyou're forced with the necessity to make decisions about how you're going to do things,\r\n\r\n509\r\n00:36:17,680 --> 00:36:20,340\r\n通常来说 你用于保持系统弹性的方法\r\nand in general, the way you'd like to retain flexibility\r\n\r\n510\r\n00:36:20,500 --> 00:36:24,720\r\n就是在你被迫做出决定前不要做任何事\r\nis to never make up your mind about anything until you're forced to do it.\r\n\r\n511\r\n00:36:26,560 --> 00:36:31,500\r\n但问题是 在推迟决定和彻底推延之间\r\nThe problem is, there's a very, very narrow line between\r\n\r\n512\r\n00:36:31,500 --> 00:36:34,960\r\n并没有太明显的界限\r\ndeferring decisions and outright procrastination.\r\n\r\n513\r\n00:36:38,500 --> 00:36:43,720\r\n你想要继续前进 但与此同时\r\nSo you'd like to make progress, but also at the same time,\r\n\r\n514\r\n00:36:43,720 --> 00:36:46,080\r\n你也希望不要被你决定的结果给限制住\r\nnever be bound by the consequences of your decisions.\r\n\r\n515\r\n00:36:48,280 --> 00:36:50,060\r\n数据抽象就是解决方法之一\r\nData abstraction's one way of doing this.\r\n\r\n516\r\n00:36:50,160 --> 00:36:52,080\r\n我的做的就是“按愿望思维”\r\nWhat we did is we used wishful thinking.\r\n\r\n517\r\n00:36:54,100 --> 00:36:55,800\r\n我们给结果命了个名字\r\nSee, we gave a name to the decision.\r\n\r\n518\r\n00:36:56,800 --> 00:37:02,040\r\n我们让MAKE-RAT、NUMER、DENOM代表它们运作的结果\r\nWe said, make-RAT, numerator, and denominator will stand for however it's going to be done,\r\n\r\n519\r\n00:37:02,040 --> 00:37:03,740\r\n但它们如何运作则是George的事\r\nand however it's going to be done is George's problem.\r\n\r\n520\r\n00:37:03,740 --> 00:37:08,000\r\n实际上 我们只是用几个名字代表我们期望运作的结果\r\nBut really, what that was doing is giving a name to the decision of how we're going to do it,\r\n\r\n521\r\n00:37:09,980 --> 00:37:12,700\r\n然后继续编程 就像我们的确得到了结果\r\nand then continuing as if we made the decision.\r\n\r\n522\r\n00:37:13,700 --> 00:37:16,820\r\n到了最后 我们确实必须计算它时\r\nAnd then eventually, when we really wanted it to work,\r\n\r\n523\r\n00:37:16,820 --> 00:37:18,820\r\n再回过头来完成必要的计算\r\ncoming back and facing what we really had to do.\r\n\r\n524\r\n00:37:20,320 --> 00:37:22,120\r\n事实上从现在起 我们将会三番五次地看到\r\nAnd in fact, we'll see a couple times from now\r\n\r\n525\r\n00:37:22,480 --> 00:37:25,640\r\n我们不会非得选定一个特定的表示方式 从来都不会\r\nthat you may never have to choose any particular representation, ever, ever.\r\n\r\n526\r\n00:37:27,420 --> 00:37:29,600\r\n不管如何 这都是一种非常有用的设计技术\r\nAnyway, that's a very powerful design technique.\r\n\r\n527\r\n00:37:30,380 --> 00:37:32,240\r\n这也是人们使用数据抽象的原因\r\nIt's the key to the reason people use data abstraction.\r\n\r\n528\r\n00:37:34,560 --> 00:37:36,660\r\n我们会不断的看到这个理念\r\nAnd we're going to see that idea again and again.\r\n\r\n529\r\n00:37:38,480 --> 00:37:39,680\r\n有什么问题吗？\r\nLet's stop for questions.\r\n\r\n530\r\n00:37:40,180 --> 00:37:44,360\r\n学生：通过抽象层做出决定与\r\nAUDIENCE: What does this decision making through abstraction layers\r\n\r\n531\r\n00:37:44,820 --> 00:37:48,040\r\n编码前做完成设计的信条相比 哪个更好呢？\r\ndo to the axiom of do all your design before any of your code?\r\n\r\n532\r\n00:37:49,420 --> 00:37:51,840\r\n教授：这只是少数人的信条\r\nPROFESSOR: Well, that's someone's axiom,\r\n\r\n533\r\n00:37:51,840 --> 00:37:56,080\r\n我打赌这是那些不经常实现大型计算机系统的家伙的信条\r\nand I bet that's the axiom of someone who hasn't implemented very large computer systems very much.\r\n\r\n534\r\n00:38:00,880 --> 00:38:02,800\r\n我曾说过计算机科学非常像魔法\r\nI said that computer science is a lot like magic,\r\n\r\n535\r\n00:38:03,560 --> 00:38:05,020\r\n像魔法这一点非常好\r\nand it's sort of good that it's like magic.\r\n\r\n536\r\n00:38:05,020 --> 00:38:07,580\r\n但是计算机科学也非常像宗教 这就不好了\r\nThere's a bad part of computer science that's a lot like religion.\r\n\r\n537\r\n00:38:08,220 --> 00:38:15,120\r\n通常来说 我认为那些相信在编码前就能把系统设计完美\r\nAnd in general, I think people who really believe that you design everything before you implement it\r\n\r\n538\r\n00:38:15,920 --> 00:38:18,140\r\n大多都是一些没有设计过大规模系统的人\r\nbasically are people who haven't designed very many things.\r\n\r\n539\r\n00:38:20,980 --> 00:38:24,700\r\n我们的方法 厉害之处就在于可以假设我们已经得到结果了\r\nThe real power is that you can pretend that you've made the decision\r\n\r\n540\r\n00:38:25,700 --> 00:38:27,920\r\n然后再讨论到底是哪个是对的\r\nand then later on figure out which one is right,\r\n\r\n541\r\n00:38:28,260 --> 00:38:29,800\r\n或者你应该得到怎样的结果\r\nwhich decision you ought to have made.\r\n\r\n542\r\n00:38:30,460 --> 00:38:32,480\r\n当你学会这招了 你会发现这个是最棒的一招\r\nAnd when you can do that, you have the best of both worlds.\r\n\r\n543\r\n00:38:35,660 --> 00:38:39,140\r\n学生：您能解释一下LET和DEFINE的区别吗？\r\nAUDIENCE: Can you explain the difference between let and define?\r\n\r\n544\r\n00:38:39,860 --> 00:38:41,060\r\n教授：好的\r\nPROFESSOR: Oh, OK.\r\n\r\n545\r\n00:38:41,540 --> 00:38:48,900\r\nLET是用来建立一个局部的名字\r\nLet is a way to establish local names.\r\n\r\n546\r\n00:38:53,100 --> 00:38:56,760\r\n嗯 我就先大概给你说下\r\nSo there... Let me give you sort of the half answer.\r\n\r\n547\r\n00:38:57,200 --> 00:39:01,640\r\n然后我们再来讨论这整个复杂的过程\r\nAnd I'll say, later on we can talk about the whole very complicated thing.\r\n\r\n548\r\n00:39:02,620 --> 00:39:06,540\r\n就现在来说 区别就在于 当你在Lisp中编程时\r\nBut the big difference for now is that, see, when you're typing at Lisp,\r\n\r\n549\r\n00:39:07,600 --> 00:39:10,920\r\n编写定义是与所在环境有关的\r\nyou're typing in this environment where you're making definitions.\r\n\r\n550\r\n00:39:11,720 --> 00:39:19,100\r\n当你想把A定义为5时 我写(DEFINE A 5)\r\nAnd when you say define a to be 5, if I say define a to be 5,\r\n\r\n551\r\n00:39:20,420 --> 00:39:22,760\r\n从此以后我们就会记得A就是5\r\nthen from then on the thing will remember that a is 5.\r\n\r\n552\r\n00:39:25,280 --> 00:39:29,840\r\nLET会建立一个包含一个定义的局部上下文\r\nLet is a way to set up a local context where there's a definition.\r\n\r\n553\r\n00:39:30,800 --> 00:39:36,640\r\n所以当我键入 比如(LET ((A\r\nSo if I type something like, saying let a--\r\n\r\n554\r\n00:39:36,640 --> 00:39:44,880\r\n或者我写(LET ((Z 10)))\r\nno, I shouldn't say a-- if I said let z be 10,\r\n\r\n555\r\n00:39:48,020 --> 00:39:53,660\r\n然后在这个上下文中 我们计算Z加上Z的和\r\nand within that context, tell me what the sum of z and z is.\r\n\r\n556\r\n00:39:54,000 --> 00:39:56,260\r\n如果我在Lisp中这样写的话\r\nSo if I typed in this expression to Lisp,\r\n\r\n557\r\n00:39:58,220 --> 00:40:00,840\r\nLisp会输出20\r\nand then this would put out 20.\r\n\r\n558\r\n00:40:01,960 --> 00:40:05,460\r\n然而 如果我再问Z是什么\r\nHowever, then if I said what's z,\r\n\r\n559\r\n00:40:06,140 --> 00:40:09,140\r\n计算机会告诉我Z是一个未绑定的变量\r\nthe computer would say that's an unbound variable.\r\n\r\n560\r\n00:40:10,600 --> 00:40:14,040\r\n因此LET可以创建一个上下文 你可以在这个上下文中进行定义\r\nSo let is a way of setting up a context where you can make definitions.\r\n\r\n561\r\n00:40:15,840 --> 00:40:18,420\r\n但是这些都是这个上下文中的局部定义\r\nBut those definitions are local to this context.\r\n\r\n562\r\n00:40:19,100 --> 00:40:27,720\r\n当然啦 我把这个改为A的话 我依旧会得到20\r\nAnd of course, if I'd said a in here, I'd still get 20.\r\n\r\n563\r\n00:40:27,720 --> 00:40:31,520\r\n但是这个A与这个A一点也不冲突\r\nBut this a would not interfere at all with this one.\r\n\r\n564\r\n00:40:33,640 --> 00:40:36,040\r\n所以我键入这个 再键入这个 再问A是什么\r\nSo if I type this, and then type this, and then say what's a?\r\n\r\n565\r\n00:40:36,040 --> 00:40:36,940\r\nA还会是5\r\na will still be 5.\r\n\r\n566\r\n00:40:39,020 --> 00:40:42,120\r\n因此在LET和DEFINE之间有这另一种代换模型\r\nSo there's some other subtle differences between let and define,\r\n\r\n567\r\n00:40:42,120 --> 00:40:44,120\r\n但这（LET的有效域是局部的）才是最重要的\r\nbut that's the most important one.\r\n\r\n568\r\n00:40:44,120 --> 00:40:50,700\r\n[音乐]\r\n[JESU, JOY OF MAN'S DESIRING]\r\n\r\n569\r\n00:41:03,760 --> 00:41:07,420\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n570\r\n00:41:07,580 --> 00:41:10,980\r\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\r\nBy: Prof. Harold Abelson && Gerald Jay Sussman\r\n\r\n571\r\n00:41:11,460 --> 00:41:14,440\r\n复合数据\r\nCompound Data\r\n\r\n572\r\n00:41:19,780 --> 00:41:23,220\r\n好了 我们已经看过作为数据抽象技术的示例\r\nAll right, well, we've looked at implementing this little system\r\n\r\n573\r\n00:41:23,500 --> 00:41:29,100\r\n在有理数域上做算术的小型系统的实现\r\nfor doing arithmetic on rational numbers as an example of this methodology of data abstraction.\r\n\r\n574\r\n00:41:30,880 --> 00:41:35,000\r\n这就是一种在大型系统中控制复杂度的方法\r\nAnd that's a way of controlling complexity in large systems.\r\n\r\n575\r\n00:41:36,560 --> 00:41:38,660\r\n就像定义过程\r\nBut, see, like procedure definition,\r\n\r\n576\r\n00:41:38,820 --> 00:41:41,680\r\n以及我们谈论的所有的控制复杂度的方法\r\nand like all the ways we're going to talk about for controlling complexity,\r\n\r\n577\r\n00:41:41,980 --> 00:41:47,100\r\n这些东西的真正厉害之处不是体现在实现它们本身\r\nthe real power of these things show up not when you sort of do these things in themselves,\r\n\r\n578\r\n00:41:47,780 --> 00:41:51,220\r\n我们构建的有理数运算系统并不是什么了不起的事\r\nlike it's not such a great thing that we've done rational number arithmetic,\r\n\r\n579\r\n00:41:52,140 --> 00:41:57,860\r\n而是你可以将这些东西用于构建更复杂的东西\r\nit's that you can use these as building blocks for making more complicated things.\r\n\r\n580\r\n00:42:00,340 --> 00:42:04,020\r\n你把两个数放在一起构成一个序对 这也一点不新奇\r\nSo it's no wonderful idea that you can just put two numbers together to form a pair.\r\n\r\n581\r\n00:42:04,020 --> 00:42:05,560\r\n如果你真想那么做的话\r\nIf that's all you ever wanted to do,\r\n\r\n582\r\n00:42:05,720 --> 00:42:07,400\r\n我们有各式各样的方法\r\nthere are tons of ways that you can do that.\r\n\r\n583\r\n00:42:08,200 --> 00:42:10,240\r\n我们的问题是 我们能否找到一种方法\r\nThe real issue is can you do that in such a way\r\n\r\n584\r\n00:42:11,220 --> 00:42:12,420\r\n可以让我们构建的东西作为一个块\r\nso that the things that you build\r\n\r\n585\r\n00:42:12,700 --> 00:42:16,100\r\n用来构建更复杂的东西？\r\nbecome building blocks for doing something even more complex?\r\n\r\n586\r\n00:42:16,900 --> 00:42:19,060\r\n因此无论何时有人向你展示控制复杂度的方法\r\nSo whenever someone shows you a method for controlling complexity,\r\n\r\n587\r\n00:42:19,060 --> 00:42:21,600\r\n你都应该说 嗯 这很不错 但我可以用它来构建什么呢？\r\nyou should say, yeah, that's great, but what can I build with it?\r\n\r\n588\r\n00:42:24,960 --> 00:42:25,760\r\n举个例子吧\r\nSo for example,\r\n\r\n589\r\n00:42:27,540 --> 00:42:31,740\r\n我举一个很像刚才那个有理数系统的例子\r\nlet me just run through another thing that's a lot like the rational number one.\r\n\r\n590\r\n00:42:31,740 --> 00:42:34,780\r\n假设我们想要在平面中表示一个点\r\nSuppose we would like to represent points in the plane.\r\n\r\n591\r\n00:42:35,300 --> 00:42:36,780\r\n好吧 这里有一个点\r\nYou sort of say, well, there's a point,\r\n\r\n592\r\n00:42:37,440 --> 00:42:39,060\r\n我们把它叫做点P\r\nand we're going to call that point p.\r\n\r\n593\r\n00:42:40,520 --> 00:42:45,100\r\n这个点可能会有一个坐标\r\nAnd that point might have coordinates,\r\n\r\n594\r\n00:42:47,000 --> 00:42:50,020\r\n比如点P就是(1,2)\r\nlike this might be the point 1 comma 2.\r\n\r\n595\r\n00:42:50,020 --> 00:42:53,500\r\nX坐标为1 Y坐标为2\r\nThe x-coordinate might be 1, and it's y-coordinate might be 2.\r\n\r\n596\r\n00:42:54,220 --> 00:42:57,920\r\n我们将要构建一个用于在平面中处理这些点的小型系统\r\nAnd we'll make a little system for manipulating points in the plane.\r\n\r\n597\r\n00:43:00,080 --> 00:43:03,800\r\n我们当然可以 可以像这样\r\nAnd again, we can do that-- here's a little example of that.\r\n\r\n598\r\n00:43:06,680 --> 00:43:09,360\r\n用向量来表示 就和点在平面中的表示是一样的\r\nIt can represent vectors, the same as points in the plane,\r\n\r\n599\r\n00:43:09,720 --> 00:43:11,260\r\n我们也会说 嗯\r\nand we'll say, yep,\r\n\r\n600\r\n00:43:11,620 --> 00:43:17,820\r\n这里有一个叫做MAKE-VECTOR的构造函数\r\nthere's a constructor called make-vector,\r\n\r\n601\r\n00:43:17,820 --> 00:43:19,420\r\n函数MAKE-VECTOR需要两个坐标\r\nmake-vector's going to take two coordinates,\r\n\r\n602\r\n00:43:20,700 --> 00:43:23,300\r\n当然 如果我们愿意的话可以将其实现为序对\r\nand here we can implement them if we like as pairs,\r\n\r\n603\r\n00:43:23,680 --> 00:43:25,540\r\n但是最重点的是我们有一个构造函数\r\nbut the important thing is that there's a constructor.\r\n\r\n604\r\n00:43:26,780 --> 00:43:28,320\r\n当我们传递了向量P后\r\nAnd then given some vector, p,\r\n\r\n605\r\n00:43:29,200 --> 00:43:30,600\r\n我们可以得到它的X坐标\r\nwe can find its x-coordinate,\r\n\r\n606\r\n00:43:31,980 --> 00:43:33,220\r\n我们也可以得到它的Y坐标\r\nor we can get its y-coordinate.\r\n\r\n607\r\n00:43:33,220 --> 00:43:36,900\r\n所以这里就有了点在平面系统中的构造函数和选择函数\r\nSo there's a constructor and selectors for points in the plane.\r\n\r\n608\r\n00:43:38,660 --> 00:43:41,820\r\n那么 我们有了平面中的点 就希望将它们用来构建事物\r\nWell, given points in the plane, we might want to use them to build something.\r\n\r\n609\r\n00:43:42,060 --> 00:43:44,060\r\n比如说 我们想要\r\nSo for instance, we might want to talk about,\r\n\r\n610\r\n00:43:44,680 --> 00:43:47,560\r\n我们有一个点P 一个点Q\r\nwe might have a point, p, and a point, q,\r\n\r\n611\r\n00:43:48,140 --> 00:43:52,460\r\n点P为(1,2) 点Q为(2,3)\r\nand p might be the point 1, 2, and q might be the point 2, 3.\r\n\r\n612\r\n00:43:54,460 --> 00:44:00,120\r\n我们想要得到从P开始 到Q截止的线段\r\nAnd we might want to talk about the line segment that starts at p and ends at q.\r\n\r\n613\r\n00:44:01,660 --> 00:44:03,100\r\n我们把它叫做线段S\r\nAnd that might be the segment s.\r\n\r\n614\r\n00:44:04,920 --> 00:44:12,340\r\n我们想用数字来表示点 并用点来构造向量\r\nSo we might want to build points for vectors in terms of numbers,\r\n\r\n615\r\n00:44:12,540 --> 00:44:13,940\r\n用向量来表示线段\r\nand segments in terms of vectors.\r\n\r\n616\r\n00:44:16,140 --> 00:44:19,000\r\n因此我们也可以对线段如法炮制\r\nSo we can represent line segments in exactly the same way.\r\n\r\n617\r\n00:44:19,700 --> 00:44:21,420\r\n因此 对于从P到Q的线段\r\nAll right, so the line segment from p to q,\r\n\r\n618\r\n00:44:21,420 --> 00:44:23,740\r\n我们这里有一个构造函数MAKE-SEGMENT\r\nwe'll say there's a constructor, make-segment.\r\n\r\n619\r\n00:44:26,680 --> 00:44:29,160\r\n然后是为选择函数取名\r\nAnd make up names for the selectors,\r\n\r\n620\r\n00:44:29,160 --> 00:44:32,240\r\n取得线段起点的函数 和取得终点的函数\r\nthe starting point of the segment and the ending point of the segment.\r\n\r\n621\r\n00:44:32,240 --> 00:44:35,400\r\n当然了 我们可以将线段实现为两个点构造成的序对\r\nAnd again, we can implement a segment using cons as a pair of points,\r\n\r\n622\r\n00:44:36,840 --> 00:44:40,340\r\nCAR和CDR可以分别取得构成线段的两个点\r\nand car and cdr get out the two points that we put together to get the segment.\r\n\r\n623\r\n00:44:44,540 --> 00:44:45,560\r\n好了 我们已经完成这个系统了\r\nWell, now having done that,\r\n\r\n624\r\n00:44:47,660 --> 00:44:49,160\r\n我们可以进行一些此操作\r\nwe can have some operations on them.\r\n\r\n625\r\n00:44:51,440 --> 00:44:56,120\r\n比如说 某个线段的中点是什么？\r\nLike we could say, what's the midpoint of a line segment?\r\n\r\n626\r\n00:44:57,320 --> 00:44:59,560\r\n这就是某个线段的中点\r\nSo here's the midpoint of a line segment,\r\n\r\n627\r\n00:44:59,880 --> 00:45:06,840\r\n该点的X、Y坐标分别为起点和终点X、Y坐标和的一半\r\nthat's going to be the points whose coordinates are the averages of the coordinates of the endpoints.\r\n\r\n628\r\n00:45:07,740 --> 00:45:08,780\r\n嗯 这就是中点\r\nOK, there's the midpoint.\r\n\r\n629\r\n00:45:09,840 --> 00:45:12,100\r\n因此 为了得到线段S的中点\r\nSo to get the midpoint of a line segment, s,\r\n\r\n630\r\n00:45:13,600 --> 00:45:17,020\r\n我们先要取得该线段的起点\r\nwe'll just say grab the starting point to the segment,\r\n\r\n631\r\n00:45:17,260 --> 00:45:18,680\r\n取得该线段的终点\r\ngrab the ending point of the segment,\r\n\r\n632\r\n00:45:19,960 --> 00:45:21,980\r\n然后构建一个向量 也就是一个点\r\nand now make a vector--make a point\r\n\r\n633\r\n00:45:22,680 --> 00:45:28,980\r\n该点的X坐标为起点、终点X坐标和的一半\r\nwhose coordinates are the average of the x-coordinate of the first point and the x-coordinate of the second point,\r\n\r\n634\r\n00:45:29,880 --> 00:45:32,300\r\nY坐标为起点、终点Y坐标和的一半\r\nand whose y-coordinate is the average of the y-coordinates.\r\n\r\n635\r\n00:45:33,480 --> 00:45:35,760\r\n这就是函数MIDPOINT一种实现\r\nSo there's an implementation of midpoint.\r\n\r\n636\r\n00:45:37,440 --> 00:45:42,980\r\n类似的 我们可以编写类似于求取线段长度的函数\r\nAnd then similarly, we can build something like the length of the segment.\r\n\r\n637\r\n00:45:43,960 --> 00:45:51,780\r\n线段的长度 可以根据勾股定理算得\r\nThe length of the segment is a thing whose-- use Pythagoras's rule,\r\n\r\n638\r\n00:45:51,780 --> 00:45:56,100\r\n线段的长度是dX的平方加dY的平方的和的平方根\r\nthe length of the segment is the square root of the d x squared plus d y squared.\r\n\r\n639\r\n00:45:56,680 --> 00:45:59,000\r\n当我们说计算某线段S的长度时\r\nWe'll say to get the length of a line segment,\r\n\r\n640\r\n00:45:59,920 --> 00:46:10,200\r\n我们令dX为起点、终点X坐标之差\r\nwe'll let dx be the difference of the x-coordinate of one endpoint and the x-coordinate of the other endpoint,\r\n\r\n641\r\n00:46:11,180 --> 00:46:14,500\r\n令dY为起点、终点Y坐标之差\r\nand we'll let dy be the difference of the y-coordinates.\r\n\r\n642\r\n00:46:15,880 --> 00:46:19,960\r\n然后我们求取dX、dY平方和的平方根\r\nAnd then we'll take the square root of the sum of the squares of dx and dy,\r\n\r\n643\r\n00:46:19,960 --> 00:46:20,780\r\n就是这样了\r\nthat's what this says.\r\n\r\n644\r\n00:46:22,020 --> 00:46:24,600\r\n好了 这就是函数LENGTH的一种实现\r\nAll right, so there's an implementation of length.\r\n\r\n645\r\n00:46:25,840 --> 00:46:33,940\r\n再次强调 我们构建的是一种层次系统\r\nAnd again, what we built is a layered system.\r\n\r\n646\r\n00:46:35,340 --> 00:46:40,200\r\n我们构建了一个有 呃 现在有线段\r\nWe built a system which has, well, say up here there's segments.\r\n\r\n647\r\n00:46:47,060 --> 00:46:48,620\r\n这里就有了一道抽象屏障\r\nAnd then there's an abstraction barrier.\r\n\r\n648\r\n00:46:50,160 --> 00:46:54,840\r\n这道抽象屏障把\r\nThe abstraction barrier separates the implementation\r\n\r\n649\r\n00:46:56,480 --> 00:46:58,920\r\n线段同向量、点的实现分离开来\r\nof segments from the implementation of vectors and points,\r\n\r\n650\r\n00:46:59,120 --> 00:47:03,580\r\n而这道抽象屏障 就是构造函数和选择函数\r\nand what that abstraction barrier is are the constructors and selectors.\r\n\r\n651\r\n00:47:03,580 --> 00:47:14,860\r\n也就是 MAKE-SEG SEG-START 和 SEG-END\r\nIt's make-segment, and segment-start, and segment-end.\r\n\r\n652\r\n00:47:17,700 --> 00:47:18,600\r\n这里是向量\r\nAnd then there are vectors.\r\n\r\n653\r\n00:47:19,720 --> 00:47:24,080\r\n而向量则是建立在序对和数的基础上\r\nAnd vectors in turn are built on top of pairs and numbers.\r\n\r\n654\r\n00:47:25,080 --> 00:47:29,080\r\n所以这里是序对和数\r\nSo I'll say pairs and numbers.\r\n\r\n655\r\n00:47:29,340 --> 00:47:31,760\r\n这又是它们的抽象屏障\r\nAnd that has its own abstraction barrier,\r\n\r\n656\r\n00:47:32,420 --> 00:47:42,620\r\n也就是 MAKE-VECT XCOR 和 YCOR\r\nwhich is make-vector, and x-coordinate, and y-coordinate.\r\n\r\n657\r\n00:47:46,440 --> 00:47:48,520\r\n如此可见 这就是一个层次系统\r\nSo we have, again, a layered system.\r\n\r\n658\r\n00:47:48,520 --> 00:47:51,460\r\n你可以清楚的看出这些分明的层次\r\nYou're starting to see that there are layers here.\r\n\r\n659\r\n00:47:51,720 --> 00:47:58,920\r\n我提一下 这里有一个非常重要但是又理所当然的东西\r\nI ought to mention, there is a very important thing that I kind of took for granted.\r\n\r\n660\r\n00:48:00,240 --> 00:48:07,120\r\n这点非常自然 但从另外一方面来说又非常重要\r\nAnd it's sort of so natural, but on the other hand it's a very important thing.\r\n\r\n661\r\n00:48:07,120 --> 00:48:10,220\r\n我们为了表示某线段S\r\nNotice that in order to represent this segment s,\r\n\r\n662\r\n00:48:11,600 --> 00:48:13,940\r\n我说这个线段就是由点构成的序对\r\nI said this segment is a pair of points.\r\n\r\n663\r\n00:48:16,260 --> 00:48:17,980\r\n而一个点又是由数构成的序对\r\nAnd a point is a pair of numbers.\r\n\r\n664\r\n00:48:18,800 --> 00:48:22,320\r\n如果要把这个结构的盒子—指针模型给画出来的话\r\nAnd if I were going to draw the box and pointers structure for that,\r\n\r\n665\r\n00:48:23,620 --> 00:48:25,060\r\n那么我会说 嗯 这个线段是\r\nI would say, oh, the segment is,\r\n\r\n666\r\n00:48:26,000 --> 00:48:29,260\r\n用我之前给你们说过的表示法来演示\r\ngiven those particular representations that I showed you,\r\n\r\n667\r\n00:48:29,260 --> 00:48:32,500\r\n线段就是一个序对\r\nI'd say this segment s is a pair,\r\n\r\n668\r\n00:48:33,720 --> 00:48:38,520\r\n序对的第一个元素是一个向量\r\nand the first thing in the pair is a vector,\r\n\r\n669\r\n00:48:40,200 --> 00:48:43,800\r\n向量是由数构成的序对\r\nand the vector is a pair of numbers.\r\n\r\n670\r\n00:48:45,460 --> 00:48:46,720\r\n这就是它 这就是点P\r\nAnd that's this, that's p.\r\n\r\n671\r\n00:48:49,920 --> 00:48:52,380\r\n线段中的另一个东西就是点Q\r\nAnd the other thing in the segment is q,\r\n\r\n672\r\n00:48:52,960 --> 00:48:58,160\r\n它本身就是一个由数构成的序对\r\nwhich is itself a pair of numbers.\r\n\r\n673\r\n00:48:59,800 --> 00:49:02,520\r\n当我说CONS可以让你把东西组合在一起的时候\r\nSo I almost took it for granted when I said that\r\n\r\n674\r\n00:49:03,260 --> 00:49:06,480\r\n就把它视作理所当然了\r\ncons allows you to put things together.\r\n\r\n675\r\n00:49:08,600 --> 00:49:13,020\r\n但有一点也很容易搞不明白 请注意\r\nBut it's very easy to not appreciate that, because notice,\r\n\r\n676\r\n00:49:13,020 --> 00:49:18,380\r\n我也可以把一些序对给组合在一起\r\nsome of the things I can put together can themselves be pairs.\r\n\r\n677\r\n00:49:20,360 --> 00:49:23,520\r\n我以后会经常用一个术语来表示\r\nAnd let me introduce a word that I'll talk about more next time,\r\n\r\n678\r\n00:49:24,100 --> 00:49:26,920\r\n一个我最喜欢的术语 这称作“闭包”\r\nit's one of my favorite words, called closure.\r\n\r\n679\r\n00:49:30,280 --> 00:49:35,460\r\n这种所谓具有“闭包性质”的组合方法\r\nAnd by closure I mean that the means of combination in your system\r\n\r\n680\r\n00:49:36,220 --> 00:49:39,320\r\n就是哪些当你用它们把东西组合在一起时\r\nare such that when you put things together using them,\r\n\r\n681\r\n00:49:39,320 --> 00:49:40,240\r\n这就像我们构建序对的时候\r\nlike we make a pair,\r\n\r\n682\r\n00:49:41,760 --> 00:49:44,500\r\n你可以继续用同样的方法把组合物继续进行组合\r\nyou can then put those together with the same means of combination.\r\n\r\n683\r\n00:49:44,940 --> 00:49:48,420\r\n因此我不仅可以有由数构成的序对 也可有由序对构成的序对\r\nSo I can have not only a pair of numbers, but I can have a pair of pairs.\r\n\r\n684\r\n00:49:51,460 --> 00:49:59,220\r\n比如说 在Fortran中的数组并不具有闭包性质\r\nSo for instance, making arrays in a language like Fortran is not a closed means of combination,\r\n\r\n685\r\n00:49:59,220 --> 00:50:00,800\r\n因为我可以有元素为数的数组\r\nbecause I can make an array of numbers,\r\n\r\n686\r\n00:50:01,560 --> 00:50:02,980\r\n但不能有以数组为元素的数组\r\nbut I can't make an array of arrays.\r\n\r\n687\r\n00:50:05,560 --> 00:50:07,000\r\n当某人给你展示组合的方法时\r\nAnd one of the things that you should ask,\r\n\r\n688\r\n00:50:07,420 --> 00:50:12,300\r\n你也应该这样问 通过该种组合方法\r\none of your tests of quality for a means of combination that someone shows you,\r\n\r\n689\r\n00:50:12,600 --> 00:50:17,120\r\n构建出的东西是否封闭\r\nis gee, are the things you make closed under that means of combination?\r\n\r\n690\r\n00:50:18,040 --> 00:50:22,280\r\n如果序对仅仅只能是由数构成的序对的话 就不是那么有趣了\r\nSo pairs would not be nearly so interesting if all I could do was make a pair of numbers.\r\n\r\n691\r\n00:50:22,820 --> 00:50:24,400\r\n我并不能用它构建出太多的结构\r\nI couldn't build very much structure at all.\r\n\r\n692\r\n00:50:26,520 --> 00:50:27,780\r\n好了 言归正传\r\nOK, well, we'll come back to that.\r\n\r\n693\r\n00:50:28,080 --> 00:50:30,760\r\n我现在只是提一下 后面我们还会详细讨论\r\nI just wanted to mention it now. You'll hear a lot about closure later on.\r\n\r\n694\r\n00:50:31,780 --> 00:50:38,840\r\n你也可以看到在我们有了层次系统后 如果不使用数据抽象\r\nYou can also see the potential for losing control of complexity\r\n\r\n695\r\n00:50:38,840 --> 00:50:42,120\r\n系统复杂度会有失控的隐患\r\nas you have a layered system if you don't use data abstraction.\r\n\r\n696\r\n00:50:43,680 --> 00:50:46,520\r\n让我们回过头来看看LENGTH函数的幻灯片\r\nLet's go back and look at this slide for length.\r\n\r\n697\r\n00:50:47,740 --> 00:50:51,880\r\nLENGTH函数简单而有效是因为\r\nLength works and is a simple thing because I can say,\r\n\r\n698\r\n00:50:52,840 --> 00:50:55,060\r\n当我使用它时 我确信\r\nwhen I want to get this value, I can say, oh,\r\n\r\n699\r\n00:50:55,300 --> 00:51:00,320\r\n这个是第一个端点的X坐标\r\nthat is the x-coordinate of the first endpoint of the segment.\r\n\r\n700\r\n00:51:02,700 --> 00:51:06,560\r\n这些东西 这些选择函数 XCOR 和 SEG-END\r\nAnd each of these things, each of these selectors, x-coordinate and endpoint,\r\n\r\n701\r\n00:51:07,140 --> 00:51:10,960\r\n都代表了一个决策选择 我不用关心它们的内部细节\r\nstand for a decision choice whose details I don't have to look at.\r\n\r\n702\r\n00:51:11,940 --> 00:51:16,000\r\n因此就和之前的有理数系统一样 我可以说\r\nSo I could perfectly well, again, just like rational numbers I did before,\r\n\r\n703\r\n00:51:16,000 --> 00:51:19,900\r\n我可以认为 嗯 线段实际上就是由序对构成的序对\r\nI could say, oh well, gee, a segment really is a pair of pairs.\r\n\r\n704\r\n00:51:20,800 --> 00:51:27,040\r\n线段第一个端点的X坐标实际上是什么 是什么呢？\r\nAnd the x-coordinate of the first endpoint or the segment really is the-- well, what is it?\r\n\r\n705\r\n00:51:27,040 --> 00:51:33,040\r\n它的线段的CAR部分的CAR部分\r\nIt's the car of the car of the segment.\r\n\r\n706\r\n00:51:33,640 --> 00:51:36,640\r\n所以我可以这样完美地重定义LENGTH\r\nSo I could perfectly well go and redefine length.\r\n\r\n707\r\n00:51:37,140 --> 00:51:46,420\r\n我可以定义某线段S的长度为\r\nI could say, define the length of some segment s.\r\n\r\n708\r\n00:51:48,640 --> 00:51:50,280\r\n我这样来写\r\nI can start off writing something like,\r\n\r\n709\r\n00:51:50,280 --> 00:51:56,000\r\n我们令dX为 令dX为什么呢？\r\nwell, we'll let dx be-- well, what's it have to be?\r\n\r\n710\r\n00:51:56,000 --> 00:51:57,920\r\n为两个坐标之差\r\nIt's got to be the difference of the two coordinates,\r\n\r\n711\r\n00:51:57,920 --> 00:52:05,820\r\n坐标之一为(CAR (CAR S))\r\nso that's the difference of, the first one is the car of the car of s,\r\n\r\n712\r\n00:52:08,140 --> 00:52:11,620\r\n从第一个坐标中减去\r\nsubtracted from the first one,\r\n\r\n713\r\n00:52:11,620 --> 00:52:15,820\r\n减去另一个点的坐标 也就是(CAR (CDR S))\r\nthe car of the other half of it, the cdr of s.\r\n\r\n714\r\n00:52:21,080 --> 00:52:24,920\r\n好了 那么dY也就是 我看看\r\nand then dy would be-- well, let's see,\r\n\r\n715\r\n00:52:25,920 --> 00:52:33,060\r\n那么Y坐标也就是 (CDR (CAR S))\r\nI'd get the y-coordinate, so it'd be the difference of the cdr of the car of s,\r\n\r\n716\r\n00:52:34,040 --> 00:52:41,260\r\n减去(CDR (CDR S)) 诸如此类\r\nand the cdr of the cdr of s, sort of go on.\r\n\r\n717\r\n00:52:43,760 --> 00:52:47,640\r\n你可以发现同之前那个程序相比 这个更难度\r\nYou can see that's much harder to read than the program I had before.\r\n\r\n718\r\n00:52:47,920 --> 00:52:52,900\r\n但比这个还糟的是 假设你这样实现了LENGTH函数\r\nBut worse than that, suppose you'd gone and implemented length?\r\n\r\n719\r\n00:52:56,520 --> 00:53:00,240\r\n而第二天 George来和你说 抱歉 我改变主意了\r\nAnd then the next day, George comes to you and says, I'm sorry, I changed my mind.\r\n\r\n720\r\n00:53:00,740 --> 00:53:03,940\r\n我想把点的X坐标放在前面\r\nI want to write points with the x-coordinate first.\r\n\r\n721\r\n00:53:04,860 --> 00:53:06,460\r\n然后您回过头来看代码 找啊找啊\r\nSo you come back you stare at this code and say,\r\n\r\n722\r\n00:53:06,460 --> 00:53:10,100\r\n那是什么呢 哦 是CAR\r\noh gee, what was that? That was the car,\r\n\r\n723\r\n00:53:10,100 --> 00:53:15,820\r\n因此我要把这个改为CDR 把这个改为CDR\r\nso I have to change this to cdr, and this is cdr,\r\n\r\n724\r\n00:53:17,020 --> 00:53:21,960\r\n这个要改为CAR 这个也要改为CAR\r\nand this now has to be car. And this has to be car.\r\n\r\n725\r\n00:53:23,480 --> 00:53:26,800\r\n你也就这么做了 然后第二天George又跑来说 抱歉 抱歉\r\nAnd you sort of do that, and then the next day George comes back and says, sorry,\r\n\r\n726\r\n00:53:27,120 --> 00:53:35,080\r\n设计显示的那个家伙想要让线段指向反方向\r\nAh the guys designing the display would like lines to be painted in the opposite direction,\r\n\r\n727\r\n00:53:35,080 --> 00:53:37,260\r\n因此我必须让截止点放到第一位\r\nso I have to write the endpoint first in the order.\r\n\r\n728\r\n00:53:37,260 --> 00:53:38,820\r\n然后你又回过头来审视这些代码\r\nAnd then you come back and you stare at this code,\r\n\r\n729\r\n00:53:38,820 --> 00:53:42,040\r\n哦 这又改怎么弄？\r\nand say, gee, what was it talking about?\r\n\r\n730\r\n00:53:42,040 --> 00:53:44,080\r\n嗯 把这个改为CDR\r\nOh yeah, well I've got to change this one to cdr,\r\n\r\n731\r\n00:53:45,020 --> 00:53:50,500\r\n这个改为CAR 改为CAR 把这个改为CDR\r\nand this one becomes car, this one comes car, and this becomes cdr.\r\n\r\n732\r\n00:53:50,500 --> 00:53:51,420\r\n你又这么做了\r\nAnd you go up and do that,\r\n\r\n733\r\n00:53:52,040 --> 00:53:53,820\r\n第二天 George又跑过来说 太抱歉了\r\nand then the next day, George comes back and says, I'm sorry,\r\n\r\n734\r\n00:53:53,820 --> 00:53:58,680\r\n我其实只是想让线段总是在屏幕上从左向右描绘\r\nwhat I really meant is that the segments always have to be painted from left to right on the screen.\r\n\r\n735\r\n00:53:59,220 --> 00:54:03,220\r\n这时候 毫无疑问 你一定会给George一个耳光\r\nAnd then you sort of, it's clear, you just go and punch George in the mouth at that point.\r\n\r\n736\r\n00:54:03,220 --> 00:54:08,940\r\n正如你所见 一旦我们有了一个10层的系统\r\nBut you see, as soon as we have a 10 layer system,\r\n\r\n737\r\n00:54:08,940 --> 00:54:11,040\r\n复杂度也就突增\r\nyou see how that complexity immediately builds up\r\n\r\n738\r\n00:54:11,500 --> 00:54:14,240\r\n甚至达到像这里一样失控的地步\r\nto the point where even something like this gets out of control.\r\n\r\n739\r\n00:54:15,940 --> 00:54:20,820\r\n因此 为了避免发生这样的事 我们就要为精灵命名\r\nSo again, the way we've gotten out of that is we've named that spirit.\r\n\r\n740\r\n00:54:20,820 --> 00:54:24,400\r\n我们构建一个系统 这个系统中有一个\r\nWe built a system where there is a thing,\r\n\r\n741\r\n00:54:25,140 --> 00:54:30,220\r\n关于你要如何显示向量的选择\r\nwhich is the representation choice for how you're going to talk about vectors.\r\n\r\n742\r\n00:54:31,180 --> 00:54:34,620\r\n这个选择在这里\r\nAnd choices about that representation are localized right there.\r\n\r\n743\r\n00:54:35,340 --> 00:54:37,460\r\n它们不必将其完全显露出来\r\nThey don't have their guts spilling over into things like\r\n\r\n744\r\n00:54:37,460 --> 00:54:39,460\r\n就像这里你计算长度和中点\r\nhow you compute the length and how you compute the midpoint.\r\n\r\n745\r\n00:54:41,000 --> 00:54:43,900\r\n这才是这个系统真正强大之处\r\nAnd that's the real power of this system.\r\n\r\n746\r\n00:54:45,320 --> 00:54:49,480\r\n我们对它们很清楚 这样我们能控制它们\r\nOK, we're explicit about them, so that we have control over them.\r\n\r\n747\r\n00:54:50,840 --> 00:54:51,460\r\n好了 有疑问吗？\r\nAll right, questions?\r\n\r\n748\r\n00:54:51,600 --> 00:54:55,900\r\n学生：在那些无法使用序对来表示的情况中会如何呢？\r\nAUDIENCE: What happens in the case where you don't want to be treating objects in terms of pairs?\r\n\r\n749\r\n00:54:55,900 --> 00:55:01,180\r\n比如说在三维空间里 一个序对无法表示三维坐标\r\nFor instance, in three-dimensional space, you'd have three coordinates.\r\n\r\n750\r\n00:55:01,180 --> 00:55:03,800\r\n也就是说在N维空间中 我们该如何做呢？\r\nOr even in the case where you have n-dimensional space, what happens?\r\n\r\n751\r\n00:55:03,800 --> 00:55:04,800\r\n教授：啊 嗯\r\nPROFESSOR: Right, OK.\r\n\r\n752\r\n00:55:04,800 --> 00:55:07,180\r\n好吧 你提到了一点明天的内容\r\nWell, this is a preview of what I'll say tomorrow.\r\n\r\n753\r\n00:55:08,020 --> 00:55:15,760\r\n但关键点就是 一旦你有了二元的东西 就可以有多元的东西\r\nBut the point is, once you have two things, you have as many things as you want.\r\n\r\n754\r\n00:55:16,800 --> 00:55:18,640\r\n能理解吗？ 如果我想要组合三个东西\r\nAll right? Because if I want to make three things,\r\n\r\n755\r\n00:55:19,040 --> 00:55:21,020\r\n我构建一个序对\r\nI could start making things like a pair\r\n\r\n756\r\n00:55:24,680 --> 00:55:25,980\r\n该序对第一个元素是1\r\nwhose first thing is 1,\r\n\r\n757\r\n00:55:26,620 --> 00:55:32,380\r\n第二个元素则又是一个序对 一个有2和3的序对\r\nand whose second thing is another pair that, say, has 2 and 3 in it.\r\n\r\n758\r\n00:55:34,700 --> 00:55:36,620\r\n以此类推 十个百个的东西 我可以把序对嵌套起来\r\nAnd so on, a hundred things. I can nest them out of pairs.\r\n\r\n759\r\n00:55:37,180 --> 00:55:40,040\r\n这里 我相当随意地使用了一种方法\r\nHere I made a pretty arbitrary decision about how to do it,\r\n\r\n760\r\n00:55:40,040 --> 00:55:42,320\r\n不久后你将看到更多地方法\r\nand you can immediately see there are lots of ways to do that.\r\n\r\n761\r\n00:55:42,680 --> 00:55:45,920\r\n而我们下节课将会讨论处理类似问题的约定\r\nWhat we'll start talking about next time are conventions for how to do things like that.\r\n\r\n762\r\n00:55:47,320 --> 00:55:50,360\r\n只要注意到我可以构建由序对构成的序对就好了\r\nBut notice that what this really depends on is I can make pairs of pairs.\r\n\r\n763\r\n00:55:51,580 --> 00:55:53,900\r\n因为我只能构建由数构成的序对的话 我就没法了\r\nIf all I could do was make pairs of numbers, I'd be stuck.\r\n\r\n764\r\n00:56:06,780 --> 00:56:10,040\r\n好吧 休息\r\nOK. Let's break.\r\n\r\n765\r\n00:56:11,060 --> 00:56:20,460\r\n[音乐]\r\n[JESU, JOY OF MAN'S DESIRING]\r\n\r\n766\r\n00:56:21,860 --> 00:56:28,000\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n767\r\n00:56:38,000 --> 00:56:41,720\r\n《计算机程序的构造和解释》\r\nThe Structure And Interpretation of Computer Programs\r\n\r\n768\r\n00:56:42,000 --> 00:56:45,600\r\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\r\nBy: Prof. Harold Abelson && Gerald Jay Sussman\r\n\r\n769\r\n00:56:46,440 --> 00:56:49,940\r\n复合数据\r\nCompound Data\r\n\r\n770\r\n00:56:55,240 --> 00:56:57,340\r\n好吧 我们刚才只是做了\r\nAll right, well, we've just gone off and done\r\n\r\n771\r\n00:56:59,240 --> 00:57:01,800\r\n一个数据抽象的简单示例\r\na couple of simple examples of data abstraction.\r\n\r\n772\r\n00:57:03,620 --> 00:57:05,060\r\n现在我想做点更复杂的事儿\r\nNow I want to do something more complicated.\r\n\r\n773\r\n00:57:05,640 --> 00:57:07,120\r\n稍后我会详细说明这意味着什么\r\nWe're going to talk about what it means.\r\n\r\n774\r\n00:57:07,900 --> 00:57:08,860\r\n这也将更困难\r\nAnd this will be harder,\r\n\r\n775\r\n00:57:08,860 --> 00:57:12,940\r\n因为在计算机程序设计中\r\nbecause it's always much harder in computer programming\r\n\r\n776\r\n00:57:12,940 --> 00:57:15,500\r\n说明某件事的的意义远比实现它难\r\nto talk about what something means than to go off and do it.\r\n\r\n777\r\n00:57:16,460 --> 00:57:21,600\r\n让我们回到最最开始的地方\r\nBut let's go back to almost the very beginning.\r\n\r\n778\r\n00:57:21,600 --> 00:57:24,640\r\n还记得当时我说过的话么？\r\nLet's go back to the point where I said,\r\n\r\n779\r\n00:57:25,400 --> 00:57:27,900\r\n我说 我们假设已经存在一些过程\r\nwe just assumed that there were procedures,\r\n\r\n780\r\n00:57:29,800 --> 00:57:36,620\r\nMAKE-RAT、NUMER以及DENOM\r\nmake-rat, and numer, and denom.\r\n\r\n781\r\n00:57:38,120 --> 00:57:40,700\r\n好吧 我们就回到那里 回到最开始的地方\r\nLet's go back to where we had this, at the very beginning,\r\n\r\n782\r\n00:57:41,740 --> 00:57:47,020\r\n有构造函数和选择函数 以及定义有理数算术的地方\r\nconstructors and selectors, and when often defined the rational number arithmetic.\r\n\r\n783\r\n00:57:47,020 --> 00:57:50,220\r\n我那时说过 假设我们已经有了那些需要George实现的东西了\r\nAnd remember, I said at that point we were sort of done, except for George.\r\n\r\n784\r\n00:57:51,620 --> 00:57:54,340\r\n那么 在那个时候我们实际上干了什么呢？\r\nWell, what is it that we'd actually done at that point?\r\n\r\n785\r\n00:57:55,580 --> 00:57:56,740\r\n做了些什么东西呢？\r\nWhat was it that was done?\r\n\r\n786\r\n00:57:59,040 --> 00:58:00,100\r\n我想说的就是\r\nWell, what I want to say is,\r\n\r\n787\r\n00:58:00,920 --> 00:58:05,240\r\n我们用这些东西实现了有理数操作后又做了什么呢\r\nwhat was done after we'd implemented the operations and terms of these,\r\n\r\n788\r\n00:58:05,720 --> 00:58:12,000\r\n我们用抽象数据来定义了有理数的表示\r\nwas that we had defined a rational number representation in terms of abstract data.\r\n\r\n789\r\n00:58:18,060 --> 00:58:19,560\r\n通过数据抽象我想表达什么？\r\nWhat do I mean by abstract data?\r\n\r\n790\r\n00:58:20,700 --> 00:58:22,060\r\n关键点就是\r\nWell, the idea is that\r\n\r\n791\r\n00:58:24,520 --> 00:58:27,140\r\n在那个时候 当我们有了+RAT和*RAT\r\nat that point, when we had our +RAT and our *RAT,\r\n\r\n792\r\n00:58:28,580 --> 00:58:36,260\r\n任何George提供给我们的MAKE-RAT NUMER和DENOM函数\r\nthat any implementation of make-RAT, and numerator, and denominator that George supplied us with,\r\n\r\n793\r\n00:58:37,700 --> 00:58:39,840\r\n都可以是有理数的表示基础\r\ncould be the basis for a rational number representation.\r\n\r\n794\r\n00:58:40,620 --> 00:58:42,280\r\n因为你并不应该关心\r\nLike, it wasn't our concern where you\r\n\r\n795\r\n00:58:42,900 --> 00:58:46,460\r\n应该在那里获得最大公约数 等等\r\ndivided through to get the greatest common denominator, or any of that.\r\n\r\n796\r\n00:58:48,540 --> 00:58:53,800\r\n关键点就是 我们构建了一个有理数算术系统\r\nSo the idea is that what we built is a rational arithmetic system\r\n\r\n797\r\n00:58:53,800 --> 00:58:56,200\r\n一个可以基于任何表示方法的系统\r\nthat would sit on top of any representation.\r\n\r\n798\r\n00:58:56,880 --> 00:58:58,360\r\n“任何表示方法”又是什么意思呢？\r\nWhat do I mean by any representation?\r\n\r\n799\r\n00:58:59,620 --> 00:59:01,160\r\n我当然不会是指\r\nI mean, certainly it can't be the case\r\n\r\n800\r\n00:59:01,820 --> 00:59:05,380\r\nGeorge从一个包里面 随便取出3个过程\r\nthat all I mean is George can reach in a bag and pull out three arbitrary procedures\r\n\r\n801\r\n00:59:07,140 --> 00:59:10,860\r\n然后说 这就是那些实现\r\nand say, well, fine, now that's the implementation.\r\n\r\n802\r\n00:59:11,460 --> 00:59:12,740\r\n不是这样的\r\nThat can't be what I mean.\r\n\r\n803\r\n00:59:13,740 --> 00:59:19,000\r\n我指的是这里有一种衡量方法\r\nWhat I've got to mean is that there's some way of saying whether\r\n\r\n804\r\n00:59:20,820 --> 00:59:25,760\r\n可以判定这三个过程用于有理数的表示是否合适\r\nthree procedures are going to be suitable as a basis for rational number representation.\r\n\r\n805\r\n00:59:25,760 --> 00:59:27,320\r\n如果我们仔细思考这个问题\r\nIf we think about it,\r\n\r\n806\r\n00:59:28,340 --> 00:59:31,800\r\n我应该像这样定义 所谓的“合适”\r\nwhat suitable might mean is if I have to assume something like this,\r\n\r\n807\r\n00:59:31,800 --> 00:59:45,400\r\n我会说 如果X是(MAKE-RAT N D)\r\nI have to say that if x is the result of say, doing make-RAT of n and d,\r\n\r\n808\r\n00:59:48,540 --> 01:00:07,060\r\n那么(NUMER X)除以(DENOM X)等同于N除以D\r\nthen the numerator of x divided by the denominator of x is equal to n over d.\r\n\r\n809\r\n01:00:09,360 --> 01:00:11,940\r\n看到了吗 这就和George订的契约\r\nSee, what that is is that's George's contract.\r\n\r\n810\r\n01:00:13,400 --> 01:00:16,100\r\n而我们契约中订好的有理数规则\r\nWhat we mean by writing a contract for rational numbers,\r\n\r\n811\r\n01:00:16,100 --> 01:00:17,680\r\n你仔细想想的话 也是正确的\r\nif you think about it, this is the right thing.\r\n\r\n812\r\n01:00:18,480 --> 01:00:21,220\r\n我给你演示的这两个东西也是正确地\r\nAnd the two ones we showed do the right thing.\r\n\r\n813\r\n01:00:21,220 --> 01:00:23,220\r\n这样的话 就算我要考虑最大公约数\r\nSee, if I'm taking out greatest common divisors,\r\n\r\n814\r\n01:00:25,400 --> 01:00:28,800\r\n我除不除、在哪里除 都无所谓\r\nit doesn't matter whether I take them out or not, or the place where I take them,\r\n\r\n815\r\n01:00:28,800 --> 01:00:30,520\r\n因为我这里进行了约分\r\nbecause the idea is I'm going to divide through.\r\n\r\n816\r\n01:00:32,060 --> 01:00:33,540\r\n嗯 这就是George的契约\r\nBut see, this is George's contract.\r\n\r\n817\r\n01:00:33,540 --> 01:00:39,920\r\n我们要告诉George的就是 提供给我三个过程\r\nSo what we really say to George is your business is to go off and find us three procedures,\r\n\r\n818\r\n01:00:40,620 --> 01:00:42,240\r\nMAKE-RAT NUMER 和 DENOM\r\nmake-RAT, and numerator, and denominator,\r\n\r\n819\r\n01:00:42,520 --> 01:00:46,520\r\n使得无论N和D如何选择 都可以满足这个契约\r\nthat fulfill this contract for any choice of n and d.\r\n\r\n820\r\n01:00:46,740 --> 01:00:52,140\r\n这也就是我所谓的我们可以用来作为有理数表示的基础\r\nAnd that's what we mean by we can use that as the basis for a rational number representation.\r\n\r\n821\r\n01:00:54,240 --> 01:00:56,540\r\n并且只要它们能满足契约\r\nAnd other than that, it fulfills this contract.\r\n\r\n822\r\n01:00:56,740 --> 01:00:58,040\r\n我们不关心他是如何实现的\r\nWe don't care how he does it.\r\n\r\n823\r\n01:00:59,380 --> 01:01:02,320\r\n这不关我们的事儿 这在抽象层之下\r\nIt's not our business. It's below the layer of abstraction.\r\n\r\n824\r\n01:01:06,620 --> 01:01:12,000\r\n事实上 如果我们想知道 有理数真正是什么\r\nIn fact, if we want to say, what is a rational number really?\r\n\r\n825\r\n01:01:13,520 --> 01:01:16,940\r\n那么 如果不在抽象层之下来讨论的话\r\nSee, what's it really, without having to talk about going below the layer of abstraction,\r\n\r\n826\r\n01:01:16,940 --> 01:01:21,340\r\n我们必须得说有理数实际上是\r\nwhat we're forced into saying is a rational number really\r\n\r\n827\r\n01:01:23,760 --> 01:01:25,100\r\n这里的这些公理\r\nis sort of this axiom,\r\n\r\n828\r\n01:01:25,800 --> 01:01:30,900\r\n就是MAKE-RAT NUMER 和 DENOM这三个满足这条公理的过程\r\nis three procedures, make-RAT, numerator, and denominator, that satisfy this axiom.\r\n\r\n829\r\n01:01:32,040 --> 01:01:36,880\r\n从某种抽象的意义来说 这就是真正的有理数\r\nIn some sense, abstractly, that's what a rational number is really.\r\n\r\n830\r\n01:01:41,240 --> 01:01:45,760\r\n这听起来很容易 因为你脑中已经有了\r\nThat's sort of easy words to listen to, because what you have in your head, of course, is well,\r\n\r\n831\r\n01:01:46,200 --> 01:01:49,480\r\n关于有理数是什么的知识\r\nfor all this thing about saying that's what a rational number is really,\r\n\r\n832\r\n01:01:50,420 --> 01:01:52,800\r\n因为你已经看到了我们是如何构建有理数的\r\nyou actually just saw that we built rational numbers.\r\n\r\n833\r\n01:01:58,480 --> 01:02:04,000\r\n对 我们是在序对的基础上构建有理数的\r\nSee, what we really did is we built rational numbers on top of pairs.\r\n\r\n834\r\n01:02:08,520 --> 01:02:13,640\r\n因此 抽象地来说 我们可以认为有理数实际上就是这些公理\r\nSo for all I'm saying abstractly, we can say a rational number really is just this axiom.\r\n\r\n835\r\n01:02:15,000 --> 01:02:19,160\r\n你可以很自然把有理数理解为序对 因为这正也是你们见到的\r\nYou can listen to that comfortably, because you're saying, well, yeah, but really it's actually pairs,\r\n\r\n836\r\n01:02:19,960 --> 01:02:22,640\r\n我把它说得抽象后反而影响你理解\r\nand I'm just annoying you by trying to be abstract.\r\n\r\n837\r\n01:02:24,520 --> 01:02:27,700\r\n那么为了让你们明白\r\nWell, let me, as an antidote for that,\r\n\r\n838\r\n01:02:28,600 --> 01:02:31,720\r\n我会展示一个吓到你们的东西\r\nlet me do something that I think is really going to terrify you.\r\n\r\n839\r\n01:02:32,620 --> 01:02:35,580\r\n我讲带领你们零距离地面对\r\nI mean, it's really going to bring you face to face\r\n\r\n840\r\n01:02:36,400 --> 01:02:40,620\r\n我们讨论的抽象的真实存在性\r\nwith the sort of existential reality of this abstraction that we're talking about.\r\n\r\n841\r\n01:02:41,260 --> 01:02:44,100\r\n我们将讨论“序对”到底是什么？\r\nAnd what I'm going to talk about is, what are pairs really?\r\n\r\n842\r\n01:02:45,700 --> 01:02:47,020\r\n说说 我是怎么给你们讲“序对”的？\r\nSee, what did I tell you about pairs?\r\n\r\n843\r\n01:02:48,340 --> 01:02:49,080\r\n我耍了你们 对吧？\r\nI tricked you, right?\r\n\r\n844\r\n01:02:49,080 --> 01:02:52,160\r\n我说 Lisp有一个叫CONS的基本过程可以构建序对\r\nI said that Lisp has this primitive called cons that builds pairs.\r\n\r\n845\r\n01:02:53,340 --> 01:02:54,740\r\n但我真正告诉你们什么呢？\r\nBut what did I really tell you about?\r\n\r\n846\r\n01:02:56,180 --> 01:02:58,740\r\n如果你回过头来看 看这些幻灯片\r\nIf you go back and said, let's look on this slide,\r\n\r\n847\r\n01:02:59,280 --> 01:03:04,680\r\n会发现我真正告诉你们的是序对应该具有这些属性\r\nall I really told you about pairs is that there happens to be this property,\r\n\r\n848\r\n01:03:04,680 --> 01:03:06,380\r\n这些CONS CAR 和 CDR构成的属性\r\nthese properties of cons, car, and cdr.\r\n\r\n849\r\n01:03:06,540 --> 01:03:07,940\r\n而我说的“序对”\r\nAnd all I really said about pairs\r\n\r\n850\r\n01:03:08,520 --> 01:03:12,740\r\n只是说这里面有叫CONS 叫CAR 和叫CDR的东西\r\nis that there's a thing called cons, and a thing called car, and a thing called cdr.\r\n\r\n851\r\n01:03:14,520 --> 01:03:18,720\r\n在这个例子中 我构建了由X和Y构成的序对 取CAR部分得X\r\nAnd it is the case that if I build cons of x, y and take car of it, I get x.\r\n\r\n852\r\n01:03:20,440 --> 01:03:24,140\r\n构建由X和Y构成的序对 取CDR部分得Y\r\nAnd if I build cons of x, y and get cdr of it, I get y.\r\n\r\n853\r\n01:03:25,520 --> 01:03:32,460\r\n尽管如此 我也对你们谎称Lisp中有个东西能这么做\r\nAnd even though I lulled you into thinking that there's something in Lisp that does that,\r\n\r\n854\r\n01:03:32,460 --> 01:03:34,200\r\n因此你们也就假装确实有这么个东西\r\nso you pretended you knew what it was,\r\n\r\n855\r\n01:03:34,380 --> 01:03:38,100\r\n事实上 关于序对 我告诉你们的跟有理数一样多\r\nin fact, I didn't tell you any more about pairs than this tells you about rational numbers.\r\n\r\n856\r\n01:03:39,400 --> 01:03:41,020\r\n都是序对的一些公理\r\nIt's just some axiom for pairs.\r\n\r\n857\r\n01:03:44,320 --> 01:03:49,380\r\n言归正传 我马上要大显身手了\r\nWell, to drive that home, let me really scare you,\r\n\r\n858\r\n01:03:51,360 --> 01:03:53,660\r\n我会用某个神秘的东西来构建序对\r\nand show you what we might build pairs in terms of.\r\n\r\n859\r\n01:03:55,760 --> 01:04:00,580\r\n你们将会看见 我们可以构建有理数\r\nAnd what you're going to see is that we can build rational numbers,\r\n\r\n860\r\n01:04:00,580 --> 01:04:03,740\r\n直线段、向量以及任何由序对构建起的东西\r\nand line segments, and vectors, and all of this stuff in terms of pairs,\r\n\r\n861\r\n01:04:04,720 --> 01:04:07,840\r\n我们在低于抽象层的这里看到 序对可以凭空产生\r\nand we're going to see below here that pairs can be built out of nothing at all.\r\n\r\n862\r\n01:04:10,640 --> 01:04:11,340\r\n纯粹的抽象\r\nPure abstraction.\r\n\r\n863\r\n01:04:12,440 --> 01:04:18,440\r\n幻灯片中展示了CONS CAR和CDR的一种实现\r\nSo let me show you on this slide an implementation of cons, car, and cdr.\r\n\r\n864\r\n01:04:21,140 --> 01:04:22,720\r\n等会儿我们会回来细看\r\nAnd we'll look at it again in a second,\r\n\r\n865\r\n01:04:23,160 --> 01:04:26,520\r\n但一定要注意过程CONS CAR和CDR的定义\r\nbut notice that their procedure definitions of cons, car, and cdr,\r\n\r\n866\r\n01:04:27,060 --> 01:04:32,300\r\n这里你看不到任何数据 你只能看到一个lambda\r\nyou don't see any data in there, what you see is a lambda.\r\n\r\n867\r\n01:04:34,860 --> 01:04:40,320\r\n这里的CONS将返回 一个返回值为新的过程的过程\r\nCons, So cons here is going to return-- is a procedure that returns a procedure,\r\n\r\n868\r\n01:04:41,080 --> 01:04:42,400\r\n就像函数AVERAGE-ADPT\r\njust like average-adpt.\r\n\r\n869\r\n01:04:44,280 --> 01:04:49,340\r\n(CONS A B)返回一个具有单个参数的过程pick\r\nCons of a and b returns a procedure of an argument called pick,\r\n\r\n870\r\n01:04:51,720 --> 01:04:52,300\r\n它的定义是\r\nand it says,\r\n\r\n871\r\n01:04:52,780 --> 01:04:55,860\r\n如果pick等于1 那么该过程返回a\r\nif pick is equal to 1, I'm going to return a,\r\n\r\n872\r\n01:04:57,080 --> 01:04:59,520\r\n而如果pick等于2 那么该过程返回b\r\nand if pick is equal to 2, I'm going to return b,\r\n\r\n873\r\n01:05:00,220 --> 01:05:01,660\r\n这就是CONS的定义\r\nand that's what cons is going to be.\r\n\r\n874\r\n01:05:04,460 --> 01:05:10,100\r\n取X的CAR部分 (CAR X)\r\nCar of a thing x, car of a pair x,\r\n\r\n875\r\n01:05:10,500 --> 01:05:13,020\r\n就是把X应用于1 注意了 这完全行得通\r\nis going to be x applied to 1. And notice that makes sense.\r\n\r\n876\r\n01:05:13,020 --> 01:05:17,360\r\n你现在还不太明白我为什么要这样做 但至少这样行得通\r\nYou might not understand why or how I'm doing such a thing, but at least it makes sense,\r\n\r\n877\r\n01:05:17,760 --> 01:05:20,700\r\n因为我通过CONS构造出了一个过程\r\nbecause the thing constructed by cons is a procedure,\r\n\r\n878\r\n01:05:21,260 --> 01:05:22,620\r\n而CAR将其应用于1\r\nand car applies that to 1.\r\n\r\n879\r\n01:05:24,260 --> 01:05:26,760\r\n类似的 CDR将其应用于2\r\nAnd similarly, cdr applies that thing to 2.\r\n\r\n880\r\n01:05:29,060 --> 01:05:32,800\r\n好了 现在我已经给出了CONS CAR和CDR的一种表示法\r\nOK, now I claimed that this is a representation of cons, car, and cdr,\r\n\r\n881\r\n01:05:32,800 --> 01:05:34,100\r\n注意这里面没有任何数据\r\nand notice there's no data in it.\r\n\r\n882\r\n01:05:35,600 --> 01:05:37,940\r\n这就是“凭空”产生的 它们仅仅是过程\r\nAll right, it's built out of air. It's just procedures.\r\n\r\n883\r\n01:05:39,220 --> 01:05:42,220\r\n这种表示法中没有任何数据对象\r\nThere's no data objects at all in that representation.\r\n\r\n884\r\n01:05:43,460 --> 01:05:45,120\r\n那么 这又可能意味着什么呢？\r\nWell, what could that possibly mean?\r\n\r\n885\r\n01:05:49,260 --> 01:05:51,140\r\n嗯 如果你承认这些东西的话\r\nWell, if you really believe this stuff,\r\n\r\n886\r\n01:05:54,000 --> 01:05:59,340\r\n那么接下来 一旦我证明了CONS CAR CDR的这种表示法\r\nthen you have to believe that in order to show that that's a representation for cons, car, and cdr,\r\n\r\n887\r\n01:05:59,640 --> 01:06:02,180\r\n能满足我们的公理的话 你就对此不容置疑了\r\nall I have to do is show that it satisfies the axiom.\r\n\r\n888\r\n01:06:03,220 --> 01:06:05,320\r\n那么 我来举一个例子\r\nSee, all I should have to convince you of is,\r\n\r\n889\r\n01:06:05,560 --> 01:06:23,000\r\n例如 (CAR (CONS 37 49))应该返回37\r\nfor example, that gee, that car of cons of 37 and 49 is 37\r\n\r\n890\r\n01:06:23,000 --> 01:06:25,700\r\n37和49是我随意挑选的任意值\r\nRight? for arbitrary values of 37 and 49.\r\n\r\n891\r\n01:06:26,460 --> 01:06:28,820\r\nCDR也是如此\r\nIf I really.... And cdr the same way.\r\n\r\n892\r\n01:06:31,800 --> 01:06:36,140\r\n如果我能用这个凭空构造的怪异过程\r\nSee, if I really can demonstrate to you that that weird procedure definition,\r\n\r\n893\r\n01:06:36,640 --> 01:06:40,180\r\n来向你们演示它能满足这些公理\r\nin terms of the air, has the property that it satisfies this,\r\n\r\n894\r\n01:06:41,480 --> 01:06:47,080\r\n那么你就应该认为这是CONS CAR和CDR的可行实现\r\nthen you just have to grant me that that is a possible implementation of cons, car, and cdr,\r\n\r\n895\r\n01:06:47,080 --> 01:06:48,700\r\n也就可以用它们来构造其它东西了\r\non which I can build everything else.\r\n\r\n896\r\n01:06:49,640 --> 01:06:53,360\r\n好了 让我们回过头来看看 这里将用到代换模型\r\nWell, let's look at that. And this will be practice in the substitution model.\r\n\r\n897\r\n01:06:53,480 --> 01:07:00,280\r\n我们该怎么来说清这个过程呢？\r\nHow would I actually, How could we check this?\r\n\r\n898\r\n01:07:00,280 --> 01:07:03,180\r\n我们好像知道点怎么做 这都是同一个代换模型\r\nWe sort of know how to do that. It's just the same substitution model.\r\n\r\n899\r\n01:07:04,640 --> 01:07:09,320\r\n我们来瞧瞧 首先 我们考虑(CAR (CONS 37 49))是什么\r\nLet's look. We start out, and we say, what's car of cons of 37 and 49?\r\n\r\n900\r\n01:07:10,800 --> 01:07:13,140\r\n接下来该怎么做？ CONS只是一个过程\r\nWhat do we do? Cons is some procedure.\r\n\r\n901\r\n01:07:15,600 --> 01:07:18,760\r\n它的值也就是一个有A和B的过程\r\nIts value is cons was a procedure of a and b.\r\n\r\n902\r\n01:07:19,580 --> 01:07:22,820\r\nCONS返回的是一个过程体\r\nThe thing returned by cons is its procedure body\r\n\r\n903\r\n01:07:23,140 --> 01:07:26,820\r\n该过程体的参数被37和49代换掉了\r\nwith 37 and 49 substituted for the parameters.\r\n\r\n904\r\n01:07:26,820 --> 01:07:31,080\r\n用37代换A 用49代换B\r\nIt'll be 37 substituted for a and 49 substituted for b.\r\n\r\n905\r\n01:07:32,520 --> 01:07:36,700\r\n所以这个表达式和这个表达式的意思是相同的\r\nSo this expression has the same meaning as this expression.\r\n\r\n906\r\n01:07:36,720 --> 01:07:40,980\r\nCAR没变 而CONS被代换为了一个以LAMBDA开头的表达式\r\nIts car of, and the body of cons was this thing that started with lambda.\r\n\r\n907\r\n01:07:42,780 --> 01:07:47,100\r\n这里PICK是另外一个变量 如果PICK为1的话\r\nAnd it says, so if pick is equal to 1, where pick is this other argument,\r\n\r\n908\r\n01:07:47,260 --> 01:07:50,420\r\n如果PICK等于1 那么就返回37 也就是A的值\r\nif pick is equal to 1, it's 37, that's where a was,\r\n\r\n909\r\n01:07:51,120 --> 01:07:53,460\r\n如果PICK等于2 那么就返回49\r\nand if pick is equal to 2, it's 49.\r\n\r\n910\r\n01:07:54,820 --> 01:07:55,780\r\n这是代换的第一步\r\nSo that's the first step.\r\n\r\n911\r\n01:07:55,780 --> 01:07:58,620\r\n我只是进行了机械地代换\r\nI'm just going through mechanical substitution.\r\n\r\n912\r\n01:07:59,120 --> 01:08:00,560\r\n注意了 这也是本课的一大要点\r\nAnd remember, at this point in the course,\r\n\r\n913\r\n01:08:00,560 --> 01:08:02,220\r\n当你搞不清楚情况的时候\r\nif you're confused about what things mean,\r\n\r\n914\r\n01:08:02,480 --> 01:08:04,820\r\n就按照代换模型进行机械地代换\r\ngo mechanically through the substitution model.\r\n\r\n915\r\n01:08:05,100 --> 01:08:06,320\r\n那么 这又会被归约为什么呢？\r\nWell, what is this reduced to?\r\n\r\n916\r\n01:08:07,620 --> 01:08:15,700\r\n而CAR则是 把给定的参数 也就是这些 应用于1\r\nCar said, take your, take your argument, which in this case is this, and apply it to 1.\r\n\r\n917\r\n01:08:15,780 --> 01:08:17,120\r\n这也就是CAR的定义\r\nThat was the definition of car.\r\n\r\n918\r\n01:08:17,700 --> 01:08:22,000\r\n考虑CAR 将其展开 我将得到\r\nSo if I look at car, if I do that, the answer is,\r\n\r\n919\r\n01:08:22,000 --> 01:08:26,000\r\n就是将CAR的参数 将其应用于1\r\nwell, it's that argument, this was the argument to car, applied to 1.\r\n\r\n920\r\n01:08:29,180 --> 01:08:30,440\r\n这又是什么意思呢？\r\nWell, what does that mean?\r\n\r\n921\r\n01:08:30,780 --> 01:08:35,320\r\n在这里的代码体中 我拿1来替换PICK\r\nI take 1, and I substitute it in the body here for this value of pick,\r\n\r\n922\r\n01:08:35,540 --> 01:08:38,340\r\n也就是这个变量的名字 我们得到什么呢？\r\nwhich is the name of the argument, what do I get?\r\n\r\n923\r\n01:08:39,560 --> 01:08:42,840\r\n如果1等于1 那么就得到37\r\nWell, I get the thing that says if 1 equals 1 it's 37,\r\n\r\n924\r\n01:08:43,080 --> 01:08:45,620\r\n如果1等于2 那么就得到49 当然答案就是37\r\nand if 1 equals 2 it's 49, so the answer's 37.\r\n\r\n925\r\n01:08:46,280 --> 01:08:50,660\r\n类似的 如果是CDR的话 也就是将其应用于2 则得到49\r\nAnd similarly, if I'd taken cdr, that would apply it to 2, and I'd get 49.\r\n\r\n926\r\n01:08:51,460 --> 01:08:56,280\r\n正如你们所见 我给你们演示了相当怪异的实现\r\nSo you see, what I've demonstrated is that that completely weird implementation\r\n\r\n927\r\n01:08:56,280 --> 01:08:58,740\r\n完全符合这些公理的CONS CAR CDR实现\r\nof cons, car, and cdr, satisfies the axioms.\r\n\r\n928\r\n01:08:59,820 --> 01:09:04,360\r\n事实上 用这种方法来构建Lisp中所有的数据对象 非常有效\r\nSo it's a perfectly valid way of building, in fact, all of the data objects we're going to see in Lisp.\r\n\r\n929\r\n01:09:05,320 --> 01:09:08,760\r\n如果你愿意的话 这一切东西 都可以凭空构建\r\nSo they all, if you like, can be built on sort of existential nothing.\r\n\r\n930\r\n01:09:09,640 --> 01:09:11,600\r\n就目前为止 你也知道它也正是这样工作的\r\nAnd as far as you know, that's how it works.\r\n\r\n931\r\n01:09:13,880 --> 01:09:16,180\r\n你无法分辨 你如果只是\r\nYou couldn't tell. If all you're ever going to do\r\n\r\n932\r\n01:09:16,960 --> 01:09:19,860\r\n将它们用CONS构建成序对 再用CAR和CDR取出来\r\nwith pairs is construct them with cons and look at them with car and cdr,\r\n\r\n933\r\n01:09:19,860 --> 01:09:22,160\r\n你可能还无法分辨它是如何运作的\r\nyou couldn't possibly tell how this thing works.\r\n\r\n934\r\n01:09:23,920 --> 01:09:26,180\r\n现在 如果我这样说 你们可能会觉得好受一点\r\nNow, it might give you a sort of warm feeling inside if I say,\r\n\r\n935\r\n01:09:26,180 --> 01:09:29,840\r\n我说 实际上因为种种原因 Lisp中有几个基本过程\r\nwell, yeah, in fact, for various reasons there happens to be a primitive\r\n\r\n936\r\n01:09:30,360 --> 01:09:33,200\r\n叫做CONS CAR和CDR 这样不会太吓着你们\r\ncalled cons, car, and cdr, and if it's too scary,\r\n\r\n937\r\n01:09:33,200 --> 01:09:35,820\r\n内部太难以理解 你就不必深究其内部了\r\nif this kind of stuff is too scary, you don't have to look inside of it.\r\n\r\n938\r\n01:09:36,440 --> 01:09:37,660\r\n这样可能会使你感觉好点\r\nSo that might make you feel better,\r\n\r\n939\r\n01:09:38,720 --> 01:09:40,900\r\n但关键点就是 它真是照这样运作的\r\nbut the point is, it really could work this way,\r\n\r\n940\r\n01:09:41,800 --> 01:09:43,920\r\n但是这对系统而言毫无区别\r\nand it wouldn't make any difference to the system at all.\r\n\r\n941\r\n01:09:46,280 --> 01:09:49,740\r\n从某种意义上来说 建立数据抽象不需要数据\r\nSo in some sense, we don't need data at all to build these data abstractions.\r\n\r\n942\r\n01:09:51,380 --> 01:09:53,280\r\n我们可以用过程来完成所有事儿\r\nWe can do everything in terms of procedures.\r\n\r\n943\r\n01:09:54,500 --> 01:09:56,320\r\n恩 那么 为什么我这样做吓到你们了呢？\r\nOK, well, why did I terrify you in this way?\r\n\r\n944\r\n01:09:57,120 --> 01:09:59,880\r\n首先 我想强化大家对抽象的认识\r\nFirst, I really want to reinforce this idea of abstraction,\r\n\r\n945\r\n01:10:01,820 --> 01:10:03,960\r\n也就是我们可以抽象地做事儿\r\nthat you really can do these things abstractly.\r\n\r\n946\r\n01:10:05,880 --> 01:10:12,000\r\n其次 我给大家介绍了将在本课中不断体现的理念\r\nSecondly, I want to introduce an idea we're going to see more and more of in this course,\r\n\r\n947\r\n01:10:13,740 --> 01:10:18,160\r\n也就是数据和过程的边界将变得越来越模糊\r\nwhich is we're going to blur the line between what's data and what's a procedure.\r\n\r\n948\r\n01:10:19,820 --> 01:10:24,600\r\n看到了吧 这个有趣的CONS实现结果是\r\nSee, in this funny implementation it turned out that cons of something\r\n\r\n949\r\n01:10:24,600 --> 01:10:28,640\r\n我们以为是数据 结果却是用一个过程来表示\r\nhappened to be represented in terms of a procedure, even though we think of it as data.\r\n\r\n950\r\n01:10:31,560 --> 01:10:33,400\r\n虽然这里只是一个数学技巧\r\nWhile here that's sort of a mathematical trick,\r\n\r\n951\r\n01:10:34,260 --> 01:10:36,260\r\n当我们将看到的则是\r\nbut one of the things we'll see is that\r\n\r\n952\r\n01:10:36,260 --> 01:10:39,500\r\n一些非常重要的编程技巧\r\na lot of the very important programming techniques that we're going to get to\r\n\r\n953\r\n01:10:40,480 --> 01:10:42,960\r\n都非常依赖于\r\nsort of depend very crucially\r\n\r\n954\r\n01:10:43,280 --> 01:10:48,280\r\n模糊这条传统的界定数据和过程的分界线\r\non blurring this traditional line between what you consider a procedure and what you consider data.\r\n\r\n955\r\n01:10:48,620 --> 01:10:50,680\r\n尤其在下次课 我们将接触得越来越多\r\nWe're going to see more and more of that, especially next time.\r\n\r\n956\r\n01:10:52,580 --> 01:10:53,440\r\n好了 有什么问题吗？\r\nOK, questions?\r\n\r\n957\r\n01:10:54,720 --> 01:10:59,800\r\n学生：如果让系统打印A 会输出什么呢？\r\nAUDIENCE: If you asked the system to print a, what would be the result?\r\n\r\n958\r\n01:11:00,260 --> 01:11:04,960\r\n教授：你想问 如果我让系统打印A\r\nPROFESSOR: The question is, what would happen if I asked the system to print a.\r\n\r\n959\r\n01:11:04,960 --> 01:11:07,900\r\n看看这种表示法 你就知道答案了\r\nGiven this representation, you already know the answer.\r\n\r\n960\r\n01:11:09,620 --> 01:11:17,980\r\n这是一个复合过程A 像上次一样\r\nThe answer is compound procedure a, just like last time.\r\n\r\n961\r\n01:11:21,280 --> 01:11:22,600\r\n系统返回“复合过程”\r\nIt'd say compound procedure.\r\n\r\n962\r\n01:11:25,260 --> 01:11:28,280\r\n说着说得更详细一点 像“复合LAMBDA过程”等等\r\nIt might say a little bit more. It might say compound procedure lambda or something or other,\r\n\r\n963\r\n01:11:29,240 --> 01:11:32,360\r\n这得看我是如何给它命名的 但它归根是个过程\r\ndepending on details of how I named it. But it's a procedure.\r\n\r\n964\r\n01:11:32,800 --> 01:11:36,520\r\n唯一的解释就是我并没有特别地告诉系统\r\nAnd the only reason for that is I haven't told the system anything special\r\n\r\n965\r\n01:11:37,320 --> 01:11:38,700\r\n如何打印这些东西\r\nabout how to print such things.\r\n\r\n966\r\n01:11:39,900 --> 01:11:44,840\r\n实际上 根据系统中CONS实现的不同\r\nNow, it's in fact true that with the actual implementation of cons that to be built in the system,\r\n\r\n967\r\n01:11:44,840 --> 01:11:45,880\r\n它会打印出不同的东西\r\nit would print something else.\r\n\r\n968\r\n01:11:47,000 --> 01:11:48,500\r\n它会打印出这是个序对\r\nIt would print, say, this is a pair.\r\n\r\n969\r\n01:11:53,200 --> 01:11:55,060\r\n学生：你定义CONS后\r\nAUDIENCE: When you define cons,\r\n\r\n970\r\n01:11:57,600 --> 01:11:59,640\r\n你给它传递了几个值\r\nand then you pass it into values,\r\n\r\n971\r\n01:12:00,760 --> 01:12:05,920\r\n它怎么知道该去哪里找这些值 毕竟你可以多次使用CONS\r\nhow does it know where to look for the cons, because you can use cons over and over again?\r\n\r\n972\r\n01:12:06,380 --> 01:12:12,100\r\n它是怎么知道我们希望取出的a和b存储在哪里呢？\r\nHow does it know where to look to know which a and b it's supposed to pull back out?\r\n\r\n973\r\n01:12:12,300 --> 01:12:17,060\r\n可能表达得不是很正确 我只是想问它都存放在哪儿？\r\nI don't know if I'm expressing that quite right. Where is it stored?\r\n\r\n974\r\n01:12:18,720 --> 01:12:20,040\r\n教授：嗯 来想想\r\nPROFESSOR: OK, the question is,\r\n\r\n975\r\n01:12:22,800 --> 01:12:28,020\r\n我先用37和49来构造一个序对 在用1和2又构造一个\r\nI sort of have a cons with a 37 and a 49, and I might make another cons with a 1 and a 2,\r\n\r\n976\r\n01:12:28,340 --> 01:12:30,800\r\n有一个参数为A 有一个参数为B\r\nand I might have one called a, and I might have one called b.\r\n\r\n977\r\n01:12:31,560 --> 01:12:34,500\r\n问题是 系统又是怎么知道的呢？它为什么没有弄混淆呢？\r\nAnd the question is, how does it know? And why don't they get confused?\r\n\r\n978\r\n01:12:35,280 --> 01:12:37,220\r\n这个问题非常好\r\nAnd that's a very good question.\r\n\r\n979\r\n01:12:40,440 --> 01:12:43,580\r\n首先 你需要认定过程是一种对象\r\nSee, you have to really believe that the procedures are objects.\r\n\r\n980\r\n01:12:44,760 --> 01:12:47,920\r\n这就像是说——让我来换个更简单的例子\r\nIt's sort of like saying-- let's try another simpler example.\r\n\r\n981\r\n01:12:49,140 --> 01:12:50,980\r\n我想去求3的平方根\r\nSuppose I ask for the square root of 3.\r\n\r\n982\r\n01:12:55,560 --> 01:12:56,820\r\n我这里用5的平方根来演示\r\nSo I asked for the square root of 5,\r\n\r\n983\r\n01:12:57,920 --> 01:13:01,560\r\n我也可以求20的平方根\r\nand then I ask for the square of 20.\r\n\r\n984\r\n01:13:06,120 --> 01:13:10,080\r\n这可能一点也不困扰你 我可以将SQRT应用于5\r\nYou're probably not the least bit bothered that I can take square root and apply it to 5,\r\n\r\n985\r\n01:13:10,080 --> 01:13:13,080\r\n也可以将其应用于20\r\nand then I can take square root and apply it to 20.\r\n\r\n986\r\n01:13:14,580 --> 01:13:18,600\r\n你知道这没问题 它分得清楚应用于哪个\r\nAnd there's sort of no issue, gee, doesn't it get confused about whether it's working on 5 or 20?\r\n\r\n987\r\n01:13:19,320 --> 01:13:25,120\r\n你觉得过程应该是做些事 所以没有问题\r\nThere's no issue about that because you're thinking of a procedure which goes off and does something.\r\n\r\n988\r\n01:13:26,180 --> 01:13:28,480\r\n从某种方面来说 你问了我一个同样的问题\r\nNow, in some sense you're asking me the same question.\r\n\r\n989\r\n01:13:30,240 --> 01:13:31,580\r\n但它使你困惑\r\nBut it's really bothering you,\r\n\r\n990\r\n01:13:31,580 --> 01:13:33,580\r\n这确实很容易让人困惑\r\nand it's bothering you for a really good reason.\r\n\r\n991\r\n01:13:34,240 --> 01:13:38,080\r\n因为我当我这样写的时候 你知道这是一个过程\r\nBecause when I write that, you're saying gee, this is, I know, sort of a procedure.\r\n\r\n992\r\n01:13:38,080 --> 01:13:41,520\r\n但它不是一个能运行的过程 而是一个定义在这里的过程\r\nBut it's not a procedure that's just running. It's just sort of a procedure sitting there.\r\n\r\n993\r\n01:13:42,220 --> 01:13:46,380\r\n那这个过程为什么时而能有37和49\r\nAnd how can it be that sometimes this procedure has 37 and 49,\r\n\r\n994\r\n01:13:46,380 --> 01:13:50,680\r\n可能又有一个过程有5和6 但它们为什么不搞混呢\r\nand there might be another one which has 5 and 6 in there, and why don't they get confused?\r\n\r\n995\r\n01:13:52,140 --> 01:13:56,200\r\n这里面就有一个非常重要的东西困扰了你\r\nSo there's something very, very important that's bothering you.\r\n\r\n996\r\n01:13:58,640 --> 01:14:00,420\r\n这东西非常关键\r\nAnd it's really crucial to what's going on.\r\n\r\n997\r\n01:14:00,760 --> 01:14:06,740\r\n这就是 过程并不仅仅是动作的集合\r\nIt's, we're suddenly saying that procedures are not just the act of doing something.\r\n\r\n998\r\n01:14:07,980 --> 01:14:10,920\r\n过程是概念实体 是对象\r\nProcedures are conceptual entities, objects,\r\n\r\n999\r\n01:14:11,400 --> 01:14:16,320\r\n如果我(CONS 37 49) 那么就构建好了一个特定的过程\r\nand if I built cons of 37 and 49, that's a particular procedure that sits there.\r\n\r\n1000\r\n01:14:17,680 --> 01:14:20,760\r\n这和(CONS 3 4)的那个不一样\r\nAnd it's different from cons of 3 and 4.\r\n\r\n1001\r\n01:14:21,120 --> 01:14:22,640\r\n这又是一个创立好的过程了\r\nThat's another procedure that sits there.\r\n\r\n1002\r\n01:14:22,640 --> 01:14:23,840\r\n学生：它们都是独立存在的\r\nAUDIENCE: Both of them exist independently.\r\n\r\n1003\r\n01:14:23,840 --> 01:14:25,120\r\n教授：对 独立存在\r\nPROFESSOR: And exists independently.\r\n\r\n1004\r\n01:14:25,280 --> 01:14:27,840\r\n学生：可以通过CAR和CDR被引用\r\nAUDIENCE: And they both can be referenced by car and cdr.\r\n\r\n1005\r\n01:14:28,040 --> 01:14:30,040\r\n教授：它们都可以通过CAR和CDR被引用。\r\nPROFESSOR: And they both would be referenced by car and cdr.\r\n\r\n1006\r\n01:14:30,040 --> 01:14:37,420\r\n我可以增加这个 也可以增加那个\r\nJust like I could increment this, and I could increment that.\r\n\r\n1007\r\n01:14:37,900 --> 01:14:41,380\r\n它们都是对象 这也是我们需要的\r\nThey're objects. And that's sort of where we're going.\r\n\r\n1008\r\n01:14:41,380 --> 01:14:43,320\r\n而你之所以这样问 正是体现了\r\nSee, the fact that you're asking the question shows that\r\n\r\n1009\r\n01:14:43,320 --> 01:14:47,400\r\n你开始思考它蕴含的东西了\r\nyou're really starting to think about the implications of what's going on.\r\n\r\n1010\r\n01:14:47,400 --> 01:14:51,520\r\n过程不仅仅只是说做某件事的行为\r\nIt's the difference between saying a procedure is just the act of doing something.\r\n\r\n1011\r\n01:14:52,620 --> 01:14:55,360\r\n任何过程都是一个存在着的真实对象\r\nAnd a procedure is a real object that has existence.\r\n\r\n1012\r\n01:14:55,960 --> 01:14:57,580\r\n学生：也就是说过程在被构建时\r\nAUDIENCE: So when the procedure gets built,\r\n\r\n1013\r\n01:14:58,040 --> 01:15:00,960\r\nA和B的确切值就被代换进去了\r\nthe actual values are now substituted for a and b--\r\n\r\n1014\r\n01:15:01,580 --> 01:15:02,020\r\n教授：是的\r\nPROFESSOR: That's right.\r\n\r\n1015\r\n01:15:02,020 --> 01:15:04,200\r\n学生：那些以LAMBDA形式存在的过程\r\nAUDIENCE: And then that procedure exists as lambda,\r\n\r\n1016\r\n01:15:04,200 --> 01:15:06,200\r\n而PICK实际上已经被传递进去了\r\nand pick is what's actually passed in.\r\n\r\n1017\r\n01:15:07,360 --> 01:15:09,580\r\n教授：是的 当CONS过程被调用时\r\nPROFESSOR: Yes, when cons gets called,\r\n\r\n1018\r\n01:15:09,580 --> 01:15:13,200\r\nCONS就返回了一个新构造好的过程\r\nand the result of cons is a new procedure that's constructed,\r\n\r\n1019\r\n01:15:13,620 --> 01:15:15,740\r\n而这个新过程有一个叫做PICK的参数\r\nthat new procedure has an argument that's called pick.\r\n\r\n1020\r\n01:15:17,120 --> 01:15:18,460\r\n学生：但是就不再有A和B了\r\nAUDIENCE: But it no longer has an a and b.\r\n\r\n1021\r\n01:15:18,460 --> 01:15:20,520\r\nA和B的确切值在那时就被传递进去了\r\nThe a and b are the actual values that are passed through.\r\n\r\n1022\r\n01:15:20,520 --> 01:15:23,120\r\n教授：根据代换模型 是这样的\r\nPROFESSOR: And it has-- right, according to the substitution model,\r\n\r\n1023\r\n01:15:23,120 --> 01:15:25,660\r\n现在它不再具有这些任意的名字A和B\r\nwhat it now has is not those arbitrary names a and b,\r\n\r\n1024\r\n01:15:25,960 --> 01:15:28,480\r\n取而代之的则是37和49\r\nit somehow has that 37 and 49 in there.\r\n\r\n1025\r\n01:15:31,200 --> 01:15:33,100\r\n但你是对的 把这件事想清楚很困难\r\nBut you're right, that's a hard thing to think about it,\r\n\r\n1026\r\n01:15:33,100 --> 01:15:35,240\r\n这同我们之前对过程的认识有所不同\r\nand it's different from the way you've been thinking about procedures.\r\n\r\n1027\r\n01:15:36,100 --> 01:15:40,880\r\n学生：如果我再次调用(CONS 37 49) 是否得到了一个不同的[听不清]\r\nAUDIENCE: And if I have again cons of 37 and 49, it's a different [UNINTELLIGIBLE]?\r\n\r\n1028\r\n01:15:40,880 --> 01:15:47,860\r\n教授：如果你再次调用(CONS 37 49)\r\nPROFESSOR: And if you make another cons of 37 and 49,\r\n\r\n1029\r\n01:15:51,420 --> 01:15:53,700\r\n你就陷入了一个深刻的哲学问题\r\nyou're into a wonderful philosophical problem,\r\n\r\n1030\r\n01:15:53,700 --> 01:15:58,500\r\n这个将是我们整个课程中段将讨论的问题\r\nwhich is going to be what the lecture about halfway through this course is about.\r\n\r\n1031\r\n01:15:59,720 --> 01:16:02,780\r\n也就是说 我调用(CONS 37 49) 然后我再调用一次\r\nWhich is, if I cons 37 and 49, and I do it again,\r\n\r\n1032\r\n01:16:02,980 --> 01:16:05,460\r\n这两者是同一个东西还是不同的东西呢？\r\nis that the same thing, or is it a different thing?\r\n\r\n1033\r\n01:16:06,180 --> 01:16:08,720\r\n我又该如何区别它们呢？这又在什么时候产生影响呢？\r\nAnd how could you tell? And when could it possibly matter?\r\n\r\n1034\r\n01:16:09,920 --> 01:16:19,620\r\n这就像说 这个和这个是同一个东西么？\r\nAnd that's sort of like saying, is that the same thing as this?\r\n\r\n1035\r\n01:16:20,840 --> 01:16:22,440\r\n那这个和这个呢？\r\nOr is this the same thing as that?\r\n\r\n1036\r\n01:16:23,480 --> 01:16:24,660\r\n这都是同一种问题\r\nIt's the same kind of question.\r\n\r\n1037\r\n01:16:24,660 --> 01:16:27,520\r\n这将是一个非常非常深刻的问题\r\nAnd that's a very, very deep question.\r\n\r\n1038\r\n01:16:27,520 --> 01:16:30,520\r\n我没法在一小时内讲清楚 但我们以后会讨论\r\nAnd I can't answer in less than an hour. But we will.\r\n\r\n1039\r\n01:16:37,600 --> 01:16:40,940\r\nMIT OpenCourseWare\r\nhttp://ocw.mit.edu\r\n\r\n1040\r\n01:16:41,100 --> 01:16:47,660\r\n本项目主页\r\nhttps://github.com/FoOTOo/Learning-SICP\r\n"
  },
  {
    "path": "SrtCN/lec3a.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:03,120\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:04,400 --> 00:00:08,026\n翻译&&时间轴：邓雄飞（Dysprosium）、Savior Michael\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:08,060 --> 00:00:12,160\n特别感谢：裘宗燕教授\n\n4\n00:00:12,370 --> 00:00:16,320\nHenderson-Escher的例子\nHenderson-Escher Example\n\n5\n00:00:20,940 --> 00:00:23,860\n上节课我们讨论了复合数据\nPROFESSOR: Well, last time we talked about compound data,\n\n6\n00:00:24,946 --> 00:00:29,740\n其中有两个关键点\nand there were two main points to that business.\n\n7\n00:00:29,740 --> 00:00:32,480\n首先 有一种数据抽象的方法学\nFirst of all, there was a methodology of data abstraction,\n\n8\n00:00:32,940 --> 00:00:39,100\n其要点是将数据的使用\nand the point of that was that you could isolate the way that data objects are used\n\n9\n00:00:40,060 --> 00:00:41,500\n和表示分离开来\nfrom the way that they're represented:\n\n10\n00:00:41,550 --> 00:00:45,200\n比如说 我们可以与一个叫做George的人“签订契约”\nthis idea that there's this guy, George, and you go out make a contract with him;\n\n11\n00:00:45,200 --> 00:00:47,480\n让他负责数据的表示\nand it's his business to represent the data objects;\n\n12\n00:00:47,480 --> 00:00:49,360\n而当我们使用这些数据的时候\nand at the moment you are using them,\n\n13\n00:00:49,360 --> 00:00:51,360\n不需要替George操心他是如何完成数据表示的工作的\nyou don't think about George's problem.\n\n14\n00:00:51,980 --> 00:00:58,440\n其次 Lisp中有一种特殊的方式把对象连接在一起\nAnd then secondly, there was this particular way that Lisp has of gluing together things\n\n15\n00:00:58,940 --> 00:01:00,520\n就是构成“序对”\nto form objects called pairs,\n\n16\n00:01:00,520 --> 00:01:03,540\n这是通过CONS CAR CDR实现的\nand that's done with cons, car and cdr.\n\n17\n00:01:03,540 --> 00:01:07,160\n而CONS CAR CDR本身是如何实现的 这不重要\nAnd the way that cons, car and cdr are implemented is basically irrelevant.\n\n18\n00:01:07,160 --> 00:01:10,020\nGeorge的任务就是如何构建这些东西\nThat's sort of George's problem of how to build those things.\n\n19\n00:01:10,020 --> 00:01:11,160\n可以将它们实现为基本过程\nIt could be done as primitives.\n\n20\n00:01:11,160 --> 00:01:13,800\n也可以利用一些奇怪的过程来实现\nIt could be done using procedures in some weird way,\n\n21\n00:01:13,800 --> 00:01:15,220\n但是我们不用操心这些\nbut we're not going to worry about that.\n\n22\n00:01:16,020 --> 00:01:19,660\n举个例子 我们来看下有理数算术\nAnd as an example, we looked at rational number arithmetic.\n\n23\n00:01:19,660 --> 00:01:21,500\n看下向量\nWe looked at vectors,\n\n24\n00:01:21,500 --> 00:01:24,180\n我们简单回顾一下向量\nand here's just a review of vectors.\n\n25\n00:01:24,180 --> 00:01:27,640\n这里有个对两个向量求和的操作\nHere's an operation that takes the sum of of two vectors,\n\n26\n00:01:27,640 --> 00:01:33,320\n我们想要把向量v1和v2相加\nso we want to add this vector, v1, and this vector, v2, and we get the sum.\n\n27\n00:01:34,460 --> 00:01:40,840\n它们的和也是一个向量 其坐标是两个向量的坐标的和\nAnd the sum is the vector whose coordinates are the sum of the coordinates of the pieces you're adding.\n\n28\n00:01:41,280 --> 00:01:45,660\n所以 定义(+VECT V1 V2)为\nSo I can say, to define make-vect, right, to add two vectors\n\n29\n00:01:45,660 --> 00:01:51,720\n我创建一个向量 其X坐标是两向量X坐标的和\nI make a vector, whose x coordinate is the sum of the two x coordinates,\n\n30\n00:01:52,100 --> 00:01:54,820\n而Y坐标是两向量Y坐标的和\nand whose y coordinate is the sum of the two y coordinates.\n\n31\n00:01:56,060 --> 00:02:04,100\n类似地 我们也可以定义一个缩放向量的操作\nAnd then similarly, we could have an operation that scales vectors,\n\n32\n00:02:04,940 --> 00:02:12,660\n这里的SCALE过程是用数字S乘以向量V\nso here's a procedure scale that multiplies a vector, v, by some number, s.\n\n33\n00:02:13,080 --> 00:02:16,140\n向量V从这里到这里\nSo here's v, v goes from there to there\n\n34\n00:02:16,320 --> 00:02:20,220\n我放大V 得到了与原来同向但更长的向量\nand I scale v, and I get a vector in the same direction that's longer.\n\n35\n00:02:21,560 --> 00:02:24,260\n为了缩放向量 我需要通过缩放坐标来实现\nAnd again, to scale a vector, I multiply the successive coordinates.\n\n36\n00:02:24,260 --> 00:02:30,220\n所以我构建了一个向量 它的X坐标是原向量X坐标的S倍\nSo I make a vector, whose x coordinate is the scale factor times the x coordinate\n\n37\n00:02:30,560 --> 00:02:33,540\n同时 它的Y坐标是原来向量Y坐标的S倍\nand whose y coordinate is the scale factor times the y coordinate.\n\n38\n00:02:33,540 --> 00:02:40,280\n上述两个操作都是利用了向量的表示来实现的\nSo those are two operations that are implemented using the representation of vectors.\n\n39\n00:02:40,280 --> 00:02:45,020\n而这种向量的表示 我们则可以用序对来实现\nAnd the representation of vectors, for instance, is something that we can build in terms of pairs.\n\n40\n00:02:45,340 --> 00:02:51,280\n因此George需要为我们提供MAKE-VECTOR、XCOR和YCOR\nSo George has gone out and implemented for us make-vector and x coordinate and y coordinate,\n\n41\n00:02:53,020 --> 00:02:57,980\n他可以使用CONS CAR CDR来实现\nand this could be done, for instance, using cons,car and cdr;\n\n42\n00:02:58,880 --> 00:03:06,780\n但是注意 我这里用了一个略微不同的方式\nand notice here, I wrote this in a slightly different way.\n\n43\n00:03:08,040 --> 00:03:11,000\n这个过程我们之前看过 其中我讲过\nThe procedures we've seen before, I've said something like\n\n44\n00:03:11,140 --> 00:03:16,220\n(MAKE-VECTOR X Y)也就是(CONS X Y)\nsay, make-vector of x and y: cons of x and y.\n\n45\n00:03:16,220 --> 00:03:17,980\n而我这里简单定义MAKE-VECTOR为CONS\nAnd here I just wrote make-vector cons.\n\n46\n00:03:17,980 --> 00:03:20,480\n这就与之前有些不同了\nAnd that means something slightly different.\n\n47\n00:03:20,480 --> 00:03:26,220\n之前我们我们把MAKE-VECTOR定义为需要两个参数的过程\nPreviously we'd say, define make-vector to be a procedure that takes two arguments, x and y,\n\n48\n00:03:26,220 --> 00:03:28,040\n效果是(CONS X Y)\nand does cons of x and y.\n\n49\n00:03:28,040 --> 00:03:34,120\n这里 我就把MAKE-VECTOR定义为CONS\nAnd here I am saying define make-vector to be the thing that cons is,\n\n50\n00:03:35,180 --> 00:03:39,660\n这跟我们之前使用的方式基本上是一样的\nand that's almost the same as the other way we've been writing things.\n\n51\n00:03:39,660 --> 00:03:46,580\n大家要习惯于“过程也是对象 而且你可以给他们命名”这种想法\nAnd I just want you to get used to the idea that procedures can be objects, and that you can name them.\n\n52\n00:03:48,700 --> 00:03:51,800\n这些就是向量的表示方法了\nOK, well there's vector representation, and again,\n\n53\n00:03:51,800 --> 00:03:55,680\n如果仅仅是那样 那就太无趣了\nif that was all there was to it,this would all be pretty boring.\n\n54\n00:03:57,020 --> 00:04:02,160\n要记住 要点是我们不仅可以通过使用CONS将数字组合成序对\nAnd the point is, remember, that you can use cons to glue together not just numbers to form pairs,\n\n55\n00:04:02,160 --> 00:04:04,160\n也可以组合任何东西\nbut to glue together arbitrary things.\n\n56\n00:04:05,200 --> 00:04:11,600\n例如 如果我想表示一个线段\nSo for instance, if we'd like to represent a line segment,\n\n57\n00:04:11,600 --> 00:04:15,640\n一个以某个向量为起点的线段\nsay the line segment that goes from a certain vector:\n\n58\n00:04:16,060 --> 00:04:28,300\n比如从向量(2,3)所代表的起点到向量(5,1)所代表的终点的线段\nsay, the segment from the vector 2,3 to the point represented by the vector 5,1.\n\n59\n00:04:28,300 --> 00:04:31,820\n如果我们想表示这条线段\nIf we want to represent that line segment,\n\n60\n00:04:33,260 --> 00:04:36,200\n那么我们可以构建一个序对的序对\nthen we can build that as a pair of pairs.\n\n61\n00:04:40,720 --> 00:04:42,940\n这样我们就可以表示一条线段了\nSo again, we can represent line segments.\n\n62\n00:04:42,940 --> 00:04:47,340\n我们可以编写一个使用CONS构造线段的构造函数\nWe can make a constructor that makes a segment using cons,\n\n63\n00:04:47,980 --> 00:04:51,600\n以及 析取出线段起点、终点的选择函数\nselects out the start of a segment, selects out the end point of the segment;\n\n64\n00:04:55,240 --> 00:04:59,760\n那么如果我们剥开抽象层一探究竟\nand then if we actually look at that, if we peel away the abstraction layers,\n\n65\n00:04:59,880 --> 00:05:02,100\n就会发现线段不过是 序对组成的序对\nand see what's that really is a pair of pairs,\n\n66\n00:05:04,660 --> 00:05:06,220\n它还是一个序对\nwe'd say well that's a pair.\n\n67\n00:05:06,220 --> 00:05:08,220\n这里有个线段\nHere's the segment.\n\n68\n00:05:10,000 --> 00:05:16,720\n它的CAR部分是个序对 CDR部分也是个序对\nIt's car, right, it's car pointer is a pair, and it's cdr is also a pair,\n\n69\n00:05:18,320 --> 00:05:25,540\n它的CAR部分是由2和3构成的序对\nand then what the car is--here's the car, that itself is a pair of 2 and 3.\n\n70\n00:05:26,020 --> 00:05:28,080\nCDR部分则由5和1构成的序对\nAnd similarly the cdr is a pair of 2 and 3.\n\n71\n00:05:28,160 --> 00:05:29,240\n这里我再提醒大家一下\nAnd let me remind you again\n\n72\n00:05:29,320 --> 00:05:33,460\n好多人认为如果我箭头向下画的话\nthat a lot of people have some idea that if I'd taken this arrow and somehow\n\n73\n00:05:33,800 --> 00:05:36,900\n会有其它的含意\nwritten it to point down, that would mean something else.\n\n74\n00:05:36,980 --> 00:05:38,280\n这是不对的\nThat's irrelevant.\n\n75\n00:05:38,580 --> 00:05:43,900\n箭头指示的是对象间如何连接 它指向水平或竖直方向都是无关紧要的\nIt's only how these are connected and not whether this arrow happens to go vertically or horizontally.\n\n76\n00:05:47,480 --> 00:05:52,180\n还要提醒一下 序对是具有闭包性质的\nAnd again just to remind you, there was this notion of closure.\n\n77\n00:05:52,940 --> 00:06:05,620\n闭包性质使我们可以构建更复杂的东西 而不仅仅是简单的序对\nSee, closure was the thing that allowed us to start building up complexity, that didn't trap us in pairs.\n\n78\n00:06:06,640 --> 00:06:15,240\n在这里我要特别指出 在我们用CONS构建出来的序对的基础上\nParticularly what I mean is the things that we make, having combined things using cons to get a pair,\n\n79\n00:06:16,440 --> 00:06:22,640\n我们也可以进一步用CONS来构造更复杂的对象\nthose things themselves can be combined using cons to make more complicated things.\n\n80\n00:06:23,280 --> 00:06:31,980\n或者用数学家的话说 Lisp中的数据对象在CONS运算下是封闭的\nOr as a mathematician might say, the set of data objects in Lisp is closed under the operation of forming pairs.\n\n81\n00:06:33,820 --> 00:06:36,340\n这个性质使我们能够构造更加复杂的数据对象\nThat's the thing that allows us to build complexity.\n\n82\n00:06:36,340 --> 00:06:38,040\n这个似乎是显然的 但是要记住\nAnd that seems obvious, but remember\n\n83\n00:06:39,060 --> 00:06:42,460\n人们使用的编程语言中有很多东西并不是封闭的\na lot of the things in the computer languages that people use are not closed.\n\n84\n00:06:42,460 --> 00:06:48,060\n举例来说 Basic和Fortran中的构造数组操作 就不是封闭的\nSo for example, forming arrays in Basic and Fortran is not a closed operation,\n\n85\n00:06:48,080 --> 00:06:51,940\n因为 虽然你可以用数字、字符或字符串等来构造数组\nbecause you can make an array of numbers or character strings or something,\n\n86\n00:06:52,040 --> 00:06:54,180\n但是你不能创建数组的数组\nbut you can't make an array of arrays.\n\n87\n00:06:54,640 --> 00:06:56,680\n当考察某种组合的方法时\nAnd when you look at means of combination\n\n88\n00:06:57,600 --> 00:07:02,780\n你应该考察该组合方法是否封闭\nyou should be asking yourself whether things are closed under that means of combination.\n\n89\n00:07:05,060 --> 00:07:08,260\n不管怎样 因为我们可以构造序对的序对\nWell in any case, because we can form pairs of pairs,\n\n90\n00:07:08,860 --> 00:07:12,780\n我们就可以用序对将数据以各种各样的方式组合起来\nwe can start using pairs to glue things together in all sorts of different ways.\n\n91\n00:07:14,020 --> 00:07:18,260\n比如我想要组合四个数 —— 1 2 3 4\nSo for instance if I'd like to glue together the four things, 1, 2, 3 and 4,\n\n92\n00:07:18,260 --> 00:07:19,820\n我有很多方法\nthere are a lot of ways I can do it.\n\n93\n00:07:20,740 --> 00:07:26,120\n比如 像构造线段那样 我可以构造一个序对\nI could, for example, like we did with that line segment, i could make a pair\n\n94\n00:07:29,020 --> 00:07:36,880\n它是((1 2) (3 4)) 对吧？\nthat had a 1 and a 2 and a 3 and a 4, right?\n\n95\n00:07:36,880 --> 00:07:40,060\n或者如果我喜欢 我可以像这样做\nOr if I liked, I could do something like this.\n\n96\n00:07:40,060 --> 00:07:45,520\n我构造一个序对 它的CAR部分也是一个序对\nI could make a pair, whose first thing is a pair,\n\n97\n00:07:46,440 --> 00:07:53,200\n这个序对的CAR部分为1 而CDR部分为由2、3构成的序对\nwhose car is 1, and his cdr is itself a pair that has the 2 and the 3\n\n98\n00:07:53,260 --> 00:07:55,080\n最后 我把4放在这里\nand then I could put the 4 up here.\n\n99\n00:07:56,920 --> 00:08:02,160\n所以你可以看到 组合对象的方式有很多种\nSo you see, there are a lot of different ways that I can start using pairs to glue things together,\n\n100\n00:08:02,160 --> 00:08:07,740\n因此就有必要建立一些统一的约定\nand so it'll be a good idea to establish some kind of conventions,right,\n\n101\n00:08:07,740 --> 00:08:11,580\n使我们能够用某种的通用的方式处理数据\nthat allow us to deal with this thing in some conventional way,\n\n102\n00:08:11,580 --> 00:08:14,000\n而不用总是针对具体问题做一些生硬的选择\nso we're not constantly making an ad hoc choice.\n\n103\n00:08:15,940 --> 00:08:19,040\nLisp里面就有这样一种约定\nAnd Lisp has a particular convention\n\n104\n00:08:20,740 --> 00:08:25,820\n这个约定将一系列的东西表示成一个序对组成的链\nfor representing a sequence of things as, essentially, a chain of pairs,\n\n105\n00:08:26,780 --> 00:08:28,180\n而这样一个数据序列就叫做一个“表”\nand that's called a List.\n\n106\n00:08:34,720 --> 00:08:40,500\n表本质上就是Lisp用来表示序列数据的一个约定而已\nAnd what a list is is essentially just a convention for representing a sequence.\n\n107\n00:08:40,700 --> 00:08:47,380\n我可以使用序对的序列来表示序列 1 2 3 4\nI would represent the sequence 1, 2, 3 and 4 by a sequence of pairs.\n\n108\n00:08:48,260 --> 00:08:54,680\n我把1放在这里 它的CDR指向另一个序对\nI'd put 1 here and then the cdr of this would point to another pair\n\n109\n00:08:59,200 --> 00:09:01,400\n这个序对的CAR部分是序列中的下一个数\nwhose car was the next thing in the sequence,\n\n110\n00:09:01,520 --> 00:09:03,420\n并且它的CDR指向了另一个序对\nand the cdr would point to another pair\n\n111\n00:09:05,440 --> 00:09:07,300\n它的CAR部分是序列的再下一个数\nwhose car was the next thing in the sequence--\n\n112\n00:09:07,360 --> 00:09:08,440\n这个是3\nso there's 3--\n\n113\n00:09:08,440 --> 00:09:09,740\n以此类推\nand then another one.\n\n114\n00:09:09,740 --> 00:09:13,220\n所以 序列中的每一个元素都对应着一个序对\nSo for each item in the sequence, I'll get a pair.\n\n115\n00:09:15,820 --> 00:09:18,320\n而当这个序列中没有其它元素时，我用一个特殊的标记\nAnd now there are no more, so I put a special marker\n\n116\n00:09:20,720 --> 00:09:22,740\n来表示列表中没有元素了\nthat means there's nothing more in the List.\n\n117\n00:09:24,140 --> 00:09:34,640\n好 这就是将序列中的元素组合起来的一种约定方式\nOK, so that's a conventional way to glue things together if you want to represent a sequence, right.\n\n118\n00:09:34,640 --> 00:09:37,980\n而它其实就是一堆序对\nAnd what it is is a bunch of pairs,\n\n119\n00:09:39,400 --> 00:09:44,800\n每个序对中的CAR部分就是我们想要组合到一起的元素\nthe successive cars of each pair are the items that you want to glue together,\n\n120\n00:09:46,000 --> 00:09:48,460\n这些序对的CDR部分则指向下一个序对\nand the cdr pointer points to the next pair.\n\n121\n00:09:50,020 --> 00:09:56,040\n现在 如果我想要构造它 我需要向Lisp中输入\nNow if I actually wanted to construct that, what I would type into Lisp is this:\n\n122\n00:09:56,620 --> 00:09:58,760\n我会像这样来构造\nI'd actually construct that as saying, well this thing is\n\n123\n00:09:59,220 --> 00:10:15,280\n(CONS 1 (CONS 2 (CONS 3 (CONS 4 NIL))))\nthe cons of 1 onto the cons of 2 onto the cons of 3 onto\nthe cons of 4 onto, well, this thing nil.\n\n124\n00:10:15,280 --> 00:10:20,000\nNIL是序列末尾标志的名字\nAnd what nil is is a name for the end of List marker.\n\n125\n00:10:20,800 --> 00:10:23,240\n它是一个特殊的名字 标识以达到表的末尾\nIt's a special name, which means this is the end of the List.\n\n126\n00:10:26,240 --> 00:10:30,260\n好 这就是如何构造一个表\nOK, so that's how I would actually construct that.\n\n127\n00:10:37,546 --> 00:10:41,400\n如果每次构造一个表时 都要输入像\nOf course, it's a terrible drag to constantly have to write something like\n\n128\n00:10:41,453 --> 00:10:45,180\n(CONS 1 (CONS 2 (CONS 3...的话 将会非常费力\nthe cons of 1 onto the cons of 2 onto the cons of 3, whenever you want to make this thing.\n\n129\n00:10:45,180 --> 00:10:50,100\n因此Lisp提供了一种叫做LIST的操作\nSo Lisp has an operation that's called LIST,\n\n130\n00:10:53,700 --> 00:10:57,720\nLIST其实是这种嵌套CONS的缩写\nand List is just an abbreviation for this nest of conses.\n\n131\n00:10:58,960 --> 00:11:06,320\n它可以让我用(LIST 1 2 3 4)来构造表\nSo I could say, I could construct that by saying that is the List of 1, 2, 3 and 4.\n\n132\n00:11:07,780 --> 00:11:11,740\n这只是另外一种方式v一个语法糖\nAnd all this is is another way, a piece of syntactic sugar,\n\n133\n00:11:11,940 --> 00:11:14,760\n用来简便地书写嵌套的CONS\na more convenient way for writing that chain of conses--\n\n134\n00:11:14,760 --> 00:11:17,840\n(CONS (CONS (CONS (CONS NIL))))\ncons of cons of cons of cons of cons of cons onto nil.\n\n135\n00:11:18,480 --> 00:11:39,780\n举例来说 我将构造一个表(1 2 3 4) 并把它叫做1-TO-4\nSo for example, I could build this thing and say, I'll define 1-TO-4 to be the List of 1, 2, 3 and 4.\n\n136\n00:11:47,960 --> 00:11:53,020\n注意使用这种简便写法的结果\nOK, well notice some of the consequences of using this convention.\n\n137\n00:11:53,800 --> 00:11:56,920\n首先 如果我有这个表(1 2 3 4)\nFirst of all if I have this List, this 1, 2, 3 and 4,\n\n138\n00:11:57,360 --> 00:12:02,640\n表的CAR把部分就是这个表的第一个元素 对吧？\nthe car of the whole thing is the first element in the List, right.\n\n139\n00:12:04,060 --> 00:12:05,280\n那么 如何获得元素2呢？\nHow do I get 2?\n\n140\n00:12:05,280 --> 00:12:23,940\n2应该是1-TO-4的CDR部分的CAR部分\nWell, 2 would be the car of the cdr of this thing 1-TO-4, it would be 2, right.\n\n141\n00:12:23,980 --> 00:12:29,480\n它的CDR是这个\nI take this thing, I take the cdr of it, which is this much,\n\n142\n00:12:29,820 --> 00:12:31,680\n而它的CAR部分是2\nand the car of that is 2,\n\n143\n00:12:32,580 --> 00:12:47,420\n同理 1-TO-4的CDR的CDR的CAR部分\nand then similarly, the car of the cdr of the cdr of 1-TO-4, cdr, cdr, car--\n\n144\n00:12:47,420 --> 00:12:51,360\n是3 以此类推\nwould give me 3, and so on.\n\n145\n00:12:52,680 --> 00:12:55,840\n我们来看下屏幕\nLet's take a look at that on the computer screen for a second.\n\n146\n00:12:57,500 --> 00:13:11,180\n我定义一个表(1 2 3 4) 命名为1-TO-4\nI could come up to List, and I could type define 1-TO-4 to be the List of 1, 2, 3 and 4, right.\n\n147\n00:13:13,780 --> 00:13:21,280\n我这样写 计算机返回定义完成 这个就是1-TO-4的定义\nAnd I'll tell that to Lisp, and it says, fine, that's the definition of 1-TO-4.\n\n148\n00:13:22,300 --> 00:13:36,740\n我问 比如 1-TO-4的CDR的CDR的CAR\nAnd I could say, for instance, what's the car of the cdr of the cdr of 1-TO-4, close paren, close paren.\n\n149\n00:13:38,340 --> 00:13:42,420\n嗯 它是3\nRight, so the car of the cdr of the cdr would be 3.\n\n150\n00:13:44,080 --> 00:13:50,080\n或者我问 1-TO-4是什么\nRight, or I could say, what's 1-TO-4 itself.\n\n151\n00:13:51,260 --> 00:13:57,220\nLisp输出的是用括号包围的 (1 2 3 4)\nAnd you see what Lisp typed out is 1, 2, 3, 4, enclosed in parentheses,\n\n152\n00:13:57,220 --> 00:14:02,120\n用括号将表中的元素包围起来的这种记号\nand this notation, typing the elements of the List enclosed in parentheses\n\n153\n00:14:02,120 --> 00:14:08,900\n通常用来打印输出表示序列的序对链\nis Lisp's conventional way for printing back this chain of pairs that represents a sequence.\n\n154\n00:14:08,900 --> 00:14:17,140\n又比如 我问1-TO-4的CDR部分是什么\nSo for example, if I said, what's the cdr of 1-TO-4,\n\n155\n00:14:19,300 --> 00:14:21,120\n结果是表的剩余部分\nthat's going to be the rest of the List.\n\n156\n00:14:21,320 --> 00:14:26,960\n这是原表首元素所指向的序对 新序列从2开始\nThat's the thing pointed to by the first pair, which is, again, a sequence that starts off with 2.\n\n157\n00:14:28,520 --> 00:14:37,740\n比如 1-TO-4的CDR的CDR部分是什么\nOr for example, I go off and say, what's the cdr of the cdr of 1-TO-4;\n\n158\n00:14:43,240 --> 00:14:44,680\n返回(3 4)\nthen that's 3,4.\n\n159\n00:14:44,820 --> 00:14:59,660\n或者 1-TO-4的CDR的CDR的CDR的CDR部分是什么\nOr if I say, what's the cdr of the cdr of the cdr of the cdr of 1-TO-4,\n\n160\n00:15:04,740 --> 00:15:10,460\n我们看一下表的尾指针 Lisp返回()\nand I'm down there looking at the end of List pointer itself, and Lisp prints that as just open paren, close paren.\n\n161\n00:15:10,960 --> 00:15:13,480\n你们可以认为这是一个空表\nYou can think of that as a List with nothing in there.\n\n162\n00:15:14,120 --> 00:15:21,380\n我求取 1-TO-4的CDR的CDR的CDR部分\nAll right, see at the end what I did there was I looked at the cdr of the cdr of the cdr of 1-TO-4,\n\n163\n00:15:21,420 --> 00:15:25,200\n这就只剩下表尾指针本身\nand I'm just left with the end of List pointer itself.\n\n164\n00:15:25,200 --> 00:15:27,200\n它的输出是()\nAnd that gets printed as open close.\n\n165\n00:15:34,140 --> 00:15:39,980\n好了 这是处理表的一种常见方式\nAll right, well that's a conventional way you can see for working down a List\n\n166\n00:15:41,500 --> 00:15:43,440\n也就是不断地取CDR部分\nby taking successive cdrs of things.\n\n167\n00:15:43,440 --> 00:15:45,000\n这个叫做表的CDRING\nIt's called cdring down a List.\n\n168\n00:15:46,640 --> 00:15:49,780\n当然手写这些CDR非常费劲\nAnd of course it's pretty much of a drag to type all those cdrs by hand.\n\n169\n00:15:49,780 --> 00:15:52,240\n我们没必要这么做 我们编写程序来这么做\nYou don't do that. You write procedures that do that.\n\n170\n00:15:52,960 --> 00:15:59,100\n事实上 Lisp中非常普遍的事情是写一些过程\nAnd in fact one very, very common thing to do in Lisp is to write procedures that,\n\n171\n00:15:59,850 --> 00:16:06,540\n表中所有元素进行某种操作 得到的是由结果构成的表\nsort of, take a List of things and do something to every element in List, and return you a List of the results.\n\n172\n00:16:07,420 --> 00:16:11,920\n比如 我写一个SCALE-LIST的过程\nSo what I mean for example, is I might write a procedure called Scale-List,\n\n173\n00:16:16,800 --> 00:16:25,240\n我要用SCALE-LIST将表1-TO-4放大10倍\nand Scale-List I might say I want to scale by 10 the entire List 1-TO-4,\n\n174\n00:16:26,660 --> 00:16:35,320\n那么它应该返回表(10 20 30 40)\nand that would return for me the List 10, 20, 30, 40.\n\n175\n00:16:38,250 --> 00:16:40,250\n没错 它返回一个表\nRight, it returns List, and\n\n176\n00:16:44,490 --> 00:16:49,300\n我们可以猜想到这当中采用了某种递归策略\nwell you can see that there's going to be some kind of recursive strategy for doing it.\n\n177\n00:16:49,300 --> 00:16:51,300\n我应该如何编写这个过程呢？\nHow would I actually write that procedure?\n\n178\n00:16:52,520 --> 00:16:59,800\n如果要构建一个每个元素都乘以10的列表\nThe idea would be, well if you'd like to build up a List where you've multiplied every element by 10,\n\n179\n00:17:00,440 --> 00:17:04,840\n需要做的是—假设已经得到了结果表的剩余元素\nwhat you'd say is well you imagine that you'd taken the rest of the List--\n\n180\n00:17:05,860 --> 00:17:08,420\n也就是表的CDR部分\nright, the thing represented by the cdr of the List,\n\n181\n00:17:08,420 --> 00:17:14,160\n这个子表中的每个元素都是原来元素乘以10\nand suppose I'd already built a List where each of these was multiplied by 10--\n\n182\n00:17:16,060 --> 00:17:19,680\n这是SCALE-LIST对表CDR部分作用的结果\nthat would be Scale-List of the cdr of the List.\n\n183\n00:17:20,120 --> 00:17:23,820\n我需要做的 就只有用表的CAR部分乘以10\nAnd then all I have to do is multiply the car of the List by 10,\n\n184\n00:17:24,890 --> 00:17:27,240\n然后用CONS将它和剩余部分连接起来 并返回这个列表\nand then cons that onto the rest, and I'll get a List.\n\n185\n00:17:29,020 --> 00:17:33,090\n类似地 为了缩放子表 我得先缩放子表的CDR部分\nRight and then similarly, to have scaled the cdr of the List, I'll scale the cdr of that\n\n186\n00:17:33,300 --> 00:17:36,200\n并将其与2*10连接起来\ncons onto that 2 multiplied by 10.\n\n187\n00:17:36,420 --> 00:17:41,160\n最终 当我处理到表尾时 这里就只剩表尾指针了\nAnd finally when I get all the way down to the end, and I only have this end of List pointer.\n\n188\n00:17:41,720 --> 00:17:45,280\n它叫做NIL 我就直接返回表尾指针\nAll right, this thing whose name is nil-- well I just returned an end of List pointer.\n\n189\n00:17:45,540 --> 00:17:47,680\n所以这就是这个过程的递归策略\nSo there's a recursive strategy for doing that.\n\n190\n00:17:47,680 --> 00:17:50,520\n这个过程就是这样\nHere's the actual procedure that does that.\n\n191\n00:17:50,960 --> 00:17:55,040\n这个例子就是对表做CDRING操作的通用策略\nRight, this is an example of the general strategy of cdr-ing down a List and\n\n192\n00:17:55,660 --> 00:17:58,240\n也就是所谓的“通过CONS组合结果”\nso called cons-ing up the result, right.\n\n193\n00:17:58,240 --> 00:18:06,040\n那么 对表L缩放S倍 我该如何做呢？\nSo to Scale a List l by some scale factor s, what do I do?\n\n194\n00:18:06,040 --> 00:18:10,400\n首先得做判断 Lisp中有个叫NULL?的谓词\nWell there's a test, and Lisp has the predicate called null.\n\n195\n00:18:10,400 --> 00:18:13,220\nNULL?判断对象是否为表尾\nNull means is this thing the end of List pointer,\n\n196\n00:18:13,900 --> 00:18:17,160\n或者说 对象是否为空表\nor another way to think of that is are there any elements in this List, right.\n\n197\n00:18:18,170 --> 00:18:23,000\n任何情况下 当我处理到表尾时 我就将其返回\nBut in any case if I'm looking at the end of List pointer, then I just return the end of List pointer.\n\n198\n00:18:23,650 --> 00:18:24,600\n简单地返回NIL\nI just return nil,\n\n199\n00:18:24,940 --> 00:18:35,140\n否则 我就用CONS把列表中的第一个元素经过操作（缩放）后的结果\notherwise I cons together the result of doing what I'm going to do to the first element in the List,\n\n200\n00:18:35,540 --> 00:18:39,290\n就是说 取L的CAR部分 然后用它乘以S\nnamely taking the car of l and multiplying it by s,\n\n201\n00:18:40,360 --> 00:18:46,340\n然后我就用CONS将这个结果 与用递归形式缩放后的表的剩下部分 连接在一起\nand I cons that onto recursively scaling the rest of the List.\n\n202\n00:18:49,980 --> 00:18:52,180\n再说一次 总体的思想是\nOK, so again, the general idea is that you\n\n203\n00:18:52,220 --> 00:18:56,090\n你要用递归的方式处理表中的剩余元素 即表的CDR部分\nyou recursively do something to the rest of the List, to the cdr of the List,\n\n204\n00:18:56,480 --> 00:19:01,160\n然后你用CONS将那部分的结果 与经过处理后的表的第一个元素连接在一起\nand then you cons that onto actually doing something to the first element of the List.\n\n205\n00:19:01,160 --> 00:19:05,180\n当你处理到结尾的时候 返回表尾标志NIL\nWhen you get down to the end here, you return the end of List pointer,\n\n206\n00:19:07,340 --> 00:19:11,360\n这就是对一个表里的数据做某种操作的通用模式\nand that's a general pattern for doing something to a list.\n\n207\n00:19:14,053 --> 00:19:19,520\n现在 你们应该清楚知道这样一个事实\nWell of course you should know by now that the very fact\n\n208\n00:19:19,530 --> 00:19:22,620\n也就是我不必额外为这种基本模式额外编写过程\nthat there's a general pattern there means I shouldn't be writing this procedure at all.\n\n209\n00:19:22,620 --> 00:19:24,900\n我要做的事情就是写一个过程\nWhat I should do is write a procedure\n\n210\n00:19:24,900 --> 00:19:26,320\n这是这个基本模式\nthat's the general pattern itself\n\n211\n00:19:26,800 --> 00:19:30,300\n对表中的元素执行操作 并以表的形式返回结果\nthat says, do something to everything in the List and define this thing in terms of that.\n\n212\n00:19:30,680 --> 00:19:32,300\n好了 我们定义一些高阶过程\nRight, make some higher order procedure,\n\n213\n00:19:32,320 --> 00:19:35,180\n我们定义一个叫MAP的高阶过程 来完成这些操作\nand here's the higher order procedure that does that. It's called MAP,\n\n214\n00:19:36,730 --> 00:19:43,170\nMAP以表L和过程P为参数\nand what MAP does is it takes a List, takes a List l, and it takes a procedure p,\n\n215\n00:19:44,920 --> 00:19:51,080\n并返回对表L中每个元素应用过程P后得到的新表\nand it returns the List of the elements gotten by applying p to each successive element in the List.\n\n216\n00:19:51,810 --> 00:19:55,400\n这个新表里的元素是(P E1) (P E2) ...  到(P En)\nAll right, so p of e1, p of e2, p of en.\n\n217\n00:19:55,640 --> 00:20:01,540\n所以我指的就是对一个表做这样一种变换：将P应用到表的每一个元素上\nRight, so I think of taking this List and transforming it by applying p to each element.\n\n218\n00:20:02,520 --> 00:20:07,080\n你们看到的这些过程正是我提到的通用策略\nAnd you see all this procedure is is exactly the general strategy I said.\n\n219\n00:20:07,080 --> 00:20:09,080\n我们用它写乘以10的过程\nInstead of multiply by 10, it's do the procedure.\n\n220\n00:20:09,080 --> 00:20:11,640\n如果表是空的 则返回NIL\nIf the List is empty, return nil.\n\n221\n00:20:11,860 --> 00:20:16,600\n否则 对表的首元素应用P\nOtherwise, apply p to the first element of the List.\n\n222\n00:20:17,140 --> 00:20:18,740\n将P应用于L的CAR部分\nRight, apply p to car of l,\n\n223\n00:20:19,300 --> 00:20:25,400\n然后连接它和将P应用于表CDR部分中的剩余元素得到的子表连接起来\nand cons that onto the result of applying p to everything in the cdr of the List,\n\n224\n00:20:25,610 --> 00:20:28,840\n这就是一个通用过程——MAP\nso that's a general procedure called MAP.\n\n225\n00:20:29,860 --> 00:20:39,040\n我们可以用MAP来定义SCALE-LIST\nAnd I could define Scale-List in terms of MAP.\n\n226\n00:20:39,040 --> 00:20:41,040\n我给你们展示一下\nLet me show you that first.\n\n227\n00:20:43,460 --> 00:20:52,500\nSCALE-LIST就是对表MAP一个特定的过程\nBut I could say Scale-List is another way to define it is just MAP along the List by the procedure,\n\n228\n00:20:52,500 --> 00:20:55,540\n这个过程需要一个参数 返回给定参数乘以S的结果\nwhich takes an item and multiplies it by s.\n\n229\n00:20:58,960 --> 00:21:01,900\n所以我思考缩放表这个过程的正确方式应该是\nRight, so this is really the way I should think about scaling the List,\n\n230\n00:21:02,120 --> 00:21:07,400\n将这种递归实质实现为通用策略 而不是一个具体针对的过程\nbuild that actual recursion into the general strategy, not to every particular procedure I write.\n\n231\n00:21:07,400 --> 00:21:11,280\n当然 这样做的意义之一是 是你会开始发现共性\nAnd of course, one of the values of doing this is that you start to see commonality.\n\n232\n00:21:12,160 --> 00:21:15,020\n我们正在掌握使用通用模式\nRight, again you're capturing general patterns of usage.\n\n233\n00:21:15,960 --> 00:21:31,180\n比如 (MAP SQUARE 1-TO-4) 返回(1 4 9 16)\nFor instance, if I said MAP, the square procedure, down this List 1-TO-4, then I'd end up with 1, 4, 9 and 16.\n\n234\n00:21:32,480 --> 00:21:37,170\n对这个表做映射\nRight, or if I said MAP down this List,\n\n235\n00:21:37,570 --> 00:21:46,320\n用(LAMBDA (X) (+ X 10))映射表1-TO-4\nlambda of x plus x 10, if I MAP that down 1-TO-4,\n\n236\n00:21:49,680 --> 00:21:52,860\n我让表的每个元素都加了10\nthen I'd get the List where everything had 10 added to it:\n\n237\n00:21:53,340 --> 00:21:58,170\n也就是得到了(11 12 13 14)\nright, so I'd get 11,12, 13, 14.\n\n238\n00:22:00,560 --> 00:22:05,760\n我们看到对表中每个元素做操作是一种非常普遍的想法\nAnd you can see that's going to be a very, very common idea: doing something to every element in the List.\n\n239\n00:22:08,660 --> 00:22:12,220\n而大家需要思考如何编写MAP的迭代版本\nOne thing you might think about is writing MAP in an iterative style.\n\n240\n00:22:12,220 --> 00:22:16,040\n我碰巧写的是一个递归版本\nThe one I wrote happens to evolve a recursive process,\n\n241\n00:22:16,360 --> 00:22:19,100\n但是我们也可以很容易地把它改成迭代过程\nbut we could just as easily have made one that evolves an iterative process.\n\n242\n00:22:19,100 --> 00:22:23,160\n有趣的是 一旦你开始用MAP来思考\nBut see the interesting thing about it is that once you start thinking in terms of MAP--\n\n243\n00:22:24,020 --> 00:22:29,000\n比如 一旦把缩放看作是一种MAP 就不用关心是迭代还是递归实现\nsee, once you say scale is just MAP, you stop thinking about whether it's iterative or recursive,\n\n244\n00:22:29,000 --> 00:22:31,820\n你只会关心 啊 这里有这样一种数据集合 有这样一个表\nand you just say, well there's this aggregate, there's this List,\n\n245\n00:22:32,220 --> 00:22:34,520\n我要做的是转化表中的每个元素\nand what I do is transform every item in the List,\n\n246\n00:22:34,560 --> 00:22:38,360\n而不去考虑特别的控制流程或顺序\nand I stop thinking about the particular control structure in order.\n\n247\n00:22:38,880 --> 00:22:41,090\n这是个非常非常重要的想法\nThat's a very, very important idea,\n\n248\n00:22:42,360 --> 00:22:46,480\n我猜这个想法来自APL语言\nand it, I guess it really comes out of APL.\n\n249\n00:22:46,480 --> 00:22:49,100\n它是APL中非常重要的思想\nIt's, sort of, the really important idea in APL\n\n250\n00:22:49,120 --> 00:22:51,130\n即不要去考虑控制结构\nthat you stop thinking about control structures,\n\n251\n00:22:51,410 --> 00:22:53,920\n而是关注于策略操作\nand you start thinking about operations on aggregates,\n\n252\n00:22:55,010 --> 00:23:00,010\n在本课程进行到一半的时候 我们将讨论一种叫做流处理的东西\nand then about halfway through this course,we'll see when we talk about something called stream processing,\n\n253\n00:23:00,260 --> 00:23:02,640\n那时我们将看到这种观点的真正威力\nhow that view of the world really comes into its glory.\n\n254\n00:23:02,640 --> 00:23:05,300\n这是一种很聪明的思想\nThis is just us a, sort of, cute idea.\n\n255\n00:23:05,300 --> 00:23:08,700\n我们可以在以后看到更多应用\nBut we'll see much more applications of that later on.\n\n256\n00:23:09,360 --> 00:23:16,840\n还有一些非常有用也非常像MAP的过程\nWell let me mention that there's something that's very similar to MAP that's also a useful idea, and that's--\n\n257\n00:23:17,560 --> 00:23:22,540\nMAP是将某个过程应用于表中每个元素\nsee, MAP says I take a List, I apply something to each item,\n\n258\n00:23:22,980 --> 00:23:25,620\n并返回相应结果构成的表\nand I return a List of the successive values.\n\n259\n00:23:25,980 --> 00:23:28,690\n还有一种与此非常非常相似的操作\nThere's another thing I might do, which is very, very similar,\n\n260\n00:23:29,320 --> 00:23:35,860\n也就是给定一个列表和操作 依次将其应用于表中每个元素\nwhich is take a List and some action you want to do and then do it to each item in the List in sequence.\n\n261\n00:23:36,290 --> 00:23:39,400\n而不会建立由结果构成的表 只是为了完成操作\nDon't make a List of the values, just do this particular action,\n\n262\n00:23:40,020 --> 00:23:45,100\n这个过程非常像MAP\nand that's something that's very much like MAP.\n\n263\n00:23:45,100 --> 00:23:46,026\n它就是FOR-EACH\nIt's called for-each,\n\n264\n00:23:46,740 --> 00:23:49,480\n它接受一个过程和一个表\nand for-each takes a procedure and a List,\n\n265\n00:23:49,620 --> 00:23:53,860\n它实际上是对表中每个元素执行此操作\nand what it's going to do is do something to every item in the List.\n\n266\n00:23:55,160 --> 00:23:58,530\n通常是这样 如果表非空\nSo basically what it does: it says if the List is not empty,\n\n267\n00:23:59,740 --> 00:24:01,120\n也就是不为NIL\nif the List is not null,\n\n268\n00:24:01,900 --> 00:24:06,250\n我将这个过程应用于表的第一个元素\nthen what I do is, I apply my procedure to the first item in the List,\n\n269\n00:24:07,680 --> 00:24:11,666\n然后对表中其余元素做同样的事情\nand then I do this thing to the rest of the List.\n\n270\n00:24:12,440 --> 00:24:15,253\n我将FOR-EACH也应用于表的CDR部分\nI apply for-each to the cdr of the List.\n\n271\n00:24:15,880 --> 00:24:18,730\n我对表的首元素进行处理 然后对表其余部分进行处理\nAll right, so I do it to the first of the List, do it to the rest of the List,\n\n272\n00:24:19,320 --> 00:24:23,920\n当然 以此类推 递归地调用 又会对表其余部分的其余部分做处理\nand of course, when I call it recursively, that's going to do it to the rest of the rest of the List and so on.\n\n273\n00:24:23,920 --> 00:24:28,120\n最终 过程结束时 我应该告知系统\nAnd finally, when I get done, I have to just do something to say I'm done,\n\n274\n00:24:28,160 --> 00:24:32,400\n所以就返回“DONE” 所以这非常像MAP\nso we'll return the message \"done.\" So that's very, very similar to MAP.\n\n275\n00:24:32,800 --> 00:24:35,120\n它们之间只是返回值不同\nIt's mostly different in what it returns.\n\n276\n00:24:35,480 --> 00:24:39,900\n比如说 如果我有一个可以在屏幕上打印对象的过程\nAnd so for example, if I had some procedure that printed things on the screen,\n\n277\n00:24:40,560 --> 00:24:45,810\n如果我想打印表中的所有元素 可以调用(FOR-EACH PRINT LIST)\nif I wanted to print everything in the List, I could say for-each, print this List.\n\n278\n00:24:46,780 --> 00:24:51,330\n如果我有一系列图表构成的表 想把它们输出在屏幕上\nOr if I had a List of figures, and I wanted to draw them on the display,\n\n279\n00:24:51,620 --> 00:24:54,860\n我可以对这个调用(FOR-EACH DISPLAY FIGURES)\nI could say for-each, display on the screen this figure.\n\n280\n00:24:58,180 --> 00:24:59,320\n有问题么？\nTake questions.\n\n281\n00:25:00,620 --> 00:25:04,260\n学生：除非你明确地指定\nAUDIENCE: Does it create a new copy with something done to it,\n\n282\n00:25:04,300 --> 00:25:07,540\nLisp会创建一个你正在处理的对象的新拷贝 是这样么？\nunless you explicitly tell it to do that? Is that correct?\n\n283\n00:25:07,540 --> 00:25:09,180\n教授：对\nPROFESSOR: Right. Ah.\n\n284\n00:25:09,930 --> 00:25:10,940\n就是这样\nYeah, that's right.\n\n285\n00:25:10,940 --> 00:25:15,140\nFOR-EACH不创建新列表 它只是对列表的每一个元素进行处理\nFor-each does not create a List. It just sort of does something.\n\n286\n00:25:15,140 --> 00:25:17,290\n所以如果你有一堆事情等着做\nSo if you have a bunch of things you want to do\n\n287\n00:25:18,020 --> 00:25:21,560\n并且你并不关心这些值 比如打印 绘图\nand you're not worried about values like printing something, or drawing something on the screen,\n\n288\n00:25:21,890 --> 00:25:24,600\n或者在终端中响铃等等\nor ringing the bell on the terminal,or for something,\n\n289\n00:25:24,600 --> 00:25:27,640\nFOR-EACH对表中每个元素做这些事\nyou can say for-each, you know, do this for-each of those things in the List,\n\n290\n00:25:28,210 --> 00:25:32,420\n而MAP其实构建了一个新集合 这个集合也许是你想要用的\nwhereas MAP actually builds you this new collection of values that you might want to use.\n\n291\n00:25:32,420 --> 00:25:34,160\n这就是它们之间的微妙关系\nIt's just a subtle difference between them.\n\n292\n00:25:34,160 --> 00:25:36,300\n学生：你能否用FOR-EACH来构造MAP\nAUDIENCE: Could you write MAP using for-each,\n\n293\n00:25:36,320 --> 00:25:40,160\n其中你用类似CONS的操作将表又构造出来了？\nso that you did some sort of cons or something to build the List back up?\n\n294\n00:25:40,180 --> 00:25:44,460\n教授：某种程度上 我也许可以\nPROFESSOR: Well, sort of. I mean, I probably could.\n\n295\n00:25:44,460 --> 00:25:49,980\n我不知道如何随手写出它 但是我可以给一些思路\nI can't think of how to do it right offhand, but yeah, I could arrange something.\n\n296\n00:25:50,480 --> 00:25:54,733\n学生：根据昨天的课程 我认为MAP和FOR-EACH的关键区别在于\nAUDIENCE: The vital difference between MAP and for-each is one is recursive and the other is not\n\n297\n00:25:54,733 --> 00:26:00,620\n它们之中一个是递归的 而另一个不是\nin the sense you defined early yesterday, I believe.\n\n298\n00:26:01,240 --> 00:26:03,860\n教授：是的 关于MAP和FOR-EACH和递归\nPROFESSOR: Yeah, about MAP and for-each and recursion.\n\n299\n00:26:03,860 --> 00:26:05,480\n这个观点很好\nYeah, that's a good point.\n\n300\n00:26:05,480 --> 00:26:13,080\n我写的MAP过程恰巧是一个递归过程\nFor the MAP procedure I wrote, that happens to be a recursive process.\n\n301\n00:26:13,820 --> 00:26:17,060\n这是因为 你需要得到处理完表的剩余部分后的值\nAnd the reason for that is that when you've done this thing to the rest of the List,\n\n302\n00:26:17,080 --> 00:26:20,960\n使其与表的开头部分相连\nyou're waiting for that value so that you can stick it on to the beginning of the List,\n\n303\n00:26:21,730 --> 00:26:24,530\n但是FOR-EACH不需要等待返回值\nwhereas for-each doesn't really have any values to wait for.\n\n304\n00:26:24,840 --> 00:26:26,660\n所以它变成了一个迭代的过程\nSo that turns out to be an iterative process.\n\n305\n00:26:26,660 --> 00:26:27,720\n这不是本质\nThat's not fundamental.\n\n306\n00:26:27,720 --> 00:26:31,800\n我可以用迭代的方式定义MAP过程\nI could have defined MAP so that it's evolved by an iterative process.\n\n307\n00:26:31,820 --> 00:26:32,820\n只是我没那么做\nI just didn't happen to.\n\n308\n00:26:34,240 --> 00:26:42,900\n学生：将FOR-EACH用在一个列表的列表上的话 我想这是可行的吧？\nAUDIENCE: If you were to call for each with a List that had embedded Lists, I imagine it would work, right?\n\n309\n00:26:42,900 --> 00:26:48,100\n它会对这些内部列表的元素进行处理么？\nIt would give you the internal elements of each of those internal Lists?\n\n310\n00:26:48,700 --> 00:26:50,400\n教授：问题是 如果我调用\nPROFESSOR: OK, the question is if I call\n\n311\n00:26:50,400 --> 00:26:52,280\nFOR-EACH或者MAP\nfor-each or map, for that matter\n\n312\n00:26:52,810 --> 00:26:55,280\n参数是一个嵌套有一个表的表\nwith a List that had Lists in it\n\n313\n00:26:56,690 --> 00:27:00,600\n虽然我们还没有讲过这个 但是那是可行的\nalthough we haven't really looked at that yet--would that work.\n\n314\n00:27:01,020 --> 00:27:06,560\n答案是肯定的 不过我俩对“可行”的定义可能有些不同\nThe answer is yes in the sense I mean work and no in the sense that you mean work,\n\n315\n00:27:06,860 --> 00:27:10,650\n来看一下 如果我给你一个表\nbecause all that-- see if I give you a List,\n\n316\n00:27:12,800 --> 00:27:14,200\n而在个箭头所指的\nwhere hanging off here is,\n\n317\n00:27:16,060 --> 00:27:21,460\n不是一个数 而是一个表 或者序对 或者是其它东西\nyou know, is something that's not a number, maybe another List or you know, another cons or something,\n\n318\n00:27:21,960 --> 00:27:24,540\nFOR-EACH对表中的每个元素做处理\nfor-each just says do something to each item in this List.\n\n319\n00:27:24,540 --> 00:27:26,960\n它会不断地处理表CDR部分\nIt goes down successively looking at the cdrs.\n\n320\n00:27:26,960 --> 00:27:27,200\n学生：嗯\nAUDIENCE: OK.\n\n321\n00:27:27,200 --> 00:27:31,060\n教授：对FOR-EACH来说 表中的第一个元素就是这个箭头所指的东西\nPROFESSOR: And as far as it's concerned, the first item in this List is whatever is hanging off here.\n\n322\n00:27:31,060 --> 00:27:31,650\n学生：唔\nAUDIENCE: Mhm.\n\n323\n00:27:31,650 --> 00:27:33,940\n教授：这对于你要完成的任务而言 也许是对的 也许不是\nPROFESSOR: That might or might not be the right thing.\n\n324\n00:27:33,940 --> 00:27:35,570\n学生：所以不能进入子表中\nAUDIENCE: So it wouldn't go down into the--\n\n325\n00:27:35,570 --> 00:27:36,910\n教授：绝对不能\nPROFESSOR: Absolutely not.\n\n326\n00:27:36,910 --> 00:27:38,510\n当然我也可以那样写程序\nI could certainly write something else.\n\n327\n00:27:38,510 --> 00:27:42,970\n你所说的是另一种公共模式 叫做树递归\nThere's another, what you're looking for is a common pattern of usage called tree recursion,\n\n328\n00:27:43,010 --> 00:27:47,940\n当你给它一个表 它会不断向深度递归 直到遇到所谓的“树叶”\nwhere you take a List, and you actually go all the way down to the what's called the leaves of the tree.\n\n329\n00:27:47,940 --> 00:27:51,050\n你可以写出来这个过程 但是它既不是FOR-EACH也不是MAP\nAnd you could write such a thing, but that's not for-each and it's not MAP.\n\n330\n00:27:52,420 --> 00:27:55,050\nFOR-EACH和MAP都很简单\nRemember, these things are really being very simple minded.\n\n331\n00:27:55,770 --> 00:27:56,890\n好 还有问题么？\nOK, no more questions?\n\n332\n00:27:57,680 --> 00:27:58,570\n好的 大家休息一下吧\nAll right, let's break.\n\n333\n00:27:59,110 --> 00:28:10,990\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n334\n00:28:11,460 --> 00:28:14,293\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n335\n00:28:14,320 --> 00:28:17,520\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n336\n00:28:27,380 --> 00:28:34,226\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n337\n00:28:34,860 --> 00:28:38,586\nHenderson-Escher的例子\nHenderson Escher Example\n\n338\n00:28:41,940 --> 00:28:48,650\n教授：我将在本节课余下的时间中 讨论一个实例\nPROFESSOR: What I'd like to do now is spend the rest of this time talking about one example,\n\n339\n00:28:50,040 --> 00:28:53,920\n这个实例 可以充分地总结我们所学的所有东西\nand this example, I think, pretty much summarizes everything that we've done up until now:\n\n340\n00:28:54,740 --> 00:28:56,290\n比如 表结构\nall right, and that's List structure\n\n341\n00:28:57,170 --> 00:28:59,480\n以及抽象的技术\nand issues of abstraction,\n\n342\n00:28:59,540 --> 00:29:00,820\n数据的表示\nand representation\n\n343\n00:29:01,600 --> 00:29:04,600\n和用高阶过程描绘共性\nand representation and capturing commonality with higher order procedures,\n\n344\n00:29:04,600 --> 00:29:09,800\n也会介绍目前为止还没怎么谈论过的\nand also is going to introduce something we haven't really talked about a lot yet-- what I said is the major third theme in this course:\n\n345\n00:29:09,850 --> 00:29:13,460\n也就是这门课的第三大主题\nwhat I said is the major third theme in this course:\n\n346\n00:29:13,960 --> 00:29:15,530\n元语言抽象\nmeta-linguistic abstraction,\n\n347\n00:29:15,540 --> 00:29:21,900\n这种在工程设计中控制复杂度的思想\nwhich is the idea that one of the ways of tackling complexity in engineering design\n\n348\n00:29:22,860 --> 00:29:25,800\n也就是建立一个合适而强大的语言\nis to build a suitable powerful language.\n\n349\n00:29:28,170 --> 00:29:34,740\n你们或许记得 我说过在这门课程中 你们将要学到的最重要的事情是\nYou might recall what I said was pretty much the very most important thing that we're going to tell you in this course is that\n\n350\n00:29:34,740 --> 00:29:41,170\n当我们考察一门语言时 关心的是它的基本元素\nwhen you think about a language, you think about it in terms of what are the primitives;\n\n351\n00:29:42,980 --> 00:29:46,690\n关心它的组合手段\nwhat are the means of combination--\n\n352\n00:29:49,720 --> 00:29:52,800\n关心那些让你能够构建更大东西的东西\nright, what are the things that allow you to build bigger things;\n\n353\n00:29:53,610 --> 00:29:55,240\n以及 抽象的方式\nand then what are the means of abstraction.\n\n354\n00:30:00,970 --> 00:30:05,160\n如何取用这些你构造出来的“大东西”\nHow do you take those bigger things that you've built\n\n355\n00:30:05,560 --> 00:30:07,970\n并将它们放入“黑盒”中\nput black boxes around them\n\n356\n00:30:08,450 --> 00:30:11,710\n然后用它们来构建更复杂的东西\nand use them as elements in making something even more complicated?\n\n357\n00:30:13,530 --> 00:30:18,720\n我将要介绍的一种语言 就是元语言抽象的一个例子\nNow the particular language I'm going to talk about is an example\n\n358\n00:30:18,730 --> 00:30:22,700\n那是我朋友Peter Handerson发明的\nthat was made up by a friend of ours called Peter Henderson.\n\n359\n00:30:28,240 --> 00:30:31,740\n他来自苏格兰的Stirling大学\nPeter Henderson is at the University of Stirling in Scotland.\n\n360\n00:30:32,780 --> 00:30:40,980\n这个语言是用来画这样的图\nAnd what this language is about is making figures that sort of look like this.\n\n361\n00:30:41,860 --> 00:30:46,660\n这是埃舍尔的木版画 《方形极限》\nThis is this is a woodcut by Escher called \"Square Limit.\"\n\n362\n00:30:49,330 --> 00:30:57,940\n正如大家所见 这里面有着很复杂的...图像的递归\nYou, sort of, see it has this complicated, kind of, recursive, sort of, recursive kind of figure,\n\n363\n00:30:58,840 --> 00:31:01,466\n其中中间的鱼形图案以自相似的方式\nwhere there's this fish pattern in the middle and things sort of\n\n364\n00:31:01,706 --> 00:31:04,560\n不断地以更小的形式出现在原来的团案旁边\nbleed out smaller and smaller in self similar ways.\n\n365\n00:31:08,490 --> 00:31:12,800\n总之 Peter Hendersion的语言是用来表述这类图形\nAnyway, Peter Henderson's language was for describing figures that look like that\n\n366\n00:31:13,370 --> 00:31:18,280\n并且设计类似的图形 将它画在显示器上\nand designing new ones that look like that and drawing them on a display screen.\n\n367\n00:31:20,240 --> 00:31:27,480\n这个例子还展示了另外一个主题\nThere's another theme that we'll see illustrated by this example,\n\n368\n00:31:28,090 --> 00:31:32,020\n这也是我跟Gerry教授多次强调的\nand that's the issue of what Gerry and I have already mentioned a lot:\n\n369\n00:31:32,020 --> 00:31:36,170\n也就是过程跟数据之间没有本质的区别\nthat there's no real difference, in some sense, between procedures and data.\n\n370\n00:31:37,260 --> 00:31:42,400\n不管如何 我希望今早课程结束后\nAnd anyway I hope by the end of this morning, if you're not already,\n\n371\n00:31:42,580 --> 00:31:47,600\n你们能将过程和数据当作一回事儿\nyou will be completely confused about what the difference between procedures and data are,\n\n372\n00:31:47,960 --> 00:31:49,580\n即使现在你们还将它们区别对待\nif you're not confused about that already.\n\n373\n00:31:50,800 --> 00:31:55,280\n那么 先让我们看一下Peter的语言\nWell in any case, let's start describing Peter's language.\n\n374\n00:31:55,280 --> 00:31:57,260\n我先告诉你们基本元素是什么\nI should start by telling you what the primitives are.\n\n375\n00:31:58,290 --> 00:32:00,920\n这个语言非常简单 因为它的基本元素只有一个\nThis language is very simple because there's only one primitive.\n\n376\n00:32:03,330 --> 00:32:06,300\n这个基本元素不是大家想象的那样\nA primitive is not quite what you think it is.\n\n377\n00:32:07,080 --> 00:32:09,180\n它唯一的基本元素叫做\"图像\"\nThere's only one primitive called a picture,\n\n378\n00:32:09,700 --> 00:32:12,110\n但此“图像”非彼“图像”\nand a picture is not quite what you think it is.\n\n379\n00:32:12,110 --> 00:32:14,170\n具体地来说\nHere's an example.\n\n380\n00:32:14,170 --> 00:32:15,170\n这是George的图像\nThis is a picture of George.\n\n381\n00:32:19,010 --> 00:32:20,370\n我们的想法是\nThe idea is that\n\n382\n00:32:22,330 --> 00:32:24,573\n在这个语言中的图像是这样一个东西\na picture in this language is going to be something\n\n383\n00:32:24,893 --> 00:32:31,460\n它能在你指定的一个矩形里画出一个缩放好图像\nthat draws a figure scaled to fit a rectangle that you specify.\n\n384\n00:32:33,000 --> 00:32:34,420\n这里大家看到的强调线\nSo here you see emphasis line\n\n385\n00:32:34,420 --> 00:32:37,700\n是这个矩形的轮廓 但不是图像的一部分\nis outline of a rectangle, that's not really part of the picture,\n\n386\n00:32:40,490 --> 00:32:47,170\n但是一旦指定一个矩形区域 图像会以以填充的方式绘制满区域\nbut the picture-- you'll give it a rectangle, and it will draw this figure scaled to fit the rectangle.\n\n387\n00:32:47,170 --> 00:32:52,160\n比如 这个是George 在这里 这个也是George\nSo for example, there's George, and here, this is also George.\n\n388\n00:32:53,210 --> 00:32:56,650\n它是同一个图像 只是缩放程度不同\nIt's the same picture, right, just scaled to fit a different rectangle.\n\n389\n00:32:57,400 --> 00:32:59,280\n这是“胖”George的版本\nHere's George as a fat kid.\n\n390\n00:33:00,010 --> 00:33:03,440\n这个也是George\nThat's the same George.\n\n391\n00:33:03,810 --> 00:33:05,140\n这是同一个图形\nIt's all the same figure.\n\n392\n00:33:05,140 --> 00:33:09,570\n这个语言中 这三个都是同一个图像\nAll of these three things are the same picture in this language.\n\n393\n00:33:09,580 --> 00:33:13,040\n仅仅是给了不同的矩形区域让它来填充\nI'm just giving it different rectangles to scale itself in.\n\n394\n00:33:16,080 --> 00:33:20,650\n这就是基本元素\nOK, those are the primitives. That is the primitive.\n\n395\n00:33:21,440 --> 00:33:25,250\n现在 我们来讨论元素组合和操作\nNow let's start talking about the means of combination and the operations.\n\n396\n00:33:25,900 --> 00:33:30,170\n比如 这里有一个叫做旋转的操作\nThere is, for example, an operation called Rotate.\n\n397\n00:33:31,090 --> 00:33:33,660\n如果我有一个图像 “旋转”操作就是\nAnd what Rotate does is, if I have a picture,\n\n398\n00:33:35,370 --> 00:33:39,930\n先假定有一个里面有个“A”的矩形\nsay a picture that draws an \"A\" in some rectangle that I give it,\n\n399\n00:33:41,840 --> 00:33:45,730\n而旋转90度的操作则会\nthe Rotate of that--say the Rotate by 90 degrees would,\n\n400\n00:33:47,020 --> 00:33:50,650\n在一个给定的矩形内 绘制同样的图像\nif I give it a rectangle, draw the same image,\n\n401\n00:33:50,650 --> 00:33:53,880\n但是 会缩放图像以适应矩形\nbut again, scaled to fit that rectangle.\n\n402\n00:33:56,110 --> 00:33:58,340\n这个就是旋转90度\nSo that's Rotate by 90 degrees.\n\n403\n00:33:58,340 --> 00:34:03,200\n另一个操作是“翻转” 可以水平翻转也可以竖直翻转\nThere's another operation called Flip that can flip something, either horizontally or vertically.\n\n404\n00:34:04,770 --> 00:34:06,000\n就是这些操作了\nAll right, so those are, sort of, operations,\n\n405\n00:34:06,010 --> 00:34:10,400\n或者你可以把它们认为是组合一个元素的各种方式\nor you can think of those as means of combination of one element.\n\n406\n00:34:10,890 --> 00:34:12,420\n我可以把它们混合起来\nI can put things together.\n\n407\n00:34:13,440 --> 00:34:15,540\n我们有一种叫BESIDE的操作\nThere's a means of combination called Beside,\n\n408\n00:34:16,460 --> 00:34:24,780\n它做的事情是 给定两个图像A、B --\nand what Beside does: it'll take two pictures, let's say A and B--\n\n409\n00:34:29,020 --> 00:34:33,250\n这里图像是指能在指定的矩形中画一个图案的东西 --\nand by picture I mean something that's going to draw an image in a specified rectangle--\n\n410\n00:34:34,050 --> 00:34:36,510\nBESIDE将会做的事情\nand what Beside will do--\n\n411\n00:34:37,850 --> 00:34:44,080\n类似于调用(BESIDE A B S) 其中S是一个数\nI have to say, Beside of A and B, the side of two pictures and some number, s.\n\n412\n00:34:45,340 --> 00:34:48,080\n是一个在0到1之间的数\nAnd s will be a number between zero and one.\n\n413\n00:34:50,510 --> 00:34:52,570\nBESIDE绘制像这样的图像\nAnd Beside will draw a picture that looks like this.\n\n414\n00:34:52,570 --> 00:34:56,710\n以给定的矩形为基础 但会将基底缩放S\nIt will take the rectangle you give it and scale its base by s.\n\n415\n00:34:56,710 --> 00:34:58,710\n这里S是0.5\nSay s is 0.5.\n\n416\n00:35:00,180 --> 00:35:07,170\n在这里 它会在这里画第一个图案\nAnd then over here it will draw-- it'll put the first picture, and over here it'll put the second picture.\n\n417\n00:35:07,810 --> 00:35:12,650\n在这里画第二个图案\nand over here it'll put the second picture.\n\n418\n00:35:13,820 --> 00:35:16,440\n又比如说 我另设一个S的值\nOr for instance if I gave it a different value of s,\n\n419\n00:35:16,810 --> 00:35:23,020\n比如调用(BESIDE A B 0.25)\nOr for instance if I gave it a different value of s, if I said Beside with a 0.25,\n\n420\n00:35:25,940 --> 00:35:29,090\n效果相同 只不过A更瘦了\nit would do the same thing, except the A would be much skinnier.\n\n421\n00:35:34,050 --> 00:35:36,280\n而B是这样的\nSo it would draw something like that.\n\n422\n00:35:37,820 --> 00:35:40,290\n这就是组合手段之一：BESIDE\nSo there's a means of combination Beside,\n\n423\n00:35:40,680 --> 00:35:46,050\n类似地 ABOVE方法在竖直方向上做这种操作\nand similarly there's an Above, which does the same thing except it puts them vertically instead of horizontally.\n\n424\n00:35:47,840 --> 00:35:48,890\n我们来看一下\nWell let's look at that.\n\n425\n00:35:50,740 --> 00:35:56,000\n这是George和他的\"弟弟\"\nAll right, there's George and his kid brother,\n\n426\n00:35:56,720 --> 00:36:07,050\n这是通过将George放在一旁\nwhich is, right, constructed by taking George and putting him Beside\n\n427\n00:36:10,360 --> 00:36:14,420\nGeorge与空图像的上下组合放在另一旁\nThe Above, taking the empty picture, and there's a thing called the empty picture,\n\n428\n00:36:14,520 --> 00:36:16,140\n这样做的意图很明显\nwhich does the obvious thing--\n\n429\n00:36:16,140 --> 00:36:19,140\n空图像放在了另一个George的上面\nputting the empty picture above a copy of George,\n\n430\n00:36:19,140 --> 00:36:21,140\n合成的图像又放在了George的旁边\nand then putting that whole thing Beside George.\n\n431\n00:36:28,960 --> 00:36:30,340\n这个是图像P\nHere's something called P which is,\n\n432\n00:36:31,100 --> 00:36:39,040\n像之前一样 是George和翻转后George的BESIDE组合\nwhich is, again, George Beside Flipping George,\n\n433\n00:36:40,530 --> 00:36:42,080\n这里 我们做的是水平翻转\nI think, horizontally in this case,\n\n434\n00:36:42,370 --> 00:36:44,800\n然后整体旋转180度\nRotating the whole result 180 degrees\n\n435\n00:36:45,800 --> 00:36:50,820\n然后调用BESIDE让它们组合在一起 系数是0.5\nputting them Beside one another with the basic rectangle divided at 0.5,\n\n436\n00:36:52,560 --> 00:36:53,900\n这样 我创建了图像P\nright, and I can call that P.\n\n437\n00:36:55,900 --> 00:36:57,880\n然后使用图像P\nAnd then I can take P,\n\n438\n00:36:59,210 --> 00:37:04,960\n与它的翻转图像做ABOVE操作 形成图像Q\nAnd then I can take P, and put it above the Flipped copy of itself, and I can call that Q.\n\n439\n00:37:09,200 --> 00:37:13,260\n请注意 我们是如何快速地增加复杂度\nNotice how rapidly that we've built up complexity,\n\n440\n00:37:14,360 --> 00:37:21,050\n转瞬之间 我们使用George组合得到了Q 这说明了什么？\njust in, you know, 15 seconds, you've gotten from George to that thing Q. Why is that?\n\n441\n00:37:22,050 --> 00:37:24,550\n为什么我们可以做得如此迅速呢?\nHow are how we able to do that so fast?\n\n442\n00:37:25,850 --> 00:37:28,020\n答案是闭包性质\nThe answer is the closure property.\n\n443\n00:37:28,690 --> 00:37:32,980\n这是因为 当我将两个图像做BESIDE操作后\nSee, it's the fact that when I take a picture and put it Beside another picture,\n\n444\n00:37:34,300 --> 00:37:35,290\n得到的也是图像\nthat's then, again, a picture\n\n445\n00:37:35,330 --> 00:37:37,780\n我可以继续执行 ROTATE FLIP 或者 ABOVE操作\nthat I can go and Rotate and Flip or put Above something else.\n\n446\n00:37:39,170 --> 00:37:40,880\n而操作的结果P\nRight, and when I take that element P,\n\n447\n00:37:40,893 --> 00:37:44,880\nBESIDE FLIP ROTATE操作的结果也是一个图像\nwhich is the Beside or the Flip or the Rotate of something, that's, again, a picture.\n\n448\n00:37:45,220 --> 00:37:50,200\n在这种组合方法下 图像的世界是封闭的\nRight, the world of pictures is closed under those means of combination.\n\n449\n00:37:50,770 --> 00:37:52,240\n所以 任何时候我都可以\nSo whenever I have something,\n\n450\n00:37:52,480 --> 00:37:55,170\n以一个东西为基本元素 去构造别的东西\nI can turn right around and use that as an element in something else.\n\n451\n00:37:56,330 --> 00:37:58,520\n这个例子比表和线段更直观\nSo maybe better than List and segments,\n\n452\n00:37:58,540 --> 00:38:03,280\n它揭示了 我们如何用封闭的操作 快速增加复杂度\nthat just gives you an image for how fast you can build up complexity, because operations are closed.\n\n453\n00:38:07,480 --> 00:38:12,020\n在构建更多东西之前\nOK, well before we go on with building more things,\n\n454\n00:38:12,040 --> 00:38:14,770\n我们先来看看这个语言是如何实现的\nlet's talk about how this language is actually implemented.\n\n455\n00:38:16,910 --> 00:38:21,500\n其中基本的一个元素\nThe basic element that sits under the table here\n\n456\n00:38:21,930 --> 00:38:24,520\n是一个称作“矩形”的东西\nis a thing called a rectangle,\n\n457\n00:38:26,090 --> 00:38:28,280\n所谓的矩形就是\nand what a rectangle is going to be,\n\n458\n00:38:28,280 --> 00:38:33,680\n它有一个原点\nit's a thing that specified by an origin\n\n459\n00:38:36,450 --> 00:38:40,180\n原点是一个向量 用以说明矩形是从哪开始\nthat's going to be some vector that says where the rectangle starts.\n\n460\n00:38:40,180 --> 00:38:42,290\n至于其它的向量\nAnd then there's going to be some other vector\n\n461\n00:38:43,660 --> 00:38:46,330\n我们称其为矩形的水平分量\nthat I'm going to call the horizontal part of the rectangle,\n\n462\n00:38:55,760 --> 00:38:59,250\n还有就是矩形的竖直分量\nand another vector called the vertical part of the rectangle.\n\n463\n00:39:00,490 --> 00:39:02,680\n这就是构成矩形的三个基本元素\nAnd those three pieces are the elements:\n\n464\n00:39:02,680 --> 00:39:04,510\n两个向量用作\nwhere the lower vertex is,\n\n465\n00:39:04,933 --> 00:39:09,970\n计算左上角和右下角的顶点坐标\nhow you get to the next vertex over here, and how you get to the vertex over there.\n\n466\n00:39:09,970 --> 00:39:12,370\n这三个向量确定了一个矩形\nThe three vectors specify a rectangle.\n\n467\n00:39:16,000 --> 00:39:18,933\n为了构建矩形 我们假设\nNow to actually build rectangles, what I'll assume is\n\n468\n00:39:19,773 --> 00:39:22,060\n假设有个“构建矩形”的构造函数\nthat we have a constructor called \"make rectangle,\"\n\n469\n00:39:23,010 --> 00:39:24,260\n也就是MAKE-RECT\nor \"make-rect,\"\n\n470\n00:39:27,560 --> 00:39:35,170\n以及选择函数 HORIZ、VERT 和 ORIGIN\nand selectors for horiz and vert and origin\n\n471\n00:39:37,580 --> 00:39:39,650\n用于取得对应的矩形属性\nthat get out the pieces of that rectangle.\n\n472\n00:39:39,650 --> 00:39:42,540\n我们知道有很多方法可以实现它\nAnd well, you know a lot of ways you can do this now.\n\n473\n00:39:42,540 --> 00:39:47,620\n可以用序对或者表 或者其它东西\nYou can do it by using pairs in some way or other standard List or not.\n\n474\n00:39:47,620 --> 00:39:51,400\n但是 这些东西的实现是George的事\nBut in any case, the implementation of these things, that's George's problem.\n\n475\n00:39:51,400 --> 00:39:53,170\n这是一个数据表示的问题\nIt's just a data representation problem.\n\n476\n00:39:53,170 --> 00:39:55,470\n现在我们假设已经有了这些矩形了\nSo let's assume we have these rectangles to work with.\n\n477\n00:39:59,053 --> 00:40:05,080\n好的 现在来看我们接下来要做的事情\nOK. Now the idea of this, remember what's got to happen.\n\n478\n00:40:05,080 --> 00:40:08,220\n我们需要关心如何取用图像\nSomehow we have to worry about taking the figure\n\n479\n00:40:09,330 --> 00:40:12,970\n将它缩放以适应你给定的矩形\nand scaling it to fit some rectangle that you give it,\n\n480\n00:40:13,600 --> 00:40:16,600\n我们要来安排这些事\nthat's the basic thing you have to arrange,\n\n481\n00:40:16,600 --> 00:40:18,600\n来完成图像的缩放\nthat these pictures can do.\n\n482\n00:40:22,220 --> 00:40:23,650\n有哪些思路呢？\nHow do we think about that?\n\n483\n00:40:23,650 --> 00:40:27,080\n一种想法是：无论何时给定一个矩形\nWell, one way to think about that is that any time I give you a rectangle,\n\n484\n00:40:35,680 --> 00:40:38,680\n无论何时给定一个矩形 也就是说\nAny time I gave you a rectangle, that defines,\n\n485\n00:40:39,250 --> 00:40:45,770\n这在某种意义上是把正方形转换成矩形\nthat defines,in some sense, a transformation from the standard square into that rectangle.\n\n486\n00:40:45,770 --> 00:40:46,540\n也就是说\nLet me say what I mean.\n\n487\n00:40:46,540 --> 00:40:48,530\n我所谓的正方形\nBy the standard square, I'll mean something,\n\n488\n00:40:49,040 --> 00:40:59,040\n它的坐标是(0,0)、(1,0)、(0,1)和(1,1)\nwhich is a square whose coordinates are 0,0, and 1,0, and 0,1 and 1,1.\n\n489\n00:41:01,400 --> 00:41:05,720\n我们有一些显而易见的缩放变换\nAnd there's some sort of the obvious scaling transformation,\n\n490\n00:41:06,120 --> 00:41:10,220\n可以把这个映射成这个 把这个映射成这个\nwhich maps this to that and this to that,\n\n491\n00:41:10,240 --> 00:41:12,080\n并且 把所有的东西统一地拉伸\nand sort of, stretches everything uniformly.\n\n492\n00:41:12,170 --> 00:41:18,250\n我们将这样的一条的线段\nSo we take a line segment like this\n\n493\n00:41:19,730 --> 00:41:24,200\n将它最终映射到像那样的一条线段\nand end up mapping it to a line segment like that,\n\n494\n00:41:26,200 --> 00:41:32,680\n而点(X,Y)变成了这里的另外一个点\nso some point (x,y) goes to some other point up there.\n\n495\n00:41:32,680 --> 00:41:39,370\n这个不紧要 会点向量运算 就能写出变换公式\nAnd although it's not important, with a little vector algebra, you could write that formula.\n\n496\n00:41:39,370 --> 00:41:43,180\n初始点(X,Y)将会变换到的点的坐标是\nThe thing that (x,y) goes to, the point that (x,y) goes to is\n\n497\n00:41:43,580 --> 00:41:50,746\n以矩形原点为基础做向量加法\ngotten by taking the origin of the rectangle and then adding that as a vector to--\n\n498\n00:41:51,160 --> 00:41:55,480\n加上 初始点X坐标 一个介于0和1之间的值\nwell, take x, the x coordinate, which is something between zero and one,\n\n499\n00:41:55,986 --> 00:42:01,840\n并乘上矩形的水平向量\nmultiply that by the horizontal vector of the rectangle;\n\n500\n00:42:07,626 --> 00:42:11,000\n再加上初始点的Y坐标 也是一个介于0和1的值\nand take the y coordinate, which is also something between zero and one\n\n501\n00:42:11,386 --> 00:42:16,280\n并乘上矩形的竖直向量\nand multiply that by the vertical vector of the rectangle.\n\n502\n00:42:16,740 --> 00:42:19,310\n这是简单的线性代数\nThat's just a little linear algebra.\n\n503\n00:42:19,310 --> 00:42:23,480\n这个就是正确的变换公式\nAnyway, that's the formula, which is the right obvious transformation\n\n504\n00:42:23,690 --> 00:42:28,180\n它将方形中的物件转化到对应矩形中\nthat takes things into the unit square, into the interior of that rectangle.\n\n505\n00:42:31,340 --> 00:42:34,020\n现在 我们把它看作是一个过程\nOK well, let's actually look at that as a procedure.\n\n506\n00:42:35,160 --> 00:42:36,293\n我们想要得到的是\nSo what we want is\n\n507\n00:42:37,800 --> 00:42:40,826\n由一个单位正方形到特定矩形的\nthe thing which tells us that particular transformation\n\n508\n00:42:41,013 --> 00:42:42,520\n特定变换过程\nthat a rectangle defines.\n\n509\n00:42:43,800 --> 00:42:45,220\n这个过程具体是这样的\nSo here's the procedure.\n\n510\n00:42:45,220 --> 00:42:47,220\n我叫它COORD-MAP\nI'll call it coordinate-map.\n\n511\n00:42:47,770 --> 00:42:52,000\nCOORD-MAP以一个矩形作为参数\nCoordinate-map is the thing that takes as its argument a rectangle\n\n512\n00:42:53,600 --> 00:42:57,850\n它返回一个以点为参数的过程\nand returns for you a procedure on points.\n\n513\n00:43:00,450 --> 00:43:06,820\n每个矩形 都对应一个变换点(X, Y)坐标的过程\nRight, so for each rectangle you get a way of transforming a point (x,y) into that rectangle.，\n\n514\n00:43:06,820 --> 00:43:08,020\n是怎么得到的呢？\nAnd how do you get it?\n\n515\n00:43:08,020 --> 00:43:10,920\n就如黑板上的Lisp代码所示\nWell I just--  writing in Lisp what I wrote there on the blackboard--\n\n516\n00:43:10,920 --> 00:43:16,010\n我让矩形的原点加上——\nI add to the origin of the rectangle\n\n517\n00:43:20,220 --> 00:43:25,020\n首先是 矩形水平部分\nthe result of adding-- I take the horizontal part of the rectangle;\n\n518\n00:43:25,020 --> 00:43:27,680\n按照点POINT的X坐标缩放\nI scale that by the x coordinate of the point.\n\n519\n00:43:29,650 --> 00:43:32,620\n然后是 矩形竖直部分\nI take the vertical vector of the rectangle.\n\n520\n00:43:33,510 --> 00:43:37,140\n按照点POINT的Y坐标缩放\nI scale that by the y coordinate of the point,\n\n521\n00:43:37,140 --> 00:43:39,140\n然后把它们三个加到一起\nand then add all those three things up.\n\n522\n00:43:40,130 --> 00:43:41,340\n这个过程就是这样\nThat's the procedure.\n\n523\n00:43:41,340 --> 00:43:44,540\n这就是我将要应用在点POINT上的过程\nThat is the procedure that I'm going to apply to a point.\n\n524\n00:43:46,540 --> 00:43:52,170\n这个过程由每个矩形自己生成\nAnd this whole thing is generated for each rectangle.\n\n525\n00:43:52,170 --> 00:43:57,250\n每个矩形对应了一个定义在点集上的过程 COORD-MAP\nSo any rectangle defines a Coordinate-MAP, which is a procedure on points.\n\n526\n00:44:06,660 --> 00:44:10,426\n比如说 这里的George\nAll right, so for example, George here,\n\n527\n00:44:11,360 --> 00:44:16,340\n最初的George 可能是我在单位正方形中通过线段绘制的\nmy original George, might have been something that I specified by segments in the unit square,\n\n528\n00:44:19,500 --> 00:44:21,960\n而当我把它应用到一个新的矩形中\nand then for each rectangle I give this thing,\n\n529\n00:44:24,140 --> 00:44:28,170\n我将会在新矩形中画出组成George的那些线段来\nI'm going to draw those segments inside that rectangle.\n\n530\n00:44:28,170 --> 00:44:29,880\n我是怎么做的呢？\nHow actually do I do that?\n\n531\n00:44:30,680 --> 00:44:36,940\n我枚举原始George中的每条线段\nWell I take each segment in my original reference George that was specified,\n\n532\n00:44:38,640 --> 00:44:40,586\n我对每条线段的终点\nand to each of the end points of those segments,\n\n533\n00:44:40,880 --> 00:44:44,450\n应用目标矩形对应的COORD-MAP过程\nI applied the COORDINATE-MAP of the particular rectangle I want to draw it in.\n\n534\n00:44:44,450 --> 00:44:46,066\n比如下面的这个矩形\nSo for example, this lower rectangle,\n\n535\n00:44:46,666 --> 00:44:50,880\n这个胖George 有它对应的COORD-MAP\nthis George as a fat kid rectangle, has its COORDINATE-MAP.\n\n536\n00:44:51,250 --> 00:44:53,693\n如果我要绘制这个图像\nAnd if I want to draw this image,\n\n537\n00:44:55,380 --> 00:44:57,920\n需要做的就是对这里的每条线段 比如这条\nAnd if I want to draw this image, what I do is for each segment here, say for this segment,\n\n538\n00:44:59,293 --> 00:45:05,340\n用COORD-MAP变换这个点 同时变换这个点\nI transformed that point by the coordinate MAP, transform that point by the coordinate MAP.\n\n539\n00:45:05,340 --> 00:45:07,093\n我就得到了这两个点\nThat will give me this point and that point\n\n540\n00:45:07,386 --> 00:45:08,946\n就可以将在两点之间画线\nand draw the segment between them.\n\n541\n00:45:09,710 --> 00:45:11,520\n这就是核心思路\nRight, that's the idea.\n\n542\n00:45:12,660 --> 00:45:14,780\n那么如果我给一个不同的矩形 比如这个\nRight, and if I give it a different rectangle like this one,\n\n543\n00:45:14,800 --> 00:45:15,760\n得到的是不同的COORD-MAP\nthat's a different coordinate-MAP,\n\n544\n00:45:15,790 --> 00:45:17,840\n因此我得到这些线段的不同图像\nso I get a different image of those line segments.\n\n545\n00:45:19,280 --> 00:45:22,140\n基本图像又该如何表示呢？\nWell how do we actually get a picture to start with?\n\n546\n00:45:22,140 --> 00:45:26,520\n可以用线段组成的表来表示\nI can build a picture to start with out of a List of line segments initially.\n\n547\n00:45:27,613 --> 00:45:32,200\n这是用于构建我所谓的“基本图像”的过程\nHere's a procedure that builds what I'll call a primitive picture,\n\n548\n00:45:33,480 --> 00:45:37,173\n意思是 没有用BESIDE ROTATE等操作\nmeaning one I, sort of, got that didn't come out of Beside or Rotate or something.\n\n549\n00:45:37,520 --> 00:45:39,600\n它以由线段组成的表为参数\nIt starts with a List of line segments,\n\n550\n00:45:42,946 --> 00:45:44,040\n代码具体行为如下\nAnd now it does what I said.\n\n551\n00:45:44,040 --> 00:45:45,580\n图像会是什么样子呢？\nWhat's a picture have to be?\n\n552\n00:45:45,580 --> 00:45:49,440\n首先 它是一个根据矩形定义的过程\nFirst of all it's a procedure that's defined on rectangles.\n\n553\n00:45:51,700 --> 00:45:53,000\n这个过程做什么呢？\nWhat does it do?\n\n554\n00:45:53,000 --> 00:45:56,560\n对于由线段组成的表中每个元素\nIt says for each-- this is going to be a List of line segments--\n\n555\n00:45:57,666 --> 00:46:03,386\n表中的每条线段S\nfor each segment, for each s, which is a segment in this List of segments,\n\n556\n00:46:05,893 --> 00:46:07,300\n都绘制了一条线\nwell it draws a line.\n\n557\n00:46:07,300 --> 00:46:08,820\n它画什么样的线段呢？\nWhat line does it draw?\n\n558\n00:46:10,600 --> 00:46:12,840\n先得到线段的起点\nIt gets the start point of that segment,\n\n559\n00:46:15,226 --> 00:46:17,946\n用对应的COORD-MAP对其做变换\ntransforms that by the coordinate MAP of the rectangle.\n\n560\n00:46:19,540 --> 00:46:21,760\n这是我们想要的第一个点\nThat's the first new point it wants to do.\n\n561\n00:46:21,760 --> 00:46:26,320\n然后对线段终点做COORD-MAP操作\nThen it takes the endpoint of the segment, transforms that by the coordinate MAP of the rectangle,\n\n562\n00:46:26,693 --> 00:46:27,920\n并将两点连线\nand then draws a line between.\n\n563\n00:46:27,920 --> 00:46:30,840\n我们假设在屏幕上绘制线段是基本操作\nLet's assume drawline is some primitive that's built into the system\n\n564\n00:46:31,093 --> 00:46:33,220\n已经在系统中实现了\nthat actually draws a line on the display.\n\n565\n00:46:33,960 --> 00:46:37,106\n通过COORD-MAP变换了线段终点\nAll right, so it transforms the endpoints by the coordinate MAP of the rectangle,\n\n566\n00:46:37,133 --> 00:46:38,200\n再把起点和终点连线\ndraws a line between them,\n\n567\n00:46:39,613 --> 00:46:44,120\n对表中每一条线段S都执行这样的操作\ndoes that for each s in this List of segments.\n\n568\n00:46:45,960 --> 00:46:51,400\n请注意 图像就是一个以矩形为参数的过程\nAnd now remember again, a picture is a procedure that takes a rectangle as argument.\n\n569\n00:46:51,400 --> 00:46:55,653\n所以当你给图像一个矩形时 它就像这样绘制线段\nSo when you hand it a rectangle, this is what it does: draws those lines.\n\n570\n00:46:57,173 --> 00:47:01,106\n那好 我应该如何使用它呢？\nAll right, so there's-- how would I actually use this thing?\n\n571\n00:47:01,220 --> 00:47:04,080\n我来说得具体一点\nLet's make it a little bit more concrete.\n\n572\n00:47:05,600 --> 00:47:24,226\n就比如说 (DEFINE R (MAKE-RECT ...))\nRight, I would say for instance, define R to be make-rectangle of some stuff,\n\n573\n00:47:24,506 --> 00:47:28,666\n这里需要用MAKE-VECTOR来构造一些向量\nand I'd have to specify some vectors here using make-vector.\n\n574\n00:47:29,840 --> 00:47:46,180\n然后定义G为 (DEFINE G (MAKE-PICT ...))\nAnd then I could say, define say, G to be make-picture, and then some stuff.\n\n575\n00:47:46,680 --> 00:47:55,280\n我要在这里使用MAKE-SEGMENT来构建线段组成的表\nAnd what I'd have to specify here is a List of line segments, right, using make segment.\n\n576\n00:47:55,280 --> 00:47:58,700\nMAKE-SEGMENT由向量构成 向量由点构成\nMake-segment might be made out of vectors, and vectors might be made out of points.\n\n577\n00:47:59,506 --> 00:48:04,600\n如果我想在一个矩形中呈现图像G\nAnd then if I actually wanted to see the image of G inside a rectangle,\n\n578\n00:48:04,653 --> 00:48:11,720\n注意 图像是一个过程 它接受一个矩形作为参数\nwell a picture is a procedure that takes a rectangle as argument.\n\n579\n00:48:12,066 --> 00:48:16,373\n所以 如果我调用(G R)\nSo if I then called G with an input of R,\n\n580\n00:48:17,960 --> 00:48:23,253\n那么无论G是什么 都会在矩形R中绘制出来\nthat would cause whatever image G is worrying about to be drawn inside the rectangle R.\n\n581\n00:48:23,620 --> 00:48:25,620\n这就是我们如何使用它\nRight, so that's how you'd use that.\n\n582\n00:48:26,866 --> 00:48:36,293\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n583\n00:48:36,290 --> 00:48:39,786\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n584\n00:48:39,820 --> 00:48:43,546\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n585\n00:48:51,280 --> 00:48:55,453\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n586\n00:48:55,500 --> 00:48:58,733\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n587\n00:48:59,346 --> 00:49:03,020\nHenderson-Escher的例子\nHenderson Escher Example\n\n588\n00:49:07,720 --> 00:49:12,480\n教授：为什么我说这个例子很好呢？\nPROFESSOR: Well why is it that I say this example is nice?\n\n589\n00:49:12,480 --> 00:49:13,740\n也许你们不这么认为\nYou probably don't think it's nice.\n\n590\n00:49:13,740 --> 00:49:15,420\n你们可能觉得它很奇怪\nYou probably think it's more weird than nice.\n\n591\n00:49:15,420 --> 00:49:20,920\n用来矩形做复杂变换的过程来表示图像 确实奇怪\nRight, representing these pictures as procedures, which do complicated things with rectangles.\n\n592\n00:49:20,920 --> 00:49:22,720\n那么 它好在哪里呢？\nSo why is it nice?\n\n593\n00:49:25,360 --> 00:49:26,693\n原因就是\nThe reason it's nice\n\n594\n00:49:27,226 --> 00:49:30,400\n一旦你按这种方法实现了基本元素\nis that once you've implemented the primitives in this way,\n\n595\n00:49:30,973 --> 00:49:35,200\n组合的手段就是构造Lisp过程\nthe means of combination just fall out by implementing procedures.\n\n596\n00:49:35,980 --> 00:49:37,480\n我给你们演示一下\nLet me show you what I mean.\n\n597\n00:49:37,480 --> 00:49:39,026\n假设我想实现BESIDE\nSuppose we want to implement Beside.\n\n598\n00:49:41,560 --> 00:49:47,360\n我要做的是 假设有个叫P1的图像\nSo I'd like to--  suppose I've got a picture. Let's call it P1.\n\n599\n00:49:47,360 --> 00:49:50,620\n一定要记得：图像本质上是一个过程\nP1 is going to be-- and now remember what a picture really is.\n\n600\n00:49:50,620 --> 00:49:54,826\n当你传递给它一个矩形\nIt's a thing that if you hand it some rectangle,\n\n601\n00:49:56,520 --> 00:50:01,466\n它会在你给定的矩形中绘制图形\nit will cause an image to be drawn in whatever rectangle you hand it.\n\n602\n00:50:03,466 --> 00:50:09,266\n假设P2是另一个图像 你传递给它一个矩形\nAnd suppose P2 two is some other picture, and you hand that a rectangle.\n\n603\n00:50:09,746 --> 00:50:12,440\n无论给它什么矩形 它都会绘制一些图案\nAnd whatever rectangle you hand it, it draws some picture.\n\n604\n00:50:14,840 --> 00:50:26,600\n现在 我想实现(BESIDE P1 P2 A) A是缩放因子\nAnd now if I'd like to implement Beside of P1 and P2 with a scale factor A,\n\n605\n00:50:27,040 --> 00:50:28,380\n会得到什么呢？\nwell what does that have to be?\n\n606\n00:50:28,380 --> 00:50:29,346\n我们会得到一个图像\nThat's gotta be a picture.\n\n607\n00:50:29,920 --> 00:50:33,880\n也就是说你传给它一个矩形 它就会在其中绘图\nIt's gotta be a thing that you handed a rectangle and draw something in that rectangle.\n\n608\n00:50:34,770 --> 00:50:37,186\n如果我们在一个矩形中执行BESIDE操作\nSo if hand Beside this rectangle--\n\n609\n00:50:38,586 --> 00:50:40,120\n比如这个矩形\nlet's hand it a rectangle.\n\n610\n00:50:41,500 --> 00:50:42,740\n要做什么呢？\nWell what's it going to do?\n\n611\n00:50:42,760 --> 00:50:46,360\n一部分比例是A 另一部分是1-A\nIt's going to take this rectangle and split it into two\n\n612\n00:50:49,293 --> 00:50:51,570\n一部分比例是A 另一部分是1-A\nat a ratio of A and one minus A.\n\n613\n00:50:52,653 --> 00:50:55,120\n现在 我们就有了两个矩形\nAnd it will say, oh sure, now I've got two rectangles.\n\n614\n00:51:02,346 --> 00:51:06,546\n然后先让P1在这个矩形中绘制\nAnd now it goes off to P1 and says P1, well draw yourself in this rectangle,\n\n615\n00:51:07,360 --> 00:51:11,640\n然后让P2在这个矩形中绘制\nand goes off to P2, and says, P2, fine, draw yourself in this rectangle.\n\n616\n00:51:13,280 --> 00:51:16,880\nBESIDE仅仅需要计算出这些矩形来\nThe only computation it has to do is figure out what these rectangles are.\n\n617\n00:51:17,360 --> 00:51:23,973\n由于矩形是由原点、水平向量和竖直向量组成\nRemember a rectangle is specified by an origin and a horizontal vector and a vertical vector.\n\n618\n00:51:23,986 --> 00:51:25,940\nBESIDE操作需要计算出这些要素\nso it's got to figure out what these things are.\n\n619\n00:51:27,373 --> 00:51:32,293\n所以对第一个矩形来说 原点变成了矩形的原点\nSo for this first rectangle, the origin turns out to be the origin of the original rectangle,\n\n620\n00:51:33,640 --> 00:51:37,800\n竖直向量与原矩形相同 不发生变化\nand the vertical vector is the same as the vertical vector of the original rectangle.\n\n621\n00:51:38,893 --> 00:51:46,600\n水平向量是原始矩形的水平向量缩放A倍得到的\nThe horizontal vector is the horizontal vector of the original rectangle scaled by A.\n\n622\n00:51:47,493 --> 00:51:48,906\n这就是第一个矩形\nAnd that's the first rectangle.\n\n623\n00:51:49,460 --> 00:51:52,693\n第二个矩形的原点是\nThe second rectangle, the origin\n\n624\n00:51:54,066 --> 00:51:59,653\n原矩形的原点加上矩形的水平向量缩放A倍\nThe second rectangle, the origin is the original origin plus that horizontal vector scaled by A.\n\n625\n00:52:01,200 --> 00:52:03,400\n第二个矩形的水平向量是\nThe horizontal vector of the second rectangle is\n\n626\n00:52:03,770 --> 00:52:06,040\n除去前一个矩形水平向量所余下的部分\nthe rest of the horizontal vector of the first one,\n\n627\n00:52:06,346 --> 00:52:11,660\n也就是(1-A)*H H是原矩形的水平向量\nwhich is 1 minus A times the original H,\n\n628\n00:52:12,053 --> 00:52:13,773\n它的竖直向量还是V\nand the vertical vector is still v.\n\n629\n00:52:15,480 --> 00:52:17,986\n基本上 BESIDE就是构造这两个矩形\nBut basically it goes and constructs these two rectangles,\n\n630\n00:52:18,000 --> 00:52:20,573\n但重要的是 一旦构造好这些矩形\nand the important point is having constructed the rectangles,\n\n631\n00:52:20,933 --> 00:52:24,586\n它就能让P1、P2在正确的位置绘制\nit says OK, p1, you draw yourself in there, and p2, you draw yourself in there,\n\n632\n00:52:24,626 --> 00:52:26,186\n这就是BESIDE需要做的全部工作\nand that's all Beside has to do.\n\n633\n00:52:27,800 --> 00:52:29,306\n我们看一下代码\nAll right, let's look at that piece of code.\n\n634\n00:52:34,333 --> 00:52:35,133\n这是BESIDE\nBeside\n\n635\n00:52:39,640 --> 00:52:46,440\n(BESIDE P1 P2 A) A是缩放比例\nBeside of a picture and another picture with some scaling ratio\n\n636\n00:52:47,840 --> 00:52:53,640\n因为该过程返回图像 所以结果是一个以矩形为参数的过程\nis first of all, since it's a picture, a procedure that's going to take a rectangle as argument.\n\n637\n00:52:55,493 --> 00:52:56,560\n它做什么呢？\nWhat's it going to do?\n\n638\n00:52:56,760 --> 00:53:02,320\n它让P1在某个矩形中绘制 P2在另一个矩形中绘制\nIt says, p1 draw yourself in some rectangle and p2 draw yourself in some other rectangle.\n\n639\n00:53:03,213 --> 00:53:04,460\n现在这些矩形又是什么呢?\nAnd now what are those rectangles?\n\n640\n00:53:04,460 --> 00:53:05,480\n就在这里计算\nWell here's the computation.\n\n641\n00:53:05,480 --> 00:53:06,546\n它创建了一个矩形\nIt makes a rectangle,\n\n642\n00:53:07,520 --> 00:53:10,400\n用的是我刚才在黑板上写的几何公式 这是矩形的原点\nand this is the algebra I just did on the board: the origin, something;\n\n643\n00:53:10,400 --> 00:53:11,840\n矩形的水平向量\nthe horizontal vector, something;\n\n644\n00:53:11,840 --> 00:53:13,440\n还有矩形的竖直向量\nand the vertical vector, something.\n\n645\n00:53:13,973 --> 00:53:14,813\n对于P2\nFor p2\n\n646\n00:53:15,506 --> 00:53:19,780\n矩形需要不同的原点 水平向量和竖直向量\nAnd for p2, the rectangle it wants has some other origin and horizontal vector and vertical vector.\n\n647\n00:53:19,780 --> 00:53:20,706\n但重要的是\nBut the important point\n\n648\n00:53:21,213 --> 00:53:27,180\nBESIDE只是将这两个矩形分别传递给了P1和P2而已\nis that all it's saying is, p1, go do your thing in one rectangle, and p2, go do your thing in another rectangle.\n\n649\n00:53:27,740 --> 00:53:29,420\n这就是BESIDE所需要做的\nThat's all the Beside has to do.\n\n650\n00:53:30,840 --> 00:53:35,620\n好 ROTATE也很类似\nOK, similarly Rotate--\n\n651\n00:53:36,960 --> 00:53:42,000\n假设我有一个图像A\nsee if I have this picture A,\n\n652\n00:53:42,973 --> 00:53:46,120\n我想让它旋转90度\nand I want to look at say rotating A by 90 degrees,\n\n653\n00:53:46,373 --> 00:53:51,920\n这意味着 给定这个矩形\nwhat that should mean is, well take this rectangle,\n\n654\n00:53:53,946 --> 00:53:58,440\n它有原点、水平向量和竖直向量\nwhich is origin and horizontal vector and vertical vector,\n\n655\n00:53:58,786 --> 00:54:03,186\n现在假设已经有了这样的矩形\nand now pretend that it's really the rectangle that looks like this,\n\n656\n00:54:03,746 --> 00:54:09,120\n这个矩形的原点、水平向量和竖直向量在这里\nwhich has an origin and a horizontal vector up here, and a vertical vector there,\n\n657\n00:54:09,600 --> 00:54:12,460\n然后在矩形里各自绘制自己\nand now draw yourself with respect to that rectangle.\n\n658\n00:54:13,260 --> 00:54:15,040\n我们来看看代码\nLet me show you that as a procedure.\n\n659\n00:54:17,026 --> 00:54:19,853\n那么 ROTATE90过程\nAll right, so we'll Rotate 90 of the picture,\n\n660\n00:54:20,613 --> 00:54:22,960\n返回的也是一个以矩形为参数的过程\nbecause again, a procedure for rectangle,\n\n661\n00:54:23,253 --> 00:54:26,120\n它就是将图像绘制在一个特定矩形中\nwhich says, OK picture, draw yourself in some rectangle;\n\n662\n00:54:27,213 --> 00:54:30,660\n这个几何公式就是这个矩形的变换规则\nand then this algebra is the transformation on the rectangle.\n\n663\n00:54:30,660 --> 00:54:33,840\n这句代码让矩形看起来像向侧面的\nIt's the one which makes it look like the rectangle is sideways,\n\n664\n00:54:33,860 --> 00:54:36,520\n原点在别的地方 竖直向量在别的地方\nthe origin is someplace else and the vertical vector is someplace else,\n\n665\n00:54:37,133 --> 00:54:39,746\n水平向量在别的地方 竖直向量在别的地方\nand the horizontal vector is someplace else, and vertical vector is someplace else.\n\n666\n00:54:46,760 --> 00:54:49,906\n再次注意 这里的关键是\nOK, again notice, the crucial thing that's going on here\n\n667\n00:54:50,533 --> 00:55:00,973\n关键是使用过程来表示图像 使其自动地具有闭包性质\nis you're using the representation of pictures as procedures to automatically get the closure property,\n\n668\n00:55:01,740 --> 00:55:05,220\n这是因为 实际上 BESIDE只是接受并使用P1\nbecause what happens is, Beside just has this thing p1.\n\n669\n00:55:05,220 --> 00:55:09,400\nBESIDE并不关心它是一个基本图像还是一些线段\nBeside doesn't care if that's a primitive picture or it's line segments\n\n670\n00:55:09,610 --> 00:55:12,693\n或者P1还是ABOVE、BESIDE、ROTATE等操作的结果\nif p1 is, itself, the result of doing Aboves or Besides or Rotates.\n\n671\n00:55:12,720 --> 00:55:16,080\n关于P1 BESIDE需要知道的就是\nAll Beside has to know about, say, p1\n\n672\n00:55:16,293 --> 00:55:19,733\n给P1传递一个矩形 就会导致某物的绘制\np1 is that if you hand p1 a rectangle, it will cause something to be drawn.\n\n673\n00:55:21,040 --> 00:55:25,986\n在这个层面上 BESIDE并不关心P1是如何完成绘制\nAnd above that level, Beside just doesn't-- it's none of its business how p1 accomplishes that drawing.\n\n674\n00:55:27,733 --> 00:55:32,253\n我们使用过程来表示图像 以保持它的闭包性质\nAll right, so you're using the procedural representation to ensure this closure.\n\n675\n00:55:35,640 --> 00:55:40,813\n将图像实现为过程 使得组合的方法变得\nSo implementing pictures as procedures makes these means of combination,\n\n676\n00:55:41,186 --> 00:55:43,933\n变得简单而优雅\nboth pretty simple and also, I think, elegant.\n\n677\n00:55:45,920 --> 00:55:48,220\n但这并不是点睛之笔\nBut that's not the real punchline.\n\n678\n00:55:49,280 --> 00:55:53,520\n点睛之笔来自于这门语言中抽象的方法\nThe real punchline comes when you look at the means of abstraction in this language.\n\n679\n00:55:54,700 --> 00:55:56,240\n我们做了些什么？\nBecause what have we done?\n\n680\n00:55:56,240 --> 00:56:03,720\n我们把组合的方法实现为了过程\nWe've implemented the means of combination themselves as procedures.\n\n681\n00:56:05,853 --> 00:56:09,386\n这也就意味着 当我们对这个语言进行抽象时\nAnd what that means is that when we go to abstract in this language,\n\n682\n00:56:10,170 --> 00:56:15,693\nLisp提供的 操作过程的一切方法\neverything that Lisp supplies us for manipulating procedures\n\n683\n00:56:16,333 --> 00:56:21,453\n都可以自动地在这个图像语言中使用\nautomatically available to do things in this picture language.\n\n684\n00:56:21,920 --> 00:56:29,746\n与其用术语“这个语言以Lisp实现” — 虽然确实如此\nThe technical term I want to say is not only is this language implemented in Lisp, obviously it is,\n\n685\n00:56:29,760 --> 00:56:32,580\n我想描述为“这个语言嵌入于Lisp”\nbut the language is nicely embedded in Lisp.\n\n686\n00:56:37,640 --> 00:56:42,080\n也就是说 通过像这样将语言嵌入\nWhat I mean is by embedding the language in this way,\n\n687\n00:56:42,906 --> 00:56:48,860\n可以以扩展的形式 自动地获得Lisp的所有力量\nall the power of Lisp is automatically available as an extension to whatever you want to do.\n\n688\n00:56:50,060 --> 00:56:51,680\n这又是什么意思呢？\nAnd what do I mean by that?\n\n689\n00:56:51,973 --> 00:57:02,946\n举个例子 假设我想用A B C D四副图像做东西\nExample: say, suppose I want to make a thing that takes four pictures A, B, C and D,\n\n690\n00:57:03,760 --> 00:57:07,060\n让它们呈现像这样的格局\nand makes a configuration that looks like this.\n\n691\n00:57:12,500 --> 00:57:16,960\n可以将其称为FOUR-PICT格局\nWell you might call that, you know, four pictures or something, four-pict configuration.\n\n692\n00:57:16,960 --> 00:57:17,700\n我该如何做呢？\nHow do I do that?\n\n693\n00:57:17,700 --> 00:57:18,680\n我可以很容易的做到这些\nWell I can obviously do that.\n\n694\n00:57:18,680 --> 00:57:23,333\n写个过程 让B和D做ABOVE\nI just write a procedure that takes B above D\n\n695\n00:57:24,133 --> 00:57:25,853\nA和C做ABOVE\nand A above C\n\n696\n00:57:26,093 --> 00:57:27,706\n得到的结果做BESIDE\nand puts those things beside each other.\n\n697\n00:57:28,240 --> 00:57:31,820\n我自然地拥有Lisp组合过程的能力\nSo I automatically have Lisp's ability to do procedure composition.\n\n698\n00:57:32,920 --> 00:57:35,820\n这不需要我为图像语言做些特殊处理\nAnd I didn't have to make that specifically in the picture language.\n\n699\n00:57:35,820 --> 00:57:39,920\n事实上 这些组合本身就是过程\nIt's automatic from the fact that the means of combination are themselves procedures.\n\n700\n00:57:40,960 --> 00:57:44,180\n假设我想做一些更复杂的事情\nOr suppose I wanted to do something a little bit more complicated.\n\n701\n00:57:44,180 --> 00:57:46,506\n我想为这里的每一个传递一个参数\nI wanted to put in a parameter so that for each of these,\n\n702\n00:57:46,520 --> 00:57:50,080\n我可以独立地做旋转90度的操作\nI could independently specify a rotation by 90 degrees.\n\n703\n00:57:50,413 --> 00:57:52,640\n这只需要我在这个过程中加入一个参数\nThat's just putting a parameter in the procedure.\n\n704\n00:57:53,173 --> 00:57:54,560\n它自然而然就有了这样的功能\nIt's automatically there.\n\n705\n00:57:54,800 --> 00:57:57,840\n它自动地嵌入进去了\nRight, it automatically comes from the embedding.\n\n706\n00:57:58,160 --> 00:58:05,360\n甚至 假设我想使用递归\nOr even more, suppose I wanted to, you know, use recursion.\n\n707\n00:58:06,160 --> 00:58:10,780\n我们看一下图像递归组合的方法\nLet's look at a recursive means of combination on pictures.\n\n708\n00:58:10,780 --> 00:58:14,640\n定义--看看你们能理解这个不\nI could say define-- let's see if you can figure out what this one is--\n\n709\n00:58:14,693 --> 00:58:18,973\n(DEFINE (RIGHT-PUSH PICT N A))\nsuppose I say define what it means to right-push a picture,\n\n710\n00:58:22,840 --> 00:58:29,800\nRIGHT-PUSH需要图片P 整数N和缩放因数A\nright-push a picture and some integer N and some scale factor A.\n\n711\n00:58:31,460 --> 00:58:41,220\n定义是：如果N为0 那么返回图像P\nI'll define this to say if N equals 0, then the answer is the picture.\n\n712\n00:58:42,200 --> 00:58:54,020\n否则 就-- 哦 这里是P\nOtherwise I'm going to put-- oops, name change: P.\n\n713\n00:58:55,880 --> 00:59:00,213\n否则 我用图形P做BESIDE操作\nOtherwise, I'm going to take P and put it beside\n\n714\n00:59:00,920 --> 00:59:18,306\nBESIDE的另一个操作数是(RIGHT-PUSH P (- N 1) A)的结果\nthe results of recursively right-pushing P with N minus 1 and A and use a scale factor of A. OK,\n\n715\n00:59:24,720 --> 00:59:31,120\n如果N为0 就返回P 否则就对P进行A倍缩放\nso if N 0 , it's P. Otherwise I put P with a scale factor of A--\n\n716\n00:59:31,120 --> 00:59:32,800\n抱歉 我这里代码没对齐\nI'm sorry I didn't align this right--\n\n717\n00:59:33,666 --> 00:59:38,500\n递归地调用(RIGHT-PUSH P (- N 1) A) 将结果用BESIDE连接\nrecursively beside the result of right-pushing P, N minus 1 times with a scale factor of A.\n\n718\n00:59:38,500 --> 00:59:42,000\n这就是一种递归组合方法\nThere's a recursive means of combination.\n\n719\n00:59:43,786 --> 00:59:44,760\n调用的结果会是怎样的？\nWhat's that look like?\n\n720\n00:59:44,760 --> 00:59:45,906\n我们来看看\nWell, here's what it looks like.\n\n721\n00:59:46,040 --> 00:59:56,040\n这是(RIGHT-PUSH GEORGE 2 0.75)的结果\nThere's George right-pushed against himself twice with a scale factor of 0.75.\n\n722\n00:59:59,260 --> 01:00:00,720\n这个是从什么地方来的呢？\nWhere'd that come from?\n\n723\n01:00:00,720 --> 01:00:02,340\n我是如何想象出这些递归来的呢？\nHow did I get all this fancy recursion?\n\n724\n01:00:02,340 --> 01:00:05,240\n答案是无意识的 绝对是无意识的\nAnd the answer is just automatic, absolutely automatic.\n\n725\n01:00:05,240 --> 01:00:09,800\n由于它们都是过程 而嵌入的目标系统中允许定义递归过程\nSince these are procedures, the embedding says, well sure, I can define recursive procedures.\n\n726\n01:00:10,360 --> 01:00:11,680\n我不必自己去做\nI didn't have to arrange that.\n\n727\n01:00:13,560 --> 01:00:16,420\n当然 我们可以模仿这个方法做些更复杂的事\nAnd of course, we can do more complicated things of the same sort.\n\n728\n01:00:16,420 --> 01:00:18,213\n我可以定义做UP-PUSH的过程\nI could make something that does an up-push.\n\n729\n01:00:18,420 --> 01:00:22,600\n对 它可以递归地把图片放在原来的上面\nRight, that sort of goes like this, by recursively putting something above.\n\n730\n01:00:22,600 --> 01:00:26,546\n我也可以用这种策略来做些其它事\nOr I could make something that, sort of, was this scheme.\n\n731\n01:00:26,560 --> 01:00:28,853\n给定一个图像\nI might start out with a picture\n\n732\n01:00:29,786 --> 01:00:37,160\n然后递归地把它放在原图片的旁边和上面\nand then, sort of, recursively both push it aside and above\n\n733\n01:00:37,573 --> 01:00:38,920\n这里再放一些别的\nand that might put something there.\n\n734\n01:00:39,520 --> 01:00:41,826\n然后我把同样递归的图像放在这里\nAnd then up here I put the same recursive thing,\n\n735\n01:00:42,360 --> 01:00:44,200\n我可以用这个来终止\nand I might end up with something like this.\n\n736\n01:00:45,400 --> 01:00:52,500\n这个过程比RIGHT-PUSH复杂一点 但也不算太多\nRight, so there's a procedure that's a little bit more complicated than right-push but not much.\n\n737\n01:00:53,640 --> 01:00:58,140\n在BESIDE的基础上 我多加了一个ABOVE操作\nI just do an Above and a Beside, rather than just a Beside.\n\n738\n01:01:01,120 --> 01:01:06,786\n如果我把它应用于四张放在一起的图像上\nNow if I take that and apply that with the idea of putting four pictures together,\n\n739\n01:01:07,533 --> 01:01:08,653\n这样做当然没问题\nwhich I can surely do;\n\n740\n01:01:09,013 --> 01:01:14,173\n我把它应用于我们之前定义的Q上\nand I go and I apply that to Q, which we defined before, right,\n\n741\n01:01:15,973 --> 01:01:18,733\n我得到的是这个玩意儿\nwhat I end up with this is this thing,\n\n742\n01:01:20,146 --> 01:01:25,266\n\"图像Q的方形极限\" 做了两次\nwhich is, sort of, the square limit of Q, done twice.\n\n743\n01:01:28,180 --> 01:01:32,253\n好 现在我们将其与Escher的\"方形极限\"对比一下\nRight, and then we can compare that with Escher's \"Square Limit.\"\n\n744\n01:01:32,880 --> 01:01:34,533\n可以看到 这都是基于同样的思想\nAnd you see, it's sort of the same idea.\n\n745\n01:01:34,740 --> 01:01:36,940\n当然 Escher的图像更加漂亮一些\nEscher's is, of course, much, much prettier.\n\n746\n01:01:36,940 --> 01:01:44,040\n如果我们回过头审视George\nIf we go back and look at George, right, if we go look at George here--\n\n747\n01:01:44,386 --> 01:01:47,373\n我最开始用的是非常随意的设计\nsee, I started with a fairly arbitrary design\n\n748\n01:01:47,426 --> 01:01:49,260\n用了George的图像 做了一些操作\nthis picture of George and did things with it.\n\n749\n01:01:51,226 --> 01:01:53,146\n我们再看看Escher的图片\nRight, whereas if we go look at the Escher picture, right,\n\n750\n01:01:54,080 --> 01:01:56,140\nEscher的图片不是随意设计的\nthe Escher picture is not an arbitrary design.\n\n751\n01:01:56,140 --> 01:01:57,666\n这个图案非常精妙\nIt's this very, very clever thing,\n\n752\n01:01:57,893 --> 01:02:00,200\n当我们把鱼身\nso that when you take this fish body\n\n753\n01:02:01,826 --> 01:02:04,973\n把鱼身旋转并放缩 就会优美地变成下一条鱼\nand Rotate it and shrink it down, it bleeds into the next one really nicely.\n\n754\n01:02:07,400 --> 01:02:11,480\n当然我没有刻意处理过George\nAnd of course with George, I didn't really do anything like that.\n\n755\n01:02:12,120 --> 01:02:13,906\n就图像George来说\nSo if we look at George,\n\n756\n01:02:15,413 --> 01:02:18,640\n也有一些地方匹配 但不够好 比较随意\nright, there's a little bit of match up, but not very nice, and it's pretty arbitrary.\n\n757\n01:02:18,640 --> 01:02:21,533\n顺便说下 一个好的程序\nOne very nice project, by the way,\n\n758\n01:02:22,306 --> 01:02:27,540\n应该有个过程 能接受像这里George一样的基本图像\nwould be to write a procedure that could take some basic figure like this George thing\n\n759\n01:02:27,866 --> 01:02:29,626\n然后调整其中的线段终点\nand start moving the ends of the lines around,\n\n760\n01:02:29,866 --> 01:02:31,200\n这样可以得到一个好看的图像\nso you got a really nice one\n\n761\n01:02:32,133 --> 01:02:34,066\n在做“方形极限”应该注意这些\nwhen you went and did that \"Square Limit\" process.\n\n762\n01:02:34,680 --> 01:02:36,306\n这是一个非常值得思考的事情\nThat'd be a really nice thing to think about.\n\n763\n01:02:38,080 --> 01:02:39,720\n同时 我还可以进行组合\nWell so, we can combine things.\n\n764\n01:02:39,720 --> 01:02:41,040\n我们还可以使用递归过程\nWe can recursive procedures.\n\n765\n01:02:41,040 --> 01:02:43,480\n我们可以自然而然地做任何事情\nWe can do all kinds of things, and that's all automatic.\n\n766\n01:02:44,600 --> 01:02:48,520\n重点在于 在语言中实际实现另一个语言\nRight, the important point, the difference between merely implementing something in a language\n\n767\n01:02:48,693 --> 01:02:50,440\n在语言中嵌入另一个语言的差异\nand embedding something in the language,\n\n768\n01:02:50,440 --> 01:02:53,720\n这可以让你不丢失原有语言的能力 而Lisp强大之处在于\nso that you don't lose the original power of the language, and what Lisp is great at,\n\n769\n01:02:54,760 --> 01:02:57,620\nLisp是一个强悍的语言 可以处理任何特定问题\nsee Lisp is a lousy language for doing any particular problem.\n\n770\n01:02:57,620 --> 01:03:02,100\n把你想要的语言嵌入到Lisp中才是真的好\nWhat it's good for is figuring out the right language that you want and embedding that in Lisp.\n\n771\n01:03:02,100 --> 01:03:05,440\n这才是这种设计方法的真正力量\nThat's the real power of this approach to design.\n\n772\n01:03:05,693 --> 01:03:06,820\n我们可以深入一下\nOf course, we can go further.\n\n773\n01:03:06,820 --> 01:03:08,813\n在Lisp中我们还可以做些其它的事\nSee, you saw the other thing that we can do in Lisp\n\n774\n01:03:09,213 --> 01:03:17,520\n就是将通用方法抽象成高阶过程\nis capture general methods of doing things as higher order procedures.\n\n775\n01:03:19,093 --> 01:03:22,573\n在我画那些图像时 你们可能已经发现\nAnd you probably just from me drawing it got the idea that right-push\n\n776\n01:03:23,786 --> 01:03:26,613\nRIGHT-PUSH和类似的过程 就是一直在上面放东西\nand the analogous thing where you push something up and up and up and up\n\n777\n01:03:26,933 --> 01:03:33,820\n而这个CORNER-PUSH则是一种一般性思想的泛化\nand this corner push thing are all generalizations of a common kind of idea.\n\n778\n01:03:34,720 --> 01:03:37,200\n为了演示并让大家熟悉\nSo just to illustrate and give you practice in looking at a\n\n779\n01:03:37,986 --> 01:03:40,653\n使用廊腰缦回的高阶过程\nat a fairly convoluted use of higher order procedures,\n\n780\n01:03:41,120 --> 01:03:47,240\n我给大家示范一下“递归地重复某种组合方法”的一般性思想\nlet me show you the general idea of pushing some means of combination to recursively repeat it.\n\n781\n01:03:48,300 --> 01:03:50,706\n这个例子可以说明一切\nSo here's a good one to puzzle out.\n\n782\n01:03:51,220 --> 01:04:00,700\n我们可以定义一个依赖于具体组合方式的PUSH过程\nWe'll define it what it means to push using a means of combination.\n\n783\n01:04:01,493 --> 01:04:04,880\nCOMB的取值可以是BESIDE或ABOVE等\nComb is going to be something like the Beside or Above.\n\n784\n01:04:06,186 --> 01:04:07,060\n过程的体是什么呢？\nWell what's that going to be.\n\n785\n01:04:07,060 --> 01:04:12,060\n它返回一个过程 想一想BESIDE实际上是什么\nThat's going to be a procedure, remember what Beside actually was, right.\n\n786\n01:04:13,220 --> 01:04:15,186\n它接受一个图像\nIt took a picture,\n\n787\n01:04:15,960 --> 01:04:18,080\n哦  它接受两个图像和一个缩放因数\ntook two pictures and a scale factor.\n\n788\n01:04:18,626 --> 01:04:24,280\n利用这个过程 定义一个接受层数、图像和缩放因数的过程\nUsing that I produced something that took a level number and a picture and a scale factor,\n\n789\n01:04:24,280 --> 01:04:25,453\n我称之为RIGHT-PUSH\nthat I called right-push.\n\n790\n01:04:26,160 --> 01:04:33,660\n这个过程接受 图像PICT 层数N和缩放因数A\nSo this is going to be something that takes a picture, a level number and a scale factor, and it's going to say--\n\n791\n01:04:36,160 --> 01:04:39,120\n我要做一些重复操作\nI'm going to do some repeated operation.\n\n792\n01:04:39,450 --> 01:04:46,626\n我会重复应用一个接受一个图像P的过程\nI'm going to repeatedly apply the procedure which takes a picture\n\n793\n01:04:48,400 --> 01:04:50,693\n并把组合的方式应用在\nand applies the means of combination\n\n794\n01:04:51,200 --> 01:04:59,080\n应用在图像PICT和在这里接受的图像P以及缩放因数A\nto the picture and the original picture and the one I took in here and the scale factor,\n\n795\n01:05:02,266 --> 01:05:07,280\n我要重复应用这个过程N次\nand I do the thing which repeats this procedure N times,\n\n796\n01:05:12,040 --> 01:05:16,200\n我则是把这整个过程应用在原图片PICT上\nand I apply that whole thing to my original picture.\n\n797\n01:05:19,560 --> 01:05:24,480\n虽然之前没提过 这里的REPEATED也是一个高阶过程\nRepeated here, in case you haven't seen it, is another higher order procedure\n\n798\n01:05:24,533 --> 01:05:28,346\n它接受一个过程P和一个数字N\nthat takes a procedure and a number\n\n799\n01:05:29,546 --> 01:05:34,293\n它返回另一个过程：将给定的过程P重复应用N次的过程\nand returns for you another procedure that applies this procedure N times.\n\n800\n01:05:36,040 --> 01:05:39,306\n可能有些人已经在练习中编写过REPEATED了\nAnd I think some of you have already written repeated as an exercise,\n\n801\n01:05:39,706 --> 01:05:43,013\n如果还没做的话 这是理解和练习高阶过程的好机会\nbut if you haven't, it's a very good exercise in thinking about higher order procedures.\n\n802\n01:05:43,840 --> 01:05:46,906\n无论如何 我将把REPEATED过程的结果应用到PICT上\nBut in any case, the result of this repeated is what I apply to picture.\n\n803\n01:05:49,466 --> 01:05:52,386\n定义好PUSH后 这就\nAnd having done that, that's going to capture the --\n\n804\n01:05:53,120 --> 01:05:57,733\n这就是从BESIDE、RIGHT-PUSH中总结出来的一般性思想\nthat is the thing, the way I got from the idea of Beside to the idea of right-push\n\n805\n01:05:59,013 --> 01:06:13,173\n现在 我就可以把RIGHT-PUSH定义为 用BESIDE来做PUSH操作\nSo having done that, I could say define right-push to be push of Beside.\n\n806\n01:06:17,653 --> 01:06:20,320\n我也可以把UP-PUSH定义为 用ABOVE来做PUSH操作\nOr if I say, define up-push to be push of Above\n\n807\n01:06:20,346 --> 01:06:25,480\n类似地 CORNER-PUSH就是用BESIDE和ABOVE的适当组合做PUSH操作\nI'd get the analogous thing or define corner-push to be push of some appropriate thing that did both the Beside and Above,\n\n808\n01:06:25,493 --> 01:06:26,706\n我可以用任何东西做PUSH操作\nor I could push anything.\n\n809\n01:06:28,266 --> 01:06:34,760\n嗯 如果你还不太理解LAMBDA的话 可以参考这个例子\nAnyway this is, if you're having trouble with lambdas, this is an excellent exercise in figuring out what this means.\n\n810\n01:06:38,986 --> 01:06:41,000\n我们可以从这个例子中学到很多东西\nOK, well there's a lot to learn from this example.\n\n811\n01:06:42,186 --> 01:06:49,800\n我主要想要介绍的是在一个语言中嵌入另一个语言\nThe main point I've been welling on is the notion of nicely embedding a language inside another language.\n\n812\n01:06:50,666 --> 01:06:55,626\n这样 母体语言--本例中是Lisp--的所有能力\nRight, so that all the power of this language like Lisp of the surrounding language\n\n813\n01:06:55,920 --> 01:07:00,280\n可以作为你所构建语言的一种扩展而取得\nis still accessible to you and appears as a natural extension of the language that you built.\n\n814\n01:07:00,986 --> 01:07:04,000\n这个例子很好地展示了这点\nThat's one thing that this example shows very well.\n\n815\n01:07:08,146 --> 01:07:10,940\n另外 当我们回过头去思考\nAnother thing is, if you go back and think about that,\n\n816\n01:07:10,940 --> 01:07:12,280\n什么是过程 什么是数据\nwhat's procedures and what's data.\n\n817\n01:07:12,280 --> 01:07:16,200\n在这里 天啊 发生了什么\nYou know, by the time we get up to here, my God, what's going on.\n\n818\n01:07:16,200 --> 01:07:19,660\n在这里 这是一个过程 它接受一个图像和一个参数\nI mean, this is some procedure, and it takes a picture and an argument,\n\n819\n01:07:19,660 --> 01:07:20,360\n但是 什么是图像呢？\nand what's a picture.\n\n820\n01:07:20,360 --> 01:07:23,820\n请回想 图像本身 就是一个以矩形为参数的过程\nWell, a picture itself, as you remember, was a procedure, and that took a rectangle.\n\n821\n01:07:23,820 --> 01:07:25,820\n这个矩形是某种抽象\nAnd a rectangle is some abstraction.\n\n822\n01:07:26,093 --> 01:07:28,133\n我希望你们现在能彻底明白\nAnd I hope now that by now you're completely lost\n\n823\n01:07:29,146 --> 01:07:33,740\n系统中什么是过程 什么是数据\nas to the question of what in the system is procedure and what's data.\n\n824\n01:07:33,740 --> 01:07:34,780\n我们发现 它们没有任何区别\nYou see, there isn't any difference.\n\n825\n01:07:35,493 --> 01:07:36,440\n真的没有区别\nThere really isn't.\n\n826\n01:07:37,933 --> 01:07:41,426\n你可以认为图像有时候是过程 有时候是数据\nAnd you might think of a picture sometimes as a procedure and sometimes as data,\n\n827\n01:07:41,840 --> 01:07:44,900\n但是 这只是让你容易理解的一种方法\nbut that's just, sort of, you know, making you feel comfortable.\n\n828\n01:07:44,900 --> 01:07:47,306\n这有一定道理 也没有道理\nIt's really both in some sense or neither in some sense.\n\n829\n01:07:49,920 --> 01:08:02,200\n关于系统的结构 一种更普遍的观点将其视作创建一种语言\nOK, there's a more general point about the structure of the system as creating a language,\n\n830\n01:08:02,520 --> 01:08:06,746\n将工程设计过程看作是创建一门语言\nviewing the engineering design process as one of creating language or\n\n831\n01:08:07,840 --> 01:08:13,973\n准确来说 是创建各种层次的语言\nor rather one of creating a sort of sequence of layers of language.\n\n832\n01:08:14,773 --> 01:08:20,013\n众所周知 有一种方法学 或者叫做“神话学”\nYou see, there's this methodology, or maybe I should say mythology,\n\n833\n01:08:20,746 --> 01:08:24,900\n姑且叫做软件“工程”\nthat's, sort of, charitably called software, quote, engineering.\n\n834\n01:08:25,213 --> 01:08:28,040\n它声称 你要先计算出你的任务\nAll right, and what does it say, it's says well, you go and you figure out your task,\n\n835\n01:08:28,040 --> 01:08:30,040\n精确且正确地计算出你的任务\nand you figure out exactly what you want to do.\n\n836\n01:08:30,400 --> 01:08:32,200\n一但你搞清楚要做的东西\nAnd once you figure out exactly what you want to do,\n\n837\n01:08:32,226 --> 01:08:34,540\n你把它划分为三个子任务\nyou find out that it breaks out into three sub-tasks,\n\n838\n01:08:34,540 --> 01:08:35,760\n然后你开始继续做--\nand you go and you start working on--\n\n839\n01:08:35,973 --> 01:08:38,940\n你开始处理这个子任务 然后你明确它是什么\nand you work on this sub-task, and you figure out exactly what that is.\n\n840\n01:08:38,940 --> 01:08:43,040\n这个子问题就分裂成三个子任务 你把它们处理完\nAnd you find out that that breaks down into three sub-tasks, and you specify them completely,\n\n841\n01:08:43,040 --> 01:08:47,320\n然后你先处理这两个任务\nand you go and you work on those two, and you work on this sub-one, and you specify that exactly.\n\n842\n01:08:47,320 --> 01:08:51,100\n解决完子任务后 你后退到这里 处理第二个子任务\nAnd then finally when you're done, you come back way up here, and you work on your second sub-task,\n\n843\n01:08:51,100 --> 01:08:53,400\n然后把它详细地实现出来\nand specify that out and work it out.\n\n844\n01:08:53,400 --> 01:08:57,640\n结束之后-- 你完成了这个美丽的大厦\nAnd then you end up with-- you end up at the end with this beautiful edifice.\n\n845\n01:08:57,640 --> 01:09:00,253\n你最后得到了一棵非凡的树\nRight, you end up with a marvelous tree,\n\n846\n01:09:00,893 --> 01:09:08,240\n你把任务划分为子任务 子任务再划分为子任务\nthat where you've broken your task into sub-tasks and broken each of these into sub-tasks and broken those into sub-tasks, right.\n\n847\n01:09:09,880 --> 01:09:15,026\n树中的每个结点都被严谨而准确地定义\nAnd each of these nodes is exactly and precisely defined\n\n848\n01:09:15,260 --> 01:09:18,666\n为奇妙而精美的任务 以构建整栋大厦\nto do the wonderful, beautiful task to make it fit into the whole edifice\n\n849\n01:09:18,960 --> 01:09:21,140\n这个就是所谓的“神话学”\nRight, that's this mythology.\n\n850\n01:09:21,140 --> 01:09:25,920\n只有计算机科学家才可能相信你构建的复杂系统像这个样子\nSee only a computer scientist could possibly believe that you build a complex system like that\n\n851\n01:09:27,480 --> 01:09:32,800\n好了 我们用Henderson的例子来做对比\nRight. Contrast that with this Henderson example.\n\n852\n01:09:32,800 --> 01:09:34,300\n它的结构不是那样\nIt didn't work like that.\n\n853\n01:09:35,260 --> 01:09:39,333\n事实是：这里有一个语言的层次序列\nWhat happened was that there was a sequence of layers of language.\n\n854\n01:09:41,066 --> 01:09:42,053\n它是什么？\nWhat happened?\n\n855\n01:09:42,180 --> 01:09:48,760\n这里有一层 允许我们构建基本图像\nThere was a layer of a thing that allowed us to build primitive pictures.\n\n856\n01:09:51,693 --> 01:09:56,240\n这个语言描述基本图像\nThere's primitive pictures and that was a language.\n\n857\n01:09:56,320 --> 01:09:57,840\n我们并没有做过多地讨论\nI didn't say much about it.\n\n858\n01:09:58,220 --> 01:09:59,586\n我们讨论了如何构造George\nWe talked about how to construct George,\n\n859\n01:09:59,613 --> 01:10:04,880\n这个语言是在单位正方形中讨论点、线和向量\nbut that was a language where you talked about vectors and line segments and points and where they sat in the unit square.\n\n860\n01:10:06,426 --> 01:10:11,293\n而在这之上\nAnd then on top of that, right, on top of that--\n\n861\n01:10:11,973 --> 01:10:14,106\n这是讨论基本图像的语言\nso this is the language of primitive pictures.\n\n862\n01:10:17,080 --> 01:10:20,360\n讨论在特定单位正方形中线段的构造\nRight, talking about line segments in particular pictures in the unit square.\n\n863\n01:10:21,400 --> 01:10:23,800\n在这个上面是另一个完整的语言\nOn top of that was a whole language.\n\n864\n01:10:24,053 --> 01:10:30,866\n关于几何组合子的语言\nThere was a language of geometric combinators,\n\n865\n01:10:32,666 --> 01:10:36,626\n关于几何物件的位置\na language of geometric positions,\n\n866\n01:10:38,773 --> 01:10:46,500\n讨论像ABOVE、BESIDE、RIGHT-PUSH和ROTATE这样的东西\nwhich talks about things like Above and Beside and right-push and Rotate.\n\n867\n01:10:48,040 --> 01:10:55,700\n这些事情恰巧与我们在这个语言中谈论的事情有关\nAnd those things, sort of, happened with reference to the things that are talked about in this language.\n\n868\n01:10:58,570 --> 01:11:00,933\n再细化一点 我们发现在这之上\nAnd then if we like, we saw that above that\n\n869\n01:11:02,613 --> 01:11:15,100\n还有一门语言 描述组合的模式\nthere was sort of a language of schemes of combination.\n\n870\n01:11:21,250 --> 01:11:22,440\n比如说PUSH\nFor example, push,\n\n871\n01:11:24,453 --> 01:11:27,880\n也就是用一个放缩因子重复地做一件事儿\nwhich talked about repeatedly doing something over with a scale factor.\n\n872\n01:11:28,380 --> 01:11:31,280\n我们在那门语言中讨论的问题\nAnd the things that were being discussed in that language\n\n873\n01:11:31,506 --> 01:11:34,346\n正是我这里构建的东西\nwere, sort of, the things that happened down here.\n\n874\n01:11:36,306 --> 01:11:42,760\n我们在每一层上所讨论的对象\nSo what you have is, at each level, the objects that are being talked about\n\n875\n01:11:44,680 --> 01:11:47,000\n都是前一个层次所建立的\nare the things that were erected the previous level.\n\n876\n01:11:48,080 --> 01:11:52,060\n这个和这个有什么区别呢？\nWhat's the difference between this thing and this thing?\n\n877\n01:11:53,346 --> 01:11:54,186\n这是因为\nThe answer is\n\n878\n01:11:56,146 --> 01:12:01,733\n实际上在这里 树的每一个结点 每一次分解\nthat over here in the tree, each node, and in fact, each decomposition down here,\n\n879\n01:12:02,146 --> 01:12:05,253\n都是旨在分成确定的任务\nis being designed to do a specific task,\n\n880\n01:12:07,506 --> 01:12:08,880\n而在另一个方案中\nwhereas in the other scheme,\n\n881\n01:12:09,213 --> 01:12:14,800\n你在每个层级上的完完全全的语言层面的能力\nwhat you have is a full range of linguistic power at each level.\n\n882\n01:12:16,000 --> 01:12:18,080\n这里的每一个层次\nSee what's happening there, at any level,\n\n883\n01:12:20,240 --> 01:12:22,720\n都不是被设计为完成一个特定任务\nit's not being set up to do a particular task.\n\n884\n01:12:23,146 --> 01:12:26,173\n它被设计为讨论整个事情\nIt's being set up to talk about a whole range of things.\n\n885\n01:12:27,620 --> 01:12:30,786\n这样设计导致的结果是：\nThe consequence of that for design\n\n886\n01:12:31,146 --> 01:12:35,586\n用这种设计方法更加健壮\nis that something that's designed in that method is likely to be more robust,\n\n887\n01:12:36,613 --> 01:12:38,200\n我所谓的“健壮”是指\nwhere by robust, I mean\n\n888\n01:12:38,440 --> 01:12:41,240\n当你在描述中做一些改变\nthat if you go and make some change in your description,\n\n889\n01:12:42,700 --> 01:12:48,040\n我们可以做出相应的改变\nit's more likely to be captured by a corresponding change,\n\n890\n01:12:49,226 --> 01:12:52,600\n用上一层语言实现的方法改变即可\nin the way that the language is implemented at the next level up,\n\n891\n01:12:54,293 --> 01:12:56,586\n因为你让每个层次都是完全的\nright, because you've made these levels full.\n\n892\n01:12:56,620 --> 01:12:59,660\n所以你不需要讨论像BESIDE这样的特定操作\nSo you're not talking about a particular thing like Beside.\n\n893\n01:12:59,946 --> 01:13:03,786\n你为表达这类事物创造了完备的词汇\nYou've given yourself a whole vocabulary to express things of that sort,\n\n894\n01:13:04,773 --> 01:13:07,020\n所以当你轻微修改规格指标时\nso if you go and change your specifications a little bit,\n\n895\n01:13:07,020 --> 01:13:11,386\n这种方法论可以捕捉并适应那些变化\nit's more likely that your methodology will able to adapt to capture that change,\n\n896\n01:13:12,693 --> 01:13:15,020\n然而这种设计却不够健壮\nwhereas a design like this is not going to be robust,\n\n897\n01:13:15,020 --> 01:13:17,080\n因为 如果我在这里改变一下\nbecause if I go and change something that's in here,\n\n898\n01:13:17,533 --> 01:13:21,693\n那可能会影响我划分这些东西的方式 严重地影响\nthat might affect the entire way that I decomposed everything down, further down the tree.\n\n899\n01:13:23,200 --> 01:13:29,740\n分解观点的最大不同在于 按层次还是严格继承分解\nRight, so very big difference in outlook in decomposition, levels of language rather than, sort of, a strict hierarchy.\n\n900\n01:13:30,520 --> 01:13:33,026\n不只是如此 当你有多个层次的语言时\nNot only that, but when you have levels of language\n\n901\n01:13:33,506 --> 01:13:35,920\n你就有了不同的词汇储备\nyou've given yourself a different vocabularies\n\n902\n01:13:36,453 --> 01:13:38,740\n用于讨论不同层次上的设计\nfor talking about the design at different levels.\n\n903\n01:13:38,740 --> 01:13:40,920\n我们再回过头来看看George\nSo if we go back and look at George one last time,\n\n904\n01:13:41,906 --> 01:13:44,080\n如果我想改变图像George\nif I wanted to change this picture George,\n\n905\n01:13:45,853 --> 01:13:48,680\n我立马得到了一种不同的方式来描述变化\nsee suddenly I have a whole different ways of describing the change.\n\n906\n01:13:48,680 --> 01:13:56,080\n比如 我想在基本设计的层面上 移动某些向量的终点\nLike for example, I may want to go to the basic primitive design and move the endpoint of some vector.\n\n907\n01:13:57,760 --> 01:14:00,760\n我会在最底层讨论这个改变\nThat's a change that I would discuss at the lowest level.\n\n908\n01:14:01,000 --> 01:14:02,506\n我会另外指定终点位置\nI would say the endpoint is somewhere else.\n\n909\n01:14:03,346 --> 01:14:07,986\n我也可以说 我想在这个小的重复元素上做文章\nOr I might come up and say, well the next thing I wanted to do, this little replicated element,\n\n910\n01:14:09,106 --> 01:14:10,940\n我可能想做些其它操作\nI might want to do by something else.\n\n911\n01:14:10,940 --> 01:14:13,840\n我想在BESIDE中使用一个缩放因数\nI might want to put a scale factor in that Beside.\n\n912\n01:14:13,840 --> 01:14:19,340\n这个改变我会在更高的层次上讨论：在组合子的层次\nThat's a change that I would discuss at the next level of design, the level of combinators.\n\n913\n01:14:19,340 --> 01:14:25,053\n我也可以改变图像的基本组合模式\nOr I might want to say, I might want to change the basic way that I took this pattern\n\n914\n01:14:26,493 --> 01:14:30,480\n做一些递归地分解 可能不会让它们填充满角落\nand made some recursive decomposition, maybe not bleeding out toward the corners or something else.\n\n915\n01:14:31,160 --> 01:14:34,180\n而这样的一个变化 我会在最高层次讨论\nThat would be a change that I would discuss at the highest level.\n\n916\n01:14:34,180 --> 01:14:36,373\n正是因为我按这种结构组织系统\nAnd because I've structured the system to be this way,\n\n917\n01:14:36,520 --> 01:14:39,626\n我有所有的词汇 可以用不同的方式描述变化\nI have all these vocabularies for talking about change in different ways\n\n918\n01:14:39,653 --> 01:14:42,480\n而且可以灵活地决定哪个更合适\nand a lot of flexibility to decide which one's appropriate.\n\n919\n01:14:44,740 --> 01:14:51,053\n这就是Lisp中不同于软件工程方法论的最大要点\nOK, well that's sort of a big point about the difference in software methodology that comes out from Lisp,\n\n920\n01:14:51,250 --> 01:14:55,453\n它来自于这样一个观点：真正的设计过程\nand it all comes again, out of the notion that really, the design process\n\n921\n01:14:56,120 --> 01:14:59,620\n与其说是在设计程序 不如说是在设计语言\nis not so much implementing programs as implementing languages.\n\n922\n01:14:59,620 --> 01:15:01,093\n而这就是Lisp的力量\nAnd that's really the power of Lisp.\n\n923\n01:15:02,213 --> 01:15:03,613\n谢谢大家 下课\nOK, thank you. Let's take a break.\n\n924\n01:15:05,690 --> 01:15:15,626\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n925\n01:15:15,653 --> 01:15:23,370\n本项目主页\nhttps://github.com/FoOTOo/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec3b.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:02,320\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:02,573 --> 00:00:06,013\n翻译&&时间轴：邓雄飞（Dysprosium）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:06,066 --> 00:00:08,973\n特别感谢：裘宗燕教授\n\n4\n00:00:11,240 --> 00:00:14,460\n符号化求导系统，引用\nSymbolic Differentiation: Quotation\n\n5\n00:00:19,100 --> 00:00:23,413\n教授：嗯 Harold教授讲解了如何构造健壮的系统\nPROFESSOR: Well, Hal just told us how you build robust systems.\n\n6\n00:00:23,800 --> 00:00:26,173\n关键点就是\nThe key idea was--\n\n7\n00:00:26,813 --> 00:00:30,200\n我想你们大多还没吃透其中的要点\nI'm sure that many of you don't really assimilate that yet--\n\n8\n00:00:30,200 --> 00:00:33,773\n要点就是 为了让系统具有健壮性\nbut the key idea is that in order to make a system that's robust,\n\n9\n00:00:33,933 --> 00:00:36,480\n应该让它对小变化不敏感\nit has to be insensitive to small changes,\n\n10\n00:00:36,600 --> 00:00:37,373\n也就是说\nthat is,\n\n11\n00:00:37,373 --> 00:00:40,906\n问题中的小改变只会导致解决方案的小改动\na small change in the problem should lead to only a small change in the solution.\n\n12\n00:00:41,320 --> 00:00:42,906\n系统应该是连续的\nThere ought to be a continuity.\n\n13\n00:00:42,900 --> 00:00:45,946\n在问题空间中 解的空间是连续的\nThe space of solutions ought to be continuous in this space of problems.\n\n14\n00:00:46,253 --> 00:00:48,760\nHarold教授给你们解释过\nThe way he was explaining how to do that\n\n15\n00:00:49,460 --> 00:00:54,786\n与其在问题分解出的子问题上 求解具体问题\nwas instead of solving a particular problem at every level of decomposition of the problem at the subproblems,\n\n16\n00:00:55,080 --> 00:00:56,780\n你不如解决一类问题\nwhere you solve the class of problems,\n\n17\n00:00:56,780 --> 00:01:00,400\n也就是你想要解决的具体问题的“邻居”\nwhich are a neighborhood of the particular problem that you're trying to solve.\n\n18\n00:01:01,400 --> 00:01:04,760\n解决之道便是在该层次上构造一门语言\nThe way you do that is by producing a language at that level of detail\n\n19\n00:01:04,760 --> 00:01:10,333\n使得我们可以用这门语言来表述这类问题\nin which the solutions to that class of problems is representable in that language.\n\n20\n00:01:11,373 --> 00:01:15,093\n因此 当着手解决的问题再发生变动时\nTherefore when you change makes more changes to the problem you're trying to solve,\n\n21\n00:01:15,090 --> 00:01:19,293\n通常 你只需要在已构造好的解决方案上做出微小改动\nyou generally have to make only small local changes to the solution you've constructed,\n\n22\n00:01:19,293 --> 00:01:22,266\n因为在你所考虑的层次上\nbecause at the level of detail you're working,\n\n23\n00:01:22,266 --> 00:01:24,266\n有一门语言可以表达\nthere's a language where you can express\n\n24\n00:01:24,800 --> 00:01:28,146\n类似问题的各种解法\nthe various solutions to alternate problems of the same type.\n\n25\n00:01:30,040 --> 00:01:33,746\n呃... 这是一个重要思想的萌芽\nWell that's the beginning of a very important idea,\n\n26\n00:01:34,400 --> 00:01:38,613\n该思想的重要性也使得计算机科学比\nthe most important perhaps idea that makes computer science more powerful\n\n27\n00:01:38,613 --> 00:01:42,373\n其它大多数工程学科还要强大\nthan most of the other kinds of engineering disciplines we know about.\n\n28\n00:01:43,386 --> 00:01:44,733\n目前为止 我们学习的是\nWhat we've seen so far\n\n29\n00:01:44,733 --> 00:01:48,786\n类似于 如何使用语言内置元素\nis sort of how to use embedding of languages.\n\n30\n00:01:49,266 --> 00:01:53,360\n当然 内置元素的力量一部分来源于\nAnd, of course, the power of embedding languages partly comes from\n\n31\n00:01:54,120 --> 00:01:56,866\n像这个一样的过程 我昨天给你们展示过了\nprocedures like this one that I showed you yesterday.\n\n32\n00:01:57,373 --> 00:02:02,133\n这里 是一份求导程序 昨天给你们描述过了\nWhat you see here is the derivative program that we described yesterday.\n\n33\n00:02:02,130 --> 00:02:05,920\n这个过程以一个过程为参数\nIt's a procedure that takes a procedure as an argument\n\n34\n00:02:06,000 --> 00:02:07,920\n并返回一个过程\nand returns a procedure as a value.\n\n35\n00:02:09,613 --> 00:02:12,653\n用这样的东西棒极了\nAnd using such things is very nice.\n\n36\n00:02:12,653 --> 00:02:14,653\n你可以像创建PUSH组合子那样构造\nYou can make things like push combinators\n\n37\n00:02:14,650 --> 00:02:16,866\n可以像上节课看到的那些奇妙东西那样\nand all that sort of wonderful thing that you saw last time.\n\n38\n00:02:17,680 --> 00:02:20,546\n现在 我要来打个太极\nHowever, now I'm going to really muddy the waters.\n\n39\n00:02:21,560 --> 00:02:25,906\n这个程序混淆了过程和数据\nSee this confuses the issue of what's the procedure and what is data,\n\n40\n00:02:26,560 --> 00:02:27,813\n虽然程度不算太重\nbut not very badly.\n\n41\n00:02:28,426 --> 00:02:30,906\n而我们将要严重地混淆两者\nWhat we really want to do is confuse it very badly.\n\n42\n00:02:31,186 --> 00:02:32,440\n最好的做法就是\nAnd the best way to do that\n\n43\n00:02:32,440 --> 00:02:37,626\n参与到过程自身所描述的代数表达式的操作中\nis to get involved with the manipulation of the algebraic expressions that the procedures themselves are expressed in.\n\n44\n00:02:39,733 --> 00:02:45,586\n所以 这里我不会讨论这张幻灯片上的东西\nSo at this point, I want to talk about instead of things like on this slide,\n\n45\n00:02:45,893 --> 00:02:49,720\n一个通过操作过程的求导程序\nthe derivative procedure being a thing that manipulates a procedure--\n\n46\n00:02:49,720 --> 00:02:51,946\n这只是一个数值化方法而已\nthis is a numerical method you see here.\n\n47\n00:02:51,946 --> 00:02:58,933\n你们所看到的是 通过数值方法来近似的求导程序\nAnd what you're seeing is a representation of the numerical approximationto the derivative.\n\n48\n00:02:59,293 --> 00:03:00,440\n也就是这里的东西了\nThat's what's here.\n\n49\n00:03:00,866 --> 00:03:04,933\n事实上 我想讨论的是这些东西\nIn fact what I'd like to talk about is instead things that look like this.\n\n50\n00:03:06,053 --> 00:03:11,333\n这是一份从微积分书中摘录的法则\nAnd what we have here are rules from a calculus book.\n\n51\n00:03:12,093 --> 00:03:16,173\n这对表达式求导的法则\nThese are rules for finding the derivatives of the expressions\n\n52\n00:03:16,706 --> 00:03:20,586\n只不过是用代数语言书写的\nthat one might write in some algebraic language.\n\n53\n00:03:21,640 --> 00:03:24,413\n法则说 常数的导数是0\nIt says things like a derivative of a constant is 0.\n\n54\n00:03:25,133 --> 00:03:29,093\n而代表你所讨论的那个数的变量导数为1\nThe derivative of the valuable with respect to which you are taking the derivative is 1.\n\n55\n00:03:29,320 --> 00:03:31,933\n常数乘以函数的导数\nThe derivative of a constant times the function\n\n56\n00:03:32,093 --> 00:03:34,373\n其值是常数的值乘以函数导数的值\nis the constant times the derivative of the function,\n\n57\n00:03:34,773 --> 00:03:36,040\n就是这个意思\nand things like that.\n\n58\n00:03:38,053 --> 00:03:41,386\n这些都是精确的表达式 而非数值近似\nThese are exact expressions. These are not numerical approximations.\n\n59\n00:03:42,960 --> 00:03:44,520\n我们还能编写程序吗？\nCan we make programs?\n\n60\n00:03:44,520 --> 00:03:52,240\n事实上 编写处理这些表达式的程序非常容易\nAnd, in fact, it's very easy to make programs that manipulate these expressions.\n\n61\n00:03:56,386 --> 00:03:59,520\n让我们仔细地看看这些法则\nWell let's see. Let's look at these rules in some detail.\n\n62\n00:04:01,080 --> 00:04:05,226\n你们曾经在初等微积分课上学过这些法则了\nYou all have seen these rules in your elementary calculus class at one time or another.\n\n63\n00:04:05,980 --> 00:04:12,120\n你们知道 微积分中对多元表达式求导很容易\nAnd you know from calculus that it's easy to produce derivatives of arbitrary expressions.\n\n64\n00:04:12,533 --> 00:04:16,053\n在微积分课上 你们也知道计算积分不容易\nYou also know from your elementary calculus that it's hard to produce integrals.\n\n65\n00:04:16,986 --> 00:04:19,373\n虽然积分和求导相对\nYet integrals and derivatives are opposites of each other.\n\n66\n00:04:19,520 --> 00:04:21,280\n它俩互为逆运算\nThey're inverse operations.\n\n67\n00:04:21,613 --> 00:04:23,306\n但它们有同样的法则\nAnd they have the same rules.\n\n68\n00:04:24,160 --> 00:04:29,680\n但这些法则中又有什么特殊的东西\nWhat is special about these rules that makes it possible for one\n\n69\n00:04:29,680 --> 00:04:33,653\n使得求导容易 求积分就困难呢？\nto produce derivatives easily and integrals why it's so hard?\n\n70\n00:04:34,853 --> 00:04:36,986\n我们浅显地想一想\nLet's think about that very simply.\n\n71\n00:04:37,400 --> 00:04:38,386\n仔细考察法则\nLook at these rules.\n\n72\n00:04:39,360 --> 00:04:43,066\n对于每条法则来说 你求导数时的方向\nEvery one of these rules, when used in the direction for taking derivatives,\n\n73\n00:04:43,060 --> 00:04:44,800\n这个箭头的方向\nwhich is in the direction of this arrow,\n\n74\n00:04:46,680 --> 00:04:49,160\n法则的左边与你的表达式相匹配\nthe left side is matched against your expression,\n\n75\n00:04:49,160 --> 00:04:53,053\n法则的右边就是表达式的导数\nand the right side is the thing which is the derivative of that expression.\n\n76\n00:04:54,026 --> 00:04:55,653\n箭头是这个方向的\nThe arrow is going that way.\n\n77\n00:04:57,373 --> 00:05:00,453\n每条法则中\nIn each of these rules,\n\n78\n00:05:01,240 --> 00:05:03,720\n法则右边的表达式\nthe expressions on the right-hand side of the rule\n\n79\n00:05:03,720 --> 00:05:06,560\n都是求导过程中的子表达式\nthat are contained within derivatives are subexpressions,\n\n80\n00:05:06,560 --> 00:05:10,293\n都是左边式子的合法子表达式\nare proper subexpressions, of the expression on the left-hand side.\n\n81\n00:05:10,600 --> 00:05:13,253\n这里 我们发现 和的导数\nSo here we see the derivative of the sum,\n\n82\n00:05:13,920 --> 00:05:16,133\n也就是左边式子的导数\nwitch is the expression on the left-hand side\n\n83\n00:05:16,133 --> 00:05:18,386\n就是两部分导数之和\nis the sum of the derivatives of the pieces.\n\n84\n00:05:20,080 --> 00:05:24,493\n法则从左至右的方向是“归约规则”\nSo the rule of moving to the right are reduction rules.\n\n85\n00:05:25,026 --> 00:05:26,613\n问题变简单了\nThe problem becomes easier.\n\n86\n00:05:27,560 --> 00:05:31,480\n我把一个复杂的问题 转化成了许多小点儿的问题\nI make, I turn a big complicated problem it's lots of smaller problems\n\n87\n00:05:32,440 --> 00:05:35,760\n然后把结果组合起来 这里用递归可以完美地解决\nand then combine the results, a perfect place for recursion to work.\n\n88\n00:05:36,586 --> 00:05:40,853\n但如果我从另外的方向来思考\nIf I'm going in the other direction like this,\n\n89\n00:05:41,813 --> 00:05:45,133\n如果我想求积分的话 你会发现有很多问题\nif I'm trying to produce integrals, well there are several problems you see here.\n\n90\n00:05:45,240 --> 00:05:49,093\n就比如 如果我想求一个和的积分\nFirst of all, if I try to integrate an expression like a sum,\n\n91\n00:05:49,213 --> 00:05:50,813\n就会匹配多条法则\nmore than one rule matches.\n\n92\n00:05:50,810 --> 00:05:52,106\n这条匹配\nHere's one that matches.\n\n93\n00:05:52,480 --> 00:05:53,653\n这条也匹配\nHere's one that matches.\n\n94\n00:05:54,813 --> 00:05:57,093\n我不知道该用哪个——它们之间可能不一样\nI don't know which one to take. And they may be different.\n\n95\n00:05:57,706 --> 00:06:00,000\n我得考察两者的不同之处\nI may get to explore different things.\n\n96\n00:06:00,253 --> 00:06:03,640\n所以 在这个方向上 表达式变复杂了\nAlso, the expressions become larger in that direction.\n\n97\n00:06:04,533 --> 00:06:06,306\n当表达式变复杂时\nAnd when the expressions become larger,\n\n98\n00:06:06,306 --> 00:06:10,560\n就没法保证我所选的路径一定能终止了\nthen there's no guarantee that any particular path I choose will terminate,\n\n99\n00:06:10,946 --> 00:06:13,466\n因为唯一的可能是偶然的约分\nbecause we will only terminate by accidental cancellation.\n\n100\n00:06:14,240 --> 00:06:18,053\n这也就是为什么 积分是一种复杂的搜索 而难以完成\nSo that's why integrals are complicated searches and hard to do.\n\n101\n00:06:19,120 --> 00:06:20,960\n现在我不想处理这么复杂的东西\nRight now I don't want to do anything as hard as that.\n\n102\n00:06:21,493 --> 00:06:23,066\n我们先来讨论求导数\nLet's work on derivatives for a while.\n\n103\n00:06:24,146 --> 00:06:28,133\n好吧 我就假设你们都大致了解这些法则了\nWell, these rules are ones you know for the most part hopefully.\n\n104\n00:06:28,786 --> 00:06:31,880\n让我们来看看能不能用程序表达这些法则\nSo let's see if we can write a program which is these rules.\n\n105\n00:06:32,226 --> 00:06:33,720\n这应该很容易\nAnd that should be very easy.\n\n106\n00:06:34,893 --> 00:06:36,213\n信手拈来\nJust write the program.\n\n107\n00:06:36,690 --> 00:06:39,293\n因为 我给你们展示的是“归约规则”\nSee, because while I showed you is that it's a reduction rule,\n\n108\n00:06:39,293 --> 00:06:41,293\n这样用递归来编写会比较合适\nit's something appropriate for a recursion.\n\n109\n00:06:43,080 --> 00:06:45,720\n当然 对每条法则来说就是一种情况\nAnd, of course, what we have for each of these rules is we have a case\n\n110\n00:06:46,666 --> 00:06:47,786\n我们做“分情况分析”\nin some case analysis.\n\n111\n00:06:48,586 --> 00:06:50,360\n我就这么写了\nSo I'm just going to write this program down.\n\n112\n00:06:52,880 --> 00:06:57,693\n当然 我得先让大家达成共识 对吧？\nNow, of course, I'm going to be saying something you have to believe. Right?\n\n113\n00:06:57,690 --> 00:07:00,333\n你们应该意识到到我可以表示这些代数式\nWhat you have to believe is I can represent these algebraic expressions,\n\n114\n00:07:00,680 --> 00:07:03,880\n我可以从中抽取式子 也可以将它们组合起来\nthat I can grab their parts, that I can put them together.\n\n115\n00:07:04,240 --> 00:07:06,493\n我们发明了表结构来解决这个问题\nWe've invented list structures so that you can do that.\n\n116\n00:07:07,520 --> 00:07:09,146\n但现在我们不必关心\nBut you don't want to worry about that now.\n\n117\n00:07:09,666 --> 00:07:12,453\n现在 我要编写一个程序来封装这些法则\nRight now I'm going to write the program that encapsulates these rules\n\n118\n00:07:12,760 --> 00:07:15,853\n但它不依赖于代数表达式的表示法\nindependent of the representation of the algebraic expressions.\n\n119\n00:07:20,426 --> 00:07:28,840\n(DERIV EXP VAR)表示表达式EXP关于变量VAR的导数\nYou have a derivative of an expression with respect to a variable.\n\n120\n00:07:30,506 --> 00:07:33,080\n这和函数的导数是不一样的\nThis is a different thing than the derivative of the function.\n\n121\n00:07:34,826 --> 00:07:38,613\n那个是我们上节课看到的数值近似\nThat's what we saw last time, that numerical approximation.\n\n122\n00:07:39,000 --> 00:07:40,826\n并不能看到函数内部\nIt's something you can't open up a function.\n\n123\n00:07:40,820 --> 00:07:41,893\n它只是一个数值\nIt's just the answers.\n\n124\n00:07:43,093 --> 00:07:45,186\n表达式的导数也是一个表达式\nThe derivative of an expression is the way it's written.\n\n125\n00:07:45,746 --> 00:07:47,853\n因此 这只是一个语法问题\nAnd therefore it's a syntactic phenomenon.\n\n126\n00:07:48,293 --> 00:07:51,626\n我们今天要做的大多数工作 就是讨论语法\nAnd so a lot of what we're going to be doing today is worrying about syntax,\n\n127\n00:07:52,333 --> 00:07:54,120\n表达式的语法或类似\nsyntax of expressions and things like that.\n\n128\n00:07:54,706 --> 00:07:55,933\n首先要做“分情况分析”\nWell, there's a case analysis.\n\n129\n00:07:57,500 --> 00:08:01,080\n任何时候我们处理复杂事物 需要递归求解时\nAnytime we do anything complicated thereby a recursion,\n\n130\n00:08:01,080 --> 00:08:02,640\n我们很可能需要“按情况分析”\nwe presumably need a case analysis.\n\n131\n00:08:03,626 --> 00:08:05,160\n通常都是这样开始的\nIt's the essential way to begin.\n\n132\n00:08:05,160 --> 00:08:07,400\n复杂的问题都是用“按情况分析”\nAnd that's usually a conditional of some large kind.\n\n133\n00:08:08,080 --> 00:08:09,973\n那么 有哪些可能（的情况）呢？\nWell, what are their possibilities?\n\n134\n00:08:09,973 --> 00:08:12,533\n第一条法则说 如果你遇到一个常数\nthe first rule that you saw is this something a constant?\n\n135\n00:08:16,506 --> 00:08:17,506\n这里 我就是在判断\nAnd what I'm asking is,\n\n136\n00:08:17,506 --> 00:08:22,226\n表达式EXP是否为给定变量VAR的常数（常量表达式）\nis the expression a constant with respect to the variable given?\n\n137\n00:08:24,906 --> 00:08:27,080\n是的话 结果就是0\nIf so, the result is 0,\n\n138\n00:08:27,506 --> 00:08:30,106\n因为导数表征的是某物的变化率\nbecause the derivative represents the rate of change of something.\n\n139\n00:08:31,760 --> 00:08:32,653\n然而\nIf, however,\n\n140\n00:08:32,893 --> 00:08:40,693\n如果我求导的表达式 与我关心的变量有关\nthe expression that I'm taking the derivative of is the variable I'm varying,\n\n141\n00:08:41,720 --> 00:08:50,426\n如果判定表达式和变量相同\nthen this is the same variable, the expression var,\n\n142\n00:08:51,146 --> 00:08:54,520\n那么关于变量VAR的表达式EXP的变化率就是1\nthen the rate of change of the expression with respect to the variable is 1.\n\n143\n00:08:55,506 --> 00:08:56,546\n它俩相同 结果是1\nIt's the same 1.\n\n144\n00:08:58,906 --> 00:09:00,773\n当然 还可能有其它的可能性\nWell now there are a couple of other possibilities.\n\n145\n00:09:01,333 --> 00:09:03,146\n比如说 它可能是一个和式\nIt could, for example, be a sum.\n\n146\n00:09:03,866 --> 00:09:05,880\n呃 我现在还完全知道该如何表示和式\nWell, I don't know how I'm going to express sums yet.\n\n147\n00:09:06,090 --> 00:09:08,253\n事实上我可以 只是我还没有告诉你们\nActually I do. But I haven't told you yet.\n\n148\n00:09:10,346 --> 00:09:11,786\n如果表达式是和式\nBut is it a sum?\n\n149\n00:09:12,480 --> 00:09:14,480\n我就假想有一种方式可以判别（和式）\nI'm imagining that there's some way of telling.\n\n150\n00:09:15,306 --> 00:09:19,440\n这里 我要做一个表达式的类型分派\nI'm doing a dispatch on the type of the expression here,\n\n151\n00:09:20,773 --> 00:09:23,573\n这是在构建语言时绝对必要的\nabsolutely essential in building languages.\n\n152\n00:09:24,720 --> 00:09:26,373\n因为语言由不同的表达式构成\nCause languages are made out of different expressions.\n\n153\n00:09:26,480 --> 00:09:27,546\n我们马上就将看到\nAnd soon we're going to see that\n\n154\n00:09:27,840 --> 00:09:31,026\n如何用更强大的方法 用语言去构建语言\nin our more powerful methods of building languages on languages.\n\n155\n00:09:32,533 --> 00:09:34,026\n表达式是和式吗？\nIs an expression a sum?\n\n156\n00:09:35,453 --> 00:09:38,826\n如果是的话 很好 我们已经知道和式的求导法则了\nIf it's a sum, well, we know the rule for derivative of the sum\n\n157\n00:09:38,826 --> 00:09:41,333\n即是各部分导数之和\nis the sum of the derivatives of the parts.\n\n158\n00:09:42,133 --> 00:09:44,320\n其中一个叫做加数 另一个叫做被加数\nOne of them is called the addend and the other is the augend.\n\n159\n00:09:44,320 --> 00:09:46,800\n黑板上没那么多空间写这么长的名字了\nBut I don't have enough space on the blackboard to such long names.\n\n160\n00:09:46,800 --> 00:09:48,400\n我就姑且把它们叫做 A1和A2\nSo I'll call them A1 and A2.\n\n161\n00:09:49,040 --> 00:09:50,373\n把它们求和\nI want to make a sum.\n\n162\n00:09:53,533 --> 00:09:55,680\n（意义不明）\nDo you remember which is the sub for head or the menu end?\n\n163\n00:09:57,146 --> 00:10:01,093\n是叫做被除数和除数一类的么？\nOr was it the dividend and the divisor or something like that?\n\n164\n00:10:01,653 --> 00:10:08,480\n将A1的导数...加上\nMake sum of the derivative of the A1, I'll call it.\n\n165\n00:10:08,480 --> 00:10:13,293\n这是关于变量VAR的表达式的加数\nIt's the addend of the expression with respect to the variable,\n\n166\n00:10:14,840 --> 00:10:22,760\n与A2的导数相加\nand the derivative of the A2 of the expression,\n\n167\n00:10:24,120 --> 00:10:28,253\n这两个参数的和 变量是VAR\nthose the two arguments, the addition. Respect to the variable.\n\n168\n00:10:32,360 --> 00:10:34,933\n我们知道还有一条乘法的求导法则\nAnd another rule that we know is product rule,\n\n169\n00:10:35,200 --> 00:10:37,440\n也就是说 如果表达式是乘式\nwhich is, if the expression is a product.\n\n170\n00:10:43,213 --> 00:10:46,106\n顺便说下 当你定义过程时 有个好习惯\nBy the way, it's a good idea when you're defining things,\n\n171\n00:10:46,960 --> 00:10:48,320\n就是在定义谓词时\nwhen you're defining predicates,\n\n172\n00:10:48,853 --> 00:10:50,960\n将谓词名以问号结尾\nto give them a name that ends in a question mark.\n\n173\n00:10:51,080 --> 00:10:52,893\n问号本身不代表什么\nThis question mark doesn't mean anything.\n\n174\n00:10:53,106 --> 00:10:54,506\n但这是俗成的约定\nIt's for us as an agreement.\n\n175\n00:10:54,613 --> 00:10:58,946\n这是人们之间约定的接口 以方便他人阅读你的脚本\nIt's a conventional interface between humans so you can read my programs more easily.\n\n176\n00:11:00,053 --> 00:11:01,960\n我希望你在写程序的时候\nSo I want you to, when you write programs,\n\n177\n00:11:01,960 --> 00:11:03,733\n当你定义谓词的时候\nif you define a predicate procedure,\n\n178\n00:11:04,013 --> 00:11:05,773\n就是那些返回TRUE或FALSE的过程\nthat's something that returns true of false,\n\n179\n00:11:05,946 --> 00:11:07,840\n你应该使它们的名字以问号结尾\nit should have a name which ends in question mark.\n\n180\n00:11:08,026 --> 00:11:10,346\n这对Lisp无异 但对人类友好\nThe lisp doesn't care. I care.\n\n181\n00:11:11,626 --> 00:11:13,146\n我需要求和\nI want to make a sum.\n\n182\n00:11:13,146 --> 00:11:17,493\n因为积的导数就是...\nBecause the product, the derivative of a product is the sum\n\n183\n00:11:17,940 --> 00:11:19,640\nM1*DERIV(M2)\nof the first times the derivative of the second plus\n\n184\n00:11:19,666 --> 00:11:20,706\n+DERIV(M1)*M2\nthe second times the derivative of the first.\n\n185\n00:11:23,546 --> 00:11:27,066\n两者加起来\nMake a sum of two things,\n\n186\n00:11:29,640 --> 00:11:38,333\n求积... 呃 就用表达式中的M1来表示（被乘数）好了\na product of, well, I'm going to say the M1 of the expression,\n\n187\n00:11:39,853 --> 00:11:48,973\n表达式中M2关于变量VAR的导数\nand the derivative of the M2 of the expression with respect to the variable,\n\n188\n00:11:51,906 --> 00:12:06,280\n以及 M1关于变量VAR的导数乘以\nand the product of the derivative of M1,\n\n189\n00:12:07,106 --> 00:12:11,920\nM1是这里的被乘数\nthe multiplier of the expression, with respect to the variable.\n\n190\n00:12:13,320 --> 00:12:18,053\n乘数是表达式中的M2\nAnd the product of that and the multiplicand, M2, of the expression.\n\n191\n00:12:20,640 --> 00:12:24,893\n求积完毕、求和完毕、乘式分析完毕\nMake that product. Make the sum. Close that case.\n\n192\n00:12:24,960 --> 00:12:28,026\n当然 在这里我可以添加更多的情况\nAnd, of course, I could add as many cases as I like here\n\n193\n00:12:28,320 --> 00:12:30,826\n微积分书中的完整法则\nfor a complete set of rules you might find in a calculus book.\n\n194\n00:12:34,800 --> 00:12:39,453\n我们就是这么来封装这些法则的\nSo this is what it takes to encapsulate those rules.\n\n195\n00:12:41,533 --> 00:12:43,906\n如你所见 我们这里用到了大量的“按愿望思维”\nAnd you see, you have to realize there's a lot of wishful thinking here.\n\n196\n00:12:44,546 --> 00:12:47,560\n我们还没有说这些（表达式）是如何表示的\nI haven't told you anything about how I'm going to make these representations.\n\n197\n00:12:48,466 --> 00:12:51,920\n现在 一旦我将其定为我的一套法则\nNow, once I've decided that this is my set of rules,\n\n198\n00:12:52,520 --> 00:12:55,200\n我想是时候考虑表示法了\nI think it's time to play with the representation.\n\n199\n00:12:55,666 --> 00:12:56,693\n我们来拿捏拿捏\nLet's attack that.\n\n200\n00:12:57,960 --> 00:13:00,000\n首先 我要用到一种“双关”思想\nWell, first of all, I'm going to play a pun.\n\n201\n00:13:00,906 --> 00:13:02,120\n这种“双关”思想非常重要\nIt's an important pun.\n\n202\n00:13:02,746 --> 00:13:06,560\n它是一种强有力思想的关键\nIt's a key to a sort of powerful idea.\n\n203\n00:13:09,626 --> 00:13:14,413\n如果我想表达诸如和、积、差、商的东西\nIf I want to represent sums, and products, and differences, and quotients, and things like that,\n\n204\n00:13:15,226 --> 00:13:18,626\n为什么不用和我程序一样的语言呢？\nwhy not use the same language as I'm writing my program in?\n\n205\n00:13:20,506 --> 00:13:23,640\n我程序中 代数表达式是形如\nI write my program it algebraic expressions that look like\n\n206\n00:13:23,986 --> 00:13:30,453\n(+ (* A (* X X))\nthe sum of the product on a and the product of x and x,\n\n207\n00:13:32,600 --> 00:13:33,800\n和与之类似的\nand things like that.\n\n208\n00:13:34,280 --> 00:13:38,506\n(* B X)以及C\nAnd the product of b and x and c, whatever,\n\n209\n00:13:38,500 --> 00:13:39,973\n把它们加起来\nmake that a sum of the product.\n\n210\n00:13:40,773 --> 00:13:44,093\n现在 我的过程还不能处理多元参数\nRight now I don't want to have procedures with unknown numbers of arguments,\n\n211\n00:13:44,933 --> 00:13:48,466\n(+ (* B X) C)\na product of b and x and c.\n\n212\n00:13:51,426 --> 00:13:52,440\n这是表结构\nThis is list structure.\n\n213\n00:13:54,120 --> 00:13:55,746\n这么做很棒 是因为\nAnd the reason why this is nice,\n\n214\n00:13:55,906 --> 00:13:58,333\n是因为这些对象都有一种性质\nis because any one of these objects has a property.\n\n215\n00:13:58,920 --> 00:14:01,533\n我知道它们的CAR部分是什么\nI know where, know where the car is.\n\n216\n00:14:01,960 --> 00:14:03,213\nCAR部分就是运算符\nThe car is the operator.\n\n217\n00:14:03,920 --> 00:14:06,386\n运算数是相继的CDR部分\nAnd the operands are the successive cdrs\n\n218\n00:14:07,226 --> 00:14:10,360\n也就是不断取表CDR部分的CAR部分\nthe successive cars of the cdrs of the list that this is.\n\n219\n00:14:12,480 --> 00:14:13,880\n这样就使它很方便了\nIt makes it very convenient.\n\n220\n00:14:14,013 --> 00:14:16,400\n我需要去解析它 但它已经帮我完成了\nIr have to parse it. It's been done for me.\n\n221\n00:14:17,426 --> 00:14:20,013\n我利用了Lisp中的内建元素\nI'm using the embedding in Lisp to advantage.\n\n222\n00:14:22,666 --> 00:14:23,773\n举个例子\nSo, for example,\n\n223\n00:14:25,080 --> 00:14:33,973\n我们用表结构来表示我所暗示的表示法吧！\nLet's start using list structure to write down the representation that I'm implicitly assuming here.\n\n224\n00:14:35,253 --> 00:14:38,346\n我需要定义一些东西 这都暗含在这种表示法中\nWell I have to define various things that are implied in this representation.\n\n225\n00:14:38,546 --> 00:14:40,906\n比如如何判定是否为常量\nLike I have to find out how to do a constant,\n\n226\n00:14:41,210 --> 00:14:42,306\n又怎么判断是同一个变量\nhow you do same variable.\n\n227\n00:14:42,400 --> 00:14:45,040\n我们先完成这些吧 都相当简单\nLet's do those first. That's pretty easy enough.\n\n228\n00:14:45,786 --> 00:14:47,706\n这里 我要介绍一些基本过程\nNow I'm going to be introducing lots of primitives here,\n\n229\n00:14:48,600 --> 00:14:50,506\n因为它们都是与表结构相关的\nbecause these are the primitives that come with list structure.\n\n230\n00:14:51,986 --> 00:14:53,466\nCONSTANT?谓词定义为\nOK, you define a constant.\n\n231\n00:15:02,253 --> 00:15:04,293\n我所谓的常量\nAnd what I mean by a constant,\n\n232\n00:15:04,293 --> 00:15:07,733\n表达式关于变量VAR是一个常量\nan expression is constant with respect to a variable.\n\n233\n00:15:09,053 --> 00:15:11,600\n是一些简单的表达式\nis that the expression is something simple.\n\n234\n00:15:11,600 --> 00:15:14,466\n我无法再细化它 但它也不是我们关心的变量\nI can't take it into pieces, and yet it isn't that variable.\n\n235\n00:15:16,586 --> 00:15:18,786\n我无法分解它 但它也不是我们关心的变量\nI can't break it up, and yet it isn't that variable.\n\n236\n00:15:18,900 --> 00:15:25,120\n这也并不是说 一些复杂的表达式就不是常量表达式\nThat does not mean that there may be other expressions that are more complicated that are constants.\n\n237\n00:15:25,200 --> 00:15:28,920\n我只是想用这种方式考察基本常量\nIt's just that I'm going to look at the primitive constants in this way.\n\n238\n00:15:29,746 --> 00:15:33,413\n因此 这个谓词是几个条件的合取\nSo what this is, is it says that's it's the and.\n\n239\n00:15:34,026 --> 00:15:37,826\nAND语句允许用户组合返回TRUE或者FALSE的谓词\nI can combine predicate expressions which return true or false with and.\n\n240\n00:15:38,626 --> 00:15:46,826\n表达式是原子的么？--原子表达式不可以再被细分\nSomething atomic, The expression is atomic, meaning it cannot be broken into parts.\n\n241\n00:15:46,820 --> 00:15:48,533\n它没有CAR部分和CDR部分\nIt doesn't have a car and a cdr.\n\n242\n00:15:49,453 --> 00:15:50,213\n它不是表\nIt's not a list.\n\n243\n00:15:50,760 --> 00:15:52,946\n系统中内建有特殊测试\nAnd it's a special test built into the system.\n\n244\n00:15:53,973 --> 00:16:04,666\n并且表达式EXP和变量VAR在EQ?的语义下不相等\nAnd it's not identically equal to that variable.\n\n245\n00:16:06,826 --> 00:16:13,360\n我用不能被分解的符号来表示变量\nI'm representing my variables by things that are symbols which cannot be broken into pieces,\n\n246\n00:16:13,906 --> 00:16:17,226\n比如'X 'Y 和像这样的\nthings like x, and y, things like this.\n\n247\n00:16:19,746 --> 00:16:22,373\n当然 像这样的组合式就可以再被细分\nWhereas, of course, something like this can be broken up into pieces.\n\n248\n00:16:24,746 --> 00:16:46,400\n(SAME-VAR? EXP VAR)定义为\nAnd the same variable of an expression with respect to a variable is,\n\n249\n00:16:46,400 --> 00:16:48,400\n实际上 一条原子表达式……\nin fact, an atomic expression.\n\n250\n00:16:48,773 --> 00:16:59,613\n该表达式与讨论变量相同\nI want to have an atomic expression, which is identical.\n\n251\n00:17:07,900 --> 00:17:11,680\n我不想深入讨论这些过程内部\nI don't want to look inside this, this stuff anymore.\n\n252\n00:17:12,520 --> 00:17:15,560\n把这些当作基本过程\nThese are primitive maybe.\n\n253\n00:17:15,773 --> 00:17:17,080\n这无关紧要\nBut it doesn't matter.\n\n254\n00:17:17,786 --> 00:17:21,746\n我用的是语言内置的功能\nI'm defining... I'm using things that are given to me with a language.\n\n255\n00:17:22,426 --> 00:17:24,040\n我并不关心这些（具体实现）\nI'm not terribly interest in them.\n\n256\n00:17:24,426 --> 00:17:26,040\n现在 我们要如何处理和式呢？\nNow how do we deal with sums?\n\n257\n00:17:26,600 --> 00:17:28,800\n啊哈 好戏就要上演了\nAh, something very interesting will happen.\n\n258\n00:17:28,986 --> 00:17:33,120\n和式不是原子的 它以‘+’号打头\nA sum is something which is not atomic and begins with the plus symbol.\n\n259\n00:17:35,160 --> 00:17:36,173\n就是这个意思\nThat's what it means.\n\n260\n00:17:36,653 --> 00:17:39,773\n这里 我定义\nSo here, I will define.\n\n261\n00:17:45,466 --> 00:17:57,773\n表达式为和式 当它不是原子表达式\nAn expression is a sum if and it's not atomic\n\n262\n00:18:04,573 --> 00:18:15,453\n并且它的开头 表达式的CAR部分是个‘+’号\nand it's head, it's beginning, its car of the expression is the symbol plus.\n\n263\n00:18:19,746 --> 00:18:24,040\n我将要引入一个你们从未见过的东西--这个引号\nNow you're about to see something you haven't seen before, this quotation.\n\n264\n00:18:25,893 --> 00:18:28,226\n我这里为什么要用引号呢？\nWhy do I have that quotation there?\n\n265\n00:18:29,480 --> 00:18:30,520\n教授：说你的名字\nPROFESSOR: Say your name,\n\n266\n00:18:30,680 --> 00:18:31,410\n观众：Susanna\nAUDIENCE: Susanna.\n\n267\n00:18:31,410 --> 00:18:32,013\n教授：大点声儿\nPROFESSOR: Louder.\n\n268\n00:18:32,013 --> 00:18:32,720\n观众：Susanna\nAUDIENCE: Susanna\n\n269\n00:18:33,253 --> 00:18:34,213\n教授：说“你的名字”\nPROFESSOR: Say your name.\n\n270\n00:18:34,213 --> 00:18:34,853\n观众：“你的名字”\nAUDIENCE: Your name.\n\n271\n00:18:34,920 --> 00:18:35,680\n教授：大点声儿\nPROFESSOR: Louder.\n\n272\n00:18:35,773 --> 00:18:36,613\n观众：“你的名字”\nAUDIENCE: Your name.\n\n273\n00:18:36,826 --> 00:18:37,506\n教授：对了\nPROFESSOR: OK.\n\n274\n00:18:38,280 --> 00:18:44,560\n在这里我想告诉大家 英语词汇是有歧义的\nWhat I'm showing you here is that the words of English are ambiguous.\n\n275\n00:18:45,506 --> 00:18:50,760\n我可能说 “说你的名字”\nI was saying, say your name.\n\n276\n00:18:51,970 --> 00:18:57,213\n我也可能说 “说‘你的名字’”\nI was also possibly saying say, your name.\n\n277\n00:19:00,720 --> 00:19:02,986\n光从说话上还无法分辨\nBut that cannot be distinguished in speech.\n\n278\n00:19:03,893 --> 00:19:08,013\n然而书面上 我们有专门的记号--引号\nHowever, we do have a notation in writing,\n\n279\n00:19:08,186 --> 00:19:12,466\n用来区别这两种可能的意思\nwhich is quotation for distinguishing these two possible meanings.\n\n280\n00:19:14,000 --> 00:19:15,640\n具体来说 这里\nIn particular, over here,\n\n281\n00:19:16,493 --> 00:19:20,840\n在Lisp中有用于区别这些语义的记号\nin Lisp we have a notation for distinguishing these meanings.\n\n282\n00:19:21,346 --> 00:19:24,453\n如果我只是写下一个加号\nIf I were to just write a plus here, a plus symbol,\n\n283\n00:19:24,640 --> 00:19:28,520\n我会问系统 表达式的首元素\nI would be asking, is the first element of the expression,\n\n284\n00:19:29,066 --> 00:19:33,613\n也就是表达式的运算符 是加运算符（一个过程）么？\nis the operator position of the expression, the addition operator?\n\n285\n00:19:34,653 --> 00:19:35,546\n我并不知道\nI don't know.\n\n286\n00:19:36,226 --> 00:19:38,160\n我本应该在那里写一个加运算符的\nI would have to have written the addition operator there,\n\n287\n00:19:39,373 --> 00:19:40,440\n但我无法那样做\nwhich I can't write.\n\n288\n00:19:41,340 --> 00:19:45,880\n而这种方式则是问 这个符号对象是否为\nHowever, this way I'm asking, is this the symbolic object plus,\n\n289\n00:19:45,986 --> 00:19:48,146\n代表加运算符的符号\nwhich normally stands for the addition operator?\n\n290\n00:19:49,573 --> 00:19:51,920\n这才是我想要问和知道的问题\nThat's what I want. That's the question I want to ask.\n\n291\n00:19:52,920 --> 00:19:54,453\n在我们深入讨论之前\nNow before I go any further,\n\n292\n00:19:54,450 --> 00:19:57,813\n我想要指出 “引用”是一个复杂的概念\nI want to point out the quotation is a very complex concept,\n\n293\n00:19:58,853 --> 00:20:01,840\n语言中引入这个概念将会造成许多麻烦\nand adding it to a language causes a great deal of troubles.\n\n294\n00:20:03,573 --> 00:20:05,040\n请看下面这张幻灯片\nConsider the next slide.\n\n295\n00:20:06,386 --> 00:20:09,493\n这里这个推论没有问题\nHere's a deduction which we should all agree with.\n\n296\n00:20:11,626 --> 00:20:17,040\n这是说 Alyssa聪明而Alyssa是George的妈妈\nWe have, Alyssa is smart and Alyssa is George's mother.\n\n297\n00:20:17,400 --> 00:20:20,600\n通过IS建立了一个等式\nThis is an equality, is.\n\n298\n00:20:22,133 --> 00:20:26,306\n我们可以从这两个陈述推论出 George的妈妈很聪明\nFrom those two, we can deduce that George's mother is smart.\n\n299\n00:20:27,320 --> 00:20:33,160\n这是因为我们总可以在表达式中等价替换\nBecause we can always substitute equals for equals in expressions.\n\n300\n00:20:34,093 --> 00:20:35,160\n真是这样吗？\nOr can we?\n\n301\n00:20:36,520 --> 00:20:40,373\n这个例子说 “Chicago”有七个字母\nHere's a case where we have \"Chicago\" has seven letters.\n\n302\n00:20:41,120 --> 00:20:44,866\n引用则是强调我讨论的是单词“Chicago”\nThe quotation means that I'm discussing the word Chicago,\n\n303\n00:20:44,866 --> 00:20:46,866\n而不是单词所代表的意思\nnot what the word represents.\n\n304\n00:20:49,826 --> 00:20:52,773\n这里说 Chicago是Illinois州最大的城市\nHere I have that Chicago is the biggest city in Illinois.\n\n305\n00:20:54,613 --> 00:20:55,800\n而（代换的）结果是……\nAs a consequence of this,\n\n306\n00:20:55,800 --> 00:20:59,093\n我可能会得到 Illinois州最大的城市有七个字母\nI would like to deduce that the biggest city in Illinois has seven letters.\n\n307\n00:20:59,320 --> 00:21:01,066\n这显然是错的\nBut that's manifestly false.\n\n308\n00:21:05,160 --> 00:21:07,173\n喔！手写笔好使了\nWow, it works.\n\n309\n00:21:09,293 --> 00:21:12,240\n所以 一旦我们有了（引用）这样的东西\nOK, so once we have things like that,\n\n310\n00:21:12,480 --> 00:21:14,493\n我们的语言就会变得复杂\nour language gets much more complicated.\n\n311\n00:21:14,493 --> 00:21:18,346\n因为我们对于语言的一些操作就不再正确\nBecause it's no longer true that things we tend to like to do with languages,\n\n312\n00:21:18,346 --> 00:21:20,760\n比如通过等价代换来得到正确答案\nlike substituting equals for equals and getting right answers,\n\n313\n00:21:21,293 --> 00:21:23,506\n如果不小心地操作就会出错\nare going to work without being very careful.\n\n314\n00:21:24,493 --> 00:21:27,346\n在一个引用不透明的上下文中 我们无法进行代换\nWe can't substitute into what's called referentially opaque contexts,\n\n315\n00:21:27,893 --> 00:21:32,640\n引用就是引用不透明上下文的典型\nof which a quotation is the prototypical type of referentially opaque context.\n\n316\n00:21:33,173 --> 00:21:35,280\n如果你知道那是什么意思……你可以成为一位哲学家\nIf you know what that means, you can consult a philosopher.\n\n317\n00:21:35,426 --> 00:21:37,026\n或许我们之中就有一位\nPresumably there is one in the room.\n\n318\n00:21:37,533 --> 00:21:41,320\n言归正传 我们继续\nIn any case, let's continue now,\n\n319\n00:21:41,320 --> 00:21:44,986\n现在我们对一个有2000年历史的问题至少有了操作上的理解\nnow that we at least have an operational understanding of a 2000-year-old issue\n\n320\n00:21:45,266 --> 00:21:48,133\n关于名称、提及和等等类似的问题\nthat has to do with name, and mention, and all sorts of things like that.\n\n321\n00:21:52,320 --> 00:22:01,600\n我得定义如何把两个数加起来 (DEFINE (MAKE-SUM A1 A2))\nI have to define what I mean, how to make a sum of two things, an a1 and a2.\n\n322\n00:22:02,120 --> 00:22:03,626\n我简单实现一下\nAnd I'm going to do this very simply.\n\n323\n00:22:03,626 --> 00:22:11,960\n'+、A1、A2构成列表\nIt's a list of the symbol plus, and a1, and a2.\n\n324\n00:22:13,866 --> 00:22:17,373\n我可以决定如何取出第一个元素\nAnd I can determine the first element.\n\n325\n00:22:21,840 --> 00:22:25,320\n(DEFINE A1 CADR)\nDefine a1 to be cadr.\n\n326\n00:22:33,880 --> 00:22:35,906\n这里又给大家介绍了一个基本过程\nI've just introduced another primitive.\n\n327\n00:22:36,173 --> 00:22:39,106\n这个是取出某物CDR部分的CAR部分\nThis is the car of the cdr of something.\n\n328\n00:22:39,800 --> 00:22:44,533\n大家或许会好奇 这些基本过程为什么叫做CAR和CDR\nYou might want to know why car and cdr are names of these primitives,\n\n329\n00:22:44,666 --> 00:22:48,426\n而且传承了下来 尽管叫做LEFT和RIGHT会好一点\nand why they've survived, even though they're much better ideas like left and right.\n\n330\n00:22:48,760 --> 00:22:50,440\n我们本可以那样叫的\nWe could have called them things like that.\n\n331\n00:22:51,280 --> 00:22:56,253\n呃 其实 这个名字来自于很久以前 当发明Lisp时\nWell, first of all, the names come from the fact that in the great past, when Lisp was invented,\n\n332\n00:22:56,360 --> 00:23:00,800\n我想大概是58年的样子 是在类似于704之类的机子上实现的\nI suppose in '58 or something, it was on a 704 or something like that,\n\n333\n00:23:00,800 --> 00:23:05,413\n这个机器有个地址寄存器和减量寄存器\nwhich had a machine. It was a machine that had an address register and a decrement register.\n\n334\n00:23:05,413 --> 00:23:08,173\n而这些就是地址寄存器和减量寄存器的值\nAnd these were the contents of the address register and the decrement register.\n\n335\n00:23:08,173 --> 00:23:09,373\n所以这是历史遗留问题\nSo it's an historical accident.\n\n336\n00:23:09,640 --> 00:23:11,280\n但是这些名字为什么又延续下来了呢？\nNow why have these names survived?\n\n337\n00:23:11,746 --> 00:23:14,760\n这是因为Lisp程序员喜欢用电话交流\nIt's because Lisp programmers like to talk to each other over the phone.\n\n338\n00:23:15,680 --> 00:23:19,600\n要是你有一长串的CAR和CDR序列 你就可能说“CDADDEDR”\nAnd if you want to have a long sequence of cars and cdrs you might say, cdaddedr,\n\n339\n00:23:21,013 --> 00:23:22,320\n这是可以理解的\nwhich can be understood.\n\n340\n00:23:22,320 --> 00:23:27,026\n但是左边的右边的右边的左边就不是那么清楚了\nBut left of right or right of left is not so clear if you get good at it.\n\n341\n00:23:27,600 --> 00:23:30,026\n这就是我们为什么有这些黑话\nSo that's why we have these words.\n\n342\n00:23:30,546 --> 00:23:34,146\n典型的Lisp系统 默认定义到第四层\nAll of them up to four deep are defined typically in a Lisp system.\n\n343\n00:23:38,666 --> 00:23:47,053\n而定义A2为……当然 如果我们考察这些表达式中的一个\nA2 to be-- and, of course, you can see that if I looked at one of these expressions\n\n344\n00:23:47,360 --> 00:23:52,146\n比如(+ 3 5)\nlike the sum of 3 and 5,\n\n345\n00:23:52,586 --> 00:24:10,453\n这个实际上是一个包含有'+、数3和数5的表\nwhat that is is a list containing the symbol plus, and a number 3, and a number 5.\n\n346\n00:24:11,720 --> 00:24:15,186\n表的CAR部分是'+\nThen the car is the symbol plus.\n\n347\n00:24:16,133 --> 00:24:18,213\nCDR部分的CAR部分\nThe car of the cdr.\n\n348\n00:24:18,210 --> 00:24:20,210\n也就是先取CDR部分 然后再取CAR部分\nWell I take the cdr and then I take the car.\n\n349\n00:24:20,210 --> 00:24:22,210\n这就是我如何取得3的 也就是第一个参数\nAnd that's how I get to the 3. That's the first argument.\n\n350\n00:24:22,520 --> 00:24:25,693\nCDR的CDR部分的CAR部分 就是这个……数5\nAnd the car of the cdr of the cdr gets me to this one, the 5.\n\n351\n00:24:28,693 --> 00:24:33,666\n当然类似地 对于乘式我可以这样定义\nAnd similarly, of course, I can define what's going on with products.\n\n352\n00:24:35,226 --> 00:24:36,560\n我快速地演示一下\nLet's do that very quickly.\n\n353\n00:24:48,973 --> 00:24:50,640\n(DEFINE (PRODUCT? EXP))\nIs the expression a product?\n\n354\n00:24:51,053 --> 00:24:54,693\n如果它不是原子的 而且\nYes if and if it's true, that's it's not atomic\n\n355\n00:25:01,413 --> 00:25:14,146\nEXP的CAR部分与用于表示乘法的符号'*在 EQ?的语义下相等\nand it's EQ quote, the asterisk symbol, which is the operator for multiplication.\n\n356\n00:25:15,640 --> 00:25:32,000\n(DEFINE (MAKE-PRODUCT M1 M2))\nMake product of an M1 and an M2 to be list,\n\n357\n00:25:34,426 --> 00:25:39,306\n(LIST '* M1 M2)\nquote, the asterisk operation and M1 and M2.\n\n358\n00:25:40,826 --> 00:25:56,810\n并定义M1为CADR M2为CADDR\nAnd I define M1 to be cadr and M2 to be caddr.\n\n359\n00:26:00,093 --> 00:26:02,386\n当你说行话的时候 你就上道了\nYou get to be a good Lisp programmer because you start talking that way.\n\n360\n00:26:02,533 --> 00:26:05,533\n你可以取表的CDR 也可以把它们组合起来\nYou can cdr thing down lists and cons them up and so on.\n\n361\n00:26:06,293 --> 00:26:10,106\n现在 我们有了原理上完整的求导程序了\nNow, now that we have essentially a complete program for finding derivatives,\n\n362\n00:26:10,106 --> 00:26:11,706\n如果需要的话 你也可以添加更多的规则\nyou can add more rules if you like.\n\n363\n00:26:12,213 --> 00:26:13,933\n它又要怎么用呢？\nWhat kind of behavior do we get out of it?\n\n364\n00:26:14,640 --> 00:26:16,773\n我先把这个笔迹清了\nI'll have to clear that x.\n\n365\n00:26:17,800 --> 00:26:20,826\n恩 假设我在这里定义FOO为\nWell, supposing I define foo here\n\n366\n00:26:22,160 --> 00:26:30,386\n定义FOO为A*X^2+B*X+C\nto be the sum of the product of ax square and bx plus c.\n\n367\n00:26:30,540 --> 00:26:32,080\n跟我们这里看到的是一样的\nThat's the same thing we see here\n\n368\n00:26:32,080 --> 00:26:36,360\n这里是用更习见的记号书写的代数表达式\nas the algebraic expression written in the more conventional notation over there.\n\n369\n00:26:37,840 --> 00:26:41,600\n那么 表达式FOO关于X的导数 结果在这里\nWell, the derivative of foo with respect to x, which we can see over here,\n\n370\n00:26:43,466 --> 00:26:45,266\n真是乱得一团糟\nis this horrible, horrendous mess.\n\n371\n00:26:46,160 --> 00:26:49,226\n我期望答案是2*A*X+B\nI would like it to be 2ax plus b.\n\n372\n00:26:50,680 --> 00:26:53,440\n虽然与结果等价 但它并不是我们希望的结果\nBut it's not. It's equivalent to it.\n\n373\n00:26:54,586 --> 00:26:55,226\n这是什么呢？\nWhat is it?\n\n374\n00:26:55,973 --> 00:26:59,960\n我们最初有什么？\nI have here, what do I have?\n\n375\n00:27:00,506 --> 00:27:04,306\n我求X*X的导数\nI have the derivative of the product of x and x.\n\n376\n00:27:04,693 --> 00:27:10,533\n答案是X*1+1*X 这当然没错\nOver here is, of course, the sum of x times 1 and 1 times x.\n\n377\n00:27:12,733 --> 00:27:15,666\n这就是乘数的导数乘以被乘数加上乘数乘以被乘数的导数\nNow, well, it's the first times the derivative of the second plus the second times the derivative of the first. It's right.\n\n378\n00:27:17,226 --> 00:27:28,373\n那就是2X、A*2X就是2AX、0X^2省去 再加上0和这里的一大堆0\nThat's 2x of course. a times 2x is 2ax plus 0X square doesn't count plus B over here plus a bunch of 0's.\n\n379\n00:27:28,960 --> 00:27:30,120\n答案是对的\nWell the answer is right.\n\n380\n00:27:30,120 --> 00:27:35,146\n当我们还需要用户额外检验一下 真是糟糕透了\nBut I give people take off points on an exam for that, sadly enough.\n\n381\n00:27:35,560 --> 00:27:37,266\n我们下一节再考虑这个内容\nLet's worry about that in the next segment.\n\n382\n00:27:37,680 --> 00:27:38,613\n有疑问吗？\nAre there any questions?\n\n383\n00:27:42,773 --> 00:27:43,453\n请说\nYes?\n\n384\n00:27:43,893 --> 00:27:46,693\n观众：写加号时不加引号\nAUDIENCE: If you had left the quote when you put the plus,\n\n385\n00:27:46,693 --> 00:27:50,826\n是表示引用加那个过程么？\nthen would that be referring to the procedure plus\n\n386\n00:27:50,826 --> 00:27:55,426\n如果有需要的话 是否能在两个过程之间进行比较\nand could you do a comparison between that procedure and some other procedure if you wanted to?\n\n387\n00:27:56,160 --> 00:27:57,080\n教授：问得好！\nPROFESSOR: Yes. Good question.\n\n388\n00:27:57,453 --> 00:28:02,266\n如果我这里不用左引号将这个引住\nIf I had left this quotation off at this point,\n\n389\n00:28:03,880 --> 00:28:07,133\n如果我这里不用引号\nOkay? If I had left that quotation off at that point,\n\n390\n00:28:07,333 --> 00:28:14,200\n那么这里我就会引用定义好的加法过程\nthen I would be referring here to the procedure which is the thing that plus is defined to be.\n\n391\n00:28:15,386 --> 00:28:24,880\n实际上 我可以比较两个过程是否同一\nAnd indeed, I could compare some procedures with each other for identity.\n\n392\n00:28:24,880 --> 00:28:27,453\n现在很难从语义上解释\nNow what that means is not clear right now.\n\n393\n00:28:27,853 --> 00:28:29,373\n我现在不想考虑这个问题\nI don't like to think about it.\n\n394\n00:28:29,893 --> 00:28:32,400\n因为我不知道比较过程需要什么\nBecause I don't know exactly what it would need to compare procedures.\n\n395\n00:28:32,400 --> 00:28:34,400\n这样做没有意义是有很多原因的\nThere are reasons why that may make no sense at all.\n\n396\n00:28:35,520 --> 00:28:37,533\n然而 这些符号我们是可以理解的\nHowever, the symbols, we understand.\n\n397\n00:28:38,546 --> 00:28:40,560\n这也是我为什么我要将它们引住\nAnd so that's why I put that quote in.\n\n398\n00:28:41,160 --> 00:28:43,706\n我想讨论出现在这些代码中的符号\nI want to talk about the symbol that's apparent on the page.\n\n399\n00:28:46,160 --> 00:28:46,920\n还有什么问题么？\nAny other questions?\n\n400\n00:28:48,520 --> 00:28:51,866\n好吧 休息一下 谢谢大家\nOK. Thank you. Let's take a break.\n\n401\n00:28:55,120 --> 00:29:00,666\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n402\n00:29:00,680 --> 00:29:04,346\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n403\n00:29:04,340 --> 00:29:06,680\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n404\n00:29:12,210 --> 00:29:19,173\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n405\n00:29:20,093 --> 00:29:24,140\n符号化导数系统、引用\nSymbolic Differentiation: Quotation\n\n406\n00:29:29,866 --> 00:29:30,920\n教授：好 我们继续\nPROFESSOR: Well, let's see.\n\n407\n00:29:31,466 --> 00:29:37,760\n我们编写了一个貌似可行的代数表达式求导程序\nWe've just developed a fairly plausible program for computing the derivatives of algebraic expressions.\n\n408\n00:29:38,200 --> 00:29:41,560\n这个程序是不完整的 你需要添加一些规则\nIt's an incomplete program, if you would like to add more rules.\n\n409\n00:29:42,130 --> 00:29:47,746\n你可能需要加强这个系统 使得它能够处理\nAnd perhaps you might extend it to deal with uses of addition with any number of arguments\n\n410\n00:29:47,760 --> 00:29:49,700\n多元加法和多元乘法\nand multiplication with any of the number of arguments.\n\n411\n00:29:49,893 --> 00:29:51,386\n这些都相当简单\nAnd that's all rather easy.\n\n412\n00:29:52,733 --> 00:29:56,933\n但这里面也有一些瑕疵\nHowever, there was a little fly in that ointment.\n\n413\n00:29:57,480 --> 00:30:02,373\n回到这张幻灯片来\nWe go back to this slide.\n\n414\n00:30:02,946 --> 00:30:08,600\n我们发现 得到的表达式相当乱\nWe see that the expressions that we get are rather bad.\n\n415\n00:30:08,880 --> 00:30:11,013\n这个表达式非常糟糕\nThis is a rather bad expression.\n\n416\n00:30:11,466 --> 00:30:13,106\n我们是怎么得到这样的表达式的？\nHow do we get such an expression?\n\n417\n00:30:13,840 --> 00:30:15,506\n为什么是这样呢？\nWhy do we have that expression?\n\n418\n00:30:16,840 --> 00:30:18,746\n我们详细地分析一下这个表达式\nLet's look at this expression in some detail.\n\n419\n00:30:18,920 --> 00:30:20,760\n找出这些片段都是出自哪里\nLet's find out where all the pieces come from.\n\n420\n00:30:21,693 --> 00:30:24,560\n如我们所见 这里的和式\nAs we see here, we have a sum--\n\n421\n00:30:24,560 --> 00:30:26,560\n也就是上一小节中给你们提到的\njust what I showed you at the end of the last time--\n\n422\n00:30:27,120 --> 00:30:29,093\n(+ (* X 1) (* 1 X))\nof X times 1 plus 1 time X.\n\n423\n00:30:29,586 --> 00:30:31,386\n是这个乘式的导数\nThat is a derivative of this product.\n\n424\n00:30:32,520 --> 00:30:36,413\n也就是A乘上这个的积 这里A不是X的函数\nThe product of a times that, where a does not depend upon x,\n\n425\n00:30:36,410 --> 00:30:38,410\n因此A关于X是一个常数\nand therefore is constant with respect to x,\n\n426\n00:30:39,040 --> 00:30:44,533\n导数为这个和式 从这里到这里 再到这里\nis this sum, which goes from here all the way through here and through here.\n\n427\n00:30:44,800 --> 00:30:48,893\n因为这个是乘数乘以被乘数的导数\nBecause it is the first thing times the derivative of the second\n\n428\n00:30:49,573 --> 00:30:54,453\n加上被乘数乘以乘数的导数\nplus the derivative of the first times the second\n\n429\n00:30:54,666 --> 00:30:59,066\n我们在黑板上的程序告诉我们确实是这样的\nas the program we wrote on the blackboard indicated we should do.\n\n430\n00:31:00,653 --> 00:31:05,360\n当然 这里B乘以X的积\nAnd, of course, the product of bx over here\n\n431\n00:31:05,493 --> 00:31:09,813\n被化成了 B*1+0*X\nmanifests itself as B times 1 plus 0 times X\n\n432\n00:31:10,813 --> 00:31:16,066\n因为B不是X的函数\nbecause we see that B does not depend upon X.\n\n433\n00:31:16,466 --> 00:31:18,560\n因此B的导数为0\nAnd so the derivative of B is this 0,\n\n434\n00:31:18,773 --> 00:31:21,480\n而X对自己求导则为1\nand the derivative of X with respect itself is the 1.\n\n435\n00:31:23,066 --> 00:31:28,640\n这里的加法化成了 这两个导数的和\nAnd, of course, the derivative of the sums over here turn into these two sums of the derivatives of the parts.\n\n436\n00:31:29,373 --> 00:31:33,506\n所以这里 我想告诉你和之前一样的东西\nSo what we're seeing here is exactly the thing I was trying to tell you about\n\n437\n00:31:33,666 --> 00:31:35,893\n也就是在讲斐波那契数那时候\nwith Fibonacci numbers a while ago,\n\n438\n00:31:37,773 --> 00:31:39,493\n所谓的 “过程的形状”\nthat the form of the process\n\n439\n00:31:41,386 --> 00:31:46,440\n就是通过局部的规则向低层次展开\nis expanded as low as from the local rules that you see in the procedure,\n\n440\n00:31:48,053 --> 00:31:52,573\n也就是过程代表了一系列用于演进过程局部规则\nthat the procedure represents a set of local rules for the expansion of this process.\n\n441\n00:31:53,360 --> 00:32:00,093\n这里 过程还遗留了一些东西--也就是答案\nAnd here, the process left behind some stuff, which is the answer.\n\n442\n00:32:00,253 --> 00:32:06,266\n这是通过遍历表达式的树结构构造出来的\nAnd it was constructed by the walk it takes of the tree structure, which is the expression.\n\n443\n00:32:08,413 --> 00:32:12,613\n答案中的每个部分对应问题中的某个部分\nSo every part in the answer we see here derives from some part of the problem.\n\n444\n00:32:14,466 --> 00:32:17,786\n比如说 现在我们考察FOO的导数\nNow, we can look at, for example, the derivative of foo,\n\n445\n00:32:17,786 --> 00:32:19,653\n也就是AX^2+BX+C\nwhich is ax square plus bx plus c,\n\n446\n00:32:19,840 --> 00:32:23,053\n并另令自变量 比如像这里\nwith respect to other things, like here, for example,\n\n447\n00:32:24,146 --> 00:32:27,480\n我们令A为自变量 求FOO的导数\nwe can see that the derivative of foo with respect to a.\n\n448\n00:32:28,106 --> 00:32:31,773\n这都非常相似 实际上 它们是同样的代数表达式\nAnd it's very similar. It's, in fact, the identical algebraic expression,\n\n449\n00:32:32,453 --> 00:32:35,240\n只是它们之中0和1的位置不一样罢了\nexcept for the fact that theses 0's and 1's are in different places.\n\n450\n00:32:36,066 --> 00:32:38,600\n这是因为在这个树结构的遍历中\nBecause the only degree of freedom we have in this tree walk\n\n451\n00:32:38,973 --> 00:32:43,853\n只可能是CONSTANT?和SAME-VAR?会因变量的不同\nis what's constant with respect to the variable we're taking the derivative with respect to\n\n452\n00:32:44,280 --> 00:32:45,813\n而造成不同结果\nand what's the same variable.\n\n453\n00:32:48,266 --> 00:32:52,093\n回到黑板上来再看看\nIn other words, if we go back to this blackboard and we look,\n\n454\n00:32:52,653 --> 00:32:57,493\n我们在求和式或乘式的导数时根本没有发挥的余地\nwe have no choice what to do when we take the derivative of the sum or a product.\n\n455\n00:32:58,080 --> 00:33:04,480\n真正可以做文章的地方 则是表达式和自变量\nThe only interesting place here is, is the expression the variable,\n\n456\n00:33:04,800 --> 00:33:10,106\n以及对于那些短小的表达式 是否为关于自变量的常量\nor is the expression a constant with respect to that variable for very, very small expressions?\n\n457\n00:33:10,360 --> 00:33:12,413\n就是这些地方导致了不同的0和1的产生\nIn which case we get various 1's and 0's,\n\n458\n00:33:12,693 --> 00:33:14,490\n回过头来看这张幻灯\nwhich if we go back to this slide,\n\n459\n00:33:15,120 --> 00:33:18,160\n这里就出现了“0”\nwe can see that the 0's that appear here, for example,\n\n460\n00:33:18,373 --> 00:33:22,746\n这里是求FOO(A)的导数时得到的“1”\nthis 1 over here in derivative of foo with respect to A,\n\n461\n00:33:22,960 --> 00:33:24,866\n我们得到了X^2\nwhich gets us an X square,\n\n462\n00:33:24,960 --> 00:33:32,533\n这个1是X*X关于X的导数 关于B求导时1变成了0\nbecause that 1 gets the multiply of X and X into the answer, that 1 is 0.\n\n463\n00:33:32,640 --> 00:33:34,893\n这里 我们求FOO关于C的导数\nOver here, we're not taking the derivative of foo with respect to c.\n\n464\n00:33:36,786 --> 00:33:39,306\n但是这些表达式的轮廓是一致的\nBut the shapes of these expressions are the same.\n\n465\n00:33:40,546 --> 00:33:43,960\n看看这些轮廓 都是相同的\nSee all those shapes. They're the same.\n\n466\n00:33:50,373 --> 00:33:52,280\n那么 难道是我们的规则出了问题？\nWell is there anything wrong with our rules?\n\n467\n00:33:53,586 --> 00:33:55,026\n不 这些规则都对\nNo. They're the right rules.\n\n468\n00:33:56,120 --> 00:33:57,773\n我们曾经遇到过这种问题\nWe've been through this one before.\n\n469\n00:33:58,066 --> 00:34:03,533\n你将会发现 这其中缺乏一些非常好的思想\nOne of the things you're going to begin to discover is that there aren't too many good ideas.\n\n470\n00:34:06,320 --> 00:34:09,746\n昨天 我们在考察有理数时\nWhen we were looking at rational numbers yesterday,\n\n471\n00:34:12,120 --> 00:34:14,480\n想要得到3/4却得到6/8\nthe problem was that we got 6/8 rather then 3/4.\n\n472\n00:34:14,973 --> 00:34:16,493\n答案没有化简\nThe answer was unsimplified.\n\n473\n00:34:18,093 --> 00:34:20,906\n当然 当下的问题也非常类似\nThe problem, of course, is very similar.\n\n474\n00:34:21,186 --> 00:34:25,413\n我想把不相同的表达式通过化简来使相同\nThere are things I'd like to be identical by simplification that don't become identical.\n\n475\n00:34:27,573 --> 00:34:31,893\n当然 有理数加法和乘法的规则依然正确\nAnd yet the rules for doing addition a multiplication of rational numbers were correct.\n\n476\n00:34:33,973 --> 00:34:37,413\n因此这里 我们依葫芦画瓢\nSo the way we might solve this problem is do the thing we did last time, which always works.\n\n477\n00:34:37,786 --> 00:34:39,893\n上次能行的办法 这次也没问题\nIf something worked last time it ought to work again.\n\n478\n00:34:40,533 --> 00:34:42,053\n也就是改换一下它的表示\nIt's changed representation.\n\n479\n00:34:43,133 --> 00:34:46,440\n或许在将其表示出来时我们可以进行\nPerhaps in the representation we could put in a simplification step\n\n480\n00:34:47,880 --> 00:34:49,786\n一步产生简化表示的步骤\nthat produces a simplified representation.\n\n481\n00:34:50,173 --> 00:34:51,733\n当然啦 这也不是万用万灵\nThis may not always work, of course.\n\n482\n00:34:52,493 --> 00:34:54,146\n我也不想证明它是万能的\nI'm not trying to say that it always works.\n\n483\n00:34:55,120 --> 00:35:00,440\n但这也是控制复杂度的一招妙计\nBut it's one of the pieces of artillery we have in our war against complexity.\n\n484\n00:35:01,466 --> 00:35:03,853\n我们小心翼翼地解决这些问题\nYou see, because we solved our problem very carefully.\n\n485\n00:35:04,306 --> 00:35:07,200\n我们所做的 就是把问题划分为几个部分\nWhat we've done, is we've divided the world in several parts.\n\n486\n00:35:07,573 --> 00:35:08,733\n分别是求导规则\nThere are derivatives rules\n\n487\n00:35:11,320 --> 00:35:15,800\n和在这种层面上的一般代数规则\nand general rules for algebra of some sort at this level of detail.\n\n488\n00:35:16,380 --> 00:35:21,226\n然后就有一道抽象屏障\nand i have an abstraction barrier.\n\n489\n00:35:22,480 --> 00:35:33,493\n这里是代数表达式的表示--表结构\nAnd i have the representation of the algebraic expressions, list structure.\n\n490\n00:35:37,333 --> 00:35:42,560\n在这道屏障中 我定义了接口过程\nAnd in this barrier, I have the interface procedures.\n\n491\n00:35:43,253 --> 00:35:49,826\n比如 CONSTANT? SAME-VAR?\nI have constant, and things like same-var.\n\n492\n00:35:54,600 --> 00:35:58,720\n又比如 SUM? MAKE-SUM\nI have things like sum, make-sum.\n\n493\n00:36:02,226 --> 00:36:05,573\n还有 A1 A2\nI have A1, A2.\n\n494\n00:36:06,600 --> 00:36:08,586\n还有 PRODUCT? 之类的东西\nI have products and things like that,\n\n495\n00:36:08,746 --> 00:36:11,906\n我所需要的、针对各式代数表达式的东西\nall the other things I might need for various kinds of algebraic expressions.\n\n496\n00:36:12,946 --> 00:36:19,146\n构筑这些屏障我可以随意地改换表示法\nMaking this barrier allows me to arbitrarily change the representation\n\n497\n00:36:20,146 --> 00:36:23,200\n而不用改变在某种表示法下编写的规则\nwithout changing the rules that are written in terms of that representation.\n\n498\n00:36:25,040 --> 00:36:29,080\n如果我能通过改变表示法来解决问题\nSo if I can make the problem go away by changing representation,\n\n499\n00:36:30,386 --> 00:36:34,520\n那么把问题分解为两个部分则帮了我大忙\nthe composition of the problem into these two parts has helped me a great deal.\n\n500\n00:36:35,653 --> 00:36:37,546\n好吧 举一个非常简单的例子\nSo let's take a very simple case of this.\n\n501\n00:36:38,826 --> 00:36:40,080\n我们的问题是什么？\nWhat was one of the problems?\n\n502\n00:36:40,266 --> 00:36:43,613\n回到这张幻灯片来\nLet's go back to this transparency again.\n\n503\n00:36:44,506 --> 00:36:47,346\n看这里 哦 这相当糟糕\nAnd we see here, oh yes, there's horrible things\n\n504\n00:36:47,626 --> 00:36:51,866\n这里是一个表达式与“0”的和\nlike here is the sum of an expression and 0.\n\n505\n00:36:53,146 --> 00:36:56,666\n毋庸置疑这应该是该表达式本身\nWell that's no reason to think of it as anything other than the expression itself.\n\n506\n00:36:57,213 --> 00:37:01,906\n为什么这里还会有加号？\nWhy should the summation operation have made up this edition?\n\n507\n00:37:03,386 --> 00:37:04,573\n这其实可以更智能点\nIt can be smarter than that.\n\n508\n00:37:05,560 --> 00:37:10,080\n又比如说这里 是某表达式与“1”的积\nOr here, for example, is a multiplication of something by 1.\n\n509\n00:37:11,160 --> 00:37:12,293\n这和之前一个道理\nIt's another thing like that.\n\n510\n00:37:12,866 --> 00:37:15,680\n又像这里 与“0”相乘显然是“0”\nOr here is a product of something with 0, which is certainly 0.\n\n511\n00:37:17,866 --> 00:37:19,520\n因此我们也不用去构造这些式子了\nSo we won't have to make this construction.\n\n512\n00:37:21,440 --> 00:37:22,626\n我们为什么不这么做呢？\nSo why don't we just do that?\n\n513\n00:37:23,666 --> 00:37:27,960\n我们需要去修改表示法 基本上就是那里了\nWe need to change the way the representation works, almost here.\n\n514\n00:37:37,400 --> 00:37:41,840\n定义 MAKE-SUM 为\nMake-sum to be.\n\n515\n00:37:42,053 --> 00:37:43,760\n呃 现在就不是那么简单了\nWell, now it's not something so simple.\n\n516\n00:37:44,000 --> 00:37:50,400\n除非是有必要 否则我不会简单地把加号和式子组合成表\nI'm not going to make a list containing the symbol plus and things unless I need to.\n\n517\n00:37:51,720 --> 00:37:53,053\n那么 还有哪些可能呢？\nWell, what are the possibilities?\n\n518\n00:37:54,560 --> 00:37:58,533\n如果……这里有一些可能的情况\nIf...I have some sort of cases here.\n\n519\n00:37:59,386 --> 00:38:08,200\n如果都是数值的话 如果A1是数值的话\nIf I have numbers, if a1 is a number--\n\n520\n00:38:09,053 --> 00:38:10,933\n这个基本过程我刚刚提到过\nand here's another primitive I've just introduced,\n\n521\n00:38:10,933 --> 00:38:13,186\n也就是用来检测参数是否为数值\nit's possible to tell whether something's number--\n\n522\n00:38:15,386 --> 00:38:23,826\n并且A2也是数值的话 也就是A2不是符号表达式\nand if number A2, meaning they're not symbolic expressions,\n\n523\n00:38:24,453 --> 00:38:26,200\n那么我们就直接把它们加起来\nthen why not do the addition now?\n\n524\n00:38:26,453 --> 00:38:29,920\n结果就是A1加上A2的和\nThe result is just a plus of A1 and A2.\n\n525\n00:38:32,320 --> 00:38:33,986\n我并不是检查它们代表数值\nI'm not asking if these represent numbers.\n\n526\n00:38:33,986 --> 00:38:35,986\n这里所有的符号都代表数值\nOf course all of these symbols represent numbers.\n\n527\n00:38:37,333 --> 00:38:41,226\n就比如 我想要考察的是这个东西是否为数值3\nI'm talking about whether the one I've got is the number 3 right now.\n\n528\n00:38:43,400 --> 00:38:44,400\n另一种情况\nAnd, for example,\n\n529\n00:38:48,773 --> 00:38:59,613\n假设A1是数值 并且为0\nsupposing A1 is a number, and it's equal to 0,\n\n530\n00:39:04,200 --> 00:39:06,386\n那么答案就是A2\nwell then the answer is just A2.\n\n531\n00:39:06,933 --> 00:39:08,680\n不用再构造什么\nThere is no reason to make anything up.\n\n532\n00:39:10,986 --> 00:39:23,413\n如果A2是数值 并且为0\nAnd if A2 is a number, and equal A2 0,\n\n533\n00:39:27,160 --> 00:39:28,906\n那么答案就是A1\nthen the result is A1.\n\n534\n00:39:30,040 --> 00:39:33,653\n如果没有比这些更好的情况\nAnd only if I can't figure out something better to do with this situation,\n\n535\n00:39:34,133 --> 00:39:35,613\n我就需要构造一个表\nwell, I can construct a list.\n\n536\n00:39:37,866 --> 00:39:42,866\n构造一个用于表示答案的表\nOtherwise I want the representation to be the list\n\n537\n00:39:44,133 --> 00:39:52,333\n其中有 '+、A1和A2\ncontaining the quoted symbol plus, and A1, and A2.\n\n538\n00:39:58,666 --> 00:40:01,653\n当然 积的导数也可以类比此法\nAnd, of course, a very similar thing can be done for products.\n\n539\n00:40:03,013 --> 00:40:05,040\n这里 我就不细讲了\nAnd I think I'll avoid boring you with them.\n\n540\n00:40:05,440 --> 00:40:07,240\n我就直接在黑板上写出结果\nI was going to write it on the blackboard.\n\n541\n00:40:07,653 --> 00:40:09,800\n这并不是很重要 你们已经了解它的思想了\nI don't think it's necessary. You know what to do.\n\n542\n00:40:10,760 --> 00:40:11,613\n非常简明\nIt's very simple.\n\n543\n00:40:12,866 --> 00:40:19,893\n现在 我们来看看用这种方式改造程序后 效果如何\nBut now, let's just see the kind of results we get out of changing our program in this way.\n\n544\n00:40:21,680 --> 00:40:27,880\n哦 这是修改表达式构造函数后的求导结果\nWell, here's the derivatives after having just changed the constructors for expressions.\n\n545\n00:40:28,986 --> 00:40:32,213\n对同样地FOO求导：AX^2+BX+C\nThe same foo, aX square plus bX plus c,\n\n546\n00:40:33,280 --> 00:40:40,706\n我得到了 2AX+B\nand what I get is nothing more than the derivative of that is 2aX plus B.\n\n547\n00:40:40,706 --> 00:40:42,106\n虽然它并没有化到最简\nWell, it's not completely simplified.\n\n548\n00:40:42,600 --> 00:40:44,533\n我应该合并同类项和求和\nI would like to collect common terms and sums.\n\n549\n00:40:45,066 --> 00:40:46,080\n但这又是另外一回事了\nWell, that's more work.\n\n550\n00:40:47,120 --> 00:40:51,866\n当然啦 完成这个功能的代码就大而复杂了\nAnd, of course, programs to do this sort of thing are huge and complicated.\n\n551\n00:40:52,280 --> 00:40:55,280\n代数化简 是一项繁复的工作\nAlgebraic simplification, it's a very complicated mess.\n\n552\n00:40:56,373 --> 00:41:00,133\n你们可能听过MIT以前开发的一个非常出名的程序 MAXIMA\nThere's a very famous program you may have heard of called Maxima developed at MIT in the past,\n\n553\n00:41:00,426 --> 00:41:03,146\n它有5000页的LISP代码\nwhich is 5,000 pages of Lisp code,\n\n554\n00:41:03,920 --> 00:41:06,506\n大部分是代数化简的操作\nmostly the algebraic simplification operations.\n\n555\n00:41:08,080 --> 00:41:12,213\n这里是FOO的导数\nThere we see the derivative of foo.\n\n556\n00:41:12,213 --> 00:41:16,866\n要是我的话 我会在初等微积分课上讲讲“改换主变量”这个东西\nIn fact, alias is something I wouldn't take off more than 1 point for on an elementary calculus class.\n\n557\n00:41:18,386 --> 00:41:22,493\n以A为自变量 FOO的导数则是X*X\nAnd the derivative of foo with respect to a, well it's gone down to X times X,\n\n558\n00:41:22,800 --> 00:41:23,800\n看起来还不差\nwhich isn't so bad.\n\n559\n00:41:24,746 --> 00:41:27,533\n以B为自变量 FOO的导数则是X本身\nAnd the derivative of foo with respect to b is just X itself.\n\n560\n00:41:28,066 --> 00:41:30,120\n以C为自变量 FOO的导数则为“1”\nAnd the derivative of foo with respect to c comes out 1.\n\n561\n00:41:30,706 --> 00:41:32,040\n我对这些结果很满意\nSo I'm pretty pleased with this.\n\n562\n00:41:34,106 --> 00:41:39,013\n你所看到的 都是精心设计、仔细规划的例子\nWhat you've seen is, of course, a little bit contrived, carefully organized example\n\n563\n00:41:39,560 --> 00:41:42,600\n用以展示如何操作代数表达式\nto show you how we can manipulate algebraic expressions,\n\n564\n00:41:42,960 --> 00:41:47,933\n我们如何不用具体的语法 而用抽象的语法抽象地进行\nhow we do that abstractly in terms of abstract syntax rather than concrete syntax\n\n565\n00:41:49,213 --> 00:41:56,293\n以及我们如何使用抽象屏障控制构造这些表达式\nand how we can use the abstraction to control what goes on in building these expressions.\n\n566\n00:41:57,800 --> 00:42:00,413\n真正的奥义并不是如此的简单\nBut the real story isn't just such a simple thing as that.\n\n567\n00:42:01,000 --> 00:42:04,453\n实际上 真正的奥义在于我在操作这些表达式时\nThe real story is, in fact, that I'm manipulating these expressions.\n\n568\n00:42:04,453 --> 00:42:06,720\n代数表达式和代码表达式--\nAnd the expressions are the same expressions--\n\n569\n00:42:06,720 --> 00:42:07,973\n回过头来看看幻灯片\ngoing back to the slide--\n\n570\n00:42:08,080 --> 00:42:10,520\n都是同一种Lisp表达式\nas the ones that are Lisp expressions.\n\n571\n00:42:12,026 --> 00:42:12,973\n这样一语双关 一石二鸟\nThere's a pun here.\n\n572\n00:42:13,826 --> 00:42:21,493\n我用表示代码相同的方法来作为我的表示法\nI've chosen my representation to be the same as the representation in my language of similar things.\n\n573\n00:42:22,893 --> 00:42:26,520\n为了要这样做 我得付出点代价\nBy doing so, I've invoked a necessity.\n\n574\n00:42:26,906 --> 00:42:30,346\n我需要使用类似于“引用”的东西\nI created the necessity to have things like quotation\n\n575\n00:42:30,973 --> 00:42:38,173\n这是因为 我的语言可以编写讨论语言表达式的表达式\nbecause of the fact that my language is capable of writing expressions that talk about expressions of the language.\n\n576\n00:42:39,760 --> 00:42:43,226\n我需要有某种东西指出 这个是我需要讨论的表达式\nI need to have something that says, this is an expression I'm talking about\n\n577\n00:42:43,760 --> 00:42:46,133\n而不是说 （去求）这个表达式的值\nrather than this expression is talking about something,\n\n578\n00:42:47,200 --> 00:42:48,440\n我想要的是前者\nand I want to talk about that.\n\n579\n00:42:51,346 --> 00:42:55,360\n引用阻止表达式被求值 其语义为“就是表达式本身”\nSo quotation stops and says, I'm talking about this expression itself.\n\n580\n00:42:57,973 --> 00:43:00,853\n有了这种能力以后\nNow, given that power,\n\n581\n00:43:01,586 --> 00:43:03,826\n如果我可以操作语言的表达式\nif I can manipulate expressions of the language,\n\n582\n00:43:04,800 --> 00:43:09,000\n我可以在语言层之上构建更加有力的层次\nI can begin to build even much more powerful layers upon layers of languages.\n\n583\n00:43:09,773 --> 00:43:12,640\n因为我可以编写不仅仅是内嵌于Lisp的语言\nBecause I can write languages that not only are embedded in Lisp\n\n584\n00:43:13,466 --> 00:43:14,800\n或者是其它的语言\nor whatever language you start with,\n\n585\n00:43:15,266 --> 00:43:17,760\n我可以编写一种完全不同的语言\nbut languages that are completely different,\n\n586\n00:43:18,586 --> 00:43:22,240\n而其实质上则是被Lisp或其它语言所解释\nthat are just, if we say, interpreted in Lisp or something like that.\n\n587\n00:43:23,173 --> 00:43:25,466\n我们以后还会对此有更深入的理解\nWe'll get to understand those words more in the future.\n\n588\n00:43:26,560 --> 00:43:32,093\n我现在只是想让你们意识到\nBut right now I just want to leave you with the fact that we've hit a line\n\n589\n00:43:32,360 --> 00:43:34,986\n我们已经感触到了一种惊人的力量\nwhich gives us tremendous power.\n\n590\n00:43:36,000 --> 00:43:37,826\n现在我们有了方天画戟\nAnd this point we've bought a sledgehammer.\n\n591\n00:43:38,173 --> 00:43:40,920\n当我们使用它时 也得万分小心\nWe have to be careful to what flies when we apply it.\n\n592\n00:43:42,170 --> 00:43:43,000\n谢谢大家\nThank you.\n\n593\n00:43:44,106 --> 00:43:49,666\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n594\n00:43:50,000 --> 00:44:00,546\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec4a.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:22,340\n[music]\n\n2\n00:00:22,340 --> 00:00:24,340\n模式匹配：基于规则的代换\nPattern-matching: Rule-based Substitution\n\n3\n00:00:24,340 --> 00:00:29,340\n教授：昨天 我们学习了一些符号操作\nPROFESSOR: Well, yesterday we learned a bit about symbolic manipulation,\n\n4\n00:00:29,920 --> 00:00:35,120\n编写了一个非常典型的程序\nand we wrote a rather stylized program\n\n5\n00:00:35,152 --> 00:00:38,976\n来实现教材中的微积分规则\nto implement a pile of calculus rule from the calculus book.\n\n6\n00:00:39,616 --> 00:00:44,592\n在这张幻灯片上\nHere on the transparencies,\n\n7\n00:00:44,960 --> 00:00:48,816\n有一些从书中摘录的微积分规则\nwe see a bunch of calculus rules from such a book.\n\n8\n00:00:49,472 --> 00:00:54,624\n我们要把这些规则转化成计算机语言\nAnd, of course, what we did is sort of translate these rules into the language of the computer.\n\n9\n00:00:55,140 --> 00:00:58,850\n当然 这种策略很有趣\nBut, of course, that's a sort of funny strategy.\n\n10\n00:00:59,360 --> 00:01:04,800\n但是我们为什么要把它们翻译成计算机语言呢？\nWhy should we have to translate these rules into the language of the computer?\n\n11\n00:01:05,008 --> 00:01:06,272\n我的意思是---\nAnd what do I really mean by that?\n\n12\n00:01:06,620 --> 00:01:11,020\n我们昨天写的程序非常典型\nThese are--the program we wrote yesterday was very stylized.\n\n13\n00:01:11,216 --> 00:01:15,984\n它是一个按表达式类型做分派的分情况分析语句\nIt was a conditional, a dispatch on the type of the expression\n\n14\n00:01:16,384 --> 00:01:18,480\n规则就是这样的\nas observed by the rules.\n\n15\n00:01:19,680 --> 00:01:21,552\n这里的规则是说:\nWhat we see here are rules that say\n\n16\n00:01:21,744 --> 00:01:25,488\n我们考察的表达式如果是---\nif the object being the derivative is being taken of,\n\n17\n00:01:25,488 --> 00:01:29,424\n如果是常量 就做一些事情\nif that expression is a constant, then do one thing.\n\n18\n00:01:29,420 --> 00:01:31,376\n如果是变量 就做另一件事情\nIf it's a variable, do another thing.\n\n19\n00:01:31,600 --> 00:01:35,568\n如果它是常量乘以变量 就做另外的事 等等\nIf it's a product of a constant times a variable, do something and so on.\n\n20\n00:01:36,000 --> 00:01:38,960\n这是一种按类型的分派\nThere's sort of a dispatch there on a type.\n\n21\n00:01:41,400 --> 00:01:45,160\n那么 既然它有如此典型的行为和结构\nWell, since it has such a stylized behavior and structure,\n\n22\n00:01:45,952 --> 00:01:49,530\n有没有其它方式把这个过程写得更加清晰？\nis there some other way of writing this program that's more clear?\n\n23\n00:01:50,832 --> 00:01:53,456\n首先要解决的是 这些规则是什么?\nWell, what's a rule, first of all, What are these rules?\n\n24\n00:01:55,560 --> 00:01:58,500\n我们来好好想一下 规则有好几个部分\nLet's think about that. Rules have parts.\n\n25\n00:01:58,944 --> 00:02:02,352\n如果仔细观察这些规则\nIf you look at these rules in detail,\n\n26\n00:02:03,712 --> 00:02:04,992\n你就会发现\nwhat you see, for example,\n\n27\n00:02:05,120 --> 00:02:09,696\n这些规则都有左右两部分\nis the rule has a left-hand side and a right-hand side.\n\n28\n00:02:10,360 --> 00:02:14,360\n每一个规则都有左边部分和右边部分\nEach of these rules has a left-hand side and the right-hand side.\n\n29\n00:02:15,152 --> 00:02:20,304\n左边部分用来与对被求导表达式做比较\nThe left-hand side is somehow compared with the expression you're trying to take the derivative of.\n\n30\n00:02:21,520 --> 00:02:25,104\n右边部分用于替换原表达式\nThe right-hand side is the replacement for that expression.\n\n31\n00:02:28,496 --> 00:02:33,104\n这张纸上的所有规则都可以描述成这样——\nSo all rules on this page are something like this.\n\n32\n00:02:36,512 --> 00:02:38,064\n我们有许多模式\nI have patterns,\n\n33\n00:02:41,488 --> 00:02:48,300\n有时候 给定一个模式 我们需要为其生成一个骨架\nand somehow, I have to produce, given a pattern, a skeleton.\n\n34\n00:02:51,888 --> 00:02:52,816\n这就是一个规则\nThis is a rule.\n\n35\n00:02:55,424 --> 00:02:57,136\n模式是用于匹配的部分\nA pattern is something that matches,\n\n36\n00:02:57,888 --> 00:03:03,264\n将成功匹配的值代换到骨架里 就得到一个新的表达式\nand a skeleton is something you substitute into in order to get a new expression.\n\n37\n00:03:06,464 --> 00:03:16,320\n我的意思是：模式是用来匹配原表达式的\nSo what that means is that the pattern is matched against the expression, which is the source expression.\n\n38\n00:03:23,728 --> 00:03:28,512\n应用规则会产生一个新的表达式\nAnd the result of the application of the rule is to produce a new expression,\n\n39\n00:03:33,616 --> 00:03:34,912\n我们称之为目标\nwhich I'll call a target,\n\n40\n00:03:38,128 --> 00:03:39,888\n这是通过骨架的实例化实现的\nby instantiation of a skeleton.\n\n41\n00:03:41,632 --> 00:03:43,020\n这个叫做实例化\nThat's called instantiation.\n\n42\n00:03:50,720 --> 00:03:54,736\n这就是这些规则所描述的过程\nSo that is the process by which these rules are described.\n\n43\n00:03:55,696 --> 00:03:57,264\n今天我想要做的是\nWhat I'd like to do today\n\n44\n00:03:58,736 --> 00:04:01,088\n构建一种语言\nis build a language\n\n45\n00:04:02,200 --> 00:04:05,488\n以及它的解释与执行方法\nand a means of interpreting that language, a means of executing that language,\n\n46\n00:04:05,744 --> 00:04:08,432\n使得这种语言可以直接表述这些规则\nwhere that language allows us to directly express these rules.\n\n47\n00:04:10,592 --> 00:04:11,584\n我们将要做的是\nAnd what we're going to do\n\n48\n00:04:11,580 --> 00:04:17,568\n与其通过将规则翻译为程序 让计算机理解并执行\ninstead of bringing the rules to the level of the computer by writing a program that is those rules\n\n49\n00:04:18,384 --> 00:04:21,560\n这里主要指 Lisp 程序\nin the computer's language--at the moment, in a Lisp--\n\n50\n00:04:22,160 --> 00:04:24,496\n我们不如让计算机理解我们\nwe're going to bring the computer to the level of us\n\n51\n00:04:25,488 --> 00:04:29,150\n我们可以写一些程序让计算机理解这些规则\nby writing a way by which the computer can understand rules of this sort.\n\n52\n00:04:30,912 --> 00:04:34,768\n这又稍微强调了上次的主旨\nThis is slightly emphasizing the idea that we had last time\n\n53\n00:04:35,440 --> 00:04:39,360\n与其解决一个特定问题 不如解决一类问题\nthat we're trying to make a solution to a class of problems rather than a particular one.\n\n54\n00:04:39,776 --> 00:04:46,720\n如果我为不同的数学运算写规则\nThe problem is if I want to write rules for a different piece of mathematics,\n\n55\n00:04:48,240 --> 00:04:51,392\n比如简单代数的化简\nsay, to simple algebraic simplification or something like that,\n\n56\n00:04:51,984 --> 00:04:55,488\n或者三角函数运算\nor manipulation of trigonometric functions,\n\n57\n00:04:56,096 --> 00:05:01,160\n如果按照昨天的方法 我就得重新写个不同的程序\nI would have to write a different program in using yesterday's method.\n\n58\n00:05:01,160 --> 00:05:05,424\n与之相反 我把程序中的共有逻辑给封装起来\nWhereas I would like to encapsulate all of the things that are common to both of those programs,\n\n59\n00:05:06,128 --> 00:05:10,176\n也就是匹配、实例化等概念 还有控制结构\nmeaning the idea of matching, instantiation, the control structure,\n\n60\n00:05:10,176 --> 00:05:12,464\n这都是非常复杂的事情\nwhich turns out to be very complicated for such a thing,\n\n61\n00:05:13,160 --> 00:05:18,460\n我想把它们从规则中分开 并封装\nI'd like to encapsulate that separately from the rules themselves.\n\n62\n00:05:20,064 --> 00:05:22,608\n首先让我们看一下表示法\nSo let's look at, first of all, a representation.\n\n63\n00:05:22,624 --> 00:05:24,096\n请大家看投影仪上的幻灯片\nI'd like to use the overhead here.\n\n64\n00:05:24,672 --> 00:05:25,600\n已经在这里了\nI'd like-- there it is.\n\n65\n00:05:26,250 --> 00:05:32,272\n我想要把求导的计算规则\nI'd like to look at a representation of the rules of calculus for derivatives\n\n66\n00:05:33,712 --> 00:05:37,150\n表示为我这里写的一种简单语言\nin a sort of simple language that I'm writing right here.\n\n67\n00:05:38,112 --> 00:05:43,296\n我会尽量避免去考虑语法\nNow, I'm going to avoid--I'm going to avoid worrying about syntax.\n\n68\n00:05:44,280 --> 00:05:49,280\n美化它很容易 虽然这个确实挺丑 但我并不关心\nWe can easily pretty this, and I'm not interested in making-- this is indeed ugly.\n\n69\n00:05:49,300 --> 00:05:56,416\n这确实不能像dx/dt那样表示\nThis doesn't look like the beautiful text set dx by dt or something that I'd like to write,\n\n70\n00:05:56,768 --> 00:05:58,120\n但这并不重要\nbut that's not essential.\n\n71\n00:05:58,880 --> 00:06:00,624\n这是一个偶然现象\nThat's sort of an accidental phenomenon.\n\n72\n00:06:01,000 --> 00:06:04,448\n这里 我只关心规则的结构\nHere, we're just worrying about the fact that the structure of the rules\n\n73\n00:06:04,832 --> 00:06:11,700\n规则的左边部分代表了我想要匹配的求导表达式\nis that there is a left-hand side here, represents the thing I want to match against the derivative expression.\n\n74\n00:06:11,808 --> 00:06:13,568\n这个表示是说\nThis is the representation I'm going to say\n\n75\n00:06:13,600 --> 00:06:18,320\n一个匹配常量的模式变量c\nfor the derivative of a constant, which we will call c\n\n76\n00:06:18,848 --> 00:06:21,200\n关于匹配任意表达式的模式变量v求导\nrespect to the variable we will call v.\n\n77\n00:06:23,088 --> 00:06:25,552\n我们在右边部分得到的是0\nAnd what we will get on the right-hand side is 0.\n\n78\n00:06:26,000 --> 00:06:28,064\n这就代表了一个规则\nSo this represents a rule.\n\n79\n00:06:29,260 --> 00:06:34,048\n下一条规则是 匹配变量的模式变量v\nThe next rule will be the derivative of a variable, which we will call v\n\n80\n00:06:34,224 --> 00:06:37,740\n对同一个模式变量求导 得到的结果是1\nrespect to the same variable v, and we get a 1.\n\n81\n00:06:38,600 --> 00:06:42,176\n然而 如果一个匹配变量的模式变量u\nHowever, if we have the derivative of a variable called u\n\n82\n00:06:42,410 --> 00:06:44,848\n关于另一个模式变量v求导\nrespect to a different variables v,\n\n83\n00:06:45,392 --> 00:06:47,050\n那么 结果就是0\nwe will get 0.\n\n84\n00:06:47,840 --> 00:06:52,176\n我想让大家看一下 这些规则是如何组织在一起的\nI just want you look at these rules a little bit and see how they fit together.\n\n85\n00:06:52,512 --> 00:06:54,304\n比如说 在这里\nFor example, over here,\n\n86\n00:06:54,736 --> 00:07:01,900\n我们要求表达式x1、x2之和的导数\nwe're going to have the derivative of the sum of an expression called x1 and an expression called x2.\n\n87\n00:07:01,900 --> 00:07:05,856\n在我们创造的这个语言中\nThese things that begin with question marks are called pattern variables\n\n88\n00:07:06,880 --> 00:07:08,624\n以问号开头的叫模式变量\nin the language that we're inventing,\n\n89\n00:07:08,930 --> 00:07:14,930\n我们就像这样来构建这些用来匹配的模式变量\nand you see we're just making it up, so pattern variables for matching.\n\n90\n00:07:14,930 --> 00:07:20,330\n这里 表达式x1加上表达式x2\nAnd so in this-- here we have the derivative of the sum of the expression which we will call x1.\n\n91\n00:07:20,330 --> 00:07:26,700\n对变量v求导的结果等于右边这里的式子\nAnd the expression we will call x2 with respect to the variable we call v will be-- here is the right-hand side:\n\n92\n00:07:26,700 --> 00:07:32,768\n右边的式子是一个骨架 表示表达式X1关于变量v求导\nthe sum of the derivative of  that expression x1 with respect to v-- the right-hand side is the skeleton--\n\n93\n00:07:33,824 --> 00:07:37,104\n加上表达式X2对变量v求导的和\nand the derivative of x2 with respect to v.\n\n94\n00:07:37,600 --> 00:07:42,384\n这里的冒号表示要代换的对象\nColons here will stand for substitution objects.\n\n95\n00:07:43,632 --> 00:07:47,232\n我们将它们称作“骨架求值”\nThey're--we'll call them skeleton evaluations.\n\n96\n00:07:48,512 --> 00:07:53,072\n让我在黑板上写一些语法\nSo let me put up here on the blackboard for a second some syntax\n\n97\n00:07:53,232 --> 00:07:55,568\n这样就能知道 在我们这门规则语言中会发生什么\nso we'll know what's going on for this rule language.\n\n98\n00:07:56,688 --> 00:07:59,888\n首先我们要处理模式匹配问题\nFirst of all, we're going to have to worry about the pattern matching.\n\n99\n00:08:06,048 --> 00:08:13,120\n第一条规则是 形如foo这样的符号与其自身匹配\nWe're going to have things like a symbol like foo matches exactly itself.\n\n100\n00:08:23,520 --> 00:08:31,344\n形如(f a b)的表达式 可以匹配这样的表\nThe expression f of a and b will be used to match any list\n\n101\n00:08:36,304 --> 00:08:57,024\n表的首元素是f、第二个元素是a、第三个元素是b\nwhose first element is f, whose second element is a, and whose third element is b.\n\n102\n00:08:58,624 --> 00:09:06,992\n另外 模式中可能还有形如(? x)这样的规则\nAlso, another thing we might have in a pattern is that--a question mark with some variable like x.\n\n103\n00:09:08,576 --> 00:09:18,672\n这个规则可以匹配任意表达式 并将其称为x\nAnd what that means, it says matches anything, which we will call x.\n\n104\n00:09:25,456 --> 00:09:29,984\n(?c x) 只匹配常量\nQuestion mark c x will match only constants.\n\n105\n00:09:31,500 --> 00:09:40,960\n并将匹配的常量记作x\nSo this is something which matches a constant called x.\n\n106\n00:09:44,560 --> 00:09:57,072\n(?v x)匹配变量 并将匹配的变量记作x\nAnd question mark v x will match a variable, which we call x.\n\n107\n00:10:01,664 --> 00:10:03,808\n这就是我们正在构建的语言\nThis is sort of the language we're making up now.\n\n108\n00:10:04,192 --> 00:10:09,408\n两个对象的比较是基于元素与元素间的比较\nIf I match two things against each other, then they are compared element by element\n\n109\n00:10:10,256 --> 00:10:15,856\n模式中的元素可以包含这些语法变量、模式变量\nBut elements in the pattern may contain these syntactic variables,\n\n110\n00:10:17,072 --> 00:10:20,432\n它们可以用来匹配任意对象\nwhich will be used to match arbitrary objects.\n\n111\n00:10:22,128 --> 00:10:29,280\n这样 我就可以用x作为名字取得被匹配对象的值\nAnd we'll get that object as the value in the name x here, for example.\n\n112\n00:10:31,056 --> 00:10:37,552\n现在 当我们为实例化准备骨架的时候\nNow, when we make skeletons for instantiation.\n\n113\n00:10:39,504 --> 00:10:41,408\n我们可能有这样的东西\nWell, then we have things like this.\n\n114\n00:10:42,272 --> 00:10:46,336\n符号foo实例化为它本身\nfoo, a symbol, instantiates to itself.\n\n115\n00:10:55,080 --> 00:11:05,920\n形如(f a b)这样的表 实例化为\nSomething which is a list like f of a and b, instantiates to--\n\n116\n00:11:06,368 --> 00:11:14,752\n实例化为一个三元素表\nwell, f instantiates to a  3-list, a list of three elements,\n\n117\n00:11:15,552 --> 00:11:33,376\n其元素分别为f、a、b各自实例化后的结果\nokay, which are the results of instantiating each of f, a, and b.\n\n118\n00:11:36,352 --> 00:11:54,272\n(: x) 会被实例化为x的值--也就是被匹配的模式\nAnd x well--we instantiate to the value of x as in the matched pattern.\n\n119\n00:12:03,056 --> 00:12:10,080\n回头看看这里的幻灯片 我们发现这些都是对象\nSo going back to the overhead here, we see -- we see that all of those kinds of objects\n\n120\n00:12:10,784 --> 00:12:16,060\n我们看到 这是一个用来匹配常量的模式变量\nwe see here a pattern variable which matches a constant,\n\n121\n00:12:16,560 --> 00:12:19,024\n这是匹配变量的模式变量\na pattern variable which matches a variable,\n\n122\n00:12:19,392 --> 00:12:21,744\n这是匹配任意表达式的模式变量\na pattern variable which will match anything.\n\n123\n00:12:22,720 --> 00:12:24,920\n如果我们有了名字一样的两个实例\nAnd if we have two instances of the same name,\n\n124\n00:12:25,080 --> 00:12:31,776\n想这个是被称作v的单变量表达式\nlike this is the derivative of the expression which is a variable only whose name will be v\n\n125\n00:12:32,864 --> 00:12:36,300\n关于一个称作v的任意表达式求导\nwith respect to some arbitrary expression which we will call v,\n\n126\n00:12:36,410 --> 00:12:38,016\n因为这个v出现了两次\nsince this v appears twice,\n\n127\n00:12:38,656 --> 00:12:41,072\n我们想约束它们相同\nwe're going to want that to mean they have to be the same.\n\n128\n00:12:42,688 --> 00:12:45,008\n只有它俩完全一致才算是匹配\nThe only consistent match is that those are the same.\n\n129\n00:12:45,230 --> 00:12:47,230\n所以在这里我们在构建一个语言\nSo here, we're making up a language.\n\n130\n00:12:47,600 --> 00:12:50,660\n事实上 这是一件非常好的事情\nAnd in fact, that's a very nice thing to be doing.\n\n131\n00:12:50,660 --> 00:12:52,600\n构建一个语言非常有趣\nIt's so much fun to make up a language.\n\n132\n00:12:52,600 --> 00:12:54,330\n并且大家一直在做这些\nAnd you do this all the time.\n\n133\n00:12:54,330 --> 00:12:56,896\n大家做过的真正强大的设计\nAnd the really most powerful design things you ever do\n\n134\n00:12:57,232 --> 00:13:00,208\n是构建一个语言来解决这样的问题\nare sort of making up a language to solve problems like this.\n\n135\n00:13:02,064 --> 00:13:05,344\n我们回头看看这些规则\nNow, here we go back here and look at some of these rules.\n\n136\n00:13:05,808 --> 00:13:07,100\n这就是它们的全部\nWell, there's a whole set of them.\n\n137\n00:13:07,100 --> 00:13:12,430\n我们有加法、乘法 就像我们之前看到的一样\nI mean, there's one for addition and one for multiplication, just like we had before.\n\n138\n00:13:12,430 --> 00:13:17,376\nx1+x2 关于变量v的导数等于\nThe derivative of the product of x1 and x2 with respect to v is\n\n139\n00:13:17,680 --> 00:13:26,528\nx2对v求导乘以x1 加上 x1对v求导乘以x2\nthe sum of the product of x1 and the derivative x2 with respect to v and the product of the derivative of x1 and x2.\n\n140\n00:13:27,264 --> 00:13:29,100\n这是指数运算的求导规则\nAnd here we have exponentiation.\n\n141\n00:13:29,248 --> 00:13:32,110\n虽然这里展示完了所有的规则 但还可以按照我们意愿添加\nAnd, of course, we run off the end down here. We get as many as we like.\n\n142\n00:13:32,704 --> 00:13:39,104\n我们在这里 建立了关于求导的规则列表\nBut the whole thing over here, I'm giving this--this list of rules the name \"derivative rules.\"\n\n143\n00:13:40,400 --> 00:13:44,330\n一旦我们有了这些 我们应该做什么呢？\nWhat would we do with such a thing once we have it?\n\n144\n00:13:45,408 --> 00:13:47,840\n恩 我将给你们展示最好的思想之一\nWell, one of the nicest ideas, first of all,\n\n145\n00:13:48,448 --> 00:13:51,680\n然后我们将花一整天来鼓捣它\nis I'm going to write for you, and we're going to play with it all day.\n\n146\n00:13:52,288 --> 00:13:57,376\n我将向大家展示一个叫做simplifier的程序\nWhat I'm going to write for you is a program called simplifier,\n\n147\n00:13:57,824 --> 00:13:59,472\n一个通用的化简器\nthe general-purpose simplifier.\n\n148\n00:14:00,090 --> 00:14:17,104\n我们将求导规则deriv-rules送入simplifier从而产生dsimp\nAnd we're going to say something like define dsimp to be a simplifier of the derivative rules.\n\n149\n00:14:23,744 --> 00:14:28,752\n传给simplifier过程一套规则 它会返回给我们一个过程\nAnd what simplifier is going to do is, given a set of rules, it will produce for me a procedure\n\n150\n00:14:29,328 --> 00:14:34,592\n它根据这些规则对表达式进行化简\nwhich will simplify expressions containing the things that are referred to by these rules.\n\n151\n00:14:37,392 --> 00:14:43,936\n因此 这里会返回一个按照你制定的规则所构造的过程\nSo here will be a procedure constructed for your purposes to simplify things with derivatives in them\n\n152\n00:14:44,590 --> 00:14:49,568\n使得在我们进入 Lisp 系统后 在命令提示符后面\nsuch that, after that, if we're typing at some Lisp system, and we get a prompt,\n\n153\n00:14:49,888 --> 00:15:03,936\n输入 (DSIMP '(dd (+ x y) x))\nand we say dsimp, for example, of the derivative of the sum of x and y with respect to x--\n\n154\n00:15:06,992 --> 00:15:10,976\n注意这里的引号 因为我们讨论的是表达式的求导\nnote the quote here because I'm talking about the expression which is the derivative--\n\n155\n00:15:13,296 --> 00:15:17,760\n然后我将得到结果 (+ 1 0)\nthen I will get back as a result plus 1 0.\n\n156\n00:15:19,968 --> 00:15:24,600\n因为 (x+y)' = x' + y'\nBecause the derivative of x plus y is the derivative of x plus derivative y.\n\n157\n00:15:24,600 --> 00:15:26,224\nx'=1\nThe derivative of x with respect to x is 1.\n\n158\n00:15:26,384 --> 00:15:27,824\ny'=0（关于x求导）\nThe derivative of y with respect to x is 0.\n\n159\n00:15:29,424 --> 00:15:30,464\n这不是我想要的\nIt's not what we're going to get.\n\n160\n00:15:31,184 --> 00:15:34,656\n我还没有在这里做代数化简\nI haven't put any simplification at that level-- algebraic simplification--yet.\n\n161\n00:15:36,160 --> 00:15:41,536\n当然一旦我有了这个东西那么我们可以 -- 我们可以看看其它的规则\nOf course, once we have such a thing, then we can--then we can look at other rules.\n\n162\n00:15:41,960 --> 00:15:49,360\n比如 我们看这张幻灯片\nSo, for example, we can, if we go to the slide, OK?\n\n163\n00:15:49,360 --> 00:15:54,128\n这里是其它的规则 代数操作规则\nHere, for example, are other rules that we might have, algebraic manipulation rules,\n\n164\n00:15:56,000 --> 00:15:58,384\n它们可以用来化简代数表达式\nones that would be used for simplifying algebraic expressions.\n\n165\n00:15:59,008 --> 00:16:02,064\n考察一下这些规则\nFor example, just looking at some of these,\n\n166\n00:16:03,040 --> 00:16:09,200\n这条规则的左部分是说 某个运算符应用到常量e1和常量e2上\nthe left-hand side says any operator applied to a constant e1 and a constant e2\n\n167\n00:16:09,328 --> 00:16:14,512\n其结果就是求(op e1 e2)的值\nis the result of evaluating that operator on the constants e1 and e2.\n\n168\n00:16:15,888 --> 00:16:21,568\n或者 当一个运算符应用在任意表达式e1和常量e2上\nOr an operator, applied to e1, any expression e1 and a constant e2,\n\n169\n00:16:21,696 --> 00:16:23,872\n化简结果会把常量前置\nis going to move the constant forward.\n\n170\n00:16:24,528 --> 00:16:27,680\n这就变成了((: op) (: e2) (: e1))\nSo that'll turn into the operator with e2 followed by e1.\n\n171\n00:16:28,592 --> 00:16:30,112\n为什么要这么做？我不知道\nWhy I did that, I don't know.\n\n172\n00:16:30,224 --> 00:16:33,168\n比如说 如果系统中有除法的话 这就不对\nIt wouldn't work if I had division, for example.\n\n173\n00:16:33,530 --> 00:16:35,312\n换句话说 规则有漏洞\nSo there's a bug in the rules, if you like.\n\n174\n00:16:36,672 --> 00:16:40,864\n所以0与任何表达式e的和 等于表达式e\nSo the sum of 0 and e is e.\n\n175\n00:16:42,176 --> 00:16:45,312\n1乘以任何表达式e的结果是表达式e\nThe product of 1 and any expression e is e.\n\n176\n00:16:46,128 --> 00:16:49,136\n0乘以任何表达式e的结果是0\nThe product of 0 and any expression e is 0.\n\n177\n00:16:49,330 --> 00:16:52,720\n我们可以有任意复杂的规则\nJust looking at some more of these rules, we could have arbitrarily complicated ones.\n\n178\n00:16:53,696 --> 00:16:54,816\n比如说\nWe could have things like\n\n179\n00:16:55,360 --> 00:17:01,696\n常量e1*(常量e2*任意表达式e3)\nthe product of the constant e1 and any constant e2 with e3\n\n180\n00:17:02,350 --> 00:17:11,968\n可以化简为 (e1*e2)*e3\nis the result of multiplying the result of multiplying now the constants e1 and e2 together and putting e3 there.\n\n181\n00:17:13,360 --> 00:17:16,768\n这个规则是说 先把常量组合起来\nSo it says combine the constants that I had,\n\n182\n00:17:16,768 --> 00:17:22,704\n如果有形如 e1*(e2*e3) 的式子 而且e1 e2都是常量 就先把常量乘起来\nwhich was if I had a product of e1 and e2 and e3 just multiply--I mean and e1 and e2 are both constants, multiply them.\n\n183\n00:17:23,840 --> 00:17:25,488\n你可以根据意愿来构建这些规则\nAnd you can make up the rules as you like.\n\n184\n00:17:25,792 --> 00:17:26,944\n这里还有很多规则\nThere are lots of them here.\n\n185\n00:17:27,424 --> 00:17:31,040\n这些规则是很复杂的 比如--\nThere are things as complicated, for example, as--\n\n186\n00:17:31,260 --> 00:17:33,930\n请看 这条规则是分配律\noh, I suppose down here some distributive law, you see.\n\n187\n00:17:33,930 --> 00:17:38,576\n任何表达式c乘以d和e\nThe product of any object c and the sum of d and e\n\n188\n00:17:39,024 --> 00:17:43,664\n等于 c与d的积加上c与e的积\ngives the result as the same as the sum of the product of c and d and the product of c and e.\n\n189\n00:17:45,312 --> 00:17:48,672\n我并不关心这些规则具体描述的什么\nNow, what exactly these rules are doesn't very much interest me.\n\n190\n00:17:49,168 --> 00:17:52,976\n我们将要构建一种语言 用来解释这些规则\nWe're going to be writing the language that will allow us to interpret these rules\n\n191\n00:17:55,504 --> 00:17:57,488\n这样我们就可以按我们的意愿编写规则\nso that we can, in fact, make up whatever rules we like,\n\n192\n00:17:58,352 --> 00:18:00,144\n这是另外一种程序设计语言\nanother whole language of programming.\n\n193\n00:18:03,392 --> 00:18:04,048\n来看看\nWell, let's see.\n\n194\n00:18:05,184 --> 00:18:06,960\n我还没告诉你我们要怎么做\nI haven't told you how we're going to do this.\n\n195\n00:18:07,536 --> 00:18:10,064\n当然我们马上就要讲了\nAnd, of course, for a while, we're going to work on that.\n\n196\n00:18:10,896 --> 00:18:15,408\n但真正的问题是：宏观地看 我要做什么？\nBut there's a real question of what is--what am I going to do at all at a large scale?\n\n197\n00:18:17,088 --> 00:18:18,224\n这些规则是如何运作的？\nHow do these rules work?\n\n198\n00:18:19,008 --> 00:18:25,456\n化简程序是如何用这些规则来输入的表达式 并返回一个合理的答案？\nHow is the simplifier program going to manipulate these rules with your expression to produce a reasonable answer?\n\n199\n00:18:26,224 --> 00:18:29,856\n首先 我认为我们有一大堆的规则\nWell, first, I'd like to think about these rules as being some sort of deck of them.\n\n200\n00:18:32,528 --> 00:18:34,224\n这里有全部的规则\nSo here I have a whole bunch of rules,\n\n201\n00:18:42,096 --> 00:18:44,496\n这里的每一个规则 ---\nEach rule-- here's a rule--\n\n202\n00:18:46,976 --> 00:18:49,248\n都有一个模式和一个骨架\nhas a pattern and a skeleton.\n\n203\n00:18:49,728 --> 00:18:51,360\n我正在努力为它作一个控制结构\nI'm trying to make up a control structure for this.\n\n204\n00:18:53,376 --> 00:18:56,560\n我有一个匹配器\nNow, what I have is a matcher,\n\n205\n00:19:00,992 --> 00:19:03,760\n还有一个实例化器\nand I have something which is an instantiater.\n\n206\n00:19:09,660 --> 00:19:12,944\n我将把一系列模式变量的值\nAnd I'm going to pass from the matcher to the instantiater\n\n207\n00:19:14,032 --> 00:19:17,470\n从匹配器中传递到实例化器中\nsome set of meaning for the pattern variables,\n\n208\n00:19:18,064 --> 00:19:19,420\n我把传递的东西叫做词典\na dictionary, I'll call it.\n\n209\n00:19:20,592 --> 00:19:21,520\n传递一本词典\nA dictionary,\n\n210\n00:19:24,928 --> 00:19:27,824\n里面记载了：x匹配下列子表达式\nwhich will say x was matched against the following subexpression\n\n211\n00:19:29,040 --> 00:19:31,312\n而y匹配另一个子表达式\nand y was matched against another following subexpression.\n\n212\n00:19:32,256 --> 00:19:36,352\n我会从实例化器中构造表达式 并送入匹配器\nAnd from the instantiater, I will be making expressions,and they will go into the matcher.\n\n213\n00:19:37,168 --> 00:19:38,368\n这些是表达式\nThey will be expressions.\n\n214\n00:19:45,008 --> 00:19:48,416\n这些规则的模式将要送进匹配器中\nAnd the patterns of the rules will be fed into the matcher,\n\n215\n00:19:49,248 --> 00:19:54,400\n规则对应的骨架将要送进实例化器中\nand the skeletons from the same rule will be fed into the instantiater.\n\n216\n00:19:55,216 --> 00:19:56,624\n现在变得有点复杂了\nNow, this is a little complicated\n\n217\n00:19:57,120 --> 00:19:59,536\n因为当我们处理代数表达式时\nbecause when you have something like an algebraic expression,\n\n218\n00:20:00,448 --> 00:20:03,600\n有一些规则使你能够做等价代换\nwhere  some of the rules are intended to be able to allow you to substitute equal for equal.\n\n219\n00:20:04,240 --> 00:20:05,872\n这些是等价代换规则\nThese are equal transformation rules.\n\n220\n00:20:06,880 --> 00:20:09,296\n所以需要考察表达式的所有子表达式\nSo all subexpressions of the expression should be looked at.\n\n221\n00:20:11,136 --> 00:20:15,824\n给定一个表达式 这些规则应该被不断应用\nYou give it an expression, this thing, and the rules should be cycled around.\n\n222\n00:20:16,032 --> 00:20:19,712\n首先 对于传入的表达式的每个子表达式\nFirst of all, for every subexpression of the expression you feed in,\n\n223\n00:20:20,224 --> 00:20:22,832\n所有的规则都需要考察一次\nall of the rules must be tried and looked at.\n\n224\n00:20:24,336 --> 00:20:27,072\n如果有规则匹配成功 那么就会执行这个过程\nAnd if any rule matches, then this process occurs.\n\n225\n00:20:27,300 --> 00:20:30,630\n传递一本存储值的词典\nThe dictionary--the dictionary is to have some values in it.\n\n226\n00:20:30,630 --> 00:20:33,392\n实例化器产生一个新的表达式\nThe instantiater makes a new expression,\n\n227\n00:20:33,904 --> 00:20:39,104\n该表达式基本上只是替换了原表达式中匹配的部分\nwhich is basically replaces that part of the expression that was matched in your original expression.\n\n228\n00:20:40,848 --> 00:20:44,464\n然后 我们要对它重新检查\nAnd then, then, of course, we're going to recheck that,\n\n229\n00:20:44,752 --> 00:20:48,112\n重新考察这些规则 看看表达式是否可以更进一步化简\ngoing to go around these rules again, seeing if that could be simplified further.\n\n230\n00:20:49,536 --> 00:20:53,712\n然后每一个子表达式这样做 直到没有任何变化为止\nAnd then, then we're going to do that for every subexpression until the thing no longer changes.\n\n231\n00:20:54,960 --> 00:20:57,504\n你可以把它想像成一个有机过程\nYou can think of this as sort of an organic process.\n\n232\n00:20:57,830 --> 00:21:00,208\n我们有一锅炖汤\nYou've got some sort of stew, right?\n\n233\n00:21:00,240 --> 00:21:04,320\n粘乎乎的汤里面有细菌 有酶\nYou've got bacteria or something, or enzymes in some, in some gooey mess.\n\n234\n00:21:05,632 --> 00:21:10,500\n这些酶改变了汤\nAnd there's these--and these enzymes change things.\n\n235\n00:21:10,500 --> 00:21:14,384\n它们附着在你的表达式上 改变了它 然后就走了\nThey attach to your expression, change it, and then they go away.\n\n236\n00:21:15,280 --> 00:21:17,830\n就像钥匙和锁一样 它们需要配对\nAnd they have to match. The key-in-lock phenomenon.\n\n237\n00:21:18,000 --> 00:21:19,730\n匹配 -- 改变 -- 然后离开\nThey match, they change it, they go away.\n\n238\n00:21:19,730 --> 00:21:21,680\n你可以将其想像成一种并行过程\nYou can imagine it as a parallel process of some sort.\n\n239\n00:21:22,704 --> 00:21:24,976\n所以你把一个表达式放到这锅“浓汤”中\nSo you stick an expression into this mess,\n\n240\n00:21:25,808 --> 00:21:28,000\n过了会儿把它拿出来 它就被简化了\nand after a while, you take it out, and it's been simplified.\n\n241\n00:21:30,448 --> 00:21:32,640\n它会一直变化 直到不能再变化为止\nAnd it just keeps changing until it no longer can be changed.\n\n242\n00:21:33,360 --> 00:21:38,336\n但这些酶可以附着在表达式的任何部分\nBut these enzymes can attach to any part of the, of the expression.\n\n243\n00:21:39,216 --> 00:21:43,760\n课先上到这里 有问题么？\nOK, at this point, I'd like to stop and ask for questions.\n\n244\n00:21:44,928 --> 00:21:45,360\n请讲\nYes.\n\n245\n00:21:45,430 --> 00:21:52,760\n学生：匹配器和实例化器是两个独立的程序 是么?\nAUDIENCE: This implies that the matching program and the instantiation program are separate programs; is that right? Or is that-- they are.\n\n246\n00:21:52,760 --> 00:21:53,856\n教授：他们被拆分成很多小片\nPROFESSOR: They're separate little pieces.\n\n247\n00:21:54,144 --> 00:21:56,600\n然后在一个更大的结构中组合起来\nThey fit together in a larger structure.\n\n248\n00:21:57,264 --> 00:21:59,136\n学生：先扫描并匹配\nAUDIENCE: So I'm going through and matching\n\n249\n00:21:59,616 --> 00:22:03,216\n并把匹配结果传递给实例化器\nand passing the information about what I matched to an instantiater,\n\n250\n00:22:03,390 --> 00:22:06,032\n实例化器做出更改 并将其返回给匹配器\nwhich makes the changes. And then I pass that back to the matcher?\n\n251\n00:22:06,110 --> 00:22:08,496\n教授：不是直接更改 而是生成新的表达式\nPROFESSOR: It won't make a change. It will make a new expression,\n\n252\n00:22:09,616 --> 00:22:18,432\n新表达式中的模式变量都被左边式子中所匹配的值所替换\nwhich has, which has substituted the values of the pattern variable that were matched on the left-hand side for the variables that are mentioned,\n\n253\n00:22:18,992 --> 00:22:23,808\n也就是右边式子中的那些骨架变量 或者说求值变量\nthe skeleton variables or evaluation variables or whatever I called them, on the right-hand side.\n\n254\n00:22:25,200 --> 00:22:27,088\n学生：然后它要回传给匹配器么?\nAUDIENCE: And then that's passed back into the matcher?\n\n255\n00:22:27,200 --> 00:22:32,320\n教授：然后要再进行一轮 直到表达式不再变化\nPROFESSOR: Then this is going to go around again. This is going to go through this mess until it no longer changes.\n\n256\n00:22:33,312 --> 00:22:37,008\n学生：感觉这样递归循环似乎有些危险\nAUDIENCE: And it seems that there would be a danger of getting into a recursive loop.\n\n257\n00:22:37,200 --> 00:22:42,000\n教授：你说得很对 如果你定义的规则不好--\nYes, if you do not write your rules nicely, you are-- indeed,\n\n258\n00:22:42,000 --> 00:22:45,536\n你发明的任何语言 如果它可以做任何事情\nin any programming language you invent, if it's sufficiently powerful to do anything,\n\n259\n00:22:45,728 --> 00:22:48,400\n你就可能写出无限循环的程序\nyou can write programs that will go into infinite loops.\n\n260\n00:22:49,376 --> 00:22:55,072\n确实 诸如代数处理 这样的过程可能会产生无限循环\nAnd indeed, writing a program for doing algebraic manipulation so on will produce infinite loops.\n\n261\n00:23:01,056 --> 00:23:01,520\n教授：请讲\nGo ahead.\n\n262\n00:23:01,790 --> 00:23:05,904\n学生：一些语言的设计者觉得这个特性非常重要\nAUDIENCE: Some language designers feel that this feature is so important\n\n263\n00:23:05,936 --> 00:23:12,030\n以至于它应该是语言的一部分 比如Scheme\nthat it should become part of the basic language, for example, scheme in this case.\n\n264\n00:23:12,030 --> 00:23:13,960\n你的观点是--\nWhat are your thoughts on--\n\n265\n00:23:13,960 --> 00:23:15,088\n老师：语言的什么特性?\nPROFESSOR: Which language feature?\n\n266\n00:23:15,792 --> 00:23:17,260\n学生：模式匹配\nAUDIENCE: The pattern matching.\n\n267\n00:23:17,260 --> 00:23:22,030\n所有应用的这些规则应该 ---\nIt's all application of such rules should be--\n\n268\n00:23:22,030 --> 00:23:23,700\n教授：你是说像 Prolog 那样？\nPROFESSOR: Oh, you mean like Prolog?\n\n269\n00:23:23,700 --> 00:23:26,600\n学生：类似 Prolog 但更加通用的--\nAUDIENCE: Like Prolog, but it becomes a more general--\n\n270\n00:23:26,600 --> 00:23:27,648\n教授：这是可行的\nPROFESSOR: It's possible.\n\n271\n00:23:28,464 --> 00:23:32,304\n好了 我是觉得吧…… 恩……\nOK, I think my feeling about that is that\n\n272\n00:23:33,168 --> 00:23:36,496\n我可以教你怎么做 这样你就不用依靠语言的设计者\nI would like to teach you how to do it so you don't depend upon some language designer.\n\n273\n00:23:40,928 --> 00:23:42,752\n教授：我们可以自己来实现\nPROFESSOR: You make it yourself. You can roll your own.\n\n274\n00:23:45,280 --> 00:23:45,630\n下课\nThank you.\n\n275\n00:23:45,630 --> 00:23:50,630\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n276\n00:23:50,630 --> 00:23:53,130\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n277\n00:23:53,130 --> 00:23:55,630\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n278\n00:24:00,320 --> 00:24:06,768\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n279\n00:24:07,070 --> 00:24:10,528\n模式匹配：基于规则的代换\nPattern-matching: Rule-based Substitution\n\n280\n00:24:14,080 --> 00:24:15,800\n好 上课\nWell, let's see.\n\n281\n00:24:15,800 --> 00:24:17,216\n现在 我得告诉你们它是如何运作的\nNow we have to tell you how it works.\n\n282\n00:24:20,000 --> 00:24:24,112\n它很容易分成很多小份\nIt conveniently breaks up into various pieces.\n\n283\n00:24:24,800 --> 00:24:26,544\n现在 我们先看一下匹配器\nI'd like to look now at the matcher.\n\n284\n00:24:28,720 --> 00:24:31,424\n匹配器的结构是像下面这样的\nThe matcher has the following basic structure.\n\n285\n00:24:32,860 --> 00:24:45,120\n它是一个盒子 它的输入是一个表达式和一个模式\nIt's a box that takes as its input an expression and a pattern,\n\n286\n00:24:52,096 --> 00:24:53,952\n还有个输入是一本词典\nand it turns out a dictionary.\n\n287\n00:25:01,712 --> 00:25:08,672\n要记住 词典把模式变量映射到匹配的值上\nA dictionary, remember, is a mapping of pattern variables to the values that were found by matching,\n\n288\n00:25:09,152 --> 00:25:11,056\n它的输出是另一本词典\nand it puts out another dictionary,\n\n289\n00:25:18,240 --> 00:25:25,536\n除了旧词典中已有的内容 新词典中还产生的新的匹配\nwhich is the result of augmenting this dictionary by what was found in matching this expression against this pattern.\n\n290\n00:25:28,000 --> 00:25:28,832\n这就是匹配器\nSo that's the matcher.\n\n291\n00:25:33,872 --> 00:25:36,544\n这是一个相当复杂的程序\nNow, this is a rather complicated program,\n\n292\n00:25:37,200 --> 00:25:41,584\n请大家看看这里的投影 请看\nNow, this is a rather complicated program, and we can look at it on the overhead over here and see,\n\n293\n00:25:41,984 --> 00:25:43,872\n哈哈 真是相当复杂\nha ha, it's very complicated.\n\n294\n00:25:44,432 --> 00:25:45,872\n我只想让大家看一下它的轮廓\nI just want you to look at the shape of it.\n\n295\n00:25:46,784 --> 00:25:49,856\n其实现细节太复杂了\nIt's too complicated to look at except in pieces.\n\n296\n00:25:51,728 --> 00:25:59,248\n然而 这是一个庞大的程序 它有很多这样的缩进的结构\nHowever, it's a fairly large, complicated program with a lot of sort of indented structure.\n\n297\n00:26:00,096 --> 00:26:05,280\n在最外层 -- 不要去读这些代码  宏观地看\nAt the largest scale-- you don't try to read those characters, but at the largest scale,\n\n298\n00:26:05,430 --> 00:26:10,368\n这里有一个分情况分析 而这些就是不同的情况\nyou see that there is a case analysis, which is all these cases lined up.\n\n299\n00:26:12,090 --> 00:26:16,192\n现在 我们将要深入细节\nWhat we're now going to do is look at this in a bit more detail,\n\n300\n00:26:16,672 --> 00:26:18,600\n试图理解它是如何工作的\nattempting to understand how it works.\n\n301\n00:26:20,080 --> 00:26:22,352\n我们来看第一张幻灯片\nLet's go now to the first slide,\n\n302\n00:26:23,552 --> 00:26:27,936\n它展示了匹配器的宏观结构\nshowing some of the structure of the matcher at a large scale.\n\n303\n00:26:28,816 --> 00:26:36,336\n我们看到匹配器 它需要的参数有：模式、表达式和词典\nAnd we see that the matcher, the matcher takes as its input a pattern, an expression, and a dictionary.\n\n304\n00:26:38,576 --> 00:26:40,400\n这里是一个cond语句\nAnd there is a case analysis here,\n\n305\n00:26:41,248 --> 00:26:45,616\n它有许多不同情况 我们省略了一些代码\nwhich is made out of several cases, some of which have been left out over here,\n\n306\n00:26:46,624 --> 00:26:48,624\n这个是我想让大家注意的 通用情况\nand the general case, which I'd like you to see.\n\n307\n00:26:50,528 --> 00:26:53,280\n考虑这个通用模式 它是个非常重要的模式\nLet's consider this general case. It's a very important pattern.\n\n308\n00:26:56,320 --> 00:27:01,616\n问题是我们需要同时地检查这两棵树\nThe problem is that we have to examine two trees simultaneously.\n\n309\n00:27:02,500 --> 00:27:08,030\n一棵树是表达式 另一棵树是模式\nOne of the trees is the tree of the expression, and the other is the tree of the pattern.\n\n310\n00:27:08,590 --> 00:27:10,112\n我们需要在它们之间进行匹配\nWe have to compare them with each other\n\n311\n00:27:11,376 --> 00:27:16,384\n使得表达式的子表达式会与模式的子表达式相匹配\nso that the subexpressions of the expression are matched against subexpressions of the pattern.\n\n312\n00:27:18,384 --> 00:27:23,440\n我们深入研究一下 假设我有一个模式\nLooking at that in a bit more detail, suppose I had a pattern, a pattern,\n\n313\n00:27:23,930 --> 00:27:31,248\n这个是模式是 一个叫做x的表达式 乘以\nwhich was the sum of the product of a thing which we will call x\n\n314\n00:27:32,448 --> 00:27:35,536\n乘以一个我们叫做y的表达式\nand a thing which we will call y,\n\n315\n00:27:39,120 --> 00:27:42,048\n再加上 刚才的表达式y 两个y必须是相同的表达式\nand the sum of that, and the same thing we call y.\n\n316\n00:27:45,210 --> 00:27:47,536\n我们在考察 乘式的和\nSo we're looking for a sum of a product\n\n317\n00:27:48,992 --> 00:27:54,784\n其中 乘法和加法的第二个参数都是相同的\nwhose second--whose second argument is the same as the second argument of the sum.\n\n318\n00:27:57,024 --> 00:27:58,848\n这是我们想要匹配像这样的表达式\nThat's a thing you might be looking for.\n\n319\n00:27:59,600 --> 00:28:02,048\n它作为一个模式看起来像这个样子\nWell, that, as a pattern, looks like this.\n\n320\n00:28:03,024 --> 00:28:04,016\n这是一课树\nThere is a tree,\n\n321\n00:28:04,940 --> 00:28:06,256\n它包含了一个加号\nwhich consists of a sum,\n\n322\n00:28:08,080 --> 00:28:20,256\n还有乘号 以及模式变量(? x)和(? y)\nand a product with a pattern variable question mark x and question mark y,\n\n323\n00:28:21,360 --> 00:28:22,736\n还有模式变量(? y)\nand question mark y,\n\n324\n00:28:24,920 --> 00:28:26,944\n这只是把表结构换了种写法 两者其实是一样的\njust looking at the same, just writing down the list structure in a different way.\n\n325\n00:28:28,752 --> 00:28:31,760\n我们先演示一个成功的匹配是如何运行的\nNow, suppose we were matching that against an expression which matches it,\n\n326\n00:28:32,496 --> 00:28:39,856\n这个模式匹配表达式 (+ (* 3 x) x)\nthe product of 3 and x and, say, x.\n\n327\n00:28:42,416 --> 00:28:43,360\n这是另一棵个树\nThat's another tree.\n\n328\n00:28:44,336 --> 00:28:56,064\n它是3乘以x的积加上x\nIt's the sum of the product of 3 and x and of x.\n\n329\n00:28:59,440 --> 00:29:03,024\n所以我要做的是 同时遍历这两棵树\nSo what I want to do is traverse these two trees simultaneously.\n\n330\n00:29:04,416 --> 00:29:07,824\n我想这样遍历它们\nAnd what I'd like to do is walk them like this.\n\n331\n00:29:08,672 --> 00:29:12,960\n我会比较它们是否一样\nI'm going to say are these the same?\n\n332\n00:29:12,960 --> 00:29:14,320\n这是一个复合对象\nThis is a complicated object.\n\n333\n00:29:15,216 --> 00:29:17,260\n我们先看它的左分支\nLet's look at the left branches.\n\n334\n00:29:17,260 --> 00:29:18,144\n这可能是car部分\nWell, that could be the car.\n\n335\n00:29:18,560 --> 00:29:21,216\n它们匹配吗？恩 两个加号成功匹配\nHow does that look? Oh yes, the plus looks just fine.\n\n336\n00:29:21,680 --> 00:29:24,200\n但是下一个对象是复合的\nBut the next thing here is a complicated thing.\n\n337\n00:29:24,200 --> 00:29:24,848\n我们看一下它\nLet's look at that.\n\n338\n00:29:25,200 --> 00:29:26,800\n这个也匹配了\nOh yes, that's pretty fine, too.\n\n339\n00:29:26,800 --> 00:29:27,792\n它们都是星号\nThey're both asterisks.\n\n340\n00:29:28,512 --> 00:29:30,240\n现在……哦！\nNow, whoops!\n\n341\n00:29:30,400 --> 00:29:33,600\n这是模式变量 它和3相匹配\nMy pattern variable, it matches against the 3.\n\n342\n00:29:34,272 --> 00:29:35,920\n记住 现在x等于3\nRemember, x equals 3 now.\n\n343\n00:29:36,360 --> 00:29:37,376\n把它记录在词典中\nThat's in my dictionary,\n\n344\n00:29:37,568 --> 00:29:40,730\n遍历过程中 词典紧随着我们 并告诉我们：x等于3\nand the dictionary's going to follow along with me: x equals three.\n\n345\n00:29:41,456 --> 00:29:45,872\nx等于3 y等于x 但这两个是不同意义上的x\nAh yes, x equals 3 and y equals x, different x.\n\n346\n00:29:46,832 --> 00:29:51,200\n那个是模式变量x 而这个是模式变量y匹配表达式x\nThe pattern x is the expression x, the pattern y.\n\n347\n00:29:53,616 --> 00:29:57,760\n这是模式变量y 它已经有值了 并且值是x\nOh yes, the pattern variable y, I've already got a value for it. It's x.\n\n348\n00:29:58,368 --> 00:30:00,060\n这是x么? 当然是\nIs this an x? Oh yeah, sure it is.\n\n349\n00:30:00,060 --> 00:30:00,752\n好的\nThat's fine.\n\n350\n00:30:02,032 --> 00:30:02,784\n完事儿了\nYep, done.\n\n351\n00:30:03,392 --> 00:30:08,096\n现在 我有一本词典 它在遍历过程中不断积累\nI now have a dictionary, which I've accumulated by making this walk.\n\n352\n00:30:11,424 --> 00:30:14,512\n现在让我们看看这个一般情况 然后看看它如何工作\nWell, now let's look at this general case here and see how that works.\n\n353\n00:30:15,888 --> 00:30:16,512\n这里..\nHere we have it.\n\n354\n00:30:17,200 --> 00:30:21,664\n我传入一个模式 一个表达式 和一本词典\nI take in a pattern variable -- sorry -- a pattern, an expression, and a dictionary.\n\n355\n00:30:22,384 --> 00:30:27,504\n这里的情况比较复杂 -- 它是通用情况\nAnd now I'm going to do a complicated thing here, which is the general case.\n\n356\n00:30:29,984 --> 00:30:34,800\n一般来说 表达式由两部分组成：左部分和右部分\nThe expression is made out of two parts: a left and a right half, in general.\n\n357\n00:30:35,456 --> 00:30:38,816\n在Lisp系统中 复合对象都是由两部分组成的\nAnything that's complicated is made out of two pieces in a Lisp system.\n\n358\n00:30:40,032 --> 00:30:41,232\n现在我们有什么呢？\nWell, now what do we have here?\n\n359\n00:30:41,888 --> 00:30:48,848\n我将会用已有的这本词典 继续匹配模式和表达式的car部分\nI'm going to match the car's of the two expressions against each other with respect to the dictionary I already have,\n\n360\n00:30:50,300 --> 00:30:53,120\n这个匹配过程会产生一本新词典\nproducing a dictionary as its value,\n\n361\n00:30:54,144 --> 00:30:57,264\n我将用它来匹配它们的cdr部分\nwhich I will then use for matching the cdr's against each other.\n\n362\n00:30:58,512 --> 00:31:02,096\n这就是词典是如何在整个结构中遍历、线索的\nSo that's how the dictionary travels, threads the entire structure.\n\n363\n00:31:03,660 --> 00:31:07,536\n匹配完car和cdr部分后得到的词典\nAnd then the result of that is the dictionary for the match of the car and the cdr,\n\n364\n00:31:10,128 --> 00:31:12,410\n会作为值返回给上级\nand that's what's going to be returned as a value.\n\n365\n00:31:13,616 --> 00:31:15,840\n匹配可能会在任何一个地方失败\nNow, at any point, a match might fail.\n\n366\n00:31:16,620 --> 00:31:18,208\n比如说 可能会有这种情况\nIt may be the case, for example,\n\n367\n00:31:18,368 --> 00:31:27,180\n我们回过头来把这里改成4 这样就不会完全匹配\nif we go back and look at an expression that doesn't quite match, like supposing this was a 4.\n\n368\n00:31:29,136 --> 00:31:34,816\n现在这两个不再匹配了 因为x应该\nWell, now these two don't match any more, because the x that had to be  --\n\n369\n00:31:34,930 --> 00:31:37,344\n不好意思 这个y是x\nsorry, the y that had to be x here\n\n370\n00:31:37,824 --> 00:31:40,128\n但是这里的y却又是4\nand this y has to be 4.\n\n371\n00:31:40,530 --> 00:31:43,520\n语法上来说 x和4显然不相同\nBut x and 4 were not the same object syntactically.\n\n372\n00:31:44,592 --> 00:31:48,816\n所以这个不会匹配成功 它会拒绝 匹配会失败\nSo this wouldn't match, and that would be rejected sometimes, so matches may fail.\n\n373\n00:31:50,192 --> 00:31:56,080\n那么 因为先前产生的词典会作为输入送入匹配器\nNow, of course, because this matcher takes the dictionary from the previous match as input,\n\n374\n00:31:56,528 --> 00:31:58,288\n所以它必须能够传播失败\nit must be able to propagate the failures.\n\n375\n00:31:58,576 --> 00:32:01,040\n第一条语句就是用来判断失败的\nAnd so that's what the first clause of this conditional does.\n\n376\n00:32:03,616 --> 00:32:08,192\n如果证实出来这个模式不是原子的---\nIt's also true that if it turned out that the pattern was not atomic--\n\n377\n00:32:08,500 --> 00:32:11,456\n如果模式是原子的 将进入这里 这里我们还没有讨论过\nsee, if the pattern was atomic, I'd go into this stuff, which we haven't looked at yet.\n\n378\n00:32:12,170 --> 00:32:13,568\n如果模式不是原子的\nBut if the pattern is not atomic\n\n379\n00:32:15,056 --> 00:32:19,232\n但表达式是原子--也就是它不由小部分组成\nand the expression is atomic-- it's not made out of pieces--\n\n380\n00:32:20,144 --> 00:32:22,650\n那么匹配必然失败 因此我们返回'failed\nthen that must be a failure, and so we go over here.\n\n381\n00:32:23,648 --> 00:32:30,784\n整理下思路 如果这个模式既不是原子的又不是模式变量的话 程序会来到这里\nIf the pattern is not atomic and the pattern is not a pattern variable--I have to remind myself of that-- then we go over here.\n\n382\n00:32:30,960 --> 00:32:32,512\n这是会使匹配失败的情况\nSo that's way, failures may occur.\n\n383\n00:32:35,264 --> 00:32:39,120\n好 让我们看这个里面的东西\nOK, so now let's look at the insides of this thing.\n\n384\n00:32:39,840 --> 00:32:42,930\n首先需要知道 如果用原子模式来进行匹配会发生什么？\nWell, the first place to look is what happens if I have an atomic pattern?\n\n385\n00:32:42,930 --> 00:32:43,900\n这简单\nThat's very simple.\n\n386\n00:32:43,900 --> 00:32:46,500\n不是由其它模式构成的模式 比如：foo\nA pattern that's not made out of any pieces: foo.\n\n387\n00:32:47,376 --> 00:32:48,544\n这是个非常好的原子模式\nThat's a nice atomic pattern.\n\n388\n00:32:49,168 --> 00:32:51,248\n让我们来看看\nWell, here's what we see.\n\n389\n00:32:52,080 --> 00:32:55,824\n如果模式是原子的 而且表达式也原子的话\nIf the pattern is atomic, then if the expression is atomic,\n\n390\n00:32:56,800 --> 00:33:01,856\n并且如果它俩是同一个东西 那么词典就跟之前一样\nthen if they are the same thing, then the dictionary I get is the same one as I had before.\n\n391\n00:33:03,088 --> 00:33:04,000\n没有变化\nNothing's changed.\n\n392\n00:33:04,608 --> 00:33:10,336\n就像刚才 +匹配+ *匹配* x匹配x\nIt's just that I matched plus against plus, asterisk against asterisk, x against x.\n\n393\n00:33:11,424 --> 00:33:12,336\n就是那样\nThat's all fine.\n\n394\n00:33:13,072 --> 00:33:16,816\n然而 如何模式和表达式并不相同的话\nHowever, if the pattern is not the one which is the expression,\n\n395\n00:33:17,328 --> 00:33:21,360\n如果这是两个不同的原子对象 比如+和*相匹配\nif I have two separate atomic objects, then it was matching plus against asterisk,\n\n396\n00:33:22,448 --> 00:33:23,408\n这样就失败了\nwhich case I fail.\n\n397\n00:33:25,600 --> 00:33:34,560\n或者说 如果模式是原子 但表达式是复合 那么匹配失败\nOr if it turns out that the pattern is atomic but the expression is complicated, it's not atomic, then I get a failure.\n\n398\n00:33:37,408 --> 00:33:38,240\n这很简单\nThat's very simple.\n\n399\n00:33:38,816 --> 00:33:43,616\n那么 那些各种各样的模式变量又是怎么处理的呢？\nNow, what about the various kinds of pattern variables?\n\n400\n00:33:44,090 --> 00:33:46,544\n我们有三类被命名了的模式变量\nWe had three kinds. I give them the names.\n\n401\n00:33:47,392 --> 00:33:52,032\n它们分别用于匹配：任意常量 任意变量 任意表达式\nThey're arbitrary constants, arbitrary variables, and arbitrary expressions.\n\n402\n00:33:53,824 --> 00:34:00,144\n(? x) 表示匹配任意表达式\nA question mark x is an arbitrary expression.\n\n403\n00:34:01,184 --> 00:34:04,544\n(?c x) 表示匹配任意常量\nA question mark cx is an arbitrary constant,\n\n404\n00:34:04,730 --> 00:34:07,296\n(?v x) 表示匹配任意变量\nand a question mark vx is an arbitrary variable.\n\n405\n00:34:08,960 --> 00:34:09,792\n好的 我们要做什么呢?\nWell, what do we do here?\n\n406\n00:34:10,512 --> 00:34:16,944\n看这里 如果模式表示的是匹配任意常量\nLooking at this, we see that if I have an arbitrary constant, if the pattern is an arbitrary constant,\n\n407\n00:34:17,536 --> 00:34:20,576\n那么待匹配的表达式最好是一个常量\nthen it had better be the case that the expression had better be a constant.\n\n408\n00:34:21,488 --> 00:34:23,536\n不然的话 匹配就会失败\nIf the expression is not a constant, then that match fails.\n\n409\n00:34:23,830 --> 00:34:27,500\n如果是一个常量 那么我就需要扩充词典\nIf it is a constant, however, then I wish to extend the dictionary.\n\n410\n00:34:27,500 --> 00:34:29,696\n扩充词典的方法则是：\nI wish to extend the dictionary\n\n411\n00:34:30,704 --> 00:34:37,760\n在旧词典后 附加一对模式与表达式的配对\nwith that pattern being remembered to be that expression using the old dictionary as a starting point.\n\n412\n00:34:41,160 --> 00:34:42,752\n因此 如果是匹配任意变量\nSo really, for arbitrary variables,\n\n413\n00:34:43,728 --> 00:34:47,460\n我得通过匹配来核查表达式是否是变量\nI have to check first if the expression is a variable by matching against.\n\n414\n00:34:47,460 --> 00:34:50,096\n如果是的话 我就扩充词典\nIf so, it's worth extending the dictionary\n\n415\n00:34:50,384 --> 00:34:54,650\n现在在原有词典基础上 我们又多了一项模式与表达式的匹配\nso the pattern is remembered to be matched against that expression, given the original dictionary,\n\n416\n00:34:55,280 --> 00:34:56,704\n这个过程返回一本新的词典\nand this makes a new dictionary.\n\n417\n00:34:58,880 --> 00:35:04,160\n在这个词典中也有很多失败 因此需要检查\nNow, it has to check. There's a sorts of failure inside extend dictionary, which is that--\n\n418\n00:35:04,160 --> 00:35:07,504\n就比如 模式变量已经有一个值了\nif one of these pattern variables already has a value\n\n419\n00:35:09,230 --> 00:35:16,176\n但我又用它匹配一个跟之前匹配的表达式不相同的表达式的话\nand I'm trying to match the thing against something else which is not equivalent to the one that I've already matched it against once,\n\n420\n00:35:16,432 --> 00:35:18,368\n那么在这里也会立即产生失败\nthen a failure will come flying out of here, too.\n\n421\n00:35:20,160 --> 00:35:21,568\n我们后面再讨论\nAnd I will see that some time.\n\n422\n00:35:22,910 --> 00:35:29,360\n最后 匹配任意的表达式不需要在语法范畴做什么检查\nAnd finally, an expression does not have to check anything syntactic about the expression that's being matched,\n\n423\n00:35:30,112 --> 00:35:32,208\n只用扩充词典就行了\nso all it does is it's an extension of the dictionary.\n\n424\n00:35:34,768 --> 00:35:38,320\n这就是一个完整的简单的匹配器\nSo you've just seen a complete, very simple matcher.\n\n425\n00:35:39,280 --> 00:35:41,376\n非常具有讽刺意味的一点是\nNow, one of the things that's rather remarkable about this\n\n426\n00:35:41,660 --> 00:35:45,120\n现在 人们花了大价钱来请一些人编写\nis people pay an awful lot of money these days for someone to make\n\n427\n00:35:45,460 --> 00:35:47,520\n所谓的 “人工智能专家系统”\na, quote, AI expert system\n\n428\n00:35:48,400 --> 00:35:52,032\n也不过是像这样的一个匹配器和实例化器罢了\nthat has nothing more in it than a matcher and maybe an instantiater like this.\n\n429\n00:35:53,568 --> 00:35:56,944\n这很容易做 现在你也可以创业开个小公司了\nBut it's very easy to do, and now, of course, you can start up a little start-up company\n\n430\n00:35:57,424 --> 00:36:01,728\n然后 第二周忽悠风投给你投个几百万\nand make a couple of megabucks in the next week taking some people for a ride.\n\n431\n00:36:03,792 --> 00:36:08,570\n我是想说 这种程序放在20年前是非凡的\nI mean, 20 years ago, this was remarkable, this kind of program.\n\n432\n00:36:09,740 --> 00:36:12,816\n但放到现在 它就是小菜一碟了 大一新生也可以学\nBut now, this is sort of easy. You can teach it to freshmen.\n\n433\n00:36:13,632 --> 00:36:15,472\n这里是一个实例化器\nWell, now there's an instantiater as well.\n\n434\n00:36:20,224 --> 00:36:23,072\n可问题是 他们都去了赚钱了 而且比我的还多\nThe problem is they're all going off and making more money than I do. Alright?\n\n435\n00:36:24,976 --> 00:36:26,592\n在大学中确实是这样\nBut that's always been true of universities.\n\n436\n00:36:27,104 --> 00:36:39,424\n实例化是用来将给定的表达式、词典和骨架生成新的表达式的\nAs expression, the purpose of the instantiater is to make expressions given a dictionary and a skeleton.\n\n437\n00:36:44,352 --> 00:36:45,696\n这个不是很难\nAnd that's not very hard at all.\n\n438\n00:36:46,608 --> 00:36:53,360\n我们在下一张幻灯片中简单地看下\nWe'll see that very simply in the next, the next slide here.\n\n439\n00:36:53,888 --> 00:36:59,296\n用一本给定的词典去实例化一个骨架 这很简单\nTo instantiate a skeleton, given a particular dictionary-- oh, this is easy.\n\n440\n00:36:59,680 --> 00:37:03,296\n我们要做的 就是对骨架递归地做树遍历\nWe're going to do a recursive tree walk over the skeleton.\n\n441\n00:37:04,080 --> 00:37:08,330\n所有的骨架变量---我叫它“骨架求值”\nAnd for everything which is a skeleton variable-- I don't know, call it a skeleton evaluation.\n\n442\n00:37:08,416 --> 00:37:11,424\n这是我在这个程序中定义的抽象语法\nThat's the name and the abstract syntax that I give it in this program:\n\n443\n00:37:11,600 --> 00:37:16,464\n在规则中 以冒号打头的就是骨架求值\na skeleton evaluation, a thing beginning with a colon in the rules.\n\n444\n00:37:18,256 --> 00:37:24,300\n在那种情况下 我要在词典中找答案 我们待会儿再讨论\nFor anything of that case, I'm going to look up the answer in the dictionary, and we'll worry about that in a second.\n\n445\n00:37:24,300 --> 00:37:25,616\n我们看整体\nLet's look at this as a whole.\n\n446\n00:37:27,776 --> 00:37:31,808\n这个过程是用一本字典来实例化一个骨架\nHere, I have-- I'm going to instantiate a skeleton, given a dictionary.\n\n447\n00:37:32,750 --> 00:37:37,152\n我在这里定义一个内部循环\nWell, I'm going to define some internal loop right there,\n\n448\n00:37:38,144 --> 00:37:39,850\n它要做的事情很简单\nand it's going to do something very simple.\n\n449\n00:37:40,176 --> 00:37:43,504\n如果这个骨架是原子的\nEven if a skeleton--even if a skeleton is simple and atomic,\n\n450\n00:37:44,608 --> 00:37:47,456\n这种情况 它直接返回一个骨架作为结果\nin which case it's nothing more than giving the skeleton back as an answer,\n\n451\n00:37:48,840 --> 00:37:51,872\n或者在通常情况下它是复合的\nor in the general case, it's complicated,\n\n452\n00:37:52,608 --> 00:37:59,400\n这种情况下 我通过一些实例化的结果构造表达式\nin which case I'm going to make up the expression which is the result of instantiating--\n\n453\n00:37:59,400 --> 00:38:04,256\n递归调用这个循环 不断实例化骨架的car和cdr部分\ncalling this loop recursively-- instantiating the car of the skeleton and the cdr.\n\n454\n00:38:04,896 --> 00:38:06,240\n这就是树的递归遍历\nSo here is a recursive tree walk.\n\n455\n00:38:08,416 --> 00:38:14,368\n如果在骨架中有冒号表达式 那么这就是一个骨架求值\nHowever, if it turns out to be a skeleton evaluation, a colon expression in the skeleton,\n\n456\n00:38:14,960 --> 00:38:22,640\n那么要做的事情是：找到冒号引导的表达式 -- 本例中 也就是CADR部分\nthen what I'm going to do is find the expression that's in the colon-- the CADR in this case.\n\n457\n00:38:22,816 --> 00:38:26,256\n这些是抽象语法 因此我能改变规则的表示\nIt's a piece of abstract syntax here, so I can change my representation of rules.\n\n458\n00:38:27,520 --> 00:38:32,736\n先不管求值过程如何实现 总之我要用这本词典对表达式求值\nI'm going to evaluate that relative to this dictionary, whatever evaluation means.\n\n459\n00:38:32,900 --> 00:38:34,656\n我们以后再仔细讨论\nWe'll find out a lot about that sometime.\n\n460\n00:38:36,128 --> 00:38:38,352\n求值的结果就是答案\nAnd the result of that is my answer.\n\n461\n00:38:39,680 --> 00:38:43,664\n这条初始化语句 通过给它传递整个骨架循环来启动它\nso. I start up this loop-- here's my initialization-- by calling it with the whole skeleton,\n\n462\n00:38:44,448 --> 00:38:47,040\n这些调用又会被分成小块的递归调用\nand this will just do a recursive decomposition into pieces.\n\n463\n00:38:49,632 --> 00:38:56,480\n那么 求值过程里面发生了些什么\nNow, one more little bit of detail is what happens inside evaluate?\n\n464\n00:38:57,184 --> 00:38:59,072\n我无法详尽地给你们解释\nI can't tell you that in great detail.\n\n465\n00:38:59,984 --> 00:39:01,344\n我就大致说一下\nI'll tell you a little bit of it.\n\n466\n00:39:01,560 --> 00:39:03,744\n之后 我们再深入地讨论\nLater, we're going to see--look into this in much more detail.\n\n467\n00:39:05,296 --> 00:39:10,816\n在一本词典的环境下 求值一个表达式\nTo evaluate some form, some expression with respect to a dictionary,\n\n468\n00:39:11,904 --> 00:39:14,176\n如果表达式是原子的\nif the expression is an atomic object, well,\n\n469\n00:39:15,040 --> 00:39:16,224\n就在词典中进行查找\nI'm going to go look it up.\n\n470\n00:39:18,608 --> 00:39:19,872\n这没啥\nNothing very exciting there.\n\n471\n00:39:20,576 --> 00:39:23,664\n难点在这里\nOtherwise, I'm going to do something complicated here,\n\n472\n00:39:23,830 --> 00:39:28,288\n我将要应用表达式的car部分对应的一个过程\nwhich is I'm going to apply a procedure which is the result of looking up the operator part\n\n473\n00:39:29,440 --> 00:39:31,680\n这个过程是在“某个地方”查找得到的--我们以后讨论\nin something that we're going to find out about someday.\n\n474\n00:39:32,144 --> 00:39:34,208\n我想请大家注意一下 这之中有一些“魔法”\nI want you realize you're seeing magic now.\n\n475\n00:39:34,672 --> 00:39:38,720\n这个魔法将在不久后“施展”出来 但不是在今天\nThis magic will become clear very soon, but not today.\n\n476\n00:39:40,000 --> 00:39:46,510\n我们在词典中查找表达式剩余部分对应的值\nThen I'm looking at--looking up all the pieces, all the arguments to that in the dictionary.\n\n477\n00:39:48,560 --> 00:39:50,880\n我还不想让你们关注细节\nSo I don't want you to look at this in detail.\n\n478\n00:39:51,440 --> 00:39:53,440\n我想让大家意识到这里还有很多代码\nI want you to see that there's more going on here,\n\n479\n00:39:54,176 --> 00:39:56,750\n我们以后再详细讨论\nand we're going to see more about this.\n\n480\n00:39:59,040 --> 00:40:00,880\n但是 魔法就到此结束了\nBut it's-- the magic is going to stop.\n\n481\n00:40:02,576 --> 00:40:06,960\n这部分利用Lisp的神奇力量 不过也就到此为止了\nThis part has to do with Lisp, and it's the end of that.\n\n482\n00:40:10,256 --> 00:40:13,568\n我们介绍了匹配和实例化\nOK, so now we know about matching and instantiation.\n\n483\n00:40:15,056 --> 00:40:16,608\n这一节有疑问么?\nAre there any questions for this segment?\n\n484\n00:40:28,100 --> 00:40:29,800\n学生：我有一个问题\nAUDIENCE: I have a question.\n\n485\n00:40:29,800 --> 00:40:30,430\n教授：请讲\nPROFESSOR: Yes.\n\n486\n00:40:30,430 --> 00:40:32,560\n学生：您能切到前张幻灯片上吗？\nAUDIENCE: Is it possible to bring up a previous slide?\n\n487\n00:40:33,600 --> 00:40:35,568\n是关于定义匹配模式的\nIt's about this define match pattern.\n\n488\n00:40:36,160 --> 00:40:40,760\n教授：好的 你想看定义匹配模式的全部的幻灯片\nPROFESSOR: Yes. You'd like to see the overall slide define match pattern.\n\n489\n00:40:40,760 --> 00:40:43,060\n有人能帮我把投影仪---\nCan somebody put up the -- no, the overhead.\n\n490\n00:40:43,060 --> 00:40:45,160\n这是最大的规模\nThat's the biggest scale one.\n\n491\n00:40:45,312 --> 00:40:46,400\n你想看哪一部分？\nWhat part would you like to see?\n\n492\n00:40:46,760 --> 00:40:49,960\n学生：呃 最上面吧\nAUDIENCE: Well, the top would be fine.\n\n493\n00:40:49,960 --> 00:40:53,760\n就是传递失败的那一部分\nAny of the parts where you're passing failed.\n\n494\n00:40:54,528 --> 00:40:55,216\n教授：恩\nPROFESSOR: Yes.\n\n495\n00:40:55,648 --> 00:40:59,330\n学生：基本的想法是把错误返回给词典 是么?\nAUDIENCE: The idea is to pass failed back to the dictionary; is that right?\n\n496\n00:40:59,330 --> 00:41:04,256\n教授：所谓的词典 就是所是匹配的答案 对吧？\nPROFESSOR: The dictionary is the answer to a match, right?\n\n497\n00:41:05,160 --> 00:41:09,808\n要么它是一些配对\nAnd it is either some mapping\n\n498\n00:41:11,072 --> 00:41:14,030\n要么根本就没有配对\nor there's no match. It doesn't match.\n\n499\n00:41:14,464 --> 00:41:14,976\n学生：对\nAUDIENCE: Right.\n\n500\n00:41:15,264 --> 00:41:17,830\n教授：这里 事实上\nPROFESSOR: So what you're seeing over here is, in fact,\n\n501\n00:41:17,830 --> 00:41:22,600\n因为一个匹配过程会向另一个匹配过程传递词典\nbecause the fact that a match may have another match pass in the dictionary,\n\n502\n00:41:22,800 --> 00:41:24,656\n可以在这里的一般情况中看到\nas you see in the general case down here.\n\n503\n00:41:25,120 --> 00:41:27,930\n这是一个匹配过程传递词典到另一个匹配过程\nHere's the general case where a match passes another match to the dictionary.\n\n504\n00:41:28,144 --> 00:41:34,160\n我是用匹配car部分得到的词典来匹配cdr部分的\nWhen I match the cdr's, I match them in the dictionary that is resulting from matching the car's.\n\n505\n00:41:36,064 --> 00:41:37,088\n这里的代码就是这个意思\nOK, that's what I have here.\n\n506\n00:41:37,296 --> 00:41:40,304\n正因为如此 如果对car部分的匹配失败了\nSo because of that, if the match of the car's fails,\n\n507\n00:41:41,232 --> 00:41:45,440\n匹配cdr部分的时候就有必要传播失败\nthen it may be necessary that the match of the cdr's propagates that failure,\n\n508\n00:41:45,952 --> 00:41:46,960\n第一行就是用于传播失败\nand that's what the first line is.\n\n509\n00:41:48,260 --> 00:41:51,730\n学生：好 但我还是不明白匹配 --\nAUDIENCE: OK, well, I'm still unclear what matches--\n\n510\n00:41:51,730 --> 00:41:54,240\n从匹配的实例出来的是什么?\nwhat comes out of one instance of the match?\n\n511\n00:41:54,730 --> 00:41:56,000\n教授：有两种可能的情况\nPROFESSOR: One of two possibilities.\n\n512\n00:41:56,336 --> 00:41:59,152\n一种是符号'failed 意味匹配失败\nEither the symbol failed, which means there is no match.\n\n513\n00:41:59,530 --> 00:41:59,930\n学生：对\nAUDIENCE: Right.\n\n514\n00:41:59,930 --> 00:42:03,872\n教授：或者是某种映射 -- 现在这还是一个抽象的东西\nPROFESSOR: Or some mapping, which is an abstract thing right now,\n\n515\n00:42:04,160 --> 00:42:05,680\n你需要知道它的结构\nand you should know about the structure of it,\n\n516\n00:42:06,496 --> 00:42:13,968\n它们把匹配过程中 匹配成功的模式变量和值关联起来\nwhich relates the pattern variables to their values as picked up in the match.\n\n517\n00:42:14,688 --> 00:42:16,704\n学生：好 那么\nAUDIENCE: OK, so it is--\n\n518\n00:42:16,800 --> 00:42:18,576\n教授：那是通过扩充词典实现的\nPROFESSOR: That's constructed by extend dictionary.\n\n519\n00:42:18,800 --> 00:42:28,544\n学生：所以根据递归性质 如果匹配过程产生并传递了失败\nAUDIENCE: So the recursive nature brings about the fact that if ever a failed gets passed out of any calling of match,\n\n520\n00:42:28,688 --> 00:42:30,304\n那么第一种情况将捕获它\nthen the first condition will pick it up--\n\n521\n00:42:30,400 --> 00:42:33,560\n教授：并且传播它 不做任何其它处理\nPROFESSOR: And just propagate it along without any further ado, right.\n\n522\n00:42:33,560 --> 00:42:34,830\n学生：哦 懂了\nAUDIENCE: Oh, right.\n\n523\n00:42:35,504 --> 00:42:37,360\n教授：这是传出失败最快的方法\nPROFESSOR: That's just the fastest way to get that failure out of there.\n\n524\n00:42:42,860 --> 00:42:43,600\n请讲\nYes.\n\n525\n00:42:43,840 --> 00:42:47,232\n学生：如果没有失败 那意味着我匹配了一个模式\nAUDIENCE: If I don't fail, that means that I've matched a pattern,\n\n526\n00:42:47,840 --> 00:42:53,008\n我会扩充词典并且传递表达式中的模式\nand I run the procedure extend dict and then pass in the pattern in the expression.\n\n527\n00:42:55,216 --> 00:42:58,430\n但是 代换并不是发生在这 对吧？\nBut the substitution will not be made at that point; is that right?\n\n528\n00:42:58,430 --> 00:42:59,030\n是吧？\nI'm just--\n\n529\n00:42:59,030 --> 00:42:59,460\n教授：你是对的\nPROFESSOR: No, no.\n\n530\n00:42:59,460 --> 00:43:02,400\n这里没有可供代换的骨架 因此不会发生代换\nThere's no substitution being there because there's no skeleton to be substituted in.\n\n531\n00:43:02,400 --> 00:43:03,060\n学生：好 那么\nAUDIENCE: Right. So\n\n532\n00:43:03,060 --> 00:43:07,160\n教授：我们这里所做的 是为后面的代换准备词典\nPROFESSOR: All you've got there is we're making up the dictionary for later substitution.\n\n533\n00:43:08,256 --> 00:43:12,432\n学生：词典的数据结构是什么呢？是有序对么？\nAUDIENCE: And what would the dictionary look like? Is it ordered pairs?\n\n534\n00:43:12,720 --> 00:43:15,960\n教授：那个 那个还没有告诉你\nPROFESSOR: Ahhhhh, That's--that's not told to you.\n\n535\n00:43:15,960 --> 00:43:16,896\n它还是一个抽象的东西\nWe're being abstract.\n\n536\n00:43:17,060 --> 00:43:17,560\n学生：哦\nAUDIENCE: OK.\n\n537\n00:43:17,560 --> 00:43:18,900\n教授：你为什么要知道呢?\nPROFESSOR: Why do you want to know?\n\n538\n00:43:18,900 --> 00:43:21,648\n它是一个函数 仅仅是一个函数\nWhat it is, it's a function. It's a function.\n\n539\n00:43:21,696 --> 00:43:22,330\n学生：我想知道它的原因是--\nAUDIENCE: Well, the reason I want to know is--\n\n540\n00:43:22,330 --> 00:43:24,176\n教授：这个抽象函数表现地像有序对\nPROFESSOR: A function abstractly is a set of ordered pairs.\n\n541\n00:43:25,120 --> 00:43:28,448\n它可以用一系列的表通过链接来实现\nIt could be implemented as a set of list pairs.\n\n542\n00:43:29,060 --> 00:43:32,430\n它也可以用一些酷炫的表机制来实现\nIt could be implemented as some fancy table mechanism.\n\n543\n00:43:32,560 --> 00:43:34,160\n它也可以实现为一个函数\nIt could be implemented as a function.\n\n544\n00:43:35,808 --> 00:43:37,408\n我可以把它写成一个函数\nAnd somehow, I'm building up a function.\n\n545\n00:43:39,024 --> 00:43:39,872\n但我不会告诉你具体细节\nBut I'm not telling you.\n\n546\n00:43:40,848 --> 00:43:43,088\n这是George的事情 由他来构建这个结构\nThat's up to George, who's going to build that later.\n\n547\n00:43:49,568 --> 00:43:52,064\n我知道 你特别想知道它的具体结构\nI know you really badly want to write concrete things.\n\n548\n00:43:52,360 --> 00:43:54,192\n但我不打算让你那么做\nI'm not going to let you do that.\n\n549\n00:43:54,430 --> 00:43:59,232\n学生：恩 最后一个问题 扩充到词典中的重要信息是什么?\nAUDIENCE: Well, let me at least ask, what is the important information there that's being passed to extend dict?\n\n550\n00:43:59,744 --> 00:44:02,080\n我想 可能是匹配发现的模式\nI want to pass the pattern I found--\n\n551\n00:44:02,736 --> 00:44:04,830\n教授：是的 那些与表达式相匹配的模式\nPROFESSOR: Yes. The pattern that's matched against the expression.\n\n552\n00:44:04,830 --> 00:44:09,300\n我们想要得到模式 只不过在本例中这些都是模式变量 对吧？\nYou want to have the pattern, which happens to be in those cases pattern variables, right?\n\n553\n00:44:09,856 --> 00:44:12,896\n这三种扩充词典的情况都是模式变量\nAll of those three cases for extend dict are pattern variables.\n\n554\n00:44:13,200 --> 00:44:13,504\n学生：恩\nAUDIENCE: Right.\n\n555\n00:44:14,480 --> 00:44:18,752\n教授：所以 在词典就有一个模式变量与一个值对应\nPROFESSOR: So you have a pattern variable that is to be given a value in a dictionary.\n\n556\n00:44:19,456 --> 00:44:22,112\n这个值是所匹配的表达式\nPROFESSOR: The value is the expression that it matched against.\n\n557\n00:44:23,312 --> 00:44:29,632\n词典就是遍历过程中记录下来的所有匹配\nThe dictionary is the set of things I've already figured out that I have memorized or learned.\n\n558\n00:44:30,540 --> 00:44:34,416\n我会以原有词典为基础 创建一本新词典\nAnd I am going to make a new dictionary, which is extended from the original one\n\n559\n00:44:35,120 --> 00:44:38,350\n新增的内容就是新发现的匹配\nby having that pattern variable have a value with the new dictionary.\n\n560\n00:44:39,984 --> 00:44:43,730\n学生：我不理解为什么不能在发现匹配后立即进行代换\nAUDIENCE: I guess what I don't understand is why can't the substitution be made right as soon as you find--\n\n561\n00:44:43,730 --> 00:44:44,800\n教授：哦 那时候还不能代换\nPROFESSOR: How do I know what I'm going to substitute?\n\n562\n00:44:44,816 --> 00:44:46,624\n因为我不知道骨架啊！\nI don't know anything about this skeleton.\n\n563\n00:44:47,584 --> 00:44:49,660\n模式和匹配器都是独立的单元\nThis pattern, this matcher is an independent unit.\n\n564\n00:44:49,660 --> 00:44:51,000\n学生：哦 我明白了\nAUDIENCE: Oh, I see. OK.\n\n565\n00:44:51,000 --> 00:44:51,500\n教授：懂了吧？\nPROFESSOR: Right?\n\n566\n00:44:51,500 --> 00:44:51,900\n学生：恩\nAUDIENCE: Yeah.\n\n567\n00:44:51,900 --> 00:44:57,230\n教授：我用这个匹配器进行匹配 如果匹配了就可以实例化\nPROFESSOR: I take the matcher. I apply the matcher. If it matches, then it was worth doing instantiation.\n\n568\n00:44:58,200 --> 00:44:59,500\n学生：知道了\nAUDIENCE: OK, good.\n\n569\n00:45:00,544 --> 00:45:03,888\n学生：您可以再求解一次黑板上的例子么\nAUDIENCE: Can you just do that answer again using that example on the board?\n\n570\n00:45:04,896 --> 00:45:06,930\n什么东西返回给了匹配器\nYou know, what you just passed back to the matcher.\n\n571\n00:45:06,930 --> 00:45:08,000\n教授：当然可以\nPROFESSOR: Oh yes. OK, yes.\n\n572\n00:45:08,260 --> 00:45:09,744\n来看这个例子\nYou're looking at this example.\n\n573\n00:45:10,672 --> 00:45:15,456\n在这里当我遍历这个结构的时候 我遇到了(? x)\nAt this point when I'm traversing this structure, I get to here: x.\n\n574\n00:45:16,672 --> 00:45:20,544\n我有一本词典 不过此时假设它是空的\nI have some dictionary, presumably an empty dictionary at this point if this is the whole expression.\n\n575\n00:45:21,560 --> 00:45:25,360\n一本空词典 然后我匹配到了x为3\nSo I have an empty dictionary, and I've matched x against 3.\n\n576\n00:45:26,620 --> 00:45:33,600\n从此以后 词典中就记录了 x与3匹配 对吧\nSo now, after this point,the dictionary contains x is 3, OK?\n\n577\n00:45:33,648 --> 00:45:36,096\n继续遍历 然后遇到(? y)\nNow, I continue walking along here. I see y.\n\n578\n00:45:36,896 --> 00:45:39,200\n它是一个特殊的x 这是模式变量x\nNow, this is a particular x, a pattern x.\n\n579\n00:45:39,792 --> 00:45:41,376\n我看到(? y) 模式变量y\nI see y, a pattern y.\n\n580\n00:45:42,176 --> 00:45:47,744\n词典说 模式变量y的值是符号x\nThe dictionary says, oh yes, the pattern y is the symbol x\n\n581\n00:45:48,992 --> 00:45:51,200\n因为这里已经匹配过了\nbecause I've gota match there.\n\n582\n00:45:52,432 --> 00:45:54,528\n所以此时 词典中包含两个条目\nSo the dictionary now contains at this point two entries.\n\n583\n00:45:55,456 --> 00:45:59,904\n模式变量x是数字3 模式变量y是表达式x\nThe pattern x is 3, and the pattern y is the expression x.\n\n584\n00:46:01,952 --> 00:46:04,112\n现在继续进行遍历\nNow, I get that, I can walk along further.\n\n585\n00:46:04,230 --> 00:46:07,456\n这里 模式变量y想要和4匹配\nI say, oh, pattern y also wants to be 4.\n\n586\n00:46:08,064 --> 00:46:10,656\n但是这个不可能 产生失败\nBut that isn't possible, producing a failure.\n\n587\n00:46:14,304 --> 00:46:15,488\n谢谢 下课\nThank you. Let's take a break.\n\n588\n00:46:16,760 --> 00:46:25,024\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n589\n00:46:25,070 --> 00:46:27,456\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n590\n00:46:27,472 --> 00:46:30,000\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n591\n00:46:48,190 --> 00:46:54,752\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n592\n00:46:55,200 --> 00:46:58,048\n模式匹配：基于规则的代换\nPattern-matching: Rule-based Substitution\n\n593\n00:47:02,384 --> 00:47:05,680\n这是大家首次看到如此庞大而复杂的程序\nOK, you're seeing your first very big and hairy program.\n\n594\n00:47:07,344 --> 00:47:09,904\n当然 本项课程的目的之一就在于\nNow, of course, one of the goals of this subject\n\n595\n00:47:09,900 --> 00:47:12,976\n是让大家可以读懂这么庞大的程序 而完全不用害怕它\nis to get you to be able to read something like this and not be afraid of it.\n\n596\n00:47:13,760 --> 00:47:16,336\n这个程序仅仅只有4页代码而已\nThis one's only about four pages of code.\n\n597\n00:47:17,080 --> 00:47:19,232\n课程结业后 我希望就算是50页长的程序\nBy the end of the subject, I hope a 50-page program\n\n598\n00:47:20,272 --> 00:47:21,800\n也吓不倒你们\nwill not look particularly frightening.\n\n599\n00:47:22,976 --> 00:47:28,208\n我不是说让你们“左耳朵进 右耳朵出”地读程序\nBut I don't expect-- and I don't want you to think that I expect you to be getting it as it's coming out.\n\n600\n00:47:29,200 --> 00:47:31,700\n你应该体会这个程序\nYou're supposed to feel the flavor of this, OK?\n\n601\n00:47:31,700 --> 00:47:34,830\n然后好好思考 因为它是一个很大的程序\nAnd then you're supposed to think about it because it is a big program.\n\n602\n00:47:35,328 --> 00:47:38,928\n在这个程序中有很多东西\nThere's a lot of stuff inside this program.\n\n603\n00:47:41,248 --> 00:47:46,032\n我已经介绍了我们正在实现的 -- 基于规则代换的模式匹配语言\nNow, I've told you about the language we're implementing, the pattern match substitution language.\n\n604\n00:47:46,816 --> 00:47:47,648\n给你们看了一些规则\nI showed you some rules.\n\n605\n00:47:48,360 --> 00:47:51,248\n我已经告诉大家匹配和实例化\nAnd I've told you about matching and instantiation,\n\n606\n00:47:51,552 --> 00:47:53,320\n它们是使规则生效的“阴阳两极”\nwhich are the two halves of how a rule works.\n\n607\n00:47:54,240 --> 00:47:56,352\n现在我们需要理解控制结构\nNow we have to understand the control structure\n\n608\n00:47:56,864 --> 00:48:00,320\n就是这些规则是如何被用在表达式上\nby which the rules are applied to the expressions\n\n609\n00:48:01,088 --> 00:48:03,840\n来指导代数化简的\nso as to do algebraic simplification.\n\n610\n00:48:06,928 --> 00:48:09,584\n这也是非常复杂的\nNow, that's also a big complicated mess.\n\n611\n00:48:12,096 --> 00:48:19,488\n其中有很多循环 相互交织 错综复杂\nThe problem is that there is a variety of interlocking, interwoven loops, if you will, involved in this.\n\n612\n00:48:20,240 --> 00:48:26,992\n一方面 我不得不检查 待化简表达式的每个子表达式\nFor one thing, I have to apply-- I have to examine every subexpression of my expression that I'm trying to simplify.\n\n613\n00:48:29,008 --> 00:48:29,930\n我们已经讲过了\nThat we know how to do.\n\n614\n00:48:29,930 --> 00:48:36,240\n这是在car、cdr部分做某种树形递归\nIt's a car cdr recursion of some sort, or something like that, and some sort of tree walk.\n\n615\n00:48:37,440 --> 00:48:38,592\n就是那样\nAnd that's going to be happening.\n\n616\n00:48:38,840 --> 00:48:42,464\n现在 在我每个遍历到的结点上\nNow, for every such place, every node that I get to\n\n617\n00:48:43,472 --> 00:48:48,760\n也就是我想要化简的（子）表达式\nin doing my traversal of the expression I'm trying to simplify,\n\n618\n00:48:49,200 --> 00:48:51,072\n我需要应用所有的规则\nI want to apply all of the rules.\n\n619\n00:48:53,424 --> 00:48:55,088\n每个规则都需要检查每个节点\nEvery rule is going to look at every node.\n\n620\n00:48:56,000 --> 00:48:57,920\n我一直在这些规则中打转（循环）\nI'm going to rotate the rules around.\n\n621\n00:49:01,664 --> 00:49:05,488\n一个规则可能匹配 也可能不匹配\nNow, either a rule will or will not match.\n\n622\n00:49:07,504 --> 00:49:10,624\n如果规则不匹配 那我就不关心了\nIf the rule does not match, then it's not very interesting.\n\n623\n00:49:12,288 --> 00:49:19,344\n如果规则匹配了 我就在那个结点用另一个表达式替换这个表达式\nIf the rule does match, then I'm going to replace that node in the expression by an alternate expression.\n\n624\n00:49:20,080 --> 00:49:22,896\n实际上 我创建了一个新表达式 它包含\nI'm actually going to make a new expression, which contains--\n\n625\n00:49:23,550 --> 00:49:28,656\n它包含了所有的东西 新的值代换入骨架后的结果\neverything contains that new value, the result of substituting into the skeleton,\n\n626\n00:49:29,216 --> 00:49:31,920\n也就是 在该层次上 把规则所对应的骨架实例化的结果\ninstantiating the skeleton for that rule at this level.\n\n627\n00:49:32,720 --> 00:49:37,376\n但我并不知道我所实例化出来的东西 是否是简化形式\nBut no one knows whether that thing that I instantiated there is in simplified form.\n\n628\n00:49:38,752 --> 00:49:43,824\n所以我要对我刚刚构建好的东西调用化简器来简化它\nSo we're going to have to simplify that, somehow to call the simplifier on the thing that I just constructed.\n\n629\n00:49:46,128 --> 00:49:50,368\n完成后 我就可以将其构建进我想要的表达式中作为答案\nAnd then when that's done, then I sort of can build that into the expression I want as my answer.\n\n630\n00:49:51,808 --> 00:49:57,456\n这里的基本思想是 我们定义一个 “废料进-废料出”的化简器\nNow, there is a basic idea here, which I will call a garbage- in, garbage-out simplifier.\n\n631\n00:50:01,472 --> 00:50:02,752\n它是一种递归调用的化简器\nIt's a kind of recursive simplifier.\n\n632\n00:50:03,584 --> 00:50:08,848\n化简方法是：基本对象 比如变量就是最简形式的了\nAnd what happens is the way simplify something is that simple objects like variables are simple.\n\n633\n00:50:10,784 --> 00:50:13,280\n复合对象 -- 呃 我也不知道\nCompound objects, well, I don't know.\n\n634\n00:50:14,096 --> 00:50:16,560\n而我要从简单的对象入手\nWhat I'm going to do is I'm going to build up from simple objects,\n\n635\n00:50:16,864 --> 00:50:21,232\n通过假设它们都是由小块的基本对象组成的\ntrying to make simple things by assuming that the pieces they're made out of are simple.\n\n636\n00:50:24,608 --> 00:50:25,616\n这就是思路\nThat's what's happening here.\n\n637\n00:50:27,824 --> 00:50:33,120\n现在如果我们看第一张投影\nWell, now, if we look at the first slide-- no, overhead, overhead.\n\n638\n00:50:33,888 --> 00:50:37,136\n我们看到一个非常复杂的程序 就像我们之前看到的匹配器一样\nIf we look at the overhead, we see a very complicated program like we saw before for the matcher,\n\n639\n00:50:37,536 --> 00:50:39,950\n它太复杂了 没有必要仔细阅读它\nso complicated that you can't read it like that.\n\n640\n00:50:41,920 --> 00:50:43,616\n我只想让大家感受一下它的轮廓\nI just want you to get the feel of the shape of it,\n\n641\n00:50:44,448 --> 00:50:50,016\n也就是这个程序里面有很多子程序\nand the shape of it is that this program has various subprograms in it.\n\n642\n00:50:52,110 --> 00:50:57,568\n这部分用于遍历表达式\nOne of them--this part is the part for traversing the expression,\n\n643\n00:50:58,976 --> 00:51:01,360\n这部分用于尝试规则\nand this part is the part for trying rules.\n\n644\n00:51:02,528 --> 00:51:05,600\n当然 我们也可以看看细节\nNow, of course, we can look at that in some more detail.\n\n645\n00:51:06,896 --> 00:51:11,808\n来看第一张幻灯片\nLet's look at--let's look at the first transparency, right?\n\n646\n00:51:13,408 --> 00:51:17,360\n化简器由数个部分组成\nThe simplifier is made out of several parts.\n\n647\n00:51:17,968 --> 00:51:22,928\n回想一下 化简器接收一系列的规则\nNow, remember at the very beginning, the simplifier is the thing which takes a rules-- a set of rules\n\n648\n00:51:23,920 --> 00:51:27,200\n并生成一个使用该规则进行化简的程序\nand produces a program which will simplify it relative to them.\n\n649\n00:51:30,048 --> 00:51:32,608\n化简器在这里定义\nSo here we have our simplifier.\n\n650\n00:51:33,488 --> 00:51:34,816\n接受一个规则集合\nIt takes a rule set.\n\n651\n00:51:36,160 --> 00:51:38,688\n在the-rules被定义的上下文中\nAnd in the context where that rule set is defined,\n\n652\n00:51:39,248 --> 00:51:41,480\n还定义了很多其它东西\nthere are various other definitions that are done here.\n\n653\n00:51:42,336 --> 00:51:46,208\n而simplifier过程的返回结果则是\nAnd then the result of this simplifier procedure is,\n\n654\n00:51:46,410 --> 00:51:50,800\n是一个已经定义好的过程 -- simplify-exp\nin fact, one of the procedures that was defined. Simplify-exp.\n\n655\n00:51:52,464 --> 00:51:57,712\n调用 (simplifier the-rules) 的返回值是\nWhat I'm returning as the value of calling the simplifier on a set of rules\n\n656\n00:51:58,170 --> 00:52:03,216\n返回值是一个过程 是在该上下文中定义的simplify-exp过程\nis a procedure the simplify exp procedure, which is defined in that context,\n\n657\n00:52:05,232 --> 00:52:08,832\n这是一个利用这些给定规则进行化简的过程\nwhich is a simplification procedure appropriate for using those set of rules.\n\n658\n00:52:15,040 --> 00:52:15,968\n定义就是这样的\nThat's what I have there.\n\n659\n00:52:17,450 --> 00:52:21,792\n这些过程的前两个 这个和这个\nNow, the first two of these procedures, this one and this one,\n\n660\n00:52:22,480 --> 00:52:25,744\n它们一起 递归地遍历一个表达式\nare together going to be the recursive traversal of an expression.\n\n661\n00:52:26,970 --> 00:52:30,208\n这个是任何表达式的通用化简方法\nThis one is the general simplification for any expression,\n\n662\n00:52:30,944 --> 00:52:33,230\n而这个过程用于化简表达式的子部分\nand this is the thing which simplifies a list of parts of an expression.\n\n663\n00:52:35,536 --> 00:52:36,080\n没别的了\nNothing more.\n\n664\n00:52:37,040 --> 00:52:39,904\n每个过程中 我们会做些复杂操作 包括尝试这些规则\nFor each of those, we're going to do something complicated, which involves trying the rules.\n\n665\n00:52:40,320 --> 00:52:41,712\n现在 我们看看这些过程\nNow, we should look at the various parts.\n\n666\n00:52:45,760 --> 00:52:48,080\n我们先来讨论一下表达式的递归遍历\nWell let's look first at the recursive traversal of an expression.\n\n667\n00:52:48,576 --> 00:52:51,680\n这是用一种很简单的方法完成的\nAnd this is done in a sort of simple way.\n\n668\n00:52:54,288 --> 00:52:57,936\n这是一个小型的、嵌套的递归过程\nThis is a little nest of recursive procedures.\n\n669\n00:52:59,424 --> 00:53:01,776\n这里有两个过程 ---\nAnd what we have here are two procedures--\n\n670\n00:53:02,590 --> 00:53:05,200\n一个是对整个表达式化简\none for simplifying an expression,\n\n671\n00:53:06,112 --> 00:53:08,160\n另一个是对表达式的某部分化简\nand one for simplifying parts of an expression.\n\n672\n00:53:09,440 --> 00:53:10,976\n它们的原理都很简单\nAnd the way this works is very simple.\n\n673\n00:53:12,128 --> 00:53:16,864\n如果我想要化简的表达式是复合表达式\nIf the expression I'm trying to simplify is a compound expression,\n\n674\n00:53:17,040 --> 00:53:18,320\n那么就对每一个部分进行化简\nI'm going to simplify all the parts of it.\n\n675\n00:53:19,950 --> 00:53:22,320\n调用simplify-parts这个过程\nAnd that's calling--that procedure, simplify parts,\n\n676\n00:53:22,336 --> 00:53:25,740\n会构造一个新的表达式 其中各个部分都是化简过的\nis going to make up a new expression with all the parts simplified,\n\n677\n00:53:26,000 --> 00:53:28,640\n我会在这里尝试那些应用规则\nwhich I'm then going to try the rules on over here.\n\n678\n00:53:30,860 --> 00:53:34,224\n如果表达式不是复合的 而是一些简单的表达式\nIf it turns out that the expression is not compound, if it's simple,\n\n679\n00:53:34,768 --> 00:53:37,130\n比如说是符号 或者'pi\nlike just a symbol or something like pi,\n\n680\n00:53:38,160 --> 00:53:39,792\n无论如何 我都需要尝试应用这些规则\nthen in any case, I'm going to try the rules on it\n\n681\n00:53:40,032 --> 00:53:47,560\n因为 因为可能有将pi扩展成3.14159265358979....这样的规则\nbecause it might be that I want in my set of rules to expand pi to 3.14159265358979,dot, dot, dot.\n\n682\n00:53:48,464 --> 00:53:49,088\n也许我不会这样做\nBut I may not.\n\n683\n00:53:50,112 --> 00:53:51,520\n但是没有理由不这样做\nBut there is no reason not to do it.\n\n684\n00:53:52,752 --> 00:53:57,536\n现在如果我对表达式的各部分化简 那就很简单了\nNow, if I want to simplify the parts, well, that's easy too.\n\n685\n00:53:58,990 --> 00:54:02,880\n要么表达式是空的 它没有更多的部分了\nEither the expression is an empty one, there's no more parts,\n\n686\n00:54:03,712 --> 00:54:05,080\n这种情况我返回一个空表达式\nin which case I have the empty expression.\n\n687\n00:54:05,728 --> 00:54:10,528\n否则 我用cons构建一个新的表达式\nOtherwise, I'm going to make a new expression by cons,\n\n688\n00:54:11,216 --> 00:54:14,272\n新表达式的car部分是原表达式car的化简结果\nwhich is the result of simplifying the first part of the expression, the car,\n\n689\n00:54:15,424 --> 00:54:17,392\n然后化简表达式的其它其他部分作为新表达式的cdr部分\nand simplifying the rest of the expression, which is the cdr.\n\n690\n00:54:21,088 --> 00:54:23,888\n我用这种方式向大家展示这些的原因是\nNow, the reason why I'm showing you this sort of stuff this way\n\n691\n00:54:24,880 --> 00:54:30,128\n我想让大家感受到 这些不同模式在编程时非常重要\nis because I want you get the feeling for the various patterns that are very important when writing programs.\n\n692\n00:54:32,208 --> 00:54:34,000\n这段程序我可以换种写法\nAnd this could be written a different way.\n\n693\n00:54:34,000 --> 00:54:36,992\n还有一种化简表达式的方法\nThere's another way to write simplified expressions so there would be only one of them.\n\n694\n00:54:37,728 --> 00:54:39,630\n这仅仅是一个小程序\nThere would only be one little procedure here.\n\n695\n00:54:39,630 --> 00:54:42,368\n我把它写到黑板上 让大家感受一下\nLet me just write that on the blackboard to give you a feeling for that.\n\n696\n00:54:49,712 --> 00:54:51,904\n你可以用这种惯用法来写程序\nThis is in another idiom, if you will.\n\n697\n00:54:59,300 --> 00:55:03,136\n那么 如何化简表达式exp呢？\nTo simplify an expression called exp, what am I going to do?\n\n698\n00:55:03,216 --> 00:55:10,144\n在以下几种情况下 调用try-rules\nI'm going to try the rules on the following situation.\n\n699\n00:55:11,120 --> 00:55:15,728\n就像之前一样 如果表达式是复合的\nIf-- on the following expression-- compound, just like we had before.\n\n700\n00:55:21,520 --> 00:55:24,272\n如果是复合的 我要怎么做呢?\nIf the expression is compound, well, what am I going to do?\n\n701\n00:55:24,530 --> 00:55:25,408\n我要化简它的每个部分\nI'm going to simplify all the parts.\n\n702\n00:55:26,010 --> 00:55:27,808\n但是我已经有对cdr部分递归的过程了\nBut I already have a cdr recursion,\n\n703\n00:55:30,256 --> 00:55:33,180\n一个被封装成高阶过程的通用模式\ncommon pattern of usage, which has been captured as a high-order procedure.\n\n704\n00:55:34,096 --> 00:55:34,464\n也就是map过程\nIt's called map.\n\n705\n00:55:36,080 --> 00:55:36,880\n我在这里写出来\nSo I'll just write that here.\n\n706\n00:55:37,160 --> 00:55:48,032\n(map simplify-exp exp)\nMap simplify the expression, all the parts of the expression.\n\n707\n00:55:49,008 --> 00:55:54,592\n这是说 把simplify-exp这个过程应用在表达式的每个部分\nThis says apply the simplification operation, which is this one, every part of the expression,\n\n708\n00:55:55,344 --> 00:55:57,344\n然后把结果用cons组合成表\nand then that cons those up into a list.\n\n709\n00:56:00,920 --> 00:56:04,384\n所以表中的每个元素都是化简过的\nIt's every element of the list which the expression is assumed to be made out of,\n\n710\n00:56:05,456 --> 00:56:08,230\n不是复合表达式的话 就不用化简了\nand otherwise, I have the expression.\n\n711\n00:56:09,050 --> 00:56:12,368\n所以不需要再写一个辅助函数来化简各个部分\nSo I don't need the helper procedure, simplify parts,\n\n712\n00:56:12,640 --> 00:56:13,480\n这句代码就够了\nbecause that's really this.\n\n713\n00:56:15,472 --> 00:56:17,056\n所以有时候可以这样写\nSo sometimes, you just write it this way.\n\n714\n00:56:17,840 --> 00:56:18,704\n这个无关紧要\nIt doesn't matter very much.\n\n715\n00:56:21,168 --> 00:56:26,272\n好现在看一下 -- 如何尝试规则\nWell, now let's take a look at-- let's just look at how you try rules.\n\n716\n00:56:27,700 --> 00:56:31,600\n这里 幻灯片上有一堆复杂的东西\nIf you look at this slide, we see this is a complicated mess also.\n\n717\n00:56:33,680 --> 00:56:35,280\n我要尝试对一个表达式施用规则\nI'm trying rules on an expression.\n\n718\n00:56:36,368 --> 00:56:39,968\n我现在尝试的表达式是最初表达式的子表达式\nIt turns out the expression I'm trying it on is some subexpression now of the expression I started with.\n\n719\n00:56:40,430 --> 00:56:43,888\n这是因为我之前特意安排要求遍历所有子表达式\nBecause the thing I just arranged allowed us to try every subexpression.\n\n720\n00:56:46,112 --> 00:56:51,900\n所以这里的exp 就是最初表达式的子表达式\nSo now here we're taking in a subexpression of the expression we started with. That's what this is.\n\n721\n00:56:52,496 --> 00:56:57,712\n这里我们定义一个scan的过程 它用来尝试每一个规则\nAnd what we're going to define here is a procedure called scan, which is going to try every rule.\n\n722\n00:56:58,720 --> 00:57:00,336\n我们会在整个规则中扫描\nAnd we're going to start it up on the whole set of rules.\n\n723\n00:57:01,920 --> 00:57:07,776\n它会通过不断取cdr部分来遍历整个规则 查找一条规则来施用\nThis is going to go cdr-ing down the rules, if you will, looking for a rule to apply.\n\n724\n00:57:09,376 --> 00:57:11,968\n当找到一条规则 它的任务就完成了\nAnd when it finds one, it'll do the job.\n\n725\n00:57:14,096 --> 00:57:16,416\n我们来看一下try-rules是如何工作的\nWell, let's take a look at how try rules works.\n\n726\n00:57:17,744 --> 00:57:21,024\n非常简单：就是顺序地扫描规则表\nIt's very simple: the scan rules. Scan rules, the way of scanning.\n\n727\n00:57:21,968 --> 00:57:23,260\n它 真的简单吗？\nWell, is it so simple?\n\n728\n00:57:23,260 --> 00:57:24,512\n不 这是个很庞大的程序\nIt's a big program, of course.\n\n729\n00:57:25,552 --> 00:57:28,576\n接收的参数是一系列的规则--它们是整个规则表的子表\nWe take a bunch of rules, which is a sublist of the list of rules.\n\n730\n00:57:30,752 --> 00:57:35,136\n我们已经查找了其中的一些 但它们都不符合 所以试试剩下的\nWe've tried some of them already, and they've not been appropriate, so we get to some here.\n\n731\n00:57:35,872 --> 00:57:36,304\n尝试下一条\nnext one.\n\n732\n00:57:36,400 --> 00:57:37,632\n如果所有规则都尝试完了\nIf there are no more rules,\n\n733\n00:57:37,904 --> 00:57:40,848\n那么 我就不能再对这个表达式做什么了 它已经是最简了\nwell then, there's nothing I can do with this expression, and it's simplified.\n\n734\n00:57:42,352 --> 00:57:47,264\n然而 如果还有规则需要扫描\nHowever, if it turns out that there are still rules to be done,\n\n735\n00:57:48,010 --> 00:57:51,584\n那么从一个空的词典开始\nthen let's match the pattern of the first rule\n\n736\n00:57:52,208 --> 00:57:55,408\n用规则表中的第一条规则对表达式进行模式匹配\nagainst the expression using the empty dictionary to start with\n\n737\n00:57:57,072 --> 00:57:58,840\n将得到的结果作为新的词典\nand use that as the dictionary.\n\n738\n00:58:00,320 --> 00:58:03,744\n如果失败了 就尝试剩余规则\nIf that happens to be a failure, try the rest of the rules.\n\n739\n00:58:06,688 --> 00:58:07,520\n这句代码就是这个意思\nThat's all it says here.\n\n740\n00:58:08,528 --> 00:58:10,336\n也就是说 丢弃那条规则\nHow it says, it says discard that rule.\n\n741\n00:58:11,104 --> 00:58:15,056\n成功的话 我将取出第一条规则对应的骨架\nOtherwise, well, I'm going to get the skeleton of the first rule,\n\n742\n00:58:15,344 --> 00:58:17,400\n利用得到的词典 来将其实例化\ninstantiate that relative to the dictionary,\n\n743\n00:58:17,936 --> 00:58:20,800\n然后对结果化简 就得到了我想要的表达式\nand simplify the result, and that's the expression I want.\n\n744\n00:58:24,200 --> 00:58:25,968\n虽然这是一个复杂的程序\nSo although that was a complicated program,\n\n745\n00:58:26,256 --> 00:58:28,720\n但是每个复杂程序都是由许多简单部分组成的\nevery complicated program is made out of a lot of simple pieces.\n\n746\n00:58:29,776 --> 00:58:33,120\n这里的递归模式非常复杂\nNow, the pattern of recursions here is very complicated.\n\n747\n00:58:34,784 --> 00:58:36,528\n最重要的事情就是：不要去思考它\nAnd one of the most important things is not to think about that.\n\n748\n00:58:38,670 --> 00:58:41,808\n如果去思考它的实际行为\nIf you try to think about the actual pattern by which this does something,\n\n749\n00:58:42,064 --> 00:58:42,976\n大家就会迷惑\nyou're going to get very confused.\n\n750\n00:58:45,312 --> 00:58:45,712\n就算是我也会\nI would.\n\n751\n00:58:47,040 --> 00:58:50,176\n没关系 可以多加练习\nThis is not a matter. you can do this with practice.\n\n752\n00:58:51,520 --> 00:58:52,464\n这些模式非常难\nThese patterns are hard.\n\n753\n00:58:54,176 --> 00:58:55,424\n但是大家不用考虑它\nBut you don't have to think about it.\n\n754\n00:58:55,830 --> 00:58:59,728\n关键点就是 好的编程或设计方法需要\nThe key to this-- it's very good programming and very good design--\n\n755\n00:58:59,744 --> 00:59:00,976\n知道什么是不需要考虑的\nis to know what not to think about.\n\n756\n00:59:03,056 --> 00:59:06,064\n回到这张幻灯片上\nThe fact is, going back to this slide,\n\n757\n00:59:06,928 --> 00:59:08,016\n我不需要考虑它\nI don't have to think about it\n\n758\n00:59:08,544 --> 00:59:13,830\n是因为我规定了exp化简后的结果是什么样子\nbecause I have specifications in my mind for what simplify x does.\n\n759\n00:59:14,000 --> 00:59:15,248\n我不需要知道它是如何做的\nI don't have to know how it does it.\n\n760\n00:59:17,088 --> 00:59:21,248\n它也许是像我们这里 又是scan 又是try-rule\nAnd it may, in fact, call scan somehow through try rules, which it does.\n\n761\n00:59:22,240 --> 00:59:24,096\n又或者在这里调用另一个递归程序\nAnd somehow, I've got another recursion going on here.\n\n762\n00:59:24,330 --> 00:59:25,696\n根据“按愿望思维” 因为我知道simplify-exp\nBut since I know that simplify exp\n\n763\n00:59:26,848 --> 00:59:30,400\n它会返回exp化简后的结果\nis assumed by wishful thinking to produce the simplified result,\n\n764\n00:59:31,616 --> 00:59:32,992\n那么我就不需要再考虑它的具体实现了\nthen I don't have to think about it anymore.\n\n765\n00:59:33,430 --> 00:59:34,830\n我直接使用它\nI've used it.\n\n766\n00:59:35,072 --> 00:59:36,430\n我合情合理地使用它\nI've used it in a reasonable way.\n\n767\n00:59:36,430 --> 00:59:37,456\n就会得到正确的结果\nI will get a reasonable answer.\n\n768\n00:59:39,952 --> 00:59:42,576\n我们必须学会这种程序设计方法 -- 学会放弃\nAnd you have to learn how to program that way-- with abandon.\n\n769\n00:59:47,568 --> 00:59:49,056\n这里还有一点剩余\nWell, there's very little left of this thing.\n\n770\n00:59:50,400 --> 00:59:54,464\n这里还有一些词典方面的细节\nAll there is left is a few details associated with what a dictionary is.\n\n771\n00:59:55,080 --> 00:59:58,320\n你们想知道到底词典是什么\nAnd those of you who've been itching to know what a dictionary is,\n\n772\n00:59:58,704 --> 01:00:01,820\n但是我会跳过它 无可奉告\nwell, I will flip it up and not tell you anything about it.\n\n773\n01:00:04,144 --> 01:00:05,200\n词典很简单\nDictionaries are easy.\n\n774\n01:00:06,016 --> 01:00:09,840\n它是用一种被称为关联表的东西来表示的\nIt's represented in terms of something else called an A list,\n\n775\n01:00:10,656 --> 01:00:16,048\n这是一种特殊使用模式 用来在线性表中存放二维表\nwhich is a particular pattern of usage for making tables in lists.\n\n776\n01:00:16,500 --> 01:00:20,176\n它们很简单 由序对构成 之前已经有同学问过了\nThey're easy. They're made out of pairs, as was asked a bit ago.\n\n777\n01:00:21,210 --> 01:00:24,624\n有个特殊的过程叫做assq 用来处理这些东西\nAnd there are special procedures for dealing with such things called assq,\n\n778\n01:00:24,944 --> 01:00:26,360\n手册里面有\nand you can find them in manuals.\n\n779\n01:00:27,040 --> 01:00:28,592\n这个都无关紧要\nI'm not terribly excited about it.\n\n780\n01:00:28,830 --> 01:00:31,216\n重要的是如何扩充词典\nThe only interesting thing here in extend dictionary\n\n781\n01:00:31,480 --> 01:00:36,944\n要用一个模式、模式对应的数据、一本旧词典来扩充\nis I have to extend the dictionary with a pattern, a datum, and a dictionary.\n\n782\n01:00:37,424 --> 01:00:42,384\n这个模式pat 实际上是一个模式变量\nI wish that, this pattern is, in fact, at this point a pattern variable.\n\n783\n01:00:43,744 --> 01:00:47,536\n我要做什么呢？我先从模式中取出模式变量的名字\nAnd what do I want to do? I want to pull out the name of that pattern variable\n\n784\n01:00:48,160 --> 01:00:49,424\n把它赋给变量name\nthe pattern variable name,\n\n785\n01:00:50,448 --> 01:00:53,712\n然后我按照这个名字在词典中查找是否有对应的值\nand I'm going to look up in the dictionary and see if it already has a value.\n\n786\n01:00:53,792 --> 01:00:56,416\n如果没有 就将这对新的模式-值加入到词典中\nIf not, I'm going to add a new one in.\n\n787\n01:00:56,928 --> 01:00:59,232\n如果已经存在一个这样名字的词条 并且有值\nIf it does have one, if it has a value,\n\n788\n01:00:59,600 --> 01:01:03,184\n那dat的值最好跟已经存储的值相等\nthen it had better be equal to the one that was already stored away.\n\n789\n01:01:03,888 --> 01:01:06,544\n这是我心目中期待的情况\nAnd if that's the case, the dictionary is what I expected it to be.\n\n790\n01:01:06,896 --> 01:01:09,152\n否则 置失败\nOtherwise, I fail.\n\n791\n01:01:12,080 --> 01:01:12,896\n所以它也很简单\nSo that's easy, too.\n\n792\n01:01:13,664 --> 01:01:16,688\n打开任何一个程序 你会发现它们都是由数个个小部分组成\nIf you open up any program, you're going to find inside of it lots of little pieces,\n\n793\n01:01:17,184 --> 01:01:18,304\n许多简单的小部分\nall of which are easy.\n\n794\n01:01:20,048 --> 01:01:21,296\n我想 到目前为止\nSo at this point, I suppose,\n\n795\n01:01:21,600 --> 01:01:25,680\n我已经告诉给你们价值百万的信息了\nI've just told you some million-dollar valuable information.\n\n796\n01:01:28,416 --> 01:01:30,960\n我想这个程序几乎已经讲完了\nAnd I suppose at this point we're pretty much done with this program.\n\n797\n01:01:31,856 --> 01:01:32,720\n有什么问题么？\nI'd like to ask about questions.\n\n798\n01:01:34,272 --> 01:01:38,160\n学生：你描述一下 化简后的表达式的规范么？\nAUDIENCE: Yes, can you give me the words that describe the specification for a simplified expression?\n\n799\n01:01:38,720 --> 01:01:39,024\n教授：好的\nPROFESSOR: Sure.\n\n800\n01:01:39,856 --> 01:01:44,336\nsimplify-exp接收一个表达式 返回一个化简后的表达式\nA simplified expression takes an expression and produces a simplified expression.\n\n801\n01:01:45,280 --> 01:01:45,776\n就是这样了\nThat's it, OK?\n\n802\n01:01:48,112 --> 01:01:50,272\n它的工作方式很简单\nHow it does it is very easy.\n\n803\n01:01:51,600 --> 01:01:56,096\n对于复合表达式 先化简各部分后 再尝试化简整体\nIn compound expressions, all the pieces are simplified, and then the rules are tried on the result.\n\n804\n01:01:56,896 --> 01:01:58,496\n原子表达式 就直接代规则化简\nAnd for simple expressions, you just try all the rules.\n\n805\n01:01:59,520 --> 01:02:02,112\n学生：是这些规则把表达式化简了么?\nAUDIENCE: So an expression is simplified by virtue of the rules?\n\n806\n01:02:02,768 --> 01:02:03,584\n教授：当然\nPROFESSOR: That's, of course, true.\n\n807\n01:02:03,760 --> 01:02:03,904\n学生：好\nAUDIENCE: Right.\n\n808\n01:02:04,064 --> 01:02:07,136\n教授：它们像你在这里看到的一样化简表达式\nPROFESSOR: And the way this works is that simplified expression, as you see here,\n\n809\n01:02:08,352 --> 01:02:11,648\n它先把表达式划分为小块\nwhat it does is it breaks the expression down into the smallest pieces,\n\n810\n01:02:12,608 --> 01:02:17,296\n在化简器中使用这些规则 自下而上化简并构造表达式\nsimplifies building up from the bottom using the rules to be the simplifier,\n\n811\n01:02:18,304 --> 01:02:22,480\n处理它们 构造一个新的表达式作为结果\nto do the manipulations, and constructs a new expression as the result.\n\n812\n01:02:24,288 --> 01:02:29,440\n最后再尝试调用这些规则化简\nEventually, one of things you see is that the rules themselves, the try rules,\n\n813\n01:02:29,700 --> 01:02:35,504\n当匹配的结果发生变化时 -- 就调用simplify-exp化简它\ncall a simplified expression on the results when it changes something, the results of a match.\n\n814\n01:02:35,800 --> 01:02:40,640\n哦 不对是 骨架的实例化结果发生改变时\nI'm sorry, the results of instantiation of a skeleton for a rule that has matched.\n\n815\n01:02:42,000 --> 01:02:47,360\n所以 规范就是 任何传入的表达式通过这些规则生成化简后的表达式\nSo the spec of a simplified expression is that any expression you put into it comes out simplified according to those rules.\n\n816\n01:02:49,840 --> 01:02:50,768\n谢谢大家 下课\nThank you. Let's take a break.\n\n"
  },
  {
    "path": "SrtCN/lec4b.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:02,256\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:02,320 --> 00:00:03,536\n翻译&&时间轴：刘殊君（rtmagic）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:03,552 --> 00:00:04,240\n特别感谢：裘宗燕教授\n\n4\n00:00:04,330 --> 00:00:10,352\n计算机程序的构造和解释\n\n5\n00:00:11,400 --> 00:00:16,500\n通用运算符\nGeneric Operators\n\n6\n00:00:20,180 --> 00:00:21,840\n教授：到目前为止 我们已经进行了很多\nPROFESSOR: So far in this course we've been talking\n\n7\n00:00:21,840 --> 00:00:23,780\n关于数据抽象的讨论\na lot about data abstraction.\n\n8\n00:00:23,780 --> 00:00:27,150\n关键理念就是在构造系统的时候\nAnd remember the idea is that we build systems\n\n9\n00:00:27,740 --> 00:00:32,560\n在其中加入水平的抽象屏障 这些抽象屏障\nthat have these horizontal barriers in them, these abstraction barriers\n\n10\n00:00:33,420 --> 00:00:39,210\n把你使用一个数据对象的方式\nthat separate use, the way you might use some data object,\n\n11\n00:00:39,930 --> 00:00:41,180\n和表示它的方式区分开来\nfrom the way you might represent it.\n\n12\n00:00:49,400 --> 00:00:52,030\n或者可以这样理解它 在上层有一个老板\nOr another way to think of that is up here you have the boss\n\n13\n00:00:52,110 --> 00:00:55,500\n想要调用某种数据对象\nwho's going to be using some sort of data object.\n\n14\n00:00:57,110 --> 00:01:02,310\n而在下层 George负责它的具体实现\nAnd down here is George who's implemented it.\n\n15\n00:01:02,310 --> 00:01:05,420\n这种把使用与表示分离的想法\nNow this notion of separating use from representation\n\n16\n00:01:05,440 --> 00:01:09,760\n可以让你分开考虑这两个问题\nso you can think about these two problems separately\n\n17\n00:01:10,600 --> 00:01:14,760\n这是一种非常强大的编程的方法论 -- 数据抽象\nis a very,very powerful programming methodology, data abstraction.\n\n18\n00:01:15,930 --> 00:01:18,810\n但另一方面 数据抽象在那些真正复杂的系统上\nOn the other hand, it's not really sufficient\n\n19\n00:01:19,560 --> 00:01:21,840\n并不是很有效\nfor really complex systems.\n\n20\n00:01:22,960 --> 00:01:27,648\n这个问题就出在George这里\nAnd the problem with this is George.\n\n21\n00:01:28,640 --> 00:01:32,090\n或者说 实际上 问题就在于\nOr actually, the problem is that\n\n22\n00:01:32,090 --> 00:01:32,780\n现在有太多的George\nthere are a lot of Georges.\n\n23\n00:01:34,630 --> 00:01:35,390\n具体地说\nLet's be concrete.\n\n24\n00:01:35,390 --> 00:01:39,180\n假设现在有George和Martha两个人\nLet's suppose there is George,and there's also Martha.\n\n25\n00:01:41,190 --> 00:01:44,220\n他们都是这个系统的开发人员\nOK, now George and Martha are both working on this system,\n\n26\n00:01:46,040 --> 00:01:47,290\n都在设计数据的表示方法\nboth designing representations,\n\n27\n00:01:48,410 --> 00:01:50,670\n而且他们完全合不来\nand absolutely are incompatible.\n\n28\n00:01:51,750 --> 00:01:53,620\n他们不会合作开发同一种表示方法\nThey wouldn't cooperate on a representation\n\n29\n00:01:54,010 --> 00:01:55,340\n永远也不会\nunder any circumstances.\n\n30\n00:01:57,480 --> 00:01:59,720\n现在的问题是 假设你想要这样一个系统\nAnd the problem is you would like to have some system\n\n31\n00:02:00,060 --> 00:02:02,600\n在这个系统中George和Martha都为它设计了数据表示方法\nwhere both George and Martha are designing representations,\n\n32\n00:02:03,820 --> 00:02:08,080\n但是如果你在高于这个抽象屏障的层面思考\nand, yet, if you're above this abstraction barrier\n\n33\n00:02:09,400 --> 00:02:11,040\n你就不用去操心这些事情\nyou don't want to have to worry about that,\n\n34\n00:02:11,660 --> 00:02:14,180\n不用操心 某个东西是到底是George做的还是Martha做的\nwhether something is done by George or by Martha.\n\n35\n00:02:14,180 --> 00:02:15,430\n同时你也不想让George和Martha\nAnd you don't want George and Martha to\n\n36\n00:02:15,430 --> 00:02:16,480\n妨碍彼此的工作\ninterfere with each other.\n\n37\n00:02:16,630 --> 00:02:20,310\n你在设计系统的时候 不仅仅需要这些\nSomehow in designing a system, you not only want these\n\n38\n00:02:20,310 --> 00:02:23,840\n水平的抽象屏障 同时也想设置一道\nhorizontal barriers, but you also want some kind of\n\n39\n00:02:25,824 --> 00:02:30,640\n垂直的屏障 -- 来把George和Martha分离开\nsome kind of vertical barrier to keep George and Martha separate.\n\n40\n00:02:32,980 --> 00:02:35,400\n我们来说得再具体一点\nLet me be a little bit more concrete.\n\n41\n00:02:36,560 --> 00:02:40,540\n想象一个很大的公司的人事记录\nImagine that you're thinking about personnel records\n\n42\n00:02:41,180 --> 00:02:46,110\n这个公司里有很多部门没什么联系\nfor a large company with a lot of loosely linked divisions\n\n43\n00:02:47,900 --> 00:02:49,710\n并且部门之间合作得也不太好\nthat don't cooperate very well either.\n\n44\n00:02:50,430 --> 00:02:57,040\n甚至还可以想象这个大公司就是由\nAnd imagine even that this company is formed by merging a\n\n45\n00:02:57,040 --> 00:02:59,450\n很多公司组成的 而且每个公司\nwhole bunch of companies that already have their personnel\n\n46\n00:02:59,450 --> 00:03:00,700\n都有自己的一套人事记录\nrecord system set up.\n\n47\n00:03:03,250 --> 00:03:06,570\n想象一下突然有一天 这些部门\nAnd imagine that once these divisions are all linked in\n\n48\n00:03:06,570 --> 00:03:08,530\n被一种神奇的卫星网络连接起来\nsome kind of very sophisticated satellite\n\n49\n00:03:08,530 --> 00:03:10,520\n它们各自的数据库都被放到了一起\nnetwork, and all these databases are put together.\n\n50\n00:03:12,240 --> 00:03:13,850\n现在你想要\nAnd what you'd like to do\n\n51\n00:03:14,840 --> 00:03:16,330\n在公司的任何地方\nis from any place in the company,\n\n52\n00:03:17,260 --> 00:03:23,130\n都能够知道 哦 某一条人事记录里的\nto be able to say things like,oh, what's the name in a\n\n53\n00:03:23,130 --> 00:03:23,870\n“姓名”是什么\npersonnel record?\n\n54\n00:03:26,300 --> 00:03:29,150\n或者一条记录里的“工作”是什么\nOr, what's the job description in a personnel record?\n\n55\n00:03:30,540 --> 00:03:34,400\n同时又不需要担心每一个部门\nAnd not have to worry about the fact that each division\n\n56\n00:03:34,840 --> 00:03:36,760\n对于人事记录的格式\nobviously is going to have completely separate\n\n57\n00:03:36,760 --> 00:03:39,370\n有着完全不同的习惯\nconventions for how you might implement these records.\n\n58\n00:03:41,580 --> 00:03:43,260\n从你的视角上你不想去了解这些东西\nFrom this point you don't want to know about that.\n\n59\n00:03:44,960 --> 00:03:47,920\n那么怎么才能做到这样呢？\nWell how could you possibly do that?\n\n60\n00:03:48,430 --> 00:03:52,410\n当然 一种方法是下发一个告示\nOne way, of course, is to send down an edict from somewhere\n\n61\n00:03:52,640 --> 00:03:56,290\n来通知所有人把他们的记录格式\nthat everybody has to change their format to some fixed\n\n62\n00:03:56,290 --> 00:03:57,240\n都改成某种标准的格式\ncompatible thing.\n\n63\n00:03:58,070 --> 00:04:00,120\n人们经常这样做 但都没有成功\nThat's what people often try, and of course it never works.\n\n64\n00:04:01,820 --> 00:04:07,340\n另一个办法则是重新安排这些记录\nAnother thing that you might want to do is somehow arrange\n\n65\n00:04:08,330 --> 00:04:09,900\n让它们中间有这种垂直的抽象屏障\nit so you can have these vertical barriers.\n\n66\n00:04:11,250 --> 00:04:14,400\n当你查询一份人事档案里的姓名的时候\nSo that when you ask for the name of a personnel record,\n\n67\n00:04:14,430 --> 00:04:17,970\n不管它是什么格式 name这个过程都能设法\nsomehow, whatever format it happens to be, name will\n\n68\n00:04:17,970 --> 00:04:19,420\n搞清楚怎么正确地完成这件事\nfigure out how to do the right thing.\n\n69\n00:04:22,730 --> 00:04:25,530\n我们把name叫做一个 所谓的“通用运算符”\nWe want name to be, so-called, a generic operator.\n\n70\n00:04:26,260 --> 00:04:30,060\n通用运算符意味着它会根据数据的种类\nGeneric operator means what it sort of precisely does depends\n\n71\n00:04:30,060 --> 00:04:31,690\n准确地做出对应的操作\non the kind of data that it's looking at.\n\n72\n00:04:33,650 --> 00:04:36,620\n更进一步讲 你想让这个系统在\nMore than that, you'd like to design the system so that the\n\n73\n00:04:36,920 --> 00:04:39,790\n下次公司里多了一个新的人员划分的时候\nnext time a new division comes into the company\n\n74\n00:04:42,510 --> 00:04:45,640\n人们连接系统的方法不会有很大的变化\nthey don't have to make any big changes in what they're already doing\n\n75\n00:04:45,640 --> 00:04:50,110\n并且公司里剩下的部门\nto link into this system, and the rest of the company\n\n76\n00:04:50,110 --> 00:04:52,010\n要把它们的人员记录添加到这个系统\ndoesn't have to make any big changes\n\n77\n00:04:52,270 --> 00:04:53,930\n也不需要做什么大的修改\nto admit their stuff to the system.\n\n78\n00:04:55,520 --> 00:04:57,520\n那么这就是你应该考虑的问题\nSo that's the problem you should be thinking about.\n\n79\n00:04:58,700 --> 00:05:00,770\n或者这就是你的工作\nLike it's sort of just your work.\n\n80\n00:05:00,770 --> 00:05:03,776\n要让系统可以用最少的改动来拥抱变化\nYou want to be able to include new things by making minimal changes.\n\n81\n00:05:05,980 --> 00:05:08,120\n这就是我们今天要讨论的问题\nOK, well that's the problem that we'll be talking about today.\n\n82\n00:05:09,440 --> 00:05:14,220\n你脑子里应该有这个分布式的人事档案系统\nAnd you should have this sort of distributed personnel record system in your mind.\n\n83\n00:05:14,240 --> 00:05:16,620\n但是实际上 我今天要讨论的是一个\nBut actually the one I'll be talking about is a problem\n\n84\n00:05:16,620 --> 00:05:18,480\n比那要更加自成体系的问题\nthat's a little bit more self-contained than that.\n\n85\n00:05:19,290 --> 00:05:21,760\n我觉得用它可以把事情说得更清楚一点\nthat'll bring up the issues, I think, more clearly.\n\n86\n00:05:21,870 --> 00:05:26,010\n我们要讨论的是 复数域上的算术系统\nThat's the problem of doing a system that does arithmetic on complex numbers.\n\n87\n00:05:27,770 --> 00:05:28,920\n我们来看看这个系统\nSo let's take a look here.\n\n88\n00:05:30,690 --> 00:05:31,744\n来复习一下\nJust as a little review,\n\n89\n00:05:32,048 --> 00:05:33,530\n什么是“复数”\nthere are things called complex numbers.\n\n90\n00:05:35,250 --> 00:05:38,220\n复数z可以看做复平面上的一点\nComplex number you can think of as a point in the plane, or z.\n\n91\n00:05:39,370 --> 00:05:47,190\n我们将复数表示为实数部分和虚数部分\nAnd you can represent a point either by its real-part and its imaginary-part.\n\n92\n00:05:47,190 --> 00:05:50,830\n所以如果这个是复数z 它的实部是这么多\nSo if this is z and its real-part is this much,\n\n93\n00:05:51,500 --> 00:05:53,240\n它的虚部是那么多\nand its imaginary-part is that much,\n\n94\n00:05:54,330 --> 00:05:56,440\n我们就可以记z=x+iy\nand you write z equals x plus iy.\n\n95\n00:05:59,110 --> 00:06:03,210\n还有另一种方法来表示一个复数 比如说\nOr another way to represent a complex number is by saying,\n\n96\n00:06:03,210 --> 00:06:09,000\n这个点与原点的距离是多少 在原点的什么角度上\nwhat's the distance from the origin, and what's the angle?\n\n97\n00:06:11,320 --> 00:06:16,670\n像这样 复数也可以表示为半径乘以一个角度\nSo that represents a complex number as its radius times an angle.\n\n98\n00:06:19,520 --> 00:06:21,920\n第一种表示法称为 直角坐标系表示\nThis one's called -- the original one's called rectangular form,\n\n99\n00:06:22,590 --> 00:06:25,456\n或者说实部-虚部表示\nrectangular representation, real- and imaginary-part\n\n100\n00:06:26,208 --> 00:06:30,040\n而后一种是用模和辐角两部分的极坐标表示\nor polar representation magnitude and angle--\n\n101\n00:06:30,040 --> 00:06:31,480\n并且如果你知道了一个复数的实部和虚部\nand if you know the real- and imaginary-part,\n\n102\n00:06:31,530 --> 00:06:33,360\n你就能计算出它的模和辐角\nyou can figure out the magnitude and angle.\n\n103\n00:06:33,720 --> 00:06:36,970\n如果知道了x和y 就能用这个式子算出r\nIf you know x and y, you can get r by this formula.\n\n104\n00:06:37,190 --> 00:06:39,480\n等于两个数平方和的平方根 然后就可以\nSquare root of sum of the squares, and you can get the\n\n105\n00:06:39,480 --> 00:06:40,760\n用反三角函数算出辐角的值\nangle as an arctangent.\n\n106\n00:06:41,420 --> 00:06:44,420\n或者反过来 如果你知道了r和A\nOr conversely, if you knew r and A you could\n\n107\n00:06:44,420 --> 00:06:45,310\n你也能计算出x和y\nfigure out x and y.\n\n108\n00:06:45,800 --> 00:06:49,430\nx=r·cos(A) y=r·sin(A)\nx is r times the cosine of A, and y is r times the sine of A.\n\n109\n00:06:51,340 --> 00:06:53,660\n这是表示复数的两种不同方法\nAll right, so there's these two. They're complex numbers.\n\n110\n00:06:54,130 --> 00:06:57,150\n分别是极坐标形式和直角坐标形式\nYou can think of them either in polar form or rectangular form.\n\n111\n00:06:57,150 --> 00:06:58,128\n我们要设计的是\nWhat we would like to do\n\n112\n00:06:58,320 --> 00:07:01,328\n一个复数域上的算术系统\nis make a system that does arithmetic on complex numbers.\n\n113\n00:07:03,952 --> 00:07:05,120\n换句话讲 我们要\nIn other words, what we'd like--\n\n114\n00:07:05,580 --> 00:07:06,990\n就像之前课上有理数运算的例子一样\njust like the rational number example--\n\n115\n00:07:07,380 --> 00:07:10,208\n是构造一个叫做+c的操作\nis to have some operations plus c,\n\n116\n00:07:10,736 --> 00:07:13,904\n它将两个复数然后把它们相加、相减\nwhich is going to take two complex numbers and add them, subtract them,\n\n117\n00:07:14,352 --> 00:07:16,944\n相乘或者相除\n and multiply them, and divide them.\n\n118\n00:07:20,730 --> 00:07:25,280\n那么我们要用到一点点数学\nOK, well there's little bit of mathematics behind it.\n\n119\n00:07:25,280 --> 00:07:28,360\n对它们进行操作的具体的算式是什么\nWhat are the actual formulas for manipulating such things?\n\n120\n00:07:30,410 --> 00:07:31,920\n它们是怎么得出来的 并不重要\nAnd it's sort of not important where they come from,\n\n121\n00:07:34,000 --> 00:07:35,790\n我们只是用它们实现运算\nbut just as an implementer let's see--\n\n122\n00:07:35,800 --> 00:07:37,950\n如果想要把两个复数相加\nif you want to add two complex numbers it's pretty easy to\n\n123\n00:07:39,130 --> 00:07:42,660\n可以很容易地获取它们的实部和虚部\nit's pretty easy to get its real-part and its imaginary-part.\n\n124\n00:07:42,660 --> 00:07:45,930\n两个复数的和的实部\nThe real-part of the sum of two complex numbers\n\n125\n00:07:47,720 --> 00:07:49,728\nz1+z2的实部\nreal-part of the z1 plus z2\n\n126\n00:07:50,064 --> 00:07:54,640\n就是z1的实部加上z2的实部\nis the real-part of z1 plus the real-part of z2.\n\n127\n00:07:57,820 --> 00:08:01,600\n然后z1+z2的虚部也就是\nAnd the imaginary-part of z1 plus z2\n\n128\n00:08:01,744 --> 00:08:05,664\nz1的虚部加上z2的虚部\nis the imaginary part of z1 plus the imaginary part of z2.\n\n129\n00:08:07,410 --> 00:08:09,480\n所以复数相加是非常简单的事情\nSo it's pretty easy to add complex numbers.\n\n130\n00:08:09,480 --> 00:08:10,992\n你只要把各个部分分别加起来\nYou just add the corresponding parts\n\n131\n00:08:11,310 --> 00:08:13,180\n然后用结果构建一个新的复数\nand make a new complex number with those parts.\n\n132\n00:08:13,370 --> 00:08:14,736\n如果你想要让复数相乘\nIf you want to multiply them,\n\n133\n00:08:15,536 --> 00:08:17,820\n那么在极坐标下运算会方便很多\nit's kind of nice to do it in polar form.\n\n134\n00:08:17,820 --> 00:08:20,384\n因为对于两个复数\nBecause if you have two complex numbers,\n\n135\n00:08:20,400 --> 00:08:26,540\n两复数积之模 就是它们各自的模的乘积\n the magnitude of their product is here, the product of the magnitudes.\n\n136\n00:08:28,850 --> 00:08:33,880\n它们的积的辐角 就是两个辐角的和\nAnd the angle of the product is the sum of the angles.\n\n137\n00:08:35,800 --> 00:08:40,540\n这就是复数域上的运算所需的数学知识\nSo that's sort of mathematics that allows you to do arithmetic on complex numbers.\n\n138\n00:08:40,540 --> 00:08:42,380\n我们来想一想具体的实现\nLet's actually think about the implementation.\n\n139\n00:08:43,720 --> 00:08:47,390\n我们就像之前运算有理数那样做\nWell we do it just like rational numbers.\n\n140\n00:08:49,840 --> 00:08:53,470\n来到底层 假设有一些构造函数和选择函数\nWe come down, we assume we have some constructors and selectors.\n\n141\n00:08:53,760 --> 00:08:54,528\n它们应该是什么样子呢\nWhat would we like?\n\n142\n00:08:55,330 --> 00:08:58,160\n假设我们制造了一些表示数据对象的“云彩”\nWell let's assume that we make a data object cloud,\n\n143\n00:08:58,540 --> 00:09:00,780\n也就是用某种形式表示的复数\nwhich is a complex number that has some stuff in it,\n\n144\n00:09:01,790 --> 00:09:04,670\n我们能从这个复数中得到它的实部\nand that we can get out from a complex number the real-part,\n\n145\n00:09:05,520 --> 00:09:09,640\n可以获得 虚部、模、或者辐角\nor the imaginary-part, or the magnitude, or the angle.\n\n146\n00:09:12,150 --> 00:09:14,010\n然后我们需要一种方法来构造复数\nWe want some ways of making complex numbers--\n\n147\n00:09:14,030 --> 00:09:15,640\n不仅要有选择函数 还要有构造函数\nnot only selectors, but constructors.\n\n148\n00:09:16,800 --> 00:09:19,520\n那么假设我们有一个叫做make-rectangular的过程\nSo we'll assume we have a thing called make-rectangular.\n\n149\n00:09:19,530 --> 00:09:24,270\n这个过程的功能是接受一个实部\nWhat make-rectangular is going to do is take a real-part and\n\n150\n00:09:24,510 --> 00:09:29,360\n和一个虚部 然后把这两个部分组合成一个复数\nan imaginary-part and construct a complex number with those parts.\n\n151\n00:09:31,920 --> 00:09:35,010\n同样我们也可以构造一个make-polar过程\nSimilarly, we can have make-polar which will taking\n\n152\n00:09:35,010 --> 00:09:37,850\n它接受一个模和一个辐角\na magnitude and an angle,\n\n153\n00:09:40,830 --> 00:09:43,900\n然后用这两个值 组成一个复数\nand construct a complex number which has that magnitude and angle.\n\n154\n00:09:44,680 --> 00:09:45,460\n那么这个系统\nSo here's a system.\n\n155\n00:09:45,460 --> 00:09:47,770\n里面会有两个构造函数和四个选择函数\nWe'll have two constructors and four selectors.\n\n156\n00:09:48,910 --> 00:09:55,150\n现在 就像之前课程中那样 我们基于这个抽象的数据结构\nAnd now, just like before, in terms of that abstract data\n\n157\n00:09:55,150 --> 00:09:59,220\n继续实现复数的各种运算\nwe'll go ahead and implement our complex number operations.\n\n158\n00:09:59,220 --> 00:10:02,300\n而这些Lisp代码\nAnd here you can see translated into Lisp code\n\n159\n00:10:03,230 --> 00:10:07,470\n是从我之前写的算术公式“翻译”而来的\njust the arithmetic formulas I put down before.\n\n160\n00:10:08,060 --> 00:10:09,980\n如果我想把两个复数相加\nIf I want to add two complex numbers\n\n161\n00:10:11,760 --> 00:10:15,560\n我就要用一个实部和一个虚部构造一个复数\nI will make a complex number out of its real- and imaginary-parts.\n\n162\n00:10:16,720 --> 00:10:19,024\n这个新的复数的实部是\nThe real part of the complex number I'm going to make\n\n163\n00:10:19,408 --> 00:10:21,800\n两个复数的实部的和\nis the sum of the real-parts.\n\n164\n00:10:23,310 --> 00:10:25,376\n它的虚数部分是\nThe imaginary part of the complex number I'm going to make\n\n165\n00:10:25,408 --> 00:10:27,520\n两个复数的虚部的和\nis the sum of the imaginary-parts.\n\n166\n00:10:30,310 --> 00:10:32,090\n我把它们放到一起 构造出一个复数\nI put those together, make a complex number.\n\n167\n00:10:32,160 --> 00:10:34,440\n这就是实现复数加法的方法\nThat's how I implement complex number addition.\n\n168\n00:10:35,780 --> 00:10:38,490\n减法实际上是一样的\nSubtraction is essentially the same.\n\n169\n00:10:39,650 --> 00:10:42,970\n只需要把各个部分相加变成把它们相减\nAll I do is subtract the parts rather than add them.\n\n170\n00:10:45,140 --> 00:10:47,072\n要把两个复数相乘\nTo multiply two complex numbers,\n\n171\n00:10:47,740 --> 00:10:49,020\n要用另外一个式子\nI use the other formula.\n\n172\n00:10:49,270 --> 00:10:53,840\n我会用一个模和一个辐角来构造一个复数\nI'll make a complex number out of a magnitude and angle.\n\n173\n00:10:55,350 --> 00:10:56,448\nz1*z2的模\nThe magnitude\n\n174\n00:10:56,656 --> 00:11:00,970\n就是z1的模乘以z2的模\nis going to be the product of the magnitudesof the two complex numbers I'm multiplying.\n\n175\n00:11:03,710 --> 00:11:05,936\n而z1*z2的辐角则是\nAnd the angle is going to be the sum\n\n176\n00:11:06,160 --> 00:11:08,510\nz1的辐角加上z2的辐角\nof the angles of the z1two complex numbers I'm multiplying.\n\n177\n00:11:09,620 --> 00:11:10,960\n那么这就是乘法的实现\nSo there's multiplication.\n\n178\n00:11:11,230 --> 00:11:12,256\n然后是除法\nAnd then division,\n\n179\n00:11:14,272 --> 00:11:15,904\n除法和乘法几乎是一样的\ndivision is almost the same.\n\n180\n00:11:17,370 --> 00:11:19,580\n我只要把两个模相除 把辐角相减就可以了\nHere I divide the magnitudes and subtract the angles.\n\n181\n00:11:28,360 --> 00:11:30,460\n现在我已经实现了各种运算\nNow I've implemented the operations.\n\n182\n00:11:31,870 --> 00:11:33,640\n然后我们做什么\nAnd what do we do?\n\n183\n00:11:33,640 --> 00:11:34,520\n我们把George叫来\nWe call on George.\n\n184\n00:11:36,060 --> 00:11:38,790\n我们完成了“使用”的部分 现在应该考虑“表示”了\nWe've done the use, let's worry about the representation.\n\n185\n00:11:38,800 --> 00:11:40,940\n我们叫来George然后对他说\nWe'll call on George and say to George,\n\n186\n00:11:40,970 --> 00:11:43,610\n“为我们设计一个一套复数的表示方法”\ngo ahead and build us a complex number representation.\n\n187\n00:11:45,250 --> 00:11:47,440\n很好\nWell that's fine...ahhh\n\n188\n00:11:47,770 --> 00:11:52,660\nGeorge可能会说 我们把一个复数\nGeorge can say, we'll implement a complex number\n\n189\n00:11:52,660 --> 00:11:57,150\n实现为 一个由实部和虚部组成的序对\nsimply as a pair that has the real-part and the imaginary-part.\n\n190\n00:11:57,200 --> 00:12:02,620\n那么如果我想用某个实部和虚部来构造复数\nSo if I want to make a complex number with a certain real-part and an imaginary-part,\n\n191\n00:12:03,360 --> 00:12:05,552\n我只需要把它们cons起来即可 这样可以--\nI'll just use cons to form a pair, and that will--\n\n192\n00:12:06,032 --> 00:12:08,110\n这就是George表示复数的方法\nthat's George's representation of a complex number.\n\n193\n00:12:09,780 --> 00:12:12,420\n那么如果我想获得它的实部 我只需要\nSo if I want to get out the real-part of something, I just\n\n194\n00:12:12,420 --> 00:12:14,120\n提取出序对的car部分 -- 它的首部分\nextract the car, the first part.\n\n195\n00:12:14,350 --> 00:12:16,670\n如果我想要得到虚部 我就提取出它的cdr部分\nIf I want to get the imaginary-part, I extract the cdr\n\n196\n00:12:19,640 --> 00:12:21,770\n那对于模和辐角 又该如何取得呢？\nHow do I deal with the magnitude and angle?\n\n197\n00:12:22,220 --> 00:12:25,750\n如果我想取得某个复数的模\nWell if I want to extract the magnitude of one of these things\n\n198\n00:12:25,750 --> 00:12:32,300\n我需要计算该复数car与cdr的平方和的算术平方根\nI get the square root of the sum of the square of the car plus the square of the cdr.\n\n199\n00:12:33,790 --> 00:12:39,260\n如果我想得到辐角 我就计算它的cdr与car比值的反正切\nIf I want to get the angle, I compute the arctangent of the cdr in the car.\n\n200\n00:12:39,530 --> 00:12:42,860\n这个Lisp过程用于计算反正切\nThis is a lisp procedure for computing arctangent.\n\n201\n00:12:44,970 --> 00:12:48,590\n要是有人给我一个模和辐角\nAnd if somebody hands me a magnitude and an angle\n\n202\n00:12:48,940 --> 00:12:50,560\n并说：“给我构造一个复数”\nand says, make me a complex number,well I compute the\n\n203\n00:12:50,890 --> 00:12:56,240\n用它们计算出实部 r*cos(a) 和虚部 r*sin(a)\nwell I compute the real-part and the imaginary-part, r * cosine of a and r * sine of a,\n\n204\n00:12:57,770 --> 00:12:59,050\n连接成一个序对就行了\nand stick them together into a pair.\n\n205\n00:13:01,460 --> 00:13:02,260\n完成了\nOK so we're done.\n\n206\n00:13:02,260 --> 00:13:04,750\n实际上我做的事情 在概念上讲\nIn fact, what I just did, conceptually,\n\n207\n00:13:06,890 --> 00:13:09,376\n和我们之前提过的有理数的表示\nis absolutely no different from the rational number\n\n208\n00:13:10,608 --> 00:13:12,440\n是完全没有区别的\nrepresentation that we looked at last time.\n\n209\n00:13:12,750 --> 00:13:13,910\n它们的思想相同\nIt's the same sort of idea.\n\n210\n00:13:13,910 --> 00:13:16,280\n实现具体过程 选择一种表示方法\nYou implement the operators, you pick a representation.\n\n211\n00:13:18,070 --> 00:13:18,650\n没有什么不同\nNothing different.\n\n212\n00:13:20,070 --> 00:13:21,560\n现在我们来关心一下Martha\nNow let's worry about Martha.\n\n213\n00:13:23,210 --> 00:13:24,520\n嗯 Martha的想法不太一样\nSee, Martha has a different idea.\n\n214\n00:13:26,670 --> 00:13:28,576\n她不想把复数表示成\nShe doesn't want to represent a complex number\n\n215\n00:13:28,592 --> 00:13:30,900\n由实部和虚部组成的序对\nas a pair of a real-part and an imaginary-part.\n\n216\n00:13:30,900 --> 00:13:34,170\n她比较喜欢把它们表示成\nWhat she would like to do is represent a complex number as\n\n217\n00:13:34,170 --> 00:13:37,690\n由模和辐角组成的序对\na pair of a magnitude and an angle.\n\n218\n00:13:39,550 --> 00:13:42,130\n那么如果我们没有让George而是让Martha\nSo if instead of calling up George we ask Martha to design\n\n219\n00:13:42,130 --> 00:13:43,740\n来设计复数的表示方法 我们就会得到这样的东西\nour representation, we get something like this.\n\n220\n00:13:44,570 --> 00:13:47,160\n有一个make-polar过程\nWe get make-polar.\n\n221\n00:13:47,160 --> 00:13:50,220\n当然了 有了一个模和一个辐角之后\nSure, if I give you a magnitude and an angle we're\n\n222\n00:13:50,220 --> 00:13:53,070\n我们只要把它们组合成一个序对就行了\njust going to form a pair that has magnitude and angle.\n\n223\n00:13:55,430 --> 00:13:57,680\n如果你想取得复数的模 那很简单\nIf you want to extract the magnitude, that's easy.\n\n224\n00:13:58,240 --> 00:13:59,370\n你只需要取序对的car部分即可\nYou just pull out the car or the pair.\n\n225\n00:13:59,780 --> 00:14:02,670\n当然 想取得复数的辐角 那也很简单\nIf you want to extract the angle, sure, that's easy.\n\n226\n00:14:02,670 --> 00:14:03,630\n只需取cdr部分即可\nYou just pull out the cdr.\n\n227\n00:14:04,810 --> 00:14:07,020\n但是如果你想要获得实部和虚部\nIf you want to look for real-parts and imaginary-parts,\n\n228\n00:14:07,420 --> 00:14:08,490\n那就得费点力气\nwell then you have to do some work.\n\n229\n00:14:08,880 --> 00:14:14,580\n想得到实部 你就得计算r*cos(a)\nIf you want the real-part, you have to get r cosine a.\n\n230\n00:14:14,580 --> 00:14:19,990\n换句话讲 用序对的car部分去乘以\nIn other words, r, the car of the pair, times the cosine of\n\n231\n00:14:19,990 --> 00:14:20,950\ncdr部分的余弦值\nthe cdr of the pair.\n\n232\n00:14:20,950 --> 00:14:26,230\n然后你就算出了r*cos(a)\nSo this is r times the cosine of a,\n\n233\n00:14:26,540 --> 00:14:27,480\n这就是这个复数的实部\nand that's the real-part.\n\n234\n00:14:28,330 --> 00:14:31,400\n要是想算出它的虚部 用r乘以sin(a)就可以了\nIf you want to get the imaginary-part, it's r times the sine of a.\n\n235\n00:14:32,660 --> 00:14:37,930\n现在如果我给你一个实部和虚部 然后说\nAnd if I hand you a real-part and an imaginary-part and say,\n\n236\n00:14:37,930 --> 00:14:42,030\n用它们给我构造一个复数\nmake me a complex number with that real-part and\n\n237\n00:14:42,030 --> 00:14:44,170\n那就要先算出\nimaginary-part, well I figure out what the magnitude and\n\n238\n00:14:44,170 --> 00:14:45,540\n模和辐角是多少\nangle should be.\n\n239\n00:14:45,540 --> 00:14:47,850\n模是实部和虚部的平方和的算术平方根\nThe magnitude's the square root of the sum of the squares\n\n240\n00:14:48,090 --> 00:14:49,230\n辐角是这个反正切\nand the angle's the arctangent.\n\n241\n00:14:49,230 --> 00:14:50,220\n我用这两个数构造一个序对\nI put those together to make a pair.\n\n242\n00:14:52,090 --> 00:14:54,170\n以上就是Martha的想法\nSo there's Martha's idea.\n\n243\n00:14:56,690 --> 00:14:57,370\n那么哪种比较好呢？\nWell which is better?\n\n244\n00:14:59,680 --> 00:15:03,150\n如果你需要做很多加法 那么George的比较好\nWell if you're doing a lot of additions, probably George's is better\n\n245\n00:15:03,160 --> 00:15:05,610\n因为你总是要用到复数的实部和虚部\nis better, because you're doing a lot of real-parts and imaginary-parts.\n\n246\n00:15:05,850 --> 00:15:08,400\n如果你大多数时间都是在做乘法\nIf mostly you're going to be doing multiplications and divisions,\n\n247\n00:15:09,480 --> 00:15:11,140\n那可能Martha的办法就要好一些\nthen maybe Martha's idea is better.\n\n248\n00:15:11,140 --> 00:15:14,840\n又或者 -- 这就是问题所在了 -- 你决定不了\nOr maybe, and this is the real point, you can't decide.\n\n249\n00:15:16,590 --> 00:15:22,320\n或者出于某些个人原因 你想让它们同时存在\nOr maybe you just have to let them both hang around, for personality reasons.\n\n250\n00:15:23,480 --> 00:15:26,760\n也可能你是真的无法决定你更喜欢哪种表示法\nMaybe you just really can't ever decide what you would like.\n\n251\n00:15:28,560 --> 00:15:32,320\n回到这个话题 我们真正想要的是这样一个系统\nAnd again, what we would really like is a system that looks like this.\n\n252\n00:15:32,650 --> 00:15:36,170\n这里面 既有George 他实现了\nThat somehow there's George over here, who has built\n\n253\n00:15:36,830 --> 00:15:39,640\n复数的直角坐标表示\nrectangular complex numbers.\n\n254\n00:15:41,470 --> 00:15:44,250\n又有Martha 她实现了复数的极坐标表示\nAnd Martha, who has polar complex numbers.\n\n255\n00:15:46,120 --> 00:15:49,696\n然后我们有各种运算\nAnd somehow we have operations\n\n256\n00:15:50,288 --> 00:15:56,890\n用来对复数进行加减乘除\nthat can add, and subtract, and multiply, and divide\n\n257\n00:15:57,560 --> 00:15:58,768\n那么这些运算\nand it shouldn't matter\n\n258\n00:15:59,344 --> 00:16:02,790\n不应该被系统中同时存在的两种\nthat there are two incompatible representations of complex\n\n259\n00:16:02,790 --> 00:16:03,980\n互不兼容的复数表示方法影响\nnumbers floating around this system.\n\n260\n00:16:04,410 --> 00:16:08,330\n或者说 我们不光有像这样的一个抽象屏障\nIn other words, not only like an abstraction barrier here\n\n261\n00:16:09,640 --> 00:16:11,840\n它里面有real-part\nthat has things in it like a real-part,\n\n262\n00:16:15,770 --> 00:16:21,710\n还有 IMAG-PART、MAG 和 ANG 等几个过程\nand an imaginary-part, and magnitude,and angle.\n\n263\n00:16:23,830 --> 00:16:25,360\n不光有一层抽象屏障\nSo not only is there an abstraction barrier\n\n264\n00:16:25,392 --> 00:16:28,380\n把实际的数据表示隐藏起来\nthat hides the actual representation from us,\n\n265\n00:16:29,100 --> 00:16:31,520\n还有一层垂直的屏障\nbut also there's some kind of vertical barrier here\n\n266\n00:16:32,190 --> 00:16:35,024\n容许不同的表示方法彼此共存\nthat allows both of these representations to exist\n\n267\n00:16:35,872 --> 00:16:37,400\n而不互相干预\nwithout interfering with each other.\n\n268\n00:16:38,570 --> 00:16:41,070\n我们的想法是把这些东西\nThe idea is that the things in here--\n\n269\n00:16:41,900 --> 00:16:44,120\nREAL-PART、IMAG-PART、MAG、ANG 这些过程\nreal-part, imaginary-part,magnitude, and angle--\n\n270\n00:16:44,120 --> 00:16:46,490\n设计成通用运算符\nwill be generic operators.\n\n271\n00:16:47,310 --> 00:16:49,450\n如果你调用real-part过程 它就会判断\nIf you ask for the real-part, it will worry about\n\n272\n00:16:49,980 --> 00:16:51,310\n要在哪一种表示方法中寻找它\nwhat representation it's looking at.\n\n273\n00:16:53,880 --> 00:16:55,100\n那么我们怎么做到这一点呢\nOK, well how can we do that?\n\n274\n00:16:56,840 --> 00:16:59,230\n实际上有一个很容易想到的办法\nThere's actually a really obvious idea,\n\n275\n00:16:59,840 --> 00:17:01,680\n如果你习惯了思考复数的模式\nif you're used to thinking about complex numbers.\n\n276\n00:17:02,520 --> 00:17:04,440\n如果你已经习惯了复合数据的思想\nIf you're used to thinking about compound data.\n\n277\n00:17:06,330 --> 00:17:10,990\n假设你只要观察一个复数\nSee, suppose you could just tell by looking at a complex number\n\n278\n00:17:12,170 --> 00:17:13,950\n就能看出它是被George还是Martha构造出来的\nwhether it was constructed by George or Martha.\n\n279\n00:17:15,790 --> 00:17:18,900\n换句话说 在你眼前漂浮的这些东西\nIn other words, so it's not that what's floating around\n\n280\n00:17:18,900 --> 00:17:20,910\n不是普通的复数 对吗？\nhere are ordinary, just complex numbers, right?\n\n281\n00:17:20,910 --> 00:17:22,940\n它们是被某个设计者“构想”出来的\nThey're fancy, designer complex numbers.\n\n282\n00:17:24,390 --> 00:17:28,040\n当考察一个复数 我们会发现它“不仅仅”是个复数\nSo you look at a complex numbers as it's not just a complex number\n\n283\n00:17:28,040 --> 00:17:29,160\n它上面有一个标签\nit's got a label on it that says,\n\n284\n00:17:29,190 --> 00:17:30,750\n写着这个是由Martha制造的\nthat one is by Martha.\n\n285\n00:17:31,450 --> 00:17:34,220\n或者这个是由George制造的\nOr this is a complex number by George.\n\n286\n00:17:34,480 --> 00:17:35,390\n对吧？它们被签了名字\nRight? They're signed.\n\n287\n00:17:36,860 --> 00:17:40,150\n在这之后 无论何时我们看见一个复数\nSee, and then whenever we looked at a complex number we\n\n288\n00:17:40,150 --> 00:17:45,480\n我们只要看它的标签  然后我们就能知道\ncould just read the label, and then we'd know how you expect\n\n289\n00:17:45,800 --> 00:17:46,720\n应该怎么对它进行运算\nto operate on that.\n\n290\n00:17:48,030 --> 00:17:51,190\n或者说 我们想要的不只是普通的数据对象\nIn other words, what we want is not just ordinary data objects.\n\n291\n00:17:51,190 --> 00:17:54,370\n我们引入一个概念：带类型的数据\nWe want to introduce the notion of what's called typed data.\n\n292\n00:17:59,760 --> 00:18:02,810\n带类型的数据就意味着 这里有一朵“云彩”\nTyped data means, again, there's some sort of cloud.\n\n293\n00:18:03,940 --> 00:18:08,930\n它里面有我们之前所说的那种\nAnd what it's got in it is an ordinary data object like\n\n294\n00:18:08,930 --> 00:18:09,900\n普通的数据对象\nwe've been thinking about.\n\n295\n00:18:13,180 --> 00:18:16,540\n这是它的内容 就是实际的数据\nPulled out the contents, sort of the actual data.\n\n296\n00:18:19,320 --> 00:18:21,568\n它里面还有一个叫做类型的东西\nBut also a thing called a type,\n\n297\n00:18:22,560 --> 00:18:25,240\n被George或者Martha签了名\nbut it's signed by either George or Martha.\n\n298\n00:18:25,990 --> 00:18:28,270\n那么我们现在就要从无类型的数据进入带类型数据的领域\nSo we're going to go from regular data to type data.\n\n299\n00:18:31,950 --> 00:18:32,710\n我们怎么构造它\nHow do we build that?\n\n300\n00:18:32,710 --> 00:18:33,500\n那很简单\nWell that's easy.\n\n301\n00:18:33,840 --> 00:18:35,320\n我们知道怎么构造“云彩”\nWe know how to build clouds.\n\n302\n00:18:35,800 --> 00:18:36,880\n我们用序对来组成它们\nWe can build them out of pairs.\n\n303\n00:18:37,920 --> 00:18:41,820\n那么我们就有了一种方法来表示带类型的数据\nSo here's a little representation that supports typed data.\n\n304\n00:18:43,510 --> 00:18:49,640\n这种方法叫做 把类型附加到内容上\nThere's a thing called take a type and attach it to a piece of contents,\n\n305\n00:18:49,690 --> 00:18:50,640\n用cons就可以做到\nand we just use cons.\n\n306\n00:18:51,640 --> 00:18:54,110\n然后面对一个带类型的数据 我们就可以知道它的类型\nAnd if we have a piece of typed data, we can look at the type\n\n307\n00:18:55,210 --> 00:18:56,000\n也就是序对的car部分\nwhich is the car.\n\n308\n00:18:56,290 --> 00:18:58,300\n我们也可以知道它的具体内容 就是它的cdr部分\nWe can look at the contents,which is the cdr.\n\n309\n00:18:59,960 --> 00:19:04,280\n我们用这种方法使用带类型的数据\nNow along with that, the way we use our type data will test,\n\n310\n00:19:05,290 --> 00:19:07,260\n面对一段类型数据就能知道它是什么类型\nwhen we're given a piece of data, what type it is.\n\n311\n00:19:07,520 --> 00:19:09,260\n那么我们现在有了几种判断类型的谓词\nSo we have some type predicates with us.\n\n312\n00:19:10,510 --> 00:19:13,730\n举例来讲 想要知道一个复数\nFor example, to see whether a complex number is one of\n\n313\n00:19:13,730 --> 00:19:16,860\n是不是George构造的 是不是直角坐标表示的 我们只需要看\nGeorge's, whether it's rectangular, we just check to\n\n314\n00:19:16,860 --> 00:19:21,850\n它的“类型”是不是rectangular这个符号\nsee if the type of that is the symbol rectangular,\n\n315\n00:19:23,680 --> 00:19:25,050\n对吧？检查 rectangular 符号\nright? The symbol rectangular.\n\n316\n00:19:27,200 --> 00:19:30,330\n同理 想要知道一个复数是不是Martha构造的\nAnd to check whether a complex number is one of Martha's,\n\n317\n00:19:30,330 --> 00:19:33,420\n我们就看它的“类型”是不是polar这个符号\nwe check to see whether the type is the symbol polar.\n\n318\n00:19:36,460 --> 00:19:39,210\n那么这就是一种识别数字的类型的方法\nSo that's a way to test what kind of number we're looking at.\n\n319\n00:19:40,750 --> 00:19:42,810\n现在来想想 怎么用这种方法来构建系统\nNow let's think about how we can use that to build the system.\n\n320\n00:19:43,870 --> 00:19:46,730\n我们假设George和Martha分别在做各自的工作\nSo let's suppose that George and Martha were off working separately,\n\n321\n00:19:47,360 --> 00:19:52,640\n每一个人都设计了他们的复数表示程序包\nand each of them had designed their complex number representation packages.\n\n322\n00:19:52,640 --> 00:19:58,520\n他们怎么让自己的东西成为系统的一部分\nWhat do they have to do to become part of the system,\n\n323\n00:19:58,730 --> 00:20:00,140\n和对方友好共存呢\nto exist compatibly?\n\n324\n00:20:00,140 --> 00:20:02,110\n那其实非常简单\nWell it's really pretty easy.\n\n325\n00:20:02,720 --> 00:20:04,510\n回忆一下 George做了这个程序包\nRemember, George had this package.\n\n326\n00:20:05,970 --> 00:20:08,480\n这就是George的程序包 或者说它的一部分\nHere's George's original package, or half of it.\n\n327\n00:20:08,980 --> 00:20:11,150\n然后红色下划线标出的部分是他需要做的修改\nAnd underlined in red are the changes he has to make.\n\n328\n00:20:12,090 --> 00:20:16,430\n之前 当George用x和y构建了一个复数的时候\nSo before, when George made a complex number out of an x and y\n\n329\n00:20:17,520 --> 00:20:19,850\n他只是把它们组合成一个序对\nhe just put them together to make a pair.\n\n330\n00:20:20,930 --> 00:20:23,390\n现在唯一不同的地方是 他给它们打了标签\nAnd the only difference is that now he signs them.\n\n331\n00:20:24,090 --> 00:20:28,080\n他把类型 -- 也就是 rectangular符号 -- 附加到这个序对上面\nHe attaches the type, which is the symbol rectangular to that pair.\n\n332\n00:20:30,600 --> 00:20:33,260\n剩下的事情都和之前一样 除了一点\nEverything else George does is the same, except that--\n\n333\n00:20:33,920 --> 00:20:38,060\n就是George和Martha的程序都有叫做real-part和imaginary-part的过程\nsee, George and Martha both have procedures named real-part and imaginary-part.\n\n334\n00:20:38,700 --> 00:20:42,960\n为了这些过程存在于在同一个Lisp环境中\nSo to allow them both to exist in the same Lisp environment,\n\n335\n00:20:44,220 --> 00:20:45,920\nGeorge就要修改他的过程名字\nGeorge had changed the names of his procedures.\n\n336\n00:20:45,920 --> 00:20:49,140\n那么我们说 这是George的real-part过程\nSo we'll say, this is George's real-part procedure.\n\n337\n00:20:49,140 --> 00:20:51,168\n叫做real-part-rectangular过程\nIt's the real-part-rectangular procedure,\n\n338\n00:20:51,488 --> 00:20:54,060\n还有 imag-part-rectangular过程\nthe imaginary-part-rectangular procedure.\n\n339\n00:20:55,420 --> 00:20:57,240\n那么这里是George的程序包剩下的部分\nAnd then here's the rest of George's package.\n\n340\n00:20:59,130 --> 00:21:02,060\n他已经有了magnitude和angle过程 只要把它们改名\nHe'd had magnitude and angle, just renames them magnitude\n\n341\n00:21:02,060 --> 00:21:04,160\n叫magnitude-rectangular和angle-rectangular就好了\nrectangular and angle rectangular.\n\n342\n00:21:06,080 --> 00:21:07,960\nMartha要做的事情基本相同\nAnd Martha has to do basically the same thing.\n\n343\n00:21:09,860 --> 00:21:16,220\n在这之前 当她用模和辐角构造复数的时候\nMartha previously, when she made a complex number out of a magnitude and angle,\n\n344\n00:21:18,140 --> 00:21:19,270\n她只是把这两个东西cons起来\nshe just cons them.\n\n345\n00:21:19,270 --> 00:21:20,860\n现在她额外附加类型 polar\nNow she attaches the type polar,\n\n346\n00:21:23,950 --> 00:21:25,610\n然后修改过程的名字\nand she changes the name\n\n347\n00:21:25,660 --> 00:21:29,850\n来避免保证她的real-part过程和George的产生冲突\nso her real-part procedure won't conflict in name with George's.\n\n348\n00:21:30,710 --> 00:21:32,990\n分别改为real-part-polar和imaginary-part-polar\nIt's a real-part-polar,imaginary-part-polar,\n\n349\n00:21:34,540 --> 00:21:38,060\nmagnitude-polar和angle-polar这四个过程\nmagnitude polar, and angle polar.\n\n350\n00:21:45,000 --> 00:21:46,130\n现在我们的系统\nNow we have the system.\n\n351\n00:21:46,130 --> 00:21:47,920\n在它里面既有George又有Martha\nRight there's George and Martha.\n\n352\n00:21:49,160 --> 00:21:51,680\n然后现在我们需要一个经理来对类型进行判断\nAnd now we've got to get some kind of manager to look at these types.\n\n353\n00:21:52,830 --> 00:21:56,480\n那么在George和Martha给我们提供了类型数据之后\nHow are these things actually going to work now\n\n354\n00:21:57,050 --> 00:21:59,400\n这个系统现在怎么工作呢？\nthat George and Martha have supplied us with typed data?\n\n355\n00:22:00,530 --> 00:22:04,300\n我们手里有的 是一堆通用选择函数\nWell what we have are a bunch of generic selectors.\n\n356\n00:22:05,260 --> 00:22:10,630\n用于复数的通用选择函数比如 real-part、imag-part、magnitude和angle等\nGeneric selectors for complex numbers real-part,imaginary-part, magnitude, and angle.\n\n357\n00:22:14,140 --> 00:22:15,400\n让我们更进一步观察它们\nLet's look at them more closely.\n\n358\n00:22:17,930 --> 00:22:19,000\nreal-part过程应该做什么\nWhat does a real-part do?\n\n359\n00:22:19,310 --> 00:22:22,760\n如果我想得到一个复数的实部\nIf I ask for the real part of a complex number,\n\n360\n00:22:24,070 --> 00:22:24,910\n那么我先要观察它\nwell I look at it.\n\n361\n00:22:25,800 --> 00:22:26,690\n我观察它的类型\nI look at its type.\n\n362\n00:22:26,690 --> 00:22:28,120\n考虑它是用直角坐标表示的吗\nI say, is it rectangular?\n\n363\n00:22:31,020 --> 00:22:35,360\n如果是的话 我就对这个复数的\"内容\"部分\nIf so, I apply George's real part procedure\n\n364\n00:22:36,060 --> 00:22:37,920\n调用George的real-part过程\nto the contents of that complex number.\n\n365\n00:22:41,070 --> 00:22:42,940\n这是一个带有类型的数字\nThis is a number that has a type on it.\n\n366\n00:22:43,720 --> 00:22:47,660\n我用contents过程剥掉类型 并且对它应用George的过程\nI strip off the type using contents and apply George's procedure.\n\n367\n00:22:50,700 --> 00:22:52,860\n那如果是一个用极坐标表示的复数呢？\nOr is this a polar complex number?\n\n368\n00:22:53,950 --> 00:22:54,970\n如果我想要得到它的实部\nIf I want the real part,\n\n369\n00:22:55,450 --> 00:22:58,780\n我就把Martha的real-part过程应用在这个数的内容上\nI apply Martha's real-part procedure to the contents of that number.\n\n370\n00:22:59,850 --> 00:23:01,150\n这就是real-part工作的方式\nSo that's how real part works.\n\n371\n00:23:02,260 --> 00:23:05,660\n还有类似的imag-part过程 几乎是一样的\nAnd then similarly there's imaginary-part, which is almost the same.\n\n372\n00:23:06,510 --> 00:23:09,600\n它先观察这个数字 它是直角坐标表示的\nRight? It looks at the number and if it's rectangular, uses\n\n373\n00:23:09,600 --> 00:23:11,130\n就调用George的imaginary-part过程\nGeorge's imaginary-part procedure.\n\n374\n00:23:11,130 --> 00:23:12,830\n是极坐标表示的 就用Martha的过程\nIf it's polar, uses Martha's.\n\n375\n00:23:13,380 --> 00:23:17,400\n同理也可以构造出magnitude和angle两个过程\nAnd then there's a magnitude and an angle.\n\n376\n00:23:19,710 --> 00:23:21,020\n我们的系统是这个样子\nSo there's a system.\n\n377\n00:23:23,000 --> 00:23:24,260\n它里面有三个部分\nHas three parts.\n\n378\n00:23:24,260 --> 00:23:26,590\n有George、Martha和一个经理\nThere's sort of George, and Martha, and the manager.\n\n379\n00:23:26,760 --> 00:23:28,970\n这就是实现通用操作符的方法\nAnd that's how you get generic operators implemented.\n\n380\n00:23:28,970 --> 00:23:32,920\n为了把它说清楚 我们举一个简单的实例\nLet's look at just a simple example, just to pin it down.\n\n381\n00:23:33,500 --> 00:23:35,120\n但是准确描述了它工作的方式\nBut exactly how this is going to work,\n\n382\n00:23:36,540 --> 00:23:43,980\n假设你现在 面对一个实部是1\nsuppose you're going to be looking at the complex number who's real-part is one,\n\n383\n00:23:44,520 --> 00:23:46,090\n虚部是2的复数\nand who's imaginary-part is two.\n\n384\n00:23:46,090 --> 00:23:48,440\n也就是1+2i\nSo that would be one plus 2i.\n\n385\n00:23:50,310 --> 00:23:52,640\n现在在这里\nWhat would happen is up here,\n\n386\n00:23:55,280 --> 00:23:57,530\n在操作发生的上层\nup here above where the operations have to happen,\n\n387\n00:23:57,630 --> 00:24:08,270\n复数被表示成一个由1和2组成的序对加上类型信息\nthat number would be represented as a pair of 1 and 2 together with type data.\n\n388\n00:24:10,480 --> 00:24:11,390\n（1和2）是内容\nThat would be the contents.\n\n389\n00:24:11,870 --> 00:24:17,960\n整个的数据就是在那之上加上一个rectangular符号\nAnd the whole data would be that thing with the symbol rectangular added onto that.\n\n390\n00:24:18,140 --> 00:24:21,530\n这就是复数在这个系统里存在的形式\nAnd that's the way that complex number would exist in the system.\n\n391\n00:24:22,330 --> 00:24:24,920\n你要调取real-part的时候\nWhen you went to take the real-part,\n\n392\n00:24:25,840 --> 00:24:28,890\n经理会检查这个数然后说 这是George构造的数字\nthe manager will look at this and say, oh it's one of George's.\n\n393\n00:24:30,270 --> 00:24:31,530\n他会先把类型拿掉\nHe'll strip off the type\n\n394\n00:24:33,340 --> 00:24:36,910\n然后把 (1,2) 这个序对传递给George\nand hand down to George the pair 1, 2.\n\n395\n00:24:38,000 --> 00:24:42,270\n这是George的系统可以直接处理的数据\nAnd that's the kind of data that George developed his system to use.\n\n396\n00:24:44,360 --> 00:24:45,920\n那么它被拆了出来\nSo it gets stripped down.\n\n397\n00:24:46,520 --> 00:24:49,760\n之后 如果你让George构造一个复数\nLater on, if you ask George to construct a complex number,\n\n398\n00:24:51,240 --> 00:24:54,560\nGeorge就会把它构造成序对\nGeorge would construct some complex number as a pair,\n\n399\n00:24:55,070 --> 00:24:58,240\n在数据被传递到上层之前\nand before he passes it back up through the manager would\n\n400\n00:24:59,420 --> 00:25:01,130\n经理会再给它加上rectangular类型\nattach the type rectangular.\n\n401\n00:25:03,920 --> 00:25:04,650\n看这个过程\nSo you see what happens.\n\n402\n00:25:04,650 --> 00:25:05,850\n这个系统不会发生混乱\nThere's no confusion in this system.\n\n403\n00:25:05,850 --> 00:25:10,840\n就算在Martha的世界里 序对(1 2)的含义完全不同\nIt doesn't matter in the least that the pair 1, 2\n\n404\n00:25:13,500 --> 00:25:15,750\n也并没有什么影响\nmeans something completely different in Martha's world.\n\n405\n00:25:15,750 --> 00:25:18,440\n在Martha的世界里这个序对代表了\nIn Martha's world this pair means the complex number whose\n\n406\n00:25:18,440 --> 00:25:20,780\n一个模为1 辐角为2的复数\nmagnitude is 1 and whose angle is 2.\n\n407\n00:25:21,190 --> 00:25:22,190\n但是这并不会造成混乱\nAnd there's no confusion,\n\n408\n00:25:22,220 --> 00:25:27,250\n因为每当有一个这样的序对经由经理之手\nbecause by the time any pair like this gets handed back through the manager to the\n\n409\n00:25:27,250 --> 00:25:29,610\n被交给主系统的时候 它都会被附加上polar的类型标志\nmain system it's going to have the type polar attached.\n\n410\n00:25:31,210 --> 00:25:33,670\n而这个就会被贴上rectangular类型的标签\nWhereas this one would have the type rectangular attached.\n\n411\n00:25:36,930 --> 00:25:37,900\n好 我们休息一下\nOK, let's take a break.\n\n412\n00:25:40,770 --> 00:25:55,552\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n413\n00:25:55,690 --> 00:25:57,776\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n414\n00:25:57,776 --> 00:25:59,760\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n\n415\n00:26:05,210 --> 00:26:11,952\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n416\n00:26:12,848 --> 00:26:16,750\n通用运算符\nGeneric Operators\n\n417\n00:26:20,210 --> 00:26:24,150\n我们刚刚提出了一种实现通用运算符的策略\nWe just looked at a strategy for implementing generic operators.\n\n418\n00:26:24,150 --> 00:26:31,400\n这种策略有一个名字 叫做“基于类型的分派”\nThat strategy has a name: it's called dispatch on type.\n\n419\n00:26:34,310 --> 00:26:39,360\n它的想法就是你要把你的系统分成很多小块\nAnd the idea is that you break your system into a bunch of pieces.\n\n420\n00:26:39,360 --> 00:26:42,670\n里面有George和Martha在设计表示方法\nThere's George and Martha, who are making representations,\n\n421\n00:26:43,370 --> 00:26:44,380\n还有一个经理\nand then there's the manager.\n\n422\n00:26:46,120 --> 00:26:48,060\n负责去看数据上的类型是什么\nLooks at the types on the data\n\n423\n00:26:48,510 --> 00:26:50,590\n然后分派给正确的人去处理\nand then dispatches them to the right person.\n\n424\n00:26:51,990 --> 00:26:56,010\n这种组织系统的方法有什么缺点呢？\nWell what criticisms can we make of that as a system organization?\n\n425\n00:26:58,150 --> 00:27:00,400\n首先 有个小小的烦人的问题\nWell first of all there was this little, annoying problem\n\n426\n00:27:00,400 --> 00:27:03,050\nGeorge和Martha需要修改他们的过程的名字\nthat George and Martha had to change the names of their procedures\n\n427\n00:27:04,000 --> 00:27:05,950\nGeorge一开始写了一个real-part过程\nGeorge originally had a real-part procedure,\n\n428\n00:27:05,980 --> 00:27:08,280\n现在他必须把它的名字改成real-part-rectangular\nand he had to go name it real-part rectangular\n\n429\n00:27:08,300 --> 00:27:10,830\n才能让它不与Martha的real-part过程相互冲突\nso it wouldn't interfere with Martha's real-part procedure,\n\n430\n00:27:10,840 --> 00:27:12,760\n而Martha的过程现在改叫real-part-polar\nwhich is now named real-part-polar,\n\n431\n00:27:13,640 --> 00:27:16,680\n这是为了不和经理的那个叫做real-part的过程发生冲突\nso it wouldn't interfere with the manager's real-part procedure, who's now named real-part.\n\n432\n00:27:17,310 --> 00:27:18,940\n这个问题确实很恼人\nThat's kind of an annoying problem.\n\n433\n00:27:19,460 --> 00:27:21,130\n但是我现在暂时不讨论这个问题\nBut I'm not going to talk about that one now.\n\n434\n00:27:21,270 --> 00:27:22,350\n我们稍后将会看到\nWe'll see later on\n\n435\n00:27:23,260 --> 00:27:26,120\n在讨论到Lisp名称与环境的结构的时候\nwhen we think about the structure of Lisp names and environments\n\n436\n00:27:26,120 --> 00:27:30,390\n我们会有方法把这些所谓的命名空间分开来封装\nthat there really are ways to package all those so-called name spaces separately so they\n\n437\n00:27:30,390 --> 00:27:31,560\n然后它们就不会互相影响了\ndon't interfere with each other.\n\n438\n00:27:32,500 --> 00:27:34,010\n现在我们暂时不去考虑这个问题\nNot going to think about that problem now.\n\n439\n00:27:35,720 --> 00:27:38,190\n我现在想关注的问题是\nThe problem that I actually want to focus on is\n\n440\n00:27:38,360 --> 00:27:43,240\n你把一个新人招纳进系统之中会发生什么\nwhat happens when you bring somebody new into the system.\n\n441\n00:27:44,510 --> 00:27:45,320\n会发生什么？\nWhat has to happen?\n\n442\n00:27:45,320 --> 00:27:46,810\nGeorge和Martha并不关心\nWell George and Martha don't care.\n\n443\n00:27:47,420 --> 00:27:50,730\nGeorge在他的直角坐标世界里\nGeorge is sitting there in his rectangular world,\n\n444\n00:27:52,200 --> 00:27:53,840\n坐拥着他的过程和数据类型\nhas his procedures and his types.\n\n445\n00:27:54,090 --> 00:27:55,740\n而Martha待在她的极坐标世界中\nMartha sits in her polar world.\n\n446\n00:27:55,930 --> 00:27:57,020\n不问世事\nShe doesn't care.\n\n447\n00:27:59,380 --> 00:28:00,540\n但是经理呢？\nBut let's look at the manager.\n\n448\n00:28:00,620 --> 00:28:02,840\n经理需要做什么？\nWhat's the manager have to do?\n\n449\n00:28:03,180 --> 00:28:06,200\n现在经理带着他的运算来了\nThe manager comes through and had these operations.\n\n450\n00:28:07,360 --> 00:28:09,040\n有直角坐标的判断\nThere was a test for rectangular\n\n451\n00:28:09,040 --> 00:28:10,140\n和极坐标的判断过程\nand a test for polar.\n\n452\n00:28:10,140 --> 00:28:14,910\n如果Harry带着某种新型的复数表示方法 进入这个系统\nIf Harry comes in with some new kind of complex number,\n\n453\n00:28:17,210 --> 00:28:19,960\n同时带来了一个新的类型--Harry型复数\nand Harry has a new type, Harry type complex number, the\n\n454\n00:28:20,270 --> 00:28:23,280\n经理就需要修改他所有的过程\nmanager has to go in and change all those procedures.\n\n455\n00:28:25,240 --> 00:28:26,940\n所以这个系统的不灵活之处\nSo the inflexibility in the system,\n\n456\n00:28:26,960 --> 00:28:32,410\n也就是需要大量工作才能适应变化的地方 就在这个经理身上\nthe place where work has to happen to accommodate change, is in the manager.\n\n457\n00:28:34,890 --> 00:28:35,990\n那是非常恼人的事情\nThat's pretty annoying.\n\n458\n00:28:35,990 --> 00:28:37,210\n更恼人的是\nIt's even more annoying\n\n459\n00:28:39,050 --> 00:28:41,210\n你意识到这个经理实际上什么也不做\nIt's even more annoying when you realize the manager's not doing anything\n\n460\n00:28:42,590 --> 00:28:44,670\n这个经理只负责“传递公文”而已\nThe manager is just being a paper pusher.\n\n461\n00:28:45,840 --> 00:28:51,130\n我们再来看看这些程序 它们在做什么\nLet's look again at these programs. What are they doing?\n\n462\n00:28:51,760 --> 00:28:52,720\nreal-part过程在做什么\nWhat does real-part do?\n\n463\n00:28:52,880 --> 00:28:56,170\n这个过程说 哦 这个复数是\nReal-part says, oh, is it the kind of complex number that\n\n464\n00:28:56,170 --> 00:28:57,000\nGeorge会处理的那一种吗\nGeorge can handle?\n\n465\n00:28:57,000 --> 00:28:58,270\n如果是的话 好 把它交给George处理\nIf so, send it off to George.\n\n466\n00:28:59,410 --> 00:29:01,760\n它是Martha能操作的那一种吗\nIs it the kind of complex number that Martha can handle?\n\n467\n00:29:01,820 --> 00:29:04,060\n是的话 把它交给Martha处理\nIf so, send it off to Martha.\n\n468\n00:29:05,040 --> 00:29:08,720\n这个系统真正恼人之处 也就是这个系统的瓶颈\nSo it's really annoying that the bottleneck in this system,\n\n469\n00:29:08,720 --> 00:29:11,660\n它降低灵活性 阻碍变化\nthe thing that's preventing flexibility and change,\n\n470\n00:29:12,090 --> 00:29:14,360\n完全是一种的官僚主义\nis completely in the bureaucracy.\n\n471\n00:29:15,000 --> 00:29:17,020\n而不是任何做实事的人\nIt's not in anybody who's doing any of the work.\n\n472\n00:29:19,700 --> 00:29:21,800\n很可惜这种情况经常发生\nNot an uncommon situation, unfortunately.\n\n473\n00:29:23,180 --> 00:29:24,410\n实际上发生的事情是\nSee, what's really going on--\n\n474\n00:29:24,480 --> 00:29:26,970\n在系统中 有一张抽象的表格\nabstractly in the system, there's a table.\n\n475\n00:29:28,100 --> 00:29:30,080\n实际发生的事情是 有这样一张表格\nSo what's really happening is somewhere there's a table.\n\n476\n00:29:30,840 --> 00:29:33,640\n其中有各种类型\nThere're types.\n\n477\n00:29:34,400 --> 00:29:38,960\n有polar和rectangular\nThere's polar and rectangular.\n\n478\n00:29:41,550 --> 00:29:43,020\n可能Harry也在这里\nAnd Harry's may be over here.\n\n479\n00:29:44,380 --> 00:29:46,560\n然后这里是各种运算符\nAnd there are operators.\n\n480\n00:29:48,050 --> 00:29:58,240\n各种运算符 比如real-part和imag-part\nThere's an operator like real-part. Or imaginary-part.\n\n481\n00:30:00,010 --> 00:30:04,220\n还有magnitude、angle这些运算符\nOr a magnitude and angle.\n\n482\n00:30:05,830 --> 00:30:18,970\n单元格中对应的是相应过程\nAnd sitting in this table are the right procedures.\n\n483\n00:30:19,280 --> 00:30:21,990\n那么填在这里 负责polar类型的real-part过程的是\nSo sitting here for the type polar and real-part is\n\n484\n00:30:21,990 --> 00:30:27,560\nMartha的real-part-polar过程\nMartha's procedure real-part-polar.\n\n485\n00:30:30,570 --> 00:30:36,620\n然后在这里是George的real-part-rectangular过程\nAnd over here in the table is George's procedure real-part-rectangular.\n\n486\n00:30:37,740 --> 00:30:43,070\n然后这里是Martha的magnitude-polar过程\nAnd over here would be, say, Martha's procedure magnitude-polar,\n\n487\n00:30:44,460 --> 00:30:49,760\n然后是George的magnitude-rectangular过程 等等等等\nand George's procedure magnitude-rectangular, right, and so on.\n\n488\n00:30:49,760 --> 00:30:51,240\n剩下的单元格也像这样填好\nThe rest of this table's filled in.\n\n489\n00:30:52,390 --> 00:30:54,260\n这就是实际上发生的事情\nAnd that's really what's going on.\n\n490\n00:30:57,630 --> 00:31:01,740\n从某种意义上讲 经理做的事情就是\nSo in some sense, all the manager is doing\n\n491\n00:31:02,110 --> 00:31:04,110\n去扮演这张表格\nis acting as this table.\n\n492\n00:31:06,860 --> 00:31:08,700\n那我们怎么去修补这个系统呢\nWell how do we fix our system?\n\n493\n00:31:11,740 --> 00:31:13,770\n怎么去消灭这种官僚主义？\nWell, how do you fix bureaucracies a lot of the time?\n\n494\n00:31:13,770 --> 00:31:15,440\n你要做的就是让这个经理走人\nWhat you do is you get rid of the manager.\n\n495\n00:31:16,010 --> 00:31:19,550\n我们用一台计算机来代替他\nWe just take the manager and replace him by a computer.\n\n496\n00:31:20,170 --> 00:31:21,760\n我们要让自动操作抹掉他存在的意义\nWe're going to automate him out of existence.\n\n497\n00:31:23,320 --> 00:31:26,570\n也就是说 我们不用这个经理去查阅这个表格\nNamely, instead of having the manager who basically consults this table,\n\n498\n00:31:27,450 --> 00:31:29,320\n而是让我们的系统直接去查阅它\nwe'll have our system use the table directly.\n\n499\n00:31:31,020 --> 00:31:32,110\n这是什么意思呢？\nWhat do I mean by that?\n\n500\n00:31:32,110 --> 00:31:36,190\n我们来假设 还是用数据抽象的观点\nLet's assume, again using data abstraction,\n\n501\n00:31:37,710 --> 00:31:40,400\n我们有这样一种表格数据结构\nthat we have some kind of data structure that's a table.\n\n502\n00:31:40,880 --> 00:31:43,610\n而且我们还有把东西填进去和从中删除的方法\nAnd we have ways of sticking things in and ways of getting things out.\n\n503\n00:31:44,350 --> 00:31:49,040\n为了把话说清楚 我们假设现在有一个叫put的方法\nAnd to be explicit, let me assume that there's an operation called \"put.\"\n\n504\n00:31:50,300 --> 00:31:58,320\n本例中put方法接受两个参数 -- 我们称其为“关键字” -- key1和key2\nAnd put is going to take, case two things I'll call \"keys.\" key1 and key2.\n\n505\n00:32:00,130 --> 00:32:00,992\n还有接受一个值\nAnd a value.\n\n506\n00:32:06,200 --> 00:32:11,120\nput过程把value存放在表格key1和key2对应的格子里\nAnd that stores the value in the table under key1 and key2.\n\n507\n00:32:11,490 --> 00:32:13,168\n然后我们假设有另一个叫get的过程\nAnd then we'll assume there's a thing called \"get,\"\n\n508\n00:32:15,232 --> 00:32:18,720\n它是这样的一个东西 如果我说把表格里\nsuch that if later on I say, get me what's in the table\n\n509\n00:32:19,408 --> 00:32:22,768\n存储在key1和key2对应的格子中的数据给我\nstored under key1 and key2,\n\n510\n00:32:23,408 --> 00:32:25,392\n它会把存储在那里的东西返回给我\nit'll retrieve whatever value was stored there.\n\n511\n00:32:26,730 --> 00:32:29,440\n我们先不要担心这个表格怎么实现\nAnd let's not worry about how tables are implemented.\n\n512\n00:32:30,000 --> 00:32:32,528\n那又是另一个数据抽象了 是George需要考虑的问题\nThat's yet another data abstraction, George's problem.\n\n513\n00:32:33,060 --> 00:32:34,368\n也许稍后我们还会看到\nAnd maybe we'll see later--\n\n514\n00:32:34,700 --> 00:32:36,970\n我们还会讨论怎么用Lisp建立这个表格\ntalk about how you might actually build tables in Lisp.\n\n515\n00:32:40,710 --> 00:32:45,504\n我们有了这个组织结构 George和Martha需要做什么呢？\nWell given this organization,what did George and Martha have to do?\n\n516\n00:32:47,380 --> 00:32:49,072\n当他们构建自己的系统的时候\nWell when they build their system,\n\n517\n00:32:49,130 --> 00:32:51,088\n都有责任在表格里\nthey each have the responsibility\n\n518\n00:32:51,440 --> 00:32:53,820\n正确地添加上自己的那一列\nto set up their appropriate column in the table.\n\n519\n00:32:55,210 --> 00:32:57,472\n比如说 对于George\nSo what George does, for example,\n\n520\n00:32:59,790 --> 00:33:02,064\n当他定义过程的时候 他需要做的就是\nwhen he defines his procedures all he has to do\n\n521\n00:33:02,272 --> 00:33:07,990\n把它们放进表格中的rectangular类型的那一列下面\nis go off and put into the table under the type-rectangular.\n\n522\n00:33:09,820 --> 00:33:12,128\n然后操作的名字是real-part\nAnd the name of the operation is real-part,\n\n523\n00:33:13,312 --> 00:33:15,264\n放入他的real-part-rectangular过程\nhis procedure real-part-rectangular.\n\n524\n00:33:16,250 --> 00:33:17,780\n注意有什么被放到了表格里\nSo notice what's going into this table.\n\n525\n00:33:17,780 --> 00:33:22,100\n这里的两个key是这两个符号：rectangular和real-part\nThe two keys here are symbols, rectangular and real-part.\n\n526\n00:33:22,100 --> 00:33:22,752\n这是引用\nThat's the quote.\n\n527\n00:33:24,400 --> 00:33:26,752\n要被填到表里的东西\nAnd what's going into the table is the actual \n\n528\n00:33:26,848 --> 00:33:29,216\n是他编写的real-part-rectangular过程\nprocedure that he wrote, real-part rectangular.\n\n529\n00:33:31,856 --> 00:33:34,304\n然后把这个获取虚部的过程也放进表里\nAnd then puts an imaginary part into the table, \n\n530\n00:33:34,592 --> 00:33:37,808\n分类到rectangular和imag-part两个关键字之下\nfiled under the keys rectangular and imaginary-part,\n\n531\n00:33:38,620 --> 00:33:42,880\n获取模值的过程放到rectangular和magnitude下面\nand magnitude under the keys rectangular magnitude,\n\n532\n00:33:43,616 --> 00:33:45,200\n获取辐角的过程放到rectangular和angle下面\nangle under rectangular-angle.\n\n533\n00:33:47,040 --> 00:33:50,840\nGeorge作为系统的一部分 就要做以上这些事情\nOkay? So that's what George has to do to be part of this system.\n\n534\n00:33:54,420 --> 00:33:58,864\nMartha用同样的方法填好表格中关于polar的这一列\nMartha similarly sets up the column and the table under polar.\n\n535\n00:33:59,430 --> 00:34:00,656\n在polar和real-part对应的这一栏\nPolar and real-part.\n\n536\n00:34:01,696 --> 00:34:03,584\n应该填的过程是real-part-polar是吧？\nRight? Is the procedure real-part-polar?\n\n537\n00:34:04,340 --> 00:34:07,296\n然后分别是imag-part、magnitude和angle过程\nAnd imaginary-part, and magnitude, and angle.\n\n538\n00:34:08,912 --> 00:34:11,400\nMartha想要加入系统当中就要做这些事情\nSo this is what Martha has to do to be part of the system.\n\n539\n00:34:11,400 --> 00:34:13,550\n每个设计了数据表示的人\nEveryone who makes a representation has the\n\n540\n00:34:13,550 --> 00:34:17,632\n都必须在表格里设置自己的一列\nresponsibility for setting up a column in the table.\n\n541\n00:34:17,760 --> 00:34:19,900\n那么Harry带着他的绝妙的复数实现方法\nAnd what does Harry do when Harry comes in with his\n\n542\n00:34:19,900 --> 00:34:21,800\n过来的时候 他需要做什么呢\nbrilliant idea for implementing complex numbers?\n\n543\n00:34:21,800 --> 00:34:23,968\n他先把过程写好\nWell he makes whatever procedure he wants and\n\n544\n00:34:24,048 --> 00:34:26,520\n然后在表格里再建立一列\nbuilds a new column in this table.\n\n545\n00:34:28,550 --> 00:34:30,048\n那么现在经理怎么样了呢\nOK, well what happened to the manager?\n\n546\n00:34:31,330 --> 00:34:34,610\n经理的存在被自动操作所取代\nThe manager has been automated out of existence and is\n\n547\n00:34:34,610 --> 00:34:37,110\n被一个叫做operate的过程代替\nreplaced by a procedure called operate.\n\n548\n00:34:37,110 --> 00:34:39,552\n这是这个系统最关键的一个过程\nAnd this is the key procedure in the whole system.\n\n549\n00:34:40,380 --> 00:34:45,920\n(define operate\nLet's say define operate.\n\n550\n00:34:51,060 --> 00:34:56,096\nOperate过程接收你想要采取的运算\nOperate is going to take an operation that you want to do,\n\n551\n00:34:57,750 --> 00:34:58,880\n应该说是这个运算的名字\nthe name of an operation,\n\n552\n00:34:59,200 --> 00:35:03,280\n和被运算的对象\nand an object that you would like to apply that operation to.\n\n553\n00:35:04,210 --> 00:35:09,760\n那么举例来说 对一个复数调用real-part operate过程会做什么呢\nSo for example, the real-part of some particular complex number, what does it do?\n\n554\n00:35:09,952 --> 00:35:11,904\n它要做的第一件事就是去查表\nWell the first thing it does, it looks in the table.\n\n555\n00:35:12,640 --> 00:35:13,872\n它查询这个表格\nGoes into the table\n\n556\n00:35:14,800 --> 00:35:22,560\n试图去找到存储在表格里的一个过程\nand tries to find a procedure that's stored in the table.\n\n557\n00:35:23,152 --> 00:35:24,800\n所以它要对表格调用get过程\nSo it gets from the table,\n\n558\n00:35:25,504 --> 00:35:33,920\n用对象的类型和运算的名称作为关键字进行检索\nusing as keys the type of the object and the operator,\n\n559\n00:35:38,920 --> 00:35:40,144\n这样就可以知道在表格中\nbut looks on the table and sees\n\n560\n00:35:40,384 --> 00:35:42,720\n与数据的类型和要进行的运算相对应的是什么了\nwhat's stored under the type of the object and the operator\n\n561\n00:35:42,896 --> 00:35:44,352\n对应的这一格里填了什么东西\nsees if anything's stored.\n\n562\n00:35:44,440 --> 00:35:45,930\n我们假设get过程已经被实现好了\nLet's assume that get is implemented.\n\n563\n00:35:45,930 --> 00:35:47,728\n所以如果在那一格什么也没有\nSo if nothing is stored there,\n\n564\n00:35:48,112 --> 00:35:51,792\n它就会返回一个空表\nit'll return a nil, return the empty list.\n\n565\n00:35:52,672 --> 00:35:55,392\n如果那里确实有什么东西\nSo it says, if there's actually something stored there,\n\n566\n00:35:56,620 --> 00:36:00,432\n如果存储有这样的一个过程\nif the procedure here is not no,\n\n567\n00:36:03,150 --> 00:36:07,120\n那么就会把在表格里找到的这个过程\nthen it'll take the procedure that it found in the table\n\n568\n00:36:09,792 --> 00:36:15,008\n应用到对象的具体内容上去\nprocedure that it found in the table and apply it to the contents of the object.\n\n569\n00:36:18,256 --> 00:36:20,400\n如果那里没有东西的话\nAnd otherwise if there was nothing stored there,\n\n570\n00:36:20,672 --> 00:36:22,512\n它就会 -- 我们可以决定\nit'll-- well we can decide.\n\n571\n00:36:22,816 --> 00:36:27,120\n本例中 我们让它输出一个错误消息：“未定义的运算符”\nIn this case let's have it put out an error message saying, undefined operator.\n\n572\n00:36:28,480 --> 00:36:30,240\n没有支持这种类型的运算符\nNo operator for this type.\n\n573\n00:36:33,072 --> 00:36:34,720\n或者其它合适的错误信息\nOr some appropriate error message.\n\n574\n00:36:39,072 --> 00:36:39,488\n对吧？\nOK?\n\n575\n00:36:39,728 --> 00:36:41,040\n这个东西替代了经理\nAnd that replaces the manager.\n\n576\n00:36:41,890 --> 00:36:42,912\n我们怎么去使用它呢\nHow do we really use it?\n\n577\n00:36:43,960 --> 00:36:49,808\n我们的想法是用operate过程来定义通用选择函数\nWell what we say is we'll go off and define our generic selectors using operate.\n\n578\n00:36:50,040 --> 00:36:56,752\n我们可以说一个对象的real-part\nWe'll say that the real-part of an object is found by\n\n579\n00:36:57,140 --> 00:37:05,664\n是这个对象被operate应用了叫做real-part的运算后得到的结果\noperating on the object with the name of the operation being real-part.\n\n580\n00:37:08,070 --> 00:37:12,224\n那么类似地 imag-part是operate对obj应用imag-part运算\nAnd then similarly, imaginary-part is operate using the name imaginary-part\n\n581\n00:37:12,224 --> 00:37:13,984\nmagnitude和angle同理\nand magnitude and angle.\n\n582\n00:37:15,360 --> 00:37:17,430\n这就是我们的实现方法\nThat's our implementation.\n\n583\n00:37:17,430 --> 00:37:20,480\n由它们加上类型再加上operate过程组成\nThat plus the type plus the operate procedure.\n\n584\n00:37:21,330 --> 00:37:24,000\n这个表格现在就有效地完成了之前经理的工作\nAnd the table effectively replaces what the  manager used to do.\n\n585\n00:37:24,064 --> 00:37:27,696\n我们来梳理一下在这个过程中发生的事情\nLet's just go through that slowly to show you what's going on.\n\n586\n00:37:27,900 --> 00:37:33,000\n假设我有一个由Martha构造的复数\nSuppose I have one of Martha's complex numbers.\n\n587\n00:37:33,536 --> 00:37:38,800\n它的模值是1 辐角是2\nIt's got magnitude 1 and angle 2.\n\n588\n00:37:39,100 --> 00:37:40,220\n它是由Martha构造的\nAnd it's one of Martha's.\n\n589\n00:37:40,220 --> 00:37:45,456\n所以它被贴上了polar的标签\nSo it's labeled here, polar.\n\n590\n00:37:47,248 --> 00:37:48,000\n我们叫它z\nLet's call that z.\n\n591\n00:37:48,000 --> 00:37:48,912\n假设这就是z\nSuppose that's z.\n\n592\n00:37:51,770 --> 00:37:54,464\n然后假设在这种实现方法下\nAnd suppose with this implementation someone comes up\n\n593\n00:37:54,800 --> 00:37:57,920\n有人想要取z的实部\nasks for the real-part of z.\n\n594\n00:38:04,870 --> 00:38:07,968\n由于real-part现在是用operate来定义的\nWell real-part now is defined in terms of operate.\n\n595\n00:38:09,160 --> 00:38:10,576\n这就等同于说\nSo that's equivalent to saying\n\n596\n00:38:12,096 --> 00:38:24,816\n调用 (operate 'real-part z)\noperate with the name of the operator being real-part, the symbol real-part on z.\n\n597\n00:38:27,060 --> 00:38:28,090\n然后operate过程\nAnd now operate comes.\n\n598\n00:38:28,090 --> 00:38:29,248\n就会去查询表格\nIt's going to look in the table,\n\n599\n00:38:31,040 --> 00:38:34,368\n然后试图去寻找在表格里存放的\nand it's going to try and find something stored under--\n\n600\n00:38:39,008 --> 00:38:46,220\n查询表格中与对象的类型相对应的一列\nthe operation is going to apply by looking in the table under the type of the object.\n\n601\n00:38:46,720 --> 00:38:48,224\n那么z的类型是polar\nAnd the type of z is polar.\n\n602\n00:38:48,790 --> 00:38:51,376\n所以它就要说 我用polar作为关键字查表\nSo it's going to look and say, can I get using polar?\n\n603\n00:38:52,990 --> 00:38:58,576\n然后运算的名称是real-part\nAnd the operation name, which was real-part.\n\n604\n00:39:05,960 --> 00:39:13,632\n它查询对应的过程 然后应用到z的内容上去\nIt's going to look in there and apply that to the contents of z.\n\n605\n00:39:14,830 --> 00:39:17,136\n如果所有东西都安排妥当的话\nWhat's that is if everything was set up correctly,\n\n606\n00:39:17,744 --> 00:39:21,700\n如果它找到的过程就是Martha编写的过程\nthis thing is the procedure that Martha put there.\n\n607\n00:39:21,700 --> 00:39:22,950\n也就是real-part-polar\nThis is real-part-polar.\n\n608\n00:39:31,056 --> 00:39:35,130\n然后这就是z去掉类型之后的东西\nAnd this is z without its type.\n\n609\n00:39:35,440 --> 00:39:38,944\n是Martha最初设计的数据表示\nThe thing that Martha originally designed those procedures to work on,\n\n610\n00:39:39,408 --> 00:39:40,432\n也就是这里的(1 2)\nwhich is 1, 2.\n\n611\n00:39:43,710 --> 00:39:45,872\n所以说在整个系统中 operate过程\nAnd so operate sort of does uniformly\n\n612\n00:39:46,464 --> 00:39:48,896\n和之前的经理做的事情没什么区别\nwhat the manager used to do sort of all over the system.\n\n613\n00:39:49,450 --> 00:39:52,592\n它通过查询表格找到正确的东西  然后剥离类型\nIt finds the right thing, looks in the table, strips off the type,\n\n614\n00:39:53,584 --> 00:39:57,520\n然后把它传递给能够处理它的人\nand passes it down into the person who handles it.\n\n615\n00:39:58,880 --> 00:40:05,488\n你会发现 这是另一种 在大多数情况下\nThis is another, and, you can see, more flexible for most purposes,\n\n616\n00:40:06,224 --> 00:40:08,048\n更灵活地实现通用运算符的方法\nway of implementing generic operators.\n\n617\n00:40:08,080 --> 00:40:15,696\n我们把它叫做“数据导向编程”\nAnd it's called data-directed programming.\n\n618\n00:40:20,350 --> 00:40:21,968\n其理念是\nAnd the idea of that is\n\n619\n00:40:23,424 --> 00:40:25,552\n在某种意义上 这些数据对象本身\nAnd the idea of that is in some sense the data objects themselves,\n\n620\n00:40:26,048 --> 00:40:28,352\n这些充斥在系统中的复数\nthose little complex numbers that are floating around the system,\n\n621\n00:40:28,736 --> 00:40:33,168\n它们自身就携带着 关于应该怎么去操作它们的信息\nare carrying with them the information about how you should operate on them.\n\n622\n00:40:35,744 --> 00:40:36,784\n有什么疑问吗？\nLet's break for questions.\n\n623\n00:40:41,000 --> 00:40:41,240\n请说\nYes.\n\n624\n00:40:41,240 --> 00:40:43,390\n学生：你在那个数据对象里存储的是什么呢\nAUDIENCE: What do you have stored in that data object?\n\n625\n00:40:43,390 --> 00:40:47,104\n这里面有这个数据本身 还有它的类型\nYou have the data itself, you have its type,\n\n626\n00:40:47,100 --> 00:40:49,600\n还有该与该类型对应的运算\nthe operations for that type?\n\n627\n00:40:49,690 --> 00:40:53,088\n或者说那些运算是存储在哪里呢？\nOr where are the operations that you found?\n\n628\n00:40:53,600 --> 00:40:54,176\n教授：好 让我--\nPROFESSOR: OK, let me--\n\n629\n00:40:54,980 --> 00:40:56,500\n恩 这是一个好问题\nyeah, that's a good question.\n\n630\n00:40:56,500 --> 00:41:00,464\n通过它暗示了实现我们目标的 其它可行方法\nBecause it raises other possibilities of how you might do it.\n\n631\n00:41:00,750 --> 00:41:02,480\n当然可能的方法有很多\nAnd of course there are a lot of possibilities.\n\n632\n00:41:04,200 --> 00:41:06,144\n在这个特定的实现当中\nIn this particular implementation,\n\n633\n00:41:06,240 --> 00:41:09,728\n在这个数据对象里放着\nwhat's sitting in this data object, for example,\n\n634\n00:41:10,448 --> 00:41:13,456\n就是数据本身 本例中是序对(1, 2)\nis the data itself-- which in this case is a pair of 1 and 2--\n\n635\n00:41:14,980 --> 00:41:16,550\n和一个符号\nand also a symbol.\n\n636\n00:41:16,550 --> 00:41:19,072\n就是这个符号 单词P-O-L-A-R\nThis is the symbol, the word P-O-L-A-R,\n\n637\n00:41:20,600 --> 00:41:22,336\n这些就是这个数据对象里面的东西\nAnd that what's sitting in this data object.\n\n638\n00:41:24,240 --> 00:41:26,690\n那么这些运算又是存放在哪里的呢？\nOK, where are the operations themselves?\n\n639\n00:41:26,690 --> 00:41:29,008\n那些运算在表格里\nThe operations are sitting in the table.\n\n640\n00:41:29,850 --> 00:41:31,072\n在这个表格里\nSo in this table,\n\n641\n00:41:32,304 --> 00:41:36,464\n所有行和列的名字都是符号\nthe rows and columns of the table are labeled by symbols.\n\n642\n00:41:38,230 --> 00:41:40,080\n所以当我往里面存什么东西的时候\nSo when I store something in this table,\n\n643\n00:41:40,096 --> 00:41:47,020\n可以以符号polar或符号magnitude作为关键字\nthe key might be the symbol polar and the symbol magnitude.\n\n644\n00:41:48,240 --> 00:41:51,310\n我这样写 可能让你们感到困惑了\nAnd I think by writing it this way I've been very confusing.\n\n645\n00:41:51,310 --> 00:41:52,704\n因为在这里面放的并不是\nBecause what's really sitting here isn't--\n\n646\n00:41:53,160 --> 00:41:54,576\n当我写下mag-polar的时候\nwhen I wrote magnitude polar,\n\n647\n00:41:57,040 --> 00:41:59,230\n我指的是那个叫mag-polar的过程\nwhat I mean is the procedure magnitude polar.\n\n648\n00:41:59,850 --> 00:42:01,856\n可能 我本来应该在这里写上\nAnd probably what I really should have written--\n\n649\n00:42:02,580 --> 00:42:04,200\n但是这里空间太小了\nexcept it's too small for me to write\n\n650\n00:42:04,200 --> 00:42:05,072\n我写不下\nin this little space--\n\n651\n00:42:05,580 --> 00:42:08,928\n应该写成lambda(z)\nis something like lambda of z,\n\n652\n00:42:10,608 --> 00:42:12,750\n然后调用Martha实现的过程\nthe thing that Martha wrote to implement.\n\n653\n00:42:14,710 --> 00:42:15,728\n你也可以从这里看出\nAnd then you can see from that,\n\n654\n00:42:15,744 --> 00:42:17,440\n我已经暗示了另一种方法\nthere's another way that I alluded to\n\n655\n00:42:17,712 --> 00:42:19,824\n来解决名字冲突的问题\nof solving this name conflict problem\n\n656\n00:42:20,048 --> 00:42:23,150\n那就是George和Martha根本不用给他们的过程起名字\nwhich is that George and Martha never have to name their procedures at all.\n\n657\n00:42:23,150 --> 00:42:25,376\n可以直接把由lambda定义的\nThey can just stick the lambda, the lambda...\n\n658\n00:42:25,392 --> 00:42:28,120\n由lambda定义的匿名函数放进表格里\nthe anonymous things generated by lambda directly into the table.\n\n659\n00:42:28,660 --> 00:42:31,760\n你的问题还引出了另一种可能性\nThere's also another thing that your question raises,\n\n660\n00:42:32,350 --> 00:42:34,064\n也就是\nis the possibility that maybe\n\n661\n00:42:34,830 --> 00:42:37,920\n可能我在这个数据对象里存储的\nwhat I would like somehow is to store in this data object\n\n662\n00:42:37,952 --> 00:42:39,480\n不是符号POLAR\nnot the symbol P-O-L-A-R but\n\n663\n00:42:39,936 --> 00:42:42,352\n也许是这些运算本身\nmaybe actually all the operations themselves.\n\n664\n00:42:43,900 --> 00:42:45,632\n这是组织系统的另一种方法\nAnd that's another way to organize the system,\n\n665\n00:42:45,664 --> 00:42:46,608\n叫做“消息传递”\ncalled message passing.\n\n666\n00:42:48,650 --> 00:42:49,920\n它们都殊途同归\nSo there are a lot of ways you can do it.\n\n667\n00:42:54,640 --> 00:42:58,040\n学生：所以说如果Martha和George\nAUDIENCE: Therefore if Martha and George had used the same\n\n668\n00:42:58,040 --> 00:43:01,230\n用了相同的过程名字也没什么问题\nprocedure names, it would be OK because it wouldn't look\n\n669\n00:43:01,230 --> 00:43:02,560\n[听不清]\nit wouldn't look into it\n\n670\n00:43:02,560 --> 00:43:04,688\n教授：对 你说得很对\nPROFESSOR: That's right.That's right.\n\n671\n00:43:04,800 --> 00:43:07,856\n看 他们甚至根本不需要给他们的过程命名\nSee, they wouldn't even have to name their procedures at all.\n\n672\n00:43:08,040 --> 00:43:09,360\nGeorge和Martha可以 --\nWhat George and Martha could writ --,\n\n673\n00:43:09,500 --> 00:43:10,624\nGeorge可以这么来做\nwhat George could have written\n\n674\n00:43:10,832 --> 00:43:15,280\n与其在rectangular和real-part对应的格子里放\ninstead of saying put in the table under rectangular- and real-part,\n\n675\n00:43:16,220 --> 00:43:17,984\n存放real-part-rectangular这个过程\nthe procedure real-part rectangular,\n\n676\n00:43:18,032 --> 00:43:21,152\nGeorge可以在rectangular和real-part对应的格子里放\nGeorge could have written put under rectangular real-part,\n\n677\n00:43:21,248 --> 00:43:23,696\n放一个lambda(z) 然后什么什么\nlambda of z, such and such, such and such,\n\n678\n00:43:24,540 --> 00:43:26,848\n整个系统会以完全相同的方式工作\nAnd the system would work completely the same.\n\n679\n00:43:27,330 --> 00:43:29,248\n学生：我的问题是 就算Martha在\nAUDIENCE: My question is, Martha could put\n\n680\n00:43:29,840 --> 00:43:33,600\nMartha在key1和key2对应的格子里放了real-part过程\ncould have put key1 key2 real-part,\n\n681\n00:43:33,952 --> 00:43:37,648\nGeorge也在key1和key2下放了一个real-part过程\nand George could have put key1 key2 real-part,\n\n682\n00:43:37,960 --> 00:43:39,600\n只要两个过程的定义不一样\nand as long as they defined them differently\n\n683\n00:43:39,808 --> 00:43:41,264\n它们就不会发生任何冲突 对吗？\nthey wouldn't have had any conflicts, right?\n\n684\n00:43:41,290 --> 00:43:43,808\n教授：对的 这完全没有问题\nPROFESSOR: Yes, that would all be OK except for the fact\n\n685\n00:43:44,976 --> 00:43:47,130\n除非你说的是George和Martha在同一个终端上工作\nthat if you imagine George and Martha typing at the same\n\n686\n00:43:47,130 --> 00:43:49,200\n并且他们两个人起的所有名字的含义全部相同\nconsole with the same meanings for all their names,\n\n687\n00:43:49,820 --> 00:43:51,232\n那么同样的real-part就会造成困扰\nand it would get confused by real-part,\n\n688\n00:43:51,248 --> 00:43:52,800\n但是就算是这种情况也有办法解决\nbut there are ways to arrange that, too.\n\n689\n00:43:52,800 --> 00:43:54,800\n从原则上讲你说的完全正确\nAnd in principle you're absolutely right.\n\n690\n00:43:54,980 --> 00:43:56,290\n如果它们的名字不互相冲突的话\nIf their names didn't conflict--\n\n691\n00:43:56,290 --> 00:43:58,190\n被填到表里的是对象本身 而不是它们的名字\nit's the objects that go in the table, not the names.\n\n692\n00:44:08,200 --> 00:44:09,056\n好 我们休息一下\nOK, let's take a break.\n\n693\n00:44:12,912 --> 00:44:20,480\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n694\n00:44:20,960 --> 00:44:23,296\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n695\n00:44:23,450 --> 00:44:25,296\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n696\n00:44:57,420 --> 00:45:05,072\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n697\n00:45:05,470 --> 00:45:09,248\n通用运算符\nGeneric Operators\n\n\n698\n00:45:12,880 --> 00:45:16,880\n教授：好的 我们刚刚讲了一个数据导向编程的例子\nRPOFESSOR: All right, well we just looked at data-directed programming\n\n699\n00:45:17,680 --> 00:45:22,840\n我们将其用于实现一个复数域上的算术系统\nas a way of implementing a system that does arithmetic on complex numbers.\n\n700\n00:45:27,600 --> 00:45:32,480\n我已经在里面实现了 +c -c 这些运算\nSo I had these operations in it called plus C and minus C,\n\n701\n00:45:32,880 --> 00:45:37,248\n*c \\c 还有其它的一些过程\nand multiply, and divide,and maybe some others.\n\n702\n00:45:38,230 --> 00:45:45,728\n这些过程存在于上层 -- 这是关键之处\nAnd that sat on top of-- and this is the key point--\n\n703\n00:45:45,740 --> 00:45:49,600\n它们存在于两种不同表示方式的上层\nsat on top of two different representations.\n\n704\n00:45:50,340 --> 00:45:55,440\n这是一个直角坐标程序包 这里一个极坐标程序包\nA rectangular package here, and a polar package.\n\n705\n00:45:58,144 --> 00:45:59,150\n可能还有其它的东西\nAnd maybe some more.\n\n706\n00:45:59,150 --> 00:46:02,800\n关键理念就是 “其它的东西”可以很容易地添加上去\nAnd we saw that the whole idea is that maybe some more are now very easy to add.\n\n707\n00:46:04,670 --> 00:46:08,352\n但是这并没有真正体现出这种方法学的威力\nBut that doesn't really show the power of this methodology.\n\n708\n00:46:08,900 --> 00:46:10,150\n我们看看发生了什么\nShows you what's going on.\n\n709\n00:46:10,150 --> 00:46:12,336\n这个方法的威力 只有当你\nThe power of the methodology only becomes apparent\n\n710\n00:46:12,944 --> 00:46:15,792\n当你把它嵌入于一些更复杂的系统中时才会显现\nwhen you start embedding this in some more complex system.\n\n711\n00:46:16,170 --> 00:46:17,744\n我现在要做的就是\nSo let... What I'm going to do now\n\n712\n00:46:17,872 --> 00:46:20,016\n把它嵌入一个更复杂的系统中\nis embed this in some more complex system.\n\n713\n00:46:20,250 --> 00:46:25,280\n假设我们已经有了一个通用算术系统\nLet's assume that what we really have is a general kind of arithmetic system.\n\n714\n00:46:25,280 --> 00:46:27,240\n所谓的“通用算术系统”\nSo called generic arithmetic system.\n\n715\n00:46:27,240 --> 00:46:28,544\n然后在系统的最顶层\nAnd at the top level here,\n\n716\n00:46:30,760 --> 00:46:35,920\n用户可以命令它把两个东西相加 或者相减\nsomebody can say add twothings, or subtract two things,\n\n717\n00:46:37,456 --> 00:46:41,056\n或者让两数相乘、相除\nor multiply two  things, or divide two things.\n\n718\n00:46:44,140 --> 00:46:46,528\n然后在它们下面是一个抽象屏障\nAnd underneath that there's an abstraction barrier.\n\n719\n00:46:47,930 --> 00:46:49,152\n抽象屏障的下层\nAnd underneath this barrier,\n\n720\n00:46:49,504 --> 00:46:52,480\n是一个复数域算术程序包\nis, say, a complex arithmetic package.\n\n721\n00:46:53,024 --> 00:46:54,960\n然后你可以让它把两个复数相加\nAnd you can say, add two complex numbers.\n\n722\n00:46:55,040 --> 00:46:58,832\n或者你还可以把 有理数域算术程序包\nOr you might also have--remember we did a rational number package\n\n723\n00:46:58,880 --> 00:46:59,936\n给安装进来\nyou might have that sitting there.\n\n724\n00:47:00,190 --> 00:47:01,728\n可以放进去有理数\nAnd there might be a rational thing.\n\n725\n00:47:04,768 --> 00:47:06,224\n然后有理数程序包里面\nAnd the rational number package,\n\n726\n00:47:07,168 --> 00:47:14,752\n有我们实现的 +rat、*rat等等的这些过程\nwell, has the things we implemented. Plus rat, and times rat, and so on.\n\n727\n00:47:15,392 --> 00:47:17,010\n或者你还可以加上通常的Lisp算术系统\nOr you might have ordinary Lisp numbers.\n\n728\n00:47:17,010 --> 00:47:18,992\n你可以让它把3和4加起来\nYou might say add three and four.\n\n729\n00:47:19,420 --> 00:47:20,944\n那么我们在这个系统里加入通常的算术系统\nSo we might have ordinary numbers,\n\n730\n00:47:28,288 --> 00:47:34,672\n其中有Lisp自带的 + - * /\nin which case we have the Lisp supplied plus, and minus, and times, and slash.\n\n731\n00:47:36,670 --> 00:47:39,120\n总而言之 我们可以想象这个复数系统\nOK, so we might imagine this complex number system\n\n732\n00:47:39,440 --> 00:47:44,448\n存在于一个更加复杂的通用运算系统里面\nsitting in a more complicated generic operator structure at the next level up.\n\n733\n00:47:47,730 --> 00:47:48,736\n我们怎么才能做到呢\nWell how can we make that?\n\n734\n00:47:49,050 --> 00:47:52,320\n我们已经有了想法 只要再一次应用它就可以了\nWe already have the idea, we're just going to do it again.\n\n735\n00:47:52,780 --> 00:47:54,720\n我们已经实现了一个有理数程序包\nWe've implemented a rational number package.\n\n736\n00:47:54,720 --> 00:47:56,896\n那么我们来看看应该怎么修改它\nLet's look at how it has to be changed.\n\n737\n00:48:01,488 --> 00:48:03,408\n实际上 在这个层面 它根本就不需要修改\nIn fact, at this level it doesn't have to be changed at all.\n\n738\n00:48:03,730 --> 00:48:05,888\n这完全就是我们上次写的那些代码\nThis is exactly the code that we wrote last time.\n\n739\n00:48:07,180 --> 00:48:08,976\n要把两个有理数相加\nTo add two rational numbers,\n\n740\n00:48:09,856 --> 00:48:10,912\n回忆一下 我们要用到这个公式\nremember there was this formula.\n\n741\n00:48:11,140 --> 00:48:13,376\n构造一个有理数 它的分子是\nYou make a rational number whose numerator--\n\n742\n00:48:13,984 --> 00:48:17,568\nx的分子乘以y的分母\nis the numerator of the first times the denominator of the second\n\n743\n00:48:17,936 --> 00:48:21,520\n加上 x的分母乘以y的分子\nplus the denominator of the first times the numerator of the second.\n\n744\n00:48:21,520 --> 00:48:23,792\n而结果的分母是 x的分母乘y的分母\nAnd who's denominator is the product of the denominators.\n\n745\n00:48:25,760 --> 00:48:29,072\n然后是-rat、*rat、/rat这些过程\nAnd minus rat, and star rat, and slash rat.\n\n746\n00:48:30,360 --> 00:48:35,120\n这就是我们之前写的那个有理数程序包\nAnd this is exactly the rational number package that we made before.\n\n747\n00:48:36,310 --> 00:48:38,896\n我们忽略最大公约数的问题 先不去考虑那个\nWe're ignoring the GCD problem,but let's not worry about that.\n\n748\n00:48:39,080 --> 00:48:42,592\n作为这个有理数包的实现人员\nHow do we install... As implementers of this rational number package,\n\n749\n00:48:42,800 --> 00:48:45,104\n怎么把它安装到我们的通用运算系统中呢？\nhow do we install it in the generic arithmetic system?\n\n750\n00:48:45,570 --> 00:48:46,224\n那很简单\nWell that's easy.\n\n751\n00:48:47,296 --> 00:48:51,568\n我们要做的事只有一件和之前不同\nGo off... There's only one thing we have to do differently.\n\n752\n00:48:51,840 --> 00:48:55,712\n在之前我们说构造一个有理数\nWhereas previously we said that to make a rational number\n\n753\n00:48:56,270 --> 00:48:59,984\n就是构造一个由分子分母组成的序对\nyou built a pair of the numerator and denominator,\n\n754\n00:49:00,960 --> 00:49:03,200\n现在我们不光构造这个序对 还要给它贴上标签\nhere we'll not only build the pair, but we'll sign it.\n\n755\n00:49:03,300 --> 00:49:04,560\n给它加上rational类型\nWe'll attach the type rational.\n\n756\n00:49:06,368 --> 00:49:08,096\n这就是唯一的不同之处\nThat's the only thing we have to do different,\n\n757\n00:49:08,560 --> 00:49:10,096\n把它变成带类型的数据\nmake it a typed data object.\n\n758\n00:49:12,380 --> 00:49:14,080\n现在 我们要把运算放进表格里\nAnd now we'll stick our operations in the table.\n\n759\n00:49:14,368 --> 00:49:18,208\n我们在rational符号和add运算对应的格子里\nWe'll put under the symbol rational and the operation add\n\n760\n00:49:18,920 --> 00:49:20,256\n放进我们的+rat过程\nour procedure -- +rat.\n\n761\n00:49:21,820 --> 00:49:23,248\n再次强调 这是一个符号\nAnd, again, note this is a symbol.\n\n762\n00:49:23,744 --> 00:49:23,930\n看到了么？\nRight?\n\n763\n00:49:24,030 --> 00:49:25,296\n这是引用 这也是引用\nQuote, and quote,\n\n764\n00:49:25,312 --> 00:49:28,016\n但是实际上放进表里的是+rat过程本身\nbut the actual thing we're putting in the table is the procedure.\n\n765\n00:49:29,824 --> 00:49:31,776\n然后怎么做减法\nAnd for how to subtract,\n\n766\n00:49:31,790 --> 00:49:36,816\n我们用-rat过程做减法\nwell you subtract rationals with minus rat.\n\n767\n00:49:38,270 --> 00:49:40,240\n然后是乘法和除法\nAnd multiply, and divide.\n\n768\n00:49:41,090 --> 00:49:43,640\n这些步骤精准地描述了 我们该怎么做\nAnd that is exactly and precisely what we have to do\n\n769\n00:49:44,144 --> 00:49:46,976\n来兼容这个通用算术系统\nto fit inside this generic arithmetic system.\n\n770\n00:49:48,510 --> 00:49:49,888\n那么整个系统怎么工作呢\nWell how does the whole thing work?\n\n771\n00:49:51,560 --> 00:49:58,400\n我们想实现的是通用运算符\nSee, what we want to do is have some generic operators.\n\n772\n00:49:59,344 --> 00:50:02,800\n为了让add、sub、mul和div变成通用运算符\nRight? Have add and sub and mul and div be generic operators.\n\n773\n00:50:03,990 --> 00:50:17,360\n所以我们要把add过程定义为 (ADD X Y)就是\nSo we're going to define add and say, to add x and y,\n\n774\n00:50:18,620 --> 00:50:22,128\n就是调用operate过程\nthat will be operate--\n\n775\n00:50:26,080 --> 00:50:27,490\n我们把这个叫做operate-2\nwe were going to call it operate-2.\n\n776\n00:50:27,490 --> 00:50:30,784\n这是我们的操作过程 但是要接收两个参数\nThis is our operator procedure, but set up for two arguments\n\n777\n00:50:31,600 --> 00:50:35,840\n对它们应用add 把它们加起来\nusing add on x and y.\n\n778\n00:50:37,600 --> 00:50:39,760\n这是和operate类似的一个东西\nAnd so this is the analog to operate.\n\n779\n00:50:40,420 --> 00:50:41,680\n我们再看看这个代码\nLet's look at the code for a second.\n\n780\n00:50:41,680 --> 00:50:42,930\n它和operate很相似\nIt's almost like operate.\n\n781\n00:50:45,792 --> 00:50:52,496\n为了将运算符运用在两个参数arg1和arg2上\nRight? To operate with some operator on an argument1 and an argument2\n\n782\n00:50:55,040 --> 00:50:56,656\n首要任务是\nwell the first thing we're going to do is check\n\n783\n00:50:56,832 --> 00:51:00,730\n检查这两个参数的类型是否相同\nand see if the two arguments have the same type.\n\n784\n00:51:01,900 --> 00:51:02,960\n所以我们要问\nSo we'll say,\n\n785\n00:51:02,992 --> 00:51:07,776\n第一个参数的类型和第二个的类型一样吗？\nis the type of the first argument the same as the type of the second argument?\n\n786\n00:51:10,350 --> 00:51:13,360\n如果不一样\nAnd if they're not, if they're not\n\n787\n00:51:13,580 --> 00:51:15,632\n我们就停止运行 然后抛出错误\nwe'll go off and complain, and say, that's an error.\n\n788\n00:51:15,670 --> 00:51:16,672\n我们不知道怎么对它们进行运算\nWe don't know how to do that.\n\n789\n00:51:19,140 --> 00:51:20,496\n如果它们的类型确实是相同的\nIf they do have the same type,\n\n790\n00:51:20,512 --> 00:51:22,080\n那就和之前一样了\nwe'll do exactly what we did before.\n\n791\n00:51:22,080 --> 00:51:26,460\n我们会查询在参数的类型对应的\nWe'll go look and filed under the type of the argument--\n\n792\n00:51:26,768 --> 00:51:29,616\n参数1和参数2是同样的类型 知道一个就可以\narg 1 and arg 2 have the same type, so it doesn't matter.\n\n793\n00:51:30,420 --> 00:51:32,592\n我们到表格里去查找对应的过程\nSo we'll look in the table, find the procedure.\n\n794\n00:51:33,640 --> 00:51:35,872\n如果找到这样一个过程\nIf there is a procedure there,\n\n795\n00:51:37,536 --> 00:51:41,744\n我们就将其应用在参数1和参数2的内容上\nthen we'll apply it to the contents of the arg1 and the contents of arg2.\n\n796\n00:51:43,030 --> 00:51:44,760\n如果是其它情况 就报错\nAnd otherwise we'll say, error.\n\n797\n00:51:44,760 --> 00:51:45,728\n“未定义运算符”\nUndefined operator.\n\n798\n00:51:46,890 --> 00:51:48,160\n这就是operate-2过程\nAnd so there's operate-2.\n\n799\n00:51:51,728 --> 00:51:54,032\n这就是我们要做的全部事情\nAnd that's all we have to do.\n\n800\n00:51:55,160 --> 00:51:57,456\n我们刚刚才写好了一个复数运算包\nWe just built the complex number package before.\n\n801\n00:51:57,640 --> 00:52:01,008\n那么怎么把它放进这个通用系统里面呢？\nHow do we embed that complex number package in this generic system?\n\n802\n00:52:02,140 --> 00:52:02,912\n方法几乎是一样的\nAlmost the same.\n\n803\n00:52:06,410 --> 00:52:08,592\n我们构造一个叫做make-complex的过程\nWe make a procedure called make-complex\n\n804\n00:52:09,952 --> 00:52:12,816\n它把George和Martha给我们的东西\nthat takes whatever George and Martha hand to us\n\n805\n00:52:13,648 --> 00:52:15,008\n贴上complex的类型标志\nand add the type complex.\n\n806\n00:52:18,170 --> 00:52:23,872\n然后我们说 要把复数相加 这个+complex过程\nAnd then we say, to add complex numbers, plus complex,\n\n807\n00:52:25,840 --> 00:52:28,784\n用我们的内部过程 +c\nwe use our internal procedure, plus c,\n\n808\n00:52:30,784 --> 00:52:32,240\n把结果加上类型\nand attach a type,\n\n809\n00:52:32,240 --> 00:52:33,424\n让它变成复数类型\nmake that a complex number.\n\n810\n00:52:37,680 --> 00:52:42,528\n那么我们的包里原来有+c和-c这两个过程\nSo our original package had names plus c and minus c\n\n811\n00:52:42,688 --> 00:52:44,752\n用来和George和Martha通信\nthat we're using to communicate with George and Martha.\n\n812\n00:52:45,250 --> 00:52:47,392\n然后为了与外部通信\nAnd then to communicate with the outside world,\n\n813\n00:52:47,408 --> 00:52:53,040\n我们还有+complex和-complex\nwe have a thing called plus-complex and minus-complex.\n\n814\n00:52:55,920 --> 00:52:56,530\n等等\nAnd so on.\n\n815\n00:52:56,530 --> 00:52:59,984\n它们唯一的不同就在于：后者的返回的是带类型的值\nAnd the only difference is that these return values that are typed\n\n816\n00:53:01,120 --> 00:53:02,416\n它们可以在这里被查询\nSo they can be looked at up here.\n\n817\n00:53:02,850 --> 00:53:05,024\n而这些是内部过程\nAnd these are internal operations.\n\n818\n00:53:09,250 --> 00:53:10,680\n我们再来看那个幻灯片\nLet's go look at that slide again.\n\n819\n00:53:10,680 --> 00:53:13,040\n我们还有一件事要做\nThere's one more thing we do.\n\n820\n00:53:13,740 --> 00:53:15,616\n在定义了+complex之后\nAfter defining plus-complex,\n\n821\n00:53:15,680 --> 00:53:20,528\n我们在complex类型和add符号对应的格子中\nwe put under the type complex and the symbol add,\n\n822\n00:53:21,312 --> 00:53:22,752\n填上过程+complex\nthat procedure plus complex.\n\n823\n00:53:23,200 --> 00:53:26,752\n对于-complex也类似\nAnd then similarly for subtracting complex numbers,\n\n824\n00:53:27,130 --> 00:53:29,130\n*complex和/complex亦如此\nand multiplying them, and dividing them.\n\n825\n00:53:31,700 --> 00:53:33,488\n那我们怎么安装寻常算术呢？\nOK, how do we install ordinary numbers?\n\n826\n00:53:35,250 --> 00:53:36,128\n方法还是一样的\nExactly the same way.\n\n827\n00:53:38,160 --> 00:53:41,360\n我们会写一个叫做make-number的过程\nCome off and say, well we'll make a thing called make-number\n\n828\n00:53:44,340 --> 00:53:48,112\nmake-number接收一个数 然后给它加上类型\nMake-number takes a number and attaches a type,\n\n829\n00:53:48,144 --> 00:53:49,296\n也就是符号number\nwhich is the symbol number.\n\n830\n00:53:50,260 --> 00:53:52,112\n我们构造一个过程叫做+number\nWe build a procedure called plus-number,\n\n831\n00:53:52,928 --> 00:53:58,752\n用Lisp自带的加法把两个数加起来\nwhich is simply, add the two things using the ordinary addition,\n\n832\n00:53:58,928 --> 00:54:00,784\n因为我们现在讨论的是寻常算术\nbecause in this case we're talking about ordinary numbers,\n\n833\n00:54:01,312 --> 00:54:03,104\n给它加上类型 让它变成number类型\nand attach a type to it and make that a number.\n\n834\n00:54:04,510 --> 00:54:08,096\n然后我们把+number过程放到\nAnd then we put into the table under the symbol number\n\n835\n00:54:08,592 --> 00:54:11,008\n表格里number和add对应的的格子中\nand the operation add, this procedure plus-number,\n\n836\n00:54:12,304 --> 00:54:16,160\n再用相同的方法把减法 乘法 除法也放进去\nand then the same thing for subtracting, and multiplying, and dividing.\n\n837\n00:54:22,672 --> 00:54:26,060\n我们举一个例子 就看得清楚一点\nLet's look at an example, just to make it clear.\n\n838\n00:54:26,060 --> 00:54:28,752\n假设 比如说\nSuppose, for instance,\n\n839\n00:54:32,288 --> 00:54:34,150\n我要执行这个运算\nI'm going to perform the operation.\n\n840\n00:54:34,150 --> 00:54:38,220\n好 现在我要执行一个运算\nSo I sit up here and I'm going to perform the operation,\n\n841\n00:54:38,220 --> 00:54:40,464\n比如说我把两个复数乘起来\nwhich looks like multiplying two complex numbers.\n\n842\n00:54:40,930 --> 00:54:48,640\n把3+4i和2+6i乘起来\nSo I would multiply, say, 3 plus 4i and 2 plus 6i.\n\n843\n00:54:50,170 --> 00:54:52,608\n这就是我调用mul过程要传入的参数\nAnd that's something that I might want to take hand that to mul.\n\n844\n00:54:52,840 --> 00:54:55,760\n这里就代表通用运算符mul\nI'll write mul as my generic operator here.\n\n845\n00:54:57,170 --> 00:54:57,984\n那么它怎么工作呢\nHow's that going to work?\n\n846\n00:54:58,280 --> 00:55:04,608\n我们讲3+4i 在整个系统里\nWell 3 plus 4i, say, sits in the system at this level\n\n847\n00:55:04,832 --> 00:55:06,112\n处于这样的一个位置\nas something that looks like this.\n\n848\n00:55:06,250 --> 00:55:07,520\n假设它是George那种方法表示的\nLet's say it was one of George's.\n\n849\n00:55:08,280 --> 00:55:14,976\n所以它的内部有一个3和一个4\nSo it would have a 3 and a 4.\n\n850\n00:55:18,490 --> 00:55:20,976\n这上面还贴着George的类型标志\nAnd attached to that would be George's type,\n\n851\n00:55:24,336 --> 00:55:28,320\n是他构造的rectangular类型\nwhich says rectangular, it came from George.\n\n852\n00:55:29,510 --> 00:55:30,576\n又附加在那上面的\nAnd attached to that--\n\n853\n00:55:31,230 --> 00:55:35,792\n从更上一层的视角来看这一段数据\nand this itself would be the data view from the next level up\n\n854\n00:55:36,192 --> 00:55:36,784\n它又是一个\nwhich it is--\n\n855\n00:55:37,936 --> 00:55:39,968\n这整个又是一个带类型的数据\nso that itself would be a type-data object\n\n856\n00:55:40,608 --> 00:55:41,808\n它的类型是complex\nwhich would say complex.\n\n857\n00:55:44,820 --> 00:55:47,312\n那么这就是这个对象\nSo that's what this object would look like\n\n858\n00:55:48,640 --> 00:55:50,240\n在最高层视角中的样子\nup here at the very highest level,\n\n859\n00:55:50,688 --> 00:55:53,568\n那些通用运算符看到的对象 就是这样的\nwhere the really super-generic operations are looking at it.\n\n860\n00:55:55,560 --> 00:55:58,720\n现在 mul过程会过来问\nNow what happens, mul eventually's going to come along\n\n861\n00:55:58,848 --> 00:56:00,400\n它的类型是什么？\nand say, oh,what's it's type?\n\n862\n00:56:00,480 --> 00:56:01,488\n它的类型是complex\nIt's type is complex.\n\n863\n00:56:04,270 --> 00:56:06,464\n然后运行到operate-2 然后说\nGo through to operate-2 and say,\n\n864\n00:56:06,460 --> 00:56:09,728\n啊 我想要把表格里的过程\noh, what I want to do is apply what's in the table,\n\n865\n00:56:09,720 --> 00:56:13,040\n也就是*complex这个过程\nwhich is going to be the procedure star complex,\n\n866\n00:56:15,088 --> 00:56:17,760\n应用到 将其类型剥离之后的结果上去\non this thing with the type stripped off.\n\n867\n00:56:17,950 --> 00:56:19,280\n所以它会把类型剥下来\nSo it's going to strip off the type,\n\n868\n00:56:19,936 --> 00:56:24,240\n把剩下的东西传递给复数的世界\ntake that much, and send that down into the complex world.\n\n869\n00:56:26,704 --> 00:56:28,736\n复数的世界看了看它有的运算操作 然后说\nThe complex world looks at its operations and says,\n\n870\n00:56:28,768 --> 00:56:30,560\n“我得调用*c这个过程”\noh, I have to apply star c.\n\n871\n00:56:31,280 --> 00:56:32,144\n然后*c过程说\nStar c might say,\n\n872\n00:56:32,224 --> 00:56:37,200\n我想知道这个东西的模值是多少\nat some point I want to look at the magnitude of this object that it's in, that it's got.\n\n873\n00:56:39,420 --> 00:56:40,160\n然后它们会说 啊\nAnd they'll say, oh, it's\n\n874\n00:56:40,160 --> 00:56:41,712\n它是直角坐标表示的 是George的东西\nrectangular, it's one of George's.\n\n875\n00:56:41,870 --> 00:56:44,416\n所以它们又剥掉了一个类型\nSo it'll then strip off the next version of type,\n\n876\n00:56:46,912 --> 00:56:49,808\n然后把内容交给George 让他提取出它的模值\nand hand that down to George to take the magnitude of.\n\n877\n00:56:52,160 --> 00:56:53,136\n那么我们看到\nSo you see what's going on\n\n878\n00:56:53,440 --> 00:56:56,990\n这其中有一条由类型构成的链条\nis that there are these chains of types.\n\n879\n00:56:59,320 --> 00:57:01,504\n这个链条的长度就是你要\nAnd the length of the chain is sort of the number of levels\n\n880\n00:57:01,530 --> 00:57:03,136\n在这个表格里上升的层数\nthat you're going to be going up in this table.\n\n881\n00:57:05,090 --> 00:57:05,968\n类型的作用则是\nAnd what a type tells you,\n\n882\n00:57:05,968 --> 00:57:10,848\n每当我们在表格中遇到一道垂直屏障时\nevery time you have a vertical barrier in this table,\n\n883\n00:57:11,056 --> 00:57:14,064\n你不知道该如何抉择时\nwhere there's some ambiguity about where you should go down to the next level,\n\n884\n00:57:14,416 --> 00:57:15,856\n类型就会给你指路\nthe type is telling you where to go.\n\n885\n00:57:17,440 --> 00:57:18,832\n然后最底层的过程\nAnd then everybody at the bottom,\n\n886\n00:57:18,976 --> 00:57:20,672\n它们构造数据结构 对数据进行筛选之后\nas they construct data and filter it up,\n\n887\n00:57:21,120 --> 00:57:22,810\n再把类型贴回去\nthey stick their type back on.\n\n888\n00:57:25,350 --> 00:57:30,750\n这就是整个系统的总体结构\nSo that's the general structure of the system.\n\n889\n00:57:33,410 --> 00:57:33,776\n好\nOK.\n\n890\n00:57:34,820 --> 00:57:35,680\n明白了这个之后\nNow that we've got this,\n\n891\n00:57:37,568 --> 00:57:39,440\n我们再让这个系统变得更加复杂\nlet's go and make this thing even more complex.\n\n892\n00:57:41,890 --> 00:57:46,544\n我们这次不光要在系统里添加新的数域\nLet's talk about adding to the system not only these kinds of numbers\n\n893\n00:57:46,600 --> 00:57:51,152\n我们也来讨论一下怎么把多项式也加进去\nnumbers, but it's also meaningful to start talking about adding polynomials.\n\n894\n00:57:51,510 --> 00:57:52,976\n让它能做多项式算术\nMight do arithmetic on polynomials.\n\n895\n00:57:53,360 --> 00:58:03,712\n比如我们可以计算x^15+2x^7+5\nLike we could have x to the fifteenth plus 2x to the seventh plus 5.\n\n896\n00:58:04,480 --> 00:58:05,840\n像这样的多项式\nThat might be some polynomial.\n\n897\n00:58:06,380 --> 00:58:07,936\n如果有两个这样的东西\nAnd if we have two such gadgets\n\n898\n00:58:07,936 --> 00:58:09,488\n我们可以把它们相加或者相乘\nwe can add them or multiply them.\n\n899\n00:58:10,530 --> 00:58:11,792\n先不管相除的问题\nLet's not worry about dividing them.\n\n900\n00:58:12,140 --> 00:58:14,672\n只考虑相加相乘和相减\nJust add them, multiply them, then we'll subtract them.\n\n901\n00:58:15,552 --> 00:58:17,160\n我们需要做什么\nAuhhh...What do we have to do? Well\n\n902\n00:58:18,528 --> 00:58:20,768\n我们先来想想怎么表示一个多项式\nlet's think about how we might represent a polynomial.\n\n903\n00:58:21,830 --> 00:58:23,552\n它也是一种带类型的数据\nIt's going to be some typed data object.\n\n904\n00:58:24,736 --> 00:58:27,552\n这个系统里的一个多项式\nSo let's say a polynomial to this system\n\n905\n00:58:28,544 --> 00:58:31,680\n应该是带有polynomial类型的对象\nmight look like a thing that starts with the type polynomial.\n\n906\n00:58:32,000 --> 00:58:34,550\n接下来它可能要问这个多项式的变量是哪个\nAnd then maybe it says the next thing is what variable its in.\n\n907\n00:58:34,550 --> 00:58:37,696\n比如这是一个以x为变量的多项式\nSo I might say I'm a polynomial in the variable x.\n\n908\n00:58:38,960 --> 00:58:41,392\n然后 多项式内还有各项的信息\nAnd then it'll have some information about what the terms are.\n\n909\n00:58:42,250 --> 00:58:44,160\n有很多种方法来实现\nAnd there're just tons of ways to do this,\n\n910\n00:58:44,256 --> 00:58:47,632\n我们采用的方法是构造一个“项表”\nbut one way is to say we're going to have a thing called a term-list.\n\n911\n00:58:51,520 --> 00:58:52,240\n所谓的“项表”\nAnd a term-list--\n\n912\n00:58:53,700 --> 00:58:55,616\n本例中 我们用的是类似这样的东西\nwell, in our case we'll use something that looks like this.\n\n913\n00:58:56,360 --> 00:58:59,680\n我们把它写成一系列 按次数排列的序对\nWe'll make it a bunch of pairs which have an order in a coefficient\n\n914\n00:58:59,690 --> 00:59:05,808\n那么这个项表就能表示这个多项式了\nSo this polynomial would be represented by this term-list.\n\n915\n00:59:09,424 --> 00:59:10,688\n它的意义是\nAnd what that means is that\n\n916\n00:59:11,488 --> 00:59:19,710\n这个多项式第一项的次数是15 系数是1\nthis polynomial starts off with a term of order 15 and coefficient 1.\n\n917\n00:59:23,820 --> 00:59:27,504\n然后下一项的次数是7 系数是2\nAnd the next thing in it is a term of order 7 and coefficient 2,\n\n918\n00:59:27,536 --> 00:59:30,496\n再下一项是一个常数 它次数是0 系数是5\na term of order 0, which is constant in coefficient 5\n\n919\n00:59:31,450 --> 00:59:34,160\n实际上有很多很多种方法\nAnd there are lots and lots of ways,\n\n920\n00:59:34,256 --> 00:59:35,968\n也有很多很多的取舍\nand lots and lots of trade-offs\n\n921\n00:59:36,016 --> 00:59:39,100\n在你认真思考如何实现代数操作程序包时\nwhen you really think about making algebraic manipulation packages\n\n922\n00:59:39,440 --> 00:59:41,730\n你该如何表示这些东西\nthat exactly how you should represent these things.\n\n923\n00:59:42,016 --> 00:59:43,680\n但是我们这种是比较标准的一种\nBut this is a fairly standard one.\n\n924\n00:59:44,180 --> 00:59:45,552\n它适用于很多情况\nIt's useful in a lot of contexts.\n\n925\n00:59:47,770 --> 00:59:50,992\n好 那么我们怎么实现我们的多项式算术呢\nOK, well how do we implement our polynomial arithmetic?\n\n926\n00:59:53,472 --> 00:59:54,960\n现在开始着手做这个事情\nLet's start out.\n\n927\n00:59:57,950 --> 01:00:00,288\n构造一个多项式 首先要\nWhat we'll do to make a polynomial--\n\n928\n01:00:00,760 --> 01:00:04,128\n首先我们得找一个办法来构造多项式\nwe'll first have a way to make polynomials.\n\n929\n01:00:05,690 --> 01:00:10,288\n我们可以用一个变量 比如x和一个项表来构造它们\nWe're going to make a polynomial out of variable like x and term-list.\n\n930\n01:00:11,248 --> 01:00:14,096\n我们要用某种方法把它们包装起来\nAnd all that does is we'll package them together someway.\n\n931\n01:00:14,304 --> 01:00:19,408\n我们可以用cons把变量和项表组合起来\nWe'll put the variable together with the term list using cons\n\n932\n01:00:19,824 --> 01:00:21,744\n然后把这个序对加上polynomial的类型标志\nand then attached to that the type polynomial.\n\n933\n01:00:26,270 --> 01:00:27,776\n那我们怎么处理多项式相加呢？\nOK, how do we add two polynomials?\n\n934\n01:00:29,280 --> 01:00:31,856\n要相加两个多项式 p1和p2\nTo add a polynomial, p1 and p2,\n\n935\n01:00:32,688 --> 01:00:35,184\n为了简化问题 假设我们\nand then just for simplicity let's say we\n\n936\n01:00:35,376 --> 01:00:37,152\n我们只相加变量相同的两个式子\nwe will only add things in the same variable.\n\n937\n01:00:37,380 --> 01:00:39,280\n那么如果它们的变量相同\nSo if they have the same variable,\n\n938\n01:00:39,696 --> 01:00:42,576\n是否相同交由我们编写的选择函数判断\nand same variable here is going to be some selector we write,\n\n939\n01:00:42,960 --> 01:00:44,384\n我们不必在意它的细节\nwhose details we don't care about.\n\n940\n01:00:45,150 --> 01:00:47,040\n如果两个多项式的变量相同\nIf the two polynomials have the same variable,\n\n941\n01:00:48,032 --> 01:00:48,810\n我们就继续运算\nthen we'll do something.\n\n942\n01:00:48,810 --> 01:00:51,264\n如果它们的变量不相同 我们返回一个错误\nIf they don't have the same variable, we'll give an error,\n\n943\n01:00:52,350 --> 01:00:54,016\n“两个多项式的变量不相同”\npolynomials not in the same variable.\n\n944\n01:00:55,480 --> 01:00:57,376\n如果它们的变量确实是相同\nAnd if they do have the same variable,\n\n945\n01:00:57,600 --> 01:00:59,184\n我们就要构造一个新的多项式\nwhat we'll do is we'll make a polynomial\n\n946\n01:00:59,800 --> 01:01:01,856\n它的变量即是原式的变量\nwhose variable is whatever that variable is,\n\n947\n01:01:03,152 --> 01:01:06,560\n它的项表则由过程+terms产生\nand whose term-list is something we'll call sum-terms.\n\n948\n01:01:07,488 --> 01:01:09,808\n+terms过程会把两个项表加起来\nPlus terms will add the two term lists.\n\n949\n01:01:10,170 --> 01:01:12,016\n所以我们要把两个多项式的项表合起来\nSo we'll add the two term lists to the polynomial.\n\n950\n01:01:13,500 --> 01:01:14,512\n该过程即可返回一个项表\nThat'll give us a term-list.\n\n951\n01:01:15,000 --> 01:01:20,016\n我们将变量和得到的项表构造成新的多项式\nWe'll add on, we'll say it's a polynomial in the variable with that term-list.\n\n952\n01:01:20,688 --> 01:01:21,792\n这就是+poly过程\nThat's plus poly.\n\n953\n01:01:22,550 --> 01:01:27,008\n然后我们要把这个过程放进表格中polynomial那一栏\nAnd then we're going to put in our table under the type polynomial\n\n954\n01:01:28,240 --> 01:01:30,144\n用+poly实现add操作\nadd them using plus poly.\n\n955\n01:01:30,520 --> 01:01:31,750\n当然实际上没做多少事情\nAnd of course we really haven't done much.\n\n956\n01:01:31,750 --> 01:01:35,312\n我们只是把所有的工作压到+terms的头上\nWhat we've really done is pushed all the work onto this thing, +terms\n\n957\n01:01:35,792 --> 01:01:37,024\n它会负责把项表相加起来\nwhich is supposed to add term-lists.\n\n958\n01:01:37,744 --> 01:01:39,168\n我们看看这个过程\nLet's look at that.\n\n959\n01:01:39,184 --> 01:01:48,032\n这是+terms过程的大概结构\nHere's an overview of how we might add two term-lists.\n\n960\n01:01:48,900 --> 01:01:51,744\nL1和L2是两个项表\nSo L1 and L2 were going to be two term-lists.\n\n961\n01:01:52,000 --> 01:01:54,816\n所谓“项表”即是按每项次数排序的序对\nAnd a term-list is a bunch of pairs, coefficient in order.\n\n962\n01:01:55,700 --> 01:01:56,950\n这里有一个大的分情况分析\nAnd it's a big case analysis.\n\n963\n01:01:59,860 --> 01:02:04,144\n首先 我们要检查项表是否为空\nAnd the first thing we'll check for and see if there are any terms\n\n964\n01:02:05,392 --> 01:02:07,552\n我们对项表做递归下降处理\nWe're going to recursively work down these term-lists\n\n965\n01:02:08,160 --> 01:02:11,744\n最终下降到 L1或L2为空\nso eventually we'll get to a place where either L1 or L2 might be empty.\n\n966\n01:02:12,270 --> 01:02:14,352\n只要其中有一个为空\nAnd if either one is empty,\n\n967\n01:02:14,528 --> 01:02:15,850\n我们的答案就是剩下的另一个\nour answer will be the other one.\n\n968\n01:02:15,850 --> 01:02:19,552\n就是说如果L1是空表 我们就返回L2\nSo if L1 is empty we'll return L2,\n\n969\n01:02:19,632 --> 01:02:21,712\nL2是空表的话就返回L1\nand if L2 is empty we'll return L1.\n\n970\n01:02:23,264 --> 01:02:25,760\n除此之外还有三种情况\nOtherwise there are sort of three interesting cases.\n\n971\n01:02:27,220 --> 01:02:27,984\n我们要做的是\nWhat we're going to do is\n\n972\n01:02:29,088 --> 01:02:31,050\n取表中的第一项\ngrab the first term in each of those lists,\n\n973\n01:02:33,504 --> 01:02:36,048\n记为t1和t2\nRight? Called t1 and t2.\n\n974\n01:02:37,660 --> 01:02:39,056\n我们来分析一下这三种情况\nAnd we're going to look at three cases,\n\n975\n01:02:39,600 --> 01:02:45,680\n分别是t1的次数大于t2的\ndepending on whether the order of t1 is greater than the order of t2,\n\n976\n01:02:47,230 --> 01:02:50,592\n小于t2的 或者等于t2的\nor less than t2, or the same.\n\n977\n01:02:53,280 --> 01:02:54,910\n这就是我们要判断的三种情况\nThose are the three cases we're going to look at.\n\n978\n01:02:54,910 --> 01:02:55,840\n先看看这一种\nLet's look at this case.\n\n979\n01:02:58,640 --> 01:03:01,312\n如果t1的次数比t2的次数要高\nIf the order of t1 is greater than the order of t2,\n\n980\n01:03:03,400 --> 01:03:04,704\n就意味着\nthen what that means is that\n\n981\n01:03:06,064 --> 01:03:09,968\n答案的第一项的次数就是t1的次数\nthen what that means is that our answer is going to start with this term of the order of t1.\n\n982\n01:03:11,568 --> 01:03:13,808\n因为高次项不会和任何低次项相加\nBecause it won't combine with any lower order terms.\n\n983\n01:03:14,176 --> 01:03:16,192\n那么我们只需要把低次的项加起来\nSo what we do is add the lower order terms.\n\n984\n01:03:16,760 --> 01:03:18,256\n我们递归地把\nWe recursively add\n\n985\n01:03:19,712 --> 01:03:25,070\n把L1和L2两个项表里剩下的项相加\ntogether all the terms in the rest of the term-list in L1 and L2.\n\n986\n01:03:27,136 --> 01:03:29,328\n作为我们的答案中低次项\nThat's going to be the lower order terms of the answer.\n\n987\n01:03:30,120 --> 01:03:32,480\n然后我们把它们和最高次的项连接起来\nAnd then we're going to adjoin to that the highest order term.\n\n988\n01:03:33,180 --> 01:03:35,456\n这里 我用了一对还未定义的过程\nAnd I'm using here a whole bunch of procedures I haven't defined\n\n989\n01:03:35,472 --> 01:03:37,552\n比如adjoin-term、rest-terms\nlike a adjoin-term, and rest-terms,\n\n990\n01:03:38,480 --> 01:03:40,176\n还有获取次数的选择函数\nand selectors that get order.\n\n991\n01:03:41,152 --> 01:03:42,784\n但是你可以想象它们是什么样子的\nBut you can imagine what those are.\n\n992\n01:03:44,448 --> 01:03:48,768\n那么如果第一个项表的次数比第二个要高\nRight? So if the first term-list has a higher order than the second\n\n993\n01:03:48,780 --> 01:03:51,088\n我们就递归地把所有的低次的项相加\nwe recursively add all the lower terms\n\n994\n01:03:51,280 --> 01:03:53,420\n再和最高次项连接起来\nand then stick on that last term.\n\n995\n01:03:55,540 --> 01:03:56,752\n其它情况也是一样的\nThe other case, the same way.\n\n996\n01:03:56,890 --> 01:04:00,288\n如果第一个多项式次数比较低\nIf the first term has a smaller order,\n\n997\n01:04:00,540 --> 01:04:08,368\n我们就把整个第一个多项式和第二个多项式低次的项相加\nwell then we add we add the first term-list and the rest of the terms in the second one\n\n998\n01:04:08,624 --> 01:04:12,656\n然后把结果再和最高次项连起来\nand adjoin on this highest order term.\n\n999\n01:04:14,570 --> 01:04:15,968\n到现在也没多少复杂的事情\nSo so far nothing's much happened,\n\n1000\n01:04:15,968 --> 01:04:19,408\n把问题变成 让低次数的项相加\nwe've just sort of pushed this thing off into adding lower order terms.\n\n1001\n01:04:19,470 --> 01:04:21,968\n还有最后一种情况是 两个多项式的次数一样\nThe last case where you actually get to a coefficients\n\n1002\n01:04:22,570 --> 01:04:25,184\n你必须要把它们的系数加起来 因为它们是同类项\nthat you have to add, this will be the case where the orders are equal.\n\n1003\n01:04:27,240 --> 01:04:30,992\n我们的应对方法仍然是 递归地把低次项相加\nWhat we do is, well again recursively add the lower order terms.\n\n1004\n01:04:31,008 --> 01:04:32,832\n但现在我们需要合并一些项了\nBut now we have to really combine something.\n\n1005\n01:04:33,460 --> 01:04:36,352\n我们构造一个项\nWhat we do is we make a term\n\n1006\n01:04:37,312 --> 01:04:39,936\n其次数为我们正在处理的那一项的次数\nwhose order is the order of the term we're looking at.\n\n1007\n01:04:40,820 --> 01:04:42,720\n因为现在t1和t2的次数是相同的\nBy now t1 and t2 have the same order.\n\n1008\n01:04:44,320 --> 01:04:44,992\n确定好次数了\nThat's its order.\n\n1009\n01:04:45,090 --> 01:04:52,336\n而它的系数是t1和t2系数之和\nAnd its coefficient is gotten by adding the coefficient of t1 and the coefficient of t2.\n\n1010\n01:04:55,792 --> 01:04:59,648\n这是一个庞大的递归过程\nThere's... This is a big recursive working down of terms,\n\n1011\n01:04:59,680 --> 01:05:03,616\n但其中只有一个符号值得玩味\nbut really there's only one interesting symbol in this procedure,\n\n1012\n01:05:04,256 --> 01:05:05,696\n它蕴含了重要的思想\nonly one interesting idea.\n\n1013\n01:05:05,900 --> 01:05:08,500\n那就是这个ADD过程\nThe interesting idea is this add.\n\n1014\n01:05:12,390 --> 01:05:14,800\n说它有趣是因为\nAnd the reason that's interesting is because\n\n1015\n01:05:15,424 --> 01:05:17,376\n有一件好事发生\nsomething completely wonderful just happened.\n\n1016\n01:05:18,220 --> 01:05:21,376\n我们没有把多项式加法\nWe reduced adding polynomials,\n\n1017\n01:05:22,560 --> 01:05:26,464\n归约为某种加法 而是归约为通用运算符ADD\nnot to sort of plus, but to the generic add.\n\n1018\n01:05:28,820 --> 01:05:32,288\n换句话说 用这种方法实现它之后\nIn other words, by implementing it that way,\n\n1019\n01:05:32,890 --> 01:05:34,688\n我们的系统就不光有\nnot only do we have our system\n\n1020\n01:05:35,920 --> 01:05:41,664\n有理数、复数还有寻常算术\nwhere we can have rational numbers, or complex numbers, or ordinary numbers,\n\n1021\n01:05:41,856 --> 01:05:43,824\n我们同时也让它支持多项式运算了\nwe've just added on polynomials.\n\n1022\n01:05:48,520 --> 01:05:51,136\n而多项式的系数可以是\nBut the coefficients of the polynomials\n\n1023\n01:05:51,248 --> 01:05:52,860\n这个系统能够相加的任何东西\ncan be anything that the system can add.\n\n1024\n01:05:53,590 --> 01:05:56,736\n也就是说多项式的系数\nSo these could be polynomials whose coefficient\n\n1025\n01:05:57,200 --> 01:06:01,200\n有理数或者复数\nare rational numbers or complex numbers,\n\n1026\n01:06:02,768 --> 01:06:06,992\n复数同时可支持直角坐标形式和极坐标形式\nwhich in turn could be either rectangular, or polar,\n\n1027\n01:06:09,120 --> 01:06:11,392\n系数还可以是寻常的数字\nor ordinary numbers.\n\n1028\n01:06:18,976 --> 01:06:21,216\n我想说的是\nRignt? So what I mean precisely is\n\n1029\n01:06:22,060 --> 01:06:24,352\n我们的系统现在可以自动地\nour system right now automatically\n\n1030\n01:06:26,600 --> 01:06:31,504\n处理像这样的式子\ncan handle things like adding together polynomials that have this form\n\n1031\n01:06:31,536 --> 01:06:39,696\n比如2/3x^2+5/17x+11/4这样的式子\n2/3 of x squared plus 5/17 x plus 11/4.\n\n1032\n01:06:40,940 --> 01:06:43,488\n也可以自动处理像是\nOr automatically handle polynomials that look like\n\n1033\n01:06:43,824 --> 01:06:52,576\n(3+2i)x^5+(4+7i)这样的式子\n3 plus 2i times x to the fifth plus 4 plus 7i, or something.\n\n1034\n01:06:53,888 --> 01:06:56,210\n系统可以自动处理这些运算\nRight? You can automatically handle those things.\n\n1035\n01:06:56,210 --> 01:06:57,072\n为什么呢？\nWhy is that?\n\n1036\n01:06:57,820 --> 01:07:01,504\n仅仅是因为 或者说深层次的原因是\nThat's merely because, or profoundly because\n\n1037\n01:07:02,170 --> 01:07:05,936\n我们把多项式相加归约成了把它们的系数相加\nwe reduced adding polynomials to adding their coefficients.\n\n1038\n01:07:06,790 --> 01:07:10,224\n而系数的相加是由通用运算符ADD完成的\nAnd adding coefficients was done by the generic add operator\n\n1039\n01:07:11,088 --> 01:07:12,944\n它说：“我不管你的数据类型是什么”\nwhich said, I don't care what your types are\n\n1040\n01:07:12,960 --> 01:07:14,080\n“只要我能够处理就行”\nas long as I know how to add you.\n\n1041\n01:07:15,232 --> 01:07:18,864\n于是我们就“免费”获得了处理这些东西的功能\nSo automatically for free we get the ability to handle that.\n\n1042\n01:07:20,650 --> 01:07:22,048\n更神奇的是\nWhat's even better than that,\n\n1043\n01:07:24,510 --> 01:07:26,528\n我们曾把\none of the things we did\n\n1044\n01:07:27,200 --> 01:07:30,528\n我们放入表格中 用于处理多项式加法\nwe put into the table that the way you add polynomials\n\n1045\n01:07:31,280 --> 01:07:32,528\n是用的+poly过程\nis using plus poly.\n\n1046\n01:07:34,660 --> 01:07:38,656\n这就意味着ADD过程也可以处理多项式了\nThat means that polynomials themselves are things that can be added.\n\n1047\n01:07:39,424 --> 01:07:42,110\n我举个例子\nSo for instance let me write one here.\n\n1048\n01:07:43,184 --> 01:07:46,192\n这是一个多项式\nHere is... Here's a polynomial.\n\n1049\n01:07:50,560 --> 01:07:52,416\n我正在写的这个东西\nSo this gadget here I'm writing up,\n\n1050\n01:07:54,128 --> 01:07:58,464\n它是一个以y作为变量的多项式\nthis is a polynomial in y\n\n1051\n01:08:01,072 --> 01:08:04,690\n每项的系数是以x作为变量的多项式\nwhose coefficients are polynomials in x.\n\n1052\n01:08:08,610 --> 01:08:11,120\n你将看到\nSo you see, simply by saying,\n\n1053\n01:08:11,760 --> 01:08:14,064\n由于 “ADD过程能够处理多项式”\npolynomials are themselves things that can be added,\n\n1054\n01:08:14,416 --> 01:08:17,904\n我们可以说 我们的系统现在不光能运算有理数\nwe can go off and say, well not only can we deal with rationals,\n\n1055\n01:08:18,270 --> 01:08:20,336\n复数和一般数字\nor complex, or ordinary numbers,\n\n1056\n01:08:20,350 --> 01:08:21,776\n我们还可以处理多项式\nbut we can deal with polynomials\n\n1057\n01:08:22,096 --> 01:08:25,392\n多项式的系数可以是有理数、复数、一般数字\nwhose coefficients are rationals, or complex, or ordinary numbers,\n\n1058\n01:08:25,504 --> 01:08:27,520\n甚至是多项式\nor polynomials\n\n1059\n01:08:29,150 --> 01:08:30,960\n作为系数的多项式 其系数还可以是有理数\nwhose coefficients are rationals,\n\n1060\n01:08:31,696 --> 01:08:36,760\n复数（直角或极坐标形式）或一般数字\nor complex, rectangular, polar, or ordinary numbers,\n\n1061\n01:08:36,944 --> 01:08:41,136\n甚至还可以是系数为有理数的多项式\nor ordinary numbers, or polynomials whose coefficients are rationals,\n\n1062\n01:08:41,800 --> 01:08:43,328\n系数为复数、一般数字的多项式\ncomplex, or ordinary numbers.\n\n1063\n01:08:43,670 --> 01:08:45,216\n以此类推\nAnd so on, and so on, and so on.\n\n1064\n01:08:45,950 --> 01:08:47,552\n我们构造出了一座无限延伸的\nSo this is sort of an infinite\n\n1065\n01:08:48,496 --> 01:08:52,880\n或者说是递归的类型高塔\nor maybe a recursive tower of types that we've built up.\n\n1066\n01:08:53,880 --> 01:08:57,120\n这一切都来源于那个小小的符号：A-D-D\nAnd it's all exactly from that one little symbol, A-D-D.\n\n1067\n01:08:57,610 --> 01:09:00,496\n来源于在多项式程序里 用“ADD”来代替“+”\nWriting \"add\" instead of \"plus\" in the polynomial thing.\n\n1068\n01:09:02,270 --> 01:09:03,776\n换一种方式来理解它就是\nSlightly different way to think about it\n\n1069\n01:09:03,952 --> 01:09:07,744\n多项式也是一种类型的构造函数\nis that polynomials are a constructor for types.\n\n1070\n01:09:08,740 --> 01:09:11,200\n也就是说你传递给它一个类型 比如整型\nNamely you give it a type, like integer,\n\n1071\n01:09:11,488 --> 01:09:15,744\n然后它就返回一个以整数作为系数的多项式\nand it returns for you polynomials in x whose coefficients are integers.\n\n1072\n01:09:16,270 --> 01:09:17,728\n过程中很重要的一点是\nAnd the important thing about\n\n1073\n01:09:18,650 --> 01:09:20,736\n就是多项式上的运算\nis that is that the operations on polynomials\n\n1074\n01:09:21,280 --> 01:09:23,376\n归约成了关于系数的运算\nreduce to the operations on the coefficients.\n\n1075\n01:09:23,392 --> 01:09:24,960\n很多地方都与这里类似\nAnd there are a lot of things like that.\n\n1076\n01:09:25,840 --> 01:09:27,920\n比如 我们再回头看看有理数\nSo for example, let's go back and rational numbers.\n\n1077\n01:09:28,870 --> 01:09:32,656\n我们之前把有理数看做 一个整数在另一个上面\nWe thought about rational numbers as an integer over an integer\n\n1078\n01:09:32,672 --> 01:09:35,660\n但这并不是关于有理式的一般性记号\nbut there's the general notion of a rational object.\n\n1079\n01:09:36,240 --> 01:09:42,032\n比如我们也可以把3x+7放在上面 x^2+1放在下面\nLike we might think about 3x plus 7 over x squared plus 1.\n\n1080\n01:09:43,072 --> 01:09:48,864\n这是一个分子分母都是多项式的广义有理式\nThat's general rational object whose numerator and denominator are polynomials.\n\n1081\n01:09:50,310 --> 01:09:52,416\n有理式相加 和有理数相加一样\nAnd to add two of them we use the same formula,\n\n1082\n01:09:52,440 --> 01:09:55,408\n分子乘分母 加 分母乘分子 结果作为分子\nnumerator times denominator plus denominator times numerator\n\n1083\n01:09:55,720 --> 01:09:56,992\n两个分母相乘 结果作为分母\nover product of denominators.\n\n1084\n01:09:57,290 --> 01:09:59,376\n怎么把它安装到我们的系统中呢？\nHow could we install that in our system?\n\n1085\n01:09:59,392 --> 01:10:02,976\n这是我们原来的有理数算术程序包\nWell here's our original rational number arithmetic package.\n\n1086\n01:10:04,250 --> 01:10:08,240\n为了让这个系统能够\nAnd all we have to do in order to make the entire system\n\n1087\n01:10:08,288 --> 01:10:11,584\n支持广义有理式的运算\ncontinue working with general rational objects,\n\n1088\n01:10:11,850 --> 01:10:16,448\n我们把特定的加法和乘法过程 都改成通用运算符\nis replace these particular pluses and stars by the generic operator.\n\n1089\n01:10:16,480 --> 01:10:19,184\n所以如果我们把原来那个过程变成这个过程\nSo if we simply change that procedure to this one,\n\n1090\n01:10:19,712 --> 01:10:22,048\n把+和*换成ADD和MUL\nhere we've changed plus and star to add a mul,\n\n1091\n01:10:22,880 --> 01:10:24,480\n这些是唯一的改动\nthose are absolutely the only change,\n\n1092\n01:10:24,840 --> 01:10:26,032\n然后霎时间\nthen suddenly\n\n1093\n01:10:27,520 --> 01:10:31,408\n我们的整个系统 就知道怎么运算这样的东西了\nour entire system can start talking about objects that look like this.\n\n1094\n01:10:33,728 --> 01:10:38,272\n比如说 这里的这个有理式\nSo for example, here is a rational object\n\n1095\n01:10:39,184 --> 01:10:44,864\n它的分子是一个系数是有理数的、关于x的多项式\nwhose numerator is a polynomial in x whose coefficients are rational numbers.\n\n1096\n01:10:47,020 --> 01:10:49,568\n而这个有理式\nOr here is a rational object\n\n1097\n01:10:51,104 --> 01:10:54,432\n它的分子是关于x的多项式\nwhose numerator is polynomials in x\n\n1098\n01:10:55,152 --> 01:10:58,192\n多项式的系数又是有理式\nwhose coefficients are rational objects\n\n1099\n01:10:59,776 --> 01:11:01,536\n有理式又由复数组成\nconstructed out of complex numbers.\n\n1100\n01:11:03,390 --> 01:11:04,850\n或者别的像这样的东西\nAnd then there are a lot of other things like that.\n\n1101\n01:11:04,850 --> 01:11:08,688\n看 只要能够归约成针对各部分的运算\nSee, whenever you have a thing where the operations reduce to operations on the pieces,\n\n1102\n01:11:08,896 --> 01:11:10,000\n另一个例子是\nanother example would be\n\n1103\n01:11:10,288 --> 01:11:11,424\n2*2的矩阵\ntwo by two matrices.\n\n1104\n01:11:12,310 --> 01:11:15,440\n假如有这样一个矩阵形式的东西\nI have the idea, there might be a matrix here\n\n1105\n01:11:16,432 --> 01:11:18,336\n不管它里面是什么\nof general things that I don't care about.\n\n1106\n01:11:18,720 --> 01:11:20,144\n但是如果我对两个这种东西调用ADD\nBut if I add two of them,\n\n1107\n01:11:22,336 --> 01:11:25,180\n答案就是\nthe answer over here is gotten by\n\n1108\n01:11:25,180 --> 01:11:28,144\n把这个和这个相加 而矩阵是怎么相加的\nadding this one and that one,however they like to add.\n\n1109\n01:11:29,030 --> 01:11:31,110\n那么我可以用同样的方法实现\nSo I can implement that the same way.\n\n1110\n01:11:31,110 --> 01:11:31,712\n如果我这么做了\nAnd if I do that,\n\n1111\n01:11:31,960 --> 01:11:34,608\n整个系统就马上可以处理像这样的东西了\nthen again suddenly my system can start handling things like this.\n\n1112\n01:11:35,296 --> 01:11:39,184\n比如说一个矩阵 它的元素都是\nSo here's a matrix whose elements happen to be--\n\n1113\n01:11:39,460 --> 01:11:42,160\n它的元素是一个有理式\nwe'll say this element here is a rational object\n\n1114\n01:11:43,104 --> 01:11:45,152\n这个有理式的分子分母都是多项式\nwhose numerator and denominators are polynomials.\n\n1115\n01:11:47,024 --> 01:11:49,568\n我们自然而然地获得了这些功能\nRight? And all that comes for free.\n\n1116\n01:11:51,280 --> 01:11:53,824\n整个过程中发生了什么？\nRight? What's really going on here?\n\n1117\n01:11:53,920 --> 01:11:56,176\n真正发生的是\nWhat's really going on is\n\n1118\n01:11:57,680 --> 01:12:02,448\n我们摆脱了凡事都想插一手的经理\ngetting rid of who's sitting there poking his nose into who everybody's business is.\n\n1119\n01:12:03,120 --> 01:12:06,192\n我们构造了一个“控制去中心化”的系统\nWe built a system that has decentralized control.\n\n1120\n01:12:14,784 --> 01:12:18,340\n你进入这个系统的时候 不会有人一边闲逛一边说\nSo when you come into and no one's poking around saying,\n\n1121\n01:12:18,352 --> 01:12:22,304\n我看看官方列表中ADD是否能够处理你\ngee, are you in the official list of people who can be added?\n\n1122\n01:12:22,440 --> 01:12:26,224\n你直接就可以用正确的方法 把你和别的东西加起来\nRather you say, well go off and add yourself how your parts like to be added.\n\n1123\n01:12:27,810 --> 01:12:31,030\n这么做的好处就是 就连这种非常非常\nAnd the result of that is you can get this very, very, very\n\n1124\n01:12:31,030 --> 01:12:33,870\n复杂的分层对象也可以被分解后\ncomplex hierarchy where a lot of things just get done and\n\n1125\n01:12:33,870 --> 01:12:35,552\n自动放到正确的地方去处理\nrooted to the right place automatically.\n\n1126\n01:12:37,008 --> 01:12:37,792\n有什么问题吗？\nLet's stop for questions.\n\n1127\n01:12:40,380 --> 01:12:42,320\n学生：你说你“免费”获得了这些功能\nAUDIENCE: You say you get this for free.\n\n1128\n01:12:42,350 --> 01:12:45,824\n但是我在意的是你现在丢掉了\nUm..... One thing that strikes me is that now you've lost\n\n1129\n01:12:46,480 --> 01:12:50,910\n某种上下层之间的清楚界限\nkind of the cleanness of the break between what's on top and what's underneath.\n\n1130\n01:12:50,910 --> 01:12:52,770\n或者说 现在你是在用\nIn other words, now you're defining some of the\n\n1131\n01:12:52,770 --> 01:12:56,080\n上层的东西来定义下层的过程\nlower-level procedures in terms of things above their own line.\n\n1132\n01:12:56,610 --> 01:12:59,456\n这不是很危险吗？\nIsn't that dangerous?\n\n1133\n01:13:00,350 --> 01:13:04,496\n或者说 结构会变得混乱？\nOr, if nothing more, a little less structured?\n\n1134\n01:13:05,440 --> 01:13:05,952\n教授：不 我--\nPROFESSOR: No, I--\n\n1135\n01:13:06,416 --> 01:13:07,770\n你问它的结构是否混乱\nthe question is whether that's less structured.\n\n1136\n01:13:07,770 --> 01:13:08,690\n这得要看你说的“结构”是指什么\nDepends on what you mean by structure.\n\n1137\n01:13:08,690 --> 01:13:10,176\n整个过程里我们都在做递归\nAll this is doing is recursion.\n\n1138\n01:13:11,050 --> 01:13:18,800\n看 就是说要把这些东西相加就要用到这个过程\nSee, it's saying that the way you add these guys is to use that.\n\n1139\n01:13:19,152 --> 01:13:21,376\n它是一种递归结构 并不混乱\nAnd that's not less structured, it's just a recursive structure.\n\n1140\n01:13:22,704 --> 01:13:24,990\n所以我不认为它不清楚\nSo I don't think it's particularly any less clean.\n\n1141\n01:13:24,990 --> 01:13:28,160\n学生：那么当你修改乘法或加法运算时\nAUDIENCE: Now when you want to change the multiplier or the add operator\n\n1142\n01:13:29,344 --> 01:13:31,380\n可能会导致\nsuddenly you've got tremendous consequences\n\n1143\n01:13:31,380 --> 01:13:34,272\n无法预测的灾难性后果\nunderneath that you're not even sure the extent of.\n\n1144\n01:13:34,480 --> 01:13:36,448\n教授：你说得对 但是那要看你的意思是什么\nPROFESSOR: That's right, but it depends what you mean.\n\n1145\n01:13:37,080 --> 01:13:38,470\n从两个角度来讨论\nSee, this goes both ways.\n\n1146\n01:13:39,104 --> 01:13:43,248\n举个什么例子好呢？\nUm....What would be a good example?\n\n1147\n01:13:44,690 --> 01:13:47,500\n比如说 之前我忽略了GCD运算\nI ignored greatest common divisor, for instance.\n\n1148\n01:13:47,776 --> 01:13:50,080\n我们忽略了它 是为了简化我们的例子\nI ignored that problem just to keep the example simple.\n\n1149\n01:13:50,280 --> 01:13:56,928\n但是如果突然我觉得 这里的+rat\nBut if I suddenly decided that plus rat here\n\n1150\n01:13:57,820 --> 01:14:01,696\n应该把结果约分 然后把这个功能安装到程序里\nshould do a GCD computation and install that,\n\n1151\n01:14:03,340 --> 01:14:07,872\n那么这个功能一旦安装 就立刻可以被所有过程调用\nthen that immediately becomes available to all of these, to that guy, and that guy,\n\n1152\n01:14:08,032 --> 01:14:10,080\n被这个或者那个 所有的这些\nand that guy, and all the way down.\n\n1153\n01:14:11,560 --> 01:14:13,890\n这取决于你系统的相干性（耦合度）\nSo it depends what you mean by the coherence of your system.\n\n1154\n01:14:13,890 --> 01:14:17,030\n确实你可能想设计一个\nIt's certainly true that you might want to have a special\n\n1155\n01:14:17,030 --> 01:14:19,568\n不这样递归下降的程序\ndifferent one that didn't filter down through the coefficients\n\n1156\n01:14:19,616 --> 01:14:22,976\n但是我举这个例子的好处 就在于我们通常都是这么做的\nbut the nice thing about this particular example is that mostly you do.\n\n1157\n01:14:25,440 --> 01:14:27,630\n学生：是不是有一个问题 我想\nAUDIENCE: Isn't that the problem, I think, that you're\n\n1158\n01:14:27,630 --> 01:14:32,950\n就是你会被这个结构捆绑起来\ngetting to tied in with the fact that the structuring, the\n\n1159\n01:14:32,950 --> 01:14:36,330\n这个递归的结构是实际上被执行了的\nrecursiveness of that structuring there is actually\n\n1160\n01:14:36,330 --> 01:14:40,340\n而不是仅仅是为了定义类型的需要\nin execution as opposed to just definition of the actual\n\n1161\n01:14:40,340 --> 01:14:41,168\n被这个事实所束缚\ntypes themselves?\n\n1162\n01:14:44,680 --> 01:14:46,120\n教授：我大概明白你的意思\nPROFESSOR: I think I understand the question.\n\n1163\n01:14:46,120 --> 01:14:47,808\n你是想说在这个系统投入运行之后\nThe point is that these types evolve\n\n1164\n01:14:47,824 --> 01:14:50,400\n这些类型还会变得越来越复杂\nand get more and more complex as the thing's actually running.\n\n1165\n01:14:50,400 --> 01:14:50,730\n你是不是想……\nIs that what--\n\n1166\n01:14:50,730 --> 01:14:50,990\n学生：对\nAUDIENCE: Yap.\n\n1167\n01:14:50,990 --> 01:14:51,790\n在它投入运行之后\nAs it's running.\n\n1168\n01:14:52,090 --> 01:14:54,180\n学生：而不是作为基本的定义\nAUDIENCE: As opposed to the basic definitions.\n\n1169\n01:14:54,180 --> 01:14:54,830\n教授：对\nPROFESSOR: Right. There's...\n\n1170\n01:14:54,830 --> 01:14:56,704\n我们的类型结构可以说就是递归的\nThe type structure is sort of recursive.\n\n1171\n01:14:57,210 --> 01:15:00,224\n它并不是一个 可以在系统投入运行之前\nIt's not that you can make this finite list of the\n\n1172\n01:15:01,584 --> 01:15:04,850\n就能把要用到的东西全部包括的列表\nactual things they might look like before the system runs.\n\n1173\n01:15:04,850 --> 01:15:05,792\n它是一个不断演进的东西\nIt's something that evolves.\n\n1174\n01:15:06,780 --> 01:15:08,640\n所以如果你想要定制这个系统\nSo if you want to specify that system,\n\n1175\n01:15:08,670 --> 01:15:10,960\n你就不能通过有限的表\nyou have to do in some other way than by this finite list.\n\n1176\n01:15:11,008 --> 01:15:13,184\n你需要用一个递归结构实现它\nYou have to do it by a recursive structure.\n\n1177\n01:15:13,670 --> 01:15:17,900\n学生：因为类型的基本结构是相当简单而明了的\nAUDIENCE: Because the basic structure of the types is pretty clean and simple.\n\n1178\n01:15:17,900 --> 01:15:18,192\n教授：对\nPROFESSOR: Right.\n\n1179\n01:15:20,400 --> 01:15:20,752\n嗯？\nYes?\n\n1180\n01:15:21,460 --> 01:15:22,870\n学生：我有一个问题\nAUDIENCE: I have a question.\n\n1181\n01:15:22,870 --> 01:15:25,680\n我明白一旦你的数据结构被设计好之后\nI understand once you have your data structure set up,\n\n1182\n01:15:25,712 --> 01:15:28,736\n它是怎么把complex标志拿掉 把它传递给下层\nhow it pulls off complex and passes that down,\n\n1183\n01:15:28,736 --> 01:15:30,640\n然后把rect类型拿掉 再传递给下层\nand then pulls off rect, passes that down.\n\n1184\n01:15:30,640 --> 01:15:33,952\n但是如果你只是一个用户 并不知道什么rect或者polar类型\nBut if you're just a user and you don't know anything about rect or polar or whatever,\n\n1185\n01:15:34,250 --> 01:15:36,048\n你怎么知道如何去设置这个数据结构\nhow do you initially set up that data structure\n\n1186\n01:15:36,090 --> 01:15:38,080\n让所有东西正常运转呢\nso that everything goes to the right spot?\n\n1187\n01:15:38,096 --> 01:15:41,008\n如果我只知道左边的这个算式\nIf I just have the equation over there on the left\n\n1188\n01:15:41,024 --> 01:15:42,500\n我只是想把复数加起来或者乘起来\nAnd I just want to add, multiply complex numbers--\n\n1189\n01:15:42,500 --> 01:15:43,640\n教授：这就是它神奇的地方\nPROFESSOR: Well that's the wonderful thing.\n\n1190\n01:15:43,640 --> 01:15:45,264\n如果你是一个用户 直接调用mul就可以了\nIf you're just a user you say \"mul.\"\n\n1191\n01:15:47,730 --> 01:15:49,952\n学生：然后它就能明白我要计算的是复数？\nAUDIENCE: And it figures out that I mean complex numbers?\n\n1192\n01:15:49,968 --> 01:15:51,232\n或者我怎么告诉它我想——\nOr how do I tell it that I want--\n\n1193\n01:15:51,264 --> 01:15:53,056\n教授：只要你给它的是复数它就能明白\nPROFESSOR: Well you're going to have in your hands complex numbers.\n\n1194\n01:15:53,050 --> 01:15:56,304\n作为这个系统的用户\nSee what you would have at some level, as a real user,\n\n1195\n01:15:56,320 --> 01:15:58,144\n你能使用的是复数的构造函数\nis a constructor for complex numbers.\n\n1196\n01:15:58,370 --> 01:15:59,552\n学生：那么我需要自己构造复数了？\nAUDIENCE: So then I have to make complex numbers?\n\n1197\n01:15:59,568 --> 01:16:00,350\n教授：那么你需要自己构造它们\nPROFESSOR: So you have to make them.\n\n1198\n01:16:00,350 --> 01:16:04,016\n作为用户 你可能只能够操作命令行\nWhat you would probably have as a user is some little thing in the reader loop,\n\n1199\n01:16:04,650 --> 01:16:07,568\n它会给你提供一些合理的方法\nwhich would give you some plausible way\n\n1200\n01:16:07,568 --> 01:16:08,864\n来输入复数\nto type in a complex number,\n\n1201\n01:16:09,312 --> 01:16:11,008\n让你用你喜欢的格式输入\nin however whatever format you like.\n\n1202\n01:16:11,590 --> 01:16:14,360\n也可能你根本就不用输入它们\nOr it might be that you're never typing them in.\n\n1203\n01:16:14,360 --> 01:16:16,170\n只是别人给你一个复数让你计算\nSomeone's just handing you a complex number.\n\n1204\n01:16:16,784 --> 01:16:19,824\n学生：好 那么如果我有一个含有多项式的复数\nAUDIENCE: OK, so if I had a complex number that had a polynomial in it,\n\n1205\n01:16:19,824 --> 01:16:21,960\n我就要先构造这个多项式 然后再构造我的复数\nI'd have to make my polynomial and then make my complex number.\n\n1206\n01:16:21,960 --> 01:16:23,968\n教授：如果你是从零开始构造它的话 是这样的\nPROFESSOR: Right if you wanted it constructed from scratch.\n\n1207\n01:16:24,288 --> 01:16:25,710\n可以说你是在从零开始构造\nAt some point you construct them from scratch.\n\n1208\n01:16:25,710 --> 01:16:27,056\n而你只要有了要计算的东西\nBut what you don't have to know of that\n\n1209\n01:16:27,280 --> 01:16:30,320\n可以直接调用mul运算 然后它们就会被乘起来\nis when you have the object you can just say \"mul.\" And it'll multiply.\n\n1210\n01:16:32,784 --> 01:16:32,992\n说吧\nYeah?\n\n1211\n01:16:33,270 --> 01:16:35,760\n学生：我想提一个问题 就是……\nAUDIENCE: I think the question that was being posed here is,\n\n1212\n01:16:36,450 --> 01:16:40,016\n比如说我想修改我的复数表示方法\nsay if I want to change my presentation of complexes,\n\n1213\n01:16:40,030 --> 01:16:41,440\n或者复数的某些运算\nor some operation of complex,\n\n1214\n01:16:41,520 --> 01:16:47,104\n为了修改一个特定的运算\nhow much real code I will have to gets around with,\n\n1215\n01:16:47,152 --> 01:16:51,264\n我得考虑多少代码？\nor change to change it in one specific operation?\n\n1216\n01:16:52,270 --> 01:16:53,490\n教授：得看你想要修改什么\nPROFESSOR: [UNINTELLIGIBLE] what you have to change.\n\n1217\n01:16:53,490 --> 01:16:54,990\n重点在于你只需要改\nAnd the point is that you only have to change\n\n1218\n01:16:55,392 --> 01:16:56,070\n你想改的那一部分\nwhat you're changing.\n\n1219\n01:16:56,070 --> 01:17:00,048\n想象一下如果Martha决定她\nSee if Martha decides that she would rather--\n\n1220\n01:17:00,320 --> 01:17:01,232\n举个不太好的例子\nlet's see something silly--\n\n1221\n01:17:01,440 --> 01:17:02,912\n比如把序对中两个数的顺序调换\nlike change the order in the pair.\n\n1222\n01:17:04,040 --> 01:17:08,720\n把模和辐角的顺序反过来\nLike angle and magnitude in the other order,\n\n1223\n01:17:09,390 --> 01:17:10,800\n她只做了局部的修改\nshe just makes that change locally.\n\n1224\n01:17:10,970 --> 01:17:13,296\n那么这个改动会准确无误地扩散到整个系统里\nAnd the whole thing will propagate through the system in the right way.\n\n1225\n01:17:14,790 --> 01:17:18,768\n或者突然你说 我有另一种方法来表示有理数\nOr if suddenly you said, gee, I have another representation for rationals.\n\n1226\n01:17:19,700 --> 01:17:23,904\n我就得不断地在表格中添加运算\nAnd I'm going to stick it here, by filing those operations in the table.\n\n1227\n01:17:24,820 --> 01:17:27,220\n那么突然之间所有的多项式\nThen suddenly all of these polynomials whose coefficients\n\n1228\n01:17:27,220 --> 01:17:29,104\n它们的系数和系数的系数 或者什么东西\nare coefficients of coefficients, or whatever,\n\n1229\n01:17:29,240 --> 01:17:32,400\n都自动支持用这种表示方法来表示了\nalso can automatically have available that representation.\n\n1230\n01:17:32,704 --> 01:17:34,672\n这就是我们这种设计的威力\nThat's the power of this particular one.\n\n1231\n01:17:36,112 --> 01:17:38,700\n学生：我提的这个问题可能听起来比较蠢\nAUDIENCE: I'm not sure if I can even pose an intelligent sounding question.\n\n1232\n01:17:38,700 --> 01:17:42,384\n整个这个系统看起来\nBut somehow this whole thing went really nicely\n\n1233\n01:17:42,540 --> 01:17:45,888\n非常完美 所有的东西都各就各位\nto this beautiful finish where all the things seemed to fall into place.\n\n1234\n01:17:46,720 --> 01:17:48,672\n完美得有点出乎意料\nAnd sort of seemed a little contrived.\n\n1235\n01:17:50,930 --> 01:17:52,528\n我相信 这都是为了教学方便\nThat's all for the sake, I'm sure, of teaching.\n\n1236\n01:17:52,560 --> 01:17:54,656\n我怀疑的是首先发明了这种做法的人\nI doubt that the guys who first did this--\n\n1237\n01:17:55,100 --> 01:17:55,856\n我可能说得不对\nand I could be wrong--\n\n1238\n01:17:56,608 --> 01:17:59,728\n难道一下子就搞清楚了所有这些东西一起\nfigured it all out so that when they just all put it all together,\n\n1239\n01:17:59,776 --> 01:18:03,936\n只要把这些放在一起 你就突然可以对各种对象做各种运算\nyou could all of the sudden, blam, do any kind of arithmetic on any kind of object.\n\n1240\n01:18:04,860 --> 01:18:07,200\n我觉得他们应该研究了很长时间\nIt seems like maybe they had to play with it for a while\n\n1241\n01:18:07,930 --> 01:18:10,624\n不断地推倒重来\nand had to bash it and rework it.\n\n1242\n01:18:11,800 --> 01:18:14,120\n然后我觉得 当我们设计一个非常复杂的系统\nAnd it seems like that's the kind of problem we're really\n\n1243\n01:18:14,120 --> 01:18:16,940\n我们也要面对这样的问题\nfaced with we start trying to design a really complex system\n\n1244\n01:18:17,310 --> 01:18:20,352\n就是有太多各种各样的部件 我们甚至不知道\nis having lots of different kinds of parts and not even knowing\n\n1245\n01:18:21,088 --> 01:18:24,620\n我们甚至不知道要对这些部件做什么样的操作\nwhat kinds of operations we're going to want to do on those parts.\n\n1246\n01:18:24,620 --> 01:18:26,544\n在这种时候我怎么用这种良好的方法组织操作\nHow to organize the operations in this nice way\n\n1247\n01:18:26,560 --> 01:18:29,630\n才能获得这种 不管怎样只要把它们放在一起\nso that no matter what you do, when you start putting them together\n\n1248\n01:18:29,630 --> 01:18:31,392\n所有事情就正常运转 这样的效果呢\neverything starts falling out for free.\n\n1249\n01:18:31,700 --> 01:18:34,340\n教授：很好 这确实是一个非常聪明的问题\nPROFESSOR: OK, well that's certainly a very intelligent question... Um\n\n1250\n01:18:35,104 --> 01:18:39,520\n要说的一点是我们这种方法论\nUm....One part is this is a very good methodology\n\n1251\n01:18:39,872 --> 01:18:43,888\n受到了符号代数的很多启发\nthat people have discovered a lot coming from symbolic algebra.\n\n1252\n01:18:44,590 --> 01:18:45,904\n符号代数相当繁复\nBecause there are a lot of complications.\n\n1253\n01:18:47,590 --> 01:18:50,710\n允许你在决定各种运算是什么样子之前\nTo allow you to implement these things before you decide\n\n1254\n01:18:50,710 --> 01:18:52,896\n来实现这个系统\nwhat you want all the operations to be, and all of that.\n\n1255\n01:18:53,310 --> 01:18:57,728\n所以从某种意义上讲 这是人们在这方面长期探索之后得出的答案\nSo in some sense it's an answer that people have discovered by wading through this stuff.\n\n1256\n01:18:58,560 --> 01:19:00,752\n从另一个角度来说 这确实是精心设计的例子\nIn another sense, it is a very contrived example.\n\n1257\n01:19:02,160 --> 01:19:06,240\n学生：看上去想要设计出这样的系统\nAUDIENCE: It seems like to be able to do this you do have to\n\n1258\n01:19:06,240 --> 01:19:09,010\n一开始先要研究一段时间然后才能变熟练\nwade through it for a certain amount of time before you can become good at it.\n\n1259\n01:19:09,010 --> 01:19:11,888\n教授：我给你看看这个东西是多么的勉强\nPROFESSOR: Let me show you how terribly contrived this is.\n\n1260\n01:19:12,220 --> 01:19:14,130\n你现在可以写下所有的这些程序\nSo you can write all these wonderful things.\n\n1261\n01:19:14,130 --> 01:19:16,256\n但是我写在这里的这个系统\nBut the system that I wrote here,\n\n1262\n01:19:17,020 --> 01:19:18,960\n如果允许我拖堂半小时的话\nand if we had another half an hour to give this lecture\n\n1263\n01:19:19,310 --> 01:19:20,464\n我会给大家讲\nI would have given this part of it,\n\n1264\n01:19:20,816 --> 01:19:23,024\n如果我让它做一个错误操作\nwhich says, notice that it breaks down\n\n1265\n01:19:23,200 --> 01:19:29,312\n比如一个愚蠢的命令 用3加上7/2 它就会崩溃\nif I tell it to do something as foolish as add 3 plus 7/2.\n\n1266\n01:19:30,880 --> 01:19:33,424\n因为程序首先会调用operate-2这个过程\nBecause what will happen is you'll get to operate-2,\n\n1267\n01:19:33,800 --> 01:19:35,952\n然后operate-2会说 这个是数字类型\nand operate-2 will say, oh this is type number,\n\n1268\n01:19:36,180 --> 01:19:37,376\n那个是有理数类型\nand that's type rational.\n\n1269\n01:19:37,560 --> 01:19:38,810\n我不知道怎么把它们加起来\nI don't know how to add them.\n\n1270\n01:19:41,530 --> 01:19:44,304\n那么你想让这个系统至少能够\nSo you'd like the system at least to be able to say something like,\n\n1271\n01:19:45,888 --> 01:19:47,344\n比如说 在做这个操作之前\ngee,before you do that\n\n1272\n01:19:48,592 --> 01:19:50,240\n把3提升为3/1\nchange that to 3/1.\n\n1273\n01:19:50,480 --> 01:19:53,216\n把它变成一个有理数 然后交给有理数程序包来处理\nTurn it into a rational number, hand that to the rational package.\n\n1274\n01:19:54,860 --> 01:19:58,704\n课堂上我们来不及讲这个问题了\nThat's the thing I didn't talk about in this lecture.\n\n1275\n01:19:58,736 --> 01:20:00,880\n书里面讨论了这个问题\nIt's a little bit in the book,which talks about the problem\n\n1276\n01:20:00,880 --> 01:20:01,952\n叫做“类型转换”\nof what's called coercion.\n\n1277\n01:20:03,390 --> 01:20:05,152\n你想要的是\nWhere you wanted--\n\n1278\n01:20:05,310 --> 01:20:08,896\n看 我们小心翼翼地把对象按类型分好类\nsee, having so carefully set up all of these types as distinct objects\n\n1279\n01:20:08,910 --> 01:20:12,176\n但是有时你也想让它\na lot of times you want to also put in knowledge\n\n1280\n01:20:12,400 --> 01:20:17,984\n知道怎么把一个普通的数字当成有理数\nabout how to view an ordinary number as a kind of rational.\n\n1281\n01:20:19,110 --> 01:20:21,296\n或者把普通的数字当成复数\nOr view an ordinary number as a kind of complex.\n\n1282\n01:20:21,620 --> 01:20:25,168\n到那个时候系统就开始变得复杂了\nThat's where the complexity in the system really starts happening\n\n1283\n01:20:25,760 --> 01:20:28,128\n就是你去思考 我应该把这些知识放在哪里的时候\nwhere you talk about, see where do I put that knowledge?\n\n1284\n01:20:28,420 --> 01:20:32,192\n是应该让有理数知道它们是由普通的数字构成的吗？\nIs it rational to know that ordinary numbers might be pieces of cons of them?\n\n1285\n01:20:33,130 --> 01:20:36,384\n或者我们举一个更加糟糕的例子\nOr they're terrible, terrible examples, like\n\n1286\n01:20:38,144 --> 01:20:47,488\n比如说我想要把一个复数加到有理数上去\nif I might want to add a complex number to a rational number.\n\n1287\n01:20:49,872 --> 01:20:50,760\n这个不好\nBad example.\n\n1288\n01:20:50,760 --> 01:20:51,584\n5/7\n5/7.\n\n1289\n01:20:53,860 --> 01:20:55,728\n然后整个系统里必须有人知道\nThen somebody's got to know that\n\n1290\n01:20:56,060 --> 01:20:58,160\n他需要把这个东西变成另一种类型\nI have to convert these to another type,\n\n1291\n01:20:58,208 --> 01:21:00,656\n要把它变成一部分是有理数的复数\nwhich is complex numbers whose parts might be rationals.\n\n1292\n01:21:01,540 --> 01:21:02,680\n那么谁应该去操心这个事情呢\nAnd who worries about that?\n\n1293\n01:21:02,680 --> 01:21:03,950\n是complex程序包吗？\nDoes complex worry about that?\n\n1294\n01:21:03,950 --> 01:21:05,030\n是rational程序包吗？\nDoes rational worry about that?\n\n1295\n01:21:05,248 --> 01:21:06,224\n还是plus过程要考虑这个问题？\nDoes plus worry about that?\n\n1296\n01:21:06,900 --> 01:21:08,520\n这就是体现复杂性的地方\nThat's where the real complexity comes in.\n\n1297\n01:21:08,520 --> 01:21:11,380\n也是这个问题的特别之处\nAnd that's where it's pretty well sorted out.\n\n1298\n01:21:11,380 --> 01:21:14,128\n同时很多的 实际上是所有的这样的“消息传递”的想法\nAnd a lot of, in fact, all of this message passing stuff\n\n1299\n01:21:14,640 --> 01:21:16,544\n都是被这样的问题启发的\nwas motivated by problems like this.\n\n1300\n01:21:18,460 --> 01:21:20,896\n当你真正深入进去\nAnd when you really push it, people are--\n\n1301\n01:21:20,912 --> 01:21:24,768\n人们发现 代数操作的问题是如此复杂\nsomehow the algebraic manipulation problem seems to be so complex\n\n1302\n01:21:25,184 --> 01:21:27,410\n而那些一直围绕它们工作的人们 确实就处在\nthat the people who are always at the edge of it are exactly in\n\n1303\n01:21:27,410 --> 01:21:28,050\n你说的那种状态\nthe state you said.\n\n1304\n01:21:28,050 --> 01:21:29,712\n他们在这些问题里艰难跋涉 时不时陷进泥里\nThey're wading through this thing, mucking around,\n\n1305\n01:21:29,728 --> 01:21:31,376\n寻找好用的工具 并试着提炼一种通用方法\nseeing what they use, trying to distill stuff.\n\n1306\n01:21:34,200 --> 01:21:37,760\n学生：我想再一次回到这个复杂度的问题上来\nAUDIENCE: I just want to come back to this issue of complexity once more.\n\n1307\n01:21:38,416 --> 01:21:44,550\n在修改底层过程的时候 这个系统\nUm... It certainly seems to be true that you have a great deal of\n\n1308\n01:21:44,550 --> 01:21:48,320\n毫无疑问 体现了非常大的灵活性\nflexibility in altering the lower level kinds of things.\n\n1309\n01:21:49,712 --> 01:21:53,408\n但是确实 在某种意义上讲\nBut it is true that you are, in a sense,\n\n1310\n01:21:53,440 --> 01:21:55,264\n冻结了高层运算\nfreezing higher level operations.\n\n1311\n01:21:55,450 --> 01:21:58,510\n或者至少如果你修改它们 你不知道\nOr at least if you change them you don't know where all of\n\n1312\n01:21:58,510 --> 01:22:02,060\n改动会体现在哪里 会怎么体现出来\nthe changes are going to show up, or how they are.\n\n1313\n01:22:02,208 --> 01:22:04,224\n教授：这个问题真是不能再好了\nPROFESSOR: OK, that's an extremely good question.\n\n1314\n01:22:04,680 --> 01:22:05,872\n我要做的事情就是\nWhat I have to do is,\n\n1315\n01:22:08,688 --> 01:22:10,848\n如果我决定添加一个通用操作\nif I decide there's a new general operation\n\n1316\n01:22:11,456 --> 01:22:13,072\n比如equality-test\ncalled equality test,\n\n1317\n01:22:14,960 --> 01:22:17,152\n那么系统中的其它人就要查表格\nthen all of these people have to decide\n\n1318\n01:22:18,224 --> 01:22:22,544\n来看他们需不需要支持equality-test\nwhether or not they would like to have an equality test by looking in the table.\n\n1319\n01:22:24,650 --> 01:22:26,848\n我们可以让它变得更加去中心化\nThere're ways to decentralize it even more.\n\n1320\n01:22:27,870 --> 01:22:30,704\n这就是之前我提示了很多次的事情\nThat's what I sort of hinted at last time, where I said\n\n1321\n01:22:31,088 --> 01:22:33,264\n你不但可以通过给对象添加符号标签来体现类型\nyou could not only have this type as a symbol,\n\n1322\n01:22:33,408 --> 01:22:38,704\n而是把每一类对象接受的运算也保存在里面\nbut you actually might store in each object the operations that it knows of that.\n\n1323\n01:22:40,450 --> 01:22:43,904\n那么你可以添加一个 比如说最大公约数过程\nSo you might have things like greatest common divisor,\n\n1324\n01:22:44,432 --> 01:22:46,816\n它只能计算整数\nwhich is a thing here which is defined only for integers,\n\n1325\n01:22:47,408 --> 01:22:49,216\n而不是对所有有理数都通用\nand not in general for rational numbers.\n\n1326\n01:22:51,030 --> 01:22:53,110\n所以这个系统可能是非常非常碎片化的\nSo it might be a very, very fragmented system.\n\n1327\n01:22:53,110 --> 01:22:55,664\n取决于你想让哪一部分比较灵活\nAnd then depending on where you want your flexibility,\n\n1328\n01:22:56,224 --> 01:22:59,024\n有一系列的地方让你把这个东西放进去\nYou...there's a whole spectrum of places that you  can build that in.\n\n1329\n01:22:59,960 --> 01:23:02,560\n但是你也指出了这种设计的弱点\nBut you're pointing at the place where this starts being weak,\n\n1330\n01:23:02,608 --> 01:23:06,370\n就是必须在顶层 对于这些通用运算符有一些约定\nthat there has to be some agreement on top here about these general operations.\n\n1331\n01:23:06,370 --> 01:23:07,824\n或者至少人们要考虑这件事情\nOr at least people have to think about them.\n\n1332\n01:23:08,390 --> 01:23:10,720\n或者你可以决定 把这个表格设计得非常稀疏\nOr you might decide, you might have a table that's very sparse\n\n1333\n01:23:10,752 --> 01:23:11,968\n里面只放很少的一点东西\nthat only has a few things in it.\n\n1334\n01:23:14,010 --> 01:23:15,490\n这个游戏有很多种玩法\nBut there are lot of ways to play that game.\n\n1335\n01:23:19,780 --> 01:23:20,432\n谢谢大家\nOK, thank you.\n\n1336\n01:23:23,530 --> 01:23:28,784\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n1337\n01:23:28,780 --> 01:23:36,560\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n\n"
  },
  {
    "path": "SrtCN/lec5a.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:01,968\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:01,980 --> 00:00:04,560\n翻译&&时间轴：杨启钊（windfarer）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:04,560 --> 00:00:06,560\n特别感谢：裘宗燕教授\n\n4\n00:00:06,656 --> 00:00:09,472\n计算机程序的构造和解释\n\n5\n00:00:09,920 --> 00:00:13,632\n赋值、状态和副作用\nAssignment, State, and Side-effects\n\n6\n00:00:18,311 --> 00:00:22,000\n教授：到目前为止 我们已经教了很多编程技巧\nPROFESSOR: Well, so far we've invented enough programming\n\n7\n00:00:22,256 --> 00:00:24,064\n来编写复杂程序了\nto do some very complicated things.\n\n8\n00:00:24,768 --> 00:00:29,660\n并且 到目前为止 关于编程你们学到了很多\nAnd you surely learned a lot about programming at this point.\n\n9\n00:00:29,660 --> 00:00:31,488\n你们已经学习了几乎所有的\nYou've learned almost all the most important tricks\n\n10\n00:00:31,860 --> 00:00:35,872\n那些拥有大量经验的人 才能领悟的技巧\nthat usually don't get taught to people until they have had a lot of experience.\n\n11\n00:00:36,416 --> 00:00:40,080\n例如 数据导向编程就是一个主要的技巧\nFor example, data directed programming is a major trick,\n\n12\n00:00:40,750 --> 00:00:43,152\n昨天 你们也学习了一种解释型语言\nand yesterday you also saw an interpreted language.\n\n13\n00:00:45,024 --> 00:00:48,460\n我们所做的这一切\nWe did this all in a computer language,\n\n14\n00:00:48,544 --> 00:00:49,632\n目前来讲\nat this point,\n\n15\n00:00:49,888 --> 00:00:51,952\n都是在一种没有赋值语句的计算机语言中完成的\nwhere there was no assignment statement.\n\n16\n00:00:53,770 --> 00:00:58,176\n对于你们中用过Basic或者Pascal的人\nAnd presumably, for those of you who've seen your Basic or Pascal or whatever,\n\n17\n00:00:58,688 --> 00:01:01,232\n可能会认为“赋值”是最重要的东西\nthat's usually considered the most important thing.\n\n18\n00:01:01,792 --> 00:01:03,820\n今天我们将要做一些糟糕的事情\nWell today, we're going to do something horrible.\n\n19\n00:01:03,820 --> 00:01:05,456\n我们要把赋值语句加进来\nWe're going to add an assignment statement.\n\n20\n00:01:07,216 --> 00:01:09,140\n既然在没有赋值语句的时候 我们都可以很好地完成工作\nAnd since we can do all these wonderful things without it,\n\n21\n00:01:09,140 --> 00:01:10,176\n为什么我们还要把它加进来呢？\nwhy should we add it?\n\n22\n00:01:10,990 --> 00:01:12,432\n为了理解它\nAn important thing to understand it\n\n23\n00:01:12,464 --> 00:01:15,710\n我们今天首先要定下一个规则\nis that today we're going to first of all, have a rule,\n\n24\n00:01:16,480 --> 00:01:17,930\n而我们将一直遵守这个规则\nwhich is going to always be obeyed,\n\n25\n00:01:17,930 --> 00:01:20,800\n这是我们为语言引入新的特性的唯一原因\nwhich is the only reason we ever add a feature to our language\n\n26\n00:01:21,536 --> 00:01:23,140\n是因为我们有一个好的理由\nis because there is a good reason.\n\n27\n00:01:23,936 --> 00:01:27,280\n好的理由归结为能力\nAnd the good reason is going to boil down to the ability,\n\n28\n00:01:27,424 --> 00:01:31,510\n你现在获得了把问题分解为不同部分的能力\nyou now get an ability to break a problem into pieces that are different sets of pieces\n\n29\n00:01:31,510 --> 00:01:33,440\n在没有相关能力之前可不行\nthen you could have broken it down without that,\n\n30\n00:01:34,384 --> 00:01:36,160\n这让你有用来分解问题的另外方法\ngive you another means of decomposition.\n\n31\n00:01:38,304 --> 00:01:39,450\n我们这就开始\nHowever, let's just start.\n\n32\n00:01:39,450 --> 00:01:41,880\n从回顾我们的\nLet me quick begin by reviewing\n\n33\n00:01:41,880 --> 00:01:47,376\n现在已经有的这种语言出发\nthe kind of language that we have now.\n\n34\n00:01:48,160 --> 00:01:50,448\n我们之前写的是所谓的函数式程序\nWe've been writing what's called functional programs.\n\n35\n00:01:51,216 --> 00:01:52,528\n函数式程序\nAnd functional programs\n\n36\n00:01:53,040 --> 00:01:57,952\n是一种对数学事实的编码\nare a kind of encoding of mathematical truths.\n\n37\n00:01:58,880 --> 00:02:00,510\n例如 当我们看到\nFor example, when we look at\n\n38\n00:02:00,510 --> 00:02:04,096\n像幻灯片上这样阶乘过程时\nthe factorial procedure that you see on the slide here,\n\n39\n00:02:05,072 --> 00:02:06,624\n基本上是两个子句\nit's basically two clauses.\n\n40\n00:02:06,992 --> 00:02:08,640\n如果n是1 则结果是1\nIf n is one, the result is one,\n\n41\n00:02:08,640 --> 00:02:11,200\n否则返回n乘以n-1的阶乘\notherwise n times factorial n minus one.\n\n42\n00:02:11,200 --> 00:02:12,336\n这是n的阶乘\nThat's factorial of n.\n\n43\n00:02:12,896 --> 00:02:14,272\n它就是阶乘函数\nWell, that is factorial of n.\n\n44\n00:02:14,832 --> 00:02:16,870\n如果用一些其他的记号\nAnd written down in some other obscure notation\n\n45\n00:02:16,870 --> 00:02:19,328\n那些你在微积分课堂上学到的晦涩的符号来写\nthat you might have learned in calculus classes,\n\n46\n00:02:20,304 --> 00:02:22,110\n用数理逻辑来写\nAhh.. mathematical logic,\n\n47\n00:02:22,110 --> 00:02:26,368\n如果n等于1\nwhat you see there is if n equals one,\n\n48\n00:02:27,136 --> 00:02:29,900\n那么n的阶乘结果是1 否则\nfor the result of n factorial is one, otherwise,\n\n49\n00:02:29,900 --> 00:02:32,560\n如果n大于1 则n的阶乘就是n * (n-1)!\ngreater than one, n factorial is n times n minus one factorial.\n\n50\n00:02:32,560 --> 00:02:33,552\n数学事实\nTrue statements,\n\n51\n00:02:34,928 --> 00:02:36,700\n就是我们一直使用的那种语言\nthat's the kind of language we've been using.\n\n52\n00:02:37,008 --> 00:02:39,230\n无论何时 我们遇到了这样的数学事实\nAnd whenever we have true statements of that sort,\n\n53\n00:02:39,536 --> 00:02:46,656\n有一种理解它们工作原理的方法\nthere is a kind of, a way of understanding how they work\n\n54\n00:02:47,408 --> 00:02:51,120\n就是这些过程可以由代换演算而来\nwhich is that such processes can be evolved by substitution.\n\n55\n00:02:51,296 --> 00:02:53,712\n来看第二张幻灯片\nAnd so we see on the second slide here,\n\n56\n00:02:54,992 --> 00:02:58,816\n我们理解执行的过程\nthat the way we understand the execution\n\n57\n00:02:58,832 --> 00:03:03,500\n隐含在表达式的顺序中\nimplied by those statements in arranged in that order,\n\n58\n00:03:04,040 --> 00:03:07,760\n也就是你不断地将实际参数\nis that you do successive substitutions of arguments\n\n59\n00:03:07,870 --> 00:03:10,880\n代换到程序体的形式参数中\nfor formal parameters in the body of a procedure.\n\n60\n00:03:12,000 --> 00:03:14,512\n这些基本上是一系列的等价代换\nThis is basically a sequence of equalities.\n\n61\n00:03:14,610 --> 00:03:17,250\n4的阶乘是4乘以3的阶乘\nFactorial four is four times factorial three.\n\n62\n00:03:17,250 --> 00:03:20,050\n也就是4乘以3乘以2的阶乘\nThat is four times three times factorial of two\n\n63\n00:03:20,050 --> 00:03:21,010\n以此类推\nand so on.\n\n64\n00:03:21,232 --> 00:03:23,872\n我们总是保持数学事实成立\nWe're always preserving truth.\n\n65\n00:03:25,232 --> 00:03:28,840\n尽管我们正在讨论数学事实\nEven though we're talking about true statements,\n\n66\n00:03:28,840 --> 00:03:31,960\n可能有多种数学事实的组织方式\nthere might be more than one organization of these true statements\n\n67\n00:03:31,960 --> 00:03:35,120\n用来描述一个特定的函数的计算\nto describe the computation of a particular function,\n\n68\n00:03:36,320 --> 00:03:38,420\n这个特定的函数的值的计算\nthe computation of the value of a particular function.\n\n69\n00:03:38,420 --> 00:03:40,928\n所以 让我来看下这里的例子\nSo, for example, looking at the next one here.\n\n70\n00:03:41,488 --> 00:03:49,020\n这有一个计算m与n之和的方法\nHere is a way of looking at the sum of n and m.\n\n71\n00:03:49,536 --> 00:03:52,048\n我们使用一个递归的过程来完成\nAnd we did this one by a recursive process.\n\n72\n00:03:52,896 --> 00:03:58,160\n也就是(1+ (+ (-1+ n) m))\nIt's the increment of the sum of the decrement of n and m.\n\n73\n00:04:00,080 --> 00:04:05,620\n当然 这里也有相应的数理逻辑 解释了这个方法\nAnd, of course, there is some piece of mathematical logic here that describes that.\n\n74\n00:04:06,176 --> 00:04:10,496\n也就是((n-1)+m)+1\nIt's the increment of the sum of the decrement of n and m,\n\n75\n00:04:11,408 --> 00:04:12,224\n跟之前那个一样\njust like that.\n\n76\n00:04:13,104 --> 00:04:16,400\n所以这儿并没有什么特殊的魔法\nSo there's nothing particularly magic about that.\n\n77\n00:04:16,416 --> 00:04:20,010\n当然 如果我们可以再来看一个相同的迭代过程\nAnd, of course, if we can also look at an iterative process for the same,\n\n78\n00:04:20,192 --> 00:04:24,920\n计算同样的函数 但是进行逐步迭代的程序\na program that evolves an iterative process, for the same function.\n\n79\n00:04:25,264 --> 00:04:27,568\n这两个程序将得到同样的结果\nThese are two things that compute the same answer.\n\n80\n00:04:30,080 --> 00:04:34,832\n我们就可以认为这两个程序在数学上是等效的\nAnd we have equivalent mathematical truths that are arranged there.\n\n81\n00:04:36,656 --> 00:04:39,936\n你对这些数学事实的排序 决定了具体（计算）过程\nAnd just the way you arrange those truths determine the particular process.\n\n82\n00:04:40,304 --> 00:04:43,424\n我们对于这些数学事实的排序和选择 决定了过程发展的方式\nIn the way choose and arrange them determines the process that's evolved.\n\n83\n00:04:44,336 --> 00:04:48,600\n因此我们可以灵活地讨论待计算的函数\nSo we have the flexibility of talking about both the function to be computed,\n\n84\n00:04:48,600 --> 00:04:50,192\n以及计算该函数的所用的方法\nand the method by which it's computed.\n\n85\n00:04:50,600 --> 00:04:52,600\n这并不清晰 我们需要再深入一些\nSo it's not clear we need more.\n\n86\n00:04:53,616 --> 00:04:55,500\n然而 今天我要来讲这个糟糕的东西\nHowever, today I'm going to this awful thing.\n\n87\n00:04:55,500 --> 00:04:58,432\n我要给大家介绍赋值操作\nI'm going to introduce this assignment operation.\n\n88\n00:04:58,896 --> 00:05:00,416\n这是什么？\nNow, what is this?\n\n89\n00:05:02,896 --> 00:05:09,220\n首先 在编程语言中有另一种语句\nWell, first of all, there is going to be another kind of kind of statement, if you will,\n\n90\n00:05:09,220 --> 00:05:10,848\n这种语句叫做SET!\nin a programming language called Set!\n\n91\n00:05:12,410 --> 00:05:15,968\n具有赋值操作的语句\nAnd SET! -- Things that do things like assignment,\n\n92\n00:05:15,984 --> 00:05:17,850\n我都会在后面加上一个感叹号\nI'm going to put exclamation points after.\n\n93\n00:05:18,512 --> 00:05:20,960\n这个感叹号代表什么意思呢？\nWe'll talk about what that means in a second.\n\n94\n00:05:20,960 --> 00:05:23,010\n这个感叹号 与问号类似\nThe exclamation point, again like question mark,\n\n95\n00:05:23,010 --> 00:05:25,880\n是我们给名字随意加的符号\nis an arbitrary thing we attach to the symbol which is the name,\n\n96\n00:05:25,880 --> 00:05:27,880\n它对于系统来说没有意义\nhas no significance to the system.\n\n97\n00:05:28,080 --> 00:05:30,210\n它唯一的意义就是告诉我们\nThe only significance is to me and you\n\n98\n00:05:30,400 --> 00:05:34,416\n注意这里是某种赋值操作\nto alert you that this is an assignment of some sort.\n\n99\n00:05:35,880 --> 00:05:40,064\n但是我们要给某个变量赋一个值\nBut we're going to set a variable to a value.\n\n100\n00:05:43,744 --> 00:05:45,130\n这意味着\nAnd what that's going to mean\n\n101\n00:05:45,130 --> 00:05:48,288\n在某个时间点发生了一些事情\nis that there is a time at which something happens.\n\n102\n00:05:48,656 --> 00:05:49,616\n这是一个时间点\nHere's a time.\n\n103\n00:05:49,860 --> 00:05:52,144\n如果时间以这个方向流动\nIf I have time going this way,\n\n104\n00:05:53,504 --> 00:05:54,820\n这是个时间轴\nit's a time axis.\n\n105\n00:05:55,008 --> 00:05:57,820\n时间在平面上由上到下地流逝\nTime progresses by walking down the page.\n\n106\n00:05:58,704 --> 00:06:00,920\n赋值是第一个\nThen an assignment is the first thing we have\n\n107\n00:06:00,920 --> 00:06:04,304\n使过去和未来之间产生差别的事物\nthat produces the difference between a before and an after.\n\n108\n00:06:06,592 --> 00:06:08,720\n我们之前写的所有程序\nAll the other programs that we've written,\n\n109\n00:06:09,184 --> 00:06:10,680\n都不包含赋值\nthat have no assignments in them,\n\n110\n00:06:10,680 --> 00:06:13,120\n这些程序以怎样的顺序进行执行都没关系\nthe order in which they were evaluated didn't matter.\n\n111\n00:06:14,704 --> 00:06:15,960\n但是赋值比较特殊\nBut assignment is special,\n\n112\n00:06:15,960 --> 00:06:17,696\n它使时间中产生了一个时间点\nit produces a moment in time.\n\n113\n00:06:17,960 --> 00:06:24,736\n因此在SET!出现之前和之后中间有一个时间点\nSo there is a moment before the set occurs and after,\n\n114\n00:06:27,616 --> 00:06:32,704\n使得在这个时间点之后\nsuch that after this moment in time,\n\n115\n00:06:33,600 --> 00:06:43,760\n变量有了一个值 即VALUE\nthe variable has the value, value.\n\n116\n00:06:49,232 --> 00:06:51,504\n与这个变量之前的值无关\nIndependent of what value it had before,\n\n117\n00:06:52,800 --> 00:06:55,792\nSET!改变了它的值\nset! changes the value of the variable.\n\n118\n00:06:57,696 --> 00:06:58,750\n在此之前\nUntil this moment,\n\n119\n00:06:58,750 --> 00:07:01,504\n什么都没有发生改变\nwe had nothing that changed.\n\n120\n00:07:03,216 --> 00:07:04,112\n举例来说\nSo, for example,\n\n121\n00:07:04,848 --> 00:07:06,230\n我们可以想到的一件事是\none of the things we can think of\n\n122\n00:07:06,230 --> 00:07:09,420\n我们写的一些过程 比如阶乘的程序\nis that the procedures we write for something like factorial\n\n123\n00:07:09,648 --> 00:07:12,752\n事实上与数学中的阶乘函数完全相同\nare in fact pretty much identical to the function factorial.\n\n124\n00:07:13,776 --> 00:07:16,448\n比如说4的阶乘 如果我写FACT(4)\nFactorial of four, if I write fact4,\n\n125\n00:07:17,232 --> 00:07:19,152\n无论它的上下文是怎样的\nindependent of what context it's in,\n\n126\n00:07:19,696 --> 00:07:21,290\n无论我写几遍\nand independent of how many times I write it,\n\n127\n00:07:21,290 --> 00:07:22,352\n我总能得到同样的结果\nI always get the same answer.\n\n128\n00:07:23,290 --> 00:07:24,128\n结果永远是24\nIt's always 24.\n\n129\n00:07:25,376 --> 00:07:28,928\n它是参数到到结果的唯一映射\nIt's a unique map from the argument to the answer.\n\n130\n00:07:30,304 --> 00:07:32,656\n迄今为止 我们之前写的所有程序都是这样的\nAnd all the programs we've written so far are like that.\n\n131\n00:07:33,520 --> 00:07:36,032\n然而 当引入赋值后 一切就不同了\nHowever, once I have assignment, that isn't true.\n\n132\n00:07:36,960 --> 00:07:38,160\n举个例子\nSo, for example,\n\n133\n00:07:39,184 --> 00:07:48,528\n如果我将COUNT定义为1\nif I were to define count to be one.\n\n134\n00:07:50,000 --> 00:07:52,416\n然后定义一个过程\nAnd then I'm going to define also a procedure,\n\n135\n00:07:55,168 --> 00:07:56,832\n一个叫做DEMO的简单过程\na simple procedure called demo,\n\n136\n00:07:59,520 --> 00:08:03,840\n它接受参数X 并执行下面的操作\nwhich takes argument x and does the following operations.\n\n137\n00:08:03,840 --> 00:08:09,620\n首先将X修改为X+1\nIt first sets x to x plus one.\n\n138\n00:08:09,620 --> 00:08:11,776\n我的天啊！ 这看起来就像FORTRAN是吧？\nMy gosh, this looksjust like FORTRAN, right--\n\n139\n00:08:13,168 --> 00:08:14,176\n只是用了些有趣的语法\nin a funny syntax.\n\n140\n00:08:16,800 --> 00:08:21,376\n然后返回(+ X COUNT)\nAnd then add to x count,\n\n141\n00:08:22,144 --> 00:08:24,144\n哦 我刚犯了个错\nOh, I just made a mistake.\n\n142\n00:08:24,384 --> 00:08:25,232\n我的意思是\nI want to say,\n\n143\n00:08:25,472 --> 00:08:27,120\n(SET! COUNT (1+ COUNT))\nset! count to one plus count.\n\n144\n00:08:30,370 --> 00:08:31,792\n就是我在这里定义的这个\nIt's this thing defined here.\n\n145\n00:08:34,416 --> 00:08:36,512\n然后X和COUNT相加\nAnd then add and said plus x count.\n\n146\n00:08:40,352 --> 00:08:42,064\n然后就可以试着运行这个过程了\nThen I can try this procedure.\n\n147\n00:08:42,480 --> 00:08:43,200\n让我们运行它\nLet's run it.\n\n148\n00:08:43,920 --> 00:08:47,220\n假设我可以输入\nSo, suppose I get a prompt and I say,\n\n149\n00:08:47,488 --> 00:08:48,688\n输入(DEMO 3)\ndemo 3\n\n150\n00:08:52,192 --> 00:08:53,200\n这里发生了什么？\nWell, what happens here?\n\n151\n00:08:53,740 --> 00:08:55,280\n发生的第一件事情是\nThe first thing that happens\n\n152\n00:08:55,536 --> 00:08:56,890\nCOUNT现在是1\nis count is currently one.\n\n153\n00:08:56,890 --> 00:08:58,400\n现在 这是一个时间点\nCurrently, there is a time.\n\n154\n00:08:59,120 --> 00:09:00,290\n我们在讨论时间点\nWe're talking about time.\n\n155\n00:09:00,624 --> 00:09:01,744\nX的值为3\nx gets three.\n\n156\n00:09:02,928 --> 00:09:04,032\n在这个时刻\nAt this moment,\n\n157\n00:09:04,672 --> 00:09:07,536\nCOUNT增加了 所以COUNT是2\nI say, oh yes, count is incremented, so count is two.\n\n158\n00:09:09,024 --> 00:09:10,448\n2加3等于5\ntwo plus three is five.\n\n159\n00:09:10,800 --> 00:09:12,432\n所以结果是5\nSo the answer I get out is five.\n\n160\n00:09:14,480 --> 00:09:21,584\n然后我再一次 输入(DEMO 3)\nThen I say, demo of say, three again.\n\n161\n00:09:23,600 --> 00:09:24,560\n结果是什么？\nOkay, What do I get?\n\n162\n00:09:24,830 --> 00:09:27,408\n现在COUNT是2 它不再是1了\nWell, now count is two, it's not one anymore,\n\n163\n00:09:28,912 --> 00:09:30,352\n因为我让COUNT加1了\nbecause I have incremented it.\n\n164\n00:09:30,920 --> 00:09:32,640\n但现在我执行这个过程\nBut now I go through this process,\n\n165\n00:09:32,720 --> 00:09:33,664\nX的值为3\nthree goes into x,\n\n166\n00:09:34,176 --> 00:09:37,408\nCOUNT变为1+COUNT 因此现在是3了\ncount becomes one plus count, so that's three now.\n\n167\n00:09:38,080 --> 00:09:39,620\n这两个相加是6\nThe sum of those two is six,\n\n168\n00:09:39,620 --> 00:09:40,944\n所以结果是6\nso the answer is six.\n\n169\n00:09:41,920 --> 00:09:43,030\n我们可以发现\nAnd what we see\n\n170\n00:09:43,030 --> 00:09:44,720\n同样的表达式\nis the same expression\n\n171\n00:09:45,088 --> 00:09:46,640\n因为时间节点的不同\nleads to two different answers,\n\n172\n00:09:48,752 --> 00:09:49,968\n得到了不同的结果\ndepending upon time.\n\n173\n00:09:52,080 --> 00:09:53,744\n所以DEMO不是函数\nSo demo is not a function,\n\n174\n00:09:54,176 --> 00:09:56,128\n或者说它并没有计算一个数学意义上的函数\ndoes not compute a mathematical function.\n\n175\n00:09:59,888 --> 00:10:02,096\n事实上 你可以知道这是为什么\nIn fact, you could also see why now, of course,\n\n176\n00:10:02,848 --> 00:10:06,416\n因为这里是第一处代换模型失效的地方\nthis is the first place where the substitution model isn't going to work.\n\n177\n00:10:07,728 --> 00:10:09,552\n它给代换模型判了死刑\nThis kills the substitution model dead.\n\n178\n00:10:11,280 --> 00:10:13,824\n有些关于引用的一些小问题\nYou know, with quotation there were some little problems\n\n179\n00:10:13,856 --> 00:10:17,180\n哲学家可能注意到 特别是与代换有关时\nthat a philosopher might notice with substitutions,\n\n180\n00:10:17,180 --> 00:10:19,872\n因为当你在引用中进行代换时\nbecause you have to worry about what deductions you can make\n\n181\n00:10:20,912 --> 00:10:22,128\n需要考虑你可以得到什么样的推论\nwhen you substitute into quotes,\n\n182\n00:10:22,340 --> 00:10:23,920\n如果你能够使用代换的话\nif you're allowed to do that at all.\n\n183\n00:10:25,088 --> 00:10:25,600\n但是\nBut\n\n184\n00:10:26,064 --> 00:10:28,000\n在这里代换模型已经失效了\nhere the substitution model is dead,\n\n185\n00:10:28,110 --> 00:10:29,408\n它什么也不能做了\ncan't do anything at all.\n\n186\n00:10:29,640 --> 00:10:30,570\n因为\nBecause,\n\n187\n00:10:30,570 --> 00:10:35,856\n假设我想用代换模型来考虑COUNT的代换\nSupposing I wanted to use a substitution model to consider substituting for count?\n\n188\n00:10:37,104 --> 00:10:41,168\n如果我在这里和这里进行代换\nWell, my gosh, if I substitute for here and here,\n\n189\n00:10:41,696 --> 00:10:42,960\n它们是不同的\nthey're different ones.\n\n190\n00:10:44,448 --> 00:10:45,968\n它不再是同一个COUNT了\nIt's not the same count any more.\n\n191\n00:10:46,480 --> 00:10:47,648\n我得到了错误的结果\nI get the wrong answer.\n\n192\n00:10:47,970 --> 00:10:50,144\n代换模型是一个静态的现象\nThe substitution model is a static phenomenon\n\n193\n00:10:51,184 --> 00:10:52,560\n它描述的事实\ndescribes things that are true\n\n194\n00:10:53,936 --> 00:10:55,296\n而不是变动\nand not things that change.\n\n195\n00:10:55,500 --> 00:10:57,040\n这里 我们的事实变动了\nHere, we have truths that change.\n\n196\n00:11:00,608 --> 00:11:06,740\n那么 在我给出任何解释之前\nOK, Well, before I give you any understanding of this,\n\n197\n00:11:06,740 --> 00:11:07,790\n这很糟糕\nthis is very bad.\n\n198\n00:11:07,790 --> 00:11:09,728\n我们失去了我们的计算模型\nNow, we've lost our model of computation.\n\n199\n00:11:10,288 --> 00:11:10,800\n并且\nAnd,\n\n200\n00:11:11,488 --> 00:11:13,696\n很快 我将不得不构建一个新的计算模型\npretty soon, I'm going to have to build you a new model of computation.\n\n201\n00:11:14,660 --> 00:11:17,872\n我们现在的讨论 还是从一个不严谨的角度进行的\nBut ours plays with this, just now, in an informal sense.\n\n202\n00:11:18,560 --> 00:11:20,160\n当然 你们已经看到的是\nOf course, what you already see\n\n203\n00:11:20,512 --> 00:11:22,704\n当我做一些像赋值之类的事情时\nis that when I have something like assignment,\n\n204\n00:11:23,120 --> 00:11:24,510\n我们所需要的模型\nthe model that we're going to need\n\n205\n00:11:24,510 --> 00:11:26,890\n与我们之前模型不同\nis different from the model that we had before\n\n206\n00:11:26,890 --> 00:11:30,930\n在这个的模型中 像COUNT或X这样的符号\nin that, the variables, those symbols like count, or x\n\n207\n00:11:30,930 --> 00:11:34,070\n不再关联于它们的值\nare no longer going to refer to the values they have,\n\n208\n00:11:34,070 --> 00:11:37,312\n而是关联于某个储存这些值的地方\nbut rather to some sort of place where the value restored.\n\n209\n00:11:37,680 --> 00:11:39,472\n我们将花些时间来适应这种思想\nWe're going to have to think that way for a while.\n\n210\n00:11:40,208 --> 00:11:42,110\n这将是一个很糟糕的事情\nAnd it's going to be a very bad thing\n\n211\n00:11:42,110 --> 00:11:43,472\n并且会造成很多麻烦\nand cause a lot of trouble.\n\n212\n00:11:44,496 --> 00:11:48,250\n所以 就像我说的 若非理由周全\nAnd so, as I said, the very fact that we're inventing this bad thing,\n\n213\n00:11:48,250 --> 00:11:50,096\n不然绝不要发明这种糟糕的东西\nmeans that there had better be a good reason for it,\n\n214\n00:11:50,370 --> 00:11:52,864\n否则 就是劳神费力\notherwise, just a waste of time and a lot of effort.\n\n215\n00:11:53,392 --> 00:11:55,552\n让我们看看一些可以讨论的东西\nLet's just look at some of it just to play.\n\n216\n00:11:55,880 --> 00:11:58,590\n假设我们写了函数式版本的阶乘函数\nSupposing we write down the functional version,\n\n217\n00:11:58,590 --> 00:12:00,480\n我们以前的就是“函数式”风格\nfunctional meaning in the old style,\n\n218\n00:12:01,376 --> 00:12:04,608\n具有迭代计算过程的阶乘函数\nof factorial by an iterative process.\n\n219\n00:12:09,590 --> 00:12:13,280\nN的阶乘\nFactorial of n.\n\n220\n00:12:18,384 --> 00:12:24,352\n我们要(ITER M I)\nwe're going to iterate of m and i,\n\n221\n00:12:26,128 --> 00:12:33,136\n就是说如果I大于N\nwhich says if i is greater than n,\n\n222\n00:12:33,776 --> 00:12:35,510\n则结果是M\nthen the result is m,\n\n223\n00:12:36,304 --> 00:12:37,392\n否则\notherwise,\n\n224\n00:12:39,792 --> 00:12:46,820\n结果是(ITER (* I M))\nthe result of iterating the product of i and m.\n\n225\n00:12:46,820 --> 00:12:49,952\n所以M将是我累积的结果\nSo m is going to be the product that I'm accumulating.\n\n226\n00:12:51,584 --> 00:12:52,624\nM就是这个乘积[注：此处教授笔误]\nm is the product.\n\n227\n00:12:57,970 --> 00:13:00,176\n然后我要把COUNT加1\nAnd the count I'm going to increase by one.\n\n228\n00:13:04,620 --> 00:13:10,976\n（闭合括号中）\nPlus, ITER, ELSE, COND, define.\n\n229\n00:13:11,952 --> 00:13:13,040\n我在这里启动这个内部过程\nI'm going to start this up.\n\n230\n00:13:17,168 --> 00:13:19,792\n对于这种代码 我想大家早已驾轻就熟了\nAnd these days, you should have no trouble reading something like this.\n\n231\n00:13:20,864 --> 00:13:25,152\n这里是一个累积的乘积 和一个计数器\nWhat I have here is a product there being accumulated and a counter.\n\n232\n00:13:26,480 --> 00:13:28,464\n我让它们都从1开始\nI start them up both at one.\n\n233\n00:13:28,896 --> 00:13:30,920\n我将不断让计数器增加\nI'm going to buzz the counter up,\n\n234\n00:13:30,920 --> 00:13:33,120\n每一轮I变成I+1\ni goes to i plus one every time around.\n\n235\n00:13:34,560 --> 00:13:37,472\n这是我们在这个过程中设置时间的唯一方法\nBut that's only way our putting a time on the process,\n\n236\n00:13:38,480 --> 00:13:40,048\n这些都是一系列的事实\neach of this is just a set of truths,\n\n237\n00:13:40,496 --> 00:13:41,344\n真实的规则\ntrue rules.\n\n238\n00:13:42,816 --> 00:13:46,130\nM将获得一个新的值 就是I乘M\nAnd m is going to get a new values of i and m,\n\n239\n00:13:46,130 --> 00:13:47,824\n每一轮I乘以M\ni times m each time around,\n\n240\n00:13:48,680 --> 00:13:50,480\n最终I将大于N\nand eventually i is going to be bigger than n,\n\n241\n00:13:50,496 --> 00:13:52,060\n在这种情况下 结果就是M\nin which case, the answer's going to be m.\n\n242\n00:13:52,672 --> 00:13:54,800\n我给你们讲课的时候 用到了“时间”这个概念\nNow, I'm speaking to you, use time in this.\n\n243\n00:13:55,680 --> 00:13:57,456\n那是因为我知道计算机是怎么工作的\nThat's just because I know how the computer works.\n\n244\n00:13:58,256 --> 00:13:59,248\n但是我没必要这么做\nBut I didn't have to.\n\n245\n00:13:59,264 --> 00:14:02,300\n这完全可以有一个纯数学的解释\nThis could be a purely mathematical description at this point,\n\n246\n00:14:02,300 --> 00:14:03,744\n因为在这里代换可以工作\nbecause substitution will work for this.\n\n247\n00:14:05,104 --> 00:14:08,140\n但是我们写一个类似的程序\nBut let's set right down a similar sort of program,\n\n248\n00:14:08,304 --> 00:14:09,952\n使用相同的算法\nusing the same algorithm,\n\n249\n00:14:10,736 --> 00:14:12,112\n但使用了赋值\nbut with assignments.\n\n250\n00:14:15,696 --> 00:14:17,168\n所以这个叫做函数式版本\nSo this is called the functional version.\n\n251\n00:14:23,728 --> 00:14:25,568\n我想写个命令式的版本的\nI want to write down an imperative version.\n\n252\n00:14:34,480 --> 00:14:35,392\nN的阶乘\nFactorial of n.\n\n253\n00:14:35,920 --> 00:14:37,744\n我要创建两个变量\nI'm going to create my two variables.\n\n254\n00:14:40,160 --> 00:14:45,536\n把I的值初始化为1\nLet i initialize itself to one,\n\n255\n00:14:46,320 --> 00:14:49,776\nM也初始化为1\nand m be initialized to one, similar.\n\n256\n00:14:51,152 --> 00:14:52,192\n我们创建一个循环\nWe'll create a loop\n\n257\n00:14:59,312 --> 00:15:07,270\n如果I比N大 循环结束\nwhich has COND greater than i, and if i is greater than n, we're done.\n\n258\n00:15:07,270 --> 00:15:08,870\n结果是M\nAnd the result is m,\n\n259\n00:15:08,870 --> 00:15:10,384\n也就是我累积的乘积\nthe product I'm accumulating.\n\n260\n00:15:10,870 --> 00:15:11,776\n否则\nOtherwise,\n\n261\n00:15:15,520 --> 00:15:17,408\n我接下来要做三件事\nI'm going to write down three things to do.\n\n262\n00:15:19,264 --> 00:15:27,056\n我要把M赋值为I*M\nI'm going to set! m to the product of i and m,\n\n263\n00:15:29,360 --> 00:15:35,200\n把I赋值为I+1\nset! i to the sum of i and one,\n\n264\n00:15:37,856 --> 00:15:39,312\n然后继续循环\nand go around the loop again.\n\n265\n00:15:40,410 --> 00:15:43,024\n你们中的FORTRAN程序员应该觉得眼熟\nLooks very familiar to you FORTRAN programmers.\n\n266\n00:15:44,736 --> 00:15:46,640\n（闭合括号中）\nELSE, COND, define,\n\n267\n00:15:46,640 --> 00:15:47,888\n就是这种语法有点陌生\nfunny syntax though.\n\n268\n00:15:51,136 --> 00:15:52,272\n启动循环\nStart the loop up,\n\n269\n00:15:56,100 --> 00:15:57,568\n程序就写完了\nand that's the program.\n\n270\n00:15:59,152 --> 00:16:00,528\n那么 这个程序\nNow, this program,\n\n271\n00:16:01,312 --> 00:16:02,496\n我们应该怎么思考它呢？\nhow do we think about it?\n\n272\n00:16:02,710 --> 00:16:04,256\n先来看看这里是什么\nWell, let's just say what we're seeing here.\n\n273\n00:16:04,848 --> 00:16:07,470\n这里有两个局部变量 I和M\nThere are two local variables, i and m,\n\n274\n00:16:07,470 --> 00:16:09,024\n它们都被初始化为1\nthat have been initialized to one.\n\n275\n00:16:10,720 --> 00:16:13,890\n在每一次循环里 我检测I是否大于N\nEvery time around the loop, I test to see if i is greater than n,\n\n276\n00:16:13,890 --> 00:16:15,088\n就是我们传入的参数\nwhich is the input argument,\n\n277\n00:16:15,300 --> 00:16:18,144\n如果成立的话 结果就是M中所累积的乘积\nand if so, the result is the product being accumulated in m.\n\n278\n00:16:19,168 --> 00:16:21,210\n然而 如果循环没有结束\nHowever, if it's not the end of the loop,\n\n279\n00:16:21,210 --> 00:16:22,896\n如果我们的工作没有结束\nif I'm not done,\n\n280\n00:16:23,640 --> 00:16:25,552\n则我们要把乘积\nthen what I'm going to do is change the product\n\n281\n00:16:25,840 --> 00:16:28,384\n变为i与当前乘积的结果\nto be the result of multiplying i times the current product.\n\n282\n00:16:29,040 --> 00:16:30,688\n就是我们在这里做过的事情\nWhich is sort of what we were doing here.\n\n283\n00:16:31,424 --> 00:16:32,688\n除了这里我没有改动\nExcept here I wasn't changing.\n\n284\n00:16:33,632 --> 00:16:35,776\n我创建了一个复本\nI was making another copy,\n\n285\n00:16:36,816 --> 00:16:42,048\n因为代换模型就是你复制过程的体\nbecause the substitution model says, you copy the body of the procedure\n\n286\n00:16:43,088 --> 00:16:45,888\n并用实际参数代换形式参数\nwith the arguments substituted for the formal parameters.\n\n287\n00:16:46,720 --> 00:16:48,420\n这里 我考虑的不是副本\nHere I'm not worried about copying,\n\n288\n00:16:48,420 --> 00:16:50,528\n在这里 我已经改变了M的值\nhere I've changed the value of m.\n\n289\n00:16:51,808 --> 00:16:55,120\n我也把I的值变成了I+1\nI also then change the value of i to i plus one,\n\n290\n00:16:55,616 --> 00:16:56,960\n然后继续循环\nand go buzzing around.\n\n291\n00:16:58,224 --> 00:17:00,080\n看起来是一样的程序\nSeems like essentially the same program,\n\n292\n00:17:00,960 --> 00:17:02,840\n在今天引入赋值之后\nbut there are some ways of making errors here\n\n293\n00:17:02,840 --> 00:17:05,504\n我们在这里有很多种方式犯错\nthat didn't exist until today.\n\n294\n00:17:06,144 --> 00:17:07,024\n例如\nFor example,\n\n295\n00:17:07,456 --> 00:17:09,408\n如果我在赋值的时候\nif I were to do the horrible thing\n\n296\n00:17:10,048 --> 00:17:12,144\n没有小心地写程序\nof not being careful in writing my program\n\n297\n00:17:12,640 --> 00:17:16,080\n把两个赋值的顺序调换了\nand interchange those two assignments,\n\n298\n00:17:17,104 --> 00:17:18,912\n程序计算的就不是相同的函数了\nthe program wouldn't compute the same function.\n\n299\n00:17:20,336 --> 00:17:22,870\n我得到了一个时间错误 因为这儿有个依赖关系\nI get a timing error because there's a dependency\n\n300\n00:17:22,870 --> 00:17:27,220\n因为M依赖于I上一次的值\nthat m depends upon having the last value of i.\n\n301\n00:17:27,344 --> 00:17:28,928\n如果我先改变I的值\nIf I try change i first,\n\n302\n00:17:31,312 --> 00:17:33,776\n就会在乘以M的时候 得到错误的I值\nthen I've got the wrong value of i when I multiply by m.\n\n303\n00:17:35,968 --> 00:17:38,380\n没有赋值的话不会存在这样的BUG\nIt's a bug that wasn't available until this moment,\n\n304\n00:17:38,380 --> 00:17:40,592\n这是由于我们引入了某些包含时间的东西造成的\nuntil we introduced something that had time in it.\n\n305\n00:17:43,440 --> 00:17:44,304\n如我所说的\nSo, as I said,\n\n306\n00:17:45,536 --> 00:17:47,390\n首先 我们需要一个新的计算模型\nfirst we need a new model of computation,\n\n307\n00:17:47,390 --> 00:17:50,864\n然后 需要有一个非常好的理由来支持我们做如此丑陋的事\nand second, we have to be damn good reason for doing this kind of ugly thing.\n\n308\n00:17:52,720 --> 00:17:53,744\n有什么问题吗？\nAre there any questions?\n\n309\n00:17:58,832 --> 00:18:00,224\nDavid 大点儿声说\nSpeak loudly, David\n\n310\n00:18:00,400 --> 00:18:03,472\n学生：现在 我们引入了SET!\nAUDIENCE: I'm confused about, we've introduced set now,\n\n311\n00:18:03,904 --> 00:18:06,368\n但是之前我们已经有LET和DEFINE了\nbut we had let before and define before.\n\n312\n00:18:06,896 --> 00:18:09,700\n我不太清楚它们的区别\nI'm confused about the difference between the three.\n\n313\n00:18:09,700 --> 00:18:13,250\nDEFINE不能像SET!一样用吗？\nWouldn't define work in the same situation as set!\n\n314\n00:18:13,984 --> 00:18:14,830\n请详细讲讲\nif you introduced it a bit?\n\n315\n00:18:14,830 --> 00:18:19,310\n教授：不 DEFINE用于创建并初始化\nPROFESSOR: No, define is intended for setting something once the first time,\n\n316\n00:18:19,310 --> 00:18:21,360\n为了创建它\nfor making it, OK?\n\n317\n00:18:22,080 --> 00:18:24,704\n你永远也不会见到我在黑板上\nYou've never seen me write on a blackboard\n\n318\n00:18:25,600 --> 00:18:26,944\n在同一行写两个DEFINE\ntwo defines in a row\n\n319\n00:18:27,088 --> 00:18:32,080\n只是为了让某个变量的旧值变成一个新的值\nwhose intention was to change the old value of some variable to a new one.\n\n320\n00:18:32,080 --> 00:18:34,510\n学生：这是一个约定俗成的规矩 还是--\nAUDIENCE: Is that by convention or--\n\n321\n00:18:34,510 --> 00:18:36,350\n教授：不 这是有意为之的\nPROFESSOR: No, it's intention.\n\n322\n00:18:36,350 --> 00:18:38,928\n答案是\nOkay? The answer is,\n\n323\n00:18:39,696 --> 00:18:40,840\n举个例子\nthat, for example,\n\n324\n00:18:40,840 --> 00:18:42,272\n在一个过程内部\ninternal to a procedure,\n\n325\n00:18:43,200 --> 00:18:45,920\n两个DEFINE写在一行里是非法的\ntwo defines in a row are illegal,\n\n326\n00:18:46,688 --> 00:18:48,576\n对于同一个变量DEFINE两次是非法的\ntwo defines in a row of the same variable.\n\n327\n00:18:50,240 --> 00:18:51,740\nX不能被DEFINE两次\nx can't be defined twice.\n\n328\n00:18:51,740 --> 00:18:55,200\n而系统会不会捕获这个错误 就是另一个问题了\nWhether or not a system catches that error is a different question,\n\n329\n00:18:55,936 --> 00:18:57,888\n但是我定下规矩\nbut I legislate to you\n\n330\n00:18:58,120 --> 00:19:00,640\n任何东西都只能DEFINE一次\nthat define happens once on anything.\n\n331\n00:19:00,736 --> 00:19:02,640\n确实 在交互式调试中\nNow, indeed, in interactive debugging,\n\n332\n00:19:03,376 --> 00:19:07,488\n我们打算让你与计算机交互时可以重新DEFINE一些东西\nwe intend that you interacting with your computer will redefine things,\n\n333\n00:19:08,192 --> 00:19:11,216\n所以交互式调试时产生的是一个特殊的异常\nand so there's a special exception made for interactive debugging.\n\n334\n00:19:11,824 --> 00:19:16,480\n但是DEFINE的意思是建立某些东西\nBut define is intended to mean to set up something\n\n335\n00:19:18,144 --> 00:19:20,960\n在那个时间点后 它的值是永远不变的\nwhich will be forever that value after that point.\n\n336\n00:19:22,050 --> 00:19:24,544\n好像所有的DEFINE都是在最开始完成的\nIt's as if all the defines were done at the beginning.\n\n337\n00:19:26,090 --> 00:19:30,928\n事实上 在Scheme过程中 DEFINE的唯一合法使用地方\nIn fact, the only legal place to put a define in Scheme internal to a procedure\n\n338\n00:19:31,024 --> 00:19:33,360\n就是在LAMBDA表达式的开始\nis just at the beginning of a lambda expression,\n\n339\n00:19:34,470 --> 00:19:37,664\n也就是过程体的开始\nwhich is the beginning of the body of a procedure.\n\n340\n00:19:40,400 --> 00:19:45,808\nLET当然与那个不一样\nNow, let of course does nothing like either of that.\n\n341\n00:19:48,096 --> 00:19:49,552\n如果你想知道LET发生了什么\nI mean, if you look at what's happening with a let,\n\n342\n00:19:50,176 --> 00:19:52,130\nLET只会绑定一次\nthis happens again exactly once.\n\n343\n00:19:52,130 --> 00:19:55,824\n它建立了一个I和M的值分别为1的上下文\nIt sets up a context where i and m are values one and one.\n\n344\n00:19:56,832 --> 00:20:00,576\n这个上下文存在于整个作用域中\nThat context exists throughout this scope,\n\n345\n00:20:01,310 --> 00:20:02,800\n也就是这个程序范围\nthis region of the program.\n\n346\n00:20:04,992 --> 00:20:10,128\n然而 你不会认为LET再次设置了I的值\nHowever, you don't think of that let as setting i again.\n\n347\n00:20:11,040 --> 00:20:12,160\n它没有改变I的值\nIt doesn't change it.\n\n348\n00:20:12,160 --> 00:20:14,016\n因为LET的作用 I将永远不会变化\ni never changes because of the let.\n\n349\n00:20:15,280 --> 00:20:16,816\n因为LET的作用 I才被创建\ni gets created because of let.\n\n350\n00:20:18,512 --> 00:20:19,296\n实际上\nIn fact,\n\n351\n00:20:19,730 --> 00:20:21,424\nLET是一个非常简单的想法\nthe let is a very simple idea.\n\n352\n00:20:22,240 --> 00:20:23,590\nLET不会做别的事情\nLet does nothing more,\n\n353\n00:20:23,590 --> 00:20:31,620\nLET的语义是……\nLet a variable one to have value one\n\n354\n00:20:31,620 --> 00:20:33,504\n我把它写得更准确点\nI'll write this down a little bit more neatly;\n\n355\n00:20:37,160 --> 00:20:43,730\n表达式 (var1 e1)\nLet's write, var one have value, the value of expression e1,\n\n356\n00:20:43,730 --> 00:20:47,360\n还有(var2 e2)\nand variable two, have this value of the expression e2,\n\n357\n00:20:48,144 --> 00:20:49,744\n在表达式e3中\nin an expression e3,\n\n358\n00:20:51,600 --> 00:21:05,808\n与一个以var1和var2为形式参数的过程一样\nis the same thing as a procedure of var one and var two, the formal parameters,\n\n359\n00:21:06,944 --> 00:21:08,960\ne3成为过程的体\nand e3 being the body,\n\n360\n00:21:10,912 --> 00:21:14,000\n在这里 var1与e1的值绑定\nwhere var one is bound to the value of e1,\n\n361\n00:21:14,270 --> 00:21:16,912\nvar2与e2的值绑定\nand var two gets the value of e2.\n\n362\n00:21:19,536 --> 00:21:23,264\n所以实际上 这是一个从代换的角度来看很容易理解的东西\nSo this is, in fact, a perfectly understandable thing from a substitution point of view.\n\n363\n00:21:24,896 --> 00:21:27,952\n其实就是同一个表达式的两种不同的写法\nThis is really the same expression written in two different ways.\n\n364\n00:21:31,690 --> 00:21:33,504\n事实上 系统真正的工作方式\nIn fact, the way the actual system works\n\n365\n00:21:33,632 --> 00:21:35,820\n就是在运行之前把代码翻译成这种形式\nis this gets translated into this before anything happens.\n\n366\n00:21:37,648 --> 00:21:41,770\n学生：我还是不清楚是什么造成了LET和DEFINE之间的区别\nAUDIENCE: OK, I'm still unclear as then what makes the difference between a let and a define. They could--\n\n367\n00:21:41,770 --> 00:21:44,304\n教授：DEFINE就是个语法糖\nPROFESSOR: A define is a syntactic sugar,\n\n368\n00:21:44,624 --> 00:21:49,104\n本质上来说 是通过LET创建一系列变量 然后给它们一次性赋值\nwhereby, essentially a bunch of variables get created by lets and then set up once.\n\n369\n00:21:57,104 --> 00:21:59,744\n好吧 我们休息一会\nOK, time for the first break, I think. Thank you.\n\n370\n00:22:02,520 --> 00:22:12,848\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n371\n00:22:12,840 --> 00:22:17,840\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n372\n00:22:48,810 --> 00:22:52,672\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n373\n00:22:52,670 --> 00:22:56,528\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n374\n00:22:56,520 --> 00:23:00,592\n赋值、状态和副作用\nAssignment, State, and Side-effects\n\n375\n00:23:04,288 --> 00:23:06,112\n看\nWell let's see.\n\n376\n00:23:06,448 --> 00:23:09,088\n现在 我不得不重建计算模型\nI now have to rebuild the model of computation,\n\n377\n00:23:09,776 --> 00:23:14,160\n使得你能够明白那些机制是如何运作的\nso you understand how some such mechanical mechanism could work\n\n378\n00:23:14,912 --> 00:23:16,464\n来完成我们刚才说的那些工作\nthat can do what we've just talked about.\n\n379\n00:23:17,536 --> 00:23:21,392\n我刚刚摧毁了你们的代换模型\nI just recently destroyed your substitution model.\n\n380\n00:23:22,624 --> 00:23:26,032\n不幸的是 这个模型比代换模型要复杂得多\nUnfortunately, this model is significantly more complicated than the substitution model.\n\n381\n00:23:26,624 --> 00:23:27,936\n这个模型叫环境模型\nIt's called the environment model.\n\n382\n00:23:29,024 --> 00:23:31,200\n我即将介绍一些术语\nAnd I'm going to have to introduce some terminology,\n\n383\n00:23:32,032 --> 00:23:34,510\n无论如何 你知道这些术语都是很好的\nwhich is very good terminology for you to know anyway.\n\n384\n00:23:34,510 --> 00:23:35,744\n它是关于名字的\nIt's about names.\n\n385\n00:23:36,510 --> 00:23:39,632\n我们要给事物的各种名字\nAnd we're going to give names to the kinds of names things have\n\n386\n00:23:40,000 --> 00:23:41,310\n和名字的使用途径以名字\nand the way those names are used.\n\n387\n00:23:42,480 --> 00:23:47,940\n如果硬要说的话 这是一个元描述\nSo this is a meta-description, if you will.\n\n388\n00:23:48,560 --> 00:23:50,850\n总之 这里面有一堆糟糕的术语\nAnyway, there is a pile of an unfortunate terminology here,\n\n389\n00:23:50,850 --> 00:23:53,760\n但我们需要利用它们来理解所谓的“环境模型”\nbut we're going to need this to understand what's called the environment model.\n\n390\n00:23:54,704 --> 00:23:57,536\n我们可能要做一点无聊的事情了\nWe're about to do a little bit of boring, dog-work here.\n\n391\n00:23:58,040 --> 00:24:01,584\n我们来看第一张幻灯片\nLet's look at the first transparency.\n\n392\n00:24:02,256 --> 00:24:06,976\n我们看到了术语“约束”的解释\nAnd we see a description of a word called bound.\n\n393\n00:24:08,800 --> 00:24:11,000\n我们会说一个变量V\nAnd we're going to say that a variable, v,\n\n394\n00:24:11,000 --> 00:24:12,912\n被约束在表达式E中\nis bound in an expression, e,\n\n395\n00:24:13,410 --> 00:24:21,520\n如果用一个没有出现在E中的变量W 对变量V统一换名\nif the meaning of e is unchanged by the uniform replacement of a variable w,\n\n396\n00:24:21,560 --> 00:24:24,288\n表达式语义没有发生改变\nnot occurrent if for every occurrence of v in e.\n\n397\n00:24:25,696 --> 00:24:27,008\n这个解释很长\nNow that's a long sentence,\n\n398\n00:24:27,370 --> 00:24:29,968\n在我们在被搞糊涂之前\nso, I think, I'm going to have to say a little bit about that\n\n399\n00:24:29,984 --> 00:24:32,620\n我应该再多解释下\nbefore we even fool around at all here.\n\n400\n00:24:33,424 --> 00:24:35,280\n我们这里讨论的约束变量\nBound variables we're talking about here.\n\n401\n00:24:44,160 --> 00:24:45,568\n你们已经看到它们很多次了\nAnd you've seen lots of them.\n\n402\n00:24:46,070 --> 00:24:48,176\n只是你们可能还没意识到\nYou may not know that you've seen lots of them.\n\n403\n00:24:48,240 --> 00:24:52,240\n在逻辑学中 你们看到一个逻辑变量\nWell, I suppose in your logic, you saw a logical variables like,\n\n404\n00:24:53,270 --> 00:25:00,112\n就像微积分课上的 对于任意任何X 存在一个Y 使得P为真\nfor every x there exists a y such that p is true of x and y from your calculus class.\n\n405\n00:25:02,880 --> 00:25:05,824\n这个变量X 这个变量Y 它们是约束变量\nThis variable, x, and this variable, y, are bound,\n\n406\n00:25:07,088 --> 00:25:07,920\n因为\nbecause,\n\n407\n00:25:08,336 --> 00:25:09,980\n这个表达式的含义\nthe meaning of this expression\n\n408\n00:25:09,980 --> 00:25:15,616\n不取决于我用来描述X和Y的具体字母\ndoes not depend upon the particular letters I used to describe x and y.\n\n409\n00:25:16,496 --> 00:25:19,184\n如果我用W替换X\nIf I were to change the w for x,\n\n410\n00:25:19,840 --> 00:25:25,680\n则可以说对于任意W 存在一个Y使得P为真\nthen said for every w there exists a y such that p is true of w and y,\n\n411\n00:25:25,984 --> 00:25:27,088\n它们其实是同一句话\nit would be the same sentence.\n\n412\n00:25:29,440 --> 00:25:30,340\n就是这个意思\nThat's what it means.\n\n413\n00:25:30,340 --> 00:25:34,896\n又或者说 你们看到这样一个积分\nOr another case of this that you've seen is integral say,\n\n414\n00:25:35,408 --> 00:25:42,656\n对dx/(1+x^2)从0到1积分\nfrom 0 to one of dx over one plus x square.\n\n415\n00:25:46,032 --> 00:25:47,920\n这就是你们经常见到的那种东西\nWell that's something you see all the time.\n\n416\n00:25:47,920 --> 00:25:50,928\n这个x是一个约束变量\nAnd this x is a bound variable.\n\n417\n00:25:52,064 --> 00:25:53,792\n如果我把它换成t\nIf I change that to a t,\n\n418\n00:25:54,150 --> 00:25:56,256\n这个表达式其实没有变化\nthe expression is still the same thing.\n\n419\n00:25:58,060 --> 00:26:02,768\n就是arctan(1)/4之类的\nThis is a 1/4 of the arctan of one or something here, something like that.\n\n420\n00:26:04,704 --> 00:26:06,016\n是的 就是arctan(1)\nYes, that's the arctan of one.\n\n421\n00:26:06,624 --> 00:26:08,768\n所以约束变量事实上很常见\nSo bound variables are actually fairly common,\n\n422\n00:26:09,080 --> 00:26:12,368\n如果你们接触过一些数学的话\nfor those of you who have played a bit with mathematics.\n\n423\n00:26:13,264 --> 00:26:17,472\n好 让我们来到编程的世界\nWell, let's go into the programming world.\n\n424\n00:26:19,024 --> 00:26:21,360\n现在量词不再是\nInstead of the quantifier being something like,\n\n425\n00:26:22,032 --> 00:26:24,060\n所有、存在和积分\nfor every, or there exists, or integral,\n\n426\n00:26:24,060 --> 00:26:26,432\n我们有一个符号作为量词 用于约束变量\na quantifier is a symbol that binds a variable.\n\n427\n00:26:27,472 --> 00:26:28,992\n我们要使用量词LAMBDA\nAnd we are going to use the quantifier lambda\n\n428\n00:26:29,792 --> 00:26:31,808\n作为约束变量的一个必要的东西\nas being the essential thing that binds variables.\n\n429\n00:26:33,808 --> 00:26:36,128\n我们有一个极好的例子\nAnd so we have some nice examples here\n\n430\n00:26:36,592 --> 00:26:44,140\n对于以Y为参数的过程 做了以下的事情\nlike that procedure of one argument y which does the following thing.\n\n431\n00:26:44,140 --> 00:26:46,960\n它调用一个含单个参数X的过程\nIt calls the procedure of one argument x,\n\n432\n00:26:47,872 --> 00:26:51,136\n该过程 将X乘以Y\nwhich multiplies x by y,\n\n433\n00:26:52,880 --> 00:26:54,528\n并应用于3\nand applies that to three.\n\n434\n00:26:58,768 --> 00:27:01,664\n这个过程中包含两个约束变量\nThat procedure has the property there of two bound variables in it,\n\n435\n00:27:02,016 --> 00:27:02,928\nX和Y\nx and y\n\n436\n00:27:04,832 --> 00:27:07,472\n这个LAMBDA量词 约束了这个Y\nThis quantifier, lambda here, binds this y,\n\n437\n00:27:07,910 --> 00:27:10,784\n这个LAMBDA量词 约束了这个X\nand this quantifier, lambda, binds that x.\n\n438\n00:27:12,112 --> 00:27:17,056\n因为 如果我用了一个没有出现在表达式中的任意符号 如W\nBecause, if I were to take an arbitrary symbol does not occur in this expression like w\n\n439\n00:27:17,984 --> 00:27:21,040\n用W替换表达式中的所有Y\nand replace all y's with w's in this expression,\n\n440\n00:27:21,360 --> 00:27:22,752\n这个表达式仍与原来的相同\nthe expression is still the same,\n\n441\n00:27:23,664 --> 00:27:24,800\n是相同的过程\nthe same procedure.\n\n442\n00:27:26,224 --> 00:27:27,410\n这是一个重要的想法\nAnd this is an important idea.\n\n443\n00:27:27,410 --> 00:27:29,648\n我们有这种东西的原因\nThe reason why we had such things like that\n\n444\n00:27:30,208 --> 00:27:31,410\n这是一种模块性\nis a kind of modularity.\n\n445\n00:27:31,410 --> 00:27:32,864\n如果有两个人写程序\nIf two people are writing programs,\n\n446\n00:27:34,032 --> 00:27:35,260\n并且他们在合作编程\nand they work together,\n\n447\n00:27:35,260 --> 00:27:40,560\n在他们自己构建的小项目里用什么命名都没有关系\nit shouldn't matter what names they use internal to their own little machines that they're building.\n\n448\n00:27:42,832 --> 00:27:44,672\n所以 实际上我想告诉你们\nAnd so, what I'm really telling you there,\n\n449\n00:27:45,440 --> 00:27:46,752\n例如\nis that, for example,\n\n450\n00:27:46,840 --> 00:27:51,264\n这个表达式等于 以Y为参数的过程\nthis is equivalent to that procedure of one argument y which\n\n451\n00:27:52,352 --> 00:27:59,232\n使用这个对于一个参数Z的过程 这个过程将Z乘以Y\nuses that procedure of one argument z which multiplies z by y.\n\n452\n00:28:01,648 --> 00:28:03,536\n因为没人关心我在这用什么\nBecause nobody cares what I used in here.\n\n453\n00:28:06,368 --> 00:28:07,248\n这是一个极好的例子\nIt's a nice example.\n\n454\n00:28:08,848 --> 00:28:09,856\n另一方面\nOn the other hand,\n\n455\n00:28:11,072 --> 00:28:14,336\n我有一些未被约束的变量\nI have some variables that are not bound.\n\n456\n00:28:15,232 --> 00:28:15,968\n举个例子\nAnd example,\n\n457\n00:28:20,272 --> 00:28:21,760\n这个对于一个以X为参数的过程\nthat procedure of one argument x\n\n458\n00:28:22,096 --> 00:28:25,040\n将X乘以Y\nwhich multiplies x by y\n\n459\n00:28:27,280 --> 00:28:28,160\n在这个例子中\nIn this case,\n\n460\n00:28:29,456 --> 00:28:30,752\ny没有被约束\ny is not bound.\n\n461\n00:28:32,464 --> 00:28:34,272\n假设Y的值是3\nSupposing y had the value three,\n\n462\n00:28:35,264 --> 00:28:36,800\nZ的值是4\nand z had the value four,\n\n463\n00:28:38,832 --> 00:28:44,272\n那么这个过程就是把它的参数乘以3\nthen this procedure would be the thing that multiplies its argument by three.\n\n464\n00:28:44,864 --> 00:28:47,392\n如果我把所有的y都用z来代替\nIf I were to replace every instance of y with z,\n\n465\n00:28:47,520 --> 00:28:51,968\n我将得到一个完全不同的过程 它会把参数乘以4\nI would have a different procedure which multiplies every argument that's given by four.\n\n466\n00:28:53,872 --> 00:28:56,400\n事实上 我们给这类变量取了个名字\nAnd, in fact, we have a name for such a variable.\n\n467\n00:28:57,760 --> 00:29:04,010\n我们把表达式E中的变量V叫做自由变量\nHere, we say that a variable, v, is free in the expression, e,\n\n468\n00:29:04,010 --> 00:29:09,424\n如果用没有出现在E中的变量W统一替换E中所有的V\nif the meaning of the expression, e, is changed by the uniform replacement of a variable, w, not occurring in e,\n\n469\n00:29:09,584 --> 00:29:11,152\n使得表达式E的含义发生了改变\nfor every occurrence of v and e.\n\n470\n00:29:13,264 --> 00:29:13,712\n所以\nSo,\n\n471\n00:29:14,496 --> 00:29:22,768\n所以这就是为什么这个变量Y 是一个自由变量\nSo that's why this variable over here, y, is a free variable.\n\n472\n00:29:29,160 --> 00:29:32,272\n所以 这个表达式里的自由变量\nAnd so free variables in this expression--\n\n473\n00:29:33,760 --> 00:29:35,184\n另一个例子是\nAnd other examples of that is that\n\n474\n00:29:36,176 --> 00:29:39,328\n对于一个以Y为参数的过程\nis that procedure of one argument y,\n\n475\n00:29:40,432 --> 00:29:42,000\n就像我们之前的那个一样\nwhich is just what we had before,\n\n476\n00:29:42,272 --> 00:29:44,608\n调用以X为参数的过程\nwhich uses that procedure of one argument x\n\n477\n00:29:45,088 --> 00:29:48,544\n将X与Y相乘--\nthat multiplies x by y--\n\n478\n00:29:51,408 --> 00:29:52,656\n并应用于3\nuse that on three.\n\n479\n00:29:57,248 --> 00:30:00,352\n这个过程中有一个自由变量\nThis procedure has a free variable in it\n\n480\n00:30:00,928 --> 00:30:01,984\n也就是这个星号\nwhich is asterisk.\n\n481\n00:30:05,008 --> 00:30:05,890\n因为\nSee, because,\n\n482\n00:30:05,890 --> 00:30:08,080\n如果它表示正常意义的乘法\nif that has a normal meaning of multiplication,\n\n483\n00:30:09,440 --> 00:30:12,784\n如果我统一地用加号来代替星号\nthen if I were to replace uniformly all asterisks with pluses,\n\n484\n00:30:14,256 --> 00:30:16,384\n这个表达式的含义就变了\nthen the meaning of this expression would change.\n\n485\n00:30:19,344 --> 00:30:20,768\n这就是自由变量的意思\nThat's what you mean by a free variable.\n\n486\n00:30:22,688 --> 00:30:24,816\n现在 你们已经学到了一些逻辑学术语\nSo, so far you've learned some logician words\n\n487\n00:30:25,648 --> 00:30:27,584\n用它们可以解释名字的用法\nwhich describe the way names are used.\n\n488\n00:30:28,944 --> 00:30:31,264\n我们需要更进一步深入\nNow, we have to do a little bit more playing around here,\n\n489\n00:30:32,960 --> 00:30:33,728\n再多了解一些\na little bit more.\n\n490\n00:30:35,136 --> 00:30:36,224\n我想给你们讲讲\nI want to tell you about\n\n491\n00:30:36,816 --> 00:30:39,760\n变量被定义的区域\nabout the regions are over which variables are defined.\n\n492\n00:30:42,176 --> 00:30:42,880\n你瞧\nYou see,\n\n493\n00:30:43,376 --> 00:30:45,696\n目前为止 我们已经相当不正式了\nwe've been very informal about this up till now,\n\n494\n00:30:46,336 --> 00:30:50,160\n当然 你们中的一些 或者大部分人可能已经理解得很透彻了\nand, of course, many of you have probably understood very clearly or most of you,\n\n495\n00:30:50,360 --> 00:30:52,848\n在这里被声明的X\nthat the x that's being declared here\n\n496\n00:30:53,648 --> 00:30:55,184\n只被定义在这里\nis defined only in here.\n\n497\n00:30:58,288 --> 00:31:00,912\n这个X 只被定义在这里\nThis x is the defined only in here,\n\n498\n00:31:01,616 --> 00:31:04,336\n这个Y 只被定义在这里\nand this y is defined only in here.\n\n499\n00:31:07,104 --> 00:31:09,168\n我们给这个概念取了个名字 叫“作用域”\nWe have a name for such an idea. It's called a scope.\n\n500\n00:31:11,616 --> 00:31:13,584\n我给你们再讲个术语\nAnd let me give you another piece of terminology.\n\n501\n00:31:14,704 --> 00:31:15,776\n这个就比较复杂\nIt's a long story.\n\n502\n00:31:15,968 --> 00:31:17,648\n如果X是E中的一个约束变量\nIf x is a bound variable in e,\n\n503\n00:31:18,160 --> 00:31:20,240\n那么它是约束于一个LAMBDA表达式中\nthen there is a lambda expression where it is bound.\n\n504\n00:31:20,896 --> 00:31:24,910\nLAMBDA表达式是约束变量的唯一方式\nSo the only way you can get a bound variable ultimately is by lambda expression.\n\n505\n00:31:24,910 --> 00:31:25,968\n你可能会担心\nThen you may worry,\n\n506\n00:31:26,220 --> 00:31:29,056\nDEFINE是它的一个例外吗？\ndoes define quite an exception to this?\n\n507\n00:31:29,648 --> 00:31:32,920\n事实证明 通过巧妙安排 我们可以避免使用DEFINE\nAnd it turns out, we could always arrange things so you don't need any defines.\n\n508\n00:31:32,920 --> 00:31:33,968\n一会我们就能看到了\nAnd we'll see that in a while.\n\n509\n00:31:34,240 --> 00:31:35,728\n它一个非常神奇的东西\nIt's a very magical thing.\n\n510\n00:31:36,540 --> 00:31:38,400\n所以我们完全不需要DEFINE\nSo define really can go away.\n\n511\n00:31:38,680 --> 00:31:41,552\n实际上 唯一能创建名字的东西是LAMBDA\nThe really, only thing that makes names is lambda .\n\n512\n00:31:42,640 --> 00:31:43,408\n这就是它的职责\nThat's its job.\n\n513\n00:31:44,304 --> 00:31:46,230\n多么的令人惊奇\nAnd what's so amazing about a lot of things\n\n514\n00:31:46,230 --> 00:31:47,872\n很多东西你只凭借LAMBDA就可以计算\nis you can compute with only lambda.\n\n515\n00:31:48,736 --> 00:31:49,584\n但是 在任何情况下\nBut, in any case,\n\n516\n00:31:51,744 --> 00:31:55,760\n一个LAMBDA表达式有一个地方来声明变量\na lambda expression has a place where it declares a variable.\n\n517\n00:31:55,760 --> 00:31:57,104\n我们把它称为形式参数表\nWe call it the formal parameter list\n\n518\n00:31:58,944 --> 00:32:00,560\n或者叫 约束变量表\nand we say or the bound variable list.\n\n519\n00:32:01,264 --> 00:32:04,512\n我们说LAMBDA表达式约束了--这是一个动词\nWe say that the lambda expression binds -- so it's a verb\n\n520\n00:32:05,020 --> 00:32:07,344\n--约束了在约束变量表里声明的变量\n--binds the variables declared in it's bound variable list.\n\n521\n00:32:08,592 --> 00:32:12,480\n另外 表达式中定义变量的那些部分\nIn addition, those parts of the expression where the variable is defined,\n\n522\n00:32:13,232 --> 00:32:15,232\n是被一些声明所声明的\nwhich was declared by some declaration\n\n523\n00:32:15,568 --> 00:32:19,264\n这些部分被叫做变量的作用域\nis called the scope of that variable.\n\n524\n00:32:20,448 --> 00:32:21,920\n所以 这些是作用域\nSo these are scopes.\n\n525\n00:32:22,256 --> 00:32:23,680\n这是Y的作用域\nThis is the scope of y.\n\n526\n00:32:27,160 --> 00:32:28,544\n这是X的作用域--\nAnd this is the scope of x--\n\n527\n00:32:33,104 --> 00:32:34,032\n以此类推\nthat sort of thing.\n\n528\n00:32:41,328 --> 00:32:42,080\n好\nOK,\n\n529\n00:32:43,936 --> 00:32:45,632\n现在我们有了足够多的术语\nwell, now we have enough terminology\n\n530\n00:32:46,608 --> 00:32:51,760\n可以开始理解如何建立一个新的计算模型了\nto begin to understand how to make a new model for computation\n\n531\n00:32:51,968 --> 00:32:53,776\n因为 这里很重要的一点是\nbecause the key thing going on here\n\n532\n00:32:54,944 --> 00:32:57,008\n我们摧毁了代换模型\nis that we destroyed the substitution model,\n\n533\n00:32:57,180 --> 00:32:58,384\n我们现在不得不需要一个模型\nand we now have to have a model\n\n534\n00:32:58,624 --> 00:33:02,320\n来体现表示名字被关联到某些地方\nthat represents the names as referring to places.\n\n535\n00:33:03,936 --> 00:33:05,344\n因为 如果我们要改变某个东西\nBecause if we are going to change something,\n\n536\n00:33:05,984 --> 00:33:07,472\n我们就需要一个存它的地方\nthen we have a place where it's stored.\n\n537\n00:33:09,568 --> 00:33:10,352\n请想一想\nYou see,\n\n538\n00:33:10,832 --> 00:33:13,312\n如果一个名字只是关联于一个值\nif a name only refers to a value,\n\n539\n00:33:14,040 --> 00:33:16,360\n如果我试图改变这个名字的含义\nand if I tried to change the name's meaning,\n\n540\n00:33:16,736 --> 00:33:20,320\n这不怎么明确\nwell, that's not clear.\n\n541\n00:33:20,320 --> 00:33:24,680\n因为没有名字可以关联的地方\nThere's nothing that is the place that that name referred to.\n\n542\n00:33:24,992 --> 00:33:25,808\n该怎么解释呢……\nHow am I really saying it?\n\n543\n00:33:25,920 --> 00:33:29,540\n也就是名字的所有实例之间没有共享任何东西\nThere're nothing shared among all of the instances of that name.\n\n544\n00:33:29,872 --> 00:33:31,680\n也就是说 对于一个名字\nAnd what we really mean, by a name,\n\n545\n00:33:31,680 --> 00:33:32,976\n是用来让我们找到某些东西的\nis that we find something out.\n\n546\n00:33:34,336 --> 00:33:36,368\n我们给某个东西一个名字 然后你得到了它\nWe've given something a name, and you have it,\n\n547\n00:33:36,736 --> 00:33:39,060\n你能得到它 是因为我给了你一个它的引用\nand you have it, because I'm given you a reference to it,\n\n548\n00:33:39,060 --> 00:33:40,448\n我把对它的引用给了你\nand I've given you a reference to it.\n\n549\n00:33:41,024 --> 00:33:42,304\n我们会看到很多相关的例子\nAnd we'll see a lot about that.\n\n550\n00:33:43,616 --> 00:33:45,216\n让我们继续学习“环境”\nSo let me tell you about environments.\n\n551\n00:33:46,192 --> 00:33:48,768\n我需要用一下头顶上的投影仪\nI need the overhead projection machine,\n\n552\n00:33:49,312 --> 00:33:49,984\n谢谢你\nthank you.\n\n553\n00:33:52,192 --> 00:33:53,024\n这里\nAnd so here\n\n554\n00:33:55,488 --> 00:34:00,400\n是一堆环境结构\nis a bunch of environment structures.\n\n555\n00:34:01,536 --> 00:34:05,760\n环境就是执行虚拟的代换的一种方法\nAn environment is a way of doing substitutions virtually.\n\n556\n00:34:06,384 --> 00:34:07,890\n它代表了一个地方\nIt represents a place\n\n557\n00:34:07,890 --> 00:34:11,392\n是存储你的未完成的代换的地方\nwhere something is stored which is the substitutions that you haven't done.\n\n558\n00:34:13,344 --> 00:34:16,500\n它是一个积累各种东西的地方\nIt's a place where everything accumulates,\n\n559\n00:34:16,500 --> 00:34:21,136\n在那里 变量的名字与值关联在一起\nwhere the names of the variables are associated with the values they have\n\n560\n00:34:21,792 --> 00:34:22,560\n使得\nsuch that,\n\n561\n00:34:22,752 --> 00:34:25,900\n当你问某个名字是什么意思的时候\nwhen you say, what dose this name mean,\n\n562\n00:34:25,900 --> 00:34:27,408\n你要在一个环境中寻找答案\nyou look it up in an environment.\n\n563\n00:34:28,080 --> 00:34:29,488\n所以环境是一个函数\nSo an environment is a function,\n\n564\n00:34:30,800 --> 00:34:31,488\n或一张表\nor a table,\n\n565\n00:34:32,224 --> 00:34:33,240\n或类似的东西\nor something like that.\n\n566\n00:34:33,240 --> 00:34:34,896\n但它是一种结构化的表\nBut it's a structured sort of table.\n\n567\n00:34:35,760 --> 00:34:37,392\n它是由框架构成\nIt's made out of things called frames.\n\n568\n00:34:41,136 --> 00:34:44,464\n框架是环境的一部分\nFrames are pieces of environment,\n\n569\n00:34:44,896 --> 00:34:46,016\n它们被链接在一起\nand they are chained together,\n\n570\n00:34:47,072 --> 00:34:48,192\n以某种很好的方式\nin some nice ways,\n\n571\n00:34:49,008 --> 00:34:52,096\n用一种叫做父链接之类的东西\nby what's called parent links or something like that.\n\n572\n00:34:54,032 --> 00:34:55,024\n这里\nSo here,\n\n573\n00:34:55,648 --> 00:34:57,620\n有一个环境结构\nwe have an environment structure\n\n574\n00:34:57,620 --> 00:35:04,224\n它由三个环境组成 分别是A B和C\nconsisting of three environments, basically, A, B, and C.\n\n575\n00:35:05,104 --> 00:35:07,632\nD也是环境 但它和C是一样的\nd is also an environment, but it's the same one,\n\n576\n00:35:08,880 --> 00:35:10,176\n它们共享了同一个环境\nthey share.\n\n577\n00:35:11,456 --> 00:35:13,968\n那就是赋值的本质所在\nAnd that's the essence of assignment.\n\n578\n00:35:14,400 --> 00:35:16,100\n如果我改变了一个变量\nIf I change a variable,\n\n579\n00:35:16,100 --> 00:35:19,800\n比如改变这个变量的值\na value of a valuable that lives here, like that one,\n\n580\n00:35:19,800 --> 00:35:23,500\n那么它将在所有地方都可见\nit should be visible from all places that you're looking at it from.\n\n581\n00:35:23,500 --> 00:35:24,840\n用x来举例\nTake this one, x.\n\n582\n00:35:24,840 --> 00:35:28,190\n如果我将X改为4\nIf I change the x to four,\n\n583\n00:35:28,190 --> 00:35:30,190\n在其他地方也是可见的\nit's visible from other places.\n\n584\n00:35:30,190 --> 00:35:32,190\n但是我们现在不去关心这个\nBut I'm not going to worry about that right now.\n\n585\n00:35:32,190 --> 00:35:33,840\n过一会儿会详细讨论这个问题\nWe're going to talk a lot about that in a little while.\n\n586\n00:35:34,560 --> 00:35:35,536\n这里有什么？\nWhat do we have here?\n\n587\n00:35:36,768 --> 00:35:38,848\n这些叫做框架 这是一个框架\nWell, these are called frames. Here is a frame,\n\n588\n00:35:39,408 --> 00:35:40,384\n这是一个框架\nhere's a frame\n\n589\n00:35:40,768 --> 00:35:41,840\n这也是一个框架\nand here's a frame.\n\n590\n00:35:43,184 --> 00:35:45,200\nA是一个环境\nA is an environment which consists of\n\n591\n00:35:45,200 --> 00:35:47,824\n它由框架II\nthe table label which is frame two,\n\n592\n00:35:48,368 --> 00:35:51,056\n和框架I组成\nfollowed by the table labeled frame one.\n\n593\n00:35:52,528 --> 00:35:54,608\n在这个环境中\nAnd, in this environment,\n\n594\n00:35:54,992 --> 00:35:59,680\n在环境C中 在框架II中\nin C, this environment, frame two,\n\n595\n00:36:00,480 --> 00:36:03,264\nX和Y是被约束的\nuh....x and y are bound.\n\n596\n00:36:04,064 --> 00:36:04,784\n它们具有值\nThey have values.\n\n597\n00:36:05,260 --> 00:36:07,180\n对不起 是在框架I中\nSorry, in frame one\n\n598\n00:36:07,180 --> 00:36:08,288\n而在框架II中\nIn frame two,\n\n599\n00:36:09,728 --> 00:36:10,832\nZ被约束\nz is bound,\n\n600\n00:36:10,992 --> 00:36:12,176\nX被约束\nand x is bound,\n\n601\n00:36:12,448 --> 00:36:13,696\n并且Y也是被约束的\nand y is bound,\n\n602\n00:36:15,248 --> 00:36:17,408\n但是我们看到的X的值\nbut the value of x that we see,\n\n603\n00:36:17,420 --> 00:36:19,040\n从这个角度来看\nlooking from this point of view,\n\n604\n00:36:20,016 --> 00:36:21,744\n是这个X 它的值是7\nis this x. It's x is seven,\n\n605\n00:36:22,368 --> 00:36:24,840\n而不是这个值为3的X\nrather than this one which is three.\n\n606\n00:36:24,840 --> 00:36:27,616\n我们称之为 这个X遮蔽了这个X\nWe say that this x shadows this x.\n\n607\n00:36:31,056 --> 00:36:32,496\n从环境III\nFrom environment three--\n\n608\n00:36:33,440 --> 00:36:34,450\n从框架III\nfrom frame three,\n\n609\n00:36:34,450 --> 00:36:35,730\n从环境B\nfrom environment b,\n\n610\n00:36:35,730 --> 00:36:37,184\n它引用了框架III\nwhich refers to frame three,\n\n611\n00:36:37,450 --> 00:36:42,128\n变量M和Y被约束 X也被约束\nwe have variables m and y bound and also x.\n\n612\n00:36:44,848 --> 00:36:46,976\n这个Y遮蔽了这个Y\nThis y shadow this one.\n\n613\n00:36:48,656 --> 00:36:51,000\n从这个角度来看\nSo the value, looking from this point of view,\n\n614\n00:36:51,104 --> 00:36:52,650\nY的值是2\nof y is two.\n\n615\n00:36:53,456 --> 00:36:55,280\n从这个角度来看\nThe value for looking from this point of view\n\n616\n00:36:55,280 --> 00:36:58,640\nM的值是1 X的值是3\nand m is one. And the value, looking from this point of view, of x is three.\n\n617\n00:37:02,224 --> 00:37:03,150\n所以 我们有了一个\nSo there we have\n\n618\n00:37:03,150 --> 00:37:05,520\n由框架构成的非常简单的环境结构\na very simple environment structure made out of frames.\n\n619\n00:37:06,384 --> 00:37:09,808\n它们与过程的应用相一致\nThese correspond to the applications of procedures.\n\n620\n00:37:10,944 --> 00:37:12,176\n我们马上就会看到\nAnd we'll see that in a second.\n\n621\n00:37:14,416 --> 00:37:17,600\n现在要给你们看看我们构建的一些其他的很好的小结构\nSo now I have to make you some other nice little structure that we build.\n\n622\n00:37:20,752 --> 00:37:21,712\n下一张幻灯片\nNext slide,\n\n623\n00:37:22,144 --> 00:37:24,368\n我们可以看到一个对象\nwe see an object,\n\n624\n00:37:24,840 --> 00:37:26,544\n我描绘的是一个过程的图像\nwhich I'm going to draw procedures.\n\n625\n00:37:27,936 --> 00:37:28,944\n这是一个过程\nThis is a procedure.\n\n626\n00:37:30,112 --> 00:37:31,904\n过程由两个部分组成\nA procedure is made out of two parts.\n\n627\n00:37:33,104 --> 00:37:34,800\n这有点像CONS\nIt's sort of like a cons.\n\n628\n00:37:37,216 --> 00:37:38,384\n不管怎样 它有两个部分\nHowever, it's the two parts.\n\n629\n00:37:40,848 --> 00:37:44,720\n第一个部分指向一些代码\nThe first part refers to some code,\n\n630\n00:37:45,696 --> 00:37:46,944\n这些代码将会被执行\nsomething that can be executed,\n\n631\n00:37:47,420 --> 00:37:50,000\n你可以把它视作一组指令\na set of instructions, if you will. You can think of it that way.\n\n632\n00:37:50,688 --> 00:37:52,832\n第二部分是环境\nAnd the second part is the environment.\n\n633\n00:37:53,888 --> 00:37:55,504\n这就是过程的全部了\nThe procedure is the whole thing.\n\n634\n00:37:57,168 --> 00:37:58,400\n我们要用它\nAnd we're going to have to use this\n\n635\n00:37:58,710 --> 00:38:05,168\n来捕获出现在过程中的自由变量的值\nto capture the values of the free variables that occur in the procedure.\n\n636\n00:38:06,176 --> 00:38:08,096\n如果变量出现在过程中\nIf a variable occurs in the procedure\n\n637\n00:38:08,112 --> 00:38:09,920\n它不是被约束的就是自由的\nit's either bound in that procedure or free.\n\n638\n00:38:11,104 --> 00:38:11,968\n如果它是被约束的\nIf it's bound,\n\n639\n00:38:12,576 --> 00:38:14,560\n则它的值将很容易被找到\nthen the value will somehow be easy to find.\n\n640\n00:38:16,112 --> 00:38:18,640\n它将存在于某个很容易找到的环境中\nIt will be in some easy environment to get at.\n\n641\n00:38:18,910 --> 00:38:19,872\n如果它是自由的\nIf it's free,\n\n642\n00:38:20,864 --> 00:38:23,020\n我们就必须在过程中放入一些东西\nwe're going to have to have something that goes with the procedure\n\n643\n00:38:23,020 --> 00:38:24,816\n用来指导我们查询自由变量的值\nthat says where we'll go look for its value.\n\n644\n00:38:27,056 --> 00:38:29,210\n相关理由目前还不清楚\nAnd the reasons why are not obvious yet,\n\n645\n00:38:29,210 --> 00:38:30,608\n但很快就要真相大白了\nbut will be soon.\n\n646\n00:38:32,320 --> 00:38:34,976\n这里有一个对象 它是个复合对象\nSo here's a procedure object. It's a composite object\n\n647\n00:38:35,344 --> 00:38:41,648\n由一些代码和一个环境结构组成\nconsisting of a piece of code and a environment structure.\n\n648\n00:38:42,720 --> 00:38:45,504\n现在我要告诉你们一些全新的规则\nNow I will tell you the new rules, the complete new rules,\n\n649\n00:38:46,416 --> 00:38:47,472\n关于执行的规则\nfor evaluation.\n\n650\n00:38:50,544 --> 00:38:52,208\n仅有的两条规则的第一条是--\nThe first rule is-- there's only two of them.\n\n651\n00:38:53,200 --> 00:38:55,392\n这些规则与代换模型规则相对应\nThese correspond to the substitution model rules.\n\n652\n00:38:57,264 --> 00:38:59,328\n第一条规则是用来解决\nAnd the first one has to do with\n\n653\n00:38:59,664 --> 00:39:02,784\n如何把一个过程 应用到参数上的问题\nhow do you apply a procedure to its arguments?\n\n654\n00:39:05,280 --> 00:39:08,544\n程序对象被应用于一组参数\nOkay, And a procedural object is applied to a set of arguments\n\n655\n00:39:08,960 --> 00:39:10,432\n是通过构建一个新的框架来完成\nby constructing a new frame.\n\n656\n00:39:11,312 --> 00:39:15,760\n那个框架将包含形式参数\nThat frame will contain the mapping of the former parameters to the actual parameters\n\n657\n00:39:15,830 --> 00:39:19,488\n到调用中使用的实际参数的映射\nof the arguments that were supplied in the call.\n\n658\n00:39:21,424 --> 00:39:22,208\n如你所知\nAs you know,\n\n659\n00:39:22,310 --> 00:39:26,940\n当我们调用一个过程 如(LAMBDA (X) (* X Y))\nwhen we make up a call to a procedure like lambda x times x y,\n\n660\n00:39:26,940 --> 00:39:29,136\n然后我们以3为参数调用它\nand we call that with the argument three,\n\n661\n00:39:30,192 --> 00:39:32,752\n那么我们需要某个从X到3的映射\nthen we're going to need some mapping of x to three.\n\n662\n00:39:34,190 --> 00:39:37,392\n你可以把它想做是代换的一种\nIt's the same thing as later substituting, if you will\n\n663\n00:39:38,272 --> 00:39:40,304\n在旧的模型中 用3代换X\nthe three for the x in the old model.\n\n664\n00:39:42,000 --> 00:39:44,800\n所以我要建立一个框架\nSo I'm going to build a frame which contains x equals three\n\n665\n00:39:45,152 --> 00:39:46,608\n在框架中包含X等于3的这个信息\nas the information in that frame.\n\n666\n00:39:49,120 --> 00:39:49,712\n现在\nNow,\n\n667\n00:39:50,336 --> 00:39:53,312\n过程的体即将被执行\nthe body of the procedure will then have to be evaluated which is this,\n\n668\n00:39:54,160 --> 00:39:56,448\n它将在一个环境中执行\nand will be evaluated in an environment\n\n669\n00:39:57,808 --> 00:40:08,032\n这个环境是由我们创建的新框架邻接组合而成\nwhich is constructed by adjoining the new frame that we just made\n\n670\n00:40:08,544 --> 00:40:11,696\n它是我们所应用的过程的一部分\nto the environment which was part of the procedure that we applied.\n\n671\n00:40:13,152 --> 00:40:15,776\n所以 举个例子\nSo I'm going to make a little example of that here.\n\n672\n00:40:19,200 --> 00:40:24,128\n假设我有一些环境\nSupposing I have some environment.\n\n673\n00:40:25,152 --> 00:40:27,232\n画个方框代表它\nHere's a frame which represents it.\n\n674\n00:40:27,968 --> 00:40:32,192\n以及一些过程--我画圆来代表它们 因为这比小三角形好画--\nAnd some procedure-- which I'm going to draw with circles here because it's easier than little triangles--\n\n675\n00:40:33,040 --> 00:40:36,368\n抱歉 是菱形\nUmmm.. sorry, those are rhombuses,\n\n676\n00:40:37,664 --> 00:40:40,784\n小块菱形的果冻之类的东西\nrhomboidal little pieces of fruit jelly or something.\n\n677\n00:40:42,688 --> 00:40:45,328\n这有一个使用这个环境的过程\nSo here's a procedure which takes this environment.\n\n678\n00:40:45,952 --> 00:40:48,160\n这个过程有一些代码\nAnd the procedure has a piece of code,\n\n679\n00:40:48,160 --> 00:40:49,680\n是一个LAMBDA表达式\nwhich is a lambda expression,\n\n680\n00:40:50,120 --> 00:40:51,696\n约束了X和Y\nwhich binds x and y\n\n681\n00:40:53,152 --> 00:40:56,432\n然后执行了表达式E\nand then executes an expression, e.\n\n682\n00:40:57,936 --> 00:40:58,992\n这个过程就是这样的\nAnd this is the procedure.\n\n683\n00:40:59,560 --> 00:41:00,576\n我们叫它P\nWe'll call it p.\n\n684\n00:41:01,440 --> 00:41:05,792\n我希望将这个过程应用于3和4\nI wish to apply that procedure to three and four.\n\n685\n00:41:06,384 --> 00:41:08,368\n所以我在这写(P 3 4)\nSo I want to do p of three and four.\n\n686\n00:41:09,760 --> 00:41:12,176\n我要做的事情则是 创建一个新的框架\nWhat I'm going to do, of course, is make a new frame.\n\n687\n00:41:13,152 --> 00:41:14,128\n创建一个框架\nI build a frame\n\n688\n00:41:15,248 --> 00:41:18,288\n框架中X等于3\nwhich contains x equals three,\n\n689\n00:41:18,848 --> 00:41:20,512\n而Y等于4\nand y equals four.\n\n690\n00:41:21,696 --> 00:41:23,488\n我要把这个框架\nI'm going to connect that frame\n\n691\n00:41:24,272 --> 00:41:25,376\n连接到这一个框架上\nto this frame over here.\n\n692\n00:41:27,632 --> 00:41:28,992\n对于这个环境\nAnd then this environment,\n\n693\n00:41:29,680 --> 00:41:30,976\n我把它叫做B\nwith I will call b,\n\n694\n00:41:31,552 --> 00:41:35,024\n我会在这个环境中求值E的体\nis the environment in which I will evaluate the body of e.\n\n695\n00:41:39,888 --> 00:41:40,336\n现在\nNow,\n\n696\n00:41:41,952 --> 00:41:45,040\nE可能包含了X和Y的引用以及一些别的东西\ne may contain references to x and y and other things.\n\n697\n00:41:46,848 --> 00:41:49,952\nX和Y的值在这里\nx and y will have values right here.\n\n698\n00:41:50,704 --> 00:41:52,528\n其他的变量的值在这里\nOther things will have their values here.\n\n699\n00:41:55,056 --> 00:41:56,256\n怎样才能获取这个框架呢？\nHow do we get this frame?\n\n700\n00:41:57,264 --> 00:41:59,264\n我们通过过程构建来完成\nThat we do by the construction of procedures\n\n701\n00:41:59,616 --> 00:42:00,608\n这就是另一条规则了\nwhich is the other rule.\n\n702\n00:42:02,032 --> 00:42:04,400\n请看下一张幻灯片\nAnd I think that's the next slide.\n\n703\n00:42:05,344 --> 00:42:06,128\n规则二\nRule two,\n\n704\n00:42:07,808 --> 00:42:09,900\n当一个LAMBDA表达式被求值时\nwhen a lambda expression is evaluated,\n\n705\n00:42:09,900 --> 00:42:11,760\n相对于某个特定的环境--\nrelative to a particular environment--\n\n706\n00:42:14,192 --> 00:42:14,400\n例如\nSee,\n\n707\n00:42:15,040 --> 00:42:18,120\n获取一个过程的方式就是求值一个LAMBDA表达式\nthe way I get a procedure is by evaluating the lambda expression.\n\n708\n00:42:18,192 --> 00:42:19,360\n这里有一个LAMBDA表达式\nHere's a lambda expression.\n\n709\n00:42:20,048 --> 00:42:21,120\n通过对它求值\nBy evaluating it,\n\n710\n00:42:21,904 --> 00:42:23,968\n我获得了一个可以应用于3的过程\nI get a procedure which I can apply to three.\n\n711\n00:42:25,088 --> 00:42:26,650\n现在这个LAMBDA表达式\nNow this lambda expression\n\n712\n00:42:26,650 --> 00:42:30,384\n在一个Y已被定义的环境中执行\nis evaluated in an environment where y is defined.\n\n713\n00:42:31,840 --> 00:42:35,840\n我希望这个过程的体中包括的Y是自由的\nAnd I want the body of this which contains a free version of y.\n\n714\n00:42:36,390 --> 00:42:38,368\n在这里面 Y是自由的\ny is free in here,\n\n715\n00:42:38,720 --> 00:42:40,384\n但是在整个的表达式中却是被约束的\nit's bound over the whole thing,\n\n716\n00:42:41,360 --> 00:42:42,752\n而在这里是自由的\nbut it's free over here.\n\n717\n00:42:43,328 --> 00:42:46,240\n我想让这两个Y指称同一个Y\nI want that y to be this one.\n\n718\n00:42:47,440 --> 00:42:55,136\n我在Y被创建的环境中求值这个过程的体\nI evaluate this body of this procedure in the environment where y was created.\n\n719\n00:42:55,328 --> 00:42:58,400\n就像这个一样 因为那是通过应用完成的\nThat's this kind of thing, because that was done by application.\n\n720\n00:42:59,008 --> 00:42:59,632\n现在\nNow,\n\n721\n00:43:00,240 --> 00:43:02,608\n如果我还想查找Y的值\nif I ever want to look up the value of y,\n\n722\n00:43:03,104 --> 00:43:04,096\n我就必须知道它在哪\nI have to know where it is.\n\n723\n00:43:04,544 --> 00:43:06,420\n因此 这个过程在被创建时\nTherefore, this procedural was created,\n\n724\n00:43:06,420 --> 00:43:10,060\n过程的创建 也就是对LAMBDA表达式求值的结果\nthe creation of the procedure which is the result of evaluating that lambda expression\n\n725\n00:43:10,060 --> 00:43:16,336\n最好是获取一个指针或记住Y被约束在哪个框架中\nhad better capture a pointer or remember the frame in which y was bound.\n\n726\n00:43:17,920 --> 00:43:19,760\n这就是这个规则的内容\nSo that's what this rule is telling us.\n\n727\n00:43:22,112 --> 00:43:23,136\n那么 举个例子\nSo, for example,\n\n728\n00:43:24,448 --> 00:43:29,328\n如果我恰好求值了一个LAMBDA表达式\nif I happen to be evaluating a lambda expression,\n\n729\n00:43:30,896 --> 00:43:33,328\n在E中的LAMBDA表达式\nlambda expression in e,\n\n730\n00:43:34,048 --> 00:43:40,464\n在E中求值(LAMBDA (X Y) G)\nlambda of say, x and y, let's call it g in e,\n\n731\n00:43:41,088 --> 00:43:42,368\n对其求值\nevaluating that.\n\n732\n00:43:42,976 --> 00:43:46,176\n这些事的意义就是我现在构建了一个过程对象\nall that means is I now construct a procedure object.\n\n733\n00:43:47,104 --> 00:43:48,288\nE是某个环境\ne is some environment.\n\n734\n00:43:48,848 --> 00:43:50,944\n有个指针指向E\ne is something which has a pointer to it.\n\n735\n00:43:51,792 --> 00:43:56,688\n我构建了一个过程对象指向了这个环境\nI construct a procedure object that points up to that environment,\n\n736\n00:43:58,560 --> 00:44:00,112\n它的代码\nwhere the code of that\n\n737\n00:44:00,544 --> 00:44:03,248\n是一个LAMBDA表达式 或者是某种中间代码\nis a lambda expression or whatever that translates into.\n\n738\n00:44:06,240 --> 00:44:07,568\n而这就是一个过程\nAnd this is the procedure.\n\n739\n00:44:12,384 --> 00:44:14,704\n它为我生成了这个和这个\nSo this produces for me-- this -- this\n\n740\n00:44:14,940 --> 00:44:16,370\n这个对象\nthis object here,\n\n741\n00:44:16,370 --> 00:44:18,128\n这个环境指针\nthis environment pointer,\n\n742\n00:44:18,370 --> 00:44:22,520\n获取了求值LAMBDA表达式时的环境\ncaptures the place where this lambda expression was evaluated,\n\n743\n00:44:22,624 --> 00:44:24,592\n定义所使用的环境\nwhere the definition was used,\n\n744\n00:44:25,584 --> 00:44:27,408\n创建一个过程时的定义所用的环境\nwhere the definition was used to make a procedure,\n\n745\n00:44:30,320 --> 00:44:31,472\n从而创建了过程\nto make the procedure.\n\n746\n00:44:32,896 --> 00:44:36,304\n所以 它将环境从定义过程的地方取出\nSo it picks up the environment from the place where that procedure was defined,\n\n747\n00:44:37,424 --> 00:44:38,928\n将它保存在过程自己内部\nstores it in the procedure itself,\n\n748\n00:44:39,600 --> 00:44:40,976\n之后当过程被调用时\nand then when the procedure is used,\n\n749\n00:44:41,328 --> 00:44:43,472\n它在被定义时的环境\nthe environment where it was defined is extended\n\n750\n00:44:43,984 --> 00:44:45,072\n将由新的框架扩充\nwith the new frame.\n\n751\n00:44:48,720 --> 00:44:52,336\n这给了我们一个放置有值的变量的地方\nSo this gives us a locus for putting where a variable has a value.\n\n752\n00:44:53,040 --> 00:44:53,960\n举个例子\nAnd, for example,\n\n753\n00:44:53,960 --> 00:44:56,816\n如果有很多东西指向那这个环境\nif there are lots of guys pointing in at that environment,\n\n754\n00:44:57,744 --> 00:45:00,336\n它们就会共享这个环境\nthen they share that place.\n\n755\n00:45:01,200 --> 00:45:02,528\n我们很快将会见到\nAnd we'll see more of that shortly.\n\n756\n00:45:04,016 --> 00:45:05,344\n现在你们有了一个新模型\nWell, now you have a new model\n\n757\n00:45:06,384 --> 00:45:09,920\n我们用它来理解程序的执行\nfor understanding the execution of programs.\n\n758\n00:45:11,360 --> 00:45:12,784\n我觉得现在我应该解答一些问题了\nI suppose I'll take questions now,\n\n759\n00:45:13,100 --> 00:45:14,960\n之后我们再继续\nand then we'll go on and use that for something.\n\n760\n00:45:18,192 --> 00:45:19,520\n学生：这么说是对的吗？\nAUDIENCE: Is it right to say then,\n\n761\n00:45:19,520 --> 00:45:23,960\n环境就是一些被连接在一起的框架\nthe environment is that linked chain of frames starting with--\n\n762\n00:45:23,960 --> 00:45:25,104\n教授：对\nPROFESSOR: That's right.\n\n763\n00:45:25,480 --> 00:45:26,640\n学生：通过它能够访问所有的框架？\nAUDIENCE:  working all the way back?\n\n764\n00:45:27,712 --> 00:45:31,456\n教授：是的 环境是一系列被连接在一起的框架\nPROFESSOR: Yes, the environment is a sequence of frames linked together.\n\n765\n00:45:32,432 --> 00:45:35,472\n我对它的理解是 它是指向第一个框架的指针\nAnd the way I like to think about it, it's the pointer to the first one,\n\n766\n00:45:36,880 --> 00:45:38,720\n因为一旦你获得了它 你就能拿到所有的框架\nbecause once you've got that you've got them all.\n\n767\n00:45:43,968 --> 00:45:44,656\n还有谁有问题吗？\nAnybody else?\n\n768\n00:45:45,200 --> 00:45:49,360\n学生：有可能在两个不同的环境中定义或求值一个过程\nAUDIENCE: Is it possible to evaluate a procedure or to define a procedure in two different environments\n\n769\n00:45:49,360 --> 00:45:53,200\n使得它有不同的行为 并且有指向两个环境的指针--\nsuch that it will behave differently, and have pointers to both--\n\n770\n00:45:53,200 --> 00:45:55,776\n教授：噢 是的 同一个过程不会有两个不同环境\nPROFESSOR: Oh, yes. The same procedure is not going to have two different environments.\n\n771\n00:45:56,900 --> 00:45:59,020\n同样的代码\nThe same code,\n\n772\n00:45:59,020 --> 00:46:00,820\n比如同样的LAMBDA表达式\nthe same lambda expression\n\n773\n00:46:00,820 --> 00:46:03,728\n再不同的环境下求值可能产生不同的过程\ncan be evaluated in two environments producing two different procedures.\n\n774\n00:46:06,032 --> 00:46:07,180\n每个过程--\nEach procedure--\n\n775\n00:46:07,180 --> 00:46:09,950\n学生：它们的定义有同样的名字 它们的运算--\nAUDIENCE: Their definition has the same name. Their operation--\n\n776\n00:46:09,950 --> 00:46:11,920\n教授：它们定义是写起来是一样的 使用同样的字母\nPROFESSOR: The definition is written the same, with the same characters.\n\n777\n00:46:12,560 --> 00:46:14,624\n我能求值那一组字母\nI can evaluate that set of characters,\n\n778\n00:46:14,930 --> 00:46:18,140\n或定义的表结构之类的东西\nwhatever, that list structure that defines,\n\n779\n00:46:18,224 --> 00:46:20,416\n那只是文本表示\nthat is the textual representation.\n\n780\n00:46:20,912 --> 00:46:24,864\n我可以在两个不同环境种对它求值 产生两个不同的过程\nI can evaluate that in two different environments producing two different procedures.\n\n781\n00:46:25,552 --> 00:46:26,848\n每一个过程\nEach of those procedures\n\n782\n00:46:27,568 --> 00:46:32,192\n有它们自己的一组局部变量\nhas its own local sets of variables,\n\n783\n00:46:32,340 --> 00:46:33,456\n我们很快就会看到\nand we'll see that right now.\n\n784\n00:46:36,704 --> 00:46:37,360\n还有问题吗？\nAnybody else?\n\n785\n00:46:42,608 --> 00:46:44,032\n好 谢谢大家 我们休息一会\nOK, thank you. Let's take a break.\n\n786\n00:46:47,980 --> 00:46:57,616\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n787\n00:46:57,610 --> 00:47:02,032\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n788\n00:47:05,984 --> 00:47:09,696\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Gerald Jay Sussman\n\n789\n00:47:09,690 --> 00:47:13,440\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n790\n00:47:13,470 --> 00:47:18,848\n赋值、状态和副作用\nAssignment, State, and Side-effects\n\n791\n00:47:22,670 --> 00:47:25,696\n现在 我已经对你们做了一件非常糟糕的事儿\nWell, now I've done this terrible thing to you.\n\n792\n00:47:26,560 --> 00:47:30,544\n我引入了一个非常复杂的东西\nI've introduced a very complicated thing,\n\n793\n00:47:32,768 --> 00:47:33,424\n赋值\nassignment,\n\n794\n00:47:34,512 --> 00:47:38,080\n它摧毁了我们程序中大部分的 有趣的数学特性\nwhich destroys most of the interesting mathematical properties of our programs.\n\n795\n00:47:41,072 --> 00:47:42,464\n我为什么要做这件事呢\nWhy should I have done this?\n\n796\n00:47:43,184 --> 00:47:45,024\n这样做可能有什么好处吗？\nWhat possible good could this do?\n\n797\n00:47:46,512 --> 00:47:48,864\n很明显 这不是一个什么好东西\nClearly not a nice thing,\n\n798\n00:47:49,600 --> 00:47:51,232\n因此我最好有一个好的理由\nso I better have a good excuse.\n\n799\n00:47:52,832 --> 00:47:54,800\n让我们来小小地玩一下\nWell, let's do a little bit of playing,\n\n800\n00:47:54,800 --> 00:47:58,352\n首先 我们写些非常有趣的带赋值的程序\nfirst of all, with some very interesting programs that have assignment.\n\n801\n00:47:58,816 --> 00:48:00,880\n来理解它们的特殊之处\nUnderstand something special about them\n\n802\n00:48:01,424 --> 00:48:02,832\n这些特殊之处使赋值变得有价值\nthat makes them somewhat valuable.\n\n803\n00:48:04,960 --> 00:48:06,704\n我们从一个非常简单的程序开始\nStart with a very simple program\n\n804\n00:48:07,696 --> 00:48:09,280\n我把这个程序叫做MAKE-COUNTER\nI'm going to call make-counter.\n\n805\n00:48:10,480 --> 00:48:18,192\n我要把它定义为\nI'm going to define make-counter\n\n806\n00:48:24,176 --> 00:48:28,128\n接受一个参数N的过程\nto be a procedure of one argument n\n\n807\n00:48:29,232 --> 00:48:32,944\n并且它的返回值是一个没有参数的过程--\nwhich returns as its value a procedure of no arguments--\n\n808\n00:48:34,368 --> 00:48:36,032\n一个生成过程的过程--\na procedure that produces a procedure--\n\n809\n00:48:36,848 --> 00:48:44,352\n这个过程把N的值设为N+1\nwhich sets n to the increment of n\n\n810\n00:48:47,888 --> 00:48:49,776\n并且返回N的值\nand returns that value of n.\n\n811\n00:48:55,376 --> 00:48:57,540\n现在 我们要研究它的行为\nNow we're going to investigate the behavior of this.\n\n812\n00:48:57,540 --> 00:48:59,024\n它很有趣\nIt's a sort of interesting thing.\n\n813\n00:48:59,824 --> 00:49:01,450\n为了研究它的行为\nIn order to investigate the behavior,\n\n814\n00:49:01,450 --> 00:49:03,088\n我需要建立一个环境模型\nI have to make an environment model,\n\n815\n00:49:04,112 --> 00:49:05,984\n因为我们不能通过其他的方式来理解它\nbecause we can't understand this any other way.\n\n816\n00:49:08,656 --> 00:49:09,632\n所以我们开始吧\nSo let's just do that.\n\n817\n00:49:10,000 --> 00:49:12,864\n我们从这里开始\nWe start out with some sort of--\n\n818\n00:49:13,240 --> 00:49:15,904\n假设机器天生就有一个全局环境\nlet's say there is a global environment that the machine is born with.\n\n819\n00:49:16,130 --> 00:49:17,120\n我们把它叫做Global\nGlobal we'll call it.\n\n820\n00:49:20,032 --> 00:49:24,256\n它内部有一堆初始化的东西\nAnd it's going to have in it a bunch of initial things.\n\n821\n00:49:24,440 --> 00:49:25,600\n我们都知道它里面有什么\nWe all know what it's got.\n\n822\n00:49:25,720 --> 00:49:30,880\n这里面有+和*\nIt's got things in it like say, plus, and times,\n\n823\n00:49:32,240 --> 00:49:37,264\n/ -和CAR\nand quotient, and difference, and CAR,\n\n824\n00:49:38,704 --> 00:49:39,744\n以此类推\nand etcetera,\n\n825\n00:49:41,450 --> 00:49:42,480\n有很多东西\nlots of things.\n\n826\n00:49:42,880 --> 00:49:43,984\n我不知道它们是什么\nI don't know what they are,\n\n827\n00:49:44,420 --> 00:49:45,552\n一些乱七八糟的符号\nsome various squiggles\n\n828\n00:49:46,080 --> 00:49:48,880\n机器一开始就有这些特性\nthat are the things the machine is born with.\n\n829\n00:49:51,216 --> 00:49:53,232\n通过在这做定义\nAnd by doing the definition here,\n\n830\n00:49:54,688 --> 00:49:55,760\n我要做的是--\nwhat I plan to do--\n\n831\n00:49:56,320 --> 00:49:57,310\n我在干什么呢？\nWell, what am I doing?\n\n832\n00:49:57,310 --> 00:49:59,584\n我要把它关联到全局环境上\nI'm doing this relative to the global environment.\n\n833\n00:49:59,720 --> 00:50:01,296\n这是我的环境指针\nSo here's my environment pointer.\n\n834\n00:50:03,728 --> 00:50:06,704\n为了达到那个目的 我要求值这个LAMBDA表达式\nIn order to do that I have to evaluate this lambda expression.\n\n835\n00:50:08,352 --> 00:50:10,016\n这意味着我创建了一个过程对象\nThat means I make a procedure object.\n\n836\n00:50:11,504 --> 00:50:13,264\n所以 我要在这创建一个过程对象\nSo I'm going to make a procedure object here.\n\n837\n00:50:17,360 --> 00:50:18,688\n这个过程对象\nAnd the procedure object has,\n\n838\n00:50:18,720 --> 00:50:20,496\n由于在它被定义的地方\nas the place it's defined,\n\n839\n00:50:21,168 --> 00:50:22,352\n有一个全局的环境\nthe global environment.\n\n840\n00:50:24,064 --> 00:50:25,792\n这个过程对象包括了\nThe procedure object contains\n\n841\n00:50:28,160 --> 00:50:31,472\n以N为参数的过程的代码\nsome code that represents a procedure of one argument n\n\n842\n00:50:31,960 --> 00:50:35,344\n它返回一个不接受参数的过程\nwhich returns a procedure of no arguments which does something.\n\n843\n00:50:38,240 --> 00:50:43,280\nDEFINE是一种改变环境的方法\nAnd the define is a way of changing this environment,\n\n844\n00:50:44,320 --> 00:50:46,736\n所以我把MAKE-COUNTER加入全局环境中\nso that I now add to it a make-counter,\n\n845\n00:50:52,288 --> 00:50:55,056\n这是对于特殊的东西定义的一个特殊的规则\na special rule for the special thing defined.\n\n846\n00:50:55,824 --> 00:50:56,944\n但它其实是\nBut what that is,\n\n847\n00:50:58,944 --> 00:51:01,968\n它给了我们一个指针 指向那个过程\nis it gives me that pointer to that procedure.\n\n848\n00:51:03,824 --> 00:51:06,320\n所以现在全局环境中也有了MAKE-COUNTER\nSo now the global environment contains make-counter as well.\n\n849\n00:51:09,280 --> 00:51:11,216\n现在 我们要进行一些操作\nNow, we're going to do some operations.\n\n850\n00:51:11,872 --> 00:51:13,504\n我要用它来创建一些计数器\nI'm going to use this to make some counters.\n\n851\n00:51:14,992 --> 00:51:16,208\n我们来看看计数器是什么\nWe'll see what a counter is.\n\n852\n00:51:17,120 --> 00:51:18,512\n所以我们定义\nSo let's define\n\n853\n00:51:23,328 --> 00:51:26,656\nC1为一个从0开始的计数器\nc1 to be a counter beginning at 0.\n\n854\n00:51:35,728 --> 00:51:38,384\n根据模型 我们知道如何做这个了\nWell, we know how to do this now, according to the model.\n\n855\n00:51:39,632 --> 00:51:44,336\n我需要在全局环境中求值这个表达式\nI have to evaluate the expression make-counter in the global environment,\n\n856\n00:51:45,408 --> 00:51:46,272\n(MAKE-COUNTER 0)\nmake-counter of 0.\n\n857\n00:51:47,808 --> 00:51:51,104\n我查找MAKE-COUNTER 发现它是一个过程\nWell, I look up make-counter and see that it's a procedure.\n\n858\n00:51:53,616 --> 00:51:55,296\n我将要应用这个过程\nI'm going to have to apply that procedure.\n\n859\n00:51:56,224 --> 00:51:57,744\n应用这个过程的方式\nThe way I apply the procedure\n\n860\n00:51:58,432 --> 00:51:59,968\n就是构建一个框架\nis by constructing a frame.\n\n861\n00:52:01,808 --> 00:52:03,792\n所以我构建了一个框架\nOkay? So I construct a frame\n\n862\n00:52:06,592 --> 00:52:10,448\n它内部有一个N的值\nwhich has a value for n in it\n\n863\n00:52:11,776 --> 00:52:12,640\n这个值是0\nwhich is 0\n\n864\n00:52:14,000 --> 00:52:15,344\n它的父环境\nand the parent environment\n\n865\n00:52:15,872 --> 00:52:19,328\n就是定义MAKE-COUNTER时的环境\nis the one which is the environment of definition of make-counter.\n\n866\n00:52:23,936 --> 00:52:28,368\n所以我已经通过将MAKE-COUNTER应用于0上 而创建了一个环境\nSo I've made an environment by applying make-counter to 0.\n\n867\n00:52:31,450 --> 00:52:34,400\n现在 我需要求值MAKE-COUNTER的体\nNow, I have to evaluate the body of make-counter,\n\n868\n00:52:34,410 --> 00:52:37,728\n就是那个环境中的LAMBDA表达式\nwhich is this lambda expression, in that environment.\n\n869\n00:52:40,640 --> 00:52:42,304\n求值这个体\nWell evaluating this body,\n\n870\n00:52:42,768 --> 00:52:44,592\n它是一个LAMBDA表达式\nthis body is a lambda expression.\n\n871\n00:52:46,288 --> 00:52:48,864\n对LAMBDA表达式求值 意味着创建一个过程对象\nEvaluate a lambda expression means make a procedure object.\n\n872\n00:52:49,568 --> 00:52:51,008\n所以我将创建一个过程对象\nSo I'm going to make a procedure object.\n\n873\n00:52:56,768 --> 00:52:58,290\n这个过程对象\nAnd that procedure object has\n\n874\n00:52:58,290 --> 00:53:00,464\n拥有一个环境\nthe environment it was defined in being that,\n\n875\n00:53:04,208 --> 00:53:05,888\n在这个环境中N被定义为0\nwhere n was defined to be 0.\n\n876\n00:53:07,680 --> 00:53:08,800\n它有一些代码\nAnd it has some code,\n\n877\n00:53:08,830 --> 00:53:11,376\n这个过程不需要参数\nwhich is the procedure of no arguments\n\n878\n00:53:11,408 --> 00:53:15,280\n该过程进行一些处理 然后进行赋值\nwhich does something, then sets something,\n\n879\n00:53:15,280 --> 00:53:16,736\n并返回N\nand returns n.\n\n880\n00:53:17,888 --> 00:53:18,816\n这个东西\nAnd this thing\n\n881\n00:53:19,424 --> 00:53:21,232\n将成为一个对象\nis going to be the object,\n\n882\n00:53:21,920 --> 00:53:24,672\n在全局环境中 它的名字是C1\nwhich in the global environment, will have the name c1.\n\n883\n00:53:26,128 --> 00:53:28,336\n所以我们在这建立一个名字 C1\nSo we construct a name here, c1,\n\n884\n00:53:28,640 --> 00:53:32,144\n并且说C1等于这个过程\nand say that equals that.\n\n885\n00:53:35,488 --> 00:53:37,360\n现在 再来创建另一个计数器\nNow, but also make another counter,\n\n886\n00:53:43,040 --> 00:53:45,136\n通过MAKE-COUNTER创建c2\nc2 to be make-counter\n\n887\n00:53:50,944 --> 00:53:52,192\n让它从10开始\nsay, starting with 10.\n\n888\n00:53:54,250 --> 00:53:55,904\n然后我执行同样的步骤\nThen I do essentially the same thing.\n\n889\n00:53:56,640 --> 00:54:00,400\n我应用这个MAKE-COUNTER过程\nI apply the make-counter procedure, which I got from here,\n\n890\n00:54:00,992 --> 00:54:04,528\n建立另一个框架 其中N等于10\nto make another frame with n being 10.\n\n891\n00:54:05,632 --> 00:54:09,184\n全局环境作为它的父环境\nThat frame has the global environment as its parent.\n\n892\n00:54:10,048 --> 00:54:11,808\n然后我构建一个过程\nI then construct a procedure\n\n893\n00:54:13,040 --> 00:54:17,632\n以这个框架作为它定义的环境\nwhich has that as it's frame of definition.\n\n894\n00:54:18,272 --> 00:54:21,664\n它的代码是\nThe code of it is\n\n895\n00:54:21,800 --> 00:54:24,384\n完成一些操作的无参过程\nthe procedure of no arguments which does something.\n\n896\n00:54:25,540 --> 00:54:28,600\n然后进行赋值 等等\nAnd it does a set, and so on.\n\n897\n00:54:28,600 --> 00:54:31,220\n然后返回N\nAnd n comes out. Okay?\n\n898\n00:54:31,456 --> 00:54:34,832\n这就是C2\nAnd c2 is this.\n\n899\n00:54:36,880 --> 00:54:39,328\n好 你们应该发现 某些东西开始变得有趣了\nWell, you're already beginning to see something fairly interesting.\n\n900\n00:54:40,176 --> 00:54:41,920\n这里有两个N\nThere are two n's here.\n\n901\n00:54:42,928 --> 00:54:44,192\n它们不是同一个N\nThey are not one n.\n\n902\n00:54:46,144 --> 00:54:48,160\n我每次调用MAKE-COUNTER的时候\nEach time I called make-counter,\n\n903\n00:54:48,640 --> 00:54:50,256\n我就创建了另一个N的实例\nI made another instance of n.\n\n904\n00:54:52,624 --> 00:54:54,400\n它们彼此独立 没有关联\nThese are distinct and separate from each other.\n\n905\n00:54:57,792 --> 00:55:00,288\n现在 我们来使用一下这些计数器\nNow, let's do some execution, use those counters.\n\n906\n00:55:05,920 --> 00:55:15,008\n如果此时 我调用C1 会发生什么？\nWell, what happens if I say, c1 at this point?\n\n907\n00:55:15,840 --> 00:55:17,344\n我会在这里查找\nWell, I go over here,\n\n908\n00:55:17,560 --> 00:55:19,984\n发现C1是一个过程\nand I say, oh yes, c1 is a procedure.\n\n909\n00:55:20,640 --> 00:55:22,784\n我要不带参数地调用这个过程\nI'm going to call this procedure on no arguments,\n\n910\n00:55:23,160 --> 00:55:24,960\n因为它不需要参数\nbut it has no parameters.\n\n911\n00:55:24,960 --> 00:55:25,632\n对吧？\nThat's right.\n\n912\n00:55:26,976 --> 00:55:27,840\n它的体是什么呢？\nWhat's its body?\n\n913\n00:55:27,960 --> 00:55:30,020\n我得来这里解释 因为我没有给誊过来\nWell, I have to look over here, because I didn't write it down.\n\n914\n00:55:30,020 --> 00:55:32,656\n这个过程体是将N赋值为N+1\nIt said, set n to one plus n\n\n915\n00:55:33,808 --> 00:55:34,896\n并且返回N\nand return n,\n\n916\n00:55:37,120 --> 00:55:38,128\n就是把N增大1\nincrement n.\n\n917\n00:55:38,976 --> 00:55:41,600\n它的N指的是这个\nWell, the n it says is this one.\n\n918\n00:55:43,088 --> 00:55:44,608\n所以我把这个n增大1\nSo I increment that n.\n\n919\n00:55:45,808 --> 00:55:47,008\n它变成了1\nThat becomes one,\n\n920\n00:55:48,640 --> 00:55:50,240\n然后返回了1\nand I return the value one.\n\n921\n00:55:53,136 --> 00:55:56,496\n之后我调用C2\nSupposing I then called c2.\n\n922\n00:55:58,384 --> 00:55:59,200\n我会做什么？\nWell, what do I do?\n\n923\n00:55:59,232 --> 00:56:03,330\nC2是相同的过程\nI say c2 is this procedure which does the same thing,\n\n924\n00:56:03,330 --> 00:56:04,480\n但这个N\nbut here's the n.\n\n925\n00:56:05,330 --> 00:56:06,576\n它变成了11\nIt becomes 11.\n\n926\n00:56:10,976 --> 00:56:14,592\n所以返回值是11\nAnd so I have an 11 which is the value.\n\n927\n00:56:15,920 --> 00:56:18,320\n然后我们再来调用一下C1\nI then can say, let's try c1 again.\n\n928\n00:56:20,912 --> 00:56:22,560\nC1是这个\nhum, c1 is this,\n\n929\n00:56:23,280 --> 00:56:24,160\n它是2\nthat's two,\n\n930\n00:56:27,248 --> 00:56:28,304\n所以结果是2\nso the answer is two.\n\n931\n00:56:29,664 --> 00:56:30,752\n然后调用C2\nAnd c2\n\n932\n00:56:33,376 --> 00:56:35,312\n然后C2通过同样的方法 返回了12\ngives me a 12 by the same method,\n\n933\n00:56:35,744 --> 00:56:37,550\n它在这里进行查找\nby walking down here looking at that\n\n934\n00:56:37,550 --> 00:56:39,280\n发现了N 并把它加1\nand saying, here's the n, I'm incrementing.\n\n935\n00:56:41,648 --> 00:56:43,680\n我拥有的是可计算的对象\nSo what I have are computational objects.\n\n936\n00:56:45,216 --> 00:56:46,864\n它们是两个计数器\nThere are two counters,\n\n937\n00:56:48,960 --> 00:56:51,024\n每一个都有各自独立的局部状态\neach with its own independent local state.\n\n938\n00:56:55,488 --> 00:56:56,624\n我们再进一步\nLet's talk about this a little.\n\n939\n00:56:56,640 --> 00:56:58,528\n这是个奇怪的东西\nThis is a strange thing.\n\n940\n00:57:01,120 --> 00:57:02,224\n什么是对象？\nWhat's an object?\n\n941\n00:57:04,112 --> 00:57:06,128\n这个概念并不明确\nIt's not at all obvious what an object is.\n\n942\n00:57:07,552 --> 00:57:09,456\n我们倾向于以对象的角度思考\nWe like to think about objects,\n\n943\n00:57:11,248 --> 00:57:13,328\n因为这样思考比较经济\nbecause it's economical to think that way.\n\n944\n00:57:14,624 --> 00:57:17,280\n这是一种智力上的经济\nIt's an intellectual economy.\n\n945\n00:57:18,576 --> 00:57:19,616\n我是一个对象\nI am an object.\n\n946\n00:57:20,992 --> 00:57:22,304\n你也是一个对象\nYou are an object.\n\n947\n00:57:23,552 --> 00:57:25,296\n但我们不是同一个对象\nWe are not the same object.\n\n948\n00:57:27,520 --> 00:57:29,648\n我可以把世界分为两部分\nI can divide the world into two parts,\n\n949\n00:57:29,920 --> 00:57:31,856\n我和你\nme and you,\n\n950\n00:57:31,920 --> 00:57:33,312\n以及其它的东西\nand there's other things as well,\n\n951\n00:57:34,704 --> 00:57:35,264\n使得\nsuch that\n\n952\n00:57:35,440 --> 00:57:39,504\n大多数对于我的讨论\nmost of the things I might want to discuss about my workings\n\n953\n00:57:39,680 --> 00:57:40,896\n不会影响到你\ndo not involve you,\n\n954\n00:57:41,392 --> 00:57:44,672\n大多数对于你的讨论不会牵涉到我\nand most of the things I want to discuss about your workings don't involve me.\n\n955\n00:57:45,664 --> 00:57:46,944\n我有血压\nI have a blood pressure,\n\n956\n00:57:47,504 --> 00:57:48,384\n体温\na temperature,\n\n957\n00:57:49,360 --> 00:57:51,488\n呼吸频率\na respiration rate,\n\n958\n00:57:53,344 --> 00:57:54,992\n血液中有确定的血糖值\ncertain amount of sugar in my blood,\n\n959\n00:57:56,112 --> 00:57:59,344\n数不清的 数以千计的状态变量--上百万实际上\nand numerous, thousands, of state variables-- millions actually,\n\n960\n00:57:59,376 --> 00:58:00,656\n我不知道具体有多少\nor I don't know how many--\n\n961\n00:58:00,930 --> 00:58:03,488\n以物理学观点 我拥有大量的状态变量\nhuge numbers of state variables in the physical sense\n\n962\n00:58:04,912 --> 00:58:07,120\n如果将我视为一个粒子的话\nwhich represent the state of me as a particle,\n\n963\n00:58:09,152 --> 00:58:10,640\n你也有许许多多这样的变量\nand you have gazillions of them as well.\n\n964\n00:58:12,688 --> 00:58:14,944\n我们的大多数变量之间是好无联系的\nAnd most of mine are uncoupled to most of yours.\n\n965\n00:58:17,312 --> 00:58:19,504\n所以可以计算我的属性\nSo we can compute the properties of me\n\n966\n00:58:20,560 --> 00:58:22,832\n而不用太担心你的属性\nwithout worrying too much about the properties of you.\n\n967\n00:58:23,824 --> 00:58:25,776\n如果把我们两个放在一起计算\nIf we had to work about both of us together,\n\n968\n00:58:25,960 --> 00:58:27,824\n那么我们需要考虑的状态的数量\nthan the number of states that we have to consider\n\n969\n00:58:27,824 --> 00:58:30,010\n就是你与我的状态的数量的乘积\nis the product of the number of states you have and the number of states I have.\n\n970\n00:58:30,528 --> 00:58:32,112\n按对象解耦的话 则只需考虑你我状态之和\nBut this way it's almost a sum.\n\n971\n00:58:32,656 --> 00:58:35,344\n然而 实际上有一种力量把我们耦合起来\nNow, indeed there are forces that couple us.\n\n972\n00:58:36,000 --> 00:58:37,952\n我对你讲话 你的状态就变了\nI'm talking to you and your state changes.\n\n973\n00:58:38,448 --> 00:58:40,096\n我看着你 我的状态就变了\nI'm looking at you and my state changes.\n\n974\n00:58:41,728 --> 00:58:44,080\n因此 我的变量中的一小部分\nSome of my state variables, a very few of them,\n\n975\n00:58:44,336 --> 00:58:46,070\n与你的一些变量是耦合的\ntherefore, are coupled to yours.\n\n976\n00:58:46,070 --> 00:58:47,800\n如果你突然大喊大叫\nIf you were to suddenly yell very loud,\n\n977\n00:58:47,800 --> 00:58:48,880\n我的血压就会升高\nmy blood pressure would go up.\n\n978\n00:58:54,304 --> 00:58:56,864\n然而 将世界看作是由独立的变量\nHowever, and it may not be always appropriate\n\n979\n00:58:57,170 --> 00:59:01,168\n和独立的粒子组成的是不恰当的\nto think about the world as being made out of independent states and independent particles.\n\n980\n00:59:02,128 --> 00:59:04,464\n在像量子力学这样的东西里存在大量的BUG\nLots of the bugs that occur in things like quantum mechanics,\n\n981\n00:59:05,230 --> 00:59:08,704\n或者当我们思考像量子力学之类的东西的时候 会在我们的脑海中产生bug\nor the bugs in our minds that occur when we think about things like quantum mechanics,\n\n982\n00:59:08,896 --> 00:59:10,970\n这是由于 当我们思考事物时\nare due the fact that we are trying to think about things\n\n983\n00:59:10,970 --> 00:59:12,960\n会去将事物分解为相互独立的部分来看待\nbeing broken up into independent pieces,\n\n984\n00:59:13,584 --> 00:59:17,328\n而事实上事物的耦合程度 远远大于在表面所看到的\nwhen in fact there's more coupling than we see on the surface,\n\n985\n00:59:18,016 --> 00:59:19,440\n即便这样 我们仍像那样思考\nor that we want to believe in,\n\n986\n00:59:19,616 --> 00:59:21,696\n是因为我们希望高效并且有效的进行计算\nbecause we want to compute efficiently and effectively.\n\n987\n00:59:22,192 --> 00:59:23,824\n我们被培养成以那种方式进行思考\nWe've been trained to think that way.\n\n988\n00:59:29,760 --> 00:59:30,512\n大家看\nWell, let's see.\n\n989\n00:59:31,504 --> 00:59:33,440\n我们如何才能知道我们是否有对象？\nHow would we know if we had objects at all?\n\n990\n00:59:35,120 --> 00:59:37,344\n如果我们有对象 应该如何分辨呢？\nHow can we tell if we have objects?\n\n991\n00:59:37,640 --> 00:59:41,456\n通过思考一些光学现象\nConsider some possible optical illusions.\n\n992\n00:59:42,464 --> 00:59:43,136\n就能解答这个问题\nThis could be done.\n\n993\n00:59:45,040 --> 00:59:47,696\n这几截粉笔不完全相同\nThese pieces of chalk are not appropriately identical,\n\n994\n00:59:47,760 --> 00:59:50,208\n但假设 只通过观察是无法区分它们的\nbut supposing you couldn't tell the difference of them by looking at them.\n\n995\n00:59:52,048 --> 00:59:53,320\n有一种可能\nWell, there's a possibility\n\n996\n00:59:53,320 --> 00:59:55,168\n是这一切都是我们与镜子的游戏\nthat this all a game I'm playing with mirrors.\n\n997\n00:59:56,070 --> 00:59:57,600\n它们真的是同一截粉笔\nIt's really the same piece of chalk,\n\n998\n00:59:59,360 --> 01:00:00,480\n但你看到了两个\nbut you're seeing two of them.\n\n999\n01:00:01,616 --> 01:00:03,872\n你怎么知道你看到的是一个还是两个呢？\nHow would you know if you're seeing one or two?\n\n1000\n01:00:05,040 --> 01:00:06,704\n我只知道有一种方法可以确定\nWell, there's only one way I know.\n\n1001\n01:00:07,376 --> 01:00:08,944\n抓起其中一个并且改变它\nYou grab one of them and change it\n\n1002\n01:00:09,456 --> 01:00:10,672\n然后看看另一个有没有跟着变化\nand see if the other one changed.\n\n1003\n01:00:14,016 --> 01:00:14,672\n而另一个没有变化\nAnd it didn't,\n\n1004\n01:00:15,504 --> 01:00:16,144\n所以它们是两截不同粉笔\nso there's two of them.\n\n1005\n01:00:19,504 --> 01:00:20,160\n另一方面\nAnd, on the other hand,\n\n1006\n01:00:20,176 --> 01:00:22,208\n事物还有一些其它的类似的纠结属性\nthere is some other screwy properties of things like that.\n\n1007\n01:00:22,576 --> 01:00:24,016\n例如 我们怎么才知道某个东西是否改变了呢？\nLike, how do we know if something changed?\n\n1008\n01:00:25,008 --> 01:00:27,936\n我们需要在它改变之前和之后进行观察\nWe have to look at it before and after the change.\n\n1009\n01:00:28,650 --> 01:00:30,020\n改变就是赋值\nThe change is an assignment,\n\n1010\n01:00:30,020 --> 01:00:31,456\n它是时间中的一个时刻\nit's a moment in time.\n\n1011\n01:00:32,144 --> 01:00:34,608\n但是那意味着我们需要知道 我们看到的是否是同一个\nBut that means we have to know it was the same one that we're looking at.\n\n1012\n01:00:36,512 --> 01:00:38,840\n所以一些东西非常奇怪\nSo some very strange, and unusual,\n\n1013\n01:00:38,840 --> 01:00:40,384\n不同寻常并且晦涩难懂\nand obscure, and -- I don't understand\n\n1014\n01:00:40,840 --> 01:00:43,520\n并且我不理解与赋值\nthe problems associated with assignment,\n\n1015\n01:00:44,450 --> 01:00:46,288\n变化以及对象有关的问题\nand change, and objects.\n\n1016\n01:00:47,296 --> 01:00:48,992\n这些东西可能变得非常非常糟糕\nThese could get very, very bad.\n\n1017\n01:00:51,408 --> 01:00:52,128\n例如\nFor example,\n\n1018\n01:00:53,312 --> 01:00:55,600\n我 一个特定的人\nhere I am, I am a particular person,\n\n1019\n01:00:56,160 --> 01:00:57,728\n一个特定的对象\na particular object, okay?\n\n1020\n01:00:57,960 --> 01:00:59,312\n现在 我可以拿出小刀\nNow, I can take out my knife,\n\n1021\n01:01:00,688 --> 01:01:01,776\n切下一片我的指甲\nand cut my fingernail.\n\n1022\n01:01:01,890 --> 01:01:04,816\n一片指甲掉在了桌子上\nAlright? A piece of my fingernail has fallen off onto the table.\n\n1023\n01:01:05,936 --> 01:01:10,160\n我相信自己和一秒钟之前的自己 是同一个人\nI believe I am the same person I was a second ago,\n\n1024\n01:01:10,976 --> 01:01:12,816\n但在物理上并不是分毫不差\nbut I'm not physically the same in the slightest.\n\n1025\n01:01:14,464 --> 01:01:15,430\n我已经改变了\nI have changed.\n\n1026\n01:01:15,584 --> 01:01:16,656\n为什么我还是同一个人呢？\nWhy am I the same?\n\n1027\n01:01:18,112 --> 01:01:19,408\n什么能认定我的身份呢？\nWhat is the identity of me?\n\n1028\n01:01:20,960 --> 01:01:23,504\n我不知道\nI don't know...Okay?\n\n1029\n01:01:25,056 --> 01:01:27,888\n除非我有某种特征\nExcept for the fact that I have some sort of identity.\n\n1030\n01:01:29,712 --> 01:01:33,040\n我觉得 由于引入赋值和对象\nAnd so, I think by introducing assignment and objects,\n\n1031\n01:01:33,648 --> 01:01:38,288\n我们不得不去面对这种\nwe have opened ourselves up to all the horrible questions of philosophy\n\n1032\n01:01:38,416 --> 01:01:42,240\n困扰了哲学家们上千年的哲学问题\nthat have been plaguing philosophers for some thousands of years about this sort of thing.\n\n1033\n01:01:43,424 --> 01:01:44,992\n这也是相比之下 为什么数学清晰得多\nIt's why mathematics is a lot cleaner.\n\n1034\n01:01:45,696 --> 01:01:50,240\n我将尽我所能地向大家阐述关于动作和身份的理解\nLet's look at the best things I know to say about actions and identity.\n\n1035\n01:01:52,448 --> 01:01:55,392\n我们说动作A 对于对于某个对象X有影响\nWe say that an action, a, had an effect on an object, x,\n\n1036\n01:01:55,776 --> 01:01:56,704\n换句话说\nor equivalently,\n\n1037\n01:01:56,928 --> 01:01:58,416\nX被A改变\nthat x was changed by a,\n\n1038\n01:01:58,896 --> 01:02:01,664\n如果某个属性P 在P作用于X之前为真\nif some property, p, which was true of x before a,\n\n1039\n01:02:01,872 --> 01:02:03,760\n在A作用于X之后为假\nbecame false of x after a.\n\n1040\n01:02:04,992 --> 01:02:05,632\n那是个测试\nThat's test.\n\n1041\n01:02:06,624 --> 01:02:09,664\n这也意味着 我必须有变动前和变动后的X\nIt still means I have to have the x before and after.\n\n1042\n01:02:10,912 --> 01:02:12,544\n或者 换句话说\nOr, the other way of saying this is,\n\n1043\n01:02:12,944 --> 01:02:14,944\n我们说对任一动作 两个对象X和Y是同一个对象\nwe say that two objects x and y are the same for any action\n\n1044\n01:02:14,976 --> 01:02:17,936\n当且仅当 该动作对X、Y有同样的影响\nwhich has an effect on x has the same effect on y\n\n1045\n01:02:19,632 --> 01:02:21,390\n然而 就像我说的\nHowever, objects are very useful,\n\n1046\n01:02:21,440 --> 01:02:23,184\n对象在智力经济上是非常有用的\nas I said, for intellectual economy.\n\n1047\n01:02:24,640 --> 01:02:27,120\n对于它们来说非常有用的东西之一\nOne of the things that's incredibly useful about them,\n\n1048\n01:02:28,272 --> 01:02:29,440\n就是对于这个世界\nis that the world\n\n1049\n01:02:30,784 --> 01:02:34,800\n我们习惯于把它认为是由带有独立状态的独立对象所构成的\nis made out of independent objects with independent local state.\n\n1050\n01:02:35,008 --> 01:02:37,280\n虽然那并不完全正确 但我们喜欢以那样的的方式来思考\nWe like to think that way, although it isn't completely true.\n\n1051\n01:02:39,680 --> 01:02:42,030\n当我们要写一个非常复杂的程序\nWhen we want to make very complicated programs\n\n1052\n01:02:42,030 --> 01:02:43,264\n来应对这样一个世界时\nthat deal with such a world,\n\n1053\n01:02:43,984 --> 01:02:46,448\n如果我们希望这些程序可以被我们理解\nif we want those programs to be understandable by us\n\n1054\n01:02:46,912 --> 01:02:48,144\n并且也是可修改的\nand also to be changeable,\n\n1055\n01:02:48,730 --> 01:02:51,120\n那么如果世界改变了 我们只需要稍微改动一下程序\nso that if we change the world we change the program only a little bit,\n\n1056\n01:02:51,392 --> 01:02:53,700\n我们希望建立一种联系 一种同构\nthen we want there to be connections, isomorphism,\n\n1057\n01:02:53,824 --> 01:02:56,880\n建立在真实世界的对象与我们脑海中的对象之间\nbetween the objects in the world and the objects in our mental model.\n\n1058\n01:02:58,768 --> 01:03:01,440\n世界的模块化 使我们的程序得以模块化\nThe modularity of the world can give us the modularity in our programming.\n\n1059\n01:03:02,416 --> 01:03:05,360\n所以我们发明了面向对象编程\nSo we invent things called object-oriented programming and things like that\n\n1060\n01:03:05,888 --> 01:03:08,368\n使我们获得那样的力量\nto provide us with that power.\n\n1061\n01:03:10,064 --> 01:03:10,944\n但是 它甚至更简单\nBut it's even easier.\n\n1062\n01:03:10,944 --> 01:03:12,256\n让我们玩一个小游戏\nLet's play a little game.\n\n1063\n01:03:12,270 --> 01:03:13,184\n我想通过这个游戏\nI want to play a little game,\n\n1064\n01:03:13,390 --> 01:03:15,776\n给你展示一个更简单的例子\nshow you an even easier example\n\n1065\n01:03:16,000 --> 01:03:21,744\n来说明谨慎地使用赋值语句 可以增强模块性\nor where modularity can be enhanced by using an assignment statement, judiciously.\n\n1066\n01:03:22,864 --> 01:03:25,350\n有一件事 我想让你牢牢地铭记\nOne thing I want to enforce and impress on you,\n\n1067\n01:03:25,450 --> 01:03:27,440\n就是不要像在FORTRAN Basic\nis don't use assignment statements the way\n\n1068\n01:03:27,456 --> 01:03:29,790\n或者Pascal里一样使用赋值语句\nyou use it in FORTRAN or Basic or something or Pascal,\n\n1069\n01:03:30,000 --> 01:03:31,712\n你不那样做 也能达到目的\nto do the things you don't have to do with it.\n\n1070\n01:03:34,048 --> 01:03:36,624\n这不是思考大多数事情的正确方式\nIt's not the right way to think for most things.\n\n1071\n01:03:36,976 --> 01:03:38,288\n有些时候它是必要的\nSometimes it's essential,\n\n1072\n01:03:38,688 --> 01:03:39,690\n或者可能是必要的\nor maybe it's essential.\n\n1073\n01:03:39,690 --> 01:03:40,976\n我们一会更深入地去研究\nWe'll see more about that too.\n\n1074\n01:03:42,240 --> 01:03:44,224\n我要给你展示一个有趣的游戏\nOK, let me show you a fun game here.\n\n1075\n01:03:47,616 --> 01:03:49,424\n从前有一个数学家\nThere was a mathematician\n\n1076\n01:03:49,680 --> 01:03:53,696\n叫做Cesaro\nby the name of Cesaro--or Cesaro, Cesaro I suppose it is--\n\n1077\n01:03:54,480 --> 01:03:57,456\n他发现了一个计算pi的巧妙方法\nwho figured out a clever way of computing pi.\n\n1078\n01:03:58,380 --> 01:04:04,304\n这个方法是说 如果我有两个随机数\nIt turns out that if I take two random numbers\n\n1079\n01:04:05,248 --> 01:04:06,944\n两个随机的整数\ntwo integers at random,\n\n1080\n01:04:07,744 --> 01:04:09,488\n计算它们的最大公约数\nand compute the greatest common divisor,\n\n1081\n01:04:10,944 --> 01:04:13,248\n结果可能是1 或者不是1\ntheir greatest common divisor is either one or it's not one.\n\n1082\n01:04:13,840 --> 01:04:15,648\n如果是1 它们没有公约数\nIf it's one, then they have no common divisors.\n\n1083\n01:04:18,144 --> 01:04:20,680\n如果它们的最大公约数是1\nIf their greatest common divisor is one--\n\n1084\n01:04:21,120 --> 01:04:23,090\n这两个随机数\nthe probability that two random numbers,\n\n1085\n01:04:23,090 --> 01:04:26,384\n两个随机生成的数 最大公约数为1的概率\ntwo numbers chosen at random, has as greatest common divisor one\n\n1086\n01:04:26,580 --> 01:04:27,824\n与pi有关系\nis related to pi.\n\n1087\n01:04:29,328 --> 01:04:30,112\n事实上\nIn fact--\n\n1088\n01:04:31,110 --> 01:04:32,336\n是的 这很奇怪\nyes, it's very strange--\n\n1089\n01:04:32,944 --> 01:04:34,416\n当然有其他计算pi的方法\nof course there are other ways of computing pi,\n\n1090\n01:04:34,416 --> 01:04:38,944\n像投针法之类的的方法\nlike dropping pins on flags, and things like that, and sort of the same kind of thing.\n\n1091\n01:04:40,192 --> 01:04:48,976\nN1和N2的最大公约数是1的概率为\nSo the probability of that the GCD of number one and number two,\n\n1092\n01:04:49,440 --> 01:04:51,024\nN1、N2是随机选取的两个数\ntwo random numbers chosen,\n\n1093\n01:04:51,712 --> 01:04:53,664\n是6/pi^2\nis 6 over pi squared.\n\n1094\n01:04:55,616 --> 01:04:56,832\n我不准备证明这个\nI'm not going to try to prove that.\n\n1095\n01:04:57,152 --> 01:04:59,648\n事实上这不难 并且有些有趣\nIt's actually not too hard and sort of fun.\n\n1096\n01:05:01,072 --> 01:05:03,056\n我们要怎样估算这个概率呢？\nHow would we estimate such probability?\n\n1097\n01:05:03,536 --> 01:05:06,464\n我们估算概率的方法则是\nWell, the way we do that, the way we estimate the probabilities,\n\n1098\n01:05:07,232 --> 01:05:08,656\n是做大量的实验\nis by doing lots of experiments,\n\n1099\n01:05:09,200 --> 01:05:12,010\n去计算成功的试验\nand then computing the ratios of the ones that come out one way\n\n1100\n01:05:12,010 --> 01:05:13,584\n与试验总次数的比率\nto the total number of experiments we do.\n\n1101\n01:05:16,320 --> 01:05:17,280\n这种方法叫做蒙特卡罗方法\nIt's called Monte Carlo,\n\n1102\n01:05:18,048 --> 01:05:22,380\n它也可以用于计算包含大量变量的积分\nand it's useful in other contexts for doing things like integrals where you have lots and lots of variables--\n\n1103\n01:05:22,944 --> 01:05:25,280\n其中积分的面积是限定的\nthe space which is limiting the dimensions you are doing you integral in.\n\n1104\n01:05:26,272 --> 01:05:28,704\n回到这里\nBut going back to here,\n\n1105\n01:05:29,760 --> 01:05:31,728\n我们来看看这张幻灯片\nLet's look at this slide,\n\n1106\n01:05:33,968 --> 01:05:36,928\n我们可以用Cesaro的方法来估算pi的值\nWe can use Cesaro's method for estimating pi\n\n1107\n01:05:37,190 --> 01:05:43,180\n通过N次试验 取结果的六分之一 开根号\nwith n trials by taking the square root of six over a Monte Carlo,\n\n1108\n01:05:43,290 --> 01:05:46,464\n用蒙特卡罗方法\na Monte Carlo experiment with n trials,\n\n1109\n01:05:46,800 --> 01:05:50,380\n进行了N次Cesaro实验\nwith n trials using Cesaro's experiment,\n\n1110\n01:05:51,376 --> 01:05:57,568\n这个实验是关于两个随机数的最大公约数的--\nwhere Cesaro's experiment is the test of whether the GCD of two random numbers--\n\n1111\n01:05:58,960 --> 01:06:01,600\n你可以看到 我已经在这里进行了一些赋值\nAnd you can see that I've already got some assignments in here,\n\n1112\n01:06:01,840 --> 01:06:03,136\n就像我写的这样\njust by what I wrote.\n\n1113\n01:06:04,048 --> 01:06:07,490\n这个在括号中的RAND\nThe fact that this word rand, in parentheses,\n\n1114\n01:06:07,490 --> 01:06:09,097\n这个过程调用\ntherefore, that procedure call,\n\n1115\n01:06:09,090 --> 01:06:11,395\n生成了一个与这个RAND不同的值\nyields a different value than this one,\n\n1116\n01:06:11,390 --> 01:06:13,728\n至少是我写的这样所假设的\nat least that's what I'm assuming by writing this this way,\n\n1117\n01:06:14,624 --> 01:06:16,752\n这表明这不是一个函数\nindicates that this is not a function,\n\n1118\n01:06:18,208 --> 01:06:20,576\n这里面会有一个不断改变内部状态\nthat there's internal state in it which is changing.\n\n1119\n01:06:22,272 --> 01:06:28,640\n如果两个随机数的最大公约数等于1\nIf the GCD of those two random numbers is equal to one,\n\n1120\n01:06:28,640 --> 01:06:29,792\n这就是整个实验过程\nthat's the experiment.\n\n1121\n01:06:31,488 --> 01:06:35,184\n那么我有了一个实验方法 用来估算pi的值\nSo here I have an experimental method for estimating the value of pi.\n\n1122\n01:06:36,512 --> 01:06:39,728\n我可以轻松地将这个问题分为两个部分\nWhere, I can easily divide this problem into two parts.\n\n1123\n01:06:40,020 --> 01:06:44,704\n一部分是使用蒙特卡罗方法进行特定的Cesaro实验 就像你刚才看到那个\nOne is the specific Monte Carlo experiment of Cesaro, which you just saw,\n\n1124\n01:06:44,992 --> 01:06:48,560\n另一部分就是一般性蒙特卡罗方法的实现\nand the other is the general technique of doing Monte Carlo experiments.\n\n1125\n01:06:49,168 --> 01:06:50,272\n就是这个\nAnd that's what this is.\n\n1126\n01:06:51,040 --> 01:06:55,472\n如果我想进行N次蒙特卡罗试验\nIf I want to do Monte Carlo experiments with n trials,\n\n1127\n01:06:55,670 --> 01:06:58,368\n即一个确定的试验次数 和一个确定的实验\na certain number of trials, and a particular experiment,\n\n1128\n01:06:59,312 --> 01:07:00,336\n我进行实验的方法就是\nthe way I do that\n\n1129\n01:07:00,848 --> 01:07:02,704\n构建一个迭代过程\nis I make a little iterative procedure\n\n1130\n01:07:03,312 --> 01:07:07,264\n这个过程有两个变量 分别是试验的剩余次数和通过次数\nwhich has variable the number of trials remaining and the number trials that have been passed,\n\n1131\n01:07:08,352 --> 01:07:09,440\n也就是实验结果为真的次数\nthat I've gotten true.\n\n1132\n01:07:10,130 --> 01:07:12,213\n如果剩余次数为0\nAnd if the number remaining is 0,\n\n1133\n01:07:12,210 --> 01:07:15,360\n结果就是通过的次数除以总次数\nthen the answer is the number past divided by this whole number of trials,\n\n1134\n01:07:16,048 --> 01:07:17,520\n也就是该概率的估算值\nwas the estimate of the probability.\n\n1135\n01:07:19,072 --> 01:07:20,040\n如果剩余次数不是0\nAnd if it's not,\n\n1136\n01:07:20,040 --> 01:07:22,080\n如果还有试验要做\nif I have more trials to do,\n\n1137\n01:07:22,080 --> 01:07:23,824\n那么接下来我们就进行一次试验\nthen let's do one. We do an experiment.\n\n1138\n01:07:23,856 --> 01:07:27,300\n我们调用一次没有参数的实验的过程\nWe call the procedure which is experiment on no arguments.\n\n1139\n01:07:27,300 --> 01:07:28,432\n我们进行这个试验\nWe do the experiment\n\n1140\n01:07:29,104 --> 01:07:30,640\n如果实验结果为真\nand then, if that turned out to be true,\n\n1141\n01:07:30,820 --> 01:07:32,256\n我们继续循环\nwe go around the loop\n\n1142\n01:07:32,620 --> 01:07:35,424\n试验剩余次数减1\ndecrementing the number of experiments we have to do by one\n\n1143\n01:07:35,700 --> 01:07:37,488\n将试验通过次数加1\nand incrementing the number that were passed.\n\n1144\n01:07:38,576 --> 01:07:40,112\n如果试验的结果为假\nAnd if the experiment was false,\n\n1145\n01:07:40,416 --> 01:07:42,250\n我们继续循环\nwe just go around the loop\n\n1146\n01:07:42,320 --> 01:07:44,380\n剩余试验次数减1\ndecrementing the number of experiments remaining\n\n1147\n01:07:44,448 --> 01:07:46,608\n试验通过次数保持不变\nand keeping the number passed the same.\n\n1148\n01:07:48,768 --> 01:07:54,592\n我们以TRIAL为剩余次数 以0为通过次数 开始迭代\nWe start this up iterating over the total number of trials with 0 experiments past.\n\n1149\n01:07:55,424 --> 01:07:57,104\n多么简洁的小程序啊\nA very elegant little program.\n\n1150\n01:07:57,744 --> 01:08:00,550\n我不一定非要进行Cesaro的实验\nAnd I don't have to just do this with Cesaro's experiment,\n\n1151\n01:08:00,550 --> 01:08:02,736\n它可以用来进行很多种蒙特卡罗实验\nit could be lots of Monte Carlo experiments I might do.\n\n1152\n01:08:03,360 --> 01:08:07,120\n当然 它依赖于某种随机数生成器的存在\nOf course, this depends upon the existence of some sort of random number generator.\n\n1153\n01:08:07,344 --> 01:08:10,992\n随机数生成器通常是像这种的东西\nAnd random number generators generally look something like this.\n\n1154\n01:08:13,600 --> 01:08:16,320\n这是一个随机数生成器--\nThere is a random number generator--\n\n1155\n01:08:17,424 --> 01:08:25,216\n它实际上就是一个过程 具体行为跟计数器有些相似\nis in fact a procedure which is going to do something just like the counter.\n\n1156\n01:08:25,616 --> 01:08:27,520\n它会把X的值更新为\nIt's going to update an x\n\n1157\n01:08:28,336 --> 01:08:31,824\n将某个函数应用于X的结果\nto the result of applying some function to x,\n\n1158\n01:08:32,200 --> 01:08:35,280\n而这类古怪的函数\nwhere this function is some screwy kind of function\n\n1159\n01:08:35,392 --> 01:08:40,160\n你可以在Kunth写的关于编程细节的书中找到\nthat you might find out in Knuth's books on the details of programming.\n\n1160\n01:08:41,568 --> 01:08:45,750\n他写的书绝妙而充满了编程细节\nHe does these wonderful books that are full of the details of programming,\n\n1161\n01:08:45,750 --> 01:08:48,528\n虽然我记不住随机数生成器该怎样写\nbecause I can't remember how to make a random number generator,\n\n1162\n01:08:48,630 --> 01:08:50,624\n但我可以在书里找出一个来用\nbut I can look it up there, and I can find out.\n\n1163\n01:08:51,648 --> 01:08:54,016\n最后 我返回了X的值\nAnd then, eventually, I return the value of x\n\n1164\n01:08:54,080 --> 01:08:57,408\n也就是随机数生成器的内部状态变量\nwhich is the state variable internal to the random number generator.\n\n1165\n01:08:58,288 --> 01:09:00,752\n这个状态变量以某种方式被初始化\nThat state variable is initialized somehow,\n\n1166\n01:09:01,328 --> 01:09:02,240\n从而获得了一个值\nand has a value.\n\n1167\n01:09:03,392 --> 01:09:08,112\n这个过程被定义在那个变量被约束的上下文中\nAnd this procedure is defined in the context where that variable is bound\n\n1168\n01:09:10,416 --> 01:09:15,264\n所以你在这看到的 是一个隐藏的局部状态\nSo this is a hidden piece of local state that you see here.\n\n1169\n01:09:15,872 --> 01:09:20,240\n这个过程定义在那个上下文中\nAnd this procedure is defined in that context.\n\n1170\n01:09:21,568 --> 01:09:23,664\n这样做起来非常容易\nNow, that's a very simple thing to do.\n\n1171\n01:09:24,880 --> 01:09:25,792\n而且结果也非常好\nAnd it's very nice.\n\n1172\n01:09:25,990 --> 01:09:27,776\n设想 我不想用赋值\nSupposing, I didn't want to use assignments.\n\n1173\n01:09:29,104 --> 01:09:31,472\n假设我想写一个不带赋值的程序\nSupposing, I wanted to write this program without assignments.\n\n1174\n01:09:32,736 --> 01:09:33,936\n我将遇到什么困难？\nWhat problems would I have?\n\n1175\n01:09:35,520 --> 01:09:37,408\n让我们来看看\nWell, let's see.\n\n1176\n01:09:37,824 --> 01:09:41,104\n我要用一下头顶上的投影仪了\nI'd like to use the overhead machine here,\n\n1177\n01:09:42,064 --> 01:09:42,704\n多谢\nthank you.\n\n1178\n01:09:43,472 --> 01:09:47,660\n首先 我们来整体看一下 这是一个很庞大的东西\nFirst of all, let's look at the whole thing. It's a big story. Right?\n\n1179\n01:09:48,016 --> 01:09:49,904\n它告诉你有某些东西出了问题\nUnfortunately, which tells you there is something wrong.\n\n1180\n01:09:50,960 --> 01:09:52,752\n毕竟有这么大一堆东西呢\nIt's at least that big,\n\n1181\n01:09:53,424 --> 01:09:54,608\n庞大而单一\nand it's monolithic.\n\n1182\n01:09:56,768 --> 01:10:00,120\n你不需要现在去理解或看这里的文本\nYou don't have to understand or look at the text there right now\n\n1183\n01:10:00,120 --> 01:10:01,392\n就把它们看做一个整体\nto see that it's monolithic.\n\n1184\n01:10:01,920 --> 01:10:04,897\n它不是Cesaro的实验\nIt isn't a thing which is Cesaro's experiment.\n\n1185\n01:10:04,890 --> 01:10:07,904\n它不是从蒙特卡罗过程中抽取出来的\nIt's not pulled out from the Monte Carlo process.\n\n1186\n01:10:09,872 --> 01:10:11,840\n它不是分离的 让我们来看看为什么\nIt's not separated. Let's look why.\n\n1187\n01:10:14,224 --> 01:10:15,850\n记住 这里的约束是\nRemember, the constraint here\n\n1188\n01:10:15,850 --> 01:10:17,872\n每个过程\nis that every procedure\n\n1189\n01:10:18,690 --> 01:10:22,208\n对于同样的参数 将返回同样的值\nreturn the same value for the same arguments.\n\n1190\n01:10:22,976 --> 01:10:24,752\n每个过程就是一个函数\nEvery procedure represents a function.\n\n1191\n01:10:26,928 --> 01:10:28,500\n那是另一种约束\nThat's a different kind of constraint.\n\n1192\n01:10:28,500 --> 01:10:31,216\n因为当我赋值时 我可以改变一些内部状态变量\nBecause when I have assignments, I can  change some internal state variable.\n\n1193\n01:10:31,744 --> 01:10:34,032\n所以让我们来看看它是怎么出错的\nSo let's see how that causes things to go wrong.\n\n1194\n01:10:35,040 --> 01:10:36,144\n我们从头开始\nWell, start at the beginning.\n\n1195\n01:10:37,504 --> 01:10:41,920\n估算pi的过程看起来是一样的\nAh...The estimate of pi looks sort of the same.\n\n1196\n01:10:42,660 --> 01:10:45,888\n我取RAMDOM-GCD-TEST应用于N\nWhat I'm doing is I take the square root\n\n1197\n01:10:46,352 --> 01:10:50,224\n的结果分之6的平方根\nof six over the random GCD test applied to n\n\n1198\n01:10:50,740 --> 01:10:51,936\n就是这个\nwhereas that's what this is.\n\n1199\n01:10:52,960 --> 01:10:55,200\n在这里 我们开始看到了一些有趣的东西\nBut here, we are beginning to see something funny.\n\n1200\n01:10:55,200 --> 01:10:57,936\n对于以TRAILS为参数的RANDOM-GCD-TEST过程\nThe random GCD test of a certain number of trials\n\n1201\n01:10:58,320 --> 01:10:59,984\n就像我们之前做的一样\nis just like we had before,\n\n1202\n01:11:00,460 --> 01:11:04,666\n是一个以剩余次数\nan iteration on the number of trials remaining,\n\n1203\n01:11:04,660 --> 01:11:06,800\n通过次数\nthe number of trials that have been passed,\n\n1204\n01:11:08,272 --> 01:11:09,712\n另一个变量X为基准的迭代\nand another variable x.\n\n1205\n01:11:10,752 --> 01:11:11,760\n这个X是什么？\nWhat's that x?\n\n1206\n01:11:12,330 --> 01:11:15,200\nX是随机数发生器的状态\nThat x is the state of the random number generator.\n\n1207\n01:11:19,008 --> 01:11:21,160\n它会在这里被使用\nAnd it is now going to be used here.\n\n1208\n01:11:21,160 --> 01:11:23,791\n这里的同样的随机更新函数\nThe same random update function that I have over here\n\n1209\n01:11:23,790 --> 01:11:27,152\n来自于一个我另外写的随机数发生器\nis the one I would have used in a random number generator if I were building it the other way,\n\n1210\n01:11:27,712 --> 01:11:29,328\n或者从Knuth的书中找一个\nthe one I get out of Knuth's books.\n\n1211\n01:11:31,560 --> 01:11:33,360\nX将转化为X1\nx is going to get transformed into x1,\n\n1212\n01:11:33,376 --> 01:11:34,360\n但我需要两个随机数\nI need two random numbers.\n\n1213\n01:11:34,816 --> 01:11:36,928\nX1将被转化为X2\nAnd x1 is going to get transformed into x2,\n\n1214\n01:11:37,264 --> 01:11:38,448\n我有两个随机数\nI have two random numbers.\n\n1215\n01:11:39,504 --> 01:11:42,144\n然后进行和之前一样的步骤\nI then have to do exactly what I did before.\n\n1216\n01:11:42,520 --> 01:11:44,192\n取X1和X2的最大公约数\nI take the GCD of x1 x2.\n\n1217\n01:11:44,224 --> 01:11:47,152\n如果结果是1 则将X2作为下一个X的值继续循环\nIf that's one, then I go around the loop with X2 being the next value of x.\n\n1218\n01:11:54,784 --> 01:11:55,984\n这里所发生的\nYou see what's happened here\n\n1219\n01:11:56,880 --> 01:11:58,704\n随机数发生器的状态\nis that the state of the random number generator\n\n1220\n01:11:58,736 --> 01:12:01,700\n不再被限制于其内部\nis no longer confined to the insides of the random number generator.\n\n1221\n01:12:01,808 --> 01:12:02,736\n它已经暴露了出来\nIt has leaked out.\n\n1222\n01:12:03,330 --> 01:12:05,506\n它已经被暴露在\nIt has leaked out into my procedure\n\n1223\n01:12:05,500 --> 01:12:10,080\n我们的的蒙特卡罗实验的过程中\nthat does the Monte Carlo experiment.\n\n1224\n01:12:10,704 --> 01:12:11,870\n但比那更糟糕的是\nBut what's worse than that,\n\n1225\n01:12:11,870 --> 01:12:16,240\n同样的 因为它也被包含在我们的Cesaro实验中\nis it's also, because it was contained inside my experiment itself, Cesaro,\n\n1226\n01:12:16,784 --> 01:12:19,488\n它被暴露了两次 因为Cesaro被调用了两次\nIt leaked out that two. Because Cesaro called twice,\n\n1227\n01:12:20,864 --> 01:12:22,470\n每次有不同的值\nhas to have a different value each time,\n\n1228\n01:12:22,470 --> 01:12:25,168\n如果我要进行一个合理的实验的话\nif I going to have a legitimate experimental test.\n\n1229\n01:12:26,320 --> 01:12:28,320\n所以Cesaro也不能成为函数了\nSo Cesaro can't be a function either,\n\n1230\n01:12:31,040 --> 01:12:35,696\n除非我把随机数发生器的种子传给它\nunless I pass it the seed of the random number generator that is going to go wandering around.\n\n1231\n01:12:36,528 --> 01:12:39,370\n所以很不幸 随机数发生器的种子\nSo unfortunately, the seed of random number generator\n\n1232\n01:12:39,370 --> 01:12:42,777\n从随机数发生器中暴露到了Cesaro内部\nhas leaked out into Cesaro, from the random number generator,\n\n1233\n01:12:42,880 --> 01:12:45,168\n被暴露在蒙特卡罗实验中\nthat's leaked into the Monte Carlo experiment.\n\n1234\n01:12:45,648 --> 01:12:49,120\n很不幸 这里的蒙特卡罗实验不再是通用的了\nAnd, unfortunately, my Monte Carlo experiment here is no longer general.\n\n1235\n01:12:50,256 --> 01:12:51,808\n这里的蒙特卡罗实验\nThe Monte Carlo experiment here\n\n1236\n01:12:52,032 --> 01:12:54,736\n知道了我在实验中需要多少个随机数\nknows how many random numbers I need to do the experiment.\n\n1237\n01:12:58,960 --> 01:12:59,744\n这真的很糟糕\nThat's sort of horrible.\n\n1238\n01:13:00,080 --> 01:13:02,544\n我失去了将问题分解开来的能力\nI lost an ability to decompose a problem into pieces,\n\n1239\n01:13:03,440 --> 01:13:09,120\n因为我不愿意接受信息的循环\nbecause I wasn't willing to accept the little loop of information,\n\n1240\n01:13:09,504 --> 01:13:12,432\n反馈的过程\nthe feedback process,\n\n1241\n01:13:12,880 --> 01:13:15,940\n这之前都是发生在随机数发生器内部\nthat happens inside the random number generator before\n\n1242\n01:13:15,940 --> 01:13:21,216\n也就是赋值给一个限制在随机数生成器内部的状态变量\nthat was made by having an assignment to a state variable that was confined to the random number generator.\n\n1243\n01:13:22,920 --> 01:13:25,488\n所以实际上 随机数发生器是一个对象\nSo the fact that the random number generator is an object,\n\n1244\n01:13:25,920 --> 01:13:27,376\n它有一个内部状态变量\nwith an internal state variable,\n\n1245\n01:13:28,064 --> 01:13:29,360\n它不受任何东西影响\nit's affected by nothing,\n\n1246\n01:13:29,376 --> 01:13:31,600\n但是它会给你某些东西 把它的力量赐予你\nbut it'll give you something, and it will apply it's force to you,\n\n1247\n01:13:32,800 --> 01:13:34,288\n那是我们现在缺少的\nthat was what we're missing now.\n\n1248\n01:13:38,000 --> 01:13:40,730\n好 我认为我已经知道了\nOK, well I think we've seen\n\n1249\n01:13:40,730 --> 01:13:42,304\n引入赋值的充分理由\nenough reason for doing this,\n\n1250\n01:13:42,832 --> 01:13:45,248\n并且一些看起来很圆满\nand it all sort of looks very wonderful.\n\n1251\n01:13:45,380 --> 01:13:50,704\n如果赋值是一个好东西\nWouldn't it be nice if assignment was a good thing\n\n1252\n01:13:51,740 --> 01:13:53,040\n并且赋值是值得的 这不是很好吗？\nand maybe it's worth it,\n\n1253\n01:13:53,280 --> 01:13:54,144\n我不是很确定\nbut I'm not sure.\n\n1254\n01:13:55,344 --> 01:13:57,040\nMr. Gilbert和Sullivan说过\nAs Mr. Gilbert and Sullivan said,\n\n1255\n01:13:57,040 --> 01:13:58,515\n事物往往不像表面看到的那样\nthings are seldom what they seem,\n\n1256\n01:13:58,510 --> 01:14:00,352\n脱脂牛奶也能装成奶油\nskim milk masquerades as cream.\n\n1257\n01:14:01,872 --> 01:14:03,904\n谁有什么问题吗？\nAre there any questions?\n\n1258\n01:14:16,976 --> 01:14:18,304\n在座的有哲学家吗？\nAre there any philosophers here?\n\n1259\n01:14:20,064 --> 01:14:22,032\n有人想要讨论有关“对象”的问题吗？\nAnybody want to argue about objects?\n\n1260\n01:14:24,320 --> 01:14:25,504\n你们已经一头雾水了是吧？\nYou're just floored, right?\n\n1261\n01:14:29,720 --> 01:14:30,720\n你们还没有完成家庭作业呢\nAnd you haven't done your homework yet.\n\n1262\n01:14:30,736 --> 01:14:32,000\n你们需要提一个好问题\nYou haven't come up with a good question.\n\n1263\n01:14:36,352 --> 01:14:37,440\n好了\nOh, well.\n\n1264\n01:14:39,970 --> 01:14:42,336\n感谢你们 我们下课吧\nSure, thank you. Let's take the long break now.\n\n1265\n01:14:47,900 --> 01:14:56,416\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n1266\n01:14:56,448 --> 01:15:05,696\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec5b.srt",
    "content": "﻿1\n00:00:00,016 --> 00:00:02,464\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:02,608 --> 00:00:05,376\n翻译&&时间轴：张大伟（DreamAndDead）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:05,408 --> 00:00:08,128\n特别感谢：裘宗燕教授\n\n4\n00:00:08,144 --> 00:00:12,400\n计算机程序的构造和解释\n\n5\n00:00:12,496 --> 00:00:17,170\n计算对象\nComputational Objects\n\n6\n00:00:21,170 --> 00:00:24,128\n现在我们已经学习了\nPROFESSOR: Well, now that we've given you some power\n\n7\n00:00:24,432 --> 00:00:27,400\n如何创建局部状态和如何建模对象\nto make independent local state and to model objects,\n\n8\n00:00:28,336 --> 00:00:32,672\n我想我们应该找点复杂的东西\nI thought we'd do a bit of programming of a very complicated kind,\n\n9\n00:00:34,032 --> 00:00:36,368\n来实践一下学过的这些知识\njust to illustrate what you can do with this sort of thing.\n\n10\n00:00:40,430 --> 00:00:43,488\n我可以这么说 假设我们处在现实世界中\nI suppose, as I said, we were motivated by physical systems\n\n11\n00:00:44,112 --> 00:00:46,256\n我们把这个世界看作是\nthe ways we like to think about physical systems,\n\n12\n00:00:46,992 --> 00:00:51,088\n由许多的事物构成的\nwhich is that there are these things that the world is made out of.\n\n13\n00:00:52,060 --> 00:00:55,984\n每个事物都有其独立的局部状态\nAnd each of these things has particular independent local state,\n\n14\n00:00:57,248 --> 00:00:59,872\n正是这些独立的状态使其成为事物\nand therefore it is a thing. That's what makes it a thing.\n\n15\n00:01:01,280 --> 00:01:04,272\n因此我们说 在这个世界的模型中\nAnd then we're going to say that in the model in the world\n\n16\n00:01:04,288 --> 00:01:09,900\n我们在大脑中和计算机中对那个世界建模\nwe have a world and a model in our minds and in the computer of that world.\n\n17\n00:01:10,940 --> 00:01:12,544\n我想要建立一种对应关系\nAnd what I want to make is a correspondence\n\n18\n00:01:12,784 --> 00:01:15,216\n把现实世界和计算机中的对象联系起来\nbetween the objects in the world and the objects in the computer,\n\n19\n00:01:15,870 --> 00:01:17,744\n把现实世界中对象间的关系\nthe relationships between the objects in the world\n\n20\n00:01:17,968 --> 00:01:21,720\n与计算机中的模型对象间的关系 对应起来\nand the relationships between those same obj...--the model objects in the computer,\n\n21\n00:01:23,180 --> 00:01:25,520\n把现实世界中关联对象的函数\nand the functions that relate things in the\n\n22\n00:01:25,936 --> 00:01:28,110\n与计算机中的函数 对应起来\nto the functions that relate things in the computer.\n\n23\n00:01:30,840 --> 00:01:33,824\n这让我们获得了模块性\nThis buys us modularity.\n\n24\n00:01:34,740 --> 00:01:36,752\n如果我们认为现实世界是像那样的\nIf we really believe the world is like that,\n\n25\n00:01:37,360 --> 00:01:38,720\n也就是由许多小的事物构成的\nthat it's made out of these little pieces,\n\n26\n00:01:39,200 --> 00:01:41,472\n当然 我们可以把世界安排成那样\nand of course we could arrange our world to be like that,\n\n27\n00:01:42,032 --> 00:01:43,952\n我们只能对像那样的事物建模\nwe could only model those things that are like that,\n\n28\n00:01:45,456 --> 00:01:49,024\n这样 我们的程序就可以从现实世界中继承模块化\nthen we can inherit the modularity in the world into our programming.\n\n29\n00:01:50,450 --> 00:01:53,584\n这就是发明面向对象编程的初衷\nThat's why we would invent some of this object-oriented programming.\n\n30\n00:01:55,420 --> 00:01:58,192\n我所见过的最完美的对象（系统）\nWell, let's take the best kind of objects I know.\n\n31\n00:01:58,890 --> 00:02:04,176\n电气系统 就是非常非常完美的对象系统\nThey're completely--they're completely wonderful: electrical systems.\n\n32\n00:02:06,400 --> 00:02:12,992\n电气系统真的是物理学家构造的非常非常好的一种对象\nElectrical systems really are the physicist's best, best objects.\n\n33\n00:02:14,220 --> 00:02:16,760\n这里 我有一些机器零件\nYou see over here I have some piece of machinery.\n\n34\n00:02:17,120 --> 00:02:18,288\n就是这些零件\nRight here's a piece of machinery.\n\n35\n00:02:20,040 --> 00:02:22,880\n有一个电线连接起了\nAnd it's got an electrical wire connecting\n\n36\n00:02:23,664 --> 00:02:26,400\n零件的两个部分\none part of the machinery with another part of the machinery.\n\n37\n00:02:27,568 --> 00:02:30,864\n电气世界中 有一个非常棒的特性\nAnd one of the wonderful properties of the electrical world\n\n38\n00:02:31,648 --> 00:02:33,120\n就是我可以说这是一个对象\nis that I can say this is an object,\n\n39\n00:02:34,016 --> 00:02:34,976\n这又是一个对象\nand this is an object,\n\n40\n00:02:35,712 --> 00:02:37,536\n它们间的关联一目了然\nand they're-- the connection between them is clear.\n\n41\n00:02:38,240 --> 00:02:43,328\n而且 如果我没有用电线连接 它们便没有关联\nIn principle, there is no connection that I didn't describe with these wires.\n\n42\n00:02:44,740 --> 00:02:46,128\n比如我有一个灯泡\nLet's say if I have light bulbs,\n\n43\n00:02:46,528 --> 00:02:50,320\n一个灯泡和一个已经接在插座上的电源\nLet's say if I have light bulbs, a light bulb and a power supply that's plugged into the outlet.\n\n44\n00:02:51,632 --> 00:02:53,536\n关联非常明了\nThen the connection is perfectly clear.\n\n45\n00:02:53,620 --> 00:02:55,424\n这就是已知所有的连接方式了\nThere's no other connections that we know of.\n\n46\n00:02:56,220 --> 00:03:02,336\n就算我把连接电灯和电源的电线打个结\nIf I were to tie a knot in the wire that connects the light bulb to the power supply,\n\n47\n00:03:02,688 --> 00:03:03,648\n灯仍然是亮的\nthe light remains lit up.\n\n48\n00:03:04,040 --> 00:03:04,768\n没什么影响\nIt doesn't care.\n\n49\n00:03:07,440 --> 00:03:12,400\n物理学上这样安排 可以使连接变成抽象的\nThat the way the physics is arranged is such that the connection can be made abstract,\n\n50\n00:03:13,088 --> 00:03:15,270\n至少在低频状态下是可以的\nat least for low frequencies and things like that.\n\n51\n00:03:17,840 --> 00:03:20,880\n而且这就是全部的关联方式了\nSo in fact, we have captured all of the connections there really are.\n\n52\n00:03:22,350 --> 00:03:23,872\n当然 我们来进一步\nWell, as you can go one step further\n\n53\n00:03:23,904 --> 00:03:27,310\n讨论一种在电气系统中最为广泛的抽象\nand talk about the most abstract types of electrical systems we have,\n\n54\n00:03:27,856 --> 00:03:29,420\n数字电路\ndigital to dual circuits.\n\n55\n00:03:31,696 --> 00:03:33,664\n这里有一些对象\nAnd here there are certain kinds of objects.\n\n56\n00:03:34,640 --> 00:03:40,128\n例如 在数字电路里中 我们有非门\nFor example, in digital circuits we have things like inverters.\n\n57\n00:03:41,392 --> 00:03:42,784\n有与门\nWe have things like and-gates.\n\n58\n00:03:43,990 --> 00:03:45,408\n还有或门\nWe have things like or-gates.\n\n59\n00:03:47,210 --> 00:03:50,128\n我们用一种特殊的“电线” 把它们连接起来\nWe connect them together by sort-of wires\n\n60\n00:03:52,000 --> 00:03:54,944\n这些“电线”代表抽象信号\nwhich represent abstract signals.\n\n61\n00:03:55,610 --> 00:03:57,184\n我们不关心具体的物理因素\nWe don't really care as physical variables\n\n62\n00:03:57,210 --> 00:03:59,728\n像电压、电流或者组合因素等\nwhether these are voltages or currents or some combination\n\n63\n00:04:00,016 --> 00:04:03,440\n又或者是水压 等等\nor water, water pressure.\n\n64\n00:04:05,200 --> 00:04:07,328\n这些抽象变量代表某类信号\nThese abstract variables represent certain signals.\n\n65\n00:04:09,420 --> 00:04:12,896\n我们用电路连接元件 构建系统\nAnd we build systems by wiring these things together with wires.\n\n66\n00:04:14,070 --> 00:04:16,224\n现在 我要向你们介绍一门新的语言\nSo today what I'm going to show you, right now,\n\n67\n00:04:17,632 --> 00:04:20,176\n我们要构建一门内嵌于Lisp中的语言\nwe're going to build up an invented language in Lisp,\n\n68\n00:04:22,144 --> 00:04:25,088\n这是一种内部DSL 是类似于之前讲过的图形语言那种\nembedded in the same sense that Henderson's picture language was embedded,\n\n69\n00:04:26,160 --> 00:04:27,328\n而不是昨天那种\nwhich is not the same sense\n\n70\n00:04:27,888 --> 00:04:31,610\n那种模式匹配语言 -- 那是外部DSL\nas the language of pattern match and substitution was done yesterday.\n\n71\n00:04:32,800 --> 00:04:36,300\n模式匹配语言是由Lisp程序所解释的\nThe pattern match substitution language was interpreted by a Lisp program.\n\n72\n00:04:38,160 --> 00:04:40,528\n而之前那种图形语言\nBut the embedding of Henderson's program\n\n73\n00:04:40,560 --> 00:04:44,270\n是在Lisp中构造我们想要的过程 来封装图形结构\nis that we just build up more and more procedures that encapsulate the structure we want.\n\n74\n00:04:45,480 --> 00:04:46,752\n举例来说\nSo for example here,\n\n75\n00:04:47,728 --> 00:04:50,640\n首先我要有一些基本对象\nI'm going to have some various primitive kinds of objects, as you see,\n\n76\n00:04:51,056 --> 00:04:52,128\n比如这个和这个\nthat one and that one.\n\n77\n00:04:53,504 --> 00:04:55,184\n然后用电线去组合它们\nI'm going to use wires to combine them.\n\n78\n00:04:55,984 --> 00:04:59,376\n我用(MAKE-WIRE)来构造一个电线\nThe way I represent attaching-- I can make wires.\n\n79\n00:04:59,870 --> 00:05:01,248\nA就代表了一根电线\nSo let's say A is a wire.\n\n80\n00:05:01,740 --> 00:05:02,690\nB也是\nAnd B is a wire.\n\n81\n00:05:02,690 --> 00:05:03,460\nC也是\nAnd C is a wire.\n\n82\n00:05:03,460 --> 00:05:04,230\nD也是\nAnd D is a wire.\n\n83\n00:05:04,230 --> 00:05:04,830\n还有E\nAnd E is wire.\n\n84\n00:05:04,830 --> 00:05:05,648\nS也是\nAnd S is a wire.\n\n85\n00:05:06,880 --> 00:05:12,752\n而或门有两个输入 分别是A和B\nWell, an or-gate that has both inputs, the inputs being A and B,\n\n86\n00:05:13,168 --> 00:05:14,752\n它的输出是D\nand the output being wire D,\n\n87\n00:05:15,072 --> 00:05:16,128\n我们用这样的记号来表示\nyou notate like this.\n\n88\n00:05:18,140 --> 00:05:22,144\n与门 输入是A和B 输出是C\nAn and-gate, which has inputs A and B and output C,\n\n89\n00:05:22,224 --> 00:05:23,240\n我们这样表示\nwe notate like that.\n\n90\n00:05:24,820 --> 00:05:28,464\n通过一系列像这样的声明\nBy making such a sequence of declarations,\n\n91\n00:05:29,296 --> 00:05:31,648\n我可以组合出任意的电路\nI can wire together an arbitrary circuit.\n\n92\n00:05:32,750 --> 00:05:34,640\n我已经告诉了你们创建数字电路\nSo I've just told you a set of primitives\n\n93\n00:05:35,312 --> 00:05:38,510\n的基本元素和组合方法了\nand means of combination for building digital circuits,\n\n94\n00:05:40,096 --> 00:05:43,040\n然后就该说抽象的方法了\nwhen I need more in a real language than abstraction.\n\n95\n00:05:43,690 --> 00:05:52,240\n举例来说 这是一个半加器\nAnd so for example, here I have--here I have a half adder.\n\n96\n00:05:52,672 --> 00:05:55,552\n如果你学过电路设计肯定知道这个东西\nIt's something you all know if you've done any digital design.\n\n97\n00:05:56,930 --> 00:06:00,448\n输入两个数A和B\nIt's used for adding numbers together on A and B\n\n98\n00:06:00,624 --> 00:06:02,120\n输出两者之和以及进位\nand putting out a sum and a carry.\n\n99\n00:06:04,352 --> 00:06:06,800\n事实上 完全可以用我刚刚说的来组合电路\nAnd in fact, the wiring diagram is exactly what I told you.\n\n100\n00:06:07,450 --> 00:06:10,992\n盒子外面 半加器盒子的外面有一些接口\nA half adder with things that come out of the box--\n\n101\n00:06:11,136 --> 00:06:14,112\n这些盒子的边界 我们总是抽象成盒子\nyou see the box, the boundary, the abstraction is always a box.\n\n102\n00:06:14,790 --> 00:06:19,700\n从盒子里引出A、B、S、C四根线\nAnd there are things that come out of it, A, B, S, and C.\n\n103\n00:06:19,700 --> 00:06:21,792\n这些是已经声明了的变量\nThose are the declared variables--\n\n104\n00:06:23,390 --> 00:06:26,256\n由LAMBDA表达式声明的几个变量\ndeclared variables of a lambda expression,\n\n105\n00:06:26,288 --> 00:06:28,010\n定义了这个半加器\nwhich is the one that defines half adder.\n\n106\n00:06:31,400 --> 00:06:35,968\n在盒子的内部 我构造了电线D和E\nAnd internal to that, I make up some more wires, D and E,\n\n107\n00:06:36,000 --> 00:06:37,440\n这是为了连接内部结构\nwhich I'm going to use for the interconnect--\n\n108\n00:06:37,744 --> 00:06:40,400\n这条是E 这条是D\nhere E is this one and D is this wire,\n\n109\n00:06:41,328 --> 00:06:43,504\n内部连接的线路并没有引出盒子之外\nthe interconnect that doesn't come through the walls of the box--\n\n110\n00:06:45,056 --> 00:06:46,832\n就像电路图那样连起来\nand wire things together as you just saw.\n\n111\n00:06:48,790 --> 00:06:50,896\n大家可以看得出来\nAnd the nice thing about this that I've just shown you\n\n112\n00:06:51,056 --> 00:06:53,024\n这个语言非常有层次性\nthis language is hierarchical in the right way.\n\n113\n00:06:53,856 --> 00:06:55,712\n如果一门语言没有层次性\nIf a language isn't hierarchical in the right way,\n\n114\n00:06:55,952 --> 00:06:59,968\n如果你不能把一个复合对象当成基本对象来使用\nif it turns out that a compound object doesn't look like a primitive,\n\n115\n00:07:00,384 --> 00:07:01,536\n这门语言肯定是有问题的\nthere's something wrong with the language--\n\n116\n00:07:02,592 --> 00:07:04,224\n至少我是这么认为的\nat least the way I feel about that.\n\n117\n00:07:06,410 --> 00:07:09,584\n之前 我们都是在研究数学函数\nSo here we have--here, instead of starting with mathematical functions,\n\n118\n00:07:09,600 --> 00:07:11,120\n或者是计算数学函数的东西\nor things that compute mathematical functions,\n\n119\n00:07:11,152 --> 00:07:12,650\n这些都是我们之前研究的东西\nwhich is what we've been doing up until now,\n\n120\n00:07:13,850 --> 00:07:16,656\n而我们现在\ninstead of starting with things that look like mathematical functions,\n\n121\n00:07:16,672 --> 00:07:17,630\n不这么做了\nor compute such things,\n\n122\n00:07:17,850 --> 00:07:20,880\n我们从一些电气对象开始\nwe are starting with things that are electrical objects\n\n123\n00:07:21,040 --> 00:07:22,640\n构建更多的对象\nand we build up more electrical objects.\n\n124\n00:07:23,350 --> 00:07:28,832\n我们用Lisp里的LAMBDA将其粘合起来\nAnd the glue we're using is basically the Lisp structure: lambdas.\n\n125\n00:07:30,384 --> 00:07:32,930\n“LAMBDA: 终极之粘合剂”\nLambda is the ultimate glue, if you will.\n\n126\n00:07:33,320 --> 00:07:36,352\n当然 半加器可以用于\nAnd of course, half adder itself can be used\n\n127\n00:07:37,648 --> 00:07:41,040\n构造一种更复杂的抽象结构 -- 全加器\nin a more complicated abstraction called a full adder,\n\n128\n00:07:41,600 --> 00:07:45,056\n如这里所示 全加器由两个半加器构成\nwhich in fact involves two half adders, as you see here,\n\n129\n00:07:45,470 --> 00:07:47,872\n用一些额外的电线连接起来\nhooked together with some extra wires,\n\n130\n00:07:48,080 --> 00:07:51,290\n就像这里所示的S、C1、C2以及一个或门\nthat you see here, S, C1, and C2, and an or-gate,\n\n131\n00:07:52,190 --> 00:07:53,600\n而对于一个全加器\nto manufacture a full adder,\n\n132\n00:07:53,872 --> 00:08:00,780\n它的输入有：两个待加的数 一个进位值\nwhich takes a input number, another input number, a carry in,\n\n133\n00:08:01,360 --> 00:08:04,176\n输出是：两数之和以及进位\nand produces output, a sum and a carry out.\n\n134\n00:08:05,900 --> 00:08:10,704\n构建好全加器以后 还可以把它们链起来组成更大的加法器\nAnd out of full adders, you can make real adder chains and big adders.\n\n135\n00:08:12,990 --> 00:08:14,832\n现在我们有了一门完整的语言\nSo we have here a language so far\n\n136\n00:08:16,064 --> 00:08:21,760\n它有基本元素、组合方法以及抽象方法\nThat has primitives, means of combination, and means of abstraction to real language.\n\n137\n00:08:22,270 --> 00:08:23,360\n现在 我们怎样实现这门语言？\nNow, how are we going to implement this?\n\n138\n00:08:25,000 --> 00:08:26,848\n其实并不难\nWell, let's do it easily.\n\n139\n00:08:27,070 --> 00:08:27,968\n首先来看基本元素\nLet's look at the primitives.\n\n140\n00:08:28,128 --> 00:08:30,112\n这是唯一的问题\nThe only problem is we have to implement the primitives.\n\n141\n00:08:31,160 --> 00:08:32,560\n不需要再做其它事情了\nNothing else has to be implemented,\n\n142\n00:08:33,744 --> 00:08:38,000\n因为我们直接借用了Lisp中的组合方法以及抽象方法\nbecause we're picking up the means of combination and abstraction from Lisp,\n\n143\n00:08:39,968 --> 00:08:41,888\n我们的语言 继承自Lisp并内嵌于其中\ninheriting them in the embedding.\n\n144\n00:08:43,776 --> 00:08:45,440\n好 我们先来看一个基本元素\nOK, so let's look at a particular primitive.\n\n145\n00:08:45,860 --> 00:08:47,400\n就拿非门来说吧\nAn inverter is a nice one.\n\n146\n00:08:51,540 --> 00:08:54,672\n非门有两个引脚 分别是输入和输出\nNow, inverter has two wires coming in, an in and an out.\n\n147\n00:08:57,312 --> 00:09:02,624\n它要对输入信号做出响应\nAnd somehow, it's going to have to know what to do when a signal comes in.\n\n148\n00:09:04,300 --> 00:09:07,008\n它需要对输入电线说 --\nSo somehow it's going to have to tell its input wire--\n\n149\n00:09:07,640 --> 00:09:10,144\n我们现在把它们视作对象\nand now we're going to talk about objects\n\n150\n00:09:10,448 --> 00:09:12,416\n其具体细节我们稍后讨论\nand we're going to see this in a little more detail soon--\n\n151\n00:09:13,230 --> 00:09:14,848\n它对其输入电线的说\nbut it's going to have to tell its input wire\n\n152\n00:09:15,824 --> 00:09:18,480\n“当你的值变发生改变时 告诉我一声”\nthat when you change, tell me.\n\n153\n00:09:20,120 --> 00:09:22,112\n所以非门这个对象\nSo this object, the object which is the inverter\n\n154\n00:09:22,416 --> 00:09:24,384\n会对输入电线这个对象说 --\nhas to tell the object which is the input wire,\n\n155\n00:09:25,136 --> 00:09:26,400\n“Hi 我是George”\nhi, my name is George.\n\n156\n00:09:26,870 --> 00:09:31,024\n“我的工作就是 对你的变化做出响应”\nAnd my, my job is to do something with results when you change.\n\n157\n00:09:31,720 --> 00:09:34,192\n“所以当你变化的时候 告诉我一声”\nSo when you change, you get a change, tell me about it.\n\n158\n00:09:34,730 --> 00:09:35,728\n“这样我才能进一步的处理”\nBecause I've got to do something with that.\n\n159\n00:09:36,880 --> 00:09:40,304\n这是通过在这里 在输入电线上\nWell, that's done down here by adding an action on the input wire called invert-in,\n\n160\n00:09:41,408 --> 00:09:44,640\n添加一个叫做INVERT-IN的动作来实现的\nWell, that's done down here by adding an action on the input wire called invert-in,\n\n161\n00:09:45,070 --> 00:09:46,944\nINVERT-IN在这里定义\nwhere invert-in is defined over here\n\n162\n00:09:47,056 --> 00:09:48,760\n它是一个无参过程\nto be a procedure of no arguments,\n\n163\n00:09:49,984 --> 00:09:54,592\n它将线路上的信号逻辑取反\nwhich gets the logical not of the signal on the input wire.\n\n164\n00:09:56,064 --> 00:09:58,640\n经过一段时长为INVERTER-DELAT的延时以后 --\nAnd after some delay, which is the inverter delay,\n\n165\n00:09:59,264 --> 00:10:01,152\n每个电路对象都有延时 --\nall these electrical objects have delays,\n\n166\n00:10:02,880 --> 00:10:04,460\n然后我们会 --\nwe'll do the following thing--\n\n167\n00:10:04,672 --> 00:10:07,140\n我们再把输出设置为新的值\nset the signal on the output wire to the new value.\n\n168\n00:10:10,160 --> 00:10:11,360\n非常简单\nA very simple program.\n\n169\n00:10:12,400 --> 00:10:15,280\n你可以想象输出电线也同样是信号敏感的\nNow, you have to imagine that the output wire has to be sensitive\n\n170\n00:10:15,770 --> 00:10:18,272\n当信号改变的时候\nand know that when its signal changes,\n\n171\n00:10:19,280 --> 00:10:21,150\n它会“告知”其它对象\nit may have to tell other guys,\n\n172\n00:10:21,792 --> 00:10:24,784\n“快醒醒！我的值已经改变啦”\nHi, wake up. My value has changed.\n\n173\n00:10:26,050 --> 00:10:30,144\n所以当你把非门和与门或者元件连在一起的时候\nSo when you hook together inverter with an and-gate or something like that,\n\n174\n00:10:30,464 --> 00:10:32,208\n它们之间将会有大量的通信\nthere has to be a lot of communication going on\n\n175\n00:10:32,864 --> 00:10:35,072\n以确保信号正确地传播\nto make sure that the signal propagates right.\n\n176\n00:10:36,810 --> 00:10:38,620\n到目前为止 没什么新奇的东西\nAnd down here is nothing very exciting.\n\n177\n00:10:38,620 --> 00:10:40,720\n我们只是针对某个特定的表示法\nThis is just the definition of logical not\n\n178\n00:10:40,720 --> 00:10:45,240\n也就是这个例子中的1、0 -- 实现了LOGICAL-NOT而已\nfor some particular representations of the logical values-- 1, 0 in this case.\n\n179\n00:10:46,736 --> 00:10:49,168\n与门就相对复杂一些\nAnd we can look at things more complicated like and-gates.\n\n180\n00:10:49,780 --> 00:10:55,808\n与门有两个输入A1和A2 输出是OUTPUT\nAnd-gates take two inputs, A1 and A2, we'll call them, and produce an output.\n\n181\n00:10:56,736 --> 00:11:00,640\n但是其结构和非门没有什么大的不同\nBut the structure of the and-gate is identical to the one we just saw.\n\n182\n00:11:00,860 --> 00:11:03,440\n只不过是 当输入信号改变的时候\nThere's one called an and-action procedure that's defined,\n\n183\n00:11:04,528 --> 00:11:09,070\n与门调用的是AND-ACTION过程罢了\nwhich is the thing that gets called when an input is changed.\n\n184\n00:11:10,910 --> 00:11:12,880\n当然 它所做的只是\nAnd what it does, of course, is nothing more than\n\n185\n00:11:12,912 --> 00:11:15,370\n对输入信号进行逻辑“与”运算\ncompute the logical and of the signals on the inputs.\n\n186\n00:11:16,192 --> 00:11:18,768\n在经过AND-GATE-DELAY的延时之后\nAnd after some delay, called the and-gate-delay,\n\n187\n00:11:20,464 --> 00:11:24,368\n调用这个过程 更新输出信号值\ncalls this procedure, which sets a signal on the output to a new value.\n\n188\n00:11:25,470 --> 00:11:28,350\n那么 我们如何用“按愿望思维”来构造这一切呢？\nNow, how I implement these things is all wishful thinking.\n\n189\n00:11:28,350 --> 00:11:31,088\n如大家所见 这里有一个赋值运算\nAs you see here, I have an assignment operation.\n\n190\n00:11:32,020 --> 00:11:32,784\n但并不是SET!\nIt's not set.\n\n191\n00:11:34,570 --> 00:11:36,784\n这是一个派生出来的运算\nIt's a derived assignment operation in the same way\n\n192\n00:11:36,784 --> 00:11:38,730\n就像可以从CAR和CDR派生出其它函数一样\nwe had functions that were derived from CAR and CDR.\n\n193\n00:11:40,800 --> 00:11:44,816\n因此 按照约定 我加上“!”（表示这个过程有副作用）\nSo I, by convention, label that with an exclamation point.\n\n194\n00:11:46,340 --> 00:11:49,184\n这里有个过程ADD-ACTION!\nAnd over here, you see there's an add-action!,\n\n195\n00:11:49,440 --> 00:11:54,672\n它用来提醒与门中的局部线路A1\nwhich is to inform the wire, called A1 locally in this and-gate,\n\n196\n00:11:55,632 --> 00:11:58,688\n当它改变的时候记得执行过程AND-ACTION-PROCEDURE\nto call the and-action-procedure when it gets changed,\n\n197\n00:11:59,584 --> 00:12:02,912\nA2也是一样\nand the wire A2 to call the and-action procedure when it gets changed.\n\n198\n00:12:06,310 --> 00:12:07,232\n非常简单\nAll very simple.\n\n199\n00:12:09,960 --> 00:12:12,096\n现在我们再来看看\nWell, let's talk a little bit about this communication\n\n200\n00:12:12,704 --> 00:12:16,120\n各部分间是如何通信的\nthat must occur between these various parts.\n\n201\n00:12:18,544 --> 00:12:19,664\n例如\nSuppose, for example,\n\n202\n00:12:23,120 --> 00:12:24,272\n有一个非常简单的电路\nI have a very simple circuit\n\n203\n00:12:24,272 --> 00:12:30,460\n它有一个与门 带有两个输入A、B\nwhich contains and-gate with wires a and b.\n\n204\n00:12:31,920 --> 00:12:38,000\n与门通过电线C跟非门相连\nAnd that connects through a wire called c to an inverter\n\n205\n00:12:39,728 --> 00:12:41,536\n非门的输出是D\nwhich has a wire output called d.\n\n206\n00:12:44,208 --> 00:12:47,344\n这就是物理世界\nWhat are the comput...--here's the physical world.\n\n207\n00:12:47,360 --> 00:12:49,024\n一个对物理世界的抽象\nIt's an abstraction of the physical world.\n\n208\n00:12:49,860 --> 00:12:53,408\n要不了几分钱就可以从Radio Shack买到这些元件\nNow I can buy these out of little pieces that you get at Radio Shack for a few cents.\n\n209\n00:12:54,880 --> 00:12:56,320\n那些元件的作用和画在这里的差不多\nAnd there are boxes that act like this,\n\n210\n00:12:57,168 --> 00:13:00,220\n元件上都标有类似于LS04的标签\nwhich have little numbers on them like LS04 or something.\n\n211\n00:13:01,530 --> 00:13:08,160\n现在来看其中的计算模型\nNow supposing I were to try to say what's the computational model.\n\n212\n00:13:09,010 --> 00:13:10,944\n它又对应着什么\nWhat is the thing that corresponds to that,\n\n213\n00:13:11,136 --> 00:13:14,096\n计算机中的对象对应着我们思维中的什么\nthat part of reality in the mind of us and in the computer?\n\n214\n00:13:15,850 --> 00:13:19,136\n我需要把现实世界中的每个对象与计算机中的对应起来\nWell, I have to assign for every object in the world an object in the computer,\n\n215\n00:13:19,792 --> 00:13:24,272\n把两个世界中对象之间的关系也对应起来\nand for every relationship in the world between them a relationship in the computer.\n\n216\n00:13:26,064 --> 00:13:26,800\n这是我的目标\nThat's my goal.\n\n217\n00:13:28,560 --> 00:13:29,456\n让我们来看看怎么做\nSo let's do that.\n\n218\n00:13:30,900 --> 00:13:34,208\n这一团东西代表信号A\nWell, I have some sort of thing called the signal, A.\n\n219\n00:13:35,712 --> 00:13:36,944\n这是信号A\nThis is A. It's a signal.\n\n220\n00:13:37,940 --> 00:13:39,328\n画得像一团云\nIt's a cloudy thing like that.\n\n221\n00:13:39,900 --> 00:13:42,800\n再画另一个信号 -- B\nAnd I have another one down here which I'm going to call B.\n\n222\n00:13:46,688 --> 00:13:47,470\n它是另一个信号\nIt's another signal.\n\n223\n00:13:49,140 --> 00:13:50,912\n这两个信号\nNow this signal--these two signals\n\n224\n00:13:51,104 --> 00:13:52,816\n要通过某种方式连在一起\nare somehow going to have to hook together\n\n225\n00:13:53,728 --> 00:13:58,752\n连在这个盒子上 -- 这就代表与门\ninto a box, let's call it this, which is the and-gate, action procedure.\n\n226\n00:14:00,320 --> 00:14:02,040\n这就是与门的动作过程\nThat's the and-gate's action procedure.\n\n227\n00:14:07,660 --> 00:14:08,592\n它将产生\nAnd it's going to produce\n\n228\n00:14:09,152 --> 00:14:13,296\n它将与另外一个称作C的信号对象交互\nwell, it's going to interact with a signal object, which we call C--\n\n229\n00:14:16,224 --> 00:14:18,880\n哦 说错了 是一条电线C\na wire object, excuse me, we call C.\n\n230\n00:14:20,590 --> 00:14:26,288\n这跟电线 又将连在另一个动作过程上\nthis is going to put out again, or connect to, another action procedure\n\n231\n00:14:26,288 --> 00:14:30,330\n在我们的电气世界中 这个过程跟一个非门关联\nwhich is one associated with the inverter in the world, not.\n\n232\n00:14:32,860 --> 00:14:40,656\n我还有另外一根电线 -- D\nAnd I'm going to have another--another wire, which we'll call D.\n\n233\n00:14:42,970 --> 00:14:45,296\n整体布局就是这样\nSo here's my layout of stuff.\n\n234\n00:14:46,000 --> 00:14:49,440\n现在必须来研究它们 有关计算的内部机制了\nNow we have to say what's inside them and what they have to know to compute.\n\n235\n00:14:51,500 --> 00:14:53,696\n每一跟电线都必须知道\nWell, every--every one of these wires has to know\n\n236\n00:14:53,696 --> 00:14:56,360\n自己承载的信号是什么\nwhat the value of the signal that's on that wire is.\n\n237\n00:14:57,340 --> 00:15:00,000\n我们用变量SIGNAL来表示\nSo there's going to be some variable inside here, we'll call it signal.\n\n238\n00:15:02,976 --> 00:15:04,048\nSIGNAL的值就是信号\nAnd he owns a value.\n\n239\n00:15:05,680 --> 00:15:07,744\n也不要忘了它所关联的环境\nSo there must be some environment associated with this.\n\n240\n00:15:08,896 --> 00:15:11,344\n对于每个元件来说 一定有一个环境绑定了信号\nAnd for each one of these, there must be an environment that binds signal.\n\n241\n00:15:15,400 --> 00:15:16,880\n因此 这里也有一个SIGNAL变量\nAnd there must be a signal here, therefore.\n\n242\n00:15:19,400 --> 00:15:21,920\nSIGNAL的值不是0就是1\nAnd presumably, signal's a value that's either 1 or 0,\n\n243\n00:15:22,816 --> 00:15:23,488\n这儿也有个SIGNAL\nand signal.\n\n244\n00:15:28,000 --> 00:15:30,560\n现在 一旦这里的信号改变\nNow, we also have to have some\n\n245\n00:15:31,264 --> 00:15:34,112\n我们需要通知一系列的对象\nlist of people to inform if the signal here changes.\n\n246\n00:15:36,660 --> 00:15:37,664\n我们得通知这个与门\nWe're going to have to inform this.\n\n247\n00:15:39,300 --> 00:15:43,968\n这里有个表 我们把它叫做AP\nSo I've got that list. We'll call it the Action Procedures, AP.\n\n248\n00:15:44,500 --> 00:15:45,600\n它可能是一个表\nAnd it's presumably a list.\n\n249\n00:15:46,448 --> 00:15:49,008\n在本例中 表里面的第一项条目是这个东西\nBut the first thing on the list, in this case, is this guy.\n\n250\n00:15:50,500 --> 00:15:54,810\n这个元件也有一个称为AP的表\nAnd the action procedures of this one happens to have some list of stuff.\n\n251\n00:15:54,810 --> 00:15:58,176\n也可能有一些其它对象 时刻等待着A来通知“它们”\nThere might be other people who are sharing A, who are looking at it.\n\n252\n00:15:59,020 --> 00:16:01,312\n所以这里可能有其它对象 比如\nSo there might be other guys on this list, like\n\n253\n00:16:01,728 --> 00:16:03,230\n一些其它我们不知道的对象\nlike somebody over there that we don't know about.\n\n254\n00:16:03,630 --> 00:16:04,880\n这些是与A连接的其它对象\nIt's the other guy attached to A.\n\n255\n00:16:07,200 --> 00:16:09,648\n这里的AP表\nAnd the action procedure here also has to point to that,\n\n256\n00:16:11,120 --> 00:16:12,400\n也指向这个与门\nthe list of action procedures.\n\n257\n00:16:13,070 --> 00:16:16,352\n相类似的 这里的AP表\nAnd of course, that means this one, its action procedures\n\n258\n00:16:16,784 --> 00:16:18,530\n也要指向这里\nhas to point up to here.\n\n259\n00:16:18,530 --> 00:16:20,896\n这里是C要通知的元件\nThis is the things-- the people it has to inform.\n\n260\n00:16:21,770 --> 00:16:23,184\nD也一样\nAnd this guy has some too.\n\n261\n00:16:24,280 --> 00:16:25,248\n但是我不知道它要通知谁\nBut I don't know what they are\n\n262\n00:16:25,264 --> 00:16:26,650\n因为我的图中没有画出来\nbecause I didn't draw it in my diagram.\n\n263\n00:16:27,190 --> 00:16:28,368\n可能是和D连接起来的其它元件\nIt's the things connected to D.\n\n264\n00:16:30,320 --> 00:16:32,624\n同样的\nNow, it's also the case\n\n265\n00:16:33,800 --> 00:16:36,960\n当AND-ACTION过程被唤醒时\nthat when the and-action procedure is awakened,\n\n266\n00:16:37,020 --> 00:16:41,312\n也就是说 之前你拜托某人将你唤醒\nsaying one of the people who know that you've told\n\n267\n00:16:41,450 --> 00:16:44,848\n你拜托它们 当它们的信号发生改变时通知你\none of the people you've told to wake you up if their signal changes,\n\n268\n00:16:46,970 --> 00:16:48,816\n你得去检查它的信号是什么\nyou have to go look and ask them what's their signal\n\n269\n00:16:49,328 --> 00:16:52,256\n这样你就可以计算逻辑与 输出信号给下一个元件\nso you can do the and, and produce a signal for this one.\n\n270\n00:16:57,090 --> 00:16:58,752\n所里 这里就必须要有\nSo there has to be, for example,\n\n271\n00:16:58,848 --> 00:17:03,000\n有信息说 A1是这个元件\ninformation here saying A1, my A1 is this guy,\n\n272\n00:17:03,900 --> 00:17:06,480\nA2就是这个元件\nmy A1 is this guy, and my A2 is this guy.\n\n273\n00:17:08,930 --> 00:17:09,984\n不只是这样\nAnd not only that,\n\n274\n00:17:11,790 --> 00:17:15,200\n当我在计算逻辑与时 我还得告诉这个元件一些信息\nwhen I do my and, I'm going to have to tell this guy something.\n\n275\n00:17:16,304 --> 00:17:21,056\n还有一个输出 输出给这个元件\nSo I need an output--  being this guy.\n\n276\n00:17:25,800 --> 00:17:30,032\n同样地 非门也有一个输入\nAnd similarly, this guy's going to have a thing called the input\n\n277\n00:17:32,380 --> 00:17:34,928\n当信号被唤醒并告知它信号被修改时\nthat he interrogates to find out\n\n278\n00:17:36,752 --> 00:17:38,640\n非门会询问该信号\nwhat the value of the signal on the input is,\n\n279\n00:17:38,640 --> 00:17:40,090\n你的值是什么\nwhen the signal wakes up and says, I've changed,\n\n280\n00:17:41,050 --> 00:17:43,472\n信号通过像这样发消息 告知“信号已改变”\nand sends a message this way saying, I've changed.\n\n281\n00:17:43,520 --> 00:17:45,536\n它就反过来查询这个新的信号值\nThis guy says, OK, what's your value now?\n\n282\n00:17:46,900 --> 00:17:50,128\n取到值之后 它将会\nWhen he gets that value, then he's going to have to say,\n\n283\n00:17:50,144 --> 00:17:55,860\n计算输出 并改变这个信号的值\nOK, output changes this guy, changes this guy.\n\n284\n00:18:00,600 --> 00:18:01,248\n以此类推\nAnd so on.\n\n285\n00:18:02,848 --> 00:18:04,560\n因此我也必须有这么多的连接\nAnd so I have to have at least that much connected-ness.\n\n286\n00:18:06,240 --> 00:18:09,232\n现在我们回头观察一下 这个与门\nNow, let's go back and look, for example, at the and-gate.\n\n287\n00:18:10,260 --> 00:18:12,096\n回到这张幻灯片\nHere we are back on this slide.\n\n288\n00:18:13,670 --> 00:18:15,040\n这几个部分的内容\nAnd we can see some of these parts.\n\n289\n00:18:16,040 --> 00:18:19,328\n对每个与门 都有A1、A2两个输入 一个OUTPUT输出\nFor any particular and-gate, there is an A1, there is an A2, and the output.\n\n290\n00:18:21,030 --> 00:18:23,536\n这些都是\nAnd those are, those are\n\n291\n00:18:25,088 --> 00:18:28,160\n在AND-GATE被调用时的环境中\nan environment that was created at the--those produce a frame\n\n292\n00:18:28,416 --> 00:18:31,248\n这些参数创建了一个框架\nat the time and-gate was called,\n\n293\n00:18:33,310 --> 00:18:35,904\n这个框架用来存放A1、A2和OUTPUT的值\nA frame where A1, A2, and output are--\n\n294\n00:18:36,672 --> 00:18:39,200\n它们都要与电线相绑定\nhave as their values, they're bound to\n\n295\n00:18:39,600 --> 00:18:44,256\n这些电线就是通过参数传进来的\nthe wires which, they are--which were passed in.\n\n296\n00:18:46,240 --> 00:18:47,312\n在这个环境下\nIn that environment,\n\n297\n00:18:47,744 --> 00:18:49,856\n我构建一个过程\nI constructed a procedure\n\n298\n00:18:50,976 --> 00:18:53,680\n就在这里\nthis one right there.\n\n299\n00:18:54,590 --> 00:18:57,312\n在该环境下定义的AND-ACTION-PROCEDURE\nAnd-action-procedure was constructed in that environment.\n\n300\n00:18:58,352 --> 00:19:00,704\n这个实际上是对一个LAMBDA表达式求值\nThat was the result of evaluating a lambda expression.\n\n301\n00:19:01,620 --> 00:19:05,488\n它跟求值该LAMBDA表达式时的环境相绑定\nSo it hangs onto the frame where these were defined.\n\n302\n00:19:07,168 --> 00:19:09,344\n找到它的局部环境\nLocal--part of its local state is that.\n\n303\n00:19:11,700 --> 00:19:13,472\n因此AND-ACTION-PROCEDURE过程能够\nThe and-action-procedure, therefore, has\n\n304\n00:19:13,648 --> 00:19:16,940\n存取这里看到的A1、A2和OUTPUT\naccess to A1, A2, and output as we see here.\n\n305\n00:19:17,310 --> 00:19:19,645\nA1、A2、OUTPUT\nA1, A2, and output.\n\n306\n00:19:22,360 --> 00:19:23,952\n我们还没有深入探索“电线”的内部结构\nNow, we haven't looked inside of a wire yet.\n\n307\n00:19:26,030 --> 00:19:26,992\n那是仅剩的部分\nThat's all that remains.\n\n308\n00:19:29,030 --> 00:19:29,920\n来看看“电线”\nLet's look at a wire.\n\n309\n00:19:33,520 --> 00:19:36,256\n麻烦请开一下投影仪\nLike the overhead, very good.\n\n310\n00:19:39,500 --> 00:19:42,560\n“电线”是有那么一点复杂\nWell, the wire, again, is a, is a somewhat complicated mess.\n\n311\n00:19:43,090 --> 00:19:44,640\n哦 摁错了\nOoh, wrong one.\n\n312\n00:19:47,056 --> 00:19:48,752\n是非常复杂 像这样\nIt's a big complicated mess, like that.\n\n313\n00:19:50,064 --> 00:19:53,104\n但是还是来看一下 到底是什么\nBut let's look at it in detail and see what's going on.\n\n314\n00:19:54,720 --> 00:19:56,672\n“电线”是这样的一种东西\nWell, the wire is one of these.\n\n315\n00:19:57,760 --> 00:20:03,520\n有两个主要部分 都是它的状态\nAnd it has to have two things that are part of it, that it's state.\n\n316\n00:20:05,010 --> 00:20:07,390\n我们这里看到的 一个是信号值\nOne of them is the signal we see here.\n\n317\n00:20:07,456 --> 00:20:10,064\n这里 当我们调用MAKE-WIRE创建一条电线时\nHeres, when we call make-wire to make a wire,\n\n318\n00:20:10,464 --> 00:20:13,024\n我们首先要创建一些变量\nthen the first thing we do is we create some variables\n\n319\n00:20:14,944 --> 00:20:16,080\n分别是这条电线的\nwhich are the signal\n\n320\n00:20:17,104 --> 00:20:19,296\nSIGNAL和ACTION-PROCS\nand the action procedures for this wire.\n\n321\n00:20:22,320 --> 00:20:23,440\n在这个上下文中\nAnd in that context,\n\n322\n00:20:23,760 --> 00:20:27,040\n我们定义了一系列的过程\nwe define various functions--or procedures, excuse me, procedures.\n\n323\n00:20:27,840 --> 00:20:31,152\n其中一个是(SET-MY-SIGNAL! NEW)\nOne of them is called set-my-signal to a new value.\n\n324\n00:20:32,850 --> 00:20:37,424\n它所做的只是 取一个新值NEW\nAnd what that does is takes a new value in.\n\n325\n00:20:37,930 --> 00:20:40,360\n如果NEW和SIGNAL一样 信号没有变化 就没必要做什么了\nIf that's equal to my current value of my signal, I'm done.\n\n326\n00:20:40,360 --> 00:20:42,624\n否则 把SIGNAL的值赋值为NEW\nOtherwise, I set the signal to the new value\n\n327\n00:20:42,752 --> 00:20:44,608\n再调用ACTION-PROCS里的所有过程\nand call each of the action procedures\n\n328\n00:20:46,528 --> 00:20:52,512\n那些我之前引入的过程\nthat I've been, that I've been--what's the right word? --  introduced to.\n\n329\n00:20:54,630 --> 00:21:01,530\n也就是我在定义与门时就定义的过程\nI get introduced when the and-gate was applied to me.\n\n330\n00:21:04,130 --> 00:21:05,600\n是在代码最后调用ADD-ACTION-PROCEDURE实现的\nBy add action procedure at the bottom.\n\n331\n00:21:07,410 --> 00:21:10,800\n然后 我还得定义一个过程 用来接受动作\nAlso, I have to define a way of accepting an action procedure--\n\n332\n00:21:10,816 --> 00:21:11,820\n也就是这段代码\nwhich is what you see here---\n\n333\n00:21:12,800 --> 00:21:15,136\n它增加了AP表\nwhich increments my action procedures\n\n334\n00:21:15,568 --> 00:21:21,630\n这是通过使用SET!将PROC与旧的AP表CONS起来实现的\nusing set to the result of CONSing up a new process--a procedure,\n\n335\n00:21:21,792 --> 00:21:24,256\n而这个PROC是作为参数传递进来的\nwhich is passed to me, on to my actions procedures list.\n\n336\n00:21:25,408 --> 00:21:27,584\n由于技术原因 最后还要再运行一次PROC\nAnd for technical reasons, I have to call that procedure one.\n\n337\n00:21:27,780 --> 00:21:29,200\n我不会再对此详细展开\nSo I'm not going to tell you anything about that,\n\n338\n00:21:29,392 --> 00:21:33,152\n这是一种事件驱动的模拟\nthat has to do with event-driven simulations and getting them started,\n\n339\n00:21:34,592 --> 00:21:36,000\n要想把这个讲清楚还是得花点时间\nwhich takes a little bit of thinking.\n\n340\n00:21:36,950 --> 00:21:39,408\n最后 我还要定义一个“分派器”\nAnd finally, I'm going to define a thing called the dispatcher,\n\n341\n00:21:39,968 --> 00:21:43,584\n这是一种将消息分派给电线的方法\nwhich is a way of passing a message to a wire,\n\n342\n00:21:45,376 --> 00:21:48,656\n它将用于从中抽取出不同的信息\nwhich is going to be used to extract from it various information,\n\n343\n00:21:49,072 --> 00:21:51,488\n比如这里 当前的信号值是多少？\nlike what is the current signal value?\n\n344\n00:21:53,820 --> 00:21:55,664\n设置新信号值的方法是什么？\nWhat is the method of setting your signal?\n\n345\n00:21:57,180 --> 00:21:58,288\n我想要这个方法\nI want to get that out of it.\n\n346\n00:22:00,100 --> 00:22:02,600\n我怎么样去添加另外的动作过程呢？\nHow do I--how do I add another action procedure?\n\n347\n00:22:05,510 --> 00:22:09,360\n最后 以DISPATCH过程为返回值返回\nAnd I'm going to return that dispatch, that procedure as a value.\n\n348\n00:22:09,940 --> 00:22:11,872\n因此 我所构造的电线\nSo the wire that I've constructed\n\n349\n00:22:12,000 --> 00:22:13,552\n是一种可以接收消息的对象\nis a message accepting object\n\n350\n00:22:14,256 --> 00:22:16,016\n它接收的消息类似于\nwhich accepts a message like, like\n\n351\n00:22:16,448 --> 00:22:18,368\n“你的哪个方法可以用来添加动作过程？”\nwhat's your method of adding action procedures?\n\n352\n00:22:19,920 --> 00:22:21,008\n它返回一个过程\nThat it'll give me a procedure,\n\n353\n00:22:21,640 --> 00:22:23,056\n它返回ADD-ACTION-PROCUDURE\nwhich is the add action procedure,\n\n354\n00:22:23,072 --> 00:22:26,540\n我可以将其应用在一个动作过程上\nwhich I can then apply to an action procedure\n\n355\n00:22:27,056 --> 00:22:29,010\n从而实现将一个动作过程加入电线的AP表中\nto create another action procedure in the wire.\n\n356\n00:22:31,620 --> 00:22:32,820\n这是一种“许可”\nSo that's a permission.\n\n357\n00:22:33,200 --> 00:22:36,080\n使得你可以去修改自身的AP表\nSo it's given me permission to change your action procedures.\n\n358\n00:22:37,824 --> 00:22:40,160\n实际上 你可以在这里看到\nAnd in fact, you can see that over here.\n\n359\n00:22:41,710 --> 00:22:42,320\n下一张幻灯片\nNext slide.\n\n360\n00:22:43,536 --> 00:22:43,824\n噢\nAh.\n\n361\n00:22:47,760 --> 00:22:49,120\n没什么有意思的\nThis is nothing very interesting.\n\n362\n00:22:49,120 --> 00:22:50,656\nCALL-EACH调用每个动作过程\nThe call each of the action procedures\n\n363\n00:22:50,896 --> 00:22:52,576\n这只是对一个表不断做CDR\nis just a CDRing down a list.\n\n364\n00:22:52,736 --> 00:22:54,608\n没什么好说的\nAnd I'm not going to even talk about that anymore.\n\n365\n00:22:54,990 --> 00:22:56,256\n我们早就知道了\nWe're too advanced for that.\n\n366\n00:22:57,560 --> 00:23:00,672\n然而 如果我想知道线路上的信号值\nHowever, if I want to get a signal from a wire,\n\n367\n00:23:01,024 --> 00:23:02,544\n我询问该线路：你的 --\nI ask the wire-- which is,\n\n368\n00:23:02,544 --> 00:23:03,090\n回想一下 什么是线路？\nwhat is the wire?\n\n369\n00:23:03,090 --> 00:23:05,408\n线路对象只是在创建它时所返回的分派过程而已\nThe wire is the dispatch returned by creating the wire.\n\n370\n00:23:05,860 --> 00:23:06,480\n只是一个过程\nIt's a procedure.\n\n371\n00:23:06,830 --> 00:23:12,272\n我向该分派器发送一个消息'GET-SIGNAL\nI call that dispatch on the message get-signal.\n\n372\n00:23:12,912 --> 00:23:15,408\n实际得到的是一个方法 用于取得线路信号值\nAnd what I should expect to get is a method of getting a signal.\n\n373\n00:23:16,900 --> 00:23:17,968\n进一步 我就可以得到信号值\nOr actually, I get the signal.\n\n374\n00:23:19,220 --> 00:23:20,528\n如果我想要设置一个信号值\nIf I want to set a signal,\n\n375\n00:23:22,656 --> 00:23:23,968\n我想要改变一个信号值\nI want to change a signal,\n\n376\n00:23:24,512 --> 00:23:26,768\n我要做的是\nthen what I'm going to do\n\n377\n00:23:26,928 --> 00:23:29,696\n以一个线路和信号的新值作为参数\nis take a wire as an argument and a new value for the signal,\n\n378\n00:23:30,016 --> 00:23:32,432\n我向线路请求许可 来设置它的信号值\nI would ask the wire for permission to set the signal\n\n379\n00:23:32,848 --> 00:23:37,616\n我会用该许可 -- 也就是一个过程 -- 应用在一个新值上\nand use that permission, which is a procedure, on the new value.\n\n380\n00:23:38,700 --> 00:23:40,512\n我们再过来看投影\nAnd if we go back to the overhead here,\n\n381\n00:23:41,648 --> 00:23:43,248\n好的 谢谢\nOkay, thank you,\n\n382\n00:23:44,208 --> 00:23:45,632\n我们看这里的投影\nwe go back to the overhead here,\n\n383\n00:23:45,920 --> 00:23:48,752\n我们看到 如果我请求设置信号的方法\nwe see that the method-- if I ask for the method of setting the signal,\n\n384\n00:23:49,344 --> 00:23:50,448\n也就是这段代码\nthat's over here,\n\n385\n00:23:52,256 --> 00:23:55,696\n返回的是一个定义在线路内部的SET-MY-SIGNAL!方法\nit's set-my-signal, a procedure that's defined inside the wire,\n\n386\n00:23:56,256 --> 00:23:57,696\n回过头来看它的定义\nwhich if we look over here\n\n387\n00:23:58,720 --> 00:23:59,744\n它的定义是\nis the thing that says\n\n388\n00:24:00,432 --> 00:24:02,688\n将我的一个内部变量SIGNAL的值设为\nset my internal value called the signal,\n\n389\n00:24:02,736 --> 00:24:05,504\n这个内部变量 用于存储信号值\nmy internal variable, which is the signal,\n\n390\n00:24:07,616 --> 00:24:10,030\n将其值设为通过参数传递的NEW\nto the new value, which is passed to me as an argument,\n\n391\n00:24:10,784 --> 00:24:13,010\n然后调用AP表中的过程 来唤醒它们\nand then call each of the action procedures waking them up.\n\n392\n00:24:16,340 --> 00:24:16,992\n非常简单\nVery simple.\n\n393\n00:24:19,248 --> 00:24:20,768\n回头来看刚才的幻灯片\nOk, Going back to that slide,\n\n394\n00:24:22,480 --> 00:24:24,320\n还有最后一点\nwe also have the one last thing--\n\n395\n00:24:24,368 --> 00:24:27,310\n我想你们现在应该很轻易地就能理解了\nwhich I suppose now you can easily work out for yourself--\n\n396\n00:24:27,776 --> 00:24:29,152\n关于我们如何添加新的动作过程\nis the way you add an action.\n\n397\n00:24:30,100 --> 00:24:35,184\n我们需要WIRE和ACTION-PROC两个参数\nYou take a wire--a wire and an action procedure.\n\n398\n00:24:36,470 --> 00:24:39,312\n然后请求添加动作过程的许可\nAnd I ask the wire for permission to add an action.\n\n399\n00:24:40,050 --> 00:24:44,224\n得到许可后 用该许可去添加新的动作过程\nGetting that permission, I use that permission to give it an action procedure.\n\n400\n00:24:45,840 --> 00:24:47,088\n所以 这确实是一个“对象”\nSo that's a real object.\n\n401\n00:24:48,570 --> 00:24:50,320\n还有些细节\nThere's a few more details about this.\n\n402\n00:24:52,460 --> 00:24:58,390\n比如 我怎么来控制它？\nFor example, how am I going to control this thing?\n\n403\n00:24:58,390 --> 00:24:59,696\n这些延时怎么实现？\nHow do I do these delays?\n\n404\n00:25:00,992 --> 00:25:02,540\n我们来快速过一遍\nOkay? Let's look at that for a second.\n\n405\n00:25:05,504 --> 00:25:07,984\n下一张\nThe next one here.\n\n406\n00:25:08,360 --> 00:25:08,880\n我们来看看\nLet's see.\n\n407\n00:25:09,570 --> 00:25:14,176\n我们细看与门、或门的定义\nWe know when we looked at the and-gate or the not-gate\n\n408\n00:25:15,312 --> 00:25:17,008\n会发现当输入信号改变时\nthat when a signal changed on the input,\n\n409\n00:25:17,248 --> 00:25:18,192\n会有“延时”\nthere was a delay.\n\n410\n00:25:18,770 --> 00:25:21,248\n然后它将调用过程\nAnd then it was going to call the procedure,\n\n411\n00:25:21,632 --> 00:25:23,008\n来改变输出\nwhich was going to change the output.\n\n412\n00:25:26,040 --> 00:25:27,920\n这个要如何实现？\nWell, how are we going to do this?\n\n413\n00:25:28,120 --> 00:25:29,920\n我们将要建立一种机制\nWe're going to make up some mechanism,\n\n414\n00:25:30,304 --> 00:25:32,000\n一种相当复杂的机制\na fairly complicated mechanism at that,\n\n415\n00:25:32,336 --> 00:25:33,760\n我们得非常细心地来看\nwhich we're going to have to be very careful about.\n\n416\n00:25:34,720 --> 00:25:37,232\n一段延时之后 我们将执行一个动作\nBut after a delay, we're going to do an action.\n\n417\n00:25:37,390 --> 00:25:38,128\nDELAY是一个数\nA delay is a number,\n\n418\n00:25:38,160 --> 00:25:39,230\n而ACTION是一个过程\nand an action is a procedure.\n\n419\n00:25:40,590 --> 00:25:43,728\n我们引入一种称为THE-AGENDA的特殊数据结构\nWhat that's going to be is they're going to have a special structure called an agenda,\n\n420\n00:25:45,504 --> 00:25:48,800\n用于组织时间与动作\nwhich is a thing that organizes time and actions.\n\n421\n00:25:49,510 --> 00:25:50,880\n一会儿再来仔细研究\nAnd we're going to see that in a while.\n\n422\n00:25:50,880 --> 00:25:52,544\n先把这里说完\nI don't want to get into that right now.\n\n423\n00:25:53,070 --> 00:25:58,288\nTHE-AGENDA将记录执行动作的时刻\nBut the agenda has a moment at which--at which something happens.\n\n424\n00:25:59,130 --> 00:26:02,464\n我们把它设定在未来的某个时刻\nWe're setting up for later at some moment,\n\n425\n00:26:02,510 --> 00:26:05,680\n也就是在CURRENT-TIME加上DELAT的时刻\nwhich is the sum of the time, which is the delay time plus the current time,\n\n426\n00:26:05,696 --> 00:26:07,130\n触发关联的动作\nwhich the agenda thinks is now.\n\n427\n00:26:09,024 --> 00:26:10,560\n我们把准备好要执行的动作\nWe're going to set up to do this action,\n\n428\n00:26:11,024 --> 00:26:12,400\n添加入THE-AGENDA中\nand add that to the agenda.\n\n429\n00:26:15,280 --> 00:26:18,032\n要使这个“机器”运行起来并不困难\nAnd the way this machine will now run is very simple.\n\n430\n00:26:18,660 --> 00:26:21,488\n我们利用这个PROPAGATE过程来完成这件事\nWe have a thing called propagate, which is the way things run.\n\n431\n00:26:22,710 --> 00:26:25,952\n如果THE-AGENDA为空 就没有要做的\nIf the agenda is empty, we're done--if there's nothing more to be done.\n\n432\n00:26:27,440 --> 00:26:28,160\n否则\nOtherwise,\n\n433\n00:26:29,760 --> 00:26:31,536\n我们就取出THE-AGENDA的第一个元素\nwe're going to take the first item off the agenda,\n\n434\n00:26:31,712 --> 00:26:33,340\n它是一个无参过程\nand that's a procedure of no arguments.\n\n435\n00:26:34,200 --> 00:26:36,030\n所以这里有额外的括号\nSo that we're going to see extra parentheses here.\n\n436\n00:26:36,030 --> 00:26:37,856\n我们对其进行无参调用\nWe call that on no arguments.\n\n437\n00:26:39,190 --> 00:26:40,176\n这就执行了之前存入的动作\nThat takes the action.\n\n438\n00:26:42,200 --> 00:26:44,176\n然后我们从THE-AGENDA中删除第一个元素\nThen we remove that first item from the agenda,\n\n439\n00:26:44,592 --> 00:26:46,144\n然后再进入传播循环\nand we go around the propagation loop.\n\n440\n00:26:48,912 --> 00:26:50,750\n这就是整体的结构\nSo that's the overall structure of this thing.\n\n441\n00:26:53,380 --> 00:26:55,936\n还有点其它的\nNow, there's a, a few other things we can look at.\n\n442\n00:26:57,430 --> 00:27:00,016\n现在 我们来看看THE-AGENDA的内部结构\nAnd then we're going to look into the agenda a little while from now.\n\n443\n00:27:00,576 --> 00:27:01,552\n请看投影仪\nNow the overhead again.\n\n444\n00:27:02,800 --> 00:27:04,672\n该如何使用这个玩意儿呢？\nWell, in order to set this thing going,\n\n445\n00:27:04,672 --> 00:27:07,410\n我需要给你们说明下这个模拟器的用法\nI just want to show you some behavior out of this simulator.\n\n446\n00:27:07,856 --> 00:27:09,936\n你们可能觉得这个模拟器太简陋了\nBy the way, you may think this simulator is very simple,\n\n447\n00:27:10,400 --> 00:27:12,016\n甚至你们认为它根本没什么用\nand probably too simple to be useful.\n\n448\n00:27:12,576 --> 00:27:13,760\n而实际上是\nThe fact of the matter is\n\n449\n00:27:13,984 --> 00:27:15,392\n这样的模拟器曾被用于\nthat this simulator has been used\n\n450\n00:27:15,728 --> 00:27:17,440\n操纵相当大型的计算机\nto manufacture a fairly large computer.\n\n451\n00:27:18,680 --> 00:27:20,640\n那是一个真实的事例\nSo this is a real live example.\n\n452\n00:27:22,360 --> 00:27:24,064\n当然 并不完全是这里的这个模拟器\nActually, not exactly this simulator，\n\n453\n00:27:24,064 --> 00:27:25,392\n我会告诉你它们的区别\nbecause I'll tell you the difference.\n\n454\n00:27:25,840 --> 00:27:28,704\n区别就是 操纵大型机的模拟器有更多的基本元素\nThe difference is that there were many more different kinds of primitives.\n\n455\n00:27:29,820 --> 00:27:32,224\n不只是有非门 与门之类的\nThere's not just the word inverter or and-gate.\n\n456\n00:27:33,200 --> 00:27:35,728\n还有边缘触发器\nThere were things like edge-triggered,\n\n457\n00:27:36,256 --> 00:27:39,888\n翻转触发器 锁存器\nflip-flops, and latches\n\n458\n00:27:40,704 --> 00:27:44,520\n电平触发器 加法器等等之类的\ntransparent latches, and adders, and things like that.\n\n459\n00:27:45,170 --> 00:27:47,312\n困难之处在于\nAnd the difficulty with that\n\n460\n00:27:47,456 --> 00:27:50,864\n就在于需要很多页的文档\nis there's pages and pages of the definitions of all these primitives\n\n461\n00:27:51,200 --> 00:27:52,896\n来描述这些基本元素\nwith numbers like LS04.\n\n462\n00:27:54,690 --> 00:27:56,740\n同时它们还有很多的参数\nAnd then there's many more parameters for them.\n\n463\n00:27:56,740 --> 00:27:57,984\n不是只有一个延时这么简单\nIt's not just one delay.\n\n464\n00:27:58,480 --> 00:28:00,816\n还有建立时间 维持时间之类的\nThere's things like set up times and hold times and all that.\n\n465\n00:28:01,220 --> 00:28:03,408\n但是 如果不算上那部分的复杂度\nBut with the exception of that part of the complexity,\n\n466\n00:28:03,820 --> 00:28:08,208\n我们用来构建真实计算机的模拟器的结构\nthe structure of the simulator that we use for building a real computer,\n\n467\n00:28:09,088 --> 00:28:12,896\n跟你们在这里看到的的是一致的\nthat works is exactly what you're seeing here.\n\n468\n00:28:15,110 --> 00:28:19,270\n无论如何 这里都是一些简单的东西\nWell in any case, what we have here is a few simple things.\n\n469\n00:28:19,270 --> 00:28:22,592\n像这个 设置非门的延时时间 构建一个 AGENDA\nLike, there's inverter delays being set up and making a new agenda.\n\n470\n00:28:23,030 --> 00:28:25,520\n我们可以构建一些输入（线路）\nAnd then we can make some inputs.\n\n471\n00:28:26,032 --> 00:28:29,184\n这里的四条线路分别是：INPUT-1、INPUT-2、SUM和CARRY\nOk? There's input-1, input-2, a sum and a carry, which are wires.\n\n472\n00:28:29,460 --> 00:28:31,888\n我将要放置一种被称为“探针”的特殊对象\nI'm going to put a special kind of object called a probe\n\n473\n00:28:32,512 --> 00:28:34,640\n放在一些线路上\nonto, onto some of the wires,\n\n474\n00:28:34,976 --> 00:28:36,240\n放在SUM和CARRY上\nonto sum and onto carry.\n\n475\n00:28:37,230 --> 00:28:40,560\n探针是一种对象 它可以 --\nA probe is a, can object that has the property\n\n476\n00:28:40,704 --> 00:28:43,600\n当你改变它所附着线路的信号时\nthat when you change a wire it's attached to,\n\n477\n00:28:43,728 --> 00:28:44,832\n它会输出一条消息\nit types out a message.\n\n478\n00:28:46,120 --> 00:28:46,928\n这很容易实现\nIt's an easy thing to do.\n\n479\n00:28:48,448 --> 00:28:49,520\n一旦我们设置好它们\nAnd then once we have that,\n\n480\n00:28:49,552 --> 00:28:51,456\n当你在放置探针的时候\nof course, then when you put the probe on,\n\n481\n00:28:51,450 --> 00:28:52,416\n它首先会输出\nthe first thing it does, it says,\n\n482\n00:28:52,672 --> 00:28:56,016\nSUM在0时刻的值为0\nthe current value of the sum at time 0 is 0\n\n483\n00:28:57,296 --> 00:28:58,432\n这个我已经注意到了\nAnd because I just noticed it.\n\n484\n00:28:59,400 --> 00:29:04,752\nCARRY在0时刻的值也是0\nAnd the value of the carry at time 0, this is the time, is 0.\n\n485\n00:29:06,048 --> 00:29:09,280\n我们继续来构建更多结构\nAnd then we go off and we build some structure.\n\n486\n00:29:09,620 --> 00:29:12,288\n比如 可以像这里一样构建一种结构\nLike, we can build a structure here that says\n\n487\n00:29:14,064 --> 00:29:18,208\n用INPUT-1、INPUT-2、SUM和CARRY组成一个半加器\nyou have a half-adder on input-1, input-2, sum, and carry.\n\n488\n00:29:18,420 --> 00:29:20,420\n然后我们把INPUT-1上的信号变为1\nAnd we're going to set the signal on input-1 to 1.\n\n489\n00:29:20,624 --> 00:29:21,728\n然后开始传播\nWe do some propagation.\n\n490\n00:29:21,880 --> 00:29:22,848\n在时刻8的时候\nAt time 8,\n\n491\n00:29:23,904 --> 00:29:26,128\n如果你想的话 也可以单步跟踪传播过程\nwhich you could see going through this thing if you wanted to,\n\n492\n00:29:26,528 --> 00:29:29,200\nSUM的值变为1\nthe new value of sum became 1.\n\n493\n00:29:29,520 --> 00:29:30,448\n然后就结束了\nAnd the thing says I'm done.\n\n494\n00:29:31,168 --> 00:29:32,256\n好像没什么意思\nThat wasn't very interesting.\n\n495\n00:29:32,630 --> 00:29:33,904\n我们还可以设置信号\nBut we can send it some more signals.\n\n496\n00:29:34,064 --> 00:29:36,736\n把INPUT-2也变为1\nLike, we set-signal on input-2 to be one.\n\n497\n00:29:36,890 --> 00:29:38,096\n如果再进行传播\nAnd at that time if we propagate,\n\n498\n00:29:38,368 --> 00:29:39,952\n在时刻11\nthen it carried at 11,\n\n499\n00:29:40,128 --> 00:29:41,424\nCARRY变为1\nthe carry becomes 1,\n\n500\n00:29:41,552 --> 00:29:44,192\n在时刻16 SUM变为0\nand at 16, the sum's new value becomes 0.\n\n501\n00:29:45,392 --> 00:29:48,990\n如果你仔细研究那个电路图\nAnd you might want to work out that, if you like, about the digital circuitry.\n\n502\n00:29:48,990 --> 00:29:50,128\n它确实是这个结果\nIt's true, and it works.\n\n503\n00:29:50,620 --> 00:29:51,535\n也并没有什么特别的\nAnd it's not very interesting.\n\n504\n00:29:51,530 --> 00:29:54,128\n但是却清楚地表明了这一些都是如何运作的\nBut that's the kind of behavior we get out of this thing.\n\n505\n00:30:01,830 --> 00:30:03,296\n我现在给你们展示的是\nSo what I've shown you right now\n\n506\n00:30:03,488 --> 00:30:05,520\n一种宏观的图景\nis a large-scale picture,\n\n507\n00:30:06,600 --> 00:30:08,560\n你如何在一个很大的规模中\nhow you, at a bigger, big scale,\n\n508\n00:30:08,720 --> 00:30:12,040\n你何去实现某种事件驱动的模拟\nyou implement an event-driven simulation of some sort.\n\n509\n00:30:13,296 --> 00:30:14,560\n你应该如何去组织\nAnd how you might organize it\n\n510\n00:30:14,880 --> 00:30:16,704\n来获得良好的层次性结构\nto have nice hierarchical structure\n\n511\n00:30:16,992 --> 00:30:21,008\n使得你可以构建可具体化的抽象盒子\nallowing you to build abstract boxes that you can instantiate.\n\n512\n00:30:21,568 --> 00:30:24,960\n但我还没有告诉你AGENDA是如何运作的\nBut I haven't told you any of the details about how this agenda and things like that work.\n\n513\n00:30:25,780 --> 00:30:26,544\n下一小节再说\nThat we'll do next.\n\n514\n00:30:28,630 --> 00:30:32,944\n这将涉及到一些关于数据变化之类的事情\nAnd that's going to involve change and mutation of data and things like that.\n\n515\n00:30:34,310 --> 00:30:35,860\n在我继续之前 有什么问题吗？\nAre there any questions now, before I go on?\n\n516\n00:30:47,160 --> 00:30:48,240\n没有的话 那就休息一下\nThank you. Let's take a break.\n\n517\n00:30:50,240 --> 00:31:00,624\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n518\n00:31:00,620 --> 00:31:06,000\n《计算机程序的构造和解释》\n\n519\n00:31:11,230 --> 00:31:17,696\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n520\n00:31:17,760 --> 00:31:21,344\n《计算机程序的构造和解释》\n\n521\n00:31:21,340 --> 00:31:25,184\n计算对象\n\n522\n00:31:28,940 --> 00:31:35,060\n我们已经做了一个模拟器\nWell, we've been making a simulation.\n\n523\n00:31:35,392 --> 00:31:37,776\n这是一种事件驱动的模拟\nAnd the simulation is an event-driven simulation\n\n524\n00:31:38,176 --> 00:31:42,752\n其中 计算机中的对象与现实中的对象一一对应\nwhere the objects in the world are the objects in the computer.\n\n525\n00:31:43,920 --> 00:31:47,280\n现实世界中按时发生的状态改变\nAnd the changes of state that are happening in the world in time\n\n526\n00:31:47,984 --> 00:31:50,832\n被组织成了计算机中的时间\nare organized to be time in the computer,\n\n527\n00:31:52,992 --> 00:31:56,048\n如果现实中某件事后于另一件事发生\nso that if something happens after something else in the world,\n\n528\n00:31:56,460 --> 00:31:57,968\n那么在计算机中\nthen we have it happen after,\n\n529\n00:31:58,896 --> 00:32:02,256\n两个事件也保持同样的先后顺序发生\nafter the corresponding events happen in the same order in the computer.\n\n530\n00:32:04,420 --> 00:32:07,168\n排列这些时间 就是我们要用到赋值的地方\nThat's where we have assignments, when we make that alignment.\n\n531\n00:32:08,220 --> 00:32:11,216\n现在我要介绍一种方法来组织时间\nRight now I want to show you a way of organizing time,\n\n532\n00:32:11,808 --> 00:32:14,864\nAGENDA -- 或者有时候所谓的“优先队列”\nwhich is an agenda or priority queue, it's sometimes called.\n\n533\n00:32:16,040 --> 00:32:18,576\n我们首先需要认识到\nWe'll do some--we'll do a little bit of just understanding\n\n534\n00:32:18,624 --> 00:32:21,008\n为了创建AGENDA 我们需要些什么东西？\nwhat are the things we need to be able to do to make agendas.\n\n535\n00:32:28,330 --> 00:32:31,280\n首先我要在这里写下一些\nAnd so we're going to have--and so right now over here, I'm going to write down a bunch\n\n536\n00:32:31,392 --> 00:32:33,888\n用于操作AGENDA的基本运算\nof primitive operations for manipulating agendas.\n\n537\n00:32:35,960 --> 00:32:37,952\n我不会给出具体代码\nI'm not going to show you the code for them\n\n538\n00:32:38,144 --> 00:32:39,584\n因为它们都非常简单\nbecause they're all very simple,\n\n539\n00:32:40,320 --> 00:32:42,608\n而且你们手上也有\nIand you've got listings of all that anyway.\n\n540\n00:32:43,680 --> 00:32:44,380\n有哪些运算呢？\nSo what do we have?\n\n541\n00:32:44,380 --> 00:32:53,504\nMAKE-AGENDA可以新建一个AGENDA\nWe have things like make-agenda which produces a new agenda.\n\n542\n00:32:57,360 --> 00:33:01,770\nCURRENT-TIME可以获得一个AGENDA的当前时间\nWe can ask--we get the current-time of an agenda,\n\n543\n00:33:07,472 --> 00:33:12,800\n返回一个数 -- 也就是当前时间\nof an agenda, which gives me a number, a time.\n\n544\n00:33:16,990 --> 00:33:21,376\nEMPTY-AGENDA?可用于判断一个AGENDA是否为空\nWe can get--we can ask whether an agenda is empty, empty-agenda.\n\n545\n00:33:30,200 --> 00:33:32,570\n返回TRUE或FALSE\nAnd that produces either a true or a false.\n\n546\n00:33:42,720 --> 00:33:44,720\n我们也可以向AGENDA中添加对象\nWe can add an object to an agenda.\n\n547\n00:33:52,710 --> 00:33:56,064\n实际上 向AGENDA中添加的是一个运算 -- 或者说是需要完成的操作\nActually, what we add to an agenda is an operation--an action to be done.\n\n548\n00:33:56,910 --> 00:33:58,144\n它需要时间TIME\nAnd that takes a time,\n\n549\n00:33:59,632 --> 00:34:00,560\n待添加的动作ACTION\nthe action itself,\n\n550\n00:34:02,864 --> 00:34:04,640\n以及AGENDA本身\nand the agenda I want to add it to.\n\n551\n00:34:07,584 --> 00:34:10,256\n它把ACTION 放入AGENDA中合适的地方\nOK? That inserts it in the appropriate place in the agenda.\n\n552\n00:34:10,710 --> 00:34:12,736\nFIRST-ITEM用于从AGENDA取出第一个事项\nI can get the first item off an agenda,\n\n553\n00:34:14,240 --> 00:34:15,392\n那是我首先需要做的事情\nthe first thing I have to do,\n\n554\n00:34:21,840 --> 00:34:23,840\n该事项是一个动作\nwhich is going to give me an action.\n\n555\n00:34:26,464 --> 00:34:28,736\n我还可以把第一个事项从AGENDA中移除\nAnd I can remove the first item from an agenda.\n\n556\n00:34:29,540 --> 00:34:31,168\n这是操作AGENDA的一个必要运算\nThat's what I have to be able to do with agendas.\n\n557\n00:34:31,409 --> 00:34:33,020\n这个运算实现起来非常繁杂\nThat is a big complicated mess.\n\n558\n00:34:42,530 --> 00:34:43,360\n从AGENDA中移除\nFrom an agenda.\n\n559\n00:34:45,984 --> 00:34:49,856\n现在我们来看如何具体组织数据结构\nWell, let's see how we can organize this thing as a data structure a bit.\n\n560\n00:34:52,960 --> 00:34:56,048\nAGENDA应该是一种表\nWell, an agenda is going to be some kind of list.\n\n561\n00:34:58,432 --> 00:35:01,200\n一种可修改的表\nAnd it's going to be a list that I'm going to have to be able to modify.\n\n562\n00:35:01,570 --> 00:35:04,032\n因为我们要向其中添加元素\nSo we have to talk about modifying of lists,\n\n563\n00:35:05,808 --> 00:35:06,896\n删除元素等等\nbecause I'm going to add things to it,\n\n564\n00:35:07,776 --> 00:35:10,272\n所以我们需要一种可修改的表\nand delete things from it, and things like that.\n\n565\n00:35:11,070 --> 00:35:12,512\n它通过时间组织起来\nIt's organized by time.\n\n566\n00:35:13,820 --> 00:35:15,570\n让它有序 也许会有益处\nIt's probably good to keep it in sorted order.\n\n567\n00:35:18,330 --> 00:35:20,880\n但是也有可能同一时间会发生很多事\nBut sometimes there are lots of things that happen at the same time\n\n568\n00:35:22,048 --> 00:35:23,420\n或者说几乎同时\napproximate same time.\n\n569\n00:35:23,800 --> 00:35:24,720\n因此我们需要\nWhat I have to do is say,\n\n570\n00:35:24,912 --> 00:35:27,520\n把它们按发生时间为事件分组\ngroup things by the time at which they're supposed to happen.\n\n571\n00:35:29,040 --> 00:35:31,616\n所以我要把AGENDA组织成由SEGMENT构成的表\nSo I'm going to make an agenda as a list of segments.\n\n572\n00:35:32,780 --> 00:35:35,696\n我来画一下这个结构\nAnd so I'm going to draw you a data structure for an agenda,\n\n573\n00:35:36,688 --> 00:35:37,936\n方便理解\na perfectly reasonable one.\n\n574\n00:35:39,620 --> 00:35:40,496\n这是一个AGENDA\nHere's an agenda.\n\n575\n00:35:41,110 --> 00:35:42,870\n以一个名字开始\nIt's a thing that begins with a name.\n\n576\n00:35:47,856 --> 00:35:50,192\n我把它画在表结构的外部\nI'm going to do it right now out of list structure.\n\n577\n00:35:52,608 --> 00:35:53,392\n这是它的头部\nIt's got a header.\n\n578\n00:35:54,144 --> 00:35:55,440\n这个头部的存在也是很必要的\nThere's a reason for the header.\n\n579\n00:35:55,840 --> 00:35:57,630\n待会你就会知道\nWe're going to see the reason soon.\n\n580\n00:36:00,680 --> 00:36:03,408\n再画一个SEGMENT\nAnd it will have a segment. We will have--\n\n581\n00:36:03,968 --> 00:36:05,620\n这是一个由SEGMENT构成的表\nIt will have--it will be a list of segments.\n\n582\n00:36:08,310 --> 00:36:10,544\n假设这个AGENDA有两个SEGMENT\nSupposing this agenda has two segments,\n\n583\n00:36:11,584 --> 00:36:15,072\n不断对这个表取CAR即可得到\nOK, they're the car's-- successive car's of this list.\n\n584\n00:36:16,416 --> 00:36:20,576\n每个SEGMENT都有一个时间\nEach segment is going to have a time--\n\n585\n00:36:24,208 --> 00:36:26,640\n比如说这里是10\nsay for example, 10--\n\n586\n00:36:26,832 --> 00:36:30,512\n也就是说 这个SEGMENT里的事件发生在10时刻\nthat says that the things that happen in this segment are at time 10.\n\n587\n00:36:33,160 --> 00:36:36,528\n这里是另外一种数据结构\nAnd what I'm going to have in here is another data structure\n\n588\n00:36:36,560 --> 00:36:38,010\n我先不具体描述\nwhich I'm not going to describe,\n\n589\n00:36:38,496 --> 00:36:41,088\n它是一个队列 表示在10时刻要做的事\nwhich is a queue of things to do at time 10.\n\n590\n00:36:42,240 --> 00:36:43,330\n它是一个队列\nIt's a queue.\n\n591\n00:36:43,330 --> 00:36:44,704\n一会儿再细说\nAnd we'll talk about that in a second.\n\n592\n00:36:45,200 --> 00:36:50,352\n不过抽象地看 队列就是一系列在固定时间要做的事\nBut abstractly, the queue is just a list of things to do at a particular time.\n\n593\n00:36:50,400 --> 00:36:52,048\n我可以向其中添加其它要做的事\nAnd I can add things to a queue.\n\n594\n00:36:53,100 --> 00:36:53,808\n这是一个队列\nThis is a queue.\n\n595\n00:36:56,140 --> 00:36:59,115\n这个是时间 这个是SEGMENT\nThere's a time, there's a segment.\n\n596\n00:37:03,232 --> 00:37:06,368\n在这个AGENDA中 还有另一个SEGMENT\nNow, I may have another segment in this agenda.\n\n597\n00:37:08,940 --> 00:37:11,200\n假设它在30时刻发生\nSupposing this is stuff that happens at time 30.\n\n598\n00:37:13,500 --> 00:37:15,920\n类似地 它也有一个队列\nIt has, of course, another queue\n\n599\n00:37:16,928 --> 00:37:20,240\n里面是在30时刻要去做的事\nof things that are queued up to be done at time 30.\n\n600\n00:37:23,210 --> 00:37:25,664\n当然 我们的AGENDA还需要支持其它操作\nWell, there are various things I have to be able to do to an agenda.\n\n601\n00:37:27,090 --> 00:37:29,200\n假设我想将一个在10时刻发生的事\nSupposing I want to add to an agenda\n\n602\n00:37:29,472 --> 00:37:31,616\n添加到AGENDA中\nanother thing to be done at time 10.\n\n603\n00:37:33,030 --> 00:37:34,160\n这并不难\nWell, that's not very hard.\n\n604\n00:37:34,700 --> 00:37:38,656\n我遍历到这里 找到时刻是10的SEGMENT\nI'm going to walk down here, looking for the segment of time 10.\n\n605\n00:37:39,730 --> 00:37:42,144\n这样的SEGMENT也可能不存在\nIt is possible that there is no segment of time 10.\n\n606\n00:37:42,930 --> 00:37:44,560\n一会儿再考虑这种情况\nWe'll cover that case in a second.\n\n607\n00:37:45,420 --> 00:37:47,568\n如果我找到了时刻为10的SEGMENT\nBut if I find a segment of time 10,\n\n608\n00:37:47,872 --> 00:37:50,432\n如果我想要把一个事情放入其中\nthen if I want to add another thing to be done at time 10,\n\n609\n00:37:50,560 --> 00:37:52,160\n我只要增加该队列即可\nI just increase that queue--\n\n610\n00:37:53,856 --> 00:37:56,224\n这个说起来倒是很容易\n\"just increase\" isn't such an obvious idea.\n\n611\n00:37:56,576 --> 00:37:59,264\n我在这里添加需要在那时做的事\nBut I increase the things to be done at that time.\n\n612\n00:38:01,430 --> 00:38:04,256\n现在 假设我想在时刻20做点什么\nNow, supposing I want to add something to be done at time 20.\n\n613\n00:38:05,312 --> 00:38:07,904\n然而并没有时刻是20的SEGMENT\nThere is no segment for time 20.\n\n614\n00:38:08,992 --> 00:38:10,640\n我不得不构造一个新的SEGMENT\nI'm going to have to create a new segment.\n\n615\n00:38:11,340 --> 00:38:15,648\n我想把这个SEGMENT 放在10与30之间\nI want my time 20 segment to exist between time 10 and time 30.\n\n616\n00:38:17,610 --> 00:38:19,328\n这着实要花点功夫\nWell, that takes a little work.\n\n617\n00:38:20,170 --> 00:38:21,525\n先用CONS\nI'm going to have to do a CONS.\n\n618\n00:38:24,260 --> 00:38:29,940\n我要为这个AGENDA构建一个新的SEGMENT\nI'm going to have to make a new element of the agenda list--list of segments.\n\n619\n00:38:33,600 --> 00:38:34,816\n这里的连接必须要变\nI'm going to have to change.\n\n620\n00:38:35,400 --> 00:38:36,304\n就像这样\nHere's change.\n\n621\n00:38:37,540 --> 00:38:42,800\n我将要修改AGENDA的CDR部分的CDR部分\nI'm going to have to change the CDR of the CDR of the agenda\n\n622\n00:38:44,880 --> 00:38:49,456\n让它指向一个新的CONS单元\npoint that a new CONS of the new segment\n\n623\n00:38:50,112 --> 00:38:54,656\n由一个新的SEGMENT和AGENDA的CDDDDR部分所构成的单元\nand the CDR of the CDR of the CDR of the agenda, the CD-D-D-DR.\n\n624\n00:38:57,180 --> 00:39:01,888\n我们有一个发生在20时刻的新的SEGMENT\nAnd this is going to have a new segment now of time 20\n\n625\n00:39:02,304 --> 00:39:03,728\n它自己维护了一个队列\nwith its own queue,\n\n626\n00:39:04,848 --> 00:39:06,290\n这个队列中只有一个元素\nwhich now has one element in it.\n\n627\n00:39:10,730 --> 00:39:12,528\n如果我想在后面添加点什么\nIf I wanted to add something at the end,\n\n628\n00:39:12,544 --> 00:39:15,870\n我就需要替换这个东西的CDR部分\nI'm going to have to replace the CDR of this,\n\n629\n00:39:16,992 --> 00:39:19,216\n替换掉这个表的CDR部分\nof this list with something.\n\n630\n00:39:20,592 --> 00:39:23,312\n我们就对该数据结构进行修改\nWe're have to change that piece of data structure.\n\n631\n00:39:24,040 --> 00:39:25,792\n因此我需要新的基本运算\nSo I'm going to need new primitives for doing this.\n\n632\n00:39:27,210 --> 00:39:28,624\n因为原有的基础运算达不到这一点\nBut I'm just showing you why I need them.\n\n633\n00:39:29,440 --> 00:39:33,888\n如果我想在5时刻做点什么事\nAnd finally, if I wanted to add a thing to be done at time 5,\n\n634\n00:39:37,120 --> 00:39:39,200\n我就得去修改这个东西\nI'm going to have to change this one,\n\n635\n00:39:40,816 --> 00:39:42,128\n因为我得添加到这里\nbecause I'm going to have to add it in over here,\n\n636\n00:39:43,290 --> 00:39:46,224\n这也就是我预留了一个“头”序对的原因\nwhich is why I planned ahead and had a header cell,\n\n637\n00:39:47,568 --> 00:39:48,592\n它预留了空间\nwhich has a place.\n\n638\n00:39:49,400 --> 00:39:52,112\n我需要有空间去做改变\nIf I'm going to change things, I have to have places for the change.\n\n639\n00:39:53,888 --> 00:39:56,560\n需要有存储空间 去改变\nI have to have a place to make the change.\n\n640\n00:39:58,600 --> 00:40:02,540\n从AGENDA中删除东西并不困难\nIf I remove things from the agenda, that's not so hard.\n\n641\n00:40:02,540 --> 00:40:04,624\n移除第一个元素相当容易\nRemoving them from the beginning is pretty easy,\n\n642\n00:40:04,928 --> 00:40:06,144\n这也是我需要考虑的唯一情况\nwhich is the only case I have.\n\n643\n00:40:06,496 --> 00:40:10,192\n我可以先找到第一个SEGMENT\nI can go looking for the first, the first segment.\n\n644\n00:40:11,220 --> 00:40:14,000\n先判断它的队列是否为空\nI see if it has a non-empty queue.\n\n645\n00:40:14,810 --> 00:40:16,176\n如果队列不是空的\nIf it has a non-empty queue,\n\n646\n00:40:16,320 --> 00:40:18,624\n那么 我就会把元素从中删除\nwell, I'm going to delete one element from the queue\n\n647\n00:40:19,216 --> 00:40:19,744\n像这样\nlike that.\n\n648\n00:40:20,100 --> 00:40:21,920\n如果这时队列变为空的\nIf the queue ever becomes empty,\n\n649\n00:40:22,640 --> 00:40:24,220\n就还要继续把SEGMENT删掉\nthen I have to delete the whole segment.\n\n650\n00:40:24,220 --> 00:40:26,496\n然后 让这个单元指向这里\nAnd then this, this changes to point to here.\n\n651\n00:40:28,220 --> 00:40:31,088\n这个数据结构操作起来很复杂\nSo it's quite a complicated data structure manipulation going on,\n\n652\n00:40:32,256 --> 00:40:35,376\n它的具体实现也不是很有趣\nthe details of which are not really very exciting.\n\n653\n00:40:36,440 --> 00:40:38,480\n现在我们来探讨一下队列\nNow, let's talk about queues.\n\n654\n00:40:38,920 --> 00:40:39,760\n它们很相似\nThey're similar.\n\n655\n00:40:41,160 --> 00:40:43,520\n每一个AGENDA都有一个队列\nBecause each of these agendas has a queue in it.\n\n656\n00:40:44,340 --> 00:40:45,024\n队列是什么？\nWhat's a queue?\n\n657\n00:40:49,472 --> 00:40:51,856\n队列能够进行下述基本运算：\nA queue is going to have the following primitive operations.\n\n658\n00:40:52,784 --> 00:41:02,170\nMAKE-QUEUE构建一个新队列\nTo make a queue, this gives me a new queue.\n\n659\n00:41:07,776 --> 00:41:17,104\nINSERT-QUEUE!向队列中插入新元素\nI'm going to have to be able to insert into a queue a new item.\n\n660\n00:41:24,510 --> 00:41:28,656\nDELETE-QUEUE!从队列中删除元素\nI'm going to have to be able to delete from a queue the first item in the queue.\n\n661\n00:41:40,448 --> 00:41:52,048\nFRONT-QUEUE查看队列中第一个元素\nAnd I want to be able to get the first thing in the queue from some queue.\n\n662\n00:41:53,136 --> 00:41:55,140\n还需要检测队列是否为空\nI also have to be able to test whether a queue is empty.\n\n663\n00:42:07,110 --> 00:42:08,704\n当你定义像这样的运算时\nAnd when you invent things like this,\n\n664\n00:42:09,024 --> 00:42:10,448\n我希望你能够注意\nI want you to be very careful\n\n665\n00:42:10,640 --> 00:42:14,090\n按照我这样的习惯去为它们命名\nto use the kinds of conventions I use for naming things.\n\n666\n00:42:15,120 --> 00:42:19,152\n“!”表示操作具有副作用 “?”代表定义谓词\nNotice that I'm careful to say these change something and that tests it.\n\n667\n00:42:19,870 --> 00:42:21,856\n就比如说 这里应该加上一个“!”\nAnd presumably, I did the same thing over here.\n\n668\n00:42:24,656 --> 00:42:26,960\n嗯 空检测谓词的“?”也不要遗漏了\nOK, and there should be an empty test over here.\n\n669\n00:42:29,240 --> 00:42:30,720\n那么 我要如何构建一个队列呢？\nOK, well, how would I make a queue?\n\n670\n00:42:31,720 --> 00:42:34,112\n队列是一种 可以向其尾部添加东西\nA queue wants to be something I can add to at the end of,\n\n671\n00:42:35,120 --> 00:42:36,830\n也可以从前面取出东西的结构\nand pick up the thing at the beginning of.\n\n672\n00:42:37,840 --> 00:42:40,512\n我可以从队列头删除元素 向队列尾添加元素\nI should be able to delete from the beginning and add to the end.\n\n673\n00:42:41,230 --> 00:42:43,248\n我可以用一种很简单的结构来实现\nWell, I'm going to show you a very simple structure for that.\n\n674\n00:42:43,888 --> 00:42:45,728\n我们当然可以使用CONS来构造\nWe can make this out of CONSes as well.\n\n675\n00:42:47,080 --> 00:42:47,792\n这是一个队列\nHere's a queue.\n\n676\n00:42:49,910 --> 00:42:52,368\n它有一个队列头\nIt has--it has a queue header,\n\n677\n00:42:53,584 --> 00:42:54,928\n它包含两个部分\nwhich contains two parts--\n\n678\n00:42:55,280 --> 00:42:56,256\n其中一个是头指针\na front pointer\n\n679\n00:42:58,784 --> 00:42:59,824\n另一个是尾指针\nand a rear pointer.\n\n680\n00:43:03,120 --> 00:43:06,336\n假设我有一个包含两个元素的队列\nAnd here I have a queue with two items in it.\n\n681\n00:43:09,136 --> 00:43:12,090\n假设第一个元素是1\nThe first item, I don't know, it's perhaps a 1.\n\n682\n00:43:12,464 --> 00:43:16,530\n而第二个元素假定是2\nAnd the second item, I don't know, let's give it a 2.\n\n683\n00:43:21,408 --> 00:43:23,520\n我之所以要在这里设置两个指针\nThe reason why I want two pointers in here,\n\n684\n00:43:24,096 --> 00:43:25,616\n一个头指针和一个尾指针\na front pointer and a rear pointer,\n\n685\n00:43:25,720 --> 00:43:27,104\n这样 当向尾部添加元素的时候\nis so I can add to the end\n\n686\n00:43:27,488 --> 00:43:29,450\n就不用从最开始开始遍历\nwithout having to chase down from the beginning.\n\n687\n00:43:31,850 --> 00:43:34,800\n例如 我想要向队列添加入一个新元素\nSo for example, if I wanted to add one more item to this queue,\n\n688\n00:43:35,260 --> 00:43:41,024\n如果想添加一个稍后使用的元素\nif I want to add on another item to be worried about later,\n\n689\n00:43:41,088 --> 00:43:42,400\n只需要先用CONS构建一个序对\nall I have to do is make a CONS,\n\n690\n00:43:43,472 --> 00:43:46,592\n假设它包含一个值 -- 3\nwhich contains that item, say a 3.\n\n691\n00:43:47,530 --> 00:43:51,340\n再添加到队列里\nThat's for inserting 3 into the queue.\n\n692\n00:43:51,520 --> 00:43:53,776\n这里就需要把这个元素CDR部分的指针\nThen I have to change this pointer here\n\n693\n00:43:56,944 --> 00:43:58,760\n指向这个元素\nOkay? to here.\n\n694\n00:44:00,100 --> 00:44:04,320\n同时也更新尾指针 让它指向新的地方\nAnd I have to change this one to point to the new rear.\n\n695\n00:44:09,120 --> 00:44:12,688\n如果我想查看队列的第一个元素\nIf I wish to take the first element of the queue, the first item,\n\n696\n00:44:12,960 --> 00:44:17,120\n我只需要通过头指针去寻找 即可轻松找到\nI just go chasing down the front pointer until I find the first one and pick it up.\n\n697\n00:44:18,890 --> 00:44:23,264\n如果我想调用DELETE-QUEUE删除元素\nIf I wish to delete the first item from the queue, delete-queue,\n\n698\n00:44:24,144 --> 00:44:26,352\n只需要把头指针向后移到就行\nall I do is move the front pointer along this way.\n\n699\n00:44:27,712 --> 00:44:29,312\n新的头指针指向这里\nThe new front of the queue is now this.\n\n700\n00:44:31,700 --> 00:44:33,136\n就是这么简单\nSo queues are very simple too.\n\n701\n00:44:34,480 --> 00:44:35,760\n为了实现这些操作\nSo what you see now\n\n702\n00:44:37,248 --> 00:44:40,832\n我们还需要一些新的基本运算\nis that I need a certain number of new primitive operations.\n\n703\n00:44:41,488 --> 00:44:42,560\n我先列出它们的名字\nAnd I'm going to give them some names.\n\n704\n00:44:42,992 --> 00:44:46,288\n然后我们再来看 它们的原理和使用方法\nAnd then we're going to look into how they work, and how they're used.\n\n705\n00:44:47,350 --> 00:44:55,040\nSET-CAR!能够为序对的CAR部分\nWe have set the CAR of some pair,\n\n706\n00:44:55,888 --> 00:44:59,360\n赋予一个新的值\nor a thing produced by CONSing, to a new value.\n\n707\n00:45:02,370 --> 00:45:09,920\nSET-CDR!可以为序对的CDR部分赋新值\nAnd set the CDR of a pair to a new value.\n\n708\n00:45:13,024 --> 00:45:14,784\n现在来看看它们到底做了什么\nAnd then we're going to look into how they work.\n\n709\n00:45:16,030 --> 00:45:20,512\n为了删除队列中的第一个元素 我需要修改这里的CAR部分\nI needed setting CAR over here to delete the first element of the queue.\n\n710\n00:45:20,960 --> 00:45:22,528\n这是CAR部分 我需要修改它的值\nThis is the CAR, and I had to set it.\n\n711\n00:45:23,470 --> 00:45:24,960\n我需要能够修改CDR部分\nI had to be able to set the CDR\n\n712\n00:45:25,280 --> 00:45:27,088\n以便我能够移动尾指针\nto be able to move the rear pointer,\n\n713\n00:45:27,216 --> 00:45:28,760\n也使得我能够扩充队列\nor to be able to increment the queue here.\n\n714\n00:45:30,160 --> 00:45:31,600\n之前介绍的所有运算\nAll of the operations I did\n\n715\n00:45:31,904 --> 00:45:35,904\n上一块黑板上的所有东西 都是基于这些运算的\nwere made out of those that I just showed you on the, on the last blackboard.\n\n716\n00:45:38,176 --> 00:45:40,140\n先讲到这里 大家休息一下\nGood. Let's pause the time, and take a little break then.\n\n717\n00:45:41,240 --> 00:45:52,672\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n718\n00:45:52,670 --> 00:45:57,840\n《计算机程序的构造和解释》\n\n719\n00:46:18,640 --> 00:46:22,800\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n720\n00:46:22,800 --> 00:46:27,152\n《计算机程序的构造和解释》\n\n721\n00:46:27,168 --> 00:46:30,768\n计算对象\n\n722\n00:46:38,816 --> 00:46:43,536\n最初 我们说序对是通过CONS构造而来的\nWhen we originally introduced pairs made out of CONS, made by CONS,\n\n723\n00:46:44,576 --> 00:46:46,800\n我们提到了几条公理\nwe only said a few axioms about them,\n\n724\n00:46:48,096 --> 00:46:50,768\n它们是怎样的呢？ 它们是形如 --\nwhich were of the form-- what were they--\n\n725\n00:46:52,280 --> 00:47:03,648\n对于任意的X和Y (CAR (CONS X Y)) = X\nfor all X and Y, the CAR of the CONS of X and Y is X\n\n726\n00:47:05,312 --> 00:47:12,928\n以及 (CDR (CONS X Y)) = Y\nand Y is X and the CDR of the CONS of X and Y is Y.\n\n727\n00:47:14,800 --> 00:47:20,000\n但是 它们并没有陈述CONS单元 是否有像人一样的“身份”\nNow, these say nothing about whether a CONS has an identity like a person.\n\n728\n00:47:21,850 --> 00:47:25,584\n实际上 它描述的是一种抽象\nIn fact, all they say is something sort of abstract,\n\n729\n00:47:25,744 --> 00:47:27,952\n也就是CONS是由几个部分组成\nthat a CONS is the parts it's made out of.\n\n730\n00:47:29,740 --> 00:47:33,184\n如果两个CONS组成部分相同的  它俩则是同样的\nAnd of course, two things are made out of the same parts, they're the same,\n\n731\n00:47:33,936 --> 00:47:35,712\n至少从这些公理来看是这样的\nat least from the point of view of these axioms.\n\n732\n00:47:37,328 --> 00:47:39,216\n但是引入了赋值以后\nBut by introducing assignment--\n\n733\n00:47:39,840 --> 00:47:42,320\n实际上 可变数据就是一种赋值\nin fact, mutable data is a kind of assignment,\n\n734\n00:47:42,880 --> 00:47:44,432\n我们有SET-CAR!和SET-CDR!\nwe have a set CAR and a set CDR--\n\n735\n00:47:45,552 --> 00:47:48,944\n引入这些运算后 这些公理就不完整了\nby introducing those, these axioms no longer tell the whole story.\n\n736\n00:47:49,830 --> 00:47:52,032\n但是这里写的也是对的\nAnd they're still true if written exactly like this.\n\n737\n00:47:53,250 --> 00:47:54,944\n只不过描述的不再完整\nBut they don't tell the whole story.\n\n738\n00:47:56,070 --> 00:48:01,680\n因为如果我要修改一个特定的CONS的CAR部分\nBecause if I'm going to set a particular CAR in a particular CONS,\n\n739\n00:48:03,024 --> 00:48:04,032\n问题是\nthe questions are,\n\n740\n00:48:04,240 --> 00:48:08,640\n我会同时修改到相同CONS单元的CAR部分么？\nwell, is that setting all CARs and all CONSes of the same two things or not?\n\n741\n00:48:10,090 --> 00:48:13,040\n假如我用CONS来构建有理数\nIf I--if we use CONSes to make up things like rational numbers,\n\n742\n00:48:14,864 --> 00:48:17,104\n比如说3/4\nor things like 3 over 4,\n\n743\n00:48:17,344 --> 00:48:20,256\n假设我有两个3/4\nsupposing I had two three-fourths.\n\n744\n00:48:21,570 --> 00:48:22,752\n这两个一样吗？\nAre they the same one--\n\n745\n00:48:24,064 --> 00:48:24,890\n或者又不一样？\nor are they different?\n\n746\n00:48:25,340 --> 00:48:26,960\n当然 对于数字来说 这并不重要\nWell, in the case of numbers, it doesn't matter.\n\n747\n00:48:27,860 --> 00:48:30,496\n修改一个数的分母并没有数学意义\nBecause there's no meaning to changing the denominator of a number.\n\n748\n00:48:33,020 --> 00:48:35,328\n我们只能够说创建一个数 具有不同的分母\nWhat you could do is make a number which has a different denominator.\n\n749\n00:48:36,840 --> 00:48:39,888\n而直接修改一个数的分母这种观念\nBut the concept of changing a number which has to have a different denominator\n\n750\n00:48:40,000 --> 00:48:43,584\n在数学意义上是一种非常奇怪而不受支持的行为\nis sort of a very weird, and sort of not supported by what you think of as mathematics.\n\n751\n00:48:44,770 --> 00:48:47,408\n然而 当这些CONS单元表示的是现实世界中的事物\nHowever, when these CONSes represent things in the physical world,\n\n752\n00:48:48,976 --> 00:48:50,432\n那么修改它的CAR部分\nthen changing something like the CAR\n\n753\n00:48:50,608 --> 00:48:52,208\n就像除掉指甲壳的一块一样\nlike removing a piece of the fingernail.\n\n754\n00:48:53,690 --> 00:48:56,560\n所以 每一个CONS都有自己的“身份”\nAnd so CONSes have an identity.\n\n755\n00:48:57,770 --> 00:48:59,920\n我来先说明“身份”是什么意思\nLet me show you what I mean about identity, first of all.\n\n756\n00:49:01,280 --> 00:49:03,056\n来看些例子\nLet's do some little example here.\n\n757\n00:49:04,320 --> 00:49:15,200\n假如(DEFINE A (CONS 1 2))\nSupposing I define A to the CONS of 1 and 2.\n\n758\n00:49:18,320 --> 00:49:19,760\n这是代表什么呢？ 首先\nWell, what that means, first of all,\n\n759\n00:49:20,672 --> 00:49:25,200\n这是说我在某个环境中创建了符号A\nis that somewhere in some environment I've made a symbol A\n\n760\n00:49:25,968 --> 00:49:28,672\n而它的值是一个序对\nto have a value which is a pair\n\n761\n00:49:29,472 --> 00:49:34,064\n这个序对由两个分别指向1和2的指针组成\nconsisting of pointers to a 1 and a pointer to a 2,\n\n762\n00:49:35,344 --> 00:49:36,160\n就像这样\njust like that.\n\n763\n00:49:38,120 --> 00:49:39,600\n又假设\nNow, supposing I also say\n\n764\n00:49:40,224 --> 00:49:47,584\n(DEFINE B (CONS A A))\ndefine B to be the CONS--\n\n765\n00:49:53,888 --> 00:49:56,816\n虽然无所谓 不过我还是更喜欢用大写\nit doesn't matter, but I like it better, it's prettier--\n\n766\n00:49:57,632 --> 00:49:59,888\n(DEFINE B (CONS A A))\nof A and A.\n\n767\n00:50:03,970 --> 00:50:06,032\n这里用了两次A\nWell, first of all, I'm using the name A twice.\n\n768\n00:50:07,840 --> 00:50:10,576\n现在就要考虑序对的身份问题了\nAt this moment, I'm going to think of CONSes as having identity.\n\n769\n00:50:11,300 --> 00:50:12,640\n这两个A是同一个东西\nThis is the same one.\n\n770\n00:50:13,690 --> 00:50:14,816\n这也就是说\nAnd so what that means\n\n771\n00:50:15,296 --> 00:50:17,616\n我创建了另一个序对\nis I make another pair,\n\n772\n00:50:18,810 --> 00:50:20,208\n我把它记作B\nwhich I'm going to call B.\n\n773\n00:50:22,384 --> 00:50:27,600\n它由两个指向A的指针组成\nAnd it contains two pointers to A.\n\n774\n00:50:28,928 --> 00:50:32,208\n对于这个对象来说 此时我有三个名字来指称它\nAt this point, I have three names for this object.\n\n775\n00:50:33,104 --> 00:50:34,160\nA是一个\nA is its name.\n\n776\n00:50:34,880 --> 00:50:36,464\n(CAR B)是一个\nThe CAR of B is its name.\n\n777\n00:50:37,230 --> 00:50:38,864\n(CDR B)也是一个\nAnd the CDR of B is its name.\n\n778\n00:50:39,360 --> 00:50:41,150\n都是这个序对的别名\nIt has several aliases, they're called.\n\n779\n00:50:44,230 --> 00:50:49,280\n假设现在我要执行\nNow, supposing I do something like set-the-CAR,\n\n780\n00:50:53,776 --> 00:51:08,380\n(SET-CAR! (CAR B) 3)\nthe CAR of the CAR of B to 3.\n\n781\n00:51:12,750 --> 00:51:17,456\n我先去找B的CAR部分 也就是它\nWhat that means is I find the CAR of B, that's this.\n\n782\n00:51:17,830 --> 00:51:20,935\n再修改它的CAR部分 修改为3\nI set the CAR of that to be 3, changing this.\n\n783\n00:51:24,760 --> 00:51:25,696\n这样我也就修改了A\nI've changed A.\n\n784\n00:51:27,248 --> 00:51:33,648\n如果我问 现在A的CAR部分是多少\nIf I were to ask what's the CAR of A--of A now?\n\n785\n00:51:35,340 --> 00:51:37,568\n结果是3\nI would get out 3,\n\n786\n00:51:38,688 --> 00:51:43,392\n尽管在这里 A是由1和2构成的序对\neven though here we see that A was the CONS of 1 and 2.\n\n787\n00:51:45,290 --> 00:51:47,440\n我通过改变B而改变了A\nI caused A to change by changing B.\n\n788\n00:51:48,560 --> 00:51:49,648\n它们之间存在共享\nThere is sharing here.\n\n789\n00:51:52,256 --> 00:51:53,472\n有时候我们需要这样的结构\nThat's sometimes what we want.\n\n790\n00:51:54,240 --> 00:51:56,128\n当然 在类似于队列这类的数据结构中\nSurely in the queues and things like that,\n\n791\n00:51:56,240 --> 00:52:02,384\n我们正是这样来定义、组织数据结果来获得数据共享的\nthat's exactly what we defined our--organized our data structures to facilitate-- sharing.\n\n792\n00:52:04,350 --> 00:52:05,664\n但是有一些非预期的共享\nBut inadvertent sharing,\n\n793\n00:52:07,760 --> 00:52:09,728\n对象间的非预期交互\nunanticipated interactions between objects,\n\n794\n00:52:10,784 --> 00:52:14,080\n是大型程序中产生的BUG的主要来源\nis the source of most of the bugs that occur in complicated programs.\n\n795\n00:52:15,440 --> 00:52:21,664\n通过使对象具有“身份”、允许共享\nSo by introducing this possibility of things having identity and sharing\n\n796\n00:52:21,870 --> 00:52:23,760\n给同一个对象取多个别名\nand having multiple names for the same thing,\n\n797\n00:52:24,080 --> 00:52:25,056\n我们获得了强大的能力\nwe get a lot of power.\n\n798\n00:52:25,136 --> 00:52:28,464\n但是同时也为此引出的BUG和复杂度而付出代价\nBut we're going to pay for it with lots of complexity and bugs.\n\n799\n00:52:32,190 --> 00:52:36,240\n为了把这个讲透彻一点 我们再举一个例子\nSo also, for example, if I just looked at this just to drive that home,\n\n800\n00:52:37,104 --> 00:52:39,872\n比如(CADR B)\nthe CADR of B,\n\n801\n00:52:42,464 --> 00:52:46,560\n看起来和(CAR B)没有一点关系\nwhich has nothing to do with even the CAR of B, apparently.\n\n802\n00:52:46,880 --> 00:52:49,024\n但是它的值是什么？\nThe CADR of B, what's that?\n\n803\n00:52:49,350 --> 00:52:53,560\n先取B的CDR部分 再取结果的CAR部分\nTake that CDR of B and now take the CAR of that.\n\n804\n00:52:53,560 --> 00:52:54,864\n哦 还是3\nOh, that's 3 also.\n\n805\n00:52:56,480 --> 00:53:00,432\n有了共享这样的机制 局部的含义也不是那么清楚了\nSo I can have non-local interactions by sharing.\n\n806\n00:53:01,120 --> 00:53:02,480\n所以我们要非常小心的操作\nAnd I have to be very careful of that.\n\n807\n00:53:06,640 --> 00:53:12,640\n目前为止 我已经介绍了好几个赋值运算\nWell, so far, of course, it seems I've introduced several different assignment operators--\n\n808\n00:53:13,184 --> 00:53:17,616\n比如SET!、SET-CAR!、SET-CDR!\nset, set CAR, set CDR.\n\n809\n00:53:18,512 --> 00:53:21,392\n或许我应该不用SET-CAR!、SET-CDR! 它们引入太多问题了\nWell, maybe I should just get rid of set CAR and set CDR. Maybe they're not worthwhile.\n\n810\n00:53:22,820 --> 00:53:23,664\n而事实则是\nWell, the answer is\n\n811\n00:53:24,120 --> 00:53:26,112\n一旦把骆驼的鼻子牵进帐篷\nthat once you let the camel's nose into the tent,\n\n812\n00:53:26,240 --> 00:53:27,340\n它的身体可就自己跟进来了\nthe rest of him follows.\n\n813\n00:53:30,160 --> 00:53:31,264\n只要有SET!\nAll I have to have is set,\n\n814\n00:53:31,616 --> 00:53:35,850\n这些糟糕的东西都可能发生\nand I can make all of the--all of the bad things that can happen.\n\n815\n00:53:38,550 --> 00:53:39,808\n我们来分析一下\nLet's play with that a little bit.\n\n816\n00:53:40,690 --> 00:53:43,728\n前些日子 讲到复合数据的时候\nA couple of days ago, when we introduced compound data,\n\n817\n00:53:45,136 --> 00:53:51,200\n哈罗德教授向你们展示了 用消息接收的方式来定义CONS\nyou saw Hal show you a definition of CONS in terms of a message acceptor.\n\n818\n00:53:52,480 --> 00:53:56,064\n我将给你们展示一种更加糟糕的方式\nI'm going to show you even a more horrible thing,\n\n819\n00:53:57,136 --> 00:54:00,048\n凭“空”定义CONS\na definition of CONS in terms of nothing but air,\n\n820\n00:54:02,560 --> 00:54:03,024\n“什么”都不用\nhot air.\n\n821\n00:54:04,440 --> 00:54:08,128\n用传统的函数式的方法如何定义CONS呢？\nWhat is the definition of CONS, of the old functional kind,\n\n822\n00:54:09,264 --> 00:54:11,664\n纯粹只用LAMBDA表达式\nin terms of purely lambdic expressions,\n\n823\n00:54:13,392 --> 00:54:14,400\n把序对表示成过程\nprocedures?\n\n824\n00:54:17,392 --> 00:54:19,664\n现在我要修改这个定义\nBecause I'm going to then modify this definition\n\n825\n00:54:20,304 --> 00:54:23,168\n使得只具有一种赋值\nto get assignment to be only one kind of assignment,\n\n826\n00:54:24,288 --> 00:54:27,936\n用SET!来代替SET-CAR!和SET-CDR!\nto get rid of the set CAR and set CDR in terms of set.\n\n827\n00:54:28,580 --> 00:54:37,392\n如果我把CONS定义为\nSo what if I define CONS of X and Y\n\n828\n00:54:38,910 --> 00:54:42,560\n定义为一个过程 该过程接收参数M\nto be a procedure of one argument called a message M,\n\n829\n00:54:43,392 --> 00:54:46,320\n该过程将M应用在X与Y上\nwhich calls that message on X and Y?\n\n830\n00:54:51,120 --> 00:54:53,104\n这是阿隆佐·丘奇发明的方法\nThis idea was invented by Alonzo Church,\n\n831\n00:54:53,776 --> 00:54:55,728\n他是20世纪最伟大的程序员\nwho was the greatest programmer of the 20th century,\n\n832\n00:54:55,792 --> 00:54:57,152\n尽管当时电脑还没有被发明\nalthough he never saw a computer.\n\n833\n00:54:57,870 --> 00:54:59,130\n但他在20世纪30年代就提出了这个方法\nIt was done in the 1930s.\n\n834\n00:54:59,424 --> 00:55:02,220\n他是一个逻辑学家 在普林斯顿大学做研究\nHe was a logician, I suppose at Princeton at the time.\n\n835\n00:55:08,660 --> 00:55:10,432\n定义(CAR X)为\nDefine CAR of X\n\n836\n00:55:13,104 --> 00:55:16,928\n把X应用在一个二元过程上\nto be the result of applying X to that procedure of two arguments,\n\n837\n00:55:17,152 --> 00:55:20,608\n参数分别是A和D 而结果是选出A\nA and D, which selects A.\n\n838\n00:55:23,710 --> 00:55:24,976\n而(CDR X)则是\nI will define CDR of X\n\n839\n00:55:33,104 --> 00:55:34,784\n这样的一个过程\nto be that procedure,\n\n840\n00:55:35,088 --> 00:55:40,256\n把X应用在一个参数分别是A和D的过程上\nto be the result of applying X to that procedure of A and D,\n\n841\n00:55:40,928 --> 00:55:42,048\n该过程选择出D\nwhich selects D.\n\n842\n00:55:46,670 --> 00:55:49,888\n可能你们还没意识到这些就是CAR、CDR和CONS\nNow, you may not recognize this as CAR, CDR, and CONS.\n\n843\n00:55:50,510 --> 00:55:53,616\n但我将要给你们演示它符合之前的公理\nBut I'm going to demonstrate to you that it satisfies the original axioms\n\n844\n00:55:54,112 --> 00:55:54,816\n举一个例子\njust once.\n\n845\n00:55:55,616 --> 00:55:57,568\n我们来看一下\nAnd then we're going to do some playing of games.\n\n846\n00:55:58,290 --> 00:56:06,272\n考虑一下语句语句(CAR (CONS 35 47))\nConsider the problem CAR of CONS of, say, 35 and 47.\n\n847\n00:56:09,936 --> 00:56:10,960\n它的结果是多少呢？\nWell, what is that?\n\n848\n00:56:11,120 --> 00:56:15,248\n它是通过把35和47代换进\nIt is the result of taking car of the result of substituting 35 and 47\n\n849\n00:56:15,376 --> 00:56:18,208\n语句体中的X和Y得到的\nX and Y in the body of this.\n\n850\n00:56:19,710 --> 00:56:20,690\n非常容易\nWell, that's easy enough.\n\n851\n00:56:20,690 --> 00:56:30,880\n就得到了语句(CAR (LAMBDA (M) (M 35 47)))\nThat's CAR of the result of substituting into lambda of M, M of 35 and 47.\n\n852\n00:56:35,530 --> 00:56:39,360\n这个的结果是把这个对象\nWell, what this is, is the result of substituting this object\n\n853\n00:56:39,440 --> 00:56:41,856\n代换进这里的X而得到的\nfor X in the body of that.\n\n854\n00:56:42,830 --> 00:56:47,664\n代换的结果是((LAMBDA (M --\nSo that's just lambda of M--\n\n855\n00:56:48,336 --> 00:56:52,192\n用这个对象代换这里的X\nthat's substituted, because this object is being substituted for X,\n\n856\n00:56:52,880 --> 00:56:54,352\n这是表的头部\nwhich is the beginning of a list,\n\n857\n00:56:54,880 --> 00:57:00,320\n体的部分是(M 35 47)\nlambda of M-- M of 35 and 47,\n\n858\n00:57:03,104 --> 00:57:07,312\n把它应用于一个参数分别的A和D的过程上\napplied to that procedure of A and D,\n\n859\n00:57:07,488 --> 00:57:08,672\n后者返回参数A\nwhich gives me A.\n\n860\n00:57:10,912 --> 00:57:14,624\n然后我们用这个来代换这里的M\nWell, that's the result of substituting this for M here.\n\n861\n00:57:15,968 --> 00:57:21,712\n这个就相当于把(LAMBDA (A D) A)\nSo that's the same thing as lambda of A, D, A,\n\n862\n00:57:22,224 --> 00:57:24,848\n应用在35和47上\napplied to 35 and 47.\n\n863\n00:57:26,330 --> 00:57:27,376\n结果就是35\nOh, well that's 35.\n\n864\n00:57:27,408 --> 00:57:31,210\n它就是用35和47分别代换A、D 最后返回A\nThat's substituting 35 for A and for 47 for D in A.\n\n865\n00:57:35,600 --> 00:57:37,248\n所以我根本不需要任何数据\nSo I don't need any data at all.\n\n866\n00:57:37,888 --> 00:57:38,752\n甚至连数字都不需要\nnot even numbers.\n\n867\n00:57:40,928 --> 00:57:42,640\n这就是 阿隆佐·邱奇的技巧\nThis is Alonso Church's hack.\n\n868\n00:57:52,420 --> 00:57:56,176\n现在呢我们来对这个定义做点修改\nWell, now we're going to do something nasty to him.\n\n869\n00:57:56,760 --> 00:57:58,496\n作为逻辑学家 他可能会不太开心\nBeing a logician, he wouldn't like this.\n\n870\n00:57:59,200 --> 00:58:01,968\n但作为程序员 -- 请看投影仪\nBut as programmers, let's look at the overhead.\n\n871\n00:58:03,260 --> 00:58:04,160\n我们来看看\nAnd here we go.\n\n872\n00:58:05,390 --> 00:58:07,584\n我修改了CONS的定义\nI'm going to change the definition of CONS.\n\n873\n00:58:09,570 --> 00:58:12,352\n和丘奇的定义很相似 但是不完全相同\nIt's almost the same as Alonzo Church's, but not quite.\n\n874\n00:58:14,416 --> 00:58:15,504\n具体到底是什么？\nWhat do we have here?\n\n875\n00:58:16,070 --> 00:58:18,720\nCONS有两个参数：X和Y\nThe CONS of two arguments, X and Y,\n\n876\n00:58:19,504 --> 00:58:22,512\n但它返回一个参数为M的过程\nis going to be that procedure of one argument M,\n\n877\n00:58:23,392 --> 00:58:25,648\n跟之前一样M会应用于X和Y上\nwhich supplies M to X and Y as before,\n\n878\n00:58:26,192 --> 00:58:29,296\n但它额外还有两个“许可”\nbut also to two permissions,\n\n879\n00:58:30,176 --> 00:58:32,016\n其中一个是把X赋值为N\nthe permission to set X to N\n\n880\n00:58:32,608 --> 00:58:34,400\n另一个则是把Y赋值为N\nand the permission to set Y to N,\n\n881\n00:58:34,448 --> 00:58:35,680\n只要我提供了相应的N\ngiven that I have an N.\n\n882\n00:58:40,940 --> 00:58:44,720\n所以出了邱奇原本的定义之外\nSo besides the things that I had here in Church's definition,\n\n883\n00:58:45,728 --> 00:58:51,664\n最大的不同在于CONS的返回值\nwhat I have is that the thing that CONS returns\n\n884\n00:58:52,128 --> 00:58:53,824\n不单会把它的参数应用于\nwill apply its argument\n\n885\n00:58:54,912 --> 00:58:59,440\n用于构成序对的X和Y之上\nto not just the values of the X and Y that the CONS is made of,\n\n886\n00:58:59,696 --> 00:59:03,584\n它还有用于为X和Y赋值的两个“许可”\nbut also permissions to set X and Y to new values.\n\n887\n00:59:06,540 --> 00:59:08,080\n当然 就如之前一样\nNow, of course, just as before,\n\n888\n00:59:08,832 --> 00:59:10,512\nCAR看起来也很相似\nCAR is exactly the same.\n\n889\n00:59:11,690 --> 00:59:14,368\n就像邱奇定义的那样\nThe CAR of X is nothing more than applying X,\n\n890\n00:59:14,544 --> 00:59:16,000\n(CAR X)只不过是把X应用在\nas in Church's definition,\n\n891\n00:59:16,864 --> 00:59:19,008\n过程上 -- 本例中是四个参数\nto a procedure, in this case, of four arguments,\n\n892\n00:59:19,296 --> 00:59:21,040\n然后从中选出第一个\nwhich selects out the first one.\n\n893\n00:59:22,540 --> 00:59:24,160\n这就和之前一样\nAnd just as we did before,\n\n894\n00:59:25,424 --> 00:59:26,960\n结果将会返回X\nthat will be the value of X\n\n895\n00:59:29,040 --> 00:59:35,408\nX的值被包含在求值这个LAMBDA表达式所产生的过程中\nthat was contained in the procedure which is the result of evaluating this lambda expression\n\n896\n00:59:35,456 --> 00:59:37,840\nX和Y的值也是在这个环境中定义的\nin the environment where X and Y are defined over here.\n\n897\n00:59:41,940 --> 00:59:43,152\n这是我们对CONS的定义\nThat's the value of CONS.\n\n898\n00:59:45,640 --> 00:59:47,536\n那么 激动人心的地方来了\nNow, however, the exciting part.\n\n899\n00:59:47,730 --> 00:59:48,960\n当然CDR的定义也类似\nCDR, of course, is the same.\n\n900\n00:59:49,390 --> 00:59:50,352\n激动人心的地方\nThe exciting part,\n\n901\n00:59:51,232 --> 00:59:52,528\nSET-CAR!和SET-CDR!的实现\nset CAR and set CDR.\n\n902\n00:59:53,456 --> 00:59:55,520\n说实话 它们也不是特别复杂\nWell, they're nothing very complicated anymore.\n\n903\n00:59:55,800 --> 01:00:00,640\n语句(SET-CAR! X Y)\nSet CAR of a CONS X to a new value Y\n\n904\n01:00:01,632 --> 01:00:03,856\n无非就是把序对X应用于\nis nothing more than applying that CONS,\n\n905\n01:00:04,112 --> 01:00:06,768\n注意X是一个一元过程\nwhich is the procedure of four--the procedure of one argument\n\n906\n01:00:07,696 --> 01:00:09,808\n该过程的体是将参数应用在四个对象上\nwhich applies its argument to four things,\n\n907\n01:00:11,248 --> 01:00:15,856\n我们把X应用于一个四元过程上\nto a procedure which is of four arguments--\n\n908\n01:00:16,000 --> 01:00:18,080\nX的值、Y的值\nthe value of X, the value of Y,\n\n909\n01:00:18,320 --> 01:00:20,544\n修改X的许可、修改Y的许可\npermission to set X, the permission to set Y--\n\n910\n01:00:21,320 --> 01:00:26,096\n语句的体则是用相应的许可 将X设置为新的值\nand using it--using that permission to set X to the new value.\n\n911\n01:00:31,650 --> 01:00:33,540\n当然SET-CDR!和它类似\nAnd similarly, set-cdr is the same thing.\n\n912\n01:00:36,256 --> 01:00:39,440\n你也看到了 我这里并没有引入新的基本运算\nSo what you've just seen is that I didn't introduce any new primitives at all.\n\n913\n01:00:40,112 --> 01:00:44,368\n具体要不要这样来实现是一个工程性问题\nI mean, Whether or not I want to implement it this way is a matter of engineering.\n\n914\n01:00:45,340 --> 01:00:47,392\n当然出于工程上的考量\nAnd the answer is of course I don't implement it this way\n\n915\n01:00:48,096 --> 01:00:49,630\n我不会这样来实现\nfor reasons that have to do with engineering.\n\n916\n01:00:51,680 --> 01:00:53,408\n但是从原理上来说\nHowever in principle, logically,\n\n917\n01:00:54,288 --> 01:00:56,432\n一旦引入了赋值运算\nI introduced one assignment operator,\n\n918\n01:00:56,960 --> 01:00:58,760\n我就可以进行各种各样的赋值运算了\nI've assigned--I've introduced them all.\n\n919\n01:01:05,420 --> 01:01:06,670\n有什么问题吗？\nAre there any questions?\n\n920\n01:01:09,200 --> 01:01:10,896\n请讲\nYes, David.\n\n921\n01:01:12,040 --> 01:01:15,648\n我可以跟的上你的思路 直到 --\nAUDIENCE: I can follow you up until you get--I can follow all of that.\n\n922\n01:01:15,648 --> 01:01:17,616\n在许可那里\nBut when we bring in the permissions,\n\n923\n01:01:18,144 --> 01:01:21,648\n我们把CONS定义为一个参数为N的过程\ndefining CONS in terms of the lambda N,\n\n924\n01:01:21,808 --> 01:01:24,210\n我不知道这个参数是什么时候传进来的\nI don't follow where N gets passed.\n\n925\n01:01:24,210 --> 01:01:25,696\n教授：哦 抱歉 我给你演示一下\nPROFESSOR: Oh, I'm sorry. I'll show you.\n\n926\n01:01:26,340 --> 01:01:27,056\n我们来推演一下\nLet's follow it.\n\n927\n01:01:27,360 --> 01:01:29,072\n虽然在黑板上推演更清晰\nOf course, we could do it on the blackboard.\n\n928\n01:01:29,180 --> 01:01:30,170\n但这并不难懂\nIt's not so hard.\n\n929\n01:01:30,170 --> 01:01:31,472\n我就将就用投影仪了\nBut it's also easy here.\n\n930\n01:01:32,450 --> 01:01:35,792\n调用(SET-CDR! X Y)会发生什么呢？\nSupposing I wish to set-cdr of X to Y.\n\n931\n01:01:37,790 --> 01:01:39,664\n就在这里(SET-CDR! X Y)\nSee that right there. set cdr x to y\n\n932\n01:01:40,360 --> 01:01:41,920\nX可能是一个序对\nX is presumably a CONS,\n\n933\n01:01:43,312 --> 01:01:45,248\n或者说对一个CONS表达式求值得到的结果\na thing resulting from evaluating CONS.\n\n934\n01:01:45,888 --> 01:01:46,352\n能跟上吧？\nright?\n\n935\n01:01:46,890 --> 01:01:49,968\n也就是说 X是由这里的代码构造出来的\nTherefore X comes from a place over here,\n\n936\n01:01:52,576 --> 01:01:56,496\n这里的X是求值这个LAMBDA表达式得到的\nthat that X is of the result of evaluating this lambda expression.\n\n937\n01:01:58,110 --> 01:01:58,496\n对吧\nRight?\n\n938\n01:01:59,380 --> 01:02:01,632\n因此当我对这个LAMBDA表达式求值时\nThat when I evaluated that lambda expression,\n\n939\n01:02:04,016 --> 01:02:08,768\n我是在定义CONS时的一个环境里求值的\nI evaluated it in an environment where the arguments to CONS were defined.\n\n940\n01:02:11,750 --> 01:02:15,184\n这也就是说 作为LAMBDA表达式中的自由变量\nThat means that as free variables in this lambda expression,\n\n941\n01:02:16,250 --> 01:02:18,688\nX和Y都存储一个框架中\nthere is the--there are in the frame,\n\n942\n01:02:18,720 --> 01:02:22,440\n也就是这整个LAMBDA表达式的父框架\nwhich is the parent frame of this lambda expression,\n\n943\n01:02:23,232 --> 01:02:25,824\n因此在这个LAMBDA语句中\nthe procedure resulting from this lambda expression,\n\n944\n01:02:26,656 --> 01:02:28,512\nX和Y都有存储空间\nX and Y have places.\n\n945\n01:02:29,250 --> 01:02:30,832\n也可以对它们赋值\nAnd it's possible to set them.\n\n946\n01:02:31,910 --> 01:02:36,080\n这里赋值为N是通过参数来传递的\nI set them to an N, which is the argument of the permission.\n\n947\n01:02:37,264 --> 01:02:39,312\n“许可”就是一个过程\nThe permission is a procedure\n\n948\n01:02:41,408 --> 01:02:43,184\n它将作为M的一个参数\nwhich is passed to M,\n\n949\n01:02:43,296 --> 01:02:46,512\n它实际上是CONS生成的对象的一部分\nwhich is the argument that the CONS object gets passed.\n\n950\n01:02:47,940 --> 01:02:50,912\n我们再来看看SET-CDR!\nNow, let's go back here in the set-cdr\n\n951\n01:02:52,112 --> 01:02:55,424\nSET-CDR!的第一个参数X是一个序对\nThe CONS object, which is the first argument of set-cdr\n\n952\n01:02:56,128 --> 01:02:57,480\n被传递了一个参数\ngets passed an argument.\n\n953\n01:02:59,776 --> 01:03:02,224\n这个是一个四元过程\nThat--there's a procedure of four things, indeed,\n\n954\n01:03:02,320 --> 01:03:04,656\n这是因为 它要作为这里的M\nbecause that's the same thing as this M over here,\n\n955\n01:03:04,992 --> 01:03:06,560\n要应用在四个对象上\nwhich is applied to four objects.\n\n956\n01:03:07,920 --> 01:03:13,344\n这边的这个SD 就对应于这个过程\nThe object over here, SD, is, in fact, this permission.\n\n957\n01:03:15,470 --> 01:03:19,930\n当我执行SD 把它应用于Y\nWhen I use SD, I apply it to Y, right there.\n\n958\n01:03:22,910 --> 01:03:24,048\n这个Y是这里传过来的\nSo that comes from this.\n\n959\n01:03:25,370 --> 01:03:26,928\n学生：那--\nAUDIENCE: So what do you--\n\n960\n01:03:27,008 --> 01:03:32,192\n教授：所以说 这里的N就对应于这里的Y\nPROFESSOR: So to finish that, the N that was here is the Y which is here.\n\n961\n01:03:34,048 --> 01:03:34,528\n明白了吧\nHow's that?\n\n962\n01:03:34,810 --> 01:03:35,750\n了解了\nAUDIENCE: Right, OK.\n\n963\n01:03:35,750 --> 01:03:37,296\n当你执行SET-CDR!的时候\nNow, when you do a set-cdr,\n\n964\n01:03:39,072 --> 01:03:41,970\nX是CDR部分要赋值的新值\nX is the value the CDR is going to become.\n\n965\n01:03:41,970 --> 01:03:44,032\n教授：这里的X\nPROFESSOR: The X over here.\n\n966\n01:03:44,960 --> 01:03:46,200\n哦 指错了\nI'm sorry, that's not true.\n\n967\n01:03:46,200 --> 01:03:48,336\n这里的X是指 -- SET-CDR!有两个参数\nThe X is--set-cdr has two arguments--\n\n968\n01:03:48,912 --> 01:03:50,368\n一个是被修改的序对\nThe CONS I'm changing\n\n969\n01:03:51,344 --> 01:03:53,936\n还有就是新值\nand the value I'm changing it to.\n\n970\n01:03:56,150 --> 01:03:58,320\n你可以代换回去看看 就很清楚了\nSo you have them backwards, that's all.\n\n971\n01:04:02,176 --> 01:04:03,168\n还有什么问题吗？\nAre there any other questions?\n\n972\n01:04:07,880 --> 01:04:08,640\n好的\nWell, thank you.\n\n973\n01:04:08,640 --> 01:04:09,520\n这节课就到这里\nIt's time for lunch.\n\n974\n01:04:10,448 --> 01:04:17,392\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n975\n01:04:17,408 --> 01:04:28,736\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec6a.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:02,704\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:02,730 --> 00:00:04,200\n翻译&&时间轴：张大伟（DreamAndDead）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:04,480 --> 00:00:06,530\n特别感谢：裘宗燕教授\n\n4\n00:00:06,680 --> 00:00:09,620\n计算机程序的构造和解释\n\n5\n00:00:09,670 --> 00:00:13,340\n流 I\nStream\n\n6\n00:00:18,550 --> 00:00:21,840\n上次Gerry教授揭晓了秘密\nPROFESSOR: Well, last time Gerry really let the cat out of the bag.\n\n7\n00:00:22,496 --> 00:00:24,608\n他介绍了赋值的概念\nHe introduced the idea of assignment.\n\n8\n00:00:26,350 --> 00:00:33,616\n赋值与状态\nAssignment and state.\n\n9\n00:00:37,480 --> 00:00:40,032\n正如我们所见\nAnd as we started to see, the implications\n\n10\n00:00:40,720 --> 00:00:43,168\n将赋值和状态引入到语言中\nof introducing assignment and state into the language\n\n11\n00:00:43,168 --> 00:00:44,410\n后果相当糟糕\nare absolutely frightening.\n\n12\n00:00:45,088 --> 00:00:48,624\n首先 代换模型不再能够描述求值过程了\nFirst of all, the substitution model of evaluation breaks down.\n\n13\n00:00:49,136 --> 00:00:52,480\n为了解释程序中语句的语义\nAnd we have to use this much more complicated environment model\n\n14\n00:00:52,480 --> 00:00:54,272\n我们不得不使用更复杂的环境模型\nthis very mechanistic thing with diagrams,\n\n15\n00:00:54,288 --> 00:00:57,248\n也就是一种跟图表相关的非常机械的东西\neven to say what statements in the programming language mean.\n\n16\n00:00:58,464 --> 00:01:00,128\n并且 这不单纯地是一个技术上的问题\nAnd that's not a mere technical point.\n\n17\n00:01:00,260 --> 00:01:03,280\n并不是因为代换模型在这里不怎么有效\nSee, it's not that we had this particular substitution model and,\n\n18\n00:01:03,600 --> 00:01:05,680\n所以我们得想些其它办法\nwell, it doesn't quite work, so we have to do something else.\n\n19\n00:01:05,712 --> 00:01:09,792\n而是代换模型这类机制都不再起效\nIt's that nothing like the substitution model can work.\n\n20\n00:01:10,730 --> 00:01:13,328\n这是因为突然间 一个变量\nBecause suddenly, a variable\n\n21\n00:01:14,128 --> 00:01:16,920\n不再是代表着一个值了\nis not just something that stands for a value.\n\n22\n00:01:17,950 --> 00:01:21,760\n现在 变量用于指明一个位置\nA variable now has to somehow specify a place\n\n23\n00:01:22,400 --> 00:01:23,340\n一个存放值的位置\nthat holds a value.\n\n24\n00:01:23,630 --> 00:01:26,144\n并且 这个位置的值可以发生改变\nAnd the value that's in that place can change.\n\n25\n00:01:30,280 --> 00:01:34,096\n比如像 (F X) 这样的表达式\nOr for instance, an expression like f of x\n\n26\n00:01:37,360 --> 00:01:39,648\n就可能含有副作用\nmight have a side effect in it.\n\n27\n00:01:40,410 --> 00:01:42,608\n如果我们执行 (F X) 得到某个值\nSo if we say f of x and it has some value,\n\n28\n00:01:43,184 --> 00:01:45,344\n之后我们再次执行 (F X)\nand then later we say f of x again,\n\n29\n00:01:47,240 --> 00:01:48,432\n可能因为求值的顺序\nwe might get a different value\n\n30\n00:01:48,860 --> 00:01:49,744\n而得到不同的值\ndepending on the order.\n\n31\n00:01:49,760 --> 00:01:52,140\n所以突然间 我们不能仅仅关注于值\nSo suddenly, we have to think not only about values\n\n32\n00:01:52,528 --> 00:01:53,600\n也要关注时序\nbut about time.\n\n33\n00:01:57,970 --> 00:01:59,984\n序对也不仅仅\nAnd then things like pairs\n\n34\n00:02:00,656 --> 00:02:02,520\n只是它的CAR和CDR部分\nare no longer just their CARs and their CDRs.\n\n35\n00:02:02,520 --> 00:02:05,616\n不是作为CAR部分和CDR部分的别称\nA pair now is not quite its CAR and its CDR.\n\n36\n00:02:05,808 --> 00:02:07,056\n它也有自己的“身份”\nIt's rather its identity.\n\n37\n00:02:08,449 --> 00:02:11,650\n序对具有“身份”\nSo a pair has identity.\n\n38\n00:02:11,650 --> 00:02:12,592\n它是一个对象\nIt's an object.\n\n39\n00:02:21,330 --> 00:02:25,152\n两个具有相同CAR和CDR部分的序对\nAnd two pairs that have the same CAR and CDR\n\n40\n00:02:25,408 --> 00:02:27,056\n可能相同也可能不同\nwell, might be the same or different,\n\n41\n00:02:27,872 --> 00:02:30,512\n因为这之中可能存在“共享”\nbecause suddenly we have to worry about sharing.\n\n42\n00:02:34,960 --> 00:02:39,456\n一引入赋值 这些就变成要考虑的问题了\nSo all of these things enter as soon as we introduce assignment.\n\n43\n00:02:40,480 --> 00:02:43,984\n确实 这和我们说讲代换的时候差别悬殊\nSee, this is a really far cry from where we started with substitution.\n\n44\n00:02:45,040 --> 00:02:48,912\n技术上来看 我们思考起来更加困难了\nIt's a technically harder way of looking at things\n\n45\n00:02:48,940 --> 00:02:53,456\n因为我们必须相当机械地思考程序语言\nbecause we have to think more mechanistically about our programming language.\n\n46\n00:02:53,472 --> 00:02:55,344\n而不能仅仅用数学的方式来思考\nWe can't just think about it as mathematics.\n\n47\n00:02:55,710 --> 00:02:58,608\n我们也会遇到哲学问题\nIt's philosophically harder,\n\n48\n00:02:59,152 --> 00:03:00,656\n我们会被这样的问题所困扰：\nbecause suddenly there are all these funny issues\n\n49\n00:03:00,672 --> 00:03:02,384\n事物的“改变”指的是什么？\nwhat does it mean that something changes\n\n50\n00:03:02,384 --> 00:03:03,776\n两个事物“同一”又如何判别？\nor that two things are the same.\n\n51\n00:03:03,840 --> 00:03:06,832\n并且 这也会给我们编程带来困扰\nAnd also, it's programming harder, because\n\n52\n00:03:07,470 --> 00:03:08,544\n正如 Sussman 教授上节课中讲的那样\nas Gerry showed last time,\n\n53\n00:03:08,560 --> 00:03:12,200\n错误的表达式顺序和别名会产生BUG\nthere are all these bugs having to do with bad sequencing and aliasing\n\n54\n00:03:12,224 --> 00:03:16,190\n这些问题在不需要考虑“对象”的语言中 是不存在的\nthat just don't exist in a language where we don't worry about objects.\n\n55\n00:03:18,210 --> 00:03:21,200\n我们是怎样陷入这样的困境的呢？\nWell, how'd we get into this mess?\n\n56\n00:03:24,010 --> 00:03:27,200\n我们这样做的原因在于\nRemember what we did, the reason we got into this is\n\n57\n00:03:27,408 --> 00:03:31,472\n我们想要构造模块化的系统\nbecause we were looking to build modular systems.\n\n58\n00:03:35,150 --> 00:03:37,696\n我们想把系统划分为\nWe wanted to build systems that\n\n59\n00:03:38,096 --> 00:03:41,040\n数个自然组合的小块\nthat fall apart into chunks that seem natural.\n\n60\n00:03:42,760 --> 00:03:43,824\n举例来说\nSo for instance,\n\n61\n00:03:44,064 --> 00:03:46,110\n我们想要构造一个随机数发生器\nwe want to take a random number generator\n\n62\n00:03:46,224 --> 00:03:49,408\n把该发生器的内部状态封装起来\nand package up the state of that random number generator inside of it\n\n63\n00:03:50,256 --> 00:03:53,712\n这样我们就可以把选取随机数\nso that we can separate the idea of picking random numbers\n\n64\n00:03:54,656 --> 00:03:57,792\n和用于估计的蒙特卡洛方法分离开来\nfrom the general Monte Carlo strategy of estimating something\n\n65\n00:03:58,650 --> 00:04:01,520\n进一步地把它同由 Ceraso 发明的\nand separate that from the particular way that you\n\n66\n00:04:01,904 --> 00:04:05,744\n求取 π 的公式分离开\nwork with random numbers in that formula developed by Cesaro for pi.\n\n67\n00:04:06,800 --> 00:04:07,920\n相似地\nAnd similarly,\n\n68\n00:04:09,616 --> 00:04:11,744\n当我们着手构建事物的模型时\nwhen we go off and construct some models of things,\n\n69\n00:04:12,352 --> 00:04:16,016\n我们去构建现实世界中事物的模型\nAh, if we go off and model a system that we see in the real world,\n\n70\n00:04:17,310 --> 00:04:19,424\n我们想把程序组织成许多自然部分\nwe'd like our program to break into natural pieces,\n\n71\n00:04:19,440 --> 00:04:20,528\n这些部分就是\npieces that mirror\n\n72\n00:04:21,056 --> 00:04:23,160\n现实事物的镜像\nthe parts of the system that we see in the real world.\n\n73\n00:04:24,900 --> 00:04:27,568\n举个例子 对于一个数字电路\nSo for example, if we look at a digital circuit,\n\n74\n00:04:28,368 --> 00:04:29,184\n我们会说\nwe say, gee,\n\n75\n00:04:30,440 --> 00:04:31,440\n这儿有一个电路\nthere's a circuit\n\n76\n00:04:32,080 --> 00:04:35,160\n它有一个这样的元件 有一个那样的元件\nand it has a piece and it has another piece.\n\n77\n00:04:40,100 --> 00:04:43,580\n这些元件都有不同的“身份”\nAnd these different pieces sort of have identity.\n\n78\n00:04:43,580 --> 00:04:44,592\n它们都有各自的状态\nThey have state.\n\n79\n00:04:45,550 --> 00:04:47,136\n状态附着在电路上\nAnd the state sits on these wires.\n\n80\n00:04:48,580 --> 00:04:50,224\n我们认为这个元件是一个对象\nAnd we think of this piece as an object\n\n81\n00:04:50,496 --> 00:04:51,930\n这个元件又是另外一个不同的对象\nthat's different from that as an object.\n\n82\n00:04:52,540 --> 00:04:53,856\n当我们观察到系统发生了变化\nAnd when we watch the system change,\n\n83\n00:04:53,872 --> 00:04:55,408\n信号从这里传递过来\nwe think about a signal coming in here\n\n84\n00:04:55,632 --> 00:04:58,416\n改变了可能存放在这里的状态 并向这里继续传播\nchanging a state that might be here and going here\n\n85\n00:04:58,672 --> 00:05:00,752\n和一个存储在这里的状态交互\nand interacting with a state that might be stored there,\n\n86\n00:05:01,248 --> 00:05:02,170\n依此类推\nand so on and so on.\n\n87\n00:05:06,860 --> 00:05:11,248\n我们想要在计算机中\nSo what we'd like is we'd like to build in the computer\n\n88\n00:05:12,768 --> 00:05:14,368\n构建模块化的系统\nsystems that fall into pieces\n\n89\n00:05:14,688 --> 00:05:17,872\n来反映我们对现实的看法\nthat fall into pieces that mirror our view of reality,\n\n90\n00:05:17,880 --> 00:05:19,872\n根据我们正在建模的实际系统\nof the way that the actual systems we're modeling\n\n91\n00:05:19,888 --> 00:05:20,910\n来划分子系统\nseem to fall into pieces.\n\n92\n00:05:23,200 --> 00:05:23,488\n然而\nWell,\n\n93\n00:05:25,744 --> 00:05:28,992\n构建像这样的系统\nmaybe the reason that building systems like this\n\n94\n00:05:28,992 --> 00:05:31,504\n看起来带来了不少技术上的麻烦\nseems to introduce such technical complications\n\n95\n00:05:31,520 --> 00:05:32,752\n但这不是计算机造成的\nhas nothing to do with computers.\n\n96\n00:05:33,610 --> 00:05:35,600\n或许 真正拖累我们\nSee, maybe the real reason\n\n97\n00:05:36,700 --> 00:05:38,656\n让我们花了那么大的功夫\nthat we pay such a price to write programs\n\n98\n00:05:38,672 --> 00:05:40,940\n才让程序反映现实世界的原因\nthat mirror our view of reality\n\n99\n00:05:41,520 --> 00:05:43,136\n是我们对现实世界的认识出了错\nis that we have the wrong view of reality.\n\n100\n00:05:44,550 --> 00:05:46,752\n或许时间只是幻觉\nSee, maybe time is just an illusion,\n\n101\n00:05:47,264 --> 00:05:48,608\n什么都没有改变\nand nothing ever changes.\n\n102\n00:05:50,150 --> 00:05:51,712\n就拿这个粉笔来说\nSee, for example, if I take this chalk,\n\n103\n00:05:52,448 --> 00:05:53,776\n我们认为它是一个对象\nand we say, gee, this is an object\n\n104\n00:05:54,016 --> 00:05:54,992\n它有自己的状态\nand it has a state.\n\n105\n00:05:55,820 --> 00:05:59,296\n每时每刻 它都有一个位置和速度\nAt each moment it has a position and a velocity.\n\n106\n00:05:59,710 --> 00:06:01,488\n如果我们做点什么 就可以改变它的状态\nAnd if we do something, that state can change.\n\n107\n00:06:04,340 --> 00:06:07,376\n但是你如果了解一点相对性的概念\nBut if you studied any relativity, for instance,\n\n108\n00:06:07,744 --> 00:06:09,712\n你可能会认为粉笔的路径\nyou know that you don't think of the path of that chalk\n\n109\n00:06:09,728 --> 00:06:11,340\n不是许多瞬时的离散点\nas something that goes on instant by instant.\n\n110\n00:06:11,340 --> 00:06:14,384\n一种深刻的见解是把整个粉笔的存在看作\nIt's more insightful to think of that whole chalk's existence\n\n111\n00:06:14,416 --> 00:06:15,648\n时空中的路径\nas a path in space-time.\n\n112\n00:06:16,020 --> 00:06:17,376\n全部都展开了\nthat's all splayed out.\n\n113\n00:06:17,872 --> 00:06:19,840\n没有单独的位置与速度\nThere aren't individual positions and velocities.\n\n114\n00:06:19,840 --> 00:06:23,808\n在时空中的存在是不会发生改变的\nThere's just its unchanging existence in space-time.\n\n115\n00:06:24,640 --> 00:06:26,512\n相似地 如果我们来考察这个电气系统\nSimilarly, if we look at this electrical system,\n\n116\n00:06:27,690 --> 00:06:30,432\n我们假设这个系统实现的是\nif we imagine this electrical system is implementing\n\n117\n00:06:30,592 --> 00:06:33,960\n某种信号处理系统\nsort of signal processing system,\n\n118\n00:06:34,368 --> 00:06:36,688\n把这些元件组合在一起的工程师\nthe signal processing engineer who put that thing together\n\n119\n00:06:36,750 --> 00:06:38,608\n也不会把它们看作\ndoesn't think of it as, well,\n\n120\n00:06:38,960 --> 00:06:41,400\n电压施加于每个独立的元件\nat each instance there's a voltage coming in.\n\n121\n00:06:41,490 --> 00:06:43,168\n转换成了某种东西\nAnd that translates into something.\n\n122\n00:06:43,340 --> 00:06:45,520\n影响了这里的状态\nAnd that affects the state over here,\n\n123\n00:06:45,536 --> 00:06:46,810\n还改变了那里的状态\nwhich changes the state over here.\n\n124\n00:06:46,810 --> 00:06:50,112\n没有一个做信号处理的会这样想\nNobody putting together a signal processing system thinks about it like that.\n\n125\n00:06:50,420 --> 00:06:51,840\n相反 你会说\nInstead, you say there's this signal\n\n126\n00:06:54,048 --> 00:06:58,060\n这里有一个在时间上伸展的信号\nthat's splayed out over time.\n\n127\n00:06:58,060 --> 00:06:59,488\n如果把这个看作一个滤波器\nAnd if this is acting as a filter,\n\n128\n00:07:00,208 --> 00:07:04,048\n这个滤波器会把整个信号转化成\nthis whole thing transforms this whole thing\n\n129\n00:07:04,288 --> 00:07:07,040\n不同的输出信号\nfor some sort of other output.\n\n130\n00:07:09,570 --> 00:07:11,280\n你们不要把这些东西的状态\nYou don't think of it as what's happening\n\n131\n00:07:11,280 --> 00:07:13,290\n想象成在许多瞬间接连发生\ninstant by instant as the state of these things.\n\n132\n00:07:14,160 --> 00:07:17,328\n我们把这个盒子看作一个整体\nAnd somehow you think of this box as a whole thing,\n\n133\n00:07:17,320 --> 00:07:20,160\n而不是在一个特定的瞬间\nnot as little pieces sending messages of state\n\n134\n00:07:20,400 --> 00:07:21,960\n互相发送状态信息的小系统\nto each other at particular instants.\n\n135\n00:07:28,250 --> 00:07:29,360\n今天我们将介绍\nWell, today we're going to look at\n\n136\n00:07:29,392 --> 00:07:31,130\n另一种分解系统的方法\nanother way to decompose systems\n\n137\n00:07:31,360 --> 00:07:35,456\n站在信号工程师的角度去看待现实世界\nthat's more like the signal processing engineer's view of the world\n\n138\n00:07:35,696 --> 00:07:38,960\n而不再认为对象间通过消息传递来通信\nthan it is like thinking about objects that communicate sending messages.\n\n139\n00:07:41,130 --> 00:07:43,744\n它被称为“流处理”\nThat's called stream processing.\n\n140\n00:07:54,570 --> 00:07:58,960\n我们打算展示\nAnd we're going to start by showing\n\n141\n00:08:00,592 --> 00:08:04,160\n如何让我们的程序变得更加统一\nby showing how we can make our programs more uniform\n\n142\n00:08:05,152 --> 00:08:06,544\n从中看到更多的共性\nand see a lot more commonality\n\n143\n00:08:06,656 --> 00:08:09,888\n如果我们跳出这些程序\nif we throw out of these programs\n\n144\n00:08:10,816 --> 00:08:12,304\n我们会发现\nwhat you might say is a\n\n145\n00:08:12,352 --> 00:08:15,120\n我们对时序的考虑过度了\ninordinate concern with worrying about time.\n\n146\n00:08:16,896 --> 00:08:20,224\n我们先来对比两个过程\nLet me start by comparing two procedures.\n\n147\n00:08:23,552 --> 00:08:25,690\n第一个是这样\nThe first one does this.\n\n148\n00:08:25,690 --> 00:08:27,770\n想像这有一个树\nWe imagine that there's a tree.\n\n149\n00:08:30,400 --> 00:08:32,144\n一个由整数构成的树\nSay there's a tree of integers.\n\n150\n00:08:33,280 --> 00:08:34,420\n一个二叉树\nIt's a binary tree.\n\n151\n00:08:36,128 --> 00:08:36,976\n这里是1\nSay 1.\n\n152\n00:08:39,100 --> 00:08:40,230\n看起来就像这样\nSo it looks like this.\n\n153\n00:08:40,230 --> 00:08:42,928\n在每个节点上都有一个整数\nAnd there's integers in each of the nodes.\n\n154\n00:08:45,184 --> 00:08:47,808\n我们想计算\nAnd what we would like to compute is\n\n155\n00:08:48,672 --> 00:08:51,568\n对这个树中所有的奇数\nfor each odd number sitting here,\n\n156\n00:08:52,304 --> 00:08:55,104\n计算它们的平方和\nwe'd like to find the square and then sum up all those squares.\n\n157\n00:08:57,056 --> 00:08:59,480\n我们对这类问题很熟悉\nWell, that should be a familiar kind of thing.\n\n158\n00:08:59,480 --> 00:09:01,952\n有一种递归策略求解它\nThere's a recursive strategy for doing it.\n\n159\n00:09:02,930 --> 00:09:04,352\n观察每个叶子节点\nWe look at each leaf, and either\n\n160\n00:09:04,560 --> 00:09:06,688\n如果是奇数我们就求它的平方 并加和\nit's going to contribute the square of the number if it's odd\n\n161\n00:09:06,704 --> 00:09:07,770\n如果是偶数 就是0\nor 0 if it's even.\n\n162\n00:09:08,680 --> 00:09:12,112\n递归地看 对于每一颗树 我们可以说\nAnd then recursively, we can say at each tree\n\n163\n00:09:12,656 --> 00:09:13,840\n它的平方和等于\nthe sum of all of them is\n\n164\n00:09:13,920 --> 00:09:15,936\n右子树的平方和 加上左子树的平方和\nthe sum coming from the right branch and the left branch,\n\n165\n00:09:16,256 --> 00:09:17,640\n就这样沿着节点递归下去\nand recursively down through the nodes.\n\n166\n00:09:17,640 --> 00:09:18,704\n我们已经很熟悉\nAnd that's a familiar way of\n\n167\n00:09:19,264 --> 00:09:20,360\n这种程序设计的思考方式了\nthinking about programming.\n\n168\n00:09:20,360 --> 00:09:22,592\n我们来幻灯片上看一下\nLet's actually look at that on the slide.\n\n169\n00:09:23,820 --> 00:09:26,752\n为了计算一棵树中奇数的平方和\nWe say to sum the odd squares in a tree,\n\n170\n00:09:27,376 --> 00:09:29,360\n我们先要判断它是否是一个叶子节点\nthere's a test. Either it's a leaf node,\n\n171\n00:09:29,824 --> 00:09:31,952\n判断方法则是考察该节点是否为整数\nand we're going to check to see if it's an integer,\n\n172\n00:09:32,880 --> 00:09:36,384\n继而判断其奇偶性 以及是否应该求取平方并加和\nand then either it's odd, in which we take the square, or else it's 0.\n\n173\n00:09:37,160 --> 00:09:38,992\n然后 整个的解就是\nAnd then the sum of the whole thing\n\n174\n00:09:39,216 --> 00:09:42,120\n左、右子树解的总和\nis the sum coming from the left branch and the right branch.\n\n175\n00:09:46,340 --> 00:09:50,560\n好的 让我们再来和下面一个问题对比一下\nOK, well, let me contrast that with a second problem.\n\n176\n00:09:51,560 --> 00:09:53,680\n假如给你一个整数N\nSuppose I give you an integer n,\n\n177\n00:09:54,736 --> 00:09:57,888\n再给定一个函数 把它应用在\nand then some function to compute of the first of each integer\n\n178\n00:09:57,936 --> 00:09:58,832\n1到N的每一个数上\n1 through n.\n\n179\n00:09:59,100 --> 00:10:01,088\n我想把其中的一些值收集成一个表\nAnd then I want to collect together in a list\n\n180\n00:10:01,280 --> 00:10:04,656\n那些满足某种属性的函数值\nall those function values that satisfy some property.\n\n181\n00:10:05,600 --> 00:10:06,880\n这是种一般性的说法\nThat's a general kind of thing.\n\n182\n00:10:06,880 --> 00:10:07,984\n说得更具体一点\nLet's say to be specific,\n\n183\n00:10:08,624 --> 00:10:10,480\n假设对于每个整数K\nlet's imagine that for each integer, k,\n\n184\n00:10:10,656 --> 00:10:12,512\n计算第K个斐波那契数\nwe're going to compute the k Fibonacci number.\n\n185\n00:10:14,210 --> 00:10:16,272\n然后挑出其中的奇数\nAnd then we'll see which of those are odd\n\n186\n00:10:16,832 --> 00:10:18,400\n并把它们组成一个表\nand assemble those into a list.\n\n187\n00:10:19,050 --> 00:10:20,710\n这个过程是这样的\nSo here's a procedure that does that.\n\n188\n00:10:23,730 --> 00:10:26,240\n寻找前N个斐波那契数中的奇数\nFind the odd Fibonacci numbers among the first n.\n\n189\n00:10:26,240 --> 00:10:28,910\n这里是我们一直以来采用的循环方法\nAnd here is a standard loop the way we've been writing it.\n\n190\n00:10:28,910 --> 00:10:29,824\n用到了递归\nThis is a recursion.\n\n191\n00:10:30,800 --> 00:10:31,792\n以K为循环变量\nIt's a loop on k,\n\n192\n00:10:32,032 --> 00:10:34,352\n如果K大于N 返回空表\nand says if k is bigger than n, it's the empty list.\n\n193\n00:10:35,136 --> 00:10:37,360\n否则计算第K个斐波那契数\nOtherwise we compute the k-th Fibonacci number,\n\n194\n00:10:37,440 --> 00:10:38,064\n将其与变量F绑定\ncall that f.\n\n195\n00:10:40,370 --> 00:10:42,848\n如果是奇数 我们把它与\nIf it's odd, we CONS it on\n\n196\n00:10:43,760 --> 00:10:46,010\n从K+1计算得到的表相连接\nto the list starting with the next one.\n\n197\n00:10:47,690 --> 00:10:50,128\n否则 我们只取从K+1计算得到的结果\nAnd otherwise, we just take the next one.\n\n198\n00:10:50,736 --> 00:10:53,000\n这是迭代式循环的标准写法\nAnd this is the standard way we've been writing iterative loops.\n\n199\n00:10:53,000 --> 00:10:55,568\n我们以1为初值 启动这个循环\nAnd we start off calling that loop with 1.\n\n200\n00:10:57,584 --> 00:11:00,064\n好的 就是这两个过程\nOK, so there are two procedures.\n\n201\n00:11:01,600 --> 00:11:02,900\n它们看起来非常不同\nThose procedures look very different.\n\n202\n00:11:02,900 --> 00:11:04,208\n完全不同的结构\nThey have very different structures.\n\n203\n00:11:04,250 --> 00:11:06,896\n然而 从一个特定的角度来看\nYet from a certain point of view,\n\n204\n00:11:06,928 --> 00:11:09,616\n两个过程做的事情是一样的\nthose procedures are really doing very much the same thing.\n\n205\n00:11:11,330 --> 00:11:14,672\n如果我是一个信号处理工程师\nSo if I was talking like a signal processing engineer,\n\n206\n00:11:14,704 --> 00:11:16,816\n我可能会说\nwhat I might say\n\n207\n00:11:18,240 --> 00:11:26,768\n第一个过程枚举了树的叶节点\nthe first procedure enumerates the leaves of a tree.\n\n208\n00:11:31,160 --> 00:11:34,560\n可以认为是信号从一个全是叶节点的地方输出\nAnd then we can think of a signal coming out of that, which is all the leaves.\n\n209\n00:11:35,330 --> 00:11:43,392\n我们想要过滤出其中的奇数\nWe'll filter them to see which ones are odd,\n\n210\n00:11:43,584 --> 00:11:44,944\n把它们放入某种滤波器中\nput them through some kind of filter.\n\n211\n00:11:45,190 --> 00:11:47,792\n然后再把它们放入某种换能器\nWe'll then put them through a kind of transducer.\n\n212\n00:11:49,200 --> 00:11:51,696\n对每一个输出 我们对其取平方\nAnd for each one of those things, we'll take the square.\n\n213\n00:11:54,448 --> 00:11:57,440\n最后把结果累积在一起\nAnd then we'll accumulate all of those.\n\n214\n00:11:58,290 --> 00:12:00,048\n我们以0为初值\nWe'll accumulate them by sticking them together\n\n215\n00:12:00,352 --> 00:12:03,370\n通过加法把它们累积起来\nwith addition starting from 0.\n\n216\n00:12:07,140 --> 00:12:08,210\n这是第一个程序\nThat's the first program.\n\n217\n00:12:08,210 --> 00:12:09,184\n对于第二个程序\nThe second program,\n\n218\n00:12:09,248 --> 00:12:11,216\n我也可以用一种非常类似的方法来描述\nI can describe in a very, very similar way.\n\n219\n00:12:11,780 --> 00:12:13,424\n我们枚举\nI'll say, we'll enumerate\n\n220\n00:12:15,808 --> 00:12:19,104\n从1到N这个区间上的数\nthe numbers on this interval, for the interval 1 through n.\n\n221\n00:12:22,500 --> 00:12:24,400\n对于每个数\nWe'll, for each one,\n\n222\n00:12:25,456 --> 00:12:26,928\n计算对应的斐波那契数\ncompute the Fibonacci number,\n\n223\n00:12:27,792 --> 00:12:29,270\n再放入一个换能器\nput them through a transducer.\n\n224\n00:12:29,270 --> 00:12:30,784\n对于输出的结果\nWe'll then take the result of that,\n\n225\n00:12:31,312 --> 00:12:34,208\n再通过奇偶性进行过滤\nand we'll filter it for oddness.\n\n226\n00:12:36,272 --> 00:12:39,248\n最后 我们将这些放入累积函数\nAnd then we'll take those and put them into an accumulator.\n\n227\n00:12:39,350 --> 00:12:40,560\n这次我们要累积出一个表\nThis time we'll build up a list,\n\n228\n00:12:40,784 --> 00:12:42,176\n所以我们用CONS来做积累\nso we'll accumulate with CONS\n\n229\n00:12:42,592 --> 00:12:43,776\n以空表为初始值\nstarting from the empty list.\n\n230\n00:12:47,110 --> 00:12:49,808\n从这个角度来看\nSo this way of looking at the program\n\n231\n00:12:49,856 --> 00:12:51,840\n这两个程序真的是太相似了\nmakes the two seem very, very similar.\n\n232\n00:12:51,900 --> 00:12:52,848\n问题在于\nThe problem is\n\n233\n00:12:53,200 --> 00:12:56,496\n两个程序的写法导致\nthat that commonality is completely obscured\n\n234\n00:12:56,640 --> 00:12:58,050\n我们看不出其中的共性\nwhen we look at the procedures we wrote.\n\n235\n00:12:58,050 --> 00:13:01,440\n再回头来看奇数平方和的问题\nLet's go back and look at some odd squares again,\n\n236\n00:13:02,224 --> 00:13:04,640\n问题来了 哪个是枚举函数呢？\nand say things like, where's the enumerator?\n\n237\n00:13:06,352 --> 00:13:08,140\n程序中哪一部分有枚举的作用？\nWhere's the enumerator in this program?\n\n238\n00:13:08,140 --> 00:13:10,528\n枚举不是仅仅在一个地方表现出来的\nWell, it's not in one place.\n\n239\n00:13:11,020 --> 00:13:15,472\n在叶子节点的判断处存在一部分\nIt's a little bit in this leaf-node test,\n\n240\n00:13:16,432 --> 00:13:17,160\n在这个判断循环终止的地方\nwhich is going to stop.\n\n241\n00:13:17,160 --> 00:13:20,064\n也下面的递归结构中也有体现\nIt's a little bit in the recursive structure of the thing itself.\n\n242\n00:13:23,150 --> 00:13:24,120\n累积函数又在哪儿呢？\nWhere's the accumulator?\n\n243\n00:13:24,120 --> 00:13:25,680\n它也不只在一个地方\nThe accumulator isn't in one place either.\n\n244\n00:13:25,680 --> 00:13:30,736\n它在 0 和 + 这两个地方分别体现出来\nIt's partly in this 0 and partly in this plus.\n\n245\n00:13:32,000 --> 00:13:34,510\n累积函数分散在过程的每个部分\nRight? It's not there as a thing that we can look at.\n\n246\n00:13:34,510 --> 00:13:39,056\n相似地 我们来观察奇数斐波那契数的例子\nSimilarly, if we look at odd Fibs,\n\n247\n00:13:39,050 --> 00:13:42,800\n某种意义上 程序中也存在枚举函数与累积函数\nthat's also, in some sense, an enumerator and an accumulator,\n\n248\n00:13:42,800 --> 00:13:44,016\n但看起来非常不同\nbut it looks very different.\n\n249\n00:13:44,624 --> 00:13:50,096\n枚举部分地表现在(> k n)的判断中\nBecause partly, the enumerator is here in this greater than sign in the test.\n\n250\n00:13:50,384 --> 00:13:52,848\n部分地表现在下面的递归调用中\nAnd partly it's in this whole recursive structure in the loop,\n\n251\n00:13:53,184 --> 00:13:54,240\n还有就是启动循环的地方\nand the way that we call it.\n\n252\n00:13:55,680 --> 00:13:56,320\n同样地\nAnd then similarly,\n\n253\n00:13:56,528 --> 00:13:58,768\n其中也混杂了累积函数\nthat's also mixed up in there with the accumulator,\n\n254\n00:13:58,912 --> 00:14:00,128\n分别在这里\nwhich is partly over there\n\n255\n00:14:00,416 --> 00:14:01,408\n和这里\nand partly over there.\n\n256\n00:14:03,600 --> 00:14:06,080\n所以这些非常自然的部分\nSo these very, very natural pieces,\n\n257\n00:14:08,736 --> 00:14:12,656\n我们之前画的那些方框在程序中完全看不出来\nthese very natural boxes here don't appear in our programs.\n\n258\n00:14:13,264 --> 00:14:14,360\n因为它们混杂在一起了\nBecause they're kind of mixed up.\n\n259\n00:14:14,360 --> 00:14:16,290\n这些程序并没有很好地对问题进行切分\nThe programs don't chop things up in the right way.\n\n260\n00:14:19,450 --> 00:14:22,176\n回到计算机科学的基本原理上来\nGoing back to this fundamental principle of computer science\n\n261\n00:14:22,192 --> 00:14:23,632\n为了控制某种东西\nthat in order to control something,\n\n262\n00:14:23,632 --> 00:14:24,960\n你需要它的名字\nyou need the name of it,\n\n263\n00:14:25,808 --> 00:14:28,448\n我们还没有很好地掌握按这种方式来思考\nwe don't really have control over thinking about things this way\n\n264\n00:14:28,672 --> 00:14:31,060\n这是因为我们没有显式地操作它们的手段\nbecause we don't have our hands in them explicitly.\n\n265\n00:14:31,060 --> 00:14:33,808\n我们没有一门好的语言来讨论它们\nWe don't have a good language for talking about them.\n\n266\n00:14:35,420 --> 00:14:38,864\n好吧 我们来创造一门合适的语言\nWell, let's invent an appropriate language\n\n267\n00:14:42,528 --> 00:14:44,048\n用它来构建这些器件\nin which we can build these pieces.\n\n268\n00:14:44,784 --> 00:14:47,216\n这种语言的关键在于\nThe key to the language is these guys,\n\n269\n00:14:47,216 --> 00:14:49,712\n这些叫作信号的东西到底是什么？\nis what is these things I called signals?\n\n270\n00:14:50,480 --> 00:14:53,320\n这些沿着箭头传递的是什么？\nWhat are these things that are flying on the arrows between the boxes?\n\n271\n00:14:56,880 --> 00:14:57,712\n这些东西\nWell, those things\n\n272\n00:14:59,856 --> 00:15:03,520\n是一种称作“流”的数据结构\nare going to be data structures called streams.\n\n273\n00:15:03,792 --> 00:15:05,872\n这也是发明这门语言的关键\nThat's going to be the key to inventing this language.\n\n274\n00:15:07,980 --> 00:15:08,512\n“流”是什么东西呢？\nWhat's a stream?\n\n275\n00:15:08,528 --> 00:15:11,504\n和其它的东西一样 “流”是一种数据抽象\nWell, a stream is, like anything else, a data abstraction.\n\n276\n00:15:12,220 --> 00:15:15,824\n所以 我先说明它的选择函数与构造函数分别是什么\nSo I should tell you what its selectors and constructors are.\n\n277\n00:15:16,870 --> 00:15:19,488\n对于流结构 我们有一个构造函数\nFor a stream, we're going to have one constructor\n\n278\n00:15:19,984 --> 00:15:21,430\n我们称其为CONS-STREAM\nthat's called CONS-stream.\n\n279\n00:15:25,690 --> 00:15:28,112\nCONS-STREAM把两个事物放在一起\nCONS-stream is going to put two things together\n\n280\n00:15:28,592 --> 00:15:30,220\n构造出一个流\nto form a thing called a stream.\n\n281\n00:15:32,040 --> 00:15:33,856\n选择函数叫作HEAD\nAnd then to extract things from the stream,\n\n282\n00:15:33,984 --> 00:15:36,112\n用于从流中提取数据\nwe're going to have a selector called the head of the stream.\n\n283\n00:15:38,010 --> 00:15:38,864\n如果我有一个流\nSo if I have a stream,\n\n284\n00:15:39,008 --> 00:15:40,416\n我可以取它的头部\nI can take its head\n\n285\n00:15:41,136 --> 00:15:42,384\n也可以取它的尾部\nor I can take its tail.\n\n286\n00:15:44,720 --> 00:15:47,424\n我把和George的约定告诉你\nAnd remember, I have to tell you George's contract\n\n287\n00:15:48,240 --> 00:15:52,704\n让你们知道和这个相关的公理\nto tell you what the axioms are that relate these.\n\n288\n00:15:53,440 --> 00:16:00,176\n对于任何的X与Y\nAnd it's going to be for any x and y,\n\n289\n00:16:03,408 --> 00:16:05,440\n如果我把它们构造成一个流 并取其头部\nif I form the CONS-stream and take the head,\n\n290\n00:16:05,696 --> 00:16:11,968\n(HEAD (CONS-STREAM X Y))\nthe head of CONS-stream of x and y\n\n291\n00:16:13,296 --> 00:16:14,528\n结果就是X\nis going to be x\n\n292\n00:16:16,144 --> 00:16:27,456\n(TAIL (CONS-STREAM X Y)) = Y\nand the tail of CONS-stream of x and y is going to be y.\n\n293\n00:16:28,440 --> 00:16:34,750\n一个构造函数 两个选择函数 一个公理 就是这些\nSo those are the constructor, two selectors for streams, and an axiom.\n\n294\n00:16:34,750 --> 00:16:35,856\n这里有点可疑\nThere's something fishy here.\n\n295\n00:16:36,980 --> 00:16:39,008\n你可能注意到了\nSo you might notice that these are exactly\n\n296\n00:16:40,192 --> 00:16:42,080\n这些就是CONS、CAR和CDR的公理\nthe axioms for CONS, CAR, and CDR.\n\n297\n00:16:43,632 --> 00:16:46,560\n把CONS-STREAM换成CONS\nSo if I said instead of writing CONS-stream I wrote CONS\n\n298\n00:16:47,104 --> 00:16:49,808\nHEAD换成CAR TAIL换成CDR\nand I said head was the CAR and tail was the CDR,\n\n299\n00:16:50,768 --> 00:16:52,810\n这些就是序对的公理\nthose are exactly the axioms for pairs.\n\n300\n00:16:52,810 --> 00:16:54,320\n事实上 还有另一个东西\nAnd in fact, there's another thing here.\n\n301\n00:16:55,130 --> 00:16:56,800\n我们有一个叫THE-EMPTY-STREAM（空流）的东西\nWe're going to have a thing called the-empty-stream\n\n302\n00:17:02,800 --> 00:17:04,048\n像空表一样\nwhich is like the-empty-list.\n\n303\n00:17:08,319 --> 00:17:10,030\n为什么我要引入这个术语呢？\nSo why am I introducing this terminology?\n\n304\n00:17:10,030 --> 00:17:12,128\n为什么我不继续使用序对与表呢？\nWhy don't I just keep talking about pairs and lists?\n\n305\n00:17:12,780 --> 00:17:13,792\n后面我们就知道了\nWell, we'll see.\n\n306\n00:17:15,510 --> 00:17:18,240\n暂时地 你们可以把术语“流”\nFor now, if you like, why don't you just pretend\n\n307\n00:17:18,304 --> 00:17:21,560\n当作“表”的另一种说法\nthat streams really are just a terminology for lists.\n\n308\n00:17:21,560 --> 00:17:22,992\n一会儿我们就会知道 为什么\nAnd we'll see in a little while why\n\n309\n00:17:23,616 --> 00:17:26,096\n为什么我们需要这个额外的抽象层\nwhy we want to keep this extra abstraction layer\n\n310\n00:17:26,832 --> 00:17:28,150\n而不是继续把它看做表\nand not just call them lists.\n\n311\n00:17:32,300 --> 00:17:33,728\n好的 有了流之后\nOK, now that we have streams,\n\n312\n00:17:33,744 --> 00:17:35,856\n我们就开始构建语言的部件了\nwe can start constructing the pieces of the language\n\n313\n00:17:37,040 --> 00:17:38,176\n用它来操作流\nto operate on streams.\n\n314\n00:17:38,752 --> 00:17:42,120\n我们可以构建出太多有用的东西了\nAnd there are a whole bunch of very useful things that we could start making.\n\n315\n00:17:42,120 --> 00:17:42,816\n举例来说\nFor instance,\n\n316\n00:17:44,890 --> 00:17:49,792\n我们构建MAP-STREAM 它的一个参数是流S\nwe'll make our map box to take a stream, s,\n\n317\n00:17:54,800 --> 00:17:56,624\n以及一个过程\nand a procedure,\n\n318\n00:17:57,808 --> 00:17:59,216\n它会生成一个新的流\nand to generate a new stream\n\n319\n00:18:00,140 --> 00:18:02,288\n它的构成元素是\nwhich has as its elements\n\n320\n00:18:02,288 --> 00:18:04,880\n将PROC应用到S的后续元素得到的结果\nthe procedure applied to all the successive elements of s.\n\n321\n00:18:05,872 --> 00:18:07,400\n我们以前见过类似的\nIn fact, we've seen this before.\n\n322\n00:18:07,400 --> 00:18:10,240\n就是以前在表上定义的MAP过程\nThis is the procedure map that we did with lists.\n\n323\n00:18:10,950 --> 00:18:12,608\n除了判断EMPTY-STREAM的部分\nAnd you see it's exactly map,\n\n324\n00:18:12,608 --> 00:18:14,650\n完全就和MAP一样\nexcept we're testing for empty-stream.\n\n325\n00:18:14,650 --> 00:18:15,560\n哦 我忘了说了\nOh, I forgot to mention that.\n\n326\n00:18:15,560 --> 00:18:17,152\nEMPTY-STREAM?就和NULL?差不多\nEmpty-stream is like the null test.\n\n327\n00:18:18,030 --> 00:18:20,480\n如果是空的 就返回一个空的流\nSo if it's empty, we generate the empty stream.\n\n328\n00:18:20,510 --> 00:18:22,288\n否则 就生成一个新的流\nOtherwise, we form a new stream\n\n329\n00:18:23,520 --> 00:18:27,184\n其第一个元素是PROC应用在流头部的结果\nwhose first element is the procedure applied to the head of the stream,\n\n330\n00:18:28,512 --> 00:18:29,328\n剩下的是\nand whose rest\n\n331\n00:18:29,600 --> 00:18:32,432\n是MAP-STREAM对流尾部应用的结果\nis gotten by mapping along with the procedure down the tail of the stream.\n\n332\n00:18:33,140 --> 00:18:35,904\n太像我们之前讲的MAP了\nSo that looks exactly like the map procedure we looked at before.\n\n333\n00:18:37,030 --> 00:18:38,208\n还有一个有用的函数\nHere's another useful thing.\n\n334\n00:18:38,350 --> 00:18:40,460\n过滤函数 就是那个用来过滤的盒子\nFilter, this is our filter box.\n\n335\n00:18:40,460 --> 00:18:43,890\n以一个谓词和一个流作为参数\nWe're going to have a predicate and a stream.\n\n336\n00:18:43,890 --> 00:18:45,088\n它将生成一个新的流\nWe're going to make a new stream\n\n337\n00:18:45,808 --> 00:18:48,176\n包含了在流S中所有\nconsists of all the elements of the original one that satisfy the predicate.\n\n338\n00:18:48,336 --> 00:18:49,488\n满足谓词PRED的元素\nthat satisfy the predicate.\n\n339\n00:18:50,384 --> 00:18:51,312\n这是一个“按条件分析语句”\nThat's case analysis.\n\n340\n00:18:51,320 --> 00:18:52,736\n如果流是空的\nWhen there's nothing in the stream,\n\n341\n00:18:53,040 --> 00:18:54,220\n就返回一个空流\nwe return the empty stream.\n\n342\n00:18:56,280 --> 00:18:59,184\n这里 用谓词来判断流的头元素\nWe test the predicate on the head of the stream.\n\n343\n00:19:00,060 --> 00:19:01,040\n如果为真\nAnd if it's true,\n\n344\n00:19:01,530 --> 00:19:02,832\n就把这个元素\nwe add the head of the stream onto the result\n\n345\n00:19:03,024 --> 00:19:06,220\n和过滤流的尾元素得到的结果连接在一起\nthe result of filtering the tail of the stream.\n\n346\n00:19:08,220 --> 00:19:10,048\n否则 如果谓词判断为假\nAnd otherwise, if that predicate was false,\n\n347\n00:19:10,496 --> 00:19:11,984\n就只返回过滤流的尾元素的结果\nwe just filter the tail of the stream.\n\n348\n00:19:13,500 --> 00:19:14,464\n这就是过滤函数的原理\nRight, so there's filter.\n\n349\n00:19:16,595 --> 00:19:18,560\n剩下的我快速过一遍\nLet me run through a couple more rather quickly.\n\n350\n00:19:18,560 --> 00:19:20,704\n这些在书上都有 你们可以自己看\nThey're all in the book and you can look at them.\n\n351\n00:19:20,880 --> 00:19:21,808\n来马上过一遍\nLet me just flash through.\n\n352\n00:19:22,110 --> 00:19:22,944\n过程ACCUMULATE\nHere's accumulate.\n\n353\n00:19:23,260 --> 00:19:26,928\nACCUMULATE的参数有：一个组合函数\nAccumulate takes a way of combining things\n\n354\n00:19:27,360 --> 00:19:29,056\n一个初始值和一个流\nan initial value in a stream\n\n355\n00:19:29,968 --> 00:19:31,136\n将它们组合在一起\nand sticks them all together.\n\n356\n00:19:31,560 --> 00:19:33,696\n如果流为空 返回初始值\nIf the stream's empty, it's just the initial value.\n\n357\n00:19:33,970 --> 00:19:36,208\n否则 我们就把流头部\nOtherwise, we combine the head of the stream\n\n358\n00:19:36,320 --> 00:19:37,824\n和流尾部做ACCUMLATE的结果\nwith the result of accumulating\n\n359\n00:19:38,016 --> 00:19:40,240\n组合起来\nthe tail of the stream starting from the initial value.\n\n360\n00:19:40,900 --> 00:19:42,830\n这就是把流中元素累积在一起的方法\nSo that's what I'd use to add up everything in the stream.\n\n361\n00:19:42,830 --> 00:19:43,984\n我会用加法来累积\nI'd accumulate with plus.\n\n362\n00:19:45,830 --> 00:19:47,568\n如何枚举树上的叶节点呢？\nHow would I enumerate the leaves of a tree?\n\n363\n00:19:48,060 --> 00:19:52,896\n如果这个树只是一个叶节点\nWell, if the tree is just a leaf itself,\n\n364\n00:19:53,792 --> 00:19:55,904\n我就构造一个只含有一个叶子节点的流\nI make something which only has that node in it.\n\n365\n00:19:56,640 --> 00:19:59,328\n否则的话 我就把\nOtherwise, I append together the stuff of enumerating\n\n366\n00:19:59,616 --> 00:20:02,352\n左、右子树枚举的结果合并起来\nthe left branch and the right branch.\n\n367\n00:20:04,340 --> 00:20:08,320\n这里的APPEND-STREAM跟表上的APPEND类似\nAnd then append here is like the ordinary append on lists.\n\n368\n00:20:13,190 --> 00:20:13,850\n再来看这个\nYou can look at that.\n\n369\n00:20:13,850 --> 00:20:17,536\n这跟和合并两个表的过程太相似了\nThat's analogous to the ordinary procedure for appending two lists.\n\n370\n00:20:18,912 --> 00:20:20,608\n如何枚举一个区间呢？\nAh... How would I enumerate an interval?\n\n371\n00:20:21,968 --> 00:20:23,776\n它有两个参数 LOW和HIGH\nThis will take two integers, low and high,\n\n372\n00:20:23,880 --> 00:20:27,008\n生成一个包含从LOW到HIGH的所有整数的流\nand generate a stream of the integers going from low to high.\n\n373\n00:20:28,320 --> 00:20:29,888\n由此 我们就可以构造一大堆的元件\nAnd we can make a whole bunch of pieces.\n\n374\n00:20:31,890 --> 00:20:34,480\n这就是一门用来讨论流的小型语言\nSo that's a little language of talking about streams.\n\n375\n00:20:34,490 --> 00:20:35,328\n当我们有了流\nOnce we have streams,\n\n376\n00:20:35,328 --> 00:20:37,670\n就可以构建用于操作它们的过程\nwe can build things for manipulating them.\n\n377\n00:20:37,670 --> 00:20:39,040\n请注意 我们正在构建一门语言\nAgain, we're making a language.\n\n378\n00:20:40,200 --> 00:20:42,224\n现在 我们可以用这门语言来表达我们的想法\nAnd now we can start expressing things in this language.\n\n379\n00:20:43,060 --> 00:20:47,310\n这个原始过程是累加树中奇数的平方的\nHere's our original procedure for summing the odd squares in a tree.\n\n380\n00:20:47,310 --> 00:20:52,624\n现在你会发现 它和那些方块图如出一辙\nAnd you'll notice it looks exactly now like the block diagram,\n\n381\n00:20:52,640 --> 00:20:54,590\n跟我们的信号处理方块图相吻合\nlike the signal processing block diagram.\n\n382\n00:20:54,590 --> 00:20:57,536\n要计算树上奇数平方和\nSo to sum the odd squares in a tree,\n\n383\n00:20:58,064 --> 00:21:00,800\n先枚举树上的叶子节点\nwe enumerate the leaves of the tree.\n\n384\n00:21:01,320 --> 00:21:03,728\n过滤出奇数\nWe filter that for oddness.\n\n385\n00:21:04,830 --> 00:21:06,544\n再用平方来做映射\nWe map that for squareness.\n\n386\n00:21:09,320 --> 00:21:13,344\n最后用加法来累积 初始值是0\nAnd we accumulate the result of that using addition, starting from 0.\n\n387\n00:21:14,760 --> 00:21:17,200\n这样我们就可以看到需要的片段\nSo we can see the pieces that we wanted.\n\n388\n00:21:17,290 --> 00:21:19,360\n类似地 斐波那契数的那个问题\nSimilarly, the Fibonacci one,\n\n389\n00:21:20,048 --> 00:21:21,888\n我们如何获得奇斐波那契数呢？\nhow do we get the odd Fibs?\n\n390\n00:21:22,050 --> 00:21:24,576\n从1到N枚举整数\nWell, we enumerate the interval from 1 to n,\n\n391\n00:21:26,320 --> 00:21:28,640\n再把FIB过程映射到上面\nwe map along that,\n\n392\n00:21:28,992 --> 00:21:30,704\n用来求取每项斐波那契数\ncomputing the Fibonacci of each one.\n\n393\n00:21:30,920 --> 00:21:33,792\n过滤出奇数的部分\nWe filter the result of those for oddness.\n\n394\n00:21:34,810 --> 00:21:36,640\n最后 以空表为初始值\nAnd we accumulate all of that stuff\n\n395\n00:21:36,880 --> 00:21:39,120\n用CONS将它们积累起来\nusing CONS starting from the empty-list.\n\n396\n00:21:43,650 --> 00:21:47,536\n那么 这么做有什么优势呢？\nOK, what's the advantage of this?\n\n397\n00:21:47,680 --> 00:21:48,592\n首先一点\nWell, for one thing,\n\n398\n00:21:48,688 --> 00:21:51,152\n我们现在有可以用来混搭的元件了\nwe now have pieces that we can start mixing and matching.\n\n399\n00:21:51,880 --> 00:21:52,640\n比如说\nSo for instance,\n\n400\n00:21:52,912 --> 00:21:55,088\n如果我想把这里改变一下\nif I wanted to change this, if I wanted to ah...\n\n401\n00:21:58,192 --> 00:22:00,320\n想要计算整数的平方再进行过滤\ncompute the squares of the integers and then filter them,\n\n402\n00:22:00,336 --> 00:22:01,344\n我只需要\nall I need to do\n\n403\n00:22:01,904 --> 00:22:03,648\n拿个像这里的MAP SQUARE这样的元件\nis pick up a standard piece like this\n\n404\n00:22:03,680 --> 00:22:05,408\n放进去就行了\nit's a map square and put it in.\n\n405\n00:22:06,576 --> 00:22:07,600\n又或者 如果我们想\nOr if we wanted to do\n\n406\n00:22:07,690 --> 00:22:11,456\n寻找树的叶节点对应的斐波那契数\nthis whole Fibonacci computation on the leaves of a tree\n\n407\n00:22:11,584 --> 00:22:12,360\n而不是一个序列所对应的\nrather than a sequence,\n\n408\n00:22:12,384 --> 00:22:13,248\n我只需要\nall I need to do\n\n409\n00:22:13,408 --> 00:22:15,936\n用这个枚举函数替换这个枚举函数\nis replace this enumerator with that one.\n\n410\n00:22:18,030 --> 00:22:19,824\n看到了吧 流处理的优势就是\nSee, the advantage of this stream processing\n\n411\n00:22:20,240 --> 00:22:21,536\n我们建立了 --\nis that we're establishing--\n\n412\n00:22:22,368 --> 00:22:24,960\n这也是本课中的一个重要主题 --\nthis is one of the big themes of the course--\n\n413\n00:22:25,296 --> 00:22:27,488\n我们建立了一个约定的接口\nwe're establishing conventional interfaces\n\n414\n00:22:32,896 --> 00:22:37,152\n约定的接口可以让我们把事物粘合起来\nconventional interfaces that allow us to glue things together.\n\n415\n00:22:38,304 --> 00:22:39,552\n像MAP和FILTER这样的东西\nThings like map and filter\n\n416\n00:22:39,792 --> 00:22:41,648\n可以作为一组标准的组件\nare a standard set of components\n\n417\n00:22:41,680 --> 00:22:44,768\n我们可以拿过来随意组合去构造程序\nthat we can start using for pasting together programs in all sorts of ways.\n\n418\n00:22:45,750 --> 00:22:48,816\n它让我们看到了程序的共性\nIt allows us to see the commonality of programs.\n\n419\n00:22:49,950 --> 00:22:50,928\n虽然在这里\nI just ought to mention,\n\n420\n00:22:51,088 --> 00:22:53,070\n我只是给你们演示了两个过程而已\nI've only showed you two procedures.\n\n421\n00:22:53,860 --> 00:22:55,168\n但是我要告诉你\nBut let me emphasize\n\n422\n00:22:55,200 --> 00:22:57,776\n像这种用MAP、FILTER和ACCUMULATE\nthat this way of putting things together\n\n423\n00:22:57,808 --> 00:23:01,008\n组合起来构建程序的方式是非常非常通用的\nwith maps, filters, and accumulators is very, very general.\n\n424\n00:23:01,410 --> 00:23:07,280\n这是一种“生成-测试”的编程范式\nIt's the generate and test paradigm for programs.\n\n425\n00:23:07,770 --> 00:23:09,104\n举例来看\nAnd as an example of that,\n\n426\n00:23:09,392 --> 00:23:12,940\nRicharc Waters -- MIT的一名硕士生\nRichard Waters, who was at MIT when he was a graduate student,\n\n427\n00:23:12,960 --> 00:23:15,264\n他的学位论文的一部分调研了\nas part of his thesis research went and analyzed\n\n428\n00:23:15,808 --> 00:23:19,210\nIBM的科学计算程序库的主要代码\na large chunk of the IBM scientific subroutine library,\n\n429\n00:23:19,824 --> 00:23:23,312\n发现其中60%的程序\nand discovered that about 60% of the programs in it\n\n430\n00:23:24,064 --> 00:23:28,256\n都可以用这样的范式来准确的表示出来\ncould be expressed exactly in terms using no more than what we've put here--\n\n431\n00:23:28,864 --> 00:23:30,176\n只用MAP、FILTER和ACCUMULATE\nmap, filter, and accumulate.\n\n432\n00:23:30,576 --> 00:23:31,504\n好 让我们休息一会\nAll right, let's take a break.\n\n433\n00:23:36,592 --> 00:23:37,120\n有问题吗？\nQuestions?\n\n434\n00:23:41,184 --> 00:23:42,896\n学生：整件事情的本质好像只是\nAUDIENCE: It seems like the essence of this whole thing\n\n435\n00:23:42,896 --> 00:23:45,968\n因为你用了一个统一、简单的数据结构\nis just that you have a very uniform, simple data structure\n\n436\n00:23:46,256 --> 00:23:47,664\n也就是流\nto work with, the stream.\n\n437\n00:23:48,380 --> 00:23:48,920\n教授：对\nPROFESSOR: Right.\n\n438\n00:23:48,920 --> 00:23:50,384\n本质就是\nThe essence is that you, again,\n\n439\n00:23:50,400 --> 00:23:53,070\n用这种约定的接口\nit's this sense of conventional interfaces.\n\n440\n00:23:53,710 --> 00:23:55,610\n因此你可以把许多东西组合起来\nSo you can start putting a lot of things together.\n\n441\n00:23:56,010 --> 00:23:58,784\n流只是 就像你说的\nAnd the stream is as you say,\n\n442\n00:23:58,784 --> 00:24:00,890\n只是一种可以支持那样操作的统一的数据结构而已\nthe uniform data structure that supports that.\n\n443\n00:24:00,890 --> 00:24:02,848\n顺便说下 这非常像APL\nThis is very much like APL, by the way.\n\n444\n00:24:03,600 --> 00:24:05,216\nAPL有着非常相似的思想\nAPL is very much the same idea,\n\n445\n00:24:05,216 --> 00:24:06,960\n只是在APL中使用的不是流\nexcept in APL, instead of this stream,\n\n446\n00:24:07,136 --> 00:24:08,448\n而是使用数组和向量\nyou have arrays and vectors.\n\n447\n00:24:09,560 --> 00:24:14,480\n而且APL的威力就在于此\nAnd a lot of the power of APL is exactly the same reason of the power of this.\n\n448\n00:24:19,910 --> 00:24:20,910\n好吧 谢谢\nOK, thank you.\n\n449\n00:24:20,910 --> 00:24:21,664\n休息一下\nLet's take a break.\n\n450\n00:24:21,660 --> 00:24:30,352\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n451\n00:24:30,440 --> 00:24:35,776\n《计算机程序的构造和解释》\n\n452\n00:24:41,000 --> 00:24:45,392\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n453\n00:24:45,420 --> 00:24:47,960\n《计算机程序的构造和解释》\n\n454\n00:24:47,980 --> 00:24:52,700\n流 I\n\n455\n00:24:57,470 --> 00:24:57,610\n好的\nAll right.\n\n456\n00:24:57,610 --> 00:24:58,592\n我们已经见识过了\nWe've been looking at\n\n457\n00:25:00,544 --> 00:25:03,200\n如何用流来组织计算过程\nat ways of organizing computations using streams.\n\n458\n00:25:03,856 --> 00:25:05,472\n但是现在我想要给你们再演示两个\nBut what I want to do now is just show you two\n\n459\n00:25:05,936 --> 00:25:09,120\n更复杂的例子\nsomewhat more complicated examples of that.\n\n460\n00:25:10,848 --> 00:25:14,128\n我们先来考虑一下\nLet's start by thinking about the following\n\n461\n00:25:14,208 --> 00:25:16,810\n这样一种有用的过程\nkind of utility procedure that will come in useful.\n\n462\n00:25:16,810 --> 00:25:18,096\n假设我有一个流\nSuppose I've got a stream.\n\n463\n00:25:19,960 --> 00:25:23,152\n流中的元素本身就是一个流\nAnd the elements of this stream are themselves streams.\n\n464\n00:25:23,984 --> 00:25:26,530\n一开始是1、2、3\nSo the first thing might be 1, 2, 3.\n\n465\n00:25:32,720 --> 00:25:33,880\n就是这样的一个流\nSo I've got a stream.\n\n466\n00:25:33,880 --> 00:25:40,100\n流中的元素也是一个流\nAnd each element of the stream is itself a stream.\n\n467\n00:25:40,976 --> 00:25:43,424\n而我想要构建出一个流\nAnd what I'd like to do is build a stream\n\n468\n00:25:43,648 --> 00:25:46,752\n用来收集所有的元素\nthat sort of collects together all of the elements,\n\n469\n00:25:46,768 --> 00:25:49,248\n把所有元素从子流中提取出来\npulls all of the elements out of these sub-streams\n\n470\n00:25:50,112 --> 00:25:51,824\n最后把它们串接在一起\nand strings them all together in one thing.\n\n471\n00:25:52,272 --> 00:25:55,616\n为了凸显使用这门语言多么简单\nSo just to show you the use of this language, how easy it is,\n\n472\n00:25:56,112 --> 00:25:57,104\n我们来定义这个FLATTEN过程\ncall that flatten.\n\n473\n00:25:57,950 --> 00:26:10,640\nFLATTEN过程的参数是由流构成的流\nAnd I can define to flatten this stream of streams.\n\n474\n00:26:12,896 --> 00:26:13,808\n那么 具体定义是怎样的呢？\nWell, what is that?\n\n475\n00:26:13,960 --> 00:26:16,240\n它只是一个累积\nThat's just an accumulation.\n\n476\n00:26:16,320 --> 00:26:25,056\n我想用APPEND来做累积\nI want to accumulate using append,\n\n477\n00:26:25,072 --> 00:26:26,450\n也就是不断地做APPEND\nby successively appending.\n\n478\n00:26:26,736 --> 00:26:29,296\n所以我用APPEND-STREAM做累积\nSo I accumulate using append streams,\n\n479\n00:26:35,900 --> 00:26:48,208\n以THE-EMPTY-STREAM为初始值 累积这个流\nstarting with the-empty-stream down that stream of streams.\n\n480\n00:26:54,840 --> 00:26:55,840\n这个例子告诉我们\nOK, so there's an example of\n\n481\n00:26:56,928 --> 00:26:59,232\n你可以使用这些高阶过程\nhow you can start using these higher order things\n\n482\n00:26:59,600 --> 00:27:00,830\n来做一些有趣的运算\nto do some interesting operations.\n\n483\n00:27:00,830 --> 00:27:05,100\n事实上 我还想定义另一个实用过程\nIn fact, there's another useful thing that I want to do.\n\n484\n00:27:05,100 --> 00:27:07,056\n定义一个过程FLAT-MAP\nI want to define a procedure called flat-map,\n\n485\n00:27:17,184 --> 00:27:20,592\n它以一个过程和一个流为参数\nflat map of some function and a stream.\n\n486\n00:27:21,840 --> 00:27:25,720\n其中S是一个流\nAnd what this is going to do is s will be a stream of elements.\n\n487\n00:27:25,720 --> 00:27:27,696\nF是一个过程\nf is going to be a function\n\n488\n00:27:27,728 --> 00:27:30,624\n它作用于流中的每个元素 并产生一个新的流\nfor each element in the stream produces another stream.\n\n489\n00:27:31,950 --> 00:27:34,528\n我想从这些流中取出所有的元素\nAnd what I want to do is take all of the elements and all of those streams\n\n490\n00:27:35,008 --> 00:27:36,000\n并把它们组合在一起\nand combine them together.\n\n491\n00:27:36,000 --> 00:27:49,136\n所以对应的代码就是 (FLATTEN (MAP F S))\nSo that's just going to be the flatten of map f down s.\n\n492\n00:27:51,200 --> 00:27:53,040\n每当我将F应用在S的某个元素上\nEach time I apply f to an element of s,\n\n493\n00:27:53,056 --> 00:27:53,850\n我得到了一个流\nI get a stream.\n\n494\n00:27:54,290 --> 00:27:55,248\n执行完这条MAP语句后\nIf I map it all the way down,\n\n495\n00:27:55,248 --> 00:27:56,272\n我得到了一个由流构成的流\nI get a stream of streams,\n\n496\n00:27:56,464 --> 00:27:57,424\n再把它进行FLATTEN\nand I'll flatten that.\n\n497\n00:27:58,670 --> 00:28:02,640\n我想再使用这种方式\nWell, I want to use that to show you a\n\n498\n00:28:03,872 --> 00:28:05,840\n来解决另一个大家很熟悉的问题\na new way to do a familiar kind of problem.\n\n499\n00:28:06,512 --> 00:28:12,272\n这个问题和我们以前遇到过的许多问题一样\nThe problem's going to be like a lot of problems you've seen,\n\n500\n00:28:12,288 --> 00:28:13,968\n只是有些变型\nalthough maybe not this particular one.\n\n501\n00:28:14,190 --> 00:28:15,490\n给定整数N\nI'm going to give you an integer, n.\n\n502\n00:28:18,680 --> 00:28:19,936\n我们的问题是\nAnd the problem is going to be\n\n503\n00:28:21,200 --> 00:28:31,536\n找出所有的整数序对(I, J)\nfind all pairs and integers i and j,\n\n504\n00:28:32,300 --> 00:28:39,968\n其中 0 < J < I <= N\nbetween 0 and i, with j less than i, up to n,\n\n505\n00:28:42,336 --> 00:28:52,032\n使得 I+J 是一个质数\nsuch that i plus j is prime.\n\n506\n00:28:55,740 --> 00:28:57,920\n如果N=6\nSo for example, if n equals 6,\n\n507\n00:28:59,744 --> 00:29:00,784\n我在这儿画个小表格\nlet's make a little table here,\n\n508\n00:29:01,552 --> 00:29:06,672\n表头是I、J和I+J\ni and j and i plus j.\n\n509\n00:29:09,700 --> 00:29:14,912\n比如说I=2 J=1 那么I+J就是3\nSo for, say, i equals 2 and j equals 1, I'd get 3.\n\n510\n00:29:15,520 --> 00:29:20,384\n然后I=3 J=2 那么I+J就是5\nAnd for i equals 3, I could have j equals 2, and that would be 5.\n\n511\n00:29:21,210 --> 00:29:26,512\nI=4 J=1 I+J=5也是一样的 等等\nAnd 4 and 1 would be 5 and so on,\n\n512\n00:29:26,928 --> 00:29:28,112\n直到I到了6就终止了\nup until i goes to 6.\n\n513\n00:29:28,400 --> 00:29:32,544\n我想要这个过程产生并返回这样的一个流\nAnd what I'd like to return is to produce a stream\n\n514\n00:29:33,200 --> 00:29:37,040\n就是像 (I, J, I+J) 这样的三元组组成的流\nall the triples like this, let's say i, j, and i plus j.\n\n515\n00:29:37,664 --> 00:29:39,552\n对于每个整数N 我想得到一个这样流\nSo for each n, I want to generate this stream.\n\n516\n00:29:40,976 --> 00:29:43,680\n听起来很简单\nOK, well, that's easy.\n\n517\n00:29:43,680 --> 00:29:44,352\n我们做做看\nLet's build it up.\n\n518\n00:29:47,230 --> 00:29:48,224\n先这样开始\nWe start like this.\n\n519\n00:29:50,150 --> 00:29:54,256\n对于每一个整数 I\nWe're going to say for each i, for each i\n\n520\n00:29:55,248 --> 00:29:56,440\n生成一个流\nwe're going to generate a stream.\n\n521\n00:29:57,000 --> 00:29:58,592\n对于I从1取到N\nFor each i in the interval 1 through n,\n\n522\n00:29:58,592 --> 00:29:59,760\n每个I都生成一个流\nwe're going to generate a stream.\n\n523\n00:30:00,660 --> 00:30:01,808\n这个流将会是什么样子？\nWhat's that stream going to be?\n\n524\n00:30:02,230 --> 00:30:04,048\n我们先生成所有的序对\nWe're going to start by generating all the pairs.\n\n525\n00:30:04,180 --> 00:30:07,552\n对于每个I 我们先生成\nSo for each i, we're going to generate,\n\n526\n00:30:08,432 --> 00:30:14,528\n对于每个从1取到I-1的J\nfor each j in the interval 1 to i minus 1,\n\n527\n00:30:16,912 --> 00:30:17,984\n我们先生成序对\nwe'll generate the pair,\n\n528\n00:30:18,352 --> 00:30:20,710\n也就是只含有I和J的表\nor the list with two elements i and j.\n\n529\n00:30:23,780 --> 00:30:27,104\n因此我们对整个区间做映射\nSo we map along the interval,\n\n530\n00:30:28,608 --> 00:30:29,744\n生成序对\ngenerating the pairs.\n\n531\n00:30:31,072 --> 00:30:33,170\n对于每个I 都生成一个序对流\nAnd for each i, that generates a stream of pairs.\n\n532\n00:30:33,408 --> 00:30:34,496\n最后进行FLATMAP\nAnd we flatmap it.\n\n533\n00:30:34,590 --> 00:30:36,208\n这样我们就生成了所有的(I, J)序对\nNow we have all the pairs i and j,\n\n534\n00:30:36,816 --> 00:30:38,080\n其中I <= J\nsuch that i is less than j.\n\n535\n00:30:38,730 --> 00:30:39,850\n就是这样\nSo that builds that.\n\n536\n00:30:39,850 --> 00:30:40,768\n紧接着就是过滤\nNow we're got to test them.\n\n537\n00:30:42,990 --> 00:30:45,840\n我们对刚才FLATMAP得到的东西\nWell, we take that thing we just built, the flatmap,\n\n538\n00:30:46,944 --> 00:30:51,376\n我们以I -- 这里分别是 I 和 J\nand we filter it to see whether the i-- see, we had an i and a j.\n\n539\n00:30:51,660 --> 00:30:54,176\nI是表的第一个元素\ni was the first thing in the list,\n\n540\n00:30:54,304 --> 00:30:55,600\nJ是第二个\nj was the second thing in the list.\n\n541\n00:30:57,216 --> 00:31:00,010\n我们用一个谓词来判断 表中的两个元素\nSo we have a predicate which says in that list of two elements\n\n542\n00:31:00,224 --> 00:31:02,000\n也就是表的CAR部分与CDR部分之和 是否为质数\nis the sum of the CAR and the CDR prime.\n\n543\n00:31:02,070 --> 00:31:05,520\n用这个谓词来过滤刚刚收集起来的表\nAnd we filter that collection of pairs we just built.\n\n544\n00:31:06,540 --> 00:31:07,856\n就得到了我们想要的表\nSo those are the pairs we want.\n\n545\n00:31:09,420 --> 00:31:10,240\n然后我们继续\nNow we go ahead\n\n546\n00:31:10,880 --> 00:31:13,104\n把过滤得到的结果 再次进行MAP操作\nNow we go ahead and we take the result of that filter\n\n547\n00:31:13,264 --> 00:31:19,056\n用来生成 I、J 和 I+J 构成的表\nwe map along it, generating the list i and j and i plus j.\n\n548\n00:31:19,610 --> 00:31:21,392\n这就是过程 PRIME-SUM-PAIRS\nAnd that's our procedure prime-sum-pairs.\n\n549\n00:31:22,570 --> 00:31:24,768\n最后只需要过一遍 这就是整个过程\nOk, and then just to flash it up, here's the whole procedure.\n\n550\n00:31:28,080 --> 00:31:30,976\n一个MAP、一个FILTER 以及一个FLATMAP\nA map, a filter, a flatmap.\n\n551\n00:31:34,850 --> 00:31:35,664\n所有的东西都在这里了\nThere's the whole thing,\n\n552\n00:31:35,664 --> 00:31:37,120\n尽管可读性不是那么好\neven though this isn't particularly readable.\n\n553\n00:31:37,424 --> 00:31:38,944\n我们只是把中间过程展开了\nIt's just expanding that flatmap.\n\n554\n00:31:39,840 --> 00:31:40,880\n这个例子\nSo there's an example\n\n555\n00:31:43,280 --> 00:31:45,008\n向我们展示了\nwhich illustrates the general point\n\n556\n00:31:45,120 --> 00:31:46,304\n嵌套循环\nthat nested loops\n\n557\n00:31:47,660 --> 00:31:50,096\n在这个过程中 它看起来就像\nin this procedure start looking like compositions of\n\n558\n00:31:50,112 --> 00:31:52,810\n各种嵌套的MAP和FLATMAP的组合\nflatmaps of flatmaps of flatmaps of maps and things.\n\n559\n00:31:54,272 --> 00:31:57,616\n所以我们不仅仅可以枚举单个个体\nSo not only can we enumerate individual things,\n\n560\n00:31:57,616 --> 00:31:58,816\n通过使用FLATMAP\nbut by using flatmaps,\n\n561\n00:31:59,120 --> 00:32:02,240\n我们可以实现其它语言中的嵌套循环\nwe can do what would correspond to nested loops in most other languages.\n\n562\n00:32:03,230 --> 00:32:03,760\n当然\nOf course,\n\n563\n00:32:04,912 --> 00:32:08,032\n重复写这些FLATMAP很烦人\nit's pretty awful to keep writing these flatmaps of flatmaps of flatmaps.\n\n564\n00:32:08,410 --> 00:32:13,008\n尽管PRIME-SUM-PAIRS其中单独的部分很容易\nPrime-sum-pairs you saw looked fairly complicated,\n\n565\n00:32:13,568 --> 00:32:15,280\n但整体看起来还是十分复杂\neven though the individual pieces were easy.\n\n566\n00:32:15,480 --> 00:32:17,136\n如果你愿意的话 可以\nSo what you can do, if you like,\n\n567\n00:32:17,152 --> 00:32:20,128\n引进一个叫COLLECT的语法糖衣\nis introduced some syntactic sugar that's called collect.\n\n568\n00:32:21,040 --> 00:32:22,688\nCOLLECT只是一个缩写\nAnd collect is just an abbreviation\n\n569\n00:32:22,912 --> 00:32:26,160\n用来代表特定顺序的FLATMAP和FILTER操作\nfor that nest of flatmaps and filters arranged in that particular way.\n\n570\n00:32:26,160 --> 00:32:28,608\n这里我们用COLLECT把PRIME-SUM-PAIRS写一遍\nHere's prime-sum-pairs again, written using collect.\n\n571\n00:32:29,450 --> 00:32:36,272\nPRIME-SUM-PAIRS过程需要收集这样一个东西\nIt says to find all those pairs, I'm going to collect together a result,\n\n572\n00:32:36,528 --> 00:32:39,200\n它的元素是形如(I, J, I+J)这样的表\nwhich is the list i, j, and i plus j,\n\n573\n00:32:40,848 --> 00:32:45,392\n而这将通过I从1取到N\nthat's going to be generated as i runs through the interval from 1 to n\n\n574\n00:32:47,440 --> 00:32:52,320\n同时J要从1取到I-1来产生\nand as j runs through the interval from 1 to i minus 1\n\n575\n00:32:54,160 --> 00:32:56,544\n并且要满足I+J是质数\nsuch that i plus j is prime.\n\n576\n00:32:58,040 --> 00:33:00,320\n课堂上我就不讲解如何定义COLLECT了\nSo I'm not going to say what collect does in general.\n\n577\n00:33:00,690 --> 00:33:02,752\n书上面有\nYou can look at that by looking at it in the book.\n\n578\n00:33:03,420 --> 00:33:05,456\n不过你可以清楚地看到 这些代码片段\nBut pretty much, you can see that the pieces of this\n\n579\n00:33:05,840 --> 00:33:08,608\n就是我原先写的过程中的片段\nare the pieces of that original procedure I wrote.\n\n580\n00:33:08,820 --> 00:33:11,408\nCOLLECT过程只是一个语法糖衣\nAnd this collect is just some syntactic sugar\n\n581\n00:33:11,440 --> 00:33:14,800\n用来自动生成嵌套FLATMAP\nfor automatically generating that nest of flatmaps and flatmaps.\n\n582\n00:33:16,310 --> 00:33:20,336\n好的 我们再来看另一个例子\nOK, well, let me do one more example\n\n583\n00:33:20,672 --> 00:33:22,000\n也展示了同样的道理\nthat shows you the same kind of thing.\n\n584\n00:33:22,120 --> 00:33:23,536\n这是一个非常著名的问题\nHere's a very famous problem\n\n585\n00:33:24,704 --> 00:33:28,752\n经常用来演示所谓的“回溯”算法\nthat's used to illustrate a lot of so-called backtracking computer algorithms\n\n586\n00:33:28,768 --> 00:33:30,200\n这就是“八皇后问题”\nThis is the eight queens problem.\n\n587\n00:33:30,200 --> 00:33:31,088\n这是一个棋盘\nThis is a chess board.\n\n588\n00:33:32,370 --> 00:33:33,648\n八皇后问题要求我们\nAnd the eight queens problem says,\n\n589\n00:33:33,648 --> 00:33:35,856\n找到一种将八个皇后放到棋盘上的摆法\nfind a way to put down eight queens on a chess board\n\n590\n00:33:36,448 --> 00:33:38,000\n使得任意的两个皇后不会相互攻击\nso that no two are attacking each other.\n\n591\n00:33:38,000 --> 00:33:40,608\n这里给出了一个解法\nAnd here's a particular solution to the eight queens problem.\n\n592\n00:33:41,210 --> 00:33:43,680\n我需要保证摆放好后\nSo I have to make sure to put down queens\n\n593\n00:33:43,712 --> 00:33:46,800\n任意两个皇后不在同一行或同一列上\nno two are in the same row or the same column\n\n594\n00:33:47,728 --> 00:33:49,472\n也不在同一对角线上\nor sit along the same diagonal.\n\n595\n00:33:51,410 --> 00:33:56,400\n有一个解决这个问题的标准解法\nNow, there's sort of a standard way of doing that.\n\n596\n00:33:59,740 --> 00:34:01,488\n首先我们要做是\nWell, first we need to do is\n\n597\n00:34:02,544 --> 00:34:04,624\n进入底层 站在George的层面\nbelow the surface, at George's level.\n\n598\n00:34:04,940 --> 00:34:08,095\n找到一种表示棋盘与位置的方式\nWe have to find some way to represent a board, and represent positions.\n\n599\n00:34:08,090 --> 00:34:09,520\n这个并不需要太担心\nAnd we'll not worry about that.\n\n600\n00:34:09,800 --> 00:34:12,784\n假设我们有一个谓词SAFE?\nBut let's assume that there's a predicate called safe.\n\n601\n00:34:16,144 --> 00:34:17,552\nSAFE?判断的是\nAnd what safe is going to do\n\n602\n00:34:17,968 --> 00:34:20,848\n假如一些皇后已经放在棋盘上\nis going to say given that I have a bunch of queens down on the chess board,\n\n603\n00:34:21,360 --> 00:34:24,544\n在这个点再放置一个皇后是否是安全？\nis it OK to put a queen in this particular spot?\n\n604\n00:34:25,400 --> 00:34:31,264\n所以SAFE?的参数分别为ROW和COLUMN\nSo safe is going to take a row and a column.\n\n605\n00:34:32,768 --> 00:34:35,472\n我将尝试把下一个皇后放在那个地方\nThat's going to be a place where I'm going to try and put down the next queen,\n\n606\n00:34:36,064 --> 00:34:42,768\n另外一个参数是剩下的位置\nand the rest of positions.\n\n607\n00:34:45,584 --> 00:34:46,752\nSAFE?要判断的是\nAnd what safe will say\n\n608\n00:34:46,864 --> 00:34:51,680\n在这些位置已经放置了皇后的情况下\nis given that I already have queens down in these positions,\n\n609\n00:34:53,024 --> 00:34:54,768\n在这行这列放置皇后\nis it safe to put another queen down\n\n610\n00:34:55,104 --> 00:34:57,200\n是否安全\nin that row and that column?\n\n611\n00:34:58,300 --> 00:34:59,360\n不用过分深究这个\nAnd let's not worry about that.\n\n612\n00:34:59,360 --> 00:35:01,380\n那是George的问题 也不难写出来\nThat's George's problem. and it's not hard to write.\n\n613\n00:35:01,380 --> 00:35:06,272\n只需要检测该行、该列\nYou just have to check whether this thing contains any things\n\n614\n00:35:06,304 --> 00:35:08,528\n以及对角线上是否有东西即可\non that row or that column or in that diagonal.\n\n615\n00:35:10,530 --> 00:35:13,120\n那么 有了这个过程后 我们的程序该如何组织呢？\nNow, how would you organize the program given that?\n\n616\n00:35:13,840 --> 00:35:17,216\n有一种传统的方式\nAnd there's sort of a traditional way to organize it\n\n617\n00:35:17,936 --> 00:35:18,976\n我们称为“回溯”\ncalled backtracking.\n\n618\n00:35:20,528 --> 00:35:23,216\n首先让我们来考虑\nAnd it says, well, let's start off\n\n619\n00:35:25,130 --> 00:35:28,880\n把第一个皇后放在第一列的\nlet's think about all the ways of putting the first queen down\n\n620\n00:35:30,048 --> 00:35:31,344\n所有方式\nin the first column.\n\n621\n00:35:31,456 --> 00:35:32,240\n有8种\nThere are eight ways.\n\n622\n00:35:32,580 --> 00:35:35,008\n先试下第一列\nWell, let's say try the first column.\n\n623\n00:35:35,880 --> 00:35:37,300\n第一行第一列\nTry column 1, row 1.\n\n624\n00:35:37,300 --> 00:35:38,704\n每个分支都代表了\nThese branches are going to represent\n\n625\n00:35:40,176 --> 00:35:41,888\n在每一个层次的可能解\nthe possibilities at each level.\n\n626\n00:35:43,360 --> 00:35:45,536\n我试着把皇后放在第一列\nSo I'll try and put a queen down in the first column.\n\n627\n00:35:46,140 --> 00:35:47,744\n现在 我在第一列放置好一个皇后以后\nAnd now given that it's in the first column,\n\n628\n00:35:47,776 --> 00:35:49,980\n我又尝试在第一列放置下一个皇后\nI'll try and put the next queen down in the first column.\n\n629\n00:35:50,608 --> 00:35:52,176\n并不成功 它们都……\nThat's no good, they're both...\n\n630\n00:35:53,310 --> 00:35:54,608\n我尝试把第一个皇后\nI'll try and put the first queen,\n\n631\n00:35:54,860 --> 00:35:56,800\n把在第一列上的那个皇后 放在第一行\nthe one in the first column, down in the first row.\n\n632\n00:35:56,920 --> 00:35:57,472\n不好意思\nI'm sorry.\n\n633\n00:35:59,050 --> 00:36:01,390\n放好后 我们再把下一个皇后放在第一行\nAnd then given that, we'll put the next queen down in the first row.\n\n634\n00:36:01,390 --> 00:36:02,090\n这不行\nAnd that's no good.\n\n635\n00:36:02,090 --> 00:36:03,184\n所以又回到这里\nSo I'll back up to here.\n\n636\n00:36:04,200 --> 00:36:04,720\n然后再考虑\nAnd I'll say,\n\n637\n00:36:04,832 --> 00:36:06,860\n我们把这个皇后放在第二行吗？\noh, can I put the first queen down in the second row?\n\n638\n00:36:07,328 --> 00:36:08,384\n然而也不行\nWell, that's no good.\n\n639\n00:36:08,550 --> 00:36:09,760\n那么放在第三行呢？\nOh, can I put it down in the third row?\n\n640\n00:36:09,760 --> 00:36:10,528\n这样可以\nWell, that's good.\n\n641\n00:36:12,790 --> 00:36:15,136\n下一个皇后可以放在第一列吗？\nWell, now can I put the next queen down in the first column?\n\n642\n00:36:15,380 --> 00:36:17,824\n我不能再画更多的棋盘了\nWell, I can't visualize this chess board anymore,\n\n643\n00:36:17,824 --> 00:36:18,864\n但我先假设这个可行\nbut I think that's right.\n\n644\n00:36:19,195 --> 00:36:20,450\n我尝试下一个\nAnd I try the next one.\n\n645\n00:36:20,450 --> 00:36:24,170\n在每一个地方 尽可能的沿着树往下\nAnd at each place, I go as far down this tree as I can.\n\n646\n00:36:24,544 --> 00:36:25,640\n然后回退\nAnd I back up.\n\n647\n00:36:25,640 --> 00:36:28,976\n如果我从这里往下走 发现下面不可能有解\nIf I get down to here and find no possibilities below there,\n\n648\n00:36:29,008 --> 00:36:30,120\n我就回溯到这里来\nI back all the way up to here,\n\n649\n00:36:30,288 --> 00:36:32,448\n然后开始生成这个子树\nand now start again generating this sub-tree.\n\n650\n00:36:33,260 --> 00:36:34,320\n我就像这样遍历\nAnd I sort of walk around.\n\n651\n00:36:35,050 --> 00:36:37,264\n最后 一路求解下来\nAnd finally, if I ever manage to get all the way down,\n\n652\n00:36:37,728 --> 00:36:38,592\n就会得到答案\nI've found a solution.\n\n653\n00:36:39,820 --> 00:36:41,984\n这种典型的范式\nSo that's a typical sort of\n\n654\n00:36:43,120 --> 00:36:45,930\n之前被广泛地使用在人工智能编程中\nparadigm that's used a lot in AI programming.\n\n655\n00:36:45,930 --> 00:36:47,300\n术语叫做 “回溯搜索”\nIt's called backtracking search.\n\n656\n00:36:57,470 --> 00:37:03,040\n这真的没有必要\nAnd it's really unnecessary.\n\n657\n00:37:03,860 --> 00:37:06,550\n你们也发现了 我在可视化这个过程时也犯了迷糊\nYou saw me get confused when I was visualizing this thing.\n\n658\n00:37:06,816 --> 00:37:08,256\n你们也看到了复杂程度\nAnd you sort of see the complication.\n\n659\n00:37:08,550 --> 00:37:10,760\n而且这种复杂还很难描述\nThis is a complicated thing to say.\n\n660\n00:37:10,760 --> 00:37:11,824\n为什么会这样？\nWhy is it complicated?\n\n661\n00:37:12,390 --> 00:37:13,296\n这是因为\nIts because somehow\n\n662\n00:37:13,530 --> 00:37:17,392\n这是因为这程序过分地关注于时间了\nthis program is too inordinately concerned with time.\n\n663\n00:37:18,580 --> 00:37:20,432\n这之中太多 -- 先试试这个 再试试这个\nIt's too much-- I try this one, and I try this one,\n\n664\n00:37:20,496 --> 00:37:22,380\n再回到上一个可行的地方 -- 这种操作太多了\nand I go back to the last possibility.\n\n665\n00:37:22,896 --> 00:37:24,340\n这很复杂\nAnd that's a complicated thing.\n\n666\n00:37:24,340 --> 00:37:26,368\n如果我们不再如此关注时间\nIf I stop worrying about time so much,\n\n667\n00:37:28,048 --> 00:37:29,760\n就有一个更简单的方式来描述\nthen there's a much simpler way to describe this.\n\n668\n00:37:31,200 --> 00:37:32,368\n让我们来想象一下\nIt says, let's imagine\n\n669\n00:37:33,312 --> 00:37:36,576\n现在我有\nthat I have in my hands\n\n670\n00:37:38,320 --> 00:37:42,160\n有一个高达K-1层的树\nthe tree down to k minus 1 levels.\n\n671\n00:37:43,400 --> 00:37:46,320\n假设我已经有了\nSee, suppose I had in my hands all possible ways\n\n672\n00:37:48,096 --> 00:37:52,192\n把皇后放在前K列的所有解法\nto solve... to put down queens in the first k columns.\n\n673\n00:37:53,560 --> 00:37:54,610\n假设是这样\nSuppose I just had that.\n\n674\n00:37:54,610 --> 00:37:55,792\n不要担心我是怎么得到的\nLet's not worry about how we get it.\n\n675\n00:37:57,070 --> 00:37:59,200\n现在 如何扩充下去呢？\nWell, then, how do I extend that?\n\n676\n00:37:59,200 --> 00:38:02,160\n怎样找到在下一列中放皇后的所有可行方法？\nHow do I find all possible ways to put down queens in the next column?\n\n677\n00:38:02,480 --> 00:38:03,136\n很简单\nIt's really easy.\n\n678\n00:38:03,620 --> 00:38:06,416\n对于已有的位置\nFor each of these positions I have,\n\n679\n00:38:07,820 --> 00:38:13,968\n我考虑把下一个皇后放在每一行上\nI enjoin, I think about putting down a queen in each row\n\n680\n00:38:15,088 --> 00:38:16,160\n来构建出下一步的棋局\nto make the next thing.\n\n681\n00:38:16,160 --> 00:38:17,296\n然后 把所有放置的位置\nAnd then for each one I put down,\n\n682\n00:38:17,440 --> 00:38:19,712\n用SAFE?进行过滤\nI filter those by the ones that are safe.\n\n683\n00:38:21,800 --> 00:38:22,992\n不像之前那样\nSo instead of thinking about\n\n684\n00:38:22,992 --> 00:38:24,670\n把这个树看做是逐步生成的\nthis tree as generated step by step,\n\n685\n00:38:24,944 --> 00:38:26,860\n我们假设所有的东西都生成好了\nI say, suppose I had it all there.\n\n686\n00:38:29,680 --> 00:38:32,416\n为了从K-1层扩展到K层\nAnd to extend it from level k minus 1 to level k,\n\n687\n00:38:32,640 --> 00:38:36,240\n我只需要扩展所有可能的放置方法\nI just need to extend each thing in all possible ways\n\n688\n00:38:36,480 --> 00:38:37,800\n最后保留安全的排列\nand only keep the ones that are safe.\n\n689\n00:38:37,800 --> 00:38:39,232\n就得到一个K层树的结果\nAnd that will give me the tree to level k.\n\n690\n00:38:39,300 --> 00:38:40,672\n这是解决八皇后问题\nAnd that's a recursive strategy\n\n691\n00:38:40,896 --> 00:38:42,176\n的一个递归策略\nfor solving the eight queens problem.\n\n692\n00:38:44,530 --> 00:38:45,344\n好的 我们来看看\nAll right, well, let's look at it.\n\n693\n00:38:50,336 --> 00:38:52,688\n我们编写子过程FILL-COLS\nTo solve the eight queens problem\n\n694\n00:38:53,008 --> 00:38:55,536\n来解决在一个特定大小棋盘上的\non a board of some specified size,\n\n695\n00:38:58,928 --> 00:39:01,030\n八皇后问题\nwe write a sub-procedure called fill-columns.\n\n696\n00:39:01,136 --> 00:39:04,864\n这个过程会把皇后放置到K个列中\nFill-columns is going to put down queens up through column k.\n\n697\n00:39:06,352 --> 00:39:07,700\n这是递归的模式\nAnd here's the pattern of the recursion.\n\n698\n00:39:07,700 --> 00:39:10,928\n最后会以棋盘的大小为参数 调用FILL-COLS\nI'm going to call fill-columns with the size eventually.\n\n699\n00:39:12,990 --> 00:39:15,280\nFILL-COLS是用来说明\nSo fill-columns says how to put down queens safely\n\n700\n00:39:15,296 --> 00:39:17,168\n如何安全地把皇后放置在\nsafely in the first k columns of this chess board\n\n701\n00:39:17,200 --> 00:39:19,584\n具有SIZE行的棋盘的前K列\nwith a size number of rows in it.\n\n702\n00:39:20,360 --> 00:39:21,648\n如果K是0\nIf k is equal to 0,\n\n703\n00:39:22,272 --> 00:39:23,600\n就不用做什么\nwell, then I don't have to put anything down.\n\n704\n00:39:23,940 --> 00:39:25,936\n结果是一个空棋盘\nSo my solution is just an empty chess board.\n\n705\n00:39:26,710 --> 00:39:28,070\n否则就做点别的\nOtherwise, I'm going to do some stuff.\n\n706\n00:39:28,352 --> 00:39:29,440\n这里将要使用COLLECT\nAnd I'm going to use collect.\n\n707\n00:39:30,816 --> 00:39:31,770\n完整的代码在这里\nAnd here's the collect.\n\n708\n00:39:34,336 --> 00:39:41,910\n我找到了所有在前K-1列中放皇后的方法\nI find all ways to put down queens in the first k minus 1 columns.\n\n709\n00:39:42,192 --> 00:39:43,320\n这是我所假设的\nAnd this was just what I set for.\n\n710\n00:39:43,320 --> 00:39:46,368\n想像这棵树下降到K-1层\nImagine I have this tree down to k minus 1 levels.\n\n711\n00:39:48,880 --> 00:39:52,112\n然后我尝试每一行\nAnd then I find all ways of trying a row,\n\n712\n00:39:52,528 --> 00:39:54,130\n尝试每一个可行的行\nthat's just each of the possible rows.\n\n713\n00:39:54,130 --> 00:39:55,040\n总共SIZE行\nThey're size rows,\n\n714\n00:39:55,312 --> 00:39:56,496\n这里枚举了所有行数\nso that's enumerate interval.\n\n715\n00:39:58,040 --> 00:39:59,792\n现在要做的是\nAnd now what I do is I collect together\n\n716\n00:40:03,152 --> 00:40:05,824\n把我将要尝试的新行和第K列\nthe new row I'm going to try and column k\n\n717\n00:40:07,952 --> 00:40:08,950\n收集起来\nwith the rest of the queens.\n\n718\n00:40:08,950 --> 00:40:10,096\n我邻接一个位置\nI adjoin a position.\n\n719\n00:40:10,200 --> 00:40:11,290\n这是George的问题了\nThis is George's problem.\n\n720\n00:40:11,290 --> 00:40:12,752\n实现ADJOIN-POSITION和SAFE?都是George的工作\nAn adjoined position is like safe.\n\n721\n00:40:13,640 --> 00:40:15,280\n这个过程需要的参数有\nIt's a thing that takes a row\n\n722\n00:40:15,504 --> 00:40:17,040\nROW、COL以及REST-OF-POS\nand a column and the rest of the positions\n\n723\n00:40:17,072 --> 00:40:19,024\n然后返回位置的集合\nand makes a new position collection.\n\n724\n00:40:19,660 --> 00:40:25,776\n我把新的行和列\nSo I adjoin a position of a new row and a new column\n\n725\n00:40:26,064 --> 00:40:27,680\n和剩下的皇后邻接起来\nto the rest of the queens,\n\n726\n00:40:28,576 --> 00:40:29,760\n那些剩下的皇后\nwhere the rest of the queens\n\n727\n00:40:29,920 --> 00:40:31,456\n会尝试所有的\nruns through all possible ways\n\n728\n00:40:31,872 --> 00:40:34,160\n放置在K-1列中的可行解\nof solving the problem in k minus 1 columns.\n\n729\n00:40:34,620 --> 00:40:37,040\n新的行遍历了所有的可能性\nAnd the new row runs through all possible rows\n\n730\n00:40:37,856 --> 00:40:40,768\n过滤出安全的位置\nsuch that it was safe to put one there.\n\n731\n00:40:43,240 --> 00:40:44,704\n这就是整个程序了\nAnd that's the whole program.\n\n732\n00:40:46,336 --> 00:40:47,312\n整个过程\nThere's the whole procedure.\n\n733\n00:40:49,840 --> 00:40:52,432\n它不仅找到了八皇后的问题的解\nNot only that, that doesn't just solve the eight queens problem,\n\n734\n00:40:53,424 --> 00:40:56,680\n它还给出了所有的解\nRight? It gives you all solutions to the eight queens problem.\n\n735\n00:40:56,680 --> 00:40:58,480\n运行结束之后 就得到一个流\nWhen you're done, you have a stream.\n\n736\n00:40:58,480 --> 00:41:01,900\n流中的元素是所有的解\nAnd the elements of that stream are all possible ways of solving that problem.\n\n737\n00:41:05,310 --> 00:41:06,260\n为什么这个更简单一点呢？\nWhy is that simpler?\n\n738\n00:41:06,260 --> 00:41:08,544\n我们完全没有把这个当做\nWell, we threw away the whole idea that\n\n739\n00:41:08,880 --> 00:41:11,520\n按时间发生的、具有状态的过程\nis some process that happens in time with state.\n\n740\n00:41:12,720 --> 00:41:14,420\n我们只说 这是一些东西的集合\nAnd we just said it's a whole collection of stuff.\n\n741\n00:41:14,944 --> 00:41:16,000\n这是它更加简单的原因\nAnd that's why it's simpler.\n\n742\n00:41:18,000 --> 00:41:20,110\n我们已经转变了观念\nRight? We've changed our view.\n\n743\n00:41:20,110 --> 00:41:22,592\n还记得吗 这节课开始我们就讲过\nRemember, that's where we started today.\n\n744\n00:41:22,820 --> 00:41:26,230\n我们转变了建模的观念\nWe've changed our view of what it is we're trying to model.\n\n745\n00:41:26,230 --> 00:41:29,200\n我们不再把事物看做按时间演进\nwe stop modeling things that evolve in time\n\n746\n00:41:29,376 --> 00:41:31,312\n也不再具有不同的阶段与状态\nhave steps and have state.\n\n747\n00:41:31,750 --> 00:41:33,792\n取而代之的是 我们对全局进行建模\nAnd instead, we're trying to model this global thing\n\n748\n00:41:33,808 --> 00:41:35,936\n我们关注粉笔的整个飞行过程\nlike the whole flight of the chalk,\n\n749\n00:41:36,288 --> 00:41:38,880\n而不是专注于每个瞬时状态\nrather than its state at each instant.\n\n750\n00:41:40,750 --> 00:41:41,440\n有什么问题吗？\nAny questions?\n\n751\n00:41:44,080 --> 00:41:46,208\n学生：在我看来回溯会\nAUDIENCE: It looks to me like backtracking would be\n\n752\n00:41:46,224 --> 00:41:48,960\n搜索到它所能找到的第一个解\nsearching for the first solution it can find,\n\n753\n00:41:49,310 --> 00:41:51,488\n而这个递归搜索\nwhereas this recursive search\n\n754\n00:41:51,488 --> 00:41:53,260\n会去寻找所有的解\nwould be looking for all solutions.\n\n755\n00:41:53,328 --> 00:41:53,600\n教授：是这样的\nPROFESSOR: Right.\n\n756\n00:41:54,030 --> 00:41:55,264\n学生：但问题是\nAUDIENCE: And it seems that\n\n757\n00:41:55,264 --> 00:41:57,920\n如果需要搜索的空间足够的大\nif you have a large enough area to search,\n\n758\n00:41:57,920 --> 00:42:00,928\n第二种搜索方式就会变得不现实\nthat the second is going to become impossible.\n\n759\n00:42:01,360 --> 00:42:05,936\n教授：呃 这个问题其实是\nPROFESSOR: OK, the answer to that question\n\n760\n00:42:07,136 --> 00:42:08,448\n这一节课剩下的内容\nis the whole rest of this lecture.\n\n761\n00:42:08,570 --> 00:42:10,540\n这个问题很好\nIt's exactly the right question.\n\n762\n00:42:13,872 --> 00:42:15,744\n先不要尝试去预知后面的课\nAnd without trying to anticipate the lecture too much,\n\n763\n00:42:15,968 --> 00:42:19,232\n只是在现在 你们要保持谨慎\nyou should start being suspicious at this point,\n\n764\n00:42:19,840 --> 00:42:21,840\n这里确实有点奇怪 难道不是么？\nand exactly those kinds of suspicions. Isn't it?\n\n765\n00:42:22,220 --> 00:42:24,512\n尽管这个看起来不错 但是难道它不低效吗？\nIt's wonderful, but isn't it so terribly inefficient?\n\n766\n00:42:24,830 --> 00:42:26,032\n这是我们待会儿要解决的问题\nThat's where we're going.\n\n767\n00:42:28,100 --> 00:42:30,020\n就让我们稍后来揭晓秘密吧\nSo I won't answer now, but I'll answer later.\n\n768\n00:42:33,350 --> 00:42:34,600\n好吧 休息一下\nOK, let's take a break.\n\n769\n00:42:34,600 --> 00:42:44,512\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n770\n00:42:44,510 --> 00:42:49,040\n《计算机程序的构造和解释》\n\n771\n00:43:10,570 --> 00:43:17,056\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n772\n00:43:17,050 --> 00:43:21,216\n《计算机程序的构造和解释》\n\n773\n00:43:21,216 --> 00:43:25,210\n流 I\n\n774\n00:43:29,650 --> 00:43:33,760\n你可能现在开始怀疑了\nWell, by now you should be starting to get suspicious.\n\n775\n00:43:35,600 --> 00:43:39,264\n我已经展示了这种简单而优雅的\nSee, I've showed your this simple, elegant\n\n776\n00:43:40,512 --> 00:43:42,288\n组合程序的方法\nof putting programs together,\n\n777\n00:43:42,864 --> 00:43:46,912\n这跟那些传统程序非常不同\nvery unlike these other traditional programs\n\n778\n00:43:46,920 --> 00:43:48,192\n那些求奇数的平方和\nthat sum the odd squares\n\n779\n00:43:48,720 --> 00:43:51,320\n或者求奇数项斐波那契数之类的程序\nor compute the odd Fibonacci numbers.\n\n780\n00:43:53,740 --> 00:43:55,488\n也不像那些混合了\nVery unlike these programs that mix up\n\n781\n00:43:55,856 --> 00:43:58,848\n枚举函数、过滤函数和累积函数的程序\nthe enumerator and the filter and the accumulator.\n\n782\n00:44:00,440 --> 00:44:01,824\n通过把它们混合起来\nAnd by mixing it up,\n\n783\n00:44:02,200 --> 00:44:04,592\n通过这种混搭式的\nwe don't have all of these wonderful\n\n784\n00:44:04,624 --> 00:44:07,344\n组合程序的方法\nconceptual advantages of these streams pieces,\n\n785\n00:44:07,824 --> 00:44:09,536\n我们并没有获得\nthese wonderful mix and match components\n\n786\n00:44:09,552 --> 00:44:11,776\n流式程序设计的理论优势\nfor putting together lots and lots of programs.\n\n787\n00:44:13,800 --> 00:44:14,256\n另一方面\nOn the other hand,\n\n788\n00:44:14,288 --> 00:44:16,880\n你们所见过的大多数程序是那种丑陋的风格\nmost of the programs you've seen look like these ugly ones.\n\n789\n00:44:18,340 --> 00:44:18,944\n为什么会这样？\nWhy's that?\n\n790\n00:44:19,200 --> 00:44:20,592\n难道计算机科学家们\nCan it possibly be\n\n791\n00:44:21,168 --> 00:44:24,304\n愚蠢得无以复加\nthat computer scientists are so obtuse\n\n792\n00:44:25,420 --> 00:44:26,448\n以至于他们没有注意到这个现象么？\nthat they don't notice\n\n793\n00:44:27,072 --> 00:44:28,752\n如果你仅仅只是做了这些事\nthat if you'd merely did this thing,\n\n794\n00:44:29,632 --> 00:44:31,936\n你就能让程序变得极其优雅么？\nthen you can get this great programming elegance?\n\n795\n00:44:33,620 --> 00:44:34,784\n肯定有什么缺陷\nThere's got to be a catch.\n\n796\n00:44:36,760 --> 00:44:39,056\n事实上这一缺陷也很容易发现\nAnd it's actually pretty easy to see what the catch is.\n\n797\n00:44:39,510 --> 00:44:41,744\n我们来看看接下来的这个问题\nLet's think about the following problem.\n\n798\n00:44:42,030 --> 00:44:45,472\n假设我让你去找\nSuppose I tell you to find the second prime\n\n799\n00:44:46,160 --> 00:44:48,160\n1,000到1,000,000之间的第二个素数\nbetween 10,000 and 1 million,\n\n800\n00:44:49,120 --> 00:44:50,560\n如果你的计算机性能更强劲的话\nor if your computer's larger,\n\n801\n00:44:50,592 --> 00:44:53,056\n或者可以去找10,000到100,000,000之间的\nsay between 10,000 and 100 billion, or something.\n\n802\n00:44:54,320 --> 00:44:55,456\n你可能觉得这很容易\nAnd you say, oh, that's easy.\n\n803\n00:44:55,472 --> 00:44:56,656\n我可以用流来解决\nI can do that with a stream.\n\n804\n00:44:57,080 --> 00:44:59,872\n我需要做的就是\nAll I do is I enumerate\n\n805\n00:45:00,576 --> 00:45:02,896\n从10,000枚举到1,000,000\nthe interval from 10,000 to 1 million.\n\n806\n00:45:04,160 --> 00:45:06,512\n我就获得了从10,000到1,000,000的所有整数\nSo I get all those integers from 10,000 to 1 million.\n\n807\n00:45:06,800 --> 00:45:08,640\n我过滤出所有的质数\nI filter them for prime-ness,\n\n808\n00:45:09,392 --> 00:45:11,104\n也就是对这些数做素性检测\nso test all of them and see if they're prime.\n\n809\n00:45:11,760 --> 00:45:12,832\n然后从中取出第二个元素\nAnd I take the second element.\n\n810\n00:45:12,848 --> 00:45:14,048\n也就是 TAIL的HEAD部分\nRight? That's the head of the tail.\n\n811\n00:45:15,792 --> 00:45:17,380\n这显然是非常荒谬的\nOK? Well, that's clearly pretty ridiculous.\n\n812\n00:45:21,660 --> 00:45:23,200\n我们的机器没有这么大的空间\nWe'd not even have room in the machine\n\n813\n00:45:23,584 --> 00:45:25,248\n来存放这些整数\nRight? To store the integers in the first place,\n\n814\n00:45:25,280 --> 00:45:26,352\n更别说来测试它们了\nmuch less to test them.\n\n815\n00:45:27,040 --> 00:45:28,640\n而且我也只是取第二个数而已\nAnd then I only want the second one.\n\n816\n00:45:29,810 --> 00:45:34,944\n这种传统程序设计风格的威力\nSee, the power of this traditional programming style\n\n817\n00:45:36,432 --> 00:45:37,680\n（虽然）也正是其弱点\nis exactly its weakness,\n\n818\n00:45:37,960 --> 00:45:38,944\n这种程序设计风格\nthat we're mixing up\n\n819\n00:45:39,616 --> 00:45:43,500\n混合了枚举、测试以及累积\nthe enumerating and the testing and the accumulating.\n\n820\n00:45:44,880 --> 00:45:46,464\n我们不需要做全部的事\nRight? We sort of don't do it all.\n\n821\n00:45:46,670 --> 00:45:49,184\n所以说 实际上这是这种\nSo by the actual... so the very thing\n\n822\n00:45:49,456 --> 00:45:51,744\n概念上丑陋的风格\nmakes it conceptually ugly\n\n823\n00:45:52,208 --> 00:45:53,808\n正是让它运行起来高效\nis the very thing that makes it efficient.\n\n824\n00:45:54,912 --> 00:45:55,840\n就是像这样来混合\nRight? It's this mixing up.\n\n825\n00:45:57,800 --> 00:45:59,344\n我今天一早上所做的好像都是在\nSo it seems that all I've done this morning so far\n\n826\n00:45:59,344 --> 00:46:00,420\n把你们搞糊涂一样\nis just confuse you.\n\n827\n00:46:00,420 --> 00:46:03,104\n我为你们展示了一种貌似可行的优雅程序设计方法\nI showed you this wonderful way that programming might work,\n\n828\n00:46:03,104 --> 00:46:03,968\n但它却不可行\nexcept that it doesn't.\n\n829\n00:46:05,840 --> 00:46:08,320\n但是 接下来就是见证奇迹的时刻\nWell, here's where the wonderful thing happens.\n\n830\n00:46:09,040 --> 00:46:10,576\n结果却是 这个游戏里\nIt turns out in this game\n\n831\n00:46:11,216 --> 00:46:13,840\n我们真的可以得到蛋糕并吃掉它\nthat we really can have our cake and eat it too.\n\n832\n00:46:14,870 --> 00:46:16,112\n我的意思是\nAnd what I mean by that\n\n833\n00:46:18,096 --> 00:46:21,152\n我们完全可以用流来组织程序\nis that we really can write stream programs\n\n834\n00:46:21,168 --> 00:46:22,480\n就像我之前编写的那样\nexactly like the ones I wrote\n\n835\n00:46:23,552 --> 00:46:27,744\n以至于当机器真正运行的时候\nand arrange things so that when the machine actually runs,\n\n836\n00:46:28,336 --> 00:46:31,520\n它可以和传统风格的程序一样高效\nit's as efficient as running this traditional programming style\n\n837\n00:46:31,712 --> 00:46:34,288\n那些混合了生成与测试的程序\nthat mixes up the generation and the test.\n\n838\n00:46:36,160 --> 00:46:38,800\n听起来不可思议\nWell, that sounds pretty magic.\n\n839\n00:46:40,770 --> 00:46:41,824\n关键在就于\nThe key to this\n\n840\n00:46:42,000 --> 00:46:43,690\n流不是表\nis that streams are not lists.\n\n841\n00:46:48,090 --> 00:46:49,792\n一会儿我们就会看到 但是现在\nWe'll see this carefully in a second, but for now,\n\n842\n00:46:49,808 --> 00:46:51,776\n先让我们来看看幻灯片\nlet's take a look at that slide again.\n\n843\n00:46:52,240 --> 00:46:53,808\n你们对这个\nThe image you should have here\n\n844\n00:46:53,840 --> 00:46:55,584\n信号处理系统的印象是\nof this signal processing system\n\n845\n00:46:57,264 --> 00:46:58,720\n你们认为要发生的是\nis that what's going to happen\n\n846\n00:46:59,136 --> 00:47:00,928\n在这类盒子中\nis there's sort of this box\n\n847\n00:47:01,184 --> 00:47:03,584\n事先产生好了整数\nthat has the integers sitting in it.\n\n848\n00:47:05,360 --> 00:47:06,400\n这里有个过滤函数\nAnd there's this filter\n\n849\n00:47:07,456 --> 00:47:09,376\n它和那个盒子相连 并从中拉取东西\nthat's connected to it and it's tugging on them.\n\n850\n00:47:10,940 --> 00:47:13,152\n这里还有人从这整个系统中\nAnd then there's someone who's tugging on this stuff\n\n851\n00:47:13,312 --> 00:47:14,912\n拉取东西\nsaying what comes out of the filter.\n\n852\n00:47:16,790 --> 00:47:18,704\n你们应该这么来理解：\nAnd the image you should have is that\n\n853\n00:47:18,992 --> 00:47:20,720\n有人想要得到第一个质数\nsomeone says, well, what's the first prime,\n\n854\n00:47:22,672 --> 00:47:24,144\n他从这个过滤函数这儿拉取\nand tugs on this filter.\n\n855\n00:47:24,590 --> 00:47:26,128\nFILTER从枚举函数中去拉取\nAnd the filter tugs on the integers.\n\n856\n00:47:28,020 --> 00:47:29,152\n你只需要在固定范围内寻找\nAnd you look only at that much,\n\n857\n00:47:29,168 --> 00:47:30,930\n然后从里面取出第二个数\nand then say, oh, I really wanted the second one.\n\n858\n00:47:30,930 --> 00:47:31,952\n第二个质数是多少？\nWhat's the second prime?\n\n859\n00:47:33,710 --> 00:47:35,376\n没有额外的计算\nAnd that no other computation\n\n860\n00:47:35,376 --> 00:47:36,640\n只要你不去拉取东西\nno computation gets done\n\n861\n00:47:36,640 --> 00:47:38,320\n就不会产生进行额外计算\nexcept when you tug on these things.\n\n862\n00:47:40,500 --> 00:47:41,410\n我来用实物演示一下\nLet me try that again.\n\n863\n00:47:41,410 --> 00:47:43,888\n这个小设备\nThis is a little device.\n\n864\n00:47:43,900 --> 00:47:44,976\n这是个小型的流机器\nThis is a little stream machine\n\n865\n00:47:45,504 --> 00:47:46,832\n这是Eric Grimson发明的\ninvented by Eric Grimson\n\n866\n00:47:47,600 --> 00:47:49,248\n他也在MIT教这门课\nwho's been teaching this course at MIT.\n\n867\n00:47:49,830 --> 00:47:52,512\n实际的流程是 -- 这里有某种流\nAnd the image is ... here's a stream of stuff,\n\n868\n00:47:52,544 --> 00:47:53,824\n就像一串整数一样\nlike a whole bunch of the integers.\n\n869\n00:47:54,780 --> 00:47:56,336\n这些是一些处理单元\nAnd here's some processing elements.\n\n870\n00:47:58,700 --> 00:48:02,600\n就像是FILTER、MAP之类的东西\nAnd if, say, it's filter of filter of map, or something.\n\n871\n00:48:03,984 --> 00:48:09,184\n如果我把流实现为表 来进行处理\nAnd if I really tried to implement that with streams as lists,\n\n872\n00:48:09,248 --> 00:48:11,264\n我拥有的是一个表\nwhat I'd say is, well, I've got this list of things,\n\n873\n00:48:11,472 --> 00:48:12,670\n现在 我先执行第一个过滤函数\nand now I do the first filter.\n\n874\n00:48:12,670 --> 00:48:14,070\n我像这样完全处理\nSo I sort of do all this processing.\n\n875\n00:48:14,880 --> 00:48:15,776\n针对这个流\nAnd I take this\n\n876\n00:48:16,320 --> 00:48:19,216\n不断地处理、处理、处理、处理\nand I process and I process and I process and I process.\n\n877\n00:48:19,610 --> 00:48:21,056\n然后得到一个新的流\nAnd now I'm got this new stream.\n\n878\n00:48:21,632 --> 00:48:24,070\n现在 我把得到的结果拿在我手中\nRight? Now I take that result in my hand someplace.\n\n879\n00:48:24,070 --> 00:48:25,260\n然后把它放进第二个\nAnd I put that through the second one.\n\n880\n00:48:25,568 --> 00:48:26,944\n又处理了全部的流\nAnd I process the whole thing.\n\n881\n00:48:28,272 --> 00:48:29,510\n得到一个新流\nAnd there's this new stream.\n\n882\n00:48:32,130 --> 00:48:33,360\n然后我再把结果\nAnd then I take the result\n\n883\n00:48:34,288 --> 00:48:36,360\n用相同的方式再次处理\nand I put it all the way through this one the same way.\n\n884\n00:48:36,360 --> 00:48:40,992\n如果仅仅把流当做表的话\nThat's what would happen to these stream programs\n\n885\n00:48:41,696 --> 00:48:42,976\n计算的过程就是这样的\nif streams were just lists.\n\n886\n00:48:43,860 --> 00:48:45,648\n但是事实上 流不是表 流就是流\nBut in fact, streams aren't lists, they're streams.\n\n887\n00:48:45,824 --> 00:48:48,112\n而你们应该这样来想像\nAnd the image you should have is something a little bit more like this.\n\n888\n00:48:50,230 --> 00:48:52,528\n我把这些小玩意连接起来\nI've got these gadgets connected up\n\n889\n00:48:55,264 --> 00:48:56,768\n数据在其中流动\nby this data that's flowing out of them.\n\n890\n00:49:00,336 --> 00:49:02,304\n这里是流的源头\nAnd here's my original source of the streams.\n\n891\n00:49:02,320 --> 00:49:02,928\n它可能在\nIt might be\n\n892\n00:49:04,192 --> 00:49:05,728\n产生一些整数\nstarting to generate the integers.\n\n893\n00:49:05,980 --> 00:49:07,392\n如果我想要拉取一个结果 会发生什么？\nAnd now, what happens if I want a result?\n\n894\n00:49:07,580 --> 00:49:08,912\n我从尾部这里拉取\nI tug on the end here.\n\n895\n00:49:10,200 --> 00:49:11,072\n而这个单元会说\nAnd this element says,\n\n896\n00:49:11,088 --> 00:49:12,208\n我需要更多的数据\ngee, I need some more data.\n\n897\n00:49:13,090 --> 00:49:15,520\n所以 它就到这个单元去拉取数据\nSo it's sort of, this one comes here and tugs on that one.\n\n898\n00:49:15,830 --> 00:49:17,392\n它说：“我需要更多的数据”\nAnd it says, gee, I need some more data.\n\n899\n00:49:17,890 --> 00:49:19,568\n然后这个又从下一个单元拉取\nAnd this one tugs on this thing,\n\n900\n00:49:19,568 --> 00:49:20,288\n可能是一个过滤函数\nwhich might be a filter,\n\n901\n00:49:20,288 --> 00:49:21,408\n从它那里取得更多数据\nand says, gee, I need some more data.\n\n902\n00:49:21,640 --> 00:49:23,152\n我在这一端拉取数据时\nAnd only as much of this\n\n903\n00:49:23,536 --> 00:49:25,568\n只会生成这么多的数据\nthing at the end here gets generated as I tugged.\n\n904\n00:49:25,780 --> 00:49:28,304\n我在另一端请求一定量的数据时\nAnd only as much of this stuff goes through the processing units\n\n905\n00:49:28,560 --> 00:49:29,984\n只有相当数量的数据被生成并处理\nas I'm pulling on the end I need.\n\n906\n00:49:30,760 --> 00:49:32,096\n这就是你们需要知道的\nThat's the image you should have\n\n907\n00:49:32,800 --> 00:49:34,384\n把流实现为表\nof the difference between implementing\n\n908\n00:49:34,560 --> 00:49:35,920\n和流真实的工作方式\nwhat we're actually going to do\n\n909\n00:49:36,160 --> 00:49:37,504\n的区别\nand if streams were lists.\n\n910\n00:49:40,784 --> 00:49:42,144\n那么 到底怎么来实现呢？\nWell, how do we make this thing?\n\n911\n00:49:42,352 --> 00:49:43,328\n知道了流的真实工作方式\nI hope you have the image.\n\n912\n00:49:43,400 --> 00:49:44,528\n构造流有什么窍门呢？\nThe trick is how to make it.\n\n913\n00:49:47,930 --> 00:49:50,320\n我们想要把流组织成\nWe want to arrange for a stream\n\n914\n00:49:50,416 --> 00:49:51,584\n一种数据结构\nto be a data structure\n\n915\n00:49:52,000 --> 00:49:54,224\n它能够增量式地计算自己\nthat sorts of computes itself incrementally,\n\n916\n00:49:54,224 --> 00:49:56,224\n一种“按需”数据结构\nsort of on-demand data structure.\n\n917\n00:49:58,960 --> 00:50:00,512\n基本思想在于\nRight? And the basic idea\n\n918\n00:50:00,976 --> 00:50:02,704\n再次强调 这是贯穿整个课程的\nis again, one of the very basic ideas\n\n919\n00:50:02,720 --> 00:50:04,128\n几大基本思想之一\nthat we're seeing throughout the whole course.\n\n920\n00:50:04,490 --> 00:50:05,008\n这就是\nAnd that is\n\n921\n00:50:05,520 --> 00:50:06,976\n数据与过程之间\nthat there's not a firm distinction\n\n922\n00:50:06,992 --> 00:50:08,448\n并没有绝对的界限\nbetween programs and data.\n\n923\n00:50:09,240 --> 00:50:10,544\n流会是这样的一种结构\nSo what a stream is going to be\n\n924\n00:50:10,592 --> 00:50:13,408\n它既是一种传统意义上的“数据结构”\nis simultaneously this data structure that you think of,\n\n925\n00:50:13,456 --> 00:50:15,920\n比如树的叶子结点组成的流\nlike the stream of the leaves of this tree.\n\n926\n00:50:16,864 --> 00:50:17,856\n但是同时\nBut at the same time,\n\n927\n00:50:17,856 --> 00:50:19,328\n它又是一种非常聪明的过程\nit's going to be a very clever procedure\n\n928\n00:50:20,240 --> 00:50:22,224\n它包含了如何计算的方法\nthat has the method of computing in it.\n\n929\n00:50:23,744 --> 00:50:25,930\n好吧 实际来看一下\nWell, let me try this.\n\n930\n00:50:25,930 --> 00:50:26,624\n事实上\nIt's going to turn out\n\n931\n00:50:26,800 --> 00:50:28,330\n我们不需要其它的机制\nthat we don't need any more mechanism.\n\n932\n00:50:28,460 --> 00:50:29,872\n我们已经有了所需要的一切东西\nWe already have everything we need\n\n933\n00:50:30,144 --> 00:50:30,992\n这是因为\nsimply from the fact\n\n934\n00:50:31,020 --> 00:50:33,936\n我们已经能够 把过程当作第一级对象来处理了\nthat we know how to handle procedures as first-class objects.\n\n935\n00:50:35,460 --> 00:50:36,880\n来看看这个关键之处\nWell, let's go back to the key.\n\n936\n00:50:36,880 --> 00:50:39,030\n关键在于 -- 回想一下 我们有这些运算\nThe key is, remember, we had these operations.\n\n937\n00:50:39,030 --> 00:50:47,520\nCONS-STREAM、HEAD和TAIL\nCONS-stream and head and tail.\n\n938\n00:50:48,080 --> 00:50:49,360\n刚开始的时候我说\nWhen I started, I said\n\n939\n00:50:49,920 --> 00:50:51,360\n你们可以把这个看作CONS\nyou can think about this as CONS\n\n940\n00:50:51,400 --> 00:50:52,624\n把HEAD看作CAR\nand think about this as CAR\n\n941\n00:50:52,624 --> 00:50:53,520\n把TAIL看作CDR\nand think about that as CDR\n\n942\n00:50:53,552 --> 00:50:54,160\n事实上没这么简单\nbut it's not.\n\n943\n00:50:55,080 --> 00:50:56,320\n现在 来看看它们到底是什么\nNow, let's look at what they really are.\n\n944\n00:50:57,712 --> 00:51:05,840\n(CONS-STREAM X Y)\nWell, CONS-stream of x and y\n\n945\n00:51:07,488 --> 00:51:17,792\n是这个东西的缩写形式\nis going to be an abbreviation for the following thing.\n\n946\n00:51:19,540 --> 00:51:28,320\n(CONS X (DELAY Y))\nCONS form a pair, ordinary CONS, of x to a thing called delay of y.\n\n947\n00:51:31,680 --> 00:51:33,536\n我先把它们写完再来解释\nAnd before I explain that, let me go and write the rest.\n\n948\n00:51:34,528 --> 00:51:35,536\n而(HEAD S)\nThe head of a stream\n\n949\n00:51:38,096 --> 00:51:39,790\n就是 (CAR S)\nis going to be just the CAR.\n\n950\n00:51:42,380 --> 00:51:44,256\n而(TAIL S)\nAnd the tail of a stream\n\n951\n00:51:46,680 --> 00:51:54,608\n则是(FORCE (CDR S))\nis going to be a thing called force the CDR of the stream.\n\n952\n00:51:56,120 --> 00:51:57,040\n我来解释一下\nNow let me explain this.\n\n953\n00:51:58,060 --> 00:51:59,888\nDELAY是一个特殊而神奇的东西\nDelay is going to be a special magic thing.\n\n954\n00:52:01,420 --> 00:52:02,336\nDELAY所做是\nWhat delay does\n\n955\n00:52:03,856 --> 00:52:05,312\n取一个表达式\nis take an expression\n\n956\n00:52:05,504 --> 00:52:06,864\n然后产生一个PROMISE\nand produce a promise\n\n957\n00:52:07,120 --> 00:52:09,152\n在你有需要时 这个PROMISE会计算那个表达式\nto compute that expression when you ask for it.\n\n958\n00:52:10,600 --> 00:52:11,980\n但在此时没有做任何计算\nIt doesn't do any computation here.\n\n959\n00:52:11,980 --> 00:52:14,320\n只是一个延期的PROMISE\nJust sort of... It just gives you a rain check.\n\n960\n00:52:14,820 --> 00:52:16,208\n承诺要做这样的事\nIt produces a promise.\n\n961\n00:52:17,110 --> 00:52:18,208\nCONS-STREAM所做的就是\nAnd CONS-stream says\n\n962\n00:52:18,816 --> 00:52:21,968\n把X和一个计算Y的PROMISE\nI'm going to put together in a pair x\n\n963\n00:52:23,312 --> 00:52:25,360\n放在在一个序对里\nand a promise to compute y.\n\n964\n00:52:28,230 --> 00:52:28,992\n如果我需要头部分\nNow, if I want the head,\n\n965\n00:52:28,992 --> 00:52:30,750\n那么就是这个序对的CAR部分\nthat's just the CAR that I put in the pair.\n\n966\n00:52:31,840 --> 00:52:33,712\n关键在于 它的尾部分\nAnd the key is that the tail is going to be--\n\n967\n00:52:34,624 --> 00:52:36,656\n强制会调用该PROMISE\nforce calls in that promise.\n\n968\n00:52:38,220 --> 00:52:39,888\n而TAIL会说\nForce -- Tail says, well,\n\n969\n00:52:40,032 --> 00:52:41,024\n好吧 取出该PROMISE\nwell, take that promise\n\n970\n00:52:41,850 --> 00:52:44,528\n然后调用该PROMISE\nand now call in that promise.\n\n971\n00:52:44,560 --> 00:52:46,032\n这才开始实际的计算\nAnd then we compute that thing.\n\n972\n00:52:47,696 --> 00:52:48,720\n这就是它的实际工作方式\nThat's how this is going to work.\n\n973\n00:52:48,740 --> 00:52:51,550\n这就是CONS-STREAM、HEAD和TAIL的真正定义\nThat's what CONS-stream, head, and tail really are.\n\n974\n00:52:54,608 --> 00:52:55,570\n具体演示一下\nNow, let's see how this works.\n\n975\n00:52:55,570 --> 00:52:57,504\n我们小心翼翼地来审查一遍\nAnd we'll go through this fairly carefully. Let's --\n\n976\n00:52:58,768 --> 00:53:00,624\n现在从计算10,000到1,000,000中的\nWe're going to see how this\n\n977\n00:53:01,328 --> 00:53:03,664\n第二个质数这个实例来看\nexample of computing the second prime\n\n978\n00:53:05,504 --> 00:53:07,168\n看看是怎么运行的\nright? between 10,000 and a million.\n\n979\n00:53:08,650 --> 00:53:12,032\n好的 我们从这个表达式开始\nOK, so we start off and we have this expression.\n\n980\n00:53:15,360 --> 00:53:16,624\n第二个质数就是\nRight? The second prime--\n\n981\n00:53:16,640 --> 00:53:21,904\n就是(HEAD (TAIL (FILTER PRIME? ... )))\nthe head of the tail of the result of filtering for primality\n\n982\n00:53:22,832 --> 00:53:25,312\n枚举的范围是(E-I 10000 1000000)\nthe integers between 10,000 and 1 million.\n\n983\n00:53:26,710 --> 00:53:27,616\n这是什么呢？\nNow, what is that?\n\n984\n00:53:28,400 --> 00:53:29,200\n那就是\nWhat that is,\n\n985\n00:53:31,632 --> 00:53:34,176\n枚举的这个10,000至1,000,000的区间\nthat interval between 10,000 and 1 million,\n\n986\n00:53:35,728 --> 00:53:37,328\n如果你追踪这个枚举区间\nwell, if you trace through enumerate interval,\n\n987\n00:53:37,344 --> 00:53:38,780\n会发现它构造了一个流\nthere builds a CONS-stream.\n\n988\n00:53:39,920 --> 00:53:41,392\nCONS-STREAM实际代换过来是\nAnd the CONS-stream is\n\n989\n00:53:41,968 --> 00:53:43,616\n把10,000\nthe CONS of 10,000\n\n990\n00:53:44,512 --> 00:53:48,928\n和一个计算10,001到1,000,000之间整数的PROMISE结合起来\nto a promise to compute the integers between 10,001 and 1 million.\n\n991\n00:53:54,000 --> 00:53:55,750\n这也就是上面这个表达式\nOkay? So that's what this expression is.\n\n992\n00:53:55,750 --> 00:53:57,328\n现在我使用代换模型\nHere I'm using the substitution model.\n\n993\n00:53:57,640 --> 00:53:59,328\n我们可以用代换模型的原因是\nAnd we can use the substitution model\n\n994\n00:53:59,344 --> 00:54:01,010\n这里并没有涉及状态和副作用\nbecause we don't have side effects and state.\n\n995\n00:54:03,560 --> 00:54:06,384\n所以我有10,000\nOkay? So I have CONS of 10,000\n\n996\n00:54:06,416 --> 00:54:08,272\n和一个计算剩余整数构成的流\nto a promise to compute the rest of the integers.\n\n997\n00:54:08,320 --> 00:54:10,496\n而到现在为止 只有一个整数被枚举了出来\nSo only one integer, so far, got enumerated.\n\n998\n00:54:14,380 --> 00:54:16,960\n然后过滤函数会对它做素性测试\nWell, I'm going to filter that thing for primality.\n\n999\n00:54:19,440 --> 00:54:21,904\n我们再来仔细看看过滤函数的代码\nAgain, you go back and look at the filter code.\n\n1000\n00:54:22,360 --> 00:54:24,464\n过滤函数首先测试流的首部分\nWhat the filter will first do is test the head.\n\n1001\n00:54:25,460 --> 00:54:28,256\n这里 过滤函数会测试10,000\nSo in this case, the filter will test 10,000\n\n1002\n00:54:30,304 --> 00:54:32,976\n然后输出：10,000不是质数\noh, 10,000's not prime.\n\n1003\n00:54:33,500 --> 00:54:35,856\n因此我只需要\nTherefore, what I have to do recursively\n\n1004\n00:54:36,256 --> 00:54:37,390\n递归地过滤尾部分\nis filter the tail.\n\n1005\n00:54:39,220 --> 00:54:40,144\n尾部分是什么呢？\nAnd what's the tail of it,\n\n1006\n00:54:40,160 --> 00:54:43,760\n就是这个流的尾部分 -- 一个PROMISE\nwell, that's the tail of this pair with a promise in it.\n\n1007\n00:54:46,340 --> 00:54:48,064\n我们进入到尾部分\nTail now comes in and says,\n\n1008\n00:54:48,288 --> 00:54:49,504\n强制（计算）该PROMISE\nwell, I'm going to force that.\n\n1009\n00:54:49,680 --> 00:54:50,944\n我强制计算该PROMISE\nI'm going to force that promise,\n\n1010\n00:54:52,304 --> 00:54:54,368\n这就意味着 我现在要\nwhich means now I'm going to compute\n\n1011\n00:54:55,584 --> 00:54:57,968\n枚举10,001到1,000,000之间的整数\nthe integers between 10,001 and 1 million.\n\n1012\n00:55:00,800 --> 00:55:02,970\n现在 过滤函数处理的是这个东西\nOK? So this filter now is looking at that.\n\n1013\n00:55:07,810 --> 00:55:08,928\n这个枚举函数枚举了它自己\nThat enumerate itself,\n\n1014\n00:55:08,944 --> 00:55:11,230\n我们又回到了最初那种枚举情况\nnow we're back in the original enumerate situation.\n\n1015\n00:55:11,960 --> 00:55:13,008\n我们的枚举函数的\nThe enumerate is\n\n1016\n00:55:14,128 --> 00:55:16,448\n首部分是整数10,001\nCONS of the first thing, 10,001,\n\n1017\n00:55:16,608 --> 00:55:18,208\n尾部分是计算剩余部分的PROMISE\nonto a promise to compute the rest.\n\n1018\n00:55:19,740 --> 00:55:22,752\n因此现在素性过滤函数将会测试10,001\nSo now the primality filter is going to go look at 10,001.\n\n1019\n00:55:23,232 --> 00:55:25,120\n开始判断它是不是质数\nIt's going to decide if it likes that or not.\n\n1020\n00:55:25,120 --> 00:55:27,088\n结果10,001不是质数\nIt turns out 10,001 isn't prime.\n\n1021\n00:55:27,550 --> 00:55:29,610\n然后再不断地强制求值PROMISE\nSo it'll force it again and again and again.\n\n1022\n00:55:32,920 --> 00:55:35,808\n最后 我觉得它找到的第一个质数可能是10,009\nAnd finally, I think the first prime it hits is 10,009.\n\n1023\n00:55:37,100 --> 00:55:38,336\n它会在这个时候停止\nAnd at that point, it'll stop.\n\n1024\n00:55:40,848 --> 00:55:41,936\n这只是第一个质数\nAnd that will be the first prime,\n\n1025\n00:55:41,968 --> 00:55:43,488\n然而 我们需要的是第二个\nand then eventually, it'll need the second prime.\n\n1026\n00:55:45,240 --> 00:55:46,848\n所以 这时它又启动了\nSo at that point, it will go again.\n\n1027\n00:55:47,030 --> 00:55:48,256\n你会发现\nSo you see what happens is that\n\n1028\n00:55:48,528 --> 00:55:50,496\n你需要多少\nno more gets generated\n\n1029\n00:55:51,856 --> 00:55:52,912\n它就只会生成多少\nthan you actually need.\n\n1030\n00:55:56,480 --> 00:55:59,920\n枚举函数生成整数的数量\nThat enumerator is not going to generate any more integers\n\n1031\n00:56:00,128 --> 00:56:01,450\n不会比过滤函数所要求的多\nthan the filter asks it for\n\n1032\n00:56:01,472 --> 00:56:03,456\n因为它只是取一部分数来做素性测试\nas it's pulling in things to check for primality.\n\n1033\n00:56:04,700 --> 00:56:06,512\n过滤函数也不会生成\nAnd the filter is not going to generate\n\n1034\n00:56:06,544 --> 00:56:08,048\n比你的要求更多的东西\nany more stuff than you ask it for,\n\n1035\n00:56:08,064 --> 00:56:09,104\n也就是尾部分的首部分\nwhich is the head of the tail.\n\n1036\n00:56:11,616 --> 00:56:13,264\n你们看\nYou see, what's happened is\n\n1037\n00:56:14,704 --> 00:56:18,240\n我们把计算机运行中实际进行的\nwe've put that mixing of generation and test\n\n1038\n00:56:18,672 --> 00:56:20,656\n生成与测试的过程 混合在了一起\ninto what actually happens in the computer,\n\n1039\n00:56:21,520 --> 00:56:22,672\n尽管\neven though\n\n1040\n00:56:23,184 --> 00:56:25,630\n我们的程序“看起来”显然不是这样\nthat's not apparently what's happening from looking at our programs.\n\n1041\n00:56:28,128 --> 00:56:29,408\n看起来都很简单\nOK, well, that seemed easy.\n\n1042\n00:56:30,230 --> 00:56:32,672\n这种机制的神奇之处在于DELAY\nAll of this mechanism got put into this magic delay.\n\n1043\n00:56:33,680 --> 00:56:35,664\n所以你也许会说 这全是因为DELAY很强大\nSo you're saying, gee, that must be where the magic is.\n\n1044\n00:56:36,900 --> 00:56:38,576\n但其实并不是\nBut see there's no magic there either.\n\n1045\n00:56:39,070 --> 00:56:39,984\nDELAY其实很简单\nYou know what delay is.\n\n1046\n00:56:40,610 --> 00:56:45,072\n(DELAY <EXP>)\nDelay on some expression\n\n1047\n00:56:48,256 --> 00:56:50,048\n只是一个缩略表达\nis just an abbreviation for--\n\n1048\n00:56:53,360 --> 00:56:55,632\n它是-- 创建一个用于计算表达式的PROMISE\nwell, what's a promise to compute an expression?\n\n1049\n00:56:56,490 --> 00:57:01,120\n(LAMBDA () <EXP>) 这样的一个表达式\nLambda of nil, procedure of no arguments, which is that expression.\n\n1050\n00:57:02,832 --> 00:57:03,840\n这就是整个过程\nRight? That's what a procedure is.\n\n1051\n00:57:03,984 --> 00:57:05,530\n这个PROMISE将要计算表达式<EXP>\nIt says I'm going to compute an expression.\n\n1052\n00:57:06,050 --> 00:57:06,736\nFORCE过程又是什么？\nWhat's force?\n\n1053\n00:57:07,344 --> 00:57:10,800\n如何处理这个PROMISE\nRight, how do I take up a promise?\n\n1054\n00:57:10,800 --> 00:57:14,112\nFROCE一个PROMISE -- 也就是某个过程\nWell, force of some procedure, a promise,\n\n1055\n00:57:14,784 --> 00:57:15,408\n只是简单地运行它\nis just run it.\n\n1056\n00:57:19,232 --> 00:57:19,568\n就是这样\nDone.\n\n1057\n00:57:20,240 --> 00:57:21,376\n所以这里并没有什么魔法\nSo there's no magic there at all.\n\n1058\n00:57:23,520 --> 00:57:24,240\n总结一下 我们都干了些什么？\nWell, what have we done?\n\n1059\n00:57:26,440 --> 00:57:27,504\n我们说\nWe said the old style,\n\n1060\n00:57:28,144 --> 00:57:30,816\n传统的编程方式更有效\ntraditional style of programming is more efficient.\n\n1061\n00:57:30,960 --> 00:57:33,920\n而流程序却更加清晰\nAnd the stream thing is more perspicacious.\n\n1062\n00:57:35,504 --> 00:57:38,720\n我们设法用DELAY\nAnd we managed to make the stream procedures\n\n1063\n00:57:38,816 --> 00:57:43,232\n使流程序和其它过程一样高效\nrun like the other procedures by using delay.\n\n1064\n00:57:43,350 --> 00:57:46,432\nDELAY所做的就是把\nAnd the thing that delay did for us was to de-couple\n\n1065\n00:57:46,688 --> 00:57:50,400\n我们程序中 事件发生的逻辑顺序\nthe apparent order of events in our programs\n\n1066\n00:57:51,216 --> 00:57:53,840\n和机器中 事件发生的实际顺序 解耦开来\nfrom the actual order of events that happened in the machine.\n\n1067\n00:57:54,440 --> 00:57:55,936\n这是DELAY的实质作用\nThat's really what delay is doing.\n\n1068\n00:57:57,152 --> 00:57:58,290\n也是全部的重点\nThat's exactly the whole point.\n\n1069\n00:57:58,290 --> 00:58:01,920\n我们放弃了那种想法\nWe've given up, right, we've given up the idea\n\n1070\n00:58:02,300 --> 00:58:04,176\n即程序的运行\nthat our procedures, as they run,\n\n1071\n00:58:04,672 --> 00:58:05,952\n或者源码的编排\nor as we look at them,\n\n1072\n00:58:06,336 --> 00:58:08,256\n反映了时间的明确概念\nmirror some clear notion of time.\n\n1073\n00:58:09,456 --> 00:58:10,576\n一旦放弃了这种想法\nAnd by giving that up,\n\n1074\n00:58:11,216 --> 00:58:13,328\n我们能使用DELAY\nwe give delay the freedom to arrange the order\n\n1075\n00:58:13,344 --> 00:58:15,200\n自由地安排计算顺序\nof events in the computation the way it likes.\n\n1076\n00:58:16,690 --> 00:58:17,610\n整个思想就是这样\nThat's the whole idea.\n\n1077\n00:58:17,610 --> 00:58:19,456\n我们解耦了\nWe de-couple the apparent order\n\n1078\n00:58:19,952 --> 00:58:21,136\n程序的逻辑顺序\nof events in our programs\n\n1079\n00:58:21,168 --> 00:58:22,896\n和其实际运行的顺序\nfrom the actual order of events in the computer.\n\n1080\n00:58:24,096 --> 00:58:25,770\n对了 还有一个细节\nOK, well there's one more detail.\n\n1081\n00:58:25,770 --> 00:58:27,216\n一个技术性的细节\nIt's just a technical detail,\n\n1082\n00:58:27,216 --> 00:58:28,432\n但是也非常重要\nbut it's actually an important one.\n\n1083\n00:58:29,730 --> 00:58:32,016\n当你们运行这些递归程序的时候\nAs you run through these recursive programs unwinding,\n\n1084\n00:58:32,160 --> 00:58:33,584\n你会看到很多像是\nyou'll see a lot of things that look like\n\n1085\n00:58:33,648 --> 00:58:37,872\n(TAIL (TAIL (TAIL ... 这样的东西\ntail of the tail of the tail.\n\n1086\n00:58:39,200 --> 00:58:41,024\n如果流是通过嵌套的CONS构造起来的\nRight. That's the kind of thing that would happen\n\n1087\n00:58:41,024 --> 00:58:42,880\n就会出现这种情况\nas I go CONSing down a stream all the way.\n\n1088\n00:58:43,860 --> 00:58:46,096\n如果我每次都要执行一次\nAnd if each time I'm doing that,\n\n1089\n00:58:46,144 --> 00:58:47,584\n如果我每次都要计算TAIL\neach time to compute a tail,\n\n1090\n00:58:48,224 --> 00:58:50,880\n我对一个过程求值\nI evaluate a procedure\n\n1091\n00:58:51,072 --> 00:58:53,072\n这个过程又将重新计算它的TAIL\nwhich then has to go re-compute its tail,\n\n1092\n00:58:53,100 --> 00:58:55,408\n它的TAIL又将重新计算TAIL的TAIL\nand re-compute its tail and recompute its tail each time,\n\n1093\n00:58:55,504 --> 00:58:56,880\n你们可以发现这非常低效\nyou can see that's very inefficient\n\n1094\n00:58:57,776 --> 00:59:00,560\n尤其是跟已经存放了所有元素的表相比\ncompared to just having a list where the elements are all there,\n\n1095\n00:59:01,168 --> 00:59:04,000\n因为那样 在取得下一个TAIL的时候不需要重新计算\nand I don't have to re-compute each tail every time I get the next tail.\n\n1096\n00:59:05,290 --> 00:59:08,288\n因此 这里有一个小技巧\nSo there's one little hack\n\n1097\n00:59:09,660 --> 00:59:13,136\n通过稍微修改DELAY的定义\nto slightly change the abbreviation, change what delay is\n\n1098\n00:59:14,960 --> 00:59:18,208\n就可以让整件事变得 -- 我先写一下\nand make it a thing which is-- I'll write it this way.\n\n1099\n00:59:19,680 --> 00:59:22,048\nDELAY实际的实现是\nDelay -- The actual implementation,\n\n1100\n00:59:24,528 --> 00:59:27,936\n(DELAY <exp>)是这样一个表达式的简写\ndelay is an abbreviation for this thing,\n\n1101\n00:59:28,112 --> 00:59:30,864\n(MEMO-PROC (LAMBDA () <EXP>))\nmemo-proc of a procedure.\n\n1102\n00:59:31,000 --> 00:59:34,064\nMEMO-PROC是一个可以改变过程的特殊过程\nMemo-proc is a special thing that transforms a procedure.\n\n1103\n00:59:35,150 --> 00:59:37,808\n它接受一个无参过程\nWhat it does is it takes a procedure of no arguments\n\n1104\n00:59:39,024 --> 00:59:41,056\n并把该过程变为\nand it transforms it into a procedure\n\n1105\n00:59:41,360 --> 00:59:43,552\n只需要执行一次计算的过程\nthat'll only have to do its computation once.\n\n1106\n00:59:45,104 --> 00:59:47,456\n我们意思是 你给它一个过程\nAnd what I mean by that is, you give it a procedure.\n\n1107\n00:59:48,700 --> 00:59:50,864\nMEMO-PROC返回一个新的过程\nThe result of memo-proc will be a new procedure,\n\n1108\n00:59:51,392 --> 00:59:53,008\n当你首次调用这个新过程\nwhich the first time you call it,\n\n1109\n00:59:53,712 --> 00:59:55,072\n它会运行原始过程\nwill run the original procedure,\n\n1110\n00:59:55,312 --> 00:59:56,912\n并记下结果\nremember what result it got,\n\n1111\n00:59:58,560 --> 01:00:00,688\n从那之后 每次你再运行这个过程\nand then from ever on after, when you call it,\n\n1112\n01:00:00,688 --> 01:00:02,176\n就不用再计算了\nit just won't have to do the computation.\n\n1113\n01:00:02,192 --> 01:00:04,432\n它会把结果存储在一个地方\nIt will have cached that result someplace.\n\n1114\n01:00:05,200 --> 01:00:06,928\n可以这样来实现MEMO-PROC\nAnd here's an implementation of memo-proc.\n\n1115\n01:00:11,210 --> 01:00:12,710\n一旦你了解怎么做 实现就很容易了\nOnce you have the idea, it's easy to implement.\n\n1116\n01:00:12,710 --> 01:00:16,768\nMEMO-PROC中有两个标记变量\nMemo-proc is this little thing that has two little flags in there.\n\n1117\n01:00:17,390 --> 01:00:19,200\nALREADY-RUN?用于记录是否运行过\nIt says, have I already been run?\n\n1118\n01:00:20,320 --> 01:00:22,480\n初始值是NIL 指示没运行过\nAnd initially it says, no, I haven't already been run.\n\n1119\n01:00:23,620 --> 01:00:27,040\nRESULT用于存储上一次计算的结果\nAnd what was the result I got the last time I was run?\n\n1120\n01:00:29,070 --> 01:00:31,072\nMEMO-PROC接收一个过程PROC\nSo memo-proc takes a procedure called proc,\n\n1121\n01:00:31,568 --> 01:00:34,016\n返回一个新的无参过程\nand it returns a new procedure of no arguments.\n\n1122\n01:00:34,360 --> 01:00:36,384\nPROC也是一个无参过程\nProc is supposed to be a procedure of no arguments.\n\n1123\n01:00:38,610 --> 01:00:41,376\n它会判断 -- 如果没有运行过\nAnd it says, oh, if I'm not already run,\n\n1124\n01:00:42,592 --> 01:00:44,064\n就进行一系列的运算\nthen I'm going to do a sequence of things.\n\n1125\n01:00:44,430 --> 01:00:46,560\n先计算PROC\nI'm going to compute proc,\n\n1126\n01:00:47,504 --> 01:00:48,450\n然后存储它的值\nI'm going to save that.\n\n1127\n01:00:48,450 --> 01:00:50,480\n存储在变量RESULT中\nI'm going to stash that in the variable result.\n\n1128\n01:00:51,140 --> 01:00:53,904\n然后对ALREADY-RUN?赋值 提醒自己已经运行过了\nI'm going to make a note to myself that I've already been run,\n\n1129\n01:00:54,288 --> 01:00:55,472\n最后返回RESULT\nand then I'll return the result.\n\n1130\n01:00:56,610 --> 01:00:59,010\n所以之前如果没运行过 就执行一次计算\nSo that's if you compute it if it's not already run.\n\n1131\n01:00:59,010 --> 01:01:01,888\n当你调用它 但已经运行过了 就直接返回结果\nIf you call it and it's already been run, it just returns the result.\n\n1132\n01:01:03,420 --> 01:01:07,120\n这种聪明的小技巧被称作“记忆化”\nSo that's a little clever hack called memoization.\n\n1133\n01:01:08,400 --> 01:01:09,136\n这样的话\nAnd in this case,\n\n1134\n01:01:10,352 --> 01:01:14,144\n就不会重复的计算TAIL了\nit short circuits having to re-compute the tail of the tail of the tail of the tail of the tail.\n\n1135\n01:01:15,270 --> 01:01:17,810\n不再那样的没效率了\nSo there isn't even that kind of inefficiency.\n\n1136\n01:01:17,810 --> 01:01:18,720\n事实上 流式程序设计\nAnd in fact, the streams\n\n1137\n01:01:19,200 --> 01:01:22,752\n甚至和传统的那种程序一样有效\nwill run with pretty much the same efficiency as the other programs precisely.\n\n1138\n01:01:24,016 --> 01:01:26,208\n再强调一下 整个的思想在于\nAnd remember, again, the whole idea of this\n\n1139\n01:01:27,480 --> 01:01:28,608\n我们已经讲过\nis that we've used\n\n1140\n01:01:29,264 --> 01:01:32,400\n过程与数据之间\nthe fact that there's no really good dividing line\n\n1141\n01:01:32,416 --> 01:01:33,610\n没有一个明确的分界线\nbetween procedures and data.\n\n1142\n01:01:33,610 --> 01:01:35,616\n事实上 我们把数据结构组织得\nWe've written data structures that, in fact,\n\n1143\n01:01:36,000 --> 01:01:37,312\n像一个过程\nare sort of like procedures.\n\n1144\n01:01:38,760 --> 01:01:40,736\n它使得我们能够\nAnd what that's allowed us to do\n\n1145\n01:01:41,584 --> 01:01:46,544\n可以实现一种常见的控制结构\nis take an example of a common control structure,\n\n1146\n01:01:46,688 --> 01:01:48,912\n在本例中是迭代\nin this place iteration.\n\n1147\n01:01:49,620 --> 01:01:51,056\n我们创建了一种数据结构\nAnd we've built a data structure\n\n1148\n01:01:51,328 --> 01:01:52,848\n由于这种数据结构本身是一个过程\nwhich, since itself is a procedure,\n\n1149\n01:01:52,864 --> 01:01:55,120\n它其中就可以有某种控制结构\nkind of has this iteration control structure in it.\n\n1150\n01:01:55,792 --> 01:01:57,136\n这就是流的实质\nAnd that's really what streams are.\n\n1151\n01:01:58,912 --> 01:01:59,760\n好 大家有什么问题吗？\nOK, questions?\n\n1152\n01:02:03,950 --> 01:02:05,840\n学生：你刚才说(TAIL (TAIL (TAIL ...\nAUDIENCE: Your description of tail-tail-tail,\n\n1153\n01:02:05,856 --> 01:02:07,168\n如果我没理解错的话\nif I understand it correctly,\n\n1154\n01:02:07,280 --> 01:02:10,768\n没有没有MEMO-PROC的话\nforce is actually execution of a procedure,\n\n1155\n01:02:10,784 --> 01:02:12,832\nFORCE实际上执行了一个过程\nif it's done without this memo-proc thing.\n\n1156\n01:02:12,896 --> 01:02:13,152\n教授：是的\nPROFESSOR: Right.\n\n1157\n01:02:13,440 --> 01:02:16,380\n学生：你说使用那个MEMO-PROC就不会有那样的问题\nAUDIENCE: And you implied that memo-proc gets around that problem.\n\n1158\n01:02:16,380 --> 01:02:18,736\n这难道不需要保证\nDoesn't it only get around it if\n\n1159\n01:02:19,344 --> 01:02:22,192\n(TAIL (TAIL (TAIL 每次的计算结构都是一致的么？\ntail-tail-tail is always executing exactly the same--\n\n1160\n01:02:22,416 --> 01:02:23,910\n教授：哦 当然\nPROFESSOR: Oh, that's-- sure.\n\n1161\n01:02:23,910 --> 01:02:25,840\n学生：我可能是漏了什么知识点\nAUDIENCE: I guess I missed that point.\n\n1162\n01:02:26,050 --> 01:02:27,216\n教授：你说得很对 这里 --\nPROFESSOR: Oh, sure. I mean the point is--  yeah.\n\n1163\n01:02:31,120 --> 01:02:33,648\n首先 为了获得结果需要进行一次计算\nYeah, I mean I have to do a computation to get the answer.\n\n1164\n01:02:34,096 --> 01:02:36,768\n关键在于 一旦得到 (TAIL STREAM)\nBut the point is, once I've found the tail of the stream,\n\n1165\n01:02:37,584 --> 01:02:38,704\n再计算 (TAIL (TAIL STREAM)) 的时候\nto get the tail of the tail,\n\n1166\n01:02:38,704 --> 01:02:40,512\n就不用再计算最内部的TAIL了\nI shouldn't have had to re-compute the first tail.\n\n1167\n01:02:42,980 --> 01:02:44,320\n明白了吧 如果我没有用MEMO-PROC\nSee, and if I didn't use memo-proc,\n\n1168\n01:02:44,352 --> 01:02:46,096\n还要再计算一遍 (TAIL STREAM)\nthat re-computation would have been done.\n\n1169\n01:02:46,460 --> 01:02:47,136\n学生：明白了\nAUDIENCE: I understand now.\n\n1170\n01:02:50,830 --> 01:02:52,560\n学生：之前的例子中你提到过\nAUDIENCE: In one of your examples, you mentioned that\n\n1171\n01:02:52,608 --> 01:02:54,224\n我们之所以可以使用代换模型\nwe were able to use the substitution model\n\n1172\n01:02:54,224 --> 01:02:56,112\n是因为这里没有副作用\nbecause there are no side effects.\n\n1173\n01:02:56,830 --> 01:03:00,736\n如果我们的信号处理单元\nWhat if we had a signal processing unit--\n\n1174\n01:03:00,784 --> 01:03:02,032\n具有副作用\nif we had a side effect,\n\n1175\n01:03:02,048 --> 01:03:03,040\n具有内部状态\nif we had a state?\n\n1176\n01:03:03,620 --> 01:03:06,848\n我们还有效地构建流模型么？\nCould we still practically build the stream model?\n\n1177\n01:03:08,464 --> 01:03:10,592\n教授：可能吧 这是一个很困难的问题\nPROFESSOR: Hum... Maybe, That's a hard question.\n\n1178\n01:03:11,200 --> 01:03:13,424\n关于代换模型和副作用并不是很兼容这一点\nI'm going to talk a little bit later about the places where\n\n1179\n01:03:14,368 --> 01:03:18,240\n我以后会稍稍地讲解一下\nwhere substitution and side effects don't really mix very well.\n\n1180\n01:03:18,960 --> 01:03:20,480\n但大体来说 我认为\nBut in general, I think the answer is\n\n1181\n01:03:20,496 --> 01:03:21,632\n除非你非常小心\nunless you're very careful,\n\n1182\n01:03:21,904 --> 01:03:24,464\n否则副作用会把一切弄得很糟糕\nany amount of side effect is going to mess up everything.\n\n1183\n01:03:35,040 --> 01:03:38,256\n学生：我不是很理解MEMO-PROC这个过程\nAUDIENCE: Sorry, I didn't quite understand the memo-proc operation. Uh...\n\n1184\n01:03:39,680 --> 01:03:41,120\n你是什么时候执行那个LAMBDA的？\nWhen do you execute the lambda?\n\n1185\n01:03:41,990 --> 01:03:43,216\n换句话说\nIn other words,\n\n1186\n01:03:43,680 --> 01:03:45,152\n当MEMO-PROC执行的时候\nwhen memo-proc is executed,\n\n1187\n01:03:45,184 --> 01:03:47,712\n只生成了LAMBDA表达式\njust this lambda expression is being generated.\n\n1188\n01:03:48,010 --> 01:03:49,680\n但我不太清楚它是什么时候被执行的\nBut it's not clear to me when it's executed.\n\n1189\n01:03:50,390 --> 01:03:51,120\n教授：好的\nPROFESSOR: Right.\n\n1190\n01:03:51,350 --> 01:03:52,688\nMEMO-PROC所做的 --\nWhat memo-proc does-- remember,\n\n1191\n01:03:53,072 --> 01:03:55,856\nMEMO-PROC的一个参数是PROC\nthe thing that's going into memo-proc, the thing proc,\n\n1192\n01:03:56,384 --> 01:03:57,930\n一个没有参数的过程\nis a procedure of no arguments.\n\n1193\n01:03:57,930 --> 01:03:59,056\n某个时刻 你会调用它\nAnd someday, you're going to call it.\n\n1194\n01:04:00,390 --> 01:04:02,752\nMEMO-PROC把该过程转化为\nMemo-proc translates that procedure\n\n1195\n01:04:02,752 --> 01:04:04,560\n另一个无参过程\ninto another procedure of no arguments,\n\n1196\n01:04:04,592 --> 01:04:05,808\n某个时刻你会调用到它\nwhich someday you're going to call.\n\n1197\n01:04:06,620 --> 01:04:07,424\nLAMBDA语句做的是这个\nThat's that lambda.\n\n1198\n01:04:09,890 --> 01:04:14,080\n所以在这里 我最初构造\nSo here, where I initially built as my\n\n1199\n01:04:15,856 --> 01:04:17,920\n构造流的TAIL的时候\nI built as my tail of the stream,\n\n1200\n01:04:18,304 --> 01:04:20,480\n这里的这个无参过程\nsay, this procedure of no arguments,\n\n1201\n01:04:20,512 --> 01:04:21,616\n会在之后的某个时刻调用\nwhich someday I'll call.\n\n1202\n01:04:24,100 --> 01:04:28,016\n相对应的 我要对(TAIL STREAM)调用MEMO-PROC\nInstead, I'm going to have the tail of the stream be memo-proc of it,\n\n1203\n01:04:28,128 --> 01:04:29,248\n以后我会调用生成的过程\nwhich someday I'll call.\n\n1204\n01:04:30,650 --> 01:04:31,904\n所以这个无参的LAMBDA\nSo that lambda of nil,\n\n1205\n01:04:32,032 --> 01:04:36,064\n是当你在调用MEMO-PROC时调用的\nthat gets called when you call the memo-proc,\n\n1206\n01:04:38,976 --> 01:04:40,960\n当你调用MEMP-PROC返回的过程时\nwhen you call the result of that memo-proc,\n\n1207\n01:04:40,970 --> 01:04:42,288\n也就会像通常的过程调用那样\nwhich would be ordinarily\n\n1208\n01:04:42,368 --> 01:04:45,760\n调用你最初设定的那个函数\nwhen you would have called the original thing that you set it.\n\n1209\n01:04:47,640 --> 01:04:48,864\n学生：我想问的是\nAUDIENCE: OK, my ask is\n\n1210\n01:04:48,864 --> 01:04:50,864\n当你调用MEMO-PROC的时候\nI had a feeling that when you call memo-proc,\n\n1211\n01:04:50,864 --> 01:04:52,304\n你返回了这个LAMBDA\nyou just return this lambda.\n\n1212\n01:04:52,610 --> 01:04:53,072\n教授：是的\nPROFESSOR: That's right.\n\n1213\n01:04:53,770 --> 01:04:58,100\n你调用MEMO-PROC的时候 返回了一个LAMBDA\nWhen you call memo-proc, you return the lambda.\n\n1214\n01:04:58,100 --> 01:04:59,840\n直到你第一次需要执行它的时候\nYou never evaluate the expression at all,\n\n1215\n01:04:59,872 --> 01:05:02,270\n你才去求值<EXP>\nuntil the first time that you would have evaluated it.\n\n1216\n01:05:07,760 --> 01:05:09,104\n学生：我这样理解对吗？\nAUDIENCE: Do I understand it right\n\n1217\n01:05:09,184 --> 01:05:11,408\n你构造了一个表\nyou actually have to build the list up,\n\n1218\n01:05:11,472 --> 01:05:14,176\n但表中的元素还没有被求值\nbut the elements of the list don't get evaluated?\n\n1219\n01:05:14,240 --> 01:05:15,630\n表达式没有被求值？\nThe expressions don't get evaluated?\n\n1220\n01:05:15,630 --> 01:05:18,540\n但在每个阶段 你还是构造了一个表\nBut at each stage, you actually are building a list.\n\n1221\n01:05:18,540 --> 01:05:20,700\n教授：啊 我应该这样说\nPROFESSOR: That's-- I really should have said this.\n\n1222\n01:05:20,700 --> 01:05:22,270\n这个想法很好\nThat's a really good point.\n\n1223\n01:05:22,270 --> 01:05:23,184\n但是 也不全对\nNo, it's not quite right.\n\n1224\n01:05:23,660 --> 01:05:25,080\n因为实际发生的事情是这样的\nSee, cause what happens is this.\n\n1225\n01:05:25,080 --> 01:05:26,352\n我先把这个画成序对\nLet me draw this as pairs.\n\n1226\n01:05:26,890 --> 01:05:28,032\n假设我要构造一个特别大的流\nSuppose I'm going to make a big stream,\n\n1227\n01:05:28,960 --> 01:05:30,128\n比如枚举一段区间\nlike enumerate interval,\n\n1228\n01:05:30,320 --> 01:05:31,488\n从1到1,000,000,000\n1 through 1 billion.\n\n1229\n01:05:32,740 --> 01:05:35,744\n这实际上是一个序对\nWhat that is, is a pair\n\n1230\n01:05:39,344 --> 01:05:43,360\n由1和一个PROMISE组成\na 1 and a promise.\n\n1231\n01:05:46,736 --> 01:05:47,890\n就是这样\nThat's exactly what it is.\n\n1232\n01:05:47,890 --> 01:05:48,768\n什么都没有构造\nNothing got built up.\n\n1233\n01:05:51,600 --> 01:05:53,296\n当我继续FORCE这个PROMISE\nWhen I go and force this,\n\n1234\n01:05:54,512 --> 01:05:56,370\n再来看看 会发生什么\nand see, what happens?\n\n1235\n01:05:56,370 --> 01:05:59,664\n这个东西现在就成为了一个递归CONS\nWell, this thing is now also recursively a CONS.\n\n1236\n01:06:00,530 --> 01:06:02,160\n所以这个PROMISE现在就变成了\nSo that this promise now is\n\n1237\n01:06:04,620 --> 01:06:08,960\n一个2和做更多事情的PROMISE\nthe next thing, which is a 2 and a promise to do more.\n\n1238\n01:06:11,350 --> 01:06:12,736\n一直这样下去\nAnd so on and so on and so on.\n\n1239\n01:06:14,470 --> 01:06:17,632\n直到你走完整个流才完整地构建了一个表\nSo nothing gets built up until you walk down the stream.\n\n1240\n01:06:18,200 --> 01:06:19,584\n因为这个东西不是表\nBecause what's sitting here is not the list,\n\n1241\n01:06:20,032 --> 01:06:21,488\n只是一个生成表的PROMISE\nbut a promise to generate the list.\n\n1242\n01:06:23,392 --> 01:06:25,500\n技术上来说 PROMISE就是一个过程\nAnd by promise, technically I mean procedure.\n\n1243\n01:06:27,808 --> 01:06:29,104\n因此并没有直接构造好一个表\nSo it doesn't get built up.\n\n1244\n01:06:30,768 --> 01:06:32,720\n我应该早点说的\nYeah, I should have said that before that.\n\n1245\n01:06:34,280 --> 01:06:35,344\n好吧 就到这里 下课\nOK. That you. Let's take a break.\n\n1246\n01:06:35,824 --> 01:06:42,960\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n1247\n01:06:42,960 --> 01:06:51,152\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec6b.srt",
    "content": "﻿1\n00:00:00,032 --> 00:00:03,728\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:03,984 --> 00:00:07,264\n翻译&&时间轴：张大伟（DreamAndDead）\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:07,408 --> 00:00:10,272\n特别感谢：裘宗燕教授\n\n4\n00:00:10,400 --> 00:00:14,928\n计算机程序的构造和解释\n\n5\n00:00:15,056 --> 00:00:19,408\n流 II\nStream\n\n6\n00:00:20,970 --> 00:00:24,080\n教授：上节课 我们介绍了流\nPROFESSOR: OK, well, we've been looking at streams,\n\n7\n00:00:24,080 --> 00:00:27,824\n按照信号处理的方式来组织系统\nthis signal processing way of putting systems together.\n\n8\n00:00:28,870 --> 00:00:31,424\n要记住的是 关键点在于\nAnd remember, the key idea is that\n\n9\n00:00:31,904 --> 00:00:32,960\n我们分离开\nwe decouple\n\n10\n00:00:34,208 --> 00:00:37,312\n程序中 事件表面上的顺序\nthe apparent order of events in our programs\n\n11\n00:00:37,584 --> 00:00:40,176\n与机器中的实际计算顺序\nfrom the actual order of events in the computer.\n\n12\n00:00:41,072 --> 00:00:42,288\n那就意味着 我们可以\nAnd that means that we can start\n\n13\n00:00:42,576 --> 00:00:44,144\n着手处理非常长的流\ndealing with very long streams\n\n14\n00:00:44,896 --> 00:00:47,392\n并且只有在需要的时候才生成其中的元素\nand only having to generate the elements on demand.\n\n15\n00:00:47,536 --> 00:00:49,392\n这种按需计算的方式\nThat sort of on-demand computation\n\n16\n00:00:49,520 --> 00:00:51,408\n是内建在流的数据结构中的\nis built into the stream's data structure.\n\n17\n00:00:54,110 --> 00:00:55,648\n即使这个流非常之长\nSo if we have a very long stream,\n\n18\n00:00:55,664 --> 00:00:57,080\n我们只计算所需要的\nwe only compute what we need.\n\n19\n00:00:58,040 --> 00:01:00,750\n只有当我们要求的时候 新的数据才会生成\nThe things only get computed when we actually ask for them.\n\n20\n00:01:00,750 --> 00:01:01,744\n要举个什么样的例子呢？\nWell, what are examples?\n\n21\n00:01:02,110 --> 00:01:03,600\n这个“按需”是什么个情况呢？\nAre they actually asking for them?\n\n22\n00:01:05,024 --> 00:01:06,016\n举个例子\nFor instance, we might\n\n23\n00:01:09,216 --> 00:01:11,376\n我们可能会想要一个流中的第N个元素\nmight ask for the n-th element of a stream.\n\n24\n00:01:15,360 --> 00:01:18,928\n这个过程可以用于计算流的第N个元素\nHere's a procedure that computes the n-th element of a stream.\n\n25\n00:01:20,090 --> 00:01:21,232\n一个参数为索引N\nAn integer n,\n\n26\n00:01:21,248 --> 00:01:22,848\n另一个参数是流S\nthe n-th element of some stream s,\n\n27\n00:01:23,408 --> 00:01:25,424\n递归遍历这个流即可求解\nand we just recursively walk down the stream.\n\n28\n00:01:25,570 --> 00:01:27,392\n如果N为0 我们就计算头部分\nAnd if n is 0, we compute the head.\n\n29\n00:01:27,960 --> 00:01:30,992\n否则 就在流的尾部分\nOtherwise, it's the n-th the minus 1 element\n\n30\n00:01:31,744 --> 00:01:32,800\n查找第N-1个元素\nof the stream.\n\n31\n00:01:34,310 --> 00:01:36,432\n看起来是Lisp中很普通的编程方式 但是不同的是\nThose two are just like for Lisp, but the difference\n\n32\n00:01:36,624 --> 00:01:38,768\n直到我们不断遍历 取得相继的N个元素\nis those elements aren't going to get computed\n\n33\n00:01:38,864 --> 00:01:40,992\n这些元素才被计算出来\nuntil we walk down, taking successive n-ths.\n\n34\n00:01:41,520 --> 00:01:44,784\n这是这些流元素可能被FORCE的一种方式\nSo that's one way that the stream elements might get forced.\n\n35\n00:01:45,776 --> 00:01:46,640\n另外一种方式则是\nAnd another way,\n\n36\n00:01:47,184 --> 00:01:48,928\n这里有个简单的过程 用来打印一个流\nhere's a little procedure that prints a stream.\n\n37\n00:01:49,300 --> 00:01:50,384\n它的定义是\nWe say print a stream,\n\n38\n00:01:51,904 --> 00:01:53,280\n过程PRINT-STREAM的定义是\nso to print a stream s.\n\n39\n00:01:54,150 --> 00:01:55,120\n我们要怎么做呢？\nWell, what do we do? We'll\n\n40\n00:01:55,744 --> 00:01:56,864\n先打印流的头部分\nWe print the head of the stream,\n\n41\n00:01:57,744 --> 00:01:59,328\n流的头部分在这时就被计算出来\nand that will cause the head to be computed.\n\n42\n00:01:59,720 --> 00:02:02,848\n然后我们再递归地打印流的尾部分\nAnd then we recursively print stream the tail of the stream.\n\n43\n00:02:04,990 --> 00:02:06,032\n完成以后\nAnd if we're already done,\n\n44\n00:02:06,048 --> 00:02:08,576\n就返回一个的表示完成的消息 “DONE”\nmaybe we have to return something about the message done.\n\n45\n00:02:09,660 --> 00:02:11,392\n如果你构造了一个流\nOK, and then so if you make a stream,\n\n46\n00:02:11,648 --> 00:02:13,648\n这个流非常的长\nyou could say here's the stream, this very long stream.\n\n47\n00:02:14,310 --> 00:02:16,336\n当你调用这个过程\nAnd then you say print the stream,\n\n48\n00:02:16,416 --> 00:02:19,776\n流中的元素会随着PRINT-STREAM的调用\nand the elements of the stream will get computed successively\n\n49\n00:02:19,872 --> 00:02:21,120\n而被依次计算出来\nas that print calls them.\n\n50\n00:02:21,320 --> 00:02:22,816\n不会在一开始就全部计算出来\nThey won't get all computed initially.\n\n51\n00:02:24,300 --> 00:02:25,664\n正因为如此 我们能够\nSo in this way, we can\n\n52\n00:02:27,504 --> 00:02:29,610\n我们能够处理非常长的流\nSo in this way, we can deal with some very long streams.\n\n53\n00:02:30,190 --> 00:02:31,920\n多长呢？\nWell, how long can a stream be?\n\n54\n00:02:33,744 --> 00:02:35,120\n可以是无限长\nWell, it can be infinitely long.\n\n55\n00:02:35,904 --> 00:02:38,048\n我们在计算机上实践一下\nLet's look at an example here on the computer.\n\n56\n00:02:38,920 --> 00:02:41,968\n我可以在计算机前输入\nI could walk up to this computer, and I could say--\n\n57\n00:02:43,488 --> 00:02:53,312\n我先定义一个函数 (INTEGERS-FROM N)\nhow about we'll define the stream of integers starting with some number N,\n\n58\n00:02:54,240 --> 00:02:57,136\n用于生成一个从N开始的正整数流\nthe stream of positive integers starting with some number n.\n\n59\n00:03:00,360 --> 00:03:19,168\n也就是 (CONS-STREAM N (INTEGERS-FROM (+ N 1))))\nAnd that's cons-stream of n onto the integers from one more.\n\n60\n00:03:24,416 --> 00:03:25,616\n这样就我们要的全部整数\nSo there are the integers.\n\n61\n00:03:28,992 --> 00:03:31,500\n现在我来尝试得到所有的整数\nThen I could say let's get all the integers.\n\n62\n00:03:34,570 --> 00:03:44,336\n(DEFINE INTEGERS (INTEGERS-FROM 1))\ndefine the stream of integers to be the integers starting with 1.\n\n63\n00:03:48,840 --> 00:03:50,944\n如果现在我执行 (NTH-STREAM 20 INTEGERS)\nAnd now if I say something like\n\n64\n00:03:54,416 --> 00:03:55,800\n来查看第20个元素\nwhat's the what's the 20th integer.\n\n65\n00:04:03,424 --> 00:04:05,536\n得到21 因为索引是从0开始的\nSo it's 21 because we start counting at 0.\n\n66\n00:04:06,848 --> 00:04:08,880\n或者我们来点更复杂的\nOr I can do more complicated things.\n\n67\n00:04:09,450 --> 00:04:10,840\n我再来定义一个谓词\nLet me to define a little predicate here.\n\n68\n00:04:11,776 --> 00:04:18,512\n谓词NO-SEVEN用来检测是否为7的倍数\nHow about define no-seven.\n\n69\n00:04:19,580 --> 00:04:20,752\n它的判定方法是这样的：\nIt's going to test an integer,\n\n70\n00:04:21,792 --> 00:04:23,168\n如果整数X不是7的倍数\nand it's going to say it's not.\n\n71\n00:04:28,820 --> 00:04:33,968\n我取X除7的余数\nI take the remainder of x by 7,\n\n72\n00:04:36,624 --> 00:04:38,352\n余数不应该为0\nI don't get 0.\n\n73\n00:04:43,808 --> 00:04:49,776\n这时用NO-SEVEN这个谓词\nAnd then I could say define the integers with no sevens\n\n74\n00:04:50,224 --> 00:04:59,120\n过滤全部的整数\ntake all the integers and filter them to have no sevens.\n\n75\n00:05:11,570 --> 00:05:13,344\n这样我就得到了所有的\nSo now I've got the stream of all the integers\n\n76\n00:05:13,632 --> 00:05:15,056\n不是7的倍数的整数构成的流\nthat are not divisible by seven.\n\n77\n00:05:16,490 --> 00:05:23,440\n如果我问 这些不是7的倍数的整数中\nSo if I say what's the 100th integer\n\n78\n00:05:24,704 --> 00:05:26,480\n的第100个数是多少？\nand the list not divisible by seven,\n\n79\n00:05:26,864 --> 00:05:28,112\n结果是117\nI get 117.\n\n80\n00:05:28,320 --> 00:05:30,672\n或者我也可以问\nOr if I'd like to say well, I could say ah.\n\n81\n00:05:32,304 --> 00:05:34,384\n这个流的所有元素都是些什么？\nwell, gee, what are all of them?\n\n82\n00:05:35,270 --> 00:05:40,352\n我可以用(PRINT-STREAM NS)来尝试打印这个流\nSo I could say print stream all these integers with no seven,\n\n83\n00:05:40,832 --> 00:05:41,792\n它就会输出个不停\nit goes off printing.\n\n84\n00:05:45,100 --> 00:05:47,070\n你可能需要等上很久才能得到全部结果\nYou may have to wait a very long time to see them all.\n\n85\n00:05:52,670 --> 00:05:53,840\n你可能会问了\nWell, you can start asking, gee,\n\n86\n00:05:54,816 --> 00:05:57,008\n这个数据结构\nyou know, is it really true that this data structure\n\n87\n00:05:58,288 --> 00:06:00,656\n真的全部是由整数构成的吗？\nwith the integers is really all the integers?\n\n88\n00:06:01,100 --> 00:06:04,053\n现在我画一个图来演示下刚写的那个程序\nAnd let me draw a picture of that program I just wrote.\n\n89\n00:06:04,960 --> 00:06:10,570\n这是我刚才键入的整数定义\nHere's the, right, here's the definition of the integers again that I just typed in,\n\n90\n00:06:12,336 --> 00:06:15,984\n它是一个由第一个整数和由下一个整数生成的流 所构成的序对\nRight it's a cons of the first integer under the integer starting with the rest.\n\n91\n00:06:17,616 --> 00:06:19,770\n现在我们画个图来看看它到底是什么样\nNow, we can make a picture of that and see what it looks like.\n\n92\n00:06:22,720 --> 00:06:24,320\n从概念上来说 这应该是一个盒子\nConceptually, what I have is a box\n\n93\n00:06:25,536 --> 00:06:27,184\n这个盒子是(INTEGER-FROM N)\nthat's the integer starting with n.\n\n94\n00:06:27,420 --> 00:06:29,088\n它接受一个参数N\nIt takes in some number n,\n\n95\n00:06:31,424 --> 00:06:32,976\n然后返回一个流\nand it's going to return a stream of--\n\n96\n00:06:35,024 --> 00:06:37,360\n这个无穷流表示从N开始的所有整数\nthis infinite stream of all integers starting with n.\n\n97\n00:06:38,080 --> 00:06:38,736\n我要做什么呢？\nAnd what do I do?\n\n98\n00:06:38,752 --> 00:06:42,384\n呃 这个是INT-FROM盒子\nWell, this is an integers-from box.\n\n99\n00:06:45,070 --> 00:06:45,800\n里面是什么样子呢？\nWhat's it got in it?\n\n100\n00:06:45,800 --> 00:06:48,608\n取得参数N之后\nWell, it takes in this n,\n\n101\n00:06:52,272 --> 00:06:53,920\n将其 +1\nand it increments it.\n\n102\n00:06:57,952 --> 00:07:03,150\n然后把结果递归地传递给另一个INT-FROM盒子\nAnd then it puts the result into recursively another integer's from box.\n\n103\n00:07:06,870 --> 00:07:09,600\n把这个盒子的结果和最初的N\nIt takes the result of that and the original n\n\n104\n00:07:10,240 --> 00:07:12,784\n用CONS组合起来\nand puts those together with a cons\n\n105\n00:07:13,392 --> 00:07:14,360\n就形成了一个流\nand forms a stream.\n\n106\n00:07:14,576 --> 00:07:17,264\n我刚才写的那个过程 画出来就是这样子\nSo that's a picture of that program I wrote. And this is a ...\n\n107\n00:07:18,528 --> 00:07:20,320\n我们看到的这类图像\nLet's see. These kind of diagrams we first saw\n\n108\n00:07:20,784 --> 00:07:21,740\n首先是由Peter Henderson提出的\ndrawn by Peter Henderson,\n\n109\n00:07:21,760 --> 00:07:23,320\n也就是前面课程中绘图语言的发明者\nthe same guy who did the Escher language.\n\n110\n00:07:23,320 --> 00:07:24,752\n我们把这种图叫做Henderson图\nWe call them Henderson diagrams.\n\n111\n00:07:25,376 --> 00:07:27,904\n画这种图需要遵守一定的约定\nAnd the convention here is that you put these things together.\n\n112\n00:07:28,530 --> 00:07:32,512\n这些实线代表输出的流\nAnd the solid lines are things coming out are streams,\n\n113\n00:07:33,024 --> 00:07:36,208\n这些虚线则是初始的输入值\nand dotted lines are initial values going in.\n\n114\n00:07:37,270 --> 00:07:39,024\n而这个图描述的形状是——\nSo this one has the shape of--\n\n115\n00:07:39,408 --> 00:07:41,600\n它会取一个整数作为初始值\nit takes in some integer, some initial value,\n\n116\n00:07:41,808 --> 00:07:42,912\n然后输出一个流\nand outputs a stream.\n\n117\n00:07:46,352 --> 00:07:48,224\n现在 你可能又要问了\nAgain, you can ask. You know it's really\n\n118\n00:07:48,380 --> 00:07:50,880\n那个INTEGERS的数据结构真的全部都是整数吗？\nIs that data structure integers really all the integers?\n\n119\n00:07:52,090 --> 00:07:54,912\n或者它只是经过了精心组织\nAlright? Or is it is something that's cleverly arranged\n\n120\n00:07:54,940 --> 00:07:56,432\n以至于总可以在其中找到\nso that whenever you look for an integer\n\n121\n00:07:56,448 --> 00:07:57,240\n我们需要的那个整数？\nyou find it there?\n\n122\n00:07:57,950 --> 00:07:59,744\n这有点像个哲学问题 不是么？\nThat's sort of a philosophical question, right?\n\n123\n00:07:59,780 --> 00:08:01,696\n如果有一个东西\nIf something is there\n\n124\n00:08:02,144 --> 00:08:03,968\n你不去观测它 能否知道它“存在”呢？\nwhenever you look, is it really there or not?\n\n125\n00:08:04,450 --> 00:08:07,344\n这就有点像\nIt's sort of the same sense in which\n\n126\n00:08:07,360 --> 00:08:09,420\n你在银行中的存款那样\nthe money in your savings account is in the bank.\n\n127\n00:08:12,380 --> 00:08:12,640\n好吧\nWell\n\n128\n00:08:16,352 --> 00:08:17,488\n我们再来看一个例子\nlet me do another example.\n\n129\n00:08:18,680 --> 00:08:20,704\n这门课的第一节课\nUmm, Gee, we started the course\n\n130\n00:08:20,720 --> 00:08:22,720\n我们就讲了一个来自于亚历山大的算法\nwith an algorithm from Alexandria,\n\n131\n00:08:23,296 --> 00:08:25,800\n来自亚历山大的Heron提出的\nwhich was Heron of Alexandria's algorithm\n\n132\n00:08:25,824 --> 00:08:26,944\n一个用于计算平方根的算法\nfor computing the square root.\n\n133\n00:08:28,470 --> 00:08:32,030\n现在再来看一个 同样来自于亚力山大的算法\nLet's take a look at another Alexandrian algorithm.\n\n134\n00:08:32,030 --> 00:08:35,088\n这个被称为Eratosthenes算法的方法\nThis one is Eratosthenes method for\n\n135\n00:08:36,192 --> 00:08:38,448\n用于计算所有的质数\nfor computing all of the primes.\n\n136\n00:08:41,169 --> 00:08:42,830\n它被称为Eratosthenes筛法\nIt is called the Sieve of Eratosthenes.\n\n137\n00:08:42,830 --> 00:08:49,728\n它是这样的 一开始\nAnd what you do is you start out,\n\n138\n00:08:50,992 --> 00:08:52,288\n先列举所有的整数\nand you list all the integers,\n\n139\n00:08:52,608 --> 00:08:53,536\n从2开始\nsay, starting with 2.\n\n140\n00:08:53,880 --> 00:08:55,040\n然后取第一个整数\nAnd then you take the first integer, and you say,\n\n141\n00:08:55,088 --> 00:08:56,670\n然后你发现 哦 2是一个质数\nand you say, oh, that's prime.\n\n142\n00:08:57,310 --> 00:08:58,352\n然后你考察剩余的整数\nAnd then you go look at the rest,\n\n143\n00:08:58,688 --> 00:09:00,880\n划掉其中可以被2整除的数\nand you cross out all the things divisible by 2.\n\n144\n00:09:01,520 --> 00:09:04,736\n我把这个划掉 还有这个 这个\nSo I cross out this and this and this.\n\n145\n00:09:05,250 --> 00:09:06,352\n有点费时\nThis takes a long time\n\n146\n00:09:06,368 --> 00:09:08,912\n我要对所有的整数进行这样的操作\nbecause I have to do it for all of the integers.\n\n147\n00:09:11,160 --> 00:09:15,392\n我遍历整个整数表\nSo I go through the entire list of integers,\n\n148\n00:09:18,272 --> 00:09:20,944\n划掉所有被2整除的数\ncrossing the ones divisible by 2.\n\n149\n00:09:22,112 --> 00:09:24,384\n所有的整数都操作完后\nAnd now when I finish with all of the integers,\n\n150\n00:09:24,784 --> 00:09:26,720\n回过头再来看还剩些什么\nI go back and look and say what am I left with?\n\n151\n00:09:27,040 --> 00:09:28,800\n好的 下一个数就是3了\nWell, the first thing that starts there is 3.\n\n152\n00:09:29,330 --> 00:09:30,336\n3也是一个质数\nSo 3 is a prime.\n\n153\n00:09:30,770 --> 00:09:33,056\n现在 我会继续在剩下的数中\nAnd now I go back through what I'm left with,\n\n154\n00:09:33,360 --> 00:09:35,072\n划掉所有被3整除的数\nand I cross out all the things divisible by 3.\n\n155\n00:09:35,080 --> 00:09:43,808\n划掉 9、15、21、27、33 等等\nSo let's see, 9 and 15 and 21 and 27 and 33 and so on.\n\n156\n00:09:44,336 --> 00:09:45,120\n我就不往下划了\nI won't finish.\n\n157\n00:09:45,350 --> 00:09:46,528\n然后看看我们还剩下什么\nThen I see what I'm left with.\n\n158\n00:09:47,250 --> 00:09:49,840\n而下一个就是5了\nAnd the next one I have is 5.\n\n159\n00:09:50,496 --> 00:09:52,048\n我又遍历剩下的数\nNow I can through the rest,\n\n160\n00:09:52,432 --> 00:09:54,512\n找到第一个能被5整除的数\nand I find the first one that's divisible by 5.\n\n161\n00:09:54,540 --> 00:09:57,616\n把剩下的能被5整除的数都划掉\nI cross out from the remainder all the ones that are divisible by 5.\n\n162\n00:09:58,352 --> 00:09:59,248\n做完这个之后\nAnd I did that,\n\n163\n00:09:59,824 --> 00:10:01,890\n下一个数就是7\nand then I go through and find 7.\n\n164\n00:10:01,890 --> 00:10:02,720\n再遍历剩下的数\nGo through all the rest,\n\n165\n00:10:02,760 --> 00:10:03,952\n划掉所有被7整除的数\ncross out things divisible 7,\n\n166\n00:10:03,984 --> 00:10:05,470\n然后一直这样下去\nand I keep doing that forever.\n\n167\n00:10:06,810 --> 00:10:07,408\n全部结束的时候\nAnd when I'm done,\n\n168\n00:10:07,408 --> 00:10:09,104\n我也就得到了所有的质数\nwhat I'm left with is a list of all the primes.\n\n169\n00:10:09,904 --> 00:10:13,312\n这就是Eratosthenes筛法\nSo that's the Sieve of Eratosthenes.\n\n170\n00:10:15,430 --> 00:10:17,696\n我们来看下实际代码\nLet's look at it as a computer program.\n\n171\n00:10:17,930 --> 00:10:19,856\n这个过程命名为SIEVE\nIt's a procedure called sieve.\n\n172\n00:10:27,910 --> 00:10:29,408\n这是对应的代码\nNow, I just write what I did.\n\n173\n00:10:30,336 --> 00:10:34,480\nSIEVE过程 以一个流S为参数\nI'll say to sieve some stream s.\n\n174\n00:10:38,770 --> 00:10:39,936\n返回一个新的流\nI'm going to build a stream\n\n175\n00:10:40,272 --> 00:10:41,840\n新的流的头部分 就是流S的头部分\nwhose first element is the head of this.\n\n176\n00:10:41,870 --> 00:10:44,432\n回忆一下 我总是取剩下的数中的第一个\nRemember, I always found the first thing I was left with,\n\n177\n00:10:44,912 --> 00:10:48,752\n而尾部分则是把流S的尾部分\nand the rest of it is the result of taking the tail of S,\n\n178\n00:10:51,080 --> 00:10:53,728\n过滤掉所有\nfiltering it to throw away all the things\n\n179\n00:10:53,744 --> 00:10:55,320\n能被S头部分整除的数\nthat are divisible by the head of S,\n\n180\n00:10:56,416 --> 00:10:57,568\n然后再对结果筛选\nand now sieving the result.\n\n181\n00:10:59,020 --> 00:11:00,096\n这个代码就是这样\nThat's just what I did.\n\n182\n00:11:01,980 --> 00:11:04,688\n现在 为了得到由质数构成的无穷流\nAnd now to get the infinite stream of times,\n\n183\n00:11:05,024 --> 00:11:06,900\n我们对从2开始的整数流进行SIEVE\nwe just sieve all the integers starting from 2.\n\n184\n00:11:14,920 --> 00:11:15,568\n我们来实践一下\nLet's try that.\n\n185\n00:11:16,300 --> 00:11:18,304\n实际上 我们可以在计算机中运行\nWe can actually do it.\n\n186\n00:11:19,760 --> 00:11:22,128\n我希望我已经预先输入过SIEVE的定义了\nI typed in the definition of sieve before, I hope,\n\n187\n00:11:22,864 --> 00:11:24,064\n所以我可以定义\nso I can say something like\n\n188\n00:11:24,928 --> 00:11:33,456\n我可以把PRIMES定义为\ndefine the primes to be\n\n189\n00:11:34,640 --> 00:11:41,456\n(SIEVE (INTEGERS-FROM 2))\nthe result of sieving the integers starting with 2.\n\n190\n00:11:46,760 --> 00:11:48,100\n现在我就得到了质数构成的表\nSo now I've got this list of primes.\n\n191\n00:11:48,100 --> 00:11:50,990\n这样就得到了所有的质数 对吧？\nThat's all of the primes, right?\n\n192\n00:11:50,990 --> 00:11:53,520\n比如我可以问 第20个质数是什么？\nSo, if for example, what's the 20th prime in that list?\n\n193\n00:12:00,736 --> 00:12:01,680\n结果是73\n73.\n\n194\n00:12:02,540 --> 00:12:03,344\n那个短促的停顿\nSee, and that little pause,\n\n195\n00:12:03,360 --> 00:12:04,928\n这是因为\nit was only at the point\n\n196\n00:12:04,940 --> 00:12:06,432\n在我询问第20个元素时\nwhen I started asking for the 20th prime\n\n197\n00:12:06,464 --> 00:12:07,680\n它才进行实际的计算\nis that it started computing.\n\n198\n00:12:10,370 --> 00:12:11,296\n在这里 我也可以要求\nOr I can say here\n\n199\n00:12:13,808 --> 00:12:14,880\n打印所有的质数\nOr I can say here let's look at all of the primes.\n\n200\n00:12:22,640 --> 00:12:24,400\n解释器就开始计算并打印所有的质数\nAnd there it goes computing all of the primes.\n\n201\n00:12:25,350 --> 00:12:26,288\n得花上好一会儿\nOf course, it will take a while\n\n202\n00:12:26,288 --> 00:12:27,610\n才能打赢完整\nagain if I want to look at all of them,\n\n203\n00:12:27,792 --> 00:12:28,570\n所以先把它停掉\nso let's stop it.\n\n204\n00:12:32,030 --> 00:12:33,130\n让我来画图演示一下\nLet me draw you a picture of that.\n\n205\n00:12:33,130 --> 00:12:34,176\n我已经画好了\nWell, I've got a picture of that.\n\n206\n00:12:34,890 --> 00:12:36,192\n这个过程的图形应该是什么样子呢？\nWhat's that program really look like?\n\n207\n00:12:37,900 --> 00:12:39,776\n用这类图形的约定来说\nAgain, some practice with these diagrams,\n\n208\n00:12:39,824 --> 00:12:40,544\n我有一个叫SIEVE的盒子\nI have a sieve box.\n\n209\n00:12:42,610 --> 00:12:43,560\n它是如何运作的呢？\nHow does sieve work?\n\n210\n00:12:43,560 --> 00:12:44,810\n它以一个流作为输入\nIt takes in a stream.\n\n211\n00:12:48,850 --> 00:12:50,592\n分离流的头、尾部分\nIt splits off the head from the tail.\n\n212\n00:12:50,870 --> 00:12:53,264\n从SIEVE盒子出来的第一个东西\nAnd the first thing that's going to come out of the sieve\n\n213\n00:12:53,488 --> 00:12:54,976\n就是原来流的头部分\nis the head of the original stream.\n\n214\n00:12:58,208 --> 00:13:00,928\n头部分同样也用于这个盒子\nThen it also takes the head and uses that.\n\n215\n00:13:02,550 --> 00:13:05,104\n这个盒子会过滤流的尾部分\nIt takes the stream. It filters the tail\n\n216\n00:13:05,552 --> 00:13:08,336\n过滤的依据是 能否被头部分整除\nIt filters the tail and uses the head to filter for nondivisibility.\n\n217\n00:13:09,536 --> 00:13:11,184\n过滤得到的不可整除的那些数\nIt takes the result of nondivisibility\n\n218\n00:13:11,248 --> 00:13:13,120\n再放入另一个SIEVE盒子\nand puts it through another sieve box\n\n219\n00:13:13,904 --> 00:13:15,130\n然后把它们组合输出\nand puts the result together.\n\n220\n00:13:15,130 --> 00:13:16,896\n你可以把SIEVE想象为一个过滤器\nSo you can think of this sieve a filter,\n\n221\n00:13:17,200 --> 00:13:19,232\n只不过它是一个无穷递归的过滤器\nbut notice that it's an infinitely recursive filter.\n\n222\n00:13:19,650 --> 00:13:20,880\n这是因为在SIEVE盒子中\nBecause inside the sieve box\n\n223\n00:13:21,520 --> 00:13:22,608\n还有另外一个SIEVE盒子\nis another sieve box,\n\n224\n00:13:23,376 --> 00:13:25,856\n内部的盒子里面还有另外一个SIEVE盒子\nand inside that is another sieve box and another sieve box.\n\n225\n00:13:27,130 --> 00:13:28,960\n我们现在逐渐有了非常厉害的能力\nSo you see we start getting some very powerful things.\n\n226\n00:13:28,960 --> 00:13:32,848\n我们开始把 信号处理的方法\nWe're starting to mix this signal processing view of the world\n\n227\n00:13:33,904 --> 00:13:36,416\n和计算中的递归结合在一起 来建模世界\nwith things like recursion that come from computation.\n\n228\n00:13:37,424 --> 00:13:39,824\n还有很多像是这样的事\nAnd there are all sorts of interesting things you can do that are like this.\n\n229\n00:13:40,970 --> 00:13:42,096\n好的 有什么问题吗？\nAll right, any questions?\n\n230\n00:13:48,190 --> 00:13:49,168\n好吧 那我们休息一下\nOK, let's take a break.\n\n231\n00:13:49,640 --> 00:14:04,128\n\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n232\n00:14:04,464 --> 00:14:08,120\n《计算机程序的构造和解释》\n\n233\n00:14:12,080 --> 00:14:16,384\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n234\n00:14:16,448 --> 00:14:20,220\n《计算机程序的构造和解释》\n\n235\n00:14:20,352 --> 00:14:25,056\n流 II\n\n236\n00:14:28,650 --> 00:14:30,368\n我们已经看了\nWell, we've been looking at a couple\n\n237\n00:14:30,368 --> 00:14:32,090\n好几个流式程序设计的例子\nof examples of stream programming.\n\n238\n00:14:34,790 --> 00:14:39,216\n我们目前接触到的流过程\nAll the stream procedures that we've looked at so far\n\n239\n00:14:39,728 --> 00:14:41,328\n都有一个共同的特征\nhave the same kind of character.\n\n240\n00:14:41,490 --> 00:14:43,632\n这些过程总是递归地\nWe've been writing these recursive procedures\n\n241\n00:14:44,160 --> 00:14:46,496\n一次生成一个元素\nthat kind of generate these stream elements one at a time\n\n242\n00:14:46,510 --> 00:14:48,720\n再用CONS-STREAM连接起来\nand put them together in cons-streams.\n\n243\n00:14:49,152 --> 00:14:50,864\n因此 我们一直把它当作是生成器\nSo we've been thinking a lot about generators.\n\n244\n00:14:50,928 --> 00:14:53,632\n还有一种思考流式程序设计的方式\nThere's another way to think about stream processing,\n\n245\n00:14:53,790 --> 00:14:56,960\n我们不认为程序是\nand that's to focus not on programs that sort of\n\n246\n00:14:57,360 --> 00:14:59,930\n沿着流逐一处理元素\nprocess these elements as you walk down the stream,\n\n247\n00:15:00,256 --> 00:15:05,680\n而是一下子处理了整个流\nbut on things that kind of process the streams all at once.\n\n248\n00:15:07,180 --> 00:15:09,168\n我先来定义两个非常有用的过程\nTo show you what I mean, let me start by defining\n\n249\n00:15:09,232 --> 00:15:11,500\n来帮助我说明\ntwo procedures that will come in handy.\n\n250\n00:15:12,410 --> 00:15:13,600\n第一个过程是ADD-STREAMS\nThe first one's called add streams.\n\n251\n00:15:15,360 --> 00:15:18,256\n它接受两个流作为参数\nAdd streams takes two streams:\n\n252\n00:15:18,816 --> 00:15:20,880\nS1和S2\ns1 and s2.\n\n253\n00:15:22,300 --> 00:15:24,672\n它生成一个新的流\nAnd it's going to produce a stream\n\n254\n00:15:24,992 --> 00:15:28,176\n其元素是两个流相应位置元素的和\nwhose elements are the are the corresponding sums\n\n255\n00:15:30,224 --> 00:15:31,888\n相当于是“按元素”的加\nWe just sort of add them element-wise.\n\n256\n00:15:32,970 --> 00:15:33,952\n如果其中一个流是空的\nIf either stream is empty,\n\n257\n00:15:33,968 --> 00:15:35,390\n我们就返回另一个\nwe just return the other one.\n\n258\n00:15:36,810 --> 00:15:38,960\n否则 我们就构建一个新的流\nOtherwise, we're going to make a new stream\n\n259\n00:15:39,904 --> 00:15:42,960\n新流的头部分是两个流头部分之和\nwhose head is the sum of the two heads\n\n260\n00:15:44,000 --> 00:15:44,880\n而新流的尾部分\nwhose tail\n\n261\n00:15:46,000 --> 00:15:48,624\n则是递归地加和尾部分\nis the result of recursively adding the tails.\n\n262\n00:15:50,090 --> 00:15:52,736\n这就会产生“按元素”地加的效果\nSo that will produce the element-wise sum of two streams.\n\n263\n00:15:53,150 --> 00:15:57,040\n另一个过程是SCALE-STREAM\nAnd then another useful thing to have around is scale stream.\n\n264\n00:15:57,500 --> 00:16:01,664\nSCALE-STREAM有两个参数 常数C和流S\nScale stream takes some constant number in a stream s\n\n265\n00:16:04,112 --> 00:16:06,624\n结果生成的流\nand is going to produce the stream\n\n266\n00:16:07,184 --> 00:16:09,504\n就是将流S的所有元素乘上了C\nof elements of s multiplied by this constant.\n\n267\n00:16:09,710 --> 00:16:11,216\n这很简单 就是一个MAP\nAnd that's easy, that's just a map\n\n268\n00:16:12,208 --> 00:16:16,224\n用到的函数是 X*C\nof the function of an element that multiplies it by the constant,\n\n269\n00:16:16,352 --> 00:16:17,808\n把这个函数MAP于整个流\nand we map that down the stream.\n\n270\n00:16:20,064 --> 00:16:21,472\n有了这两个过程\nSo given those two,\n\n271\n00:16:22,640 --> 00:16:24,368\n我来给你们解释 什么叫做\nlet me show you what I mean by programs that\n\n272\n00:16:24,704 --> 00:16:27,008\n“一下子处理整个流”\nthat operate on streams all at once.\n\n273\n00:16:28,128 --> 00:16:28,736\n我们来看这个\nLet's look at this.\n\n274\n00:16:30,200 --> 00:16:30,928\n假设这样\nSuppose I write this.\n\n275\n00:16:31,680 --> 00:16:52,352\n(DEFINE ONES (CONS-STREAM 1 ONES))\nI say define--  I'll call it ones-- to be cons-stream of 1 onto ones.\n\n276\n00:16:54,860 --> 00:16:55,520\n这是什么？\nWhat's that?\n\n277\n00:16:56,950 --> 00:16:58,944\n这是一个表示无穷个1的流\nThat's going to be an infinite stream of ones\n\n278\n00:16:59,968 --> 00:17:01,440\n因为第一个元素是1\nbecause the first thing is 1.\n\n279\n00:17:03,330 --> 00:17:05,152\n尾部分则是这样的\nAnd the tail of it is a thing\n\n280\n00:17:05,552 --> 00:17:06,832\n它的头部分是1\nwhose first thing is 1\n\n281\n00:17:07,630 --> 00:17:09,024\n它的尾部分\nwhose tail is a thing\n\n282\n00:17:09,120 --> 00:17:10,240\n的头部分又为1\nwhose first thing is 1\n\n283\n00:17:10,528 --> 00:17:11,780\n以此类推\nand so on and so on.\n\n284\n00:17:11,780 --> 00:17:13,328\n这就是无穷个1的流\nSo that's an infinite stream of ones.\n\n285\n00:17:15,130 --> 00:17:15,936\n现在根据ONES\nAnd now using that,\n\n286\n00:17:16,128 --> 00:17:18,032\n我再给出另一种定义整数的方式\nlet me give you another definition of the integers.\n\n287\n00:17:19,472 --> 00:17:27,360\n(DEFINE INTEGERS\nWe can define the integers to be--\n\n288\n00:17:28,240 --> 00:17:30,768\n当然 第一个数是1\nwell, the first integer we'll take to be 1,\n\n289\n00:17:32,752 --> 00:17:38,576\n(CONS-STREAM 1 (ADD-STREAM\nhis cons-stream of 1 onto the element-wise sum\n\n290\n00:17:40,224 --> 00:17:48,270\nINTEGERS ONES)))\nonto add streams of the integers to ones.\n\n291\n00:17:55,100 --> 00:17:56,352\n整数流是这样的：\nThe integers are a thing\n\n292\n00:17:57,248 --> 00:17:59,984\n它的第一个元素是1\nwhose first element is 1,\n\n293\n00:18:00,880 --> 00:18:02,320\n而其余部分则是\nand the rest of them you get\n\n294\n00:18:03,120 --> 00:18:06,144\n依次把每个整数加1\nby taking those integers and incrementing each one by one.\n\n295\n00:18:06,640 --> 00:18:08,192\n因此 整数流的第二个元素则是\nSo the second element of the integers\n\n296\n00:18:08,512 --> 00:18:11,968\n整数流的第一个元素加1\nis the first element of the integers incremented by one.\n\n297\n00:18:13,920 --> 00:18:15,184\n下一个数又要加1\nAnd the rest of that is the next one,\n\n298\n00:18:15,200 --> 00:18:16,480\n第三个元素则是\nand the third element of that\n\n299\n00:18:16,620 --> 00:18:20,416\nINTEGER流尾部分的第一个元素\nis the same as the first element of the tail of the integers\n\n300\n00:18:20,848 --> 00:18:21,960\n加1\nincremented by one,\n\n301\n00:18:22,512 --> 00:18:23,760\n这也就相当于\nwhich is the same as the\n\n302\n00:18:25,088 --> 00:18:28,656\n最初整数流的第一个元素加1\nfirst element of the original integers incremented by one\n\n303\n00:18:28,864 --> 00:18:31,250\n然后再加1 以此类推\nand incremented by one again and so on.\n\n304\n00:18:35,240 --> 00:18:36,310\n这看起来有点匪夷所思\nThat looks pretty suspicious.\n\n305\n00:18:36,310 --> 00:18:37,472\n这样的过程可以正常运行\nSee, notice that it works\n\n306\n00:18:38,128 --> 00:18:38,990\n关键在于延时求值\nbecause of delay.\n\n307\n00:18:40,150 --> 00:18:43,328\n我们来看这个ONES\nSee, this looks like-- let's take a look at ones.\n\n308\n00:18:43,870 --> 00:18:45,920\n这看起来根本不可能\nThis looks like it couldn't even be processed\n\n309\n00:18:46,256 --> 00:18:47,632\n因为它突然说\nbecause it's suddenly saying\n\n310\n00:18:47,792 --> 00:18:48,960\n在定义ONES的时候\nin order to know what ones is,\n\n311\n00:18:49,008 --> 00:18:50,912\n发现它依赖于它本身\nI say it's cons-stream of something onto ones.\n\n312\n00:18:51,130 --> 00:18:52,080\n它之所以可以运行是因为\nThe reason that works\n\n313\n00:18:52,096 --> 00:18:54,040\n这里暗中隐藏着延时求值\nbecause of that very sneaky hidden delay in there.\n\n314\n00:18:55,250 --> 00:18:56,560\n这个代码实际上是\nBecause what this really is,\n\n315\n00:18:57,792 --> 00:18:59,696\n回忆下 CONS-STREAM是只是一个缩写\nremember, cons-stream is just an abbreviation.\n\n316\n00:19:00,290 --> 00:19:01,152\n实际上则是\nThis really is\n\n317\n00:19:01,856 --> 00:19:08,992\n(CONS 1 (DELAY ONES))\ncons of 1 onto delay of ones.\n\n318\n00:19:12,140 --> 00:19:13,216\n它又是怎么运作的呢？\nSo how does that work?\n\n319\n00:19:15,500 --> 00:19:16,880\n你想要定义ONES\nYou say I'm going to define ones.\n\n320\n00:19:18,020 --> 00:19:20,240\n我来看看ONES要被定义成什么样\nFirst I see what ones is supposed to be defined as.\n\n321\n00:19:20,700 --> 00:19:23,408\nONES被定义为一个序对\nWell, ones is supposed to be defined as\n\n322\n00:19:24,896 --> 00:19:28,112\n其CAR部分为1\na cons whose first part is 1\n\n323\n00:19:28,320 --> 00:19:29,456\n而CDR部分则是\nand the second part is,\n\n324\n00:19:29,450 --> 00:19:30,736\n是一个计算某物的PROMISE\nwell, it's a promise to compute something\n\n325\n00:19:30,752 --> 00:19:31,690\n我现在还不用关心\nthat I don't worry about yet.\n\n326\n00:19:32,710 --> 00:19:34,256\n所以虽然这时ONES还没有定义\nSo it doesn't bother me that at the point\n\n327\n00:19:34,288 --> 00:19:36,300\n但对我并不造成什么影响\nI do this definition, ones isn't defined.\n\n328\n00:19:37,270 --> 00:19:39,456\n一旦运行了整个定义 ONES就被定义了\nHaving run the definition, now ones is defined.\n\n329\n00:19:40,670 --> 00:19:42,832\n所以 访问它尾部的时候 它就有定义了\nSo that when I go and look at the tail of it, it's defined.\n\n330\n00:19:44,920 --> 00:19:46,064\n这一点非常隐讳\nIt's very sneaky.\n\n331\n00:19:46,590 --> 00:19:47,904\n整数流的定义也是如此\nAnd an integer is the same way.\n\n332\n00:19:48,470 --> 00:19:50,464\n我可以在这里引用INTEGERS是因为\nI can refer to integers here because\n\n333\n00:19:51,136 --> 00:19:53,210\n是因为这个CONS-STREAM的缘故\nhidden way down-- because of this cons-stream.\n\n334\n00:19:53,850 --> 00:19:55,248\n用CONS-STREAM把1\nIt's the cons-stream of 1\n\n335\n00:19:55,376 --> 00:19:57,050\n和一个不立即需要的东西组合起来\nonto something that I don't worry that yet.\n\n336\n00:19:57,050 --> 00:19:59,600\n所以我在运行INTEGERS的定义的时候\nSo I don't look at it, and I don't notice that integers isn't defined\n\n337\n00:20:00,224 --> 00:20:01,904\n并不会发现INTEGER没有定义过\nat the point where I try and run the definition.\n\n338\n00:20:06,320 --> 00:20:08,272\n听上去非常玄乎\nOK, let me draw a picture of that integers thing\n\n339\n00:20:08,448 --> 00:20:11,504\n让我用图像来演示一下INTEGERS的原理\nbecause it still maybe seems a little bit shaky.\n\n340\n00:20:12,430 --> 00:20:14,720\n怎么画呢？\nWhat do I do? Uh...\n\n341\n00:20:15,020 --> 00:20:16,304\n首先是ONES这个流\nI've got the stream of ones,\n\n342\n00:20:20,510 --> 00:20:21,888\n它作为参数输入\nand that sort of comes in\n\n343\n00:20:23,260 --> 00:20:24,928\n进入一个加法器\ncomes in and goes into an adder\n\n344\n00:20:24,960 --> 00:20:26,590\n进行流的加法运算\nthat's going to be this add streams thing.\n\n345\n00:20:29,310 --> 00:20:35,872\n输出则是整数流INTEGERS\nAnd that goes in-- that's going to put out the integers.\n\n346\n00:20:40,760 --> 00:20:42,704\n这里 这个整数流又重新进入加法器\nAnd the other thing that goes into the adder here\n\n347\n00:20:44,944 --> 00:20:46,976\n形成了一个小型的反馈回路\nis the integer, so there's a little feedback loop.\n\n348\n00:20:48,060 --> 00:20:49,424\n我需要在某处接入最初的ONES\nAnd all I need to start it off\n\n349\n00:20:50,096 --> 00:20:52,880\n才能让它生效\nis someplace I've got a stick that initial 1.\n\n350\n00:20:57,100 --> 00:20:58,640\n在真实的信号处理中\nIn a real signal processing thing,\n\n351\n00:20:58,720 --> 00:21:02,480\n这里是一个被初始化为1的延时元件\nthis might be a delay element with that was initialized to 1.\n\n352\n00:21:02,910 --> 00:21:05,904\n这就是ONES程序的图示\nBut there's a picture of that ones program.\n\n353\n00:21:07,860 --> 00:21:09,632\n事实上 这个非常像\nAnd in fact, that looks a lot like--\n\n354\n00:21:09,808 --> 00:21:13,776\n如果你见过真正的信号方块图的话\nif you've seen real signal block diagram things,\n\n355\n00:21:13,776 --> 00:21:16,304\n这个图形非常像累加器\nthat looks a lot like accumulators,\n\n356\n00:21:16,352 --> 00:21:17,488\n有穷状态累加器\nfinite state accumulators.\n\n357\n00:21:17,980 --> 00:21:20,064\n事实上 我们可以稍加修改\nAnd in fact, we can modify this a little bit\n\n358\n00:21:21,184 --> 00:21:23,968\n就可以让它对一个流做积分\nto change this into something that integrates a stream\n\n359\n00:21:25,370 --> 00:21:26,976\n或者说是有穷状态累加器\nor a finite state accumulator,\n\n360\n00:21:27,008 --> 00:21:28,040\n你怎么认为都可以\nhowever you like to think about it.\n\n361\n00:21:28,440 --> 00:21:30,864\n现在 不再是输入ONES 输出INTEGERS\nSo instead of the ones coming in and getting out the integers,\n\n362\n00:21:31,680 --> 00:21:32,384\n我们要做的是\nwhat we'll do is\n\n363\n00:21:32,912 --> 00:21:34,832\n这里有一个流S为输入\nsay there's a stream s coming in,\n\n364\n00:21:35,760 --> 00:21:40,560\n我们要计算这个流的积分\nand we're going to get out the integral of this.\n\n365\n00:21:42,600 --> 00:21:44,096\n也就是累加这个流的值\nsuccessive values of that,\n\n366\n00:21:44,448 --> 00:21:45,630\n这看起来几乎就是一样的\nand it looks almost the same.\n\n367\n00:21:45,660 --> 00:21:46,848\n我们要做的就是\nThe only thing we're going to do is\n\n368\n00:21:47,024 --> 00:21:48,080\n当S从这里输入时\nwhen s comes in here,\n\n369\n00:21:49,216 --> 00:21:50,640\n在把它求和之前\nbefore we just add it in\n\n370\n00:21:50,912 --> 00:21:54,260\n先将其乘以dt\nwe're going to multiply it by some number dt.\n\n371\n00:21:57,680 --> 00:22:00,000\n剩下的就不用改了\nAnd now what we have here, this is exactly the same thing.\n\n372\n00:22:00,000 --> 00:22:00,912\n我们就得到了一个盒子\nWe have a box,\n\n373\n00:22:03,360 --> 00:22:04,560\n一个积分器\nwhich is an integrator.\n\n374\n00:22:09,790 --> 00:22:11,264\n对一个流S进行积分\nAnd it takes in a stream s,\n\n375\n00:22:11,904 --> 00:22:14,512\n把这里的1替换为\nand instead of 1 here,\n\n376\n00:22:14,944 --> 00:22:18,352\n该积分的初始值\nwe can put the additional value for the integral.\n\n377\n00:22:19,980 --> 00:22:21,600\n这个看起来就非常像\nAnd that one looks very much like a\n\n378\n00:22:22,352 --> 00:22:24,860\n信号处理中的方框图了\na signal processing block diagram program.\n\n379\n00:22:25,270 --> 00:22:28,112\n事实上 这个图示对应的是这样一个过程\nIn fact, here's the procedure that looks exactly like that.\n\n380\n00:22:31,490 --> 00:22:33,616\n对一个流进行积分\nFind the integral of a stream.\n\n381\n00:22:34,010 --> 00:22:35,488\nINTEGRAL函数接收一个流\nSo an integral's going to take a stream\n\n382\n00:22:35,680 --> 00:22:36,864\n返回一个新的流\nSand produce a new stream,\n\n383\n00:22:37,530 --> 00:22:40,672\n它还接收一个初始值和某个时间常量\nand it takes in an initial value and some time constant.\n\n384\n00:22:42,230 --> 00:22:42,976\n然后呢？\nAnd what do we do?\n\n385\n00:22:43,040 --> 00:22:45,056\n首先在内部定义一个流INT\nWell, we internally define this thing int,\n\n386\n00:22:45,200 --> 00:22:46,320\n之所以要给它一个内部名字\nand we make this internal name\n\n387\n00:22:46,336 --> 00:22:48,860\n原因在于可以使它反馈 以形成循环\nso we can feed it back, loop it around itself.\n\n388\n00:22:49,400 --> 00:22:50,800\nINT的定义是\nAnd int is defined to be\n\n389\n00:22:51,104 --> 00:22:53,328\n一个以INITIA-VALUE开始的流\nsomething that starts out at the initial value,\n\n390\n00:22:54,976 --> 00:23:00,144\n而其余的元素则是把它们加起来\nand the rest of it is gotten by adding together.\n\n391\n00:23:01,280 --> 00:23:03,616\n我们把输入流乘以dt\nWe take our input stream, scale it by dt,\n\n392\n00:23:03,872 --> 00:23:04,928\n然后和INT相加\nand add that to int.\n\n393\n00:23:06,880 --> 00:23:09,664\n整个INTEGRAL函数的结果就是这个INT\nAnd now we'll return from all that the value of integral is this thing int.\n\n394\n00:23:10,690 --> 00:23:12,944\n我们使用这种内部定义的语法\nAnd we use this internal definition syntax so we could\n\n395\n00:23:13,344 --> 00:23:15,664\n是为了可以在内部引用它自己\nwrite a little internal definition that refers to itself.\n\n396\n00:23:21,880 --> 00:23:23,710\n我们还可以做更多的事情\nWell, there are all sorts of things we can do.\n\n397\n00:23:23,710 --> 00:23:24,512\n来看这个\nLet's try this one.\n\n398\n00:23:25,632 --> 00:23:26,890\n斐波那契数\nhow about the Fibonacci numbers.\n\n399\n00:23:26,895 --> 00:23:32,625\n(DEFINE FIBS\nYou can say define fibs.\n\n400\n00:23:36,350 --> 00:23:37,632\n斐波那契数是什么呢？\nWell, what are the Fibonacci numbers?\n\n401\n00:23:37,980 --> 00:23:46,544\n它从0开始\nThey're something that starts out with 0,\n\n402\n00:23:48,656 --> 00:23:50,090\n下一个是1\nand the next one is 1.\n\n403\n00:23:56,260 --> 00:23:59,168\n的其余的斐波那契数是通过\nAnd the rest of the Fibonacci numbers are gotten by\n\n404\n00:23:59,872 --> 00:24:11,000\n把它们的尾部分求和而得来\nadding the Fibonacci numbers to their own tail.\n\n405\n00:24:17,570 --> 00:24:19,280\n这样来定义斐波那契数\nThere's a definition of the Fibonacci numbers.\n\n406\n00:24:20,580 --> 00:24:21,430\n这是如何运作的呢？\nHow does that work?\n\n407\n00:24:21,430 --> 00:24:24,192\n我们来试试\nWell, we start off,\n\n408\n00:24:24,208 --> 00:24:26,490\n假如开始计算斐波那契数\nand someone says compute for us the Fibonacci numbers,\n\n409\n00:24:29,648 --> 00:24:31,920\n首先告诉你 它以0和1开始\nand we're going to tell you it starts out with 0 and 1.\n\n410\n00:24:35,790 --> 00:24:38,224\n而0和1之后的数则是\nAnd everything after the 0 and 1\n\n411\n00:24:39,184 --> 00:24:40,864\n通过加和两个流而得\nis gotten by summing two streams.\n\n412\n00:24:41,120 --> 00:24:42,592\n一个流是FIBS本身\nOne is the fibs themselves,\n\n413\n00:24:44,064 --> 00:24:45,696\n另一个是FIBS的尾部分\nand the other one is the tail of the fibs.\n\n414\n00:24:49,120 --> 00:24:51,168\n如果我知道这是以0和1起始的\nSo if I know that these start out with 0 and 1,\n\n415\n00:24:51,790 --> 00:24:55,424\n我就能知道 FIBS是以0和1起始的\nI know that the fibs now start out with 0 and 1,\n\n416\n00:24:55,744 --> 00:24:57,408\n那么 FIBS的尾部分则应该以1开始\nand the tail of the fibs start out with 1.\n\n417\n00:24:58,360 --> 00:24:59,456\n一旦我知道了这点\nSo as soon as I know that,\n\n418\n00:24:59,664 --> 00:25:02,112\n我就知道 FIBS的下一个数就是0+1=1\nI know that the next one here is 0 plus 1 is 1,\n\n419\n00:25:02,960 --> 00:25:04,608\n它也同样告诉我这里是1\nand that tells me that the next one here is 1\n\n420\n00:25:04,624 --> 00:25:05,728\n这里也是1\nand the next one here is 1.\n\n421\n00:25:06,300 --> 00:25:07,280\n知道了这些之后\nAnd as soon as I know that,\n\n422\n00:25:07,296 --> 00:25:08,760\n我就知道下一个是2\nI know that the next one is 2.\n\n423\n00:25:09,390 --> 00:25:11,700\n这里是2 这里也是2\nSo the next one here is 2 and the next one here is 2.\n\n424\n00:25:11,700 --> 00:25:12,560\n下一个是3\nAnd this is 3.\n\n425\n00:25:14,720 --> 00:25:15,792\n这里是3\nThis one goes to 3,\n\n426\n00:25:16,192 --> 00:25:17,136\n这里是5\nand this is 5.\n\n427\n00:25:18,672 --> 00:25:19,968\n这个定义完全说得通\nSo it's a perfectly sensible definition.\n\n428\n00:25:21,500 --> 00:25:22,784\n这个定义只有一行\nIt's a one-line definition.\n\n429\n00:25:22,830 --> 00:25:25,008\n当然 我也可以在计算机中\nAnd again, I could walk over to the computer\n\n430\n00:25:25,008 --> 00:25:26,624\n原原本本地键入计算机中\nand type that in, exactly that,\n\n431\n00:25:27,040 --> 00:25:28,944\n然后要求输出斐波那契数\nand then say print stream the Fibonacci numbers,\n\n432\n00:25:28,944 --> 00:25:30,150\n然后它就会不断输出\nand they all come flying out.\n\n433\n00:25:32,790 --> 00:25:35,200\n这又像是在学习递归\nSee, this is a lot like learning about recursion again.\n\n434\n00:25:36,810 --> 00:25:39,792\n过程可以被递归定义\nInstead of thinking that recursive procedures,\n\n435\n00:25:40,992 --> 00:25:43,504\n我们也可以递归地定义数据对象\nwe have recursively defined data objects.\n\n436\n00:25:45,160 --> 00:25:46,928\n但你们一点儿不应该感到吃惊\nBut that shouldn't surprise you at all,\n\n437\n00:25:47,120 --> 00:25:49,504\n因为现在 你们应该真正相信\nbecause by now, you should be coming to really believe\n\n438\n00:25:49,520 --> 00:25:53,056\n过程与数据之间没有区别\nthat there's no difference really between procedures and data.\n\n439\n00:25:53,090 --> 00:25:53,920\n事实上 就某种意义上来说\nIn fact, in some sense,\n\n440\n00:25:53,936 --> 00:25:56,416\n流也是由过程来实现的\nthe underlying streams are procedures sitting there,\n\n441\n00:25:56,432 --> 00:25:57,790\n只不过我们不把它看做过程而已\nalthough we don't think of them that way.\n\n442\n00:25:58,210 --> 00:26:00,384\n因此既然我们有递归过程\nSo the fact that we have recursive procedures,\n\n443\n00:26:00,704 --> 00:26:03,630\n那么 有递归数据也就不足为奇了\nwell, then it should be natural that we have recursive data, too.\n\n444\n00:26:07,728 --> 00:26:09,696\n虽然流非常简洁\nOK, well, this is all pretty neat.\n\n445\n00:26:09,720 --> 00:26:13,920\n但不幸的是 有些问题流无法解决\nUnfortunately, there are problems that streams aren't going to solve.\n\n446\n00:26:14,990 --> 00:26:16,480\n我来举个例子\nLet me show you one of them.\n\n447\n00:26:17,580 --> 00:26:20,352\n同样地 我们来想象一下\nSee, in the same way, let's imagine that we're\n\n448\n00:26:20,768 --> 00:26:23,616\n我们正在构建求解微分方程的模拟计算机\nbuilding an analog computer to solve some differential equation\n\n449\n00:26:25,200 --> 00:26:34,304\n比如求解方程 y' = y^2\nlike, say, we want to solve the equation y prime dy dt is y squared,\n\n450\n00:26:34,760 --> 00:26:36,160\n我会给你一个初值\nand I'm going to give you some initial value.\n\n451\n00:26:36,390 --> 00:26:38,030\ny(0) = 1\nI'll tell you y of 0 equals 1.\n\n452\n00:26:41,488 --> 00:26:44,064\ndt = .0001\nLet's say dt is equal to something.\n\n453\n00:26:46,770 --> 00:26:47,536\n很久之前\nNow, in the old days,\n\n454\n00:26:48,000 --> 00:26:50,650\n就有人构建模拟计算机 来解决这类问题\npeople built analog computers to solve these kinds of things.\n\n455\n00:26:51,360 --> 00:26:53,020\n原理非常简单\nAnd the way you do that is really simple.\n\n456\n00:26:53,020 --> 00:26:54,416\n你首先需要一个积分器\nYou get yourself an integrator,\n\n457\n00:27:00,048 --> 00:27:01,696\n比如这个INT盒子\nlike that one, an integrator box.\n\n458\n00:27:03,050 --> 00:27:06,480\n我们设定初始值 y(0) = 1\nAnd we put in the initial value y of 0 is 1.\n\n459\n00:27:08,530 --> 00:27:10,928\n现在如果我们送入一个输入 就会得到输出\nAnd now if we feed something in and get something out,\n\n460\n00:27:10,960 --> 00:27:13,168\n输出的结果就是y\nwe'll say, gee, what we're getting out is the answer.\n\n461\n00:27:14,256 --> 00:27:16,960\n输入的是y的导数\nAnd what we're going to feed in is the derivative,\n\n462\n00:27:17,520 --> 00:27:20,528\n在这里 导数 y' = y^2\nand the derivative is supposed to be the square of the answer.\n\n463\n00:27:21,490 --> 00:27:27,072\n如果我们用MAP把SQUARE映射在这些值上\nSo if we take these values and map using square,\n\n464\n00:27:30,736 --> 00:27:32,096\n然后把这个引过来\nand if I feed this around,\n\n465\n00:27:36,280 --> 00:27:38,480\n这个方块图\nthat's how I build a block diagram\n\n466\n00:27:38,576 --> 00:27:41,088\n就是用于求解这个微分方程的模拟计算机\nfor an analog computer that solves this differential equation.\n\n467\n00:27:42,910 --> 00:27:44,800\n现在我们用代码\nNow, what we'd like to do is write a stream\n\n468\n00:27:44,800 --> 00:27:46,780\n来表示下这个过程\nprogram that looks exactly like that.\n\n469\n00:27:47,230 --> 00:27:48,720\n这个图究竟表示的是什么呢？\nAnd what do I mean exactly like that?\n\n470\n00:27:49,390 --> 00:27:58,304\n(DEFINE Y\nWell, I'd say define y to be the integral\n\n471\n00:28:04,288 --> 00:28:11,680\n(INTEGRAL DY 1 .001))\nof dy starting at 1 with 0.001 as a time step.\n\n472\n00:28:13,790 --> 00:28:15,456\n接下来\nAnd I'd like to say that says this.\n\n473\n00:28:16,805 --> 00:28:20,850\n通过MAP SQUARE 来表示dy\nAnd then I'd like to say, well, dy is gotten by mapping the square along y.\n\n474\n00:28:20,850 --> 00:28:32,816\n(DEFINE DY (MAP SQUARE Y))\nSo define dy to be map square along y.\n\n475\n00:28:33,510 --> 00:28:36,800\n这就是这个模拟计算机的流式描述\nSo there's a stream description of this analog computer,\n\n476\n00:28:38,624 --> 00:28:40,320\n不幸的是 它并不起效\nand unfortunately, it doesn't work.\n\n477\n00:28:41,410 --> 00:28:42,672\n你也可以发现这是为什么\nAnd you can see why it doesn't work\n\n478\n00:28:42,970 --> 00:28:44,992\n因为我把Y定义为\nbecause when I come in and say define y\n\n479\n00:28:46,432 --> 00:28:47,850\nDY 的积分\nto be the integral of dy\n\n480\n00:28:49,040 --> 00:28:50,656\n它会问 对什么的积分？\nit says, oh, the integral of what-- huh?\n\n481\n00:28:51,190 --> 00:28:52,128\n没定义啊\nOh, that's undefined.\n\n482\n00:28:53,710 --> 00:28:57,632\n所以这个定义必须写在这个定义的后面\nSo I can't write this definition before I've written this one.\n\n483\n00:28:58,770 --> 00:29:00,512\n另一方面 如果先定义了dy\nOn the other hand, if I try and write this one first,\n\n484\n00:29:00,512 --> 00:29:03,024\n定义为 (MAP SQUARE 某个东西)\nit says, oh, I define y to be the map of square along what?\n\n485\n00:29:03,580 --> 00:29:04,640\n这个也还没有定义\nOh, that's not defined yet.\n\n486\n00:29:05,770 --> 00:29:08,176\n我既不能先写这个 又不能先写那个\nSo I can't write this one first, and I can't write that one first.\n\n487\n00:29:09,088 --> 00:29:11,580\n这个游戏就没法玩了\nSo I can't quite play this game.\n\n488\n00:29:17,560 --> 00:29:18,512\n怎样来解决呢？\nWell, is there a way out?\n\n489\n00:29:20,608 --> 00:29:21,840\n我们可以用ONES来解决\nSee, we can do that with ones.\n\n490\n00:29:22,200 --> 00:29:25,824\n所以 我们在这里定义的ONES\nSee, over here, we did this thing ones,\n\n491\n00:29:27,248 --> 00:29:29,904\n我们之所以可以使用ONES来定义ONES\nand we were able to define ones in terms of ones because\n\n492\n00:29:30,400 --> 00:29:32,032\n这是因为其中的延时求值\nof this delay that was built inside\n\n493\n00:29:32,432 --> 00:29:34,128\nCONS-STREAM是延时求值的\nbecause cons-stream had a delay.\n\n494\n00:29:34,770 --> 00:29:35,792\n那么 这又为什么说得通呢？\nNow, why's it sensible?\n\n495\n00:29:35,920 --> 00:29:38,512\n为什么CONS-STREAM是延时求值的是合理的呢？\nWhy's it sensible for cons-stream to be built with this delay?\n\n496\n00:29:40,730 --> 00:29:43,136\n原因在于 CONS-STREAM不需要其尾部分\nThe reason is that cons-stream can do a useful thing\n\n497\n00:29:43,488 --> 00:29:44,880\n就可以完成有意义的事\nwithout looking at its tail.\n\n498\n00:29:45,950 --> 00:29:46,848\n比如我说\nSee, if I say\n\n499\n00:29:47,488 --> 00:29:49,648\n这个是1和某个东西组成的流\nthis is cons-stream of 1 onto something\n\n500\n00:29:49,920 --> 00:29:51,696\n虽然我对它一无所知\nwithout knowing anything about something,\n\n501\n00:29:52,160 --> 00:29:54,032\n但我却知道整个流是以1开始的\nI know that the stream starts off with 1.\n\n502\n00:29:54,870 --> 00:29:57,296\n所以用CONS-STREAM来构造是有意义的\nThat's why it was sensible to build something like cons-stream.\n\n503\n00:29:59,960 --> 00:30:01,248\n我们在这里放了一个DELAY\nSo we put a delay in there,\n\n504\n00:30:01,424 --> 00:30:04,656\n这就使得我们能够进行某种自引用的定义\nand that allows us to have this sort of self-referential definition.\n\n505\n00:30:06,320 --> 00:30:07,952\nINTEGRAL也可以用这种方式来解决\nWell, integral is a little bit the same way.\n\n506\n00:30:08,190 --> 00:30:12,528\n注意 对于INTEGRAL来说 我可以\nSee, notice for an integral, I can--\n\n507\n00:30:14,608 --> 00:30:16,080\n让我们回过头来再看看INTEGRAL的定义\nlet's go back and look at integral for a second.\n\n508\n00:30:17,580 --> 00:30:18,560\n求积分的时候\nSee, notice integral,\n\n509\n00:30:21,392 --> 00:30:25,008\n知道INTEGRAL的第一个元素是合理的\nit makes sense to say what's the first thing in the integral\n\n510\n00:30:26,048 --> 00:30:27,872\n尽管还不知道整个流是什么样的\nwithout knowing the stream that you're integrating.\n\n511\n00:30:28,970 --> 00:30:30,176\n这是因为INTEGRAL中第一个元素\nBecause the first thing in the integral\n\n512\n00:30:30,200 --> 00:30:32,160\n总会是你传递过来的INITIAL-VALUE\nis always going to be the initial value that you're handed.\n\n513\n00:30:33,140 --> 00:30:36,112\n所以INTEGRAL可以用CONS-STREAM来实现\nSo integral could be a procedure like cons-stream.\n\n514\n00:30:37,090 --> 00:30:37,984\n我们可以定义它\nYou could define it,\n\n515\n00:30:38,256 --> 00:30:40,880\n甚至不用知道要积分的流是什么\nand then even before it knows what it's supposed to be integrating,\n\n516\n00:30:42,848 --> 00:30:45,184\n只需要知道初始值是什么就行了\nit knows enough to say what its initial value is.\n\n517\n00:30:46,710 --> 00:30:48,176\nINTEGRAL还可以修改得更为智能\nSo we can make a smarter integral,\n\n518\n00:30:48,416 --> 00:30:50,688\n我们给它一个待积分的流\nwhich is aha, you're going to give me a stream to integrate\n\n519\n00:30:50,832 --> 00:30:51,920\n以及一个初值\nand an initial value,\n\n520\n00:30:52,112 --> 00:30:54,992\n直到你要求沿着这个流求解积分时\nbut I really don't have to look at that stream that I'm supposed to integrate\n\n521\n00:30:55,216 --> 00:30:56,976\n我才关心这个流是什么\nuntil you ask me to work down the stream.\n\n522\n00:30:58,430 --> 00:31:00,512\n换句话说INTEGRAL可以像CONS-STREAM一样\nIn other words, integral can be like cons-stream,\n\n523\n00:31:00,570 --> 00:31:03,744\n你可以认为INTEGRAL被放在DELAY之中\nand you can expect that there's going to be a delay around its integrand.\n\n524\n00:31:03,760 --> 00:31:04,864\n我们这样修改\nAnd we can write that.\n\n525\n00:31:05,610 --> 00:31:07,024\n这个过程是像这样的\nHere's a procedure that does that.\n\n526\n00:31:07,650 --> 00:31:08,752\n这是另一个版本的INTEGRAL\nAnother version of integral,\n\n527\n00:31:08,896 --> 00:31:10,544\n这个跟之前的版本非常相似\nand this is almost like the previous one,\n\n528\n00:31:11,104 --> 00:31:13,344\n只不过作为参数的流\nexcept the stream it's going to get in\n\n529\n00:31:13,776 --> 00:31:15,696\n必须要是一个延时对象\nis going to expect to be a delayed object.\n\n530\n00:31:17,110 --> 00:31:18,432\n这个INTEGRAL又是如何运作的呢？\nAnd how does this integral work?\n\n531\n00:31:18,850 --> 00:31:21,792\n我们在内部定义的INT则是\nWell, the little thing it's going to define inside of itself\n\n532\n00:31:22,144 --> 00:31:24,192\n用CONS-STREAM构造一个流\nsays on the cons-stream,\n\n533\n00:31:24,736 --> 00:31:26,448\n初值还是INITIAL-VALUE\nthe initial value is the initial value,\n\n534\n00:31:27,160 --> 00:31:29,680\n但是在CONS-STREAM中\nbut only inside of that cons-stream,\n\n535\n00:31:29,744 --> 00:31:32,300\n要注意 这里面有个隐藏的DELAY\nand remember, there's going to be a hidden delay inside here.\n\n536\n00:31:34,950 --> 00:31:39,072\n只有在这个CONS-STREAM的内部\nOnly inside of that cons-stream will I start looking at\n\n537\n00:31:39,824 --> 00:31:42,110\n我才会查看延时对象的实际内容\nwhat the actual delayed object is.\n\n538\n00:31:43,180 --> 00:31:45,792\n所以 答案的第一个元素将会是初值\nSo my answer is the first thing's the initial value.\n\n539\n00:31:45,970 --> 00:31:47,904\n如果有人想访问我的尾部分\nIf anybody now asks me for my tail,\n\n540\n00:31:48,400 --> 00:31:49,424\n此时\nat that point,\n\n541\n00:31:50,000 --> 00:31:51,728\n我会FORCE该延迟对象\nI'm going to force that delayed object--\n\n542\n00:31:52,624 --> 00:31:53,600\n把结果记作S\nand I'll call that s--\n\n543\n00:31:54,448 --> 00:31:55,600\n然后再进行ADD-STREAMS\nand I do the add streams.\n\n544\n00:31:56,368 --> 00:31:59,260\n这个INTEGRAL就有点像CONS-STREAM\nSo this is an integral which is sort of like cons-stream.\n\n545\n00:31:59,260 --> 00:32:02,592\n直到你确实需要知道第一个元素的时候\nIt's not going to actually try and see what you handed it\n\n546\n00:32:03,888 --> 00:32:07,136\n它才会去查看DELAYED-S是什么\nas the thing to integrate until you look past the first element.\n\n547\n00:32:10,120 --> 00:32:11,024\n如果这样的话\nAnd if we do that\n\n548\n00:32:11,520 --> 00:32:12,832\n也就能求解 y' = y^2 了\nand we can make this work,\n\n549\n00:32:13,360 --> 00:32:15,200\n这里我们只需要\nall we have to do here is\n\n550\n00:32:16,000 --> 00:32:25,312\n把Y定义为对延时对象DY的积分\ndefine y to the integral of delay of y, of delay of dy.\n\n551\n00:32:27,090 --> 00:32:28,224\n所以Y的定义就变成了\nSo y is going to be\n\n552\n00:32:28,400 --> 00:32:34,368\n(INTEGRAL (DELAY DY) 1 .001)\nthe integral of delay of dy starting at 1,\n\n553\n00:32:34,384 --> 00:32:35,130\n这样一来就可以了\nand now this will work.\n\n554\n00:32:35,280 --> 00:32:37,440\n因为我输入Y的定义\nBecause I type in the definition of y,\n\n555\n00:32:38,000 --> 00:32:39,680\n它是某个东西的积分\nand that says, oh, I'm supposed to use the integral of\n\n556\n00:32:40,208 --> 00:32:42,688\n但这是个延迟对象 我现在还不用关心\nsomething I don't care about right now because it's a delay.\n\n557\n00:32:44,600 --> 00:32:46,320\n这之后 再定义DY\nAnd these things, now you define dy.\n\n558\n00:32:46,320 --> 00:32:47,376\n现在Y就有定义了\nNow, y is defined.\n\n559\n00:32:47,550 --> 00:32:48,896\n所以我在定义DY时\nSo when I define dy,\n\n560\n00:32:49,136 --> 00:32:50,672\n它可以知道Y的定义\nit can see that definition for y.\n\n561\n00:32:51,700 --> 00:32:52,840\n一切都正常了\nEverything is now started up.\n\n562\n00:32:52,840 --> 00:32:54,336\n两个流都有第一个元素\nBoth streams have their first element.\n\n563\n00:32:54,920 --> 00:32:56,256\n当我不断取得下一个元素\nAnd then when I start mapping down,\n\n564\n00:32:56,272 --> 00:32:57,312\n沿着流做MAP运算时\nlooking at successive elements,\n\n565\n00:32:57,376 --> 00:32:58,880\nY和DY都被定义过了\nboth y and dy are defined.\n\n566\n00:33:00,590 --> 00:33:04,240\n所以为了继续这个游戏 我们不能仅仅\nSo there's a little game you can play that goes a little bit beyond\n\n567\n00:33:04,670 --> 00:33:07,136\n只使用隐藏在流中的DELAY\njust using the delay that's hidden inside streams.\n\n568\n00:33:08,368 --> 00:33:08,976\n有问题么？\nQuestions?\n\n569\n00:33:13,520 --> 00:33:14,272\n休息一下吧\nOK, let's take a break.\n\n570\n00:33:14,720 --> 00:33:26,864\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n571\n00:33:27,370 --> 00:33:30,944\n《计算机程序的构造和解释》\n\n572\n00:33:52,160 --> 00:33:55,264\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n573\n00:33:55,420 --> 00:33:59,264\n《计算机程序的构造和解释》\n\n574\n00:34:00,384 --> 00:34:03,930\n流 II\n\n575\n00:34:07,300 --> 00:34:10,048\n上节课的最后\nWell, just before the break, um..\n\n576\n00:34:10,890 --> 00:34:11,808\n不知道你们注意到没有\nI'm not sure if you noticed it,\n\n577\n00:34:11,824 --> 00:34:13,550\n事情正变得糟糕起来\nbut something nasty started to happen.\n\n578\n00:34:14,832 --> 00:34:18,400\n我们讲了很多关于 流\nWe've been going along with the streams\n\n579\n00:34:19,168 --> 00:34:22,688\n以及分离程序中的时间和计算机中的时间\nand divorcing time in the programs from time in the computers,\n\n580\n00:34:22,864 --> 00:34:26,288\n这些分离都被隐藏在流中了\nand all that divorcing got hidden inside the streams.\n\n581\n00:34:27,280 --> 00:34:29,504\n上节课快结束时我们发现\nAnd then at the very end, we saw that sometimes\n\n582\n00:34:29,710 --> 00:34:32,192\n为了真正发挥这种方法的优势\nin order to really take advantage of this method,\n\n583\n00:34:32,224 --> 00:34:34,380\n我们需要另外的DELAY\nyou have to pull out other delays.\n\n584\n00:34:34,380 --> 00:34:35,856\n不只需要隐藏在CONS-STREAM中的DELAY\nYou have to write some explicit delays\n\n585\n00:34:36,096 --> 00:34:37,950\n还需要显式地使用DELAY\nthat are not hidden inside that cons-stream.\n\n586\n00:34:39,030 --> 00:34:41,888\n我只是用微分方程举了一个很简单的例子\nAnd I did a very simple example with differential equations,\n\n587\n00:34:42,350 --> 00:34:44,080\n但是如果你有一个非常复杂的系统\nbut if you have some very complicated system\n\n588\n00:34:44,128 --> 00:34:45,408\n里面充斥着各种各样的自循环\nwith all kinds of self-loops,\n\n589\n00:34:45,950 --> 00:34:47,840\n那就很难再发现\nit becomes very, very difficult to\n\n590\n00:34:47,904 --> 00:34:49,310\n在什么地方需要额外的DELAY了\nsee where you need those delays.\n\n591\n00:34:49,920 --> 00:34:51,184\n假如你一不小心漏了一个\nAnd if you leave them out by mistake,\n\n592\n00:34:51,456 --> 00:34:54,368\n就很难发现程序为什么不起效\nit becomes very, very difficult to see why the thing maybe isn't working.\n\n593\n00:34:55,550 --> 00:34:57,152\n这是一种混乱\nSo that's kind of mess,\n\n594\n00:34:57,792 --> 00:35:01,712\n让我们能够使用DELAY\nthat by getting this power and allowing us to use delay,\n\n595\n00:35:02,080 --> 00:35:04,704\n有时却会让程序设计变得非常复杂\nwe end up with some very complicated programming sometimes,\n\n596\n00:35:04,720 --> 00:35:06,800\n因为它们不能完全隐藏在流中\nbecause it can't all be hidden inside the streams.\n\n597\n00:35:08,512 --> 00:35:09,792\n那么 有没有什么解决方案呢？\nWell, is there a way out of that?\n\n598\n00:35:11,136 --> 00:35:12,672\n所幸的是 有\nYeah, there is a way out of that.\n\n599\n00:35:13,480 --> 00:35:16,080\n我们可以修改整个语言\nWe could change the language so that\n\n600\n00:35:16,144 --> 00:35:18,192\n使得所有的过程都表现得像CONS-STREAM一样\nall procedures acted like cons-stream,\n\n601\n00:35:19,104 --> 00:35:21,488\n这样所有的过程都会\nso that every procedure automatically\n\n602\n00:35:22,320 --> 00:35:25,450\n自动、隐式地为它的参数加上DELAY\nhas an implicit delay around its arguments.\n\n603\n00:35:25,450 --> 00:35:26,432\n这是什么意思呢？\nAnd what would that mean?\n\n604\n00:35:27,520 --> 00:35:29,536\n就是说 当你调用一个过程时\nThat would mean when you call a procedure,\n\n605\n00:35:30,160 --> 00:35:31,888\n参数并不会立即求值\nthe arguments wouldn't get evaluated.\n\n606\n00:35:32,210 --> 00:35:34,704\n只有在需要被求值的时候 它们才会被求值\nInstead, they'd only be evaluated when you need them,\n\n607\n00:35:34,896 --> 00:35:36,720\n它们也可能被传递给其它的过程\nso they might be passed off to some other procedure,\n\n608\n00:35:36,768 --> 00:35:38,128\n而这个过程也不会求值这些参数\nwhich wouldn't evaluate them either.\n\n609\n00:35:39,260 --> 00:35:41,904\n因此这些过程间传递的是PROMISE\nSo all these procedures would be passing promises around.\n\n610\n00:35:42,150 --> 00:35:44,464\n直到最后\nAnd then finally maybe when you finally got down\n\n611\n00:35:44,656 --> 00:35:47,344\n你需要查看某个值的时候\nto having to look at the value of something\n\n612\n00:35:47,360 --> 00:35:48,992\n可能是因为一个基本运算所需要\nthat was handed to a primitive operator\n\n613\n00:35:49,376 --> 00:35:51,488\n这是你才实际求值这些PROMISE\nwhich you actually start calling in all those promises.\n\n614\n00:35:52,380 --> 00:35:53,168\n像这样修改语言之后\nIf we did that,\n\n615\n00:35:53,360 --> 00:35:55,376\n由于所有的东西都是统一被延时的\nsince everything would have a uniform delay,\n\n616\n00:35:57,168 --> 00:35:59,008\n就不需要任何显式的DELAY了\nthen you wouldn't have to write any explicit delays,\n\n617\n00:35:59,040 --> 00:36:01,552\n因为它自动地内建在语言之中了\nbecause it would be automatically built into the way the language works.\n\n618\n00:36:03,248 --> 00:36:04,384\n换句话来说\nOr another way to say that,\n\n619\n00:36:05,100 --> 00:36:08,144\n从技术上来说 我所描述的\ntechnically what I'm describing is what's called\n\n620\n00:36:09,024 --> 00:36:10,768\n如果修改后的语言被称作\nif we did that, our language would be\n\n621\n00:36:12,192 --> 00:36:16,576\n所谓的“正则序求值”语言\nso-called normal-order evaluation language\n\n622\n00:36:20,208 --> 00:36:23,470\n这个跟我们一直使用的语言不同\nversus what we've actually been working with,\n\n623\n00:36:23,872 --> 00:36:33,792\n我们所用的是“应用序求值”语言\nwhich is called applicative order--  versus applicative-order evaluation.\n\n624\n00:36:34,560 --> 00:36:36,835\n还记得应用序求值的代换模型吧\nAnd remember the substitution model for applicative order.\n\n625\n00:36:36,830 --> 00:36:40,496\n当你求值一个组合式的时候\nIt says when you go and evaluate a combination,\n\n626\n00:36:40,512 --> 00:36:42,112\n你需要先计算出每一个元素的值\nyou find the values of all the pieces.\n\n627\n00:36:43,590 --> 00:36:45,408\n先求值所有的参数\nYou evaluate the arguments and then you\n\n628\n00:36:45,720 --> 00:36:47,424\n再把它们代换入过程的体\nsubstitute them in the body of the procedure.\n\n629\n00:36:47,600 --> 00:36:49,552\n正则序则不是这样\nNormal order says no, don't do that.\n\n630\n00:36:49,890 --> 00:36:51,904\n你所做的则是\nWhat you do is effectively\n\n631\n00:36:52,768 --> 00:36:54,416\n直接将参数代换入过程的体\nsubstitute in the body of the procedure,\n\n632\n00:36:54,448 --> 00:36:56,192\n而不先对参数求值\nbut instead of evaluating the arguments,\n\n633\n00:36:56,544 --> 00:36:58,080\n只是代换入了一个计算参数的PROMISE\nyou just put a promise to compute them there.\n\n634\n00:36:58,816 --> 00:36:59,904\n换句话说就是\nOr another way to say that\n\n635\n00:36:59,920 --> 00:37:02,096\n把作为参数的整个表达式\nyou take the expressions for the arguments, if you like,\n\n636\n00:37:02,288 --> 00:37:04,848\n直接代入过程的体进行代换\nand substitute them in the body of the procedure and go on,\n\n637\n00:37:05,168 --> 00:37:06,880\n在此之间从不进行任何化简\nand never really simplify anything\n\n638\n00:37:07,168 --> 00:37:08,768\n直到遇到一个基本运算符\nuntil you get down to a primitive operator.\n\n639\n00:37:09,472 --> 00:37:10,992\n这就是所谓的正则序求值语言\nSo that would be a normal-order language.\n\n640\n00:37:12,176 --> 00:37:13,120\n我们为什么不这样做呢？\nWell, why don't we do that?\n\n641\n00:37:13,824 --> 00:37:14,608\n这样做了之后\nBecause if we did,\n\n642\n00:37:15,008 --> 00:37:17,344\n我们就获得了延时求值的所有优点\nwe'd get all the advantages of delayed evaluation\n\n643\n00:37:17,904 --> 00:37:18,800\n而不会一片混乱\nwith none of the mess.\n\n644\n00:37:18,940 --> 00:37:20,192\n事实上 如果我们这样做了之后\nIn fact, if we did that\n\n645\n00:37:20,432 --> 00:37:22,672\nCONS也会是延时求值的\nand cons was just a delayed procedure,\n\n646\n00:37:22,688 --> 00:37:24,570\n就和CONS-STREAM一样\nthat would make cons the same as cons-stream.\n\n647\n00:37:24,710 --> 00:37:25,824\n我们就不再需要流了\nWe wouldn't need streams at all\n\n648\n00:37:26,368 --> 00:37:28,544\n因为表自动成为了流\nbecause lists would automatically be streams.\n\n649\n00:37:29,552 --> 00:37:30,704\n表和流有一样的行为\nThat's how lists would behave,\n\n650\n00:37:30,752 --> 00:37:32,350\n所有的数据结构也会像那样\nall data structures would behave that way.\n\n651\n00:37:32,350 --> 00:37:33,648\n所有的都是\nEverything would behave that way.\n\n652\n00:37:35,070 --> 00:37:37,632\n直到需要答案的时候\nRight, You'd never really do any computation\n\n653\n00:37:37,664 --> 00:37:39,424\n才会去实际的求值\nuntil you actually needed the answer.\n\n654\n00:37:40,800 --> 00:37:43,584\n不必再担心 什么时候需要显式地标注DELAY\nYou wouldn't have to worry about all these explicit annoying delays.\n\n655\n00:37:44,790 --> 00:37:46,160\n为什么不这样做呢？\nWell, why don't we do that?\n\n656\n00:37:47,160 --> 00:37:48,816\n首先 已经有人这样做过了\nFirst of all, I should say people do do that.\n\n657\n00:37:49,230 --> 00:37:51,850\n有一些十分优雅的语言\nThere's some very beautiful languages.\n\n658\n00:37:51,850 --> 00:37:55,216\n其中最为人称道的是一门名为 Miranda 的语言\nOne of the very nicest is a language called Miranda,\n\n659\n00:37:55,776 --> 00:37:56,768\n它是由\nwhich is, um..\n\n660\n00:37:57,440 --> 00:37:59,808\n肯特大学的 David Turner 开发的\ndeveloped by David Turner at the University of Kent.\n\n661\n00:38:00,710 --> 00:38:01,930\n它就是用这样的原理实现的\nAnd that's how this language works.\n\n662\n00:38:01,930 --> 00:38:03,344\nMiranda是正则序求值语言\nIt's a normal-order language\n\n663\n00:38:04,272 --> 00:38:05,552\n它的数据结构\nand its data structures,\n\n664\n00:38:06,160 --> 00:38:08,416\n看起来像表 实际上确实流\nwhich look like lists, are actually streams.\n\n665\n00:38:08,960 --> 00:38:10,912\n你不需要任何特殊的功能\nAnd you write ordinary procedures in Miranda,\n\n666\n00:38:11,280 --> 00:38:13,280\n就可以在Miranda中编写普通的过程\nand they do these prime things and eight queens things,\n\n667\n00:38:13,328 --> 00:38:14,970\n来解决质数、八皇后这样的问题\njust without anything special.\n\n668\n00:38:14,970 --> 00:38:16,352\n这些都是语言的内建功能\nIt's all built in there.\n\n669\n00:38:17,936 --> 00:38:18,912\n但这样做也要付出代价\nBut there's a price.\n\n670\n00:38:21,190 --> 00:38:22,368\n还记得我们为什么引入流了吗？\nRemember how we got here.\n\n671\n00:38:23,170 --> 00:38:27,480\n我们分离了程序的时间和它实际执行的时间\nWe're decoupling time in the programs from time in the machines.\n\n672\n00:38:27,968 --> 00:38:28,880\n如果我们引入了DELAY\nAnd if we put delay,\n\n673\n00:38:29,040 --> 00:38:30,336\n这样就在所有的地方完成了解耦\nthat sort of decouples it everywhere,\n\n674\n00:38:30,400 --> 00:38:31,424\n而不单单是在流中\nnot just in streams.\n\n675\n00:38:32,192 --> 00:38:33,140\n我们的初衷是什么？\nRemember what we're trying to do.\n\n676\n00:38:33,140 --> 00:38:38,112\n我们把程序设计看做是指定计算过程\nWe're trying to think about programming as a way to specify processes.\n\n677\n00:38:39,300 --> 00:38:40,624\n如果我们放弃了对时间的控制\nAnd if we give up too much time,\n\n678\n00:38:40,656 --> 00:38:42,416\n尽管语言变得优雅起来\nour language becomes more elegant,\n\n679\n00:38:43,744 --> 00:38:45,872\n但是它的表达力却有所下降\nbut it becomes a little bit less expressive.\n\n680\n00:38:47,030 --> 00:38:49,840\n这里面还有一些我们无法消除的区别\nThere are certain distinctions that we can't draw.\n\n681\n00:38:51,480 --> 00:38:53,152\n其中之一就是迭代\nOne of them, for instance, is iteration.\n\n682\n00:38:53,980 --> 00:38:56,448\n还记得这个程序吗？\nRemember this old procedure,\n\n683\n00:38:56,960 --> 00:38:58,288\n迭代式的阶乘\niterative factorial,\n\n684\n00:38:58,448 --> 00:39:00,480\n这是我们很早之前就研究过的\nthat we looked at quite a long time ago.\n\n685\n00:39:01,230 --> 00:39:02,976\n过程FACT-ITER\nIterative factorial had a thing,\n\n686\n00:39:03,040 --> 00:39:04,912\n有一个内部过程ITER\nand it said there was an internal procedure,\n\n687\n00:39:05,184 --> 00:39:07,504\n它含有两个状态PRODUCT和COUNTER\nand there was a state which was a product and a counter,\n\n688\n00:39:08,704 --> 00:39:10,960\n它们随着循环不断迭代\nand we iterate that going around the loop.\n\n689\n00:39:12,120 --> 00:39:13,680\n之所以说这个过程是迭代的\nAnd we said that was an iterative procedure\n\n690\n00:39:13,712 --> 00:39:14,832\n是因为它没有创建新状态\nbecause it didn't build up state.\n\n691\n00:39:15,730 --> 00:39:17,456\n之所以没有创建新状态\nAnd the reason it didn't build up state is\n\n692\n00:39:17,472 --> 00:39:20,256\n是因为在调用ITER时\nbecause this iter that's called\n\n693\n00:39:20,304 --> 00:39:22,864\n作为参数传递给它自己的始终是这些东西\nis just passing these things around to itself.\n\n694\n00:39:23,900 --> 00:39:25,392\n在代换模型中\nOr in the substitution model that,\n\n695\n00:39:25,552 --> 00:39:27,792\nGerald教授给你们讲解过\nyou could see in the substitution model that Jerry did,\n\n696\n00:39:28,720 --> 00:39:30,016\n在迭代过程中\nthat in an iterative procedure,\n\n697\n00:39:30,032 --> 00:39:31,440\n状态并不需要增长\nthat state doesn't have to grow.\n\n698\n00:39:31,824 --> 00:39:34,224\n因此这是一个迭代过程\nAnd in fact, we said it doesn't, so this is an iteration.\n\n699\n00:39:34,992 --> 00:39:37,472\n但是如果用正则序语言\nBut now think about this exact same text\n\n700\n00:39:37,472 --> 00:39:39,104\n来运行这段程序\nif we had a normal-order language.\n\n701\n00:39:41,150 --> 00:39:42,176\n这就会导致\nWhat would happen is\n\n702\n00:39:42,880 --> 00:39:44,960\n这个过程不再是迭代式了\nthis would no longer be an iterative procedure\n\n703\n00:39:45,650 --> 00:39:48,672\n如果你仔细地思考代换模型\nAnd if you really think about the details of the substitution model,\n\n704\n00:39:48,672 --> 00:39:49,904\n在这里我就不细说了\nwhich I'm not going to do here,\n\n705\n00:39:51,200 --> 00:39:52,352\n这个表达式会不断增长\nthis expression would grow.\n\n706\n00:39:52,368 --> 00:39:53,184\n为什么会这样？\nWhy would it grow?\n\n707\n00:39:53,280 --> 00:39:55,200\n因为当ITER调用自己时\nIt's because when iter calls itself,\n\n708\n00:39:55,856 --> 00:39:57,312\n参数是这个乘法表达式\nit calls itself with this product.\n\n709\n00:39:58,080 --> 00:39:59,360\n而在正则序语言中\nIf it's a normal-order language,\n\n710\n00:39:59,392 --> 00:40:01,168\n这个乘法并不会在这里求值\nthat multiplication is not going to get done.\n\n711\n00:40:02,510 --> 00:40:03,824\n传递给自己并代换的\nThat's going to say I'm to call myself\n\n712\n00:40:03,936 --> 00:40:05,680\n只是这个乘法计算的PROMISE\nwith a promise to compute this product.\n\n713\n00:40:06,670 --> 00:40:08,032\n然后继续代换下去\nAnd now iter goes around again.\n\n714\n00:40:09,760 --> 00:40:11,552\n我调用自己\nAnd I'm going to call myself\n\n715\n00:40:11,840 --> 00:40:14,048\n用的是计算这个乘法的PROMISE\nwith a promise to compute this product\n\n716\n00:40:14,048 --> 00:40:17,820\n但其中的一个因数也是个PROMISE\nwhere now one of the one factors is a promise.\n\n717\n00:40:18,400 --> 00:40:19,430\n然后我又自调用\nAnd I call myself again.\n\n718\n00:40:19,430 --> 00:40:21,136\n如果你用代换模型\nAnd if you write out the substitution model\n\n719\n00:40:21,984 --> 00:40:23,600\n来推演这个迭代步骤\nfor that iterative process,\n\n720\n00:40:23,776 --> 00:40:26,832\n你会发现同样的状态增长\nyou'll see exactly the same growth in state,\n\n721\n00:40:27,160 --> 00:40:28,960\n所有的PROMISE都需要被记住\nall those promises that are getting remembered\n\n722\n00:40:28,976 --> 00:40:30,760\n以便在最后被调用\nthat have to get called in at the very end.\n\n723\n00:40:31,790 --> 00:40:35,024\n所以 正则序的缺点之一\nSo one of the disadvantages\n\n724\n00:40:35,056 --> 00:40:36,864\n就是无法有效地表达迭代\nis that you can't really express iteration.\n\n725\n00:40:36,980 --> 00:40:39,600\n也许这个理由有点偏理论\nMaybe that's a little theoretical reason why not,\n\n726\n00:40:39,616 --> 00:40:43,904\n但事实上 那些使用这类语言来编写\nbut in fact, people who are trying to write real operating systems\n\n727\n00:40:44,272 --> 00:40:47,568\n实际操作系统的人 也都遇到了这类问题\nin these languages are running into exactly these types of problems.\n\n728\n00:40:48,208 --> 00:40:50,752\n当然 完全可以\nLike it's perfectly possible to\n\n729\n00:40:51,648 --> 00:40:54,384\n用这类语言实现一个文本编辑器\nimplement a text editor in languages like these.\n\n730\n00:40:54,610 --> 00:40:56,080\n但是你才用了一会儿\nBut after you work a while,\n\n731\n00:40:56,720 --> 00:40:59,392\n就发现已经占用了3MB空间\nyou suddenly have 3 megabytes of stuff,\n\n732\n00:40:59,440 --> 00:41:02,048\n我想 那些遇到这类问题的人\nwhich is-- I guess they call them\n\n733\n00:41:02,160 --> 00:41:05,600\n把它叫做 “拖尾问题”\nthe dragging tail problem who are looking at these,\n\n734\n00:41:05,824 --> 00:41:08,208\n由于不能有效地表达迭代计算\nof stuff of promises that sort of haven't been called in\n\n735\n00:41:08,240 --> 00:41:10,464\n导致堆积了一堆没有被调用的PROMISE\nbecause you couldn't quite express an iteration.\n\n736\n00:41:10,720 --> 00:41:14,816\n针对这类语言的一个研究方向就是\nAnd one of the research questions in these kinds of languages\n\n737\n00:41:14,832 --> 00:41:17,488\n找出一种有效的编译器技术\nare figuring out the right compiler technology\n\n738\n00:41:17,824 --> 00:41:19,856\n来避免这种所谓的“拖尾问题”\nto get rid of the so-called dragging tails.\n\n739\n00:41:20,176 --> 00:41:21,616\n这并不简单\nIt's not simple.\n\n740\n00:41:23,940 --> 00:41:27,312\n但是 还有一个很突出的问题\nBut there's another kind of more striking issue\n\n741\n00:41:27,968 --> 00:41:31,040\n使你的语言不能变成正则序\nabout why you just don't go ahead and make your language normal order.\n\n742\n00:41:32,512 --> 00:41:33,296\n问题就在于\nAnd the reason is\n\n743\n00:41:35,056 --> 00:41:38,096\n正则序和副作用\nthat normal-order evaluation and side effects\n\n744\n00:41:38,896 --> 00:41:40,192\n是不相容的\njust don't mix.\n\n745\n00:41:42,000 --> 00:41:43,968\n它们不能很好地相互配合\nThey just don't go together very well.\n\n746\n00:41:45,440 --> 00:41:46,656\n这是因为 你不能\nSomehow, you can't-\n\n747\n00:41:48,288 --> 00:41:50,800\n你不能一边\nit's sort of you can't simultaneously\n\n748\n00:41:51,008 --> 00:41:54,336\n建模具有局部状态的对象\ngo around trying to model objects with local state and change\n\n749\n00:41:55,728 --> 00:41:56,960\n同时又\nat the same time\n\n750\n00:41:57,184 --> 00:41:59,552\n使用正则序的技巧来解耦时间\ndo these normal-order tricks of de-coupling time.\n\n751\n00:42:00,400 --> 00:42:03,552\n我来举一个非常简单的例子\nLet me just show you a really simple example, very, very simple.\n\n752\n00:42:03,790 --> 00:42:05,504\n假设语言是正则序求值\nSuppose we had a normal-order language.\n\n753\n00:42:07,520 --> 00:42:09,550\n例子是这样的\nAnd I'm going to start out in this language.\n\n754\n00:42:09,550 --> 00:42:10,520\n注意现在是正则序求值\nThis is now normal order.\n\n755\n00:42:10,520 --> 00:42:12,224\n(DEFINE X 0)\nI'm going to define x to be 0.\n\n756\n00:42:13,570 --> 00:42:15,568\n这只是变量的初始化\nIt's just some variable I'll initialize.\n\n757\n00:42:15,750 --> 00:42:17,696\n现在我要定义一个有趣的函数\nAnd now I'm going to define this little funny function,\n\n758\n00:42:18,576 --> 00:42:20,448\n它就是恒等函数ID\nwhich is an identity function.\n\n759\n00:42:22,640 --> 00:42:23,904\n它所做的就是\nAnd what it does,\n\n760\n00:42:24,112 --> 00:42:26,608\n用X来记录上一次调用它时N的值\nit keeps track of the last time you called it using x.\n\n761\n00:42:31,400 --> 00:42:34,160\n因此(ID N)就返回N\nRight? So the identity of n just returns n,\n\n762\n00:42:34,176 --> 00:42:35,390\n但还要把X赋值为N\nbut it sets x to be n.\n\n763\n00:42:36,760 --> 00:42:38,544\n最后再定义一个过程INC\nAnd now I'll define a little increment function,\n\n764\n00:42:39,552 --> 00:42:42,304\n也非常简单\nwhich is a very little, simple scenario.\n\n765\n00:42:42,580 --> 00:42:45,344\n假设在正则序求值的语言里\nNow, imagine I'm interacting with this in the normal-order language,\n\n766\n00:42:46,272 --> 00:42:47,230\n求值下面的表达式\nand I type the following.\n\n767\n00:42:47,230 --> 00:42:52,832\n我输入 (DEFINE Y (INC (ID 3)))\nI say define y to be increment the identity function of 3,\n\n768\n00:42:52,832 --> 00:42:53,968\n因此Y的值应该是4\nso y is going to be 4.\n\n769\n00:42:57,410 --> 00:42:58,352\nX应该是多少呢？\nNow, I say what's x?\n\n770\n00:42:59,520 --> 00:43:02,160\nX应该是最后一次被记住的值\nWell, x should have been the value that was remembered last\n\n771\n00:43:02,640 --> 00:43:04,016\n也就是我调用函数ID的时候\nwhen I called the identity function.\n\n772\n00:43:04,710 --> 00:43:06,736\n你可能会想 这里X应该是3\nSo you'd expect to say, well, x is 3 at this point,\n\n773\n00:43:06,912 --> 00:43:07,520\n但是并不是这样\nbut it's not.\n\n774\n00:43:08,530 --> 00:43:11,152\n这是因为当我在这里定义Y的时候\nBecause when I defined here, y here,\n\n775\n00:43:11,792 --> 00:43:13,456\nY的真正定义却是\nwhat I really defined y to be\n\n776\n00:43:13,472 --> 00:43:15,712\n一个调用函数ID的PROMISE的增量\nincrement of a promise to do this thing.\n\n777\n00:43:17,000 --> 00:43:18,176\n因为我没有访问Y\nSo I didn't look at y,\n\n778\n00:43:18,368 --> 00:43:20,256\n所以ID没有运行\nso that identity function didn't get run.\n\n779\n00:43:21,560 --> 00:43:23,200\n我输入这个定义之后\nSo if I type in this definition\n\n780\n00:43:23,312 --> 00:43:24,800\n然后查询X得到的结果是0\nand look at x, I'm going to get 0.\n\n781\n00:43:28,360 --> 00:43:31,200\n现在 我输入Y查询它的值\nNow, if I go look at y and say what's y,\n\n782\n00:43:31,520 --> 00:43:32,432\n就会得到结果4\nsay y is 4,\n\n783\n00:43:32,670 --> 00:43:35,168\n对Y的主动查询\nlooking at y, that very active looking at y\n\n784\n00:43:35,296 --> 00:43:37,424\n会导致ID运行\ncaused the identity function to be run.\n\n785\n00:43:38,720 --> 00:43:40,480\n现在X=3就被记住\nAnd now x will get remembered as 3.\n\n786\n00:43:40,740 --> 00:43:41,872\n所以上面这里的X就应该是0\nSo here x will be 0.\n\n787\n00:43:41,936 --> 00:43:42,960\n下面这里是3\nHere, x will be 3.\n\n788\n00:43:43,280 --> 00:43:46,160\n这是一个非常简单的场景\nThat's a tiny, little, simple scenario,\n\n789\n00:43:46,304 --> 00:43:49,280\n但你会发现 调试正则序语言\nbut you can see what kind of a mess that's going to make\n\n790\n00:43:50,368 --> 00:43:53,344\n的交互式程序\nfor debugging interactive programs\n\n791\n00:43:54,128 --> 00:43:55,888\n会变得相当混乱\nwhen you have normal-order evaluation.\n\n792\n00:43:57,100 --> 00:43:58,128\n很令人迷惑\nIt's very confusing.\n\n793\n00:43:59,690 --> 00:44:02,048\n导致这样的深层次的原因\nBut it's very confusing for a very deep reason,\n\n794\n00:44:02,800 --> 00:44:06,416\n也就是引入DELAY的根本理念\nwhich is that the whole idea of putting in delays\n\n795\n00:44:06,928 --> 00:44:08,432\n是因为我们抛弃了时间的概念\nis that you throw away time.\n\n796\n00:44:09,780 --> 00:44:11,750\n也因为如此我们可以处理一些无穷的情况\nThat's why we can have these infinite processes.\n\n797\n00:44:11,750 --> 00:44:12,976\n我们抛弃了时间\nSince we've thrown away time,\n\n798\n00:44:12,992 --> 00:44:14,270\n就没有必要等它们运行\nwe don't have to wait for them to run,\n\n799\n00:44:17,550 --> 00:44:20,448\n我们把计算机中事件发生的顺序\nRight? We decouple the order of events in the computer\n\n800\n00:44:20,832 --> 00:44:22,112\n与程序中的顺序 分离开来\nfrom what we write in our programs.\n\n801\n00:44:22,352 --> 00:44:25,280\n但是当我们谈及状态、赋值和改变的时候\nBut when we talk about state and set and change,\n\n802\n00:44:25,488 --> 00:44:27,424\n这些又都是我们想要控制的\nthat's exactly what we do want control of.\n\n803\n00:44:28,760 --> 00:44:33,824\n我们的目的有着根本性的矛盾\nSo it's almost as if there's this fundamental contradiction in what you want.\n\n804\n00:44:34,570 --> 00:44:39,120\n这又让我们进入了一个哲学问题\nAnd that brings us back to these sort of philosophical mutterings\n\n805\n00:44:39,136 --> 00:44:40,752\n用什么样的模型\nwhat is it that you're trying to model\n\n806\n00:44:40,784 --> 00:44:41,776\n和从什么角度来看这个世界\nand how do you look at the world.\n\n807\n00:44:42,410 --> 00:44:44,304\n有时这也被称为\nOr sometimes this is called the\n\n808\n00:44:44,768 --> 00:44:46,608\n“函数式程序设计的争论”\nthe debate over functional programming.\n\n809\n00:44:54,192 --> 00:44:56,608\n所谓的“纯函数式语言”\nA so-called purely functional language\n\n810\n00:44:57,072 --> 00:44:59,200\n是完全没有副作用的\nis one that just doesn't have any side effects.\n\n811\n00:45:00,440 --> 00:45:01,632\n不需要副作用\nSince you have no side effects,\n\n812\n00:45:01,648 --> 00:45:03,020\n也就不需要赋值运算符\nthere's no assignment operator,\n\n813\n00:45:03,344 --> 00:45:05,728\n也就没有什么糟糕的后果\nso there are no terrible consequences of it.\n\n814\n00:45:06,360 --> 00:45:07,930\n可以使用类似代换模型\nYou can use a substitution-like thing.\n\n815\n00:45:07,930 --> 00:45:10,480\n程序更像是数学\nPrograms really are like mathematics and not like\n\n816\n00:45:10,768 --> 00:45:13,824\n而不像现实世界中的模型和对象\nnot like models in the real world, not like objects in the real world.\n\n817\n00:45:15,050 --> 00:45:17,170\n函数式语言有很多了不起的特性\nThere are a lot of wonderful things about functional languages.\n\n818\n00:45:17,170 --> 00:45:19,632\n没有时间的概念 所以完全不用担心同步的问题\nSince there's no time, you never have any synchronization problems.\n\n819\n00:45:20,640 --> 00:45:23,728\n如果你想在并行算法中应用一些东西\nAnd if you want to put something into a parallel algorithm,\n\n820\n00:45:24,720 --> 00:45:28,208\n你可以在这些并行过程中随心所欲地使用\nyou can run the pieces of that parallel processing any way you want.\n\n821\n00:45:29,408 --> 00:45:31,440\n从来不担心同步问题\nThere's just never any synchronization to worry that,\n\n822\n00:45:31,504 --> 00:45:33,344\n在这种环境下这样做是非常方便的\nand it's a very congenial environment for doing this.\n\n823\n00:45:33,640 --> 00:45:35,712\n代价则是 放弃了赋值\nThe price is you give up assignment.\n\n824\n00:45:39,104 --> 00:45:41,328\n函数式语言的支持者会认为\nSo an advocate of a functional language would say,\n\n825\n00:45:41,344 --> 00:45:43,040\n这点代价算不了什么\ngee, that's just a tiny price to pay.\n\n826\n00:45:44,520 --> 00:45:46,510\n在大部分情况下 你都不应该使用赋值\nYou probably shouldn't use assignment most of the time anyway.\n\n827\n00:45:46,880 --> 00:45:48,272\n如果用你放弃了赋值\nAnd if you just give up assignment,\n\n828\n00:45:48,432 --> 00:45:51,408\n你可以得到一个比对象世界\nyou can be in this much, much nicer world\n\n829\n00:45:51,968 --> 00:45:53,248\n好得多的世界\nthan this place with objects.\n\n830\n00:45:54,190 --> 00:45:56,300\n怎么来反驳这个观点呢？\nWell, what's the rejoinder to that?\n\n831\n00:45:56,300 --> 00:45:58,592\n想想 我们如何走到这一步的\nRemember how we got into this mess.\n\n832\n00:46:00,064 --> 00:46:03,792\n我们尝试建模具有局部状态的对象\nWe started trying to model things that had local state.\n\n833\n00:46:04,440 --> 00:46:06,496\n想一想Gerald教授给你们讲的随机数生成器\nSo remember Gerry's random number generator.\n\n834\n00:46:07,168 --> 00:46:08,672\n这里有一个随机数生成器\nThere was this random number generator\n\n835\n00:46:09,280 --> 00:46:10,624\n它内部有一些状态\nthat had some little state in it\n\n836\n00:46:10,830 --> 00:46:12,080\n用来计算下一个随机数\nto compute the next random number\n\n837\n00:46:12,128 --> 00:46:14,080\n下下一个 以及再下一个\nand the next random number and the next random number.\n\n838\n00:46:14,288 --> 00:46:16,144\n我们想要把这些状态跟\nAnd we wanted to hide that state away from the\n\n839\n00:46:16,432 --> 00:46:18,960\n计算π的Cesaro算法分离开来\nthe Cesaro compute pi process,\n\n840\n00:46:19,840 --> 00:46:20,928\n这就是我们为什么需要赋值\nand that's why we needed set!\n\n841\n00:46:20,976 --> 00:46:22,912\n我们想要把状态封装在模块中\nWe wanted to package that stated modularly.\n\n842\n00:46:24,070 --> 00:46:26,368\n函数式语言程序员可能会说\nWell, a functional programming person would say,\n\n843\n00:46:26,384 --> 00:46:27,560\n“你搞错了”\nwell, you're just all wet.\n\n844\n00:46:27,560 --> 00:46:29,840\n“我的意思是 你能写出另一种更具模块化的程序”\nI mean, you can write a perfectly good modular program.\n\n845\n00:46:29,840 --> 00:46:32,464\n“你对模块化的认识并不正确”\nIt's just you're thinking about modularity wrong.\n\n846\n00:46:33,080 --> 00:46:35,024\n你太执着于 “生成一个随机数\nYou're hung up in this next random number\n\n847\n00:46:35,072 --> 00:46:36,880\n再生成一个 再生成一个” 这种范式了\nand the next random number and the next random number.\n\n848\n00:46:36,880 --> 00:46:39,424\n为什么不写一个这样的程序\nWhy don't you just say let's write a program.\n\n849\n00:46:40,090 --> 00:46:41,296\n构造一个枚举器\nLet's write an enumerator\n\n850\n00:46:41,952 --> 00:46:44,480\n它会生成一个随机数的无穷流\nwhich just generates an infinite stream of random numbers.\n\n851\n00:46:49,010 --> 00:46:50,912\n我们可以立即生成这个流\nWe can sort of have that stream all at once,\n\n852\n00:46:52,640 --> 00:46:54,540\n这样就可以用作随机数的源泉\nand that's going to be our source of random numbers.\n\n853\n00:46:54,540 --> 00:46:55,248\n如果有需要的话\nAnd then if you like,\n\n854\n00:46:55,536 --> 00:46:57,472\n你可以把它跟某个处理过程相连\nyou can put that through some sort of processor,\n\n855\n00:46:57,776 --> 00:47:01,168\n比如说Cesaro测试\nwhich is-- I don't know-- a Cesaro test,\n\n856\n00:47:04,944 --> 00:47:06,224\n然后这个处理过程进行自己的计算\nand that can do what it wants.\n\n857\n00:47:06,880 --> 00:47:08,560\n从这里出来的则是\nAnd what would come out of there\n\n858\n00:47:08,720 --> 00:47:27,456\n其中是一串的对π的估计值组成的流\nwould be a stream of successive approximations to pi.\n\n859\n00:47:28,140 --> 00:47:30,656\n随着我们深入访问这个流\nSo as we looked further down this stream,\n\n860\n00:47:30,768 --> 00:47:32,384\n相当于去拽这个Cesaro盒子\nwe'd tug on this Cesaro thing,\n\n861\n00:47:33,120 --> 00:47:35,360\n它就会拉取出许多随机数\nand it would pull out more and more random numbers.\n\n862\n00:47:35,540 --> 00:47:37,216\n随着我们对流的深入访问\nAnd the further and further we look down the stream,\n\n863\n00:47:37,232 --> 00:47:38,960\n得到的对π的估计值就越准\nthe better an approximation we'd get to pi.\n\n864\n00:47:39,720 --> 00:47:41,664\n具体的计算过程还是一样的\nAnd it would do exactly the same as the other computation,\n\n865\n00:47:41,664 --> 00:47:43,792\n只不过使用了另一种模块化的方式\nexcept we're thinking about the modularity different.\n\n866\n00:47:43,890 --> 00:47:45,552\n我们可以想象成一下子\nWe're saying imagine we had all that\n\n867\n00:47:45,560 --> 00:47:47,472\n就有了这所有的随机数\ninfinite streams of random numbers all at once.\n\n868\n00:47:49,280 --> 00:47:52,240\n这个过程的细节在书上有\nYou can see the details of this procedure in the book.\n\n869\n00:47:53,610 --> 00:47:57,856\n我们同样也陷于另外一些类似的事情中\nBut similarly, there are other things that we tend to get locked into\n\n870\n00:47:58,272 --> 00:48:01,200\n这种关于 这个、下一个以及再下一个的范式\non this one and that one and the next one and the next one,\n\n871\n00:48:01,376 --> 00:48:02,816\n完全可以不这么来做\nwhich don't have to be that way.\n\n872\n00:48:03,280 --> 00:48:06,544\n我们来思考一下银行系统\nLike you might think about like a banking system,\n\n873\n00:48:07,680 --> 00:48:08,900\n有个非常简单的场景\nwhich is a very simple idea.\n\n874\n00:48:08,900 --> 00:48:12,210\n我们假设这个程序代表了银行帐户\nImagine we have a program that sort of represents a bank account.\n\n875\n00:48:18,810 --> 00:48:20,848\n银行账户中可能有\nThe bank account might have in it--\n\n876\n00:48:22,784 --> 00:48:26,224\n如果我们以消息传递的角度来看\nif we looked at this in a sort of message-passing view of the world,\n\n877\n00:48:26,448 --> 00:48:28,128\n我们认为银行账户是一个对象\nwe'd say a bank account is an object\n\n878\n00:48:28,592 --> 00:48:31,510\n内部保存着标识余额的局部状态BALANCE\nthat has some local state in there, which is the balance, say.\n\n879\n00:48:34,110 --> 00:48:36,000\n如果一个用户使用这个系统\nAnd a user using this system comes\n\n880\n00:48:36,448 --> 00:48:38,144\n发出交易请求\nand sends a transaction request.\n\n881\n00:48:39,312 --> 00:48:41,056\n用户发出的交易请求可能是\nSo the user sends a transaction request,\n\n882\n00:48:41,072 --> 00:48:42,208\n存一些钱\nlike deposit some money,\n\n883\n00:48:42,288 --> 00:48:43,536\n银行账户就会\nand the bank account maybe--\n\n884\n00:48:43,920 --> 00:48:46,784\n我们假设银行账户总是以当前余额作为回应\nlet's say the bank account always responds with what the current balance is.\n\n885\n00:48:48,220 --> 00:48:50,048\n用户存了一些钱\nThe user says let's deposits some money,\n\n886\n00:48:50,064 --> 00:48:53,210\n银行账户就会返回一个消息指明当前余额\nand the bank account sends back a message which is the balance.\n\n887\n00:48:54,350 --> 00:48:57,424\n用户再存一些钱\nAnd the user says deposit some more,\n\n888\n00:48:57,456 --> 00:48:58,816\n银行就再返回消息\nand the bank account sends back a message.\n\n889\n00:48:59,150 --> 00:49:00,752\n就像生成随机数一样\nAnd just like the random number generating\n\n890\n00:49:00,784 --> 00:49:02,128\n我们想使用赋值来实现\nyou'd say, gee, we would like to use set.\n\n891\n00:49:03,200 --> 00:49:06,880\n帐户的内部保存了局部状态BALANCE\nWe'd like to have balance be a piece of local state inside this bank account\n\n892\n00:49:06,880 --> 00:49:08,400\n因为我们想要把用户状态\nbecause we want to separate the state of the user\n\n893\n00:49:08,416 --> 00:49:09,570\n和银行账户的状态分离开来\nfrom the state of the bank account.\n\n894\n00:49:13,280 --> 00:49:16,420\n这是从消息传递的角度来看\nWell, that's the message-processing view.\n\n895\n00:49:16,420 --> 00:49:18,208\n如果从流的角度来看\nThere's a stream view with that thing,\n\n896\n00:49:19,488 --> 00:49:22,192\n不需要赋值或副作用就可以达到同样的效果\nwhich does the same thing without any set or side effects.\n\n897\n00:49:22,740 --> 00:49:26,736\n再次强调 想法是这样的\nAnd the idea is again\n\n898\n00:49:27,376 --> 00:49:30,256\n我们认为它们都没有局部状态\nwe don't think about anything having local state.\n\n899\n00:49:31,180 --> 00:49:33,088\n我们把银行账户看作是\nWe think about the bank account as something\n\n900\n00:49:33,408 --> 00:49:37,712\n能够处理一系列交易请求的东西\nthat's going to process a stream of transaction requests.\n\n901\n00:49:38,640 --> 00:49:40,160\n不把银行账户看做\nSo think about this bank account not\n\n902\n00:49:40,224 --> 00:49:42,000\n逐个消息地处理\nas something that goes message by message,\n\n903\n00:49:42,448 --> 00:49:45,856\n而是处理某种交易请求流的东西\nbut something that takes in a stream of transaction requests\n\n904\n00:49:45,872 --> 00:49:48,496\n这个请求流可能是一些列的存款声明\nlike maybe successive deposit announced.\n\n905\n00:49:49,490 --> 00:49:54,944\n比如 1 2 2 4 这样的连续存钱请求\n1, 2, 2, 4, those might be successive amounts to deposit.\n\n906\n00:49:55,940 --> 00:50:02,448\n从帐户出来的流应该是 1 3 5 9\nAnd then coming out of it is the successive balances 1, 3, 5, 9.\n\n907\n00:50:03,770 --> 00:50:06,144\n我们不把银行账户看做某种具有状态的东西\nSo we think of the bank account not as something that has state,\n\n908\n00:50:06,400 --> 00:50:07,264\n而是某种能够处理\nbut something that acts\n\n909\n00:50:08,928 --> 00:50:10,820\n有关请求的无穷流的东西\nsort of on the infinite stream of requests.\n\n910\n00:50:10,820 --> 00:50:12,304\n但要注意 我们抛弃了时间\nBut remember, we've thrown away time.\n\n911\n00:50:12,370 --> 00:50:14,272\n如果这里有一个用户\nSo what we can do is if the user's here,\n\n912\n00:50:16,120 --> 00:50:19,136\n这个无穷请求流的元素\nwe can have this infinite stream of requests\n\n913\n00:50:19,184 --> 00:50:22,540\n我们可以一次生成一个\nbeing generated one at a time coming from the user\n\n914\n00:50:24,064 --> 00:50:26,576\n而这个交易流\nand this transaction stream\n\n915\n00:50:26,570 --> 00:50:28,800\n则会逐个打印在屏幕上\ncoming back on a printer being printed one at a time.\n\n916\n00:50:30,010 --> 00:50:31,376\n如果在这里画一条线\nAnd if we drew a little line here,\n\n917\n00:50:32,560 --> 00:50:33,088\n就在这里\nright there to the user,\n\n918\n00:50:33,280 --> 00:50:34,912\n对用户来说 他根本无法分辨\nthe user couldn't tell that this system doesn't have state.\n\n919\n00:50:36,192 --> 00:50:37,712\n这个系统是否有内部状态\nthat this system doesn't have state.\n\n920\n00:50:39,560 --> 00:50:41,136\n这个跟消息传递那种是一样的\nIt looks just like the other one,\n\n921\n00:50:41,296 --> 00:50:42,464\n只不过这个没有状态\nbut there's no state in there.\n\n922\n00:50:42,848 --> 00:50:45,872\n哦 顺便提一下\nAnd by the way,\n\n923\n00:50:46,720 --> 00:50:49,472\n这是具体的代码实现\njust to show you, here's an actual implementation\n\n924\n00:50:50,528 --> 00:50:52,304\n我们把它叫做MAKE-DEPOSIT-ACCOUNT\nof this-- we'll call it make deposit account\n\n925\n00:50:52,320 --> 00:50:53,328\n因为它只能够存钱\nbecause you can only deposit.\n\n926\n00:50:54,176 --> 00:50:55,776\n这个过程接受一个初始余额\nIt takes an initial balance\n\n927\n00:50:56,096 --> 00:50:58,096\n以及一个可能发起的存款流\nand then a stream of deposits you might make.\n\n928\n00:51:00,020 --> 00:51:00,820\n具体怎么做呢？\nAnd what is it?\n\n929\n00:51:00,820 --> 00:51:02,544\n它只是用CONS-STREAM把余额BALANCE\nWell, it's just cons-stream of the balance\n\n930\n00:51:03,232 --> 00:51:05,312\n和一个新的存款账户流组合在一起\nonto make a new account stream\n\n931\n00:51:06,240 --> 00:51:07,328\n新存款流的初始余额\nwhose initial balance\n\n932\n00:51:07,488 --> 00:51:10,272\n就是之前BALANCE的值加上存款流的第一个元素\nis the old balance plus the first thing in the deposit stream\n\n933\n00:51:10,864 --> 00:51:13,408\n而其余部分则是\nwhose rest, right and,\n\n934\n00:51:13,760 --> 00:51:17,376\n存款流的尾部分\nmake deposit account works on the rest of which is the tail of the deposit stream.\n\n935\n00:51:18,300 --> 00:51:23,840\n因此这种非常典型的消息传递式、面向对象的问题\nSo there's sort of a very typical message-passing,\n\n936\n00:51:23,952 --> 00:51:27,552\n完全可以不用副作用来解决\nmessage-passing, object-oriented thing that's done without side effects at all.\n\n937\n00:51:29,056 --> 00:51:30,768\n很多地方都可以这样做\nThere are very many things you can do this way.\n\n938\n00:51:32,250 --> 00:51:35,232\n那么 我们可以完全不用赋值么？\nWell, can you do everything without assignment?\n\n939\n00:51:36,400 --> 00:51:39,008\n可以只用纯函数式语言吗？\nCan everybody go over to purely functional languages?\n\n940\n00:51:40,050 --> 00:51:42,048\n这个问题谁也说不清\nWell, we don't know,\n\n941\n00:51:42,272 --> 00:51:43,440\n好像有些地方\nbut there seem to be places\n\n942\n00:51:43,920 --> 00:51:46,032\n纯函数式语言无法派上用场\nwhere purely functional programming breaks down.\n\n943\n00:51:48,100 --> 00:51:50,272\n当遇到像这样的系统时 问题就变得棘手起来\nWhere it starts hurting is when you have things like this,\n\n944\n00:51:50,432 --> 00:51:52,320\n特别是当你\nbut you also mix it up with\n\n945\n00:51:52,608 --> 00:51:54,272\n还需要考虑其它因素的时候\nthe other things that we had to worry that,\n\n946\n00:51:54,304 --> 00:51:55,648\n有关对象和共享\nwhich are objects and sharing\n\n947\n00:51:55,904 --> 00:51:58,528\n以及两个独立的主体共享同一个东西\nand two independent agents being the same.\n\n948\n00:51:58,850 --> 00:51:59,936\n举一个典型的例子\nSo under a typical one,\n\n949\n00:51:59,968 --> 00:52:01,632\n假如你来扩展这个帐户\nsuppose you want to extend this bank account.\n\n950\n00:52:03,248 --> 00:52:04,272\n这是一个帐户\nSo here's a bank account.\n\n951\n00:52:12,220 --> 00:52:14,752\n帐户接受一个交易请求流\nBank accounts take in a stream of transaction requests\n\n952\n00:52:15,200 --> 00:52:18,448\n输出的流则是关于余额的回复\nand put out streams of, say, balances or responses to that.\n\n953\n00:52:18,780 --> 00:52:20,160\n假设你所建模的是联合账户\nBut suppose you want to model the fact\n\n954\n00:52:20,176 --> 00:52:24,368\n而由两个独立用户共享\nthat this is a joint bank account between two independent people.\n\n955\n00:52:25,680 --> 00:52:28,656\n我们假设 假设有两个人\nRight? I don't know. So suppose there are two people,\n\n956\n00:52:28,976 --> 00:52:30,960\n比如说Bill和Dave\nsay, Bill and Dave,\n\n957\n00:52:31,776 --> 00:52:33,140\n他们俩共享一个帐户\nwho have a joint bank account.\n\n958\n00:52:35,960 --> 00:52:36,850\n怎么来建模呢？\nHow would you model this?\n\n959\n00:52:36,880 --> 00:52:39,800\n你或许会让Bill输出一个交易请求流\nWell, you might, Bill puts out a stream of transaction requests,\n\n960\n00:52:40,240 --> 00:52:42,256\nDave也产生一个这样的流\nand Dave puts out a stream of transaction requests,\n\n961\n00:52:42,256 --> 00:52:45,168\n这两个流需要以某种方式合并到银行账户中\nand somehow, they have to merge into this bank account.\n\n962\n00:52:45,880 --> 00:52:47,856\n因此你需要编写一个MERGE过程\nSo what you might do is write a little stream\n\n963\n00:52:47,904 --> 00:52:50,650\n来处理这些流\nprocessing thing called merge,\n\n964\n00:52:57,232 --> 00:52:59,136\n它把这些流合并在一起\nwhich sort of takes these, merges them together,\n\n965\n00:52:59,344 --> 00:53:01,190\n形成单个流 送入银行账户\nproduces a single stream for the bank account.\n\n966\n00:53:01,190 --> 00:53:02,992\n现在他们就共享一个帐户了\nNow they're both talking to the same bank account.\n\n967\n00:53:03,610 --> 00:53:05,488\n看起来不错 问题是怎么来实现MERGE\nThat's all great, but how do you write merge?\n\n968\n00:53:05,936 --> 00:53:08,240\nMERGE怎么来合并？\nWhat, What's this procedure merge?\n\n969\n00:53:09,730 --> 00:53:11,424\n需要合理的合并依据\nYou want to do something that's reasonable.\n\n970\n00:53:12,380 --> 00:53:13,808\n你可能首先会想\nYour first guess might be to say,\n\n971\n00:53:13,808 --> 00:53:16,688\n我们从Bill和Dave中选一个请求来处理\nwell, we'll take alternate requests from Bill and Dave.\n\n972\n00:53:18,190 --> 00:53:20,976\n但是如果在这中途\nBut what happens if But what happens if suddenly in the middle thing\n\n973\n00:53:21,184 --> 00:53:23,088\nDave突然外出度假两年 会怎么样？\nDave goes away on vacation for two years?\n\n974\n00:53:24,150 --> 00:53:25,408\nBill的交易就完全被阻塞了\nThen Bill's sort of stuck.\n\n975\n00:53:27,690 --> 00:53:29,750\n你想要的是\nSo what you want to do is-- well, it's hard to describe.\n\n976\n00:53:29,750 --> 00:53:33,648\n是一种公平的合并\nWhat you want to do is what people call fair merge.\n\n977\n00:53:38,410 --> 00:53:40,176\n这个所谓公平的合并\nThe idea of fair merge is\n\n978\n00:53:40,736 --> 00:53:42,464\n应该是交替地一次处理一个\nis it sort of should do them alternately,\n\n979\n00:53:42,496 --> 00:53:43,920\n但是如果一个人没有了交易\nbut if there's nothing waiting here,\n\n980\n00:53:43,968 --> 00:53:44,912\n应该继续去处理另一个人的交易\nit should take one twice.\n\n981\n00:53:46,010 --> 00:53:48,450\n但是没有时间 我就不能这样做\nNotice I can't even say that without talking about time.\n\n982\n00:53:51,300 --> 00:53:56,416\n函数式语言的另一个活跃研究领域就是\nSo one of the other active researcher areas in functional languages\n\n983\n00:53:56,432 --> 00:53:59,488\n发明类似于“公平合并”的算法\nis inventing little things like fair merge\n\n984\n00:54:00,350 --> 00:54:01,312\n又或者是其它的东西\nmaybe some others,\n\n985\n00:54:01,568 --> 00:54:06,256\n用于取代原来需要副作用和对象的地方\nwhich will take the places where I used to need side effects and objects\n\n986\n00:54:06,800 --> 00:54:10,528\n用一种良好定义的模块化系统来隐藏它们\nand sort of hide them away in some very well-defined modules of the system\n\n987\n00:54:10,860 --> 00:54:13,504\n这样 系统中就不会到处产生\nso that all the problems of assignment\n\n988\n00:54:13,520 --> 00:54:15,344\n赋值所带来的问题\ndon't sort of leak out all over the system but\n\n989\n00:54:15,408 --> 00:54:17,880\n因为它可以被理解透彻的概念所描述\nare captured in some fairly well-understood things.\n\n990\n00:54:20,780 --> 00:54:22,704\n推而广之 我想你们也发现了\nMore generally, I think what you're seeing\n\n991\n00:54:23,120 --> 00:54:24,064\n我们正面对 我所认为的\nis that we're running across\n\n992\n00:54:24,080 --> 00:54:26,670\n计算机科学中最基本的问题\nwhat I think is a very basic problem in computer science,\n\n993\n00:54:26,976 --> 00:54:27,824\n也就是\nwhich is how to\n\n994\n00:54:28,240 --> 00:54:32,032\n我们如何定义一门支持延迟求值的语言\nhow to define languages that somehow can talk about delayed evaluation\n\n995\n00:54:34,144 --> 00:54:35,088\n但同时又能够\nBut also\n\n996\n00:54:35,872 --> 00:54:38,256\n又能够把事物看做对象来操作\nbe able to reflect this view that there are objects in the world.\n\n997\n00:54:38,360 --> 00:54:40,368\n怎么样才能两者兼有之？\nHow do we somehow get both?\n\n998\n00:54:41,230 --> 00:54:43,040\n我认为这个问题很困难\nAnd I think that's a very hard problem.\n\n999\n00:54:43,040 --> 00:54:45,520\n但是这个很困难的问题\nAnd it may be that it's a very hard problem\n\n1000\n00:54:45,856 --> 00:54:48,176\n却和计算机科学的关系不大\nthat has almost nothing to do with computer science,\n\n1001\n00:54:48,590 --> 00:54:50,240\n它真正涉及的是\nthat it really is a problem having to do with\n\n1002\n00:54:50,272 --> 00:54:52,736\n两种不相容的看待世界的方式\ntwo very incompatible ways of looking at the world.\n\n1003\n00:54:54,144 --> 00:54:54,720\n有问题吗？\nOK, questions?\n\n1004\n00:55:17,550 --> 00:55:19,200\n学生：你之前提到过\nAUDIENCE: You mentioned earlier that\n\n1005\n00:55:20,112 --> 00:55:21,328\n一旦引入了赋值\nonce you introduce assignment,\n\n1006\n00:55:21,328 --> 00:55:25,890\n就不能使用代换模型了\nthe general rule for using the substitution model is you can't.\n\n1007\n00:55:25,890 --> 00:55:27,570\n除非你非常小心\nUnless you're very careful, you can't.\n\n1008\n00:55:27,570 --> 00:55:27,968\n教授：对的\nPROFESSOR: Right.\n\n1009\n00:55:28,260 --> 00:55:33,280\n学生：有什么技术或者指导方针\nAUDIENCE: Is there a set of techniques or a set of guidelines\n\n1010\n00:55:33,424 --> 00:55:35,920\n来确定赋值的影响\nfor localizing the effects of assignment\n\n1011\n00:55:36,528 --> 00:55:40,300\n以便说清楚这个“很小心”是怎么回事吗？\nso that the very careful becomes defined?\n\n1012\n00:55:40,300 --> 00:55:42,608\n教授：我不知道\nPROFESSOR: I don't know. Um...\n\n1013\n00:55:42,890 --> 00:55:43,584\n我想想\nLet me think.\n\n1014\n00:55:45,430 --> 00:55:48,944\n当然 实现MEM-PROC也使用了赋值\nWell, certainly, there was an assignment inside memo proc,\n\n1015\n00:55:50,128 --> 00:55:51,480\n但是它被隐藏了起来\nbut that was sort of hidden away.\n\n1016\n00:55:51,480 --> 00:55:53,008\n因为它没有对结果造成影响\nIt ended up not making any difference.\n\n1017\n00:55:53,480 --> 00:55:56,448\n部分原因之一在于 一旦触发这个过程\nPart of the reason for that is once this thing triggered\n\n1018\n00:55:57,152 --> 00:55:58,832\n它被求值并得到结果\nthat it had run and gotten an answer,\n\n1019\n00:55:58,832 --> 00:56:00,064\n这个结果不会再变化\nthat answer will never change.\n\n1020\n00:56:00,608 --> 00:56:02,336\n有点像单次赋值\nSo that was sort of a one-time assignment.\n\n1021\n00:56:02,350 --> 00:56:03,856\n一个一般性原则就是\nSo one very general thing you can do\n\n1022\n00:56:04,304 --> 00:56:06,352\n如果你只用这种单次赋值\nis if you only do what's called a one-time assignment\n\n1023\n00:56:08,040 --> 00:56:09,248\n并且它不再改变\nand never change anything,\n\n1024\n00:56:09,632 --> 00:56:10,540\n我想应该不会有太大问题\nthen you can do better.\n\n1025\n00:56:11,250 --> 00:56:14,128\n还有一个问题在于MERGE --\nOne of the problems in this merge thing, people have--\n\n1026\n00:56:14,672 --> 00:56:18,320\n让我想想对不对\npeople have-- let me see if this is right.\n\n1027\n00:56:18,490 --> 00:56:21,552\n我认为有了公平合并这一技术\nI think it's true that with fair merge,\n\n1028\n00:56:22,256 --> 00:56:26,096\n你可以在语言的其它地方\nwith just fair merge, you can begin effectively simulating\n\n1029\n00:56:27,024 --> 00:56:28,896\n有效地模拟赋值\nassignment in the rest of the language.\n\n1030\n00:56:30,820 --> 00:56:33,296\n这就像为了解决问题你会引入一些东西\nIt seems like anything you do to go outside--\n\n1031\n00:56:33,504 --> 00:56:35,504\n我不清楚对公平合并来说是否成立\nI'm not quite sure that's true for fair merge,\n\n1032\n00:56:35,536 --> 00:56:39,312\n但是对人们正在尝试的一些一般性事情是成立的\nbut it's true of a little bit more general things that people have been doing.\n\n1033\n00:56:39,520 --> 00:56:41,344\n所以 这可能是你引入的这一点点东西\nSo it might be that any little bit you put in,\n\n1034\n00:56:41,616 --> 00:56:44,144\n突然间 使你能构建任何东西\nsuddenly if they allow you to build arbitrary stuff,\n\n1035\n00:56:44,160 --> 00:56:46,512\n这就几乎跟有了赋值一样糟糕了\nit's almost as bad as having assignment altogether.\n\n1036\n00:56:47,970 --> 00:56:50,672\n这也是人们在研究的一个领域\nBut that's an area that people are thinking about now.\n\n1037\n00:56:51,590 --> 00:56:54,304\n学生：我还没有太明白MERGE的问题\nAUDIENCE: I guess I don't see the problem here with merge\n\n1038\n00:56:54,830 --> 00:56:59,200\n如果我调用Bill它是个过程\nif, you know the sense, I call Bill, if Bill is a procedure,\n\n1039\n00:56:59,216 --> 00:57:02,416\n那么Bill就会增加银行账户\nthen Bill is going to increment the bank account\n\n1040\n00:57:02,448 --> 00:57:04,730\n或者创建一个表 用于放置下一个存款\nor build the list that 's going to put in the next element.\n\n1041\n00:57:04,730 --> 00:57:06,848\n如果我连续调用Dave两次 他肯定也会那样\nIf I call Dave twice in a row, that will do that.\n\n1042\n00:57:07,170 --> 00:57:09,350\n我并不清楚为什么需要公平合并\nI'm not sure where fair merge has to be involved.\n\n1043\n00:57:09,350 --> 00:57:11,200\n教授：关键在于你得把这些当作真人一样\nPROFESSOR: The problem is imagine these really as people.\n\n1044\n00:57:11,200 --> 00:57:14,208\n这里有一个用户在操作帐户\nSee, here I have the user who's interacting with this bank account.\n\n1045\n00:57:14,850 --> 00:57:17,070\n请求一次 得到结果\nPut in a request, get an answer. Put in a request, get an answer.\n\n1046\n00:57:17,200 --> 00:57:17,568\n学生：对\nAUDIENCE: Right.\n\n1047\n00:57:18,200 --> 00:57:20,624\n教授：如果我只能通过从两个流中选择一个\nPROFESSOR: But if the only way I can process request\n\n1048\n00:57:20,656 --> 00:57:22,250\n来处理请求的话\nis to alternate them from two people--\n\n1049\n00:57:22,912 --> 00:57:24,220\n学生：为什么要二选一呢？\nAUDIENCE: Well, why would you alternate them?\n\n1050\n00:57:24,220 --> 00:57:25,232\n教授：为什么不呢？\nPROFESSOR: Why don't I?\n\n1051\n00:57:25,456 --> 00:57:25,808\n学生：对啊 为什么要这样呢？\nAUDIENCE: Yes. Why do you?\n\n1052\n00:57:26,608 --> 00:57:27,728\n教授：假设这些是现实中的人 对吗？\nPROFESSOR: Think of them as real people, right?\n\n1053\n00:57:27,760 --> 00:57:28,976\n这个人外出一年\nThis guy might go away for a year.\n\n1054\n00:57:29,280 --> 00:57:31,744\n你只能在银行账户窗口旁边等待\nAnd you're sitting here at the bank account window,\n\n1055\n00:57:32,430 --> 00:57:33,728\n就是不能处理两个请求\nand you can't put in two requests\n\n1056\n00:57:33,744 --> 00:57:34,944\n因为你还得等这个人\nbecause it's waiting for this guy.\n\n1057\n00:57:35,480 --> 00:57:37,072\n学生：为什么非得等他呢？\nAUDIENCE: Why does it have to be waiting for one?\n\n1058\n00:57:37,380 --> 00:57:39,110\n教授：因为这里是在计算一个函数\nPROFESSOR: Because it's trying to compute a function.\n\n1059\n00:57:39,110 --> 00:57:40,928\n我必须定义一个函数\nI have to define a function.\n\n1060\n00:57:41,720 --> 00:57:42,608\n换种方式来说\nAnother way to say that\n\n1061\n00:57:42,848 --> 00:57:44,992\n这个MERGE盒子的输出\nis the answer to what comes out of this merge box\n\n1062\n00:57:46,240 --> 00:57:49,488\n并不是输入的函数\nis not a function of what goes in.\n\n1063\n00:57:51,690 --> 00:57:53,490\n明白了吗？再来看看这个MERGE是怎么运行的\nBecause, see, what would the function be?\n\n1064\n00:57:53,490 --> 00:57:58,864\n假设Bill输入 1 1 1 1\nSuppose he puts in 1, 1, 1, 1,\n\n1065\n00:57:59,824 --> 00:58:02,784\nDave输入2 2 2 2\nand he puts in 2, 2, 2, 2.\n\n1066\n00:58:03,470 --> 00:58:04,800\nMERGE应该输出什么呢？\nWhat's the answer supposed to be?\n\n1067\n00:58:05,584 --> 00:58:08,740\n这里并不一定是 1 2 1 2 1 2\nIt's not good enough to say it's 1, 2, 1, 2, 1, 2.\n\n1068\n00:58:08,740 --> 00:58:09,390\n学生：我明白了\nAUDIENCE: I understand.\n\n1069\n00:58:09,390 --> 00:58:11,560\n当Bill输入1 1也就进去了\nBut when Bill puts in 1, 1 goes in.\n\n1070\n00:58:11,560 --> 00:58:13,950\nDave再输入两个2 MERGE就输出两个2\nWhen Dave puts in 2, twice 2 goes in twice.\n\n1071\n00:58:13,950 --> 00:58:14,736\n学生：当Bill输入\nAUDIENCE: When Bill puts in--\n\n1072\n00:58:14,768 --> 00:58:15,088\n教授：对的\nPROFESSOR: Right.\n\n1073\n00:58:15,130 --> 00:58:18,432\n学生：为什么不能在输入的数据上\nAUDIENCE: Why can't it be hooked to the time of the input--\n\n1074\n00:58:18,592 --> 00:58:20,064\n加上时间信息呢？\nthe actual procedural--\n\n1075\n00:58:20,128 --> 00:58:21,840\n教授：因为这里没有时间这个概念\nPROFESSOR: Because I don't have time.\n\n1076\n00:58:23,980 --> 00:58:26,900\n我只是定义一个函数\nSee, all I can say is I'm going to define a function.\n\n1077\n00:58:26,900 --> 00:58:28,150\n没有时间概念\nI don't have time.\n\n1078\n00:58:32,000 --> 00:58:34,192\n如果是二选一的话\nThere's no concept if it's going to alternate,\n\n1079\n00:58:34,192 --> 00:58:36,544\n如果选中的流没有人 就得等待它\nexcept if nobody's there, it's going to wait a while for him.\n\n1080\n00:58:38,420 --> 00:58:41,360\n它只会说 我有一个请求流\nIt's just going to say I have the stream of requests,\n\n1081\n00:58:41,740 --> 00:58:43,344\n这是是Dave生成的\nthe timeless infinite streams\n\n1082\n00:58:43,360 --> 00:58:45,296\n没有时刻的、无穷长度的请求流\nof all the requests that Dave would have made, right?\n\n1083\n00:58:47,550 --> 00:58:50,416\nBill可能生成 没有时刻的无穷请求流\nAnd the timeless infinite stream of all the requests Bill would have made,\n\n1084\n00:58:50,544 --> 00:58:51,690\n我想对这些东西做运算\nand I want to operate on them.\n\n1085\n00:58:51,690 --> 00:58:53,510\n这就是银行帐户的工作原理\nSee, that's how this bank account is working.\n\n1086\n00:58:56,710 --> 00:58:57,584\n问题是\nAnd the problem is\n\n1087\n00:58:57,610 --> 00:59:00,752\n这些坐在银行窗口前的倒霉蛋们\nthat these poor people who are sitting at the bank account windows\n\n1088\n00:59:00,768 --> 00:59:03,824\n来得并不是时候\nhave the misfortune to exist in time.\n\n1089\n00:59:05,296 --> 00:59:07,136\n它们才看不到这个无穷流\nThey don't see their infinite stream\n\n1090\n00:59:07,696 --> 00:59:09,536\n什么时候其中会有请求\nof all the requests they would have ever made.\n\n1091\n00:59:10,070 --> 00:59:11,550\n他们只是等着 等待帐户的响应\nThey're waiting now, and they want an answer.\n\n1092\n00:59:14,480 --> 00:59:15,760\n假设你坐在屏幕前\nSo if you're sitting there--\n\n1093\n00:59:16,240 --> 00:59:20,864\n操作着一台分时系统的计算机\nif this is the screen operation on some time-sharing system\n\n1094\n00:59:21,520 --> 00:59:22,608\n而且它还是函数式的\nand it's working functionally,\n\n1095\n00:59:22,640 --> 00:59:24,592\n输入指令后你就希望看到结果\nyou want an answer then when you talk the character.\n\n1096\n00:59:25,290 --> 00:59:27,424\n但是你并不想主机在处理完所有其它人的命令\nYou don't want it to have to wait for everybody in the whole system\n\n1097\n00:59:27,456 --> 00:59:29,920\n之后再来处理你的命令\nto have typed one character before it can get around to service you.\n\n1098\n00:59:30,910 --> 00:59:31,920\n这就是问题所在\nSo that's the problem.\n\n1099\n00:59:34,000 --> 00:59:36,384\n我的意思就是 用户的世界当然是存在时间概念的\nI mean, the fact that people live in time, apparently.\n\n1100\n00:59:37,216 --> 00:59:38,620\n如果没有 这就不构成问题\nIf they didn't, it wouldn't be a problem.\n\n1101\n00:59:49,100 --> 00:59:51,024\n学生：我想我还是不太理解\nAUDIENCE: I'm afraid I miss the point of\n\n1102\n00:59:51,088 --> 00:59:54,240\n银行交易中为什么没有时间概念这一要点\nhaving no time in this banking transaction.\n\n1103\n00:59:54,740 --> 00:59:56,656\n难道时间不是非常重要吗？\nIsn't time very important?\n\n1104\n00:59:56,880 --> 00:59:59,056\n举例说 有一系列事件\nFor instance, the sequence of events.\n\n1105\n00:59:59,950 --> 01:00:05,024\n比如Dave取款$100\nAs if, If Dave take out $100, and then\n\n1106\n01:00:06,304 --> 01:00:08,400\n这些顺序应该很重要才对\nthen the timing sequence should be important.\n\n1107\n01:00:08,400 --> 01:00:10,864\n你怎么能把它们看作是流呢？\nHow do you treat transactions as streams?\n\n1108\n01:00:11,260 --> 01:00:14,260\n教授：这就是我一直在强调的\nPROFESSOR: Well, that's the thing I'm saying.\n\n1109\n01:00:14,260 --> 01:00:15,616\n在这个例子中确实做不到那一点\nThis is an example where you can't.\n\n1110\n01:00:17,510 --> 01:00:18,128\n做不到\nYou can't.\n\n1111\n01:00:18,160 --> 01:00:20,080\n关键在于 这里的输出\nWhat goes, The point is what comes out of here\n\n1112\n01:00:20,240 --> 01:00:21,888\n并不是这两个输入流\nis simply not a function of the stream going in here\n\n1113\n01:00:21,920 --> 01:00:23,600\n的函数\ngoing in here and the stream going in here.\n\n1114\n01:00:24,170 --> 01:00:25,984\n这个函数跟这个输入流有关\nIt's a function of the stream going in here\n\n1115\n01:00:26,192 --> 01:00:27,264\n还跟这个输入流有关\nand the stream going in here\n\n1116\n01:00:27,360 --> 01:00:29,072\n还包括某种有关时间的信息\nand some kind of information about time,\n\n1117\n01:00:29,376 --> 01:00:32,368\n这也正是正则序语言不想让你知道的\nwhich is precisely what a normal-order language won't let you say.\n\n1118\n01:00:34,810 --> 01:00:37,952\n学生：为了让这个系统更加函数式\nAUDIENCE: In order to brings this back into a more functional perspective,\n\n1119\n01:00:38,544 --> 01:00:42,048\n我们能不能把Bill和Dave的交易请求附上时间戳\ncould we just explicitly time stamp all the inputs from Bill and Dave\n\n1120\n01:00:42,544 --> 01:00:46,400\n而使用时间戳作为公平合并的依据？\nand define fair merge to just be the sort on those time stamps?\n\n1121\n01:00:48,416 --> 01:00:49,550\n教授：当然 当然可以\nPROFESSOR: Yeah, you can do that.\n\n1122\n01:00:49,550 --> 01:00:50,600\n你可以那样做\nYou can do that sort of thing.\n\n1123\n01:00:50,600 --> 01:00:52,560\n或者 我们可以这样来想象\nAnother thing you could say is imagine\n\n1124\n01:00:52,768 --> 01:00:54,448\n我们把这个函数看作是\nthat really what this function is,\n\n1125\n01:00:54,784 --> 01:00:56,880\nMERGE每毫秒读一次输入\nis that it does a read every microsecond,\n\n1126\n01:00:58,860 --> 01:00:59,936\n如果没有读到东西\nand then if there's none there,\n\n1127\n01:00:59,936 --> 01:01:00,970\n就认为没有请求\nthat's considered an empty one.\n\n1128\n01:01:00,970 --> 01:01:03,392\n这和你刚刚说的那种方式是等价的\nThat's about equivalent to what you said.\n\n1129\n01:01:03,610 --> 01:01:06,080\n当然可以这样做 但有点旁门左道\nAnd yes, you can do that, but that's a glitch.\n\n1130\n01:01:07,110 --> 01:01:10,144\n我们不只是关心函数的具体实现\nSo it's not quite only implementation we're worried about.\n\n1131\n01:01:10,768 --> 01:01:12,736\n我们关心的是语言的表达力\nWe're worried about expressive power in the language,\n\n1132\n01:01:12,752 --> 01:01:14,672\n我们遇到的困难是\nand what we're running across is a real mismatch\n\n1133\n01:01:14,992 --> 01:01:17,440\n我们不能很容易地表达我们想要表达的东西\nbetween what we can say easily and what we'd like to say.\n\n1134\n01:01:19,880 --> 01:01:22,016\n学生：听起来好像如果两个人同时发出请求\nAUDIENCE: It sounds like where we're getting hung up with that\n\n1135\n01:01:22,064 --> 01:01:26,090\n这个方法就会出问题\none input from both Bill and Dave at the same time.\n\n1136\n01:01:26,120 --> 01:01:28,432\n教授：并不只是这个 只要是你定义的都可能出问题\nPROFESSOR: It's not quite one, but it's anything you define.\n\n1137\n01:01:28,530 --> 01:01:30,576\n你当然可以说Dave经常发起两个请求\nSo you can say Dave can go twice as often,\n\n1138\n01:01:30,720 --> 01:01:32,320\n但是你如果预先定义了什么\nbut if anything you predefine,\n\n1139\n01:01:32,688 --> 01:01:33,872\n这样做也不正确\nit's not the right thing.\n\n1140\n01:01:36,110 --> 01:01:40,704\n你不能确定某些特定函数的输入请求\nYou can't decide at some particular function of their input requests.\n\n1141\n01:01:41,930 --> 01:01:43,376\n但是还有更坏的情况\nWorse yet, I mean, worse yet,\n\n1142\n01:01:44,128 --> 01:01:45,728\n有一些情况甚至MERGE也处理不了\nthere are things that even merge can't do.\n\n1143\n01:01:47,290 --> 01:01:49,696\n比如突然有一天你想要\nOne thing you might want to do that's even more general is suddenly\n\n1144\n01:01:50,240 --> 01:01:52,470\n把另一个人关联在这个银行帐户上\nyou add somebody else to this bank account system.\n\n1145\n01:01:52,470 --> 01:01:54,512\n假如这个人是John\nYou go and you add John to this bank account system.\n\n1146\n01:01:56,030 --> 01:01:58,896\n现在图上就要多一个流\nAnd now there's yet another stream that's going to come into the picture\n\n1147\n01:01:58,912 --> 01:02:00,704\n在一个我们未曾指定的时候\nat some time which we haven't prespecified.\n\n1148\n01:02:02,040 --> 01:02:04,000\n这种情况甚至公平合并也无法给出合理的合并\nSo that's something even fair merge can't do,\n\n1149\n01:02:04,000 --> 01:02:08,256\n还需要有MANAGER一类的东西\nand they're things called-- I forget-- manager or something.\n\n1150\n01:02:08,860 --> 01:02:11,790\n需要一种更一般性的公平合并来解决\nThat's a generalization of fair merge to allow that.\n\n1151\n01:02:11,790 --> 01:02:13,984\n有很多研究都在讨论\nThere's a whole sort of research discipline saying\n\n1152\n01:02:14,000 --> 01:02:16,300\n通过不断引入新机制\nhow far can you push this functional perspective\n\n1153\n01:02:16,592 --> 01:02:18,720\n函数式思维能应用到哪种程度？\nby adding more and more mechanism?\n\n1154\n01:02:19,580 --> 01:02:21,792\n在我们不得不使用赋值之前\nAnd how far does that go before the whole thing breaks down\n\n1155\n01:02:21,824 --> 01:02:23,408\n函数式程序设计能干成什么样？\nand you might as well been using set anyway.\n\n1156\n01:02:25,984 --> 01:02:28,000\n学生：看来自动存款就不行\nAUDIENCE: But not automatic deposit.\n\n1157\n01:02:39,328 --> 01:02:40,496\n教授：好的 下课\nPROFESSOR: OK, thank you.\n\n1158\n01:02:41,328 --> 01:02:51,088\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n1159\n01:02:51,080 --> 01:03:00,080\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec7a.srt",
    "content": "﻿1\n00:00:00,030 --> 00:00:02,688\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:02,752 --> 00:00:05,968\n翻译&&时间轴：邓雄飞、张大伟\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:06,000 --> 00:00:08,752\n特别感谢：裘宗燕教授\n\n4\n00:00:08,848 --> 00:00:11,408\n计算机程序的构造和解释\n\n5\n00:00:11,420 --> 00:00:13,248\n元循环求值器 I\nMetacircular Evaluator\n\n6\n00:00:15,792 --> 00:00:17,328\n教授：今天我们将学习一些\nPROFESSOR: Well today we're going to learn about something\n\n7\n00:00:17,520 --> 00:00:18,410\n非同一般的东西\nquite amazing.\n\n8\n00:00:19,200 --> 00:00:21,888\n我们将对计算机程序\nWe're going to understand what we mean by a program\n\n9\n00:00:22,592 --> 00:00:25,216\n有更深层次的理解\na little bit more profoundly than we have up till now.\n\n10\n00:00:26,800 --> 00:00:29,120\n目前为止 我们一直把程序看作\nUp till now, we've been thinking\n\n11\n00:00:29,264 --> 00:00:32,096\n对机器的描述\nprograms as describing machines.\n\n12\n00:00:32,720 --> 00:00:37,216\n举个例子 在这个幻灯片上\nSo for example, looking at this still store\n\n13\n00:00:37,936 --> 00:00:41,776\n我们可以看到一个计算阶乘的程序\nwe see here is a program for factorial.\n\n14\n00:00:42,800 --> 00:00:47,312\n当然 你可以认为这些字符串描述了\nAnd what it is, is a character string description, if you will,\n\n15\n00:00:47,664 --> 00:00:51,984\n这个线路图所表示的无穷机器\nof the wiring diagram of a potentially infinite machine.\n\n16\n00:00:52,496 --> 00:00:54,800\n我们可以稍稍地看下 它描述的是什么\nAnd we can look at that a little bit and just see the idea.\n\n17\n00:00:55,130 --> 00:00:58,208\n这种紧凑的记法 描述的是：\nThat this is a sort of compact notation which says,\n\n18\n00:00:58,544 --> 00:01:00,170\n如果N是0 结果就是1\nif n is 0, the result is one.\n\n19\n00:01:00,170 --> 00:01:02,000\nN是从这里进入机器的\nWell here comes n coming into this machine,\n\n20\n00:01:02,336 --> 00:01:03,520\n如果它是0的话\nand if it's 0,\n\n21\n00:01:03,744 --> 00:01:05,200\n那么我就控制这个开关\nthen I control this switch\n\n22\n00:01:05,472 --> 00:01:08,208\n把它掰到输出为1的那一端\nin such a way that the switch allows the output to be one.\n\n23\n00:01:09,340 --> 00:01:10,080\n否则的话\nOtherwise,\n\n24\n00:01:10,384 --> 00:01:12,832\n就是(* N (FACT (- N 1)))\nit's n times factorial of n minus one.\n\n25\n00:01:12,970 --> 00:01:15,136\n我先计算(FACT (- N 1))\nWell, I'm computing factorial of n minus one\n\n26\n00:01:15,290 --> 00:01:16,688\n再把结果乘以N\nand multiplying that by n,\n\n27\n00:01:16,848 --> 00:01:18,912\n这样如果N不为0的话\nin the case that it's not 0,\n\n28\n00:01:18,912 --> 00:01:20,608\n这个开关就会输出这里的结果\nthis switch makes the output come from there.\n\n29\n00:01:21,900 --> 00:01:22,320\n当然了\nOf course,\n\n30\n00:01:22,368 --> 00:01:25,130\n这个机器可能有无穷多个部件\nthis is a machine with a potentially infinite number of parts,\n\n31\n00:01:25,488 --> 00:01:28,128\n因为FACT内部又调用了FACT\nbecause factorial occurs within factorial,\n\n32\n00:01:28,432 --> 00:01:30,176\n因此我们不知道调用栈有多深\nso we don't know how deep it has to be.\n\n33\n00:01:31,070 --> 00:01:33,552\n但到目前为止\nBut that's basically what our notation\n\n34\n00:01:34,224 --> 00:01:37,696\n代码对我们来说就是这样的东西了\nfor programs really means to us at this point.\n\n35\n00:01:38,310 --> 00:01:40,592\n你可以认为代码是用字符串来描述\nIt's a character string description, if you will,\n\n36\n00:01:41,280 --> 00:01:44,160\n某种用其它方式描画的线路图\nof a wiring diagram that could also be drawn some other way.\n\n37\n00:01:44,900 --> 00:01:46,608\n事实上 很多人都向我提议\nAnd, in fact, many people have proposed to me,\n\n38\n00:01:46,848 --> 00:01:49,040\n说程序设计语言应该像这个一样 是图像化的\nprogramming languages look graphical like this.\n\n39\n00:01:49,490 --> 00:01:51,808\n不过我不认为用图形表示会有很多优势\nI'm not sure I believe there are many advantages.\n\n40\n00:01:52,000 --> 00:01:53,792\n当然 最主要的劣势就是\nThe major disadvantage, of course,\n\n41\n00:01:53,808 --> 00:01:55,632\n它需要占用很大的平面空间\nis that it takes up more space on a page,\n\n42\n00:01:55,968 --> 00:01:59,952\n所以展示和修改起来就非常麻烦\nand, therefore, it's harder to pack into a listing or to edit very well.\n\n43\n00:02:01,344 --> 00:02:02,160\n但是不管怎样\nBut in any case,\n\n44\n00:02:03,580 --> 00:02:05,152\n在计算的世界中\nthere's something very remarkable\n\n45\n00:02:05,184 --> 00:02:07,050\n还有一个非常重要的东西\nthat can happen in the computation world\n\n46\n00:02:07,648 --> 00:02:10,640\n也就是所谓的“通用机器”\nwhich is that you can have something called a universal machine.\n\n47\n00:02:10,730 --> 00:02:15,248\n我们再来看第二张幻灯片\nIf we look at the second slide,\n\n48\n00:02:16,048 --> 00:02:17,184\n我们看到的就是\nwhat we see is\n\n49\n00:02:18,144 --> 00:02:19,888\n名为EVAL的特殊机器\na special machine called eval.\n\n50\n00:02:21,260 --> 00:02:22,864\n这个叫做EVAL的机器\nThere is a machine called eval,\n\n51\n00:02:22,880 --> 00:02:24,240\n也就是我今天要讲解的\nand I'm going to show it to you today.\n\n52\n00:02:25,824 --> 00:02:26,672\n它非常简单\nIt's very simple.\n\n53\n00:02:27,780 --> 00:02:30,800\n最了不起的是 它简单得可以写在黑板上\nWhat is remarkable is that it will fit on the blackboard.\n\n54\n00:02:33,350 --> 00:02:35,792\n然而 EVAL这个机器\nHowever, eval is a machine\n\n55\n00:02:36,000 --> 00:02:39,840\n是以其它机器的描述作为输入的\nwhich takes as input a description of another machine.\n\n56\n00:02:40,450 --> 00:02:42,128\n它可以接收一个\nIt could take the wiring diagram\n\n57\n00:02:42,400 --> 00:02:45,584\n阶乘机器的线路图作为输入\nof a factorial machine as input.\n\n58\n00:02:46,490 --> 00:02:47,664\n这样一来\nHaving done so,\n\n59\n00:02:48,496 --> 00:02:52,570\n它就可以模拟那台阶乘机器\nit becomes a simulator for the factorial machine\n\n60\n00:02:53,136 --> 00:02:53,792\n这样的话\nsuch that,\n\n61\n00:02:54,160 --> 00:02:56,368\n如果输入6 就会得到720\nif you put a six in, out comes a 720.\n\n62\n00:02:58,910 --> 00:03:01,680\n这是一个非常了不起的机器\nThat's a very remarkable sort of machine.\n\n63\n00:03:02,130 --> 00:03:03,584\n而最让人惊奇的是\nAnd the most amazing part of it\n\n64\n00:03:03,776 --> 00:03:05,136\n它竟然可以写在一个黑板内\nit is that it fits on a blackboard.\n\n65\n00:03:05,590 --> 00:03:06,656\n与之相反的是\nBy contrast,\n\n66\n00:03:07,320 --> 00:03:10,448\n我们可以想象一下模拟电子世界中的\none could imagine in the analog electronics world\n\n67\n00:03:11,552 --> 00:03:12,864\n一台非常不同的机器\na very different machine.\n\n68\n00:03:14,576 --> 00:03:16,336\n这台机器呢\na machine where, a machine\n\n69\n00:03:16,528 --> 00:03:18,816\n某种意义上 同样也是“通用机器”\nwhich also was, in some sense, universal,\n\n70\n00:03:19,260 --> 00:03:23,120\n只要你输入一个电路图\nwhere you gave a circuit diagram as one of the inputs,\n\n71\n00:03:23,824 --> 00:03:25,744\n比如这个小型的低通滤波器\nfor example, of this little low-pass filter,\n\n72\n00:03:26,016 --> 00:03:27,488\n单极低通滤波器之类的\none-pole low-pass filter.\n\n73\n00:03:28,050 --> 00:03:29,536\n你可以想像\nAnd you can imagine that\n\n74\n00:03:29,710 --> 00:03:33,152\n如果我们扫描这个元件得到扫描线\nyou could, for example, scan this out-- the scan lines\n\n75\n00:03:34,432 --> 00:03:37,130\n得到的信号描述的就是\nRight? are the signal that's describing\n\n76\n00:03:37,392 --> 00:03:40,400\n这个机器所模拟的\nwhat this machine is to simulate--\n\n77\n00:03:40,784 --> 00:03:43,392\n这个模拟机器EVAL是由电路构成\nthen the analog of eval which is made out of electrical circuits,\n\n78\n00:03:43,680 --> 00:03:45,152\n它可以把自己配置成一个滤波器\nwhich configure itself into a filter\n\n79\n00:03:45,184 --> 00:03:48,040\n响应由电路图指定的频率\nhas the frequency response specified by the circuit diagram.\n\n80\n00:03:49,890 --> 00:03:51,488\n这种机器很难制造出来\nThat's a very hard machine to make,\n\n81\n00:03:51,616 --> 00:03:54,064\n当然 更不可能用一个黑板就把它说清楚\nand, surely, there's no chance that I could put it on a blackboard.\n\n82\n00:03:55,670 --> 00:03:57,584\n所以今天我们将学习一些神奇的东西\nSo we're going to see an amazing thing today.\n\n83\n00:03:58,430 --> 00:04:00,816\n我们将在黑板上见证\nWe're going to see, on the blackboard,\n\n84\n00:04:01,168 --> 00:04:02,496\n通用机器\nthe universal machine.\n\n85\n00:04:02,790 --> 00:04:04,416\n跟其它程序比起来\nAnd we'll see that among other things,\n\n86\n00:04:04,528 --> 00:04:05,808\n它真是非常简单\nit's extremely simple.\n\n87\n00:04:06,780 --> 00:04:08,752\n现在 我们已经非常接近\nNow, we're getting very close\n\n88\n00:04:09,088 --> 00:04:10,976\n计算机中真正的精灵了\nthe real spirit in the computer at this point.\n\n89\n00:04:11,280 --> 00:04:14,624\n所以为了保持足够的尊重\nSo I have to show a certain amount of reverence and respect,\n\n90\n00:04:15,184 --> 00:04:17,328\n我特地穿上外套\nso I'm going to wear a suit jacket for the only time\n\n91\n00:04:17,520 --> 00:04:19,296\n你们应该从没见我穿过\nthat you'll ever see me wear a suit jacket here.\n\n92\n00:04:20,470 --> 00:04:22,736\n在这个盛重的场合\nAnd I think I'm also going to\n\n93\n00:04:23,552 --> 00:04:26,704\n我还得戴上一顶合适的帽子\nput on an appropriate hat for the occasion.\n\n94\n00:04:28,780 --> 00:04:31,440\n开讲前再给大家提个醒\nNow, this is a lecturer which I have to warn you--\n\n95\n00:04:34,140 --> 00:04:36,912\n那些40岁以下\nlet's see, normally, people under 40\n\n96\n00:04:37,168 --> 00:04:38,490\n以及没有孩子的人\nand who don't have several children\n\n97\n00:04:38,672 --> 00:04:40,496\n你们可要小心了\nare advised to be careful.\n\n98\n00:04:40,490 --> 00:04:41,968\n如果真的受不了 可以选择离开\nIf they're really worried, they should leave.\n\n99\n00:04:43,340 --> 00:04:45,568\n因为一会儿要发生一些\nBecause there's a certain amount of\n\n100\n00:04:45,728 --> 00:04:47,130\n非常神秘的事情\nmysticism that will appear here\n\n101\n00:04:47,744 --> 00:04:51,056\n可能使你的大脑异常混乱\nwhich may be disturbing and cause trouble in your minds.\n\n102\n00:04:51,820 --> 00:04:54,288\n好了 无论如何\nWell in any case, let's see,\n\n103\n00:04:55,712 --> 00:05:01,104\n我要带着你们写一个Lisp求值器\nI wish to write for you the evaluator for Lisp.\n\n104\n00:05:02,510 --> 00:05:04,288\n求值器并不复杂\nNow the evaluator isn't very complicated.\n\n105\n00:05:05,020 --> 00:05:07,632\n很像我们以前见到过的程序\nIt's very much like all the programs we've seen already.\n\n106\n00:05:08,240 --> 00:05:09,488\n这也是它令人吃惊的地方\nThat's the amazing part of it.\n\n107\n00:05:10,860 --> 00:05:13,104\n现在我开始写这个程序\nIt's going to be-- and I'm going to write it right here--\n\n108\n00:05:15,280 --> 00:05:16,620\n我把这个程序叫做EVAL\nit's a program called eval.\n\n109\n00:05:22,900 --> 00:05:26,240\n这个过程接收两个参数\nAnd it's a procedure of two arguments\n\n110\n00:05:26,280 --> 00:05:29,440\n表达式EXP和环境ENV\nexpression and an environment.\n\n111\n00:05:31,860 --> 00:05:33,792\n跟所有实用过程一样\nAnd like every interesting procedure,\n\n112\n00:05:34,016 --> 00:05:35,136\n它是个“按情况分析”语句\nit's a case analysis.\n\n113\n00:05:40,460 --> 00:05:41,872\n但是在我开始之前\nBut before I start on this,\n\n114\n00:05:42,528 --> 00:05:43,904\n我还想你们注意一下\nI want to tell you some things.\n\n115\n00:05:44,448 --> 00:05:46,064\n我将要在黑板上写的程序\nThe program we're going to write on the blackboard\n\n116\n00:05:46,560 --> 00:05:50,240\n非常丑陋、混乱、令人作呕\nis ugly, dirty, disgusting,\n\n117\n00:05:50,944 --> 00:05:53,168\n并不是一种专业的写法\nnot the way I would write this is a professional.\n\n118\n00:05:54,320 --> 00:05:56,576\n它是用具体语法写就的\nIt is written with concrete syntax,\n\n119\n00:05:57,248 --> 00:05:58,832\n也就是说用了很多CAR、CDR\nmeaning you've got really to use lots of CARs and CDRs\n\n120\n00:05:58,848 --> 00:06:00,624\n我之前告诉过你们这样写并不好\nwhich is exactly what I told you not to do.\n\n121\n00:06:02,944 --> 00:06:05,616\n在这里是故意这样来写的\nThat's on purpose in this case,\n\n122\n00:06:06,110 --> 00:06:09,024\n因为我想让它尽量精简\nbecause I want it to be small, compact,\n\n123\n00:06:09,344 --> 00:06:10,400\n能塞在黑板内\nfit on the blackboard\n\n124\n00:06:10,432 --> 00:06:11,856\n你们就可以看到整个代码\nso you can get the whole thing.\n\n125\n00:06:12,420 --> 00:06:14,800\n我就不像平时那样实用长变量名了\nSo I don't want to use long names like I normally use.\n\n126\n00:06:15,600 --> 00:06:17,296\n就用CAR、CDR 因为它们短小\nI want to use CAR-CDR because it's short.\n\n127\n00:06:18,060 --> 00:06:20,784\n这算是一种取舍\nOkay, I wanna, it's a whole, that's a trade-off.\n\n128\n00:06:20,896 --> 00:06:22,816\n我不希望你们这样来写程序\nI don't want you writing programs like this.\n\n129\n00:06:23,570 --> 00:06:25,088\n这里单纯地想达到一种简洁的效果\nThis is purely for an effect.\n\n130\n00:06:25,850 --> 00:06:27,616\n因此你们读起来可能有些费力\nNow, you're going to have to work a little harder to read it,\n\n131\n00:06:27,776 --> 00:06:30,192\n我尽量写得清楚一些\nbut I'm going to try to make it clear as I'm writing it.\n\n132\n00:06:31,270 --> 00:06:34,400\n这个解释器已经比较完整了\nI'm also-- this is a pretty much complete interpreter,\n\n133\n00:06:34,512 --> 00:06:36,240\n但是还是缺少一些功能\nbut there's going to be room for putting in more things--\n\n134\n00:06:36,256 --> 00:06:38,608\n我就不写定义和赋值的部分了\nI'm going to leave out definition and assignment,\n\n135\n00:06:39,104 --> 00:06:42,416\n因为它们都不是最本质的\njust because they are not essential,\n\n136\n00:06:42,880 --> 00:06:46,464\n稍后我就会解释 这是数学上的原因\nand a, for a mathematical reason I'll show you later\n\n137\n00:06:46,928 --> 00:06:49,968\n当然啦 黑板也没有那么大\nand also they take up more space.\n\n138\n00:06:51,888 --> 00:06:53,648\n但是 我们怎么做呢？\nBut, in any case, what do we have to do?\n\n139\n00:06:53,952 --> 00:06:55,664\n我们需要一个分派\nWe have to do a dispatch\n\n140\n00:06:56,096 --> 00:06:57,904\n它根据表达式的类型\nwhich breaks the types of expressions up\n\n141\n00:06:58,288 --> 00:07:00,384\n把它们划分为几类\ninto particular classes.\n\n142\n00:07:01,728 --> 00:07:03,264\n这就是现在要做的\nOkay? So that's what we're going to have here.\n\n143\n00:07:03,824 --> 00:07:05,150\n我们都有哪些表达式？\nWell, what expressions are there?\n\n144\n00:07:05,150 --> 00:07:06,368\n我们先来看几种表达式\nLet's look at the kinds of expressions.\n\n145\n00:07:06,810 --> 00:07:09,600\n比如说 数字“3”就是一个表达式\nWe can have things like the numeral three.\n\n146\n00:07:10,420 --> 00:07:11,584\n我想让它代表什么呢？\nWhat do I want that to do?\n\n147\n00:07:12,720 --> 00:07:14,752\n我有很多选择 但是就现在而言\nI can make choices, but I think right now,\n\n148\n00:07:15,056 --> 00:07:16,208\n我就想让它表示数字3\nI want it to be a three.\n\n149\n00:07:17,050 --> 00:07:17,888\n这就是我要的\nThat's what I want.\n\n150\n00:07:18,720 --> 00:07:19,696\n这个足够简单\nSo that's easy enough.\n\n151\n00:07:20,032 --> 00:07:22,912\n那就意味着 如果表达式是数字\nThat means I want, if the thing is a number,\n\n152\n00:07:27,290 --> 00:07:31,680\n表达式本身就应该是求值结果\nthat I want the expression itself as the answer.\n\n153\n00:07:35,420 --> 00:07:36,768\n另外一种情况是\nNow the next possibility\n\n154\n00:07:36,896 --> 00:07:38,864\n表达式还可能是符号\nis things that we represent as symbols.\n\n155\n00:07:39,390 --> 00:07:46,752\n比如EXP、ENV、EVAL、NUMBER、X之类\nExamples of symbols are things like x, n, eval, number, x.\n\n156\n00:07:48,016 --> 00:07:49,184\n它们意味着什么？\nWhat do I mean them to be?\n\n157\n00:07:50,160 --> 00:07:51,632\n它们是一类代表其它事物的事物\nThose are things that stand for other things.\n\n158\n00:07:51,632 --> 00:07:53,232\n也就是我们语言中所谓的变量\nThose are the variables of our language.\n\n159\n00:07:54,770 --> 00:07:56,880\n因此我想要能够 比如说\nAnd so I want to be able to say, for example,\n\n160\n00:07:57,056 --> 00:08:01,040\n对X求值 可能会得到3\nthat x, for example, transforms to it's value which might be three.\n\n161\n00:08:02,640 --> 00:08:05,760\n又可能是CAR\nOr I might ask something like car.\n\n162\n00:08:07,760 --> 00:08:09,408\n我希望它的值是\nI want to have as its value--\n\n163\n00:08:09,632 --> 00:08:11,344\n某种类似于过程的东西\nbe something like some procedure,\n\n164\n00:08:16,512 --> 00:08:18,432\n我不需要知道它内部是什么\nwhich I don't know what is inside there,\n\n165\n00:08:18,640 --> 00:08:21,152\n可能是一些机器码 或者类似的东西\nperhaps a machine language code or something like that.\n\n166\n00:08:22,848 --> 00:08:24,272\n到这是还是相对简单的\nOk? So, well, that's easy enough.\n\n167\n00:08:24,430 --> 00:08:26,896\n我想把这部分交给其他人来写\nI'm going to push that off on someone else.\n\n168\n00:08:27,808 --> 00:08:28,896\n如果我们有一个符号\nIf something is a symbol,\n\n169\n00:08:30,800 --> 00:08:32,480\n假如表达式是符号\nif the expression is a symbol,\n\n170\n00:08:33,424 --> 00:08:34,880\n那么我求值它的结果就应该是\nthen I want the answer to be the result,\n\n171\n00:08:34,912 --> 00:08:40,240\n在环境ENV中查找该表达式的值\nlooking up the expression in the environment.\n\n172\n00:08:46,480 --> 00:08:48,992\n环境是一个字典\nNow the environment is a dictionary\n\n173\n00:08:49,968 --> 00:08:54,060\n它把符号映射成一个值\nwhich maps the symbol names to their values.\n\n174\n00:08:54,288 --> 00:08:55,168\n就这么简单\nAnd that's all it is.\n\n175\n00:08:56,280 --> 00:08:57,200\n怎么完成的呢？\nHow it's done?\n\n176\n00:08:57,530 --> 00:08:58,528\n稍后我们再谈这个\nWell, we'll see that later.\n\n177\n00:08:59,680 --> 00:09:00,576\n其实并不难\nIt's very easy.\n\n178\n00:09:01,670 --> 00:09:04,288\n编写类似于表的数据结构非常容易\nIt's easy to make data structures that are tables of various sorts.\n\n179\n00:09:04,840 --> 00:09:05,744\n但它只是一个表\nBut it's only a table,\n\n180\n00:09:05,776 --> 00:09:07,560\n而这是存取某个表的过程\nand this is the access routine for some table.\n\n181\n00:09:09,550 --> 00:09:10,816\n好的 接下来\nOk? Well, the next thing,\n\n182\n00:09:11,312 --> 00:09:12,560\n另一类表达式\nanother kind of expression--\n\n183\n00:09:12,672 --> 00:09:15,568\n表达式可能是一些不是数字的常量\nyou have things that are described constants that are not numbers,\n\n184\n00:09:16,064 --> 00:09:17,430\n比如 'FOO\nlike 'foo.\n\n185\n00:09:20,170 --> 00:09:21,296\n为了方便起见\nWell, for my convenience,\n\n186\n00:09:21,312 --> 00:09:23,360\n我想在语法上\nI want to syntactically transform that\n\n187\n00:09:24,736 --> 00:09:26,800\n把它转换成表结构\ninto a list structure which is,\n\n188\n00:09:26,848 --> 00:09:31,520\n比如说是(QUOTE FOO)\nwhich is, quote foo.\n\n189\n00:09:33,728 --> 00:09:37,180\n一个被引用起来的对象 无论它是什么\nOr it's -- A quoted object, whatever it is,\n\n190\n00:09:38,352 --> 00:09:40,832\n都实际上是一个缩写\nis going to be actually an abbreviation,\n\n191\n00:09:41,040 --> 00:09:42,592\n这一部分并不由求值器负责\nwhich is not part of the evaluator\n\n192\n00:09:43,216 --> 00:09:44,464\n这是在其它地方完成的\nbut happens somewhere else,\n\n193\n00:09:44,752 --> 00:09:47,792\n左边的符号就是右边表达式的缩略形式\nan abbreviation for an expression that looks like this.\n\n194\n00:09:48,780 --> 00:09:50,480\n这样 我就可以\nThis way, I can test for\n\n195\n00:09:50,576 --> 00:09:53,120\n依据表达式的CAR部分\nthe type of the expression as being a quotation\n\n196\n00:09:53,312 --> 00:09:55,952\n来判断它的类型了\nby examining the car of the expression.\n\n197\n00:09:58,460 --> 00:10:01,088\n因此这一部分也不会出现在求值器中\nSo I'm not going to worry about that in the evaluator.\n\n198\n00:10:01,650 --> 00:10:02,688\n这在更早时候\nIt's happening somewhere earlier\n\n199\n00:10:02,700 --> 00:10:03,968\n比如源代码读取阶段完成\nin the reader or something.\n\n200\n00:10:05,540 --> 00:10:15,040\n如果是引用表达式\nIf the expression of the expression is quote,\n\n201\n00:10:18,272 --> 00:10:19,104\n那么求值的结果就是\nthen what I want,\n\n202\n00:10:19,630 --> 00:10:25,136\n我想让(QUOTE FOO)求值为自身FOO\nI want quote foo to itself evaluate to foo.\n\n203\n00:10:25,140 --> 00:10:25,952\n一个常量\nIt's a constant.\n\n204\n00:10:27,530 --> 00:10:28,928\n这条代码是说\nThis is just a way of saying\n\n205\n00:10:29,088 --> 00:10:30,736\n这类表达式求值为它自己\nthat this evaluates to itself.\n\n206\n00:10:31,792 --> 00:10:33,660\n怎么才能把它取出来呢？\nOk? So thats the. What is that?\n\n207\n00:10:33,660 --> 00:10:36,368\n这是列表第二个元素的第一个部分\nThat's the first of the second of the list.\n\n208\n00:10:36,592 --> 00:10:37,584\n也就是表的第二个元素\nThat's the second of the list.\n\n209\n00:10:38,496 --> 00:10:40,320\n也就是CADR\nThe second element of the list is it's CADR.\n\n210\n00:10:41,280 --> 00:10:42,384\n所以这里我就写CADR\nSo I'm just going to write here, CADR.\n\n211\n00:10:51,088 --> 00:10:52,352\n表达式还可能是什么类型呢？\nOK? What else do we have here?\n\n212\n00:10:52,510 --> 00:10:53,808\n还有LAMBDA表达式\nWe have lambda expressions,\n\n213\n00:10:55,008 --> 00:11:03,296\n比如 (LAMBDA (X) (+ X Y))\nfor example, lambda of x plus x y.\n\n214\n00:11:04,160 --> 00:11:06,336\n我还得找到某种表示方法\nWell, I going have to have some representation for the procedure\n\n215\n00:11:06,336 --> 00:11:07,856\nLAMBDA表达式求值的结果\nwhich is the value of an expression,\n\n216\n00:11:08,112 --> 00:11:09,088\n也就是如何表示过程\nof a lambda expression.\n\n217\n00:11:09,600 --> 00:11:12,624\n过程并不就是表达式(LAMBDA (x))\nThe procedure here is not the expression lambda x.\n\n218\n00:11:13,136 --> 00:11:15,568\n表达式只是过程的代码描述\nThat's the description of it, the textual description.\n\n219\n00:11:16,416 --> 00:11:18,330\n如果在词法作用域的语言中实现过程\nHowever, what what I going to expect to see here\n\n220\n00:11:18,560 --> 00:11:21,200\n那么我希望在表示过程的时候\nis something which contains an environment as one of its parts\n\n221\n00:11:23,232 --> 00:11:25,360\n能够把当前的求值环境包括进来\nif I'm implementing a lexical language.\n\n222\n00:11:25,840 --> 00:11:29,072\n所以这里我还需要\nAnd so what I'd like to see\n\n223\n00:11:29,200 --> 00:11:30,672\n一些类型标志\nis some type flags.\n\n224\n00:11:30,704 --> 00:11:33,904\n这样后面我就可以用它们来区分过程\nI'm going to have to be able to distinguish procedures later,\n\n225\n00:11:34,304 --> 00:11:36,592\n看哪些是由LAMBDA表达式生成的\nprocedures which were produced by lambdas,\n\n226\n00:11:36,816 --> 00:11:38,032\n哪些是基本过程\nfrom ones that may be primitive.\n\n227\n00:11:39,060 --> 00:11:41,968\n所以这里是个类型标志\nAnd so I'm going to have some flag,\n\n228\n00:11:41,984 --> 00:11:43,568\n出于历史原因\nwhich I'll just arbitrarily call closure,\n\n229\n00:11:43,568 --> 00:11:45,104\n我用CLOSURE作为类型标志\njust for historical reasons.\n\n230\n00:11:47,680 --> 00:11:49,600\n现在来看看 哪部分比较重要\nNow, to say what parts of this are important.\n\n231\n00:11:49,920 --> 00:11:51,120\n我需要知道\nI'm going to need to know\n\n232\n00:11:51,248 --> 00:11:52,928\n绑定变量表和过程的体\nthe bound variable list and the body.\n\n233\n00:11:54,220 --> 00:11:55,408\n这是它的CDR部分\nWell, that's the CDR of this,\n\n234\n00:11:56,096 --> 00:12:01,856\n这里就是((X) (+ X Y))\nso it's going to be x and plus x y and some environment.\n\n235\n00:12:03,040 --> 00:12:03,872\n以及某个环境<ENV>\nand some environment.\n\n236\n00:12:08,170 --> 00:12:12,208\n用户不应该看到这个东西\nNow this is not something that users should ever see,\n\n237\n00:12:13,536 --> 00:12:16,192\n这只是过程对象的\nthis is purely a representation, internally,\n\n238\n00:12:16,768 --> 00:12:18,304\n一种内部表示\nfor a procedure object.\n\n239\n00:12:18,520 --> 00:12:20,528\n它包括绑定变量表\nIt contains a bound variable list,\n\n240\n00:12:20,704 --> 00:12:22,624\n过程的体和某个环境\na body, and an environment,\n\n241\n00:12:23,536 --> 00:12:25,808\n以及一个类型标签 表示这是一个过程\nand some type tag saying, I am a procedure.\n\n242\n00:12:26,340 --> 00:12:27,376\n接下来写代码\nI'm going to make one now.\n\n243\n00:12:28,080 --> 00:12:38,720\n如果表达式的CAR部分是'LAMBDA\nSo if the CAR of the expression is quote lambda,\n\n244\n00:12:43,472 --> 00:12:44,816\n这里 我就要\nthen what I'm going to put here\n\n245\n00:12:45,648 --> 00:12:51,840\n创建一个表 表头是'CLOSURE\nis-- I'm going to make a list of closure,\n\n246\n00:12:55,150 --> 00:13:00,736\n接着是 过程代码的CDR部分\nthe CDR of the procedure description\n\n247\n00:13:01,568 --> 00:13:02,976\n也就是除开LAMBDA的其它部分\nwas everything except the lambda,\n\n248\n00:13:07,744 --> 00:13:08,864\n以及当前的环境\nand the current environment.\n\n249\n00:13:10,250 --> 00:13:15,328\n这样就实现了环境模型中的那些规则\nThis implements the rule for environments in the environment model.\n\n250\n00:13:15,456 --> 00:13:18,528\n这是从LAMBDA表达式中构建过程所必须遵守的\nIt has to do with construction of procedures from lambda expressions.\n\n251\n00:13:19,408 --> 00:13:20,976\n那个求值器在遇到\nThe environment that was around\n\n252\n00:13:21,488 --> 00:13:24,320\nLAMBDA表达式时的环境\nat the time the evaluator encountered the lambda expression\n\n253\n00:13:25,040 --> 00:13:28,464\n在过程运行的时候\nis the environment where the lambda expression gets\n\n254\n00:13:28,688 --> 00:13:31,776\n会去这个环境中查找自由变量的值\nwhere the procedure resulting interprets it's free variables.\n\n255\n00:13:34,720 --> 00:13:35,824\n所以需要把它囊括进来\nSo that's part of that.\n\n256\n00:13:35,920 --> 00:13:37,552\n因此我们必须把求值时的环境\nAnd so we have to capture that environment\n\n257\n00:13:37,568 --> 00:13:38,860\n作为过程对象的一部分\nas part of the procedure object.\n\n258\n00:13:39,210 --> 00:13:40,624\n之后再来看它的作用\nAnd we'll see how that gets used later.\n\n259\n00:13:42,032 --> 00:13:43,776\n我们也有COND表达式\nThere are also conditional expressions\n\n260\n00:13:44,592 --> 00:13:52,816\n像是(COND (P1 E1) (P2 E2) ...)这样的\nof things like COND of say, p one, e one, p two, e two.\n\n261\n00:13:54,400 --> 00:13:56,096\nP1是谓词\nWhere this is a predicate,\n\n262\n00:13:56,352 --> 00:13:58,432\n谓词总是返回TRUE或者FALSE\na predicate is a thing that is either true or false,\n\n263\n00:13:58,992 --> 00:14:01,760\n如果谓词P1为真时 表达式E1才被求值\nand the expression to be evaluated if the predicate is true.\n\n264\n00:14:03,440 --> 00:14:06,080\n当然 你也可以列这么一组子句\nA set of clauses, if you will, that's the name for such a thing.\n\n265\n00:14:06,790 --> 00:14:09,360\n我会把它封装在另一个过程中\nSo I'm going put that somewhere else.\n\n266\n00:14:09,360 --> 00:14:11,568\n我们稍后在那个过程中进行处理\nWe're going to worry about that in another piece of code.\n\n267\n00:14:12,420 --> 00:14:21,280\n如果表达式的CAR部分是'COND的话\nSo EQ--  if the CAR of the expression is COND,\n\n268\n00:14:24,000 --> 00:14:26,848\n那么我就用EVCOND来求值这个表达式\nthen I'm going to do nothing more than evaluate the COND,\n\n269\n00:14:30,208 --> 00:14:31,424\n求值表达式的CDR部分\nthe CDR of the expression.\n\n270\n00:14:34,400 --> 00:14:38,496\n记得带上环境\nThat's all the clauses in the environment that I'm given.\n\n271\n00:14:41,430 --> 00:14:42,608\n好的 还有一种情况\nWell, there's one more case,\n\n272\n00:14:44,096 --> 00:14:48,224\n任意的像(+ X 3)这样的表达式\narbitrary thing like the sum of x and three,\n\n273\n00:14:50,624 --> 00:14:53,952\n这是把运算符应用在运算对象上\nwhere this is an operator applied to operands,\n\n274\n00:14:55,136 --> 00:14:56,590\n这并没有什么特殊的\nand there's nothing special about it.\n\n275\n00:14:56,590 --> 00:14:59,632\n就是说 它不属于这里的特殊形式\nIt's not one of the special cases, the special forms.\n\n276\n00:14:59,850 --> 00:15:01,424\n上面写的这些都是特殊形式\nThese are the special forms.\n\n277\n00:15:09,650 --> 00:15:12,128\n再说明一下 如果我要把这个程序写得专业一点\nAnd if I were writing here a professional program, again,\n\n278\n00:15:12,368 --> 00:15:14,176\n我会把它设计成数据导向的\nI would somehow make this data directed.\n\n279\n00:15:14,480 --> 00:15:16,528\n那样的话 这里就不会是一系列的条件判断\nSo there wouldn't be a sequence of conditionals here,\n\n280\n00:15:16,656 --> 00:15:18,208\n而是根据一些比特位来做分派\nthere'd be a dispatch on some bits\n\n281\n00:15:19,424 --> 00:15:22,256\n这样来设计会更加专业一些\nif I were trying to do this in a more professional way.\n\n282\n00:15:22,360 --> 00:15:24,144\n并且 我不用大量修改程序\nSo that, in fact, I can add to the thing\n\n283\n00:15:24,688 --> 00:15:26,384\n就可以添加规则\nwithout changing my program much.\n\n284\n00:15:26,710 --> 00:15:28,464\n这样来做可能运行得更快\nSo, for example, they would run fast,\n\n285\n00:15:29,040 --> 00:15:30,432\n但这里我并不打算这么做\nbut I'm not worried about that.\n\n286\n00:15:31,280 --> 00:15:33,984\n现在的目的是把握EVAL过程的整体\nHere we're trying to look at this in its entirety.\n\n287\n00:15:35,072 --> 00:15:35,808\n那么 最后一种情况\nSo it's else.\n\n288\n00:15:37,696 --> 00:15:38,560\n要怎么做呢？\nWell, what do we do?\n\n289\n00:15:38,560 --> 00:15:41,232\n在这种情况下 我需要进行加法运算\nIn this case, I have to somehow do an addition.\n\n290\n00:15:44,350 --> 00:15:46,160\n那么我就得搞清楚 '+到底是什么\nWell, I could find out what the plus is.\n\n291\n00:15:46,848 --> 00:15:49,296\n我还得知道X和3又代表什么\nI have to find out what the x and the three are.\n\n292\n00:15:50,550 --> 00:15:53,968\n然后再把'+的所代表的东西\nAnd then I have to apply the result of finding what the plus is\n\n293\n00:15:54,432 --> 00:15:57,008\n应用于'X与3所代表的东西上\nto the result of finding out what the x and the three are.\n\n294\n00:15:58,112 --> 00:15:59,392\n具体来写一下\nWe'll have a name for that.\n\n295\n00:15:59,872 --> 00:16:09,550\n我要把表达式CAR部分的求值结果\nSo I'm going to apply the result of evaluating the CAR\n\n296\n00:16:11,200 --> 00:16:12,140\n应用在\nof the expression--\n\n297\n00:16:13,216 --> 00:16:15,504\n表达式的CAR部分就是运算符\nthe car of the expression is the operator--\n\n298\n00:16:17,200 --> 00:16:18,512\n要在给定的环境中进行\nin the environment given.\n\n299\n00:16:20,512 --> 00:16:22,896\n对运算符求值会得到一个过程\nSo evaluating the operator gets me the procedure.\n\n300\n00:16:24,050 --> 00:16:26,784\n现在 我要求值所有运算对象来取得参数\nNow I have to evaluate all the operands to get the arguments.\n\n301\n00:16:27,290 --> 00:16:28,224\n我将调用EVLIST\nI'll call that EVLIST,\n\n302\n00:16:31,264 --> 00:16:35,536\n来求值表达式的CDR部分 也就是运算对象\nthe CDR of the operands, of the expression,\n\n303\n00:16:36,768 --> 00:16:39,008\n当然是在相应的环境中\nwith respect to the environment.\n\n304\n00:16:41,940 --> 00:16:43,136\n我们待会儿再定义EVLIST\nEVLIST will come up later--\n\n305\n00:16:43,264 --> 00:16:48,070\n（闭合括号中）\nEVLIST, apply, COND pair, COND, lambda, define.\n\n306\n00:16:50,900 --> 00:16:52,336\n你现在看到的\nSo that what you are seeing here\n\n307\n00:16:52,670 --> 00:16:56,112\n基本上就是一个完整的求值器\nis pretty much all there is in the evaluator itself.\n\n308\n00:16:56,496 --> 00:17:01,000\n它根据表达式的类型分情况处理\nIt's the case dispatch on the type of the expression\n\n309\n00:17:01,240 --> 00:17:02,112\n默认的情况是\nwith the default\n\n310\n00:17:04,992 --> 00:17:07,950\n表达式应用或者说是组合式\nbeing a general application or a combination.\n\n311\n00:17:17,520 --> 00:17:19,520\n不过还有好些过程 我们没有定义\nNow there is lots of things we haven't defined yet.\n\n312\n00:17:20,080 --> 00:17:21,600\n接下来就看这些未定义的部分\nLet's just look at them and see what they are.\n\n313\n00:17:21,780 --> 00:17:24,128\n我们还要定义EVCOND\nWe're going to have to do this later, evcond.\n\n314\n00:17:25,480 --> 00:17:26,672\n我得定义APPLY\nWe have to write apply.\n\n315\n00:17:27,570 --> 00:17:28,624\n还有EVLIST\nWe're going to have to write EVLIST.\n\n316\n00:17:28,944 --> 00:17:30,208\n以及LOOKUP\nWe're going to write LOOKUP.\n\n317\n00:17:31,790 --> 00:17:33,430\n我看看 没别的了吧？\nI think that's everything, isn't there?\n\n318\n00:17:33,430 --> 00:17:35,168\n剩下的东西都很简单\nEverything else is something which is simple,\n\n319\n00:17:35,168 --> 00:17:37,184\n比如基本元素之类的东西\nor primitive, or something like that.\n\n320\n00:17:38,570 --> 00:17:39,488\n当然\nAnd, of course,\n\n321\n00:17:39,696 --> 00:17:42,064\n在这里 可以扩充很多特殊形式\nwe could many more special forms here,\n\n322\n00:17:42,256 --> 00:17:44,450\n但如果在通用语言中这么做就很糟糕\nbut that would be a bad idea in general in a language.\n\n323\n00:17:44,450 --> 00:17:45,920\n在这里添加大量的东西\nYou make a language very complicated\n\n324\n00:17:46,000 --> 00:17:47,488\n会让语言变得复杂\nby putting a lot of things in there.\n\n325\n00:17:47,690 --> 00:17:50,352\n语言中的保留字\nThe number of reserve words that should exist in a language\n\n326\n00:17:50,768 --> 00:17:53,616\n不该比你能用几个手指、脚指记住的数目多\nshould be no more than a person could remember on his fingers and toes.\n\n327\n00:17:54,160 --> 00:17:55,536\n有些语言的保留字有成百上千个\nAnd I get very upset with languages\n\n328\n00:17:55,568 --> 00:17:58,208\n我都不知道该说什么了\nwhich have hundreds of reserve words.\n\n329\n00:17:59,410 --> 00:18:00,710\n保留字就是在这里定义的\nBut that's where the reserve words go.\n\n330\n00:18:03,152 --> 00:18:06,540\n好 接下来 我们来看下一个部分\nOkay. Well, now let's get to the next part of this,\n\n331\n00:18:06,560 --> 00:18:07,690\n求值器的核心 APPLY\nthe kernel, apply.\n\n332\n00:18:09,640 --> 00:18:10,752\n它还做些什么呢？\nWhat else is this doing?\n\n333\n00:18:11,590 --> 00:18:17,536\nAPPLY把还是符号状态的求值运算符和运算对象\nWell, apply's job is to take a procedure and apply it to its arguments\n\n334\n00:18:17,664 --> 00:18:20,688\n求值为相应的过程以及参数值\nafter both have been evaluated to come up with a procedure and the arguments\n\n335\n00:18:20,912 --> 00:18:23,856\n然后把得到的过程应用在参数上\nrather the operator symbols and the operand symbols,\n\n336\n00:18:24,096 --> 00:18:26,960\n无论它们是什么符号表达式\nwhatever they are-- symbolic expressions.\n\n337\n00:18:33,270 --> 00:18:35,088\n我们把APPLY定义为\nSo we will define apply\n\n338\n00:18:38,352 --> 00:18:40,656\n接收两个参数的过程\nto be a procedure of two arguments,\n\n339\n00:18:40,752 --> 00:18:43,440\n一个过程和对应的参数\na procedure and arguments.\n\n340\n00:18:47,248 --> 00:18:48,128\n它要怎么做呢？\nAnd what does it do?\n\n341\n00:18:48,144 --> 00:18:49,552\n其实并不复杂\nIt does nothing very complicated.\n\n342\n00:18:49,936 --> 00:18:50,784\n分两种情况就够了\nIt's got two cases.\n\n343\n00:18:53,580 --> 00:18:55,168\n如果这个过程是基本过程--\nEither the procedure is primitive--\n\n344\n00:19:03,424 --> 00:19:06,416\n我不知道这个谓词具体是如何判断的\nAnd I don't know exactly how that is done.\n\n345\n00:19:06,864 --> 00:19:10,240\n可能这里面有某种类型信息\nIt's possible there's some type information\n\n346\n00:19:10,384 --> 00:19:12,416\n就像我们在这里用'CLOSURE\njust like we made closure for, here,\n\n347\n00:19:12,688 --> 00:19:15,056\n来描述一些复合对象一样\nbeing the description of the type of a compound thing--\n\n348\n00:19:16,336 --> 00:19:17,792\n我想可能是这样\nOK? probably so.\n\n349\n00:19:18,550 --> 00:19:20,208\n但是具体怎么判断并不重要\nBut it is not essential how that works,\n\n350\n00:19:20,688 --> 00:19:22,016\n事实上\nin fact, it turns out,\n\n351\n00:19:22,192 --> 00:19:23,856\n你可能已经知道或者推断过\nas you probably know or have deduced,\n\n352\n00:19:23,872 --> 00:19:25,472\n我们并不需要任何基本过程\nthat you don't need any primitives anyway.\n\n353\n00:19:27,350 --> 00:19:29,280\n就算没有它们 照样可以进行计算\nYou can compute anything because without\n\n354\n00:19:30,464 --> 00:19:33,190\n因为我们可以用一直在用的LAMBDA\nbecause some of the lambda that I've been playing with.\n\n355\n00:19:33,616 --> 00:19:34,768\n但是有它们总归方便点儿\nBut it's nice to have them.\n\n356\n00:19:34,810 --> 00:19:36,272\n我在这儿略施魔法\nSo here we're going to do some magic\n\n357\n00:19:36,304 --> 00:19:37,470\n但不会去解释\nwhich I'm not going to explain.\n\n358\n00:19:38,060 --> 00:19:41,440\n转到机器语言 执行APPLY-PRIMOP\nGo to machine language, apply primop.\n\n359\n00:19:42,912 --> 00:19:43,808\n加法是在这里运算的\nHere's how it adds.\n\n360\n00:19:44,784 --> 00:19:46,100\n执行加法指令\nExecute an add instruction.\n\n361\n00:19:50,620 --> 00:19:52,112\n然而一门语言有趣的部分\nHowever, the interesting part of a language\n\n362\n00:19:52,144 --> 00:19:54,270\n在于组合基本元素的粘合剂\nis the glue by which the primitives are glued together.\n\n363\n00:19:54,912 --> 00:19:55,904\n我们接着往下看\nSo let's look at that.\n\n364\n00:19:56,910 --> 00:19:58,384\n另一种可能就是\nWell, the other possibility\n\n365\n00:19:58,752 --> 00:20:04,128\n这个复合对象是求值LAMBDA表达式得到的\nthis is a compound made up by executing a lambda expression,\n\n366\n00:20:04,976 --> 00:20:07,056\n这是个复合过程\nthis is a compound procedure.\n\n367\n00:20:07,620 --> 00:20:09,360\n检测它的类型标志\nWell, we'll check its type.\n\n368\n00:20:10,110 --> 00:20:17,072\n如果是'CLOSURE\nIf it is closure,\n\n369\n00:20:20,512 --> 00:20:24,096\n如果是的话 我就得求值这个过程的体\nif it's one of those, then I have to do an eval of the body.\n\n370\n00:20:24,190 --> 00:20:27,392\n过程的体的求值方式则是\nThe way I do this, the way I deal with this at all\n\n371\n00:20:28,080 --> 00:20:31,696\n我求值过程的应用是通过\nis the way I evaluate the application of a procedure to its arguments,\n\n372\n00:20:31,720 --> 00:20:33,710\n先扩充程序的求值环境\nis by evaluating the body of the procedure\n\n373\n00:20:34,192 --> 00:20:37,808\n在这个环境中 把过程的形式参数\nin the environment resulting from extending the environment of the procedure\n\n374\n00:20:37,920 --> 00:20:40,480\n跟传递过来的实际参数绑定在一起\nwith the bindings of the formal parameters\n\n375\n00:20:41,024 --> 00:20:43,680\n在这个环境中求值过程的体\nof the procedure to the arguments that were passed to it.\n\n376\n00:20:46,704 --> 00:20:47,872\n这句话很长\nThat was a long sentence.\n\n377\n00:20:51,130 --> 00:20:52,160\n但其实简单\nWell that's easy enough.\n\n378\n00:20:52,820 --> 00:20:54,480\n一会儿可能会出现许多CAR CDR...\nNow here's going to be a lot of CAR-CDRing.\n\n379\n00:20:56,464 --> 00:20:58,110\n现在我先要得到过程体\nI have to get the body of the procedure.\n\n380\n00:20:59,400 --> 00:21:02,304\n如何取出过程体呢？\nWhere's the body of the procedure in here?\n\n381\n00:21:02,960 --> 00:21:04,080\n这里是CAR部分\nWell here's the CAR,\n\n382\n00:21:04,496 --> 00:21:06,130\n这一块是剩下部分的CDR部分\nhere's the CDR is the whole rest of this.\n\n383\n00:21:06,130 --> 00:21:06,960\n因此这就是CADR\nSo here's the CADR.\n\n384\n00:21:07,400 --> 00:21:09,456\n所以这里我得到的过程体\nAnd so I see, what I have here is the body\n\n385\n00:21:09,456 --> 00:21:13,040\n是过程对象第二个元素的第二个元素\nis the second element of the second element of the procedure.\n\n386\n00:21:13,200 --> 00:21:15,152\n因此CADR的CADR 也就是CADADR\nSo it's the CADR of the CADR or the CADADR.\n\n387\n00:21:19,170 --> 00:21:27,680\n这里取过程对象的CADADR部分\nIt's the C-A-D-A-D-R, CADADR of the procedure.\n\n388\n00:21:30,260 --> 00:21:31,560\n为了求值过程体\nTo evaluate the body\n\n389\n00:21:31,984 --> 00:21:36,480\n要在参数绑定后的新环境之中进行\nin the result of binding that's making up more environment,\n\n390\n00:21:38,096 --> 00:21:42,064\n我还得获取过程的形式参数\nwell I need the formal parameters of the of the procedure,\n\n391\n00:21:42,064 --> 00:21:42,720\n要怎么取呢？\nwhat is that?\n\n392\n00:21:43,500 --> 00:21:45,136\n就是CADR部分的CAR部分\nThat's the CAR of the CADR.\n\n393\n00:21:46,528 --> 00:21:48,780\n这很糟糕不是吗？\nOK? It's horrible isn't it?\n\n394\n00:21:52,656 --> 00:21:53,632\n过程的CADR部分\n--of the procedure.\n\n395\n00:21:55,440 --> 00:22:00,864\n在随着过程一起传递过来的环境中\nBind that to the arguments that were passed in the environment,\n\n396\n00:22:00,896 --> 00:22:04,144\n把形参和由环境传递过来的实参绑定起来\nwhich is passed also as part of the procedure.\n\n397\n00:22:04,540 --> 00:22:07,904\n也就是CDR的CDR的CAR\nWell, that's the CAR of the CDR of the CDR of this,\n\n398\n00:22:09,792 --> 00:22:16,624\n也就是过程的CADDR部分\nCADDR, of the procedure.\n\n399\n00:22:20,290 --> 00:22:24,960\n（闭合括号中）\nBind, eval, pair, COND, lamda, define--\n\n400\n00:22:26,144 --> 00:22:29,680\n当然 如果我非常追求整洁\nNow, of course, if I were being really a neat character,\n\n401\n00:22:29,872 --> 00:22:31,344\n并且又非常谨慎\nand I was being very careful,\n\n402\n00:22:32,240 --> 00:22:34,128\n我会在后面多加一个情况\nI would actually put an extra case here\n\n403\n00:22:34,384 --> 00:22:35,984\n来判断是否出错\nfor checking for certain errors like,\n\n404\n00:22:36,176 --> 00:22:38,416\n比如应用在参数上的是一个过程吗？\ndid you try to apply one to an argument?\n\n405\n00:22:39,000 --> 00:22:41,696\n如果不是 这里就是未定义的过程类型\nYou get a undefined procedure type.\n\n406\n00:22:42,570 --> 00:22:44,096\n我在这里也会这么做\nSo I may as well do that anyway.\n\n407\n00:22:45,808 --> 00:22:55,968\n像这样 在ELSE子句中返回错误\n--else, some sort of error, like that.\n\n408\n00:22:57,610 --> 00:23:01,616\n当然 在现实中的一些系统中\nNow, of course, again, in some sort of more real system,\n\n409\n00:23:02,560 --> 00:23:04,224\n出于专业设计的考虑\nwritten for professional reasons,\n\n410\n00:23:05,320 --> 00:23:08,000\n这里可能会根据某种分派\nthis would be written with a case analysis\n\n411\n00:23:08,368 --> 00:23:09,900\n来进行“分情况处理”\ndone by some sort of dispatch.\n\n412\n00:23:10,750 --> 00:23:12,688\n回到这里 我可能还会添加新的条件来检查\nOver here, I would probably have other cases\n\n413\n00:23:12,704 --> 00:23:14,144\n比如 这是编译过的代码吗？\nlike, is this compiled code?\n\n414\n00:23:16,220 --> 00:23:16,848\n这很重要\nIt's very important.\n\n415\n00:23:16,880 --> 00:23:18,352\n这样的话我就可以区分\nI might have distinguished the kind of code\n\n416\n00:23:18,384 --> 00:23:22,336\n过程是直接由解释LAMBDA表达式而来\nthat's produced by a directly evaluating a lambda in interpretation\n\n417\n00:23:22,944 --> 00:23:25,872\n还是从另外的编译器中得到的 等等\nfrom code that was produced by somebody's compiler or something like that.\n\n418\n00:23:26,112 --> 00:23:27,230\n之后再讨论这个话题\nAnd we'll talk about that later.\n\n419\n00:23:27,230 --> 00:23:29,616\n又或许是 我必须要执行的一段Frotran代码\nOr is this a piece Fortran program I have to go off and execute.\n\n420\n00:23:30,510 --> 00:23:32,512\n这完全是可能的\nIt's a perfectly possible thing, at this point, to do that.\n\n421\n00:23:32,920 --> 00:23:36,416\n实际上 我用具体语法写的这个求值器\nIn fact, in this concrete syntax evaluator I'm writing here,\n\n422\n00:23:37,456 --> 00:23:40,864\n假定了它是用Lisp来编写的\nthere's an assumption built in that this is Lisp,\n\n423\n00:23:42,304 --> 00:23:43,824\n这是因为我用了CAR和CDR\nbecause I'm using CARs and CDRs.\n\n424\n00:23:43,840 --> 00:23:45,104\n用CAR来取运算符\nCAR means the operator,\n\n425\n00:23:45,280 --> 00:23:46,640\n用CDR来取运算对象\nand CDR means the operand.\n\n426\n00:23:46,750 --> 00:23:49,968\n教科书上给出了一个用抽象语法编写的求值器\nIn the text, there is an abstract syntax evaluator\n\n427\n00:23:50,350 --> 00:23:53,152\n它使用的都是抽象的名字\nwhich these could be-- these are given abstract names\n\n428\n00:23:53,160 --> 00:23:54,096\n比如OPERATOR、OPERAND\nlike operator, and operand,\n\n429\n00:23:54,144 --> 00:23:55,820\n以及类似的名字\nand all these other things are like that.\n\n430\n00:23:56,160 --> 00:23:56,864\n那样的话\nAnd, in that case,\n\n431\n00:23:57,024 --> 00:24:00,912\n你可以毫无问题地用ALGOL来重新实现\nyou could reprogram it to be ALGOL with no problem.\n\n432\n00:24:03,360 --> 00:24:06,400\n写完APPLY之后\nWell, here we have added another couple of things\n\n433\n00:24:07,200 --> 00:24:08,432\n又有一些东西没有定义\nthat we haven't defined.\n\n434\n00:24:10,810 --> 00:24:12,576\n我先不操心这两个\nI don't think I'll worry about these at all,\n\n435\n00:24:13,392 --> 00:24:15,050\n我们稍后讨论这个很重要的BIND\nhowever, this one will be interesting later.\n\n436\n00:24:17,184 --> 00:24:19,760\n现在我们来快速过一遍 结束这一部分\nLet's just proceed through this and get it done.\n\n437\n00:24:20,550 --> 00:24:22,656\n只剩下两块黑板了 不能够写太长\nThere's only two more blackboards so it can't be very long.\n\n438\n00:24:27,408 --> 00:24:29,088\n我还得悉心裁剪才能刚好写下\nIt's carefully tailored to exactly fit.\n\n439\n00:24:30,070 --> 00:24:30,980\n嗯 还剩下点什么？\nWell, what do we have left?\n\n440\n00:24:30,980 --> 00:24:33,200\n我们得定义这里的EVLIST\nWe have to define EVLIST, which is over here.\n\n441\n00:24:33,730 --> 00:24:35,072\nEVLIST只不过是\nAnd EVLIST is nothing more\n\n442\n00:24:35,264 --> 00:24:43,088\n在运算对象上映射某个函数得到参数\nthan a map down a bunch of operands producing arguments.\n\n443\n00:24:44,304 --> 00:24:45,408\n但是我还是要写出来看看\nBut I'm going to write it out.\n\n444\n00:24:45,820 --> 00:24:48,304\n我把它写出来的原因有点神秘\nAnd one of the reasons I'm going to write this out is for a mystical reason,\n\n445\n00:24:49,888 --> 00:24:52,048\n我想让这个求值器简单得\nwhich is I want to make this evaluator so simple\n\n446\n00:24:52,064 --> 00:24:53,568\n可以求值自身\nthat it can understand itself.\n\n447\n00:24:56,450 --> 00:24:58,096\n我真的很在意这一点\nI'm going to really worry about that a little bit.\n\n448\n00:25:00,230 --> 00:25:01,744\n现在我就把它完全写在这里\nSo let's write it out completely.\n\n449\n00:25:02,850 --> 00:25:04,240\n我并不关心\nSee, I don't want to worry about\n\n450\n00:25:04,272 --> 00:25:06,080\n它能否把过程作为参数传递\nwhether or not the thing can pass functional arguments.\n\n451\n00:25:06,272 --> 00:25:08,064\n求值器并不会用到这些参数\nThe value evaluator is not going to use them.\n\n452\n00:25:08,980 --> 00:25:10,784\n求值器也不会生成一个是过程的值\nThe evaluator is not going to produce functional values.\n\n453\n00:25:10,880 --> 00:25:12,672\n因此 如果另外有个不同的语言\nSo even if there were a different, alternative language\n\n454\n00:25:12,800 --> 00:25:13,968\n跟这个又非常相似\nthat were very close to this,\n\n455\n00:25:15,160 --> 00:25:17,792\n这个求值器能够求值像Scheme这样的复杂语言\nthis evaluates a complex language like Scheme\n\n456\n00:25:17,808 --> 00:25:23,120\nScheme是能够把过程当做参数传递的\nwhich does allow procedural arguments, procedural values, and procedural data.\n\n457\n00:25:24,070 --> 00:25:25,952\n但当我在求值ALGOL时\nBut even if I were evaluating ALGOL,\n\n458\n00:25:27,344 --> 00:25:28,960\n尽管ALGOL并不支持过程值\nwhich doesn't allow procedural values,\n\n459\n00:25:29,472 --> 00:25:30,592\n这个求值器也能正常工作\nI could use this evaluator.\n\n460\n00:25:31,580 --> 00:25:33,920\n因为这个解释器 并没有对这个做过什么假定\nAnd this evaluator is not making any assumptions about that.\n\n461\n00:25:34,270 --> 00:25:36,032\n实际上 就算这个求值器\nAnd, in fact, if this evaluator were to be restricted\n\n462\n00:25:36,270 --> 00:25:37,504\n被限制不允许那么做 也没有什么关系\nto not being able to that, it wouldn't matter\n\n463\n00:25:37,520 --> 00:25:40,030\n因为它没有使用那些高级功能\nbecause it doesn't use any of those clever things.\n\n464\n00:25:40,640 --> 00:25:42,416\n这就是我为什么要把它设计得非常简单\nSo that's why I'm arranging this to be super simple.\n\n465\n00:25:44,070 --> 00:25:46,464\n这几乎是所有可能的语言求值器的核心\nThis is sort of the kernel of all possible language evaluators.\n\n466\n00:25:47,810 --> 00:25:48,480\n回到这个定义上来\nHow about that?\n\n467\n00:25:49,420 --> 00:25:53,568\nEVLIST -- 它是什么呢？\nEvlist--  well, what is it?\n\n468\n00:25:53,820 --> 00:25:57,040\n这个过程接收两个参数 L和ENV\nIt's the procedure of two arguments, l and an environment,\n\n469\n00:25:58,096 --> 00:25:59,088\n其中L是个表\nwhere l is a list\n\n470\n00:25:59,584 --> 00:26:08,272\n这样的话 如果参数表是空表\nsuch that if the list of arguments is the empty list,\n\n471\n00:26:10,192 --> 00:26:12,688\n那么结果就是空表\nthen the result is the empty list.\n\n472\n00:26:14,032 --> 00:26:19,232\n否则的话 我就要组合\nOtherwise, I want to cons up\n\n473\n00:26:20,752 --> 00:26:26,672\n在ENV中求值运算对象表的CAR部分\nresult of evaluating the CAR of the\n\n474\n00:26:28,160 --> 00:26:32,512\n在ENV中求值运算对象CAR部分的结果\nthe CAR of the list of operands in the environment.\n\n475\n00:26:33,344 --> 00:26:35,712\n我想先求值第一个运算对象\nSo I want the first operand evaluated,\n\n476\n00:26:35,984 --> 00:26:38,400\n返回的结果将是一个新表\nand I'm going to make a list of the results\n\n477\n00:26:38,970 --> 00:26:40,768\n是通过把这个和\nby CONSing that onto the result\n\n478\n00:26:41,088 --> 00:26:45,420\n用CDR递归EVLIST的结果组合得到的\nof this EVLISTing as a CDR recursion,\n\n479\n00:26:46,224 --> 00:26:50,130\n在同样的ENV下 L的CDR部分\nthe CDR of the list relative to the same environment.\n\n480\n00:26:53,088 --> 00:26:58,240\n（闭合括号中）\nEvlist, cons, else, COND, lambda, define--\n\n481\n00:26:59,660 --> 00:27:01,840\n还有一个过程\nOK? And I have one more\n\n482\n00:27:01,840 --> 00:27:03,360\n我也想写在这里\nthat I want to put on the blackboard.\n\n483\n00:27:03,620 --> 00:27:05,216\n它是这整个的关键\nIt's the essence of this whole thing.\n\n484\n00:27:05,648 --> 00:27:08,130\n还要深入一个层次\nAnd there's some sort of next layer down.\n\n485\n00:27:14,540 --> 00:27:15,440\n也就是COND语句\nConditionals--\n\n486\n00:27:15,690 --> 00:27:16,992\n在剩下的东西中\nconditionals are the only thing left\n\n487\n00:27:17,024 --> 00:27:18,170\nEVCOND是唯一的重要过程\nthat are sort of substantial.\n\n488\n00:27:18,880 --> 00:27:20,752\n解决完这个后\nThen below that, we have to worry about\n\n489\n00:27:21,072 --> 00:27:22,944\n我们再讨论LOOKUP和BIND\nthings like lookup and bind,\n\n490\n00:27:23,568 --> 00:27:25,360\n稍后再来讨论\nand we'll look at that in a second.\n\n491\n00:27:25,530 --> 00:27:27,936\n在这个层次上 这是非常重要的\nBut of the substantial stuff at this level of detail,\n\n492\n00:27:28,656 --> 00:27:30,624\n下一个重要的事就是如何处理COND语句\nnext important thing is how you deal with conditionals.\n\n493\n00:27:31,600 --> 00:27:33,330\n那么 我们怎么来处理呢？\nWell, how do we have a conditional thing?\n\n494\n00:27:36,970 --> 00:27:38,560\n它是一个过程\nIt's a procedure\n\n495\n00:27:39,488 --> 00:27:45,000\n参数是一组子句CLAUSES和环境ENV\nof clauses and an environment.\n\n496\n00:27:47,712 --> 00:27:48,512\n它做些什么呢？\nAnd what does it do?\n\n497\n00:27:49,820 --> 00:27:55,472\n如果子句为空\nIt says, if I've no more clauses,\n\n498\n00:28:02,608 --> 00:28:03,968\n我得有一个返回值\nwell, I have to give this a value.\n\n499\n00:28:04,704 --> 00:28:05,872\n可能是一个错误\nIt could be that it was an error.\n\n500\n00:28:06,540 --> 00:28:08,592\n如果遍历完了所有条件 都没有符合的\nSupposing it run off the end of a conditional,\n\n501\n00:28:09,152 --> 00:28:10,060\n那么它可能有任意的行为\nit's pretty arbitrary.\n\n502\n00:28:10,060 --> 00:28:12,880\n这完全取决于程序员要怎么处理\nIt's up to me as programmer to choose what I want to happen.\n\n503\n00:28:13,650 --> 00:28:15,456\n现在对我来说最方便的是\nIt's convenient for me, right now, to write down\n\n504\n00:28:15,632 --> 00:28:17,536\n让它返回一个空表\nthis has a value which is the empty list,\n\n505\n00:28:18,144 --> 00:28:18,832\n这无所谓\ndoesn't matter.\n\n506\n00:28:20,100 --> 00:28:20,880\n为了检查出错误\nFor error checking,\n\n507\n00:28:20,896 --> 00:28:22,760\n有些人喜欢在这里写点别的\nsome people might prefer something else.\n\n508\n00:28:23,110 --> 00:28:24,816\n下面的更有意思\nBut the interesting things are the following ones.\n\n509\n00:28:25,392 --> 00:28:27,248\n如果我遇到了ELSE子句\nIf I've got an else clause--\n\n510\n00:28:31,000 --> 00:28:32,736\n请看 我们有一个由子句组成的表\nYou see, if I have a list of clauses,\n\n511\n00:28:33,216 --> 00:28:34,416\n其中每个子句也是一个表\nthen each clause is a list.\n\n512\n00:28:35,440 --> 00:28:40,528\n因此谓词就应该是CLAUSES的CAAR部分\nAnd so the predicate part is the CAAR of the clauses.\n\n513\n00:28:43,560 --> 00:28:45,024\n它是\nIt's the CAR,\n\n514\n00:28:45,040 --> 00:28:49,008\nCLAUSES表中第一个元素的CAR部分\nwhich is the first part of the first clause in the list of clauses.\n\n515\n00:28:51,090 --> 00:28:51,840\n如果它是'ELSE的话\nIf it's an else,\n\n516\n00:28:54,320 --> 00:28:56,510\n就意味着整个COND表达式的结果\nthen it means I want my result of the conditional\n\n517\n00:28:56,640 --> 00:28:59,152\n就是求值匹配表达式的结果\nto be the result of evaluating the matching expression.\n\n518\n00:29:00,128 --> 00:29:04,320\n所以我求值CADAR部分\nSo I eval the CADAR.\n\n519\n00:29:07,008 --> 00:29:09,568\n这是第一个子句的\nSo this is the first clause,\n\n520\n00:29:10,128 --> 00:29:11,632\n第二个元素 也就是CADAR\nthe second element of it, CADAR--\n\n521\n00:29:12,810 --> 00:29:17,088\n也就是CLAUSES的CAR部分的CADR部分\nCADR of a CAR-- of the clauses,\n\n522\n00:29:21,232 --> 00:29:22,576\n求值的环境是ENV\nwith respect to the environment.\n\n523\n00:29:26,620 --> 00:29:28,608\n下一种可能性更有意思\nNow the next possibility is more interesting.\n\n524\n00:29:29,630 --> 00:29:30,448\n如果它返回FALSE的话\nIf it's false,\n\n525\n00:29:33,056 --> 00:29:35,104\n如果谓词表中的第一个谓词\nif the first predicate in the predicate list\n\n526\n00:29:35,744 --> 00:29:37,680\n既不是ELSE子句 又不为FALSE\nis not an else, and it's not false,\n\n527\n00:29:38,320 --> 00:29:39,504\n也就是它不是保留字ELSE\nif it's not the word else,\n\n528\n00:29:40,160 --> 00:29:42,000\n并且也不是一个值为FALSE的东西\nand if it's not a false thing--\n\n529\n00:29:42,032 --> 00:29:43,664\n如果为FALSE又要怎么处理呢？\nLet's write down what it is if it's a false thing.\n\n530\n00:29:44,360 --> 00:29:50,080\n如果在相应的环境中\nIf the result of evaluating the first clause -- first predicate,\n\n531\n00:29:52,336 --> 00:29:56,768\n求值子句中第一个谓词的结果\nthe clauses--  respect the environment,\n\n532\n00:29:58,190 --> 00:30:01,008\n如果求值的结果是FALSE的话\nif that evaluation yields false,\n\n533\n00:30:01,696 --> 00:30:03,824\n这就意味着 还得接着判断后面的子句\nthen it means, I want to look at the next clause.\n\n534\n00:30:04,368 --> 00:30:05,744\n第一个就扔掉不管了\nSo I want to discard the first one.\n\n535\n00:30:06,250 --> 00:30:08,336\n所以就进入下一个EVCOND循环\nSo we just go around loop, evcond,\n\n536\n00:30:09,952 --> 00:30:16,496\n在对应的环境中继续判断子句的CDR部分\nthe CDR of the clauses relative to that environment.\n\n537\n00:30:19,952 --> 00:30:25,150\n又或者 我遇到了求值为TRUE的子句\nAnd otherwise, I had a true clause,\n\n538\n00:30:26,848 --> 00:30:28,960\n这样的话 我想在对应的环境中\nwhat I want is to evaluate\n\n539\n00:30:31,856 --> 00:30:41,456\n求值CLAUSES的CADAR部分\nthe CADAR of the clauses relative to that environment.\n\n540\n00:30:48,208 --> 00:30:49,616\n快了 快完成了\nBoy, it's almost done.\n\n541\n00:30:51,210 --> 00:30:52,800\n基本上完整了\nIt's quite close to done.\n\n542\n00:30:53,730 --> 00:30:55,872\n把这一部分结束\nI think we're going to finish this part off.\n\n543\n00:30:56,210 --> 00:30:58,576\n再回顾一下这个求值器\nSo just buzzing through this evaluator,\n\n544\n00:30:58,816 --> 00:31:00,704\n它基本上就是这样了\nbut so far you're seeing almost everything.\n\n545\n00:31:01,088 --> 00:31:04,040\n接着来看一张幻灯片\nLet's look at the next transparency here.\n\n546\n00:31:06,320 --> 00:31:10,432\n这是BIND的定义\nAnd see IS, Here is bind.\n\n547\n00:31:11,980 --> 00:31:14,544\nBIND用于在环境中添加新的绑定\nBind is for making more table.\n\n548\n00:31:15,460 --> 00:31:18,672\n我们要在这里\nAnd what we are going to do here is make a--\n\n549\n00:31:19,248 --> 00:31:22,800\n为环境结构创建一个新框架\nwe're going to make a new frame for an environment structure.\n\n550\n00:31:22,800 --> 00:31:25,424\n环境结构是通过由框架组成的表\nThe environment structure is going to be represented\n\n551\n00:31:25,936 --> 00:31:27,200\n来表示的\nas a list of frames.\n\n552\n00:31:28,080 --> 00:31:30,192\n给定一个已有的环境\nSo given an existing environment structure,\n\n553\n00:31:30,320 --> 00:31:32,112\n我可以通过把一个新建的框架\nI'm going to make a new environment structure\n\n554\n00:31:32,256 --> 00:31:33,824\nCONS在已有的环境上\nby consing a new frame\n\n555\n00:31:33,936 --> 00:31:35,696\n来获得新的环境\nonto the existing environment structure,\n\n556\n00:31:36,624 --> 00:31:40,368\n正在应用的过程中 那些被绑定变量\nwhere the new frame consists of the result of pairing up the variables,\n\n557\n00:31:41,050 --> 00:31:43,790\n与传递给过程的参数值结合在一起\nwhich are the bound variables of the procedure I'm applying,\n\n558\n00:31:44,128 --> 00:31:48,256\n组成了我们所创建的新框架\nto the values which are the arguments that were passed that procedure.\n\n559\n00:31:49,690 --> 00:31:50,656\nBIND其实就是创建表\nThis is just making a list,\n\n560\n00:31:51,648 --> 00:31:54,064\n环境就是一组由框架组成的表\nadding a new element to our list of frames,\n\n561\n00:31:54,300 --> 00:31:55,600\n把新的元素加入其中\nwhich is an environment structure,\n\n562\n00:31:55,744 --> 00:31:56,896\n也就形成了新的环境\nto make a new environment.\n\n563\n00:31:58,656 --> 00:32:00,656\n而PAIR-UP的定义非常简单\nWhere pair-up is very simple.\n\n564\n00:32:01,540 --> 00:32:02,848\nPAIR-UP只不过是\nPair-up is nothing more\n\n565\n00:32:03,136 --> 00:32:05,568\n如果我们有一个变量表和一个值表\nthan if I have a list of variables and a list of values,\n\n566\n00:32:05,936 --> 00:32:08,624\n那么 如果它俩的元素个数又相同\nwell, if I run out of variables and if I run out of values,\n\n567\n00:32:08,624 --> 00:32:09,584\n就可以让它们一一对应\neverything's OK.\n\n568\n00:32:09,720 --> 00:32:11,488\n否则的话 就是参数传递多了\nOtherwise, I've given too many arguments.\n\n569\n00:32:12,512 --> 00:32:15,984\n如果值的个数比变量的个数多\nIf I've not run out of variables, but I've run out of values,\n\n570\n00:32:16,064 --> 00:32:17,376\n那就说明参数传递少了\nthat I have too few arguments.\n\n571\n00:32:18,512 --> 00:32:19,632\n通常的情况是\nAnd in the general case,\n\n572\n00:32:19,632 --> 00:32:21,488\n如果没有出错 又没有完成的话\nwhere I don't have any errors, and I'm not done,\n\n573\n00:32:22,060 --> 00:32:25,616\n我就添加一个由第一个变量\nOK? Then I really am just adding a new pair\n\n574\n00:32:25,760 --> 00:32:30,176\n和第一个参数组成的新序对\nof the first variable with the first argument,\n\n575\n00:32:30,944 --> 00:32:32,128\n这是第一个值\nthe first value,\n\n576\n00:32:32,760 --> 00:32:36,400\n把它们CONS在\nonto a list resulting from pairing-up\n\n577\n00:32:37,120 --> 00:32:40,640\n剩余变量和值组成的表上\nthe rest of the variables with the rest of the values.\n\n578\n00:32:42,950 --> 00:32:44,784\nLOOKUP也同样简单\nLookup is of course equally simple.\n\n579\n00:32:46,288 --> 00:32:49,632\n加入我要在环境中查找一个符号\nIf I have to look up a symbol in an environment,\n\n580\n00:32:49,936 --> 00:32:51,392\n那么 如果是空环境\nwell, if the environment is empty,\n\n581\n00:32:51,568 --> 00:32:53,008\n那么就说明 该变量尚未绑定\nthen I've got an unbound variable.\n\n582\n00:32:54,650 --> 00:32:55,472\n否则\nOtherwise,\n\n583\n00:32:56,864 --> 00:33:00,368\n我就要使用一个特殊的关联表查找过程\nwhat I'm going to do is use a special pair list lookup procedure,\n\n584\n00:33:00,384 --> 00:33:01,872\n我们不久就会看到它的定义\nwhich we'll have very shortly,\n\n585\n00:33:02,240 --> 00:33:05,440\n用它在环境的第一个框架中查找该符号\nof the symbol in the first frame of the environment.\n\n586\n00:33:05,930 --> 00:33:07,216\n由于我知道这个环境不是空的\nSince I know the environment is not empty,\n\n587\n00:33:07,232 --> 00:33:08,400\n因此 它至少有一个框架\nit must have a first frame.\n\n588\n00:33:09,200 --> 00:33:11,140\n所以 我就在它第一个框架中查找\nSo I lookup the symbol in the first frame.\n\n589\n00:33:11,568 --> 00:33:13,584\n找到的序对会传递给这里的VCELL\nThat becomes the value cell here.\n\n590\n00:33:14,380 --> 00:33:17,616\n如果VCELL为空\nOK? And then, if the value cell is empty,\n\n591\n00:33:18,448 --> 00:33:20,576\n那就说明当前框架中没有这个符号\nif there is no such value cell,\n\n592\n00:33:20,704 --> 00:33:22,848\n我就需要在环境中剩下的框架中查找\nthen I have to continue and look at the rest of the frames.\n\n593\n00:33:23,720 --> 00:33:25,040\nVCELL为空 意味着当前框架没有相应的符号\nIt means there was nothing found there.\n\n594\n00:33:25,990 --> 00:33:28,896\n如果没有找到\nSo that's a property of ASSQ is it returns emptiness\n\n595\n00:33:29,520 --> 00:33:30,800\nASSQ就会返回空表\nif it doesn't find something.\n\n596\n00:33:32,320 --> 00:33:33,856\n如果找到了\nbut if it did find something,\n\n597\n00:33:33,856 --> 00:33:36,064\n那么我就使用VCELL的CDR部分\nthen I'm going to use the CDR of the value cell here,\n\n598\n00:33:36,464 --> 00:33:40,256\n因为VCELL是变量和值组成的序对\nwhich is the thing that was the pair consisting of the variable and the value.\n\n599\n00:33:41,050 --> 00:33:43,936\n因此可以用CDR取得对应的值\nSo the CDR of it is the value part. OK?\n\n600\n00:33:45,000 --> 00:33:47,824\nASSQ这个过程你们之前见过\nFinally, ASSQ is something you've probably seen already.\n\n601\n00:33:47,970 --> 00:33:50,832\nASSQ的参数是一个符号和一个由序对组成的表\nASSQ takes a symbol and a list of pairs,\n\n602\n00:33:51,424 --> 00:33:53,408\n如果表为空 它就返回空表\nand if the list is empty, it's empty.\n\n603\n00:33:53,520 --> 00:33:56,304\n如果这个符号是ALIST的第一个元素\nIf the symbol is the first thing in the list--\n\n604\n00:33:58,064 --> 00:33:58,912\n这里写错了\nThat's an error.\n\n605\n00:33:59,820 --> 00:34:02,176\n应该是CAAR\nThat should be CAAR, C-A-A-R.\n\n606\n00:34:03,168 --> 00:34:04,160\n大家注意一下\nEverybody note that.\n\n607\n00:34:07,632 --> 00:34:09,376\n就是这里 看到了吗？\nRight there, OK?\n\n608\n00:34:13,424 --> 00:34:14,416\n总之\nAnd in any case,\n\n609\n00:34:14,560 --> 00:34:16,816\n如果符号等于表的CAAR\nf the symbol is the CAAR of the A list,\n\n610\n00:34:17,160 --> 00:34:20,976\n那么我就返回ALIST中第一个序对\nthen I want the first, the first pair, in the alist.\n\n611\n00:34:22,080 --> 00:34:25,504\n换句话说 这个键匹配了正确的条目\nSo, in other words, if this is the key matching the right entry,\n\n612\n00:34:26,240 --> 00:34:26,976\n否则的话\notherwise,\n\n613\n00:34:27,088 --> 00:34:28,944\n我就需要在剩下的表中继续查找\nI want to look up that symbol in the rest.\n\n614\n00:34:30,080 --> 00:34:33,312\n这里有个笔误 很抱歉\nSorry for producing a bug, bugs appear.\n\n615\n00:34:35,190 --> 00:34:36,288\n好了 不管如何\nWell, in any case,\n\n616\n00:34:37,056 --> 00:34:39,488\n你们基本上已经看到了全貌\nyou're pretty much seeing the whole thing now.\n\n617\n00:34:41,880 --> 00:34:43,296\n虽然我们的代码风格非常丑陋\nIt's a very beautiful thing,\n\n618\n00:34:44,192 --> 00:34:46,000\n但是作为所有语言的核心\neven though it's written in an ugly style,\n\n619\n00:34:46,768 --> 00:34:48,304\n它却是非常美妙\nbeing the kernel of every language.\n\n620\n00:34:49,600 --> 00:34:51,376\n我提议 让我们再欣赏一会儿\nI suggest that we just-- let's look at it for a while.\n\n621\n00:35:00,320 --> 00:35:47,024\n[音乐]\n[ALSO SPRACH ZARATHUSTRA]\n\n622\n00:35:49,750 --> 00:35:50,912\n大家有什么问题吗？\nAre there any questions?\n\n623\n00:36:01,180 --> 00:36:03,296\n没有的话就休息一会儿吧\nAlright, I suppose it's time to take a small break then.\n\n624\n00:36:04,040 --> 00:36:10,736\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n625\n00:36:13,880 --> 00:36:17,648\n《计算机程序的构造和解释》\n\n626\n00:36:40,800 --> 00:36:43,936\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n627\n00:36:43,950 --> 00:36:47,984\n《计算机程序的构造和解释》\n\n628\n00:36:48,060 --> 00:36:51,936\n元循环求值器 I\n\n629\n00:36:56,780 --> 00:36:58,992\n现在 我们将用一个实例\nOK, now we're just going to do a little bit of practice\n\n630\n00:36:59,296 --> 00:37:02,672\n来理解一下求值器的运作过程\nunderstanding what it is we've just shown you. OK?\n\n631\n00:37:03,470 --> 00:37:05,488\n我们通过手工进行代换\nWhat we're going to do is go through, in detail,\n\n632\n00:37:05,504 --> 00:37:10,368\n来深入解释器的详细工作原理\nan evaluation by informally substituting through the interpreter.\n\n633\n00:37:11,500 --> 00:37:14,944\n由于我们的求值器不支持赋值和定义\nAnd since we have no assignments or definitions in this interpreter,\n\n634\n00:37:15,200 --> 00:37:17,344\n我们也就不用担心副作用\nwe have no possible side effects,\n\n635\n00:37:17,984 --> 00:37:22,032\n因此我们可以放心大胆地进行代换\nand so the we can do substitution with impunity\n\n636\n00:37:22,528 --> 00:37:24,592\n不用担心任何副作用\nand not worry about results.\n\n637\n00:37:25,330 --> 00:37:27,808\n我们将要尝试去手工代换\nSo the particular problem I'd like to look at\n\n638\n00:37:28,064 --> 00:37:29,632\n这个复杂的表达式\nis it an interesting one.\n\n639\n00:37:30,690 --> 00:37:34,096\n(EVAL\nIt's the evaluation of\n\n640\n00:37:34,910 --> 00:37:48,080\n'(((LAMBDA (X) (LAMBDA (Y) (+ X Y)))\nquote, open, open, open, lambda of x, lambda of y plus x y,\n\n641\n00:37:50,300 --> 00:37:52,624\n（闭合括号中）\nlambda, lambda,\n\n642\n00:37:53,040 --> 00:37:56,128\n要把它应用在3和4上\napplied to three, applied to four,\n\n643\n00:37:56,944 --> 00:37:59,580\n求值过程是发生在全局环境E0中的\nin some global environment which I'll call e0.\n\n644\n00:38:04,930 --> 00:38:05,968\n这里的这个表达式\nSo what we have here\n\n645\n00:38:06,368 --> 00:38:08,048\n是个参数为X的一元过程\nis a procedure of one argument x,\n\n646\n00:38:08,090 --> 00:38:11,056\n返回一个参数为Y的一元过程\nwhich produces as its value a procedure of one argument y,\n\n647\n00:38:11,072 --> 00:38:12,128\n后者计算X+Y\nwhich adds x to y.\n\n648\n00:38:14,300 --> 00:38:17,960\n外层的这个过程应用于数字3\nWe are applying the procedure of one argument x to three.\n\n649\n00:38:17,960 --> 00:38:19,392\n所以X应该是3\nSo x should become three.\n\n650\n00:38:21,400 --> 00:38:23,984\n返回的结果是一个参数为Y的一元过程\nAnd the result of that should be procedure of one argument y,\n\n651\n00:38:24,336 --> 00:38:25,824\n该过程将应用于数字4\nwhich will then apply to 4.\n\n652\n00:38:28,910 --> 00:38:30,320\n然后要做的也很简单\nAnd there is a very simple case,\n\n653\n00:38:31,040 --> 00:38:32,736\n计算X+Y即可\nthey will then add those results.\n\n654\n00:38:34,790 --> 00:38:35,824\n具体做之前\nAnd now in order to do that,\n\n655\n00:38:35,840 --> 00:38:37,760\n先来构造一个非常简单的环境模型\nI want to make a very simple environment model.\n\n656\n00:38:37,904 --> 00:38:40,480\n到了现在 我相信你们已经想到\nAnd at this point, you should already have in your mind\n\n657\n00:38:40,992 --> 00:38:42,592\n这个过程产生的环境了\nthe environments that this produces.\n\n658\n00:38:44,460 --> 00:38:46,624\n我们从全局环境开始\nBut we're going to start out with a global environment,\n\n659\n00:38:48,592 --> 00:38:50,064\n我们把它记作E0\nwhich I'll call e0,\n\n660\n00:38:54,608 --> 00:38:55,472\n就像这样\nwhich is that.\n\n661\n00:38:56,740 --> 00:39:02,464\n里面应该有过程+、*的定义\nAnd it's going to have in it things, definitions for plus, and times,\n\n662\n00:39:06,304 --> 00:39:10,368\n这里 我们用希腊字母来表示过程对象 这样有趣点\nand-- using Greek letters, isn't that interesting, for the objects--\n\n663\n00:39:11,216 --> 00:39:27,936\n-、/、CAR、CDR、CONS以及EQ?\nand minus, and quotient, and CAR, and CDR, and CONS, and EQ,\n\n664\n00:39:28,592 --> 00:39:31,056\n其它需要的基本过程都在全局环境中\nand everything else you might imagine in a global environment.\n\n665\n00:39:31,270 --> 00:39:33,824\n每个符号都对应着一个过程对象\nIt's got something there for each of those things,\n\n666\n00:39:34,620 --> 00:39:36,096\n这些都是解释器自带的\nsomething the machine is born with,\n\n667\n00:39:37,104 --> 00:39:38,090\n这就是E0\nthat's e0.\n\n668\n00:39:39,220 --> 00:39:41,840\n现在 这个求值要怎样进行呢？\nNow what does it mean to do this evaluation?\n\n669\n00:39:42,940 --> 00:39:45,184\n我们来看看这些特殊形式\nWell, we go through the set of special forms.\n\n670\n00:39:45,696 --> 00:39:47,056\n首先 这不是数字\nFirst of all, this is not a number.\n\n671\n00:39:48,670 --> 00:39:50,380\n也不是符号\nThis is not a symbol.\n\n672\n00:39:53,136 --> 00:39:55,600\n这不是一个引用表达式\nGee, it's not a quoted expression.\n\n673\n00:39:56,608 --> 00:39:58,384\n虽然外层是一个引用表达式\nThis is a quoted expression,\n\n674\n00:39:59,470 --> 00:40:00,800\n但并不是我想要去求值的那个\nbut that's not what I mentioned.\n\n675\n00:40:00,832 --> 00:40:01,360\n我想问的是\nThe question is,\n\n676\n00:40:01,392 --> 00:40:04,960\n被引用的这个表达式 是否也是个引用表达式？\nwhether or not the thing which is quoted is quoted expression?\n\n677\n00:40:05,890 --> 00:40:07,960\n我是在求值一个表达式\nI'm evaluating an expression.\n\n678\n00:40:07,960 --> 00:40:09,984\n这个引号是为了引用这个特定表达式\nThis just says it's this particular expression.\n\n679\n00:40:11,410 --> 00:40:12,660\n而被引用的并非引用表达式\nThis is not a quoted expression.\n\n680\n00:40:13,712 --> 00:40:17,216\n当然 它也不是以LAMBDA开头\nOK? It's not a thing that begins with lambda.\n\n681\n00:40:19,120 --> 00:40:20,672\n也不以COND开头\nIt's not a thing that begins with COND.\n\n682\n00:40:22,030 --> 00:40:25,952\n因此它是过程的应用\nTherefore, it's an application of its of an operated operands.\n\n683\n00:40:26,310 --> 00:40:27,120\n这是一个组合式\nIt's a combination.\n\n684\n00:40:28,570 --> 00:40:30,704\n既然它是组合式\nThe combination thus has\n\n685\n00:40:30,890 --> 00:40:34,000\n这就是它的运算符\nthis as the operator\n\n686\n00:40:34,640 --> 00:40:36,080\n而这是它的运算对象\nand this is the operands.\n\n687\n00:40:40,130 --> 00:40:42,416\n这就意味着 我要\nWell, that means that what I'm going to do is\n\n688\n00:40:42,570 --> 00:40:47,904\n把它转换成\ntransform this into apply of eval,\n\n689\n00:40:50,128 --> 00:40:57,616\n(APPLY (EVAL '((LAMBDA (X) (LAMBDA (y)\nof quote, open, open lambda of x, lambda of y--\n\n690\n00:40:57,880 --> 00:40:59,120\n也就是在E0环境中\nI'm evaluating the operator--\n\n691\n00:40:59,952 --> 00:41:04,192\n求值(+ X Y)\nplus x y, in the environment,\n\n692\n00:41:07,264 --> 00:41:08,640\n不要漏了<E0>\nalso e0,\n\n693\n00:41:12,784 --> 00:41:15,200\n要应用到的运算对象则是\nwith the operands that I'm going to apply this to,\n\n694\n00:41:15,260 --> 00:41:17,280\n用EVLIST求值参数的结果\nthe arguments being the result of EVLIST,\n\n695\n00:41:21,216 --> 00:41:24,496\n也就是'(4)\nthe list containing four, fin e0.\n\n696\n00:41:29,010 --> 00:41:31,264\n我用这个特殊的记号来表示<E0>\nI'm using this funny notation here for e0\n\n697\n00:41:32,320 --> 00:41:34,832\n这是为了指代那个环境\nbecause this should be that environment.\n\n698\n00:41:35,450 --> 00:41:37,770\n我无法为它命名\nI haven't a name for it,\n\n699\n00:41:37,808 --> 00:41:39,152\n因为我没有环境来存放<E0>的名字\nbecause I have no environment to name it in.\n\n700\n00:41:41,960 --> 00:41:44,090\n你当然可以把<E0>看作是\nSo this is just a representation\n\n701\n00:41:44,176 --> 00:41:46,176\n某种引用表达式\nwhat would be a quoted expression, if you will.\n\n702\n00:41:47,730 --> 00:41:51,168\n在那里 它表示环境这种数据结构\nThe data structure, which is the environment, goes there.\n\n703\n00:41:53,040 --> 00:41:55,040\n好的 这是变换后的结果\nWell, that's what we're seeing here.\n\n704\n00:41:55,850 --> 00:41:56,672\n为了执行这个表达式\nWell in order to do this,\n\n705\n00:41:56,688 --> 00:41:58,048\n我还得求值这两个表达式\nI have to do this, and I have to do that.\n\n706\n00:41:59,610 --> 00:42:00,496\nEVLIST简单点\nWell this one's easy,\n\n707\n00:42:00,576 --> 00:42:03,184\n我们先计算这个吧\nso why don't we do that one first. OK?\n\n708\n00:42:03,770 --> 00:42:07,440\n这就被归约为\nThis turns into apply of eval--\n\n709\n00:42:07,456 --> 00:42:08,832\n上面的某些部分直接抄过来就好\njust copying something now.\n\n710\n00:42:09,424 --> 00:42:11,000\n代换的过程中少不了照抄\nMost of the substitution rule is copying.\n\n711\n00:42:18,530 --> 00:42:21,248\n抄写的时候我就不多加解释了\nSo I'm going to not say the words when I copy,\n\n712\n00:42:21,712 --> 00:42:23,872\n这样能快一点儿\nbecause it's faster.\n\n713\n00:42:26,410 --> 00:42:28,640\nEVLIST的部分就代换成为\nAnd then the EVLIST is going to turn into a\n\n714\n00:42:28,656 --> 00:42:36,720\n(CONS (EVAL '4 <E0>)\ncons, of eval, of four, in e0--\n\n715\n00:42:38,784 --> 00:42:40,176\n因为它不是空表\nbecause it was not an empty list--\n\n716\n00:42:41,440 --> 00:42:49,392\n(EVLIST '() <E0>))\nonto the result of EVLISTing, on the empty list, in e0.\n\n717\n00:42:52,580 --> 00:42:54,208\n我要省略一些步骤了\nAnd I'm going to start leaving out steps soon,\n\n718\n00:42:54,240 --> 00:42:55,360\n因为太详细就有些无聊了\nbecause it's going to get boring.\n\n719\n00:42:59,870 --> 00:43:05,424\n下一步跟上面基本上一样\nBut this is basically the same thing as apply, of eval--\n\n720\n00:43:07,504 --> 00:43:08,544\n继续照抄\nI'm going to keep doing this--\n\n721\n00:43:10,688 --> 00:43:20,240\n(((LAMBDA (X) (LAMBDA (Y) (+ X Y)) 3) 4) <E0>)\nthe lambda of x, the lambda of y, plus xy, 3, close, e0.\n\n722\n00:43:20,240 --> 00:43:21,200\n看来我还宝刀未老嘛\nI'm a pretty good machine.\n\n723\n00:43:24,240 --> 00:43:26,240\n下面对4求值\nWell, eval of four,\n\n724\n00:43:26,560 --> 00:43:28,440\n4是一个数字\nthat's meets the question, is it a number.\n\n725\n00:43:29,008 --> 00:43:33,904\n结果就应该是(CONS 4\nSo that's cons, right, cons of 4.\n\n726\n00:43:34,032 --> 00:43:37,472\nEVLIST对空表求值 结果也是空表\nAnd EVLIST of the empty list is the empty list,\n\n727\n00:43:38,336 --> 00:43:39,240\n也就是这个\nso that's this.\n\n728\n00:43:42,620 --> 00:43:45,088\n这个非常容易理解\nOK. And that's very simple to understand,\n\n729\n00:43:45,104 --> 00:43:47,440\n就是一个只含有4的表\nbecause that means the list containing four itself.\n\n730\n00:43:48,710 --> 00:43:53,840\n继续代换为 (APPLY (EVAL\nSo this is nothing more than apply of eval,\n\n731\n00:43:55,280 --> 00:44:02,512\n'((LAMBDA (X) (LAMBDA (Y) (+ X Y))\nquote, open, open, lambda of x, lambda of y, plus x y,\n\n732\n00:44:03,400 --> 00:44:07,488\n3) 4) <E0>)\nthree applied to, e0, applied to the list four--\n\n733\n00:44:08,688 --> 00:44:12,608\n应用在'(4)上 这样就完成了\napplied to the list four-- bang\n\n734\n00:44:13,940 --> 00:44:15,056\n这是这一步的结果\nSo that's that step.\n\n735\n00:44:17,008 --> 00:44:19,968\n现在让我们进行下一步 更有意思的一步\nNow let's look at the next, more interesting thing.\n\n736\n00:44:20,360 --> 00:44:21,728\n这行代码要如何求值？\nWhat do I do to evaluate that?\n\n737\n00:44:23,070 --> 00:44:24,448\n为了求值这一部分\nEvaluating this means\n\n738\n00:44:25,200 --> 00:44:28,656\n我得先求值-- 首先 它不是--\nmeans I have to evaluate-- Well, it's not.\n\n739\n00:44:29,460 --> 00:44:31,040\n这是一个应用\nIt's nothing but an application.\n\n740\n00:44:31,680 --> 00:44:33,104\n它并不是特殊形式\nIt's not one of the special things.\n\n741\n00:44:33,570 --> 00:44:36,512\n如果应用中的运算符\nIf the application of this operator,\n\n742\n00:44:36,510 --> 00:44:37,376\n就是这里\nwhich we see here--\n\n743\n00:44:37,664 --> 00:44:38,944\n这就是运算符\nhere's the operator--\n\n744\n00:44:40,190 --> 00:44:41,770\n应用在这个运算对象上\napplied to this operands,\n\n745\n00:44:44,544 --> 00:44:45,744\n形成了一个组合式\nthat combination.\n\n746\n00:44:46,720 --> 00:44:48,256\n现在我们要如何来求值呢？\nBut we know how to do that,\n\n747\n00:44:48,848 --> 00:44:52,370\n它是COND语句中的最后一种情况\nbecause that's the last case of the conditional.\n\n748\n00:44:52,370 --> 00:44:55,520\n在这步求值中 进行的代换是\nSo substituting in for this evaluation,\n\n749\n00:44:55,710 --> 00:44:57,472\n把运算符的求值结果\nit's apply of eval of the operator\n\n750\n00:44:57,504 --> 00:44:59,000\n应用在EVLIST的运算对象上\nin the EVLIST of the operands.\n\n751\n00:45:01,160 --> 00:45:08,208\n这也就是 (APPLY (APPLY (EVAL\nWell, it's apply, of apply, of eval,\n\n752\n00:45:10,576 --> 00:45:21,072\n'(LAMBDA (X) (LAMBDA (Y) (+ X Y)))\nof quote, open, lambda of x, lambda of y, plus x y,\n\n753\n00:45:21,800 --> 00:45:23,450\n（闭合括号中）\nlambda, lambda,\n\n754\n00:45:23,744 --> 00:45:25,424\n<E0>)\nin environment e0.\n\n755\n00:45:30,520 --> 00:45:32,672\n我就直接给出运算对象的求值结果了\nI'm going to short circuit the evaluation of the operands,\n\n756\n00:45:32,688 --> 00:45:34,144\n具体过程跟之前是一样的\nbecause they're the same as they were before.\n\n757\n00:45:35,230 --> 00:45:36,480\n我有一个表'(3)\nI got a list containing three,\n\n758\n00:45:36,512 --> 00:45:39,160\n把它应用于'(4)\napply that, and apply that to four.\n\n759\n00:45:42,448 --> 00:45:43,568\n我们接着看\nWell let's see.\n\n760\n00:45:44,410 --> 00:45:46,384\n对一个LAMBDA表达式求值\nEval of a lambda expression\n\n761\n00:45:48,016 --> 00:45:49,450\n会产生一个过程对象\nproduces a procedure object.\n\n762\n00:45:52,030 --> 00:45:57,888\n继续变换就是 (APPLY (APPLY\nSo this is apply, of apply,\n\n763\n00:46:00,304 --> 00:46:02,272\n然后是一个过程对象 '(CLOSURE\nof the procedure object closure,\n\n764\n00:46:04,520 --> 00:46:08,688\n它里面包含了过程的体\nwhich contains the body of the procedure, x,\n\n765\n00:46:08,944 --> 00:46:11,920\n它绑定了变量X\nwhich is lambda, which binds x [UNINTELLIGIBLE]\n\n766\n00:46:12,130 --> 00:46:15,408\n然后是函数体内部\nthe internals of the body,\n\n767\n00:46:15,808 --> 00:46:18,176\n它返回一个参数为Y的单参过程\nit returns the procedure of one argument y,\n\n768\n00:46:18,560 --> 00:46:20,630\n这个过程计算X+Y\nwhich adds x to y.\n\n769\n00:46:23,210 --> 00:46:25,504\n这个过程对象捕获了环境<E0>\nEnvironment e0 is now captured in it,\n\n770\n00:46:27,248 --> 00:46:29,632\n因为这些求值都是在<E0>中发生的\nbecause this was evaluated with respect to e0.\n\n771\n00:46:30,112 --> 00:46:32,432\n现在 <E0>也是CLOSURE对象的一部分\ne0 is part now of the closure object.\n\n772\n00:46:33,040 --> 00:46:38,192\n先应用于'(3)\nApply that to open, three, close, apply,\n\n773\n00:46:38,816 --> 00:46:41,300\n再应用于'(4)\nto open, 4, close, apply.\n\n774\n00:46:47,390 --> 00:46:49,296\n在这步到这步的过程中\nSo going from this step to this step\n\n775\n00:46:49,312 --> 00:46:50,896\n我构建了一个过程对象\nmeant that I made up a procedure object\n\n776\n00:46:50,910 --> 00:46:52,032\n它捕获了<E0>\nwhich captured in it\n\n777\n00:46:53,888 --> 00:46:55,980\n并将其作为本身的一部分\ne0 as part of the procedure object.\n\n778\n00:46:57,150 --> 00:46:58,512\n现在 要把它们传递给APPLY了\nNow, we're going to pass those to apply.\n\n779\n00:46:58,520 --> 00:46:59,712\n我们得把这个过程\nWe have to apply this procedure\n\n780\n00:47:00,480 --> 00:47:01,580\n应用在对应的参数上\nto that set of arguments.\n\n781\n00:47:02,710 --> 00:47:06,512\n这里的过程并不是基本过程\nWell, but that procedure is not primitive.\n\n782\n00:47:07,380 --> 00:47:09,888\n它有一个类型标志'CLOSURE\nIt's, in fact, a thing which has got the tag closure,\n\n783\n00:47:10,240 --> 00:47:12,096\n因此还需要进行参数绑定\nand, therefore, what we have to do is do a bind.\n\n784\n00:47:13,710 --> 00:47:14,720\n必须要绑定\nWe have to bind.\n\n785\n00:47:15,830 --> 00:47:19,408\n在这里构造的新环境\nA new environment is made at this point,\n\n786\n00:47:20,448 --> 00:47:22,800\n它有一个父环境\nwhich has as its parent environment\n\n787\n00:47:22,944 --> 00:47:27,568\n父环境是这里的<E0>\nthe one over here, e0, that environment.\n\n788\n00:47:30,320 --> 00:47:31,570\n我们把新环境记作<E1>\nAnd we'll call this one, e1.\n\n789\n00:47:34,620 --> 00:47:35,744\n这里要绑定些什么呢？\nNow what's bound in there?\n\n790\n00:47:36,040 --> 00:47:37,488\n变量X绑定为值3\nx is bound to three.\n\n791\n00:47:38,620 --> 00:47:40,448\n这里写X=3\nSo I have x equal three.\n\n792\n00:47:41,480 --> 00:47:42,336\n就是这些\nThat's what's in there.\n\n793\n00:47:44,940 --> 00:47:46,240\n新环境记作E1\nAnd we'll call that e1.\n\n794\n00:47:46,240 --> 00:47:48,448\n而这个表达式会变换为\nSo what this transforms into\n\n795\n00:47:49,130 --> 00:47:50,720\n对一个过程体的求值\nis an eval of the body\n\n796\n00:47:51,728 --> 00:47:53,070\n就是这个 在这里\nof this, which is this,\n\n797\n00:47:54,400 --> 00:47:55,728\n这个过程的体\nthe body of that procedure,\n\n798\n00:47:56,448 --> 00:47:58,528\n在刚才创建的<E1>中进行求值\nin the environment that you just saw.\n\n799\n00:48:00,290 --> 00:48:05,056\n也就是 (APPLY (EVAL\nSo that's an apply, of eval,\n\n800\n00:48:06,920 --> 00:48:16,432\n'(LAMBDA (Y) (+ X Y)) <E1>)\nquote, open, lambda of y, plus x y-- the body-- in e1.\n\n801\n00:48:20,496 --> 00:48:22,480\n把求值的结果应用于4\nAnd apply the result of that to four,\n\n802\n00:48:23,680 --> 00:48:26,736\n也就是'(4)\nopen, close, 4-- list of arguments.\n\n803\n00:48:28,432 --> 00:48:29,872\n到了这里就很清晰了\nWell, that's sensible enough\n\n804\n00:48:30,080 --> 00:48:32,272\n我知道该如何求值LAMBDA表达式\nbecause evaluating a lambda, I know what to do.\n\n805\n00:48:33,110 --> 00:48:34,176\n也就是(APPLY\nThat means I apply,\n\n806\n00:48:37,168 --> 00:48:38,928\n一个过程对象'(CLOSURE\nthe procedure which is closure,\n\n807\n00:48:43,744 --> 00:48:46,848\n它绑定参数Y 计算X+Y\nbinds one argument y, adds x to y,\n\n808\n00:48:49,280 --> 00:48:52,150\n并且捕获了环境<E1>\nwith e1 captured in it.\n\n809\n00:48:55,790 --> 00:48:57,424\n你应该已经见过了 对吧？\nAnd you should really see this. Right?\n\n810\n00:48:57,800 --> 00:49:00,140\n我构造了一个CLOSURE对象\nI somehow manufactured a closure.\n\n811\n00:49:00,140 --> 00:49:01,168\n放在这里\nI should've put this here.\n\n812\n00:49:01,790 --> 00:49:03,040\n之前的那个也是\nThere was one over here too.\n\n813\n00:49:05,904 --> 00:49:07,472\n这是现在的这个\nOK? Well, there's one here now.\n\n814\n00:49:08,080 --> 00:49:09,808\n它捕获了环境<E1>\nI've captured e1,\n\n815\n00:49:10,416 --> 00:49:14,256\n而这个是参数为Y的一元过程\nand this is the procedure of one argument y,\n\n816\n00:49:15,456 --> 00:49:16,704\n先不管它具体是什么\nwhatever this is.\n\n817\n00:49:18,096 --> 00:49:20,720\n我们只知道它是一个CLOSURE\nThat's what that is there, that closure.\n\n818\n00:49:22,576 --> 00:49:26,464\n将这个过程应用于'(4)\nOK? I'm going to apply that to four.\n\n819\n00:49:30,288 --> 00:49:31,776\n很简单\nOK. Well, that's easy enough.\n\n820\n00:49:36,830 --> 00:49:38,736\n我需要通过复制一个指针\nThat means I have to make a new environment\n\n821\n00:49:38,864 --> 00:49:40,528\n就是这个过程的指针\nby copying this pointer,\n\n822\n00:49:41,568 --> 00:49:43,216\n来构造一个新环境\nwhich was the pointer of the procedure,\n\n823\n00:49:44,944 --> 00:49:48,960\n同时还得把参数Y跟值4绑定\nwhich binds y equal 4 with that environment.\n\n824\n00:49:49,824 --> 00:49:52,224\n我把这个新环境 记作<E2>\nAnd here's my new environment, which I'll call e2.\n\n825\n00:49:56,030 --> 00:49:58,120\n当然 这里的这个应用\nAnd, of course, this application then\n\n826\n00:49:58,224 --> 00:50:00,336\n其过程体的求值 是在<E2>中进行的\nis evaluate the body in e2.\n\n827\n00:50:01,584 --> 00:50:07,872\n所以这就变成了对过程体的求值\nSo this is eval, the body,\n\n828\n00:50:07,900 --> 00:50:11,856\n也就是 (EVAL '(+ X Y) <E2>)\nwhich is plus x y, in the environment e2.\n\n829\n00:50:13,710 --> 00:50:14,944\n但由于这是一个应用\nBut this is an application,\n\n830\n00:50:15,480 --> 00:50:23,888\n所以又代换为 (APPLY (EVAL '+ <E2>)\nso this is the apply, of eval, plus in e2,\n\n831\n00:50:26,336 --> 00:50:37,340\n(EVLIST '(X Y) <E2>))\nan EVLIST, quote, open, x y, in e2.\n\n832\n00:50:44,880 --> 00:50:45,590\n我们来看\nWell, but let's see.\n\n833\n00:50:45,590 --> 00:50:51,712\n下一步代换为 (APPLY\nThat is apply, the object\n\n834\n00:50:52,080 --> 00:50:53,872\n求值‘+得到的结果\nwhich is a result of that and plus.\n\n835\n00:50:54,190 --> 00:50:55,664\n所以我们从<E2>开始找\nSo here we are in e2,\n\n836\n00:50:55,696 --> 00:50:57,728\n'+既不在<E2> 也不在<E1>\nplus is not here, it's not here,\n\n837\n00:50:57,744 --> 00:51:01,056\n‘+是<E0>中的基本运算符\nyes, but's here as some primitive operator.\n\n838\n00:51:01,780 --> 00:51:04,745\n这个基本运算符是用于加法的\nSo it's the primitive operator for addition.\n\n839\n00:51:07,472 --> 00:51:14,128\n把它应用于 在<E2>中求值X和Y的结果\nApply that to the result of evaluating x and y in e2.\n\n840\n00:51:14,370 --> 00:51:17,008\n我们知道X是3 Y是4\nBut we can see that x is three and y is four.\n\n841\n00:51:18,112 --> 00:51:23,312\n所以这里是'(3 4)\nSo that's a three and four, here.\n\n842\n00:51:24,160 --> 00:51:26,280\n然后就神奇地得到结果7\nAnd that magically produces for me a seven.\n\n843\n00:51:30,520 --> 00:51:32,448\n我再来整理一下这个过程 这样你们\nI wanted to go through this so you would see,\n\n844\n00:51:32,704 --> 00:51:34,736\n就能了解这其中的重要本质\nessentially, one important ingredient,\n\n845\n00:51:35,760 --> 00:51:37,296\n这个过程中传递了些什么？\nwhich is what's being passed around,\n\n846\n00:51:37,312 --> 00:51:39,568\n每个模块持有什么 又负责什么？\nand who owns what, and what his job is.\n\n847\n00:51:40,470 --> 00:51:41,616\n有哪些模块呢？\nSo what do we have here?\n\n848\n00:51:41,700 --> 00:51:42,624\n一个是EVAL\nWe have eval,\n\n849\n00:51:44,800 --> 00:51:45,640\n还有个APPLY\nWe have eval, and we have apply,\n\n850\n00:51:45,664 --> 00:51:46,624\n两个主要角色\nthe two main players.\n\n851\n00:51:49,370 --> 00:51:51,568\n它们之间有个像这样的大循环\nAnd there is a big loop the goes around like this.\n\n852\n00:51:52,320 --> 00:52:04,576\n其中 EVAL为APPLY生成过程和参数\nWhich is eval produces a procedure and arguments for apply.\n\n853\n00:52:06,270 --> 00:52:08,576\n也有些事情 EVAL也可以自己做\nNow some things eval could do by itself.\n\n854\n00:52:09,504 --> 00:52:10,860\n都是一些细小的事情\nThose are little self things here.\n\n855\n00:52:10,860 --> 00:52:11,744\n并不十分有趣\nThey're not interesting.\n\n856\n00:52:12,700 --> 00:52:15,600\n同时 EVAL也逐个求值所有的参数\nAlso eval evaluates all of the arguments, one after another.\n\n857\n00:52:16,240 --> 00:52:17,280\n也没什么意思\nThat's not very interesting.\n\n858\n00:52:17,650 --> 00:52:20,096\nAPPLY可以应用像+这类的过程\nApply can apply some procedures like plus,\n\n859\n00:52:21,024 --> 00:52:22,040\n这很普通\nnot very interesting.\n\n860\n00:52:22,300 --> 00:52:24,640\n然而 如果APPLY不能应用像+这样的过程\nHowever, if apply can't apply a procedure like plus,\n\n861\n00:52:25,312 --> 00:52:33,312\n它就为EVAL生成一个表达式及相应的环境\nit produces an expression and environment for eval.\n\n862\n00:52:35,470 --> 00:52:37,616\n过程的参数封装了\nThe procedural arguments wrap up\n\n863\n00:52:38,240 --> 00:52:40,608\n计算所必需的状态\nessentially the state of a computation\n\n864\n00:52:41,664 --> 00:52:43,424\n以及相应的环境\nand, certainly, the expression of environment.\n\n865\n00:52:43,740 --> 00:52:45,312\n但我们接下来要做的\nAnd so what we're actually going to do next\n\n866\n00:52:45,328 --> 00:52:46,464\n并不是完整的状态\nis not the complete state,\n\n867\n00:52:46,480 --> 00:52:48,820\n因为它没有说明谁需要返回的结果\nbecause it doesn't say who wants the answers.\n\n868\n00:52:51,280 --> 00:52:52,208\n我们要做的就是\nBut what we're going to do--\n\n869\n00:52:52,240 --> 00:52:54,800\n总是把某个表达式以及相应的环境\nit's always got something like an expression of environment\n\n870\n00:52:54,992 --> 00:52:56,144\n或者过程对象以及其参数\nor procedure and arguments\n\n871\n00:52:56,288 --> 00:52:58,080\n在这个循环之间不断传递\nas the main loop that we're going around.\n\n872\n00:52:58,970 --> 00:53:01,808\n这里还有一些小型的子循环 比如EVLIST\nThere are minor little sub loops like eval through EVLIST,\n\n873\n00:53:04,496 --> 00:53:06,768\n又或者是EVAL中的EVCOND循环\nor eval through evcond,\n\n874\n00:53:09,104 --> 00:53:11,968\n甚至于APPLY调用PRIMITIVE-APPLY\nor apply through a primitive apply.\n\n875\n00:53:16,140 --> 00:53:17,648\n但是它们并不是最主要的\nBut they're not the essential things.\n\n876\n00:53:18,864 --> 00:53:20,288\n这整个就是我想让你们看到的\nSo that's what I wanted you to see.\n\n877\n00:53:21,860 --> 00:53:22,880\n有什么问题吗？\nAre there any questions?\n\n878\n00:53:25,930 --> 00:53:27,376\nDavid 请说\nYes. David\n\n879\n00:53:27,740 --> 00:53:33,310\n学生：我不明白为什么X是3\nAUDIENCE: I'm trying to understand how x got down to three\n\n880\n00:53:34,016 --> 00:53:36,304\n而不是4\ninstead of four.\n\n881\n00:53:37,070 --> 00:53:38,520\n在那个部分\nAt the early part of the--\n\n882\n00:53:38,560 --> 00:53:40,544\n教授：是在这里\nPROFESSOR: Here.\n\n883\n00:53:41,310 --> 00:53:43,310\n你想知道X是如何跟3绑定的\nYou want to know how x got down to three?\n\n884\n00:53:43,520 --> 00:53:47,424\n学生：因为X是外层过程的参数\nAUDIENCE: Because x is the outer procedure,\n\n885\n00:53:48,464 --> 00:53:50,992\n而内层过程中既有X又有Y\nand x and y are the inner procedure.\n\n886\n00:53:51,264 --> 00:53:51,888\n教授：明白了\nPROFESSOR: Fine.\n\n887\n00:53:52,848 --> 00:53:54,624\n代换的过程中 我已经非常小心了\nWell, I was very careful and mechanical.\n\n888\n00:53:55,020 --> 00:53:56,928\n或许首先 我应该把这些过程\nFirst of all, I should write those procedures\n\n889\n00:53:56,944 --> 00:53:58,410\n重新编排得更易读一点\nagain for you, pretty printed.\n\n890\n00:54:00,610 --> 00:54:01,472\n你之所以有所疑惑\nFirst order of business,\n\n891\n00:54:01,488 --> 00:54:02,990\n或许是因为你把程序看岔了\nbecause you're probably not reading them well.\n\n892\n00:54:03,830 --> 00:54:04,704\n所以这里应该是\nSo I have here\n\n893\n00:54:05,150 --> 00:54:09,600\n一个以X为参数的过程\nthat procedure of-- was it x over there--\n\n894\n00:54:11,216 --> 00:54:14,990\n它返回一个以Y为参数的过程\nwhich is -- value of that procedure of y\n\n895\n00:54:15,728 --> 00:54:18,440\n后者计算X+Y\nwhich adds x to y,\n\n896\n00:54:19,824 --> 00:54:21,104\n（闭合括号中）\nlambda, lambda,\n\n897\n00:54:21,408 --> 00:54:22,896\n外面的过程应用到3上\napplied that to three,\n\n898\n00:54:24,080 --> 00:54:26,128\n把得到的结果应用到4上\ntakes the result of that, and applied that to four.\n\n899\n00:54:26,140 --> 00:54:28,810\n这个和之前那个是一样的 对吧？\nIs that not what I wrote? OK?\n\n900\n00:54:28,810 --> 00:54:32,336\n现在 你可以立马发现\nNow, you should immediately see that\n\n901\n00:54:33,776 --> 00:54:34,944\n这里是一个应用\nhere is an application--\n\n902\n00:54:35,168 --> 00:54:36,464\n我先换根白粉笔\nlet me get a white piece of chalk--\n\n903\n00:54:37,328 --> 00:54:41,120\n这一部分是应用 是一个组合式\nhere is an application, a combination.\n\n904\n00:54:43,440 --> 00:54:46,400\n这部分是组合式的运算符\nOK? That combination has this as the operator\n\n905\n00:54:48,144 --> 00:54:49,552\n而这是运算对象\nand this as the operand.\n\n906\n00:54:51,040 --> 00:54:53,056\n这个3会跟这里的X绑定\nThe three is going in for the x here.\n\n907\n00:54:54,900 --> 00:54:56,368\n而这个组合式的结果\nThe result of this\n\n908\n00:54:56,560 --> 00:54:58,464\n是一个参数为Y的一元过程\nis a procedure of one argument y,\n\n909\n00:54:58,736 --> 00:54:59,792\n它将应用于4\nwhich gets applied to four.\n\n910\n00:55:00,880 --> 00:55:01,584\n明白了吧？\nOK?\n\n911\n00:55:02,208 --> 00:55:04,080\n所以你可能只是看岔了\nSo you just weren't reading the expression right.\n\n912\n00:55:04,400 --> 00:55:07,856\n而你们在这里看到的\nThe way you see that over here. OK.\n\n913\n00:55:09,424 --> 00:55:12,960\n是一个实际的过程对象 它有一个参数X\nis that here I have the actual procedure object, x.\n\n914\n00:55:13,340 --> 00:55:15,312\n这个CLOSURE将应用于3\nIt's getting applied to three,\n\n915\n00:55:15,952 --> 00:55:17,072\n也就是'(3)\nthe list containing three.\n\n916\n00:55:18,980 --> 00:55:21,344\n得到的结果再应用于'(4)\nWhat I'm left over with is something which gets applied to four.\n\n917\n00:55:24,080 --> 00:55:25,200\n还有疑问吗？\nAre there any other questions?\n\n918\n00:55:28,350 --> 00:55:30,384\n那就休息一下吧\nTime for our next small break then.\n\n919\n00:55:30,832 --> 00:55:31,370\n谢谢大家\nThank you.\n\n920\n00:55:33,730 --> 00:55:41,408\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n921\n00:55:42,128 --> 00:55:47,440\n《计算机程序的构造和解释》\n\n922\n00:55:50,700 --> 00:55:54,080\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n923\n00:55:54,120 --> 00:55:59,168\n《计算机程序的构造和解释》\n\n924\n00:55:59,232 --> 00:56:03,952\n元循环求值器 I\n\n925\n00:56:08,410 --> 00:56:11,296\n教授：课上到这里\nPROFESSOR: Let's see, at this point,\n\n926\n00:56:13,328 --> 00:56:14,592\n你们可能开始觉得\nyou should be getting the feeling,\n\n927\n00:56:14,752 --> 00:56:17,960\nSussman教授又在胡说八道些什么\nwhat's this nonsense this Sussman character is feeding me?\n\n928\n00:56:20,740 --> 00:56:23,920\n他讲的东西奇怪、愚蠢又毫无意义\nThere's an awful lot of strange nonsense here.\n\n929\n00:56:24,800 --> 00:56:27,408\n他还宣称要给我们解释Lisp\nAfter all, he purported to explain to me Lisp,\n\n930\n00:56:28,016 --> 00:56:29,904\n然后在黑板上给我们写了一个Lisp程序\nand he wrote me a Lisp program on the blackboard.\n\n931\n00:56:31,232 --> 00:56:33,536\n他还说：“这个Lisp程序就是Lisp解释器”\nThe Lisp program was intended to be interpreted for Lisp,\n\n932\n00:56:33,850 --> 00:56:35,024\n但是为了运行这个Lisp程序\nbut you need a Lisp interpreter\n\n933\n00:56:35,040 --> 00:56:36,300\n你还先得有一个Lisp解释器啊\nin order to understand that program.\n\n934\n00:56:38,370 --> 00:56:40,192\n那个程序怎么能告诉我\nHow could that program have told me anything\n\n935\n00:56:40,224 --> 00:56:43,200\n有关于Lisp的知识呢？\nthere is to be known about Lisp?\n\n936\n00:56:44,150 --> 00:56:46,224\n它为什么又不是空中楼阁呢？\nHow is that not completely vacuous?\n\n937\n00:56:48,490 --> 00:56:50,256\n这件事非常奇怪\nIt's a very strange thing.\n\n938\n00:56:50,990 --> 00:56:52,430\n它究竟告诉了我什么？\nDoes it tell me anything at all?\n\n939\n00:56:56,070 --> 00:56:57,200\n我们发现 其实这整件事\nWell, you see, the whole thing\n\n940\n00:56:57,328 --> 00:56:59,790\n非常像我们在这张幻灯片上看到的\nis sort of like these Escher's hands\n\n941\n00:57:00,464 --> 00:57:03,552\nEscher所画的手\nthat we see on this slide.\n\n942\n00:57:06,180 --> 00:57:07,728\n是的 EVAL和APPLY\nYes, eval and apply\n\n943\n00:57:07,760 --> 00:57:10,160\n彼此画出彼此\neach sort of draw each other\n\n944\n00:57:11,504 --> 00:57:14,160\n并且构造出了真实的东西\nand construct the real thing,\n\n945\n00:57:14,864 --> 00:57:16,304\n它完全是自己画出了自己\nwhich can sit out and draw itself.\n\n946\n00:57:17,110 --> 00:57:18,464\nEscher真是绝顶聪明\nEscher was a very brilliant man,\n\n947\n00:57:18,688 --> 00:57:20,416\n他只不过叫不出这些精灵的名字\nhe just didn't know the names of these spirits.\n\n948\n00:57:23,910 --> 00:57:25,008\n我现在要做的就是\nWell, I'm going to do now,\n\n949\n00:57:26,096 --> 00:57:28,000\n使你们相信\nis I'm going to try to convince you\n\n950\n00:57:28,160 --> 00:57:29,872\n这一切都是有意义的\nthat both this mean something,\n\n951\n00:57:30,160 --> 00:57:31,980\n并且\nand, as a aside,\n\n952\n00:57:32,992 --> 00:57:34,720\n我将要解释为什么我们不需要DEFINE\nI'm going to show you why you don't need definitions.\n\n953\n00:57:36,090 --> 00:57:37,712\n事实证明 我们并不需要DEFINE\nJust turns out that sort of falls out,\n\n954\n00:57:38,096 --> 00:57:41,120\n为了进行数学意义上的计算\nwhy definitions are not essential in a mathematical sense\n\n955\n00:57:42,512 --> 00:57:44,890\nDEFINE并不是必需的\nfor doing all the things we need to do for computing.\n\n956\n00:57:49,104 --> 00:57:50,032\n我们来看一下\nWell, let's see here.\n\n957\n00:57:50,690 --> 00:57:53,312\n考虑下面的一小段程序\nConsider the following small program,\n\n958\n00:57:53,744 --> 00:57:54,640\n它有什么作用？\nwhat does it mean?\n\n959\n00:57:54,870 --> 00:57:57,648\n这是一个计算指数的程序\nThis is a program for computing exponentials.\n\n960\n00:58:07,270 --> 00:58:13,232\nEXPT计算X的N次方\nThe exponential of x to the nth power is if--\n\n961\n00:58:16,832 --> 00:58:18,128\n如果N为0\nn is zero,\n\n962\n00:58:19,200 --> 00:58:20,768\n那么结果就是1\nthen the result is one.\n\n963\n00:58:22,070 --> 00:58:22,816\n否则\nOtherwise,\n\n964\n00:58:25,568 --> 00:58:28,480\n结果就是X乘以\nI want the product of x\n\n965\n00:58:28,752 --> 00:58:33,930\n(EXPT X (- N 1))))\nand the result of exponentiating x to the n minus one power.\n\n966\n00:58:43,696 --> 00:58:44,560\n应该没错\nI think I got it right.\n\n967\n00:58:46,630 --> 00:58:48,720\n一个递归定义\nNow this is a recursive definition.\n\n968\n00:58:49,470 --> 00:58:52,176\n用EXPT自身\nIt's a definition of the exponentiation\n\n969\n00:58:52,464 --> 00:58:54,780\n来定义EXPT过程自己\nprocedure in terms of itself.\n\n970\n00:58:56,410 --> 00:58:58,320\n就像我之前说的那样\nAnd, as it has been mentioned before,\n\n971\n00:58:59,280 --> 00:59:01,680\n你们高中数学老师在教这些东西的时候\nyour high school geometry teacher\n\n972\n00:59:01,840 --> 00:59:04,048\n你们一定学得很痛苦\nprobably gave you a hard time about things like that.\n\n973\n00:59:05,650 --> 00:59:06,736\n这样定义合理吗？\nWas that justified?\n\n974\n00:59:07,910 --> 00:59:10,848\n为什么这种自引用的定义\nWhy does this self referential definition\n\n975\n00:59:10,960 --> 00:59:12,040\n能够说得通呢？\nmake any sense?\n\n976\n00:59:13,430 --> 00:59:15,104\n首先我要说的是\nWell, first of all, I'm going to convince you that\n\n977\n00:59:15,136 --> 00:59:17,600\n你们高中数学老师并非在胡说八道\nyour high school geometry teacher was not telling you nonsense.\n\n978\n00:59:20,370 --> 00:59:23,424\n考虑下面的几组定义\nConsider the following set of definitions here.\n\n979\n00:59:24,270 --> 00:59:27,424\nX+Y=3\nx plus y equals three,\n\n980\n00:59:28,240 --> 00:59:32,240\nX-Y=1\nand x minus y equal one.\n\n981\n00:59:33,070 --> 00:59:35,568\n这个方程用Y来告诉你X\nWell, gee, this tells you x in terms of y,\n\n982\n00:59:35,584 --> 00:59:37,840\n而这个方程或许是用X来告诉你Y\nand this one tells you y in terms of x, presumably.\n\n983\n00:59:40,150 --> 00:59:42,950\n碰巧这组方程有唯一的解\nAnd yet this happens to have a unique solution in x and y.\n\n984\n00:59:55,910 --> 00:59:58,112\n然而 我也可能有这样的方程\nHowever, I could also write\n\n985\n00:59:59,872 --> 01:00:04,256\n2X+2Y=6\ntwo x plus two y is six.\n\n986\n01:00:06,832 --> 01:00:09,872\n这两个方程有无穷多个解\nThese two equations have an infinite number solutions.\n\n987\n01:00:15,730 --> 01:00:17,424\n我还可以有像这样的方程\nAnd I could write you, for example,\n\n988\n01:00:18,896 --> 01:00:21,536\nX-Y=2\nx minus y equal 2,\n\n989\n01:00:22,144 --> 01:00:24,416\n而下面的这两个方程没有解\nand these two equations have no solutions.\n\n990\n01:00:29,820 --> 01:00:33,040\n这里 我有三组线性方程组\nWell, I have here three sets of simultaneous linear equations,\n\n991\n01:00:35,456 --> 01:00:39,510\n分别是这组、这组和这组\nthis set, this set, and this set.\n\n992\n01:00:39,888 --> 01:00:41,792\n它们的解的数目完全不同\nBut they have different numbers of solutions.\n\n993\n01:00:42,900 --> 01:00:45,760\n解的数目并不取决于方程的形式\nThe number of solutions is not in the form of the equations.\n\n994\n01:00:46,336 --> 01:00:48,208\n三组方程都有一样的形式\nThey all three sets have the same form.\n\n995\n01:00:48,544 --> 01:00:50,416\n解的数目取决于方程的内容\nThe number of solutions is in the content.\n\n996\n01:00:53,000 --> 01:00:55,152\n我不能通过观察方程的形式\nI can't tell by looking at the form of a definition\n\n997\n01:00:55,168 --> 01:00:56,240\n来判断解的数目\nwhether it makes sense,\n\n998\n01:00:56,864 --> 01:00:58,608\n必须要看它的内容\nonly by its detailed content.\n\n999\n01:00:59,660 --> 01:01:00,880\n比如 对于线性方程组\nWhat are the coefficients,\n\n1000\n01:01:01,344 --> 01:01:03,392\n它的系数都是什么？\nfor example, in the case of linear equations?\n\n1001\n01:01:05,100 --> 01:01:06,720\n我不能够通过观察\nSo I shouldn't expect to be able to tell\n\n1002\n01:01:06,992 --> 01:01:08,336\n像这样的简单情况\nlooking at something like this,\n\n1003\n01:01:08,592 --> 01:01:09,952\n来判定\nfrom some simple things like,\n\n1004\n01:01:10,080 --> 01:01:14,496\nEXPT就是这个递归方程的解\noh yes, EXPT is the solution of this recursion equation.\n\n1005\n01:01:16,030 --> 01:01:18,416\n我不能说 EXPT就是那个过程\nExpt is the procedure\n\n1006\n01:01:18,912 --> 01:01:21,104\n如果我们把它代换入其中\nwhich if substituted in here,\n\n1007\n01:01:22,048 --> 01:01:24,064\n它就能给我们返回EXPT\ngives me expt back.\n\n1008\n01:01:25,328 --> 01:01:25,680\n能跟上吗？\nOK?\n\n1009\n01:01:26,040 --> 01:01:29,248\n通过观察这个形式 我也无法判别\nI can't tell, looking at this form,\n\n1010\n01:01:29,808 --> 01:01:32,608\nEXPT是否有唯一解\nwhether or not there's a single, unique solution for EXPT,\n\n1011\n01:01:33,232 --> 01:01:35,312\n有无穷个解 还是根本没有解\nan infinite number of solutions, or no solutions.\n\n1012\n01:01:37,200 --> 01:01:38,624\n我们要了解它是如何计数的\nIt's got to be how it counts\n\n1013\n01:01:38,640 --> 01:01:40,144\n或者是一些类似的计算细节\nand things like that, the details.\n\n1014\n01:01:40,608 --> 01:01:42,752\n这可比在线性代数难多了\nAnd it's harder in programming than linear algebra.\n\n1015\n01:01:43,280 --> 01:01:45,210\n程序设计中可用的定理并不多\nThere aren't too many theorems about it in programming.\n\n1016\n01:01:48,450 --> 01:01:51,216\n我想把这些方程稍稍重写一下\nWell, I want to rewrite these equations a little bit,\n\n1017\n01:01:51,936 --> 01:01:53,776\n就是这里的方程\nthese over here.\n\n1018\n01:01:53,970 --> 01:01:56,624\n因为我们要研究的是这种形式的方程\nBecause what we're investigating is equations like this.\n\n1019\n01:01:57,000 --> 01:01:58,384\n但是我想用我们比较了解的方程\nBut I want to play a little with equations\n\n1020\n01:01:58,400 --> 01:01:59,530\n来做演示\nlike this that we understand,\n\n1021\n01:02:00,704 --> 01:02:02,912\n以便于对于这类问题有深入的洞见\njust so we get some insight into this kind of question.\n\n1022\n01:02:04,720 --> 01:02:06,432\n我们可以把这里的方程 改写为\nWe could rewrite our equations here,\n\n1023\n01:02:06,752 --> 01:02:08,672\n这样的一种有趣形式\nsay these two, the ones that are interesting,\n\n1024\n01:02:09,776 --> 01:02:14,864\nX=3-Y\nas x equals three minus y,\n\n1025\n01:02:15,888 --> 01:02:19,680\nY=X-1\nand y equals x minus one.\n\n1026\n01:02:22,010 --> 01:02:24,050\n我们把这种变换叫什么来着？\nWhat do we call this transformation?\n\n1027\n01:02:24,050 --> 01:02:26,528\n这是一个线性变换 记为T\nThis is a linear transformation, t.\n\n1028\n01:02:29,430 --> 01:02:32,256\n我们这里就得到了一个方程\nThen what we're getting here is an equation\n\n1029\n01:02:32,976 --> 01:02:37,370\n<X Y> = T<X Y>\nx y equals t of x y.\n\n1030\n01:02:42,990 --> 01:02:43,984\n我要去找什么呢？\nWhat am I looking for?\n\n1031\n01:02:44,560 --> 01:02:46,016\n我在找T的不动点\nI'm looking for a fixed point of t.\n\n1032\n01:02:46,976 --> 01:02:59,424\nT的不动点就是方程的解\nThe solution is a fixed point of t.\n\n1033\n01:03:01,910 --> 01:03:05,536\n所以 如果我们能通过找不动点\nSo the methods we should have for looking for solutions to equations,\n\n1034\n01:03:05,904 --> 01:03:07,488\n来求解方程\nif I can do it by fixed points,\n\n1035\n01:03:08,656 --> 01:03:09,872\n这看来是可行的\nmight be applicable.\n\n1036\n01:03:10,880 --> 01:03:12,368\n如果我可以用不动点\nIf I have a means of finding a solution\n\n1037\n01:03:12,384 --> 01:03:14,320\n来求解方程\nto an equations by fixed points--\n\n1038\n01:03:15,520 --> 01:03:18,192\n当然 也许它不可行\njust, might not work--\n\n1039\n01:03:18,570 --> 01:03:19,800\n不过也可以借鉴来\nbut it might be applicable\n\n1040\n01:03:20,096 --> 01:03:22,272\n研究如何求解这类方程\nto investigating solutions of equations like this.\n\n1041\n01:03:27,240 --> 01:03:29,488\n重要的是 我想让你们把它看成一个方程\nBut what I want you to feel is that this is an equation.\n\n1042\n01:03:30,260 --> 01:03:31,216\n它是一个表达式\nIt's an expression\n\n1043\n01:03:31,360 --> 01:03:33,580\n其中有不同的变量\nwith several instances of various names\n\n1044\n01:03:34,704 --> 01:03:37,664\n只不过这些名字还得满足一定的约束\nwhich puts a constraint on the name,\n\n1045\n01:03:38,432 --> 01:03:40,528\n这些名字限定了对应变量的取值\nsaying what that name could have as its value,\n\n1046\n01:03:41,488 --> 01:03:45,010\n我们不能够随意、机械地代换\nrather than some sort of mechanical process of substitution right now.\n\n1047\n01:03:47,740 --> 01:03:49,776\n这就是我尝试求解的方程\nThis is an equation which I'm going to try to solve.\n\n1048\n01:03:51,220 --> 01:03:52,432\n我们来试试看\nWell, let's play around and solve it.\n\n1049\n01:03:53,960 --> 01:03:55,664\n首先我需要写下\nFirst of all, I want to write down\n\n1050\n01:03:56,640 --> 01:03:59,008\n跟T相对应的函数\nthe function which corresponds to t.\n\n1051\n01:04:00,320 --> 01:04:03,008\n我写下的这个T对应的函数\nFirst I want to write down the function which corresponds to t\n\n1052\n01:04:04,496 --> 01:04:06,960\n它的不动点就是这个方程的解\nwhose fixed point is the answer to this question.\n\n1053\n01:04:10,760 --> 01:04:11,280\n能明白吗？\nOK?\n\n1054\n01:04:12,256 --> 01:04:14,304\n让我们来看下面这个过程F\nWell, let's consider the following procedure f.\n\n1055\n01:04:16,870 --> 01:04:18,304\n我说 F计算的是这样一个函数\nI claim it computes that function.\n\n1056\n01:04:19,340 --> 01:04:22,912\nF本身是一个参数为G的一元过程\nf is that procedure of one argument g,\n\n1057\n01:04:25,232 --> 01:04:25,936\n它返回\nwhich is\n\n1058\n01:04:26,400 --> 01:04:32,000\n一个参数为X和N的过程\nthat procedure of two arguments x and n.\n\n1059\n01:04:33,430 --> 01:04:34,736\n这个过程的定义是：\nWhich have the property that\n\n1060\n01:04:36,720 --> 01:04:40,432\n如果N为0\nif n is zero,\n\n1061\n01:04:41,728 --> 01:04:43,200\n那么结果就是1\nthen the result is one,\n\n1062\n01:04:45,344 --> 01:04:46,176\n否则的话\notherwise,\n\n1063\n01:04:49,900 --> 01:05:01,408\n结果就是(* X (G X (- N 1)))\nthe result is the product of x and g, applied to x, and minus n1.\n\n1064\n01:05:03,370 --> 01:05:07,808\n（闭合括号中）\ng, times, else, COND, lambda, lambda--\n\n1065\n01:05:08,944 --> 01:05:09,408\n没问题吧\nOK?\n\n1066\n01:05:12,304 --> 01:05:14,624\n这里 F是一个过程\nHere f is a procedure,\n\n1067\n01:05:15,050 --> 01:05:17,792\n如果我能解出这个方程\nwhich if I had a solution to that equation,\n\n1068\n01:05:19,040 --> 01:05:22,048\n如果我找到了一个良好的指数过程\nif I had a good exponentiation procedure,\n\n1069\n01:05:23,420 --> 01:05:26,320\n我把这个F应用到那个过程上\nand I applied f to that procedure,\n\n1070\n01:05:27,600 --> 01:05:31,248\n那么返回的应该也是一个良好的指数过程\nthen the result would be a good exponentiation procedure.\n\n1071\n01:05:37,460 --> 01:05:38,576\n这是为什么呢？\nBecause, what does it do?\n\n1072\n01:05:39,420 --> 01:05:40,880\n这是因为\nWell, all it is\n\n1073\n01:05:42,368 --> 01:05:44,640\nF假设G是一个良好的指数过程\nis exposing g were a good exponentiation procedure,\n\n1074\n01:05:45,632 --> 01:05:47,584\n那么这里就会返回\nwell then this would produce, as its value,\n\n1075\n01:05:47,840 --> 01:05:49,680\n一个参数为X和N的过程\na procedure to arguments x and n,\n\n1076\n01:05:50,490 --> 01:05:51,520\n其中如果N=0\nsuch that if n were 0,\n\n1077\n01:05:51,552 --> 01:05:52,416\n结果就是1\nthe result would be one,\n\n1078\n01:05:52,448 --> 01:05:54,160\n这是非常符合定义的\nwhich is certainly true of exponentiation.\n\n1079\n01:05:54,640 --> 01:05:57,056\n否则 就返回X乘以\nOtherwise, it will be the result of multiplying x\n\n1080\n01:05:57,264 --> 01:05:59,264\n用给定的指数过程G\nby the exponentiation procedure given to me\n\n1081\n01:06:00,176 --> 01:06:02,448\n计算(G X (- N 1))\nwith x and n minus one as arguments.\n\n1082\n01:06:03,470 --> 01:06:04,784\n因此如果G能够\nSo if this computed the correct\n\n1083\n01:06:04,816 --> 01:06:06,300\n正确计算X^(N-1)\nexponentiation for n minus one,\n\n1084\n01:06:07,872 --> 01:06:11,280\n那么这个表达式就能正确计算X^N\nthen this would be the correct exponentiation for exponent n,\n\n1085\n01:06:12,176 --> 01:06:14,416\n所以整个就会是一个正确的求指数过程\nso this would have been the right exponentiation procedure.\n\n1086\n01:06:17,500 --> 01:06:19,824\n因此 我在这里真正想指出的是\nSo what I really want to say here is\n\n1087\n01:06:21,020 --> 01:06:32,448\n过程EXPT是函数F的不动点\nE-X-P-T is a fixed point of f.\n\n1088\n01:06:36,990 --> 01:06:38,352\n现在我们的问题在于\nNow our problem is\n\n1089\n01:06:38,352 --> 01:06:39,680\n不动点可能不止一个\nthere might be more than one fixed point.\n\n1090\n01:06:40,060 --> 01:06:42,192\n也可能没有不动点\nThere might be no fixed points.\n\n1091\n01:06:43,270 --> 01:06:44,810\n所以我们必须求出不动点\nI have to go hunting for the fixed points.\n\n1092\n01:06:48,224 --> 01:06:49,376\n需要来解这个方程\nGot to solve this equation.\n\n1093\n01:06:52,160 --> 01:06:54,288\n求不动点的方法有很多种\nWell there are various ways to hunt for fixed points.\n\n1094\n01:06:55,580 --> 01:06:57,088\n本门课程的第一节课\nOf course, the one we played with\n\n1095\n01:06:57,248 --> 01:07:01,160\n我们就用余弦函数做了演示\nat the beginning of this term worked for cosine.\n\n1096\n01:07:02,736 --> 01:07:07,690\n先把你的计算器调成弧度制\nGoing to. Go into radians mode on your calculator\n\n1097\n01:07:07,856 --> 01:07:10,512\n然后一直按COS键\nand push cosine, and just keep doing it,\n\n1098\n01:07:11,840 --> 01:07:15,456\n最后数字会稳定在0.73、0.74左右\nand you get to some number which is about 0.73 or 0.74.\n\n1099\n01:07:16,090 --> 01:07:17,184\n我记不清是哪个了\nI can't remember which.\n\n1100\n01:07:20,576 --> 01:07:22,640\n通过迭代一个过程\nBy iterating a procedure, which has\n\n1101\n01:07:22,816 --> 01:07:24,400\n我们不断迭代\nBy iterating a function,\n\n1102\n01:07:25,600 --> 01:07:27,168\n想要寻找不动点的函数\nwhose fixed point I'm searching for,\n\n1103\n01:07:27,500 --> 01:07:31,136\n有时候 它就会收敛在一个点上\nit is sometimes the case that that function will converge\n\n1104\n01:07:31,872 --> 01:07:33,088\n这就是不动点\nin producing the fixed point.\n\n1105\n01:07:33,770 --> 01:07:35,440\n碰碰运气\nI think we luck out in this case,\n\n1106\n01:07:36,448 --> 01:07:37,216\n来试试这种方法\nso let's look for it.\n\n1107\n01:07:39,910 --> 01:07:46,288\n来看这张幻灯片\nLet's look at this overhead, this slide.\n\n1108\n01:07:48,030 --> 01:07:51,712\n考虑这么一连串的过程\nConsider the following sequence of procedures.\n\n1109\n01:07:56,400 --> 01:07:57,792\n这里的E0\ne0 over here\n\n1110\n01:07:59,248 --> 01:08:01,632\n这个E0过程什么也不做\nthe procedure which does nothing at all.\n\n1111\n01:08:02,890 --> 01:08:05,104\n无论你给它传递什么参数\nIt's the procedure which produces an error\n\n1112\n01:08:05,104 --> 01:08:06,240\n它都会产生ERROR\nfor any arguments you give it.\n\n1113\n01:08:07,780 --> 01:08:09,030\n基本上没什么用\nIt's basically useless.\n\n1114\n01:08:14,480 --> 01:08:20,080\n然而 我可以做近似\nWell, however, I can make an approximation.\n\n1115\n01:08:20,080 --> 01:08:23,936\n让我们考虑下 指数过程的最差近似\nLet's consider it the worst possible approximation to exponentiation,\n\n1116\n01:08:24,736 --> 01:08:25,536\n因为它什么也做不了\nbecause it does nothing.\n\n1117\n01:08:26,990 --> 01:08:29,680\n假设我调用F\nWell, supposing I substituted e0\n\n1118\n01:08:30,352 --> 01:08:33,260\n用E0去代换G\nfor g by calling f,\n\n1119\n01:08:33,792 --> 01:08:36,304\n这里 G就被代换为了E0\nas you see over here on e0.\n\n1120\n01:08:37,380 --> 01:08:39,776\n所以在这里就是E0\nSo you see over here, have e0 there.\n\n1121\n01:08:40,848 --> 01:08:42,352\n那么E1又成了什么呢？\nThen gee, what's e1?\n\n1122\n01:08:43,630 --> 01:08:46,032\n如果用E1来计算X^0\ne1 is a procedure which exponentiate things\n\n1123\n01:08:46,672 --> 01:08:48,784\n没什么问题\nto the 0th power, with no trouble.\n\n1124\n01:08:49,600 --> 01:08:50,752\n它返回的结果是正确的\nIt gets the right answer,\n\n1125\n01:08:51,050 --> 01:08:52,352\n任何数的0次幂都是1\nanything to the zero is one,\n\n1126\n01:08:52,688 --> 01:08:54,250\n然而计算其它次幂就会出错\nand it makes an error on anything else.\n\n1127\n01:08:57,390 --> 01:09:01,568\n现在如果我用E1来调用F\nWell, now what if I take e1\n\n1128\n01:09:02,304 --> 01:09:07,408\n把G代换为E1 会发生什么？\nand substituted it for g by calling f on e1?\n\n1129\n01:09:09,580 --> 01:09:11,180\n这样的话\nOh gosh,\n\n1130\n01:09:12,016 --> 01:09:15,024\n我就会得到这个二元过程\nI have here a procedure of two arguments.\n\n1131\n01:09:15,670 --> 01:09:16,848\n想一想 E1这个过程\nNow remember e1\n\n1132\n01:09:16,960 --> 01:09:19,664\n只能正确计算X^0\nwas appropriate for taking exponentiations of 0,\n\n1133\n01:09:21,472 --> 01:09:23,376\n它只能计算0次幂\nfor raising to the 0 exponent.\n\n1134\n01:09:24,200 --> 01:09:25,008\n所以这里\nSo here,\n\n1135\n01:09:25,520 --> 01:09:27,280\n如果N为0 结果就是1\nif is n is 0, the result is one,\n\n1136\n01:09:27,296 --> 01:09:28,672\nE2的这部分也正确\nso this guy is good for that too.\n\n1137\n01:09:29,520 --> 01:09:32,016\n然而 我可以通过把0次幂乘以X\nHowever, I can use something for raising to the 0th power\n\n1138\n01:09:32,512 --> 01:09:35,264\n来计算1次幂\nto multiply it by x to raise something to the first power.\n\n1139\n01:09:35,979 --> 01:09:39,670\n所以E2可以正确计算0次幂和1次幂\nSo e2 is good for both power 0 and 1.\n\n1140\n01:09:41,600 --> 01:09:41,920\n对吧？\nOK?\n\n1141\n01:09:43,712 --> 01:09:46,672\nE3的构造过程和E2是类似的\nAnd e3 is constructed from e2 in the same way.\n\n1142\n01:09:47,890 --> 01:09:50,240\n当然 E3具有同样的参数\nAnd e3, of course, by the same argument\n\n1143\n01:09:50,320 --> 01:09:53,370\n能够正确计算0、1、2次幂\nis good for powers 0, one, and two.\n\n1144\n01:09:55,120 --> 01:09:55,408\n对吧？\nOK?\n\n1145\n01:09:56,090 --> 01:09:59,080\n因此我就不加证明地告诉你结论\nAnd so I will assert for you, without proof,\n\n1146\n01:09:59,664 --> 01:10:01,728\n因为这个证明过程太难了\nbecause the proof is horribly difficult.\n\n1147\n01:10:02,520 --> 01:10:03,600\n这种事情\nAnd that's the sort of thing that\n\n1148\n01:10:03,632 --> 01:10:06,368\n是由人们所谓“指称语义学家”完成的\npeople called denotational semanticists do.\n\n1149\n01:10:06,590 --> 01:10:07,648\n这个伟大的想法\nI suppose it was invented\n\n1150\n01:10:07,872 --> 01:10:10,592\n应该是由Scott和Strachey提出的\nThis great idea was invented by Scott and Strachey.\n\n1151\n01:10:11,648 --> 01:10:16,320\n他们是非常著名的数学家\nAh, sort of. They're very famous mathematician types\n\n1152\n01:10:16,864 --> 01:10:21,216\n他们发明了这些程序的解释方式\nwho invented the interpretation for these programs that we have\n\n1153\n01:10:22,368 --> 01:10:24,000\n就是我刚才讲的那些\nthat I'm talking to you about right now.\n\n1154\n01:10:24,240 --> 01:10:26,176\n他们通过拓扑学的方法证明了\nAnd they proved, by topology\n\n1155\n01:10:27,040 --> 01:10:29,328\n在我们刚才那种情况下\nthat there is such a fixed point\n\n1156\n01:10:29,824 --> 01:10:31,264\n不动点是存在的\nin the cases that we want.\n\n1157\n01:10:32,220 --> 01:10:33,248\n这个结论就是：\nBut the assertion is\n\n1158\n01:10:33,400 --> 01:10:44,240\n当N趋近于无穷时 EXPT是E(N)的极限\nE-X-P-T is limit as n goes to infinity of em.\n\n1159\n01:10:45,520 --> 01:10:47,900\n我们是通过下面这种方式来构造这个极限的\nand And that we've constructed this by the following way.\n\n1160\n01:10:50,520 --> 01:10:55,664\nEXPT=(F (F (F (F ....\n--is Well, it's f of, f of, f of, f of, f of--\n\n1161\n01:10:57,616 --> 01:11:00,192\n(F 丄)\nf applied to anything at all.\n\n1162\n01:11:01,120 --> 01:11:02,464\n它是什么都无所谓\nIt didn't matter what that was,\n\n1163\n01:11:03,184 --> 01:11:05,008\n因为它总会生成一个错误\nbecause, in fact, this always produces an error.\n\n1164\n01:11:07,456 --> 01:11:08,416\n（闭合括号中）\nApplied to this--\n\n1165\n01:11:12,896 --> 01:11:14,480\n这是F无穷嵌套调用\nThat's by infinite nesting of f's.\n\n1166\n01:11:16,380 --> 01:11:17,712\n现在我们的问题\nSo now my problem\n\n1167\n01:11:18,224 --> 01:11:19,760\n又变成了如何构造出无穷调用\nis to make some infinite things.\n\n1168\n01:11:22,590 --> 01:11:24,080\n我们需要它们\nWe need some infinite things.\n\n1169\n01:11:24,920 --> 01:11:26,256\n我怎样才能把F\nHow am I going to nest up an f\n\n1170\n01:11:26,560 --> 01:11:27,808\n嵌套无穷层呢？\nan infinite number of times?\n\n1171\n01:11:28,980 --> 01:11:30,128\n我得把它构造出来\nI'd better construct this.\n\n1172\n01:11:32,380 --> 01:11:32,930\n好吧 我不知道\nWell, I don't know.\n\n1173\n01:11:32,930 --> 01:11:34,320\n到底怎么样构建一个无穷循环呢？\nHow would I make an infinite loop at all?\n\n1174\n01:11:34,810 --> 01:11:36,320\n我们先来看个非常简单的无穷循环\nLet's take a very simple infinite loop,\n\n1175\n01:11:36,576 --> 01:11:38,340\n能想到的最简单的无穷循环\nthe simplest infinite loop imaginable.\n\n1176\n01:11:43,550 --> 01:11:47,552\n把这样一个参数为X的函数过程\nIf I were to take that procedure of one argument x\n\n1177\n01:11:48,000 --> 01:11:49,792\n过程体是(X X)\nwhich applies x to x\n\n1178\n01:11:53,552 --> 01:11:53,920\n看到了吧？\nOK?\n\n1179\n01:11:55,056 --> 01:11:58,416\n应用在一个参数为X过程上\nand apply that to the procedure of one argument x\n\n1180\n01:11:59,360 --> 01:12:01,056\n后者的过程体也是(X X)\nwhich applies x to x,\n\n1181\n01:12:04,832 --> 01:12:06,000\n这就形成了一个无穷循环\nthen this is an infinite loop.\n\n1182\n01:12:07,216 --> 01:12:09,312\n这个循环之所以是无穷的\nThe reason why this is an infinite loop is as follows.\n\n1183\n01:12:09,980 --> 01:12:11,312\n是因为\nThe way I understand this\n\n1184\n01:12:11,520 --> 01:12:13,696\n我用实际参数代换掉\nis I substitute the argument\n\n1185\n01:12:14,224 --> 01:12:16,592\n过程体的形式参数\nfor the formal parameter in the body.\n\n1186\n01:12:18,850 --> 01:12:21,600\n这样做了以后 这里的每个X\nBut if I do that, I take for each of these x's,\n\n1187\n01:12:22,400 --> 01:12:23,760\n都被代换为了这个\nI substitute one of these,\n\n1188\n01:12:24,368 --> 01:12:26,960\n相当于把最初的表达式又复制了一遍\nmaking a copy of the original expression I just started with,\n\n1189\n01:12:28,352 --> 01:12:29,376\n这就是最简单的无穷循环\nthe simplest infinite loop.\n\n1190\n01:12:35,440 --> 01:12:39,296\n现在 我要介绍一个特殊的运算符\nNow I want to tell you about a particular operator\n\n1191\n01:12:40,384 --> 01:12:43,090\n它是通过对这个无穷循环稍作修改而来\nwhich is constructed by a perturbation from this infinite loop.\n\n1192\n01:12:46,960 --> 01:12:47,920\n我把它记作“Y”\nI'll call it y.\n\n1193\n01:12:50,896 --> 01:12:55,820\n它的全称是：Curry的矛盾Y组合子\nOK y -- This is called Curry's Paradoxical Combinator of y\n\n1194\n01:12:56,624 --> 01:12:58,992\n这是用二十世纪三十年代的逻辑学家\nafter a fellow by the name of Curry,\n\n1195\n01:12:59,344 --> 01:13:01,856\nCurry的名字来命名的\nwho was a logician of the 1930s also.\n\n1196\n01:13:04,480 --> 01:13:06,880\nY组合子是一个参数为f的过程\nAnd if I have a procedure of one argument f,\n\n1197\n01:13:08,176 --> 01:13:09,330\n它的过程体是什么呢？\nwhat's it going to have in it?\n\n1198\n01:13:09,330 --> 01:13:11,200\n它的内部是某种无穷循环\nIt's going to have a kind of infinite loop in it,\n\n1199\n01:13:11,984 --> 01:13:15,472\n是一个参数为x的过程\nwhich is that procedure of one argument x\n\n1200\n01:13:15,952 --> 01:13:18,800\n它调用(f (x x))\nwhich applies f to x of x,\n\n1201\n01:13:21,630 --> 01:13:24,750\n这个过程应用在一个参数为X的过程上\napplied to that procedure of one argument x,\n\n1202\n01:13:25,104 --> 01:13:27,344\n后者调用(f (x x))\nwhich applies f to f of x.\n\n1203\n01:13:32,300 --> 01:13:33,136\n这个是怎么运作的？\nNow what's this do?\n\n1204\n01:13:34,800 --> 01:13:36,060\n假设执行(Y F)\nSuppose we apply y to F.\n\n1205\n01:13:41,312 --> 01:13:42,576\n这非常简单\nOK? Well, that's easy enough.\n\n1206\n01:13:43,152 --> 01:13:44,624\n这里大写的F跟那边的是同一个\nThat's this capital F over here.\n\n1207\n01:13:46,910 --> 01:13:48,160\n在这里 很简单\nWell, the easiest thing to say there\n\n1208\n01:13:48,304 --> 01:13:49,920\n我把F代换到这里来\nis, I substitute F for here.\n\n1209\n01:13:55,320 --> 01:13:57,072\n基本上 我就会得到\nSo that's going to give me, basically--\n\n1210\n01:13:58,750 --> 01:14:00,848\n因为我待会儿要用这个表达式\nbecause then I'm going to substitute this\n\n1211\n01:14:01,456 --> 01:14:02,800\n代换这里的x\nfor x in here.\n\n1212\n01:14:04,176 --> 01:14:05,232\n这里就是(F\nThat F of\n\n1213\n01:14:08,970 --> 01:14:10,096\n我还是把这步写出来吧\nLet me actually do it in steps,\n\n1214\n01:14:10,224 --> 01:14:11,456\n这样你们就能看得更全面\nso you can see it completely.\n\n1215\n01:14:11,920 --> 01:14:14,272\n我会非常小心 好吗？\nI'm going to be very careful. OK?\n\n1216\n01:14:15,020 --> 01:14:18,256\n这里是 ((LAMBDA (x)\nThis is open, open, lambda of x ,\n\n1217\n01:14:19,088 --> 01:14:22,112\n(F (x x))\ncapital F, x, x,\n\n1218\n01:14:26,880 --> 01:14:35,552\n把它应用到自身 (LAMBDA (x) (F (x x)))\napplied to itself, F of x of x.\n\n1219\n01:14:37,910 --> 01:14:39,664\n把这个表达式代换进去\nSubstituting this for this in here,\n\n1220\n01:14:40,064 --> 01:14:40,912\n就得到\nthis is\n\n1221\n01:14:43,130 --> 01:14:48,352\n把这个代进去 得到什么呢？\nF applied to-- what is it-- substituting this in here\n\n1222\n01:14:48,656 --> 01:14:54,810\n(F (LAMBDA (x) (F (x x)))\nopen, open, lambda of x, F, of x and x,\n\n1223\n01:14:57,072 --> 01:14:58,176\n应用到\napplied to\n\n1224\n01:14:59,180 --> 01:15:06,480\n(LAMBDA (x) (F (x x))))\nlambda of x, F of x of x, F,\n\n1225\n01:15:06,992 --> 01:15:10,448\n（闭合括号中）\nlambda, pair, F.\n\n1226\n01:15:11,510 --> 01:15:12,400\n哇 这又是什么？\nOh, but what is this?\n\n1227\n01:15:13,420 --> 01:15:16,352\n我刚才计算的这一部分\nThis thing over here that I just computed,\n\n1228\n01:15:17,136 --> 01:15:18,560\n就是这里的这部分\nis this thing over here.\n\n1229\n01:15:20,192 --> 01:15:21,840\n只不过它被包在另一个F里面\nBut I just wrapped another F around it.\n\n1230\n01:15:23,370 --> 01:15:24,672\n因此 通过把Y应用在F上\nSo by applying y to F,\n\n1231\n01:15:24,688 --> 01:15:26,224\n我构造出了F的无穷嵌套\nI make an infinite series of F's.\n\n1232\n01:15:27,850 --> 01:15:29,450\n我如果让它一直这样进行下去\nIf I just let this run forever,\n\n1233\n01:15:29,696 --> 01:15:31,776\n我在外层就会得到越来越多的F\nI'll just keep making more and more F's outside.\n\n1234\n01:15:33,170 --> 01:15:34,800\n我运行一个无用的循环\nI ran an infinite loop which is useless,\n\n1235\n01:15:35,200 --> 01:15:37,024\n但内部是无用的并不重要\nbut it doesn't matter that the inside is useless.\n\n1236\n01:15:39,856 --> 01:15:47,856\n因此 我们有 (Y F)=(F (Y F))\nOK? So y of F is F applied to y of F.\n\n1237\n01:15:50,336 --> 01:15:52,144\nY组合子十分神奇\nSo y is a magical thing\n\n1238\n01:15:53,856 --> 01:15:56,256\n如果把它应用于某个函数\nwhich, when applied to some function,\n\n1239\n01:15:57,376 --> 01:16:00,384\n它就会返回这个函数的不动点\nproduces the object which is the fixed point of that function,\n\n1240\n01:16:01,696 --> 01:16:04,256\n当然是在不动点存在的前提下\nif it exists, and if this all works.\n\n1241\n01:16:07,910 --> 01:16:10,080\n这是因为 如果我把(Y F)带入F\nBecause, indeed, if I take y of F\n\n1242\n01:16:10,128 --> 01:16:11,120\n结果还是(Y F)\nI get y of F out.\n\n1243\n01:16:16,240 --> 01:16:18,864\n现在我想让你们在\nNow I want you to think this in terms of\n\n1244\n01:16:19,856 --> 01:16:22,384\nEVAL-APPLY解释器方面思考一下\nthe eval-apply interpreter for a bit.\n\n1245\n01:16:23,860 --> 01:16:26,272\n我在这里写了一大堆递归方程组\nI wrote down a whole bunch of recursion equations out there.\n\n1246\n01:16:28,540 --> 01:16:30,224\n那些联立方程组像\nThey're simultaneous in the same way\n\n1247\n01:16:30,224 --> 01:16:31,232\n这些方程一样联立起来\nthese are simultaneous equations.\n\n1248\n01:16:31,470 --> 01:16:33,310\n但EXPT不是联立方程\nExponentiation was not a simultaneous equation.\n\n1249\n01:16:33,310 --> 01:16:35,792\n只是一个需要我赋义的变量\nIt was only one variable I was looking for a meaning for.\n\n1250\n01:16:38,150 --> 01:16:40,768\n而Lisp则是某个过程的不动点\nBut what Lisp is is the fixed point of the process\n\n1251\n01:16:40,816 --> 01:16:42,570\n对这个过程来说 如果我知道Lisp的定义\nthat's which says, if I knew what Lisp was\n\n1252\n01:16:42,592 --> 01:16:46,512\n然后在递归方程等号的右边\nand substituted it in for eval, and apply, and so on,\n\n1253\n01:16:46,590 --> 01:16:49,792\n用它来代换EVAL、APPLY等变量\non the right hand sides of all those recursion equations,\n\n1254\n01:16:50,940 --> 01:16:53,968\n如果它是一个良好定义的Lisp的话\nthen if it was a real good Lisp, is a real one,\n\n1255\n01:16:54,368 --> 01:16:56,304\n那么递归方程等号左边 也是一个良好定义的Lisp\nthen the left hand side would also be Lisp.\n\n1256\n01:16:58,220 --> 01:16:59,824\n这样 那个定义就讲得通了\nSo I made sense of that definition.\n\n1257\n01:17:02,420 --> 01:17:05,410\n不过是否有解却不太明显\nNow whether or not there's an answer isn't so obvious.\n\n1258\n01:17:05,696 --> 01:17:06,752\n我也说不清\nI can't attack that.\n\n1259\n01:17:07,740 --> 01:17:09,216\n现在我要介绍的论证\nNow these arguments that I'm giving you now\n\n1260\n01:17:09,264 --> 01:17:10,272\n相当危险\nare quite dangerous.\n\n1261\n01:17:10,660 --> 01:17:11,648\n具体看这里\nLet's look over here.\n\n1262\n01:17:13,056 --> 01:17:14,610\n这些是关于极限的论证\nOn the. These are limit arguments.\n\n1263\n01:17:14,610 --> 01:17:15,392\n我们要讨论的极限\nWe're talking about limits,\n\n1264\n01:17:15,456 --> 01:17:17,680\n是微积分或者拓扑学的概念\nand it's really calculus, or topology,\n\n1265\n01:17:17,872 --> 01:17:20,032\n或者说是类似的 数学分析中的概念\nor something like that, a kind of analysis.\n\n1266\n01:17:20,768 --> 01:17:23,380\n这个论证是你们都承认的\nOK？Now here's an argument that you all believe.\n\n1267\n01:17:23,380 --> 01:17:25,296\n我想让你们意识到\nAnd I want to make sure you realize\n\n1268\n01:17:25,424 --> 01:17:27,664\n我可以把你们耍得团团转\nthat I could be bullshitting you.\n\n1269\n01:17:28,864 --> 01:17:30,480\n准备好了吗？ 这是什么？\nAlright? What is this?\n\n1270\n01:17:34,250 --> 01:17:39,520\nu = 1 + 1/2 + 1/4 + .......\nu is the sum of 1/2, 1/4, and 1/8, and so on,\n\n1271\n01:17:39,744 --> 01:17:41,328\n这是几何级数求和\nthe sum of a geometric series.\n\n1272\n01:17:42,820 --> 01:17:44,688\n当然 我也可以耍点小把戏\nAnd, of course, I could play a game here.\n\n1273\n01:17:44,820 --> 01:17:47,570\nu - 1 = 1/2 + 1/4 + 1/8 ......\nu minus one is 1/2, plus 1/4, plus 1/8, and so on.\n\n1274\n01:17:51,904 --> 01:17:54,464\n这里我可以\nBut now if I multiple. What I could do here--\n\n1275\n01:17:56,096 --> 01:17:57,936\n糟糕了 这里漏掉了括号\nOoops. There is a parentheses error here.\n\n1276\n01:17:58,920 --> 01:18:01,456\n这里应该是\nBut I can put here two times u minus one\n\n1277\n01:18:01,744 --> 01:18:03,990\n2(u - 1) = 1 + 1/2 + 1/4 + 1/8 ........\nis one plus 1/2, plus 1/4, plus 1/8.\n\n1278\n01:18:07,570 --> 01:18:08,544\n这里能修改一下吗？\nCan I fix that?\n\n1279\n01:18:14,010 --> 01:18:16,430\n哦 可以\nYes, well.\n\n1280\n01:18:18,192 --> 01:18:18,656\n看到了吗？\nOK?\n\n1281\n01:18:19,520 --> 01:18:20,640\n这样 我就得到\nBut that gives me back\n\n1282\n01:18:23,536 --> 01:18:26,640\n2(u - 1) = u\ntwo times u minus one is u,\n\n1283\n01:18:27,808 --> 01:18:29,584\n因此我们推断出 u=2\ntherefore, we conclude that u is two.\n\n1284\n01:18:30,300 --> 01:18:31,376\n这是正确的\nAnd this actually is true.\n\n1285\n01:18:31,968 --> 01:18:33,328\n这个推理过程没有问题\nThere's no problem like that.\n\n1286\n01:18:34,048 --> 01:18:37,552\n但如果我要是做点别的什么呢？\nBut supposing I did something different.\n\n1287\n01:18:38,540 --> 01:18:39,488\n假设我要求和的式子\nSupposing I start up with something\n\n1288\n01:18:39,504 --> 01:18:41,200\n明显没有和\nwhich manifestly has no sum.\n\n1289\n01:18:41,568 --> 01:18:46,992\nv = 1 + 2 + 4 + ........\nv is one, plus two, plus four, plus 8, plus dot, dot, dot. OK?\n\n1290\n01:18:47,390 --> 01:18:51,392\nv - 1 = 2 + 4 + 8 + ......\nWell, v minus one is surely two, plus four, plus eight, plus dot, dot, dot. Right?\n\n1291\n01:18:52,272 --> 01:18:56,032\n(v - 1)/2 = v\nv minus one over two, gee, that looks like v again.\n\n1292\n01:18:57,410 --> 01:19:00,544\n这里我就可以推断出\nFrom that I should be able to conclude that--\n\n1293\n01:19:01,376 --> 01:19:02,912\n显然这里又写错了\nthat's also wrong, apparently.\n\n1294\n01:19:03,070 --> 01:19:04,510\n应该是 v = -1\nv equals minus one.\n\n1295\n01:19:12,450 --> 01:19:13,824\n这里应该是-1\nThat should be a minus one.\n\n1296\n01:19:15,280 --> 01:19:16,912\n这个结论明显是错误的\nAnd that's certainly a false conclusion.\n\n1297\n01:19:22,000 --> 01:19:23,472\n当你处理极限的时候\nSo when you play with limits,\n\n1298\n01:19:24,224 --> 01:19:27,856\n在某种方式下可行的论证\narguments that may work in one case\n\n1299\n01:19:29,424 --> 01:19:30,750\n在其它情况下可能又不行了\nthey may not work in some other case.\n\n1300\n01:19:30,750 --> 01:19:31,696\n要多加注意\nYou have to be very careful.\n\n1301\n01:19:32,240 --> 01:19:33,872\n参数必须具有良好的形式\nThe arguments have to be well-formed.\n\n1302\n01:19:36,144 --> 01:19:39,232\n但我不清楚 通常来说\nAnd I don't know, in general,\n\n1303\n01:19:39,856 --> 01:19:41,936\n像这样的论证有什么样的要求\nwhat the story is about arguments like this.\n\n1304\n01:19:43,270 --> 01:19:45,248\n我们要研习一大堆拓扑学文献来寻找答案\nWe can read a pile of topology and find out.\n\n1305\n01:19:46,272 --> 01:19:48,640\n但是至少你们现在理解了\nBut, surely, at least you understand now,\n\n1306\n01:19:49,104 --> 01:19:51,136\n为什么我们在黑板上写的这些东西\nwhy it might be some meaning\n\n1307\n01:19:51,152 --> 01:19:52,768\n是有一定语义的\nto the things we've been writing on the blackboard.\n\n1308\n01:19:53,664 --> 01:19:55,616\n你们也理解了它的语义\nAnd you understand what that might mean.\n\n1309\n01:19:56,480 --> 01:19:58,352\n我想现在是时候\nSo, I suppose, it's almost about time\n\n1310\n01:19:59,070 --> 01:20:03,840\n祝贺你们成为\nfor you to merit being made a member\n\n1311\n01:20:04,280 --> 01:20:05,552\n神圣的递归秩序中的\nof the grand recursive order\n\n1312\n01:20:05,568 --> 01:20:07,040\n一名LAMBDA演算黑客了\nof lambda calculus hackers.\n\n1313\n01:20:08,848 --> 01:20:10,176\n这是我们的徽章\nI would. This is the badge.\n\n1314\n01:20:10,820 --> 01:20:12,544\n因为你已经理解了\nBecause you now understand, for example,\n\n1315\n01:20:13,400 --> 01:20:15,200\n它上面的那句话\nwhat it says at the very top,\n\n1316\n01:20:16,896 --> 01:20:18,416\n(Y F) = (F (Y F))\ny F equals F y F.\n\n1317\n01:20:21,040 --> 01:20:21,664\n这节课讲完了\nThank you.\n\n1318\n01:20:21,856 --> 01:20:22,752\n有什么问题吗？\nAre there any questions?\n\n1319\n01:20:24,710 --> 01:20:25,150\nLev 请说\nYes, Lev.\n\n1320\n01:20:25,370 --> 01:20:27,392\n学生：目前的状况来看\nAUDIENCE: With this, it seems that\n\n1321\n01:20:27,408 --> 01:20:30,224\n正如你指出的那样 我们不再需要DEFINE\nthere's no need to define, as you imply,\n\n1322\n01:20:30,240 --> 01:20:32,704\n不需要先存储一个值 以后再用\nto just remember a value, to apply it later.\n\n1323\n01:20:32,992 --> 01:20:33,328\n教授：对\nPROFESSOR: Yeah.\n\n1324\n01:20:33,504 --> 01:20:36,448\n学生：DEFINE在语言中好像有一些副作用\nAUDIENCE: Defines were kind of a side-effect it seemed in the language.\n\n1325\n01:20:36,490 --> 01:20:38,528\n（听不清）并且依赖于时序\n[INTERPOSING] are order dependent.\n\n1326\n01:20:39,300 --> 01:20:42,064\n不用DEFINE 是否消除了副作用？\nDoes this eliminate the side-effect from the.\n\n1327\n01:20:42,280 --> 01:20:44,688\n教授： 实际上\nPROFESSOR: Well. The answer is,\n\n1328\n01:20:44,880 --> 01:20:46,440\n解释器并不是像这样实现的\nthis is not the way these things were implemented.\n\n1329\n01:20:47,520 --> 01:20:47,936\n明白了吧？\nOK?\n\n1330\n01:20:48,920 --> 01:20:53,152\n在实际的实现中 DEFINE这个运算\nDefine, indeed is implemented as an operation\n\n1331\n01:20:53,184 --> 01:20:55,536\n确实修改了环境\nthat actually modifies an environment structure,\n\n1332\n01:20:57,952 --> 01:21:02,336\n改变了执行DEFINE的那个框架\nchanges the frame that the define is executed in.\n\n1333\n01:21:03,690 --> 01:21:06,512\n这样做是有很多原因的\nAnd there are many reasons for that,\n\n1334\n01:21:07,390 --> 01:21:08,640\n其中之一就是\nbut a lot of this has to do with\n\n1335\n01:21:08,672 --> 01:21:10,090\n方便交互式系统\nmaking an interactive system.\n\n1336\n01:21:11,340 --> 01:21:14,128\n就是说 如果你构造了一个系统\nWhat this is saying is that if you've made a system,\n\n1337\n01:21:14,350 --> 01:21:15,200\n而且你知道\nand you know\n\n1338\n01:21:15,420 --> 01:21:16,608\n你不打算进行调试\nand you know you're not going to do any debugging\n\n1339\n01:21:16,608 --> 01:21:17,550\n或之类的事儿\nor anything like that,\n\n1340\n01:21:17,840 --> 01:21:20,720\n你想立马知道所有的东西\nand you know everything there is all at once,\n\n1341\n01:21:20,750 --> 01:21:21,248\n你想知道的是\nand you want to say,\n\n1342\n01:21:21,264 --> 01:21:23,120\n方程组的最终解是什么？\nwhat is the meaning of a final set of equations?\n\n1343\n01:21:24,090 --> 01:21:25,264\n然后系统返回你相应的值\nThis gives you a meaning for it.\n\n1344\n01:21:25,790 --> 01:21:27,456\n但如果想要让系统变成交互式的\nBut in order to make an interactive system,\n\n1345\n01:21:27,456 --> 01:21:28,752\n这样你可以在不影响其它部分的情况下\nwhere you can change the meaning of one\n\n1346\n01:21:28,768 --> 01:21:31,680\n增量式地修改某一部分\nwithout changing everything else, incrementally,\n\n1347\n01:21:32,336 --> 01:21:35,040\n没有DEFINE的话 就不能这么做了\nyou can't do that by implementing it this way.\n\n1348\n01:21:40,990 --> 01:21:41,248\n你说\nYes.\n\n1349\n01:21:42,304 --> 01:21:44,256\n学生：就是那张“危险”的幻灯片\nAUDIENCE: Another question on your danger slide.\n\n1350\n01:21:44,650 --> 01:21:47,136\n好像你举的两个例子\nIt seemed that the two examples that you gave\n\n1351\n01:21:47,160 --> 01:21:49,070\n与其收敛与否有关系？\nhad to do with convergence and non-convergence?\n\n1352\n01:21:49,184 --> 01:21:49,568\n教授：是的\nPROFESSOR: Right.\n\n1353\n01:21:50,300 --> 01:21:52,624\n学生：函数理论中是否有\nAUDIENCE: And that may or may not have something to do with\n\n1354\n01:21:52,760 --> 01:21:54,688\n像线性系统\nwith function theory in a way which\n\n1355\n01:21:54,720 --> 01:21:56,600\n或者非线性系统中的\nwould lead you to think of it in terms of linear systems,\n\n1356\n01:21:57,744 --> 01:21:59,008\n那种思考方式\nor non-linear systems.\n\n1357\n01:21:59,344 --> 01:22:01,760\n函数的收敛性能否先验地知道\nHow does this convergence relate to being able to\n\n1358\n01:22:02,352 --> 01:22:05,536\n哪些属性可能被违反？\nsee a priori what properties of that might be violated?\n\n1359\n01:22:05,792 --> 01:22:06,576\n教授：我不知道\nPROFESSOR: I don't know.\n\n1360\n01:22:07,680 --> 01:22:10,096\n我也不知道它需要什么条件\nThe answer is, I don't know under what circumstances.\n\n1361\n01:22:10,610 --> 01:22:12,048\n我不知道怎么在一节课内\nI don't know how to translate that\n\n1362\n01:22:12,528 --> 01:22:14,736\n就给你们讲清楚\ninto less than an hour of talk more.\n\n1363\n01:22:16,910 --> 01:22:18,480\n有什么条件来判别它们\nWhat are the conditions under which,\n\n1364\n01:22:18,864 --> 01:22:20,768\n是否收敛？\nfor which we know that these things converge?\n\n1365\n01:22:22,864 --> 01:22:23,312\n确实\nAnd indeed,\n\n1366\n01:22:23,328 --> 01:22:26,350\n这些都是为了告诉你 基于收敛的论证\nall that was telling you that arguments that are based on convergence\n\n1367\n01:22:28,240 --> 01:22:29,472\n都不可靠\nare flaky\n\n1368\n01:22:29,664 --> 01:22:31,584\n如果你事先不知道收敛性的话\nif you don't know the convergence beforehand.\n\n1369\n01:22:32,810 --> 01:22:34,208\n你可能做出错误的论证\nYou can make wrong arguments.\n\n1370\n01:22:34,440 --> 01:22:37,312\n你可以先假设知道了答案 然后进行演绎\nYou can make deductions, as if you know the answer,\n\n1371\n01:22:37,392 --> 01:22:39,936\n看它会不会产生什么明显的矛盾\nand not be stopped somewhere by some obvious contradiction.\n\n1372\n01:22:40,976 --> 01:22:42,288\n学生：我们是否可以说\nAUDIENCE: So can we say then that\n\n1373\n01:22:42,336 --> 01:22:44,880\n如果数学表达式F收敛\nif F is a convergent mathematical expression,\n\n1374\n01:22:45,008 --> 01:22:47,360\n那么它的递归性质就--\nthen the recursion property can be--\n\n1375\n01:22:47,584 --> 01:22:51,296\n教授：我认为 在技术上有一类F\nPROFESSOR: Well, I think there's a technical kind of F,\n\n1376\n01:22:52,120 --> 01:22:54,224\n通过一些技术准则\nOK? There is a technical description\n\n1377\n01:22:54,240 --> 01:22:55,900\n我们可以找到这样的F\nof those F's that have the property\n\n1378\n01:22:55,984 --> 01:23:01,312\n当你像这样迭代地应用它们时\nthat when you iteratively apply them like this,\n\n1379\n01:23:01,520 --> 01:23:02,256\n它一定会收敛\nyou converge.\n\n1380\n01:23:03,020 --> 01:23:06,512\n这类准则包括：单调、连续\nThings that are monotonic, and continuous,\n\n1381\n01:23:07,328 --> 01:23:07,952\n我想想\nOK?\n\n1382\n01:23:08,384 --> 01:23:09,370\n我把其它的准则忘了\nand I forgot what else.\n\n1383\n01:23:09,370 --> 01:23:11,136\n还有一些列像这样的\nThere is a whole bunch of little conditions like that\n\n1384\n01:23:11,680 --> 01:23:12,992\n判别准则\nwhich have this property.\n\n1385\n01:23:13,430 --> 01:23:16,000\n现在的难点是 给定F然后进行推理\nNow the real problem is deducing from looking at the F,\n\n1386\n01:23:16,928 --> 01:23:17,888\n这是F的定义\nits definition here,\n\n1387\n01:23:18,170 --> 01:23:19,660\n它满足这些准则吗？\nwhether not it has those properties,\n\n1388\n01:23:20,272 --> 01:23:21,328\n这很难判断\nand that's very hard.\n\n1389\n01:23:22,010 --> 01:23:24,000\n那些准则都很简单得可以写下来\nThe properties are easy. You can write them down.\n\n1390\n01:23:24,580 --> 01:23:26,320\n你可以看Joe Stoy写的一本书\nYou can look in a book by Joe Stoy.\n\n1391\n01:23:26,672 --> 01:23:29,584\n那本书非常不错\nIt's a great book-- Stoy.\n\n1392\n01:23:32,220 --> 01:23:34,064\n叫做The Scott-Strachey\nIt's called, The Scott-Strachey\n\n1393\n01:23:34,496 --> 01:23:38,460\n《指称语义：基于Scott-Strachey方法》\nThe Scott-Strachey Method of Denotational Semantics,\n\n1394\n01:23:39,552 --> 01:23:40,768\n作者是Joe Stoy\nand it's by Joe Stoy,\n\n1395\n01:23:40,800 --> 01:23:41,760\n由MIT出版社出版\nMIT Press.\n\n1396\n01:23:48,064 --> 01:23:49,888\n他把这一方面讲得非常详细\nAnd he works out all this in great detail,\n\n1397\n01:23:50,208 --> 01:23:51,376\n绝对会让你吓一大跳\nenough to horrify you.\n\n1398\n01:23:55,056 --> 01:23:56,192\n但是这本书仍然值得一读\nBut it really is readable.\n\n1399\n01:24:09,150 --> 01:24:10,080\n好吧 谢谢大家\nOK, well, thank you.\n\n1400\n01:24:11,490 --> 01:24:12,992\n这节课到此为止\nTime for the bigger break, I suppose.\n\n1401\n01:24:14,176 --> 01:24:20,928\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n1402\n01:24:20,920 --> 01:24:34,496\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec7b.srt",
    "content": "﻿1\n00:00:00,010 --> 00:00:01,632\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:01,630 --> 00:00:04,336\n翻译&&时间轴：邓雄飞、张大伟\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:04,384 --> 00:00:07,344\n特别感谢：裘宗燕教授\n\n4\n00:00:07,360 --> 00:00:09,488\n计算机程序的构造和解释\n\n5\n00:00:09,520 --> 00:00:13,664\n元循环求值器 II\nMetacircular Evaluator II\n\n6\n00:00:17,216 --> 00:00:17,968\n教授：目前为止\nPROFESSOR: Well, let's see.\n\n7\n00:00:19,520 --> 00:00:21,296\n我们学的东西都非常有趣\nWhat we did so far was a lot of fun,\n\n8\n00:00:21,520 --> 00:00:23,050\n但它有什么实际的用途吗？\nwas it useful for anything?\n\n9\n00:00:26,330 --> 00:00:27,968\n我想答案是“是的”\nI suppose the answer is going to be yes.\n\n10\n00:00:29,380 --> 00:00:31,920\n这些元循环解释器\nIf these metacircular interpreters\n\n11\n00:00:32,960 --> 00:00:34,608\n非常值得琢磨\nare a valuable thing to play with.\n\n12\n00:00:34,624 --> 00:00:36,176\n我花了大概\nI spend, say\n\n13\n00:00:38,050 --> 00:00:41,856\n曾几何时 我花了半年的功夫\nthere have been times I spend 50% of my time, over a year,\n\n14\n00:00:42,864 --> 00:00:45,264\n用上节课讲的那种\ntrying various design alternatives\n\n15\n00:00:45,760 --> 00:00:48,192\n元循环解释器来试验\nby experimenting with them with metacircular interpreters--\n\n16\n00:00:49,472 --> 00:00:52,016\n各种各样的设计变种\nmetacircular interpreters like the sort you just saw.\n\n17\n00:00:52,570 --> 00:00:54,112\n用元循环解释器是因为\nMetacircular is because\n\n18\n00:00:54,720 --> 00:00:56,944\n它们通过自己定义自己\nthey are defined in terms of themselves in such a way\n\n19\n00:00:56,976 --> 00:00:59,712\n因此被解释的语言也包含了自己\nthat the language they interpret contains itself.\n\n20\n00:01:01,270 --> 00:01:03,872\n这样的解释器是一种的媒介\nSuch interpreters are a convenient medium\n\n21\n00:01:03,888 --> 00:01:05,584\n方便我们探索语言问题\nfor exploring language issues.\n\n22\n00:01:06,800 --> 00:01:09,440\n如果你想添加一个新的FEATURE\nIf you want to try adding a new feature,\n\n23\n00:01:10,512 --> 00:01:12,384\n这就是小菜一碟\nit's sort of a snap, it's easy,\n\n24\n00:01:12,736 --> 00:01:15,104\n你只需要稍作修改 然后观察结果\nyou just do it and see what happens.\n\n25\n00:01:15,490 --> 00:01:17,200\n在尝试了一会儿新语言后\nYou play with that language for a while you say,\n\n26\n00:01:17,240 --> 00:01:18,240\n你可能觉得它不好\ngee, I'm didn't like that,\n\n27\n00:01:18,528 --> 00:01:19,470\n就把它扔到一边去了\nyou throw it away.\n\n28\n00:01:20,960 --> 00:01:23,552\n或者你也想研究\nOr you might want to see what\n\n29\n00:01:23,648 --> 00:01:27,376\n不同绑定策略的差异\nthe difference is if you'd make a slight difference in the binding strategy,\n\n30\n00:01:28,816 --> 00:01:31,904\n或者是一些更复杂的东西\nor some more complicated things that might occur.\n\n31\n00:01:33,720 --> 00:01:35,488\n事实上 这些元循环解释器\nIn fact, these metacircular interpreters\n\n32\n00:01:36,170 --> 00:01:37,888\n非常适合作为交换媒介\nare an excellent medium for people\n\n33\n00:01:38,208 --> 00:01:42,560\n用于承载人们关于语言设计想法\nexchanging ideas about language design,\n\n34\n00:01:43,984 --> 00:01:45,744\n因为它们易于理解\nbecause they're pretty easy to understand,\n\n35\n00:01:46,288 --> 00:01:48,464\n它们短小、紧凑而且简洁\nand they're short, and compact, and simple.\n\n36\n00:01:49,328 --> 00:01:50,800\n如果我有一些点子\nIf I have some idea\n\n37\n00:01:51,536 --> 00:01:53,776\n想让其它人评论一下\nthat I want somebody to criticize\n\n38\n00:01:54,256 --> 00:01:58,320\n比如Indiana大学的Dan Friedman教授\nlike say, Dan Friedman at Indiana,\n\n39\n00:01:59,050 --> 00:02:02,000\n我就编写一个小型元循环解释器\nI'd write a little metacircular interpreter\n\n40\n00:02:02,560 --> 00:02:03,792\n然后给他发一封电子邮件\nsend him some network mail\n\n41\n00:02:04,656 --> 00:02:05,450\n并附上解释器\nwith this interpreter in it.\n\n42\n00:02:05,450 --> 00:02:07,904\n他就可以在计算机上安装并运行\nHe could whip it up on his machine and play with it\n\n43\n00:02:07,920 --> 00:02:09,824\n可能他会觉得这个设计并不好\nand say, that's no good.\n\n44\n00:02:11,940 --> 00:02:13,104\n然后他会给我回一封邮件\nAnd then send it back to me and say,\n\n45\n00:02:13,136 --> 00:02:14,830\n“为什么不试试这个 这个更好一点”\nwell, why don't you try this one, it's a little better.\n\n46\n00:02:16,880 --> 00:02:19,360\n所以我将会讲一些这方面的技术\nSo I want to show you some of that technology.\n\n47\n00:02:20,160 --> 00:02:24,208\n因为在设计你自己的特定用途语言时\nSee, because, really, it's the essential, simple technology\n\n48\n00:02:24,720 --> 00:02:28,688\n这种简单的技术非常重要\nfor getting started in designing your own languages for particular purposes.\n\n49\n00:02:30,790 --> 00:02:32,080\n我们试着先在Lisp中\nLet's start by adding\n\n50\n00:02:32,512 --> 00:02:34,210\n添加一个非常简单的FEATURE\na very simple feature to a Lisp.\n\n51\n00:02:40,640 --> 00:02:44,370\n在这之前 我先来谈谈FEATURE吧\nNow, one thing I want to tell you about is features, before I start.\n\n52\n00:02:49,560 --> 00:02:52,176\n很多语言添加了大量的FEATURE\nThere are many languages that have made a mess of themselves\n\n53\n00:02:53,056 --> 00:02:54,912\n把它们本身搞得混乱不堪\nby adding huge numbers of features.\n\n54\n00:02:56,864 --> 00:02:58,384\n计算机科学家有一个笑话\nComputer scientists have a joke\n\n55\n00:02:59,280 --> 00:03:02,520\n“这不是BUG 这是FEATURE”\nabout bugs that transform it to features all the time.\n\n56\n00:03:05,030 --> 00:03:06,464\n而我宁愿认为\nBut I like to think of it is that\n\n57\n00:03:08,912 --> 00:03:11,440\n很多系统都在遭受着“功能蔓延”的影响\nmany systems suffer from what's called creeping featurism.\n\n58\n00:03:12,820 --> 00:03:13,440\n比方说\nWhich is that\n\n59\n00:03:14,944 --> 00:03:18,160\nGeorge希望系统中有某个FEATURE\nGeorge has a pet feature he'd like in the system,\n\n60\n00:03:18,720 --> 00:03:19,360\n他就加了进来\nso he adds it.\n\n61\n00:03:20,170 --> 00:03:22,144\nHarry也想着\nAnd then Harry says, go says\n\n62\n00:03:22,176 --> 00:03:24,208\n这个系统现在也不是我喜欢的那个了\ngee, this system is no longer what exactly I like,\n\n63\n00:03:24,240 --> 00:03:25,920\n然后加入了自己最喜欢的FEATURE\nso I'm going to add my favorite feature.\n\n64\n00:03:26,640 --> 00:03:30,240\nJim也这样做\nAnd then Jim adds his favorite feature.\n\n65\n00:03:30,832 --> 00:03:31,792\n一段时间过后\nAnd, after a while,\n\n66\n00:03:31,808 --> 00:03:34,816\n操作手册就多达500页\nthe thing has a manual 500 pages long\n\n67\n00:03:35,152 --> 00:03:36,512\n以至于没人能看得懂\nthat no one can understand.\n\n68\n00:03:37,790 --> 00:03:39,328\n有时候也可能只是\nAnd sometimes it's the same person\n\n69\n00:03:39,904 --> 00:03:41,376\n同一个人在添加FEATURE\nwho writes all of these features\n\n70\n00:03:41,392 --> 00:03:43,232\n也会导致同样糟糕的结果\nand produces this terribly complicated thing.\n\n71\n00:03:44,140 --> 00:03:46,096\n很多情况下 比如编辑器\nIn some cases, like editors,\n\n72\n00:03:47,376 --> 00:03:49,120\n具有很多FEATURE就很合理\nit's sort of reasonable to have lots of features,\n\n73\n00:03:50,920 --> 00:03:52,656\n因为你想要能够完成\nbecause there are a lot of things you want to be able to do\n\n74\n00:03:52,688 --> 00:03:53,760\n各种不同的事情\nand many of them arbitrary.\n\n75\n00:03:56,112 --> 00:03:57,296\n但对计算机语言来说\nBut in computer languages,\n\n76\n00:03:57,850 --> 00:03:58,912\n我认为太多的FEATURE\nI think it's a disaster\n\n77\n00:04:00,016 --> 00:04:01,290\n是一个灾难\nto have too much stuff in them.\n\n78\n00:04:04,032 --> 00:04:08,000\n另外 系统也可能变成某种“尖叫的怪物”\nThe other alternative you get into is something called feeping creaturism,\n\n79\n00:04:09,520 --> 00:04:11,392\n假设你有一个盒子\nwhich is where you have a box\n\n80\n00:04:11,808 --> 00:04:15,290\n它有一个鼠标和花哨的显示器\nwhich has a display, a fancy display, and a mouse,\n\n81\n00:04:15,952 --> 00:04:20,048\n这些花哨的IO带来了各种各样的复杂性\nand there is all sorts of complexity associated with all this fancy IO.\n\n82\n00:04:21,010 --> 00:04:22,800\n你的程序语言就变成了\nAnd your computer language becomes\n\n83\n00:04:23,344 --> 00:04:25,376\n阴暗无用的小玩意儿\na dismal, little, tiny thing that barely works\n\n84\n00:04:25,408 --> 00:04:27,904\n这是由计算机上的视窗系统进行的\nbecause of all the swapping, and disk twitching, and so on,\n\n85\n00:04:28,096 --> 00:04:29,360\n内存换页和磁盘抖动所导致的\ncaused by your Window system.\n\n86\n00:04:30,080 --> 00:04:31,824\n每当你使用计算机的时候\nAnd every time you go near the computer,\n\n87\n00:04:31,936 --> 00:04:33,456\n鼠标处理进程就会唤醒\nthe mouse process wakes up and says,\n\n88\n00:04:33,850 --> 00:04:35,950\n你有什么事情要我做的吗？\ngee do you have something for me to do,\n\n89\n00:04:36,144 --> 00:04:37,232\n然后又回去休眠\nand then it goes back to sleep.\n\n90\n00:04:37,440 --> 00:04:39,440\n如果你的胳膊肘不小心碰到了鼠标\nAnd if you accidentally push mouse with you elbow,\n\n91\n00:04:39,616 --> 00:04:42,320\n一大堆烟雾就会从你的电脑出来 类似于这样\na big puff of smoke comes out of your computer and things like that.\n\n92\n00:04:42,940 --> 00:04:45,296\n这就是由于添加FEATURE\nSo two ways to disastrously\n\n93\n00:04:45,552 --> 00:04:47,216\n导致系统不能用的两种典型情况\ndestroy a system by adding features.\n\n94\n00:04:47,500 --> 00:04:49,730\n现在我们要添加的是 一个非常简单的FEATURE\nBut try right now to add a little, simple feature.\n\n95\n00:04:52,608 --> 00:04:53,776\n这个FEATURE非常好\nThis actually is a good one,\n\n96\n00:04:53,856 --> 00:04:56,176\n事实上 Lisp中就有这个FEATURE\nand in fact, real Lisps have it.\n\n97\n00:04:57,250 --> 00:04:58,176\n我们都知道\nAs you've seen,\n\n98\n00:04:59,296 --> 00:05:03,136\n像+、*这样的过程\nthere are procedures like plus and times\n\n99\n00:05:03,376 --> 00:05:04,896\n可以接受不定数目的参数\nthat take any number of arguments.\n\n100\n00:05:05,430 --> 00:05:06,448\n因此我们就可以写\nSo we can write things\n\n101\n00:05:06,576 --> 00:05:10,944\n(+ (* A X X)\nlike the sum of the product of a and x and x,\n\n102\n00:05:12,096 --> 00:05:16,992\n(* B X) C)\nand the product of b and x and c.\n\n103\n00:05:17,540 --> 00:05:18,688\n这里可以看到\nAs you can see here,\n\n104\n00:05:18,928 --> 00:05:21,760\n+有两到三个参数\naddition takes three arguments or two arguments,\n\n105\n00:05:22,304 --> 00:05:24,816\n*也有两到三个参数\nmultiplication takes two arguments or three arguments,\n\n106\n00:05:25,080 --> 00:05:26,768\n不管多少个参数\ntaking numbers of arguments\n\n107\n00:05:26,784 --> 00:05:28,490\n都应该用同样的方式对待\nall of which are to be treated in the same way.\n\n108\n00:05:30,000 --> 00:05:32,176\n支持不定数目的参数\nThis is a valuable thing,\n\n109\n00:05:32,288 --> 00:05:34,010\n这一点非常有用\nindefinite numbers of arguments.\n\n110\n00:05:34,960 --> 00:05:38,416\n而我上节课所讲的Lisp求值器\nYet the particular Lisp system that I show you\n\n111\n00:05:39,232 --> 00:05:41,856\n只能处理固定数目的参数\nis one where the numbers of arguments is fixed,\n\n112\n00:05:42,620 --> 00:05:45,280\n因为我要用BIND过程中的PAIR-UP过程\nbecause I had to match the arguments against the formal parameters\n\n113\n00:05:45,632 --> 00:05:47,920\n让形式参数与实际参数一一对应\nin the binder, where there's a pairup.\n\n114\n00:05:50,810 --> 00:05:53,808\n假如我想能够定义像这样的过程\nWell, I'd like to be able to define new procedures like this\n\n115\n00:05:54,896 --> 00:05:57,328\n它们可以接收任意个数的参数\nthat can have any number of arguments.\n\n116\n00:05:58,752 --> 00:06:00,400\n这个问题有好几部分\nWell there's several parts to this problem.\n\n117\n00:06:01,344 --> 00:06:04,816\n首先是挑选合适的语法描述\nThe first part is coming up with the syntactic specification,\n\n118\n00:06:05,720 --> 00:06:11,216\n我们需要能够标注额外的参数\nsome way of notating the additional arguments,\n\n119\n00:06:12,176 --> 00:06:13,632\n标注那些不知道个数的参数\nof which you don't know how many there are.\n\n120\n00:06:15,480 --> 00:06:16,624\n另外就是\nAnd then there's the other thing,\n\n121\n00:06:17,104 --> 00:06:18,704\n一旦我们标注出来后\nwhich is once we've notated it,\n\n122\n00:06:19,072 --> 00:06:20,784\n我们怎样解释这些个记号\nhow are we going to interpret that notation\n\n123\n00:06:21,740 --> 00:06:23,100\n才能得到\nso as to do the right thing,\n\n124\n00:06:23,856 --> 00:06:25,376\n正确的结果呢？\nwhatever the right thing is?\n\n125\n00:06:26,980 --> 00:06:28,800\n让我们来考虑一种\nSo let's consider an example of a sort of thing\n\n126\n00:06:28,848 --> 00:06:30,272\n我们可能会遇到的情况\nwe might want to be able to do.\n\n127\n00:06:33,070 --> 00:06:34,512\n比如说\nSo an example might be,\n\n128\n00:06:35,424 --> 00:06:37,344\n我想要定义这样的一个过程\nthat I might want to be able to define a procedure\n\n129\n00:06:37,952 --> 00:06:41,360\n它有一个必选参数X\nwhich is a procedure of one required argument x\n\n130\n00:06:42,200 --> 00:06:45,264\n还有个可选参数 -- 或者说一堆参数\nand a non-required -- bunch of arguments,\n\n131\n00:06:45,280 --> 00:06:47,230\n我不知道它们的数目 就记作Y吧\nI don't know how many there are, called y.\n\n132\n00:06:49,090 --> 00:06:50,368\nX是必选的\nSo x is required,\n\n133\n00:06:55,888 --> 00:06:57,440\n然而有很多参数Y\nand there are many y's,\n\n134\n00:06:59,536 --> 00:07:05,990\n这些参数形成的表 -- 我就记作Y\nmany arguments-- y will be the list of them.\n\n135\n00:07:14,480 --> 00:07:16,064\n写好了参数表\nNow, with such a thing,\n\n136\n00:07:16,096 --> 00:07:17,680\n我现在要这样定义过程体\nwe might be able to say something like,\n\n137\n00:07:19,024 --> 00:07:21,984\n我要对每一个元素都做同样的处理\nmap-- I'm going to do something to every one--\n\n138\n00:07:22,520 --> 00:07:25,760\n(MAP (LAMBDA (U)\nof that procedure of one argument u,\n\n139\n00:07:27,000 --> 00:07:34,544\n(* X U)) Y)\nwhich multiplies x by u, and we'll apply that to y.\n\n140\n00:07:36,890 --> 00:07:38,048\n这里 我用了一个“点号”\nI've used a dot here\n\n141\n00:07:38,592 --> 00:07:41,312\n来表明点号后面的东西\nto indicate that the thing after this\n\n142\n00:07:42,192 --> 00:07:44,304\n是剩下的所有参数构成的表\nis a list of all the rest of the arguments.\n\n143\n00:07:46,300 --> 00:07:48,128\n这就是一个语法规范\nI'm making a syntactic specification.\n\n144\n00:07:53,320 --> 00:07:54,640\n为什么这样来写呢？\nNow, what this depends upon,\n\n145\n00:07:55,712 --> 00:07:58,064\n这种语法规范之所以合理\nthe reason why this is sort of a reasonable thing to do,\n\n146\n00:07:59,776 --> 00:08:01,968\n是因为Lisp的源码读取器\nis because this happens to be a syntax\n\n147\n00:08:02,000 --> 00:08:03,600\n刚好使用这种语法\nthat's used in the Lisp reader\n\n148\n00:08:04,416 --> 00:08:07,152\n来表示序对\nfor representing conses.\n\n149\n00:08:08,944 --> 00:08:11,080\n我们之前没有介绍过\nWe've never introduced that before.You never see.\n\n150\n00:08:11,080 --> 00:08:12,784\n你在自己尝试的时候可能遇到过\nYou may have seen when playing with the system\n\n151\n00:08:13,040 --> 00:08:14,624\n当你调用(CONS X Y)时\nif you cons two things together, you get the\n\n152\n00:08:14,896 --> 00:08:18,128\n你会得到 X . Y\nfirst, space, dot, the second, space--\n\n153\n00:08:19,790 --> 00:08:22,832\n准确来说是(X . Y)\nthe first, space, dot, space, the second\n\n154\n00:08:23,088 --> 00:08:24,640\n两边还有括号\nwith parentheses around the whole thing.\n\n155\n00:08:26,980 --> 00:08:28,160\n举例来说吧\nSo that, for example,\n\n156\n00:08:28,970 --> 00:08:35,040\n这里的(X . Y)对应着一个序对\nthis x dot y corresponds to a pair,\n\n157\n00:08:36,336 --> 00:08:39,296\nX是CAR部分 Y是CDR部分\nwhich has got an x in it and a y in it.\n\n158\n00:08:41,488 --> 00:08:43,984\n你们目前为止见过的其它记号\nThe other notations that you've seen so far\n\n159\n00:08:44,944 --> 00:08:46,672\n是像\nare things like, like\n\n160\n00:08:46,920 --> 00:08:55,248\n(LAMBDA (X Y Z) ...)这样的\na procedure of arguments x and y and z which do things\n\n161\n00:08:55,710 --> 00:08:57,630\n它们则是像这样的\nand that looks like--\n\n162\n00:09:02,000 --> 00:09:03,616\n就拿形式参数表来说\nJust looking at the bound variable list,\n\n163\n00:09:04,224 --> 00:09:05,296\n它实际上是这样\nit looks like this,\n\n164\n00:09:09,936 --> 00:09:17,328\n这里分别是 X、Y、Z和空表\nx, y, z, and the empty thing.\n\n165\n00:09:18,280 --> 00:09:21,088\n如果我有一个想要与之匹配的参数表的话\nIf I have a list of arguments I wish to match this against,\n\n166\n00:09:22,608 --> 00:09:25,600\n假设实际参数表是'(1 2 3)\nI have a list of arguments one, two, three,\n\n167\n00:09:25,872 --> 00:09:27,264\n我想把它们和形参相匹配\nI want to match these against.\n\n168\n00:09:28,384 --> 00:09:37,104\n所以这里 可能有个三个元素的表\nOK? So I might have here a list of three things,\n\n169\n00:09:42,448 --> 00:09:46,944\n分别是1、2、3\none, two, three.\n\n170\n00:09:48,990 --> 00:09:53,168\n用'(1 2 3)来匹配'(X Y Z)\nAnd I want to match x, y, z against one, two, three.\n\n171\n00:09:54,220 --> 00:09:56,288\n很显然1和X相匹配\nWell, it's clear that the one matches the x,\n\n172\n00:09:56,320 --> 00:09:58,016\n因为我可以顺着这个结构来\nbecause I can just sort of follow the structure,\n\n173\n00:09:58,864 --> 00:10:01,568\n2和Y相匹配\nand the two matches the y,\n\n174\n00:10:02,464 --> 00:10:04,048\n3和Z相匹配\nand the three matches the z.\n\n175\n00:10:05,480 --> 00:10:09,536\n假设我现在要把这个(X . Y)\nBut now, supposing I were to compare this x dot y.\n\n176\n00:10:09,552 --> 00:10:11,840\n这个是(X . Y)\nthis is x dot y--\n\n177\n00:10:12,512 --> 00:10:16,912\n如果我想把它跟'(1 2 3)相匹配的话\nsupposing I compare that with a list of three arguments, one, two, three.\n\n178\n00:10:19,088 --> 00:10:20,000\n我们再来看\nLet's look at that again.\n\n179\n00:10:28,000 --> 00:10:30,320\n这里是1、2、3\nOne, two, three--\n\n180\n00:10:30,864 --> 00:10:32,880\n我可以沿着这里遍历\nWell, I can walk along here\n\n181\n00:10:32,992 --> 00:10:35,504\n会发现 1和X相匹配\nand say, oh yes, x matches the one,\n\n182\n00:10:37,568 --> 00:10:41,840\n而Y和表'(2 3)相匹配\nAh, the y matches the list, which is two and three.\n\n183\n00:10:43,740 --> 00:10:46,224\n所以这里选用的表示法\nSo the notation I'm choosing here\n\n184\n00:10:46,416 --> 00:10:50,160\n对于Lisp来说是非常自然的\nis one that's very natural for Lisp system.\n\n185\n00:10:52,660 --> 00:10:54,144\n所以我就选择用这个记号\nBut I'm going to choose this as a notation\n\n186\n00:10:54,176 --> 00:10:55,808\n来表示数目不定的参数\nfor representing a bunch of arguments.\n\n187\n00:10:58,290 --> 00:11:00,096\n还有一种可能性\nNow, there's an alternative possibility.\n\n188\n00:11:00,592 --> 00:11:02,784\n如果我不是特别想命名某个参数\nIf I don't want to take one special out,\n\n189\n00:11:03,008 --> 00:11:05,008\n或者是命名某两个参数之类的\nor two special ones out or something like that,\n\n190\n00:11:06,544 --> 00:11:07,568\n如果我不想那样的话\nif I don't want to do that,\n\n191\n00:11:08,780 --> 00:11:10,448\n如果我想像+那样\nif I want to talk about\n\n192\n00:11:10,528 --> 00:11:12,520\n一下子引用所有的参数\njust the list of all the arguments like in addition，\n\n193\n00:11:13,880 --> 00:11:17,960\n那么我就应该把参数表写成\nwell then the argument list I'm going to choose to be\n\n194\n00:11:18,200 --> 00:11:23,456\n(LAMBDA X ...)\nthat procedure of all the arguments x, which does something with x\n\n195\n00:11:25,140 --> 00:11:26,304\n举例来说\nAnd which, for example,\n\n196\n00:11:26,816 --> 00:11:27,968\n如果我定义一个过程\nif I take the procedure,\n\n197\n00:11:28,064 --> 00:11:30,448\n它把接收所有的参数\nwhich takes all the arguments x\n\n198\n00:11:31,120 --> 00:11:32,704\n然后返回一个由它们组成的表X\nand returned the list of them,\n\n199\n00:11:34,810 --> 00:11:38,672\n返回的结果就是过程的参数表 明白吗？\nOK? That's list. That's the procedure list.\n\n200\n00:11:45,850 --> 00:11:46,672\n这又是怎么回事呢？\nHow does this work?\n\n201\n00:11:46,840 --> 00:11:50,064\n实际上 无论我们的参数表是何种形式\nWell, indeed what I had as the bound variable list in this case,\n\n202\n00:11:50,600 --> 00:11:51,456\n无论是何种形式\nwhatever it is,\n\n203\n00:11:51,616 --> 00:11:53,680\n都要与实际参数表相匹配\nis being matched against a list of arguments.\n\n204\n00:11:55,140 --> 00:11:57,145\n现在 这个符号就是所有的实际参数了\nThis symbol now is all of the arguments.\n\n205\n00:12:01,490 --> 00:12:05,136\n所以 我选择使用这个特定的语法规范\nAnd so this is the choice I'm making for a particular syntactic specification,\n\n206\n00:12:05,648 --> 00:12:07,632\n来描述那些\nfor the description of procedures\n\n207\n00:12:08,048 --> 00:12:10,560\n接收不定数目参数的过程\nwhich take indefinite numbers of arguments.\n\n208\n00:12:13,456 --> 00:12:14,608\n一共有两种情况\nThere are two cases of it,\n\n209\n00:12:15,400 --> 00:12:16,350\n上面这种和下面这种\nthis one and this one.\n\n210\n00:12:17,440 --> 00:12:18,368\n这两种都 --\nAnd none of this.\n\n211\n00:12:18,420 --> 00:12:20,112\n当你们在制定语法规范时\nWhen you make syntactic specifications,\n\n212\n00:12:20,448 --> 00:12:22,544\n千万注意不要有歧义\nit's important that it's unambiguous,\n\n213\n00:12:23,568 --> 00:12:27,360\n就比如说这里的两种情况\nthat neither of these can be confused with\n\n214\n00:12:27,664 --> 00:12:31,200\n就不要与这里我们已有的这种混淆了\na representation we already have, this one.\n\n215\n00:12:33,610 --> 00:12:35,824\n我总是可以区分出\nI can always tell whether I have\n\n216\n00:12:36,544 --> 00:12:39,808\n过程的形式参数\na fixed number of explicitly named arguments\n\n217\n00:12:40,288 --> 00:12:41,760\n是数目固定的具名参数\nmade by these formal parameters,\n\n218\n00:12:42,640 --> 00:12:43,130\n还是\nor\n\n219\n00:12:43,280 --> 00:12:45,360\n既有数目固定的具名参数\na fixed number of named formal parameters\n\n220\n00:12:45,440 --> 00:12:48,016\n又跟着数目可变的参数\nfollowed by a thing which picks up all the rest of them,\n\n221\n00:12:49,424 --> 00:12:53,520\n又或者是所有参数组成的表\nor a list of all the arguments\n\n222\n00:12:53,680 --> 00:12:56,528\n这个表会和这里的形式参数X相匹配\nwhich will be matched against this particular formal parameter called x,\n\n223\n00:12:56,992 --> 00:12:58,848\n我都是可以从语法上区分它们\nbecause these are syntactically distinguishable.\n\n224\n00:13:02,250 --> 00:13:04,624\n由于语言中存在语法歧义\nMany languages make terrible errors in that form\n\n225\n00:13:05,040 --> 00:13:08,032\n整个待解释的程序被错误地分段\nwhere whole segments of interpretation are cut off,\n\n226\n00:13:08,640 --> 00:13:13,920\n从而导致了可怕的错误\nbecause there are syntactic ambiguities in the language.\n\n227\n00:13:14,560 --> 00:13:16,672\n类Algol语言中就有些传统问题\nThey are the traditional problems with ALGOL like languages\n\n228\n00:13:16,672 --> 00:13:23,472\n就跟谓词部分的嵌套IF语句有关\nhaving to do with the nesting of ifs in the predicate part.\n\n229\n00:13:25,060 --> 00:13:25,936\n总之\nIn any case,\n\n230\n00:13:27,520 --> 00:13:29,440\n我现在已经把语法告诉你们了\nnow, so I've told you about the syntax,\n\n231\n00:13:30,272 --> 00:13:34,832\n我们要怎么来处理它的语义呢？\nnow, what are we going to do about the semantics of this?\n\n232\n00:13:35,250 --> 00:13:36,112\n我们如何来解释它？\nHow do we interpret it?\n\n233\n00:13:36,590 --> 00:13:37,968\n其实很简单\nWell this is just super easy.\n\n234\n00:13:38,440 --> 00:13:42,576\n我修改一下元循环解释器就行\nI'm going to modify the metacircular interpreter to do it.\n\n235\n00:13:43,712 --> 00:13:44,768\n只需修改一行\nAnd that's a one liner.\n\n236\n00:13:45,984 --> 00:13:46,576\n在这里\nThere it is.\n\n237\n00:13:47,536 --> 00:13:49,560\n我修改一下PAIR-UP过程\nI'm changing the way you pair things up.\n\n238\n00:13:50,816 --> 00:13:54,192\n这里的PAIR-UP过程把\nOK? Here we have procedure that pairs --\n\n239\n00:13:56,760 --> 00:14:02,032\n这是从上节课的元循环求值器中\nHere's the procedure that pairs the\n\n240\n00:14:04,810 --> 00:14:09,568\n摘录过来的PAIR-UP过程\nthe variables, the formal parameters, with the arguments that were passed\n\n241\n00:14:12,160 --> 00:14:16,688\n它把形式参数与传递过来的实际参数匹配起来\nfrom the last description of the metacircular interpreter.\n\n242\n00:14:18,960 --> 00:14:21,936\n大部分地方都和以前一样\nAnd here's some things that are the same as they were before.\n\n243\n00:14:22,670 --> 00:14:23,232\n也就是说\nIn other words,\n\n244\n00:14:23,312 --> 00:14:25,072\n如果变量表为空\nif the list of variables is empty,\n\n245\n00:14:25,520 --> 00:14:27,312\n并且值表也为空\nthen if the list of values is empty,\n\n246\n00:14:27,456 --> 00:14:29,616\n就返回空表\nthen I have an empty list.\n\n247\n00:14:31,050 --> 00:14:33,008\n否则就是参数过多\nOtherwise, I have too many arguments,\n\n248\n00:14:33,980 --> 00:14:40,192\n如果变量表为空 但值表非空\nIf I have, that is if I have empty variables but not empty values.\n\n249\n00:14:41,580 --> 00:14:44,000\n如果值表为空\nIf I have empty values,\n\n250\n00:14:44,960 --> 00:14:47,472\n但是变量表又非空\nOK? But the variables are not empty,\n\n251\n00:14:47,488 --> 00:14:48,560\n那就是实际参数少了\nthat I have too few arguments.\n\n252\n00:14:48,944 --> 00:14:51,312\n然而如果我有一个变量是符号的话\nHowever if I have a variable -- the variables are a symbol--\n\n253\n00:14:55,536 --> 00:14:56,496\n这就有意思了\ninteresting case--\n\n254\n00:14:58,300 --> 00:15:04,400\n那么 我就认为遇到了特殊情况\nthen, what I should do is say, oh yes, this is the special case\n\n255\n00:15:04,592 --> 00:15:06,510\n也就是尾部分为符号的情况\nthat I have a symbolic tail.\n\n256\n00:15:08,350 --> 00:15:14,112\n情况就像这里的一样\nOK. I have here a thing just like we looked over here.\n\n257\n00:15:14,900 --> 00:15:17,872\n这个尾部分就是一个符号Y\nThis is a tail which is a symbol, y.\n\n258\n00:15:18,630 --> 00:15:19,392\n它不是NIL\nIt's not a nil.\n\n259\n00:15:20,730 --> 00:15:21,728\n不是个空表\nIt's not the empty list.\n\n260\n00:15:23,264 --> 00:15:25,600\n而这个一开始就是个符号\nHere's a symbolic tail that is just the very beginning of the tail.\n\n261\n00:15:25,984 --> 00:15:26,816\n就没有别的东西了\nThere is nothing else.\n\n262\n00:15:27,790 --> 00:15:28,720\n这种情况下\nIn that case,\n\n263\n00:15:29,960 --> 00:15:37,200\n我就用这个符号去匹配所有的值\nI wish to match that variable with all the values\n\n264\n00:15:38,032 --> 00:15:42,520\n并把它们添加到要返回的结果中\nand add that to the pairing that I'm making.\n\n265\n00:15:44,500 --> 00:15:46,912\n否则的话 我就像正常情况那样\nOtherwise, I go through the normal arrangement\n\n266\n00:15:47,152 --> 00:15:48,528\n来创建所有的配对\nof making up the whole pairing.\n\n267\n00:15:52,020 --> 00:15:53,824\n我认为这很容易理解\nI suppose that's very simple.\n\n268\n00:15:54,510 --> 00:15:55,840\n就是这些\nAnd that's all there is to it.\n\n269\n00:15:57,080 --> 00:15:58,330\n现在 答疑时间\nAnd now I'll answer some questions.\n\n270\n00:16:02,620 --> 00:16:05,056\n有什么问题吗？\nThe first one-- Are there any questions?\n\n271\n00:16:06,600 --> 00:16:06,944\n你说\nYes?\n\n272\n00:16:07,376 --> 00:16:09,920\n学生：你能再解释一下第三种形式吗？\nAUDIENCE: Could you explain that third form?\n\n273\n00:16:09,980 --> 00:16:12,128\n教授：第三种？这个？\nPROFESSOR: Third form. This one? OK.\n\n274\n00:16:12,590 --> 00:16:14,272\n或许你用表结构来思考\nWell, maybe we should look at the thing\n\n275\n00:16:14,300 --> 00:16:16,240\n会更容易理解一些\nas a piece of list structure.\n\n276\n00:16:18,570 --> 00:16:22,736\n这是一个过程 包含一个LAMBDA\nThis is a procedure which contains a lambda.\n\n277\n00:16:25,856 --> 00:16:29,616\n我画出来的这个表结构就代表上面的这个\nI'm just looking at the list structure which represents this.\n\n278\n00:16:31,264 --> 00:16:32,448\n这里是X\nHere's x.\n\n279\n00:16:32,730 --> 00:16:33,980\n这些是我们的符号\nThese are our symbols.\n\n280\n00:16:37,410 --> 00:16:39,580\n过程体就是X而已\nAnd then the body is nothing but x.\n\n281\n00:16:44,840 --> 00:16:48,752\n如果我需要这个过程的形式参数表\nIf I were looking for the bound variable list part of this procedure,\n\n282\n00:16:50,096 --> 00:16:51,584\n我就取它的CADR部分\nI would go looking at the CADR,\n\n283\n00:16:52,144 --> 00:16:53,168\n我会得到一个符号\nand I'd find a symbol.\n\n284\n00:16:54,010 --> 00:16:57,168\n所以我们的匹配器 -- 也就是我给你们展示的PAIR-UP过程\nSo the, matcher, which is this pairup thing I just showed you,\n\n285\n00:16:58,240 --> 00:17:00,448\n就会把这个符号对象\nis going to be matching a symbolic object\n\n286\n00:17:01,568 --> 00:17:04,400\n跟我们传递的实际参数表相匹配了\nagainst a list of arguments that were passed.\n\n287\n00:17:05,760 --> 00:17:09,559\n这个符号与实际参数表相绑定\nAnd it will bind that symbol to the list of arguments.\n\n288\n00:17:11,376 --> 00:17:16,480\n而在这个例子中 如果我去取它的话\nThe -- In this case, if I'm looking for it,\n\n289\n00:17:16,928 --> 00:17:20,976\n匹配器就会把它与变量表的这个部分相匹配\nthe match will be against this in the bound variable list position.\n\n290\n00:17:24,140 --> 00:17:26,144\n如果一个过程只是\nNow, if what this does is\n\n291\n00:17:26,170 --> 00:17:29,130\n直接返回得到的参数表的话 返回的就是一个表\nit gets a list of arguments and returns it, that's list\n\n292\n00:17:30,400 --> 00:17:31,392\n这个过程就是这样的\nThat's the procedure is.\n\n293\n00:17:34,510 --> 00:17:35,488\n好吧 谢谢大家\nOh well, thank you.\n\n294\n00:17:36,140 --> 00:17:37,280\n大家休息一下吧\nLet's take a break.\n\n295\n00:17:37,830 --> 00:17:55,360\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n296\n00:17:55,360 --> 00:17:59,024\n《计算机程序的构造和解释》\n\n297\n00:18:03,530 --> 00:18:07,568\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n298\n00:18:07,560 --> 00:18:11,696\n《计算机程序的构造和解释》\n\n299\n00:18:12,256 --> 00:18:16,110\n元循环求值器 II\n\n300\n00:18:20,864 --> 00:18:21,616\n教授：我们接着来看\nPROFESSOR: Well let's see.\n\n301\n00:18:23,260 --> 00:18:26,320\n现在 我将介绍一种相当重要的变种\nNow, I'm going to tell you about a rather more substantial variation\n\n302\n00:18:27,456 --> 00:18:31,040\n这种变体非常有名\none that's a famous variation\n\n303\n00:18:31,600 --> 00:18:36,800\n早期的很多Lisp都支持它\nhat many early Lisps had.\n\n304\n00:18:38,256 --> 00:18:40,064\n它被称为变量的动态绑定\nIt's called dynamic binding of variables.\n\n305\n00:18:41,770 --> 00:18:44,680\n我们现在来研究一下它\nAnd we'll investigate a little bit about that right now.\n\n306\n00:18:47,620 --> 00:18:50,160\n我先来介绍一下是什么导致\nI'm going to first introduce this by showing you the sort of thing\n\n307\n00:18:50,352 --> 00:18:52,368\n人们产生这样的想法\nthat would make someone want this idea.\n\n308\n00:18:53,740 --> 00:18:55,232\n然而我并不会直接点明原因\nI'm not going to tell what it is yet,\n\n309\n00:18:55,408 --> 00:18:57,600\n我来举一个例子 你们来感受一下\nI'm going to show you why you might want it.\n\n310\n00:18:58,640 --> 00:18:59,936\n假设\nSuppose, for example,\n\n311\n00:19:00,750 --> 00:19:02,592\n我们再来考察一下\nwe looked at the sum procedure again\n\n312\n00:19:05,024 --> 00:19:06,430\n计算一系列数之和的SUM过程\nfor summing up a bunch of things.\n\n313\n00:19:08,140 --> 00:19:09,472\n它的参数为\nTo be that procedure,\n\n314\n00:19:09,600 --> 00:19:10,784\n计算当前项的TERM\nof a term,\n\n315\n00:19:13,040 --> 00:19:14,416\n下界A\nlower bound,\n\n316\n00:19:15,240 --> 00:19:17,040\n计算下一项索引的NEXT\nmethod of computing the next index,\n\n317\n00:19:17,248 --> 00:19:18,560\n上界B\nand upper bound,\n\n318\n00:19:19,360 --> 00:19:20,160\n过程体是\nsuch that,\n\n319\n00:19:23,160 --> 00:19:26,940\n如果A>B\nif a is greater than b\n\n320\n00:19:27,150 --> 00:19:28,640\n那么结果就是0\nthen the result is 0,\n\n321\n00:19:30,240 --> 00:19:31,088\n否则就是\notherwise,\n\n322\n00:19:33,680 --> 00:19:39,824\n(+ (TERM A)\nit's the sum, of the term, procedure, applied to a\n\n323\n00:19:40,608 --> 00:19:44,240\n(SUM TERM\nand the result of adding up, terms,\n\n324\n00:19:47,680 --> 00:19:52,640\n(NEXT A)\nwith the next a being the a,\n\n325\n00:20:00,300 --> 00:20:03,560\n这个NEXT过程直接传递过去\nthe next procedure passed along,\n\n326\n00:20:06,400 --> 00:20:08,256\n上界B也直接传递过去\nand the upper bound being passed along.\n\n327\n00:20:14,510 --> 00:20:15,760\n（闭合括号中）\nBlink, blink, blink--\n\n328\n00:20:17,824 --> 00:20:21,450\n当我使用SUM过程的时候\nOK? Now, when I use this sum procedure,\n\n329\n00:20:21,968 --> 00:20:24,352\n我可以像这样来用\nI can use it, for example, like this.\n\n330\n00:20:25,450 --> 00:20:38,048\n我们可以把SUM-POWERS过程定义为\nWe can define the sum of the powers to be,\n\n331\n00:20:38,080 --> 00:20:40,330\n这个函数是用来计算Σ(X^N)的\nfor example, sum of a bunch of powers x to the n,\n\n332\n00:20:41,104 --> 00:20:45,936\n它的参数有A、B以及N\nto be that procedure of a, b, and n--\n\n333\n00:20:45,952 --> 00:20:47,696\n分别指下界、上界以及指数\nlower bound, the upper bound, and n--\n\n334\n00:20:48,060 --> 00:20:53,344\n它的定义是(SUM (LAMBDA (X)\nwhich is sum, of lambda of x,\n\n335\n00:20:53,600 --> 00:20:59,310\n这个参数为X的过程计算(EXPT X N)\nthe procedure of one argument x, which exponentiates x to the n,\n\n336\n00:21:02,190 --> 00:21:09,296\n我们还要传递A、1+还有B\nwith the a, the incrementer, and b, being passed along.\n\n337\n00:21:11,824 --> 00:21:15,760\n因此 给定一系列X 我们计算Σ(X^N)的值\nSo we're adding up x to n, given an x.\n\n338\n00:21:16,144 --> 00:21:19,740\nX从A到B取值 步长为1\nx takes on values from a to b, incrementing by one.\n\n339\n00:21:22,940 --> 00:21:24,384\n我也可以定义--\nI can also write the--\n\n340\n00:21:27,680 --> 00:21:28,200\n好像这里有点问题\nThat's right.\n\n341\n00:21:29,780 --> 00:21:31,024\n不好意思\nProduct, excuse me.\n\n342\n00:21:31,910 --> 00:21:33,360\n这里应该是PRODUCT-POWERS\nThe product of a bunch of powers.\n\n343\n00:21:38,080 --> 00:21:39,120\n名字有点奇怪\nIt's a strange name.\n\n344\n00:21:40,020 --> 00:21:40,800\n还是不改了\nI'm going to leave it there.\n\n345\n00:21:41,960 --> 00:21:46,320\n有点怪 就按原来的吧\nWeird-- OK? I write up what I have.\n\n346\n00:21:49,344 --> 00:21:50,192\n这回应该对了\nI'm sure that's right.\n\n347\n00:21:51,376 --> 00:21:53,824\n而PRODUCT-POWERS的定义则是\nAnd if I want the product of a bunch of powers--\n\n348\n00:21:58,416 --> 00:22:02,368\n（意义不明）\nThat was 12 brain cells, that double-take.\n\n349\n00:22:03,000 --> 00:22:06,816\n我可以用像SUM一样的过程 \nI can for example use the procedure which is like sum,\n\n350\n00:22:06,816 --> 00:22:08,220\n只不过是用来计算乘积的\nwhich is for making products,\n\n351\n00:22:08,560 --> 00:22:11,056\n但是很类似 就跟你们在那里见到的一样\nbut it's similar to that, that you've seen before.\n\n352\n00:22:11,450 --> 00:22:16,384\n它也是一个三参数的过程\nThere's a procedure of three arguments again.\n\n353\n00:22:17,000 --> 00:22:25,424\n求积的因数是通过构造而来\nWhich is the product of terms that are constructed, or factors in this case,\n\n354\n00:22:25,664 --> 00:22:31,600\n也就是(PRODUCT (LAMBDA (X) (EXPT X N))\nconstructed from exponentiating x to the n,\n\n355\n00:22:34,432 --> 00:22:37,856\n下界是A 步长为1 上界为B\nwhere I start with a, I increment, and I go to b.\n\n356\n00:22:41,530 --> 00:22:41,888\n现在\nNow,\n\n357\n00:22:46,832 --> 00:22:49,504\n你可能马上就意识到一些问题\nthere's some sort of thing here that should disturb you immediately.\n\n358\n00:22:50,750 --> 00:22:52,016\n它们看起来几乎一样\nThese look the same.\n\n359\n00:22:53,180 --> 00:22:55,200\n为什么要重复写代码呢？\nWhy am I writing this code so many times?\n\n360\n00:22:56,590 --> 00:22:59,728\n现在就很像我们之前遇到的情况了\nHere I am, in the same boat I've been in before.\n\n361\n00:23:01,008 --> 00:23:03,152\n构建一个抽象不是更好吗？\nRight? Wouldn't it be nice to make an abstraction here?\n\n362\n00:23:03,810 --> 00:23:05,760\n如何构建良好的抽象呢？\nWhat's an example of a good abstraction to make?\n\n363\n00:23:05,856 --> 00:23:07,552\n我看到有一些完全相同的代码\nWell, I see some codes that's identical.\n\n364\n00:23:08,470 --> 00:23:09,328\n这有一段\nHere's one,\n\n365\n00:23:09,984 --> 00:23:11,080\n这是另一段\nand here's another.\n\n366\n00:23:14,450 --> 00:23:16,224\n所以我应该把它们提取出来\nAnd so maybe I should be able to pull that out.\n\n367\n00:23:17,090 --> 00:23:19,232\n我就会想\nI should be able to say, oh yes,\n\n368\n00:23:20,512 --> 00:23:22,672\nSUM-POWERS可以用\nthe sum of the powers could be written in terms of\n\n369\n00:23:22,880 --> 00:23:24,528\nNTH-POWERS的过程来编写\nsomething called the nth power procedure.\n\n370\n00:23:25,710 --> 00:23:27,408\n假如有人想写一个\nImagine somebody wanted to write\n\n371\n00:23:27,744 --> 00:23:30,030\n稍微不同的过程 就像这个一样\na slightly different procedure that looks like this.\n\n372\n00:23:37,630 --> 00:23:45,184\n(DEFINE SUM-POWERS\nThe sum powers to be a procedure\n\n373\n00:23:46,448 --> 00:23:48,460\n(LAMBDA (A B N)\nof a, b, and n,\n\n374\n00:23:48,752 --> 00:23:52,272\n(SUM (NTH-POWER\nwhich the result of summing up the nth power.\n\n375\n00:23:53,888 --> 00:23:55,424\n我们调用过程NTH-POWER\nWe're going to give a name to that idea,\n\n376\n00:23:58,352 --> 00:24:02,272\n下界为A 步长为1 上界为B\nfor starting at a, going by one, and ending at b.\n\n377\n00:24:05,744 --> 00:24:06,912\n类似地\nAnd similarly,\n\n378\n00:24:10,656 --> 00:24:12,768\n我想用这种方式来重写PRODUCT-POWERS\nI might want to write the product powers this way,\n\n379\n00:24:12,896 --> 00:24:15,248\n把求幂指数从这里抽象出来\nabstracting out this idea.\n\n380\n00:24:16,270 --> 00:24:17,376\n可以这样写\nI might want this.\n\n381\n00:24:22,100 --> 00:24:23,024\n(DEFINE PRODUCT-POWERS\nProduct powers,\n\n382\n00:24:29,488 --> 00:24:34,944\n(LAMBDA (A B N)\nto be a procedure of a, b, and n,\n\n383\n00:24:35,312 --> 00:24:42,336\n(PRODUCT NTH-POWERS\nwhich is the product of the nth power operation\n\n384\n00:24:46,448 --> 00:24:50,304\nA 1+ B)))\non a with the incrementation and b being\n\n385\n00:24:53,504 --> 00:24:57,568\n把NTH-POWER的结果作为PRODUCT的参数\nbeing my arguments for the analogous-thing product.\n\n386\n00:24:58,380 --> 00:25:00,240\n我们还需要定义\nAnd I'd like to be able to define,\n\n387\n00:25:02,048 --> 00:25:03,888\n还需要定义过程NTH-POWERS\nI'd like to be able to define nth power--\n\n388\n00:25:04,896 --> 00:25:05,930\n我把它写在这边\nI'll put it over here.\n\n389\n00:25:12,224 --> 00:25:12,990\n写在上面\nI'll put it at the top.\n\n390\n00:25:25,410 --> 00:25:29,040\n它是一个参数为X的过程\n--to be, in fact, my procedure of one argument x\n\n391\n00:25:29,600 --> 00:25:34,560\n计算(EXPT X N)\nwhich is the result of exponentiating x to the n.\n\n392\n00:25:35,936 --> 00:25:36,960\n但是我遇到一个问题\nBut I have a problem.\n\n393\n00:25:38,640 --> 00:25:39,936\n我们使用的环境模型\nMy environment model,\n\n394\n00:25:40,576 --> 00:25:43,232\n我们用来解释\nthat is my means of interpretation\n\n395\n00:25:44,000 --> 00:25:45,952\n目前所定义的语言的这种手段\nof interpretation for the language that we've defined so far,\n\n396\n00:25:46,272 --> 00:25:48,810\n并没有给我说明这个N的值\ndoes not give me a meaning for this n.\n\n397\n00:25:52,768 --> 00:25:59,264\n因为 正如大家所知\nBecause, as you know, the, as you know\n\n398\n00:26:00,768 --> 00:26:04,256\n在这个过程中 N是自由变量\nthis n is free in this procedure.\n\n399\n00:26:06,410 --> 00:26:07,984\n环境模型告诉我们\nThe environment model tells us\n\n400\n00:26:08,608 --> 00:26:10,208\n自由变量的值\nthat the meaning of a free variable\n\n401\n00:26:11,216 --> 00:26:14,992\n取决于过程被定义时所在的环境\nis determined in the environment in which this procedure is defined.\n\n402\n00:26:16,640 --> 00:26:17,472\n在我编写它们的时候\nIn a way I have written it,\n\n403\n00:26:17,488 --> 00:26:19,840\n就假设它们已经在黑板上被定义了\nassuming these things are defined on the blackboard as is,\n\n404\n00:26:21,648 --> 00:26:23,632\nNTH-POWER是定义在全局环境下的\nthis is defined in the global environment,\n\n405\n00:26:24,064 --> 00:26:25,152\n其中没有N的定义\nwhere there is no n.\n\n406\n00:26:25,936 --> 00:26:27,632\n因此 N是未绑定的变量\nTherefore, n is unbound variable.\n\n407\n00:26:28,720 --> 00:26:31,664\n但对我们来说\nBut it's perfectly clear, to most of us,\n\n408\n00:26:32,608 --> 00:26:36,320\n我们明确希望它是这里和这里的N\nthat we would like it to be this n and this n.\n\n409\n00:26:38,990 --> 00:26:42,672\n另外一方面\nOn the other hand, OK, it would be nice.\n\n410\n00:26:42,840 --> 00:26:44,288\n当然我们要十分小心地确保\nCertainly we've got to be careful here\n\n411\n00:26:44,560 --> 00:26:46,064\n这里的N是这里的N\nof keeping this to be this,\n\n412\n00:26:48,960 --> 00:26:52,832\n还有这里的这个 要跟这里的一致\nand this one over here, wherever it is to be this one.\n\n413\n00:26:57,390 --> 00:26:59,744\n这种想法造就了\nWell, the desire to make this work\n\n414\n00:27:00,672 --> 00:27:02,720\n一个非常著名的BUG\nhas led to a very famous bug.\n\n415\n00:27:04,656 --> 00:27:06,048\n我来细说下这个BUG\nI'll tell you about the famous bug.\n\n416\n00:27:07,152 --> 00:27:09,408\n请看这张幻灯片\nLook at this slide.\n\n417\n00:27:10,660 --> 00:27:12,704\n这种想法被称作“动态绑定”\nThis is an idea called dynamic binding.\n\n418\n00:27:13,990 --> 00:27:16,912\n在这种情况下 自由变量不再被\nWhere, instead of the free variable being interpreted\n\n419\n00:27:17,760 --> 00:27:21,232\n定义过程时的环境所解释\nin the environment of definition of a procedure,\n\n420\n00:27:22,400 --> 00:27:25,168\n这种情况下 自由变量的值\nthe free variable is interpreted as having its value\n\n421\n00:27:25,440 --> 00:27:29,312\n就像是存储在过程调用者的环境中一样\nin the environment of the caller of the procedure.\n\n422\n00:27:31,850 --> 00:27:34,848\n所以在这个系统中\nSo what you have is a system\n\n423\n00:27:34,860 --> 00:27:39,680\n你需要不断地搜索调用过程的调用者的环境\nwhere you search up the chain of callers of a particular procedure,\n\n424\n00:27:40,432 --> 00:27:42,656\n当然 在本例中\nand, of course, in this case,\n\n425\n00:27:42,840 --> 00:27:44,304\n无论NTH-POWER在何处定义\nsince nth power is called\n\n426\n00:27:44,336 --> 00:27:45,980\n它都是在PRODUCT过程中被调用的\nfrom inside product whatever it is--\n\n427\n00:27:46,416 --> 00:27:48,688\n我就需要在SUM过程中再编写一个类似的过程\nI had to write our own sum which is the analogous procedure--\n\n428\n00:27:50,512 --> 00:27:54,928\n而PRODUCT又是被PRODUCT-POWERS所调用\nand product is presumably called from product powers,\n\n429\n00:27:55,136 --> 00:27:56,144\n就是你们在这里看到的\nas you see over here,\n\n430\n00:27:56,832 --> 00:27:59,376\n由于PRODUCT-POWERS过程绑定了变量N\nthen since product powers bind with variable n ,\n\n431\n00:28:00,096 --> 00:28:04,096\n因此NTH-POWER中的N会从这个链中派生出来\nthen nth powers n would be derived through that chain.\n\n432\n00:28:08,140 --> 00:28:09,648\n相似地 这个N\nSimilarly, this n,\n\n433\n00:28:10,112 --> 00:28:12,016\nNTH-POWER中的N在这种情况下\nthe nth power in n in this case,\n\n434\n00:28:12,320 --> 00:28:15,800\n可能是来自于这里SUM过程的调用\nwould come through nth power here being called from inside sum.\n\n435\n00:28:15,800 --> 00:28:18,272\n你们可以从这里看到 它在SUM内部被调用\nYou can see it being called from inside sum here.\n\n436\n00:28:20,736 --> 00:28:21,696\n对应这里的TERM\nIt's called term here.\n\n437\n00:28:22,900 --> 00:28:25,728\n而SUM是在SUM-POWERS的内部被调用\nBut sum was called from inside of sum powers,\n\n438\n00:28:26,944 --> 00:28:27,968\n后者绑定了N\nwhich bound n.\n\n439\n00:28:28,930 --> 00:28:30,656\n因此这里就有一个N\nTherefore, there would be an n available\n\n440\n00:28:32,752 --> 00:28:36,112\n可供NTH-POWER中的N取值\nthat n to get it's value from.\n\n441\n00:28:37,950 --> 00:28:39,248\n这就是动态 --\nThis is called dynamic --\n\n442\n00:28:39,280 --> 00:28:43,104\n这条白线以下的东西 再加上这部分\nWhat we have below this white line plus over here\n\n443\n00:28:43,312 --> 00:28:46,048\n就是我们所谓的动态绑定\nis what's called a dynamic binding view of the world.\n\n444\n00:28:46,592 --> 00:28:49,008\n用动态绑定的角度来解释 就可以正常运行\nIf that works, that's a dynamic binding view.\n\n445\n00:28:50,850 --> 00:28:52,656\n现在 让我们来看一个例子\nNow, let's take a look, for example,\n\n446\n00:28:54,544 --> 00:28:55,990\n要怎么实现这个功能\nat just what it takes to implement that.\n\n447\n00:28:55,990 --> 00:28:56,960\n非常简单\nThat's real easy.\n\n448\n00:28:57,480 --> 00:28:59,344\n事实上 最早的Lisp实现\nIn fact, the very first Lisps\n\n449\n00:29:00,016 --> 00:29:02,528\n对自由变量有各种形式的解释\nhad any form of interpretations of the free variables at all,\n\n450\n00:29:03,312 --> 00:29:05,984\n包括用动态绑定来解释自由变量\nhad dynamic binding interpretations for the free variables.\n\n451\n00:29:06,400 --> 00:29:10,144\nAPL也是用动态绑定来解释自由变量的\nAPL has dynamic binding interpretation for the free variables,\n\n452\n00:29:11,680 --> 00:29:14,320\n而不是词法绑定 或者说静态绑定\nnot lexical or static binding.\n\n453\n00:29:15,220 --> 00:29:17,008\n当然 要从EVAL开始修改\nSo, of course, the change is in eval.\n\n454\n00:29:19,312 --> 00:29:20,592\n只需修改两个地方就行\nAnd it's really in two places.\n\n455\n00:29:22,780 --> 00:29:25,616\n首先我们会发现\nFirst of all, one thing we see,\n\n456\n00:29:26,528 --> 00:29:28,496\n事情变得更简单了\nis that things become a little simpler.\n\n457\n00:29:29,390 --> 00:29:33,632\n如果我不需要\nIf I don't have to have the -- If I don't have to have the\n\n458\n00:29:33,648 --> 00:29:36,200\n在定义过程的那个环境中求值\nenvironment be the environment of definition for procedure,\n\n459\n00:29:36,448 --> 00:29:38,048\n过程在定义的时候就无需\nthe procedure need not capture\n\n460\n00:29:38,432 --> 00:29:40,176\n捕获当时的环境了\nthe environment at the time it's defined.\n\n461\n00:29:42,030 --> 00:29:44,960\n所以我们可以在幻灯片的这里看到\nAnd so if we look here at this slide,\n\n462\n00:29:45,840 --> 00:29:50,080\n这条用于判断是否为LAMBDA表达式的子句\nwe see that the clause for a lambda expression,\n\n463\n00:29:50,736 --> 00:29:52,432\n过程就是在这个时候创建的\nwhich is the way a procedure is defined,\n\n464\n00:29:53,920 --> 00:29:56,736\n就不会返回一个带有类型标签\ndoes not make up a thing which has a type closure\n\n465\n00:29:56,752 --> 00:30:01,050\n和环境结构的过程对象了\nand a attached environment structure.\n\n466\n00:30:01,290 --> 00:30:02,540\n就是EXP本身\nIt's just the expression itself.\n\n467\n00:30:02,540 --> 00:30:04,768\n而我们会在其它地方用某种方式来解耦\nAnd we'll decompose that some other way somewhere else.\n\n468\n00:30:06,440 --> 00:30:09,408\n另外一处修改就是组合式的应用\nThe other thing we see is the applicator\n\n469\n00:30:10,368 --> 00:30:13,696\n应用的时候必须要取得调用者的环境\napplicator must be able to get the environment of the caller.\n\n470\n00:30:14,290 --> 00:30:17,240\n调用者的环境就在这里\nThe caller of a procedure is right here.\n\n471\n00:30:17,260 --> 00:30:19,456\n如果表达式是一个过程应用--\nIf the procedure is a application--\n\n472\n00:30:19,560 --> 00:30:21,632\n如果我们求值的是一个组合式\nIf the expression we're evaluating is a combination,\n\n473\n00:30:21,792 --> 00:30:23,712\n我们就会调用一个组合式\nthen we're going to call a combination\n\n474\n00:30:23,936 --> 00:30:25,504\n调用一个过程\nthen we're going to call a procedure\n\n475\n00:30:25,664 --> 00:30:27,376\n来取得运算符的值\nwhich is the value of the operator.\n\n476\n00:30:29,840 --> 00:30:31,440\n调用者的环境\nThe environment of the caller\n\n477\n00:30:31,984 --> 00:30:34,512\n就是我们当前的环境\nis the environment we have right here, available now.\n\n478\n00:30:35,890 --> 00:30:40,720\n所以 我只需要要把这个环境传递给APPLY\nSo all I have to do is pass that environment to the applicator, to apply.\n\n479\n00:30:41,490 --> 00:30:42,752\n我们再来看看APPLY\nAnd if we look at that here,\n\n480\n00:30:43,584 --> 00:30:44,976\n我们只需要\nthe only change we have to make\n\n481\n00:30:45,712 --> 00:30:48,416\n把参数列表加上一个环境ENV\nis that fellow takes that environment\n\n482\n00:30:48,780 --> 00:30:55,680\n然后用这个环境来扩展环境\nuses that environment for the purpose of extending that environment\n\n483\n00:30:56,670 --> 00:30:59,024\n扩展把形式参数\nwhen abiding the formal parameters\n\n484\n00:30:59,024 --> 00:31:01,370\n和传递过来的实际参数绑定在一起的环境\nof the procedure to the arguments that were passed,\n\n485\n00:31:03,088 --> 00:31:05,984\n而不再是之前由过程捕获的环境了\nnot an environment that was captured in the procedure.\n\n486\n00:31:06,810 --> 00:31:09,456\n最早的Lisp偶然地采用了\nThe reason why the first Lisps were implemented this way,\n\n487\n00:31:09,664 --> 00:31:11,968\n这种最显然的方式实现\nis the sort of the obvious, accidental implementation.\n\n488\n00:31:14,130 --> 00:31:16,680\n当然 像往常一样 人们习惯了并喜欢上了它\nAnd, of course, as usual, people got used to it and liked it.\n\n489\n00:31:17,250 --> 00:31:18,272\n因此就有一些人说\nAnd there were some people said,\n\n490\n00:31:18,400 --> 00:31:19,504\n“就应该这么来做”\nthis is the way to do it.\n\n491\n00:31:21,590 --> 00:31:24,096\n不幸的是 这导致一些严重的问题\nUnfortunately that causes some serious problems.\n\n492\n00:31:25,408 --> 00:31:27,248\n最严重的一点是\nThe most important, serious problem\n\n493\n00:31:27,536 --> 00:31:29,840\n采用动态绑定\nin using dynamic binding\n\n494\n00:31:31,008 --> 00:31:33,568\n破坏了模块性\nis there's a modularity crisis that's involved it.\n\n495\n00:31:35,460 --> 00:31:37,664\n如果有两个人在一个大型系统上协同工作\nIf two people are working together on some big system,\n\n496\n00:31:38,576 --> 00:31:40,016\n那么一个重要的原则就是\nthen an important thing to one\n\n497\n00:31:40,352 --> 00:31:42,192\n每个人所使用的名字\nis that the names used by each one\n\n498\n00:31:42,992 --> 00:31:44,580\n都不应该干扰到对方的名字\ndon't interfere with the names of the other.\n\n499\n00:31:47,930 --> 00:31:50,784\n如果我写了一段代码\nIt's important that when I invent some segment of code\n\n500\n00:31:51,072 --> 00:31:53,136\n别人就不能通过在他代码内部\nthat no one can make my code stop working\n\n501\n00:31:53,880 --> 00:31:56,576\n使用我代码中的名字来破坏我的代码\nby using my names that I use internal to my code,\n\n502\n00:31:56,752 --> 00:31:57,710\n这一点很重要\ninternal to his code.\n\n503\n00:31:59,850 --> 00:32:00,464\n然而\nHowever,\n\n504\n00:32:01,040 --> 00:32:05,184\n动态绑定明显地违背了这种特定的模块化约束\ndynamic binding violates that particular modularity constraint in a clear way.\n\n505\n00:32:06,670 --> 00:32:08,080\n我们考虑一下\nConsider, for example,\n\n506\n00:32:09,184 --> 00:32:10,352\n这段代码会有什么效果？\nwhat happens over here.\n\n507\n00:32:12,540 --> 00:32:13,792\n假设我想要把\nSuppose it was the case\n\n508\n00:32:15,472 --> 00:32:19,810\n我想要把变量NEXT换个名字\nthat I decided to change the word next.\n\n509\n00:32:19,810 --> 00:32:24,416\n假设某个人要编写SUM过程\nSupposing somebody is writing, somebody is writing sum,\n\n510\n00:32:25,104 --> 00:32:26,688\n而别人则会使用这个SUM过程\nand somebody else is going to use sum.\n\n511\n00:32:28,970 --> 00:32:30,320\n编写SUM的那个人\nThe writer of sum\n\n512\n00:32:30,496 --> 00:32:32,304\n可以选择他想要使用的名字\nhas a choice of what names he may use.\n\n513\n00:32:33,664 --> 00:32:34,848\n假设我就是那个编写者\nLet's say, I'm that writer.\n\n514\n00:32:36,832 --> 00:32:39,300\n刚巧 这里我不想用NEXT来表示\nWell, by gosh, just happens I didn't want to call this next.\n\n515\n00:32:39,300 --> 00:32:40,096\n而是用N来表示\nI called it n.\n\n516\n00:32:41,740 --> 00:32:43,104\n所以我把所有出现NEXT的地方\nSo all places where you see next,\n\n517\n00:32:44,288 --> 00:32:45,260\n都换成N\nI called it n.\n\n518\n00:32:48,140 --> 00:32:48,480\n哎呀\nWhoops.\n\n519\n00:32:49,940 --> 00:32:52,224\n我没有改变这个程序的规范\nI changed nothing about the specifications of this program,\n\n520\n00:32:53,328 --> 00:32:54,864\n但是整个程序就崩溃了\nbut this program stops working.\n\n521\n00:32:56,110 --> 00:32:57,968\n不仅如此 这边也出现了问题\nNot only that, unfortunately, this one does too.\n\n522\n00:32:59,504 --> 00:33:01,408\n为什么会这样？\nWhy do these programs stop working?\n\n523\n00:33:02,260 --> 00:33:03,248\n答案非常明显\nWell, it's sort of clear.\n\n524\n00:33:04,480 --> 00:33:09,296\nNTH-POWER中的变量N的值\nInstead of chasing out the value of the n\n\n525\n00:33:09,310 --> 00:33:13,728\n也就是这个N和这个N\nthat occurs in nth power over here or over here,\n\n526\n00:33:14,976 --> 00:33:17,168\n根据环境模型的定义\nthrough the environment of definition,\n\n527\n00:33:17,200 --> 00:33:19,580\n这两个N总是相关的\nwhere this one is always linked to this one,\n\n528\n00:33:19,870 --> 00:33:21,488\n如果是根据环境模型的定义的话\nif it was through the environment of definition,\n\n529\n00:33:21,552 --> 00:33:23,630\n因为N在这里被绑定\nbecause here is the definition.\n\n530\n00:33:24,370 --> 00:33:26,256\n这个LAMBDA表达式是在\nThis lambda expression was executed\n\n531\n00:33:26,592 --> 00:33:28,592\nN被绑定的环境中执行的\nin the environment where that n was defined.\n\n532\n00:33:30,700 --> 00:33:31,840\n如果不用环境模型的话\nIf instead of doing that,\n\n533\n00:33:32,016 --> 00:33:33,680\n我必须追踪过程的调用链\nI have to chase through the call chain,\n\n534\n00:33:34,784 --> 00:33:36,272\n那么就会发生糟糕的事儿\nthen look what horrible thing happens.\n\n535\n00:33:37,320 --> 00:33:41,184\n在SUM内部 这个是作为TERM调用的\nWell, this was called from inside sum as term, term a.\n\n536\n00:33:41,760 --> 00:33:42,384\n这里的(TERM A)\nterm a.\n\n537\n00:33:44,780 --> 00:33:46,192\n这时再来查找N的值\nI'm looking for a value of n.\n\n538\n00:33:47,350 --> 00:33:48,400\n我得到的不知这个值\nInstead of getting this one,\n\n539\n00:33:48,848 --> 00:33:49,760\n而是这个值\nI get that one.\n\n540\n00:33:50,700 --> 00:33:52,544\n因此 只是这个程序的内部做了修改\nSo by changing the insides of this program,\n\n541\n00:33:52,864 --> 00:33:54,096\n这个程序却崩溃了\nthis program stops working.\n\n542\n00:33:56,770 --> 00:34:00,080\nLAMBDA就不再像我以前说得那样是个量词了\nSo I no longer have a quantifier, as I described before.\n\n543\n00:34:01,120 --> 00:34:05,136\nLAMBDA应该是一个量词\nWhich is a symbol -- The lambda symbol is supposed to be a quantifier.\n\n544\n00:34:05,430 --> 00:34:06,704\n量词有一个性质\nA thing which has the property\n\n545\n00:34:06,896 --> 00:34:11,424\n被它绑定的名字都不重要\nthat the names that are bound by it are unimportant,\n\n546\n00:34:12,656 --> 00:34:15,712\n只要我用不在过程体中的新名字\nthat I can uniformly substitute any names for these\n\n547\n00:34:16,928 --> 00:34:19,984\n统一地在过程体中代换旧名字\nthroughout this thing, so long as they don't occur in here, the new names,\n\n548\n00:34:20,944 --> 00:34:23,168\n就不会改变表达式的语义\nand the meaning of this expression should remain unchanged.\n\n549\n00:34:24,040 --> 00:34:25,504\n而我刚才却通过修改一个名字\nI've just changed the meaning of the expression\n\n550\n00:34:25,536 --> 00:34:27,200\n改变了表达式的语义\nby changing the one of the names.\n\n551\n00:34:28,690 --> 00:34:30,896\n因此LAMBDA就不再是一个良好定义的量词了\nSo lambda is no longer a well defined idea.\n\n552\n00:34:32,170 --> 00:34:33,376\n这个问题非常严重\nIt's a very serious problem.\n\n553\n00:34:34,550 --> 00:34:35,552\n正是因为这个原因\nSo for that reason,\n\n554\n00:34:36,640 --> 00:34:42,512\n我和同事放弃了这种抽象方法\nI and my buddies have given up this particular kind of abstraction,\n\n555\n00:34:43,136 --> 00:34:44,368\n相对的 我更喜欢\nwhich I would like to have,\n\n556\n00:34:45,616 --> 00:34:47,504\n模块化原则\nin favor of a modularity principle.\n\n557\n00:34:48,090 --> 00:34:50,208\n如果你愿意探索解释器\nBut this is the kind of experiment you can do\n\n558\n00:34:51,968 --> 00:34:53,680\n那就非常值得做这类实验\nif you want to play with these interpreters.\n\n559\n00:34:54,832 --> 00:34:56,912\n你可以尝试多种设计\nYou can try them out this way, that way, and the other way.\n\n560\n00:34:58,112 --> 00:35:00,256\n探索更优雅的语言设计\nYou see what makes a nicer language.\n\n561\n00:35:02,680 --> 00:35:04,496\n这是元循环求值器非常重要的功能\nSo that's a very important thing to be able to do.\n\n562\n00:35:04,990 --> 00:35:06,688\n现在 我也想讲一讲\nNow, I would like to give you a feeling\n\n563\n00:35:06,720 --> 00:35:08,496\n这种情况下的正确做法\nfor I think the right thing to do is here.\n\n564\n00:35:09,328 --> 00:35:12,912\n我又如何来获得这种\nHow are you going to, how are you going to I get this kind of\n\n565\n00:35:13,040 --> 00:35:15,344\n词法作用域的能力呢？\nof power in a lexical system?\n\n566\n00:35:16,280 --> 00:35:17,392\n当然 实际情况是\nAnd the answer is, of course,\n\n567\n00:35:17,552 --> 00:35:20,032\n在这里我想要的是\nwhat I really want is a something that makes up for me\n\n568\n00:35:20,688 --> 00:35:22,608\n针对特定N的求指数函数\nan exponentiator for a particular n.\n\n569\n00:35:23,690 --> 00:35:24,288\n给定一个N\nGiven an n,\n\n570\n00:35:24,320 --> 00:35:25,664\n它会返回给我一个特定的求指数过程\nit will make me an exponentiator.\n\n571\n00:35:26,280 --> 00:35:27,408\n这非常简单\nOh, but that's easy too.\n\n572\n00:35:28,170 --> 00:35:30,570\n换言之 我可以这样来写\nIn other words, I can write my program this way.\n\n573\n00:35:35,840 --> 00:35:37,840\n我要定义一个过程PGEN\nI'm going to define a thing called PGEN,\n\n574\n00:35:40,256 --> 00:35:42,544\n它有一个参数N\nwhich is a procedure of n\n\n575\n00:35:43,168 --> 00:35:45,952\n返回一个指数过程\nwhich produces for me an exponentiator.\n\n576\n00:35:50,240 --> 00:35:51,232\n计算X^N\n--x to the n.\n\n577\n00:35:56,800 --> 00:35:57,984\n有了这个以后\nGiven that I have that,\n\n578\n00:35:58,592 --> 00:36:00,880\n我就可以进行想要的那种抽象\nthen I can capture the abstraction I wanted\n\n579\n00:36:01,424 --> 00:36:03,936\n甚至于现在的封装方法还要更好一些\neven better, because now it's encapsulated in a way\n\n580\n00:36:04,096 --> 00:36:06,608\n因为系统现在不会因改名而崩溃了\nwhere I can't be destroyed by a change of names.\n\n581\n00:36:07,890 --> 00:36:12,352\n(DEFINE SUM-POWERS\nI can define some powers\n\n582\n00:36:17,280 --> 00:36:20,704\n(LAMBDA (A B N)\nI can define some powers to be a procedure again of a, b, and n\n\n583\n00:36:21,616 --> 00:36:26,832\n(SUM\nwhich is the sum of the term function\n\n584\n00:36:26,880 --> 00:36:32,320\n(PGEN N)\ngenerated by using this generator, PGEN, n,\n\n585\n00:36:34,400 --> 00:36:38,010\nA 1+ B)))\nwith a, incrementer, and b.\n\n586\n00:36:42,490 --> 00:36:47,952\n(DEFINE PRODUCT-POWERS\nAnd I can define the product of powers\n\n587\n00:36:54,112 --> 00:36:58,840\n(LAMBDA (A B N)\nto be a procedure of a, b, and n\n\n588\n00:36:59,808 --> 00:37:09,968\n(PRODUCT (PGEN N) A 1+ B)))\nwhich is the product PGEN, n, with a, increment, and b.\n\n589\n00:37:11,280 --> 00:37:13,280\n当然 这只是一个非常简单的例子\nNow, of course, this is a very simple example\n\n590\n00:37:13,600 --> 00:37:16,352\n这里 我想要抽象的对象也十分简单\nwhere this object that I'm trying to abstract over is small.\n\n591\n00:37:17,280 --> 00:37:18,832\n但它也有可能是长达100行的代码\nBut it could be a 100 lines of code.\n\n592\n00:37:20,100 --> 00:37:23,670\n我这么写是为了保持简单\nAnd so, the purpose of this is, of course, to make it simple.\n\n593\n00:37:23,670 --> 00:37:24,576\n我给它命了名\nI'd give a name to it,\n\n594\n00:37:24,736 --> 00:37:26,944\n这里它只是一个参数化的名字\nit's just that here it's a parameterized name.\n\n595\n00:37:28,200 --> 00:37:30,272\n这个名字显式地依赖于\nIt's a name that depends upon, explicitly,\n\n596\n00:37:30,496 --> 00:37:33,632\n词法作用域下N的值\nthe lexically apparent value of n.\n\n597\n00:37:37,130 --> 00:37:38,592\n因此可以把它看做一个很长的名字\nSo you can think of this as a long name.\n\n598\n00:37:40,210 --> 00:37:41,584\n这里 我是通过\nAnd here, I've solved my problem\n\n599\n00:37:41,760 --> 00:37:45,824\n为计算TERM的过程命名\nby naming my... by naming the term generation\n\n600\n00:37:46,128 --> 00:37:49,220\n来解决问题的\nprocedures within an n in them.\n\n601\n00:37:55,080 --> 00:37:55,872\n有什么问题吗？\nAre there any questions?\n\n602\n00:37:57,008 --> 00:37:58,380\nDavid 你说\nOh, yes, David.\n\n603\n00:37:58,570 --> 00:38:02,270\n学生：刚才那个问题\nAUDIENCE: Is the only solution to um...\n\n604\n00:38:03,070 --> 00:38:06,464\n只能通过新建一个过程来解决吗？\nthe problem you raise to create another procedure?\n\n605\n00:38:06,470 --> 00:38:08,928\n换句话说 是不是必须要语言能够\nIn other words, can this only work in languages that are\n\n606\n00:38:08,992 --> 00:38:11,568\n把对象定义为过程？\ncapable of defining objects as procedures?\n\n607\n00:38:12,416 --> 00:38:13,760\n教授：我明白了\nPROFESSOR: Oh, I see.\n\n608\n00:38:15,904 --> 00:38:19,744\n我构建抽象的这种方法\nMy solution to making this abstraction,\n\n609\n00:38:20,144 --> 00:38:22,864\n需要过程能够返回或者导出一个过程\nwhen I didn't want include the procedure inside the body,\n\n610\n00:38:23,264 --> 00:38:26,816\n以便我不想让过程体中包含特定过程\ndepends upon my ability to return a procedure or export one.\n\n611\n00:38:27,040 --> 00:38:27,248\n学生：没错\nAUDIENCE: And that's right.\n\n612\n00:38:28,190 --> 00:38:28,880\n教授：是这样的\nPROFESSOR: And that's right.\n\n613\n00:38:29,536 --> 00:38:31,520\n如果我不能这么做的话\nIf I don't have that,\n\n614\n00:38:32,240 --> 00:38:35,136\n那么我就无法去构造一个抽象\nthen I just don't have this ability to make an abstraction in a way\n\n615\n00:38:35,536 --> 00:38:41,776\n使得符号之间不会出现冲突\nwhere I don't have possibilities of symbol conflicts that were unanticipated.\n\n616\n00:38:43,000 --> 00:38:43,488\n你说得对\nThat's right.\n\n617\n00:38:44,144 --> 00:38:46,512\n我认为\nSo one of the, the essential -- I consider, I consider\n\n618\n00:38:46,540 --> 00:38:48,912\n能够把过程作为返回值\nbeing able to return the procedural value and, therefore,\n\n619\n00:38:49,200 --> 00:38:58,288\n更一般地说是支持“第一级过程”\nand therefore, to sort of have first class procedures, in general,\n\n620\n00:38:59,136 --> 00:39:02,464\n是模块化程序程序设计所必须的\nas being essential to doing very good modular programming.\n\n621\n00:39:03,700 --> 00:39:06,432\n有很多种方式来解决这个问题\nNow, indeed there are many other ways to skin this cat.\n\n622\n00:39:07,440 --> 00:39:09,168\n你可以的做的就是\nWhat you can do is take for each of the\n\n623\n00:39:09,184 --> 00:39:11,840\n针对你所需要关心的每一种糟糕情况\nfor each of the bad things that you have to worry about,\n\n624\n00:39:12,272 --> 00:39:15,200\n你可以添加一个特殊的FEATURE来解决它\nyou can make a special feature that covers that thing.\n\n625\n00:39:15,840 --> 00:39:17,120\n你可以做一个包系统\nYou can make a package system.\n\n626\n00:39:17,744 --> 00:39:21,168\n或者像Ada中的模块系统 等等\nYou can make a module system as in Ada, et cetera. OK?\n\n627\n00:39:22,240 --> 00:39:24,880\n这些都可以 可能区别只是解决的程度不一\nAnd all of those work, or they cover little regions of it.\n\n628\n00:39:26,440 --> 00:39:28,384\n而能够把过程作为返回值\nThe thing is that returning procedures as values\n\n629\n00:39:28,416 --> 00:39:29,740\n可以解决这所有的问题\ncover all of those problems.\n\n630\n00:39:32,688 --> 00:39:34,608\n这种最简单的机制\nAnd so it's the simplest mechanism\n\n631\n00:39:35,584 --> 00:39:37,792\n却可以给予你最好的模块性\nthat gives you the best modularity,\n\n632\n00:39:39,216 --> 00:39:41,312\n它赋予你所有已知的模块机制\ngives you all of the known modularity mechanisms.\n\n633\n00:39:45,590 --> 00:39:48,248\n好的 该休息一会儿了 谢谢大家\nWell, I suppose it's time for the next break, thank you.\n\n634\n00:39:48,240 --> 00:40:01,088\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n635\n00:40:01,280 --> 00:40:04,752\n《计算机程序的构造和解释》\n\n636\n00:40:25,690 --> 00:40:29,424\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n637\n00:40:30,010 --> 00:40:33,280\n《计算机程序的构造和解释》\n\n638\n00:40:34,170 --> 00:40:37,616\n元循环求值器 II\n\n639\n00:40:42,320 --> 00:40:44,288\n教授：昨天你们学习流的时候\nPROFESSOR: Well, yesterday when you learned about streams,\n\n640\n00:40:46,016 --> 00:40:51,168\nHal教授告诉了你们求值顺序\nHal worried to you about the order of evaluation\n\n641\n00:40:51,952 --> 00:40:53,872\n以及过程的延迟求值\nand delayed arguments to procedures.\n\n642\n00:40:55,616 --> 00:40:58,304\n昨天在讲流的时候 我们说\nThe way we played with streams yesterday,\n\n643\n00:41:00,250 --> 00:41:04,224\n调用者和被调者都应该认同\nit was the responsibility of the caller and the callee\n\n644\n00:41:05,776 --> 00:41:08,848\n参数是被延迟了的\nboth agree that an argument was delayed,\n\n645\n00:41:09,424 --> 00:41:13,440\n如果被调者需要结果 就需要对参数FORCE\nand the callee must force the argument if it needs the answer.\n\n646\n00:41:15,130 --> 00:41:17,872\n因此在过程的设计者和使用者之间\nSo there had to be a lot of hand shaking between\n\n647\n00:41:18,176 --> 00:41:24,320\n就有很多关于延时求值的握手\nthe designer of a procedure and user of it over delayedness.\n\n648\n00:41:26,368 --> 00:41:28,720\n当然 这看起来相当糟糕\nThat turns out, of course, to be a fairly bad thing,\n\n649\n00:41:29,488 --> 00:41:30,960\n虽说对于流没什么不妥\nit works all right with streams.\n\n650\n00:41:31,740 --> 00:41:32,864\n但作为一般性的原则来说\nBut as a general thing,\n\n651\n00:41:32,928 --> 00:41:36,320\n我们希望能有个地方\nwhat you want is an idea to have a locus,\n\n652\n00:41:36,464 --> 00:41:38,496\n能够把我们的设计考虑\na decision, a design decision in general,\n\n653\n00:41:38,890 --> 00:41:41,280\n显式地、清晰地\nto have a place where it's made, explicitly,\n\n654\n00:41:41,632 --> 00:41:43,930\n标注出来\nand notated in a clear way.\n\n655\n00:41:45,888 --> 00:41:49,280\n因此就不必在过程编写者\nAnd so it's not a very good idea to have to have an agreement,\n\n656\n00:41:50,464 --> 00:41:54,896\n和使用者之间达成共识\nbetween the person who writes a procedure and the person who calls it,\n\n657\n00:41:55,088 --> 00:41:57,984\n有关于参数求值\nabout such details as, maybe, the arguments of evaluation,\n\n658\n00:41:58,432 --> 00:41:59,500\n以及求值顺序等细节\nthe order of evaluation.\n\n659\n00:41:59,500 --> 00:42:00,750\n虽然 这也不是太糟糕\nAlthough, that's not so bad.\n\n660\n00:42:01,024 --> 00:42:03,952\n我的意思是 可能还有像“输入是一个数字”这样的共识\nI mean, we have other such agreements like, the input's a number.\n\n661\n00:42:05,200 --> 00:42:06,080\n但是\nBut it would be nice if\n\n662\n00:42:06,352 --> 00:42:09,200\n如果其中一个人可以全权负责 就再好不过了\none of these guys could take responsibility, completely.\n\n663\n00:42:11,020 --> 00:42:13,312\n这个想法已经不算新潮了\nNow this is not a new idea.\n\n664\n00:42:15,510 --> 00:42:21,168\nAlgol60就支持两种不同的过程调用方法\nALGOL 60 had two different ways of calling a procedure.\n\n665\n00:42:22,020 --> 00:42:24,288\n参数可以按名或按值传递\nThe arguments could be passed by name or by value.\n\n666\n00:42:25,590 --> 00:42:27,488\n按名传递就意味着\nAnd what that meant was that\n\n667\n00:42:27,632 --> 00:42:29,720\n参数会延时求值\na name argument was delayed.\n\n668\n00:42:31,110 --> 00:42:32,848\n当你按名传递一个参数时\nThat when you passed an argument by name,\n\n669\n00:42:33,648 --> 00:42:36,528\n只有你去取它的值的时候\nthat its value would only be obtained\n\n670\n00:42:36,960 --> 00:42:39,552\n它的值才会被计算出来\nif you accessed that argument.\n\n671\n00:42:42,290 --> 00:42:44,208\n所以 现在我就要\nSo what I'd like to do now is show you,\n\n672\n00:42:44,432 --> 00:42:46,960\n像之前那样\nfirst of all, a little bit about, again,\n\n673\n00:42:46,992 --> 00:42:48,656\n对语言做出一些小小的修改\nwe're going to make a modification to a language.\n\n674\n00:42:50,320 --> 00:42:51,792\n这里 我们再添加一个新的FEATURE\nIn this case, we're going to add a feature.\n\n675\n00:42:53,370 --> 00:42:55,056\n我们要添加的FEATURE是\nWe're going to add the feature of,\n\n676\n00:42:55,360 --> 00:42:58,736\n“按名传递参数” 或者可以叫做“延迟求值参数”\nby name parameters, if you will, or delayed parameters.\n\n677\n00:43:00,430 --> 00:43:04,416\n因为事实上 Lisp系统中默认\nBecause, in fact, the default in our Lisp system\n\n678\n00:43:04,768 --> 00:43:06,608\n传递的是一个指针\nis by the value of a pointer.\n\n679\n00:43:08,220 --> 00:43:09,152\n指针被复制了一份\nA pointer is copied,\n\n680\n00:43:09,152 --> 00:43:10,910\n但所指的数据结构却没有被复制\nbut the data structure it points at is not.\n\n681\n00:43:13,410 --> 00:43:14,848\n现在我要告诉你们\nBut I'd like to, in fact, show you\n\n682\n00:43:15,040 --> 00:43:18,384\n如何来添加按名传递参数\nis how you add name arguments as well.\n\n683\n00:43:19,990 --> 00:43:22,128\n为什么我们需要这样的FEATURE呢？\nNow again, why would we need such a thing?\n\n684\n00:43:23,100 --> 00:43:24,720\n假设我们想要开发\nWell supposing we wanted to invent\n\n685\n00:43:25,248 --> 00:43:28,448\n像是某种特殊形式的功能\ncertain kinds of what otherwise would be special forms,\n\n686\n00:43:28,736 --> 00:43:29,720\n类似于“保留字”\nreserve words?\n\n687\n00:43:29,720 --> 00:43:31,488\n但不是用保留字的方式来实现 \nBut I'd rather not take up reserve words.\n\n688\n00:43:32,180 --> 00:43:34,768\n我想用过程来实现类似IF的效果\nI want procedures that can do things like if.\n\n689\n00:43:36,360 --> 00:43:39,420\n无论是IF还是COND 都是特殊形式\nIf is special, or cond, or whatever it is.\n\n690\n00:43:39,420 --> 00:43:40,432\n它俩是一样的\nIt's the same thing.\n\n691\n00:43:40,590 --> 00:43:42,864\n这个特殊形式用于\nIt's special in that it determines whether or not\n\n692\n00:43:42,928 --> 00:43:45,020\n根据谓词返回真假\nto evaluate the consequent or the alternative\n\n693\n00:43:46,224 --> 00:43:49,760\n决定求值真子句还是假子句\nbased on the value of the predicate part of an expression.\n\n694\n00:43:50,840 --> 00:43:53,120\n它们都是根据某个值\nSo taking the value of one thing\n\n695\n00:43:53,440 --> 00:43:55,360\n来决定是否去做另外的某件事\ndetermines whether or not to do something else.\n\n696\n00:43:57,270 --> 00:43:58,880\n然而像+之类的过程\nWhereas all the procedures like plus,\n\n697\n00:43:59,152 --> 00:44:01,200\n也就是那些我们现在可以定义的过程\nevaluate... the ones that we can define right now,\n\n698\n00:44:01,424 --> 00:44:06,560\n是在应用前就求值所有的参数\nevaluate all of their arguments before application.\n\n699\n00:44:08,670 --> 00:44:09,648\n因此 举例来说\nSo, for example,\n\n700\n00:44:10,464 --> 00:44:12,416\n假设我想定义一个过程\nsupposing I wish to be able to define something like\n\n701\n00:44:15,392 --> 00:44:18,752\n用IF来实现与IF相反的效果\nthe reverse of if in terms of if.\n\n702\n00:44:19,856 --> 00:44:20,700\n我叫它UNLESS\nCall it unless.\n\n703\n00:44:24,890 --> 00:44:27,472\n参数是 谓词P、真子句C和假子句A\nWe've a predicate, a consequent, and an alternative.\n\n704\n00:44:28,672 --> 00:44:30,448\n接下来 我想\nNow what I would like to sort of be able to do is\n\n705\n00:44:30,464 --> 00:44:32,080\n用COND来实现\nsay-- oh, I'll do it in terms of cond.\n\n706\n00:44:32,640 --> 00:44:36,720\n(COND ((NOT P)\nCond, if not the predicate,\n\n707\n00:44:38,960 --> 00:44:40,320\n结果就是真子句C\nthen take the consequent,\n\n708\n00:44:41,584 --> 00:44:45,632\n否则就是假子句A\notherwise, take the alternative.\n\n709\n00:44:51,290 --> 00:44:52,768\n我定义这个过程是为了\nNow, what I'd like this to mean,\n\n710\n00:44:53,328 --> 00:44:55,408\n请考虑下面这种情况\nis supposing I do something like this.\n\n711\n00:44:56,920 --> 00:45:04,128\n(UNLESS (= 1 0)\nI'd like this unless say if equals one, 0,\n\n712\n00:45:05,088 --> 00:45:06,640\n那么结果就是2\nthen the answer is two,\n\n713\n00:45:07,904 --> 00:45:11,350\n否则 结果就是(/ 1 0)\notherwise, the quotient of one and 0.\n\n714\n00:45:15,920 --> 00:45:18,912\n这段代码相当于进行这样的代换：\nWhat I'd like that to mean is the result of substituting\n\n715\n00:45:20,000 --> 00:45:23,264\n用(= 1 0)、2和(/ 1 0)\nequal one, 0, and the quotient of one, 0\n\n716\n00:45:23,664 --> 00:45:24,760\n分别代换上面的P、C以及A\nfor p, c, and a.\n\n717\n00:45:25,580 --> 00:45:27,584\n这样很有趣\nI'd like that to mean, and this is funny,\n\n718\n00:45:28,112 --> 00:45:30,336\n代换后就变成了\nI'd like it to transform into or mean\n\n719\n00:45:30,752 --> 00:45:38,448\n(COND ((NOT (= 1 0))\ncond not equal one, 0,\n\n720\n00:45:40,624 --> 00:45:42,544\n结果就是2\nthen the result is two,\n\n721\n00:45:44,280 --> 00:45:45,104\n否则就是\notherwise\n\n722\n00:45:48,224 --> 00:45:51,160\n(/ 1 0)\nI want it to be the quotient one and 0.\n\n723\n00:45:54,480 --> 00:45:56,480\n你们也知道 如果向Lisp中输入这段代码\nNow, you know that if I were to type this into Lisp,\n\n724\n00:45:57,744 --> 00:45:58,592\n结果会是2\nI'd get a two.\n\n725\n00:45:59,970 --> 00:46:01,328\n这没问题\nThere's no problem with that.\n\n726\n00:46:02,910 --> 00:46:04,640\n但如果我输入的是这段代码\nHowever, if I were to type this into Lisp,\n\n727\n00:46:05,280 --> 00:46:07,792\n由于参数会在过程调用前求值\nbecause all the arguments are evaluated before I start,\n\n728\n00:46:09,120 --> 00:46:10,736\n那么这段代码就会报错\nthen I'm going to get an error out of this.\n\n729\n00:46:13,380 --> 00:46:15,616\n当然 如果成功进行代换的话\nSo that if the substitutions work at all, of course,\n\n730\n00:46:16,032 --> 00:46:16,880\n我可以得到正确的结果\nI would get the right answer.\n\n731\n00:46:16,880 --> 00:46:20,160\n但是这里这种情况 代换并不能进行\nBut here's a case where the substitutions don't work.\n\n732\n00:46:22,176 --> 00:46:23,860\n我连错误的结果都无法得到\nI don't get the wrong answer.\n\n733\n00:46:23,860 --> 00:46:24,670\n没有结果\nI get no answer.\n\n734\n00:46:24,800 --> 00:46:25,600\n只能得到错误\nI get an error.\n\n735\n00:46:28,420 --> 00:46:31,216\n现在 我要想办法\nNow, however, I'd like to be able to make my definition\n\n736\n00:46:31,616 --> 00:46:32,992\n使这样的定义可以成功运行\nso that this kind of thing works.\n\n737\n00:46:34,480 --> 00:46:36,512\n但我想标注出\nWhat I want to do is say something special\n\n738\n00:46:36,704 --> 00:46:38,760\nC和A是特殊的东西\nabout c and a.\n\n739\n00:46:39,930 --> 00:46:43,152\n我想使它们自动地延时求值\nI want them to be delayed automatically.\n\n740\n00:46:44,272 --> 00:46:48,080\n我不想它们在我调用过程的时候\nI don't want them to be, I don't want them to be evaluated\n\n741\n00:46:48,528 --> 00:46:49,744\n就被求值\nat the time I call.\n\n742\n00:46:51,520 --> 00:46:52,720\n所以我得先制定一种声明\nSo I'm going to make a declaration,\n\n743\n00:46:52,752 --> 00:46:55,328\n然后再考虑如何实现此种声明\nand then I'm going to see how to implement such a declaration.\n\n744\n00:46:55,600 --> 00:46:57,632\n再次强调 希望你们能够提醒自己\nBut again, I want you to say to yourself,\n\n745\n00:46:57,792 --> 00:47:00,256\n我们这里添加的是临时组件\noh, this is an interesting kluge he's adding in here.\n\n746\n00:47:00,760 --> 00:47:02,160\n必须要知道\nA kluge, you know.\n\n747\n00:47:02,256 --> 00:47:04,720\n滥用临时组件会造成大混乱\nThe piles of kluges make a big complicated mess.\n\n748\n00:47:05,750 --> 00:47:09,792\n还会破坏一些已有的东西\nAnd is this going to foul up something else that might occur.\n\n749\n00:47:10,120 --> 00:47:12,704\n首先 它会造成语法歧义性么？\nFirst of all, is it syntactically unambiguous?\n\n750\n00:47:13,860 --> 00:47:15,504\n就我们目前已有的语法来说\nWell, it will be syntactically unambiguous\n\n751\n00:47:15,712 --> 00:47:16,910\n它不会造成什么歧义\nwith what we've seen so far.\n\n752\n00:47:17,840 --> 00:47:20,768\n但接下来要做的却可能招来麻烦\nBut what I'm going to do may, in fact, cause trouble.\n\n753\n00:47:21,670 --> 00:47:24,672\n我要添加的东西可能会跟\nIt may be that the thing I had will conflict with\n\n754\n00:47:25,152 --> 00:47:27,104\n我以后添加的类型声明冲突\ntype declarations I might want to add in the future\n\n755\n00:47:28,192 --> 00:47:31,088\n类型系统通过提供已知的类型信息\nfor giving some system, some compiler or something,\n\n756\n00:47:31,216 --> 00:47:33,664\n使得语言系统或者编译器可以做出优化\nthe ability to optimize given the types are known.\n\n757\n00:47:34,750 --> 00:47:36,976\n当然也会与我想添加的形式参数的\nOr it might conflict with other types of declarations\n\n758\n00:47:37,008 --> 00:47:39,710\n其它类型的声明相冲突\nthat I might want to make about the formal parameters.\n\n759\n00:47:40,570 --> 00:47:42,560\n所以这里我并不打算做一个一般性的机制\nSo I'm not making a general mechanism here\n\n760\n00:47:43,770 --> 00:47:45,248\n使得我可以添加声明\nwhere I can add declarations.\n\n761\n00:47:45,280 --> 00:47:46,544\n虽然我很想那么做\nAnd I would like to be able to do that.\n\n762\n00:47:46,896 --> 00:47:48,816\n但现在并不打算这么做\nBut I don't want to talk about that right now.\n\n763\n00:47:51,010 --> 00:47:53,888\n接下来 我要添加某种临时的解决方法\nSo here I'm going to do, I'm going to build a kluge.\n\n764\n00:47:57,568 --> 00:48:08,384\n(DEFINE (UNLESS P\nSo we're going to define unless of a predicate--\n\n765\n00:48:08,810 --> 00:48:10,272\n后面的参数都是按名调用\nand I'm going to call these by name--\n\n766\n00:48:12,784 --> 00:48:15,280\n分别记作(NAME C)和(NAME A)\nthe consequent, and name the alternative.\n\n767\n00:48:19,850 --> 00:48:25,280\n哈 哈 卡在黑板边了\nHuh, huh-- I got caught in the corner.\n\n768\n00:48:31,760 --> 00:48:35,616\n(COND ((NOT P) C)\nIf not p then the result is c,\n\n769\n00:48:36,800 --> 00:48:41,168\n(ELSE A)))\nelse-- that's what I'd like.\n\n770\n00:48:44,670 --> 00:48:46,880\n我可以显式地声明\nWhere I can explicitly declare\n\n771\n00:48:47,552 --> 00:48:51,650\n哪些参数按名称传递或延时求值\ncertain of the parameters to be delayed, to be computed later.\n\n772\n00:48:55,600 --> 00:48:58,480\n对解释器的这个修改并不简单\nNow, this is actually a very complicated modification to an interpreter\n\n773\n00:48:58,704 --> 00:48:59,776\n反而相当复杂\nrather than a simple one.\n\n774\n00:49:00,450 --> 00:49:03,104\n我们之前介绍的动态绑定\nThe ones you saw before, dynamic binding\n\n775\n00:49:03,408 --> 00:49:06,896\n或者让过程支持不定数目的参数\nor adding indefinite argument procedures,\n\n776\n00:49:07,504 --> 00:49:08,528\n都相对简单\nis relatively simple.\n\n777\n00:49:09,280 --> 00:49:11,280\n这次的修改涉及基本策略\nBut this one changes a basic strategy.\n\n778\n00:49:12,320 --> 00:49:13,392\n这里的问题是\nThe problem here\n\n779\n00:49:13,968 --> 00:49:17,630\n我们的解释器 就如代码所写的那样\nis that our interpreter, as written\n\n780\n00:49:17,960 --> 00:49:23,408\n在求值组合式时\nevaluates a combination by evaluating the procedure,\n\n781\n00:49:24,240 --> 00:49:25,920\n先通过求值运算符取得过程\nthe operator producing the procedure,\n\n782\n00:49:26,208 --> 00:49:30,352\n然后再求值运算对象得到参数\nand evaluating the operands producing the arguments,\n\n783\n00:49:30,768 --> 00:49:35,264\n再把过程应用到参数上\nand then doing apply of the procedure to the arguments.\n\n784\n00:49:36,384 --> 00:49:37,072\n然而这里\nHowever, here,\n\n785\n00:49:37,360 --> 00:49:41,488\n直到我检查了整个过程\nI don't want to evaluate the operands to produce the arguments\n\n786\n00:49:41,740 --> 00:49:43,660\n确定了程序的声明\nuntil after I examined the procedure\n\n787\n00:49:44,624 --> 00:49:46,864\n才会去求值程序的参数\nto see what the procedure's declarations look like.\n\n788\n00:49:49,590 --> 00:49:50,592\n我们来看这个\nSo let's look at that.\n\n789\n00:49:52,680 --> 00:49:56,544\n这是修改后的求值器\nHere we have a changed evaluator.\n\n790\n00:49:57,480 --> 00:50:01,152\n我是基于那个最简单的词法作用域求值器\nI'm starting with the simple lexical evaluator,\n\n791\n00:50:01,728 --> 00:50:02,650\n不是动态绑定的那个\nnot dynamic\n\n792\n00:50:04,144 --> 00:50:08,208\n但是却要做一些类似于动态绑定的修改\nbut we're going to have to do something sort of similar in some ways.\n\n793\n00:50:09,750 --> 00:50:11,456\n这是因为\nBecause of the fact that,\n\n794\n00:50:11,904 --> 00:50:13,344\n如果我延时一个过程 --\nif I delay a procedure--\n\n795\n00:50:13,664 --> 00:50:15,152\n哦说错了 -- 延时一个过程的参数\nI'm sorry-- delay an argument to a procedure,\n\n796\n00:50:15,408 --> 00:50:17,520\n就必须把当前的环境和参数关联在一起\nI'm going to have to attach and environment to it.\n\n797\n00:50:19,360 --> 00:50:21,552\n还记得Hal教授如何实现DELAY的吧？\nRemember how Hal implemented delay.\n\n798\n00:50:23,380 --> 00:50:25,440\nHal教授把DELAY实现为\nHal implemented delay as being\n\n799\n00:50:25,504 --> 00:50:27,472\n一个无参过程\na procedure of no arguments\n\n800\n00:50:28,560 --> 00:50:30,528\n用来执行某些表达式\nwhich does some expression.\n\n801\n00:50:31,180 --> 00:50:36,944\n就是这样让表达式延迟求值的\nThat's what delay of the expression is. --of that expression.\n\n802\n00:50:39,296 --> 00:50:40,992\n(DELAY E)实际上是这个\nThis turned into something like this.\n\n803\n00:50:44,520 --> 00:50:46,928\n然而 如果我求值这个LAMBDA表达式\nNow, however, if I evaluate a lambda expression,\n\n804\n00:50:47,424 --> 00:50:49,200\n我就必须得捕获当前环境\nI have to capture the environment.\n\n805\n00:50:51,410 --> 00:50:53,456\n这是因为\nThe reason why is because there are\n\n806\n00:50:54,608 --> 00:50:56,320\n我想让这其中的变量的值\nthere are variables in there\n\n807\n00:50:57,024 --> 00:51:00,832\n取决于它们被定义时的上下文\nwho's meaning I wish to derive from the context where this was written.\n\n808\n00:51:04,010 --> 00:51:05,760\n这也就是为什么要用LAMBDA表达式\nSo that's why a lambda does the job.\n\n809\n00:51:06,624 --> 00:51:07,504\n这才是正确的\nIt's the right thing.\n\n810\n00:51:08,070 --> 00:51:15,120\n(FORCE E)则相当于\nAnd such that the forcing of a delayed expression\n\n811\n00:51:16,528 --> 00:51:20,080\n无参地调用这个过程\nwas same thing as calling that with no arguments.\n\n812\n00:51:21,090 --> 00:51:22,288\n恰恰和上面相对\nIt's just the opposite of this.\n\n813\n00:51:24,100 --> 00:51:26,944\n这个调用产生的环境则是\nProducing an environment of the call\n\n814\n00:51:27,360 --> 00:51:29,904\n定义这个过程时的环境\nwhich is, in fact, the environment where this was defined\n\n815\n00:51:30,816 --> 00:51:32,368\n额外加上一个空框架\nwith an extra frame in it that's empty.\n\n816\n00:51:33,232 --> 00:51:34,416\n我并不在意它\nI don't care about that.\n\n817\n00:51:36,240 --> 00:51:39,408\n我们再来看这张幻灯片\nWell, if we go back to this slide,\n\n818\n00:51:40,992 --> 00:51:43,728\n仔细观察一会儿\nsince it's the case, if we look at this for a second,\n\n819\n00:51:44,144 --> 00:51:46,128\n会发现大部分跟以前相同\neverything is the same as it was before\n\n820\n00:51:46,350 --> 00:51:50,656\n只是对应用或组合式的处理不同\nexcept the case of applications or combinations.\n\n821\n00:51:51,980 --> 00:51:53,712\n处理组合式分两步\nAnd combinations are going to do two things.\n\n822\n00:51:54,680 --> 00:51:57,792\n首先要求值这个过程\nOne, is I have to evaluate the procedure--\n\n823\n00:51:57,920 --> 00:51:59,888\n我就必须通过求值运算符来得到对应过程\nI have to get the procedure-- by evaluating the operator.\n\n824\n00:52:00,704 --> 00:52:01,696\n也就是这一部分\nThat's what you see right here.\n\n825\n00:52:02,380 --> 00:52:04,352\n我得这个值是计算求出的现值\nI have to make sure that that's current,\n\n826\n00:52:04,464 --> 00:52:05,760\n而不是一个延时对象\nthat is not a delayed object,\n\n827\n00:52:06,368 --> 00:52:09,856\n也就要求值它在被延时前的表达式\nand evaluate that to the point where became it's forced now.\n\n828\n00:52:10,730 --> 00:52:12,080\n接下来我就要\nAnd then I have to somehow\n\n829\n00:52:12,240 --> 00:52:17,328\n把它应用于运算对象\napply that to the, to the operands.\n\n830\n00:52:18,030 --> 00:52:19,616\n但我仍然要保持这个环境\nBut I have to keep the environment,\n\n831\n00:52:19,632 --> 00:52:20,920\n并将其传递过去\npass that environmental along.\n\n832\n00:52:21,530 --> 00:52:23,710\n如果有一些运算对象是延时了的\nSo some of those operands I may have to delay.\n\n833\n00:52:23,710 --> 00:52:27,536\n我就需要为这些运算对象附上相应的环境\nI may have to attach that environment to those operands.\n\n834\n00:52:29,664 --> 00:52:31,520\n这里的处理相当复杂\nThis is a rather complicated thing happening here.\n\n835\n00:52:32,990 --> 00:52:34,240\n来看看APPLY中对应的部分\nLooking at that in apply.\n\n836\n00:52:36,400 --> 00:52:38,720\nAPPLY这一部分处理基本过程\nApply, well it has a primitive procedure\n\n837\n00:52:39,360 --> 00:52:40,600\n这和之前一样\nthing just like before.\n\n838\n00:52:42,610 --> 00:52:44,688\n但复合过程部分就比较有意思了\nBut the compound one is a little more interesting.\n\n839\n00:52:47,250 --> 00:52:49,520\n和之前一样 我需要求值过程体\nI have to evaluate the body, just as before,\n\n840\n00:52:50,480 --> 00:52:51,984\n基于的环境是\nin an environment which is\n\n841\n00:52:52,288 --> 00:52:54,976\n把形式参数和\nwhich is the result of binding some\n\n842\n00:52:55,616 --> 00:53:00,290\n实际参数绑定在一起的结果\nformal parameters to arguments in the environment.\n\n843\n00:53:00,290 --> 00:53:01,072\n是这样的\nThat's true.\n\n844\n00:53:01,530 --> 00:53:03,820\n环境来自于过程对象\nThe environment is the one that comes from the procedure now.\n\n845\n00:53:03,820 --> 00:53:06,656\n因为我们的语言是词法作用域、静态绑定的\nIt's a lexical language, statically bound.\n\n846\n00:53:08,040 --> 00:53:11,824\n然而 我还需要去掉NAME声明\nHowever, one thing I have to do is strip off the declarations\n\n847\n00:53:11,840 --> 00:53:12,840\n获得变量的实际名字\nto get the names of the variables.\n\n848\n00:53:12,848 --> 00:53:15,200\n这是由VNAMES过程完成的\nThat's what this guy does, vnames.\n\n849\n00:53:15,450 --> 00:53:16,672\n然后要做的就是\nAnd the other thing I have to do\n\n850\n00:53:16,976 --> 00:53:18,864\n处理这些声明\nis process these declarations,\n\n851\n00:53:19,136 --> 00:53:21,520\n决定这些运算对象中\ndeciding which of these operands--\n\n852\n00:53:21,760 --> 00:53:23,920\n现在它们还是形式参数 而非实际参数\nthat's the operands now, as opposed to the arguments--\n\n853\n00:53:24,096 --> 00:53:25,872\n哪些运算对象需要立即求值\nwhich of these operands to evaluate,\n\n854\n00:53:26,624 --> 00:53:30,208\n而哪些运算对象又要\nand which of them are to be\n\n855\n00:53:30,992 --> 00:53:33,770\n用某种方式封装为延时对象\nencapsulated in delays of some sort.\n\n856\n00:53:37,280 --> 00:53:40,080\n另外 在处理基本过程这里\nThe other thing you see here is that we got a primitive,\n\n857\n00:53:40,600 --> 00:53:42,384\n当遇到像+这样的基本过程\na primitive like plus,\n\n858\n00:53:42,688 --> 00:53:45,580\n它们的参数最好立即求值\nhad better get at the real operands.\n\n859\n00:53:45,820 --> 00:53:47,392\n也就我们需要是这里FORCE这些表达式\nSo here is a place where we're going to have to force them.\n\n860\n00:53:47,920 --> 00:53:50,384\nEVLIST中完成了很多FORCE操作\nAnd we're going to look at what evlist is going to have to do a bunch of forces.\n\n861\n00:53:51,340 --> 00:53:52,780\n现在 我们有了两种不同的EVLIST\nSo we have two different kinds of evlist now.\n\n862\n00:53:52,780 --> 00:53:54,096\nEVLIST和GEVLIST\nWe have evlist and gevlist.\n\n863\n00:53:54,520 --> 00:53:57,168\nGEVLIST封装延迟参数\nGevlist is going to wrap delays around some things\n\n864\n00:53:57,184 --> 00:53:59,740\n而对另外的参数立即求值\nand force others, evaluate others.\n\n865\n00:53:59,870 --> 00:54:05,856\n而EVLIST则会FORCE所有的表达式\nAnd this guy's going to do some forcing of things.\n\n866\n00:54:07,900 --> 00:54:09,168\n简单地看下EVLIST的代码\nJust looking at this a little bit,\n\n867\n00:54:09,696 --> 00:54:11,984\n课后你们一定要亲自上手试试\nthis is a game you must play for yourself, you know.\n\n868\n00:54:12,250 --> 00:54:14,672\n光是听我在这里讲课\nIt's not something that you're going to see all possible\n\n869\n00:54:14,720 --> 00:54:18,200\n可不能够学到求值器的不同变种\nvariations on an evaluator talking to me.\n\n870\n00:54:19,520 --> 00:54:21,248\n你们需要上手亲自实践一下。\nWhat you have to do is do this for yourself.\n\n871\n00:54:21,376 --> 00:54:23,840\n你试验过后 对它们有了感悟\nAnd after you feel this, you play this a bit,\n\n872\n00:54:24,224 --> 00:54:27,024\n你才能理解各种可能的设计决策\nyou get to see all the possible design decisions and what they might mean,\n\n873\n00:54:27,776 --> 00:54:29,168\n才能清楚它们如何相互关联\nand how they interact with each other.\n\n874\n00:54:29,930 --> 00:54:32,384\n了解求值器描述的是何种语言\nSo what languages might have in them.\n\n875\n00:54:33,160 --> 00:54:34,640\n以及构建一门合理的语言\nAnd what are some of the consistent sets\n\n876\n00:54:34,944 --> 00:54:36,320\n需要哪些一致性集合\nthat make a legitimate language.\n\n877\n00:54:37,200 --> 00:54:40,064\n哪些临时方案又是复杂而无用\nWhereas what things are complicated kluges that are just piles of junk.\n\n878\n00:54:41,850 --> 00:54:44,688\n就和我说得一样 这里的EVLIST\nSo evlist of course, over here, just as I said,\n\n879\n00:54:44,816 --> 00:54:46,032\n参数之一为运算对象表\nis a list of operands\n\n880\n00:54:46,704 --> 00:54:50,280\n表中的元素会在求值之后被取消延时\nwhich are going to be undelayed after evaluation.\n\n881\n00:54:50,750 --> 00:54:51,904\n它们都会被FORCE\nSo these are going to be forced,\n\n882\n00:54:53,280 --> 00:54:54,448\n无论它们是否为延时对象\nwhatever that's going to mean.\n\n883\n00:54:56,050 --> 00:54:58,512\n下一个 GEVLIST\nAnd gevlist, which is the next thing--\n\n884\n00:55:01,264 --> 00:55:01,856\n谢谢\nThank you.\n\n885\n00:55:04,040 --> 00:55:06,350\n我们在这里会发现\nWhat we see here, uh\n\n886\n00:55:07,808 --> 00:55:09,616\n这里面有多种可能\nwell there's a couple of possibilities.\n\n887\n00:55:09,810 --> 00:55:11,520\n要么是普通的情况\nEither it's a normal, ordinary thing,\n\n888\n00:55:12,480 --> 00:55:13,696\n比如元素直接是一个符号\na symbol sitting there\n\n889\n00:55:13,744 --> 00:55:16,200\n就像UNLESS中的参数P那样\nlike the predicate in the unless,\n\n890\n00:55:17,648 --> 00:55:18,816\n对应这一部分代码\nand that's what we have here.\n\n891\n00:55:19,390 --> 00:55:22,496\n在这种情况下 我们就用应用序来求值\nIn which case, this is intended to be evaluated in applicative order.\n\n892\n00:55:23,340 --> 00:55:25,456\n基本上就像以前一样\nAnd it's, essentially, just what we had before.\n\n893\n00:55:25,630 --> 00:55:28,848\n就是将EVAL映射在这个表上\nIt's mapping eval down the list.\n\n894\n00:55:29,952 --> 00:55:32,144\n换言之 就是先求值第一个表达式\nIn other words, I evaluate the first expression\n\n895\n00:55:32,656 --> 00:55:37,360\n然后在ENV中 求值(GEVLIST (CDR EXPRS))\nand continue gevlisting the CDR of the expression in the environment.\n\n896\n00:55:37,936 --> 00:55:43,200\n然而 我们也可能遇到按名传递的参数\nHowever, it's possible that this is a name parameter.\n\n897\n00:55:44,000 --> 00:55:45,056\n如果参数是按名传递\nIf it's a name parameter,\n\n898\n00:55:45,200 --> 00:55:46,592\n我就需要给它包裹上一个DELAY\nI want to put a delay in\n\n899\n00:55:47,008 --> 00:55:50,976\nDELAY里面就是我想按名调用的表达式\nwhich combines that expression, which I'm calling by name,\n\n900\n00:55:52,144 --> 00:55:57,740\n还要附上定义过程时的环境\nwith the environment that's available at this time\n\n901\n00:55:59,056 --> 00:56:00,592\n把它们作为实际参数\nand passing that as the parameter.\n\n902\n00:56:02,790 --> 00:56:05,040\n然后像这样继续递归处理\nAnd this is part of the mapping process that you see here.\n\n903\n00:56:09,070 --> 00:56:11,310\n这个解释器中另外一个有意思的地方\nThe only other interesting place in this procedure\n\n904\n00:56:11,376 --> 00:56:13,536\n就在于COND\nin this interpreter is cond.\n\n905\n00:56:14,700 --> 00:56:15,920\n人们可能就这么来写\nPeople tend to write this thing,\n\n906\n00:56:15,936 --> 00:56:17,248\n然后就不管了\nand then they leave this one out.\n\n907\n00:56:18,550 --> 00:56:19,984\n你需要在一处FORCE\nThere's a place where you have to force.\n\n908\n00:56:20,510 --> 00:56:23,104\nCOND表达式需要知道\nConditionals have to know\n\n909\n00:56:24,208 --> 00:56:25,904\n谓词判定结果的真假\nwhether or not the answer is true or false.\n\n910\n00:56:25,990 --> 00:56:26,832\n就像基本过程那样\nIt's like a primitive.\n\n911\n00:56:28,550 --> 00:56:30,560\n求值COND语句时 需要FORCE\nWhen you do a conditional, you have to force.\n\n912\n00:56:31,728 --> 00:56:33,952\n剩下的细节就没什么特别的了\nNow, I'm not going to look at any more of this in any detail.\n\n913\n00:56:34,624 --> 00:56:36,288\n就先不深究了\nIt isn't very exciting.\n\n914\n00:56:36,750 --> 00:56:38,990\n剩下的就是如何实现MAKE-DELAY\nAnd what's left is how you make delays.\n\n915\n00:56:38,990 --> 00:56:40,912\n延时对象是一种数据结构\nWell, delays are data structures\n\n916\n00:56:41,312 --> 00:56:44,752\n它包括：类型标识、表达式以及环境\nwhich contain an expression, an environment, and a type on them.\n\n917\n00:56:44,840 --> 00:56:46,368\n它的类型标识是'THUNK\nAnd it says they're a thunk.\n\n918\n00:56:46,960 --> 00:56:48,464\n这个术语来自于Algol语言\nThat comes from ALGOL language,\n\n919\n00:56:49,072 --> 00:56:50,816\n据说这是个拟声词\nand it's claimed to be the sound of\n\n920\n00:56:50,832 --> 00:56:52,064\n是把东西压栈的声音\nof something being pushed on a stack.\n\n921\n00:56:52,970 --> 00:56:53,410\n我不太清楚\nI don't know.\n\n922\n00:56:53,410 --> 00:56:57,120\n我既不是Algol学家 又不是Algol程序员\nI was not an ALGOLician, so or an ALGOLite or whatever,\n\n923\n00:56:57,600 --> 00:56:58,384\n所以我不太清楚\nso I don't know.\n\n924\n00:56:58,740 --> 00:56:59,648\n但据说它是那样的\nBut that's what was claimed.\n\n925\n00:57:00,270 --> 00:57:01,568\n而UNDELAY的定义则是\nAnd undelay is something\n\n926\n00:57:01,770 --> 00:57:03,664\n递归地UNDELAY这些THUNK\nwhich will recursively undelay thunks\n\n927\n00:57:03,696 --> 00:57:06,000\n直到得到一个非THUNK对象\nuntil the thunk becomes something which isn't a thunk.\n\n928\n00:57:07,728 --> 00:57:10,944\n这就是如何实现Algol中的按名调用\nThis is the way you implement a call by name like thing in ALGOL.\n\n929\n00:57:12,050 --> 00:57:13,760\n差不多就是这样了\nAnd that's about all there is.\n\n930\n00:57:15,210 --> 00:57:16,256\n有什么问题吗？\nAre there any questions?\n\n931\n00:57:26,688 --> 00:57:27,520\n学生：Gerry？\nAUDIENCE: Gerry?\n\n932\n00:57:28,096 --> 00:57:28,800\n教授：你说 Vesko\nPROFESSOR: Yes, Vesko?\n\n933\n00:57:30,030 --> 00:57:32,992\n学生：我注意到 对于基本过程\nAUDIENCE: I noticed you avoided calling by name\n\n934\n00:57:33,440 --> 00:57:34,890\n你是避免按名调用的\nin the primitive procedures,\n\n935\n00:57:36,410 --> 00:57:38,384\n我很想知道 你为什么要这样？\nI was wondering what cause you have on that?\n\n936\n00:57:38,416 --> 00:57:39,216\n需要这样吗？\nYou never need that?\n\n937\n00:57:40,070 --> 00:57:41,616\n教授：Vesko想问的是\nPROFESSOR: Vesko is asking\n\n938\n00:57:42,064 --> 00:57:46,000\n基本过程也按名调用是否合理？\nif it's ever reasonable to call a primitive procedure by name?\n\n939\n00:57:47,140 --> 00:57:48,704\n答案是：是的\nThe answer is, yes.\n\n940\n00:57:49,270 --> 00:57:52,320\n有一种情况下是可以的 实际上是两种\nThere's one particular case where it's reasonable, actually two.\n\n941\n00:57:55,536 --> 00:57:58,272\n比如用CONS来构造一个数据结构\nConstruction of a data structure like cons\n\n942\n00:57:59,020 --> 00:58:02,000\n构建一个元素个数不定的数组时\nwhere making an array if you have arrays with any number of elements.\n\n943\n00:58:03,264 --> 00:58:07,440\n就没必要求值参数\nOK? It's unnecessary to evaluate those arguments.\n\n944\n00:58:07,440 --> 00:58:08,832\n你只需要创建一些PROMISE\nAll you need is promises\n\n945\n00:58:09,104 --> 00:58:10,816\n在确实需要时才来求值这些参数\nto evaluate those arguments if you look at them.\n\n946\n00:58:11,504 --> 00:58:15,088\n如果我把两个对象CONS起来\nIf I cons together a, two things,\n\n947\n00:58:16,240 --> 00:58:17,776\n那么我CONS这些PROMISE\nthen I could cons together the promises\n\n948\n00:58:17,808 --> 00:58:19,936\n就和CONS这些对象一样容易\njust as easily as I can cons together the things.\n\n949\n00:58:21,150 --> 00:58:23,376\n甚至在对它们进行CAR CDR的时候\nAnd it's not even when I CAR CDR them\n\n950\n00:58:23,392 --> 00:58:24,304\n也不用进行实际的计算\nthat I have to look at them.\n\n951\n00:58:24,840 --> 00:58:26,976\n取出PROMISE 并直接传递给其它人\nThat just gets out the promises and passes them to somebody.\n\n952\n00:58:28,260 --> 00:58:30,512\n这也就是为什么Alonzo Church用LAMBDA演算\nThat's why the lambda calculus definition, the\n\n953\n00:58:30,576 --> 00:58:34,032\n定义的CAR、CDR和CONS说得通的原因\nthe Alonzo Church definition of CAR, CDR, and cons makes sense.\n\n954\n00:58:34,420 --> 00:58:36,320\n这是因为CAR、CDR以及CONS并没有执行计算\nIt's because no work is done in CAR, CDR, and cons,\n\n955\n00:58:36,380 --> 00:58:40,064\n你们可以认为它是在重组数据而已\nit's just shuffling data, it's just routing, if you will.\n\n956\n00:58:40,990 --> 00:58:42,208\n然而像 + 这样的过程\nHowever, the things that do have\n\n957\n00:58:42,240 --> 00:58:43,840\n必须要了解参数是什么\nto look at data are things like plus.\n\n958\n00:58:45,280 --> 00:58:46,912\n它们需要确认\nBecause they have a look at the bits\n\n959\n00:58:47,120 --> 00:58:48,304\n构成这些数字的比特\nthat the numbers are made out of,\n\n960\n00:58:48,320 --> 00:58:50,448\n除非它们处理的是LAMBDA演算中的数字\nunless they're lambda calculus numbers\n\n961\n00:58:50,448 --> 00:58:51,880\n这就是另外一码事了\nwhich are funny. OK?\n\n962\n00:58:52,430 --> 00:58:53,584\n为了运算加法\nThey have to look at the bits to\n\n963\n00:58:53,776 --> 00:58:55,530\n它需要知道构成数字的比特\nbe able to crunch them together to do the add.\n\n964\n00:58:59,210 --> 00:58:59,920\n因此 实际上\nSo, in fact,\n\n965\n00:59:00,192 --> 00:59:02,784\n数据的构造过程和选择过程\ndata constructors, data selectors,\n\n966\n00:59:03,248 --> 00:59:05,504\n以及具有副作用的数据对象\nin fact, things that side-effect data objects\n\n967\n00:59:06,270 --> 00:59:09,760\n在最极端的惰性解释器中\ndon't need to do, don't need to do any forcing\n\n968\n00:59:11,344 --> 00:59:13,392\n也不需要被FORCE\nin the laziest possible interpreters.\n\n969\n00:59:16,460 --> 00:59:16,992\n另外一方面\nOn the other hand\n\n970\n00:59:17,024 --> 00:59:18,700\n针对数据结构的谓词需要被FORCE\npredicates on data structures have to.\n\n971\n00:59:19,616 --> 00:59:22,656\n如果你想判断 这是一个序对吗？\nIf you want to say, is this a, is this a pair?\n\n972\n00:59:23,560 --> 00:59:24,400\n或者是一个符号？\nOr is it a symbol?\n\n973\n00:59:24,640 --> 00:59:26,576\n最好搞清楚是什么\nWell, you better find out. You got to look at it then.\n\n974\n00:59:30,300 --> 00:59:31,184\n还有问题吗？\nAny other questions?\n\n975\n00:59:40,050 --> 00:59:41,610\n那好吧 下课\nOh, well, I suppose it's time for a break.\n\n976\n00:59:42,100 --> 00:59:55,840\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n977\n00:59:55,840 --> 01:00:04,560\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec8a.chn.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:17,814\n【背景音乐：巴赫】\n\n2\n00:00:17,814 --> 00:00:22,132\n教授：上次课我们学习了如何构建一门语言。\n\n3\n00:00:22,132 --> 00:00:26,050\n要点是解释器（比如lisp解释器）\n\n4\n00:00:26,050 --> 00:00:27,580\n是由两个主要部分构成的。\n\n5\n00:00:27,580 --> 00:00:36,350\n一个是EVAL。EVAL负责接收一个表达式（expression）和环境（environment）\n\n6\n00:00:36,350 --> 00:00:43,820\n并将其转换成一个过程和一些参数，\n\n7\n00:00:43,820 --> 00:00:46,635\n然后传递给APPLY。\n\n8\n00:00:49,410 --> 00:00:52,250\nAPP接收该过程和参数，再将其\n\n9\n00:00:52,250 --> 00:00:55,680\n转换为（一般情况下）另一个表达式。\n\n10\n00:00:55,680 --> 00:00:58,280\n该表达式将结合另外一个环境求值。APPLY将表达式回传给EVAL，\n\n11\n00:00:58,280 --> 00:01:00,770\nEVAL再传给APPLY，\n\n12\n00:01:00,770 --> 00:01:02,750\n形成一个大的循环，\n\n13\n00:01:02,750 --> 00:01:05,519\n直至被翻译成基本数据\n\n14\n00:01:05,519 --> 00:01:07,740\n或基本过程\n\n15\n00:01:07,740 --> 00:01:12,080\n这个循环所作的工作就是分解\n\n16\n00:01:12,080 --> 00:01:15,020\n语言当中的组合和抽象。\n\n17\n00:01:15,020 --> 00:01:17,870\n比如，你有一个LISP过程 --\n\n18\n00:01:17,870 --> 00:01:21,320\n一个通用的，可以用来\n\n19\n00:01:21,320 --> 00:01:25,392\n对这个表达式代入任何参数进行求值，\n\n20\n00:01:25,392 --> 00:01:27,670\n和我们正在做的差不多。\n\n21\n00:01:27,670 --> 00:01:28,510\n这就是APPLY的工作。\n\n22\n00:01:28,510 --> 00:01:30,770\n它规定将所有作为参数传进来的值\n\n23\n00:01:30,770 --> 00:01:33,380\n归约为表达式的主体。\n\n24\n00:01:33,380 --> 00:01:35,790\n如果这是一个复合表达式，或调用了\n\n25\n00:01:35,790 --> 00:01:40,440\n另外一个过程，就会一直循环下去。\n\n26\n00:01:40,440 --> 00:01:43,040\n哇，这就是几乎所有\n\n27\n00:01:43,040 --> 00:01:45,120\n解释器的基本结构了。\n\n28\n00:01:45,120 --> 00:01:46,720\n另外就是，当你拿到一个解释器后，\n\n29\n00:01:46,720 --> 00:01:49,080\n你就可以随心所欲的摆布\n\n30\n00:01:49,080 --> 00:01:49,870\n你的语言了。\n\n31\n00:01:49,870 --> 00:01:53,390\n你可以加入对动态范围的支持，\n\n32\n00:01:53,390 --> 00:01:55,960\n正常次序求值，或者为语言增加一种\n\n33\n00:01:55,960 --> 00:01:57,680\n新的变形，随便怎样都行。\n\n34\n00:01:57,680 --> 00:02:00,570\n更一般的，我们遇到了元语言抽象\n\n35\n00:02:00,570 --> 00:02:07,930\n就是说你作为一个工程师，一个软件工程师，\n\n36\n00:02:07,930 --> 00:02:09,970\n而不仅是一个一般的工程师，经常可以通过发明\n\n37\n00:02:09,970 --> 00:02:15,270\n新的语言以对复杂度\n\n38\n00:02:15,270 --> 00:02:18,010\n进行控制。\n\n39\n00:02:18,010 --> 00:02:22,830\n从某个角度上看，计算机编程\n\n40\n00:02:22,830 --> 00:02:25,170\n仅仅是偶然的，刚好利用到了\n\n41\n00:02:25,170 --> 00:02:26,440\n计算机来做事情。\n\n42\n00:02:26,440 --> 00:02:29,220\n计算机程序主要是一种\n\n43\n00:02:29,220 --> 00:02:33,270\n表达，交流想法的方法。\n\n44\n00:02:33,270 --> 00:02:36,300\n有时，为了表达新的想法，\n\n45\n00:02:36,300 --> 00:02:39,770\n你会更喜欢发明一种新的模式。\n\n46\n00:02:39,770 --> 00:02:44,300\n好，今天我们将使用这个框架来\n\n47\n00:02:44,300 --> 00:02:45,730\n构建一门新语言。\n\n48\n00:02:45,730 --> 00:02:48,140\n一旦我们掌握了解释器的基本原理，\n\n49\n00:02:48,140 --> 00:02:50,830\n你就可以构建任何你喜欢的语言。\n\n50\n00:02:50,830 --> 00:02:54,370\n比如我们可以构建Pascal。\n\n51\n00:02:54,370 --> 00:02:58,820\n确实有很多需要考虑的东西：语法，解析，\n\n52\n00:02:58,820 --> 00:03:01,450\n各种各样的编译器优化，而且有很多人\n\n53\n00:03:01,450 --> 00:03:05,580\n以此为生，过着诚实的生活。\n\n54\n00:03:05,580 --> 00:03:09,100\n但在我们讨论的抽象层级上，一个Pascal解释器\n\n55\n00:03:09,100 --> 00:03:13,020\n和上次Gerry做的那个，\n\n56\n00:03:13,020 --> 00:03:15,350\n没有任何区别。\n\n57\n00:03:15,350 --> 00:03:18,190\n今天我们不做那个。我们要构建一门\n\n58\n00:03:18,190 --> 00:03:23,400\n真正与众不同的语言。\n\n59\n00:03:23,400 --> 00:03:26,980\n它可以引导你跳出过程（procedure），\n\n60\n00:03:26,980 --> 00:03:29,090\n以一种完全不同的方式去看待程序设计。\n\n61\n00:03:29,090 --> 00:03:33,650\n今天的课程会同时在两个层面上展开。\n\n62\n00:03:34,810 --> 00:03:37,210\n一方面，我会介绍这门语言长什么样，\n\n63\n00:03:37,210 --> 00:03:40,410\n另一方面，我会向你们展示如何实现它。\n\n64\n00:03:41,010 --> 00:03:43,250\n我们会用LISP去实现它，\n\n65\n00:03:43,250 --> 00:03:44,220\n并研究它如何工作。\n\n66\n00:03:44,220 --> 00:03:48,730\n你们将从两个层面上学习。\n\n67\n00:03:48,730 --> 00:03:52,190\n一个是要认识到语言可以如此的与众不同，\n\n68\n00:03:53,790 --> 00:03:57,830\n以至于如果你们认为从Fortran到LISP\n\n69\n00:03:57,830 --> 00:04:01,560\n是一个巨大的跨越，那实际上你们还没开眼。\n\n70\n00:04:01,560 --> 00:04:05,660\n第二，你们会看到，即使是\n\n71\n00:04:05,660 --> 00:04:08,590\n这样一门特立独行的语言，\n\n72\n00:04:08,590 --> 00:04:12,260\n它完全没有过程，也没有函数，\n\n73\n00:04:12,260 --> 00:04:16,570\n但它背后还是基本的求值（eval）、应用（apply）循环，\n\n74\n00:04:16,570 --> 00:04:19,170\n负责分解组合以及抽象的各种方法。\n\n75\n00:04:20,950 --> 00:04:24,430\n第三点，作为一个很小但很优雅的技术点，\n\n76\n00:04:24,430 --> 00:04:27,720\n你们会看到如何使用流（Stream）避免回溯（backtracking）。\n\n77\n00:04:32,330 --> 00:04:35,860\n好了，我说过这门语言非常特别。\n\n78\n00:04:35,860 --> 00:04:41,620\n为了解释它为什么特别，让我们回到在课程之初\n\n79\n00:04:41,620 --> 00:04:44,710\n提到的第一个观点，\n\n80\n00:04:44,710 --> 00:04:48,780\n关于声明式知识和数学之间的差异。\n\n81\n00:04:50,240 --> 00:04:55,470\n对平方根的定义是一个数学真理--\n\n82\n00:04:55,470 --> 00:04:59,080\n而计算机科学是关于“怎么做”的知识--\n\n83\n00:04:59,810 --> 00:05:03,700\n对比一下平方根的定义\n\n84\n00:05:03,700 --> 00:05:05,970\n和一个用来计算平方根的程序。\n\n85\n00:05:05,970 --> 00:05:08,042\n我们从这里开始。\n\n86\n00:05:08,042 --> 00:05:11,830\n如果我们能做到这样，是不是很伟大：\n\n87\n00:05:11,830 --> 00:05:16,030\n发明一种新的语言填平这道沟。它可以执行计算，\n\n88\n00:05:16,030 --> 00:05:20,510\n但我们用声明式的，用描述事实的方法去和它交流。\n\n89\n00:05:22,380 --> 00:05:24,110\n在这样的语言里\n\n90\n00:05:24,110 --> 00:05:27,690\n你们定义事实\n\n91\n00:05:27,690 --> 00:05:28,880\n你们告诉它“是什么”\n\n92\n00:05:28,880 --> 00:05:30,950\n你们告诉它“什么是真”\n\n93\n00:05:30,950 --> 00:05:34,220\n然后当你们需要答案时，\n\n94\n00:05:34,220 --> 00:05:38,560\n植语言已经入了一般性的\n\n95\n00:05:38,560 --> 00:05:41,200\n关于“怎么做”的知识。它就可以接受你们输入的事实\n\n96\n00:05:41,200 --> 00:05:44,180\n并基于这些事实，以及一些通用的逻辑规则，\n\n97\n00:05:44,180 --> 00:05:46,200\n一步步去行演算。\n\n98\n00:05:49,330 --> 00:05:53,920\n举个例子，我可以对这个程序说：\n\n99\n00:05:55,645 --> 00:06:08,920\n我告诉它Adam的儿子是Abel。\n\n100\n00:06:08,920 --> 00:06:17,660\nAdam的儿子是Cain。\n\n101\n00:06:17,660 --> 00:06:24,670\nCain的儿子是Enoch。\n\n102\n00:06:27,502 --> 00:06:37,550\nEnoch的儿子是Irad，\n\n103\n00:06:37,550 --> 00:06:41,190\n以及创世纪中提到的所有信息，\n\n104\n00:06:41,190 --> 00:06:45,010\n一直到Adah结束。\n\n105\n00:06:45,010 --> 00:06:48,760\n这就是从Cain到Adah的完整谱系。\n\n106\n00:06:48,760 --> 00:06:52,520\n总之，一旦你告诉了它这些事实\n\n107\n00:06:52,520 --> 00:06:53,510\n你就可以向它提问。\n\n108\n00:06:53,510 --> 00:06:58,560\n你可以向这门语言提问：\n\n109\n00:06:58,560 --> 00:07:00,420\n谁是Adam的儿子？\n\n110\n00:07:00,420 --> 00:07:03,480\n很容易你就能想到\n\n111\n00:07:03,480 --> 00:07:06,460\n用一个通用的搜索程序\n\n112\n00:07:06,460 --> 00:07:08,800\n进行搜索并回答，yeah，有两个答案\n\n113\n00:07:08,800 --> 00:07:10,930\nAdam的儿子是Abel\n\n114\n00:07:10,930 --> 00:07:14,140\nAdam的儿子是Cain。\n\n115\n00:07:14,140 --> 00:07:19,350\n或者你可以问，基于同样的事实，\n\n116\n00:07:19,350 --> 00:07:21,950\nCain是谁的儿子？\n\n117\n00:07:21,950 --> 00:07:25,520\n然后你又可以想象一下产生一段\n\n118\n00:07:25,520 --> 00:07:29,510\n稍微有些不同的搜索程序，可以查询事实\n\n119\n00:07:29,510 --> 00:07:33,760\n并发现谁是Cain，他是谁的儿子，\n\n120\n00:07:33,760 --> 00:07:35,890\n然后找到Adam。\n\n121\n00:07:35,890 --> 00:07:40,300\n或者你可以问\n\n122\n00:07:40,300 --> 00:07:42,070\nCain和Enoch是什么关系？\n\n123\n00:07:42,070 --> 00:07:46,340\n再一次的，该搜索程序又有一个小变种\n\n124\n00:07:46,340 --> 00:07:48,160\n你能得到他们是父子关系。\n\n125\n00:07:52,880 --> 00:07:56,960\n即使在这个简单的例子里\n\n126\n00:07:56,960 --> 00:08:00,460\n你们可以发现，同一个简单的事实，比如\n\n127\n00:08:00,460 --> 00:08:04,230\nAdam的儿子是Cain，可以被用来\n\n128\n00:08:04,230 --> 00:08:06,520\n回答很多个不同的问题。\n\n129\n00:08:06,520 --> 00:08:10,540\n你可以问，谁是Adam的儿子\n\n130\n00:08:10,540 --> 00:08:12,220\n或者你可以问亚当和该隐是什么关系\n\n131\n00:08:12,970 --> 00:08:17,370\n这些问题由依据同样的事实的\n\n132\n00:08:17,370 --> 00:08:22,474\n一些不同的传统过程所回答。\n\n133\n00:08:22,474 --> 00:08:24,960\n这就是这种编程风格的精华所在\n\n134\n00:08:24,960 --> 00:08:30,050\n一条声明式的知识\n\n135\n00:08:30,050 --> 00:08:33,150\n可以被用做许多不同种类的”怎么做“\n\n136\n00:08:33,150 --> 00:08:36,440\n的问题的基础，而不是我们以前写的那种过程\n\n137\n00:08:36,440 --> 00:08:39,010\n告诉它输入是什么\n\n138\n00:08:39,010 --> 00:08:41,490\n期望什么样的答案。\n\n139\n00:08:41,490 --> 00:08:43,710\n比如，我们的平方根程序可以完美的\n\n140\n00:08:43,710 --> 00:08:48,900\n回答这样的问题，144的平方根是多少？\n\n141\n00:08:48,900 --> 00:08:51,290\n但本质上，平方根的数学定义\n\n142\n00:08:51,290 --> 00:08:52,830\n可以回答更多的问题\n\n143\n00:08:52,830 --> 00:08:57,590\n比如17是哪个数的平方根？\n\n144\n00:08:57,590 --> 00:08:58,590\n这个问题可能需要使用一个\n\n145\n00:08:58,590 --> 00:09:01,920\n不同的程序来回答。\n\n146\n00:09:01,920 --> 00:09:05,700\n所以数学定义，或者更一般的，\n\n147\n00:09:05,700 --> 00:09:09,540\n我们告诉语言的事实，\n\n148\n00:09:09,540 --> 00:09:10,900\n跟问题没有强绑定关系。\n\n149\n00:09:10,900 --> 00:09:13,240\n但是我们习惯与特定的程序，因为\n\n150\n00:09:13,240 --> 00:09:15,230\n它们是关于”怎么做“的知识，\n\n151\n00:09:15,230 --> 00:09:17,700\n查找某个特定的答案。\n\n152\n00:09:17,700 --> 00:09:19,530\n所以这将是我们将要讨论的一个特征。\n\n153\n00:09:21,810 --> 00:09:23,480\n我们继续。\n\n154\n00:09:23,480 --> 00:09:26,420\n设想我们已经给我们的语言\n\n155\n00:09:26,420 --> 00:09:27,710\n输入了一些事实。\n\n156\n00:09:27,710 --> 00:09:30,020\n现在让我们再给它一些推导规则。\n\n157\n00:09:30,020 --> 00:09:35,100\n举个例子，我们可以说，如果---\n\n158\n00:09:35,100 --> 00:09:36,510\n这里编一些语法---\n\n159\n00:09:36,510 --> 00:09:41,580\n如果x的儿子是y--\n\n160\n00:09:41,580 --> 00:09:45,650\n我用问号表示这是一个变量--\n\n161\n00:09:45,650 --> 00:10:01,800\n如果x的儿子是y，且y的儿子是z，\n\n162\n00:10:01,800 --> 00:10:09,320\n那么x的孙子是z。\n\n163\n00:10:09,320 --> 00:10:15,370\n所以我可以设想一下，把规则告诉机器\n\n164\n00:10:15,370 --> 00:10:17,680\n然后问它，比如说，\n\n165\n00:10:17,680 --> 00:10:20,610\n谁是亚当的孙子？\n\n166\n00:10:20,610 --> 00:10:24,790\n或者Irad是谁的孙子？\n\n167\n00:10:24,790 --> 00:10:28,080\n或者基于已知信息，\n\n168\n00:10:28,080 --> 00:10:29,330\n找出所有的祖孙关系。\n\n169\n00:10:31,220 --> 00:10:34,580\n我们不妨设想一下，语言知道如何\n\n170\n00:10:34,580 --> 00:10:35,830\n自动的回答这些问题。\n\n171\n00:10:42,640 --> 00:10:45,200\n让我在举几个更具体的例子。\n\n172\n00:10:49,610 --> 00:10:53,700\n这是一个用来合并两个有序列表的过程。\n\n173\n00:10:53,700 --> 00:11:01,370\nx和y是两个数字的列表，每个列表中没有重复元素。\n\n174\n00:11:01,370 --> 00:11:04,780\n然后，如果你们愿意的话，按升序排列。\n\n175\n00:11:04,780 --> 00:11:08,560\nmerge的作用是取两个列表，\n\n176\n00:11:08,560 --> 00:11:10,040\n合并成一个列表，仍然按升序排列。\n\n177\n00:11:10,040 --> 00:11:15,330\n这么简单的程序，你们应该\n\n178\n00:11:15,330 --> 00:11:16,390\n都会写。\n\n179\n00:11:16,390 --> 00:11:18,860\n如果x为空，结果为y。\n\n180\n00:11:18,860 --> 00:11:21,180\n如果y为空，结果为x。\n\n181\n00:11:21,180 --> 00:11:22,990\n否则，比较各自的第一个元素。\n\n182\n00:11:22,990 --> 00:11:25,540\n取出x的第一个元素和y中的第一个元素\n\n183\n00:11:25,540 --> 00:11:31,060\n哪个小，就把哪个元素放到一边，然后对剩余部分\n\n184\n00:11:31,060 --> 00:11:35,500\n（或者把x的头去掉，或者把y的头去掉）\n\n185\n00:11:35,500 --> 00:11:40,150\n再和刚才取出来的元素合并。\n\n186\n00:11:42,400 --> 00:11:43,960\n这是一个标准的程序。\n\n187\n00:11:46,470 --> 00:11:48,620\n我们看一下它的逻辑。\n\n188\n00:11:48,620 --> 00:11:51,660\n忘掉刚才的程序。看看这个过程所\n\n189\n00:11:51,660 --> 00:11:53,820\n基于的逻辑。\n\n190\n00:11:53,820 --> 00:11:56,860\n看，这里逻辑是，如果第一个\n\n191\n00:11:56,860 --> 00:12:00,240\n更小一些，我们就把某个东西和\n\n192\n00:12:00,240 --> 00:12:03,350\n剩余的部分递归合并的结果进行合并。\n\n193\n00:12:03,350 --> 00:12:05,420\n我们试一下准确的说出使程序工作的逻辑。\n\n194\n00:12:08,430 --> 00:12:10,130\n这一块，\n\n195\n00:12:10,130 --> 00:12:13,820\n这块程序递归的\n\n196\n00:12:13,820 --> 00:12:19,980\n当x更小的时候消去x的首元素。\n\n197\n00:12:19,980 --> 00:12:22,030\n如果我们想要更准确的给出这里的逻辑\n\n198\n00:12:22,030 --> 00:12:27,120\n那么这实际上是一个推导过程，\n\n199\n00:12:27,120 --> 00:12:31,790\n即，如果我们知道cdr x和y合并等于z，\n\n200\n00:12:40,480 --> 00:12:47,570\n且a比y的首元素小，我们就知道\n\n201\n00:12:47,570 --> 00:12:55,820\n如果把a合并到cdr x的之前，再与y合并，结果就等于a+z。\n\n202\n00:12:55,820 --> 00:12:58,720\n这就是背后的逻辑。\n\n203\n00:12:58,720 --> 00:13:01,620\n我没有把它写成程序，而是写成一种推导。\n\n204\n00:13:01,620 --> 00:13:05,480\n它是这段话背后的东西。\n\n205\n00:13:05,480 --> 00:13:09,410\n它决定了在这里可以使用递归。\n\n206\n00:13:09,410 --> 00:13:11,910\n类似地，看另外一段，\n\n207\n00:13:11,910 --> 00:13:14,000\n把它做完。\n\n208\n00:13:14,000 --> 00:13:16,880\n另外一段基于几乎相同的逻辑\n\n209\n00:13:16,880 --> 00:13:19,460\n我就不细说了。\n\n210\n00:13:19,460 --> 00:13:22,730\n然后这是我们要测试的n个场景。它基于这样的思想：\n\n211\n00:13:22,730 --> 00:13:26,920\n任何x与空list合并还是x\n\n212\n00:13:26,920 --> 00:13:30,740\n任何y与空list合并还是y\n\n213\n00:13:33,360 --> 00:13:39,340\n好。我们看到了一段过程，以及它所基于的逻辑。\n\n214\n00:13:41,740 --> 00:13:44,750\n注意一个巨大的差异\n\n215\n00:13:44,750 --> 00:13:51,050\n过程是这样的。\n\n216\n00:13:51,050 --> 00:13:52,900\n它规定这里有一个盒子。\n\n217\n00:13:52,900 --> 00:13:55,410\n我们做的所有的事情都有这样的特点\n\n218\n00:13:55,410 --> 00:13:57,890\n一个盒子，有东西进来，有东西出去。\n\n219\n00:13:57,890 --> 00:14:04,480\n这个盒子叫merge，进来了x和y\n\n220\n00:14:04,480 --> 00:14:07,550\n出来一个答案\n\n221\n00:14:07,550 --> 00:14:09,340\n这就是过程的特点。\n\n222\n00:14:13,160 --> 00:14:14,660\n规则就不一样\n\n223\n00:14:14,660 --> 00:14:17,620\n规则讲的是关系\n\n224\n00:14:17,620 --> 00:14:23,030\n这些胶片里有一些我称为\n\n225\n00:14:23,030 --> 00:14:25,370\n\"合并\"的规则\n\n226\n00:14:25,370 --> 00:14:29,200\n我说x和y合并等于z\n\n227\n00:14:29,200 --> 00:14:32,610\n这还是个函数\n\n228\n00:14:32,610 --> 00:14:32,850\n对吧？\n\n229\n00:14:32,850 --> 00:14:36,070\n答案是x和y的函数。这里我看到的\n\n230\n00:14:36,070 --> 00:14:39,720\n是三个东西之间的关系\n\n231\n00:14:39,720 --> 00:14:43,120\n我不会规定哪些是输入\n\n232\n00:14:43,120 --> 00:14:44,200\n那些是输出\n\n233\n00:14:44,200 --> 00:14:48,690\n我这样说的原因是因为，原则上\n\n234\n00:14:48,690 --> 00:14:51,300\n我们可以用这些同样的逻辑规则去回答\n\n235\n00:14:51,300 --> 00:14:54,570\n很多个不同的问题\n\n236\n00:14:54,570 --> 00:14:56,750\n所以我们可以，比如，\n\n237\n00:14:56,750 --> 00:14:59,050\n假设把这些逻辑规则交给机器。\n\n238\n00:14:59,050 --> 00:15:01,400\n不是程序，而是背后的逻辑规则\n\n239\n00:15:01,400 --> 00:15:04,750\n于是它就可以回答，\n\n240\n00:15:04,750 --> 00:15:06,770\n比如我们可以问--\n\n241\n00:15:06,770 --> 00:15:20,910\n1, 3, 7和2, 4, 8合并等于什么？\n\n242\n00:15:20,910 --> 00:15:23,880\n这个问题它应该可以回答\n\n243\n00:15:23,880 --> 00:15:26,480\n这恰恰是我们的lisp\n\n244\n00:15:26,480 --> 00:15:28,180\n过程所回答的问题\n\n245\n00:15:28,180 --> 00:15:33,750\n它同样的规则还可以回答\n\n246\n00:15:33,750 --> 00:15:41,760\n这样的问题：1, 3, 7和什么合并可以得到\n\n247\n00:15:41,760 --> 00:15:45,560\n1, 2, 3, 4, 7, 8?\n\n248\n00:15:45,560 --> 00:15:48,120\n同样的一组规则可以回答它，但是\n\n249\n00:15:48,120 --> 00:15:50,880\n刚才写的过程就不行\n\n250\n00:15:50,880 --> 00:15:56,070\n或者我们可以说\n\n251\n00:15:56,070 --> 00:16:07,900\n什么与什么合并得到----\n\n252\n00:16:07,900 --> 00:16:13,780\n什么与什么合并得到1,2,3,4,7,8?\n\n253\n00:16:13,780 --> 00:16:16,320\n如果这个东西真的可以应用刚才的逻辑，它可以一直跑下去\n\n254\n00:16:16,320 --> 00:16:20,470\n推导出第2～6个问题的答案\n\n255\n00:16:25,600 --> 00:16:28,790\n它可以是1和其它，或者1，2与其它\n\n256\n00:16:28,790 --> 00:16:32,490\n或者1，3，7与其它。\n\n257\n00:16:32,490 --> 00:16:33,410\n有很多个答案。\n\n258\n00:16:33,410 --> 00:16:36,830\n原则上，这个逻辑\n\n259\n00:16:36,830 --> 00:16:38,550\n足以推导出它们。\n\n260\n00:16:38,550 --> 00:16:44,540\n所以，在我们将要研究的程序\n\n261\n00:16:44,540 --> 00:16:48,370\n和其它程序\n\n262\n00:16:48,370 --> 00:16:49,850\n包括lisp和差不多你们之前见过的所有程序之间\n\n263\n00:16:49,850 --> 00:16:54,150\n存在着两个巨大的差异\n\n264\n00:16:54,150 --> 00:16:57,620\n首先，我们不会去计算函数。\n\n265\n00:17:00,800 --> 00:17:03,770\n我们不会去关注接受输入返回输出的东西。\n\n266\n00:17:04,410 --> 00:17:06,890\n我们将讨论关系。\n\n267\n00:17:06,890 --> 00:17:09,180\n原则上，这些关系\n\n268\n00:17:09,180 --> 00:17:11,089\n是没有方向的。\n\n269\n00:17:11,089 --> 00:17:14,569\n所以你们所定义的，用来回答这个问题的知识\n\n270\n00:17:14,569 --> 00:17:19,220\n可以同样的用来回答这些问题\n\n271\n00:17:19,220 --> 00:17:21,345\n以及反过来的问题。\n\n272\n00:17:26,310 --> 00:17:30,590\n第二个问题是，因为我们讨论的是关系\n\n273\n00:17:30,590 --> 00:17:33,150\n那么这些关系就未必\n\n274\n00:17:33,150 --> 00:17:35,610\n只有一个答案\n\n275\n00:17:35,610 --> 00:17:37,480\n所以底下的第三个问题\n\n276\n00:17:37,480 --> 00:17:39,415\n没有一个唯一的答案，它有一堆答案。\n\n277\n00:17:42,270 --> 00:17:44,640\nOK, 这就是我们下面要学习的。\n\n278\n00:17:44,640 --> 00:17:48,620\n另外，这种编程风格，\n\n279\n00:17:48,620 --> 00:17:51,310\n称为逻辑编程。原因很明显。\n\n280\n00:17:56,160 --> 00:18:02,440\n使用逻辑编程的人这么说 ---\n\n281\n00:18:02,440 --> 00:18:04,150\n---逻辑编程的关键就在于:\n\n282\n00:18:04,150 --> 00:18:10,190\n用逻辑表达什么是真\n\n283\n00:18:10,190 --> 00:18:15,190\n用逻辑去检查什么为真\n\n284\n00:18:15,190 --> 00:18:19,200\n用逻辑去寻找什么为真。\n\n285\n00:18:19,200 --> 00:18:23,300\n已知的最好的逻辑编程语言\n\n286\n00:18:23,300 --> 00:18:25,780\n你们可能听说过，是Prolog.\n\n287\n00:18:25,780 --> 00:18:31,010\n今天上午我们将要实现的语言，\n\n288\n00:18:31,010 --> 00:18:33,110\n叫做query语言\n\n289\n00:18:33,110 --> 00:18:35,320\n它具有Prolog的精华。\n\n290\n00:18:35,320 --> 00:18:38,340\n它能做同样的事。当然它很慢\n\n291\n00:18:38,340 --> 00:18:42,390\n因为我们将要用LISP去实现它\n\n292\n00:18:42,390 --> 00:18:44,210\n而不是去开发一个专用的编译器。\n\n293\n00:18:44,210 --> 00:18:47,510\n我们将要在LISP解释器的基础上实现新语言的解释器。\n\n294\n00:18:47,510 --> 00:18:48,950\n除此以外，新语言的功能\n\n295\n00:18:48,950 --> 00:18:49,750\n和prolog是一样的。\n\n296\n00:18:49,750 --> 00:18:52,160\n它的能力和限制\n\n297\n00:18:52,160 --> 00:18:54,696\n几乎都一样。\n\n298\n00:18:54,696 --> 00:18:56,120\n我们暂停一下，问题时间\n\n299\n00:19:00,040 --> 00:19:04,010\n学生：能否请您重复一下\n\n300\n00:19:04,010 --> 00:19:06,720\n使用逻辑编程的三个目的？\n\n301\n00:19:06,720 --> 00:19:09,120\n换句话说，是不是“寻找什么是真”，\n\n302\n00:19:09,120 --> 00:19:09,840\n“学习什么是真”，“什么是真”？\n\n303\n00:19:09,840 --> 00:19:10,520\n教授：是的。\n\n304\n00:19:10,520 --> 00:19:15,850\n可以说是逻辑程序员的教义吧。\n\n305\n00:19:15,850 --> 00:19:22,610\n你用逻辑来表达什么是真，就像这些规则一样。\n\n306\n00:19:22,610 --> 00:19:26,120\n你使用逻辑来检查某些东西是否为真。这是一些我还没有回答过的问题。\n\n307\n00:19:28,550 --> 00:19:29,720\n我可以说 --\n\n308\n00:19:29,720 --> 00:19:33,620\n我来写另一个问题，\n\n309\n00:19:33,620 --> 00:19:41,400\n1,3,7和2,4,8是否合并成1,2,6,10？\n\n310\n00:19:41,400 --> 00:19:45,690\n同样的逻辑足以判断出这是假的。\n\n311\n00:19:45,690 --> 00:19:49,190\n所以我使用逻辑来判断什么是真，\n\n312\n00:19:49,190 --> 00:19:50,480\n你还可以用逻辑查找什么是真。\n\n313\n00:20:04,060 --> 00:20:04,570\n好。\n\n314\n00:20:04,570 --> 00:20:06,138\n我们休息。\n\n315\n00:20:06,138 --> 00:20:22,106\n【巴赫的音乐】\n\n316\n00:20:22,106 --> 00:20:47,590\n音乐结束\n\n317\n00:20:47,590 --> 00:21:02,901\n【巴赫的音乐】\n\n318\n00:21:02,901 --> 00:21:06,810\n教授：继续。\n\n319\n00:21:06,810 --> 00:21:10,520\n看一下这个查询语言和操作。\n\n320\n00:21:10,520 --> 00:21:12,890\n当你看到这个小圣经数据库时，\n\n321\n00:21:12,890 --> 00:21:15,390\n你注意到的第一点可能是\n\n322\n00:21:15,390 --> 00:21:18,900\n能向这门语言提一些基于某些事实集合的问题，\n\n323\n00:21:18,900 --> 00:21:21,330\n真的很好。\n\n324\n00:21:21,330 --> 00:21:26,060\n现在我们开始，先制作一些事实的集合。\n\n325\n00:21:26,060 --> 00:21:31,700\n这是一家位于波士顿的高科技公司的员工记录的一部分。\n\n326\n00:21:34,440 --> 00:21:37,500\n这是Ben Bitdiddle的记录。\n\n327\n00:21:37,500 --> 00:21:41,470\nBen Bitdiddle是计算机巫师。\n\n328\n00:21:41,470 --> 00:21:44,660\n薪水超低的计算机巫师。\n\n329\n00:21:46,420 --> 00:21:49,330\n他的领导是Oliver Warbucks\n\n330\n00:21:49,330 --> 00:21:52,150\n这是他的地址。\n\n331\n00:21:52,150 --> 00:21:55,220\n我们记录信息的格式是这样的：\n\n332\n00:21:55,220 --> 00:21:57,300\n职位，薪资，上级，地址。\n\n333\n00:21:57,300 --> 00:21:59,250\n我们还有一些约定。\n\n334\n00:21:59,250 --> 00:22:01,570\n这里的Computer表示Ben在计算机部门工作，\n\n335\n00:22:01,570 --> 00:22:03,590\n它在计算机部门的岗位\n\n336\n00:22:03,590 --> 00:22:06,440\n是巫师。\n\n337\n00:22:06,440 --> 00:22:07,580\n这是另外一个人。\n\n338\n00:22:07,580 --> 00:22:13,860\nAlyssa, Alyssa P. Hacker是一个程序员，\n\n339\n00:22:13,860 --> 00:22:17,550\n在Ben手底下工作，她住在剑桥。\n\n340\n00:22:17,550 --> 00:22:19,990\nBen手下还有另外一个程序员，\n\n341\n00:22:19,990 --> 00:22:22,820\nLem E. Tweakit。\n\n342\n00:22:22,820 --> 00:22:26,330\n这是另外一个程序员教练，\n\n343\n00:22:26,330 --> 00:22:30,100\nLouis Reasoner，为Alyssa工作。\n\n344\n00:22:30,100 --> 00:22:34,830\n公司的大老板，\n\n345\n00:22:34,830 --> 00:22:37,010\n谁也管不了他，对吧？\n\n346\n00:22:37,010 --> 00:22:38,110\nOliver Warbucks。\n\n347\n00:22:38,110 --> 00:22:43,080\n好了，我们要做的就是\n\n348\n00:22:43,080 --> 00:22:44,971\n围绕着这个小世界开始提问。\n\n349\n00:22:44,971 --> 00:22:47,410\n这就是我们要进行逻辑演算的\n\n350\n00:22:47,410 --> 00:22:48,660\n小世界。\n\n351\n00:22:51,420 --> 00:22:55,810\n让我在这里写一下，最后一次，\n\n352\n00:22:55,810 --> 00:22:57,600\n你们应该从这们课里学到的最重要的东西\n\n353\n00:22:57,600 --> 00:23:00,760\n当有人问到你们某一门语言时，\n\n354\n00:23:00,760 --> 00:23:03,440\n你能说，好吧 --\n\n355\n00:23:03,440 --> 00:23:15,050\n它的原语是什么，组合的方式是什么，\n\n356\n00:23:15,050 --> 00:23:18,480\n你怎么把原语组合起来，\n\n357\n00:23:18,480 --> 00:23:24,690\n如何进行抽象，如何对复合的零件进行抽象，\n\n358\n00:23:24,690 --> 00:23:26,740\n以便可以把它们当作零件，来搭建更复杂的东西？\n\n359\n00:23:28,500 --> 00:23:31,440\n这些我们已经讲了很多次了，\n\n360\n00:23:31,440 --> 00:23:32,690\n但还是值得再说一次。\n\n361\n00:23:36,210 --> 00:23:36,670\n开始。\n\n362\n00:23:36,670 --> 00:23:38,040\n原语。\n\n363\n00:23:38,040 --> 00:23:41,660\n好吧，事实上原语只有一条，\n\n364\n00:23:41,660 --> 00:23:44,400\n叫做查询。\n\n365\n00:23:44,400 --> 00:23:46,810\n查询原语。\n\n366\n00:23:46,810 --> 00:23:48,060\n让我们看一些查询原语的例子。\n\n367\n00:23:52,160 --> 00:23:53,100\nJob x.\n\n368\n00:23:53,100 --> 00:23:55,550\n谁是程序员？\n\n369\n00:23:55,550 --> 00:24:04,700\n或者查找所有符合以下模式的事实：\n\n370\n00:24:04,700 --> 00:24:06,640\nJob of the x is computer programmer.\n\n371\n00:24:06,640 --> 00:24:08,470\n这里有一点小小的语法了。\n\n372\n00:24:08,470 --> 00:24:11,330\n不带问号的东西是字面量，\n\n373\n00:24:11,330 --> 00:24:13,940\n问号 x表示变量，这个东西会匹配\n\n374\n00:24:13,940 --> 00:24:18,110\n这样的事实：Alyssa P. Hacker是一个程序员，\n\n375\n00:24:18,110 --> 00:24:21,930\n或者x是Alyssa P. Hacker。\n\n376\n00:24:26,820 --> 00:24:29,170\n或者更一般的，我们可以在\n\n377\n00:24:29,170 --> 00:24:30,750\n一条语句里包含两个变量。\n\n378\n00:24:30,750 --> 00:24:39,530\n我可以这样写：x的工作是computer XXX.\n\n379\n00:24:39,530 --> 00:24:42,140\n这会匹配计算机巫师。\n\n380\n00:24:42,140 --> 00:24:44,865\n注意这里：类型匹配巫师，\n\n381\n00:24:44,865 --> 00:24:49,390\n或者程序员，或者x可以匹配\n\n382\n00:24:49,390 --> 00:24:50,370\n很多东西。\n\n383\n00:24:50,370 --> 00:24:53,270\n所以在我们的例子里，\n\n384\n00:24:53,270 --> 00:24:55,150\n数据库里只有3条事实符合查询。\n\n385\n00:24:59,210 --> 00:25:04,910\n我们看一下同样的查询。这是为了给你们看一下语法。\n\n386\n00:25:04,910 --> 00:25:11,490\n这个查询不匹配job of x，\n\n387\n00:25:11,490 --> 00:25:13,200\n不匹配Lewis Reasoner。原因是\n\n388\n00:25:13,200 --> 00:25:17,160\n当我这样写的时候，表示这里有两个符号，\n\n389\n00:25:17,160 --> 00:25:22,730\n第一个词是computer，\n\n390\n00:25:22,730 --> 00:25:24,810\n第二个可以是任何东西。\n\n391\n00:25:24,810 --> 00:25:28,130\nLewis的职位描述有三个符号，\n\n392\n00:25:28,130 --> 00:25:30,340\n所以不匹配。\n\n393\n00:25:30,340 --> 00:25:35,360\n再给你们看一点语法，\n\n394\n00:25:35,360 --> 00:25:37,920\n我想写的更一般类型是一个东西\n\n395\n00:25:37,920 --> 00:25:42,550\n后面加一个点，这中方法表示\n\n396\n00:25:42,550 --> 00:25:46,560\n这回死一个list，其中第一个元素\n\n397\n00:25:46,560 --> 00:25:49,350\n是computer，其它的东西，\n\n398\n00:25:49,350 --> 00:25:50,600\n我称之为类型。\n\n399\n00:25:53,730 --> 00:25:56,930\n所以这一个是匹配的。\n\n400\n00:25:56,930 --> 00:26:00,000\nLewis's 的工作是程序员教练，\n\n401\n00:26:00,000 --> 00:26:04,690\n这里的类型是list的身体部分，就是\n\n402\n00:26:04,690 --> 00:26:06,960\n程序员教练列表。\n\n403\n00:26:06,960 --> 00:26:08,410\n像这样对“点”的处理会\n\n404\n00:26:08,410 --> 00:26:10,460\n由Lisp解释器自动完成。\n\n405\n00:26:15,900 --> 00:26:17,760\n好了，让我们正式试一试吧。\n\n406\n00:26:17,760 --> 00:26:20,810\n我用这门语言进行输入，\n\n407\n00:26:20,810 --> 00:26:23,630\n然后答案就会出来。\n\n408\n00:26:23,630 --> 00:26:25,180\n看这。\n\n409\n00:26:25,180 --> 00:26:30,000\n我来问：谁在计算机部门工作？\n\n410\n00:26:30,000 --> 00:26:39,730\nJob of x is computer dot y.\n\n411\n00:26:39,730 --> 00:26:42,562\n这个变量叫什么没关系。\n\n412\n00:26:42,562 --> 00:26:45,690\n答案出来了。有4个答案。\n\n413\n00:26:48,650 --> 00:26:51,380\n我再问：告诉我所有人的领导。\n\n414\n00:26:52,505 --> 00:26:56,610\n我这样写查询，一条查询原语，\n\n415\n00:26:56,610 --> 00:26:59,390\nthe supervisor of x is y.\n\n416\n00:27:02,860 --> 00:27:05,540\n这就是所有我们能了解的上下级关系。\n\n417\n00:27:05,540 --> 00:27:08,830\n我还可以输入：谁住在剑桥？\n\n418\n00:27:08,830 --> 00:27:20,670\n像这样：address of x is cambridge . 随便什么\n\n419\n00:27:25,090 --> 00:27:26,585\n只有一个人住在剑桥。\n\n420\n00:27:30,820 --> 00:27:32,170\n这些都是查询原语。\n\n421\n00:27:32,170 --> 00:27:34,460\n和系统的间的基本交互就是\n\n422\n00:27:34,460 --> 00:27:38,140\n你输入查询，系统\n\n423\n00:27:38,140 --> 00:27:39,620\n输出所有可能的答案。\n\n424\n00:27:39,620 --> 00:27:43,100\n或者说，系统找出\n\n425\n00:27:43,100 --> 00:27:45,330\n所有x和y或者t或者随便什么名字的变量的所有可能的取值\n\n426\n00:27:45,330 --> 00:27:50,380\n，并按所有满足查询的方式\n\n427\n00:27:50,380 --> 00:27:53,080\n填充原语并输出 ---\n\n428\n00:27:53,080 --> 00:27:56,250\n回想一下系统规则那堂课里讲的--\n\n429\n00:27:56,250 --> 00:27:59,150\n用所有变量的所有可能的取值实例化查询\n\n430\n00:27:59,150 --> 00:28:01,000\n并输出。\n\n431\n00:28:01,000 --> 00:28:02,370\n对一门逻辑语言，\n\n432\n00:28:02,370 --> 00:28:03,350\n存在很多种排列方式\n\n433\n00:28:03,350 --> 00:28:06,010\n比如Prolog就略有差异。\n\n434\n00:28:06,010 --> 00:28:08,980\n它不是输出查询语句，而是输出\n\n435\n00:28:08,980 --> 00:28:12,230\nx等于这个，y等于这个，\n\n436\n00:28:12,230 --> 00:28:12,650\n或者x=这个，y=这个。\n\n437\n00:28:12,650 --> 00:28:16,430\n这些是一些表层的东西，你可以\n\n438\n00:28:16,430 --> 00:28:19,070\n选择你喜欢的方式。\n\n439\n00:28:19,070 --> 00:28:20,760\n好。\n\n440\n00:28:20,760 --> 00:28:21,340\n就这样。\n\n441\n00:28:21,340 --> 00:28:23,390\n这门语言里有哪些原语？\n\n442\n00:28:23,390 --> 00:28:24,570\n就一个，对吗？\n\n443\n00:28:24,570 --> 00:28:27,230\n查询原语。\n\n444\n00:28:31,360 --> 00:28:31,650\n好。\n\n445\n00:28:31,650 --> 00:28:34,330\n组合的方法。\n\n446\n00:28:34,330 --> 00:28:39,770\n我们看一些这门语言里的复合查询。\n\n447\n00:28:39,770 --> 00:28:41,790\n这里有一个。\n\n448\n00:28:41,790 --> 00:28:47,250\n它说：告诉我所有在\n\n449\n00:28:47,250 --> 00:28:49,810\n计算机部门工作的人。\n\n450\n00:28:49,810 --> 00:28:52,610\n告诉我所有在计算机部门工作\n\n451\n00:28:52,610 --> 00:28:53,860\n的人，以及他们的领导。\n\n452\n00:28:56,800 --> 00:29:00,220\n我写这条语句的方式是这样的： .. and ...\n\n453\n00:29:00,220 --> 00:29:04,920\n而且x是computer或者别的什么东西。\n\n454\n00:29:04,920 --> 00:29:07,560\n而且x的职位是computer . y。\n\n455\n00:29:07,560 --> 00:29:11,650\nx的主观是z。\n\n456\n00:29:11,650 --> 00:29:13,570\n告诉我所有在计算机部门工作的人--\n\n457\n00:29:13,570 --> 00:29:16,460\n就是这个--以及他们的领导。\n\n458\n00:29:16,460 --> 00:29:20,290\n注意在这条查询里我使用了3个变量--\n\n459\n00:29:20,290 --> 00:29:23,660\nx, y, 和z.\n\n460\n00:29:23,660 --> 00:29:29,450\n这个x和这个x相同。\n\n461\n00:29:29,450 --> 00:29:31,560\n所以x在计算机部门工作，\n\n462\n00:29:31,560 --> 00:29:34,810\n而且x的领导是z。\n\n463\n00:29:34,810 --> 00:29:37,250\n我们再试一下另外一个。\n\n464\n00:29:37,250 --> 00:29:39,005\n所以一种组合的方式是 and。\n\n465\n00:29:41,540 --> 00:29:45,790\n都有哪些人收入超过3万美元？\n\n466\n00:29:45,790 --> 00:29:51,640\n员工p的收入是a。\n\n467\n00:29:54,590 --> 00:30:00,600\n我们再看一下a，a大于3万美元。\n\n468\n00:30:00,600 --> 00:30:06,300\nlisp-value在这的作用是\n\n469\n00:30:06,300 --> 00:30:10,600\n作为查询语言和底层LISP的接口。\n\n470\n00:30:10,600 --> 00:30:13,540\nlisp-value可以允许你在一条查询中\n\n471\n00:30:13,540 --> 00:30:17,180\n调用任何LISP谓词。\n\n472\n00:30:17,180 --> 00:30:19,110\n我在这使用了LISP谓词greater than，\n\n473\n00:30:19,110 --> 00:30:21,020\n所以我用lisp-value。\n\n474\n00:30:21,020 --> 00:30:21,750\n我这样写。\n\n475\n00:30:21,750 --> 00:30:28,190\n所有收入超过3万美元的人。\n\n476\n00:30:28,190 --> 00:30:31,270\n或者这里有一个跟复杂的。\n\n477\n00:30:31,270 --> 00:30:36,150\n告诉我所有这样的人：他在计算机部工作，\n\n478\n00:30:36,150 --> 00:30:38,560\n但他的领导不在\n\n479\n00:30:38,560 --> 00:30:39,810\n计算机部。\n\n480\n00:30:42,790 --> 00:30:45,510\nx在计算机部。\n\n481\n00:30:45,510 --> 00:30:47,780\nThe job of x is computer\ndot y. x的工作是computer 点。\n\n482\n00:30:47,780 --> 00:30:55,570\nand 不能满足这个条件：\n\n483\n00:30:55,570 --> 00:30:59,620\nx有领导z，而且z的工作是computer加随便什么东西。\n\n484\n00:30:59,620 --> 00:31:04,050\n好的，这一次这个x还是和这个x相等。\n\n485\n00:31:04,050 --> 00:31:05,710\n这个z和这个z相等。\n\n486\n00:31:09,390 --> 00:31:11,380\n你们看到了另外一种组合的方式：not（非）。\n\n487\n00:31:17,272 --> 00:31:20,880\n好的，让我们再看一下。\n\n488\n00:31:20,880 --> 00:31:22,400\n它工作的方式是一样的。\n\n489\n00:31:22,400 --> 00:31:33,110\n我可以对机器说 x的工作是computer点y。\n\n490\n00:31:33,110 --> 00:31:35,400\ncomputer dot y.\n\n491\n00:31:38,480 --> 00:31:46,600\nx的领导是z。\n\n492\n00:31:46,600 --> 00:31:50,794\n我把这些作为查询输进去。\n\n493\n00:31:50,794 --> 00:31:55,680\n得到的输出是使用所有可能的答案\n\n494\n00:31:55,680 --> 00:31:58,930\n填充输进去的查询。\n\n495\n00:31:58,930 --> 00:32:02,000\n你们看这里有很多个答案。\n\n496\n00:32:02,000 --> 00:32:02,190\n好吧。\n\n497\n00:32:02,190 --> 00:32:05,230\n所以在这门语言里的组合方式是逻辑运算。\n\n498\n00:32:05,230 --> 00:32:07,550\n这也是为什么它被称为逻辑语言。\n\n499\n00:32:09,800 --> 00:32:16,120\n组合的方式是 AND和NOT。\n\n500\n00:32:16,120 --> 00:32:18,490\n还有一个我还没讲的，OR（或）。\n\n501\n00:32:18,490 --> 00:32:24,310\n我还介绍了lisp-value。\n\n502\n00:32:24,310 --> 00:32:26,365\n当然它不是逻辑运算，而是一个小技巧，用于\n\n503\n00:32:26,365 --> 00:32:29,250\n和LISP对接以便获得更多的功能。\n\n504\n00:32:29,250 --> 00:32:32,690\n这些就是组合的方式。\n\n505\n00:32:32,690 --> 00:32:34,160\nOK。 抽象的方式。\n\n506\n00:32:34,160 --> 00:32:35,410\n我们想要做的是--\n\n507\n00:32:38,330 --> 00:32:42,260\n我们往回看上一张胶片。\n\n508\n00:32:42,260 --> 00:32:45,010\n我们的问题很复杂，\n\n509\n00:32:45,010 --> 00:32:48,800\n那些在一个部门工作，\n\n510\n00:32:48,800 --> 00:32:52,400\n但是领导却不在这个部门的人。\n\n511\n00:32:52,400 --> 00:32:56,090\n和之前一样，给它起个名字。\n\n512\n00:32:56,090 --> 00:32:58,800\n如果一个人在某部门工作，但他的\n\n513\n00:32:58,800 --> 00:33:00,950\n领导却不在这个部门工作，\n\n514\n00:33:00,950 --> 00:33:02,750\n我们就叫他大腕（big shot）。\n\n515\n00:33:02,750 --> 00:33:08,370\n我们定义一条规则，x满足一下条件时是一个大腕：\n\n516\n00:33:08,370 --> 00:33:16,760\nx在某部门工作，同时x的领导\n\n517\n00:33:16,760 --> 00:33:19,610\n在同一部门工作不成立。\n\n518\n00:33:21,510 --> 00:33:22,940\n这就是我们的抽象方式。\n\n519\n00:33:22,940 --> 00:33:24,190\n这是一条规则。\n\n520\n00:33:26,220 --> 00:33:27,580\n一条规则有3个部分。\n\n521\n00:33:30,970 --> 00:33:33,450\n这个规定了它是一条规则。\n\n522\n00:33:33,450 --> 00:33:37,530\n这是规则的结论。\n\n523\n00:33:37,530 --> 00:33:40,000\n这是规则的主体。\n\n524\n00:33:40,000 --> 00:33:42,150\n你们可以把这个当作一条逻辑：\n\n525\n00:33:42,150 --> 00:33:46,940\n如果规则的主体为真，则\n\n526\n00:33:46,940 --> 00:33:49,470\n规则的结论部分也为真。\n\n527\n00:33:49,470 --> 00:33:52,640\n想要得出x是一个大腕的结论，\n\n528\n00:33:52,640 --> 00:33:57,480\n验证它就可以了。\n\n529\n00:33:57,480 --> 00:33:58,820\n规则就是长这个样子的。\n\n530\n00:34:03,280 --> 00:34:07,180\n再回去看我们休息之前我给出的\n\n531\n00:34:07,180 --> 00:34:08,110\n合并的例子。\n\n532\n00:34:08,110 --> 00:34:11,610\n我们看一下如果用规则来表示会是什么样子。\n\n533\n00:34:11,610 --> 00:34:14,030\n我要把我给出的逻辑\n\n534\n00:34:14,030 --> 00:34:15,500\n转换成一组像这样的格式的规则。\n\n535\n00:34:18,739 --> 00:34:19,350\n这是一条规则。\n\n536\n00:34:19,350 --> 00:34:21,710\n记住，这是“合并成为”。\n\n537\n00:34:21,710 --> 00:34:28,489\n这里有一条规则：空list和y合并\n\n538\n00:34:28,489 --> 00:34:29,620\n的结果是y。\n\n539\n00:34:29,620 --> 00:34:30,870\n这是规则的结论。\n\n540\n00:34:33,210 --> 00:34:36,650\n注意这条规则没有主体部分。\n\n541\n00:34:36,650 --> 00:34:40,010\n在这门语言里，一条没有主体的规则\n\n542\n00:34:40,010 --> 00:34:41,239\n永远为真。\n\n543\n00:34:41,239 --> 00:34:42,510\n你可以始终认为它为真。\n\n544\n00:34:45,190 --> 00:34:47,530\n这里是另外一条逻辑，它说空list中的anything\n\n545\n00:34:47,530 --> 00:34:49,460\n合并得到的结果是anything。\n\n546\n00:34:49,460 --> 00:34:50,900\n就是这个。\n\n547\n00:34:50,900 --> 00:34:55,510\n规则：y和空list合并得到y。\n\n548\n00:34:55,510 --> 00:34:58,060\n这对应于我们的合并过程中的最后两个case。\n\n549\n00:34:58,060 --> 00:35:00,890\n但我们现在说的是规则，而不是过程。\n\n550\n00:35:03,490 --> 00:35:07,560\n然后我们还有另外一条规则：如果你知道\n\n551\n00:35:07,560 --> 00:35:09,830\n短一点的东西如何合并，你就可以把它们放到一起。\n\n552\n00:35:09,830 --> 00:35:15,340\n这就是说，如果你有一个list x，y，和z，而且\n\n553\n00:35:15,340 --> 00:35:19,530\n你想知道a.x--这表示常量a加上x，或者\n\n554\n00:35:19,530 --> 00:35:23,160\n一个list，第一个元素是a，剩余部分是x --\n\n555\n00:35:23,160 --> 00:35:26,230\n如果你想得到它： a.x和b.y合并\n\n556\n00:35:26,230 --> 00:35:27,480\n得到b.c。\n\n557\n00:35:30,570 --> 00:35:34,070\n就是说你合并list a.x和b.x并且\n\n558\n00:35:34,070 --> 00:35:37,680\n你将得到一个以b开始的东西--\n\n559\n00:35:37,680 --> 00:35:41,880\n如果你知道，\n\n560\n00:35:41,880 --> 00:35:48,690\na.x和y合并得到z，以及a大于b同时成立。\n\n561\n00:35:48,690 --> 00:35:52,610\n于是当我们合并它们时，b会在list的前面。\n\n562\n00:35:52,610 --> 00:35:56,050\n这是从我前面用伪英语描述\n\n563\n00:35:56,050 --> 00:35:57,960\n的逻辑翻译过来的。\n\n564\n00:35:57,960 --> 00:35:59,870\n为了更完备的描述这个问题，\n\n565\n00:35:59,870 --> 00:36:03,130\n再看另一种情况。\n\n566\n00:36:03,130 --> 00:36:08,170\n如果x和b.y合并等于z而且b大于a，则\n\n567\n00:36:08,170 --> 00:36:12,190\na.x和b.y合并等于a.z。\n\n568\n00:36:12,190 --> 00:36:15,610\n这就是我用这门语言写的一个小程序，\n\n569\n00:36:15,610 --> 00:36:17,416\n我们看一下它运行起来是什么样子。\n\n570\n00:36:21,900 --> 00:36:27,740\n我把前面的合并规则输进去，\n\n571\n00:36:27,740 --> 00:36:28,510\n并把它做为一个过程使用。\n\n572\n00:36:28,510 --> 00:36:39,590\n我可以说：合并1,3和2,7。\n\n573\n00:36:39,590 --> 00:36:43,330\n我现在就像一个lisp过程一样使用它。\n\n574\n00:36:43,330 --> 00:36:46,940\n它现在需要思考一下，\n\n575\n00:36:46,940 --> 00:36:48,190\n并应用这些规则。\n\n576\n00:36:50,780 --> 00:36:52,800\n它找到了一个答案。\n\n577\n00:36:52,800 --> 00:36:55,370\n它还要再找一找有没有别的答案。\n\n578\n00:36:55,370 --> 00:36:57,810\n它事先并不知道只有一个答案。\n\n579\n00:36:57,810 --> 00:37:00,790\n所以它正在检查所有的可能性，\n\n580\n00:37:00,790 --> 00:37:01,970\n然后它回答：没有别的了。\n\n581\n00:37:01,970 --> 00:37:02,775\n完。\n\n582\n00:37:02,775 --> 00:37:05,210\n这里我像使用过程一样使用这些规则。\n\n583\n00:37:05,210 --> 00:37:08,340\n记住全部的要点在于，\n\n584\n00:37:08,340 --> 00:37:10,220\n我可以问不同形式的问题。\n\n585\n00:37:10,220 --> 00:37:24,590\n我可以问，比如，2和a合并。\n\n586\n00:37:24,590 --> 00:37:29,440\n有些2元素列表我已经知道以2开始，\n\n587\n00:37:29,440 --> 00:37:34,600\n其它的我不知道，而且x和某些别的list\n\n588\n00:37:34,600 --> 00:37:39,510\n合并得到a, 1, 2, 3, 4。\n\n589\n00:37:42,760 --> 00:37:44,590\n它又在开始思考了。\n\n590\n00:37:44,590 --> 00:37:45,840\n它会找到答案的 --\n\n591\n00:37:48,070 --> 00:37:49,095\n它找到了一个。\n\n592\n00:37:49,095 --> 00:37:53,830\n它说a可以是3，x是list 1， 4.\n\n593\n00:37:53,830 --> 00:37:57,220\n现在它还要继续查找，因为\n\n594\n00:37:57,220 --> 00:37:59,050\n它事先并不知道\n\n595\n00:37:59,050 --> 00:38:00,300\n并没有其它的可能性了。\n\n596\n00:38:03,680 --> 00:38:10,660\n我前面说过，我可以问一些类似合并的问题：\n\n597\n00:38:10,660 --> 00:38:17,275\n比如，谁和谁合并得到1,2,3,4,5?\n\n598\n00:38:24,340 --> 00:38:25,590\n它正在思考。\n\n599\n00:38:28,490 --> 00:38:30,310\n它应该会找到很多个答案。\n\n600\n00:38:35,180 --> 00:38:37,920\n你们看到了，你们需要付出\n\n601\n00:38:37,920 --> 00:38:39,170\n运行速度作为代价。\n\n602\n00:38:42,210 --> 00:38:43,880\n有3个原因。\n\n603\n00:38:43,880 --> 00:38:47,630\n首先这门语言被解释了两次。\n\n604\n00:38:47,630 --> 00:38:50,100\n在现实环境中，你们会\n\n605\n00:38:50,100 --> 00:38:52,190\n把它编译成原子操作。\n\n606\n00:38:52,190 --> 00:38:56,410\n另一个原因是我们用的合并算法\n\n607\n00:38:56,410 --> 00:38:58,380\n是双重递归的。\n\n608\n00:38:58,380 --> 00:39:01,020\n所以它会占用很长的时间。\n\n609\n00:39:01,020 --> 00:39:06,710\n最后，它会跑完并找到--\n\n610\n00:39:06,710 --> 00:39:07,130\n找到什么？\n\n611\n00:39:07,130 --> 00:39:08,730\n第2到第5个可能的答案。\n\n612\n00:39:12,140 --> 00:39:14,830\n你们看，它们的顺序是相当随机的，\n\n613\n00:39:14,830 --> 00:39:17,100\n这取决于它按什么顺序\n\n614\n00:39:17,100 --> 00:39:20,160\n去试验这些规则。\n\n615\n00:39:20,160 --> 00:39:21,530\n实际上，当我们编辑视频时，\n\n616\n00:39:21,530 --> 00:39:24,310\n会把这块的速度加快。\n\n617\n00:39:24,310 --> 00:39:26,600\n你们自己做demo的时候\n\n618\n00:39:26,600 --> 00:39:28,250\n也会想要把这些等待时间刨掉吧？\n\n619\n00:39:32,840 --> 00:39:34,260\n它还在那里推磨呢。\n\n620\n00:39:39,220 --> 00:39:41,170\n一共有32中可能呢--\n\n621\n00:39:41,170 --> 00:39:42,630\n我们不等它把所有的答案都打出来了。\n\n622\n00:39:47,850 --> 00:39:49,410\n所以在这门语言里，\n\n623\n00:39:49,410 --> 00:39:50,660\n抽象的方法是规则。\n\n624\n00:39:53,630 --> 00:39:57,410\n我们把一堆用逻辑联系在一起的东西\n\n625\n00:39:57,410 --> 00:40:00,350\n起个名字。\n\n626\n00:40:00,350 --> 00:40:02,080\n你们可以把这看作是为一个\n\n627\n00:40:02,080 --> 00:40:03,410\n特定的逻辑模式起名。\n\n628\n00:40:03,410 --> 00:40:05,810\n或者可以把它看作是这样的：如果你想要得到某些结论，\n\n629\n00:40:05,810 --> 00:40:10,660\n你可以应用那些逻辑的规则。\n\n630\n00:40:10,660 --> 00:40:13,420\n这些是这门语言的三个元素。\n\n631\n00:40:13,420 --> 00:40:15,670\n我们休息一下，接下来我们将要讲\n\n632\n00:40:15,670 --> 00:40:16,920\n如何实现它。\n\n633\n00:40:22,747 --> 00:40:27,380\n学生： 使用lisp-value一类的东西\n\n634\n00:40:27,380 --> 00:40:31,770\n是否会影响我们在一个查询的两个方向间的转换？\n\n635\n00:40:31,770 --> 00:40:33,530\n教授： OK, 这是一个--\n\n636\n00:40:33,530 --> 00:40:37,840\n这个问题是，使用lisp-value是否会干扰\n\n637\n00:40:37,840 --> 00:40:40,090\n在查询的两个方向上转换的能力？\n\n638\n00:40:40,090 --> 00:40:43,850\n我们还没有讲到具体的实现，\n\n639\n00:40:43,850 --> 00:40:46,890\n但答案是“yes”，会影响的。\n\n640\n00:40:46,890 --> 00:40:50,510\n一般的，我们在后面会看到的 --\n\n641\n00:40:50,510 --> 00:40:53,330\n尽管我不会进入具体的细节 --\n\n642\n00:40:53,330 --> 00:40:58,140\n这确实很复杂，尤其是当你们使用\n\n643\n00:40:58,140 --> 00:40:59,780\nnot（非）或lisp-value时--\n\n644\n00:40:59,780 --> 00:41:04,310\n或者说，实际上如果你们想使用任何“AND”以外的东西时，\n\n645\n00:41:04,310 --> 00:41:07,350\n都会变得很复杂，很难判断\n\n646\n00:41:07,350 --> 00:41:08,700\n这些东西好不好使。\n\n647\n00:41:08,700 --> 00:41:10,360\n我们不能保证他们在所有的情况下都能正常工作。\n\n648\n00:41:10,360 --> 00:41:14,300\n今天的后半堂课快结束时我会将这个问题。\n\n649\n00:41:14,300 --> 00:41:17,180\n但你的问题的答案是：yes。\n\n650\n00:41:17,180 --> 00:41:22,000\n当我们通过lisp-value获得了更多的能力时，\n\n651\n00:41:22,000 --> 00:41:24,170\n我们也失去了一些逻辑编程的关键能力。\n\n652\n00:41:24,170 --> 00:41:28,090\n这是一个必须接受的交换。\n\n653\n00:41:28,090 --> 00:41:30,390\nOK。我们休息一下。\n"
  },
  {
    "path": "SrtCN/lec8a.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:02,672\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:18,270 --> 00:00:19,680\n教授：上节课中 我们学习了\nPROFESSOR: The last time we began having a look\n\n3\n00:00:19,728 --> 00:00:21,264\n如何构造语言\nat how languages are constructed.\n\n4\n00:00:22,416 --> 00:00:25,888\n核心点就是 像Lisp这样的求值器\nRemember the main point that an evaluator for, LISP, say,\n\n5\n00:00:26,080 --> 00:00:27,580\n有两个主要部分\nhas two main elements.\n\n6\n00:00:27,580 --> 00:00:28,400\n一个是EVAL\nThere is EVAL,\n\n7\n00:00:31,040 --> 00:00:37,424\nEVAL接受一个表达式EXP和环境ENV\nand EVAL's job is to take in an expression and an environment\n\n8\n00:00:38,912 --> 00:00:44,448\n然后返回一个过程和相关的实际参数\nand turn that into a procedure and some arguments\n\n9\n00:00:45,424 --> 00:00:47,056\n并把它们传递给APPLY\nand pass that off to APPLY.\n\n10\n00:00:49,410 --> 00:00:51,296\nAPPLY接收这些过程和实际参数\nAnd APPLY takes the procedure in the arguments,\n\n11\n00:00:51,696 --> 00:00:55,120\n通常来说 APPLY会返回另一个表达式\nturns that back into, in a general case, another expression\n\n12\n00:00:55,392 --> 00:00:57,712\n返回一个在其它环境中求值的表达式\nto be evaluated in another environment\n\n13\n00:00:57,744 --> 00:01:00,000\n表达式就像这样在EVAL-APPLY之间传递\nand passes that off to EVAL, which passes it to APPLY,\n\n14\n00:01:00,272 --> 00:01:01,440\n这就是整个元循环\nand there's this whole big circle\n\n15\n00:01:01,470 --> 00:01:02,944\n表达式在这里面循环往复\nwhere things go around and around and around\n\n16\n00:01:03,024 --> 00:01:06,560\n直到最后求值为基本数据或基本过程\nuntil you get either to some very primitive data or to a primitive procedure.\n\n17\n00:01:07,740 --> 00:01:09,248\n这个循环要做的就是\nSee, what this cycle has to do with\n\n18\n00:01:09,440 --> 00:01:12,576\n把语言中的组合手段\nis unwinding the means of combination\n\n19\n00:01:12,590 --> 00:01:14,368\n和抽象手段展开\nand the means of abstraction in the language.\n\n20\n00:01:15,020 --> 00:01:17,728\n比如说在Lisp中 你有一个过程\nSo for instance, you have a procedure in LISP--\n\n21\n00:01:17,744 --> 00:01:20,528\n定义过程是为了\na procedure is a general way of saying,\n\n22\n00:01:20,540 --> 00:01:22,576\n让表达式的计算过程\nI want to be able to evaluate this expression\n\n23\n00:01:22,672 --> 00:01:24,410\n适用于任意的参数\nfor any value of the arguments,\n\n24\n00:01:25,760 --> 00:01:27,184\n这就是这里面发生的事情\nand that's sort of what's going on here.\n\n25\n00:01:27,670 --> 00:01:28,510\n这就是APPLY做的事\nThat's what APPLY does.\n\n26\n00:01:28,510 --> 00:01:30,688\n当一个带参数的一般性表达式进入以后\nIt says the general thing coming in with the arguments\n\n27\n00:01:30,720 --> 00:01:32,704\n它将其归约为过程体的表达式\nreduces to the expression that's the body,\n\n28\n00:01:33,056 --> 00:01:34,720\n如果归约得到的是复合表达式\nand then if that's a compound expression\n\n29\n00:01:34,832 --> 00:01:36,464\n或者是另外的过程应用\nor another procedure application,\n\n30\n00:01:36,784 --> 00:01:38,448\n那么这个循环就会不断地进行\nthe thing will go around and around the circle.\n\n31\n00:01:40,336 --> 00:01:44,080\n这基本上就是 -- 大部分解释器的基本结构了\nAnyway, that's sort of the basic structure of gee, pretty much any interpreter.\n\n32\n00:01:45,200 --> 00:01:46,256\n另外一点就是\nThe other thing that you saw\n\n33\n00:01:46,288 --> 00:01:47,660\n一旦你有了一个解释器\nonce you have the interpreter in your hands,\n\n34\n00:01:47,696 --> 00:01:49,870\n你就有了操作这门语言的所有能力\nyou have all this power to start playing with the language.\n\n35\n00:01:49,870 --> 00:01:51,520\n因此你可以让它成为动态作用域\nSo you can make it dynamically scoped,\n\n36\n00:01:51,840 --> 00:01:54,560\n你也可以引入正则序求值\nor you can put in normal order evaluation,\n\n37\n00:01:54,590 --> 00:01:56,480\n你也可以为语言添加新的形式\nor you can add new forms to the language,\n\n38\n00:01:56,860 --> 00:01:57,504\n想怎么样都行\nwhatever you like.\n\n39\n00:01:57,584 --> 00:01:58,624\n或者更一般地说\nOr more generally,\n\n40\n00:01:58,768 --> 00:02:01,328\n这种元语言抽象的概念\nthere's this notion of metalinguistic abstraction,\n\n41\n00:02:02,640 --> 00:02:06,016\n它告诉我们 作为一名软件工程师\nwhich says that part of your perspective\n\n42\n00:02:07,616 --> 00:02:10,528\n从广义的“工程师”的角度来看\nas an engineer, as a software engineer, but as an engineer in general\n\n43\n00:02:11,392 --> 00:02:13,888\n有时你可以通过发明新的语言\nis that you can gain control of complexity\n\n44\n00:02:14,960 --> 00:02:17,168\n来获得控制复杂度的能力\nby inventing new languages sometimes.\n\n45\n00:02:18,010 --> 00:02:20,816\n一种思考计算机程序设计的方法就是\nSee, one way to think about computer programming\n\n46\n00:02:21,552 --> 00:02:26,270\n它只是偶然地让计算机执行某事儿\nis that it only incidentally has to do with getting a computer to do something.\n\n47\n00:02:26,440 --> 00:02:28,976\n计算机程序的主要工作却是\nPrimarily what a computer program has to do with,\n\n48\n00:02:29,008 --> 00:02:32,520\n用来表达和交换想法\nit's a way of expressing ideas with communicating ideas.\n\n49\n00:02:33,168 --> 00:02:34,048\n有时\nAnd sometimes\n\n50\n00:02:34,896 --> 00:02:36,624\n当我们想要表达新的想法时\nwhen you want to communicate new kinds of ideas,\n\n51\n00:02:36,656 --> 00:02:38,736\n我们就想要发明新的模式来表达它们\nyou'd like to invent new modes of expressing that.\n\n52\n00:02:39,824 --> 00:02:44,992\n那么 今天我们就将按照这个框架来创建新语言\nWell, today we're going to apply this framework to build a new language.\n\n53\n00:02:45,730 --> 00:02:48,000\n一旦我们了解了解释器的基本结构\nSee, once we have the basic idea of the interpreter,\n\n54\n00:02:48,032 --> 00:02:50,272\n我们就可以按意愿来构造任意的语言\nyou can pretty much go build any language that you like.\n\n55\n00:02:50,830 --> 00:02:53,216\n比如说 我们可以构造Pascal（的解释器）\nSo for example, we can go off and build Pascal.\n\n56\n00:02:54,370 --> 00:02:55,152\n以及\nAnd...\n\n57\n00:02:56,170 --> 00:02:58,192\n我们需要操心语法的表示与解析\ngee, we would worry about syntax and parsing\n\n58\n00:02:58,192 --> 00:03:00,510\n还有一大堆的编译器优化\nand various kinds of compiler optimizations,\n\n59\n00:03:01,120 --> 00:03:03,296\n还有一些人会这样做\nand there are people who make honest livings doing that,\n\n60\n00:03:03,856 --> 00:03:07,600\n但是就在我们所讨论的抽象层次来说\nbut at the level of abstraction that we're talking,\n\n61\n00:03:08,048 --> 00:03:10,992\n一个Pascal语言的解释器看起来\na Pascal interpreter would not look very different at all\n\n62\n00:03:12,032 --> 00:03:13,760\n跟Gerry教授上节课所讲的大同小异\nfrom what you saw Gerry do last time.\n\n63\n00:03:15,024 --> 00:03:18,960\n但是今天 我们要构建一门与众不同的语言\nInstead of that, we'll spend today building a really different language,\n\n64\n00:03:20,510 --> 00:03:22,816\n这门语言\na language that encourages you\n\n65\n00:03:23,056 --> 00:03:26,040\n不推荐你用过程式的思维来思考程序设计\nto think about programming not in terms of procedures,\n\n66\n00:03:26,240 --> 00:03:27,648\n而是用一种非常不同的方式\nbut in a really different way.\n\n67\n00:03:29,090 --> 00:03:31,024\n今天的课程呢\nAnd the lecture today is\n\n68\n00:03:31,744 --> 00:03:34,640\n将会在两个层次中同时进行\ngoing to be at two levels simultaneously.\n\n69\n00:03:34,810 --> 00:03:35,520\n一方面\nOn the one hand,\n\n70\n00:03:35,904 --> 00:03:37,710\n我会向大家介绍这门语言是如何使用的\nI'm going to show you what this language looks like,\n\n71\n00:03:38,960 --> 00:03:41,080\n另一方面呢 我会带领大家实现这门语言\nand on the other hand, I'll show you how it's implemented.\n\n72\n00:03:41,320 --> 00:03:42,960\n我们将会用Lisp来实现\nAnd we'll build an implementation in LISP\n\n73\n00:03:42,992 --> 00:03:43,900\n并观察它的运行原理\nand see how that works.\n\n74\n00:03:44,048 --> 00:03:48,256\n你应该在两个层次上学到知识\nAnd you should be drawing lessons on two levels.\n\n75\n00:03:48,688 --> 00:03:53,000\n首先要认识到 语言之间可以有多么地“不同”\nThe first is to realize just how different a language can be.\n\n76\n00:03:53,790 --> 00:03:58,144\n如果你认为Fortran和Lisp算是天差地别的话\nSo if you think that the jump from Fortran to LISP is a big deal,\n\n77\n00:03:58,240 --> 00:03:59,360\n那就小巫见大巫了\nyou haven't seen anything yet.\n\n78\n00:04:01,560 --> 00:04:03,680\n其次\nAnd secondly,\n\n79\n00:04:03,776 --> 00:04:06,544\n甚至于在这门与众不同的语言中\nyou'll see that even with such a very different language,\n\n80\n00:04:07,360 --> 00:04:09,520\n这门既不讨论函数\nwhich will turn out to not have procedures at all\n\n81\n00:04:09,920 --> 00:04:11,648\n也没有过程的语言中\nand not talk about functions at all,\n\n82\n00:04:12,200 --> 00:04:15,720\n其中也有基本的EVAL-APPLY循环\nthere will still be this basic cycle of eval and apply\n\n83\n00:04:16,192 --> 00:04:19,984\n也就是对组合手段和抽象手段的展开\nthat's unwinds the means of combination and the means an abstraction.\n\n84\n00:04:20,950 --> 00:04:24,688\n第三点 是一个不太重要但非常优雅的技术技巧\nAnd then thirdly, as kind of a minor but elegant technical point,\n\n85\n00:04:24,890 --> 00:04:28,528\n就是如何巧妙地使用流来避免回溯\nyou'll see a nice use of streams to avoid backtracking.\n\n86\n00:04:32,330 --> 00:04:34,400\n好吧 我说过这门语言与众不同\nOK, well, I said that this language is very different.\n\n87\n00:04:35,860 --> 00:04:36,640\n为了解释这点\nTo explain that,\n\n88\n00:04:37,050 --> 00:04:42,816\n让我们回到这门课最初的理念上\nlet's go back to the very first idea that we talked about in this course,\n\n89\n00:04:43,260 --> 00:04:46,544\n就是要区别\nand that was the idea of the distinction between\n\n90\n00:04:46,720 --> 00:04:49,520\n数学中“陈述性”的知识\nthe declarative knowledge of mathematics--\n\n91\n00:04:50,192 --> 00:04:54,144\n比如平方根的定义就是一条数学事实\nthe definition of a square root as a mathematical truth--\n\n92\n00:04:55,488 --> 00:04:59,568\n而计算机科学讨论的是“如何做”的知识\nand the idea that computer science talks about the how to knowledge--\n\n93\n00:04:59,760 --> 00:05:04,592\n“什么是平方根”和“如何计算平方根”是不同的\ncontrast that definition of square root with a program to compute a square root.\n\n94\n00:05:05,970 --> 00:05:07,072\n我们是从这里开始的\nThat's where we started off.\n\n95\n00:05:08,512 --> 00:05:09,520\n如果我们能够通过某种方式\nWell, wouldn't it be great\n\n96\n00:05:09,888 --> 00:05:12,160\n弥合这种差距 岂不是更好么？\nif you could somehow bridge this gap\n\n97\n00:05:12,810 --> 00:05:16,432\n我们创建一门这样的语言\nand make a programming language which sort of did things,\n\n98\n00:05:16,672 --> 00:05:21,610\n以声明式的方式、用数学事实来完成计算\nbut you talked about it in terms of truth, in declarative terms?\n\n99\n00:05:22,380 --> 00:05:25,504\n你用这种该语言来指定事实\nSo that would be a programming language in which you specify facts.\n\n100\n00:05:27,690 --> 00:05:28,880\n你告诉它\nYou tell it what is.\n\n101\n00:05:28,880 --> 00:05:29,968\n什么是事实\nYou say what is true.\n\n102\n00:05:30,950 --> 00:05:33,072\n而当你需要一个答案时\nAnd then when you want an answer,\n\n103\n00:05:33,216 --> 00:05:36,384\n语言已经自动地内建了\nsomehow the language has built into it automatically\n\n104\n00:05:37,600 --> 00:05:39,456\n有关于“如何做”的一般性知识\ngeneral kinds of how to knowledge\n\n105\n00:05:39,472 --> 00:05:40,640\n这样它就可以根据你给出的事实\nso it can just take your facts\n\n106\n00:05:40,896 --> 00:05:42,832\n自行地演进这些方法\nand it can evolve these methods on its own\n\n107\n00:05:43,312 --> 00:05:46,128\n通过你给定的事实和某种一般性的逻辑规则\nusing the facts you gave it and maybe some general rules of logic.\n\n108\n00:05:49,330 --> 00:05:50,544\n就比如说\nSo for instance,\n\n109\n00:05:52,064 --> 00:05:55,120\n我会告诉程序下述事实\nI might go up to this program and start telling it some things.\n\n110\n00:05:56,000 --> 00:06:07,080\n我告诉它 (SON-OF ADAM ABEL)\nSo I might tell it that the son of Adam is Abel.\n\n111\n00:06:08,920 --> 00:06:16,512\n同时告诉它 (SON-OF ADAM CAIN)\nAnd I might tell it that the son of Adam is Cain.\n\n112\n00:06:17,660 --> 00:06:25,088\n以及 (SON-OF CAIN ENOCH)\nAnd I might tell it that the son of Cain is Enoch.\n\n113\n00:06:27,792 --> 00:06:34,896\n还有 (SON-OF ENOCH IRAD)\nAnd I might tell it that the son of Enoch is Irad,\n\n114\n00:06:37,024 --> 00:06:40,720\n以及《创世纪》章节中的其它人物\nand all through the rest of our chapter whatever of Genesis,\n\n115\n00:06:41,152 --> 00:06:43,184\n最后终止于ADAH\nwhich ends up ending in Adah, by the way,\n\n116\n00:06:43,328 --> 00:06:46,784\n这些是从ADAH到CAIN的家谱\nand this shows the genealogy of Adah from Cain.\n\n117\n00:06:48,440 --> 00:06:50,672\n总之 一旦你指明了这些事实\nAnyway, once you tell it these facts,\n\n118\n00:06:52,352 --> 00:06:53,408\n你就可以提出问题\nyou might ask it things.\n\n119\n00:06:53,510 --> 00:06:55,056\n你可以对语言系统发问\nYou might go up to your language and say,\n\n120\n00:06:56,064 --> 00:06:59,296\n谁是ADAM的孩子？\nwho's the son of Adam?\n\n121\n00:07:00,420 --> 00:07:04,912\n可以很容易地想到一个通用搜索程序\nAnd you can very easily imagine having a little general purpose search program\n\n122\n00:07:05,520 --> 00:07:06,960\n它会遍历所有的事实\nwhich would be able to go through\n\n123\n00:07:07,008 --> 00:07:09,260\n然后回答：“哦 有两个答案”\nand in response to that say, oh yeah, there are two answers:\n\n124\n00:07:09,296 --> 00:07:10,448\nABEL是ADAM的孩子\nthe son of Adam is Abel\n\n125\n00:07:10,688 --> 00:07:12,176\nCAIN也是ADAM的孩子\nand the son of Adam is Cain.\n\n126\n00:07:14,140 --> 00:07:14,976\n你也可以这样问\nOr you might say,\n\n127\n00:07:15,070 --> 00:07:16,890\n基于同样的事实\nbased on the very same facts,\n\n128\n00:07:18,048 --> 00:07:19,952\nCAIN是谁的孩子？\nwho is Cain the son of?\n\n129\n00:07:21,950 --> 00:07:27,024\n你们就会想到生成另外一个略微不同的搜索程序\nAnd then you can imagine generating another slightly different search program\n\n130\n00:07:27,920 --> 00:07:29,216\n它也会遍历所有的事实\nwhich would be able to go through\n\n131\n00:07:29,450 --> 00:07:33,056\n检查谁的孩子是CAIN\nand checked for who is Cain, and son of,\n\n132\n00:07:33,520 --> 00:07:34,440\n发现结果是ADAM\nand come up with Adam.\n\n133\n00:07:35,890 --> 00:07:36,992\n你也可以问\nOr you might say,\n\n134\n00:07:38,016 --> 00:07:41,408\nCAIN和ENOCH之间是什么关系？\nwhat's the relationship between Cain and Enoch?\n\n135\n00:07:42,070 --> 00:07:45,088\n又会生成另一个略微不同的搜索程序\nAnd again, a minor variant on that search program.\n\n136\n00:07:46,340 --> 00:07:48,160\n得到的结果是亲子关系（SON-OF）\nYou could figure out that it said son of.\n\n137\n00:07:52,880 --> 00:07:54,928\n在这个非常简单的例子中\nBut even here in this very simple example,\n\n138\n00:07:56,144 --> 00:07:58,448\n我们发现 即使是单条事实\nwhat you see is that a single fact,\n\n139\n00:07:58,816 --> 00:08:01,520\n比如说 (SON-OF ADAM CAIN)\nsee, a single fact like the son of Adam is Cain\n\n140\n00:08:02,848 --> 00:08:05,520\n可以被用来回答不同种类的问题\ncan be used to answer different kinds of questions.\n\n141\n00:08:06,520 --> 00:08:08,128\n你可以问CAIN是谁的孩子？\nYou can say, who's Cain the son of,\n\n142\n00:08:08,144 --> 00:08:10,928\n你也可以问ADAM的孩子是谁？\nor you can say who's the son of Adam,\n\n143\n00:08:10,944 --> 00:08:12,864\n你也可以问ADAM和CAIN之间的关系是什么？\nor you can say what's the relation between Adam and Cain?\n\n144\n00:08:12,880 --> 00:08:14,480\n这些由不同的传统程序\nThose are different questions\n\n145\n00:08:15,536 --> 00:08:18,544\n所解答的不同的问题\nbeing run by different traditional procedures\n\n146\n00:08:18,688 --> 00:08:20,720\n都基于同样的事实\nall based on the same fact.\n\n147\n00:08:22,752 --> 00:08:25,920\n这正是这种程序设计风格的威力所在\nAnd that's going to be the essence of the power of this programming style,\n\n148\n00:08:26,912 --> 00:08:29,504\n也就是一条陈述性知识\nthat one piece of declarative knowledge\n\n149\n00:08:30,040 --> 00:08:34,016\n可以作为大量关于“如何做”的各种知识的基础\ncan be used as the basis for a lot of different kinds of how-to knowledge,\n\n150\n00:08:34,816 --> 00:08:37,088\n这跟我们正在编写的过程是不同的\nas opposed to the kinds of procedures we're writing\n\n151\n00:08:37,152 --> 00:08:39,552\n我们编写的过程描述了输入\nwhere you sort of tell it what input you're giving in\n\n152\n00:08:39,616 --> 00:08:40,656\n以及想要的输出\nand what answer you want.\n\n153\n00:08:41,490 --> 00:08:44,704\n比如说 我们的平方根程序可以完美地回答\nSo for instance, our square root program can perfectly well answer the question,\n\n154\n00:08:44,768 --> 00:08:47,168\n144的平方根是多少？\nwhat's the square root of 144?\n\n155\n00:08:48,900 --> 00:08:49,776\n但从原理上来说\nBut in principle,\n\n156\n00:08:49,824 --> 00:08:52,830\n平方根的数学定义告诉了你另外的东西\nthe mathematical definition of square root tells you other things.\n\n157\n00:08:52,848 --> 00:08:56,430\n就比如说 17是谁的平方根\nLike it could say, what is 17 the square root of?\n\n158\n00:08:57,590 --> 00:08:59,712\n这就需要另外一个程序来解答\nAnd that would be have to be answered by a different program.\n\n159\n00:09:01,920 --> 00:09:03,504\n因此 数学定义\nSo the mathematical definition,\n\n160\n00:09:03,980 --> 00:09:05,120\n或者更一般地说\nor in general, the\n\n161\n00:09:05,536 --> 00:09:10,300\n你给定的事实 对于问题是没有偏向性的\nthe facts that you give it are somehow unbiased as to what the question is.\n\n162\n00:09:10,900 --> 00:09:12,816\n而我们倾向于编写专门的程序\nWhereas the programs we tend to write specifically\n\n163\n00:09:12,830 --> 00:09:14,208\n因为它们是关于“如何做”的知识\nbecause they are how-to knowledge\n\n164\n00:09:14,240 --> 00:09:16,368\n倾向于寻找特定的答案\ntend to be looking for a specific answer.\n\n165\n00:09:17,568 --> 00:09:20,120\n所以这是我们正在讨论的一个特点\nSo that's going to be one characteristic of what we're talking about.\n\n166\n00:09:21,810 --> 00:09:22,608\n然而我们可以更进一步\nWe can go on.\n\n167\n00:09:23,480 --> 00:09:27,520\n想象一下 我们可以向语言给定一些事实\nWe can imagine that we've given our language some sort of facts.\n\n168\n00:09:27,710 --> 00:09:29,616\n现在 我们给它一些推理规则\nNow let's give it some rules of inference.\n\n169\n00:09:30,020 --> 00:09:31,360\n比如说\nWe can say, for instance,\n\n170\n00:09:31,952 --> 00:09:36,192\n这里 我们先用某种语法表示\nif the-- make up some syntax here--\n\n171\n00:09:36,448 --> 00:09:41,536\n如果(SON-OF ?X ?Y)成立\nif the son of x is y--\n\n172\n00:09:41,680 --> 00:09:45,210\n在这里 我用问号来标识变量\nI'll put question marks to indicate variables here--\n\n173\n00:09:45,616 --> 00:09:56,060\n如果(SON-OF ?X ?Y)和(SON-OF ?Y ?Z)都成立\nif the son of x is y and the son of y is z,\n\n174\n00:09:58,960 --> 00:10:08,464\n那么就有(GRANSON ?X ?Z)\nthen the grandson of x is z.\n\n175\n00:10:09,320 --> 00:10:13,408\n想象一下 如果把这条规则告诉机器\nSo I can imagine telling my machine that rule\n\n176\n00:10:15,008 --> 00:10:17,280\n那么我们就可以这么来询问\nand then being able to say, for instance,\n\n177\n00:10:17,440 --> 00:10:18,688\n谁是ADAM的孙子？\nwho's the grandson of Adam?\n\n178\n00:10:20,610 --> 00:10:23,648\n或者说 IRAD是谁的孙子？\nOr who is Irad the grandson of?\n\n179\n00:10:24,790 --> 00:10:29,088\n或者从这些信息中尽可能地推断出所有的祖孙关系\nOr deduce all grandson relationships you possibly can from this information.\n\n180\n00:10:31,136 --> 00:10:35,600\n我们可以想象 语言知道如何自动求解\nWe can imagine somehow the language knowing how to do that automatically.\n\n181\n00:10:40,224 --> 00:10:45,200\n好吧 我再举一个更具体一点的例子\nOk, Let me give you maybe a little bit more concrete example.\n\n182\n00:10:45,776 --> 00:10:51,952\n这是个用来合并两个有序表的过程\nHere's a procedure that merges two sorted lists.\n\n183\n00:10:53,920 --> 00:11:00,272\nX和Y是两个由数字构成的表\nSo x and y are two, say, lists of numbers,\n\n184\n00:11:00,304 --> 00:11:04,208\n我们可以认为它们是严格升序的表\nlists of distinct numbers, if you like, that are in increasing order.\n\n185\n00:11:04,768 --> 00:11:07,530\nMERGE会把这两个表\nAnd what merge does is take two such lists\n\n186\n00:11:07,712 --> 00:11:10,384\n合并成一个有序的表\nand combine them into a list where everything's in increasing order,\n\n187\n00:11:11,210 --> 00:11:15,000\n这个程序非常简单\nand this is a pretty easy programs\n\n188\n00:11:15,024 --> 00:11:16,144\n你们可以轻松地写出来\nthat you ought to be able to write.\n\n189\n00:11:16,390 --> 00:11:18,640\n也就是 如果X为空 那么结果就是Y\nIt says, if x is empty, the answer is y.\n\n190\n00:11:18,860 --> 00:11:20,464\n如果Y为空 那结果就是X\nIf y is empty, the answer is x.\n\n191\n00:11:21,180 --> 00:11:22,990\n否则的话 就要比较为首的两个元素\nOtherwise, you compare the first two elements.\n\n192\n00:11:22,990 --> 00:11:24,464\n取出X中的第一个元素\nSo you pick out the first thing in x\n\n193\n00:11:24,848 --> 00:11:26,016\n以及Y中的第一个元素\nand the first thing in y,\n\n194\n00:11:26,810 --> 00:11:31,680\n把它们当中谁是最小的那一个\nand then depending on which of those first elements is less,\n\n195\n00:11:32,832 --> 00:11:36,608\nCONS在递归地调用MERGE的结果上\nyou stick the lower one on to the result a recursively merging,\n\n196\n00:11:37,872 --> 00:11:39,920\n要么就是(MERGE (CDR X) Y)\neither chopping the first one off x\n\n197\n00:11:40,112 --> 00:11:41,616\n要么就是(MERGE X (CDR Y))\nor chopping the first one off y.\n\n198\n00:11:42,400 --> 00:11:43,960\n这是标准的程序\nThat's a standard kind of program.\n\n199\n00:11:46,470 --> 00:11:48,416\n我们来考察下其中的逻辑\nLet's look at the logic.\n\n200\n00:11:48,620 --> 00:11:49,792\n先不考虑程序\nLet's forget about the program\n\n201\n00:11:50,288 --> 00:11:52,768\n来看看这个过程所基于的逻辑\nand look at the logic on which that procedure is based.\n\n202\n00:11:53,820 --> 00:11:55,008\n这其中的逻辑是\nSee, there's some logic which says,\n\n203\n00:11:55,024 --> 00:11:57,210\n如果第一个元素较小\ngee, if the first one is less,\n\n204\n00:11:57,536 --> 00:12:00,000\n那么最后的结果就是把它\nthen we get the answer by sticking something onto the\n\n205\n00:12:00,160 --> 00:12:02,128\n跟递归MERGE的结果CONS起来\nthe result of recursively merging the rest.\n\n206\n00:12:02,848 --> 00:12:04,096\n让我们试着把\nSo let's try and be explicit about\n\n207\n00:12:04,240 --> 00:12:06,416\n使这个程序运作的逻辑说清楚一点\nwhat that logic is that's making the program work.\n\n208\n00:12:08,304 --> 00:12:09,440\n这是一部分\nSo here's one piece.\n\n209\n00:12:10,130 --> 00:12:11,536\n这段程序\nHere's the piece of the program which\n\n210\n00:12:12,640 --> 00:12:15,264\n递归地剥离X\nrecursively chops down x\n\n211\n00:12:15,664 --> 00:12:17,824\n如果X中的首元素较小的话\nif the first thing in x is smaller.\n\n212\n00:12:19,980 --> 00:12:22,544\n如果要显式地指出其中的逻辑的话\nAnd if you want to be very explicit about what the logic is there,\n\n213\n00:12:23,450 --> 00:12:26,496\n它其实就是演绎推理\nwhat's really going on is a deduction,\n\n214\n00:12:26,720 --> 00:12:32,384\n其中 如果知道表CDR-X和表Y\nwhich says, if you know that some list, that we'll call cdr of x, and y\n\n215\n00:12:33,290 --> 00:12:35,440\n能够通过MERGE-TO-FORM形成Z\nmerged to form z,\n\n216\n00:12:37,840 --> 00:12:41,520\n并且还知道A比Y中的第一个元素小\nAnd you know that a is less than the first thing in y.\n\n217\n00:12:43,600 --> 00:12:48,520\n那么你就知道 如果你把A和CDR-X给CONS起来\nthen you know that if you put a onto the cdr of x.\n\n218\n00:12:49,740 --> 00:12:51,850\n得到的结果和Y一起\nand that result and y\n\n219\n00:12:52,608 --> 00:12:54,992\n可以通过MERGE-TO-FORM形成Z\nmerge-to-form a onto z.\n\n220\n00:12:55,820 --> 00:12:58,096\n这就是它所基于的逻辑\nAnd what that is, that's the underlying piece of logic--\n\n221\n00:12:58,720 --> 00:12:59,952\n我没有把它写成程序\nI haven't written it as a program,\n\n222\n00:12:59,968 --> 00:13:02,000\n我把它写成了某种演绎\nI wrote it a sort of deduction\n\n223\n00:13:02,032 --> 00:13:04,896\n正是属于这个特定子句的\nthat sits underneath this particular clause\n\n224\n00:13:05,216 --> 00:13:07,264\n它告诉我们可以在这里使用递归\nthat says we can use the recursion there.\n\n225\n00:13:09,410 --> 00:13:12,784\n同样地 这里还有些句子来补全其中的逻辑\nAnd then similar, here's the other clause just to complete it.\n\n226\n00:13:14,000 --> 00:13:15,872\n其它的句子都是基于这些逻辑\nThe other clause is based on this piece of logic,\n\n227\n00:13:15,920 --> 00:13:18,352\n由于它们大部分是相同的 我就不细讲了\nwhich is almost the same and I won't go through it,\n\n228\n00:13:19,008 --> 00:13:20,352\n然后就是终止条件\nand then there's the end cases\n\n229\n00:13:20,416 --> 00:13:22,016\n是用来检查NULL的\nwhere we tested for null,\n\n230\n00:13:22,032 --> 00:13:24,048\n其基本想法是 对于任意的X\nand that's based on the idea that for any x,\n\n231\n00:13:24,510 --> 00:13:27,200\nX和空表可以通过MERGE-TO-FORM形成X\nx and the empty list merge to form an x,\n\n232\n00:13:28,048 --> 00:13:30,864\n而空表可以和任意的Y通过MERGE-TO-FORM形成Y\nor for any y, the empty list and y merge to form y.\n\n233\n00:13:33,360 --> 00:13:38,128\n这就是一段过程的代码\nOK, so there's a piece of procedure\n\n234\n00:13:38,432 --> 00:13:40,112\n以及它所基于的逻辑\nand the logic on which it's based.\n\n235\n00:13:41,740 --> 00:13:42,976\n请注意其中的巨大差异\nAnd notice a big difference.\n\n236\n00:13:45,104 --> 00:13:50,528\n过程看起来是像这样的：\nThe procedure looked like this:\n\n237\n00:13:50,656 --> 00:13:52,288\n首先这有一个盒子\nit said there was a box--\n\n238\n00:13:52,860 --> 00:13:55,392\n我们到目前为止所做的事都有这样的特征\nand all the things we've been doing have the characteristic\n\n239\n00:13:55,408 --> 00:13:57,690\n我们有一个盒子 有东西进去 也有东西出来\nwe have boxes and things going in and things going out--\n\n240\n00:13:58,080 --> 00:13:59,610\n这儿有个MERGE盒子\nthere was this box called merge,\n\n241\n00:14:01,296 --> 00:14:03,856\n输入是X和Y\nand in came an x and y,\n\n242\n00:14:04,448 --> 00:14:05,376\n输出ANS\nand out came an answer.\n\n243\n00:14:07,632 --> 00:14:09,488\n这是我们所编写的程序的特征\nThat's the character of the procedure that we wrote.\n\n244\n00:14:13,024 --> 00:14:14,660\n但是规则并不像这样\nThese rules don't look like that.\n\n245\n00:14:14,660 --> 00:14:16,768\n规则讨论的是关系\nThese rules talk about a relation.\n\n246\n00:14:17,920 --> 00:14:24,160\n也就是在幻灯片中我称作MERGE-TO-FORM的关系\nThere's some sort of relation that in those slides I called mrege-to-form.\n\n247\n00:14:25,370 --> 00:14:28,768\n每当我说X和Y通过MERGE-TO-FORM形成Z\nSo I said x and y merge to form z,\n\n248\n00:14:29,008 --> 00:14:32,336\n这个是一个函数\nand somehow this is not -- this is a function.\n\n249\n00:14:32,610 --> 00:14:32,850\n对吧？\nRight?\n\n250\n00:14:32,850 --> 00:14:34,416\nANS是X和Y的函数\nThe answer is a function of x and y,\n\n251\n00:14:34,592 --> 00:14:38,192\n而我这里得到的是三个东西之间的关系\nand here what I have is a relation between three things.\n\n252\n00:14:39,720 --> 00:14:41,328\n我不会指明\nAnd I'm not going to specify\n\n253\n00:14:42,096 --> 00:14:43,770\n哪个是输入 哪个是输出\nwhich is the input and which is the output.\n\n254\n00:14:44,200 --> 00:14:47,408\n我之所以这么说 是因为原理上\nAnd the reason I want to say that is because in principle,\n\n255\n00:14:48,640 --> 00:14:50,832\n我们可以用同样的逻辑规则\nwe could use exactly those same logic rules\n\n256\n00:14:50,848 --> 00:14:52,448\n来回答相当多的问题\nanswer a lot of different questions.\n\n257\n00:14:54,570 --> 00:14:56,304\n比如 我们可以问\nSo we can say, for instance-- giving\n\n258\n00:14:56,720 --> 00:14:59,050\n想象一下 如果把这些逻辑规则输入机器\nimagine giving our machine those rules of logic.\n\n259\n00:14:59,050 --> 00:15:01,200\n不是输入程序 而是其中依赖的逻辑\nNot the program, the underlying rules of logic.\n\n260\n00:15:01,400 --> 00:15:03,120\n那么 它也就应该回答--\nThen it ought to be able to say--\n\n261\n00:15:04,752 --> 00:15:05,520\n我们可以问它\nwe could ask it--\n\n262\n00:15:06,736 --> 00:15:19,184\n(1 3 7)和(2 4 8)可以通过MERGE-TO-FORM形成什么？\n1, 3, 7 and 2, 4, 8 merge to form what?\n\n263\n00:15:20,910 --> 00:15:23,424\n机器能够回答这样的问题\nAnd that's a question it ought to be able to answer.\n\n264\n00:15:23,880 --> 00:15:27,360\n这同样也是我们的Lisp程序所回答的问题\nThat's exactly the same question that our Lisp procedure answered.\n\n265\n00:15:28,180 --> 00:15:30,144\n但这同样的规则\nBut the exact same rules\n\n266\n00:15:30,896 --> 00:15:34,800\n也能够回答像这样的问题：\nshould also be able to answer a question like this:\n\n267\n00:15:36,192 --> 00:15:43,248\n(1 3 7)和什么能够通过MERGE-TO-FORM形成(1 2 3 4 7 8)\n1, 3, 7 and what merged to form 1, 2, 3, 4, 7, 8?\n\n268\n00:15:45,560 --> 00:15:47,808\n同样的逻辑规则也能够回答这个\nThe same rules of logic can answer this,\n\n269\n00:15:47,840 --> 00:15:49,904\n但我们编写的过程却无法回答这个问题\nalthough the procedure we wrote can't answer that question.\n\n270\n00:15:50,800 --> 00:15:52,336\n又或者 我们可以问\nOr we might be able to say what\n\n271\n00:15:53,710 --> 00:16:01,120\n什么和什么能通过MERGE-TO-FORM\nwhat and what else merge to form--\n\n272\n00:16:04,288 --> 00:16:12,688\n哪两个东西可以通过MERGE-TO-FORM形成(1 2 3 4 7 8)？\nwhat and what else merge to form 1, 2, 3, 4, 7, 8?\n\n273\n00:16:13,780 --> 00:16:15,344\n机器能够进行遍历\nAnd the thing should be able to go through,\n\n274\n00:16:15,840 --> 00:16:17,312\n如果它能应用这些逻辑规则的话\nif it really can apply that logic,\n\n275\n00:16:17,792 --> 00:16:22,540\n就能够推断出这个问题所有的2^6种答案\nand deduce all, whatever is, 2 to the sixth answers to that question.\n\n276\n00:16:25,600 --> 00:16:27,690\n因为可以分别是 (1)和其余的\nCause it could be 1 and the rester, or it could be 1, 2 and the rest.\n\n277\n00:16:27,696 --> 00:16:28,752\n也可以是 (1 2)和其余的\nor it could be 1, 2 and the rester.\n\n278\n00:16:28,790 --> 00:16:31,536\n也可以是(1 3 7)和其余的\nOr it could be 1 and 3 and 7 and the rest.\n\n279\n00:16:32,016 --> 00:16:33,264\n有一大堆的答案\nThere's a whole bunch of answers.\n\n280\n00:16:33,410 --> 00:16:37,760\n但原理上来说 逻辑能推断出所有的答案\nAnd in principle, the logic should be enough to deduce that.\n\n281\n00:16:38,550 --> 00:16:42,032\n因此这里面就有两个巨大的不同\nSo there are going to be two big differences\n\n282\n00:16:44,048 --> 00:16:46,000\n在我们所编写的程序中\nin the kind of program we're going to look at\n\n283\n00:16:46,540 --> 00:16:48,192\n不只是Lisp程序\nand not only Lisp,\n\n284\n00:16:48,208 --> 00:16:50,560\n基本上是你们目前编写过的所有程序\nbut essentially all the programming you've probably done so far\n\n285\n00:16:52,032 --> 00:16:53,600\n用你能叫出名字的程序语言所编写的程序\nin pretty much any language you can think of.\n\n286\n00:16:54,150 --> 00:16:57,792\n首先 我们并不准备计算一个函数\nThe first is, we're not going to be computing functions.\n\n287\n00:17:00,620 --> 00:17:02,016\n我们将要讨论的东西\nWe're not going to be talking about\n\n288\n00:17:02,624 --> 00:17:04,410\n并不具有输入和输出\nabout things that take input and output.\n\n289\n00:17:04,410 --> 00:17:05,824\n我们讨论的是关系\nWe're going to be talking about relations.\n\n290\n00:17:06,890 --> 00:17:10,000\n也就是说 原理上 关系是没有方向性的\nAnd that means in principle, these relations don't have directionality.\n\n291\n00:17:11,080 --> 00:17:15,056\n所以你指明用来回答这个问题的知识\nSo the knowledge that you specify to answer this question,\n\n292\n00:17:16,460 --> 00:17:18,416\n也同样应该能够反过来\nshould be same, that same knowledge\n\n293\n00:17:18,432 --> 00:17:21,800\n让你回答其它的这些问题\nalso allow you to answer these other questions and conversely.\n\n294\n00:17:26,608 --> 00:17:29,408\n其次则是\nAnd the second issue is that\n\n295\n00:17:29,616 --> 00:17:31,232\n因为我们讨论的是关系\nsince we're talking about relations,\n\n296\n00:17:32,320 --> 00:17:34,448\n关系的答案并不唯一\nthese relations don't necessarily have one answer.\n\n297\n00:17:35,610 --> 00:17:37,008\n所以在第三个问题中\nSo that third question down there\n\n298\n00:17:37,020 --> 00:17:38,360\n并没有特定的答案\ndoesn't have a particular answer,\n\n299\n00:17:38,400 --> 00:17:39,584\n它有很多的答案\nit has a whole bunch of answers.\n\n300\n00:17:42,270 --> 00:17:44,640\n这就是我们的目标\nWell, that's where we're going.\n\n301\n00:17:44,640 --> 00:17:45,904\n顺便说一下\nThis style of programming,\n\n302\n00:17:46,720 --> 00:17:49,216\n这种程序设计风格被称作逻辑式程序设计\nby the way, is called logic programming,\n\n303\n00:17:50,224 --> 00:17:51,584\n原因是显而易见的\nfor kind of obvious reasons.\n\n304\n00:17:56,160 --> 00:18:00,384\n用逻辑式进行程序设计的那群人之间\nAnd people who do logic programming say that --\n\n305\n00:18:00,400 --> 00:18:03,150\n流传着几句箴言\nthey have this little phrase--\n\n306\n00:18:03,168 --> 00:18:04,672\n他们把逻辑式程序设计的要点归纳为\nthey say the point of logic programming\n\n307\n00:18:04,768 --> 00:18:09,008\n用逻辑来表达 什么算是“真的”\nis that you use logic to express what is true,\n\n308\n00:18:10,096 --> 00:18:13,888\n用逻辑来检测 是否是“真的”\nyou use logic to check whether something is true,\n\n309\n00:18:14,672 --> 00:18:17,248\n用逻辑来找出这些“真的”\nand you use logic to find out what is true.\n\n310\n00:18:19,200 --> 00:18:22,096\n最为大家所熟知的逻辑式程序设计语言\nThe best known logic programming language,\n\n311\n00:18:22,976 --> 00:18:24,784\n你们可能也听过 -- 叫做Prolog\nas you probably know, is called Prolog.\n\n312\n00:18:25,780 --> 00:18:28,880\n今天早上我们将要实现的这门语言\nThe language that we're going to implement this morning\n\n313\n00:18:29,824 --> 00:18:32,320\n是一种查询语言\nis something we call the query language,\n\n314\n00:18:32,480 --> 00:18:34,416\n它基本上就是Prolog的本质了\nand it essentially has the essence of prolog.\n\n315\n00:18:35,320 --> 00:18:36,736\n它可以完成相同的工作\nIt can do about the same stuff,\n\n316\n00:18:37,290 --> 00:18:38,736\n虽然它比Prolog慢得多\nalthough it's a lot slower\n\n317\n00:18:38,736 --> 00:18:40,010\n这是因为我们是通过Lisp来解释的\nbecause we're going to implement it in LISP\n\n318\n00:18:41,904 --> 00:18:44,368\n而非构造一个专门的编译器\nrather than building a particular compiler.\n\n319\n00:18:44,464 --> 00:18:46,624\n对它的解释 将运行在Lisp解释器之上\nWe're going to interpret it on top of the LISP interpreter.\n\n320\n00:18:47,510 --> 00:18:49,840\n除此之外 它可以完成与Prolog相同的事儿\nBut other than that, it can do about the same stuff as prolog.\n\n321\n00:18:49,888 --> 00:18:52,784\n不但同样的能力 也有同样的局限\nIt has about the same power and about the same limitations.\n\n322\n00:18:55,088 --> 00:18:56,176\n好吧 先解答一下疑惑\nAll right, let's break for question.\n\n323\n00:19:00,430 --> 00:19:02,848\n学生：您能再重复一下\nAUDIENCE: Yes, could you please repeat what the three\n\n324\n00:19:03,488 --> 00:19:06,090\n用逻辑去寻找的三件事么？\nthings you use logic programming to find?\n\n325\n00:19:06,720 --> 00:19:09,840\n就是那些 找出什么为真 知道什么是真 等等\nIn other words, to find what is true, learn what is true-- what is the?\n\n326\n00:19:09,840 --> 00:19:10,520\n教授：好的\nPROFESSOR: Right.\n\n327\n00:19:10,560 --> 00:19:15,744\n这算是程序员的某种“教义问答”\nSort of a logic programmer's little catechism.\n\n328\n00:19:15,850 --> 00:19:19,160\n我们用逻辑来表达怎么算是“真的”\nYou use logic to express what is true,\n\n329\n00:19:20,800 --> 00:19:21,792\n就像这些规则一样\nlike these rules.\n\n330\n00:19:22,610 --> 00:19:25,568\n我们用逻辑来检测某事是否是“真的”\nYou use logic to check whether something is true,\n\n331\n00:19:25,600 --> 00:19:27,760\n但在这里我没有回答这个问题\nand that's the kind of question I didn't answer here.\n\n332\n00:19:28,550 --> 00:19:29,296\n我可以问\nI might say--\n\n333\n00:19:29,680 --> 00:19:32,144\n在这里我可以这样来问\nanother question I could put down here is to say,\n\n334\n00:19:33,264 --> 00:19:36,560\n(1 3 7)和(2 4 8)是否能够\nis it true that 1, 3, 7 and 2, 4, 8\n\n335\n00:19:36,910 --> 00:19:40,380\n通过MERGE-TO-FORM形成(1 2 6 19)\nmerge to form 1, 2, 6, 10\n\n336\n00:19:41,120 --> 00:19:44,688\n同样的逻辑规则会告诉我们不行\nAnd that same logic should be enough to say no.\n\n337\n00:19:45,690 --> 00:19:47,936\n这里 我使用逻辑来检测是否为真\nSo I use logic to check what is true,\n\n338\n00:19:48,288 --> 00:19:50,480\n然后 我们也可以使用逻辑来找出为真的东西\nand then you also use logic to find out what's true.\n\n339\n00:20:04,464 --> 00:20:05,168\n休息一下吧\nLet's break.\n\n340\n00:20:06,130 --> 00:20:17,024\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n341\n00:20:17,050 --> 00:20:20,688\n《计算机程序的构造和解释》\n\n342\n00:20:47,590 --> 00:20:51,024\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n343\n00:20:51,070 --> 00:20:55,600\n《计算机程序的构造和解释》\n\n344\n00:20:55,630 --> 00:21:00,688\n逻辑式程序设计\n\n345\n00:21:03,248 --> 00:21:04,976\n教授：让我们继续来看一看\nPROFESSOR: OK, let's go ahead and\n\n346\n00:21:05,840 --> 00:21:08,448\n这个查询语言及其操作\ntake a look at this query language and operation.\n\n347\n00:21:10,520 --> 00:21:11,840\n首先需要注意到\nThe first thing you might notice,\n\n348\n00:21:12,240 --> 00:21:14,144\n当我建立好那个小型的圣经数据库后\nwhen I put up that little biblical database,\n\n349\n00:21:14,160 --> 00:21:17,240\n我们就能够针对一系列的事实\nis that it's nice to be able to ask this language questions\n\n350\n00:21:17,488 --> 00:21:19,920\n以关系的方式来向这个语言提问\nin relation to some collection of facts.\n\n351\n00:21:21,330 --> 00:21:25,152\n因此 我们先来陈述一些事实\nSo let's start off and make a little collection of facts.\n\n352\n00:21:26,060 --> 00:21:29,680\n这是波士顿一家高科技公司的\nThis is a tiny fragment of personnel records\n\n353\n00:21:30,080 --> 00:21:32,624\n一小部分人事档案\nfor a Boston high tech company,\n\n354\n00:21:33,056 --> 00:21:36,800\n这部分档案是Ben Bitdiddle的\nand here's a piece of the personnel records of Ben Bitdiddle.\n\n355\n00:21:37,500 --> 00:21:41,952\nBitdiddle是这家公司的计算机向导\nAnd Ben Bitdiddle is the computer wizard in this company,\n\n356\n00:21:42,848 --> 00:21:45,808\n他是这家公司的低薪向导\nhe's the underpaid computer wizard in this company.\n\n357\n00:21:46,420 --> 00:21:48,784\n他的上司是Oliver Warbucks\nHis supervisor is all Oliver Warbucks,\n\n358\n00:21:49,280 --> 00:21:50,704\n这里是他的住址\nand here's his address.\n\n359\n00:21:52,150 --> 00:21:56,544\n我们按照这样的格式给出信息：职务、薪水、上司、住址\nSo the format is we're giving this information: job, salary, supervisor, address.\n\n360\n00:21:57,568 --> 00:21:59,250\n还有一些其它的约定\nAnd there are some other conventions.\n\n361\n00:21:59,250 --> 00:22:02,224\n这里的COMPUTER表示BEN在计算机分部工作\nComputer here means that Ben works in the computer division, and\n\n362\n00:22:02,768 --> 00:22:04,944\n而他在这个分部的工作是向导\nhis position in the computer division is wizard.\n\n363\n00:22:05,660 --> 00:22:07,152\n这里是其他人的\nHere's somebody else.\n\n364\n00:22:07,168 --> 00:22:12,280\nALyssa P.Hacker是一名计算机程序员\nAlyssa, Alyssa P. Hacker is a computer programmer,\n\n365\n00:22:13,360 --> 00:22:14,608\n她的上司是Ben\nand she works for Ben,\n\n366\n00:22:15,216 --> 00:22:16,544\n而她住在Cambridge\nand she lives in Cambridge.\n\n367\n00:22:17,550 --> 00:22:19,424\nBen手下的另外一个程序员\nAnd there's another programmer who works for Ben\n\n368\n00:22:20,032 --> 00:22:21,440\n叫做Lem E. Tweakit\nwho's Lem E. Tweakit.\n\n369\n00:22:22,820 --> 00:22:26,736\n实习程序员 Louis Reasoner\nAnd there's a programmer trainee, who is Louis Reasoner,\n\n370\n00:22:27,424 --> 00:22:28,624\n在Alyssa手下工作\nand he works for Alyssa.\n\n371\n00:22:30,100 --> 00:22:35,456\n公司里的“大老板”不为任何人工作\nAnd the big wheel of the company doesn't work for anybody.\n\n372\n00:22:36,816 --> 00:22:38,110\n这就是Oliver Warbucks的档案了\nRight, That's Oliver Warbucks.\n\n373\n00:22:38,110 --> 00:22:39,312\n我们将要做的就是\nAnyway, what we're going to do is\n\n374\n00:22:40,944 --> 00:22:43,664\n对这个小型的世界提问\nis ask questions about that little world.\n\n375\n00:22:44,970 --> 00:22:48,400\n这将是我们进行逻辑运算的样本世界\nAnd that'll be a sample world that we're going to do logic in.\n\n376\n00:22:51,420 --> 00:22:54,960\n我再最后一次强调一下\nLet me just write up here, for probably the last time,\n\n377\n00:22:55,600 --> 00:22:58,208\n你们应该从这门课中学到的最重要的知识\nwhat I said is the very most important thing you should get out of this course,\n\n378\n00:22:58,800 --> 00:23:01,664\n也就是 当别人向你介绍语言时\nand that is, when somebody tells you about a language,\n\n379\n00:23:02,256 --> 00:23:04,432\n你要问：“它的基本元素是什么？”\nyou say, fine-- what are the primitives,\n\n380\n00:23:06,120 --> 00:23:07,790\n组合的手段有哪些？\nwhat are the means of combination,\n\n381\n00:23:14,704 --> 00:23:16,400\n如何把基本元素组织在一起\nhow do you put the primitives together,\n\n382\n00:23:16,672 --> 00:23:19,376\n然后把它们抽象出来？\nand then how do you abstract them,\n\n383\n00:23:19,968 --> 00:23:21,936\n如何抽象这些复合元素\nhow do you abstract the compound pieces\n\n384\n00:23:24,688 --> 00:23:27,584\n以便于你能够复用它们构造更复杂的东西？\nso you can use them as pieces to make something more complicated?\n\n385\n00:23:29,024 --> 00:23:30,816\n我已经强调过很多次了\nAnd we've said this a whole bunch of times already,\n\n386\n00:23:31,168 --> 00:23:32,480\n但还是值得重申一遍\nbut it's worth saying again.\n\n387\n00:23:35,008 --> 00:23:36,670\n记住了么？我们开始了\nOKay? Let's start.\n\n388\n00:23:36,670 --> 00:23:37,344\n首先是基本元素\nThe primitives.\n\n389\n00:23:37,776 --> 00:23:39,440\n这其中 只有唯一的基本元素\nWell, there's really only one primitive,\n\n390\n00:23:40,960 --> 00:23:43,200\n这门语言中的基本元素就是“查询”\nand the primitive in this language is called a query.\n\n391\n00:23:44,144 --> 00:23:45,744\n一条基本查询\nA primitive query.\n\n392\n00:23:46,810 --> 00:23:48,256\n我们先来看几条基本查询\nLet's look at some primitive queries.\n\n393\n00:23:51,824 --> 00:23:53,024\n首先 这条查询问的是\nAlright. Job x.\n\n394\n00:23:53,100 --> 00:23:54,816\n“谁是计算机程序员？”\nWho is a computer programmer?\n\n395\n00:23:55,550 --> 00:23:59,888\n或者可以解释为：找出数据库中\nOr find every fact in the database\n\n396\n00:24:01,552 --> 00:24:06,144\n所有JOB栏为COMPUTER PROGRAMMER的事实\nthat matches job of the x is computer programmer.\n\n397\n00:24:06,640 --> 00:24:08,016\n这里有一些小语法\nAnd you see a little syntax here.\n\n398\n00:24:08,470 --> 00:24:10,592\n不带问号的都是字面量\nThings without question marks are meant to be literal,\n\n399\n00:24:11,280 --> 00:24:13,152\n?X表示X是变量\nquestion mark x means that's a variable,\n\n400\n00:24:13,312 --> 00:24:15,568\n而这条查询会匹配 比如说 --\nand this thing will match, for example,\n\n401\n00:24:16,032 --> 00:24:19,008\nAlyssa P. Hacker 是程序员\nthe fact that Alyssa P. Hacker is a computer programmer,\n\n402\n00:24:19,280 --> 00:24:21,930\n其中X为Alyssa P. Hacker这条事实\nor x is Alyssa P. Hacker.\n\n403\n00:24:26,820 --> 00:24:29,984\n或者更一般地 我可以在一条查询中引入两个变量\nOr more generally, I could have something with two variables in it.\n\n404\n00:24:30,750 --> 00:24:31,456\n我可以问\nI could say,\n\n405\n00:24:31,600 --> 00:24:35,888\n?X的JOB必须是COMPUTER ?TYPE\nthe job of x is computer something,\n\n406\n00:24:39,344 --> 00:24:41,392\n也就是会匹配COMPUTER WIZARD\nand that'll match computer wizard.\n\n407\n00:24:42,140 --> 00:24:44,288\n所以这里?TYPE可能会匹配WIZARD\nSo there's something here: type will match wizard,\n\n408\n00:24:44,928 --> 00:24:46,464\n也可能会匹配PROGRAMMER\nor type will match programmer,\n\n409\n00:24:47,488 --> 00:24:50,370\n而?X会匹配不同的东西\nor x might match various certain things.\n\n410\n00:24:50,370 --> 00:24:52,240\n但在我们的这个小例子中\nSo there are, in our little example,\n\n411\n00:24:52,256 --> 00:24:55,150\n数据库中只有三条事实符合那条查询\nonly three facts in that database that match that query.\n\n412\n00:24:59,120 --> 00:25:02,080\n把语法说得再清楚一点 同样的查询\nLet's see, just to show you some syntax, the same query,\n\n413\n00:25:05,296 --> 00:25:08,096\n同样的这条指定了?X的JOB的查询\nthis query doesn't match the job of x,\n\n414\n00:25:09,856 --> 00:25:11,792\n并不能够与Lewis Reasoner匹配\ndoesn't match Lewis Reasoner,\n\n415\n00:25:11,840 --> 00:25:13,648\n这是因为我这里所写的\nthe reason for that is when I write something here,\n\n416\n00:25:14,224 --> 00:25:17,744\n表示要匹配的是由两个符号构成的表\nwhat I mean is that this is going to be a list of two symbols,\n\n417\n00:25:19,968 --> 00:25:21,968\n其中首元素必须为单词“COMPUTER”\nof which the first is the word computer,\n\n418\n00:25:22,320 --> 00:25:23,808\n而第二个可以匹配任意的东西\nand the second can be anything.\n\n419\n00:25:25,080 --> 00:25:27,320\n而Lewis这里的工作描述有三个符号\nAnd Lewis's job description here has three symbols,\n\n420\n00:25:27,808 --> 00:25:28,832\n因此不匹配\nso it doesn't match.\n\n421\n00:25:30,340 --> 00:25:32,192\n你们还需要知道的一种语法是\nAnd just to show you a little bit of syntax,\n\n422\n00:25:35,040 --> 00:25:38,320\n更具一般性的点记号\nthe more general thing I might want to type is a thing with a dot here,\n\n423\n00:25:40,176 --> 00:25:42,928\n这个标准的表记号表示的是\nand this is just standard list notation for saying,\n\n424\n00:25:43,040 --> 00:25:43,824\n首先这是一个表\nthis is a list,\n\n425\n00:25:44,128 --> 00:25:47,320\n它的首元素为单词“COMPUTER”\nof which the first element is the word computers,\n\n426\n00:25:47,584 --> 00:25:50,224\n而其余的部分 我们把它们称作?TYPE\nand THE REST, is something that I'll call type.\n\n427\n00:25:53,730 --> 00:25:55,504\n因此这条查询就会匹配上\nSo this one would match.\n\n428\n00:25:56,930 --> 00:25:59,312\nLewis的工作是COMPUTER PROGRAMMER TRAINEE\nLewis's job is computer programmer trainee,\n\n429\n00:25:59,440 --> 00:26:03,296\n而?TYPE的值将会是这个表的CDR部分\nand type here would be the cdr of this list.\n\n430\n00:26:03,328 --> 00:26:05,648\n也就是表(PROGRAMMER TRAINEE)\nIt would be the list programmer trainee.\n\n431\n00:26:06,960 --> 00:26:10,460\nLisp源码读取器会自动完成对点记号的处理\nAnd that kind of dot processing is done automatically by the LISP reader.\n\n432\n00:26:15,900 --> 00:26:17,760\n让我们来实际操作一下\nWell, let's actually try this.\n\n433\n00:26:17,760 --> 00:26:20,512\n我将向语言系统输入这些查询\nThe idea is I'm going to type in queries in this language,\n\n434\n00:26:20,768 --> 00:26:21,824\n然后得到结果\nand answers will come out.\n\n435\n00:26:22,544 --> 00:26:24,480\n让我们在计算机中试试\nLet's look at this.\n\n436\n00:26:25,180 --> 00:26:26,512\n我可以问\nI can go up and say,\n\n437\n00:26:27,344 --> 00:26:28,880\n谁在计算机分部工作？\nwho works in the computer division?\n\n438\n00:26:30,000 --> 00:26:38,224\n(JOB ?X (COMPUTER . ?Y)\nJob of x is computer dot y.\n\n439\n00:26:39,730 --> 00:26:41,488\n哑变量的名字并不重要\nDoesn't matter what I call the dummy variables.\n\n440\n00:26:42,768 --> 00:26:44,144\n查询的结果是\nIt says the answers to that,\n\n441\n00:26:44,416 --> 00:26:45,680\n有四条记录\nand it's found four answers.\n\n442\n00:26:48,650 --> 00:26:50,096\n我也可以问\nOr I can go off and say,\n\n443\n00:26:50,560 --> 00:26:52,384\n大家的上司都是谁？\ntell me about everybody's supervisor.\n\n444\n00:26:52,816 --> 00:26:54,880\n我输入一条基本查询\nSo I'll put in the query, the primitive query,\n\n445\n00:26:56,528 --> 00:26:59,390\n(SUPERVISOR ?X ?Y)\nthe supervisor of x is y.\n\n446\n00:27:02,560 --> 00:27:05,424\n这些都是我所知道的上下级关系\nThere are all the supervisor relationships I know.\n\n447\n00:27:05,540 --> 00:27:08,830\n或者我也可以问：“谁住在Cambridge？”\nOr I could go type in, who lives in Cambridge?\n\n448\n00:27:08,830 --> 00:27:09,472\n我就这么输入：\nSo I can say,\n\n449\n00:27:10,240 --> 00:27:20,928\n(ADDRESS ?X (CAMBRIDGE . ?T))\nthe address of x is Cambridge dot anything.\n\n450\n00:27:25,090 --> 00:27:26,896\n只有一个人住在Cambridge\nAnd only one person lives in Cambridge.\n\n451\n00:27:30,820 --> 00:27:32,170\n这些就是基本查询\nOK, so those are primitive queries.\n\n452\n00:27:32,170 --> 00:27:34,960\n你们看到的这些 就是与系统的基础交互\nAnd you see what happens to basic interaction with the system\n\n453\n00:27:35,296 --> 00:27:39,248\n你输入一条查询 他输出所有可能的查询\nis you type in a query, and it types out all possible answers.\n\n454\n00:27:39,620 --> 00:27:40,656\n换句话说 也就是\nOr another way to say that:\n\n455\n00:27:40,670 --> 00:27:44,160\n它找出这些变量所有可能的值\nit finds out all the possible values of those variables\n\n456\n00:27:44,192 --> 00:27:45,872\n不管它是叫X、Y还是T\nx and y or t or whatever I've called them,\n\n457\n00:27:46,096 --> 00:27:52,080\n然后它输出的是用所有可行值实例化该条查询的结果\nand it types out all ways of taking that query and instantiating it--\n\n458\n00:27:52,920 --> 00:27:55,168\n也就是规则系统那一课讲的“实例化”\nremember that from the rule system lecture--\n\n459\n00:27:55,168 --> 00:27:58,830\n用变量所有可能的值来实例化查询\ninstantiates the query with all possible values for those variables\n\n460\n00:27:59,008 --> 00:28:00,352\n然后输出所有的结果\nand then types out all of them.\n\n461\n00:28:01,000 --> 00:28:03,350\n当然 还有不同的呈现结果的方式\nAnd there are a lot of ways you can arrange a logic language.\n\n462\n00:28:03,350 --> 00:28:06,010\n比如说 Prolog就有些不一样\nProlog, for instance, does something slightly different.\n\n463\n00:28:06,010 --> 00:28:07,440\n它并不向你返回查询\nRather than typing back your query,\n\n464\n00:28:07,760 --> 00:28:10,784\nProlog会输出X=这个 Y=那个\nprolog would type out, x equals this and y equals that,\n\n465\n00:28:10,976 --> 00:28:12,944\n又或者X=这个 Y=那个\nor x equals this and y equals that.\n\n466\n00:28:13,660 --> 00:28:15,488\n这是使用界面层次的差别\nAnd that's a very surface level thing,\n\n467\n00:28:15,712 --> 00:28:17,050\n你可以根据你的喜好来决定\nyou can decide what you like.\n\n468\n00:28:18,976 --> 00:28:19,584\n我们继续\nOK.\n\n469\n00:28:21,008 --> 00:28:22,688\n也就是说 这个语言中的基本元素\nAlright. So the primitives in this language?\n\n470\n00:28:23,390 --> 00:28:24,570\n只有一个 对吧？\nOnly one, right?\n\n471\n00:28:24,570 --> 00:28:27,230\n也就是基本查询\nPrimitive query.\n\n472\n00:28:31,312 --> 00:28:32,560\n来看看组合的手段\nMeans of combination.\n\n473\n00:28:34,330 --> 00:28:37,680\n我们来考察一下这个语言中的复合查询\nLet's look at some compound queries in this language.\n\n474\n00:28:39,770 --> 00:28:40,464\n比如这条\nHere's one.\n\n475\n00:28:41,790 --> 00:28:42,512\n这条查询是说\nThis one says,\n\n476\n00:28:45,056 --> 00:28:48,224\n列举出所有在计算机分部工作的人\ntell me all the people who work in the computer division.\n\n477\n00:28:49,810 --> 00:28:52,000\n在计算机分部工作的人\nTell me all the people who work in the computer division\n\n478\n00:28:52,544 --> 00:28:53,960\n以及他们的上司\ntogether with their supervisors.\n\n479\n00:28:56,800 --> 00:28:58,832\n我使用AND来编写这条查询\nWhere I write that is the query is and.\n\n480\n00:29:00,220 --> 00:29:04,064\n(AND (JOB ?X (COMPUTER . ?Y))\nAnd the job of the x is computer something or other.\n\n481\n00:29:04,920 --> 00:29:06,832\n(JOB ?X (COMPUTER . ?Y))\nAnd job of x is computer dot y.\n\n482\n00:29:07,560 --> 00:29:10,032\n并且(SUPERVISOR ?X ?Z)\nAnd the supervisor of x is z.\n\n483\n00:29:11,440 --> 00:29:14,160\n找出所有在计算机分部工作的人 -- 对应这条\nTell me all the people in the computer division-- that's this--\n\n484\n00:29:14,304 --> 00:29:15,888\n以及它们的上司\ntogether with their supervisors.\n\n485\n00:29:16,460 --> 00:29:17,824\n注意这条查询中\nAnd notice in this query\n\n486\n00:29:18,672 --> 00:29:22,416\n我引入了三个变量 ?X ?Y 以及 ?Z\nI have three variables-- x, y, and z.\n\n487\n00:29:23,584 --> 00:29:28,656\n并且 这两个?X应该匹配同样的东西\nAnd this x is supposed to be the same as that x.\n\n488\n00:29:29,450 --> 00:29:31,168\n?X被约束在了计算机分部中\nSo x works in the computer division,\n\n489\n00:29:31,312 --> 00:29:33,008\n并且?X的上司是?Z\nand the supervisor of x is z.\n\n490\n00:29:34,810 --> 00:29:35,808\n我们再来看一条\nLet's try another one.\n\n491\n00:29:37,250 --> 00:29:39,280\nAND算是一种组合手段\nSo one means of combination is and.\n\n492\n00:29:41,440 --> 00:29:43,968\n哪些人的薪水超过$30,000？\nWho are all the people who make more than $30,000?\n\n493\n00:29:45,712 --> 00:29:51,712\n(AND (SALARY ?P ?A)\nAnd the salary of some person p is some amount a.\n\n494\n00:29:54,590 --> 00:29:57,456\n而关于?A的要求则是\nAnd when I go and look at a,\n\n495\n00:29:57,488 --> 00:30:00,128\n(LISP-VALUE > ?A 300000)\na is greater than $30,000.\n\n496\n00:30:00,600 --> 00:30:03,232\n这里的LISP-VALUE是一个接口\nAnd LISP value here is a little piece of interface\n\n497\n00:30:04,304 --> 00:30:10,048\n用来连接查询语言与其底层的Lisp\nthat interfaces the query language to the underlying LISP.\n\n498\n00:30:10,600 --> 00:30:12,720\nLISP-VALUE让你能够在查询\nAnd what the LISP value allows you to do\n\n499\n00:30:12,752 --> 00:30:16,912\n中调用任意的Lisp谓词\ncall any LISP predicate inside a query.\n\n500\n00:30:17,180 --> 00:30:20,112\n因为我要用Lisp中的谓词> 所以我用LISP-VALUE\nSo here I'm using the LISP predicate greater than, so I say LISP value.\n\n501\n00:30:21,020 --> 00:30:21,750\n所以这里我用了AND\nThis I say and.\n\n502\n00:30:21,750 --> 00:30:24,480\n因此这样就查询出了薪水超过$30000的人\nSo all the people whose salary is greater than $30,000.\n\n503\n00:30:28,190 --> 00:30:30,032\n或者这条更复杂的查询\nOr here's a more complicated one.\n\n504\n00:30:31,270 --> 00:30:35,024\n告诉我所有那些 在计算机分部中工作\nTell me all the people who work in the computer division\n\n505\n00:30:36,256 --> 00:30:39,360\n但他的上司不在计算机分部工作的人\nwho do not have a supervisor who works in the computer division.\n\n506\n00:30:42,790 --> 00:30:45,510\n(AND (JOB ?X (COMPUTER . ?Y))\nand x works in the computer division.\n\n507\n00:30:45,510 --> 00:30:47,328\n表示?X在计算机分部工作\nThe job of x is computer dot y.\n\n508\n00:30:47,780 --> 00:30:49,248\n但是呢\nAnd it's not the case\n\n509\n00:30:50,496 --> 00:30:54,256\n?X的上司?Z\nthat both x has a supervisor z\n\n510\n00:30:55,376 --> 00:30:57,872\n?Z的JOB不是形如(COMPUTER ...)一类的\nand the job of z is computer something or other.\n\n511\n00:30:59,620 --> 00:31:00,352\n同样的\nAll right, so again,\n\n512\n00:31:00,512 --> 00:31:02,384\n这两个?X应该是一致的\nthis x has got to be that x,\n\n513\n00:31:03,200 --> 00:31:05,760\n而这两个?Z也应该是一致的\nand this z is going to be that z.\n\n514\n00:31:09,390 --> 00:31:11,380\n你又了解了另一种组合手段 -- NOT\nAnd then you see another means a combination, not.\n\n515\n00:31:17,712 --> 00:31:18,672\n好了 再让我们来试试这些\nAll right, well, let's look at that.\n\n516\n00:31:20,880 --> 00:31:22,080\n它同样起效\nIt works the same way.\n\n517\n00:31:22,400 --> 00:31:24,128\n我可以问计算机：\nI can go up to the machine and say\n\n518\n00:31:26,896 --> 00:31:35,400\n(AND (JOB ?X (COMPUTER . ?Y)))\nand the job of the x is computer dot y.\n\n519\n00:31:38,848 --> 00:31:45,952\n另一个条件是(SUPERVISOR ?X ?Z)\nAnd the supervisor of x is z.\n\n520\n00:31:46,832 --> 00:31:49,536\n我把这条查询输入进去\nAnd I typed that in like a query.\n\n521\n00:31:51,072 --> 00:31:52,976\n计算机返回给我们的\nAnd what it types back,\n\n522\n00:31:54,000 --> 00:31:58,736\n计算机利用所有可能的答案把我的查询实例化了\nwhat you see are the queries I typed in instantiated by all possible answers.\n\n523\n00:31:58,930 --> 00:32:00,080\n你会发现有很多的答案\nAnd then you see there are a lot of answers.\n\n524\n00:32:01,696 --> 00:32:02,144\n好\nAll right.\n\n525\n00:32:02,190 --> 00:32:04,048\n之所以把这门语言称作“逻辑语言”\nSo the means of combination in this language--\n\n526\n00:32:05,216 --> 00:32:06,608\n是因为这门语言中的组合手段\nand this is why it's called a logic language--\n\n527\n00:32:06,640 --> 00:32:09,472\n都是逻辑运算\nare logical operations.\n\n528\n00:32:09,800 --> 00:32:15,680\n组合的手段有AND和NOT\nMeans of combinations are things like AND and NOT\n\n529\n00:32:15,968 --> 00:32:17,920\n以及我还没有告诉你的OR\nand there's one I didn't show you, which is OR.\n\n530\n00:32:18,490 --> 00:32:20,368\n我还告诉过你LISP-VALUE\nAnd then I showed you LISP value,\n\n531\n00:32:20,720 --> 00:32:24,480\n当然 虽然它不是一个逻辑运算\nwhich is a, not logic, of course,\n\n532\n00:32:24,512 --> 00:32:26,896\n但是这个特殊的小技巧把它跟Lisp连接在了一起\nbut is a little special hack to interface that to LISP\n\n533\n00:32:27,344 --> 00:32:28,752\n让你获得了更多的力量\nso you can get more power.\n\n534\n00:32:29,250 --> 00:32:30,672\n这些就是组合手段\nThose are the means of combination.\n\n535\n00:32:32,592 --> 00:32:33,984\n好 接着是抽象手段\nOK, the means of abstraction.\n\n536\n00:32:34,160 --> 00:32:35,216\n我们想要的是\nWhat we'd like to do--\n\n537\n00:32:38,272 --> 00:32:41,248\n想让我们回过头来看上一张幻灯片\nlet's go back for second and look at that last slide.\n\n538\n00:32:42,260 --> 00:32:44,256\n我们想要把一些非常复杂的东西\nWe might like to take very complicated thing,\n\n539\n00:32:44,460 --> 00:32:48,000\n比如不与上司在同一部门工作\nthe idea that someone works in a division\n\n540\n00:32:48,016 --> 00:32:50,090\n的人的这种概念\nbut does not have a supervisor in the division.\n\n541\n00:32:52,400 --> 00:32:55,104\n像以前一样 给它命名\nAnd as before, name that.\n\n542\n00:32:56,090 --> 00:32:58,128\n如果在某个分部工作的人\nWell, if someone works in a division\n\n543\n00:32:58,176 --> 00:33:00,250\n他的上司却不在那个分部工作\nand does not have a supervisor who works in that division,\n\n544\n00:33:00,480 --> 00:33:01,936\n这就意味着他是个“大腕”\nthat means that person is a big shot.\n\n545\n00:33:02,750 --> 00:33:05,136\n这样 我们就定义一条规则指明\nSo let's make a rule that\n\n546\n00:33:06,432 --> 00:33:09,168\n如果?X是某个部门的BIGSHOT\nsomebody x is a big shot in some department\n\n547\n00:33:10,912 --> 00:33:14,688\n如果他在该部门工作\nif x works in the department\n\n548\n00:33:16,048 --> 00:33:20,080\n并且他的上司不在该部门工作\nand it's not the case that x has a supervisor who works in the department.\n\n549\n00:33:21,510 --> 00:33:22,940\n因此这就是我们的抽象手段\nSo this is our means of abstraction.\n\n550\n00:33:22,940 --> 00:33:23,904\n这是一条规则\nThis is a rule.\n\n551\n00:33:26,220 --> 00:33:27,580\n规则由三部分构成\nAnd a rule has three parts.\n\n552\n00:33:31,008 --> 00:33:32,480\n关键字RULE表明这是一条规则\nThe thing that says it's a rule.\n\n553\n00:33:33,408 --> 00:33:35,488\n接着是规则的结论\nAnd then there's the conclusion of the rule.\n\n554\n00:33:37,530 --> 00:33:39,072\n然后是规则的体\nAnd then there's the body of the rule.\n\n555\n00:33:40,000 --> 00:33:41,888\n你可以把它解读为这样的一段逻辑：\nAnd you can read this as a piece of logic which says,\n\n556\n00:33:41,920 --> 00:33:45,150\n如果你知道规则的体为真\nif you know that the body of the rule is true,\n\n557\n00:33:46,400 --> 00:33:48,720\n那么你就可以推导出结论为真\nthen you can conclude that the conclusion is true.\n\n558\n00:33:49,456 --> 00:33:53,280\n或者说为了推断出?X是某个部门的“大腕”\nOr in order to deduce that x is a big shot in some department,\n\n559\n00:33:53,792 --> 00:33:55,712\n这些条件足够验证了\nit's enough to verify that.\n\n560\n00:33:57,480 --> 00:33:58,820\n这就是规则的形式\nSo that's what rules look like.\n\n561\n00:34:03,280 --> 00:34:06,160\n让我们回过头来看看\nLet's go back and look at that merge example\n\n562\n00:34:06,736 --> 00:34:07,920\n课间休息前我举的那个例子\nthat I did before the break.\n\n563\n00:34:08,110 --> 00:34:10,688\n我们来看看 如果用规则来描述会是什么样的\nLet's look at how that would look in terms of rules.\n\n564\n00:34:11,440 --> 00:34:12,848\n我会抽取出其中的逻辑\nI'm going to take the logic I put up\n\n565\n00:34:13,088 --> 00:34:15,500\n并将它们变为这种格式的规则\nand just change it into a bunch of rules in this format.\n\n566\n00:34:18,739 --> 00:34:19,350\n就有了下面的规则\nWe have a rule.\n\n567\n00:34:19,350 --> 00:34:20,960\n这就是MERGE-TO-FORM的规则\nRemember, there was this thing merge-to-form.\n\n568\n00:34:21,710 --> 00:34:22,976\n这个规则是说\nThere is a rule that says,\n\n569\n00:34:26,288 --> 00:34:29,620\n'()与?Y可以通过MERGE-TO-FORM形成?Y\nthe empty list and y merge to form y.\n\n570\n00:34:29,620 --> 00:34:30,870\n这是规则的结论\nThis is the rule conclusion.\n\n571\n00:34:33,210 --> 00:34:35,744\n需要注意的是 这个特定的规则没有体\nAnd notice this particular rule has no body.\n\n572\n00:34:36,650 --> 00:34:37,664\n在这门语言中\nAnd in this language,\n\n573\n00:34:38,112 --> 00:34:40,864\n没有体的规则总是真的\na rule with no body is something that is always true.\n\n574\n00:34:41,239 --> 00:34:42,510\n你总是可以假设它们为真\nYou can always assume that's true.\n\n575\n00:34:45,190 --> 00:34:46,496\n另一条规则说的是\nAnd there was another piece of logic\n\n576\n00:34:46,640 --> 00:34:49,460\n任意对象与空表进行MERGE-TO-FORM 得到的任然是原物\nthat said anything in the empty list merged to form the anything.\n\n577\n00:34:49,460 --> 00:34:50,128\n就是这条\nThat's this.\n\n578\n00:34:50,900 --> 00:34:53,552\n(MERGE-TO-FORM ?Y '() ?Y)\nA rule y and the empty list merge to form y.\n\n579\n00:34:55,510 --> 00:34:58,400\n它们对应了我们MERGE过程中的两个终止条件\nThose corresponded to the two end cases in our merge procedure,\n\n580\n00:34:58,448 --> 00:34:59,776\n但我们现在讨论的是逻辑\nbut now we're talking about logic,\n\n581\n00:35:00,416 --> 00:35:01,456\n而非过程\nnot about procedures.\n\n582\n00:35:03,490 --> 00:35:04,480\n我们还有另外一条规则\nThen we had another rule,\n\n583\n00:35:04,832 --> 00:35:08,736\n描述的是 如果你知道如何MERGE较短的表\nwhich said if you know how shorter things merge,\n\n584\n00:35:08,912 --> 00:35:09,830\n那么你就可以把它们结合在一起\nyou can put them together.\n\n585\n00:35:09,830 --> 00:35:14,160\n这条规则说：如果你有表?X、?Y以及?Z\nSo this says, if you have a list x and y and z,\n\n586\n00:35:14,928 --> 00:35:17,616\n如果你想推断出(?A . ?X)\nand if you want to deduce that a dot x--\n\n587\n00:35:17,632 --> 00:35:19,088\n这个记法表示(CONS ?A ?X)\nthis means cons a onto x,\n\n588\n00:35:19,488 --> 00:35:22,368\n或者说首元素是'A、剩余元素是'X的表\nor a list whose first thing is a and whose rest is x--\n\n589\n00:35:23,160 --> 00:35:27,400\n由此 如果你想推断(MERGE-TO-FROM (?A . ?X) (?B . ?Y) (?B . ?Z))\nso if you want to deduce that a dot x and b dot y merge to form b dot z--\n\n590\n00:35:30,360 --> 00:35:33,904\n毋宁说如果你想要把表(?A ?X)和表(?B ?Y)合并得到\nthat would say you merge these two lists a x and b y\n\n591\n00:35:33,920 --> 00:35:35,856\n一个以?B为首的表\nand you're going to get something that starts with b--\n\n592\n00:35:36,768 --> 00:35:40,672\n你想要推断出这个结果 就要满足\nyou can deduce that if you know that it's the case\n\n593\n00:35:40,910 --> 00:35:44,480\n不但(MERGE-TP-FORM (?A . ?X) ?Y ?Z)\nboth that a dot x and y merge to form z\n\n594\n00:35:45,184 --> 00:35:47,248\n并且(LISP-VALUE > ?A ?B)\nand a is larger than b.\n\n595\n00:35:48,690 --> 00:35:50,592\n因此当我在合并它们时 ?B会首先出现在表中\nSo when I merge them, b will come first in the list.\n\n596\n00:35:51,824 --> 00:35:54,912\n这就是简单的把我之前写的伪代码\nThat's a little translation of the logic rule\n\n597\n00:35:55,248 --> 00:35:57,184\n翻译成逻辑的语言\nthat I wrote in pseudo-English before.\n\n598\n00:35:57,960 --> 00:36:01,632\n为了翻译完整 这还里有种情况\nAnd then just for completeness, here's the other case.\n\n599\n00:36:02,880 --> 00:36:05,952\n(MERGE-TO-FORM (?A . ?X) (?B . ?Y) (?A . ?Z))成立\na dot x and b dot y merge to form a dot z\n\n600\n00:36:06,080 --> 00:36:09,168\n就需要(MERGE-TO-FORM ?X (?B . ?Y) ?Z)\nif x and b dot y merged to form z and b is larger than a.\n\n601\n00:36:09,472 --> 00:36:11,008\n和(LISP-VALUE > ?B ?A)都成立\nand b is larger than a.\n\n602\n00:36:12,190 --> 00:36:15,984\n我已经把这个用逻辑语言编写的小程序输入计算机了\nSo that's a little program that I've typed in in this language,\n\n603\n00:36:16,016 --> 00:36:17,070\n现在让我们来试着运行一下\nand now let's look at it run.\n\n604\n00:36:21,900 --> 00:36:23,904\n由于我已经输入过MERGE-TO-FORM的规则了\nSo I typed in the merge rules before,\n\n605\n00:36:24,624 --> 00:36:25,776\n我就可以\nand I could say, ahh\n\n606\n00:36:27,040 --> 00:36:28,510\n我可以像过程一样使用它\nI could use this like a procedure.\n\n607\n00:36:28,510 --> 00:36:38,240\n我可以问(MERGE-TO-FORM (1 3) (2 7) ?X)\nI could say merge to form 1 and 3 and 2 and 7.\n\n608\n00:36:39,424 --> 00:36:41,552\n这里 我把它当作一个Lisp过程来使用\nSo here I'm using it like the LISP procedure.\n\n609\n00:36:43,168 --> 00:36:44,976\n它先会思考一会儿\nNow it's going to think about that for a while\n\n610\n00:36:46,432 --> 00:36:47,568\n然后应用这些规则\nand apply these rules.\n\n611\n00:36:50,780 --> 00:36:51,920\n它找到了一个答案\nSo it found an answer.\n\n612\n00:36:52,800 --> 00:36:54,544\n现在它还要继续寻找其它的答案\nNow it's going to see if there are any other answers\n\n613\n00:36:55,072 --> 00:36:57,328\n因为它事先不知道这里答案只有一个\nit doesn't know a priori there's only one answer.\n\n614\n00:36:57,810 --> 00:36:59,904\n因此它就在这里检查所有的可能性\nSo it's sitting here checking all possibilities,\n\n615\n00:37:00,416 --> 00:37:02,544\n确认没有后 输出'DONE'\nand it says, no more. Done.\n\n616\n00:37:03,168 --> 00:37:05,072\n这里 我把它们当作过程来使用\nSo there I've used those rules like a procedure.\n\n617\n00:37:05,210 --> 00:37:09,056\n不过要注意 我还可以问不同类型的问题\nOr remember the whole point is that I can ask different kinds of questions.\n\n618\n00:37:10,220 --> 00:37:11,072\n我可以问\nI could say\n\n619\n00:37:18,560 --> 00:37:24,590\n(MERGE-TO-FORM (2 ?A)\nmerge to form, let's see, how about 2 and a.\n\n620\n00:37:24,590 --> 00:37:27,904\n一个我已知是以2为首的二元表\nSome list of two elements which I know starts with 2,\n\n621\n00:37:29,376 --> 00:37:31,264\n而另外一个东西是未知的\nand the other thing I don't know,\n\n622\n00:37:33,056 --> 00:37:35,040\n用?X来表示这个未知的表\nand x and some other list\n\n623\n00:37:36,480 --> 00:37:39,510\n可以通过MERGE-TO-FORM形成(1 2 3 4)\nmerge to form a 1, 2, 3 and 4.\n\n624\n00:37:42,760 --> 00:37:44,112\n现在它将思考这个问题\nSo now it's going to think about that.\n\n625\n00:37:44,590 --> 00:37:49,408\n它会找到 -- 它找到了一种可能\nIt's got to find--  so it found one possibility.\n\n626\n00:37:49,520 --> 00:37:52,464\n比如A=3 X=(1 4)\nIt said a could be 3, and x could be the list 1, 4.\n\n627\n00:37:53,720 --> 00:37:55,168\n现在 它又要继续检查\nAnd now, again, it's got to check\n\n628\n00:37:56,560 --> 00:37:57,712\n因为它事先并不知道\nbecause it doesn't a priori know\n\n629\n00:37:57,744 --> 00:38:00,300\n这里并没有其它的可能了\nthat there aren't any other possibilities going on.\n\n630\n00:38:03,680 --> 00:38:06,576\n或者 就像我说过的\nOr like I said,\n\n631\n00:38:07,008 --> 00:38:09,840\n我可以问\nI could say something like merge to form,\n\n632\n00:38:10,544 --> 00:38:17,552\n能够通过MERGE-TO-FORM形成(1 2 3 4 5)的?X和?Y分别是什么？\nlike, what and what else merge to form 1, 2, 3, 4, 5?\n\n633\n00:38:23,680 --> 00:38:25,536\n语言系统又要思考这个问题\nNow it's going to think about that.\n\n634\n00:38:28,490 --> 00:38:30,310\n它可能会得到很多答案\nAnd there are a lot of answers that it might get.\n\n635\n00:38:35,180 --> 00:38:38,576\n这里我们就体会到了缓慢的代价\nAnd what you see is here you're really paying the price of slowness.\n\n636\n00:38:42,210 --> 00:38:43,880\n大概是有三种原因造成这样\nAnd kind of for three reasons.\n\n637\n00:38:43,880 --> 00:38:46,224\n首先 这门语言经过了两次解释\nOne is that this language is doubly interpreted.\n\n638\n00:38:47,630 --> 00:38:49,728\n然而在真正的实现中\nWhereas in a real implementation,\n\n639\n00:38:49,760 --> 00:38:52,048\n你应该把这些编译成基本运算\nyou would go compile this down to primitive operations.\n\n640\n00:38:52,190 --> 00:38:53,872\n其次就是\nThe other reason is that\n\n641\n00:38:53,888 --> 00:38:58,112\n这个MERGE算法 是双重递归的\nthis particular algorithm for merges is doubly recursive.\n\n642\n00:38:58,380 --> 00:39:00,064\n因此它需要花费很长的时间\nSo it's going to take a very long time.\n\n643\n00:39:01,020 --> 00:39:04,336\n最后呢 它又要遍历所有的情况\nAnd eventually, this is going to go through\n\n644\n00:39:04,592 --> 00:39:07,130\n找出 -- 找出什么呢？\nand find-- find what?\n\n645\n00:39:07,130 --> 00:39:08,730\n所有的2^5种可行解\nTwo to the fifth possible answers.\n\n646\n00:39:12,140 --> 00:39:14,960\n我们发现它们以某种相当随意的顺序输出\nAnd you see they come out in some fairly arbitrary order,\n\n647\n00:39:15,008 --> 00:39:18,144\n这取决于它们用什么样的顺序尝试这些规则\ndepending on which order it's going to be trying these rules.\n\n648\n00:39:20,160 --> 00:39:22,112\n事实上 在后期制作本视频时\nIn fact, what we're going to do when they edit the videotape\n\n649\n00:39:22,400 --> 00:39:23,480\n我们将加速这段\nis speed all this up.\n\n650\n00:39:24,080 --> 00:39:26,600\n我们就不再这里浪费时间了\nDon't you like taking out these waits?\n\n651\n00:39:26,600 --> 00:39:28,272\n课后你们可以自行尝试\nAnd don't you wish you could do that in your demos?\n\n652\n00:39:29,488 --> 00:39:34,240\n好吧 它还在运行\nAnyway, it's still grinding there.\n\n653\n00:39:39,220 --> 00:39:41,120\n总之 一共有32种可能\nAnyway, there are 32 possibilities--\n\n654\n00:39:41,136 --> 00:39:42,630\n我们就不等到输出所有的结果了\nwe won't wait for it to print out all of them.\n\n655\n00:39:47,850 --> 00:39:50,448\n因此 这门语言中的抽象手段就是RULE\nOK, so the needs of abstraction in this language are rules.\n\n656\n00:39:53,536 --> 00:39:58,016\n我们用逻辑把事物组织在一起\nSo we take some bunch of things that are put together with logic\n\n657\n00:39:59,120 --> 00:40:00,080\n并为它们命名\nand we name them.\n\n658\n00:40:00,350 --> 00:40:03,410\n你们可以认为这是为一组特定的逻辑模式命名\nAnd you can think of that as naming a particular pattern of logic.\n\n659\n00:40:03,410 --> 00:40:04,544\n你们可以把它想做\nOr you can think of that as saying,\n\n660\n00:40:04,560 --> 00:40:06,750\n如果我们想要推断出某个结论\nif you want to deduce some conclusion,\n\n661\n00:40:07,904 --> 00:40:09,520\n就可以应用这些逻辑规则\nyou can apply those rules of logic.\n\n662\n00:40:10,660 --> 00:40:13,200\n这些就是这门语言中的三种要素\nAnd those are three elements of this language.\n\n663\n00:40:13,420 --> 00:40:14,560\n我们先休息一会儿\nLet's break now,\n\n664\n00:40:14,608 --> 00:40:16,590\n然后再来讨论如何实际实现\nand then we'll talk about how it's actually implemented.\n\n665\n00:40:23,616 --> 00:40:28,848\n学生：使用LISP-VALUE之类的基本过程会影响\nAUDIENCE: Does using LISP value primitive or whatever interfere with your means\n\n666\n00:40:29,152 --> 00:40:30,640\n查询的双向性吗？\nboth directions on a query?\n\n667\n00:40:31,770 --> 00:40:34,480\n教授：这个问题 -- 你问的是\nPROFESSOR: OK, that's a-- the question is,\n\n668\n00:40:35,088 --> 00:40:36,928\n使用LISP-VALUE是否会影响\ndoes using LISP value interfere\n\n669\n00:40:37,536 --> 00:40:40,090\n双向地推断一条查询\nwith the ability to go both directions on the query?\n\n670\n00:40:40,090 --> 00:40:42,816\n虽然我们还没有实际讨论具体实现\nWe haven't really talked about the implementation yet,\n\n671\n00:40:43,680 --> 00:40:45,520\n但是它们确实会造成影响\nbut the answer is, yes, it can.\n\n672\n00:40:46,890 --> 00:40:50,208\n通常来说 我们最后将会发现\nIn general, as we'll see at the end--\n\n673\n00:40:50,224 --> 00:40:52,170\n虽然我不会讲得太细\nalthough I really won't to go into details--\n\n674\n00:40:53,216 --> 00:40:59,360\n当你使用NOT和LISP-VALUE时 会变得相当复杂\nit's fairly complicated, especially when you use either not or LISP value--\n\n675\n00:40:59,550 --> 00:41:02,890\n或者实际上 只要你用了除AND以外的东西\nor actually, if you use anything besides only and,\n\n676\n00:41:04,128 --> 00:41:08,192\n很难再说清楚这些东西是否会起效了\nit becomes very complicated to say when these things will work.\n\n677\n00:41:08,208 --> 00:41:10,360\n它们并不是在任何情况下都有效\nThey won't work quite in all situations.\n\n678\n00:41:10,360 --> 00:41:13,392\n我会在下一堂课的最后讨论这个问题\nI'll talk about that at the end of the second half today.\n\n679\n00:41:14,300 --> 00:41:15,840\n但对于你的问题来说：答案是“会影响”\nBut the answer to your question is, yes,\n\n680\n00:41:16,192 --> 00:41:19,216\n用LISP-VALUE一方面从Lisp中获得了巨大威力\nby dragging in a lot more power from LISP value,\n\n681\n00:41:19,408 --> 00:41:23,776\n另一方面你失去了逻辑式程序设计的重要威力\nyou lose some of the principal power of logic programming.\n\n682\n00:41:24,170 --> 00:41:25,568\n这是你需要做出的取舍\nThat's a trade-off that you have to make.\n\n683\n00:41:28,480 --> 00:41:29,392\n好吧 先休息一会儿\nOK, let's take a break.\n\n684\n00:41:30,176 --> 00:41:37,392\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n685\n00:41:37,408 --> 00:41:44,304\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec8b.eng.srt",
    "content": "﻿1\n00:00:18,910 --> 00:00:22,502\nPROFESSOR: All right, well, we've seen how the query language works.\n\n2\n00:00:22,502 --> 00:00:26,280\nNow, let's talk about how it's implemented.\n\n3\n00:00:26,280 --> 00:00:29,470\nYou already pretty much can guess what's going on there.\n\n4\n00:00:29,470 --> 00:00:32,810\nAt the bottom of it, there's a pattern matcher.\n\n5\n00:00:32,810 --> 00:00:38,110\nAnd we looked at a pattern matcher when we did the rule-based control language.\n\n6\n00:00:38,110 --> 00:00:41,520\nJust to remind you, here are some sample patterns.\n\n7\n00:00:41,520 --> 00:00:50,650\nThis is a pattern that will match any list of three things of which the first is a and the second is c and the middle one can be anything.\n\n8\n00:00:50,650 --> 00:00:54,050\nSo in this little pattern-matching syntax, there's only one distinction you make.\n\n9\n00:00:54,050 --> 00:00:59,080\nThere's either literal things or variables, and variables begin with question mark.\n\n10\n00:01:01,370 --> 00:01:06,500\nSo this matches any list of three things of which the first is a and the second is c.\n\n11\n00:01:06,500 --> 00:01:12,530\nThis one matches any list of three things of which the first is the symbol job.\n\n12\n00:01:12,530 --> 00:01:14,210\nThe second can be anything.\n\n13\n00:01:14,210 --> 00:01:20,480\nAnd the third is a list of two things of which the first is the symbol computer and the second can be anything.\n\n14\n00:01:20,480 --> 00:01:37,860\nAnd this one, this next one matches any list of three things, and the only difference is, here, the third list, the first is the symbol computer, and then there's some rest of the list. So this means two elements and this means arbitrary number.\n\n15\n00:01:37,860 --> 00:01:44,050\nAnd our language implementation isn't even going to have to worry about implementing this dot because that's automatically done by Lisp's reader.\n\n16\n00:01:48,340 --> 00:01:50,310\nRemember matchers also have some consistency in them.\n\n17\n00:01:50,310 --> 00:01:54,430\nThis match is a list of three things of which the first is a.\n\n18\n00:01:54,430 --> 00:01:57,940\nAnd the second and third can be anything, but they have to be the same thing.\n\n19\n00:01:57,940 --> 00:01:59,600\nThey're both called x.\n\n20\n00:01:59,600 --> 00:02:05,590\nAnd this matches a list of four things of which the first is the fourth and the second is the same as the third.\n\n21\n00:02:05,590 --> 00:02:09,685\nAnd this last one matches any list that begins with a.\n\n22\n00:02:09,685 --> 00:02:14,040\nThe first thing is a, and the rest can be anything.\n\n23\n00:02:14,040 --> 00:02:18,780\nSo that's just a review of pattern matcher syntax that you've already seen.\n\n24\n00:02:18,780 --> 00:02:22,740\nAnd remember, that's implemented by some procedure called match.\n\n25\n00:02:24,870 --> 00:02:35,695\nAnd match takes a pattern and some data and a dictionary.\n\n26\n00:02:43,200 --> 00:02:58,160\nAnd match asks the question is there any way to match this pattern against this data object subject to the bindings that are already in this dictionary?\n\n27\n00:02:58,160 --> 00:03:22,010\nSo, for instance, if we're going to match the pattern x, y, y, x against the data a, b, b, a subject to a dictionary, that says x equals a.\n\n28\n00:03:22,010 --> 00:03:25,260\nThen the matcher would say, yes, that's consistent.\n\n29\n00:03:25,260 --> 00:03:30,320\nThese match, and it's consistent with what's in the dictionary to say that x equals a.\n\n30\n00:03:30,320 --> 00:03:39,490\nAnd the result of the match is the extended dictionary that says x equals a and y equals b.\n\n31\n00:03:39,490 --> 00:03:46,840\nSo a matcher takes in pattern data dictionary, puts out an extended dictionary if it matches, or if it doesn't match, says that it fails.\n\n32\n00:03:46,840 --> 00:04:06,665\nSo, for example, if I use the same pattern here, if I say this x, y, y, x match a, b, b, a with the dictionary y equals a, then the matcher would put out fail.\n\n33\n00:04:12,150 --> 00:04:21,190\nWell, you've already seen the code for a pattern matcher so I'm not going to go over it, but it's the same thing we've been doing before.\n\n34\n00:04:21,190 --> 00:04:23,220\nYou saw that in the system on rule-based control.\n\n35\n00:04:23,220 --> 00:04:24,950\nIt's essentially the same matcher.\n\n36\n00:04:24,950 --> 00:04:31,400\nIn fact, I think the syntax is a little bit simpler because we're not worrying about arbitrary constants and expressions and things.\n\n37\n00:04:31,400 --> 00:04:32,690\nThere's just variables and constants.\n\n38\n00:04:35,790 --> 00:04:39,610\nOK, well, given that, what's a primitive query?\n\n39\n00:04:42,970 --> 00:04:46,720\nPrimitive query is going to be a rather complicated thing.\n\n40\n00:04:46,720 --> 00:05:03,490\nIt's going to be-- let's think about the query job of x is d dot y.\n\n41\n00:05:06,850 --> 00:05:09,400\nThat's a query we might type in.\n\n42\n00:05:09,400 --> 00:05:11,095\nThat's going to be implemented in the system.\n\n43\n00:05:14,270 --> 00:05:15,700\nWe'll think of it as this little box.\n\n44\n00:05:15,700 --> 00:05:18,880\nHere's the primitive query.\n\n45\n00:05:18,880 --> 00:05:34,030\nWhat this little box is going to do is take in two streams and put out a stream.\n\n46\n00:05:34,030 --> 00:05:41,120\nSo the shape of a primitive query is that it's a thing where two streams come in and one stream goes out.\n\n47\n00:05:41,120 --> 00:05:45,925\nWhat these streams are going to be is down here is the database.\n\n48\n00:05:51,600 --> 00:06:00,330\nSo we imagine all the things in the database sort of sitting there in a stream and this thing sucks on them.\n\n49\n00:06:00,330 --> 00:06:02,800\nSo what are some things that might be in the database?\n\n50\n00:06:02,800 --> 00:06:25,770\nOh, job of Alyssa is something and some other job is something.\n\n51\n00:06:25,770 --> 00:06:32,040\nSo imagine all of the facts in the database sitting there in the stream.\n\n52\n00:06:32,040 --> 00:06:33,400\nThat's what comes in here.\n\n53\n00:06:33,400 --> 00:06:38,510\nWhat comes in here is a stream of dictionaries.\n\n54\n00:06:38,510 --> 00:06:48,855\nSo one particular dictionary might say y equals programmer.\n\n55\n00:06:55,470 --> 00:07:11,390\nNow, what the query does when it gets in a dictionary from this stream, it finds all possible ways of matching the query against whatever is coming in from the database.\n\n56\n00:07:11,390 --> 00:07:27,550\nIt looks at the query as a pattern, matches it against any fact from the database or all possible ways of finding and matching the database with respect to this dictionary that's coming in.\n\n57\n00:07:27,550 --> 00:07:35,110\nSo for each fact in the database, it calls the matcher using the pattern, fact, and dictionary.\n\n58\n00:07:35,110 --> 00:07:40,420\nAnd every time it gets a good match, it puts out the extended dictionary.\n\n59\n00:07:40,420 --> 00:07:52,970\nSo, for example, if this one comes in and it finds a match, out will come a dictionary that in this case will have y equals programmer and x equals something.\n\n60\n00:07:56,740 --> 00:08:01,430\ny is programmer, x is something, and d is whatever it found.\n\n61\n00:08:01,430 --> 00:08:03,520\nAnd that's all.\n\n62\n00:08:03,520 --> 00:08:07,980\nAnd, of course, it's going to try this for every fact in the dictionary.\n\n63\n00:08:07,980 --> 00:08:09,250\nSo it might find lots of them.\n\n64\n00:08:09,250 --> 00:08:16,355\nIt might find another one that says y equals programmer and x equals, and d equals.\n\n65\n00:08:20,040 --> 00:08:30,470\nSo for one frame coming in, it might put out-- for one dictionary coming in, it might put out a lot of dictionaries, or it might put out none.\n\n66\n00:08:30,470 --> 00:08:39,320\nIt might have something that wouldn't match like x equals FOO.\n\n67\n00:08:39,320 --> 00:08:47,510\nThis one might not match anything in which case nothing will go into this stream corresponding to this frame.\n\n68\n00:08:47,510 --> 00:09:07,570\nOr what you might do is put in an empty frame, and an empty frame says try matching all ways--  find all possible ways of matching the query against something in the database subject to no previous restrictions.\n\n69\n00:09:07,570 --> 00:09:13,980\nAnd if you think about what that means, that's just the computation that's done when you type in a query right off.\n\n70\n00:09:13,980 --> 00:09:16,650\nIt tries to find all matches.\n\n71\n00:09:16,650 --> 00:09:19,370\nSo a primitive query sets up this mechanism.\n\n72\n00:09:19,370 --> 00:09:44,990\nAnd what the language does, when you type in the query at the top level, it takes this mechanism, feeds in one single empty dictionary, and then for each thing that comes out takes the original query and instantiates the result with all the different dictionaries, producing a new stream of instantiated patterns here.\n\n73\n00:09:44,990 --> 00:09:48,170\nAnd that's what gets printed on the terminal.\n\n74\n00:09:48,170 --> 00:09:53,510\nThat's the basic mechanism going on there.\n\n75\n00:09:53,510 --> 00:09:56,870\nWell, why is that so complicated?\n\n76\n00:09:56,870 --> 00:10:04,725\nYou probably can think of a lot simpler ways to arrange this match for a primitive query rather than having all of these streams floating around.\n\n77\n00:10:04,725 --> 00:10:10,860\nAnd the answer is-- you probably guess already.\n\n78\n00:10:10,860 --> 00:10:17,790\nThe answer is this thing extends elegantly to implement the means of combination.\n\n79\n00:10:17,790 --> 00:10:22,470\nSo, for instance, suppose I don't only want to do this.\n\n80\n00:10:22,470 --> 00:10:27,230\nI don't want to say who to be everybody's job description.\n\n81\n00:10:27,230 --> 00:10:48,800\nSuppose I want to say AND the job of x is d dot y and the supervisor of x is z.\n\n82\n00:10:48,800 --> 00:11:08,700\nNow, supervisor of x is z is going to be another primitive query that has the same shape to take in a stream of data objects, a stream of initial dictionaries, which are the restrictions to try and use when you match, and it's going to put out a stream of dictionaries.\n\n83\n00:11:08,700 --> 00:11:11,680\nSo that's what this primitive query looks like.\n\n84\n00:11:11,680 --> 00:11:12,910\nAnd how do I implement the AND?\n\n85\n00:11:12,910 --> 00:11:13,450\nWell, it's simple.\n\n86\n00:11:13,450 --> 00:11:14,880\nI just hook them together.\n\n87\n00:11:14,880 --> 00:11:19,830\nI take the output of this one, and I put that to the input of that one.\n\n88\n00:11:19,830 --> 00:11:21,545\nAnd I take the dictionary here and I fan it out.\n\n89\n00:11:26,570 --> 00:11:37,920\nAnd then you see how that's going to work, because what's going to happen is a frame will now come in here, which has a binding for x, y, and d.\n\n90\n00:11:37,920 --> 00:11:56,080\nAnd then when this one gets it, it'll say, oh, gee, subject to these restrictions, which now already have values in the dictionary for y and x and d, it looks in the database and says, gee, can I find any supervisor facts?\n\n91\n00:11:56,080 --> 00:12:09,340\nAnd if it finds any, out will come dictionaries which have bindings for y and x and d and z now.\n\n92\n00:12:12,070 --> 00:12:26,470\nAnd then notice that because the frames coming in here have these restrictions, that's the thing that assures that when you do the AND, this x will mean the same thing as that x.\n\n93\n00:12:26,470 --> 00:12:34,460\nBecause by the time something comes floating in here, x has a value that you have to match against consistently.\n\n94\n00:12:34,460 --> 00:12:40,710\nAnd then you remember from the code from the matcher, there was something in the way the matcher did dictionaries that arrange consistent matches.\n\n95\n00:12:40,710 --> 00:12:44,260\nSo there's AND.\n\n96\n00:12:44,260 --> 00:12:48,570\nThe important point to notice is the general shape.\n\n97\n00:12:48,570 --> 00:12:52,600\nLook at what happened: the AND of two queries, say, P and Q.\n\n98\n00:12:52,600 --> 00:13:01,190\nHere's P and Q. The AND of two queries, well, it looks like this.\n\n99\n00:13:01,190 --> 00:13:10,230\nEach query takes in a stream from the database, a stream of inputs, and puts out a stream of outputs.\n\n100\n00:13:10,230 --> 00:13:32,360\nAnd the important point to notice is that if I draw a box around this thing and say this is AND of P and Q, then that box has exactly the same overall shape.\n\n101\n00:13:32,360 --> 00:13:34,200\nIt's something that takes in a stream from the database.\n\n102\n00:13:34,200 --> 00:13:38,160\nHere it's going to get fanned out inside, but from the outside you don't see that.\n\n103\n00:13:38,160 --> 00:13:42,230\nIt takes an input stream and puts out an output stream.\n\n104\n00:13:42,230 --> 00:13:43,570\nSo this is AND.\n\n105\n00:13:43,570 --> 00:13:46,020\nAnd then similarly, OR would look like this.\n\n106\n00:13:46,020 --> 00:13:49,840\nOR would-- although I didn't show you examples of OR.\n\n107\n00:13:49,840 --> 00:13:58,070\nOR would say can I find all ways of matching P or Q. So I have P and Q. Each will have their shape.\n\n108\n00:14:04,460 --> 00:14:12,500\nAnd the way OR is implemented is I'll take my database stream.\n\n109\n00:14:12,500 --> 00:14:13,490\nI'll fan it out.\n\n110\n00:14:13,490 --> 00:14:21,980\nI'll put one into P and one into Q. I'll take my initial query stream coming in and fan it out.\n\n111\n00:14:26,750 --> 00:14:41,080\nSo I'll look at all the answers I might get from P and all the answers I might get from Q, and I'll put them through some sort of thing that appends them or merges the result into one stream, and that's what will come out.\n\n112\n00:14:41,080 --> 00:14:48,240\nAnd this whole thing from the outside is OR.\n\n113\n00:14:52,350 --> 00:14:56,790\nAnd again, you see it has the same overall shape when looked at from the outside.\n\n114\n00:15:01,000 --> 00:15:02,020\nWhat's NOT?\n\n115\n00:15:02,020 --> 00:15:04,310\nNOT works kind of the same way.\n\n116\n00:15:04,310 --> 00:15:14,690\nIf I have some query P, I take the primitive query for P.\n\n117\n00:15:14,690 --> 00:15:20,720\nHere, I'm going to implement NOT P. And NOT's just going to act as a filter.\n\n118\n00:15:20,720 --> 00:15:39,020\nI'll take in the database and my original stream of dictionaries coming in, and what NOT P will do is it will filter these guys.\n\n119\n00:15:39,020 --> 00:15:47,460\nAnd the way it will filter it, it will say when I get in a dictionary here, I'll find all the matches, and if I find any, I'll throw it away.\n\n120\n00:15:47,460 --> 00:15:55,560\nAnd if I don't find any matches to something coming in here, I'll just pass that through, so NOT is a pure filter.\n\n121\n00:15:55,560 --> 00:15:59,980\nSo AND is-- think of these sort of electoral resistors or something.\n\n122\n00:15:59,980 --> 00:16:04,960\nAND is series combination and OR is parallel combination.\n\n123\n00:16:04,960 --> 00:16:07,460\nAnd then NOT is not going to extend any dictionaries at all.\n\n124\n00:16:07,460 --> 00:16:08,750\nIt's just going to filter it.\n\n125\n00:16:08,750 --> 00:16:12,640\nIt's going to throw away the ones for which it finds a way to match.\n\n126\n00:16:12,640 --> 00:16:14,540\nAnd list value is sort of the same way.\n\n127\n00:16:14,540 --> 00:16:16,600\nThe filter's a little more complicated.\n\n128\n00:16:16,600 --> 00:16:19,640\nIt applies to predicate.\n\n129\n00:16:19,640 --> 00:16:24,980\nThe major point to notice here, and it's a major point we've looked at before, is this idea of closure.\n\n130\n00:16:28,490 --> 00:16:39,750\nThe things that we build as a means of combination have the same overall structure as the primitive things that we're combining.\n\n131\n00:16:39,750 --> 00:16:44,630\nSo the AND of two things when looked at from the outside has the same shape.\n\n132\n00:16:44,630 --> 00:16:54,950\nAnd what that means is that this box here could be an AND or an OR or a NOT or something because it has the same shape to interface to the larger things.\n\n133\n00:16:54,950 --> 00:17:04,170\nIt's the same thing that allowed us to get complexity in the Escher picture language or allows you to immediately build up these complicated structures just out of pairs.\n\n134\n00:17:04,170 --> 00:17:06,280\nIt's closure.\n\n135\n00:17:06,280 --> 00:17:19,260\nAnd that's the thing that allowed me to do what by now you took for granted when I said, gee, there's a query which is AND of job and salary, and I said, oh, there's another one, which is AND of job, a NOT of something.\n\n136\n00:17:19,260 --> 00:17:25,230\nThe fact that I can do that is a direct consequence of this closure principle.\n\n137\n00:17:25,230 --> 00:17:29,520\nOK, let's break and then we'll go on.\n\n138\n00:17:29,520 --> 00:17:30,710\nAUDIENCE: Where does the dictionary come from?\n\n139\n00:17:30,710 --> 00:17:36,030\nPROFESSOR: The dictionary comes initially from what you type in.\n\n140\n00:17:36,030 --> 00:17:41,090\nSo when you start this up, the first thing it does is set up this whole structure.\n\n141\n00:17:41,090 --> 00:17:45,000\nIt puts in one empty dictionary.\n\n142\n00:17:45,000 --> 00:17:52,310\nAnd if all you have is one primitive query, then what will come out is a bunch of dictionaries with things filled in.\n\n143\n00:17:52,310 --> 00:17:59,710\nThe general situation that I have here is when this is in the middle of some nest of combined things.\n\n144\n00:18:02,380 --> 00:18:03,790\nLet's look at the picture over here.\n\n145\n00:18:03,790 --> 00:18:06,730\nThis supervisor query gets in some dictionary.\n\n146\n00:18:06,730 --> 00:18:08,730\nWhere did this one come from?\n\n147\n00:18:08,730 --> 00:18:16,260\nThis dictionary came from the fact that I'm looking at the output of this primitive query.\n\n148\n00:18:16,260 --> 00:18:31,770\nSo maybe to be very specific, if I literally typed in just this query at the top level, this AND, what would actually happen is it would build this structure and start up this whole thing with one empty dictionary.\n\n149\n00:18:31,770 --> 00:18:38,640\nAnd now this one would process, and a whole bunch of dictionaries would come out with x, y's and d's in them.\n\n150\n00:18:38,640 --> 00:18:40,190\nRun it through this one.\n\n151\n00:18:40,190 --> 00:18:42,160\nSo now that's the input to this one.\n\n152\n00:18:42,160 --> 00:18:45,040\nThis one would now put out some other stuff.\n\n153\n00:18:45,040 --> 00:18:56,110\nAnd if this itself were buried in some larger thing, like an OR of something, then that would go feed into the next one.\n\n154\n00:18:58,560 --> 00:19:07,660\nSo you initially get only one empty dictionary when you start it, but as you're in the middle of processing these compounds things, that's where these cascades of dictionaries start getting generated.\n\n155\n00:19:07,660 --> 00:19:12,280\nAUDIENCE: Dictionaries only come about as a result of using the queries?\n\n156\n00:19:15,120 --> 00:19:23,220\nOr do they become-- do they stay someplace in space like the database does?\n\n157\n00:19:23,220 --> 00:19:24,980\nAre these temporary items?\n\n158\n00:19:24,980 --> 00:19:28,030\nPROFESSOR: They're created temporarily in the matcher.\n\n159\n00:19:28,030 --> 00:19:29,880\nReally, they're someplace in storage.\n\n160\n00:19:29,880 --> 00:19:40,950\nInitially, someone creates a thing called the empty dictionary that gets initially fed to this match procedure, and then the match procedure builds some dictionaries, and they get passed on and on.\n\n161\n00:19:40,950 --> 00:19:43,526\nAUDIENCE: OK, so they'll go way after the match?\n\n162\n00:19:43,526 --> 00:19:45,930\nPROFESSOR: They'll go away when no one needs them again, yeah.\n\n163\n00:19:51,900 --> 00:19:56,050\nAUDIENCE: It appears that the AND performs some redundant searches of the database.\n\n164\n00:19:56,050 --> 00:20:06,700\nIf the first clause matched, let's say, the third element and not on the first two elements, the second clause is going to look at those first two elements again, discarding them because they don't match.\n\n165\n00:20:06,700 --> 00:20:10,000\nThe match is already in the dictionary.\n\n166\n00:20:10,000 --> 00:20:14,450\nWould it makes sense to carry the data element from the database along with the dictionary?\n\n167\n00:20:17,120 --> 00:20:21,740\nPROFESSOR: Well, in general, there are other ways to arrange this search, and there's some analysis that you can do.\n\n168\n00:20:21,740 --> 00:20:29,850\nI think there's a problem in the book, which talks about a different way that you can cascade AND to eliminate various kinds of redundancies.\n\n169\n00:20:29,850 --> 00:20:34,650\nThis one is meant to be-- was mainly meant to be very simple so you can see how they fit together.\n\n170\n00:20:34,650 --> 00:20:35,380\nBut you're quite right.\n\n171\n00:20:35,380 --> 00:20:38,370\nThere are redundancies here that you can get rid of.\n\n172\n00:20:38,370 --> 00:20:41,190\nThat's another reason why this language is somewhat slow.\n\n173\n00:20:41,190 --> 00:20:42,930\nThere are a lot smarter things you can do.\n\n174\n00:20:42,930 --> 00:20:46,840\nWe're just trying to show you a very simple, in principle, implementation.\n\n175\n00:20:51,220 --> 00:20:55,150\nAUDIENCE: Did you model this language on Prolog, or did it just come out looking like Prolog?\n\n176\n00:21:04,960 --> 00:21:16,120\nPROFESSOR: Well, Jerry insulted a whole bunch of people yesterday, so I might as well say that the MIT attitude towards Prolog is something that people did in about 1971 and decided that it wasn't really the right thing and stopped.\n\n177\n00:21:16,120 --> 00:21:37,330\nSo we modeled this on the sort of natural way that this thing was done in about 1971, except at that point, we didn't do it with streams. After we were using it for about six months, we discovered that it had all these problems, some of which I'll talk about later.\n\n178\n00:21:37,330 --> 00:21:41,250\nAnd we said, gee, Prolog must have fixed those, and then we found out that it didn't.\n\n179\n00:21:41,250 --> 00:21:43,460\nSo this does about the same thing as Prolog.\n\n180\n00:21:43,460 --> 00:21:44,950\nAUDIENCE: Does Prolog use streams?\n\n181\n00:21:44,950 --> 00:21:46,200\nPROFESSOR: No.\n\n182\n00:21:48,540 --> 00:21:51,040\nIn how it behaves, it behaves a lot like Prolog.\n\n183\n00:21:51,040 --> 00:21:53,800\nProlog uses a backtracking strategy.\n\n184\n00:21:53,800 --> 00:22:20,850\nBut the other thing that's really good about Prolog that makes it a usable thing is that there's a really very, very well-engineered compiler technology that makes it run fast. So although you saw the merge spitting out these answers very, very slowly, a real Prolog will run very, very fast. Because even though it's sort of doing this, the real work that went into Prolog is a very, very excellent compiler effort.\n\n185\n00:22:24,460 --> 00:22:25,710\nLet's take a break.\n\n186\n00:23:16,650 --> 00:23:26,950\nWe've looked at the primitive queries and the ways that streams are used to implement the means of combination: AND and OR and NOT.\n\n187\n00:23:26,950 --> 00:23:29,580\nNow, let go on to the means of abstraction.\n\n188\n00:23:29,580 --> 00:23:32,570\nRemember, the means of abstraction in this language are rules.\n\n189\n00:23:35,150 --> 00:23:48,900\nSo z is a boss in division d if there's some x who has a job in division d and z is the supervisor of x.\n\n190\n00:23:48,900 --> 00:23:52,260\nThat's what it means for someone to be a boss.\n\n191\n00:23:52,260 --> 00:24:33,900\nAnd in effect, if you think about what we're doing with relation to this, there's the query we wrote-- the job of x is in d and the supervisor of x is z-- what we in effect want to do is take this whole mess and draw a box around it and say this whole thing inside the box is boss of z in division d.\n\n192\n00:24:33,900 --> 00:24:35,250\nThat's in effect what we want to do.\n\n193\n00:24:38,720 --> 00:25:33,045\nSo, for instance, if we've done that, and we want to check whether or not it's true that Ben Bitdiddle is a boss in the computer division, so if I want to say boss of Ben Bitdiddle in the computer division, imagine typing that in as query to the system, in effect what we want to do is set up a dictionary here, which has z to Ben Bitdiddle and d to computer.\n\n194\n00:25:37,340 --> 00:25:38,720\nWhere did that dictionary come from?\n\n195\n00:25:38,720 --> 00:25:40,710\nLet's look at the slide for one second.\n\n196\n00:25:40,710 --> 00:25:51,650\nThat dictionary came from matching the query that said boss of Ben Bitdiddle and computer onto the conclusion of the rule: boss of z and d.\n\n197\n00:25:51,650 --> 00:25:54,190\nSo we match the query to the conclusion of the rule.\n\n198\n00:25:54,190 --> 00:26:06,670\nThat gives us a dictionary, and that's the thing that we would now like to put into this whole big thing and process and see if anything comes out the other side.\n\n199\n00:26:06,670 --> 00:26:11,330\nIf anything comes out, it'll be true.\n\n200\n00:26:11,330 --> 00:26:12,370\nThat's the basic idea.\n\n201\n00:26:12,370 --> 00:26:23,580\nSo in general, the way we implement a rule is we match the conclusion of the rule against something we might want to check it's true.\n\n202\n00:26:23,580 --> 00:26:36,470\nThat match gives us a dictionary, and with respect to that dictionary, we process the body of the rule.\n\n203\n00:26:36,470 --> 00:26:43,070\nWell, that's really all there is, except for two technical points.\n\n204\n00:26:43,070 --> 00:26:47,510\nThe first technical point is that I might have said something else.\n\n205\n00:26:47,510 --> 00:26:52,490\nI might have said who's the boss in the computer division?\n\n206\n00:26:52,490 --> 00:26:56,270\nSo I might say boss of who in computer division.\n\n207\n00:27:00,329 --> 00:27:18,620\nAnd if I did that, what I would really like to do in effect is start up this dictionary with a match that sort of says, well, d is computer and z is whatever who is.\n\n208\n00:27:21,700 --> 00:27:23,220\nAnd our matcher won't quite do that.\n\n209\n00:27:23,220 --> 00:27:28,580\nThat's not quite matching a pattern against data.\n\n210\n00:27:28,580 --> 00:27:33,480\nIt's matching two patterns and saying are they consistent or not or what ways make them consistent.\n\n211\n00:27:33,480 --> 00:27:39,740\nIn other words, what we need is not quite a pattern matcher, but something a little bit more general called a unifier.\n\n212\n00:27:44,420 --> 00:27:49,530\nAnd a unifier is a slight generalization of a pattern matcher.\n\n213\n00:27:49,530 --> 00:28:05,680\nWhat a unifier does is take two patterns and say what's the most general thing you can substitute for the variables in those two patterns to make them satisfy the pattern simultaneously?\n\n214\n00:28:05,680 --> 00:28:08,900\nLet me give you an example.\n\n215\n00:28:08,900 --> 00:28:43,440\nIf I have the pattern two-element list, which is x and x, so I have a two-element list where both elements are the same and otherwise I don't care what they are, and I unify that against the pattern that says there's a two-element list, and the first one is a and something in c and the second one is a and b and z, then what the unifier should tell me is, oh yeah, in that dictionary, x has to be a, b, c, and y has to be d and z has to be c.\n\n216\n00:28:43,440 --> 00:28:55,420\nThose are the restrictions I'd have to put on the values of x, y, and z to make these two unify, or in other words, to make this match x and make this match x.\n\n217\n00:28:55,420 --> 00:28:58,540\nThe unifier should be able to deduce that.\n\n218\n00:28:58,540 --> 00:29:01,080\nBut the unifier may-- there are more complicated things.\n\n219\n00:29:01,080 --> 00:29:03,810\nI might have said something a little bit more complicated.\n\n220\n00:29:03,810 --> 00:29:12,650\nI might have said there's a list with two elements, and they're both the same, and they should unify against something of this form.\n\n221\n00:29:12,650 --> 00:29:16,890\nAnd the unifier should be able to deduce from that.\n\n222\n00:29:16,890 --> 00:29:19,570\nLike that y would have to be b. y would have to be b.\n\n223\n00:29:19,570 --> 00:29:24,340\nBecause these two are the same, so y's got to be b.\n\n224\n00:29:24,340 --> 00:29:28,940\nAnd v here would have to be a.\n\n225\n00:29:28,940 --> 00:29:32,700\nAnd z and w can be anything, but they have to be the same thing.\n\n226\n00:29:35,710 --> 00:29:44,680\nAnd x would have to be b, followed by a, followed by whatever w is or whatever z is, which is the same.\n\n227\n00:29:44,680 --> 00:29:50,880\nSo you see, the unifier somehow has to deduce things to unify these patterns.\n\n228\n00:29:50,880 --> 00:29:55,850\nSo you might think there's some kind of magic deduction going on, but there's not.\n\n229\n00:29:55,850 --> 00:30:00,150\nA unifier is basically a very simple modification of a pattern matcher.\n\n230\n00:30:00,150 --> 00:30:08,280\nAnd if you look in the book, you'll see something like three or four lines of code added to the pattern matcher you just saw to handle the symmetric case.\n\n231\n00:30:08,280 --> 00:30:14,980\nRemember, the pattern matcher has a place where it says is this variable matching a constant.\n\n232\n00:30:14,980 --> 00:30:16,420\nAnd if so, it checks in the dictionary.\n\n233\n00:30:16,420 --> 00:30:27,030\nThere's only one other clause in the unifier, which says is this variable matching a variable, in which case you go look in the dictionary and see if that's consistent with what's in the dictionary.\n\n234\n00:30:27,030 --> 00:30:45,260\nSo all the, quote, deduction that's in this language, if you sort of look at it, sort of sits in the rule applications, which, if you look at that, sits in the unifier, which, if you look at that under a microscope, sits essentially in the pattern matcher.\n\n235\n00:30:45,260 --> 00:30:47,410\nThere's no magic at all going on in there.\n\n236\n00:30:47,410 --> 00:30:56,030\nAnd the, quote, deduction that you see is just the fact that there's this recursion, which is unwinding the matches bit by bit.\n\n237\n00:30:56,030 --> 00:31:02,140\nSo it looks like this thing is being very clever, but in fact, it's not being very clever at all.\n\n238\n00:31:02,140 --> 00:31:04,880\nThere are cases where a unifier might have to be clever.\n\n239\n00:31:04,880 --> 00:31:06,130\nLet me show you one more.\n\n240\n00:31:11,070 --> 00:31:24,370\nSuppose I want to unify a list of two elements, x and x, with a thing that says it's y followed by a dot y.\n\n241\n00:31:24,370 --> 00:31:37,330\nNow, if you think of what that would have to mean, it would have to mean that x had better be the same as y, but also x had better be the same as a list whose first element is a and whose rest is y.\n\n242\n00:31:37,330 --> 00:31:44,710\nAnd if you think about what that would have to mean, it would have to mean that y is the infinite list of a's.\n\n243\n00:31:47,500 --> 00:32:01,840\nIn some sense, in order to do that unification, I have to solve the fixed-point equation cons of a to y is equal to y.\n\n244\n00:32:04,570 --> 00:32:07,290\nAnd in general, I wrote a very simple one.\n\n245\n00:32:07,290 --> 00:32:15,530\nReally doing unification might have to solve an arbitrary fixed-point equation: f of y equals y.\n\n246\n00:32:15,530 --> 00:32:20,570\nAnd basically, you can't do that and make the thing finite all the time.\n\n247\n00:32:20,570 --> 00:32:25,140\nSo how does the logic language handle that?\n\n248\n00:32:25,140 --> 00:32:26,850\nThe answer is it doesn't.\n\n249\n00:32:26,850 --> 00:32:28,730\nIt just punts.\n\n250\n00:32:28,730 --> 00:32:38,650\nAnd there's a little check in the unifier, which says, oh, is this one of the hard cases which when I go to match things would involve solving a fixed-point equation?\n\n251\n00:32:38,650 --> 00:32:42,840\nAnd in this case, I will throw up my hands.\n\n252\n00:32:42,840 --> 00:32:47,990\nAnd if that check were not in there, what would happen?\n\n253\n00:32:47,990 --> 00:32:53,740\nIn most cases is that the unifier would just go into an infinite loop.\n\n254\n00:32:53,740 --> 00:32:56,800\nAnd other logic programming languages work like that.\n\n255\n00:32:56,800 --> 00:32:58,220\nSo there's really no magic.\n\n256\n00:32:58,220 --> 00:33:00,100\nThe easy case is done in a matcher.\n\n257\n00:33:00,100 --> 00:33:02,960\nThe hard case is not done at all.\n\n258\n00:33:02,960 --> 00:33:05,115\nAnd that's about the state of this technology.\n\n259\n00:33:12,840 --> 00:33:17,390\nLet me just say again formally how rules work now that I talked about unifiers.\n\n260\n00:33:17,390 --> 00:33:28,270\nSo the official definition is that to apply a rule, we-- well, let's start using some words we've used before.\n\n261\n00:33:28,270 --> 00:33:43,850\nLet's talk about sticking dictionaries into these big boxes of query things as evaluating these large queries relative to an environment or a frame.\n\n262\n00:33:43,850 --> 00:33:46,720\nSo when you think of that dictionary, what's the dictionary after all?\n\n263\n00:33:46,720 --> 00:33:48,180\nIt's a bunch of meanings for symbols.\n\n264\n00:33:48,180 --> 00:33:51,800\nThat's what we've been calling frames or environments.\n\n265\n00:33:51,800 --> 00:33:55,970\nWhat does it mean to do some processing relevant to an environment?\n\n266\n00:33:55,970 --> 00:33:58,310\nThat's what we've been calling evaluation.\n\n267\n00:33:58,310 --> 00:34:13,230\nSo we can say the way that you apply a rule is to evaluate the rule body relative to an environment that's formed by unifying the rule conclusion with the given query.\n\n268\n00:34:13,230 --> 00:34:21,630\nAnd the thing I want you to notice is the complete formal similarity to the net of circular evaluator or the substitution model.\n\n269\n00:34:21,630 --> 00:34:34,560\nTo apply a procedure, we evaluate the procedure body relative to an environment that's formed by blinding the procedure parameters to the arguments.\n\n270\n00:34:34,560 --> 00:34:43,650\nThere's a complete formal similarity here between the rules, rule application, and procedure application even though these things are very, very different.\n\n271\n00:34:43,650 --> 00:34:47,290\nAnd again, you have the EVAL APPLY loop.\n\n272\n00:34:47,290 --> 00:34:49,445\nEVAL and APPLY.\n\n273\n00:34:53,360 --> 00:35:08,660\nSo in general, I might be processing some combined expression that will turn into a rule application, which will generate some dictionaries or frames or environments-- whatever you want to call them-- from match, which will then be the input to some big compound thing like this.\n\n274\n00:35:08,660 --> 00:35:13,580\nThis has pieces of it and may have other rule applications.\n\n275\n00:35:13,580 --> 00:35:19,680\nAnd you have essentially the same cycle even though there's nothing here at all that looks like procedures.\n\n276\n00:35:19,680 --> 00:35:25,490\nIt really has to do with the fact you've built a language whose means of combination and abstraction unwind in certain ways.\n\n277\n00:35:28,770 --> 00:35:40,460\nAnd then in general, what happens at the very top level, you might have rules in your database also, so things in this database might be rules.\n\n278\n00:35:40,460 --> 00:35:42,920\nThere are ways to check that things are true.\n\n279\n00:35:42,920 --> 00:35:46,750\nSo it might come in here and have to do a rule check.\n\n280\n00:35:46,750 --> 00:35:53,350\nAnd then there's some control structure which says, well, you look at some rules, and you look at some data elements, and you look at some rules and data elements, and these fan out and out and out.\n\n281\n00:35:53,350 --> 00:36:00,245\nSo it becomes essentially impossible to say what order it's looking at these things in, whether it's breadth first or depth first or anything.\n\n282\n00:36:00,245 --> 00:36:11,270\nAnd it's even more impossible because the actual order is somehow buried in the delays of the streams. So what's very hard to tell from this is the order in which it's scanned.\n\n283\n00:36:11,270 --> 00:36:15,820\nBut what's true, because you're looking at the stream view, is that all of them eventually get looked at.\n\n284\n00:36:24,980 --> 00:36:28,150\nLet me just mention one tiny technical problem.\n\n285\n00:36:37,530 --> 00:36:45,780\nSuppose I tried saying boss of y is computer, then a funny thing would happen.\n\n286\n00:36:45,780 --> 00:37:01,580\nAs I stuck a dictionary with y in here, I might get-- this y is not the same as that y, which was the other piece of somebody's job description.\n\n287\n00:37:01,580 --> 00:37:10,930\nSo if I really only did literally what I said, we'd get some variable conflict problems. So I lied to you a little bit.\n\n288\n00:37:10,930 --> 00:37:14,360\nNotice that problem is exactly a problem we've run into before.\n\n289\n00:37:14,360 --> 00:37:20,505\nIt is precisely the need for local variables in a language.\n\n290\n00:37:20,505 --> 00:37:24,960\nWhen I have the sum of squares, that x had better not be that x.\n\n291\n00:37:24,960 --> 00:37:31,800\nThat's exactly the same as this y had better not be that y.\n\n292\n00:37:31,800 --> 00:37:33,100\nAnd we know how to solve that.\n\n293\n00:37:33,100 --> 00:37:37,710\nThat was this whole environment model, and we built chains of frames and all sorts of things like that.\n\n294\n00:37:37,710 --> 00:37:39,270\nThere's a much more brutal way to solve it.\n\n295\n00:37:39,270 --> 00:37:41,730\nIn the query language, we didn't even do that.\n\n296\n00:37:41,730 --> 00:37:43,540\nWe did something completely brutal.\n\n297\n00:37:43,540 --> 00:37:55,720\nWe said every time you apply a rule, rename consistently all the variables in the rule to some new unique names that won't conflict with anything.\n\n298\n00:37:55,720 --> 00:37:59,970\nThat's conceptually simpler, but really brutal and not particularly efficient.\n\n299\n00:37:59,970 --> 00:38:09,180\nBut notice, we could have gotten rid of all of our environment structures if we defined for procedures in Lisp the same thing.\n\n300\n00:38:09,180 --> 00:38:19,040\nIf every time we applied a procedure and did the substitution model we renamed all the variables in the procedure, then we never would have had to worry about local variables because they would never arise.\n\n301\n00:38:19,040 --> 00:38:25,610\nOK, well, that would be inefficient, and it's inefficient here in the query language, too, but we did it to keep it simple.\n\n302\n00:38:25,610 --> 00:38:26,860\nLet's break for questions.\n\n303\n00:38:30,880 --> 00:38:41,170\nAUDIENCE: When you started this section, you emphasized how powerful our APPLY EVAL model was that we could use it for any language.\n\n304\n00:38:41,170 --> 00:38:43,950\nAnd then you say we're going to have this language which is so different.\n\n305\n00:38:43,950 --> 00:38:47,880\nIt turns out that this language, as you just pointed out, is very much the same.\n\n306\n00:38:47,880 --> 00:38:57,030\nI'm wondering if you're arguing that all languages end up coming down to this you can apply a rule or apply a procedure or some kind of apply?\n\n307\n00:38:57,030 --> 00:39:14,880\nPROFESSOR: I would say that pretty much any language where you really are building up these means of combination and giving them simpler names and you're saying anything of the sort, like here's a general kind of expression, like how to square something, almost anything that you would call a procedure.\n\n308\n00:39:14,880 --> 00:39:18,020\nIf that's got to have parts, you have to unwind those parts.\n\n309\n00:39:18,020 --> 00:39:31,720\nYou have to have some kind of organization which says when I look at the abstract variables or tags or whatever you want to call them that might stand for particular things, you have to keep track of that, and that's going to be something like an environment.\n\n310\n00:39:31,720 --> 00:39:37,440\nAnd then if you say this part can have parts which I have to unwind, you've got to have something like this cycle.\n\n311\n00:39:39,970 --> 00:39:45,590\nAnd lots and lots of languages have that character when they sort of get put together in this way.\n\n312\n00:39:45,590 --> 00:39:50,690\nThis language again really is different because there's nothing like procedures on the outside.\n\n313\n00:39:50,690 --> 00:39:54,870\nWhen you go below the surface and you see the implementation, of course, it starts looking the same.\n\n314\n00:39:54,870 --> 00:39:56,950\nBut from the outside, it's a very different world view.\n\n315\n00:39:56,950 --> 00:39:58,650\nYou're not computing functions of inputs.\n\n316\n00:40:03,970 --> 00:40:15,495\nAUDIENCE: You mentioned earlier that when you build all of these rules in pattern matcher and with the delayed action of streams, you really have no way to know in what order things are evaluated.\n\n317\n00:40:15,495 --> 00:40:15,940\nPROFESSOR: Right.\n\n318\n00:40:15,940 --> 00:40:23,950\nAUDIENCE: And that would indicate then that you should only express declarative knowledge that's true for all-time, no-time sequence built into it.\n\n319\n00:40:23,950 --> 00:40:28,490\nOtherwise, these things get all-- PROFESSOR: Yes.\n\n320\n00:40:28,490 --> 00:40:28,820\nYes.\n\n321\n00:40:28,820 --> 00:40:40,830\nThe question is this really is set up for doing declarative knowledge, and as I presented it-- and I'll show you some of the ugly warts under this after the break.\n\n322\n00:40:40,830 --> 00:40:43,070\nAs I presented it, it's just doing logic.\n\n323\n00:40:43,070 --> 00:40:48,840\nAnd in principle, if it were logic, it wouldn't matter what order it's getting done.\n\n324\n00:40:48,840 --> 00:41:01,290\nAnd it's quite true when you start doing things where you have side effects like adding things to the database and taking things out, and we'll see some others, you use that kind of control.\n\n325\n00:41:01,290 --> 00:41:02,940\nSo, for example, contrasting with Prolog.\n\n326\n00:41:02,940 --> 00:41:09,640\nSay Prolog has various features where you really exploit the order of evaluation.\n\n327\n00:41:09,640 --> 00:41:11,770\nAnd people write Prolog programs that way.\n\n328\n00:41:11,770 --> 00:41:18,590\nThat turns out to be very complicated in Prolog, although if you're an expert Prolog programmer, you can do it.\n\n329\n00:41:18,590 --> 00:41:20,210\nHowever, here I don't think you can do it at all.\n\n330\n00:41:20,210 --> 00:41:27,150\nIt's very complicated because you really are giving up control over any prearranged order of trying things.\n\n331\n00:41:27,150 --> 00:41:30,670\nAUDIENCE: Now, that would indicate then that you have a functional mapping.\n\n332\n00:41:30,670 --> 00:41:38,810\nAnd when you started out this lecture, you said that we express the declarative knowledge which is a relation, and we don't talk about the inputs and the outputs.\n\n333\n00:41:41,390 --> 00:41:43,370\nPROFESSOR: Well, there's a pun on functional, right?\n\n334\n00:41:43,370 --> 00:41:48,700\nThere's function in the sense of no side effects and not depending on what order is going on.\n\n335\n00:41:48,700 --> 00:41:52,220\nAnd then there's functional in the sense of mathematical function, which means input and output.\n\n336\n00:41:52,220 --> 00:41:56,510\nAnd it's just that pun that you're making, I think.\n\n337\n00:41:56,510 --> 00:42:01,270\nAUDIENCE: I'm a little unclear on what you're doing with these two statements, the two boss statements.\n\n338\n00:42:01,270 --> 00:42:12,440\nIs the first one building up the database and the second one a query or-- PROFESSOR: OK, I'm sorry.\n\n339\n00:42:12,440 --> 00:42:19,470\nWhat I meant here, if I type something like this in as a query-- I should have given an example way at the very beginning.\n\n340\n00:42:19,470 --> 00:42:34,220\nIf I type in job, Ben Bitdiddle, computer wizard, what the processing will do is if it finds a match, it'll find a match to that exact thing, and it'll type out a job, Ben Bitdiddle, computer wizard.\n\n341\n00:42:34,220 --> 00:42:37,400\nIf it doesn't find a match, it won't find anything.\n\n342\n00:42:37,400 --> 00:42:50,680\nSo what I should have said is the way you use the query language to check whether something is true, remember, that's one of the things you want to do in logic programming, is you type in your query and either that comes out or it doesn't.\n\n343\n00:42:50,680 --> 00:42:57,480\nSo what I was trying to illustrate here, I wanted to start with a very simple example before talking about unifiers.\n\n344\n00:42:57,480 --> 00:43:07,830\nSo what I should have said, if I just wanted to check whether this is true, I could type that in and see if anything came out AUDIENCE: And then the second one-- PROFESSOR: The second one would be a real query.\n\n345\n00:43:07,830 --> 00:43:10,770\nAUDIENCE: A real query, yeah.\n\n346\n00:43:10,770 --> 00:43:19,560\nPROFESSOR: What would come out, see, it would go in here say with FOO, and in would go frame that says z is bound to who and d is bound to computer.\n\n347\n00:43:19,560 --> 00:43:23,250\nAnd this will pass through, and then by the time it got out of here, who would pick up a binding.\n\n348\n00:43:26,950 --> 00:43:36,460\nAUDIENCE: On the unifying thing there, I still am not sure what happens with who and z.\n\n349\n00:43:36,460 --> 00:43:46,260\nIf the unifying-- the rule here says--  OK, so you say that you can't make question mark equal to question mark who.\n\n350\n00:43:46,260 --> 00:43:46,410\nPROFESSOR: Right.\n\n351\n00:43:46,410 --> 00:43:48,360\nThat's what the matcher can't do.\n\n352\n00:43:48,360 --> 00:43:53,800\nBut what this will mean to a unifier is that there's an environment with three variables.\n\n353\n00:43:56,690 --> 00:43:58,520\nd here is computer.\n\n354\n00:43:58,520 --> 00:44:01,830\nz is whatever who is.\n\n355\n00:44:01,830 --> 00:44:18,360\nSo if later on in the matcher routine it said, for example, who has to be 3, then when I looked up in the dictionary, it will say, oh, z is 3 because it's the same as who.\n\n356\n00:44:18,360 --> 00:44:22,640\nAnd that's in some sense the only thing you need to do to extend the unifier to a matcher.\n\n357\n00:44:22,640 --> 00:44:29,770\nAUDIENCE: OK, because it looked like when you were telling how to unify it, it looked like you would put the things together in such a way that you'd actually solve and have a value for both of them.\n\n358\n00:44:29,770 --> 00:44:34,860\nAnd what it looks like now is that you're actually pass a dictionary with two variables and the variables are linked.\n\n359\n00:44:34,860 --> 00:44:35,130\nPROFESSOR: Right.\n\n360\n00:44:35,130 --> 00:44:40,540\nIt only looks like you're solving for both of them because you're sort of looking at the whole solution at once.\n\n361\n00:44:40,540 --> 00:44:44,980\nIf you sort of watch the thing getting built up recursively, it's merely this.\n\n362\n00:44:44,980 --> 00:44:48,400\nAUDIENCE: OK, so you do pass off that dictionary with two variables?\n\n363\n00:44:48,400 --> 00:44:49,110\nPROFESSOR: That's right.\n\n364\n00:44:49,110 --> 00:44:50,190\nAUDIENCE: And link?\n\n365\n00:44:50,190 --> 00:44:50,560\nPROFESSOR: Right.\n\n366\n00:44:50,560 --> 00:44:54,055\nIt just looks like an ordinary dictionary.\n\n367\n00:44:54,055 --> 00:45:04,725\nAUDIENCE: When you're talking about the unifier, is it that there are some cases or some points that you are not able to use by them?\n\n368\n00:45:04,725 --> 00:45:05,220\nPROFESSOR: Right.\n\n369\n00:45:05,220 --> 00:45:18,540\nAUDIENCE: Can you just by building the rules or writing the forms know in advance if you are going to be able to solve to get the unification or not?\n\n370\n00:45:18,540 --> 00:45:30,090\nCan you add some properties either to the rules itself or to the formula that you're writing so that you avoid the problem of not finding unification?\n\n371\n00:45:30,090 --> 00:45:35,390\nPROFESSOR: I mean, you can agree, I think, to write in a fairly restricted way where you won't run into it.\n\n372\n00:45:35,390 --> 00:45:55,300\nSee, because what you're getting-- see, the place where you get into problems is when you-- well, again, you're trying to match things like that against things where these have structure, where a, y, b, y something.\n\n373\n00:45:58,980 --> 00:46:03,070\nSo this is the kind of place where you're going to get into trouble.\n\n374\n00:46:03,070 --> 00:46:06,370\nAUDIENCE: So you can do that syntactically?\n\n375\n00:46:06,370 --> 00:46:11,561\nPROFESSOR: So you can kind of watch your rules in the kinds of things that your writing.\n\n376\n00:46:11,561 --> 00:46:16,310\nAUDIENCE: So that's the problem that the builder of the database has to be concerned?\n\n377\n00:46:16,310 --> 00:46:17,560\nPROFESSOR: That's a problem.\n\n378\n00:46:19,930 --> 00:46:25,800\nIt's a problem either-- not quite the builder of the database, the person who is expressing the rules, or the builder of the database.\n\n379\n00:46:25,800 --> 00:46:34,940\nWhat the unifier actually does is you can check at the next level down when you actually get to the unifier and you'll see in the code where it looks up in the dictionary.\n\n380\n00:46:34,940 --> 00:46:37,260\nIf it sort of says what does y have to be?\n\n381\n00:46:37,260 --> 00:46:41,960\nOh, does y have to be something that contains a y as its expression?\n\n382\n00:46:41,960 --> 00:46:46,240\nAt that point, the unifier and say, oh my God, I'm trying to solve a fixed-point equation.\n\n383\n00:46:46,240 --> 00:46:49,220\nI'll give it up here.\n\n384\n00:46:49,220 --> 00:46:51,910\nAUDIENCE: You make the distinction between the rules in the database.\n\n385\n00:46:51,910 --> 00:46:56,950\nAre the rules added to the database?\n\n386\n00:46:56,950 --> 00:46:57,870\nPROFESSOR: Yes.\n\n387\n00:46:57,870 --> 00:46:58,870\nYes, I should have said that.\n\n388\n00:46:58,870 --> 00:47:03,890\nOne way to think about rules is that they're just other things in the database.\n\n389\n00:47:03,890 --> 00:47:09,445\nSo if you want to check the things that have to be checked in the database, they're kind of virtual facts that are in the database.\n\n390\n00:47:09,445 --> 00:47:18,230\nAUDIENCE: But in that explanation, you made the differentiation between database and the rules itself.\n\n391\n00:47:18,230 --> 00:47:20,490\nPROFESSOR: Yeah, I probably should not have done that.\n\n392\n00:47:20,490 --> 00:47:23,540\nThe only reason to do that is in terms of the implementation.\n\n393\n00:47:23,540 --> 00:47:30,470\nWhen you look at the implementation, there's a part which says check either primitive assertions in the database or check rules.\n\n394\n00:47:30,470 --> 00:47:44,600\nAnd then the real reason why you can't tell what order things are going to come out in and is that the rules database and the data database sort of get merged in a kind of delayed evaluation way.\n\n395\n00:47:44,600 --> 00:47:46,320\nAnd so that's what makes the order very complicated.\n\n396\n00:47:55,440 --> 00:47:56,690\nOK, let's break.\n\n397\n00:48:33,160 --> 00:48:37,230\nWe've just seen how the logic language works and how rules work.\n\n398\n00:48:37,230 --> 00:48:40,120\nNow, let's turn to a more profound question.\n\n399\n00:48:40,120 --> 00:48:43,180\nWhat do these things mean?\n\n400\n00:48:43,180 --> 00:48:53,570\nThat brings us to the subtlest, most devious part of this whole query language business, and that is that it's not quite what it seems to be.\n\n401\n00:48:53,570 --> 00:49:07,690\nAND and OR and NOT and the logical implication of rules are not really the AND and OR and NOT and logical implication of logic.\n\n402\n00:49:07,690 --> 00:49:09,910\nLet me give you an example of that.\n\n403\n00:49:09,910 --> 00:49:30,100\nCertainly, if we have two things in logic, it ought to be the case that AND of P and Q is the same as AND of Q and P and that OR of P and Q is the same as OR of Q and P. But let's look here.\n\n404\n00:49:30,100 --> 00:49:32,180\nHere's an example.\n\n405\n00:49:32,180 --> 00:49:40,140\nLet's talk about somebody outranking somebody else in our little database organization.\n\n406\n00:49:40,140 --> 00:49:55,640\nWe'll say s is outranked by b or if either the supervisor of this is b or there's some middle manager here, that supervisor of s is m, and m is outranked by b.\n\n407\n00:49:59,830 --> 00:50:02,310\nSo there's one way to define rule outranked by.\n\n408\n00:50:02,310 --> 00:50:11,630\nOr we can write exactly the same thing, except at the bottom here, we reversed the order of these two clauses.\n\n409\n00:50:11,630 --> 00:50:16,690\nAnd certainly if this were logic, those ought to mean the same thing.\n\n410\n00:50:16,690 --> 00:50:34,110\nHowever, in our particular implementation, if you say something like who's outranked by Ben Bitdiddle, what you'll find is that this rule will work perfectly well and generate answers, whereas this rule will go into an infinite loop.\n\n411\n00:50:34,110 --> 00:50:39,400\nAnd the reason for that is that this will come in and say, oh, who's outranked by Ben Bitdiddle?\n\n412\n00:50:41,920 --> 00:50:50,330\nFind an s which is outranked by b, where b is Ben Bitdiddle, which is going to happen in it a subproblem.\n\n413\n00:50:50,330 --> 00:50:58,560\nOh gee, find an m such as m is outranked by Ben Bitdiddle with no restrictions on m.\n\n414\n00:50:58,560 --> 00:51:04,570\nSo this will say in order to solve this problem, I solve exactly the same problem.\n\n415\n00:51:04,570 --> 00:51:08,000\nAnd then after I've solved that, I'll check for a supervisory relationship.\n\n416\n00:51:08,000 --> 00:51:15,260\nWhereas this one won't get into that, because before it tries to find this outranked by, it'll already have had a restriction on m here.\n\n417\n00:51:18,560 --> 00:51:22,860\nSo these two things which ought to mean the same, in fact, one goes into an infinite loop.\n\n418\n00:51:22,860 --> 00:51:26,720\nOne does not.\n\n419\n00:51:26,720 --> 00:51:42,240\nThat's a very extreme case of a general thing that you'll find in logic programming that if you start changing the order of the things in the ANDs or ORs, you'll find tremendous differences in efficiency.\n\n420\n00:51:42,240 --> 00:51:47,110\nAnd we just saw an infinitely big difference in efficiency and an infinite loop.\n\n421\n00:51:49,190 --> 00:51:54,070\nAnd there are similar things having to do with the order in which you enter rules.\n\n422\n00:51:54,070 --> 00:52:03,840\nThe order in which it happens to look at rules in the database may vastly change the efficiency with which it gets out answers or, in fact, send it into an infinite loop for some orderings.\n\n423\n00:52:03,840 --> 00:52:10,950\nAnd this whole thing has to do with the fact that you're checking these rules in some order.\n\n424\n00:52:10,950 --> 00:52:15,180\nAnd some rules may lead to really long paths of implication.\n\n425\n00:52:15,180 --> 00:52:16,440\nOthers might not.\n\n426\n00:52:16,440 --> 00:52:19,300\nAnd you don't know a priori which ones are good and which ones are bad.\n\n427\n00:52:19,300 --> 00:52:26,970\nAnd there's a whole bunch of research having to do with that, mostly having to do with thinking about making parallel implementations of logic programming languages.\n\n428\n00:52:26,970 --> 00:52:32,620\nAnd in some sense, what you'd like to do is check all rules in parallel and whichever ones get answers, you bubble them up.\n\n429\n00:52:32,620 --> 00:52:40,550\nAnd if some go down infinite deductive changed, well, you just-- you know, memory is cheap and processors are cheap, and you just let them buzz for as for as long as you want.\n\n430\n00:52:43,510 --> 00:52:50,870\nThere's a deeper problem, though, in comparing this logic language to real logic.\n\n431\n00:52:50,870 --> 00:52:58,370\nThe example I just showed you, it went into an infinite loop maybe, but at least it didn't give the wrong answer.\n\n432\n00:52:58,370 --> 00:53:09,490\nThere's an actual deeper problem when we start comparing, seriously comparing this logic language with real classical logic.\n\n433\n00:53:09,490 --> 00:53:14,030\nSo let's sort of review real classical logic.\n\n434\n00:53:14,030 --> 00:53:22,140\nAll humans are mortal.\n\n435\n00:53:22,140 --> 00:53:24,390\nThat's pretty classical logic.\n\n436\n00:53:24,390 --> 00:53:29,120\nThen maybe we'll continue in the very best classical tradition.\n\n437\n00:53:29,120 --> 00:53:32,740\nWe'll say all-- let's make it really classical.\n\n438\n00:53:32,740 --> 00:53:48,060\nAll Greeks are human, which has the syllogism that Socrates is a Greek.\n\n439\n00:53:48,060 --> 00:53:49,210\nAnd then what do you write here?\n\n440\n00:53:49,210 --> 00:53:51,890\nI think three dots, classical logic.\n\n441\n00:53:51,890 --> 00:54:01,360\nTherefore, then the syllogism, Socrates is mortal.\n\n442\n00:54:01,360 --> 00:54:05,880\nSo there's some real honest classical logic.\n\n443\n00:54:05,880 --> 00:54:12,570\nLet's compare that with our classical logic database.\n\n444\n00:54:12,570 --> 00:54:16,270\nSo here's a classical logic database.\n\n445\n00:54:16,270 --> 00:54:18,030\nSocrates is a Greek.\n\n446\n00:54:18,030 --> 00:54:19,600\nPlato is a Greek.\n\n447\n00:54:19,600 --> 00:54:24,120\nZeus is a Greek, and Zeus is a god.\n\n448\n00:54:24,120 --> 00:54:30,780\nAnd all humans are mortal.\n\n449\n00:54:30,780 --> 00:54:34,650\nTo show that something is mortal, it's enough to show that it's human.\n\n450\n00:54:34,650 --> 00:54:35,900\nAll humans are fallible.\n\n451\n00:54:38,900 --> 00:54:40,980\nAnd all Greeks are humans is not quite right.\n\n452\n00:54:40,980 --> 00:54:45,920\nThis says that all Greeks who are not gods are human.\n\n453\n00:54:45,920 --> 00:54:49,320\nSo to show something's human, it's enough to show it's a Greek and not a god.\n\n454\n00:54:49,320 --> 00:54:54,470\nAnd the address of any Greek god is Mount Olympus.\n\n455\n00:54:54,470 --> 00:54:57,390\nSo there's a little classical logic database.\n\n456\n00:54:57,390 --> 00:54:59,490\nAnd indeed, that would work fairly well.\n\n457\n00:54:59,490 --> 00:55:06,910\nIf we type that in and say is Socrates mortal or Socrates fallible or mortal?\n\n458\n00:55:06,910 --> 00:55:07,690\nIt'll say yes.\n\n459\n00:55:07,690 --> 00:55:09,710\nIs Plato mortal and fallible.\n\n460\n00:55:09,710 --> 00:55:10,680\nIt'll say yes.\n\n461\n00:55:10,680 --> 00:55:12,210\nIf we say is Zeus mortal?\n\n462\n00:55:12,210 --> 00:55:14,900\nIt won't find anything.\n\n463\n00:55:14,900 --> 00:55:16,640\nAnd it'll work perfectly well.\n\n464\n00:55:16,640 --> 00:55:20,120\nHowever, suppose we want to extend this.\n\n465\n00:55:20,120 --> 00:55:25,070\nLet's define what it means for someone to be a perfect being.\n\n466\n00:55:25,070 --> 00:55:27,020\nLet's say rule: a perfect being.\n\n467\n00:55:34,050 --> 00:55:35,480\nAnd I think this is right.\n\n468\n00:55:35,480 --> 00:55:44,100\nIf you're up on your medieval scholastic philosophy, I believe that perfect beings are ones who were neither mortal nor fallible.\n\n469\n00:55:44,100 --> 00:55:59,300\nAND NOT mortal x, NOT fallible x.\n\n470\n00:55:59,300 --> 00:56:05,790\nSo we'll define this system to teach it what a perfect being is.\n\n471\n00:56:05,790 --> 00:56:11,750\nAnd now what we're going to do is he ask for the address of all the perfect beings.\n\n472\n00:56:11,750 --> 00:56:23,680\nAND the address of x is y and x is perfect.\n\n473\n00:56:23,680 --> 00:56:33,830\nAnd so what we're generating here is the world's most exclusive mailing list. For the address of all the perfect things, we might have typed this in.\n\n474\n00:56:33,830 --> 00:56:36,240\nOr we might type in this.\n\n475\n00:56:36,240 --> 00:56:52,140\nWe'll say AND perfect of x and the address of x is y.\n\n476\n00:56:52,140 --> 00:56:55,190\nWell, suppose we type all that in and we try this query.\n\n477\n00:56:55,190 --> 00:56:57,650\nThis query is going to give us an answer.\n\n478\n00:56:57,650 --> 00:56:59,745\nThis query will say, yeah, Mount Olympus.\n\n479\n00:57:04,230 --> 00:57:06,740\nThis query, in fact, is going to give us nothing.\n\n480\n00:57:06,740 --> 00:57:11,640\nIt will say no addresses of perfect beings.\n\n481\n00:57:11,640 --> 00:57:12,510\nNow, why is that?\n\n482\n00:57:12,510 --> 00:57:14,230\nWhy is there a difference?\n\n483\n00:57:14,230 --> 00:57:15,690\nThis is not an infinite loop question.\n\n484\n00:57:15,690 --> 00:57:19,145\nThis is a different answer question.\n\n485\n00:57:19,145 --> 00:57:25,880\nThe reason is that if you remember the implementation of NOT, NOT acted as a filter.\n\n486\n00:57:25,880 --> 00:57:36,520\nNOT said I'm going to take some possible dictionaries, some possible frames, some possible answers, and filter out the ones that happened to satisfy some condition, and that's how I implement NOT.\n\n487\n00:57:36,520 --> 00:57:47,720\nIf you think about what's going on here, I'll build this query box where the output of an address piece gets fed into a perfect piece.\n\n488\n00:57:50,290 --> 00:57:55,290\nWhat will happen is the address piece will set up some things of everyone whose address I know.\n\n489\n00:57:55,290 --> 00:57:59,880\nThose will get filtered by the NOTs inside perfect here.\n\n490\n00:57:59,880 --> 00:58:04,910\nSo it will throw out the ones which happened to be either mortal or fallible.\n\n491\n00:58:04,910 --> 00:58:09,520\nIn the other order what happens is I set this up, started up with an empty frame.\n\n492\n00:58:09,520 --> 00:58:13,920\nThe perfect in here doesn't find anything for the NOTs to filter, so nothing comes out here at all.\n\n493\n00:58:18,830 --> 00:58:21,940\nAnd there's sort of nothing there that gets fed into the address thing.\n\n494\n00:58:21,940 --> 00:58:24,260\nSo here, I don't get an answer.\n\n495\n00:58:24,260 --> 00:58:27,440\nAnd again, the reason for that is NOT isn't generating anything.\n\n496\n00:58:27,440 --> 00:58:28,800\nNOT's only throwing out things.\n\n497\n00:58:28,800 --> 00:58:32,020\nAnd if I never started up with anything, there's nothing for it to throw out.\n\n498\n00:58:32,020 --> 00:58:33,770\nSo out of this thing, I get the wrong answer.\n\n499\n00:58:37,200 --> 00:58:37,970\nHow can you fix that?\n\n500\n00:58:37,970 --> 00:58:39,070\nWell, there are ways to fix that.\n\n501\n00:58:39,070 --> 00:58:41,410\nSo you might say, well, that's sort of stupid.\n\n502\n00:58:41,410 --> 00:58:44,900\nWhy are you just doing all your NOT stuff at the beginning?\n\n503\n00:58:44,900 --> 00:58:58,560\nThe right way to implement NOT is to realize that when you have conditions like NOT, you should generate all your answers first, and then with each of these dictionaries pass along until at the very end I'll do filtering.\n\n504\n00:58:58,560 --> 00:59:04,050\nAnd there are implementations of logic languages that work like that that solve this particular problem.\n\n505\n00:59:06,660 --> 00:59:12,530\nHowever, there's a more profound problem, which is which one of these is the right answer?\n\n506\n00:59:12,530 --> 00:59:15,320\nIs it Mount Olympus or is it nothing?\n\n507\n00:59:15,320 --> 00:59:24,805\nSo you might say it's Mount Olympus, because after all, Zeus is in that database, and Zeus was neither mortal nor fallible.\n\n508\n00:59:29,550 --> 00:59:44,120\nSo you might say Zeus wants to satisfy NOT mortal Zeus or NOT fallible Zeus.\n\n509\n00:59:44,120 --> 00:59:47,638\nBut let's actually look at that database.\n\n510\n00:59:47,638 --> 00:59:49,320\nLet's look at it.\n\n511\n00:59:49,320 --> 00:59:54,810\nThere's no way-- how does it know that Zeus is not fallible?\n\n512\n00:59:54,810 --> 00:59:57,930\nThere's nothing in there about that.\n\n513\n00:59:57,930 --> 00:59:59,410\nWhat's in there is that humans are fallible.\n\n514\n01:00:02,390 --> 01:00:04,430\nHow does it know that Zeus is not mortal?\n\n515\n01:00:04,430 --> 01:00:07,980\nThere's nothing in there about that.\n\n516\n01:00:07,980 --> 01:00:16,690\nIt just said I don't have any rule, which-- the only way I can deduce something's mortal is if it's human, and that's all it really knows about mortal.\n\n517\n01:00:16,690 --> 01:00:25,300\nAnd in fact, if you remember your classical mythology, you know that the Greek gods were not mortal but fallible.\n\n518\n01:00:25,300 --> 01:00:30,850\nSo the answer is not in the rules there.\n\n519\n01:00:30,850 --> 01:00:32,100\nSee, why does it deduce that?\n\n520\n01:00:34,710 --> 01:00:40,080\nSee, Socrates would certainly not have made this error of logic.\n\n521\n01:00:40,080 --> 01:00:43,370\nWhat NOT needs in this language is not NOT.\n\n522\n01:00:43,370 --> 01:00:44,930\nIt's not the NOT of logic.\n\n523\n01:00:44,930 --> 01:00:55,140\nWhat NOT needs in this language is not deducible from things in the database as opposed to not true.\n\n524\n01:00:55,140 --> 01:00:57,300\nThat's a very big difference.\n\n525\n01:00:57,300 --> 01:00:59,250\nSubtle, but big.\n\n526\n01:00:59,250 --> 01:01:04,610\nSo, in fact, this is perfectly happy to say not anything that it doesn't know about.\n\n527\n01:01:04,610 --> 01:01:07,830\nSo if you ask it is it not true that Zeus likes chocolate ice cream?\n\n528\n01:01:07,830 --> 01:01:10,251\nIt will say sure, it's not true.\n\n529\n01:01:10,251 --> 01:01:12,850\nOr anything else or anything it doesn't know about.\n\n530\n01:01:12,850 --> 01:01:18,280\nNOT means not deducible from the things you've told me.\n\n531\n01:01:18,280 --> 01:01:27,050\nIn a world where you're identifying not deducible with, in fact, not true, this is called the closed world assumption.\n\n532\n01:01:36,870 --> 01:01:38,320\nThe closed world assumption.\n\n533\n01:01:38,320 --> 01:01:46,500\nAnything that I cannot deduce from what I know is not true, right?\n\n534\n01:01:46,500 --> 01:01:49,290\nIf I don't know anything about x, the x isn't true.\n\n535\n01:01:49,290 --> 01:01:51,420\nThat's very dangerous.\n\n536\n01:01:51,420 --> 01:01:54,480\nFrom a logical point of view, first of all, it doesn't really makes sense.\n\n537\n01:01:54,480 --> 01:02:00,240\nBecause if I don't know anything about x, I'm willing to say not x.\n\n538\n01:02:00,240 --> 01:02:03,850\nBut am I willing to say not not x?\n\n539\n01:02:03,850 --> 01:02:06,470\nWell, sure, I don't know anything about that either maybe.\n\n540\n01:02:06,470 --> 01:02:15,970\nSo not not x is not necessarily the same as x and so on and so on and so on, so there's some sort of funny bias in there.\n\n541\n01:02:15,970 --> 01:02:17,290\nSo that's sort of funny.\n\n542\n01:02:17,290 --> 01:02:27,210\nThe second thing, if you start building up real reasoning programs based on this, think how dangerous that is.\n\n543\n01:02:27,210 --> 01:02:37,780\nYou're saying I know I'm in a position to deduce everything true that's relevant to this problem.\n\n544\n01:02:37,780 --> 01:02:48,860\nI'm reasoning, and built into my reasoning mechanism is the assumption that anything that I don't know can't possibly be relevant to this problem, right?\n\n545\n01:02:48,860 --> 01:02:54,720\nThere are a lot of big organizations that work like that, right?\n\n546\n01:02:54,720 --> 01:02:56,830\nMost corporate marketing divisions work like that.\n\n547\n01:02:56,830 --> 01:03:00,560\nYou know the consequences to that.\n\n548\n01:03:00,560 --> 01:03:12,600\nSo it's very dangerous to start really typing in these big logical implication systems and going on what they say, because they have this really limiting assumption built in.\n\n549\n01:03:12,600 --> 01:03:14,905\nSo you have to be very, very careful about that.\n\n550\n01:03:14,905 --> 01:03:16,560\nAnd that's a deep problem.\n\n551\n01:03:16,560 --> 01:03:23,840\nThat's not a problem about we can make a little bit cleverer implementation and do the filters and organize the infinite loops to make them go away.\n\n552\n01:03:23,840 --> 01:03:25,920\nIt's a different kind of problem.\n\n553\n01:03:25,920 --> 01:03:27,060\nIt's a different semantics.\n\n554\n01:03:27,060 --> 01:03:50,560\nSo I think to wrap this up, it's fair to say that logic programming I think is a terrifically exciting idea, the idea that you can bridge this gap from the imperative to the declarative, that you can start talking about relations and really get tremendous power by going above the abstraction of what's my input and what's my output.\n\n555\n01:03:50,560 --> 01:03:58,080\nAnd linked to logic, the problem is it's a goal that I think has yet to be realized.\n\n556\n01:03:58,080 --> 01:04:09,460\nAnd probably one of the very most interesting research questions going on now in languages is how do you somehow make a real logic language?\n\n557\n01:04:09,460 --> 01:04:18,680\nAnd secondly, how do you bridge the gap from this world of logic and relations to the worlds of more traditional languages and somehow combine the power of both.\n\n558\n01:04:18,680 --> 01:04:19,930\nOK, let's break.\n\n559\n01:04:23,750 --> 01:04:27,430\nAUDIENCE: Couldn't you solve that last problem by having the extra rules that imply it?\n\n560\n01:04:27,430 --> 01:04:32,210\nThe problem here is you have the definition of something, but you don't have the definition of its opposite.\n\n561\n01:04:32,210 --> 01:04:40,370\nIf you include in the database something that says something implies mortal x, something else implies not mortal x, haven't you basically solved the problem?\n\n562\n01:04:43,370 --> 01:04:46,910\nPROFESSOR: But the issue is do you put a finite number of those in?\n\n563\n01:04:50,740 --> 01:04:57,220\nAUDIENCE: If things are specified always in pairs-- PROFESSOR: But the impression is then what do you do about deduction?\n\n564\n01:05:00,200 --> 01:05:03,400\nYou can't specify NOTs.\n\n565\n01:05:03,400 --> 01:05:07,960\nBut the problem is, in a big system, it turns out that might not be a finite number of things.\n\n566\n01:05:12,820 --> 01:05:15,290\nThere are also sort of two issues.\n\n567\n01:05:15,290 --> 01:05:16,690\nPartly it might not be finite.\n\n568\n01:05:16,690 --> 01:05:21,510\nPartly it might be that's not what you want.\n\n569\n01:05:21,510 --> 01:05:25,120\nSo a good example would be suppose I want to do connectivity.\n\n570\n01:05:25,120 --> 01:05:28,050\nI want a reason about connectivity.\n\n571\n01:05:28,050 --> 01:05:35,480\nAnd I'm going to tell you there's four things: a and b and c and d.\n\n572\n01:05:35,480 --> 01:05:43,200\nAnd I'll tell you a is connected to b and c's connected to d.\n\n573\n01:05:43,200 --> 01:05:45,260\nAnd now I'll tell you is a connected to d?\n\n574\n01:05:45,260 --> 01:05:46,780\nThat's the question.\n\n575\n01:05:46,780 --> 01:05:50,610\nThere's an example where I would like something like the closed world assumption.\n\n576\n01:05:54,200 --> 01:06:01,340\nThat's a tiny toy, but a lot of times, I want to be able to say something like anything that I haven't told you, assume is not true.\n\n577\n01:06:04,260 --> 01:06:09,470\nSo it's not as simple as you only want to put in explicit NOTs all over the place.\n\n578\n01:06:09,470 --> 01:06:14,150\nIt's that sometimes it really isn't clear what you even want.\n\n579\n01:06:14,150 --> 01:06:20,960\nThat having to specify both everything and not everything is too precise, and then you get down into problems there.\n\n580\n01:06:20,960 --> 01:06:26,510\nBut there are a lot of approaches that explicitly put in NOTs and reason based on that.\n\n581\n01:06:26,510 --> 01:06:28,070\nSo it's a very good idea.\n\n582\n01:06:28,070 --> 01:06:33,490\nIt's just that then it starts becoming a little cumbersome in the very large problems you'd like to use.\n\n583\n01:06:43,460 --> 01:06:53,840\nAUDIENCE: I'm not sure how directly related to the argument this is, but one of your points was that one of the dangers of the closed rule is you never really know all the things that are there.\n\n584\n01:06:53,840 --> 01:06:55,930\nYou never really know all the parts to it.\n\n585\n01:06:55,930 --> 01:06:58,160\nIsn't that a major problem with any programming?\n\n586\n01:06:58,160 --> 01:07:07,390\nI always write programs where I assume that I've got all the cases, and so I check for them all or whatever, and somewhere down the road, I find out that I didn't check for one of them.\n\n587\n01:07:07,390 --> 01:07:08,540\nPROFESSOR: Well, sure, it's true.\n\n588\n01:07:08,540 --> 01:07:19,600\nBut the problem here is it's that assumption which is the thing that you're making if you believe you're identifying this with logic.\n\n589\n01:07:19,600 --> 01:07:20,510\nSo you're quite right.\n\n590\n01:07:20,510 --> 01:07:22,220\nIt's a situation you're never in.\n\n591\n01:07:22,220 --> 01:07:33,470\nThe problem is if you're starting to believe that what this is doing is logic and you look at the rules you write down and say what can I deduce from them, you have to be very careful to remember that NOT means something else.\n\n592\n01:07:33,470 --> 01:07:39,030\nAnd it means something else based on an assumption which is probably not true.\n\n593\n01:07:39,030 --> 01:07:47,990\nAUDIENCE: Do I understand you correctly that you cannot fix this problem without killing off all possibilities of inference through altering NOT?\n\n594\n01:07:47,990 --> 01:07:49,370\nPROFESSOR: No, that's not quite right.\n\n595\n01:07:49,370 --> 01:07:56,340\nThere are other--  there are ways to do logic with real NOTs.\n\n596\n01:07:56,340 --> 01:07:58,540\nThere are actually ways to do that.\n\n597\n01:07:58,540 --> 01:08:01,610\nBut they're very inefficient as far as anybody knows.\n\n598\n01:08:01,610 --> 01:08:11,980\nAnd they're much more--  the, quote, inference in here is built into this unifier and this pattern matching unification algorithm.\n\n599\n01:08:11,980 --> 01:08:16,590\nThere are ways to automate real logical reasoning.\n\n600\n01:08:16,590 --> 01:08:23,850\nBut it's not based on that, and logic programming languages don't tend to do that because it's very inefficient as far as anybody knows.\n\n601\n01:08:29,390 --> 01:08:30,640\nAll right, thank you.\n\n"
  },
  {
    "path": "SrtCN/lec8b.srt",
    "content": "﻿1\n00:00:00,000 --> 00:00:02,144\nLearning-SICP 学习小组\n倾情制作\n\n2\n00:00:02,400 --> 00:00:05,600\n《计算机程序的构造和解释》\n\n3\n00:00:18,910 --> 00:00:21,792\n我们已经了解了查询语言的使用方式\nPROFESSOR: All right, well, we've seen how the query language works.\n\n4\n00:00:22,640 --> 00:00:25,072\n现在该来讨论如何实现了\nNow, let's talk about how it's implemented.\n\n5\n00:00:26,280 --> 00:00:27,984\n你们也应该能够猜到\nYou already pretty much can guess\n\n6\n00:00:28,592 --> 00:00:29,470\n它其中的原理了\nwhat's going on there.\n\n7\n00:00:29,470 --> 00:00:31,648\n它的最底层是一个模式匹配器\nAt the bottom of it, there's a pattern matcher.\n\n8\n00:00:32,810 --> 00:00:34,256\n我们在《基于规则的控制语言》一课中\nAnd we looked at a pattern matcher\n\n9\n00:00:34,672 --> 00:00:36,944\n已经介绍过模式匹配器了\nwhen we did the rule-based control language.\n\n10\n00:00:38,110 --> 00:00:40,592\n我举个例子来让你们温习一下\nJust to remind you, here are some sample patterns.\n\n11\n00:00:41,520 --> 00:00:43,680\n这个模式会匹配\nThis is a pattern that will match\n\n12\n00:00:43,808 --> 00:00:44,928\n一个含有三个元素的表\nany list of three things\n\n13\n00:00:44,960 --> 00:00:47,104\n其中 首元素为A\nwhich the first is a\n\n14\n00:00:47,168 --> 00:00:48,336\n其次是C\nthe second is c\n\n15\n00:00:48,480 --> 00:00:50,192\n而中间可以为任意元素\nand the middle one can be anything.\n\n16\n00:00:50,650 --> 00:00:52,272\n所以在这个小型的模式匹配语言中\nSo in this little pattern-matching syntax,\n\n17\n00:00:52,304 --> 00:00:54,050\n你只能区分一种类型\nthere's only one distinction you make.\n\n18\n00:00:54,050 --> 00:00:57,200\n也就是区分字面量或者变量\nThere's either literal things or variables,\n\n19\n00:00:57,232 --> 00:00:58,864\n以问号开头的就是变量\nand variables begin with question mark.\n\n20\n00:01:01,370 --> 00:01:03,648\n因此这个模式会匹配任意的三元表\nSo this matches any list of three things\n\n21\n00:01:04,448 --> 00:01:06,500\n只要它的首元素为A 而第三个元素为C\nof which the first is a and the second is c.\n\n22\n00:01:06,500 --> 00:01:09,008\n而这个模式匹配的三元表\nThis one matches any list of three things\n\n23\n00:01:10,432 --> 00:01:12,530\n它的首元素必须是符号'JOB\nof which the first is the symbol job.\n\n24\n00:01:12,530 --> 00:01:13,904\n第二个元素为任意值\nThe second can be anything.\n\n25\n00:01:14,210 --> 00:01:15,904\n第三个元素必须是一个二元表\nAnd the third is a list of two things\n\n26\n00:01:15,952 --> 00:01:17,728\n二元表的首元素为符号'COMPUTER\nof which the first is the symbol computer\n\n27\n00:01:17,888 --> 00:01:19,424\n第二个元素可以为任意值\nand the second can be anything.\n\n28\n00:01:20,480 --> 00:01:25,552\n而下一条模式所匹配的三元表\nAnd this one, this next one matches any list of three things,\n\n29\n00:01:25,872 --> 00:01:26,992\n区别就在于\nand the only difference is,\n\n30\n00:01:28,400 --> 00:01:31,320\n在于第三个元素的首元素必须为符号'COMPUTER\nhere, the third list, the first is the symbol computer,\n\n31\n00:01:31,760 --> 00:01:33,296\n表剩余部分可以是任意值\nand then there's some rest of the list.\n\n32\n00:01:35,040 --> 00:01:37,536\n也就是说 上面是二元表 而下面没有限定数目\nSo this means two elements and this means arbitrary number.\n\n33\n00:01:37,860 --> 00:01:39,744\n然而我们的语言实现\nAnd our language implementation isn't\n\n34\n00:01:39,856 --> 00:01:42,064\n根本不用操心如何去实现这个点号\nisn't even going to have to worry about implementing this dot\n\n35\n00:01:42,112 --> 00:01:44,176\n因为这个由Lisp读取器自动地完成\nbecause that's automatically done by Lisp's reader.\n\n36\n00:01:48,340 --> 00:01:50,310\n要注意 匹配器还要保持一致性\nRemember matchers also have some consistency in them.\n\n37\n00:01:50,310 --> 00:01:52,320\n这个模式匹配一个三元表\nThis match is a list of three things\n\n38\n00:01:52,592 --> 00:01:53,984\n表的首元素是A\nof which the first is a.\n\n39\n00:01:54,430 --> 00:01:55,792\n而第二个元素和第三个元素可以是任意值\nAnd the second and third can be anything,\n\n40\n00:01:55,808 --> 00:01:57,088\n但它们必须是相同的\nbut they have to be the same thing.\n\n41\n00:01:57,940 --> 00:01:58,848\n它们都是?X\nThey're both called x.\n\n42\n00:01:59,600 --> 00:02:01,552\n而这个模式匹配一个四元表\nAnd this matches a list of four things\n\n43\n00:02:01,968 --> 00:02:03,264\n其中第一个元素与第四个元素相同\nof which the first is the fourth\n\n44\n00:02:03,664 --> 00:02:05,152\n而第二个元素与第三个元素相同\nand the second is the same as the third.\n\n45\n00:02:05,590 --> 00:02:08,608\n最后一个模式匹配以A开头的任意表\nAnd this last one matches any list that begins with a.\n\n46\n00:02:09,680 --> 00:02:11,056\n以A开头\nThe first thing is a,\n\n47\n00:02:11,232 --> 00:02:12,560\n余下的可以是任意值\nand the rest can be anything.\n\n48\n00:02:14,040 --> 00:02:16,608\n这是对我们已经学习过的模式匹配语言\nSo that's just a review of pattern matcher syntax\n\n49\n00:02:16,624 --> 00:02:17,872\n的一个回顾\nthat you've already seen.\n\n50\n00:02:18,780 --> 00:02:19,648\n还记得吗\nAnd remember,\n\n51\n00:02:19,792 --> 00:02:22,288\n这是由一个叫做MATCH的过程实现的\nthat's implemented by some procedure called match.\n\n52\n00:02:24,870 --> 00:02:36,064\nMATCH有三个参数：PAT、DATA以及DICTIONARY\nAnd match takes a pattern and some data and a dictionary.\n\n53\n00:02:43,200 --> 00:02:47,120\nMATCH考虑的是\nAnd match asks the question\n\n54\n00:02:47,790 --> 00:02:52,640\n利用给定DICTIONAY中的绑定\nis there any way to match this pattern against this data object\n\n55\n00:02:53,552 --> 00:02:56,736\n能够找到一种方法把模式与数据对象匹配起来吗？\nsubject to the bindings that are already in this dictionary?\n\n56\n00:02:58,160 --> 00:02:59,216\n比如说\nSo, for instance,\n\n57\n00:02:59,568 --> 00:03:06,432\n如果我们想要把模式(?X ?Y ?Y ?X)\nif we're going to match the pattern x, y, y, x\n\n58\n00:03:07,712 --> 00:03:13,840\n与数据对象(A B B A)相匹配\nagainst the data a, b, b, a\n\n59\n00:03:15,120 --> 00:03:20,528\n又给定了一个字典 X=A\nsubject to a dictionary, that says x equals a.\n\n60\n00:03:22,010 --> 00:03:25,232\nMATCH就会说：“它们是一致的”\nThen the matcher would say, yes, that's consistent.\n\n61\n00:03:25,260 --> 00:03:27,168\n再给定的字典说 X=A 的情况下\nThese match, and it's consistent\n\n62\n00:03:27,808 --> 00:03:30,208\n模式与数据相匹配\nwith what's in the dictionary to say that x equals a.\n\n63\n00:03:30,320 --> 00:03:31,600\n而匹配的结果则是\nAnd the result of the match\n\n64\n00:03:32,256 --> 00:03:34,304\n一个扩展了的词典\nis the extended dictionary\n\n65\n00:03:34,464 --> 00:03:37,600\n其中包含 X=A Y=B\nthat says x equals a and y equals b.\n\n66\n00:03:39,490 --> 00:03:42,240\nMATCH接收模式、数据以及字典\nSo a matcher takes in pattern data dictionary,\n\n67\n00:03:42,384 --> 00:03:44,544\n如果成功匹配就输出一个扩展后的词典\nputs out an extended dictionary if it matches,\n\n68\n00:03:44,976 --> 00:03:46,840\n否则就报错\nor if it doesn't match, says that it fails.\n\n69\n00:03:46,840 --> 00:03:47,712\n因此 比如说\nSo, for example,\n\n70\n00:03:47,888 --> 00:03:50,384\n如果我在这里使用同样的模式\nif I use the same pattern here,\n\n71\n00:03:50,976 --> 00:03:55,120\n如果我用模式(?X ?Y ?Y ?X)\nif I say this x, y, y, x\n\n72\n00:03:55,660 --> 00:03:58,496\n去匹配(A B B A)\nmatch a, b, b, a\n\n73\n00:03:59,470 --> 00:04:02,840\n并给定词典 Y=A\nwith the dictionary y equals a,\n\n74\n00:04:05,152 --> 00:04:06,816\n那么MATCH就会输出FAIL\nthen the matcher would put out fail.\n\n75\n00:04:12,528 --> 00:04:14,656\n你们已经见过模式匹配器的代码了\nWell, you've already seen the code for a pattern matcher\n\n76\n00:04:15,008 --> 00:04:16,176\n我就不会再去细讲\nso I'm not going to go over it,\n\n77\n00:04:16,640 --> 00:04:19,776\n这跟我们以前做的类似\nbut it's the same thing we've been doing before.\n\n78\n00:04:21,190 --> 00:04:23,220\n我们在《基于规则的系统》中已经见过了\nYou saw that in the system on rule-based control.\n\n79\n00:04:23,220 --> 00:04:24,560\n基本上是同样的匹配器\nIt's essentially the same matcher.\n\n80\n00:04:24,950 --> 00:04:27,664\n实际上 我认为这里的语法还更简单一点\nIn fact, I think the syntax is a little bit simpler\n\n81\n00:04:28,160 --> 00:04:29,312\n因为我们不用去关心\nbecause we're not worrying about\n\n82\n00:04:29,408 --> 00:04:31,400\n任意变量、任意表达式之类的东西\narbitrary constants and expressions and things.\n\n83\n00:04:31,400 --> 00:04:32,880\n这里面只区分变量和常量\nThere's just variables and constants.\n\n84\n00:04:35,790 --> 00:04:37,328\n那么 有了模式匹配器以后\nOK, well, given that,\n\n85\n00:04:38,464 --> 00:04:39,610\n基本查询又是怎么样的呢？\nwhat's a primitive query?\n\n86\n00:04:42,970 --> 00:04:45,344\n基本查询将会是一个相当复杂的东西\nPrimitive query is going to be a rather complicated thing.\n\n87\n00:04:46,672 --> 00:05:03,580\n就拿查询(JOB ?X (?D . ?Y))来说\nIt's going to be-- let's think about the query job of x is d dot y.\n\n88\n00:05:07,040 --> 00:05:08,736\n我们可能会输入这样的查询\nThat's a query we might type in.\n\n89\n00:05:09,400 --> 00:05:11,392\n这又将如何在系统内实现呢？\nThat's going to be implemented in the system.\n\n90\n00:05:14,144 --> 00:05:15,664\n我们可以把它想做这个小盒子\nWe'll think of it as this little box.\n\n91\n00:05:15,700 --> 00:05:16,800\n这是一条基本查询\nHere's the primitive query.\n\n92\n00:05:18,880 --> 00:05:20,304\n这个小盒子将会\nWhat this little box is going to do\n\n93\n00:05:22,240 --> 00:05:27,280\n以两条流作为输入\nis take in two streams and put out a stream.\n\n94\n00:05:31,968 --> 00:05:33,200\n并输出一条流\nand put out a stream.\n\n95\n00:05:34,030 --> 00:05:36,192\n因此一条基本查询的形状\nSo the shape of a primitive query\n\n96\n00:05:36,512 --> 00:05:38,464\n就将是有两条输入流\nis that it's a thing where two streams come in\n\n97\n00:05:38,672 --> 00:05:39,968\n和一条输出流\nand one stream goes out.\n\n98\n00:05:41,120 --> 00:05:46,208\n而这些流 来自于这里的数据库\nWhat these streams are going to be is down here is the database.\n\n99\n00:05:51,952 --> 00:05:53,936\n因此我们把数据库中的所有数据\nSo we imagine all the things in the database\n\n100\n00:05:55,930 --> 00:05:57,200\n想象成一条流\nsort of sitting there in a stream\n\n101\n00:05:57,310 --> 00:05:58,400\n而这个盒子不断地吸取\nand this thing sucks on them.\n\n102\n00:06:00,368 --> 00:06:02,432\n那么 数据库中有什么呢？\nSo what are some things that might be in the database?\n\n103\n00:06:08,432 --> 00:06:20,320\n首先是(JOB (ALYSSA ...))\nOh, job of Alyssa is something\n\n104\n00:06:21,968 --> 00:06:23,712\n以及还有其它的JOB数据\nand some other job is something.\n\n105\n00:06:25,770 --> 00:06:30,416\n想象一下 数据库中的所有事实都在这条流中\nSo imagine all of the facts in the database sitting there in the stream.\n\n106\n00:06:32,040 --> 00:06:33,104\n都到了这里\nThat's what comes in here.\n\n107\n00:06:33,360 --> 00:06:34,528\n而这条流送来的\nWhat comes in here\n\n108\n00:06:34,896 --> 00:06:36,520\n是一些字典\nis a stream of dictionaries.\n\n109\n00:06:38,510 --> 00:06:41,408\n其中一个就可能是\nSo one particular dictionary might say\n\n110\n00:06:46,704 --> 00:06:49,312\nY=PROG\nmight say y equals programmer.\n\n111\n00:06:55,470 --> 00:06:56,640\n现在 查询工作就是要\nNow, what the query does\n\n112\n00:06:57,072 --> 00:06:59,808\n当它从这条流中取得一个字典后\nwhen it gets in a dictionary from this stream,\n\n113\n00:07:02,010 --> 00:07:06,672\n它会搜寻数据库中的东西\nit finds all possible ways of matching the query\n\n114\n00:07:07,456 --> 00:07:10,240\n来尽可能产生所有匹配结果\nagainst whatever is coming in from the database.\n\n115\n00:07:11,390 --> 00:07:12,896\n它把查询视作一种模式\nIt looks at the query as a pattern,\n\n116\n00:07:13,152 --> 00:07:16,720\n并将它们与数据库中的事实匹配起来\nmatches it against any fact from the database\n\n117\n00:07:16,960 --> 00:07:21,984\n结合着相应的字典中的数据\nor all possible ways of finding and matching the database\n\n118\n00:07:22,944 --> 00:07:25,680\n找到数据库中所有匹配的结果\nwith respect to this dictionary that's coming in.\n\n119\n00:07:27,550 --> 00:07:29,696\n所以针对数据库中的每条事实\nSo for each fact in the database,\n\n120\n00:07:29,728 --> 00:07:34,350\n它都会调用(MATCH PAT FACT DICTIONAY)来检查\nit calls the matcher using the pattern, fact, and dictionary.\n\n121\n00:07:35,110 --> 00:07:37,680\n如果成功匹配\nAnd every time it gets a good match,\n\n122\n00:07:38,192 --> 00:07:39,936\n它就输出一个扩展了的字典\nit puts out the extended dictionary.\n\n123\n00:07:40,672 --> 00:07:42,320\n比如说 这里进来了一本字典\nSo, for example, if this one comes in\n\n124\n00:07:43,008 --> 00:07:44,096\n并且成功匹配\nand it finds a match,\n\n125\n00:07:44,512 --> 00:07:45,872\n那么就会输出一本字典\nout will come a dictionary\n\n126\n00:07:46,816 --> 00:07:49,792\n本例中就是Y=PROG\nthat in this case will have y equals programmer\n\n127\n00:07:51,520 --> 00:07:52,970\nX=...\nnd x equals something.\n\n128\n00:07:56,544 --> 00:07:58,752\nY=PROG X=...\ny is programmer, x is something,\n\n129\n00:07:58,960 --> 00:08:00,544\nD又是一个新的项\nand d is whatever it found.\n\n130\n00:08:01,728 --> 00:08:02,272\n像这样扩展\nAnd that's all.\n\n131\n00:08:03,520 --> 00:08:07,824\n当然 它会针对数据库中的所有事实做同样的尝试\nAnd, of course, it's going to try this for every fact in the dictionary.\n\n132\n00:08:07,980 --> 00:08:09,250\n所以就可能有很多的结果\nSo it might find lots of them.\n\n133\n00:08:09,568 --> 00:08:10,592\n可能会产生另一本字典\nIt might find another one\n\n134\n00:08:11,280 --> 00:08:17,120\n其中 Y=PROG X=... D=...\nthat says y equals programmer and x equals, and d equals.\n\n135\n00:08:19,184 --> 00:08:21,550\n因此 对于每个输入的框架\nSo thats, So for one frame coming in,\n\n136\n00:08:21,760 --> 00:08:23,696\n对于每输入一本字典\nit might put out-- for one dictionary coming in,\n\n137\n00:08:23,728 --> 00:08:25,240\n它可能输出很多本字典\nit might put out a lot of dictionaries,\n\n138\n00:08:26,544 --> 00:08:28,672\n或者什么也不输出\nor it might put out none.\n\n139\n00:08:30,470 --> 00:08:38,480\n可能会有一些不匹配的情况 比如X=FOO\nIt might have something that wouldn't match like x equals FOO.\n\n140\n00:08:39,024 --> 00:08:40,896\n这个条目不会匹配任何东西\nThis one might not match anything\n\n141\n00:08:41,520 --> 00:08:45,120\n就这个框架来说 不会向输出流中输出东西\nin which case nothing will go into this stream corresponding to this frame.\n\n142\n00:08:47,510 --> 00:08:51,280\n或者你也可以输入一个空框架\nOr what you might do is put in an empty frame,\n\n143\n00:08:52,910 --> 00:08:56,240\n空框架是用来\nand an empty frame says try matching all ways--\n\n144\n00:08:59,872 --> 00:09:02,336\n在没有任何约束的情况下\nfind all possible ways of matching the query\n\n145\n00:09:02,576 --> 00:09:06,144\n匹配数据库中所有可能的结果\nagainst something in the database subject to no previous restrictions.\n\n146\n00:09:07,570 --> 00:09:09,168\n这仅仅代表着\nAnd if you think about what that means, that's just\n\n147\n00:09:10,320 --> 00:09:13,872\n处理你输入的查询 最初所进行的计算\nthe computation that's done when you type in a query right off.\n\n148\n00:09:14,208 --> 00:09:15,568\n它试图找出所有的匹配\nIt tries to find all matches.\n\n149\n00:09:16,650 --> 00:09:18,832\n基本查询建立了这种机制\nSo a primitive query sets up this mechanism.\n\n150\n00:09:19,370 --> 00:09:20,576\n而语言要做的是\nAnd what the language does,\n\n151\n00:09:22,752 --> 00:09:24,672\n当你在顶层输入这条查询时\nwhen you type in the query at the top level,\n\n152\n00:09:24,848 --> 00:09:26,144\n它基于这种机制\nit takes this mechanism,\n\n153\n00:09:26,160 --> 00:09:28,352\n它会输入一本空的字典\nfeeds in one single empty dictionary,\n\n154\n00:09:30,864 --> 00:09:32,560\n而对于输出的每个东西\nand then for each thing that comes out\n\n155\n00:09:33,088 --> 00:09:35,888\n然后把最初的查询\ntakes the original query\n\n156\n00:09:36,560 --> 00:09:40,448\n用不同的字典来实例化\nand instantiates the result with all the different dictionaries,\n\n157\n00:09:40,816 --> 00:09:44,368\n于是实例化后的模式就形成了一条新的流\nproducing a new stream of instantiated patterns here.\n\n158\n00:09:44,990 --> 00:09:46,512\n这就是在终端上打印出来的内容\nAnd that's what gets printed on the terminal.\n\n159\n00:09:48,170 --> 00:09:51,248\n这也就是其中的基本原理\nThat's the basic mechanism going on there.\n\n160\n00:09:53,510 --> 00:09:55,488\n那么 这又为什么复杂呢？\nWell, why is that so complicated?\n\n161\n00:09:57,712 --> 00:10:01,008\n除了使用这种基于流的方法\nYou probably can think of a lot simpler ways to arrange this match for\n\n162\n00:10:01,376 --> 00:10:04,256\n你们可以想出很多更简单的方法来组织基本查询\na primitive query rather than having all of these streams floating around.\n\n163\n00:10:05,184 --> 00:10:06,096\n而答案就在于\nAnd the answer is--\n\n164\n00:10:07,152 --> 00:10:08,512\n你们可能已经在想了\nyou probably guess already.\n\n165\n00:10:10,860 --> 00:10:14,096\n答案就是 这种方法能够优雅地\nThe answer is this thing extends elegantly\n\n166\n00:10:14,560 --> 00:10:16,768\n实现组合手段\nto implement the means of combination.\n\n167\n00:10:17,790 --> 00:10:18,800\n比如说\nSo, for instance,\n\n168\n00:10:20,656 --> 00:10:22,470\n假设我还想实现其它的效果\nsuppose I don't only want to do this.\n\n169\n00:10:22,470 --> 00:10:26,960\n我不只是想查询所有人的工作信息\nI don't want to say who to be everybody's job description.\n\n170\n00:10:27,230 --> 00:10:28,352\n假设我还想查询\nSuppose I want to say\n\n171\n00:10:29,472 --> 00:10:35,920\n(AND (JOB ?X (?D . ?Y))\nto say AND the job of x is d dot y\n\n172\n00:10:36,800 --> 00:10:47,040\n(SUPERVIOSR ?X ?Z))\nand the supervisor of x is z.\n\n173\n00:10:48,800 --> 00:10:50,672\n(SUPERVISOR ?X ?Z)这条查询\nNow, supervisor of x is z\n\n174\n00:10:51,392 --> 00:10:52,960\n是另外的一条基本查询\nis going to be another primitive query\n\n175\n00:10:53,712 --> 00:10:58,432\n它也有类似的形状——接收一条数据对象流\nthat has the same shape to take in a stream of data objects,\n\n176\n00:10:59,184 --> 00:11:01,648\n一条初始字典流\na stream of initial dictionaries,\n\n177\n00:11:01,680 --> 00:11:05,520\n字典是你在进行匹配时 需要遵循的约束\nwhich are the restrictions to try and use when you match,\n\n178\n00:11:05,536 --> 00:11:07,440\n然后它会输出一条字典流\nand it's going to put out a stream of dictionaries.\n\n179\n00:11:08,700 --> 00:11:10,800\n这就是这条基本查询的形状\nSo that's what this primitive query looks like.\n\n180\n00:11:11,504 --> 00:11:12,910\n我又该如何实现AND呢？\nAnd how do I implement the AND?\n\n181\n00:11:12,910 --> 00:11:13,450\n其实很简单\nWell, it's simple.\n\n182\n00:11:13,450 --> 00:11:14,448\n把它们连接起来就好了\nI just hook them together.\n\n183\n00:11:14,880 --> 00:11:16,288\n我把这条查询的输出\nI take the output of this one,\n\n184\n00:11:16,960 --> 00:11:18,816\n连接在这条查询的输入上\nand I put that to the input of that one.\n\n185\n00:11:19,830 --> 00:11:21,840\n然后把这里的字典扇出开来\nAnd I take the dictionary here and I fan it out.\n\n186\n00:11:26,570 --> 00:11:27,968\n你们就能发现它是如何工作的了\nAnd then you see how that's going to work,\n\n187\n00:11:29,050 --> 00:11:32,448\n这里会输出一个框架\nbecause what's going to happen is a frame will now come in here,\n\n188\n00:11:32,512 --> 00:11:36,848\n其中有X、Y和D的绑定\nwhich has a binding for x, y, and d.\n\n189\n00:11:37,920 --> 00:11:39,280\n当后面的查询接收到结果后\nAnd then when this one gets it, it'll say,\n\n190\n00:11:39,296 --> 00:11:41,600\n当它了解了这些约束后\noh, gee, subject to these restrictions,\n\n191\n00:11:42,176 --> 00:11:49,248\n字典中的是Y、X和D的值\nwhich now already have values in the dictionary for y and x and d,\n\n192\n00:11:51,808 --> 00:11:53,088\n它会搜寻数据库\nit looks in the database and says,\n\n193\n00:11:53,120 --> 00:11:54,928\n试图找到有关SUPERVISOR关系的事实\ngee, can I find any supervisor facts?\n\n194\n00:11:56,048 --> 00:11:58,510\n如果找到了的话 它就会输出一些词典\nAnd if it finds any, out will come dictionaries\n\n195\n00:11:59,584 --> 00:12:09,340\n其中有Y、X、D以及Z的绑定\nwhich have bindings for y and x and d and z now.\n\n196\n00:12:12,070 --> 00:12:14,096\n不过要注意\nAnd then notice that the match---\n\n197\n00:12:14,192 --> 00:12:17,248\n因为这里输入的框架建立了约束\nbecause the frames coming in here have these restrictions,\n\n198\n00:12:17,610 --> 00:12:20,288\n它保证了当你执行AND运算时\nthat's the thing that assures when you do the AND,\n\n199\n00:12:20,496 --> 00:12:24,624\n这两个X是相同的\nthis x will mean the same thing as that x.\n\n200\n00:12:26,470 --> 00:12:28,960\n这是因为通过这条流输出时\nBecause by the time something comes floating in here,\n\n201\n00:12:29,968 --> 00:12:32,656\nX已经有值了 你要确保匹配的一致性\nx has a value that you have to match against consistently.\n\n202\n00:12:34,460 --> 00:12:36,176\n然后我们想起在MATCH的代码中\nAnd then you remember from the code from the matcher,\n\n203\n00:12:36,190 --> 00:12:38,176\n有一种操作字典的特殊组织方法\nthere was something in the way the matcher did dictionaries\n\n204\n00:12:38,208 --> 00:12:39,820\n确保了匹配的一致性\nthat arrange consistent matches.\n\n205\n00:12:40,928 --> 00:12:41,776\n这就是AND的实现\nSo there's AND.\n\n206\n00:12:44,080 --> 00:12:46,944\n关键是要注意它的一般性形状\nThe important point to notice is the general shape.\n\n207\n00:12:48,496 --> 00:12:51,550\n我们来看看(AND P Q)\nLook at what happened: the AND of two queries, say, P and Q.\n\n208\n00:12:52,880 --> 00:12:55,616\n这里是P和Q\nHere's P and Q.\n\n209\n00:12:57,296 --> 00:12:58,608\n两条查询的AND\nThe AND of two queries,\n\n210\n00:13:00,272 --> 00:13:01,190\n看起来像是这样\nwell, it looks like this.\n\n211\n00:13:01,190 --> 00:13:04,448\n每一条查询都通过一条流连接数据库\nEach query takes in a stream from the database,\n\n212\n00:13:04,544 --> 00:13:05,712\n一条输入流\na stream of inputs,\n\n213\n00:13:06,336 --> 00:13:08,176\n并输出一条输出流\nand puts out a stream of outputs.\n\n214\n00:13:10,230 --> 00:13:11,728\n关键是要注意\nAnd the important point to notice\n\n215\n00:13:12,208 --> 00:13:15,024\n如果我在它们周围画一个盒子\nis that if I draw a box around this thing\n\n216\n00:13:19,264 --> 00:13:23,648\n这就是(AND P Q)\nand say this is AND of P and Q,\n\n217\n00:13:25,664 --> 00:13:30,384\n那么这个盒子也有同样的形状\nthen that box has exactly the same overall shape.\n\n218\n00:13:32,048 --> 00:13:34,200\n它也有一条连接数据库的流\nIt's something that takes in a stream from the database.\n\n219\n00:13:34,200 --> 00:13:35,744\n但是在内部会扇出开来\nHere it's going to get fanned out inside,\n\n220\n00:13:36,608 --> 00:13:37,936\n但是在外部你看不到\nbut from the outside you don't see that.\n\n221\n00:13:38,160 --> 00:13:40,640\n它接收一个流 并输出一个流\nIt takes an input stream and puts out an output stream.\n\n222\n00:13:42,064 --> 00:13:43,168\n这就是AND\nSo this is AND.\n\n223\n00:13:43,570 --> 00:13:45,728\n类似地 OR可能看起像这样\nAnd then similarly, OR would look like this.\n\n224\n00:13:46,020 --> 00:13:49,584\n虽然我没给你们演示过OR的用法\nOR would-- although I didn't show you examples of OR.\n\n225\n00:13:49,840 --> 00:13:54,704\nOR会尝试找出P或Q所有匹配的事实\nOR would say can I find all ways of matching P or Q.\n\n226\n00:13:55,808 --> 00:13:58,070\nP、Q两条查询都有各自的形状\nSo I have P and Q. Each will have their shape.\n\n227\n00:14:04,460 --> 00:14:06,688\nOR的实现则是\nAnd the way OR is implemented is\n\n228\n00:14:08,544 --> 00:14:10,912\n我把来自于数据库的流\nI'll take my database stream.\n\n229\n00:14:12,500 --> 00:14:13,490\n扇出开来\nI'll fan it out.\n\n230\n00:14:13,490 --> 00:14:16,048\n把它们分别送给P和Q\nI'll put one into P and one into Q.\n\n231\n00:14:17,440 --> 00:14:21,980\n我把最初的查询流也给扇出开来\nI'll take my initial query stream coming in and fan it out.\n\n232\n00:14:26,750 --> 00:14:29,168\n这样我不但能够得到P的所有结果\nSo I'll look at all the answers I might get from P\n\n233\n00:14:29,296 --> 00:14:31,088\n也能得到Q的所有结果\nand all the answers I might get from Q,\n\n234\n00:14:31,616 --> 00:14:34,560\n把这些输出送入某种“附加器”中\nand I'll put them through some sort of thing that appends them\n\n235\n00:14:34,624 --> 00:14:37,488\n或者把它们“合并”到一条流中\nor merges the result into one stream,\n\n236\n00:14:39,648 --> 00:14:40,880\n然后得到输出\nand that's what will come out.\n\n237\n00:14:41,080 --> 00:14:48,240\n而从外部来看 这整个东西就是OR\nAnd this whole thing from the outside is OR.\n\n238\n00:14:52,350 --> 00:14:54,896\n同样的 当你们从外部观察它时\nAnd again, you see it has the same overall shape\n\n239\n00:14:55,072 --> 00:14:56,544\n你会发现它具有相同的形状\nAnd again, you see it has the same overall shape\n\n240\n00:15:01,000 --> 00:15:01,616\nNOT又如何实现呢？\nWhat's NOT?\n\n241\n00:15:02,020 --> 00:15:03,456\nNOT的原理有些类似\nNOT works kind of the same way.\n\n242\n00:15:04,310 --> 00:15:05,952\n如果我有一条查询P\nIf I have some query P,\n\n243\n00:15:06,864 --> 00:15:13,504\n这是一条基本查询P\nIf I have P, I take the primitive query for P.\n\n244\n00:15:14,690 --> 00:15:16,320\n现在我要实现(NOT P)\nHere, I'm going to implement NOT P.\n\n245\n00:15:18,688 --> 00:15:20,544\nNOT的作用像是一个过滤器\nAnd NOT's just going to act as a filter.\n\n246\n00:15:20,720 --> 00:15:21,952\n这里连接数据库\nI'll take in the database\n\n247\n00:15:23,840 --> 00:15:28,288\n这里是输入的字典流\nand my original stream of dictionaries coming in,\n\n248\n00:15:28,780 --> 00:15:31,536\n(NOT P)要做的就是\nand what NOT P will do is\n\n249\n00:15:31,888 --> 00:15:37,400\n对这些东西做过滤\nit will filter these guys.\n\n250\n00:15:39,020 --> 00:15:40,096\n过滤的方法则是\nAnd the way it will filter it,\n\n251\n00:15:40,192 --> 00:15:42,704\n如果我在这里获得了一本字典\nit will say when I get in a dictionary here,\n\n252\n00:15:43,424 --> 00:15:44,656\n那么我就去找所有的匹配\nI'll find all the matches,\n\n253\n00:15:44,832 --> 00:15:46,480\n然后丢弃找到的结果\nand if I find any, I'll throw it away.\n\n254\n00:15:47,460 --> 00:15:49,936\n如果我没有在这里找到匹配\nAnd if I don't find any matches to something coming in here,\n\n255\n00:15:50,128 --> 00:15:51,376\n我就把它传递过去\nI'll just pass that through,\n\n256\n00:15:52,400 --> 00:15:53,552\nNOT就是一个纯粹的过滤器\nso NOT is a pure filter.\n\n257\n00:15:55,344 --> 00:15:59,980\n因此AND就类似于一个电阻\nSo AND is-- think of these sort of electoral resistors or something.\n\n258\n00:15:59,980 --> 00:16:01,856\nAND是串行的组合\nAND is series combination\n\n259\n00:16:02,496 --> 00:16:04,140\nOR是并行组合\nand OR is parallel combination.\n\n260\n00:16:04,960 --> 00:16:07,460\n然而NOT并不会对字典做任何扩展\nAnd then NOT is not going to extend any dictionaries at all.\n\n261\n00:16:07,460 --> 00:16:08,400\n它只会做过滤\nIt's just going to filter it.\n\n262\n00:16:08,750 --> 00:16:11,792\n它会丢弃那些能够匹配的结果\nIt's going to throw away the ones for which it finds a way to match.\n\n263\n00:16:12,640 --> 00:16:14,192\nLISP-VALUE的原理类似\nAnd lisp-value is sort of the same way.\n\n264\n00:16:14,848 --> 00:16:16,600\n它的过滤器会复杂点\nThe filter's a little more complicated.\n\n265\n00:16:16,600 --> 00:16:17,376\n因为要应用到谓词上\nIt applies to predicate.\n\n266\n00:16:19,936 --> 00:16:21,648\n这里需要注意的关键点是\nThe major point to notice here,\n\n267\n00:16:21,920 --> 00:16:23,552\n我们之前也强调过了\nand it's a major point we've looked at before,\n\n268\n00:16:23,648 --> 00:16:25,296\n就是关于“闭包性质”的思想\nis this idea of closure.\n\n269\n00:16:28,220 --> 00:16:31,808\n我们通过组合手段构建的东西\nThe things that we build as a means of combination\n\n270\n00:16:31,952 --> 00:16:34,512\n跟所使用的基本物件\nhave the same overall structure\n\n271\n00:16:35,696 --> 00:16:37,584\n有同样的结构\nas the primitive things that we're combining.\n\n272\n00:16:39,750 --> 00:16:41,680\n所以从外面看\nSo the AND of two things\n\n273\n00:16:41,712 --> 00:16:43,720\n查询的AND与基本查询结构相同\nlooked at from the outside has the same shape.\n\n274\n00:16:44,630 --> 00:16:46,144\n这就意味着\nAnd what that means is that\n\n275\n00:16:46,940 --> 00:16:50,288\n这里的盒子可以是AND、OR、NOT或者其它的\nthis box here could be an AND or an OR or a NOT or something\n\n276\n00:16:50,304 --> 00:16:54,220\n因为它具有相同的形状来连接更大的东西\nbecause it has the same shape to interface to the larger things.\n\n277\n00:16:54,950 --> 00:16:56,688\n这种思想能够让我们获得\nIt's the same thing that allowed us to get\n\n278\n00:16:56,928 --> 00:16:58,960\nEscher绘图语言中的那种复杂度\ncomplexity in the Escher picture language\n\n279\n00:16:59,550 --> 00:17:01,312\n让你能够仅仅使用序对\nor allows you to immediately build up these\n\n280\n00:17:01,344 --> 00:17:03,260\n构建出这些复杂结构\ncomplicated structures just out of pairs.\n\n281\n00:17:03,936 --> 00:17:04,784\n这就是“闭包性质”\nIt's closure.\n\n282\n00:17:06,280 --> 00:17:08,064\n这种性质\nAnd that's the thing that\n\n283\n00:17:09,648 --> 00:17:11,728\n能够让我完成你们现在觉得理所当然的事儿\nallowed me to do what by now you took for granted\n\n284\n00:17:11,760 --> 00:17:14,912\n比如我可以查询(AND JOB SALARY)\nI said, gee, there's a query which is AND of job and salary,\n\n285\n00:17:14,912 --> 00:17:18,800\n当然我也可以查询(AND JOB (NOT ...))等等\nand I said, oh, there's another one, which is AND of job, a NOT of something.\n\n286\n00:17:19,260 --> 00:17:20,928\n这种便利是由\nThe fact that I can do that is\n\n287\n00:17:20,944 --> 00:17:22,910\n这种“闭包原则”直接带给我们的\na direct consequence of this closure principle.\n\n288\n00:17:25,184 --> 00:17:27,080\n好吧 提问时间\nOK, let's break and then we'll go on.\n\n289\n00:17:29,328 --> 00:17:30,896\n学生：字典是从哪里来的？\nAUDIENCE: Where does the dictionary come from?\n\n290\n00:17:30,990 --> 00:17:36,032\n教授：字典最初来自于你的输入\nPROFESSOR: The dictionary comes initially from what you type in.\n\n291\n00:17:36,096 --> 00:17:37,328\n因此当你最初进行查询时\nSo when you start this up,\n\n292\n00:17:39,168 --> 00:17:41,090\n它首先会建立起这整个结构\nthe first thing it does is set up this whole structure.\n\n293\n00:17:41,090 --> 00:17:42,640\n它先输入一个空字典\nIt puts in one empty dictionary.\n\n294\n00:17:45,000 --> 00:17:47,248\n如果你只有一条基本查询的话\nAnd if all you have is one primitive query,\n\n295\n00:17:48,240 --> 00:17:51,104\n那么它就会输出一系列具有内容的字典\nthen what will come out is a bunch of dictionaries with things filled in.\n\n296\n00:17:52,310 --> 00:17:54,336\n这里演示的一般性情况是\nThe general situation that I have here\n\n297\n00:17:54,512 --> 00:17:59,710\n某个嵌套组合查询的中间过程\nis when this is in the middle of some nest of combined things.\n\n298\n00:18:01,552 --> 00:18:02,304\n所以在那时\nSo by the time.\n\n299\n00:18:02,380 --> 00:18:03,790\n让我们来看看这里\nLet's look at the picture over here.\n\n300\n00:18:04,384 --> 00:18:06,730\n这条SUPERVISOR查询得到了某本字典\nThis supervisor query gets in some dictionary.\n\n301\n00:18:06,730 --> 00:18:08,032\n这本字典来自于哪里呢？\nWhere did this one come from?\n\n302\n00:18:08,730 --> 00:18:11,152\n它来自于\nThis dictionary came from the fact that\n\n303\n00:18:12,848 --> 00:18:14,896\n这条基本查询的输出\nI'm looking at the output of this primitive query.\n\n304\n00:18:16,260 --> 00:18:17,888\n说得更具体一点\nSo maybe to be very specific,\n\n305\n00:18:18,352 --> 00:18:21,728\n如果我最初在顶层只输入了这条查询\nif I literally typed in just this query at the top level,\n\n306\n00:18:22,272 --> 00:18:22,928\n这整条AND查询\nthis AND,\n\n307\n00:18:23,072 --> 00:18:25,280\n它实际上会构建这种结构\nwhat would actually happen is it would build this structure\n\n308\n00:18:25,500 --> 00:18:30,240\n并使用一本空字典来启动整个过程\nand start up this whole thing with one empty dictionary.\n\n309\n00:18:31,770 --> 00:18:34,336\n处理过程开始后 会产生一系列的字典\nAnd now this one would process, and a whole bunch of dictionaries\n\n310\n00:18:34,368 --> 00:18:37,360\n其中就有X、Y以及D\nwould come out with x, y's and d's in them.\n\n311\n00:18:38,640 --> 00:18:39,584\n向这边传递\nRun it through this one.\n\n312\n00:18:40,190 --> 00:18:42,160\n这就是这条查询的输入\nSo now that's the input to this one.\n\n313\n00:18:42,160 --> 00:18:43,728\n这条查询也会生成其它的东西\nThis one would now put out some other stuff.\n\n314\n00:18:45,040 --> 00:18:48,224\n如果这整个查询是构建在一个更大的查询中的话\nAnd if this itself were buried in some larger thing,\n\n315\n00:18:49,312 --> 00:18:51,008\n比如说一条OR查询\nlike an OR of something,\n\n316\n00:18:53,424 --> 00:18:55,712\n那么它将输出到下一个查询中\nthen that would go feed into the next one.\n\n317\n00:18:58,560 --> 00:19:01,280\n因此最初开始处理时 只有一本空字典\nSo you initially get only one empty dictionary when you start it,\n\n318\n00:19:01,680 --> 00:19:04,080\n但是在处理这些复合查询的过程中\nbut as you're in the middle of processing these compounds things,\n\n319\n00:19:04,112 --> 00:19:06,656\n会生成各种不同的字典\nthat's where these cascades of dictionaries start getting generated.\n\n320\n00:19:07,660 --> 00:19:12,280\n学生：字典都是查询的结果吗？\nAUDIENCE: Dictionaries only come about as a result of using the queries?\n\n321\n00:19:15,120 --> 00:19:17,696\n它们会变成\nOr do they stays, do they become--\n\n322\n00:19:18,848 --> 00:19:22,816\n它们存储在数据库中吗？\ndo they stay someplace in space like the database does?\n\n323\n00:19:23,680 --> 00:19:24,980\n它们是临时数据吗？\nAre these temporary items?\n\n324\n00:19:24,980 --> 00:19:27,184\n教授：它们是在MATCH过程中临时创建的\nPROFESSOR: They're created temporarily in the matcher.\n\n325\n00:19:28,030 --> 00:19:29,880\n但它们实际存放在内存中\nReally, they're someplace in storage.\n\n326\n00:19:29,880 --> 00:19:33,024\n最初 某人创建了一本THE-EMPTY-DICT字典\nInitially, someone creates a thing called the empty dictionary\n\n327\n00:19:34,224 --> 00:19:36,800\n送入这个匹配过程\nthat gets initially fed to this match procedure,\n\n328\n00:19:36,810 --> 00:19:39,056\nMATCH过程据此构建新字典\nand then the match procedure builds some dictionaries,\n\n329\n00:19:39,070 --> 00:19:40,272\n并把它们传递下去\nand they get passed on and on.\n\n330\n00:19:40,768 --> 00:19:42,480\n学生：因此匹配完成后它们就被丢弃了？\nAUDIENCE: OK, so they'll go way after the match?\n\n331\n00:19:43,640 --> 00:19:46,256\n教授：实际上 当没人需要它们后（就被废料回收了）\nPROFESSOR: They'll go away when no one needs them again, yeah.\n\n332\n00:19:51,900 --> 00:19:53,600\n学生：似乎AND查询对数据库\nAUDIENCE: It appears that the AND performs\n\n333\n00:19:53,632 --> 00:19:55,370\n进行了一些冗余操作\nsome redundant searches of the database.\n\n334\n00:19:55,960 --> 00:19:57,488\n如果第一条子句扫描过了\nIf the first clause matched,\n\n335\n00:19:57,504 --> 00:19:59,900\n比如说前两个元素没有匹配 而第三个元素匹配了\nlet's say, the third element and not on the first two elements,\n\n336\n00:20:00,256 --> 00:20:03,648\n然而第二条子句又会检查这两个元素\nthe second clause is going to look at those first two elements again,\n\n337\n00:20:04,320 --> 00:20:06,592\n然后又一次丢弃这些不匹配的元素\ndiscarding them because they don't match.\n\n338\n00:20:06,640 --> 00:20:08,720\n而字典中已经有匹配的项了\nThe match is already in the dictionary.\n\n339\n00:20:10,000 --> 00:20:12,560\n如果我们把数据库中的数据\nWould it makes sense to carry the data element\n\n340\n00:20:12,576 --> 00:20:14,432\n跟字典同时传递 这样可行么？\nfrom the database along with the dictionary?\n\n341\n00:20:15,690 --> 00:20:17,600\n教授：实际上 通常来说\nPROFESSOR: Yeah, there're... Well, in general,\n\n342\n00:20:17,632 --> 00:20:19,480\n我们能够以其它方式来安排这些搜索\nthere are other ways to arrange this search,\n\n343\n00:20:20,128 --> 00:20:21,740\n你也可以做一些分析\nand there's some analysis that you can do.\n\n344\n00:20:21,740 --> 00:20:23,168\n我记得书里面就有这样的习题\nI think there's a problem in the book,\n\n345\n00:20:23,872 --> 00:20:26,656\n是考察通过安排AND子句的顺序\nwhich talks about a different way that you can cascade AND\n\n346\n00:20:27,008 --> 00:20:29,200\n来消除不同类型的冗余\nto eliminate various kinds of redundancies.\n\n347\n00:20:29,850 --> 00:20:30,720\n而这里只是为了\nThis one is meant to be--\n\n348\n00:20:31,328 --> 00:20:34,544\n用非常简单的情况来向你们展示它们是如何配合的\nwas mainly meant to be very simple so you can see how they fit together.\n\n349\n00:20:34,704 --> 00:20:35,380\n但是你说得非常对\nBut you're quite right.\n\n350\n00:20:35,380 --> 00:20:37,328\n这些冗余是可以避免的\nThere are redundancies here that you can get rid of.\n\n351\n00:20:38,370 --> 00:20:40,800\n这也是这门语言缓慢的原因之一\nThat's another reason why this language is somewhat slow.\n\n352\n00:20:41,190 --> 00:20:42,704\n你们可以让它变得更聪明\nThere are a lot smarter things you can do.\n\n353\n00:20:42,930 --> 00:20:46,224\n我只是为了向你们演示非常简单的、原理性的实现\nWe're just trying to show you a very simple, in principle, implementation.\n\n354\n00:20:51,220 --> 00:20:53,232\n学生：您是根据Prolog来建模这门语言的\nAUDIENCE: Did you model this language on Prolog,\n\n355\n00:20:53,248 --> 00:20:55,136\n还是说它只是偶然地像Prolog？\nor did it just come out looking like Prolog?\n\n356\n00:21:04,960 --> 00:21:07,088\n教授：Gerry教授昨天羞辱了一大堆人\nPROFESSOR: Well, Gerry insulted a whole bunch of people yesterday,\n\n357\n00:21:07,248 --> 00:21:09,920\n我想说真实的情况是\nso I might as well say that the MIT attitude towards Prolog is\n\n358\n00:21:10,190 --> 00:21:12,608\nMIT的研究人员在1971年做了类似的事\nis something that people did in about 1971\n\n359\n00:21:12,640 --> 00:21:15,600\n但是发现这个方向并不正确 并停止了研究\nand decided that it wasn't really the right thing and stopped.\n\n360\n00:21:16,120 --> 00:21:22,800\n因此我们是根据查询处理的基本原理建模的\nSo we modeled this on the sort of natural way that this thing was done\n\n361\n00:21:22,848 --> 00:21:24,730\n大概在1971年左右\nin about 1971,\n\n362\n00:21:25,136 --> 00:21:27,248\n只是说 那时候我们还没有用流来实现\nexcept at that point, we didn't do it with streams.\n\n363\n00:21:28,272 --> 00:21:33,040\n然后我们 -- 但我们使用了它差不多六个月后\nAnd then we... After we were using it for about six months,\n\n364\n00:21:33,080 --> 00:21:34,912\n发现它存在各种各样的问题\nwe discovered that it had all these problems,\n\n365\n00:21:34,944 --> 00:21:36,300\n稍后我会解释\nsome of which I'll talk about later.\n\n366\n00:21:37,330 --> 00:21:38,192\n然后我们就想\nAnd we said,\n\n367\n00:21:38,448 --> 00:21:39,920\nProlog一定解决了这些问题\ngee, Prolog must have fixed those,\n\n368\n00:21:39,930 --> 00:21:41,216\n但却发现它并没有\nand then we found out that it didn't.\n\n369\n00:21:41,250 --> 00:21:43,024\n从这种意义上来说 它确实跟Prolog一样\nSo this does about the same thing as Prolog.\n\n370\n00:21:43,600 --> 00:21:44,950\n学生：Prolog基于流么？\nAUDIENCE: Does Prolog use streams?\n\n371\n00:21:44,950 --> 00:21:46,200\n教授：不 Prolog基于的是\nPROFESSOR: No. Prolog --\n\n372\n00:21:46,784 --> 00:21:51,040\n就行为上来说 我们的语言很像Prolog\nIn how it behaves, it behaves a lot like Prolog.\n\n373\n00:21:51,040 --> 00:21:52,960\nProlog使用回溯策略\nProlog uses a backtracking strategy.\n\n374\n00:21:53,800 --> 00:21:55,712\n但是Prolog有一个优点非常好\nBut the other thing that's really good about Prolog\n\n375\n00:21:55,728 --> 00:21:57,984\n也使得它变得实用\nthat makes it a usable thing\n\n376\n00:21:58,280 --> 00:22:01,504\n你知道吗\nis that there's a really very, very\n\n377\n00:22:01,680 --> 00:22:04,090\n它们精心设计了Prolog的编译器\nthere's a really very, very well-engineered compiler technology\n\n378\n00:22:04,112 --> 00:22:05,328\n使得它能够高速运行\nthat makes it run fast.\n\n379\n00:22:06,656 --> 00:22:10,816\n因此 虽然我们这门语言非常缓慢地输出答案\nSo although you saw the merge spitting out these answers very, very slowly,\n\n380\n00:22:11,664 --> 00:22:13,616\n真正的Prolog程序却运行得非常快\na real Prolog will run very, very fast.\n\n381\n00:22:14,704 --> 00:22:16,480\n这是因为 尽管搜索过程十分低效\nBecause even though it's sort of doing this,\n\n382\n00:22:16,670 --> 00:22:20,816\nProlog卓越的编译器也会高效地完成工作\nthe real work that went into Prolog is a very, very excellent compiler effort.\n\n383\n00:22:24,304 --> 00:22:25,216\n休息一下吧\nLet's take a break.\n\n384\n00:22:25,420 --> 00:22:36,176\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n385\n00:22:36,352 --> 00:22:39,872\n《计算机程序的构造和解释》\n\n386\n00:23:01,488 --> 00:23:05,120\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n387\n00:23:05,180 --> 00:23:09,056\n《计算机程序的构造和解释》\n\n388\n00:23:09,120 --> 00:23:13,664\n逻辑式程序设计 II\n\n389\n00:23:16,650 --> 00:23:18,832\n我们已经考察过了基本查询\nWe've looked at the primitive queries\n\n390\n00:23:19,216 --> 00:23:23,520\n以及如何使用流来实现组合手段\nand the ways that streams are used to implement the means of combination:\n\n391\n00:23:23,792 --> 00:23:25,728\nAND、OR以及NOT\nAND and OR and NOT.\n\n392\n00:23:26,950 --> 00:23:28,432\n现在 该讨论抽象手段了\nNow, let go on to the means of abstraction.\n\n393\n00:23:29,580 --> 00:23:32,800\n回想一下 我们这门语言的抽象手段是RULE\nRemember, the means of abstraction in this language are rules.\n\n394\n00:23:35,150 --> 00:23:37,792\n(BOSS ?Z ?D)描述的是\nSo z is a boss in division d\n\n395\n00:23:39,184 --> 00:23:43,776\n如果某人在D部门工作\nif there's some x who has a job in division d\n\n396\n00:23:45,680 --> 00:23:47,472\n并且Z是X的上司\nand z is the supervisor of x.\n\n397\n00:23:48,900 --> 00:23:50,608\n这就是所谓的“BOSS”\nThat's what it means for someone to be a boss.\n\n398\n00:23:52,260 --> 00:23:53,152\n并且 实际上\nSo, and in effect,\n\n399\n00:23:53,344 --> 00:23:55,616\n如果我们考察一下编写的规则与这边的关系\nif you think about what we're doing with relation to this,\n\n400\n00:23:56,800 --> 00:23:57,904\n这是我们编写的查询\nthere's the query we wrote--\n\n401\n00:23:57,936 --> 00:24:01,900\n这个是(JOB ?X ?D) 而这个是(SUPERVISOR ?X ?Z)\nthe job of x is in d and the supervisor of x is z--\n\n402\n00:24:02,192 --> 00:24:04,288\n我们实际想要把这一大堆东西\nwhat we in effect want to do is take this whole mess\n\n403\n00:24:05,072 --> 00:24:06,576\n用一个盒子封装起来\nand draw a box around it\n\n404\n00:24:19,080 --> 00:24:24,544\n然后把这个盒子里的所有东西\nand say this whole thing inside the box\n\n405\n00:24:25,152 --> 00:24:32,480\n认为是(BOSS ?Z ?D)\nis boss of z in division d.\n\n406\n00:24:33,900 --> 00:24:35,250\n这是我们想要达到的效果\nThat's in effect what we want to do.\n\n407\n00:24:38,720 --> 00:24:39,728\n因此 比如说\nSo, for instance,\n\n408\n00:24:43,184 --> 00:24:44,080\n我们这样做了过后\nif we've done that,\n\n409\n00:24:45,008 --> 00:24:47,840\n我们想要检查\nand we want to check whether or not it's true\n\n410\n00:24:47,952 --> 00:24:50,512\nBen Bitdiddle是否为计算机分部的BOSS\nthat Ben Bitdiddle is a boss in the computer division,\n\n411\n00:24:51,104 --> 00:25:02,864\n如果我想查询 (BOSS (BITDIDDLE BEN) COMPUTER)\nso if I want to say boss of Ben Bitdiddle in the computer division,\n\n412\n00:25:04,784 --> 00:25:07,088\n想象一下把这条查询输入系统\nimagine typing that in as query to the system,\n\n413\n00:25:07,120 --> 00:25:09,168\n实际上发生的是\nin effect what we want to do\n\n414\n00:25:10,672 --> 00:25:12,928\n在这里先构建一本字典\nis set up a dictionary here,\n\n415\n00:25:15,820 --> 00:25:23,632\n其中 ?Z=BITDIDDLE\nwhich has z to Ben Bitdiddle\n\n416\n00:25:28,880 --> 00:25:33,310\n?D=COMPUTER\nand d to computer.\n\n417\n00:25:37,088 --> 00:25:38,624\n这个字典又是来自于哪里呢？\nWhere did that dictionary come from?\n\n418\n00:25:38,688 --> 00:25:40,710\n我们来看下幻灯片\nLet's look at the slide for one second.\n\n419\n00:25:40,710 --> 00:25:43,712\n这本字典是通过把\nThat dictionary came from matching the query\n\n420\n00:25:44,304 --> 00:25:46,336\n查询(BOSS (BITDIDDLE BEN) COMPUTER)\nthat said boss of Ben Bitdiddle and computer\n\n421\n00:25:46,512 --> 00:25:49,632\n与规则的结论(BOSS ?Z ?D)相匹配得到\nonto the conclusion of the rule: boss of z and d.\n\n422\n00:25:51,650 --> 00:25:54,112\n所以我们把规则的结论和查询匹配了起来\nSo we match the query to the conclusion of the rule.\n\n423\n00:25:54,190 --> 00:25:55,536\n这样我们就获得了一本字典\nThat gives us a dictionary,\n\n424\n00:25:58,992 --> 00:26:02,544\n现在我们就要把这本字典输入到这整个结构中\nand that's the thing that we would now like to put into this whole big thing\n\n425\n00:26:02,928 --> 00:26:05,568\n进行处理 并观察是否有输出\nand process and see if anything comes out the other side.\n\n426\n00:26:06,670 --> 00:26:09,888\n如果输出了结果 那么查询就为真\nIf anything comes out, it'll be true.\n\n427\n00:26:11,330 --> 00:26:12,370\n这是基本的思想\nThat's the basic idea.\n\n428\n00:26:12,370 --> 00:26:13,248\n因此 通常来说\nSo in general,\n\n429\n00:26:14,032 --> 00:26:15,408\n我们实现规则的方法就是\nthe way we implement a rule\n\n430\n00:26:15,856 --> 00:26:18,896\n用规则的结论去匹配\nis we match the conclusion of the rule\n\n431\n00:26:20,864 --> 00:26:22,960\n假设为真的查询\nagainst something we might want to check it's true.\n\n432\n00:26:23,580 --> 00:26:25,120\n这个过程会产生一本字典\nThat match gives us a dictionary,\n\n433\n00:26:25,296 --> 00:26:28,224\n在有了相关字典后\nand with respect to that dictionary,\n\n434\n00:26:30,352 --> 00:26:34,512\n我们来处理规则的体\nwe process the body of the rule.\n\n435\n00:26:36,336 --> 00:26:37,680\n基本上就是这样了\nWell, that's really all there is,\n\n436\n00:26:38,640 --> 00:26:41,440\n但还有两个技术点\nexcept for two technical points.\n\n437\n00:26:43,040 --> 00:26:44,320\n首先就是\nThe first technical point is that\n\n438\n00:26:45,744 --> 00:26:47,264\n我也可能有其它的问法\nI might have said something else.\n\n439\n00:26:47,510 --> 00:26:48,416\n比如说\nI might have said\n\n440\n00:26:50,544 --> 00:26:52,368\n查询计算机分部的BOSS\nwho's the boss in the computer division?\n\n441\n00:26:52,544 --> 00:26:56,320\n就可以查询 (BOSS ?WHO COMPUTER)\nSo I might say boss of who in computer division.\n\n442\n00:27:00,784 --> 00:27:01,632\n这样做了以后\nAnd if I did that,\n\n443\n00:27:02,576 --> 00:27:04,624\n我真正想要做的\nwhat I would really like to do in effect is not\n\n444\n00:27:05,040 --> 00:27:06,496\n就是先建立一本字典\nis start up this dictionary\n\n445\n00:27:08,352 --> 00:27:09,888\n其中有一些约束\nwith a match that sort of says,\n\n446\n00:27:09,936 --> 00:27:11,200\n比如 ?D=COMPUTER\nwell, d is computer\n\n447\n00:27:14,352 --> 00:27:18,480\n而?Z等同于?WHO\nand z is whatever who is.\n\n448\n00:27:21,700 --> 00:27:23,220\n我们的匹配器不会那么做\nAnd our matcher won't quite do that.\n\n449\n00:27:23,220 --> 00:27:27,008\n这不是模式和数据的匹配方式\nThat's not quite matching a pattern against data.\n\n450\n00:27:28,580 --> 00:27:29,728\n这是在匹配两个模式\nIt's matching two patterns\n\n451\n00:27:29,744 --> 00:27:31,584\n并判断它们是否一致\nsort of saying are they consistent or not\n\n452\n00:27:31,904 --> 00:27:33,480\n又是什么使它们不一致\nor what ways make them consistent.\n\n453\n00:27:33,480 --> 00:27:36,432\n换句话说 我们需要的不是一个模式匹配器\nIn other words, what we need is not quite a pattern matcher,\n\n454\n00:27:36,960 --> 00:27:38,912\n而是一种更一般性的东西\nbut something a little bit more general\n\n455\n00:27:39,136 --> 00:27:40,112\n就是“合一”算法\ncalled a unifier.\n\n456\n00:27:44,420 --> 00:27:48,064\n“合一”是更为一般化的模式匹配算法\nAnd a unifier is a slight generalization of a pattern matcher.\n\n457\n00:27:49,530 --> 00:27:52,176\n合一算法接收两条模式\nWhat a unifier does is take two patterns\n\n458\n00:27:53,232 --> 00:27:57,536\n它考虑的是：可以找到哪些一般性的元素\nand say what's the most general thing you can substitute\n\n459\n00:27:58,208 --> 00:28:00,016\n用来代换模式中的变量\nfor the variables in those two patterns\n\n460\n00:28:02,688 --> 00:28:05,088\n使得它俩能够同时满足\nto make them satisfy the pattern simultaneously?\n\n461\n00:28:05,680 --> 00:28:06,608\n让我来举个例子\nLet me give you an example.\n\n462\n00:28:08,864 --> 00:28:14,490\n我有一个含有两个元素的模式：(?X ?X)\nIf I have the pattern two-element list, which is x and x,\n\n463\n00:28:15,760 --> 00:28:17,152\n它描述的是一个二元表\nso this is I have a two-element list\n\n464\n00:28:17,320 --> 00:28:18,640\n不管元素具体是什么\nwhere both elements are the same\n\n465\n00:28:18,672 --> 00:28:20,040\n但两个元素是相同的\nand otherwise I don't care what they are,\n\n466\n00:28:20,400 --> 00:28:22,832\n我把它与另一个模式进行“合一”\nand I unify that against the pattern\n\n467\n00:28:22,920 --> 00:28:24,624\n后者描述的是一个二元表\nthat says there's a two-element list,\n\n468\n00:28:24,656 --> 00:28:27,616\n首元素一张由A、?Y、C构成的表\nand the first one is a and something and c\n\n469\n00:28:28,000 --> 00:28:30,144\n而第二个元素是由A、B、?Z构成的表\nand the second one is a and b and z,\n\n470\n00:28:33,070 --> 00:28:34,880\n那么 合一算法能够告诉我\nthen what the unifier should tell me is,\n\n471\n00:28:34,896 --> 00:28:36,176\n在生成的字典中\noh yeah, in that dictionary,\n\n472\n00:28:36,352 --> 00:28:37,968\n?X必须是(A B C)\nx has to be a, b, c,\n\n473\n00:28:39,344 --> 00:28:41,920\n?Y必须为B ?Z必须为C\nand y has to be d and z has to be c.\n\n474\n00:28:43,440 --> 00:28:46,288\n这些是我必须对X、Y以及Z施加的约束\nThose are the restrictions I'd have to put on the values of x, y, and z\n\n475\n00:28:46,336 --> 00:28:47,580\n以便让两个模式合一\nto make these two unify,\n\n476\n00:28:48,120 --> 00:28:50,848\n或者换句话来说 让它匹配这个?X\nor in other words, to make this match x\n\n477\n00:28:51,152 --> 00:28:53,370\n让它匹配这个?X\nand make this match x.\n\n478\n00:28:55,280 --> 00:28:57,760\n合一算法需要能够推断出这些\nThe unifier should be able to deduce that.\n\n479\n00:28:58,540 --> 00:29:01,080\n但是合一算法也会遇到复杂的情况\nBut the unifier may-- there are more complicated things.\n\n480\n00:29:01,080 --> 00:29:03,072\n我可能会询问一些复杂的查询\nI might have said something a little bit more complicated.\n\n481\n00:29:03,488 --> 00:29:05,744\n比如这是一个二元表\nI might have said there's a list with two elements,\n\n482\n00:29:07,008 --> 00:29:08,288\n其中的元素都是相同的\nand they're both the same,\n\n483\n00:29:08,864 --> 00:29:11,152\n它要与这个模式进行合一\nand they should unify against something of this form.\n\n484\n00:29:12,650 --> 00:29:15,360\n合一算法也要能够从中推断出\nAnd the unifier should be able to deduce from that.\n\n485\n00:29:16,890 --> 00:29:19,570\n?Y必须为B\nLike that y would have to be b. y would have to be b.\n\n486\n00:29:19,570 --> 00:29:22,128\n因为这两个是一样的\nBecause these two are the same,\n\n487\n00:29:22,224 --> 00:29:23,520\n因此?Y就是B\nso y's got to be b.\n\n488\n00:29:24,340 --> 00:29:27,536\n这里 ?V应该为A\nAnd v here would have to be a.\n\n489\n00:29:28,940 --> 00:29:30,992\n只要?Z和?W取值相同\nAnd z and w can be anything,\n\n490\n00:29:31,008 --> 00:29:32,432\n它们就可以是任意值\nbut they have to be the same thing.\n\n491\n00:29:35,710 --> 00:29:41,760\n?X就应该是(B A ?W) 其中?W为任意值\nAnd x would have to be b, followed by a, followed by whatever w\n\n492\n00:29:42,832 --> 00:29:44,680\n或者是?Z -- 因为?Z和?W是一致的\nor whatever z is, which is the same.\n\n493\n00:29:44,704 --> 00:29:49,420\n发现了么 合一算法需要从这些模式中推断出信息\nSo you see, the unifier somehow has to deduce things to unify these patterns.\n\n494\n00:29:50,880 --> 00:29:53,520\n所以你们可能认为 这其中有某种魔法般的推理\nSo you might think there's some kind of magic deduction going on,\n\n495\n00:29:54,272 --> 00:29:55,232\n但其实并不是\nbut there's not.\n\n496\n00:29:55,850 --> 00:29:59,888\n合一算法基本上只是对模式匹配的小小修改\nA unifier is basically a very simple modification of a pattern matcher.\n\n497\n00:30:00,150 --> 00:30:01,856\n如果你们翻阅教材 就会发现\nAnd if you look in the book, you'll see something like\n\n498\n00:30:02,256 --> 00:30:06,160\n在模式匹配算法中加入了三到四行代码\nlike three or four lines of code added to the pattern matcher you just saw\n\n499\n00:30:06,496 --> 00:30:08,176\n来处理对称的情况\nto handle the symmetric case.\n\n500\n00:30:08,280 --> 00:30:10,816\n还记得吗 模式匹配中有一处代码判断\nRemember, the pattern matcher has a place where it says\n\n501\n00:30:11,664 --> 00:30:14,288\n这个变量匹配一个常量吗？\nis this variable matching a constant.\n\n502\n00:30:14,980 --> 00:30:16,420\n如果是的话 就在字典中进行检查\nAnd if so, it checks in the dictionary.\n\n503\n00:30:16,420 --> 00:30:18,256\n在合一算法中只有另一条子句\nThere's only one other clause in the unifier,\n\n504\n00:30:18,496 --> 00:30:20,752\n它判断两个变量是否相匹配\nwhich says is this variable matching a variable,\n\n505\n00:30:22,000 --> 00:30:23,424\n这种情况下你去查询字典\nin which case you go look in the dictionary\n\n506\n00:30:23,456 --> 00:30:25,680\n看它们在字典的约束下是否一致\nand see if that's consistent with what's in the dictionary.\n\n507\n00:30:27,030 --> 00:30:31,136\n因此 这门语言中的所有“推断”\nSo all the, quote, deduction that's in this language,\n\n508\n00:30:31,280 --> 00:30:34,590\n你会发现它蕴含在规则应用中\nif you sort of look at it, sort of sits in the rule applications,\n\n509\n00:30:34,992 --> 00:30:37,888\n更进一步地考察 你会发现在合一算法中\nwhich, if you look at that, sits in the unifier,\n\n510\n00:30:38,368 --> 00:30:40,320\n如果更进一步地用“显微镜”观察\nwhich, if you look at that under a microscope,\n\n511\n00:30:40,560 --> 00:30:43,968\n基本上就在模式匹配算法中\nsits essentially in the pattern matcher.\n\n512\n00:30:44,944 --> 00:30:47,072\n这其中并没有什么魔法\nThere's no magic at all going on in there.\n\n513\n00:30:47,410 --> 00:30:50,256\n而你们所见到的“推断”\nAnd the, quote, deduction that you see\n\n514\n00:30:50,944 --> 00:30:52,896\n只是因为其中的递归\nis just the fact that there's this recursion,\n\n515\n00:30:52,928 --> 00:30:55,696\n它一点一点地回绕MATCH过程\nwhich is unwinding the matches bit by bit.\n\n516\n00:30:56,030 --> 00:30:58,032\n它让这个过程看起来很聪明\nSo it looks like this thing is being very clever,\n\n517\n00:30:58,448 --> 00:31:00,368\n但它实际上并不是那么聪明\nbut in fact, it's not being very clever at all.\n\n518\n00:31:02,140 --> 00:31:04,416\n当然 合一算法需要聪明地识别出一些情况\nThere are cases where a unifier might have to be clever.\n\n519\n00:31:04,880 --> 00:31:05,872\n我来举个例子吧\nLet me show you one more.\n\n520\n00:31:11,070 --> 00:31:13,360\n假设我想要用一个二元表进行合一\nSuppose I want to unify a list of two elements,\n\n521\n00:31:13,488 --> 00:31:14,816\n(?X ?X)\nx and x,\n\n522\n00:31:17,240 --> 00:31:22,144\n另一个模式则是 (?Y (a . ?Y))\nwith a thing that says it's y followed by a dot y.\n\n523\n00:31:24,370 --> 00:31:26,128\n现在 如果你想一想它所表达的意思\nNow, if you think of what that would have to mean,\n\n524\n00:31:26,864 --> 00:31:29,712\n它表示了?X应该跟?Y一致\nit would have to mean that x had better be the same as y,\n\n525\n00:31:30,928 --> 00:31:31,664\n同时呢\nbut also\n\n526\n00:31:31,824 --> 00:31:36,160\n?X又应该跟(A . ?Y)相同\nx had better be the same as a list whose first element is a and whose rest is y.\n\n527\n00:31:37,330 --> 00:31:39,456\n如果你仔细思考它成立的条件\nAnd if you think about what that would have to mean,\n\n528\n00:31:42,272 --> 00:31:44,710\n你会发现 ?Y必须是一个由A构成的无穷表\nit would have to mean that y is the infinite list of a's.\n\n529\n00:31:47,500 --> 00:31:48,352\n从某种角度来说\nIn some sense,\n\n530\n00:31:49,216 --> 00:31:52,400\n为了完成这样的合一\nin order to do that unification,\n\n531\n00:31:52,608 --> 00:31:54,848\n我需要求解一个不动点方程\nI have to solve the fixed-point equation\n\n532\n00:31:55,056 --> 00:32:01,840\n(CONS 'A Y)=Y\ncons of a to y is equal to y.\n\n533\n00:32:04,570 --> 00:32:06,960\n通常来说 --- 我这个例子很简单\nAnd in general, I wrote a very simple one.\n\n534\n00:32:07,290 --> 00:32:08,672\n但实际进行合一时\nReally doing unification\n\n535\n00:32:08,976 --> 00:32:11,984\n我们可能要求解一个任意的不动点方程\nmight have to solve an arbitrary fixed-point equation:\n\n536\n00:32:12,016 --> 00:32:13,424\n(F Y)=Y\nf of y equals y.\n\n537\n00:32:15,530 --> 00:32:17,088\n你基本上不能保证\nAnd basically, you can't do that\n\n538\n00:32:17,104 --> 00:32:19,472\n在有穷时间内找到解\nand make the thing finite all the time.\n\n539\n00:32:20,570 --> 00:32:23,600\n我们的逻辑语言又该如何处理这类情况呢？\nSo how does the logic language handle that?\n\n540\n00:32:24,896 --> 00:32:26,480\n答案就是：“不处理”\nThe answer is it doesn't.\n\n541\n00:32:27,168 --> 00:32:28,048\n它会撒手不干\nIt just punts.\n\n542\n00:32:28,730 --> 00:32:31,072\n合一算法中有一处小检查\nAnd there's a little check in the unifier,\n\n543\n00:32:31,312 --> 00:32:33,824\n用来判断是否为困难的情况\nwhich says, oh, is this one of the hard cases\n\n544\n00:32:34,448 --> 00:32:38,000\n也就是 匹配这些东西需要求解不动点方程\nwhich when I go to match things would involve solving a fixed-point equation?\n\n545\n00:32:38,650 --> 00:32:40,816\n遇到这类情况 我就撒手不干\nAnd in this case, I will throw up my hands.\n\n546\n00:32:42,840 --> 00:32:44,656\n如果不进行这样的检查\nAnd if that check were not in there,\n\n547\n00:32:45,008 --> 00:32:45,888\n会发生什么情况？\nwhat would happen?\n\n548\n00:32:47,990 --> 00:32:49,104\n大多数情况就是\nIn most cases is\n\n549\n00:32:49,136 --> 00:32:51,312\n合一算法会陷入无穷循环\nthat the unifier would just go into an infinite loop.\n\n550\n00:32:53,740 --> 00:32:56,544\n其它的逻辑语言有类似的工作原理\nAnd other logic programming languages work like that.\n\n551\n00:32:56,800 --> 00:32:58,144\n因此这其中没有什么魔法\nSo there's really no magic.\n\n552\n00:32:58,220 --> 00:32:59,936\n简单的情况由匹配器完成\nThe easy case is done in a matcher.\n\n553\n00:33:00,100 --> 00:33:01,584\n困难的情况根本不去处理\nThe hard case is not done at all.\n\n554\n00:33:02,960 --> 00:33:05,472\n这就是这种技术的现状\nAnd that's about the state of this technology.\n\n555\n00:33:11,888 --> 00:33:14,240\n现在 我来形式化地描述一下\nOK, Let me just say again formally\n\n556\n00:33:14,272 --> 00:33:16,384\n规则系统的运行原理 -- 也就是合一算法\nhow rules work now that I talked about unifiers.\n\n557\n00:33:17,390 --> 00:33:18,752\n因此 正式的定义就是\nSo the official definition\n\n558\n00:33:19,200 --> 00:33:20,960\n应用一条规则\nis that to apply a rule,\n\n559\n00:33:24,176 --> 00:33:27,136\n我们需要使用一些之前的术语\nwe-- well, let's start using some words we've used before.\n\n560\n00:33:28,270 --> 00:33:32,016\n我们把向查询的盒子中\nLet's talk about sticking dictionaries into\n\n561\n00:33:32,880 --> 00:33:34,784\n塞入字典称作是\nthese big boxes of query things\n\n562\n00:33:34,816 --> 00:33:38,544\n相对一个环境或者框架\nas evaluating these large queries\n\n563\n00:33:39,952 --> 00:33:43,850\n对这些大型查询求值\nrelative to an environment or a frame.\n\n564\n00:33:43,850 --> 00:33:45,040\n因此 当我们谈及“字典”的时候\nSo when you think of that dictionary,\n\n565\n00:33:45,072 --> 00:33:46,280\n“字典”究竟是什么？\nwhat's the dictionary after all?\n\n566\n00:33:46,720 --> 00:33:48,180\n它是符号的一系列语义\nIt's a bunch of meanings for symbols.\n\n567\n00:33:48,180 --> 00:33:50,224\n我们把它叫做“框架”或者“环境”\nThat's what we've been calling frames or environments.\n\n568\n00:33:51,800 --> 00:33:55,970\n根据环境进行操作 又是什么？\nWhat does it mean to do some processing relevant to an environment?\n\n569\n00:33:55,970 --> 00:33:57,424\n我们把这个叫做“求值”\nThat's what we've been calling evaluation.\n\n570\n00:33:58,336 --> 00:34:01,560\n因此我们就说 应用一条规则的方法是\nSo we can say the way that you apply a rule\n\n571\n00:34:01,920 --> 00:34:06,160\n先通过将给定的查询与规则的结论合一 得到环境\nis to evaluate the rule body relative to an environment\n\n572\n00:34:06,672 --> 00:34:11,580\n再在该环境中求值相应规则的体\nthat's formed by unifying the rule conclusion with the given query.\n\n573\n00:34:13,230 --> 00:34:14,512\n我想要让你们注意的是\nAnd the thing I want you to notice\n\n574\n00:34:14,800 --> 00:34:17,088\n这非常像是\nis the complete formal similarity\n\n575\n00:34:18,160 --> 00:34:21,504\n元循环求值器以及代换模型\nto the net of circular evaluator or the substitution model.\n\n576\n00:34:21,630 --> 00:34:22,736\n规则的应用就是\nTo apply a procedure,\n\n577\n00:34:22,860 --> 00:34:28,368\n在一个环境中求值规则的体\nwe evaluate the procedure body relative to an environment\n\n578\n00:34:28,544 --> 00:34:33,136\n环境是通过将实际参数与形式参数绑定起来得到的\nthat's formed by blinding the procedure parameters to the arguments.\n\n579\n00:34:34,560 --> 00:34:36,416\n规则、规则的应用、过程的应用\nThere's a complete formal similarity there\n\n580\n00:34:36,440 --> 00:34:40,416\n它们在形式上完全相似\nbetween the rules, rule application, and procedure application\n\n581\n00:34:40,576 --> 00:34:42,304\n尽管它们又非常不同\neven though these things are very, very different.\n\n582\n00:34:43,650 --> 00:34:45,616\n再一次地出现了EVAL-APPLY循环\nAnd again, you have the EVAL APPLY loop.\n\n583\n00:34:47,290 --> 00:34:49,520\nEVAL-APPLY\nEVAL and APPLY.\n\n584\n00:34:53,392 --> 00:34:57,390\n因此通常来说 我们可能会处理一些复合表达式\nSo in general, I might be processing some combined expression\n\n585\n00:34:57,424 --> 00:34:59,136\n它们会变成规则的应用\nthat will turn into a rule application,\n\n586\n00:35:00,704 --> 00:35:03,280\n进一步又会产生字典、框架或者环境\nwhich will generate some dictionaries or frames or environments--\n\n587\n00:35:03,312 --> 00:35:04,720\n不管你要怎么叫它\nwhatever you want to call them-- from match,\n\n588\n00:35:05,024 --> 00:35:08,432\n它们随后又会作为某个大的复合对象的输入\nwhich will then be the input to some big compound thing like this.\n\n589\n00:35:08,660 --> 00:35:11,776\n这有它的一部分 并可能有其它规则的应用\nThis has pieces of it and may have other rule applications.\n\n590\n00:35:13,580 --> 00:35:15,680\n这基本上就是相同的循环\nAnd you have essentially the same cycle\n\n591\n00:35:15,720 --> 00:35:18,688\n尽管这里没有什么东西看起来像过程\neven though there's nothing here at all that looks like procedures.\n\n592\n00:35:19,680 --> 00:35:21,872\n这是因为我们创建的语言\nIt really has to do with the fact you've built a language\n\n593\n00:35:22,080 --> 00:35:25,490\n它们的组合手段和抽象手段以某种方式展开\nwhose means of combination and abstraction unwind in certain ways.\n\n594\n00:35:28,770 --> 00:35:29,520\n通常来说\nAnd then in general,\n\n595\n00:35:29,776 --> 00:35:31,392\n最顶层所发生的是\nwhat happens at the very top level,\n\n596\n00:35:33,792 --> 00:35:35,968\n数据库中也有一些规则\nyou might have rules in your database also,\n\n597\n00:35:36,656 --> 00:35:38,704\n数据库中的数据也可能是规则\nso things in this database might be rules.\n\n598\n00:35:40,460 --> 00:35:42,064\n它们用来检查对象是否为真\nThere are ways to check that things are true.\n\n599\n00:35:42,920 --> 00:35:44,896\n所以这里可能会有规则检查\nSo it might come in here and have to do a rule check.\n\n600\n00:35:46,750 --> 00:35:48,160\n然后就会有一些控制结构\nAnd then there's some control structure\n\n601\n00:35:48,192 --> 00:35:50,480\n用来判断你访问的是规则\nwhich says, well, you look at some rules, and you look at some data elements,\n\n602\n00:35:50,512 --> 00:35:51,808\n还是数据元素\nand you look at some rules and data elements,\n\n603\n00:35:51,840 --> 00:35:53,120\n然后不断地把它们扇出来开\nand these fan out and out and out.\n\n604\n00:35:53,350 --> 00:35:55,488\n所以基本上不可能说清楚\nSo it becomes essentially impossible\n\n605\n00:35:55,680 --> 00:35:57,696\n是用什么样的顺序来查询这些东西的\nto say what order it's looking at these things in,\n\n606\n00:35:58,208 --> 00:36:00,272\n是广度优先还是深度优先\nwhether it's breadth first or depth first or anything.\n\n607\n00:36:00,280 --> 00:36:01,648\n另外一个原因是\nAnd it's even more impossible\n\n608\n00:36:01,664 --> 00:36:05,584\n我们通过惰性流隐藏了实际执行顺序\nbecause the actual order is somehow buried in the delays of the streams.\n\n609\n00:36:07,696 --> 00:36:11,168\n因此很难说清楚它的扫描顺序\nSo what's very hard to tell from this is the order in which it's scanned.\n\n610\n00:36:11,270 --> 00:36:12,160\n但真实的是\nBut what's true is,\n\n611\n00:36:12,192 --> 00:36:13,648\n由于你是在流视图观察它的\nbecause you're looking at the stream view,\n\n612\n00:36:13,904 --> 00:36:15,820\n而它们最终都要被扫描到\nis that all of them eventually get looked at.\n\n613\n00:36:24,980 --> 00:36:28,150\n这里还有一个小小的技术问题\nLet me just mention one tiny technical problem.\n\n614\n00:36:30,880 --> 00:36:33,552\n假设我在这里输入\nUm Suppose I tried over here.\n\n615\n00:36:37,530 --> 00:36:41,008\n假设我输入(BOSS ?Y COMPUTER)\nSuppose I tried saying boss of y is computer,\n\n616\n00:36:44,224 --> 00:36:45,780\n然后就会发生一件有意思的事儿\nthen a funny thing would happen.\n\n617\n00:36:45,780 --> 00:36:50,256\n这里的字典就有一项?Y\nAs I stuck a dictionary with y in here,\n\n618\n00:36:52,736 --> 00:36:57,376\n而这两个?Y是不相同的\nI might get-- this y is not the same as that y,\n\n619\n00:36:57,424 --> 00:37:00,624\n后者是其它人的工作描述\nwhich was the other piece of somebody's job description.\n\n620\n00:37:01,580 --> 00:37:03,808\n因此 按照输入“照本宣科”地执行的话\nSo if I really only did literally what I said,\n\n621\n00:37:04,224 --> 00:37:06,448\n我们就会遇到变量冲突的问题\nwe'd get some variable conflict problems.\n\n622\n00:37:09,280 --> 00:37:10,480\n所以我骗了你们一下\nSo I lied to you a little bit.\n\n623\n00:37:10,930 --> 00:37:13,840\n注意 我们之前也遇到过同样的问题\nNotice that problem is exactly a problem we've run into before.\n\n624\n00:37:14,270 --> 00:37:15,568\n具体来说就是\nIt is precisely\n\n625\n00:37:15,968 --> 00:37:18,360\n一门语言需要局部变量\nthe need for local variables in a language.\n\n626\n00:37:19,240 --> 00:37:21,744\n当我计算SQUARE和SUM-SQUARES的时候\nWhen I square, when I have the sum of squares,\n\n627\n00:37:21,792 --> 00:37:23,390\n这两个X应该是不同的\nthat x had better not be that x.\n\n628\n00:37:24,960 --> 00:37:26,320\n同样的道理\nThat's exactly the same as\n\n629\n00:37:27,392 --> 00:37:29,776\n这两个?Y应该也不相同\nas this y had better not be that y.\n\n630\n00:37:31,800 --> 00:37:32,752\n我们知道该如何解决\nAnd we know how to solve that.\n\n631\n00:37:32,784 --> 00:37:34,490\n就是引入环境模型\nWe built -- That was this whole environment model,\n\n632\n00:37:34,512 --> 00:37:37,040\n我们构建类似于“框架链”一类的东西\nand we built chains of frames and all sorts of things like that.\n\n633\n00:37:37,710 --> 00:37:39,104\n还有更加“粗暴”的解决方法\nThere's a much more brutal way to solve it.\n\n634\n00:37:39,104 --> 00:37:41,730\n在查询语言中 我们根本不这么做\nIn the query language, we didn't even do that.\n\n635\n00:37:41,730 --> 00:37:43,184\n我们的解决方法非常粗暴\nWe did something completely brutal.\n\n636\n00:37:43,540 --> 00:37:45,936\n我们规定 每次你在应用一条规则的时候\nWe said every time you apply a rule,\n\n637\n00:37:47,264 --> 00:37:49,632\n用一个不会引起冲突的唯一名字\nrename consistently all the variables in the rule\n\n638\n00:37:49,776 --> 00:37:53,504\n统一地为规则中的所有变量更名\nto some new unique names that won't conflict with anything.\n\n639\n00:37:54,040 --> 00:37:57,104\n这个从概念上来说更简单\nIf you looked at the -- That's conceptually simpler,\n\n640\n00:37:57,120 --> 00:37:59,240\n但既粗暴 又不是很有效\nbut really brutal and not particularly efficient.\n\n641\n00:37:59,970 --> 00:38:01,152\n但是请注意\nBut notice,\n\n642\n00:38:01,392 --> 00:38:04,688\n如果我们对Lisp中定义的过程也这么处理\nwe could have gotten rid of all of our environment structures\n\n643\n00:38:05,500 --> 00:38:08,720\n那么就不需要环境模型了\nif we defined for procedures in Lisp the same thing.\n\n644\n00:38:08,752 --> 00:38:11,560\n如果我们每次在应用一个过程的时候\nIf every time we applied a procedure and did the substitution model\n\n645\n00:38:11,872 --> 00:38:13,904\n我们为过程中的所有变量更名\nwe renamed all the variables in the procedure,\n\n646\n00:38:14,192 --> 00:38:16,288\n那么我们就不需要担心局部变量了\nthen we never would have had to worry about local variables\n\n647\n00:38:16,336 --> 00:38:17,392\n因为它们不会出现\nbecause they would never arise.\n\n648\n00:38:19,040 --> 00:38:20,416\n但这种做法比较低效\nOK, well, that would be inefficient,\n\n649\n00:38:20,912 --> 00:38:23,040\n在我们的查询语言中同样也比较低效\nand it's inefficient here in the query language, too,\n\n650\n00:38:23,296 --> 00:38:24,592\n但我们还是这样做了 并让它保持简单\nbut we did it to keep it simple.\n\n651\n00:38:25,610 --> 00:38:26,672\n有问题吗？\nLet's break for questions.\n\n652\n00:38:30,880 --> 00:38:33,392\n学生：您这一小节开始的时候\nAUDIENCE: When you started this section,\n\n653\n00:38:33,408 --> 00:38:39,600\n就强调APPLY-EVAL模型是多么的强大\nyou emphasized how powerful our APPLY EVAL model was\n\n654\n00:38:39,632 --> 00:38:41,170\n以至于任何语言都适用\nthat we could use it for any language.\n\n655\n00:38:41,170 --> 00:38:43,392\n但你又说这门语言将会非常不同\nAnd then you say we're going to have this language which is so different.\n\n656\n00:38:43,950 --> 00:38:45,136\n但最后却发现这门语言\nIt turns out that this language,\n\n657\n00:38:45,584 --> 00:38:47,880\n就像你指出的那样--也是同样的\nas you just pointed out, is very much the same.\n\n658\n00:38:47,880 --> 00:38:49,856\n我在想 您是否是在论证\nI'm wondering if you're arguing that all languages end up\n\n659\n00:38:50,480 --> 00:38:54,576\n所有的语言都可以转化成 规则或过程的应用\ncoming down to this you can apply a rule or apply a procedure\n\n660\n00:38:55,120 --> 00:38:55,984\n或者类似的\nor some kind of apply?\n\n661\n00:38:57,072 --> 00:38:58,880\n教授：可以说 几乎所有语言\nPROFESSOR: I would say that pretty much any language\n\n662\n00:38:58,928 --> 00:39:00,304\n我们通过组合手段构建对象\nwhere you really are building up\n\n663\n00:39:00,928 --> 00:39:04,400\n用简单的名字给它们命名\nthese means of combination and giving them simpler names\n\n664\n00:39:04,704 --> 00:39:06,864\n你可以把任何类似的 比如\nand you're saying anything of the sort, like\n\n665\n00:39:07,790 --> 00:39:09,900\n有一种一般性的表达式\nhere's a general kind of expression,\n\n666\n00:39:09,984 --> 00:39:11,408\n比如说如何计算某数的平方\nlike how to square something,\n\n667\n00:39:12,032 --> 00:39:14,208\n几乎所有的东西都可以称为“过程”\nalmost anything that you would call a procedure.\n\n668\n00:39:14,880 --> 00:39:15,888\n如果语言中有这么一部分的话\nIf that's got to have parts,\n\n669\n00:39:15,904 --> 00:39:17,248\n那么你就需要能够展开它们\nyou have to unwind those parts.\n\n670\n00:39:18,020 --> 00:39:20,192\n你需要有某种组织 使得\nYou have to have some kind of organization which says\n\n671\n00:39:20,570 --> 00:39:24,032\n当你查看这些抽象变量 或者说标签的时候\nwhen I look at the abstract variables or tags\n\n672\n00:39:24,064 --> 00:39:27,100\n它们可能代表着某些特定的东西\nor whatever you want to call them that might stand for particular things,\n\n673\n00:39:28,336 --> 00:39:29,344\n你必须一直跟踪它们\nyou have to keep track of that,\n\n674\n00:39:29,392 --> 00:39:30,912\n这就会形成类似于环境的结构\nand that's going to be something like an environment.\n\n675\n00:39:31,720 --> 00:39:32,544\n让后当你要\nAnd then if you say\n\n676\n00:39:32,704 --> 00:39:35,264\n展开复合对象其中的一个部分的时候\nthis part can have parts which I have to unwind,\n\n677\n00:39:35,808 --> 00:39:37,440\n你就需要EVAL-APPLY循环了\nyou've got to have something like this cycle.\n\n678\n00:39:39,970 --> 00:39:43,200\n有很多很多的语言有这样的特点\nAnd lots and lots of languages have that character\n\n679\n00:39:43,360 --> 00:39:45,408\n它们也是按这种方式组织的\nas long ... when they sort of get put together in this way.\n\n680\n00:39:45,590 --> 00:39:47,200\n而这门语言特殊之处在于\nThis language again really is different\n\n681\n00:39:47,216 --> 00:39:49,504\n从外界看 并没有“过程”\nbecause there's nothing like procedures on the outside.\n\n682\n00:39:50,690 --> 00:39:52,688\n而当你剖开表层 深入到实现中去\nWhen you go below the surface and you see the implementation,\n\n683\n00:39:52,704 --> 00:39:54,240\n当然 你会发现本质是一样的\nof course, it starts looking the same.\n\n684\n00:39:54,870 --> 00:39:56,950\n但是从外界来看 这是一种非常不同的世界观\nBut from the outside, it's a very different world view.\n\n685\n00:39:56,950 --> 00:39:58,544\n你没有计算输入的函数\nYou're not computing functions of inputs.\n\n686\n00:40:03,970 --> 00:40:05,712\n学生：您之前提到过\nAUDIENCE: You mentioned earlier that\n\n687\n00:40:06,608 --> 00:40:09,552\n当用模式匹配来实现这些规则时\nwhen you build all of these rules in pattern matcher\n\n688\n00:40:10,010 --> 00:40:11,424\n由于使用了流实现延迟求值\nand with the delayed action of streams,\n\n689\n00:40:11,456 --> 00:40:12,720\n所以没有办法知道\nyou really have no way to know\n\n690\n00:40:13,376 --> 00:40:15,360\n对象的求值顺序\nin what order things are evaluated.\n\n691\n00:40:15,584 --> 00:40:15,940\n教授：是这样的\nPROFESSOR: Right.\n\n692\n00:40:15,940 --> 00:40:18,288\n学生：但这就表明\nAUDIENCE: And that would indicate then that\n\n693\n00:40:18,940 --> 00:40:22,288\n我们只能表达总是为真的陈述性知识\nyou should only express declarative knowledge that's true for all-time,\n\n694\n00:40:22,304 --> 00:40:23,790\n语言并不支持时间序列\nno-time sequence built into it.\n\n695\n00:40:23,950 --> 00:40:25,472\n否则的话 后果就会--\nOtherwise, these things get all--\n\n696\n00:40:27,390 --> 00:40:28,768\n教授：是的 非常正确\nPROFESSOR: Yes. Yes.\n\n697\n00:40:28,820 --> 00:40:29,488\n问题在于\nThe question is\n\n698\n00:40:30,064 --> 00:40:32,608\n这个本来就是用来处理陈述性知识的\nthis really is set up for doing declarative knowledge,\n\n699\n00:40:33,264 --> 00:40:34,816\n而就我目前所演示的来说 不支持\nand as I presented it-- no\n\n700\n00:40:35,712 --> 00:40:39,568\n休息之后我会向你们揭露这其中的丑陋之处\nand I'll show you some of the ugly warts under this after the break.\n\n701\n00:40:40,830 --> 00:40:42,608\n就如我目前所展示的 它只是进行逻辑运算\nAs I presented it, it's just doing logic.\n\n702\n00:40:43,070 --> 00:40:44,528\n原理上来说 如果我们做的是逻辑运算\nAnd in principle, if it were logic,\n\n703\n00:40:44,544 --> 00:40:46,810\n用什么顺序完成并不会造成影响\nit wouldn't matter what order it's getting done.\n\n704\n00:40:48,840 --> 00:40:51,552\n但是呢\nAnd it's quite true\n\n705\n00:40:51,600 --> 00:40:53,616\n当你在进行一些具有副作用的操作的时候\nwhen you start doing things where you have side effects\n\n706\n00:40:53,680 --> 00:40:55,200\n比如向数据库中添加项\nlike adding things to the database\n\n707\n00:40:55,230 --> 00:40:58,160\n从中取出项 等等操作\nand taking things out, and we'll see some others,\n\n708\n00:40:58,752 --> 00:41:00,832\n你就丧失了这类控制\nyou loose that kind of control.\n\n709\n00:41:01,290 --> 00:41:02,940\n因此 这就与Prolog完全不同\nSo, for example, contrasting with Prolog.\n\n710\n00:41:02,940 --> 00:41:05,152\nProlog有各种功能\nSay Prolog has various features\n\n711\n00:41:05,168 --> 00:41:07,792\n能够让你利用求值的顺序\nwhere you really exploit the order of evaluation.\n\n712\n00:41:09,640 --> 00:41:11,770\n人们也这么来写Prolog\nAnd people write Prolog programs that way.\n\n713\n00:41:11,770 --> 00:41:14,048\n结果发现这样变得非常困难\nThat turns out to be very complicated in Prolog,\n\n714\n00:41:14,320 --> 00:41:17,552\n但如果你是Prolog程序专家 你就可以这么做\nalthough if you're an expert Prolog programmer, you can do it.\n\n715\n00:41:18,590 --> 00:41:20,210\n但是我认为你们现在并不可以\nHowever, here I don't think you can do it at all.\n\n716\n00:41:20,210 --> 00:41:21,248\n它相当复杂\nIt's very complicated\n\n717\n00:41:21,728 --> 00:41:23,648\n因为你们放弃了对事先安排的\nbecause you really are giving up control over\n\n718\n00:41:23,776 --> 00:41:25,728\n求值顺序的控制权\nany prearranged order of trying things.\n\n719\n00:41:27,150 --> 00:41:30,160\n学生：这就表明 当你有一个函数式映射时\nAUDIENCE: Now, that would indicate then that you have a functional mapping.\n\n720\n00:41:30,670 --> 00:41:32,512\n而你最初在讲这门课的时候\nAnd when you started out this lecture,\n\n721\n00:41:32,992 --> 00:41:34,080\n你说过\nyou said that\n\n722\n00:41:34,672 --> 00:41:36,704\n我们在表述作为关系的陈述性知识\nwe express the declarative knowledge which is a relation,\n\n723\n00:41:37,152 --> 00:41:38,810\n因为我们讨论的不是输入和输出\nand we don't talk about the inputs and the outputs.\n\n724\n00:41:41,216 --> 00:41:43,370\n教授：这是关于“函数式”的双关语\nPROFESSOR: Well, there's a pun on functional, right?\n\n725\n00:41:43,370 --> 00:41:45,792\n一种是没有副作用\nThere's functional in the sense of no side effects\n\n726\n00:41:46,208 --> 00:41:48,160\n因此并不依赖于求值的顺序\nand not depending on what order is going on.\n\n727\n00:41:48,700 --> 00:41:51,040\n还有就是数学意义上的“函数”\nAnd then there's functional in the sense of mathematical function,\n\n728\n00:41:51,072 --> 00:41:52,220\n有关于输入和输出\nwhich means input and output.\n\n729\n00:41:52,592 --> 00:41:54,368\n我想这就是你想表达的双关\nAnd it's just that pun that you're making, I think.\n\n730\n00:41:56,510 --> 00:41:58,512\n学生：我对其中两条语句不太明白\nAUDIENCE: I'm a little unclear on what you're doing with\n\n731\n00:41:58,816 --> 00:42:00,704\n也就是那两条有关BOSS的语句\ntwo statements, the two boss statements.\n\n732\n00:42:01,270 --> 00:42:05,744\n是不是 第一条查询构建了一个数据库\nIs the first one building up the database\n\n733\n00:42:05,760 --> 00:42:08,080\n然后第二条查询--\nand the second one a query or--\n\n734\n00:42:09,072 --> 00:42:10,128\n教授：抱歉\nPROFESSOR: OK, I'm sorry.\n\n735\n00:42:12,440 --> 00:42:15,168\n这里的意思是 如果我输入这样的查询\nWhat I meant here, if I type something like this in as a query--\n\n736\n00:42:16,128 --> 00:42:18,448\n我应该最初就给你们举这个例子\nI should have given an example way at the very beginning.\n\n737\n00:42:19,470 --> 00:42:23,520\n如果我输入(JOB (BITDIDDLE BEN) (COMPUTER WIZARD))\nIf I type in job, Ben Bitdiddle, computer wizard,\n\n738\n00:42:25,040 --> 00:42:27,770\n系统会找到一处事实\nwhat the processing will do is if it finds a match,\n\n739\n00:42:28,304 --> 00:42:30,288\n来完全匹配这条查询\nit'll find a match to that exact thing,\n\n740\n00:42:30,864 --> 00:42:33,280\n然后输出(JOB (BITDIDDLE BEN) (COMPUTER WIZARD))\nand it'll type out a job, Ben Bitdiddle, computer wizard.\n\n741\n00:42:34,220 --> 00:42:35,600\n如果没找到这样的匹配\nIf it doesn't find a match,\n\n742\n00:42:35,696 --> 00:42:36,752\n它就什么也不输出\nit won't find anything.\n\n743\n00:42:37,400 --> 00:42:39,552\n我应该这么来表述\nSo what I should have said is the way\n\n744\n00:42:39,568 --> 00:42:42,272\n这门语言是用来查询某个表述是否为真\nyou use the query language to check whether something is true,\n\n745\n00:42:43,408 --> 00:42:45,776\n这是逻辑式编程的目的之一\nthat's one of the things you want to do in logic programming,\n\n746\n00:42:46,416 --> 00:42:49,344\n输入一条查询 要么得到结果 要么没有\nis you type in your query and either that comes out or it doesn't.\n\n747\n00:42:50,680 --> 00:42:52,384\n因此 我这里想要演示的是\nSo what I was trying to illustrate here,\n\n748\n00:42:52,416 --> 00:42:54,800\n我想要在介绍合一算法前\nI wanted to start with a very simple example\n\n749\n00:42:54,832 --> 00:42:56,624\n举一个简单的例子\nbefore talking about unifiers.\n\n750\n00:42:57,480 --> 00:42:58,112\n所以 我应该说\nSo what I should have said,\n\n751\n00:42:58,144 --> 00:43:00,960\n如果我想要检查 这个是否为真\nif I just wanted to check whether this is true,\n\n752\n00:43:01,184 --> 00:43:03,280\n我就可以将它输入 并看有没有任何输出\nI could type that in and see if anything came out\n\n753\n00:43:05,168 --> 00:43:06,272\n学生：然后第二条查询\nAUDIENCE: And then the second one--\n\n754\n00:43:06,288 --> 00:43:07,840\n教授：第二条就是真正意义上的“查询”\nPROFESSOR: The second one would be a real query.\n\n755\n00:43:07,888 --> 00:43:09,120\n学生：好的 真正的查询\nAUDIENCE: A real query, yeah.\n\n756\n00:43:10,770 --> 00:43:13,104\n教授：在这里它就会输出与?WHO相关的信息\nPROFESSOR: What would come out, see, it would go in here say with WHO,\n\n757\n00:43:13,904 --> 00:43:15,744\n就会有一个框架 存储着\nand in would go frame that says z\n\n758\n00:43:16,624 --> 00:43:18,816\n?Z=?WHO ?D=COMPUTER\nz is bound to who and d is bound to computer.\n\n759\n00:43:19,560 --> 00:43:20,496\n这个会传递下去\nAnd this will pass through,\n\n760\n00:43:20,512 --> 00:43:21,952\n传递到这里的时候\nand then by the time it got out of here,\n\n761\n00:43:22,016 --> 00:43:23,250\n?WHO就会被绑定起来\nwho would pick up a binding.\n\n762\n00:43:26,950 --> 00:43:28,768\n学生：在合一那里\nAUDIENCE: On the unifying thing there,\n\n763\n00:43:29,180 --> 00:43:35,968\n我还是不太清楚?WHO和?Z之间发生了什么\nI still am not sure what happens with who and z.\n\n764\n00:43:36,460 --> 00:43:39,584\n要进行合一的话 这里的规则说\nOK being unifying-- the rule here says--\n\n765\n00:43:42,032 --> 00:43:46,224\n你说过 两个模式变量之间不能互相绑定\nOK, so you say that you can't make question mark equal to question mark who.\n\n766\n00:43:46,260 --> 00:43:48,080\n教授：模式匹配器确实不能这样\nPROFESSOR: Right. That's what the matcher can't do.\n\n767\n00:43:48,360 --> 00:43:50,832\n但对合一算法来说\nBut unifier, what this will mean to a unifier\n\n768\n00:43:51,920 --> 00:43:54,016\n就是一个有存储三个变量的环境\nis that there's an environment with three variables.\n\n769\n00:43:56,690 --> 00:43:57,904\n其中?D=COMPUTER\nd here is computer.\n\n770\n00:43:58,520 --> 00:44:00,192\n?Z=?WHO\nz is whatever who is.\n\n771\n00:44:01,830 --> 00:44:05,264\n所以在稍后的匹配过程中\nSo if later on in the matcher routine\n\n772\n00:44:07,200 --> 00:44:10,384\n如果?WHO=3\nit said, for example, who has to be 3,\n\n773\n00:44:12,064 --> 00:44:13,664\n那么当我再查找字典的时候\nthen when I looked up in the dictionary,\n\n774\n00:44:14,000 --> 00:44:16,400\n它会告诉我 因为?Z=?WHO 所以?Z=3\nit will say, oh, z is 3 because it's the same as who.\n\n775\n00:44:18,360 --> 00:44:20,448\n从某种意义上来说 你就只需要修改这一点\nAnd that's in some sense the only thing you need to do\n\n776\n00:44:20,464 --> 00:44:21,984\n就可以把合一算法变成模式匹配器\nto extend the unifier to a matcher.\n\n777\n00:44:22,480 --> 00:44:24,800\n学生：但是看起来你好像告诉了它 如何进行合一\nAUDIENCE: OK, because it looked like when you were telling how to unify,\n\n778\n00:44:24,830 --> 00:44:26,960\n就像你已经解好了方程 准备好了值\nit looked like you would put the things together in such a way\n\n779\n00:44:26,992 --> 00:44:29,232\n并把它们安排成这样\nthat you'd actually solve and have a value for both of them.\n\n780\n00:44:29,770 --> 00:44:31,248\n现在看起来就像是\nAnd what it looks like now\n\n781\n00:44:31,280 --> 00:44:32,832\n你传递了一本字典\nis that you're actually pass a dictionary\n\n782\n00:44:32,880 --> 00:44:34,860\n其中的两个变量是关联起来的\nwith two variables and the variables are linked.\n\n783\n00:44:34,880 --> 00:44:37,230\n教授：实际上 我们在同时求解它们\nPROFESSOR: Right. It only looks like you're solving for both of them\n\n784\n00:44:37,520 --> 00:44:39,744\n这是因为我们想要一下得到整个答案\nbecause you're sort of looking at the whole solution at once.\n\n785\n00:44:40,540 --> 00:44:42,816\n如果你观察它们是如何被递归地构建的\nIf you sort of watch the thing getting built up recursively,\n\n786\n00:44:42,816 --> 00:44:43,740\n基本上就是这样了\nit's merely this.\n\n787\n00:44:44,980 --> 00:44:48,400\n学生：也就是确实要传递含有两个变量的字典？\nAUDIENCE: OK, so you do pass off that dictionary with two variables?\n\n788\n00:44:48,400 --> 00:44:49,110\n教授：是的\nPROFESSOR: That's right.\n\n789\n00:44:49,110 --> 00:44:49,680\n学生：然后把它们关联起来？\nAUDIENCE: And link?\n\n790\n00:44:50,384 --> 00:44:52,912\n教授：就像通常的字典那样\nPROFESSOR: Right. It just looks like an ordinary dictionary.\n\n791\n00:44:54,352 --> 00:44:56,064\n学生：你在讨论合一算法的时候\nAUDIENCE: When you're talking about the unifier,\n\n792\n00:44:56,096 --> 00:45:00,192\n你说过在某些情况下\nis it that there are some cases or some points\n\n793\n00:45:00,752 --> 00:45:03,984\n合一不能够完成\nthat you are not able to unify them?\n\n794\n00:45:04,032 --> 00:45:04,304\n教授：是的\nPROFESSOR: Right.\n\n795\n00:45:04,970 --> 00:45:08,464\n学生：那么 是否可以通过编写规则\nAUDIENCE: Can you just by building the rules or\n\n796\n00:45:09,160 --> 00:45:15,936\n或者 写入那些事先知道可解的形式\nwriting the forms know in advance if you are going to be able to solve\n\n797\n00:45:16,480 --> 00:45:18,540\n来使得合一算法能够完成\nto get the unification or not?\n\n798\n00:45:18,768 --> 00:45:22,944\n是否可以在规则中添加一些属性\nCan you add some properties either to the rules itself\n\n799\n00:45:23,184 --> 00:45:25,456\n或者向输入的形式中添加属性\nor to the form that you're writing\n\n800\n00:45:25,824 --> 00:45:29,040\n来避免无法进行合一的窘境\nso that you avoid the problem of not finding unification?\n\n801\n00:45:29,180 --> 00:45:31,152\nPROFESSOR: 我想 你也同意\nWell I mean, you can agree,\n\n802\n00:45:31,472 --> 00:45:35,264\n用非常受限的方式来编写查询\nI think, to write in a fairly restricted way where you won't run into it.\n\n803\n00:45:35,600 --> 00:45:36,672\n看 你遇到的是\nSee, because what you're getting--\n\n804\n00:45:36,880 --> 00:45:39,120\n仔细看 你遇到问题是在\nsee, the place where you get into problems is when you--\n\n805\n00:45:39,680 --> 00:45:44,256\n用像这样的东西去匹配\nwell, again, you're trying to match things like that\n\n806\n00:45:44,592 --> 00:45:47,200\n具有这样结构的模式时\nagainst things where these have structure,\n\n807\n00:45:47,552 --> 00:45:55,300\n比如((A ?Y B) ?Y)\nwhere a, y, b, y something.\n\n808\n00:45:58,980 --> 00:46:01,488\n这是你可能遇到问题的一个地方\nSo this is the kind of place where you're going to get into trouble.\n\n809\n00:46:03,070 --> 00:46:05,808\n学生：所以你可以在语法层次上处理它么？\nAUDIENCE: So you can do that syntactically?\n\n810\n00:46:06,140 --> 00:46:08,768\n教授：你可以在写查询时\nPROFESSOR: So you can kind of watch your rules\n\n811\n00:46:08,768 --> 00:46:10,490\n注意你的规则\nin the kinds of things that your writing.\n\n812\n00:46:11,904 --> 00:46:14,080\n学生：这个问题应该由\nAUDIENCE: So that's the problem that the builder\n\n813\n00:46:14,112 --> 00:46:16,272\n数据库的构建者考虑么？\nof the database has to be concerned?\n\n814\n00:46:16,576 --> 00:46:17,808\n教授：这个问题\nPROFESSOR: That's a problem.\n\n815\n00:46:19,930 --> 00:46:22,016\n不完全是数据库的构建者\nIt's a problem either-- not quite the builder of the database,\n\n816\n00:46:22,048 --> 00:46:23,616\n或者是表述规则的人\nthe person who is expressing the rules,\n\n817\n00:46:24,016 --> 00:46:25,312\n所需要考虑的\nor the builder of the database.\n\n818\n00:46:25,800 --> 00:46:29,792\n当你们仔细审查合一算法的代码时\nWhat the unifier actually does is you can check at the next level down\n\n819\n00:46:29,920 --> 00:46:31,872\n你们会发现\nwhen you actually get to the unifier\n\n820\n00:46:32,416 --> 00:46:34,768\n它实际上在查询一个字典\nand you'll see in the code where it looks up in the dictionary.\n\n821\n00:46:34,940 --> 00:46:36,832\n它会问 ?Y的取值应该是什么？\nIf it sort of says what does y have to be?\n\n822\n00:46:37,260 --> 00:46:41,424\n?Y应该是一个含有自包含的表达式么？\nOh, does y have to be something that contains a y as its expression?\n\n823\n00:46:41,960 --> 00:46:43,264\n这时候 合一算法就会说\nAt that point, the unifier and say,\n\n824\n00:46:43,280 --> 00:46:46,240\n哦 我正在求解一个不动点方程\noh my God, I'm trying to solve a fixed-point equation.\n\n825\n00:46:46,240 --> 00:46:46,992\n我还是放弃吧\nI'll give it up here.\n\n826\n00:46:48,592 --> 00:46:51,910\n学生：你区分过数据库中的规则\nAUDIENCE: You make the distinction between the rules in the database.\n\n827\n00:46:51,910 --> 00:46:56,480\n这些规则是加入数据库的么？\nAre the rules added to the database?\n\n828\n00:46:56,950 --> 00:46:57,360\n教授：是的\nPROFESSOR: Yes.\n\n829\n00:46:57,870 --> 00:46:58,870\n我应该这么来说\nYes, I should have said that.\n\n830\n00:46:58,870 --> 00:47:00,336\n你们可以把规则看作\nOne way to think about rules\n\n831\n00:47:00,608 --> 00:47:02,656\n数据库中的其它东西\nis that they're just other things in the database.\n\n832\n00:47:03,712 --> 00:47:06,810\n如果你想要检查数据库中需要检查的东西\nSo if you want to check the things that have to be checked in the database,\n\n833\n00:47:06,832 --> 00:47:09,440\n它们就是存在于数据库中的虚拟事实\nthey're kind of virtual facts that are in the database.\n\n834\n00:47:09,440 --> 00:47:12,320\n学生：但是在这个解释中\nAUDIENCE: But in that explanation, you made the differentiation\n\n835\n00:47:12,432 --> 00:47:17,264\n你就已经区分了数据库和规则本身\nbetween database and the rules itself.\n\n836\n00:47:18,230 --> 00:47:19,904\n教授：是的 我应该不这么来说\nPROFESSOR: Yeah, I probably should not have done that.\n\n837\n00:47:20,490 --> 00:47:23,312\n这样做的唯一理由就是实现\nThe only reason to do that is in terms of the implementation.\n\n838\n00:47:23,540 --> 00:47:24,672\n当你们查看具体实现时\nWhen you look at the implementation,\n\n839\n00:47:24,680 --> 00:47:27,504\n会发现其中有部分用来检查数据库中的\nthere's a part which says check either primitive\n\n840\n00:47:27,552 --> 00:47:29,850\n基本断言或者规则\nassertions in the database or check rules.\n\n841\n00:47:30,470 --> 00:47:32,720\n这其中的真正原因就是\nAnd then the real reason, the real reason why\n\n842\n00:47:32,780 --> 00:47:34,560\n你不知道查询结果是以什么顺序输出的\nyou can't tell what order things are going to come out in\n\n843\n00:47:34,960 --> 00:47:40,460\n而规则数据库和数据数据库\nis that the rules database and the data database\n\n844\n00:47:40,480 --> 00:47:43,680\n是通过某种延迟求值的方式合并的\nsort of get merged in a kind of delayed evaluation way.\n\n845\n00:47:44,600 --> 00:47:46,800\n这就使得顺序变得非常复杂\nAnd so that's what makes the order very complicated.\n\n846\n00:47:55,440 --> 00:47:56,096\n那好 我们休息一下\nOK, let's break.\n\n847\n00:47:56,300 --> 00:48:09,904\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n848\n00:48:10,040 --> 00:48:14,416\n《计算机程序的构造和解释》\n\n\n849\n00:48:18,680 --> 00:48:22,096\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n850\n00:48:22,090 --> 00:48:25,968\n《计算机程序的构造和解释》\n\n851\n00:48:26,000 --> 00:48:29,872\n逻辑式程序设计 II\n\n852\n00:48:33,160 --> 00:48:35,376\n我们已经学习了逻辑式语言与\nWe've just seen how the logic language works\n\n853\n00:48:35,392 --> 00:48:36,416\n规则系统的运行原理\nand how rules work.\n\n854\n00:48:37,230 --> 00:48:39,376\n现在 让我们来探讨一个更加深刻的问题\nNow, let's turn to a more profound question.\n\n855\n00:48:40,120 --> 00:48:41,280\n来看下它们意味着什么\nWhat do these things mean?\n\n856\n00:48:43,180 --> 00:48:46,864\n这把我们带入到整个查询语言中\nThat brings us to the subtlest, most devious part\n\n857\n00:48:46,992 --> 00:48:48,672\n最微妙的部分\nof this whole query language business,\n\n858\n00:48:49,216 --> 00:48:53,070\n也就是它看起来与想象中不同的地方\nand that is that it's not quite what it seems to be.\n\n859\n00:48:53,570 --> 00:48:56,224\nAND、OR以及NOT\nAND and OR and NOT\n\n860\n00:48:57,024 --> 00:48:58,880\n以及规则的逻辑蕴含\nand the logical implication of rules\n\n861\n00:48:59,696 --> 00:49:06,640\n并不是逻辑学中的与、或、非以及蕴含\nare not really the AND and OR and NOT and logical implication of logic.\n\n862\n00:49:07,690 --> 00:49:09,712\n让我来举一个实例\nLet me give you an example of that.\n\n863\n00:49:09,910 --> 00:49:12,224\n当然 如果我们有两个逻辑命题\nCertainly, if we have two things in logic,\n\n864\n00:49:12,400 --> 00:49:19,440\n那么(AND P Q)就应该\nit ought to be the case that AND of P and Q\n\n865\n00:49:20,000 --> 00:49:22,592\n等同于(AND Q P)\nis the same as AND of Q and P\n\n866\n00:49:23,100 --> 00:49:24,510\n而(OR P Q)就应该\nand that OR of P and Q\n\n867\n00:49:24,780 --> 00:49:26,510\n等同于(OR Q P)\nis the same as OR of Q and P.\n\n868\n00:49:28,672 --> 00:49:30,096\n但我们来看看这里\nBut let's look here.\n\n869\n00:49:30,100 --> 00:49:32,016\n这里是一个例子\nHere's an example.\n\n870\n00:49:32,180 --> 00:49:36,160\n来看看 在我们的数据库中\nLet's talk about somebody outranking somebody else\n\n871\n00:49:36,288 --> 00:49:40,140\n如何表示某人的级别高于他人\nin this our little database organization.\n\n872\n00:49:40,140 --> 00:49:42,896\n我们定义(OUTRANKED-BY ?S ?B)为\nWe'll say s is outranked by b\n\n873\n00:49:44,640 --> 00:49:48,624\n或者S是B的上司\nif or if either the supervisor of s is b\n\n874\n00:49:49,630 --> 00:49:51,072\n或者这其中有某个中间经理M\nor there's some middle manager here,\n\n875\n00:49:51,104 --> 00:49:55,820\n其中S是M的上司 M的级别又比B高\nthat supervisor of s is m, and m is outranked by b.\n\n876\n00:49:59,648 --> 00:50:02,310\n这是定义OUTRANKED-BY的一种方式\nSo there's one way to define rule outranked by.\n\n877\n00:50:02,310 --> 00:50:04,160\n或者我们可以原封不动地写过来\nOr we can write exactly the same thing,\n\n878\n00:50:05,088 --> 00:50:06,912\n除了在最底部的这里\nexcept at the bottom here,\n\n879\n00:50:07,216 --> 00:50:09,888\n我们颠倒一下这两个子句的顺序\nwe reversed the order of these two clauses.\n\n880\n00:50:11,630 --> 00:50:12,992\n当然 如果它们都是逻辑表达式的话\nAnd certainly if this were logic,\n\n881\n00:50:13,008 --> 00:50:14,880\n它们应该表示的是相同的东西\nthose ought to mean the same thing.\n\n882\n00:50:16,690 --> 00:50:17,312\n然而\nHowever,\n\n883\n00:50:17,712 --> 00:50:19,616\n在我们这个特定的实现中\nin our particular implementation,\n\n884\n00:50:19,648 --> 00:50:22,880\n如果你查询(OUTRANDKED-BY ?WHO (BITDIIDLE BEN))\nif you say something like who's outranked by Ben Bitdiddle,\n\n885\n00:50:23,488 --> 00:50:25,360\n你会发现 这条规则\nwhat you'll find is that this rule\n\n886\n00:50:26,768 --> 00:50:28,720\n会完美地生成答案\nwill work perfectly well and generate answers,\n\n887\n00:50:30,048 --> 00:50:31,984\n然而 这条规则会陷入无穷循环\nwhereas this rule will go into an infinite loop.\n\n888\n00:50:34,110 --> 00:50:36,272\n其中的原因就是\nAnd the reason for that is that\n\n889\n00:50:36,336 --> 00:50:40,336\n这条规则会问谁比BEN BITDIDDLE级别高？\nthis will come in and say, oh, who's outranked by Ben Bitdiddle?\n\n890\n00:50:41,920 --> 00:50:43,536\n它试图寻找一个S\nFind an s, find an s\n\n891\n00:50:43,888 --> 00:50:46,224\n使得S比B的级别更高 其中B是BEN BITDIDDLE\nwhich is outranked by b, where b is Ben Bitdiddle,\n\n892\n00:50:47,504 --> 00:50:49,632\n这会在一个子问题中重复出现\nwhich is going to happen in it a subproblem.\n\n893\n00:50:50,330 --> 00:50:51,984\n找到一个M\nOh gee, find an m\n\n894\n00:50:52,240 --> 00:50:54,576\n使得M的级别高于BEN BITDIDDLE\nsuch as m is outranked by Ben Bitdiddle\n\n895\n00:50:55,616 --> 00:50:57,360\n而对M没有限制\nwith no restrictions on m.\n\n896\n00:50:58,560 --> 00:51:00,400\n这就相当于为了解决这个问题\nSo this will say in order to solve this problem,\n\n897\n00:51:01,424 --> 00:51:03,296\n我就还需要求解同样的问题\nI solve exactly the same problem.\n\n898\n00:51:04,570 --> 00:51:07,232\n在把它解出来后 我才检查SUPERVISOR关系\nAnd then after I've solved that, I'll check for a supervisory relationship.\n\n899\n00:51:08,000 --> 00:51:09,168\n然而这条规则没有这样的问题\nWhereas this one won't get into that,\n\n900\n00:51:09,184 --> 00:51:12,350\n因为在它尝试找出这条OUTRANKED-BY规则之前\nbecause before it tries to find this outranked by,\n\n901\n00:51:12,944 --> 00:51:15,260\n在这里已经对M施加过约束了\nit'll already have had a restriction on m here.\n\n902\n00:51:18,384 --> 00:51:20,944\n随意 这两条规则理论上是相同的\nSo these two things which ought to mean the same,\n\n903\n00:51:20,992 --> 00:51:22,672\n但实际上 其中一条会陷入无穷循环\nin fact, one goes into an infinite loop.\n\n904\n00:51:22,860 --> 00:51:25,040\n而另一条不会\nOne goes, one does not.\n\n905\n00:51:26,720 --> 00:51:29,776\n通过这个非常极端的例子\nThat's a very extreme case\n\n906\n00:51:29,790 --> 00:51:32,656\n你会发现在逻辑式程序设计中\nof a general thing that you'll find in logic programming that\n\n907\n00:51:34,288 --> 00:51:38,704\n如果你改变了AND或OR所连接子句的顺序\nif you start changing the order of the things in the ANDs or ORs,\n\n908\n00:51:39,344 --> 00:51:41,584\n你会发现效率上的巨大差异\nyou'll find tremendous differences in efficiency.\n\n909\n00:51:42,240 --> 00:51:43,216\n我们刚刚就看到了\nAnd we just saw\n\n910\n00:51:43,552 --> 00:51:46,544\n在无穷循环方面的巨大差异\nan infinitely big difference in efficiency and an infinite loop.\n\n911\n00:51:49,190 --> 00:51:51,744\n同样的 这也跟输入规则\nAnd there are similar things having to do order\n\n912\n00:51:52,000 --> 00:51:53,312\n的顺序有关\nin which you enter rules.\n\n913\n00:51:54,070 --> 00:51:56,480\n向数据库查询规则的顺序\nThe order in which it happens to look at rules in the database\n\n914\n00:51:56,700 --> 00:51:59,952\n会极大程度上影响效率：比如得到答案\nmay vastly change the efficiency with which it gets out answers or,\n\n915\n00:52:00,464 --> 00:52:02,608\n或者在某些顺序下陷入无穷循环\nin fact, send it into an infinite loop for some orderings.\n\n916\n00:52:03,840 --> 00:52:07,296\n这些都跟\nAnd this whole thing has to do\n\n917\n00:52:07,632 --> 00:52:10,048\n你检查这些规则的顺序有关\nthe fact that you're checking these rules in some order.\n\n918\n00:52:10,950 --> 00:52:14,416\n有些规则的蕴含路径会相当的长\nAnd some rules may lead to really long paths of implication.\n\n919\n00:52:14,448 --> 00:52:16,064\n而另外一些不会\nOthers might, others might not.\n\n920\n00:52:16,440 --> 00:52:17,680\n但你事先并不知道\nAnd you don't know a priori\n\n921\n00:52:17,728 --> 00:52:19,168\n哪一个长 哪一个短\nwhich ones are good and which ones are bad.\n\n922\n00:52:19,300 --> 00:52:21,488\n有很多研究都与此有关\nAnd there's a whole bunch of research having to do with that,\n\n923\n00:52:22,160 --> 00:52:23,760\n其中大多数都是想通过\nmostly having to do with thinking about\n\n924\n00:52:23,952 --> 00:52:26,970\n用并行的方法来实现逻辑式程序设计语言\nmaking parallel implementations of logic programming languages.\n\n925\n00:52:27,320 --> 00:52:29,904\n某种意义上来说 就是并行地检查所有规则\nAnd in some sense, what you'd like to do is check all rules in parallel\n\n926\n00:52:30,360 --> 00:52:32,800\n一旦有一条搜索得到答案 就返回结果\nand whichever ones get answers, you bubble them up. And\n\n927\n00:52:33,040 --> 00:52:34,992\n如果某条路径陷入了无穷的推导\nif some go down infinite deductive chain,\n\n928\n00:52:35,020 --> 00:52:38,256\n那么 你只需知道 内存和处理器都非常廉价\nwell, you just-- you know, memory is cheap and processors are cheap,\n\n929\n00:52:38,288 --> 00:52:40,490\n让它们根据你的需要一直搜寻就好了\nyou just let them buzz for as for as long as you want.\n\n930\n00:52:43,472 --> 00:52:44,832\n尽管如此 与真正的逻辑相比\nThere's a deeper problem, though,\n\n931\n00:52:45,184 --> 00:52:50,496\n这门逻辑式语言还有一个更深刻的问题\nin comparing this logic language to real logic.\n\n932\n00:52:50,688 --> 00:52:52,528\n我给你们演示的例子\nThe example I just showed you, it\n\n933\n00:52:52,976 --> 00:52:54,800\n只是会陷入无穷循环\nwent into an infinite loop maybe,\n\n934\n00:52:55,376 --> 00:52:56,992\n但至少不会给你错误的答案\nbut at least it didn't give the wrong answer.\n\n935\n00:52:58,370 --> 00:53:03,648\n当我们开始严肃地把这门逻辑式语言\nThere's an actual deeper problem when we start comparing,\n\n936\n00:53:03,680 --> 00:53:05,240\n与真正的经典逻辑作比较时\nyou know, seriously comparing\n\n937\n00:53:05,712 --> 00:53:08,464\n就会发现其中最深层次的问题\nthis logic language with real classical logic.\n\n938\n00:53:09,490 --> 00:53:12,432\n让我们来看看真正的经典逻辑\nSo let's sort of review real classical logic.\n\n939\n00:53:13,712 --> 00:53:21,040\n所有的人类都是凡人\nAll humans are mortal.\n\n940\n00:53:22,352 --> 00:53:23,456\n相当经典的逻辑命题\nThat's pretty classical logic.\n\n941\n00:53:24,390 --> 00:53:28,672\n然后我们就依照最经典的传统\nThen maybe we'll continue in the very best classical tradition.\n\n942\n00:53:29,248 --> 00:53:32,464\n我们按照最传统的方式来做\nWe'll say all-- let's make it really classical.\n\n943\n00:53:32,670 --> 00:53:37,168\n所有的希腊人都是人类\nAll Greeks are human,\n\n944\n00:53:40,496 --> 00:53:46,064\n苏格拉底是希腊人\nwhich has the syllogism that Socrates is a Greek.\n\n945\n00:53:48,176 --> 00:53:49,210\n然后我们又该写什么呢？\nAnd then what do you write here?\n\n946\n00:53:49,210 --> 00:53:51,890\n经典逻辑中有一个三点符号\nI think three dots, classical logic.\n\n947\n00:53:51,890 --> 00:53:54,336\n因此 我们得到了一个三段论\nTherefore, then the syllogism,\n\n948\n00:53:54,640 --> 00:53:59,552\n苏格拉底是凡人\nSocrates is mortal.\n\n949\n00:54:01,360 --> 00:54:04,912\n这些都是真正的经典逻辑\nSo there's some real honest classical logic.\n\n950\n00:54:05,880 --> 00:54:11,056\n把它跟我们经典逻辑数据库比较一下\nLet's compare that with our classical logic database.\n\n951\n00:54:12,400 --> 00:54:14,464\n这是一个经典逻辑数据库\nSo here's a classical logic database.\n\n952\n00:54:16,270 --> 00:54:17,488\n(GREEK SOCRATES)\nSocrates is a Greek.\n\n953\n00:54:18,030 --> 00:54:18,848\n(GREEK PLATO)\nPlato is a Greek.\n\n954\n00:54:19,600 --> 00:54:20,400\n(GREEK ZEUS)\nZeus is a Greek,\n\n955\n00:54:20,848 --> 00:54:21,984\n(GOD ZEUS)\nand Zeus is a god.\n\n956\n00:54:24,120 --> 00:54:29,968\n所有的人类都是凡人\nAnd all humans are mortal.\n\n957\n00:54:30,540 --> 00:54:32,128\n为了证明某人是平凡的\nTo show that something is mortal,\n\n958\n00:54:32,160 --> 00:54:33,600\n只需要证明他是人类\nit's enough to show that it's human.\n\n959\n00:54:34,650 --> 00:54:35,900\n所有的人类都是不可靠的\nAll humans are fallible.\n\n960\n00:54:38,900 --> 00:54:40,980\n并且说所有的希腊人都是人类 并不正确\nAnd all Greeks are humans is not quite right.\n\n961\n00:54:40,980 --> 00:54:44,416\n这条规则说 所有不是神的希腊人都是人类\nThis says that all Greeks who are not gods are human.\n\n962\n00:54:45,710 --> 00:54:47,040\n因此为了证明某人是人类\nSo to show something's human,\n\n963\n00:54:47,072 --> 00:54:48,896\n只需要说明他是一个希腊人 并且不是神\nit's enough to show it's a Greek and not a god.\n\n964\n00:54:49,320 --> 00:54:52,880\n任何一个希腊神的住址是奥林匹斯山\nAnd the address of any Greek god is Mount Olympus.\n\n965\n00:54:54,320 --> 00:54:57,168\n这就是一个小型经典逻辑数据库\nSo there's a little classical logic database.\n\n966\n00:54:57,390 --> 00:54:59,328\n确实 它运行得相当好\nAnd indeed, that would work fairly well.\n\n967\n00:54:59,490 --> 00:55:02,096\n如果我们向其询问\nIf we type that in and say\n\n968\n00:55:03,472 --> 00:55:06,576\n苏格拉底是凡人么 不可靠么？\nis Socrates mortal or Socrates fallible or mortal?\n\n969\n00:55:06,910 --> 00:55:07,690\n它会输出：是\nIt'll say yes.\n\n970\n00:55:07,776 --> 00:55:09,710\n柏拉图是凡人并且不可靠么？\nIs Plato mortal and fallible.\n\n971\n00:55:09,710 --> 00:55:10,240\n它会回答：是\nIt'll say yes.\n\n972\n00:55:10,680 --> 00:55:12,210\n如果我们问宙斯是凡人么\nIf we say is Zeus mortal?\n\n973\n00:55:12,210 --> 00:55:13,232\n它什么都不会找到\nIt won't find anything.\n\n974\n00:55:14,900 --> 00:55:15,968\n运行得非常完美\nAnd it'll work perfectly well.\n\n975\n00:55:16,544 --> 00:55:20,120\n然而 如果我们想要把它扩展一下\nHowever, suppose we want to extend this.\n\n976\n00:55:20,120 --> 00:55:23,056\n让我们来定义一下什么是“完美生命体”\nLet's define what it means for someone to be a perfect being.\n\n977\n00:55:23,824 --> 00:55:27,216\n我们把规则PERFECT定义为\nLet's say rule: a perfect being.\n\n978\n00:55:34,050 --> 00:55:35,480\n我想这样来定义是正确的\nAnd I think this is right.\n\n979\n00:55:35,480 --> 00:55:38,144\n如果你熟悉中世纪经院哲学\nIf you're up on your medieval scholastic philosophy,\n\n980\n00:55:38,448 --> 00:55:40,176\n我想所谓“完美生命体”一定\nI believe that perfect beings are ones\n\n981\n00:55:40,688 --> 00:55:42,656\n既不是凡人 又不会不可靠\nwho were neither mortal nor fallible.\n\n982\n00:55:44,100 --> 00:55:56,848\n(AND (NOT (MORTAL ?X)) (NOT (FALLIBLE ?X)))\nAND NOT mortal x, NOT fallible x.\n\n983\n00:55:59,300 --> 00:56:00,896\n这样 我们就定义了一个规则\nSo we'll define this system\n\n984\n00:56:02,672 --> 00:56:04,368\n来告诉系统 什么是“完美生命体”\nto teach it what a perfect being is.\n\n985\n00:56:05,790 --> 00:56:07,696\n现在 我们就要\nAnd now what we're going to do is\n\n986\n00:56:08,064 --> 00:56:10,176\n询问所有“完美生命体”的地址\nask for the address of all the perfect beings.\n\n987\n00:56:11,488 --> 00:56:22,304\n(AND (ADDRESS ?X ?Y) (PERFECT ?X))\nAND the address of x is y and x is perfect.\n\n988\n00:56:23,488 --> 00:56:24,976\n在这里 我们生成了\nAnd so what we're generating here is\n\n989\n00:56:24,992 --> 00:56:27,808\n世界上最独有的邮件列表\nthe world's most exclusive mailing list.\n\n990\n00:56:30,160 --> 00:56:32,200\n为了查询所有完美生命体的地址\nFor the address of all the perfect beings,\n\n991\n00:56:32,240 --> 00:56:33,472\n我们会输入像这样的查询\nwe might have typed this in.\n\n992\n00:56:33,830 --> 00:56:35,440\n或者像这样输入\nOr we might type in this.\n\n993\n00:56:36,240 --> 00:56:50,576\n(AND (PERFECT ?X) (ADDRESS ?X ?Y))\nWe'll say AND perfect of x and the address of x is y.\n\n994\n00:56:52,064 --> 00:56:54,960\n假设我们把它输入进去 并尝试查询\nWell, suppose we type all that in and we try this query.\n\n995\n00:56:55,190 --> 00:56:56,768\n这条查询会给我们答案\nThis query is going to give us an answer.\n\n996\n00:56:57,650 --> 00:57:00,000\n这条查询会输出：奥林匹斯山\nThis query will say, yeah, Mount Olympus.\n\n997\n00:57:04,230 --> 00:57:06,576\n而这条查询 什么也不会输出\nThis query, in fact, is going to give us nothing.\n\n998\n00:57:06,740 --> 00:57:09,584\n它找不到完美生命体的地址\nIt will say no addresses of perfect beings.\n\n999\n00:57:11,640 --> 00:57:12,510\n为什么会这样？\nNow, why is that?\n\n1000\n00:57:12,510 --> 00:57:13,440\n这又为什么不同？\nWhy is there a difference?\n\n1001\n00:57:14,230 --> 00:57:15,690\n这个问题跟无穷循环没什么关系\nThis is not an infinite loop question.\n\n1002\n00:57:15,690 --> 00:57:17,088\n这个的问题是答案不相同\nThis is a different answer question.\n\n1003\n00:57:19,488 --> 00:57:20,096\n原因就是\nThe reason is\n\n1004\n00:57:20,380 --> 00:57:22,320\n如果你们还记得NOT的实现的话\nthat if you remember the implementation of NOT,\n\n1005\n00:57:23,504 --> 00:57:24,848\nNOT是作为一个过滤器\nNOT acted as a filter.\n\n1006\n00:57:25,880 --> 00:57:29,008\nNOT会接收一本字典\nNOT said I'm going to take some possible dictionaries,\n\n1007\n00:57:29,050 --> 00:57:31,568\n里面有可行解构成的框架\nsome possible frames, some possible answers,\n\n1008\n00:57:31,792 --> 00:57:33,168\n然后过滤出那些\nand filter out the ones\n\n1009\n00:57:33,290 --> 00:57:34,940\n满足某个条件的解\nthat happened to satisfy some condition,\n\n1010\n00:57:34,976 --> 00:57:36,112\n这就是我如何实现NOT的\nand that's how I implement NOT.\n\n1011\n00:57:36,928 --> 00:57:38,432\n如果你们仔细想想其中的原理\nIf you think about what's going on here,\n\n1012\n00:57:40,112 --> 00:57:42,656\n我创建了一个查询盒子\nI'll build this query box where the address piece\n\n1013\n00:57:43,320 --> 00:57:47,392\nADDRESS盒子的输出作为了PERFECT的输入\nthe output of an address piece gets fed into a perfect piece.\n\n1014\n00:57:50,290 --> 00:57:51,008\n这就使得\nWhat will happen is\n\n1015\n00:57:51,328 --> 00:57:53,264\nADDRESS盒子会创建出\nthe address piece will set up some things of\n\n1016\n00:57:53,328 --> 00:57:54,832\n我知道地址的人\neveryone whose address I know.\n\n1017\n00:57:55,290 --> 00:57:57,648\n这些都会被PERFECT中的NOT给过滤掉\nThose will get filtered by the NOTs inside perfect here.\n\n1018\n00:57:59,880 --> 00:58:04,192\n所以它会丢弃掉那些满足平凡的或者不可靠的数据\nSo it will throw out the ones which happened to be either mortal or fallible.\n\n1019\n00:58:04,910 --> 00:58:06,384\n而对于另外一种顺序来说\nIn the other order what happens\n\n1020\n00:58:06,736 --> 00:58:09,120\n我以一个空框架开始的\nis I set this up, started up with an empty frame.\n\n1021\n00:58:09,520 --> 00:58:12,352\n但是这里PERFECT没有可以给NOT过滤的东西\nThe perfect in here doesn't find anything for the NOTs to filter,\n\n1022\n00:58:12,384 --> 00:58:13,984\n所以这里不会有什么输出\nso nothing comes out here at all.\n\n1023\n00:58:18,830 --> 00:58:21,504\n这也就导致没有东西输入到ADDRESS中\nAnd there's sort of nothing there that gets fed into the address thing.\n\n1024\n00:58:21,940 --> 00:58:23,152\n因此 我得不到答案\nSo here, I don't get an answer.\n\n1025\n00:58:23,936 --> 00:58:27,040\n在强调一下 这是因为NOT不会生成任何东西\nAnd again, the reason for that is NOT isn't generating anything.\n\n1026\n00:58:27,440 --> 00:58:28,800\nNOT只会丢弃数据\nNOT's only throwing out things.\n\n1027\n00:58:29,080 --> 00:58:30,512\n如果我不向NOT传递东西的话\nAnd if I never started up with anything,\n\n1028\n00:58:30,528 --> 00:58:31,744\n它也就不会输出\nthere's nothing for it to throw out.\n\n1029\n00:58:32,020 --> 00:58:33,770\n这样我就得到了错误的答案\nSo out of this thing, I get the wrong answer.\n\n1030\n00:58:37,200 --> 00:58:37,970\n我们又该如何修复它呢？\nHow can you fix that?\n\n1031\n00:58:37,970 --> 00:58:39,070\n当然 有很多办法\nWell, there are ways to fix that.\n\n1032\n00:58:39,360 --> 00:58:40,912\n你可能认为 现在这样有点愚蠢\nSo you might say, well, that's sort of stupid.\n\n1033\n00:58:41,410 --> 00:58:44,900\n为什么要一开始就执行NOT呢？\nWhy are you just doing all your NOT stuff at the beginning?\n\n1034\n00:58:44,960 --> 00:58:47,488\n想要正确地实现NOT\nThe right way to implement NOT is to realize\n\n1035\n00:58:47,840 --> 00:58:50,080\n就是要认识到当你遇到NOT时\nthat when you have conditions like NOT,\n\n1036\n00:58:50,336 --> 00:58:52,096\n你应该首先生成好答案\nyou should generate all your answers first,\n\n1037\n00:58:52,800 --> 00:58:54,976\n然后通过字典把它们传递过来\nand then with each of these dictionaries pass along\n\n1038\n00:58:55,520 --> 00:58:57,856\n然后再最后再做过滤\nGee, at the very end I'll do filtering.\n\n1039\n00:58:58,560 --> 00:59:02,016\n有些按照这种方式实现的逻辑式语言\nAnd there are implementations of logic languages that work like that\n\n1040\n00:59:02,416 --> 00:59:04,050\n能够解决这个问题\nthat solve this particular problem.\n\n1041\n00:59:06,800 --> 00:59:08,976\n然而 还有一个更深刻的问题\nHowever, there's a more profound problem,\n\n1042\n00:59:09,600 --> 00:59:11,536\n也就是 哪个才是正确答案呢？\nwhich is which one of these is the right answer?\n\n1043\n00:59:12,530 --> 00:59:14,240\n是奥林匹斯山 还是没有呢？\nIs it Mount Olympus or is it nothing?\n\n1044\n00:59:15,376 --> 00:59:18,730\n你可能会认为是奥林匹斯山\nSo you might say it's Mount Olympus,\n\n1045\n00:59:18,760 --> 00:59:20,730\n毕竟 宙斯在数据库中\nbecause after all, Zeus is in that database,\n\n1046\n00:59:22,528 --> 00:59:25,104\n宙斯不是平凡的 也不是不可靠的\nand Zeus was neither mortal nor fallible.\n\n1047\n00:59:29,550 --> 00:59:32,448\n因此你可能会认为宙斯满足\nSo you might say Zeus wants to satisfy\n\n1048\n00:59:34,304 --> 00:59:44,032\n(NOT (MORTAL ZEUS))或者(NOT (FALLIBLE ZEUS))\nNOT mortal Zeus or NOT fallible Zeus.\n\n1049\n00:59:44,120 --> 00:59:45,856\n但我们实际来看一看数据库\nBut let's actually look at that database.\n\n1050\n00:59:47,920 --> 00:59:48,464\n来看一下\nLet's look at it.\n\n1051\n00:59:49,360 --> 00:59:53,240\n它要如何知道宙斯不是不可靠的？\nThere's no way-- how does it know that Zeus is not fallible?\n\n1052\n00:59:54,810 --> 00:59:56,112\n这里面没有关于它的知识\nThere's nothing in there about that.\n\n1053\n00:59:57,930 --> 00:59:59,664\n里面只能得到人类是不可靠的\nWhat's in there is that humans are fallible.\n\n1054\n01:00:02,160 --> 01:00:04,128\n它又如何知道宙斯不是不可靠的呢？\nHow does it know that Zeus is not mortal?\n\n1055\n01:00:04,480 --> 01:00:05,936\n这其中没有相关的规则\nThere's nothing in there about that.\n\n1056\n01:00:07,980 --> 01:00:11,008\n它只是说 我没有这样的规则\nIt just said I don't have any rule, which--\n\n1057\n01:00:11,680 --> 01:00:14,064\n我只能通过某人是人类来推断出他是平凡的\nsee the only way I can deduce something's mortal is if it's human\n\n1058\n01:00:14,080 --> 01:00:15,680\n这也是它所知道关于“平凡”的所有东西\nand that's all it really knows about mortal.\n\n1059\n01:00:16,690 --> 01:00:19,856\n然而 如果你还记得古典神话的话\nAnd in fact, if you remember your classical mythology,\n\n1060\n01:00:19,872 --> 01:00:23,488\n你就知道 古希腊众神是不平凡的 但都不可靠\nyou know that the Greek gods were not mortal but fallible.\n\n1061\n01:00:25,056 --> 01:00:28,656\n所以 不能通过这些规则得到答案\nSo the answer is not in the rules there.\n\n1062\n01:00:30,850 --> 01:00:32,100\n但它又为什么推导出这些呢？\nSee, why does it deduce that?\n\n1063\n01:00:34,496 --> 01:00:38,320\n显然 苏格拉底不会犯这类逻辑错误\nSee, Socrates would certainly not have made this error of logic.\n\n1064\n01:00:40,080 --> 01:00:42,672\n在这门语言中 NOT并不是NOT\nWhat NOT means in this language is not NOT.\n\n1065\n01:00:43,370 --> 01:00:44,320\n不是逻辑非运算\nIt's not the NOT of logic.\n\n1066\n01:00:44,930 --> 01:00:46,400\n这门语言中 NOT表示的是\nWhat NOT needs in this language is\n\n1067\n01:00:47,160 --> 01:00:49,960\n不可以从数据库中推断出结果\nnot deducible from things in the database\n\n1068\n01:00:50,752 --> 01:00:53,344\n而不是“非真”\nas opposed to not true.\n\n1069\n01:00:55,024 --> 01:00:56,304\n完全是天壤之别\nThat's a very big difference.\n\n1070\n01:00:57,300 --> 01:00:58,640\n很细微 但也很巨大\nSubtle, but big.\n\n1071\n01:00:59,250 --> 01:01:00,272\n因此 实际上\nSo, in fact,\n\n1072\n01:01:00,768 --> 01:01:03,920\n如果什么都不知道 最好就说NOT\nthis is perfectly happy to say not anything that it doesn't know about.\n\n1073\n01:01:04,680 --> 01:01:06,144\n如果你问它\nSo if you ask it is it not true\n\n1074\n01:01:06,160 --> 01:01:07,830\n宙斯是否喜欢巧克力冰激凌\nthat Zeus likes chocolate ice cream?\n\n1075\n01:01:07,856 --> 01:01:09,120\n它会说 这个查询当然非真\nIt will say sure, it's not true.\n\n1076\n01:01:10,640 --> 01:01:12,512\n这些事情它都不知道\nOr anything else or anything it doesn't know about.\n\n1077\n01:01:12,592 --> 01:01:17,344\nNOT表示：不能从你告知它的事实中推断出来\nNOT means not deducible from the things you've told me.\n\n1078\n01:01:18,280 --> 01:01:22,448\n换句话说 你要把“无法推断出”\nIn a world where you're identifying not deducible\n\n1079\n01:01:22,656 --> 01:01:24,000\n与“命题非真”区别开来\nwith, in fact, not true,\n\n1080\n01:01:24,416 --> 01:01:26,304\n这被称作是“封闭世界假说”\nthis is called the closed world assumption.\n\n1081\n01:01:37,376 --> 01:01:38,176\n封闭世界假说\nclosed world assumption.\n\n1082\n01:01:38,200 --> 01:01:42,384\n只要结论不能通过我所知道的知识推断出来\nAnything that I cannot deduce from what I know\n\n1083\n01:01:43,500 --> 01:01:44,368\n那么就不是真的\nis not true,\n\n1084\n01:01:46,240 --> 01:01:48,010\n对吧 如果我对X一无所知\nRight? If I don't know anything about x,\n\n1085\n01:01:48,224 --> 01:01:49,216\n那么X就非真\nthe x isn't true.\n\n1086\n01:01:49,290 --> 01:01:50,336\n这相当危险\nThat's very dangerous.\n\n1087\n01:01:51,296 --> 01:01:52,448\n首先 从逻辑学的角度来说\nFrom a logical point of view,\n\n1088\n01:01:52,464 --> 01:01:53,760\n它一点也说不通\nfirst of all, it doesn't really makes sense.\n\n1089\n01:01:54,480 --> 01:01:56,336\n因为如果我对X一无所知的话\nBecause if I don't know anything about x,\n\n1090\n01:01:58,384 --> 01:01:59,696\n就说X非真\nI'm willing to say not x.\n\n1091\n01:02:00,240 --> 01:02:03,328\n但为什么不说“X非真”非真\nBut am I willing to say not not x?\n\n1092\n01:02:03,850 --> 01:02:05,664\n当然 我也许对后面那个命题也一无所知\nWell, sure, I don't know anything about that either maybe.\n\n1093\n01:02:06,470 --> 01:02:08,656\n因此(NOT (NOT X))就没有必要与X一致\nSo not not x is not necessarily the same as x\n\n1094\n01:02:09,248 --> 01:02:10,944\n等等等等\nand so on and so on and so on, so\n\n1095\n01:02:11,712 --> 01:02:13,936\n因此 这里面一定有某种“偏见”\nthere's some sort of funny bias in there.\n\n1096\n01:02:15,970 --> 01:02:17,290\n这相当有趣\nSo that's sort of funny.\n\n1097\n01:02:17,290 --> 01:02:18,096\n第二点就是\nThe second thing,\n\n1098\n01:02:20,144 --> 01:02:24,128\n如果你基于此 构建一个真正的推理程序\nif you start building up real reasoning programs based on this,\n\n1099\n01:02:24,704 --> 01:02:26,112\n想一想是多么地危险\nthink how dangerous that is.\n\n1100\n01:02:27,070 --> 01:02:32,000\n你说我知道我可以推断出\nYou're saying I know I'm in a position\n\n1101\n01:02:32,224 --> 01:02:36,220\n与这个问题有关的所有事情\nto deduce everything true that's relevant to this problem.\n\n1102\n01:02:37,440 --> 01:02:40,784\n因为在我推理机制的内部\nI'm reasoning, and built into my reasoning mechanism\n\n1103\n01:02:41,232 --> 01:02:44,200\n会认为所有与问题有关的知识\nis the assumption that anything that I don't know\n\n1104\n01:02:44,240 --> 01:02:46,272\n我都已经知道了\ncan't possibly be relevant to this problem.\n\n1105\n01:02:48,448 --> 01:02:53,040\n有相当多的大型组织都像这样运作 对吧？\nRight? There are a lot of big organizations that work like that, right?\n\n1106\n01:02:53,168 --> 01:02:56,830\n大多数公司的市场部门都是这样工作的。\nMost corporate marketing divisions work like that.\n\n1107\n01:02:56,830 --> 01:02:59,120\n你们也知道这样做的后果\nYou know the consequences to that.\n\n1108\n01:03:00,330 --> 01:03:03,456\n因此 向这个大型逻辑推理系统\nSo it's very dangerous to start really\n\n1109\n01:03:03,840 --> 01:03:06,250\n输入各种查询 根据输出继续工作\ntyping in these big logical implication systems\n\n1110\n01:03:07,056 --> 01:03:09,008\n的做法相当危险\nand going on what they say,\n\n1111\n01:03:09,024 --> 01:03:11,280\n因为它们内建的假说非常地有限\nbecause they have this really limiting assumption built in.\n\n1112\n01:03:12,600 --> 01:03:14,368\n因此你对此需要非常非常地小心\nSo you have to be very, very careful about that.\n\n1113\n01:03:15,296 --> 01:03:16,288\n就是这么一个深层次问题\nAnd that's a deep problem.\n\n1114\n01:03:16,560 --> 01:03:17,824\n这个问题并不是\nThat's not a problem about\n\n1115\n01:03:18,224 --> 01:03:20,144\n通过构建更加聪明的实现\nwe can make a little bit cleverer implementation\n\n1116\n01:03:20,160 --> 01:03:21,856\n或者通过组织无穷循环\nand do the filters and organize the\n\n1117\n01:03:22,160 --> 01:03:23,840\n以及过滤器就可以消除的\nthe infinite loops to make them go away.\n\n1118\n01:03:23,840 --> 01:03:25,088\n这是完全不同的一类问题\nIt's a different kind of problem.\n\n1119\n01:03:25,920 --> 01:03:26,896\n完全不同的语义\nIt's a different semantics.\n\n1120\n01:03:27,060 --> 01:03:30,512\n我想该总结一下了 平心而论\nSo I think to wrap this up, it's fair to say\n\n1121\n01:03:31,344 --> 01:03:34,432\n逻辑式程序设计是一个振奋人心的想法\nthat logic programming I think is a terrifically exciting idea,\n\n1122\n01:03:34,600 --> 01:03:37,008\n这个想法使你能够弥合\nthe idea that you can bridge this\n\n1123\n01:03:37,040 --> 01:03:38,780\n命令式与声明式语言的鸿沟\ngap from the imperative to the declarative,\n\n1124\n01:03:39,900 --> 01:03:42,944\n使得你可以谈论关系\nthat you can start talking about relations\n\n1125\n01:03:43,584 --> 01:03:45,088\n从而获得惊人的力量\nand really get tremendous power\n\n1126\n01:03:46,096 --> 01:03:49,488\n让你超越输入和输出的抽象\nby going above the abstraction of what's my input and what's my output.\n\n1127\n01:03:50,560 --> 01:03:51,536\n而关于逻辑\nAnd linked to logic,\n\n1128\n01:03:52,464 --> 01:03:56,464\n我认为这个问题还尚未解决\nthe problem is it's a goal that I think has yet to be realized.\n\n1129\n01:03:58,032 --> 01:04:01,808\n也许现在语言中最令人感兴趣的\nAnd probably one of the very most interesting\n\n1130\n01:04:02,272 --> 01:04:04,416\n研究问题之一就是\nresearch questions going on now in languages\n\n1131\n01:04:04,672 --> 01:04:08,288\n你该如何创建一门真正的逻辑语言？\nis how do you somehow make a real logic language?\n\n1132\n01:04:09,460 --> 01:04:11,056\n其次 你如何从\nAnd secondly, how do you bridge the gap\n\n1133\n01:04:11,312 --> 01:04:13,152\n这个逻辑和关系的世界\nthis world of logic and relations\n\n1134\n01:04:13,520 --> 01:04:16,432\n到更传统语言的世界之间\nto the worlds of more traditional languages\n\n1135\n01:04:16,464 --> 01:04:17,984\n架起桥梁并结合两者的力量\nand somehow combine the power of both.\n\n1136\n01:04:18,880 --> 01:04:19,680\n有什么问题吗？\nOK, let's break.\n\n1137\n01:04:23,290 --> 01:04:25,296\n学生：你能够通过添加额外的规则\nAUDIENCE: Couldn't you solve that last problem\n\n1138\n01:04:25,296 --> 01:04:27,740\n来解决最后一个问题么？\nby having the extra rules that imply it?\n\n1139\n01:04:27,968 --> 01:04:29,856\n这里的困境是：你有某物的定义\nThe problem here is you have the definition of something,\n\n1140\n01:04:29,888 --> 01:04:31,824\n但没有它对立面的定义\nbut you don't have the definition of its opposite.\n\n1141\n01:04:32,080 --> 01:04:33,920\n如果你在数据库中有\nIf you include in the database something that says\n\n1142\n01:04:34,144 --> 01:04:36,890\n某些规则推导出(MORTAL X)\nuh... something implies mortal x,\n\n1143\n01:04:36,992 --> 01:04:38,704\n另外一些规则推导出(NOT (MORTAL X))\nsomething else implies not mortal x,\n\n1144\n01:04:38,752 --> 01:04:40,370\n这不就基本上解决这个问题么？\nhaven't you basically solved the problem?\n\n1145\n01:04:43,370 --> 01:04:44,144\n教授：但问题就是\nPROFESSOR: But the issue is\n\n1146\n01:04:44,752 --> 01:04:46,384\n添加的这些规则是有穷个么？\ndo you put a finite number of those in?\n\n1147\n01:04:48,656 --> 01:04:53,130\n学生：如果你同时定义正、反两面 --\nAUDIENCE: If things are specified always in pairs--\n\n1148\n01:04:53,616 --> 01:04:57,072\n教授：但问题就是 你该如何去做推断？\nPROFESSOR: But the question is then what do you do about deduction?\n\n1149\n01:05:00,200 --> 01:05:02,112\n要知道 你不能直接定义命题的非\nSee, you can't specify NOTs.\n\n1150\n01:05:03,400 --> 01:05:04,768\n而问题就在于 在大型系统中\nBut the problem is, in a big system,\n\n1151\n01:05:04,784 --> 01:05:07,960\n可能含有无穷个数的东西\nit turns out that might not be a finite number of things.\n\n1152\n01:05:12,820 --> 01:05:15,290\n这其中有两个问题\nThere are also sort of two issues.\n\n1153\n01:05:15,290 --> 01:05:16,560\n其一是可能有无穷项\nPartly it might not be finite.\n\n1154\n01:05:16,690 --> 01:05:19,392\n另外是因为可能不向你想的那样\nPartly it might be that's not what you want.\n\n1155\n01:05:21,510 --> 01:05:24,528\n一个极好的例子 就是连通性\nSo a good example would be suppose I want to do connectivity.\n\n1156\n01:05:25,120 --> 01:05:26,544\n我想对连通性做推理\nI want a reason about connectivity.\n\n1157\n01:05:28,050 --> 01:05:30,384\n我会告诉你这有四个对象\nAnd I'm going to tell you there's four things:\n\n1158\n01:05:30,400 --> 01:05:33,744\nA、B、C和D\na and b and c and d.\n\n1159\n01:05:35,480 --> 01:05:38,190\n我会告诉你A和B相连\nAnd I'll tell you a is connected to b\n\n1160\n01:05:38,640 --> 01:05:41,424\nC和D相连\nand c's connected to d.\n\n1161\n01:05:43,200 --> 01:05:44,800\n然后我再告诉你A和D相连\nAnd now I'll tell you is a connected to d?\n\n1162\n01:05:45,056 --> 01:05:46,032\n就是这种情况\nThat's the question.\n\n1163\n01:05:46,780 --> 01:05:48,528\n在这个例子中\nThere's an example where I would like\n\n1164\n01:05:48,704 --> 01:05:50,352\n我就希望有“封闭世界假说”这样的东西\nsomething like the closed world assumption.\n\n1165\n01:05:54,432 --> 01:05:55,664\n这是个小玩具\nThat's a tiny toy,\n\n1166\n01:05:56,240 --> 01:05:58,304\n但是很多时候 我都想说\nbut a lot of times, I want to be able to say something like\n\n1167\n01:05:58,480 --> 01:06:01,340\n我没告诉你的事 都假设非真\nanything that I haven't told you, assume is not true.\n\n1168\n01:06:04,260 --> 01:06:06,272\n所以这并不是你显式地\nSo it's not as simple as you only want to put in\n\n1169\n01:06:06,272 --> 01:06:08,090\n为所有命题定义否命题就可以解决的\nexplicit NOTs all over the place.\n\n1170\n01:06:09,470 --> 01:06:12,704\n而是有些时候 你不清楚自己真正想要什么\nIt's that sometimes it really isn't clear what you even want.\n\n1171\n01:06:14,150 --> 01:06:17,920\n同时定义原命题与否命题又太过于精细\nThat having to specify both everything and not everything is too precise,\n\n1172\n01:06:17,936 --> 01:06:20,000\n这会使你陷入困境\nand then you get down into problems there.\n\n1173\n01:06:20,960 --> 01:06:22,688\n但还是有很多方法\nBut there are a lot of approaches that\n\n1174\n01:06:23,328 --> 01:06:25,936\n显式地定义否命题 并基于此进行推理\nyou know, that explicitly put in NOTs and reason based on that.\n\n1175\n01:06:26,510 --> 01:06:27,664\n这个想法非常好\nSo it's a very good idea.\n\n1176\n01:06:28,070 --> 01:06:31,456\n只是在一些复杂的大型问题中\nIt's just that then it starts becoming a little cumbersome\n\n1177\n01:06:31,488 --> 01:06:33,490\n这么做就变得有些笨重了\nin the very large problems you'd like to use.\n\n1178\n01:06:43,460 --> 01:06:45,968\n学生：有个论点 我不知道它和本节课的直接关系\nAUDIENCE: I'm not sure how directly related to the argument this is,\n\n1179\n01:06:46,000 --> 01:06:47,984\n但你想要表达的是\nbut one of your points was that\n\n1180\n01:06:48,496 --> 01:06:50,160\n封闭世界假说的危害之一就是\none of the dangers of the closed world rule is\n\n1181\n01:06:50,192 --> 01:06:52,064\n你永远不会真正了解那里的所有事物\nyou never really know all the things that are there.\n\n1182\n01:06:53,440 --> 01:06:55,328\n你永远不会知道它们的每个部分\nYou never really know all the parts to it.\n\n1183\n01:06:55,872 --> 01:06:58,160\n这难道不是任何一门程序设计语言的主要问题吗？\nIsn't that a major problem with any programming?\n\n1184\n01:06:58,160 --> 01:06:59,648\n写程序时 我总是\nI always write programs where I\n\n1185\n01:06:59,904 --> 01:07:01,568\n假设我考虑了所有的情况\nI assume that I've got all the cases,\n\n1186\n01:07:01,584 --> 01:07:03,408\n然后我检查了每一种情况\nand so I check for them all or whatever, and i\n\n1187\n01:07:04,060 --> 01:07:04,992\n然而在某处\nand somewhere down the road, I\n\n1188\n01:07:05,024 --> 01:07:06,520\n我发现了我遗漏了其中的一个\nI find out that I didn't check for one of them.\n\n1189\n01:07:07,390 --> 01:07:08,540\n教授：你说得很对\nPROFESSOR: Well, sure, it's true.\n\n1190\n01:07:08,540 --> 01:07:09,760\n但这里的问题在于\nBut the problem here is\n\n1191\n01:07:11,968 --> 01:07:15,472\n对于你所做的事情\nit's that assumption which is the thing that you're making\n\n1192\n01:07:15,488 --> 01:07:17,344\n你是否认为它是逻辑问题\nif you believe you're identifying this with logic.\n\n1193\n01:07:19,600 --> 01:07:20,510\n你说得非常正确\nSo you're quite right.\n\n1194\n01:07:20,510 --> 01:07:22,220\n这是你永远不会遇到的情况\nIt's a situation you're never in.\n\n1195\n01:07:22,220 --> 01:07:24,140\n问题在于 如果你认为\nThe problem is if you're starting to believe that\n\n1196\n01:07:24,176 --> 01:07:25,440\n你在进行逻辑式程序设计\nwhat this is doing is logic\n\n1197\n01:07:26,170 --> 01:07:27,328\n然后审视你所编写的规则\nand you look at the rules you write down\n\n1198\n01:07:27,344 --> 01:07:28,890\n并思考能从中推断出什么\nand say what can I deduce from them,\n\n1199\n01:07:29,536 --> 01:07:32,800\n你就需要清醒地认识到NOT具有另外的意义\nyou have to be very careful to remember that NOT means something else.\n\n1200\n01:07:33,470 --> 01:07:35,216\n它的意义基于某种假设\nAnd it means something else based on an assumption\n\n1201\n01:07:35,248 --> 01:07:36,704\n并且可能并不正确\nwhich is probably not true.\n\n1202\n01:07:39,030 --> 01:07:40,192\n学生：我不知道这样理解是否正确\nAUDIENCE: Do I understand you correctly that\n\n1203\n01:07:40,256 --> 01:07:41,840\n也就是我们无法通过改变NOT\nyou cannot fix this problem\n\n1204\n01:07:42,256 --> 01:07:46,080\n来消灭推断的所有可能性 从而解决这个问题？\nwithout killing off all possibilities of inference through altering NOT?\n\n1205\n01:07:46,544 --> 01:07:49,808\n教授：不 并不是这样\nPROFESSOR: No, that's not quite right.\n\n1206\n01:07:52,960 --> 01:07:55,088\n有很多种方法可以实现真正的逻辑非\nThere are ways to do logic with real NOTs.\n\n1207\n01:07:56,340 --> 01:07:58,032\n实际上有很多种方法\nThere are actually ways to do that.\n\n1208\n01:07:58,540 --> 01:08:00,848\n但目前没有一个广为人知的高效算法\nBut they're very inefficient as far as anybody knows.\n\n1209\n01:08:01,610 --> 01:08:02,560\n而且他们还--\nAnd they're much more--\n\n1210\n01:08:04,096 --> 01:08:06,896\n这里所谓的“推论”\nthey don't--  the, quote, inference in here\n\n1211\n01:08:07,390 --> 01:08:08,830\n是建立在这个合一算法\nis built into this unifier\n\n1212\n01:08:08,912 --> 01:08:11,296\n以及模式匹配算法之中的\nand this pattern matching unification algorithm.\n\n1213\n01:08:11,980 --> 01:08:16,192\n有多种方法可以实现真正的逻辑推理\nThere are ways to automate real logical reasoning.\n\n1214\n01:08:16,590 --> 01:08:18,192\n但它们并不基于此\nBut it's not based on that,\n\n1215\n01:08:18,510 --> 01:08:20,736\n而逻辑式程序设计语言也不倾向于这么做\nand logic programming languages don't tend to do that \n\n1216\n01:08:20,752 --> 01:08:23,850\n因为大家都知道 那样做非常低效\nbecause it's very inefficient as far as anybody knows.\n\n1217\n01:08:29,390 --> 01:08:30,032\n好吧 下课\nAll right, thank you.\n\n1218\n01:08:30,030 --> 01:08:37,120\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n1219\n01:08:37,152 --> 01:08:42,688\n\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec9a.srt",
    "content": "﻿1\n00:00:00,032 --> 00:00:02,048\nLearning-SICP学习小组\n倾情制作\n\n2\n00:00:02,040 --> 00:00:06,160\n翻译&&时间轴：邓雄飞\n压制&&特效：邓雄飞（Dysprosium）\n校对：邓雄飞（Dysprosium）\n\n3\n00:00:06,160 --> 00:00:08,160\n特别感谢：裘宗燕教授\n\n4\n00:00:08,160 --> 00:00:12,032\n计算机程序的构造和解释\n\n5\n00:00:12,032 --> 00:00:14,030\n寄存机器\nRegister Machines\n\n6\n00:00:17,260 --> 00:00:19,072\n教授：我认为 到目前为止\nPROFESSOR: Well, up 'til now, I suppose,\n\n7\n00:00:19,328 --> 00:00:23,936\n我们已经学习了很多关于\nwe've been learning about a lot of techniques for\n\n8\n00:00:24,096 --> 00:00:28,830\n组织程序以及操纵符号的技术\norganizing big programs, symbolic manipulation a bit,\n\n9\n00:00:30,848 --> 00:00:35,600\n以及用来构建语言的技术\nsome of the technology that you use for establishing languages,\n\n10\n00:00:35,630 --> 00:00:36,784\n用一门语言去创建另一门语言\none in terms of another,\n\n11\n00:00:37,104 --> 00:00:39,920\n这在组织大型程序时非常有用\nwhich is used for organizing very large programs.\n\n12\n00:00:39,968 --> 00:00:42,304\n实际上 我所知的最好的程序\nIn fact, the nicest programs I know\n\n13\n00:00:42,448 --> 00:00:44,432\n看起来更像是一堆语言\nlook more like a pile of languages\n\n14\n00:00:44,912 --> 00:00:47,968\n而不是将问题分解成若干部分\nthan like a decomposition of a problem into parts.\n\n15\n00:00:49,900 --> 00:00:51,456\n我想 此时此刻\nWell, I suppose at this point,\n\n16\n00:00:52,080 --> 00:00:53,584\n关于这类东西的工作方式\nthere are still, however, a few mysteries\n\n17\n00:00:53,616 --> 00:00:55,328\n仍然存在一些谜团\nabout how this sort of stuff works.\n\n18\n00:00:56,260 --> 00:00:59,680\n因此 我现在需要\nAnd so what we'd like to do now is\n\n19\n00:01:00,030 --> 00:01:02,608\n偏离原先的计划\ndiverge from the plan of\n\n20\n00:01:02,960 --> 00:01:05,420\n不再继续讲解如何组织大型程序\ntelling you how to organize big programs,\n\n21\n00:01:05,450 --> 00:01:08,192\n而是告诉你一些关于\nand rather tell you something about the mechanisms\n\n22\n00:01:08,528 --> 00:01:11,710\n使这些事情可以起作用的机制\nby which these things can be made to work.\n\n23\n00:01:12,190 --> 00:01:14,832\n这样做的主要是为了\nThe main reason for this is\n\n24\n00:01:15,808 --> 00:01:17,870\n揭秘\ndemystification, if you will,\n\n25\n00:01:18,656 --> 00:01:20,540\n剩下的很多谜团\nthat we have a lot of mysteries left,\n\n26\n00:01:21,080 --> 00:01:25,488\n比如说 如何控制程序的运行\nlike exactly how it is the case that a program is controlled,\n\n27\n00:01:26,080 --> 00:01:30,384\n计算机如何知晓下一步的动作\nhow a computer knows what the next thing to do is,\n\n28\n00:01:30,528 --> 00:01:31,744\n等等等等\nor something like that.\n\n29\n00:01:32,430 --> 00:01:35,568\n我现在就要让你们清楚地知道\nAnd what I'd like to do now is make that clear to you\n\n30\n00:01:35,856 --> 00:01:39,104\n就算你之前没有使用过计算机\nthat even if you've never played with a physical computer before,\n\n31\n00:01:39,568 --> 00:01:43,504\n但这种机制非常简单\nthe mechanism is really very simple,\n\n32\n00:01:44,336 --> 00:01:46,352\n你可以毫无问题地理解它\nand that you can understand it completely with no trouble.\n\n33\n00:01:47,650 --> 00:01:51,248\n好吧 我们先来想象一个 --\nSo I'd like to start by imagining that we--\n\n34\n00:01:51,328 --> 00:01:52,912\n先说明一下 我们采用的方法是\nwell, the way we're going to do this, by the way,\n\n35\n00:01:52,960 --> 00:01:55,808\n把一些非常简单的Lisp程序\nis we're going to take some very simple Lisp programs,\n\n36\n00:01:56,544 --> 00:01:58,128\n真的非常简单\nvery simple Lisp programs,\n\n37\n00:01:59,040 --> 00:02:00,624\n把它们转换成硬件\nand transform them into hardware.\n\n38\n00:02:02,160 --> 00:02:04,160\n我不会考虑一些中间步骤\nI'm not going to worry about some intermediate step\n\n39\n00:02:04,700 --> 00:02:07,456\n比如转换成某种现有的机器语言\nof going through some existing computer machine language\n\n40\n00:02:07,472 --> 00:02:09,050\n然后来解释计算机是如何工作的\nand then showing you how that computer works,\n\n41\n00:02:09,824 --> 00:02:12,000\n因为那不太明显\nbecause that's not as illuminating.\n\n42\n00:02:12,750 --> 00:02:14,176\n所以我真正要向你展示的是\nSo what I'm really going to show you\n\n43\n00:02:14,512 --> 00:02:17,488\n如何构建一台机器来完成\nis how a piece of machinery can be built\n\n44\n00:02:18,032 --> 00:02:22,040\n一项由你写的程序所描述的工作\nto do a job that you have written down as a program.\n\n45\n00:02:22,040 --> 00:02:24,032\n而程序呢 实际上就是一个机器的描述\nThat program is, in fact, a description of a machine.\n\n46\n00:02:25,760 --> 00:02:27,696\n我们从一个非常简单的程序开始\nWe're going to start with a very simple program,\n\n47\n00:02:28,096 --> 00:02:30,816\n然后演示一些简单的机制\nproceed to show you some simple mechanisms,\n\n48\n00:02:31,392 --> 00:02:33,680\n进而用更复杂的程序\nproceed to a few more complicated programs,\n\n49\n00:02:34,304 --> 00:02:37,420\n然后又演示一个不那么复杂的程序\nand then later show you a not very complicated program,\n\n50\n00:02:37,440 --> 00:02:41,230\n来演示求值器是如何变成硬件的\nhow the evaluator transforms into a piece of hardware.\n\n51\n00:02:41,230 --> 00:02:42,064\n当然 到那个时候\nAnd of course at that point,\n\n52\n00:02:42,080 --> 00:02:44,080\n你就有了通用的转换算法\nyou have made the universal transition\n\n53\n00:02:44,224 --> 00:02:46,880\n并且可以用一个定义明确的硬件\nand can execute any program imaginable\n\n54\n00:02:47,168 --> 00:02:48,800\n来执行任何可以想象的程序\nwith a piece of well-defined hardware.\n\n55\n00:02:51,728 --> 00:02:52,912\n那么 现在让我们开始\nWell, let's start up now,\n\n56\n00:02:53,056 --> 00:02:55,312\n给你们关于这些东西的具体感觉\ngive you a real concrete feeling for this sort of thing.\n\n57\n00:02:55,440 --> 00:02:57,664\n我们先从一个非常简单的程序开始\nLet's start with a very simple program.\n\n58\n00:02:59,600 --> 00:03:00,850\n这是欧几里得算法\nHere's Euclid's algorithm.\n\n59\n00:03:03,880 --> 00:03:07,008\n它实际上比欧几里德算法更现代一些\nIt's actually a little bit more modern than Euclid's algorithm.\n\n60\n00:03:07,020 --> 00:03:10,096\n我想 用来计算两数最大公约数的欧几里得算法\nEuclid's algorithm for computing the greatest common divisor of two numbers\n\n61\n00:03:10,416 --> 00:03:13,600\n是在公元前350年发明的\nwas invented 350 BC, I think.\n\n62\n00:03:14,300 --> 00:03:15,696\n它是已知最古老的算法\nIt's the oldest known algorithm.\n\n63\n00:03:19,320 --> 00:03:23,344\n我们先定义(GCD A B)\nBut here we're going to talk about GCD of A and B,\n\n64\n00:03:23,360 --> 00:03:25,616\n也就是用来计算A、B两数的最大公约数\nthe Greatest Common Divisor or two numbers, A and B.\n\n65\n00:03:26,208 --> 00:03:28,912\n这个算法相当简单\nAnd the algorithm is extremely simple.\n\n66\n00:03:29,500 --> 00:03:31,088\n如果B等于0\nIf B is 0,\n\n67\n00:03:34,160 --> 00:03:36,832\n那么结果就是A\nthen the result is going to be A.\n\n68\n00:03:37,520 --> 00:03:43,616\n否则结果就是 (GCD B\nOtherwise, the result is the GCD of B\n\n69\n00:03:44,496 --> 00:03:53,392\n(REMAINDER A B))\nand the remainder when A is divided by B.\n\n70\n00:03:58,530 --> 00:04:01,904\n这里 我们定义了一个简单的迭代过程\nSo this we have here is a very simple iterative process.\n\n71\n00:04:02,030 --> 00:04:04,080\n这是一个简单的递归过程\nThis a simple recursive procedure,\n\n72\n00:04:04,380 --> 00:04:07,536\n也可以说这个过程是递归地定义的\nrecursively defined procedure, recursive definition,\n\n73\n00:04:07,712 --> 00:04:09,264\n但它产生的计算过程是迭代的\nwhich yields an iterative process.\n\n74\n00:04:09,952 --> 00:04:12,460\n它的原理是 在每一步\nAnd the way it works is that every step,\n\n75\n00:04:12,800 --> 00:04:15,104\n判断B是否为0\nit determines whether B was zero.\n\n76\n00:04:16,240 --> 00:04:18,800\n如果B为0 那么A的值就是我们的答案\nAnd if B is 0, we got the answer in A.\n\n77\n00:04:19,632 --> 00:04:22,464\n否则就进入下一个步骤\nOtherwise, we make another step\n\n78\n00:04:22,496 --> 00:04:23,872\n其中A就变成旧的B\nwhere A is the old B,\n\n79\n00:04:23,888 --> 00:04:27,040\n而B的值 是A旧值除B旧值的余数\nand B is the remainder of the old A divided by the old B.\n\n80\n00:04:28,768 --> 00:04:29,552\n非常简单\nVery simple.\n\n81\n00:04:31,110 --> 00:04:32,720\n现在 我已经通过这种方式\nNow this, I've already told you\n\n82\n00:04:32,992 --> 00:04:34,860\n告诉了你一些机制\nsome of the mechanism by just saying it that way.\n\n83\n00:04:34,860 --> 00:04:35,904\n我是按时序告诉你们的\nI said it in time.\n\n84\n00:04:36,360 --> 00:04:37,728\n我说 其中有特定的步骤\nI said there are certain steps,\n\n85\n00:04:38,144 --> 00:04:39,328\n并且实际上\nand that, in fact,\n\n86\n00:04:39,520 --> 00:04:40,864\n你可以在这里知道\none of the things you can see here\n\n87\n00:04:41,184 --> 00:04:43,696\n为什么这个过程是迭代的\nis that one of the reasons why this is iterative\n\n88\n00:04:43,950 --> 00:04:47,680\n是因为最后一步无需额外信息来得到答案\nis nothing is needed of the last step to get the answer.\n\n89\n00:04:49,440 --> 00:04:55,290\n所有运行此算法所需的信息都在A和B中\nAll of the information that's needed to run this algorithm is in A and B.\n\n90\n00:04:55,744 --> 00:04:57,808\n它有两个定义明确的状态变量\nIt has two well-defined state variables.\n\n91\n00:05:00,470 --> 00:05:02,336\n现在 我就要给你们定义一台机器\nSo I'm going to define a machine for you\n\n92\n00:05:03,984 --> 00:05:05,552\n用来计算GCD\ncan compute you GCDs.\n\n93\n00:05:06,560 --> 00:05:07,120\n我们来看看\nNow let's see.\n\n94\n00:05:07,120 --> 00:05:11,280\n每台制造的计算机都是单进程计算机\nEvery computer that's ever been made that's a single-process computer,\n\n95\n00:05:11,800 --> 00:05:14,080\n而不是某种多处理器\nas opposed to a multiprocessor of some sort,\n\n96\n00:05:15,040 --> 00:05:16,592\n都是按照相同的方案制定的\nis made according to the same plan.\n\n97\n00:05:17,840 --> 00:05:19,536\n这种方案就是：计算机由两部分组成\nThe plan is the computer has two parts,\n\n98\n00:05:20,576 --> 00:05:22,352\n一部分叫数据通路\na part called the datapaths,\n\n99\n00:05:23,104 --> 00:05:24,368\n而另一部分叫控制器\nand a part called the controller.\n\n100\n00:05:25,910 --> 00:05:29,280\n数据通路相当于你可能有的计算器\nThe datapaths correspond to a calculator that you might have.\n\n101\n00:05:29,712 --> 00:05:31,872\n它有一些寄存器 能够存储数据\nIt contains certain registers that remember things,\n\n102\n00:05:31,904 --> 00:05:33,136\n你们都用过计算器\nand you've all used calculators.\n\n103\n00:05:33,560 --> 00:05:35,344\n它上面有一些按钮和指示灯\nIt has some buttons on it and some lights.\n\n104\n00:05:37,030 --> 00:05:38,496\n通过按下不同的按钮\nAnd so by pushing the various buttons,\n\n105\n00:05:38,528 --> 00:05:41,344\n你可以使操作在寄存器内发生\nyou can cause operations to happen inside there among the registers,\n\n106\n00:05:41,872 --> 00:05:43,488\n并显示计算结果\nand some of the results to be displayed.\n\n107\n00:05:45,160 --> 00:05:46,250\n它是完全机械式的\nThat's completely mechanical.\n\n108\n00:05:46,250 --> 00:05:49,552\n你可以认为那个盒子没有任何智能\nYou could imagine that box has no intelligence in it.\n\n109\n00:05:50,900 --> 00:05:53,280\n它能计算一个数的正弦也许令人吃惊\nNow it might be very impressive that it can produce the sine of a number,\n\n110\n00:05:53,536 --> 00:05:58,970\n但它显然是机械式的\nbut that at least is apparently possibly mechanical.\n\n111\n00:05:58,970 --> 00:06:01,712\n至少 我可以像打开GCD机器一样打开它\nAt least, I could open that up in the same way I'm about to open GCD.\n\n112\n00:06:02,690 --> 00:06:04,368\n也就是说 它其中可能有一整台计算机\nSo this may have a whole computer inside of it,\n\n113\n00:06:04,688 --> 00:06:05,696\n但这并不有趣\nbut that's not interesting.\n\n114\n00:06:05,940 --> 00:06:07,104\n加法相当简单\nAddition is certainly simple.\n\n115\n00:06:08,200 --> 00:06:09,840\n不借助额外机制就可以完成\nThat can be done without any further mechanism.\n\n116\n00:06:10,890 --> 00:06:15,648\n现在 如果我们来看另外的一部分：控制器\nNow also, if we were to look at the other half, the controller,\n\n117\n00:06:15,936 --> 00:06:17,392\n这一部分也非常简单\nthat's a part that's dumb, too.\n\n118\n00:06:18,190 --> 00:06:19,168\n它负责按下按钮\nIt pushes the buttons.\n\n119\n00:06:20,350 --> 00:06:21,520\n它根据指令序列来按按钮\nIt pushes them according to the sequence,\n\n120\n00:06:21,552 --> 00:06:22,848\n指令是写在纸上的\nwhich is written down on a piece of paper,\n\n121\n00:06:24,272 --> 00:06:25,648\n控制器还会观察指示灯\nand observes the lights.\n\n122\n00:06:26,290 --> 00:06:29,440\n而且每隔一段 它就会来到指令序列中的一处\nAnd every so often, it comes to a place in a sequence that says,\n\n123\n00:06:29,472 --> 00:06:32,370\n如果指示灯A亮 则执行某段指令\nif light A is on, do this sequence.\n\n124\n00:06:32,370 --> 00:06:33,856\n否则执行另外的指令\nOtherwise, do that sequence.\n\n125\n00:06:34,620 --> 00:06:37,456\n因此 这其中也没有什么复杂的\nAnd thereby, there's no complexity there either.\n\n126\n00:06:38,350 --> 00:06:39,328\n那么 让我们来画一下\nWell, let's just draw that\n\n127\n00:06:39,344 --> 00:06:40,570\n然后来感受一下它\nand see what we feel about that.\n\n128\n00:06:42,510 --> 00:06:44,848\n为了计算GCD\nSo for computing GCDs,\n\n129\n00:06:45,888 --> 00:06:49,520\n你们要知道：这其中有一些寄存器\nwhat I want you to think about is that there are these registers.\n\n130\n00:06:50,560 --> 00:06:53,024\n这里 寄存器就是一个存储数值的地方\nA register is a place where I store a number, in this case.\n\n131\n00:06:53,520 --> 00:06:54,656\n这个寄存器存储的是A\nAnd this one's called a.\n\n132\n00:06:56,810 --> 00:06:58,700\n而另外的这个存储的是B\nAnd then there's another one for storing b.\n\n133\n00:07:03,170 --> 00:07:05,456\n现在我们来看看 有了这些寄存器后能做什么\nNow we have to see what things we can do with these registers,\n\n134\n00:07:05,980 --> 00:07:08,736\n至于你能利用它做什么 并不是很明显\nand they're not entirely obvious what you can do with them.\n\n135\n00:07:09,840 --> 00:07:11,728\n那么 我们必须看看需要用它们做什么\nWell, we have to see what things we need to do with them.\n\n136\n00:07:11,824 --> 00:07:13,872\n我们来看看尝试求解的问题\nWe're looking at the problem we're trying to solve.\n\n137\n00:07:14,030 --> 00:07:16,096\n计算机设计的一个要点就是\nOne of the important things for designing a computer,\n\n138\n00:07:17,104 --> 00:07:19,584\n我想大多数设计师都不会照做\nwhich I think most designers don't do,\n\n139\n00:07:20,208 --> 00:07:21,888\n也就是专注于待解的问题\nis you stay the problem you want to solve\n\n140\n00:07:22,624 --> 00:07:25,180\n然后使用你研究问题所学到的东西\nand then use what you learn from studying the problem you want to solve\n\n141\n00:07:25,440 --> 00:07:27,280\n把那些求解问题所需要的机制\nto put in the mechanisms needed to solve it\n\n142\n00:07:27,530 --> 00:07:28,700\n融入正在构建的计算机中\nin the computer you're building,\n\n143\n00:07:28,816 --> 00:07:30,080\n不多也不少\nno more no less.\n\n144\n00:07:32,140 --> 00:07:33,968\n现在 可能你所要解决的问题\nNow it may be that the problem you're trying to solve\n\n145\n00:07:34,240 --> 00:07:35,408\n是大家共有的问题\nis everybody's problem,\n\n146\n00:07:36,060 --> 00:07:37,584\n这种情况下你需要构建\nin which case you have to build in a universal\n\n147\n00:07:37,600 --> 00:07:39,290\n某种语言的通用解释器\ninterpreter of some language.\n\n148\n00:07:40,190 --> 00:07:42,320\n但是你添加的机制不能比\nBut you shouldn't put any more in than required\n\n149\n00:07:42,352 --> 00:07:44,256\n想构建的语言解释器的需求多\nto build the universal interpreter of some language.\n\n150\n00:07:44,448 --> 00:07:45,856\n这一点 我们稍后来讨论\nWe'll worry about that in a second.\n\n151\n00:07:47,232 --> 00:07:49,930\n好了 让我们回到这里\nOK, going back to here, let's see.\n\n152\n00:07:49,930 --> 00:07:51,248\n我们必须能够做什么？\nWhat do we have to be able to do?\n\n153\n00:07:51,792 --> 00:07:54,144\n首先 我们能把B的值赋给A\nWell, somehow, we have to be able to get B into A.\n\n154\n00:07:56,080 --> 00:07:59,600\n我们要能够把B的旧值赋给A\nWe have to be able to get the old value of B into the value of A.\n\n155\n00:08:00,380 --> 00:08:03,328\n因此 我们需要某种能够让数据流通的“路径”\nSo we have to have some path by which stuff can flow\n\n156\n00:08:03,344 --> 00:08:04,760\n而不管数据具体是什么\nwhatever this information is,\n\n157\n00:08:05,376 --> 00:08:06,576\n从B到A的通路\nOK? from b to a.\n\n158\n00:08:07,390 --> 00:08:09,264\n我箭头来指示\nI'm going to draw that with by an arrow\n\n159\n00:08:09,520 --> 00:08:12,624\n我们能够把B的值赋给A\nsaying that it is possible to move the contents of b into a,\n\n160\n00:08:12,960 --> 00:08:14,576\n从而替换A的旧值\nreplacing the value of a.\n\n161\n00:08:15,120 --> 00:08:16,736\n当你按下这里的按钮后\nAnd there's a little button here which you push\n\n162\n00:08:17,488 --> 00:08:18,560\n就能够实现这个效果\nwhich allows that to happen.\n\n163\n00:08:19,710 --> 00:08:20,784\n这个按钮就在这里\nThat's what the little x is here.\n\n164\n00:08:23,070 --> 00:08:23,936\n同样的\nNow it's also the case\n\n165\n00:08:23,952 --> 00:08:26,288\n我还需要能够计算A除B的余数\nthat I have to be able to compute the remainder of a and b.\n\n166\n00:08:27,000 --> 00:08:28,496\n这可能混乱而又复杂\nNow that may be a complicated mess.\n\n167\n00:08:28,860 --> 00:08:30,864\n但另一方面 我会把它放到一个小盒子中\nOn the other hand, I'm going to make it a small box.\n\n168\n00:08:31,960 --> 00:08:33,920\n如果有必要的话 我们可以打开那个盒子\nIf we have to, we may open up that box\n\n169\n00:08:34,128 --> 00:08:35,632\n看看其中有些什么\nand look inside and see what it is.\n\n170\n00:08:37,770 --> 00:08:39,168\n这就是那个小盒子\nSo here, I'm going to have a little box,\n\n171\n00:08:39,200 --> 00:08:40,380\n我这么来画它\nwhich I'm going to draw this way,\n\n172\n00:08:43,168 --> 00:08:44,384\n我把它叫做REM\nwhich we'll call the remainder.\n\n173\n00:08:46,440 --> 00:08:48,608\n它接受A\nAnd it's going to take in a.\n\n174\n00:08:50,910 --> 00:08:52,160\n同时也要接受B\nThat's going to take in b.\n\n175\n00:08:54,370 --> 00:08:56,512\n它有一个输出\nAnd it's going to put out something,\n\n176\n00:08:58,896 --> 00:09:00,464\n也就是A除以B的余数\nthe remainder of a divided by b.\n\n177\n00:09:02,290 --> 00:09:03,616\n在这里 我们同样需要能够\nAnother thing we have to see here is\n\n178\n00:09:03,648 --> 00:09:06,060\n判断B是否等于0\nthat we have to be able to test whether b is equal to 0.\n\n179\n00:09:08,000 --> 00:09:09,664\n也就是说 总得有个东西\nWell, that means somebody's got to be looking at--\n\n180\n00:09:10,000 --> 00:09:12,304\n去查询B的值\na thing that's looking at the value of b.\n\n181\n00:09:13,390 --> 00:09:14,400\n这是一个指示灯\nI have a light bulb here\n\n182\n00:09:15,856 --> 00:09:17,390\n当B等于0时 它就会点亮\nwhich lights up if b equals 0.\n\n183\n00:09:21,110 --> 00:09:22,016\n它就是干这个的\nThat's its job.\n\n184\n00:09:24,030 --> 00:09:26,784\n最后 因为我们希望\nAnd finally, I suppose, because of the fact\n\n185\n00:09:26,960 --> 00:09:30,432\nA的新值是B的旧值\nthat we want the new value of a to be the old value of b,\n\n186\n00:09:30,464 --> 00:09:34,416\n同时B的新值是有关于A的\nand simultaneously the new value of b to be something I've done with a,\n\n187\n00:09:35,280 --> 00:09:37,600\n如果我打算让机器\nand if I plan to make my machine\n\n188\n00:09:37,808 --> 00:09:39,744\n一次只发生一件事\nsuch that everything happens one at a time,\n\n189\n00:09:40,208 --> 00:09:41,408\n一次执行一个动作\none motion at a time,\n\n190\n00:09:41,616 --> 00:09:43,424\n并且我不能在一个寄存器中放两个数字\nand I can't put two numbers in a register,\n\n191\n00:09:44,032 --> 00:09:46,300\n那么进行互换时 必须有另外的地方放置一个数字\nthen I have to have another place to put one while I'm interchanging.\n\n192\n00:09:49,296 --> 00:09:49,600\n对吧？\nOK?\n\n193\n00:09:50,000 --> 00:09:51,856\n我不能同时交换两手的东西\nI can't interchange the two things in my hands,\n\n194\n00:09:52,110 --> 00:09:53,728\n除非我一手拿两个\nunless I either put two in one hand\n\n195\n00:09:53,728 --> 00:09:55,130\n然后从中取另外一个\nand then pull it back the other way,\n\n196\n00:09:55,504 --> 00:09:56,912\n或者我先放下一个\nor unless I put one down,\n\n197\n00:09:57,024 --> 00:09:58,688\n取得另一个后再像这样捡起来\npick it up, and put the other one, like that\n\n198\n00:09:59,648 --> 00:10:00,944\n除非我是耍杂技的\nunless I'm a juggler,\n\n199\n00:10:01,660 --> 00:10:03,500\n当然正如大家所见 我并不是\nwhich I'm not, as you can see,\n\n200\n00:10:04,656 --> 00:10:07,360\n这种情况下 我就会遇到时序错误\nin which case I have a possibility of timing errors.\n\n201\n00:10:08,850 --> 00:10:11,040\n事实上 人们所做的许多类型的计算机设计\nIn fact, much of the type of computer design\n\n202\n00:10:11,072 --> 00:10:12,688\n都遇到了时序错误\npeople do involves timing errors,\n\n203\n00:10:13,120 --> 00:10:15,008\n或者潜在的时序错误\nof some potential timing errors,\n\n204\n00:10:15,248 --> 00:10:16,432\n我不太喜欢这种错误\nwhich I don't much like.\n\n205\n00:10:17,340 --> 00:10:18,640\n因此 出于这个原因\nBut. So for that reason,\n\n206\n00:10:18,688 --> 00:10:21,216\n我需要有一个地方来放置\nI have to have a place to put the third thing down\n\n207\n00:10:22,060 --> 00:10:23,296\n其中的一个元素\nthe second one of them down.\n\n208\n00:10:23,410 --> 00:10:24,720\n因此 这里有一个寄存器\nSo I have a place called t,\n\n209\n00:10:24,752 --> 00:10:26,840\n用来存放临时值T\nwhich is a register just for temporary, t,\n\n210\n00:10:28,592 --> 00:10:29,632\n上面有一个按钮\nwith a button on it.\n\n211\n00:10:30,470 --> 00:10:31,888\n我会使用它的结果\nAnd then I'll take the result of that,\n\n212\n00:10:31,904 --> 00:10:34,144\n因为我需要把这个结果送入B\nsince I have to take that and put into b, over here,\n\n213\n00:10:34,688 --> 00:10:36,736\n我们会把结果像这样给送过来\nwe'll take the result of that and go like this,\n\n214\n00:10:38,416 --> 00:10:39,300\n这里同样有一个按钮\nand a button here.\n\n215\n00:10:42,430 --> 00:10:45,840\n这就是GCD机器的数据通路\nSo that's the datapaths of a GCD machine.\n\n216\n00:10:47,600 --> 00:10:48,576\n那么 控制器又是怎样的呢？\nNow what's the controller?\n\n217\n00:10:49,740 --> 00:10:51,280\n控制器同样很简单\nController's a very simple thing, too.\n\n218\n00:10:52,280 --> 00:10:53,264\n机器具有状态\nThe machine has a state.\n\n219\n00:10:54,384 --> 00:10:57,728\n我喜欢形象地把它们比作迷宫\nThe way I like to visualize that is that I've got a maze.\n\n220\n00:10:59,010 --> 00:11:03,200\n这个迷宫的各处是通过直接的箭头连接的\nAnd the maze has a bunch of places connected by directed arrows.\n\n221\n00:11:04,430 --> 00:11:05,600\n而我有一颗弹珠\nAnd what I have is a marble,\n\n222\n00:11:06,464 --> 00:11:09,072\n它代表了控制器的状态\nwhich represents the state of the controller.\n\n223\n00:11:10,740 --> 00:11:12,272\n弹珠在迷宫中四处滚动\nThe marble rolls around in the maze.\n\n224\n00:11:13,744 --> 00:11:17,150\n当然 这种类比因能量的原因而不成立\nOf course, this analogy breaks down for energy reasons.\n\n225\n00:11:17,150 --> 00:11:19,088\n有时我不得不将弹珠泵到顶部\nI sometimes have to pump the marble up to the top,\n\n226\n00:11:19,120 --> 00:11:21,856\n不然它就会成为一台永动机\nbecause it's going to otherwise be a perpetual motion machine.\n\n227\n00:11:22,000 --> 00:11:23,328\n但不用担心那么多\nBut not worrying about that,\n\n228\n00:11:23,904 --> 00:11:25,904\n这并不是一个物理比喻\nthis is not a physical analogy.\n\n229\n00:11:26,080 --> 00:11:27,424\n弹珠到处滚动\nThis marble rolls around.\n\n230\n00:11:27,680 --> 00:11:29,568\n就像弹球机一样\nAnd every time it rolls around certain bumpers,\n\n231\n00:11:29,680 --> 00:11:30,976\n每次当它滚动到一些缓冲器时\nlike in a pinball machine,\n\n232\n00:11:31,264 --> 00:11:32,608\n它就会按下这些按钮\nit pushes one of these buttons.\n\n233\n00:11:34,830 --> 00:11:37,504\n它也会经常来到一个分支区域\nAnd every so often, it comes to a place, which is a division,\n\n234\n00:11:38,624 --> 00:11:39,680\n它要在这里做选择\nwhere it has to make a choice.\n\n235\n00:11:40,250 --> 00:11:42,360\n然后有一个由这个组件控制的挡板\nAnd there's a flap, which is controlled by this.\n\n236\n00:11:46,000 --> 00:11:48,820\n所以这是一个非常机械化的思考方式\nSo that's a really mechanical way of thinking about it.\n\n237\n00:11:48,820 --> 00:11:51,056\n当然 真实计算机中的控制器\nOf course, controllers not these days, are not built that way\n\n238\n00:11:51,088 --> 00:11:51,840\n并不是这样的\nin real computers.\n\n239\n00:11:51,840 --> 00:11:56,016\n而是由一些ROM和状态寄存器构成\nThey're built with a little bit of ROM and a state register.\n\n240\n00:11:56,610 --> 00:11:58,736\n但曾几何时 像DEC、PDP-6这些个机器\nBut there was a time, like the DEC PDP-6,\n\n241\n00:11:59,296 --> 00:12:01,024\n它们的控制器就是我们说的那样\nwhere that's how you built the controller of a machine.\n\n242\n00:12:01,808 --> 00:12:03,616\n延迟线上有一些比特信息\nThere was a bit that ran around the delay line,\n\n243\n00:12:05,696 --> 00:12:08,144\n它随着时间的推移而触发事件\nand it triggered things as it went by.\n\n244\n00:12:08,580 --> 00:12:10,704\n然后回到开始并再次轮回\nAnd it would come back to the beginning and get fed round again.\n\n245\n00:12:11,990 --> 00:12:13,728\n当然 还有各种各样的错误\nAnd of course, there were all sorts of great bugs you could have\n\n246\n00:12:13,744 --> 00:12:17,670\n比如两个比特的信息 -- 对应两个弹珠\nlike two bits going around, two marbles.\n\n247\n00:12:17,670 --> 00:12:19,260\n机器也会丢失弹珠\nAnd then the machine has lost its marbles.\n\n248\n00:12:19,456 --> 00:12:20,208\n这也会发生\nThat happens, too.\n\n249\n00:12:20,980 --> 00:12:21,584\n好吧\nOh, well.\n\n250\n00:12:22,272 --> 00:12:24,224\n无论如何 对于这台机器\nSo anyway, for this machine,\n\n251\n00:12:24,272 --> 00:12:25,488\n我想要这么来做\nwhat I have to do is the following.\n\n252\n00:12:25,808 --> 00:12:27,744\n迷宫从这里开始\nI'm going to start my maze here.\n\n253\n00:12:30,520 --> 00:12:32,736\n我首先要做的是\nAnd the first thing I've got to do,\n\n254\n00:12:33,760 --> 00:12:36,752\n用一个你们非常熟悉的流程图记号\nis in a notation which many of you are familiar with,\n\n255\n00:12:37,072 --> 00:12:39,856\n这是一个判断：B是否为0\nis b equal to zero, a test.\n\n256\n00:12:41,504 --> 00:12:43,790\n如果判断为是的话\nAnd there's a possibility, either yes,\n\n257\n00:12:43,936 --> 00:12:45,584\n那我就做完了\nin which case I'm done.\n\n258\n00:12:49,790 --> 00:12:51,264\n否则的话\nOtherwise, if no,\n\n259\n00:12:52,704 --> 00:12:54,320\n我就不得不滚动一些缓冲器\nthen I'm going have to roll over some bumpers.\n\n260\n00:12:55,008 --> 00:12:56,464\n按照下列顺序执行\nI'm going to do it in the following order.\n\n261\n00:12:57,420 --> 00:13:03,408\n我想向这样来做一个互换游戏\nI want to, I want to do this interchange game.\n\n262\n00:13:04,050 --> 00:13:05,808\n首先 因为我需要A和B\nNow first, since I need both a and b,\n\n263\n00:13:06,320 --> 00:13:08,576\n但首先 -- 虽然并不是必要的\nbut then the first-- and this is not necessary--\n\n264\n00:13:08,656 --> 00:13:09,728\n我需要先把它们收集起来\nI want to collect this.\n\n265\n00:13:11,070 --> 00:13:12,624\n这里的值要送入到B中\nThis is the thing that's going to go into b.\n\n266\n00:13:13,240 --> 00:13:14,032\n因此 我会说\nSo I'm going to say,\n\n267\n00:13:14,288 --> 00:13:16,272\n用A和B的值来计算这个\ntake this, which depends upon both a and b,\n\n268\n00:13:16,368 --> 00:13:18,672\n并把算得的余数放到这里\nand put the remainder into here.\n\n269\n00:13:19,150 --> 00:13:20,336\n因此 我首先要按下这个按钮\nSo I'm going to push this button first.\n\n270\n00:13:21,536 --> 00:13:24,432\n然后我要把B的值送入A\nThen, I'm going to transfer b to a,\n\n271\n00:13:24,448 --> 00:13:25,600\n通过按这个钮来实现\npush that button,\n\n272\n00:13:25,824 --> 00:13:27,632\n然后我再把临时值送入B\nand then I transfer the temporary into b,\n\n273\n00:13:28,768 --> 00:13:29,424\n通过这个按钮实现\npush that button.\n\n274\n00:13:32,030 --> 00:13:34,970\n这是一个相当时序化的机器\nSo a very sequential machine,\n\n275\n00:13:35,392 --> 00:13:36,528\n它非常的低效\nit's very inefficient.\n\n276\n00:13:37,750 --> 00:13:39,056\n但目前来说还好\nBut that's fine right now.\n\n277\n00:13:39,810 --> 00:13:40,970\n我们来为按钮命名\nWe're going to name the buttons,\n\n278\n00:13:41,472 --> 00:13:42,720\nT←R\nt gets remainder.\n\n279\n00:13:46,750 --> 00:13:48,736\nA←B\na gets b.\n\n280\n00:13:50,030 --> 00:13:54,816\nB←T\nAnd b gets t.\n\n281\n00:13:55,470 --> 00:13:57,632\n然后我要来到这里\nAnd then I'm going to go around here\n\n282\n00:13:58,784 --> 00:13:59,888\n也就是回到开始的地方\nand it's to go back to start.\n\n283\n00:14:01,620 --> 00:14:03,870\n在这里 我们看到了什么？\nAnd if you look, what are we seeing here?\n\n284\n00:14:03,870 --> 00:14:04,912\n我们看到各种各样的 --\nWe're seeing the various--\n\n285\n00:14:05,056 --> 00:14:07,168\n我们真正拥有的是某种机械连接\nwhat I really have is some sort of mechanical connection,\n\n286\n00:14:07,424 --> 00:14:13,632\n其中T←R控制了这个东西\nwhere t gets r controls this thing.\n\n287\n00:14:16,830 --> 00:14:21,488\nA←B控制了这个东西\nAnd I have here that a gets b controls this fellow over here,\n\n288\n00:14:26,960 --> 00:14:28,120\n而这里的这个东西\nand this fellow over here.\n\n289\n00:14:28,120 --> 00:14:31,088\n同学们 这简直太恶劣了\nBoy, that's absolutely pessimal,\n\n290\n00:14:31,488 --> 00:14:32,480\n一点也没有优化\nthe inverse of optimal.\n\n291\n00:14:32,630 --> 00:14:34,590\n我画的所有线条都相互交叉\nEvery line heads across every other line the way I drew it.\n\n292\n00:14:38,540 --> 00:14:41,150\n我想B←T控制的是这个\nI suppose this goes here, b gets t.\n\n293\n00:14:45,690 --> 00:14:47,952\n现在 我就要运行这台机器了\nNow I'd like to run this machine.\n\n294\n00:14:48,040 --> 00:14:49,344\n但是在我运行它之前\nBut before I run the machine,\n\n295\n00:14:49,376 --> 00:14:51,408\n我想写下它的控制器的描述\nI want to write down a description of this controller,\n\n296\n00:14:51,630 --> 00:14:52,816\n以便使你们相信\njust so you can see that these things,\n\n297\n00:14:52,848 --> 00:14:55,632\n这些东西可以组织成某种良好的语言\nof course, as usual, can be written down in some nice language,\n\n298\n00:14:56,080 --> 00:14:58,080\n这样我们就不必总是像这样画图\nso that we don't have to always draw these diagrams.\n\n299\n00:14:58,368 --> 00:15:00,688\n图示的缺陷之一 就是占用了太多空间\nOne of the problems with diagrams is that they take up a lot of space.\n\n300\n00:15:00,896 --> 00:15:01,980\n对于这样的一个小型机器来说\nAnd for a machine this small,\n\n301\n00:15:02,000 --> 00:15:03,056\n它占用了两块黑板\nit takes two blackboards.\n\n302\n00:15:03,220 --> 00:15:05,248\n而一台求值器机器\nFor a machine that's the evaluator machine,\n\n303\n00:15:05,408 --> 00:15:07,104\n我就很难将它画在这间屋子里了\nI have trouble putting it into this room,\n\n304\n00:15:07,952 --> 00:15:09,168\n尽管它还不是非常大\neven though it isn't very big.\n\n305\n00:15:09,900 --> 00:15:11,280\n因此我要为它构造一门小型语言\nSo I'm going to make a little language for this\n\n306\n00:15:11,296 --> 00:15:12,512\n用来描述这个机器\nthat's just a description of that,\n\n307\n00:15:13,104 --> 00:15:23,296\n(DEFIME-MACHINE GCD\nsaying define a machine we'll call GCD.\n\n308\n00:15:24,420 --> 00:15:25,664\n当然 一旦我们有了像这样的描述\nOf course, once we have something like this,\n\n309\n00:15:25,680 --> 00:15:26,832\n我们就能够模拟该机器\nwe have a simulator for it.\n\n310\n00:15:27,220 --> 00:15:29,424\n我之所以想构建这种形式的语言\nAnd the reason why we want to build a language in this form,\n\n311\n00:15:29,568 --> 00:15:32,944\n是因为我们能够立即操纵这些表达式\nis because all of a sudden we can manipulate these expressions that I'm writing down.\n\n312\n00:15:33,210 --> 00:15:34,912\n因此 我也就能够\nAnd then of course I can write things I can\n\n313\n00:15:35,290 --> 00:15:38,160\n代数地操作 或者模拟这些东西\nalgebraically manipulate these things, simulate them\n\n314\n00:15:38,208 --> 00:15:39,968\n以及各种各样我想进行的操作\nall that sort of things that I might want to do,\n\n315\n00:15:40,128 --> 00:15:42,592\n或者还可以把它们转换成布局图 谁知道呢？\nperhaps transform them as a layout, who knows.\n\n316\n00:15:43,630 --> 00:15:48,384\n一旦我有了寄存器的良好表示\nOnce I have a nice representation of registers,\n\n317\n00:15:48,510 --> 00:15:49,616\n它有一些寄存器\nit has certain registers,\n\n318\n00:15:53,008 --> 00:15:55,640\n记作(REGISTERS A B T)\nwhich we can call A, B, and T.\n\n319\n00:15:56,752 --> 00:15:57,808\n它还有控制器\nAnd there's a controller.\n\n320\n00:16:02,190 --> 00:16:04,464\n实际上 更好的做法是让它更显式一些\nActually, a better language, which would be more explicit,\n\n321\n00:16:04,496 --> 00:16:06,976\n也就是说 为每一个按钮命名\nwould be one which named every button\n\n322\n00:16:08,144 --> 00:16:10,176\n并指明它们的操作\nalso and said what it did.\n\n323\n00:16:10,420 --> 00:16:11,376\n比如说这个按钮\nLike, this button\n\n324\n00:16:11,552 --> 00:16:14,190\n会让T的值送入到B中\ncauses the contents of T to go to the contents of B.\n\n325\n00:16:15,100 --> 00:16:16,096\n但我却不想这么做\nWell I don't want to do that,\n\n326\n00:16:16,112 --> 00:16:17,952\n因为这样会让代码难以阅读\nbecause it's actually harder to read to do that,\n\n327\n00:16:18,208 --> 00:16:19,344\n也会占用更多空间\nand it takes up more space.\n\n328\n00:16:19,510 --> 00:16:22,368\n所以我会把相关的指令写在控制器中\nSo I'm going to have that in the instructions written in the controller.\n\n329\n00:16:23,290 --> 00:16:25,248\n这样就隐式地指明了具体的操作\nIt's going to be implicit what the operations are.\n\n330\n00:16:26,320 --> 00:16:28,576\n可以通过阅读代码推断出来\nThey can be deduced by reading these\n\n331\n00:16:29,168 --> 00:16:31,392\n并收集所有可以完成的不同事情\nand collecting together all the different things that can be done.\n\n332\n00:16:31,696 --> 00:16:33,500\n我们来看一看\nWe look and see, see...\n\n333\n00:16:33,500 --> 00:16:34,704\n我们来看下这些东西是什么吧\nWell, let's just look at what these things are.\n\n334\n00:16:35,712 --> 00:16:37,296\n首先是一个循环\nThere's a little loop that we go around\n\n335\n00:16:38,240 --> 00:16:40,208\n先是一条分支指令\nwhich says branch,\n\n336\n00:16:42,640 --> 00:16:46,464\n这个就对应了机器中的小挡板\nthis is the representation of the little flap\n\n337\n00:16:46,896 --> 00:16:48,496\n它决定了你在此处的走向\nthat decides which way you go here,\n\n338\n00:16:49,104 --> 00:16:58,000\n判断 -- 取B的值 并判断是否为0\nif 0, OK, fetch of B, the contents of B,\n\n339\n00:16:58,650 --> 00:17:00,064\n如果B的值是0\nand if the contents of B is 0,\n\n340\n00:17:00,320 --> 00:17:01,720\n那么就跳转到一个叫DONE的地方\nthen go to a place called done.\n\n341\n00:17:03,640 --> 00:17:05,296\n现在 你们在这里看到的是\nNow, one thing you're seeing here,\n\n342\n00:17:05,296 --> 00:17:07,400\n这个看起来非常像传统计算机语言\nthis looks very much like a traditional computer language.\n\n343\n00:17:08,170 --> 00:17:09,552\n但你们所见的是\nAnd what you're seeing here\n\n344\n00:17:10,032 --> 00:17:12,000\n一些个标签\nis things like labels\n\n345\n00:17:12,992 --> 00:17:16,864\n它们代表着存放了一系列指令的地方\nthat represent places in a sequence written down as a sequence.\n\n346\n00:17:17,600 --> 00:17:18,944\n之所以需要它们\nThe reason why they're needed\n\n347\n00:17:19,488 --> 00:17:21,152\n是因为在这里\nis because over here,\n\n348\n00:17:21,456 --> 00:17:22,816\n我表达了“循环”的概念\nI've written something with loops.\n\n349\n00:17:23,320 --> 00:17:26,112\n但是如果我是在写英文之类的文本\nBut if I'm writing English text, or something like that,\n\n350\n00:17:26,448 --> 00:17:28,096\n就很难去引用一个位置\nit's hard to refer to a place.\n\n351\n00:17:28,580 --> 00:17:29,536\n我没有箭头\nI don't have arrows.\n\n352\n00:17:30,800 --> 00:17:33,024\n箭头是通过\nArrows are represented by giving names\n\n353\n00:17:33,056 --> 00:17:34,440\n给箭头所指的地方命名来表示的\nto the places where the arrows terminate,\n\n354\n00:17:34,576 --> 00:17:36,288\n并通过名字来引用\nand then referring to them by those names.\n\n355\n00:17:37,408 --> 00:17:38,592\n这只是一种编码\nNow this is just an encoding.\n\n356\n00:17:39,860 --> 00:17:41,888\n而不是某种魔法\nThere's nothing magical about things like that.\n\n357\n00:17:43,150 --> 00:17:44,960\n接下来我们要做的是\nNext thing we're going to do is we're going to say,\n\n358\n00:17:45,024 --> 00:17:46,840\n我们如何来实现T←R\nhow do we do T gets R?\n\n359\n00:17:47,450 --> 00:17:49,760\n非常简单 用ASSIGN\nOh, that's easy enough, assign.\n\n360\n00:17:52,192 --> 00:17:55,552\n我们把余数赋值给T\nWe assign to T the remainder.\n\n361\n00:17:56,320 --> 00:17:59,248\nASSIGN就是按钮的名字\nAssign is the name of the button.\n\n362\n00:18:01,470 --> 00:18:02,640\n就是按按钮的家伙\nThat's the button-pusher.\n\n363\n00:18:03,140 --> 00:18:04,976\n把余数赋给T\nAssign to T the remainder,\n\n364\n00:18:04,992 --> 00:18:06,768\n这个操作是这样表示的\nand here's the representation of the operation,\n\n365\n00:18:11,744 --> 00:18:17,536\n取A、B的值 相除得到余数\nwhen we divide the fetch of A by the fetch of B.\n\n366\n00:18:23,856 --> 00:18:30,992\n同时 我们也要取B的值 赋给A\nAnd we're also going to assign to A the fetch of B,\n\n367\n00:18:34,990 --> 00:18:47,888\n再取T的值赋给B\nassign to B the result of getting the contents of T.\n\n368\n00:18:49,616 --> 00:18:51,856\n现在 我需要引用这个开头\nAnd now I have to refer to the beginning here.\n\n369\n00:18:53,184 --> 00:18:55,920\n呃 我为什么不把这里叫做LOOP呢？\nI see, why don't I call that loop like I have here?\n\n370\n00:19:04,096 --> 00:19:07,040\n这就是如何引用这个箭头\nOK? So that's that reference to that arrow.\n\n371\n00:19:07,610 --> 00:19:08,950\n当执行到DONE时 就完成了所有操作\nAnd when we're done, we're done.\n\n372\n00:19:09,024 --> 00:19:13,072\n我们来到了这里 所有指令的结尾\nWe go to here, which is the end of the thing.\n\n373\n00:19:15,260 --> 00:19:17,040\n这段文字化描述的就是\nSo here's just a written representation\n\n374\n00:19:17,696 --> 00:19:20,860\n我们在这里画的一小部分机器\nof this fragment of machinery that we've drawn here.\n\n375\n00:19:21,660 --> 00:19:24,848\n下面 我就要运行它\nNow the next thing I'd like to do is run this.\n\n376\n00:19:25,490 --> 00:19:26,656\n我想让你们感受一下它的运行\nI want us to feel it running.\n\n377\n00:19:27,620 --> 00:19:29,808\n从来没有做过这个 你必须做一次\nNever done this before, you got to do it once.\n\n378\n00:19:31,010 --> 00:19:32,624\n让我们以一个具体的问题来演示\nSo let's take a particular problem.\n\n379\n00:19:33,100 --> 00:19:34,704\n假设我们想要计算\nSuppose we want to compute the GCD\n\n380\n00:19:35,040 --> 00:19:40,680\n30和42的最大公约数\nof a equals 30 and b equals 42.\n\n381\n00:19:42,210 --> 00:19:44,928\n我现在不知道结果是多少\nI have no idea what that is right now.\n\n382\n00:19:45,860 --> 00:19:47,600\n但我知道A=30而B=42\nBut a 30 and b is 42.\n\n383\n00:19:50,960 --> 00:19:52,096\n我就这么着开始\nSo that's how I start this thing up.\n\n384\n00:19:52,608 --> 00:19:53,904\n那么 我首先要做些什么呢？\nWell, what's the first thing I do?\n\n385\n00:19:54,240 --> 00:19:56,864\n我先判断B是否为0：否\nI say is B equal to 0, no.\n\n386\n00:19:57,590 --> 00:20:02,112\n然后计算A除B的余数 并赋给T\nThen assign to T the remainder of the fetch of A and the fetch of B.\n\n387\n00:20:02,800 --> 00:20:07,600\n当然 30除以42的余数就是30自己\nWell the remainder of 30 when divided by 42 is itself 30.\n\n388\n00:20:11,130 --> 00:20:12,032\n按下那个按钮\nPush that button.\n\n389\n00:20:12,920 --> 00:20:15,104\n现在弹珠就滚动到了这里\nNow the marble has rolled to here.\n\n390\n00:20:17,100 --> 00:20:18,064\nA←B\nA gets B.\n\n391\n00:20:19,024 --> 00:20:20,768\n又按下了这个按钮\nThat pushes this button.\n\n392\n00:20:21,220 --> 00:20:22,544\n因此42来到了这里\nSo 42 moves into here.\n\n393\n00:20:26,592 --> 00:20:27,600\nB←T\nB gets T.\n\n394\n00:20:28,368 --> 00:20:29,344\n按下了这个按钮\nPush that button.\n\n395\n00:20:29,870 --> 00:20:30,960\n30来到了这里\nThe 30 goes here.\n\n396\n00:20:32,576 --> 00:20:33,696\n这样我就交换了它们\nLet met just interchange them.\n\n397\n00:20:34,660 --> 00:20:38,272\n我们再来看看 回到开始\nNow let's see, go back to the beginning.\n\n398\n00:20:38,640 --> 00:20:39,728\nB为0么？不\nB 0, no.\n\n399\n00:20:40,192 --> 00:20:41,504\n将余数赋给T\nT gets the remainder.\n\n400\n00:20:43,230 --> 00:20:46,304\n我想 42除以30的余数是12\nI suppose the remainder when dividing 42 by 30 is 12.\n\n401\n00:20:47,240 --> 00:20:48,304\n按下这个钮\nI push that one.\n\n402\n00:20:48,530 --> 00:20:51,408\n下面 我想让30来到这里\nNext thing I do is allow the 30 to go to here,\n\n403\n00:20:53,904 --> 00:20:55,950\n按下这个钮 让12来到这里\npush this one, allow the 12 to go to here.\n\n404\n00:20:58,416 --> 00:21:00,380\n然后继续\nOK? Go around this thing.\n\n405\n00:21:00,380 --> 00:21:01,312\n程序执行完了么？\nIs that done?\n\n406\n00:21:01,530 --> 00:21:02,128\n并没有\nNo.\n\n407\n00:21:02,360 --> 00:21:08,224\n现在 我需要求解30除以12的余数\nHow about-- so now I have to find out the remainder of 30 divided by 12.\n\n408\n00:21:08,850 --> 00:21:10,672\n我想答案是6\nAnd I believe that's 6.\n\n409\n00:21:12,420 --> 00:21:15,136\n按下这个钮 6就到了这里\nSo 6 goes here on this button push.\n\n410\n00:21:16,208 --> 00:21:18,256\n然后我又按下这个钮\nThen the next thing I push is this one,\n\n411\n00:21:18,304 --> 00:21:19,616\n这就让12来到了这里\nwhich the 12 goes into here.\n\n412\n00:21:23,730 --> 00:21:25,090\n然后我又按下这个按钮\nThen I push this button.\n\n413\n00:21:25,090 --> 00:21:26,000\n6就来到了这里\nThe 6 gets into here.\n\n414\n00:21:29,850 --> 00:21:31,680\n6等于0么？\nIs 6 equal to 0?\n\n415\n00:21:31,888 --> 00:21:32,496\n不等于\nNo.\n\n416\n00:21:33,420 --> 00:21:33,984\n好的\nOK.\n\n417\n00:21:34,380 --> 00:21:36,800\n因此这时\nSo then at that point,\n\n418\n00:21:36,890 --> 00:21:38,128\n接下来又要计算余数\nthe next thing to do is divide it.\n\n419\n00:21:38,144 --> 00:21:39,808\n哦 这个的余数是0\nOoh, this has got a remainder of 0.\n\n420\n00:21:40,660 --> 00:21:41,744\n看起来我们就快完成了\nLooks like we're almost done.\n\n421\n00:21:42,360 --> 00:21:44,360\n将6从这里挪到这里\nMove the 6 over here next.\n\n422\n00:21:47,008 --> 00:21:48,272\n0移动到这里\n0 over here.\n\n423\n00:21:49,090 --> 00:21:50,200\n0等于0么？\nIs the answer 0?\n\n424\n00:21:50,200 --> 00:21:50,736\n是的\nYes.\n\n425\n00:21:51,340 --> 00:21:53,360\nB的值等于0 因此答案就是A的值\nB is 0, therefore the answer is in A.\n\n426\n00:21:54,288 --> 00:21:55,760\n因此答案就是6\nThe answer is 6.\n\n427\n00:21:56,610 --> 00:21:57,616\n这确实是正确的答案\nAnd indeed that's right,\n\n428\n00:21:57,632 --> 00:21:59,472\n因为如果我们回过头审视最初的问题\nbecause if we look at the original problem,\n\n429\n00:22:00,080 --> 00:22:06,640\n我们知道30=2×3×5\nwhat we have is 30 is 2 times 3 times 5,\n\n430\n00:22:07,008 --> 00:22:11,120\n42=2×3×7\nand 42 is 2 times 3 times 7.\n\n431\n00:22:11,670 --> 00:22:14,112\n因此最大公约数就是2×3\nSo the greatest common divisor is 2 times 3,\n\n432\n00:22:14,208 --> 00:22:15,088\n也就是6\nwhich is 6.\n\n433\n00:22:18,380 --> 00:22:20,560\n我们通常在这里画另外一条线\nNow normally, we write one other little line here,\n\n434\n00:22:20,592 --> 00:22:22,528\n为了使它更清晰一点\njust to make it a little bit clearer,\n\n435\n00:22:22,896 --> 00:22:27,712\n在这两者之间建立了联系\nwhich is that we leave in a connection saying\n\n436\n00:22:27,856 --> 00:22:31,010\n小挡板需要根据这个指示灯来工作\nthat this light is the guy that that flap looks at.\n\n437\n00:22:34,000 --> 00:22:37,328\n当然 跟我给你们展示的东西相比\nOf course, any real machine has a lot more\n\n438\n00:22:37,856 --> 00:22:40,000\n真实计算机的组件更加复杂\ncomplicated things in it than what I've just shown you.\n\n439\n00:22:41,350 --> 00:22:47,168\n让我们来看看第一张幻灯片\nLet's look for a second at the first still store.\n\n440\n00:22:47,980 --> 00:22:48,816\n哇\nWow.\n\n441\n00:22:50,190 --> 00:22:52,432\n我们看到 我们想要做的就是\nWell you see, for example, one thing we might want to do\n\n442\n00:22:52,656 --> 00:22:55,856\nIO形式的操作\nis worry about the operations that are of IO form.\n\n443\n00:22:56,840 --> 00:23:01,424\n我们需要从外部搜集一些东西\nAnd we may have to collect something from the outside.\n\n444\n00:23:01,980 --> 00:23:03,936\n因此 对我们的状态机器来说\nSo a state machine that we might have,\n\n445\n00:23:04,300 --> 00:23:07,024\n它们的控制器\nthe controller may have to,\n\n446\n00:23:07,264 --> 00:23:10,560\n可能会从某处取得某值\nmay have to, for example, get a value from something\n\n447\n00:23:10,784 --> 00:23:12,416\n将它们放入寄存器并从中读取\nand put register a to load it up.\n\n448\n00:23:13,490 --> 00:23:15,920\n我还可以把另外的值加载到寄存器B中\nI have to master load up register b with another value.\n\n449\n00:23:17,070 --> 00:23:18,608\n稍后 当执行完毕后\nAnd then later, when I'm done,\n\n450\n00:23:18,992 --> 00:23:20,528\n我想要输出结果\nI might want to print the answer out.\n\n451\n00:23:21,200 --> 00:23:25,232\n当然 答案或简单或复杂\nAnd of course, that might be either simple or complicated.\n\n452\n00:23:26,090 --> 00:23:28,032\n我写代码的时候 总假设PRINT很简单\nI'm writing, assuming print is very simple,\n\n453\n00:23:28,096 --> 00:23:29,296\nREAD也很简单\nand read is very simple.\n\n454\n00:23:29,880 --> 00:23:31,088\n但实际上 在真实世界中\nBut in fact, in the real world,\n\n455\n00:23:31,120 --> 00:23:32,896\n这些都是非常复杂的操作\nthose are very complicated operations,\n\n456\n00:23:33,080 --> 00:23:35,520\n跟你尝试求解的问题相比\nfairly, usually much, much larger and more complicated\n\n457\n00:23:35,552 --> 00:23:38,330\n它们通常更加庞大而复杂\nthan the thing you're doing as your problem you're trying to solve.\n\n458\n00:23:41,670 --> 00:23:43,904\n另一方面 我犹记得\nOn the other hand, I can remember a time when,\n\n459\n00:23:44,896 --> 00:23:48,784\n使用IBM 7090一类的计算机的时候\nI remember using IBM 7090 computer of sorts,\n\n460\n00:23:49,056 --> 00:23:53,040\n它的READ和WRITE只能操作单个对象\nwhere things like read and write of a single object,\n\n461\n00:23:53,088 --> 00:23:54,624\n也就是一个数字\na single number, a number,\n\n462\n00:23:55,840 --> 00:23:58,544\n这就是一个基本的IO操作\nis a primitive operation of the IO controller.\n\n463\n00:23:59,632 --> 00:24:02,048\n我们这里有同样的操作\nOK? And so we have that kind of thing in there.\n\n464\n00:24:02,330 --> 00:24:04,672\n在这样的一台机器中\nAnd in such a machine,\n\n465\n00:24:05,440 --> 00:24:06,896\n我们实际上在做什么？\nwell, what are we really doing?\n\n466\n00:24:07,120 --> 00:24:11,600\n我们看到 这个叫做“READ”的组件是数据源头\nWe're just saying that there's a source over here called \"read\"\n\n467\n00:24:12,208 --> 00:24:14,464\n这个操作总是返回一个值\nwhich is an operation which always has a value.\n\n468\n00:24:14,660 --> 00:24:17,136\n我们可以把它看做 总是返回一个值\nWe have to think about this as always having a value\n\n469\n00:24:17,216 --> 00:24:19,840\n它可以赋给寄存器A或B\nwhich can be gated into either register a or b.\n\n470\n00:24:21,660 --> 00:24:23,232\n而PRINT这个过程呢\nAnd print is some sort of thing\n\n471\n00:24:23,376 --> 00:24:25,024\n当你正确连接它的时候\nwhich when you gate it appropriately,\n\n472\n00:24:25,248 --> 00:24:26,432\n当你按下上面的按钮\nwhen you push the button on it,\n\n473\n00:24:26,656 --> 00:24:29,616\n就会打印出当前寄存器A中的值\nwill cause a print of the value that's currently in register a.\n\n474\n00:24:31,660 --> 00:24:32,736\n这非常普通\nNothing very exciting.\n\n475\n00:24:33,328 --> 00:24:35,200\n这是我们想要的一种功能\nSo that's one sort of thing you might want to have.\n\n476\n00:24:35,888 --> 00:24:38,320\n但这里还有些其它事情需要我们担忧\nBut these are also other things that are a little bit worrisome.\n\n477\n00:24:38,320 --> 00:24:40,672\n比如说 这里我使用了一些复杂的机制\nLike I've used here some complicated mechanisms.\n\n478\n00:24:41,050 --> 00:24:42,480\n我们这里有REMAINDER组件\nWhat you see here is remainder.\n\n479\n00:24:43,850 --> 00:24:44,448\n这是个什么东西呢？\nWhat is that?\n\n480\n00:24:44,690 --> 00:24:46,416\n求取余数的计算过程并不是那么“显然”\nThat may not be so obvious how to compute.\n\n481\n00:24:46,920 --> 00:24:48,928\n如果我们把这个组件给拆开\nIt may be something which when you open it up,\n\n482\n00:24:49,488 --> 00:24:50,624\n就会得到一整台机器\nyou get a whole machine.\n\n483\n00:24:51,840 --> 00:24:53,664\n事实就是这样的\nOK? In fact, that's true.\n\n484\n00:24:54,540 --> 00:24:59,152\n举例来说 如果要编程实现REMAINDER\nFor example, if I write down the program for remainder,\n\n485\n00:24:59,440 --> 00:25:02,440\n最简单的算法就是 不断地做减法\nthe simplest program for it is by repeated subtraction.\n\n486\n00:25:04,780 --> 00:25:05,952\n这是因为 除法可以通过\nBecause of course, division can be done\n\n487\n00:25:05,968 --> 00:25:08,990\n对整数不断做减法来实现\nby repeated subtraction of numbers, of integers.\n\n488\n00:25:09,800 --> 00:25:23,584\nN除以D的余数不外乎就是\nSo the remainder of N divided by D\n\n489\n00:25:24,992 --> 00:25:31,440\n如果N小于D的话\nis nothing more than if N is less than D,\n\n490\n00:25:32,240 --> 00:25:33,664\n答案就是N\nthen the result is N.\n\n491\n00:25:34,304 --> 00:25:35,904\n否则的话就是\nOtherwise, it's the remainder\n\n492\n00:25:41,150 --> 00:25:47,600\nN先减去D\nwhen we subtract D from N with respect to D,\n\n493\n00:25:48,272 --> 00:25:49,328\n再除以D的余数\nwhen divided by D.\n\n494\n00:25:51,280 --> 00:25:55,056\n天啊 这个看起来就像是GCD程序\nGee, this looks just like the GCD program.\n\n495\n00:25:56,890 --> 00:25:59,488\n当然 这个不是求余数的最优算法\nOf course, it's not a very nice way to do remainders.\n\n496\n00:25:59,750 --> 00:26:00,912\n在实际中 你应该使用那些\nYou'd really want to use something like\n\n497\n00:26:00,920 --> 00:26:05,424\n二进制运算、移位运算等操作\nbinary notation and shift and things like that in a practical computer.\n\n498\n00:26:05,550 --> 00:26:06,976\n但关键点就是\nBut the point of that is\n\n499\n00:26:07,136 --> 00:26:08,480\n如果我把这些组件打开\nthat if I open this thing up,\n\n500\n00:26:08,928 --> 00:26:10,640\n我可能会发现其中有一台计算机\nI might find inside of it a computer.\n\n501\n00:26:11,880 --> 00:26:12,992\n现在我们就知道它的原理了\nOh, we know how to do that.\n\n502\n00:26:13,510 --> 00:26:14,336\n因为我们就造过一台\nWe just made one.\n\n503\n00:26:15,640 --> 00:26:17,104\n这些个机器都大同小异\nAnd it could be another thing just like this.\n\n504\n00:26:17,400 --> 00:26:18,064\n另外一方面\nOn the other hand,\n\n505\n00:26:18,080 --> 00:26:20,000\n我们可能想要构建一台更高效\nwe might want to make a more efficient\n\n506\n00:26:20,016 --> 00:26:21,680\n组织更精良的机器\nor better-structured machine,\n\n507\n00:26:21,850 --> 00:26:23,968\n比如说 多次利用其中的寄存器\nor maybe make use of some of the registers more than once,\n\n508\n00:26:24,000 --> 00:26:27,050\n或者是硬件设计者能想到的其它可怕混乱\nor some horrible mess like that that hardware designers like to do,\n\n509\n00:26:27,312 --> 00:26:28,608\n等等原因\nand for very good reasons.\n\n510\n00:26:29,250 --> 00:26:31,568\n比如说 你们所见的这台机器\nSo for example, here's a machine that you see,\n\n511\n00:26:32,528 --> 00:26:34,912\n不是让你们去细读它的结构的\nwhich you're not supposed to be able to read.\n\n512\n00:26:35,050 --> 00:26:37,520\n它有些复杂 对吧？\nIt's a little bit complicated. OK?\n\n513\n00:26:37,520 --> 00:26:39,872\n但它实际上是\nBut what it is is the integration of\n\n514\n00:26:40,096 --> 00:26:43,824\n整合了REMAINDER的GCD机器\nremainder into the GCD machine.\n\n515\n00:26:44,464 --> 00:26:46,020\n并且实际上 它没有多余的寄存器\nAnd it takes, in fact, no more registers.\n\n516\n00:26:46,020 --> 00:26:48,624\n数据通路上有三个寄存器\nThere are three registers in the datapaths. OK?\n\n517\n00:26:49,050 --> 00:26:50,640\n但现在 这里有个减法器\nBut now there's a subtractor.\n\n518\n00:26:51,550 --> 00:26:52,992\n又有两个东西被测试\nThere are two things that are tested.\n\n519\n00:26:53,020 --> 00:26:55,072\nB等于0么？\nIs b equal to 0,\n\n520\n00:26:55,232 --> 00:26:56,560\nT小于B么？\nor is t less than b?\n\n521\n00:26:57,250 --> 00:26:59,456\n而至于这一块的控制器\nAnd then the controller, which you see over here,\n\n522\n00:27:00,224 --> 00:27:01,760\n并不会更加复杂\nis not much more complicated.\n\n523\n00:27:01,850 --> 00:27:03,872\n它有两个循环\nBut it has two loops in it,\n\n524\n00:27:04,528 --> 00:27:08,336\n最主要的循环是计算GCD的\none of which is the main one for doing the GCD,\n\n525\n00:27:08,400 --> 00:27:10,144\n而另一条是减法循环\nand one of which is the subtraction loop\n\n526\n00:27:10,432 --> 00:27:12,800\n是用来计算余数的子操作\nfor doing the remainder sub-operation.\n\n527\n00:27:14,030 --> 00:27:15,808\n当然 还有一种思考方式\nAnd there are ways, of course, of,\n\n528\n00:27:15,968 --> 00:27:18,688\n就是把求余数程序\nif you think about it, taking the remainder program.\n\n529\n00:27:19,920 --> 00:27:21,712\n如果我把那边的REMAINDER机器\nIf I take remainder, as you see over there\n\n530\n00:27:21,728 --> 00:27:22,830\n当作LAMBDA表达式\nas a lambda expression,\n\n531\n00:27:23,568 --> 00:27:27,024\n代换到GCD程序的REMAINDER中\nsubstitute it in for remainder over here in the GCD program,\n\n532\n00:27:28,208 --> 00:27:30,128\n然后再做一些化简\nOK, then do some simplification\n\n533\n00:27:30,320 --> 00:27:33,664\n代换其中的A和B\nby substituting a and b for remainder in there,\n\n534\n00:27:34,464 --> 00:27:35,952\n那么 我就可以展开这个循环\nthen I can unwind this loop.\n\n535\n00:27:36,630 --> 00:27:39,424\n那么我就可以通过\nAnd I can get this piece of machinery\n\n536\n00:27:40,736 --> 00:27:42,944\nLAMBDA表达式的基本代数化简\nby basically, a little bit of simplification\n\n537\n00:27:43,360 --> 00:27:45,216\n来得到这台机器\nalgebraic simplification on the lambda expressions.\n\n538\n00:27:48,550 --> 00:27:51,200\n我想 你们已经见识了一个非常简单的机器了\nSo I suppose you've seen your first very simple machines now.\n\n539\n00:27:51,952 --> 00:27:53,280\n有什么疑问么？\nAre there any questions?\n\n540\n00:28:02,700 --> 00:28:03,104\n很好\nGood.\n\n541\n00:28:05,360 --> 00:28:06,544\n看起来很容易 难道不是吗？\nThis looks easy, doesn't it?\n\n542\n00:28:10,144 --> 00:28:11,328\n好吧 休息一下 谢谢大家\nThank you. I suppose, take a break.\n\n543\n00:28:12,540 --> 00:28:24,944\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n544\n00:28:25,136 --> 00:28:28,080\n《计算机程序的构造和解释》\n\n545\n00:28:31,370 --> 00:28:34,700\n《计算机程序的构造和解释》\n\n546\n00:28:34,768 --> 00:28:38,000\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n547\n00:28:38,000 --> 00:28:43,296\n寄存机器\n\n548\n00:28:47,936 --> 00:28:48,704\n教授：好吧\nPROFESSOR: Well, let's see.\n\n549\n00:28:49,376 --> 00:28:52,464\n现在 你们已经知道如何去把迭代过程\nNow you know how to make an iterative procedure,\n\n550\n00:28:52,544 --> 00:28:54,544\n或者是产生迭代计算的过程\nor a procedure that yields an iterative process,\n\n551\n00:28:55,184 --> 00:28:56,528\n变成一台机器\nturn into a machine.\n\n552\n00:28:57,770 --> 00:29:00,048\n我想 接下来我们就应该考虑\nI suppose the next thing we want to do is worry about things\n\n553\n00:29:00,544 --> 00:29:02,304\n如何来处理递归过程了\nthat reveal recursive processes.\n\n554\n00:29:02,816 --> 00:29:05,056\n我们先从一个简单的阶乘过程开始\nSo let's play with a simple factorial procedure.\n\n555\n00:29:11,200 --> 00:29:16,944\n(DEFINE (FACT N)\nWe define factorial of N to be\n\n556\n00:29:19,632 --> 00:29:24,256\n如果N=1 那么结果就是1\nif n is 1, the result is 1,\n\n557\n00:29:24,624 --> 00:29:27,696\n为了减少模拟它的工作量 我就使用1\nusing 1 right now to decrease the amount of work I have to do to simulate it,\n\n558\n00:29:28,128 --> 00:29:33,940\n否则结果就是(* N (FACT (- N 1)))\nelse it's times N factorial N minus 1.\n\n559\n00:29:42,520 --> 00:29:46,048\n正如你们所知 这个程序的不同之处在于\nAnd what's different with this program, as you know,\n\n560\n00:29:46,656 --> 00:29:50,368\n这里 我在计算(FACT (- N 1))之后\nis that after I've computed factorial of N minus 1 here,\n\n561\n00:29:50,672 --> 00:29:52,260\n我要对结果做一些运算\nI have to do something to the result.\n\n562\n00:29:52,260 --> 00:29:53,680\n我要将它与N相乘\nI have to multiply it by N.\n\n563\n00:29:56,000 --> 00:30:00,672\n将这台机器可视化的唯一途径就是\nSo the only way I can visualize what this machine is doing,\n\n564\n00:30:01,088 --> 00:30:02,016\n首先 由于--\nbecause of the fact--\n\n565\n00:30:02,352 --> 00:30:03,184\n请你们这么来想\nthink of it this way,\n\n566\n00:30:03,360 --> 00:30:04,944\n这里 我有一台机器\nthat I have a machine out here\n\n567\n00:30:05,088 --> 00:30:08,112\n而这台机器又需要某个阶乘机器来计算结果\nwhich somehow needs a factorial machine in order to compute its answer.\n\n568\n00:30:09,320 --> 00:30:11,168\n但外面的这台机器\nBut this machine, the outer machine,\n\n569\n00:30:11,200 --> 00:30:13,024\n又需要在调用内部阶乘机器\nhas to exist before and after\n\n570\n00:30:13,920 --> 00:30:15,720\n的前后都要存在\nthe factorial machine, which is inside.\n\n571\n00:30:16,800 --> 00:30:17,904\n然而在迭代情况中\nWhereas in the iterative case,\n\n572\n00:30:18,752 --> 00:30:20,528\n外面的机器不需要\nthe outer machine doesn't need to exist\n\n573\n00:30:20,912 --> 00:30:24,016\n在内部机器运行后保持存在\nafter the inner machine is running,\n\n574\n00:30:24,830 --> 00:30:26,160\n这是因为你不需要回到\nbecause you never need to go back\n\n575\n00:30:26,192 --> 00:30:27,530\n外部机器来进行其它操作\nto the outer machine to do anything.\n\n576\n00:30:28,640 --> 00:30:30,064\n因此 我们这里的问题是\nSo here we have a problem\n\n577\n00:30:30,270 --> 00:30:30,976\n我们的机器内部\nwhere we have a machine\n\n578\n00:30:31,008 --> 00:30:32,730\n有一个同样的机器\nwhich has the same machine inside of it,\n\n579\n00:30:33,872 --> 00:30:35,520\n一台无穷大的机器\nan infinitely large machine.\n\n580\n00:30:40,390 --> 00:30:43,120\n这里面也有其它的东西 比如乘法器\nAnd it's got other things inside of it, like a multiplier,\n\n581\n00:30:44,768 --> 00:30:46,032\n它接收输入\nwhich takes some inputs,\n\n582\n00:30:46,272 --> 00:30:47,776\n这是-1操作\nand there's a minus 1 box,\n\n583\n00:30:48,128 --> 00:30:49,312\n等等\nand things like that.\n\n584\n00:30:50,690 --> 00:30:53,728\n你们可以想象 -- 它就是这个样子的\nYou know, You can imagine that's what it looks like.\n\n585\n00:30:54,370 --> 00:30:56,768\n但重要之处就在于\nBut the important thing is that here I have\n\n586\n00:30:57,020 --> 00:30:58,704\n内部机器执行之前与执行之后\nsomething that happens before and after,\n\n587\n00:30:58,784 --> 00:31:01,600\n外部机器中都进行了一些运算\nin the outer machine, the execution of the inner machine.\n\n588\n00:31:02,540 --> 00:31:04,080\n因此这台机器必须有“生命”\nSo this machine has to have a life.\n\n589\n00:31:05,472 --> 00:31:11,440\n外部机器需要在内部机器的两个时间点保持存在\nIt has to exist on both times sides of this machine.\n\n590\n00:31:13,490 --> 00:31:15,808\n因此 我就需要有一个地方来保存\nSo somehow, I have to have a place to store\n\n591\n00:31:16,192 --> 00:31:18,192\n维持外部机器运转的数据\nthe things that this thing needs to run.\n\n592\n00:31:20,030 --> 00:31:22,096\n现实世界中不存在无穷的对象\nInfinite objects don't exist in the real world.\n\n593\n00:31:24,140 --> 00:31:25,584\n我们要做的就是营造一种假象\nWhat we have to do is arrange an illusion\n\n594\n00:31:26,128 --> 00:31:27,488\n一种无穷对象的假象\nthat we have an infinite object,\n\n595\n00:31:27,984 --> 00:31:29,776\n我们在某处有无穷的硬件资源\nwe have an infinite amount of hardware somewhere.\n\n596\n00:31:31,830 --> 00:31:35,344\n现在 这个假象非常重要\nNow of course, illusion's all that really matters.\n\n597\n00:31:36,280 --> 00:31:37,376\n如果我们能保证\nIf we can arrange\n\n598\n00:31:38,000 --> 00:31:39,840\n每次当你查看某个无穷对象时\nthat every time you look at some infinite object,\n\n599\n00:31:39,880 --> 00:31:42,960\n你所要观察的那部分存在\nthe part of it that you look at is there,\n\n600\n00:31:44,496 --> 00:31:46,040\n那么就不需要实际上的“无穷”\nthen it's as infinite as you need it to be.\n\n601\n00:31:47,390 --> 00:31:49,440\n当然 这里面我们想做的就是\nAnd of course, one of the things we might want to do,\n\n602\n00:31:49,824 --> 00:31:52,496\n来看下这里的东西\njust look at this thing over here,\n\n603\n00:31:53,008 --> 00:31:54,976\n这是我们目前为止的结构\nis the organization that we've had so far\n\n604\n00:31:56,048 --> 00:31:57,648\n这些结构呢\norganization that we've had so far\n\n605\n00:31:57,920 --> 00:32:01,376\n是机器的几大部分\ninvolves having a part of the machine,\n\n606\n00:32:01,408 --> 00:32:02,336\n比如控制器\nwhich is the controller,\n\n607\n00:32:03,184 --> 00:32:04,464\n它在这里\nwhich sits right over here,\n\n608\n00:32:04,784 --> 00:32:07,616\n它相当简单 并且是有穷的\nwhich is perfectly finite and very simple.\n\n609\n00:32:09,170 --> 00:32:10,448\n我们还有数据通路\nWe have some datapaths,\n\n610\n00:32:10,464 --> 00:32:12,752\n它由寄存器和运算器组成\nwhich consist of registers and operators.\n\n611\n00:32:13,080 --> 00:32:15,200\n现在我提议\nAnd what I propose to do here is decompose\n\n612\n00:32:15,488 --> 00:32:16,960\n把机器分成两部分\nthe machine into two parts,\n\n613\n00:32:17,360 --> 00:32:19,792\n这样 其中一部分全部是有穷的\nsuch that there is a part which is fundamentally finite,\n\n614\n00:32:20,784 --> 00:32:23,536\n而另一部分 可以保存无穷数据中的一部分\nand some part where a certain amount of infinite stuff can be kept.\n\n615\n00:32:24,230 --> 00:32:25,904\n换句话说 这部分也非常简单\nOn the other hand this is very simple\n\n616\n00:32:26,416 --> 00:32:28,720\n但并非无穷 只是非常大而已\nand really isn't infinite, but it's just very large.\n\n617\n00:32:29,430 --> 00:32:30,400\n但它非常简单\nBut it's so simple\n\n618\n00:32:30,528 --> 00:32:32,928\n以至于能够廉价地大量生产\nthat it could be cheaply reproduced in such large amounts,\n\n619\n00:32:34,096 --> 00:32:34,928\n它就是内存\nwe call it memory,\n\n620\n00:32:35,952 --> 00:32:39,072\n我们可以利用它来构造栈结构\nOK? that we can make a structure called a stack out of it\n\n621\n00:32:39,408 --> 00:32:41,232\n事实上 这就使得我们\nwhich will allow us to, in fact,\n\n622\n00:32:41,450 --> 00:32:43,632\n能够模拟无穷机器的存在\nsimulate the existence of an infinite machine\n\n623\n00:32:43,648 --> 00:32:46,960\n也就是那些递归嵌套的机器\nwhich is made out of a recursive nest of many machines.\n\n624\n00:32:48,340 --> 00:32:50,432\n而它的原理则是\nAnd the way it's going to work is that\n\n625\n00:32:50,560 --> 00:32:52,976\n我们要在栈上存放必要的信息\nwe're going to store in this place called the stack\n\n626\n00:32:54,304 --> 00:32:57,584\n用于内部机器执行完毕后\nthe information required after the inner machine runs\n\n627\n00:32:59,184 --> 00:33:01,072\n继续外部机器的操作\nto resume the operation of the outer machine.\n\n628\n00:33:03,840 --> 00:33:05,488\n因此它会记住\nSo it will remember\n\n629\n00:33:05,632 --> 00:33:07,952\n关于外部机器生命期的重要数据\nthe important things about the life of the outer machine\n\n630\n00:33:08,048 --> 00:33:10,304\n这些是进行计算所必需的\nthat will be needed for this computation.\n\n631\n00:33:11,390 --> 00:33:12,480\n当然\nSince, of course,\n\n632\n00:33:12,752 --> 00:33:16,336\n由于这些机器是通过递归的方式嵌套的\nthese machines are nested in a recursive manner,\n\n633\n00:33:18,330 --> 00:33:23,392\n因此 栈的存取方式也会是\nthen in fact the stack will only be accessed in a manner\n\n634\n00:33:23,456 --> 00:33:26,440\n也会是后进先出的\nwhich is the last thing that goes in is the first thing that comes out.\n\n635\n00:33:29,330 --> 00:33:30,640\n因此我们只需要存取\nSo we'll only need to access\n\n636\n00:33:30,800 --> 00:33:32,528\n这个栈内存的一小部分\nsome little part of this stack memory.\n\n637\n00:33:34,930 --> 00:33:35,920\n好吧 让我们来试一试\nOK, well, let's do it.\n\n638\n00:33:36,810 --> 00:33:38,416\n我已经给你们画好了数据通路\nI'm going to build you a datapath now,\n\n639\n00:33:38,448 --> 00:33:39,680\n现在该布置控制器了\nand I'm going to write the controller.\n\n640\n00:33:40,370 --> 00:33:42,864\n然后我们来运行一下 观察实际工作原理\nAnd then we're going to execute this to see how you do it.\n\n641\n00:33:43,510 --> 00:33:46,880\n还好阶乘机器不是特别的复杂\nSo the factorial machine isn't so bad.\n\n642\n00:33:47,900 --> 00:33:50,160\n它有一个VAL寄存器\nIt's going to have a register called the value,\n\n643\n00:33:52,224 --> 00:33:53,888\n这是用来存储答案的\nwhere the answer is going to be stored,\n\n644\n00:33:54,896 --> 00:33:56,672\n还有一个寄存器N\nand a registered called N,\n\n645\n00:33:59,856 --> 00:34:04,160\n它里面存储的是要计算阶乘的数\nwhich is where the number I'm taking factorial will be stored, factorial of.\n\n646\n00:34:04,510 --> 00:34:06,576\n为了满足某些情况\nAnd it will be necessary in some instances\n\n647\n00:34:07,488 --> 00:34:10,520\n我们要连接VAL和N\nto connect VAL to N.\n\n648\n00:34:11,744 --> 00:34:15,630\n事实上 如果我在这里返回N\nIn fact, one nice case of this is if I just said over here,\n\n649\n00:34:16,380 --> 00:34:19,536\n也是正确的 因为这时N就等于1\nN, because that would be right for N equal 1N.\n\n650\n00:34:20,090 --> 00:34:23,264\n这样的话 我就可以把结果移动过去\nAnd I could just move the answer over there if that's important.\n\n651\n00:34:23,900 --> 00:34:25,552\n但我现在不考虑这个问题\nI'm not worried about that right now.\n\n652\n00:34:26,980 --> 00:34:28,608\n我还需要做一些事情\nAnd there are things I have to be able to do.\n\n653\n00:34:29,060 --> 00:34:31,024\n就像我们在这里看到的 我们还需要\nLike I have to be able to, as we see here,\n\n654\n00:34:31,216 --> 00:34:34,672\n用VAL的值乘以N\nmultiply N by something in VAL,\n\n655\n00:34:34,912 --> 00:34:37,456\n因为VAL是计算阶乘的结果\nbecause VAL is the result of computing factorial.\n\n656\n00:34:38,688 --> 00:34:40,448\n我需要把算得的结果送回VAL\nAnd I have to put the result back into VAL.\n\n657\n00:34:41,488 --> 00:34:42,656\n所以这里我们看到\nSo here we can see\n\n658\n00:34:42,832 --> 00:34:46,432\nN的阶乘就是\nthat the result of computing a factorial\n\n659\n00:34:46,576 --> 00:34:49,200\nN乘以某个阶乘\nis N times the result of computing a factorial.\n\n660\n00:34:50,690 --> 00:34:53,776\n而VAL就代表了内部阶乘的结果\nVAL will be the representation of the answer of the inner factorial.\n\n661\n00:34:55,190 --> 00:35:00,256\n因此 在这里我需要有一个乘法器\nAnd so I'm going to have to have a multiplier here,\n\n662\n00:35:02,360 --> 00:35:07,184\n它的参数有：N以及VAL\nwhich is going to sample the value of N and the value of VAL\n\n663\n00:35:08,640 --> 00:35:15,600\n并且 像这样把计算结果送回VAL\nOK? and put the result back into VAL like that.\n\n664\n00:35:17,170 --> 00:35:19,392\n我也需要知道N是否为1\nI'm also going to have to be able to see if N is 1.\n\n665\n00:35:21,328 --> 00:35:22,384\n因此我需要一个指示灯\nSo I need a light bulb.\n\n666\n00:35:28,200 --> 00:35:30,400\n另外 我想我还需要\nAnd I suppose the other thing I'm going to need to have\n\n667\n00:35:31,024 --> 00:35:32,848\n一个组件来减小N\nis a way of decrementing N.\n\n668\n00:35:34,848 --> 00:35:36,096\n所以这里有一个递减器\nSo I'm going to have a decrementer,\n\n669\n00:35:38,192 --> 00:35:41,390\n它接收参数N 将结果送回N\nwhich takes N and is going to put back the result into N.\n\n670\n00:35:46,620 --> 00:35:48,400\n这基本上就是我的机器所需要的东西了\nThat's pretty much what I need in my machine.\n\n671\n00:35:49,550 --> 00:35:51,648\n然而 我还需要一些个东西\nNow, there's a little bit else I need.\n\n672\n00:35:52,304 --> 00:35:53,584\n一个稍微复杂一点的东西\nIt's a little bit more complicated,\n\n673\n00:35:55,168 --> 00:35:56,880\n因为我需要有一种方式能够存储\nbecause I'm also going to need a way to store,\n\n674\n00:35:57,168 --> 00:35:59,696\n必要的一些信息\nto save away, the things that are going to be needed\n\n675\n00:36:01,020 --> 00:36:03,072\n以便计算完子阶乘后\nfor resuming the computation of a factorial\n\n676\n00:36:03,104 --> 00:36:04,896\n恢复原始阶乘的计算\nafter I've done a sub-factorial.\n\n677\n00:36:06,250 --> 00:36:06,864\n需要哪些信息呢?\nWhat's that?\n\n678\n00:36:07,230 --> 00:36:08,736\n首先就是N\nOne thing I need is N.\n\n679\n00:36:09,850 --> 00:36:12,048\n因此 我要在这里构造一个栈\nSo I'm going to build here a thing called a stack.\n\n680\n00:36:14,700 --> 00:36:15,776\n所谓的栈就是\nThe stack is\n\n681\n00:36:17,984 --> 00:36:24,976\n一大堆连续的空间\na bunch of stuff that I'm going to write in sequentially.\n\n682\n00:36:27,152 --> 00:36:28,592\n我不知道它到底有多深\nI don't know how long it is.\n\n683\n00:36:29,152 --> 00:36:31,488\n栈越深 无穷的假象营造得就越好\nThe longer it is, the better my illusion of infinity.\n\n684\n00:36:33,230 --> 00:36:35,568\n我还需要有一种方法 能够把\nAnd I'm going to have to have a way of getting stuff\n\n685\n00:36:35,600 --> 00:36:37,020\nN中的值放入栈中\nout of N and into the stack\n\n686\n00:36:38,128 --> 00:36:39,088\n反过来也是\nand vice versa.\n\n687\n00:36:39,936 --> 00:36:41,744\n因此我需要一条像这样的连接\nSo I'm going to need a connection like this,\n\n688\n00:36:44,416 --> 00:36:45,488\n它是双向的\nwhich is two-way,\n\n689\n00:36:50,448 --> 00:36:52,224\n通过它 我就可以在某个时间\nwhereby I can save the value of N\n\n690\n00:36:52,240 --> 00:36:55,504\n把N的值存储起来\nand then restore it some other time through that connection.\n\n691\n00:36:56,048 --> 00:36:56,848\n这就是栈\nThis is the stack.\n\n692\n00:36:58,100 --> 00:37:01,712\n我还需要一种方法来记住\nI also need a way of remembering\n\n693\n00:37:01,840 --> 00:37:07,728\n我现在计算到外部程序的哪个地方了\nwhere I was in the computation of factorial in the outer program.\n\n694\n00:37:08,530 --> 00:37:10,064\n现在 对于这台机器来说\nNow in the case of this machine,\n\n695\n00:37:10,768 --> 00:37:13,344\n这并不是什么问题\nit isn't very much a problem.\n\n696\n00:37:14,176 --> 00:37:16,240\nFACT总是返回在\nFactorial always returns,\n\n697\n00:37:16,864 --> 00:37:19,072\n一个跟N相乘的地方\nhas to go back to the place where we multiply by N,\n\n698\n00:37:19,344 --> 00:37:20,720\n除了最后的一次\nexcept for the last time,\n\n699\n00:37:21,150 --> 00:37:23,024\n它返回到需要FACT最终答案的地方\nwhen it has to return to whatever needs the factorial\n\n700\n00:37:23,040 --> 00:37:24,040\n或者是'DONE、'STOP之类的\nor go to done or stop.\n\n701\n00:37:25,660 --> 00:37:26,672\n然而 通常来说\nHowever, in general,\n\n702\n00:37:27,168 --> 00:37:28,736\n我需要记住我去过哪些地方\nI'm going to have to remember where I have been,\n\n703\n00:37:29,136 --> 00:37:31,248\n因为 我可能从其它地方调用FACT\nbecause I might have computed factorial from somewhere else.\n\n704\n00:37:32,080 --> 00:37:34,896\n我需要返回到那个地方 并从那里继续\nI have to go back to that place and continue there.\n\n705\n00:37:36,070 --> 00:37:38,000\n因此 我需要有一种方法能够\nSo I'm going to have to have some way of taking the place\n\n706\n00:37:38,016 --> 00:37:40,864\n记住有穷状态控制器中弹珠的位置\nwhere the marble is in the finite state controller,\n\n707\n00:37:41,328 --> 00:37:42,640\n也就是控制器的状态\nthe state of the controller,\n\n708\n00:37:44,224 --> 00:37:46,352\n并将它存储在栈中\nand storing that in the stack as well.\n\n709\n00:37:47,400 --> 00:37:49,104\n我也需要有一种方法\nAnd I'm going to have to have ways of restoring that\n\n710\n00:37:49,456 --> 00:37:51,120\n能够恢复弹珠的状态\nback to the state of the-- the marble.\n\n711\n00:37:52,144 --> 00:37:54,288\n因此 我需要有一种将弹珠归位的能力\nSo I have to have something that moves the marble to the right place.\n\n712\n00:37:54,704 --> 00:37:56,528\n现在 我们有一个地方用于存储弹珠\nWell, we're going to have a place which is the marble now.\n\n713\n00:37:57,872 --> 00:37:59,344\n它被称作“继续”寄存器\nAnd it's called the continue register,\n\n714\n00:38:03,616 --> 00:38:04,528\n记作CONTINUE\ncalled continue,\n\n715\n00:38:09,160 --> 00:38:10,688\n下一次调用(GOTO CONTINUE)时\nwhich is the place to put the marble\n\n716\n00:38:11,008 --> 00:38:13,050\n弹珠就会去向这个地方\nnext time I go to continue.\n\n717\n00:38:14,912 --> 00:38:15,920\n它就是用来干这个的\nThat's what that's for.\n\n718\n00:38:16,140 --> 00:38:18,480\n因此 它和控制器之间应该有一条通路\nAnd so there's got to be some path from that into the controller.\n\n719\n00:38:22,910 --> 00:38:27,120\n我也能够将它存储在栈上\nI also have to have some way of saving that on the stack.\n\n720\n00:38:29,450 --> 00:38:33,104\n我也能够把它设置成各种常量\nAnd I have to have some way of setting that up to have various constants,\n\n721\n00:38:34,016 --> 00:38:35,696\n某一些常量\na certain fixed number of constants.\n\n722\n00:38:36,860 --> 00:38:38,208\n这非常容易实现\nAnd that's very easy to arrange.\n\n723\n00:38:38,840 --> 00:38:40,144\n我们现在这里设一些常量\nSo let's have some constants here.\n\n724\n00:38:40,180 --> 00:38:41,504\n我们把这个记作AFTER-FACT\nWe'll call this one after-fact.\n\n725\n00:38:47,328 --> 00:38:48,752\n这个常量\nAnd that's a constant\n\n726\n00:38:48,848 --> 00:38:51,504\n会送入CONTINUE寄存器\nwhich will get into the continue register,\n\n727\n00:38:52,592 --> 00:38:54,432\n另外一个寄存器是FACT-DONE\nand also another one called fact-done.\n\n728\n00:39:05,210 --> 00:39:07,824\n这就是我想要构建的机器\nSo this is the machine I want to build.\n\n729\n00:39:08,130 --> 00:39:09,488\n至少是数据通路部分\nThat's its datapaths, at least.\n\n730\n00:39:09,920 --> 00:39:11,696\n这里还混合了一些控制器\nAnd it mixes a little with the controller here,\n\n731\n00:39:11,856 --> 00:39:14,592\n这是因为我需要记住我当前的位置\nbecause of the fact that I have to remember where I was\n\n732\n00:39:14,704 --> 00:39:16,352\n并将我恢复到该位置\nand restore myself to that place.\n\n733\n00:39:17,300 --> 00:39:19,936\n现在 让我们来编写控制器对应的程序\nBut let's write the program now which represents the controller.\n\n734\n00:39:20,390 --> 00:39:23,472\n我就把DEFINE-MACHINE和寄存器列表给省略了\nI'm not going to write the define machine thing and the register list,\n\n735\n00:39:23,488 --> 00:39:24,890\n因为它们无关紧要\nbecause that's not very interesting.\n\n736\n00:39:25,130 --> 00:39:27,792\n我就直接写那些跟控制器有关的\nI'm just going to write down the sequence of instructions\n\n737\n00:39:27,824 --> 00:39:29,020\n指令序列\nthat constitute the controller.\n\n738\n00:39:31,488 --> 00:39:41,856\n首先是(ASSIGN CONTINUE DONE)\nSo we have assign, to set up, continue to done.\n\n739\n00:39:45,150 --> 00:39:45,824\n然后是一个循环\nWe have a loop\n\n740\n00:39:47,344 --> 00:39:56,080\n先判断 如果1=N 那么就跳转\nwhich says branch if equal 1 fetch N,\n\n741\n00:40:00,944 --> 00:40:04,112\n那么就进入归纳的基本步骤\nif N is 1, then go to the base step of the induction,\n\n742\n00:40:06,064 --> 00:40:07,200\n也就是最简单的情况\nthe simple case.\n\n743\n00:40:08,050 --> 00:40:08,768\n否则的话\nOtherwise,\n\n744\n00:40:08,880 --> 00:40:10,848\n我就要记住那些\nI have to remember the things that are necessary\n\n745\n00:40:10,880 --> 00:40:13,840\n计算子阶乘所必须的信息\nto perform a sub-factorial.\n\n746\n00:40:14,672 --> 00:40:16,752\n我需要来带这里 以便计算子阶乘\nI'm going to go over here, and I have to perform a sub-factorial.\n\n747\n00:40:17,570 --> 00:40:19,296\n所以我需要记住 完成它需要些什么\nSo I have to remember what's needed to do that\n\n748\n00:40:19,712 --> 00:40:22,528\n需要记住我计算完之后需要哪些东西\nremember what's needed after I will be done with that.\n\n749\n00:40:24,000 --> 00:40:25,510\n看到了吗 我要做些糟糕的事儿\nSee, I'm about to do something terrible.\n\n750\n00:40:25,728 --> 00:40:27,392\n我要去修改N的值\nI'm about to change the value of N.\n\n751\n00:40:28,576 --> 00:40:30,400\n但是它又需要记住N的旧值\nBut this guy has to know the old value of N.\n\n752\n00:40:32,140 --> 00:40:33,648\n但是为了计算子阶乘\nBut in order to make the sub-factorial work,\n\n753\n00:40:33,664 --> 00:40:34,920\n我又需要修改N的值\nI have to change the value of N.\n\n754\n00:40:35,600 --> 00:40:37,104\n因此 我就得记住N的旧值\nSo I have to remember the old value.\n\n755\n00:40:38,000 --> 00:40:39,600\n我也需要记住我的位置\nAnd I also have to remember where I've been.\n\n756\n00:40:40,850 --> 00:40:42,320\n因此 我保存CONTINUE的值\nSo I save up continue.\n\n757\n00:40:47,700 --> 00:40:51,296\n这条指令 就是用来将数据入栈的\nAnd this is an instruction that says, put something in the stack.\n\n758\n00:40:53,120 --> 00:40:55,536\n将CONTINUE寄存器的值保存起来\nSave the contents of the continuation register,\n\n759\n00:40:56,512 --> 00:40:58,000\n在本例中也就是DONE\nwhich in this case is done,\n\n760\n00:40:58,880 --> 00:41:00,256\n因为稍后我也会修改它\nbecause later I'm going to change that, too,\n\n761\n00:41:00,272 --> 00:41:02,780\n因为我也需要回到AFTER-FACT\nbecause I need to go back to after-fact, as well.\n\n762\n00:41:03,550 --> 00:41:04,192\n我们来看看\nWe'll see that.\n\n763\n00:41:05,040 --> 00:41:09,712\n我们需要存储N 因为稍后会用到\nWe save N, because I'm going to need that for later.\n\n764\n00:41:10,380 --> 00:41:20,544\n(ASSIGN N (-1+ (FETCH N)))\nAssign to N the decrement of fetch N.\n\n765\n00:41:23,264 --> 00:41:28,976\n(ASSIGN CONTINUE ...\nAssign continue,\n\n766\n00:41:32,128 --> 00:41:33,424\n我看一下 --\nwe're going to look at this now,\n\n767\n00:41:34,064 --> 00:41:35,616\nAFT)\nto after, we'll call it.\n\n768\n00:41:37,690 --> 00:41:38,704\n这个名字很好\nThat's a good name for this,\n\n769\n00:41:38,736 --> 00:41:40,656\n因为它短小精炼 很适合用在这里\na little bit easier and shorter, and fits in here.\n\n770\n00:41:53,360 --> 00:41:54,640\n现在 来看看我怎么做\nNow look what I'm doing here.\n\n771\n00:41:55,330 --> 00:41:57,020\n我说 如果ANSWER是1的话\nI'm saying, if the answer is 1,\n\n772\n00:41:58,720 --> 00:41:59,664\n那程序就结束了\nOK, I'm done.\n\n773\n00:42:00,464 --> 00:42:01,664\n我只需要取得这个答案\nI'm going to have to just get the answer.\n\n774\n00:42:02,150 --> 00:42:04,880\n否则我就要保存当前的继续以及N的值\nOtherwise, I'm going to save the continuation, save N,\n\n775\n00:42:05,776 --> 00:42:07,328\n然后让N减1\nmake N one less than N,\n\n776\n00:42:07,600 --> 00:42:09,632\n注意 我先要跳转到某处\nremember I'm going to come back to someplace else,\n\n777\n00:42:09,648 --> 00:42:11,488\n然后来到这里 计算另外的阶乘\nand go back and start doing another factorial.\n\n778\n00:42:13,504 --> 00:42:15,744\n然而 这之中又有了另外的机器\nOK? However, I've got a different machine in me now.\n\n779\n00:42:16,050 --> 00:42:18,380\n其中N=1 CONTINUE是其它值\nN is 1, and continue is something else.\n\n780\n00:42:22,112 --> 00:42:23,216\nN=N-1\nN is N minus 1.\n\n781\n00:42:23,770 --> 00:42:25,280\n再我完成这个之后\nNow after I'm done with that,\n\n782\n00:42:26,944 --> 00:42:27,760\n我会来到这里\nI can go there.\n\n783\n00:42:28,660 --> 00:42:30,464\n我会恢复N的旧值\nI will restore the old value of N,\n\n784\n00:42:32,688 --> 00:42:36,560\n也就是这里SAVE的逆运算\nwhich is the opposite of this save over here.\n\n785\n00:42:38,360 --> 00:42:39,888\n然后恢复CONTINUE\nI will restore the continuation.\n\n786\n00:42:49,660 --> 00:42:52,576\n然后我又会来到这里\nI will then go to here.\n\n787\n00:42:54,320 --> 00:43:00,864\n(ASSIGN VAL\nI will assign to the VAL register\n\n788\n00:43:01,168 --> 00:43:08,130\n(* (FETCH N) (FETCH VAL)))\nthe product of N and fetch VAL.\n\n789\n00:43:13,440 --> 00:43:18,304\n（闭合括号中）\nVAL fetch product assign.\n\n790\n00:43:19,790 --> 00:43:21,440\n这样操作就完成了\nAnd then I will be done.\n\n791\n00:43:21,440 --> 00:43:25,680\n子阶乘的结果就存储在了VAL中\nI will have my answer to the sub-factorial in VAL.\n\n792\n00:43:26,570 --> 00:43:27,376\n这个时候\nAt that point,\n\n793\n00:43:27,660 --> 00:43:28,752\n我就要返回到\nI'm going to return\n\n794\n00:43:29,280 --> 00:43:31,610\nCONTINUE所指向的地方\nby going to the place where the continuation is pointing.\n\n795\n00:43:33,640 --> 00:43:35,776\n也就是(GOTO (FETCH CONTINUE))\nThat says, go to fetch continue.\n\n796\n00:43:45,870 --> 00:43:47,408\n最后就是基本情况的那步\nAnd then I have finally a base step,\n\n797\n00:43:49,312 --> 00:43:50,512\n也就是一个立即值\nwhich is the immediate answer.\n\n798\n00:43:50,680 --> 00:43:56,880\n(ASSIGN VAL (FETCH N))\nAssign to VAL fetch N,\n\n799\n00:44:01,360 --> 00:44:02,752\n(GOTO (FETCH CONTINUE))\nand go to fetch continue.\n\n800\n00:44:12,670 --> 00:44:13,552\n这样我就完成了\nAnd then I'm done.\n\n801\n00:44:18,640 --> 00:44:21,216\n现在 我们用一个非常简单的例子来运行一下\nNow let's see how this executes on a very simple case,\n\n802\n00:44:22,512 --> 00:44:23,536\n因为这样我们就将看到\nbecause then we'll see\n\n803\n00:44:23,664 --> 00:44:26,528\n栈是如何帮助我们完成计算的\nthe use of this stack to do the job we need.\n\n804\n00:44:26,890 --> 00:44:28,224\n这是计算的静态描述\nThis is statically what it's doing,\n\n805\n00:44:28,224 --> 00:44:29,800\n我们需要动态地观察它\nbut we have look dynamically at this.\n\n806\n00:44:31,340 --> 00:44:32,096\n因此 让我们来看看\nSo let's see.\n\n807\n00:44:32,300 --> 00:44:34,560\n首先我们要把CONTINUE设置为DONE\nFirst thing we do is continue gets done.\n\n808\n00:44:36,730 --> 00:44:38,096\n这是我通过按下这个钮来实现的\nThe way that happened is I pushed this.\n\n809\n00:44:38,300 --> 00:44:39,600\n我们还是把它记作DONE吧\nLet's call that done the way I have it.\n\n810\n00:44:46,224 --> 00:44:47,030\n我按下这个按钮\nI push that button.\n\n811\n00:44:47,030 --> 00:44:48,112\nDONE就进到了这里\nDone goes into there.\n\n812\n00:44:48,950 --> 00:44:53,712\n现在 我还要为这些东西设置初始值\nNow I also have to set this thing up to have an initial value.\n\n813\n00:44:53,850 --> 00:44:58,080\n让我们考虑3的阶乘\nLet's consider a factorial of three,\n\n814\n00:44:58,384 --> 00:44:59,248\n这个例子非常简单\na simple case.\n\n815\n00:45:00,544 --> 00:45:04,048\n我们的栈从这里开始增长\nAnd we're going to start out with our stack growing over here.\n\n816\n00:45:05,900 --> 00:45:07,760\n栈有它们自己的内部状态\nStacks have their own little internal state\n\n817\n00:45:07,792 --> 00:45:09,056\n用来标识栈顶位置\nsaying where they are,\n\n818\n00:45:09,808 --> 00:45:11,648\n也就是下一个可写位置\nwhere the next place I'm going to write is.\n\n819\n00:45:12,770 --> 00:45:14,590\n现在我们问 N=1么？\nSo now we say, is N 1?\n\n820\n00:45:14,768 --> 00:45:15,712\n当然不等于\nThe answer is no.\n\n821\n00:45:16,110 --> 00:45:18,560\n因此现在我要保存CONTINUE\nSo now I'm going to save continue, bang.\n\n822\n00:45:19,152 --> 00:45:20,656\n现在 DONE就来到了这里\nNow that done goes in here.\n\n823\n00:45:22,080 --> 00:45:23,552\n然后 这个指针移动到了这里\nAnd this moves to here,\n\n824\n00:45:24,880 --> 00:45:26,144\n下次我要把数据写到这里\nthe next place I'm going to write.\n\n825\n00:45:26,660 --> 00:45:28,784\n保存N的值--也就是3\nSave N 3.\n\n826\n00:45:29,950 --> 00:45:30,320\n对吧？\nOK?\n\n827\n00:45:30,672 --> 00:45:33,616\nN←N-1\nAssign to N the decrement of N.\n\n828\n00:45:33,968 --> 00:45:35,376\n也就是说 我得按下这个钮\nThat means I've pushed this button.\n\n829\n00:45:35,940 --> 00:45:37,320\n这就变成了2\nThis becomes 2.\n\n830\n00:45:38,736 --> 00:45:42,288\nCOUNTINUE←AFT\nOK? Assign to continue aft.\n\n831\n00:45:42,580 --> 00:45:43,610\n因此我要按下这个钮\nSo I've pushed that button.\n\n832\n00:45:43,610 --> 00:45:44,544\nAFT就进入了这里\nAft goes in here.\n\n833\n00:45:49,140 --> 00:45:53,936\n然后 跳转到LOOP 我们就来到了这里\nOK, now go to loop, bang, so up to here.\n\n834\n00:45:54,830 --> 00:45:57,088\nN=1么？当然不\nIs N 1? No\n\n835\n00:45:57,780 --> 00:45:59,232\n因此我又要保存CONTINUE\nSo I have to save continue.\n\n836\n00:45:59,490 --> 00:46:00,272\nCONTINUE的值是什么呢？\nWhat's continue?\n\n837\n00:46:00,600 --> 00:46:01,530\n目前是AFT\nContinue is aft.\n\n838\n00:46:01,530 --> 00:46:02,320\n按下这个按钮\nPush this button.\n\n839\n00:46:02,780 --> 00:46:03,952\n这个指针移动到了这里\nSo this moves to here.\n\n840\n00:46:08,490 --> 00:46:09,744\n我还要保存N\nI have to save N.\n\n841\n00:46:10,510 --> 00:46:12,128\nN在那里 它的值是2\nN is over here. I got to 2.\n\n842\n00:46:12,280 --> 00:46:13,376\n按下这个按钮\nPush that button.\n\n843\n00:46:13,856 --> 00:46:15,248\n2就进入了这里\nSo a 2 gets written there.\n\n844\n00:46:16,050 --> 00:46:17,648\n然后这个指针移动到了这里\nAnd then this thing moves down here.\n\n845\n00:46:20,060 --> 00:46:22,608\n保存N之后 又赋N←N-1\nOK, save N. Assign N to the decrement of N.\n\n846\n00:46:24,608 --> 00:46:25,460\n它就变成了1\nThis becomes a 1.\n\n847\n00:46:29,240 --> 00:46:30,544\nCONTINUE←AFT\nAssign continue to aft.\n\n848\n00:46:31,370 --> 00:46:34,480\nAFT又进入了这里\nA-F-T gets written there again.\n\n849\n00:46:34,960 --> 00:46:35,648\n然后又跳转到LOOP\nGo to loop.\n\n850\n00:46:36,520 --> 00:46:37,744\nN等于1么？\nIs N equal to 1?\n\n851\n00:46:37,930 --> 00:46:39,520\n是的 那么答案就是1\nOh, yes, the answer is 1.\n\n852\n00:46:41,040 --> 00:46:43,264\n跳转到BASE那一步\nOK, go to base step.\n\n853\n00:46:44,160 --> 00:46:45,776\n(ASSIGN VAL (FETCH N))\nAssign to VAL fetch of N.\n\n854\n00:46:46,560 --> 00:46:50,720\n按下这个 1就进入到了这里\nBang, 1 gets put in there. OK?\n\n855\n00:46:51,100 --> 00:46:52,200\n(GOTO (FETCH CONTINUE))\nGo to fetch continue.\n\n856\n00:46:52,200 --> 00:46:53,536\n来看下CONTINUE寄存器\nSo we look in continue.\n\n857\n00:46:53,680 --> 00:46:56,064\n基本上来说 我按下这里的按钮 进入到控制器\nBasically, I'm pushing a button over here that goes to the controller.\n\n858\n00:46:56,670 --> 00:46:58,288\nCONTINUE寄存器就变成了AFT\nThe continue becomes aft,\n\n859\n00:46:58,320 --> 00:47:00,256\n这样一下子 程序就运行到了这里\nand all of a sudden, the program's running here.\n\n860\n00:47:02,640 --> 00:47:05,632\n现在 我就需要恢复外部的阶乘了\nI now have to restore the outer version of factorial.\n\n861\n00:47:06,650 --> 00:47:07,550\n因此我们来到这里\nSo we go here.\n\n862\n00:47:07,550 --> 00:47:09,488\n我们先要恢复N\nWe say, restore N.\n\n863\n00:47:10,320 --> 00:47:13,040\n这就意味着 我们要使用这里的内容\nSo restore N means take the contents that's here.\n\n864\n00:47:13,940 --> 00:47:18,176\n按下这个按钮 2就会来到这里\nPush this button, and it goes into here, 2,\n\n865\n00:47:18,560 --> 00:47:20,048\n然后指针会向上移动\nand the pointer moves up.\n\n866\n00:47:21,984 --> 00:47:24,490\n恢复CONTINUE寄存器也非常简单\nRestore continue, pretty easy.\n\n867\n00:47:24,810 --> 00:47:26,496\n来按下这个按钮\nGo push this button.\n\n868\n00:47:27,020 --> 00:47:28,928\n然后 AFT又一次进入到这里\nAnd then aft gets written in here again.\n\n869\n00:47:31,280 --> 00:47:32,640\n同时 这个指针也要上移\nThat means this thing moves up.\n\n870\n00:47:32,640 --> 00:47:35,190\n这样就避开了栈上的其它东西\nI've gotten rid of something else on my stack.\n\n871\n00:47:42,240 --> 00:47:43,472\n然后我来到这里\nRight, then I go to here,\n\n872\n00:47:43,872 --> 00:47:47,152\n也就是(ASSIGN VAL (* N VAL))\nwhich says, assign to VAL the product of N and VAL.\n\n873\n00:47:47,850 --> 00:47:50,576\n然后我按下这个按钮\nSo I push this button over here, bang.\n\n874\n00:47:50,970 --> 00:47:52,912\n2乘以1等于2\n2 times 1 gives me a 2,\n\n875\n00:47:54,016 --> 00:47:54,752\n我写到这里\nget written there.\n\n876\n00:47:55,760 --> 00:47:57,200\n然后是(GOTO (FETCH CONTINUE))\nOK? Go to fetch continue.\n\n877\n00:47:57,540 --> 00:47:59,856\nCONTINUE现在是AFT 我跳转到AFT\nContinue is aft. I go to aft.\n\n878\n00:48:01,150 --> 00:48:03,888\nAFT首先要恢复N\nOK? Aft says restore N.\n\n879\n00:48:04,368 --> 00:48:05,728\n恢复N指的是\nDo your restore N,\n\n880\n00:48:05,872 --> 00:48:08,448\n我把这里的值 也就是3\nmeans I take the value over here, which is 3,\n\n881\n00:48:09,248 --> 00:48:10,336\n按下这里的按钮\npush this up to here,\n\n882\n00:48:10,600 --> 00:48:15,504\n然后把它放到这里 N\nand move it into here, N.\n\n883\n00:48:16,256 --> 00:48:17,344\n然后 我们按下这个钮\nNow it's pushing that button.\n\n884\n00:48:18,016 --> 00:48:19,904\n接下来我就要恢复CONTINUE\nThe next thing I do is restore continue.\n\n885\n00:48:20,200 --> 00:48:22,208\nCONTINUE寄存器现在成为了DONE\nContinue is now going to become done.\n\n886\n00:48:22,830 --> 00:48:26,784\n当我按下这个钮后 指针就移动到了这里\nSo this moves up here when I push this button.\n\n887\n00:48:27,130 --> 00:48:29,728\nDONE可能从此之后不在这里了\nDone may or may be there anymore,\n\n888\n00:48:29,728 --> 00:48:31,550\n对此我并不感兴趣 但它现在一定在这里\nI'm not interested, but it certainly is here.\n\n889\n00:48:35,800 --> 00:48:38,120\n下一步 我将要把VAL赋值为\nNext thing I do is assign to VAL\n\n890\n00:48:38,432 --> 00:48:40,768\nN乘以VAL的值\nthe product of the fetch of N and the fetch of VAL.\n\n891\n00:48:41,440 --> 00:48:44,300\n按下这里的按钮就可以实现\nThat's pushing this button over here, bang.\n\n892\n00:48:44,300 --> 00:48:45,776\n2乘以3等于6\n2 times 3 is 6.\n\n893\n00:48:46,520 --> 00:48:47,870\n所以这里我就得到了6\nSo I get a 6 over here.\n\n894\n00:48:50,976 --> 00:48:53,408\n下一步是(GOTO (FETCH CONTINUE))\nOK? And go to fetch continue,\n\n895\n00:48:53,488 --> 00:48:54,832\n哦 跳转到DONE 这样我就完成了\nwhoops, I go to done, and I'm done.\n\n896\n00:48:55,020 --> 00:48:56,096\n最后的答案是6\nAnd my answer is 6,\n\n897\n00:48:56,608 --> 00:48:57,824\n你们可以在VAL寄存器中看到\nas you can see in the VAL register.\n\n898\n00:48:58,950 --> 00:48:59,824\n事实上\nAnd in fact,\n\n899\n00:49:00,912 --> 00:49:03,344\n栈又回到了它初始的状态\nthe stack is in the state it originally was in.\n\n900\n00:49:08,208 --> 00:49:10,704\n在使用像栈这样的东西中 有一些原则\nNow there's a bit of discipline in using these things like stacks\n\n901\n00:49:11,200 --> 00:49:12,272\n我们需要注意\nthat we have to be careful of.\n\n902\n00:49:13,620 --> 00:49:15,520\n我们会在下一小节中介绍\nAnd we'll see that in the next segment.\n\n903\n00:49:16,260 --> 00:49:18,464\n但首先 对于这一小节所讲的内容\nBut first I want to ask if there are any questions for this.\n\n904\n00:49:28,560 --> 00:49:29,648\n有什么问题么？\nAre there any questions?\n\n905\n00:49:30,170 --> 00:49:30,630\nRon 请讲\nYes, Ron.\n\n906\n00:49:30,630 --> 00:49:33,376\n学生：当你越过了栈的顶端会怎样--\nAUDIENCE: What happens when you roll off the end of the stack with--\n\n907\n00:49:33,392 --> 00:49:34,624\n教授：你所谓的“越过”是指什么？\nPROFESSOR: What do you mean, roll off of?\n\n908\n00:49:35,030 --> 00:49:37,504\n学生：如果我们的N是一个很大的数\nAUDIENCE: Well, the largest number-- a larger starting point of N\n\n909\n00:49:37,520 --> 00:49:38,720\n就需要更多的内存 对吧？\nrequires more memory, correct?\n\n910\n00:49:38,860 --> 00:49:39,440\n教授：是的\nPROFESSOR: Oh, yes.\n\n911\n00:49:39,440 --> 00:49:41,120\n这样 我就需要一个足够大的栈\nWell, I need to have a long enough stack.\n\n912\n00:49:41,530 --> 00:49:43,200\n你想问 如果破坏了无穷存储的假象会发生什么？\nYou say, what if I violate my illusion?\n\n913\n00:49:43,840 --> 00:49:44,128\n学生：是的\nAUDIENCE: Yes.\n\n914\n00:49:44,550 --> 00:49:46,736\n教授：那么 这些魔法就不再起效了\nPROFESSOR: Well, then the magic doesn't work. OK?\n\n915\n00:49:47,968 --> 00:49:51,008\n真相就是 任何机器都是有穷的\nThe truth of the matter is that every machine is finite.\n\n916\n00:49:51,640 --> 00:49:53,728\n而对于像这样的过程\nAnd for a procedure like this,\n\n917\n00:49:54,176 --> 00:49:58,864\n我只能进行有限数量的子阶乘计算\nthere's a limit to the number of sub-factorials I could have.\n\n918\n00:49:59,950 --> 00:50:02,480\n想一想 我们之前讲解的Y组合子\nRemember when we were doing the y-operator a while ago,\n\n919\n00:50:02,800 --> 00:50:06,224\n我们指出 存在一系列的指数过程\nwe pointed out that there was a sequence of exponentiation procedures,\n\n920\n00:50:06,256 --> 00:50:08,096\n其中每一个都要比前一个更精准\neach of which was a little better than the previous one.\n\n921\n00:50:08,720 --> 00:50:11,600\n现在 我们看到了如何实现这个数学理念\nWell, we're now seeing how we implement that mathematical idea.\n\n922\n00:50:13,090 --> 00:50:14,192\n这个取极限的过程\nThe limiting process\n\n923\n00:50:14,352 --> 00:50:16,336\n只有当你取到极限时才足够精准\nis only so good as as far as you take the limit.\n\n924\n00:50:17,990 --> 00:50:19,420\n如果你仔细想想 我这里用了什么\nIf you think about it, what am I using here?\n\n925\n00:50:19,420 --> 00:50:22,656\n对于这个过程的每一次递归\nI'm using about two chunks, pieces of memory\n\n926\n00:50:23,040 --> 00:50:27,072\n我用了大概两块内存\nfor iteration for every recursion of this process.\n\n927\n00:50:29,100 --> 00:50:31,712\n如果我们尝试计算10000的阶乘\nIf we try to compute factorial of 10,000,\n\n928\n00:50:31,728 --> 00:50:32,816\n这并不会花掉很多内存\nthat's not a lot of memory.\n\n929\n00:50:33,180 --> 00:50:34,688\n虽然这是一个很大的数\nOn the other hand, it's an awful big number.\n\n930\n00:50:35,952 --> 00:50:38,416\n因此 实际的问题就是值不值得\nSo the question is, is that a valuable thing in this case.\n\n931\n00:50:39,180 --> 00:50:42,192\n但这并不是这种实现的局限\nBut it really turns out not to be a terrible limit,\n\n932\n00:50:42,224 --> 00:50:43,536\n因为内存非常低廉\nbecause memory is el cheapo,\n\n933\n00:50:44,160 --> 00:50:45,344\n但人力资源却相当昂贵\nand people are pretty expensive.\n\n934\n00:50:48,130 --> 00:50:50,224\n好吧 我们先休息一下 谢谢大家\nOK, thank you, let's take a break.\n\n935\n00:50:50,780 --> 00:51:07,600\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n936\n00:51:07,600 --> 00:51:12,192\n《计算机程序的构造和解释》\n\n937\n00:51:39,930 --> 00:51:43,696\n讲师：哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\n\n938\n00:51:43,710 --> 00:51:47,936\n《计算机程序的构造和解释》\n\n939\n00:51:47,930 --> 00:51:53,088\n寄存机器\n\n940\n00:51:56,112 --> 00:51:57,040\n教授：我们讲解了\nPROFESSOR: Well, let's see.\n\n941\n00:51:58,704 --> 00:52:03,376\n如果进行简单的迭代计算\nWhat I've shown you now is how to do a simple iterative process\n\n942\n00:52:03,696 --> 00:52:05,312\n以及简单的递归计算\nand a simple recursive process.\n\n943\n00:52:05,640 --> 00:52:08,688\n我只想通过向你们展示一些针对特定应用的\nI just want to summarize the design of simple machines\n\n944\n00:52:09,632 --> 00:52:11,120\n更加复杂的设计\nfor specific applications\n\n945\n00:52:11,216 --> 00:52:13,584\n来总结简单机器的设计\nby showing you a little bit more complicated design,\n\n946\n00:52:13,968 --> 00:52:17,136\n也就是同时递归地调用两个斐波那契函数\nthat of a thing that does doubly recursive Fibonacci,\n\n947\n00:52:17,232 --> 00:52:19,888\n因为它会向我们表明 并且我们会理解\nbecause it will indicate to us, and we'll understand,\n\n948\n00:52:20,048 --> 00:52:22,688\n一些关于栈正常工作\na bit about the conventions required\n\n949\n00:52:22,768 --> 00:52:25,040\n所需要遵守的约定\nfor making stacks operate correctly.\n\n950\n00:52:26,400 --> 00:52:27,110\n现在 让我们来看看\nSo let's see.\n\n951\n00:52:27,110 --> 00:52:28,272\n先让我在黑板上写下\nI'm just going to write down, first of all,\n\n952\n00:52:28,304 --> 00:52:29,712\n将要翻译的程序\nthe program I'm going to translate.\n\n953\n00:52:34,150 --> 00:52:36,528\n这是一个斐波那契过程\nI need a Fibonacci procedure,\n\n954\n00:52:39,232 --> 00:52:41,584\n它非常的简单\nit's very simple, which says, if\n\n955\n00:52:44,608 --> 00:52:48,560\n如果N小于2 那么结果就是N\nN is less than 2, the result is N,\n\n956\n00:52:49,264 --> 00:52:55,344\n否则就是(FIB (- N 1))加上\notherwise it's the sum of Fib of N minus 1\n\n957\n00:52:58,448 --> 00:52:59,856\n(FIB (- N 2))\nand Fib of N minus 2.\n\n958\n00:53:07,056 --> 00:53:09,290\n这就是我的计划\nThat's the plan I have here.\n\n959\n00:53:09,290 --> 00:53:12,560\n现在 我们要来写下这台机器的控制器\nAnd we're just going to write down the controller for such a machine.\n\n960\n00:53:13,070 --> 00:53:15,536\n首先 我们假设有一个寄存器N\nWe're going to assume that there are registers, N,\n\n961\n00:53:15,568 --> 00:53:19,150\n里面存放的是斐波那契函数的自变量\nwhich holds the number we're taking Fibonacci of,\n\n962\n00:53:19,824 --> 00:53:21,808\n而计算结果会存放在VAL寄存器中\nVAL, which is where the answer is going to get put,\n\n963\n00:53:22,176 --> 00:53:24,976\nCONTINUE寄存器会和控制器相连\nand continue, which is the thing that's linked to the controller,\n\n964\n00:53:26,112 --> 00:53:26,810\n就跟之前一样\nlike before.\n\n965\n00:53:26,960 --> 00:53:29,216\n但我不会再去画数据通路了\nBut I'm not going to draw another physical datapath,\n\n966\n00:53:31,536 --> 00:53:34,000\n因为它和之前的那个差不多\nbecause it's pretty much the same as the last one you've seen.\n\n967\n00:53:34,360 --> 00:53:37,840\n当然 关于计算的最神奇的事情之一\nAnd of course, one of the most amazing things about computation\n\n968\n00:53:38,752 --> 00:53:39,888\n就是一段时间后\nis that after a while,\n\n969\n00:53:40,080 --> 00:53:41,936\n你构建了一个又一个的小功能\nyou build up a little more features and a few more features,\n\n970\n00:53:41,952 --> 00:53:43,328\n你就一下子拥有了需要的一切\nand all of the sudden, you've got everything you need.\n\n971\n00:53:44,752 --> 00:53:47,600\n这种效率是非常了不起的\nSo it's remarkable that it just gets there so fast.\n\n972\n00:53:48,176 --> 00:53:50,848\n构造制作一台通用计算机不需要太多的东西\nI don't need much more to make a universal computer.\n\n973\n00:53:51,810 --> 00:53:54,688\n总之 我们来看看斐波那契机器的控制器\nBut in any case, let's look at the controller for the Fibonacci thing.\n\n974\n00:53:55,060 --> 00:53:57,072\n我首先要做的是\nFirst thing I want to do is\n\n975\n00:53:57,328 --> 00:54:02,528\n通过为CONTINUE寄存器赋值\nstart the thing up by assign to continue\n\n976\n00:54:07,136 --> 00:54:10,288\n赋FIB-DONE来启动计算\na place called done, called Fib-done here.\n\n977\n00:54:14,144 --> 00:54:15,536\n这就意味着在这里\nSo that means that somewhere over here,\n\n978\n00:54:15,552 --> 00:54:18,480\n我需要有一个标签 FIB-DONE\nI'm going to have a label, Fib-done,\n\n979\n00:54:19,712 --> 00:54:21,104\n当我来到这个地方后\nwhich is the place where I go\n\n980\n00:54:21,232 --> 00:54:22,448\n机器就停止了\nwhen I want the machine to stop.\n\n981\n00:54:24,000 --> 00:54:24,864\n这就是这个标签的作用\nThat's what that is.\n\n982\n00:54:25,920 --> 00:54:26,896\n然后我要创建一个循环\nAnd I'm going to make up a loop.\n\n983\n00:54:31,110 --> 00:54:34,256\n我要来到这里来启动FIB的计算\nIt's a place I'm going to go to in order to start up computing a Fib.\n\n984\n00:54:35,470 --> 00:54:36,864\n无论这时 N等于多少\nWhatever is in N at this point,\n\n985\n00:54:37,392 --> 00:54:38,992\n斐波那契函数都会被计算\nFibonacci will be computed of,\n\n986\n00:54:39,136 --> 00:54:42,016\n然后会返回到由CONTINUE寄存器指向的地方\nand we will return to the place specified by continue.\n\n987\n00:54:44,800 --> 00:54:48,400\n因此你们将在这里看到\nSo what you're going to see here at this place,\n\n988\n00:54:48,448 --> 00:54:50,480\n我想要在做一个约定\nwhat I want here is the contract\n\n989\n00:54:50,970 --> 00:54:54,256\n我用注释的形式来说明这个约定\nthat says, I'm going to write this with a comment syntax,\n\n990\n00:54:54,576 --> 00:55:00,992\n也就是N中存储的是参数\nthe contract is N contains arg, the argument.\n\n991\n00:55:02,100 --> 00:55:09,824\n而CONTINUE存储的是接收者\nContinue is the recipient.\n\n992\n00:55:13,360 --> 00:55:14,290\n这个约定就是这样的\nAnd that's where it is.\n\n993\n00:55:15,710 --> 00:55:18,960\n因此每当我来到这里\nAt this point, if I ever go to this place,\n\n994\n00:55:19,248 --> 00:55:21,040\n我希望这个约定是成立的\nI'm expecting this to be true,\n\n995\n00:55:21,520 --> 00:55:23,328\n这些计算斐波那契函数所需要的参数\nthe argument for computing the Fibonacci.\n\n996\n00:55:24,820 --> 00:55:26,832\n接下来我想做的是分支\nNow the next thing I want to do is to branch.\n\n997\n00:55:30,220 --> 00:55:32,224\n如果N小于2\nAnd if N is less than 2--\n\n998\n00:55:35,072 --> 00:55:37,440\n随便说一下 我使用的语法看起来像Lisp\nby the way, I'm using what looks like Lisp syntax.\n\n999\n00:55:38,730 --> 00:55:39,632\n但它并不是Lisp\nThis is not Lisp.\n\n1000\n00:55:41,310 --> 00:55:42,384\n它们运行不起来\nThis does not run.\n\n1001\n00:55:42,750 --> 00:55:45,472\n我在这里写的并不是一个简单的Lisp程序\nWhat I'm writing here does not run as a simple Lisp program.\n\n1002\n00:55:46,120 --> 00:55:49,312\n这是另一门语言的表示形式\nThis is a representation of another language.\n\n1003\n00:55:49,710 --> 00:55:52,256\n我之所以使用这种满是括号的语法\nThe reason I'm using the syntax of parentheses and so on\n\n1004\n00:55:52,400 --> 00:55:54,704\n是因为我刚好使用Lisp系统\nis because I tend to use a Lisp system\n\n1005\n00:55:55,328 --> 00:55:57,344\n来为这门语言编写解释器\nto write an interpreter for this\n\n1006\n00:55:57,824 --> 00:55:59,184\n这就使得我们能够模拟\nwhich allows me to simulate\n\n1007\n00:55:59,296 --> 00:56:00,912\n我想要构建的机器\nthe machine I'm trying to build.\n\n1008\n00:56:03,380 --> 00:56:06,240\n我不想让你们感到困惑 认为这是Lisp代码\nI don't want to confuse this to think that this is Lisp code.\n\n1009\n00:56:06,940 --> 00:56:08,608\n只是我用了很多Lisp组件\nIt's just I'm using a lot of the pieces of Lisp.\n\n1010\n00:56:09,510 --> 00:56:10,848\n我在Lisp中嵌入了一门语言\nI'm embedding a language in Lisp,\n\n1011\n00:56:11,024 --> 00:56:12,448\n把Lisp当作组件\nusing Lisp as pieces\n\n1012\n00:56:12,720 --> 00:56:15,120\n这样就能让我的模拟工作变得简单\nto make my process of making my simulator easy.\n\n1013\n00:56:16,620 --> 00:56:18,560\n我从Lisp中继承了这些属性\nSo I'm inheriting from Lisp all of its properties.\n\n1014\n00:56:19,100 --> 00:56:21,530\n(FETCH N) 2)\nFetch of N 2,\n\n1015\n00:56:21,776 --> 00:56:23,728\n成立的话 我想要跳转到IMMEDIATE-ANSWER这个地方\nI want to go to a place called immediate answer.\n\n1016\n00:56:26,208 --> 00:56:27,296\n这是基本步骤\nIt's the base step.\n\n1017\n00:56:33,150 --> 00:56:34,352\n它对应在这里\nNow, that's somewhere over here,\n\n1018\n00:56:35,920 --> 00:56:36,896\n也就是在FIB-DONE的上方\njust above done.\n\n1019\n00:56:37,750 --> 00:56:38,640\n我们稍后就会看到\nAnd we'll see it later.\n\n1020\n00:56:39,424 --> 00:56:40,704\n现在 对于一般情况来说\nNow, in the general case,\n\n1021\n00:56:40,720 --> 00:56:42,448\n也就是我现在要写的\nwhich is the part I'm going to write down now,\n\n1022\n00:56:43,136 --> 00:56:44,192\n是这样的\nlet's just do it.\n\n1023\n00:56:44,912 --> 00:56:48,200\n首先呢 我需要调用斐波那契函数两次\nWell, first of all, I'm going to have to call Fibonacci twice.\n\n1024\n00:56:49,420 --> 00:56:52,544\n在每一次中 -- 至少在其中一次\nIn each case-- well, in one case at least,\n\n1025\n00:56:52,780 --> 00:56:53,952\n我得需要知道该怎么做\nI'm going to have to know what to do\n\n1026\n00:56:53,968 --> 00:56:55,360\n才能回过头来进行另外一个计算\nto come back and do the next one.\n\n1027\n00:56:56,310 --> 00:56:58,368\n我需要记住\nI have to remember,\n\n1028\n00:56:59,200 --> 00:57:01,232\n我计算完第一个FIB了么？\nhave I done the first Fib,\n\n1029\n00:57:01,264 --> 00:57:02,544\n或者第二个也计算完了？\nor have I done the second one?\n\n1030\n00:57:04,500 --> 00:57:07,040\n我是该返回到计算第二个FIB的地方\nDo I have to come back to the place where I do the second Fib,\n\n1031\n00:57:07,072 --> 00:57:09,088\n还是回到执行ADD的地方\nor do I have to come back to the place where I do the add?\n\n1032\n00:57:10,128 --> 00:57:12,112\n无论哪种情况 我都需要--\nIn both cases I going to need, I don't\n\n1033\n00:57:12,140 --> 00:57:14,464\n在第一个计算第一个FIB时\nIn the first case, over the first Fibonacci,\n\n1034\n00:57:14,512 --> 00:57:16,980\n我需要保存N的值 来计算第二个FIB\nI'm going to need the value of N for computing for the second one.\n\n1035\n00:57:19,840 --> 00:57:21,584\n因此我要把这些东西保存起来\nSo I have to store some of these things up.\n\n1036\n00:57:23,360 --> 00:57:24,896\n首先要保存CONTINUE\nSo first I'm going to save continue.\n\n1037\n00:57:26,192 --> 00:57:27,328\n也就是答案的接收者\nThat's who needs the answer.\n\n1038\n00:57:31,320 --> 00:57:32,464\n我之所以要这么做\nAnd the reason I'm doing that\n\n1039\n00:57:32,480 --> 00:57:34,208\n是因为我现在要把CONTINUE赋值为\nis because I'm about to assign continue\n\n1040\n00:57:40,112 --> 00:57:44,320\n我待会儿想要返回的地方\nto the place which is the place I want to go to after.\n\n1041\n00:57:46,832 --> 00:57:50,272\n我们把它叫做AFTER-FIB-N-1\nLet's call it Fib-N-minus-1,\n\n1042\n00:57:51,040 --> 00:57:53,760\n这个长名字 非常具有Lisp的命名特点\nbig long name, classic Lisp name.\n\n1043\n00:57:57,360 --> 00:58:00,224\n这是因为我先要计算第一个(FIB (- N 1))\nBecause I'm going to compute the first Fib of N minus 1,\n\n1044\n00:58:00,840 --> 00:58:01,728\n计算完成之后\nand then after that,\n\n1045\n00:58:01,728 --> 00:58:03,290\n我想要回过头来做些其它事\nI want to come back and do something else.\n\n1046\n00:58:03,960 --> 00:58:06,528\n而AFTER-FIB-N-1这个地方\nThat's the place I want to go to after I've done\n\n1047\n00:58:07,552 --> 00:58:09,488\n就是我计算完第一个FIB后应该返回的地方\nthe first Fibonacci calculation.\n\n1048\n00:58:11,520 --> 00:58:13,136\n接下来我要保存N\nAnd I want to do a save of N,\n\n1049\n00:58:14,416 --> 00:58:17,264\n因为我稍后需要用到它\nbecause I'm going to need it later, after that.\n\n1050\n00:58:19,130 --> 00:58:20,544\n在这里 我就已经\nNow I'm going to, at this point,\n\n1051\n00:58:20,672 --> 00:58:22,848\n准备好计算(FIB (- N 1))了\nget ready to do the Fibonacci of N minus 1.\n\n1052\n00:58:23,024 --> 00:58:33,950\n(ASSIGN N (- (FETCH N) 1))\nSo assign to N the difference of the fetch of N and 1.\n\n1053\n00:58:38,110 --> 00:58:40,270\n现在 该跳转到FIB-LOOP了\nNow I'm ready to go back to doing the Fib loop.\n\n1054\n00:58:47,184 --> 00:58:49,872\n我满足我立下的约定么？\nDo I have... Have I satisfied my contract?\n\n1055\n00:58:50,400 --> 00:58:51,504\n答案是是的\nAnd the answer is yes.\n\n1056\n00:58:51,770 --> 00:58:55,120\nN现在存储的是N-1 这是我需要的\nN contains N minus 1, which is what I need.\n\n1057\n00:58:56,432 --> 00:59:00,096\n而CONTINUE包含的是计算完成后 返回的目的地\nOK? Continue contains a place I want to go to when I'm done\n\n1058\n00:59:01,280 --> 00:59:03,072\n也就是计算(FIB (- N 1))完成之后\nwith calculating FIB N minus 1.\n\n1059\n00:59:04,100 --> 00:59:05,440\n因此我满足了这些约定\nSo I've satisfied the contract.\n\n1060\n00:59:05,440 --> 00:59:09,024\n因此 我就可以在这里写下一个标签\nAnd therefore, I can write down here a tag, after, a label,\n\n1061\n00:59:11,472 --> 00:59:17,568\nAFTER-FIB-N-1\nafter-Fib-N-minus-1.\n\n1062\n00:59:20,490 --> 00:59:21,632\n在这里 我又该做些什么呢？\nNow what am I going to do here?\n\n1063\n00:59:22,690 --> 00:59:23,616\n在这里\nHere's a place\n\n1064\n00:59:23,952 --> 00:59:26,750\n我已经准备好去计算(FIB (- N 2))了\nwhere I now have to get ready to do Fib of N minus 2.\n\n1065\n00:59:29,270 --> 00:59:30,720\n但是为了计算(FIB (- N 2))\nBut in order to do a Fib of N minus 2,\n\n1066\n00:59:30,752 --> 00:59:31,630\n首先 我不知道\nlook, I don't know.\n\n1067\n00:59:31,780 --> 00:59:33,408\n这里 我已经改变了N\nI've clobbered my N over here.\n\n1068\n00:59:33,810 --> 00:59:35,472\n或者在这个时候 我的N总是不断地\nAnd presumably my N is counted down\n\n1069\n00:59:37,856 --> 00:59:38,800\n向1或者0递减\nall the way to 1 or 0 or something at this point.\n\n1070\n00:59:39,780 --> 00:59:42,512\n所以我不知道N寄存器中存储的到底是什么\nSo I don't know what the value of N in the N register is.\n\n1071\n00:59:43,030 --> 00:59:44,752\n我想要保存在栈中的N的值\nI want the value of N that was on the stack\n\n1072\n00:59:44,800 --> 00:59:46,000\n也就是我在这里保存的值\nthat I saved over here\n\n1073\n00:59:46,176 --> 00:59:47,888\n这样我就可以在这里恢复它\nso that could restore it over here.\n\n1074\n00:59:49,520 --> 00:59:51,024\n我在这里存储的N\nI saved up the value of N,\n\n1075\n00:59:51,150 --> 00:59:54,496\n是这个时间点N的值\nwhich is this value of N at this point,\n\n1076\n00:59:54,896 --> 00:59:57,376\n因此计算完(FIB (- N 1))之后我可以恢复它\nso that I could restore it after computing Fib of N minus 1,\n\n1077\n00:59:57,530 --> 00:59:59,360\n这样的话 我就可以计算(- N 2)\nso that I could count that down to N minus 2\n\n1078\n00:59:59,392 --> 01:00:00,860\n然后就可以计算(FIB (- N 2))的值\nand then compute Fib of N minus 2.\n\n1079\n01:00:01,810 --> 01:00:02,752\n现在让我们来恢复它\nSo let's restore that.\n\n1080\n01:00:08,830 --> 01:00:09,776\n(RESTORE N)\nRestore of N.\n\n1081\n01:00:11,130 --> 01:00:15,984\n现在我要做一件很教条的事\nNow I'm about to do something which is superstitious,\n\n1082\n01:00:16,000 --> 01:00:17,408\n我们会尽快将其删除\nand we will remove it shortly.\n\n1083\n01:00:18,520 --> 01:00:20,480\n如果你们愿意的话\nI am about to finish the sequence\n\n1084\n01:00:20,592 --> 01:00:23,440\n我将要结束子过程调用\nof doing the subroutine call, if you will.\n\n1085\n01:00:24,800 --> 01:00:25,952\n接下来我会说\nI'm going to say, well,\n\n1086\n01:00:26,064 --> 01:00:27,904\n因为我保存了CONTINUE\nI also saved up the continuation,\n\n1087\n01:00:28,480 --> 01:00:30,432\n现在就要去恢复它\nsince I'm going to restore it now.\n\n1088\n01:00:31,600 --> 01:00:32,608\n但实际上 我并不需要这么做\nBut actually, I don't have to,\n\n1089\n01:00:32,640 --> 01:00:33,550\n因为我并不需要用到它\nbecause I'm not going to need it.\n\n1090\n01:00:34,610 --> 01:00:35,728\n我们稍后会修正它\nWe'll fix that in a second.\n\n1091\n01:00:36,260 --> 01:00:37,952\n现在我们来恢复CONTINUE\nSo we'll do a restore of continue,\n\n1092\n01:00:46,048 --> 01:00:48,020\n通常来说 我都会这么做\nwhich is what I would in general need to do.\n\n1093\n01:00:48,020 --> 01:00:49,232\n我们将要看到\nAnd we're just going to see whats called\n\n1094\n01:00:49,312 --> 01:00:52,144\n编译器领域中的“窥孔优化”\nwhat you would call in the compiler world a peephole optimization,\n\n1095\n01:00:52,272 --> 01:00:53,728\n来帮我们消除这个不必要的步骤\nwhich says, whoops, you didn't have to do that.\n\n1096\n01:00:55,420 --> 01:00:57,104\n因此 我即将要做的就是\nOK, so the next thing I see here\n\n1097\n01:00:58,464 --> 01:01:02,288\n准备好计算(FIB (- N 2))\nis that I have to get ready now to do Fibonacci of N minus 2.\n\n1098\n01:01:02,770 --> 01:01:04,496\n但是我不再需要保存N了\nBut I don't have to save N anymore.\n\n1099\n01:01:05,050 --> 01:01:06,720\n原因就是\nThe reason why I don't have to save N anymore\n\n1100\n01:01:06,800 --> 01:01:09,344\n计算完(FIB (- N 2))之后 我就不需要N了\nis because I don't need N after I've done Fib of N minus 2,\n\n1101\n01:01:09,360 --> 01:01:10,720\n因为 我接下来要做的就是ADD\nbecause the next thing I do is add.\n\n1102\n01:01:13,540 --> 01:01:15,856\n因此 我会这么来设置N\nSo I'm just going to set up my N that way.\n\n1103\n01:01:16,608 --> 01:01:28,990\n(ASSIGN N (- (FETCH N) 2))\nAssign N minus difference of fetch N and 2.\n\n1104\n01:01:31,850 --> 01:01:34,016\n现在我需要结束\nNow I have to finish the setup\n\n1105\n01:01:34,272 --> 01:01:36,730\n调用(FIB (- N 2))的设置过程了\nfor calling Fibonacci of N minus 2.\n\n1106\n01:01:36,950 --> 01:01:38,336\n我需要保存CONTINUE\nWell, I have to save up continue\n\n1107\n01:01:44,224 --> 01:01:49,024\n然后把CONTINUE赋值为\nand assign continue, continue,\n\n1108\n01:01:52,304 --> 01:01:59,952\nAFTER-FIB-N-2\nto the place which is after Fib N 2,\n\n1109\n01:02:02,576 --> 01:02:04,032\n对应了那边代码的某处\nthat place over here somewhere.\n\n1110\n01:02:05,320 --> 01:02:07,232\n然而 我需要非常小心\nHowever, I've got to be very careful.\n\n1111\n01:02:08,650 --> 01:02:11,424\n而(FIB (- N 1))的值\nThe old value, the value of Fib of N minus 1,\n\n1112\n01:02:12,064 --> 01:02:13,120\n我稍后会用到\nI'm going to need later.\n\n1113\n01:02:15,300 --> 01:02:17,376\n(FIB (- N 1))的值\nThe value of Fibonacci of N minus 1,\n\n1114\n01:02:17,616 --> 01:02:18,480\n我需要它的值\nI'm going to need.\n\n1115\n01:02:18,784 --> 01:02:19,808\n我不能去改变它\nAnd I can't clobber it,\n\n1116\n01:02:21,072 --> 01:02:23,600\n因为我需要用它来加上(FIB (- N 2))\nbecause I'm going to have to add it to the value of Fib of N minus 2.\n\n1117\n01:02:24,150 --> 01:02:25,888\n它是存放在寄存器中的 因此我需要保存它\nThat's in the value register, so I'm going to save it.\n\n1118\n01:02:27,792 --> 01:02:32,608\n所以现在我要用(SAVE VAL)来保存它\nSo I have to save this right now, save up VAL.\n\n1119\n01:02:33,780 --> 01:02:35,440\n现在我就可以调用子过程了\nAnd now I can go off to my subroutine,\n\n1120\n01:02:36,672 --> 01:02:39,540\n(GOTO FIB-LOOP)\ngo to Fib loop.\n\n1121\n01:02:44,220 --> 01:02:46,576\n现在 在进行更进一步计算之前\nNow before I go any further\n\n1122\n01:02:46,800 --> 01:02:49,360\n在结束这个程序之前\nand finish this program,\n\n1123\n01:02:49,392 --> 01:02:51,050\n我想审视一下目前的代码片段\nI just want to look at this segment so far\n\n1124\n01:02:51,232 --> 01:02:56,000\n这里有一系列的指令\nand see, oh yes, there's a sequence of instructions here, if you will\n\n1125\n01:02:57,840 --> 01:02:59,088\n我可以对它们进行某些操作\nthat I can do something about.\n\n1126\n01:03:01,580 --> 01:03:03,200\n这里 我有一个操作用来恢复CONTINUE\nHere I have a restore of continue,\n\n1127\n01:03:04,256 --> 01:03:05,488\n一个操作用来保存CONTINUE\na save of continue,\n\n1128\n01:03:06,016 --> 01:03:07,408\n然后给CONTINUE赋值\nand then an assign of continue,\n\n1129\n01:03:08,704 --> 01:03:10,640\n但这之中没有CONTINUE的其它引用\nwith no other references to continue in between.\n\n1130\n01:03:13,840 --> 01:03:15,488\n恢复之后又保存\nThe restore followed by the save\n\n1131\n01:03:15,504 --> 01:03:16,670\n使得栈没有被修改\nleaves the stack unchanged.\n\n1132\n01:03:19,090 --> 01:03:21,728\n唯一的区别就是 我给CONTINUE寄存器赋了值\nThe only difference is that I set the continue register to a value,\n\n1133\n01:03:21,968 --> 01:03:23,280\n一个存放在栈上的值\nwhich is the value that was on the stack.\n\n1134\n01:03:24,330 --> 01:03:25,792\n由于我现在改变了这个值\nSince I now clobber that value,\n\n1135\n01:03:26,448 --> 01:03:27,936\n但这之间并没有引用这个值\nas in it was never referenced,\n\n1136\n01:03:28,592 --> 01:03:30,096\n这些指令就是不必要的\nthese instructions are unnecessary.\n\n1137\n01:03:31,760 --> 01:03:35,390\n因此我们会移除它们\nSo we will remove these.\n\n1138\n01:03:38,880 --> 01:03:40,784\n但我只有先把它们写出来 才会发现这个情况\nBut I couldn't have seen that unless I had written them down.\n\n1139\n01:03:43,780 --> 01:03:44,720\n真是这样吗？\nWas that really true?\n\n1140\n01:03:45,776 --> 01:03:46,608\n我并不知道\nWell, I don't know.\n\n1141\n01:03:48,610 --> 01:03:52,912\n现在 我们要开始计算(FIB (- N 2))了\nOK, so we've now gone off to compute Fibonacci of N minus 2.\n\n1142\n01:03:53,660 --> 01:03:54,592\n计算完毕后\nSo after that,\n\n1143\n01:04:02,960 --> 01:04:03,856\n我们又要做什么呢？\nwhat are we going to do?\n\n1144\n01:04:05,070 --> 01:04:06,768\n我想 我们首先要做的就是\nWell, I suppose the first thing we have to do--\n\n1145\n01:04:06,992 --> 01:04:07,888\n我们有两件事要做\nwe've got two things.\n\n1146\n01:04:07,960 --> 01:04:10,496\n目前VAL寄存器中的值 是有意义的\nWe've got a thing in the value register which is now valuable.\n\n1147\n01:04:10,920 --> 01:04:11,984\n然而 栈上也有一个数据\nWe also have a thing on the stack\n\n1148\n01:04:12,048 --> 01:04:13,632\n需要恢复到VAL寄存器中\ncan be restored into the value register.\n\n1149\n01:04:14,810 --> 01:04:16,576\n现在我需要非常小心的是\nAnd what I have to be careful with now\n\n1150\n01:04:16,880 --> 01:04:18,992\n正确地给它们排序 以便计算乘法\nis I want to shuffle this right so I can do the multiply.\n\n1151\n01:04:19,470 --> 01:04:21,248\n现在 我可能会使用不同的约定\nNow there are various conventions I might use,\n\n1152\n01:04:21,472 --> 01:04:23,520\n但我现在会采用非常挑剔的一种\nbut I'm going to be very picky and say,\n\n1153\n01:04:23,552 --> 01:04:25,888\n栈上数据来自于哪个寄存器 就恢复到那个寄存器中\nI'm only going to restore into a register I've saved from.\n\n1154\n01:04:26,740 --> 01:04:28,288\n如果是这样的话 在这里我就要进行洗牌\nIf that's the case, I have to do a shuffle here.\n\n1155\n01:04:29,248 --> 01:04:31,840\n这跟我有多少只手是同样的问题\nIt's the same problem with how many hands I have.\n\n1156\n01:04:32,688 --> 01:04:37,136\n现在我要给N赋值\nSo I'm going to assign to N,\n\n1157\n01:04:37,168 --> 01:04:39,376\n因为我现在不再需要N了 N是无用的\nbecause I'm not going to need N anymore, N is useless,\n\n1158\n01:04:39,920 --> 01:04:41,216\n获取当前VAL寄存器的值\nthe current value of VAL,\n\n1159\n01:04:45,216 --> 01:04:47,340\n也就是(FIB (- N 2))的值\nwhich was the value of Fib of N minus 2.\n\n1160\n01:04:52,950 --> 01:04:56,352\n现在 我就要恢复VAL寄存器了\nAnd I'm going to restore the value register now.\n\n1161\n01:05:01,850 --> 01:05:03,920\n这个RESTORE匹配这里的SAVE\nThis restore matches this save.\n\n1162\n01:05:05,584 --> 01:05:08,832\n如果你非常仔细地研究发生了什么\nAnd if you're very careful and examine very carefully what goes on,\n\n1163\n01:05:09,216 --> 01:05:11,968\n会发现 RESTORE和SAVE总是成对的\nOK? restores and saves are always matched.\n\n1164\n01:05:13,840 --> 01:05:15,152\n现在 这里有个额外的SAVE\nNow there's an outstanding save,\n\n1165\n01:05:15,184 --> 01:05:16,384\n当然 我们很快就会消灭它\nof course, that we have to get rid of soon.\n\n1166\n01:05:19,000 --> 01:05:20,590\n恢复完VAL寄存器后\nAnd so I restored the value register.\n\n1167\n01:05:20,944 --> 01:05:22,576\n我就要恢复CONTINUE寄存器了\nNow I restore the continue one,\n\n1168\n01:05:31,152 --> 01:05:32,400\n它匹配了这个\nwhich matches this one,\n\n1169\n01:05:34,800 --> 01:05:37,856\n从这里到这里\ndot, dot, dot, dot, dot, dot, dot, down to here,\n\n1170\n01:05:40,592 --> 01:05:42,464\n这样就恢复了继续\nNow restoring that continuation.\n\n1171\n01:05:42,860 --> 01:05:45,712\n这个表达式继续是由(FIB N)产生的\nThat continuation is a continuation of Fib of N,\n\n1172\n01:05:46,460 --> 01:05:47,840\n也就是我正尝试求解的\nwhich is the problem I was trying to solve,\n\n1173\n01:05:47,856 --> 01:05:49,320\n最主要的问题\na major problem I'm trying to solve.\n\n1174\n01:05:49,984 --> 01:05:52,352\n我需要把(FIB N)的答案返回给这个继续\nSo that's the guy I have to go back to who wants Fib of N.\n\n1175\n01:05:52,544 --> 01:05:54,032\n在我意识到N并不小于2之前\nI saved them all the way up here\n\n1176\n01:05:54,160 --> 01:05:56,608\n我一直保存着它们\nwhen I realized N was not less than 2.\n\n1177\n01:05:57,360 --> 01:05:59,072\n因此 我需要进行一个复杂的运算\nAnd so I had to do a complicated operation.\n\n1178\n01:06:00,840 --> 01:06:02,576\n现在万事俱备\nNow I've got everything I need to do it.\n\n1179\n01:06:03,240 --> 01:06:04,368\n因此我要恢复它们\nSo I'm going to restore that,\n\n1180\n01:06:05,420 --> 01:06:21,088\n(ASSIGN VAL (+ (FETCH VAL) (FETCH N)))\nassign to VAL the sum of fetch VAL and fetch of N\n\n1181\n01:06:27,440 --> 01:06:28,608\n然后跳转到CONTINUE\nand go to continue.\n\n1182\n01:06:38,260 --> 01:06:44,784\n然后我就从(FIB N)中返回了出来\nSo now I've returned from computing Fibonacci of N,\n\n1183\n01:06:45,392 --> 01:06:46,576\n也就是FIB的一般情况\nthe general case.\n\n1184\n01:06:47,110 --> 01:06:50,608\n现在还有一些细节 需要我们填充\nNow what's left is we have to fix up a few details,\n\n1185\n01:06:50,992 --> 01:06:55,536\n比如归纳的基本情况：可以立即得到答案\nlike there's the base case of this induction, immediate answer,\n\n1186\n01:07:02,540 --> 01:07:06,592\n这不过就是\nas, which is nothing more than\n\n1187\n01:07:06,608 --> 01:07:11,850\n(ASSIGN VAL (FETCH N)\nassign to VAL fetch of N,\n\n1188\n01:07:13,640 --> 01:07:15,472\n因为N小于2\nbecause N was less than 2,\n\n1189\n01:07:15,504 --> 01:07:16,890\n因此答案就是N\nand therefore, the answer is N\n\n1190\n01:07:16,990 --> 01:07:18,192\n跟源程序是一致的\nin our original program,\n\n1191\n01:07:19,230 --> 01:07:26,480\n(GOTO (FETCH CONTINUE))\nand return continue--\n\n1192\n01:07:31,248 --> 01:07:36,130\n最后就结束了\nbobble, bobble almost-- and finally Fib done.\n\n1193\n01:07:43,460 --> 01:07:45,640\n这是个相当复杂的程序\nSo that's a fairly complicated program.\n\n1194\n01:07:45,640 --> 01:07:47,344\n我之所以给你们演示这个程序\nAnd the reason I wanted you see to that\n\n1195\n01:07:47,500 --> 01:07:49,216\n是因为我想让你们见识\nis because I want you to see the particular\n\n1196\n01:07:49,456 --> 01:07:52,672\n我所遵守的栈使用准则\nflavors of stack discipline that I was obeying.\n\n1197\n01:07:53,328 --> 01:07:55,216\n第一点就是 我不想保存那些\nIt was first of all, I don't want to save anything\n\n1198\n01:07:56,928 --> 01:07:58,128\n稍后不需要的值\nthat I'm not going to need later.\n\n1199\n01:08:00,576 --> 01:08:01,850\n我非常地小心\nI was being very careful.\n\n1200\n01:08:01,850 --> 01:08:02,912\n这非常重要\nAnd it's very important.\n\n1201\n01:08:03,940 --> 01:08:06,528\n当然 人们还制定了其它的准则\nAnd there are all sorts of other disciplines people make\n\n1202\n01:08:07,376 --> 01:08:09,616\n来操作栈帧之类的东西\nwith frames and things like that of some sort,\n\n1203\n01:08:10,190 --> 01:08:11,392\n这些准则中 那些不再需要的东西\nwhere you save all sorts of junk\n\n1204\n01:08:11,408 --> 01:08:12,640\n也需要保存并恢复\nyou're not going to need later and restore it\n\n1205\n01:08:12,672 --> 01:08:15,260\n因为从某种意义上来说 这样做更容易些\nbecause, in some sense, it's easier to do that.\n\n1206\n01:08:15,830 --> 01:08:17,408\n但这会带来各种灾难\nThat's going to lead to various disasters,\n\n1207\n01:08:18,592 --> 01:08:20,256\n我们稍后就会见识一些\nwhich we'll see a little later.\n\n1208\n01:08:21,440 --> 01:08:24,240\n只保存那些你稍后需要的值 这很关键\nIt's crucial to save exactly what you're going to need later.\n\n1209\n01:08:26,890 --> 01:08:28,016\n这是非常重要的理念\nIt's an important idea.\n\n1210\n01:08:29,872 --> 01:08:33,360\n无论谁保存了一个值 都应该由他来恢复\nAnd the responsibility of that is whoever saves something\n\n1211\n01:08:33,760 --> 01:08:35,328\n因为他需要这个值\nis the guy who restores it, because he needs it.\n\n1212\n01:08:36,930 --> 01:08:38,544\n在这样的准则中\nAnd in such discipline,\n\n1213\n01:08:38,864 --> 01:08:40,768\n你可以发现哪些数据是不必要的\nyou can see what things are unnecessary,\n\n1214\n01:08:43,456 --> 01:08:44,736\n哪些操作又是不重要的\noperations that are unimportant.\n\n1215\n01:08:47,150 --> 01:08:50,400\n我还想告诉你们\nNow, one other thing I want to tell you about is very simple\n\n1216\n01:08:51,664 --> 01:08:54,672\n当然 你们看到的并不是全部的图景\nis that, of course, the picture you see is not the whole picture.\n\n1217\n01:08:55,350 --> 01:08:56,688\n假设我的系统中\nSupposing I had systems\n\n1218\n01:08:56,800 --> 01:09:01,520\n具有像CAR、CDR、CONS这样的运算\nhad things like other operations, CAR, CDR, CONS,\n\n1219\n01:09:03,536 --> 01:09:05,600\n或者创建一个向量\nbuilding a vector\n\n1220\n01:09:05,888 --> 01:09:07,328\n并引用它的第N个元素\nand referencing the nth element of it,\n\n1221\n01:09:08,304 --> 01:09:09,216\n等等运算\nor things like that.\n\n1222\n01:09:10,400 --> 01:09:13,600\n然而 就在这个层次的细节来说\nWell, at this level of detail, whatever it is,\n\n1223\n01:09:13,872 --> 01:09:17,856\n我们可以在数据通路中把它们视为基本运算\nwe can conceptualize those as primitive operations in the datapath.\n\n1224\n01:09:18,752 --> 01:09:21,952\n换句话说 我们可以认为 有一台机器\nIn other words, we could say that some machine that, for example, has\n\n1225\n01:09:22,320 --> 01:09:24,112\n包含了APPEND机器\nhas the append machine,\n\n1226\n01:09:24,208 --> 01:09:26,464\n它通过(CONS (CAR X)\nwhich has to do cons of the CAR of x\n\n1227\n01:09:26,640 --> 01:09:29,808\n(APPEND (CDR X) Y)来实现\nwith the append of the CDR of x and y,\n\n1228\n01:09:29,888 --> 01:09:33,184\n哦 天啊 这就跟阶乘机器有相同的结构\nwell, gee, that's exactly the same as the factorial structure.\n\n1229\n01:09:33,630 --> 01:09:35,296\n当然 它有相同的结构\nWell, it's got about the same structure.\n\n1230\n01:09:36,544 --> 01:09:37,270\n我们有什么呢？\nAnd what do we have?\n\n1231\n01:09:37,270 --> 01:09:39,392\n我们有某种东西 其中有\nWe have some sort of things in it\n\n1232\n01:09:39,760 --> 01:09:42,480\n诸如X、Y之类的寄存器\nwhich may be registers, x and y,\n\n1233\n01:09:42,510 --> 01:09:45,120\n有时X会移动到Y中\nand then x has to somehow move to y sometimes,\n\n1234\n01:09:45,280 --> 01:09:46,750\n或者X会取得Y的值\nx has to get the value of y.\n\n1235\n01:09:46,930 --> 01:09:50,112\n我们或许要需要能够进行CONS运算\nAnd then we may have to be able to do something which is a cons.\n\n1236\n01:09:51,700 --> 01:09:57,744\n我记不清这个系统中是否需要这样的东西\nI don't remember if I need to like this is in this system,\n\n1237\n01:09:57,760 --> 01:10:01,100\n但CONS有点类似于减法器或加法器之类的东西\nbut cons is sort of like subtract or add or something.\n\n1238\n01:10:01,420 --> 01:10:02,704\n它把两个东西结合起来\nIt combines two things,\n\n1239\n01:10:02,736 --> 01:10:04,272\n然后产生一个序对\nproducing a thing which is the cons,\n\n1240\n01:10:04,512 --> 01:10:06,496\n然后会把输出结果送入到这里\nwhich we may then think goes into there.\n\n1241\n01:10:07,600 --> 01:10:09,728\n可能还有一个叫做CAR的组件\nAnd then maybe a thing called the CAR,\n\n1242\n01:10:12,880 --> 01:10:16,224\n它的结果是 -- 某个东西的CAR部分\nwhich will produce-- I can get the CAR or something.\n\n1243\n01:10:16,920 --> 01:10:19,552\n我还可以取得某物的CDR部分 等等\nAnd maybe I can get the CDR of something, and so on.\n\n1244\n01:10:20,150 --> 01:10:22,304\n但我们不应该害怕这么说\nBut we shouldn't be too afraid of saying things this way,\n\n1245\n01:10:22,928 --> 01:10:24,240\n因为最坏的情况不过\nbecause the worst that could happen\n\n1246\n01:10:24,944 --> 01:10:26,416\n当我们打开CONS后\nis if we open up cons,\n\n1247\n01:10:27,312 --> 01:10:29,824\n会发现其中存在某台机器\nwhat we're going to find is some machine.\n\n1248\n01:10:31,888 --> 01:10:34,448\nCONS可能会与CAR和CDR有所重叠\nAnd cons may in fact overlap with CAR and CDR, and it always does,\n\n1249\n01:10:35,504 --> 01:10:38,128\n就像加法和减法有所重叠一样\nin the same way that plus and minus overlap,\n\n1250\n01:10:38,576 --> 01:10:39,856\n它们本质上都是一样的\nand really the same business.\n\n1251\n01:10:41,210 --> 01:10:42,608\nCONS、CAR和CDR将会有所重叠\nCONS, CAR, and CDR are going to overlap,\n\n1252\n01:10:42,624 --> 01:10:44,528\n我们会发现其中有小型控制器\nand we're going to find a little controller,\n\n1253\n01:10:45,504 --> 01:10:46,544\n小型的数据通路\na little datapath,\n\n1254\n01:10:48,032 --> 01:10:49,648\n其中还有一些寄存器\nwhich may have some registers in it,\n\n1255\n01:10:50,000 --> 01:10:52,864\n一些其它的像这样的东西\nsome stuff like that.\n\n1256\n01:10:53,300 --> 01:10:54,416\n并且 也许在这之中\nAnd maybe inside it,\n\n1257\n01:10:54,432 --> 01:10:56,160\n可能也有无穷的部分\nthere may also be an infinite part,\n\n1258\n01:10:56,464 --> 01:10:58,704\n又或者是半无穷的 之类的\na part that's semi-infinite or something,\n\n1259\n01:10:58,816 --> 01:11:00,656\n这些都是统一的东西\nwhich is a lot of very uniform stuff,\n\n1260\n01:11:00,960 --> 01:11:02,030\n也就是我们所谓的“内存”\nwhich we'll call memory.\n\n1261\n01:11:06,570 --> 01:11:08,832\n有限的内存也能无穷地存储 对此我一点也不吃惊\nAnd I wouldn't be so horrified if that were the way it works.\n\n1262\n01:11:09,330 --> 01:11:11,072\n实际上它就是这样的 我们之后就会了解\nIn fact, it does, and we'll talk about that later.\n\n1263\n01:11:13,320 --> 01:11:14,570\n那么 有什么疑问么？\nSo are there any questions?\n\n1264\n01:11:24,340 --> 01:11:25,808\n天啊！你们都一言不发\nGee, what an unquestioning audience.\n\n1265\n01:11:28,670 --> 01:11:30,330\n假设我说得都是谎言吧！\nSuppose I tell you a horrible pile of lies.\n\n1266\n01:11:39,690 --> 01:11:40,384\n好吧\nOK.\n\n1267\n01:11:41,990 --> 01:11:42,520\n谢谢大家\nWell, thank you.\n\n1268\n01:11:42,520 --> 01:11:43,280\n我们下课吧！\nLet's take our break.\n\n1269\n01:11:44,230 --> 01:11:48,780\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n1270\n01:11:48,780 --> 01:11:55,152\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n"
  },
  {
    "path": "SrtCN/lec9b.eng.srt",
    "content": "﻿1\n00:00:15,840 --> 00:00:29,730\nPROFESSOR: Well, I hope you appreciate that we have inducted you into some real magic, the magic of building languages, really building new languages.\n\n2\n00:00:29,730 --> 00:00:30,430\nWhat have we looked at?\n\n3\n00:00:30,430 --> 00:00:42,360\nWe've looked at an Escher picture language: this language invented by Peter Henderson.\n\n4\n00:00:42,360 --> 00:00:46,260\nWe looked at digital logic language.\n\n5\n00:00:53,260 --> 00:00:53,570\nLet's see.\n\n6\n00:00:53,570 --> 00:00:55,360\nWe've looked at the query language.\n\n7\n00:00:59,700 --> 00:01:08,250\nAnd the thing you should realize is, even though these were toy examples, they really are the kernels of really useful things.\n\n8\n00:01:08,250 --> 00:01:23,300\nSo, for instance, the Escher picture language was taken by Henry Wu, who's a student at MIT, and developed into a real language for laying out PC boards based just on extending those structures.\n\n9\n00:01:23,300 --> 00:01:33,460\nAnd the digital logic language, Jerry mentioned when he showed it to you, was really extended to be used as the basis for a simulator that was used to design a real computer.\n\n10\n00:01:33,460 --> 00:01:37,510\nAnd the query language, of course, is kind of the germ of prologue.\n\n11\n00:01:37,510 --> 00:01:41,080\nSo we built all of these languages, they're all based on LISP.\n\n12\n00:01:43,630 --> 00:01:48,820\nA lot of people ask what particular problems is LISP good for solving for?\n\n13\n00:01:48,820 --> 00:02:01,470\nThe answer is LISP is not good for solving any particular problems. What LISP is good for is constructing within it the right language to solve the problems you want to solve, and that's how you should think about it.\n\n14\n00:02:01,470 --> 00:02:04,326\nSo all of these languages were based on LISP.\n\n15\n00:02:04,326 --> 00:02:07,270\nNow, what's LISP based on?\n\n16\n00:02:07,270 --> 00:02:07,920\nWhere's that come from?\n\n17\n00:02:07,920 --> 00:02:09,400\nWell, we looked at that too.\n\n18\n00:02:12,740 --> 00:02:25,810\nWe looked at the meta-circular evaluator and said well, LISP is based on LISP.\n\n19\n00:02:25,810 --> 00:02:29,950\nAnd when we start looking at that, we've got to do some real magic, right?\n\n20\n00:02:29,950 --> 00:02:31,660\nSo what does that mean, right?\n\n21\n00:02:31,660 --> 00:02:47,470\nWhy operators, and fixed points, and the idea that what this means is that LISP is somehow the fixed-point equation for this funny set of things which are defined in terms of themselves.\n\n22\n00:02:47,470 --> 00:02:49,070\nNow, it's real magic.\n\n23\n00:02:49,070 --> 00:02:54,250\nWell, today, for a final piece of magic, we're going to make all the magic go away.\n\n24\n00:03:06,430 --> 00:03:09,770\nWe already know how to do that.\n\n25\n00:03:09,770 --> 00:03:15,500\nThe idea is, we're going to take the register machine architecture and show how to implement LISP on terms of that.\n\n26\n00:03:15,500 --> 00:03:24,800\nAnd, remember, the idea of the register machine is that there's a fixed and finite part of the machine.\n\n27\n00:03:24,800 --> 00:03:30,510\nThere's a finite-state controller, which does some particular thing with a particular amount of hardware.\n\n28\n00:03:30,510 --> 00:03:33,550\nThere are particular data paths: the operation the machine does.\n\n29\n00:03:33,550 --> 00:03:42,060\nAnd then, in order to implement recursion and sustain the illusion of infinity, there's some large amount of memory, which is the stack.\n\n30\n00:03:42,060 --> 00:03:49,850\nSo, if we implement LISP in terms of a register machine, then everything ought to become, at this point, completely concrete.\n\n31\n00:03:49,850 --> 00:03:51,650\nAll the magic should go away.\n\n32\n00:03:51,650 --> 00:04:04,720\nAnd, by the end of this talk, I want you get the feeling that, as opposed to this very mysterious meta-circular evaluator, that a LISP evaluator really is something that's concrete enough that you can hold in the palm of your hand.\n\n33\n00:04:04,720 --> 00:04:09,546\nYou should be able to imagine holding a LISP interpreter there.\n\n34\n00:04:09,546 --> 00:04:10,950\nAll right, how are we going to do this?\n\n35\n00:04:10,950 --> 00:04:13,960\nWe already have all the ingredients.\n\n36\n00:04:13,960 --> 00:04:28,210\nSee, what you learned last time from Jerry is how to take any particular couple of LISP procedures and hand-translate them into something that runs on a register machine.\n\n37\n00:04:28,210 --> 00:04:39,120\nSo, to implement all of LISP on a register machine, all we have to do is take the particular procedures that are the meta-circular evaluator and hand-translate them for a register machine.\n\n38\n00:04:39,120 --> 00:04:42,320\nAnd that does all of LISP, right?\n\n39\n00:04:42,320 --> 00:04:45,380\nSo, in principle, we already know how to do this.\n\n40\n00:04:45,380 --> 00:04:54,670\nAnd, indeed, it's going to be no different, in kind, from translating, say, recursive factorial or recursive Fibonacci.\n\n41\n00:04:54,670 --> 00:04:56,840\nIt's just bigger and there's more of it.\n\n42\n00:04:56,840 --> 00:05:01,730\nSo it'd just be more details, but nothing really conceptually new.\n\n43\n00:05:01,730 --> 00:05:14,810\nAll right, also, when we've done that, and the thing is completely explicit, and we see how to implement LISP in terms of the actual sequential register operations, that's going to be our final most explicit model of LISP in this course.\n\n44\n00:05:14,810 --> 00:05:16,950\nAnd, remember, that's a progression through this course.\n\n45\n00:05:16,950 --> 00:05:20,370\nWe started out with substitution, which is sort of like algebra.\n\n46\n00:05:20,370 --> 00:05:26,390\nAnd then we went to the environment model, which talked about the actual frames and how they got linked together.\n\n47\n00:05:26,390 --> 00:05:31,080\nAnd then we made that more concrete in the meta-circular evaluator.\n\n48\n00:05:31,080 --> 00:05:34,360\nThere are things the meta-circular evaluator doesn't tell us.\n\n49\n00:05:34,360 --> 00:05:36,090\nYou should realize that.\n\n50\n00:05:36,090 --> 00:05:47,210\nFor instance, it left unanswered the question of how a procedure, like recursive factorial here , somehow takes space that grows.\n\n51\n00:05:47,210 --> 00:05:56,760\nOn the other hand, a procedure which also looks syntactically recursive, called fact-iter, somehow doesn't take space.\n\n52\n00:05:56,760 --> 00:06:01,960\nWe justify that it doesn't need to take space by showing the substitution model.\n\n53\n00:06:01,960 --> 00:06:12,520\nBut we didn't really say how it happens that the machine manages to do that, that that has to do with the details of how arguments are passed to procedures.\n\n54\n00:06:12,520 --> 00:06:23,510\nAnd that's the thing we didn't see in the meta-circular evaluator precisely because the way arguments got passed to procedures in this LISP depended on the way arguments got passed to procedures in this LISP.\n\n55\n00:06:26,070 --> 00:06:30,740\nBut, now, that's going to become extremely explicit.\n\n56\n00:06:30,740 --> 00:06:31,230\nOK.\n\n57\n00:06:31,230 --> 00:06:43,250\nWell, before going on to the evaluator, let me just give you a sense of what a whole LISP system looks like so you can see the parts we're going to talk about and the parts we're not going to talk about.\n\n58\n00:06:43,250 --> 00:06:52,525\nLet's see, over here is a happy LISP user, and the LISP user is talking to something called the reader.\n\n59\n00:07:00,360 --> 00:07:19,210\nThe reader's job in life is to take characters from the user and turn them into data structures in something called a list structure memory.\n\n60\n00:07:29,783 --> 00:07:42,340\nAll right, so the reader is going to take symbols, parentheses, and A's and B's, and ones and threes that you type in, and turn these into actual list structure: pairs, and pointers, and things.\n\n61\n00:07:42,340 --> 00:07:45,850\nAnd so, by the time evaluator is going, there are no characters in the world.\n\n62\n00:07:45,850 --> 00:07:56,280\nAnd, of course, in more modern list systems, there's sort of a big morass here that might sit between the user and the reader: Windows systems, and top levels, and mice, and all kinds of things.\n\n63\n00:07:56,280 --> 00:07:59,590\nBut conceptually, characters are coming in.\n\n64\n00:07:59,590 --> 00:08:17,090\nAll right, the reader transforms these into pointers to stuff in this memory, and that's what the evaluator sees, OK?\n\n65\n00:08:17,090 --> 00:08:19,780\nThe evaluator has a bunch of helpers.\n\n66\n00:08:19,780 --> 00:08:23,080\nIt has all possible primitive operators you might want.\n\n67\n00:08:23,080 --> 00:08:35,960\nSo there's a completely separate box, a floating point unit, or all sorts of things, which do the primitive operators.\n\n68\n00:08:35,960 --> 00:08:42,080\nAnd, if you want more special primitives, you build more primitive operators, but they're separate from the evaluator.\n\n69\n00:08:42,080 --> 00:08:47,400\nThe evaluator finally gets an answer and communicates that to the printer.\n\n70\n00:08:50,780 --> 00:09:05,540\nAnd now, the printer's job in life is to take this list structure coming from the evaluator, and turn it back into characters, and communicate them to the user through whatever interface there is.\n\n71\n00:09:08,050 --> 00:09:08,810\nOK.\n\n72\n00:09:08,810 --> 00:09:12,670\nWell, today, what we're going to talk about is this evaluator.\n\n73\n00:09:12,670 --> 00:09:19,440\nThe primitive operators have nothing particular to do with LISP, they're however you like to implement primitive operations.\n\n74\n00:09:19,440 --> 00:09:24,420\nThe reader and printer are actually complicated, but we're not going to talk about them.\n\n75\n00:09:24,420 --> 00:09:29,900\nThey sort of have to do with details of how you might build up list structure from characters.\n\n76\n00:09:29,900 --> 00:09:32,490\nSo that is a long story, but we're not going to talk about it.\n\n77\n00:09:32,490 --> 00:09:36,930\nThe list structure memory, we'll talk about next time.\n\n78\n00:09:36,930 --> 00:09:46,295\nSo, pretty much, except for the details of reading and printing, the only mystery that's going to be left after you see the evaluator is how you build list structure on conventional memories.\n\n79\n00:09:46,295 --> 00:09:50,580\nBut we'll worry about that next time too.\n\n80\n00:09:50,580 --> 00:09:51,830\nOK.\n\n81\n00:09:53,350 --> 00:09:56,110\nWell, let's start talking about the evaluator.\n\n82\n00:09:56,110 --> 00:10:01,120\nThe one that we're going to show you, of course, is not, I think, nothing special about it.\n\n83\n00:10:01,120 --> 00:10:04,810\nIt's just a particular register machine that runs LISP.\n\n84\n00:10:04,810 --> 00:10:09,890\nAnd it has seven registers, and here are the seven registers.\n\n85\n00:10:09,890 --> 00:10:18,370\nThere's a register, called EXP, and its job is to hold the expression to be evaluated.\n\n86\n00:10:18,370 --> 00:10:26,550\nAnd by that, I mean it's going to hold a pointer to someplace in list structure memory that holds the expression to be evaluated.\n\n87\n00:10:26,550 --> 00:10:34,070\nThere's a register, called ENV, which holds the environment in which this expression is to be evaluated.\n\n88\n00:10:34,070 --> 00:10:34,940\nAnd, again, I made a pointer.\n\n89\n00:10:34,940 --> 00:10:38,240\nThe environment is some data structure.\n\n90\n00:10:38,240 --> 00:10:44,630\nThere's a register, called FUN, which will hold the procedure to be applied when you go to apply a procedure.\n\n91\n00:10:44,630 --> 00:10:50,630\nA register, called ARGL, which wants the list of evaluated arguments.\n\n92\n00:10:50,630 --> 00:10:53,140\nWhat you can start seeing here is the basic structure of the evaluator.\n\n93\n00:10:53,140 --> 00:10:54,490\nRemember how evaluators work.\n\n94\n00:10:54,490 --> 00:11:03,480\nThere's a piece that takes expressions and environments, and there's a piece that takes functions, or procedures and arguments.\n\n95\n00:11:03,480 --> 00:11:07,740\nAnd going back and forth around here is the eval/apply loop.\n\n96\n00:11:07,740 --> 00:11:10,270\nSo those are the basic pieces of the eval and apply.\n\n97\n00:11:10,270 --> 00:11:11,610\nThen there's some other things, there's continue.\n\n98\n00:11:11,610 --> 00:11:19,000\nYou just saw before how the continue register is used to implement recursion and stack discipline.\n\n99\n00:11:19,000 --> 00:11:24,190\nThere's a register that's going to hold the result of some evaluation.\n\n100\n00:11:24,190 --> 00:11:37,150\nAnd then, besides that, there's one temporary register, called UNEV, which typically, in the evaluator, is going to be used to hold temporary pieces of the expression you're working on, which you haven't gotten around to evaluate yet, right?\n\n101\n00:11:37,150 --> 00:11:40,646\nSo there's my machine: a seven-register machine.\n\n102\n00:11:40,646 --> 00:11:48,480\nAnd, of course, you might want to make a machine with a lot more registers to get better performance, but this is just a tiny, minimal one.\n\n103\n00:11:48,480 --> 00:11:49,780\nWell, how about the data paths?\n\n104\n00:11:49,780 --> 00:11:55,100\nThis machine has a lot of special operations for LISP.\n\n105\n00:11:55,100 --> 00:12:00,120\nSo, here are some typical data paths.\n\n106\n00:12:00,120 --> 00:12:06,710\nA typical one might be, oh, assign to the VAL register the contents of the EXP register.\n\n107\n00:12:06,710 --> 00:12:11,900\nIn terms of those diagrams you saw, that's a little button on some arrow.\n\n108\n00:12:11,900 --> 00:12:14,040\nHere's a more complicated one.\n\n109\n00:12:14,040 --> 00:12:23,850\nIt says branch, if the thing in the expression register is a conditional to some label here, called the ev-conditional.\n\n110\n00:12:23,850 --> 00:12:26,230\nAnd you can imagine this implemented in a lot of different ways.\n\n111\n00:12:26,230 --> 00:12:36,610\nYou might imagine this conditional test as a special purpose sub-routine, and conditional might be represented as some data abstraction that you don't care about at this level of detail.\n\n112\n00:12:36,610 --> 00:12:37,980\nSo that might be done as a sub-routine.\n\n113\n00:12:37,980 --> 00:12:45,350\nThis might be a machine with hardware-types, and conditional might be testing some bits for a particular code.\n\n114\n00:12:45,350 --> 00:12:50,190\nThere are all sorts of ways that's beneath the level of abstraction we're looking at.\n\n115\n00:12:50,190 --> 00:12:56,840\nAnother kind of operation, and there are a lot of different operations assigned to EXP, the first clause of what's in EXP.\n\n116\n00:12:56,840 --> 00:12:59,260\nThis might be part of processing a conditional.\n\n117\n00:12:59,260 --> 00:13:04,470\nAnd, again, first clause is some selector whose details we don't care about.\n\n118\n00:13:04,470 --> 00:13:12,170\nAnd you can, again, imagine that as a sub-routine which'll do some list operations, or you can imagine that as something that's built directly into hardware.\n\n119\n00:13:12,170 --> 00:13:19,740\nThe reason I keep saying you can imagine it built directly into hardware is even though there are a lot of operations, there are still a fixed number of them.\n\n120\n00:13:19,740 --> 00:13:22,370\nI forget how many, maybe 150.\n\n121\n00:13:22,370 --> 00:13:26,400\nSo, it's plausible to think of building these directly into hardware.\n\n122\n00:13:26,400 --> 00:13:28,500\nHere's a more complicated one.\n\n123\n00:13:28,500 --> 00:13:31,710\nYou can see this has to do with looking up the values of variables.\n\n124\n00:13:31,710 --> 00:13:42,850\nIt says assign to the VAL register the result of looking up the variable value of some particular expression, which, in this case, is supposed to be a variable in some environment.\n\n125\n00:13:42,850 --> 00:13:52,240\nAnd this'll be some operation that searches through the environment structure, however it is represented, and goes and looks up that variable.\n\n126\n00:13:52,240 --> 00:13:55,790\nAnd, again, that's below the level of detail that we're thinking about.\n\n127\n00:13:55,790 --> 00:14:00,380\nThis has to do with the details of the data structures for representing environments.\n\n128\n00:14:00,380 --> 00:14:05,940\nBut, anyway, there is this fixed and finite number of operations in the register machine.\n\n129\n00:14:08,500 --> 00:14:11,720\nWell, what's its overall structure?\n\n130\n00:14:11,720 --> 00:14:14,930\nThose are some typical operations.\n\n131\n00:14:14,930 --> 00:14:22,890\nRemember what we have to do, we have to take the meta-circular evaluator-- and here's a piece of the meta-circular evaluator.\n\n132\n00:14:22,890 --> 00:14:28,310\nThis is the one using abstract syntax that's in the book.\n\n133\n00:14:28,310 --> 00:14:33,500\nIt's a little bit different from the one that Jerry shows you.\n\n134\n00:14:33,500 --> 00:14:48,560\nAnd the main thing to remember about the evaluator is that it's doing some sort of case analysis on the kinds of expressions: so if it's either self-evaluated, or quoted, or whatever else.\n\n135\n00:14:48,560 --> 00:14:55,750\nAnd then, in the general case where the expression it's looking at is an application, there's some tricky recursions going on.\n\n136\n00:14:55,750 --> 00:15:05,880\nFirst of all, eval has to call itself both to evaluate the operator and to evaluate all the operands.\n\n137\n00:15:05,880 --> 00:15:12,270\nSo there's this sort of red recursion of values walking down the tree that's really the easy recursion.\n\n138\n00:15:12,270 --> 00:15:14,750\nThat's just a val walking down this tree of expressions.\n\n139\n00:15:14,750 --> 00:15:16,600\nThen, in the evaluator, there's a hard recursion.\n\n140\n00:15:16,600 --> 00:15:18,200\nThere's the red to green.\n\n141\n00:15:18,200 --> 00:15:19,450\nEval calls apply.\n\n142\n00:15:22,470 --> 00:15:30,370\nThat's the case where evaluating a procedure or argument reduces to applying the procedure to the list of arguments.\n\n143\n00:15:30,370 --> 00:15:31,700\nAnd then, apply comes over here.\n\n144\n00:15:34,770 --> 00:15:44,560\nApply takes a procedure and arguments and, in the general case where there's a compound procedure, apply goes around and green calls red.\n\n145\n00:15:44,560 --> 00:15:48,170\nApply comes around and calls eval again.\n\n146\n00:15:48,170 --> 00:15:56,605\nEval's the body of the procedure in the result of extending the environment with the parameters of the procedure by binding the arguments.\n\n147\n00:15:59,620 --> 00:16:05,980\nExcept in the primitive case, where it just calls something else primitive-apply, which is not really the business of the evaluator.\n\n148\n00:16:05,980 --> 00:16:17,186\nSo this sort of red to green, to red to green, that's the eval/apply loop, and that's the thing that we're going to want to see in the evaluator.\n\n149\n00:16:19,840 --> 00:16:19,970\nAll right.\n\n150\n00:16:19,970 --> 00:16:27,470\nWell, it won't surprise you at all that the two big pieces of this evaluator correspond to eval and apply.\n\n151\n00:16:27,470 --> 00:16:32,110\nThere's a piece called eval-dispatch, and a piece called apply-dispatch.\n\n152\n00:16:32,110 --> 00:16:41,870\nAnd, before we get into the details of the code, the way to understand this is to think, again, in terms of these pieces of the evaluator having contracts with the rest of the world.\n\n153\n00:16:41,870 --> 00:16:45,780\nWhat do they do from the outside before getting into the grungy details?\n\n154\n00:16:45,780 --> 00:16:51,300\nWell, the contract for eval-dispatch-- remember, it corresponds to eval.\n\n155\n00:16:51,300 --> 00:16:54,100\nIt's got to evaluate an expression in an environment.\n\n156\n00:16:54,100 --> 00:17:03,640\nSo, in particular, what this one is going to do, eval-dispatch will assume that, when you call it, that the expression you want to evaluate is in the EXP register.\n\n157\n00:17:03,640 --> 00:17:09,569\nThe environment in which you want the evaluation to take place is in the ENV register.\n\n158\n00:17:09,569 --> 00:17:13,880\nAnd continue tells you the place where the machine should go next when the evaluation is done.\n\n159\n00:17:17,440 --> 00:17:26,619\nEval-dispatch's contract is that it'll actually perform that evaluation, and, at the end of which, it'll end up at the place specified by continue.\n\n160\n00:17:26,619 --> 00:17:29,950\nThe result of the evaluation will be in the VAL register.\n\n161\n00:17:29,950 --> 00:17:35,230\nAnd it just warns you, it makes no promises about what happens to the registers.\n\n162\n00:17:35,230 --> 00:17:37,490\nAll other registers might be destroyed.\n\n163\n00:17:37,490 --> 00:17:41,790\nSo, there's one piece, OK?\n\n164\n00:17:41,790 --> 00:17:54,540\nTogether, the pieces, apply-dispatch that corresponds to apply, it's got to apply a procedure to some arguments, so it assumes that this register, ARGL, contains a list of the evaluated arguments.\n\n165\n00:17:54,540 --> 00:17:57,220\nFUN contains the procedure.\n\n166\n00:17:57,220 --> 00:18:01,055\nThose correspond to the arguments to the apply procedure in the meta-circular evaluator.\n\n167\n00:18:03,970 --> 00:18:21,840\nAnd apply, in this particular evaluator, we're going to use a discipline which says the place the machine should go to next when apply is done is, at the moment apply-dispatch is called at the top of the stack, that's just discipline for the way this particular machine's organized.\n\n168\n00:18:21,840 --> 00:18:23,950\nAnd now apply's contract is given all that.\n\n169\n00:18:23,950 --> 00:18:25,540\nIt'll perform the application.\n\n170\n00:18:25,540 --> 00:18:28,890\nThe result of that application will end up in VAL.\n\n171\n00:18:28,890 --> 00:18:31,120\nThe stack will be popped.\n\n172\n00:18:31,120 --> 00:18:35,110\nAnd, again, the contents of all the other registers may be destroyed, all right?\n\n173\n00:18:35,110 --> 00:18:39,760\nSo that's the basic organization of this machine.\n\n174\n00:18:39,760 --> 00:18:42,700\nLet's break for a little bit and see if there are any questions, and then we'll do a real example.\n\n175\n00:19:47,850 --> 00:20:03,400\nWell, let's take the register machine now, and actually step through, and really, in real detail, so you see completely concrete how some expressions are evaluated, all right?\n\n176\n00:20:03,400 --> 00:20:06,435\nSo, let's start with a very simple expression.\n\n177\n00:20:09,620 --> 00:20:13,320\nLet's evaluate the expression 1.\n\n178\n00:20:18,880 --> 00:20:23,085\nAnd we need an environment, so let's imagine that somewhere there's an environment, we'll call it E,0.\n\n179\n00:20:30,260 --> 00:20:38,360\nAnd just, since we'll use these later, we obviously don't really need anything to evaluate 1.\n\n180\n00:20:38,360 --> 00:20:49,140\nBut, just for reference later, let's assume that E,0 has in it an X that's bound to 3 and a Y that's bound to 4, OK?\n\n181\n00:20:49,140 --> 00:21:03,560\nAnd now what we're going to do is we're going to evaluate 1 in this environment, and so the ENV register has a pointer to this environment, E,0, all right?\n\n182\n00:21:03,560 --> 00:21:05,650\nSo let's watch that thing go.\n\n183\n00:21:05,650 --> 00:21:08,260\nWhat I'm going to do is step through the code.\n\n184\n00:21:08,260 --> 00:21:10,080\nAnd, let's see, I'll be the controller.\n\n185\n00:21:10,080 --> 00:21:16,830\nAnd now what I need, since this gets rather complicated, is a very little execution unit.\n\n186\n00:21:16,830 --> 00:21:22,624\nSo here's the execution unit, OK?\n\n187\n00:21:22,624 --> 00:21:23,874\nOK.\n\n188\n00:21:27,088 --> 00:21:28,590\nOK.\n\n189\n00:21:28,590 --> 00:21:30,690\nAll right, now we're going to start.\n\n190\n00:21:30,690 --> 00:21:33,660\nWe're going to start the machine at eval-dispatch, right?\n\n191\n00:21:33,660 --> 00:21:36,120\nThat's the beginning of this.\n\n192\n00:21:36,120 --> 00:21:42,010\nEval-dispatch is going to look at the expression in dispatch, just like eval where we look at the very first thing.\n\n193\n00:21:42,010 --> 00:21:47,950\nWe branch on whether or not this expression is self-evaluating.\n\n194\n00:21:47,950 --> 00:21:57,040\nSelf-evaluating is some abstraction we put into the machine-- it's going to be true for numbers-- to a place called ev-self-eval, right?\n\n195\n00:21:57,040 --> 00:22:02,780\nSo me, being the controller, looks at ev-self-eval, so we'll go over to there.\n\n196\n00:22:02,780 --> 00:22:15,220\nEv-self-eval says fine, assign to val whatever is in the expression unit, OK?\n\n197\n00:22:15,220 --> 00:22:32,050\nAnd I have a bug because what I didn't do when I initialized this machine is also say what's supposed to happen when it's done, so I should have started out the machine with done being in the continue register, OK?\n\n198\n00:22:32,050 --> 00:22:33,640\nSo we assign to VAL.\n\n199\n00:22:33,640 --> 00:22:40,000\nAnd now go to fetch of continue, and now change-- OK.\n\n200\n00:22:40,000 --> 00:22:42,160\nOK, let's try something harder.\n\n201\n00:22:42,160 --> 00:22:56,710\nLet's reset the machine here, and we'll put in the expression register, X, OK?\n\n202\n00:22:56,710 --> 00:22:59,610\nStart again at eval-dispatch.\n\n203\n00:22:59,610 --> 00:23:01,690\nCheck, is it self-evaluating?\n\n204\n00:23:01,690 --> 00:23:02,650\nNo.\n\n205\n00:23:02,650 --> 00:23:04,630\nIs it a variable?\n\n206\n00:23:04,630 --> 00:23:05,560\nYes.\n\n207\n00:23:05,560 --> 00:23:08,380\nWe go off to ev-variable.\n\n208\n00:23:08,380 --> 00:23:21,620\nIt says assign to VAL, look up the variable value in the expression register, OK?\n\n209\n00:23:21,620 --> 00:23:23,625\nGo to fetch of continue.\n\n210\n00:23:23,625 --> 00:23:24,875\nPROFESSOR: Done.\n\n211\n00:23:27,252 --> 00:23:28,950\nPROFESSOR: OK.\n\n212\n00:23:28,950 --> 00:23:29,430\nAll right.\n\n213\n00:23:29,430 --> 00:23:31,330\nWell, that's the basic idea.\n\n214\n00:23:31,330 --> 00:23:32,920\nThat's a simple operation of the machine.\n\n215\n00:23:32,920 --> 00:23:36,070\nNow, let's actually do something a little bit more interesting.\n\n216\n00:23:36,070 --> 00:23:49,678\nLet's look at the expression the sum of x and y.\n\n217\n00:23:49,678 --> 00:23:50,130\nOK.\n\n218\n00:23:50,130 --> 00:23:57,100\nAnd now we'll see how you start unrolling these expression trees, OK?\n\n219\n00:23:57,100 --> 00:24:00,645\nWell, start again at eval-dispatch, all right?\n\n220\n00:24:04,610 --> 00:24:06,060\nSelf-evaluating?\n\n221\n00:24:06,060 --> 00:24:06,810\nNo.\n\n222\n00:24:06,810 --> 00:24:07,280\nVariable?\n\n223\n00:24:07,280 --> 00:24:07,850\nNo.\n\n224\n00:24:07,850 --> 00:24:13,260\nAll the other special forms which I didn't write down, like quote, and lambda, and set, and whatever, it's none of those.\n\n225\n00:24:13,260 --> 00:24:19,970\nIt turns out to be an application, so we go off to ev-application, OK?\n\n226\n00:24:19,970 --> 00:24:25,580\nEv-application, remember what it's going to do overall.\n\n227\n00:24:25,580 --> 00:24:28,310\nIt is going to evaluate the operator.\n\n228\n00:24:28,310 --> 00:24:35,060\nIt's going to evaluate the arguments, and then it's going to go apply them.\n\n229\n00:24:35,060 --> 00:24:55,340\nSo, before we start, since we're being very literal, we'd better remember that, somewhere in this environment, it's linked to another environment in which plus is bound to the primitive procedure plus before we get an unknown variable in our machine.\n\n230\n00:24:55,340 --> 00:24:56,590\nOK, so we're at ev-application.\n\n231\n00:24:59,850 --> 00:25:07,920\nOK, assign to UNEV the operands of what's in the expression register, OK?\n\n232\n00:25:07,920 --> 00:25:09,230\nThose are the operands.\n\n233\n00:25:09,230 --> 00:25:12,916\nUNEV's a temporary register where we're going to save them.\n\n234\n00:25:12,916 --> 00:25:13,860\nPROFESSOR: I'm assigning.\n\n235\n00:25:13,860 --> 00:25:18,070\nPROFESSOR: Assign to x the operator.\n\n236\n00:25:18,070 --> 00:25:25,820\nNow, notice we've destroyed that expression in x, but the piece that we need is now in UNEV. OK.\n\n237\n00:25:25,820 --> 00:25:28,750\nNow, we're going to get set up to recursively evaluate the operator.\n\n238\n00:25:28,750 --> 00:25:31,565\nSave the continue register on the stack.\n\n239\n00:25:34,870 --> 00:25:36,120\nSave the environment.\n\n240\n00:25:40,520 --> 00:25:54,460\nSave UNEV. OK, assign to continue a label called eval-args.\n\n241\n00:26:01,400 --> 00:26:01,980\nNow, what have we done?\n\n242\n00:26:01,980 --> 00:26:04,380\nWe've set up for a recursive call.\n\n243\n00:26:04,380 --> 00:26:06,280\nWe're about to go to eval-dispatch.\n\n244\n00:26:06,280 --> 00:26:10,230\nWe've set up for a recursive call to eval-dispatch.\n\n245\n00:26:10,230 --> 00:26:11,020\nWhat did we do?\n\n246\n00:26:11,020 --> 00:26:27,120\nWe took the things we're going to need later, those operands that were in UNEV; the environment in which we're going to eventually have to, maybe, evaluate those operands; the place we eventually want to go to, which, in this case, was done; we've saved them on the stack.\n\n247\n00:26:27,120 --> 00:26:33,550\nThe reason we saved them on the stack is because eval-dispatch makes no promises about what registers it may destroy.\n\n248\n00:26:33,550 --> 00:26:35,020\nSo all that stuff is saved on the stack.\n\n249\n00:26:35,020 --> 00:26:37,380\nNow, we've set up eval-dispatch's contract.\n\n250\n00:26:37,380 --> 00:26:47,600\nThere's a new expression, which is the operator plus; a new environment, although, in this case, it's the same one; and a new place to go to when you're done, which is eval-args.\n\n251\n00:26:47,600 --> 00:26:48,130\nSo that's set up.\n\n252\n00:26:48,130 --> 00:26:50,890\nNow, we're going to go off to eval-dispatch.\n\n253\n00:26:50,890 --> 00:26:53,090\nHere we are back at eval-dispatch.\n\n254\n00:26:53,090 --> 00:26:54,490\nIt's not self-evaluating.\n\n255\n00:26:54,490 --> 00:27:00,260\nOh, it's a variable, so we'd better go off to ev-variable, right?\n\n256\n00:27:00,260 --> 00:27:02,880\nEv-variable is assigned to VAL.\n\n257\n00:27:02,880 --> 00:27:08,770\nLook up the variable value of the expression, OK?\n\n258\n00:27:08,770 --> 00:27:13,000\nSo VAL is the primitive procedure plus, OK?\n\n259\n00:27:13,000 --> 00:27:15,020\nAnd go to fetch of continue.\n\n260\n00:27:15,020 --> 00:27:15,660\nPROFESSOR: Eval-args.\n\n261\n00:27:15,660 --> 00:27:19,340\nPROFESSOR: Right, which is now eval-args not done.\n\n262\n00:27:19,340 --> 00:27:23,210\nSo we come back here at eval-args, and what do we do?\n\n263\n00:27:23,210 --> 00:27:32,900\nWe're going to restore the stuff that we saved, so we restore UNEV. And notice, there, it wasn't necessary, although, in general, it would be.\n\n264\n00:27:32,900 --> 00:27:35,430\nIt might be some arbitrary evaluation that happened.\n\n265\n00:27:35,430 --> 00:27:51,900\nWe restore ENV. OK, we assign to FUN fetch of VAL.\n\n266\n00:27:58,620 --> 00:28:04,340\nOK, now, we're going to go off and start evaluating some arguments.\n\n267\n00:28:04,340 --> 00:28:10,165\nWell, first thing we'd better do is save FUN because some arbitrary stuff might happen in that evaluation.\n\n268\n00:28:15,330 --> 00:28:25,460\nWe initialize the argument list. Assign to argl an empty argument list, and go to eval-arg-loop, OK?\n\n269\n00:28:25,460 --> 00:28:38,090\nAt eval-arg-loop, the idea of this is we're going to evaluate the pieces of the expressions that are in UNEV, one by one, and move them from unevaluated in UNEV to evaluated in the arg list, OK?\n\n270\n00:28:38,090 --> 00:28:39,340\nSo we save argl.\n\n271\n00:28:43,950 --> 00:28:53,960\nWe assign to x the first operand of the stuff in UNEV.\n\n272\n00:28:53,960 --> 00:28:55,890\nNow, we check and see if that was the last operand.\n\n273\n00:28:55,890 --> 00:28:59,190\nIn this case, it is not, all right?\n\n274\n00:28:59,190 --> 00:29:01,235\nSo we save the environment.\n\n275\n00:29:09,170 --> 00:29:13,500\nWe save UNEV because those are all things we might need later.\n\n276\n00:29:13,500 --> 00:29:15,800\nWe're going to need the environment to do some more evaluations.\n\n277\n00:29:15,800 --> 00:29:20,340\nWe're going to need UNEV to look at what the rest of those arguments were.\n\n278\n00:29:20,340 --> 00:29:24,040\nWe're going to assign continue a place called accumulate-args, or accumulate-arg.\n\n279\n00:29:30,898 --> 00:29:36,810\nOK, now, we've set up for another call to eval-dispatch, OK?\n\n280\n00:29:36,810 --> 00:29:41,090\nAll right, now, let me short-circuit this so we don't go through the details of eval-dispatch.\n\n281\n00:29:41,090 --> 00:29:51,320\nEval-dispatch's contract says I'm going to end up, the world will end up, with the value of evaluating this expression in this environment in the VAL register, and I'll end up there.\n\n282\n00:29:51,320 --> 00:29:58,010\nSo we short-circuit all of this, and a 3 ends up in VAL.\n\n283\n00:29:58,010 --> 00:30:02,110\nAnd, when we return from eval-dispatch, we're going to return to accumulate-arg.\n\n284\n00:30:02,110 --> 00:30:03,555\nPROFESSOR: Accumulate-arg.\n\n285\n00:30:03,555 --> 00:30:08,720\nPROFESSOR: With 3 in the VAL register, OK?\n\n286\n00:30:08,720 --> 00:30:10,650\nSo that short-circuited that evaluation.\n\n287\n00:30:10,650 --> 00:30:11,320\nNow, what do we do?\n\n288\n00:30:11,320 --> 00:30:28,650\nWe're going to go back and look at the rest of the arguments, so we restore UNEV. We restore ENV. We restore argl.\n\n289\n00:30:28,650 --> 00:30:29,170\nOne thing.\n\n290\n00:30:29,170 --> 00:30:31,290\nPROFESSOR: Oops! Parity error.\n\n291\n00:30:31,290 --> 00:30:33,465\n[LAUGHTER]\n\n292\n00:30:33,465 --> 00:30:34,905\nPROFESSOR: Restore argl.\n\n293\n00:30:41,650 --> 00:30:42,900\nPROFESSOR: OK.\n\n294\n00:30:45,570 --> 00:30:53,130\nOK, we assign to argl consing on fetch of the value register to what's in argl.\n\n295\n00:30:58,985 --> 00:31:11,516\nOK, we assign to UNEV the rest of the operands in fetch of UNEV, and we go back to eval-arg-loop.\n\n296\n00:31:11,516 --> 00:31:12,280\nPROFESSOR: Eval-arg-loop.\n\n297\n00:31:12,280 --> 00:31:13,530\nPROFESSOR: OK.\n\n298\n00:31:15,880 --> 00:31:19,340\nNow, we're about to do the next argument, so the first thing we do is save argl.\n\n299\n00:31:25,400 --> 00:31:37,140\nOK, we assign to x the first operand of fetch of UNEV. OK, we test and see if that's the last operand.\n\n300\n00:31:37,140 --> 00:31:47,446\nIn this case, it is, so we're going to go to a special place that says evaluate the last argument because, notice, after evaluating the argument, we don't need the environment any more.\n\n301\n00:31:47,446 --> 00:31:50,250\nThat's going to be the difference.\n\n302\n00:31:50,250 --> 00:32:06,900\nSo here, at eval-last-arg, which is assigned to accumulate-last-arg, now, we're set up again for eval-dispatch.\n\n303\n00:32:06,900 --> 00:32:08,620\nWe've got a place to go to when we're done.\n\n304\n00:32:08,620 --> 00:32:09,840\nWe've got an expression.\n\n305\n00:32:09,840 --> 00:32:11,330\nWe've got an environment.\n\n306\n00:32:11,330 --> 00:32:14,370\nOK, so we'll short-circuit the call to eval-dispatch.\n\n307\n00:32:14,370 --> 00:32:21,060\nAnd what'll happen is there's a y there, it's 4 in that environment, so VAL will end up with 4 in it.\n\n308\n00:32:21,060 --> 00:32:25,450\nAnd, then, we're going to end up at accumulate-last-arg, OK?\n\n309\n00:32:25,450 --> 00:32:30,150\nSo, at accumulate-last-arg, we restore argl.\n\n310\n00:32:41,490 --> 00:32:49,850\nWe assign to argl cons of fetch of the new value onto it, so we cons a 4 onto that.\n\n311\n00:32:49,850 --> 00:32:53,446\nWe restore what was saved in the function register.\n\n312\n00:32:53,446 --> 00:32:59,420\nAnd notice, in this case, it had not been destroyed, but, in general, it will be.\n\n313\n00:32:59,420 --> 00:33:02,850\nAnd now, we're ready to go off to apply-dispatch, all right?\n\n314\n00:33:02,850 --> 00:33:04,510\nSo we've just gone through the eval.\n\n315\n00:33:04,510 --> 00:33:09,580\nWe evaluated the argument, the operator, and the arguments, and now, we're about to apply them.\n\n316\n00:33:09,580 --> 00:33:17,481\nSo we come off to apply-dispatch here, OK?\n\n317\n00:33:17,481 --> 00:33:23,450\nWe come off to apply-dispatch, and we're going to check whether it's a primitive or a compound procedure.\n\n318\n00:33:23,450 --> 00:33:24,116\nPROFESSOR: Yes.\n\n319\n00:33:24,116 --> 00:33:24,830\nPROFESSOR: All right.\n\n320\n00:33:24,830 --> 00:33:29,790\nSo, in this case, it's a primitive procedure, and we go off to primitive-apply.\n\n321\n00:33:29,790 --> 00:33:40,940\nSo we go off to primitive-apply, and it says assign to VAL the result of applying primitive procedure of the function to the argument list.\n\n322\n00:33:40,940 --> 00:33:42,540\nPROFESSOR: I don't know how to add.\n\n323\n00:33:42,540 --> 00:33:43,995\nI'm just an execution unit.\n\n324\n00:33:43,995 --> 00:33:45,350\nPROFESSOR: Well, I don't know how to add either.\n\n325\n00:33:45,350 --> 00:33:48,360\nI'm just the evaluator, so we need a primitive operator.\n\n326\n00:33:48,360 --> 00:33:52,605\nLet's see, so the primitive operator, what's the sum of 3 and 4?\n\n327\n00:33:52,605 --> 00:33:53,205\nAUDIENCE: 7.\n\n328\n00:33:53,205 --> 00:33:54,580\nPROFESSOR: OK, 7.\n\n329\n00:33:54,580 --> 00:33:55,999\nPROFESSOR: Thank you.\n\n330\n00:33:58,837 --> 00:34:12,900\nPROFESSOR: Now, we restore continue, and we go to fetch of continue.\n\n331\n00:34:12,900 --> 00:34:13,880\nPROFESSOR: Done.\n\n332\n00:34:13,880 --> 00:34:14,929\nPROFESSOR: OK.\n\n333\n00:34:14,929 --> 00:34:18,659\nWell, that was in as much detail as you will ever see.\n\n334\n00:34:18,659 --> 00:34:21,590\nWe'll never do it in as much detail again.\n\n335\n00:34:21,590 --> 00:34:29,780\nOne very important thing to notice is that we just executed a recursive procedure, right?\n\n336\n00:34:29,780 --> 00:34:33,070\nThis whole thing, we used a stack and the evaluator was recursive.\n\n337\n00:34:33,070 --> 00:34:42,150\nA lot of people think the reason that you need a stack and recursion in an evaluator is because you might be evaluating recursive procedures like factorial or Fibonacci.\n\n338\n00:34:42,150 --> 00:34:43,670\nIt's not true.\n\n339\n00:34:43,670 --> 00:34:48,010\nSo you notice we did recursion here, and all we evaluated was plus X, Y, all right?\n\n340\n00:34:48,010 --> 00:34:54,780\nThe reason that you need recursion in the evaluator is because the evaluation process, itself, is recursive, all right?\n\n341\n00:34:54,780 --> 00:34:59,270\nIt's not because the procedure that you might be evaluating in LISP is a recursive procedure.\n\n342\n00:34:59,270 --> 00:35:03,010\nSo that's an important thing that people get confused about a lot.\n\n343\n00:35:03,010 --> 00:35:07,120\nThe other thing to notice is that, when we're done here, we're really done.\n\n344\n00:35:07,120 --> 00:35:13,810\nNot only are we at done, but there's no accumulated stuff on the stack, right?\n\n345\n00:35:13,810 --> 00:35:17,170\nThe machine is back to its initial state, all right?\n\n346\n00:35:17,170 --> 00:35:19,830\nSo that's part of what it means to be done.\n\n347\n00:35:19,830 --> 00:35:33,460\nAnother way to say that is the evaluation process has reduced the expression, plus X, Y, to the value here, 7.\n\n348\n00:35:33,460 --> 00:35:36,010\nAnd by reduced, I mean a very particular thing.\n\n349\n00:35:36,010 --> 00:35:38,180\nIt means that there's nothing left on the stack.\n\n350\n00:35:38,180 --> 00:35:42,760\nThe machine is now in the same state, except there's something in the value register.\n\n351\n00:35:42,760 --> 00:35:44,520\nIt's not part of a sub-problem of anything.\n\n352\n00:35:44,520 --> 00:35:46,210\nThere's nothing to go back to.\n\n353\n00:35:46,210 --> 00:35:46,440\nOK.\n\n354\n00:35:46,440 --> 00:35:47,690\nLet's break.\n\n355\n00:35:49,712 --> 00:35:50,159\nQuestion?\n\n356\n00:35:50,159 --> 00:35:55,820\nAUDIENCE: The question here, in the stack, is because the data may be recursive.\n\n357\n00:35:55,820 --> 00:35:59,312\nYou may have embedded expressions, for instance.\n\n358\n00:35:59,312 --> 00:36:02,080\nPROFESSOR: Yes, because you might have embedded expressions.\n\n359\n00:36:02,080 --> 00:36:12,930\nBut, again, don't confuse that with what people sometimes mean by the data may be recursive, which is to say you have these list-structured, recursive data list operations.\n\n360\n00:36:12,930 --> 00:36:13,980\nThat has nothing to do with it.\n\n361\n00:36:13,980 --> 00:36:17,363\nIt's simply that the expressions contain sub-expressions.\n\n362\n00:36:17,363 --> 00:36:19,618\nYeah?\n\n363\n00:36:19,618 --> 00:36:23,225\nAUDIENCE: Why is it that the order of the arguments in the arg list got reversed?\n\n364\n00:36:23,225 --> 00:36:27,260\nPROFESSOR: Ah! Yes, I should've mentioned that.\n\n365\n00:36:27,260 --> 00:36:36,050\nHere, the reason the order is reversed--  it's a question of what you mean by reversed.\n\n366\n00:36:36,050 --> 00:36:40,624\nI believe it was Newton.\n\n367\n00:36:40,624 --> 00:36:46,840\nIn the very early part of optics, people realized that, when you look through the lens of your eye, the image was up-side down.\n\n368\n00:36:46,840 --> 00:36:51,280\nAnd there was a lot of argument about why that didn't mean you saw things up-side down.\n\n369\n00:36:51,280 --> 00:36:52,860\nSo it's sort of the same issue.\n\n370\n00:36:52,860 --> 00:36:54,810\nReversed from what?\n\n371\n00:36:54,810 --> 00:36:57,940\nSo we just need some convention.\n\n372\n00:36:57,940 --> 00:37:04,520\nThe reason that they're coming at 4, 3 is because we're taking UNEV and consing the result onto argl.\n\n373\n00:37:04,520 --> 00:37:06,900\nSo you have to realize you've made that convention.\n\n374\n00:37:06,900 --> 00:37:11,230\nThe place that you have to realize that-- well, there's actually two places.\n\n375\n00:37:11,230 --> 00:37:19,490\nOne is in apply-primitive-operator, which has to realize that the arguments to primitives go in, in the opposite order from the way you're writing them down.\n\n376\n00:37:19,490 --> 00:37:28,870\nAnd the other one is, we'll see later when you actually go to bind a function's parameters, you should realize the arguments are going to come in from the opposite order of the variables to which you're binding them.\n\n377\n00:37:28,870 --> 00:37:31,830\nSo, if you just keep track of that, there's no problem.\n\n378\n00:37:31,830 --> 00:37:40,730\nAlso, this is completely arbitrary because, if we'd done, say, an iteration through a vector assigning them, they might come out in the other order, OK?\n\n379\n00:37:40,730 --> 00:37:45,085\nSo it's just a convention of the way this particular evaluator works.\n\n380\n00:37:45,085 --> 00:37:46,335\nAll right, let's take a break.\n\n381\n00:38:41,840 --> 00:38:46,950\nWe just saw evaluating an expression and, of course, that was very simple one.\n\n382\n00:38:46,950 --> 00:38:55,130\nBut, in essence, it would be no different if it was some big nested expression, so there would just be deeper recursion on the stack.\n\n383\n00:38:55,130 --> 00:38:56,920\nBut what I want to do now is show you the last piece.\n\n384\n00:38:56,920 --> 00:39:01,300\nI want to walk you around this eval and apply loop, right?\n\n385\n00:39:01,300 --> 00:39:03,000\nThat's the thing we haven't seen, really.\n\n386\n00:39:03,000 --> 00:39:15,810\nWe haven't seen any compound procedures where applying a procedure reduces to evaluating the body of the procedure, so let's just suppose we had this.\n\n387\n00:39:15,810 --> 00:39:47,280\nSuppose we were looking at the procedure define F of A and B to be the sum of A and B. So, as we typed in that procedure previously, and now we're going to evaluate F of X and Y, again, in this environment, E,0, where X is bound to 3 and Y is bound to 4.\n\n388\n00:39:50,830 --> 00:39:55,950\nWhen the defined is executed, remember, there's a lambda here, and lambdas create procedures.\n\n389\n00:39:55,950 --> 00:40:18,180\nAnd, basically, what will happen is, in E,0, we'll end up with a binding for F, which will say F is a procedure, and its args are A and B, and its body is plus a,b.\n\n390\n00:40:18,180 --> 00:40:24,400\nSo that's what the environment would have looked like had we made that definition.\n\n391\n00:40:24,400 --> 00:40:31,810\nThen, when we go to evaluate F of X and Y, we'll go through exactly the same process that we did before.\n\n392\n00:40:31,810 --> 00:40:33,360\nIt's even the same expression.\n\n393\n00:40:33,360 --> 00:40:41,040\nThe only difference is that F, instead of having primitive plus in it, will have this thing.\n\n394\n00:40:41,040 --> 00:41:08,040\nAnd so we'll go through exactly the same process, except this time, when we end up at apply-dispatch, the function register, instead of having primitive plus, will have a thing that will represent it saying procedure, where the args are A and B, and the body is plus A, B.\n\n395\n00:41:08,040 --> 00:41:13,280\nAnd, again, what I mean, by its ENV, I mean there's a pointer to it, so don't worry that I'm writing a lot of stuff there.\n\n396\n00:41:13,280 --> 00:41:17,170\nThere's a pointer to this procedure data structure.\n\n397\n00:41:17,170 --> 00:41:20,960\nOK, so, we're in exactly the same situation.\n\n398\n00:41:20,960 --> 00:41:26,480\nWe get to apply-dispatch, so, here, we come to apply-dispatch.\n\n399\n00:41:26,480 --> 00:41:30,010\nLast time, we branched off to a primitive procedure.\n\n400\n00:41:30,010 --> 00:41:36,150\nHere, it says oh, we now have a compound procedure, so we're going to go off to compound-apply.\n\n401\n00:41:38,660 --> 00:41:39,910\nNow, what's compound-apply?\n\n402\n00:41:42,100 --> 00:41:45,090\nWell, remember what the meta-circular evaluator did?\n\n403\n00:41:45,090 --> 00:41:54,120\nCompound-apply said we're going to evaluate the body of the procedure in some new environment.\n\n404\n00:41:54,120 --> 00:41:56,730\nWhere does that new environment come from?\n\n405\n00:41:56,730 --> 00:42:14,990\nWe take the environment that was packaged with the procedure, we bind the parameters of the procedure to the arguments that we're passing in, and use that as a new frame to extend the procedure environment.\n\n406\n00:42:14,990 --> 00:42:21,630\nAnd that's the environment in which we evaluate the procedure body, right?\n\n407\n00:42:21,630 --> 00:42:24,470\nThat's going around the apply/eval loop.\n\n408\n00:42:24,470 --> 00:42:27,988\nThat's apply coming back to call eval, all right?\n\n409\n00:42:30,910 --> 00:42:32,860\nOK.\n\n410\n00:42:32,860 --> 00:42:36,950\nSo, now, that's all we have to do in compound-apply.\n\n411\n00:42:36,950 --> 00:42:37,720\nWhat are we going to do?\n\n412\n00:42:37,720 --> 00:42:40,730\nWe're going to manufacture a new environment.\n\n413\n00:42:43,720 --> 00:42:48,310\nAnd we're going to manufacture a new environment, let's see, that we'll call E,1.\n\n414\n00:42:53,100 --> 00:43:09,270\nE,1 is going to be some environment where the parameters of the procedure, where A is bound to 3 and B is bound to 4, and it's linked to E,0 because that's where f is defined.\n\n415\n00:43:09,270 --> 00:43:12,050\nAnd, in this environment, we're going to evaluate the body of the procedure.\n\n416\n00:43:12,050 --> 00:43:13,870\nSo let's look at that, all right?\n\n417\n00:43:16,730 --> 00:43:28,300\nAll right, here we are at compound-apply, which says assign to the expression register the body of the procedure that's in the function register.\n\n418\n00:43:28,300 --> 00:43:42,710\nSo I assign to the expression register the procedure body, OK?\n\n419\n00:43:42,710 --> 00:43:57,800\nThat's going to be evaluated in an environment which is formed by making some bindings using information determined by the procedure-- that's what's in FUN-- and the argument list.\n\n420\n00:43:57,800 --> 00:44:01,930\nAnd let's not worry about exactly what that does, but you can see the information's there.\n\n421\n00:44:01,930 --> 00:44:08,200\nSo make bindings will say oh, the procedure, itself, had an environment attached to it.\n\n422\n00:44:08,200 --> 00:44:09,320\nI didn't write that quite here.\n\n423\n00:44:09,320 --> 00:44:13,660\nI should've said in environment because every procedure gets built with an environment.\n\n424\n00:44:13,660 --> 00:44:19,290\nSo, from that environment, it knows what the procedure's definition environment is.\n\n425\n00:44:19,290 --> 00:44:21,830\nIt knows what the arguments are.\n\n426\n00:44:21,830 --> 00:44:24,280\nIt looks at argl, and then you see a reversal convention here.\n\n427\n00:44:24,280 --> 00:44:29,990\nIt just has to know that argl is reversed, and it builds this frame, E,1.\n\n428\n00:44:29,990 --> 00:44:35,780\nAll right, so, let's assume that that's what make bindings returns, so it assigns to ENV this thing, E,1.\n\n429\n00:44:41,490 --> 00:44:46,890\nAll right, the next thing it says is restore continue.\n\n430\n00:44:46,890 --> 00:44:48,760\nRemember what continue was here?\n\n431\n00:44:48,760 --> 00:44:52,240\nIt got put up in the last segment.\n\n432\n00:44:52,240 --> 00:44:54,020\nContinue got stored.\n\n433\n00:44:54,020 --> 00:44:59,920\nThat was the original done, which said what are you going to do after you're done with this particular application?\n\n434\n00:44:59,920 --> 00:45:03,920\nIt was one of the very first things that happened when we evaluated the application.\n\n435\n00:45:03,920 --> 00:45:06,860\nAnd now, finally, we're going to restore continue.\n\n436\n00:45:06,860 --> 00:45:09,290\nRemember apply-dispatch's contract.\n\n437\n00:45:09,290 --> 00:45:13,590\nIt assumes that where it should go to next was on the stack, and there it was on the stack.\n\n438\n00:45:13,590 --> 00:45:19,940\nContinue has done, and now we're going to go back to eval-dispatch.\n\n439\n00:45:19,940 --> 00:45:20,970\nWe're set up again.\n\n440\n00:45:20,970 --> 00:45:25,511\nWe have an expression, an environment, and a place to go to.\n\n441\n00:45:25,511 --> 00:45:29,940\nWe're not going to go through that because it's sort of the same expression.\n\n442\n00:45:35,167 --> 00:45:44,830\nOK, but the thing, again, to notice is, at this point, we have reduced the original expression, F,X,Y, right?\n\n443\n00:45:44,830 --> 00:45:52,670\nWe've reduced evaluating F,X,Y in environment E,0 to evaluate plus A, B in E,1.\n\n444\n00:45:52,670 --> 00:45:55,720\nAnd notice, nothing's on the stack, right?\n\n445\n00:45:55,720 --> 00:45:56,830\nIt's a reduction.\n\n446\n00:45:56,830 --> 00:46:08,090\nAt this point, the machine does not contain, as part of its state, the fact that it's in the middle of evaluating some procedure called f, that's gone, right?\n\n447\n00:46:08,090 --> 00:46:13,072\nThere's no accumulated state, OK?\n\n448\n00:46:13,072 --> 00:46:14,370\nAgain, that's a very important idea.\n\n449\n00:46:14,370 --> 00:46:21,350\nThat's the meaning of, when we used to write in the substitution model, this expression reduces to that expression.\n\n450\n00:46:21,350 --> 00:46:22,660\nAnd you don't have to remember anything.\n\n451\n00:46:22,660 --> 00:46:24,500\nAnd here, you see the meaning of reduction.\n\n452\n00:46:24,500 --> 00:46:26,160\nAt this point, there is nothing on the stack.\n\n453\n00:46:31,590 --> 00:46:35,240\nSee, that has very important consequences.\n\n454\n00:46:35,240 --> 00:46:40,590\nLet's go back and look at iterative factorial, all right?\n\n455\n00:46:40,590 --> 00:46:45,130\nRemember, this was some sort of loop and doing iter.\n\n456\n00:46:45,130 --> 00:46:49,430\nAnd we kept saying that's an iterative procedure, right?\n\n457\n00:46:52,570 --> 00:47:12,360\nAnd what we wrote, remember, are things like, we said, fact-iter of 5.\n\n458\n00:47:12,360 --> 00:47:27,210\nWe wrote things like reduces to iter of 1, and 1, and 5, which reduces to iter of 1, and 2, and 5, and so on, and so on, and so on.\n\n459\n00:47:27,210 --> 00:47:31,720\nAnd we kept saying well, look, you don't have to build up any storage to do that.\n\n460\n00:47:31,720 --> 00:47:35,040\nAnd we waved our hands, and said in principle, there's no storage needed.\n\n461\n00:47:35,040 --> 00:47:36,170\nNow, you see no storage needed.\n\n462\n00:47:36,170 --> 00:47:39,090\nEach of these is a real reduction, right?\n\n463\n00:47:49,280 --> 00:48:01,650\nAs you walk through these expressions, what you'll see are these expressions on the stack in some particular environment, and then these expressions in the EXP register in some particular environment.\n\n464\n00:48:01,650 --> 00:48:09,135\nAnd, at each point, there'll be no accumulated stuff on the stack because each one's a real reduction, OK?\n\n465\n00:48:09,135 --> 00:48:48,120\nAll right, so, for example, just to go through it in a little bit more care, if I start out with an expression that says something like, oh, say, fact-iter of 5 in some environment that will, at some point, create an environment in which n is down to 5.\n\n466\n00:48:51,340 --> 00:49:17,160\nLet's call that--  And, at some point, the machine will reduce this whole thing to a thing that says that's really iter of 1, and 1, and n, evaluated in this environment, E,1 with nothing on the stack.\n\n467\n00:49:17,160 --> 00:49:29,366\nSee, at this moment, the machine is not remembering that evaluating this expression, iter--  which is the loop-- is part of this thing called iterative factorial.\n\n468\n00:49:29,366 --> 00:49:30,590\nIt's not remembering that.\n\n469\n00:49:30,590 --> 00:49:33,170\nIt's just reducing the expression to that, right?\n\n470\n00:49:33,170 --> 00:49:42,810\nIf we look again at the body of iterative factorial, this expression has reduced to that expression.\n\n471\n00:49:42,810 --> 00:49:44,060\nOh, I shouldn't have the n there.\n\n472\n00:49:46,590 --> 00:49:53,340\nIt's a slightly different convention from the slide to the program, OK?\n\n473\n00:49:53,340 --> 00:49:56,310\nAnd, then, what's the body of iter?\n\n474\n00:49:56,310 --> 00:50:00,060\nWell, iter's going to be an it, and I won't go through the details of if.\n\n475\n00:50:00,060 --> 00:50:02,540\nIt'll evaluate the predicate.\n\n476\n00:50:02,540 --> 00:50:03,810\nIn this case, it'll be false.\n\n477\n00:50:03,810 --> 00:50:43,200\nAnd this iter will now reduce to the expression iter of whatever it says, star, counter product, and-- what does it say-- plus counter 1 in some other environment, by this time, E,2, where E,2 will be set up having bindings for product and counter, right?\n\n478\n00:50:43,200 --> 00:50:45,140\nAnd it'll reduce to that, right?\n\n479\n00:50:45,140 --> 00:50:49,340\nIt won't be remembering that it's part of something that it has to return to.\n\n480\n00:50:49,340 --> 00:50:59,160\nAnd when iter calls iter again, it'll reduce to another thing that looks like this in some environment, E,3, which has new bindings for product and counter.\n\n481\n00:50:59,160 --> 00:51:21,230\nSo, if you're wondering, see, if you've always been queasy about how it is we've been saying those procedures, that look syntactically recursive, are, in fact, iterative, run in constant space, well, I don't know if this makes you less queasy, but at least it shows you what's happening.\n\n482\n00:51:21,230 --> 00:51:22,830\nThere really isn't any buildup there.\n\n483\n00:51:25,910 --> 00:51:31,710\nNow, you might ask well, is there buildup in principle in these environment frames?\n\n484\n00:51:31,710 --> 00:51:36,440\nAnd the answer is yeah, you have to make these new environment frames, but you don't have to hang onto them when you're done.\n\n485\n00:51:36,440 --> 00:51:40,720\nThey can be garbage collected, or the space can be reused automatically.\n\n486\n00:51:40,720 --> 00:51:50,132\nBut you see the control structure of the evaluator is really using this idea that you actually have a reduction, so these procedures really are iterative procedures.\n\n487\n00:51:50,132 --> 00:51:51,382\nAll right, let's stop for questions.\n\n488\n00:52:02,288 --> 00:52:03,538\nAll right, let's break.\n\n489\n00:52:48,770 --> 00:52:58,030\nLet me contrast the iterative procedure just so you'll see where space does build up with a recursive procedure, so you can see the difference.\n\n490\n00:52:58,030 --> 00:53:02,880\nLet's look at the evaluation of recursive factorial, all right?\n\n491\n00:53:02,880 --> 00:53:07,220\nSo, here's fact-recursive, or standard factorial definition.\n\n492\n00:53:07,220 --> 00:53:13,750\nWe said this one is still a recursive procedure, but this is actually a recursive process.\n\n493\n00:53:13,750 --> 00:54:15,240\nAnd then, just to link it back to the way we started, we said oh, you can see that it's going to be recursive process by the substitution model because, if I say recursive factorial of 5, that turns into 5 times-- what is it, fact-rec, or record fact--  5 times recursive factorial of 4, which turns into 5 times 4 times fact-rec of 3, which returns into 5 times 4 times 3 times, and so on, right?\n\n494\n00:54:15,240 --> 00:54:21,520\nThe idea is there was this chain of stuff building up, which justified, in the substitution model, the fact that it's recursive.\n\n495\n00:54:21,520 --> 00:54:27,465\nAnd now, let's actually see that chain of stuff build up and where it is in the machine, OK?\n\n496\n00:54:27,465 --> 00:54:30,230\nAll right, well, let's imagine we're going to start out again.\n\n497\n00:54:30,230 --> 00:54:49,580\nWe'll tell it to evaluate recursive factorial of 5 in some environment, again, E,0 where recursive factorial is defined, OK?\n\n498\n00:54:49,580 --> 00:54:52,490\nWell, now we know what's eventually going to happen.\n\n499\n00:54:52,490 --> 00:55:14,610\nThis is going to come along, it'll evaluate those things, figure out it's a procedure, build somewhere over here an environment, E,1, which has n bound to 5, which hangs off of E,0, which would be, presumably, the definition environment of recursive factorial, OK?\n\n500\n00:55:14,610 --> 00:55:19,670\nAnd, in this environment, it's going to go off and evaluate the body.\n\n501\n00:55:19,670 --> 00:55:30,240\nSo, again, the evaluation here will reduce to evaluating the body in E,1.\n\n502\n00:55:30,240 --> 00:55:33,530\nThat's going to look at an if, and I won't go through the details of if.\n\n503\n00:55:33,530 --> 00:55:34,880\nIt'll look at the predicate.\n\n504\n00:55:34,880 --> 00:55:37,840\nIt'll decide it eventually has to evaluate the alternative.\n\n505\n00:55:37,840 --> 00:56:08,720\nSo this whole thing, again, will reduce to the alternative of recursive factorial, the alternative clause, which says that this whole thing reduces to times n of recursive factorial of n minus 1 in the environment E,1, OK?\n\n506\n00:56:08,720 --> 00:56:14,130\nSo the original expression, now, is going to reduce to evaluating that expression, all right?\n\n507\n00:56:14,130 --> 00:56:16,280\nNow we have an application.\n\n508\n00:56:16,280 --> 00:56:18,500\nWe did an application before.\n\n509\n00:56:18,500 --> 00:56:20,390\nRemember what happens in an application?\n\n510\n00:56:20,390 --> 00:56:25,350\nThe first thing you do is you go off and you save the value of the continue register on the stack.\n\n511\n00:56:25,350 --> 00:56:27,365\nSo the stack here is going to have done in it.\n\n512\n00:56:29,980 --> 00:56:35,130\nAnd then you're going to set up to evaluate the sub-parts, OK?\n\n513\n00:56:35,130 --> 00:56:36,710\nSo here we go off to evaluate the sub-parts.\n\n514\n00:56:39,520 --> 00:56:41,045\nFirst thing we're going to do is evaluate the operator.\n\n515\n00:56:44,490 --> 00:56:47,250\nWhat happens when we evaluate an operator?\n\n516\n00:56:47,250 --> 00:56:51,480\nWell, we arrange things so that the operator ends up in the expression register.\n\n517\n00:56:51,480 --> 00:56:56,590\nThe environments in the ENV register continue someplace where we're going to go evaluate the arguments.\n\n518\n00:56:56,590 --> 00:57:01,720\nAnd, on the stack, we've saved the original continue, which is where we wanted to be when we're all done.\n\n519\n00:57:01,720 --> 00:57:15,620\nAnd then the things we needed when we're going to get done evaluating the operator, the things we'll need to evaluate the arguments, namely, the environment and those arguments, those unevaluated arguments, so there they are sitting on the stack.\n\n520\n00:57:15,620 --> 00:57:18,370\nAnd we're about to go off to evaluate the operator.\n\n521\n00:57:23,130 --> 00:57:43,080\nWell, when we return from this particular call-- so we're about to call eval-dispatch here-- when we return from this call, the value of that operator, which, in this case, is going to be the primitive multiplier procedure, will end up in the FUN register, all right?\n\n522\n00:57:43,080 --> 00:57:44,530\nWe're going to evaluate some arguments.\n\n523\n00:57:44,530 --> 00:57:47,730\nThey will evaluate in here.\n\n524\n00:57:47,730 --> 00:57:50,250\nThat'll give us 5, in this case.\n\n525\n00:57:50,250 --> 00:57:57,460\nWe're going to put that in the argl register, and then we'll go off to evaluate the second operand.\n\n526\n00:57:57,460 --> 00:58:09,460\nSo, at the point where we go off to evaluate the second operand-- and I'll skip details like computing, and minus 1, and all of that-- but, when we go off to evaluate the second operand, that will eventually reduce to another call to fact-recursive.\n\n527\n00:58:12,060 --> 00:58:23,790\nAnd, what we've got on the stack here is the operator from that combination that we're going to use it in and the other argument, OK?\n\n528\n00:58:23,790 --> 00:58:30,200\nSo, now, we're set up for another call to recursive factorial.\n\n529\n00:58:30,200 --> 00:58:33,935\nAnd, when we're done with this one, we're going to go to accumulate the last arg.\n\n530\n00:58:33,935 --> 00:58:35,200\nAnd remember what that'll do?\n\n531\n00:58:35,200 --> 00:58:41,690\nThat'll say oh, whatever the result of this has to get combined with that, and we're going to multiply them.\n\n532\n00:58:41,690 --> 00:58:45,720\nBut, notice now, we're at another recursive factorial.\n\n533\n00:58:45,720 --> 00:58:53,700\nWe're about to call eval-dispatch again, except we haven't really reduced it because there's stuff on the stack now.\n\n534\n00:58:53,700 --> 00:58:58,430\nThe stuff on the stack says oh, when you get back, you'd better multiply it by the 5 you had hanging there.\n\n535\n00:58:58,430 --> 00:59:09,300\nSo, when we go off to make another call, we evaluate the n minus 1.\n\n536\n00:59:09,300 --> 00:59:14,600\nThat gives us another environment in which the new n's going to be down to 4.\n\n537\n00:59:14,600 --> 00:59:18,930\nAnd we're about to call eval-dispatch again, right?\n\n538\n00:59:18,930 --> 00:59:21,350\nWe get another call.\n\n539\n00:59:21,350 --> 00:59:26,040\nThat 4 is going to end up in the same situation.\n\n540\n00:59:26,040 --> 00:59:30,020\nWe'll end up with another call to fact-recursive n.\n\n541\n00:59:30,020 --> 00:59:35,360\nAnd sitting on the stack will be the stuff from the original one and, now, the subsidiary one we're doing.\n\n542\n00:59:35,360 --> 00:59:36,910\nAnd both of them are waiting for the same thing.\n\n543\n00:59:36,910 --> 00:59:40,600\nThey're going to go to accumulate a last argument.\n\n544\n00:59:40,600 --> 00:59:45,640\nAnd then, of course, when we go to the fourth call, the same thing happens, right?\n\n545\n00:59:45,640 --> 00:59:47,300\nAnd this goes on, and on, and on.\n\n546\n00:59:47,300 --> 00:59:54,960\nAnd what you see here on the stack, exactly what's sitting here on the stack, the thing that says times and 5.\n\n547\n00:59:54,960 --> 01:00:00,470\nAnd what you're going to do with that is accumulate that into a last argument.\n\n548\n01:00:00,470 --> 01:00:02,760\nThat's exactly this, right?\n\n549\n01:00:02,760 --> 01:00:05,650\nThis is exactly where that stuff is hanging.\n\n550\n01:00:05,650 --> 01:00:19,620\nEffectively, the operator you're going to apply, the other argument that it's got to be multiplied by when you get back and the parentheses, which says yeah, what you wanted to do was accumulate them.\n\n551\n01:00:19,620 --> 01:00:22,560\nSo, you see, the substitution model is not such a lie.\n\n552\n01:00:22,560 --> 01:00:27,198\nThat really is, in some sense, what's sitting right on the stack.\n\n553\n01:00:27,198 --> 01:00:29,046\nOK.\n\n554\n01:00:29,046 --> 01:00:49,430\nAll right, so that, in some sense, should explain for you, or at least convince you, that, somehow, this evaluator is managing to take these procedures and execute some of them iteratively and some of them recursively, even though, as syntactically, they look like recursive procedures.\n\n555\n01:00:49,430 --> 01:00:50,660\nHow's it managing to do that?\n\n556\n01:00:50,660 --> 01:01:01,090\nWell, the basic reason it's managing to do that is the evaluator is set up to save only what it needs later.\n\n557\n01:01:01,090 --> 01:01:20,160\nSo, for example, at the point where you've reduced evaluating an expression and an environment to applying a procedure to some arguments, it doesn't need that original environment anymore because any environment stuff will be packaged inside the procedures where the application's going to happen.\n\n558\n01:01:20,160 --> 01:01:31,500\nAll right, similarly, when you're going along evaluating an argument list, when you've finished evaluating the list, when you're finished evaluating the last argument, you don't need that argument list any more, right?\n\n559\n01:01:31,500 --> 01:01:36,690\nAnd you don't need the environment where those arguments would be evaluated, OK?\n\n560\n01:01:36,690 --> 01:01:43,050\nSo the basic reason that this interpreter is being so smart is that it's not being smart at all, it's being stupid.\n\n561\n01:01:43,050 --> 01:01:46,010\nIt's just saying I'm only going to save what I really need.\n\n562\n01:01:48,700 --> 01:01:51,000\nWell, let me show you here.\n\n563\n01:01:54,880 --> 01:01:58,310\nHere's the actual thing that's making a tail recursive.\n\n564\n01:01:58,310 --> 01:02:00,135\nRemember, it's the restore of continue.\n\n565\n01:02:00,135 --> 01:02:15,170\nIt's saying when I go off to evaluate the procedure body, I should tell eval to come back to the place where that original evaluation was supposed to come back to.\n\n566\n01:02:15,170 --> 01:02:18,770\nSo, in some sense, you want to say what's the actual line that makes a tail recursive?\n\n567\n01:02:18,770 --> 01:02:19,920\nIt's that one.\n\n568\n01:02:19,920 --> 01:02:39,920\nIf I wanted to build a non-tail recursive evaluator, for some strange reason, all I would need to do is, instead of restoring continue at this point, I'd set up a label down here called, \"Where to come back after you've finished applying the procedure.\" Instead, I'd set continue to that.\n\n569\n01:02:39,920 --> 01:02:43,790\nI'd go to eval-dispatch, and then eval-dispatch would come back here.\n\n570\n01:02:43,790 --> 01:02:47,920\nAt that point, I would restore continue and go to the original one.\n\n571\n01:02:47,920 --> 01:02:52,840\nSo here, the only consequence of that would be to make it non-tail recursive.\n\n572\n01:02:52,840 --> 01:02:59,500\nIt would give you exactly the same answers, except, if you did that iterative factorial and all those iterative procedures, it would execute recursively.\n\n573\n01:03:03,080 --> 01:03:13,890\nWell, I lied to you a little bit, but just a little bit, because I showed you a slightly over-simplified evaluator where it assumes that each procedure body has only one expression.\n\n574\n01:03:13,890 --> 01:03:17,870\nRemember, in general, a procedure has a sequence of expressions in it.\n\n575\n01:03:17,870 --> 01:03:20,490\nSo there's nothing really conceptually new.\n\n576\n01:03:20,490 --> 01:03:24,730\nLet me just show you the actual evaluator that handles sequences of expressions.\n\n577\n01:03:28,470 --> 01:03:42,670\nThis is compound-apply now, and the only difference from the old one is that, instead of going off to eval directly, it takes the whole body of the procedure, which, in this case, is a sequence of expressions, and goes off to eval-sequence.\n\n578\n01:03:42,670 --> 01:03:49,980\nAnd eval-sequence is a little loop that, basically, does these evaluations one at a time.\n\n579\n01:03:52,630 --> 01:03:53,900\nSo it does an evaluation.\n\n580\n01:03:53,900 --> 01:03:58,440\nSays oh, when I come back, I'd better come back here to do the next one.\n\n581\n01:03:58,440 --> 01:04:06,410\nAnd, when I'm all done, when I want to get the last expression, I just restore my continue and go off to eval-dispatch.\n\n582\n01:04:06,410 --> 01:04:14,900\nAnd, again, if you wanted for some reason to break tail recursion in this evaluator, all you need to do is not handle the last expression, especially.\n\n583\n01:04:14,900 --> 01:04:21,900\nJust say, after you've done the last expression, come back to some other place after which you restore continue.\n\n584\n01:04:21,900 --> 01:04:26,550\nAnd, for some reason, a lot of LISP evaluators tended to work that way.\n\n585\n01:04:26,550 --> 01:04:31,614\nAnd the only consequence of that is that iterative procedures built up stack.\n\n586\n01:04:31,614 --> 01:04:35,670\nAnd it's not clear why that happened.\n\n587\n01:04:35,670 --> 01:04:36,210\nAll right.\n\n588\n01:04:36,210 --> 01:04:41,120\nWell, let me just sort of summarize, since this is a lot of details in a big program.\n\n589\n01:04:41,120 --> 01:04:47,060\nBut the main point is that it's no different, conceptually, from translating any other program.\n\n590\n01:04:47,060 --> 01:04:51,870\nAnd the main idea is that we have this universal evaluator program, the meta-circular evaluator.\n\n591\n01:04:51,870 --> 01:04:54,560\nIf we translate that into LISP, then we have all of LISP.\n\n592\n01:04:54,560 --> 01:04:57,980\nAnd that's all we did, OK?\n\n593\n01:04:57,980 --> 01:04:59,680\nThe second point is that the magic's gone away.\n\n594\n01:04:59,680 --> 01:05:01,970\nThere should be no more magic in this whole system, right?\n\n595\n01:05:04,820 --> 01:05:12,640\nIn principle, it should all be very clear except, maybe, for how list structured memory works, and we'll see that later.\n\n596\n01:05:12,640 --> 01:05:15,450\nBut that's not very hard.\n\n597\n01:05:15,450 --> 01:05:25,870\nThe third point is that all this tail recursion came from the discipline of eval being very careful to save only what it needs next time.\n\n598\n01:05:25,870 --> 01:05:33,940\nIt's not some arbitrary thing where we're saying well, whenever we call a sub-routine, we'll save all the registers in the world and come back, right?\n\n599\n01:05:33,940 --> 01:05:37,150\nSee, sometimes it pays to really worry about efficiency.\n\n600\n01:05:37,150 --> 01:05:45,230\nAnd, when you're down in the guts of your evaluator machine, it really pays to think about things like that because it makes big consequences.\n\n601\n01:05:45,230 --> 01:05:52,560\nWell, I hope what this has done is really made the evaluator seem concrete, right?\n\n602\n01:05:52,560 --> 01:05:59,390\nI hope you really believe that somebody could hold a LISP evaluator in the palm of their hand.\n\n603\n01:05:59,390 --> 01:06:06,160\nMaybe to help you believe that, here's a LISP evaluator that I'm holding the palm of my hand, right?\n\n604\n01:06:06,160 --> 01:06:13,700\nAnd this is a chip which is actually quite a bit more complicated than the evaluator I showed you.\n\n605\n01:06:17,815 --> 01:06:19,200\nMaybe, here's a better picture of it.\n\n606\n01:06:22,070 --> 01:06:24,730\nWhat there is, is you can see the same overall structure.\n\n607\n01:06:24,730 --> 01:06:26,940\nThis is a register array.\n\n608\n01:06:26,940 --> 01:06:27,910\nThese are the data paths.\n\n609\n01:06:27,910 --> 01:06:29,800\nHere's a finite state controller.\n\n610\n01:06:29,800 --> 01:06:32,810\nAnd again, finite state, that's all there is.\n\n611\n01:06:32,810 --> 01:06:35,750\nAnd somewhere there's external memory that'll worry about things.\n\n612\n01:06:35,750 --> 01:06:57,120\nAnd this particular one is very complicated because it's trying to run LISP fast. And it has some very, very fast parallel operations in there like, if you want to index into an array, simultaneously check that the index is an integer, check that it doesn't exceed the array bands, and go off and do the memory access, and do all those things simultaneously.\n\n613\n01:06:57,120 --> 01:07:00,420\nAnd then, later, if they're all OK, actually get the value there.\n\n614\n01:07:00,420 --> 01:07:06,550\nSo there are a lot of complicated operations in these data paths for making LISP run in parallel.\n\n615\n01:07:06,550 --> 01:07:10,640\nIt's a completely non-risk philosophy of evaluating LISP.\n\n616\n01:07:10,640 --> 01:07:13,740\nAnd then, this microcode is pretty complicated.\n\n617\n01:07:13,740 --> 01:07:17,740\nLet's see, there's what?\n\n618\n01:07:17,740 --> 01:07:27,940\nThere's about 389 instructions of 220-bit microcode sitting here because these are very complicated data paths.\n\n619\n01:07:27,940 --> 01:07:33,580\nAnd the whole thing has about 89,000 transistors, OK?\n\n620\n01:07:33,580 --> 01:07:33,840\nOK.\n\n621\n01:07:33,840 --> 01:07:37,970\nWell, I hope that that takes away a lot of the mystery.\n\n622\n01:07:37,970 --> 01:07:39,240\nMaybe somebody wants to look at this.\n\n623\n01:07:42,048 --> 01:07:43,298\nYeah.\n\n624\n01:07:46,260 --> 01:07:46,480\nOK.\n\n625\n01:07:46,480 --> 01:07:47,730\nLet's stop.\n\n626\n01:07:55,890 --> 01:07:57,815\nQuestions?\n\n627\n01:07:57,815 --> 01:08:15,165\nAUDIENCE: OK, now, it sounds like what you're saying is that, with the restore continue put in the proper place, that procedures that would invoke a recursive process now invoke an integer process just by the way that the eval signature is?\n\n628\n01:08:15,165 --> 01:08:28,029\nPROFESSOR: I think the way I'd prefer to put it is that, with restore continue put in the wrong place, you can cause any syntactically-looking recursive procedure, in fact, to build up stack as it runs.\n\n629\n01:08:28,029 --> 01:08:35,660\nBut there's no reason for that, so you might want to play around with it.\n\n630\n01:08:35,660 --> 01:08:45,060\nYou can just switch around two or three instructions in the way compound-apply comes back, and you'll get something which isn't tail recursive.\n\n631\n01:08:45,060 --> 01:08:47,670\nBut the thing I wanted to emphasize is there's no magic.\n\n632\n01:08:47,670 --> 01:09:01,060\nIt's not as if there's some very clever pre-processing program that's looking at this procedure, factorial iter, and say oh, gee, I really notice that I don't have to push stack in order to do this.\n\n633\n01:09:01,060 --> 01:09:03,760\nSome people think that that's what's going on.\n\n634\n01:09:03,760 --> 01:09:08,880\nIt's something much, much more dumb than that, it's this one place you're putting the restore instruction.\n\n635\n01:09:08,880 --> 01:09:10,353\nIt's just automatic.\n\n636\n01:09:10,353 --> 01:09:11,603\nAUDIENCE: OK.\n\n637\n01:09:14,217 --> 01:09:17,850\nAUDIENCE: But that's not affecting the time complexity is it?\n\n638\n01:09:17,850 --> 01:09:18,275\nPROFESSOR: No.\n\n639\n01:09:18,275 --> 01:09:23,020\nAUDIENCE: It's just that it's handling it recursively instead of iteratively.\n\n640\n01:09:23,020 --> 01:09:29,220\nBut, in terms of the order of time it takes to finish the operation, it's the same one way or the other, right?\n\n641\n01:09:29,220 --> 01:09:29,920\nPROFESSOR: Yes.\n\n642\n01:09:29,920 --> 01:09:36,029\nTail recursion is not going to change the time complexity of anything because, in some sense, it's the same algorithm that's going on.\n\n643\n01:09:36,029 --> 01:09:41,210\nWhat it's doing is really making this thing run as an iteration, right?\n\n644\n01:09:41,210 --> 01:09:47,683\nNot going to run out of memory counting up to a giant number simply because the stack would get pushed.\n\n645\n01:09:47,683 --> 01:09:57,990\nSee, the thing you really have to believe is that, when we write-- see, we've been writing all these things called iterations, infinite loops, define loop to be called loop.\n\n646\n01:10:01,660 --> 01:10:07,630\nThat's is as much an iteration as if we wrote do forever loop, right?\n\n647\n01:10:07,630 --> 01:10:09,280\nIt's just syntactic sugar as the difference.\n\n648\n01:10:09,280 --> 01:10:14,730\nThese things are real, honest to god, iterations, right?\n\n649\n01:10:14,730 --> 01:10:18,535\nThey don't change the time complexity, but they turn them into real iterations.\n\n650\n01:10:21,686 --> 01:10:23,800\nAll right, thank you.\n\n"
  },
  {
    "path": "SrtCN/lec9b.srt",
    "content": "﻿1\n00:00:16,300 --> 00:00:18,080\n教授：我想大家已经意识到\nPROFESSOR: Well, I hope you appreciate that we have\n\n2\n00:00:20,010 --> 00:00:22,730\n我们介绍了一些真正的魔法\nwe have inducted you into some real magic,\n\n3\n00:00:24,200 --> 00:00:27,240\n创造新语言的魔法\nthe magic of building languages\n\n4\n00:00:27,420 --> 00:00:28,720\n用来创造全新的语言\nreally building new languages.\n\n5\n00:00:29,690 --> 00:00:30,400\n我们学了些什么？\nWhat have we looked at?\n\n6\n00:00:30,430 --> 00:00:32,780\n我们学习了一门用来操作图片的Escher的语言\nWe've looked at an Escher picture language.\n\n7\n00:00:38,920 --> 00:00:41,150\n这门语言由Peter Henderson发明\nOK? this language invented by Peter Henderson.\n\n8\n00:00:42,010 --> 00:00:46,490\n我们还学习了数字逻辑语言\nWe looked at digital logic language.\n\n9\n00:00:53,160 --> 00:00:55,550\n以及 我们还学习了查询语言\nLet's see.We've looked at the query language.\n\n10\n00:00:59,700 --> 00:01:00,780\n然而你需要明白的是\nAnd the thing you should realize is,\n\n11\n00:01:00,810 --> 00:01:03,100\n尽管它们都是“玩具级”的语言示例\neven though these were toy examples,\n\n12\n00:01:04,700 --> 00:01:07,610\n但也确实是实用工具的核心\nthey really are the kernels of really useful things.\n\n13\n00:01:08,250 --> 00:01:09,480\n比如说\nSo, for instance,\n\n14\n00:01:10,120 --> 00:01:11,184\nEscher图片语言\nthe Escher picture language\n\n15\n00:01:11,200 --> 00:01:14,336\n就被MIT的学生Henry Wu拿去\n was taken byHenry Wu, who's a student at MIT,\n\n16\n00:01:14,880 --> 00:01:16,432\n开发成了一门用于\nand developed into a real\n\n17\n00:01:16,976 --> 00:01:19,450\n为电路板布局的语言\nlanguage for laying out PC boards,\n\n18\n00:01:20,350 --> 00:01:22,560\n它就是在这些结构上扩展而来\nbased just on extending those structures.\n\n19\n00:01:23,240 --> 00:01:24,650\n至于数字逻辑语言\nAnd the digital logic language,\n\n20\n00:01:24,680 --> 00:01:26,080\nGerry教授在上课的时候也提到过\nGerry mentioned when he showed it to you,\n\n21\n00:01:26,430 --> 00:01:29,920\n它被扩展为了一个仿真器的基础\nwas really extended to be used as the basis for a simulator\n\n22\n00:01:30,850 --> 00:01:32,960\n用来设计真实的计算机\nthat was used to design a real computer.\n\n23\n00:01:33,460 --> 00:01:34,320\n至于查询语言\nAnd the query language,\n\n24\n00:01:34,350 --> 00:01:36,440\n当然就是Prolog语言的一种核心\nof course, is kind of the germ of prolog.\n\n25\n00:01:37,510 --> 00:01:39,070\n我们构造的这些语言\nSo we built all of these languages,\n\n26\n00:01:39,550 --> 00:01:40,650\n全都是用Lisp编写\nthey're all based on LISP.\n\n27\n00:01:43,630 --> 00:01:44,590\n很多人问\nA lot of people ask\n\n28\n00:01:45,270 --> 00:01:48,730\nLisp适合用来解决哪一类问题？\nwhat particular problems is LISP good for solving for?\n\n29\n00:01:48,750 --> 00:01:49,930\n答案就是\nThe answer is LISP is not...\n\n30\n00:01:50,330 --> 00:01:52,650\nLisp不适合解决任何一类问题\nLISP is not good for solving any particular problems.\n\n31\n00:01:53,530 --> 00:01:54,600\nLisp擅长的是\nWhat LISP is good for\n\n32\n00:01:54,730 --> 00:01:57,150\n用它来构造一门合适的语言\nis constructing within it the right language\n\n33\n00:01:57,180 --> 00:01:58,570\n来解决你的问题\nto solve the problems you want to solve,\n\n34\n00:01:59,170 --> 00:02:00,440\n你应该像这样看待Lisp\nand that's how you should think about it.\n\n35\n00:02:01,470 --> 00:02:03,390\n那么既然这些语言都基于Lisp\nSo all of these languages were based on LISP.\n\n36\n00:02:04,570 --> 00:02:05,720\n那Lisp又基于什么？\nNow, what's LISP based on?\n\n37\n00:02:06,970 --> 00:02:07,880\n它又从何而来？\nWhere's that come from?\n\n38\n00:02:07,900 --> 00:02:09,400\n这个我们也学过\nWell, we looked at that too.\n\n39\n00:02:09,580 --> 00:02:16,090\n我们学过元循环求值器\nWe looked at the meta-circular evaluator\n\n40\n00:02:21,530 --> 00:02:23,400\n学习了元循环求值器后 我们说\nthe meta-circular evaluator and sort of said\n\n41\n00:02:23,420 --> 00:02:25,760\nLisp就是基于Lisp的\nwell, LISP is based on LISP.\n\n42\n00:02:25,800 --> 00:02:27,480\n而当我们研究它的时候\nAnd when we start looking at that,\n\n43\n00:02:28,270 --> 00:02:29,950\n我们必须得施展一些真正的魔法 对吧？\nwe've got to do some real magic, right?\n\n44\n00:02:29,950 --> 00:02:31,740\n这又是什么意思呢？\nSo what does that mean, right?\n\n45\n00:02:31,740 --> 00:02:34,960\nY算子、不动点\nY operators, and fixed points,\n\n46\n00:02:35,760 --> 00:02:38,330\n以及这样的一个观念--\nand the idea that what this means is\n\n47\n00:02:38,360 --> 00:02:41,440\nLisp实际上是一个方程的不动点\nthat LISP is somehow the fixed-point equation for the\n\n48\n00:02:42,200 --> 00:02:45,420\n一个通过自身来定义的有趣方程\nfor this funny set of things which are defined in terms of themselves.\n\n49\n00:02:47,400 --> 00:02:48,560\n这确实是神奇的魔法\nNow, it's real magic.\n\n50\n00:02:49,070 --> 00:02:52,350\n那么今天 作为魔法的最后一步\nWell, today, for a final piece of magic,\n\n51\n00:02:52,620 --> 00:02:54,030\n我们要把它们通通消除掉\nwe're going to make all the magic go away.\n\n52\n00:03:06,800 --> 00:03:07,980\n我们已经知道怎么做了\nWe already know how to do that.\n\n53\n00:03:09,770 --> 00:03:10,768\n核心要思想是\nThe idea is, we're going to take\n\n54\n00:03:11,136 --> 00:03:12,730\n将Lisp语言\nthe register machine architecture\n\n55\n00:03:13,360 --> 00:03:15,500\n实现在使用寄存器架构的机器上\nand show how to implement LISP on terms of that.\n\n56\n00:03:15,500 --> 00:03:17,936\n回想一下 寄存器机器的关键之处在于\nAnd, remember, the idea of the register machine\n\n57\n00:03:19,600 --> 00:03:24,680\n机器的一部分是确定且有穷的\nis that there's a fixed and finite part of the machine.\n\n58\n00:03:24,720 --> 00:03:26,120\n它有一个有穷状态控制器\nThere's a finite-state controller,\n\n59\n00:03:26,120 --> 00:03:27,872\n它用特定的硬件\nwhich dose particular thing\n\n60\n00:03:27,888 --> 00:03:29,310\n去完成特定的事情\nwith a particular amount of hardware.\n\n61\n00:03:30,510 --> 00:03:31,740\n其中还有一些运算所需的\nThere are particular data paths,\n\n62\n00:03:31,760 --> 00:03:33,240\n特殊数据通路\nthe operation the machine does\n\n63\n00:03:33,550 --> 00:03:35,290\n然后 为了实现递归\nAnd then, in order to implement recursion\n\n64\n00:03:35,530 --> 00:03:37,600\n并且维持无穷的假象\nand sustain the illusion of infinity,\n\n65\n00:03:37,820 --> 00:03:39,770\n还使用了一种称作“栈”的大内存\nthere's some large amount of memory, which is the stack.\n\n66\n00:03:42,060 --> 00:03:43,728\n所以如果我们在\nSo, if we implement LISP\n\n67\n00:03:43,920 --> 00:03:45,500\n寄存器机器上实现了Lisp\nin terms of a register machine,\n\n68\n00:03:47,020 --> 00:03:48,350\n那么这个时候\nthen everything ought to become,\n\n69\n00:03:48,400 --> 00:03:49,850\n所有的东西都会完全具体化\nat this point,completely concrete.\n\n70\n00:03:49,850 --> 00:03:51,230\n所有的魔法都会消除\nAll the magic should go away.\n\n71\n00:03:51,650 --> 00:03:53,520\n这堂课结束时\nAnd, by the end of this talk,\n\n72\n00:03:53,530 --> 00:03:54,780\n我想让你感觉到\nI want you get the feeling\n\n73\n00:03:55,140 --> 00:03:59,050\n相对于神秘的元循环求值器\nthat, as opposed to this very mysterious meta-circular evaluator\n\n74\n00:03:59,670 --> 00:04:02,600\nLisp求值器是非常具体的东西\nthat a LISP evaluator really is something that's concrete enough\n\n75\n00:04:02,850 --> 00:04:04,570\n你甚至可以把它放在手心中\nthat you can hold in the palm of your hand.\n\n76\n00:04:04,760 --> 00:04:06,240\n你可以想象一下\nYou should be able to imagine holding\n\n77\n00:04:06,570 --> 00:04:07,900\n手里拿着一个Lisp解释器的情景\nholding a LISP interpreter there.\n\n78\n00:04:09,630 --> 00:04:10,940\n好 那我们怎么做呢？\nAll right, how are we going to do this?\n\n79\n00:04:10,950 --> 00:04:12,760\n所有的原料都已经齐全\nWe already have all the ingredients.\n\n80\n00:04:13,960 --> 00:04:17,450\n上节课Gerry教了你们\nSee, what you learned last time from Gerry\n\n81\n00:04:17,600 --> 00:04:21,470\n对一个任意的Lisp过程\nis how to take any particular couple of LISP procedures.\n\n82\n00:04:22,600 --> 00:04:24,280\n如何手动地把它们\nand hand-translate them\n\n83\n00:04:24,750 --> 00:04:26,670\n翻译成在寄存器机器上运行的代码\ninto something that runs on a register machine.\n\n84\n00:04:28,200 --> 00:04:30,520\n那么 要在寄存器机器上实现Lisp本身\nSo, to implement all of LISP on a register machine,\n\n85\n00:04:30,570 --> 00:04:31,440\n我们只需要\nall we have to do\n\n86\n00:04:31,690 --> 00:04:33,450\n把最关键的过程\nis take the particular procedures\n\n87\n00:04:33,680 --> 00:04:35,420\n也就是元循环求值器\nthat are the meta-circular evaluator\n\n88\n00:04:36,170 --> 00:04:38,110\n手工翻译成寄存器机器的代码\nand hand-translate them for a register machine.\n\n89\n00:04:39,040 --> 00:04:40,250\n这就实现了整个Lisp\nAnd that does all of LISP\n\n90\n00:04:42,140 --> 00:04:43,008\n因此 我们已经知道了\nRight? So, in principle,\n\n91\n00:04:43,024 --> 00:04:44,430\n实现的原理\nwe already know how to do this.\n\n92\n00:04:45,380 --> 00:04:46,544\n而且实际上\nAnd, indeed, it's going to be no\n\n93\n00:04:46,688 --> 00:04:48,864\n这跟翻译\nno different, in kind,\n\n94\n00:04:50,000 --> 00:04:53,400\n递归版的阶乘或斐波那契数列\nfrom in say recursive factorial\n\n95\n00:04:53,420 --> 00:04:54,670\n没什么区别\nor recursive Fibonacci.\n\n96\n00:04:54,670 --> 00:04:56,000\n只是它规模更大 代码更多\nIt's just bigger and there's more of it.\n\n97\n00:04:56,840 --> 00:04:58,030\n只是包含了更多细节\nSo it'd just be more details,\n\n98\n00:04:58,040 --> 00:04:59,660\n但是没有任何新的概念\nbut nothing really conceptually new.\n\n99\n00:05:01,480 --> 00:05:03,020\n当我们完成这个以后\nAnd also, when we've done that,\n\n100\n00:05:03,080 --> 00:05:04,760\n所有的东西都变得明确了\nand the thing is completely explicit,\n\n101\n00:05:04,870 --> 00:05:06,910\n当我们看到如何用一系列的\nand we see how to implement LISP\n\n102\n00:05:06,940 --> 00:05:10,080\n寄存器操作来实现Lisp之后\nin terms of the actual sequential register operations,\n\n103\n00:05:10,160 --> 00:05:11,630\n它就成为了我们整个课程中\nthat's going to be our final\n\n104\n00:05:11,950 --> 00:05:14,160\n最明确的Lisp模型\nmost explicit model of LISP in this course.\n\n105\n00:05:14,810 --> 00:05:16,950\n回忆一下 这个过程贯穿了整个课程\nAnd, remember, that's a progression through this course.\n\n106\n00:05:16,950 --> 00:05:18,250\n我们先从代换模型开始\nWe started out with substitution,\n\n107\n00:05:18,280 --> 00:05:19,580\n它和代数有点相似\nwhich is sort of like algebra.\n\n108\n00:05:20,240 --> 00:05:21,870\n然后学习了环境模型\nAnd then we went to the environment model,\n\n109\n00:05:21,880 --> 00:05:24,000\n它引入了“框架”的概念\nwhich talked about the actual frames\n\n110\n00:05:24,030 --> 00:05:25,310\n以及框架之间的关联\nand how they got linked together.\n\n111\n00:05:26,320 --> 00:05:27,880\n然后我们在元循环求值器中\nAnd then we made that more concrete\n\n112\n00:05:27,900 --> 00:05:29,360\n把它变得更具体了\nin the meta-circular evaluator.\n\n113\n00:05:31,050 --> 00:05:31,640\n但是有的事情\nThere are things\n\n114\n00:05:31,870 --> 00:05:33,980\n元循环求值器没有告诉我们\nthe meta-circular evaluator doesn't tell us.\n\n115\n00:05:34,360 --> 00:05:35,340\n你应该认识到这点\nYou should realize that.\n\n116\n00:05:36,090 --> 00:05:38,640\n比如说 我们还不知道\nFor instance, it left unanswered the question\n\n117\n00:05:38,730 --> 00:05:42,670\n像这里的递归阶乘过程\nof how a procedure, like recursive factorial here,\n\n118\n00:05:45,170 --> 00:05:47,130\n为何不断地申请新的空间\nsomehow takes space that grows.\n\n119\n00:05:47,210 --> 00:05:47,980\n另一方面\nOn the other hand,\n\n120\n00:05:48,160 --> 00:05:51,940\n一个语法上看起来像是递归的过程\na procedure which also looks syntactically recursive,\n\n121\n00:05:52,110 --> 00:05:55,070\n比如FACT-ITER 并不占用栈空间\ncalled fact-iter, somehow doesn't take space.\n\n122\n00:05:55,100 --> 00:05:59,160\n我们通过代换模型来证明\nWe justify that it doesn't need to take space\n\n123\n00:06:00,500 --> 00:06:01,960\n它不占用空间\nby showing the substitution model.\n\n124\n00:06:01,960 --> 00:06:02,940\n但我们并没有说清楚\nBut we didn't really say\n\n125\n00:06:03,420 --> 00:06:06,760\n机器是如何做到这一点的\nhow it happens that the machine manages to do that,\n\n126\n00:06:07,310 --> 00:06:08,910\n这涉及到一些细节\nthat that has to do with the details\n\n127\n00:06:09,020 --> 00:06:11,120\n比如参数是如何传递给过程的\nof how arguments are passed to procedures\n\n128\n00:06:12,480 --> 00:06:13,690\n这是我们在元循环求值器中\nAnd that's the thing we didn't see\n\n129\n00:06:13,710 --> 00:06:15,340\n没有看到的\nin the meta-circular evaluator\n\n130\n00:06:15,360 --> 00:06:17,400\n完全是因为在所实现的Lisp中\nprecisely because the way arguments\n\n131\n00:06:17,420 --> 00:06:19,200\n把参数传递给过程的方式\ngot passed to procedures in this LISP\n\n132\n00:06:19,700 --> 00:06:20,590\n取决于\ndepended on\n\n133\n00:06:21,020 --> 00:06:23,500\n外部Lisp的传参方式\nthe way arguments got passed to procedures in this LISP.\n\n134\n00:06:25,870 --> 00:06:29,020\n但现在 这一点将变得非常明确\nBut, now, that's going to become extremely explicit.\n\n135\n00:06:30,740 --> 00:06:31,120\n好\nOK.\n\n136\n00:06:31,230 --> 00:06:34,300\n在开始研究求值器之前\nWell, before going on to the evaluator,\n\n137\n00:06:34,360 --> 00:06:35,530\n我先让你们感受一下\nlet me just give you a sense of\n\n138\n00:06:35,550 --> 00:06:37,000\n一个完整Lisp系统是怎么样的\nwhat a whole LISP system looks like\n\n139\n00:06:37,600 --> 00:06:39,360\n这样你就可以知道 我们要讨论哪部分\nso you can see the parts we're going to talk about\n\n140\n00:06:39,400 --> 00:06:40,810\n不讨论哪些部分\nand the parts we're not going to talk about.\n\n141\n00:06:43,180 --> 00:06:47,420\n首先 这里有一个快乐的Lisp用户\nLet's see, over here is a happy LISP user,\n\n142\n00:06:48,670 --> 00:06:52,650\n他正在和一个叫做读取器的东西交流\nand the LISP user is talking to something called the reader.\n\n143\n00:07:00,360 --> 00:07:01,530\n读取器的工作是\nThe reader's job in life\n\n144\n00:07:01,950 --> 00:07:13,230\n读取用户输入的字符串\nis to take characters from the user\n\n145\n00:07:14,170 --> 00:07:16,620\n把它们转化成一种称作\nand turn them into data structures\n\n146\n00:07:17,200 --> 00:07:19,370\n表结构内存的数据结构\nin something called a list structure memory.\n\n147\n00:07:30,000 --> 00:07:31,720\n读取器会读取--\nAll right, so the reader is going to take\n\n148\n00:07:32,650 --> 00:07:33,950\n你敲出来的符号、括号\nsymbols, parentheses,\n\n149\n00:07:34,480 --> 00:07:37,120\nA和B、1和3这些东西\nand A's and B's, and 1s and 3s that you type in,\n\n150\n00:07:37,180 --> 00:07:39,040\n并把它们变成表结构\nand turn these into actual list structure:\n\n151\n00:07:39,150 --> 00:07:40,540\n变成序对、指针等等\npairs, and pointers, and things.\n\n152\n00:07:42,350 --> 00:07:43,920\n所以当求值器运行的时候\nAnd so, by the time evaluator is going,\n\n153\n00:07:43,930 --> 00:07:45,100\n环境里已经不存在原始字符了\nthere are no characters in the world.\n\n154\n00:07:45,850 --> 00:07:48,160\n当然 在更现代的Lisp系统中\nAnd, of course, in more modern Lisp systems, there's\n\n155\n00:07:49,000 --> 00:07:50,440\n可能还有一大团东西\nthere's sort a big morass here\n\n156\n00:07:50,440 --> 00:07:52,170\n存在于在读取器和用户之间\nthat might sit between the user and the reader:\n\n157\n00:07:52,410 --> 00:07:54,520\n最顶层首先是视窗系统\nyou know, Windows systems, in top levels,\n\n158\n00:07:54,770 --> 00:07:56,030\n以及鼠标之类的东西\nand mice, and all kinds of things.\n\n159\n00:07:56,280 --> 00:07:58,200\n但从概念上来说 都是在输入字符\nBut conceptually, characters are coming in.\n\n160\n00:07:59,930 --> 00:08:04,320\n总之 读取器把它们都变成指针\nAll right, the reader transforms these into pointers\n\n161\n00:08:05,560 --> 00:08:07,280\n指向内存中的对象\npointers to stuff in this memory,\n\n162\n00:08:08,270 --> 00:08:10,940\n这是求值器的所能看到的东西\nand that's what the evaluator sees\n\n163\n00:08:15,550 --> 00:08:16,040\n明白吗？\nOK?\n\n164\n00:08:17,020 --> 00:08:18,880\n求值器有一些辅助函数\nThe evaluator has a bunch of helpers.\n\n165\n00:08:19,780 --> 00:08:23,160\n包括你需要的所有基本运算\nIt has all possible primitive operators you might want.\n\n166\n00:08:23,160 --> 00:08:24,910\n也就是说这里另有一盒子东西\nSo there's a completely separate box,\n\n167\n00:08:28,400 --> 00:08:30,250\n比如浮点单元\na floating point unit,\n\n168\n00:08:32,220 --> 00:08:34,400\n或者其它类似的东西来执行这些运算\nor all sorts of things, which do the primitive operators.\n\n169\n00:08:35,390 --> 00:08:37,680\n如果你需要支持更多的基本运算\nthere's and, if you want more special primitives,\n\n170\n00:08:37,710 --> 00:08:39,020\n你就实现更多的运算符执行器\nyou build more primitive operators,\n\n171\n00:08:39,050 --> 00:08:40,480\n但它们和求值器都是分离的\nbut they're separate from the evaluator.\n\n172\n00:08:42,080 --> 00:08:43,770\n求值器最终算出结果\nThe evaluator finally gets an answer\n\n173\n00:08:45,168 --> 00:08:46,768\n并且把它们告诉打印程序\nand communicates that to the printer.\n\n174\n00:08:50,624 --> 00:08:52,016\n现在 打印程序的任务就是\nAnd now, the printer's job in life\n\n175\n00:08:52,016 --> 00:08:54,544\n从求值器取得这个表结构\nis this list structure coming from the evaluator,\n\n176\n00:08:55,392 --> 00:08:56,992\n再把它们变回字符\nand turn it back into characters,\n\n177\n00:09:01,856 --> 00:09:04,070\n然后通过某种界面\nand communicate them to the user through\n\n178\n00:09:04,288 --> 00:09:05,664\n展示给用户\nwhatever interface there is.\n\n179\n00:09:08,050 --> 00:09:11,232\n那么 今天我们要讨论的是这个求值器\nOK. Well, today, what we're going to talk about is this evaluator.\n\n180\n00:09:12,670 --> 00:09:15,200\n基本运算和Lisp没有什么特别的关系\nThe primitive operators have nothing particular to do with LISP,\n\n181\n00:09:15,200 --> 00:09:18,144\n它们只取决于你怎么实现基本运算\nthey're however you like to implement primitive operations.\n\n182\n00:09:19,360 --> 00:09:22,180\n读取器和打印程序实际上很复杂\nThe reader and printer are actually complicated,\n\n183\n00:09:22,180 --> 00:09:23,552\n但是我们不去讨论它们\nbut we're not going to talk about them.\n\n184\n00:09:24,688 --> 00:09:27,100\n从字符构建表的过程中\nThey sort of have to do with details of how you might build\n\n185\n00:09:27,100 --> 00:09:28,928\n它们需要处理很多细节\nbuild up list structure from characters.\n\n186\n00:09:29,900 --> 00:09:31,184\n说来话长\nSo that is a long story,\n\n187\n00:09:31,184 --> 00:09:32,320\n我们就不讨论它了\nbut we're not going to talk about it,\n\n188\n00:09:32,490 --> 00:09:33,696\n关于表结构内存\nthe list structure memory,\n\n189\n00:09:34,368 --> 00:09:35,632\n我们下次再来讨论\nwe'll talk about next time.\n\n190\n00:09:36,930 --> 00:09:39,728\n那么去除了读取和打印的细节\nSo, pretty much, except for the details of reading and printing,\n\n191\n00:09:40,120 --> 00:09:41,712\n关于这个求值器\nthe only mystery that's going to be left\n\n192\n00:09:41,728 --> 00:09:43,056\n所剩下的唯一谜团\nafter you see the evaluator\n\n193\n00:09:43,250 --> 00:09:45,856\n几乎就只有怎么在传统内存上构建表结构了\nis how you build list structure on conventional memories.\n\n194\n00:09:46,656 --> 00:09:48,208\n不过我们把那也放到下次来讨论\nBut we'll worry about that next time too.\n\n195\n00:09:50,580 --> 00:09:51,040\n好\nOK.\n\n196\n00:09:53,344 --> 00:09:56,110\n那么 我们先来看看这个求值器\nWell, let's start talking about the evaluator.\n\n197\n00:09:56,200 --> 00:09:58,320\n我将要展示的这个求值器\nThe one that we're going to show you,\n\n198\n00:09:58,496 --> 00:10:01,120\n我想 它并没有什么特别的\nof course, is not, I think, nothing special about it.\n\n199\n00:10:01,152 --> 00:10:04,560\n它只是一台专门运行Lisp的寄存器机器\nIt's just a particular register machine that runs LISP.\n\n200\n00:10:04,810 --> 00:10:06,096\n它有七个寄存器\nAnd it has seven registers,\n\n201\n00:10:07,888 --> 00:10:09,264\n这是它的七个寄存器\nand here are the seven registers.\n\n202\n00:10:09,890 --> 00:10:12,384\n这个寄存器叫EXP\nThere's a register, called EXP\n\n203\n00:10:14,120 --> 00:10:15,536\n它的任务是存放\nand its job is to hold\n\n204\n00:10:16,368 --> 00:10:18,032\n将要被求值的表达式\nthe expression to be evaluated.\n\n205\n00:10:18,370 --> 00:10:19,808\n具体来说\nAnd by that, I mean\n\n206\n00:10:20,384 --> 00:10:21,648\n它存放的是一个指针\nit's going to hold a pointer\n\n207\n00:10:22,032 --> 00:10:23,552\n指针指向存放着求值的表达式\nto someplace in list structure memory\n\n208\n00:10:23,568 --> 00:10:25,328\n的一处表结构内存\nthe expression to be evaluated.\n\n209\n00:10:26,550 --> 00:10:27,824\n还有一个叫做ENV的寄存器\nThere's a register, called ENV,\n\n210\n00:10:28,880 --> 00:10:30,288\n它存放着环境\nwhich holds the environment\n\n211\n00:10:31,000 --> 00:10:33,056\n也就是表达式的求值环境\nin which this expression is to be evaluated.\n\n212\n00:10:34,070 --> 00:10:35,024\n同样的 这也是一个指针\nAnd, again, I made a pointer.\n\n213\n00:10:35,024 --> 00:10:36,752\n环境是一种数据结构\nThe environment is some data structure.\n\n214\n00:10:38,240 --> 00:10:40,144\n这个叫做FUN的寄存器--\nThere's a register, called FUN, which will\n\n215\n00:10:40,752 --> 00:10:42,544\n当你在应用一个过程时\nwhich will hold the procedure to be applied\n\n216\n00:10:42,576 --> 00:10:43,968\n它会存放这个过程\nwhen you go to apply a procedure.\n\n217\n00:10:44,560 --> 00:10:46,240\n还有寄存器ARGL\nA register, called ARGL,\n\n218\n00:10:47,360 --> 00:10:49,344\n它存放的是已求值的参数\nwhich holds the list of evaluated arguments.\n\n219\n00:10:50,540 --> 00:10:51,600\n从这里开始你能看到\nWhat you can start seeing here is\n\n220\n00:10:51,632 --> 00:10:53,140\n求值器的基本构造\nthe basic structure of the evaluator.\n\n221\n00:10:53,140 --> 00:10:54,490\n回忆一下它是怎么工作的\nRemember how evaluators work.\n\n222\n00:10:54,490 --> 00:10:56,624\n对这一块输入表达式和环境\nThere's a piece that takes expressions and environments,\n\n223\n00:10:57,670 --> 00:10:59,712\n而这一块接收函数\nand there's a piece that takes functions\n\n224\n00:10:59,744 --> 00:11:02,144\n或者说 过程以及参数\nor procedures and arguments.\n\n225\n00:11:03,480 --> 00:11:06,304\nEVAL-APPLY循环使用这些寄存器工作\nAnd going back and forth around here is the eval/apply loop.\n\n226\n00:11:07,408 --> 00:11:09,696\n所以这些是EVAL-APPLY的基本组成部分\nSo those are the basic pieces of the eval and apply.\n\n227\n00:11:10,200 --> 00:11:10,992\n还有一些别的东西\nThen there's some other things,\n\n228\n00:11:11,008 --> 00:11:11,610\n比如CONTINUE寄存器\nthere's continue.\n\n229\n00:11:11,610 --> 00:11:15,340\n你之前已经见过CONTINUE寄存器\nYou just saw before how the continue register is used to\n\n230\n00:11:15,340 --> 00:11:18,048\n是如何实现递归以及栈操作的\nimplement recursion and stack discipline.\n\n231\n00:11:18,940 --> 00:11:20,688\n还有个寄存器用来存放\nThere's a register that's going to hold the\n\n232\n00:11:20,944 --> 00:11:22,520\n某个求值的结果\nresult of some evaluation.\n\n233\n00:11:24,140 --> 00:11:24,896\n然后 除了这些以外\nAnd then, besides that,\n\n234\n00:11:24,896 --> 00:11:26,432\n还有一个临时寄存器\nthere's one temporary register,\n\n235\n00:11:26,700 --> 00:11:27,296\n它就是UNEV\ncalled UNEV,\n\n236\n00:11:27,296 --> 00:11:29,040\n一般来讲 在求值器中\nwhich typically, in the evaluator,\n\n237\n00:11:29,280 --> 00:11:32,720\n它是用来存放正在求值的表达式\nis going to be used to hold temporary pieces of the\n\n238\n00:11:32,896 --> 00:11:33,950\n的临时部分\nexpression you're working on,\n\n239\n00:11:33,950 --> 00:11:35,728\n就是那些尚未求值的部分\nwhich you haven't gotten around to evaluate yet\n\n240\n00:11:36,976 --> 00:11:39,824\n那么 这就是我的七寄存器机器\nRight? So there's my machine: a seven-register machine.\n\n241\n00:11:40,960 --> 00:11:42,980\n当然 你可能想造一台\nAnd, of course, you might want to make a machine with\n\n242\n00:11:42,980 --> 00:11:44,960\n有更多寄存器的机器 来取得更好性能\na lot more registers to get better performance,\n\n243\n00:11:44,976 --> 00:11:47,056\n但我们这个只是一台小型机器\nbut this is just a tiny, minimal one.\n\n244\n00:11:48,480 --> 00:11:49,584\n那么数据通路呢？\nWell, how about the data paths?\n\n245\n00:11:49,780 --> 00:11:53,664\n这台机器有很多专为Lisp设计的运算\nThis machine has a lot of special operations for LISP.\n\n246\n00:11:55,100 --> 00:11:58,080\n这里有几条典型的数据通路\nSo, here are some typical data paths.\n\n247\n00:12:00,120 --> 00:12:01,040\n其中一条可能是\nA typical one might be,\n\n248\n00:12:01,370 --> 00:12:03,408\n将EXP寄存器的值\noh, assign to the VAL register\n\n249\n00:12:03,408 --> 00:12:04,800\n赋给VAL寄存器\nthe contents of the EXP register.\n\n250\n00:12:05,710 --> 00:12:08,016\n用我们之前的数据通路图来说\nThat's in terms of those diagrams you saw,\n\n251\n00:12:08,032 --> 00:12:10,816\n就是一条箭头上的小按钮\nthat's a little button on some arrow.\n\n252\n00:12:11,900 --> 00:12:13,136\n这还有一个更复杂的\nHere's a more complicated one.\n\n253\n00:12:13,690 --> 00:12:14,800\n它判断\nIt says branch,\n\n254\n00:12:15,230 --> 00:12:19,584\n如果EXP寄存器的内容是COND语句\nif the thing in the expression register is a conditional\n\n255\n00:12:20,496 --> 00:12:22,720\n那么这里就会跳转到EV-COND标号处\nto some label here, called the ev-conditional.\n\n256\n00:12:23,808 --> 00:12:26,230\n你可以想象出很多种实现它的方法\nAnd you can imagine this implemented in a lot of different ways.\n\n257\n00:12:26,230 --> 00:12:28,368\n你可以把这个判断看作是\nYou might imagine this conditional test\n\n258\n00:12:28,368 --> 00:12:29,984\n一个特殊意图的子过程\nas a special purpose sub-routine,\n\n259\n00:12:30,600 --> 00:12:33,952\n而条件被表示成某种数据抽象\nand conditional might be represented as some data abstraction\n\n260\n00:12:33,968 --> 00:12:36,000\n你在这个层面上不用考虑它\nthat you don't care about at this level of detail.\n\n261\n00:12:36,610 --> 00:12:37,980\n那么它可以用子过程实现\nSo that might be done as a sub-routine.\n\n262\n00:12:37,980 --> 00:12:40,672\n如果机器通过硬件来判断表达式类型\nThis might be a machine with hardware-types,\n\n263\n00:12:40,900 --> 00:12:44,048\n那么某些特定比特就代表了COND语句\nand conditional might be testing some bits for a particular code.\n\n264\n00:12:45,350 --> 00:12:46,410\n有很多种实现办法\nThere are all sorts of ways that's\n\n265\n00:12:46,410 --> 00:12:48,480\n它们都低于我们关注的这一层抽象\nbeneath the level of abstraction we're looking at.\n\n266\n00:12:50,190 --> 00:12:51,712\n然后还有另一种操作\nAnother kind of operation,\n\n267\n00:12:51,712 --> 00:12:53,240\n以及其它很多操作\nand there are a lot of different operations\n\n268\n00:12:53,240 --> 00:12:56,656\n把EXP的第一个子句赋值给EXP\nassigned to EXP, the first clause of what's in EXP.\n\n269\n00:12:56,840 --> 00:12:58,896\n这可能是处理COND语句的一部分\nThis might be part of processing a conditional.\n\n270\n00:12:59,260 --> 00:13:01,808\n同样 FIRST-SELECTOR这个选择子\nAnd, again, first clause is some selector\n\n271\n00:13:03,072 --> 00:13:04,480\n我们也不需要关心它的细节\nwhose details we don't care about.\n\n272\n00:13:04,496 --> 00:13:06,464\n同样可以把那也看成一个子过程\nAnd you can, again, imagine that as a sub-routine\n\n273\n00:13:06,460 --> 00:13:07,904\n用来进行一些表操作\nwhich'll do some list operations,\n\n274\n00:13:08,224 --> 00:13:09,180\n或者你也可以想象成\nor you can imagine that as\n\n275\n00:13:09,180 --> 00:13:10,736\n一个直接构建在硬件中的东西\nsomething that's built directly into hardware.\n\n276\n00:13:12,170 --> 00:13:13,712\n我之所以强调\nThe reason I keep saying you can imagine it\n\n277\n00:13:14,032 --> 00:13:15,220\n你可以把它想象成硬件直接实现\nbuilt directly into hardware\n\n278\n00:13:15,220 --> 00:13:17,808\n是因为尽管有很多的运算\nis even though there are a lot of operations,\n\n279\n00:13:18,360 --> 00:13:19,740\n但也它们的数量也是固定的\nthere are still a fixed number of them.\n\n280\n00:13:20,128 --> 00:13:21,808\n我记不清有多少 大概有150个\nI forget how many, maybe 150.\n\n281\n00:13:22,370 --> 00:13:25,392\n所以假设用硬件实现它们是合理的\nSo, it's plausible to think of building these directly into hardware.\n\n282\n00:13:26,416 --> 00:13:27,680\n而这一条更加复杂\nHere's a more complicated one.\n\n283\n00:13:28,270 --> 00:13:29,472\n你会发现 这条涉及到\nYou can see this has to do with\n\n284\n00:13:29,472 --> 00:13:31,104\n查找变量的值\nlooking up the values of variables.\n\n285\n00:13:31,500 --> 00:13:33,280\n它会查找某条表达式中\nIt says assign to the VAL register\n\n286\n00:13:33,456 --> 00:13:36,912\n某个变量的值\nthe result of looking up the variable value\n\n287\n00:13:36,992 --> 00:13:38,528\n并赋值给VAL寄存器\nof some particular expression,\n\n288\n00:13:39,180 --> 00:13:40,304\n在本例中 也就是\nwhich, in this case, is supposed to be\n\n289\n00:13:40,336 --> 00:13:42,000\n在某个环境中查找变量\na variable in some environment.\n\n290\n00:13:42,800 --> 00:13:44,688\n然后这个操作\nAnd this'll be some operation\n\n291\n00:13:45,210 --> 00:13:47,504\n会搜索整个环境结构\nthat search through the environment structure,\n\n292\n00:13:47,520 --> 00:13:48,976\n无论环境是如何表示的\nhowever it is represented,\n\n293\n00:13:49,376 --> 00:13:50,912\n并查找该变量\nand goes and looks up that variable.\n\n294\n00:13:52,176 --> 00:13:53,952\n同样 它也不在我们思考的\nAnd, again, that's below the level of detail\n\n295\n00:13:53,960 --> 00:13:54,864\n的抽象层面上\nthat we're thinking about.\n\n296\n00:13:54,896 --> 00:13:57,300\n它需要处理的细节是\nThis is... this has to do with the details of\n\n297\n00:13:57,552 --> 00:13:59,440\n用来表示环境的数据结构\nthe data structures for representing environments.\n\n298\n00:14:00,070 --> 00:14:01,216\n但是不管怎么说\nBut, anyway, there is this\n\n299\n00:14:01,312 --> 00:14:03,470\n这就是这台寄存器机器的\nthere is this fixed and finite number\n\n300\n00:14:04,112 --> 00:14:06,080\n有穷数量的固定操作\nof operations in the register machine.\n\n301\n00:14:08,500 --> 00:14:11,600\n那么 它的整体结构是什么样子的？\nWell, what's its overall structure?\n\n302\n00:14:11,720 --> 00:14:13,232\n这有几个典型的运算\nThose are some typical operations.\n\n303\n00:14:14,768 --> 00:14:16,336\n想一想 我们要做什么\nRemember what we have to do,\n\n304\n00:14:16,440 --> 00:14:18,400\n我们需要把元循环求值器\nwe have to take the meta-circular evaluator--\n\n305\n00:14:20,432 --> 00:14:22,760\n这就是元循环求值器的一部分\nand here's a piece of the meta-circular evaluator.\n\n306\n00:14:22,760 --> 00:14:26,896\n这是书中使用抽象代码的版本\nThis is the one using abstract syntax that's in the book.\n\n307\n00:14:28,224 --> 00:14:31,536\n它和Gerry教授给你们展示的有些不同\nIt's a little bit different from the one that Gerry shows you.\n\n308\n00:14:33,500 --> 00:14:35,104\n关于求值器\nAnd the main thing\n\n309\n00:14:35,136 --> 00:14:37,870\n主要需要记住的是\nto remember about the evaluator is that\n\n310\n00:14:37,870 --> 00:14:40,960\n它是某种针对表达式类型的分情况分析\nit's doing some sort of case analysis on the kinds of expressions:\n\n311\n00:14:43,760 --> 00:14:45,904\n看它是否为自求值的 或被引用的\nso if it's either self-evaluated, or quoted,\n\n312\n00:14:45,920 --> 00:14:46,864\n或是别的什么\nor whatever else.\n\n313\n00:14:48,560 --> 00:14:50,576\n而在大部分情况下\nAnd then, in the general case where\n\n314\n00:14:50,860 --> 00:14:52,960\n它处理的是一个过程应用\nthe expression it's looking at is an application,\n\n315\n00:14:53,550 --> 00:14:55,360\n那么里面有一些技巧性的递归过程\nthere's some tricky recursions going on.\n\n316\n00:14:55,750 --> 00:14:59,360\n首先 EVAL要调用它自己\nFirst of all, eval has to call itself\n\n317\n00:14:59,790 --> 00:15:01,456\n来求值运算符以及\nboth to evaluate the operator\n\n318\n00:15:02,144 --> 00:15:04,048\n所有的运算对象\nand to evaluate all the operands.\n\n319\n00:15:05,880 --> 00:15:07,408\n因此这些标红线的地方\nSo there's this sort of red recursion\n\n320\n00:15:07,632 --> 00:15:09,280\n就是某种在语法树上的递归\nof values walking down the tree\n\n321\n00:15:10,944 --> 00:15:12,270\n这是很简单的递归\nthat's sort of the easy recursion.\n\n322\n00:15:12,270 --> 00:15:14,448\n只是EVAL在递归地遍历语法树\nThat's just eval walking down this tree of expressions.\n\n323\n00:15:14,750 --> 00:15:15,536\n然后在求值器中\nThen, in the evaluator,\n\n324\n00:15:15,536 --> 00:15:16,460\n有一个复杂的递归\nthere's a hard recursion.\n\n325\n00:15:16,490 --> 00:15:17,920\n由绿线到红线的递归\nThere's the red to green.\n\n326\n00:15:18,000 --> 00:15:19,660\n由EVAL调用APPLY\nEval calls apply.\n\n327\n00:15:22,470 --> 00:15:26,450\n也就是把过程调用\nThat's the case where evaluating a procedure argument\n\n328\n00:15:26,450 --> 00:15:28,720\n归约为了 将过程应用在\nreduces to applying the procedure\n\n329\n00:15:28,944 --> 00:15:29,936\n实参表上\nto the list of arguments.\n\n330\n00:15:30,370 --> 00:15:31,760\n然后请看APPLY\nAnd then, apply comes over here.\n\n331\n00:15:34,770 --> 00:15:36,672\nAPPLY需要过程PROC和参数ARGS\nApply takes a procedure and arguments\n\n332\n00:15:37,650 --> 00:15:39,456\n一般情况下\nand, in the general case\n\n333\n00:15:39,488 --> 00:15:40,816\nPROC都是一个复合过程\nwhere there's a compound procedure,\n\n334\n00:15:41,050 --> 00:15:42,192\n随着APPLY不断被调用\napply goes around and\n\n335\n00:15:42,256 --> 00:15:43,152\n绿线处会调用红线处\ngreen calls red.\n\n336\n00:15:43,344 --> 00:15:46,448\nAPPLY被调用并再次调用EVAL\nEval-- Apply comes around and calls eval again.\n\n337\n00:15:48,170 --> 00:15:49,792\nEVAL会求值过程体\nEval's the body of the procedure\n\n338\n00:15:50,240 --> 00:15:52,592\n基于一个扩展了的环境\nin the result of extending the environment\n\n339\n00:15:53,696 --> 00:15:55,280\n这个环境通过将过程的形式参数\nwith the parameters of the procedure\n\n340\n00:15:55,480 --> 00:15:56,928\n与实际参数绑定起来而得\nby binding the arguments.\n\n341\n00:15:59,620 --> 00:16:00,624\n而对于最基本的情况\nExcept in the primitive case,\n\n342\n00:16:00,640 --> 00:16:02,528\n它会调用PRIMITIVE-APPLY过程\nwhere it just calls something else primitive-apply\n\n343\n00:16:02,736 --> 00:16:04,704\n而那又不是求值器的工作了\nwhich is not really the business of the evaluator.\n\n344\n00:16:05,980 --> 00:16:07,472\n那么像这样从红到绿\nSo this sort of red to green,\n\n345\n00:16:07,470 --> 00:16:08,400\n又到红又到绿\nto red to green,\n\n346\n00:16:09,792 --> 00:16:12,720\n这就是EVAL-APPLY循环\nRight? That's the that's the eval/apply loop,\n\n347\n00:16:14,064 --> 00:16:15,744\n这就是我们在求值器中\nand that's the thing that we're going to want to see\n\n348\n00:16:16,192 --> 00:16:17,728\n想要看到的东西\nin the evaluator.\n\n349\n00:16:19,696 --> 00:16:21,070\n这样 你不会惊异于\nWell, it won't surprise you at all that\n\n350\n00:16:21,070 --> 00:16:23,520\n这个求值器的两大部分\nthe two big pieces of this evaluator\n\n351\n00:16:25,344 --> 00:16:27,040\n对应于EVAL-APPLY\nare correspond to eval and apply.\n\n352\n00:16:27,470 --> 00:16:29,440\n一个部分叫EVAL-DISPATCH\nThere's a piece called eval-dispatch,\n\n353\n00:16:29,600 --> 00:16:31,200\n另一部分叫做APPLY-DISPATCH\nand a piece called apply-dispatch.\n\n354\n00:16:32,000 --> 00:16:34,090\n在我们关注代码细节之前\nAnd, before we get into the details of the code,\n\n355\n00:16:34,208 --> 00:16:35,760\n理解它们的方法就是\nthe way to understand this is to think,\n\n356\n00:16:36,090 --> 00:16:39,024\n假设这些求值器的各个部分\nagain, in terms of these pieces of evaluator\n\n357\n00:16:39,024 --> 00:16:40,976\n和这个世界中其它的部分有一些约定\nhaving contracts with the rest of the world.\n\n358\n00:16:41,870 --> 00:16:43,184\n在进入这些肮脏的细节前\nWhat do they do from the outside\n\n359\n00:16:43,200 --> 00:16:45,504\n它们在外部做了什么？\nbefore getting into the grungy details?\n\n360\n00:16:45,780 --> 00:16:49,328\n针对EVAL-DISPATCH的约定\nWell, the contract for eval-dispatch--\n\n361\n00:16:50,016 --> 00:16:51,408\n还记得吗 它对应的是EVAL\nremember, it corresponds to eval.\n\n362\n00:16:51,552 --> 00:16:54,100\n它要在环境中求值一个表达式\nIt's got to evaluate an expression in an environment.\n\n363\n00:16:54,100 --> 00:16:55,888\n那么 这部分要做的就是\nSo, in particular, what this one is going to do,\n\n364\n00:16:56,520 --> 00:16:58,688\nEVAL-DISPATCH会假设当你调用它的时候\neval-dispatch will assume that, when you call it,\n\n365\n00:16:59,680 --> 00:17:01,488\n你想要求值的表达式\nthat the expression you want to evaluate\n\n366\n00:17:01,488 --> 00:17:02,528\n就存放在EXP寄存器中\nis in the EXP register.\n\n367\n00:17:03,640 --> 00:17:07,392\n而求值所基于的环境\nThe environment in which you want the evaluation\n\n368\n00:17:07,456 --> 00:17:09,056\n则存放在ENV环境中\nto take place is in the ENV register.\n\n369\n00:17:09,560 --> 00:17:10,672\n而CONTINUE寄存器用来指示\nAnd continue tells you\n\n370\n00:17:10,848 --> 00:17:12,464\n当求值完成后\nthe place where the machine should go next\n\n371\n00:17:12,528 --> 00:17:13,920\n机器需要去向何方\nwhen the evaluation is done.\n\n372\n00:17:17,280 --> 00:17:19,184\nEVAL-DISPATCH的约定实际上就是\nEval-dispatch's contract is that\n\n373\n00:17:19,280 --> 00:17:21,264\n它会执行实际的求值\nit'll actually perform that evaluation,\n\n374\n00:17:21,400 --> 00:17:22,464\n并且在求值结束后\nand, at the end of which,\n\n375\n00:17:23,280 --> 00:17:25,632\n它会转到由CONTINUE寄存器指定的位置\nit'll end up at the place specified by continue.\n\n376\n00:17:26,610 --> 00:17:29,168\n求值的结果会存放在VAL寄存器中\nThe result of the evaluation will be in the VAL register.\n\n377\n00:17:29,820 --> 00:17:30,960\n需要提醒的是\nAnd it just warns you,\n\n378\n00:17:30,992 --> 00:17:32,912\n它对其余的寄存器\nit makes no promises about\n\n379\n00:17:32,960 --> 00:17:34,608\n不做任何承诺\nwhat happens to rest the registers.\n\n380\n00:17:35,230 --> 00:17:36,816\n其它所有的寄存器都可能被修改\nAll other registers might be destroyed.\n\n381\n00:17:37,490 --> 00:17:40,144\n那么这是一部分\nSo, there's one piece, OK?\n\n382\n00:17:41,552 --> 00:17:43,488\n这些部分一块构成了APPLY-DISPATCH\nTogether, the pieces, apply-dispatch\n\n383\n00:17:43,520 --> 00:17:44,928\n它们对应了APPLY\nthat corresponds to apply,\n\n384\n00:17:46,096 --> 00:17:48,432\n用来把一个过程应用在一些参数上\nit's got to apply a procedure to some arguments,\n\n385\n00:17:48,730 --> 00:17:51,430\n因此它假设ARGL寄存器\nso it assumes that this register, ARGL,\n\n386\n00:17:51,680 --> 00:17:53,776\n存放着求值后的参数列表\ncontains a list of the evaluated arguments.\n\n387\n00:17:54,540 --> 00:17:55,968\nFUN寄存器存放着那个过程\nFUN contains the procedure.\n\n388\n00:17:57,220 --> 00:17:58,832\n它们对应于元循环求值器中的\nThose correspond to the arguments to\n\n389\n00:17:58,944 --> 00:18:01,360\n参数应用部分\nthe apply procedure in the meta-circular evaluator.\n\n390\n00:18:03,970 --> 00:18:06,048\n在我们的这个求值器中\nAnd apply, in this particular evaluator,\n\n391\n00:18:06,064 --> 00:18:07,584\n我们APPLY时采用的约定是\nwe're going to use a discipline which says\n\n392\n00:18:07,720 --> 00:18:08,976\n当APPLY完成后--\nthe place that apply\n\n393\n00:18:09,470 --> 00:18:11,200\n机器应该跳转到\nthe place the machine should go to next\n\n394\n00:18:11,792 --> 00:18:13,456\n的下一个地方应该是\nwhen apply is done, is at the moment\n\n395\n00:18:13,552 --> 00:18:15,920\nAPPLY-DISPATCH被调用时的栈顶元素\napply-dispatch is called at the top of the stack\n\n396\n00:18:17,070 --> 00:18:21,248\n这只是针对这台机器的约定\nthat's just discipline for the way this particular machine's organized.\n\n397\n00:18:21,840 --> 00:18:23,700\n现在已经给出了APPLY的所有约定\nAnd now apply's contract is given all that.\n\n398\n00:18:23,936 --> 00:18:25,376\n它会去执行应用\nIt'll perform the application.\n\n399\n00:18:25,540 --> 00:18:27,856\n这个应用的结果将会保存在VAL寄存器中\nThe result of that application will end up in VAL.\n\n400\n00:18:28,890 --> 00:18:29,952\n栈会被弹出\nThe stack will be popped.\n\n401\n00:18:31,120 --> 00:18:31,664\n同样的\nAnd, again,\n\n402\n00:18:31,712 --> 00:18:34,030\n其它所有寄存器的内容都可能被修改\nthe contents of all the other registers may be destroyed.\n\n403\n00:18:34,840 --> 00:18:37,824\n那么 这就是这台机器的基本结构\nAll right? So that's the basic organization of this machine.\n\n404\n00:18:38,992 --> 00:18:41,504\n我们先课间休息一下\nLet's break for a little bit and see if there are any questions\n\n405\n00:18:41,520 --> 00:18:42,700\n然后再来研究一个真实的例子\nand then we'll do a real example.\n\n406\n00:18:43,530 --> 00:19:08,112\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n407\n00:19:08,144 --> 00:19:13,472\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n408\n00:19:33,100 --> 00:19:35,872\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Sussman Jay Sussman\n\n\n409\n00:19:35,870 --> 00:19:40,384\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n410\n00:19:40,380 --> 00:19:45,296\n显式控制求值器\nExplicit-control Evaluator\n\n411\n00:19:47,850 --> 00:19:49,952\n现在 我们来研究一下这台寄存器机器\nWell, let's take the register machine now,\n\n412\n00:19:50,416 --> 00:19:51,776\n我们一步一步地跟进\nand actually step through,\n\n413\n00:19:52,270 --> 00:19:56,944\n具体到每一处细节\nand really, in real detail,\n\n414\n00:19:57,072 --> 00:19:58,520\n这样你就能完全具体地看到\nso you see completely concrete\n\n415\n00:19:58,864 --> 00:20:01,248\n表达式是如何求值的\nhow some expressions are evaluated,\n\n416\n00:20:03,150 --> 00:20:06,864\n那么我们从一个非常简单的表达式开始\nAlright? So, let's start with a very simple expression.\n\n417\n00:20:07,456 --> 00:20:13,520\n我们要求值的表达式只有一个1\nLet's evaluate the expression 1.\n\n418\n00:20:18,770 --> 00:20:20,400\n我们需要一个环境\nAnd we need an environment,\n\n419\n00:20:20,432 --> 00:20:22,352\n因此我们假设某处有一个环境\nso let's imagine that somewhere there's an environment\n\n420\n00:20:22,384 --> 00:20:23,392\n我们把它记作E0\nwe'll call it E0.\n\n421\n00:20:30,064 --> 00:20:34,560\n由于我们之后也要用到它\nAnd just, since we'll use these later,\n\n422\n00:20:35,620 --> 00:20:37,040\n而且显然不需要任何东西\nwe obviously don't really need anything\n\n423\n00:20:37,072 --> 00:20:37,930\n就可以求值1\nto evaluate 1.\n\n424\n00:20:38,360 --> 00:20:39,456\n但是为了方便以后引用\nBut, just for reference later,\n\n425\n00:20:39,456 --> 00:20:40,944\n我们假设环境E0中有\nlet's assume that E0 has in it\n\n426\n00:20:41,440 --> 00:20:43,152\nX=3\nan X that's bound to 3\n\n427\n00:20:43,720 --> 00:20:45,370\nY=4\nand a Y that's bound to 4,\n\n428\n00:20:48,272 --> 00:20:48,784\n好吗？\nOK?\n\n429\n00:20:49,140 --> 00:20:50,128\n现在 我们要做的就是\nAnd now what we're going to do\n\n430\n00:20:50,510 --> 00:20:54,592\n在这个环境中求值表达式1\nis we're going to evaluate 1 in this environment\n\n431\n00:20:55,744 --> 00:20:58,544\n这样 ENV寄存器就存放了一个指针\nand so the ENV register has a pointer\n\n432\n00:20:59,650 --> 00:21:01,040\n指向这个环境E0\nto this environment, E0, all right?\n\n433\n00:21:03,312 --> 00:21:05,650\n那么我们来看它是怎么进行的\nRight? So let's watch that thing go.\n\n434\n00:21:05,650 --> 00:21:07,264\n我要步步跟进代码\nWhat I'm going to do is step through the code.\n\n435\n00:21:08,260 --> 00:21:10,000\n这样的话 我会充当控制器\nAnd, let's see, I'll be the controller.\n\n436\n00:21:10,040 --> 00:21:10,800\n现在我需要的是--\nAnd now what I need,\n\n437\n00:21:11,024 --> 00:21:12,490\n由于这台机器已经变得相当复杂\nsince this gets rather complicated,\n\n438\n00:21:12,980 --> 00:21:16,830\n我需要一个小小的执行单元\nis a very little execution unit.\n\n439\n00:21:16,830 --> 00:21:18,160\n那么请上我们的执行单元\nSo here's the execution unit, OK?\n\n440\n00:21:22,620 --> 00:21:23,120\n好的\nOK.\n\n441\n00:21:28,590 --> 00:21:29,968\n好 现在我们要开始了\nAll right, now we're going to start.\n\n442\n00:21:30,530 --> 00:21:32,480\n我们要从EVAL-DISPATCH启动机器\nWe're going to start the machine at eval-dispatch。\n\n443\n00:21:33,264 --> 00:21:34,624\n这是整个过程的开始\nRight? That's the beginning of this.\n\n444\n00:21:35,870 --> 00:21:38,752\nEVAL-DISPATCH会查看表达式并进行分派\nEval-dispatch is going to look at the expression and dispatch,\n\n445\n00:21:39,320 --> 00:21:40,064\n就像EVAL\njust like eval\n\n446\n00:21:40,870 --> 00:21:42,000\n先从第一句看起\nwhere we look at the very first thing.\n\n447\n00:21:42,048 --> 00:21:47,950\n先判断表达式是不是自求值的\nWe branch on whether or not this expression is self-evaluating.\n\n448\n00:21:47,950 --> 00:21:49,968\nSELF-EVALUATING?是我们放入机器的\nSelf-evaluating is some abstraction\n\n449\n00:21:49,968 --> 00:21:51,100\n一个抽象过程\nwe put into the machine--\n\n450\n00:21:52,224 --> 00:21:53,510\n它对于数字1来说为真\nit's going to be true for numbers--\n\n451\n00:21:53,648 --> 00:21:55,520\n因此跳转的目的是EV-SELF-EVAL\nto a place called ev-self-eval,\n\n452\n00:21:56,770 --> 00:21:58,208\n那么我作为控制器\nSo me, being the controller,\n\n453\n00:21:58,224 --> 00:21:59,552\n会去查看EV-SELF-EVAL\nlooks at ev-self-eval,\n\n454\n00:22:00,064 --> 00:22:01,072\n所以我们要跳到那里\nso we'll go over to there.\n\n455\n00:22:02,600 --> 00:22:04,768\nEV-SELF-EAVL的代码是--\nEv-self-eval says fine,\n\n456\n00:22:06,544 --> 00:22:09,904\n把EXP寄存器的值赋值给VAL寄存器\nassign to val whatever is in the expression unit.\n\n457\n00:22:15,248 --> 00:22:16,512\n我遇到一个BUG\nAnd I have a bug\n\n458\n00:22:17,936 --> 00:22:20,592\n因为我初始化机器的时候没有做一件事情\nbecause what I didn't do when I initialized this machine\n\n459\n00:22:21,620 --> 00:22:22,896\n也就是指定当它执行完毕后\nis also say what's supposed\n\n460\n00:22:22,912 --> 00:22:24,192\n应该做什么\nto happen when it's done,\n\n461\n00:22:24,650 --> 00:22:26,832\n所以在启动机器的时候\nso I should have started out the machine\n\n462\n00:22:27,376 --> 00:22:29,856\n应该将CONTINUE寄存器设置为DONE\nwith done being in the continue register,\n\n463\n00:22:31,184 --> 00:22:33,264\n所以我们给VAL赋值\nOK? So we assign to VAL.\n\n464\n00:22:33,370 --> 00:22:35,568\n然后执行(GOTO (FETCH CONTINUE))\nAnd now go to fetch of continue,\n\n465\n00:22:35,632 --> 00:22:36,560\n并且修改--\nand now change--\n\n466\n00:22:38,096 --> 00:22:38,608\n好\nOK.\n\n467\n00:22:40,000 --> 00:22:41,168\n好 我们来看一个更复杂的\nOK, let's try something harder.\n\n468\n00:22:42,160 --> 00:22:43,456\n我们先重置机器\nLet's reset the machine here,\n\n469\n00:22:44,864 --> 00:22:50,880\n然后把X放入EXP寄存器中\nand we'll put in the expression register, X, OK?\n\n470\n00:22:56,710 --> 00:22:58,208\n重新从EVAL-DISPATCH开始\nStart again at eval-dispatch.\n\n471\n00:22:59,610 --> 00:23:01,690\n先检查它是自求值的么？\nCheck, is it self-evaluating?\n\n472\n00:23:01,690 --> 00:23:02,032\n不是\nNo.\n\n473\n00:23:02,650 --> 00:23:03,616\n它是变量吗\nIs it a variable?\n\n474\n00:23:04,630 --> 00:23:05,024\n是的\nYes.\n\n475\n00:23:05,560 --> 00:23:07,072\n我们跳转到EV-VARIABLE\nWe go off to ev-variable.\n\n476\n00:23:08,380 --> 00:23:10,976\n它说：查找EXP寄存器中变量的值\nIt says assign to VAL,\n\n477\n00:23:12,130 --> 00:23:15,696\n并把它赋值给VAL寄存器\nlook up the variable value in the expression register\n\n478\n00:23:21,232 --> 00:23:22,912\n(GOTO (FETCH CONTINUE))\nGo to fetch of continue.\n\n479\n00:23:23,968 --> 00:23:24,480\nSussman教授：DONE\nPROFESSOR: Done.\n\n480\n00:23:27,616 --> 00:23:28,096\nAbelson教授：好\nPROFESSOR: OK.\n\n481\n00:23:29,312 --> 00:23:30,768\n这些都是最基本的理念\nAlright, Well, that's the basic idea. Those're\n\n482\n00:23:31,330 --> 00:23:32,656\n这是这台机器上的简单运算\nThat's a simple operation of the machine.\n\n483\n00:23:32,680 --> 00:23:35,072\n现在 我们来做些有意义的事情\nNow, let's actually do something a little bit more interesting.\n\n484\n00:23:36,070 --> 00:23:38,640\n我们看这条表达式\nLet's look at the expression\n\n485\n00:23:43,584 --> 00:23:47,936\n(+ X Y)\nthe sum of x and y.\n\n486\n00:23:49,696 --> 00:23:51,280\n现在我们会看到\nOK. And now we'll see how you start\n\n487\n00:23:52,416 --> 00:23:54,016\n如何展开这些表达式树\nunrolling these expression trees.\n\n488\n00:23:57,136 --> 00:23:58,688\n我们再次从EVAL-DISPATCH开始\nWell, start again at eval-dispatch.\n\n489\n00:24:04,610 --> 00:24:05,808\n是自求值的吗？\nSelf-evaluating?\n\n490\n00:24:05,952 --> 00:24:06,528\n不是\nNo.\n\n491\n00:24:06,704 --> 00:24:07,712\n是变量吗？不是\nVariable? No.\n\n492\n00:24:07,820 --> 00:24:08,992\n它也不是我在这里\nAll the other special forms\n\n493\n00:24:08,992 --> 00:24:10,120\n没有列出的特殊形式\nwhich I didn't write down,\n\n494\n00:24:10,270 --> 00:24:12,480\n比如引用、LAMBDA、SET! 等等\nlike quote, and lambda, and set, and whatever,\n\n495\n00:24:12,480 --> 00:24:13,088\n它都不是\nit's none of those.\n\n496\n00:24:13,260 --> 00:24:14,736\n它是一个过程应用\nIt turns out to be an application,\n\n497\n00:24:15,880 --> 00:24:17,424\n所以我们要跳转到EV-APPLICATION\nso we go off to ev-application.\n\n498\n00:24:19,970 --> 00:24:24,944\n回忆一下EV-APPLICATION要做什么\nEv-application, remember what it's going to do overall.\n\n499\n00:24:25,580 --> 00:24:28,192\n它先要求值运算符\nIt is going to evaluate the operator.\n\n500\n00:24:28,272 --> 00:24:31,408\n然后求值运算对象\nIt's going to evaluate the arguments,\n\n501\n00:24:32,368 --> 00:24:34,304\n然后再进行应用\nand then it's going to go apply them.\n\n502\n00:24:35,060 --> 00:24:36,096\n所以在我们开始之前\nSo, before we start,\n\n503\n00:24:36,944 --> 00:24:37,880\n由于我们是严格按照代码来执行的\nsince we're being very literal,\n\n504\n00:24:37,880 --> 00:24:38,880\n我们最好记住\nwe'd better remember that,\n\n505\n00:24:39,070 --> 00:24:40,544\n在这个环境中的某处\nsomewhere in this environment,\n\n506\n00:24:40,576 --> 00:24:42,368\n连接到了另一个环境\nit's linked to another environment\n\n507\n00:24:43,980 --> 00:24:44,944\n其中符号'+\nin which plus\n\n508\n00:24:45,728 --> 00:24:49,160\n跟基本的加法过程绑定在了一起\nis bound to the primitive procedure plus\n\n509\n00:24:51,632 --> 00:24:54,032\n这样 求值+时就不会导致“变量未定义”\nbefore we get an unknown variable in our machine.\n\n510\n00:24:55,340 --> 00:24:56,848\n现在我们来到了EV-APPLICATION\nOK, so we're at ev-application.\n\n511\n00:24:59,856 --> 00:25:04,320\n把EXP寄存器对应的运算对象\nOK, assign to UNEV the operands\n\n512\n00:25:04,928 --> 00:25:06,896\n赋值给UNEV寄存器\nof what's in the expression register.\n\n513\n00:25:07,616 --> 00:25:08,832\n这些是运算对象\nOK. Those are the operands.\n\n514\n00:25:09,230 --> 00:25:11,664\nUNEV这个临时寄存器\nUNEV's a temporary register\n\n515\n00:25:11,680 --> 00:25:12,590\n就是用来暂存它们的\nwhere we're going to save them.\n\n516\n00:25:13,220 --> 00:25:13,860\nSussman教授：我正在赋值\nPROFESSOR: I'm assigning.\n\n517\n00:25:14,288 --> 00:25:16,624\nAbelson教授：把运算符赋值给EXP寄存器\nPROFESSOR: Assign to EXP the operator.\n\n518\n00:25:18,070 --> 00:25:20,096\n注意 现在我们已经修改了EXP中的表达式\nNow, notice we've destroyed that expression in EXP,\n\n519\n00:25:21,840 --> 00:25:23,616\n但是我们需要的部分在UNEV中\nbut the piece that we need is now in UNEV.\n\n520\n00:25:25,820 --> 00:25:26,816\n现在 我们要准备好\nNow, we're going to get set up to\n\n521\n00:25:26,816 --> 00:25:28,592\n去递归地求值运算符\nto recursively evaluate the operator.\n\n522\n00:25:28,750 --> 00:25:31,696\n把CONTINUE寄存器保存在栈上\nSave the continue register on the stack.\n\n523\n00:25:34,864 --> 00:25:36,096\n保存ENV\nSave the environment.\n\n524\n00:25:40,480 --> 00:25:41,696\n保存UNEV\nSave UNEV.\n\n525\n00:25:49,536 --> 00:25:54,640\n把标号EVAL-ARGS赋值给CONTINUE寄存器\nOK, assign to continue a label called eval-args.\n\n526\n00:26:01,400 --> 00:26:01,950\n我们做了什么\nNow, what have we done?\n\n527\n00:26:01,950 --> 00:26:04,380\n我们为递归调用做了必要的准备\nWe've set up for a recursive call.\n\n528\n00:26:04,380 --> 00:26:05,888\n我们要开始执行EVAL-DISPATCH\nWe're about to go to eval-dispatch.\n\n529\n00:26:06,280 --> 00:26:08,832\n我们为递归调用EVAL-DISPATCH做好了准备\nWe've set up for a recursive call to eval-dispatch.\n\n530\n00:26:10,230 --> 00:26:10,864\n我们做了哪些事情\nWhat did we do?\n\n531\n00:26:11,020 --> 00:26:13,648\n我们把之后要用到的东西\nWe took the things we're going to need later,\n\n532\n00:26:14,480 --> 00:26:15,984\n也就是UNEV中的运算对象\nthose operands that were in UNEV;\n\n533\n00:26:16,360 --> 00:26:18,992\n以及我们最终求值运算对象时\nthe environment in which we're going to eventually have to,\n\n534\n00:26:19,168 --> 00:26:20,720\n会用到的环境\nmaybe, evaluate those operands;\n\n535\n00:26:22,288 --> 00:26:23,936\n以及我们最终想要去的位置\nthe place we eventually want to go to,\n\n536\n00:26:23,952 --> 00:26:25,072\n本例中 也就是DONE\nwhich, in this case, was done;\n\n537\n00:26:25,344 --> 00:26:26,704\n我们把它们保存在栈上\nwe've saved them on the stack.\n\n538\n00:26:27,104 --> 00:26:28,416\n我们之所以把它们保存在栈上\nThe reason we saved them on the stack\n\n539\n00:26:28,430 --> 00:26:30,672\n是因为EVAL-DISPATCH并不会保证\nis because eval-dispatch makes no promises\n\n540\n00:26:30,944 --> 00:26:32,544\n不会去修改这些寄存器\nabout what registers it may destroy.\n\n541\n00:26:33,550 --> 00:26:35,020\n那么所有这些东西都存在了栈上\nSo all that stuff is saved on the stack.\n\n542\n00:26:35,020 --> 00:26:36,912\n现在我们满足了EVAL-DISPATCH的约定\nNow, we've set up eval-dispatch's contract.\n\n543\n00:26:37,380 --> 00:26:38,752\n这是一条新的表达式\nThere's a new expression,\n\n544\n00:26:38,784 --> 00:26:40,048\n也就是+运算符\nwhich is the operator plus;\n\n545\n00:26:41,072 --> 00:26:41,952\n以及一个新的环境\na new environment,\n\n546\n00:26:41,984 --> 00:26:43,600\n尽管在本例中是同一个环境\nalthough, in this case, it's the same one;\n\n547\n00:26:44,250 --> 00:26:45,872\n以及在完成后要返回的位置\nand a new place to go to when you're done,\n\n548\n00:26:45,872 --> 00:26:46,910\n也就是EVAL-ARGS\nwhich is eval-args.\n\n549\n00:26:47,600 --> 00:26:48,130\n这样就满足了\nSo that's set up.\n\n550\n00:26:48,130 --> 00:26:49,680\n现在我们来执行EVAL-DISPATCH\nNow, we're going to go off to eval-dispatch.\n\n551\n00:26:50,890 --> 00:26:52,368\n我们回到了EVAL-DISPATCH\nHere we are back at eval-dispatch.\n\n552\n00:26:53,056 --> 00:26:54,400\n它不是自求值的\nIt's not self-evaluating.\n\n553\n00:26:54,440 --> 00:26:55,472\n但它是一个变量\nOh, it's a variable,\n\n554\n00:26:56,320 --> 00:26:58,064\n因此我们最好跳转到EV-VARIABLE\nso we'd better go off to ev-variable,\n\n555\n00:26:59,792 --> 00:27:02,656\nEV-VARIABLE首先要给VAL赋值\nRight? Ev-variable is assigned to VAL.\n\n556\n00:27:02,704 --> 00:27:06,336\n查找表达式中变量的值\nLook up the variable value of the expression,\n\n557\n00:27:08,496 --> 00:27:10,752\n那么VAL寄存器中应该是基本的加法运算\nOK? So VAL is the primitive procedure plus.\n\n558\n00:27:13,376 --> 00:27:15,168\n然后(GOTO (FETCH CONTINUE))\nAnd go to fetch of continue.\n\n559\n00:27:15,232 --> 00:27:16,112\nSussman教授：它是EVAL-ARGS\nPROFESSOR: Eval-args.\n\n560\n00:27:16,208 --> 00:27:18,736\nAbelson教授：现在它是EVAL-ARGS而不是DONE了\nPROFESSOR: Right, which is now eval-args not done.\n\n561\n00:27:19,424 --> 00:27:21,264\n然后我们来到EVAL-ARGS\nSo we come back here at eval-args,\n\n562\n00:27:22,160 --> 00:27:23,024\n看看它要做什么\nand what do we do?\n\n563\n00:27:23,072 --> 00:27:24,848\n我们要恢复之前保存的东西\nWe're going to restore the stuff that we saved,\n\n564\n00:27:25,200 --> 00:27:26,576\n因此调用(RESTORE UNEV)\nso we restore UNEV.\n\n565\n00:27:29,216 --> 00:27:31,696\n注意 这里并不是必要的\nAnd notice, there, it wasn't necessary,\n\n566\n00:27:31,744 --> 00:27:32,900\n但通常来说都会有这么一步\nalthough, in general, it would be.\n\n567\n00:27:32,900 --> 00:27:35,168\n它可以是任意的求值过程\nIt might be some arbitrary evaluation that happened.\n\n568\n00:27:35,430 --> 00:27:36,704\n恢复ENV寄存器\nWe restore ENV.\n\n569\n00:27:47,872 --> 00:27:52,048\n然后把(FETCH VAL)赋值给FUN\nOK, we assign to FUN fetch of VAL.\n\n570\n00:27:59,952 --> 00:28:02,816\n现在我们要开始求值参数了\nOK, now, we're going to go off and start evaluating some arguments.\n\n571\n00:28:04,340 --> 00:28:06,480\n首先 我们最好把FUN寄存器保存起来\nWell, first thing we'd better do is save FUN\n\n572\n00:28:07,424 --> 00:28:10,624\n因为求值过程中可能发生任何事情\nbecause some arbitrary stuff might happen in that evaluation.\n\n573\n00:28:15,330 --> 00:28:16,880\n我们初始化参数列表\nWe initialize the argument list.\n\n574\n00:28:16,912 --> 00:28:19,296\n给ARGL赋值一个空的参数列表\nAssign to argl an empty argument list,\n\n575\n00:28:20,880 --> 00:28:22,176\n然后跳转到EVAL-ARG-LOOP\nand go to eval-arg-loop,\n\n576\n00:28:24,860 --> 00:28:26,272\n在EVAL-ARG-LOOP中\nAt eval-arg-loop,\n\n577\n00:28:27,770 --> 00:28:31,536\n我们想要去一条一条的求值\nthe idea of this is we're going to evaluate the pieces of the\n\n578\n00:28:31,616 --> 00:28:33,370\nUNEV中的表达式\nexpressions that are in UNEV, one by one,\n\n579\n00:28:33,540 --> 00:28:35,680\n然后把它们从UNEV中的待求值表\nand move them from unevaluated in UNEV\n\n580\n00:28:35,900 --> 00:28:37,264\n移动到ARGL中的已求值表中\nto evaluated in the arg list.\n\n581\n00:28:37,840 --> 00:28:39,184\n然后我们保存ARGL\nOK. So we save argl.\n\n582\n00:28:43,950 --> 00:28:47,264\n然后我们把UNEV中的第一个运算对象\nWe assign to EXP the first operand \n\n583\n00:28:47,376 --> 00:28:48,380\n赋值给EXP\nof the stuff in UNEV.\n\n584\n00:28:53,770 --> 00:28:55,890\n然后我们检查它是否为最后一个运算对象\nNow, we check and see if that was the last operand.\n\n585\n00:28:55,890 --> 00:28:56,912\n在这里 它还不是\nIn this case, it is not.\n\n586\n00:28:58,992 --> 00:29:01,552\n然后我们保存环境\nSo we save the environment.\n\n587\n00:29:08,000 --> 00:29:10,064\n我们之所以保存UNEV\nWe save UNEV\n\n588\n00:29:11,616 --> 00:29:13,500\n是因为稍后我们可能会需要它们\nbecause those are all things we might need later.\n\n589\n00:29:13,500 --> 00:29:14,400\n我们需要环境\nWe're going to need the environment\n\n590\n00:29:14,448 --> 00:29:15,648\n来进行一些求值\nto do some more evaluations.\n\n591\n00:29:15,800 --> 00:29:16,608\n我们需要UNEV寄存器来指示\nWe're going to need UNEV\n\n592\n00:29:16,624 --> 00:29:19,200\n其余的待求值参数\nto look at what the rest of those arguments were.\n\n593\n00:29:20,340 --> 00:29:21,552\n我们要把CONTINUE寄存器赋值为\nWe're going to assign continue\n\n594\n00:29:21,560 --> 00:29:24,448\nACCUMULATE-ARG这个标号\na place called accumulate-args, or accumulate-arg.\n\n595\n00:29:31,136 --> 00:29:34,016\n现在 我们已经准备好再次调用EVAL-DISPATCH了\nOK, now, we've set up for another call to eval-dispatch,\n\n596\n00:29:37,072 --> 00:29:38,544\n现在让我把这个短路掉\nAll right, now, let me short-circuit this\n\n597\n00:29:39,120 --> 00:29:41,090\n这里我们不跟进EVAL-DISPATCH的细节\nso we don't go through the details of eval-dispatch.\n\n598\n00:29:41,090 --> 00:29:42,640\nEVAL-DISPATCH的约定说：\nEval-dispatch's contract says\n\n599\n00:29:42,970 --> 00:29:45,008\n我的调用完成后\ni'm going to end up,\n\n600\n00:29:45,136 --> 00:29:45,960\n整个机器的状态会变为\nthe world will end up,\n\n601\n00:29:46,032 --> 00:29:48,208\n也就是在ENV环境中求值EXP表达式\nwith the value of evaluating this expression\n\n602\n00:29:48,240 --> 00:29:50,270\n求值结果会保存在VAL寄存器中\nin this environment in the VAL register,\n\n603\n00:29:50,270 --> 00:29:51,072\n结束状态就是这样\nand I'll end up there.\n\n604\n00:29:51,320 --> 00:29:52,624\n那么我们把这些全都省略掉\nSo we short-circuit all of this,\n\n605\n00:29:54,432 --> 00:29:56,368\n最后VAL的内容是3\nand a 3 ends up in VAL.\n\n606\n00:29:58,010 --> 00:29:59,760\n并且当我们从EVAL-DISPATCH返回的时候\nAnd, when we return from eval-dispatch,\n\n607\n00:29:59,760 --> 00:30:01,760\n我们会返回到ACCUMULAT-ARG这里\nwe're going to return to accumulate-arg.\n\n608\n00:30:02,304 --> 00:30:03,232\nSussman教授：跳转到ACCUMULATE-ARG\nPROFESSOR: Accumulate-arg.\n\n609\n00:30:06,224 --> 00:30:08,208\nAbelson教授：VAL寄存器里是3 对吧？\nPROFESSOR: With 3 in the VAL register, OK?\n\n610\n00:30:08,720 --> 00:30:10,592\n我们跳过了求值的细节\nSo that short-circuited that evaluation.\n\n611\n00:30:10,650 --> 00:30:11,320\n现在我们要做什么？\nNow, what do we do?\n\n612\n00:30:11,320 --> 00:30:13,680\n我们返回继续看剩下的参数\nWe're going to go back and look at the rest of the arguments,\n\n613\n00:30:13,680 --> 00:30:14,832\n我们恢复UNEV\nso we restore UNEV.\n\n614\n00:30:17,510 --> 00:30:19,008\n恢复ENV\nWe restore ENV.\n\n615\n00:30:25,792 --> 00:30:27,056\n然后恢复ARGL\nWe restore argl.\n\n616\n00:30:28,650 --> 00:30:29,170\n这件事\nOne thing.\n\n617\n00:30:30,064 --> 00:30:31,456\nSussman教授：糟糕 奇偶错误\nPROFESSOR: Oops! Parity error.\n\n618\n00:30:33,760 --> 00:30:34,832\nAbelson教授：恢复ARGL\nPROFESSOR: Restore argl.\n\n619\n00:30:45,570 --> 00:30:49,760\n然后 我们把VAL寄存器和ARGL给CONS起来\nOK, we assign to argl consing on\n\n620\n00:30:50,656 --> 00:30:52,640\n然后赋值给ARGL寄存器\nfetch of the value register to what's in argl.\n\n621\n00:30:59,360 --> 00:31:02,960\n我们把UNEV中剩余的运算对象\nOK, we assign to UNEV the rest of the operands\n\n622\n00:31:03,344 --> 00:31:04,528\n赋值给UNEV\nin fetch of UNEV,\n\n623\n00:31:08,912 --> 00:31:10,768\n然后我们返回到EVAL-ARG-LOOP\nand we go back to eval-arg-loop.\n\n624\n00:31:11,510 --> 00:31:12,280\nSussman教授：EVAL-ARG-LOOP\nPROFESSOR: Eval-arg-loop.\n\n625\n00:31:12,280 --> 00:31:12,864\nAbelson教授：好\nPROFESSOR: OK.\n\n626\n00:31:15,880 --> 00:31:17,088\n现在我们处理下一个参数\nNow, we're about to do the next argument,\n\n627\n00:31:17,584 --> 00:31:19,312\n所以首先我们要保存ARGL\nso the first thing we do is save argl.\n\n628\n00:31:25,400 --> 00:31:28,272\n然后我们把UNEV中的第一个运算对象\nOK, we assign to EXP the first operand\n\n629\n00:31:29,152 --> 00:31:30,816\n赋给EXP\nof fetch of UNEV.\n\n630\n00:31:34,720 --> 00:31:37,024\n然后我们检查它是否为最后一个运算对象\nOK, we test and see if that's the last operand.\n\n631\n00:31:37,024 --> 00:31:38,000\n这里它是最后一个\nIn this case, it is\n\n632\n00:31:39,088 --> 00:31:40,272\n所以我们跳到一个特殊的地方\nso we're going to go to a special place\n\n633\n00:31:40,288 --> 00:31:42,064\n来求值最后一个参数\nthat says evaluate the last argument\n\n634\n00:31:43,376 --> 00:31:45,072\n因为请注意 在求值这个参数之后\nbecause, notice,after evaluating the argument,\n\n635\n00:31:45,104 --> 00:31:46,624\n我们就不再需要这个环境了\nwe don't need the environment any more.\n\n636\n00:31:47,648 --> 00:31:48,784\n这就是区别\nThat's going to be the difference.\n\n637\n00:31:50,250 --> 00:31:51,856\n在这里 在EVAL-LAST-ARG这里\nSo here, at eval-last-arg,\n\n638\n00:31:52,240 --> 00:31:54,928\nCONTINUE被赋值为了ACCUMULATE-LAST-ARG\nwhich is assigned to continue accumulate-last-arg,\n\n\n639\n00:32:04,270 --> 00:32:06,900\n现在我们再次为EVAL-DISPATCH做准备\nnow, we're set up again for eval-dispatch.\n\n640\n00:32:06,900 --> 00:32:08,512\n我们有一个完成时要跳转的目的地\nWe've got a place to go to when we're done.\n\n641\n00:32:08,620 --> 00:32:09,840\n我们有一条表达式\nWe've got an expression.\n\n642\n00:32:09,840 --> 00:32:10,800\n还有一个环境\nWe've got an environment.\n\n643\n00:32:11,330 --> 00:32:13,648\n好 那么我们略过对EVAL-DISPATCH的调用\nOK, so we'll short-circuit the call to eval-dispatch.\n\n644\n00:32:14,370 --> 00:32:16,416\n现在情况是这里有一个Y\nAnd what'll happen is there's a y there,\n\n645\n00:32:16,700 --> 00:32:18,560\n在这个环境中 它的值是4\nit's 4 in that environment,\n\n646\n00:32:18,608 --> 00:32:20,096\n所以最终VAL寄存器将会是4\nso VAL will end up with 4 in it.\n\n647\n00:32:21,060 --> 00:32:22,864\n然后我们就要以ACCUMULATE-LAST-ARG结束了\nAnd, then, we're going to end up at accumulate-last-arg, OK?\n\n648\n00:32:25,450 --> 00:32:26,912\n因此 在ACCUMULATE-LAST-ARG中\nSo, at accumulate-last-arg,\n\n649\n00:32:29,280 --> 00:32:30,520\n我们恢复ARGL寄存器\nwe restore argl.\n\n650\n00:32:37,696 --> 00:32:42,768\n我们把ARGL赋值为\nWe assign to argl, we assign to argl cons,\n\n651\n00:32:43,600 --> 00:32:45,830\n将一个新值CONS在它上面的结果\nof fetch of the new value onto it,\n\n652\n00:32:45,936 --> 00:32:47,392\n所以我们在它的旧值前CONS一个4\nso we cons a 4 onto that.\n\n653\n00:32:49,850 --> 00:32:52,528\n我们恢复FUN寄存器中的内容\nWe restore what was saved in the function register.\n\n654\n00:32:53,770 --> 00:32:54,992\n需要注意的是 在则个例子中\nAnd notice, in this case,\n\n655\n00:32:55,008 --> 00:32:56,270\nFUN寄存器还没有被修改过\nit had not been destroyed,\n\n656\n00:32:56,384 --> 00:32:57,728\n但是通常来说 它会的\nbut in general, it will be.\n\n657\n00:32:59,130 --> 00:33:01,504\n现在 我们将要调用APPLY-DISPATCH\nAnd now, we're ready to go off to apply-dispatch,\n\n658\n00:33:02,650 --> 00:33:04,400\n所以我们刚刚步步跟进了EVAL过程\nAlright? So we've just gone through the eval.\n\n659\n00:33:04,510 --> 00:33:05,856\n我们求值了运算符\nWe evaluated the argument,\n\n660\n00:33:06,464 --> 00:33:07,980\n以及实际参数\nthe operator, and the arguments,\n\n661\n00:33:07,980 --> 00:33:09,248\n现在我们要应用它们了\nand now, we're about to apply them.\n\n662\n00:33:09,580 --> 00:33:11,376\n因此 我们来到APPLY-DISPATCH这里\nSo we come off to apply-dispatch here\n\n663\n00:33:18,032 --> 00:33:19,296\n这是APPLY-DISPATCH的代码\nWe come off to apply-dispatch,\n\n664\n00:33:21,056 --> 00:33:22,416\n我们要检查它是一个基本过程\nand we're going to check whether it's a primitive\n\n665\n00:33:22,416 --> 00:33:23,450\n还是一个复合过程\nor a compound procedure.\n\n666\n00:33:23,648 --> 00:33:24,208\nSussman教授：基本过程\nPROFESSOR: Yes.\n\n667\n00:33:24,544 --> 00:33:24,830\nAbelson教授：好的\nPROFESSOR: All right.\n\n668\n00:33:24,896 --> 00:33:26,528\n这里 它是一个基本过程\nSo, in this case, it's a primitive procedure,\n\n669\n00:33:27,456 --> 00:33:28,912\n因此 我们跳转到PRIMITIVE-APPLY\nand we go off to primitive-apply.\n\n670\n00:33:29,790 --> 00:33:31,360\n我们来到PRIMITIVE-APPLY\nSo we go off to primitive-apply,\n\n671\n00:33:33,710 --> 00:33:35,376\n它说：把VAL赋值为\nthat says assign to VAL\n\n672\n00:33:35,696 --> 00:33:38,256\n把基本过程\nresult of applying primitive procedure\n\n673\n00:33:38,360 --> 00:33:40,304\n应用在参数表的结果\nof the function to the argument list.\n\n674\n00:33:41,312 --> 00:33:42,432\nSussman教授：我不知道怎么做加法\nPROFESSOR: I don't know how to add.\n\n675\n00:33:42,540 --> 00:33:43,808\n我只是一个执行单元\nI'm just an execution unit.\n\n676\n00:33:44,144 --> 00:33:45,350\nAbelson教授：我也不知道\nPROFESSOR: Well, I don't know how to add either.\n\n677\n00:33:45,350 --> 00:33:46,512\n我只是一个求值器\nI'm just the evaluator,\n\n678\n00:33:47,088 --> 00:33:48,360\n因此 我们需要一个基本运算执行器\nso we need a primitive operator.\n\n679\n00:33:48,360 --> 00:33:49,728\n那么 请问基本运算执行器\nLet's see, so the primitive operator,\n\n680\n00:33:49,760 --> 00:33:52,368\n3+4等于多少？\nWhat's the... what's the sum of 3 and 4?\n\n681\n00:33:52,864 --> 00:33:53,328\n学生：7\nAUDIENCE: 7.\n\n682\n00:33:53,712 --> 00:33:54,656\nAbelson教授：好 是7\nPROFESSOR: OK, 7.\n\n683\n00:33:55,328 --> 00:33:55,990\nSussman教授：谢谢\nPROFESSOR: Thank you.\n\n684\n00:33:59,200 --> 00:34:00,608\nAbelson教授：现在 我们恢复CONTINUE\nPROFESSOR: Now, we restore continue,\n\n685\n00:34:11,584 --> 00:34:12,900\n执行(GOTO (FETCH CONTINUE))\nand we go to fetch of continue.\n\n686\n00:34:13,072 --> 00:34:13,472\nSussman教授：'DONE\nPROFESSOR: Done.\n\n687\n00:34:14,208 --> 00:34:14,672\nAbelson教授：好\nPROFESSOR: OK.\n\n688\n00:34:14,920 --> 00:34:18,410\n这些是你能看到的最细致的过程了\nWell, that was in as much detail as you will ever see.\n\n689\n00:34:18,410 --> 00:34:20,192\n我们再也不会讲得这么细了\nWe'll never do it in as much detail again.\n\n690\n00:34:21,590 --> 00:34:23,920\n有一件重要的事需要注意\nOne very important thing to notice\n\n691\n00:34:24,912 --> 00:34:27,552\n我们刚刚执行了一个递归过程\nis that we just executed a recursive procedure,\n\n692\n00:34:29,568 --> 00:34:31,170\n我们在整个过程中使用了栈\nRight? This whole thing, we used a stack\n\n693\n00:34:31,170 --> 00:34:32,752\n而且求值器是递归的\nand the evaluator was recursive.\n\n694\n00:34:33,070 --> 00:34:35,888\n有很多人以为在求值器中\nA lot of people think the reason that you need a stack\n\n\n695\n00:34:36,480 --> 00:34:37,856\n会用到栈和递归\nand recursion in an evaluator\n\n696\n00:34:37,872 --> 00:34:38,976\n或许是因为\nis because you might be\n\n697\n00:34:39,090 --> 00:34:42,150\n回去求值像阶乘或者FIB那样的递归过程\nevaluating recursive procedures like factorial or Fibonacci.\n\n698\n00:34:42,150 --> 00:34:42,928\n这并不正确\nIt's not true.\n\n699\n00:34:43,670 --> 00:34:44,992\n注意 我们在这里进行了递归\nSo you notice we did recursion here,\n\n700\n00:34:45,008 --> 00:34:46,864\n而仅仅是去求值(+ X Y)\nand all we evaluated was (+ x y)\n\n701\n00:34:47,776 --> 00:34:50,656\n在求值器中需要递归 实际上是因为\nRight? The reason that you need recursion in the evaluator\n\n702\n00:34:50,960 --> 00:34:52,976\n是因为求值过程本身\nis because the evaluation process,\n\n703\n00:34:52,992 --> 00:34:54,060\n就是递归的\nitself, is recursive.\n\n704\n00:34:54,450 --> 00:34:56,176\n并不是因为你在Lisp中\nRight? It's not because the procedure\n\n705\n00:34:56,320 --> 00:34:58,096\n要求值的那个过程\nthat you might be evaluating in LISP\n\n706\n00:34:58,128 --> 00:34:59,270\n是一个递归过程\nis a recursive procedure.\n\n707\n00:34:59,270 --> 00:35:00,528\n这一点很重要\nSo that's an important thing\n\n708\n00:35:00,528 --> 00:35:02,144\n人们经常在这里被弄糊涂\nthat people get confused about a lot.\n\n709\n00:35:03,010 --> 00:35:04,272\n另一点要注意的是\nThe other thing to notice is that,\n\n710\n00:35:04,272 --> 00:35:05,648\n我们在这里完成之后\nwhen we're done here,\n\n711\n00:35:06,280 --> 00:35:07,120\n真正完成以后\nwe're really done.\n\n712\n00:35:07,120 --> 00:35:08,496\n不仅仅是指我们在'DONE这个标号\nNot only are we at done,\n\n713\n00:35:09,456 --> 00:35:13,232\n栈上也没有累积的东西了\nbut there's no accumulated stuff on the stack,\n\n714\n00:35:13,600 --> 00:35:15,712\n对吧？机器又回到了它的初始状态\nRight? The machine is back to its initial state.\n\n715\n00:35:17,008 --> 00:35:18,752\n那就是“完成”的其中一部分意义\nSo that's part of what it means to be done.\n\n716\n00:35:19,710 --> 00:35:21,040\n换句话说就是\nAnother way to say that is\n\n717\n00:35:22,720 --> 00:35:26,048\n整个求值过程是把\nthe evaluation process has reduced\n\n718\n00:35:26,410 --> 00:35:28,320\n(+ X Y)这条表达式\nthe expression, plus X, Y,\n\n719\n00:35:30,544 --> 00:35:32,784\n归约为这里的7\nto the value here, 7.\n\n720\n00:35:33,240 --> 00:35:35,456\n我所指的“归约”有特殊的意义\nAnd by reduced, I mean a very particular thing.\n\n721\n00:35:36,010 --> 00:35:38,180\n也就是栈上没剩下任何东西了\nIt means that there's nothing left on the stack.\n\n722\n00:35:38,180 --> 00:35:40,368\n机器现在与初始状态相同\nThe machine is now in the same state,\n\n723\n00:35:40,928 --> 00:35:42,656\n只是VAL寄存器里有一些东西\nexcept there's something in the value register.\n\n724\n00:35:42,720 --> 00:35:44,520\n它不是任何问题的子问题\nIt's not part of a sub-problem of anything.\n\n725\n00:35:44,520 --> 00:35:45,632\n不需要返回到其它地方\nThere's nothing to go back to.\n\n726\n00:35:46,128 --> 00:35:46,960\n好 这节课就讲到这里\nOK. Let's break.\n\n727\n00:35:50,160 --> 00:35:50,768\n有问题吗\nQuestion?\n\n728\n00:35:51,088 --> 00:35:54,020\n学生：关于栈有一个问题\nAUDIENCE: The question here, in the stack,\n\n729\n00:35:54,020 --> 00:35:55,820\n由于数据有可能是递归的\nis because the data may be recursive.\n\n730\n00:35:56,208 --> 00:35:58,752\n例如 嵌套的表达式\nYou may have embedded expressions, for instance.\n\n731\n00:35:59,310 --> 00:36:02,080\n教授：是的 因为你可能遇到嵌套的表达式\nPROFESSOR: Yes, because you might have embedded expressions.\n\n732\n00:36:02,080 --> 00:36:04,770\n但是再说一遍 不要搞混\nBut, again, don't confuse that\n\n733\n00:36:04,770 --> 00:36:07,984\n有时候人们说数据是递归的\nwith what people sometimes mean by the data may be recursive,\n\n734\n00:36:08,000 --> 00:36:10,352\n他们说的是对于这些表结构的\nwhich is to say you have these list-structured,\n\n735\n00:36:11,040 --> 00:36:12,930\n一些递归运算\nrecursive data list operations.\n\n736\n00:36:12,930 --> 00:36:13,968\n那和这没有关系\nThat has nothing to do with it.\n\n737\n00:36:13,984 --> 00:36:16,160\n这只是包含子表达式的表达式而已\nIt's simply that the expressions contain sub-expressions.\n\n738\n00:36:20,048 --> 00:36:23,520\n学生：为什么ARGL中参数的顺序是反过来的\nAUDIENCE: Why is it that the order of the arguments in the arg list got reversed?\n\n739\n00:36:23,552 --> 00:36:25,296\n教授：对 我应该提一嘴这个\nPROFESSOR: Ah! Yes, I should've mentioned that.\n\n740\n00:36:27,260 --> 00:36:29,070\n之所以在这里把顺序反过来\nHere, the reason the order is reversed--\n\n741\n00:36:32,784 --> 00:36:35,376\n你首先定义怎么算“逆序”\nit's a question of what you mean by reversed.\n\n742\n00:36:36,050 --> 00:36:39,904\n我记得应该是牛顿\nI believe it was Newton.\n\n743\n00:36:40,910 --> 00:36:42,416\n在光学发展的很早期\nIn the very early part of optics,\n\n744\n00:36:42,432 --> 00:36:43,260\n人们意识到\npeople realized\n\n745\n00:36:43,616 --> 00:36:45,360\n当你用眼睛通过透镜看东西的时候\nthat when you look through the lens of your eye,\n\n746\n00:36:45,500 --> 00:36:46,730\n图像是上下颠倒的\nthe image was up-side down.\n\n747\n00:36:46,730 --> 00:36:48,040\n当时有很多的争论说\nAnd there was a lot of argument about\n\n748\n00:36:48,040 --> 00:36:50,480\n为什么不能是你眼睛平时看见的都是上下颠倒的\nwhy that didn't mean you saw things up-side down.\n\n749\n00:36:51,280 --> 00:36:52,656\n这实际上是一样的道理\nSo it's sort of the same issue.\n\n750\n00:36:52,860 --> 00:36:53,904\n和什么相比反过来了\nReversed from what?\n\n751\n00:36:54,810 --> 00:36:56,240\n我们只是需要一个约定\nSo we just need some convention.\n\n752\n00:36:56,590 --> 00:37:00,352\n它们作为(4 3)出现的原因是\nSo all we.. The reason that they're coming at 4, 3\n\n753\n00:37:00,800 --> 00:37:02,496\n是因为我们从UNEV中取出东西\nis because taking UNEV\n\n754\n00:37:02,528 --> 00:37:04,030\n并且把它CONS到了ARGL上面\nand consing the result onto argl.\n\n755\n00:37:04,520 --> 00:37:06,688\n那么你要意识到你已经做了这个约定\nSo you have to realize you've made that convention.\n\n756\n00:37:06,864 --> 00:37:09,376\n你需要意识到这点的地方有\nThe place that you have to realize that--\n\n757\n00:37:09,980 --> 00:37:11,230\n实际上有两个地方\nwell, there's actually two places.\n\n758\n00:37:11,230 --> 00:37:12,910\n首先是在APPLY-PRIMITIVE-OPERATOR\nOne is in apply-primitive-operator,\n\n\n759\n00:37:12,910 --> 00:37:14,064\n你要意识到\nwhich has to realize that\n\n760\n00:37:15,120 --> 00:37:16,752\n参数传入基本运算的顺序\nthe arguments to primitives go in,\n\n761\n00:37:16,784 --> 00:37:18,720\n是和你的书写顺序相反的\nthe opposite order from the way you're writing them down.\n\n762\n00:37:19,490 --> 00:37:21,000\n我们之后会在另外一处看到\nAnd the other one is, we'll see later\n\n\n763\n00:37:21,072 --> 00:37:23,808\n当你实际绑定绑定函数的形式参数时\nwhen you actually go to bind a function's parameters,\n\n764\n00:37:24,010 --> 00:37:25,740\n你要意识到参数进入的顺序\nyou should realize the arguments are going to come in\n\n765\n00:37:25,740 --> 00:37:28,544\n和你要绑定这些变量时的顺序相反\nfrom the opposite order of the variables to which you're binding them.\n\n766\n00:37:28,870 --> 00:37:30,176\n所以如果你注意这些\nSo, if you just keep track of that,\n\n767\n00:37:31,088 --> 00:37:31,830\n就没有问题了\nthere's no problem.\n\n768\n00:37:31,830 --> 00:37:33,696\n同样 这完全是随意的\nAlso, this is completely arbitrary\n\n769\n00:37:33,900 --> 00:37:34,960\n因为如果我们做了一个\nbecause, if we'd done,\n\n770\n00:37:35,104 --> 00:37:37,152\n比如 给向量的各个维度赋值的迭代\nsay, an iteration through a vector assigning them,\n\n771\n00:37:37,420 --> 00:37:38,736\n它们可能会以其它顺序输出\nthey might come out in the other order.\n\n772\n00:37:40,410 --> 00:37:42,048\n那么这只是这个求值器\nOK. So it's just a convention of the way\n\n773\n00:37:42,064 --> 00:37:43,536\n工作时的一个约定\nthis particular evaluator works.\n\n774\n00:37:45,392 --> 00:37:46,240\n好 我们休息一下\nAll right, let's take a break.\n\n775\n00:37:46,330 --> 00:38:02,448\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n776\n00:38:02,440 --> 00:38:07,648\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n777\n00:38:28,620 --> 00:38:32,512\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Sussman Jay Sussman\n\n778\n00:38:32,510 --> 00:38:35,680\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n779\n00:38:35,680 --> 00:38:39,616\n显式控制求值器\nExplicit-control Evaluator\n\n780\n00:38:41,840 --> 00:38:45,310\n教授：我们已经学习了表达式的求值\nProfessor: We just saw evaluating an expression\n\n781\n00:38:45,600 --> 00:38:47,080\n虽然这只是一个非常简单的例子\nand, of course, that was very simple one. But\n\n782\n00:38:48,810 --> 00:38:50,240\n但从本质上来说\nin essence, it would be no different\n\n783\n00:38:50,240 --> 00:38:52,030\n它跟那些大型嵌套表达式没什么不同\nif it was some big nested expression,\n\n784\n00:38:52,030 --> 00:38:54,570\n后者只是在栈上递归得更深而已\nso there would just be deeper recursion on the stack.\n\n785\n00:38:55,130 --> 00:38:56,032\n我现在要为你们\nBut what I want to do now\n\n786\n00:38:56,048 --> 00:38:56,910\n讲解最后一部分\nis show you the last piece.\n\n787\n00:38:56,920 --> 00:38:59,820\n我要带着你们观察EVAL-APPLY循环\nI want to walk you around this eval and apply loop,\n\n788\n00:39:01,010 --> 00:39:02,810\n我们还没有仔细研究过它\nThat's the thing we haven't seen, really.\n\n789\n00:39:03,000 --> 00:39:04,750\n我们还没有见过一个复合程序\nWe haven't seen any compound procedures\n\n790\n00:39:05,200 --> 00:39:07,790\n对它的求值会归约为\nwhere evalutation of procedure reduces to\n\n791\n00:39:07,920 --> 00:39:10,110\n对一个过程的应用\nwhere applying of procedure reduces to\n\n792\n00:39:10,120 --> 00:39:11,640\n进而是对过程体的求值\nevaluating the body of the procedure,\n\n793\n00:39:12,440 --> 00:39:15,880\n因此 假设我们有这个\nso let's just suppose we had this.\n\n794\n00:39:15,930 --> 00:39:17,440\n假设我们正在考察\nSuppose we were looking at the procedure\n\n795\n00:39:18,070 --> 00:39:31,600\n(DEFINE (F A B) (+ A B)\ndefine F of A and B to be the sum of A and B.\n\n796\n00:39:33,990 --> 00:39:37,320\n假设我们预先定义好了这个过程\nSo, as we typed in that procedure previously,\n\n797\n00:39:37,690 --> 00:39:41,640\n现在 我们将要求值(F X Y)\nand now we're going to evaluate F of X and Y\n\n798\n00:39:42,270 --> 00:39:44,200\n基于的环境是E0\nagain, in this environment, E,0,\n\n799\n00:39:44,350 --> 00:39:47,020\n其中X=3 Y=4\nwhere X is bound to 3 and Y is bound to 4.\n\n800\n00:39:50,780 --> 00:39:52,110\n当执行DEFINE的时候\nWhen the defined is executed,\n\n801\n00:39:52,120 --> 00:39:53,690\n还记得么 这里是一个LAMBDA\nremember, there's a lambda here,\n\n802\n00:39:53,820 --> 00:39:55,530\nLAMBDA会创建一个过程\nand lambdas create procedures.\n\n803\n00:39:55,950 --> 00:39:58,490\n基本上 会发生的事情是\nAnd, basically, what will happen is,\n\n804\n00:39:59,632 --> 00:40:00,688\n在环境E0中\nin E0,\n\n805\n00:40:01,008 --> 00:40:02,650\n我们会得到F的绑定\nwe'll end up with a binding for F,\n\n806\n00:40:03,560 --> 00:40:05,610\n它指出F是一个过程\nwhich will say F is a procedure,\n\n807\n00:40:07,150 --> 00:40:11,280\n这个过程的参数是A和B\nand its args are A and B,\n\n808\n00:40:12,570 --> 00:40:16,190\n而过程体是(+ A B)\nand its body is plus a,b.\n\n809\n00:40:18,110 --> 00:40:20,990\n这就是环境大概的样子\nSo that's what the environment would have looked like\n\n810\n00:40:21,210 --> 00:40:22,520\n我们之前就定义过了\nhad we made that definition.\n\n811\n00:40:24,220 --> 00:40:27,280\n然后 我们去求值(F X Y)\nThen, when we go to evaluate F of X and Y,\n\n812\n00:40:28,800 --> 00:40:30,896\n我们会仔细地解释每一步\nwe'll go through exactly the same process\n\n813\n00:40:31,024 --> 00:40:31,850\n就像之前那样\nthat we did before.\n\n814\n00:40:31,880 --> 00:40:33,090\n不会跳过重复的表达式\nIt's even the same expression.\n\n815\n00:40:33,280 --> 00:40:34,380\n唯一的不同是\nThe only difference is that\n\n816\n00:40:34,400 --> 00:40:36,640\n它的内部不再是基本的“+”过程\nF, instead of having primitive \"plus\" in it\n\n817\n00:40:37,240 --> 00:40:38,990\n它还有这个东西\nwill have this thing.\n\n818\n00:40:41,040 --> 00:40:43,600\n因此我们要进行相同的过程\nAnd so we'll go through exactly the same process,\n\n819\n00:40:43,600 --> 00:40:44,928\n只不过这次\nexcept this time, when we end up\n\n820\n00:40:45,264 --> 00:40:47,420\n当我们停在APPLY-DISPATCH时\nat apply-dispatch,\n\n821\n00:40:47,860 --> 00:40:50,280\nFUN寄存器中不再是基本的“+”过程\nthe function register, instead of having primitive plus,\n\n822\n00:40:50,440 --> 00:40:53,580\n而是一个代表过程的东西\nwill have a thing that will represent it saying procedure,\n\n823\n00:40:54,300 --> 00:40:59,000\n其中参数为A和B\nwhere the args are A and B,\n\n824\n00:41:00,640 --> 00:41:06,270\n过程体是(+ A B)\nand the body is plus A, B.\n\n825\n00:41:07,870 --> 00:41:09,920\n再强调一下 我所谓的ENV\nAnd, again, what I mean, by its ENV,\n\n826\n00:41:09,960 --> 00:41:11,120\n是一个指向环境的指针\nI mean there's a pointer to it,\n\n827\n00:41:11,240 --> 00:41:13,070\n所以不用担心我在这里写了很多东西\nso don't worry that I'm writing a lot of stuff there.\n\n828\n00:41:13,280 --> 00:41:15,630\n这是一个指向代表过程的数据结构的指针\nThere's a pointer to this procedure data structure.\n\n829\n00:41:17,170 --> 00:41:19,770\n因此 我们现在面临着相同的情况\nOK, so, we're in exactly the same situation.\n\n830\n00:41:20,270 --> 00:41:22,430\n我们来到了APPLY-DISPATCH\nWe get to apply-dispatch,\n\n831\n00:41:23,980 --> 00:41:26,480\n这是APPLY-DISPATCH的代码\nso, here, we come to apply-dispatch.\n\n832\n00:41:26,480 --> 00:41:28,730\n上一次 我们分支跳转到了一个基本过程\nLast time, we branched off to a primitive procedure.\n\n833\n00:41:30,010 --> 00:41:30,700\n然而这一次\nHere, it says oh,\n\n834\n00:41:30,840 --> 00:41:32,800\n我们遇到的是一个复合过程\nwe now have a compound procedure,\n\n835\n00:41:34,550 --> 00:41:36,600\n因此我们要跳转到COMPOUND-APPLY\nso we're going to go off to compound-apply.\n\n836\n00:41:38,470 --> 00:41:39,920\nCOMPOUND-APPLY又是怎样定义的呢？\nNow, what's compound-apply?\n\n837\n00:41:41,920 --> 00:41:44,540\n还记得元循环求值器是怎么做的么？\nWell, remember what the meta-circular evaluator did?\n\n838\n00:41:45,090 --> 00:41:47,400\nCOMPOUND-APPLY的执行步骤则是\nCompound-apply said we're going to evaluate\n\n839\n00:41:49,900 --> 00:41:51,600\n在一个新的环境中\nthe body of the procedure\n\n840\n00:41:52,940 --> 00:41:54,120\n求值一个过程的体\nin some new environment.\n\n841\n00:41:54,120 --> 00:41:55,870\n这个新的环境来自于哪里呢？\nWhere does that new environment come from?\n\n842\n00:41:56,730 --> 00:42:01,360\n我们把跟过程一同打包的环境\nWe take the environment that was packaged with the procedure,\n\n843\n00:42:03,020 --> 00:42:05,790\n我们把过程的形式参数\nwe bind the parameters of the procedure\n\n844\n00:42:06,000 --> 00:42:07,630\n同传递进来的实际参数给绑定起来\nto the arguments that we're passing in,\n\n845\n00:42:09,750 --> 00:42:11,950\n把这个作为新的框架\nand use that as a new frame to extend\n\n846\n00:42:12,590 --> 00:42:13,790\n来扩展过程附带的环境\nthe procedure environment.\n\n847\n00:42:14,990 --> 00:42:16,080\n我们就是在这个环境中\nAnd that's the environment\n\n848\n00:42:16,300 --> 00:42:18,880\n求值过程的体\nin which we evaluate the procedure body,\n\n849\n00:42:20,120 --> 00:42:24,470\n对吧？这就是APPLY-EVAL循环做的事\nRight? That's going around the apply/eval loop.\n\n850\n00:42:24,470 --> 00:42:26,250\n这就是APPLY回过头来调用EVAL\nThat's apply coming back to call eval,\n\n851\n00:42:32,860 --> 00:42:34,920\n因此 这就是我们要在COMPOUND-APPLY中要做的所有事\nSo, now, that's all we have to do in compound-apply.\n\n852\n00:42:36,780 --> 00:42:37,720\n要怎么来实现呢？\nWhat are we going to do?\n\n853\n00:42:37,720 --> 00:42:40,970\n我们要构造一个新的环境\nWe're going to manufacture a new environment.\n\n854\n00:42:43,550 --> 00:42:45,640\n而我们构造的这个新环境呢\nAnd we're going to manufacture a new environment that,\n\n855\n00:42:46,760 --> 00:42:48,110\n我们把它记作E1\nlet's see, that we'll call E1.\n\n856\n00:42:52,900 --> 00:42:55,630\nE1这个环境呢\nE1 is going to be some environment where the\n\n857\n00:42:57,310 --> 00:42:59,150\n存储了过程的参数绑定\nwhere the parameters of the procedure,\n\n858\n00:42:59,210 --> 00:43:03,260\n其中A=3 B=4\nNwhere A is bound to 3, and B is bound to 4,\n\n859\n00:43:04,270 --> 00:43:05,760\n并且它跟E0相连\nand it's linked to E0\n\n860\n00:43:05,760 --> 00:43:08,080\n这是因为 F就是在E0中定义的\nbecause that's where f is defined.\n\n861\n00:43:09,270 --> 00:43:10,270\n因此 在这个环境中\nAnd, in this environment,\n\n862\n00:43:10,270 --> 00:43:11,960\n我们要来求值过程的体\nwe're going to evaluate the body of the procedure.\n\n863\n00:43:12,050 --> 00:43:14,480\n让我们来看一看\nSo let's look at that, we're going\n\n864\n00:43:16,520 --> 00:43:18,320\n我们来看COMPOUND-APPLY的代码\nHere we are at compound-apply,\n\n865\n00:43:20,300 --> 00:43:23,470\n首先是给EXP寄存器赋值\nwhich says assign to the expression register\n\n866\n00:43:24,500 --> 00:43:25,984\n所赋的值是FUN寄存器\nthe body of the procedure\n\n867\n00:43:25,984 --> 00:43:27,260\n所指向过程的体\nthat's in the function register.\n\n868\n00:43:28,380 --> 00:43:30,640\n这样 我就将过程的体\nSo I assign to the expression register\n\n869\n00:43:31,296 --> 00:43:32,330\n赋值给了EXP寄存器\nthe procedure body,\n\n870\n00:43:40,750 --> 00:43:41,100\n对吧？\nOK?\n\n871\n00:43:42,640 --> 00:43:44,970\n而这将在某个环境中求值\nThat's going to be evaluated in an environment\n\n872\n00:43:45,820 --> 00:43:48,320\n这个环境是通过将FUN寄存器\nwhich is formed by making some bindings\n\n873\n00:43:51,300 --> 00:43:53,670\n所指向的过程中的形式参数\nusing information determined by the procedure--\n\n874\n00:43:53,670 --> 00:43:56,250\n与实际参数绑定起来 得到的\nthat's what's in FUN-- and the argument list.\n\n875\n00:43:57,800 --> 00:44:00,000\n我们先不要关系它的具体细节\nAnd let's not worry about exactly what that does,\n\n876\n00:44:00,080 --> 00:44:01,630\n你可以知道它的最后结果\nbut you can see the information's there.\n\n877\n00:44:01,930 --> 00:44:03,320\n因此MAKE-BINDINGS会说\nSo make bindings will say oh,\n\n878\n00:44:04,040 --> 00:44:07,900\n过程本身就附带有一个环境\nthe procedure, itself, had an environment attached to it.\n\n879\n00:44:07,960 --> 00:44:09,320\n在这里 我没有写出来\nI didn't write that quite here.\n\n880\n00:44:09,360 --> 00:44:10,560\n但我应该说过它有一个环境\nI should've said in environment\n\n881\n00:44:11,300 --> 00:44:12,736\n因为每个过程在构造时\nbecause every procedure gets built\n\n882\n00:44:12,768 --> 00:44:13,440\n都有一个环境\nwith an environment.\n\n883\n00:44:13,660 --> 00:44:14,832\n因此 通过这个环境\nSo, from that environment,\n\n884\n00:44:15,680 --> 00:44:16,350\n它能够知道\nit knows\n\n885\n00:44:16,600 --> 00:44:18,650\n定义该过程时的环境是怎样的\nwhat the procedure's definition environment is.\n\n886\n00:44:19,290 --> 00:44:20,750\n它知道实际参数是什么\nIt knows what the arguments are.\n\n887\n00:44:21,830 --> 00:44:22,490\n它查看ARGL\nIt looks at argl,\n\n888\n00:44:22,490 --> 00:44:24,280\n然后你会在这里看到逆序的约定\nand then you see a reversal convention here.\n\n889\n00:44:24,280 --> 00:44:26,620\n它需要知道ARGL是逆序的\nIt just has to know that argl is reversed,\n\n890\n00:44:27,060 --> 00:44:28,810\n然后它构造了这个框架 E1\nand it builds this frame, E,1.\n\n891\n00:44:29,990 --> 00:44:31,088\n因此我们假设\nAll right, so, let's assume that\n\n892\n00:44:31,104 --> 00:44:32,920\nMAKE-BINDINGS返回的就是这些东西\nthat's what make bindings returns,\n\n893\n00:44:33,360 --> 00:44:36,220\n然后 它把E1赋值给ENV\nso it assigns to ENV this thing, E,1.\n\n894\n00:44:41,340 --> 00:44:42,544\n下一步就是\nThe next thing it says\n\n895\n00:44:43,952 --> 00:44:45,840\n恢复CONTINUE\nis restore continue.\n\n896\n00:44:46,890 --> 00:44:48,190\n还记得CONTINUE之前是什么吗？\nRemember what continue was here?\n\n897\n00:44:48,760 --> 00:44:50,430\n在最后一段中\nIt got put up in the last segment.\n\n898\n00:44:52,240 --> 00:44:54,020\nCONTINUE被保存了\nContinue got stored.\n\n899\n00:44:54,020 --> 00:44:55,180\n它的值是最初的'DONE\nThat was the original done,\n\n900\n00:44:55,320 --> 00:44:56,560\n这代表了\nwhich said what are you going to do\n\n901\n00:44:56,730 --> 00:44:59,440\n在完成这项特定应用后要做的事\nafter you're done with this particular application?\n\n902\n00:45:00,140 --> 00:45:01,720\n这是在求值整个应用时\nIt was one of the very first things that happened\n\n903\n00:45:01,760 --> 00:45:03,180\n最先发生的事儿\nwhen we evaluated the application.\n\n904\n00:45:03,880 --> 00:45:05,870\n现在 我们要恢复CONTINUE了\nAnd now, finally, we're going to restore continue.\n\n905\n00:45:06,860 --> 00:45:09,550\n还记得APPLY-DISPATCH的约定么？\nRemember apply-dispatch's contract.\n\n906\n00:45:09,580 --> 00:45:11,200\n它假设下一步的跳转目标\nIt assumes that where it should go to next\n\n907\n00:45:11,230 --> 00:45:11,980\n已经存放在栈上了\nwas on the stack,\n\n908\n00:45:12,030 --> 00:45:13,120\n并且 这里确实存放在栈上了\nand there it was on the stack.\n\n909\n00:45:13,590 --> 00:45:14,760\nCONTINUE被赋值成了DONE\nContinue has done,\n\n910\n00:45:17,820 --> 00:45:19,900\n现在我们要回到EVAL-DISPATCH了\nand now we're going to go back to eval-dispatch.\n\n911\n00:45:19,940 --> 00:45:20,840\n我们要再次进行寄存器设置\nWe're set up again.\n\n912\n00:45:20,970 --> 00:45:24,410\n我们有表达式、环境、下一步\nWe have an expression, an environment, and a place to go to.\n\n913\n00:45:25,800 --> 00:45:26,890\n我不会再细讲了\nWe're not going to go through that\n\n914\n00:45:27,880 --> 00:45:29,550\n因为它基本上就是相同的表达式\nbecause it's sort of the same expression.\n\n915\n00:45:35,400 --> 00:45:37,792\n但是需要注意的是\nOK, but the thing, again, to notice\n\n916\n00:45:37,824 --> 00:45:38,736\n在这个时候\nis, at this point,\n\n917\n00:45:39,340 --> 00:45:43,720\n我们已经归约了原始表达式(F X Y)\nwe have reduced the original expression, F,X,Y,\n\n918\n00:45:44,640 --> 00:45:47,920\n通过在E0中求值(F X Y)\nWe've reduced evaluating F,X,Y in environment E,0\n\n919\n00:45:48,890 --> 00:45:52,670\n将其归约为在E1中求值(+ A B)\nto evaluate plus A, B in E,1.\n\n920\n00:45:52,780 --> 00:45:55,920\n要注意 栈上并没有什么东西 对吧？\nAnd notice, nothing's on the stack, right?\n\n921\n00:45:56,110 --> 00:45:56,830\n这是一个归约\nIt's a reduction.\n\n922\n00:45:56,840 --> 00:45:59,800\n这个时候 机器的状态中\nAt this point, the machine does not contain,\n\n923\n00:45:59,840 --> 00:46:01,200\n并没有包含\nas part of its state,\n\n924\n00:46:01,760 --> 00:46:03,712\n它是求值过程F的\nthe fact that it's in the middle of evaluating\n\n925\n00:46:03,728 --> 00:46:04,880\n中间状态的事实\nsome procedure called f,\n\n926\n00:46:05,490 --> 00:46:06,280\n它消失了\nthat's gone,\n\n927\n00:46:07,660 --> 00:46:09,550\n这里面没有积累的状态\nRight? There's no accumulated state?\n\n928\n00:46:13,070 --> 00:46:14,370\n注意 这个思想非常重要\nAgain, that's a very important idea.\n\n929\n00:46:14,370 --> 00:46:16,330\n这意味着\nThat's the meaning of,\n\n930\n00:46:16,760 --> 00:46:18,390\n当我们使用代换模型时\nwhen we used to write in the substitution model,\n\n931\n00:46:18,390 --> 00:46:20,860\n一条表达式会归约到另一条表达式\nthis expression reduces to that expression.\n\n932\n00:46:21,350 --> 00:46:22,660\n而你不需要记住任何东西\nAnd you don't have to remember anything.\n\n933\n00:46:22,660 --> 00:46:24,500\n这里 你就见到了归约的真谛\nAnd here, you see the meaning of reduction.\n\n934\n00:46:24,560 --> 00:46:26,160\n这个时候 栈上没有任何东西\nAt this point, there is nothing on the stack.\n\n935\n00:46:31,590 --> 00:46:33,630\n这样就有一个非常重要的结果\nSee, that has very important consequences.\n\n936\n00:46:35,240 --> 00:46:37,900\n让我们回过头来看看迭代式阶乘\nLet's go back and look at iterative factorial,\n\n937\n00:46:40,420 --> 00:46:42,768\n还记得吗？这是某种循环\nall right? Remember, this was some sort of loop\n\n938\n00:46:44,016 --> 00:46:44,880\n用来进行迭代\nand doing iter.\n\n939\n00:46:45,130 --> 00:46:47,360\n我们不断强调 它是一个迭代过程\nAnd we kept saying that's an iterative procedure,\n\n940\n00:46:49,260 --> 00:46:53,840\n还记得吗\nAnd what we wrote, remember,\n\n941\n00:46:58,440 --> 00:47:03,130\n我们使用它的时候\nare things like, we said,\n\n942\n00:47:04,350 --> 00:47:11,070\n是像(FACT-ITER 5)这样调用它的\nfact-iter of 5.\n\n943\n00:47:12,360 --> 00:47:18,670\n然后我们把它归约成(ITER 1 1 5)\nWe wrote things like reduces to iter of 1, and 1, and 5,\n\n944\n00:47:19,030 --> 00:47:25,150\n然后它归约成(ITER 1 2 5)\nwhich reduces to iter of 1, and 2, and 5,\n\n945\n00:47:25,320 --> 00:47:27,070\n等等等等\nand so on, and so on, and so on.\n\n946\n00:47:27,070 --> 00:47:28,170\n然后我们又说 看\nAnd we kept saying well, look,\n\n947\n00:47:28,170 --> 00:47:30,350\n为了实现这个效果 不需要存储任何东西\nyou don't have to build up any storage to do that.\n\n948\n00:47:31,720 --> 00:47:32,730\n我们摆了摆手 说\nAnd we waved our hands,\n\n949\n00:47:32,750 --> 00:47:34,590\n“原则上 这不需要任何存储”\nand said in principle, there's no storage needed.\n\n950\n00:47:35,040 --> 00:47:36,170\n现在你们发现 确实不需要\nNow, you see no storage needed.\n\n951\n00:47:36,170 --> 00:47:39,090\n这里的每一步都是真正的归约 对吧？\nEach of these is a real reduction, right?\n\n952\n00:47:39,090 --> 00:47:42,600\n随着你求值这些表达式\nAs you walk through these expressions,\n\n953\n00:47:47,300 --> 00:47:50,512\n在求值这些表达式的过程中\nAs you walk through these expressions,\n\n954\n00:47:50,832 --> 00:47:51,370\n你会发现\nwhat you'll see\n\n955\n00:47:51,370 --> 00:47:52,810\n栈上的这些表达式\nare these expressions on the stack\n\n956\n00:47:53,750 --> 00:47:55,640\n都在一个特定的环境中\nin some particular environment,\n\n957\n00:47:56,420 --> 00:48:00,020\n抱歉 是EXP寄存器中的表达式\nand then these expressions, sorry, in the EXP register\n\n958\n00:48:00,020 --> 00:48:01,500\n是在某个特定的环境中\nin some particular environment.\n\n959\n00:48:01,570 --> 00:48:02,190\n并且 在每一步\nAnd, at each point,\n\n960\n00:48:02,190 --> 00:48:04,000\n栈上不会积累任何东西\nthere'll be no accumulated stuff on the stack\n\n961\n00:48:04,360 --> 00:48:05,680\n因为每一步都是真正的归约\nbecause each one's a real reduction.\n\n962\n00:48:09,280 --> 00:48:10,510\n因此 举例来说\nAll right, so, for example,\n\n963\n00:48:10,580 --> 00:48:12,510\n说得更仔细一点\njust to go through it in a little bit more care,\n\n964\n00:48:13,460 --> 00:48:16,880\n如果我从这样的一条表达式开始\nif I start out with an expression that says something like,\n\n965\n00:48:22,440 --> 00:48:34,250\n比如说 在某个环境中计算(FACT-ITER 5)\noh, say, fact-iter of 5 in some environment\n\n966\n00:48:42,110 --> 00:48:46,300\n它将在某个时刻创建一个环境\nthat will, at some point, create an environment\n\n967\n00:48:46,810 --> 00:48:48,380\n其中N=5\nin which n is down to 5.\n\n968\n00:48:51,470 --> 00:48:52,010\n我们把它写下来\nLet's call that--\n\n969\n00:48:55,680 --> 00:48:56,590\n然后 在某个时候\nAnd, at some point,\n\n970\n00:48:56,890 --> 00:49:02,560\n机器会归约这整个东西\nthe machine will reduce this whole thing\n\n971\n00:49:02,910 --> 00:49:04,350\n将它归约为\nto a thing that says that's really\n\n972\n00:49:04,760 --> 00:49:09,850\n(ITER 1 1 N)\niter of 1, and 1, and n,\n\n973\n00:49:10,680 --> 00:49:13,720\n然后在环境E1中求值这条表达式\nevaluated in this environment, E,1\n\n974\n00:49:15,870 --> 00:49:17,160\n而不在栈上存放任何东西\nwith nothing on the stack.\n\n975\n00:49:17,160 --> 00:49:19,550\n看到了么 这时机器并不会记住\nSee, at this moment, the machine is not remembering\n\n976\n00:49:20,710 --> 00:49:22,500\n求值这条ITER表达式--\nthat evaluating this expression, iter--\n\n977\n00:49:25,000 --> 00:49:25,630\n也就是某种循环--\nwhich is the loop--\n\n978\n00:49:25,790 --> 00:49:28,570\n并不是FACT-ITER的一部分\nis part of this thing called iterative factorial.\n\n979\n00:49:29,680 --> 00:49:30,590\n它不会记住这个事实\nIt's not remembering that.\n\n980\n00:49:30,590 --> 00:49:33,170\n它只是归约了该表达式\nIt's just reducing the expression to that, right?\n\n981\n00:49:33,170 --> 00:49:36,560\n如果我们再来看迭代式阶乘的体\nIf we look again at the body of iterative factorial,\n\n982\n00:49:38,050 --> 00:49:41,080\n这条表达式归约为了这条表达式\nthis expression has reduced to that expression.\n\n983\n00:49:42,810 --> 00:49:43,870\n哦 这里漏了一个N\nOh, I shouldn't have the n there.\n\n984\n00:49:46,590 --> 00:49:47,744\n幻灯片中的约定\nIt's a slightly different convention\n\n985\n00:49:47,744 --> 00:49:49,130\n和实际程序中稍有不同\nfrom the slide to the program.\n\n986\n00:49:53,340 --> 00:49:56,250\n那么 ITER的体又是什么？\nAnd, then, what's the body of iter?\n\n987\n00:49:56,280 --> 00:49:57,400\nITER的体首先是一个IF--\nWell, iter's going to be an if,\n\n988\n00:49:58,750 --> 00:50:00,190\n我不会再深入IF语句的细节了\nand I won't go through the details of if.\n\n989\n00:50:00,240 --> 00:50:01,630\n它会对谓词求值\nIt'll evaluate the predicate.\n\n990\n00:50:02,400 --> 00:50:03,710\n本例中 会返回FALSE\nIn this case, it'll be false.\n\n991\n00:50:03,810 --> 00:50:08,640\n然后这里的ITER会归约为表达式--\nAnd this iter will now reduce to the expression\n\n992\n00:50:09,850 --> 00:50:20,200\n(ITER (* COUNTER PRODUCT)\niter of whatever it says, star, counter product, and--\n\n993\n00:50:21,620 --> 00:50:22,240\n按照它代码写的--\nwhat does it say--\n\n994\n00:50:22,680 --> 00:50:24,560\n(+ COUNTER 1))\nplus counter 1\n\n995\n00:50:28,720 --> 00:50:31,420\n在另外的一个环境E2中求值\nin some other environment, by this time, E,2,\n\n996\n00:50:32,970 --> 00:50:35,980\n其中 E2会记录着\nwhere E,2 will be set up having bindings\n\n997\n00:50:36,490 --> 00:50:39,390\nPRODUCT和COUNTER的值\nfor product and counter.\n\n998\n00:50:42,920 --> 00:50:44,330\n它会被归约为这条语句\nAnd it'll reduce to that.\n\n999\n00:50:44,940 --> 00:50:46,040\n它不会记得\nRight? It won't be remembering\n\n1000\n00:50:46,060 --> 00:50:48,750\n它是一个需要返回到某处的一部分\nthat it's part of something that it has to return to.\n\n1001\n00:50:49,340 --> 00:50:50,430\n当ITER再次调用ITER时\nAnd when iter calls iter again,\n\n1002\n00:50:50,440 --> 00:50:52,560\n它会归约为另一个像这样的东西\nit'll reduce to another thing that looks like this\n\n1003\n00:50:53,050 --> 00:50:54,680\n只是会在新环境E3中\nin some environment, E,3,\n\n1004\n00:50:54,830 --> 00:50:56,670\n里面有关于PRODUCT和COUNTER新的绑定\nwhich has new bindings for product and counter.\n\n1005\n00:50:58,800 --> 00:51:05,290\n因此 如果你想知道\nOK? So, if you're wondering,\n\n1006\n00:51:06,090 --> 00:51:07,530\n如果你一直感到不安\nif you've always been queasy about\n\n1007\n00:51:08,250 --> 00:51:10,670\n不知道为什么我们说这些过程\nabout how it is we've been saying those procedures\n\n1008\n00:51:10,670 --> 00:51:12,450\n虽然从语法上看起来是递归的\nthat look syntactically recursive,\n\n1009\n00:51:13,200 --> 00:51:15,690\n但实际上是迭代的\nare, in fact, iterative,\n\n1010\n00:51:15,870 --> 00:51:17,240\n可以在常量空间中运行\nrun in constant space,\n\n1011\n00:51:18,400 --> 00:51:19,750\n我不知道这么说是否打消了你们的疑虑\nwell, I don't know if this makes you less queasy,\n\n1012\n00:51:19,750 --> 00:51:21,230\n但至少让你们知道发生了什么\nbut at least it shows you what's happening.\n\n1013\n00:51:21,230 --> 00:51:22,810\n这其中没有任何构造\nThere really isn't any buildup there.\n\n1014\n00:51:25,910 --> 00:51:27,580\n但你也会说 这里面还是有一些构造\nNow, you might ask well, is there buildup\n\n1015\n00:51:27,980 --> 00:51:30,080\n从原则上来说 我们也构造了环境框架\nin principle in these environment frames?\n\n1016\n00:51:31,710 --> 00:51:32,370\n答案则是\nAnd the answer is yeah,\n\n1017\n00:51:32,400 --> 00:51:33,840\n你确实需要构建这些环境框架\nyou have to make these new environment frames,\n\n1018\n00:51:33,840 --> 00:51:35,264\n但是 等你求值完毕后\nbut you don't have to hang onto them\n\n1019\n00:51:35,424 --> 00:51:36,192\n不必保留它们\nwhen you're done.\n\n1020\n00:51:36,440 --> 00:51:37,610\n它们可以被废料收集\nThey can be garbage collected,\n\n1021\n00:51:37,920 --> 00:51:39,470\n这些空间也可以被自动地重用\nor the space can be reused automatically.\n\n1022\n00:51:40,720 --> 00:51:42,990\n但你们可以看到求值器控制流\nBut you see the control structure of the evaluator\n\n1023\n00:51:43,250 --> 00:51:46,120\n的中心思想就是进行归约\nis really using this idea that you actually have a reduction,\n\n1024\n00:51:47,020 --> 00:51:49,290\n因此这些过程实际上是迭代过程\nso these procedures really are iterative procedures.\n\n1025\n00:51:50,130 --> 00:51:51,380\n好吧 有什么问题么？\nAll right, let's stop for questions.\n\n1026\n00:52:02,680 --> 00:52:03,230\n好吧 课件休息吧\nAll right, let's break.\n\n1027\n00:52:04,120 --> 00:52:24,560\n[音乐]\n[JESU, JOY OF MAN'S DESIRING]\n\n1028\n00:52:24,600 --> 00:52:29,696\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n1029\n00:52:35,200 --> 00:52:38,368\n讲师： 哈罗德·艾伯森教授 及 格兰德·杰·萨斯曼教授\nBy: Prof. Harold Abelson && Sussman Jay Sussman\n\n1030\n00:52:38,360 --> 00:52:42,144\n《计算机程序的构造和解释》\nThe Structure And Interpretation of Computer Programs\n\n1031\n00:52:42,140 --> 00:52:46,448\n显示控制求值器\nExplicit-control Evaluator\n\n1032\n00:52:48,770 --> 00:52:51,550\n教授：跟迭代过程形成对比的是\nPROFESSOR: Let me contrast the iterative procedure\n\n1033\n00:52:52,770 --> 00:52:54,896\n确实会占用空间的\njust so you'll see where space does build up\n\n1034\n00:52:55,120 --> 00:52:56,140\n递归过程\nwith a recursive procedure,\n\n1035\n00:52:56,170 --> 00:52:57,290\n你们可以看到其中的区别\nso you can see the difference.\n\n1036\n00:52:58,030 --> 00:53:01,200\n让我们来看看递归式阶乘的求值\nLet's look at the evaluation of recursive factorial.\n\n1037\n00:53:02,650 --> 00:53:05,536\n这里的FACT-REC\nSo, here's fact-recursive,\n\n1038\n00:53:05,552 --> 00:53:07,220\n就是阶乘的标准定义\nor standard factorial definition.\n\n1039\n00:53:07,220 --> 00:53:10,010\n这个当然是一个递归过程\nWe said this one is still a recursive procedure,\n\n1040\n00:53:10,010 --> 00:53:12,570\n它的计算过程也是递归的\nbut this is actually a recursive process.\n\n1041\n00:53:13,750 --> 00:53:16,560\n然后 只要把它和我们开始的方式联系起来\nAnd then, just to link it back to the way we started,\n\n1042\n00:53:16,830 --> 00:53:20,530\n我们会通过代换模型发现\nwe said oh, you can see that it's going to be recursive process\n\n1043\n00:53:20,530 --> 00:53:21,820\n这是一个递归过程\nby the substitution model\n\n1044\n00:53:22,360 --> 00:53:28,000\n因为 如果我调用(REC-FACT 5)\nbecause, if I say recursive factorial of 5,\n\n1045\n00:53:30,450 --> 00:53:34,940\n会变成(* 5\nthat turns into 5 times--\n\n1046\n00:53:36,280 --> 00:53:37,820\n哦 这里是FACT-REC\nwhat is it, fact-rec, or record fact--\n\n1047\n00:53:42,620 --> 00:53:47,930\n(* 5 (FACT-REC 4))\n5 times recursive factorial of 4,\n\n1048\n00:53:49,660 --> 00:53:58,220\n又会变成(* 5 (* 4 (FACT-REC 3)))\nwhich turns into 5 times 4 times fact-rec of 3,\n\n1049\n00:54:00,220 --> 00:54:08,600\n又会变成(* 5 (* 4 (* 3 (* ...\nwhich returns into 5 times 4 times 3 times\n\n1050\n00:54:13,450 --> 00:54:15,310\n以此类推\nand so on, right?\n\n1051\n00:54:15,390 --> 00:54:17,390\n关键点就是 有一条链条被不断构造出来\nThe idea is there was this chain of stuff building up,\n\n1052\n00:54:18,100 --> 00:54:20,060\n这就在代换模型中证明了\nwhich justified, in the substitution model,\n\n1053\n00:54:20,080 --> 00:54:21,280\nFACT-REC是递归的\nthe fact that it's recursive.\n\n1054\n00:54:21,520 --> 00:54:24,180\n现在 让我们来看看这条构造起来的链条\nAnd now, let's actually see that chain of stuff build up\n\n1055\n00:54:24,180 --> 00:54:25,290\n它又是在机器中的什么地方？\nand where it is in the machine, OK?\n\n1056\n00:54:27,680 --> 00:54:29,950\n好吧 让我们想象一下要从哪里开始\nAll right, well, let's imagine we're going to start out again.\n\n1057\n00:54:30,440 --> 00:54:40,010\n我们告诉机器 求值(FACT-REC 5)\nWe'll tell it to evaluate recursive factorial of 5\n\n1058\n00:54:41,450 --> 00:54:43,390\n基于的环境是E0\nin some environment, again, E0, where\n\n1059\n00:54:45,080 --> 00:54:48,970\n也就是定义FACT-REC时的环境\nwhere recursive factorial is defined, OK?\n\n1060\n00:54:49,550 --> 00:54:51,230\n现在 我们知道最终要发生什么\nWell, now we know what's eventually going to happen.\n\n1061\n00:54:52,250 --> 00:54:53,640\n首先\nThis is going to come along,\n\n1062\n00:54:53,920 --> 00:54:55,640\n它会对这些东西求值\nit'll evaluate those things,\n\n1063\n00:54:55,680 --> 00:54:56,990\n发现它是一个过程\nfigure out it's a procedure,\n\n1064\n00:54:57,180 --> 00:55:00,160\n在这里创建一个新环境E1\nbuild somewhere over here an environment, E1,\n\n1065\n00:55:00,880 --> 00:55:03,690\n其中N=5\nwhich has n bound to 5,\n\n1066\n00:55:04,330 --> 00:55:06,540\n并且与E0相连\nwhich hangs off of E0,\n\n1067\n00:55:07,800 --> 00:55:08,970\n这个E0也就是\nwhich would be, presumably,\n\n1068\n00:55:08,990 --> 00:55:12,300\n定义FACT-REC的那个环境\nthe definition environment of recursive factorial.\n\n1069\n00:55:14,110 --> 00:55:15,740\n然后 在E1这个环境中\nOK? And, in this environment,\n\n1070\n00:55:15,760 --> 00:55:17,480\n求值过程的体\nit's going to go off and evaluate the body.\n\n1071\n00:55:19,670 --> 00:55:25,920\n因此 在这里求值会归约为\nSo, again, the evaluation here will reduce to\n\n1072\n00:55:27,000 --> 00:55:28,920\n在E1中求值过程的体\nevaluating the body in E1.\n\n1073\n00:55:30,160 --> 00:55:31,340\n这就需要求值IF语句\nThat's going to look at an if,\n\n1074\n00:55:32,170 --> 00:55:33,530\n而我不会讲解IF语句的细节\nand I won't go through the details of if.\n\n1075\n00:55:33,530 --> 00:55:34,880\nIF语句会求值谓词\nIt'll look at the predicate.\n\n1076\n00:55:34,880 --> 00:55:37,530\n最后发现需要求值ELSE子句\nIt'll decide it eventually has to evaluate the alternative.\n\n1077\n00:55:37,840 --> 00:55:40,410\n因此 这里的整个部分 会归约为\nSo this whole thing, again, will reduce to\n\n1078\n00:55:41,300 --> 00:55:45,530\nFACT-REC的ELSE子句\nthe alternative of recursive factorial,\n\n1079\n00:55:45,820 --> 00:55:46,970\n也就是谓词为假的部分\nthe alternative clause,\n\n1080\n00:55:47,230 --> 00:55:51,160\n整个表达式就归约为了(* N\nwhich says that this whole thing reduces to times n\n\n1081\n00:55:53,070 --> 00:55:59,960\n(FACT-REC (- N 1))\nof recursive factorial of n minus 1\n\n1082\n00:56:03,480 --> 00:56:05,550\n求值的环境是E1\nin the environment E1\n\n1083\n00:56:08,380 --> 00:56:10,910\n因此 最初的表达式现在就会归约为\nOK? So the original expression, now, is going to reduce\n\n1084\n00:56:11,040 --> 00:56:12,520\n求值这样的一个表达式\nto evaluating that expression, all right?\n\n1085\n00:56:13,750 --> 00:56:16,280\n而现在 我们面对的是一个应用\nOK? Now we have an application.\n\n1086\n00:56:16,280 --> 00:56:17,630\n我们之前求值过应用\nWe did an application before.\n\n1087\n00:56:18,220 --> 00:56:20,250\n还记得要怎么求值应用么？\nRemember what happens in an application?\n\n1088\n00:56:20,360 --> 00:56:21,690\n正式求值一个应用之前\nThe first thing you do is you go off and you\n\n1089\n00:56:21,740 --> 00:56:24,810\n你需要把CONTINUE寄存器的值保存在栈上\nyou save the value of the continue register on the stack.\n\n1090\n00:56:25,350 --> 00:56:27,180\n此时 栈上会有一个值'DONE\nSo the stack here is going to have done in it.\n\n1091\n00:56:29,980 --> 00:56:32,880\n接下来 你要为求值子部分做准备\nAnd then you're going to set up to evaluate the sub-parts.\n\n1092\n00:56:35,000 --> 00:56:37,200\n因此 我们在这里开始求值子部分\nOK? So here we go off to evaluate the sub-parts.\n\n1093\n00:56:39,470 --> 00:56:41,450\n首先要做的是求值运算符\nFirst thing we're going to do is evaluate the operator.\n\n1094\n00:56:44,600 --> 00:56:46,320\n运算符是怎样求值的呢？\nWhat happens when we evaluate an operator?\n\n1095\n00:56:47,250 --> 00:56:48,990\n我们通过一些手段\nWell, we arrange things so that\n\n1096\n00:56:49,000 --> 00:56:51,040\n将EXP寄存器指向运算符对应的过程\nthe operator ends up in the expression register.\n\n1097\n00:56:51,480 --> 00:56:53,150\n并且让ENV寄存器指向求值的环境\nThe environments in the ENV register\n\n1098\n00:56:53,660 --> 00:56:54,608\n而把CONTINUE寄存器赋值为\ncontinue someplace\n\n1099\n00:56:54,624 --> 00:56:56,220\n用于求值参数的EVAL-ARGS\nwhere we're going to go evaluate the arguments.\n\n1100\n00:56:56,590 --> 00:56:57,370\n并且 我们把\nAnd, on the stack,\n\n1101\n00:56:57,400 --> 00:56:59,290\nCONTINUE的原始值保存在栈上\nwe've saved the original continue,\n\n1102\n00:56:59,520 --> 00:57:01,020\n我们完成所有工作后 就会跳转到这个地方\nwhich is where we wanted to be when we're all done.\n\n1103\n00:57:01,720 --> 00:57:02,860\n在我们求值完运算符后\nAnd then the things we needed\n\n1104\n00:57:03,580 --> 00:57:05,800\n需要做的则是\nwhen we're going to get done evaluating the operator,\n\n1105\n00:57:05,900 --> 00:57:07,660\n求值对实际参数进行求值\nthe things we'll need to evaluate the arguments,\n\n1106\n00:57:07,690 --> 00:57:12,010\n也就是这个环境和这些参数\nnamely the environment and those arguments,\n\n1107\n00:57:12,140 --> 00:57:13,440\n这些尚未求值的实际参数\nthose unevaluated arguments,\n\n1108\n00:57:14,200 --> 00:57:15,620\n它们现在都还在栈上\nso there they are sitting on the stack.\n\n1109\n00:57:15,620 --> 00:57:18,590\n我们现在就要先来求值运算符\nAnd we're about to go off to evaluate the operator.\n\n1110\n00:57:23,260 --> 00:57:26,730\n当我们从这个调用返回时\nWell, when we return from this particular call--\n\n1111\n00:57:26,920 --> 00:57:28,640\n在这里 我们将要去调用EVAL-DISPATCH\nso we're about to call eval-dispatch here--\n\n1112\n00:57:29,380 --> 00:57:30,830\n当我们从这个调用返回时\nwhen we return from this call,\n\n1113\n00:57:31,450 --> 00:57:32,700\n这个运算符所对应的值\nthe value of that operator,\n\n1114\n00:57:32,730 --> 00:57:33,520\n在本例中\nwhich, in this case,\n\n1115\n00:57:33,552 --> 00:57:35,440\n也就是基本的乘法过程\nis going to be the primitive multiplier procedure,\n\n1116\n00:57:36,440 --> 00:57:37,930\n会存放在FUN寄存器中\nwill end up in the FUN register.\n\n1117\n00:57:43,020 --> 00:57:44,530\n我们要去求值实际参数\nWe're going to evaluate some arguments.\n\n1118\n00:57:44,530 --> 00:57:45,850\n现在这里求值N\nThey will evaluate n here.\n\n1119\n00:57:47,730 --> 00:57:49,870\n本例中 会返回5\nThat'll give us 5, in this case.\n\n1120\n00:57:50,250 --> 00:57:52,040\n然后我们会把它放入ARGL寄存器\nWe're going to put that in the argl register,\n\n1121\n00:57:53,000 --> 00:57:55,880\n然后我们会去求值第二个运算对象\nand then we'll go off to evaluate the second operand.\n\n1122\n00:57:57,460 --> 00:58:00,480\n就在我们准备求值第二个运算对象之时\nSo, at the point where we go off to evaluate the second operand--\n\n1123\n00:58:00,520 --> 00:58:02,192\n我会省略计算\nand I'll skip details like computing,\n\n1124\n00:58:02,208 --> 00:58:03,580\n(- N 1)之类的细节\nN minus 1, and all of that--\n\n1125\n00:58:03,710 --> 00:58:05,880\n但是 当我们去求值第二个运算对象时\nbut, when we go off to evaluate the second operand,\n\n1126\n00:58:06,620 --> 00:58:10,440\n会最终归约为对FACT-REC的另一个调用\nthat will eventually reduce to another call to fact-recursive.\n\n1127\n00:58:12,000 --> 00:58:14,200\n现在 我们在栈上有\nAnd, what we've got on the stack here is\n\n1128\n00:58:16,520 --> 00:58:19,940\n来自于这个组合式的运算符\nthe operator from that combination that we're going to use it in\n\n1129\n00:58:20,120 --> 00:58:21,070\n以及其它的参数\nand the other argument.\n\n1130\n00:58:23,400 --> 00:58:27,610\n现在 我们已经准备好\nOK? So, now, we're set up for another call\n\n1131\n00:58:28,490 --> 00:58:29,690\n去调用另外的FACT-REC了\nto recursive factorial.\n\n1132\n00:58:30,200 --> 00:58:31,430\n而让我们完成了这个调用以后\nAnd, when we're done with this one,\n\n1133\n00:58:31,560 --> 00:58:33,640\n我们就要跳转到ACCUMULATE-LAST-ARG\nwe're going to go to accumulate the last arg.\n\n1134\n00:58:34,120 --> 00:58:35,200\n还记得这是做什么的么？\nand remember what that'll do?\n\n1135\n00:58:35,200 --> 00:58:35,930\n它会说\nThat'll say oh,\n\n1136\n00:58:36,450 --> 00:58:39,280\n我们会把这个调用的结果\nwhatever the result of this has to get combined with that,\n\n1137\n00:58:39,280 --> 00:58:40,400\n和这个5相乘\nand we're going to multiply them.\n\n1138\n00:58:41,690 --> 00:58:42,380\n但是请注意\nBut, notice now,\n\n1139\n00:58:42,730 --> 00:58:44,810\n我们现在处于另一个递归阶乘中\nwe're at another recursive factorial.\n\n1140\n00:58:45,720 --> 00:58:48,920\n我们又要再次调用EVAL-DISPATCH\nWe're about to call eval-dispatch again,\n\n1141\n00:58:49,320 --> 00:58:50,600\n然而我们并没有真正地“归约”它\nexcept we haven't really reduced it\n\n1142\n00:58:50,640 --> 00:58:52,080\n因为现在栈上还有东西\nbecause there's stuff on the stack now.\n\n1143\n00:58:53,700 --> 00:58:55,390\n栈上的这些东西说：“当你返回时”\nThe stuff on the stack says oh, when you get back,\n\n1144\n00:58:55,400 --> 00:58:57,520\n你最好把结果和放在这里的5相乘\nyou'd better multiply it by the 5 you had hanging there.\n\n1145\n00:58:58,430 --> 00:59:05,770\n所以当我们进行另外的调用\nSo, when we go off to make another call,\n\n1146\n00:59:07,120 --> 00:59:08,840\n求值(- N 1)\nwe evaluate the n minus 1.\n\n1147\n00:59:09,300 --> 00:59:11,050\n这会返回给我们另一个环境\nThat gives us another environment which\n\n1148\n00:59:11,250 --> 00:59:13,840\n其中N的新值为4\nin which the new n's going to be down to 4.\n\n1149\n00:59:14,600 --> 00:59:16,220\n然后又将调用EVAL-DISPATCH\nAnd we're about to call eval-dispatch again.\n\n1150\n00:59:19,200 --> 00:59:20,220\n我们又创建了另一个调用\nWe get another call.\n\n1151\n00:59:21,350 --> 00:59:24,440\n这个4又会遇到相同的情况\nThat 4 is going to end up in the same situation.\n\n1152\n00:59:26,040 --> 00:59:28,620\n我们最后会遇到对(FACT-REC N)的又一次调用\nWe'll end up with another call to fact-recursive n.\n\n1153\n00:59:30,020 --> 00:59:32,680\n而这时候 栈上会有从最初的调用\nAnd sitting on the stack will be the stuff from the original one\n\n1154\n00:59:32,880 --> 00:59:34,510\n到最近一次调用的东西\nand, now, the subsidiary one we're doing.\n\n1155\n00:59:35,360 --> 00:59:36,910\n它们都在等待同一个东西\nAnd both of them are waiting for the same thing.\n\n1156\n00:59:36,910 --> 00:59:39,160\n它们都要跳转到ACCUMULATE-LAST-ARG\nThey're going to go to accumulate a last argument.\n\n1157\n00:59:40,510 --> 00:59:42,940\n当然 当我们进行第四次调用时\nAnd then, of course, when we go to the fourth call,\n\n1158\n00:59:43,250 --> 00:59:44,380\n会发生同样的事\nthe same thing happens.\n\n1159\n00:59:45,640 --> 00:59:47,070\n如此往复\nAnd this goes on, and on, and on.\n\n1160\n00:59:47,300 --> 00:59:48,600\n在这里 你在栈上看到的\nAnd what you see here on the stack,\n\n1161\n00:59:50,300 --> 00:59:52,220\n栈上面实际存放的是\nexactly what's sitting here on the stack,\n\n1162\n00:59:52,220 --> 00:59:54,590\n基本过程*以及5\nthe thing that says times and 5.\n\n1163\n00:59:54,960 --> 00:59:56,400\n而你要把它用来\nAnd what you're going to do with that\n\n1164\n00:59:56,590 --> 00:59:58,540\n调用ACCUMULATE-LAST-ARG\naccumulate that into a last argument.\n\n1165\n01:00:00,470 --> 01:00:02,016\n就是这样 对吧？\nThat's exactly this, right?\n\n1166\n01:00:02,010 --> 01:00:04,750\n这跟它们在表达式中的顺序是一致的\nThis is exactly where that stuff is hanging.\n\n1167\n01:00:05,650 --> 01:00:10,650\n实际上 你将要应用的运算符\nEffectively, the operator you're going to apply,\n\n1168\n01:00:11,720 --> 01:00:14,304\n以及当你返回时\nthe other argument that it's got\n\n1169\n01:00:14,320 --> 01:00:15,790\n需要去求积的参数\nto be multiplied by when you get back\n\n1170\n01:00:15,808 --> 01:00:16,910\n以及这里的括号\nand sort of the parentheses,\n\n1171\n01:00:16,940 --> 01:00:18,960\n都在告诉你 在对它们进行积累\nwhich says yeah, what you wanted to do was accumulate them.\n\n1172\n01:00:19,620 --> 01:00:21,880\n因此 你可以看到代换模型并不是这样的谎言\nSo, you see, the substitution model is not such a lie.\n\n1173\n01:00:22,560 --> 01:00:23,630\n从某种意义上来说 它实际上是\nThat really is, in some sense,\n\n1174\n01:00:23,640 --> 01:00:25,310\n存在于栈上的那些东西\nwhat's sitting right on the stack.\n\n1175\n01:00:29,370 --> 01:00:30,400\n好吧 从某种意义上来说\nAll right, so that,\n\n1176\n01:00:30,810 --> 01:00:32,480\n应该给你们解释了\nin some sense, should explain for you,\n\n1177\n01:00:33,260 --> 01:00:34,520\n或者 至少让你们相信\nor at least convince you,\n\n1178\n01:00:35,930 --> 01:00:38,720\n求值器会通过某些方式\nthat somehow, this evaluator is managing\n\n1179\n01:00:40,060 --> 01:00:42,860\n迭代地去求值某些过程\nto take these procedures and execute some of them iteratively\n\n1180\n01:00:42,950 --> 01:00:44,250\n而递归地去求值另外的过程\nand some of them recursively,\n\n1181\n01:00:45,260 --> 01:00:47,450\n尽管从语法上看\neven though, as syntactically,\n\n1182\n01:00:47,450 --> 01:00:49,050\n它们都是递归过程\nthey look like recursive procedures.\n\n1183\n01:00:49,400 --> 01:00:50,640\n它又是如何做到的呢？\nHow's it managing to do that?\n\n1184\n01:00:50,660 --> 01:00:53,720\n其中的基本原因就是\nWell, the basic reason it's managing to do that\n\n1185\n01:00:53,800 --> 01:00:55,680\n求值器被设置为\nis the evaluator is set up\n\n1186\n01:00:56,040 --> 01:00:59,260\n只保存那些稍后会用到的东西\nto save only what it needs later.\n\n1187\n01:01:01,090 --> 01:01:04,250\n比如说 当你在把\nSo, for example, at the point where you've reduced\n\n1188\n01:01:04,670 --> 01:01:07,390\n在一个环境中求值表达式归约为\nevaluating an expression and an environment\n\n1189\n01:01:07,870 --> 01:01:09,870\n将某个过程应用在参数上时\nto applying a procedure to some arguments,\n\n1190\n01:01:10,520 --> 01:01:12,490\n它就不再需要最初的环境了\nit doesn't need that original environment anymore\n\n1191\n01:01:13,370 --> 01:01:16,650\n因为所需要的环境信息都被打包到\nbecause any environment stuff will be packaged inside the procedures\n\n1192\n01:01:17,880 --> 01:01:19,360\n需要应用的那个过程中了\nwhere the application's going to happen.\n\n1193\n01:01:20,750 --> 01:01:21,610\n同样 类似地\nAll right, similarly,\n\n1194\n01:01:21,630 --> 01:01:23,650\n当你求值一个参数表时\nwhen you're going along evaluating an argument list,\n\n1195\n01:01:23,650 --> 01:01:25,200\n当你完成对表的求值时\nwhen you've finished evaluating the list,\n\n1196\n01:01:25,910 --> 01:01:28,030\n当你求值完最后一个参数时\nwhen you're finished evaluating the last argument,\n\n1197\n01:01:28,200 --> 01:01:31,610\n你就不再需要这个参数表了 对吧？\nyou don't need that argument list any more, right?\n\n1198\n01:01:31,630 --> 01:01:32,940\n你也就不再需要\nAnd you don't need the environment where\n\n1199\n01:01:33,040 --> 01:01:34,640\n求值这些参数所需的环境了\nthose arguments would be evaluated.\n\n1200\n01:01:36,690 --> 01:01:40,890\n所以这个解释器如此“智能”的根本原因\nSo the basic reason that this interpreter is being so smart\n\n1201\n01:01:40,890 --> 01:01:42,880\n根本不是因为它“智能” 只是因为它老实\nis that it's not being smart at all, it's being stupid.\n\n1202\n01:01:43,050 --> 01:01:45,740\n它的原则就是：“只保存那些需要的”\nIt's just saying I'm only going to save what I really need.\n\n1203\n01:01:48,700 --> 01:01:51,000\n这里 让我来给你们展示\nWell, let me show you here.\n\n1204\n01:01:53,070 --> 01:01:57,200\n这是致使尾递归的根本原因\nHere's the actual thing that's making a tail recursive.\n\n1205\n01:01:58,310 --> 01:02:00,200\n要记住 (RESOTRE CONTINUE)这条代码\nRemember, it's the restore of continue.\n\n1206\n01:02:00,220 --> 01:02:06,940\n它指的是 当我去求值过程体的时候\nIt's saying when I go off to evaluate the procedure body,\n\n1207\n01:02:08,960 --> 01:02:11,000\n我应该告诉EVAL返回到\nI should tell eval to come back to\n\n1208\n01:02:11,250 --> 01:02:12,540\n最初的求值\nthe place where that original\n\n1209\n01:02:12,540 --> 01:02:14,250\n应该返回的地方\nevaluation was supposed to come back to.\n\n1210\n01:02:15,170 --> 01:02:15,950\n因此 从某种角度来说\nSo, in some sense,\n\n1211\n01:02:16,170 --> 01:02:18,840\n你想知道是哪一行代码致使了尾递归\nyou want to say what's the actual line that makes tail recursive\n\n1212\n01:02:18,890 --> 01:02:19,440\n那么就是这一行\nIt's that one.\n\n1213\n01:02:19,920 --> 01:02:21,530\n出于某些奇怪的原因\nIf I wanted to build a non-\n\n1214\n01:02:21,770 --> 01:02:24,800\n如果我想构建一个没有尾递归的求值器\ntail recursive evaluator, for some strange reason,\n\n1215\n01:02:25,690 --> 01:02:26,860\n我需要做的就是\nall I would need to do\n\n1216\n01:02:27,120 --> 01:02:29,290\n在这里先不要去恢复CONTINUE\nis, instead of restoring continue at this point,\n\n1217\n01:02:30,060 --> 01:02:31,660\n而是在这里建立一个标号\nI'd set up a label down here\n\n1218\n01:02:32,750 --> 01:02:36,250\n用来标识完成过程应用后的返回位置\ncalled, \"Where to come back after you've finished applying the procedure.\"\n\n1219\n01:02:37,640 --> 01:02:39,710\n而我会把CONTINUE设置为这个标号\nInstead, I'd set continue to that.\n\n1220\n01:02:39,920 --> 01:02:41,210\n然后跳转到EVAL-DISPATCH\nI'd go to eval-dispatch,\n\n1221\n01:02:41,400 --> 01:02:43,210\n然后EVAL-DISPATCH会回到这里\nand then eval-dispatch would come back here.\n\n1222\n01:02:43,790 --> 01:02:44,300\n而这时\nAt that point,\n\n1223\n01:02:44,320 --> 01:02:45,280\n我会恢复CONTINUE\nI would restore continue\n\n1224\n01:02:45,290 --> 01:02:46,520\n并回到最初的返回位置\nand go to the original one.\n\n1225\n01:02:47,920 --> 01:02:51,000\n因此 这里唯一的后果就是\nSo here, the only consequence of that\n\n1226\n01:02:51,150 --> 01:02:52,680\n解释器不再是尾递归的了\nwould be to make it non-tail recursive.\n\n1227\n01:02:52,840 --> 01:02:54,620\n它会给你完全相同的答案\nIt would give you exactly the same answers,\n\n1228\n01:02:54,720 --> 01:02:57,020\n只是当你执行迭代式阶乘\nexcept if you did that iterative factorial\n\n1229\n01:02:57,050 --> 01:02:58,360\n或者其它迭代过程时\nand all those iterative procedures,\n\n1230\n01:02:58,600 --> 01:02:59,800\n它都会递归地去执行\nit would execute recursively.\n\n1231\n01:03:03,040 --> 01:03:05,400\n然而 我对你们撒了一个小谎\nWell, I lied to you a little bit, but just a little bit,\n\n1232\n01:03:05,760 --> 01:03:06,990\n因为我演示的\nbecause I showed you a slightly\n\n1233\n01:03:07,020 --> 01:03:08,330\n一个有些过于简化的解释器\nover-simplified evaluator\n\n1234\n01:03:08,720 --> 01:03:10,380\n这个解释器假设每个过程\nwhere it assumes that each procedure --\n\n1235\n01:03:11,360 --> 01:03:13,660\n只含有一条表达式\neach procedure body has only one expression.\n\n1236\n01:03:13,890 --> 01:03:14,540\n还记得吗 通常来说\nRemember, in general,\n\n1237\n01:03:14,560 --> 01:03:16,570\n过程的体是多条表达式组成的序列\na procedure has a sequence of expressions in it.\n\n1238\n01:03:17,870 --> 01:03:20,490\n所以没有什么新概念\nSo there's nothing really conceptually new.\n\n1239\n01:03:20,490 --> 01:03:22,280\n让我来展示一下实际的求值器\nLet me just show you the actual evaluator\n\n1240\n01:03:22,890 --> 01:03:24,730\n是怎么来处理表达式序列的\nthat handles sequences of expressions.\n\n1241\n01:03:28,470 --> 01:03:29,740\n这是现在的COMPOUND-APPLY\nThis is compound-apply now,\n\n1242\n01:03:29,740 --> 01:03:31,310\n和之前的唯一不同是\nand the only difference from the old one\n\n1243\n01:03:32,070 --> 01:03:34,330\n它不再直接地跳转到EVAL\nis that, instead of going off to eval directly,\n\n1244\n01:03:35,980 --> 01:03:38,030\n它先获取整个过程的体\nit takes the whole body of the procedure,\n\n1245\n01:03:38,030 --> 01:03:40,150\n在本例中 也就是表达式序列\nwhich, in this case, is a sequence of expressions,\n\n1246\n01:03:40,280 --> 01:03:41,710\n然后跳转到EVAL-SEQUENCE\nand goes off to eval-sequence.\n\n1247\n01:03:42,600 --> 01:03:45,320\nEVAL-SEQUENCE是一个小型的循环\nAnd eval-sequence is a little loop\n\n1248\n01:03:46,830 --> 01:03:49,980\n然后每次求值一条表达式\nthat, basically, does these evaluations one at a time.\n\n1249\n01:03:52,630 --> 01:03:53,850\n就是这样来求值的--\nSo it does an evaluation.\n\n1250\n01:03:53,900 --> 01:03:54,940\n当它求值完一条表达式后\nSays oh, when I come back,\n\n1251\n01:03:54,970 --> 01:03:56,860\n会跳转到这里 去求值下一条\nI'd better come back here to do the next one.\n\n1252\n01:03:58,440 --> 01:03:59,290\n当我完成了所有的求值后\nAnd, when I'm all done,\n\n1253\n01:03:59,290 --> 01:04:01,020\n我想要跳转到LAST-EXP\nwhen I want to get the last expression,\n\n1254\n01:04:01,310 --> 01:04:03,280\n我就只需要恢复CONTINUE寄存器\nI just restore my continue\n\n1255\n01:04:03,920 --> 01:04:05,280\n然后跳转到EVAL-DISPATCH\nand go off to eval-dispatch.\n\n1256\n01:04:06,410 --> 01:04:08,200\n同样的 如果你想要在这种求值器中\nAnd, again, if you wanted for some reason\n\n1257\n01:04:08,200 --> 01:04:10,350\n破坏尾递归机制\nto break tail recursion in this evaluator,\n\n1258\n01:04:10,640 --> 01:04:13,710\n你只需要在LAST-EXP中不做特殊处理即可\nall you need to do is not handle the last expression, especially.\n\n1259\n01:04:14,900 --> 01:04:17,340\n也就是说 当你处理完最后一条表达式\nJust say, after you've done the last expression,\n\n1260\n01:04:17,360 --> 01:04:18,650\n你跳转到另外一个地方\ncome back to some other place\n\n1261\n01:04:19,150 --> 01:04:20,680\n在那个地方去恢复CONTINUE\nafter which you restore continue.\n\n1262\n01:04:21,900 --> 01:04:23,260\n出于某些原因\nAnd, for some reason,\n\n1263\n01:04:23,260 --> 01:04:25,740\n很多Lisp求值器倾向于这么做\na lot of LISP evaluators tended to work that way.\n\n1264\n01:04:26,550 --> 01:04:28,440\n这样做的后果就是\nAnd the only consequence of that is that\n\n1265\n01:04:28,860 --> 01:04:30,720\n迭代式过程也会使栈增长\niterative procedures built up stack.\n\n1266\n01:04:31,880 --> 01:04:33,610\n还不清楚为什么会这样\nAnd it's not clear why that happened.\n\n1267\n01:04:35,920 --> 01:04:37,980\n好吧 我稍微来总结一下\nAll right. Well, let me just sort of summarize,\n\n1268\n01:04:38,090 --> 01:04:39,600\n毕竟这是一个大程序\nsince this is a lot of details\n\n1269\n01:04:39,980 --> 01:04:41,040\n又有很多细节\nin a big program.\n\n1270\n01:04:41,120 --> 01:04:42,250\n但关键点就是\nBut the main point is that\n\n1271\n01:04:43,040 --> 01:04:43,872\n从概念上来说\nit's no different,\n\n1272\n01:04:44,048 --> 01:04:46,080\n这跟翻译其它程序没什么不同\nconceptually, from translating any other program.\n\n1273\n01:04:47,060 --> 01:04:48,060\n核心思想就是\nAnd the main idea is that\n\n1274\n01:04:48,060 --> 01:04:50,280\n我们已经有了通用求值器程序\nwe have this universal evaluator program,\n\n1275\n01:04:50,330 --> 01:04:51,710\n一个元循环求值器\nthe meta-circular evaluator.\n\n1276\n01:04:51,870 --> 01:04:53,070\n如果我们把它翻译为了Lisp\nIf we translate that into LISP,\n\n1277\n01:04:53,100 --> 01:04:53,950\n那么我们就有了Lisp的所有东西\nthen we have all of LISP.\n\n1278\n01:04:54,330 --> 01:04:55,150\n我们就是这么来做的\nAnd that's all we did.\n\n1279\n01:04:57,980 --> 01:04:59,680\n第二点则是 魔法消失了\nThe second point is that the magic's gone away.\n\n1280\n01:04:59,680 --> 01:05:01,970\n这整个系统不再神秘了 对吧？\nThere should be no more magic in this whole system, right?\n\n1281\n01:05:01,970 --> 01:05:07,790\n原则上来说 这应该相当清楚了\nIn principle, it should all be very clear\n\n1282\n01:05:07,820 --> 01:05:10,080\n只是还不太了解表结构的内存管理\nexcept, maybe, for how list structured memory works,\n\n1283\n01:05:10,800 --> 01:05:11,800\n我们后面会讲\nand we'll see that later.\n\n1284\n01:05:12,640 --> 01:05:14,200\n这也并不困难\nBut that's not very hard.\n\n1285\n01:05:15,450 --> 01:05:16,350\n第三点就是\nThe third point is that\n\n1286\n01:05:16,350 --> 01:05:17,520\n所有的这些尾递归\nall this tail recursion\n\n1287\n01:05:18,240 --> 01:05:21,960\n来自于严格的求值纪律\ncame from the discipline of eval being very careful\n\n1288\n01:05:22,550 --> 01:05:24,510\n也就是只保存那些后面会用到的东西\nto save only what it needs next time.\n\n1289\n01:05:25,870 --> 01:05:27,720\n而不是一些比较随意的原则\nIt's not some arbitrary thing\n\n1290\n01:05:27,760 --> 01:05:29,860\n比如 无论什么时候我们调用一个子过程\nwhere we're saying well, whenever we call a sub-routine,\n\n1291\n01:05:29,860 --> 01:05:32,160\n我们会保存所有的寄存器并且返回\nwe'll save all the registers in the world and come back?\n\n1292\n01:05:33,940 --> 01:05:36,490\n有些时候为了提效 这样做很值得\nSee, sometimes it pays to really worry about efficiency.\n\n1293\n01:05:37,150 --> 01:05:39,960\n当你研究求值机器的内部原理时\nAnd, when you're down in the guts of your evaluator machine,\n\n1294\n01:05:40,450 --> 01:05:42,560\n这类东西就很值得去研究\nit really pays to think about things like that\n\n1295\n01:05:42,560 --> 01:05:43,960\n因为它会带来显著的不同\nbecause it makes big consequences.\n\n1296\n01:05:45,230 --> 01:05:47,690\n我想现在基本上已经\nWell, I hope what this has done\n\n1297\n01:05:47,900 --> 01:05:52,300\n把这个求值器讲得很清楚了\nis really made the evaluator seem concrete.\n\n1298\n01:05:52,560 --> 01:05:53,900\n我希望你们能相信\nI hope you really believe\n\n1299\n01:05:54,320 --> 01:05:56,270\n真的有人能够\nthat somebody could hold a LISP\n\n1300\n01:05:56,840 --> 01:05:58,560\n将一个Lisp求值器放在掌心之中\nLISP evaluator in the palm of their hand.\n\n1301\n01:05:59,070 --> 01:06:00,490\n为了让你们死心塌地\nMaybe to help you believe that, here's a\n\n1302\n01:06:00,800 --> 01:06:01,960\n我给你们看一个Lisp求值器\nhere's a LISP evaluator\n\n1303\n01:06:02,540 --> 01:06:04,060\n它就在我的手掌中\nthat I'm holding the palm of my hand.\n\n1304\n01:06:06,160 --> 01:06:10,560\n这块求值器芯片实际上\nAnd this is a chip which is actually\n\n1305\n01:06:10,890 --> 01:06:13,700\n比我给你们展示的求值器还要复杂\nquite a bit more complicated than the evaluator I showed you.\n\n1306\n01:06:16,864 --> 01:06:19,200\n这张图片效果更好\nUh.. maybe, here's a better picture of it.\n\n1307\n01:06:22,070 --> 01:06:22,570\n在这上面\nWhat there is,\n\n1308\n01:06:22,600 --> 01:06:24,380\n你可以看到相同的宏观结构\nis you can see the same overall structure.\n\n1309\n01:06:24,730 --> 01:06:25,930\n这是寄存器阵列\nThis is a register array.\n\n1310\n01:06:26,800 --> 01:06:27,710\n这些是数据通路\nThese are the data paths.\n\n1311\n01:06:27,720 --> 01:06:29,070\n这里有是有穷状态控制器\nHere's a finite state controller.\n\n1312\n01:06:29,800 --> 01:06:31,040\n再强调一下 是有穷状态\nAnd again, finite state,\n\n1313\n01:06:31,960 --> 01:06:32,800\n全都在这里了\nthat's all there is.\n\n1314\n01:06:32,810 --> 01:06:34,160\n在另外的地方还有外部存储\nAnd somewhere there's external memory\n\n1315\n01:06:34,160 --> 01:06:35,230\n用来存储数据\nthat'll worry about things.\n\n1316\n01:06:35,750 --> 01:06:37,630\n而这块芯片非常复杂\nAnd this particular one is very complicated\n\n1317\n01:06:37,640 --> 01:06:39,160\n是因为它尝试更快地运行Lisp\nbecause it's trying to run LISP fast.\n\n1318\n01:06:39,660 --> 01:06:42,970\n它具有非常非常之快的并行运算\nAnd it has some very, very fast parallel operations in there\n\n1319\n01:06:43,070 --> 01:06:46,320\n比如说 如果你想要索引一个数组\nlike, if you want to index into an array,\n\n1320\n01:06:46,700 --> 01:06:50,400\n同时又要检查该索引是否为一个整数\nsimultaneously check that the index is an integer,\n\n1321\n01:06:50,430 --> 01:06:52,860\n以及该索引没有越界\ncheck that it doesn't exceed the array bands,\n\n1322\n01:06:53,040 --> 01:06:55,020\n同时还要进行内存存取\nand go off and do the memory access,\n\n1323\n01:06:55,050 --> 01:06:56,700\n它会同时进行这些事\nand do all those things simultaneously.\n\n1324\n01:06:57,120 --> 01:06:58,400\n如果这些操作都没有问题的话\nAnd then, later, if they're all OK,\n\n1325\n01:06:58,440 --> 01:06:59,960\n最终就会在这里得到结果\nactually get the value there.\n\n1326\n01:07:00,420 --> 01:07:02,460\n因此 数据通路中大量的\nSo there are a lot of complicated operations\n\n1327\n01:07:02,480 --> 01:07:04,650\n复杂运算使得Lisp能够并行运行\nin these data paths for making LISP run in parallel.\n\n1328\n01:07:05,260 --> 01:07:08,416\n这完全是求值Lisp的\nIt's a completely non-risk\n\n1329\n01:07:08,768 --> 01:07:10,360\n一种无冒险的哲学\nphilosophy of evaluating LISP.\n\n1330\n01:07:10,640 --> 01:07:13,200\n并且 这个的微指令也相当复杂\nAnd then, this microcode is pretty complicated.\n\n1331\n01:07:13,450 --> 01:07:17,560\n让我先看一看\nLet's see, there's what?\n\n1332\n01:07:17,600 --> 01:07:21,100\n这其中有大概389条\nThere's about 389 instructions of\n\n1333\n01:07:21,680 --> 01:07:23,850\n220比特的微指令\nof 220-bit microcode sitting here\n\n1334\n01:07:24,070 --> 01:07:27,940\n只因为这些数据通路非常复杂\nbecause these are very complicated data paths.\n\n1335\n01:07:27,940 --> 01:07:32,250\n整个芯片大概有89,000支晶体管\nAnd the whole thing has about 89,000 transistors, OK?\n\n1336\n01:07:33,560 --> 01:07:36,860\n好吧 我希望通过这节课解答了大部分疑惑\nOK. Well, I hope that that takes away a lot of the mystery.\n\n1337\n01:07:37,970 --> 01:07:39,240\n也许你们想看一看这块芯片\nMaybe somebody wants to look at this.\n\n1338\n01:07:46,140 --> 01:07:46,890\n好吧 先讲到这里\nOK. Let's stop.\n\n1339\n01:07:56,460 --> 01:07:56,750\n有问题吗？\nQuestions?\n\n1340\n01:07:59,000 --> 01:08:00,420\n学生：您所讲的 听起来像是\nAUDIENCE: OK, now, it sounds like what you're saying is that,\n\n1341\n01:08:00,420 --> 01:08:03,480\n如果把(RESTORE CONTINUE)放在合适的地方\nwith the restore continue put in the proper place,\n\n1342\n01:08:03,580 --> 01:08:09,420\n这样之前递归求值的过程\nthat procedures that would invoke a recursive process\n\n1343\n01:08:09,420 --> 01:08:11,950\n现在就会变成迭代求值的\nnow invoke an iterative process\n\n1344\n01:08:12,670 --> 01:08:15,360\n（意义不明）\njust by the way that the eval-sequence source?\n\n1345\n01:08:15,600 --> 01:08:17,540\n教授：我想我应该这么来说\nPROFESSOR: I think the way I'd prefer to put it is that,\n\n1346\n01:08:17,540 --> 01:08:19,820\n如果把(RESTORE CONTINUE)放在了错误的位置\nwith restore continue put in the wrong place,\n\n1347\n01:08:20,550 --> 01:08:25,480\n你就会让那些语法上看起来像递归的过程\nyou can cause any syntactically-looking recursive procedure,\n\n1348\n01:08:25,520 --> 01:08:27,280\n在运行的时候不断地扩张栈\nin fact, to build up stack as it runs.\n\n1349\n01:08:28,640 --> 01:08:30,520\n但这样是没有原因的\nBut there's no reason for that,\n\n1350\n01:08:33,150 --> 01:08:35,120\n你可以自己去试一试\nso you might want to play around with it.\n\n1351\n01:08:35,150 --> 01:08:38,090\n你可以在COMPOND-APPLY返回后\nYou can just switch around two or three instructions\n\n1352\n01:08:38,180 --> 01:08:40,780\n交换两、三条语句的顺序\nin the way compound-apply comes back,\n\n1353\n01:08:41,310 --> 01:08:43,260\n那么你得到的就不再是尾递归了\nand you'll get something which isn't tail recursive.\n\n1354\n01:08:45,060 --> 01:08:46,140\n我只是想强调\nBut the thing I wanted to emphasize\n\n1355\n01:08:46,160 --> 01:08:47,400\n这其中没有什么魔法\nis there's no magic. there's no\n\n1356\n01:08:47,670 --> 01:08:48,570\n这并不是\nIt's not as if\n\n1357\n01:08:49,310 --> 01:08:52,170\n有什么智能的预处理程序\nthere's some very clever pre-processing program\n\n1358\n01:08:52,650 --> 01:08:55,450\n它会分析FACT-ITER这个程序\nthat's looking at this procedure, factorial iter,\n\n1359\n01:08:55,470 --> 01:08:56,730\n然后说\nand say oh, gee, um\n\n1360\n01:08:57,420 --> 01:08:58,860\n我注意到\nI really notice that\n\n1361\n01:08:58,880 --> 01:09:01,130\n完成这个调用 不需要我进行压栈\nI don't have to push stack in order to do this.\n\n1362\n01:09:01,130 --> 01:09:02,880\n但是有些人是这么认为的\nSome people think that that's what's going on.\n\n1363\n01:09:03,760 --> 01:09:05,380\n而是一种比这个还要蠢的机制\nIt's something much, much more dumb than that,\n\n1364\n01:09:05,380 --> 01:09:07,500\n就是在合适的地方插入RESTORE指令\nit's this one place you're putting the restore instruction.\n\n1365\n01:09:08,560 --> 01:09:09,790\n就可以自动地实现\nIt's just automatic.\n\n1366\n01:09:14,720 --> 01:09:17,550\n学生：但这不会影响到时间复杂度 对吧？\nAUDIENCE: But that's not affecting the time complexity is it?\n\n1367\n01:09:17,580 --> 01:09:17,870\n教授：不会\nPROFESSOR: No.\n\n1368\n01:09:18,600 --> 01:09:21,770\n学生：它不会迭代地处理\nAUDIENCE: It's just that it's handling it recursively\n\n1369\n01:09:21,800 --> 01:09:23,020\n而是会递归地处理\ninstead of iteratively.\n\n1370\n01:09:23,020 --> 01:09:27,340\n但就从完成这两个运算的时间来说\nBut, in terms of the order of time it takes to finish the operation,\n\n1371\n01:09:27,370 --> 01:09:29,220\n它们都是相同的 对吧？\nit's the same one way or the other, right?\n\n1372\n01:09:29,470 --> 01:09:29,760\n教授 ：是的\nPROFESSOR: Yes.\n\n1373\n01:09:29,790 --> 01:09:32,680\n尾递归不会改变任何东西的时间复杂度\nTail recursion is not going to change the time complexity of anything\n\n1374\n01:09:32,720 --> 01:09:33,290\n因为 从某种意义上来说\nbecause, in some sense,\n\n1375\n01:09:33,340 --> 01:09:35,150\n两者都是相同的算法\nit's the same algorithm that's going on.\n\n1376\n01:09:36,020 --> 01:09:39,370\n它只是让这个过程迭代地运行\nWhat it's doing is really making this thing run as an iteration.\n\n1377\n01:09:41,000 --> 01:09:42,640\n这样 当参数很大时\nRight? Not going to run out of memory\n\n1378\n01:09:42,680 --> 01:09:44,220\n它不会耗尽所有的内存\nyou know counting up to a giant number\n\n1379\n01:09:44,750 --> 01:09:46,400\n因为这其中没有压栈\nsimply because the stack would get pushed.\n\n1380\n01:09:48,350 --> 01:09:50,240\n事实上 你们需要相信\nSee, the thing you really have to believe is that,\n\n1381\n01:09:50,560 --> 01:09:51,130\n当我们编写--\nwhen we write--\n\n1382\n01:09:51,640 --> 01:09:53,780\n我们一直把这些代码称作“迭代”\nsee, we've been writing all these things called iterations,\n\n1383\n01:09:53,930 --> 01:09:57,990\n把(DEFINE (LOOP) (LOOP))称作无穷循环\ninfinite loops, define loop to be called loop.\n\n1384\n01:10:00,320 --> 01:10:03,360\n这就是一个迭代\nThat's is as much an iteration\n\n1385\n01:10:03,650 --> 01:10:05,660\n跟我们用DO语句来写无穷循环是一样的\nyou know as if we wrote do forever loop.\n\n1386\n01:10:07,630 --> 01:10:09,280\n它们只是语法上不同而已\nIt's just syntactic sugar as the difference.\n\n1387\n01:10:09,280 --> 01:10:11,320\n它们实际上都是迭代\nThese things are real, honest to god, iterations?\n\n1388\n01:10:14,730 --> 01:10:16,080\n它们并不改变时间复杂度\nThey don't change the time complexity,\n\n1389\n01:10:16,110 --> 01:10:18,530\n但是它会把它们变成真正的迭代\nbut they turn them into real iterations.\n\n1390\n01:10:21,680 --> 01:10:23,800\n好吧 下课\nAll right, thank you.\n\n1391\n01:10:23,800 --> 01:10:25,800\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n1392\n01:10:25,800 --> 01:10:27,800\n本项目主页\nhttps://github.com/DeathKing/Learning-SICP\n\n\n"
  },
  {
    "path": "SrtEN/lec10a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:05,580\n\n\n1\n00:00:05,580 --> 00:00:20,180\n[MUSIC PLAYING]\n\n2\n00:00:20,180 --> 00:00:23,920\nPROFESSOR: Last time, we took a\nlook at an explicit control\n\n3\n00:00:23,920 --> 00:00:27,280\nevaluator for Lisp, and that\nbridged the gap between all\n\n4\n00:00:27,280 --> 00:00:30,460\nthese high-level languages\nlike Lisp and the query\n\n5\n00:00:30,460 --> 00:00:33,330\nlanguage and all of that stuff,\nbridged the gap between\n\n6\n00:00:33,330 --> 00:00:36,640\nthat and a conventional\nregister machine.\n\n7\n00:00:36,640 --> 00:00:40,140\nAnd in fact, you can think of\nthe explicit control evaluator\n\n8\n00:00:40,140 --> 00:00:44,650\neither as, say, the code for a\nLisp interpreter if you wanted\n\n9\n00:00:44,650 --> 00:00:47,680\nto implement it in the assembly\nlanguage of some\n\n10\n00:00:47,680 --> 00:00:50,120\nconventional register transfer\nmachine, or, if you like, you\n\n11\n00:00:50,120 --> 00:00:52,770\ncan think of it as the microcode\nof some machine\n\n12\n00:00:52,770 --> 00:00:55,340\nthat's going to be specially\ndesigned to run Lisp.\n\n13\n00:00:55,340 --> 00:00:58,160\nIn either case, what we're\ndoing is we're taking a\n\n14\n00:00:58,160 --> 00:01:01,790\nmachine that speaks some\nlow-level language, and we're\n\n15\n00:01:01,790 --> 00:01:05,250\nraising the machine to a\nhigh-level language like Lisp\n\n16\n00:01:05,250 --> 00:01:08,230\nby writing an interpreter.\n\n17\n00:01:08,230 --> 00:01:21,160\nSo for instance, here,\nconceptually, is a special\n\n18\n00:01:21,160 --> 00:01:23,910\npurpose machine for computing\nfactorials.\n\n19\n00:01:23,910 --> 00:01:29,000\nIt takes in five and\nputs out 120.\n\n20\n00:01:29,000 --> 00:01:32,060\nAnd what this special purpose\nmachine is is actually a Lisp\n\n21\n00:01:32,060 --> 00:01:38,410\ninterpreter that's configured\nitself to run factorials,\n\n22\n00:01:38,410 --> 00:01:39,880\nbecause you fit into\nit a description of\n\n23\n00:01:39,880 --> 00:01:42,410\nthe factorial machine.\n\n24\n00:01:42,410 --> 00:01:43,610\nSo that's what an\ninterpreter is.\n\n25\n00:01:43,610 --> 00:01:47,320\nIt configures itself to emulate\na machine whose\n\n26\n00:01:47,320 --> 00:01:50,120\ndescription you read in.\n\n27\n00:01:50,120 --> 00:01:52,110\nNow, inside the Lisp\ninterpreter, what's that?\n\n28\n00:01:52,110 --> 00:01:54,860\nWell, that might be your general\nregister language\n\n29\n00:01:54,860 --> 00:01:59,500\ninterpreter that configures\nitself to behave like a Lisp\n\n30\n00:01:59,500 --> 00:02:01,360\ninterpreter, because you\nput in a whole bunch of\n\n31\n00:02:01,360 --> 00:02:03,410\ninstructions in register\nlanguage.\n\n32\n00:02:03,410 --> 00:02:07,070\nThis is the explicit\ncontrol evaluator.\n\n33\n00:02:07,070 --> 00:02:09,300\nAnd then it also has some sort\nof library, a library of\n\n34\n00:02:09,300 --> 00:02:11,620\nprimitive operators and Lisp\noperations and all sorts of\n\n35\n00:02:11,620 --> 00:02:12,780\nthings like that.\n\n36\n00:02:12,780 --> 00:02:17,350\nThat's the general strategy\nof interpretation.\n\n37\n00:02:17,350 --> 00:02:19,420\nAnd the point is, what we're\ndoing is we're writing an\n\n38\n00:02:19,420 --> 00:02:24,060\ninterpreter to raise the machine\nto the level of the\n\n39\n00:02:24,060 --> 00:02:25,430\nprograms that we\nwant to write.\n\n40\n00:02:25,430 --> 00:02:27,850\nWell, there's another strategy,\na different one,\n\n41\n00:02:27,850 --> 00:02:29,030\nwhich is compilation.\n\n42\n00:02:29,030 --> 00:02:31,090\nCompilation's a little\nbit different.\n\n43\n00:02:31,090 --> 00:02:37,720\nHere--here we might have\nproduced a special purpose\n\n44\n00:02:37,720 --> 00:02:44,430\nmachine for, for computing\nfactorials, starting with some\n\n45\n00:02:44,430 --> 00:02:46,450\nsort of machine that speaks\nregister language, except\n\n46\n00:02:46,450 --> 00:02:47,870\nwe're going to do a different\nstrategy.\n\n47\n00:02:47,870 --> 00:02:51,680\nWe take our factorial program.\n\n48\n00:02:51,680 --> 00:02:53,780\nWe use that as the source\ncode into a compiler.\n\n49\n00:02:53,780 --> 00:02:57,090\nWhat the compiler will do is\ntranslate that factorial\n\n50\n00:02:57,090 --> 00:02:59,926\nprogram into some register\nmachine language.\n\n51\n00:02:59,926 --> 00:03:03,110\nAnd this will now be not the\nexplicit control evaluator for\n\n52\n00:03:03,110 --> 00:03:04,990\nLisp, this will be some\nregister language for\n\n53\n00:03:04,990 --> 00:03:06,760\ncomputing factorials.\n\n54\n00:03:06,760 --> 00:03:10,460\nSo this is the translation\nof that.\n\n55\n00:03:10,460 --> 00:03:14,690\nThat will go into some sort of\nloader which will combine this\n\n56\n00:03:14,690 --> 00:03:17,520\ncode with code selected from the\nlibrary to do things like\n\n57\n00:03:17,520 --> 00:03:19,970\nprimitive multiplication.\n\n58\n00:03:19,970 --> 00:03:23,190\nAnd then we'll produce a load\nmodule which configures the\n\n59\n00:03:23,190 --> 00:03:25,760\nregister language machine\nto be a special\n\n60\n00:03:25,760 --> 00:03:28,320\npurpose factorial machine.\n\n61\n00:03:28,320 --> 00:03:29,905\nSo that's a, that's a\ndifferent strategy.\n\n62\n00:03:29,905 --> 00:03:33,740\nIn interpretation, we're raising\nthe machine to the\n\n63\n00:03:33,740 --> 00:03:35,360\nlevel of our language,\nlike Lisp.\n\n64\n00:03:35,360 --> 00:03:38,580\nIn compilation, we're taking our\nprogram and lowering it to\n\n65\n00:03:38,580 --> 00:03:42,040\nthe language that's spoken\nby the machine.\n\n66\n00:03:42,040 --> 00:03:44,280\nWell, how do these two\nstrategies compare?\n\n67\n00:03:44,280 --> 00:03:48,890\nThe compiler can produce code\nthat will execute more\n\n68\n00:03:48,890 --> 00:03:50,140\nefficiently.\n\n69\n00:03:50,140 --> 00:03:52,490\n\n\n70\n00:03:52,490 --> 00:03:56,820\nThe essential reason for that is\nthat if you think about the\n\n71\n00:03:56,820 --> 00:04:02,870\nregister operations that are\nrunning, the interpreter has\n\n72\n00:04:02,870 --> 00:04:05,880\nto produce register operations\nwhich, in principle, are going\n\n73\n00:04:05,880 --> 00:04:10,260\nto be general enough to execute\nany Lisp procedure.\n\n74\n00:04:10,260 --> 00:04:12,680\nWhereas the compiler only has\nto worry about producing a\n\n75\n00:04:12,680 --> 00:04:16,029\nspecial bunch of register\noperations for, for doing the\n\n76\n00:04:16,029 --> 00:04:20,209\nparticular Lisp procedure\nthat you've compiled.\n\n77\n00:04:20,209 --> 00:04:23,340\nOr another way to say that is\nthat the interpreter is a\n\n78\n00:04:23,340 --> 00:04:26,940\ngeneral purpose simulator, that\nwhen you read in a Lisp\n\n79\n00:04:26,940 --> 00:04:29,820\nprocedure, then those can\nsimulate the program described\n\n80\n00:04:29,820 --> 00:04:31,160\nby that, by that procedure.\n\n81\n00:04:31,160 --> 00:04:33,290\nSo the interpreter is worrying\nabout making a general purpose\n\n82\n00:04:33,290 --> 00:04:36,170\nsimulator, whereas the compiler,\nin effect, is\n\n83\n00:04:36,170 --> 00:04:37,930\nconfiguring the thing to\nbe the machine that the\n\n84\n00:04:37,930 --> 00:04:40,000\ninterpreter would have\nbeen simulating.\n\n85\n00:04:40,000 --> 00:04:41,340\nSo the compiler can be faster.\n\n86\n00:04:41,340 --> 00:04:52,830\n\n\n87\n00:04:52,830 --> 00:04:57,100\nOn the other hand, the\ninterpreter is a nicer\n\n88\n00:04:57,100 --> 00:04:59,340\nenvironment for debugging.\n\n89\n00:04:59,340 --> 00:05:02,200\nAnd the reason for that is that\nwe've got the source code\n\n90\n00:05:02,200 --> 00:05:02,960\nactually there.\n\n91\n00:05:02,960 --> 00:05:03,740\nWe're interpreting it.\n\n92\n00:05:03,740 --> 00:05:06,010\nThat's what we're\nworking with.\n\n93\n00:05:06,010 --> 00:05:07,880\nAnd we also have the\nlibrary around.\n\n94\n00:05:07,880 --> 00:05:10,150\nSee, the interpreter--the\nlibrary sitting there is part\n\n95\n00:05:10,150 --> 00:05:11,140\nof the interpreter.\n\n96\n00:05:11,140 --> 00:05:13,660\nThe compiler only pulls out from\nthe library what it needs\n\n97\n00:05:13,660 --> 00:05:14,830\nto run the program.\n\n98\n00:05:14,830 --> 00:05:18,710\nSo if you're in the middle of\ndebugging, and you might like\n\n99\n00:05:18,710 --> 00:05:21,730\nto write a little extra program\nto examine some run\n\n100\n00:05:21,730 --> 00:05:24,450\ntime data structure or to\nproduce some computation that\n\n101\n00:05:24,450 --> 00:05:25,990\nyou didn't think of when you\nwrote the program, the\n\n102\n00:05:25,990 --> 00:05:28,390\ninterpreter can do that\nperfectly well, whereas the\n\n103\n00:05:28,390 --> 00:05:29,670\ncompiler can't.\n\n104\n00:05:29,670 --> 00:05:31,850\nSo there are sort of dual,\ndual advantages.\n\n105\n00:05:31,850 --> 00:05:34,720\nThe compiler will produce code\nthat executes faster.\n\n106\n00:05:34,720 --> 00:05:39,030\nThe interpreter is a better\nenvironment for debugging.\n\n107\n00:05:39,030 --> 00:05:43,520\nAnd most Lisp systems end up\nhaving both, end up being\n\n108\n00:05:43,520 --> 00:05:45,860\nconfigured so you have an\ninterpreter that you use when\n\n109\n00:05:45,860 --> 00:05:46,930\nyou're developing your code.\n\n110\n00:05:46,930 --> 00:05:49,060\nThen you can speed it\nup by compiling.\n\n111\n00:05:49,060 --> 00:05:51,720\nAnd very often, you can arrange\nthat compiled code and\n\n112\n00:05:51,720 --> 00:05:54,810\ninterpreted code can\ncall each other.\n\n113\n00:05:54,810 --> 00:05:55,700\nWe'll see how to do that.\n\n114\n00:05:55,700 --> 00:05:56,950\nThat's not hard.\n\n115\n00:05:56,950 --> 00:06:01,040\n\n\n116\n00:06:01,040 --> 00:06:02,290\nIn fact, the way we'll--\n\n117\n00:06:02,290 --> 00:06:04,390\n\n\n118\n00:06:04,390 --> 00:06:06,580\nin the compiler we're going to\nmake, the way we'll arrange\n\n119\n00:06:06,580 --> 00:06:08,952\nfor compiled coding and\ninterpreted code to call, to\n\n120\n00:06:08,952 --> 00:06:12,220\ncall each other, is that we'll\nhave the compiler use exactly\n\n121\n00:06:12,220 --> 00:06:14,320\nthe same register conventions\nas the interpreter.\n\n122\n00:06:14,320 --> 00:06:18,680\n\n\n123\n00:06:18,680 --> 00:06:23,900\nWell, the idea of a compiler is\nvery much like the idea of\n\n124\n00:06:23,900 --> 00:06:25,490\nan interpreter or evaluator.\n\n125\n00:06:25,490 --> 00:06:27,070\nIt's the same thing.\n\n126\n00:06:27,070 --> 00:06:31,460\nSee, the evaluator walks over\nthe code and performs some\n\n127\n00:06:31,460 --> 00:06:33,840\nregister operations.\n\n128\n00:06:33,840 --> 00:06:37,040\nThat's what we did yesterday.\n\n129\n00:06:37,040 --> 00:06:39,700\nWell, the compiler essentially\nwould like to walk over the\n\n130\n00:06:39,700 --> 00:06:44,000\ncode and produce the register\noperations that the evaluator\n\n131\n00:06:44,000 --> 00:06:48,890\nwould have done were it\nevaluating the thing.\n\n132\n00:06:48,890 --> 00:06:52,000\nAnd that gives us a model\nfor how to implement a\n\n133\n00:06:52,000 --> 00:06:57,150\nzeroth-order compiler, a\nvery bad compiler but\n\n134\n00:06:57,150 --> 00:06:58,330\nessentially a compiler.\n\n135\n00:06:58,330 --> 00:07:00,900\nA model for doing that is you\njust take the evaluator, you\n\n136\n00:07:00,900 --> 00:07:04,970\nrun it over the code, but\ninstead of executing the\n\n137\n00:07:04,970 --> 00:07:07,550\nactual operations, you\njust save them away.\n\n138\n00:07:07,550 --> 00:07:08,820\nAnd that's your compiled code.\n\n139\n00:07:08,820 --> 00:07:10,140\nSo let me give you an\nexample of that.\n\n140\n00:07:10,140 --> 00:07:15,130\n\n\n141\n00:07:15,130 --> 00:07:15,770\nSuppose we're going to\ncompile--suppose we want to\n\n142\n00:07:15,770 --> 00:07:18,010\ncompile the expression f of x.\n\n143\n00:07:18,010 --> 00:07:25,100\n\n\n144\n00:07:25,100 --> 00:07:28,175\nSo let's assume that we've got\nf of x in the x register and\n\n145\n00:07:28,175 --> 00:07:30,170\nsomething in the environment\nregister.\n\n146\n00:07:30,170 --> 00:07:31,745\nAnd now imagine starting\nup the evaluator.\n\n147\n00:07:31,745 --> 00:07:34,560\n\n\n148\n00:07:34,560 --> 00:07:36,370\nWell, it looks at the expression\nand it sees that\n\n149\n00:07:36,370 --> 00:07:38,000\nit's an application.\n\n150\n00:07:38,000 --> 00:07:43,730\nAnd it branches to a place in\nthe evaluator code we saw\n\n151\n00:07:43,730 --> 00:07:44,980\ncalled ev-application.\n\n152\n00:07:44,980 --> 00:07:47,230\n\n\n153\n00:07:47,230 --> 00:07:48,190\nAnd then it begins.\n\n154\n00:07:48,190 --> 00:07:50,560\nIt stores away the operands and\nunev, and then it's going\n\n155\n00:07:50,560 --> 00:07:53,030\nto put the operator in exp,\nand it's going to go\n\n156\n00:07:53,030 --> 00:07:54,410\nrecursively evaluate it.\n\n157\n00:07:54,410 --> 00:07:56,385\nThat's the process that\nwe walk through.\n\n158\n00:07:56,385 --> 00:07:58,360\nAnd if you start looking at\nthe code, you start seeing\n\n159\n00:07:58,360 --> 00:08:00,200\nsome register operations.\n\n160\n00:08:00,200 --> 00:08:03,370\nYou see assign to unev the\noperands, assign to exp the\n\n161\n00:08:03,370 --> 00:08:05,520\noperator, save the environment,\ngenerate\n\n162\n00:08:05,520 --> 00:08:06,770\nthat, and so on.\n\n163\n00:08:06,770 --> 00:08:10,310\n\n\n164\n00:08:10,310 --> 00:08:16,220\nWell, if we look on the overhead\nhere, we can see, we\n\n165\n00:08:16,220 --> 00:08:20,860\ncan see those operations\nstarting to be produced.\n\n166\n00:08:20,860 --> 00:08:24,130\nHere's sort of the first real\noperation that the evaluator\n\n167\n00:08:24,130 --> 00:08:24,910\nwould have done.\n\n168\n00:08:24,910 --> 00:08:27,980\nIt pulls the operands out of the\nexp register and assigns\n\n169\n00:08:27,980 --> 00:08:31,340\nit to unev. And then it assigns\nsomething to the\n\n170\n00:08:31,340 --> 00:08:34,240\nexpression register, and it\nsaves continue, and it saves\n\n171\n00:08:34,240 --> 00:08:34,740\nenv.\n\n172\n00:08:34,740 --> 00:08:38,049\nAnd all I'm doing here is\nwriting down the register\n\n173\n00:08:38,049 --> 00:08:41,130\nassignments that the evaluator\nwould have done in\n\n174\n00:08:41,130 --> 00:08:42,010\nexecuting that code.\n\n175\n00:08:42,010 --> 00:08:44,280\nAnd can zoom out a little bit.\n\n176\n00:08:44,280 --> 00:08:49,430\nAltogether, there are about\n19 operations there.\n\n177\n00:08:49,430 --> 00:08:52,650\nAnd this is the--this will be\nthe piece of code up until the\n\n178\n00:08:52,650 --> 00:08:56,230\npoint where the evaluator\nbranches off to\n\n179\n00:08:56,230 --> 00:08:57,940\napply-dispatch.\n\n180\n00:08:57,940 --> 00:09:00,110\nAnd in fact, in this compiler,\nwe're not going to worry about\n\n181\n00:09:00,110 --> 00:09:01,450\napply-dispatch at all.\n\n182\n00:09:01,450 --> 00:09:02,672\nWe're going to have\neverything--we're going to\n\n183\n00:09:02,672 --> 00:09:06,160\nhave both interpreted code\nand compiled code.\n\n184\n00:09:06,160 --> 00:09:08,670\nAlways evaluate procedures,\nalways apply procedures by\n\n185\n00:09:08,670 --> 00:09:10,240\ngoing to apply-dispatch.\n\n186\n00:09:10,240 --> 00:09:12,720\nThat will easily allow\ninterpreted code and compiled\n\n187\n00:09:12,720 --> 00:09:13,970\ncode to call each other.\n\n188\n00:09:13,970 --> 00:09:18,330\n\n\n189\n00:09:18,330 --> 00:09:21,220\nWell, in principle, that's\nall we need to do.\n\n190\n00:09:21,220 --> 00:09:22,620\nYou just run the evaluator.\n\n191\n00:09:22,620 --> 00:09:24,320\nSo the compiler's a lot\nlike the evaluator.\n\n192\n00:09:24,320 --> 00:09:26,890\nYou run it, except it stashes\naway these operations instead\n\n193\n00:09:26,890 --> 00:09:29,480\nof actually executing them.\n\n194\n00:09:29,480 --> 00:09:32,680\nWell, that's not, that's\nnot quite true.\n\n195\n00:09:32,680 --> 00:09:36,370\nThere's only one little\nlie in that.\n\n196\n00:09:36,370 --> 00:09:40,480\nWhat you have to worry about is\nif you have a, a predicate.\n\n197\n00:09:40,480 --> 00:09:44,200\nIf you have some kind of test\nyou want to do, obviously, at\n\n198\n00:09:44,200 --> 00:09:47,000\nthe point when you're compiling\nit, you don't know\n\n199\n00:09:47,000 --> 00:09:49,490\nwhich branch of these--of a\nconditional like this you're\n\n200\n00:09:49,490 --> 00:09:51,400\ngoing to do.\n\n201\n00:09:51,400 --> 00:09:55,010\nSo you can't say which one the\nevaluator would have done.\n\n202\n00:09:55,010 --> 00:09:57,190\nSo all you do there\nis very simple.\n\n203\n00:09:57,190 --> 00:09:58,985\nYou compile both branches.\n\n204\n00:09:58,985 --> 00:10:02,050\nSo you compile a structure\nthat looks like this.\n\n205\n00:10:02,050 --> 00:10:08,430\nThat'll compile into something\nthat says, the code, the code\n\n206\n00:10:08,430 --> 00:10:18,140\nfor P. And it puts its results\nin, say, the val register.\n\n207\n00:10:18,140 --> 00:10:21,680\nSo you walk the interpreter over\nthe predicate and make\n\n208\n00:10:21,680 --> 00:10:24,770\nsure that the result would\ngo into the val register.\n\n209\n00:10:24,770 --> 00:10:30,790\nAnd then you compile an\ninstruction that says, branch\n\n210\n00:10:30,790 --> 00:10:38,670\nif, if val is true, to a place\nwe'll call label one.\n\n211\n00:10:38,670 --> 00:10:44,950\n\n\n212\n00:10:44,950 --> 00:10:49,792\nThen we, we will put the\ncode for B to walk the\n\n213\n00:10:49,792 --> 00:10:54,040\ninterpreter--walk the\ninterpreter over B. And then\n\n214\n00:10:54,040 --> 00:10:58,070\ngo to put in an instruction\nthat says, go to the next\n\n215\n00:10:58,070 --> 00:11:03,820\nthing, whatever, whatever was\nsupposed to happen after this\n\n216\n00:11:03,820 --> 00:11:04,920\nthing was done.\n\n217\n00:11:04,920 --> 00:11:06,900\nYou put in that instruction.\n\n218\n00:11:06,900 --> 00:11:08,280\nAnd here you put label one.\n\n219\n00:11:08,280 --> 00:11:11,521\n\n\n220\n00:11:11,521 --> 00:11:19,860\nAnd here you put the\ncode for A. And you\n\n221\n00:11:19,860 --> 00:11:25,870\nput go to next thing.\n\n222\n00:11:25,870 --> 00:11:31,420\n\n\n223\n00:11:31,420 --> 00:11:33,090\nSo that's how you treat\na conditional.\n\n224\n00:11:33,090 --> 00:11:35,890\nYou generate a little\nblock like that.\n\n225\n00:11:35,890 --> 00:11:40,550\nAnd other than that, this\nzeroth-order compiler is the\n\n226\n00:11:40,550 --> 00:11:42,310\nsame as the evaluator.\n\n227\n00:11:42,310 --> 00:11:44,380\nIt's just stashing away the\ninstructions instead of\n\n228\n00:11:44,380 --> 00:11:46,380\nexecuting them.\n\n229\n00:11:46,380 --> 00:11:48,140\nThat seems pretty simple,\nbut we've gained\n\n230\n00:11:48,140 --> 00:11:50,120\nsomething by that.\n\n231\n00:11:50,120 --> 00:11:51,360\nSee, already that's\ngoing to be more\n\n232\n00:11:51,360 --> 00:11:53,630\nefficient than the evaluator.\n\n233\n00:11:53,630 --> 00:11:58,030\nBecause, if you watch the\nevaluator run, it's not only\n\n234\n00:11:58,030 --> 00:12:01,410\ngenerating the register\noperations we wrote down, it's\n\n235\n00:12:01,410 --> 00:12:04,740\nalso doing things to decide\nwhich ones to generate.\n\n236\n00:12:04,740 --> 00:12:08,480\nSo the very first thing it does,\nsay, here for instance,\n\n237\n00:12:08,480 --> 00:12:13,470\nis go do some tests and decide\nthat this is an application,\n\n238\n00:12:13,470 --> 00:12:15,930\nand then branch off to the\nplace that, that handles\n\n239\n00:12:15,930 --> 00:12:16,780\napplications.\n\n240\n00:12:16,780 --> 00:12:18,870\nIn other words, what the\nevaluator's doing is\n\n241\n00:12:18,870 --> 00:12:23,720\nsimultaneously analyzing the\ncode to see what to do, and\n\n242\n00:12:23,720 --> 00:12:25,580\nrunning these operations.\n\n243\n00:12:25,580 --> 00:12:25,960\nAnd when you--\n\n244\n00:12:25,960 --> 00:12:28,960\nif you run the evaluator a\nmillion times, that analysis\n\n245\n00:12:28,960 --> 00:12:31,870\nphase happens a million times,\nwhereas in the compiler, it's\n\n246\n00:12:31,870 --> 00:12:33,650\nhappened once, and then you\njust have the register\n\n247\n00:12:33,650 --> 00:12:34,900\noperations themselves.\n\n248\n00:12:34,900 --> 00:12:39,730\n\n\n249\n00:12:39,730 --> 00:12:42,310\nOk, that's a, a zeroth-order\ncompiler, but it is a\n\n250\n00:12:42,310 --> 00:12:44,550\nwretched, wretched compiler.\n\n251\n00:12:44,550 --> 00:12:47,200\nIt's really dumb.\n\n252\n00:12:47,200 --> 00:12:52,040\nLet's--let's go back and, and\nlook at this overhead.\n\n253\n00:12:52,040 --> 00:12:54,170\nSo look at look at some\nof the operations\n\n254\n00:12:54,170 --> 00:12:56,020\nthis thing is doing.\n\n255\n00:12:56,020 --> 00:13:01,030\nWe're supposedly looking\nat the operations and\n\n256\n00:13:01,030 --> 00:13:03,710\ninterpreting f of x.\n\n257\n00:13:03,710 --> 00:13:05,220\nNow, look here what\nit's doing.\n\n258\n00:13:05,220 --> 00:13:10,360\nFor example, here it\nassigns to exp the\n\n259\n00:13:10,360 --> 00:13:13,850\noperator in fetch of exp.\n\n260\n00:13:13,850 --> 00:13:16,290\nBut see, there's no reason to\ndo that, because this is--\n\n261\n00:13:16,290 --> 00:13:21,290\nthe compiler knows that the\noperator, fetch of exp, is f\n\n262\n00:13:21,290 --> 00:13:23,310\nright here.\n\n263\n00:13:23,310 --> 00:13:25,850\nSo there's no reason why this\ninstruction should say that.\n\n264\n00:13:25,850 --> 00:13:29,580\nIt should say, we'll\nassign to exp, f.\n\n265\n00:13:29,580 --> 00:13:32,000\nOr in fact, you don't\nneed exp at all.\n\n266\n00:13:32,000 --> 00:13:33,670\nThere's no reason it should\nhave exp at all.\n\n267\n00:13:33,670 --> 00:13:35,170\nWhat, what did exp\nget used for?\n\n268\n00:13:35,170 --> 00:13:43,190\nWell, if we come down here,\nwe're going to assign to val,\n\n269\n00:13:43,190 --> 00:13:48,620\nlook up the stuff in exp\nin the environment.\n\n270\n00:13:48,620 --> 00:13:50,800\nSo what we really should do is\nget rid of the exp register\n\n271\n00:13:50,800 --> 00:13:53,290\naltogether, and just change\nthis instruction to say,\n\n272\n00:13:53,290 --> 00:13:57,600\nassign to val, look up the\nvariable value of the symbol f\n\n273\n00:13:57,600 --> 00:13:58,850\nin the environment.\n\n274\n00:13:58,850 --> 00:14:01,100\n\n\n275\n00:14:01,100 --> 00:14:04,800\nSimilarly, back up here, we\ndon't need unev at all,\n\n276\n00:14:04,800 --> 00:14:08,260\nbecause we know what the\noperands of fetch of exp are\n\n277\n00:14:08,260 --> 00:14:09,150\nfor this piece of code.\n\n278\n00:14:09,150 --> 00:14:10,630\nIt's the, it's the list x.\n\n279\n00:14:10,630 --> 00:14:13,270\n\n\n280\n00:14:13,270 --> 00:14:19,660\nSo in some sense, you don't\nwant unev and exp at all.\n\n281\n00:14:19,660 --> 00:14:22,690\nSee, what they really are in\nsome sense, those aren't\n\n282\n00:14:22,690 --> 00:14:24,330\nregisters of the actual machine\n\n283\n00:14:24,330 --> 00:14:25,230\nthat's supposed to run.\n\n284\n00:14:25,230 --> 00:14:28,180\nThose are registers that have to\ndo with arranging the thing\n\n285\n00:14:28,180 --> 00:14:30,760\nthat can simulate\nthat machine.\n\n286\n00:14:30,760 --> 00:14:34,890\nSo they're always going to hold\nexpressions which, from\n\n287\n00:14:34,890 --> 00:14:37,330\nthe compiler's point of view,\nare just constants, so can be\n\n288\n00:14:37,330 --> 00:14:39,510\nput right into the code.\n\n289\n00:14:39,510 --> 00:14:41,850\nSo you can forget about all the\noperations worrying about\n\n290\n00:14:41,850 --> 00:14:44,000\nexp and unev and just\nuse those constants.\n\n291\n00:14:44,000 --> 00:14:48,200\nSimilarly, again, if we go, go\nback and look here, there are\n\n292\n00:14:48,200 --> 00:14:50,510\nthings like assign to\ncontinue eval-args.\n\n293\n00:14:50,510 --> 00:14:53,890\n\n\n294\n00:14:53,890 --> 00:14:55,440\nNow, that has nothing\nto do with anything.\n\n295\n00:14:55,440 --> 00:14:59,280\nThat was just the evaluator\nkeeping track of where it\n\n296\n00:14:59,280 --> 00:15:05,150\nshould go next, to evaluate the\narguments in some, in some\n\n297\n00:15:05,150 --> 00:15:06,920\napplication.\n\n298\n00:15:06,920 --> 00:15:08,690\nBut of course, that's irrelevant\nto the compiler,\n\n299\n00:15:08,690 --> 00:15:09,940\nbecause you--\n\n300\n00:15:09,940 --> 00:15:11,470\n\n\n301\n00:15:11,470 --> 00:15:15,220\nthe analysis phase will have\nalready done that.\n\n302\n00:15:15,220 --> 00:15:17,680\nSo this is completely\nirrelevant.\n\n303\n00:15:17,680 --> 00:15:20,170\nSo a lot of these, these\nassignments to continue have\n\n304\n00:15:20,170 --> 00:15:24,070\nnot to do where the running\nmachine is supposed to\n\n305\n00:15:24,070 --> 00:15:26,120\ncontinue in keeping track\nof its state.\n\n306\n00:15:26,120 --> 00:15:28,380\nIt has to, to do with where the\nevaluator analysis should\n\n307\n00:15:28,380 --> 00:15:30,080\ncontinue, and those are\ncompletely irrelevant.\n\n308\n00:15:30,080 --> 00:15:31,330\nSo we can get rid of them.\n\n309\n00:15:31,330 --> 00:15:44,330\n\n\n310\n00:15:44,330 --> 00:15:46,990\nOk, well, if we, if we simply\ndo that, make those kinds of\n\n311\n00:15:46,990 --> 00:15:51,380\noptimizations, get rid, get rid\nof worrying about exp and\n\n312\n00:15:51,380 --> 00:15:55,030\nunev, and get rid of these\nirrelevant register\n\n313\n00:15:55,030 --> 00:16:01,400\nassignments to continue, then we\ncan take this literal code,\n\n314\n00:16:01,400 --> 00:16:05,370\nthese sort of 19 instructions\nthat the, that the evaluator\n\n315\n00:16:05,370 --> 00:16:08,540\nwould have done, and\nthen replace them.\n\n316\n00:16:08,540 --> 00:16:09,865\nLet's look at the,\nat the slide.\n\n317\n00:16:09,865 --> 00:16:13,490\n\n\n318\n00:16:13,490 --> 00:16:15,180\nReplace them by--we get rid\nof about half of them.\n\n319\n00:16:15,180 --> 00:16:18,370\n\n\n320\n00:16:18,370 --> 00:16:21,470\nAnd again, this is just sort\nof filtering what the\n\n321\n00:16:21,470 --> 00:16:23,410\nevaluator would have done\nby getting rid of\n\n322\n00:16:23,410 --> 00:16:25,200\nthe irrelevant stuff.\n\n323\n00:16:25,200 --> 00:16:29,450\nAnd you see, for instance, here\nthe--where the evaluator\n\n324\n00:16:29,450 --> 00:16:32,570\nsaid, assign val, look up\nvariable value, fetch of exp,\n\n325\n00:16:32,570 --> 00:16:35,470\nhere we have put in\nthe constant f.\n\n326\n00:16:35,470 --> 00:16:37,020\nHere we've put in\nthe constant x.\n\n327\n00:16:37,020 --> 00:16:39,770\n\n\n328\n00:16:39,770 --> 00:16:43,860\nSo there's a, there's a little\nbetter compiler.\n\n329\n00:16:43,860 --> 00:16:47,930\nIt's still pretty dumb.\n\n330\n00:16:47,930 --> 00:16:50,560\nIt's still doing a lot\nof dumb things.\n\n331\n00:16:50,560 --> 00:16:53,290\nAgain, if we go look at the\nslide again, look at the very\n\n332\n00:16:53,290 --> 00:17:00,150\nbeginning here, we see a save\nthe environment, assign\n\n333\n00:17:00,150 --> 00:17:03,430\nsomething to the val register,\nand restore the environment.\n\n334\n00:17:03,430 --> 00:17:05,030\nWhere'd that come from?\n\n335\n00:17:05,030 --> 00:17:08,200\nThat came from the evaluator\nback here saying, oh, I'm in\n\n336\n00:17:08,200 --> 00:17:11,160\nthe middle of evaluating\nan application.\n\n337\n00:17:11,160 --> 00:17:15,940\nSo I'm going to recursively\ncall eval dispatch.\n\n338\n00:17:15,940 --> 00:17:18,170\nSo I'd better save the thing I'm\ngoing to need later, which\n\n339\n00:17:18,170 --> 00:17:19,849\nis the environment.\n\n340\n00:17:19,849 --> 00:17:21,609\nThis was the result\nof recursively\n\n341\n00:17:21,609 --> 00:17:23,520\ncalling eval dispatch.\n\n342\n00:17:23,520 --> 00:17:26,540\nIt was evaluating the symbol\nf in that case.\n\n343\n00:17:26,540 --> 00:17:28,900\nThen it came back from eval\ndispatch, restored the\n\n344\n00:17:28,900 --> 00:17:31,380\nenvironment.\n\n345\n00:17:31,380 --> 00:17:35,290\nBut in fact, the actual thing\nit ended up doing in the\n\n346\n00:17:35,290 --> 00:17:38,740\nevaluation is not going to hurt\nthe environment at all.\n\n347\n00:17:38,740 --> 00:17:40,890\nSo there's no reason to be\nsaving the environment and\n\n348\n00:17:40,890 --> 00:17:42,170\nrestoring the environment\nhere.\n\n349\n00:17:42,170 --> 00:17:46,020\n\n\n350\n00:17:46,020 --> 00:17:53,690\nSimilarly, here I'm saving the\nargument list. That's a piece\n\n351\n00:17:53,690 --> 00:17:56,560\nof the argument evaluation\nloop, saving the argument\n\n352\n00:17:56,560 --> 00:17:58,090\nlist, and here you restore it.\n\n353\n00:17:58,090 --> 00:18:01,510\nBut the actual thing that you\nended up doing didn't trash\n\n354\n00:18:01,510 --> 00:18:04,090\nthe argument list. So there\nwas no reason to save it.\n\n355\n00:18:04,090 --> 00:18:08,690\n\n\n356\n00:18:08,690 --> 00:18:14,415\nSo another way to say, another\nway to say that is that the,\n\n357\n00:18:14,415 --> 00:18:19,923\nthe evaluator has to be\nmaximally pessimistic, because\n\n358\n00:18:19,923 --> 00:18:22,050\nas far from its point of view\nit's just going off to\n\n359\n00:18:22,050 --> 00:18:23,180\nevaluate something.\n\n360\n00:18:23,180 --> 00:18:26,200\nSo it better save what it's\ngoing to need later.\n\n361\n00:18:26,200 --> 00:18:28,700\nBut once you've done the\nanalysis, the compiler is in a\n\n362\n00:18:28,700 --> 00:18:32,140\nposition to say, well, what\nactually did I need to save?\n\n363\n00:18:32,140 --> 00:18:35,410\nAnd doesn't need to do any--\nit doesn't need to be as\n\n364\n00:18:35,410 --> 00:18:38,060\ncareful as the evaluator,\nbecause it knows what it\n\n365\n00:18:38,060 --> 00:18:39,950\nactually needs.\n\n366\n00:18:39,950 --> 00:18:44,240\nWell, in any case, if we do that\nand eliminate all those\n\n367\n00:18:44,240 --> 00:18:48,110\nredundant saves and restores,\nthen we can\n\n368\n00:18:48,110 --> 00:18:49,400\nget it down to this.\n\n369\n00:18:49,400 --> 00:18:52,810\nAnd you see there are actually\nonly three instructions that\n\n370\n00:18:52,810 --> 00:18:56,230\nwe actually need, down from the\ninitial 11 or so, or the\n\n371\n00:18:56,230 --> 00:19:00,070\ninitial 20 or so in\nthe original one.\n\n372\n00:19:00,070 --> 00:19:03,260\nAnd that's just saying, of those\nregister operations,\n\n373\n00:19:03,260 --> 00:19:04,870\nwhich ones did we\nactually need?\n\n374\n00:19:04,870 --> 00:19:09,490\n\n\n375\n00:19:09,490 --> 00:19:11,950\nLet me just sort of summarize\nthat in another way, just to\n\n376\n00:19:11,950 --> 00:19:13,450\nshow you in a little\nbetter picture.\n\n377\n00:19:13,450 --> 00:19:16,010\n\n\n378\n00:19:16,010 --> 00:19:18,690\nHere's a picture of starting--\n\n379\n00:19:18,690 --> 00:19:20,530\nThis is looking at all the\nsaves and restores.\n\n380\n00:19:20,530 --> 00:19:23,770\n\n\n381\n00:19:23,770 --> 00:19:26,300\nSo here's the expression, f\nof x, and then this traces\n\n382\n00:19:26,300 --> 00:19:30,940\nthrough, on the bottom here,\nthe various places in the\n\n383\n00:19:30,940 --> 00:19:38,160\nevaluator that were passed when\nthe evaluation happened.\n\n384\n00:19:38,160 --> 00:19:40,250\nAnd then here, here\nyou see arrows.\n\n385\n00:19:40,250 --> 00:19:42,320\nArrow down means\nregister saved.\n\n386\n00:19:42,320 --> 00:19:43,690\nSo the first thing that\nhappened is the\n\n387\n00:19:43,690 --> 00:19:46,860\nenvironment got saved.\n\n388\n00:19:46,860 --> 00:19:48,305\nAnd over here, the environment\ngot restored.\n\n389\n00:19:48,305 --> 00:19:52,380\n\n\n390\n00:19:52,380 --> 00:19:56,220\nAnd these-- so there are all the\npairs of stack operations.\n\n391\n00:19:56,220 --> 00:19:59,462\nNow, if you go ahead and say,\nwell, let's remember that we\n\n392\n00:19:59,462 --> 00:20:02,070\ndon't--that unev, for instance,\nis a completely\n\n393\n00:20:02,070 --> 00:20:03,320\nuseless register.\n\n394\n00:20:03,320 --> 00:20:07,550\n\n\n395\n00:20:07,550 --> 00:20:09,820\nAnd if we use the constant\nstructure of the code, well,\n\n396\n00:20:09,820 --> 00:20:11,770\nwe don't need, we don't need\nto save unev. We don't need\n\n397\n00:20:11,770 --> 00:20:13,020\nunev at all.\n\n398\n00:20:13,020 --> 00:20:16,220\n\n\n399\n00:20:16,220 --> 00:20:18,790\nAnd then, depending on how we\nset up the discipline of\n\n400\n00:20:18,790 --> 00:20:22,610\nthe--of calling other things\nthat apply, we may or may not\n\n401\n00:20:22,610 --> 00:20:23,860\nneed to save continue.\n\n402\n00:20:23,860 --> 00:20:27,360\n\n\n403\n00:20:27,360 --> 00:20:28,800\nThat's the first step I did.\n\n404\n00:20:28,800 --> 00:20:30,116\nAnd then we can look and see\nwhat's actually, what's\n\n405\n00:20:30,116 --> 00:20:32,960\nactually needed.\n\n406\n00:20:32,960 --> 00:20:36,300\nSee, we don't-- didn't really\nneed to save env or\n\n407\n00:20:36,300 --> 00:20:38,536\ncross-evaluating f, because\nit wouldn't, it\n\n408\n00:20:38,536 --> 00:20:40,040\nwouldn't trash it.\n\n409\n00:20:40,040 --> 00:20:46,720\nSo if we take advantage of that,\nand see the evaluation\n\n410\n00:20:46,720 --> 00:20:52,280\nof f here, doesn't really need\nto worry about, about hurting\n\n411\n00:20:52,280 --> 00:20:57,560\nenv. And similarly, the\nevaluation of x here, when the\n\n412\n00:20:57,560 --> 00:21:00,140\nevaluator did that it said, oh,\nI'd better preserve the\n\n413\n00:21:00,140 --> 00:21:03,320\nfunction register around that,\nbecause I might need it later.\n\n414\n00:21:03,320 --> 00:21:07,140\nAnd I better preserve\nthe argument list.\n\n415\n00:21:07,140 --> 00:21:09,280\nWhereas the compiler is now in\na position to know, well, we\n\n416\n00:21:09,280 --> 00:21:10,690\ndidn't really need\nto save-- to do\n\n417\n00:21:10,690 --> 00:21:12,730\nthose saves and restores.\n\n418\n00:21:12,730 --> 00:21:15,520\nSo in fact, all of the stack\noperations done by the\n\n419\n00:21:15,520 --> 00:21:18,900\nevaluator turned out to be\nunnecessary or overly\n\n420\n00:21:18,900 --> 00:21:19,670\npessimistic.\n\n421\n00:21:19,670 --> 00:21:21,390\nAnd the compiler is in a\nposition to know that.\n\n422\n00:21:21,390 --> 00:21:27,470\n\n\n423\n00:21:27,470 --> 00:21:29,980\nWell that's the basic idea.\n\n424\n00:21:29,980 --> 00:21:32,600\nWe take the evaluator, we\neliminate the things that you\n\n425\n00:21:32,600 --> 00:21:34,450\ndon't need, that in some sense\nhave nothing to do with the\n\n426\n00:21:34,450 --> 00:21:38,480\ncompiler at all, just the\nevaluator, and then you see\n\n427\n00:21:38,480 --> 00:21:40,460\nwhich stack operations\nare unnecessary.\n\n428\n00:21:40,460 --> 00:21:44,490\nThat's the basic structure of\nthe compiler that's described\n\n429\n00:21:44,490 --> 00:21:45,130\nin the book.\n\n430\n00:21:45,130 --> 00:21:48,620\nLet me just show you\nhow that examples a\n\n431\n00:21:48,620 --> 00:21:51,280\nlittle bit too simple.\n\n432\n00:21:51,280 --> 00:21:53,500\nTo see how you, how you actually\nsave a lot, let's\n\n433\n00:21:53,500 --> 00:21:55,765\nlook at a little bit more\ncomplicated expression.\n\n434\n00:21:55,765 --> 00:21:58,330\n\n\n435\n00:21:58,330 --> 00:22:03,542\nF of G of X and 1.\n\n436\n00:22:03,542 --> 00:22:06,410\nAnd I'm not going to go\nthrough all the code.\n\n437\n00:22:06,410 --> 00:22:09,830\nThere's a, there's a\nfair pile of it.\n\n438\n00:22:09,830 --> 00:22:13,410\nI think there are, there are\nsomething like 16 pairs of\n\n439\n00:22:13,410 --> 00:22:15,440\nregister saves and restores\nas the evaluator\n\n440\n00:22:15,440 --> 00:22:17,270\nwalks through that.\n\n441\n00:22:17,270 --> 00:22:20,680\nHere's a diagram of them.\n\n442\n00:22:20,680 --> 00:22:21,060\nLet's see.\n\n443\n00:22:21,060 --> 00:22:24,210\nYou see what's going on.\n\n444\n00:22:24,210 --> 00:22:25,530\nYou start out by--the evaluator\nsays, oh, I'm about\n\n445\n00:22:25,530 --> 00:22:26,480\nto do an application.\n\n446\n00:22:26,480 --> 00:22:28,010\nI'll preserve the environment.\n\n447\n00:22:28,010 --> 00:22:30,261\nI'll restore it here.\n\n448\n00:22:30,261 --> 00:22:33,900\nThen I'm about to do\nthe first operand.\n\n449\n00:22:33,900 --> 00:22:36,790\n\n\n450\n00:22:36,790 --> 00:22:38,970\nHere it recursively goes\nto the evaluator.\n\n451\n00:22:38,970 --> 00:22:41,370\nThe evaluator says, oh, this is\nan application, I'll save\n\n452\n00:22:41,370 --> 00:22:44,090\nthe environment, do the operator\nof that combination,\n\n453\n00:22:44,090 --> 00:22:46,740\nrestore it here.\n\n454\n00:22:46,740 --> 00:22:51,720\nThis save--this restore matches\nthat save. And so on.\n\n455\n00:22:51,720 --> 00:22:53,740\nThere's unev here, which turns\nout to be completely\n\n456\n00:22:53,740 --> 00:22:57,240\nunnecessary, continues getting\nbumped around here.\n\n457\n00:22:57,240 --> 00:23:01,040\nThe function register is\ngetting, getting saved across\n\n458\n00:23:01,040 --> 00:23:05,330\nthe first operands, across\nthe operands.\n\n459\n00:23:05,330 --> 00:23:06,680\nAll sorts of things\nare going on.\n\n460\n00:23:06,680 --> 00:23:09,090\nBut if you say, well, what of\nthose really were the business\n\n461\n00:23:09,090 --> 00:23:12,770\nof the compiler as opposed to\nthe evaluator, you get rid of\n\n462\n00:23:12,770 --> 00:23:14,320\na whole bunch.\n\n463\n00:23:14,320 --> 00:23:19,500\nAnd then on top of that, if\nyou say things like, the\n\n464\n00:23:19,500 --> 00:23:24,520\nevaluation of F doesn't hurt the\nenvironment register, or\n\n465\n00:23:24,520 --> 00:23:30,500\nsimply looking up the symbol X,\nyou don't have to protect\n\n466\n00:23:30,500 --> 00:23:34,570\nthe function register\nagainst that.\n\n467\n00:23:34,570 --> 00:23:36,044\nSo you come down to just\na couple of, a\n\n468\n00:23:36,044 --> 00:23:37,530\ncouple of pairs here.\n\n469\n00:23:37,530 --> 00:23:40,280\n\n\n470\n00:23:40,280 --> 00:23:42,160\nAnd still, you can do\na little better.\n\n471\n00:23:42,160 --> 00:23:44,962\nLook what's going on here with\nthe environment register.\n\n472\n00:23:44,962 --> 00:23:51,350\nThe environment register comes\nalong and says, oh, here's a\n\n473\n00:23:51,350 --> 00:23:52,600\ncombination.\n\n474\n00:23:52,600 --> 00:23:54,280\n\n\n475\n00:23:54,280 --> 00:23:58,580\nThis evaluator, by the way,\ndoesn't know anything about G.\n\n476\n00:23:58,580 --> 00:24:02,330\nSo here it says, so it says,\nI'd better save the\n\n477\n00:24:02,330 --> 00:24:05,610\nenvironment register, because\nevaluating G might be some\n\n478\n00:24:05,610 --> 00:24:07,960\narbitrary piece of code that\nwould trash it, and I'm going\n\n479\n00:24:07,960 --> 00:24:12,360\nto need it later, after\nthis argument, for\n\n480\n00:24:12,360 --> 00:24:15,540\ndoing the second argument.\n\n481\n00:24:15,540 --> 00:24:20,580\nSo that's why this one didn't go\naway, because the compiler\n\n482\n00:24:20,580 --> 00:24:22,550\nmade no assumptions about\nwhat G would do.\n\n483\n00:24:22,550 --> 00:24:26,170\nOn the other hand, if you look\nat what the second argument\n\n484\n00:24:26,170 --> 00:24:27,710\nis, that's just looking\nup one.\n\n485\n00:24:27,710 --> 00:24:30,810\nThat doesn't need this\nenvironment register.\n\n486\n00:24:30,810 --> 00:24:32,070\nSo there's no reason\nto save it.\n\n487\n00:24:32,070 --> 00:24:35,020\nSo in fact, you can get\nrid of that one, too.\n\n488\n00:24:35,020 --> 00:24:38,290\nAnd from this whole pile of, of\nregister operations, if you\n\n489\n00:24:38,290 --> 00:24:40,840\nsimply do a little bit of\nreasoning like that, you get\n\n490\n00:24:40,840 --> 00:24:45,170\ndown to, I think, just two pairs\nof saves and restores.\n\n491\n00:24:45,170 --> 00:24:47,870\nAnd those, in fact, could go\naway further if you, if you\n\n492\n00:24:47,870 --> 00:24:56,650\nknew something about G.\n\n493\n00:24:56,650 --> 00:24:59,250\nSo again, the general idea is\nthat the reason the compiler\n\n494\n00:24:59,250 --> 00:25:01,430\ncan be better is that the\ninterpreter doesn't know what\n\n495\n00:25:01,430 --> 00:25:03,310\nit's about to encounter.\n\n496\n00:25:03,310 --> 00:25:05,740\nIt has to be maximally\npessimistic in saving things\n\n497\n00:25:05,740 --> 00:25:07,750\nto protect itself.\n\n498\n00:25:07,750 --> 00:25:10,820\nThe compiler only has\nto deal with what\n\n499\n00:25:10,820 --> 00:25:13,410\nactually had to be saved.\n\n500\n00:25:13,410 --> 00:25:15,620\nAnd there are two reasons\nthat something might\n\n501\n00:25:15,620 --> 00:25:17,920\nnot have to be saved.\n\n502\n00:25:17,920 --> 00:25:20,100\nOne is that what you're\nprotecting it against, in\n\n503\n00:25:20,100 --> 00:25:22,700\nfact, didn't trash the register,\nlike it was just a\n\n504\n00:25:22,700 --> 00:25:24,210\nvariable look-up.\n\n505\n00:25:24,210 --> 00:25:26,730\nAnd the other one is, that the\nthing that you were saving it\n\n506\n00:25:26,730 --> 00:25:30,800\nfor might turn out not\nto actually need it.\n\n507\n00:25:30,800 --> 00:25:34,370\nSo those are the two basic\npieces of knowledge that the\n\n508\n00:25:34,370 --> 00:25:37,010\ncompiler can take advantage\nof in making\n\n509\n00:25:37,010 --> 00:25:38,260\nthe code more efficient.\n\n510\n00:25:38,260 --> 00:25:44,570\n\n\n511\n00:25:44,570 --> 00:25:45,820\nLet's break for questions.\n\n512\n00:25:45,820 --> 00:25:51,280\n\n\n513\n00:25:51,280 --> 00:25:54,410\nAUDIENCE: You kept saying that\nthe uneval register, unev\n\n514\n00:25:54,410 --> 00:25:56,350\nregister didn't need\nto be used at all.\n\n515\n00:25:56,350 --> 00:25:57,660\nDoes that mean that you\ncould just map a\n\n516\n00:25:57,660 --> 00:25:58,590\nsix-register machine?\n\n517\n00:25:58,590 --> 00:26:00,220\nOr is that, in this particular\nexample, it\n\n518\n00:26:00,220 --> 00:26:01,860\ndidn't need to be used?\n\n519\n00:26:01,860 --> 00:26:05,480\nPROFESSOR: For the compiler,\nyou could generate code for\n\n520\n00:26:05,480 --> 00:26:07,580\nthe six-register, five, right?\n\n521\n00:26:07,580 --> 00:26:08,930\nBecause that exp\ngoes away also.\n\n522\n00:26:08,930 --> 00:26:11,750\n\n\n523\n00:26:11,750 --> 00:26:14,700\nAssuming--yeah, you can get\nrid of both exp and unev,\n\n524\n00:26:14,700 --> 00:26:17,380\nbecause, see, those are data\nstructures of the evaluator.\n\n525\n00:26:17,380 --> 00:26:19,600\nThose are all things that would\nbe constants from the\n\n526\n00:26:19,600 --> 00:26:21,410\npoint of view of the compiler.\n\n527\n00:26:21,410 --> 00:26:24,730\nThe only thing is this\nparticular compiler is set up\n\n528\n00:26:24,730 --> 00:26:29,330\nso that interpreted code and\ncompiled code can coexist.\n\n529\n00:26:29,330 --> 00:26:34,330\nSo the way to think about it is,\nis maybe you build a chip\n\n530\n00:26:34,330 --> 00:26:37,420\nwhich is the evaluator, and what\nthe compiler might do is\n\n531\n00:26:37,420 --> 00:26:39,920\ngenerate code for that chip.\n\n532\n00:26:39,920 --> 00:26:41,550\nIt just wouldn't use two\nof the registers.\n\n533\n00:26:41,550 --> 00:26:51,158\n\n\n534\n00:26:51,158 --> 00:26:53,326\nAll right, let's take a break.\n\n535\n00:26:53,326 --> 00:27:28,576\n[MUSIC PLAYING]\n\n536\n00:27:28,576 --> 00:27:32,900\nWe just looked at what the\ncompiler is supposed to do.\n\n537\n00:27:32,900 --> 00:27:36,700\nNow let's very briefly look\nat how, how this gets\n\n538\n00:27:36,700 --> 00:27:38,120\naccomplished.\n\n539\n00:27:38,120 --> 00:27:39,600\nAnd I'm going to give\nno details.\n\n540\n00:27:39,600 --> 00:27:42,580\nThere's, there's a giant pile of\ncode in the book that gives\n\n541\n00:27:42,580 --> 00:27:43,440\nall the details.\n\n542\n00:27:43,440 --> 00:27:46,150\nBut what I want to do is\njust show you the, the\n\n543\n00:27:46,150 --> 00:27:49,590\nessential idea here.\n\n544\n00:27:49,590 --> 00:27:51,450\nWorry about the details\nsome other time.\n\n545\n00:27:51,450 --> 00:27:55,420\nLet's imagine that we're\ncompiling an expression that\n\n546\n00:27:55,420 --> 00:27:57,650\nlooks like there's some\noperator, and\n\n547\n00:27:57,650 --> 00:27:58,900\nthere are two arguments.\n\n548\n00:27:58,900 --> 00:28:03,660\n\n\n549\n00:28:03,660 --> 00:28:06,310\nNow, the--\n\n550\n00:28:06,310 --> 00:28:08,940\nwhat's the code that the\ncompiler should generate?\n\n551\n00:28:08,940 --> 00:28:12,630\nWell, first of all, it should\nrecursively go off and compile\n\n552\n00:28:12,630 --> 00:28:14,192\nthe operator.\n\n553\n00:28:14,192 --> 00:28:18,650\nSo it says, I'll compile\nthe operator.\n\n554\n00:28:18,650 --> 00:28:21,250\n\n\n555\n00:28:21,250 --> 00:28:26,600\nAnd where I'm going to need that\nis to be in the function\n\n556\n00:28:26,600 --> 00:28:28,400\nregister, eventually.\n\n557\n00:28:28,400 --> 00:28:30,830\nSo I'll compile some\ninstructions that will compile\n\n558\n00:28:30,830 --> 00:28:37,640\nthe operator and end up\nwith the result in\n\n559\n00:28:37,640 --> 00:28:38,890\nthe function register.\n\n560\n00:28:38,890 --> 00:28:45,420\n\n\n561\n00:28:45,420 --> 00:28:49,770\nThe next thing it's going to do,\nanother piece is to say,\n\n562\n00:28:49,770 --> 00:28:55,140\nwell, I have to compile\nthe first argument.\n\n563\n00:28:55,140 --> 00:28:58,100\nSo it calls itself\nrecursively.\n\n564\n00:28:58,100 --> 00:29:03,010\nAnd let's say the result\nwill go into val.\n\n565\n00:29:03,010 --> 00:29:09,150\n\n\n566\n00:29:09,150 --> 00:29:11,460\nAnd then what it's going to need\nto do is start setting up\n\n567\n00:29:11,460 --> 00:29:25,060\nthe argument list. So it'll say,\nassign to argl cons of\n\n568\n00:29:25,060 --> 00:29:27,160\nfetch-- so it generates this\nliteral instruction--\n\n569\n00:29:27,160 --> 00:29:35,430\nfetch of val onto empty list.\n\n570\n00:29:35,430 --> 00:29:36,680\nHowever, it might\nhave to work--\n\n571\n00:29:36,680 --> 00:29:39,590\n\n\n572\n00:29:39,590 --> 00:29:43,950\nwhen it gets here, it's going\nto need the environment.\n\n573\n00:29:43,950 --> 00:29:45,650\nIt's going to need whatever\nenvironment was here in order\n\n574\n00:29:45,650 --> 00:29:49,030\nto do this evaluation of\nthe first argument.\n\n575\n00:29:49,030 --> 00:29:54,990\nSo it has to ensure that the\ncompilation of this operand,\n\n576\n00:29:54,990 --> 00:29:58,610\nor it has to protect the\nfunction register against\n\n577\n00:29:58,610 --> 00:30:01,220\nwhatever might happen in the\ncompilation of this operand.\n\n578\n00:30:01,220 --> 00:30:04,820\nSo it puts a note here and says,\noh, this piece should be\n\n579\n00:30:04,820 --> 00:30:12,650\ndone preserving the environment\nregister.\n\n580\n00:30:12,650 --> 00:30:17,350\n\n\n581\n00:30:17,350 --> 00:30:22,630\nSimilarly, here, after it gets\ndone compiling the first\n\n582\n00:30:22,630 --> 00:30:25,110\noperand, it's going to say,\nI better compile--\n\n583\n00:30:25,110 --> 00:30:26,740\nI'm going to need to know\nthe environment\n\n584\n00:30:26,740 --> 00:30:27,930\nfor the second operand.\n\n585\n00:30:27,930 --> 00:30:30,870\nSo it puts a little note here,\nsaying, yeah, this is also\n\n586\n00:30:30,870 --> 00:30:41,510\ndone preserving env. Now it goes\non and says, well, the\n\n587\n00:30:41,510 --> 00:30:48,880\nnext chunk of code is the one\nthat's going to compile the\n\n588\n00:30:48,880 --> 00:30:50,760\nsecond argument.\n\n589\n00:30:50,760 --> 00:30:57,840\nAnd let's say it'll compile\nit with a targeted to\n\n590\n00:30:57,840 --> 00:30:59,360\nval, as they say.\n\n591\n00:30:59,360 --> 00:31:03,940\n\n\n592\n00:31:03,940 --> 00:31:08,360\nAnd then it'll generate the\nliteral instruction, building\n\n593\n00:31:08,360 --> 00:31:20,860\nup the argument list. So it'll\nsay, assign to argl cons of\n\n594\n00:31:20,860 --> 00:31:34,060\nthe new value it just got onto\nthe old argument list.\n\n595\n00:31:34,060 --> 00:31:37,610\nHowever, in order to have the\nold argument list, it better\n\n596\n00:31:37,610 --> 00:31:40,440\nhave arranged that the argument\nlist didn't get\n\n597\n00:31:40,440 --> 00:31:43,510\ntrashed by whatever\nhappened in here.\n\n598\n00:31:43,510 --> 00:31:46,200\nSo it puts a little note here\nand says, oh, this has to be\n\n599\n00:31:46,200 --> 00:31:51,400\ndone preserving argl.\n\n600\n00:31:51,400 --> 00:31:54,380\n\n\n601\n00:31:54,380 --> 00:31:58,090\nNow it's got the argument\nlist set up.\n\n602\n00:31:58,090 --> 00:32:02,520\nAnd it's all ready to go\nto apply dispatch.\n\n603\n00:32:02,520 --> 00:32:06,450\n\n\n604\n00:32:06,450 --> 00:32:10,440\nIt generates this literal\ninstruction.\n\n605\n00:32:10,440 --> 00:32:14,990\n\n\n606\n00:32:14,990 --> 00:32:19,310\nBecause now it's got the\narguments in argl and the\n\n607\n00:32:19,310 --> 00:32:22,360\noperator in fun, but wait, it's\nonly got the operator in\n\n608\n00:32:22,360 --> 00:32:27,520\nfun if it had ensured that\nthis block of code didn't\n\n609\n00:32:27,520 --> 00:32:29,600\ntrash what was in the\nfunction register.\n\n610\n00:32:29,600 --> 00:32:32,090\nSo it puts a little note here\nand says, oh, yes, all this\n\n611\n00:32:32,090 --> 00:32:39,460\nstuff here had better\nbe done preserving\n\n612\n00:32:39,460 --> 00:32:40,710\nthe function register.\n\n613\n00:32:40,710 --> 00:32:46,110\n\n\n614\n00:32:46,110 --> 00:32:46,210\nSo that's the little--so when\nit starts ticking--so\n\n615\n00:32:46,210 --> 00:32:51,510\nbasically, what the compiler\ndoes is append a whole bunch\n\n616\n00:32:51,510 --> 00:32:53,432\nof code sequences.\n\n617\n00:32:53,432 --> 00:32:58,580\nSee, what it's got in it is\nlittle primitive pieces of\n\n618\n00:32:58,580 --> 00:33:01,940\nthings, like how to look up\na symbol, how to do a\n\n619\n00:33:01,940 --> 00:33:02,560\nconditional.\n\n620\n00:33:02,560 --> 00:33:05,530\nThose are all little\npieces of things.\n\n621\n00:33:05,530 --> 00:33:07,340\nAnd then it appends them\ntogether in this sort of\n\n622\n00:33:07,340 --> 00:33:08,810\ndiscipline.\n\n623\n00:33:08,810 --> 00:33:11,890\nSo the basic means of combining\nthings is to append\n\n624\n00:33:11,890 --> 00:33:13,140\ntwo code sequences.\n\n625\n00:33:13,140 --> 00:33:21,610\n\n\n626\n00:33:21,610 --> 00:33:22,860\nThat's what's going on here.\n\n627\n00:33:22,860 --> 00:33:25,690\n\n\n628\n00:33:25,690 --> 00:33:27,590\nAnd it's a little bit tricky.\n\n629\n00:33:27,590 --> 00:33:32,020\nThe idea is that it appends\ntwo code sequences, taking\n\n630\n00:33:32,020 --> 00:33:35,670\ncare to preserve a register.\n\n631\n00:33:35,670 --> 00:33:39,250\nSo the actual append operation\nlooks like this.\n\n632\n00:33:39,250 --> 00:33:41,230\nWhat it wants to\ndo is say, if--\n\n633\n00:33:41,230 --> 00:33:44,450\nhere's what it means to append\ntwo code sequences.\n\n634\n00:33:44,450 --> 00:33:53,685\nSo if sequence one\nneeds register--\n\n635\n00:33:53,685 --> 00:33:54,720\nI should change this.\n\n636\n00:33:54,720 --> 00:33:57,200\nAppend sequence one\nto sequence two,\n\n637\n00:33:57,200 --> 00:34:03,815\npreserving some register.\n\n638\n00:34:03,815 --> 00:34:08,370\n\n\n639\n00:34:08,370 --> 00:34:11,080\nLet me say, and.\n\n640\n00:34:11,080 --> 00:34:13,719\nSo it's clear that sequence\none comes first.\n\n641\n00:34:13,719 --> 00:34:26,449\nSo if sequence two needs the\nregister and sequence one\n\n642\n00:34:26,449 --> 00:34:35,230\nmodifies the register, then\nthe instructions that the\n\n643\n00:34:35,230 --> 00:34:43,380\ncompiler spits out are,\nsave the register.\n\n644\n00:34:43,380 --> 00:34:44,440\nHere's the code.\n\n645\n00:34:44,440 --> 00:34:45,280\nYou generate this code.\n\n646\n00:34:45,280 --> 00:34:50,860\nSave the register, and then you\nput out the recursively\n\n647\n00:34:50,860 --> 00:34:53,389\ncompiled stuff for\nsequence one.\n\n648\n00:34:53,389 --> 00:34:54,639\nAnd then you restore\nthe register.\n\n649\n00:34:54,639 --> 00:35:00,440\n\n\n650\n00:35:00,440 --> 00:35:04,610\nAnd then you put out the\nrecursively compiled stuff for\n\n651\n00:35:04,610 --> 00:35:07,330\nsequence two.\n\n652\n00:35:07,330 --> 00:35:09,610\nThat's in the case where\nyou need to do it.\n\n653\n00:35:09,610 --> 00:35:12,700\nSequence two actually needs the\nregister, and sequence one\n\n654\n00:35:12,700 --> 00:35:15,430\nactually clobbers it.\n\n655\n00:35:15,430 --> 00:35:16,320\nSo that's sort of if.\n\n656\n00:35:16,320 --> 00:35:25,820\nOtherwise, all you spit out is\nsequence one followed by\n\n657\n00:35:25,820 --> 00:35:28,240\nsequence two.\n\n658\n00:35:28,240 --> 00:35:31,720\nSo that's the basic operation\nfor sticking together these\n\n659\n00:35:31,720 --> 00:35:34,490\nbits of code fragments,\nthese bits of\n\n660\n00:35:34,490 --> 00:35:36,960\ninstructions into a sequence.\n\n661\n00:35:36,960 --> 00:35:42,840\nAnd you see, from this point\nof view, the difference\n\n662\n00:35:42,840 --> 00:35:46,840\nbetween the interpreter and the\ncompiler, in some sense,\n\n663\n00:35:46,840 --> 00:35:50,220\nis that where the compiler has\nthese preserving notes, and\n\n664\n00:35:50,220 --> 00:35:52,910\nsays, maybe I'll actually\ngenerate the saves and\n\n665\n00:35:52,910 --> 00:35:56,220\nrestores and maybe I won't,\nthe interpreter being\n\n666\n00:35:56,220 --> 00:35:59,550\nmaximally pessimistic always has\na save and restore here.\n\n667\n00:35:59,550 --> 00:36:04,140\nThat's the essential\ndifference.\n\n668\n00:36:04,140 --> 00:36:07,620\nWell, in order to do this, of\ncourse, the compiler needs\n\n669\n00:36:07,620 --> 00:36:10,775\nsome theory of what code\nsequences need\n\n670\n00:36:10,775 --> 00:36:12,025\nand modifier registers.\n\n671\n00:36:12,025 --> 00:36:14,330\n\n\n672\n00:36:14,330 --> 00:36:17,670\nSo the tiny little fragments\nthat you put in, like the\n\n673\n00:36:17,670 --> 00:36:23,340\nbasic primitive code fragments,\nsay, what are the\n\n674\n00:36:23,340 --> 00:36:27,120\noperations that you do when\nyou look up a variable?\n\n675\n00:36:27,120 --> 00:36:29,630\nWhat are the sequence of things\nthat you do when you\n\n676\n00:36:29,630 --> 00:36:32,900\ncompile a constant or\napply a function?\n\n677\n00:36:32,900 --> 00:36:35,600\nThose have little notations in\nthere about what they need and\n\n678\n00:36:35,600 --> 00:36:36,850\nwhat they modify.\n\n679\n00:36:36,850 --> 00:36:38,760\n\n\n680\n00:36:38,760 --> 00:36:42,750\nSo the bottom-level\ndata structures--\n\n681\n00:36:42,750 --> 00:36:44,330\nWell, I'll say this.\n\n682\n00:36:44,330 --> 00:36:48,070\nA code sequence to the compiler\nlooks like this.\n\n683\n00:36:48,070 --> 00:36:50,945\nIt has the actual sequence\nof instructions.\n\n684\n00:36:50,945 --> 00:36:55,780\n\n\n685\n00:36:55,780 --> 00:37:00,370\nAnd then, along with\nit, there's the set\n\n686\n00:37:00,370 --> 00:37:02,195\nof registers modified.\n\n687\n00:37:02,195 --> 00:37:10,630\n\n\n688\n00:37:10,630 --> 00:37:12,335\nAnd then there's the set\nof registers needed.\n\n689\n00:37:12,335 --> 00:37:19,910\n\n\n690\n00:37:19,910 --> 00:37:24,310\nSo that's the information the\ncompiler has that it draws on\n\n691\n00:37:24,310 --> 00:37:25,965\nin order to be able to\ndo this operation.\n\n692\n00:37:25,965 --> 00:37:29,420\n\n\n693\n00:37:29,420 --> 00:37:30,650\nAnd where do those come from?\n\n694\n00:37:30,650 --> 00:37:34,920\nWell, those come from, you might\nexpect, for the very\n\n695\n00:37:34,920 --> 00:37:37,230\nprimitive ones, we're going\nto put them in by hand.\n\n696\n00:37:37,230 --> 00:37:39,890\nAnd then, when we combine two\nsequences, we'll figure out\n\n697\n00:37:39,890 --> 00:37:42,080\nwhat these things should be.\n\n698\n00:37:42,080 --> 00:37:48,460\nSo for example, a very primitive\none, let's see.\n\n699\n00:37:48,460 --> 00:37:51,790\nHow about doing a register\nassignment.\n\n700\n00:37:51,790 --> 00:37:56,040\nSo a primitive sequence might\nsay, oh, it's code fragment.\n\n701\n00:37:56,040 --> 00:38:03,050\nIts code instruction is assigned\nto R1, fetch of R2.\n\n702\n00:38:03,050 --> 00:38:05,000\nSo this is an example.\n\n703\n00:38:05,000 --> 00:38:08,510\nThat might be an example of a\nsequence of instructions.\n\n704\n00:38:08,510 --> 00:38:13,110\nAnd along with that, it'll\nsay, oh, what I need to\n\n705\n00:38:13,110 --> 00:38:20,670\nremember is that that modifies\nR1, and then it needs R2.\n\n706\n00:38:20,670 --> 00:38:24,630\n\n\n707\n00:38:24,630 --> 00:38:27,640\nSo when you're first building\nthis compiler, you put in\n\n708\n00:38:27,640 --> 00:38:31,030\nlittle fragments of\nstuff like that.\n\n709\n00:38:31,030 --> 00:38:37,320\nAnd now, when it combines two\nsequences, if I'm going to\n\n710\n00:38:37,320 --> 00:38:45,990\ncombine, let's say, sequence\none, that modifies a bunch of\n\n711\n00:38:45,990 --> 00:38:50,950\nregisters M1, and needs a\nbunch of registers N1.\n\n712\n00:38:50,950 --> 00:38:54,940\n\n\n713\n00:38:54,940 --> 00:39:00,800\nAnd I'm going to combine\nthat with sequence two.\n\n714\n00:39:00,800 --> 00:39:07,780\nThat modifies a bunch of\nregisters M2, and needs a\n\n715\n00:39:07,780 --> 00:39:09,570\nbunch of registers N2.\n\n716\n00:39:09,570 --> 00:39:12,590\n\n\n717\n00:39:12,590 --> 00:39:15,035\nThen, well, we can\nreason it out.\n\n718\n00:39:15,035 --> 00:39:20,230\nThe new code fragment,\nsequence one, and--\n\n719\n00:39:20,230 --> 00:39:25,270\nfollowed by sequence two, well,\n\n720\n00:39:25,270 --> 00:39:27,760\nwhat's it going to modify?\n\n721\n00:39:27,760 --> 00:39:29,380\nThe things that it will modify\nare the things that are\n\n722\n00:39:29,380 --> 00:39:33,990\nmodified either by sequence\none or sequence two.\n\n723\n00:39:33,990 --> 00:39:38,380\nSo the union of these\ntwo sets are what\n\n724\n00:39:38,380 --> 00:39:40,530\nthe new thing modifies.\n\n725\n00:39:40,530 --> 00:39:45,620\nAnd then you say, well, what is\nthis--what registers is it\n\n726\n00:39:45,620 --> 00:39:47,870\ngoing to need?\n\n727\n00:39:47,870 --> 00:39:50,770\nIt's going to need the things\nthat are, first of all, needed\n\n728\n00:39:50,770 --> 00:39:52,790\nby sequence one.\n\n729\n00:39:52,790 --> 00:39:55,250\nSo what it needs is\nsequence one.\n\n730\n00:39:55,250 --> 00:39:58,820\nAnd then, well, not quite all of\nthe ones that are needed by\n\n731\n00:39:58,820 --> 00:39:59,760\nsequence one.\n\n732\n00:39:59,760 --> 00:40:02,910\nWhat it needs are the ones that\nare needed by sequence\n\n733\n00:40:02,910 --> 00:40:08,070\ntwo that have not been set\nup by sequence one.\n\n734\n00:40:08,070 --> 00:40:12,880\nSo it's sort of the union of the\nthings that sequence two\n\n735\n00:40:12,880 --> 00:40:19,370\nneeds minus the ones that\nsequence one modifies.\n\n736\n00:40:19,370 --> 00:40:20,910\nBecause it worries about\nsetting them up.\n\n737\n00:40:20,910 --> 00:40:24,230\n\n\n738\n00:40:24,230 --> 00:40:26,740\nSo there's the basic structure\nof the compiler.\n\n739\n00:40:26,740 --> 00:40:30,520\nThe way you do register\noptimizations is you have some\n\n740\n00:40:30,520 --> 00:40:34,010\nstrategies for what needs\nto be preserved.\n\n741\n00:40:34,010 --> 00:40:35,450\nThat depends on a\ndata structure.\n\n742\n00:40:35,450 --> 00:40:37,600\nWell, it depends on the\noperation of what it means to\n\n743\n00:40:37,600 --> 00:40:39,080\nput things together.\n\n744\n00:40:39,080 --> 00:40:44,710\nPreserving something, that\ndepends on knowing what\n\n745\n00:40:44,710 --> 00:40:46,200\nregisters are needed\nand modified\n\n746\n00:40:46,200 --> 00:40:48,900\nby these code fragments.\n\n747\n00:40:48,900 --> 00:40:52,820\nThat depends on having little\ndata structures, which say, a\n\n748\n00:40:52,820 --> 00:40:56,450\ncode sequence is the actual\ninstructions, what they modify\n\n749\n00:40:56,450 --> 00:40:57,350\nand what they need.\n\n750\n00:40:57,350 --> 00:40:58,750\nThat comes from, at\nthe primitive\n\n751\n00:40:58,750 --> 00:41:00,240\nlevel, building it in.\n\n752\n00:41:00,240 --> 00:41:02,800\nAt the primitive level, it's\ngoing to be completely obvious\n\n753\n00:41:02,800 --> 00:41:04,850\nwhat something needs\nand modifies.\n\n754\n00:41:04,850 --> 00:41:08,160\nPlus, this particular way that\nsays, when I build up bigger\n\n755\n00:41:08,160 --> 00:41:11,130\nones, here's how I generate\nthe new set of registers\n\n756\n00:41:11,130 --> 00:41:15,010\nmodified and the new set\nof registers needed.\n\n757\n00:41:15,010 --> 00:41:16,120\nAnd that's the whole--\n\n758\n00:41:16,120 --> 00:41:17,810\nwell, I shouldn't say that's\nthe whole thing.\n\n759\n00:41:17,810 --> 00:41:21,320\nThat's the whole thing except\nfor about 30 pages of details\n\n760\n00:41:21,320 --> 00:41:21,860\nin the book.\n\n761\n00:41:21,860 --> 00:41:28,880\nBut it is a perfectly usable\nrudimentary compiler.\n\n762\n00:41:28,880 --> 00:41:31,390\nLet me kind of show\nyou what it does.\n\n763\n00:41:31,390 --> 00:41:36,330\nSuppose we start out with\nrecursive factorial.\n\n764\n00:41:36,330 --> 00:41:38,590\nAnd these slides are going to\nbe much too small to read.\n\n765\n00:41:38,590 --> 00:41:40,370\nI just want to flash through\nthe code and show you about\n\n766\n00:41:40,370 --> 00:41:41,620\nhow much it is.\n\n767\n00:41:41,620 --> 00:41:44,460\n\n\n768\n00:41:44,460 --> 00:41:46,220\nThat starts out with--here's a\nfirst block of it, where it\n\n769\n00:41:46,220 --> 00:41:48,740\ncompiles a procedure entry and\ndoes a bunch of assignments.\n\n770\n00:41:48,740 --> 00:41:53,000\nAnd this thing is basically up\nthrough the part where it sets\n\n771\n00:41:53,000 --> 00:41:55,500\nup to do the predicate\nand test whether\n\n772\n00:41:55,500 --> 00:41:56,830\nthe predicate's true.\n\n773\n00:41:56,830 --> 00:41:59,530\nThe second part is what\nresults from--\n\n774\n00:41:59,530 --> 00:42:04,210\nin the recursive call to\nfact of n minus one.\n\n775\n00:42:04,210 --> 00:42:08,750\nAnd this last part is coming\nback from that and then taking\n\n776\n00:42:08,750 --> 00:42:09,890\ncare of the constant case.\n\n777\n00:42:09,890 --> 00:42:12,010\nSo that's about how\nmuch code it\n\n778\n00:42:12,010 --> 00:42:13,760\nwould produce for factorial.\n\n779\n00:42:13,760 --> 00:42:18,380\nWe could make this compiler\nmuch, much better, of course.\n\n780\n00:42:18,380 --> 00:42:21,870\nThe main way we could make\nit better is to allow the\n\n781\n00:42:21,870 --> 00:42:24,720\ncompiler to make any assumptions\nat all about what\n\n782\n00:42:24,720 --> 00:42:26,990\nhappens when you call\na procedure.\n\n783\n00:42:26,990 --> 00:42:30,810\nSo this compiler, for instance,\ndoesn't even know,\n\n784\n00:42:30,810 --> 00:42:35,030\nsay, that multiplication\nis something that\n\n785\n00:42:35,030 --> 00:42:36,030\ncould be coded in line.\n\n786\n00:42:36,030 --> 00:42:37,670\nInstead, it sets up this\nwhole mechanism.\n\n787\n00:42:37,670 --> 00:42:38,920\nIt goes to apply-dispatch.\n\n788\n00:42:38,920 --> 00:42:41,430\n\n\n789\n00:42:41,430 --> 00:42:43,900\nThat's a tremendous waste,\nbecause what you do every time\n\n790\n00:42:43,900 --> 00:42:46,060\nyou go to apply-dispatch is\nyou have to concept this\n\n791\n00:42:46,060 --> 00:42:48,640\nargument list, because it's\na very general thing\n\n792\n00:42:48,640 --> 00:42:49,170\nyou're going to.\n\n793\n00:42:49,170 --> 00:42:51,510\nIn any real compiler, of course,\nyou're going to have\n\n794\n00:42:51,510 --> 00:42:53,830\nregisters for holding\narguments.\n\n795\n00:42:53,830 --> 00:42:57,060\nAnd you're going to start\npreserving and saving the way\n\n796\n00:42:57,060 --> 00:43:00,510\nyou use those registers\nsimilar to the\n\n797\n00:43:00,510 --> 00:43:02,442\nsame strategy here.\n\n798\n00:43:02,442 --> 00:43:06,700\nSo that's probably the very main\nway that this particular\n\n799\n00:43:06,700 --> 00:43:08,940\ncompiler in the book\ncould be fixed.\n\n800\n00:43:08,940 --> 00:43:12,010\nThere are other things like\nlooking up variable values and\n\n801\n00:43:12,010 --> 00:43:14,010\nmaking more efficient primitive\noperations and all\n\n802\n00:43:14,010 --> 00:43:14,490\nsorts of things.\n\n803\n00:43:14,490 --> 00:43:17,260\nEssentially, a good Lisp\ncompiler can absorb an\n\n804\n00:43:17,260 --> 00:43:19,780\narbitrary amount of effort.\n\n805\n00:43:19,780 --> 00:43:23,820\nAnd probably one of the reasons\nthat Lisp is slow with\n\n806\n00:43:23,820 --> 00:43:27,470\ncompared to languages like\nFORTRAN is that, if you look\n\n807\n00:43:27,470 --> 00:43:29,860\nover history at the amount of\neffort that's gone into\n\n808\n00:43:29,860 --> 00:43:32,110\nbuilding Lisp compilers, it's\nnowhere near the amount of\n\n809\n00:43:32,110 --> 00:43:34,520\neffort that's gone into\nFORTRAN compilers.\n\n810\n00:43:34,520 --> 00:43:36,910\nAnd maybe that's something that\nwill change over the next\n\n811\n00:43:36,910 --> 00:43:38,250\ncouple of years.\n\n812\n00:43:38,250 --> 00:43:39,500\nOK, let's break.\n\n813\n00:43:39,500 --> 00:43:43,950\n\n\n814\n00:43:43,950 --> 00:43:45,200\nQuestions?\n\n815\n00:43:45,200 --> 00:43:48,370\n\n\n816\n00:43:48,370 --> 00:43:49,590\nAUDIENCE: One of the very\nfirst classes--\n\n817\n00:43:49,590 --> 00:43:52,180\nI don't know if it was during\nclass or after class- you\n\n818\n00:43:52,180 --> 00:43:57,040\nshowed me the, say, addition has\na primitive that we don't\n\n819\n00:43:57,040 --> 00:44:00,720\nsee, and-percent add or\nsomething like that.\n\n820\n00:44:00,720 --> 00:44:03,070\nIs that because, if you're doing\ninline code you'd want\n\n821\n00:44:03,070 --> 00:44:08,540\nto just do it for two\noperators, operands?\n\n822\n00:44:08,540 --> 00:44:10,552\nBut if you had more operands,\nyou'd want to\n\n823\n00:44:10,552 --> 00:44:12,800\ndo something special?\n\n824\n00:44:12,800 --> 00:44:15,290\nPROFESSOR: Yeah, you're looking\nin the actual scheme\n\n825\n00:44:15,290 --> 00:44:15,980\nimplementation.\n\n826\n00:44:15,980 --> 00:44:17,880\nThere's a plus, and a plus\nis some operator.\n\n827\n00:44:17,880 --> 00:44:20,630\nAnd then if you go look inside\nthe code for plus, you see\n\n828\n00:44:20,630 --> 00:44:21,440\nsomething called--\n\n829\n00:44:21,440 --> 00:44:24,640\nI forget-- and-percent plus\nor something like that.\n\n830\n00:44:24,640 --> 00:44:27,190\nAnd what's going on there is\nthat particular kind of\n\n831\n00:44:27,190 --> 00:44:28,540\noptimization.\n\n832\n00:44:28,540 --> 00:44:30,520\nBecause, see, general\nplus takes an\n\n833\n00:44:30,520 --> 00:44:31,770\narbitrary number of arguments.\n\n834\n00:44:31,770 --> 00:44:34,750\n\n\n835\n00:44:34,750 --> 00:44:38,020\nSo the most general plus says,\noh, if I have an argument\n\n836\n00:44:38,020 --> 00:44:42,400\nlist, I'd better cons it up in\nsome list and then figure out\n\n837\n00:44:42,400 --> 00:44:44,880\nhow many there were or\nsomething like that.\n\n838\n00:44:44,880 --> 00:44:47,820\nThat's terribly inefficient,\nespecially since most of the\n\n839\n00:44:47,820 --> 00:44:49,200\ntime you're probably\nadding two numbers.\n\n840\n00:44:49,200 --> 00:44:52,200\nYou don't want to really have to\ncons this argument list. So\n\n841\n00:44:52,200 --> 00:44:57,050\nwhat you'd like to do is build\nthe code for plus with a bunch\n\n842\n00:44:57,050 --> 00:44:58,170\nof entries.\n\n843\n00:44:58,170 --> 00:45:00,170\nSo most of what it's\ndoing is the same.\n\n844\n00:45:00,170 --> 00:45:02,630\nHowever, there might be a\nspecial entry that you'd go to\n\n845\n00:45:02,630 --> 00:45:04,640\nif you knew there were\nonly two arguments.\n\n846\n00:45:04,640 --> 00:45:05,910\nAnd those you'll put\nin registers.\n\n847\n00:45:05,910 --> 00:45:07,590\nThey won't be in an argument\nlist and you won't have to\n\n848\n00:45:07,590 --> 00:45:09,080\n[UNINTELLIGIBLE].\n\n849\n00:45:09,080 --> 00:45:12,570\nThat's how a lot of\nthese things work.\n\n850\n00:45:12,570 --> 00:45:13,948\nOK, let's take a break.\n\n851\n00:45:13,948 --> 00:45:15,696\n[MUSIC PLAYING]\n\n852\n00:45:15,696 --> 00:45:42,911\n\n"
  },
  {
    "path": "SrtEN/lec10b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:04,970\n\n\n1\n00:00:04,970 --> 00:00:05,285\n[MUSIC-- \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n2\n00:00:05,285 --> 00:00:06,535\nJOHANN SEBASTIAN BACH]\n\n3\n00:00:06,535 --> 00:00:18,910\n\n\n4\n00:00:18,910 --> 00:00:22,140\nPROFESSOR: Well, there's one bit\nof mystery left, which I'd\n\n5\n00:00:22,140 --> 00:00:24,440\nlike to get rid of right now.\n\n6\n00:00:24,440 --> 00:00:28,210\nAnd that's that we've been\nblithely doing things like\n\n7\n00:00:28,210 --> 00:00:33,660\ncons assuming there's\nalways another one.\n\n8\n00:00:33,660 --> 00:00:37,060\nThat we've been doing these\nthings like car-ing and\n\n9\n00:00:37,060 --> 00:00:38,750\ncdr-ing and assuming that\nwe had some idea\n\n10\n00:00:38,750 --> 00:00:40,020\nhow this can be done.\n\n11\n00:00:40,020 --> 00:00:43,800\nNow indeed we said that that's\nequivalent to having\n\n12\n00:00:43,800 --> 00:00:45,780\nprocedures.\n\n13\n00:00:45,780 --> 00:00:48,360\nBut that doesn't really solve\nthe problem, because the\n\n14\n00:00:48,360 --> 00:00:50,470\nprocedure need all sorts of\ncomplicated mechanisms like\n\n15\n00:00:50,470 --> 00:00:53,010\nenvironment structures and\nthings like that to work.\n\n16\n00:00:53,010 --> 00:00:55,770\nAnd those were ultimately made\nout of conses in the model\n\n17\n00:00:55,770 --> 00:00:59,380\nthat we had, so that really\ndoesn't solve the problem.\n\n18\n00:00:59,380 --> 00:01:02,860\nNow the problem here is\nthe glue the data\n\n19\n00:01:02,860 --> 00:01:04,760\nstructure's made out of.\n\n20\n00:01:04,760 --> 00:01:07,370\nWhat kind of possible\nthing could it be?\n\n21\n00:01:07,370 --> 00:01:11,060\nWe've been showing you things\nlike a machine, a computer\n\n22\n00:01:11,060 --> 00:01:14,700\nthat has a controller, and some\n\n23\n00:01:14,700 --> 00:01:16,980\nregisters, and maybe a stack.\n\n24\n00:01:16,980 --> 00:01:18,270\nAnd we haven't said anything\nabout, for\n\n25\n00:01:18,270 --> 00:01:20,570\nexample, larger memory.\n\n26\n00:01:20,570 --> 00:01:23,740\nAnd I think that's what we have\nto worry about right now.\n\n27\n00:01:23,740 --> 00:01:27,160\nBut just to make it perfectly\nclear that this is an\n\n28\n00:01:27,160 --> 00:01:31,320\ninessential, purely\nimplementational thing, I'd\n\n29\n00:01:31,320 --> 00:01:33,500\nlike to show you, for example,\nhow you can do it\n\n30\n00:01:33,500 --> 00:01:34,800\nall with the numbers.\n\n31\n00:01:34,800 --> 00:01:37,590\nThat's an easy one.\n\n32\n00:01:37,590 --> 00:01:45,020\nFamous fellow by the name of\nGodel, a logician at the end\n\n33\n00:01:45,020 --> 00:01:51,050\nof the 1930s, invented a very\nclever way of encoding the\n\n34\n00:01:51,050 --> 00:01:54,320\ncomplicated expressions\nas numbers.\n\n35\n00:01:54,320 --> 00:01:55,540\nFor example--\n\n36\n00:01:55,540 --> 00:01:58,250\nI'm not saying exactly what\nGodel's scheme is, because he\n\n37\n00:01:58,250 --> 00:01:59,660\ndidn't use words like cons.\n\n38\n00:01:59,660 --> 00:02:03,090\nHe had other kinds of ways of\ncombining to make expressions.\n\n39\n00:02:03,090 --> 00:02:05,860\nBut he said, I'm going to\nassign a number to every\n\n40\n00:02:05,860 --> 00:02:07,920\nalgebraic expression.\n\n41\n00:02:07,920 --> 00:02:09,970\nAnd the way I'm going to\nmanufacture these numbers is\n\n42\n00:02:09,970 --> 00:02:12,470\nby combining the numbers\nof the parts.\n\n43\n00:02:12,470 --> 00:02:15,880\nSo for example, what we were\ndoing our world, we could say\n\n44\n00:02:15,880 --> 00:02:34,130\nthat if objects are represented\nby numbers, then\n\n45\n00:02:34,130 --> 00:02:42,660\ncons of x and y could be\nrepresented by 2 to the x\n\n46\n00:02:42,660 --> 00:02:46,130\ntimes 2 to the y.\n\n47\n00:02:46,130 --> 00:02:49,560\nBecause then we could\nextract the parts.\n\n48\n00:02:49,560 --> 00:02:57,500\nWe could say, for example, that\nthen car of, say, x is\n\n49\n00:02:57,500 --> 00:03:06,690\nthe number of factors\nof 2 in x.\n\n50\n00:03:06,690 --> 00:03:10,690\nAnd of course cdr is\nthe same thing.\n\n51\n00:03:10,690 --> 00:03:16,510\nIt's the number of factors\nof 3 in x.\n\n52\n00:03:16,510 --> 00:03:19,660\nNow this is a perfectly\nreasonable scheme, except for\n\n53\n00:03:19,660 --> 00:03:22,870\nthe fact that the numbers\nrapidly get to be much larger\n\n54\n00:03:22,870 --> 00:03:25,500\nin number of digits\nthan the number of\n\n55\n00:03:25,500 --> 00:03:27,950\nprotons in the universe.\n\n56\n00:03:27,950 --> 00:03:30,420\nSo there's no easy way to use\nthis scheme other than the\n\n57\n00:03:30,420 --> 00:03:33,430\ntheoretical one.\n\n58\n00:03:33,430 --> 00:03:37,010\nOn the other hand, there are\nother ways of representing\n\n59\n00:03:37,010 --> 00:03:38,450\nthese things.\n\n60\n00:03:38,450 --> 00:03:44,010\nWe have been thinking in\nterms of little boxes.\n\n61\n00:03:44,010 --> 00:03:47,000\nWe've been thinking about our\ncons structures as looking\n\n62\n00:03:47,000 --> 00:03:50,280\nsort of like this.\n\n63\n00:03:50,280 --> 00:03:53,610\nThey're little pigeon holes\nwith things in them.\n\n64\n00:03:53,610 --> 00:03:57,210\nAnd of course we arrange\nthem in little trees.\n\n65\n00:03:57,210 --> 00:04:00,680\nI wish that the semiconductor\nmanufacturers would supply me\n\n66\n00:04:00,680 --> 00:04:04,280\nwith something appropriate for\nthis, but actually what they\n\n67\n00:04:04,280 --> 00:04:09,380\ndo supply me with is\na linear memory.\n\n68\n00:04:09,380 --> 00:04:15,170\nMemory is sort of a big\npile of pigeonholes,\n\n69\n00:04:15,170 --> 00:04:17,720\npigeonholes like this.\n\n70\n00:04:17,720 --> 00:04:21,470\nEach of which can hold a certain\nsized object, a fixed\n\n71\n00:04:21,470 --> 00:04:23,390\nsize object.\n\n72\n00:04:23,390 --> 00:04:25,890\nSo, for example, a complicated\nlist with 25 elements won't\n\n73\n00:04:25,890 --> 00:04:28,550\nfit in one of these.\n\n74\n00:04:28,550 --> 00:04:30,600\nHowever, each of these is\nindexed by an address.\n\n75\n00:04:30,600 --> 00:04:33,970\n\n\n76\n00:04:33,970 --> 00:04:36,750\nSo the address might be zero\nhere, one here, two here,\n\n77\n00:04:36,750 --> 00:04:38,060\nthree here, and so on.\n\n78\n00:04:38,060 --> 00:04:40,400\nThat we write these down as\nnumbers is unimportant.\n\n79\n00:04:40,400 --> 00:04:42,710\nWhat matters is that they're\ndistinct as a way to get to\n\n80\n00:04:42,710 --> 00:04:44,970\nthe next one.\n\n81\n00:04:44,970 --> 00:04:48,300\nAnd inside of each of these,\nwe can stuff something into\n\n82\n00:04:48,300 --> 00:04:49,530\nthese pigeonholes.\n\n83\n00:04:49,530 --> 00:04:52,300\nThat's what memory is like, for\nthose of you who haven't\n\n84\n00:04:52,300 --> 00:04:53,550\nbuilt a computer.\n\n85\n00:04:53,550 --> 00:04:56,690\n\n\n86\n00:04:56,690 --> 00:04:59,280\nNow the problem is how are we\ngoing to impose on this type\n\n87\n00:04:59,280 --> 00:05:03,290\nof structure, this nice\ntree structure.\n\n88\n00:05:03,290 --> 00:05:05,480\nWell it's not very hard, and\nthere have been numerous\n\n89\n00:05:05,480 --> 00:05:06,630\nschemes involved in this.\n\n90\n00:05:06,630 --> 00:05:09,930\nThe most important one is to\nsay, well assuming that the\n\n91\n00:05:09,930 --> 00:05:13,920\nsemiconductor manufacturer\nallows me to arrange my memory\n\n92\n00:05:13,920 --> 00:05:16,390\nso that one of these pigeonholes\nis big enough to\n\n93\n00:05:16,390 --> 00:05:21,706\nhold the address of another\nI haven't made.\n\n94\n00:05:21,706 --> 00:05:23,730\nNow it actually has to be a\nlittle bit bigger because I\n\n95\n00:05:23,730 --> 00:05:28,215\nhave to also install or store\nsome information as to a tag\n\n96\n00:05:28,215 --> 00:05:30,390\nwhich describes the kind\nof thing that's there.\n\n97\n00:05:30,390 --> 00:05:32,350\nAnd we'll see that\nin a second.\n\n98\n00:05:32,350 --> 00:05:34,560\nAnd of course if the\nsemiconductor manufacturer\n\n99\n00:05:34,560 --> 00:05:37,470\ndoesn't arrange it so I can do\nthat, then of course I can,\n\n100\n00:05:37,470 --> 00:05:40,910\nwith some cleverness, arrange\ncombinations of these to fit\n\n101\n00:05:40,910 --> 00:05:43,770\ntogether in that way.\n\n102\n00:05:43,770 --> 00:05:48,510\nSo we're going to have to\nimagine imposing this\n\n103\n00:05:48,510 --> 00:05:51,740\ncomplicated tree structure on\nour nice linear memory.\n\n104\n00:05:51,740 --> 00:05:57,540\nIf we look at the first still\nstore, we see a classic scheme\n\n105\n00:05:57,540 --> 00:05:59,490\nfor doing that.\n\n106\n00:05:59,490 --> 00:06:03,910\nIt's a standard way of\nrepresenting Lisp structures\n\n107\n00:06:03,910 --> 00:06:05,980\nin a linear memory.\n\n108\n00:06:05,980 --> 00:06:12,030\nWhat we do is we divide this\nmemory into two parts.\n\n109\n00:06:12,030 --> 00:06:17,580\nAn array called the cars, and\nan array called the cdrs.\n\n110\n00:06:17,580 --> 00:06:20,470\nNow whether those happen to\nbe sequential addresses or\n\n111\n00:06:20,470 --> 00:06:22,560\nwhatever, it's not important.\n\n112\n00:06:22,560 --> 00:06:25,800\nThat's somebody's implementation\ndetails.\n\n113\n00:06:25,800 --> 00:06:28,960\nBut there are two arrays here.\n\n114\n00:06:28,960 --> 00:06:34,840\nLinear arrays indexed by\nsequential indices like this.\n\n115\n00:06:34,840 --> 00:06:36,150\nWhat is stored in each of these\n\n116\n00:06:36,150 --> 00:06:41,430\npigeonholes is a typed object.\n\n117\n00:06:41,430 --> 00:06:44,840\nAnd what we have here are types\nwhich begin with letters\n\n118\n00:06:44,840 --> 00:06:47,790\nlike p, standing for a pair.\n\n119\n00:06:47,790 --> 00:06:50,040\nOr n, standing for a number.\n\n120\n00:06:50,040 --> 00:06:57,290\nOr e, standing for an empty\nlist. The end of the list. And\n\n121\n00:06:57,290 --> 00:07:00,420\nso if we wish to represent an\nobject like this, the list\n\n122\n00:07:00,420 --> 00:07:04,310\nbeginning with 1, 2 and then\nhaving a 3 and a 4 as its\n\n123\n00:07:04,310 --> 00:07:06,430\nsecond and third elements.\n\n124\n00:07:06,430 --> 00:07:10,220\nA list containing a list as its\nfirst part and then two\n\n125\n00:07:10,220 --> 00:07:12,610\nnumbers as a second\nand third parts.\n\n126\n00:07:12,610 --> 00:07:15,250\nThen of course we draw it sort\nof like this these days, in\n\n127\n00:07:15,250 --> 00:07:17,320\nbox-and-pointer notation.\n\n128\n00:07:17,320 --> 00:07:21,190\nAnd you see, these are the three\ncells that have as their\n\n129\n00:07:21,190 --> 00:07:28,390\ncar pointer the object which\nis either 1, 2 or 3 or 4.\n\n130\n00:07:28,390 --> 00:07:30,860\nAnd then of course the 1, 2,\nthe car of this entire\n\n131\n00:07:30,860 --> 00:07:33,870\nstructure, is itself a\nsubstructure which contains a\n\n132\n00:07:33,870 --> 00:07:35,940\nsublist like that.\n\n133\n00:07:35,940 --> 00:07:39,970\nWhat I'm about to do is put\ndown places which are--\n\n134\n00:07:39,970 --> 00:07:41,880\nI'm going to assign indices.\n\n135\n00:07:41,880 --> 00:07:45,530\nLike this 1, over here,\nrepresents the\n\n136\n00:07:45,530 --> 00:07:46,850\nindex of this cell.\n\n137\n00:07:46,850 --> 00:07:49,850\n\n\n138\n00:07:49,850 --> 00:07:55,540\nBut that pointer that we see\nhere is a reference to the\n\n139\n00:07:55,540 --> 00:07:57,640\npair of pigeonholes in the cars\nand the cdrs that are\n\n140\n00:07:57,640 --> 00:08:02,000\nlabeled by 1 in my linear\nmemory down here.\n\n141\n00:08:02,000 --> 00:08:05,920\nSo if I wish to impose this\nstructure on my linear memory,\n\n142\n00:08:05,920 --> 00:08:08,780\nwhat I do is I say, oh yes,\nwhy don't we drop\n\n143\n00:08:08,780 --> 00:08:12,220\nthis into cell 1?\n\n144\n00:08:12,220 --> 00:08:12,660\nI pick one.\n\n145\n00:08:12,660 --> 00:08:14,270\nThere's 1.\n\n146\n00:08:14,270 --> 00:08:16,640\nAnd that says that its\ncar, I'm going to\n\n147\n00:08:16,640 --> 00:08:17,950\nassign it to be a pair.\n\n148\n00:08:17,950 --> 00:08:22,590\nIt's a pair, which\nis in index 5.\n\n149\n00:08:22,590 --> 00:08:26,360\nAnd the cdr, which is this one\nover here, is a pair which I'm\n\n150\n00:08:26,360 --> 00:08:28,340\ngoing to stick into place 2.\n\n151\n00:08:28,340 --> 00:08:30,890\np2.\n\n152\n00:08:30,890 --> 00:08:32,950\nAnd take a look at p2.\n\n153\n00:08:32,950 --> 00:08:37,550\nOh yes, well p2 is a thing whose\ncar is the number 3, so\n\n154\n00:08:37,550 --> 00:08:39,520\nas you see, an n3.\n\n155\n00:08:39,520 --> 00:08:46,640\nAnd whose cdr, over here, is a\npair, which lives in place 4.\n\n156\n00:08:46,640 --> 00:08:48,650\nSo that's what this p4 is.\n\n157\n00:08:48,650 --> 00:08:56,200\np4 is a number whose value is 4\nin its car and whose cdr is\n\n158\n00:08:56,200 --> 00:08:59,170\nan empty list right there.\n\n159\n00:08:59,170 --> 00:09:00,690\nAnd that ends it.\n\n160\n00:09:00,690 --> 00:09:05,750\nSo this is the traditional way\nof representing this kind of\n\n161\n00:09:05,750 --> 00:09:11,620\nbinary tree in a\nlinear memory.\n\n162\n00:09:11,620 --> 00:09:15,770\nNow the next question, of\ncourse, that we might want to\n\n163\n00:09:15,770 --> 00:09:18,440\nworry about is just a little\nbit of implementation.\n\n164\n00:09:18,440 --> 00:09:22,690\nThat means that when I write\nprocedures of the form\n\n165\n00:09:22,690 --> 00:09:24,600\nassigned a, [UNINTELLIGIBLE]\nprocedures--\n\n166\n00:09:24,600 --> 00:09:29,000\nlines of register machine code\nof the form assigned a, the\n\n167\n00:09:29,000 --> 00:09:30,140\ncar of [UNINTELLIGIBLE]\n\n168\n00:09:30,140 --> 00:09:38,740\nb, what I really mean is\naddressing these elements.\n\n169\n00:09:38,740 --> 00:09:44,470\nAnd so we're going to think of\nthat as a abbreviation for it.\n\n170\n00:09:44,470 --> 00:09:46,720\nNow of course in order to write\nthat down I'm going to\n\n171\n00:09:46,720 --> 00:09:49,140\nintroduce some sort of a\nstructure called a vector.\n\n172\n00:09:49,140 --> 00:09:52,120\n\n\n173\n00:09:52,120 --> 00:09:53,990\nAnd we're going to have\nsomething which will reference\n\n174\n00:09:53,990 --> 00:09:58,710\na vector, just so we\ncan write it down.\n\n175\n00:09:58,710 --> 00:10:02,240\nWhich takes the name of\nthe vector, or the--\n\n176\n00:10:02,240 --> 00:10:03,970\nI don't think that name\nis the right word.\n\n177\n00:10:03,970 --> 00:10:12,010\nWhich takes the vector and the\nindex, and I have to have a\n\n178\n00:10:12,010 --> 00:10:13,950\nway of setting one of those with\nsomething called a vector\n\n179\n00:10:13,950 --> 00:10:16,280\nset, I don't really care.\n\n180\n00:10:16,280 --> 00:10:19,520\nBut let's look, for example,\nat then that kind of\n\n181\n00:10:19,520 --> 00:10:26,470\nimplementation of car and cdr.\n\n182\n00:10:26,470 --> 00:10:31,470\nSo for example if I happen to\nhave a register b, which\n\n183\n00:10:31,470 --> 00:10:37,580\ncontains the type index of a\npair, and therefore it is the\n\n184\n00:10:37,580 --> 00:10:41,930\npointer to a pair, then I could\ntake the car of that and\n\n185\n00:10:41,930 --> 00:10:42,760\nif I-- write this down--\n\n186\n00:10:42,760 --> 00:10:44,490\nI might put that\nin register a.\n\n187\n00:10:44,490 --> 00:10:49,400\nWhat that really is is a\nrepresentation of the assign\n\n188\n00:10:49,400 --> 00:10:52,890\nto a, the value of\nvector reffing--\n\n189\n00:10:52,890 --> 00:10:54,700\nor array indexing,\nif you will-- or\n\n190\n00:10:54,700 --> 00:10:58,490\nsomething, the cars object--\n\n191\n00:10:58,490 --> 00:10:59,990\nwhatever that is--\n\n192\n00:10:59,990 --> 00:11:02,650\nwith the index, b.\n\n193\n00:11:02,650 --> 00:11:06,330\nAnd similarly for cdr. And we\ncan do the same thing for\n\n194\n00:11:06,330 --> 00:11:10,370\nassignment to data structures,\nif we need to do that sort of\n\n195\n00:11:10,370 --> 00:11:11,840\nthing at all.\n\n196\n00:11:11,840 --> 00:11:14,580\nIt's not too hard\nto build that.\n\n197\n00:11:14,580 --> 00:11:16,170\nWell now the next question\nis how are we going to do\n\n198\n00:11:16,170 --> 00:11:18,010\nallocation.\n\n199\n00:11:18,010 --> 00:11:21,550\nAnd every so often I\nsay I want a cons.\n\n200\n00:11:21,550 --> 00:11:23,790\nNow conses don't\ngrow on trees.\n\n201\n00:11:23,790 --> 00:11:25,340\nOr maybe they should.\n\n202\n00:11:25,340 --> 00:11:29,980\nBut I have to have some way\nof getting the next one.\n\n203\n00:11:29,980 --> 00:11:33,920\nI have to have some idea of if\ntheir memory is unused that I\n\n204\n00:11:33,920 --> 00:11:35,630\nmight want to allocate from.\n\n205\n00:11:35,630 --> 00:11:37,380\nAnd there are many schemes\nfor doing this.\n\n206\n00:11:37,380 --> 00:11:38,660\nAnd the particular thing\nI'm showing you\n\n207\n00:11:38,660 --> 00:11:42,100\nright now is not essential.\n\n208\n00:11:42,100 --> 00:11:44,960\nHowever it's convenient and\nhas been done many times.\n\n209\n00:11:44,960 --> 00:11:47,660\nOne scheme's was called the free\nlist allocation scheme.\n\n210\n00:11:47,660 --> 00:11:50,570\nWhat that means is that all of\nthe free memory that there is\n\n211\n00:11:50,570 --> 00:11:54,700\nin the world is linked together\nin a linked list,\n\n212\n00:11:54,700 --> 00:11:56,960\njust like all the other stuff.\n\n213\n00:11:56,960 --> 00:12:01,230\nAnd whenever you need a free\ncell to make a new cons, you\n\n214\n00:12:01,230 --> 00:12:04,440\ngrab the first, one make the\nfree list be the cdr of it,\n\n215\n00:12:04,440 --> 00:12:06,030\nand then allocate that.\n\n216\n00:12:06,030 --> 00:12:09,530\nAnd so what that looks like\nis something like this.\n\n217\n00:12:09,530 --> 00:12:18,510\nHere we have the free\nlist starting in 6.\n\n218\n00:12:18,510 --> 00:12:24,860\nAnd what that is is a\npointer-off to say 8.\n\n219\n00:12:24,860 --> 00:12:27,020\nSo what it says is, this\none is free and the\n\n220\n00:12:27,020 --> 00:12:28,870\nnext one is an 8.\n\n221\n00:12:28,870 --> 00:12:32,880\nThis one is free and the next\none is in 3, the next one\n\n222\n00:12:32,880 --> 00:12:33,930\nthat's free.\n\n223\n00:12:33,930 --> 00:12:37,680\nThat one's free and the\nnext one is in 0.\n\n224\n00:12:37,680 --> 00:12:40,940\nThat one's free and the\nnext one's in 15.\n\n225\n00:12:40,940 --> 00:12:42,780\nSomething like that.\n\n226\n00:12:42,780 --> 00:12:46,400\nWe can imagine having\nsuch a structure.\n\n227\n00:12:46,400 --> 00:12:50,480\nGiven that we have something\nlike that, then it's possible\n\n228\n00:12:50,480 --> 00:12:53,940\nto just get one when\nyou need it.\n\n229\n00:12:53,940 --> 00:12:57,960\nAnd so a program for doing\ncons, this is what\n\n230\n00:12:57,960 --> 00:12:59,320\ncons might turn into.\n\n231\n00:12:59,320 --> 00:13:05,410\nTo assign to a register A the\nresult of cons-ing, a B onto\n\n232\n00:13:05,410 --> 00:13:08,250\nC, the value in this containing\nB and the value\n\n233\n00:13:08,250 --> 00:13:11,240\ncontaining C, what we have\nto do is get the current\n\n234\n00:13:11,240 --> 00:13:13,400\n[? type ?] ahead of the\nfreelist, make the free list\n\n235\n00:13:13,400 --> 00:13:19,840\nbe its cdr. Then we have to\nchange the cars to be the\n\n236\n00:13:19,840 --> 00:13:25,680\nthing we're making up to be in A\nto be the B, the thing in B.\n\n237\n00:13:25,680 --> 00:13:30,880\nAnd we have to make change the\ncdrs of the thing that's in A\n\n238\n00:13:30,880 --> 00:13:36,020\nto be C. And then what we have\nin A is the right new frob,\n\n239\n00:13:36,020 --> 00:13:36,650\nwhatever it is.\n\n240\n00:13:36,650 --> 00:13:40,470\nThe object that we want.\n\n241\n00:13:40,470 --> 00:13:43,490\nNow there's a little bit of a\ncheat here that I haven't told\n\n242\n00:13:43,490 --> 00:13:47,155\nyou about, which is somewhere\naround here I haven't set that\n\n243\n00:13:47,155 --> 00:13:51,540\nI've the type of the thing that\nI'm cons-ing up to be a\n\n244\n00:13:51,540 --> 00:13:53,510\npair, and I ought to.\n\n245\n00:13:53,510 --> 00:13:56,570\nSo there should be some sort\nof bits here are being set,\n\n246\n00:13:56,570 --> 00:13:59,810\nand I just haven't written\nthat down.\n\n247\n00:13:59,810 --> 00:14:01,480\nWe could have arranged it, of\ncourse, for the free lift to\n\n248\n00:14:01,480 --> 00:14:03,100\nbe made out of pairs.\n\n249\n00:14:03,100 --> 00:14:06,430\nAnd so then there's no\nproblem with that.\n\n250\n00:14:06,430 --> 00:14:10,160\nBut that sort of-- again, an\ninessential detail in a way\n\n251\n00:14:10,160 --> 00:14:13,500\nsome particular programmer or\narchitect or whatever might\n\n252\n00:14:13,500 --> 00:14:17,540\nmanufacture his machine\nor Lisp system.\n\n253\n00:14:17,540 --> 00:14:23,930\nSo for example, just looking\nat this, to allocate given\n\n254\n00:14:23,930 --> 00:14:27,200\nthat I had already the structure\nthat you saw before,\n\n255\n00:14:27,200 --> 00:14:31,900\nsupposing I wanted to allocate\na new cell, which is going to\n\n256\n00:14:31,900 --> 00:14:38,680\nbe representation of list one,\none, two, where already one\n\n257\n00:14:38,680 --> 00:14:43,430\ntwo was the car of the list we\nwere playing with before.\n\n258\n00:14:43,430 --> 00:14:44,780\nWell that's not so hard.\n\n259\n00:14:44,780 --> 00:14:47,670\nI stored that one and one,\nso p1 one is the\n\n260\n00:14:47,670 --> 00:14:49,530\nrepresentation of this.\n\n261\n00:14:49,530 --> 00:14:51,690\nThis is p5.\n\n262\n00:14:51,690 --> 00:14:54,070\nThat's going to be\nthe cdr of this.\n\n263\n00:14:54,070 --> 00:14:55,610\nNow we're going to pull\nsomething off the free list,\n\n264\n00:14:55,610 --> 00:14:57,780\nbut remember the free\nlist started at six.\n\n265\n00:14:57,780 --> 00:15:01,540\nThe new free list after this\nallocation is eight, a free\n\n266\n00:15:01,540 --> 00:15:02,890\nlist beginning at eight.\n\n267\n00:15:02,890 --> 00:15:06,360\nAnd of course in six now we have\na number one, which is\n\n268\n00:15:06,360 --> 00:15:10,540\nwhat we wanted, with its cdr\nbeing the pair starting in\n\n269\n00:15:10,540 --> 00:15:13,330\nlocation five.\n\n270\n00:15:13,330 --> 00:15:16,810\nAnd that's no big deal.\n\n271\n00:15:16,810 --> 00:15:21,480\nSo the only problem really\nremaining here is, well, I\n\n272\n00:15:21,480 --> 00:15:25,080\ndon't have an infinitely\nlarge memory.\n\n273\n00:15:25,080 --> 00:15:28,070\nIf I do this for a little\nwhile, say, for example,\n\n274\n00:15:28,070 --> 00:15:30,745\nsupposing it takes me a\nmicrosecond to do a cons, and\n\n275\n00:15:30,745 --> 00:15:34,570\nI have a million cons memory\nthen I'm only going to run out\n\n276\n00:15:34,570 --> 00:15:38,000\nin a second, and that's\npretty bad.\n\n277\n00:15:38,000 --> 00:15:41,470\nSo what we do to prevent that\ndisaster, that ecological\n\n278\n00:15:41,470 --> 00:15:44,300\ndisaster, talk about right\nafter questions.\n\n279\n00:15:44,300 --> 00:15:45,550\nAre there any questions?\n\n280\n00:15:45,550 --> 00:15:51,500\n\n\n281\n00:15:51,500 --> 00:15:52,030\nYes.\n\n282\n00:15:52,030 --> 00:15:54,830\nAUDIENCE: In the environment\ndiagrams that we were drawing\n\n283\n00:15:54,830 --> 00:15:58,630\nwe would use the body of\nprocedures, and you would\n\n284\n00:15:58,630 --> 00:16:02,620\neventually wind up with things\nthat were no longer useful in\n\n285\n00:16:02,620 --> 00:16:04,930\nthat structure.\n\n286\n00:16:04,930 --> 00:16:06,890\nHow is that represented?\n\n287\n00:16:06,890 --> 00:16:09,180\nPROFESSOR: There's two\nproblems here.\n\n288\n00:16:09,180 --> 00:16:13,870\nOne you were asking is that\nmaterial becomes useless.\n\n289\n00:16:13,870 --> 00:16:14,920\nWe'll talk about that\nin a second.\n\n290\n00:16:14,920 --> 00:16:18,100\nThat has to do with how to\nprevent ecological disasters.\n\n291\n00:16:18,100 --> 00:16:20,190\nIf I make a lot of garbage I\nhave to somehow be able to\n\n292\n00:16:20,190 --> 00:16:21,820\nclean up after myself.\n\n293\n00:16:21,820 --> 00:16:23,430\nAnd we'll talk about\nthat in a second.\n\n294\n00:16:23,430 --> 00:16:25,370\nThe other question you're asking\nis how you represent\n\n295\n00:16:25,370 --> 00:16:27,210\nthe environments, I think.\n\n296\n00:16:27,210 --> 00:16:27,600\nAUDIENCE: Yes.\n\n297\n00:16:27,600 --> 00:16:28,190\nPROFESSOR: OK.\n\n298\n00:16:28,190 --> 00:16:29,780\nAnd the environment structures\ncan be represented in\n\n299\n00:16:29,780 --> 00:16:30,860\narbitrary ways.\n\n300\n00:16:30,860 --> 00:16:31,780\nThere are lots of them.\n\n301\n00:16:31,780 --> 00:16:33,630\nI mean, here I'm just telling\nyou about list cells.\n\n302\n00:16:33,630 --> 00:16:36,400\nOf course every real system\nhas vectors of arbitrary\n\n303\n00:16:36,400 --> 00:16:39,500\nlength as well as the vectors\nof length, too, which\n\n304\n00:16:39,500 --> 00:16:41,080\nrepresent list cells.\n\n305\n00:16:41,080 --> 00:16:45,460\nAnd the environment structures\nthat one uses in a\n\n306\n00:16:45,460 --> 00:16:49,890\nprofessionally written Lisp\nsystem tend to be vectors\n\n307\n00:16:49,890 --> 00:16:52,350\nwhich contain a number of\nelements approximately equal\n\n308\n00:16:52,350 --> 00:16:56,090\nto the number of arguments-- a\nlittle bit more because you\n\n309\n00:16:56,090 --> 00:16:58,290\nneed certain glue.\n\n310\n00:16:58,290 --> 00:17:00,360\nSo remember, the environment\n[UNINTELLIGIBLE]\n\n311\n00:17:00,360 --> 00:17:00,740\nframes.\n\n312\n00:17:00,740 --> 00:17:03,980\nThe frames are constructed\nby applying a procedure.\n\n313\n00:17:03,980 --> 00:17:08,849\nIn doing so, an allocation is\nmade of a place which is the\n\n314\n00:17:08,849 --> 00:17:11,270\nnumber of arguments long\nplus [? unglue ?]\n\n315\n00:17:11,270 --> 00:17:13,859\nthat gets linked into a chain.\n\n316\n00:17:13,859 --> 00:17:15,660\nIt's just like algol\nat that level.\n\n317\n00:17:15,660 --> 00:17:19,810\n\n\n318\n00:17:19,810 --> 00:17:21,060\nThere any other questions?\n\n319\n00:17:21,060 --> 00:17:23,700\n\n\n320\n00:17:23,700 --> 00:17:23,920\nOK.\n\n321\n00:17:23,920 --> 00:17:26,106\nThank you, and let's\ntake a short break.\n\n322\n00:17:26,106 --> 00:17:26,449\n[MUSIC-- \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n323\n00:17:26,449 --> 00:17:27,699\nJOHANN SEBASTIAN BACH]\n\n324\n00:17:27,699 --> 00:18:12,270\n\n\n325\n00:18:12,270 --> 00:18:15,840\nPROFESSOR: Well, as I just\nsaid, computer memories\n\n326\n00:18:15,840 --> 00:18:19,420\nsupplied by the semiconductor\nmanufacturers are finite.\n\n327\n00:18:19,420 --> 00:18:21,620\nAnd that's quite a pity.\n\n328\n00:18:21,620 --> 00:18:24,030\nIt might not always\nbe that way.\n\n329\n00:18:24,030 --> 00:18:27,990\nJust for a quick calculation,\nyou can see that it's possible\n\n330\n00:18:27,990 --> 00:18:28,860\nthat if [? memory ?]\n\n331\n00:18:28,860 --> 00:18:32,130\nprices keep going at the rate\nthey're going that if you\n\n332\n00:18:32,130 --> 00:18:34,950\nstill took a microsecond second\nto do a cons, then--\n\n333\n00:18:34,950 --> 00:18:37,120\nfirst of all, everybody should\nknow that there's about pi\n\n334\n00:18:37,120 --> 00:18:39,450\ntimes ten to the seventh\nseconds in a year.\n\n335\n00:18:39,450 --> 00:18:42,640\nAnd so that would be ten to the\nseventh plus ten to the\n\n336\n00:18:42,640 --> 00:18:43,940\nsixth is ten to the\nthirteenth.\n\n337\n00:18:43,940 --> 00:18:45,870\nSo there's maybe ten to the\nfourteenth conses in the life\n\n338\n00:18:45,870 --> 00:18:47,520\nof a machine.\n\n339\n00:18:47,520 --> 00:18:49,900\nIf there was ten to the\nfourteenth words of memory on\n\n340\n00:18:49,900 --> 00:18:54,020\nyour machine, you'd\nnever run out.\n\n341\n00:18:54,020 --> 00:18:56,310\nAnd that's not completely\nunreasonable.\n\n342\n00:18:56,310 --> 00:18:58,460\nTen to the fourteenth is not\na very large number.\n\n343\n00:18:58,460 --> 00:19:03,860\n\n\n344\n00:19:03,860 --> 00:19:05,180\nI don't think it is.\n\n345\n00:19:05,180 --> 00:19:08,700\nBut then again I like to\nplay with astronomy.\n\n346\n00:19:08,700 --> 00:19:11,380\nIt's at least ten to the\neighteenth centimeters between\n\n347\n00:19:11,380 --> 00:19:12,930\nus and the nearest star.\n\n348\n00:19:12,930 --> 00:19:19,620\nBut the thing I'm about to worry\nabout is, at least in\n\n349\n00:19:19,620 --> 00:19:22,130\nthe current economic state of\naffairs, ten to the fourteenth\n\n350\n00:19:22,130 --> 00:19:24,200\npieces of memory is expensive.\n\n351\n00:19:24,200 --> 00:19:27,280\nAnd so I suppose what we\nhave to do is make\n\n352\n00:19:27,280 --> 00:19:28,120\ndo with much smaller.\n\n353\n00:19:28,120 --> 00:19:30,170\nMemories\n\n354\n00:19:30,170 --> 00:19:35,800\nNow in general we want to have\nan illusion of infinity.\n\n355\n00:19:35,800 --> 00:19:38,850\nAll we need to do is arrange it\nso that whenever you look,\n\n356\n00:19:38,850 --> 00:19:40,100\nthe thing is there.\n\n357\n00:19:40,100 --> 00:19:42,670\n\n\n358\n00:19:42,670 --> 00:19:45,105\nThat's really an\nimportant idea.\n\n359\n00:19:45,105 --> 00:19:49,540\n\n\n360\n00:19:49,540 --> 00:19:52,470\nA person or a computer lives\nonly a finite amount of time\n\n361\n00:19:52,470 --> 00:19:55,280\nand can only take a finite\nnumber of looks at something.\n\n362\n00:19:55,280 --> 00:19:58,190\nAnd so you really only need\na finite amount of stuff.\n\n363\n00:19:58,190 --> 00:20:01,730\nBut you have to arrange it so\nno matter how much there is,\n\n364\n00:20:01,730 --> 00:20:04,000\nhow much you really claim\nthere is, there's always\n\n365\n00:20:04,000 --> 00:20:06,900\nenough stuff so that when you\ntake a look, it's there.\n\n366\n00:20:06,900 --> 00:20:08,750\nAnd so you only need\na finite amount.\n\n367\n00:20:08,750 --> 00:20:11,630\nBut let's see.\n\n368\n00:20:11,630 --> 00:20:14,980\nOne problem is, as was brought\nup, that there are possible\n\n369\n00:20:14,980 --> 00:20:18,660\nways that there is lots of stuff\nthat we make that we\n\n370\n00:20:18,660 --> 00:20:19,410\ndon't need.\n\n371\n00:20:19,410 --> 00:20:20,895\nAnd we could recycle\nthe material out\n\n372\n00:20:20,895 --> 00:20:22,760\nof which its made.\n\n373\n00:20:22,760 --> 00:20:27,820\nAn example is the fact that\nwe're building environment\n\n374\n00:20:27,820 --> 00:20:30,470\nstructures, and we do so every\ntime we call a procedure.\n\n375\n00:20:30,470 --> 00:20:32,810\nWe have built in it a\nenvironment frame.\n\n376\n00:20:32,810 --> 00:20:34,840\nThat environment frame\ndoesn't necessarily\n\n377\n00:20:34,840 --> 00:20:36,730\nhave a very long lifetime.\n\n378\n00:20:36,730 --> 00:20:40,330\nIts lifetime, meaning its\nusefulness, may exist only\n\n379\n00:20:40,330 --> 00:20:42,850\nover the invocation\nof the procedure.\n\n380\n00:20:42,850 --> 00:20:45,860\nOr if the procedure exports\nanother procedure by returning\n\n381\n00:20:45,860 --> 00:20:48,260\nit as a value and that procedure\nis defined inside of\n\n382\n00:20:48,260 --> 00:20:52,210\nit, well then the lifetime\nof the frame of the outer\n\n383\n00:20:52,210 --> 00:20:57,070\nprocedure still is only the\nlifetime of the procedure\n\n384\n00:20:57,070 --> 00:20:58,530\nwhich was exported.\n\n385\n00:20:58,530 --> 00:21:01,960\nAnd so ultimately, a lot\nof that is garbage.\n\n386\n00:21:01,960 --> 00:21:05,370\nThere are other ways of\nproducing garbage as well.\n\n387\n00:21:05,370 --> 00:21:07,240\nUsers produce garbage.\n\n388\n00:21:07,240 --> 00:21:10,930\nAn example of user garbage\nis something like this.\n\n389\n00:21:10,930 --> 00:21:15,220\nIf we write a program to, for\nexample, append two lists\n\n390\n00:21:15,220 --> 00:21:19,890\ntogether, well one way to do\nit is to reverse the first\n\n391\n00:21:19,890 --> 00:21:23,440\nlist onto the empty list and\nreverse that onto the second\n\n392\n00:21:23,440 --> 00:21:28,160\nlist. Now that's not terribly\nbad way of doing it.\n\n393\n00:21:28,160 --> 00:21:31,070\nAnd however, the intermediate\nresult, which is the reversal\n\n394\n00:21:31,070 --> 00:21:37,300\nof the first list as done by\nthis program, is never going\n\n395\n00:21:37,300 --> 00:21:39,920\nto be accessed ever again after\nit's copied back on to\n\n396\n00:21:39,920 --> 00:21:41,010\nthe second.\n\n397\n00:21:41,010 --> 00:21:43,580\nIt's an intermediate result.\n\n398\n00:21:43,580 --> 00:21:47,230\nIt's going to be hard to ever\nsee how anybody would ever be\n\n399\n00:21:47,230 --> 00:21:48,600\nable to access it.\n\n400\n00:21:48,600 --> 00:21:51,050\nIn fact, it will go away.\n\n401\n00:21:51,050 --> 00:21:53,190\nNow if we make a lot of garbage\nlike that, and we\n\n402\n00:21:53,190 --> 00:21:56,210\nshould be allowed to, then\nthere's got to be some way to\n\n403\n00:21:56,210 --> 00:21:58,800\nreclaim that garbage.\n\n404\n00:21:58,800 --> 00:22:03,050\nWell, what I'd like to tell you\nabout now is a very clever\n\n405\n00:22:03,050 --> 00:22:09,820\ntechnique whereby a Lisp system\ncan prove a small\n\n406\n00:22:09,820 --> 00:22:12,750\ntheorem every so often on the\n[? forum, ?] the following\n\n407\n00:22:12,750 --> 00:22:17,410\npiece of junk will never\nbe accessed again.\n\n408\n00:22:17,410 --> 00:22:21,400\nIt can have no affect on the\nfuture of the computation.\n\n409\n00:22:21,400 --> 00:22:24,920\nIt's actually based on\na very simple idea.\n\n410\n00:22:24,920 --> 00:22:28,570\nWe've designed our computers\nto look sort of like this.\n\n411\n00:22:28,570 --> 00:22:35,280\nThere's some data path, which\ncontains the registers.\n\n412\n00:22:35,280 --> 00:22:42,610\nThere are things like x, and\nenv, and val, and so on.\n\n413\n00:22:42,610 --> 00:22:47,490\nAnd there's one here called\nstack, some sort which points\n\n414\n00:22:47,490 --> 00:22:50,240\noff to a structure somewhere,\nwhich is the stack.\n\n415\n00:22:50,240 --> 00:22:51,740\nAnd we'll worry about\nthat in a second.\n\n416\n00:22:51,740 --> 00:22:55,390\nThere's some finite controller,\nfinite state\n\n417\n00:22:55,390 --> 00:22:56,730\nmachine controller.\n\n418\n00:22:56,730 --> 00:22:59,850\nAnd there's some control signals\nthat go this way and\n\n419\n00:22:59,850 --> 00:23:02,270\npredicate results that\ncome this way, not\n\n420\n00:23:02,270 --> 00:23:04,260\nthe interesting part.\n\n421\n00:23:04,260 --> 00:23:07,140\nThere's some sort of structured\nmemory, which I\n\n422\n00:23:07,140 --> 00:23:10,460\njust told you how to make, which\nmay contain a stack.\n\n423\n00:23:10,460 --> 00:23:12,690\nI didn't tell you how to make\nthings of arbitrary shape,\n\n424\n00:23:12,690 --> 00:23:13,450\nonly pairs.\n\n425\n00:23:13,450 --> 00:23:16,280\nBut in fact with what I've told\nyou can simulate a stack\n\n426\n00:23:16,280 --> 00:23:19,140\nby a big list. I don't plan\nto do that, it's not a\n\n427\n00:23:19,140 --> 00:23:20,360\nnice way to do it.\n\n428\n00:23:20,360 --> 00:23:22,990\nBut we could have something\nlike that.\n\n429\n00:23:22,990 --> 00:23:25,990\nWe have all sorts of little data\nstructures in here that\n\n430\n00:23:25,990 --> 00:23:27,470\nare hooked together\nin funny ways.\n\n431\n00:23:27,470 --> 00:23:30,115\n\n\n432\n00:23:30,115 --> 00:23:32,560\nThey connect to other things.\n\n433\n00:23:32,560 --> 00:23:33,250\nAnd so on.\n\n434\n00:23:33,250 --> 00:23:37,190\nAnd ultimately things up there\nare pointers to these.\n\n435\n00:23:37,190 --> 00:23:40,730\nThe things that are in the\nregisters are pointers off to\n\n436\n00:23:40,730 --> 00:23:44,910\nthe data structures that live in\nthis Lisp structure memory.\n\n437\n00:23:44,910 --> 00:23:52,660\nNow the truth of the matter is\nthat the entire consciousness\n\n438\n00:23:52,660 --> 00:23:55,550\nof this machine is in\nthese registers.\n\n439\n00:23:55,550 --> 00:23:59,380\nThere is no possible way that\nthe machine, if done\n\n440\n00:23:59,380 --> 00:24:02,410\ncorrectly, if built correctly,\ncan access anything in this\n\n441\n00:24:02,410 --> 00:24:05,580\nLisp structure memory unless\nthe thing in that Lisp\n\n442\n00:24:05,580 --> 00:24:10,310\nstructure memory is connected\nby a sequence of data\n\n443\n00:24:10,310 --> 00:24:15,070\nstructures to the registers.\n\n444\n00:24:15,070 --> 00:24:17,550\nIf it's accessible by legitimate\ndata structure\n\n445\n00:24:17,550 --> 00:24:20,100\nselectors from the\npointers that are\n\n446\n00:24:20,100 --> 00:24:22,280\nstored in these registers.\n\n447\n00:24:22,280 --> 00:24:24,940\nThings like array references,\nperhaps.\n\n448\n00:24:24,940 --> 00:24:28,790\nOr cons cell references,\ncars and cdrs.\n\n449\n00:24:28,790 --> 00:24:30,970\nBut I can't just talk about a\nrandom place in this memory,\n\n450\n00:24:30,970 --> 00:24:32,740\nbecause I can't get to it.\n\n451\n00:24:32,740 --> 00:24:34,665\nThese are being arbitrary\nnames I'm not allowed to\n\n452\n00:24:34,665 --> 00:24:38,985\ncount, at least as I'm\nevaluating expressions.\n\n453\n00:24:38,985 --> 00:24:41,620\n\n\n454\n00:24:41,620 --> 00:24:44,600\nIf that's the case then there's\na very simple theorem\n\n455\n00:24:44,600 --> 00:24:47,160\nto be proved.\n\n456\n00:24:47,160 --> 00:24:49,730\nWhich is, if I start with all\nlead pointers that are in all\n\n457\n00:24:49,730 --> 00:24:53,570\nthese registers and recursively\nchase out, marking\n\n458\n00:24:53,570 --> 00:24:57,980\nall the places I can get to by\nselectors, then eventually I\n\n459\n00:24:57,980 --> 00:25:00,750\nmark everything they\ncan be gotten to.\n\n460\n00:25:00,750 --> 00:25:02,140\nAnything which is\nnot so marked is\n\n461\n00:25:02,140 --> 00:25:05,560\ngarbage and can be recycled.\n\n462\n00:25:05,560 --> 00:25:07,200\nVery simple.\n\n463\n00:25:07,200 --> 00:25:11,180\nCannot affect the future\nof the computation.\n\n464\n00:25:11,180 --> 00:25:16,616\nSo let me show you that in\na particular example.\n\n465\n00:25:16,616 --> 00:25:19,800\nNow that means I'm going\nto have to append to my\n\n466\n00:25:19,800 --> 00:25:23,640\ndescription of the list\nstructure a mark.\n\n467\n00:25:23,640 --> 00:25:29,080\nAnd so here, for example, is\na Lisp structured memory.\n\n468\n00:25:29,080 --> 00:25:31,360\nAnd in this Lisp structured\nmemory is a Lisp structure\n\n469\n00:25:31,360 --> 00:25:33,030\nbeginning in a place\nI'm going to call--\n\n470\n00:25:33,030 --> 00:25:35,640\n\n\n471\n00:25:35,640 --> 00:25:38,590\nthis is the root.\n\n472\n00:25:38,590 --> 00:25:40,120\nNow it doesn't really\nhave to have a root.\n\n473\n00:25:40,120 --> 00:25:42,670\nIt could be a bunch of them,\nlike all the registers.\n\n474\n00:25:42,670 --> 00:25:45,270\nBut I could cleverly arrange it\nso all the registers, all\n\n475\n00:25:45,270 --> 00:25:47,080\nthe things that are in old\nregisters are also at the\n\n476\n00:25:47,080 --> 00:25:50,770\nright moment put into this root\nstructure, and then we've\n\n477\n00:25:50,770 --> 00:25:51,850\ngot one pointer to it.\n\n478\n00:25:51,850 --> 00:25:54,570\nI don't really care.\n\n479\n00:25:54,570 --> 00:25:57,290\nSo the idea is we're going to\ncons up stuff until our free\n\n480\n00:25:57,290 --> 00:25:58,720\nlist is empty.\n\n481\n00:25:58,720 --> 00:26:00,950\nWe've run out of things.\n\n482\n00:26:00,950 --> 00:26:04,560\nNow we're going to do this\nprocess of proving the theorem\n\n483\n00:26:04,560 --> 00:26:07,850\nthat a certain percentage of the\nmemory has got crap in it.\n\n484\n00:26:07,850 --> 00:26:10,320\nAnd then we're going to recycle\nthat to grow new\n\n485\n00:26:10,320 --> 00:26:14,570\ntrees, a standard use\nof such garbage.\n\n486\n00:26:14,570 --> 00:26:17,090\n\n\n487\n00:26:17,090 --> 00:26:18,840\nSo in any case, what\ndo we have here?\n\n488\n00:26:18,840 --> 00:26:21,700\nWell we have some data structure\nwhich starts out\n\n489\n00:26:21,700 --> 00:26:27,502\nover here one.\n\n490\n00:26:27,502 --> 00:26:33,980\nAnd in fact it has a car in\nfive, and its cdr is in two.\n\n491\n00:26:33,980 --> 00:26:36,700\nAnd all the marks start\nout at zero.\n\n492\n00:26:36,700 --> 00:26:39,920\nWell let's start marking,\njust to play this game.\n\n493\n00:26:39,920 --> 00:26:42,540\nOK.\n\n494\n00:26:42,540 --> 00:26:47,090\nSo for example, since I can\naccess one from the root I\n\n495\n00:26:47,090 --> 00:26:48,390\nwill mark that.\n\n496\n00:26:48,390 --> 00:26:50,960\nLet me mark it.\n\n497\n00:26:50,960 --> 00:26:52,430\nBang.\n\n498\n00:26:52,430 --> 00:26:54,560\nThat's marked.\n\n499\n00:26:54,560 --> 00:27:00,020\nNow since I have a five here I\ncan go to five and see, well\n\n500\n00:27:00,020 --> 00:27:01,450\nI'll mark that.\n\n501\n00:27:01,450 --> 00:27:01,760\nBang.\n\n502\n00:27:01,760 --> 00:27:02,900\nThat's useful stuff.\n\n503\n00:27:02,900 --> 00:27:05,410\nBut five references as a number\nin its car, I'm not\n\n504\n00:27:05,410 --> 00:27:08,700\ninterested in marking numbers\nbut its cdr is seven.\n\n505\n00:27:08,700 --> 00:27:10,450\nSo I can mark that.\n\n506\n00:27:10,450 --> 00:27:12,260\nBang.\n\n507\n00:27:12,260 --> 00:27:16,000\nSeven is the empty list, the\nonly thing that references,\n\n508\n00:27:16,000 --> 00:27:17,120\nand it's got a number\nin its car.\n\n509\n00:27:17,120 --> 00:27:19,490\nNot interesting.\n\n510\n00:27:19,490 --> 00:27:20,500\nWell now let's go back here.\n\n511\n00:27:20,500 --> 00:27:21,650\nI forgot about something.\n\n512\n00:27:21,650 --> 00:27:22,840\nTwo.\n\n513\n00:27:22,840 --> 00:27:25,960\nSee in other words, if I'm\nlooking at cell one, cell one\n\n514\n00:27:25,960 --> 00:27:30,370\ncontains a two right\nover here.\n\n515\n00:27:30,370 --> 00:27:31,730\nA reference to two.\n\n516\n00:27:31,730 --> 00:27:35,700\nThat means I should\ngo mark two.\n\n517\n00:27:35,700 --> 00:27:37,140\nBang.\n\n518\n00:27:37,140 --> 00:27:38,960\nTwo contains a reference\nto four.\n\n519\n00:27:38,960 --> 00:27:41,593\nIt's got a number in its car,\nI'm not interested in that, so\n\n520\n00:27:41,593 --> 00:27:43,780\nI'm going to go mark that.\n\n521\n00:27:43,780 --> 00:27:47,840\nFour refers to seven through its\ncar, and is empty in its\n\n522\n00:27:47,840 --> 00:27:49,990\ncdr, but I've already marked\nthat one so I don't have to\n\n523\n00:27:49,990 --> 00:27:51,400\nmark it again.\n\n524\n00:27:51,400 --> 00:27:55,000\nThis is all the accessible\nstructure from that place.\n\n525\n00:27:55,000 --> 00:27:58,710\nSimple recursive\nmark algorithm.\n\n526\n00:27:58,710 --> 00:28:01,160\nNow there are some unhappinesses\nabout that\n\n527\n00:28:01,160 --> 00:28:04,920\nalgorithm, and we can worry\nabout that a second.\n\n528\n00:28:04,920 --> 00:28:07,280\nBut basically you'll see that\nall the things that have not\n\n529\n00:28:07,280 --> 00:28:14,220\nbeen marked are places that are\nfree, and I could recycle.\n\n530\n00:28:14,220 --> 00:28:16,210\nSo the next stage after that is\ngoing to be to scan through\n\n531\n00:28:16,210 --> 00:28:21,180\nall of my memory, looking for\nthings that are not marked.\n\n532\n00:28:21,180 --> 00:28:23,370\nEvery time I come across a\nmarked thing I unmark it, and\n\n533\n00:28:23,370 --> 00:28:26,390\nevery time I come across an\nunmarked thing I'm going to\n\n534\n00:28:26,390 --> 00:28:28,770\nlink it together in\nmy free list.\n\n535\n00:28:28,770 --> 00:28:32,120\nClassic, very simple algorithm.\n\n536\n00:28:32,120 --> 00:28:33,840\nSo let's see.\n\n537\n00:28:33,840 --> 00:28:34,770\nIs that very simple?\n\n538\n00:28:34,770 --> 00:28:35,570\nYes it is.\n\n539\n00:28:35,570 --> 00:28:38,340\nI'm not going to go through the\ncode in any detail, but I\n\n540\n00:28:38,340 --> 00:28:40,090\njust want to show you about\nhow long it is.\n\n541\n00:28:40,090 --> 00:28:42,490\nLet's look at the mark phase.\n\n542\n00:28:42,490 --> 00:28:45,060\nHere's the first part\nof the mark phase.\n\n543\n00:28:45,060 --> 00:28:48,280\nWe pick up the root.\n\n544\n00:28:48,280 --> 00:28:52,380\nWe're going to use that as a\nrecursive procedure call.\n\n545\n00:28:52,380 --> 00:28:55,800\nWe're going to sweep from there,\nafter when we're done\n\n546\n00:28:55,800 --> 00:28:57,380\nwith marking.\n\n547\n00:28:57,380 --> 00:28:59,840\nAnd then we're going to do a\nlittle couple of instructions\n\n548\n00:28:59,840 --> 00:29:01,920\nthat do this checking out on\nthe marks and changing the\n\n549\n00:29:01,920 --> 00:29:04,000\nmarks and things like that,\naccording to the algorithm\n\n550\n00:29:04,000 --> 00:29:05,500\nI've just shown you.\n\n551\n00:29:05,500 --> 00:29:06,470\nIt comes out here.\n\n552\n00:29:06,470 --> 00:29:08,800\nYou have to mark the cars of\nthings and you also have to be\n\n553\n00:29:08,800 --> 00:29:10,660\nable to mark the\ncdrs of things.\n\n554\n00:29:10,660 --> 00:29:14,370\nThat's the entire mark phase.\n\n555\n00:29:14,370 --> 00:29:16,590\nI'll just tell you a little\nstory about this.\n\n556\n00:29:16,590 --> 00:29:22,950\nThe old DEC PDP-6 computer,\nthis was the way that the\n\n557\n00:29:22,950 --> 00:29:26,740\nmark-sweep garbage collection,\nas it was, was written.\n\n558\n00:29:26,740 --> 00:29:31,940\nThe program was so small that\nwith the data that it needed,\n\n559\n00:29:31,940 --> 00:29:34,310\nwith the registers that it\nneeded to manipulate the\n\n560\n00:29:34,310 --> 00:29:38,070\nmemory, it fit into the fast\nregisters of the machine,\n\n561\n00:29:38,070 --> 00:29:39,280\nwhich were 16.\n\n562\n00:29:39,280 --> 00:29:39,800\nThe whole program.\n\n563\n00:29:39,800 --> 00:29:40,700\nAnd you could execute\n\n564\n00:29:40,700 --> 00:29:43,170\ninstructions in the fast registers.\n\n565\n00:29:43,170 --> 00:29:46,560\nSo it's an extremely small\nprogram, and it could run very\n\n566\n00:29:46,560 --> 00:29:48,870\nfast.\n\n567\n00:29:48,870 --> 00:29:53,130\nNow unfortunately, of course,\nthis program, because the fact\n\n568\n00:29:53,130 --> 00:29:57,630\nthat it's recursive in the way\nthat you do something first\n\n569\n00:29:57,630 --> 00:29:59,690\nand then you do something after\nthat, you have to work\n\n570\n00:29:59,690 --> 00:30:03,410\non the cars and then the cdrs,\nit requires auxiliary memory.\n\n571\n00:30:03,410 --> 00:30:05,680\nSo Lisp systems--\n\n572\n00:30:05,680 --> 00:30:08,260\nthose requires a stack\nfor marking.\n\n573\n00:30:08,260 --> 00:30:12,440\nLisp systems that are built this\nway have a limit to the\n\n574\n00:30:12,440 --> 00:30:16,060\ndepth of recursion you can have\nin data structures in\n\n575\n00:30:16,060 --> 00:30:19,930\neither the car or the cdr, and\nthat doesn't work very nicely.\n\n576\n00:30:19,930 --> 00:30:23,180\nOn the other hand, you never\nnotice it if it's big enough.\n\n577\n00:30:23,180 --> 00:30:27,650\nAnd that's certainly been the\ncase for most Maclisp, for\n\n578\n00:30:27,650 --> 00:30:30,760\nexample, which ran Macsyma\nwhere you could deal with\n\n579\n00:30:30,760 --> 00:30:33,560\nexpressions of thousands\nof elements long.\n\n580\n00:30:33,560 --> 00:30:35,490\nThese are algebraic expressions\nwith thousand of\n\n581\n00:30:35,490 --> 00:30:39,490\nterms. And there's no\nproblem with that.\n\n582\n00:30:39,490 --> 00:30:42,190\nSuch, the garbage collector\ndoes work.\n\n583\n00:30:42,190 --> 00:30:44,750\nOn the other hand, there's a\nvery clever modification to\n\n584\n00:30:44,750 --> 00:30:49,020\nthis algorithm, which I will not\ndescribe, by Peter Deutsch\n\n585\n00:30:49,020 --> 00:30:50,720\nand Schorr and Waite--\n\n586\n00:30:50,720 --> 00:30:55,380\nHerb Schorr from IBM and Waite,\nwho I don't know.\n\n587\n00:30:55,380 --> 00:30:58,470\nThat algorithm allows you to\nbuild-- you do can do this\n\n588\n00:30:58,470 --> 00:31:01,990\nwithout auxiliary memory, by\nremembering as you walk the\n\n589\n00:31:01,990 --> 00:31:04,760\ndata structures where you came\nfrom by reversing the pointers\n\n590\n00:31:04,760 --> 00:31:06,650\nas you go down and crawling\nup the reverse\n\n591\n00:31:06,650 --> 00:31:07,520\npointers as you go up.\n\n592\n00:31:07,520 --> 00:31:09,130\nIt's a rather tricky\nalgorithm.\n\n593\n00:31:09,130 --> 00:31:11,230\nThe first time you write it--\nor in fact, the first three\n\n594\n00:31:11,230 --> 00:31:14,350\ntimes you write it it has\na terrible bug in it.\n\n595\n00:31:14,350 --> 00:31:18,110\nAnd it's also rather slow,\nbecause it's complicated.\n\n596\n00:31:18,110 --> 00:31:21,150\nIt takes about six times as many\nmemory references to do\n\n597\n00:31:21,150 --> 00:31:24,580\nthe sorts of things that\nwe're talking about.\n\n598\n00:31:24,580 --> 00:31:28,140\nWell now once I've done this\nmarking phase, and I get into\n\n599\n00:31:28,140 --> 00:31:30,920\na position where things look\nlike this, let's look--\n\n600\n00:31:30,920 --> 00:31:31,510\nyes.\n\n601\n00:31:31,510 --> 00:31:35,590\nHere we have the mark done,\njust as I did it.\n\n602\n00:31:35,590 --> 00:31:37,330\nNow we have to perform\nthe sweep phase.\n\n603\n00:31:37,330 --> 00:31:39,820\nAnd I described to you what\nthis sweep is like.\n\n604\n00:31:39,820 --> 00:31:42,130\nI'm going to walk down from\none end of memory or the\n\n605\n00:31:42,130 --> 00:31:45,690\nother, I don't care where,\nscanning every cell that's in\n\n606\n00:31:45,690 --> 00:31:46,836\nthe memory.\n\n607\n00:31:46,836 --> 00:31:51,000\nAnd as I scan these cells, I'm\ngoing to link them together,\n\n608\n00:31:51,000 --> 00:31:53,890\nif they are free, into the free\nlist. And if they're not\n\n609\n00:31:53,890 --> 00:31:57,500\nfree, I'm going to unmark them\nso the marks become zero.\n\n610\n00:31:57,500 --> 00:32:00,050\nAnd in fact what I get-- well\nthe program is not very\n\n611\n00:32:00,050 --> 00:32:00,460\ncomplicated.\n\n612\n00:32:00,460 --> 00:32:02,780\nIt looks sort of like this--\nit's a little longer.\n\n613\n00:32:02,780 --> 00:32:04,820\nHere's the first piece of it.\n\n614\n00:32:04,820 --> 00:32:06,710\nThis one's coming down from\nthe top of memory.\n\n615\n00:32:06,710 --> 00:32:09,580\nI don't want you to try to\nunderstand this at this point.\n\n616\n00:32:09,580 --> 00:32:11,030\nIt's rather simple.\n\n617\n00:32:11,030 --> 00:32:14,260\nIt's a very simple algorithm,\nbut there's pieces of it that\n\n618\n00:32:14,260 --> 00:32:15,970\njust sort of look like this.\n\n619\n00:32:15,970 --> 00:32:18,600\nThey're all sort of obvious.\n\n620\n00:32:18,600 --> 00:32:21,060\nAnd after we've done the sweep,\nwe get an answer that\n\n621\n00:32:21,060 --> 00:32:22,310\nlooks like that.\n\n622\n00:32:22,310 --> 00:32:25,330\n\n\n623\n00:32:25,330 --> 00:32:27,150\nNow there are some disadvantages\nwith mark-sweep\n\n624\n00:32:27,150 --> 00:32:29,590\nalgorithms of this sort.\n\n625\n00:32:29,590 --> 00:32:31,940\nSerious ones.\n\n626\n00:32:31,940 --> 00:32:34,250\nOne important disadvantage is\nthat your memories get larger\n\n627\n00:32:34,250 --> 00:32:36,498\nand larger.\n\n628\n00:32:36,498 --> 00:32:39,100\nAs you say, address spaces get\nlarger and larger, you're\n\n629\n00:32:39,100 --> 00:32:43,080\nwilling to represent more and\nmore stuff, then it gets very\n\n630\n00:32:43,080 --> 00:32:46,360\ncostly to scan all of memory.\n\n631\n00:32:46,360 --> 00:32:50,490\nWhat you'd really like to do\nis only scan useful stuff.\n\n632\n00:32:50,490 --> 00:32:56,120\nIt would even be better if you\nrealized that some stuff was\n\n633\n00:32:56,120 --> 00:32:59,320\nknown to be good and useful, and\nyou don't have to look at\n\n634\n00:32:59,320 --> 00:33:00,370\nit more than once or twice.\n\n635\n00:33:00,370 --> 00:33:01,550\nOr very rarely.\n\n636\n00:33:01,550 --> 00:33:05,120\nWhereas other stuff that you're\nnot so sure about, you\n\n637\n00:33:05,120 --> 00:33:10,110\ncan look at more detail every\ntime you want to do this, want\n\n638\n00:33:10,110 --> 00:33:11,910\nto garbage collect.\n\n639\n00:33:11,910 --> 00:33:15,660\nWell there are algorithms that\nare organized in this way.\n\n640\n00:33:15,660 --> 00:33:18,850\nLet me tell you about a famous\nold algorithm which allows you\n\n641\n00:33:18,850 --> 00:33:20,370\nonly look at the part\nof memory which\n\n642\n00:33:20,370 --> 00:33:22,800\nis known to be useful.\n\n643\n00:33:22,800 --> 00:33:24,690\nAnd which happens to be the\nfastest known garbage\n\n644\n00:33:24,690 --> 00:33:26,310\ncollector algorithm.\n\n645\n00:33:26,310 --> 00:33:28,170\nThis is the\nMinsky-Feinchel-Yochelson\n\n646\n00:33:28,170 --> 00:33:30,150\ngarbage collector algorithm.\n\n647\n00:33:30,150 --> 00:33:36,660\nIt was invented by Minsky in\n1961 or '60 or something, for\n\n648\n00:33:36,660 --> 00:33:45,870\nthe RLE PDP-1 Lisp, which had\n4,096 words of list memory,\n\n649\n00:33:45,870 --> 00:33:48,480\nand a drum.\n\n650\n00:33:48,480 --> 00:33:50,890\nAnd the whole idea was\nto garbage collect\n\n651\n00:33:50,890 --> 00:33:53,380\nthis terrible memory.\n\n652\n00:33:53,380 --> 00:33:56,510\nWhat Minsky realized was the\neasiest way to do this is to\n\n653\n00:33:56,510 --> 00:33:59,950\nscan the memory in the same\nsense, walking the good\n\n654\n00:33:59,950 --> 00:34:06,350\nstructure, copying it out into\nthe drum, compacted.\n\n655\n00:34:06,350 --> 00:34:09,429\nAnd then when we were done\ncopying it all out, then you\n\n656\n00:34:09,429 --> 00:34:12,300\nswap that back into\nyour memory.\n\n657\n00:34:12,300 --> 00:34:14,260\nNow whether or you not use a\ndrum, or another piece of\n\n658\n00:34:14,260 --> 00:34:17,030\nmemory, or something like\nthat isn't important.\n\n659\n00:34:17,030 --> 00:34:18,260\nIn fact, I don't think\npeople use\n\n660\n00:34:18,260 --> 00:34:20,350\ndrums anymore for anything.\n\n661\n00:34:20,350 --> 00:34:25,920\nBut this algorithm basically\ndepends upon having about\n\n662\n00:34:25,920 --> 00:34:30,270\ntwice as much address space\nas you're actually using.\n\n663\n00:34:30,270 --> 00:34:35,370\nAnd so what you have is some,\ninitially, some mixture of\n\n664\n00:34:35,370 --> 00:34:37,110\nuseful data and garbage.\n\n665\n00:34:37,110 --> 00:34:38,560\nSo this is called fromspace.\n\n666\n00:34:38,560 --> 00:34:45,179\n\n\n667\n00:34:45,179 --> 00:34:47,800\nAnd this is a mixture of crud.\n\n668\n00:34:47,800 --> 00:34:52,000\nSome of it's important\nand some of it isn't.\n\n669\n00:34:52,000 --> 00:34:55,770\nNow there's another place which\nis hopefully big enough,\n\n670\n00:34:55,770 --> 00:34:58,240\nif we recall, tospace, which\nis where we're copying to.\n\n671\n00:34:58,240 --> 00:35:01,590\n\n\n672\n00:35:01,590 --> 00:35:03,260\nAnd what happens is-- and\nI'm not going to go\n\n673\n00:35:03,260 --> 00:35:04,970\nthrough this detail.\n\n674\n00:35:04,970 --> 00:35:07,590\nIt's in our book quite\nexplicitly.\n\n675\n00:35:07,590 --> 00:35:11,030\nThere's a root point where\nyou start from.\n\n676\n00:35:11,030 --> 00:35:14,600\nAnd the idea is that you\nstart with the root.\n\n677\n00:35:14,600 --> 00:35:18,610\nYou copy the first thing you\nsee, the first thing that the\n\n678\n00:35:18,610 --> 00:35:22,810\nroot points at, to the\nbeginning of tospace.\n\n679\n00:35:22,810 --> 00:35:24,790\nThe first thing is a\npair or something\n\n680\n00:35:24,790 --> 00:35:27,560\nlike, a data structure.\n\n681\n00:35:27,560 --> 00:35:32,330\nYou then also leave behind a\nbroken heart saying, I moved\n\n682\n00:35:32,330 --> 00:35:36,330\nthis object from here to\nhere, giving the place\n\n683\n00:35:36,330 --> 00:35:37,800\nwhere it moved to.\n\n684\n00:35:37,800 --> 00:35:40,270\nThis is called a broken heart\nbecause a friend of mine who\n\n685\n00:35:40,270 --> 00:35:44,760\nimplemented one of these in\n1966 was a very romantic\n\n686\n00:35:44,760 --> 00:35:46,760\ncharacter and called\nit a broken heart.\n\n687\n00:35:46,760 --> 00:35:49,580\n\n\n688\n00:35:49,580 --> 00:35:53,570\nBut in any case, the next thing\nyou do is now you have a\n\n689\n00:35:53,570 --> 00:35:57,840\nnew free pointer which is here,\nand you start scanning.\n\n690\n00:35:57,840 --> 00:36:00,235\nYou scan this data structure\nyou just copied.\n\n691\n00:36:00,235 --> 00:36:02,710\nAnd every time you encounter a\npointer in it, you treat it as\n\n692\n00:36:02,710 --> 00:36:04,000\nif it was the root\npointer here.\n\n693\n00:36:04,000 --> 00:36:05,170\nOh, I'm sorry.\n\n694\n00:36:05,170 --> 00:36:06,330\nThe other thing you do\nis you now move the\n\n695\n00:36:06,330 --> 00:36:09,220\nroot pointer to there.\n\n696\n00:36:09,220 --> 00:36:11,310\nSo now you scan this, and\neverything you see you treat\n\n697\n00:36:11,310 --> 00:36:14,110\nas it were the root pointer.\n\n698\n00:36:14,110 --> 00:36:16,360\nSo if you see something,\nwell it points\n\n699\n00:36:16,360 --> 00:36:18,510\nup into there somewhere.\n\n700\n00:36:18,510 --> 00:36:21,780\nIs it pointing at a thing which\nyou've not copied yet?\n\n701\n00:36:21,780 --> 00:36:23,880\nIs there a broken heart there?\n\n702\n00:36:23,880 --> 00:36:25,370\nIf there's a broken heart there\nand it's something you\n\n703\n00:36:25,370 --> 00:36:27,640\nhave copied, you've just\nreplaced this pointer with the\n\n704\n00:36:27,640 --> 00:36:30,620\nthing a broken heart\npoints at.\n\n705\n00:36:30,620 --> 00:36:33,030\nIf this thing has not been\ncopied, you copy it to the\n\n706\n00:36:33,030 --> 00:36:34,430\nnext place over here.\n\n707\n00:36:34,430 --> 00:36:39,860\nMove your free pointer over\nhere, and then leave a broken\n\n708\n00:36:39,860 --> 00:36:43,670\nheart behind and scan.\n\n709\n00:36:43,670 --> 00:36:46,840\nAnd eventually when the scant\npointer hits the free pointer,\n\n710\n00:36:46,840 --> 00:36:50,140\neverything in memory\nhas been copied.\n\n711\n00:36:50,140 --> 00:36:52,170\nAnd then there's a whole bunch\nof empty space up here, which\n\n712\n00:36:52,170 --> 00:36:53,820\nyou could either make into a\nfree list, if that's what you\n\n713\n00:36:53,820 --> 00:36:54,470\nwant to do.\n\n714\n00:36:54,470 --> 00:36:56,270\nBut generally you don't in\nthis kind of system.\n\n715\n00:36:56,270 --> 00:36:57,470\nIn this system you sequentially\n\n716\n00:36:57,470 --> 00:37:00,910\nallocate your memory.\n\n717\n00:37:00,910 --> 00:37:03,820\nThat is a very, very nice\nalgorithm, and sort of the one\n\n718\n00:37:03,820 --> 00:37:06,790\nwe use in the scheme that\nyou've been using.\n\n719\n00:37:06,790 --> 00:37:09,490\nAnd it's expected--\n\n720\n00:37:09,490 --> 00:37:12,400\nI believe no one has found a\nfaster algorithm than that.\n\n721\n00:37:12,400 --> 00:37:14,150\nThere are very simple\nmodifications to this\n\n722\n00:37:14,150 --> 00:37:19,060\nalgorithm invented by Henry\nBaker which allow one to run\n\n723\n00:37:19,060 --> 00:37:21,210\nthis algorithm in real time,\nmeaning you don't have to stop\n\n724\n00:37:21,210 --> 00:37:22,010\nto garbage collect.\n\n725\n00:37:22,010 --> 00:37:25,410\nBut you could interleave the\nconsing that the machine does\n\n726\n00:37:25,410 --> 00:37:27,870\nwhen its running with steps\nof the garbage collection\n\n727\n00:37:27,870 --> 00:37:31,370\nprocess, so that the garbage\ncollector's distributed, and\n\n728\n00:37:31,370 --> 00:37:32,980\nthe machine doesn't have\nto stop, and garbage\n\n729\n00:37:32,980 --> 00:37:34,640\ncollecting can start.\n\n730\n00:37:34,640 --> 00:37:37,520\nOf course in the case of\nmachines with virtual memory\n\n731\n00:37:37,520 --> 00:37:41,760\nwhere a lot of it is in\ninaccessible places, this\n\n732\n00:37:41,760 --> 00:37:44,460\nbecomes a very expensive\nprocess.\n\n733\n00:37:44,460 --> 00:37:47,690\nAnd there have been numerous\nattempts to\n\n734\n00:37:47,690 --> 00:37:49,190\nmake this much better.\n\n735\n00:37:49,190 --> 00:37:52,080\nThere is a nice paper, for\nthose of you who are\n\n736\n00:37:52,080 --> 00:37:56,210\ninterested, by Moon and other\npeople which describes a\n\n737\n00:37:56,210 --> 00:37:57,940\nmodification to the\nincremental\n\n738\n00:37:57,940 --> 00:38:00,290\nMinsky-Feinchel-Yochelson\nalgorithm, and modification\n\n739\n00:38:00,290 --> 00:38:05,980\nthe Baker algorithm which is\nmore efficient for virtual\n\n740\n00:38:05,980 --> 00:38:08,340\nmemory systems.\n\n741\n00:38:08,340 --> 00:38:12,840\nWell I think now the mystery\nto this is sort of gone.\n\n742\n00:38:12,840 --> 00:38:14,090\nAnd I'd like to see if there\nare any questions.\n\n743\n00:38:14,090 --> 00:38:19,780\n\n\n744\n00:38:19,780 --> 00:38:20,810\nYes.\n\n745\n00:38:20,810 --> 00:38:24,100\nAUDIENCE: I saw one of you run\nthe garbage collector on the\n\n746\n00:38:24,100 --> 00:38:27,640\nsystems upstairs, and it seemed\nto me to run extremely\n\n747\n00:38:27,640 --> 00:38:30,190\nfast. Did the whole\nthing take--\n\n748\n00:38:30,190 --> 00:38:31,880\ndoes it sweep through\nall of memory?\n\n749\n00:38:31,880 --> 00:38:32,510\nPROFESSOR: No.\n\n750\n00:38:32,510 --> 00:38:34,480\nIt swept through exactly\nwhat was needed to\n\n751\n00:38:34,480 --> 00:38:37,320\ncopy the useful structure.\n\n752\n00:38:37,320 --> 00:38:40,030\nIt's a copying collector.\n\n753\n00:38:40,030 --> 00:38:45,090\nAnd it is very fast. On the\nwhole, I suppose to copy--\n\n754\n00:38:45,090 --> 00:38:47,000\nin a Bobcat--\n\n755\n00:38:47,000 --> 00:38:52,450\nto copy, I think, a three\nmegabyte thing or something is\n\n756\n00:38:52,450 --> 00:38:56,800\nless than a second, real time.\n\n757\n00:38:56,800 --> 00:38:59,200\nReally, these are very small\nprograms. One thing you should\n\n758\n00:38:59,200 --> 00:39:05,400\nrealise is that garbage\ncollectors have to be small.\n\n759\n00:39:05,400 --> 00:39:08,770\nNot because they have to be\nfast, but because no one can\n\n760\n00:39:08,770 --> 00:39:11,340\ndebug a complicated\ngarbage collector.\n\n761\n00:39:11,340 --> 00:39:15,000\nA garbage collector, if it\ndoesn't work, will trash your\n\n762\n00:39:15,000 --> 00:39:16,940\nmemory in such a way that you\ncannot figure out what the\n\n763\n00:39:16,940 --> 00:39:18,350\nhell happened.\n\n764\n00:39:18,350 --> 00:39:20,660\nYou need an audit trail.\n\n765\n00:39:20,660 --> 00:39:22,460\nBecause it rearranges\neverything, and how do you\n\n766\n00:39:22,460 --> 00:39:23,740\nknow what happened there?\n\n767\n00:39:23,740 --> 00:39:27,480\nSo this is the only kind of\nprogram that it really,\n\n768\n00:39:27,480 --> 00:39:30,100\nseriously matters if you stare\nat it long enough so you\n\n769\n00:39:30,100 --> 00:39:31,970\nbelieve that it works.\n\n770\n00:39:31,970 --> 00:39:35,100\nAnd sort of prove\nit to yourself.\n\n771\n00:39:35,100 --> 00:39:36,940\nSo there's no way to debug it.\n\n772\n00:39:36,940 --> 00:39:39,230\nAnd that takes it being small\nenough so you can\n\n773\n00:39:39,230 --> 00:39:41,690\nhold it in your head.\n\n774\n00:39:41,690 --> 00:39:45,020\nGarbage collectors are\nspecial in this way.\n\n775\n00:39:45,020 --> 00:39:47,130\nSo every reasonable garbage\ncollector has gotten small,\n\n776\n00:39:47,130 --> 00:39:52,430\nand generally small programs\nare fast. Yes.\n\n777\n00:39:52,430 --> 00:39:53,650\nAUDIENCE: Can you repeat\nthe name of this\n\n778\n00:39:53,650 --> 00:39:54,510\ntechnique once again?\n\n779\n00:39:54,510 --> 00:39:56,220\nPROFESSOR: That's the\nMinsky-Feinchel-Yochelson\n\n780\n00:39:56,220 --> 00:39:58,420\ngarbage collector.\n\n781\n00:39:58,420 --> 00:39:59,340\nAUDIENCE: You got that?\n\n782\n00:39:59,340 --> 00:40:02,210\nPROFESSOR: Minsky invented it\nin '61 for the RLE PDP-1.\n\n783\n00:40:02,210 --> 00:40:07,410\nA version of it was developed\nand elaborated to be used in\n\n784\n00:40:07,410 --> 00:40:12,410\nMultics Maclisp by Feinchel\nand Yochelson in somewhere\n\n785\n00:40:12,410 --> 00:40:19,570\naround 1968 or '69.\n\n786\n00:40:19,570 --> 00:40:20,650\nOK.\n\n787\n00:40:20,650 --> 00:40:22,640\nLet's take a break.\n\n788\n00:40:22,640 --> 00:40:22,934\n[MUSIC: \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n789\n00:40:22,934 --> 00:40:24,184\nJOHANN SEBASTIAN BACH]\n\n790\n00:40:24,184 --> 00:41:17,310\n\n\n791\n00:41:17,310 --> 00:41:21,600\nPROFESSOR: Well we've come to\nthe end of this subject, and\n\n792\n00:41:21,600 --> 00:41:24,860\nwe've already shown you a\nuniversal machine which is\n\n793\n00:41:24,860 --> 00:41:26,740\ndown to evaluator.\n\n794\n00:41:26,740 --> 00:41:28,980\nIt's down to the level of detail\nyou could imagine you\n\n795\n00:41:28,980 --> 00:41:30,420\ncould make one.\n\n796\n00:41:30,420 --> 00:41:34,390\nThis is a particular\nimplementation of Lisp, built\n\n797\n00:41:34,390 --> 00:41:37,530\non one of those scheme chips\nthat was talked about\n\n798\n00:41:37,530 --> 00:41:39,180\nyesterday, sitting over here.\n\n799\n00:41:39,180 --> 00:41:42,990\nThis is mostly interface to\nsomebody's memory with a\n\n800\n00:41:42,990 --> 00:41:45,010\nlittle bit of timing and\nother such stuff.\n\n801\n00:41:45,010 --> 00:41:48,760\nBut this fellow actually ran\nLisp at a fairly reasonable\n\n802\n00:41:48,760 --> 00:41:50,610\nrate, as interpretive.\n\n803\n00:41:50,610 --> 00:41:56,500\nIt ran Lisp as fast as a DEC\nPDP-10 back in 1979.\n\n804\n00:41:56,500 --> 00:41:59,870\nAnd so it's gotten\npretty hardware.\n\n805\n00:41:59,870 --> 00:42:02,470\nPretty concrete.\n\n806\n00:42:02,470 --> 00:42:05,000\nWe've also downed you\na bit with the\n\n807\n00:42:05,000 --> 00:42:07,370\nthings you can compute.\n\n808\n00:42:07,370 --> 00:42:11,850\nBut is it the case that there\nare things we can't compute?\n\n809\n00:42:11,850 --> 00:42:14,690\nAnd so I'd like to end this with\nshowing you some things\n\n810\n00:42:14,690 --> 00:42:18,190\nthat you'd like be able to\ncompute that you can't.\n\n811\n00:42:18,190 --> 00:42:22,720\nThe answer is yes, there are\nthings you can't compute.\n\n812\n00:42:22,720 --> 00:42:28,200\nFor example, something you'd\nreally like is--\n\n813\n00:42:28,200 --> 00:42:30,210\nif you're writing\n[UNINTELLIGIBLE], you'd like a\n\n814\n00:42:30,210 --> 00:42:32,800\nprogram that would check\nthat the thing you're\n\n815\n00:42:32,800 --> 00:42:34,630\ngoing to do will work.\n\n816\n00:42:34,630 --> 00:42:36,080\nWouldn't that be nice?\n\n817\n00:42:36,080 --> 00:42:37,960\nYou'd like something that would\ncatch infinite loops,\n\n818\n00:42:37,960 --> 00:42:43,190\nfor example, in programs that\nwere written by users.\n\n819\n00:42:43,190 --> 00:42:45,890\nBut in general you can't write\nsuch a program that will read\n\n820\n00:42:45,890 --> 00:42:48,760\nany program and determine\nwhether or not it's an\n\n821\n00:42:48,760 --> 00:42:50,990\ninfinite loop.\n\n822\n00:42:50,990 --> 00:42:51,685\nLet me show you that.\n\n823\n00:42:51,685 --> 00:42:53,340\nIt's a little bit of a\nminor mathematics.\n\n824\n00:42:53,340 --> 00:42:58,780\n\n\n825\n00:42:58,780 --> 00:43:01,360\nLet's imagine that we just\nhad a mathematical\n\n826\n00:43:01,360 --> 00:43:02,620\nfunction before we start.\n\n827\n00:43:02,620 --> 00:43:12,980\nAnd there is one, called s,\nwhich takes a procedure and\n\n828\n00:43:12,980 --> 00:43:14,230\nits argument, a.\n\n829\n00:43:14,230 --> 00:43:19,320\n\n\n830\n00:43:19,320 --> 00:43:24,250\nAnd what s does is it determines\nwhether or not it's\n\n831\n00:43:24,250 --> 00:43:26,632\nsafe to run p on a.\n\n832\n00:43:26,632 --> 00:43:34,500\nAnd what I mean by that is this:\nit's true if p applied\n\n833\n00:43:34,500 --> 00:43:45,330\nto a will converge to a value\nwithout an error.\n\n834\n00:43:45,330 --> 00:43:52,365\n\n\n835\n00:43:52,365 --> 00:44:06,890\nAnd it's false if p of a loops\nforever or makes an error.\n\n836\n00:44:06,890 --> 00:44:15,000\n\n\n837\n00:44:15,000 --> 00:44:18,780\nNow that's surely a function.\n\n838\n00:44:18,780 --> 00:44:21,830\nThere is some for every\nprocedure and for every\n\n839\n00:44:21,830 --> 00:44:25,900\nargument you could give it that\nis either true or false\n\n840\n00:44:25,900 --> 00:44:28,440\nthat it converges without\nmaking an error.\n\n841\n00:44:28,440 --> 00:44:31,770\nAnd you could make a giant\ntable of them.\n\n842\n00:44:31,770 --> 00:44:34,710\nBut the question is, can you\nwrite a procedure that compute\n\n843\n00:44:34,710 --> 00:44:37,430\nthe values of this function?\n\n844\n00:44:37,430 --> 00:44:39,720\nWell let's assume that we can.\n\n845\n00:44:39,720 --> 00:44:58,740\nSuppose that we have a procedure\ncalled \"safe\" that\n\n846\n00:44:58,740 --> 00:44:59,990\ncomputes the value of s.\n\n847\n00:44:59,990 --> 00:45:12,170\n\n\n848\n00:45:12,170 --> 00:45:17,620\nNow I'm going to show you\nby several methods that\n\n849\n00:45:17,620 --> 00:45:19,760\nyou can't do this.\n\n850\n00:45:19,760 --> 00:45:22,300\nThe easiest one, or the first\none, let's define a procedure\n\n851\n00:45:22,300 --> 00:45:23,810\ncalled diag1.\n\n852\n00:45:23,810 --> 00:45:38,250\nGiven that we have safe, we\ncan define diag1 to be the\n\n853\n00:45:38,250 --> 00:45:43,430\nprocedure of one argument, p,\nwhich has the following\n\n854\n00:45:43,430 --> 00:45:44,780\nproperties.\n\n855\n00:45:44,780 --> 00:45:54,620\nIf if it's safe to apply p to\nitself, then I wish to have an\n\n856\n00:45:54,620 --> 00:45:55,870\ninfinite loop.\n\n857\n00:45:55,870 --> 00:45:59,330\n\n\n858\n00:45:59,330 --> 00:46:00,715\nOtherwise I'm going\nto return 3.\n\n859\n00:46:00,715 --> 00:46:03,680\n\n\n860\n00:46:03,680 --> 00:46:04,470\nRemember it was 42.\n\n861\n00:46:04,470 --> 00:46:07,060\nWhat's the answer to\nthe big question?\n\n862\n00:46:07,060 --> 00:46:08,525\nWhere of course we know what\nan infinite loop is.\n\n863\n00:46:08,525 --> 00:46:12,050\n\n\n864\n00:46:12,050 --> 00:46:16,130\nInfinite loop, to be a procedure\nof no arguments,\n\n865\n00:46:16,130 --> 00:46:18,430\nwhich is that nice lambda\ncalculus loop.\n\n866\n00:46:18,430 --> 00:46:24,680\nLambda of x, x of x, applied\nto lambda of x, x of x.\n\n867\n00:46:24,680 --> 00:46:26,550\nSo there's nothing left to\nthe imagination here.\n\n868\n00:46:26,550 --> 00:46:29,830\n\n\n869\n00:46:29,830 --> 00:46:32,500\nWell let's see what\nthe story is.\n\n870\n00:46:32,500 --> 00:46:38,100\nI'm supposing it's the case\nthat we worry about the\n\n871\n00:46:38,100 --> 00:46:43,180\nprocedure called diag1\napplied to diag1.\n\n872\n00:46:43,180 --> 00:46:45,860\n\n\n873\n00:46:45,860 --> 00:46:49,970\nWell what could it\npossibly be?\n\n874\n00:46:49,970 --> 00:46:51,390\nWell I don't know.\n\n875\n00:46:51,390 --> 00:46:57,310\nWe're going to substitute diag1\nfor p in the body here.\n\n876\n00:46:57,310 --> 00:47:00,220\nWell is it safe to compute\ndiag1 of diag1?\n\n877\n00:47:00,220 --> 00:47:00,780\nI don't know.\n\n878\n00:47:00,780 --> 00:47:03,400\nThere are two possibilities.\n\n879\n00:47:03,400 --> 00:47:06,260\nIf it's safe to compute diag1\nof diag1 that means it\n\n880\n00:47:06,260 --> 00:47:08,490\nshouldn't loop.\n\n881\n00:47:08,490 --> 00:47:09,540\nThat means I go to\nhere, but then I\n\n882\n00:47:09,540 --> 00:47:10,560\nproduce an infinite loop.\n\n883\n00:47:10,560 --> 00:47:12,210\nSo it can't be safe.\n\n884\n00:47:12,210 --> 00:47:15,055\nBut if it's not safe to compute\ndiag1 of diag1 then\n\n885\n00:47:15,055 --> 00:47:16,020\nthe answer to this is 3.\n\n886\n00:47:16,020 --> 00:47:20,530\nBut that's diag1 of diag1,\nso it had to be safe.\n\n887\n00:47:20,530 --> 00:47:27,470\nSo therefore by contradiction\nyou cannot produce safe.\n\n888\n00:47:27,470 --> 00:47:30,565\nFor those of you who were\nboggled by that one I'm going\n\n889\n00:47:30,565 --> 00:47:32,820\nto say it again, in\na different way.\n\n890\n00:47:32,820 --> 00:47:35,530\nListen to one more\nalternative.\n\n891\n00:47:35,530 --> 00:47:36,780\nLet's define diag2.\n\n892\n00:47:36,780 --> 00:47:39,840\n\n\n893\n00:47:39,840 --> 00:47:45,260\nThese are named diag because of\nCantor's diagonal argument.\n\n894\n00:47:45,260 --> 00:47:48,180\nThese are instances of a famous\nargument which was\n\n895\n00:47:48,180 --> 00:47:52,070\noriginally used by Cantor in\nthe late part of the last\n\n896\n00:47:52,070 --> 00:47:56,420\ncentury to prove that the real\nnumbers were not countable,\n\n897\n00:47:56,420 --> 00:47:58,160\nthat there are too many\nreal numbers to\n\n898\n00:47:58,160 --> 00:48:00,190\nbe counted by integers.\n\n899\n00:48:00,190 --> 00:48:02,710\nThat there are more points on\na line, for example, than\n\n900\n00:48:02,710 --> 00:48:05,260\nthere are counting numbers.\n\n901\n00:48:05,260 --> 00:48:07,190\nIt may or may not be obvious,\nand I don't want to\n\n902\n00:48:07,190 --> 00:48:08,440\nget into that now.\n\n903\n00:48:08,440 --> 00:48:10,900\n\n\n904\n00:48:10,900 --> 00:48:15,820\nBut diag2 is again a procedure\nof one argument p.\n\n905\n00:48:15,820 --> 00:48:19,220\nIt's almost the same as the\nprevious one, which is, if\n\n906\n00:48:19,220 --> 00:48:26,445\nit's safe to compute p on p,\nthen I'm going to produce--\n\n907\n00:48:26,445 --> 00:48:29,310\n\n\n908\n00:48:29,310 --> 00:48:34,010\nthen I want to compute\nsome other things\n\n909\n00:48:34,010 --> 00:48:38,960\nother than p of p.\n\n910\n00:48:38,960 --> 00:48:40,210\nOtherwise I'm going\nto put out false.\n\n911\n00:48:40,210 --> 00:48:43,600\n\n\n912\n00:48:43,600 --> 00:48:46,510\nWhere other then it says,\nwhatever p of p, I'm going to\n\n913\n00:48:46,510 --> 00:48:48,880\nput out something else.\n\n914\n00:48:48,880 --> 00:48:51,860\nI can give you an example of a\ndefinition of other than which\n\n915\n00:48:51,860 --> 00:48:53,890\nI think works.\n\n916\n00:48:53,890 --> 00:48:55,640\nLet's see.\n\n917\n00:48:55,640 --> 00:48:56,330\nYes.\n\n918\n00:48:56,330 --> 00:49:06,580\nWhere other than be a procedure\nof one argument x\n\n919\n00:49:06,580 --> 00:49:14,090\nwhich says, if its eq x to, say,\nquote a, then the answer\n\n920\n00:49:14,090 --> 00:49:15,720\nis quote b.\n\n921\n00:49:15,720 --> 00:49:16,970\nOtherwise it's quote a.\n\n922\n00:49:16,970 --> 00:49:20,090\n\n\n923\n00:49:20,090 --> 00:49:22,770\nThat always produces something\nwhich is not what\n\n924\n00:49:22,770 --> 00:49:25,350\nits argument is.\n\n925\n00:49:25,350 --> 00:49:26,540\nThat's all it is.\n\n926\n00:49:26,540 --> 00:49:28,250\nThat's all I wanted.\n\n927\n00:49:28,250 --> 00:49:30,640\nWell now let's consider this\none, diag2 of diag2.\n\n928\n00:49:30,640 --> 00:49:38,220\n\n\n929\n00:49:38,220 --> 00:49:39,560\nWell look.\n\n930\n00:49:39,560 --> 00:49:42,950\nThis only does something\ndangerous, like calling p of\n\n931\n00:49:42,950 --> 00:49:47,470\np, if it's safe to do so.\n\n932\n00:49:47,470 --> 00:49:51,590\nSo if safe defined at all,\nif you can define such a\n\n933\n00:49:51,590 --> 00:49:55,680\nprocedure, safe, then this\nprocedure is always defined\n\n934\n00:49:55,680 --> 00:49:57,225\nand therefore safe\non any inputs.\n\n935\n00:49:57,225 --> 00:50:01,540\n\n\n936\n00:50:01,540 --> 00:50:11,770\nSo diag2 of diag2 must reduce to\nother than diag2 of diag2.\n\n937\n00:50:11,770 --> 00:50:15,496\n\n\n938\n00:50:15,496 --> 00:50:20,020\nAnd that doesn't make sense,\nso we have a contradiction,\n\n939\n00:50:20,020 --> 00:50:22,950\nand therefore we can't\ndefine safe.\n\n940\n00:50:22,950 --> 00:50:27,210\nI just waned to do that twice,\nslightly differently, so you\n\n941\n00:50:27,210 --> 00:50:32,260\nwouldn't feel that the first\none was a trick.\n\n942\n00:50:32,260 --> 00:50:34,275\nThey may be both tricks,\nbut they're at\n\n943\n00:50:34,275 --> 00:50:37,300\nleast slightly different.\n\n944\n00:50:37,300 --> 00:50:40,080\nSo I suppose that pretty\nmuch wraps it up.\n\n945\n00:50:40,080 --> 00:50:43,540\nI've just proved what we call\nthe halting theorem, and I\n\n946\n00:50:43,540 --> 00:50:46,720\nsuppose with that we're\ngoing to halt.\n\n947\n00:50:46,720 --> 00:50:47,970\nI hope you have a good time.\n\n948\n00:50:47,970 --> 00:50:50,900\n\n\n949\n00:50:50,900 --> 00:50:53,300\nAre there any questions?\n\n950\n00:50:53,300 --> 00:50:53,810\nYes.\n\n951\n00:50:53,810 --> 00:50:56,940\nAUDIENCE: What is the\nvalue of s of diag1?\n\n952\n00:50:56,940 --> 00:50:57,430\nPROFESSOR: Of what?\n\n953\n00:50:57,430 --> 00:51:00,120\nAUDIENCE: S of diag1.\n\n954\n00:51:00,120 --> 00:51:02,340\nIf you said s is a function\nand we can\n\n955\n00:51:02,340 --> 00:51:02,620\n[INTERPOSING VOICES]\n\n956\n00:51:02,620 --> 00:51:03,870\nPROFESSOR: Oh, I don't know.\n\n957\n00:51:03,870 --> 00:51:04,350\nI don't know.\n\n958\n00:51:04,350 --> 00:51:06,850\nIt's a function, but I don't\nknow how to compute it.\n\n959\n00:51:06,850 --> 00:51:08,610\nI can't do it.\n\n960\n00:51:08,610 --> 00:51:11,530\nI'm just a machine, too.\n\n961\n00:51:11,530 --> 00:51:12,210\nRight?\n\n962\n00:51:12,210 --> 00:51:14,670\nThere's no machine that\nin principle--\n\n963\n00:51:14,670 --> 00:51:16,690\nit might be that in that\nparticular case you just\n\n964\n00:51:16,690 --> 00:51:18,580\nasked, with some thinking\nI could figure it out.\n\n965\n00:51:18,580 --> 00:51:21,670\nBut in general I can't compute\nthe value of s any better than\n\n966\n00:51:21,670 --> 00:51:23,780\nany other machine can.\n\n967\n00:51:23,780 --> 00:51:27,210\nThere is such a function, it's\njust that no machine can be\n\n968\n00:51:27,210 --> 00:51:29,580\nbuilt to compute it.\n\n969\n00:51:29,580 --> 00:51:32,980\nNow there's a way of saying\nthat that should not be\n\n970\n00:51:32,980 --> 00:51:35,350\nsurprising.\n\n971\n00:51:35,350 --> 00:51:36,390\nGoing through this--\n\n972\n00:51:36,390 --> 00:51:41,020\nI mean, I don't have time to do\nthis here, but the number\n\n973\n00:51:41,020 --> 00:51:44,600\nof functions is very large.\n\n974\n00:51:44,600 --> 00:51:48,210\nIf there's a certain number of\nanswers possible and a certain\n\n975\n00:51:48,210 --> 00:51:50,520\nnumber of inputs possible,\nthen it's the number of\n\n976\n00:51:50,520 --> 00:51:52,290\nanswers raised to the number\ninputs is the number of\n\n977\n00:51:52,290 --> 00:51:54,720\npossible functions.\n\n978\n00:51:54,720 --> 00:51:55,970\nOn one variable.\n\n979\n00:51:55,970 --> 00:51:58,150\n\n\n980\n00:51:58,150 --> 00:52:03,690\nNow that's always bigger than\nthe thing you're raising to,\n\n981\n00:52:03,690 --> 00:52:05,480\nthe exponent.\n\n982\n00:52:05,480 --> 00:52:12,150\nThe number of functions is\nlarger than the number of\n\n983\n00:52:12,150 --> 00:52:15,340\nprograms that one\ncan write, by an\n\n984\n00:52:15,340 --> 00:52:17,840\ninfinity counting argument.\n\n985\n00:52:17,840 --> 00:52:19,475\nAnd it's much larger.\n\n986\n00:52:19,475 --> 00:52:22,540\nSo there must be a lot of\nfunctions that can't be\n\n987\n00:52:22,540 --> 00:52:26,280\ncomputed by programs.\n\n988\n00:52:26,280 --> 00:52:27,300\nAUDIENCE: A few moments ago\nyou were talking about\n\n989\n00:52:27,300 --> 00:52:30,640\nspecifications and automatic\ngeneration of solutions.\n\n990\n00:52:30,640 --> 00:52:33,360\nDo you see any steps between\nspecifications and solutions?\n\n991\n00:52:33,360 --> 00:52:37,250\n\n\n992\n00:52:37,250 --> 00:52:38,720\nPROFESSOR: Steps between.\n\n993\n00:52:38,720 --> 00:52:42,720\nYou mean, you're saying, how\nyou go about constructing\n\n994\n00:52:42,720 --> 00:52:45,205\ndevices given that have\nspecifications for the device?\n\n995\n00:52:45,205 --> 00:52:45,500\nSure.\n\n996\n00:52:45,500 --> 00:52:48,540\nAUDIENCE: There's a lot of\nsoftware engineering that goes\n\n997\n00:52:48,540 --> 00:52:51,703\nthrough specifications through\nmany layers of design and then\n\n998\n00:52:51,703 --> 00:52:52,430\nimplementation.\n\n999\n00:52:52,430 --> 00:52:52,850\nPROFESSOR: Yes?\n\n1000\n00:52:52,850 --> 00:52:55,600\nAUDIENCE: I was curious if you\nthink that's realistic.\n\n1001\n00:52:55,600 --> 00:52:57,210\nPROFESSOR: Well I think that\nsome of it's realistic and\n\n1002\n00:52:57,210 --> 00:52:58,100\nsome of it isn't.\n\n1003\n00:52:58,100 --> 00:53:01,680\nI mean, surely if I want to\nbuild an electrical filter and\n\n1004\n00:53:01,680 --> 00:53:07,160\nI have a rather interesting\npossibility.\n\n1005\n00:53:07,160 --> 00:53:12,180\nSupposing I want to build a\nthing that matches some power\n\n1006\n00:53:12,180 --> 00:53:19,906\noutput to the radio transmitter,\nto some antenna.\n\n1007\n00:53:19,906 --> 00:53:21,970\nAnd I'm really out\nof this power--\n\n1008\n00:53:21,970 --> 00:53:23,230\nit's output tube out here.\n\n1009\n00:53:23,230 --> 00:53:25,920\nAnd the problem is that they\nhave different impedances.\n\n1010\n00:53:25,920 --> 00:53:27,550\nI want them to match\nthe impedances.\n\n1011\n00:53:27,550 --> 00:53:29,920\nI also want to make a filter in\nthere which is going to get\n\n1012\n00:53:29,920 --> 00:53:32,780\nrid of some harmonic\nradiation.\n\n1013\n00:53:32,780 --> 00:53:36,270\nWell one old-fashioned technique\nfor doing this is\n\n1014\n00:53:36,270 --> 00:53:38,860\ncalled image impedances,\nor something like that.\n\n1015\n00:53:38,860 --> 00:53:40,240\nAnd what you do is you\nsay you have a basic\n\n1016\n00:53:40,240 --> 00:53:43,300\nmodule called an L-section.\n\n1017\n00:53:43,300 --> 00:53:44,550\nLooks like this.\n\n1018\n00:53:44,550 --> 00:53:47,080\n\n\n1019\n00:53:47,080 --> 00:53:50,470\nIf I happen to connect this to\nsome resistance, r, and if I\n\n1020\n00:53:50,470 --> 00:53:55,150\nmake this impedance x, xl, and\nif it happens to be q times r,\n\n1021\n00:53:55,150 --> 00:53:59,710\nthen this produces a low pass\nfilter with a q square plus\n\n1022\n00:53:59,710 --> 00:54:02,110\none impedance match.\n\n1023\n00:54:02,110 --> 00:54:03,120\nJust what I need.\n\n1024\n00:54:03,120 --> 00:54:04,610\nBecause now I can take two\nof these, hook them\n\n1025\n00:54:04,610 --> 00:54:06,510\ntogether like this.\n\n1026\n00:54:06,510 --> 00:54:11,660\n\n\n1027\n00:54:11,660 --> 00:54:16,570\nOK, and I take another one\nand I'll hook them\n\n1028\n00:54:16,570 --> 00:54:18,290\ntogether like that.\n\n1029\n00:54:18,290 --> 00:54:20,320\nAnd I have two L-sections\nhooked together.\n\n1030\n00:54:20,320 --> 00:54:22,460\nAnd this will step the impedance\ndown to one that I\n\n1031\n00:54:22,460 --> 00:54:25,530\nknow, and this will step\nit up to one I know.\n\n1032\n00:54:25,530 --> 00:54:26,710\nEach of these is a\nlow pass filter\n\n1033\n00:54:26,710 --> 00:54:28,090\ngetting rid of some harmonics.\n\n1034\n00:54:28,090 --> 00:54:30,270\nIt's good filter, it's called\na pie-section filter.\n\n1035\n00:54:30,270 --> 00:54:31,700\nGreat.\n\n1036\n00:54:31,700 --> 00:54:34,300\nExcept for the fact that in\ndoing what I just did, I've\n\n1037\n00:54:34,300 --> 00:54:38,620\nmade a terrible inefficiency\nin this system.\n\n1038\n00:54:38,620 --> 00:54:41,620\nI've made two coils where\nI should have made one.\n\n1039\n00:54:41,620 --> 00:54:45,200\nAnd the problem with most\nsoftware engineering art is\n\n1040\n00:54:45,200 --> 00:54:47,440\nthat there's no mechanism,\nother than peephole\n\n1041\n00:54:47,440 --> 00:54:50,280\noptimization and compilers,\nfor getting rid of the\n\n1042\n00:54:50,280 --> 00:54:52,810\nredundant parts that are\nconstructed when doing top\n\n1043\n00:54:52,810 --> 00:54:55,350\ndown design.\n\n1044\n00:54:55,350 --> 00:54:57,160\nIt's even worse, there are\nlots of very important\n\n1045\n00:54:57,160 --> 00:55:01,110\nstructures that you can't\nconstruct at all this way.\n\n1046\n00:55:01,110 --> 00:55:03,940\nSo I think that the standard\ntop down design is a rather\n\n1047\n00:55:03,940 --> 00:55:05,710\nshallow business.\n\n1048\n00:55:05,710 --> 00:55:08,315\nDoesn't really capture what\npeople want to do in design.\n\n1049\n00:55:08,315 --> 00:55:10,100\nI'll give you another\nelectrical example.\n\n1050\n00:55:10,100 --> 00:55:12,140\nElectrical examples are\nso much clearer than\n\n1051\n00:55:12,140 --> 00:55:14,440\ncomputational examples, because\ncomputation examples\n\n1052\n00:55:14,440 --> 00:55:17,220\nrequire a certain degree of\ncomplexity to explain them.\n\n1053\n00:55:17,220 --> 00:55:19,650\nBut one of my favorite examples\nin the electrical\n\n1054\n00:55:19,650 --> 00:55:23,330\nworld is how would I ever come\nup with the output stage of\n\n1055\n00:55:23,330 --> 00:55:27,530\nthis inter-stage connection\nin an IF amplifier.\n\n1056\n00:55:27,530 --> 00:55:32,410\nIt's a little transistor\nhere, and let's see.\n\n1057\n00:55:32,410 --> 00:55:37,560\nWell I'm going to have a tank,\nand I'm going to hook this up\n\n1058\n00:55:37,560 --> 00:55:43,040\nto, say, I'm going to\nlink-couple that to the input\n\n1059\n00:55:43,040 --> 00:55:44,850\nof the next stage.\n\n1060\n00:55:44,850 --> 00:55:48,580\nHere's a perfectly\nplausible plan--\n\n1061\n00:55:48,580 --> 00:55:51,070\nwell except for the fact that\nsince I put that going up I\n\n1062\n00:55:51,070 --> 00:55:53,170\nshould make that\ngoing that way.\n\n1063\n00:55:53,170 --> 00:55:56,050\nHere's a perfectly plausible\nplan for a--\n\n1064\n00:55:56,050 --> 00:55:57,270\nno I shouldn't.\n\n1065\n00:55:57,270 --> 00:55:57,940\nI'm dumb.\n\n1066\n00:55:57,940 --> 00:55:59,690\nExcuse me.\n\n1067\n00:55:59,690 --> 00:56:00,730\nDoesn't matter.\n\n1068\n00:56:00,730 --> 00:56:01,540\nThe point is [UNINTELLIGIBLE]\n\n1069\n00:56:01,540 --> 00:56:02,560\nplan for a couple\n[UNINTELLIGIBLE]\n\n1070\n00:56:02,560 --> 00:56:04,590\nstages together.\n\n1071\n00:56:04,590 --> 00:56:07,620\nNow what the problem is is\nwhat's this hierarchically?\n\n1072\n00:56:07,620 --> 00:56:09,480\nIt's not one thing.\n\n1073\n00:56:09,480 --> 00:56:11,990\nHierarchically it doesn't\nmake any sense at all.\n\n1074\n00:56:11,990 --> 00:56:17,230\nIt's the inductance of a tuned\ncircuit, it's the primary of a\n\n1075\n00:56:17,230 --> 00:56:22,350\ntransformer, and it's also\nthe DC path by which bias\n\n1076\n00:56:22,350 --> 00:56:26,460\nconditions get to the collector\nof that transistor.\n\n1077\n00:56:26,460 --> 00:56:29,170\nAnd there's no simple top-down\ndesign that's going to produce\n\n1078\n00:56:29,170 --> 00:56:33,400\na structure like that with so\nmany overlapping uses for a\n\n1079\n00:56:33,400 --> 00:56:34,530\nparticular thing.\n\n1080\n00:56:34,530 --> 00:56:39,015\nPlaying Scrabble, where you have\nto do triple word scores,\n\n1081\n00:56:39,015 --> 00:56:44,950\nor whatever, is not so easy in\ntop-down design strategy.\n\n1082\n00:56:44,950 --> 00:56:48,100\nYet most of real engineering is\nbased on getting the most\n\n1083\n00:56:48,100 --> 00:56:52,140\noomph for effort.\n\n1084\n00:56:52,140 --> 00:56:54,860\nAnd that's what you're\nseeing here.\n\n1085\n00:56:54,860 --> 00:56:55,550\nYeah?\n\n1086\n00:56:55,550 --> 00:56:56,810\nAUDIENCE: Is this the\nlast question?\n\n1087\n00:56:56,810 --> 00:57:00,282\n\n\n1088\n00:57:00,282 --> 00:57:18,640\n[LAUGHTER]\n\n1089\n00:57:18,640 --> 00:57:19,890\nPROFESSOR: Apparently so.\n\n1090\n00:57:19,890 --> 00:57:23,240\n\n\n1091\n00:57:23,240 --> 00:57:26,092\nThank you.\n\n1092\n00:57:26,092 --> 00:57:39,040\n[APPLAUSE]\n\n1093\n00:57:39,040 --> 00:57:39,383\n[MUSIC-- \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n1094\n00:57:39,383 --> 00:57:40,633\nJOHANN SEBASTIAN BACH]\n\n1095\n00:57:40,633 --> 00:58:53,546\n\n"
  },
  {
    "path": "SrtEN/lec1a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:03,880\n\n\n1\n00:00:03,880 --> 00:00:14,550\n[MUSIC PLAYING]\n\n2\n00:00:14,550 --> 00:00:15,790\nPROFESSOR: I'd like to\nwelcome you to this\n\n3\n00:00:15,790 --> 00:00:17,270\ncourse on computer science.\n\n4\n00:00:17,270 --> 00:00:28,370\n\n\n5\n00:00:28,370 --> 00:00:29,990\nActually, that's a terrible\nway to start.\n\n6\n00:00:29,990 --> 00:00:32,740\nComputer science is a terrible\nname for this business.\n\n7\n00:00:32,740 --> 00:00:35,572\nFirst of all, it's\nnot a science.\n\n8\n00:00:35,572 --> 00:00:40,300\nIt might be engineering or it\nmight be art, but we'll\n\n9\n00:00:40,300 --> 00:00:43,470\nactually see that computer\nso-called science actually has\n\n10\n00:00:43,470 --> 00:00:45,350\na lot in common with magic,\nand we'll see\n\n11\n00:00:45,350 --> 00:00:47,210\nthat in this course.\n\n12\n00:00:47,210 --> 00:00:48,040\nSo it's not a science.\n\n13\n00:00:48,040 --> 00:00:53,340\nIt's also not really very\nmuch about computers.\n\n14\n00:00:53,340 --> 00:00:57,140\nAnd it's not about computers in\nthe same sense that physics\n\n15\n00:00:57,140 --> 00:01:02,920\nis not really about particle\naccelerators, and biology is\n\n16\n00:01:02,920 --> 00:01:06,350\nnot really about microscopes\nand petri dishes.\n\n17\n00:01:06,350 --> 00:01:10,400\nAnd it's not about computers\nin the same sense that\n\n18\n00:01:10,400 --> 00:01:16,480\ngeometry is not really about\nusing surveying instruments.\n\n19\n00:01:16,480 --> 00:01:20,320\nIn fact, there's a lot of\ncommonality between computer\n\n20\n00:01:20,320 --> 00:01:21,240\nscience and geometry.\n\n21\n00:01:21,240 --> 00:01:23,830\nGeometry, first of all,\nis another subject\n\n22\n00:01:23,830 --> 00:01:25,680\nwith a lousy name.\n\n23\n00:01:25,680 --> 00:01:28,130\nThe name comes from Gaia,\nmeaning the Earth, and metron,\n\n24\n00:01:28,130 --> 00:01:29,770\nmeaning to measure.\n\n25\n00:01:29,770 --> 00:01:31,350\nGeometry originally\nmeant measuring\n\n26\n00:01:31,350 --> 00:01:34,260\nthe Earth or surveying.\n\n27\n00:01:34,260 --> 00:01:37,260\nAnd the reason for that was\nthat, thousands of years ago,\n\n28\n00:01:37,260 --> 00:01:40,930\nthe Egyptian priesthood\ndeveloped the rudiments of\n\n29\n00:01:40,930 --> 00:01:45,320\ngeometry in order to figure\nout how to restore the\n\n30\n00:01:45,320 --> 00:01:47,430\nboundaries of fields that were\ndestroyed in the annual\n\n31\n00:01:47,430 --> 00:01:49,390\nflooding of the Nile.\n\n32\n00:01:49,390 --> 00:01:52,360\nAnd to the Egyptians who did\nthat, geometry really was the\n\n33\n00:01:52,360 --> 00:01:55,600\nuse of surveying instruments.\n\n34\n00:01:55,600 --> 00:01:57,850\nNow, the reason that we think\ncomputer science is about\n\n35\n00:01:57,850 --> 00:02:01,770\ncomputers is pretty much the\nsame reason that the Egyptians\n\n36\n00:02:01,770 --> 00:02:04,520\nthought geometry was about\nsurveying instruments.\n\n37\n00:02:04,520 --> 00:02:07,340\nAnd that is, when some field\nis just getting started and\n\n38\n00:02:07,340 --> 00:02:11,790\nyou don't really understand it\nvery well, it's very easy to\n\n39\n00:02:11,790 --> 00:02:15,280\nconfuse the essence of what\nyou're doing with the tools\n\n40\n00:02:15,280 --> 00:02:17,590\nthat you use.\n\n41\n00:02:17,590 --> 00:02:20,960\nAnd indeed, on some absolute\nscale of things, we probably\n\n42\n00:02:20,960 --> 00:02:25,100\nknow less about the essence of\ncomputer science than the\n\n43\n00:02:25,100 --> 00:02:26,955\nancient Egyptians really\nknew about geometry.\n\n44\n00:02:26,955 --> 00:02:29,970\n\n\n45\n00:02:29,970 --> 00:02:32,570\nWell, what do I mean by the\nessence of computer science?\n\n46\n00:02:32,570 --> 00:02:34,300\nWhat do I mean by the\nessence of geometry?\n\n47\n00:02:34,300 --> 00:02:36,380\nSee, it's certainly true that\nthese Egyptians went off and\n\n48\n00:02:36,380 --> 00:02:40,190\nused surveying instruments, but\nwhen we look back on them\n\n49\n00:02:40,190 --> 00:02:42,240\nafter a couple of thousand\nyears, we say, gee, what they\n\n50\n00:02:42,240 --> 00:02:45,910\nwere doing, the important stuff\nthey were doing, was to\n\n51\n00:02:45,910 --> 00:02:52,510\nbegin to formalize notions about\nspace and time, to start\n\n52\n00:02:52,510 --> 00:02:57,490\na way of talking about\nmathematical truths formally.\n\n53\n00:02:57,490 --> 00:02:59,420\nThat led to the axiomatic\nmethod.\n\n54\n00:02:59,420 --> 00:03:04,420\nThat led to sort of all of\nmodern mathematics, figuring\n\n55\n00:03:04,420 --> 00:03:08,350\nout a way to talk precisely\nabout so-called declarative\n\n56\n00:03:08,350 --> 00:03:10,000\nknowledge, what is true.\n\n57\n00:03:10,000 --> 00:03:12,550\n\n\n58\n00:03:12,550 --> 00:03:15,680\nWell, similarly, I think in the\nfuture people will look\n\n59\n00:03:15,680 --> 00:03:18,520\nback and say, yes, those\nprimitives in the 20th century\n\n60\n00:03:18,520 --> 00:03:20,190\nwere fiddling around with\nthese gadgets called\n\n61\n00:03:20,190 --> 00:03:25,790\ncomputers, but really what they\nwere doing is starting to\n\n62\n00:03:25,790 --> 00:03:32,730\nlearn how to formalize\nintuitions about process, how\n\n63\n00:03:32,730 --> 00:03:47,100\nto do things, starting to\ndevelop a way to talk\n\n64\n00:03:47,100 --> 00:03:52,190\nprecisely about how-to\nknowledge, as opposed to\n\n65\n00:03:52,190 --> 00:03:56,470\ngeometry that talks about\nwhat is true.\n\n66\n00:03:56,470 --> 00:03:57,810\nLet me give you an\nexample of that.\n\n67\n00:03:57,810 --> 00:04:01,650\n\n\n68\n00:04:01,650 --> 00:04:02,550\nLet's take a look.\n\n69\n00:04:02,550 --> 00:04:08,250\nHere is a piece of mathematics\nthat says what\n\n70\n00:04:08,250 --> 00:04:10,250\na square root is.\n\n71\n00:04:10,250 --> 00:04:17,019\nThe square root of X is the\nnumber Y, such that Y squared\n\n72\n00:04:17,019 --> 00:04:20,290\nis equal to X and Y\nis greater than 0.\n\n73\n00:04:20,290 --> 00:04:23,510\nNow, that's a fine piece of\nmathematics, but just telling\n\n74\n00:04:23,510 --> 00:04:26,900\nyou what a square root is\ndoesn't really say anything\n\n75\n00:04:26,900 --> 00:04:31,420\nabout how you might go\nout and find one.\n\n76\n00:04:31,420 --> 00:04:37,410\nSo let's contrast that with a\npiece of imperative knowledge,\n\n77\n00:04:37,410 --> 00:04:39,840\nhow you might go out and\nfind a square root.\n\n78\n00:04:39,840 --> 00:04:44,660\nThis, in fact, also comes\nfrom Egypt, not\n\n79\n00:04:44,660 --> 00:04:45,640\nancient, ancient Egypt.\n\n80\n00:04:45,640 --> 00:04:50,050\nThis is an algorithm due to\nHeron of Alexandria, called\n\n81\n00:04:50,050 --> 00:04:52,910\nhow to find a square root\nby successive averaging.\n\n82\n00:04:52,910 --> 00:05:03,370\nAnd what it says is that, in\norder to find a square root,\n\n83\n00:05:03,370 --> 00:05:07,560\nyou make a guess, you\nimprove that guess--\n\n84\n00:05:07,560 --> 00:05:10,070\n\n\n85\n00:05:10,070 --> 00:05:12,670\nand the way you improve the\nguess is to average the guess\n\n86\n00:05:12,670 --> 00:05:15,170\nand X over the guess, and we'll\ntalk a little bit later\n\n87\n00:05:15,170 --> 00:05:17,080\nabout why that's a reasonable\nthing--\n\n88\n00:05:17,080 --> 00:05:19,740\nand you keep improving the guess\nuntil it's good enough.\n\n89\n00:05:19,740 --> 00:05:20,800\nThat's a method.\n\n90\n00:05:20,800 --> 00:05:25,070\nThat's how to do something\nas opposed to declarative\n\n91\n00:05:25,070 --> 00:05:28,270\nknowledge that says what\nyou're looking for.\n\n92\n00:05:28,270 --> 00:05:29,520\nThat's a process.\n\n93\n00:05:29,520 --> 00:05:34,130\n\n\n94\n00:05:34,130 --> 00:05:38,850\nWell, what's a process\nin general?\n\n95\n00:05:38,850 --> 00:05:40,000\nIt's kind of hard to say.\n\n96\n00:05:40,000 --> 00:05:45,350\nYou can think of it as like a\nmagical spirit that sort of\n\n97\n00:05:45,350 --> 00:05:47,870\nlives in the computer\nand does something.\n\n98\n00:05:47,870 --> 00:05:56,250\nAnd the thing that directs a\nprocess is a pattern of rules\n\n99\n00:05:56,250 --> 00:05:57,500\ncalled a procedure.\n\n100\n00:05:57,500 --> 00:06:01,690\n\n\n101\n00:06:01,690 --> 00:06:05,940\nSo procedures are the spells,\nif you like, that control\n\n102\n00:06:05,940 --> 00:06:10,700\nthese magical spirits that\nare the processes.\n\n103\n00:06:10,700 --> 00:06:12,650\nI guess you know everyone needs\na magical language, and\n\n104\n00:06:12,650 --> 00:06:17,310\nsorcerers, real sorcerers, use\nancient Arcadian or Sumerian\n\n105\n00:06:17,310 --> 00:06:18,670\nor Babylonian or whatever.\n\n106\n00:06:18,670 --> 00:06:21,540\nWe're going to conjure our\nspirits in a magical language\n\n107\n00:06:21,540 --> 00:06:26,750\ncalled Lisp, which is a language\ndesigned for talking\n\n108\n00:06:26,750 --> 00:06:31,120\nabout, for casting the spells\nthat are procedures to direct\n\n109\n00:06:31,120 --> 00:06:32,040\nthe processes.\n\n110\n00:06:32,040 --> 00:06:33,780\nNow, it's very easy\nto learn Lisp.\n\n111\n00:06:33,780 --> 00:06:35,810\nIn fact, in a few minutes,\nI'm going to teach you,\n\n112\n00:06:35,810 --> 00:06:36,960\nessentially, all of Lisp.\n\n113\n00:06:36,960 --> 00:06:40,660\nI'm going to teach you,\nessentially, all of the rules.\n\n114\n00:06:40,660 --> 00:06:43,440\nAnd you shouldn't find that\nparticularly surprising.\n\n115\n00:06:43,440 --> 00:06:46,150\nThat's sort of like saying it's\nvery easy to learn the\n\n116\n00:06:46,150 --> 00:06:46,940\nrules of chess.\n\n117\n00:06:46,940 --> 00:06:48,860\nAnd indeed, in a few minutes,\nyou can tell somebody the\n\n118\n00:06:48,860 --> 00:06:50,710\nrules of chess.\n\n119\n00:06:50,710 --> 00:06:53,490\nBut of course, that's very\ndifferent from saying you\n\n120\n00:06:53,490 --> 00:06:55,740\nunderstand the implications of\nthose rules and how to use\n\n121\n00:06:55,740 --> 00:06:58,420\nthose rules to become a\nmasterful chess player.\n\n122\n00:06:58,420 --> 00:07:00,380\nWell, Lisp is the same way.\n\n123\n00:07:00,380 --> 00:07:02,610\nWe're going to state the rules\nin a few minutes, and it'll be\n\n124\n00:07:02,610 --> 00:07:03,360\nvery easy to see.\n\n125\n00:07:03,360 --> 00:07:06,210\nBut what's really hard is going\nto be the implications\n\n126\n00:07:06,210 --> 00:07:09,310\nof those rules, how you exploit\nthose rules to be a\n\n127\n00:07:09,310 --> 00:07:12,080\nmaster programmer.\n\n128\n00:07:12,080 --> 00:07:15,260\nAnd the implications of those\nrules are going to take us\n\n129\n00:07:15,260 --> 00:07:17,770\nthe, well, the whole rest of\nthe subject and, of course,\n\n130\n00:07:17,770 --> 00:07:19,020\nway beyond.\n\n131\n00:07:19,020 --> 00:07:21,420\n\n\n132\n00:07:21,420 --> 00:07:26,070\nOK, so in computer science,\nwe're in the business of\n\n133\n00:07:26,070 --> 00:07:30,910\nformalizing this sort of how-to\nimperative knowledge,\n\n134\n00:07:30,910 --> 00:07:33,330\nhow to do stuff.\n\n135\n00:07:33,330 --> 00:07:35,120\nAnd the real issues of computer\nscience are, of\n\n136\n00:07:35,120 --> 00:07:38,620\ncourse, not telling people\nhow to do square roots.\n\n137\n00:07:38,620 --> 00:07:40,050\nBecause if that was\nall it was, there\n\n138\n00:07:40,050 --> 00:07:41,760\nwouldn't be no big deal.\n\n139\n00:07:41,760 --> 00:07:45,550\nThe real problems come when we\ntry to build very, very large\n\n140\n00:07:45,550 --> 00:07:49,270\nsystems, computer programs that\nare thousands of pages\n\n141\n00:07:49,270 --> 00:07:52,640\nlong, so long that nobody can\nreally hold them in their\n\n142\n00:07:52,640 --> 00:07:54,640\nheads all at once.\n\n143\n00:07:54,640 --> 00:07:58,770\nAnd the only reason that that's\npossible is because\n\n144\n00:07:58,770 --> 00:08:17,830\nthere are techniques for\ncontrolling the complexity of\n\n145\n00:08:17,830 --> 00:08:21,590\nthese large systems. And these\ntechniques that are\n\n146\n00:08:21,590 --> 00:08:22,950\ncontrolling complexity\nare what this\n\n147\n00:08:22,950 --> 00:08:24,700\ncourse is really about.\n\n148\n00:08:24,700 --> 00:08:26,030\nAnd in some sense, that's\nreally what\n\n149\n00:08:26,030 --> 00:08:29,650\ncomputer science is about.\n\n150\n00:08:29,650 --> 00:08:31,740\nNow, that may seem like a very\nstrange thing to say.\n\n151\n00:08:31,740 --> 00:08:34,960\nBecause after all, a lot of\npeople besides computer\n\n152\n00:08:34,960 --> 00:08:37,970\nscientists deal with controlling\ncomplexity.\n\n153\n00:08:37,970 --> 00:08:41,860\nA large airliner is an extremely\ncomplex system, and\n\n154\n00:08:41,860 --> 00:08:44,760\nthe aeronautical engineers who\ndesign that are dealing with\n\n155\n00:08:44,760 --> 00:08:47,030\nimmense complexity.\n\n156\n00:08:47,030 --> 00:08:49,380\nBut there's a difference\nbetween that kind of\n\n157\n00:08:49,380 --> 00:08:52,205\ncomplexity and what we deal\nwith in computer science.\n\n158\n00:08:52,205 --> 00:08:55,090\n\n\n159\n00:08:55,090 --> 00:08:57,750\nAnd that is that computer\nscience, in some\n\n160\n00:08:57,750 --> 00:08:59,700\nsense, isn't real.\n\n161\n00:08:59,700 --> 00:09:02,670\n\n\n162\n00:09:02,670 --> 00:09:07,070\nYou see, when an engineer is\ndesigning a physical system,\n\n163\n00:09:07,070 --> 00:09:09,520\nthat's made out of real parts.\n\n164\n00:09:09,520 --> 00:09:12,820\nThe engineers who worry about\nthat have to address problems\n\n165\n00:09:12,820 --> 00:09:16,540\nof tolerance and approximation\nand noise in the system.\n\n166\n00:09:16,540 --> 00:09:19,280\nSo for example, as an electrical\nengineer, I can go\n\n167\n00:09:19,280 --> 00:09:21,885\noff and easily build a one-stage\namplifier or a\n\n168\n00:09:21,885 --> 00:09:25,090\ntwo-stage amplifier, and I can\nimagine cascading a lot of\n\n169\n00:09:25,090 --> 00:09:26,760\nthem to build a million-stage\namplifier.\n\n170\n00:09:26,760 --> 00:09:30,900\nBut it's ridiculous to build\nsuch a thing, because long\n\n171\n00:09:30,900 --> 00:09:33,160\nbefore the millionth stage,\nthe thermal noise in those\n\n172\n00:09:33,160 --> 00:09:34,740\ncomponents way at the beginning\nis going to get\n\n173\n00:09:34,740 --> 00:09:36,200\namplified and make the whole\nthing meaningless.\n\n174\n00:09:36,200 --> 00:09:38,880\n\n\n175\n00:09:38,880 --> 00:09:44,070\nComputer science deals with\nidealized components.\n\n176\n00:09:44,070 --> 00:09:47,430\nWe know as much as we want about\nthese little program and\n\n177\n00:09:47,430 --> 00:09:51,820\ndata pieces that we're fitting\nthings together.\n\n178\n00:09:51,820 --> 00:09:53,090\nWe don't have to worry\nabout tolerance.\n\n179\n00:09:53,090 --> 00:09:57,960\nAnd that means that, in building\na large program,\n\n180\n00:09:57,960 --> 00:10:01,720\nthere's not all that much\ndifference between what I can\n\n181\n00:10:01,720 --> 00:10:06,520\nbuild and what I can imagine,\nbecause the parts are these\n\n182\n00:10:06,520 --> 00:10:10,250\nabstract entities that I\nknow as much as I want.\n\n183\n00:10:10,250 --> 00:10:13,430\nI know about them as precisely\nas I'd like.\n\n184\n00:10:13,430 --> 00:10:15,920\nSo as opposed to other kinds\nof engineering, where the\n\n185\n00:10:15,920 --> 00:10:17,830\nconstraints on what you can\nbuild are the constraints of\n\n186\n00:10:17,830 --> 00:10:19,810\nphysical systems, the\nconstraints of physics and\n\n187\n00:10:19,810 --> 00:10:24,160\nnoise and approximation, the\nconstraints imposed in\n\n188\n00:10:24,160 --> 00:10:26,640\nbuilding large software systems\nare the limitations of\n\n189\n00:10:26,640 --> 00:10:28,930\nour own minds.\n\n190\n00:10:28,930 --> 00:10:32,460\nSo in that sense, computer\nscience is like an abstract\n\n191\n00:10:32,460 --> 00:10:33,530\nform of engineering.\n\n192\n00:10:33,530 --> 00:10:35,680\nIt's the kind of engineering\nwhere you ignore the\n\n193\n00:10:35,680 --> 00:10:37,645\nconstraints that are\nimposed by reality.\n\n194\n00:10:37,645 --> 00:10:42,050\n\n\n195\n00:10:42,050 --> 00:10:46,400\nWell, what are some of\nthese techniques?\n\n196\n00:10:46,400 --> 00:10:47,830\nThey're not special to\ncomputer science.\n\n197\n00:10:47,830 --> 00:10:50,360\n\n\n198\n00:10:50,360 --> 00:10:54,140\nFirst technique, which is used\nin all of engineering, is a\n\n199\n00:10:54,140 --> 00:10:57,785\nkind of abstraction called\nblack-box abstraction.\n\n200\n00:10:57,785 --> 00:11:07,670\n\n\n201\n00:11:07,670 --> 00:11:14,340\nTake something and build\na box about it.\n\n202\n00:11:14,340 --> 00:11:19,220\nLet's see, for example, if we\nlooked at that square root\n\n203\n00:11:19,220 --> 00:11:29,678\nmethod, I might want to take\nthat and build a box.\n\n204\n00:11:29,678 --> 00:11:38,980\nThat sort of says, to find the\nsquare root of X. And that\n\n205\n00:11:38,980 --> 00:11:42,560\nmight be a whole complicated\nset of rules.\n\n206\n00:11:42,560 --> 00:11:46,280\nAnd that might end up being a\nkind of thing where I can put\n\n207\n00:11:46,280 --> 00:11:50,270\nin, say, 36 and say, what's\nthe square root of 36?\n\n208\n00:11:50,270 --> 00:11:51,520\nAnd out comes 6.\n\n209\n00:11:51,520 --> 00:11:53,880\n\n\n210\n00:11:53,880 --> 00:11:59,630\nAnd the important thing is that\nI'd like to design that\n\n211\n00:11:59,630 --> 00:12:05,080\nso that if George comes along\nand would like to compute,\n\n212\n00:12:05,080 --> 00:12:11,580\nsay, the square root of A plus\nthe square root of B, he can\n\n213\n00:12:11,580 --> 00:12:14,930\ntake this thing and use it as\na module without having to\n\n214\n00:12:14,930 --> 00:12:16,760\nlook inside and build something\nthat looks like\n\n215\n00:12:16,760 --> 00:12:24,960\nthis, like an A and a B and a\nsquare root box and another\n\n216\n00:12:24,960 --> 00:12:32,660\nsquare root box and then\nsomething that adds that would\n\n217\n00:12:32,660 --> 00:12:33,870\nput out the answer.\n\n218\n00:12:33,870 --> 00:12:38,830\nAnd you can see, just from the\nfact that I want to do that,\n\n219\n00:12:38,830 --> 00:12:41,560\nis from George's point of view,\nthe internals of what's\n\n220\n00:12:41,560 --> 00:12:44,170\nin here should not\nbe important.\n\n221\n00:12:44,170 --> 00:12:46,940\nSo for instance, it shouldn't\nmatter that, when I wrote\n\n222\n00:12:46,940 --> 00:12:50,750\nthis, I said I want to find the\nsquare root of X. I could\n\n223\n00:12:50,750 --> 00:12:54,840\nhave said the square root of Y,\nor the square root of A, or\n\n224\n00:12:54,840 --> 00:12:56,890\nanything at all.\n\n225\n00:12:56,890 --> 00:13:03,480\nThat's the fundamental notion of\nputting something in a box\n\n226\n00:13:03,480 --> 00:13:07,520\nusing black-box abstraction\nto suppress detail.\n\n227\n00:13:07,520 --> 00:13:10,070\nAnd the reason for that is you\nwant to go off and build\n\n228\n00:13:10,070 --> 00:13:11,990\nbigger boxes.\n\n229\n00:13:11,990 --> 00:13:13,880\nNow, there's another reason\nfor doing black-box\n\n230\n00:13:13,880 --> 00:13:17,340\nabstraction other than you want\nto suppress detail for\n\n231\n00:13:17,340 --> 00:13:18,310\nbuilding bigger boxes.\n\n232\n00:13:18,310 --> 00:13:24,880\nSometimes you want to say that\nyour way of doing something,\n\n233\n00:13:24,880 --> 00:13:30,210\nyour how-to method, is an\ninstance of a more general\n\n234\n00:13:30,210 --> 00:13:33,430\nthing, and you'd like your\nlanguage to be able to express\n\n235\n00:13:33,430 --> 00:13:35,560\nthat generality.\n\n236\n00:13:35,560 --> 00:13:37,800\nLet me show you another example\n\n237\n00:13:37,800 --> 00:13:38,740\nsticking with square roots.\n\n238\n00:13:38,740 --> 00:13:42,260\nLet's go back and take another\nlook at that slide with the\n\n239\n00:13:42,260 --> 00:13:44,380\nsquare root algorithm on it.\n\n240\n00:13:44,380 --> 00:13:45,460\nRemember what that says.\n\n241\n00:13:45,460 --> 00:13:50,700\nThat says, in order to do\nsomething, I make a guess, and\n\n242\n00:13:50,700 --> 00:13:53,800\nI improve that guess,\nand I sort of keep\n\n243\n00:13:53,800 --> 00:13:56,970\nimproving that guess.\n\n244\n00:13:56,970 --> 00:13:59,560\nSo there's the general strategy\nof, I'm looking for\n\n245\n00:13:59,560 --> 00:14:02,440\nsomething, and the way\nI find it is that I\n\n246\n00:14:02,440 --> 00:14:04,280\nkeep improving it.\n\n247\n00:14:04,280 --> 00:14:10,930\nNow, that's a particular case\nof another kind of strategy\n\n248\n00:14:10,930 --> 00:14:14,176\nfor finding a fixed point\nof something.\n\n249\n00:14:14,176 --> 00:14:17,660\nSo you have a fixed point\nof a function.\n\n250\n00:14:17,660 --> 00:14:26,090\nA fixed point of a function\nis something, is a value.\n\n251\n00:14:26,090 --> 00:14:30,710\nA fixed point of a function F is\na value Y, such that F of Y\n\n252\n00:14:30,710 --> 00:14:41,592\nequals Y. And the way I might do\nthat is start with a guess.\n\n253\n00:14:41,592 --> 00:14:44,630\nAnd then if I want something\nthat doesn't change when I\n\n254\n00:14:44,630 --> 00:14:47,800\nkeep applying F, is I'll keep\napplying F over and over until\n\n255\n00:14:47,800 --> 00:14:50,150\nthat result doesn't\nchange very much.\n\n256\n00:14:50,150 --> 00:14:52,290\nSo there's a general strategy.\n\n257\n00:14:52,290 --> 00:14:56,250\nAnd then, for example, to\ncompute the square root of X,\n\n258\n00:14:56,250 --> 00:15:00,780\nI can try and find a fixed point\nof the function which\n\n259\n00:15:00,780 --> 00:15:05,020\ntakes Y to the average of X/Y.\nAnd the idea that is that if I\n\n260\n00:15:05,020 --> 00:15:09,300\nreally had Y equal to the square\nroot of X, then Y and\n\n261\n00:15:09,300 --> 00:15:12,080\nX/Y would be the same value.\n\n262\n00:15:12,080 --> 00:15:16,370\nThey'd both be the square root\nof X, because X over the\n\n263\n00:15:16,370 --> 00:15:19,080\nsquare root of X is the\nsquare root of X.\n\n264\n00:15:19,080 --> 00:15:23,860\nAnd so the average if Y were\nequal to the square of X, then\n\n265\n00:15:23,860 --> 00:15:26,230\nthe average wouldn't change.\n\n266\n00:15:26,230 --> 00:15:27,530\nSo the square root of X\nis a fixed point of\n\n267\n00:15:27,530 --> 00:15:30,250\nthat particular function.\n\n268\n00:15:30,250 --> 00:15:34,010\nNow, what I'd like to have,\nI'd like to express the\n\n269\n00:15:34,010 --> 00:15:36,430\ngeneral strategy for finding\nfixed points.\n\n270\n00:15:36,430 --> 00:15:37,210\nSo what I might imagine doing,\nis to find, is to be able to\n\n271\n00:15:37,210 --> 00:15:37,309\nuse my language to define a box\nthat says \"fixed point,\"\n\n272\n00:15:37,309 --> 00:15:37,417\njust like I could make a box\nthat says \"square root.\" And\n\n273\n00:15:37,417 --> 00:15:38,667\nI'd like to be able to express\nthis in my language.\n\n274\n00:15:38,667 --> 00:15:56,350\n\n\n275\n00:15:56,350 --> 00:16:00,870\nSo I'd like to express not only\nthe imperative how-to\n\n276\n00:16:00,870 --> 00:16:03,620\nknowledge of a particular thing\nlike square root, but\n\n277\n00:16:03,620 --> 00:16:05,600\nI'd like to be able to express\nthe imperative knowledge of\n\n278\n00:16:05,600 --> 00:16:09,930\nhow to do a general thing like\nhow to find fixed point.\n\n279\n00:16:09,930 --> 00:16:12,090\nAnd in fact, let's go back and\nlook at that slide again.\n\n280\n00:16:12,090 --> 00:16:15,010\n\n\n281\n00:16:15,010 --> 00:16:23,380\nSee, not only is this a piece\nof imperative knowledge, how\n\n282\n00:16:23,380 --> 00:16:27,190\nto find a fixed point, but\nover here on the bottom,\n\n283\n00:16:27,190 --> 00:16:29,890\nthere's another piece of\nimperative knowledge which\n\n284\n00:16:29,890 --> 00:16:34,350\nsays, one way to compute square\nroot is to apply this\n\n285\n00:16:34,350 --> 00:16:36,140\ngeneral fixed point method.\n\n286\n00:16:36,140 --> 00:16:37,710\nSo I'd like to also\nbe able to express\n\n287\n00:16:37,710 --> 00:16:39,700\nthat imperative knowledge.\n\n288\n00:16:39,700 --> 00:16:40,650\nWhat would that look like?\n\n289\n00:16:40,650 --> 00:16:46,010\nThat would say, this fixed point\nbox is such that if I\n\n290\n00:16:46,010 --> 00:16:56,980\ninput to it the function that\ntakes Y to the average of Y\n\n291\n00:16:56,980 --> 00:17:04,300\nand X/Y, then what should come\nout of that fixed point box is\n\n292\n00:17:04,300 --> 00:17:06,200\na method for finding\nsquare roots.\n\n293\n00:17:06,200 --> 00:17:08,800\n\n\n294\n00:17:08,800 --> 00:17:10,829\nSo in these boxes we're\nbuilding, we're not only\n\n295\n00:17:10,829 --> 00:17:16,369\nbuilding boxes that you input\nnumbers and output numbers,\n\n296\n00:17:16,369 --> 00:17:19,410\nwe're going to be building in\nboxes that, in effect, compute\n\n297\n00:17:19,410 --> 00:17:22,250\nmethods like finding\nsquare root.\n\n298\n00:17:22,250 --> 00:17:27,480\nAnd my take is their inputs\nfunctions, like Y goes to the\n\n299\n00:17:27,480 --> 00:17:32,360\naverage of Y and X/Y. The reason\nwe want to do that, the\n\n300\n00:17:32,360 --> 00:17:35,425\nreason this is a procedure, will\nend up being a procedure,\n\n301\n00:17:35,425 --> 00:17:39,640\nas we'll see, whose value is\nanother procedure, the reason\n\n302\n00:17:39,640 --> 00:17:42,630\nwe want to do that is because\nprocedures are going to be our\n\n303\n00:17:42,630 --> 00:17:47,960\nways of talking about imperative\nknowledge.\n\n304\n00:17:47,960 --> 00:17:50,560\nAnd the way to make that very\npowerful is to be able to talk\n\n305\n00:17:50,560 --> 00:17:53,260\nabout other kinds\nof knowledge.\n\n306\n00:17:53,260 --> 00:17:55,930\nSo here is a procedure that, in\neffect, talks about another\n\n307\n00:17:55,930 --> 00:17:59,450\nprocedure, a general strategy\nthat itself talks about\n\n308\n00:17:59,450 --> 00:18:00,700\ngeneral strategies.\n\n309\n00:18:00,700 --> 00:18:04,290\n\n\n310\n00:18:04,290 --> 00:18:08,370\nWell, our first topic in this\ncourse-- there'll be three\n\n311\n00:18:08,370 --> 00:18:11,070\nmajor topics-- will be black-box\nabstraction.\n\n312\n00:18:11,070 --> 00:18:15,150\nLet's look at that in a little\nbit more detail.\n\n313\n00:18:15,150 --> 00:18:23,910\nWhat we're going to do is we\nwill start out talking about\n\n314\n00:18:23,910 --> 00:18:27,480\nhow Lisp is built up out\nof primitive objects.\n\n315\n00:18:27,480 --> 00:18:29,580\nWhat does the language\nsupply with us?\n\n316\n00:18:29,580 --> 00:18:32,690\nAnd we'll see that there are\nprimitive procedures and\n\n317\n00:18:32,690 --> 00:18:35,620\nprimitive data.\n\n318\n00:18:35,620 --> 00:18:38,510\nThen we're going to see, how do\nyou take those primitives\n\n319\n00:18:38,510 --> 00:18:41,940\nand combine them to make more\ncomplicated things, means of\n\n320\n00:18:41,940 --> 00:18:42,860\ncombination?\n\n321\n00:18:42,860 --> 00:18:44,824\nAnd what we'll see is that\nthere are ways of putting\n\n322\n00:18:44,824 --> 00:18:47,850\nthings together, putting\nprimitive procedures together\n\n323\n00:18:47,850 --> 00:18:50,960\nto make more complicated\nprocedures.\n\n324\n00:18:50,960 --> 00:18:53,250\nAnd we'll see how to put\nprimitive data together to\n\n325\n00:18:53,250 --> 00:18:55,830\nmake compound data.\n\n326\n00:18:55,830 --> 00:18:59,700\nThen we'll say, well, having\nmade those compounds things,\n\n327\n00:18:59,700 --> 00:19:02,830\nhow do you abstract them?\n\n328\n00:19:02,830 --> 00:19:05,290\nHow do you put those black boxes\naround them so you can\n\n329\n00:19:05,290 --> 00:19:08,090\nuse them as components in\nmore complex things?\n\n330\n00:19:08,090 --> 00:19:11,640\nAnd we'll see that's done by\ndefining procedures and a\n\n331\n00:19:11,640 --> 00:19:13,740\ntechnique for dealing with\ncompound data called data\n\n332\n00:19:13,740 --> 00:19:15,540\nabstraction.\n\n333\n00:19:15,540 --> 00:19:19,150\nAnd then, what's maybe the most\nimportant thing, is going\n\n334\n00:19:19,150 --> 00:19:21,650\nfrom just the rules to how\ndoes an expert work?\n\n335\n00:19:21,650 --> 00:19:25,800\nHow do you express common\npatterns of doing things, like\n\n336\n00:19:25,800 --> 00:19:28,580\nsaying, well, there's a general\nmethod of fixed point\n\n337\n00:19:28,580 --> 00:19:32,822\nand square root is a particular\ncase of that?\n\n338\n00:19:32,822 --> 00:19:34,290\nAnd we're going to use--\n\n339\n00:19:34,290 --> 00:19:36,640\nI've already hinted at it--\nsomething called higher-order\n\n340\n00:19:36,640 --> 00:19:40,770\nprocedures, namely procedures\nwhose inputs and outputs are\n\n341\n00:19:40,770 --> 00:19:43,230\nthemselves procedures.\n\n342\n00:19:43,230 --> 00:19:44,900\nAnd then we'll also see\nsomething very interesting.\n\n343\n00:19:44,900 --> 00:19:47,730\nWe'll see, as we go further and\nfurther on and become more\n\n344\n00:19:47,730 --> 00:19:50,310\nabstract, there'll be very--\n\n345\n00:19:50,310 --> 00:19:53,700\nwell, the line between what we\nconsider to be data and what\n\n346\n00:19:53,700 --> 00:19:56,920\nwe consider to be procedures\nis going to blur at an\n\n347\n00:19:56,920 --> 00:19:58,170\nincredible rate.\n\n348\n00:19:58,170 --> 00:20:03,270\n\n\n349\n00:20:03,270 --> 00:20:06,300\nWell, that's our first\nsubject, black-box\n\n350\n00:20:06,300 --> 00:20:07,020\nabstraction.\n\n351\n00:20:07,020 --> 00:20:08,270\nLet's look at the\nsecond topic.\n\n352\n00:20:08,270 --> 00:20:10,640\n\n\n353\n00:20:10,640 --> 00:20:13,510\nI can introduce it like this.\n\n354\n00:20:13,510 --> 00:20:19,590\nSee, suppose I want to\nexpress the idea--\n\n355\n00:20:19,590 --> 00:20:22,790\nremember, we're talking\nabout ideas--\n\n356\n00:20:22,790 --> 00:20:30,950\nsuppose I want to express the\nidea that I can take something\n\n357\n00:20:30,950 --> 00:20:36,070\nand multiply it by the sum\nof two other things.\n\n358\n00:20:36,070 --> 00:20:40,180\nSo for example, I might say, if\nI had 1 and 3 and multiply\n\n359\n00:20:40,180 --> 00:20:41,920\nthat by 2, I get 8.\n\n360\n00:20:41,920 --> 00:20:43,930\nBut I'm talking about the\ngeneral idea of what's called\n\n361\n00:20:43,930 --> 00:20:46,470\nlinear combination, that you\ncan add two things and\n\n362\n00:20:46,470 --> 00:20:49,170\nmultiply them by\nsomething else.\n\n363\n00:20:49,170 --> 00:20:51,040\nIt's very easy when I think\nabout it for numbers, but\n\n364\n00:20:51,040 --> 00:20:56,060\nsuppose I also want to use that\nsame idea to think about,\n\n365\n00:20:56,060 --> 00:21:00,920\nI could add two vectors, a1 and\na2, and then scale them by\n\n366\n00:21:00,920 --> 00:21:03,060\nsome factor x and get\nanother vector.\n\n367\n00:21:03,060 --> 00:21:08,570\nOr I might say, I want to think\nabout a1 and a2 as being\n\n368\n00:21:08,570 --> 00:21:13,720\npolynomials, and I might want\nto add those two polynomials\n\n369\n00:21:13,720 --> 00:21:16,680\nand then multiply them by 2 to\nget a more complicated one.\n\n370\n00:21:16,680 --> 00:21:20,020\n\n\n371\n00:21:20,020 --> 00:21:24,650\nOr a1 and a2 might be electrical\nsignals, and I\n\n372\n00:21:24,650 --> 00:21:26,870\nmight want to think about\nsumming those two electrical\n\n373\n00:21:26,870 --> 00:21:29,350\nsignals and then putting the\nwhole thing through an\n\n374\n00:21:29,350 --> 00:21:33,890\namplifier, multiplying it by\nsome factor of 2 or something.\n\n375\n00:21:33,890 --> 00:21:34,850\nThe idea is I want to\nthink about the\n\n376\n00:21:34,850 --> 00:21:38,530\ngeneral notion of that.\n\n377\n00:21:38,530 --> 00:21:42,880\nNow, if our language is going\nto be good language for\n\n378\n00:21:42,880 --> 00:21:47,960\nexpressing those kind of general\nideas, if I really,\n\n379\n00:21:47,960 --> 00:21:55,190\nreally can do that, I'd like to\nbe able to say I'm going to\n\n380\n00:21:55,190 --> 00:22:03,660\nmultiply by x the sum of a1 and\na2, and I'd like that to\n\n381\n00:22:03,660 --> 00:22:07,470\nexpress the general idea of all\ndifferent kinds of things\n\n382\n00:22:07,470 --> 00:22:09,980\nthat a1 and a2 could be.\n\n383\n00:22:09,980 --> 00:22:11,690\nNow, if you think about that,\nthere's a problem, because\n\n384\n00:22:11,690 --> 00:22:16,370\nafter all, the actual primitive\noperations that go\n\n385\n00:22:16,370 --> 00:22:17,870\non in the machine are obviously\ngoing to be\n\n386\n00:22:17,870 --> 00:22:22,070\ndifferent if I'm adding two\nnumbers than if I'm adding two\n\n387\n00:22:22,070 --> 00:22:25,790\npolynomials, or if I'm adding\nthe representation of two\n\n388\n00:22:25,790 --> 00:22:27,940\nelectrical signals\nor wave forms.\n\n389\n00:22:27,940 --> 00:22:30,950\nSomewhere, there has to be the\nknowledge of the kinds of\n\n390\n00:22:30,950 --> 00:22:33,140\nvarious things that you\ncan add and the\n\n391\n00:22:33,140 --> 00:22:34,390\nways of adding them.\n\n392\n00:22:34,390 --> 00:22:37,110\n\n\n393\n00:22:37,110 --> 00:22:39,430\nNow, to construct such a system,\nthe question is, where\n\n394\n00:22:39,430 --> 00:22:41,090\ndo I put that knowledge?\n\n395\n00:22:41,090 --> 00:22:43,280\nHow do I think about\nthe different kinds\n\n396\n00:22:43,280 --> 00:22:44,480\nof choices I have?\n\n397\n00:22:44,480 --> 00:22:48,310\nAnd if tomorrow George comes up\nwith a new kind of object\n\n398\n00:22:48,310 --> 00:22:51,770\nthat might be added and\nmultiplied, how do I add\n\n399\n00:22:51,770 --> 00:22:54,280\nGeorge's new object to the\nsystem without screwing up\n\n400\n00:22:54,280 --> 00:22:57,690\neverything that was\nalready there?\n\n401\n00:22:57,690 --> 00:23:00,790\nWell, that's going to be the\nsecond big topic, the way of\n\n402\n00:23:00,790 --> 00:23:03,720\ncontrolling that kind\nof complexity.\n\n403\n00:23:03,720 --> 00:23:07,480\nAnd the way you do that is by\nestablishing conventional\n\n404\n00:23:07,480 --> 00:23:20,230\ninterfaces, agreed upon ways of\nplugging things together.\n\n405\n00:23:20,230 --> 00:23:23,530\nJust like in electrical\nengineering, people have\n\n406\n00:23:23,530 --> 00:23:26,520\nstandard impedances for\nconnectors, and then you know\n\n407\n00:23:26,520 --> 00:23:28,080\nif you build something with\none of those standard\n\n408\n00:23:28,080 --> 00:23:30,160\nimpedances, you can plug it\ntogether with something else.\n\n409\n00:23:30,160 --> 00:23:32,720\n\n\n410\n00:23:32,720 --> 00:23:34,300\nSo that's going to be our\nsecond large topic,\n\n411\n00:23:34,300 --> 00:23:35,690\nconventional interfaces.\n\n412\n00:23:35,690 --> 00:23:39,000\nWhat we're going to see is,\nfirst, we're going to talk\n\n413\n00:23:39,000 --> 00:23:41,400\nabout the problem of generic\noperations, which is the one I\n\n414\n00:23:41,400 --> 00:23:46,100\nalluded to, things like \"plus\"\nthat have to work with all\n\n415\n00:23:46,100 --> 00:23:47,350\ndifferent kinds of data.\n\n416\n00:23:47,350 --> 00:23:52,149\n\n\n417\n00:23:52,149 --> 00:23:54,660\nSo we talk about generic\noperations.\n\n418\n00:23:54,660 --> 00:23:58,270\nThen we're going to talk about\nreally large-scale structures.\n\n419\n00:23:58,270 --> 00:24:01,820\nHow do you put together very\nlarge programs that model the\n\n420\n00:24:01,820 --> 00:24:03,880\nkinds of complex systems\nin the real world that\n\n421\n00:24:03,880 --> 00:24:05,480\nyou'd like to model?\n\n422\n00:24:05,480 --> 00:24:08,990\nAnd what we're going to see\nis that there are two very\n\n423\n00:24:08,990 --> 00:24:11,770\nimportant metaphors for putting\ntogether such systems.\n\n424\n00:24:11,770 --> 00:24:14,730\nOne is called object-oriented\nprogramming, where you sort of\n\n425\n00:24:14,730 --> 00:24:19,840\nthink of your system as a kind\nof society full of little\n\n426\n00:24:19,840 --> 00:24:21,150\nthings that interact by sending\n\n427\n00:24:21,150 --> 00:24:23,300\ninformation between them.\n\n428\n00:24:23,300 --> 00:24:26,540\nAnd then the second one is\noperations on aggregates,\n\n429\n00:24:26,540 --> 00:24:29,820\ncalled streams, where you think\nof a large system put\n\n430\n00:24:29,820 --> 00:24:33,530\ntogether kind of like a signal\nprocessing engineer puts\n\n431\n00:24:33,530 --> 00:24:35,020\ntogether a large electrical\nsystem.\n\n432\n00:24:35,020 --> 00:24:38,610\n\n\n433\n00:24:38,610 --> 00:24:40,240\nThat's going to be\nour second topic.\n\n434\n00:24:40,240 --> 00:24:43,370\n\n\n435\n00:24:43,370 --> 00:24:47,000\nNow, the third thing we're going\nto come to, the third\n\n436\n00:24:47,000 --> 00:24:49,640\nbasic technique for controlling\ncomplexity, is\n\n437\n00:24:49,640 --> 00:24:51,680\nmaking new languages.\n\n438\n00:24:51,680 --> 00:24:54,370\nBecause sometimes, when you're\nsort of overwhelmed by the\n\n439\n00:24:54,370 --> 00:24:56,640\ncomplexity of a design, the\nway that you control that\n\n440\n00:24:56,640 --> 00:25:01,330\ncomplexity is to pick a\nnew design language.\n\n441\n00:25:01,330 --> 00:25:03,330\nAnd the purpose of the new\ndesign language will be to\n\n442\n00:25:03,330 --> 00:25:05,730\nhighlight different aspects\nof the system.\n\n443\n00:25:05,730 --> 00:25:08,360\nIt will suppress some kinds of\ndetails and emphasize other\n\n444\n00:25:08,360 --> 00:25:09,610\nkinds of details.\n\n445\n00:25:09,610 --> 00:25:12,910\n\n\n446\n00:25:12,910 --> 00:25:15,910\nThis is going to be the most\nmagical part of the course.\n\n447\n00:25:15,910 --> 00:25:18,350\nWe're going to start out by\nactually looking at the\n\n448\n00:25:18,350 --> 00:25:21,730\ntechnology for building new\ncomputer languages.\n\n449\n00:25:21,730 --> 00:25:25,770\nThe first thing we're going to\ndo is actually build in Lisp.\n\n450\n00:25:25,770 --> 00:25:29,210\n\n\n451\n00:25:29,210 --> 00:25:32,940\nWe're going to express in Lisp\nthe process of interpreting\n\n452\n00:25:32,940 --> 00:25:33,800\nLisp itself.\n\n453\n00:25:33,800 --> 00:25:36,840\nAnd that's going to be a very\nsort of self-circular thing.\n\n454\n00:25:36,840 --> 00:25:38,870\nThere's a little mystical\nsymbol that\n\n455\n00:25:38,870 --> 00:25:40,750\nhas to do with that.\n\n456\n00:25:40,750 --> 00:25:45,500\nThe process of interpreting Lisp\nis sort of a giant wheel\n\n457\n00:25:45,500 --> 00:25:49,150\nof two processes, apply and\neval, which sort of constantly\n\n458\n00:25:49,150 --> 00:25:52,031\nreduce expressions\nto each other.\n\n459\n00:25:52,031 --> 00:25:54,150\nThen we're going to see all\nsorts of other magical things.\n\n460\n00:25:54,150 --> 00:25:56,690\nHere's another magical symbol.\n\n461\n00:25:56,690 --> 00:25:59,870\n\n\n462\n00:25:59,870 --> 00:26:02,260\nThis is sort of the Y operator,\nwhich is, in some\n\n463\n00:26:02,260 --> 00:26:04,800\nsense, the expression\nof infinity inside\n\n464\n00:26:04,800 --> 00:26:06,390\nour procedural language.\n\n465\n00:26:06,390 --> 00:26:08,610\nWe'll take a look at that.\n\n466\n00:26:08,610 --> 00:26:11,880\nIn any case, this section\nof the course is called\n\n467\n00:26:11,880 --> 00:26:24,270\nMetalinguistic Abstraction,\nabstracting by talking about\n\n468\n00:26:24,270 --> 00:26:25,535\nhow you construct\nnew languages.\n\n469\n00:26:25,535 --> 00:26:30,270\n\n\n470\n00:26:30,270 --> 00:26:34,140\nAs I said, we're going to start\nout by looking at the\n\n471\n00:26:34,140 --> 00:26:35,530\nprocess of interpretation.\n\n472\n00:26:35,530 --> 00:26:38,270\nWe're going to look\nat this apply-eval\n\n473\n00:26:38,270 --> 00:26:41,980\nloop, and build Lisp.\n\n474\n00:26:41,980 --> 00:26:44,450\nThen, just to show you that this\nis very general, we're\n\n475\n00:26:44,450 --> 00:26:47,100\ngoing to use exactly the same\ntechnology to build a very\n\n476\n00:26:47,100 --> 00:26:49,780\ndifferent kind of language, a\nso-called logic programming\n\n477\n00:26:49,780 --> 00:26:52,880\nlanguage, where you don't really\ntalk about procedures\n\n478\n00:26:52,880 --> 00:26:54,560\nat all that have inputs\nand outputs.\n\n479\n00:26:54,560 --> 00:26:57,290\nWhat you do is talk about\nrelations between things.\n\n480\n00:26:57,290 --> 00:27:01,220\nAnd then finally, we're going\nto talk about how you\n\n481\n00:27:01,220 --> 00:27:04,140\nimplement these things very\nconcretely on the very\n\n482\n00:27:04,140 --> 00:27:06,830\nsimplest kind of machines.\n\n483\n00:27:06,830 --> 00:27:09,860\nWe'll see something like this.\n\n484\n00:27:09,860 --> 00:27:14,880\nThis is a picture of a chip,\nwhich is the Lisp interpreter\n\n485\n00:27:14,880 --> 00:27:17,330\nthat we will be talking about\nthen in hardware.\n\n486\n00:27:17,330 --> 00:27:21,010\n\n\n487\n00:27:21,010 --> 00:27:24,840\nWell, there's an outline of the\ncourse, three big topics.\n\n488\n00:27:24,840 --> 00:27:28,120\nBlack-box abstraction,\nconventional interfaces,\n\n489\n00:27:28,120 --> 00:27:31,590\nmetalinguistic abstraction.\n\n490\n00:27:31,590 --> 00:27:33,480\nNow, let's take a break now and\nthen we'll get started.\n\n491\n00:27:33,480 --> 00:28:04,770\n[MUSIC PLAYING]\n\n492\n00:28:04,770 --> 00:28:08,020\nLet's actually start in\nlearning Lisp now.\n\n493\n00:28:08,020 --> 00:28:10,250\nActually, we'll start out by\nlearning something much more\n\n494\n00:28:10,250 --> 00:28:12,320\nimportant, maybe the very most\nimportant thing in this\n\n495\n00:28:12,320 --> 00:28:16,220\ncourse, which is not Lisp, in\nparticular, of course, but\n\n496\n00:28:16,220 --> 00:28:20,320\nrather a general framework for\nthinking about languages that\n\n497\n00:28:20,320 --> 00:28:21,970\nI already alluded to.\n\n498\n00:28:21,970 --> 00:28:24,420\nWhen somebody tells you they're\ngoing to show you a\n\n499\n00:28:24,420 --> 00:28:27,150\nlanguage, what you should say\nis, what I'd like you to tell\n\n500\n00:28:27,150 --> 00:28:32,510\nme is what are the primitive\nelements?\n\n501\n00:28:32,510 --> 00:28:37,490\n\n\n502\n00:28:37,490 --> 00:28:38,930\nWhat does the language\ncome with?\n\n503\n00:28:38,930 --> 00:28:43,650\nThen, what are the ways you\nput those together?\n\n504\n00:28:43,650 --> 00:28:46,720\nWhat are the means\nof combination?\n\n505\n00:28:46,720 --> 00:28:50,190\n\n\n506\n00:28:50,190 --> 00:28:53,400\nWhat are the things that allow\nyou to take these primitive\n\n507\n00:28:53,400 --> 00:28:57,920\nelements and build bigger\nthings out of them?\n\n508\n00:28:57,920 --> 00:29:01,280\nWhat are the ways of putting\nthings together?\n\n509\n00:29:01,280 --> 00:29:04,890\nAnd then, what are the\nmeans of abstraction?\n\n510\n00:29:04,890 --> 00:29:08,110\n\n\n511\n00:29:08,110 --> 00:29:15,830\nHow do we take those complicated\nthings and draw\n\n512\n00:29:15,830 --> 00:29:16,750\nthose boxes around them?\n\n513\n00:29:16,750 --> 00:29:20,180\nHow do we name them so that we\ncan now use them as if they\n\n514\n00:29:20,180 --> 00:29:22,810\nwere primitive elements\nin making still\n\n515\n00:29:22,810 --> 00:29:23,790\nmore complex things?\n\n516\n00:29:23,790 --> 00:29:26,850\nAnd so on, and so\non, and so on.\n\n517\n00:29:26,850 --> 00:29:28,580\nSo when someone says to you,\ngee, I have a great new\n\n518\n00:29:28,580 --> 00:29:32,900\ncomputer language, you don't\nsay, how many characters does\n\n519\n00:29:32,900 --> 00:29:35,810\nit take to invert a matrix?\n\n520\n00:29:35,810 --> 00:29:37,460\nIt's irrelevant.\n\n521\n00:29:37,460 --> 00:29:41,220\nWhat you say is, if the language\ndid not come with\n\n522\n00:29:41,220 --> 00:29:43,470\nmatrices built in or with\nsomething else built in, how\n\n523\n00:29:43,470 --> 00:29:45,910\ncould I then build that thing?\n\n524\n00:29:45,910 --> 00:29:47,590\nWhat are the means of\ncombination which would allow\n\n525\n00:29:47,590 --> 00:29:48,610\nme to do that?\n\n526\n00:29:48,610 --> 00:29:52,450\nAnd then, what are the means of\nabstraction which allow me\n\n527\n00:29:52,450 --> 00:29:55,750\nthen to use those as elements\nin making more complicated\n\n528\n00:29:55,750 --> 00:29:57,000\nthings yet?\n\n529\n00:29:57,000 --> 00:29:58,960\n\n\n530\n00:29:58,960 --> 00:30:02,330\nWell, we're going to see that\nLisp has some primitive data\n\n531\n00:30:02,330 --> 00:30:05,280\nand some primitive procedures.\n\n532\n00:30:05,280 --> 00:30:08,410\nIn fact, let's really start.\n\n533\n00:30:08,410 --> 00:30:09,950\nAnd here's a piece of\nprimitive data in\n\n534\n00:30:09,950 --> 00:30:16,710\nLisp, number 3.\n\n535\n00:30:16,710 --> 00:30:18,800\nActually, if I'm being\nvery pedantic, that's\n\n536\n00:30:18,800 --> 00:30:19,790\nnot the number 3.\n\n537\n00:30:19,790 --> 00:30:24,620\nThat's some symbol that\nrepresents Plato's concept of\n\n538\n00:30:24,620 --> 00:30:27,060\nthe number 3.\n\n539\n00:30:27,060 --> 00:30:30,500\nAnd here's another.\n\n540\n00:30:30,500 --> 00:30:35,370\nHere's some more primitive\ndata in Lisp, 17.4.\n\n541\n00:30:35,370 --> 00:30:40,940\nOr actually, some representation\nof 17.4.\n\n542\n00:30:40,940 --> 00:30:43,795\nAnd here's another one, 5.\n\n543\n00:30:43,795 --> 00:30:46,750\n\n\n544\n00:30:46,750 --> 00:30:48,490\nHere's another primitive\nobject that's\n\n545\n00:30:48,490 --> 00:30:52,130\nbuilt in Lisp, addition.\n\n546\n00:30:52,130 --> 00:30:56,830\nActually, to use the same kind\nof pedantic-- this is a name\n\n547\n00:30:56,830 --> 00:31:00,140\nfor the primitive method\nof adding things.\n\n548\n00:31:00,140 --> 00:31:02,920\nJust like this is a name for\nPlato's number 3, this is a\n\n549\n00:31:02,920 --> 00:31:10,370\nname for Plato's concept\nof how you add things.\n\n550\n00:31:10,370 --> 00:31:12,370\nSo those are some primitive\nelements.\n\n551\n00:31:12,370 --> 00:31:14,090\nI can put them together.\n\n552\n00:31:14,090 --> 00:31:18,140\nI can say, gee, what's the\nsum of 3 and 17.4 and 5?\n\n553\n00:31:18,140 --> 00:31:25,580\nAnd the way I do that is to\nsay, let's apply the sum\n\n554\n00:31:25,580 --> 00:31:27,600\noperator to these\nthree numbers.\n\n555\n00:31:27,600 --> 00:31:28,310\nAnd I should get, what?\n\n556\n00:31:28,310 --> 00:31:29,690\n8, 17.\n\n557\n00:31:29,690 --> 00:31:34,390\n25.4.\n\n558\n00:31:34,390 --> 00:31:37,590\nSo I should be able to ask Lisp\nwhat the value of this\n\n559\n00:31:37,590 --> 00:31:43,050\nis, and it will return 25.4.\n\n560\n00:31:43,050 --> 00:31:44,610\nLet's introduce some names.\n\n561\n00:31:44,610 --> 00:31:50,950\nThis thing that I typed is\ncalled a combination.\n\n562\n00:31:50,950 --> 00:31:56,830\n\n\n563\n00:31:56,830 --> 00:31:59,040\nAnd a combination consists,\nin general,\n\n564\n00:31:59,040 --> 00:32:02,790\nof applying an operator--\n\n565\n00:32:02,790 --> 00:32:04,220\nso this is an operator--\n\n566\n00:32:04,220 --> 00:32:09,500\n\n\n567\n00:32:09,500 --> 00:32:13,190\nto some operands.\n\n568\n00:32:13,190 --> 00:32:14,440\nThese are the operands.\n\n569\n00:32:14,440 --> 00:32:21,760\n\n\n570\n00:32:21,760 --> 00:32:23,640\nAnd of course, I can make\nmore complex things.\n\n571\n00:32:23,640 --> 00:32:25,950\nThe reason I can get complexity\nout of this is\n\n572\n00:32:25,950 --> 00:32:30,290\nbecause the operands themselves,\nin general, can be\n\n573\n00:32:30,290 --> 00:32:31,200\ncombinations.\n\n574\n00:32:31,200 --> 00:32:37,770\nSo for instance, I could say,\nwhat is the sum of 3 and the\n\n575\n00:32:37,770 --> 00:32:45,660\nproduct of 5 and\n6 and 8 and 2?\n\n576\n00:32:45,660 --> 00:32:47,520\nAnd I should get-- let's see--\n\n577\n00:32:47,520 --> 00:32:52,355\n30, 40, 43.\n\n578\n00:32:52,355 --> 00:32:56,520\nSo Lisp should tell\nme that that's 43.\n\n579\n00:32:56,520 --> 00:33:01,610\nForming combinations is the\nbasic needs of combination\n\n580\n00:33:01,610 --> 00:33:04,690\nthat we'll be looking at.\n\n581\n00:33:04,690 --> 00:33:10,520\nAnd then, well, you see\nsome syntax here.\n\n582\n00:33:10,520 --> 00:33:16,940\nLisp uses what's called prefix\nnotation, which means that the\n\n583\n00:33:16,940 --> 00:33:25,400\noperator is written to the\nleft of the operands.\n\n584\n00:33:25,400 --> 00:33:27,810\nIt's just a convention.\n\n585\n00:33:27,810 --> 00:33:29,960\nAnd notice, it's fully\nparenthesized.\n\n586\n00:33:29,960 --> 00:33:32,170\nAnd the parentheses make it\ncompletely unambiguous.\n\n587\n00:33:32,170 --> 00:33:36,840\nSo by looking at this, I can see\nthat there's the operator,\n\n588\n00:33:36,840 --> 00:33:42,760\nand there are 1, 2,\n3, 4 operands.\n\n589\n00:33:42,760 --> 00:33:46,980\nAnd I can see that the second\noperand here is itself some\n\n590\n00:33:46,980 --> 00:33:52,500\ncombination that has one\noperator and two operands.\n\n591\n00:33:52,500 --> 00:33:55,740\nParentheses in Lisp are a little\nbit, or are very unlike\n\n592\n00:33:55,740 --> 00:33:57,630\nparentheses in conventional\nmathematics.\n\n593\n00:33:57,630 --> 00:34:01,400\nIn mathematics, we sort of use\nthem to mean grouping, and it\n\n594\n00:34:01,400 --> 00:34:03,140\nsort of doesn't hurt if\nsometimes you leave out\n\n595\n00:34:03,140 --> 00:34:04,610\nparentheses if people\nunderstand\n\n596\n00:34:04,610 --> 00:34:05,790\nthat that's a group.\n\n597\n00:34:05,790 --> 00:34:07,660\nAnd in general, it doesn't\nhurt if you put in extra\n\n598\n00:34:07,660 --> 00:34:09,760\nparentheses, because that\nmaybe makes the\n\n599\n00:34:09,760 --> 00:34:10,570\ngrouping more distinct.\n\n600\n00:34:10,570 --> 00:34:13,010\nLisp is not like that.\n\n601\n00:34:13,010 --> 00:34:17,020\nIn Lisp, you cannot leave out\nparentheses, and you cannot\n\n602\n00:34:17,020 --> 00:34:20,530\nput in extra parentheses,\nbecause putting in parentheses\n\n603\n00:34:20,530 --> 00:34:23,980\nalways means, exactly and\nprecisely, this is a\n\n604\n00:34:23,980 --> 00:34:27,260\ncombination which has\nmeaning, applying\n\n605\n00:34:27,260 --> 00:34:29,050\noperators to operands.\n\n606\n00:34:29,050 --> 00:34:32,290\nAnd if I left this out, if I\nleft those parentheses out, it\n\n607\n00:34:32,290 --> 00:34:35,469\nwould mean something else.\n\n608\n00:34:35,469 --> 00:34:38,100\nIn fact, the way to think about\nthis, is really what I'm\n\n609\n00:34:38,100 --> 00:34:42,280\ndoing when I write something\nlike this is writing a tree.\n\n610\n00:34:42,280 --> 00:34:48,909\nSo this combination is a tree\nthat has a plus and then a 3\n\n611\n00:34:48,909 --> 00:34:54,500\nand then a something else\nand an 8 and a 2.\n\n612\n00:34:54,500 --> 00:34:57,670\nAnd then this something else\nhere is itself a little\n\n613\n00:34:57,670 --> 00:35:03,770\nsubtree that has a star\nand a 5 and a 6.\n\n614\n00:35:03,770 --> 00:35:07,400\nAnd the way to think of that\nis, really, what's going on\n\n615\n00:35:07,400 --> 00:35:13,260\nare we're writing these trees,\nand parentheses are just a way\n\n616\n00:35:13,260 --> 00:35:16,390\nto write this two-dimensional\nstructure as a linear\n\n617\n00:35:16,390 --> 00:35:19,130\ncharacter string.\n\n618\n00:35:19,130 --> 00:35:22,110\nBecause at least when Lisp first\nstarted and people had\n\n619\n00:35:22,110 --> 00:35:24,630\nteletypes or punch cards or\nwhatever, this was more\n\n620\n00:35:24,630 --> 00:35:25,890\nconvenient.\n\n621\n00:35:25,890 --> 00:35:29,590\nMaybe if Lisp started today,\nthe syntax of Lisp\n\n622\n00:35:29,590 --> 00:35:31,900\nwould look like that.\n\n623\n00:35:31,900 --> 00:35:33,720\nWell, let's look at\nwhat that actually\n\n624\n00:35:33,720 --> 00:35:36,450\nlooks like on the computer.\n\n625\n00:35:36,450 --> 00:35:39,320\nHere I have a Lisp interaction\nset up.\n\n626\n00:35:39,320 --> 00:35:41,060\nThere's a editor.\n\n627\n00:35:41,060 --> 00:35:43,980\nAnd on the top, I'm going to\ntype some values and ask Lisp\n\n628\n00:35:43,980 --> 00:35:45,050\nwhat they are.\n\n629\n00:35:45,050 --> 00:35:46,750\nSo for instance, I can say\nto Lisp, what's the\n\n630\n00:35:46,750 --> 00:35:49,370\nvalue of that symbol?\n\n631\n00:35:49,370 --> 00:35:50,050\nThat's 3.\n\n632\n00:35:50,050 --> 00:35:51,850\nAnd I ask Lisp to evaluate it.\n\n633\n00:35:51,850 --> 00:35:55,530\nAnd there you see Lisp has\nreturned on the bottom, and\n\n634\n00:35:55,530 --> 00:35:57,690\nsaid, oh yeah, that's 3.\n\n635\n00:35:57,690 --> 00:36:06,490\nOr I can say, what's the\nsum of 3 and 4 and 8?\n\n636\n00:36:06,490 --> 00:36:08,950\nWhat's that combination?\n\n637\n00:36:08,950 --> 00:36:10,660\nAnd ask Lisp to evaluate it.\n\n638\n00:36:10,660 --> 00:36:14,660\n\n\n639\n00:36:14,660 --> 00:36:16,246\nThat's 15.\n\n640\n00:36:16,246 --> 00:36:19,210\nOr I can type in something\nmore complicated.\n\n641\n00:36:19,210 --> 00:36:29,510\nI can say, what's the sum of the\nproduct of 3 and the sum\n\n642\n00:36:29,510 --> 00:36:35,210\nof 7 and 19.5?\n\n643\n00:36:35,210 --> 00:36:37,820\nAnd you'll notice here that Lisp\nhas something built in\n\n644\n00:36:37,820 --> 00:36:39,660\nthat helps me keep track of\nall these parentheses.\n\n645\n00:36:39,660 --> 00:36:42,260\nWatch as I type the next closed\nparentheses, which is\n\n646\n00:36:42,260 --> 00:36:45,620\ngoing to close the combination\nstarting with the star.\n\n647\n00:36:45,620 --> 00:36:48,220\nThe opening one will flash.\n\n648\n00:36:48,220 --> 00:36:50,200\nHere, I'll rub those out\nand do it again.\n\n649\n00:36:50,200 --> 00:36:53,590\nType close, and you see\nthat closes the plus.\n\n650\n00:36:53,590 --> 00:36:57,910\nClose again, that\ncloses the star.\n\n651\n00:36:57,910 --> 00:36:59,570\nNow I'm back to the sum,\nand maybe I'm going to\n\n652\n00:36:59,570 --> 00:37:01,480\nadd that all to 4.\n\n653\n00:37:01,480 --> 00:37:02,630\nThat closes the plus.\n\n654\n00:37:02,630 --> 00:37:05,750\nNow I have a complete\ncombination, and I can ask\n\n655\n00:37:05,750 --> 00:37:07,170\nLisp for the value of that.\n\n656\n00:37:07,170 --> 00:37:11,310\nThat kind of paren balancing is\nsomething that's built into\n\n657\n00:37:11,310 --> 00:37:13,630\na lot of Lisp systems to help\nyou keep track, because it is\n\n658\n00:37:13,630 --> 00:37:16,760\nkind of hard just by hand doing\nall these parentheses.\n\n659\n00:37:16,760 --> 00:37:20,520\nThere's another kind of\nconvention for keeping track\n\n660\n00:37:20,520 --> 00:37:21,100\nof parentheses.\n\n661\n00:37:21,100 --> 00:37:24,800\nLet me write another complicated\ncombination.\n\n662\n00:37:24,800 --> 00:37:33,170\nLet's take the sum of the\nproduct of 3 and 5 and add\n\n663\n00:37:33,170 --> 00:37:34,090\nthat to something.\n\n664\n00:37:34,090 --> 00:37:37,510\nAnd now what I'm going to do is\nI'm going to indent so that\n\n665\n00:37:37,510 --> 00:37:39,830\nthe operands are written\nvertically.\n\n666\n00:37:39,830 --> 00:37:47,250\nWhich the sum of that and\nthe product of 47 and--\n\n667\n00:37:47,250 --> 00:37:50,340\nlet's say the product\nof 47 with a\n\n668\n00:37:50,340 --> 00:37:54,520\ndifference of 20 and 6.8.\n\n669\n00:37:54,520 --> 00:37:58,236\nThat means subtract\n6.8 from 20.\n\n670\n00:37:58,236 --> 00:38:00,050\nAnd then you see the\nparentheses close.\n\n671\n00:38:00,050 --> 00:38:01,890\nClose the minus.\n\n672\n00:38:01,890 --> 00:38:03,572\nClose the star.\n\n673\n00:38:03,572 --> 00:38:05,150\nAnd now let's get another\noperator.\n\n674\n00:38:05,150 --> 00:38:08,230\nYou see the Lisp editor here\nis indenting to the right\n\n675\n00:38:08,230 --> 00:38:12,660\nposition automatically to\nhelp me keep track.\n\n676\n00:38:12,660 --> 00:38:13,920\nI'll do that again.\n\n677\n00:38:13,920 --> 00:38:16,220\nI'll close that last\nparentheses again.\n\n678\n00:38:16,220 --> 00:38:17,470\nYou see it balances the plus.\n\n679\n00:38:17,470 --> 00:38:20,340\n\n\n680\n00:38:20,340 --> 00:38:24,100\nNow I can say, what's\nthe value of that?\n\n681\n00:38:24,100 --> 00:38:29,620\nSo those two things, indenting\nto the right level, which is\n\n682\n00:38:29,620 --> 00:38:34,230\ncalled pretty printing, and\nflashing parentheses, are two\n\n683\n00:38:34,230 --> 00:38:37,120\nthings that a lot of Lisp\nsystems have built in to help\n\n684\n00:38:37,120 --> 00:38:37,660\nyou keep track.\n\n685\n00:38:37,660 --> 00:38:38,910\nAnd you should learn\nhow to use them.\n\n686\n00:38:38,910 --> 00:38:42,020\n\n\n687\n00:38:42,020 --> 00:38:44,640\nWell, those are the\nprimitives.\n\n688\n00:38:44,640 --> 00:38:46,190\nThere's a means of\ncombination.\n\n689\n00:38:46,190 --> 00:38:49,360\nNow let's go up to the\nmeans of abstraction.\n\n690\n00:38:49,360 --> 00:38:52,400\nI'd like to be able to take\nthe idea that I do some\n\n691\n00:38:52,400 --> 00:38:54,820\ncombination like this, and\nabstract it and give it a\n\n692\n00:38:54,820 --> 00:38:57,300\nsimple name, so I can use\nthat as an element.\n\n693\n00:38:57,300 --> 00:39:01,770\nAnd I do that in Lisp with\n\"define.\" So I can say, for\n\n694\n00:39:01,770 --> 00:39:14,515\nexample, define A to be the\nproduct of 5 and 5.\n\n695\n00:39:14,515 --> 00:39:17,936\n\n\n696\n00:39:17,936 --> 00:39:23,240\nAnd now I could say, for\nexample, to Lisp, what is the\n\n697\n00:39:23,240 --> 00:39:26,742\nproduct of A and A?\n\n698\n00:39:26,742 --> 00:39:31,980\nAnd this should be 25, and\nthis should be 625.\n\n699\n00:39:31,980 --> 00:39:36,200\nAnd then, crucial thing,\nI can now use A--\n\n700\n00:39:36,200 --> 00:39:38,360\nhere I've used it in\na combination--\n\n701\n00:39:38,360 --> 00:39:41,770\nbut I could use that in other\nmore complicated things that I\n\n702\n00:39:41,770 --> 00:39:43,440\nname in turn.\n\n703\n00:39:43,440 --> 00:39:53,970\nSo I could say, define B to be\nthe sum of, we'll say, A and\n\n704\n00:39:53,970 --> 00:40:00,260\nthe product of 5 and A. And\nthen close the plus.\n\n705\n00:40:00,260 --> 00:40:03,470\n\n\n706\n00:40:03,470 --> 00:40:04,920\nLet's take a look at that\non the computer and\n\n707\n00:40:04,920 --> 00:40:07,850\nsee how that looks.\n\n708\n00:40:07,850 --> 00:40:10,515\nSo I'll just type what\nI wrote on the board.\n\n709\n00:40:10,515 --> 00:40:21,165\nI could say, define A to be\nthe product of 5 and 5.\n\n710\n00:40:21,165 --> 00:40:23,675\n\n\n711\n00:40:23,675 --> 00:40:25,640\nAnd I'll tell that to Lisp.\n\n712\n00:40:25,640 --> 00:40:27,320\nAnd notice what Lisp responded\nthere with\n\n713\n00:40:27,320 --> 00:40:29,120\nwas an A in the bottom.\n\n714\n00:40:29,120 --> 00:40:31,680\nIn general, when you type in\na definition in Lisp, it\n\n715\n00:40:31,680 --> 00:40:35,180\nresponds with the symbol\nbeing defined.\n\n716\n00:40:35,180 --> 00:40:39,200\nNow I could say to Lisp, what\nis the product of A and A?\n\n717\n00:40:39,200 --> 00:40:42,266\n\n\n718\n00:40:42,266 --> 00:40:46,140\nAnd it says that's 625.\n\n719\n00:40:46,140 --> 00:40:59,790\nI can define B to be the sum of\nA and the product of 5 and\n\n720\n00:40:59,790 --> 00:41:03,110\nA. Close a paren closes\nthe star.\n\n721\n00:41:03,110 --> 00:41:04,600\nClose the plus.\n\n722\n00:41:04,600 --> 00:41:11,030\nClose the \"define.\" Lisp says,\nOK, B, there on the bottom.\n\n723\n00:41:11,030 --> 00:41:13,110\nAnd now I can say to Lisp,\nwhat's the value of B?\n\n724\n00:41:13,110 --> 00:41:17,100\n\n\n725\n00:41:17,100 --> 00:41:19,310\nAnd I can say something more\ncomplicated, like what's the\n\n726\n00:41:19,310 --> 00:41:26,600\nsum of A and the quotient\nof B and 5?\n\n727\n00:41:26,600 --> 00:41:30,430\nThat slash is divide, another\nprimitive operator.\n\n728\n00:41:30,430 --> 00:41:33,830\nI've divided B by 5,\nadded it to A. Lisp\n\n729\n00:41:33,830 --> 00:41:36,830\nsays, OK, that's 55.\n\n730\n00:41:36,830 --> 00:41:39,810\nSo there's what it looks like.\n\n731\n00:41:39,810 --> 00:41:43,670\nThere's the basic means\nof defining something.\n\n732\n00:41:43,670 --> 00:41:47,870\nIt's the simplest kind of\nnaming, but it's not really\n\n733\n00:41:47,870 --> 00:41:49,970\nvery powerful.\n\n734\n00:41:49,970 --> 00:41:51,760\nSee, what I'd really\nlike to name--\n\n735\n00:41:51,760 --> 00:41:53,510\nremember, we're talking about\ngeneral methods--\n\n736\n00:41:53,510 --> 00:41:56,810\nI'd like to name, oh, the\ngeneral idea that, for\n\n737\n00:41:56,810 --> 00:42:11,440\nexample, I could multiply 5 by\n5, or 6 by 6, or 1,001 by\n\n738\n00:42:11,440 --> 00:42:18,240\n1,001, 1,001.7 by 1,001.7.\n\n739\n00:42:18,240 --> 00:42:22,350\nI'd like to be able to name\nthe general idea of\n\n740\n00:42:22,350 --> 00:42:23,970\nmultiplying something\nby itself.\n\n741\n00:42:23,970 --> 00:42:28,400\n\n\n742\n00:42:28,400 --> 00:42:28,960\nWell, you know what that is.\n\n743\n00:42:28,960 --> 00:42:31,146\nThat's called squaring.\n\n744\n00:42:31,146 --> 00:42:43,640\nAnd the way I can do that in\nLisp is I can say, define to\n\n745\n00:42:43,640 --> 00:42:57,850\nsquare something x, multiply\nx by itself.\n\n746\n00:42:57,850 --> 00:43:01,260\nAnd then having done that,\nI could say to Lisp, for\n\n747\n00:43:01,260 --> 00:43:06,240\nexample, what's the\nsquare of 10?\n\n748\n00:43:06,240 --> 00:43:10,240\nAnd Lisp will say 100.\n\n749\n00:43:10,240 --> 00:43:14,796\nSo now let's actually look at\nthat a little more closely.\n\n750\n00:43:14,796 --> 00:43:17,040\nRight, there's the definition\nof square.\n\n751\n00:43:17,040 --> 00:43:23,730\nTo square something, multiply\nit by itself.\n\n752\n00:43:23,730 --> 00:43:26,210\nYou see this x here.\n\n753\n00:43:26,210 --> 00:43:28,550\nThat x is kind of a pronoun,\nwhich is the something that\n\n754\n00:43:28,550 --> 00:43:31,380\nI'm going to square.\n\n755\n00:43:31,380 --> 00:43:35,220\nAnd what I do with it\nis I multiply x, I\n\n756\n00:43:35,220 --> 00:43:36,930\nmultiply it by itself.\n\n757\n00:43:36,930 --> 00:43:44,670\n\n\n758\n00:43:44,670 --> 00:43:44,775\nOK.\n\n759\n00:43:44,775 --> 00:43:48,280\nSo there's the notation for\ndefining a procedure.\n\n760\n00:43:48,280 --> 00:43:52,500\nActually, this is a little bit\nconfusing, because this is\n\n761\n00:43:52,500 --> 00:43:53,830\nsort of how I might\nuse square.\n\n762\n00:43:53,830 --> 00:43:57,790\nAnd I say square root of x or\nsquare root of 10, but it's\n\n763\n00:43:57,790 --> 00:44:00,300\nnot making it very clear that\nI'm actually naming something.\n\n764\n00:44:00,300 --> 00:44:02,970\n\n\n765\n00:44:02,970 --> 00:44:05,790\nSo let me write this definition\nin another way that\n\n766\n00:44:05,790 --> 00:44:06,770\nmakes it a little\nbit more clear\n\n767\n00:44:06,770 --> 00:44:08,420\nthat I'm naming something.\n\n768\n00:44:08,420 --> 00:44:28,250\nI'll say, \"define\" square to\nbe lambda of x times xx.\n\n769\n00:44:28,250 --> 00:44:36,550\n\n\n770\n00:44:36,550 --> 00:44:40,480\nHere, I'm naming something\nsquare, just like over here,\n\n771\n00:44:40,480 --> 00:44:44,390\nI'm naming something A. The\nthing that I'm naming square--\n\n772\n00:44:44,390 --> 00:44:49,290\nhere, the thing I named A was\nthe value of this combination.\n\n773\n00:44:49,290 --> 00:44:52,270\nHere, the thing that I'm naming\nsquare is this thing\n\n774\n00:44:52,270 --> 00:44:55,610\nthat begins with lambda, and\nlambda is Lisp's way of saying\n\n775\n00:44:55,610 --> 00:44:56,860\nmake a procedure.\n\n776\n00:44:56,860 --> 00:45:00,150\n\n\n777\n00:45:00,150 --> 00:45:04,170\nLet's look at that more\nclosely on the slide.\n\n778\n00:45:04,170 --> 00:45:07,410\nThe way I read that definition\nis to say, I define square to\n\n779\n00:45:07,410 --> 00:45:09,910\nbe make a procedure--\n\n780\n00:45:09,910 --> 00:45:12,730\n\n\n781\n00:45:12,730 --> 00:45:14,010\nthat's what the lambda is--\n\n782\n00:45:14,010 --> 00:45:19,220\nmake a procedure with\nan argument named x.\n\n783\n00:45:19,220 --> 00:45:22,030\nAnd what it does is return\nthe results of\n\n784\n00:45:22,030 --> 00:45:24,920\nmultiplying x by itself.\n\n785\n00:45:24,920 --> 00:45:32,380\nNow, in general, we're going to\nbe using this top form of\n\n786\n00:45:32,380 --> 00:45:35,050\ndefining, just because it's a\nlittle bit more convenient.\n\n787\n00:45:35,050 --> 00:45:38,750\nBut don't lose sight of the fact\nthat it's really this.\n\n788\n00:45:38,750 --> 00:45:41,530\nIn fact, as far as the Lisp\ninterpreter's concerned,\n\n789\n00:45:41,530 --> 00:45:44,830\nthere's no difference between\ntyping this to it and typing\n\n790\n00:45:44,830 --> 00:45:46,460\nthis to it.\n\n791\n00:45:46,460 --> 00:45:54,380\nAnd there's a word for that,\nsort of syntactic sugar.\n\n792\n00:45:54,380 --> 00:45:58,400\nWhat syntactic sugar means,\nit's having somewhat more\n\n793\n00:45:58,400 --> 00:46:01,060\nconvenient surface forms\nfor typing something.\n\n794\n00:46:01,060 --> 00:46:04,470\nSo this is just really syntactic\nsugar for this\n\n795\n00:46:04,470 --> 00:46:07,310\nunderlying Greek thing\nwith the lambda.\n\n796\n00:46:07,310 --> 00:46:09,710\nAnd the reason you should\nremember that is don't forget\n\n797\n00:46:09,710 --> 00:46:12,430\nthat, when I write something\nlike this, I'm\n\n798\n00:46:12,430 --> 00:46:14,380\nreally naming something.\n\n799\n00:46:14,380 --> 00:46:17,040\nI'm naming something square,\nand the something that I'm\n\n800\n00:46:17,040 --> 00:46:21,620\nnaming square is a procedure\nthat's getting constructed.\n\n801\n00:46:21,620 --> 00:46:24,820\nWell, let's look at that\non the computer, too.\n\n802\n00:46:24,820 --> 00:46:30,660\nSo I'll come and I'll say,\ndefine square of\n\n803\n00:46:30,660 --> 00:46:34,670\nx to be times xx.\n\n804\n00:46:34,670 --> 00:46:49,570\n\n\n805\n00:46:49,570 --> 00:46:53,042\nNow I'll tell Lisp that.\n\n806\n00:46:53,042 --> 00:46:56,580\nIt says \"square.\" See, I've\nnamed something \"square.\" Now,\n\n807\n00:46:56,580 --> 00:47:00,760\nhaving done that, I can\nask Lisp for, what's\n\n808\n00:47:00,760 --> 00:47:05,230\nthe square of 1,001?\n\n809\n00:47:05,230 --> 00:47:14,920\nOr in general, I could say,\nwhat's the square of the sum\n\n810\n00:47:14,920 --> 00:47:17,340\nof 5 and 7?\n\n811\n00:47:17,340 --> 00:47:22,532\n\n\n812\n00:47:22,532 --> 00:47:25,190\nThe square of 12's 144.\n\n813\n00:47:25,190 --> 00:47:28,080\nOr I can use square itself\nas an element in some\n\n814\n00:47:28,080 --> 00:47:28,680\ncombination.\n\n815\n00:47:28,680 --> 00:47:36,240\nI can say, what's the sum\nof the square of 3 and\n\n816\n00:47:36,240 --> 00:47:37,490\nthe square of 4?\n\n817\n00:47:37,490 --> 00:47:42,480\n\n\n818\n00:47:42,480 --> 00:47:44,950\n9 and 16 is 25.\n\n819\n00:47:44,950 --> 00:47:49,580\nOr I can use square as an\nelement in some much more\n\n820\n00:47:49,580 --> 00:47:50,390\ncomplicated thing.\n\n821\n00:47:50,390 --> 00:47:53,032\nI can say, what's the square\nof, the sqare of,\n\n822\n00:47:53,032 --> 00:48:07,016\nthe square of 1,001?\n\n823\n00:48:07,016 --> 00:48:11,160\nAnd there's the square of the\nsquare of the square of 1,001.\n\n824\n00:48:11,160 --> 00:48:15,620\nOr I can say to Lisp, what\nis square itself?\n\n825\n00:48:15,620 --> 00:48:17,040\nWhat's the value of that?\n\n826\n00:48:17,040 --> 00:48:21,040\nAnd Lisp returns some\nconventional way of telling me\n\n827\n00:48:21,040 --> 00:48:22,200\nthat that's a procedure.\n\n828\n00:48:22,200 --> 00:48:24,990\nIt says, \"compound procedure\nsquare.\" Remember, the value\n\n829\n00:48:24,990 --> 00:48:30,050\nof square is this procedure, and\nthe thing with the stars\n\n830\n00:48:30,050 --> 00:48:33,810\nand the brackets are just Lisp's\nconventional way of\n\n831\n00:48:33,810 --> 00:48:37,010\ndescribing that.\n\n832\n00:48:37,010 --> 00:48:40,830\nLet's look at two more\nexamples of defining.\n\n833\n00:48:40,830 --> 00:48:45,020\n\n\n834\n00:48:45,020 --> 00:48:47,210\nHere are two more procedures.\n\n835\n00:48:47,210 --> 00:48:51,860\nI can define the average of x\nand y to be the sum of x and y\n\n836\n00:48:51,860 --> 00:48:54,460\ndivided by 2.\n\n837\n00:48:54,460 --> 00:49:00,830\nOr having had average and mean\nsquare, having had average and\n\n838\n00:49:00,830 --> 00:49:03,970\nsquare, I can use that to talk\nabout the mean square of\n\n839\n00:49:03,970 --> 00:49:08,325\nsomething, which is the average\nof the square of x and\n\n840\n00:49:08,325 --> 00:49:10,790\nthe square of y.\n\n841\n00:49:10,790 --> 00:49:13,870\nSo for example, having done\nthat, I could say, what's the\n\n842\n00:49:13,870 --> 00:49:24,915\nmean square of 2 and 3?\n\n843\n00:49:24,915 --> 00:49:29,530\nAnd I should get the average\nof 4 and 9, which is 6.5.\n\n844\n00:49:29,530 --> 00:49:32,970\n\n\n845\n00:49:32,970 --> 00:49:37,000\nThe key thing here is that,\nhaving defined square, I can\n\n846\n00:49:37,000 --> 00:49:38,560\nuse it as if it were\nprimitive.\n\n847\n00:49:38,560 --> 00:49:41,410\n\n\n848\n00:49:41,410 --> 00:49:45,200\nSo if we look here on the\nslide, if I look at mean\n\n849\n00:49:45,200 --> 00:49:50,910\nsquare, the person defining mean\nsquare doesn't have to\n\n850\n00:49:50,910 --> 00:49:54,660\nknow, at this point, whether\nsquare was something built\n\n851\n00:49:54,660 --> 00:49:57,540\ninto the language or\nwhether it was a\n\n852\n00:49:57,540 --> 00:49:59,600\nprocedure that was defined.\n\n853\n00:49:59,600 --> 00:50:04,040\nAnd that's a key thing in Lisp,\nthat you do not make\n\n854\n00:50:04,040 --> 00:50:08,230\narbitrary distinctions between\nthings that happen to be\n\n855\n00:50:08,230 --> 00:50:10,400\nprimitive in the language\nand things that\n\n856\n00:50:10,400 --> 00:50:12,740\nhappen to be built in.\n\n857\n00:50:12,740 --> 00:50:14,750\nA person using that shouldn't\neven have to know.\n\n858\n00:50:14,750 --> 00:50:17,800\nSo the things you construct get\nused with all the power\n\n859\n00:50:17,800 --> 00:50:19,700\nand flexibility as if they\nwere primitives.\n\n860\n00:50:19,700 --> 00:50:21,470\nIn fact, you can drive that\nhome by looking on the\n\n861\n00:50:21,470 --> 00:50:24,750\ncomputer one more time.\n\n862\n00:50:24,750 --> 00:50:26,680\nWe talked about plus.\n\n863\n00:50:26,680 --> 00:50:29,920\nAnd in fact, if I come here on\nthe computer screen and say,\n\n864\n00:50:29,920 --> 00:50:31,745\nwhat is the value of plus?\n\n865\n00:50:31,745 --> 00:50:34,380\n\n\n866\n00:50:34,380 --> 00:50:36,120\nNotice what Lisp types out.\n\n867\n00:50:36,120 --> 00:50:38,230\nOn the bottom there, it typed\nout, \"compound procedure\n\n868\n00:50:38,230 --> 00:50:43,070\nplus.\" Because, in this system,\nit turns out that the\n\n869\n00:50:43,070 --> 00:50:45,770\naddition operator is itself\na compound procedure.\n\n870\n00:50:45,770 --> 00:50:48,140\nAnd if I didn't just type that\nin, you'd never know that, and\n\n871\n00:50:48,140 --> 00:50:49,710\nit wouldn't make any\ndifference anyway.\n\n872\n00:50:49,710 --> 00:50:50,240\nWe don't care.\n\n873\n00:50:50,240 --> 00:50:52,500\nIt's below the level of\nthe abstraction that\n\n874\n00:50:52,500 --> 00:50:54,120\nwe're dealing with.\n\n875\n00:50:54,120 --> 00:50:57,230\nSo the key thing is you cannot\ntell, should not be able to\n\n876\n00:50:57,230 --> 00:51:00,910\ntell, in general, the difference\nbetween things that\n\n877\n00:51:00,910 --> 00:51:03,590\nare built in and things\nthat are compound.\n\n878\n00:51:03,590 --> 00:51:04,160\nWhy is that?\n\n879\n00:51:04,160 --> 00:51:06,630\nBecause the things that are\ncompound have an abstraction\n\n880\n00:51:06,630 --> 00:51:09,420\nwrapper wrapped around them.\n\n881\n00:51:09,420 --> 00:51:12,510\nWe've seen almost all the\nelements of Lisp now.\n\n882\n00:51:12,510 --> 00:51:15,090\nThere's only one more we have to\nlook at, and that is how to\n\n883\n00:51:15,090 --> 00:51:16,510\nmake a case analysis.\n\n884\n00:51:16,510 --> 00:51:18,760\nLet me show you what I mean.\n\n885\n00:51:18,760 --> 00:51:22,550\nWe might want to think about the\nmathematical definition of\n\n886\n00:51:22,550 --> 00:51:23,740\nthe absolute value functions.\n\n887\n00:51:23,740 --> 00:51:30,520\nI might say the absolute value\nof x is the function which has\n\n888\n00:51:30,520 --> 00:51:35,670\nthe property that it's\nnegative of x.\n\n889\n00:51:35,670 --> 00:51:42,580\nFor x less than 0, it's\n0 for x equal to 0.\n\n890\n00:51:42,580 --> 00:51:46,360\nAnd it's x for x\ngreater than 0.\n\n891\n00:51:46,360 --> 00:51:49,190\n\n\n892\n00:51:49,190 --> 00:51:51,490\nAnd Lisp has a way of making\ncase analyses.\n\n893\n00:51:51,490 --> 00:51:55,210\nLet me define for you\nabsolute value.\n\n894\n00:51:55,210 --> 00:52:03,080\nSay define the absolute value\nof x is conditional.\n\n895\n00:52:03,080 --> 00:52:05,075\nThis means case analysis,\nCOND.\n\n896\n00:52:05,075 --> 00:52:08,773\n\n\n897\n00:52:08,773 --> 00:52:18,760\nIf x is less than 0, the\nanswer is negate x.\n\n898\n00:52:18,760 --> 00:52:22,990\n\n\n899\n00:52:22,990 --> 00:52:24,290\nWhat I've written here\nis a clause.\n\n900\n00:52:24,290 --> 00:52:29,490\n\n\n901\n00:52:29,490 --> 00:52:33,818\nThis whole thing is a\nconditional clause,\n\n902\n00:52:33,818 --> 00:52:36,380\nand it has two parts.\n\n903\n00:52:36,380 --> 00:52:44,760\nThis part here is a predicate\nor a condition.\n\n904\n00:52:44,760 --> 00:52:45,640\nThat's a condition.\n\n905\n00:52:45,640 --> 00:52:47,680\nAnd the condition is expressed\nby something called a\n\n906\n00:52:47,680 --> 00:52:51,170\npredicate, and a predicate in\nLisp is some sort of thing\n\n907\n00:52:51,170 --> 00:52:53,440\nthat returns either\ntrue or false.\n\n908\n00:52:53,440 --> 00:52:55,490\nAnd you see Lisp has a\nprimitive procedure,\n\n909\n00:52:55,490 --> 00:53:00,510\nless-than, that tests whether\nsomething is true or false.\n\n910\n00:53:00,510 --> 00:53:06,940\nAnd the other part of a clause\nis an action or a thing to do,\n\n911\n00:53:06,940 --> 00:53:07,930\nin the case where that's true.\n\n912\n00:53:07,930 --> 00:53:12,130\nAnd here, what I'm doing\nis negating x.\n\n913\n00:53:12,130 --> 00:53:13,300\nThe negation operator, the\nminus sign in Lisp is\n\n914\n00:53:13,300 --> 00:53:14,550\na little bit funny.\n\n915\n00:53:14,550 --> 00:53:17,880\n\n\n916\n00:53:17,880 --> 00:53:19,186\nIf there's two or more\narguments, if there's two\n\n917\n00:53:19,186 --> 00:53:21,740\narguments it subtracts the\nsecond one from the first, and\n\n918\n00:53:21,740 --> 00:53:22,380\nwe saw that.\n\n919\n00:53:22,380 --> 00:53:25,280\nAnd if there's one argument,\nit negates it.\n\n920\n00:53:25,280 --> 00:53:27,700\nSo this corresponds to that.\n\n921\n00:53:27,700 --> 00:53:28,960\nAnd then there's another\nCOND clause.\n\n922\n00:53:28,960 --> 00:53:34,630\nIt says, in the case where\nx is equal to 0,\n\n923\n00:53:34,630 --> 00:53:37,482\nthe answer is 0.\n\n924\n00:53:37,482 --> 00:53:43,480\nAnd in the case where\nx is greater than 0,\n\n925\n00:53:43,480 --> 00:53:45,430\nthe answer is x.\n\n926\n00:53:45,430 --> 00:53:46,790\nClose that clause.\n\n927\n00:53:46,790 --> 00:53:48,250\nClose the COND.\n\n928\n00:53:48,250 --> 00:53:48,920\nClose the definition.\n\n929\n00:53:48,920 --> 00:53:51,110\nAnd there's the definition\nof absolute value.\n\n930\n00:53:51,110 --> 00:53:53,560\nAnd you see it's the case\nanalysis that looks very much\n\n931\n00:53:53,560 --> 00:53:55,265\nlike the case analysis you\nuse in mathematics.\n\n932\n00:53:55,265 --> 00:53:58,500\n\n\n933\n00:53:58,500 --> 00:54:02,300\nThere's a somewhat different\nway of writing a restricted\n\n934\n00:54:02,300 --> 00:54:03,090\ncase analysis.\n\n935\n00:54:03,090 --> 00:54:05,520\nOften, you have a case analysis\nwhere you only have\n\n936\n00:54:05,520 --> 00:54:08,810\none case, where you test\nsomething, and then depending\n\n937\n00:54:08,810 --> 00:54:11,000\non whether it's true or false,\nyou do something.\n\n938\n00:54:11,000 --> 00:54:16,150\nAnd here's another definition of\nabsolute value which looks\n\n939\n00:54:16,150 --> 00:54:21,010\nalmost the same, which says,\nif x is less than 0, the\n\n940\n00:54:21,010 --> 00:54:24,380\nresult is negate x.\n\n941\n00:54:24,380 --> 00:54:25,960\nOtherwise, the answer is x.\n\n942\n00:54:25,960 --> 00:54:27,120\nAnd we'll be using \"if\" a lot.\n\n943\n00:54:27,120 --> 00:54:30,650\nBut again, the thing to remember\nis that this form of\n\n944\n00:54:30,650 --> 00:54:35,130\nabsolute value that you're\nlooking at here, and then this\n\n945\n00:54:35,130 --> 00:54:37,650\none over here that I wrote\non the board, are\n\n946\n00:54:37,650 --> 00:54:39,040\nessentially the same.\n\n947\n00:54:39,040 --> 00:54:40,700\nAnd \"if\" and COND are--\n\n948\n00:54:40,700 --> 00:54:42,020\nwell, whichever way\nyou like it.\n\n949\n00:54:42,020 --> 00:54:45,100\nYou can think of COND as\nsyntactic sugar for \"if,\" or\n\n950\n00:54:45,100 --> 00:54:47,375\nyou can think of \"if\" as\nsyntactic sugar for COND, and\n\n951\n00:54:47,375 --> 00:54:48,810\nit doesn't make any\ndifference.\n\n952\n00:54:48,810 --> 00:54:51,400\nThe person implementing a Lisp\nsystem will pick one and\n\n953\n00:54:51,400 --> 00:54:52,840\nimplement the other\nin terms of that.\n\n954\n00:54:52,840 --> 00:54:54,570\nAnd it doesn't matter\nwhich one you pick.\n\n955\n00:54:54,570 --> 00:55:02,660\n\n\n956\n00:55:02,660 --> 00:55:05,640\nWhy don't we break now, and\nthen take some questions.\n\n957\n00:55:05,640 --> 00:55:11,760\nHow come sometimes when I write\ndefine, I put an open\n\n958\n00:55:11,760 --> 00:55:16,790\nparen here and say, define open\nparen something or other,\n\n959\n00:55:16,790 --> 00:55:19,480\nand sometimes when\nI write this, I\n\n960\n00:55:19,480 --> 00:55:22,330\ndon't put an open paren?\n\n961\n00:55:22,330 --> 00:55:27,550\nThe answer is, this particular\nform of \"define,\" where you\n\n962\n00:55:27,550 --> 00:55:30,850\nsay define some expression, is\nthis very special thing for\n\n963\n00:55:30,850 --> 00:55:33,630\ndefining procedures.\n\n964\n00:55:33,630 --> 00:55:37,900\nBut again, what it really means\nis I'm defining this\n\n965\n00:55:37,900 --> 00:55:41,350\nsymbol, square, to be that.\n\n966\n00:55:41,350 --> 00:55:44,810\nSo the way you should think\nabout it is what \"define\" does\n\n967\n00:55:44,810 --> 00:55:48,330\nis you write \"define,\" and the\nsecond thing you write is the\n\n968\n00:55:48,330 --> 00:55:49,830\nsymbol here-- no open paren--\n\n969\n00:55:49,830 --> 00:55:54,610\nthe symbol you're defining and\nwhat you're defining it to be.\n\n970\n00:55:54,610 --> 00:55:57,300\nThat's like here\nand like here.\n\n971\n00:55:57,300 --> 00:56:01,480\nThat's sort of the basic way\nyou use \"define.\" And then,\n\n972\n00:56:01,480 --> 00:56:05,040\nthere's this special syntactic\ntrick which allows you to\n\n973\n00:56:05,040 --> 00:56:08,140\ndefine procedures that\nlook like this.\n\n974\n00:56:08,140 --> 00:56:10,690\nSo the difference is, it's\nwhether or not you're defining\n\n975\n00:56:10,690 --> 00:56:11,755\na procedure.\n\n976\n00:56:11,755 --> 00:56:38,110\n[MUSIC PLAYING]\n\n977\n00:56:38,110 --> 00:56:42,600\nWell, believe it or not, you\nactually now know enough Lisp\n\n978\n00:56:42,600 --> 00:56:46,610\nto write essentially any\nnumerical procedure that you'd\n\n979\n00:56:46,610 --> 00:56:49,470\nwrite in a language like FORTRAN\nor Basic or whatever,\n\n980\n00:56:49,470 --> 00:56:51,656\nor, essentially, any\nother language.\n\n981\n00:56:51,656 --> 00:56:55,190\nAnd you're probably saying,\nthat's not believable, because\n\n982\n00:56:55,190 --> 00:56:56,890\nyou know that these languages\nhave things like \"for\n\n983\n00:56:56,890 --> 00:57:00,910\nstatements,\" and \"do until\nwhile\" or something.\n\n984\n00:57:00,910 --> 00:57:04,745\nBut we don't really\nneed any of that.\n\n985\n00:57:04,745 --> 00:57:06,220\nIn fact, we're not going\nto use any of\n\n986\n00:57:06,220 --> 00:57:08,180\nthat in this course.\n\n987\n00:57:08,180 --> 00:57:10,410\nLet me show you.\n\n988\n00:57:10,410 --> 00:57:14,400\nAgain, looking back at square\nroot, let's go back to this\n\n989\n00:57:14,400 --> 00:57:18,505\nsquare root algorithm of\nHeron of Alexandria.\n\n990\n00:57:18,505 --> 00:57:20,000\nRemember what that said.\n\n991\n00:57:20,000 --> 00:57:23,060\nIt said, to find an\napproximation to the square\n\n992\n00:57:23,060 --> 00:57:28,730\nroot of X, you make a guess,\nyou improve that guess by\n\n993\n00:57:28,730 --> 00:57:32,900\naveraging the guess and\nX over the guess.\n\n994\n00:57:32,900 --> 00:57:36,382\nYou keep improving that until\nthe guess is good enough.\n\n995\n00:57:36,382 --> 00:57:38,460\nI already alluded to the idea.\n\n996\n00:57:38,460 --> 00:57:44,650\nThe idea is that, if the initial\nguess that you took\n\n997\n00:57:44,650 --> 00:57:48,430\nwas actually equal to the square\nroot of X, then G here\n\n998\n00:57:48,430 --> 00:57:52,760\nwould be equal to X/G.\n\n999\n00:57:52,760 --> 00:57:54,400\nSo if you hit the square\nroot, averaging them\n\n1000\n00:57:54,400 --> 00:57:55,630\nwouldn't change it.\n\n1001\n00:57:55,630 --> 00:57:59,160\nIf the G that you picked was\nlarger than the square root of\n\n1002\n00:57:59,160 --> 00:58:03,280\nX, then X/G will be smaller than\nthe square root of X, so\n\n1003\n00:58:03,280 --> 00:58:05,890\nthat when you average\nG and X/G, you get\n\n1004\n00:58:05,890 --> 00:58:09,130\nsomething in between.\n\n1005\n00:58:09,130 --> 00:58:11,790\nSo if you pick a G that's\ntoo small, your\n\n1006\n00:58:11,790 --> 00:58:13,040\nanswer will be too large.\n\n1007\n00:58:13,040 --> 00:58:17,190\nIf you pick a G that's too\nlarge, if your G is larger\n\n1008\n00:58:17,190 --> 00:58:19,420\nthan the square root of X and\nX/G will be smaller than the\n\n1009\n00:58:19,420 --> 00:58:21,110\nsquare root of X.\n\n1010\n00:58:21,110 --> 00:58:24,460\nSo averaging always gives you\nsomething in between.\n\n1011\n00:58:24,460 --> 00:58:27,450\nAnd then, it's not quite\ntrivial, but it's possible to\n\n1012\n00:58:27,450 --> 00:58:31,050\nshow that, in fact, if G misses\nthe square root of X by\n\n1013\n00:58:31,050 --> 00:58:34,220\na little bit, the average of G\nand X/G will actually keep\n\n1014\n00:58:34,220 --> 00:58:37,800\ngetting closer to the square\nroot of X. So if you keep\n\n1015\n00:58:37,800 --> 00:58:40,140\ndoing this enough, you'll\neventually get as\n\n1016\n00:58:40,140 --> 00:58:41,680\nclose as you want.\n\n1017\n00:58:41,680 --> 00:58:44,170\nAnd then there's another fact,\nthat you can always start out\n\n1018\n00:58:44,170 --> 00:58:49,210\nthis process by using 1\nas an initial guess.\n\n1019\n00:58:49,210 --> 00:58:52,440\nAnd it'll always converge to\nthe square root of X. So\n\n1020\n00:58:52,440 --> 00:58:55,610\nthat's this method of successive\naveraging due to\n\n1021\n00:58:55,610 --> 00:58:56,660\nHeron of Alexandria.\n\n1022\n00:58:56,660 --> 00:59:00,250\nLet's write it in Lisp.\n\n1023\n00:59:00,250 --> 00:59:05,770\nWell, the central idea is, what\ndoes it mean to try a\n\n1024\n00:59:05,770 --> 00:59:07,940\nguess for the square\nroot of X?\n\n1025\n00:59:07,940 --> 00:59:09,780\nLet's write that.\n\n1026\n00:59:09,780 --> 00:59:24,310\nSo we'll say, define to try a\nguess for the square root of\n\n1027\n00:59:24,310 --> 00:59:27,750\nX, what do we do?\n\n1028\n00:59:27,750 --> 00:59:44,130\nWe'll say, if the guess is good\nenough to be a guess for\n\n1029\n00:59:44,130 --> 00:59:48,330\nthe square root of X,\nthen, as an answer,\n\n1030\n00:59:48,330 --> 00:59:51,550\nwe'll take the guess.\n\n1031\n00:59:51,550 --> 00:59:58,620\nOtherwise, we will try\nthe improved guess.\n\n1032\n00:59:58,620 --> 01:00:05,400\nWe'll improve that guess for\nthe square root of X, and\n\n1033\n01:00:05,400 --> 01:00:09,690\nwe'll try that as a guess for\nthe square root of X. Close\n\n1034\n01:00:09,690 --> 01:00:13,510\nthe \"try.\" Close the \"if.\" Close\nthe \"define.\" So that's\n\n1035\n01:00:13,510 --> 01:00:15,820\nhow we try a guess.\n\n1036\n01:00:15,820 --> 01:00:18,050\nAnd then, the next part of the\nprocess said, in order to\n\n1037\n01:00:18,050 --> 01:00:28,370\ncompute square roots, we'll\nsay, define to compute the\n\n1038\n01:00:28,370 --> 01:00:35,290\nsquare root of X, we will try\n1 as a guess for the square\n\n1039\n01:00:35,290 --> 01:00:40,280\nroot of X. Well, we have to\ndefine a couple more things.\n\n1040\n01:00:40,280 --> 01:00:43,770\nWe have to say, how is\na guess good enough?\n\n1041\n01:00:43,770 --> 01:00:45,545\nAnd how do we improve a guess?\n\n1042\n01:00:45,545 --> 01:00:47,380\nSo let's look at that.\n\n1043\n01:00:47,380 --> 01:00:53,650\nThe algorithm to improve a guess\nfor the square root of\n\n1044\n01:00:53,650 --> 01:00:55,640\nX, we average--\n\n1045\n01:00:55,640 --> 01:00:57,000\nthat was the algorithm--\n\n1046\n01:00:57,000 --> 01:01:00,680\nwe average the guess with\nthe quotient of\n\n1047\n01:01:00,680 --> 01:01:03,030\ndividing X by the guess.\n\n1048\n01:01:03,030 --> 01:01:05,810\nThat's how we improve a guess.\n\n1049\n01:01:05,810 --> 01:01:07,720\nAnd to tell whether a guess is\ngood enough, well, we have to\n\n1050\n01:01:07,720 --> 01:01:09,530\ndecide something.\n\n1051\n01:01:09,530 --> 01:01:11,510\nThis is supposed to be a guess\nfor the square root of X, so\n\n1052\n01:01:11,510 --> 01:01:14,700\none possible thing you can do\nis say, when you take that\n\n1053\n01:01:14,700 --> 01:01:19,110\nguess and square it, do you get\nsomething very close to X?\n\n1054\n01:01:19,110 --> 01:01:22,870\nSo one way to say that is to\nsay, I square the guess,\n\n1055\n01:01:22,870 --> 01:01:26,900\nsubtract X from that, and see if\nthe absolute value of that\n\n1056\n01:01:26,900 --> 01:01:31,200\nwhole thing is less than some\nsmall number, which depends on\n\n1057\n01:01:31,200 --> 01:01:32,450\nmy purposes.\n\n1058\n01:01:32,450 --> 01:01:35,080\n\n\n1059\n01:01:35,080 --> 01:01:40,410\nSo there's a complete procedure\nfor how to compute\n\n1060\n01:01:40,410 --> 01:01:42,830\nthe square root of X. Let's look\nat the structure of that\n\n1061\n01:01:42,830 --> 01:01:44,080\na little bit.\n\n1062\n01:01:44,080 --> 01:01:47,970\n\n\n1063\n01:01:47,970 --> 01:01:49,100\nI have the whole thing.\n\n1064\n01:01:49,100 --> 01:01:55,370\nI have the notion of how to\ncompute a square root.\n\n1065\n01:01:55,370 --> 01:01:56,960\nThat's some kind of module.\n\n1066\n01:01:56,960 --> 01:01:58,580\nThat's some kind of black box.\n\n1067\n01:01:58,580 --> 01:02:07,340\nIt's defined in terms of how to\ntry a guess for the square\n\n1068\n01:02:07,340 --> 01:02:09,090\nroot of X.\n\n1069\n01:02:09,090 --> 01:02:15,110\n\"Try\" is defined in terms of,\nwell, telling whether\n\n1070\n01:02:15,110 --> 01:02:16,640\nsomething is good enough\nand telling\n\n1071\n01:02:16,640 --> 01:02:18,680\nhow to improve something.\n\n1072\n01:02:18,680 --> 01:02:19,800\nSo good enough.\n\n1073\n01:02:19,800 --> 01:02:30,790\n\"Try\" is defined in terms of\n\"good enough\" and \"improve.\"\n\n1074\n01:02:30,790 --> 01:02:32,170\nAnd let's see what\nelse I fill in.\n\n1075\n01:02:32,170 --> 01:02:34,640\nWell, I'll go down this tree.\n\n1076\n01:02:34,640 --> 01:02:36,040\n\"Good enough\" was defined\nin terms of\n\n1077\n01:02:36,040 --> 01:02:37,930\nabsolute value, and square.\n\n1078\n01:02:37,930 --> 01:02:40,910\n\n\n1079\n01:02:40,910 --> 01:02:43,290\nAnd improve was defined in\nterms of something called\n\n1080\n01:02:43,290 --> 01:02:47,340\naveraging and then some other\nprimitive operator.\n\n1081\n01:02:47,340 --> 01:02:49,530\nSquare root's defined in terms\nof \"try.\" \"Try\" is defined in\n\n1082\n01:02:49,530 --> 01:02:53,860\nterms of \"good enough\"\nand \"improve,\"\n\n1083\n01:02:53,860 --> 01:02:55,410\nbut also \"try\" itself.\n\n1084\n01:02:55,410 --> 01:03:02,750\nSo \"try\" is also defined in\nterms of how to try itself.\n\n1085\n01:03:02,750 --> 01:03:06,240\nWell, that may give you some\nproblems. Your high school\n\n1086\n01:03:06,240 --> 01:03:10,680\ngeometry teacher probably told\nyou that it's naughty to try\n\n1087\n01:03:10,680 --> 01:03:13,360\nand define things in terms of\nthemselves, because it doesn't\n\n1088\n01:03:13,360 --> 01:03:13,810\nmake sense.\n\n1089\n01:03:13,810 --> 01:03:16,440\nBut that's false.\n\n1090\n01:03:16,440 --> 01:03:18,730\nSometimes it makes perfect\nsense to define things in\n\n1091\n01:03:18,730 --> 01:03:20,210\nterms of themselves.\n\n1092\n01:03:20,210 --> 01:03:22,918\nAnd this is the case.\n\n1093\n01:03:22,918 --> 01:03:24,150\nAnd we can look at that.\n\n1094\n01:03:24,150 --> 01:03:28,140\nWe could write down what this\nmeans, and say, suppose I\n\n1095\n01:03:28,140 --> 01:03:30,100\nasked Lisp what the square\nroot of 2 is.\n\n1096\n01:03:30,100 --> 01:03:32,690\n\n\n1097\n01:03:32,690 --> 01:03:35,710\nWhat's the square\nroot of 2 mean?\n\n1098\n01:03:35,710 --> 01:03:42,700\nWell, that means I try\n1 as a guess for the\n\n1099\n01:03:42,700 --> 01:03:43,950\nsquare root of 2.\n\n1100\n01:03:43,950 --> 01:03:47,100\n\n\n1101\n01:03:47,100 --> 01:03:47,760\nNow I look.\n\n1102\n01:03:47,760 --> 01:03:50,000\nI say, gee, is 1 a good\nenough guess for the\n\n1103\n01:03:50,000 --> 01:03:51,140\nsquare root of 2?\n\n1104\n01:03:51,140 --> 01:03:54,140\nAnd that depends on the test\nthat \"good enough\" does.\n\n1105\n01:03:54,140 --> 01:03:57,240\nAnd in this case, \"good enough\"\nwill say, no, 1 is not\n\n1106\n01:03:57,240 --> 01:03:59,740\na good enough guess for\nthe square root of 2.\n\n1107\n01:03:59,740 --> 01:04:10,350\nSo that will reduce to saying,\nI have to try an improved--\n\n1108\n01:04:10,350 --> 01:04:15,910\nimprove 1 as a guess for the\nsquare root of 2, and try that\n\n1109\n01:04:15,910 --> 01:04:19,110\nas a guess for the\nsquare root of 2.\n\n1110\n01:04:19,110 --> 01:04:22,350\nImproving 1 as a guess for the\nsquare root of 2 means I\n\n1111\n01:04:22,350 --> 01:04:27,270\naverage 1 and 2 divided by 1.\n\n1112\n01:04:27,270 --> 01:04:29,550\nSo this is going\nto be average.\n\n1113\n01:04:29,550 --> 01:04:37,830\nThis piece here will be the\naverage of 1 and the\n\n1114\n01:04:37,830 --> 01:04:40,930\nquotient of 2 by 1.\n\n1115\n01:04:40,930 --> 01:04:44,910\nThat's this piece here.\n\n1116\n01:04:44,910 --> 01:04:46,160\nAnd this is 1.5.\n\n1117\n01:04:46,160 --> 01:04:49,060\n\n\n1118\n01:04:49,060 --> 01:04:53,670\nSo this square root of 2 reduces\nto trying 1 for the\n\n1119\n01:04:53,670 --> 01:05:03,370\nsquare root of 2, which reduces\nto trying 1.5 as a\n\n1120\n01:05:03,370 --> 01:05:06,220\nguess for the square\nroot of 2.\n\n1121\n01:05:06,220 --> 01:05:07,880\nSo that makes sense.\n\n1122\n01:05:07,880 --> 01:05:09,650\nLet's look at the rest\nof the process.\n\n1123\n01:05:09,650 --> 01:05:14,890\nIf I try 1.5, that reduces.\n\n1124\n01:05:14,890 --> 01:05:18,210\n1.5 turns out to be not good\nenough as a guess for the\n\n1125\n01:05:18,210 --> 01:05:20,130\nsquare root of 2.\n\n1126\n01:05:20,130 --> 01:05:23,340\nSo that reduces to trying the\naverage of 1.5 and 2 divided\n\n1127\n01:05:23,340 --> 01:05:28,200\nby 1.5 as a guess for the\nsquare root of 2.\n\n1128\n01:05:28,200 --> 01:05:31,110\nThat average turns\nout to be 1.333.\n\n1129\n01:05:31,110 --> 01:05:34,215\nSo this whole thing reduces to\ntrying 1.333 as a guess for\n\n1130\n01:05:34,215 --> 01:05:35,130\nthe square root of 2.\n\n1131\n01:05:35,130 --> 01:05:37,910\nAnd then so on.\n\n1132\n01:05:37,910 --> 01:05:40,750\nThat reduces to another called\na \"good enough,\" 1.4\n\n1133\n01:05:40,750 --> 01:05:41,630\nsomething or other.\n\n1134\n01:05:41,630 --> 01:05:45,160\nAnd then it keeps going until\nthe process finally stops with\n\n1135\n01:05:45,160 --> 01:05:47,780\nsomething that \"good enough\"\nthinks is good enough, which,\n\n1136\n01:05:47,780 --> 01:05:52,500\nin this case, is 1.4142\nsomething or other.\n\n1137\n01:05:52,500 --> 01:05:55,890\nSo the process makes\nperfect sense.\n\n1138\n01:05:55,890 --> 01:05:59,710\n\n\n1139\n01:05:59,710 --> 01:06:02,620\nThis, by the way, is called\na recursive definition.\n\n1140\n01:06:02,620 --> 01:06:14,410\n\n\n1141\n01:06:14,410 --> 01:06:19,470\nAnd the ability to make\nrecursive definitions is a\n\n1142\n01:06:19,470 --> 01:06:20,710\nsource of incredible power.\n\n1143\n01:06:20,710 --> 01:06:24,040\nAnd as you can already see I've\nhinted at, it's the thing\n\n1144\n01:06:24,040 --> 01:06:27,160\nthat effectively allows you to\ndo these infinite computations\n\n1145\n01:06:27,160 --> 01:06:30,730\nthat go on until something is\ntrue, without having any other\n\n1146\n01:06:30,730 --> 01:06:33,235\nconstricts other than the\nability to call a procedure.\n\n1147\n01:06:33,235 --> 01:06:35,890\n\n\n1148\n01:06:35,890 --> 01:06:37,970\nWell, let's see, there's\none more thing.\n\n1149\n01:06:37,970 --> 01:06:43,210\nLet me show you a variant of\nthis definition of square root\n\n1150\n01:06:43,210 --> 01:06:46,300\nhere on the slide.\n\n1151\n01:06:46,300 --> 01:06:48,320\nHere's sort of the same thing.\n\n1152\n01:06:48,320 --> 01:06:51,430\nWhat I've done here is packaged\nthe definitions of\n\n1153\n01:06:51,430 --> 01:06:55,340\n\"improve\" and \"good enough\"\nand \"try\" inside \"square\n\n1154\n01:06:55,340 --> 01:06:59,760\nroot.\" So, in effect, what\nI've done is I've built a\n\n1155\n01:06:59,760 --> 01:07:01,860\nsquare root box.\n\n1156\n01:07:01,860 --> 01:07:07,320\nSo I've built a box that's the\nsquare root procedure that\n\n1157\n01:07:07,320 --> 01:07:08,150\nsomeone can use.\n\n1158\n01:07:08,150 --> 01:07:11,910\nThey might put in 36\nand get out 6.\n\n1159\n01:07:11,910 --> 01:07:15,080\nAnd then, packaged inside this\nbox are the definitions of\n\n1160\n01:07:15,080 --> 01:07:26,530\n\"try\" and \"good enough\"\nand \"improve.\"\n\n1161\n01:07:26,530 --> 01:07:28,260\nSo they're hidden\ninside this box.\n\n1162\n01:07:28,260 --> 01:07:32,010\nAnd the reason for doing that\nis that, if someone's using\n\n1163\n01:07:32,010 --> 01:07:34,920\nthis square root, if George is\nusing this square root, George\n\n1164\n01:07:34,920 --> 01:07:39,180\nprobably doesn't care very much\nthat, when I implemented\n\n1165\n01:07:39,180 --> 01:07:42,600\nsquare root, I had things inside\nthere called \"try\" and\n\n1166\n01:07:42,600 --> 01:07:48,150\n\"good enough\" and \"improve.\" And\nin fact, Harry might have\n\n1167\n01:07:48,150 --> 01:07:50,300\na cube root procedure that has\n\"try\" and \"good enough\" and\n\n1168\n01:07:50,300 --> 01:07:53,260\n\"improve.\" And in order to not\nget the whole system confused,\n\n1169\n01:07:53,260 --> 01:07:55,430\nit'd be good for Harry to\npackage his internal\n\n1170\n01:07:55,430 --> 01:07:58,320\nprocedures inside his\ncube root procedure.\n\n1171\n01:07:58,320 --> 01:08:00,970\nWell, this is called block\nstructure, this particular way\n\n1172\n01:08:00,970 --> 01:08:09,940\nof packaging internals inside\nof a definition.\n\n1173\n01:08:09,940 --> 01:08:13,040\nAnd let's go back and look\nat the slide again.\n\n1174\n01:08:13,040 --> 01:08:17,720\nThe way to read this kind of\nprocedure is to say, to define\n\n1175\n01:08:17,720 --> 01:08:23,010\n\"square root,\" well, inside that\ndefinition, I'll have the\n\n1176\n01:08:23,010 --> 01:08:26,479\ndefinition of an \"improve\" and\nthe definition of \"good\n\n1177\n01:08:26,479 --> 01:08:31,149\nenough\" and the definition of\n\"try.\" And then, subject to\n\n1178\n01:08:31,149 --> 01:08:36,010\nthose definitions, the way I\ndo square root is to try 1.\n\n1179\n01:08:36,010 --> 01:08:38,310\nAnd notice here, I don't have\nto say 1 as a guess for the\n\n1180\n01:08:38,310 --> 01:08:41,290\nsquare root of X, because since\nit's all inside the\n\n1181\n01:08:41,290 --> 01:08:44,270\nsquare root, it sort of\nhas this X known.\n\n1182\n01:08:44,270 --> 01:08:54,770\n\n\n1183\n01:08:54,770 --> 01:08:56,510\nLet me summarize.\n\n1184\n01:08:56,510 --> 01:08:59,890\nWe started out with the idea\nthat what we're going to be\n\n1185\n01:08:59,890 --> 01:09:04,960\ndoing is expressing imperative\nknowledge.\n\n1186\n01:09:04,960 --> 01:09:08,960\nAnd in fact, here's a slide\nthat summarizes the way we\n\n1187\n01:09:08,960 --> 01:09:09,680\nlooked at Lisp.\n\n1188\n01:09:09,680 --> 01:09:13,609\nWe started out by looking at\nsome primitive elements in\n\n1189\n01:09:13,609 --> 01:09:17,609\naddition and multiplication,\nsome predicates for testing\n\n1190\n01:09:17,609 --> 01:09:19,630\nwhether something is less-than\nor something's equal.\n\n1191\n01:09:19,630 --> 01:09:22,330\nAnd in fact, we saw really\nsneakily in the system we're\n\n1192\n01:09:22,330 --> 01:09:25,160\nactually using, these aren't\nactually primitives, but it\n\n1193\n01:09:25,160 --> 01:09:26,550\ndoesn't matter.\n\n1194\n01:09:26,550 --> 01:09:28,120\nWhat matters is we're going\nto use them as if they're\n\n1195\n01:09:28,120 --> 01:09:28,510\nprimitives.\n\n1196\n01:09:28,510 --> 01:09:30,220\nWe're not going to\nlook inside.\n\n1197\n01:09:30,220 --> 01:09:34,540\nWe also have some primitive\ndata and some numbers.\n\n1198\n01:09:34,540 --> 01:09:36,830\nWe saw some means of\ncomposition, means of\n\n1199\n01:09:36,830 --> 01:09:41,300\ncombination, the basic one being\ncomposing functions and\n\n1200\n01:09:41,300 --> 01:09:44,840\nbuilding combinations with\noperators and operands.\n\n1201\n01:09:44,840 --> 01:09:47,600\nAnd there were some other\nthings, like COND and \"if\" and\n\n1202\n01:09:47,600 --> 01:09:53,790\n\"define.\" But the main thing\nabout \"define,\" in particular,\n\n1203\n01:09:53,790 --> 01:09:55,710\nwas that it was the means\nof abstraction.\n\n1204\n01:09:55,710 --> 01:09:57,670\nIt was the way that\nwe name things.\n\n1205\n01:09:57,670 --> 01:09:59,770\nYou can also see from this slide\nnot only where we've\n\n1206\n01:09:59,770 --> 01:10:01,450\nbeen, but holes we\nhave to fill in.\n\n1207\n01:10:01,450 --> 01:10:03,930\nAt some point, we'll have to\ntalk about how you combine\n\n1208\n01:10:03,930 --> 01:10:07,720\nprimitive data to get compound\ndata, and how you abstract\n\n1209\n01:10:07,720 --> 01:10:11,950\ndata so you can use large\nglobs of data as\n\n1210\n01:10:11,950 --> 01:10:13,900\nif they were primitive.\n\n1211\n01:10:13,900 --> 01:10:16,370\nSo that's where we're going.\n\n1212\n01:10:16,370 --> 01:10:20,790\nBut before we do that, for the\nnext couple of lectures we're\n\n1213\n01:10:20,790 --> 01:10:25,720\ngoing to be talking about, first\nof all, how it is that\n\n1214\n01:10:25,720 --> 01:10:28,900\nyou make a link between these\nprocedures we write and the\n\n1215\n01:10:28,900 --> 01:10:32,040\nprocesses that happen\nin the machine.\n\n1216\n01:10:32,040 --> 01:10:36,210\nAnd then, how it is that you\nstart using the power of Lisp\n\n1217\n01:10:36,210 --> 01:10:38,710\nto talk not only about these\nindividual little\n\n1218\n01:10:38,710 --> 01:10:43,080\ncomputations, but about general\nconventional methods\n\n1219\n01:10:43,080 --> 01:10:45,200\nof doing things.\n\n1220\n01:10:45,200 --> 01:10:46,730\nOK, are there any questions?\n\n1221\n01:10:46,730 --> 01:10:47,640\nAUDIENCE: Yes.\n\n1222\n01:10:47,640 --> 01:10:51,880\nIf we defined A using\nparentheses instead of as we\n\n1223\n01:10:51,880 --> 01:10:53,400\ndid, what would be\nthe difference?\n\n1224\n01:10:53,400 --> 01:10:58,130\nPROFESSOR: If I wrote this, if\nI wrote that, what I would be\n\n1225\n01:10:58,130 --> 01:11:03,740\ndoing is defining a procedure\nnamed A. In this case, a\n\n1226\n01:11:03,740 --> 01:11:07,950\nprocedure of no arguments,\nwhich, when I ran it, would\n\n1227\n01:11:07,950 --> 01:11:10,274\ngive me back 5 times 5.\n\n1228\n01:11:10,274 --> 01:11:10,716\nAUDIENCE: Right.\n\n1229\n01:11:10,716 --> 01:11:12,610\nI mean, you come up with the\nsame thing, except for you\n\n1230\n01:11:12,610 --> 01:11:13,940\nreally got a different--\n\n1231\n01:11:13,940 --> 01:11:14,120\nPROFESSOR: Right.\n\n1232\n01:11:14,120 --> 01:11:16,330\nAnd the difference would\nbe, in the old one--\n\n1233\n01:11:16,330 --> 01:11:19,180\nLet me be a little\nbit clearer here.\n\n1234\n01:11:19,180 --> 01:11:24,070\nLet's call this A, like here.\n\n1235\n01:11:24,070 --> 01:11:35,060\nAnd pretend here, just for\ncontrast, I wrote, define D to\n\n1236\n01:11:35,060 --> 01:11:37,300\nbe the product of 5 and 5.\n\n1237\n01:11:37,300 --> 01:11:40,200\n\n\n1238\n01:11:40,200 --> 01:11:42,450\nAnd the difference between\nthose, let's think about\n\n1239\n01:11:42,450 --> 01:11:45,770\ninteractions with the\nLisp interpreter.\n\n1240\n01:11:45,770 --> 01:11:52,860\nI could type in A and Lisp\nwould return 25.\n\n1241\n01:11:52,860 --> 01:12:01,240\nI could type in D, if I just\ntyped in D, Lisp would return\n\n1242\n01:12:01,240 --> 01:12:08,000\ncompound procedure D, because\nthat's what it is.\n\n1243\n01:12:08,000 --> 01:12:09,670\nIt's a procedure.\n\n1244\n01:12:09,670 --> 01:12:12,500\nI could run D. I could say,\nwhat's the value of running D?\n\n1245\n01:12:12,500 --> 01:12:16,520\nHere is a combination\nwith no operands.\n\n1246\n01:12:16,520 --> 01:12:17,570\nI see there are no operands.\n\n1247\n01:12:17,570 --> 01:12:22,940\nI didn't put any after D. And\nit would say, oh, that's 25.\n\n1248\n01:12:22,940 --> 01:12:28,070\nOr I could say, just for\ncompleteness, if I typed in,\n\n1249\n01:12:28,070 --> 01:12:29,310\nwhat's the value of running A?\n\n1250\n01:12:29,310 --> 01:12:31,690\nI get an error.\n\n1251\n01:12:31,690 --> 01:12:35,150\nThe error would be the same\none as over there.\n\n1252\n01:12:35,150 --> 01:12:40,010\nIt'd be the error would say,\nsorry, 25, which is the value\n\n1253\n01:12:40,010 --> 01:12:43,720\nof A, is not an operator that\nI can apply to something.\n\n1254\n01:12:43,720 --> 01:12:53,076\n\n"
  },
  {
    "path": "SrtEN/lec1b_512kb.mp4.srt",
    "content": "1\n00:00:00,000 --> 00:00:14,550\n[MUSIC PLAYING BY J.S. BACH]\n\n2\n00:00:14,550 --> 00:00:16,320\nPROFESSOR: Hi.\n\n3\n00:00:16,320 --> 00:00:20,050\nYou've seen that the job of\na programmer is to design\n\n4\n00:00:20,050 --> 00:00:24,070\nprocesses that accomplish\nparticular goals, such as\n\n5\n00:00:24,070 --> 00:00:27,050\nfinding the square roots of\nnumbers or other sorts of\n\n6\n00:00:27,050 --> 00:00:28,830\nthings you might want to do.\n\n7\n00:00:28,830 --> 00:00:32,080\nWe haven't introduced\nanything else yet.\n\n8\n00:00:32,080 --> 00:00:34,370\nOf course, the way in which a\nprogrammer does this is by\n\n9\n00:00:34,370 --> 00:00:39,440\nconstructing spells, which are\nconstructed out of procedures\n\n10\n00:00:39,440 --> 00:00:41,050\nand expressions.\n\n11\n00:00:41,050 --> 00:00:46,000\nAnd that these spells are\nsomehow direct a process to\n\n12\n00:00:46,000 --> 00:00:49,190\naccomplish the goal that was\nintended by the programmer.\n\n13\n00:00:49,190 --> 00:00:51,670\nIn order for the programmer to\ndo this effectively, he has to\n\n14\n00:00:51,670 --> 00:00:54,330\nunderstand the relationship\nbetween the particular things\n\n15\n00:00:54,330 --> 00:00:56,830\nthat he writes, these particular\nspells, and the\n\n16\n00:00:56,830 --> 00:01:01,630\nbehavior of the process that\nhe's attempting to control.\n\n17\n00:01:01,630 --> 00:01:03,560\nSo what we're doing this\nlecture is attempt to\n\n18\n00:01:03,560 --> 00:01:07,630\nestablish that connection in\nas clear a way as possible.\n\n19\n00:01:07,630 --> 00:01:10,450\nWhat we will particularly do is\nunderstand how particular\n\n20\n00:01:10,450 --> 00:01:15,300\npatterns of procedures and\nexpressions cause particular\n\n21\n00:01:15,300 --> 00:01:17,230\npatterns of execution,\nparticular\n\n22\n00:01:17,230 --> 00:01:19,050\nbehaviors from the processes.\n\n23\n00:01:19,050 --> 00:01:22,420\n\n\n24\n00:01:22,420 --> 00:01:24,190\nLet's get down to that.\n\n25\n00:01:24,190 --> 00:01:28,240\nI'm going to start with\na very simple program.\n\n26\n00:01:28,240 --> 00:01:29,680\nThis is a program to compute\nthe sum of the\n\n27\n00:01:29,680 --> 00:01:33,630\nsquares of two numbers.\n\n28\n00:01:33,630 --> 00:01:45,970\nAnd we'll define the sum of the\nsquares of x and y to be\n\n29\n00:01:45,970 --> 00:01:49,835\nthe sum of the square of x--\n\n30\n00:01:49,835 --> 00:01:51,460\nI'm going to write\nit that way--\n\n31\n00:01:51,460 --> 00:02:08,690\nand the square of y where\nthe square of x is the\n\n32\n00:02:08,690 --> 00:02:10,830\nproduct of x and x.\n\n33\n00:02:10,830 --> 00:02:14,220\n\n\n34\n00:02:14,220 --> 00:02:17,670\nNow, supposing I were to say\nsomething to this, like, to\n\n35\n00:02:17,670 --> 00:02:20,845\nthe system after having defined\nthese things, of the\n\n36\n00:02:20,845 --> 00:02:26,420\nform, the sum of the squares of\n3 and 4, I am hoping that I\n\n37\n00:02:26,420 --> 00:02:29,310\nwill get out a 25.\n\n38\n00:02:29,310 --> 00:02:33,090\nBecause the square of 3 is 9,\nand the square of 4 is 16, and\n\n39\n00:02:33,090 --> 00:02:34,900\n25 is the sum of those.\n\n40\n00:02:34,900 --> 00:02:36,720\nBut how does that happen?\n\n41\n00:02:36,720 --> 00:02:39,730\nIf we're going to understand\nprocesses and how we control\n\n42\n00:02:39,730 --> 00:02:43,910\nthem, then we have to have a\nmapping from the mechanisms of\n\n43\n00:02:43,910 --> 00:02:49,540\nthis procedure into the way in\nwhich these processes behave.\n\n44\n00:02:49,540 --> 00:02:52,380\nWhat we're going to have is\na formal, or semi-formal,\n\n45\n00:02:52,380 --> 00:02:56,180\nmechanical model whereby you\nunderstand how a machine\n\n46\n00:02:56,180 --> 00:02:57,920\ncould, in fact, in principle,\ndo this.\n\n47\n00:02:57,920 --> 00:03:00,660\nWhether or not the actual\nmachine really does what I'm\n\n48\n00:03:00,660 --> 00:03:01,860\nabout to tell you is completely\n\n49\n00:03:01,860 --> 00:03:03,840\nirrelevant at this moment.\n\n50\n00:03:03,840 --> 00:03:06,290\nIn fact, this is an engineering\nmodel in the same\n\n51\n00:03:06,290 --> 00:03:09,600\nway that, electrical resistor,\nwe write down a model v equals\n\n52\n00:03:09,600 --> 00:03:12,330\ni r, it's approximately true.\n\n53\n00:03:12,330 --> 00:03:13,880\nIt's not really true.\n\n54\n00:03:13,880 --> 00:03:16,860\nIf I put up current through\nthe resistor it goes boom.\n\n55\n00:03:16,860 --> 00:03:20,410\nSo the voltage is not always\nproportional to the current,\n\n56\n00:03:20,410 --> 00:03:24,200\nbut for some purposes the\nmodel is appropriate.\n\n57\n00:03:24,200 --> 00:03:26,640\nIn particular, the model we're\ngoing to describe right now,\n\n58\n00:03:26,640 --> 00:03:29,770\nwhich I call the substitution\nmodel, is the simplest model\n\n59\n00:03:29,770 --> 00:03:32,700\nthat we have for understanding\nhow procedures work and how\n\n60\n00:03:32,700 --> 00:03:34,310\nprocesses work.\n\n61\n00:03:34,310 --> 00:03:36,350\nHow procedures yield\nprocesses.\n\n62\n00:03:36,350 --> 00:03:39,150\nAnd that substitution model will\nbe accurate for most of\n\n63\n00:03:39,150 --> 00:03:41,790\nthe things we'll be dealing\nwith in the next few days.\n\n64\n00:03:41,790 --> 00:03:45,240\nBut eventually, it will become\nimpossible to sustain the\n\n65\n00:03:45,240 --> 00:03:47,060\nillusion that that's the way the\nmachine works, and we'll\n\n66\n00:03:47,060 --> 00:03:50,490\ngo to other more specific and\nparticular models that will\n\n67\n00:03:50,490 --> 00:03:53,590\nshow more detail.\n\n68\n00:03:53,590 --> 00:03:58,200\nOK, well, the first thing, of\ncourse, is we say, what are\n\n69\n00:03:58,200 --> 00:03:59,170\nthe things we have here?\n\n70\n00:03:59,170 --> 00:04:00,550\nWe have some cryptic symbols.\n\n71\n00:04:00,550 --> 00:04:04,350\nAnd these cryptic symbols\nare made out of pieces.\n\n72\n00:04:04,350 --> 00:04:05,990\nThere are kinds of\nexpressions.\n\n73\n00:04:05,990 --> 00:04:07,410\nSo let's write down\nhere the kinds of\n\n74\n00:04:07,410 --> 00:04:08,660\nexpressions there are.\n\n75\n00:04:08,660 --> 00:04:17,890\n\n\n76\n00:04:17,890 --> 00:04:20,295\nAnd we have-- and so far I\nsee things like numbers.\n\n77\n00:04:20,295 --> 00:04:25,370\n\n\n78\n00:04:25,370 --> 00:04:28,030\nI see things like symbols\nlike that.\n\n79\n00:04:28,030 --> 00:04:32,160\n\n\n80\n00:04:32,160 --> 00:04:35,430\nWe have seen things before like\nlambda expressions, but\n\n81\n00:04:35,430 --> 00:04:36,190\nthey're not here.\n\n82\n00:04:36,190 --> 00:04:37,180\nI'm going to leave them out.\n\n83\n00:04:37,180 --> 00:04:39,650\nLambda expressions, we'll\nworry about them later.\n\n84\n00:04:39,650 --> 00:04:44,630\n\n\n85\n00:04:44,630 --> 00:04:45,880\nThings like definitions.\n\n86\n00:04:45,880 --> 00:04:51,900\n\n\n87\n00:04:51,900 --> 00:04:53,150\nThings like conditionals.\n\n88\n00:04:53,150 --> 00:04:58,410\n\n\n89\n00:04:58,410 --> 00:05:00,155\nAnd finally, things\nlike combinations.\n\n90\n00:05:00,155 --> 00:05:07,040\n\n\n91\n00:05:07,040 --> 00:05:10,470\nThese kinds of expressions\nare--\n\n92\n00:05:10,470 --> 00:05:12,880\nI'll worry about later--\n\n93\n00:05:12,880 --> 00:05:16,030\nthese are special forms.\nThere are particular\n\n94\n00:05:16,030 --> 00:05:17,670\nrules for each of these.\n\n95\n00:05:17,670 --> 00:05:19,950\nI'm going to tell you, however,\nthe rules for doing a\n\n96\n00:05:19,950 --> 00:05:21,120\ngeneral case.\n\n97\n00:05:21,120 --> 00:05:23,510\nHow does one evaluate\na combination?\n\n98\n00:05:23,510 --> 00:05:25,820\nBecause, in fact, over here,\nall I really have are\n\n99\n00:05:25,820 --> 00:05:29,180\ncombinations and some\nsymbols and numbers.\n\n100\n00:05:29,180 --> 00:05:31,290\nAnd the simple things like\na number, well, it\n\n101\n00:05:31,290 --> 00:05:33,370\nwill evaluate to itself.\n\n102\n00:05:33,370 --> 00:05:35,180\nIn the model I will\nhave for you, the\n\n103\n00:05:35,180 --> 00:05:37,170\nsymbols will disappear.\n\n104\n00:05:37,170 --> 00:05:40,220\nThey won't be there at the time\nwhen you need them, when\n\n105\n00:05:40,220 --> 00:05:41,680\nyou need to get at them.\n\n106\n00:05:41,680 --> 00:05:44,000\nSo the only thing I really have\nto explain to you is, how\n\n107\n00:05:44,000 --> 00:05:45,250\ndo we evaluate combinations?\n\n108\n00:05:45,250 --> 00:05:48,350\n\n\n109\n00:05:48,350 --> 00:05:50,340\nOK, let's see.\n\n110\n00:05:50,340 --> 00:05:54,430\nSo first I want to get\nthe first slide.\n\n111\n00:05:54,430 --> 00:05:58,450\nHere is the rule for evaluating\nan application.\n\n112\n00:05:58,450 --> 00:06:01,430\n\n\n113\n00:06:01,430 --> 00:06:07,030\nWhat we have is a rule that\nsays, to evaluate a\n\n114\n00:06:07,030 --> 00:06:08,530\ncombination, there are\ntwo parts, three\n\n115\n00:06:08,530 --> 00:06:09,740\nparts to the rule.\n\n116\n00:06:09,740 --> 00:06:12,390\nThe combination has\nseveral parts.\n\n117\n00:06:12,390 --> 00:06:16,630\nIt has operators and\nit has operands.\n\n118\n00:06:16,630 --> 00:06:20,180\nThe operator returns\ninto a procedure.\n\n119\n00:06:20,180 --> 00:06:22,480\nIf we evaluate the operator,\nwe will get a procedure.\n\n120\n00:06:22,480 --> 00:06:25,330\nAnd you saw, for example, how\nI'll type at the machine and\n\n121\n00:06:25,330 --> 00:06:28,880\nout came compound procedure\nsomething or other.\n\n122\n00:06:28,880 --> 00:06:31,940\nAnd the operands produce\narguments.\n\n123\n00:06:31,940 --> 00:06:35,690\nOnce we've gotten the operator\nevaluated to get a procedure,\n\n124\n00:06:35,690 --> 00:06:38,050\nand the argument is evaluated\nto get argument--\n\n125\n00:06:38,050 --> 00:06:39,550\nthe operand's value\nto get arguments--\n\n126\n00:06:39,550 --> 00:06:43,320\nwe apply the procedure to these\narguments by copying the\n\n127\n00:06:43,320 --> 00:06:46,000\nbody of the procedure, which\nis the expression that the\n\n128\n00:06:46,000 --> 00:06:47,800\nprocedure is defined\nin terms of.\n\n129\n00:06:47,800 --> 00:06:49,500\nWhat is it supposed to do?\n\n130\n00:06:49,500 --> 00:06:53,060\nSubstituting the argument\nsupplied for the formal\n\n131\n00:06:53,060 --> 00:06:56,120\nparameters of the procedure,\nthe formal parameters being\n\n132\n00:06:56,120 --> 00:06:59,100\nthe names defined by the\ndeclaration of the procedure.\n\n133\n00:06:59,100 --> 00:07:02,700\nThen we evaluate the resulting\nnew body, the body resulting\n\n134\n00:07:02,700 --> 00:07:07,350\nfrom copying the old body with\nthe substitutions made.\n\n135\n00:07:07,350 --> 00:07:10,900\nIt's a very simple rule, and\nwe're going to do it very\n\n136\n00:07:10,900 --> 00:07:12,300\nformally for a little while.\n\n137\n00:07:12,300 --> 00:07:15,620\nBecause for the next few\nlectures, what I want you to\n\n138\n00:07:15,620 --> 00:07:18,330\ndo is to say, if I don't\nunderstand something, if I\n\n139\n00:07:18,330 --> 00:07:21,260\ndon't understand something, be\nvery mechanical and do this.\n\n140\n00:07:21,260 --> 00:07:23,890\n\n\n141\n00:07:23,890 --> 00:07:26,360\nSo let's see.\n\n142\n00:07:26,360 --> 00:07:28,590\nLet's consider a particular\nevaluation, the one we were\n\n143\n00:07:28,590 --> 00:07:29,550\ntalking about before.\n\n144\n00:07:29,550 --> 00:07:33,330\nThe sum of the squares\nof 3 and 4.\n\n145\n00:07:33,330 --> 00:07:35,900\n\n\n146\n00:07:35,900 --> 00:07:37,010\nWhat does that mean?\n\n147\n00:07:37,010 --> 00:07:38,600\nIt says, take--\n\n148\n00:07:38,600 --> 00:07:41,470\nwell, I could find out what's\non the square-- it's some\n\n149\n00:07:41,470 --> 00:07:43,500\nprocedure, and I'm not going\nto worry about the\n\n150\n00:07:43,500 --> 00:07:44,870\nrepresentation, and I'm not\ngoing to write it on the\n\n151\n00:07:44,870 --> 00:07:46,800\nblackboard for you.\n\n152\n00:07:46,800 --> 00:07:50,650\nAnd I have that 3 represents\nsome number, but if I have to\n\n153\n00:07:50,650 --> 00:07:52,690\nrepeat that number, I can't\ntell you the number.\n\n154\n00:07:52,690 --> 00:07:54,580\nThe number itself is some\nabstract thing.\n\n155\n00:07:54,580 --> 00:07:56,670\nThere's a numeral which\nrepresents it, which I'll call\n\n156\n00:07:56,670 --> 00:07:59,680\n3, and I'll use that\nin my substitution.\n\n157\n00:07:59,680 --> 00:08:01,880\nAnd 4 is also a number.\n\n158\n00:08:01,880 --> 00:08:07,420\nI'm going to substitute 3 for\nx and 4 for y in the body of\n\n159\n00:08:07,420 --> 00:08:09,540\nthis procedure that\nyou see over here.\n\n160\n00:08:09,540 --> 00:08:11,560\nHere's the body of\nthe procedure.\n\n161\n00:08:11,560 --> 00:08:13,300\nIt corresponds to this\n\n162\n00:08:13,300 --> 00:08:14,860\ncombination, which is an addition.\n\n163\n00:08:14,860 --> 00:08:17,500\n\n\n164\n00:08:17,500 --> 00:08:21,210\nSo what that reduces to, as a\nreduction step, we call it, is\n\n165\n00:08:21,210 --> 00:08:30,450\nthe sum of the square of\n3 and the square of 4.\n\n166\n00:08:30,450 --> 00:08:34,200\nNow, what's the next step\nI have to do here?\n\n167\n00:08:34,200 --> 00:08:36,100\nI say, well, I have\nto evaluate this.\n\n168\n00:08:36,100 --> 00:08:40,299\nAccording to my rule, which you\njust saw on that overhead\n\n169\n00:08:40,299 --> 00:08:44,430\nor slide, what we had\nwas that we have to\n\n170\n00:08:44,430 --> 00:08:46,260\nevaluate the operands--\n\n171\n00:08:46,260 --> 00:08:48,220\nand here are the operands,\nhere's one and\n\n172\n00:08:48,220 --> 00:08:49,120\nhere's the next operand--\n\n173\n00:08:49,120 --> 00:08:51,060\nand how we have to evaluate\nprocedure.\n\n174\n00:08:51,060 --> 00:08:52,830\nThe order doesn't matter.\n\n175\n00:08:52,830 --> 00:08:56,810\nAnd then we're going to apply\nthe procedure, which is plus,\n\n176\n00:08:56,810 --> 00:08:59,830\nand magically somehow that's\ngoing to produce the answer.\n\n177\n00:08:59,830 --> 00:09:02,500\nI'm not to open up plus\nand look inside of it.\n\n178\n00:09:02,500 --> 00:09:05,380\nHowever, in order to evaluate\nthe operand, let's pick some\n\n179\n00:09:05,380 --> 00:09:06,780\narbitrary order and do them.\n\n180\n00:09:06,780 --> 00:09:08,540\nI'm going to go from\nright to left.\n\n181\n00:09:08,540 --> 00:09:10,530\nWell, in order to evaluate\nthis operand, I have to\n\n182\n00:09:10,530 --> 00:09:14,350\nevaluate the parts of\nit by the same rule.\n\n183\n00:09:14,350 --> 00:09:16,260\nAnd the parts are I have to find\nout what square is-- it's\n\n184\n00:09:16,260 --> 00:09:19,580\nsome procedure, which has\na formal parameter x.\n\n185\n00:09:19,580 --> 00:09:25,510\nAnd also, I have an operand\nwhich is 4, which I have to\n\n186\n00:09:25,510 --> 00:09:28,710\nsubstitute for x in the\nbody of square.\n\n187\n00:09:28,710 --> 00:09:32,170\nSo the next step is basically to\nsay that this is the sum of\n\n188\n00:09:32,170 --> 00:09:40,990\nthe square of 3 and the\nproduct of 4 and 4.\n\n189\n00:09:40,990 --> 00:09:44,460\nOf course, I could open up\nasterisk if I liked--\n\n190\n00:09:44,460 --> 00:09:46,920\nthe multiplication operation--\n\n191\n00:09:46,920 --> 00:09:47,900\nbut I'm not going to do that.\n\n192\n00:09:47,900 --> 00:09:50,610\nI'm going to consider\nthat primitive.\n\n193\n00:09:50,610 --> 00:09:53,320\nAnd, of course, at any level of\ndetail, if you look inside\n\n194\n00:09:53,320 --> 00:09:55,540\nthis machine, you're going to\nfind that there's multiple\n\n195\n00:09:55,540 --> 00:09:58,250\nlevels below that that\nyou don't know about.\n\n196\n00:09:58,250 --> 00:09:59,620\nBut one of the things we\nhave to learn how to\n\n197\n00:09:59,620 --> 00:10:02,520\ndo is ignore details.\n\n198\n00:10:02,520 --> 00:10:04,960\nThe key to understanding\ncomplicated things is to know\n\n199\n00:10:04,960 --> 00:10:07,710\nwhat not to look at and\nwhat not compute\n\n200\n00:10:07,710 --> 00:10:09,500\nand what not to think.\n\n201\n00:10:09,500 --> 00:10:12,380\nSo we're going to stop this\none here and say, oh, yes,\n\n202\n00:10:12,380 --> 00:10:14,510\nthis is the product\nof two things.\n\n203\n00:10:14,510 --> 00:10:15,930\nWe're going to do it now.\n\n204\n00:10:15,930 --> 00:10:19,220\nSo this is nothing more\nthan the sum of the\n\n205\n00:10:19,220 --> 00:10:23,340\nsquare of 3 and 16.\n\n206\n00:10:23,340 --> 00:10:27,910\nAnd now I have another thing I\nhave to evaluate, but that\n\n207\n00:10:27,910 --> 00:10:29,430\nsquare of 3, well, it's\nthe same thing.\n\n208\n00:10:29,430 --> 00:10:36,910\nThat's the sum of the product\nof 3 and 3 and 16, which is\n\n209\n00:10:36,910 --> 00:10:44,830\nthe sum of 9 and 16,\nwhich is 25.\n\n210\n00:10:44,830 --> 00:10:49,366\nSo now you see the basic method\nof doing substitutions.\n\n211\n00:10:49,366 --> 00:10:54,980\nAnd I warn you that this is not\na perfect description of\n\n212\n00:10:54,980 --> 00:10:57,200\nwhat the computer does.\n\n213\n00:10:57,200 --> 00:11:00,800\nBut it's a good enough\ndescription for the problems\n\n214\n00:11:00,800 --> 00:11:03,090\nthat we're going to have in the\nnext few lectures that you\n\n215\n00:11:03,090 --> 00:11:05,220\nshould think about\nthis religiously.\n\n216\n00:11:05,220 --> 00:11:07,880\nAnd this is how the machine\nworks for now.\n\n217\n00:11:07,880 --> 00:11:09,130\nLater we'll get more detailed.\n\n218\n00:11:09,130 --> 00:11:12,090\n\n\n219\n00:11:12,090 --> 00:11:14,500\nNow, of course, I made a\nspecific choice of the order\n\n220\n00:11:14,500 --> 00:11:15,780\nof evaluation here.\n\n221\n00:11:15,780 --> 00:11:17,180\nThere are other possibilities.\n\n222\n00:11:17,180 --> 00:11:21,360\nIf we go back to the telestrator\nhere and look at\n\n223\n00:11:21,360 --> 00:11:25,130\nthe substitution rule, we see\nthat I evaluated the operator\n\n224\n00:11:25,130 --> 00:11:27,910\nto get the procedures, and I\nevaluated the operands to get\n\n225\n00:11:27,910 --> 00:11:31,110\nthe arguments first, before\nI do the application.\n\n226\n00:11:31,110 --> 00:11:33,320\nIt's entirely possible, and\nthere are alternate rules\n\n227\n00:11:33,320 --> 00:11:36,570\ncalled normal order evaluation\nwhereby you can do the\n\n228\n00:11:36,570 --> 00:11:41,150\nsubstitution of the expressions\nwhich are the\n\n229\n00:11:41,150 --> 00:11:44,580\noperands for the formal\nparameters inside the body\n\n230\n00:11:44,580 --> 00:11:48,880\nfirst. And you'll get also\nthe same answer.\n\n231\n00:11:48,880 --> 00:11:50,970\nBut right now, for concreteness,\nand because this\n\n232\n00:11:50,970 --> 00:11:53,780\nis the way our machine really\ndoes it, I'm going to give you\n\n233\n00:11:53,780 --> 00:11:56,510\nthis rule, which has\na particular order.\n\n234\n00:11:56,510 --> 00:11:58,440\nBut that order is to some\nextent arbitrary, too.\n\n235\n00:11:58,440 --> 00:12:01,110\n\n\n236\n00:12:01,110 --> 00:12:03,110\nIn the long run, there are some\nreasons why you might\n\n237\n00:12:03,110 --> 00:12:04,920\npick one order or another,\nand we'll get to that\n\n238\n00:12:04,920 --> 00:12:06,170\nlater in the subject.\n\n239\n00:12:06,170 --> 00:12:12,320\n\n\n240\n00:12:12,320 --> 00:12:15,500\nOK, well now the only other\nthing I have to tell you about\n\n241\n00:12:15,500 --> 00:12:17,530\njust to understand what's going\non is let's look at the\n\n242\n00:12:17,530 --> 00:12:19,840\nrule for conditionals.\n\n243\n00:12:19,840 --> 00:12:27,200\nConditionals are very simple,\nand I'd like to examine this.\n\n244\n00:12:27,200 --> 00:12:32,490\nA conditional is something\nthat is if-- there's also\n\n245\n00:12:32,490 --> 00:12:33,720\ncond, of course--\n\n246\n00:12:33,720 --> 00:12:35,980\nbut I'm going to give names to\nthe parts of the expression.\n\n247\n00:12:35,980 --> 00:12:39,340\nThere's a predicate, which\nis a thing that is\n\n248\n00:12:39,340 --> 00:12:40,900\neither true or false.\n\n249\n00:12:40,900 --> 00:12:46,920\nAnd there's a consequent, which\nis the thing you do if\n\n250\n00:12:46,920 --> 00:12:48,370\nthe predicate is true.\n\n251\n00:12:48,370 --> 00:12:53,970\nAnd there's an alternative,\nwhich is the thing you do if\n\n252\n00:12:53,970 --> 00:12:55,470\nthe predicate is false.\n\n253\n00:12:55,470 --> 00:13:00,202\nIt's important, by the way, to\nget names for, to get names\n\n254\n00:13:00,202 --> 00:13:03,810\nfor, the parts of things, or\nthe parts of expressions.\n\n255\n00:13:03,810 --> 00:13:06,410\nOne of the things that every\nsorcerer will tell you is if\n\n256\n00:13:06,410 --> 00:13:10,350\nyou have the name of a spirit,\nyou have power over it.\n\n257\n00:13:10,350 --> 00:13:12,320\nSo you have to learn these names\nso that we can discuss\n\n258\n00:13:12,320 --> 00:13:13,790\nthese things.\n\n259\n00:13:13,790 --> 00:13:16,570\nSo here we have a predicate,\na consequent, and an\n\n260\n00:13:16,570 --> 00:13:17,860\nalternative.\n\n261\n00:13:17,860 --> 00:13:21,830\nAnd, using such words, we see\nthat an if expression, the\n\n262\n00:13:21,830 --> 00:13:25,160\nproblems you evaluate to the\npredicate expression, if that\n\n263\n00:13:25,160 --> 00:13:29,630\nyields true, then you then go on\nto evaluate the consequent.\n\n264\n00:13:29,630 --> 00:13:31,975\nOtherwise, you evaluate the\nalternative expression.\n\n265\n00:13:31,975 --> 00:13:34,880\n\n\n266\n00:13:34,880 --> 00:13:39,290\nSo I'd like to illustrate that\nnow in the context of a\n\n267\n00:13:39,290 --> 00:13:43,600\nparticular little program.\n\n268\n00:13:43,600 --> 00:13:44,620\nGoing to write down a\nprogram which we're\n\n269\n00:13:44,620 --> 00:13:45,870\ngoing to see many times.\n\n270\n00:13:45,870 --> 00:13:51,770\n\n\n271\n00:13:51,770 --> 00:13:58,380\nThis is the sum of x and y done\nby what's called Peano\n\n272\n00:13:58,380 --> 00:14:00,140\narithmetic, which is all we're\ndoing is incrementing and\n\n273\n00:14:00,140 --> 00:14:01,510\ndecrementing.\n\n274\n00:14:01,510 --> 00:14:03,070\nAnd we're going to see this\nfor a little bit.\n\n275\n00:14:03,070 --> 00:14:06,240\nIt's a very important program.\n\n276\n00:14:06,240 --> 00:14:12,190\nIf x equals o, then\nthe result is y.\n\n277\n00:14:12,190 --> 00:14:17,980\nOtherwise, this is the sum of\nthe decrement of x and the\n\n278\n00:14:17,980 --> 00:14:20,590\nincrement of y.\n\n279\n00:14:20,590 --> 00:14:23,720\n\n\n280\n00:14:23,720 --> 00:14:28,000\nWe're going to look at this\na lot more in the future.\n\n281\n00:14:28,000 --> 00:14:29,360\nLet's look at the overhead.\n\n282\n00:14:29,360 --> 00:14:31,830\nSo here we have this procedure,\nand we're going to\n\n283\n00:14:31,830 --> 00:14:33,930\nlook at how we do the\nsubstitutions, the sequence of\n\n284\n00:14:33,930 --> 00:14:36,110\nsubstitutions.\n\n285\n00:14:36,110 --> 00:14:38,370\nWell, I'm going to try and\nadd together 3 and 4.\n\n286\n00:14:38,370 --> 00:14:40,950\nWell, using the first rule\nthat I showed you, we\n\n287\n00:14:40,950 --> 00:14:44,840\nsubstitute 3 for x and\n4 four y in the\n\n288\n00:14:44,840 --> 00:14:45,980\nbody of this procedure.\n\n289\n00:14:45,980 --> 00:14:49,000\nThe body of the procedure is the\nthing that begins with if\n\n290\n00:14:49,000 --> 00:14:51,410\nand finishes over here.\n\n291\n00:14:51,410 --> 00:14:54,025\nSo what we get is, of course,\nif 3 is 0, then\n\n292\n00:14:54,025 --> 00:14:56,010\nthe result is 4.\n\n293\n00:14:56,010 --> 00:14:58,960\nOtherwise, it's the sum of the\ndecrement of 3 and the\n\n294\n00:14:58,960 --> 00:15:01,360\nincrement of 4.\n\n295\n00:15:01,360 --> 00:15:03,320\nBut I'm not going to worry\nabout these yet\n\n296\n00:15:03,320 --> 00:15:05,610\nbecause 3 is not 0.\n\n297\n00:15:05,610 --> 00:15:08,310\nSo the answer is not 4.\n\n298\n00:15:08,310 --> 00:15:12,250\nTherefore, this if reduces\nto an evaluation of the\n\n299\n00:15:12,250 --> 00:15:14,550\nexpression, the sum to the\ndecrement of 3 and the\n\n300\n00:15:14,550 --> 00:15:16,860\nincrement of 4.\n\n301\n00:15:16,860 --> 00:15:19,540\nContinuing with my evaluation,\nthe increment I presume to be\n\n302\n00:15:19,540 --> 00:15:23,010\nprimitive, and so\nI get a 5 there.\n\n303\n00:15:23,010 --> 00:15:26,090\nOK, and then the decrement is\nalso primitive, and I get a 2.\n\n304\n00:15:26,090 --> 00:15:28,560\nAnd so I change the problem\ninto a simpler problem.\n\n305\n00:15:28,560 --> 00:15:33,480\nInstead of adding 3 to\n4, I'm adding 2 to 5.\n\n306\n00:15:33,480 --> 00:15:35,380\nThe reason why this is a simpler\nproblem is because I'm\n\n307\n00:15:35,380 --> 00:15:40,540\ncounting down on x, and\neventually, then, x will be 0.\n\n308\n00:15:40,540 --> 00:15:43,480\n\n\n309\n00:15:43,480 --> 00:15:46,090\nSo, so much for the\nsubstitution rule.\n\n310\n00:15:46,090 --> 00:15:49,240\nIn general, I'm not going to\nwrite down intermediate steps\n\n311\n00:15:49,240 --> 00:15:52,160\nwhen using substitutions having\nto do with ifs, because\n\n312\n00:15:52,160 --> 00:15:55,520\nthey just expand things\nto become complicated.\n\n313\n00:15:55,520 --> 00:15:58,160\nWhat we will be doing is saying,\noh, yes, the sum of 3\n\n314\n00:15:58,160 --> 00:16:02,463\nand 4 results in the sum of 2\nand 5 and reduces to the sum\n\n315\n00:16:02,463 --> 00:16:07,100\nof 2 and 5, which, in fact,\nreduces to the sum of 1 and 6,\n\n316\n00:16:07,100 --> 00:16:11,410\nwhich reduces to the sum of\n0 and 7 over here, which\n\n317\n00:16:11,410 --> 00:16:14,130\nreduces to a 7.\n\n318\n00:16:14,130 --> 00:16:16,550\nThat's what we're going\nto be seeing.\n\n319\n00:16:16,550 --> 00:16:20,600\nAre there any questions for\nthe first segment yet?\n\n320\n00:16:20,600 --> 00:16:21,942\nYes?\n\n321\n00:16:21,942 --> 00:16:24,858\nSTUDENT: You're using 1\nplus and minus 1 plus.\n\n322\n00:16:24,858 --> 00:16:25,830\nAre those primitive\noperations?\n\n323\n00:16:25,830 --> 00:16:26,810\nPROFESSOR: Yes.\n\n324\n00:16:26,810 --> 00:16:29,370\nOne of the things you're going\nto be seeing in this subject\n\n325\n00:16:29,370 --> 00:16:33,360\nis I'm going to, without\nthinking about it, introduce\n\n326\n00:16:33,360 --> 00:16:36,180\nmore and more primitive\noperations.\n\n327\n00:16:36,180 --> 00:16:38,400\nThere's presumably some large\nlibrary of primitive\n\n328\n00:16:38,400 --> 00:16:39,830\noperations somewhere.\n\n329\n00:16:39,830 --> 00:16:41,620\nBut it doesn't matter that\nthey're primitive--\n\n330\n00:16:41,620 --> 00:16:43,860\nthere may be some manual\nthat lists them all.\n\n331\n00:16:43,860 --> 00:16:45,900\nIf I tell you what they do,\nyou say, oh, yes, I\n\n332\n00:16:45,900 --> 00:16:46,960\nknow what they do.\n\n333\n00:16:46,960 --> 00:16:49,070\nSo one of them is the\ndecrementor--\n\n334\n00:16:49,070 --> 00:16:50,960\nminus 1 plus-- and the\nother operation is\n\n335\n00:16:50,960 --> 00:16:53,310\nincrement, which is 1 plus.\n\n336\n00:16:53,310 --> 00:16:53,840\nThank you.\n\n337\n00:16:53,840 --> 00:16:55,662\nThat's the end of the\nfirst segment.\n\n338\n00:16:55,662 --> 00:17:19,230\n[MUSIC PLAYING BY J.S. BACH]\n\n339\n00:17:19,230 --> 00:17:22,079\nPROFESSOR: Now that we have a\nreasonably mechanical way of\n\n340\n00:17:22,079 --> 00:17:28,349\nunderstanding how a program\nmade out of procedures and\n\n341\n00:17:28,349 --> 00:17:32,390\nexpressions evolves a process,\nI'd like to develop some\n\n342\n00:17:32,390 --> 00:17:36,920\nintuition about how particular\nprograms evolve particular\n\n343\n00:17:36,920 --> 00:17:39,930\nprocesses, what the shapes of\nprograms have to be in order\n\n344\n00:17:39,930 --> 00:17:42,940\nto get particular shaped\nprocesses.\n\n345\n00:17:42,940 --> 00:17:47,110\nThis is a question about,\nreally, pre-visualizing.\n\n346\n00:17:47,110 --> 00:17:49,230\nThat's a word from\nphotography.\n\n347\n00:17:49,230 --> 00:17:53,140\nI used to be interested in\nphotography a lot, and one of\n\n348\n00:17:53,140 --> 00:17:55,140\nthe things you discover when\nyou start trying to learn\n\n349\n00:17:55,140 --> 00:17:57,330\nabout photography is that you\nsay, gee, I'd like to be a\n\n350\n00:17:57,330 --> 00:17:58,910\ncreative photographer.\n\n351\n00:17:58,910 --> 00:18:01,820\nNow, I know the rules, I push\nbuttons, and I adjust the\n\n352\n00:18:01,820 --> 00:18:03,430\naperture and things like that.\n\n353\n00:18:03,430 --> 00:18:06,710\nBut the key to being a creative\nperson, partly, is to\n\n354\n00:18:06,710 --> 00:18:09,595\nbe able to do analysis\nat some level.\n\n355\n00:18:09,595 --> 00:18:13,880\nTo say, how do I know what it\nis that I'm going to get on\n\n356\n00:18:13,880 --> 00:18:17,170\nthe film before I\npush the button.\n\n357\n00:18:17,170 --> 00:18:23,060\nCan I imagine in my mind the\nresulting image very precisely\n\n358\n00:18:23,060 --> 00:18:28,300\nand clearly as a consequence of\nthe particular framing, of\n\n359\n00:18:28,300 --> 00:18:32,620\nthe aperture I choose, of the\nfocus, and things like that?\n\n360\n00:18:32,620 --> 00:18:35,755\nThat's part of the art of doing\nthis sort of thing.\n\n361\n00:18:35,755 --> 00:18:39,230\nAnd learning a lot\nof that involves\n\n362\n00:18:39,230 --> 00:18:40,970\nthings like test strips.\n\n363\n00:18:40,970 --> 00:18:44,950\nYou take very simple images that\nhave varying degrees of\n\n364\n00:18:44,950 --> 00:18:47,870\ndensity in them, for example,\nand examine what those look\n\n365\n00:18:47,870 --> 00:18:51,630\nlike on a piece of paper when\nyou print them out.\n\n366\n00:18:51,630 --> 00:18:54,270\nYou find out what is the range\nof contrasts that you can\n\n367\n00:18:54,270 --> 00:18:55,850\nactually see.\n\n368\n00:18:55,850 --> 00:18:58,650\nAnd what, in a real scene,\nwould correspond to the\n\n369\n00:18:58,650 --> 00:19:02,790\nvarious levels and zones\nthat you have of\n\n370\n00:19:02,790 --> 00:19:05,440\ndensity in an image.\n\n371\n00:19:05,440 --> 00:19:08,410\nWell, today I want to look at\nsome very particular test\n\n372\n00:19:08,410 --> 00:19:12,000\nstrips, and I suppose one of\nthem I see here is up on the\n\n373\n00:19:12,000 --> 00:19:14,880\ntelestrator, so we should\nswitch to that.\n\n374\n00:19:14,880 --> 00:19:19,350\nThere's a very important, very\nimportant pair of programs for\n\n375\n00:19:19,350 --> 00:19:24,500\nunderstanding what's going on in\nthe evolution of a process\n\n376\n00:19:24,500 --> 00:19:27,320\nby the execution of a program.\n\n377\n00:19:27,320 --> 00:19:29,090\nWhat we have here are\ntwo procedures\n\n378\n00:19:29,090 --> 00:19:30,340\nthat are almost identical.\n\n379\n00:19:30,340 --> 00:19:32,820\n\n\n380\n00:19:32,820 --> 00:19:35,440\nAlmost no difference between\nthem at all.\n\n381\n00:19:35,440 --> 00:19:38,860\nIt's a few characters that\ndistinguish them.\n\n382\n00:19:38,860 --> 00:19:42,140\nThese are two ways of adding\nnumbers together.\n\n383\n00:19:42,140 --> 00:19:48,660\nThe first one, which you see\nhere, the first one is the sum\n\n384\n00:19:48,660 --> 00:19:50,880\nof two numbers-- just\nwhat we did before--\n\n385\n00:19:50,880 --> 00:19:52,580\nis, if the first one is\n0, it's the answer\n\n386\n00:19:52,580 --> 00:19:53,600\nof the second one.\n\n387\n00:19:53,600 --> 00:19:56,480\nOtherwise, it's the sum of the\ndecrement of the first and the\n\n388\n00:19:56,480 --> 00:19:57,960\nincrement of the second.\n\n389\n00:19:57,960 --> 00:20:04,480\nAnd you may think of that\nas having two piles.\n\n390\n00:20:04,480 --> 00:20:06,280\nAnd the way I'm adding these\nnumbers together to make a\n\n391\n00:20:06,280 --> 00:20:10,560\nthird pile is by moving marbles\nfrom one to the other.\n\n392\n00:20:10,560 --> 00:20:11,640\nNothing more than that.\n\n393\n00:20:11,640 --> 00:20:13,520\nAnd eventually, when I run\nout of one, then the\n\n394\n00:20:13,520 --> 00:20:15,650\nother is the sum.\n\n395\n00:20:15,650 --> 00:20:20,690\nHowever, the second procedure\nhere doesn't do it that way.\n\n396\n00:20:20,690 --> 00:20:22,960\nIt says if the first number\nis 0, then the\n\n397\n00:20:22,960 --> 00:20:24,330\nanswer is the second.\n\n398\n00:20:24,330 --> 00:20:28,550\nOtherwise, it's the increment of\nthe sum of the decrement of\n\n399\n00:20:28,550 --> 00:20:31,360\nthe first number\nand the second.\n\n400\n00:20:31,360 --> 00:20:35,930\nSo what this says is add\ntogether the decrement of the\n\n401\n00:20:35,930 --> 00:20:38,870\nfirst number and the second-- a\nsimpler problem, no doubt--\n\n402\n00:20:38,870 --> 00:20:43,190\nand then change that result\nto increment it.\n\n403\n00:20:43,190 --> 00:20:45,900\nAnd so this means that if you\nthink about this in terms of\n\n404\n00:20:45,900 --> 00:20:49,320\npiles, it means I'm holding\nin my hand the\n\n405\n00:20:49,320 --> 00:20:52,120\nthings to be added later.\n\n406\n00:20:52,120 --> 00:20:53,990\nAnd then I'm going\nto add them in.\n\n407\n00:20:53,990 --> 00:20:57,710\nAs I slowly decrease one pile\nto 0, I've got what's left\n\n408\n00:20:57,710 --> 00:21:00,330\nhere, and then I'm going\nto add them back.\n\n409\n00:21:00,330 --> 00:21:02,360\nTwo different ways of adding.\n\n410\n00:21:02,360 --> 00:21:05,270\nThe nice thing about these two\nprograms is that they're\n\n411\n00:21:05,270 --> 00:21:06,580\nalmost identical.\n\n412\n00:21:06,580 --> 00:21:09,530\nThe only thing is where\nI put the increment.\n\n413\n00:21:09,530 --> 00:21:11,860\nA couple of characters\nmoved around.\n\n414\n00:21:11,860 --> 00:21:15,370\nNow I want to understand the\nkind of behavior we're going\n\n415\n00:21:15,370 --> 00:21:18,200\nto get from each of these\nprograms. Just to get them\n\n416\n00:21:18,200 --> 00:21:19,670\nfirmly in your mind--\n\n417\n00:21:19,670 --> 00:21:22,120\nI usually don't want to\nbe this careful--\n\n418\n00:21:22,120 --> 00:21:24,490\nbut just to get them firmly in\nyour mind, I'm going to write\n\n419\n00:21:24,490 --> 00:21:26,155\nthe programs again on the\nblackboard, and then I'm going\n\n420\n00:21:26,155 --> 00:21:28,150\nto evolve a process.\n\n421\n00:21:28,150 --> 00:21:29,350\nAnd you're going to\nsee what happens.\n\n422\n00:21:29,350 --> 00:21:31,910\nWe're going to look at the\nshape of the process as a\n\n423\n00:21:31,910 --> 00:21:34,390\nconsequence of the program.\n\n424\n00:21:34,390 --> 00:21:44,170\nSo the program we started with\nis this: the sum of x and y\n\n425\n00:21:44,170 --> 00:21:51,160\nsays if x is 0, then\nthe result is y.\n\n426\n00:21:51,160 --> 00:21:56,090\nOtherwise, it's the sum of the\ndecrement of x and the\n\n427\n00:21:56,090 --> 00:21:58,630\nincrement of y.\n\n428\n00:21:58,630 --> 00:22:01,740\n\n\n429\n00:22:01,740 --> 00:22:07,080\nNow, supposing we wish to do\nthis addition of 3 and 4, the\n\n430\n00:22:07,080 --> 00:22:10,900\nsum of 3 and 4, well,\nwhat is that?\n\n431\n00:22:10,900 --> 00:22:14,580\nIt says that I have to\nsubstitute the arguments for\n\n432\n00:22:14,580 --> 00:22:17,750\nthe formal parameters\nin the body.\n\n433\n00:22:17,750 --> 00:22:19,940\nI'm doing that in my mind.\n\n434\n00:22:19,940 --> 00:22:22,830\nAnd I say, oh, yes, 3 is\nsubstituted for x, but 3 is\n\n435\n00:22:22,830 --> 00:22:28,650\nnot 0, so I'm going to go\ndirectly to this part and\n\n436\n00:22:28,650 --> 00:22:30,710\nwrite down the simplified\nconsequent here.\n\n437\n00:22:30,710 --> 00:22:33,420\nBecause I'm really interested\nin the behavior of addition.\n\n438\n00:22:33,420 --> 00:22:34,400\nWell, what is that?\n\n439\n00:22:34,400 --> 00:22:38,460\nThat therefore turns into\nthe sum of 2 and 5.\n\n440\n00:22:38,460 --> 00:22:41,750\nIn other words, I've reduced\nthis problem to this problem.\n\n441\n00:22:41,750 --> 00:22:48,450\nThen I reduce this problem to\nthe sum of 1 and 6, and then,\n\n442\n00:22:48,450 --> 00:22:53,390\ngoing around again once, I\nget the sum of 0 and 7.\n\n443\n00:22:53,390 --> 00:22:57,110\nAnd that's one where x equals 0\nso the result is y, and so I\n\n444\n00:22:57,110 --> 00:23:00,260\nwrite down here a 7.\n\n445\n00:23:00,260 --> 00:23:03,790\nSo this is the behavior of the\nprocess evolved by trying to\n\n446\n00:23:03,790 --> 00:23:07,410\nadd together 3 and 4\nwith this program.\n\n447\n00:23:07,410 --> 00:23:20,060\nFor the other program, which\nis over here, I will define\n\n448\n00:23:20,060 --> 00:23:23,376\nthe sum of x and y.\n\n449\n00:23:23,376 --> 00:23:24,626\nAnd what is it?\n\n450\n00:23:24,626 --> 00:23:27,260\n\n\n451\n00:23:27,260 --> 00:23:32,100\nIf x is 0, then the result\nis y-- almost the same--\n\n452\n00:23:32,100 --> 00:23:36,200\notherwise the increment\nof the sum of the\n\n453\n00:23:36,200 --> 00:23:40,550\ndecrement of x and y.\n\n454\n00:23:40,550 --> 00:23:47,770\n\n\n455\n00:23:47,770 --> 00:23:49,020\nNo.\n\n456\n00:23:49,020 --> 00:23:53,330\n\n\n457\n00:23:53,330 --> 00:23:56,490\nI don't have my balancer\nin front of me.\n\n458\n00:23:56,490 --> 00:23:59,060\nOK, well, let's do it now.\n\n459\n00:23:59,060 --> 00:24:01,560\nThe sum of 3 and 4.\n\n460\n00:24:01,560 --> 00:24:03,660\nWell, this is actually a little\nmore interesting.\n\n461\n00:24:03,660 --> 00:24:07,930\nOf course, 3 is not 0 as before,\nso that results in the\n\n462\n00:24:07,930 --> 00:24:14,240\nincrement of the sum of the\ndecrement of x, which is 2 and\n\n463\n00:24:14,240 --> 00:24:23,240\n4, which is the increment\nof the sum of 1 and--\n\n464\n00:24:23,240 --> 00:24:26,000\nwhoops: the increment\nof the increment.\n\n465\n00:24:26,000 --> 00:24:30,040\nWhat I have to do now is compute\nwhat this means.\n\n466\n00:24:30,040 --> 00:24:31,310\nI have to evaluate this.\n\n467\n00:24:31,310 --> 00:24:33,530\nOr what that is, the result\nof substituting 2 and\n\n468\n00:24:33,530 --> 00:24:35,690\n4 for x and y here.\n\n469\n00:24:35,690 --> 00:24:44,810\nBut that is the increment of the\nsum of 1 and 4, which is--\n\n470\n00:24:44,810 --> 00:24:47,820\nwell, now I have\nto expand this.\n\n471\n00:24:47,820 --> 00:24:52,520\nAh, but that's the increment\nof the increment of the\n\n472\n00:24:52,520 --> 00:24:56,520\nincrement of the\nsum of 0 and 4.\n\n473\n00:24:56,520 --> 00:25:00,050\n\n\n474\n00:25:00,050 --> 00:25:03,190\nAh, but now I'm beginning\nto find things I can do.\n\n475\n00:25:03,190 --> 00:25:07,430\nThe increment of the increment\nof the increment of-- well,\n\n476\n00:25:07,430 --> 00:25:08,850\nthe sum of 0 and 4 is 4.\n\n477\n00:25:08,850 --> 00:25:12,430\n\n\n478\n00:25:12,430 --> 00:25:14,235\nThe increment of 4 is 5.\n\n479\n00:25:14,235 --> 00:25:20,880\nSo this is the increment of the\nincrement of 5, which is\n\n480\n00:25:20,880 --> 00:25:26,112\nthe increment of\n6, which is 7.\n\n481\n00:25:26,112 --> 00:25:29,960\nTwo different ways of\ncomputing sums.\n\n482\n00:25:29,960 --> 00:25:31,430\nNow, let's see.\n\n483\n00:25:31,430 --> 00:25:34,250\nThese processes have very\ndifferent shapes.\n\n484\n00:25:34,250 --> 00:25:36,760\nI want you to feel\nthese shapes.\n\n485\n00:25:36,760 --> 00:25:40,740\nIt's the feeling for the\nshapes that matters.\n\n486\n00:25:40,740 --> 00:25:43,000\nWhat's some things we\ncan see about this?\n\n487\n00:25:43,000 --> 00:25:45,650\nWell, somehow this is\nsort of straight.\n\n488\n00:25:45,650 --> 00:25:47,750\nIt goes this way-- straight.\n\n489\n00:25:47,750 --> 00:25:54,130\nThis right edge doesn't vary\nparticularly in size.\n\n490\n00:25:54,130 --> 00:25:57,610\nWhereas this one, I see that\nthis thing gets bigger and\n\n491\n00:25:57,610 --> 00:25:58,860\nthen it gets smaller.\n\n492\n00:25:58,860 --> 00:26:01,240\n\n\n493\n00:26:01,240 --> 00:26:03,110\nSo I don't know what\nthat means yet,\n\n494\n00:26:03,110 --> 00:26:04,080\nbut what are we seeing?\n\n495\n00:26:04,080 --> 00:26:09,170\nWe're seeing here that somehow\nthese increments are expanding\n\n496\n00:26:09,170 --> 00:26:13,070\nout and then contracting back.\n\n497\n00:26:13,070 --> 00:26:16,470\nI'm building up a bunch\nof them to do later.\n\n498\n00:26:16,470 --> 00:26:18,960\nI can't do them now.\n\n499\n00:26:18,960 --> 00:26:21,770\nThere's things to be deferred.\n\n500\n00:26:21,770 --> 00:26:23,000\nWell, let's see.\n\n501\n00:26:23,000 --> 00:26:24,830\nI can imagine an abstract\nmachine.\n\n502\n00:26:24,830 --> 00:26:26,680\nThere's some physical machine,\nperhaps, that could be built\n\n503\n00:26:26,680 --> 00:26:29,260\nto do it, which, in fact,\nexecutes these programs\n\n504\n00:26:29,260 --> 00:26:31,730\nexactly as I tell you,\nsubstituting character strings\n\n505\n00:26:31,730 --> 00:26:34,540\nin like this.\n\n506\n00:26:34,540 --> 00:26:37,910\nSuch a machine, the number of\nsuch steps is an approximation\n\n507\n00:26:37,910 --> 00:26:40,040\nof the amount of\ntime it takes.\n\n508\n00:26:40,040 --> 00:26:41,290\nSo this way is time.\n\n509\n00:26:41,290 --> 00:26:45,510\n\n\n510\n00:26:45,510 --> 00:26:48,890\nAnd the width of the thing is\nhow much I have to remember in\n\n511\n00:26:48,890 --> 00:26:50,150\norder to continue the process.\n\n512\n00:26:50,150 --> 00:26:51,400\nAnd this much is space.\n\n513\n00:26:51,400 --> 00:26:53,920\n\n\n514\n00:26:53,920 --> 00:26:58,800\nAnd what we see here is a\nprocess that takes a time\n\n515\n00:26:58,800 --> 00:27:02,710\nwhich is proportional\nto the argument x.\n\n516\n00:27:02,710 --> 00:27:05,820\nBecause if I made x larger by 1,\nthen I'd had an extra line.\n\n517\n00:27:05,820 --> 00:27:08,810\n\n\n518\n00:27:08,810 --> 00:27:12,080\nSo this is a process which\nis space-- sorry--\n\n519\n00:27:12,080 --> 00:27:14,640\ntime.\n\n520\n00:27:14,640 --> 00:27:20,630\nThe time of this process is\nwhat we say order of x.\n\n521\n00:27:20,630 --> 00:27:24,390\nThat means it is proportional\nto x by some constant of\n\n522\n00:27:24,390 --> 00:27:26,430\nproportionality, and I'm not\nparticularly interested in\n\n523\n00:27:26,430 --> 00:27:28,580\nwhat the constant is.\n\n524\n00:27:28,580 --> 00:27:31,360\nThe other thing we see here is\nthat the amount of space this\n\n525\n00:27:31,360 --> 00:27:35,150\ntakes up is constant, it's\nproportional to 1.\n\n526\n00:27:35,150 --> 00:27:42,070\nSo the space complexity\nof this is order of 1.\n\n527\n00:27:42,070 --> 00:27:44,180\nWe have a name for\nsuch a process.\n\n528\n00:27:44,180 --> 00:27:45,950\nSuch a process is called\nan iteration.\n\n529\n00:27:45,950 --> 00:27:51,000\n\n\n530\n00:27:51,000 --> 00:27:55,390\nAnd what matters here is not\nthat some particular machine I\n\n531\n00:27:55,390 --> 00:27:58,590\ndesigned here and talked to\nyou about and called a\n\n532\n00:27:58,590 --> 00:28:00,240\nsubstitution machine\nor whatever--\n\n533\n00:28:00,240 --> 00:28:01,480\nsubstitution model--\n\n534\n00:28:01,480 --> 00:28:04,550\nmanaged to do this in\nconstant space.\n\n535\n00:28:04,550 --> 00:28:07,140\nWhat really matters is this\ntells us a bound.\n\n536\n00:28:07,140 --> 00:28:09,680\nAny machine could do this\nin constant space.\n\n537\n00:28:09,680 --> 00:28:13,275\nThis algorithm represented by\nthis procedure is executable\n\n538\n00:28:13,275 --> 00:28:15,250\nin constant space.\n\n539\n00:28:15,250 --> 00:28:18,330\nNow, of course, the model is\nignoring some things, standard\n\n540\n00:28:18,330 --> 00:28:19,120\nsorts of things.\n\n541\n00:28:19,120 --> 00:28:22,390\nLike numbers that are bigger\ntake up more space and so on.\n\n542\n00:28:22,390 --> 00:28:23,990\nBut that's a level of\nabstraction at which I'm\n\n543\n00:28:23,990 --> 00:28:24,360\ncutting off.\n\n544\n00:28:24,360 --> 00:28:25,290\nHow do you represent numbers?\n\n545\n00:28:25,290 --> 00:28:28,090\nI'm considering every number\nto be the same size.\n\n546\n00:28:28,090 --> 00:28:30,540\nAnd numbers grow slowly for the\namount of space they take\n\n547\n00:28:30,540 --> 00:28:34,240\nup and their size.\n\n548\n00:28:34,240 --> 00:28:38,000\nNow, this algorithm is different\nin its complexity.\n\n549\n00:28:38,000 --> 00:28:42,850\nAs we can see here, this\nalgorithm has a time\n\n550\n00:28:42,850 --> 00:28:48,220\ncomplexity which is also\nproportional to the input\n\n551\n00:28:48,220 --> 00:28:49,460\nargument x.\n\n552\n00:28:49,460 --> 00:28:53,040\nThat's because if I were to add\n1 to 3, if I made a larger\n\n553\n00:28:53,040 --> 00:28:56,170\nproblem, which is larger by 1\nhere, then I'd add a line at\n\n554\n00:28:56,170 --> 00:28:57,670\nthe top and I'd add a\nline at the bottom.\n\n555\n00:28:57,670 --> 00:29:00,650\n\n\n556\n00:29:00,650 --> 00:29:03,300\nAnd the fact that it's a\nconstant amount, like this is\n\n557\n00:29:03,300 --> 00:29:05,420\ntwice as many lines as that,\nis not interesting at the\n\n558\n00:29:05,420 --> 00:29:08,030\nlevel of detail I'm talking\nabout right now.\n\n559\n00:29:08,030 --> 00:29:13,020\nSo this is a time complexity\norder of the input argument x.\n\n560\n00:29:13,020 --> 00:29:18,500\nAnd space complexity, well,\nthis is more interesting.\n\n561\n00:29:18,500 --> 00:29:21,130\nI happen to have some overhead,\nwhich you see over\n\n562\n00:29:21,130 --> 00:29:23,670\nhere, which is constant\napproximately.\n\n563\n00:29:23,670 --> 00:29:24,620\nConstant overhead.\n\n564\n00:29:24,620 --> 00:29:27,240\nBut then I have something which\nincreases and decreases\n\n565\n00:29:27,240 --> 00:29:29,950\nand is proportional to\nthe input argument x.\n\n566\n00:29:29,950 --> 00:29:31,350\nThe input argument x is 3.\n\n567\n00:29:31,350 --> 00:29:34,590\nThat's why there are three\ndeferred increments sitting\n\n568\n00:29:34,590 --> 00:29:36,700\naround here.\n\n569\n00:29:36,700 --> 00:29:37,720\nSee?\n\n570\n00:29:37,720 --> 00:29:42,060\nSo the space complexity\nhere is also order x.\n\n571\n00:29:42,060 --> 00:29:44,835\nAnd this kind of process, named\nfor the kind of process,\n\n572\n00:29:44,835 --> 00:29:46,085\nthis is a recursion.\n\n573\n00:29:46,085 --> 00:29:50,770\n\n\n574\n00:29:50,770 --> 00:29:56,020\nA linear recursion, I will call\nit, because of the fact\n\n575\n00:29:56,020 --> 00:29:57,920\nthat it's proportional to\nthe input argument in\n\n576\n00:29:57,920 --> 00:29:59,170\nboth time and space.\n\n577\n00:29:59,170 --> 00:30:01,560\n\n\n578\n00:30:01,560 --> 00:30:03,225\nThis could have been\na linear iteration.\n\n579\n00:30:03,225 --> 00:30:13,960\n\n\n580\n00:30:13,960 --> 00:30:16,740\nSo then what's the essence\nof this matter?\n\n581\n00:30:16,740 --> 00:30:19,100\nThis matter isn't so obvious.\n\n582\n00:30:19,100 --> 00:30:21,320\nMaybe there are other models by\nwhich we can describe the\n\n583\n00:30:21,320 --> 00:30:23,780\ndifferences between iterative\nand recursive processes.\n\n584\n00:30:23,780 --> 00:30:25,520\nBecause this is hard now.\n\n585\n00:30:25,520 --> 00:30:27,975\nRemember, we have-- those are\nboth recursive definitions.\n\n586\n00:30:27,975 --> 00:30:32,020\nWhat we're seeing there are both\nrecursive definitions,\n\n587\n00:30:32,020 --> 00:30:34,170\ndefinitions that refer to the\nthing being defined in the\n\n588\n00:30:34,170 --> 00:30:35,330\ndefinition.\n\n589\n00:30:35,330 --> 00:30:37,770\nBut they lead to different\nshape processes.\n\n590\n00:30:37,770 --> 00:30:42,220\nThere's nothing special about\nthe fact that the definition\n\n591\n00:30:42,220 --> 00:30:46,140\nis recursive that leads to\na recursive process.\n\n592\n00:30:46,140 --> 00:30:48,770\nOK.\n\n593\n00:30:48,770 --> 00:30:50,210\nLet's think of another model.\n\n594\n00:30:50,210 --> 00:30:52,940\nI'm going to talk to you\nabout bureaucracy.\n\n595\n00:30:52,940 --> 00:30:54,730\nBureaucracy is sort\nof interesting.\n\n596\n00:30:54,730 --> 00:31:00,076\nHere we see on a slide\nan iteration.\n\n597\n00:31:00,076 --> 00:31:04,220\nAn iteration is sort of\na fun kind of process.\n\n598\n00:31:04,220 --> 00:31:06,150\nImagine that there's a\nfellow called GJS--\n\n599\n00:31:06,150 --> 00:31:08,140\nthat stands for me--\n\n600\n00:31:08,140 --> 00:31:13,240\nand he's got a problem: he wants\nto add together 3 and 4.\n\n601\n00:31:13,240 --> 00:31:16,176\nThis fella here wants to\nadd together 3 and 4.\n\n602\n00:31:16,176 --> 00:31:18,850\nWell, the way he's going to do\nit-- he's lazy-- is he's going\n\n603\n00:31:18,850 --> 00:31:21,420\nto find somebody else\nto help him do it.\n\n604\n00:31:21,420 --> 00:31:22,340\nThey way he finds someone\nelse to--\n\n605\n00:31:22,340 --> 00:31:25,300\nhe finds someone else to help\nhim do it and says, well, give\n\n606\n00:31:25,300 --> 00:31:28,040\nme the answer to 3 and 4 and\nreturn the result to me.\n\n607\n00:31:28,040 --> 00:31:32,040\nHe makes a little piece of paper\nand says, here, here's a\n\n608\n00:31:32,040 --> 00:31:33,140\npiece of paper-- you go ahead\nand solve this problem and\n\n609\n00:31:33,140 --> 00:31:35,310\ngive the result back to me.\n\n610\n00:31:35,310 --> 00:31:38,370\nAnd this guy, of course,\nis lazy, too.\n\n611\n00:31:38,370 --> 00:31:41,310\nHe doesn't want to see this\npiece of paper again.\n\n612\n00:31:41,310 --> 00:31:46,550\nHe says, oh, yes, produce a new\nproblem, which is the sum\n\n613\n00:31:46,550 --> 00:31:50,420\nof 2 ad 5, and return the\nresult back to GJS.\n\n614\n00:31:50,420 --> 00:31:52,290\nI don't want to see it again.\n\n615\n00:31:52,290 --> 00:31:56,130\nThis guy does not want to\nsee this piece of paper.\n\n616\n00:31:56,130 --> 00:32:01,070\nAnd then this fellow makes a\nnew problem, which is the\n\n617\n00:32:01,070 --> 00:32:04,120\naddition of the sum of 1 and\n6, and he give it to this\n\n618\n00:32:04,120 --> 00:32:08,440\nfella and says, produce that\nanswer and returned it to GJS.\n\n619\n00:32:08,440 --> 00:32:11,270\nAnd that produces a problem,\nwhich is to add together 0 and\n\n620\n00:32:11,270 --> 00:32:14,190\n7, and give the result to GJS.\n\n621\n00:32:14,190 --> 00:32:16,650\nThis fella finally just says,\noh, yeah, the answer is 7, and\n\n622\n00:32:16,650 --> 00:32:18,480\nsends it back to GJS.\n\n623\n00:32:18,480 --> 00:32:20,160\nThat's what an iteration is.\n\n624\n00:32:20,160 --> 00:32:22,680\nBy contrast, a recursion\nis a slightly\n\n625\n00:32:22,680 --> 00:32:23,930\ndifferent kind of process.\n\n626\n00:32:23,930 --> 00:32:26,390\n\n\n627\n00:32:26,390 --> 00:32:28,520\nThis one involves more\nbureaucracy.\n\n628\n00:32:28,520 --> 00:32:30,150\nIt keeps more people busy.\n\n629\n00:32:30,150 --> 00:32:32,680\nIt keeps more people employed.\n\n630\n00:32:32,680 --> 00:32:35,850\nPerhaps it's better\nfor that reason.\n\n631\n00:32:35,850 --> 00:32:38,860\nBut here it is: I want the\nanswer to the problem 3 and 4.\n\n632\n00:32:38,860 --> 00:32:40,780\nSo I make a piece of paper that\nsays, give the result\n\n633\n00:32:40,780 --> 00:32:43,260\nback to me.\n\n634\n00:32:43,260 --> 00:32:44,670\nGive it to this fella.\n\n635\n00:32:44,670 --> 00:32:48,050\nThis fellow says, oh, yes, I\nwill remember that I have to\n\n636\n00:32:48,050 --> 00:32:51,550\nadd later, and I want to get the\nanswer the problem 2 plus\n\n637\n00:32:51,550 --> 00:32:55,980\n4, give that one to Harry,\nand have the results\n\n638\n00:32:55,980 --> 00:32:56,710\nsent back to me--\n\n639\n00:32:56,710 --> 00:32:58,830\nI'm Joe.\n\n640\n00:32:58,830 --> 00:33:01,800\nWhen the answer comes back from\nHarry, which is a 6, I\n\n641\n00:33:01,800 --> 00:33:07,600\nwill then do the increment and\ngive that 7 back to GJS.\n\n642\n00:33:07,600 --> 00:33:10,240\nSo there are more pieces of\npaper outstanding in the\n\n643\n00:33:10,240 --> 00:33:12,600\nrecursive process than\nthe iteration.\n\n644\n00:33:12,600 --> 00:33:16,890\n\n\n645\n00:33:16,890 --> 00:33:19,850\nThere's another way to think\nabout what an iteration is and\n\n646\n00:33:19,850 --> 00:33:21,780\nthe difference between an\niteration and a recursion.\n\n647\n00:33:21,780 --> 00:33:27,090\nYou see, the question is, how\nmuch stuff is under the table?\n\n648\n00:33:27,090 --> 00:33:28,650\nIf I were to stop--\n\n649\n00:33:28,650 --> 00:33:32,250\nsupposing I were to kill this\ncomputer right now, OK?\n\n650\n00:33:32,250 --> 00:33:37,040\nAnd at this point I lose the\nstate of affairs, well, I\n\n651\n00:33:37,040 --> 00:33:40,340\ncould continue the computation\nfrom this point but everything\n\n652\n00:33:40,340 --> 00:33:43,860\nI need to continue the\ncomputation is in the\n\n653\n00:33:43,860 --> 00:33:48,050\nvaluables that were defined\nin the procedure that the\n\n654\n00:33:48,050 --> 00:33:49,300\nprogrammer wrote for me.\n\n655\n00:33:49,300 --> 00:33:53,080\nAn iteration is a system that\nhas all of its state in\n\n656\n00:33:53,080 --> 00:33:54,330\nexplicit variables.\n\n657\n00:33:54,330 --> 00:33:56,990\n\n\n658\n00:33:56,990 --> 00:34:01,290\nWhereas the recursion is\nnot quite the same.\n\n659\n00:34:01,290 --> 00:34:05,820\nIf I were to lose this pile of\njunk over here, and all I was\n\n660\n00:34:05,820 --> 00:34:08,070\nleft with was the sum of 1\nand 4, that's not enough\n\n661\n00:34:08,070 --> 00:34:11,290\ninformation to continue the\nprocess of computing out the 7\n\n662\n00:34:11,290 --> 00:34:14,870\nfrom the original problem of\nadding together 3 of 4.\n\n663\n00:34:14,870 --> 00:34:20,570\nBesides the information that's\nin the variables of the formal\n\n664\n00:34:20,570 --> 00:34:24,190\nparameters of the program,\nthere is also information\n\n665\n00:34:24,190 --> 00:34:27,360\nunder the table belonging to\nthe computer, which is what\n\n666\n00:34:27,360 --> 00:34:30,440\nthings have been deferred\nfor later.\n\n667\n00:34:30,440 --> 00:34:33,500\nAnd, of course, there's a\nphysical analogy to this,\n\n668\n00:34:33,500 --> 00:34:38,300\nwhich is in differential\nequations, for example, when\n\n669\n00:34:38,300 --> 00:34:42,300\nwe talk about something\nlike drawing a circle.\n\n670\n00:34:42,300 --> 00:34:45,920\nTry to draw a circle, you make\nthat out of a differential\n\n671\n00:34:45,920 --> 00:34:51,940\nequation which says the change\nin my state as a function of\n\n672\n00:34:51,940 --> 00:34:53,190\nmy current state.\n\n673\n00:34:53,190 --> 00:34:55,830\nSo if my current state\ncorresponds to particular\n\n674\n00:34:55,830 --> 00:35:00,020\nvalues of y and x, then I can\ncompute from them a derivative\n\n675\n00:35:00,020 --> 00:35:03,480\nwhich says how the state\nmust change.\n\n676\n00:35:03,480 --> 00:35:09,470\nAnd, in fact, you can see this\nwas a circle because if I\n\n677\n00:35:09,470 --> 00:35:15,510\nhappen to be, say, at this place\nover here, at 1, 0, for\n\n678\n00:35:15,510 --> 00:35:21,240\nexample, on this graph, then it\nmeans that the derivative\n\n679\n00:35:21,240 --> 00:35:23,620\nof y is x, which we\nsee over here.\n\n680\n00:35:23,620 --> 00:35:26,140\nThat's 1, so I'm going up.\n\n681\n00:35:26,140 --> 00:35:29,075\nAnd the derivative of\nx is minus y, which\n\n682\n00:35:29,075 --> 00:35:31,510\nmeans I'm going backwards.\n\n683\n00:35:31,510 --> 00:35:33,580\nI'm actually doing nothing at\nthis point, then I start going\n\n684\n00:35:33,580 --> 00:35:37,920\nbackwards as y increases.\n\n685\n00:35:37,920 --> 00:35:40,090\nSo that's how you\nmake a circle.\n\n686\n00:35:40,090 --> 00:35:43,960\nAnd the interesting thing to see\nis a little program that\n\n687\n00:35:43,960 --> 00:35:45,400\nwill draw a circle\nby this method.\n\n688\n00:35:45,400 --> 00:35:47,675\nActually, this won't draw a\ncircle because it's a forward\n\n689\n00:35:47,675 --> 00:35:49,230\noil or integrator and\nwill eventually\n\n690\n00:35:49,230 --> 00:35:51,090\nspiral out and all that.\n\n691\n00:35:51,090 --> 00:35:52,200\nBut it'll draw a circle\nfor a while\n\n692\n00:35:52,200 --> 00:35:54,240\nbefore it starts spiraling.\n\n693\n00:35:54,240 --> 00:35:58,050\nHowever, what we see here is two\nstate variables, x and y.\n\n694\n00:35:58,050 --> 00:36:01,120\nAnd there's an iteration that\nsays, in order to circle,\n\n695\n00:36:01,120 --> 00:36:03,920\ngiven an x and y, what I want\nis to circle with the next\n\n696\n00:36:03,920 --> 00:36:08,260\nvalues of x and y being the old\nvalue of x decrement by y\n\n697\n00:36:08,260 --> 00:36:14,140\ntimes dt where dt is the time\nstep and the old value of y\n\n698\n00:36:14,140 --> 00:36:17,560\nbeing implemented by x times dt,\ngiving me the new values\n\n699\n00:36:17,560 --> 00:36:18,810\nof x and y.\n\n700\n00:36:18,810 --> 00:36:21,390\n\n\n701\n00:36:21,390 --> 00:36:25,360\nSo now you have a feeling for\nat least two different kinds\n\n702\n00:36:25,360 --> 00:36:28,900\nof processes that can\nbe evolved by\n\n703\n00:36:28,900 --> 00:36:30,150\nalmost the same program.\n\n704\n00:36:30,150 --> 00:36:32,600\n\n\n705\n00:36:32,600 --> 00:36:34,630\nAnd with a little bit of\nperturbation analysis like\n\n706\n00:36:34,630 --> 00:36:37,320\nthis, how you change a program\na little bit and see how the\n\n707\n00:36:37,320 --> 00:36:41,940\nprocess changes, that's how\nwe get some intuition.\n\n708\n00:36:41,940 --> 00:36:44,320\nPretty soon we're going to use\nthat intuition to build big,\n\n709\n00:36:44,320 --> 00:36:45,060\nhairy, complicated\n\n710\n00:36:45,060 --> 00:36:47,627\nsystems. Thank you.\n\n711\n00:36:47,627 --> 00:37:06,513\n[MUSIC PLAYING BY J.S. BACH]\n\n712\n00:37:06,513 --> 00:37:09,100\nPROFESSOR: Well, you've just\nseen a simple perturbational\n\n713\n00:37:09,100 --> 00:37:13,690\nanalysis of some programs. I\ntook a program that was very\n\n714\n00:37:13,690 --> 00:37:16,580\nsimilar to another program and\nlooked at them both and saw\n\n715\n00:37:16,580 --> 00:37:18,540\nhow they evolved processes.\n\n716\n00:37:18,540 --> 00:37:20,580\nI want to show you some variety\nby showing you some\n\n717\n00:37:20,580 --> 00:37:25,033\nother processes and shapes they\nmay have. Again, we're\n\n718\n00:37:25,033 --> 00:37:27,140\ngoing to take very simple\nthings, programs that you\n\n719\n00:37:27,140 --> 00:37:29,070\nwouldn't want to ever write.\n\n720\n00:37:29,070 --> 00:37:32,565\nThey would be probably the worst\nway of computing some of\n\n721\n00:37:32,565 --> 00:37:34,080\nthe things we're going\nto compute.\n\n722\n00:37:34,080 --> 00:37:36,040\nBut I'm just going to show you\nthese things for the purpose\n\n723\n00:37:36,040 --> 00:37:42,750\nof feeling out how to program\nrepresents itself as the rule\n\n724\n00:37:42,750 --> 00:37:46,486\nfor the evolution\nof a process.\n\n725\n00:37:46,486 --> 00:37:50,770\nSo let's consider a fun thing,\nthe Fibonacci numbers.\n\n726\n00:37:50,770 --> 00:37:53,340\nYou probably know about\nthe Fibonacci numbers.\n\n727\n00:37:53,340 --> 00:37:57,740\nSomebody, I can't remember who,\nwas interested in the\n\n728\n00:37:57,740 --> 00:38:00,035\ngrowth of piles of rabbits.\n\n729\n00:38:00,035 --> 00:38:03,670\nAnd for some reason or other,\nthe piles of rabbits tend to\n\n730\n00:38:03,670 --> 00:38:05,870\ngrow exponentially,\nas we know.\n\n731\n00:38:05,870 --> 00:38:09,700\nAnd we have a nice model for\nthis process, is that we start\n\n732\n00:38:09,700 --> 00:38:13,750\nwith two numbers, 0 and 1.\n\n733\n00:38:13,750 --> 00:38:16,000\nAnd then every number\nafter this is the\n\n734\n00:38:16,000 --> 00:38:18,040\nsum of the two previous.\n\n735\n00:38:18,040 --> 00:38:20,240\nSo we have here a 1.\n\n736\n00:38:20,240 --> 00:38:22,760\nThen the sum of these\ntwo is 2.\n\n737\n00:38:22,760 --> 00:38:24,570\nThe sum of those two is 3.\n\n738\n00:38:24,570 --> 00:38:26,465\nThe sum of those two is 5.\n\n739\n00:38:26,465 --> 00:38:28,640\nThe sum of those two is 8.\n\n740\n00:38:28,640 --> 00:38:31,650\nThe sum of those two is 13.\n\n741\n00:38:31,650 --> 00:38:34,800\nThis is 21.\n\n742\n00:38:34,800 --> 00:38:36,940\n34.\n\n743\n00:38:36,940 --> 00:38:38,160\n55.\n\n744\n00:38:38,160 --> 00:38:40,640\nEt cetera.\n\n745\n00:38:40,640 --> 00:38:43,170\nIf we start numbering these\nnumbers, say this is the\n\n746\n00:38:43,170 --> 00:38:46,280\nzeroth one, the first one, the\nsecond one, the third one, the\n\n747\n00:38:46,280 --> 00:38:47,780\nfourth one, et cetera.\n\n748\n00:38:47,780 --> 00:38:51,850\nThis is the 10th one, the\n10th Fibonacci number.\n\n749\n00:38:51,850 --> 00:38:56,010\nThese numbers grow very fast.\nJust like rabbits.\n\n750\n00:38:56,010 --> 00:38:59,750\nWhy rabbits grow this way I'm\nnot going to hazard a guess.\n\n751\n00:38:59,750 --> 00:39:02,550\nNow, I'm going to try to write\nfor you the very simplest\n\n752\n00:39:02,550 --> 00:39:05,740\nprogram that computes\nFibonacci numbers.\n\n753\n00:39:05,740 --> 00:39:08,300\n\n\n754\n00:39:08,300 --> 00:39:13,375\nWhat I want is a program that,\ngiven an n, will produce for\n\n755\n00:39:13,375 --> 00:39:14,625\nme Fibonacci event.\n\n756\n00:39:14,625 --> 00:39:18,220\n\n\n757\n00:39:18,220 --> 00:39:19,470\nOK?\n\n758\n00:39:19,470 --> 00:39:21,830\n\n\n759\n00:39:21,830 --> 00:39:23,080\nI'll write it right here.\n\n760\n00:39:23,080 --> 00:39:28,240\n\n\n761\n00:39:28,240 --> 00:39:33,275\nI want the Fibonacci of n, which\nmeans the-- this is the\n\n762\n00:39:33,275 --> 00:39:36,066\nn, and this is Fibonacci of n.\n\n763\n00:39:36,066 --> 00:39:38,160\nAnd here's the story.\n\n764\n00:39:38,160 --> 00:39:45,330\nIf n is less than 2, then\nthe result is n.\n\n765\n00:39:45,330 --> 00:39:47,260\nBecause that's what these are.\n\n766\n00:39:47,260 --> 00:39:49,090\nThat's how you start it up.\n\n767\n00:39:49,090 --> 00:39:58,870\nOtherwise, the result is the\nsum of Fib of n minus 1 and\n\n768\n00:39:58,870 --> 00:40:01,344\nthe Fibonacci number,\nn minus 2.\n\n769\n00:40:01,344 --> 00:40:10,540\n\n\n770\n00:40:10,540 --> 00:40:13,620\nSo this is a very simple, direct\nspecification of the\n\n771\n00:40:13,620 --> 00:40:16,765\ndescription of Fibonacci numbers\nthat I gave you when I\n\n772\n00:40:16,765 --> 00:40:18,460\nintroduced those numbers.\n\n773\n00:40:18,460 --> 00:40:21,670\nIt represents the recurrence\nrelation in the simplest\n\n774\n00:40:21,670 --> 00:40:23,650\npossible way.\n\n775\n00:40:23,650 --> 00:40:24,920\nNow, how do we use\nsuch a thing?\n\n776\n00:40:24,920 --> 00:40:27,230\nLet's draw this process.\n\n777\n00:40:27,230 --> 00:40:29,610\nLet's figure out\nwhat this does.\n\n778\n00:40:29,610 --> 00:40:31,620\nLet's consider something very\nsimple by computing\n\n779\n00:40:31,620 --> 00:40:32,870\nFibonacci of 4.\n\n780\n00:40:32,870 --> 00:40:35,679\n\n\n781\n00:40:35,679 --> 00:40:39,070\nTo compute Fibonacci\nof 4, what do I do?\n\n782\n00:40:39,070 --> 00:40:41,080\nWell, it says I have--\n\n783\n00:40:41,080 --> 00:40:43,070\nit's not less than 2.\n\n784\n00:40:43,070 --> 00:40:45,500\nTherefore it's the sum\nof two things.\n\n785\n00:40:45,500 --> 00:40:47,430\nWell, in order to compute that\nI have to compute, then,\n\n786\n00:40:47,430 --> 00:40:52,860\nFibonacci of 3 and\nFibonacci of 2.\n\n787\n00:40:52,860 --> 00:40:57,200\n\n\n788\n00:40:57,200 --> 00:41:00,940\nIn order to compute Fibonacci\nof 3, I have to compute\n\n789\n00:41:00,940 --> 00:41:04,340\nFibonacci of 2 and\nFibonacci of 1.\n\n790\n00:41:04,340 --> 00:41:08,000\n\n\n791\n00:41:08,000 --> 00:41:10,730\nIn order to compute Fibonacci\nof 2, I have to compute\n\n792\n00:41:10,730 --> 00:41:12,090\nFibonacci of 1 and\nFibonacci of 0.\n\n793\n00:41:12,090 --> 00:41:16,890\n\n\n794\n00:41:16,890 --> 00:41:20,010\nIn order to compute Fibonacci\nof 1, well, the answer is 1.\n\n795\n00:41:20,010 --> 00:41:26,070\nThat's from the base case\nof this recursion.\n\n796\n00:41:26,070 --> 00:41:28,923\nAnd in order to compute\nFibonacci of 0, well, that\n\n797\n00:41:28,923 --> 00:41:30,480\nanswer is 0, from\nthe same base.\n\n798\n00:41:30,480 --> 00:41:33,200\nAnd here is a 1.\n\n799\n00:41:33,200 --> 00:41:38,238\nAnd Fibonacci of 2 is really\nthe sum of Fibonacci of 1.\n\n800\n00:41:38,238 --> 00:41:43,023\nAnd Fib of 0, in order to\ncompute that, I get a 1, and\n\n801\n00:41:43,023 --> 00:41:44,273\nhere I've got a 0.\n\n802\n00:41:44,273 --> 00:41:47,010\n\n\n803\n00:41:47,010 --> 00:41:50,310\nI've built a tree.\n\n804\n00:41:50,310 --> 00:41:53,700\nNow, we can observe some\nthings about this tree.\n\n805\n00:41:53,700 --> 00:41:56,340\nWe can see why this is an\nextremely bad way to compute\n\n806\n00:41:56,340 --> 00:41:58,420\nFibonacci numbers.\n\n807\n00:41:58,420 --> 00:41:59,960\nBecause in order to compute\nFibonacci of 4, I had to\n\n808\n00:41:59,960 --> 00:42:03,045\ncompute Fibonacci of\n2's sub-tree twice.\n\n809\n00:42:03,045 --> 00:42:07,670\n\n\n810\n00:42:07,670 --> 00:42:10,326\nIn fact, in order way to add one\nmore, supposing I want to\n\n811\n00:42:10,326 --> 00:42:13,940\ndo Fibonacci of 5, what I really\nhave to do then is\n\n812\n00:42:13,940 --> 00:42:18,100\ncompute Fibonacci of 4\nplus Fibonacci of 3.\n\n813\n00:42:18,100 --> 00:42:21,045\nBut Fibonacci of 3's sub-tree\nhas already been built.\n\n814\n00:42:21,045 --> 00:42:24,870\n\n\n815\n00:42:24,870 --> 00:42:27,700\nThis is a prescription\nfor a process that's\n\n816\n00:42:27,700 --> 00:42:30,570\nexponential in time.\n\n817\n00:42:30,570 --> 00:42:33,740\nTo add 1, I have to multiply by\nsomething because I take a\n\n818\n00:42:33,740 --> 00:42:38,350\nproportion of the existing thing\nand add it to itself to\n\n819\n00:42:38,350 --> 00:42:39,880\nadd one more step.\n\n820\n00:42:39,880 --> 00:42:48,270\nSo this is a thing whose time\ncomplexity is order of--\n\n821\n00:42:48,270 --> 00:42:50,520\nactually, it turns out\nto be Fibonacci--\n\n822\n00:42:50,520 --> 00:42:51,770\nof n.\n\n823\n00:42:51,770 --> 00:42:56,230\n\n\n824\n00:42:56,230 --> 00:43:01,130\nThere's a thing that grows\nexactly at Fibonacci numbers.\n\n825\n00:43:01,130 --> 00:43:02,620\nIt's a horrible thing.\n\n826\n00:43:02,620 --> 00:43:03,640\nYou wouldn't want to do it.\n\n827\n00:43:03,640 --> 00:43:06,170\nThe reason why the time has to\ngrow that way is because we're\n\n828\n00:43:06,170 --> 00:43:07,110\npresuming in the model--\n\n829\n00:43:07,110 --> 00:43:09,220\nthe substitution model that I\ngave you, which I'm not doing\n\n830\n00:43:09,220 --> 00:43:14,130\nformally here, I sort of now\nspit it out in a simple way--\n\n831\n00:43:14,130 --> 00:43:17,880\nbut presuming that everything\nis done sequentially.\n\n832\n00:43:17,880 --> 00:43:19,810\nThat every one of these\nnodes in this\n\n833\n00:43:19,810 --> 00:43:21,350\ntree has to be examined.\n\n834\n00:43:21,350 --> 00:43:24,740\n\n\n835\n00:43:24,740 --> 00:43:27,350\nAnd so since the number of\nnodes in this tree grows\n\n836\n00:43:27,350 --> 00:43:29,960\nexponentially, because I add a\nproportion of the existing\n\n837\n00:43:29,960 --> 00:43:35,820\nnodes to the nodes I already\nhave to add 1, then I know\n\n838\n00:43:35,820 --> 00:43:38,860\nI've got an exponential\nexplosion here.\n\n839\n00:43:38,860 --> 00:43:40,610\nNow, let's see if we can\nthink of how much\n\n840\n00:43:40,610 --> 00:43:41,860\nspace this takes up.\n\n841\n00:43:41,860 --> 00:43:44,520\n\n\n842\n00:43:44,520 --> 00:43:46,140\nWell, it's not so bad.\n\n843\n00:43:46,140 --> 00:43:48,020\nIt depends on how much we have\nto remember in order to\n\n844\n00:43:48,020 --> 00:43:50,220\ncontinue this thing running.\n\n845\n00:43:50,220 --> 00:43:51,650\nWell, that's not so hard.\n\n846\n00:43:51,650 --> 00:43:54,815\nIt says, gee, in order to know\nwhere I am in this tree, I\n\n847\n00:43:54,815 --> 00:43:56,760\nhave to have a path\nback to the root.\n\n848\n00:43:56,760 --> 00:43:59,210\nIn other words, in order to--\nlet's consider the path I\n\n849\n00:43:59,210 --> 00:44:00,795\nwould have to execute this.\n\n850\n00:44:00,795 --> 00:44:03,190\nI'd say, oh, yes, I'm going\nto go down here.\n\n851\n00:44:03,190 --> 00:44:04,950\nI don't care which\ndirection I go.\n\n852\n00:44:04,950 --> 00:44:06,265\nI have to do this.\n\n853\n00:44:06,265 --> 00:44:06,935\nI have to then do this.\n\n854\n00:44:06,935 --> 00:44:09,300\nI have to traverse this tree\nin a sort of funny way.\n\n855\n00:44:09,300 --> 00:44:12,040\n\n\n856\n00:44:12,040 --> 00:44:13,290\nI'm going to walk this\nnice little path.\n\n857\n00:44:13,290 --> 00:44:15,740\nI come back to here.\n\n858\n00:44:15,740 --> 00:44:18,050\nWell, I've got to remember where\nI'm going to be next.\n\n859\n00:44:18,050 --> 00:44:20,110\nI've got to keep that in mind.\n\n860\n00:44:20,110 --> 00:44:21,240\nSo I have to know\nwhat I've done.\n\n861\n00:44:21,240 --> 00:44:22,740\nI have to know what's left.\n\n862\n00:44:22,740 --> 00:44:26,793\nIn order to compute Fibonacci of\n4, at some point I'm going\n\n863\n00:44:26,793 --> 00:44:28,580\nto have to be down here.\n\n864\n00:44:28,580 --> 00:44:32,170\nAnd I have to remember that I\nhave to go back and then go\n\n865\n00:44:32,170 --> 00:44:33,750\nback to here to do\nan addition.\n\n866\n00:44:33,750 --> 00:44:35,200\nAnd then go back to here to do\nan addition to something I\n\n867\n00:44:35,200 --> 00:44:38,060\nhaven't touched yet.\n\n868\n00:44:38,060 --> 00:44:40,390\nThe amount of space that\ntakes up is the\n\n869\n00:44:40,390 --> 00:44:42,800\npath, the longest path.\n\n870\n00:44:42,800 --> 00:44:45,920\nHow long it is.\n\n871\n00:44:45,920 --> 00:44:48,360\nAnd that grows as n.\n\n872\n00:44:48,360 --> 00:44:50,550\nSo the space--\n\n873\n00:44:50,550 --> 00:44:53,040\nbecause that's the length\nof the deepest\n\n874\n00:44:53,040 --> 00:44:54,660\nline through the tree--\n\n875\n00:44:54,660 --> 00:44:59,210\nthe space is order of n.\n\n876\n00:44:59,210 --> 00:45:00,460\nIt's a pretty bad process.\n\n877\n00:45:00,460 --> 00:45:09,010\n\n\n878\n00:45:09,010 --> 00:45:13,930\nNow, one thing I want to see\nfrom this is a feeling of\n\n879\n00:45:13,930 --> 00:45:15,660\nwhat's going on here.\n\n880\n00:45:15,660 --> 00:45:17,460\nWhy are there--\n\n881\n00:45:17,460 --> 00:45:20,712\nhow is this program related\nto this process?\n\n882\n00:45:20,712 --> 00:45:22,150\nWell, what are we seeing here?\n\n883\n00:45:22,150 --> 00:45:25,110\nThere really are only\ntwo sorts of things\n\n884\n00:45:25,110 --> 00:45:27,460\nthis program does.\n\n885\n00:45:27,460 --> 00:45:29,950\nThis program consists of\ntwo rules, if you will.\n\n886\n00:45:29,950 --> 00:45:36,100\nOne rule that says Fibonacci of\nn is this sum that you see\n\n887\n00:45:36,100 --> 00:45:42,120\nover here, which is a node\nthat's shaped like this.\n\n888\n00:45:42,120 --> 00:45:45,165\nIt says that I break up\nsomething into two parts.\n\n889\n00:45:45,165 --> 00:45:48,340\n\n\n890\n00:45:48,340 --> 00:45:52,890\nUnder some condition over here\nthat n is greater than 2, then\n\n891\n00:45:52,890 --> 00:45:56,880\nthe node breaks up\ninto two parts.\n\n892\n00:45:56,880 --> 00:45:57,920\nLess than 2.\n\n893\n00:45:57,920 --> 00:45:58,390\nNo.\n\n894\n00:45:58,390 --> 00:46:00,704\nGreater than 2.\n\n895\n00:46:00,704 --> 00:46:01,830\nYes.\n\n896\n00:46:01,830 --> 00:46:04,700\nThe other possibility is\nthat I have a reduction\n\n897\n00:46:04,700 --> 00:46:05,950\nthat looks like this.\n\n898\n00:46:05,950 --> 00:46:08,780\n\n\n899\n00:46:08,780 --> 00:46:10,950\nAnd that's this case.\n\n900\n00:46:10,950 --> 00:46:14,470\nIf it's less than 2, the\nanswer is n itself.\n\n901\n00:46:14,470 --> 00:46:16,990\nSo what we're seeing here is\nthat the process that got\n\n902\n00:46:16,990 --> 00:46:22,210\nbuilt locally at every place is\nan instance of this rule.\n\n903\n00:46:22,210 --> 00:46:24,130\nHere's one instance\nof the rule.\n\n904\n00:46:24,130 --> 00:46:26,350\nHere is another instance\nof the rule.\n\n905\n00:46:26,350 --> 00:46:28,460\nAnd the reason why people think\nof programming as being\n\n906\n00:46:28,460 --> 00:46:32,230\nhard, of course, is because\nyou're writing down a general\n\n907\n00:46:32,230 --> 00:46:37,310\nrule, which is going to be used\nfor lots of instances,\n\n908\n00:46:37,310 --> 00:46:39,710\nthat a particular instance--\n\n909\n00:46:39,710 --> 00:46:43,900\nit's going to control each\nparticular instance for you.\n\n910\n00:46:43,900 --> 00:46:46,820\nYou've got to write down\nsomething that's a general in\n\n911\n00:46:46,820 --> 00:46:48,400\nterms of variables, and you\nhave to think of all the\n\n912\n00:46:48,400 --> 00:46:50,640\nthings that could possibly fit\nin those variables, and all\n\n913\n00:46:50,640 --> 00:46:53,600\nthose have to lead to the\nprocess you want to work.\n\n914\n00:46:53,600 --> 00:46:57,770\nLocally, you have to break up\nyour process into things that\n\n915\n00:46:57,770 --> 00:46:59,490\ncan be represented in\nterms of these very\n\n916\n00:46:59,490 --> 00:47:00,740\nspecific local rules.\n\n917\n00:47:00,740 --> 00:47:03,540\n\n\n918\n00:47:03,540 --> 00:47:05,030\nWell, let's see.\n\n919\n00:47:05,030 --> 00:47:08,190\nFibonaccis are, of course,\nnot much fun.\n\n920\n00:47:08,190 --> 00:47:09,180\nYes, they are.\n\n921\n00:47:09,180 --> 00:47:12,820\nYou get something called the\ngolden ratio, and we may even\n\n922\n00:47:12,820 --> 00:47:15,420\nsee a lot of that some time.\n\n923\n00:47:15,420 --> 00:47:16,840\nWell, let's talk about\nanother thing.\n\n924\n00:47:16,840 --> 00:47:20,310\nThere's a famous game called the\nTowers of Hanoi, because I\n\n925\n00:47:20,310 --> 00:47:24,170\nwant to teach you how to think\nabout these recursively.\n\n926\n00:47:24,170 --> 00:47:29,700\nThe problem is this one: I have\na bunch of disks, I have\n\n927\n00:47:29,700 --> 00:47:34,130\na bunch of spikes, and it's\nrumored that somewhere in the\n\n928\n00:47:34,130 --> 00:47:38,420\nOrient there is a 64-high tower,\nand the job of various\n\n929\n00:47:38,420 --> 00:47:41,320\nmonks or something is to move\nthese spikes in some\n\n930\n00:47:41,320 --> 00:47:43,860\ncomplicated pattern\nso eventually--\n\n931\n00:47:43,860 --> 00:47:45,220\nthese disks--\n\n932\n00:47:45,220 --> 00:47:49,450\nso eventually I moved all\nof the disks from one\n\n933\n00:47:49,450 --> 00:47:50,555\nspike to the other.\n\n934\n00:47:50,555 --> 00:47:54,000\nAnd if it's 64 high, and it's\ngoing to take 2 to the 64th\n\n935\n00:47:54,000 --> 00:47:57,746\nmoves, then it's a long time.\n\n936\n00:47:57,746 --> 00:48:03,820\nThey claim that the universe\nends when this is done.\n\n937\n00:48:03,820 --> 00:48:05,630\nWell, let's see.\n\n938\n00:48:05,630 --> 00:48:08,830\nThe way in which you would\nconstruct a recursive process\n\n939\n00:48:08,830 --> 00:48:11,990\nis by wishful thinking.\n\n940\n00:48:11,990 --> 00:48:14,600\nYou have to believe.\n\n941\n00:48:14,600 --> 00:48:15,610\nSo, the idea.\n\n942\n00:48:15,610 --> 00:48:20,360\nSupposing I want to move this\npile from here to here, from\n\n943\n00:48:20,360 --> 00:48:25,400\nspike one to spike two, well,\nthat's not so hard.\n\n944\n00:48:25,400 --> 00:48:28,470\nSee, supposing somehow, by some\nmagic-- because I've got\n\n945\n00:48:28,470 --> 00:48:29,310\na simpler problem--\n\n946\n00:48:29,310 --> 00:48:31,240\nI move a three-high\npile to here--\n\n947\n00:48:31,240 --> 00:48:32,070\nI can only move one\ndisk at a time, so\n\n948\n00:48:32,070 --> 00:48:33,900\nidentifying how I did it.\n\n949\n00:48:33,900 --> 00:48:37,910\nBut supposing I could do that,\nwell, then I could just pick\n\n950\n00:48:37,910 --> 00:48:41,500\nup this disk and move it here.\n\n951\n00:48:41,500 --> 00:48:42,980\nAnd now I have a\nsimple problem.\n\n952\n00:48:42,980 --> 00:48:44,110\nI have to move a three-high\ntower to\n\n953\n00:48:44,110 --> 00:48:46,220\nhere, which is no problem.\n\n954\n00:48:46,220 --> 00:48:48,860\nSo by two moves of a three high\ntower plus one move of a\n\n955\n00:48:48,860 --> 00:48:53,140\nsingle object, I can move the\ntower from here to here.\n\n956\n00:48:53,140 --> 00:48:55,680\n\n\n957\n00:48:55,680 --> 00:48:57,530\nNow, whether or not--\n\n958\n00:48:57,530 --> 00:49:02,730\nthis is not obvious in any\ndeep way that this works.\n\n959\n00:49:02,730 --> 00:49:04,300\nAnd why?\n\n960\n00:49:04,300 --> 00:49:07,320\nNow, why is it the case that I\ncan presume, maybe, that I can\n\n961\n00:49:07,320 --> 00:49:08,570\nmove the three-high tower?\n\n962\n00:49:08,570 --> 00:49:11,430\n\n\n963\n00:49:11,430 --> 00:49:14,550\nWell, the answer is because I'm\nalways counting down, and\n\n964\n00:49:14,550 --> 00:49:16,840\neventually I get down to\nzero-high tower, and a\n\n965\n00:49:16,840 --> 00:49:20,070\nzero-high tower requires\nno moves.\n\n966\n00:49:20,070 --> 00:49:24,060\nSo let's write the algorithm\nfor that.\n\n967\n00:49:24,060 --> 00:49:26,670\nVery easy.\n\n968\n00:49:26,670 --> 00:49:29,260\nI'm going to label these towers\nwith numbers, but it\n\n969\n00:49:29,260 --> 00:49:31,120\ndoesn't matter what they're\nlabelled with.\n\n970\n00:49:31,120 --> 00:49:35,020\nAnd the problem is to move an\nn-high tower from a spike\n\n971\n00:49:35,020 --> 00:49:37,785\ncalled From to a spike called\nTo with a particular spike\n\n972\n00:49:37,785 --> 00:49:39,968\ncalled Spare.\n\n973\n00:49:39,968 --> 00:49:41,414\nThat's what we're going to do.\n\n974\n00:49:41,414 --> 00:49:50,240\n\n\n975\n00:49:50,240 --> 00:49:53,070\nUsing the algorithm I informally\ndescribed to you,\n\n976\n00:49:53,070 --> 00:50:02,532\nmove of a n-high tower from\nFrom to To with a Spare.\n\n977\n00:50:02,532 --> 00:50:06,300\n\n\n978\n00:50:06,300 --> 00:50:11,540\nWell, I've got two cases, and\nthis is a case analysis, just\n\n979\n00:50:11,540 --> 00:50:14,840\nlike it is in all the other\nthings we've done.\n\n980\n00:50:14,840 --> 00:50:20,285\n\n\n981\n00:50:20,285 --> 00:50:23,160\nIf n is 0, then--\n\n982\n00:50:23,160 --> 00:50:24,600\nI'm going to put out\nsome answers--\n\n983\n00:50:24,600 --> 00:50:26,870\nDone, we'll say.\n\n984\n00:50:26,870 --> 00:50:29,530\nI don't know what that means.\n\n985\n00:50:29,530 --> 00:50:32,200\nBecause we'll never use that\nanswer for anything.\n\n986\n00:50:32,200 --> 00:50:34,350\nWe're going to do these moves.\n\n987\n00:50:34,350 --> 00:50:36,640\nElse.\n\n988\n00:50:36,640 --> 00:50:37,890\nI'm going to do a move.\n\n989\n00:50:37,890 --> 00:50:40,250\n\n\n990\n00:50:40,250 --> 00:50:44,495\nMove a tower of height\nless than n, the\n\n991\n00:50:44,495 --> 00:50:48,140\ndecrement of n height.\n\n992\n00:50:48,140 --> 00:50:51,030\nNow, I'm going to move it\nto the Spare tower.\n\n993\n00:50:51,030 --> 00:50:55,220\nThe whole idea now is to move\nthis from here to here, to the\n\n994\n00:50:55,220 --> 00:50:57,550\nSpare tower-- so from\nFrom to Spare--\n\n995\n00:50:57,550 --> 00:51:03,050\n\n\n996\n00:51:03,050 --> 00:51:04,700\nusing To as a spare tower.\n\n997\n00:51:04,700 --> 00:51:08,960\n\n\n998\n00:51:08,960 --> 00:51:14,680\nLater, somewhere later, I'm\ngoing to move that same n-high\n\n999\n00:51:14,680 --> 00:51:17,340\ntower, after I've done this.\n\n1000\n00:51:17,340 --> 00:51:21,650\nGoing to move that same n minus\none-high tower from the\n\n1001\n00:51:21,650 --> 00:51:24,750\nSpare tower to the To\ntower using the\n\n1002\n00:51:24,750 --> 00:51:26,380\nFrom tower as my spare.\n\n1003\n00:51:26,380 --> 00:51:29,390\n\n\n1004\n00:51:29,390 --> 00:51:40,410\nSo the Spare tower to\nthe To tower using\n\n1005\n00:51:40,410 --> 00:51:44,225\nthe From as the spare.\n\n1006\n00:51:44,225 --> 00:51:48,780\n\n\n1007\n00:51:48,780 --> 00:51:51,670\nAll I have to do now is when\nI've gotten it in this\n\n1008\n00:51:51,670 --> 00:51:56,600\ncondition, between these two\nmoves of a whole tower--\n\n1009\n00:51:56,600 --> 00:51:57,950\nI've got it into that\ncondition--\n\n1010\n00:51:57,950 --> 00:52:03,100\nnow I just have to\nmove one disk.\n\n1011\n00:52:03,100 --> 00:52:04,543\nSo I'm going to say that some\nthings are printing a move and\n\n1012\n00:52:04,543 --> 00:52:05,793\nI don't care how it works.\n\n1013\n00:52:05,793 --> 00:52:11,680\n\n\n1014\n00:52:11,680 --> 00:52:13,660\nFrom the To.\n\n1015\n00:52:13,660 --> 00:52:17,890\n\n\n1016\n00:52:17,890 --> 00:52:20,410\nNow, you see the reason why I'm\nbringing this up at this\n\n1017\n00:52:20,410 --> 00:52:24,800\nmoment is this is an almost\nidentical program to this one\n\n1018\n00:52:24,800 --> 00:52:26,980\nin some sense.\n\n1019\n00:52:26,980 --> 00:52:29,810\nIt's not computing the same\nmathematical quantity, it's\n\n1020\n00:52:29,810 --> 00:52:34,620\nnot exactly the same tree, but\nit's going to produce a tree.\n\n1021\n00:52:34,620 --> 00:52:38,760\nThe general way of making these\nmoves is going to lead\n\n1022\n00:52:38,760 --> 00:52:41,760\nto an exponential tree.\n\n1023\n00:52:41,760 --> 00:52:43,060\nWell, let's do this four-high.\n\n1024\n00:52:43,060 --> 00:52:45,720\n\n\n1025\n00:52:45,720 --> 00:52:50,660\nI have my little crib sheet here\notherwise I get confused.\n\n1026\n00:52:50,660 --> 00:52:54,720\n\n\n1027\n00:52:54,720 --> 00:52:57,320\nWell, what I'm going to put in\nis the question of move a\n\n1028\n00:52:57,320 --> 00:53:10,080\ntower of height four from one to\nspike two using spike three\n\n1029\n00:53:10,080 --> 00:53:11,980\nas a spare.\n\n1030\n00:53:11,980 --> 00:53:14,190\nThat's all I'm really\ngoing to do.\n\n1031\n00:53:14,190 --> 00:53:15,550\nYou know, let's just do it.\n\n1032\n00:53:15,550 --> 00:53:17,140\nI'm not going to worry\nabout writing out\n\n1033\n00:53:17,140 --> 00:53:17,950\nthe traits of this.\n\n1034\n00:53:17,950 --> 00:53:21,950\nYou can do that yourself because\nit's very simple.\n\n1035\n00:53:21,950 --> 00:53:26,680\nI'm going to move disk\none to disk three.\n\n1036\n00:53:26,680 --> 00:53:28,760\nAnd how do I get to move\ndisk one to disk three?\n\n1037\n00:53:28,760 --> 00:53:29,530\nHow do I know that?\n\n1038\n00:53:29,530 --> 00:53:32,790\nWell, I suppose I have to look\nat the trace a little bit.\n\n1039\n00:53:32,790 --> 00:53:33,810\nWhat am I doing here?\n\n1040\n00:53:33,810 --> 00:53:36,560\nWell, and this is not--\nn is not zero.\n\n1041\n00:53:36,560 --> 00:53:38,650\nSo I'm going to look\ndown here.\n\n1042\n00:53:38,650 --> 00:53:41,000\nThis is going to require\ndoing two moves.\n\n1043\n00:53:41,000 --> 00:53:42,320\nI'm only going to look\nat the first one.\n\n1044\n00:53:42,320 --> 00:53:43,570\nIt's going to require moving--\n\n1045\n00:53:43,570 --> 00:53:47,860\n\n\n1046\n00:53:47,860 --> 00:53:49,010\nwhy do I have move tower?\n\n1047\n00:53:49,010 --> 00:53:52,910\nIt makes it harder\nfor me to move.\n\n1048\n00:53:52,910 --> 00:53:59,950\nI'm going to move a three-high\ntower from the from place,\n\n1049\n00:53:59,950 --> 00:54:04,750\nwhich is four, to the\nspare, which is two,\n\n1050\n00:54:04,750 --> 00:54:07,940\nusing three as my--\n\n1051\n00:54:07,940 --> 00:54:15,220\nno, using from--\n\n1052\n00:54:15,220 --> 00:54:15,988\nSTUDENT: [INAUDIBLE PHRASE].\n\n1053\n00:54:15,988 --> 00:54:16,944\nPROFESSOR: Yes.\n\n1054\n00:54:16,944 --> 00:54:18,370\nI'm sorry.\n\n1055\n00:54:18,370 --> 00:54:19,710\nFrom two--\n\n1056\n00:54:19,710 --> 00:54:26,230\nfrom one to three using\ntwo as my spare.\n\n1057\n00:54:26,230 --> 00:54:27,520\nThat's right.\n\n1058\n00:54:27,520 --> 00:54:32,940\nAnd then there's another move\nover here afterwards.\n\n1059\n00:54:32,940 --> 00:54:37,790\nSo now I say, oh, yes, that\nrequires me moving a two-high\n\n1060\n00:54:37,790 --> 00:54:42,950\ntower from one to two using\nthree as a spare.\n\n1061\n00:54:42,950 --> 00:54:45,760\nAnd so, are the same, and that's\ngoing to require me\n\n1062\n00:54:45,760 --> 00:54:52,470\nmoving and one-high tower\nfrom one to three\n\n1063\n00:54:52,470 --> 00:54:53,720\nusing two as a spare.\n\n1064\n00:54:53,720 --> 00:54:57,740\n\n\n1065\n00:54:57,740 --> 00:54:59,720\nWell, and then there's lots of\nother things to be done.\n\n1066\n00:54:59,720 --> 00:55:03,510\n\n\n1067\n00:55:03,510 --> 00:55:09,265\nSo I move my one-high tower from\none to three using two as\n\n1068\n00:55:09,265 --> 00:55:11,490\na spare, which I didn't\ndo anything with.\n\n1069\n00:55:11,490 --> 00:55:15,570\nWell, this thing just proceeds\nvery simply.\n\n1070\n00:55:15,570 --> 00:55:17,652\nI move this from one to two.\n\n1071\n00:55:17,652 --> 00:55:21,500\nAnd I move this disk\nfrom three to two.\n\n1072\n00:55:21,500 --> 00:55:23,060\nAnd I don't really want\nto do it, but I\n\n1073\n00:55:23,060 --> 00:55:24,310\nmove from one to three.\n\n1074\n00:55:24,310 --> 00:55:29,390\nThen I move two to one.\n\n1075\n00:55:29,390 --> 00:55:32,150\nThen I move two to three.\n\n1076\n00:55:32,150 --> 00:55:36,310\nThen one to three.\n\n1077\n00:55:36,310 --> 00:55:39,620\nOne to two.\n\n1078\n00:55:39,620 --> 00:55:41,390\nThree to two.\n\n1079\n00:55:41,390 --> 00:55:44,055\nThree to one.\n\n1080\n00:55:44,055 --> 00:55:46,380\nThis all got worked out\nbeforehand, of course.\n\n1081\n00:55:46,380 --> 00:55:48,090\nTwo to one.\n\n1082\n00:55:48,090 --> 00:55:50,810\nThree to two.\n\n1083\n00:55:50,810 --> 00:55:52,950\nOne to three.\n\n1084\n00:55:52,950 --> 00:55:54,176\nSTUDENT: [INAUDIBLE PHRASE].\n\n1085\n00:55:54,176 --> 00:55:55,650\nPROFESSOR: Oh, one to three.\n\n1086\n00:55:55,650 --> 00:55:55,823\nExcuse me.\n\n1087\n00:55:55,823 --> 00:55:56,460\nThank you.\n\n1088\n00:55:56,460 --> 00:55:59,020\nOne to two.\n\n1089\n00:55:59,020 --> 00:56:00,850\nAnd then three to two.\n\n1090\n00:56:00,850 --> 00:56:02,100\nWhew.\n\n1091\n00:56:02,100 --> 00:56:04,250\n\n\n1092\n00:56:04,250 --> 00:56:07,920\nNow what I'd like you to think\nabout, you just saw a\n\n1093\n00:56:07,920 --> 00:56:09,920\nrecursive algorithm for doing\nthis, and it takes exponential\n\n1094\n00:56:09,920 --> 00:56:11,040\ntime, of course.\n\n1095\n00:56:11,040 --> 00:56:12,530\nNow, I don't know if there's\nany algorithm that doesn't\n\n1096\n00:56:12,530 --> 00:56:14,820\ntake exponential time--\nit has to.\n\n1097\n00:56:14,820 --> 00:56:16,320\nAs I'm doing one operation--\n\n1098\n00:56:16,320 --> 00:56:17,890\nI can only move one\nthing at a time--\n\n1099\n00:56:17,890 --> 00:56:18,590\nthere's no algorithm\nthat's not going to\n\n1100\n00:56:18,590 --> 00:56:20,570\ntake exponential time.\n\n1101\n00:56:20,570 --> 00:56:24,420\nBut can you write an iterative\nalgorithm rather than a\n\n1102\n00:56:24,420 --> 00:56:25,670\nrecursive algorithm\nfor doing this?\n\n1103\n00:56:25,670 --> 00:56:28,740\n\n\n1104\n00:56:28,740 --> 00:56:30,700\nOne of the sort of little things\nI like to think about.\n\n1105\n00:56:30,700 --> 00:56:33,590\n\n\n1106\n00:56:33,590 --> 00:56:38,970\nCan you write one that, in\nfact, doesn't break this\n\n1107\n00:56:38,970 --> 00:56:41,510\nproblem into two sub-problems\nthe way I described, but\n\n1108\n00:56:41,510 --> 00:56:45,250\nrather proceeds a step at a time\nusing a more local rule?\n\n1109\n00:56:45,250 --> 00:56:48,160\n\n\n1110\n00:56:48,160 --> 00:56:50,660\nThat might be fun.\n\n1111\n00:56:50,660 --> 00:56:52,025\nThank you so much for\nthe third segment.\n\n1112\n00:56:52,025 --> 00:56:56,310\n\n\n1113\n00:56:56,310 --> 00:56:57,910\nAre there questions?\n\n1114\n00:56:57,910 --> 00:57:01,670\nSTUDENT: [INAUDIBLE] a way to\nreduce a tree or recursion\n\n1115\n00:57:01,670 --> 00:57:06,970\nproblem, how do you save the\nimmediate work you have done\n\n1116\n00:57:06,970 --> 00:57:08,985\nin computing the Fibonacci\nnumber?\n\n1117\n00:57:08,985 --> 00:57:12,760\nPROFESSOR: Oh, well, in fact,\none of the ways to do is what\n\n1118\n00:57:12,760 --> 00:57:13,890\nyou just said.\n\n1119\n00:57:13,890 --> 00:57:16,480\nYou said, I save the\nintermediate work.\n\n1120\n00:57:16,480 --> 00:57:16,960\nOK?\n\n1121\n00:57:16,960 --> 00:57:19,310\nWell, let me tell you--\n\n1122\n00:57:19,310 --> 00:57:21,010\nthis, again, we'll see later--\n\n1123\n00:57:21,010 --> 00:57:24,710\nbut suppose it's the case that\nanytime I compute anything,\n\n1124\n00:57:24,710 --> 00:57:28,240\nany one of these Fibonacci\nnumbers, I remember the table\n\n1125\n00:57:28,240 --> 00:57:32,790\nthat takes only linear time\nto look up the answer.\n\n1126\n00:57:32,790 --> 00:57:35,180\nThen if I ever see it again,\ninstead of doing the\n\n1127\n00:57:35,180 --> 00:57:37,050\nexpansional tree,\nI look it up.\n\n1128\n00:57:37,050 --> 00:57:39,820\nI've just transformed my problem\ninto a problem that's\n\n1129\n00:57:39,820 --> 00:57:41,380\nmuch simpler.\n\n1130\n00:57:41,380 --> 00:57:44,380\nNow, of course, there are the\nway to do this, as well.\n\n1131\n00:57:44,380 --> 00:57:47,240\nThat one's called memoization,\nand you'll see it sometime\n\n1132\n00:57:47,240 --> 00:57:48,280\nlater in this term.\n\n1133\n00:57:48,280 --> 00:57:53,890\nBut I suppose there's a very\nsimple linear time, and, in\n\n1134\n00:57:53,890 --> 00:57:57,110\nfact, iterative model for\ncomputing Fibonaccis, and\n\n1135\n00:57:57,110 --> 00:58:00,320\nthat's another thing you should\nsit down and work out.\n\n1136\n00:58:00,320 --> 00:58:01,340\nThat's important.\n\n1137\n00:58:01,340 --> 00:58:05,560\nIt's important to see\nhow to do this.\n\n1138\n00:58:05,560 --> 00:58:07,310\nI want you to practice.\n\n1139\n00:58:07,310 --> 00:58:19,540\n\n"
  },
  {
    "path": "SrtEN/lec2a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:25,680\n\n\n1\n00:00:25,680 --> 00:00:27,960\nPROFESSOR: Well, yesterday\nwas easy.\n\n2\n00:00:27,960 --> 00:00:33,020\nYou learned all of the rules\nof programming and lived.\n\n3\n00:00:33,020 --> 00:00:34,980\nAlmost all of them.\n\n4\n00:00:34,980 --> 00:00:38,372\nAnd so at this point, you're\nnow certified programmers--\n\n5\n00:00:38,372 --> 00:00:40,200\nit says.\n\n6\n00:00:40,200 --> 00:00:48,890\nHowever, I suppose what we did\nis we, aah, sort of got you a\n\n7\n00:00:48,890 --> 00:00:51,700\nlittle bit of into\nan easy state.\n\n8\n00:00:51,700 --> 00:00:54,770\nHere, you still believe it's\npossible that this might be\n\n9\n00:00:54,770 --> 00:00:59,250\nprogramming in BASIC or Pascal\nwith just a funny syntax.\n\n10\n00:00:59,250 --> 00:01:01,770\nToday, that illusion--\n\n11\n00:01:01,770 --> 00:01:04,919\nor you can no longer support\nthat belief.\n\n12\n00:01:04,919 --> 00:01:06,450\nWhat we're going to do\ntoday is going to\n\n13\n00:01:06,450 --> 00:01:08,340\ncompletely smash that.\n\n14\n00:01:08,340 --> 00:01:13,590\nSo let's start out by writing\na few programs on the\n\n15\n00:01:13,590 --> 00:01:15,895\nblackboard that have a lot in\ncommon with each other.\n\n16\n00:01:15,895 --> 00:01:19,540\nWhat we're going to do is try to\nmake them abstractions that\n\n17\n00:01:19,540 --> 00:01:23,880\nare not ones that are easy to\nmake in most languages.\n\n18\n00:01:23,880 --> 00:01:26,040\nLet's start with some very\nsimple ones that you can make\n\n19\n00:01:26,040 --> 00:01:28,070\nin most languages.\n\n20\n00:01:28,070 --> 00:01:32,130\nSupposing I want to write the\nmathematical expression which\n\n21\n00:01:32,130 --> 00:01:34,100\nadds up a bunch of integers.\n\n22\n00:01:34,100 --> 00:01:38,850\nSo if I wanted to write down\nand say the sum from i\n\n23\n00:01:38,850 --> 00:01:41,410\nequal a to b on i.\n\n24\n00:01:41,410 --> 00:01:44,190\nNow, you know that that's an\neasy thing to compute in a\n\n25\n00:01:44,190 --> 00:01:46,180\nclosed form for it, and I'm\nnot interested in that.\n\n26\n00:01:46,180 --> 00:01:47,140\nBut I'm going to write\na program that\n\n27\n00:01:47,140 --> 00:01:49,045\nadds up those integers.\n\n28\n00:01:49,045 --> 00:01:57,890\nWell, that's rather easy to do\nto say I want to define the\n\n29\n00:01:57,890 --> 00:02:08,710\nsum of the integers from\na to b to be--\n\n30\n00:02:08,710 --> 00:02:11,380\nwell, it's the following\ntwo possibilities.\n\n31\n00:02:11,380 --> 00:02:17,430\nIf a is greater than b, well,\nthen there's nothing to be\n\n32\n00:02:17,430 --> 00:02:19,582\ndone and the answer is zero.\n\n33\n00:02:19,582 --> 00:02:22,530\nThis is how you're going to\nhave to think recursively.\n\n34\n00:02:22,530 --> 00:02:24,880\nYou're going to say if I have\nan easy case that I know the\n\n35\n00:02:24,880 --> 00:02:26,610\nanswer to, just write it down.\n\n36\n00:02:26,610 --> 00:02:29,890\nOtherwise, I'm going to try to\nreduce this problem to a\n\n37\n00:02:29,890 --> 00:02:31,060\nsimpler problem.\n\n38\n00:02:31,060 --> 00:02:33,000\nAnd maybe in this case, I'm\ngoing to make a subproblem of\n\n39\n00:02:33,000 --> 00:02:35,340\nthe simpler problem and then\ndo something to the result.\n\n40\n00:02:35,340 --> 00:02:41,290\nSo the easiest way to do this\nis say that I'm going to add\n\n41\n00:02:41,290 --> 00:02:46,530\nthe index, which in this case is\na, to the result of adding\n\n42\n00:02:46,530 --> 00:02:57,960\nup the integers from\na plus 1 to b.\n\n43\n00:02:57,960 --> 00:03:02,343\n\n\n44\n00:03:02,343 --> 00:03:04,460\nNow, at this point, you should\nhave no trouble looking at\n\n45\n00:03:04,460 --> 00:03:06,190\nsuch a definition.\n\n46\n00:03:06,190 --> 00:03:09,740\nIndeed, coming up with such a\nthing might be a little hard\n\n47\n00:03:09,740 --> 00:03:12,230\nin synthesis, but being able\nto read it at this point\n\n48\n00:03:12,230 --> 00:03:13,840\nshould be easy.\n\n49\n00:03:13,840 --> 00:03:18,220\nAnd what it says to you is,\nwell, here is the subproblem\n\n50\n00:03:18,220 --> 00:03:19,520\nI'm going to solve.\n\n51\n00:03:19,520 --> 00:03:24,240\nI'm going to try to add up the\nintegers, one fewer integer\n\n52\n00:03:24,240 --> 00:03:26,970\nthan I added up for the\nthe whole problem.\n\n53\n00:03:26,970 --> 00:03:31,270\nI'm adding up the one fewer one,\nand that subproblem, once\n\n54\n00:03:31,270 --> 00:03:35,150\nI've solved it, I'm going to add\na to that, and that will\n\n55\n00:03:35,150 --> 00:03:38,550\nbe the answer to this problem.\n\n56\n00:03:38,550 --> 00:03:41,626\nAnd the simplest case, I don't\nhave to do any work.\n\n57\n00:03:41,626 --> 00:03:44,990\nNow, I'm also going to write\ndown another simple one just\n\n58\n00:03:44,990 --> 00:03:49,617\nlike this, which is the\nmathematical expression, the\n\n59\n00:03:49,617 --> 00:03:55,840\nsum of the square from\ni equal a to b.\n\n60\n00:03:55,840 --> 00:03:58,055\nAnd again, it's a very\nsimple program.\n\n61\n00:03:58,055 --> 00:04:11,220\n\n\n62\n00:04:11,220 --> 00:04:13,510\nAnd indeed, it starts\nthe same way.\n\n63\n00:04:13,510 --> 00:04:16,029\n\n\n64\n00:04:16,029 --> 00:04:21,240\nIf a is greater than b, then\nthe answer is zero.\n\n65\n00:04:21,240 --> 00:04:24,160\nAnd, of course, we're beginning\nto see that there's\n\n66\n00:04:24,160 --> 00:04:27,980\nsomething wrong with me writing\nthis down again.\n\n67\n00:04:27,980 --> 00:04:29,820\nIt's the same program.\n\n68\n00:04:29,820 --> 00:04:42,180\nIt's the sum of the square of a\nand the sum of the square of\n\n69\n00:04:42,180 --> 00:04:46,134\nthe increment and b.\n\n70\n00:04:46,134 --> 00:04:50,880\n\n\n71\n00:04:50,880 --> 00:04:54,070\nNow, if you look at these\nthings, these programs are\n\n72\n00:04:54,070 --> 00:04:56,380\nalmost identical.\n\n73\n00:04:56,380 --> 00:04:59,860\nThere's not much to\ndistinguish them.\n\n74\n00:04:59,860 --> 00:05:03,140\nThey have the same first clause\nof the conditional and\n\n75\n00:05:03,140 --> 00:05:06,250\nthe same predicate and the\nsame consequence, and the\n\n76\n00:05:06,250 --> 00:05:08,910\nalternatives are very\nsimilar, too.\n\n77\n00:05:08,910 --> 00:05:15,510\nThey only differ by the fact\nthat where here I have a,\n\n78\n00:05:15,510 --> 00:05:17,336\nhere, I have the square of a.\n\n79\n00:05:17,336 --> 00:05:22,020\nThe only other difference, but\nthis one's sort of unessential\n\n80\n00:05:22,020 --> 00:05:25,240\nis in the name of this procedure\nis sum int, whereas\n\n81\n00:05:25,240 --> 00:05:27,560\nthe name of the procedure\nis sum square.\n\n82\n00:05:27,560 --> 00:05:29,820\nSo the things that vary\nbetween these\n\n83\n00:05:29,820 --> 00:05:33,250\ntwo are very small.\n\n84\n00:05:33,250 --> 00:05:36,080\nNow, wherever you see yourself\nwriting the same thing down\n\n85\n00:05:36,080 --> 00:05:38,340\nmore than once, there's\nsomething wrong, and you\n\n86\n00:05:38,340 --> 00:05:40,280\nshouldn't be doing it.\n\n87\n00:05:40,280 --> 00:05:43,420\nAnd the reason is not because\nit's a waste of time to write\n\n88\n00:05:43,420 --> 00:05:45,540\nsomething down more than once.\n\n89\n00:05:45,540 --> 00:05:50,720\nIt's because there's some idea\nhere, a very simple idea,\n\n90\n00:05:50,720 --> 00:05:54,620\nwhich has to do with the\nsigma notation--\n\n91\n00:05:54,620 --> 00:05:57,330\nthis much--\n\n92\n00:05:57,330 --> 00:06:01,255\nnot depending upon what\nit is I'm adding up.\n\n93\n00:06:01,255 --> 00:06:03,070\nAnd I would like\nto be able to--\n\n94\n00:06:03,070 --> 00:06:05,610\nalways, whenever trying to make\ncomplicated systems and\n\n95\n00:06:05,610 --> 00:06:08,575\nunderstand them, it's crucial\nto divide the things up into\n\n96\n00:06:08,575 --> 00:06:11,030\nas many pieces as I can, each\nof which I understand\n\n97\n00:06:11,030 --> 00:06:13,050\nseparately.\n\n98\n00:06:13,050 --> 00:06:15,030\nI would like to understand the\nway of adding things up\n\n99\n00:06:15,030 --> 00:06:19,540\nindependently of what it is I'm\nadding up so I can do that\n\n100\n00:06:19,540 --> 00:06:24,260\nhaving debugged it once and\nunderstood it once and having\n\n101\n00:06:24,260 --> 00:06:29,400\nbeen able to share that among\nmany different uses of it.\n\n102\n00:06:29,400 --> 00:06:32,360\nHere, we have another example.\n\n103\n00:06:32,360 --> 00:06:40,400\nThis is Leibnitz's formula\nfor finding pi over 8.\n\n104\n00:06:40,400 --> 00:06:43,460\nIt's a funny, ugly mess.\n\n105\n00:06:43,460 --> 00:06:43,930\nWhat is it?\n\n106\n00:06:43,930 --> 00:06:50,670\nIt's something like 1 over 1\ntimes 3 plus 1 over 5 times 7\n\n107\n00:06:50,670 --> 00:06:54,340\nplus 1 over 9 times 11 plus--\n\n108\n00:06:54,340 --> 00:06:59,750\nand for some reason, things\nlike this tend to have\n\n109\n00:06:59,750 --> 00:07:02,160\ninteresting values\nlike pi over 8.\n\n110\n00:07:02,160 --> 00:07:04,460\nBut what do we see here?\n\n111\n00:07:04,460 --> 00:07:07,850\nIt's the same program or almost\nthe same program.\n\n112\n00:07:07,850 --> 00:07:09,290\nIt's a sum.\n\n113\n00:07:09,290 --> 00:07:12,660\nSo we're seeing the figure\nnotation, although over here,\n\n114\n00:07:12,660 --> 00:07:17,320\nwe're dealing with incrementing\nby 4, so it's a\n\n115\n00:07:17,320 --> 00:07:20,550\nslightly different problem,\nwhich means that over here, I\n\n116\n00:07:20,550 --> 00:07:25,560\nhave to change a by 4, as\nyou see right over here.\n\n117\n00:07:25,560 --> 00:07:28,390\nIt's not by 1.\n\n118\n00:07:28,390 --> 00:07:31,150\nThe other thing, of course,\nis that the thing that's\n\n119\n00:07:31,150 --> 00:07:34,805\nrepresented by square in the\nprevious sum of squares, or a\n\n120\n00:07:34,805 --> 00:07:36,400\nwhen adding up the integers.\n\n121\n00:07:36,400 --> 00:07:38,060\nWell, here, I have a different\nthing I'm adding up, a\n\n122\n00:07:38,060 --> 00:07:44,290\ndifferent term, which is 1\nover a times a plus 2.\n\n123\n00:07:44,290 --> 00:07:45,875\nBut the rest of this program\nis identical.\n\n124\n00:07:45,875 --> 00:07:48,530\n\n\n125\n00:07:48,530 --> 00:07:50,640\nWell, any time we have a bunch\nof things like this that are\n\n126\n00:07:50,640 --> 00:07:53,200\nidentical, we're going to have\nto come up with some sort of\n\n127\n00:07:53,200 --> 00:07:55,582\nabstraction to cover them.\n\n128\n00:07:55,582 --> 00:07:59,920\nIf you think about this, what\nyou've learned so far is the\n\n129\n00:07:59,920 --> 00:08:03,370\nrules of some language, some\nprimitive, some means of\n\n130\n00:08:03,370 --> 00:08:06,310\ncombination, almost all\nof them, the means of\n\n131\n00:08:06,310 --> 00:08:09,730\nabstraction, almost\nall of them.\n\n132\n00:08:09,730 --> 00:08:13,290\nBut what you haven't learned is\ncommon patterns of usage.\n\n133\n00:08:13,290 --> 00:08:15,150\nNow, most of the time, you learn\nidioms when learning a\n\n134\n00:08:15,150 --> 00:08:18,380\nlanguage, which is a common\npattern that mean things that\n\n135\n00:08:18,380 --> 00:08:20,760\nare useful to know in a flash.\n\n136\n00:08:20,760 --> 00:08:22,760\nAnd if you build a great number\nof them, if you're a\n\n137\n00:08:22,760 --> 00:08:26,180\nFORTRAN programmer, of course,\neverybody knows how to--\n\n138\n00:08:26,180 --> 00:08:29,640\nwhat do you do, for example, to\nget an integer which is the\n\n139\n00:08:29,640 --> 00:08:31,250\nbiggest integer in something.\n\n140\n00:08:31,250 --> 00:08:32,600\nIt's a classic thing.\n\n141\n00:08:32,600 --> 00:08:34,350\nEvery FORTRAN programmer\nknows how to do that.\n\n142\n00:08:34,350 --> 00:08:36,059\nAnd if you don't know that,\nyou're in real hot water\n\n143\n00:08:36,059 --> 00:08:38,150\nbecause it takes a long\ntime to think it out.\n\n144\n00:08:38,150 --> 00:08:41,620\nHowever, one of the things you\ncan do in this language that\n\n145\n00:08:41,620 --> 00:08:43,900\nwe're showing you is not only\ndo you know something like\n\n146\n00:08:43,900 --> 00:08:48,380\nthat, but you give the knowledge\nof that a name.\n\n147\n00:08:48,380 --> 00:08:50,500\nAnd so that's what we're going\nto be going after right now.\n\n148\n00:08:50,500 --> 00:08:53,530\n\n\n149\n00:08:53,530 --> 00:08:55,860\nOK, well, let's see what these\nthings have in common.\n\n150\n00:08:55,860 --> 00:08:58,680\n\n\n151\n00:08:58,680 --> 00:09:02,560\nRight over here we have what\nappears to be a general\n\n152\n00:09:02,560 --> 00:09:06,470\npattern, a general pattern which\ncovers all of the cases\n\n153\n00:09:06,470 --> 00:09:09,700\nwe've seen so far.\n\n154\n00:09:09,700 --> 00:09:15,200\nThere is a sum procedure,\nwhich is being defined.\n\n155\n00:09:15,200 --> 00:09:17,680\nIt has two arguments, which\nare a lower bound\n\n156\n00:09:17,680 --> 00:09:19,630\nand an upper bound.\n\n157\n00:09:19,630 --> 00:09:23,150\nThe lower bound is tested to\nbe greater than the upper\n\n158\n00:09:23,150 --> 00:09:27,590\nbound, and if it is greater,\nthen the result is zero.\n\n159\n00:09:27,590 --> 00:09:31,640\nOtherwise, we're going to do\nsomething to the lower bound,\n\n160\n00:09:31,640 --> 00:09:35,540\nwhich is the index of the\nconversation, and add that\n\n161\n00:09:35,540 --> 00:09:40,150\nresult to the result of\nfollowing the procedure\n\n162\n00:09:40,150 --> 00:09:45,050\nrecursively on our lower bound\nincremented by some next\n\n163\n00:09:45,050 --> 00:09:49,605\noperation with the same upper\nbound as I had before.\n\n164\n00:09:49,605 --> 00:09:53,710\n\n\n165\n00:09:53,710 --> 00:09:59,230\nSo this is a general pattern,\nand what I'd like to do is be\n\n166\n00:09:59,230 --> 00:10:03,610\nable to name this general\npattern a bit.\n\n167\n00:10:03,610 --> 00:10:06,550\nWell, that's sort of easy,\nbecause one of the things I'm\n\n168\n00:10:06,550 --> 00:10:09,610\ngoing to do right now is--\nthere's nothing very special\n\n169\n00:10:09,610 --> 00:10:11,790\nabout numbers.\n\n170\n00:10:11,790 --> 00:10:14,790\nNumbers are just one\nkind of data.\n\n171\n00:10:14,790 --> 00:10:17,570\nIt seems to me perfectly\nreasonable to give all sorts\n\n172\n00:10:17,570 --> 00:10:23,260\nof names to all kinds of data,\nfor example, procedures.\n\n173\n00:10:23,260 --> 00:10:26,370\nAnd now many languages allow you\nhave procedural arguments,\n\n174\n00:10:26,370 --> 00:10:27,830\nand right now, we're\ngoing to talk\n\n175\n00:10:27,830 --> 00:10:29,120\nabout procedural arguments.\n\n176\n00:10:29,120 --> 00:10:31,280\nThey're very easy\nto deal with.\n\n177\n00:10:31,280 --> 00:10:33,300\nAnd shortly, we'll do some\nremarkable things that are not\n\n178\n00:10:33,300 --> 00:10:35,730\nlike procedural arguments.\n\n179\n00:10:35,730 --> 00:10:43,190\nSo here, we'll define\nour sigma notation.\n\n180\n00:10:43,190 --> 00:10:55,450\nThis is called sum and it takes\na term, an A, a next\n\n181\n00:10:55,450 --> 00:11:00,190\nterm, and B as arguments.\n\n182\n00:11:00,190 --> 00:11:03,420\nSo it takes four arguments,\nand there was nothing\n\n183\n00:11:03,420 --> 00:11:06,580\nparticularly special about me\nwriting this in lowercase.\n\n184\n00:11:06,580 --> 00:11:08,700\nI hope that it doesn't confuse\nyou, so I'll write it in\n\n185\n00:11:08,700 --> 00:11:09,930\nuppercase right now.\n\n186\n00:11:09,930 --> 00:11:11,180\nThe machine doesn't care.\n\n187\n00:11:11,180 --> 00:11:14,350\n\n\n188\n00:11:14,350 --> 00:11:17,180\nBut these two arguments\nare different.\n\n189\n00:11:17,180 --> 00:11:19,360\nThese are not numbers.\n\n190\n00:11:19,360 --> 00:11:21,600\nThese are going to be procedures\nfor computing\n\n191\n00:11:21,600 --> 00:11:23,690\nsomething given a number.\n\n192\n00:11:23,690 --> 00:11:26,590\nTerm will be a procedure which,\nwhen given an index,\n\n193\n00:11:26,590 --> 00:11:29,920\nwill produce the value of\nthe term for that index.\n\n194\n00:11:29,920 --> 00:11:31,660\nNext will be given an\nindex, which will\n\n195\n00:11:31,660 --> 00:11:34,050\nproduce the next index.\n\n196\n00:11:34,050 --> 00:11:36,000\nThis will be for counting.\n\n197\n00:11:36,000 --> 00:11:37,250\nAnd it's very simple.\n\n198\n00:11:37,250 --> 00:11:40,590\n\n\n199\n00:11:40,590 --> 00:11:43,400\nIt's exactly what you see.\n\n200\n00:11:43,400 --> 00:11:52,220\nIf A is greater than B,\nthen the result is 0.\n\n201\n00:11:52,220 --> 00:12:04,970\nOtherwise, it's the sum of term\napplied to A and the sum\n\n202\n00:12:04,970 --> 00:12:10,410\nof term, next index.\n\n203\n00:12:10,410 --> 00:12:14,990\n\n\n204\n00:12:14,990 --> 00:12:16,480\nLet me write it this way.\n\n205\n00:12:16,480 --> 00:12:29,370\n\n\n206\n00:12:29,370 --> 00:12:32,160\nNow, I'd like you to see\nsomething, first of all.\n\n207\n00:12:32,160 --> 00:12:35,210\nI was writing here, and\nI ran out of space.\n\n208\n00:12:35,210 --> 00:12:38,110\nWhat I did is I start indenting\naccording to the\n\n209\n00:12:38,110 --> 00:12:41,080\nPretty-printing rule, which says\nthat I align all of the\n\n210\n00:12:41,080 --> 00:12:44,340\narguments of the procedure\nso I can see\n\n211\n00:12:44,340 --> 00:12:47,060\nwhich ones go together.\n\n212\n00:12:47,060 --> 00:12:49,840\nAnd this is just something I do\nautomatically, and I want\n\n213\n00:12:49,840 --> 00:12:51,530\nyou to learn how to do that,\ntoo, so your programs can be\n\n214\n00:12:51,530 --> 00:12:52,780\nread and understood.\n\n215\n00:12:52,780 --> 00:12:54,750\n\n\n216\n00:12:54,750 --> 00:12:57,610\nHowever, what do we have here?\n\n217\n00:12:57,610 --> 00:13:01,730\nWe have four arguments: the\nprocedure, the lower index--\n\n218\n00:13:01,730 --> 00:13:03,670\nlower bound index--\n\n219\n00:13:03,670 --> 00:13:09,010\nthe way to get the next index,\nand the upper bound.\n\n220\n00:13:09,010 --> 00:13:13,890\nWhat's passed along on the\nrecursive call is indeed the\n\n221\n00:13:13,890 --> 00:13:18,110\nsame procedure because I'm going\nto need it again, the\n\n222\n00:13:18,110 --> 00:13:21,260\nnext index, which is using the\nnext procedure to compute it,\n\n223\n00:13:21,260 --> 00:13:23,332\nthe procedure for computing\nnext, which I also have to\n\n224\n00:13:23,332 --> 00:13:25,250\nhave separately, and\nthat's different.\n\n225\n00:13:25,250 --> 00:13:27,940\nThe procedure for computing\nnext is different from the\n\n226\n00:13:27,940 --> 00:13:30,680\nnext index, which is the result\nof using next on the\n\n227\n00:13:30,680 --> 00:13:32,510\nlast index.\n\n228\n00:13:32,510 --> 00:13:34,210\nAnd I also have to pass\nalong the upper bound.\n\n229\n00:13:34,210 --> 00:13:37,090\n\n\n230\n00:13:37,090 --> 00:13:44,850\nSo this captures both of these\nand the other nice program\n\n231\n00:13:44,850 --> 00:13:47,810\nthat we are playing with.\n\n232\n00:13:47,810 --> 00:13:52,740\nSo using this, we can write down\nthe original program as\n\n233\n00:13:52,740 --> 00:13:56,260\ninstances of sum very simply.\n\n234\n00:13:56,260 --> 00:14:08,880\n\n\n235\n00:14:08,880 --> 00:14:17,620\nA and B. Well, I'm going to\nneed an identity procedure\n\n236\n00:14:17,620 --> 00:14:29,440\nhere because ,ahh, the sum of\nthe integers requires me to in\n\n237\n00:14:29,440 --> 00:14:33,020\nthis case compute a term for\nevery integer, but the term\n\n238\n00:14:33,020 --> 00:14:35,560\nprocedure doesn't want to do\nanything to that integer.\n\n239\n00:14:35,560 --> 00:14:41,460\nSo the identity procedure on A\nis A or X or whatever, and I\n\n240\n00:14:41,460 --> 00:14:52,420\nwant to say the sum of using\nidentity of the term procedure\n\n241\n00:14:52,420 --> 00:14:58,400\nand using A as the initial\nindex and the incrementer\n\n242\n00:14:58,400 --> 00:15:05,552\nbeing the way to get the next\nindex and B being the high\n\n243\n00:15:05,552 --> 00:15:07,870\nbound, the upper bound.\n\n244\n00:15:07,870 --> 00:15:12,010\nThis procedure does exactly\nthe same as the sum of the\n\n245\n00:15:12,010 --> 00:15:14,140\nintegers over here, computes\nthe same answer.\n\n246\n00:15:14,140 --> 00:15:17,690\n\n\n247\n00:15:17,690 --> 00:15:21,520\nNow, one thing you should see,\nof course, is that there's\n\n248\n00:15:21,520 --> 00:15:25,220\nnothing very special over here\nabout what I used as the\n\n249\n00:15:25,220 --> 00:15:25,990\nformal parameter.\n\n250\n00:15:25,990 --> 00:15:27,230\nI could have, for example,\nwritten this\n\n251\n00:15:27,230 --> 00:15:29,690\nX. It doesn't matter.\n\n252\n00:15:29,690 --> 00:15:33,760\nI just wanted you to see that\nthis name does not conflict\n\n253\n00:15:33,760 --> 00:15:35,140\nwith this one at all.\n\n254\n00:15:35,140 --> 00:15:37,850\nIt's an internal name.\n\n255\n00:15:37,850 --> 00:15:40,500\nFor the second procedure here,\nthe sum of the squares, it's\n\n256\n00:15:40,500 --> 00:15:41,750\neven a little bit easier.\n\n257\n00:15:41,750 --> 00:15:53,760\n\n\n258\n00:15:53,760 --> 00:15:54,850\nAnd what do we have to do?\n\n259\n00:15:54,850 --> 00:16:02,560\nNothing more than add up the\nsquares, this is the procedure\n\n260\n00:16:02,560 --> 00:16:05,620\nthat each index will be given,\nwill be given each--\n\n261\n00:16:05,620 --> 00:16:06,780\nyes.\n\n262\n00:16:06,780 --> 00:16:10,410\nEach index will have this done\nto it to get the term.\n\n263\n00:16:10,410 --> 00:16:13,570\nThat's the thing that maps\nagainst term over here.\n\n264\n00:16:13,570 --> 00:16:18,810\nThen I have A as the lower\nbound, the incrementer as the\n\n265\n00:16:18,810 --> 00:16:21,520\nnext term method, and B\nas the upper bound.\n\n266\n00:16:21,520 --> 00:16:26,780\n\n\n267\n00:16:26,780 --> 00:16:29,030\nAnd finally, just for the thing\nthat we did about pi\n\n268\n00:16:29,030 --> 00:16:33,270\nsums, pi sums are sort of--\n\n269\n00:16:33,270 --> 00:16:35,840\nwell, it's even easier to think\nabout them this way\n\n270\n00:16:35,840 --> 00:16:36,610\nbecause I don't have to think.\n\n271\n00:16:36,610 --> 00:16:41,110\nWhat I'm doing is separating the\nthing I'm adding up from\n\n272\n00:16:41,110 --> 00:16:43,340\nthe method of doing\nthe addition.\n\n273\n00:16:43,340 --> 00:16:57,200\nAnd so we have here, for\nexample, pi sum A B\n\n274\n00:16:57,200 --> 00:16:59,890\nof the sum of things.\n\n275\n00:16:59,890 --> 00:17:03,350\nI'm going to write the terms\nprocedure here explicitly\n\n276\n00:17:03,350 --> 00:17:05,670\nwithout giving it a name.\n\n277\n00:17:05,670 --> 00:17:07,119\nThis is done anonymously.\n\n278\n00:17:07,119 --> 00:17:10,960\nI don't necessarily have to give\na name to something if I\n\n279\n00:17:10,960 --> 00:17:12,310\njust want to use it once.\n\n280\n00:17:12,310 --> 00:17:18,050\nAnd, of course, I can write\nsort of a expression that\n\n281\n00:17:18,050 --> 00:17:19,579\nproduces a procedure.\n\n282\n00:17:19,579 --> 00:17:22,740\nI'm going to write the Greek\nlambda letter here instead of\n\n283\n00:17:22,740 --> 00:17:26,220\nL-A-M-B-D-A in general to avoid\ntaking up a lot of space\n\n284\n00:17:26,220 --> 00:17:27,240\non blackboards.\n\n285\n00:17:27,240 --> 00:17:28,270\nBut unfortunately,\nwe don't have\n\n286\n00:17:28,270 --> 00:17:29,960\nlambda keys on our keyboards.\n\n287\n00:17:29,960 --> 00:17:32,170\nMaybe we can convince our\nfriends in the computer\n\n288\n00:17:32,170 --> 00:17:34,040\nindustry that this\nis an important.\n\n289\n00:17:34,040 --> 00:17:43,480\nLambda of i is the quotient of 1\nand the product of i and the\n\n290\n00:17:43,480 --> 00:17:58,020\nsum of i 2, starting at a with\nthe way of incrementing being\n\n291\n00:17:58,020 --> 00:18:08,666\nthat procedure of an index i,\nwhich adds i to 4, and b being\n\n292\n00:18:08,666 --> 00:18:09,916\nthe upper bound.\n\n293\n00:18:09,916 --> 00:18:12,270\n\n\n294\n00:18:12,270 --> 00:18:17,490\nSo you can see that this\nnotation, the invention of the\n\n295\n00:18:17,490 --> 00:18:21,370\nprocedure that takes a\nprocedural argument, allows us\n\n296\n00:18:21,370 --> 00:18:26,066\nto compress a lot of these\nprocedures into one thing.\n\n297\n00:18:26,066 --> 00:18:32,780\nThis procedure, sums, covers\na whole bunch of ideas.\n\n298\n00:18:32,780 --> 00:18:34,740\nNow, just why is\nthis important?\n\n299\n00:18:34,740 --> 00:18:37,370\nI tried to say before that it\nhelps us divide a problem into\n\n300\n00:18:37,370 --> 00:18:42,760\ntwo pieces, and indeed, it does,\nfor example, if someone\n\n301\n00:18:42,760 --> 00:18:46,570\ncame up with a different way of\nimplementing this, which,\n\n302\n00:18:46,570 --> 00:18:50,010\nof course, one might.\n\n303\n00:18:50,010 --> 00:18:51,230\nHere, for example, an iterative\n\n304\n00:18:51,230 --> 00:18:52,480\nimplementation of sum.\n\n305\n00:18:52,480 --> 00:18:55,900\n\n\n306\n00:18:55,900 --> 00:18:59,470\nIterative implementation for\nsome reason might be better\n\n307\n00:18:59,470 --> 00:19:00,840\nthan the recursive\nimplementation.\n\n308\n00:19:00,840 --> 00:19:03,670\n\n\n309\n00:19:03,670 --> 00:19:06,460\nBut the important thing is\nthat it's different.\n\n310\n00:19:06,460 --> 00:19:09,460\nNow, supposing I had written my\nprogram this way that you\n\n311\n00:19:09,460 --> 00:19:14,310\nsee on the blackboard\non the left.\n\n312\n00:19:14,310 --> 00:19:17,810\nThat's correct, the left.\n\n313\n00:19:17,810 --> 00:19:22,280\nWell, then if I want to change\nthe method of addition, then\n\n314\n00:19:22,280 --> 00:19:25,200\nI'd have to change\neach of these.\n\n315\n00:19:25,200 --> 00:19:30,210\nWhereas if I write them like\nthis that you see here, then\n\n316\n00:19:30,210 --> 00:19:32,430\nthe method by which I did the\naddition is encapsulated in\n\n317\n00:19:32,430 --> 00:19:34,850\nthe procedure sum.\n\n318\n00:19:34,850 --> 00:19:37,780\nThat decomposition allows me\nto independently change one\n\n319\n00:19:37,780 --> 00:19:43,210\npart of the program and prove\nit perhaps without changing\n\n320\n00:19:43,210 --> 00:19:45,052\nthe other part that was\nwritten for some\n\n321\n00:19:45,052 --> 00:19:46,630\nof the other cases.\n\n322\n00:19:46,630 --> 00:19:50,366\n\n\n323\n00:19:50,366 --> 00:19:51,010\nThank you.\n\n324\n00:19:51,010 --> 00:19:52,420\nAre there any questions?\n\n325\n00:19:52,420 --> 00:19:53,190\nYes, sir.\n\n326\n00:19:53,190 --> 00:19:55,150\nAUDIENCE: Would you go over\nnext A and next again on--\n\n327\n00:19:55,150 --> 00:19:55,640\nPROFESSOR: Yes.\n\n328\n00:19:55,640 --> 00:19:56,680\nIt's the same problem.\n\n329\n00:19:56,680 --> 00:19:57,900\nI'm sure you're going to--\n\n330\n00:19:57,900 --> 00:19:59,160\nyou're going to have\nto work on this.\n\n331\n00:19:59,160 --> 00:20:01,280\nThis is hard the first\ntime you've ever seen\n\n332\n00:20:01,280 --> 00:20:02,460\nsomething like this.\n\n333\n00:20:02,460 --> 00:20:06,300\nWhat I have here is\na-- procedures\n\n334\n00:20:06,300 --> 00:20:07,550\ncan be named by variables.\n\n335\n00:20:07,550 --> 00:20:10,020\n\n\n336\n00:20:10,020 --> 00:20:12,710\nProcedures are not special.\n\n337\n00:20:12,710 --> 00:20:15,230\nActually, sum square is a\nvariable, which has gotten a\n\n338\n00:20:15,230 --> 00:20:18,640\nvalue, which is a procedure.\n\n339\n00:20:18,640 --> 00:20:20,030\nThis is define sum square to be\n\n340\n00:20:20,030 --> 00:20:23,310\nlambda of A and B something.\n\n341\n00:20:23,310 --> 00:20:24,700\nSo the procedure can be named.\n\n342\n00:20:24,700 --> 00:20:27,900\nTherefore, they can be passed\nfrom one to another, one\n\n343\n00:20:27,900 --> 00:20:31,430\nprocedure to another,\nas arguments.\n\n344\n00:20:31,430 --> 00:20:33,630\nWell, what we're doing here is\nwe're passing the procedure\n\n345\n00:20:33,630 --> 00:20:38,190\nterm as an argument to sum just\nwhen we get it around in\n\n346\n00:20:38,190 --> 00:20:41,060\nthe next recursive.\n\n347\n00:20:41,060 --> 00:20:45,350\nHere, we're passing\nthe procedure next\n\n348\n00:20:45,350 --> 00:20:47,630\nas an argument also.\n\n349\n00:20:47,630 --> 00:20:50,120\nHowever, here we're using\nthe procedure next.\n\n350\n00:20:50,120 --> 00:20:51,690\nThat's what the parentheses\nmean.\n\n351\n00:20:51,690 --> 00:20:56,750\nWe're applying next to A to get\nthe next value of A. If\n\n352\n00:20:56,750 --> 00:20:59,390\nyou look at what next is mapped\nagainst, remember that\n\n353\n00:20:59,390 --> 00:21:02,390\nthe way you think about this\nis that you substitute the\n\n354\n00:21:02,390 --> 00:21:06,800\narguments for the formal\nparameters in the body.\n\n355\n00:21:06,800 --> 00:21:10,590\nIf you're ever confused, think\nof the thing that way.\n\n356\n00:21:10,590 --> 00:21:14,730\nWell, over here, with\nsum of the integers.\n\n357\n00:21:14,730 --> 00:21:21,150\nI substitute identity for\na term and 1 plus the\n\n358\n00:21:21,150 --> 00:21:26,070\nincrementer for next\nin the body.\n\n359\n00:21:26,070 --> 00:21:30,600\nWell, the identity procedure\non A is what I get here.\n\n360\n00:21:30,600 --> 00:21:35,170\nIdentity is being passed\nalong, and here, I have\n\n361\n00:21:35,170 --> 00:21:41,040\nincrement 1 plus being applied\nto A and 1 plus is being\n\n362\n00:21:41,040 --> 00:21:42,980\npassed along.\n\n363\n00:21:42,980 --> 00:21:46,340\nDoes that clarify\nthe situation?\n\n364\n00:21:46,340 --> 00:21:49,355\nAUDIENCE: We could also define\nexplicitly those two\n\n365\n00:21:49,355 --> 00:21:51,300\nfunctions, then pass them.\n\n366\n00:21:51,300 --> 00:21:52,360\nPROFESSOR: Sure.\n\n367\n00:21:52,360 --> 00:21:54,950\nWhat we can do is we could have\ngiven names to them, just\n\n368\n00:21:54,950 --> 00:21:55,770\nlike I did here.\n\n369\n00:21:55,770 --> 00:21:57,530\nIn fact, I gave you various\nways so you\n\n370\n00:21:57,530 --> 00:21:59,390\ncould see it, a variety.\n\n371\n00:21:59,390 --> 00:22:05,130\nHere, I define the thing which\nI passed the name of.\n\n372\n00:22:05,130 --> 00:22:07,850\nI referenced it by its name.\n\n373\n00:22:07,850 --> 00:22:10,400\nBut the thing is, in fact, that\nprocedure, one argument\n\n374\n00:22:10,400 --> 00:22:14,300\nX, which is X. And the identity\nprocedure is just\n\n375\n00:22:14,300 --> 00:22:20,870\nlambda of X X. And that's\nwhat you're seeing here.\n\n376\n00:22:20,870 --> 00:22:26,190\nHere, I happened to just write\nits canonical name there for\n\n377\n00:22:26,190 --> 00:22:27,440\nyou to see.\n\n378\n00:22:27,440 --> 00:22:31,730\n\n\n379\n00:22:31,730 --> 00:22:33,020\nIs it OK if we take our\nfive-minute break?\n\n380\n00:22:33,020 --> 00:23:15,850\n\n\n381\n00:23:15,850 --> 00:23:19,780\nAs I said, computers to make\npeople happy, not people to\n\n382\n00:23:19,780 --> 00:23:21,070\nmake computers happy.\n\n383\n00:23:21,070 --> 00:23:23,080\nAnd for the most part, the\nreason why we introduce all\n\n384\n00:23:23,080 --> 00:23:26,440\nthis abstraction stuff is to\nmake it so that programs can\n\n385\n00:23:26,440 --> 00:23:29,940\nbe more easily written\nand more easily read.\n\n386\n00:23:29,940 --> 00:23:32,930\nLet's try to understand what's\nthe most complicated program\n\n387\n00:23:32,930 --> 00:23:36,280\nwe've seen so far using\na little bit of\n\n388\n00:23:36,280 --> 00:23:38,120\nthis abstraction stuff.\n\n389\n00:23:38,120 --> 00:23:44,560\nIf you look at the slide, this\nis the Heron of Alexandria's\n\n390\n00:23:44,560 --> 00:23:51,590\nmethod of computing square roots\nthat we saw yesterday.\n\n391\n00:23:51,590 --> 00:23:56,460\nAnd let's see.\n\n392\n00:23:56,460 --> 00:24:00,780\nWell, in any case, this\nprogram is a little\n\n393\n00:24:00,780 --> 00:24:01,805\ncomplicated.\n\n394\n00:24:01,805 --> 00:24:04,800\nAnd at the current state of your\nthinking, you just can't\n\n395\n00:24:04,800 --> 00:24:07,320\nlook at that and say, oh,\nthis obviously means\n\n396\n00:24:07,320 --> 00:24:10,380\nsomething very clear.\n\n397\n00:24:10,380 --> 00:24:12,930\nIt's not obvious from\nlooking at the\n\n398\n00:24:12,930 --> 00:24:17,060\nprogram what it's computing.\n\n399\n00:24:17,060 --> 00:24:21,890\nThere's some loop here inside\ntry, and a loop does something\n\n400\n00:24:21,890 --> 00:24:26,030\nabout trying the improvement\nof y.\n\n401\n00:24:26,030 --> 00:24:30,170\nThere's something called\nimprove, which does some\n\n402\n00:24:30,170 --> 00:24:33,270\naveraging and quotienting\nand things like that.\n\n403\n00:24:33,270 --> 00:24:34,840\nBut what's the real idea?\n\n404\n00:24:34,840 --> 00:24:38,930\nCan we make it clear\nwhat the idea is?\n\n405\n00:24:38,930 --> 00:24:41,610\nWell, I think we can.\n\n406\n00:24:41,610 --> 00:24:45,070\nI think we can use abstraction\nthat we have learned about so\n\n407\n00:24:45,070 --> 00:24:48,990\nfar to clarify what's\ngoing on.\n\n408\n00:24:48,990 --> 00:24:54,720\nNow, what we have mathematically\nis a procedure\n\n409\n00:24:54,720 --> 00:24:58,411\nfor improving a guess\nfor square roots.\n\n410\n00:24:58,411 --> 00:25:02,610\nAnd if y is a guess for a square\nroot, then what we want\n\n411\n00:25:02,610 --> 00:25:04,570\nto get we'll call\na function f.\n\n412\n00:25:04,570 --> 00:25:07,660\nThis is the means\nof improvement.\n\n413\n00:25:07,660 --> 00:25:17,510\nI want to get y plus x/y over\n2, so the average of y and x\n\n414\n00:25:17,510 --> 00:25:24,080\ndivided by y as the improved\nvalue for the square root of x\n\n415\n00:25:24,080 --> 00:25:27,920\nsuch that-- one thing you can\nnotice about this function f\n\n416\n00:25:27,920 --> 00:25:36,310\nis that f of the square root\nof f is in fact the\n\n417\n00:25:36,310 --> 00:25:38,460\nsquare root of x.\n\n418\n00:25:38,460 --> 00:25:41,670\nIn other words, if I take\nthe square root of x and\n\n419\n00:25:41,670 --> 00:25:44,930\nsubstitute it for y here, I see\nthe square root of x plus\n\n420\n00:25:44,930 --> 00:25:47,560\nx divided by the square of x,\nwhich is the square root of x.\n\n421\n00:25:47,560 --> 00:25:49,890\nThat's 2 times the square root\nof x divided by 2, is the\n\n422\n00:25:49,890 --> 00:25:51,640\nsquare root of x.\n\n423\n00:25:51,640 --> 00:25:55,630\nSo, in fact, what we're really\nlooking for is we're looking\n\n424\n00:25:55,630 --> 00:26:12,850\nfor a fixed point, a fixed\npoint of the function f.\n\n425\n00:26:12,850 --> 00:26:17,570\n\n\n426\n00:26:17,570 --> 00:26:22,650\nA fixed point is a place which\nhas the property that if you\n\n427\n00:26:22,650 --> 00:26:24,850\nput it into the function, you\nget the same value out.\n\n428\n00:26:24,850 --> 00:26:27,620\n\n\n429\n00:26:27,620 --> 00:26:29,700\nNow, I suppose if I were giving\nsome nice, boring\n\n430\n00:26:29,700 --> 00:26:34,480\nlecture, and you happened to\nhave in front of you an HP-35\n\n431\n00:26:34,480 --> 00:26:36,380\ndesk calculator like I\nused to have when I\n\n432\n00:26:36,380 --> 00:26:38,170\nwent to boring lectures.\n\n433\n00:26:38,170 --> 00:26:41,120\nAnd if you think it was really\nboring, you put it into\n\n434\n00:26:41,120 --> 00:26:44,720\nradians mode, and you hit\ncosine, and you hit cosine,\n\n435\n00:26:44,720 --> 00:26:45,780\nand you hit cosine.\n\n436\n00:26:45,780 --> 00:26:48,770\nAnd eventually, you end\nup with 0.734 or\n\n437\n00:26:48,770 --> 00:26:50,090\nsomething like that.\n\n438\n00:26:50,090 --> 00:26:53,250\n0.743, I don't remember what\nexactly, and it gets closer\n\n439\n00:26:53,250 --> 00:26:54,810\nand closer to that.\n\n440\n00:26:54,810 --> 00:26:57,980\nSome functions have the property\nthat you can find\n\n441\n00:26:57,980 --> 00:27:03,420\ntheir fixed point by iterating\nthe function, and that's\n\n442\n00:27:03,420 --> 00:27:07,170\nessentially what's happening in\nthe square root program by\n\n443\n00:27:07,170 --> 00:27:08,420\nHeron's method.\n\n444\n00:27:08,420 --> 00:27:11,550\n\n\n445\n00:27:11,550 --> 00:27:14,732\nSo let's see if we can write\nthat down, that idea.\n\n446\n00:27:14,732 --> 00:27:17,670\nNow, I'm not going to say how\nI compute fixed points yet.\n\n447\n00:27:17,670 --> 00:27:19,240\nThere might be more\nthan one way.\n\n448\n00:27:19,240 --> 00:27:22,750\nBut the first thing to\ndo is I'm going to\n\n449\n00:27:22,750 --> 00:27:24,310\nsay what I just said.\n\n450\n00:27:24,310 --> 00:27:27,460\nI'm going to say it\nspecifically, the square root.\n\n451\n00:27:27,460 --> 00:27:32,440\n\n\n452\n00:27:32,440 --> 00:27:48,210\nThe square root of x is the\nfixed point of that procedure\n\n453\n00:27:48,210 --> 00:27:59,180\nwhich takes an argument\ny and averages of x\n\n454\n00:27:59,180 --> 00:28:02,330\ndivided by y with y.\n\n455\n00:28:02,330 --> 00:28:05,620\n\n\n456\n00:28:05,620 --> 00:28:08,120\nAnd we're going to start up with\nthe initial guess for the\n\n457\n00:28:08,120 --> 00:28:09,630\nfixed point of 1.\n\n458\n00:28:09,630 --> 00:28:11,860\nIt doesn't matter\nwhere it starts.\n\n459\n00:28:11,860 --> 00:28:13,940\nA theorem having to do\nwith square roots.\n\n460\n00:28:13,940 --> 00:28:18,610\n\n\n461\n00:28:18,610 --> 00:28:21,410\nSo what you're seeing here is\nI'm just trying to write out\n\n462\n00:28:21,410 --> 00:28:22,560\nby wishful thinking.\n\n463\n00:28:22,560 --> 00:28:24,380\nI don't know how I'm going to\nmake fixed point happen.\n\n464\n00:28:24,380 --> 00:28:26,290\nWe'll worry about that later.\n\n465\n00:28:26,290 --> 00:28:29,570\nBut if somehow I had a way of\nfinding the fixed point of the\n\n466\n00:28:29,570 --> 00:28:33,590\nfunction computed by this\nprocedure, then I would have--\n\n467\n00:28:33,590 --> 00:28:36,120\nthat would be the square root\nthat I'm looking for.\n\n468\n00:28:36,120 --> 00:28:39,770\n\n\n469\n00:28:39,770 --> 00:28:41,500\nOK, well, now let's see how\nwe're going to write--\n\n470\n00:28:41,500 --> 00:28:43,470\nhow we're going to come\nup with fixed points.\n\n471\n00:28:43,470 --> 00:28:44,890\nWell, it's very simple,\nactually.\n\n472\n00:28:44,890 --> 00:28:47,180\nI'm going to write an\nabbreviated version here just\n\n473\n00:28:47,180 --> 00:28:48,430\nso we understand it.\n\n474\n00:28:48,430 --> 00:29:00,450\n\n\n475\n00:29:00,450 --> 00:29:03,310\nI'm going to find the fixed\npoint of a function f--\n\n476\n00:29:03,310 --> 00:29:06,140\nactually, the fixed point of the\nfunction computed by the\n\n477\n00:29:06,140 --> 00:29:09,990\nprocedure whose name will\nbe f in this procedure.\n\n478\n00:29:09,990 --> 00:29:11,025\nHow's that?\n\n479\n00:29:11,025 --> 00:29:13,230\nA long sentence--\n\n480\n00:29:13,230 --> 00:29:14,820\nstarting with a particular\nstarting value.\n\n481\n00:29:14,820 --> 00:29:19,920\n\n\n482\n00:29:19,920 --> 00:29:22,660\nWell, I'm going to have a little\nloop inside here, which\n\n483\n00:29:22,660 --> 00:29:25,800\nis going to push the button on\nthe calculator repeatedly,\n\n484\n00:29:25,800 --> 00:29:28,940\nhoping that it will eventually\nconverge.\n\n485\n00:29:28,940 --> 00:29:35,290\nAnd we will say here internal\nloops are written by defining\n\n486\n00:29:35,290 --> 00:29:36,540\ninternal procedures.\n\n487\n00:29:36,540 --> 00:29:39,340\n\n\n488\n00:29:39,340 --> 00:29:41,860\nWell, one thing I'm going to\nhave to do is I'm going to\n\n489\n00:29:41,860 --> 00:29:43,690\nhave to say whether I'm done.\n\n490\n00:29:43,690 --> 00:29:45,410\nAnd the way I'm going to decide\nwhen I'm done is when\n\n491\n00:29:45,410 --> 00:29:47,760\nthe old value and the new value\nare close enough so I\n\n492\n00:29:47,760 --> 00:29:50,820\ncan't distinguish\nthem anymore.\n\n493\n00:29:50,820 --> 00:29:53,510\nThat's the standard thing you\ndo on the calculator unless\n\n494\n00:29:53,510 --> 00:29:54,970\nyou look at more precision,\nand eventually,\n\n495\n00:29:54,970 --> 00:29:57,820\nyou run out of precision.\n\n496\n00:29:57,820 --> 00:30:06,530\nSo the old value and new value,\nand I'm going to stay\n\n497\n00:30:06,530 --> 00:30:14,758\nhere if I can't distinguish them\nif they're close enough,\n\n498\n00:30:14,758 --> 00:30:16,830\nand we'll have to worry about\nwhat that is soon.\n\n499\n00:30:16,830 --> 00:30:20,780\n\n\n500\n00:30:20,780 --> 00:30:22,580\nThe old value and the new value\nare close enough to each\n\n501\n00:30:22,580 --> 00:30:25,880\nother and let's pick the new\nvalue as the answer.\n\n502\n00:30:25,880 --> 00:30:33,520\nOtherwise, I'm going to iterate\naround again with the\n\n503\n00:30:33,520 --> 00:30:39,020\nnext value of old being the\ncurrent value of new and the\n\n504\n00:30:39,020 --> 00:30:43,160\nnext value of new being the\nresult of calling f on new.\n\n505\n00:30:43,160 --> 00:30:54,810\n\n\n506\n00:30:54,810 --> 00:30:57,680\nAnd so this is my iteration loop\nthat pushes the button on\n\n507\n00:30:57,680 --> 00:30:58,600\nthe calculator.\n\n508\n00:30:58,600 --> 00:31:00,760\nI basically think of it as\nhaving two registers on the\n\n509\n00:31:00,760 --> 00:31:02,495\ncalculator: old and new.\n\n510\n00:31:02,495 --> 00:31:09,070\nAnd in each step, new becomes\nold, and new gets F of new.\n\n511\n00:31:09,070 --> 00:31:13,080\nSo this is the thing where I'm\ngetting the next value.\n\n512\n00:31:13,080 --> 00:31:20,970\nAnd now, I'm going to\nstart this thing up\n\n513\n00:31:20,970 --> 00:31:22,220\nby giving two values.\n\n514\n00:31:22,220 --> 00:31:28,470\n\n\n515\n00:31:28,470 --> 00:31:30,570\nI wrote down on the blackboard\nto be slow\n\n516\n00:31:30,570 --> 00:31:31,640\nso you can see this.\n\n517\n00:31:31,640 --> 00:31:34,650\nThis is the first time you've\nseen something quite this\n\n518\n00:31:34,650 --> 00:31:37,700\ncomplicated, I think.\n\n519\n00:31:37,700 --> 00:31:44,710\nHowever, we might want to see\nthe whole thing over here in\n\n520\n00:31:44,710 --> 00:31:50,720\nthis transparency or\nslide or whatever.\n\n521\n00:31:50,720 --> 00:31:57,200\nWhat we have is all of the\ndetails that are required to\n\n522\n00:31:57,200 --> 00:31:58,500\nmake this thing work.\n\n523\n00:31:58,500 --> 00:32:01,660\nI have a way of getting a\ntolerance for a close enough\n\n524\n00:32:01,660 --> 00:32:03,080\nprocedure, which we see here.\n\n525\n00:32:03,080 --> 00:32:06,030\nThe close enough procedure, it\ntests whether u and v are\n\n526\n00:32:06,030 --> 00:32:09,170\nclose enough by seeing if the\nabsolute value of the\n\n527\n00:32:09,170 --> 00:32:12,460\ndifference in u and v is less\nthan the given tolerance, OK?\n\n528\n00:32:12,460 --> 00:32:14,440\nAnd here is the iteration loop\nthat I just wrote on the\n\n529\n00:32:14,440 --> 00:32:17,930\nblackboard and the\ninitialization for it, which\n\n530\n00:32:17,930 --> 00:32:19,180\nis right there.\n\n531\n00:32:19,180 --> 00:32:21,680\n\n\n532\n00:32:21,680 --> 00:32:22,930\nIt's very simple.\n\n533\n00:32:22,930 --> 00:32:34,210\n\n\n534\n00:32:34,210 --> 00:32:34,880\nBut let's see.\n\n535\n00:32:34,880 --> 00:32:36,630\nI haven't told you enough.\n\n536\n00:32:36,630 --> 00:32:39,500\nIt's actually easier\nthan this.\n\n537\n00:32:39,500 --> 00:32:42,120\nThere is more structure to\nthis problem than I've\n\n538\n00:32:42,120 --> 00:32:43,310\nalready told you.\n\n539\n00:32:43,310 --> 00:32:45,700\nLike why should this work?\n\n540\n00:32:45,700 --> 00:32:48,070\nWhy should it converge?\n\n541\n00:32:48,070 --> 00:32:50,930\nThere's a hairy theorem in\nmathematics tied up in what\n\n542\n00:32:50,930 --> 00:32:52,760\nI've written here.\n\n543\n00:32:52,760 --> 00:32:55,890\nWhy is it that I should assume\nthat by iterating averaging\n\n544\n00:32:55,890 --> 00:32:57,780\nthe quotient of x and y\nand y that I should\n\n545\n00:32:57,780 --> 00:33:00,110\nget the right answer?\n\n546\n00:33:00,110 --> 00:33:01,360\nIt isn't so obvious.\n\n547\n00:33:01,360 --> 00:33:03,710\n\n\n548\n00:33:03,710 --> 00:33:07,280\nSurely there are other things,\nother procedures, which\n\n549\n00:33:07,280 --> 00:33:09,870\ncompute functions whose fixed\npoints would also be the\n\n550\n00:33:09,870 --> 00:33:12,040\nsquare root.\n\n551\n00:33:12,040 --> 00:33:20,480\nFor example, the obvious one\nwill be a new function g,\n\n552\n00:33:20,480 --> 00:33:25,330\nwhich maps y to x/y.\n\n553\n00:33:25,330 --> 00:33:27,950\n\n\n554\n00:33:27,950 --> 00:33:30,870\nThat's even simpler.\n\n555\n00:33:30,870 --> 00:33:34,540\nThe fixed point of g is surely\nthe square root also, and it's\n\n556\n00:33:34,540 --> 00:33:37,400\na simpler procedure.\n\n557\n00:33:37,400 --> 00:33:39,020\nWhy am I not using it?\n\n558\n00:33:39,020 --> 00:33:40,470\nWell, I suppose you know.\n\n559\n00:33:40,470 --> 00:33:44,970\nSupposing x is 2 and I start out\nwith 1, and if I divide 1\n\n560\n00:33:44,970 --> 00:33:47,700\ninto 2, I get 2.\n\n561\n00:33:47,700 --> 00:33:49,610\nAnd then if I divide\n2 into 2, I get 1.\n\n562\n00:33:49,610 --> 00:33:52,740\nIf I divide 1 into 2, I get 2,\nand 2 into 2, I get 1, and I\n\n563\n00:33:52,740 --> 00:33:55,480\nnever get any closer\nto the square root.\n\n564\n00:33:55,480 --> 00:33:56,730\nIt just oscillates.\n\n565\n00:33:56,730 --> 00:33:59,080\n\n\n566\n00:33:59,080 --> 00:34:03,110\nSo what we have is a signal\nprocessing system, an\n\n567\n00:34:03,110 --> 00:34:06,230\nelectrical circuit which is\noscillating, and I want to\n\n568\n00:34:06,230 --> 00:34:07,480\ndamp out these oscillations.\n\n569\n00:34:07,480 --> 00:34:10,530\n\n\n570\n00:34:10,530 --> 00:34:11,840\nWell, I can do that.\n\n571\n00:34:11,840 --> 00:34:14,190\nSee, what I'm really doing\nhere when I'm taking my\n\n572\n00:34:14,190 --> 00:34:17,290\naverage, the average is\naveraging the last two values\n\n573\n00:34:17,290 --> 00:34:21,350\nof something which oscillates,\ngetting something in between.\n\n574\n00:34:21,350 --> 00:34:24,480\nThe classic way is damping out\noscillations in a signal\n\n575\n00:34:24,480 --> 00:34:25,730\nprocessing system.\n\n576\n00:34:25,730 --> 00:34:28,460\n\n\n577\n00:34:28,460 --> 00:34:31,719\nSo why don't we write down the\nstrategy that I just said in a\n\n578\n00:34:31,719 --> 00:34:33,872\nmore clear way?\n\n579\n00:34:33,872 --> 00:34:35,520\nWell, that's easy enough.\n\n580\n00:34:35,520 --> 00:34:38,639\n\n\n581\n00:34:38,639 --> 00:34:53,790\nI'm going to define the square\nroot of x to be a fixed point\n\n582\n00:34:53,790 --> 00:34:58,510\nof the procedure resulting\nfrom average damping.\n\n583\n00:34:58,510 --> 00:35:10,780\nSo I have a procedure resulting\nfrom average damp of\n\n584\n00:35:10,780 --> 00:35:24,820\nthe procedure, that procedure\nof y, which divides x by y\n\n585\n00:35:24,820 --> 00:35:26,070\nstarting out at 1.\n\n586\n00:35:26,070 --> 00:35:29,840\n\n\n587\n00:35:29,840 --> 00:35:33,520\nAh, but average damp is a\nspecial procedure that's going\n\n588\n00:35:33,520 --> 00:35:35,720\nto take a procedure as its\nargument and return a\n\n589\n00:35:35,720 --> 00:35:38,080\nprocedure as its value.\n\n590\n00:35:38,080 --> 00:35:42,090\nIt's a generalization that says\ngiven a procedure, it's\n\n591\n00:35:42,090 --> 00:35:45,090\nthe thing which produces a\nprocedure which averages the\n\n592\n00:35:45,090 --> 00:35:47,980\nlast value and the\nvalue before and\n\n593\n00:35:47,980 --> 00:35:51,320\nafter running the procedure.\n\n594\n00:35:51,320 --> 00:35:53,260\nYou can use it for anything\nif you want to damp out\n\n595\n00:35:53,260 --> 00:35:54,880\noscillations.\n\n596\n00:35:54,880 --> 00:35:56,495\nSo let's write that down.\n\n597\n00:35:56,495 --> 00:35:57,745\nIt's very easy.\n\n598\n00:35:57,745 --> 00:36:00,624\n\n\n599\n00:36:00,624 --> 00:36:04,590\nAnd stylistically here, I'm\ngoing to use lambda notation\n\n600\n00:36:04,590 --> 00:36:06,950\nbecause it's much easier to\nthink when you're dealing with\n\n601\n00:36:06,950 --> 00:36:08,845\nprocedure, the mid-line\nprocedures, to understand that\n\n602\n00:36:08,845 --> 00:36:11,552\nthe procedures are the objects\nI'm dealing with, so I'm going\n\n603\n00:36:11,552 --> 00:36:13,830\nto use lambda notation here.\n\n604\n00:36:13,830 --> 00:36:14,490\nNot always.\n\n605\n00:36:14,490 --> 00:36:18,110\nI don't always use it, but\nvery specifically here to\n\n606\n00:36:18,110 --> 00:36:22,040\nexpand on that idea,\nto elucidate it.\n\n607\n00:36:22,040 --> 00:36:28,590\n\n\n608\n00:36:28,590 --> 00:36:33,810\nWell, average damp is a\nprocedure, which takes a\n\n609\n00:36:33,810 --> 00:36:37,560\nprocedure as its argument,\nwhich we will call f.\n\n610\n00:36:37,560 --> 00:36:38,710\nAnd what does it produce?\n\n611\n00:36:38,710 --> 00:36:40,340\nIt produces as its value--\n\n612\n00:36:40,340 --> 00:36:43,890\nthe body of this procedure is\na thing which produces a\n\n613\n00:36:43,890 --> 00:36:47,260\nprocedure, the construct of the\nprocedures right here, of\n\n614\n00:36:47,260 --> 00:37:00,440\none argument x, which averages\nf of x with x.\n\n615\n00:37:00,440 --> 00:37:10,420\n\n\n616\n00:37:10,420 --> 00:37:14,070\nThis is a very special thing.\n\n617\n00:37:14,070 --> 00:37:17,730\nI think for the first time\nyou're seeing a procedure\n\n618\n00:37:17,730 --> 00:37:21,730\nwhich produces a procedure\nas its value.\n\n619\n00:37:21,730 --> 00:37:25,690\nThis procedure takes the\nprocedure f and does something\n\n620\n00:37:25,690 --> 00:37:29,360\nto it to produce a new procedure\nof one argument x,\n\n621\n00:37:29,360 --> 00:37:31,050\nwhich averages f--\n\n622\n00:37:31,050 --> 00:37:31,950\nthis f--\n\n623\n00:37:31,950 --> 00:37:36,040\napplied to x and x itself.\n\n624\n00:37:36,040 --> 00:37:40,280\nUsing the context here, I apply\naverage damping to the\n\n625\n00:37:40,280 --> 00:37:44,670\nprocedure, which just\ndivides x by y.\n\n626\n00:37:44,670 --> 00:37:45,920\nIt's a division.\n\n627\n00:37:45,920 --> 00:37:48,122\n\n\n628\n00:37:48,122 --> 00:37:51,980\nAnd I'm finding to fixed point\nof that, and that's a clearer\n\n629\n00:37:51,980 --> 00:37:54,460\nway of writing down what\nI wrote down over\n\n630\n00:37:54,460 --> 00:37:57,796\nhere, wherever it was.\n\n631\n00:37:57,796 --> 00:38:01,110\nHere, because it tells why\nI am writing this down.\n\n632\n00:38:01,110 --> 00:38:07,910\n\n\n633\n00:38:07,910 --> 00:38:11,110\nI suppose this to some extent\nreally clarifies what Heron of\n\n634\n00:38:11,110 --> 00:38:14,260\nAlexandria was up to.\n\n635\n00:38:14,260 --> 00:38:15,130\nI suppose I'll stop now.\n\n636\n00:38:15,130 --> 00:38:16,380\nAre there any questions?\n\n637\n00:38:16,380 --> 00:38:18,190\n\n\n638\n00:38:18,190 --> 00:38:21,282\nAUDIENCE: So when you define\naverage damp, don't you need\n\n639\n00:38:21,282 --> 00:38:25,210\nto have a variable on f?\n\n640\n00:38:25,210 --> 00:38:28,150\nPROFESSOR: Ah, the question was,\nand here we're having--\n\n641\n00:38:28,150 --> 00:38:29,900\nagain, you've got to learn\nabout the syntax.\n\n642\n00:38:29,900 --> 00:38:33,840\nThe question was when defining\naverage damp, don't you have\n\n643\n00:38:33,840 --> 00:38:38,070\nto have a variable\ndefined with f?\n\n644\n00:38:38,070 --> 00:38:40,310\nWhat you are asking about is\nthe formal parameter of f?\n\n645\n00:38:40,310 --> 00:38:41,290\nAUDIENCE: Yeah.\n\n646\n00:38:41,290 --> 00:38:42,810\nPROFESSOR: OK.\n\n647\n00:38:42,810 --> 00:38:45,580\nThe formal parameter\nof f is here.\n\n648\n00:38:45,580 --> 00:38:47,318\nThe formal parameter of f--\n\n649\n00:38:47,318 --> 00:38:50,190\nAUDIENCE: The formal parameter\nof average damp.\n\n650\n00:38:50,190 --> 00:38:51,890\nPROFESSOR: F is being\nused to apply it to\n\n651\n00:38:51,890 --> 00:38:54,400\nan argument, right?\n\n652\n00:38:54,400 --> 00:38:57,780\nIt's indeed true that f must\nhave a formal parameter.\n\n653\n00:38:57,780 --> 00:39:00,380\nLet's find out what f's\nformal parameter is.\n\n654\n00:39:00,380 --> 00:39:02,440\nAUDIENCE: The formal parameter\nof average damp.\n\n655\n00:39:02,440 --> 00:39:04,700\nPROFESSOR: Oh, f is the formal\nparameter of average damp.\n\n656\n00:39:04,700 --> 00:39:05,500\nI'm sorry.\n\n657\n00:39:05,500 --> 00:39:07,910\nYou're just confusing\na syntactic thing.\n\n658\n00:39:07,910 --> 00:39:10,470\nI could have written\nthis the other way.\n\n659\n00:39:10,470 --> 00:39:12,520\nActually, I didn't understand\nyour question.\n\n660\n00:39:12,520 --> 00:39:13,910\nOf course, I could have written\nit this other way.\n\n661\n00:39:13,910 --> 00:39:19,340\n\n\n662\n00:39:19,340 --> 00:39:21,540\nThose are identical notations.\n\n663\n00:39:21,540 --> 00:39:25,607\nThis is a different way\nof writing this.\n\n664\n00:39:25,607 --> 00:39:31,710\n\n\n665\n00:39:31,710 --> 00:39:33,280\nYou're going to have to get\nused to lambda notation\n\n666\n00:39:33,280 --> 00:39:35,520\nbecause I'm going to use it.\n\n667\n00:39:35,520 --> 00:39:40,460\nWhat it says here, I'm defining\nthe name average damp\n\n668\n00:39:40,460 --> 00:39:44,600\nto name the procedure whose\nof one argument f.\n\n669\n00:39:44,600 --> 00:39:49,250\nThat's the formal parameter of\nthe procedure average damp.\n\n670\n00:39:49,250 --> 00:39:56,550\nWhat define does is it says\ngive this name a value.\n\n671\n00:39:56,550 --> 00:39:57,860\nHere is the value of for it.\n\n672\n00:39:57,860 --> 00:40:01,310\n\n\n673\n00:40:01,310 --> 00:40:05,100\nThat there happens to be a\nfunny syntax to make that\n\n674\n00:40:05,100 --> 00:40:08,085\neasier in some cases is\npurely convenience.\n\n675\n00:40:08,085 --> 00:40:10,900\n\n\n676\n00:40:10,900 --> 00:40:14,540\nBut the reason why I wrote it\nthis way here is to emphasize\n\n677\n00:40:14,540 --> 00:40:16,530\nthat I'm dealing with a\nprocedure that takes a\n\n678\n00:40:16,530 --> 00:40:18,100\nprocedure as its argument\nand produces a\n\n679\n00:40:18,100 --> 00:40:19,350\nprocedure as its value.\n\n680\n00:40:19,350 --> 00:40:23,640\n\n\n681\n00:40:23,640 --> 00:40:25,800\nAUDIENCE: I don't understand\nwhy you use lambda twice.\n\n682\n00:40:25,800 --> 00:40:27,760\nCan you just use one\nlambda and take two\n\n683\n00:40:27,760 --> 00:40:29,230\narguments f and x?\n\n684\n00:40:29,230 --> 00:40:29,520\nPROFESSOR: No.\n\n685\n00:40:29,520 --> 00:40:30,330\nAUDIENCE: You can't?\n\n686\n00:40:30,330 --> 00:40:32,500\nPROFESSOR: No, that would\nbe a different thing.\n\n687\n00:40:32,500 --> 00:40:36,190\nIf I were to write the procedure\nlambda of f and x,\n\n688\n00:40:36,190 --> 00:40:40,090\nthe average of f of x and x,\nthat would not be something\n\n689\n00:40:40,090 --> 00:40:42,810\nwhich would be allowed to take a\nprocedure as an argument and\n\n690\n00:40:42,810 --> 00:40:44,580\nproduce a procedure\nas its value.\n\n691\n00:40:44,580 --> 00:40:46,330\nThat would be a thing that\ntakes a procedure as its\n\n692\n00:40:46,330 --> 00:40:48,700\nargument and numbers\nits argument and\n\n693\n00:40:48,700 --> 00:40:50,620\nproduces a new number.\n\n694\n00:40:50,620 --> 00:40:53,650\nBut what I'm producing here is\na procedure to fit in the\n\n695\n00:40:53,650 --> 00:40:56,090\nprocedure slot over here,\nwhich is going to\n\n696\n00:40:56,090 --> 00:40:58,860\nbe used over here.\n\n697\n00:40:58,860 --> 00:41:01,450\nSo the number has to\ncome from here.\n\n698\n00:41:01,450 --> 00:41:04,440\nThis is the thing that's going\nto eventually end up in the x.\n\n699\n00:41:04,440 --> 00:41:07,810\nAnd if you're confused, you\nshould do some substitution\n\n700\n00:41:07,810 --> 00:41:09,060\nand see for yourself.\n\n701\n00:41:09,060 --> 00:41:12,010\n\n\n702\n00:41:12,010 --> 00:41:12,746\nYes?\n\n703\n00:41:12,746 --> 00:41:15,870\nAUDIENCE: Will you please show\nthe definition for average\n\n704\n00:41:15,870 --> 00:41:19,320\ndamp without using lambda\nnotation in both cases.\n\n705\n00:41:19,320 --> 00:41:21,490\nPROFESSOR: I can't make a very\nsimple one like that.\n\n706\n00:41:21,490 --> 00:41:22,990\nLet me do it for you, though.\n\n707\n00:41:22,990 --> 00:41:26,530\nI can get rid of this\nlambda easily.\n\n708\n00:41:26,530 --> 00:41:27,780\nI don't want to be--\n\n709\n00:41:27,780 --> 00:41:32,760\n\n\n710\n00:41:32,760 --> 00:41:33,810\nactually, I'm lying to you.\n\n711\n00:41:33,810 --> 00:41:37,170\nI don't want to do what you want\nbecause I think it's more\n\n712\n00:41:37,170 --> 00:41:39,310\nconfusing than you think.\n\n713\n00:41:39,310 --> 00:41:40,560\nI'm not going to write\nwhat you want.\n\n714\n00:41:40,560 --> 00:41:55,450\n\n\n715\n00:41:55,450 --> 00:41:56,500\nSo we'll have to get a name.\n\n716\n00:41:56,500 --> 00:42:13,370\nFOO of x to be of F of x and x\nand return as a value FOO.\n\n717\n00:42:13,370 --> 00:42:17,140\n\n\n718\n00:42:17,140 --> 00:42:20,406\nThis is equivalent, but\nI've had to make an\n\n719\n00:42:20,406 --> 00:42:21,700\narbitrary name up.\n\n720\n00:42:21,700 --> 00:42:26,290\nThis is equivalent to this\nwithout any lambdas.\n\n721\n00:42:26,290 --> 00:42:31,240\nLambda is very convenient for\nnaming anonymous procedures.\n\n722\n00:42:31,240 --> 00:42:34,080\nIt's the anonymous name\nof something.\n\n723\n00:42:34,080 --> 00:42:39,780\nNow, if you really want to know\na cute way of doing this,\n\n724\n00:42:39,780 --> 00:42:41,820\nwe'll talk about it later.\n\n725\n00:42:41,820 --> 00:42:44,680\nWe're going to have to define\nthe anonymous procedure.\n\n726\n00:42:44,680 --> 00:42:45,930\nAny other questions?\n\n727\n00:42:45,930 --> 00:42:49,116\n\n\n728\n00:42:49,116 --> 00:42:50,880\nAnd so we go for our\nbreak again.\n\n729\n00:42:50,880 --> 00:43:31,740\n\n\n730\n00:43:31,740 --> 00:43:35,380\nSo now we've seen how\nto use high-order\n\n731\n00:43:35,380 --> 00:43:36,490\nprocedures, they're called.\n\n732\n00:43:36,490 --> 00:43:38,570\nThat's procedures that take\nprocedural arguments and\n\n733\n00:43:38,570 --> 00:43:43,310\nproduce procedural values to\nhelp us clarify and abstract\n\n734\n00:43:43,310 --> 00:43:46,470\nsome otherwise complicated\nprocesses.\n\n735\n00:43:46,470 --> 00:43:48,500\nI suppose what I'd like to do\nnow is have a bit of fun with\n\n736\n00:43:48,500 --> 00:43:54,080\nthat and sort of a little\npractice as well.\n\n737\n00:43:54,080 --> 00:43:56,290\nSo let's play with this square\nroot thing even more.\n\n738\n00:43:56,290 --> 00:43:59,800\nLet's elaborate it and\nunderstand what's going on and\n\n739\n00:43:59,800 --> 00:44:04,270\nmake use of this kind of\nprogramming style.\n\n740\n00:44:04,270 --> 00:44:08,680\nOne thing that you might know\nis that there is a general\n\n741\n00:44:08,680 --> 00:44:12,990\nmethod called Newton's method\nthe purpose of which is to\n\n742\n00:44:12,990 --> 00:44:15,180\nfind the roots--\n\n743\n00:44:15,180 --> 00:44:17,280\nthat's the zeroes--\n\n744\n00:44:17,280 --> 00:44:19,130\nof functions.\n\n745\n00:44:19,130 --> 00:44:38,420\nSo, for example, to find a y\nsuch that f of y equals 0, we\n\n746\n00:44:38,420 --> 00:44:40,280\nstart with some guess.\n\n747\n00:44:40,280 --> 00:44:41,530\nThis is Newton's method.\n\n748\n00:44:41,530 --> 00:44:51,260\n\n\n749\n00:44:51,260 --> 00:44:55,860\nAnd the guess we start with\nwe'll call y0, and then we\n\n750\n00:44:55,860 --> 00:45:01,100\nwill iterate the following\nexpression.\n\n751\n00:45:01,100 --> 00:45:04,880\ny n plus 1-- this is a\ndifference equation--\n\n752\n00:45:04,880 --> 00:45:17,366\nis yn minus f of yn over the\nderivative with respect to y\n\n753\n00:45:17,366 --> 00:45:23,270\nof f evaluated at y equal yn.\n\n754\n00:45:23,270 --> 00:45:26,430\nVery strange notation.\n\n755\n00:45:26,430 --> 00:45:31,700\nI must say ugh.\n\n756\n00:45:31,700 --> 00:45:35,990\nThe derivative of f with respect\nto y is a function.\n\n757\n00:45:35,990 --> 00:45:38,420\nI'm having a little bit of\nunhappiness with that, but\n\n758\n00:45:38,420 --> 00:45:39,120\nthat's all right.\n\n759\n00:45:39,120 --> 00:45:41,050\nIt turns out in the programming\nlanguage world,\n\n760\n00:45:41,050 --> 00:45:43,930\nthe notation is much clearer.\n\n761\n00:45:43,930 --> 00:45:45,950\nNow, what is this?\n\n762\n00:45:45,950 --> 00:45:47,330\nPeople call it Newton's\nmethod.\n\n763\n00:45:47,330 --> 00:45:54,250\nIt's a method for finding the\nroots of the function f.\n\n764\n00:45:54,250 --> 00:45:56,410\nAnd it, of course, sometimes\nconverges, and when it does,\n\n765\n00:45:56,410 --> 00:45:59,310\nit does so very fast. And\nsometimes, it doesn't\n\n766\n00:45:59,310 --> 00:46:03,230\nconverge, and, oh well, we have\nto do something else.\n\n767\n00:46:03,230 --> 00:46:07,190\nBut let's talk about square\nroot by Newton's method.\n\n768\n00:46:07,190 --> 00:46:08,680\nWell, that's rather\ninteresting.\n\n769\n00:46:08,680 --> 00:46:11,340\nLet's do exactly the same thing\nwe did last time: a bit\n\n770\n00:46:11,340 --> 00:46:13,490\nof wishful thinking.\n\n771\n00:46:13,490 --> 00:46:18,210\nWe will apply Newton's method,\nassuming we knew how to do it.\n\n772\n00:46:18,210 --> 00:46:20,620\nYou don't know how\nto do it yet.\n\n773\n00:46:20,620 --> 00:46:21,870\nWell, let's go.\n\n774\n00:46:21,870 --> 00:46:25,090\n\n\n775\n00:46:25,090 --> 00:46:26,070\nWhat do I have here?\n\n776\n00:46:26,070 --> 00:46:27,320\nThe square root of x.\n\n777\n00:46:27,320 --> 00:46:31,410\n\n\n778\n00:46:31,410 --> 00:46:37,480\nIt's Newton's method applied\nto a procedure which will\n\n779\n00:46:37,480 --> 00:46:39,990\nrepresent that function\nof y, which computes\n\n780\n00:46:39,990 --> 00:46:42,480\nthat function of y.\n\n781\n00:46:42,480 --> 00:46:48,820\nWell, that procedure is that\nprocedure of y, which is the\n\n782\n00:46:48,820 --> 00:46:51,810\ndifference between x and\nthe square of y.\n\n783\n00:46:51,810 --> 00:47:00,080\n\n\n784\n00:47:00,080 --> 00:47:07,570\nIndeed, if I had a value of y\nfor which this was zero, then\n\n785\n00:47:07,570 --> 00:47:10,020\ny would be the square\nroot of x.\n\n786\n00:47:10,020 --> 00:47:13,730\n\n\n787\n00:47:13,730 --> 00:47:15,550\nSee that?\n\n788\n00:47:15,550 --> 00:47:19,250\nOK, I'm going to start this\nout searching at 1.\n\n789\n00:47:19,250 --> 00:47:23,570\nAgain, completely arbitrary\nproperty of square roots that\n\n790\n00:47:23,570 --> 00:47:24,820\nI can do that.\n\n791\n00:47:24,820 --> 00:47:27,950\n\n\n792\n00:47:27,950 --> 00:47:31,480\nNow, how am I going to compute\nNewton's method?\n\n793\n00:47:31,480 --> 00:47:32,170\nWell, this is the method.\n\n794\n00:47:32,170 --> 00:47:34,310\nI have it right here.\n\n795\n00:47:34,310 --> 00:47:37,740\nIn fact, what I'm doing is\nlooking for a fixed point of\n\n796\n00:47:37,740 --> 00:47:41,240\nsome procedure.\n\n797\n00:47:41,240 --> 00:47:45,190\nThis procedure involves some\ncomplicated expressions in\n\n798\n00:47:45,190 --> 00:47:47,150\nterms of other complicated\nthings.\n\n799\n00:47:47,150 --> 00:47:48,800\nWell, I'm trying to find the\nfixed point of this.\n\n800\n00:47:48,800 --> 00:47:54,620\nI want to find the values of y,\nwhich if I put y in here, I\n\n801\n00:47:54,620 --> 00:48:00,130\nget the same value out here up\nto some degree of accuracy.\n\n802\n00:48:00,130 --> 00:48:02,710\nWell, I already have a\nfixed point process\n\n803\n00:48:02,710 --> 00:48:05,040\naround to do that.\n\n804\n00:48:05,040 --> 00:48:07,350\nAnd so, let's just define\nNewton's method over here.\n\n805\n00:48:07,350 --> 00:48:19,430\n\n\n806\n00:48:19,430 --> 00:48:21,680\nA procedure which computes\na function and a\n\n807\n00:48:21,680 --> 00:48:26,640\nguess, initial guess.\n\n808\n00:48:26,640 --> 00:48:28,920\nNow, I'm going to have\nto do something here.\n\n809\n00:48:28,920 --> 00:48:33,280\nI'm going to need the derivative\nof the function.\n\n810\n00:48:33,280 --> 00:48:36,550\nI'm going to need a procedure\nwhich computes the derivative\n\n811\n00:48:36,550 --> 00:48:39,490\nof the function computed by\nthe given a procedure f.\n\n812\n00:48:39,490 --> 00:48:42,140\n\n\n813\n00:48:42,140 --> 00:48:44,440\nI'm trying to be very careful\nabout what I'm saying.\n\n814\n00:48:44,440 --> 00:48:46,270\nI don't want to mix up the word\nprocedure and function.\n\n815\n00:48:46,270 --> 00:48:47,875\nFunction is a mathematical\nword.\n\n816\n00:48:47,875 --> 00:48:52,950\nIt says I'm mapping from values\nto other values, a set\n\n817\n00:48:52,950 --> 00:48:55,430\nof ordered pairs.\n\n818\n00:48:55,430 --> 00:49:00,380\nBut sometimes, I'll accidentally\nmix those up.\n\n819\n00:49:00,380 --> 00:49:01,655\nProcedures compute functions.\n\n820\n00:49:01,655 --> 00:49:07,400\n\n\n821\n00:49:07,400 --> 00:49:12,100\nSo I'm going to define the\nderivative of f to be by\n\n822\n00:49:12,100 --> 00:49:12,930\nwishful thinking again.\n\n823\n00:49:12,930 --> 00:49:14,720\nI don't know how I'm\ngoing to do it.\n\n824\n00:49:14,720 --> 00:49:15,970\nLet's worry about that later--\n\n825\n00:49:15,970 --> 00:49:18,612\n\n\n826\n00:49:18,612 --> 00:49:25,340\nof F. So if F is a procedure,\nwhich happens to be this one\n\n827\n00:49:25,340 --> 00:49:31,800\nover here for a square root,\nthen DF will be the derivative\n\n828\n00:49:31,800 --> 00:49:34,890\nof it, which is also the\nderivative of the function\n\n829\n00:49:34,890 --> 00:49:36,080\ncomputed by that procedure.\n\n830\n00:49:36,080 --> 00:49:38,760\nDF will be a procedure that\ncomputes the derivative of the\n\n831\n00:49:38,760 --> 00:49:42,920\nfunction computed by the\nprocedure F. And then given\n\n832\n00:49:42,920 --> 00:49:44,850\nthat, I will just go looking\nfor a fixed point.\n\n833\n00:49:44,850 --> 00:49:51,910\n\n\n834\n00:49:51,910 --> 00:49:53,710\nWhat is the fixed point\nI'm looking for?\n\n835\n00:49:53,710 --> 00:49:57,580\nIt's the one for that procedure\nof one argument x,\n\n836\n00:49:57,580 --> 00:50:00,500\nwhich I compute by\nsubtracting x.\n\n837\n00:50:00,500 --> 00:50:04,870\nThat's the old-- that's\nthe yn here.\n\n838\n00:50:04,870 --> 00:50:21,110\nThe quotient of f of x and df\nof x, starting out with the\n\n839\n00:50:21,110 --> 00:50:22,360\noriginal guess.\n\n840\n00:50:22,360 --> 00:50:29,450\n\n\n841\n00:50:29,450 --> 00:50:32,640\nThat's all very simple.\n\n842\n00:50:32,640 --> 00:50:35,130\nNow, I have one part left that\nI haven't written, and I want\n\n843\n00:50:35,130 --> 00:50:37,720\nyou to see the process by which\nI write these things,\n\n844\n00:50:37,720 --> 00:50:40,150\nbecause this is really true.\n\n845\n00:50:40,150 --> 00:50:43,810\nI start out with some\nmathematical idea, perhaps.\n\n846\n00:50:43,810 --> 00:50:48,440\nBy wishful thinking, I assume\nthat by some magic I can do\n\n847\n00:50:48,440 --> 00:50:50,980\nsomething that I have\na name for.\n\n848\n00:50:50,980 --> 00:50:54,850\nI'm not going to worry about\nhow I do it yet.\n\n849\n00:50:54,850 --> 00:50:57,970\nThen I go walking down here and\nsay, well, by some magic,\n\n850\n00:50:57,970 --> 00:51:01,142\nI'm somehow going to figure how\nto do that, but I'm going\n\n851\n00:51:01,142 --> 00:51:04,330\nto write my program anyway.\n\n852\n00:51:04,330 --> 00:51:07,990\nWishful thinking, essential\nto good engineering, and\n\n853\n00:51:07,990 --> 00:51:10,060\ncertainly essential to a\ngood computer science.\n\n854\n00:51:10,060 --> 00:51:12,770\n\n\n855\n00:51:12,770 --> 00:51:15,900\nSo anyway, how many of\nyou wished that your\n\n856\n00:51:15,900 --> 00:51:17,150\ncomputer ran faster?\n\n857\n00:51:17,150 --> 00:51:21,120\n\n\n858\n00:51:21,120 --> 00:51:23,390\nWell, the derivative isn't\nso bad either.\n\n859\n00:51:23,390 --> 00:51:24,640\nSort of like average damping.\n\n860\n00:51:24,640 --> 00:51:28,922\n\n\n861\n00:51:28,922 --> 00:51:34,010\nThe derivative is a procedure\nthat takes a procedure that\n\n862\n00:51:34,010 --> 00:51:38,560\ncomputes a function as its\nargument, and it produces a\n\n863\n00:51:38,560 --> 00:51:42,230\nprocedure that computes a\nfunction, which needs one\n\n864\n00:51:42,230 --> 00:51:43,930\nargument x.\n\n865\n00:51:43,930 --> 00:51:46,270\nWell, you all know\nthis definition.\n\n866\n00:51:46,270 --> 00:51:49,040\nIt's f of x plus delta x minus\nf of x over delta x, right?\n\n867\n00:51:49,040 --> 00:51:50,800\nFor some small delta x.\n\n868\n00:51:50,800 --> 00:51:59,850\nSo that's the quotient of the\ndifference of f of the sum of\n\n869\n00:51:59,850 --> 00:52:10,345\nx and dx minus f point\nx divided by dx.\n\n870\n00:52:10,345 --> 00:52:18,530\n\n\n871\n00:52:18,530 --> 00:52:21,360\nI think the thing was lining up\ncorrectly when I balanced\n\n872\n00:52:21,360 --> 00:52:22,610\nthe parentheses.\n\n873\n00:52:22,610 --> 00:52:25,120\n\n\n874\n00:52:25,120 --> 00:52:27,070\nNow, I want you to\nlook at this.\n\n875\n00:52:27,070 --> 00:52:28,320\nJust look.\n\n876\n00:52:28,320 --> 00:52:31,330\n\n\n877\n00:52:31,330 --> 00:52:33,220\nI suppose I haven't told\nyou what dx is.\n\n878\n00:52:33,220 --> 00:52:44,880\nSomewhere in the world I'm going\nto have to write down\n\n879\n00:52:44,880 --> 00:52:45,770\nsomething like that.\n\n880\n00:52:45,770 --> 00:52:48,150\nI'm not interested.\n\n881\n00:52:48,150 --> 00:52:52,970\nThis is a procedure which takes\na procedure and produces\n\n882\n00:52:52,970 --> 00:52:55,950\nan approximation, a procedure\nthat computes an approximation\n\n883\n00:52:55,950 --> 00:52:58,010\nof the derivative of the\nfunction computed by the\n\n884\n00:52:58,010 --> 00:53:02,740\nprocedure given by the standard\nmethods that you all\n\n885\n00:53:02,740 --> 00:53:04,800\nknow and love.\n\n886\n00:53:04,800 --> 00:53:08,920\nNow, it may not be the case that\ndoing this operation is\n\n887\n00:53:08,920 --> 00:53:11,390\nsuch a good way of approximating\na derivative.\n\n888\n00:53:11,390 --> 00:53:14,800\nNumerical analysts here\nshould jump on me and\n\n889\n00:53:14,800 --> 00:53:16,690\nsay don't do that.\n\n890\n00:53:16,690 --> 00:53:20,150\nComputing derivatives produces\nnoisy answers, which is true.\n\n891\n00:53:20,150 --> 00:53:24,850\nHowever, this again is for the\nsake of understanding.\n\n892\n00:53:24,850 --> 00:53:26,620\nLook what we've got.\n\n893\n00:53:26,620 --> 00:53:29,040\nWe started out with what is\napparently a mathematically\n\n894\n00:53:29,040 --> 00:53:31,210\ncomplex thing.\n\n895\n00:53:31,210 --> 00:53:31,610\nand.\n\n896\n00:53:31,610 --> 00:53:35,370\nIn a few blackboards full, we\nmanaged to decompose the\n\n897\n00:53:35,370 --> 00:53:37,900\nproblem of computing square\nroots by the way you were\n\n898\n00:53:37,900 --> 00:53:41,770\ntaught in your college\ncalculus class--\n\n899\n00:53:41,770 --> 00:53:43,720\nNewton's method--\n\n900\n00:53:43,720 --> 00:53:45,830\nso that it can be understood.\n\n901\n00:53:45,830 --> 00:53:47,840\nIt's clear.\n\n902\n00:53:47,840 --> 00:53:51,231\nLet's look at the structure\nof what it is we've got.\n\n903\n00:53:51,231 --> 00:53:54,660\nLet's look at this slide.\n\n904\n00:53:54,660 --> 00:54:03,110\nThis is a diagram of the machine\ndescribed by the\n\n905\n00:54:03,110 --> 00:54:05,520\nprogram on the blackboard.\n\n906\n00:54:05,520 --> 00:54:08,940\nThere's a machine\ndescribed here.\n\n907\n00:54:08,940 --> 00:54:10,700\nAnd what have I got?\n\n908\n00:54:10,700 --> 00:54:17,690\nOver here is the Newton's method\nfunction f that we have\n\n909\n00:54:17,690 --> 00:54:21,040\non the left-most blackboard.\n\n910\n00:54:21,040 --> 00:54:24,990\nIt's the thing that takes an\nargument called y and puts out\n\n911\n00:54:24,990 --> 00:54:32,500\nthe difference between x and\nthe square of y, where x is\n\n912\n00:54:32,500 --> 00:54:35,400\nsome sort of free variable that\ncomes in from the outside\n\n913\n00:54:35,400 --> 00:54:38,050\nby some magic.\n\n914\n00:54:38,050 --> 00:54:43,430\nSo the square root routine picks\nup an x, and builds this\n\n915\n00:54:43,430 --> 00:54:47,750\nprocedure, which I have the\nx rolled up in it by\n\n916\n00:54:47,750 --> 00:54:50,170\nsubstitution.\n\n917\n00:54:50,170 --> 00:54:58,930\nNow, this procedure in the cloud\nis fed in as the f into\n\n918\n00:54:58,930 --> 00:55:01,630\nthe Newton's method which\nis here, this box.\n\n919\n00:55:01,630 --> 00:55:04,650\n\n\n920\n00:55:04,650 --> 00:55:08,790\nThe f is fanned out.\n\n921\n00:55:08,790 --> 00:55:12,130\nPart of it goes into something\nelse, and the other part of it\n\n922\n00:55:12,130 --> 00:55:15,670\ngoes through a derivative\nprocess into something else to\n\n923\n00:55:15,670 --> 00:55:20,570\nproduce a procedure, which\ncomputes the function which is\n\n924\n00:55:20,570 --> 00:55:24,090\nthe iteration function of\nNewton's method when we use\n\n925\n00:55:24,090 --> 00:55:27,450\nthe fixed point method.\n\n926\n00:55:27,450 --> 00:55:33,030\nSo this procedure, which\ncontains it by substitution--\n\n927\n00:55:33,030 --> 00:55:37,730\nremember, Newton's method over\nhere, Newton's method builds\n\n928\n00:55:37,730 --> 00:55:43,010\nthis procedure, and Newton's\nmethod has in it defined f and\n\n929\n00:55:43,010 --> 00:55:48,900\ndf, so those are captured\nover here: f and df.\n\n930\n00:55:48,900 --> 00:55:51,930\nStarting with this procedure,\nI can now feed this to the\n\n931\n00:55:51,930 --> 00:55:55,260\nfixed point process within an\ninitial guess coming out from\n\n932\n00:55:55,260 --> 00:55:59,135\nthe outside from square\nroot to produce the\n\n933\n00:55:59,135 --> 00:56:00,385\nsquare root of x.\n\n934\n00:56:00,385 --> 00:56:03,680\n\n\n935\n00:56:03,680 --> 00:56:07,680\nSo what we've built is a very\npowerful engine, which allows\n\n936\n00:56:07,680 --> 00:56:11,256\nus to make nice things\nlike this.\n\n937\n00:56:11,256 --> 00:56:19,000\nNow, I want to end this with\nbasically an idea of Chris\n\n938\n00:56:19,000 --> 00:56:21,520\nStrachey, one of the\n\n939\n00:56:21,520 --> 00:56:23,230\ngrandfathers of computer science.\n\n940\n00:56:23,230 --> 00:56:27,440\nHe's a logician who\nlived in the--\n\n941\n00:56:27,440 --> 00:56:30,320\nI suppose about 10 years ago\nor 15 years ago, he died.\n\n942\n00:56:30,320 --> 00:56:31,840\nI don't remember exactly when.\n\n943\n00:56:31,840 --> 00:56:33,250\nHe's one of the inventors\nof something called\n\n944\n00:56:33,250 --> 00:56:34,820\ndenotational semantics.\n\n945\n00:56:34,820 --> 00:56:40,560\nHe was a great advocate of\nmaking procedures or functions\n\n946\n00:56:40,560 --> 00:56:43,950\nfirst-class citizens in a\nprogramming language.\n\n947\n00:56:43,950 --> 00:56:46,910\nSo here's the rights and\nprivileges of first-class\n\n948\n00:56:46,910 --> 00:56:50,690\ncitizens in a programming\nlanguage.\n\n949\n00:56:50,690 --> 00:56:53,070\nIt allows you to make any\nabstraction you like if you\n\n950\n00:56:53,070 --> 00:56:57,710\nhave functions as first-class\ncitizens.\n\n951\n00:56:57,710 --> 00:56:59,030\nThe first-class citizens\nmust be able\n\n952\n00:56:59,030 --> 00:57:02,270\nto be named by variables.\n\n953\n00:57:02,270 --> 00:57:04,600\nAnd you're seeing me doing\nthat all the time.\n\n954\n00:57:04,600 --> 00:57:07,700\nHere's a nice variable which\nnames a procedure which\n\n955\n00:57:07,700 --> 00:57:08,950\ncomputes something.\n\n956\n00:57:08,950 --> 00:57:13,270\n\n\n957\n00:57:13,270 --> 00:57:15,370\nThey have to be passed as\narguments to procedures.\n\n958\n00:57:15,370 --> 00:57:18,540\nWe've certainly seen that.\n\n959\n00:57:18,540 --> 00:57:20,640\nWe have to be able to return\nthem as values from\n\n960\n00:57:20,640 --> 00:57:23,340\nprocedures.\n\n961\n00:57:23,340 --> 00:57:25,300\nAnd I suppose we've seen that.\n\n962\n00:57:25,300 --> 00:57:27,970\nWe haven't yet seen anything\nabout data structures.\n\n963\n00:57:27,970 --> 00:57:31,490\nWe will soon, but it's also the\ncase that in order to have\n\n964\n00:57:31,490 --> 00:57:33,940\na first-class citizen in a\nprogramming language, the\n\n965\n00:57:33,940 --> 00:57:37,200\nobject has to be allowed to be\npart of a data structure.\n\n966\n00:57:37,200 --> 00:57:39,110\nWe're going to see that soon.\n\n967\n00:57:39,110 --> 00:57:43,530\nSo I just want to close with\nthis and say having things\n\n968\n00:57:43,530 --> 00:57:46,180\nlike procedures as first-class\ndata structures, first-class\n\n969\n00:57:46,180 --> 00:57:50,780\ndata, allows one to make\npowerful abstractions, which\n\n970\n00:57:50,780 --> 00:57:53,110\nencode general methods\nlike Newton's method\n\n971\n00:57:53,110 --> 00:57:54,780\nin very clear way.\n\n972\n00:57:54,780 --> 00:57:57,430\nAre there any questions?\n\n973\n00:57:57,430 --> 00:57:57,780\nYes.\n\n974\n00:57:57,780 --> 00:58:00,040\nAUDIENCE: Could you put\nderivative instead of df\n\n975\n00:58:00,040 --> 00:58:02,570\ndirectly in the fixed point?\n\n976\n00:58:02,570 --> 00:58:03,810\nPROFESSOR: Oh, sure.\n\n977\n00:58:03,810 --> 00:58:09,220\nYes, I could have put deriv of\nf right here, no question.\n\n978\n00:58:09,220 --> 00:58:11,810\n\n\n979\n00:58:11,810 --> 00:58:16,190\nAny time you see something\ndefined, you can put the thing\n\n980\n00:58:16,190 --> 00:58:18,950\nthat the definition is\nthere because you\n\n981\n00:58:18,950 --> 00:58:21,060\nget the same result.\n\n982\n00:58:21,060 --> 00:58:22,800\nIn fact, what that would look\nlike, it's interesting.\n\n983\n00:58:22,800 --> 00:58:23,750\nAUDIENCE: Lambda.\n\n984\n00:58:23,750 --> 00:58:24,085\nPROFESSOR: Huh?\n\n985\n00:58:24,085 --> 00:58:25,970\nAUDIENCE: You could put the\nlambda expression in there.\n\n986\n00:58:25,970 --> 00:58:29,990\nPROFESSOR: I could also put\nderivative of f here.\n\n987\n00:58:29,990 --> 00:58:32,640\nIt would look interesting\nbecause of the open paren,\n\n988\n00:58:32,640 --> 00:58:38,610\nopen paren, deriv of f,\nclosed paren on an x.\n\n989\n00:58:38,610 --> 00:58:40,900\nNow, that would have the bad\nproperty of computing the\n\n990\n00:58:40,900 --> 00:58:43,980\nderivative many times, because\nevery time I would run this\n\n991\n00:58:43,980 --> 00:58:45,490\nprocedure, I would compute\nthe derivative again.\n\n992\n00:58:45,490 --> 00:58:48,030\n\n\n993\n00:58:48,030 --> 00:58:52,510\nHowever, the two open parens\nhere both would be meaningful.\n\n994\n00:58:52,510 --> 00:58:54,600\nI want you to understand\nsyntactically that that's a\n\n995\n00:58:54,600 --> 00:58:55,350\nsensible thing.\n\n996\n00:58:55,350 --> 00:58:58,190\nBecause if was to rewrite this\nprogram-- and I should do it\n\n997\n00:58:58,190 --> 00:59:00,210\nright here just so\nyou see because\n\n998\n00:59:00,210 --> 00:59:01,460\nthat's a good question--\n\n999\n00:59:01,460 --> 00:59:11,490\n\n\n1000\n00:59:11,490 --> 00:59:25,430\nof F and guess to be fixed point\nof that procedure of one\n\n1001\n00:59:25,430 --> 00:59:34,920\nargument x, which subtracts\nfrom x the quotient of F\n\n1002\n00:59:34,920 --> 00:59:45,045\napplied to x and the deriv\nof F applied to x.\n\n1003\n00:59:45,045 --> 00:59:53,459\n\n\n1004\n00:59:53,459 --> 00:59:54,709\nThis is guess.\n\n1005\n00:59:54,709 --> 00:59:59,960\n\n\n1006\n00:59:59,960 --> 01:00:02,680\nThis is a perfectly legitimate\nprogram,\n\n1007\n01:00:02,680 --> 01:00:04,250\nbecause what I have here--\n\n1008\n01:00:04,250 --> 01:00:05,910\nremember the evaluation rule.\n\n1009\n01:00:05,910 --> 01:00:08,760\nThe evaluation rule is evaluate\nall of the parts of\n\n1010\n01:00:08,760 --> 01:00:12,070\nthe combination: the operator\nand the operands.\n\n1011\n01:00:12,070 --> 01:00:14,575\nThis is the operator of\nthis combination.\n\n1012\n01:00:14,575 --> 01:00:17,080\n\n\n1013\n01:00:17,080 --> 01:00:21,080\nEvaluating this operator will,\nof course, produce the\n\n1014\n01:00:21,080 --> 01:00:28,250\nderivative of F.\n\n1015\n01:00:28,250 --> 01:00:30,300\nAUDIENCE: To get it one step\nfurther, you could put the\n\n1016\n01:00:30,300 --> 01:00:31,200\nlambda expression there, too.\n\n1017\n01:00:31,200 --> 01:00:33,180\nPROFESSOR: Oh, of course.\n\n1018\n01:00:33,180 --> 01:00:37,620\nAny time I take something which\nis define, I can put the\n\n1019\n01:00:37,620 --> 01:00:40,420\nthing it's defined to be in\nthe place where the thing\n\n1020\n01:00:40,420 --> 01:00:42,420\ndefined is.\n\n1021\n01:00:42,420 --> 01:00:44,430\nI can't remember which is\ndefiniens and which is\n\n1022\n01:00:44,430 --> 01:00:45,680\ndefiniendum.\n\n1023\n01:00:45,680 --> 01:00:47,490\n\n\n1024\n01:00:47,490 --> 01:00:50,230\nWhen I'm trying to figure out\nhow to do a lecture about this\n\n1025\n01:00:50,230 --> 01:00:54,160\nin a freshman class, I use such\nwords and tell everybody\n\n1026\n01:00:54,160 --> 01:00:55,440\nit's fun to tell\ntheir friends.\n\n1027\n01:00:55,440 --> 01:00:59,470\n\n\n1028\n01:00:59,470 --> 01:01:01,460\nOK, I think that's it.\n\n1029\n01:01:01,460 --> 01:01:18,506\n\n"
  },
  {
    "path": "SrtEN/lec2b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:05,892\n\n\n1\n00:00:05,892 --> 00:00:22,120\n[MUSIC PLAYING]\n\n2\n00:00:22,120 --> 00:00:24,170\nPROFESSOR: Well, so far in this\ncourse we've been talking\n\n3\n00:00:24,170 --> 00:00:27,680\nabout procedures, and then just\nto remind you of this\n\n4\n00:00:27,680 --> 00:00:31,090\nframework that we introduced for\ntalking about languages,\n\n5\n00:00:31,090 --> 00:00:33,980\nwe talked about the primitive\nthings that are\n\n6\n00:00:33,980 --> 00:00:36,040\nbuilt into the system.\n\n7\n00:00:36,040 --> 00:00:39,710\nWe mentioned some means of\ncombination by which you take\n\n8\n00:00:39,710 --> 00:00:42,530\nthe primitive things and you\nmake more complicated things.\n\n9\n00:00:42,530 --> 00:00:44,610\nAnd then we talked about the\nmeans of abstraction, how you\n\n10\n00:00:44,610 --> 00:00:47,190\ncan take those complicated\nthings and name them so you\n\n11\n00:00:47,190 --> 00:00:49,770\ncan use them as simple\nbuilding blocks.\n\n12\n00:00:49,770 --> 00:00:51,750\nAnd then last time you saw\nwe went even beyond that.\n\n13\n00:00:51,750 --> 00:00:55,830\nWe saw that by using higher\norder procedures, you can\n\n14\n00:00:55,830 --> 00:00:58,400\nactually express general methods\nfor computing things.\n\n15\n00:00:58,400 --> 00:01:01,540\nLike the method of doing\nsomething by fixed points, or\n\n16\n00:01:01,540 --> 00:01:05,280\nNewton's method, and so the\nincredible expressive power\n\n17\n00:01:05,280 --> 00:01:08,730\nyou can get just by combining\nthese means of abstraction.\n\n18\n00:01:08,730 --> 00:01:13,260\nAnd the crucial idea in all of\nthis is the one that we build\n\n19\n00:01:13,260 --> 00:01:15,210\na layered system.\n\n20\n00:01:15,210 --> 00:01:17,570\nSo for instance, if we're\nwriting the square root\n\n21\n00:01:17,570 --> 00:01:24,950\nprocedure, somewhere the square\nroot procedure uses a\n\n22\n00:01:24,950 --> 00:01:33,130\nprocedure called good-enough,\nand between those there is\n\n23\n00:01:33,130 --> 00:01:35,220\nsome sort of abstraction\nboundary.\n\n24\n00:01:35,220 --> 00:01:38,060\n\n\n25\n00:01:38,060 --> 00:01:41,620\nIt's almost as if we go out and\nin writing square root, we\n\n26\n00:01:41,620 --> 00:01:45,940\ngo and make a contract with\nGeorge, and tell George that\n\n27\n00:01:45,940 --> 00:01:49,600\nhis job is to write good-enough,\nand so long as\n\n28\n00:01:49,600 --> 00:01:52,630\ngood-enough works, we don't\ncare what it does.\n\n29\n00:01:52,630 --> 00:01:54,380\nWe don't care exactly how\nit's implemented.\n\n30\n00:01:54,380 --> 00:01:58,360\nThere are levels of detail here\nthat are George's concern\n\n31\n00:01:58,360 --> 00:02:00,450\nand not ours.\n\n32\n00:02:00,450 --> 00:02:03,680\nSo for instance, George might\nuse an absolute value\n\n33\n00:02:03,680 --> 00:02:07,370\nprocedure that's written by\nHarry, and we don't much care\n\n34\n00:02:07,370 --> 00:02:10,065\nabout that or even know that,\nmaybe, Harry exists.\n\n35\n00:02:10,065 --> 00:02:13,830\n\n\n36\n00:02:13,830 --> 00:02:16,910\nSo the crucial idea is that when\nwe're building things, we\n\n37\n00:02:16,910 --> 00:02:22,600\ndivorce the task of building\nthings from the task of\n\n38\n00:02:22,600 --> 00:02:23,850\nimplementing the parts.\n\n39\n00:02:23,850 --> 00:02:27,690\n\n\n40\n00:02:27,690 --> 00:02:30,110\nAnd in a large system, of\ncourse, we have abstraction\n\n41\n00:02:30,110 --> 00:02:34,180\nbarriers like this at lots, and\nlots, and lots of levels.\n\n42\n00:02:34,180 --> 00:02:36,700\nAnd that's the idea that we've\nbeen using so far over and\n\n43\n00:02:36,700 --> 00:02:38,290\nover in implementing\nprocedures.\n\n44\n00:02:38,290 --> 00:02:41,220\nWell, now what we're going\nto do is look at the\n\n45\n00:02:41,220 --> 00:02:44,170\nsame issues for data.\n\n46\n00:02:44,170 --> 00:02:46,350\nWe're going to see that the\nsystem has primitive data.\n\n47\n00:02:46,350 --> 00:02:47,470\nIn fact, we've already\nseen that.\n\n48\n00:02:47,470 --> 00:02:50,270\nWe've talked about numbers\nas primitive data.\n\n49\n00:02:50,270 --> 00:02:51,300\nAnd then we're going to\nsee their means of\n\n50\n00:02:51,300 --> 00:02:52,390\ncombination for data.\n\n51\n00:02:52,390 --> 00:02:55,940\nThere's glue that allows you to\nput primitive data together\n\n52\n00:02:55,940 --> 00:02:59,500\nto make more complicated,\nkind of compound data.\n\n53\n00:02:59,500 --> 00:03:04,840\nAnd then we're going to see a\nmethodology for abstraction\n\n54\n00:03:04,840 --> 00:03:07,330\nthat's a very good thing to use\nwhen you start building up\n\n55\n00:03:07,330 --> 00:03:09,090\ndata in terms of simpler data.\n\n56\n00:03:09,090 --> 00:03:11,790\nAnd again, the key idea is that\nyou're going to build the\n\n57\n00:03:11,790 --> 00:03:15,700\nsystem in layers and set up\nabstraction barriers that\n\n58\n00:03:15,700 --> 00:03:20,250\nisolate the details at the lower\nlayers from the thing\n\n59\n00:03:20,250 --> 00:03:21,630\nthat's going on at\nthe upper layers.\n\n60\n00:03:21,630 --> 00:03:23,270\nThe details at the\nlower layers, the\n\n61\n00:03:23,270 --> 00:03:25,260\nideas, they won't matter.\n\n62\n00:03:25,260 --> 00:03:27,680\nThey're going to be George's\nconcern because he signed this\n\n63\n00:03:27,680 --> 00:03:30,430\ncontract with us for how the\nstuff that he implements\n\n64\n00:03:30,430 --> 00:03:36,250\nbehaves, and how he implements\nthe thing is his problem.\n\n65\n00:03:36,250 --> 00:03:37,890\nAll right, well let's\nlook at an example.\n\n66\n00:03:37,890 --> 00:03:40,990\nAnd the example I'm going to\ntalk about is a system that\n\n67\n00:03:40,990 --> 00:03:43,010\ndoes arithmetic on\nrational numbers.\n\n68\n00:03:43,010 --> 00:03:46,160\nAnd what I have in mind is that\nwe should have something\n\n69\n00:03:46,160 --> 00:03:52,220\nin the computer that allows us\nto ask it, like, what's the\n\n70\n00:03:52,220 --> 00:04:00,590\nsum of 1/2 and 1/4, and somehow\nthe system should say,\n\n71\n00:04:00,590 --> 00:04:02,890\nyeah, that's 3/4.\n\n72\n00:04:02,890 --> 00:04:11,370\nOr we should be able to say\nwhat's 3/4 times 2/3, and the\n\n73\n00:04:11,370 --> 00:04:13,650\nsystem should be able to\nsay, yeah, that's 1/2.\n\n74\n00:04:13,650 --> 00:04:16,500\n\n\n75\n00:04:16,500 --> 00:04:16,730\nRight?\n\n76\n00:04:16,730 --> 00:04:17,990\nAnd you know what\nI have in mind.\n\n77\n00:04:17,990 --> 00:04:20,700\nAnd you also know how to do this\nfrom, I don't know, fifth\n\n78\n00:04:20,700 --> 00:04:22,410\ngrade or sixth grade.\n\n79\n00:04:22,410 --> 00:04:26,510\nThere are these formulas that\nsay if I have some fraction\n\n80\n00:04:26,510 --> 00:04:29,350\nwhich is a numerator over a\ndenominator, and I want to add\n\n81\n00:04:29,350 --> 00:04:33,600\nthat to some other fraction\nwhich is another numerator\n\n82\n00:04:33,600 --> 00:04:38,200\nover another denominator, then\nthe answer is the numerator of\n\n83\n00:04:38,200 --> 00:04:41,920\nthe first times the denominator\nof the second,\n\n84\n00:04:41,920 --> 00:04:45,885\nplus the numerator of the second\ntimes the denominator\n\n85\n00:04:45,885 --> 00:04:49,930\nof the first. That's the\nnumerator of the answer, and\n\n86\n00:04:49,930 --> 00:04:53,260\nthe denominator is the product\nof the two denominators.\n\n87\n00:04:53,260 --> 00:04:53,400\nRight?\n\n88\n00:04:53,400 --> 00:04:56,850\nSo there's something from fifth\nor sixth grade fraction\n\n89\n00:04:56,850 --> 00:04:57,570\narithmetic.\n\n90\n00:04:57,570 --> 00:05:00,320\nAnd then similarly, if I want\nto multiply two things, n1\n\n91\n00:05:00,320 --> 00:05:06,710\nover d1 multiplied by n2 over\nd2 is the product of the\n\n92\n00:05:06,710 --> 00:05:10,510\nnumerators over the product\nof the denominators.\n\n93\n00:05:10,510 --> 00:05:14,330\n\n\n94\n00:05:14,330 --> 00:05:18,880\nSo it's no problem at all, but\nit's absolutely no problem to\n\n95\n00:05:18,880 --> 00:05:21,460\nthink about what computation you\nwant to make in adding and\n\n96\n00:05:21,460 --> 00:05:23,760\nmultiplying these fractions.\n\n97\n00:05:23,760 --> 00:05:26,010\nBut as soon as we go\nto implement it, we\n\n98\n00:05:26,010 --> 00:05:27,920\nrun up across something.\n\n99\n00:05:27,920 --> 00:05:33,320\nWe don't have what a\nrational number is.\n\n100\n00:05:33,320 --> 00:05:36,840\nSo we said that the system gives\nus individual numbers,\n\n101\n00:05:36,840 --> 00:05:43,700\nso we can have 5 and 3, but\nsomehow we don't have a way of\n\n102\n00:05:43,700 --> 00:05:47,970\nsaying there's a thing that has\nboth a 3 and a 4 in it, or\n\n103\n00:05:47,970 --> 00:05:49,850\nboth a 2 and a 3.\n\n104\n00:05:49,850 --> 00:05:55,110\nIt's almost as if we'd like to\nimagine that somehow there are\n\n105\n00:05:55,110 --> 00:06:00,820\nthese clouds, and a cloud\nsomehow has both a numerator\n\n106\n00:06:00,820 --> 00:06:03,590\nand a denominator in it, and\nthat's what we'd like to work\n\n107\n00:06:03,590 --> 00:06:04,840\nin terms of.\n\n108\n00:06:04,840 --> 00:06:06,820\n\n\n109\n00:06:06,820 --> 00:06:08,320\nWell, how are we going to\nsolve that problem?\n\n110\n00:06:08,320 --> 00:06:11,360\nWe're going to solve that\nproblem by using this\n\n111\n00:06:11,360 --> 00:06:14,450\nincredibly powerful design\nstrategy that you've already\n\n112\n00:06:14,450 --> 00:06:16,580\nseen us use over and over.\n\n113\n00:06:16,580 --> 00:06:18,330\nAnd that's the strategy\nof wishful thinking.\n\n114\n00:06:18,330 --> 00:06:25,700\n\n\n115\n00:06:25,700 --> 00:06:27,870\nJust like before when we didn't\nhave a procedure, we\n\n116\n00:06:27,870 --> 00:06:31,420\nsaid, well, let's imagine that\nthat procedure already exists.\n\n117\n00:06:31,420 --> 00:06:36,100\nWe'll say, well, let's imagine\nthat we have these clouds.\n\n118\n00:06:36,100 --> 00:06:42,400\nNow more precisely what I mean\nis let's imagine that we have\n\n119\n00:06:42,400 --> 00:06:45,120\nthree procedures, one\ncalled make-RAT.\n\n120\n00:06:45,120 --> 00:06:47,740\n\n\n121\n00:06:47,740 --> 00:06:54,696\nmake-RAT is going to take as\narguments two numbers, so I'll\n\n122\n00:06:54,696 --> 00:06:58,800\ncall them numerator and\ndenominator, and it'll return\n\n123\n00:06:58,800 --> 00:07:02,860\nfor us a cloud--\n\n124\n00:07:02,860 --> 00:07:05,300\none of these clouds.\n\n125\n00:07:05,300 --> 00:07:07,030\nI don't really know\nwhat a cloud is.\n\n126\n00:07:07,030 --> 00:07:11,500\nIt's whatever make-RAT returns,\nthat's its business.\n\n127\n00:07:11,500 --> 00:07:13,400\nAnd then we're going to say,\nsuppose we've got one of these\n\n128\n00:07:13,400 --> 00:07:17,800\nclouds, we have a procedure\ncalled numer, which takes in a\n\n129\n00:07:17,800 --> 00:07:21,462\ncloud that has an n and a d in\nit, whatever a cloud is, and I\n\n130\n00:07:21,462 --> 00:07:23,990\ndon't know what it is,\nand returns for us\n\n131\n00:07:23,990 --> 00:07:26,980\nthe numerator part.\n\n132\n00:07:26,980 --> 00:07:31,750\nAnd then we'll assume we have a\nprocedure denom, which again\n\n133\n00:07:31,750 --> 00:07:36,610\ntakes in a cloud, whatever a\ncloud is, and returns for us\n\n134\n00:07:36,610 --> 00:07:37,850\nthe denominator [? required. ?]\n\n135\n00:07:37,850 --> 00:07:42,530\nThis is just like before, when\nif we're building a square\n\n136\n00:07:42,530 --> 00:07:45,440\nroot, we assume that we\nhave good enough.\n\n137\n00:07:45,440 --> 00:07:45,600\nRight?\n\n138\n00:07:45,600 --> 00:07:48,310\nAnd what we'll say is, we'll go\nfind George, and we'll say\n\n139\n00:07:48,310 --> 00:07:50,480\nto George, well, it's your\nbusiness to make us these\n\n140\n00:07:50,480 --> 00:07:52,280\nprocedures.\n\n141\n00:07:52,280 --> 00:07:54,170\nAnd how you choose to implement\nthese clouds, that's\n\n142\n00:07:54,170 --> 00:07:55,060\nyour problem.\n\n143\n00:07:55,060 --> 00:07:56,310\nWe don't want to know.\n\n144\n00:07:56,310 --> 00:07:58,670\n\n\n145\n00:07:58,670 --> 00:08:03,740\nWell, having pushed this task\noff onto George, then it's\n\n146\n00:08:03,740 --> 00:08:05,520\npretty easy to do\nthe other part.\n\n147\n00:08:05,520 --> 00:08:08,360\nOnce we've got the clouds, it's\npretty easy to write the\n\n148\n00:08:08,360 --> 00:08:11,820\nthing that does say addition\nof rational numbers.\n\n149\n00:08:11,820 --> 00:08:17,820\nYou can just say define,\nwell, let's say +RAT.\n\n150\n00:08:17,820 --> 00:08:21,980\n\n\n151\n00:08:21,980 --> 00:08:25,450\nDefine +RAT, which will\ntake in two rational\n\n152\n00:08:25,450 --> 00:08:28,110\nnumbers, x and y.\n\n153\n00:08:28,110 --> 00:08:31,880\nx and y are each these clouds.\n\n154\n00:08:31,880 --> 00:08:32,539\nAnd what does it do?\n\n155\n00:08:32,539 --> 00:08:35,840\nWell, it's going to return\nfor us a rational number.\n\n156\n00:08:35,840 --> 00:08:40,299\n\n\n157\n00:08:40,299 --> 00:08:41,460\nWhat rational number is it?\n\n158\n00:08:41,460 --> 00:08:43,659\nWell, we've got the\nformulas there.\n\n159\n00:08:43,659 --> 00:08:49,620\nThe numerator of it is the\nsum of the product of the\n\n160\n00:08:49,620 --> 00:08:56,550\nnumerator of x and the\ndenominator of y.\n\n161\n00:08:56,550 --> 00:09:02,580\n\n\n162\n00:09:02,580 --> 00:09:03,950\nIt's one thing in the sum.\n\n163\n00:09:03,950 --> 00:09:07,310\nAnd the other thing in the\nnumerator is the product of\n\n164\n00:09:07,310 --> 00:09:19,060\nthe numerator of y and\nthe denominator of x.\n\n165\n00:09:19,060 --> 00:09:20,910\nThe star, close the plus.\n\n166\n00:09:20,910 --> 00:09:23,830\nRight, that's the first argument\nto make-RAT, which is\n\n167\n00:09:23,830 --> 00:09:26,080\nthe numerator of the thing\nI'm constructing.\n\n168\n00:09:26,080 --> 00:09:28,860\nAnd then the rest of the thing\ngoes into make-RAT is the\n\n169\n00:09:28,860 --> 00:09:32,950\ndenominator of the answer, which\nis the product of the\n\n170\n00:09:32,950 --> 00:09:42,230\ndenominator of x and the\ndenominator of y.\n\n171\n00:09:42,230 --> 00:09:43,480\nLike that.\n\n172\n00:09:43,480 --> 00:09:46,050\n\n\n173\n00:09:46,050 --> 00:09:46,500\nOK?\n\n174\n00:09:46,500 --> 00:09:50,480\nSo there is the analog of doing\n\n175\n00:09:50,480 --> 00:09:51,710\nrational number addition.\n\n176\n00:09:51,710 --> 00:09:54,030\nAnd it's no problem at\nall, assuming that\n\n177\n00:09:54,030 --> 00:09:55,280\nwe have these clouds.\n\n178\n00:09:55,280 --> 00:09:59,020\n\n\n179\n00:09:59,020 --> 00:10:00,810\nAnd of course, we can do\n\n180\n00:10:00,810 --> 00:10:02,250\nmultiplication in the same way.\n\n181\n00:10:02,250 --> 00:10:05,570\n\n\n182\n00:10:05,570 --> 00:10:10,030\nDefine how to get the product\nof two rational\n\n183\n00:10:10,030 --> 00:10:13,080\nnumbers, call it *RAT.\n\n184\n00:10:13,080 --> 00:10:20,950\nTakes in two of these clouds, x\nand y, it returns a rational\n\n185\n00:10:20,950 --> 00:10:27,100\nnumber, make-RAT, whose\nnumerator is the product of\n\n186\n00:10:27,100 --> 00:10:28,350\nthe numerators--\n\n187\n00:10:28,350 --> 00:10:30,270\n\n\n188\n00:10:30,270 --> 00:10:38,170\nnumerator of x times\nthe numerator of y.\n\n189\n00:10:38,170 --> 00:10:41,780\nAnd the denominator of the thing\nit's going to return is\n\n190\n00:10:41,780 --> 00:10:43,030\nthe product of the\ndenominators.\n\n191\n00:10:43,030 --> 00:10:57,930\n\n\n192\n00:10:57,930 --> 00:11:01,550\nWell, except that I haven't\ntold you what these clouds\n\n193\n00:11:01,550 --> 00:11:04,510\nare, that's all there\nis to it.\n\n194\n00:11:04,510 --> 00:11:05,280\nSee, what did I do?\n\n195\n00:11:05,280 --> 00:11:08,510\nI assumed by wishful thinking\nthat I had a new\n\n196\n00:11:08,510 --> 00:11:10,490\nkind of data object.\n\n197\n00:11:10,490 --> 00:11:14,780\nAnd in particular, I assumed I\nhad ways of creating these\n\n198\n00:11:14,780 --> 00:11:16,360\ndata objects.\n\n199\n00:11:16,360 --> 00:11:18,140\nMake-RAT creates one\nof these things.\n\n200\n00:11:18,140 --> 00:11:19,390\nThis is called a constructor.\n\n201\n00:11:19,390 --> 00:11:25,720\n\n\n202\n00:11:25,720 --> 00:11:29,750\nAll right, I have a thing that\nconstructs such data objects.\n\n203\n00:11:29,750 --> 00:11:34,370\nAnd then I assume I have things\nthat, having made these\n\n204\n00:11:34,370 --> 00:11:35,940\nthings, I have ways of getting\nthe parts out.\n\n205\n00:11:35,940 --> 00:11:37,550\nThose are called selectors.\n\n206\n00:11:37,550 --> 00:11:42,850\n\n\n207\n00:11:42,850 --> 00:11:45,750\nAnd so formally, what I said is\nI assumed I had procedures\n\n208\n00:11:45,750 --> 00:11:48,450\nthat are constructors and\nselectors for these data\n\n209\n00:11:48,450 --> 00:11:52,090\nobjects, and then I went\noff and used them.\n\n210\n00:11:52,090 --> 00:11:55,010\nThat's no different in kind from\nsaying I assume I have a\n\n211\n00:11:55,010 --> 00:11:57,240\nprocedure good-enough,\nand I go use it to\n\n212\n00:11:57,240 --> 00:11:58,490\nimplement square root.\n\n213\n00:11:58,490 --> 00:12:00,850\n\n\n214\n00:12:00,850 --> 00:12:06,940\nOK, well before we go on, let's\nask the question of why\n\n215\n00:12:06,940 --> 00:12:08,660\ndo we want to do this\nin the first place?\n\n216\n00:12:08,660 --> 00:12:14,170\nSee, why do we want a procedure\nlike +RAT that takes\n\n217\n00:12:14,170 --> 00:12:20,340\nin two rational numbers and\nreturns a rational number?\n\n218\n00:12:20,340 --> 00:12:22,140\nSee, another way to think about\nthis is, well, here's\n\n219\n00:12:22,140 --> 00:12:23,390\nthis formula.\n\n220\n00:12:23,390 --> 00:12:25,160\n\n\n221\n00:12:25,160 --> 00:12:28,060\nAnd I've also got to implement\nsomething that\n\n222\n00:12:28,060 --> 00:12:29,890\nadds rational numbers.\n\n223\n00:12:29,890 --> 00:12:32,240\nOne other way to think about is,\nwell, there's this thing,\n\n224\n00:12:32,240 --> 00:12:34,850\nand I type in four numbers,\nan n1, and a d1, and\n\n225\n00:12:34,850 --> 00:12:36,600\nan n2, and a d2.\n\n226\n00:12:36,600 --> 00:12:41,610\nAnd it sets some registers in\nthe machine to this numerator\n\n227\n00:12:41,610 --> 00:12:42,440\nand this denominator.\n\n228\n00:12:42,440 --> 00:12:44,380\nSo I might say, well, why don't\nI just add rational\n\n229\n00:12:44,380 --> 00:12:46,640\nnumbers by I type in four\nnumbers, numerators and\n\n230\n00:12:46,640 --> 00:12:48,950\ndenominators, and get out two\nnumbers, which is a numerator\n\n231\n00:12:48,950 --> 00:12:51,000\nand a denominator.\n\n232\n00:12:51,000 --> 00:12:54,020\nWhy are we worrying\nabout building\n\n233\n00:12:54,020 --> 00:12:55,270\nthings like this anyway?\n\n234\n00:12:55,270 --> 00:12:58,620\n\n\n235\n00:12:58,620 --> 00:13:02,390\nWell, the answer is, suppose\nyou want to think about\n\n236\n00:13:02,390 --> 00:13:06,620\nexpressing something like this,\nsuppose I'd like to\n\n237\n00:13:06,620 --> 00:13:14,840\nexpress the idea of taking two\nrational numbers, x plus y,\n\n238\n00:13:14,840 --> 00:13:20,720\nsay, and multiplying that\nby the sum of two\n\n239\n00:13:20,720 --> 00:13:23,670\nother rational numbers.\n\n240\n00:13:23,670 --> 00:13:28,650\nWell, the way I do it, having\nthings like +RAT and *RAT, is\n\n241\n00:13:28,650 --> 00:13:33,930\nI'd say, oh yeah, what that\nis is just the product.\n\n242\n00:13:33,930 --> 00:13:51,570\nThat's *RAT of the sum of x and\ny and the sum of s and t.\n\n243\n00:13:51,570 --> 00:13:57,710\nSo except for syntax, I get an\nexpression that looks like the\n\n244\n00:13:57,710 --> 00:13:59,490\nway I want to think about\nit mathematically.\n\n245\n00:13:59,490 --> 00:14:02,080\nI want to say there\nare two numbers.\n\n246\n00:14:02,080 --> 00:14:06,060\nThere's a thing which is the\nsum of them, and there's a\n\n247\n00:14:06,060 --> 00:14:07,490\nthing which is the\nsum of these two.\n\n248\n00:14:07,490 --> 00:14:10,780\nThat's this and this.\n\n249\n00:14:10,780 --> 00:14:12,530\nAnd then I multiply them.\n\n250\n00:14:12,530 --> 00:14:14,640\nSo I get an expression that\nmatches this expression.\n\n251\n00:14:14,640 --> 00:14:17,720\nIf I did the other thing, if I\nsaid, well, the way I want to\n\n252\n00:14:17,720 --> 00:14:20,770\nthink about this is I type into\nmy machine four numbers,\n\n253\n00:14:20,770 --> 00:14:24,140\nwhich are the numerators and the\ndenominators of x and y,\n\n254\n00:14:24,140 --> 00:14:26,540\nand then four more numbers,\nwhich are the numerators and\n\n255\n00:14:26,540 --> 00:14:29,140\ndenominators of s and t.\n\n256\n00:14:29,140 --> 00:14:30,460\nAnd then what I'd be sitting\nwith is, well,\n\n257\n00:14:30,460 --> 00:14:31,340\nwhat would I do?\n\n258\n00:14:31,340 --> 00:14:34,380\nI'd add these, and somehow I'd\nhave to have two temporary\n\n259\n00:14:34,380 --> 00:14:37,090\nvariables, which are the\nnumerators and denominators of\n\n260\n00:14:37,090 --> 00:14:39,710\nthis sum, and I'd go off and\nstore them someplace.\n\n261\n00:14:39,710 --> 00:14:42,500\n\n\n262\n00:14:42,500 --> 00:14:44,670\nAnd then I'd go over here, I'd\ntype in four more numbers, I'd\n\n263\n00:14:44,670 --> 00:14:47,140\nget two more temporary\nvariables, which are the\n\n264\n00:14:47,140 --> 00:14:50,180\nnumerators and denominators\nof s and t.\n\n265\n00:14:50,180 --> 00:14:55,000\nAnd then finally, I put those\ntogether by multiplying them.\n\n266\n00:14:55,000 --> 00:14:56,890\nYou see, what's starting to\nhappen, there are all these\n\n267\n00:14:56,890 --> 00:15:01,450\ntemporary variables, which are\nsort of the guts of the\n\n268\n00:15:01,450 --> 00:15:04,320\ninternals of these rational\nnumbers that start hanging out\n\n269\n00:15:04,320 --> 00:15:06,190\nall over the system.\n\n270\n00:15:06,190 --> 00:15:08,050\nAnd of course, if I had more\nand more complicated\n\n271\n00:15:08,050 --> 00:15:10,380\nexpressions, there'd be more and\nmore guts hanging out that\n\n272\n00:15:10,380 --> 00:15:13,010\nconfuse my programming.\n\n273\n00:15:13,010 --> 00:15:15,920\nAnd those of you who sort of\nprogrammed things like that,\n\n274\n00:15:15,920 --> 00:15:18,440\nwhere you're just adding numbers\nin assembly language,\n\n275\n00:15:18,440 --> 00:15:20,280\nyou sort of see you have to\nsuddenly be concerned with\n\n276\n00:15:20,280 --> 00:15:23,040\nthese temporary variables.\n\n277\n00:15:23,040 --> 00:15:28,350\nBut more importantly than\nconfusing my programming,\n\n278\n00:15:28,350 --> 00:15:29,760\nthey're going to confuse\nmy mind.\n\n279\n00:15:29,760 --> 00:15:34,700\nBecause the whole name of this\ngame is that we'd like the\n\n280\n00:15:34,700 --> 00:15:38,750\nprogramming language to express\nthe concepts that we\n\n281\n00:15:38,750 --> 00:15:41,350\nhave in our heads, like rational\nnumbers are things\n\n282\n00:15:41,350 --> 00:15:44,770\nthat you can add and then take\nthat result and multiply them.\n\n283\n00:15:44,770 --> 00:15:48,760\n\n\n284\n00:15:48,760 --> 00:15:50,010\nLet's break for questions.\n\n285\n00:15:50,010 --> 00:15:59,570\n\n\n286\n00:15:59,570 --> 00:16:00,080\nYeah?\n\n287\n00:16:00,080 --> 00:16:03,240\nAUDIENCE: I don't quite see the\nneed- when we had make-RAT\n\n288\n00:16:03,240 --> 00:16:05,150\nwith the numerator and\ndenominator, we had to have\n\n289\n00:16:05,150 --> 00:16:07,590\nthe numerator and denominator\nto pass as parameters to\n\n290\n00:16:07,590 --> 00:16:10,420\ncreate the cloud, and then we\nextracted to get back what we\n\n291\n00:16:10,420 --> 00:16:11,720\nhad to have originally.\n\n292\n00:16:11,720 --> 00:16:13,740\nPROFESSOR: That's right.\n\n293\n00:16:13,740 --> 00:16:16,310\nSo the question is, I sort of\nhave the numerator and the\n\n294\n00:16:16,310 --> 00:16:20,690\ndenominator, why am I worrying\nabout having the cloud given\n\n295\n00:16:20,690 --> 00:16:23,500\nthat I have to get\nthe pieces out?\n\n296\n00:16:23,500 --> 00:16:26,310\nThat's sort of what I tried to\nsay at the end, but let me try\n\n297\n00:16:26,310 --> 00:16:27,250\nand say it again,\nbecause that's\n\n298\n00:16:27,250 --> 00:16:29,390\nreally the crucial question.\n\n299\n00:16:29,390 --> 00:16:32,540\nThe point is, I want to carry\nthis numerator and denominator\n\n300\n00:16:32,540 --> 00:16:36,816\naround together all the time.\n\n301\n00:16:36,816 --> 00:16:39,570\nAnd it's almost as if I want\nto know, yeah, there's a\n\n302\n00:16:39,570 --> 00:16:42,350\nnumerator and denominator in\nthere, but also, I would like\n\n303\n00:16:42,350 --> 00:16:50,180\nto say, fine, but from another\npoint of view, that's x.\n\n304\n00:16:50,180 --> 00:16:53,040\nAnd I carry x around, and I name\nit as x, and I hold it.\n\n305\n00:16:53,040 --> 00:16:56,520\nAnd I can say things like, the\nsum of x and y, rather than\n\n306\n00:16:56,520 --> 00:16:59,180\njust have-- see, it's not so bad\nwhen I only think about x,\n\n307\n00:16:59,180 --> 00:17:02,360\nbut if I have a system with 10\nrational numbers, suddenly I\n\n308\n00:17:02,360 --> 00:17:04,770\nhave 20 numerators and\ndenominators, which are not\n\n309\n00:17:04,770 --> 00:17:05,930\nnecessarily--\n\n310\n00:17:05,930 --> 00:17:08,609\nif I don't link them, then it's\njust 20 arbitrary numbers\n\n311\n00:17:08,609 --> 00:17:10,560\nthat are not linked in\nany particular way.\n\n312\n00:17:10,560 --> 00:17:14,400\nIt's a lot like saying, well, I\nhave these instructions that\n\n313\n00:17:14,400 --> 00:17:16,099\nare the body of the procedures,\nwhy do I want to\n\n314\n00:17:16,099 --> 00:17:17,970\npackage them and say\nit's the procedure?\n\n315\n00:17:17,970 --> 00:17:19,220\nIt's exactly the same idea.\n\n316\n00:17:19,220 --> 00:17:31,875\n\n\n317\n00:17:31,875 --> 00:17:33,840\nNo?\n\n318\n00:17:33,840 --> 00:17:35,120\nOK.\n\n319\n00:17:35,120 --> 00:17:36,870\nLet's break, let's just stretch\nand get somebody--\n\n320\n00:17:36,870 --> 00:17:38,349\n[INAUDIBLE]\n\n321\n00:17:38,349 --> 00:18:27,080\n[MUSIC PLAYING]\n\n322\n00:18:27,080 --> 00:18:29,790\nOK, well, we've been working\non this rational number\n\n323\n00:18:29,790 --> 00:18:34,590\narithmetic system, and then\nwhat we did, the important\n\n324\n00:18:34,590 --> 00:18:37,430\nthing about what we did, is we\nthought about the problem by\n\n325\n00:18:37,430 --> 00:18:40,160\nbreaking it into two pieces.\n\n326\n00:18:40,160 --> 00:18:43,580\nWe said, assume there is this\ncontract with George, and\n\n327\n00:18:43,580 --> 00:18:46,200\nGeorge has figured out the way\nto how to construct these\n\n328\n00:18:46,200 --> 00:18:50,900\nclouds, provided us procedures\nmake-RAT, which was a\n\n329\n00:18:50,900 --> 00:18:54,340\nconstructor, and selectors,\nwhich are numerator and\n\n330\n00:18:54,340 --> 00:18:55,040\ndenominator.\n\n331\n00:18:55,040 --> 00:18:57,580\nAnd then in terms of that, we\nwent off and implemented\n\n332\n00:18:57,580 --> 00:19:00,630\naddition and multiplication\nof rational numbers.\n\n333\n00:19:00,630 --> 00:19:03,640\nWell, now let's go look\nat George's problem.\n\n334\n00:19:03,640 --> 00:19:06,910\nHow can we go and package\ntogether a numerator and a\n\n335\n00:19:06,910 --> 00:19:09,360\ndenominator and actually make\none of these clouds?\n\n336\n00:19:09,360 --> 00:19:15,760\nSee, what we need is a kind of\nglue, a glue for data objects\n\n337\n00:19:15,760 --> 00:19:18,040\nthat allows us to put\nthings together.\n\n338\n00:19:18,040 --> 00:19:23,170\nAnd Lisp provides such\na glue, and that glue\n\n339\n00:19:23,170 --> 00:19:24,420\nis called list structure.\n\n340\n00:19:24,420 --> 00:19:30,410\n\n\n341\n00:19:30,410 --> 00:19:35,700\nList structure is a way of\ngluing things together, and\n\n342\n00:19:35,700 --> 00:19:40,750\nmore precisely, Lisp provides\na way of constructing things\n\n343\n00:19:40,750 --> 00:19:42,000\ncalled pairs.\n\n344\n00:19:42,000 --> 00:19:44,750\n\n\n345\n00:19:44,750 --> 00:19:52,222\nThere's a primitive operator\nin Lisp called cons.\n\n346\n00:19:52,222 --> 00:19:54,920\nWe can take a look at it.\n\n347\n00:19:54,920 --> 00:19:57,170\nThere's a thing called cons.\n\n348\n00:19:57,170 --> 00:20:00,620\n\n\n349\n00:20:00,620 --> 00:20:03,880\nCons is an operator which takes\nin two arguments called\n\n350\n00:20:03,880 --> 00:20:08,800\nx and y, and it returns for\nus a thing called a pair.\n\n351\n00:20:08,800 --> 00:20:11,510\n\n\n352\n00:20:11,510 --> 00:20:17,520\nAll right, so a thing called a\npair that has a first part a\n\n353\n00:20:17,520 --> 00:20:18,770\nsecond part.\n\n354\n00:20:18,770 --> 00:20:22,250\n\n\n355\n00:20:22,250 --> 00:20:25,450\nSo cons takes two objects.\n\n356\n00:20:25,450 --> 00:20:26,780\nThere's a thing called a pair.\n\n357\n00:20:26,780 --> 00:20:30,700\nThe first part of the cons\nis x, and the second part\n\n358\n00:20:30,700 --> 00:20:31,600\nof the cons is y.\n\n359\n00:20:31,600 --> 00:20:34,090\nAnd that's what it builds.\n\n360\n00:20:34,090 --> 00:20:35,740\nAnd then we also assume\nwe have ways of\n\n361\n00:20:35,740 --> 00:20:36,880\ngetting things out.\n\n362\n00:20:36,880 --> 00:20:41,820\nIf you're given a pair, there's\na thing called car,\n\n363\n00:20:41,820 --> 00:20:44,760\nand car of a pair, p, gives\nyou out the first part\n\n364\n00:20:44,760 --> 00:20:46,640\nof the pair, p.\n\n365\n00:20:46,640 --> 00:20:49,650\nAnd there's a thing called cdr,\nand cdr of the pair, p,\n\n366\n00:20:49,650 --> 00:20:54,310\ngives you the second part\nof the pair, p.\n\n367\n00:20:54,310 --> 00:20:56,710\nOK, so that's how we\nconstruct things.\n\n368\n00:20:56,710 --> 00:21:01,720\nThere's also a conventional\nway of drawing pictures of\n\n369\n00:21:01,720 --> 00:21:02,800\nthese things.\n\n370\n00:21:02,800 --> 00:21:09,070\nJust like we write down that\nas the conventional way of\n\n371\n00:21:09,070 --> 00:21:17,480\nwriting Plato's idea of two,\nthe way we could draw a\n\n372\n00:21:17,480 --> 00:21:21,510\ndiagram to represent cons of\ntwo and three is like this.\n\n373\n00:21:21,510 --> 00:21:23,912\nWe draw a little box.\n\n374\n00:21:23,912 --> 00:21:27,140\nAnd so here's the box we're\ntalking about, and this box\n\n375\n00:21:27,140 --> 00:21:30,070\nhas two arrows coming\nout of it.\n\n376\n00:21:30,070 --> 00:21:35,890\nAnd say the first part of this\npair is 2, and the second part\n\n377\n00:21:35,890 --> 00:21:38,250\nof this pair is 3.\n\n378\n00:21:38,250 --> 00:21:41,180\nAnd this notation has\na name, it's called\n\n379\n00:21:41,180 --> 00:21:44,855\nbox and pointer notation.\n\n380\n00:21:44,855 --> 00:21:56,050\n\n\n381\n00:21:56,050 --> 00:21:58,340\nBy the way, let me say right now\nthat a lot of people get\n\n382\n00:21:58,340 --> 00:22:01,650\nconfused that there's some\nsignificance to the geometric\n\n383\n00:22:01,650 --> 00:22:03,640\nway I drew these pointers,\nthe directions.\n\n384\n00:22:03,640 --> 00:22:06,090\nLike some people think it'd be\ndifferent if I took this\n\n385\n00:22:06,090 --> 00:22:08,660\npointer and turned it up here,\nand put the 3 out here.\n\n386\n00:22:08,660 --> 00:22:10,760\nThat has no significance.\n\n387\n00:22:10,760 --> 00:22:10,940\nAll right?\n\n388\n00:22:10,940 --> 00:22:13,240\nIt's merely you have a bunch\nof arrows, these\n\n389\n00:22:13,240 --> 00:22:15,090\npointers, and the boxes.\n\n390\n00:22:15,090 --> 00:22:18,860\nThe only issue is how they're\nconnected, not the geometric\n\n391\n00:22:18,860 --> 00:22:20,400\narrangement of whether\nI write the pointer\n\n392\n00:22:20,400 --> 00:22:23,160\nacross, or up, or down.\n\n393\n00:22:23,160 --> 00:22:26,700\nNow it's completely un-obvious,\nprobably, why\n\n394\n00:22:26,700 --> 00:22:28,870\nthat's called list structure.\n\n395\n00:22:28,870 --> 00:22:30,420\nWe're not actually going to\ntalk about that today.\n\n396\n00:22:30,420 --> 00:22:31,850\nWe'll see that next time.\n\n397\n00:22:31,850 --> 00:22:37,870\n\n\n398\n00:22:37,870 --> 00:22:41,740\nSo those are pairs, there's\ncons that constructs them.\n\n399\n00:22:41,740 --> 00:22:45,640\nAnd what I'm going to know about\ncons, and car, and cdr,\n\n400\n00:22:45,640 --> 00:22:51,420\nis precisely that if I have any\nx and y, all right, if I\n\n401\n00:22:51,420 --> 00:22:59,420\nhave any things x and y, and I\nuse cons to construct a pair,\n\n402\n00:22:59,420 --> 00:23:03,090\nthen the car of that pair is\ngoing to be x, the thing I put\n\n403\n00:23:03,090 --> 00:23:07,790\nin, and the cdr of that\npair is going to be y.\n\n404\n00:23:07,790 --> 00:23:12,360\nThat's the behavior of these\noperators, cons, car, and cdr.\n\n405\n00:23:12,360 --> 00:23:14,870\nGiven them, it's pretty clear\nhow George can go off and\n\n406\n00:23:14,870 --> 00:23:17,520\nconstruct his rational\nnumbers.\n\n407\n00:23:17,520 --> 00:23:19,390\nAfter all, all he has to do--\n\n408\n00:23:19,390 --> 00:23:21,710\nremember George's problem was\nto implement make-RAT,\n\n409\n00:23:21,710 --> 00:23:23,320\nnumerator, and denom.\n\n410\n00:23:23,320 --> 00:23:34,980\nSo all George has to do is\nsay define make-RAT of\n\n411\n00:23:34,980 --> 00:23:37,110\nsome n and a d--\n\n412\n00:23:37,110 --> 00:23:40,710\nso all I have to do\nis cons them.\n\n413\n00:23:40,710 --> 00:23:42,790\nThat's cons of n and d.\n\n414\n00:23:42,790 --> 00:23:45,570\n\n\n415\n00:23:45,570 --> 00:23:48,300\nAnd then if I want to get the\nnumerator out, I would say\n\n416\n00:23:48,300 --> 00:24:00,260\ndefine the numerator, numer,\nof some rational number, x.\n\n417\n00:24:00,260 --> 00:24:03,010\nIf the rational number's\nimplemented as a pair, then\n\n418\n00:24:03,010 --> 00:24:06,190\nall I have to do is get\nout the car of x.\n\n419\n00:24:06,190 --> 00:24:19,350\nAnd then similarly, define the\ndenom is going to be the cdr,\n\n420\n00:24:19,350 --> 00:24:21,430\nthe other thing I put\ninto the pair.\n\n421\n00:24:21,430 --> 00:24:27,080\n\n\n422\n00:24:27,080 --> 00:24:28,960\nWell, now we're in business.\n\n423\n00:24:28,960 --> 00:24:31,530\nThat's a complete\n\n424\n00:24:31,530 --> 00:24:33,810\nimplementation of rational numbers.\n\n425\n00:24:33,810 --> 00:24:34,410\nLet's use it.\n\n426\n00:24:34,410 --> 00:24:37,270\nSuppose I want to say, so I want\nto think about how to add\n\n427\n00:24:37,270 --> 00:24:43,470\n1/2 plus 1/4 and watch\nthe system work.\n\n428\n00:24:43,470 --> 00:24:50,780\nWell, the way I'd use that is\nI'd say, well, maybe define a.\n\n429\n00:24:50,780 --> 00:24:53,080\nI have to make a 1/2.\n\n430\n00:24:53,080 --> 00:24:55,980\nWell, that's a rational number\nwith numerator 1 and\n\n431\n00:24:55,980 --> 00:25:01,090\ndenominator 2, so a will\nbe make-RAT of 1 and 2.\n\n432\n00:25:01,090 --> 00:25:05,490\n\n\n433\n00:25:05,490 --> 00:25:07,770\nAnd then I'll construct\nthe 1/4.\n\n434\n00:25:07,770 --> 00:25:20,560\nI'll say define d to be\nmake-RAT of 1 and 4.\n\n435\n00:25:20,560 --> 00:25:23,362\n\n\n436\n00:25:23,362 --> 00:25:25,440\nAnd if I'd like to look\nat the answer--\n\n437\n00:25:25,440 --> 00:25:27,710\nwell, assuming I don't have a\nspecial thing that prints\n\n438\n00:25:27,710 --> 00:25:30,100\nrational numbers, or\nI could make one--\n\n439\n00:25:30,100 --> 00:25:41,622\nI could say, for instance,\ndefine the answer to be +RAT\n\n440\n00:25:41,622 --> 00:25:47,790\nof a and b, and now I can\nsay, what's the answer?\n\n441\n00:25:47,790 --> 00:25:50,900\nWhat are the numerators and\ndenominators of the answer?\n\n442\n00:25:50,900 --> 00:25:55,520\nSo if I'm adding 1/2 and 1/4,\nI'll say, what is the\n\n443\n00:25:55,520 --> 00:26:00,440\nnumerator of the answer?\n\n444\n00:26:00,440 --> 00:26:04,230\n\n\n445\n00:26:04,230 --> 00:26:10,880\nAnd the system is going\nto type out, well, 6.\n\n446\n00:26:10,880 --> 00:26:13,250\nBad news.\n\n447\n00:26:13,250 --> 00:26:22,790\nAnd if I say what's the\ndenominator of the answer, the\n\n448\n00:26:22,790 --> 00:26:26,430\nsystem's going to type out 8.\n\n449\n00:26:26,430 --> 00:26:30,400\nSo instead of what I would\nreally like, which is for it\n\n450\n00:26:30,400 --> 00:26:36,550\nto say that 1/2 and 1/4 is 3/4,\nthis foolish machine is\n\n451\n00:26:36,550 --> 00:26:40,450\ngoing to say, no, it's 6/8.\n\n452\n00:26:40,450 --> 00:26:43,400\nWell, that's sort of bad news.\n\n453\n00:26:43,400 --> 00:26:44,650\nWhere's the bug?\n\n454\n00:26:44,650 --> 00:26:47,280\n\n\n455\n00:26:47,280 --> 00:26:48,780\nWhy does it do that,\nafter all?\n\n456\n00:26:48,780 --> 00:26:51,400\nWell, it's the way that\nwe just had +RAT.\n\n457\n00:26:51,400 --> 00:26:53,220\n+RAT just took the--\n\n458\n00:26:53,220 --> 00:26:58,510\nit said you add the numerator\ntimes the denominator, you add\n\n459\n00:26:58,510 --> 00:27:01,230\nthat to the numerator times the\ndenominator, and put that\n\n460\n00:27:01,230 --> 00:27:03,140\nover the product of the two\ndenominators, and that's why\n\n461\n00:27:03,140 --> 00:27:05,890\nyou get 6/8.\n\n462\n00:27:05,890 --> 00:27:10,640\nSo what was wrong with our\nimplementation of +RAT?\n\n463\n00:27:10,640 --> 00:27:12,110\nWhat's wrong with that rational\nnumber arithmetic\n\n464\n00:27:12,110 --> 00:27:15,880\nstuff that we did before\nthe break?\n\n465\n00:27:15,880 --> 00:27:17,730\nWell, the answer is one way to\nlook at it is absolutely\n\n466\n00:27:17,730 --> 00:27:19,730\nnothing's wrong.\n\n467\n00:27:19,730 --> 00:27:21,070\nThat's perfectly good\nimplementation.\n\n468\n00:27:21,070 --> 00:27:26,285\nIt follows the sixth grade,\nfifth grade mathematic for\n\n469\n00:27:26,285 --> 00:27:27,535\nadding fractions.\n\n470\n00:27:27,535 --> 00:27:30,000\n\n\n471\n00:27:30,000 --> 00:27:33,310\nOne thing we can say is, well,\nthat's George's problem.\n\n472\n00:27:33,310 --> 00:27:37,030\nLike, boy, wasn't George dumb\nto say that he can make a\n\n473\n00:27:37,030 --> 00:27:39,960\nrational number simply by\nsticking together the\n\n474\n00:27:39,960 --> 00:27:42,900\nnumerator and the denominator?\n\n475\n00:27:42,900 --> 00:27:45,910\nWouldn't it be better for\nGeorge, when he made a\n\n476\n00:27:45,910 --> 00:27:50,970\nrational number, to reduce the\nstuff to lowest terms?\n\n477\n00:27:50,970 --> 00:27:55,750\nAnd what I mean is, wouldn't\nit be better for George,\n\n478\n00:27:55,750 --> 00:28:01,300\ninstead of using this version\nof make-RAT, to use this one\n\n479\n00:28:01,300 --> 00:28:03,580\non the slide?\n\n480\n00:28:03,580 --> 00:28:09,190\nOr instead of just saying cons\ntogether n and d, what you do\n\n481\n00:28:09,190 --> 00:28:13,650\nis compute the greatest common\ndivisor of n and d, and gcd is\n\n482\n00:28:13,650 --> 00:28:16,540\nthe procedure which, well, for\nall we care is a primitive,\n\n483\n00:28:16,540 --> 00:28:20,628\nwhich computes the greatest\ncommon divisor of two numbers.\n\n484\n00:28:20,628 --> 00:28:24,890\nSo the way I can construct a\nrational number is get the\n\n485\n00:28:24,890 --> 00:28:27,140\ngreatest common divisor of the\ntwo numbers, and I'm going to\n\n486\n00:28:27,140 --> 00:28:33,000\ncall that g, and then instead\nof consing together n and d,\n\n487\n00:28:33,000 --> 00:28:34,000\nI'll divide them through.\n\n488\n00:28:34,000 --> 00:28:37,630\nI'll cons together the quotient\nof n by the the gcd\n\n489\n00:28:37,630 --> 00:28:40,510\nand the quotient of\nd by the gcd.\n\n490\n00:28:40,510 --> 00:28:42,540\nAnd that will reduce the\nrational number to lowest\n\n491\n00:28:42,540 --> 00:28:49,200\nterms. So when I do\nthis addition,\n\n492\n00:28:49,200 --> 00:28:54,330\nwhen +RAT calls make-RAT--\n\n493\n00:28:54,330 --> 00:28:57,810\nand for the definition of +RAT\nit had a make-RAT in there--\n\n494\n00:28:57,810 --> 00:28:59,880\njust by the fact that it's\nconstructing that, the thing\n\n495\n00:28:59,880 --> 00:29:01,425\nwill get reduced to lowest\nterms automatically.\n\n496\n00:29:01,425 --> 00:29:09,612\n\n\n497\n00:29:09,612 --> 00:29:15,180\nOK, that is a complete system.\n\n498\n00:29:15,180 --> 00:29:16,780\nFor rational number arithmetic,\nlet's look at what\n\n499\n00:29:16,780 --> 00:29:19,590\nwe've done.\n\n500\n00:29:19,590 --> 00:29:22,440\nAll right, we said we want\nto build rational number\n\n501\n00:29:22,440 --> 00:29:27,230\narithmetic, and we had\na thing called +RAT.\n\n502\n00:29:27,230 --> 00:29:29,940\nWe implemented that.\n\n503\n00:29:29,940 --> 00:29:34,660\nAnd I showed you multiplying\nrational numbers, and although\n\n504\n00:29:34,660 --> 00:29:36,570\nI didn't put them up there,\npresumably we'd like to have\n\n505\n00:29:36,570 --> 00:29:39,860\nsomething that subtracts\nrational numbers, and I don't\n\n506\n00:29:39,860 --> 00:29:40,770\nknow, all sorts of things.\n\n507\n00:29:40,770 --> 00:29:43,120\nThings that test equality in\ndivision, and maybe things\n\n508\n00:29:43,120 --> 00:29:46,190\nthat print rational numbers\nin some particular way.\n\n509\n00:29:46,190 --> 00:29:52,330\nAnd we implemented those\nin terms of pairs.\n\n510\n00:29:52,330 --> 00:29:55,800\nThese pairs, cons, car, and cdr\nthat are built into Lisp.\n\n511\n00:29:55,800 --> 00:30:05,100\nBut the important thing is that\nbetween these and these,\n\n512\n00:30:05,100 --> 00:30:07,622\nwe set up an abstraction\nbarrier.\n\n513\n00:30:07,622 --> 00:30:09,260\nWe set up a layer\nof abstraction.\n\n514\n00:30:09,260 --> 00:30:17,310\n\n\n515\n00:30:17,310 --> 00:30:19,190\nAnd what was that layer\nof abstraction?\n\n516\n00:30:19,190 --> 00:30:22,140\nThat layer of abstraction was\nprecisely the constructor and\n\n517\n00:30:22,140 --> 00:30:23,390\nthe selectors.\n\n518\n00:30:23,390 --> 00:30:25,630\n\n\n519\n00:30:25,630 --> 00:30:34,730\nThis layer was make-RAT,\nand numer, and denom.\n\n520\n00:30:34,730 --> 00:30:38,970\n\n\n521\n00:30:38,970 --> 00:30:43,670\nThis methodology, another way\nto say what it's doing, is\n\n522\n00:30:43,670 --> 00:30:53,960\nthat we are separating the way\nsomething is used, separating\n\n523\n00:30:53,960 --> 00:30:57,760\nthe use of data objects,\nfrom the\n\n524\n00:30:57,760 --> 00:30:59,350\nrepresentation of data objects.\n\n525\n00:30:59,350 --> 00:31:07,650\n\n\n526\n00:31:07,650 --> 00:31:10,010\nSo up here, we have the way\nthat rational numbers are\n\n527\n00:31:10,010 --> 00:31:12,620\nused, do arithmetic on them.\n\n528\n00:31:12,620 --> 00:31:15,280\nDown here, we have the way that\nthey're represented, and\n\n529\n00:31:15,280 --> 00:31:17,950\nthey're separated by\nthis boundary.\n\n530\n00:31:17,950 --> 00:31:19,605\nThe boundary is the constructors\nand selectors.\n\n531\n00:31:19,605 --> 00:31:23,760\n\n\n532\n00:31:23,760 --> 00:31:25,920\nAnd this methodology\nhas a name.\n\n533\n00:31:25,920 --> 00:31:27,170\nThis is called data\nabstraction.\n\n534\n00:31:27,170 --> 00:31:35,820\n\n\n535\n00:31:35,820 --> 00:31:39,030\nData abstraction is sort of the\nprogramming methodology of\n\n536\n00:31:39,030 --> 00:31:42,060\nsetting up data objects by\npostulating constructors and\n\n537\n00:31:42,060 --> 00:31:44,085\nselectors to isolate use\nfrom representation.\n\n538\n00:31:44,085 --> 00:31:47,550\n\n\n539\n00:31:47,550 --> 00:31:49,060\nWell, so why?\n\n540\n00:31:49,060 --> 00:31:51,750\nI mean, after all, we didn't\nhave to do it this way.\n\n541\n00:31:51,750 --> 00:31:55,450\nIt's perfectly possible to do\nrational number addition\n\n542\n00:31:55,450 --> 00:31:57,550\nwithout having any compound data\nobjects, and here on the\n\n543\n00:31:57,550 --> 00:32:00,060\nslide is one example.\n\n544\n00:32:00,060 --> 00:32:04,640\nWe certainly could have defined\n+RAT, which takes in\n\n545\n00:32:04,640 --> 00:32:07,830\nthings x and y, and we'll say,\nwell what are these rational\n\n546\n00:32:07,830 --> 00:32:10,030\nnumbers really?\n\n547\n00:32:10,030 --> 00:32:13,060\nSo really, they're just pairs,\nand the numerator's the car\n\n548\n00:32:13,060 --> 00:32:16,180\nand the denominator's the cdr.\nSo what we'll do is we'll take\n\n549\n00:32:16,180 --> 00:32:23,310\nthe car of x times the cdr\nof y, multiply them.\n\n550\n00:32:23,310 --> 00:32:26,470\nTake the car of y times the\ncdr of x, multiply them.\n\n551\n00:32:26,470 --> 00:32:28,650\nAdd them.\n\n552\n00:32:28,650 --> 00:32:31,960\nTake the cdr of x and the cdr of\ny, multiply them, and then\n\n553\n00:32:31,960 --> 00:32:33,210\nconstitute together.\n\n554\n00:32:33,210 --> 00:32:35,450\n\n\n555\n00:32:35,450 --> 00:32:36,890\nWell, that sort of does\nthe same thing.\n\n556\n00:32:36,890 --> 00:32:41,560\n\n\n557\n00:32:41,560 --> 00:32:43,930\nBut this ignores the problem of\nreducing things to lowest\n\n558\n00:32:43,930 --> 00:32:47,680\nterms, but let's not worry\nabout that for a minute.\n\n559\n00:32:47,680 --> 00:32:48,200\nBut so what?\n\n560\n00:32:48,200 --> 00:32:50,790\nWhy don't we do it that way?\n\n561\n00:32:50,790 --> 00:32:50,960\nRight?\n\n562\n00:32:50,960 --> 00:32:53,220\nAfter all, there are sort of\nfewer procedures to define,\n\n563\n00:32:53,220 --> 00:32:54,470\nand it's a lot more\nstraightforward.\n\n564\n00:32:54,470 --> 00:32:57,210\n\n\n565\n00:32:57,210 --> 00:32:59,610\nIt saves all this self-righteous\nBS about\n\n566\n00:32:59,610 --> 00:33:00,850\ntalking about data\nabstraction.\n\n567\n00:33:00,850 --> 00:33:02,270\nWe just sort of do it.\n\n568\n00:33:02,270 --> 00:33:04,870\nI mean, who knows, maybe it's\neven marginally more efficient\n\n569\n00:33:04,870 --> 00:33:07,930\ndepending on whatever compiler\nwere using for this.\n\n570\n00:33:07,930 --> 00:33:11,500\nWhat's the point of isolating\nthe use from the\n\n571\n00:33:11,500 --> 00:33:13,910\nrepresentation?\n\n572\n00:33:13,910 --> 00:33:17,130\nWell, it goes back to this\nnotion of naming.\n\n573\n00:33:17,130 --> 00:33:21,020\nRemember, one of the most\nimportant principles in\n\n574\n00:33:21,020 --> 00:33:23,770\nprogramming is the same as\none of the most important\n\n575\n00:33:23,770 --> 00:33:25,660\nprinciples in sorcery,\nall right?\n\n576\n00:33:25,660 --> 00:33:28,210\nThat's if you have the name\nof the spirit, you get\n\n577\n00:33:28,210 --> 00:33:30,330\ncontrol over it.\n\n578\n00:33:30,330 --> 00:33:34,420\nAnd if you go back and look at\nthe slide, you see what's in\n\n579\n00:33:34,420 --> 00:33:38,580\nthere is we have this thing\n+RAT, but nowhere in the\n\n580\n00:33:38,580 --> 00:33:41,710\nsystem, if I have a +RAT and a\n-RAT and a *RAT, and things\n\n581\n00:33:41,710 --> 00:33:44,870\nthat look like that, nowhere\nin the system do I have a\n\n582\n00:33:44,870 --> 00:33:50,770\nthing that I can point at which\nis a rational number.\n\n583\n00:33:50,770 --> 00:33:53,550\n\n\n584\n00:33:53,550 --> 00:33:58,480\nI don't have, in a system like\nthat, the idea of rational\n\n585\n00:33:58,480 --> 00:34:01,340\nnumber as a conceptual entity.\n\n586\n00:34:01,340 --> 00:34:04,270\nWell, what's the advantage\nof that?\n\n587\n00:34:04,270 --> 00:34:07,200\nWhat's the advantage of\nisolating the idea of rational\n\n588\n00:34:07,200 --> 00:34:09,400\nnumbers as a conceptual entity,\nand really naming it\n\n589\n00:34:09,400 --> 00:34:12,900\nwith make-RAT, numerator,\nand denominator.\n\n590\n00:34:12,900 --> 00:34:18,659\nWell, one advantage is you might\nwant to have alternative\n\n591\n00:34:18,659 --> 00:34:20,679\nrepresentations.\n\n592\n00:34:20,679 --> 00:34:24,889\nSee, before I showed you that\none way George can solve this\n\n593\n00:34:24,889 --> 00:34:27,280\nthings not reduced to lowest\nterms problem, is when you\n\n594\n00:34:27,280 --> 00:34:30,260\nbuild a rational number, you\ndivide up by the greatest\n\n595\n00:34:30,260 --> 00:34:31,190\ncommon denominator.\n\n596\n00:34:31,190 --> 00:34:36,650\nAnother way to do that\nis shown over here.\n\n597\n00:34:36,650 --> 00:34:38,810\nI can have an alternative\nrepresentation for rational\n\n598\n00:34:38,810 --> 00:34:40,980\nnumbers where when you make\na rational number,\n\n599\n00:34:40,980 --> 00:34:43,409\nyou just cons them.\n\n600\n00:34:43,409 --> 00:34:46,610\nHowever, when you go to select\nout the numerator, at that\n\n601\n00:34:46,610 --> 00:34:50,929\npoint you compute the gcd of\nthe stuff that's sitting in\n\n602\n00:34:50,929 --> 00:34:53,440\nthat pair, and divide\nout by the gcd.\n\n603\n00:34:53,440 --> 00:34:57,970\n\n\n604\n00:34:57,970 --> 00:35:02,300\nAnd similarly, when I get the\ndenominator, at that point\n\n605\n00:35:02,300 --> 00:35:03,990\nwhen I go to get the\ndenominator, I'll divide out\n\n606\n00:35:03,990 --> 00:35:05,420\nby the gcd.\n\n607\n00:35:05,420 --> 00:35:09,090\nSo the difference would be in\nthe old representation, when\n\n608\n00:35:09,090 --> 00:35:13,680\nans was constructed here, say\nwhat's 6 and 8, in the first\n\n609\n00:35:13,680 --> 00:35:16,260\nway, the 6 and 8 would have\ngot reduced when they got\n\n610\n00:35:16,260 --> 00:35:20,380\nstuck into that pair, numerator\nwould select out 3.\n\n611\n00:35:20,380 --> 00:35:23,850\nAnd in the way I just showed\nyou, well, ans would get 6 and\n\n612\n00:35:23,850 --> 00:35:27,650\n8 put in, and then at the point\nwhere I said numerator,\n\n613\n00:35:27,650 --> 00:35:29,770\nsome computation would\nget done to put out\n\n614\n00:35:29,770 --> 00:35:32,590\n3 instead of 6.\n\n615\n00:35:32,590 --> 00:35:34,520\nSo those are two different\nways I might do it.\n\n616\n00:35:34,520 --> 00:35:37,530\nWhich one's better?\n\n617\n00:35:37,530 --> 00:35:38,460\nWell, it depends, right?\n\n618\n00:35:38,460 --> 00:35:41,230\nIf I'm making a system where\nI am mostly constructing\n\n619\n00:35:41,230 --> 00:35:43,240\nrational numbers and hardly\never looking at them, then\n\n620\n00:35:43,240 --> 00:35:46,520\nit's probably better not to do\nthat gcd computation when I\n\n621\n00:35:46,520 --> 00:35:47,776\nconstruct them.\n\n622\n00:35:47,776 --> 00:35:51,070\nIf I'm doing a system where I\nlook at things a lot more than\n\n623\n00:35:51,070 --> 00:35:54,470\nI construct them, then it's\nprobably better to do the work\n\n624\n00:35:54,470 --> 00:35:57,240\nwhen I construct them.\n\n625\n00:35:57,240 --> 00:35:58,170\nSo there's a choice there.\n\n626\n00:35:58,170 --> 00:36:04,840\nBut the real issue is that you\nmight not be able to decide at\n\n627\n00:36:04,840 --> 00:36:07,640\nthe moment you're worrying about\nthese rational numbers.\n\n628\n00:36:07,640 --> 00:36:14,470\nSee, in general, as systems\ndesigners, you're forced with\n\n629\n00:36:14,470 --> 00:36:16,350\nthe necessity to make decisions\nabout how you're\n\n630\n00:36:16,350 --> 00:36:19,640\ngoing to do things, and in\ngeneral, the way you'd like to\n\n631\n00:36:19,640 --> 00:36:22,720\nretain flexibility is to never\nmake up your mind about\n\n632\n00:36:22,720 --> 00:36:26,890\nanything until you're\nforced to do it.\n\n633\n00:36:26,890 --> 00:36:31,730\nThe problem is, there's a very,\nvery narrow line between\n\n634\n00:36:31,730 --> 00:36:34,765\ndeferring decisions and outright\nprocrastination.\n\n635\n00:36:34,765 --> 00:36:38,760\n\n\n636\n00:36:38,760 --> 00:36:43,860\nSo you'd like to make progress,\nbut also at the same\n\n637\n00:36:43,860 --> 00:36:45,020\ntime, never be bound by the\n\n638\n00:36:45,020 --> 00:36:48,620\nconsequences of your decisions.\n\n639\n00:36:48,620 --> 00:36:50,550\nData abstraction's one\nway of doing this.\n\n640\n00:36:50,550 --> 00:36:54,540\nWhat we did is we used\nwishful thinking.\n\n641\n00:36:54,540 --> 00:36:57,190\nSee, we gave a name\nto the decision.\n\n642\n00:36:57,190 --> 00:37:01,340\nWe said, make-RAT, numerator,\nand denominator will stand for\n\n643\n00:37:01,340 --> 00:37:03,040\nhowever it's going to be done,\nand however it's going to be\n\n644\n00:37:03,040 --> 00:37:04,080\ndone is George's problem.\n\n645\n00:37:04,080 --> 00:37:07,100\nBut really, what that was doing\nis giving a name to the\n\n646\n00:37:07,100 --> 00:37:12,030\ndecision of how we're going to\ndo it, and then continuing as\n\n647\n00:37:12,030 --> 00:37:14,400\nif we made the decision.\n\n648\n00:37:14,400 --> 00:37:17,110\nAnd then eventually, when we\nreally wanted it to work,\n\n649\n00:37:17,110 --> 00:37:20,330\ncoming back and facing what\nwe really had to do.\n\n650\n00:37:20,330 --> 00:37:23,080\nAnd in fact, we'll see a couple\ntimes from now that you\n\n651\n00:37:23,080 --> 00:37:25,440\nmay never have to choose any\nparticular representation,\n\n652\n00:37:25,440 --> 00:37:27,800\never, ever.\n\n653\n00:37:27,800 --> 00:37:30,230\nAnyway, that's a very powerful\ndesign technique.\n\n654\n00:37:30,230 --> 00:37:32,295\nIt's the key to the reason\npeople use data abstraction.\n\n655\n00:37:32,295 --> 00:37:34,830\n\n\n656\n00:37:34,830 --> 00:37:37,854\nAnd we're going to see that\nidea again and again.\n\n657\n00:37:37,854 --> 00:37:40,510\nLet's stop for questions.\n\n658\n00:37:40,510 --> 00:37:43,810\nAUDIENCE: What does this\ndecision making through\n\n659\n00:37:43,810 --> 00:37:47,500\nabstraction layers do to the\naxiom of do all your design\n\n660\n00:37:47,500 --> 00:37:49,800\nbefore any of your code?\n\n661\n00:37:49,800 --> 00:37:52,700\nPROFESSOR: Well, that's\nsomeone's axiom, and I bet\n\n662\n00:37:52,700 --> 00:37:54,990\nthat's the axiom of someone who\nhasn't implemented very\n\n663\n00:37:54,990 --> 00:37:56,600\nlarge computer systems\nvery much.\n\n664\n00:37:56,600 --> 00:38:01,220\n\n\n665\n00:38:01,220 --> 00:38:04,116\nI said that computer science is\na lot like magic, and it's\n\n666\n00:38:04,116 --> 00:38:05,270\nsort of good that\nit's like magic.\n\n667\n00:38:05,270 --> 00:38:06,690\nThere's a bad part of\ncomputer science\n\n668\n00:38:06,690 --> 00:38:08,746\nthat's a lot like religion.\n\n669\n00:38:08,746 --> 00:38:13,570\nAnd in general, I think people\nwho really believe that you\n\n670\n00:38:13,570 --> 00:38:16,800\ndesign everything before you\nimplement it basically are\n\n671\n00:38:16,800 --> 00:38:18,440\npeople who haven't designed\nvery many things.\n\n672\n00:38:18,440 --> 00:38:21,230\n\n\n673\n00:38:21,230 --> 00:38:24,660\nThe real power is that you can\npretend that you've made the\n\n674\n00:38:24,660 --> 00:38:28,640\ndecision and then later on\nfigure out which one is right,\n\n675\n00:38:28,640 --> 00:38:30,550\nwhich decision you ought\nto have made.\n\n676\n00:38:30,550 --> 00:38:32,870\nAnd when you can do that, you\nhave the best of both worlds.\n\n677\n00:38:32,870 --> 00:38:35,834\n\n\n678\n00:38:35,834 --> 00:38:37,330\nAUDIENCE: Can you explain\nthe difference\n\n679\n00:38:37,330 --> 00:38:40,180\nbetween let and define?\n\n680\n00:38:40,180 --> 00:38:43,520\nPROFESSOR: Oh, OK.\n\n681\n00:38:43,520 --> 00:38:49,040\nLet is a way to establish\nlocal names.\n\n682\n00:38:49,040 --> 00:38:55,150\n\n\n683\n00:38:55,150 --> 00:38:57,430\nLet me give you sort\nof the half answer.\n\n684\n00:38:57,430 --> 00:39:00,970\nAnd I'll say, later on we can\ntalk about the whole very\n\n685\n00:39:00,970 --> 00:39:02,960\ncomplicated thing.\n\n686\n00:39:02,960 --> 00:39:06,000\nBut the big difference for now\nis that, see, when you're\n\n687\n00:39:06,000 --> 00:39:10,020\ntyping at Lisp, you're typing\nin this environment where\n\n688\n00:39:10,020 --> 00:39:12,020\nyou're making definitions.\n\n689\n00:39:12,020 --> 00:39:18,990\nAnd when you say define a to be\n5, if I say define a to be\n\n690\n00:39:18,990 --> 00:39:25,640\n5, then from then on the thing\nwill remember that a is 5.\n\n691\n00:39:25,640 --> 00:39:29,460\nLet is a way to set up a local\ncontext where there's a\n\n692\n00:39:29,460 --> 00:39:31,090\ndefinition.\n\n693\n00:39:31,090 --> 00:39:37,695\nSo if I type something like,\nsaying let a-- no, I\n\n694\n00:39:37,695 --> 00:39:40,642\nshouldn't say a--\n\n695\n00:39:40,642 --> 00:39:50,480\nif I said let z be 10, and\nwithin that context, tell me\n\n696\n00:39:50,480 --> 00:39:54,280\nwhat the sum of z and z is.\n\n697\n00:39:54,280 --> 00:39:59,780\nSo if I typed in this expression\nto Lisp, and then\n\n698\n00:39:59,780 --> 00:40:02,210\nthis would put out 20.\n\n699\n00:40:02,210 --> 00:40:07,340\nHowever, then if I said what's\nz, the computer would say\n\n700\n00:40:07,340 --> 00:40:10,910\nthat's an unbound variable.\n\n701\n00:40:10,910 --> 00:40:13,710\nSo let is a way of setting up\na context where you can make\n\n702\n00:40:13,710 --> 00:40:16,320\ndefinitions.\n\n703\n00:40:16,320 --> 00:40:19,320\nBut those definitions are\nlocal to this context.\n\n704\n00:40:19,320 --> 00:40:27,990\nAnd of course, if I'd said a\nin here, I'd still get 20.\n\n705\n00:40:27,990 --> 00:40:33,960\nBut this a would not interfere\nat all with this one.\n\n706\n00:40:33,960 --> 00:40:36,210\nSo if I type this, and then type\nthis, and then say what's\n\n707\n00:40:36,210 --> 00:40:39,160\na? a will still be 5.\n\n708\n00:40:39,160 --> 00:40:42,220\nSo there's some other subtle\ndifferences between let and\n\n709\n00:40:42,220 --> 00:40:44,543\ndefine, but that's the\nmost important one.\n\n710\n00:40:44,543 --> 00:41:20,090\n\n\n711\n00:41:20,090 --> 00:41:22,980\nAll right, well, we've looked\nat implementing this little\n\n712\n00:41:22,980 --> 00:41:27,470\nsystem for doing arithmetic on\nrational numbers as an example\n\n713\n00:41:27,470 --> 00:41:31,096\nof this methodology of\ndata abstraction.\n\n714\n00:41:31,096 --> 00:41:34,430\nAnd that's a way of controlling\ncomplexity in\n\n715\n00:41:34,430 --> 00:41:39,530\nlarge systems. But, see, like\nprocedure definition, and like\n\n716\n00:41:39,530 --> 00:41:41,420\nall the ways we're going to\ntalk about for controlling\n\n717\n00:41:41,420 --> 00:41:45,660\ncomplexity, the real power of\nthese things show up not when\n\n718\n00:41:45,660 --> 00:41:49,370\nyou sort of do these things in\nthemselves, like it's not such\n\n719\n00:41:49,370 --> 00:41:52,430\na great thing that we've done\nrational number arithmetic,\n\n720\n00:41:52,430 --> 00:41:57,150\nit's that you can use these as\nbuilding blocks for making\n\n721\n00:41:57,150 --> 00:42:00,620\nmore complicated things.\n\n722\n00:42:00,620 --> 00:42:03,460\nSo it's no wonderful idea that\nyou can just put two numbers\n\n723\n00:42:03,460 --> 00:42:04,265\ntogether to form a pair.\n\n724\n00:42:04,265 --> 00:42:06,890\nIf that's all you ever wanted to\ndo, there are tons of ways\n\n725\n00:42:06,890 --> 00:42:08,450\nthat you can do that.\n\n726\n00:42:08,450 --> 00:42:11,910\nThe real issue is can you do\nthat in such a way so that the\n\n727\n00:42:11,910 --> 00:42:14,420\nthings that you build become\nbuilding blocks for doing\n\n728\n00:42:14,420 --> 00:42:16,945\nsomething even more complex?\n\n729\n00:42:16,945 --> 00:42:19,120\nSo whenever someone shows you\na method for controlling\n\n730\n00:42:19,120 --> 00:42:21,080\ncomplexity, you should say,\nyeah, that's great, but what\n\n731\n00:42:21,080 --> 00:42:22,330\ncan I build with it?\n\n732\n00:42:22,330 --> 00:42:25,290\n\n\n733\n00:42:25,290 --> 00:42:30,490\nSo for example, let me just\nrun through another thing\n\n734\n00:42:30,490 --> 00:42:32,090\nthat's a lot like the\nrational number one.\n\n735\n00:42:32,090 --> 00:42:35,760\nSuppose we would like to\nrepresent points in the plane.\n\n736\n00:42:35,760 --> 00:42:38,130\nYou sort of say, well, there's\na point, and we're going to\n\n737\n00:42:38,130 --> 00:42:40,810\ncall that point p.\n\n738\n00:42:40,810 --> 00:42:48,810\nAnd that point might have\ncoordinates, like this might\n\n739\n00:42:48,810 --> 00:42:50,330\nbe the point 1 comma 2.\n\n740\n00:42:50,330 --> 00:42:52,500\nThe x-coordinate might\nbe 1, and it's\n\n741\n00:42:52,500 --> 00:42:54,370\ny-coordinate might be 2.\n\n742\n00:42:54,370 --> 00:42:57,310\nAnd we'll make a little system\nfor manipulating\n\n743\n00:42:57,310 --> 00:43:00,450\npoints in the plane.\n\n744\n00:43:00,450 --> 00:43:03,040\nAnd again, we can do\nthat-- here's a\n\n745\n00:43:03,040 --> 00:43:04,290\nlittle example of that.\n\n746\n00:43:04,290 --> 00:43:07,070\n\n\n747\n00:43:07,070 --> 00:43:10,080\nIt can represent vectors, the\nsame as points in the plane,\n\n748\n00:43:10,080 --> 00:43:17,550\nand we'll say, yep, there's\na constructor called\n\n749\n00:43:17,550 --> 00:43:21,100\nmake-vector, make-vector's going\nto take two coordinates,\n\n750\n00:43:21,100 --> 00:43:24,280\nand here we can implement them\nif we like as pairs, but the\n\n751\n00:43:24,280 --> 00:43:27,120\nimportant thing is that\nthere's a constructor.\n\n752\n00:43:27,120 --> 00:43:31,890\nAnd then given some vector, p,\nwe can find its x-coordinate,\n\n753\n00:43:31,890 --> 00:43:33,540\nor we can get its\ny-coordinate.\n\n754\n00:43:33,540 --> 00:43:36,270\nSo there's a constructor\nand selectors for\n\n755\n00:43:36,270 --> 00:43:39,010\npoints in the plane.\n\n756\n00:43:39,010 --> 00:43:41,310\nWell, given points in the plane,\nwe might want to use\n\n757\n00:43:41,310 --> 00:43:42,420\nthem to build something.\n\n758\n00:43:42,420 --> 00:43:45,730\nSo for instance, we might want\nto talk about, we might have a\n\n759\n00:43:45,730 --> 00:43:51,220\npoint, p, and a point, q, and p\nmight be the point 1, 2, and\n\n760\n00:43:51,220 --> 00:43:54,790\nq might be the point 2, 3.\n\n761\n00:43:54,790 --> 00:43:58,970\nAnd we might want to talk about\nthe line segment that\n\n762\n00:43:58,970 --> 00:44:01,570\nstarts at p and ends at q.\n\n763\n00:44:01,570 --> 00:44:05,180\nAnd that might be\nthe segment s.\n\n764\n00:44:05,180 --> 00:44:12,300\nSo we might want to build points\nfor vectors in terms of\n\n765\n00:44:12,300 --> 00:44:16,410\nnumbers, and segments\nin terms of vectors.\n\n766\n00:44:16,410 --> 00:44:18,240\nSo we can represent\nline segments in\n\n767\n00:44:18,240 --> 00:44:19,920\nexactly the same way.\n\n768\n00:44:19,920 --> 00:44:22,300\nAll right, so the line segment\nfrom p to q, we'll say there's\n\n769\n00:44:22,300 --> 00:44:23,640\na constructor, make-segment.\n\n770\n00:44:23,640 --> 00:44:27,010\n\n\n771\n00:44:27,010 --> 00:44:30,270\nAnd make up names for the\nselectors, the starting point\n\n772\n00:44:30,270 --> 00:44:32,560\nof the segment and the ending\npoint of the segment.\n\n773\n00:44:32,560 --> 00:44:35,290\nAnd again, we can implement a\nsegment using cons as a pair\n\n774\n00:44:35,290 --> 00:44:39,610\nof points, and car and cdr get\nout the two points that we put\n\n775\n00:44:39,610 --> 00:44:40,860\ntogether to get the segment.\n\n776\n00:44:40,860 --> 00:44:44,820\n\n\n777\n00:44:44,820 --> 00:44:48,520\nWell, now having done that,\nwe can have some\n\n778\n00:44:48,520 --> 00:44:51,920\noperations on them.\n\n779\n00:44:51,920 --> 00:44:57,610\nLike we could say, what's the\nmidpoint of a line segment?\n\n780\n00:44:57,610 --> 00:45:00,540\nSo here's the midpoint of a line\nsegment, that's going to\n\n781\n00:45:00,540 --> 00:45:05,880\nbe the points whose coordinates\nare the averages\n\n782\n00:45:05,880 --> 00:45:07,310\nof the coordinates\nof the endpoints.\n\n783\n00:45:07,310 --> 00:45:10,170\nOK, there's the midpoint.\n\n784\n00:45:10,170 --> 00:45:14,290\nSo to get the midpoint of a line\nsegment, s, we'll just\n\n785\n00:45:14,290 --> 00:45:18,240\nsay grab the starting point to\nthe segment, grab the ending\n\n786\n00:45:18,240 --> 00:45:21,640\npoint of the segment, and\nnow make a vector--\n\n787\n00:45:21,640 --> 00:45:26,480\nmake a point whose coordinates\nare the average of the\n\n788\n00:45:26,480 --> 00:45:28,510\nx-coordinate of the first point\nand the x-coordinate of\n\n789\n00:45:28,510 --> 00:45:31,930\nthe second point, and whose\ny-coordinate is the average of\n\n790\n00:45:31,930 --> 00:45:33,530\nthe y-coordinates.\n\n791\n00:45:33,530 --> 00:45:37,810\nSo there's an implementation\nof midpoint.\n\n792\n00:45:37,810 --> 00:45:42,400\nAnd then similarly, we can\nbuild something like the\n\n793\n00:45:42,400 --> 00:45:44,450\nlength of the segment.\n\n794\n00:45:44,450 --> 00:45:47,070\nThe length of the segment\nis a thing whose--\n\n795\n00:45:47,070 --> 00:45:50,410\n\n\n796\n00:45:50,410 --> 00:45:53,000\nuse Pythagoras's rule, the\nlength of the segment is the\n\n797\n00:45:53,000 --> 00:45:57,100\nsquare root of the d x squared\nplus d y squared.\n\n798\n00:45:57,100 --> 00:46:02,200\nWe'll say to get the length of\na line segment, we'll let dx\n\n799\n00:46:02,200 --> 00:46:09,030\nbe the difference of the\nx-coordinate of one endpoint\n\n800\n00:46:09,030 --> 00:46:12,180\nand the x-coordinate of the\nother endpoint, and we'll let\n\n801\n00:46:12,180 --> 00:46:16,260\ndy be the difference of\nthe y-coordinates.\n\n802\n00:46:16,260 --> 00:46:19,290\nAnd then we'll take the square\nroot of the sum of the squares\n\n803\n00:46:19,290 --> 00:46:22,251\nof dx and dy, that's\nwhat this says.\n\n804\n00:46:22,251 --> 00:46:26,190\nAll right, so there's an\nimplementation of length.\n\n805\n00:46:26,190 --> 00:46:35,760\nAnd again, what we built\nis a layered system.\n\n806\n00:46:35,760 --> 00:46:39,730\nWe built a system which\nhas, well, say up\n\n807\n00:46:39,730 --> 00:46:40,980\nhere there's segments.\n\n808\n00:46:40,980 --> 00:46:47,430\n\n\n809\n00:46:47,430 --> 00:46:50,530\nAnd then there's an abstraction\nbarrier.\n\n810\n00:46:50,530 --> 00:46:56,880\nThe abstraction barrier\nseparates the implementation\n\n811\n00:46:56,880 --> 00:46:59,000\nof segments from the\nimplementation of vectors and\n\n812\n00:46:59,000 --> 00:47:02,950\npoints, and what that\nabstraction barrier is are the\n\n813\n00:47:02,950 --> 00:47:04,260\nconstructors and selectors.\n\n814\n00:47:04,260 --> 00:47:14,340\nIt's make-segment, and\nsegment-start, and\n\n815\n00:47:14,340 --> 00:47:15,590\nsegment-end.\n\n816\n00:47:15,590 --> 00:47:18,030\n\n\n817\n00:47:18,030 --> 00:47:20,120\nAnd then there are vectors.\n\n818\n00:47:20,120 --> 00:47:25,600\nAnd vectors in turn are built\non top of pairs and numbers.\n\n819\n00:47:25,600 --> 00:47:29,670\nSo I'll say pairs and numbers.\n\n820\n00:47:29,670 --> 00:47:33,250\nAnd that has its own abstraction\nbarrier, which is\n\n821\n00:47:33,250 --> 00:47:42,350\nmake-vector, and x-coordinate,\nand y-coordinate.\n\n822\n00:47:42,350 --> 00:47:46,920\n\n\n823\n00:47:46,920 --> 00:47:48,930\nSo we have, again,\na layered system.\n\n824\n00:47:48,930 --> 00:47:52,080\nYou're starting to see that\nthere are layers here.\n\n825\n00:47:52,080 --> 00:47:58,080\nI ought to mention, there is a\nvery important thing that I\n\n826\n00:47:58,080 --> 00:47:59,330\nkind of took for granted.\n\n827\n00:47:59,330 --> 00:48:02,016\n\n\n828\n00:48:02,016 --> 00:48:06,700\nAnd it's sort of so natural, but\non the other hand it's a\n\n829\n00:48:06,700 --> 00:48:07,580\nvery important thing.\n\n830\n00:48:07,580 --> 00:48:12,070\nNotice that in order to\nrepresent this segment s, I\n\n831\n00:48:12,070 --> 00:48:16,600\nsaid this segment is\na pair of points.\n\n832\n00:48:16,600 --> 00:48:19,120\nAnd a point is a pair\nof numbers.\n\n833\n00:48:19,120 --> 00:48:22,180\nAnd if I were going to draw the\nbox and pointers structure\n\n834\n00:48:22,180 --> 00:48:27,180\nfor that, I would say, oh, the\nsegment is, given those\n\n835\n00:48:27,180 --> 00:48:29,900\nparticular representations that\nI showed you, I'd say\n\n836\n00:48:29,900 --> 00:48:38,070\nthis segment s is a pair, and\nthe first thing in the pair is\n\n837\n00:48:38,070 --> 00:48:45,430\na vector, and the vector\nis a pair of numbers.\n\n838\n00:48:45,430 --> 00:48:47,000\nAnd that's this, that's p.\n\n839\n00:48:47,000 --> 00:48:50,190\n\n\n840\n00:48:50,190 --> 00:48:55,330\nAnd the other thing in the\nsegment is q, which is itself\n\n841\n00:48:55,330 --> 00:49:00,100\na pair of numbers.\n\n842\n00:49:00,100 --> 00:49:04,070\nSo I almost took it for granted\nwhen I said that cons\n\n843\n00:49:04,070 --> 00:49:08,960\nallows you to put\nthings together.\n\n844\n00:49:08,960 --> 00:49:13,110\nBut it's very easy to not\nappreciate that, because\n\n845\n00:49:13,110 --> 00:49:17,650\nnotice, some of the things\nI can put together can\n\n846\n00:49:17,650 --> 00:49:20,720\nthemselves be pairs.\n\n847\n00:49:20,720 --> 00:49:23,510\nAnd let me introduce a word that\nI'll talk about more next\n\n848\n00:49:23,510 --> 00:49:26,915\ntime, it's one of my favorite\nwords, called closure.\n\n849\n00:49:26,915 --> 00:49:30,640\n\n\n850\n00:49:30,640 --> 00:49:35,180\nAnd by closure I mean that the\nmeans of combination in your\n\n851\n00:49:35,180 --> 00:49:39,390\nsystem are such that when you\nput things together using\n\n852\n00:49:39,390 --> 00:49:43,430\nthem, like we make a pair, you\ncan then put those together\n\n853\n00:49:43,430 --> 00:49:45,080\nwith the same means\nof combination.\n\n854\n00:49:45,080 --> 00:49:48,120\nSo I can have not only a pair\nof numbers, but I can have a\n\n855\n00:49:48,120 --> 00:49:49,370\npair of pairs.\n\n856\n00:49:49,370 --> 00:49:51,710\n\n\n857\n00:49:51,710 --> 00:49:58,070\nSo for instance, making arrays\nin a language like Fortran is\n\n858\n00:49:58,070 --> 00:50:00,120\nnot a closed means of\ncombination, because I can\n\n859\n00:50:00,120 --> 00:50:02,200\nmake an array of numbers,\nbut I can't\n\n860\n00:50:02,200 --> 00:50:03,450\nmake an array of arrays.\n\n861\n00:50:03,450 --> 00:50:05,790\n\n\n862\n00:50:05,790 --> 00:50:09,060\nAnd one of the things that you\nshould ask, one of your tests\n\n863\n00:50:09,060 --> 00:50:12,430\nof quality for a means of\ncombination that someone shows\n\n864\n00:50:12,430 --> 00:50:16,500\nyou, is gee, are the things\nyou make closed under that\n\n865\n00:50:16,500 --> 00:50:18,340\nmeans of combination?\n\n866\n00:50:18,340 --> 00:50:21,290\nSo pairs would not be nearly so\ninteresting if all I could\n\n867\n00:50:21,290 --> 00:50:23,160\ndo was make a pair of numbers.\n\n868\n00:50:23,160 --> 00:50:26,820\nI couldn't build very much\nstructure at all.\n\n869\n00:50:26,820 --> 00:50:28,170\nOK, well, we'll come\nback to that.\n\n870\n00:50:28,170 --> 00:50:29,300\nI just wanted to\nmention it now.\n\n871\n00:50:29,300 --> 00:50:32,170\nYou'll hear a lot about\nclosure later on.\n\n872\n00:50:32,170 --> 00:50:38,520\nYou can also see the potential\nfor losing control of\n\n873\n00:50:38,520 --> 00:50:41,310\ncomplexity as you have a layered\nsystem if you don't\n\n874\n00:50:41,310 --> 00:50:44,030\nuse data abstraction.\n\n875\n00:50:44,030 --> 00:50:48,130\nLet's go back and look at\nthis slide for length.\n\n876\n00:50:48,130 --> 00:50:53,190\nLength works and is a simple\nthing because I can say, when\n\n877\n00:50:53,190 --> 00:50:56,450\nI want to get this value, I\ncan say, oh, that is the\n\n878\n00:50:56,450 --> 00:51:00,430\nx-coordinate of the first\nendpoint of the segment.\n\n879\n00:51:00,430 --> 00:51:02,990\n\n\n880\n00:51:02,990 --> 00:51:04,850\nAnd each of these things,\neach of these selectors,\n\n881\n00:51:04,850 --> 00:51:09,190\nx-coordinate and endpoint, stand\nfor a decision choice\n\n882\n00:51:09,190 --> 00:51:12,260\nwhose details I don't\nhave to look at.\n\n883\n00:51:12,260 --> 00:51:15,070\nSo I could perfectly well,\nagain, just like rational\n\n884\n00:51:15,070 --> 00:51:17,910\nnumbers I did before, I could\nsay, oh well, gee, a segment\n\n885\n00:51:17,910 --> 00:51:21,180\nreally is a pair of pairs.\n\n886\n00:51:21,180 --> 00:51:24,810\nAnd the x-coordinate of the\nfirst endpoint or the segment\n\n887\n00:51:24,810 --> 00:51:26,770\nreally is the--\n\n888\n00:51:26,770 --> 00:51:27,330\nwell, what is it?\n\n889\n00:51:27,330 --> 00:51:33,890\nIt's the car of the car\nof the segment.\n\n890\n00:51:33,890 --> 00:51:37,500\nSo I could perfectly well\ngo and redefine length.\n\n891\n00:51:37,500 --> 00:51:48,614\nI could say, define the length\nof some segment s.\n\n892\n00:51:48,614 --> 00:51:51,050\nAnd I could start off writing\nsomething like, well, we'll\n\n893\n00:51:51,050 --> 00:51:56,260\nlet dx be-- well, what's\nit have to be?\n\n894\n00:51:56,260 --> 00:51:58,380\nIt's got to be the difference\nof the two coordinates, so\n\n895\n00:51:58,380 --> 00:52:04,310\nthat's the difference of, the\nfirst one is the car of the\n\n896\n00:52:04,310 --> 00:52:13,070\ncar of s, subtracted from the\nfirst one, the car of the\n\n897\n00:52:13,070 --> 00:52:16,140\nother half of it,\nthe cdr of s.\n\n898\n00:52:16,140 --> 00:52:21,530\n\n\n899\n00:52:21,530 --> 00:52:24,430\nAll right, and then\ndy would be--\n\n900\n00:52:24,430 --> 00:52:27,780\nwell, let's see, I'd get the\ny-coordinate, so it'd be the\n\n901\n00:52:27,780 --> 00:52:36,890\ndifference of the cdr of the car\nof s, and the cdr of the\n\n902\n00:52:36,890 --> 00:52:41,385\ncdr of s, sort of go on.\n\n903\n00:52:41,385 --> 00:52:44,210\n\n\n904\n00:52:44,210 --> 00:52:46,980\nYou can see that's much harder\nto read than the\n\n905\n00:52:46,980 --> 00:52:48,270\nprogram I had before.\n\n906\n00:52:48,270 --> 00:52:52,075\nBut worse than that,\nsuppose you'd gone\n\n907\n00:52:52,075 --> 00:52:53,325\nand implemented length?\n\n908\n00:52:53,325 --> 00:52:56,930\n\n\n909\n00:52:56,930 --> 00:52:59,150\nAnd then the next day, George\ncomes to you and says, I'm\n\n910\n00:52:59,150 --> 00:53:01,030\nsorry, I changed my mind.\n\n911\n00:53:01,030 --> 00:53:05,390\nI want to write points with the\nx-coordinate first. So you\n\n912\n00:53:05,390 --> 00:53:06,940\ncome back you stare at\nthis code and say, oh\n\n913\n00:53:06,940 --> 00:53:07,750\ngee, what was that?\n\n914\n00:53:07,750 --> 00:53:15,510\nThat was the car, so I have to\nchange this to cdr, and this\n\n915\n00:53:15,510 --> 00:53:20,770\nis cdr, and this now\nhas to be car.\n\n916\n00:53:20,770 --> 00:53:23,900\nAnd this has to be car.\n\n917\n00:53:23,900 --> 00:53:26,050\nAnd you sort of do that, and\nthen the next day George comes\n\n918\n00:53:26,050 --> 00:53:31,600\nback and says, sorry, the guys\ndesigning the display would\n\n919\n00:53:31,600 --> 00:53:35,740\nlike lines to be painted in the\nopposite direction, so I\n\n920\n00:53:35,740 --> 00:53:37,630\nhave to write the endpoint\nfirst in the order.\n\n921\n00:53:37,630 --> 00:53:39,386\nAnd then you come back and you\nstare at this code, and say,\n\n922\n00:53:39,386 --> 00:53:42,400\ngee, what was it\ntalking about?\n\n923\n00:53:42,400 --> 00:53:45,520\nOh yeah, well I've got to change\nthis one to cdr, and\n\n924\n00:53:45,520 --> 00:53:50,500\nthis one becomes car, this one\ncomes car, and this becomes\n\n925\n00:53:50,500 --> 00:53:50,620\ncdr.\n\n926\n00:53:50,620 --> 00:53:53,340\nAnd you go up and do that, and\nthen the next day, George\n\n927\n00:53:53,340 --> 00:53:55,270\ncomes back and says, I'm sorry,\nwhat I really meant is\n\n928\n00:53:55,270 --> 00:53:58,150\nthat the segments always have\nto be painted from left to\n\n929\n00:53:58,150 --> 00:53:59,660\nright on the screen.\n\n930\n00:53:59,660 --> 00:54:01,800\nAnd then you sort of, it's\nclear, you just go and punch\n\n931\n00:54:01,800 --> 00:54:03,610\nGeorge in the mouth\nat that point.\n\n932\n00:54:03,610 --> 00:54:09,410\nBut you see, as soon as we have\na 10 layer system, you\n\n933\n00:54:09,410 --> 00:54:12,050\nsee how that complexity\nimmediately builds up to the\n\n934\n00:54:12,050 --> 00:54:16,250\npoint where even something like\nthis gets out of control.\n\n935\n00:54:16,250 --> 00:54:20,470\nSo again, the way we've gotten\nout of that is we've named\n\n936\n00:54:20,470 --> 00:54:21,150\nthat spirit.\n\n937\n00:54:21,150 --> 00:54:26,560\nWe built a system where there\nis a thing, which is the\n\n938\n00:54:26,560 --> 00:54:29,510\nrepresentation choice\nfor how you're going\n\n939\n00:54:29,510 --> 00:54:31,570\nto talk about vectors.\n\n940\n00:54:31,570 --> 00:54:34,430\nAnd choices about that\nrepresentation are localized\n\n941\n00:54:34,430 --> 00:54:35,670\nright there.\n\n942\n00:54:35,670 --> 00:54:37,840\nThey don't have their guts\nspilling over into things like\n\n943\n00:54:37,840 --> 00:54:40,926\nhow you compute the length and\nhow you compute the midpoint.\n\n944\n00:54:40,926 --> 00:54:45,660\nAnd that's the real power\nof this system.\n\n945\n00:54:45,660 --> 00:54:48,890\nOK, we're explicit about\nthem, so that we have\n\n946\n00:54:48,890 --> 00:54:50,916\ncontrol over them.\n\n947\n00:54:50,916 --> 00:54:52,190\nAll right, questions?\n\n948\n00:54:52,190 --> 00:54:54,685\nAUDIENCE: What happens in the\ncase where you don't want to\n\n949\n00:54:54,685 --> 00:54:56,660\nbe treating objects\nin terms of pairs?\n\n950\n00:54:56,660 --> 00:55:00,590\nFor instance, in\nthree-dimensional space, you'd\n\n951\n00:55:00,590 --> 00:55:01,680\nhave three coordinates.\n\n952\n00:55:01,680 --> 00:55:02,740\nOr even in the case\nwhere you have\n\n953\n00:55:02,740 --> 00:55:04,180\nn-dimensional space, what happens?\n\n954\n00:55:04,180 --> 00:55:05,140\nPROFESSOR: Right, OK.\n\n955\n00:55:05,140 --> 00:55:08,374\nWell, this is a preview of\nwhat I'll say tomorrow.\n\n956\n00:55:08,374 --> 00:55:15,020\nBut the point is, once you have\ntwo things, you have as\n\n957\n00:55:15,020 --> 00:55:16,972\nmany things as you want.\n\n958\n00:55:16,972 --> 00:55:17,370\nAll right?\n\n959\n00:55:17,370 --> 00:55:19,970\nBecause if I want to make three\nthings, I could start\n\n960\n00:55:19,970 --> 00:55:26,970\nmaking things like a pair whose\nfirst thing is 1, and\n\n961\n00:55:26,970 --> 00:55:31,780\nwhose second thing is another\npair that, say,\n\n962\n00:55:31,780 --> 00:55:34,582\nhas 2 and 3 in it.\n\n963\n00:55:34,582 --> 00:55:35,760\nAnd so on, a hundred things.\n\n964\n00:55:35,760 --> 00:55:37,550\nI can nest them out of pairs.\n\n965\n00:55:37,550 --> 00:55:40,370\nI made a pretty arbitrary\ndecision about how to do it,\n\n966\n00:55:40,370 --> 00:55:41,770\nand you can immediately\nsee there are lots\n\n967\n00:55:41,770 --> 00:55:42,730\nof ways to do that.\n\n968\n00:55:42,730 --> 00:55:45,210\nWhat we'll start talking about\nnext time are conventions for\n\n969\n00:55:45,210 --> 00:55:47,660\nhow to do things like that.\n\n970\n00:55:47,660 --> 00:55:49,730\nBut notice that what this really\ndepends on is I can\n\n971\n00:55:49,730 --> 00:55:51,950\nmake pairs of pairs.\n\n972\n00:55:51,950 --> 00:55:53,380\nIf all I could do was\nmake pairs of\n\n973\n00:55:53,380 --> 00:55:54,630\nnumbers, I'd be stuck.\n\n974\n00:55:54,630 --> 00:56:07,140\n\n\n975\n00:56:07,140 --> 00:56:09,236\nOK.\n\n976\n00:56:09,236 --> 00:56:11,960\nLet's break.\n\n977\n00:56:11,960 --> 00:56:55,580\n[MUSIC PLAYING]\n\n978\n00:56:55,580 --> 00:57:00,210\nAll right, well, we've just gone\noff and done a couple of\n\n979\n00:57:00,210 --> 00:57:03,575\nsimple examples of\ndata abstraction.\n\n980\n00:57:03,575 --> 00:57:05,695\nNow I want to do something\nmore complicated.\n\n981\n00:57:05,695 --> 00:57:08,310\nWe're going to talk about\nwhat it means.\n\n982\n00:57:08,310 --> 00:57:11,590\nAnd this will be harder, because\nit's always much\n\n983\n00:57:11,590 --> 00:57:14,450\nharder in computer programming\nto talk about what something\n\n984\n00:57:14,450 --> 00:57:16,450\nmeans than to go\noff and do it.\n\n985\n00:57:16,450 --> 00:57:22,070\nBut let's go back to almost\nthe very beginning.\n\n986\n00:57:22,070 --> 00:57:27,050\nLet's go back to the point where\nI said, we just assumed\n\n987\n00:57:27,050 --> 00:57:32,370\nthat there were procedures,\nmake-RAT,\n\n988\n00:57:32,370 --> 00:57:38,480\nand numer, and denom.\n\n989\n00:57:38,480 --> 00:57:41,570\nLet's go back to where we had\nthis, at the very beginning,\n\n990\n00:57:41,570 --> 00:57:46,210\nconstructors and selectors,\nand when often defined the\n\n991\n00:57:46,210 --> 00:57:47,210\nrational number arithmetic.\n\n992\n00:57:47,210 --> 00:57:49,700\nAnd remember, I said at that\npoint we were sort of done,\n\n993\n00:57:49,700 --> 00:57:51,990\nexcept for George.\n\n994\n00:57:51,990 --> 00:57:55,920\nWell, what is it that we'd\nactually done at that point?\n\n995\n00:57:55,920 --> 00:57:59,420\nWhat was it that was done?\n\n996\n00:57:59,420 --> 00:58:03,540\nWell, what I want to say is,\nwhat was done after we'd\n\n997\n00:58:03,540 --> 00:58:06,540\nimplemented the operations and\nterms of these, was that we\n\n998\n00:58:06,540 --> 00:58:11,100\nhad defined a rational number\nrepresentation in terms of\n\n999\n00:58:11,100 --> 00:58:12,390\nabstract data.\n\n1000\n00:58:12,390 --> 00:58:17,946\n\n\n1001\n00:58:17,946 --> 00:58:21,090\nWhat do I mean by\nabstract data?\n\n1002\n00:58:21,090 --> 00:58:26,630\nWell, the idea is that at that\npoint, when we had our +RAT\n\n1003\n00:58:26,630 --> 00:58:32,115\nand our *RAT, that any\nimplementation of make-RAT,\n\n1004\n00:58:32,115 --> 00:58:38,000\nand numerator, and denominator\nthat George supplied us with,\n\n1005\n00:58:38,000 --> 00:58:39,520\ncould be the basis for\na rational number\n\n1006\n00:58:39,520 --> 00:58:40,990\nrepresentation.\n\n1007\n00:58:40,990 --> 00:58:44,550\nLike, it wasn't our concern\nwhere you divided through to\n\n1008\n00:58:44,550 --> 00:58:48,980\nget the greatest common\ndenominator, or any of that.\n\n1009\n00:58:48,980 --> 00:58:53,830\nSo the idea is that what we\nbuilt is a rational arithmetic\n\n1010\n00:58:53,830 --> 00:58:57,140\nsystem that would sit on top\nof any representation.\n\n1011\n00:58:57,140 --> 00:58:59,930\nWhat do I mean by any\nrepresentation?\n\n1012\n00:58:59,930 --> 00:59:02,950\nI mean, certainly it can't be\nthe case that all I mean is\n\n1013\n00:59:02,950 --> 00:59:05,130\nGeorge can reach in a bag and\npull out three arbitrary\n\n1014\n00:59:05,130 --> 00:59:10,380\nprocedures and say, well,\nfine, now that's the\n\n1015\n00:59:10,380 --> 00:59:11,960\nimplementation.\n\n1016\n00:59:11,960 --> 00:59:14,080\nThat can't be what I mean.\n\n1017\n00:59:14,080 --> 00:59:18,990\nWhat I've got to mean is that\nthere's some way of saying\n\n1018\n00:59:18,990 --> 00:59:23,950\nwhether three procedures are\ngoing to be suitable as a\n\n1019\n00:59:23,950 --> 00:59:26,690\nbasis for rational number\nrepresentation.\n\n1020\n00:59:26,690 --> 00:59:30,750\nIf we think about it, what\nsuitable might mean is if I\n\n1021\n00:59:30,750 --> 00:59:36,220\nhave to assume something like\nthis, I have to say that if x\n\n1022\n00:59:36,220 --> 00:59:54,130\nis the result of say, doing\nmake-RAT of n and d, then the\n\n1023\n00:59:54,130 --> 01:00:06,400\nnumerator of x divided by\nthe denominator of x is\n\n1024\n01:00:06,400 --> 01:00:09,680\nequal to n over d.\n\n1025\n01:00:09,680 --> 01:00:13,770\nSee, what that is is that's\nGeorge's contract.\n\n1026\n01:00:13,770 --> 01:00:16,520\nWhat we mean by writing a\ncontract for rational numbers,\n\n1027\n01:00:16,520 --> 01:00:18,790\nif you think about it, this\nis the right thing.\n\n1028\n01:00:18,790 --> 01:00:21,510\nAnd the two ones we showed\ndo the right thing.\n\n1029\n01:00:21,510 --> 01:00:25,720\nSee, if I'm taking out greatest\ncommon divisors, it\n\n1030\n01:00:25,720 --> 01:00:28,350\ndoesn't matter whether I take\nthem out or not, or the place\n\n1031\n01:00:28,350 --> 01:00:29,830\nwhere I take them, because\nthe idea is I'm\n\n1032\n01:00:29,830 --> 01:00:32,380\ngoing to divide through.\n\n1033\n01:00:32,380 --> 01:00:33,930\nBut see, this is George's\ncontract.\n\n1034\n01:00:33,930 --> 01:00:37,160\nSo what we really say to George\nis your business is to\n\n1035\n01:00:37,160 --> 01:00:41,703\ngo off and find us three\nprocedures, make-RAT, and\n\n1036\n01:00:41,703 --> 01:00:45,810\nnumerator, and denominator, that\nfulfill this contract for\n\n1037\n01:00:45,810 --> 01:00:46,870\nany choice of n and d.\n\n1038\n01:00:46,870 --> 01:00:51,080\nAnd that's what we mean by we\ncan use that as the basis for\n\n1039\n01:00:51,080 --> 01:00:54,540\na rational number\nrepresentation.\n\n1040\n01:00:54,540 --> 01:00:57,130\nAnd other than that, it fulfills\nthis contract.\n\n1041\n01:00:57,130 --> 01:00:59,292\nWe don't care how he does it.\n\n1042\n01:00:59,292 --> 01:01:00,410\nIt's not our business.\n\n1043\n01:01:00,410 --> 01:01:02,330\nIt's below the layer\nof abstraction.\n\n1044\n01:01:02,330 --> 01:01:07,010\n\n\n1045\n01:01:07,010 --> 01:01:09,980\nIn fact, if we want\nto say, what is a\n\n1046\n01:01:09,980 --> 01:01:13,860\nrational number really?\n\n1047\n01:01:13,860 --> 01:01:16,240\nSee, what's it really, without\nhaving to talk about going\n\n1048\n01:01:16,240 --> 01:01:18,240\nbelow the layer of abstraction,\nwhat we're forced\n\n1049\n01:01:18,240 --> 01:01:24,820\ninto saying is a rational number\nreally is sort of this\n\n1050\n01:01:24,820 --> 01:01:28,830\naxiom, is three procedures,\nmake-RAT, numerator, and\n\n1051\n01:01:28,830 --> 01:01:32,370\ndenominator, that satisfy\nthis axiom.\n\n1052\n01:01:32,370 --> 01:01:34,790\nIn some sense, abstractly,\nthat's what a\n\n1053\n01:01:34,790 --> 01:01:37,080\nrational number is really.\n\n1054\n01:01:37,080 --> 01:01:41,490\n\n\n1055\n01:01:41,490 --> 01:01:44,860\nThat's sort of easy words to\nlisten to, because what you\n\n1056\n01:01:44,860 --> 01:01:47,190\nhave in your head, of course,\nis well, for all this thing\n\n1057\n01:01:47,190 --> 01:01:50,850\nabout saying that's what a\nrational number is really, you\n\n1058\n01:01:50,850 --> 01:01:52,950\nactually just saw that we\nbuilt rational numbers.\n\n1059\n01:01:52,950 --> 01:01:58,830\n\n\n1060\n01:01:58,830 --> 01:02:00,230\nSee, what we really did\nis we built rational\n\n1061\n01:02:00,230 --> 01:02:04,230\nnumbers on top of pairs.\n\n1062\n01:02:04,230 --> 01:02:08,680\n\n\n1063\n01:02:08,680 --> 01:02:11,170\nSo for all I'm saying\nabstractly, we can say a\n\n1064\n01:02:11,170 --> 01:02:15,450\nrational number really\nis just this axiom.\n\n1065\n01:02:15,450 --> 01:02:17,370\nYou can listen to that\ncomfortably, because you're\n\n1066\n01:02:17,370 --> 01:02:20,510\nsaying, well, yeah, but really\nit's actually pairs, and I'm\n\n1067\n01:02:20,510 --> 01:02:24,820\njust annoying you by trying\nto be abstract.\n\n1068\n01:02:24,820 --> 01:02:29,960\nWell, let me, as an antidote for\nthat, let me do something\n\n1069\n01:02:29,960 --> 01:02:32,636\nthat I think is really\ngoing to terrify you.\n\n1070\n01:02:32,636 --> 01:02:36,920\nI mean, it's really going to\nbring you face to face with\n\n1071\n01:02:36,920 --> 01:02:40,090\nthe sort of existential reality\nof this abstraction\n\n1072\n01:02:40,090 --> 01:02:41,490\nthat we're talking about.\n\n1073\n01:02:41,490 --> 01:02:43,250\nAnd what I'm going\nto talk about is,\n\n1074\n01:02:43,250 --> 01:02:45,960\nwhat are pairs really?\n\n1075\n01:02:45,960 --> 01:02:48,710\nSee, what did I tell\nyou about pairs?\n\n1076\n01:02:48,710 --> 01:02:49,420\nI tricked you, right?\n\n1077\n01:02:49,420 --> 01:02:52,115\nI said that Lisp has this\nprimitive called cons that\n\n1078\n01:02:52,115 --> 01:02:53,520\nbuilds pairs.\n\n1079\n01:02:53,520 --> 01:02:56,470\nBut what did I really\ntell you about?\n\n1080\n01:02:56,470 --> 01:03:00,060\nIf you go back and said, let's\nlook on this slide, all I\n\n1081\n01:03:00,060 --> 01:03:04,090\nreally told you about pairs is\nthat there happens to be this\n\n1082\n01:03:04,090 --> 01:03:07,220\nproperty, these properties of\ncons, car, and cdr. And all I\n\n1083\n01:03:07,220 --> 01:03:09,840\nreally said about pairs is that\nthere's a thing called\n\n1084\n01:03:09,840 --> 01:03:14,870\ncons, and a thing called car,\nand a thing called cdr.\n\n1085\n01:03:14,870 --> 01:03:18,080\nAnd it is the case that if I\nbuild cons of x, y and take\n\n1086\n01:03:18,080 --> 01:03:20,710\ncar of it, I get x.\n\n1087\n01:03:20,710 --> 01:03:25,810\nAnd if I build cons of x, y and\nget cdr of it, I get y.\n\n1088\n01:03:25,810 --> 01:03:31,670\nAnd even though I lulled you\ninto thinking that there's\n\n1089\n01:03:31,670 --> 01:03:33,890\nsomething in Lisp that does\nthat, so you pretended you\n\n1090\n01:03:33,890 --> 01:03:36,590\nknew what it was, in fact, I\ndidn't tell you any more about\n\n1091\n01:03:36,590 --> 01:03:39,750\npairs than this tells you\nabout rational numbers.\n\n1092\n01:03:39,750 --> 01:03:41,050\nIt's just some axiom\nfor pairs.\n\n1093\n01:03:41,050 --> 01:03:44,720\n\n\n1094\n01:03:44,720 --> 01:03:51,880\nWell, to drive that home, let me\nreally scare you, and show\n\n1095\n01:03:51,880 --> 01:03:56,120\nyou what we might build\npairs in terms of.\n\n1096\n01:03:56,120 --> 01:04:00,470\nAnd what you're going to see is\nthat we can build rational\n\n1097\n01:04:00,470 --> 01:04:02,960\nnumbers, and line segments, and\nvectors, and all of this\n\n1098\n01:04:02,960 --> 01:04:06,160\nstuff in terms of pairs, and\nwe're going to see below here\n\n1099\n01:04:06,160 --> 01:04:10,680\nthat pairs can be built\nout of nothing at all.\n\n1100\n01:04:10,680 --> 01:04:12,680\nPure abstraction.\n\n1101\n01:04:12,680 --> 01:04:17,800\nSo let me show you on this slide\nan implementation of\n\n1102\n01:04:17,800 --> 01:04:23,080\ncons, car, and cdr. And we'll\nlook at it again in a second,\n\n1103\n01:04:23,080 --> 01:04:26,480\nbut notice that their procedure\ndefinitions of cons,\n\n1104\n01:04:26,480 --> 01:04:29,850\ncar, and cdr, you don't see any\ndata in there, what you\n\n1105\n01:04:29,850 --> 01:04:34,720\nsee is a lambda.\n\n1106\n01:04:34,720 --> 01:04:39,630\nSo cons here is going to\nreturn-- is a procedure that\n\n1107\n01:04:39,630 --> 01:04:44,630\nreturns a procedure, just like\naverage [UNINTELLIGIBLE].\n\n1108\n01:04:44,630 --> 01:04:49,050\nCons of a and b returns a\nprocedure of an argument\n\n1109\n01:04:49,050 --> 01:04:55,265\ncalled pick, and it says, if\npick is equal to 1, I'm going\n\n1110\n01:04:55,265 --> 01:04:59,220\nto return a, and if pick is\nequal to 2, I'm going to\n\n1111\n01:04:59,220 --> 01:05:02,000\nreturn b, and that's what\ncons is going to be.\n\n1112\n01:05:02,000 --> 01:05:04,810\n\n\n1113\n01:05:04,810 --> 01:05:11,600\nCar of a thing x, car of a\npair x, is going to be x\n\n1114\n01:05:11,600 --> 01:05:12,320\napplied to 1.\n\n1115\n01:05:12,320 --> 01:05:13,470\nAnd notice that makes sense.\n\n1116\n01:05:13,470 --> 01:05:16,690\nYou might not understand why or\nhow I'm doing such a thing,\n\n1117\n01:05:16,690 --> 01:05:19,820\nbut at least it makes sense,\nbecause the thing constructed\n\n1118\n01:05:19,820 --> 01:05:24,630\nby cons is a procedure, and\ncar applies that to 1.\n\n1119\n01:05:24,630 --> 01:05:29,370\nAnd similarly, cdr applies\nthat thing to 2.\n\n1120\n01:05:29,370 --> 01:05:33,290\nOK, now I claimed that this is a\nrepresentation of cons, car,\n\n1121\n01:05:33,290 --> 01:05:35,780\nand cdr, and notice there's\nno data in it.\n\n1122\n01:05:35,780 --> 01:05:37,190\nAll right, it's built\nout of air.\n\n1123\n01:05:37,190 --> 01:05:39,600\nIt's just procedures.\n\n1124\n01:05:39,600 --> 01:05:43,660\nThere's no data objects at all\nin that representation.\n\n1125\n01:05:43,660 --> 01:05:45,140\nWell, what could that\npossibly mean?\n\n1126\n01:05:45,140 --> 01:05:49,690\n\n\n1127\n01:05:49,690 --> 01:05:54,990\nWell, if you really believe this\nstuff, then you have to\n\n1128\n01:05:54,990 --> 01:05:58,650\nbelieve that in order to show\nthat that's a representation\n\n1129\n01:05:58,650 --> 01:06:01,390\nfor cons, car, and cdr, all I\nhave to do is show that it\n\n1130\n01:06:01,390 --> 01:06:03,550\nsatisfies the axiom.\n\n1131\n01:06:03,550 --> 01:06:06,070\nSee, all I should have to\nconvince you of is, for\n\n1132\n01:06:06,070 --> 01:06:23,760\nexample, that gee, that car of\ncons of 37 and 49 is 37 for\n\n1133\n01:06:23,760 --> 01:06:28,060\narbitrary values of 37 and 49.\n\n1134\n01:06:28,060 --> 01:06:29,310\nAnd cdr the same way.\n\n1135\n01:06:29,310 --> 01:06:32,070\n\n\n1136\n01:06:32,070 --> 01:06:35,050\nSee, if I really can demonstrate\nto you that that\n\n1137\n01:06:35,050 --> 01:06:38,900\nweird procedure definition, in\nterms of [? air ?], has the\n\n1138\n01:06:38,900 --> 01:06:42,860\nproperty that it satisfies this,\nthen you just have to\n\n1139\n01:06:42,860 --> 01:06:46,520\ngrant me that that is a possible\nimplementation of\n\n1140\n01:06:46,520 --> 01:06:50,030\ncons, car, and cdr, on which I\ncan build everything else.\n\n1141\n01:06:50,030 --> 01:06:50,980\nWell, let's look at that.\n\n1142\n01:06:50,980 --> 01:06:53,820\nAnd this will be practice in\nthe substitution model.\n\n1143\n01:06:53,820 --> 01:06:59,320\n\n\n1144\n01:06:59,320 --> 01:07:00,690\nHow could we check this?\n\n1145\n01:07:00,690 --> 01:07:01,840\nWe sort of know how\nto do that.\n\n1146\n01:07:01,840 --> 01:07:05,920\nIt's just the same substitution\nmodel.\n\n1147\n01:07:05,920 --> 01:07:06,310\nLet's look.\n\n1148\n01:07:06,310 --> 01:07:07,910\nWe start out, and we\nsay, what's car of\n\n1149\n01:07:07,910 --> 01:07:11,120\ncons of 37 and 49?\n\n1150\n01:07:11,120 --> 01:07:11,720\nWhat do we do?\n\n1151\n01:07:11,720 --> 01:07:13,085\nCons is some procedure.\n\n1152\n01:07:13,085 --> 01:07:15,950\n\n\n1153\n01:07:15,950 --> 01:07:19,530\nIts value is cons was a\nprocedure of a and b.\n\n1154\n01:07:19,530 --> 01:07:25,450\nThe thing returned by cons is\nits procedure body with 37 and\n\n1155\n01:07:25,450 --> 01:07:27,370\n49 substituted for\nthe parameters.\n\n1156\n01:07:27,370 --> 01:07:32,770\nIt'll be 37 substituted for a\nand 49 substituted for b.\n\n1157\n01:07:32,770 --> 01:07:36,710\nSo this expression has the\nsame meaning as this\n\n1158\n01:07:36,710 --> 01:07:37,170\nexpression.\n\n1159\n01:07:37,170 --> 01:07:40,410\nIts car of, and the body of\ncons was this thing that\n\n1160\n01:07:40,410 --> 01:07:43,190\nstarted with lambda.\n\n1161\n01:07:43,190 --> 01:07:46,730\nAnd it says, so if pick is equal\nto 1, where pick is this\n\n1162\n01:07:46,730 --> 01:07:50,070\nother argument, if pick is equal\nto 1, it's 37, that's\n\n1163\n01:07:50,070 --> 01:07:55,240\nwhere a was, and if pick\nis equal to 2, it's 49.\n\n1164\n01:07:55,240 --> 01:07:56,410\nSo that's the first step.\n\n1165\n01:07:56,410 --> 01:07:59,460\nI'm just going through\nmechanical substitution.\n\n1166\n01:07:59,460 --> 01:08:01,630\nAnd remember, at this point in\nthe course, if you're confused\n\n1167\n01:08:01,630 --> 01:08:04,190\nabout what things mean, go\nmechanically through the\n\n1168\n01:08:04,190 --> 01:08:05,480\nsubstitution model.\n\n1169\n01:08:05,480 --> 01:08:07,920\nWell, what is this reduced to?\n\n1170\n01:08:07,920 --> 01:08:15,050\nCar said, take your argument,\nwhich in this case is this,\n\n1171\n01:08:15,050 --> 01:08:16,060\nand apply it to 1.\n\n1172\n01:08:16,060 --> 01:08:17,979\nThat was the definition\nof car.\n\n1173\n01:08:17,979 --> 01:08:22,600\nSo if I look at car, if I do\nthat, the answer is, well,\n\n1174\n01:08:22,600 --> 01:08:24,470\nit's that argument, this\nwas the argument to\n\n1175\n01:08:24,470 --> 01:08:26,319\ncar, applied to 1.\n\n1176\n01:08:26,319 --> 01:08:29,580\n\n\n1177\n01:08:29,580 --> 01:08:31,140\nWell, what does that mean?\n\n1178\n01:08:31,140 --> 01:08:34,800\nI take 1, and I substitute it\nin the body here for this\n\n1179\n01:08:34,800 --> 01:08:36,630\nvalue of pick, which\nis the name of the\n\n1180\n01:08:36,630 --> 01:08:39,779\nargument, what do I get?\n\n1181\n01:08:39,779 --> 01:08:43,390\nWell, I get the thing that says\nif 1 equals 1 it's 37,\n\n1182\n01:08:43,390 --> 01:08:46,700\nand if 1 equals 2 it's 49,\nso the answer's 37.\n\n1183\n01:08:46,700 --> 01:08:49,880\nAnd similarly, if I'd taken cdr,\nthat would apply it to 2,\n\n1184\n01:08:49,880 --> 01:08:51,729\nand I'd get 49.\n\n1185\n01:08:51,729 --> 01:08:55,020\nSo you see, what I've\ndemonstrated is that that\n\n1186\n01:08:55,020 --> 01:08:57,560\ncompletely weird implementation\nof cons, car,\n\n1187\n01:08:57,560 --> 01:09:02,000\nand cdr, satisfies the axioms.\nSo it's a perfectly valid way\n\n1188\n01:09:02,000 --> 01:09:04,100\nof building, in fact, all of the\ndata objects we're going\n\n1189\n01:09:04,100 --> 01:09:05,620\nto see in Lisp.\n\n1190\n01:09:05,620 --> 01:09:07,930\nSo they all, if you like,\ncan be built on sort of\n\n1191\n01:09:07,930 --> 01:09:09,670\nexistential nothing.\n\n1192\n01:09:09,670 --> 01:09:14,229\nAnd as far as you know,\nthat's how it works.\n\n1193\n01:09:14,229 --> 01:09:15,149\nYou couldn't tell.\n\n1194\n01:09:15,149 --> 01:09:18,580\nIf all you're ever going to do\nwith pairs is construct them\n\n1195\n01:09:18,580 --> 01:09:20,890\nwith cons and look at them with\ncar and cdr, you couldn't\n\n1196\n01:09:20,890 --> 01:09:24,270\npossibly tell how this\nthing works.\n\n1197\n01:09:24,270 --> 01:09:26,370\nNow, it might give you a sort\nof warm feeling inside if I\n\n1198\n01:09:26,370 --> 01:09:29,470\nsay, well, yeah, in fact, for\nvarious reasons there happens\n\n1199\n01:09:29,470 --> 01:09:32,930\nto be a primitive called cons,\ncar, and cdr, and if it's too\n\n1200\n01:09:32,930 --> 01:09:35,330\nscary, if this kind of stuff is\ntoo scary, you don't have\n\n1201\n01:09:35,330 --> 01:09:36,770\nto look inside of it.\n\n1202\n01:09:36,770 --> 01:09:40,060\nSo that might make you feel\nbetter, but the point is, it\n\n1203\n01:09:40,060 --> 01:09:42,910\nreally could work this way,\nand it wouldn't make any\n\n1204\n01:09:42,910 --> 01:09:46,590\ndifference to the\nsystem at all.\n\n1205\n01:09:46,590 --> 01:09:48,979\nSo in some sense, we don't\nneed data at all to build\n\n1206\n01:09:48,979 --> 01:09:51,760\nthese data abstractions.\n\n1207\n01:09:51,760 --> 01:09:54,860\nWe can do everything in\nterms of procedures.\n\n1208\n01:09:54,860 --> 01:09:57,500\nOK, well, why did I terrify\nyou in this way?\n\n1209\n01:09:57,500 --> 01:09:59,660\nFirst, I really want to\nreinforce this idea of\n\n1210\n01:09:59,660 --> 01:10:03,670\nabstraction, that you really\ncan do these things\n\n1211\n01:10:03,670 --> 01:10:06,220\nabstractly.\n\n1212\n01:10:06,220 --> 01:10:10,640\nSecondly, I want to introduce\nan idea we're going to see\n\n1213\n01:10:10,640 --> 01:10:15,190\nmore and more of in this course,\nwhich is we're going\n\n1214\n01:10:15,190 --> 01:10:17,440\nto blur the line between\nwhat's data\n\n1215\n01:10:17,440 --> 01:10:19,715\nand what's a procedure.\n\n1216\n01:10:19,715 --> 01:10:22,350\nSee, in this funny\nimplementation it turned out\n\n1217\n01:10:22,350 --> 01:10:26,340\nthat cons of something happened\nto be represented in\n\n1218\n01:10:26,340 --> 01:10:29,080\nterms of a procedure, even\nthough we think of it as data.\n\n1219\n01:10:29,080 --> 01:10:31,940\n\n\n1220\n01:10:31,940 --> 01:10:35,360\nWhile here that's sort of a\nmathematical trick, but one of\n\n1221\n01:10:35,360 --> 01:10:38,050\nthe things we'll see is that\na lot of the very important\n\n1222\n01:10:38,050 --> 01:10:42,150\nprogramming techniques that\nwe're going to get to sort of\n\n1223\n01:10:42,150 --> 01:10:45,840\ndepend very crucially on\nblurring this traditional line\n\n1224\n01:10:45,840 --> 01:10:47,940\nbetween what you consider\na procedure and what you\n\n1225\n01:10:47,940 --> 01:10:48,950\nconsider data.\n\n1226\n01:10:48,950 --> 01:10:50,060\nWe're going to see more\nand more of that,\n\n1227\n01:10:50,060 --> 01:10:52,495\nespecially next time.\n\n1228\n01:10:52,495 --> 01:10:55,190\nOK, questions?\n\n1229\n01:10:55,190 --> 01:10:57,290\nAUDIENCE: If you asked\nthe system to print\n\n1230\n01:10:57,290 --> 01:11:00,720\na, what would happen?\n\n1231\n01:11:00,720 --> 01:11:04,570\nPROFESSOR: The question is, what\nwould happen if I asked\n\n1232\n01:11:04,570 --> 01:11:05,600\nthe system to print a.\n\n1233\n01:11:05,600 --> 01:11:10,200\nGiven this representation, you\nalready know the answer.\n\n1234\n01:11:10,200 --> 01:11:16,360\nThe answer is compound\nprocedure a,\n\n1235\n01:11:16,360 --> 01:11:18,485\njust like last time.\n\n1236\n01:11:18,485 --> 01:11:21,170\n\n\n1237\n01:11:21,170 --> 01:11:22,590\nIt'd say compound procedure.\n\n1238\n01:11:22,590 --> 01:11:25,150\n\n\n1239\n01:11:25,150 --> 01:11:26,420\nIt might say a little\nbit more.\n\n1240\n01:11:26,420 --> 01:11:28,250\nIt might say compound procedure\nlambda or something\n\n1241\n01:11:28,250 --> 01:11:31,730\nor other, depending on details\nof how I named it.\n\n1242\n01:11:31,730 --> 01:11:33,070\nBut it's a procedure.\n\n1243\n01:11:33,070 --> 01:11:35,790\nAnd the only reason for that is\nI haven't told the system\n\n1244\n01:11:35,790 --> 01:11:40,220\nanything special about how\nto print such things.\n\n1245\n01:11:40,220 --> 01:11:43,500\nNow, it's in fact true that with\nthe actual implementation\n\n1246\n01:11:43,500 --> 01:11:45,630\nof cons that to be built in\nthe system, it would print\n\n1247\n01:11:45,630 --> 01:11:46,840\nsomething else.\n\n1248\n01:11:46,840 --> 01:11:48,890\nIt would print, say,\nthis is a pair.\n\n1249\n01:11:48,890 --> 01:11:53,500\n\n\n1250\n01:11:53,500 --> 01:11:58,870\nAUDIENCE: When you define cons,\nand then you pass it\n\n1251\n01:11:58,870 --> 01:12:03,840\ninto values, how does it know\nwhere to look for the cons,\n\n1252\n01:12:03,840 --> 01:12:07,220\nbecause you can use cons\nover and over again?\n\n1253\n01:12:07,220 --> 01:12:11,442\nHow does it know where to look\nto know which a and b it's\n\n1254\n01:12:11,442 --> 01:12:13,500\nsupposed to pull back out?\n\n1255\n01:12:13,500 --> 01:12:17,140\nI don't know if I'm expressing\nthat quite right.\n\n1256\n01:12:17,140 --> 01:12:19,120\nWhere is it stored?\n\n1257\n01:12:19,120 --> 01:12:24,760\nPROFESSOR: OK, the question is,\nI sort of have a cons with\n\n1258\n01:12:24,760 --> 01:12:27,880\na 37 and a 49, and I might make\nanother cons with a 1 and\n\n1259\n01:12:27,880 --> 01:12:30,200\na 2, and I might have one\ncalled a, and I might\n\n1260\n01:12:30,200 --> 01:12:31,920\nhave one called b.\n\n1261\n01:12:31,920 --> 01:12:33,400\nAnd the question is,\nhow does it know?\n\n1262\n01:12:33,400 --> 01:12:35,275\nAnd why don't they\nget confused?\n\n1263\n01:12:35,275 --> 01:12:37,510\nAnd that's a very\ngood question.\n\n1264\n01:12:37,510 --> 01:12:40,820\n\n\n1265\n01:12:40,820 --> 01:12:43,280\nSee, you have to really believe\nthat the procedures\n\n1266\n01:12:43,280 --> 01:12:45,550\nare objects.\n\n1267\n01:12:45,550 --> 01:12:46,725\nIt's sort of like saying--\nlet's try\n\n1268\n01:12:46,725 --> 01:12:49,340\nanother simpler example.\n\n1269\n01:12:49,340 --> 01:12:51,190\nSuppose I ask for the\nsquare root of 3.\n\n1270\n01:12:51,190 --> 01:12:55,760\n\n\n1271\n01:12:55,760 --> 01:12:59,220\nSo I asked for the square root\nof 5, and then I ask for the\n\n1272\n01:12:59,220 --> 01:13:06,470\nsquare of 20.\n\n1273\n01:13:06,470 --> 01:13:09,050\nYou're probably not the least\nbit bothered that I can take\n\n1274\n01:13:09,050 --> 01:13:11,470\nsquare root and apply it to 5,\nand then I can take square\n\n1275\n01:13:11,470 --> 01:13:14,880\nroot and apply it to 20.\n\n1276\n01:13:14,880 --> 01:13:16,980\nAnd there's sort of no issue,\ngee, doesn't it get confused\n\n1277\n01:13:16,980 --> 01:13:19,630\nabout whether it's working\non 5 or 20?\n\n1278\n01:13:19,630 --> 01:13:23,120\nThere's no issue about that\nbecause you're thinking of a\n\n1279\n01:13:23,120 --> 01:13:26,600\nprocedure which goes off\nand does something.\n\n1280\n01:13:26,600 --> 01:13:30,410\nNow, in some sense you're asking\nme the same question.\n\n1281\n01:13:30,410 --> 01:13:32,940\nBut it's really bothering you,\nand it's bothering you for a\n\n1282\n01:13:32,940 --> 01:13:34,140\nreally good reason.\n\n1283\n01:13:34,140 --> 01:13:37,150\nBecause when I write that,\nyou're saying gee, this is, I\n\n1284\n01:13:37,150 --> 01:13:38,300\nknow, sort of a procedure.\n\n1285\n01:13:38,300 --> 01:13:40,250\nBut it's not a procedure\nthat's just running.\n\n1286\n01:13:40,250 --> 01:13:42,600\nIt's just sort of a procedure\nsitting there.\n\n1287\n01:13:42,600 --> 01:13:45,570\nAnd how can it be that sometimes\nthis procedure has\n\n1288\n01:13:45,570 --> 01:13:49,540\n37 and 49, and there might be\nanother one which has 5 and 6\n\n1289\n01:13:49,540 --> 01:13:52,630\nin there, and why don't\nthey get confused?\n\n1290\n01:13:52,630 --> 01:13:55,910\nSo there's something very,\nvery important that's\n\n1291\n01:13:55,910 --> 01:13:58,990\nbothering you.\n\n1292\n01:13:58,990 --> 01:14:01,380\nAnd it's really crucial\nto what's going on.\n\n1293\n01:14:01,380 --> 01:14:05,870\nWe're suddenly saying that\nprocedures are not just the\n\n1294\n01:14:05,870 --> 01:14:08,290\nact of doing something.\n\n1295\n01:14:08,290 --> 01:14:12,310\nProcedures are conceptual\nentities, objects, and if I\n\n1296\n01:14:12,310 --> 01:14:16,080\nbuilt cons of 37 and 49, that's\na particular procedure\n\n1297\n01:14:16,080 --> 01:14:18,070\nthat sits there.\n\n1298\n01:14:18,070 --> 01:14:21,490\nAnd it's different from\ncons of 3 and 4.\n\n1299\n01:14:21,490 --> 01:14:23,020\nThat's another procedure\nthat sits there.\n\n1300\n01:14:23,020 --> 01:14:24,060\nAUDIENCE: Both of them\nexist independently.\n\n1301\n01:14:24,060 --> 01:14:25,610\nPROFESSOR: And exists\nindependently.\n\n1302\n01:14:25,610 --> 01:14:28,370\nAUDIENCE: And they both can be\nreferenced by car and cdr.\n\n1303\n01:14:28,370 --> 01:14:30,350\nPROFESSOR: And they both would\nbe referenced by car and cdr.\n\n1304\n01:14:30,350 --> 01:14:35,500\nJust like I could increment\nthis, and I\n\n1305\n01:14:35,500 --> 01:14:38,270\ncould increment that.\n\n1306\n01:14:38,270 --> 01:14:39,960\nThey're objects.\n\n1307\n01:14:39,960 --> 01:14:41,730\nAnd that's sort of where\nwe're going.\n\n1308\n01:14:41,730 --> 01:14:43,660\nSee, the fact that you're asking\nthe question shows that\n\n1309\n01:14:43,660 --> 01:14:46,330\nyou're really starting to think\nabout the implications\n\n1310\n01:14:46,330 --> 01:14:47,790\nof what's going on.\n\n1311\n01:14:47,790 --> 01:14:50,820\nIt's the difference between\nsaying a procedure is just the\n\n1312\n01:14:50,820 --> 01:14:53,070\nact of doing something.\n\n1313\n01:14:53,070 --> 01:14:56,270\nAnd a procedure is a real object\nthat has existence.\n\n1314\n01:14:56,270 --> 01:14:58,550\nAUDIENCE: So when the procedure\ngets built, the\n\n1315\n01:14:58,550 --> 01:15:01,930\nactual values are now\nsubstituted for a and b--\n\n1316\n01:15:01,930 --> 01:15:02,050\nPROFESSOR: That's right.\n\n1317\n01:15:02,050 --> 01:15:04,870\nAUDIENCE: And then that\nprocedure exists as lambda,\n\n1318\n01:15:04,870 --> 01:15:07,720\nand pick is what's actually\npassed in.\n\n1319\n01:15:07,720 --> 01:15:11,850\nPROFESSOR: Yes, when cons gets\ncalled, and the result of cons\n\n1320\n01:15:11,850 --> 01:15:14,260\nis a new procedure that's\nconstructed, that new\n\n1321\n01:15:14,260 --> 01:15:17,440\nprocedure has an argument\nthat's called pick.\n\n1322\n01:15:17,440 --> 01:15:18,830\nAUDIENCE: But it no longer\nhas an a and b.\n\n1323\n01:15:18,830 --> 01:15:20,416\nThe a and b are the\nactual values\n\n1324\n01:15:20,416 --> 01:15:20,820\nthat are passed through.\n\n1325\n01:15:20,820 --> 01:15:23,280\nPROFESSOR: And it has-- right,\naccording to the substitution\n\n1326\n01:15:23,280 --> 01:15:26,340\nmodel, what it now has is not\nthose arbitrary names a and b,\n\n1327\n01:15:26,340 --> 01:15:31,560\nit somehow has that 37\nand 49 in there.\n\n1328\n01:15:31,560 --> 01:15:33,520\nBut you're right, that's a hard\nthing to think about it,\n\n1329\n01:15:33,520 --> 01:15:35,150\nand it's different from the way\nyou've been thinking about\n\n1330\n01:15:35,150 --> 01:15:36,500\nprocedures.\n\n1331\n01:15:36,500 --> 01:15:39,285\nAUDIENCE: And if I have again\ncons of 37 and 49, it's a\n\n1332\n01:15:39,285 --> 01:15:41,300\ndifferent [UNINTELLIGIBLE]?\n\n1333\n01:15:41,300 --> 01:15:51,790\nPROFESSOR: And if you make\nanother cons of 37 and 49,\n\n1334\n01:15:51,790 --> 01:15:54,390\nyou're into a wonderful\nphilosophical problem, which\n\n1335\n01:15:54,390 --> 01:15:57,870\nis going to be what the lecture\nabout halfway through\n\n1336\n01:15:57,870 --> 01:16:00,080\nthis course is about.\n\n1337\n01:16:00,080 --> 01:16:03,810\nWhich is, if I cons 37 and 49,\nand I do it again, is that the\n\n1338\n01:16:03,810 --> 01:16:06,490\nsame thing, or is it\na different thing?\n\n1339\n01:16:06,490 --> 01:16:07,680\nAnd how could you tell?\n\n1340\n01:16:07,680 --> 01:16:10,240\nAnd when could it\npossibly matter?\n\n1341\n01:16:10,240 --> 01:16:18,110\nAnd that's sort of like\nsaying, is that the\n\n1342\n01:16:18,110 --> 01:16:21,140\nsame thing as this?\n\n1343\n01:16:21,140 --> 01:16:23,850\nOr is this the same\nthing as that?\n\n1344\n01:16:23,850 --> 01:16:25,150\nIt's the same kind\nof question.\n\n1345\n01:16:25,150 --> 01:16:27,930\nAnd that's a very, very\ndeep question.\n\n1346\n01:16:27,930 --> 01:16:30,180\nAnd I can't answer in\nless than an hour.\n\n1347\n01:16:30,180 --> 01:16:31,770\nBut we will.\n\n1348\n01:16:31,770 --> 01:16:45,972\n\n"
  },
  {
    "path": "SrtEN/lec3a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:04,470\n\n\n1\n00:00:04,470 --> 00:00:21,130\n[MUSIC PLAYING]\n\n2\n00:00:21,130 --> 00:00:24,770\nPROFESSOR: Well, last time we\ntalked about compound data,\n\n3\n00:00:24,770 --> 00:00:29,800\nand there were two main points\nto that business.\n\n4\n00:00:29,800 --> 00:00:31,640\nFirst of all, there was\na methodology of data\n\n5\n00:00:31,640 --> 00:00:35,010\nabstraction, and the point of\nthat was that you could\n\n6\n00:00:35,010 --> 00:00:40,500\nisolate the way that data\nobjects are used from the way\n\n7\n00:00:40,500 --> 00:00:43,170\nthat they're represented: this\nidea that there's this guy,\n\n8\n00:00:43,170 --> 00:00:45,600\nGeorge, and you go out make a\ncontract with him; and it's\n\n9\n00:00:45,600 --> 00:00:47,800\nhis business to represent the\ndata objects; and at the\n\n10\n00:00:47,800 --> 00:00:49,880\nmoment you are using them,\nyou don't think\n\n11\n00:00:49,880 --> 00:00:52,220\nabout George's problem.\n\n12\n00:00:52,220 --> 00:00:55,460\nAnd then secondly, there was\nthis particular way that Lisp\n\n13\n00:00:55,460 --> 00:01:00,770\nhas of gluing together things to\nform objects called pairs,\n\n14\n00:01:00,770 --> 00:01:03,870\nand that's done with cons, car\nand cdr. And the way that\n\n15\n00:01:03,870 --> 00:01:06,480\ncons, car and cdr are\nimplemented is basically\n\n16\n00:01:06,480 --> 00:01:07,790\nirrelevant.\n\n17\n00:01:07,790 --> 00:01:09,230\nThat's sort of George's\nproblem of how\n\n18\n00:01:09,230 --> 00:01:10,030\nto build those things.\n\n19\n00:01:10,030 --> 00:01:11,160\nIt could be done\nas primitives.\n\n20\n00:01:11,160 --> 00:01:13,780\nIt could be done using\nprocedures in some weird way,\n\n21\n00:01:13,780 --> 00:01:16,210\nbut we're not going to\nworry about that.\n\n22\n00:01:16,210 --> 00:01:20,230\nAnd as an example, we looked at\nrational number arithmetic.\n\n23\n00:01:20,230 --> 00:01:21,800\nWe looked at vectors,\nand here's\n\n24\n00:01:21,800 --> 00:01:24,160\njust a review of vectors.\n\n25\n00:01:24,160 --> 00:01:28,355\nHere's an operation that takes\nthe sum of of two vectors, so\n\n26\n00:01:28,355 --> 00:01:32,390\nwe want to add this vector, v1,\nand this vector, v2, and\n\n27\n00:01:32,390 --> 00:01:34,680\nwe get the sum.\n\n28\n00:01:34,680 --> 00:01:39,120\nAnd the sum is the vector whose\ncoordinates are the sum\n\n29\n00:01:39,120 --> 00:01:41,380\nof the coordinates of the\npieces you're adding.\n\n30\n00:01:41,380 --> 00:01:45,440\nSo I can say, to define\nmake-vect, right, to add two\n\n31\n00:01:45,440 --> 00:01:50,710\nvectors I make a vector, whose x\ncoordinate is the sum of the\n\n32\n00:01:50,710 --> 00:01:53,810\ntwo x coordinates, and whose y\ncoordinate is the sum of the\n\n33\n00:01:53,810 --> 00:01:56,760\ntwo y coordinates.\n\n34\n00:01:56,760 --> 00:02:03,520\nAnd then similarly, we could\nhave an operation that scales\n\n35\n00:02:03,520 --> 00:02:09,449\nvectors, so here's a procedure\nscale that multiplies a\n\n36\n00:02:09,449 --> 00:02:13,160\nvector, v, by some number, s.\n\n37\n00:02:13,160 --> 00:02:17,270\nSo here's v, v goes from there\nto there and I scale v, and I\n\n38\n00:02:17,270 --> 00:02:21,520\nget a vector in the same\ndirection that's longer.\n\n39\n00:02:21,520 --> 00:02:23,850\nAnd again, to scale a vector,\nI multiply the successive\n\n40\n00:02:23,850 --> 00:02:24,320\ncoordinates.\n\n41\n00:02:24,320 --> 00:02:29,090\nSo I make a vector, whose x\ncoordinate is the scale factor\n\n42\n00:02:29,090 --> 00:02:31,900\ntimes the x coordinate and\nwhose y coordinate is the\n\n43\n00:02:31,900 --> 00:02:34,340\nscale factor times\nthe y coordinate.\n\n44\n00:02:34,340 --> 00:02:38,970\nSo those are two operations that\nare implemented using the\n\n45\n00:02:38,970 --> 00:02:40,570\nrepresentation of vectors.\n\n46\n00:02:40,570 --> 00:02:42,900\nAnd the representation of\nvectors, for instance, is\n\n47\n00:02:42,900 --> 00:02:45,640\nsomething that we can build\nin terms of pairs.\n\n48\n00:02:45,640 --> 00:02:48,760\nSo George has gone out and\nimplemented for us make-vector\n\n49\n00:02:48,760 --> 00:02:53,960\nand x coordinate and y\ncoordinate, and this could be\n\n50\n00:02:53,960 --> 00:03:04,380\ndone, for instance, using cons,\ncar and cdr; and notice\n\n51\n00:03:04,380 --> 00:03:08,320\nhere, I wrote this in a slightly\ndifferent way.\n\n52\n00:03:08,320 --> 00:03:10,660\nThe procedures we've seen\nbefore, I've said something\n\n53\n00:03:10,660 --> 00:03:16,170\nlike say, make-vector of x\nand y: cons of x and y.\n\n54\n00:03:16,170 --> 00:03:18,870\nAnd here I just wrote\nmake-vector cons.\n\n55\n00:03:18,870 --> 00:03:20,920\nAnd that means something\nslightly different.\n\n56\n00:03:20,920 --> 00:03:23,990\nPreviously we'd say, define\nmake-vector to be a procedure\n\n57\n00:03:23,990 --> 00:03:26,870\nthat takes two arguments,\nx and y, and does\n\n58\n00:03:26,870 --> 00:03:28,150\ncons of x and y.\n\n59\n00:03:28,150 --> 00:03:32,870\nAnd here I am saying define\nmake-vector to be the thing\n\n60\n00:03:32,870 --> 00:03:38,630\nthat cons is, and that's almost\nthe same as the other\n\n61\n00:03:38,630 --> 00:03:39,670\nway we've been writing things.\n\n62\n00:03:39,670 --> 00:03:43,510\nAnd I just want you to get\nused to the idea that\n\n63\n00:03:43,510 --> 00:03:46,360\nprocedures can be objects, and\nthat you can name them.\n\n64\n00:03:46,360 --> 00:03:48,960\n\n\n65\n00:03:48,960 --> 00:03:52,640\nOK, well there's vector\nrepresentation, and again, if\n\n66\n00:03:52,640 --> 00:03:54,650\nthat was all there was\nto it, this would\n\n67\n00:03:54,650 --> 00:03:56,666\nall be pretty boring.\n\n68\n00:03:56,666 --> 00:04:00,290\nAnd the point is, remember, that\nyou can use cons to glue\n\n69\n00:04:00,290 --> 00:04:02,790\ntogether not just numbers to\nform pairs, but to glue\n\n70\n00:04:02,790 --> 00:04:04,270\ntogether arbitrary things.\n\n71\n00:04:04,270 --> 00:04:11,500\nSo for instance, if we'd like\nto represent a line segment,\n\n72\n00:04:11,500 --> 00:04:16,959\nsay the line segment that goes\nfrom a certain vector: say,\n\n73\n00:04:16,959 --> 00:04:27,160\nthe segment from the vector 2,3\nto the point represented\n\n74\n00:04:27,160 --> 00:04:28,270\nby the vector 5,1.\n\n75\n00:04:28,270 --> 00:04:33,770\nIf we want to represent that\nline segment, then we can\n\n76\n00:04:33,770 --> 00:04:35,785\nbuild that as a pair of pairs.\n\n77\n00:04:35,785 --> 00:04:41,130\n\n\n78\n00:04:41,130 --> 00:04:42,990\nSo again, we can represent\nline segments.\n\n79\n00:04:42,990 --> 00:04:48,150\nWe can make a constructor that\nmakes a segment using cons,\n\n80\n00:04:48,150 --> 00:04:50,760\nselects out the start of a\nsegment, selects out the end\n\n81\n00:04:50,760 --> 00:04:57,310\npoint of the segment; and then\nif we actually look at that,\n\n82\n00:04:57,310 --> 00:05:00,040\nif we peel away the abstraction\nlayers, and say\n\n83\n00:05:00,040 --> 00:05:05,160\nwhat's that really is a pair\nof pairs, we'd say\n\n84\n00:05:05,160 --> 00:05:06,290\nwell that's a pair.\n\n85\n00:05:06,290 --> 00:05:07,540\nHere's the segment.\n\n86\n00:05:07,540 --> 00:05:10,320\n\n\n87\n00:05:10,320 --> 00:05:15,030\nIt's car, right, it's car\npointer is a pair, and it's\n\n88\n00:05:15,030 --> 00:05:21,130\ncdr is also a pair, and then\nwhat the car is-- here's the\n\n89\n00:05:21,130 --> 00:05:26,110\ncar, that itself is\na pair of 2 and 3.\n\n90\n00:05:26,110 --> 00:05:28,090\nAnd similarly the cdr is\na pair of 2 and 3.\n\n91\n00:05:28,090 --> 00:05:30,800\nAnd let me remind you again,\nthat a lot of people have some\n\n92\n00:05:30,800 --> 00:05:35,110\nidea that if I'd taken this\narrow and somehow written it\n\n93\n00:05:35,110 --> 00:05:36,870\nto point down, that would\nmean something else.\n\n94\n00:05:36,870 --> 00:05:38,980\nThat's irrelevant.\n\n95\n00:05:38,980 --> 00:05:40,900\nIt's only how these are\nconnected and not whether this\n\n96\n00:05:40,900 --> 00:05:43,280\narrow happens to go vertically\nor horizontally.\n\n97\n00:05:43,280 --> 00:05:47,770\n\n\n98\n00:05:47,770 --> 00:05:49,930\nAnd again just to remind\nyou, there was\n\n99\n00:05:49,930 --> 00:05:52,860\nthis notion of closure.\n\n100\n00:05:52,860 --> 00:06:02,900\nSee, closure was the thing\nthat allowed us to start\n\n101\n00:06:02,900 --> 00:06:06,910\nbuilding up complexity, that\ndidn't trap us in pairs.\n\n102\n00:06:06,910 --> 00:06:12,610\nParticularly what I mean is\nthe things that we make,\n\n103\n00:06:12,610 --> 00:06:16,970\nhaving combined things using\ncons to get a pair, those\n\n104\n00:06:16,970 --> 00:06:21,330\nthings themselves can be\ncombined using cons to make\n\n105\n00:06:21,330 --> 00:06:23,800\nmore complicated things.\n\n106\n00:06:23,800 --> 00:06:27,360\nOr as a mathematician might say,\nthe set of data objects\n\n107\n00:06:27,360 --> 00:06:34,130\nin List is closed under the\noperation of forming pairs.\n\n108\n00:06:34,130 --> 00:06:36,360\nThat's the thing that allows\nus to build complexity.\n\n109\n00:06:36,360 --> 00:06:40,000\nAnd that seems obvious, but\nremember, a lot of the things\n\n110\n00:06:40,000 --> 00:06:42,480\nin the computer languages that\npeople use are not closed.\n\n111\n00:06:42,480 --> 00:06:47,120\nSo for example, forming arrays\nin basic and Fortran is not a\n\n112\n00:06:47,120 --> 00:06:50,390\nclosed operation, because you\ncan make an array of numbers\n\n113\n00:06:50,390 --> 00:06:52,690\nor character strings or\nsomething, but you can't make\n\n114\n00:06:52,690 --> 00:06:54,800\nan array of arrays.\n\n115\n00:06:54,800 --> 00:06:59,260\nAnd when you look at means of\ncombination, you should be\n\n116\n00:06:59,260 --> 00:07:01,260\nshould be asking yourself\nwhether things are closed\n\n117\n00:07:01,260 --> 00:07:02,510\nunder that means\nof combination.\n\n118\n00:07:02,510 --> 00:07:05,280\n\n\n119\n00:07:05,280 --> 00:07:09,100\nWell in any case, because we\ncan form pairs of pairs, we\n\n120\n00:07:09,100 --> 00:07:11,980\ncan start using pairs to glue\nthings together in all sorts\n\n121\n00:07:11,980 --> 00:07:14,230\nof different ways.\n\n122\n00:07:14,230 --> 00:07:17,300\nSo for instance if I'd like to\nglue together the four things,\n\n123\n00:07:17,300 --> 00:07:20,880\n1, 2, 3 and 4, there are a\nlot of ways I can do it.\n\n124\n00:07:20,880 --> 00:07:25,050\nI could, for example, like we\ndid with that line segment, I\n\n125\n00:07:25,050 --> 00:07:32,990\ncould make a pair that\nhad a 1 and a 2 and\n\n126\n00:07:32,990 --> 00:07:36,900\na 3 and a 4, right?\n\n127\n00:07:36,900 --> 00:07:40,090\nOr if I liked, I could do\nsomething like this.\n\n128\n00:07:40,090 --> 00:07:46,580\nI could make a pair, whose first\nthing is a pair, whose\n\n129\n00:07:46,580 --> 00:07:53,010\ncar is 1, and his cdr is itself\na pair that has the 2\n\n130\n00:07:53,010 --> 00:07:56,660\nand the 3, and then I could\nput the 4 up here.\n\n131\n00:07:56,660 --> 00:07:59,420\nSo you see, there are a lot of\ndifferent ways that I can\n\n132\n00:07:59,420 --> 00:08:02,560\nstart using pairs to glue things\ntogether, and so it'll\n\n133\n00:08:02,560 --> 00:08:07,540\nbe a good idea to establish\nsome kind of conventions,\n\n134\n00:08:07,540 --> 00:08:10,830\nright, that allow us to deal\nwith this thing in some\n\n135\n00:08:10,830 --> 00:08:12,590\nconventional way, so we're\nnot constantly\n\n136\n00:08:12,590 --> 00:08:16,070\nmaking an ad hoc choice.\n\n137\n00:08:16,070 --> 00:08:21,650\nAnd List has a particular\nconvention for representing a\n\n138\n00:08:21,650 --> 00:08:26,730\nsequence of things as,\nessentially, a chain of pairs,\n\n139\n00:08:26,730 --> 00:08:34,581\nand that's called a List.\n\n140\n00:08:34,581 --> 00:08:39,169\nAnd what a List is is\nessentially just a convention\n\n141\n00:08:39,169 --> 00:08:40,929\nfor representing a sequence.\n\n142\n00:08:40,929 --> 00:08:45,790\nI would represent the sequence\n1, 2, 3 and 4 by\n\n143\n00:08:45,790 --> 00:08:48,420\na sequence of pairs.\n\n144\n00:08:48,420 --> 00:08:53,920\nI'd put 1 here and then the\ncdr of this would point to\n\n145\n00:08:53,920 --> 00:09:01,490\nanother pair whose car was the\nnext thing in the sequence,\n\n146\n00:09:01,490 --> 00:09:06,260\nand the cdr would point to\nanother pair whose car was the\n\n147\n00:09:06,260 --> 00:09:08,400\nnext thing in the sequence--\nso there's 3--\n\n148\n00:09:08,400 --> 00:09:09,550\nand then another one.\n\n149\n00:09:09,550 --> 00:09:15,450\nSo for each item in the\nsequence, I'll get a pair.\n\n150\n00:09:15,450 --> 00:09:21,130\nAnd now there are no more, so\nI put a special marker that\n\n151\n00:09:21,130 --> 00:09:28,760\nmeans there's nothing more in\nthe List. OK, so that's a\n\n152\n00:09:28,760 --> 00:09:31,750\nconventional way to glue things\ntogether if you want to\n\n153\n00:09:31,750 --> 00:09:34,450\nrepresent a sequence, right.\n\n154\n00:09:34,450 --> 00:09:42,570\nAnd what it is is a bunch of\npairs, the successive cars of\n\n155\n00:09:42,570 --> 00:09:46,470\neach pair are the items that you\nwant to glue together, and\n\n156\n00:09:46,470 --> 00:09:50,330\nthe cdr pointer points\nto the next pair.\n\n157\n00:09:50,330 --> 00:09:52,710\nNow if I actually wanted to\nconstruct that, what I would\n\n158\n00:09:52,710 --> 00:09:57,630\ntype into List is this: I'd\nactually construct that as\n\n159\n00:09:57,630 --> 00:10:07,640\nsaying, well this thing is the\ncons of 1 onto the cons of 2\n\n160\n00:10:07,640 --> 00:10:14,390\nonto the cons of 3 onto\nthe cons of 4 onto,\n\n161\n00:10:14,390 --> 00:10:15,150\nwell, this thing nil.\n\n162\n00:10:15,150 --> 00:10:21,050\nAnd what nil is is a name for\nthe end of List marker.\n\n163\n00:10:21,050 --> 00:10:22,960\nIt's a special name, which means\nthis is the end of the\n\n164\n00:10:22,960 --> 00:10:29,980\nList. OK, so that's how I would\nactually construct that.\n\n165\n00:10:29,980 --> 00:10:37,195\n\n\n166\n00:10:37,195 --> 00:10:40,670\nOf course, it's a terrible drag\nto constantly have to\n\n167\n00:10:40,670 --> 00:10:43,000\nwrite something like the cons\nof 1 onto the cons of 2 onto\n\n168\n00:10:43,000 --> 00:10:45,310\nthe cons of 3, whenever you\nwant to make this thing.\n\n169\n00:10:45,310 --> 00:10:54,270\nSo List has an operation that's\ncalled List, and List\n\n170\n00:10:54,270 --> 00:10:59,160\nis just an abbreviation for\nthis nest of conses.\n\n171\n00:10:59,160 --> 00:11:02,310\nSo I could say, I could\nconstruct that by saying that\n\n172\n00:11:02,310 --> 00:11:08,010\nis the List of 1, 2, 3 and 4.\n\n173\n00:11:08,010 --> 00:11:11,310\nAnd all this is is another\nway, a piece of syntactic\n\n174\n00:11:11,310 --> 00:11:13,550\nsugar, a more convenient\nway for writing\n\n175\n00:11:13,550 --> 00:11:15,390\nthat chain of conses--\n\n176\n00:11:15,390 --> 00:11:18,410\ncons of cons of cons of cons\nof cons of cons onto nil.\n\n177\n00:11:18,410 --> 00:11:21,810\nSo for example, I could build\nthis thing and say, I'll\n\n178\n00:11:21,810 --> 00:11:39,150\ndefine 1-TO-4 to be the\nList of 1, 2, 3 and 4.\n\n179\n00:11:39,150 --> 00:11:48,070\n\n\n180\n00:11:48,070 --> 00:11:51,890\nOK, well notice some of the\nconsequences of using this\n\n181\n00:11:51,890 --> 00:11:54,190\nconvention.\n\n182\n00:11:54,190 --> 00:11:57,520\nFirst of all if I have this\nList, this 1, 2, 3 and 4, the\n\n183\n00:11:57,520 --> 00:11:59,290\ncar of the whole thing\nis the first element\n\n184\n00:11:59,290 --> 00:12:04,100\nin the List, right.\n\n185\n00:12:04,100 --> 00:12:05,400\nHow do I get 2?\n\n186\n00:12:05,400 --> 00:12:21,850\nWell, 2 would be the car of the\ncdr of this thing 1-TO-4,\n\n187\n00:12:21,850 --> 00:12:25,160\nit would be 2, right.\n\n188\n00:12:25,160 --> 00:12:30,050\nI take this thing, I take the\ncdr of it, which is this much,\n\n189\n00:12:30,050 --> 00:12:38,760\nand the car of that is 2, and\nthen similarly, the car of the\n\n190\n00:12:38,760 --> 00:12:48,060\ncdr of the cdr of 1-TO-4,\ncdr, cdr, car--\n\n191\n00:12:48,060 --> 00:12:52,898\nwould give me 3, and so on.\n\n192\n00:12:52,898 --> 00:12:54,650\nLet's take a look at that\non the computer\n\n193\n00:12:54,650 --> 00:12:55,900\nscreen for a second.\n\n194\n00:12:55,900 --> 00:12:57,880\n\n\n195\n00:12:57,880 --> 00:13:07,050\nI could come up to List, and I\ncould type define 1-TO-4 to be\n\n196\n00:13:07,050 --> 00:13:14,190\nthe List of 1, 2,\n3 and 4, right.\n\n197\n00:13:14,190 --> 00:13:19,690\nAnd I'll tell that to List, and\nit says, fine, that's the\n\n198\n00:13:19,690 --> 00:13:22,540\ndefinition of 1-TO-4.\n\n199\n00:13:22,540 --> 00:13:28,950\nAnd I could say, for instance,\nwhat's the car of the cdr of\n\n200\n00:13:28,950 --> 00:13:38,096\nthe cdr of 1-TO-4, close\nparen, close paren.\n\n201\n00:13:38,096 --> 00:13:43,916\nRight, so the car of the cdr\nof the cdr would be 3.\n\n202\n00:13:43,916 --> 00:13:51,660\nRight, or I could say,\nwhat's 1-TO-4 itself.\n\n203\n00:13:51,660 --> 00:13:56,160\nAnd you see what List typed out\nis 1, 2, 3, 4, enclosed in\n\n204\n00:13:56,160 --> 00:13:59,630\nparentheses, and this notation,\ntyping the elements\n\n205\n00:13:59,630 --> 00:14:02,930\nof the List enclosed in\nparentheses is List's\n\n206\n00:14:02,930 --> 00:14:07,660\nconventional way for printing\nback this chain of pairs that\n\n207\n00:14:07,660 --> 00:14:09,190\nrepresents a sequence.\n\n208\n00:14:09,190 --> 00:14:19,520\nSo for example, if I said,\nwhat's the cdr of 1-TO-4,\n\n209\n00:14:19,520 --> 00:14:22,080\nthat's going to be the rest of\nthe List. That's the thing\n\n210\n00:14:22,080 --> 00:14:25,410\npointed to by the first pair,\nwhich is, again, a sequence\n\n211\n00:14:25,410 --> 00:14:28,880\nthat starts off with 2.\n\n212\n00:14:28,880 --> 00:14:36,740\nOr for example, I go off and\nsay, what's the cdr of the cdr\n\n213\n00:14:36,740 --> 00:14:44,990\nof 1-TO-4; then that's 3,4.\n\n214\n00:14:44,990 --> 00:14:58,205\nOr if I say, what's the cdr of\nthe cdr of the cdr of the cdr\n\n215\n00:14:58,205 --> 00:15:07,090\nof 1-TO-4, and I'm down there\nlooking at the end of List\n\n216\n00:15:07,090 --> 00:15:09,340\npointer itself, and List prints\nthat as just open\n\n217\n00:15:09,340 --> 00:15:10,780\nparen, close paren.\n\n218\n00:15:10,780 --> 00:15:13,805\nYou can think of that as a List\nwith nothing in there.\n\n219\n00:15:13,805 --> 00:15:16,190\nAll right, see at the end what\nI did there was I looked at\n\n220\n00:15:16,190 --> 00:15:22,150\nthe cdr of the cdr of the cdr\nof 1-TO-4, and I'm just left\n\n221\n00:15:22,150 --> 00:15:24,880\nwith the end of List\npointer itself.\n\n222\n00:15:24,880 --> 00:15:26,450\nAnd that gets printed\nas open close.\n\n223\n00:15:26,450 --> 00:15:34,350\n\n\n224\n00:15:34,350 --> 00:15:37,660\nAll right, well that's a\nconventional way you can see\n\n225\n00:15:37,660 --> 00:15:42,080\nfor working down a\nList by taking\n\n226\n00:15:42,080 --> 00:15:43,340\nsuccessive cdrs of things.\n\n227\n00:15:43,340 --> 00:15:47,470\nIt's called cdring down a\nList. And of course it's\n\n228\n00:15:47,470 --> 00:15:49,840\npretty much of a drag to type\nall those cdrs by hand.\n\n229\n00:15:49,840 --> 00:15:50,570\nYou don't do that.\n\n230\n00:15:50,570 --> 00:15:53,220\nYou write procedures\nthat do that.\n\n231\n00:15:53,220 --> 00:15:56,300\nAnd in fact one very, very\ncommon thing to do in List is\n\n232\n00:15:56,300 --> 00:16:02,290\nto write procedures that, sort\nof, take a List of things and\n\n233\n00:16:02,290 --> 00:16:05,630\ndo something to every element in\nList, and return you a List\n\n234\n00:16:05,630 --> 00:16:07,400\nof the results.\n\n235\n00:16:07,400 --> 00:16:10,550\nSo what I mean for example, is\nI might write a procedure\n\n236\n00:16:10,550 --> 00:16:18,440\ncalled Scale-List, and\nScale-List I might say I want\n\n237\n00:16:18,440 --> 00:16:27,640\nto scale by 10 the entire List\n1-TO-4, and that would return\n\n238\n00:16:27,640 --> 00:16:36,513\nfor me the List 10,\n20, 30, 40.\n\n239\n00:16:36,513 --> 00:16:38,480\n[UNINTELLIGIBLE PHRASE]\n\n240\n00:16:38,480 --> 00:16:46,360\nRight, it returns List, and well\nyou can see that there's\n\n241\n00:16:46,360 --> 00:16:48,320\ngoing to be some kind\nof recursive\n\n242\n00:16:48,320 --> 00:16:49,320\nstrategy for doing it.\n\n243\n00:16:49,320 --> 00:16:52,800\nHow would I actually write\nthat procedure?\n\n244\n00:16:52,800 --> 00:16:56,760\nThe idea would be, well if you'd\nlike to build up a List\n\n245\n00:16:56,760 --> 00:17:01,140\nwhere you've multiplied every\nelement by 10, what you'd say\n\n246\n00:17:01,140 --> 00:17:06,010\nis well you imagine that you'd\ntaken the rest of the List--\n\n247\n00:17:06,010 --> 00:17:08,560\nright, the thing represented\nby the cdr of the List, and\n\n248\n00:17:08,560 --> 00:17:12,869\nsuppose I'd already built a List\nwhere each of these was\n\n249\n00:17:12,869 --> 00:17:16,470\nmultiplied by 10--\n\n250\n00:17:16,470 --> 00:17:20,784\nthat would be Scale-List of the\ncdr of the List. And then\n\n251\n00:17:20,784 --> 00:17:25,099\nall I have to do is multiply the\ncar of the List by 10, and\n\n252\n00:17:25,099 --> 00:17:28,666\nthen cons that onto the rest,\nand I'll get a List.\n\n253\n00:17:28,666 --> 00:17:31,610\nRight and then similarly, to\nhave scaled the cdr of the\n\n254\n00:17:31,610 --> 00:17:35,020\nList, I'll scale the cdr of\nthat and cons onto that 2\n\n255\n00:17:35,020 --> 00:17:36,830\nmultiplied by 10.\n\n256\n00:17:36,830 --> 00:17:38,690\nAnd finally when I get all the\nway down to the end, and I\n\n257\n00:17:38,690 --> 00:17:41,672\nonly have this end\nof List pointer.\n\n258\n00:17:41,672 --> 00:17:43,640\nAll right, this thing whose\nname is nil-- well I just\n\n259\n00:17:43,640 --> 00:17:45,455\nreturned an end of\nList pointer.\n\n260\n00:17:45,455 --> 00:17:47,700\nSo there's a recursive strategy\nfor doing that.\n\n261\n00:17:47,700 --> 00:17:51,180\nHere's the actual procedure\nthat does that.\n\n262\n00:17:51,180 --> 00:17:53,810\nRight, this is an example of\nthe general strategy of\n\n263\n00:17:53,810 --> 00:17:56,800\ncdr-ing down a List and\nso called cons-ing\n\n264\n00:17:56,800 --> 00:17:58,310\nup the result, right.\n\n265\n00:17:58,310 --> 00:18:06,090\nSo to Scale a List l by some\nscale factor s, what do I do?\n\n266\n00:18:06,090 --> 00:18:10,560\nWell there's a test, and List\nhas the predicate called null.\n\n267\n00:18:10,560 --> 00:18:14,060\nNull means is this thing the\nend of List pointer, or\n\n268\n00:18:14,060 --> 00:18:16,700\nanother way to think of that is\nare there any elements in\n\n269\n00:18:16,700 --> 00:18:17,810\nthis List, right.\n\n270\n00:18:17,810 --> 00:18:20,820\nBut in any case if I'm looking\nat the end of List pointer,\n\n271\n00:18:20,820 --> 00:18:23,640\nthen I just return the\nend of List pointer.\n\n272\n00:18:23,640 --> 00:18:32,290\nI just return nil, otherwise I\ncons together the result of\n\n273\n00:18:32,290 --> 00:18:35,850\ndoing what I'm going to do to\nthe first element in the List,\n\n274\n00:18:35,850 --> 00:18:40,920\nnamely taking the car of l and\nmultiplying it by s, and I\n\n275\n00:18:40,920 --> 00:18:50,240\ncons that onto recursively\nscaling the rest of the List.\n\n276\n00:18:50,240 --> 00:18:53,730\nOK, so again, the general idea\nis that you recursively do\n\n277\n00:18:53,730 --> 00:18:56,740\nsomething to the rest of the\nList, to the cdr of the List,\n\n278\n00:18:56,740 --> 00:18:59,560\nand then you cons that onto\nactually doing something to\n\n279\n00:18:59,560 --> 00:19:02,230\nthe first element of the List.\nWhen you get down to the end\n\n280\n00:19:02,230 --> 00:19:07,810\nhere, you return the end of\nList pointer, and that's a\n\n281\n00:19:07,810 --> 00:19:16,400\ngeneral pattern for doing\nsomething to a List. Well of\n\n282\n00:19:16,400 --> 00:19:19,540\ncourse you should know by now\nthat the very fact that\n\n283\n00:19:19,540 --> 00:19:21,190\nthere's a general pattern there\nmeans I shouldn't be\n\n284\n00:19:21,190 --> 00:19:23,140\nwriting this procedure at all.\n\n285\n00:19:23,140 --> 00:19:25,500\nWhat I should do is write a\nprocedure that's the general\n\n286\n00:19:25,500 --> 00:19:28,350\npattern itself that says, do\nsomething to everything in the\n\n287\n00:19:28,350 --> 00:19:30,870\nList and define this thing\nin terms of that.\n\n288\n00:19:30,870 --> 00:19:33,050\nRight, make some higher order\nprocedure, and here's the\n\n289\n00:19:33,050 --> 00:19:34,390\nhigher order procedure\nthat does that.\n\n290\n00:19:34,390 --> 00:19:40,100\nIt's called MAP, and what MAP\ndoes is it takes a List, takes\n\n291\n00:19:40,100 --> 00:19:45,700\na List l, and it takes a\nprocedure p, and it returns\n\n292\n00:19:45,700 --> 00:19:49,840\nthe List of the elements gotten\nby applying p to each\n\n293\n00:19:49,840 --> 00:19:53,445\nsuccessive element in the List.\nAll right, so p to v1, p\n\n294\n00:19:53,445 --> 00:19:56,480\nto v2, p of en.\n\n295\n00:19:56,480 --> 00:19:59,670\nRight, so I think of taking this\nList and transforming it\n\n296\n00:19:59,670 --> 00:20:02,720\nby applying p to each element.\n\n297\n00:20:02,720 --> 00:20:06,200\nAnd you see all this procedure\nis is exactly the general\n\n298\n00:20:06,200 --> 00:20:07,030\nstrategy I said.\n\n299\n00:20:07,030 --> 00:20:09,370\nInstead of multiply by 10,\nit's do the procedure.\n\n300\n00:20:09,370 --> 00:20:13,150\nIf the List is empty,\nreturn nil.\n\n301\n00:20:13,150 --> 00:20:17,240\nOtherwise, apply p to the first\nelement of the List.\n\n302\n00:20:17,240 --> 00:20:21,990\nRight, apply p to car of l, and\ncons that onto the result\n\n303\n00:20:21,990 --> 00:20:26,450\nof applying p to everything in\nthe cdr of the List, so that's\n\n304\n00:20:26,450 --> 00:20:30,110\na general procedure\ncalled MAP.\n\n305\n00:20:30,110 --> 00:20:39,590\nAnd I could define Scale-List\nin terms of MAP.\n\n306\n00:20:39,590 --> 00:20:43,265\nLet me show you that first.\n\n307\n00:20:43,265 --> 00:20:46,650\nBut I could say Scale-List is\nanother way to define it is\n\n308\n00:20:46,650 --> 00:20:53,950\njust MAP along the List by the\nprocedure, which takes an item\n\n309\n00:20:53,950 --> 00:20:55,430\nand multiplies it by s.\n\n310\n00:20:55,430 --> 00:20:58,208\n\n\n311\n00:20:58,208 --> 00:21:01,260\nRight, so this is really the\nway I should think about\n\n312\n00:21:01,260 --> 00:21:04,640\nscaling the List, build that\nactual recursion into the\n\n313\n00:21:04,640 --> 00:21:07,570\ngeneral strategy, not to every\nparticular procedure I write.\n\n314\n00:21:07,570 --> 00:21:09,900\nAnd of course, one of the values\nof doing this is that\n\n315\n00:21:09,900 --> 00:21:11,962\nyou start to see commonality.\n\n316\n00:21:11,962 --> 00:21:16,420\nRight, again you're capturing\ngeneral patterns of usage.\n\n317\n00:21:16,420 --> 00:21:22,610\nFor instance, if I said MAP,\nthe square procedure, down\n\n318\n00:21:22,610 --> 00:21:32,690\nthis List 1-TO-4, then I'd end\nup with 1, 4, 9 and 16.\n\n319\n00:21:32,690 --> 00:21:42,710\nRight, or if I said MAP down\nthis List, lambda of x plus\n\n320\n00:21:42,710 --> 00:21:51,020\nx10, if I MAP that down 1-TO-4,\nthen I'd get the List\n\n321\n00:21:51,020 --> 00:21:55,020\nwhere everything had 10 added\nto it: right, so I'd get 11,\n\n322\n00:21:55,020 --> 00:22:00,400\n12, 13, 14.\n\n323\n00:22:00,400 --> 00:22:03,480\nAnd you can see that's going\nto be a very, very common\n\n324\n00:22:03,480 --> 00:22:08,760\nidea: doing something to every\nelement in the List.\n\n325\n00:22:08,760 --> 00:22:11,240\nOne thing you might think about\nis writing MAP in an\n\n326\n00:22:11,240 --> 00:22:12,350\niterative style.\n\n327\n00:22:12,350 --> 00:22:15,460\nThe one I wrote happens to\nevolve a recursive process,\n\n328\n00:22:15,460 --> 00:22:18,050\nbut we could just as easily have\nmade one that evolves an\n\n329\n00:22:18,050 --> 00:22:19,390\niterative process.\n\n330\n00:22:19,390 --> 00:22:21,610\nBut see the interesting thing\nabout it is that once you\n\n331\n00:22:21,610 --> 00:22:24,270\nstart thinking in\nterms of MAP--\n\n332\n00:22:24,270 --> 00:22:27,170\nsee, once you say scale is just\nMAP, you stop thinking\n\n333\n00:22:27,170 --> 00:22:29,200\nabout whether it's iterative\nor recursive, and you just\n\n334\n00:22:29,200 --> 00:22:32,380\nsay, well there's this\naggregate, there's this List,\n\n335\n00:22:32,380 --> 00:22:34,490\nand what I do is transform every\nitem in the List, and I\n\n336\n00:22:34,490 --> 00:22:37,360\nstop thinking about the\nparticular control\n\n337\n00:22:37,360 --> 00:22:39,050\nstructure in order.\n\n338\n00:22:39,050 --> 00:22:45,190\nThat's a very, very important\nidea, and it, I guess it\n\n339\n00:22:45,190 --> 00:22:46,530\nreally comes out of APL.\n\n340\n00:22:46,530 --> 00:22:49,370\nIt's, sort of, the really\nimportant idea in APL that you\n\n341\n00:22:49,370 --> 00:22:52,020\nstop thinking about control\nstructures, and you start\n\n342\n00:22:52,020 --> 00:22:55,580\nthinking about operations on\naggregates, and then about\n\n343\n00:22:55,580 --> 00:22:58,330\nhalfway through this course,\nwe'll see when we talk about\n\n344\n00:22:58,330 --> 00:23:00,940\nsomething called stream\nprocessing, how that view of\n\n345\n00:23:00,940 --> 00:23:02,670\nthe world really comes\ninto its glory.\n\n346\n00:23:02,670 --> 00:23:05,400\nThis is just us a, sort\nof, cute idea.\n\n347\n00:23:05,400 --> 00:23:09,520\nBut we'll see much more\napplications of that later on.\n\n348\n00:23:09,520 --> 00:23:13,560\nWell let me mention that there's\nsomething that's very\n\n349\n00:23:13,560 --> 00:23:17,680\nsimilar to MAP that's also a\nuseful idea, and that's--\n\n350\n00:23:17,680 --> 00:23:23,130\nsee, MAP says I take a List, I\napply something to each item,\n\n351\n00:23:23,130 --> 00:23:26,220\nand I return a List of the\nsuccessive values.\n\n352\n00:23:26,220 --> 00:23:28,200\nThere's another thing I might\ndo, which is very, very\n\n353\n00:23:28,200 --> 00:23:32,850\nsimilar, which is take a List\nand some action you want to do\n\n354\n00:23:32,850 --> 00:23:36,470\nand then do it to each item\nin the List in sequence.\n\n355\n00:23:36,470 --> 00:23:38,240\nDon't make a List of the\nvalues, just do this\n\n356\n00:23:38,240 --> 00:23:40,810\nparticular action, and that's\nsomething that's\n\n357\n00:23:40,810 --> 00:23:45,040\nvery much like MAP.\n\n358\n00:23:45,040 --> 00:23:49,130\nIt's called for-each, and\nfor-each takes a procedure and\n\n359\n00:23:49,130 --> 00:23:52,970\na List, and what it's going to\ndo is do something to every\n\n360\n00:23:52,970 --> 00:23:56,830\nitem in the List. So basically\nwhat it does: it says if the\n\n361\n00:23:56,830 --> 00:24:02,250\nList is not empty, right, if\nthe List is not null, then\n\n362\n00:24:02,250 --> 00:24:05,830\nwhat I do is, I apply my\nprocedure to the first item in\n\n363\n00:24:05,830 --> 00:24:12,130\nthe List, and then I do this\nthing to the rest of the List.\n\n364\n00:24:12,130 --> 00:24:15,610\nI apply for-each to the\ncdr of the List.\n\n365\n00:24:15,610 --> 00:24:17,660\nAll right, so I do it to the\nfirst of the List, do it to\n\n366\n00:24:17,660 --> 00:24:20,930\nthe rest of the List, and of\ncourse, when I call it\n\n367\n00:24:20,930 --> 00:24:22,920\nrecursively, that's going to do\nit to the rest of the rest\n\n368\n00:24:22,920 --> 00:24:24,050\nof the List and so on.\n\n369\n00:24:24,050 --> 00:24:27,540\nAnd finally, when I get done, I\nhave to just do something to\n\n370\n00:24:27,540 --> 00:24:30,930\nsay I'm done, so we'll return\nthe message \"done.\" So that's\n\n371\n00:24:30,930 --> 00:24:32,980\nvery, very similar to MAP.\n\n372\n00:24:32,980 --> 00:24:35,680\nIt's mostly different\nin what it returns.\n\n373\n00:24:35,680 --> 00:24:38,920\nAnd so for example, if I had\nsome procedure that printed\n\n374\n00:24:38,920 --> 00:24:42,030\nthings on the screen, if I\nwanted to print everything in\n\n375\n00:24:42,030 --> 00:24:47,160\nthe List, I could say for-each,\nprint this List. Or\n\n376\n00:24:47,160 --> 00:24:50,660\nif I had a List of figures, and\nI wanted to draw them on\n\n377\n00:24:50,660 --> 00:24:53,900\nthe display, I could say\nfor-each, display on the\n\n378\n00:24:53,900 --> 00:24:55,150\nscreen this figure.\n\n379\n00:24:55,150 --> 00:24:57,750\n\n\n380\n00:24:57,750 --> 00:25:00,970\nLet's take questions.\n\n381\n00:25:00,970 --> 00:25:03,810\nAUDIENCE: Does it create a new\ncopy with something done to\n\n382\n00:25:03,810 --> 00:25:06,744\nit, unless you explicitly\ntell it to do that?\n\n383\n00:25:06,744 --> 00:25:08,010\nIs that correct?\n\n384\n00:25:08,010 --> 00:25:10,030\nPROFESSOR: Right.\n\n385\n00:25:10,030 --> 00:25:10,980\nYeah, that's right.\n\n386\n00:25:10,980 --> 00:25:14,020\nFor-each does not create\na List. It just\n\n387\n00:25:14,020 --> 00:25:15,350\nsort of does something.\n\n388\n00:25:15,350 --> 00:25:18,180\nSo if you have a bunch of things\nyou want to do and\n\n389\n00:25:18,180 --> 00:25:19,720\nyou're not worried about\nvalues like printing\n\n390\n00:25:19,720 --> 00:25:22,030\nsomething, or drawing something\non the screen, or\n\n391\n00:25:22,030 --> 00:25:24,610\nringing the bell on the\nterminal, or for something,\n\n392\n00:25:24,610 --> 00:25:26,760\nyou can say for-each, you know,\ndo this for-each of\n\n393\n00:25:26,760 --> 00:25:29,770\nthose things in the List,\nwhereas MAP actually builds\n\n394\n00:25:29,770 --> 00:25:31,780\nyou this new collection\nof values that you\n\n395\n00:25:31,780 --> 00:25:32,570\nmight want to use.\n\n396\n00:25:32,570 --> 00:25:34,380\nIt's just a subtle difference\nbetween them.\n\n397\n00:25:34,380 --> 00:25:37,590\nAUDIENCE: Could you write MAP\nusing for-each, so that you\n\n398\n00:25:37,590 --> 00:25:39,640\ndid some sort of cons or\nsomething to build\n\n399\n00:25:39,640 --> 00:25:41,520\nthe List back up?\n\n400\n00:25:41,520 --> 00:25:42,510\nPROFESSOR: Well, sort of.\n\n401\n00:25:42,510 --> 00:25:44,570\nI mean, I probably could.\n\n402\n00:25:44,570 --> 00:25:48,810\nI can't think of how to do it\nright offhand, but yeah, I\n\n403\n00:25:48,810 --> 00:25:51,380\ncould arrange something.\n\n404\n00:25:51,380 --> 00:25:52,830\nAUDIENCE: The vital difference\nbetween MAP and for-each is\n\n405\n00:25:52,830 --> 00:25:57,320\none is recursive and the other\nis not in the sense you\n\n406\n00:25:57,320 --> 00:26:01,570\ndefined early yesterday,\nI believe.\n\n407\n00:26:01,570 --> 00:26:03,660\nPROFESSOR: Yeah, about MAP and\nfor-each and recursion.\n\n408\n00:26:03,660 --> 00:26:05,390\nYeah, that's a good point.\n\n409\n00:26:05,390 --> 00:26:09,420\n\n\n410\n00:26:09,420 --> 00:26:11,615\nFor the MAP procedure I\nwrote, that happens to\n\n411\n00:26:11,615 --> 00:26:13,880\nbe a recursive process.\n\n412\n00:26:13,880 --> 00:26:16,130\nAnd the reason for that is that\nwhen you've done this\n\n413\n00:26:16,130 --> 00:26:19,000\nthing to the rest of the List,\nyou're waiting for that value\n\n414\n00:26:19,000 --> 00:26:21,830\nso that you can stick it on to\nthe beginning of the List,\n\n415\n00:26:21,830 --> 00:26:23,340\nwhereas for-each doesn't\nreally have any\n\n416\n00:26:23,340 --> 00:26:24,740\nvalues to wait for.\n\n417\n00:26:24,740 --> 00:26:26,680\nSo that turns out to be\nan iterative process.\n\n418\n00:26:26,680 --> 00:26:27,590\nThat's not fundamental.\n\n419\n00:26:27,590 --> 00:26:30,920\nI could have defined MAP so\nthat it's evolved by an\n\n420\n00:26:30,920 --> 00:26:31,770\niterative process.\n\n421\n00:26:31,770 --> 00:26:33,670\nI just didn't happen to.\n\n422\n00:26:33,670 --> 00:26:37,780\nAUDIENCE: If you were to cons\nfor each with a List that had\n\n423\n00:26:37,780 --> 00:26:43,210\nembedded Lists, I imagine\nit would work, right?\n\n424\n00:26:43,210 --> 00:26:47,300\nIt would give you the internal\nelements of each of those\n\n425\n00:26:47,300 --> 00:26:48,940\ninternal Lists?\n\n426\n00:26:48,940 --> 00:26:50,430\nPROFESSOR: OK, the question\nis if I [UNINTELLIGIBLE]\n\n427\n00:26:50,430 --> 00:26:54,420\nfor each or MAP, for that\nmatter, with a List that had\n\n428\n00:26:54,420 --> 00:26:56,406\nLists in it--\n\n429\n00:26:56,406 --> 00:26:59,430\nalthough we haven't really\nlooked at that yet--\n\n430\n00:26:59,430 --> 00:27:01,310\nwould that work.\n\n431\n00:27:01,310 --> 00:27:04,610\nThe answer is yes in the sense\nI mean work and no in the\n\n432\n00:27:04,610 --> 00:27:09,140\nsense that you mean work,\nbecause all that--\n\n433\n00:27:09,140 --> 00:27:16,190\nsee if I give you a List, where\nhanging off here is, you\n\n434\n00:27:16,190 --> 00:27:19,700\nknow, is something that's not\na number, maybe another List\n\n435\n00:27:19,700 --> 00:27:22,670\nor you know, another cons or\nsomething, for-each just says\n\n436\n00:27:22,670 --> 00:27:25,240\ndo something to each item in\nthis List. It goes down\n\n437\n00:27:25,240 --> 00:27:26,965\nsuccessively looking\nat the cdrs.\n\n438\n00:27:26,965 --> 00:27:27,220\nAUDIENCE: OK.\n\n439\n00:27:27,220 --> 00:27:29,140\nPROFESSOR: And as far as it's\nconcerned, the first item in\n\n440\n00:27:29,140 --> 00:27:30,830\nthis List is whatever\nis hanging off here.\n\n441\n00:27:30,830 --> 00:27:31,830\nAUDIENCE: Mhm.\n\n442\n00:27:31,830 --> 00:27:33,780\nPROFESSOR: That might or might\nnot be the right thing.\n\n443\n00:27:33,780 --> 00:27:35,670\nAUDIENCE: So it wouldn't\ngo down into the--\n\n444\n00:27:35,670 --> 00:27:37,030\nPROFESSOR: Absolutely not.\n\n445\n00:27:37,030 --> 00:27:38,380\nI could certainly write\nsomething else.\n\n446\n00:27:38,380 --> 00:27:40,930\nThere's another, what you're\nlooking for is a common\n\n447\n00:27:40,930 --> 00:27:43,600\npattern of usage called tree\nrecursion, where you take a\n\n448\n00:27:43,600 --> 00:27:46,523\nList, and you actually go all\nthe way down to the what's\n\n449\n00:27:46,523 --> 00:27:48,140\ncalled the leaves of the tree.\n\n450\n00:27:48,140 --> 00:27:50,140\nAnd you could write such a\nthing, but that's not for-each\n\n451\n00:27:50,140 --> 00:27:52,420\nand it's not MAP.\n\n452\n00:27:52,420 --> 00:27:53,590\nRemember, these things\nare really\n\n453\n00:27:53,590 --> 00:27:55,492\nbeing very simple minded.\n\n454\n00:27:55,492 --> 00:27:57,390\nOK, no more questions?\n\n455\n00:27:57,390 --> 00:27:58,998\nAll right, let's break.\n\n456\n00:27:58,998 --> 00:28:42,480\n[MUSIC PLAYING]\n\n457\n00:28:42,480 --> 00:28:46,220\nPROFESSOR: What I'd like to do\nnow is spend the rest of this\n\n458\n00:28:46,220 --> 00:28:50,960\ntime talking about one example,\nand this example, I\n\n459\n00:28:50,960 --> 00:28:53,510\nthink, pretty much summarizes\neverything that we've done up\n\n460\n00:28:53,510 --> 00:28:58,050\nuntil now: all right, and that's\nList structure and\n\n461\n00:28:58,050 --> 00:29:02,360\nissues of abstraction, and\nrepresentation and capturing\n\n462\n00:29:02,360 --> 00:29:05,620\ncommonality with higher order\nprocedures, and also is going\n\n463\n00:29:05,620 --> 00:29:09,290\nto introduce something we\nhaven't really talked about a\n\n464\n00:29:09,290 --> 00:29:13,160\nlot yet-- what I said is the\nmajor third theme in this\n\n465\n00:29:13,160 --> 00:29:17,190\ncourse: meta-linguistic\nabstraction, which is the idea\n\n466\n00:29:17,190 --> 00:29:20,930\nthat one of the ways of\ntackling complexity in\n\n467\n00:29:20,930 --> 00:29:27,750\nengineering design is to build\na suitable powerful language.\n\n468\n00:29:27,750 --> 00:29:31,370\nYou might recall what I said was\npretty much the very most\n\n469\n00:29:31,370 --> 00:29:33,620\nimportant thing that we're\ngoing to tell you in this\n\n470\n00:29:33,620 --> 00:29:39,010\ncourse is that when you think\nabout a language, you think\n\n471\n00:29:39,010 --> 00:29:43,470\nabout it in terms of what are\nthe primitives; what are the\n\n472\n00:29:43,470 --> 00:29:46,225\nmeans of combination--\n\n473\n00:29:46,225 --> 00:29:49,560\n\n\n474\n00:29:49,560 --> 00:29:52,310\nright, what are the things that\nallow you to build bigger\n\n475\n00:29:52,310 --> 00:29:54,945\nthings; and then what are the\nmeans of abstraction.\n\n476\n00:29:54,945 --> 00:30:01,170\n\n\n477\n00:30:01,170 --> 00:30:05,800\nHow do you take those bigger\nthings that you've built and\n\n478\n00:30:05,800 --> 00:30:09,620\nput black boxes around them and\nuse them as elements in\n\n479\n00:30:09,620 --> 00:30:12,846\nmaking something even\nmore complicated?\n\n480\n00:30:12,846 --> 00:30:18,170\nNow the particular language I'm\ngoing to talk about is an\n\n481\n00:30:18,170 --> 00:30:21,675\nexample that was made up\nby a friend of ours\n\n482\n00:30:21,675 --> 00:30:22,925\ncalled Peter Henderson.\n\n483\n00:30:22,925 --> 00:30:28,130\n\n\n484\n00:30:28,130 --> 00:30:29,800\nPeter Henderson is\nat the University\n\n485\n00:30:29,800 --> 00:30:32,870\nof Stirling in Scotland.\n\n486\n00:30:32,870 --> 00:30:39,170\nAnd what this language is about\nis making figures that\n\n487\n00:30:39,170 --> 00:30:42,090\nsort of look like this.\n\n488\n00:30:42,090 --> 00:30:49,470\nThis is this is a woodcut by\nEscher called \"Square Limit.\"\n\n489\n00:30:49,470 --> 00:30:52,860\nYou, sort of, see it has this\ncomplicated, kind of,\n\n490\n00:30:52,860 --> 00:30:59,170\nrecursive, sort of, recursive\nkind of figure, where there's\n\n491\n00:30:59,170 --> 00:31:02,060\nthis fish pattern in the middle\nand things sort of\n\n492\n00:31:02,060 --> 00:31:04,570\nbleed out smaller and smaller\nin self similar ways.\n\n493\n00:31:04,570 --> 00:31:08,610\n\n\n494\n00:31:08,610 --> 00:31:11,450\nAnyway, Peter Henderson's\nlanguage was for describing\n\n495\n00:31:11,450 --> 00:31:15,990\nfigures that look like that and\ndesigning new ones that\n\n496\n00:31:15,990 --> 00:31:20,240\nlook like that and drawing\nthem on a display screen.\n\n497\n00:31:20,240 --> 00:31:26,930\nThere's another theme that we'll\nsee illustrated by this\n\n498\n00:31:26,930 --> 00:31:31,030\nexample, and that's the issue\nof what Gerry and I have\n\n499\n00:31:31,030 --> 00:31:34,300\nalready mentioned a lot: that\nthere's no real difference, in\n\n500\n00:31:34,300 --> 00:31:37,340\nsome sense, between procedures\nand data.\n\n501\n00:31:37,340 --> 00:31:41,820\nAnd anyway I hope by the end of\nthis morning, if you're not\n\n502\n00:31:41,820 --> 00:31:45,470\nalready, you will be completely\nconfused about what\n\n503\n00:31:45,470 --> 00:31:47,715\nthe difference between\nprocedures and data are, if\n\n504\n00:31:47,715 --> 00:31:51,190\nyou're not confused about\nthat already.\n\n505\n00:31:51,190 --> 00:31:55,370\nWell in any case, let's start\ndescribing Peter's language.\n\n506\n00:31:55,370 --> 00:31:58,410\nI should start by telling you\nwhat the primitives are.\n\n507\n00:31:58,410 --> 00:31:59,690\nThis language is very\nsimple because\n\n508\n00:31:59,690 --> 00:32:00,940\nthere's only one primitive.\n\n509\n00:32:00,940 --> 00:32:03,380\n\n\n510\n00:32:03,380 --> 00:32:07,480\nA primitive is not quite\nwhat you think it is.\n\n511\n00:32:07,480 --> 00:32:09,970\nThere's only one primitive\ncalled a picture, and a\n\n512\n00:32:09,970 --> 00:32:12,200\npicture is not quite what\nyou think it is.\n\n513\n00:32:12,200 --> 00:32:13,950\nHere's an example.\n\n514\n00:32:13,950 --> 00:32:15,220\nThis is a picture of George.\n\n515\n00:32:15,220 --> 00:32:18,980\n\n\n516\n00:32:18,980 --> 00:32:23,990\nThe idea is that a picture in\nthis language is going to be\n\n517\n00:32:23,990 --> 00:32:30,640\nsomething that draws a figure\nscaled to fit a rectangle that\n\n518\n00:32:30,640 --> 00:32:33,030\nyou specify.\n\n519\n00:32:33,030 --> 00:32:34,200\nSo here you see in [? Saint ?]\n\n520\n00:32:34,200 --> 00:32:34,570\n[? Lawrence's ?]\n\n521\n00:32:34,570 --> 00:32:37,070\noutline of a rectangle, that's\nnot really part of the\n\n522\n00:32:37,070 --> 00:32:43,210\npicture, but the picture--\n\n523\n00:32:43,210 --> 00:32:45,270\nyou'll give it a rectangle, and\nit will draw this figure\n\n524\n00:32:45,270 --> 00:32:47,100\nscaled to fit the rectangle.\n\n525\n00:32:47,100 --> 00:32:50,930\nSo for example, there's\nGeorge, and here,\n\n526\n00:32:50,930 --> 00:32:52,840\nthis is also George.\n\n527\n00:32:52,840 --> 00:32:55,480\nIt's the same picture,\nright, just scaled to\n\n528\n00:32:55,480 --> 00:32:57,920\nfit a different rectangle.\n\n529\n00:32:57,920 --> 00:32:59,290\nHere's George as a fat kid.\n\n530\n00:32:59,290 --> 00:33:02,400\n\n\n531\n00:33:02,400 --> 00:33:03,920\nThat's the same George.\n\n532\n00:33:03,920 --> 00:33:05,260\nIt's all the same figure.\n\n533\n00:33:05,260 --> 00:33:07,810\nAll of these three things\nare the same\n\n534\n00:33:07,810 --> 00:33:09,670\npicture in this language.\n\n535\n00:33:09,670 --> 00:33:12,900\nI'm just giving it different\nrectangles to scale itself in.\n\n536\n00:33:12,900 --> 00:33:16,300\n\n\n537\n00:33:16,300 --> 00:33:19,150\nOK, those are the primitives.\n\n538\n00:33:19,150 --> 00:33:21,420\nThat is the primitive.\n\n539\n00:33:21,420 --> 00:33:24,440\nNow let's start talking about\nthe means of combination and\n\n540\n00:33:24,440 --> 00:33:25,960\nthe operations.\n\n541\n00:33:25,960 --> 00:33:31,080\nThere is, for example, an\noperation called Rotate.\n\n542\n00:33:31,080 --> 00:33:35,900\nAnd what Rotate does is, if I\nhave a picture, say a picture\n\n543\n00:33:35,900 --> 00:33:42,080\nthat draws an \"A\" in some\nrectangle that I give it, the\n\n544\n00:33:42,080 --> 00:33:43,080\nRotate of that--\n\n545\n00:33:43,080 --> 00:33:47,490\nsay the Rotate by 90 degrees\nwould, if I give it a\n\n546\n00:33:47,490 --> 00:33:52,850\nrectangle, draw the same image,\nbut again, scaled to\n\n547\n00:33:52,850 --> 00:33:54,100\nfit that rectangle.\n\n548\n00:33:54,100 --> 00:33:56,160\n\n\n549\n00:33:56,160 --> 00:33:58,400\nSo that's Rotate\nby 90 degrees.\n\n550\n00:33:58,400 --> 00:34:00,700\nThere's another operation called\nFlip that can flip\n\n551\n00:34:00,700 --> 00:34:04,351\nsomething, either horizontally\nor vertically.\n\n552\n00:34:04,351 --> 00:34:06,450\nAll right, so those are, sort\nof, operations, or you can\n\n553\n00:34:06,450 --> 00:34:11,010\nthink of those as means of\ncombination of one element.\n\n554\n00:34:11,010 --> 00:34:12,880\nI can put things together.\n\n555\n00:34:12,880 --> 00:34:17,350\nThere's a means of combination\ncalled Beside, and what Beside\n\n556\n00:34:17,350 --> 00:34:24,525\ndoes: it'll take two pictures,\nlet's say A and B--\n\n557\n00:34:24,525 --> 00:34:29,489\n\n\n558\n00:34:29,489 --> 00:34:31,230\nand by picture I mean something\nthat's going to draw\n\n559\n00:34:31,230 --> 00:34:34,159\nan image in a specified\nrectangle--\n\n560\n00:34:34,159 --> 00:34:38,159\nand what Beside will do--\n\n561\n00:34:38,159 --> 00:34:42,719\nI have to say, Beside of A and\nB, the side of two pictures\n\n562\n00:34:42,719 --> 00:34:45,590\nand some number, s.\n\n563\n00:34:45,590 --> 00:34:47,639\nAnd s will be a number\nbetween zero and one.\n\n564\n00:34:47,639 --> 00:34:50,960\n\n\n565\n00:34:50,960 --> 00:34:52,620\nAnd Beside will draw a picture\nthat looks like this.\n\n566\n00:34:52,620 --> 00:34:55,100\nIt will take the rectangle\nyou give it and\n\n567\n00:34:55,100 --> 00:34:56,480\nscale its base by s.\n\n568\n00:34:56,480 --> 00:34:57,730\nSay s is 0.5.\n\n569\n00:34:57,730 --> 00:35:00,240\n\n\n570\n00:35:00,240 --> 00:35:04,980\nAnd then over here\nit will draw--\n\n571\n00:35:04,980 --> 00:35:12,070\nit'll put the first picture,\nand over here it'll put the\n\n572\n00:35:12,070 --> 00:35:14,100\nsecond picture.\n\n573\n00:35:14,100 --> 00:35:17,250\nOr for instance if I gave it a\ndifferent value of s, if I\n\n574\n00:35:17,250 --> 00:35:27,390\nsaid Beside with a 0.25, it\nwould do the same thing,\n\n575\n00:35:27,390 --> 00:35:28,640\nexcept the A would\nbe much skinnier.\n\n576\n00:35:28,640 --> 00:35:32,230\n\n\n577\n00:35:32,230 --> 00:35:38,230\nSo it would draw something\nlike that.\n\n578\n00:35:38,230 --> 00:35:41,110\nSo there's a means of\ncombination Beside, and\n\n579\n00:35:41,110 --> 00:35:43,410\nsimilarly there's an Above,\nwhich does the same thing\n\n580\n00:35:43,410 --> 00:35:45,230\nexcept it puts them vertically\ninstead of horizontally.\n\n581\n00:35:45,230 --> 00:35:47,990\n\n\n582\n00:35:47,990 --> 00:35:50,470\nWell let's look at that.\n\n583\n00:35:50,470 --> 00:35:58,830\nAll right, there's George and\nhis kid brother, which is,\n\n584\n00:35:58,830 --> 00:36:10,630\nright, constructed by taking\nGeorge and putting him Beside\n\n585\n00:36:10,630 --> 00:36:11,760\nthe Above--\n\n586\n00:36:11,760 --> 00:36:13,440\ntaking the empty picture, and\nthere's a thing called the\n\n587\n00:36:13,440 --> 00:36:16,650\nempty picture, which does\nthe obvious thing--\n\n588\n00:36:16,650 --> 00:36:19,515\nputting the empty picture above\na copy of George, and\n\n589\n00:36:19,515 --> 00:36:21,100\nthen putting that whole\nthing Beside George.\n\n590\n00:36:21,100 --> 00:36:28,900\n\n\n591\n00:36:28,900 --> 00:36:38,230\nHere's something called P which\nis, again, George Beside\n\n592\n00:36:38,230 --> 00:36:42,550\nFlipping George, I think,\nhorizontally in this case, and\n\n593\n00:36:42,550 --> 00:36:46,400\nthen Rotating the whole result\n180 degrees and putting them\n\n594\n00:36:46,400 --> 00:36:50,510\nBeside one another with the\nbasic rectangle divided at\n\n595\n00:36:50,510 --> 00:36:59,320\n0.5, right, and I can call that\nP. And then I can take P,\n\n596\n00:36:59,320 --> 00:37:04,100\nand put it above the Flipped\ncopy of itself, and I can call\n\n597\n00:37:04,100 --> 00:37:09,650\nthat Q.\n\n598\n00:37:09,650 --> 00:37:15,570\nNotice how rapidly that we've\nbuilt up complexity, just in,\n\n599\n00:37:15,570 --> 00:37:18,640\nyou know, 15 seconds, you've\ngotten from George to that\n\n600\n00:37:18,640 --> 00:37:22,260\nthing Q. Why is that?\n\n601\n00:37:22,260 --> 00:37:26,100\nHow are how we able to\ndo that so fast?\n\n602\n00:37:26,100 --> 00:37:28,670\nThe answer is the closure\nproperty.\n\n603\n00:37:28,670 --> 00:37:31,810\nSee, it's the fact that when\nI take a picture and put it\n\n604\n00:37:31,810 --> 00:37:35,560\nBeside another picture, that's\nthen, again, a picture that I\n\n605\n00:37:35,560 --> 00:37:39,090\ncan go and Rotate and Flip or\nput Above something else.\n\n606\n00:37:39,090 --> 00:37:41,645\nRight, and when I take that\nelement P, which is the Beside\n\n607\n00:37:41,645 --> 00:37:43,450\nor the Flip or the Rotate\nof something,\n\n608\n00:37:43,450 --> 00:37:45,560\nthat's, again, a picture.\n\n609\n00:37:45,560 --> 00:37:49,420\nRight, the world of pictures is\nclosed under those means of\n\n610\n00:37:49,420 --> 00:37:50,830\ncombination.\n\n611\n00:37:50,830 --> 00:37:53,570\nSo whenever I have something,\nI can turn right around and\n\n612\n00:37:53,570 --> 00:37:56,480\nuse that as an element\nin something else.\n\n613\n00:37:56,480 --> 00:37:59,010\nSo maybe better than List and\nsegments, that just gives you\n\n614\n00:37:59,010 --> 00:38:02,020\nan image for how fast you can\nbuild up complexity, because\n\n615\n00:38:02,020 --> 00:38:03,270\noperations are closed.\n\n616\n00:38:03,270 --> 00:38:07,500\n\n\n617\n00:38:07,500 --> 00:38:12,440\nOK, well before we go on with\nbuilding more things, let's\n\n618\n00:38:12,440 --> 00:38:14,345\ntalk about how this language\nis actually implemented.\n\n619\n00:38:14,345 --> 00:38:17,200\n\n\n620\n00:38:17,200 --> 00:38:23,270\nThe basic element that sits\nunder the table here is a\n\n621\n00:38:23,270 --> 00:38:27,610\nthing called a rectangle, and\nwhat a rectangle is going to\n\n622\n00:38:27,610 --> 00:38:36,900\nbe, it's a thing that specified\nby an origin that's\n\n623\n00:38:36,900 --> 00:38:38,910\ngoing to be some vector\nthat says where\n\n624\n00:38:38,910 --> 00:38:40,390\nthe rectangle starts.\n\n625\n00:38:40,390 --> 00:38:44,020\nAnd then there's going to be\nsome other vector that I'm\n\n626\n00:38:44,020 --> 00:38:49,020\ngoing to call the horizontal\npart of the rectangle, and\n\n627\n00:38:49,020 --> 00:38:57,650\nanother picture called the\n\n628\n00:38:57,650 --> 00:39:00,640\nvertical part of the rectangle.\n\n629\n00:39:00,640 --> 00:39:03,790\nAnd those three pieces are the\nelements: where the lower\n\n630\n00:39:03,790 --> 00:39:08,200\nvertex is, how you get to the\nnext vertex over here, and how\n\n631\n00:39:08,200 --> 00:39:09,630\nyou get to the vertex\nover there.\n\n632\n00:39:09,630 --> 00:39:11,590\nThe three vectors specify\na rectangle.\n\n633\n00:39:11,590 --> 00:39:16,080\n\n\n634\n00:39:16,080 --> 00:39:18,380\nNow to actually build\nrectangles, what I'll assume\n\n635\n00:39:18,380 --> 00:39:23,380\nis that we have a constructor\ncalled \"make rectangle,\" or\n\n636\n00:39:23,380 --> 00:39:37,910\n\"make-rect,\" and selectors for\nhoriz and vert and origin that\n\n637\n00:39:37,910 --> 00:39:39,720\nget out the pieces of\nthat rectangle.\n\n638\n00:39:39,720 --> 00:39:42,500\nAnd well, you know a lot of\nways you can do this now.\n\n639\n00:39:42,500 --> 00:39:47,190\nYou can do it by using pairs in\nsome way or other standard\n\n640\n00:39:47,190 --> 00:39:47,670\nList or not.\n\n641\n00:39:47,670 --> 00:39:50,130\nBut in any case, the\nimplementation of these\n\n642\n00:39:50,130 --> 00:39:51,320\nthings, that's George's\nproblem.\n\n643\n00:39:51,320 --> 00:39:53,300\nIt's just a data representation\nproblem.\n\n644\n00:39:53,300 --> 00:39:55,500\nSo let's assume we have these\nrectangles to work with.\n\n645\n00:39:55,500 --> 00:39:58,902\n\n\n646\n00:39:58,902 --> 00:40:00,152\nOK.\n\n647\n00:40:00,152 --> 00:40:02,310\n\n\n648\n00:40:02,310 --> 00:40:05,090\nNow the idea of this, remember\nwhat's got to happen.\n\n649\n00:40:05,090 --> 00:40:10,250\nSomehow we have to worry about\ntaking the figure and scaling\n\n650\n00:40:10,250 --> 00:40:15,260\nit to fit some rectangle that\nyou give it, that's the basic\n\n651\n00:40:15,260 --> 00:40:18,340\nthing you have to arrange, that\nthese pictures can do.\n\n652\n00:40:18,340 --> 00:40:22,440\n\n\n653\n00:40:22,440 --> 00:40:23,460\nHow do we think about that?\n\n654\n00:40:23,460 --> 00:40:26,010\nWell, one way to think about\nthat is that any time I give\n\n655\n00:40:26,010 --> 00:40:40,050\nyou a rectangle, that defines,\nin some sense, a\n\n656\n00:40:40,050 --> 00:40:43,340\ntransformation from\nthe standard\n\n657\n00:40:43,340 --> 00:40:45,685\nsquare into that rectangle.\n\n658\n00:40:45,685 --> 00:40:46,960\nLet me say what I mean.\n\n659\n00:40:46,960 --> 00:40:49,540\nBy the standard square, I'll\nmean something, which is a\n\n660\n00:40:49,540 --> 00:40:58,420\nsquare whose coordinates are\n0,0, and 1,0, and 0,1 and 1,1.\n\n661\n00:40:58,420 --> 00:41:01,830\n\n\n662\n00:41:01,830 --> 00:41:04,590\nAnd there's some sort of\nthe obvious scaling\n\n663\n00:41:04,590 --> 00:41:10,180\ntransformation, which maps this\nto that and this to that,\n\n664\n00:41:10,180 --> 00:41:11,920\nand sort of, stretches\neverything uniformly.\n\n665\n00:41:11,920 --> 00:41:22,755\nSo we take a line segment like\nthis and end up mapping it to\n\n666\n00:41:22,755 --> 00:41:31,390\na line segment like that, so\nsome point xy goes to some\n\n667\n00:41:31,390 --> 00:41:33,000\nother point up there.\n\n668\n00:41:33,000 --> 00:41:36,870\nAnd although it's not important,\nwith a little\n\n669\n00:41:36,870 --> 00:41:39,190\nvector algebra, you could\nwrite that formula.\n\n670\n00:41:39,190 --> 00:41:43,670\nThe thing that xy goes to, the\npoint that xy goes to is\n\n671\n00:41:43,670 --> 00:41:48,950\ngotten by taking the origin of\nthe rectangle and then adding\n\n672\n00:41:48,950 --> 00:41:51,280\nthat as a vector to--\n\n673\n00:41:51,280 --> 00:41:54,300\nwell, take x, the x coordinate,\nwhich is something\n\n674\n00:41:54,300 --> 00:42:01,030\nbetween zero and one, multiply\nthat by the horizontal vector\n\n675\n00:42:01,030 --> 00:42:09,670\nof the rectangle; and take the\ny coordinate, which is also\n\n676\n00:42:09,670 --> 00:42:14,460\nsomething between zero and one\nand multiply that by the\n\n677\n00:42:14,460 --> 00:42:16,690\nvertical vector of\nthe rectangle.\n\n678\n00:42:16,690 --> 00:42:19,280\nThat's just a little\nlinear algebra.\n\n679\n00:42:19,280 --> 00:42:22,600\nAnyway, that's the formula,\nwhich is the right obvious\n\n680\n00:42:22,600 --> 00:42:26,100\ntransformation that takes things\ninto the unit square,\n\n681\n00:42:26,100 --> 00:42:27,760\ninto the interior of\nthat rectangle.\n\n682\n00:42:27,760 --> 00:42:31,790\n\n\n683\n00:42:31,790 --> 00:42:35,200\nOK well, let's actually look\nat that as a procedure.\n\n684\n00:42:35,200 --> 00:42:39,830\nSo what we want is the thing\nwhich tells us that particular\n\n685\n00:42:39,830 --> 00:42:44,070\ntransformation that a\nrectangle defines.\n\n686\n00:42:44,070 --> 00:42:45,860\nSo here's the procedure.\n\n687\n00:42:45,860 --> 00:42:48,010\nI'll call it coordinate-map.\n\n688\n00:42:48,010 --> 00:42:51,180\nCoordinate-map is the thing that\ntakes as its argument a\n\n689\n00:42:51,180 --> 00:42:57,605\nrectangle and returns for you\na procedure on points.\n\n690\n00:42:57,605 --> 00:43:00,690\n\n\n691\n00:43:00,690 --> 00:43:03,600\nRight, so for each rectangle you\nget a way of transforming\n\n692\n00:43:03,600 --> 00:43:07,310\na point xy into that\nrectangle.\n\n693\n00:43:07,310 --> 00:43:08,020\nAnd how do you get it?\n\n694\n00:43:08,020 --> 00:43:08,750\nWell I just--\n\n695\n00:43:08,750 --> 00:43:10,890\nwriting in List what I wrote\nthere on the blackboard--\n\n696\n00:43:10,890 --> 00:43:18,300\nI add to the origin\nof the rectangle\n\n697\n00:43:18,300 --> 00:43:20,540\nthe result of adding--\n\n698\n00:43:20,540 --> 00:43:26,080\nI take the horizontal part of\nthe rectangle; I scale that by\n\n699\n00:43:26,080 --> 00:43:29,880\nthe x coordinate of the point.\n\n700\n00:43:29,880 --> 00:43:33,750\nI take the vertical vector\nof the rectangle.\n\n701\n00:43:33,750 --> 00:43:37,720\nI scale that by the y coordinate\nof the point, and\n\n702\n00:43:37,720 --> 00:43:40,380\nthen add all those\nthree things up.\n\n703\n00:43:40,380 --> 00:43:41,320\nThat's the procedure.\n\n704\n00:43:41,320 --> 00:43:44,045\nThat is the procedure that I'm\ngoing to apply to a point.\n\n705\n00:43:44,045 --> 00:43:46,890\n\n\n706\n00:43:46,890 --> 00:43:53,170\nAnd this whole thing is\ngenerated for each rectangle.\n\n707\n00:43:53,170 --> 00:43:55,900\nSo any rectangle defines a\ncoordinate MAP, which is a\n\n708\n00:43:55,900 --> 00:43:59,370\nprocedure on points.\n\n709\n00:43:59,370 --> 00:44:00,620\nOK.\n\n710\n00:44:00,620 --> 00:44:06,720\n\n\n711\n00:44:06,720 --> 00:44:12,020\nAll right, so for example,\nGeorge here, my original\n\n712\n00:44:12,020 --> 00:44:14,900\nGeorge, might have been\nsomething that I specified by\n\n713\n00:44:14,900 --> 00:44:20,970\nsegments in the unit square, and\nthen for each rectangle I\n\n714\n00:44:20,970 --> 00:44:27,600\ngive this thing, I'm going to\ndraw those segments inside\n\n715\n00:44:27,600 --> 00:44:28,180\nthat rectangle.\n\n716\n00:44:28,180 --> 00:44:30,630\nHow actually do I do that?\n\n717\n00:44:30,630 --> 00:44:35,820\nWell I take each segment in my\noriginal reference George that\n\n718\n00:44:35,820 --> 00:44:40,080\nwas specified, and to each of\nthe end points of those\n\n719\n00:44:40,080 --> 00:44:42,490\nsegments, I applied the\ncoordinate MAP of the\n\n720\n00:44:42,490 --> 00:44:44,440\nparticular rectangle I\nwant to draw it in.\n\n721\n00:44:44,440 --> 00:44:47,530\nSo for example, this lower\nrectangle, this George as a\n\n722\n00:44:47,530 --> 00:44:51,370\nfat kid rectangle, has\nits coordinate MAP.\n\n723\n00:44:51,370 --> 00:44:56,310\nAnd if I want to draw this\nimage, what I do is for each\n\n724\n00:44:56,310 --> 00:45:01,500\nsegment here, say for this\nsegment, I transformed that\n\n725\n00:45:01,500 --> 00:45:04,600\npoint by the coordinate MAP,\ntransform that point by the\n\n726\n00:45:04,600 --> 00:45:04,990\ncoordinate MAP.\n\n727\n00:45:04,990 --> 00:45:07,890\nThat will give me this point\nand that point and draw the\n\n728\n00:45:07,890 --> 00:45:10,150\nsegment between them.\n\n729\n00:45:10,150 --> 00:45:12,970\nRight, that's the idea.\n\n730\n00:45:12,970 --> 00:45:14,570\nRight, and if I give it a\ndifferent rectangle like this\n\n731\n00:45:14,570 --> 00:45:16,200\none, that's a different\ncoordinate MAP, so I get a\n\n732\n00:45:16,200 --> 00:45:19,281\ndifferent image of those\nline segments.\n\n733\n00:45:19,281 --> 00:45:22,500\nWell how do we actually get\na picture to start with?\n\n734\n00:45:22,500 --> 00:45:25,250\nI can build a picture to start\nwith out of a List of line\n\n735\n00:45:25,250 --> 00:45:27,750\nsegments initially.\n\n736\n00:45:27,750 --> 00:45:31,680\nHere's a procedure that builds\nwhat I'll call a primitive\n\n737\n00:45:31,680 --> 00:45:35,570\npicture, meaning one I, sort of,\ngot that didn't come out\n\n738\n00:45:35,570 --> 00:45:37,680\nof Beside or Rotate\nor something.\n\n739\n00:45:37,680 --> 00:45:43,270\nIt starts with a List of\nline segments, and now\n\n740\n00:45:43,270 --> 00:45:44,090\nit does what I said.\n\n741\n00:45:44,090 --> 00:45:45,600\nWhat's a picture have to be?\n\n742\n00:45:45,600 --> 00:45:48,790\nFirst of all it's a procedure\nthat's defined on rectangles.\n\n743\n00:45:48,790 --> 00:45:52,060\n\n\n744\n00:45:52,060 --> 00:45:53,190\nWhat does it do?\n\n745\n00:45:53,190 --> 00:45:54,880\nIt says for each--\n\n746\n00:45:54,880 --> 00:45:57,480\nthis is going to be a List\nof line segments--\n\n747\n00:45:57,480 --> 00:46:02,510\nfor each segment, for each s,\nwhich is a segment in this\n\n748\n00:46:02,510 --> 00:46:07,410\nList of segments, well\nit draws a line.\n\n749\n00:46:07,410 --> 00:46:10,690\nWhat line does it draw?\n\n750\n00:46:10,690 --> 00:46:16,230\nIt gets the start point of that\nsegment, transforms that\n\n751\n00:46:16,230 --> 00:46:19,920\nby the coordinate MAP\nof the rectangle.\n\n752\n00:46:19,920 --> 00:46:21,830\nThat's the first new point\nit wants to do.\n\n753\n00:46:21,830 --> 00:46:24,160\nThen it takes the endpoint of\nthe segment, transforms that\n\n754\n00:46:24,160 --> 00:46:27,310\nby the coordinate MAP of the\nrectangle, and then draws a\n\n755\n00:46:27,310 --> 00:46:27,990\nline between.\n\n756\n00:46:27,990 --> 00:46:30,180\nLet's assume drawline is some\nprimitive that's built into\n\n757\n00:46:30,180 --> 00:46:34,250\nthe system that actually draws\na line on the display.\n\n758\n00:46:34,250 --> 00:46:35,980\nAll right, so it transforms\nthe endpoints by the\n\n759\n00:46:35,980 --> 00:46:37,670\ncoordinate MAP of the rectangle,\ndraws a line\n\n760\n00:46:37,670 --> 00:46:43,110\nbetween them, does that\nfor each s in\n\n761\n00:46:43,110 --> 00:46:46,220\nthis List of segments.\n\n762\n00:46:46,220 --> 00:46:49,000\nAnd now remember again, a\npicture is a procedure that\n\n763\n00:46:49,000 --> 00:46:51,550\ntakes a rectangle as argument.\n\n764\n00:46:51,550 --> 00:46:53,610\nSo when you hand it a rectangle,\nthis is what it\n\n765\n00:46:53,610 --> 00:46:57,140\ndoes: draws those lines.\n\n766\n00:46:57,140 --> 00:46:59,690\nAll right, so there's--\n\n767\n00:46:59,690 --> 00:47:01,260\nhow would I actually\nuse this thing?\n\n768\n00:47:01,260 --> 00:47:03,325\nLet's make it a little\nbit more concrete.\n\n769\n00:47:03,325 --> 00:47:05,890\n\n\n770\n00:47:05,890 --> 00:47:21,070\nRight, I would say for instance,\ndefine R to be\n\n771\n00:47:21,070 --> 00:47:26,520\nmake-rectangle of some stuff,\nand I'd have to specify some\n\n772\n00:47:26,520 --> 00:47:30,080\nvectors here using\nmake-vector.\n\n773\n00:47:30,080 --> 00:47:45,010\nAnd then I could say, define\nsay, G to be make-picture, and\n\n774\n00:47:45,010 --> 00:47:47,100\nthen some stuff.\n\n775\n00:47:47,100 --> 00:47:51,540\nAnd what I'd have to specify\nhere is a List of line\n\n776\n00:47:51,540 --> 00:47:55,250\nsegments, right, using\nmake segment.\n\n777\n00:47:55,250 --> 00:47:57,480\nMake-segment might be made out\nof vectors, and vectors might\n\n778\n00:47:57,480 --> 00:47:59,610\nbe made out of points.\n\n779\n00:47:59,610 --> 00:48:03,970\nAnd then if I actually wanted to\nsee the image of G inside a\n\n780\n00:48:03,970 --> 00:48:10,280\nrectangle, well a picture is\na procedure that takes a\n\n781\n00:48:10,280 --> 00:48:11,940\nrectangle as argument.\n\n782\n00:48:11,940 --> 00:48:18,720\nSo if I then called G with an\ninput of R, that would cause\n\n783\n00:48:18,720 --> 00:48:22,520\nwhatever image G is worrying\nabout to be drawn inside the\n\n784\n00:48:22,520 --> 00:48:26,722\nrectangle R. Right, so that's\nhow you'd use that.\n\n785\n00:48:26,722 --> 00:49:08,072\n[MUSIC PLAYING]\n\n786\n00:49:08,072 --> 00:49:12,530\nPROFESSOR: Well why is it that\nI say this example is nice?\n\n787\n00:49:12,530 --> 00:49:13,680\nYou probably don't\nthink it's nice.\n\n788\n00:49:13,680 --> 00:49:15,540\nYou probably think it's\nmore weird than nice.\n\n789\n00:49:15,540 --> 00:49:18,740\nRight, representing these\npictures as procedures, which\n\n790\n00:49:18,740 --> 00:49:21,430\ndo complicated things\nwith rectangles.\n\n791\n00:49:21,430 --> 00:49:22,680\nSo why is it nice?\n\n792\n00:49:22,680 --> 00:49:25,460\n\n\n793\n00:49:25,460 --> 00:49:29,070\nThe reason it's nice is that\nonce you've implemented the\n\n794\n00:49:29,070 --> 00:49:32,670\nprimitives in this way, the\nmeans of combination just fall\n\n795\n00:49:32,670 --> 00:49:36,390\nout by implementing\nprocedures.\n\n796\n00:49:36,390 --> 00:49:37,400\nLet me show you what I mean.\n\n797\n00:49:37,400 --> 00:49:38,650\nSuppose we want to\nimplement Beside.\n\n798\n00:49:38,650 --> 00:49:41,980\n\n\n799\n00:49:41,980 --> 00:49:44,040\nSo I'd like to--\n\n800\n00:49:44,040 --> 00:49:46,310\nsuppose I've got a picture.\n\n801\n00:49:46,310 --> 00:49:47,620\nLet's call it P1.\n\n802\n00:49:47,620 --> 00:49:49,500\nP1 is going to be-- and\nnow remember what a\n\n803\n00:49:49,500 --> 00:49:50,780\npicture really is.\n\n804\n00:49:50,780 --> 00:49:56,800\nIt's a thing that if you can\nhand it some rectangle, it\n\n805\n00:49:56,800 --> 00:50:00,920\nwill cause an image to be drawn\nin whatever rectangle\n\n806\n00:50:00,920 --> 00:50:03,520\nyou hand it.\n\n807\n00:50:03,520 --> 00:50:08,210\nAnd suppose P2 two is some other\npicture, and you hand\n\n808\n00:50:08,210 --> 00:50:09,570\nthat a rectangle.\n\n809\n00:50:09,570 --> 00:50:11,220\nAnd whatever rectangle\nyou hand it,\n\n810\n00:50:11,220 --> 00:50:12,470\nit draws some picture.\n\n811\n00:50:12,470 --> 00:50:14,920\n\n\n812\n00:50:14,920 --> 00:50:25,230\nAnd now if I'd like to implement\nBeside of P1 and P2\n\n813\n00:50:25,230 --> 00:50:28,380\nwith a scale factor A, well\nwhat does that have to be?\n\n814\n00:50:28,380 --> 00:50:29,950\nThat's got to be picture.\n\n815\n00:50:29,950 --> 00:50:32,440\nIt's got to be a thing that you\nhand it a rectangle, and\n\n816\n00:50:32,440 --> 00:50:34,800\nit draws something in\nthat rectangle.\n\n817\n00:50:34,800 --> 00:50:38,350\nSo if hand Beside\nthis rectangle--\n\n818\n00:50:38,350 --> 00:50:41,206\nlet's hand it a rectangle.\n\n819\n00:50:41,206 --> 00:50:42,860\nWell what's it going to do?\n\n820\n00:50:42,860 --> 00:50:45,900\nit's going to take this\nrectangle and split it into\n\n821\n00:50:45,900 --> 00:50:53,470\ntwo at a ratio of A and one\nminus A. And it will say, oh\n\n822\n00:50:53,470 --> 00:50:54,895\nsure, now I've got\ntwo rectangles.\n\n823\n00:50:54,895 --> 00:51:02,370\n\n\n824\n00:51:02,370 --> 00:51:05,560\nAnd now it goes off to P1 and\nsays P1, well draw yourself in\n\n825\n00:51:05,560 --> 00:51:10,220\nthis rectangle, and goes off\nto P2, and says, P2, fine,\n\n826\n00:51:10,220 --> 00:51:13,490\ndraw yourself in\nthis rectangle.\n\n827\n00:51:13,490 --> 00:51:15,690\nThe only computation it has to\ndo is figure out what these\n\n828\n00:51:15,690 --> 00:51:17,550\nrectangles are.\n\n829\n00:51:17,550 --> 00:51:21,660\nRemember a rectangle is\nspecified by an origin and a\n\n830\n00:51:21,660 --> 00:51:24,480\nhorizontal vector and a vertical\nvector, so it's got\n\n831\n00:51:24,480 --> 00:51:27,400\nto figure out what\nthese things are.\n\n832\n00:51:27,400 --> 00:51:30,740\nSo for this first rectangle, the\norigin turns out to be the\n\n833\n00:51:30,740 --> 00:51:34,370\norigin of the original\nrectangle, and the vertical\n\n834\n00:51:34,370 --> 00:51:36,810\nvector is the same as the\nvertical vector of the\n\n835\n00:51:36,810 --> 00:51:38,930\noriginal rectangle.\n\n836\n00:51:38,930 --> 00:51:43,510\nThe horizontal vector is the\nhorizontal vector of the\n\n837\n00:51:43,510 --> 00:51:47,740\noriginal rectangle\nscaled by A. And\n\n838\n00:51:47,740 --> 00:51:49,680\nthat's the first rectangle.\n\n839\n00:51:49,680 --> 00:51:55,390\nThe second rectangle, the origin\nis the original origin\n\n840\n00:51:55,390 --> 00:52:01,910\nplus that horizontal vector\nscaled by A. The horizontal\n\n841\n00:52:01,910 --> 00:52:05,060\nvector of the second rectangle\nis the rest of the horizontal\n\n842\n00:52:05,060 --> 00:52:10,780\nvector of the first one, which\nis 1 minus A times the\n\n843\n00:52:10,780 --> 00:52:15,660\noriginal H, and the vertical\nvector is still v. But\n\n844\n00:52:15,660 --> 00:52:17,570\nbasically it goes and\nconstructs these two\n\n845\n00:52:17,570 --> 00:52:19,890\nrectangles, and the important\npoint is having constructed\n\n846\n00:52:19,890 --> 00:52:22,940\nthe rectangles, it says OK,\np1, you draw yourself in\n\n847\n00:52:22,940 --> 00:52:25,080\nthere, and p2, you draw yourself\nin there, and that's\n\n848\n00:52:25,080 --> 00:52:27,480\nall Beside has to do.\n\n849\n00:52:27,480 --> 00:52:29,115\nAll right, let's look at\nthat piece of code.\n\n850\n00:52:29,115 --> 00:52:34,500\n\n\n851\n00:52:34,500 --> 00:52:45,420\nBeside of a picture and another\npicture with some\n\n852\n00:52:45,420 --> 00:52:51,030\nscaling ratio is first of all,\nsince it's a picture, a\n\n853\n00:52:51,030 --> 00:52:55,590\nprocedure that's going to take\na rectangle as argument.\n\n854\n00:52:55,590 --> 00:52:57,050\nWhat's it going to do?\n\n855\n00:52:57,050 --> 00:53:00,650\nIt says, p1 draw yourself in\nsome rectangle and p2 draw\n\n856\n00:53:00,650 --> 00:53:03,190\nyourself in some other\nrectangle.\n\n857\n00:53:03,190 --> 00:53:04,530\nAnd now what are those\nrectangles?\n\n858\n00:53:04,530 --> 00:53:05,550\nWell here's the computation.\n\n859\n00:53:05,550 --> 00:53:08,680\nIt makes a rectangle, and this\nis the algebra I just did on\n\n860\n00:53:08,680 --> 00:53:11,140\nthe board: the origin,\nsomething; the horizontal\n\n861\n00:53:11,140 --> 00:53:13,030\nvector, something; and the\nvertical vector, something.\n\n862\n00:53:13,030 --> 00:53:17,790\nAnd for p2, the rectangle it\nwants has some other origin\n\n863\n00:53:17,790 --> 00:53:19,820\nand horizontal vector\nand vertical vector.\n\n864\n00:53:19,820 --> 00:53:23,330\nBut the important point is that\nall it's saying is, p1,\n\n865\n00:53:23,330 --> 00:53:25,990\ngo do your thing in one\nrectangle, and p2, go do your\n\n866\n00:53:25,990 --> 00:53:27,890\nthing in another rectangle.\n\n867\n00:53:27,890 --> 00:53:30,920\nThat's all the Beside\nhas to do.\n\n868\n00:53:30,920 --> 00:53:37,060\nOK, similarly Rotate--\n\n869\n00:53:37,060 --> 00:53:44,180\nsee if I have this picture A,\nand I want to look at say\n\n870\n00:53:44,180 --> 00:53:51,050\nrotating A by 90 degrees, what\nthat should mean is, well take\n\n871\n00:53:51,050 --> 00:53:57,010\nthis rectangle, which is origin\nand horizontal vector\n\n872\n00:53:57,010 --> 00:54:01,570\nand vertical vector, and now\npretend that it's really the\n\n873\n00:54:01,570 --> 00:54:05,710\nrectangle that looks like this,\nwhich has an origin and\n\n874\n00:54:05,710 --> 00:54:09,690\na horizontal vector up here, and\na vertical vector there,\n\n875\n00:54:09,690 --> 00:54:13,620\nand now draw yourself with\nrespect to that rectangle.\n\n876\n00:54:13,620 --> 00:54:17,120\nLet me show you that\nas a procedure.\n\n877\n00:54:17,120 --> 00:54:21,570\nAll right, so we'll Rotate 90 of\nthe picture, because again,\n\n878\n00:54:21,570 --> 00:54:24,870\na procedure for rectangle, which\nsays, OK picture, draw\n\n879\n00:54:24,870 --> 00:54:29,190\nyourself in some rectangle; and\nthen this algebra is the\n\n880\n00:54:29,190 --> 00:54:30,580\ntransformation on\nthe rectangle.\n\n881\n00:54:30,580 --> 00:54:33,370\nIt's the one which makes it\nlook like the rectangle is\n\n882\n00:54:33,370 --> 00:54:35,220\nsideways, the origin is\nsomeplace else and the\n\n883\n00:54:35,220 --> 00:54:37,670\nvertical vector is someplace\nelse, and the horizontal\n\n884\n00:54:37,670 --> 00:54:38,965\nvector is someplace else,\nand vertical vector\n\n885\n00:54:38,965 --> 00:54:41,704\nis someplace else.\n\n886\n00:54:41,704 --> 00:54:43,117\nOK?\n\n887\n00:54:43,117 --> 00:54:44,367\nOK.\n\n888\n00:54:44,367 --> 00:54:46,890\n\n\n889\n00:54:46,890 --> 00:54:50,810\nOK, again notice, the crucial\nthing that's going on here is\n\n890\n00:54:50,810 --> 00:54:57,080\nyou're using the representation\nof pictures as\n\n891\n00:54:57,080 --> 00:55:01,910\nprocedures to automatically\nget the closure property,\n\n892\n00:55:01,910 --> 00:55:05,320\nbecause what happens is, Beside\njust has this thing p1.\n\n893\n00:55:05,320 --> 00:55:08,430\nBeside doesn't care if that's\na primitive picture or it's\n\n894\n00:55:08,430 --> 00:55:11,760\nline segments or if p1 is,\nitself, the result of doing\n\n895\n00:55:11,760 --> 00:55:12,950\nAboves or Besides or Rotates.\n\n896\n00:55:12,950 --> 00:55:17,380\nAll Beside has to know about,\nsay, p1 is that if you hand p1\n\n897\n00:55:17,380 --> 00:55:21,070\na rectangle, it will cause\nsomething to be drawn.\n\n898\n00:55:21,070 --> 00:55:23,550\nAnd above that level, Beside\njust doesn't--\n\n899\n00:55:23,550 --> 00:55:27,321\nit's none of its business how p1\naccomplishes that drawing.\n\n900\n00:55:27,321 --> 00:55:31,140\nAll right, so you're using the\nprocedural representation to\n\n901\n00:55:31,140 --> 00:55:32,390\nensure this closure.\n\n902\n00:55:32,390 --> 00:55:34,440\n\n\n903\n00:55:34,440 --> 00:55:35,830\nOK.\n\n904\n00:55:35,830 --> 00:55:40,010\nSo implementing pictures as\nprocedures makes these means\n\n905\n00:55:40,010 --> 00:55:43,090\nof combination, you know, both\npretty simple and also, I\n\n906\n00:55:43,090 --> 00:55:46,040\nthink, elegant.\n\n907\n00:55:46,040 --> 00:55:49,370\nBut that's not the\nreal punchline.\n\n908\n00:55:49,370 --> 00:55:52,030\nThe real punchline comes when\nyou look at the means of\n\n909\n00:55:52,030 --> 00:55:54,870\nabstraction in this language.\n\n910\n00:55:54,870 --> 00:55:56,300\nBecause what have we done?\n\n911\n00:55:56,300 --> 00:56:02,760\nWe've implemented the means of\ncombination themselves as\n\n912\n00:56:02,760 --> 00:56:04,010\nprocedures.\n\n913\n00:56:04,010 --> 00:56:05,950\n\n\n914\n00:56:05,950 --> 00:56:08,870\nAnd what that means is that when\nwe go to abstract in this\n\n915\n00:56:08,870 --> 00:56:14,890\nlanguage, everything that List\nsupplies us for manipulating\n\n916\n00:56:14,890 --> 00:56:20,600\nprocedures is automatically\navailable to do things in this\n\n917\n00:56:20,600 --> 00:56:22,010\npicture language.\n\n918\n00:56:22,010 --> 00:56:25,520\nThe technical term I want to\nsay is not only is this\n\n919\n00:56:25,520 --> 00:56:29,900\nlanguage implemented in List,\nobviously it is, but the\n\n920\n00:56:29,900 --> 00:56:39,890\nlanguage is nicely embedded\nin List. What I mean is by\n\n921\n00:56:39,890 --> 00:56:44,800\nembedding the language in this\nway, all the power of List is\n\n922\n00:56:44,800 --> 00:56:47,680\nautomatically available\nas an extension to\n\n923\n00:56:47,680 --> 00:56:49,880\nwhatever you want to do.\n\n924\n00:56:49,880 --> 00:56:52,030\nAnd what do I mean by that?\n\n925\n00:56:52,030 --> 00:56:57,410\nExample: say, suppose I want\nto make a thing that takes\n\n926\n00:56:57,410 --> 00:57:06,090\nfour pictures A, B, C and D, and\nmakes a configuration that\n\n927\n00:57:06,090 --> 00:57:07,340\nlooks like this.\n\n928\n00:57:07,340 --> 00:57:12,870\n\n\n929\n00:57:12,870 --> 00:57:14,670\nWell you might call that, you\nknow, four pictures or\n\n930\n00:57:14,670 --> 00:57:17,110\nsomething, four-pict\nconfiguration.\n\n931\n00:57:17,110 --> 00:57:17,740\nHow do I do that?\n\n932\n00:57:17,740 --> 00:57:18,700\nWell I can obviously do that.\n\n933\n00:57:18,700 --> 00:57:26,140\nI just write a procedure that\ntakes B above D and A above C\n\n934\n00:57:26,140 --> 00:57:28,350\nand puts those things\nbeside each other.\n\n935\n00:57:28,350 --> 00:57:31,150\nSo I automatically have List's\nability to do procedure\n\n936\n00:57:31,150 --> 00:57:33,090\ncomposition.\n\n937\n00:57:33,090 --> 00:57:34,960\nAnd I didn't have to make\nthat specifically\n\n938\n00:57:34,960 --> 00:57:35,790\nin the picture language.\n\n939\n00:57:35,790 --> 00:57:38,710\nIt's automatic from the fact\nthat the means of combination\n\n940\n00:57:38,710 --> 00:57:41,100\nare themselves procedures.\n\n941\n00:57:41,100 --> 00:57:43,570\nOr suppose I wanted to do\nsomething a little bit more\n\n942\n00:57:43,570 --> 00:57:44,200\ncomplicated.\n\n943\n00:57:44,200 --> 00:57:46,670\nI wanted to put in a parameter\nso that for each of these, I\n\n944\n00:57:46,670 --> 00:57:50,530\ncould independently specify\na rotation by 90 degrees.\n\n945\n00:57:50,530 --> 00:57:53,200\nThat's just putting a parameter\nin the procedure.\n\n946\n00:57:53,200 --> 00:57:55,430\nIt's automatically there.\n\n947\n00:57:55,430 --> 00:57:58,470\nRight, it automatically comes\nfrom the embedding.\n\n948\n00:57:58,470 --> 00:58:04,850\nOr even more, suppose I wanted\nto, you know, use recursion.\n\n949\n00:58:04,850 --> 00:58:09,560\nLet's look at a recursive\nmeans of\n\n950\n00:58:09,560 --> 00:58:10,740\ncombination on pictures.\n\n951\n00:58:10,740 --> 00:58:12,620\nI could say define--\n\n952\n00:58:12,620 --> 00:58:14,890\nlet's see if you can figure out\nwhat this one is-- suppose\n\n953\n00:58:14,890 --> 00:58:22,990\nI say define what it means\nto right-push a picture,\n\n954\n00:58:22,990 --> 00:58:28,770\nright-push a picture and some\ninteger N and some scale\n\n955\n00:58:28,770 --> 00:58:40,000\nfactor A. I'll define this to\nsay if N equals 0, then the\n\n956\n00:58:40,000 --> 00:58:42,340\nanswer is the picture.\n\n957\n00:58:42,340 --> 00:58:49,724\nOtherwise I'm going to put--\n\n958\n00:58:49,724 --> 00:58:59,080\noops, name change: P. Otherwise,\nI'm going to take P\n\n959\n00:58:59,080 --> 00:59:09,460\nand put it beside the results of\nrecursively right-pushing P\n\n960\n00:59:09,460 --> 00:59:25,660\nwith N minus 1 and A and use a\nscale factor of A. OK, so if\n\n961\n00:59:25,660 --> 00:59:31,080\nN0 , it's P. Otherwise I put P\nwith a scale factor of A--\n\n962\n00:59:31,080 --> 00:59:33,610\nI'm sorry I didn't align\nthis right--\n\n963\n00:59:33,610 --> 00:59:37,070\nrecursively beside the result of\nright-pushing P, N minus 1\n\n964\n00:59:37,070 --> 00:59:38,550\ntimes with a scale\nfactor of A.\n\n965\n00:59:38,550 --> 00:59:43,860\nThere's a recursive means\nof combination.\n\n966\n00:59:43,860 --> 00:59:44,790\nWhat's that look like?\n\n967\n00:59:44,790 --> 00:59:46,060\nWell, here's what\nit looks like.\n\n968\n00:59:46,060 --> 00:59:54,250\nThere's George right-pushed\nagainst himself twice with a\n\n969\n00:59:54,250 --> 00:59:59,520\nscale factor of 0.75.\n\n970\n00:59:59,520 --> 01:00:00,020\nOK.\n\n971\n01:00:00,020 --> 01:00:00,850\nWhere'd that come from?\n\n972\n01:00:00,850 --> 01:00:02,260\nHow did I get all this\nfancy recursion?\n\n973\n01:00:02,260 --> 01:00:02,960\nAnd the answer is just\n\n974\n01:00:02,960 --> 01:00:05,240\nautomatic, absolutely automatic.\n\n975\n01:00:05,240 --> 01:00:08,370\nSince these are procedures, the\nembedding says, well sure,\n\n976\n01:00:08,370 --> 01:00:10,440\nI can define recursive\nprocedures.\n\n977\n01:00:10,440 --> 01:00:13,830\nI didn't have to arrange that.\n\n978\n01:00:13,830 --> 01:00:15,320\nAnd of course, we can\ndo more complicated\n\n979\n01:00:15,320 --> 01:00:16,440\nthings of the same sort.\n\n980\n01:00:16,440 --> 01:00:18,240\nI could make something\nthat does an up-push.\n\n981\n01:00:18,240 --> 01:00:21,740\nRight, that sort of goes like\nthis, by recursively putting\n\n982\n01:00:21,740 --> 01:00:22,670\nsomething above.\n\n983\n01:00:22,670 --> 01:00:25,730\nOr I could make something\nthat, sort\n\n984\n01:00:25,730 --> 01:00:26,590\nof, was this scheme.\n\n985\n01:00:26,590 --> 01:00:33,430\nI might start out with a picture\nand then, sort of,\n\n986\n01:00:33,430 --> 01:00:38,250\nrecursively both push it aside\nand above, and that might put\n\n987\n01:00:38,250 --> 01:00:39,420\nsomething there.\n\n988\n01:00:39,420 --> 01:00:42,590\nAnd then up here I put the same\nrecursive thing, and I\n\n989\n01:00:42,590 --> 01:00:45,220\nmight end up with something\nlike this.\n\n990\n01:00:45,220 --> 01:00:49,650\nRight, so there's a procedure\nthat's a little bit more\n\n991\n01:00:49,650 --> 01:00:53,800\ncomplicated than right-push\nbut not much.\n\n992\n01:00:53,800 --> 01:00:56,670\nI just do an Above\nand a Beside,\n\n993\n01:00:56,670 --> 01:00:57,920\nrather than just a Beside.\n\n994\n01:00:57,920 --> 01:01:01,380\n\n\n995\n01:01:01,380 --> 01:01:05,780\nNow if I take that and apply\nthat with the idea of putting\n\n996\n01:01:05,780 --> 01:01:09,500\nfour pictures together, which I\ncan surely do; and I go and\n\n997\n01:01:09,500 --> 01:01:16,460\nI apply that to Q, which we\ndefined before, right, what I\n\n998\n01:01:16,460 --> 01:01:22,310\nend up with this is this thing,\nwhich is, sort of, the\n\n999\n01:01:22,310 --> 01:01:25,045\nsquare limit of Q, done twice.\n\n1000\n01:01:25,045 --> 01:01:27,970\n\n\n1001\n01:01:27,970 --> 01:01:31,960\nRight, and then we can compare\nthat with Escher's \"Square\n\n1002\n01:01:31,960 --> 01:01:35,110\nLimit.\" And you see, it's\nsort of the same idea.\n\n1003\n01:01:35,110 --> 01:01:37,040\nEscher's is, of course,\nmuch, much prettier.\n\n1004\n01:01:37,040 --> 01:01:43,250\nIf we go back and look at\nGeorge, right, if we go look\n\n1005\n01:01:43,250 --> 01:01:44,340\nat George here--\n\n1006\n01:01:44,340 --> 01:01:47,970\nsee, I started with a fairly\narbitrary design, this picture\n\n1007\n01:01:47,970 --> 01:01:51,170\nof George and did\nthings with it.\n\n1008\n01:01:51,170 --> 01:01:54,420\nRight, whereas if we go look at\nthe Escher picture, right,\n\n1009\n01:01:54,420 --> 01:01:56,200\nthe Escher picture is not\nan arbitrary design.\n\n1010\n01:01:56,200 --> 01:01:59,130\nIt's this very, very clever\nthing, so that when you take\n\n1011\n01:01:59,130 --> 01:02:03,590\nthis fish body and Rotate it and\nshrink it down, it bleeds\n\n1012\n01:02:03,590 --> 01:02:04,990\ninto the next one\nreally nicely.\n\n1013\n01:02:04,990 --> 01:02:07,620\n\n\n1014\n01:02:07,620 --> 01:02:10,320\nAnd of course with George,\nI didn't really do\n\n1015\n01:02:10,320 --> 01:02:12,140\nanything like that.\n\n1016\n01:02:12,140 --> 01:02:16,300\nSo if we look at George, right,\nthere's a little bit of\n\n1017\n01:02:16,300 --> 01:02:18,670\nmatch up, but not very nice,\nand it's pretty arbitrary.\n\n1018\n01:02:18,670 --> 01:02:23,710\nOne very nice project, by the\nway, would be to write a\n\n1019\n01:02:23,710 --> 01:02:27,120\nprocedure that could take some\nbasic figure like this George\n\n1020\n01:02:27,120 --> 01:02:30,050\nthing and start moving the ends\nof the lines around, so\n\n1021\n01:02:30,050 --> 01:02:33,170\nyou got a really nice one when\nyou went and did that \"Square\n\n1022\n01:02:33,170 --> 01:02:34,720\nLimit\" process.\n\n1023\n01:02:34,720 --> 01:02:38,360\nThat'd be a really nice\nthing to think about.\n\n1024\n01:02:38,360 --> 01:02:39,710\nWell so, we can combine\nthings.\n\n1025\n01:02:39,710 --> 01:02:40,980\nWe can recursive procedures.\n\n1026\n01:02:40,980 --> 01:02:44,680\nWe can do all kinds of things,\nand that's all automatic.\n\n1027\n01:02:44,680 --> 01:02:47,050\nRight, the important point, the\ndifference between merely\n\n1028\n01:02:47,050 --> 01:02:49,370\nimplementing something in\na language and embedding\n\n1029\n01:02:49,370 --> 01:02:51,570\nsomething in the language, so\nthat you don't lose the\n\n1030\n01:02:51,570 --> 01:02:53,280\noriginal power of the language,\nand what List is\n\n1031\n01:02:53,280 --> 01:02:56,680\ngreat at, see List is a lousy\nlanguage for doing any\n\n1032\n01:02:56,680 --> 01:02:57,600\nparticular problem.\n\n1033\n01:02:57,600 --> 01:03:00,260\nWhat it's good for is figuring\nout the right language that\n\n1034\n01:03:00,260 --> 01:03:04,000\nyou want and embedding that in\nList. That's the real power of\n\n1035\n01:03:04,000 --> 01:03:05,980\nthis approach to design.\n\n1036\n01:03:05,980 --> 01:03:06,880\nOf course, we can go further.\n\n1037\n01:03:06,880 --> 01:03:10,970\nSee, you saw the other thing\nthat we can do in List is\n\n1038\n01:03:10,970 --> 01:03:16,800\ncapture general methods of doing\nthings as higher order\n\n1039\n01:03:16,800 --> 01:03:19,090\nprocedures.\n\n1040\n01:03:19,090 --> 01:03:21,800\nAnd you probably just from me\ndrawing it got the idea that\n\n1041\n01:03:21,800 --> 01:03:25,600\nright-push and the analogous\nthing where you push something\n\n1042\n01:03:25,600 --> 01:03:31,570\nup and up and up and up and this\ncorner push thing are all\n\n1043\n01:03:31,570 --> 01:03:34,690\ngeneralizations of a common\nkind of idea.\n\n1044\n01:03:34,690 --> 01:03:38,210\nSo just to illustrate and give\nyou practice in looking at a\n\n1045\n01:03:38,210 --> 01:03:41,340\nfairly convoluted use of higher\norder procedures, let\n\n1046\n01:03:41,340 --> 01:03:45,280\nme show you the general idea\nof pushing some means of\n\n1047\n01:03:45,280 --> 01:03:48,510\ncombination to recursively\nrepeat it.\n\n1048\n01:03:48,510 --> 01:03:51,240\nSo here's a good one\nto puzzle out.\n\n1049\n01:03:51,240 --> 01:03:59,550\nWe'll define it what it means\nto push using a means of\n\n1050\n01:03:59,550 --> 01:04:01,800\ncombination.\n\n1051\n01:04:01,800 --> 01:04:05,582\nComb is going to be something\nlike the Beside or Above.\n\n1052\n01:04:05,582 --> 01:04:07,240\nWell what's that going to be.\n\n1053\n01:04:07,240 --> 01:04:10,540\nThat's going to be a procedure,\nremember what\n\n1054\n01:04:10,540 --> 01:04:13,480\nBeside actually was, right.\n\n1055\n01:04:13,480 --> 01:04:18,700\nIt took a picture, took two\npictures and a scale factor.\n\n1056\n01:04:18,700 --> 01:04:21,740\nUsing that I produced something\nthat took a level\n\n1057\n01:04:21,740 --> 01:04:24,800\nnumber and a picture and a scale\nfactor, that I called\n\n1058\n01:04:24,800 --> 01:04:26,310\nright-push.\n\n1059\n01:04:26,310 --> 01:04:27,700\nSo this is going to be something\nthat takes a\n\n1060\n01:04:27,700 --> 01:04:32,700\npicture, a level number and\na scale factor, and\n\n1061\n01:04:32,700 --> 01:04:33,950\nit's going to say--\n\n1062\n01:04:33,950 --> 01:04:36,320\n\n\n1063\n01:04:36,320 --> 01:04:39,520\nI'm going to do some\nrepeated operation.\n\n1064\n01:04:39,520 --> 01:04:46,100\nI'm going to repeatedly apply\nthe procedure which takes a\n\n1065\n01:04:46,100 --> 01:04:53,540\npicture and applies the means of\ncombination to the picture\n\n1066\n01:04:53,540 --> 01:04:58,160\nand the original picture and the\none I took in here and the\n\n1067\n01:04:58,160 --> 01:05:06,100\nscale factor, and I do the\nthing which repeats this\n\n1068\n01:05:06,100 --> 01:05:15,370\nprocedure N times, and I apply\nthat whole thing to my\n\n1069\n01:05:15,370 --> 01:05:16,620\noriginal picture.\n\n1070\n01:05:16,620 --> 01:05:19,600\n\n\n1071\n01:05:19,600 --> 01:05:23,390\nRepeated here, in case you\nhaven't seen it, is another\n\n1072\n01:05:23,390 --> 01:05:29,660\nhigher order procedure that\ntakes a procedure and a number\n\n1073\n01:05:29,660 --> 01:05:32,510\nand returns for you another\nprocedure that applies this\n\n1074\n01:05:32,510 --> 01:05:36,150\nprocedure N times.\n\n1075\n01:05:36,150 --> 01:05:38,690\nAnd I think some of you have\nalready written repeated as an\n\n1076\n01:05:38,690 --> 01:05:41,520\nexercise, but if you haven't,\nit's a very good exercise in\n\n1077\n01:05:41,520 --> 01:05:43,910\nthinking about higher\norder procedures.\n\n1078\n01:05:43,910 --> 01:05:46,320\nBut in any case, the result of\nthis repeated is what I apply\n\n1079\n01:05:46,320 --> 01:05:47,570\nto picture.\n\n1080\n01:05:47,570 --> 01:05:49,510\n\n\n1081\n01:05:49,510 --> 01:05:52,880\nAnd having done that, that's\ngoing to capture--\n\n1082\n01:05:52,880 --> 01:05:56,700\nthat is the thing, the way I got\nfrom the idea of Beside to\n\n1083\n01:05:56,700 --> 01:06:00,760\nthe idea of right-push So having\ndone that, I could say\n\n1084\n01:06:00,760 --> 01:06:12,790\ndefine right-push to\nbe push of Beside.\n\n1085\n01:06:12,790 --> 01:06:17,640\n\n\n1086\n01:06:17,640 --> 01:06:20,770\nOr if I say, define up-push to\nbe push of Beside, I'd get the\n\n1087\n01:06:20,770 --> 01:06:23,480\nanalogous thing or define\ncorner-push to be push of some\n\n1088\n01:06:23,480 --> 01:06:25,745\nappropriate thing that did both\nthe Beside and Above, or\n\n1089\n01:06:25,745 --> 01:06:28,340\nI could push anything.\n\n1090\n01:06:28,340 --> 01:06:31,660\nAnyway this is, if you're having\ntrouble with lambdas,\n\n1091\n01:06:31,660 --> 01:06:33,840\nthis is an excellent exercise\nin figuring\n\n1092\n01:06:33,840 --> 01:06:36,100\nout what this means.\n\n1093\n01:06:36,100 --> 01:06:42,190\nOK, well there's a lot to\nlearn from this example.\n\n1094\n01:06:42,190 --> 01:06:46,040\nThe main point I've been\ndwelling on is the notion of\n\n1095\n01:06:46,040 --> 01:06:50,760\nnicely embedding a language\ninside another language.\n\n1096\n01:06:50,760 --> 01:06:54,700\nRight, so that all the power of\nthis language like List of\n\n1097\n01:06:54,700 --> 01:06:57,270\nthe surrounding language is\nstill accessible to you and\n\n1098\n01:06:57,270 --> 01:06:59,270\nappears as a natural\nextension of the\n\n1099\n01:06:59,270 --> 01:07:01,000\nlanguage that you built.\n\n1100\n01:07:01,000 --> 01:07:06,140\nThat's one thing that this\nexample shows very well.\n\n1101\n01:07:06,140 --> 01:07:07,990\nOK.\n\n1102\n01:07:07,990 --> 01:07:10,960\nAnother thing is, if you go\nback and think about that,\n\n1103\n01:07:10,960 --> 01:07:12,180\nwhat's procedures\nand what's data.\n\n1104\n01:07:12,180 --> 01:07:15,320\nYou know, by the time we\nget up to here, my God,\n\n1105\n01:07:15,320 --> 01:07:16,190\nwhat's going on.\n\n1106\n01:07:16,190 --> 01:07:18,620\nI mean, this is some procedure,\nand it takes a\n\n1107\n01:07:18,620 --> 01:07:20,380\npicture and an argument,\nand what's a picture.\n\n1108\n01:07:20,380 --> 01:07:22,700\nWell, a picture itself, as you\nremember, was a procedure, and\n\n1109\n01:07:22,700 --> 01:07:23,630\nthat took a rectangle.\n\n1110\n01:07:23,630 --> 01:07:26,090\nAnd a rectangle is\nsome abstraction.\n\n1111\n01:07:26,090 --> 01:07:31,300\nAnd I hope now that by now\nyou're completely lost as to\n\n1112\n01:07:31,300 --> 01:07:32,580\nthe question of what\nin the system is\n\n1113\n01:07:32,580 --> 01:07:33,590\nprocedure and what's data.\n\n1114\n01:07:33,590 --> 01:07:35,500\nYou see, there isn't\nany difference.\n\n1115\n01:07:35,500 --> 01:07:38,020\nThere really isn't.\n\n1116\n01:07:38,020 --> 01:07:39,850\nAnd you might think of a\npicture sometimes as a\n\n1117\n01:07:39,850 --> 01:07:42,790\nprocedure and sometimes as data,\nbut that's just, sort\n\n1118\n01:07:42,790 --> 01:07:44,860\nof, you know, making you\nfeel comfortable.\n\n1119\n01:07:44,860 --> 01:07:48,640\nIt's really both in some sense\nor neither in some sense.\n\n1120\n01:07:48,640 --> 01:07:56,370\nOK, there's a more general point\nabout the structure of\n\n1121\n01:07:56,370 --> 01:08:03,510\nthe system as creating a\nlanguage, viewing the\n\n1122\n01:08:03,510 --> 01:08:08,030\nengineering design process as\none of creating language or\n\n1123\n01:08:08,030 --> 01:08:12,730\nrather one of creating\na sort of sequence\n\n1124\n01:08:12,730 --> 01:08:14,830\nof layers of language.\n\n1125\n01:08:14,830 --> 01:08:18,010\nYou see, there's this\nmethodology, or maybe I should\n\n1126\n01:08:18,010 --> 01:08:22,460\nsay mythology, that's, sort\nof, charitably called\n\n1127\n01:08:22,460 --> 01:08:24,989\nsoftware, quote, engineering.\n\n1128\n01:08:24,989 --> 01:08:27,090\nAll right, and what does it say,\nit's says well, you go\n\n1129\n01:08:27,090 --> 01:08:29,140\nand you figure out your task,\nand you figure out exactly\n\n1130\n01:08:29,140 --> 01:08:30,520\nwhat you want to do.\n\n1131\n01:08:30,520 --> 01:08:32,080\nAnd once you figure out exactly\nwhat you want to do,\n\n1132\n01:08:32,080 --> 01:08:34,490\nyou find out that it breaks out\ninto three sub-tasks, and\n\n1133\n01:08:34,490 --> 01:08:36,710\nyou go and you start working\non-- and you work on this\n\n1134\n01:08:36,710 --> 01:08:38,770\nsub-task, and you figure out\nexactly what that is.\n\n1135\n01:08:38,770 --> 01:08:40,649\nAnd you find out that that\nbreaks down into three\n\n1136\n01:08:40,649 --> 01:08:43,380\nsub-tasks, and you specify them\ncompletely, and you go\n\n1137\n01:08:43,380 --> 01:08:45,920\nand you work on those two, and\nyou work on this sub-one, and\n\n1138\n01:08:45,920 --> 01:08:47,229\nyou specify that exactly.\n\n1139\n01:08:47,229 --> 01:08:48,990\nAnd then finally when you're\ndone, you come back way up\n\n1140\n01:08:48,990 --> 01:08:51,779\nhere, and you work on your\nsecond sub-task, and specify\n\n1141\n01:08:51,779 --> 01:08:53,370\nthat out and work it out.\n\n1142\n01:08:53,370 --> 01:08:55,490\nAnd then you end up with--\n\n1143\n01:08:55,490 --> 01:08:57,680\nyou end up at the end with\nthis beautiful edifice.\n\n1144\n01:08:57,680 --> 01:09:03,120\nRight, you end up with a\nmarvelous tree, where you've\n\n1145\n01:09:03,120 --> 01:09:05,590\nbroken your task into sub-tasks\nand broken each of\n\n1146\n01:09:05,590 --> 01:09:07,260\nthese into sub-tasks\nand broken those\n\n1147\n01:09:07,260 --> 01:09:10,370\ninto sub-tasks, right.\n\n1148\n01:09:10,370 --> 01:09:15,200\nAnd each of these nodes is\nexactly and precisely defined\n\n1149\n01:09:15,200 --> 01:09:17,779\nto do the wonderful, beautiful\ntask to make it fit into the\n\n1150\n01:09:17,779 --> 01:09:19,180\nwhole edifice, right.\n\n1151\n01:09:19,180 --> 01:09:21,080\nThat's this mythology.\n\n1152\n01:09:21,080 --> 01:09:23,970\nSee only a computer scientist\ncould possibly believe that\n\n1153\n01:09:23,970 --> 01:09:28,220\nyou build a complex system\nlike that, right.\n\n1154\n01:09:28,220 --> 01:09:32,700\nContrast that with this\nHenderson example.\n\n1155\n01:09:32,700 --> 01:09:35,319\nIt didn't work like that.\n\n1156\n01:09:35,319 --> 01:09:37,359\nWhat happened was that\nthere was a sequence\n\n1157\n01:09:37,359 --> 01:09:41,319\nof layers of language.\n\n1158\n01:09:41,319 --> 01:09:41,990\nWhat happened?\n\n1159\n01:09:41,990 --> 01:09:47,770\nThere was a layer of a thing\nthat allowed us to build\n\n1160\n01:09:47,770 --> 01:09:49,020\nprimitive pictures.\n\n1161\n01:09:49,020 --> 01:09:51,569\n\n\n1162\n01:09:51,569 --> 01:09:56,440\nThere's primitive pictures\nand that was a language.\n\n1163\n01:09:56,440 --> 01:09:57,530\nI didn't say much about it.\n\n1164\n01:09:57,530 --> 01:09:59,900\nWe talked about how to construct\nGeorge, but that was\n\n1165\n01:09:59,900 --> 01:10:01,950\na language where you talked\nabout vectors and line\n\n1166\n01:10:01,950 --> 01:10:06,520\nsegments and points and where\nthey sat in the unit square.\n\n1167\n01:10:06,520 --> 01:10:12,000\nAnd then on top of that,\nright, on top of that--\n\n1168\n01:10:12,000 --> 01:10:13,850\nso this is the language\nof primitive pictures.\n\n1169\n01:10:13,850 --> 01:10:17,100\n\n\n1170\n01:10:17,100 --> 01:10:19,240\nRight, talking about line\nsegments in particular\n\n1171\n01:10:19,240 --> 01:10:21,620\npictures in the unit square.\n\n1172\n01:10:21,620 --> 01:10:24,110\nOn top of that was\na whole language.\n\n1173\n01:10:24,110 --> 01:10:33,110\nThere was a language of\ngeometric combinators, a\n\n1174\n01:10:33,110 --> 01:10:41,340\nlanguage of geometric positions,\nwhich talks about\n\n1175\n01:10:41,340 --> 01:10:48,240\nthings like Above and Beside\nand right-push and Rotate.\n\n1176\n01:10:48,240 --> 01:10:53,600\nAnd those things, sort of,\nhappened with reference to the\n\n1177\n01:10:53,600 --> 01:10:55,470\nthings that are talked about\nin this language.\n\n1178\n01:10:55,470 --> 01:10:58,640\n\n\n1179\n01:10:58,640 --> 01:11:03,070\nAnd then if we like, we saw that\nabove that there was sort\n\n1180\n01:11:03,070 --> 01:11:14,810\nof a language of schemes\nof combination.\n\n1181\n01:11:14,810 --> 01:11:21,410\n\n\n1182\n01:11:21,410 --> 01:11:25,930\nFor example, push, which talked\nabout repeatedly doing\n\n1183\n01:11:25,930 --> 01:11:28,540\nsomething over with\na scale factor.\n\n1184\n01:11:28,540 --> 01:11:31,130\nAnd the things that were being\ndiscussed in that language\n\n1185\n01:11:31,130 --> 01:11:36,280\nwere, sort of, the things\nthat happened down here.\n\n1186\n01:11:36,280 --> 01:11:41,310\nSo what you have is, at each\nlevel, the objects that are\n\n1187\n01:11:41,310 --> 01:11:46,090\nbeing talked about are the\nthings that were erected at\n\n1188\n01:11:46,090 --> 01:11:48,270\nthe previous level.\n\n1189\n01:11:48,270 --> 01:11:53,270\nWhat's the difference between\nthis thing and this thing?\n\n1190\n01:11:53,270 --> 01:11:59,890\nThe answer is that over here in\nthe tree, each node, and in\n\n1191\n01:11:59,890 --> 01:12:03,610\nfact, each decomposition down\nhere, is being designed to do\n\n1192\n01:12:03,610 --> 01:12:09,640\na specific task, whereas in\nthe other scheme, what you\n\n1193\n01:12:09,640 --> 01:12:13,900\nhave is a full range\nof linguistic\n\n1194\n01:12:13,900 --> 01:12:15,940\npower at each level.\n\n1195\n01:12:15,940 --> 01:12:21,340\nSee what's happening there, at\nany level, it's not being set\n\n1196\n01:12:21,340 --> 01:12:23,310\nup to do a particular task.\n\n1197\n01:12:23,310 --> 01:12:27,710\nIt's being set up to talk about\na whole range of things.\n\n1198\n01:12:27,710 --> 01:12:31,810\nThe consequence of that for\ndesign is that something\n\n1199\n01:12:31,810 --> 01:12:36,620\nthat's designed in that method\nis likely to be more robust,\n\n1200\n01:12:36,620 --> 01:12:40,470\nwhere by robust, I mean that if\nyou go and make some change\n\n1201\n01:12:40,470 --> 01:12:46,820\nin your description, it's more\nlikely to be captured by a\n\n1202\n01:12:46,820 --> 01:12:51,070\ncorresponding change, in the\nway that the language is\n\n1203\n01:12:51,070 --> 01:12:55,460\nimplemented at the next level\nup, right, because you've made\n\n1204\n01:12:55,460 --> 01:12:56,660\nthese levels full.\n\n1205\n01:12:56,660 --> 01:12:59,980\nSo you're not talking about a\nparticular thing like Beside.\n\n1206\n01:12:59,980 --> 01:13:02,880\nYou've given yourself a whole\nvocabulary to express things\n\n1207\n01:13:02,880 --> 01:13:06,540\nof that sort, so if you go and\nchange your specifications a\n\n1208\n01:13:06,540 --> 01:13:09,580\nlittle bit, it's more likely\nthat your methodology will\n\n1209\n01:13:09,580 --> 01:13:13,680\nable to adapt to capture that\nchange, whereas a design like\n\n1210\n01:13:13,680 --> 01:13:15,770\nthis is not going to be robust,\nbecause if I go and\n\n1211\n01:13:15,770 --> 01:13:18,310\nchange something that's in here,\nthat might affect the\n\n1212\n01:13:18,310 --> 01:13:20,840\nentire way that I decomposed\neverything down,\n\n1213\n01:13:20,840 --> 01:13:23,240\nfurther down the tree.\n\n1214\n01:13:23,240 --> 01:13:26,350\nRight, so very big difference\nin outlook in decomposition,\n\n1215\n01:13:26,350 --> 01:13:28,590\nlevels of language\nrather than, sort\n\n1216\n01:13:28,590 --> 01:13:30,580\nof, a strict hierarchy.\n\n1217\n01:13:30,580 --> 01:13:33,750\nNot only that, but when you have\nlevels of language you've\n\n1218\n01:13:33,750 --> 01:13:37,390\ngiven yourself a different\nvocabularies for talking about\n\n1219\n01:13:37,390 --> 01:13:38,780\nthe design at different\nlevels.\n\n1220\n01:13:38,780 --> 01:13:42,260\nSo if we go back and look at\nGeorge one last time, if I\n\n1221\n01:13:42,260 --> 01:13:46,610\nwanted to change this picture\nGeorge, see suddenly I have a\n\n1222\n01:13:46,610 --> 01:13:48,800\nwhole different ways of\ndescribing the change.\n\n1223\n01:13:48,800 --> 01:13:52,320\nLike for example, I may want to\ngo to the basic primitive\n\n1224\n01:13:52,320 --> 01:13:57,640\ndesign and move the endpoint\nof some vector.\n\n1225\n01:13:57,640 --> 01:14:01,140\nThat's a change that I would\ndiscuss at the lowest level.\n\n1226\n01:14:01,140 --> 01:14:03,420\nI would say the endpoint\nis somewhere else.\n\n1227\n01:14:03,420 --> 01:14:05,440\nOr I might come up and say, well\nthe next thing I wanted\n\n1228\n01:14:05,440 --> 01:14:10,320\nto do, this little replicated\nelement, I might want to do by\n\n1229\n01:14:10,320 --> 01:14:10,990\nsomething else.\n\n1230\n01:14:10,990 --> 01:14:13,740\nI might want to put a scale\nfactor in that Beside.\n\n1231\n01:14:13,740 --> 01:14:17,850\nThat's a change that I would\ndiscuss at the next level of\n\n1232\n01:14:17,850 --> 01:14:19,350\ndesign, the level\nof combinators.\n\n1233\n01:14:19,350 --> 01:14:22,580\nOr I might want to say, I might\nwant to change the basic\n\n1234\n01:14:22,580 --> 01:14:27,510\nway that I took this pattern\nand made some recursive\n\n1235\n01:14:27,510 --> 01:14:29,400\ndecomposition, maybe not\nbleeding out toward the\n\n1236\n01:14:29,400 --> 01:14:30,960\ncorners or something else.\n\n1237\n01:14:30,960 --> 01:14:33,150\nThat would be a change\nthat I would discuss\n\n1238\n01:14:33,150 --> 01:14:34,260\nat the highest level.\n\n1239\n01:14:34,260 --> 01:14:36,700\nAnd because I've structured the\nsystem to be this way, I\n\n1240\n01:14:36,700 --> 01:14:39,120\nhave all these vocabularies for\ntalking about change in\n\n1241\n01:14:39,120 --> 01:14:41,580\ndifferent ways and a lot of\nflexibility to decide which\n\n1242\n01:14:41,580 --> 01:14:42,830\none's appropriate.\n\n1243\n01:14:42,830 --> 01:14:44,810\n\n\n1244\n01:14:44,810 --> 01:14:48,370\nOK, well that's sort of a big\npoint about the difference in\n\n1245\n01:14:48,370 --> 01:14:51,470\nsoftware methodology that comes\nout from List, and it\n\n1246\n01:14:51,470 --> 01:14:54,840\nall comes, again, out of the\nnotion that really, the design\n\n1247\n01:14:54,840 --> 01:14:58,430\nprocess is not so much\nimplementing programs as\n\n1248\n01:14:58,430 --> 01:14:59,370\nimplementing languages.\n\n1249\n01:14:59,370 --> 01:15:02,870\nAnd that's really the powerful\nof List. OK, thank you.\n\n1250\n01:15:02,870 --> 01:15:04,480\nLet's take a break.\n\n1251\n01:15:04,480 --> 01:15:34,591\n\n"
  },
  {
    "path": "SrtEN/lec3b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:02,928\n\n\n1\n00:00:02,928 --> 00:00:19,520\n[MUSIC PLAYING]\n\n2\n00:00:19,520 --> 00:00:22,720\nPROFESSOR: Well, Hal just told\nus how you build robust\n\n3\n00:00:22,720 --> 00:00:26,960\nsystems. The key idea was--\n\n4\n00:00:26,960 --> 00:00:30,000\nI'm sure that many of you don't\nreally assimilate that\n\n5\n00:00:30,000 --> 00:00:32,980\nyet-- but the key idea is that\nin order to make a system\n\n6\n00:00:32,980 --> 00:00:36,850\nthat's robust, it has to be\ninsensitive to small changes,\n\n7\n00:00:36,850 --> 00:00:39,680\nthat is, a small change in the\nproblem should lead to only a\n\n8\n00:00:39,680 --> 00:00:41,340\nsmall change in the solution.\n\n9\n00:00:41,340 --> 00:00:42,670\nThere ought to be\na continuity.\n\n10\n00:00:42,670 --> 00:00:45,275\nThe space of solutions ought to\nbe continuous in this space\n\n11\n00:00:45,275 --> 00:00:46,120\nof problems.\n\n12\n00:00:46,120 --> 00:00:50,270\nThe way he was explaining how\nto do that was instead of\n\n13\n00:00:50,270 --> 00:00:52,240\nsolving a particular problem\nat every level of\n\n14\n00:00:52,240 --> 00:00:55,520\ndecomposition of the problem at\nthe subproblems, where you\n\n15\n00:00:55,520 --> 00:00:58,570\nsolve the class of problems,\nwhich are a neighborhood of\n\n16\n00:00:58,570 --> 00:01:01,440\nthe particular problem that\nyou're trying to solve.\n\n17\n00:01:01,440 --> 00:01:03,980\nThe way you do that is by\nproducing a language at that\n\n18\n00:01:03,980 --> 00:01:07,500\nlevel of detail in which the\nsolutions to that class of\n\n19\n00:01:07,500 --> 00:01:11,170\nproblems is representable\nin that language.\n\n20\n00:01:11,170 --> 00:01:14,370\nTherefore when you makes more\nchanges to the problem you're\n\n21\n00:01:14,370 --> 00:01:17,140\ntrying to solve, you generally\nhave to make only small local\n\n22\n00:01:17,140 --> 00:01:20,640\nchanges to the solution you've\nconstructed, because at the\n\n23\n00:01:20,640 --> 00:01:23,190\nlevel of detail you're working,\nthere's a language\n\n24\n00:01:23,190 --> 00:01:26,940\nwhere you can express the\nvarious solutions to alternate\n\n25\n00:01:26,940 --> 00:01:30,170\nproblems of the same type.\n\n26\n00:01:30,170 --> 00:01:35,090\nWell that's the beginning of a\nvery important idea, the most\n\n27\n00:01:35,090 --> 00:01:37,950\nimportant perhaps idea that\nmakes computer science more\n\n28\n00:01:37,950 --> 00:01:40,320\npowerful than most of the other\nkinds of engineering\n\n29\n00:01:40,320 --> 00:01:43,500\ndisciplines we know about.\n\n30\n00:01:43,500 --> 00:01:47,350\nWhat we've seen so far\nis sort of how to use\n\n31\n00:01:47,350 --> 00:01:49,500\nembedding of languages.\n\n32\n00:01:49,500 --> 00:01:52,570\nAnd, of course, the power of\nembedding languages partly\n\n33\n00:01:52,570 --> 00:01:55,480\ncomes from procedures\nlike this one that\n\n34\n00:01:55,480 --> 00:01:57,500\nI showed you yesterday.\n\n35\n00:01:57,500 --> 00:02:01,210\nWhat you see here is the\nderivative program that we\n\n36\n00:02:01,210 --> 00:02:02,280\ndescribed yesterday.\n\n37\n00:02:02,280 --> 00:02:06,270\nIt's a procedure that takes a\nprocedure as an argument and\n\n38\n00:02:06,270 --> 00:02:09,880\nreturns a procedure\nas a value.\n\n39\n00:02:09,880 --> 00:02:12,680\nAnd using such things\nis very nice.\n\n40\n00:02:12,680 --> 00:02:15,480\nYou can make things like push\ncombinators and all that sort\n\n41\n00:02:15,480 --> 00:02:18,020\nof wonderful thing that\nyou saw last time.\n\n42\n00:02:18,020 --> 00:02:21,730\nHowever, now I'm going to\nreally muddy the waters.\n\n43\n00:02:21,730 --> 00:02:25,430\nSee this confuses the issue of\nwhat's the procedure and what\n\n44\n00:02:25,430 --> 00:02:28,310\nis data, but not very badly.\n\n45\n00:02:28,310 --> 00:02:31,260\nWhat we really want to do is\nconfuse it very badly.\n\n46\n00:02:31,260 --> 00:02:33,400\nAnd the best way to do that is\nto get involved with the\n\n47\n00:02:33,400 --> 00:02:35,980\nmanipulation of the algebraic\nexpressions that the\n\n48\n00:02:35,980 --> 00:02:39,750\nprocedures themselves\nare expressed in.\n\n49\n00:02:39,750 --> 00:02:43,660\nSo at this point, I want to talk\nabout instead of things\n\n50\n00:02:43,660 --> 00:02:48,300\nlike on this slide, the\nderivative procedure being a\n\n51\n00:02:48,300 --> 00:02:49,880\nthing that manipulates\na procedure--\n\n52\n00:02:49,880 --> 00:02:51,870\nthis is a numerical method\nyou see here.\n\n53\n00:02:51,870 --> 00:02:56,440\nAnd what you're seeing is\na representation of the\n\n54\n00:02:56,440 --> 00:02:59,275\nnumerical approximation\nto the derivative.\n\n55\n00:02:59,275 --> 00:03:00,980\nThat's what's here.\n\n56\n00:03:00,980 --> 00:03:04,180\nIn fact what I'd like to talk\nabout is instead things that\n\n57\n00:03:04,180 --> 00:03:06,170\nlook like this.\n\n58\n00:03:06,170 --> 00:03:12,080\nAnd what we have here are rules\nfrom a calculus book.\n\n59\n00:03:12,080 --> 00:03:15,010\nThese are rules for finding\nthe derivatives of the\n\n60\n00:03:15,010 --> 00:03:18,190\nexpressions that one\nmight write in\n\n61\n00:03:18,190 --> 00:03:21,520\nsome algebraic language.\n\n62\n00:03:21,520 --> 00:03:24,990\nIt says things like a derivative\nof a constant is 0.\n\n63\n00:03:24,990 --> 00:03:27,700\nThe derivative of the valuable\nwith respect to which you are\n\n64\n00:03:27,700 --> 00:03:29,250\ntaking the derivative is 1.\n\n65\n00:03:29,250 --> 00:03:32,490\nThe derivative of a constant\ntimes the function is the\n\n66\n00:03:32,490 --> 00:03:34,980\nconstant times the derivative\nof the function,\n\n67\n00:03:34,980 --> 00:03:38,300\nand things like that.\n\n68\n00:03:38,300 --> 00:03:39,690\nThese are exact expressions.\n\n69\n00:03:39,690 --> 00:03:43,090\nThese are not numerical\napproximations.\n\n70\n00:03:43,090 --> 00:03:44,560\nCan we make programs?\n\n71\n00:03:44,560 --> 00:03:51,000\nAnd, in fact, it's very easy\nto make programs that\n\n72\n00:03:51,000 --> 00:03:52,250\nmanipulate these expressions.\n\n73\n00:03:52,250 --> 00:03:56,130\n\n\n74\n00:03:56,130 --> 00:03:57,480\nWell let's see.\n\n75\n00:03:57,480 --> 00:04:01,350\nLet's look at these rules\nin some detail.\n\n76\n00:04:01,350 --> 00:04:03,850\nYou all have seen these rules\nin your elementary calculus\n\n77\n00:04:03,850 --> 00:04:06,140\nclass at one time or another.\n\n78\n00:04:06,140 --> 00:04:10,570\nAnd you know from calculus\nthat it's easy to produce\n\n79\n00:04:10,570 --> 00:04:12,840\nderivatives of arbitrary\nexpressions.\n\n80\n00:04:12,840 --> 00:04:14,900\nYou also know from your\nelementary calculus that it's\n\n81\n00:04:14,900 --> 00:04:17,140\nhard to produce integrals.\n\n82\n00:04:17,140 --> 00:04:19,690\nYet integrals and derivatives\nare opposites of each other.\n\n83\n00:04:19,690 --> 00:04:21,800\nThey're inverse operations.\n\n84\n00:04:21,800 --> 00:04:24,360\nAnd they have the same rules.\n\n85\n00:04:24,360 --> 00:04:29,110\nWhat is special about these\nrules that makes it possible\n\n86\n00:04:29,110 --> 00:04:32,310\nfor one to produce derivatives\neasily and\n\n87\n00:04:32,310 --> 00:04:35,100\nintegrals why it's so hard?\n\n88\n00:04:35,100 --> 00:04:37,510\nLet's think about that\nvery simply.\n\n89\n00:04:37,510 --> 00:04:39,390\nLook at these rules.\n\n90\n00:04:39,390 --> 00:04:42,190\nEvery one of these rules, when\nused in the direction for\n\n91\n00:04:42,190 --> 00:04:44,260\ntaking derivatives, which is\nin the direction of this\n\n92\n00:04:44,260 --> 00:04:48,830\narrow, the left side is\nmatched against your\n\n93\n00:04:48,830 --> 00:04:51,710\nexpression, and the right side\nis the thing which is the\n\n94\n00:04:51,710 --> 00:04:53,810\nderivative of that expression.\n\n95\n00:04:53,810 --> 00:04:55,570\nThe arrow is going that way.\n\n96\n00:04:55,570 --> 00:04:58,630\n\n\n97\n00:04:58,630 --> 00:05:02,830\nIn each of these rules, the\nexpressions on the right-hand\n\n98\n00:05:02,830 --> 00:05:05,600\nside of the rule that are\ncontained within derivatives\n\n99\n00:05:05,600 --> 00:05:08,630\nare subexpressions, are proper\nsubexpressions, of the\n\n100\n00:05:08,630 --> 00:05:10,670\nexpression on the\nleft-hand side.\n\n101\n00:05:10,670 --> 00:05:14,510\nSo here we see the derivative\nof the sum, with is the\n\n102\n00:05:14,510 --> 00:05:17,260\nexpression on the left-hand\nside is the sum of the\n\n103\n00:05:17,260 --> 00:05:20,030\nderivatives of the pieces.\n\n104\n00:05:20,030 --> 00:05:25,070\nSo the rule of moving to the\nright are reduction rules.\n\n105\n00:05:25,070 --> 00:05:28,110\nThe problem becomes easier.\n\n106\n00:05:28,110 --> 00:05:30,810\nI turn a big complicated problem\nit's lots of smaller\n\n107\n00:05:30,810 --> 00:05:35,000\nproblems and then combine the\nresults, a perfect place for\n\n108\n00:05:35,000 --> 00:05:36,730\nrecursion to work.\n\n109\n00:05:36,730 --> 00:05:42,310\nIf I'm going in the other\ndirection like this, if I'm\n\n110\n00:05:42,310 --> 00:05:44,160\ntrying to produce integrals,\nwell there are several\n\n111\n00:05:44,160 --> 00:05:45,340\nproblems you see here.\n\n112\n00:05:45,340 --> 00:05:48,460\nFirst of all, if I try to\nintegrate an expression like a\n\n113\n00:05:48,460 --> 00:05:50,930\nsum, more than one\nrule matches.\n\n114\n00:05:50,930 --> 00:05:52,610\nHere's one that matches.\n\n115\n00:05:52,610 --> 00:05:54,850\nHere's one that matches.\n\n116\n00:05:54,850 --> 00:05:56,210\nI don't know which\none to take.\n\n117\n00:05:56,210 --> 00:05:57,870\nAnd they may be different.\n\n118\n00:05:57,870 --> 00:06:00,250\nI may get to explore\ndifferent things.\n\n119\n00:06:00,250 --> 00:06:04,660\nAlso, the expressions become\nlarger in that direction.\n\n120\n00:06:04,660 --> 00:06:06,910\nAnd when the expressions become\nlarger, then there's no\n\n121\n00:06:06,910 --> 00:06:10,940\nguarantee that any particular\npath I choose will terminate,\n\n122\n00:06:10,940 --> 00:06:14,380\nbecause we will only terminate\nby accidental cancellation.\n\n123\n00:06:14,380 --> 00:06:16,840\nSo that's why integrals\nare complicated\n\n124\n00:06:16,840 --> 00:06:19,170\nsearches and hard to do.\n\n125\n00:06:19,170 --> 00:06:21,640\nRight now I don't want to do\nanything as hard as that.\n\n126\n00:06:21,640 --> 00:06:24,260\nLet's work on derivatives\nfor a while.\n\n127\n00:06:24,260 --> 00:06:26,860\nWell, these roles are\nones you know for\n\n128\n00:06:26,860 --> 00:06:28,860\nthe most part hopefully.\n\n129\n00:06:28,860 --> 00:06:32,410\nSo let's see if we can write a\nprogram which is these rules.\n\n130\n00:06:32,410 --> 00:06:34,790\nAnd that should be very easy.\n\n131\n00:06:34,790 --> 00:06:36,830\nJust write the program.\n\n132\n00:06:36,830 --> 00:06:39,010\nSee, because while I showed you\nis that it's a reduction\n\n133\n00:06:39,010 --> 00:06:43,180\nrule, it's something appropriate\nfor a recursion.\n\n134\n00:06:43,180 --> 00:06:45,230\nAnd, of course, what we have for\neach of these rules is we\n\n135\n00:06:45,230 --> 00:06:48,375\nhave a case in some\ncase analysis.\n\n136\n00:06:48,375 --> 00:06:50,350\nSo I'm just going to write\nthis program down.\n\n137\n00:06:50,350 --> 00:06:53,130\n\n\n138\n00:06:53,130 --> 00:06:56,780\nNow, of course, I'm going to be\nsaying something you have\n\n139\n00:06:56,780 --> 00:06:57,450\nto believe.\n\n140\n00:06:57,450 --> 00:06:57,890\nRight?\n\n141\n00:06:57,890 --> 00:06:59,870\nWhat you have to believe is I\ncan represent these algebraic\n\n142\n00:06:59,870 --> 00:07:03,210\nexpressions, that I can grab\ntheir parts, that I can put\n\n143\n00:07:03,210 --> 00:07:04,330\nthem together.\n\n144\n00:07:04,330 --> 00:07:07,620\nWe've invented list structures\nso that you can do that.\n\n145\n00:07:07,620 --> 00:07:09,810\nBut you don't want to worry\nabout that now.\n\n146\n00:07:09,810 --> 00:07:11,680\nRight now I'm going to write the\nprogram that encapsulates\n\n147\n00:07:11,680 --> 00:07:14,920\nthese rules independent of\nthe representation of the\n\n148\n00:07:14,920 --> 00:07:16,170\nalgebraic expressions.\n\n149\n00:07:16,170 --> 00:07:20,580\n\n\n150\n00:07:20,580 --> 00:07:27,610\nYou have a derivative of\nan expression with\n\n151\n00:07:27,610 --> 00:07:30,280\nrespect to a variable.\n\n152\n00:07:30,280 --> 00:07:32,020\nThis is a different\nthing than the\n\n153\n00:07:32,020 --> 00:07:35,040\nderivative of the function.\n\n154\n00:07:35,040 --> 00:07:39,130\nThat's what we saw last time,\nthat numerical approximation.\n\n155\n00:07:39,130 --> 00:07:40,860\nIt's something you can't\nopen up a function.\n\n156\n00:07:40,860 --> 00:07:42,990\nIt's just the answers.\n\n157\n00:07:42,990 --> 00:07:44,450\nThe derivative of\nan expression is\n\n158\n00:07:44,450 --> 00:07:45,990\nthe way it's written.\n\n159\n00:07:45,990 --> 00:07:48,410\nAnd therefore it's a syntactic\nphenomenon.\n\n160\n00:07:48,410 --> 00:07:50,540\nAnd so a lot of what we're going\nto be doing today is\n\n161\n00:07:50,540 --> 00:07:53,400\nworrying about syntax,\nsyntax of expressions\n\n162\n00:07:53,400 --> 00:07:54,830\nand things like that.\n\n163\n00:07:54,830 --> 00:07:57,700\nWell, there's a case analysis.\n\n164\n00:07:57,700 --> 00:08:00,420\nAnytime we do anything\ncomplicated thereby a\n\n165\n00:08:00,420 --> 00:08:03,690\nrecursion, we presumably\nneed a case analysis.\n\n166\n00:08:03,690 --> 00:08:05,340\nIt's the essential\nway to begin.\n\n167\n00:08:05,340 --> 00:08:06,590\nAnd that's usually\na conditional\n\n168\n00:08:06,590 --> 00:08:08,170\nof some large kind.\n\n169\n00:08:08,170 --> 00:08:10,000\nWell, what are their\npossibilities?\n\n170\n00:08:10,000 --> 00:08:12,290\nthe first rule that you saw is\nthis something a constant?\n\n171\n00:08:12,290 --> 00:08:16,610\n\n\n172\n00:08:16,610 --> 00:08:20,510\nAnd what I'm asking is, is the\nexpression a constant with\n\n173\n00:08:20,510 --> 00:08:21,920\nrespect to the variable given?\n\n174\n00:08:21,920 --> 00:08:24,990\n\n\n175\n00:08:24,990 --> 00:08:28,460\nIf so, the result is 0,\nbecause the derivative\n\n176\n00:08:28,460 --> 00:08:31,880\nrepresents the rate of\nchange of something.\n\n177\n00:08:31,880 --> 00:08:38,169\nIf, however, the expression that\nI'm taking the derivative\n\n178\n00:08:38,169 --> 00:08:42,770\nof is the variable I'm varying,\nthen this is the same\n\n179\n00:08:42,770 --> 00:08:52,560\nvariable, the expression var,\nthen the rate of change of the\n\n180\n00:08:52,560 --> 00:08:55,560\nexpression with respect\nto the variable is 1.\n\n181\n00:08:55,560 --> 00:08:56,810\nIt's the same 1.\n\n182\n00:08:56,810 --> 00:08:58,970\n\n\n183\n00:08:58,970 --> 00:09:01,490\nWell now there are a couple\nof other possibilities.\n\n184\n00:09:01,490 --> 00:09:04,010\nIt could, for example,\nbe a sum.\n\n185\n00:09:04,010 --> 00:09:06,140\nWell, I don't know how I'm going\nto express sums yet.\n\n186\n00:09:06,140 --> 00:09:07,180\nActually I do.\n\n187\n00:09:07,180 --> 00:09:10,370\nBut I haven't told you yet.\n\n188\n00:09:10,370 --> 00:09:12,630\nBut is it a sum?\n\n189\n00:09:12,630 --> 00:09:15,520\nI'm imagining that there's\nsome way of telling.\n\n190\n00:09:15,520 --> 00:09:20,860\nI'm doing a dispatch on the type\nof the expression here,\n\n191\n00:09:20,860 --> 00:09:24,960\nabsolutely essential in\nbuilding languages.\n\n192\n00:09:24,960 --> 00:09:26,520\nLanguages are made out of\ndifferent expressions.\n\n193\n00:09:26,520 --> 00:09:28,930\nAnd soon we're going to see\nthat in our more powerful\n\n194\n00:09:28,930 --> 00:09:32,760\nmethods of building languages\non languages.\n\n195\n00:09:32,760 --> 00:09:35,530\nIs an expression a sum?\n\n196\n00:09:35,530 --> 00:09:38,360\nIf it's a sum, well, we know the\nrule for derivative of the\n\n197\n00:09:38,360 --> 00:09:42,160\nsum is the sum of the\nderivatives of the parts.\n\n198\n00:09:42,160 --> 00:09:43,370\nOne of them is called\nthe addend and the\n\n199\n00:09:43,370 --> 00:09:44,050\nother is the augend.\n\n200\n00:09:44,050 --> 00:09:45,710\nBut I don't have enough space\non the blackboard\n\n201\n00:09:45,710 --> 00:09:46,810\nto such long names.\n\n202\n00:09:46,810 --> 00:09:48,660\nSo I'll call them A1 and A2.\n\n203\n00:09:48,660 --> 00:09:50,250\nI want to make a sum.\n\n204\n00:09:50,250 --> 00:09:53,100\n\n\n205\n00:09:53,100 --> 00:09:57,300\nDo you remember which is the sum\nfor end or the menu end?\n\n206\n00:09:57,300 --> 00:10:00,310\nOr was it the dividend\nand the divisor or\n\n207\n00:10:00,310 --> 00:10:01,700\nsomething like that?\n\n208\n00:10:01,700 --> 00:10:08,720\nMake sum of the derivative\nof the A1, I'll call it.\n\n209\n00:10:08,720 --> 00:10:12,640\nIt's the addend of the\nexpression with respect to the\n\n210\n00:10:12,640 --> 00:10:23,506\nvariable, and the derivative of\nthe A2 of the expression,\n\n211\n00:10:23,506 --> 00:10:27,020\nbecause the two arguments,\nthe addition with\n\n212\n00:10:27,020 --> 00:10:28,270\nrespect to the variable.\n\n213\n00:10:28,270 --> 00:10:32,450\n\n\n214\n00:10:32,450 --> 00:10:36,350\nAnd another rule that we know is\nproduct rule, which is, if\n\n215\n00:10:36,350 --> 00:10:37,600\nthe expression is a product.\n\n216\n00:10:37,600 --> 00:10:43,090\n\n\n217\n00:10:43,090 --> 00:10:47,070\nBy the way, it's a good idea\nwhen you're defining things,\n\n218\n00:10:47,070 --> 00:10:49,440\nwhen you're defining predicates,\nto give them a\n\n219\n00:10:49,440 --> 00:10:51,290\nname that ends in\na question mark.\n\n220\n00:10:51,290 --> 00:10:53,140\nThis question mark doesn't\nmean anything.\n\n221\n00:10:53,140 --> 00:10:54,730\nIt's for us as an agreement.\n\n222\n00:10:54,730 --> 00:10:57,710\nIt's a conventional interface\nbetween humans so you can read\n\n223\n00:10:57,710 --> 00:10:59,980\nmy programs more easily.\n\n224\n00:10:59,980 --> 00:11:02,510\nSo I want you to, when you write\nprograms, if you define\n\n225\n00:11:02,510 --> 00:11:05,330\na predicate procedure, that's\nsomething that rings true of\n\n226\n00:11:05,330 --> 00:11:07,720\nfalse, it should have a name\nwhich ends in question mark.\n\n227\n00:11:07,720 --> 00:11:09,740\nThe list doesn't care.\n\n228\n00:11:09,740 --> 00:11:11,740\nI care.\n\n229\n00:11:11,740 --> 00:11:13,400\nI want to make a sum.\n\n230\n00:11:13,400 --> 00:11:18,280\nBecause the derivative of a\nproduct is the sum of the\n\n231\n00:11:18,280 --> 00:11:19,920\nfirst times the derivative of\nthe second plus the second\n\n232\n00:11:19,920 --> 00:11:26,620\ntimes the derivative of the\nfirst. Make a sum of two\n\n233\n00:11:26,620 --> 00:11:37,710\nthings, a product of, well, I'm\ngoing to say the M1 of the\n\n234\n00:11:37,710 --> 00:11:47,560\nexpression, and the derivative\nof the M2 of the expression\n\n235\n00:11:47,560 --> 00:12:01,680\nwith respect to the variable,\nand the product of the\n\n236\n00:12:01,680 --> 00:12:10,720\nderivative of M1, the multiplier\nof the expression,\n\n237\n00:12:10,720 --> 00:12:13,450\nwith respect to the variable.\n\n238\n00:12:13,450 --> 00:12:17,340\nIt's the product of that and the\nmultiplicand, M2, of the\n\n239\n00:12:17,340 --> 00:12:18,590\nexpression.\n\n240\n00:12:18,590 --> 00:12:21,660\n\n\n241\n00:12:21,660 --> 00:12:22,630\nMake that product.\n\n242\n00:12:22,630 --> 00:12:23,850\nMake the sum.\n\n243\n00:12:23,850 --> 00:12:25,080\nClose that case.\n\n244\n00:12:25,080 --> 00:12:28,590\nAnd, of course, I could add as\nmany cases as I like here for\n\n245\n00:12:28,590 --> 00:12:30,960\na complete set of rules you\nmight find in a calculus book.\n\n246\n00:12:30,960 --> 00:12:34,880\n\n\n247\n00:12:34,880 --> 00:12:41,184\nSo this is what it takes to\nencapsulate those rules.\n\n248\n00:12:41,184 --> 00:12:43,080\nAnd you see, you have to realize\nthere's a lot of\n\n249\n00:12:43,080 --> 00:12:44,690\nwishful thinking here.\n\n250\n00:12:44,690 --> 00:12:46,620\nI haven't told you anything\nabout how I'm going to make\n\n251\n00:12:46,620 --> 00:12:48,570\nthese representations.\n\n252\n00:12:48,570 --> 00:12:52,830\nNow, once I've decided that\nthis is my set of rules, I\n\n253\n00:12:52,830 --> 00:12:55,820\nthink it's time to play with\nthe representation.\n\n254\n00:12:55,820 --> 00:12:58,030\nLet's attack that/\n\n255\n00:12:58,030 --> 00:13:01,120\nWell, first of all, I'm\ngoing to play a pun.\n\n256\n00:13:01,120 --> 00:13:02,870\nIt's an important pun.\n\n257\n00:13:02,870 --> 00:13:06,590\nIt's a key to a sort\nof powerful idea.\n\n258\n00:13:06,590 --> 00:13:09,750\n\n\n259\n00:13:09,750 --> 00:13:12,790\nIf I want to represent sums, and\nproducts, and differences,\n\n260\n00:13:12,790 --> 00:13:16,450\nand quotients, and things like\nthat, why not use the same\n\n261\n00:13:16,450 --> 00:13:20,660\nlanguage as I'm writing\nmy program in?\n\n262\n00:13:20,660 --> 00:13:23,130\nI write my program in algebraic\nexpressions that\n\n263\n00:13:23,130 --> 00:13:29,280\nlook like the sum of the product\non a and the product\n\n264\n00:13:29,280 --> 00:13:34,330\nof x and x, and things\nlike that.\n\n265\n00:13:34,330 --> 00:13:39,390\nAnd the product of b and x and\nc, whatever, make that a sum\n\n266\n00:13:39,390 --> 00:13:40,960\nof the product.\n\n267\n00:13:40,960 --> 00:13:43,230\nRight now I don't want to have\nprocedures with unknown\n\n268\n00:13:43,230 --> 00:13:48,300\nnumbers of arguments, a product\nof b and x and c.\n\n269\n00:13:48,300 --> 00:13:51,050\n\n\n270\n00:13:51,050 --> 00:13:54,280\nThis is list structure.\n\n271\n00:13:54,280 --> 00:13:56,950\nAnd the reason why this is nice,\nis because any one of\n\n272\n00:13:56,950 --> 00:14:00,380\nthese objects has a property.\n\n273\n00:14:00,380 --> 00:14:01,970\nI know where the car is.\n\n274\n00:14:01,970 --> 00:14:04,100\nThe car is the operator.\n\n275\n00:14:04,100 --> 00:14:08,190\nAnd the operands are the\nsuccessive cdrs the successive\n\n276\n00:14:08,190 --> 00:14:12,276\ncars of the cdrs of the\nlist that this is.\n\n277\n00:14:12,276 --> 00:14:14,470\nIt makes it very convenient.\n\n278\n00:14:14,470 --> 00:14:15,560\nI have to parse it.\n\n279\n00:14:15,560 --> 00:14:17,590\nIt's been done for me.\n\n280\n00:14:17,590 --> 00:14:19,685\nI'm using the embedding\nand Lisp to advantage.\n\n281\n00:14:19,685 --> 00:14:22,860\n\n\n282\n00:14:22,860 --> 00:14:29,340\nSo, for example, let's start\nusing list structure to write\n\n283\n00:14:29,340 --> 00:14:35,390\ndown the representation that I'm\nimplicitly assuming here.\n\n284\n00:14:35,390 --> 00:14:37,590\nWell I have to define various\nthings that are implied in\n\n285\n00:14:37,590 --> 00:14:38,640\nthis representation.\n\n286\n00:14:38,640 --> 00:14:41,210\nLike I have to find out\nhow to do a constant,\n\n287\n00:14:41,210 --> 00:14:42,520\nhow you do same variable.\n\n288\n00:14:42,520 --> 00:14:45,890\nLet's do those first. That's\npretty easy enough.\n\n289\n00:14:45,890 --> 00:14:47,410\nNow I'm going to be introducing\nlots of primitives\n\n290\n00:14:47,410 --> 00:14:49,680\nhere, because these are\nthe primitives that\n\n291\n00:14:49,680 --> 00:14:51,745\ncome with list structure.\n\n292\n00:14:51,745 --> 00:14:53,015\nOK, you define a constant.\n\n293\n00:14:53,015 --> 00:15:02,800\n\n\n294\n00:15:02,800 --> 00:15:06,350\nAnd what I mean by a constant,\nan expression that's constant\n\n295\n00:15:06,350 --> 00:15:10,860\nwith respect to a veritable,\nis that the expression is\n\n296\n00:15:10,860 --> 00:15:11,530\nsomething simple.\n\n297\n00:15:11,530 --> 00:15:13,550\nI can't take it into\npieces, and yet\n\n298\n00:15:13,550 --> 00:15:16,550\nit isn't that variable.\n\n299\n00:15:16,550 --> 00:15:18,940\nI can't break it up, and yet\nit isn't that variable.\n\n300\n00:15:18,940 --> 00:15:22,840\nThat does not mean that there\nmay be other expressions that\n\n301\n00:15:22,840 --> 00:15:25,230\nare more complicated\nthat are constants.\n\n302\n00:15:25,230 --> 00:15:26,700\nIt's just that I'm going to\nlook at the primitive\n\n303\n00:15:26,700 --> 00:15:30,510\nconstants in this way.\n\n304\n00:15:30,510 --> 00:15:34,080\nSo what this is, is it says\nthat's it's the and.\n\n305\n00:15:34,080 --> 00:15:37,030\nI can combine predicate\nexpressions which return true\n\n306\n00:15:37,030 --> 00:15:38,610\nor false with and.\n\n307\n00:15:38,610 --> 00:15:45,600\nSomething atomic, The expression\nis atomic, meaning\n\n308\n00:15:45,600 --> 00:15:47,050\nit cannot be broken\ninto parts.\n\n309\n00:15:47,050 --> 00:15:51,150\nIt doesn't have a car and a cdr.\nIt's not a list. It adds\n\n310\n00:15:51,150 --> 00:15:54,250\na special test built\ninto the system.\n\n311\n00:15:54,250 --> 00:16:06,950\nAnd it's not identically\nequal to that variable.\n\n312\n00:16:06,950 --> 00:16:11,810\nI'm representing my variable\nby things that are symbols\n\n313\n00:16:11,810 --> 00:16:16,550\nwhich cannot be broken into\npieces, things like x, and y,\n\n314\n00:16:16,550 --> 00:16:17,800\nthings like this.\n\n315\n00:16:17,800 --> 00:16:19,850\n\n\n316\n00:16:19,850 --> 00:16:21,890\nWhereas, of course, something\nlike this can be broken up\n\n317\n00:16:21,890 --> 00:16:23,140\ninto pieces.\n\n318\n00:16:23,140 --> 00:16:24,860\n\n\n319\n00:16:24,860 --> 00:16:40,560\nAnd the same variable of an\nexpression with respect to a\n\n320\n00:16:40,560 --> 00:16:48,840\nvariable is, in fact, an\natomic expression.\n\n321\n00:16:48,840 --> 00:16:50,040\nI want to have an atomic\n\n322\n00:16:50,040 --> 00:16:59,330\nexpression, which is identical.\n\n323\n00:16:59,330 --> 00:17:08,030\n\n\n324\n00:17:08,030 --> 00:17:13,329\nI don't want to look inside\nthis stuff anymore.\n\n325\n00:17:13,329 --> 00:17:16,040\nThese are primitive maybe.\n\n326\n00:17:16,040 --> 00:17:18,180\nBut it doesn't matter.\n\n327\n00:17:18,180 --> 00:17:22,569\nI'm using things that are given\nto me with a language.\n\n328\n00:17:22,569 --> 00:17:24,300\nI'm not terribly interest\nin them\n\n329\n00:17:24,300 --> 00:17:26,900\nNow how do we deal with sums?\n\n330\n00:17:26,900 --> 00:17:29,100\nAh, something very interesting\nwill happen.\n\n331\n00:17:29,100 --> 00:17:32,380\nA sum is something which is not\natomic and begins with the\n\n332\n00:17:32,380 --> 00:17:35,230\nplus symbol.\n\n333\n00:17:35,230 --> 00:17:36,680\nThat's what it means.\n\n334\n00:17:36,680 --> 00:17:39,125\nSo here, I will define.\n\n335\n00:17:39,125 --> 00:17:45,630\n\n\n336\n00:17:45,630 --> 00:18:08,380\nAn question is a sum if and it's\nnot atomic and it's head,\n\n337\n00:18:08,380 --> 00:18:15,140\nit's beginning, its car of the\nexpression is the symbol plus.\n\n338\n00:18:15,140 --> 00:18:19,950\n\n\n339\n00:18:19,950 --> 00:18:21,730\nNow you're about to see\nsomething you haven't seen\n\n340\n00:18:21,730 --> 00:18:23,690\nbefore, this quotation.\n\n341\n00:18:23,690 --> 00:18:26,240\n\n\n342\n00:18:26,240 --> 00:18:29,440\nWhy do I have that\nquotation there?\n\n343\n00:18:29,440 --> 00:18:30,970\nSay your name,\n\n344\n00:18:30,970 --> 00:18:31,410\nAUDIENCE: Susanna.\n\n345\n00:18:31,410 --> 00:18:32,270\nPROFESSOR: Louder.\n\n346\n00:18:32,270 --> 00:18:33,190\nAUDIENCE: Susanna\n\n347\n00:18:33,190 --> 00:18:34,250\nPROFESSOR: Say your name.\n\n348\n00:18:34,250 --> 00:18:35,160\nAUDIENCE: Your name.\n\n349\n00:18:35,160 --> 00:18:35,910\nPROFESSOR: Louder.\n\n350\n00:18:35,910 --> 00:18:36,960\nAUDIENCE: Your name.\n\n351\n00:18:36,960 --> 00:18:39,100\nPROFESSOR: OK.\n\n352\n00:18:39,100 --> 00:18:42,040\nWhat I'm showing you here\nis that the words\n\n353\n00:18:42,040 --> 00:18:45,520\nof English are ambiguous.\n\n354\n00:18:45,520 --> 00:18:52,220\nI was saying, say your name.\n\n355\n00:18:52,220 --> 00:18:57,070\nI was also possibly saying\nsay, your name.\n\n356\n00:18:57,070 --> 00:19:00,710\n\n\n357\n00:19:00,710 --> 00:19:04,100\nBut that cannot be distinguished\nin speech.\n\n358\n00:19:04,100 --> 00:19:09,600\nHowever, we do have a notation\nin writing, which is quotation\n\n359\n00:19:09,600 --> 00:19:14,180\nfor distinguishing these\ntwo possible meanings.\n\n360\n00:19:14,180 --> 00:19:19,490\nIn particular, over here, in\nLisp we have a notation for\n\n361\n00:19:19,490 --> 00:19:21,510\ndistinguishing these meetings.\n\n362\n00:19:21,510 --> 00:19:24,992\nIf I were to just write a plus\nhere, a plus symbol, I would\n\n363\n00:19:24,992 --> 00:19:29,400\nbe asking, is the first element\nof the expression, is\n\n364\n00:19:29,400 --> 00:19:32,220\nthe operator position\nof the expression,\n\n365\n00:19:32,220 --> 00:19:34,760\nthe addition operator?\n\n366\n00:19:34,760 --> 00:19:36,330\nI don't know.\n\n367\n00:19:36,330 --> 00:19:39,550\nI would have to have written the\naddition operator there,\n\n368\n00:19:39,550 --> 00:19:41,330\nwhich I can't write.\n\n369\n00:19:41,330 --> 00:19:45,470\nHowever, this way I'm asking,\nis this the symbolic object\n\n370\n00:19:45,470 --> 00:19:49,790\nplus, which normally stands\nfor the addition operator?\n\n371\n00:19:49,790 --> 00:19:50,420\nThat's what I want.\n\n372\n00:19:50,420 --> 00:19:53,110\nThat's the question\nI want to ask.\n\n373\n00:19:53,110 --> 00:19:55,430\nNow before I go any further,\nI want to point out the\n\n374\n00:19:55,430 --> 00:19:59,780\nquotation is a very complex\nconcept, and adding it to a\n\n375\n00:19:59,780 --> 00:20:03,510\nlanguage causes a great\ndeal of troubles.\n\n376\n00:20:03,510 --> 00:20:06,370\nConsider the next slide.\n\n377\n00:20:06,370 --> 00:20:11,830\nHere's a deduction which we\nshould all agree with.\n\n378\n00:20:11,830 --> 00:20:17,530\nWe have, Alyssa is smart and\nAlyssa is George's mother.\n\n379\n00:20:17,530 --> 00:20:22,350\nThis is an equality, is.\n\n380\n00:20:22,350 --> 00:20:27,470\nFrom those two, we can deduce\nthat George's mother is smart.\n\n381\n00:20:27,470 --> 00:20:32,320\nBecause we can always substitute\nequals for equals\n\n382\n00:20:32,320 --> 00:20:34,250\nin expressions.\n\n383\n00:20:34,250 --> 00:20:36,420\nOr can we?\n\n384\n00:20:36,420 --> 00:20:41,400\nHere's a case where we have\n\"Chicago\" has seven letters.\n\n385\n00:20:41,400 --> 00:20:45,100\nThe quotation means that I'm\ndiscussing the word Chicago,\n\n386\n00:20:45,100 --> 00:20:46,365\nnot what the word represents.\n\n387\n00:20:46,365 --> 00:20:49,940\n\n\n388\n00:20:49,940 --> 00:20:54,830\nHere I have that Chicago is the\nbiggest city in Illinois.\n\n389\n00:20:54,830 --> 00:20:57,160\nAs a consequence of this, I\nwould like to deduce that the\n\n390\n00:20:57,160 --> 00:20:59,250\nbiggest city in Illinois\nhas seven letters.\n\n391\n00:20:59,250 --> 00:21:00,785\nBut that's manifestly false.\n\n392\n00:21:00,785 --> 00:21:05,480\n\n\n393\n00:21:05,480 --> 00:21:09,420\nWow, it works.\n\n394\n00:21:09,420 --> 00:21:13,420\nOK, so once we have things like\nthat, our language gets\n\n395\n00:21:13,420 --> 00:21:14,540\nmuch more complicated.\n\n396\n00:21:14,540 --> 00:21:17,440\nBecause it's no longer true that\nthings we tend to like to\n\n397\n00:21:17,440 --> 00:21:19,750\ndo with languages, like\nsubstituting equals for equals\n\n398\n00:21:19,750 --> 00:21:22,840\nand getting right answers, are\ngoing to work without being\n\n399\n00:21:22,840 --> 00:21:24,550\nvery careful.\n\n400\n00:21:24,550 --> 00:21:26,470\nWe can't substitute into what's\ncalled referentially\n\n401\n00:21:26,470 --> 00:21:30,410\nopaque contexts, of which a\nquotation is the prototypical\n\n402\n00:21:30,410 --> 00:21:33,380\ntype of referentially\nopaque context.\n\n403\n00:21:33,380 --> 00:21:35,560\nIf you know what that means, you\ncan consult a philosopher.\n\n404\n00:21:35,560 --> 00:21:38,790\nPresumably there is\none in the room.\n\n405\n00:21:38,790 --> 00:21:42,280\nIn any case, let's continue now,\nnow that we at least have\n\n406\n00:21:42,280 --> 00:21:45,660\nan operational understanding of\na 2000-year-old issue that\n\n407\n00:21:45,660 --> 00:21:47,350\nhas to do with name, and\nmention, and all sorts of\n\n408\n00:21:47,350 --> 00:21:48,600\nthings like that.\n\n409\n00:21:48,600 --> 00:21:52,440\n\n\n410\n00:21:52,440 --> 00:21:59,790\nI have to define what I mean,\nhow to make a sum of two\n\n411\n00:21:59,790 --> 00:22:02,250\nthings, an a1 and a2.\n\n412\n00:22:02,250 --> 00:22:03,590\nAnd I'm going to do\nthis very simply.\n\n413\n00:22:03,590 --> 00:22:13,600\nIt's a list of the symbol\nplus, and a1, and a2.\n\n414\n00:22:13,600 --> 00:22:17,075\nAnd I can determine\nthe first element.\n\n415\n00:22:17,075 --> 00:22:21,600\n\n\n416\n00:22:21,600 --> 00:22:34,510\nDefine a1 to be cadr. I've just\n\n417\n00:22:34,510 --> 00:22:36,370\nintroduced another primitive.\n\n418\n00:22:36,370 --> 00:22:39,990\nThis is the car of the\ncdr of something.\n\n419\n00:22:39,990 --> 00:22:43,950\nYou might want to know why car\nand cdr are names of these\n\n420\n00:22:43,950 --> 00:22:46,720\nprimitives, and why they've\nsurvived, even though they're\n\n421\n00:22:46,720 --> 00:22:48,970\nmuch better ideas like\nleft and right.\n\n422\n00:22:48,970 --> 00:22:51,380\nWe could have called them\nthings like that.\n\n423\n00:22:51,380 --> 00:22:54,340\nWell, first of all, the names\ncome from the fact that in the\n\n424\n00:22:54,340 --> 00:22:57,470\ngreat past, when Lisp was\ninvented, I suppose in '58 or\n\n425\n00:22:57,470 --> 00:23:00,730\nsomething, it was on a\n704 or something like\n\n426\n00:23:00,730 --> 00:23:01,870\nthat, which had a machine.\n\n427\n00:23:01,870 --> 00:23:04,440\nIt was a machine that had an\naddress register and a\n\n428\n00:23:04,440 --> 00:23:05,340\ndecrement register.\n\n429\n00:23:05,340 --> 00:23:07,610\nAnd these were the contents of\nthe address register and the\n\n430\n00:23:07,610 --> 00:23:08,270\ndecrement register.\n\n431\n00:23:08,270 --> 00:23:09,880\nSo it's an historical\naccident.\n\n432\n00:23:09,880 --> 00:23:11,880\nNow why have these\nnames survived?\n\n433\n00:23:11,880 --> 00:23:14,110\nIt's because Lisp programmers\nlike to talk to each other\n\n434\n00:23:14,110 --> 00:23:15,900\nover the phone.\n\n435\n00:23:15,900 --> 00:23:18,460\nAnd if you want to have a long\nsequence of cars and cdrs you\n\n436\n00:23:18,460 --> 00:23:22,530\nmight say, cdaddedr, which\ncan be understood.\n\n437\n00:23:22,530 --> 00:23:26,330\nBut left of right or right of\nleft is not so clear if you\n\n438\n00:23:26,330 --> 00:23:26,970\nget good at it.\n\n439\n00:23:26,970 --> 00:23:30,570\nSo that's why we have\nthese words.\n\n440\n00:23:30,570 --> 00:23:33,566\nAll of them up to four deep\nare defined typically in a\n\n441\n00:23:33,566 --> 00:23:34,816\nLisp system.\n\n442\n00:23:34,816 --> 00:23:38,270\n\n\n443\n00:23:38,270 --> 00:23:40,540\nA2 to be--\n\n444\n00:23:40,540 --> 00:23:43,540\n\n\n445\n00:23:43,540 --> 00:23:46,170\nand, of course, you can see\nthat if I looked at one of\n\n446\n00:23:46,170 --> 00:23:54,630\nthese expressions like the sum\nof 3 and 5, what that is is a\n\n447\n00:23:54,630 --> 00:24:06,100\nlist containing the symbol\nplus, and a number 3,\n\n448\n00:24:06,100 --> 00:24:11,470\nand a number 5.\n\n449\n00:24:11,470 --> 00:24:16,100\nThen the car is the\nsymbol plus.\n\n450\n00:24:16,100 --> 00:24:19,210\nThe car of the cdr. Well\nI take the cdr and\n\n451\n00:24:19,210 --> 00:24:20,070\nthen I take the car.\n\n452\n00:24:20,070 --> 00:24:21,200\nAnd that's how I get to the 3.\n\n453\n00:24:21,200 --> 00:24:22,630\nThat's the first argument.\n\n454\n00:24:22,630 --> 00:24:24,370\nAnd the car of the cdr\nof the cdr gets me to\n\n455\n00:24:24,370 --> 00:24:25,640\nthis one, the 5.\n\n456\n00:24:25,640 --> 00:24:28,860\n\n\n457\n00:24:28,860 --> 00:24:32,970\nAnd similarly, of course, I\ncan define what's going on\n\n458\n00:24:32,970 --> 00:24:35,300\nwith products.\n\n459\n00:24:35,300 --> 00:24:36,550\nLet's do that very quickly.\n\n460\n00:24:36,550 --> 00:24:48,760\n\n\n461\n00:24:48,760 --> 00:24:51,130\nIs the expression a product?\n\n462\n00:24:51,130 --> 00:25:01,910\nYes if and if it's true, that's\nit's not atomic and\n\n463\n00:25:01,910 --> 00:25:13,260\nit's EQ quote, the asterisk\nsymbol, which is the operator\n\n464\n00:25:13,260 --> 00:25:15,800\nfor multiplication.\n\n465\n00:25:15,800 --> 00:25:35,090\nMake product of an M1 and an\nM2 to be list, quote, the\n\n466\n00:25:35,090 --> 00:25:40,930\nasterisk operation\nand M1 and M2.\n\n467\n00:25:40,930 --> 00:26:00,596\nand I define M1 to be cadr and\nM2 to be caddr. You get to be\n\n468\n00:26:00,596 --> 00:26:02,690\na good Lisp programmer because\nyou start talking that way.\n\n469\n00:26:02,690 --> 00:26:06,430\nI cdr down lists and console\nthem up and so on.\n\n470\n00:26:06,430 --> 00:26:09,480\nNow, now that we have\nessentially a complete program\n\n471\n00:26:09,480 --> 00:26:10,880\nfor finding derivatives,\nyou can add more\n\n472\n00:26:10,880 --> 00:26:12,360\nrules if you like.\n\n473\n00:26:12,360 --> 00:26:14,800\nWhat kind of behavior\ndo we get out of it?\n\n474\n00:26:14,800 --> 00:26:17,930\nI'll have to clear that x.\n\n475\n00:26:17,930 --> 00:26:28,060\nWell, supposing I define foo\nhere to be the sum of the\n\n476\n00:26:28,060 --> 00:26:30,450\nproduct of ax square\nand bx plus c.\n\n477\n00:26:30,450 --> 00:26:34,020\nThat's the same thing we see\nhere as the algebraic\n\n478\n00:26:34,020 --> 00:26:35,260\nexpression written in the\nmore conventional\n\n479\n00:26:35,260 --> 00:26:37,860\nnotation over there.\n\n480\n00:26:37,860 --> 00:26:40,620\nWell, the derivative of foo with\nrespect to x, which we\n\n481\n00:26:40,620 --> 00:26:46,250\ncan see over here, is this\nhorrible, horrendous mess.\n\n482\n00:26:46,250 --> 00:26:50,760\nI would like it to\nbe 2ax plus b.\n\n483\n00:26:50,760 --> 00:26:52,240\nBut it's not.\n\n484\n00:26:52,240 --> 00:26:54,620\nIt's equivalent to it.\n\n485\n00:26:54,620 --> 00:26:56,090\nWhat is it?\n\n486\n00:26:56,090 --> 00:27:00,510\nI have here, what do I have?\n\n487\n00:27:00,510 --> 00:27:04,550\nI have the derivative of\nthe product of x and x.\n\n488\n00:27:04,550 --> 00:27:09,410\nOver here is, of course,\nthe sum of x times\n\n489\n00:27:09,410 --> 00:27:12,830\n1 and 1 times x.\n\n490\n00:27:12,830 --> 00:27:14,100\nNow, well, it's the first times\nthe derivative of the\n\n491\n00:27:14,100 --> 00:27:15,330\nsecond plus the second times the\nderivative of the first.\n\n492\n00:27:15,330 --> 00:27:17,780\nIt's right.\n\n493\n00:27:17,780 --> 00:27:20,220\nThat's 2x of course.\n\n494\n00:27:20,220 --> 00:27:26,600\na times 2x is 2ax plus 0X square\ndoesn't count plus B\n\n495\n00:27:26,600 --> 00:27:29,100\nover here plus a bunch of 0's.\n\n496\n00:27:29,100 --> 00:27:30,130\nWell the answer is right.\n\n497\n00:27:30,130 --> 00:27:34,390\nBut I give people take off\npoints on an exam for that,\n\n498\n00:27:34,390 --> 00:27:35,690\nsadly enough.\n\n499\n00:27:35,690 --> 00:27:37,830\nLet's worry about that\nin the next segment.\n\n500\n00:27:37,830 --> 00:27:39,080\nAre there any questions?\n\n501\n00:27:39,080 --> 00:27:42,970\n\n\n502\n00:27:42,970 --> 00:27:44,070\nYes?\n\n503\n00:27:44,070 --> 00:27:46,790\nAUDIENCE: If you had left the\nquote when you put the plus,\n\n504\n00:27:46,790 --> 00:27:51,120\nthen would that be referring\nto the procedure plus and\n\n505\n00:27:51,120 --> 00:27:53,560\ncould you do a comparison\nbetween that procedure and\n\n506\n00:27:53,560 --> 00:27:55,460\nsome other procedure\nif you wanted to?\n\n507\n00:27:55,460 --> 00:27:56,320\nPROFESSOR: Yes.\n\n508\n00:27:56,320 --> 00:27:58,960\nGood question.\n\n509\n00:27:58,960 --> 00:28:05,650\nIf I had left this quotation\noff at this point, if I had\n\n510\n00:28:05,650 --> 00:28:08,720\nleft that quotation off at that\npoint, then I would be\n\n511\n00:28:08,720 --> 00:28:12,790\nreferring here to the procedure\nwhich is the thing\n\n512\n00:28:12,790 --> 00:28:15,510\nthat plus is defined to be.\n\n513\n00:28:15,510 --> 00:28:22,810\nAnd indeed, I could compare\nsome procedures with each\n\n514\n00:28:22,810 --> 00:28:25,070\nother for identity.\n\n515\n00:28:25,070 --> 00:28:28,080\nNow what that means is\nnot clear right now.\n\n516\n00:28:28,080 --> 00:28:30,100\nI don't like to think\nabout it.\n\n517\n00:28:30,100 --> 00:28:31,840\nBecause I don't know exactly\nwhat it would need to compare\n\n518\n00:28:31,840 --> 00:28:32,450\nprocedures.\n\n519\n00:28:32,450 --> 00:28:35,610\nThere are reasons why that\nmay make no sense at all.\n\n520\n00:28:35,610 --> 00:28:38,890\nHowever, the symbols,\nwe understand.\n\n521\n00:28:38,890 --> 00:28:41,240\nAnd so that's why I\nput that quote in.\n\n522\n00:28:41,240 --> 00:28:42,510\nI want to talk about\nthe symbol that's\n\n523\n00:28:42,510 --> 00:28:43,760\napparent on the page.\n\n524\n00:28:43,760 --> 00:28:46,250\n\n\n525\n00:28:46,250 --> 00:28:48,700\nAny other questions?\n\n526\n00:28:48,700 --> 00:28:50,720\nOK.\n\n527\n00:28:50,720 --> 00:28:51,060\nThank you.\n\n528\n00:28:51,060 --> 00:28:54,210\nLet's take a break.\n\n529\n00:28:54,210 --> 00:29:30,010\n[MUSIC PLAYING]\n\n530\n00:29:30,010 --> 00:29:31,580\nPROFESSOR: Well, let's see.\n\n531\n00:29:31,580 --> 00:29:35,560\nWe've just developed a fairly\nplausible program for\n\n532\n00:29:35,560 --> 00:29:38,390\ncomputing the derivatives of\nalgebraic expressions.\n\n533\n00:29:38,390 --> 00:29:40,400\nIt's an incomplete program,\nif you would\n\n534\n00:29:40,400 --> 00:29:42,330\nlike to add more rules.\n\n535\n00:29:42,330 --> 00:29:46,020\nAnd perhaps you might extend\nit to deal with uses of\n\n536\n00:29:46,020 --> 00:29:48,390\naddition with any number of\narguments and multiplication\n\n537\n00:29:48,390 --> 00:29:49,950\nwith any of the number\nof arguments.\n\n538\n00:29:49,950 --> 00:29:52,470\nAnd that's all rather easy.\n\n539\n00:29:52,470 --> 00:29:57,620\nHowever, there was a little\nfly in that ointment.\n\n540\n00:29:57,620 --> 00:30:02,980\nWe go back to this slide.\n\n541\n00:30:02,980 --> 00:30:09,000\nWe see that the expressions that\nwe get are rather bad.\n\n542\n00:30:09,000 --> 00:30:11,620\nThis is a rather\nbad expression.\n\n543\n00:30:11,620 --> 00:30:14,000\nHow do we get such\nan expression?\n\n544\n00:30:14,000 --> 00:30:16,940\nWhy do we have that\nexpression?\n\n545\n00:30:16,940 --> 00:30:19,060\nLet's look at this expression\nin some detail.\n\n546\n00:30:19,060 --> 00:30:21,850\nLet's find out where all\nthe pieces come from.\n\n547\n00:30:21,850 --> 00:30:24,590\nAs we see here, we\nhave a sum--\n\n548\n00:30:24,590 --> 00:30:27,012\njust what I showed you at the\nend of the last time--\n\n549\n00:30:27,012 --> 00:30:30,110\nof X times 1 plus 1\ntime X. That is a\n\n550\n00:30:30,110 --> 00:30:32,590\nderivative of this product.\n\n551\n00:30:32,590 --> 00:30:36,270\nThe produce of a times that,\nwhere a does not depend upon\n\n552\n00:30:36,270 --> 00:30:40,430\nx, and therefore is constant\nwith respect to x, is this\n\n553\n00:30:40,430 --> 00:30:43,910\nsum, which goes from here all\nthe way through here and\n\n554\n00:30:43,910 --> 00:30:44,840\nthrough here.\n\n555\n00:30:44,840 --> 00:30:48,470\nBecause it is the first thing\ntimes the derivative of the\n\n556\n00:30:48,470 --> 00:30:54,900\nsecond plus the derivative of\nthe first times the second as\n\n557\n00:30:54,900 --> 00:30:57,970\nthe program we wrote\non the blackboard\n\n558\n00:30:57,970 --> 00:31:00,740\nindicated we should do.\n\n559\n00:31:00,740 --> 00:31:06,690\nAnd, of course, the product of\nbx over here manifests itself\n\n560\n00:31:06,690 --> 00:31:15,220\nas B times 1 plus 0 times X\nbecause we see that B does not\n\n561\n00:31:15,220 --> 00:31:19,085\ndepend upon X. And so the\nderivative of B is this 0, and\n\n562\n00:31:19,085 --> 00:31:23,100\nthe derivative of X with respect\nitself is the 1.\n\n563\n00:31:23,100 --> 00:31:26,510\nAnd, of course, the derivative\nof the sums over here turn\n\n564\n00:31:26,510 --> 00:31:29,360\ninto these two sums of the\nderivatives of the parts.\n\n565\n00:31:29,360 --> 00:31:32,620\nSo what we're seeing here is\nexactly the thing I was trying\n\n566\n00:31:32,620 --> 00:31:37,760\nto tell you about with Fibonacci\nnumbers a while ago,\n\n567\n00:31:37,760 --> 00:31:44,430\nthat the form of the process\nis expanded from the local\n\n568\n00:31:44,430 --> 00:31:48,850\nrules that you see in the\nprocedure, that the procedure\n\n569\n00:31:48,850 --> 00:31:51,720\nrepresents a set of local rules\nfor the expansion of\n\n570\n00:31:51,720 --> 00:31:53,520\nthis process.\n\n571\n00:31:53,520 --> 00:31:59,440\nAnd here, the process left\nbehind some stuff, which is\n\n572\n00:31:59,440 --> 00:32:00,370\nthe answer.\n\n573\n00:32:00,370 --> 00:32:03,850\nAnd it was constructed by the\nwalk it takes of the tree\n\n574\n00:32:03,850 --> 00:32:05,775\nstructure, which is\nthe expression.\n\n575\n00:32:05,775 --> 00:32:08,390\n\n\n576\n00:32:08,390 --> 00:32:11,540\nSo every part in the answer we\nsee here derives from some\n\n577\n00:32:11,540 --> 00:32:14,670\npart of the problem.\n\n578\n00:32:14,670 --> 00:32:17,360\nNow, we can look at, for\nexample, the derivative of\n\n579\n00:32:17,360 --> 00:32:20,500\nfoo, which is ax square plus\nbx plus c, with respect to\n\n580\n00:32:20,500 --> 00:32:25,320\nother things, like here, for\nexample, we can see that the\n\n581\n00:32:25,320 --> 00:32:27,860\nderivative of foo with\nrespect to a.\n\n582\n00:32:27,860 --> 00:32:29,390\nAnd it's very similar.\n\n583\n00:32:29,390 --> 00:32:32,840\nIt's, in fact, the identical\nalgebraic expression, except\n\n584\n00:32:32,840 --> 00:32:34,320\nfor the fact that theses\n0's and 1's are\n\n585\n00:32:34,320 --> 00:32:35,900\nin different places.\n\n586\n00:32:35,900 --> 00:32:38,260\nBecause the only degree of\nfreedom we have in this tree\n\n587\n00:32:38,260 --> 00:32:42,285\nwalk is what's constant with\nrespect to the variable we're\n\n588\n00:32:42,285 --> 00:32:44,550\ntaking the derivative\nwith respect to and\n\n589\n00:32:44,550 --> 00:32:45,800\nwas the same variable.\n\n590\n00:32:45,800 --> 00:32:48,310\n\n\n591\n00:32:48,310 --> 00:32:51,660\nIn other words, if we go back\nto this blackboard and we\n\n592\n00:32:51,660 --> 00:32:55,302\nlook, we have no choice what\nto do when we take the\n\n593\n00:32:55,302 --> 00:32:58,150\nderivative of the sum\nor a product.\n\n594\n00:32:58,150 --> 00:33:03,840\nThe only interesting place here\nis, is the expression the\n\n595\n00:33:03,840 --> 00:33:07,590\nvariable, or is the expression\na constant with respect to\n\n596\n00:33:07,590 --> 00:33:10,130\nthat variable for very, very\nsmall expressions?\n\n597\n00:33:10,130 --> 00:33:13,220\nIn which case we get various\n1's and 0's, which if we go\n\n598\n00:33:13,220 --> 00:33:17,290\nback to this slide, we can see\nthat the 0's that appear here,\n\n599\n00:33:17,290 --> 00:33:21,740\nfor example, this 1 over here\nin derivative of foo with\n\n600\n00:33:21,740 --> 00:33:25,980\nrespect to A, which gets us an\nX square, because that 1 gets\n\n601\n00:33:25,980 --> 00:33:32,770\nthe multiply of X and X into\nthe answer, that 1 is 0.\n\n602\n00:33:32,770 --> 00:33:34,173\nOver here, we're not taking\nthe derivative of foo with\n\n603\n00:33:34,173 --> 00:33:36,690\nrespect to c.\n\n604\n00:33:36,690 --> 00:33:40,301\nBut the shapes of these\nexpressions are the same.\n\n605\n00:33:40,301 --> 00:33:42,561\nSee all those shapes.\n\n606\n00:33:42,561 --> 00:33:43,811\nThey're the same.\n\n607\n00:33:43,811 --> 00:33:50,480\n\n\n608\n00:33:50,480 --> 00:33:53,750\nWell is there anything\nwrong with our rules?\n\n609\n00:33:53,750 --> 00:33:54,030\nNo.\n\n610\n00:33:54,030 --> 00:33:56,250\nThey're the right rules.\n\n611\n00:33:56,250 --> 00:33:58,160\nWe've been through\nthis one before.\n\n612\n00:33:58,160 --> 00:34:02,020\nOne of the things you're going\nto begin to discover is that\n\n613\n00:34:02,020 --> 00:34:03,270\nthere aren't too many\ngood ideas.\n\n614\n00:34:03,270 --> 00:34:06,510\n\n\n615\n00:34:06,510 --> 00:34:12,139\nWhen we were looking at rational\nnumbers yesterday,\n\n616\n00:34:12,139 --> 00:34:14,909\nthe problem was that we got\n6/8 rather then 3/4.\n\n617\n00:34:14,909 --> 00:34:17,949\nThe answer was unsimplified.\n\n618\n00:34:17,949 --> 00:34:21,150\nThe problem, of course,\nis very similar.\n\n619\n00:34:21,150 --> 00:34:24,350\nThere are things I'd like to be\nidentical by simplification\n\n620\n00:34:24,350 --> 00:34:27,350\nthat don't become identical.\n\n621\n00:34:27,350 --> 00:34:30,690\nAnd yet the rules for doing\naddition a multiplication of\n\n622\n00:34:30,690 --> 00:34:34,000\nrational numbers were correct.\n\n623\n00:34:34,000 --> 00:34:36,350\nSo the way we might solve this\nproblem is do the thing we did\n\n624\n00:34:36,350 --> 00:34:37,940\nlast time, which always works.\n\n625\n00:34:37,940 --> 00:34:40,690\nIf something worked last time\nit ought to work again.\n\n626\n00:34:40,690 --> 00:34:43,120\nIt's changed representation.\n\n627\n00:34:43,120 --> 00:34:45,350\nPerhaps in the representation\nwe could put in a\n\n628\n00:34:45,350 --> 00:34:48,940\nsimplification step that\nproduces a simplified\n\n629\n00:34:48,940 --> 00:34:50,199\nrepresentation.\n\n630\n00:34:50,199 --> 00:34:52,580\nThis may not always\nwork, of course.\n\n631\n00:34:52,580 --> 00:34:55,210\nI'm not trying to say that\nit always works.\n\n632\n00:34:55,210 --> 00:34:59,540\nBut it's one of the pieces of\nartillery we have in our war\n\n633\n00:34:59,540 --> 00:35:01,560\nagainst complexity.\n\n634\n00:35:01,560 --> 00:35:04,360\nYou see, because we solved our\nproblem very carefully.\n\n635\n00:35:04,360 --> 00:35:06,170\nWhat we've done, is\nwe've divided the\n\n636\n00:35:06,170 --> 00:35:07,630\nworld in several parts.\n\n637\n00:35:07,630 --> 00:35:12,980\nThere are derivatives rules and\ngeneral rules for algebra\n\n638\n00:35:12,980 --> 00:35:16,420\nof some sort at this\nlevel of detail.\n\n639\n00:35:16,420 --> 00:35:17,925\nand i have an abstraction\nbarrier.\n\n640\n00:35:17,925 --> 00:35:21,874\n\n\n641\n00:35:21,874 --> 00:35:32,710\nAnd i have the representation of\nthe algebraic expressions,\n\n642\n00:35:32,710 --> 00:35:33,960\nlist structure.\n\n643\n00:35:33,960 --> 00:35:37,420\n\n\n644\n00:35:37,420 --> 00:35:43,050\nAnd in this barrier, I have\nthe interface procedures.\n\n645\n00:35:43,050 --> 00:35:49,410\nI have constant, and things\nlike same-var.\n\n646\n00:35:49,410 --> 00:35:54,680\n\n\n647\n00:35:54,680 --> 00:35:58,095\nI have things like\nsum, make-sum.\n\n648\n00:35:58,095 --> 00:36:02,310\n\n\n649\n00:36:02,310 --> 00:36:06,770\nI have A1, A2.\n\n650\n00:36:06,770 --> 00:36:09,370\nI have products and things\nlike that, all the other\n\n651\n00:36:09,370 --> 00:36:11,490\nthings I might need for various\nkinds of algebraic\n\n652\n00:36:11,490 --> 00:36:13,000\nexpressions.\n\n653\n00:36:13,000 --> 00:36:18,080\nMaking this barrier allows me\nto arbitrarily change the\n\n654\n00:36:18,080 --> 00:36:21,710\nrepresentation without changing\nthe rules that are\n\n655\n00:36:21,710 --> 00:36:25,060\nwritten in terms of that\nrepresentation.\n\n656\n00:36:25,060 --> 00:36:28,220\nSo if I can make the problem\ngo away by changing\n\n657\n00:36:28,220 --> 00:36:32,320\nrepresentation, the composition\nof the problem\n\n658\n00:36:32,320 --> 00:36:35,660\ninto these two parts has\nhelped me a great deal.\n\n659\n00:36:35,660 --> 00:36:38,860\nSo let's take a very simple\ncase of this.\n\n660\n00:36:38,860 --> 00:36:40,330\nWhat was one of the problems?\n\n661\n00:36:40,330 --> 00:36:44,115\nLet's go back to this\ntransparency again.\n\n662\n00:36:44,115 --> 00:36:48,280\nAnd we see here, oh yes, there's\nhorrible things like\n\n663\n00:36:48,280 --> 00:36:53,190\nhere is the sum of an\nexpression and 0.\n\n664\n00:36:53,190 --> 00:36:55,590\nWell that's no reason to think\nof it as anything other than\n\n665\n00:36:55,590 --> 00:36:57,300\nthe expression itself.\n\n666\n00:36:57,300 --> 00:36:59,970\nWhy should the summation\noperation have\n\n667\n00:36:59,970 --> 00:37:03,450\nmade up this edition?\n\n668\n00:37:03,450 --> 00:37:05,550\nIt can be smarter than that.\n\n669\n00:37:05,550 --> 00:37:09,080\nOr here, for example, is\na multiplication of\n\n670\n00:37:09,080 --> 00:37:10,816\nsomething by 1.\n\n671\n00:37:10,816 --> 00:37:12,990\nIt's another thing like that.\n\n672\n00:37:12,990 --> 00:37:14,960\nOr here is a product of\nsomething with 0, which is\n\n673\n00:37:14,960 --> 00:37:17,800\ncertainly 0.\n\n674\n00:37:17,800 --> 00:37:21,430\nSo we won't have to make\nthis construction.\n\n675\n00:37:21,430 --> 00:37:23,800\nSo why don't we just do that?\n\n676\n00:37:23,800 --> 00:37:25,340\nWe need to change the way\nthe representation\n\n677\n00:37:25,340 --> 00:37:27,990\nworks, almost here.\n\n678\n00:37:27,990 --> 00:37:37,500\n\n\n679\n00:37:37,500 --> 00:37:42,060\nMake-sum to be.\n\n680\n00:37:42,060 --> 00:37:44,020\nWell, now it's not something\nso simple.\n\n681\n00:37:44,020 --> 00:37:48,500\nI'm not going to make a list\ncontaining the symbol plus and\n\n682\n00:37:48,500 --> 00:37:51,322\nthings unless I need to.\n\n683\n00:37:51,322 --> 00:37:52,630\nWell, what are the\npossibilities?\n\n684\n00:37:52,630 --> 00:37:57,220\n\n\n685\n00:37:57,220 --> 00:37:59,420\nI have some sort\nof cases here.\n\n686\n00:37:59,420 --> 00:38:09,160\nIf I have numbers, if\nanyone is a number--\n\n687\n00:38:09,160 --> 00:38:10,930\nand here's another primitive\nI've just introduced, it's\n\n688\n00:38:10,930 --> 00:38:15,230\npossible to tell whether\nsomething's number--\n\n689\n00:38:15,230 --> 00:38:23,090\nand if number A2, meaning\nthey're not symbolic\n\n690\n00:38:23,090 --> 00:38:26,280\nexpressions, then why not\ndo the addition now?\n\n691\n00:38:26,280 --> 00:38:29,540\nThe result is just a\nplus of A1 and A2.\n\n692\n00:38:29,540 --> 00:38:32,270\n\n\n693\n00:38:32,270 --> 00:38:34,000\nI'm not asking if these\nrepresent numbers.\n\n694\n00:38:34,000 --> 00:38:37,100\nOf course all of these symbols\nrepresent numbers.\n\n695\n00:38:37,100 --> 00:38:39,100\nI'm talking about whether\nthe one I've got is the\n\n696\n00:38:39,100 --> 00:38:43,420\nnumber 3 right now.\n\n697\n00:38:43,420 --> 00:38:59,070\nAnd, for example, supposing A1\nis a number, and it's equal to\n\n698\n00:38:59,070 --> 00:39:06,900\n0, well then the answer\nis just A2.\n\n699\n00:39:06,900 --> 00:39:10,698\nThere is no reason to\nmake anything up.\n\n700\n00:39:10,698 --> 00:39:27,630\nAnd if A2 is a number,\nand equal A20, then\n\n701\n00:39:27,630 --> 00:39:30,210\nthe result is A1.\n\n702\n00:39:30,210 --> 00:39:32,770\nAnd only if I can't figure out\nsomething better to do with\n\n703\n00:39:32,770 --> 00:39:41,160\nthis situation, well, I can\nstart a list. Otherwise I want\n\n704\n00:39:41,160 --> 00:39:45,790\nthe representation to be the\nlist containing the quoted\n\n705\n00:39:45,790 --> 00:39:51,850\nsymbol plus, and A1, and A2.\n\n706\n00:39:51,850 --> 00:39:58,720\n\n\n707\n00:39:58,720 --> 00:40:00,660\nAnd, of course, a very\nsimilar thing\n\n708\n00:40:00,660 --> 00:40:03,020\ncan be done for products.\n\n709\n00:40:03,020 --> 00:40:05,650\nAnd I think I'll avoid\nboring you with them.\n\n710\n00:40:05,650 --> 00:40:07,740\nI was going to write it\non the blackboard.\n\n711\n00:40:07,740 --> 00:40:09,080\nI don't think it's necessary.\n\n712\n00:40:09,080 --> 00:40:10,830\nYou know what to do.\n\n713\n00:40:10,830 --> 00:40:12,880\nIt's very simple.\n\n714\n00:40:12,880 --> 00:40:17,890\nBut now, let's just see the kind\nof results we get out of\n\n715\n00:40:17,890 --> 00:40:21,870\nchanging our program\nin this way.\n\n716\n00:40:21,870 --> 00:40:25,920\nWell, here's the derivatives\nafter having just changed the\n\n717\n00:40:25,920 --> 00:40:28,810\nconstructors for expressions.\n\n718\n00:40:28,810 --> 00:40:35,810\nThe same foo, aX square plus bX\nplus c, and what I get is\n\n719\n00:40:35,810 --> 00:40:40,265\nnothing more than the derivative\nof that is 2aX plus\n\n720\n00:40:40,265 --> 00:40:40,660\nB.\n\n721\n00:40:40,660 --> 00:40:42,670\nWell, it's not completely\nsimplified.\n\n722\n00:40:42,670 --> 00:40:45,170\nI would like to collect\ncommon terms and sums.\n\n723\n00:40:45,170 --> 00:40:47,180\nWell, that's more work.\n\n724\n00:40:47,180 --> 00:40:51,130\nAnd, of course, programs to do\nthis sort of thing are huge\n\n725\n00:40:51,130 --> 00:40:52,440\nand complicated.\n\n726\n00:40:52,440 --> 00:40:56,510\nAlgebraic simplification, it's\na very complicated mess.\n\n727\n00:40:56,510 --> 00:40:58,240\nThere's a very famous program\nyou may have heard of called\n\n728\n00:40:58,240 --> 00:41:02,750\nMaxima developed at MIT in the\npast, which is 5,000 pages of\n\n729\n00:41:02,750 --> 00:41:05,830\nLisp code, mostly the algebraic\nsimplification\n\n730\n00:41:05,830 --> 00:41:07,080\noperations.\n\n731\n00:41:07,080 --> 00:41:10,080\n\n\n732\n00:41:10,080 --> 00:41:12,210\nThere we see the derivative\nof foo.\n\n733\n00:41:12,210 --> 00:41:14,390\nIn fact, X is at something I\nwouldn't take off more than 1\n\n734\n00:41:14,390 --> 00:41:18,390\npoint for on an elementary\ncalculus class.\n\n735\n00:41:18,390 --> 00:41:20,960\nAnd the derivative of foo with\nrespect to a, well it's gone\n\n736\n00:41:20,960 --> 00:41:24,730\ndown to X times X, which\nisn't so bad.\n\n737\n00:41:24,730 --> 00:41:28,200\nAnd the derivative of foo with\nrespect to b is just X itself.\n\n738\n00:41:28,200 --> 00:41:30,730\nAnd the derivative of foo with\nrespect to c comes out 1.\n\n739\n00:41:30,730 --> 00:41:34,260\nSo I'm pretty pleased\nwith this.\n\n740\n00:41:34,260 --> 00:41:36,830\nWhat you've seen is, of\ncourse, a little bit\n\n741\n00:41:36,830 --> 00:41:41,020\ncontrived, carefully organized\nexample to show you how we can\n\n742\n00:41:41,020 --> 00:41:43,610\nmanipulate algebraic\nexpressions, how we do that\n\n743\n00:41:43,610 --> 00:41:46,890\nabstractly in terms of abstract\nsyntax rather than\n\n744\n00:41:46,890 --> 00:41:53,910\nconcrete syntax and how we can\nuse the abstraction to control\n\n745\n00:41:53,910 --> 00:41:57,850\nwhat goes on in building\nthese expressions.\n\n746\n00:41:57,850 --> 00:42:00,910\nBut the real story isn't just\nsuch a simple thing as that.\n\n747\n00:42:00,910 --> 00:42:03,890\nThe real story is, in fact, that\nI'm manipulating these\n\n748\n00:42:03,890 --> 00:42:04,450\nexpressions.\n\n749\n00:42:04,450 --> 00:42:06,860\nAnd the expressions are\nthe same expressions--\n\n750\n00:42:06,860 --> 00:42:08,150\ngoing back to the slide--\n\n751\n00:42:08,150 --> 00:42:12,110\nas the ones that are\nLisp expressions.\n\n752\n00:42:12,110 --> 00:42:13,890\nThere's a pun here.\n\n753\n00:42:13,890 --> 00:42:17,020\nI've chosen my representation\nto be the same as the\n\n754\n00:42:17,020 --> 00:42:22,830\nrepresentation in my language\nof similar things.\n\n755\n00:42:22,830 --> 00:42:26,990\nBy doing so, I've invoked\na necessity.\n\n756\n00:42:26,990 --> 00:42:30,890\nI created the necessity to have\nthings like quotation\n\n757\n00:42:30,890 --> 00:42:35,690\nbecause of the fact that my\nlanguage is capable of writing\n\n758\n00:42:35,690 --> 00:42:39,820\nexpressions that talk about\nexpressions of the language.\n\n759\n00:42:39,820 --> 00:42:42,420\nI need to have something that\nsays, this is an expression\n\n760\n00:42:42,420 --> 00:42:45,320\nI'm talking about rather than\nthis expression is talking\n\n761\n00:42:45,320 --> 00:42:48,400\nabout something, and I want\nto talk about that.\n\n762\n00:42:48,400 --> 00:42:51,290\n\n\n763\n00:42:51,290 --> 00:42:54,420\nSo quotation stops and says,\nI'm talking about this\n\n764\n00:42:54,420 --> 00:42:55,670\nexpression itself.\n\n765\n00:42:55,670 --> 00:42:58,140\n\n\n766\n00:42:58,140 --> 00:43:03,030\nNow, given that power, if I can\nmanipulate expressions of\n\n767\n00:43:03,030 --> 00:43:07,370\nthe language, I can begin to\nbuild even much more powerful\n\n768\n00:43:07,370 --> 00:43:09,860\nlayers upon layers\nof languages.\n\n769\n00:43:09,860 --> 00:43:12,370\nBecause I can write languages\nthat not only are embedded in\n\n770\n00:43:12,370 --> 00:43:16,730\nLisp or whatever language you\nstart with, but languages that\n\n771\n00:43:16,730 --> 00:43:20,400\nare completely different, that\nare just, if we say,\n\n772\n00:43:20,400 --> 00:43:23,280\ninterpreted in Lisp or\nsomething like that.\n\n773\n00:43:23,280 --> 00:43:26,232\nWe'll get to understand those\nwords more in the future.\n\n774\n00:43:26,232 --> 00:43:30,150\nBut right now I just want to\nleave you with the fact that\n\n775\n00:43:30,150 --> 00:43:36,160\nwe've hit a line which gives\nus tremendous power.\n\n776\n00:43:36,160 --> 00:43:37,900\nAnd this point we've bought\na sledgehammer.\n\n777\n00:43:37,900 --> 00:43:42,250\nWe have to be careful to what\nflies when we apply it.\n\n778\n00:43:42,250 --> 00:43:42,570\nThank you.\n\n779\n00:43:42,570 --> 00:43:43,820\n[MUSIC PLAYING]\n\n780\n00:43:43,820 --> 00:44:03,796\n\n"
  },
  {
    "path": "SrtEN/lec4a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:24,460\n\n\n1\n00:00:24,460 --> 00:00:28,270\nPROFESSOR: Well, yesterday we\nlearned a bit about symbolic\n\n2\n00:00:28,270 --> 00:00:35,140\nmanipulation, and we wrote a\nrather stylized program to\n\n3\n00:00:35,140 --> 00:00:40,620\nimplement a pile of calculus\nrule from the calculus book.\n\n4\n00:00:40,620 --> 00:00:47,790\nHere on the transparencies, we\nsee a bunch of calculus rules\n\n5\n00:00:47,790 --> 00:00:49,470\nfrom such a book.\n\n6\n00:00:49,470 --> 00:00:53,030\nAnd, of course, what we did is\nsort of translate these rules\n\n7\n00:00:53,030 --> 00:00:56,040\ninto the language\nof the computer.\n\n8\n00:00:56,040 --> 00:00:59,340\nBut, of course, that's a\nsort of funny strategy.\n\n9\n00:00:59,340 --> 00:01:03,570\nWhy should we have to translate\nthese rules into the\n\n10\n00:01:03,570 --> 00:01:04,989\nlanguage of the computer?\n\n11\n00:01:04,989 --> 00:01:07,320\nAnd what do I really\nmean by that?\n\n12\n00:01:07,320 --> 00:01:08,170\nThese are--the program we wrote\n\n13\n00:01:08,170 --> 00:01:11,240\nyesterday was very stylized.\n\n14\n00:01:11,240 --> 00:01:15,210\nIt was a conditional, a dispatch\non the type of the\n\n15\n00:01:15,210 --> 00:01:19,660\nexpression as observed\nby the rules.\n\n16\n00:01:19,660 --> 00:01:23,450\nWhat we see here are rules that\nsay if the object being\n\n17\n00:01:23,450 --> 00:01:26,850\nthe derivative is being taken\nof, if that expression is a\n\n18\n00:01:26,850 --> 00:01:29,350\nconstant, then do one thing.\n\n19\n00:01:29,350 --> 00:01:31,590\nIf it's a variable,\ndo another thing.\n\n20\n00:01:31,590 --> 00:01:34,040\nIf it's a product of a constant\ntimes a variable, do\n\n21\n00:01:34,040 --> 00:01:36,220\nsomething and so on.\n\n22\n00:01:36,220 --> 00:01:38,630\nThere's sort of a dispatch\nthere on a type.\n\n23\n00:01:38,630 --> 00:01:41,750\n\n\n24\n00:01:41,750 --> 00:01:44,260\nWell, since it has such a\nstylized behavior and\n\n25\n00:01:44,260 --> 00:01:48,110\nstructure, is there some other\nway of writing this program\n\n26\n00:01:48,110 --> 00:01:50,401\nthat's more clear?\n\n27\n00:01:50,401 --> 00:01:52,280\nWell, what's a rule,\nfirst of all?\n\n28\n00:01:52,280 --> 00:01:53,530\nWhat are these rules?\n\n29\n00:01:53,530 --> 00:01:55,960\n\n\n30\n00:01:55,960 --> 00:01:57,130\nLet's think about that.\n\n31\n00:01:57,130 --> 00:01:58,910\nRules have parts.\n\n32\n00:01:58,910 --> 00:02:04,400\nIf you look at these rules in\ndetail, what you see, for\n\n33\n00:02:04,400 --> 00:02:08,750\nexample, is the rule has\na left-hand side and a\n\n34\n00:02:08,750 --> 00:02:10,940\nright-hand side.\n\n35\n00:02:10,940 --> 00:02:13,220\nEach of these rules has a\nleft-hand side and the\n\n36\n00:02:13,220 --> 00:02:14,960\nright-hand side.\n\n37\n00:02:14,960 --> 00:02:18,640\nThe left-hand side is somehow\ncompared with the expression\n\n38\n00:02:18,640 --> 00:02:21,250\nyou're trying to take\nthe derivative of.\n\n39\n00:02:21,250 --> 00:02:24,440\nThe right-hand side is the\nreplacement for that\n\n40\n00:02:24,440 --> 00:02:25,690\nexpression.\n\n41\n00:02:25,690 --> 00:02:28,410\n\n\n42\n00:02:28,410 --> 00:02:33,070\nSo all rules on this page\nare something like this.\n\n43\n00:02:33,070 --> 00:02:35,900\n\n\n44\n00:02:35,900 --> 00:02:45,990\nI have patterns, and somehow,\nI have to produce, given a\n\n45\n00:02:45,990 --> 00:02:47,845\npattern, a skeleton.\n\n46\n00:02:47,845 --> 00:02:51,700\n\n\n47\n00:02:51,700 --> 00:02:52,950\nThis is a rule.\n\n48\n00:02:52,950 --> 00:02:55,420\n\n\n49\n00:02:55,420 --> 00:02:58,650\nA pattern is something that\nmatches, and a skeleton is\n\n50\n00:02:58,650 --> 00:03:02,470\nsomething you substitute into\nin order to get a new\n\n51\n00:03:02,470 --> 00:03:03,720\nexpression.\n\n52\n00:03:03,720 --> 00:03:06,410\n\n\n53\n00:03:06,410 --> 00:03:12,960\nSo what that means is that the\npattern is matched against the\n\n54\n00:03:12,960 --> 00:03:15,910\nexpression, which is the\nsource expression.\n\n55\n00:03:15,910 --> 00:03:23,730\n\n\n56\n00:03:23,730 --> 00:03:26,620\nAnd the result of the\napplication of the rule is to\n\n57\n00:03:26,620 --> 00:03:38,070\nproduce a new expression, which\nI'll call a target, by\n\n58\n00:03:38,070 --> 00:03:41,620\ninstantiation of a skeleton.\n\n59\n00:03:41,620 --> 00:03:42,870\nThat's called instantiation.\n\n60\n00:03:42,870 --> 00:03:50,580\n\n\n61\n00:03:50,580 --> 00:03:52,530\nSo that is the process by which\n\n62\n00:03:52,530 --> 00:03:55,780\nthese rules are described.\n\n63\n00:03:55,780 --> 00:04:02,680\nWhat I'd like to do today is\nbuild a language and a means\n\n64\n00:04:02,680 --> 00:04:04,950\nof interpreting that language,\na means of executing that\n\n65\n00:04:04,950 --> 00:04:07,770\nlanguage, where that language\nallows us to directly express\n\n66\n00:04:07,770 --> 00:04:10,550\nthese rules.\n\n67\n00:04:10,550 --> 00:04:14,150\nAnd what we're going to do is\ninstead of bringing the rules\n\n68\n00:04:14,150 --> 00:04:16,920\nto the level of the computer by\nwriting a program that is\n\n69\n00:04:16,920 --> 00:04:20,279\nthose rules in the computer's\nlanguage--\n\n70\n00:04:20,279 --> 00:04:22,170\nat the moment, in a Lisp--\n\n71\n00:04:22,170 --> 00:04:25,740\nwe're going to bring the\ncomputer to the level of us by\n\n72\n00:04:25,740 --> 00:04:28,400\nwriting a way by which the\ncomputer can understand rules\n\n73\n00:04:28,400 --> 00:04:30,670\nof this sort.\n\n74\n00:04:30,670 --> 00:04:35,210\nThis is slightly emphasizing the\nidea that we had last time\n\n75\n00:04:35,210 --> 00:04:37,560\nthat we're trying to make\na solution to a class of\n\n76\n00:04:37,560 --> 00:04:39,630\nproblems rather than\na particular one.\n\n77\n00:04:39,630 --> 00:04:45,740\nThe problem is if I want to\nwrite rules for a different\n\n78\n00:04:45,740 --> 00:04:49,990\npiece of mathematics, say,\nto simple algebraic\n\n79\n00:04:49,990 --> 00:04:54,050\nsimplification or something like\nthat, or manipulation of\n\n80\n00:04:54,050 --> 00:04:57,160\ntrigonometric functions,\nI would have to write a\n\n81\n00:04:57,160 --> 00:05:01,130\ndifferent program in using\nyesterday's method.\n\n82\n00:05:01,130 --> 00:05:03,550\nWhereas I would like to\nencapsulate all of the things\n\n83\n00:05:03,550 --> 00:05:06,770\nthat are common to both of those\nprograms, meaning the\n\n84\n00:05:06,770 --> 00:05:09,870\nidea of matching, instantiation,\nthe control\n\n85\n00:05:09,870 --> 00:05:12,090\nstructure, which turns out to be\nvery complicated for such a\n\n86\n00:05:12,090 --> 00:05:17,420\nthing, I'd like to encapsulate\nthat separately from the rules\n\n87\n00:05:17,420 --> 00:05:20,010\nthemselves.\n\n88\n00:05:20,010 --> 00:05:22,730\nSo let's look at, first of\nall, a representation.\n\n89\n00:05:22,730 --> 00:05:24,670\nI'd like to use the\noverhead here.\n\n90\n00:05:24,670 --> 00:05:25,975\nI'd like-- there it is.\n\n91\n00:05:25,975 --> 00:05:29,440\nI'd like to look at a\nrepresentation of the rules of\n\n92\n00:05:29,440 --> 00:05:36,010\ncalculus for derivatives in a\nsort of simple language that\n\n93\n00:05:36,010 --> 00:05:38,140\nI'm writing right here.\n\n94\n00:05:38,140 --> 00:05:41,420\nNow, I'm going to avoid--I'm\ngoing to avoid\n\n95\n00:05:41,420 --> 00:05:44,250\nworrying about syntax.\n\n96\n00:05:44,250 --> 00:05:48,340\nWe can easily pretty this, and\nI'm not interested in making--\n\n97\n00:05:48,340 --> 00:05:49,230\nthis is indeed ugly.\n\n98\n00:05:49,230 --> 00:05:54,810\nThis doesn't look like the\nbeautiful text set dx by dt or\n\n99\n00:05:54,810 --> 00:05:56,730\nsomething that I'd\nlike to write,\n\n100\n00:05:56,730 --> 00:05:58,710\nbut that's not essential.\n\n101\n00:05:58,710 --> 00:06:00,480\nThat's sort of an accidental\nphenomenon.\n\n102\n00:06:00,480 --> 00:06:03,220\nHere, we're just worrying\nabout the fact that the\n\n103\n00:06:03,220 --> 00:06:07,060\nstructure of the rules is that\nthere is a left-hand side\n\n104\n00:06:07,060 --> 00:06:10,510\nhere, represents the thing I\nwant to match against the\n\n105\n00:06:10,510 --> 00:06:11,720\nderivative expression.\n\n106\n00:06:11,720 --> 00:06:14,140\nThis is the representation\nI'm going to say for the\n\n107\n00:06:14,140 --> 00:06:18,980\nderivative of a constant, which\nwe will call c with\n\n108\n00:06:18,980 --> 00:06:23,730\nrespect to the variable we will\ncall v. And what we will\n\n109\n00:06:23,730 --> 00:06:26,010\nget on the right-hand\nside is 0.\n\n110\n00:06:26,010 --> 00:06:29,620\nSo this represents a rule.\n\n111\n00:06:29,620 --> 00:06:32,980\nThe next rule will be the\nderivative of a variable,\n\n112\n00:06:32,980 --> 00:06:36,010\nwhich we will call v with\nrespect to the same variable\n\n113\n00:06:36,010 --> 00:06:38,560\nv, and we get a 1.\n\n114\n00:06:38,560 --> 00:06:41,360\nHowever, if we have the\nderivative of a variable\n\n115\n00:06:41,360 --> 00:06:44,490\ncalled u with respect to\na different variables\n\n116\n00:06:44,490 --> 00:06:47,790\nv, we will get 0.\n\n117\n00:06:47,790 --> 00:06:50,880\nI just want you look at these\nrules a little bit and see how\n\n118\n00:06:50,880 --> 00:06:52,750\nthey fit together.\n\n119\n00:06:52,750 --> 00:06:56,310\nFor example, over here, we're\ngoing to have the derivative\n\n120\n00:06:56,310 --> 00:07:00,360\nof the sum of an expression\ncalled x1 and an\n\n121\n00:07:00,360 --> 00:07:01,790\nexpression called x2.\n\n122\n00:07:01,790 --> 00:07:04,960\nThese things that begin with\nquestion marks are called\n\n123\n00:07:04,960 --> 00:07:08,910\npattern variables in the\nlanguage that we're inventing,\n\n124\n00:07:08,910 --> 00:07:12,820\nand you see we're just making\nit up, so pattern variables\n\n125\n00:07:12,820 --> 00:07:14,960\nfor matching.\n\n126\n00:07:14,960 --> 00:07:16,050\nAnd so in this--\n\n127\n00:07:16,050 --> 00:07:19,140\nhere we have the derivative of\nthe sum of the expression\n\n128\n00:07:19,140 --> 00:07:20,380\nwhich we will call x1.\n\n129\n00:07:20,380 --> 00:07:23,150\nAnd the expression we will call\nx2 with respect to the\n\n130\n00:07:23,150 --> 00:07:26,500\nvariable we call v will be--\nhere is the right-hand side:\n\n131\n00:07:26,500 --> 00:07:29,700\nthe sum of the derivative of\nthat expression x1 with\n\n132\n00:07:29,700 --> 00:07:33,910\nrespect to v-- the right-hand\nside is the skeleton--\n\n133\n00:07:33,910 --> 00:07:38,950\nand the derivative of x2 with\nrespect to v. Colons here will\n\n134\n00:07:38,950 --> 00:07:42,170\nstand for substitution\nobjects.\n\n135\n00:07:42,170 --> 00:07:44,690\n\n\n136\n00:07:44,690 --> 00:07:48,480\nThey're--we'll call them\nskeleton evaluations.\n\n137\n00:07:48,480 --> 00:07:52,420\nSo let me put up here on the\nblackboard for a second some\n\n138\n00:07:52,420 --> 00:07:54,380\nsyntax so we'll know\nwhat's going on\n\n139\n00:07:54,380 --> 00:07:56,620\nfor this rule language.\n\n140\n00:07:56,620 --> 00:07:58,730\nFirst of all, we're going to\nhave to worry about the\n\n141\n00:07:58,730 --> 00:07:59,980\npattern matching.\n\n142\n00:07:59,980 --> 00:08:05,790\n\n\n143\n00:08:05,790 --> 00:08:11,950\nWe're going to have things like\na symbol like foo matches\n\n144\n00:08:11,950 --> 00:08:13,200\nexactly itself.\n\n145\n00:08:13,200 --> 00:08:23,170\n\n\n146\n00:08:23,170 --> 00:08:35,919\nThe expression f of a and b will\nbe used to match any list\n\n147\n00:08:35,919 --> 00:08:51,130\nwhose first element is f, whose\nsecond element is a, and\n\n148\n00:08:51,130 --> 00:08:58,550\nwhose third element is b.\n\n149\n00:08:58,550 --> 00:09:03,200\nAlso, another thing we might\nhave in a pattern is that--\n\n150\n00:09:03,200 --> 00:09:08,150\na question mark with some\nvariable like x.\n\n151\n00:09:08,150 --> 00:09:17,965\nAnd what that means, it says\nmatches anything, which we\n\n152\n00:09:17,965 --> 00:09:19,215\nwill call x.\n\n153\n00:09:19,215 --> 00:09:25,610\n\n\n154\n00:09:25,610 --> 00:09:30,922\nQuestion mark c x will\nmatch only constants.\n\n155\n00:09:30,922 --> 00:09:41,140\nSo this is something which\nmatches a constant colon x.\n\n156\n00:09:41,140 --> 00:09:44,620\n\n\n157\n00:09:44,620 --> 00:09:55,920\nAnd question mark v x will\nmatch a variable,\n\n158\n00:09:55,920 --> 00:09:57,170\nwhich we call x.\n\n159\n00:09:57,170 --> 00:10:01,690\n\n\n160\n00:10:01,690 --> 00:10:04,140\nThis is sort of the language\nwe're making up now.\n\n161\n00:10:04,140 --> 00:10:07,240\nIf I match two things against\neach other, then they are\n\n162\n00:10:07,240 --> 00:10:10,200\ncompared element by element.\n\n163\n00:10:10,200 --> 00:10:13,630\nBut elements in the pattern may\ncontain these syntactic\n\n164\n00:10:13,630 --> 00:10:19,310\nvariables, pattern variables,\nwhich will be used to match\n\n165\n00:10:19,310 --> 00:10:22,160\narbitrary objects.\n\n166\n00:10:22,160 --> 00:10:28,480\nAnd we'll get that object as the\nvalue in the name x here,\n\n167\n00:10:28,480 --> 00:10:31,030\nfor example.\n\n168\n00:10:31,030 --> 00:10:39,290\nNow, when we make skeletons\nfor instantiation.\n\n169\n00:10:39,290 --> 00:10:42,320\nWell, then we have\nthings like this.\n\n170\n00:10:42,320 --> 00:10:46,160\nfoo, a symbol, instantiates\nto itself.\n\n171\n00:10:46,160 --> 00:10:55,020\n\n\n172\n00:10:55,020 --> 00:10:59,630\nSomething which is a list\nlike f of a and b,\n\n173\n00:10:59,630 --> 00:11:06,350\ninstantiates to--\n\n174\n00:11:06,350 --> 00:11:14,270\nwell, f instantiates to a\n3-list, a list of three\n\n175\n00:11:14,270 --> 00:11:27,420\nelements, okay, which are the\nresults of instantiating each\n\n176\n00:11:27,420 --> 00:11:33,320\nof f, a, and b.\n\n177\n00:11:33,320 --> 00:11:36,310\n\n\n178\n00:11:36,310 --> 00:11:53,470\nAnd x well--we instantiate to\nthe value of x as in the\n\n179\n00:11:53,470 --> 00:11:54,720\nmatched pattern.\n\n180\n00:11:54,720 --> 00:12:02,960\n\n\n181\n00:12:02,960 --> 00:12:08,630\nSo going back to the overhead\nhere, we see--we see that all\n\n182\n00:12:08,630 --> 00:12:14,040\nof those kinds of objects, we\nsee here a pattern variable\n\n183\n00:12:14,040 --> 00:12:18,180\nwhich matches a constant, a\npattern variable which matches\n\n184\n00:12:18,180 --> 00:12:22,660\na variable, a pattern variable\nwhich will match anything.\n\n185\n00:12:22,660 --> 00:12:25,810\nAnd if we have two instances of\nthe same name, like this is\n\n186\n00:12:25,810 --> 00:12:29,840\nthe derivative of the expression\nwhich is a variable\n\n187\n00:12:29,840 --> 00:12:34,510\nonly whose name will be v with\nrespect to some arbitrary\n\n188\n00:12:34,510 --> 00:12:38,560\nexpression which we will call v,\nsince this v appears twice,\n\n189\n00:12:38,560 --> 00:12:42,770\nwe're going to want that to mean\nthey have to be the same.\n\n190\n00:12:42,770 --> 00:12:45,630\nThe only consistent match is\nthat those are the same.\n\n191\n00:12:45,630 --> 00:12:48,170\nSo here, we're making\nup a language.\n\n192\n00:12:48,170 --> 00:12:50,440\nAnd in fact, that's a very\nnice thing to be doing.\n\n193\n00:12:50,440 --> 00:12:52,555\nIt's so much fun to make\nup a language.\n\n194\n00:12:52,555 --> 00:12:54,320\nAnd you do this all the time.\n\n195\n00:12:54,320 --> 00:12:57,390\nAnd the really most powerful\ndesign things you ever do are\n\n196\n00:12:57,390 --> 00:13:02,050\nsort of making up a language to\nsolve problems like this.\n\n197\n00:13:02,050 --> 00:13:05,780\nNow, here we go back here and\nlook at some of these rules.\n\n198\n00:13:05,780 --> 00:13:07,070\nWell, there's a whole\nset of them.\n\n199\n00:13:07,070 --> 00:13:10,540\nI mean, there's one for\naddition and one for\n\n200\n00:13:10,540 --> 00:13:12,390\nmultiplication, just\nlike we had before.\n\n201\n00:13:12,390 --> 00:13:16,900\nThe derivative of the product of\nx1 and x2 with respect to v\n\n202\n00:13:16,900 --> 00:13:22,660\nis the sum of the product of x1\nand the derivative x2 with\n\n203\n00:13:22,660 --> 00:13:24,750\nrespect to v and the\nproduct of the\n\n204\n00:13:24,750 --> 00:13:27,200\nderivative of x1 and x2.\n\n205\n00:13:27,200 --> 00:13:29,180\nAnd here we have\nexponentiation.\n\n206\n00:13:29,180 --> 00:13:30,880\nAnd, of course, we run off\nthe end down here.\n\n207\n00:13:30,880 --> 00:13:32,540\nWe get as many as we like.\n\n208\n00:13:32,540 --> 00:13:36,270\nBut the whole thing over here,\nI'm giving this--this list of\n\n209\n00:13:36,270 --> 00:13:40,910\nrules the name \"derivative\nrules.\"\n\n210\n00:13:40,910 --> 00:13:45,240\nWhat would we do with such\na thing once we have it?\n\n211\n00:13:45,240 --> 00:13:49,080\nWell, one of the nicest ideas,\nfirst of all, is I'm going to\n\n212\n00:13:49,080 --> 00:13:52,230\nwrite for you, and we're going\nto play with it all day.\n\n213\n00:13:52,230 --> 00:13:56,680\nWhat I'm going to write for\nyou is a program called\n\n214\n00:13:56,680 --> 00:14:00,150\nsimplifier, the general-purpose\nsimplifier.\n\n215\n00:14:00,150 --> 00:14:09,150\nAnd we're going to say something\nlike define dsimp to\n\n216\n00:14:09,150 --> 00:14:17,260\nbe a simplifier of the\nderivative rules.\n\n217\n00:14:17,260 --> 00:14:23,740\n\n\n218\n00:14:23,740 --> 00:14:26,390\nAnd what simplifier is going\nto do is, given a set of\n\n219\n00:14:26,390 --> 00:14:29,670\nrules, it will produce for\nme a procedure which will\n\n220\n00:14:29,670 --> 00:14:33,200\nsimplify expressions containing\nthe things that are\n\n221\n00:14:33,200 --> 00:14:34,680\nreferred to by these rules.\n\n222\n00:14:34,680 --> 00:14:37,360\n\n\n223\n00:14:37,360 --> 00:14:42,110\nSo here will be a procedure\nconstructed for your purposes\n\n224\n00:14:42,110 --> 00:14:45,150\nto simplify things with\nderivatives in them such that,\n\n225\n00:14:45,150 --> 00:14:49,050\nafter that, if we're typing at\nsome list system, and we get a\n\n226\n00:14:49,050 --> 00:14:58,030\nprompt, and we say dsimp, for\nexample, of the derivative of\n\n227\n00:14:58,030 --> 00:15:03,885\nthe sum of x and y with\nrespect to x--\n\n228\n00:15:03,885 --> 00:15:06,990\n\n\n229\n00:15:06,990 --> 00:15:08,740\nnote the quote here because\nI'm talking about the\n\n230\n00:15:08,740 --> 00:15:10,660\nexpression which is\nthe derivative--\n\n231\n00:15:10,660 --> 00:15:13,310\n\n\n232\n00:15:13,310 --> 00:15:19,970\nthen I will get back as\na result plus 1 0.\n\n233\n00:15:19,970 --> 00:15:23,760\nBecause the derivative of x plus\ny is the derivative of x\n\n234\n00:15:23,760 --> 00:15:24,490\nplus derivative y.\n\n235\n00:15:24,490 --> 00:15:26,300\nThe derivative of x with\nrespect to x is 1.\n\n236\n00:15:26,300 --> 00:15:29,260\nThe derivative of y with\nrespect to x is 0.\n\n237\n00:15:29,260 --> 00:15:31,170\nIt's not what we're\ngoing to get.\n\n238\n00:15:31,170 --> 00:15:33,280\nI haven't put any simplification\nat that level--\n\n239\n00:15:33,280 --> 00:15:34,440\nalgebraic simplification--\n\n240\n00:15:34,440 --> 00:15:36,010\nyet.\n\n241\n00:15:36,010 --> 00:15:39,702\nOf course, once we have such a\nthing, then we can--then we\n\n242\n00:15:39,702 --> 00:15:42,340\ncan look at other rules.\n\n243\n00:15:42,340 --> 00:15:49,310\nSo, for example, we can, if\nwe go to the slide, OK?\n\n244\n00:15:49,310 --> 00:15:52,480\nHere, for example, are other\nrules that we might have,\n\n245\n00:15:52,480 --> 00:15:56,780\nalgebraic manipulation rules,\nones that would be used for\n\n246\n00:15:56,780 --> 00:15:58,960\nsimplifying algebraic\nexpressions.\n\n247\n00:15:58,960 --> 00:16:04,470\nFor example, just looking at\nsome of these, the left-hand\n\n248\n00:16:04,470 --> 00:16:08,220\nside says any operator applied\nto a constant e1 and a\n\n249\n00:16:08,220 --> 00:16:12,310\nconstant e2 is the result of\nevaluating that operator on\n\n250\n00:16:12,310 --> 00:16:15,850\nthe constants e1 and e2.\n\n251\n00:16:15,850 --> 00:16:20,660\nOr an operator, applied to e1,\nany expression e1 and a\n\n252\n00:16:20,660 --> 00:16:24,520\nconstant e2, is going to move\nthe constant forward.\n\n253\n00:16:24,520 --> 00:16:25,980\nSo that'll turn into\nthe operator with\n\n254\n00:16:25,980 --> 00:16:28,770\ne2 followed by e1.\n\n255\n00:16:28,770 --> 00:16:30,200\nWhy I did that, I don't know.\n\n256\n00:16:30,200 --> 00:16:33,560\nIt wouldn't work if I had\ndivision, for example.\n\n257\n00:16:33,560 --> 00:16:36,610\nSo there's a bug in the\nrules, if you like.\n\n258\n00:16:36,610 --> 00:16:42,120\nSo the sum of 0 and e is e.\n\n259\n00:16:42,120 --> 00:16:46,110\nThe product of 1 and any\nexpression e is e.\n\n260\n00:16:46,110 --> 00:16:49,520\nThe product of 0 and any\nexpression e is 0.\n\n261\n00:16:49,520 --> 00:16:51,130\nJust looking at some more of\nthese rules, we could have\n\n262\n00:16:51,130 --> 00:16:53,670\narbitrarily complicated ones.\n\n263\n00:16:53,670 --> 00:16:59,050\nWe could have things like the\nproduct of the constant e1 and\n\n264\n00:16:59,050 --> 00:17:04,230\nany constant e2 with e3 is the\nresult of multiplying the\n\n265\n00:17:04,230 --> 00:17:10,310\nresult of--multiplying now the\nconstants e1 and e2 together\n\n266\n00:17:10,310 --> 00:17:13,319\nand putting e3 there.\n\n267\n00:17:13,319 --> 00:17:16,760\nSo it says combine the constants\nthat I had, which\n\n268\n00:17:16,760 --> 00:17:20,480\nwas if I had a product of e1 and\ne2 and e3 just multiply--I\n\n269\n00:17:20,480 --> 00:17:23,800\nmean and e1 and e2 are both\nconstants, multiply them.\n\n270\n00:17:23,800 --> 00:17:25,690\nAnd you can make up the\nrules as you like.\n\n271\n00:17:25,690 --> 00:17:27,619\nThere are lots of them here.\n\n272\n00:17:27,619 --> 00:17:31,300\nThere are things as complicated,\nfor example, as--\n\n273\n00:17:31,300 --> 00:17:33,910\noh, I suppose down here some\ndistributive law, you see.\n\n274\n00:17:33,910 --> 00:17:39,150\nThe product of any object c and\nthe sum of d and e gives\n\n275\n00:17:39,150 --> 00:17:42,340\nthe result as the same as the\nsum of the product of c and d\n\n276\n00:17:42,340 --> 00:17:45,320\nand the product of c and e.\n\n277\n00:17:45,320 --> 00:17:47,770\nNow, what exactly these\nrules are doesn't very\n\n278\n00:17:47,770 --> 00:17:49,220\nmuch interest me.\n\n279\n00:17:49,220 --> 00:17:51,970\nWe're going to be writing the\nlanguage that will allow us to\n\n280\n00:17:51,970 --> 00:17:56,480\ninterpret these rules so that\nwe can, in fact, make up\n\n281\n00:17:56,480 --> 00:17:59,430\nwhatever rules we like, another\nwhole language of\n\n282\n00:17:59,430 --> 00:18:00,680\nprogramming.\n\n283\n00:18:00,680 --> 00:18:03,350\n\n\n284\n00:18:03,350 --> 00:18:05,130\nWell, let's see.\n\n285\n00:18:05,130 --> 00:18:07,520\nI haven't told you how we're\ngoing to do this.\n\n286\n00:18:07,520 --> 00:18:10,760\nAnd, of course, for a while,\nwe're going to work on that.\n\n287\n00:18:10,760 --> 00:18:13,980\nBut there's a real question of\nwhat is--what am I going to do\n\n288\n00:18:13,980 --> 00:18:16,940\nat all at a large scale?\n\n289\n00:18:16,940 --> 00:18:18,930\nHow do these rules work?\n\n290\n00:18:18,930 --> 00:18:21,830\nHow is the simplifier program\ngoing to manipulate these\n\n291\n00:18:21,830 --> 00:18:26,190\nrules with your expression to\nproduce a reasonable answer?\n\n292\n00:18:26,190 --> 00:18:28,410\nWell, first, I'd like to think\nabout these rules as being\n\n293\n00:18:28,410 --> 00:18:32,100\nsome sort of deck of them.\n\n294\n00:18:32,100 --> 00:18:42,030\nSo here I have a whole bunch\nof rules, right?\n\n295\n00:18:42,030 --> 00:18:43,660\nEach rule--\n\n296\n00:18:43,660 --> 00:18:46,930\nhere's a rule--\n\n297\n00:18:46,930 --> 00:18:49,720\nhas a pattern and a skeleton.\n\n298\n00:18:49,720 --> 00:18:53,410\nI'm trying to make up a control\nstructure for this.\n\n299\n00:18:53,410 --> 00:19:02,720\nNow, what I have is a matcher,\nand I have something which is\n\n300\n00:19:02,720 --> 00:19:03,970\nan instantiater.\n\n301\n00:19:03,970 --> 00:19:09,120\n\n\n302\n00:19:09,120 --> 00:19:13,950\nAnd I'm going to pass from the\nmatcher to the instantiater\n\n303\n00:19:13,950 --> 00:19:18,200\nsome set of meaning for the\npattern variables, a\n\n304\n00:19:18,200 --> 00:19:20,560\ndictionary, I'll call it.\n\n305\n00:19:20,560 --> 00:19:26,740\nA dictionary, which will say\nx was matched against the\n\n306\n00:19:26,740 --> 00:19:30,410\nfollowing subexpression and y\nwas matched against another\n\n307\n00:19:30,410 --> 00:19:32,170\nfollowing subexpression.\n\n308\n00:19:32,170 --> 00:19:35,040\nAnd from the instantiater, I\nwill be making expressions,\n\n309\n00:19:35,040 --> 00:19:37,130\nand they will go into\nthe matcher.\n\n310\n00:19:37,130 --> 00:19:38,380\nThey will be expressions.\n\n311\n00:19:38,380 --> 00:19:44,960\n\n\n312\n00:19:44,960 --> 00:19:49,190\nAnd the patterns of the rules\nwill be fed into the matcher,\n\n313\n00:19:49,190 --> 00:19:53,600\nand the skeletons from the same\nrule will be fed into the\n\n314\n00:19:53,600 --> 00:19:55,190\ninstantiater.\n\n315\n00:19:55,190 --> 00:19:57,920\nNow, this is a little\ncomplicated because when you\n\n316\n00:19:57,920 --> 00:20:00,965\nhave something like an algebraic\nexpression, where\n\n317\n00:20:00,965 --> 00:20:02,290\nsometh--the rules are intended\nto be able to allow you to\n\n318\n00:20:02,290 --> 00:20:04,290\nsubstitute equal for equal.\n\n319\n00:20:04,290 --> 00:20:06,860\nThese are equal transformation\nrules.\n\n320\n00:20:06,860 --> 00:20:08,710\nSo all subexpressions\nof the expression\n\n321\n00:20:08,710 --> 00:20:11,090\nshould be looked at.\n\n322\n00:20:11,090 --> 00:20:14,440\nYou give it an expression,\nthis thing, and the rules\n\n323\n00:20:14,440 --> 00:20:16,010\nshould be cycled around.\n\n324\n00:20:16,010 --> 00:20:18,540\nFirst of all, for every\nsubexpression of the\n\n325\n00:20:18,540 --> 00:20:21,340\nexpression you feed in, all\nof the rules must be\n\n326\n00:20:21,340 --> 00:20:24,390\ntried and looked at.\n\n327\n00:20:24,390 --> 00:20:27,200\nAnd if any rule matches, then\nthis process occurs.\n\n328\n00:20:27,200 --> 00:20:30,620\nThe dictionary--the dictionary\nis to have some values in it.\n\n329\n00:20:30,620 --> 00:20:34,800\nThe instantiater makes a new\nexpression, which is basically\n\n330\n00:20:34,800 --> 00:20:38,000\nreplaces that part of the\nexpression that was matched in\n\n331\n00:20:38,000 --> 00:20:40,800\nyour original expression.\n\n332\n00:20:40,800 --> 00:20:44,700\nAnd then, then, of course, we're\ngoing to recheck that,\n\n333\n00:20:44,700 --> 00:20:47,170\ngoing to go around these rules\nagain, seeing if that could be\n\n334\n00:20:47,170 --> 00:20:49,520\nsimplified further.\n\n335\n00:20:49,520 --> 00:20:50,960\nAnd then, then we're going\nto do that for every\n\n336\n00:20:50,960 --> 00:20:54,940\nsubexpression until the thing\nno longer changes.\n\n337\n00:20:54,940 --> 00:20:57,890\nYou can think of this as sort\nof an organic process.\n\n338\n00:20:57,890 --> 00:21:00,190\nYou've got some sort\nof stew, right?\n\n339\n00:21:00,190 --> 00:21:03,076\nYou've got bacteria or\nsomething, or enzymes in some,\n\n340\n00:21:03,076 --> 00:21:05,590\nin some gooey mess.\n\n341\n00:21:05,590 --> 00:21:10,470\nAnd there's these--and these\nenzymes change things.\n\n342\n00:21:10,470 --> 00:21:13,320\nThey attach to your expression,\nchange it, and\n\n343\n00:21:13,320 --> 00:21:15,300\nthen they go away.\n\n344\n00:21:15,300 --> 00:21:16,080\nAnd they have to match.\n\n345\n00:21:16,080 --> 00:21:17,740\nThe key-in-lock phenomenon.\n\n346\n00:21:17,740 --> 00:21:19,660\nThey match, they change\nit, they go away.\n\n347\n00:21:19,660 --> 00:21:22,310\nYou can imagine it as a parallel\nprocess of some sort.\n\n348\n00:21:22,310 --> 00:21:26,250\nSo you stick an expression into\nthis mess, and after a\n\n349\n00:21:26,250 --> 00:21:29,440\nwhile, you take it out, and\nit's been simplified.\n\n350\n00:21:29,440 --> 00:21:31,660\nAnd it just keeps changing\nuntil it no\n\n351\n00:21:31,660 --> 00:21:33,170\nlonger can be changed.\n\n352\n00:21:33,170 --> 00:21:37,840\nBut these enzymes can attach\nto any part of the, of the\n\n353\n00:21:37,840 --> 00:21:39,230\nexpression.\n\n354\n00:21:39,230 --> 00:21:44,990\nOK, at this point, I'd like to\nstop and ask for questions.\n\n355\n00:21:44,990 --> 00:21:45,950\nYes.\n\n356\n00:21:45,950 --> 00:21:48,550\nAUDIENCE: This implies that the\nmatching program and the\n\n357\n00:21:48,550 --> 00:21:50,460\ninstantiation program\nare separate\n\n358\n00:21:50,460 --> 00:21:51,650\nprograms; is that right?\n\n359\n00:21:51,650 --> 00:21:52,690\nOr is that-- they are.\n\n360\n00:21:52,690 --> 00:21:54,090\nPROFESSOR: They're separate\nlittle pieces.\n\n361\n00:21:54,090 --> 00:21:57,170\nThey fit together in\na larger structure.\n\n362\n00:21:57,170 --> 00:22:00,480\nAUDIENCE: So I'm going through\nand matching and passing the\n\n363\n00:22:00,480 --> 00:22:03,520\ninformation about what I matched\nto an instantiater,\n\n364\n00:22:03,520 --> 00:22:04,620\nwhich makes the changes.\n\n365\n00:22:04,620 --> 00:22:06,480\nAnd then I pass that back\nto the matcher?\n\n366\n00:22:06,480 --> 00:22:07,060\nPROFESSOR: It won't\nmake a change.\n\n367\n00:22:07,060 --> 00:22:11,540\nIt will make a new expression,\nwhich has, which has\n\n368\n00:22:11,540 --> 00:22:14,980\nsubstituted the values of the\npattern variable that were\n\n369\n00:22:14,980 --> 00:22:17,860\nmatched on the left-hand side\nfor the variables that are\n\n370\n00:22:17,860 --> 00:22:20,570\nmentioned, the skeleton\nvariables or evaluation\n\n371\n00:22:20,570 --> 00:22:25,170\nvariables or whatever I called\nthem, on the right-hand side.\n\n372\n00:22:25,170 --> 00:22:27,660\nAUDIENCE: And then that's passed\nback into the matcher?\n\n373\n00:22:27,660 --> 00:22:29,490\nPROFESSOR: Then this is going\nto go around again.\n\n374\n00:22:29,490 --> 00:22:31,330\nThis is going to go through\nthis mess until\n\n375\n00:22:31,330 --> 00:22:33,240\nit no longer changes.\n\n376\n00:22:33,240 --> 00:22:35,440\nAUDIENCE: And it seems that\nthere would be a danger of\n\n377\n00:22:35,440 --> 00:22:37,170\ngetting into a recursive loop.\n\n378\n00:22:37,170 --> 00:22:38,160\nPROFESSOR: Yes.\n\n379\n00:22:38,160 --> 00:22:41,240\nYes, if you do not write your\nrules nicely, you are--\n\n380\n00:22:41,240 --> 00:22:43,870\nindeed, in any programming\nlanguage you invent, if it's\n\n381\n00:22:43,870 --> 00:22:46,190\nsufficiently powerful to do\nanything, you can write\n\n382\n00:22:46,190 --> 00:22:49,280\nprograms that will go\ninto infinite loops.\n\n383\n00:22:49,280 --> 00:22:52,600\nAnd indeed, writing a program\nfor doing algebraic\n\n384\n00:22:52,600 --> 00:22:55,010\nmanipulation for long will\nproduce infinite loops.\n\n385\n00:22:55,010 --> 00:23:00,722\n\n\n386\n00:23:00,722 --> 00:23:01,680\nGo ahead.\n\n387\n00:23:01,680 --> 00:23:04,580\nAUDIENCE: Some language\ndesigners feel that this\n\n388\n00:23:04,580 --> 00:23:07,850\nfeature is so important that it\nshould become part of the\n\n389\n00:23:07,850 --> 00:23:12,670\nbasic language, for example,\nscheme in this case.\n\n390\n00:23:12,670 --> 00:23:13,960\nWhat are your thoughts on--\n\n391\n00:23:13,960 --> 00:23:15,722\nPROFESSOR: Which language\nfeature?\n\n392\n00:23:15,722 --> 00:23:17,290\nAUDIENCE: The pairs matching.\n\n393\n00:23:17,290 --> 00:23:21,840\nIt's all application of\nsuch rules should be--\n\n394\n00:23:21,840 --> 00:23:23,650\nPROFESSOR: Oh, you\nmean like Prolog?\n\n395\n00:23:23,650 --> 00:23:26,595\nAUDIENCE: Like Prolog, but it\nbecomes a more general--\n\n396\n00:23:26,595 --> 00:23:28,470\nPROFESSOR: It's possible.\n\n397\n00:23:28,470 --> 00:23:33,740\nOK, I think my feeling about\nthat is that I would like to\n\n398\n00:23:33,740 --> 00:23:35,840\nteach you how to do it so you\ndon't depend upon some\n\n399\n00:23:35,840 --> 00:23:38,490\nlanguage designer.\n\n400\n00:23:38,490 --> 00:23:40,870\nAUDIENCE: OK.\n\n401\n00:23:40,870 --> 00:23:41,850\nPROFESSOR: You make\nit yourself.\n\n402\n00:23:41,850 --> 00:23:44,640\nYou can roll your own.\n\n403\n00:23:44,640 --> 00:23:45,890\nThank you.\n\n404\n00:23:45,890 --> 00:24:14,120\n\n\n405\n00:24:14,120 --> 00:24:15,800\nWell, let's see.\n\n406\n00:24:15,800 --> 00:24:17,100\nNow we have to tell\nyou how it works.\n\n407\n00:24:17,100 --> 00:24:21,586\n\n\n408\n00:24:21,586 --> 00:24:24,445\nIt conveniently breaks up\ninto various pieces.\n\n409\n00:24:24,445 --> 00:24:28,680\nI'd like to look now\nat the matcher.\n\n410\n00:24:28,680 --> 00:24:32,730\nThe matcher has the following\nbasic structure.\n\n411\n00:24:32,730 --> 00:24:44,500\nIt's a box that takes as its\ninput an expression and a\n\n412\n00:24:44,500 --> 00:24:53,570\npattern, and it turns\nout a dictionary.\n\n413\n00:24:53,570 --> 00:25:01,530\n\n\n414\n00:25:01,530 --> 00:25:06,440\nA dictionary, remember, is a\nmapping of pattern variables\n\n415\n00:25:06,440 --> 00:25:09,990\nto the values that were found\nby matching, and it puts out\n\n416\n00:25:09,990 --> 00:25:20,370\nanother dictionary, which is the\nresult of augmenting this\n\n417\n00:25:20,370 --> 00:25:24,350\ndictionary by what was found\nin matching this expression\n\n418\n00:25:24,350 --> 00:25:25,600\nagainst this pattern.\n\n419\n00:25:25,600 --> 00:25:27,930\n\n\n420\n00:25:27,930 --> 00:25:29,180\nSo that's the matcher.\n\n421\n00:25:29,180 --> 00:25:33,900\n\n\n422\n00:25:33,900 --> 00:25:37,600\nNow, this is a rather\ncomplicated program, and we\n\n423\n00:25:37,600 --> 00:25:42,530\ncan look at it on the overhead\nover here and see, ha, ha,\n\n424\n00:25:42,530 --> 00:25:44,430\nit's very complicated.\n\n425\n00:25:44,430 --> 00:25:46,740\nI just want you to look\nat the shape of it.\n\n426\n00:25:46,740 --> 00:25:51,670\nIt's too complicated to look\nat except in pieces.\n\n427\n00:25:51,670 --> 00:25:56,720\nHowever, it's a fairly large,\ncomplicated program with a lot\n\n428\n00:25:56,720 --> 00:26:00,140\nof sort of indented structure.\n\n429\n00:26:00,140 --> 00:26:02,090\nAt the largest scale--\n\n430\n00:26:02,090 --> 00:26:04,740\nyou don't try to read those\ncharacters, but at the largest\n\n431\n00:26:04,740 --> 00:26:09,130\nscale, you see that there is a\ncase analysis, which is all\n\n432\n00:26:09,130 --> 00:26:12,100\nthese cases lined up.\n\n433\n00:26:12,100 --> 00:26:15,400\nWhat we're now going to do is\nlook at this in a bit more\n\n434\n00:26:15,400 --> 00:26:19,970\ndetail, attempting to understand\nhow it works.\n\n435\n00:26:19,970 --> 00:26:24,810\nLet's go now to the first slide,\nshowing some of the\n\n436\n00:26:24,810 --> 00:26:28,710\nstructure of the matcher\nat a large scale.\n\n437\n00:26:28,710 --> 00:26:33,440\nAnd we see that the matcher, the\nmatcher takes as its input\n\n438\n00:26:33,440 --> 00:26:36,050\na pattern, an expression,\nand a dictionary.\n\n439\n00:26:36,050 --> 00:26:38,580\n\n\n440\n00:26:38,580 --> 00:26:42,370\nAnd there is a case analysis\nhere, which is made out of\n\n441\n00:26:42,370 --> 00:26:46,630\nseveral cases, some of which\nhave been left out over here,\n\n442\n00:26:46,630 --> 00:26:50,560\nand the general case, which\nI'd like you to see.\n\n443\n00:26:50,560 --> 00:26:51,920\nLet's consider this\ngeneral case.\n\n444\n00:26:51,920 --> 00:26:53,230\nIt's a very important pattern.\n\n445\n00:26:53,230 --> 00:26:55,920\n\n\n446\n00:26:55,920 --> 00:27:00,650\nThe problem is that we have\nto examine two trees\n\n447\n00:27:00,650 --> 00:27:03,000\nsimultaneously.\n\n448\n00:27:03,000 --> 00:27:06,230\nOne of the trees is the tree\nof the expression, and the\n\n449\n00:27:06,230 --> 00:27:08,660\nother is the tree\nof the pattern.\n\n450\n00:27:08,660 --> 00:27:12,540\nWe have to compare them with\neach other so that the\n\n451\n00:27:12,540 --> 00:27:15,230\nsubexpressions of the expression\nare matched against\n\n452\n00:27:15,230 --> 00:27:18,380\nsubexpressions of the pattern.\n\n453\n00:27:18,380 --> 00:27:21,170\nLooking at that in a bit more\ndetail, suppose I had a\n\n454\n00:27:21,170 --> 00:27:29,820\npattern, a pattern, which was\nthe sum of the product of a\n\n455\n00:27:29,820 --> 00:27:38,130\nthing which we will call x and\na thing which we will call y,\n\n456\n00:27:38,130 --> 00:27:42,000\nand the sum of that, and the\nsame thing we call y.\n\n457\n00:27:42,000 --> 00:27:45,070\n\n\n458\n00:27:45,070 --> 00:27:49,902\nSo we're looking for a sum of a\nproduct whose second--whose\n\n459\n00:27:49,902 --> 00:27:53,790\nsecond argument is the\nsame as the second\n\n460\n00:27:53,790 --> 00:27:56,960\nargument of the sum.\n\n461\n00:27:56,960 --> 00:27:59,650\nThat's a thing you might\nbe looking for.\n\n462\n00:27:59,650 --> 00:28:02,770\nWell, that, as a pattern,\nlooks like this.\n\n463\n00:28:02,770 --> 00:28:09,660\nThere is a tree, which consists\nof a sum, and a\n\n464\n00:28:09,660 --> 00:28:16,640\nproduct with a pattern variable\nquestion mark x and\n\n465\n00:28:16,640 --> 00:28:21,960\nquestion mark y, the other\npattern variable, and question\n\n466\n00:28:21,960 --> 00:28:25,785\nmark y, just looking at the\nsame, just writing down the\n\n467\n00:28:25,785 --> 00:28:28,760\nlist structure in\na different way.\n\n468\n00:28:28,760 --> 00:28:31,040\nNow, suppose we were matching\nthat against an expression\n\n469\n00:28:31,040 --> 00:28:38,990\nwhich matches it, the sum of,\nsay, the product of 3 and x\n\n470\n00:28:38,990 --> 00:28:42,420\nand, say, x.\n\n471\n00:28:42,420 --> 00:28:44,380\nThat's another tree.\n\n472\n00:28:44,380 --> 00:28:56,250\nIt's the sum of the product\nof 3 and x and of x.\n\n473\n00:28:56,250 --> 00:28:59,320\n\n\n474\n00:28:59,320 --> 00:29:02,030\nSo what I want to do is traverse\nthese two trees\n\n475\n00:29:02,030 --> 00:29:04,410\nsimultaneously.\n\n476\n00:29:04,410 --> 00:29:08,670\nAnd what I'd like to do is\nwalk them like this.\n\n477\n00:29:08,670 --> 00:29:12,880\nI'm going to say are\nthese the same?\n\n478\n00:29:12,880 --> 00:29:15,200\nThis is a complicated object.\n\n479\n00:29:15,200 --> 00:29:17,240\nLet's look at the\nleft branches.\n\n480\n00:29:17,240 --> 00:29:18,460\nWell, that could be the car.\n\n481\n00:29:18,460 --> 00:29:19,250\nHow does that look?\n\n482\n00:29:19,250 --> 00:29:21,880\nOh yes, the plus looks\njust fine.\n\n483\n00:29:21,880 --> 00:29:24,080\nBut the next thing here is\na complicated thing.\n\n484\n00:29:24,080 --> 00:29:25,170\nLet's look at that.\n\n485\n00:29:25,170 --> 00:29:26,780\nOh yes, that's pretty\nfine, too.\n\n486\n00:29:26,780 --> 00:29:28,560\nThey're both asterisks.\n\n487\n00:29:28,560 --> 00:29:30,410\nNow, whoops!\n\n488\n00:29:30,410 --> 00:29:34,300\nMy pattern variable, it\nmatches against the 3.\n\n489\n00:29:34,300 --> 00:29:36,400\nRemember, x equals 3 now.\n\n490\n00:29:36,400 --> 00:29:38,290\nThat's in my dictionary, and\nthe dictionary's going to\n\n491\n00:29:38,290 --> 00:29:41,490\nfollow along with me:\nx equals three.\n\n492\n00:29:41,490 --> 00:29:46,800\nAh yes, x equals 3 and y\nequals x, different x.\n\n493\n00:29:46,800 --> 00:29:51,060\nThe pattern x is the expression\nx, the pattern y.\n\n494\n00:29:51,060 --> 00:29:53,630\n\n\n495\n00:29:53,630 --> 00:29:56,570\nOh yes, the pattern variable\ny, I've already\n\n496\n00:29:56,570 --> 00:29:57,270\ngot a value for it.\n\n497\n00:29:57,270 --> 00:29:58,410\nIt's x.\n\n498\n00:29:58,410 --> 00:29:59,050\nIs this an x?\n\n499\n00:29:59,050 --> 00:30:00,070\nOh yeah, sure it is.\n\n500\n00:30:00,070 --> 00:30:02,040\nThat's fine.\n\n501\n00:30:02,040 --> 00:30:03,380\nYep, done.\n\n502\n00:30:03,380 --> 00:30:07,070\nI now have a dictionary,\nwhich I've accumulated\n\n503\n00:30:07,070 --> 00:30:08,320\nby making this walk.\n\n504\n00:30:08,320 --> 00:30:11,370\n\n\n505\n00:30:11,370 --> 00:30:14,080\nWell, now let's look at this\ngeneral case here and see how\n\n506\n00:30:14,080 --> 00:30:15,830\nthat works.\n\n507\n00:30:15,830 --> 00:30:17,150\nHere we have it.\n\n508\n00:30:17,150 --> 00:30:20,520\nI take in a pattern variable--a\npattern, an\n\n509\n00:30:20,520 --> 00:30:22,310\nexpression, and a dictionary.\n\n510\n00:30:22,310 --> 00:30:26,650\nAnd now I'm going to do a\ncomplicated thing here, which\n\n511\n00:30:26,650 --> 00:30:29,610\nis the general case.\n\n512\n00:30:29,610 --> 00:30:33,480\nThe expression is made out of\ntwo parts: a left and a right\n\n513\n00:30:33,480 --> 00:30:35,470\nhalf, in general.\n\n514\n00:30:35,470 --> 00:30:38,080\nAnything that's complicated is\nmade out of two pieces in a\n\n515\n00:30:38,080 --> 00:30:39,950\nLisp system.\n\n516\n00:30:39,950 --> 00:30:41,870\nWell, now what do\nwe have here?\n\n517\n00:30:41,870 --> 00:30:45,840\nI'm going to match the car's of\nthe two expressions against\n\n518\n00:30:45,840 --> 00:30:50,190\neach other with respect to the\ndictionary I already have,\n\n519\n00:30:50,190 --> 00:30:55,620\nproducing a dictionary as its\nvalue, which I will then use\n\n520\n00:30:55,620 --> 00:30:58,130\nfor matching the cdr's\nagainst each other.\n\n521\n00:30:58,130 --> 00:31:00,580\nSo that's how the dictionary\ntravels,\n\n522\n00:31:00,580 --> 00:31:03,580\nthreads the entire structure.\n\n523\n00:31:03,580 --> 00:31:06,310\nAnd then the result of that is\nthe dictionary for the match\n\n524\n00:31:06,310 --> 00:31:11,230\nof the car and the cdr, and\nthat's what's going to be\n\n525\n00:31:11,230 --> 00:31:13,640\nreturned as a value.\n\n526\n00:31:13,640 --> 00:31:16,670\nNow, at any point, a\nmatch might fail.\n\n527\n00:31:16,670 --> 00:31:19,670\nIt may be the case, for example,\nif we go back and\n\n528\n00:31:19,670 --> 00:31:24,010\nlook at an expression that\ndoesn't quite match, like\n\n529\n00:31:24,010 --> 00:31:29,040\nsupposing this was a 4.\n\n530\n00:31:29,040 --> 00:31:33,520\nWell, now these two don't match\nany more, because the x\n\n531\n00:31:33,520 --> 00:31:38,190\nthat had to be-- sorry, the y\nthat had to be x here and this\n\n532\n00:31:38,190 --> 00:31:40,410\ny has to be 4.\n\n533\n00:31:40,410 --> 00:31:44,510\nBut x and 4 were not the same\nobject syntactically.\n\n534\n00:31:44,510 --> 00:31:47,130\nSo this wouldn't match, and\nthat would be rejected\n\n535\n00:31:47,130 --> 00:31:50,220\nsometimes, so matches\nmay fail.\n\n536\n00:31:50,220 --> 00:31:54,140\nNow, of course, because this\nmatcher takes the dictionary\n\n537\n00:31:54,140 --> 00:31:57,110\nfrom the previous match as\ninput, it must be able to\n\n538\n00:31:57,110 --> 00:31:58,520\npropagate the failures.\n\n539\n00:31:58,520 --> 00:32:00,090\nAnd so that's what the\nfirst clause of\n\n540\n00:32:00,090 --> 00:32:03,420\nthis conditional does.\n\n541\n00:32:03,420 --> 00:32:07,330\nIt's also true that if it turned\nout that the pattern\n\n542\n00:32:07,330 --> 00:32:08,540\nwas not atomic--\n\n543\n00:32:08,540 --> 00:32:10,280\nsee, if the pattern was atomic,\nI'd go into this\n\n544\n00:32:10,280 --> 00:32:12,060\nstuff, which we haven't\nlooked at yet.\n\n545\n00:32:12,060 --> 00:32:16,250\nBut if the pattern is\nnot atomic and the\n\n546\n00:32:16,250 --> 00:32:17,825\nexpression is atomic--\n\n547\n00:32:17,825 --> 00:32:20,010\nit's not made out of pieces--\n\n548\n00:32:20,010 --> 00:32:23,560\nthen that must be a failure,\nand so we go over here.\n\n549\n00:32:23,560 --> 00:32:26,660\nIf the pattern is not atomic\nand the pattern is not a\n\n550\n00:32:26,660 --> 00:32:27,420\npattern variable--\n\n551\n00:32:27,420 --> 00:32:29,716\nI have to remind myself\nof that--\n\n552\n00:32:29,716 --> 00:32:30,850\nthen we go over here.\n\n553\n00:32:30,850 --> 00:32:32,570\nSo that way, failures\nmay occur.\n\n554\n00:32:32,570 --> 00:32:35,280\n\n\n555\n00:32:35,280 --> 00:32:39,612\nOK, so now let's look at the\ninsides of this thing.\n\n556\n00:32:39,612 --> 00:32:42,080\nWell, the first place to look\nis what happens if I have an\n\n557\n00:32:42,080 --> 00:32:42,870\natomic pattern?\n\n558\n00:32:42,870 --> 00:32:43,870\nThat's very simple.\n\n559\n00:32:43,870 --> 00:32:46,945\nA pattern that's not made\nout of any pieces: foo.\n\n560\n00:32:46,945 --> 00:32:49,200\nThat's a nice atomic pattern.\n\n561\n00:32:49,200 --> 00:32:52,060\nWell, here's what we see.\n\n562\n00:32:52,060 --> 00:32:56,750\nIf the pattern is atomic, then\nif the expression is atomic,\n\n563\n00:32:56,750 --> 00:33:00,200\nthen if they are the same thing,\nthen the dictionary I\n\n564\n00:33:00,200 --> 00:33:03,120\nget is the same one\nas I had before.\n\n565\n00:33:03,120 --> 00:33:04,730\nNothing's changed.\n\n566\n00:33:04,730 --> 00:33:09,160\nIt's just that I matched plus\nagainst plus, asterisk against\n\n567\n00:33:09,160 --> 00:33:11,440\nasterisk, x against x.\n\n568\n00:33:11,440 --> 00:33:12,920\nThat's all fine.\n\n569\n00:33:12,920 --> 00:33:16,110\nHowever, if the pattern is\nnot the one which is the\n\n570\n00:33:16,110 --> 00:33:19,405\nexpression, if I have two\nseparate atomic objects, then\n\n571\n00:33:19,405 --> 00:33:25,810\nit was matching plus against\nasterisk, which case I fail.\n\n572\n00:33:25,810 --> 00:33:29,300\nOr if it turns out that the\npattern is atomic but the\n\n573\n00:33:29,300 --> 00:33:33,310\nexpression is complicated,\nit's not atomic,\n\n574\n00:33:33,310 --> 00:33:34,560\nthen I get a failure.\n\n575\n00:33:34,560 --> 00:33:37,100\n\n\n576\n00:33:37,100 --> 00:33:38,800\nThat's very simple.\n\n577\n00:33:38,800 --> 00:33:44,040\nNow, what about the various\nkinds of pattern variables?\n\n578\n00:33:44,040 --> 00:33:45,610\nWe had three kinds.\n\n579\n00:33:45,610 --> 00:33:47,340\nI give them the names.\n\n580\n00:33:47,340 --> 00:33:50,990\nThey're arbitrary constants,\narbitrary variables, and\n\n581\n00:33:50,990 --> 00:33:53,770\narbitrary expressions.\n\n582\n00:33:53,770 --> 00:34:01,210\nA question mark x is an\narbitrary expression.\n\n583\n00:34:01,210 --> 00:34:04,830\nA question mark cx is an\narbitrary constant, and a\n\n584\n00:34:04,830 --> 00:34:08,537\nquestion mark vx is an\narbitrary variable.\n\n585\n00:34:08,537 --> 00:34:10,540\nWell, what do we do here?\n\n586\n00:34:10,540 --> 00:34:14,139\nLooking at this, we see that\nif I have an arbitrary\n\n587\n00:34:14,139 --> 00:34:18,080\nconstant, if the pattern is an\narbitrary constant, then it\n\n588\n00:34:18,080 --> 00:34:19,560\nhad better be the case\nthat the expression\n\n589\n00:34:19,560 --> 00:34:21,480\nhad better be a constant.\n\n590\n00:34:21,480 --> 00:34:22,620\nIf the expression is\nnot a constant,\n\n591\n00:34:22,620 --> 00:34:23,920\nthen that match fails.\n\n592\n00:34:23,920 --> 00:34:26,780\nIf it is a constant, however,\nthen I wish to extend the\n\n593\n00:34:26,780 --> 00:34:27,620\ndictionary.\n\n594\n00:34:27,620 --> 00:34:32,380\nI wish to extend the dictionary\nwith that pattern\n\n595\n00:34:32,380 --> 00:34:36,650\nbeing remembered to be that\nexpression using the old\n\n596\n00:34:36,650 --> 00:34:37,900\ndictionary as a starting\npoint.\n\n597\n00:34:37,900 --> 00:34:41,050\n\n\n598\n00:34:41,050 --> 00:34:44,179\nSo really, for arbitrary\nvariables, I have to check\n\n599\n00:34:44,179 --> 00:34:47,440\nfirst if the expression is a\nvariable by matching against.\n\n600\n00:34:47,440 --> 00:34:50,750\nIf so, it's worth extending\nthe dictionary so that the\n\n601\n00:34:50,750 --> 00:34:52,639\npattern is remembered to\nbe matched against that\n\n602\n00:34:52,639 --> 00:34:55,900\nexpression, given the original\ndictionary, and this makes a\n\n603\n00:34:55,900 --> 00:34:58,880\nnew dictionary.\n\n604\n00:34:58,880 --> 00:35:00,310\nNow, it has to check.\n\n605\n00:35:00,310 --> 00:35:03,860\nThere's a sorts of failure\ninside extend dictionary,\n\n606\n00:35:03,860 --> 00:35:04,990\nwhich is that--\n\n607\n00:35:04,990 --> 00:35:09,200\nif one of these pattern\nvariables already has a value\n\n608\n00:35:09,200 --> 00:35:12,810\nand I'm trying to match the\nthing against something else\n\n609\n00:35:12,810 --> 00:35:15,310\nwhich is not equivalent to the\none that I've already matched\n\n610\n00:35:15,310 --> 00:35:17,760\nit against once, then a failure\nwill come flying out\n\n611\n00:35:17,760 --> 00:35:20,220\nof here, too.\n\n612\n00:35:20,220 --> 00:35:22,890\nAnd I will see that some time.\n\n613\n00:35:22,890 --> 00:35:25,850\nAnd finally, an arbitrary\nexpression does not have to\n\n614\n00:35:25,850 --> 00:35:29,010\ncheck anything syntactic about\nthe expression that's being\n\n615\n00:35:29,010 --> 00:35:31,670\nmatched, so all it does is\nit's an extension of the\n\n616\n00:35:31,670 --> 00:35:34,355\ndictionary.\n\n617\n00:35:34,355 --> 00:35:39,300\nSo you've just seen a complete,\nvery simple matcher.\n\n618\n00:35:39,300 --> 00:35:41,640\nNow, one of the things that's\nrather remarkable about this\n\n619\n00:35:41,640 --> 00:35:44,670\nis people pay an awful lot of\nmoney these days for someone\n\n620\n00:35:44,670 --> 00:35:49,290\nto make a, quote, AI expert\nsystem that has nothing more\n\n621\n00:35:49,290 --> 00:35:53,470\nin it than a matcher and maybe\nan instantiater like this.\n\n622\n00:35:53,470 --> 00:35:55,780\nBut it's very easy to do, and\nnow, of course, you can start\n\n623\n00:35:55,780 --> 00:35:59,070\nup a little start-up company and\nmake a couple of megabucks\n\n624\n00:35:59,070 --> 00:36:01,835\nin the next week taking some\npeople for a ride.\n\n625\n00:36:01,835 --> 00:36:04,690\n\n\n626\n00:36:04,690 --> 00:36:07,510\n20 years ago, this\nwas remarkable,\n\n627\n00:36:07,510 --> 00:36:09,610\nthis kind of program.\n\n628\n00:36:09,610 --> 00:36:11,870\nBut now, this is sort of easy.\n\n629\n00:36:11,870 --> 00:36:13,660\nYou can teach it to freshmen.\n\n630\n00:36:13,660 --> 00:36:15,380\nWell, now there's an\ninstantiater as well.\n\n631\n00:36:15,380 --> 00:36:19,980\n\n\n632\n00:36:19,980 --> 00:36:21,710\nThe problem is they're all\ngoing off and making more\n\n633\n00:36:21,710 --> 00:36:24,190\nmoney than I do.\n\n634\n00:36:24,190 --> 00:36:26,660\nBut that's always been\ntrue of universities.\n\n635\n00:36:26,660 --> 00:36:33,140\nAs expression, the purpose of\nthe instantiater is to make\n\n636\n00:36:33,140 --> 00:36:39,245\nexpressions given a dictionary\nand a skeleton.\n\n637\n00:36:39,245 --> 00:36:44,290\n\n\n638\n00:36:44,290 --> 00:36:46,770\nAnd that's not very\nhard at all.\n\n639\n00:36:46,770 --> 00:36:53,590\nWe'll see that very simply in\nthe next, the next slide here.\n\n640\n00:36:53,590 --> 00:36:57,570\nTo instantiate a skeleton,\ngiven a particular\n\n641\n00:36:57,570 --> 00:36:58,230\ndictionary--\n\n642\n00:36:58,230 --> 00:36:59,650\noh, this is easy.\n\n643\n00:36:59,650 --> 00:37:04,050\nWe're going to do a recursive\ntree walk over the skeleton.\n\n644\n00:37:04,050 --> 00:37:06,540\nAnd for everything which is\na skeleton variable--\n\n645\n00:37:06,540 --> 00:37:08,390\nI don't know, call it a\nskeleton evaluation.\n\n646\n00:37:08,390 --> 00:37:10,612\nThat's the name and the abstract\nsyntax that I give it\n\n647\n00:37:10,612 --> 00:37:13,610\nin this program: a skeleton\nevaluation, a thing beginning\n\n648\n00:37:13,610 --> 00:37:18,180\nwith a colon in the rules.\n\n649\n00:37:18,180 --> 00:37:21,850\nFor anything of that case, I'm\ngoing to look up the answer in\n\n650\n00:37:21,850 --> 00:37:24,470\nthe dictionary, and we'll worry\nabout that in a second.\n\n651\n00:37:24,470 --> 00:37:27,700\nLet's look at this as a whole.\n\n652\n00:37:27,700 --> 00:37:28,530\nHere, I have--\n\n653\n00:37:28,530 --> 00:37:32,740\nI'm going to instantiate a\nskeleton, given a dictionary.\n\n654\n00:37:32,740 --> 00:37:38,300\nWell, I'm going to define some\ninternal loop right there, and\n\n655\n00:37:38,300 --> 00:37:40,190\nit's going to do something\nvery simple.\n\n656\n00:37:40,190 --> 00:37:44,600\nEven if a skeleton--even if a\nskeleton is simple and atomic,\n\n657\n00:37:44,600 --> 00:37:46,450\nin which case it's nothing more\nthan giving the skeleton\n\n658\n00:37:46,450 --> 00:37:51,140\nback as an answer, or in\nthe general case, it's\n\n659\n00:37:51,140 --> 00:37:56,150\ncomplicated, in which case\nI'm going to make up the\n\n660\n00:37:56,150 --> 00:37:59,360\nexpression which is the result\nof instantiating--\n\n661\n00:37:59,360 --> 00:38:01,000\ncalling this loop\nrecursively--\n\n662\n00:38:01,000 --> 00:38:04,870\ninstantiating the car of the\nskeleton and the cdr.\n\n663\n00:38:04,870 --> 00:38:08,090\nSo here is a recursive\ntree walk.\n\n664\n00:38:08,090 --> 00:38:12,410\nHowever, if it turns out to be a\nskeleton evaluation, a colon\n\n665\n00:38:12,410 --> 00:38:18,020\nexpression in the skeleton, then\nwhat I'm going to do is\n\n666\n00:38:18,020 --> 00:38:21,520\nfind the expression that's\nin the colon--\n\n667\n00:38:21,520 --> 00:38:22,820\nthe CADR in this case.\n\n668\n00:38:22,820 --> 00:38:25,110\nIt's a piece of abstract syntax\nhere, so I can change\n\n669\n00:38:25,110 --> 00:38:27,480\nmy representation of rules.\n\n670\n00:38:27,480 --> 00:38:31,330\nI'm going to evaluate that\nrelative to this dictionary,\n\n671\n00:38:31,330 --> 00:38:32,940\nwhatever evaluation means.\n\n672\n00:38:32,940 --> 00:38:36,100\nWe'll find out a lot about\nthat sometime.\n\n673\n00:38:36,100 --> 00:38:39,650\nAnd the result of that\nis my answer.\n\n674\n00:38:39,650 --> 00:38:39,830\nso.\n\n675\n00:38:39,830 --> 00:38:42,240\nI start up this loop-- here's\nmy initialization--\n\n676\n00:38:42,240 --> 00:38:44,900\nby calling it with the whole\nskeleton, and this will just\n\n677\n00:38:44,900 --> 00:38:47,100\ndo a recursive decomposition\ninto pieces.\n\n678\n00:38:47,100 --> 00:38:49,690\n\n\n679\n00:38:49,690 --> 00:38:55,090\nNow, one more little bit\nof detail is what\n\n680\n00:38:55,090 --> 00:38:57,130\nhappens inside evaluate?\n\n681\n00:38:57,130 --> 00:39:00,030\nI can't tell you that\nin great detail.\n\n682\n00:39:00,030 --> 00:39:01,650\nI'll tell you a little\nbit of it.\n\n683\n00:39:01,650 --> 00:39:03,130\nLater, we're going to see--look\ninto this in much\n\n684\n00:39:03,130 --> 00:39:04,970\nmore detail.\n\n685\n00:39:04,970 --> 00:39:10,120\nTo evaluate some form, some\nexpression with respect to a\n\n686\n00:39:10,120 --> 00:39:15,355\ndictionary, if the expression is\nan atomic object, well, I'm\n\n687\n00:39:15,355 --> 00:39:18,620\ngoing to go look it up.\n\n688\n00:39:18,620 --> 00:39:20,610\nNothing very exciting there.\n\n689\n00:39:20,610 --> 00:39:23,900\nOtherwise, I'm going to do\nsomething complicated here,\n\n690\n00:39:23,900 --> 00:39:26,790\nwhich is I'm going to apply a\nprocedure which is the result\n\n691\n00:39:26,790 --> 00:39:30,220\nof looking up the operator part\nin something that we're\n\n692\n00:39:30,220 --> 00:39:32,150\ngoing to find out\nabout someday.\n\n693\n00:39:32,150 --> 00:39:34,630\nI want you realize you're\nseeing magic now.\n\n694\n00:39:34,630 --> 00:39:40,000\nThis magic will become clear\nvery soon, but not today.\n\n695\n00:39:40,000 --> 00:39:43,540\nThen I'm looking at--looking\nup all the pieces, all the\n\n696\n00:39:43,540 --> 00:39:48,460\narguments to that in\nthe dictionary.\n\n697\n00:39:48,460 --> 00:39:51,390\nSo I don't want you to look\nat this in detail.\n\n698\n00:39:51,390 --> 00:39:54,330\nI want you to say that there's\nmore going on here, and we're\n\n699\n00:39:54,330 --> 00:39:59,000\ngoing to see more about this.\n\n700\n00:39:59,000 --> 00:39:59,490\nBut it's--\n\n701\n00:39:59,490 --> 00:40:02,490\nthe magic is going to stop.\n\n702\n00:40:02,490 --> 00:40:07,140\nThis part has to do with Lisp,\nand it's the end of that.\n\n703\n00:40:07,140 --> 00:40:10,260\n\n\n704\n00:40:10,260 --> 00:40:15,040\nOK, so now we know about\nmatching and instantiation.\n\n705\n00:40:15,040 --> 00:40:16,505\nAre there any questions\nfor this segment?\n\n706\n00:40:16,505 --> 00:40:27,936\n\n\n707\n00:40:27,936 --> 00:40:29,870\nAUDIENCE: I have a question.\n\n708\n00:40:29,870 --> 00:40:30,880\nPROFESSOR: Yes.\n\n709\n00:40:30,880 --> 00:40:33,600\nAUDIENCE: Is it possible to\nbring up a previous slide?\n\n710\n00:40:33,600 --> 00:40:36,160\nIt's about this define\nmatch pattern.\n\n711\n00:40:36,160 --> 00:40:37,300\nPROFESSOR: Yes.\n\n712\n00:40:37,300 --> 00:40:40,590\nYou'd like to see the overall\nslide define match pattern.\n\n713\n00:40:40,590 --> 00:40:41,890\nCan somebody put up the--\n\n714\n00:40:41,890 --> 00:40:42,940\nno, the overhead.\n\n715\n00:40:42,940 --> 00:40:45,300\nThat's the biggest scale one.\n\n716\n00:40:45,300 --> 00:40:47,640\nWhat part would you\nlike to see?\n\n717\n00:40:47,640 --> 00:40:49,930\nAUDIENCE: Well, the\ntop would be fine.\n\n718\n00:40:49,930 --> 00:40:54,540\nAny of the parts where you're\npassing failed.\n\n719\n00:40:54,540 --> 00:40:56,300\nPROFESSOR: Yes.\n\n720\n00:40:56,300 --> 00:40:58,625\nAUDIENCE: The idea is to pass\nfailed back to the dictionary;\n\n721\n00:40:58,625 --> 00:40:59,000\nis that right?\n\n722\n00:40:59,000 --> 00:41:05,180\nPROFESSOR: The dictionary is the\nanswer to a match, right?\n\n723\n00:41:05,180 --> 00:41:13,150\nAnd it is either some mapping\nor there's no match.\n\n724\n00:41:13,150 --> 00:41:14,560\nIt doesn't match.\n\n725\n00:41:14,560 --> 00:41:15,150\nAUDIENCE: Right.\n\n726\n00:41:15,150 --> 00:41:18,110\nPROFESSOR: So what you're seeing\nover here is, in fact,\n\n727\n00:41:18,110 --> 00:41:21,620\nbecause the fact that a match\nmay have another match pass in\n\n728\n00:41:21,620 --> 00:41:24,950\nthe dictionary, as you see in\nthe general case down here.\n\n729\n00:41:24,950 --> 00:41:27,325\nHere's the general case where\na match passes another match\n\n730\n00:41:27,325 --> 00:41:28,090\nto the dictionary.\n\n731\n00:41:28,090 --> 00:41:31,860\nWhen I match the cdr's, I match\nthem in the dictionary\n\n732\n00:41:31,860 --> 00:41:36,070\nthat is resulting from\nmatching the car's.\n\n733\n00:41:36,070 --> 00:41:37,180\nOK, that's what I have here.\n\n734\n00:41:37,180 --> 00:41:41,430\nSo because of that, if the match\nof the car's fails, then\n\n735\n00:41:41,430 --> 00:41:44,770\nit may be necessary that the\nmatch of the cdr's propagates\n\n736\n00:41:44,770 --> 00:41:48,570\nthat failure, and that's\nwhat the first line is.\n\n737\n00:41:48,570 --> 00:41:51,400\nAUDIENCE: OK, well, I'm still\nunclear what matches--\n\n738\n00:41:51,400 --> 00:41:54,800\nwhat comes out of one instance\nof the match?\n\n739\n00:41:54,800 --> 00:41:56,320\nPROFESSOR: One of two\npossibilities.\n\n740\n00:41:56,320 --> 00:41:59,350\nEither the symbol failed, which\nmeans there is no match.\n\n741\n00:41:59,350 --> 00:41:59,840\nAUDIENCE: Right.\n\n742\n00:41:59,840 --> 00:42:03,360\nPROFESSOR: Or some mapping,\nwhich is an abstract thing\n\n743\n00:42:03,360 --> 00:42:06,480\nright now, and you should know\nabout the structure of it,\n\n744\n00:42:06,480 --> 00:42:13,170\nwhich relates the pattern\nvariables to their values as\n\n745\n00:42:13,170 --> 00:42:14,490\npicked up in the match.\n\n746\n00:42:14,490 --> 00:42:16,930\nAUDIENCE: OK, so it is--\n\n747\n00:42:16,930 --> 00:42:18,810\nPROFESSOR: That's constructed\nby extend dictionary.\n\n748\n00:42:18,810 --> 00:42:22,450\nAUDIENCE: So the recursive\nnature brings about the fact\n\n749\n00:42:22,450 --> 00:42:28,290\nthat if ever a failed gets\npassed out of any calling of\n\n750\n00:42:28,290 --> 00:42:30,430\nmatch, then the first condition\nwill pick it up--\n\n751\n00:42:30,430 --> 00:42:32,820\nPROFESSOR: And just propagate\nit along without any further\n\n752\n00:42:32,820 --> 00:42:33,530\nado, right.\n\n753\n00:42:33,530 --> 00:42:34,370\nAUDIENCE: Oh, right.\n\n754\n00:42:34,370 --> 00:42:35,460\nOK.\n\n755\n00:42:35,460 --> 00:42:36,650\nPROFESSOR: That's just the\nfastest way to get that\n\n756\n00:42:36,650 --> 00:42:37,900\nfailure out of there.\n\n757\n00:42:37,900 --> 00:42:43,260\n\n\n758\n00:42:43,260 --> 00:42:43,850\nYes.\n\n759\n00:42:43,850 --> 00:42:46,530\nAUDIENCE: If I don't fail, that\nmeans that I've matched a\n\n760\n00:42:46,530 --> 00:42:51,230\npattern, and I run the procedure\nextend dict and then\n\n761\n00:42:51,230 --> 00:42:52,655\npass in the pattern\nin the expression.\n\n762\n00:42:52,655 --> 00:42:55,270\n\n\n763\n00:42:55,270 --> 00:42:57,290\nBut the substitution will\nnot be made at that\n\n764\n00:42:57,290 --> 00:42:58,400\npoint; is that right?\n\n765\n00:42:58,400 --> 00:42:59,110\nI'm just--\n\n766\n00:42:59,110 --> 00:42:59,420\nPROFESSOR: No, no.\n\n767\n00:42:59,420 --> 00:43:00,960\nThere's no substitution being\nthere because there's no\n\n768\n00:43:00,960 --> 00:43:02,520\nskeleton to be substituted in.\n\n769\n00:43:02,520 --> 00:43:02,950\nAUDIENCE: Right.\n\n770\n00:43:02,950 --> 00:43:03,070\nSo what--\n\n771\n00:43:03,070 --> 00:43:04,760\nPROFESSOR: All you've got there\nis we're making up the\n\n772\n00:43:04,760 --> 00:43:08,270\ndictionary for later\nsubstitution.\n\n773\n00:43:08,270 --> 00:43:10,680\nAUDIENCE: And what would the\ndictionary look like?\n\n774\n00:43:10,680 --> 00:43:13,540\nIs it ordered pairs?\n\n775\n00:43:13,540 --> 00:43:15,940\nPROFESSOR: That's--that's\nnot told to you.\n\n776\n00:43:15,940 --> 00:43:16,700\nWe're being abstract.\n\n777\n00:43:16,700 --> 00:43:17,650\nAUDIENCE: OK.\n\n778\n00:43:17,650 --> 00:43:18,850\nPROFESSOR: Why do you\nwant to know?\n\n779\n00:43:18,850 --> 00:43:20,075\nWhat it is, it's a function.\n\n780\n00:43:20,075 --> 00:43:21,330\nIt's a function.\n\n781\n00:43:21,330 --> 00:43:22,090\nAUDIENCE: Well, the reason\nI want to know is--\n\n782\n00:43:22,090 --> 00:43:23,300\nPROFESSOR: A function\nabstractly is a\n\n783\n00:43:23,300 --> 00:43:25,130\nset of ordered pairs.\n\n784\n00:43:25,130 --> 00:43:29,040\nIt could be implemented as\na set of list pairs.\n\n785\n00:43:29,040 --> 00:43:32,590\nIt could be implemented as some\nfancy table mechanism.\n\n786\n00:43:32,590 --> 00:43:35,780\nIt could be implemented\nas a function.\n\n787\n00:43:35,780 --> 00:43:38,500\nAnd somehow, I'm building\nup a function.\n\n788\n00:43:38,500 --> 00:43:40,560\nBut I'm not telling you.\n\n789\n00:43:40,560 --> 00:43:43,090\nThat's up to George, who's going\nto build that later.\n\n790\n00:43:43,090 --> 00:43:49,430\n\n\n791\n00:43:49,430 --> 00:43:52,470\nI know you really badly want\nto write concrete things.\n\n792\n00:43:52,470 --> 00:43:54,280\nI'm not going to let\nyou do that.\n\n793\n00:43:54,280 --> 00:43:56,020\nAUDIENCE: Well, let me at\nleast ask, what is the\n\n794\n00:43:56,020 --> 00:43:57,530\nimportant information\nthere that's being\n\n795\n00:43:57,530 --> 00:43:59,750\npassed to extend dict?\n\n796\n00:43:59,750 --> 00:44:01,720\nI want to pass the\npattern I found--\n\n797\n00:44:01,720 --> 00:44:02,630\nPROFESSOR: Yes.\n\n798\n00:44:02,630 --> 00:44:04,870\nThe pattern that's matched\nagainst the expression.\n\n799\n00:44:04,870 --> 00:44:07,680\nYou want to have the pattern,\nwhich happens to be in those\n\n800\n00:44:07,680 --> 00:44:09,970\ncases pattern variables,\nright?\n\n801\n00:44:09,970 --> 00:44:11,420\nAll of those three\ncases for extend\n\n802\n00:44:11,420 --> 00:44:13,220\ndict are pattern variables.\n\n803\n00:44:13,220 --> 00:44:14,090\nAUDIENCE: Right.\n\n804\n00:44:14,090 --> 00:44:16,370\nPROFESSOR: So you have a pattern\nvariable that is to be\n\n805\n00:44:16,370 --> 00:44:18,965\ngiven a value in a dictionary.\n\n806\n00:44:18,965 --> 00:44:19,250\nAUDIENCE: Mm-hmm.\n\n807\n00:44:19,250 --> 00:44:21,760\nPROFESSOR: The value is the\nexpression that it matched\n\n808\n00:44:21,760 --> 00:44:27,260\nagainst. The dictionary is the\nset of things I've already\n\n809\n00:44:27,260 --> 00:44:30,195\nfigured out that I have\nmemorized or learned.\n\n810\n00:44:30,195 --> 00:44:33,250\nAnd I am going to make a new\ndictionary, which is extended\n\n811\n00:44:33,250 --> 00:44:36,870\nfrom the original one by having\nthat pattern variable\n\n812\n00:44:36,870 --> 00:44:39,880\nhave a value with the\nnew dictionary.\n\n813\n00:44:39,880 --> 00:44:41,580\nAUDIENCE: I guess what I don't\nunderstand is why can't the\n\n814\n00:44:41,580 --> 00:44:43,450\nsubstitution be made right\nas soon as you find--\n\n815\n00:44:43,450 --> 00:44:44,760\nPROFESSOR: How do I know what\nI'm going to substitute?\n\n816\n00:44:44,760 --> 00:44:47,590\nI don't know anything\nabout this skeleton.\n\n817\n00:44:47,590 --> 00:44:49,550\nThis pattern, this matcher\nis an independent unit.\n\n818\n00:44:49,550 --> 00:44:50,320\nAUDIENCE: Oh, I see.\n\n819\n00:44:50,320 --> 00:44:51,090\nOK.\n\n820\n00:44:51,090 --> 00:44:51,350\nPROFESSOR: Right?\n\n821\n00:44:51,350 --> 00:44:52,330\nAUDIENCE: Yeah.\n\n822\n00:44:52,330 --> 00:44:53,200\nPROFESSOR: I take the matcher.\n\n823\n00:44:53,200 --> 00:44:54,170\nI apply the matcher.\n\n824\n00:44:54,170 --> 00:44:57,532\nIf it matches, then it was worth\ndoing instantiation.\n\n825\n00:44:57,532 --> 00:44:58,516\nAUDIENCE: OK, good.\n\n826\n00:44:58,516 --> 00:44:59,008\nYeah.\n\n827\n00:44:59,008 --> 00:45:00,484\nPROFESSOR: OK?\n\n828\n00:45:00,484 --> 00:45:02,880\nAUDIENCE: Can you just do that\nanswer again using that\n\n829\n00:45:02,880 --> 00:45:04,940\nexample on the board?\n\n830\n00:45:04,940 --> 00:45:06,390\nYou know, what you just passed\nback to the matcher.\n\n831\n00:45:06,390 --> 00:45:06,900\nPROFESSOR: Oh yes.\n\n832\n00:45:06,900 --> 00:45:08,480\nOK, yes.\n\n833\n00:45:08,480 --> 00:45:10,660\nYou're looking at\nthis example.\n\n834\n00:45:10,660 --> 00:45:14,470\nAt this point when I'm\ntraversing this structure, I\n\n835\n00:45:14,470 --> 00:45:16,630\nget to here: x.\n\n836\n00:45:16,630 --> 00:45:18,760\nI have some dictionary,\npresumably an empty dictionary\n\n837\n00:45:18,760 --> 00:45:22,020\nat this point if this is\nthe whole expression.\n\n838\n00:45:22,020 --> 00:45:26,550\nSo I have an empty dictionary,\nand I've matched x against 3.\n\n839\n00:45:26,550 --> 00:45:28,850\nSo now, after this point,\nthe dictionary\n\n840\n00:45:28,850 --> 00:45:33,550\ncontains x is 3, OK?\n\n841\n00:45:33,550 --> 00:45:35,290\nNow, I continue walking\nalong here.\n\n842\n00:45:35,290 --> 00:45:37,040\nI see y.\n\n843\n00:45:37,040 --> 00:45:39,780\nNow, this is a particular\nx, a pattern x.\n\n844\n00:45:39,780 --> 00:45:41,690\nI see y, a pattern y.\n\n845\n00:45:41,690 --> 00:45:48,940\nThe dictionary says, oh yes, the\npattern y is the symbol x\n\n846\n00:45:48,940 --> 00:45:52,360\nbecause I've got\na match there.\n\n847\n00:45:52,360 --> 00:45:55,380\nSo the dictionary now contains\nat this point two entries.\n\n848\n00:45:55,380 --> 00:46:02,180\nThe pattern x is 3, and the\npattern y is the expression x.\n\n849\n00:46:02,180 --> 00:46:04,230\nNow, I get that, I can\nwalk along further.\n\n850\n00:46:04,230 --> 00:46:08,100\nI say, oh, pattern y\nalso wants to be 4.\n\n851\n00:46:08,100 --> 00:46:10,680\nBut that isn't possible,\nproducing a failure.\n\n852\n00:46:10,680 --> 00:46:14,340\n\n\n853\n00:46:14,340 --> 00:46:14,830\nThank you.\n\n854\n00:46:14,830 --> 00:46:16,080\nLet's take a break.\n\n855\n00:46:16,080 --> 00:47:02,380\n\n\n856\n00:47:02,380 --> 00:47:07,020\nOK, you're seeing your first\nvery big and hairy program.\n\n857\n00:47:07,020 --> 00:47:10,380\nNow, of course, one of the goals\nof this subsegment is to\n\n858\n00:47:10,380 --> 00:47:12,440\nget you to be able to read\nsomething like this and not be\n\n859\n00:47:12,440 --> 00:47:13,760\nafraid of it.\n\n860\n00:47:13,760 --> 00:47:16,715\nThis one's only about\nfour pages of code.\n\n861\n00:47:16,715 --> 00:47:20,460\nBy the end of the subject, I\nhope a 50-page program will\n\n862\n00:47:20,460 --> 00:47:22,510\nnot look particularly\nfrightening.\n\n863\n00:47:22,510 --> 00:47:25,310\nBut I don't expect-- and I don't\nwant you to think that I\n\n864\n00:47:25,310 --> 00:47:29,200\nexpect you to be getting\nit as it's coming out.\n\n865\n00:47:29,200 --> 00:47:31,760\nYou're supposed to feel the\nflavor of this, OK?\n\n866\n00:47:31,760 --> 00:47:33,800\nAnd then you're supposed to\nthink about it because it is a\n\n867\n00:47:33,800 --> 00:47:35,220\nbig program.\n\n868\n00:47:35,220 --> 00:47:40,812\nThere's a lot of stuff\ninside this program.\n\n869\n00:47:40,812 --> 00:47:44,400\nNow, I've told you about the\nlanguage we're implementing,\n\n870\n00:47:44,400 --> 00:47:46,770\nthe pattern match substitution\nlanguage.\n\n871\n00:47:46,770 --> 00:47:48,320\nI showed you some rules.\n\n872\n00:47:48,320 --> 00:47:51,490\nAnd I've told you about matching\nand instantiation,\n\n873\n00:47:51,490 --> 00:47:54,240\nwhich are the two halves\nof how a rule works.\n\n874\n00:47:54,240 --> 00:47:57,350\nNow we have to understand the\ncontrol structure by which the\n\n875\n00:47:57,350 --> 00:48:03,220\nrules are applied to the\nexpressions so as to do\n\n876\n00:48:03,220 --> 00:48:04,470\nalgebraic simplification.\n\n877\n00:48:04,470 --> 00:48:06,960\n\n\n878\n00:48:06,960 --> 00:48:12,060\nNow, that's also a big\ncomplicated mess.\n\n879\n00:48:12,060 --> 00:48:16,450\nThe problem is that there is\na variety of interlocking,\n\n880\n00:48:16,450 --> 00:48:20,140\ninterwoven loops, if you\nwill, involved in this.\n\n881\n00:48:20,140 --> 00:48:22,540\nFor one thing, I\nhave to apply--\n\n882\n00:48:22,540 --> 00:48:25,910\nI have to examine every\nsubexpression of my expression\n\n883\n00:48:25,910 --> 00:48:29,070\nthat I'm trying to simplify.\n\n884\n00:48:29,070 --> 00:48:29,960\nThat we know how to do.\n\n885\n00:48:29,960 --> 00:48:34,090\nIt's a car cdr recursion of some\nsort, or something like\n\n886\n00:48:34,090 --> 00:48:37,480\nthat, and some sort\nof tree walk.\n\n887\n00:48:37,480 --> 00:48:38,850\nAnd that's going to\nbe happening.\n\n888\n00:48:38,850 --> 00:48:43,660\nNow, for every such place, every\nnode that I get to in\n\n889\n00:48:43,660 --> 00:48:48,270\ndoing my traversal of the\nexpression I'm trying to\n\n890\n00:48:48,270 --> 00:48:53,390\nsimplify, I want to apply\nall of the rules.\n\n891\n00:48:53,390 --> 00:48:56,380\nEvery rule is going to\nlook at every node.\n\n892\n00:48:56,380 --> 00:48:57,750\nI'm going to rotate\nthe rules around.\n\n893\n00:48:57,750 --> 00:49:01,660\n\n\n894\n00:49:01,660 --> 00:49:07,530\nNow, either a rule will\nor will not match.\n\n895\n00:49:07,530 --> 00:49:10,140\nIf the rule does not match,\nthen it's not very\n\n896\n00:49:10,140 --> 00:49:12,270\ninteresting.\n\n897\n00:49:12,270 --> 00:49:16,090\nIf the rule does match, then I'm\ngoing to replace that node\n\n898\n00:49:16,090 --> 00:49:20,110\nin the expression by an\nalternate expression.\n\n899\n00:49:20,110 --> 00:49:21,360\nI'm actually going\nto make a new\n\n900\n00:49:21,360 --> 00:49:23,530\nexpression, which contains--\n\n901\n00:49:23,530 --> 00:49:26,560\neverything contains that new\nvalue, the result of\n\n902\n00:49:26,560 --> 00:49:29,950\nsubstituting into the skeleton,\ninstantiating the\n\n903\n00:49:29,950 --> 00:49:32,480\nskeleton for that rule\nat this level.\n\n904\n00:49:32,480 --> 00:49:35,670\nBut no one knows whether that\nthing that I instantiated\n\n905\n00:49:35,670 --> 00:49:38,180\nthere is in simplified form.\n\n906\n00:49:38,180 --> 00:49:41,690\nSo we're going to have to\nsimplify that, somehow to call\n\n907\n00:49:41,690 --> 00:49:43,370\nthe simplifier on the thing\nthat I just constructed.\n\n908\n00:49:43,370 --> 00:49:45,990\n\n\n909\n00:49:45,990 --> 00:49:48,710\nAnd then when that's done, then\nI sort of can build that\n\n910\n00:49:48,710 --> 00:49:51,820\ninto the expression I\nwant as my answer.\n\n911\n00:49:51,820 --> 00:49:55,490\nNow, there is a basic idea\nhere, which I will call a\n\n912\n00:49:55,490 --> 00:49:57,110\ngarbage- in, garbage-out\nsimplifier.\n\n913\n00:49:57,110 --> 00:50:01,280\n\n\n914\n00:50:01,280 --> 00:50:03,570\nIt's a kind of recursive\nsimplifier.\n\n915\n00:50:03,570 --> 00:50:06,750\nAnd what happens is the way you\nsimplify something is that\n\n916\n00:50:06,750 --> 00:50:10,660\nsimple objects like variables\nare simple.\n\n917\n00:50:10,660 --> 00:50:14,110\nCompound objects, well,\nI don't know.\n\n918\n00:50:14,110 --> 00:50:16,260\nWhat I'm going to do is I'm\ngoing to build up from simple\n\n919\n00:50:16,260 --> 00:50:19,940\nobjects, trying to make simple\nthings by assuming that the\n\n920\n00:50:19,940 --> 00:50:21,220\npieces they're made\nout of are simple.\n\n921\n00:50:21,220 --> 00:50:24,540\n\n\n922\n00:50:24,540 --> 00:50:27,830\nThat's what's happening here.\n\n923\n00:50:27,830 --> 00:50:30,400\nWell, now, if we look\nat the first slide--\n\n924\n00:50:30,400 --> 00:50:31,965\nno, overhead, overhead.\n\n925\n00:50:31,965 --> 00:50:35,780\nIf we look at the overhead, we\nsee a very complicated program\n\n926\n00:50:35,780 --> 00:50:38,810\nlike we saw before for the\nmatcher, so complicated that\n\n927\n00:50:38,810 --> 00:50:41,260\nyou can't read it like that.\n\n928\n00:50:41,260 --> 00:50:44,590\nI just want you to get the feel\nof the shape of it, and\n\n929\n00:50:44,590 --> 00:50:48,880\nthe shape of it is that this\nprogram has various\n\n930\n00:50:48,880 --> 00:50:50,210\nsubprograms in it.\n\n931\n00:50:50,210 --> 00:50:53,550\n\n\n932\n00:50:53,550 --> 00:50:57,080\nOne of them--this part is the\npart for traversing the\n\n933\n00:50:57,080 --> 00:51:02,560\nexpression, and this part is\nthe part for trying rules.\n\n934\n00:51:02,560 --> 00:51:06,490\nNow, of course, we can look at\nthat in some more detail.\n\n935\n00:51:06,490 --> 00:51:13,370\nLet's look at--let's look at the\nfirst transparency, right?\n\n936\n00:51:13,370 --> 00:51:17,990\nThe simplifier is made\nout of several parts.\n\n937\n00:51:17,990 --> 00:51:20,500\nNow, remember at the very\nbeginning, the simplifier is\n\n938\n00:51:20,500 --> 00:51:24,100\nthe thing which takes a rules--a\nset of rules and\n\n939\n00:51:24,100 --> 00:51:27,190\nproduces a program which will\nsimplify it relative to them.\n\n940\n00:51:27,190 --> 00:51:29,850\n\n\n941\n00:51:29,850 --> 00:51:32,390\nSo here we have our\nsimplifier.\n\n942\n00:51:32,390 --> 00:51:36,150\nIt takes a rule set.\n\n943\n00:51:36,150 --> 00:51:39,440\nAnd in the context where that\nrule set is defined, there are\n\n944\n00:51:39,440 --> 00:51:42,260\nvarious other definitions\nthat are done here.\n\n945\n00:51:42,260 --> 00:51:46,660\nAnd then the result of this\nsimplifier procedure is, in\n\n946\n00:51:46,660 --> 00:51:50,110\nfact, one of the procedures\nthat was defined.\n\n947\n00:51:50,110 --> 00:51:52,400\nSimplify x.\n\n948\n00:51:52,400 --> 00:51:56,480\nWhat I'm returning as the\nvalue of calling the\n\n949\n00:51:56,480 --> 00:52:01,340\nsimplifier on a set of rules is\na procedure, the simplify x\n\n950\n00:52:01,340 --> 00:52:05,680\nprocedure, which is defined in\nthat context, which is a\n\n951\n00:52:05,680 --> 00:52:08,200\nsimplification procedure\nappropriate for using those\n\n952\n00:52:08,200 --> 00:52:09,450\nset of rules.\n\n953\n00:52:09,450 --> 00:52:14,930\n\n\n954\n00:52:14,930 --> 00:52:17,460\nThat's what I have there.\n\n955\n00:52:17,460 --> 00:52:21,440\nNow, the first two of these\nprocedures, this one and this\n\n956\n00:52:21,440 --> 00:52:25,070\none, are together going to be\nthe recursive traversal of an\n\n957\n00:52:25,070 --> 00:52:26,950\nexpression.\n\n958\n00:52:26,950 --> 00:52:29,680\nThis one is the general\nsimplification for any\n\n959\n00:52:29,680 --> 00:52:32,620\nexpression, and this is the\nthing which simplifies a list\n\n960\n00:52:32,620 --> 00:52:35,540\nof parts of an expression.\n\n961\n00:52:35,540 --> 00:52:36,940\nNothing more.\n\n962\n00:52:36,940 --> 00:52:38,770\nFor each of those, we're going\nto do something complicated,\n\n963\n00:52:38,770 --> 00:52:40,340\nwhich involves trying\nthe rules.\n\n964\n00:52:40,340 --> 00:52:41,700\nNow, we should look at\nthe various parts.\n\n965\n00:52:41,700 --> 00:52:45,290\n\n\n966\n00:52:45,290 --> 00:52:47,710\nWell let's look first at the\nrecursive traversal of an\n\n967\n00:52:47,710 --> 00:52:48,530\nexpression.\n\n968\n00:52:48,530 --> 00:52:54,210\nAnd this is done in a\nsort of simple way.\n\n969\n00:52:54,210 --> 00:52:59,310\nThis is a little nest of\nrecursive procedures.\n\n970\n00:52:59,310 --> 00:53:02,580\nAnd what we have here\nare two procedures--\n\n971\n00:53:02,580 --> 00:53:06,600\none for simplifying an\nexpression, and one for\n\n972\n00:53:06,600 --> 00:53:08,982\nsimplifying parts of\nan expression.\n\n973\n00:53:08,982 --> 00:53:12,130\nAnd the way this works\nis very simple.\n\n974\n00:53:12,130 --> 00:53:16,270\nIf the expression I'm trying\nto simplify is a compound\n\n975\n00:53:16,270 --> 00:53:19,920\nexpression, I'm going to\nsimplify all the parts of it.\n\n976\n00:53:19,920 --> 00:53:22,480\nAnd that's calling--that\nprocedure, simplify parts, is\n\n977\n00:53:22,480 --> 00:53:25,020\ngoing to make up a new\nexpression with all the parts\n\n978\n00:53:25,020 --> 00:53:26,920\nsimplified, which I'm then\ngoing to try the\n\n979\n00:53:26,920 --> 00:53:30,840\nrules on over here.\n\n980\n00:53:30,840 --> 00:53:33,560\nIf it turns out that the\nexpression is not compound, if\n\n981\n00:53:33,560 --> 00:53:37,990\nit's simple, like just a symbol\nor something like pi,\n\n982\n00:53:37,990 --> 00:53:40,300\nthen in any case, I'm going to\ntry the rules on it because it\n\n983\n00:53:40,300 --> 00:53:42,900\nmight be that I want in my set\nof rules to expand pi to\n\n984\n00:53:42,900 --> 00:53:48,290\n3.14159265358979,\ndot, dot, dot.\n\n985\n00:53:48,290 --> 00:53:49,570\nBut I may not.\n\n986\n00:53:49,570 --> 00:53:52,750\nBut there is no reason\nnot to do it.\n\n987\n00:53:52,750 --> 00:53:59,010\nNow, if I want to simplify the\nparts, well, that's easy too.\n\n988\n00:53:59,010 --> 00:54:02,480\nEither the expression is an\nempty one, there's no more\n\n989\n00:54:02,480 --> 00:54:05,730\nparts, in which case I have\nthe empty expression.\n\n990\n00:54:05,730 --> 00:54:11,460\nOtherwise, I'm going to make a\nnew expression by cons, which\n\n991\n00:54:11,460 --> 00:54:13,360\nis the result of simplifying\nthe first part of the\n\n992\n00:54:13,360 --> 00:54:16,370\nexpression, the car, and\nsimplifying the rest of the\n\n993\n00:54:16,370 --> 00:54:21,060\nexpression, which is the cdr.\n\n994\n00:54:21,060 --> 00:54:23,250\nNow, the reason why I'm showing\nyou this sort of stuff\n\n995\n00:54:23,250 --> 00:54:26,740\nthis way is because I want you\nget the feeling for the\n\n996\n00:54:26,740 --> 00:54:29,800\nvarious patterns that are very\nimportant when writing\n\n997\n00:54:29,800 --> 00:54:33,970\nprograms. And this could be\nwritten a different way.\n\n998\n00:54:33,970 --> 00:54:35,850\nThere's another way to write\nsimplified expressions so\n\n999\n00:54:35,850 --> 00:54:37,355\nthere would be only\none of them.\n\n1000\n00:54:37,355 --> 00:54:39,530\nThere would only be one\nlittle procedure here.\n\n1001\n00:54:39,530 --> 00:54:41,540\nLet me just write that on the\nblackboard to give you a\n\n1002\n00:54:41,540 --> 00:54:42,790\nfeeling for that.\n\n1003\n00:54:42,790 --> 00:54:49,520\n\n\n1004\n00:54:49,520 --> 00:54:52,170\nThis in another idiom,\nif you will.\n\n1005\n00:54:52,170 --> 00:54:58,449\n\n\n1006\n00:54:58,449 --> 00:55:02,696\nTo simplify an expression\ncalled x, what\n\n1007\n00:55:02,696 --> 00:55:03,400\nam I going to do?\n\n1008\n00:55:03,400 --> 00:55:11,100\nI'm going to try the rules on\nthe following situation.\n\n1009\n00:55:11,100 --> 00:55:12,170\nIf--\n\n1010\n00:55:12,170 --> 00:55:14,090\non the following expression--\n\n1011\n00:55:14,090 --> 00:55:15,690\ncompound, just like\nwe had before.\n\n1012\n00:55:15,690 --> 00:55:21,060\n\n\n1013\n00:55:21,060 --> 00:55:24,270\nIf the expression is compound,\nwell, what am I going to do?\n\n1014\n00:55:24,270 --> 00:55:25,970\nI'm going to simplify\nall the parts.\n\n1015\n00:55:25,970 --> 00:55:30,950\nBut I already have a cdr\nrecursion, a common pattern of\n\n1016\n00:55:30,950 --> 00:55:33,590\nusage, which has been captured\nas a high-order procedure.\n\n1017\n00:55:33,590 --> 00:55:36,040\nIt's called map.\n\n1018\n00:55:36,040 --> 00:55:37,180\nSo I'll just write that here.\n\n1019\n00:55:37,180 --> 00:55:47,290\nMap simplify the expression,\nall the parts of the\n\n1020\n00:55:47,290 --> 00:55:49,060\nexpression.\n\n1021\n00:55:49,060 --> 00:55:52,580\nThis says apply the\nsimplification operation,\n\n1022\n00:55:52,580 --> 00:55:55,780\nwhich is this one, every part\nof the expression, and then\n\n1023\n00:55:55,780 --> 00:56:02,440\nthat cuts those up into a list.\nIt's every element of\n\n1024\n00:56:02,440 --> 00:56:06,254\nthe list which the expression is\nassumed to be made out of,\n\n1025\n00:56:06,254 --> 00:56:08,910\nand otherwise, I have\nthe expression.\n\n1026\n00:56:08,910 --> 00:56:12,650\nSo I don't need the helper\nprocedure, simplify parts,\n\n1027\n00:56:12,650 --> 00:56:15,370\nbecause that's really this.\n\n1028\n00:56:15,370 --> 00:56:17,690\nSo sometimes, you just\nwrite it this way.\n\n1029\n00:56:17,690 --> 00:56:20,830\nIt doesn't matter very much.\n\n1030\n00:56:20,830 --> 00:56:24,410\nWell, now let's take\na look at--\n\n1031\n00:56:24,410 --> 00:56:27,660\nlet's just look at how\nyou try rules.\n\n1032\n00:56:27,660 --> 00:56:30,540\nIf you look at this slide,\nwe see this is a\n\n1033\n00:56:30,540 --> 00:56:33,680\ncomplicated mess also.\n\n1034\n00:56:33,680 --> 00:56:36,140\nI'm trying rules on\nan expression.\n\n1035\n00:56:36,140 --> 00:56:38,030\nIt turns out the expression\nI'm trying it on is some\n\n1036\n00:56:38,030 --> 00:56:40,490\nsubexpression now of the\nexpression I started with.\n\n1037\n00:56:40,490 --> 00:56:43,040\nBecause the thing I just\narranged allowed us to try\n\n1038\n00:56:43,040 --> 00:56:44,290\nevery subexpression.\n\n1039\n00:56:44,290 --> 00:56:46,050\n\n\n1040\n00:56:46,050 --> 00:56:50,140\nSo now here we're taking in\na subexpression of the\n\n1041\n00:56:50,140 --> 00:56:51,080\nexpression we started with.\n\n1042\n00:56:51,080 --> 00:56:52,225\nThat's what this is.\n\n1043\n00:56:52,225 --> 00:56:55,670\nAnd what we're going to define\nhere is a procedure called\n\n1044\n00:56:55,670 --> 00:56:58,640\nscan, which is going\nto try every rule.\n\n1045\n00:56:58,640 --> 00:57:01,920\nAnd we're going to start it up\non the whole set of rules.\n\n1046\n00:57:01,920 --> 00:57:06,670\nThis is going to go cdr-ing down\nthe rules, if you will,\n\n1047\n00:57:06,670 --> 00:57:09,370\nlooking for a rule to apply.\n\n1048\n00:57:09,370 --> 00:57:14,140\nAnd when it finds one,\nit'll do the job.\n\n1049\n00:57:14,140 --> 00:57:17,630\nWell, let's take a look at\nhow try rules works.\n\n1050\n00:57:17,630 --> 00:57:19,720\nIt's very simple:\nthe scan rules.\n\n1051\n00:57:19,720 --> 00:57:22,066\nScan rules, the way\nof scanning.\n\n1052\n00:57:22,066 --> 00:57:23,270\nWell, is it so simple?\n\n1053\n00:57:23,270 --> 00:57:25,510\nIt's a big program, of course.\n\n1054\n00:57:25,510 --> 00:57:28,060\nWe take a bunch of rules,\nwhich is a sublist\n\n1055\n00:57:28,060 --> 00:57:30,700\nof the list of rules.\n\n1056\n00:57:30,700 --> 00:57:33,080\nWe've tried some of them\nalready, and they've not been\n\n1057\n00:57:33,080 --> 00:57:35,360\nappropriate, so we\nget to some here.\n\n1058\n00:57:35,360 --> 00:57:36,490\nWe get to move to\nthe next one.\n\n1059\n00:57:36,490 --> 00:57:38,600\nIf there are no more rules, well\nthen, there's nothing I\n\n1060\n00:57:38,600 --> 00:57:42,200\ncan do with this expression,\nand it's simplified.\n\n1061\n00:57:42,200 --> 00:57:46,790\nHowever, if it turns out that\nthere are still rules to be\n\n1062\n00:57:46,790 --> 00:57:52,180\ndone, then let's match the\npattern of the first rule\n\n1063\n00:57:52,180 --> 00:57:55,280\nagainst the expression using the\nempty dictionary to start\n\n1064\n00:57:55,280 --> 00:58:00,270\nwith and use that as\nthe dictionary.\n\n1065\n00:58:00,270 --> 00:58:02,830\nIf that happens to\nbe a failure, try\n\n1066\n00:58:02,830 --> 00:58:04,080\nthe rest of the rules.\n\n1067\n00:58:04,080 --> 00:58:06,540\n\n\n1068\n00:58:06,540 --> 00:58:08,790\nThat's all it says here.\n\n1069\n00:58:08,790 --> 00:58:11,080\nIt says discard that rule.\n\n1070\n00:58:11,080 --> 00:58:14,640\nOtherwise, well, I'm going to\nget the skeleton of the first\n\n1071\n00:58:14,640 --> 00:58:17,890\nrule, instantiate that relative\nto the dictionary,\n\n1072\n00:58:17,890 --> 00:58:20,940\nand simplify the result, and\nthat's the expression I want.\n\n1073\n00:58:20,940 --> 00:58:24,070\n\n\n1074\n00:58:24,070 --> 00:58:26,380\nSo although that was a\ncomplicated program, every\n\n1075\n00:58:26,380 --> 00:58:29,940\ncomplicated program is made out\nof a lot of simple pieces.\n\n1076\n00:58:29,940 --> 00:58:34,760\nNow, the pattern of recursions\nhere is very complicated.\n\n1077\n00:58:34,760 --> 00:58:35,950\nAnd one of the most important\nthings is not\n\n1078\n00:58:35,950 --> 00:58:38,126\nto think about that.\n\n1079\n00:58:38,126 --> 00:58:41,130\nIf you try to think about the\nactual pattern by which this\n\n1080\n00:58:41,130 --> 00:58:45,250\ndoes something, you're going\nto get very confused.\n\n1081\n00:58:45,250 --> 00:58:47,420\nI would.\n\n1082\n00:58:47,420 --> 00:58:51,470\nThis is not a matter of you\ncan do this with practice.\n\n1083\n00:58:51,470 --> 00:58:53,761\nThese patterns are hard.\n\n1084\n00:58:53,761 --> 00:58:55,840\nBut you don't have to\nthink about it.\n\n1085\n00:58:55,840 --> 00:58:57,010\nThe key to this--\n\n1086\n00:58:57,010 --> 00:59:00,120\nit's very good programming and\nvery good design-- is to know\n\n1087\n00:59:00,120 --> 00:59:02,990\nwhat not to think about.\n\n1088\n00:59:02,990 --> 00:59:07,540\nThe fact is, going back to this\nslide, I don't have to\n\n1089\n00:59:07,540 --> 00:59:11,640\nthink about it because I have\nspecifications in my mind for\n\n1090\n00:59:11,640 --> 00:59:14,000\nwhat simplify x does.\n\n1091\n00:59:14,000 --> 00:59:16,735\nI don't have to know\nhow it does it.\n\n1092\n00:59:16,735 --> 00:59:20,720\nAnd it may, in fact, call scan\nsomehow through try rules,\n\n1093\n00:59:20,720 --> 00:59:22,190\nwhich it does.\n\n1094\n00:59:22,190 --> 00:59:24,230\nAnd somehow, I've got another\nrecursion going on here.\n\n1095\n00:59:24,230 --> 00:59:28,470\nBut since I know that simplify\nx is assumed by wishful\n\n1096\n00:59:28,470 --> 00:59:31,446\nthinking to produce the\nsimplified result, then I\n\n1097\n00:59:31,446 --> 00:59:33,900\ndon't have to think\nabout it anymore.\n\n1098\n00:59:33,900 --> 00:59:35,030\nI've used it.\n\n1099\n00:59:35,030 --> 00:59:36,480\nI've used it in a\nreasonable way.\n\n1100\n00:59:36,480 --> 00:59:39,468\nI will get a reasonable\nanswer.\n\n1101\n00:59:39,468 --> 00:59:41,760\nAnd you have to learn how\nto program that way--\n\n1102\n00:59:41,760 --> 00:59:43,010\nwith abandon.\n\n1103\n00:59:43,010 --> 00:59:47,480\n\n\n1104\n00:59:47,480 --> 00:59:50,390\nWell, there's very little\nleft of this thing.\n\n1105\n00:59:50,390 --> 00:59:53,610\nAll there is left is a few\ndetails associated with what a\n\n1106\n00:59:53,610 --> 00:59:55,060\ndictionary is.\n\n1107\n00:59:55,060 --> 00:59:57,520\nAnd those of you who've been\nitching to know what a\n\n1108\n00:59:57,520 --> 01:00:01,130\ndictionary is, well, I will flip\nit up and not tell you\n\n1109\n01:00:01,130 --> 01:00:04,110\nanything about it.\n\n1110\n01:00:04,110 --> 01:00:06,020\nDictionaries are easy.\n\n1111\n01:00:06,020 --> 01:00:09,570\nIt's represented in terms of\nsomething else called an A\n\n1112\n01:00:09,570 --> 01:00:14,730\nlist, which is a particular\npattern of usage for making\n\n1113\n01:00:14,730 --> 01:00:16,730\ntables in lists.\n\n1114\n01:00:16,730 --> 01:00:17,220\nThey're easy.\n\n1115\n01:00:17,220 --> 01:00:21,670\nThey're made out of pairs,\nas was asked a bit ago.\n\n1116\n01:00:21,670 --> 01:00:23,270\nAnd there are special procedures\nfor dealing with\n\n1117\n01:00:23,270 --> 01:00:27,020\nsuch things called assq, and you\ncan find them in manuals.\n\n1118\n01:00:27,020 --> 01:00:28,730\nI'm not terribly excited\nabout it.\n\n1119\n01:00:28,730 --> 01:00:31,710\nThe only interesting thing here\nin extend dictionary is I\n\n1120\n01:00:31,710 --> 01:00:36,480\nhave to extend the dictionary\nwith a pattern, a datum, and a\n\n1121\n01:00:36,480 --> 01:00:37,910\ndictionary.\n\n1122\n01:00:37,910 --> 01:00:42,896\nThis pattern is, in fact, at\nthis point a pattern variable.\n\n1123\n01:00:42,896 --> 01:00:44,880\nAnd what do I want to do?\n\n1124\n01:00:44,880 --> 01:00:48,220\nI want to pull out the name of\nthat pattern variable, the\n\n1125\n01:00:48,220 --> 01:00:52,100\npattern variable name, and I'm\ngoing to look up in the\n\n1126\n01:00:52,100 --> 01:00:53,750\ndictionary and see if it\nalready has a value.\n\n1127\n01:00:53,750 --> 01:00:57,030\nIf not, I'm going to\nadd a new one in.\n\n1128\n01:00:57,030 --> 01:01:00,730\nIf it does have one, if it has a\nvalue, then it had better be\n\n1129\n01:01:00,730 --> 01:01:03,920\nequal to the one that was\nalready stored away.\n\n1130\n01:01:03,920 --> 01:01:05,690\nAnd if that's the case, the\ndictionary is what I\n\n1131\n01:01:05,690 --> 01:01:06,940\nexpected it to be.\n\n1132\n01:01:06,940 --> 01:01:11,605\nOtherwise, I fail.\n\n1133\n01:01:11,605 --> 01:01:13,430\nSo that's easy, too.\n\n1134\n01:01:13,430 --> 01:01:15,940\nIf you open up any program,\nyou're going to find inside of\n\n1135\n01:01:15,940 --> 01:01:20,000\nit lots of little pieces,\nall of which are easy.\n\n1136\n01:01:20,000 --> 01:01:23,340\nSo at this point, I suppose,\nI've just told you some\n\n1137\n01:01:23,340 --> 01:01:27,995\nmillion-dollar valuable\ninformation.\n\n1138\n01:01:27,995 --> 01:01:30,320\nAnd I suppose at this point\nwe're pretty much done with\n\n1139\n01:01:30,320 --> 01:01:31,930\nthis program.\n\n1140\n01:01:31,930 --> 01:01:34,330\nI'd like to ask about\nquestions.\n\n1141\n01:01:34,330 --> 01:01:35,940\nAUDIENCE: Yes, can you give me\nthe words that describe the\n\n1142\n01:01:35,940 --> 01:01:38,650\nspecification for a simplified\nexpression?\n\n1143\n01:01:38,650 --> 01:01:39,475\nPROFESSOR: Sure.\n\n1144\n01:01:39,475 --> 01:01:43,330\nA simplified expression takes\nan expression and produces a\n\n1145\n01:01:43,330 --> 01:01:44,838\nsimplified expression.\n\n1146\n01:01:44,838 --> 01:01:48,120\nThat's it, OK?\n\n1147\n01:01:48,120 --> 01:01:51,212\nHow it does it is very easy.\n\n1148\n01:01:51,212 --> 01:01:53,710\nIn compound expressions, all the\npieces are simplified, and\n\n1149\n01:01:53,710 --> 01:01:56,910\nthen the rules are tried\non the result.\n\n1150\n01:01:56,910 --> 01:01:59,216\nAnd for simple expressions, you\njust try all the rules.\n\n1151\n01:01:59,216 --> 01:02:01,280\nAUDIENCE: So an expression\nis simplified by\n\n1152\n01:02:01,280 --> 01:02:02,535\nvirtue of the rules?\n\n1153\n01:02:02,535 --> 01:02:03,660\nPROFESSOR: That's,\nof course, true.\n\n1154\n01:02:03,660 --> 01:02:04,140\nAUDIENCE: Right.\n\n1155\n01:02:04,140 --> 01:02:06,060\nPROFESSOR: And the way this\nworks is that simplifi\n\n1156\n01:02:06,060 --> 01:02:10,000\nexpression, as you see here,\nwhat it does is it breaks the\n\n1157\n01:02:10,000 --> 01:02:13,190\nexpression down into the\nsmallest pieces, simplifies\n\n1158\n01:02:13,190 --> 01:02:16,690\nbuilding up from the bottom\nusing the rules to be the\n\n1159\n01:02:16,690 --> 01:02:21,100\nsimplifier, to do the\nmanipulations, and constructs\n\n1160\n01:02:21,100 --> 01:02:24,400\na new expression\nas the result.\n\n1161\n01:02:24,400 --> 01:02:28,290\nEventually, one of things you\nsee is that the rules\n\n1162\n01:02:28,290 --> 01:02:30,880\nthemselves, the try rules, call\na simplified expression\n\n1163\n01:02:30,880 --> 01:02:34,280\non the results when it changes\nsomething, the\n\n1164\n01:02:34,280 --> 01:02:35,830\nresults of a match.\n\n1165\n01:02:35,830 --> 01:02:39,420\nI'm sorry, the results of\ninstantiation of a skeleton\n\n1166\n01:02:39,420 --> 01:02:41,900\nfor a rule that has matched.\n\n1167\n01:02:41,900 --> 01:02:44,570\nSo the spec of a simplified\nexpression is that any\n\n1168\n01:02:44,570 --> 01:02:46,860\nexpression you put into it comes\nout simplified according\n\n1169\n01:02:46,860 --> 01:02:49,590\nto those rules.\n\n1170\n01:02:49,590 --> 01:02:50,190\nThank you.\n\n1171\n01:02:50,190 --> 01:02:51,860\nLet's take a break.\n\n1172\n01:02:51,860 --> 01:03:07,924\n\n"
  },
  {
    "path": "SrtEN/lec4b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:03,936\n\n\n1\n00:00:03,936 --> 00:00:04,279\n[MUSIC-- \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n2\n00:00:04,279 --> 00:00:05,529\nJOHANN SEBASTIAN BACH]\n\n3\n00:00:05,529 --> 00:00:20,180\n\n\n4\n00:00:20,180 --> 00:00:21,840\nPROFESSOR: So far in this course\nwe've been talking a\n\n5\n00:00:21,840 --> 00:00:23,780\nlot about data abstraction.\n\n6\n00:00:23,780 --> 00:00:28,230\nAnd remember the idea is that\nwe build systems that have\n\n7\n00:00:28,230 --> 00:00:31,980\nthese horizontal barriers in\nthem, these abstraction\n\n8\n00:00:31,980 --> 00:00:38,490\nbarriers that separate use,\nthe way you might use some\n\n9\n00:00:38,490 --> 00:00:41,180\ndata object, from the way\nyou might represent it.\n\n10\n00:00:41,180 --> 00:00:48,985\n\n\n11\n00:00:48,985 --> 00:00:51,760\nOr another way to think of that\nis up here you have the\n\n12\n00:00:51,760 --> 00:00:57,110\nboss who's going to be using\nsome sort of data object.\n\n13\n00:00:57,110 --> 00:01:02,310\nAnd down here is George\nwho's implemented it.\n\n14\n00:01:02,310 --> 00:01:05,760\nNow this notion of separating\nuse from representation so you\n\n15\n00:01:05,760 --> 00:01:10,930\ncan think about these two\nproblems separately is a very,\n\n16\n00:01:10,930 --> 00:01:15,930\nvery powerful programming\nmethodology, data abstraction.\n\n17\n00:01:15,930 --> 00:01:21,040\nOn the other hand, it's not\nreally sufficient for really\n\n18\n00:01:21,040 --> 00:01:28,640\ncomplex systems. And the problem\nwith this is George.\n\n19\n00:01:28,640 --> 00:01:32,110\nOr actually, the problem\nis that there\n\n20\n00:01:32,110 --> 00:01:34,630\nare a lot of Georges.\n\n21\n00:01:34,630 --> 00:01:35,390\nLet's be concrete.\n\n22\n00:01:35,390 --> 00:01:41,192\nLet's suppose there is George,\nand there's also Martha.\n\n23\n00:01:41,192 --> 00:01:46,040\nOK, now George and Martha are\nboth working on this system,\n\n24\n00:01:46,040 --> 00:01:49,250\nboth designing representations,\nand\n\n25\n00:01:49,250 --> 00:01:51,750\nabsolutely are incompatible.\n\n26\n00:01:51,750 --> 00:01:54,620\nThey wouldn't cooperate on a\nrepresentation under any\n\n27\n00:01:54,620 --> 00:01:57,250\ncircumstances.\n\n28\n00:01:57,250 --> 00:02:00,060\nAnd the problem is you would\nlike to have some system where\n\n29\n00:02:00,060 --> 00:02:05,380\nboth George and Martha are\ndesigning representations, and\n\n30\n00:02:05,380 --> 00:02:09,756\nyet, if you're above this\nabstraction barrier you don't\n\n31\n00:02:09,756 --> 00:02:12,360\nwant to have to worry about\nthat, whether something is\n\n32\n00:02:12,360 --> 00:02:14,180\ndone by George or by Martha.\n\n33\n00:02:14,180 --> 00:02:15,430\nAnd you don't want George\nand Martha to\n\n34\n00:02:15,430 --> 00:02:16,630\ninterfere with each other.\n\n35\n00:02:16,630 --> 00:02:20,310\nSomehow in designing a system,\nyou not only want these\n\n36\n00:02:20,310 --> 00:02:26,300\nhorizontal barriers, but you\nalso want some kind of\n\n37\n00:02:26,300 --> 00:02:32,980\nvertical barrier to keep George\nand Martha separate.\n\n38\n00:02:32,980 --> 00:02:36,560\nLet me be a little bit\nmore concrete.\n\n39\n00:02:36,560 --> 00:02:42,650\nImagine that you're thinking\nabout personnel records for a\n\n40\n00:02:42,650 --> 00:02:48,180\nlarge company with a lot of\nloosely linked divisions that\n\n41\n00:02:48,180 --> 00:02:50,430\ndon't cooperate very\nwell either.\n\n42\n00:02:50,430 --> 00:02:57,040\nAnd imagine even that this\ncompany is formed by merging a\n\n43\n00:02:57,040 --> 00:02:59,450\nwhole bunch of companies that\nalready have their personnel\n\n44\n00:02:59,450 --> 00:03:00,700\nrecord system set up.\n\n45\n00:03:00,700 --> 00:03:03,250\n\n\n46\n00:03:03,250 --> 00:03:06,570\nAnd imagine that once these\ndivisions are all linked in\n\n47\n00:03:06,570 --> 00:03:08,530\nsome kind of very sophisticated\nsatellite\n\n48\n00:03:08,530 --> 00:03:12,240\nnetwork, and all these databases\nare put together.\n\n49\n00:03:12,240 --> 00:03:17,260\nAnd what you'd like to do is,\nfrom any place in the company,\n\n50\n00:03:17,260 --> 00:03:23,130\nto be able to say things like,\noh, what's the name in a\n\n51\n00:03:23,130 --> 00:03:26,400\npersonnel record?\n\n52\n00:03:26,400 --> 00:03:30,540\nOr, what's the job description\nin a personnel record?\n\n53\n00:03:30,540 --> 00:03:34,840\nAnd not have to worry about the\nfact that each division\n\n54\n00:03:34,840 --> 00:03:36,760\nobviously is going to have\ncompletely separate\n\n55\n00:03:36,760 --> 00:03:41,580\nconventions for how you might\nimplement these records.\n\n56\n00:03:41,580 --> 00:03:44,960\nFrom this point you don't\nwant to know about that.\n\n57\n00:03:44,960 --> 00:03:48,430\nWell how could you\npossibly do that?\n\n58\n00:03:48,430 --> 00:03:52,640\nOne way, of course, is to send\ndown an edict from somewhere\n\n59\n00:03:52,640 --> 00:03:56,290\nthat everybody has to change\ntheir format to some fixed\n\n60\n00:03:56,290 --> 00:03:58,070\ncompatible thing.\n\n61\n00:03:58,070 --> 00:04:01,820\nThat's what people often try,\nand of course it never works.\n\n62\n00:04:01,820 --> 00:04:07,340\nAnother thing that you might\nwant to do is somehow arrange\n\n63\n00:04:07,340 --> 00:04:11,250\nit so you can have these\nvertical barriers.\n\n64\n00:04:11,250 --> 00:04:14,430\nSo that when you ask for the\nname of a personnel record,\n\n65\n00:04:14,430 --> 00:04:17,970\nsomehow, whatever format it\nhappens to be, name will\n\n66\n00:04:17,970 --> 00:04:19,470\nfigure out how to do\nthe right thing.\n\n67\n00:04:19,470 --> 00:04:22,730\n\n\n68\n00:04:22,730 --> 00:04:26,260\nWe want name to be, so-called,\na generic operator.\n\n69\n00:04:26,260 --> 00:04:30,060\nGeneric operator means what it\nsort of precisely does depends\n\n70\n00:04:30,060 --> 00:04:33,650\non the kind of data that\nit's looking at.\n\n71\n00:04:33,650 --> 00:04:37,100\nMore than that, you'd like to\ndesign the system so that the\n\n72\n00:04:37,100 --> 00:04:43,250\nnext time a new division comes\ninto the company they don't\n\n73\n00:04:43,250 --> 00:04:45,640\nhave to make any big changes in\nwhat they're already doing\n\n74\n00:04:45,640 --> 00:04:50,110\nto link into this system, and\nthe rest of the company\n\n75\n00:04:50,110 --> 00:04:53,500\ndoesn't have to make any big\nchanges to admit their stuff\n\n76\n00:04:53,500 --> 00:04:55,520\nto the system.\n\n77\n00:04:55,520 --> 00:04:58,700\nSo that's the problem you should\nbe thinking about.\n\n78\n00:04:58,700 --> 00:05:00,770\nLike it's sort of\njust your work.\n\n79\n00:05:00,770 --> 00:05:02,390\nYou want to be able to\ninclude new things by\n\n80\n00:05:02,390 --> 00:05:03,640\nmaking minimal changes.\n\n81\n00:05:03,640 --> 00:05:05,980\n\n\n82\n00:05:05,980 --> 00:05:07,340\nOK, well that's the problem\nthat we'll be\n\n83\n00:05:07,340 --> 00:05:09,440\ntalking about today.\n\n84\n00:05:09,440 --> 00:05:13,140\nAnd you should have this sort\nof distributed personnel\n\n85\n00:05:13,140 --> 00:05:14,240\nrecord system in your mind.\n\n86\n00:05:14,240 --> 00:05:16,620\nBut actually the one I'll be\ntalking about is a problem\n\n87\n00:05:16,620 --> 00:05:18,900\nthat's a little bit more\nself-contained than that.\n\n88\n00:05:18,900 --> 00:05:21,870\nthat'll bring up the issues,\nI think, more clearly.\n\n89\n00:05:21,870 --> 00:05:25,300\nThat's the problem of doing a\nsystem that does arithmetic on\n\n90\n00:05:25,300 --> 00:05:27,770\ncomplex numbers.\n\n91\n00:05:27,770 --> 00:05:30,690\nSo let's take a look here.\n\n92\n00:05:30,690 --> 00:05:32,460\nJust as a little review,\nthere are things\n\n93\n00:05:32,460 --> 00:05:35,250\ncalled complex numbers.\n\n94\n00:05:35,250 --> 00:05:36,960\nComplex number you can think\nof as a point in\n\n95\n00:05:36,960 --> 00:05:39,370\nthe plane, or z.\n\n96\n00:05:39,370 --> 00:05:46,230\nAnd you can represent a point\neither by its real-part and\n\n97\n00:05:46,230 --> 00:05:47,190\nits imaginary-part.\n\n98\n00:05:47,190 --> 00:05:51,690\nSo if this is z and its\nreal-part is this much, and\n\n99\n00:05:51,690 --> 00:05:54,880\nits imaginary-part is that\nmuch, and you write z\n\n100\n00:05:54,880 --> 00:05:56,130\nequals x plus iy.\n\n101\n00:05:56,130 --> 00:05:59,110\n\n\n102\n00:05:59,110 --> 00:06:03,210\nOr another way to represent a\ncomplex number is by saying,\n\n103\n00:06:03,210 --> 00:06:10,900\nwhat's the distance from the\norigin, and what's the angle?\n\n104\n00:06:10,900 --> 00:06:13,540\nSo that represents a complex\nnumber as its\n\n105\n00:06:13,540 --> 00:06:16,670\nradius times an angle.\n\n106\n00:06:16,670 --> 00:06:19,520\n\n\n107\n00:06:19,520 --> 00:06:20,820\nThis one's called-- the\noriginal one's called\n\n108\n00:06:20,820 --> 00:06:24,690\nrectangular form, rectangular\nrepresentation, real- and\n\n109\n00:06:24,690 --> 00:06:28,640\nimaginary-part, or polar\nrepresentation.\n\n110\n00:06:28,640 --> 00:06:30,040\nMagnitude and angle--\n\n111\n00:06:30,040 --> 00:06:32,260\nand if you know the real- and\nimaginary-part, you can figure\n\n112\n00:06:32,260 --> 00:06:33,720\nout the magnitude and angle.\n\n113\n00:06:33,720 --> 00:06:37,190\nIf you know x and y, you can\nget r by this formula.\n\n114\n00:06:37,190 --> 00:06:39,480\nSquare root of sum of the\nsquares, and you can get the\n\n115\n00:06:39,480 --> 00:06:41,420\nangle as an arctangent.\n\n116\n00:06:41,420 --> 00:06:44,420\nOr conversely, if you knew\nr and A you could\n\n117\n00:06:44,420 --> 00:06:45,800\nfigure out x and y.\n\n118\n00:06:45,800 --> 00:06:49,435\nx is r times the cosine of A,\nand y is r times the sine of\n\n119\n00:06:49,435 --> 00:06:52,490\nA. All right, so there's\nthese two.\n\n120\n00:06:52,490 --> 00:06:54,130\nThey're complex numbers.\n\n121\n00:06:54,130 --> 00:06:55,810\nYou can think of them\neither in polar form\n\n122\n00:06:55,810 --> 00:06:57,150\nor rectangular form.\n\n123\n00:06:57,150 --> 00:06:59,830\nWhat we would like to do is\nmake a system that does\n\n124\n00:06:59,830 --> 00:07:03,850\narithmetic on complex numbers.\n\n125\n00:07:03,850 --> 00:07:05,580\nIn other words, what\nwe'd like--\n\n126\n00:07:05,580 --> 00:07:07,380\njust like the rational\nnumber example--\n\n127\n00:07:07,380 --> 00:07:11,120\nis to have some operations plus\nc, which is going to take\n\n128\n00:07:11,120 --> 00:07:14,640\ntwo complex numbers and add\nthem, subtract them, and\n\n129\n00:07:14,640 --> 00:07:16,910\nmultiply them, and\ndivide them.\n\n130\n00:07:16,910 --> 00:07:20,730\n\n\n131\n00:07:20,730 --> 00:07:25,280\nOK, well there's little bit\nof mathematics behind it.\n\n132\n00:07:25,280 --> 00:07:29,800\nWhat are the actual formulas for\nmanipulating such things?\n\n133\n00:07:29,800 --> 00:07:34,270\nAnd it's sort of not important\nwhere they come from, but just\n\n134\n00:07:34,270 --> 00:07:36,120\nas an implementer let's see--\n\n135\n00:07:36,120 --> 00:07:40,030\nif you want to add two complex\nnumbers it's pretty easy to\n\n136\n00:07:40,030 --> 00:07:42,660\nget its real-part and\nits imaginary-part.\n\n137\n00:07:42,660 --> 00:07:47,810\nThe real-part of the sum of\ntwo complex numbers, the\n\n138\n00:07:47,810 --> 00:07:53,720\nreal-part of the z1 plus z2 is\nthe real-part of z1 plus the\n\n139\n00:07:53,720 --> 00:07:54,970\nreal-part of z2.\n\n140\n00:07:54,970 --> 00:07:57,820\n\n\n141\n00:07:57,820 --> 00:08:02,770\nAnd the imaginary-part of z1\nplus z2 is the imaginary part\n\n142\n00:08:02,770 --> 00:08:07,410\nof z1 plus the imaginary\npart of z2.\n\n143\n00:08:07,410 --> 00:08:09,480\nSo it's pretty easy to\nadd complex numbers.\n\n144\n00:08:09,480 --> 00:08:12,320\nYou just add the corresponding\nparts and make a new complex\n\n145\n00:08:12,320 --> 00:08:13,400\nnumber with those parts.\n\n146\n00:08:13,400 --> 00:08:17,180\nIf you want to multiply them,\nit's kind of nice to do it in\n\n147\n00:08:17,180 --> 00:08:17,840\npolar form.\n\n148\n00:08:17,840 --> 00:08:21,810\nBecause if you have two complex\nnumbers, the magnitude\n\n149\n00:08:21,810 --> 00:08:26,285\nof their product is here, the\nproduct of the magnitudes.\n\n150\n00:08:26,285 --> 00:08:28,850\n\n\n151\n00:08:28,850 --> 00:08:35,809\nAnd the angle of the product\nis the sum of the angles.\n\n152\n00:08:35,809 --> 00:08:39,179\nSo that's sort of mathematics\nthat allows you to do\n\n153\n00:08:39,179 --> 00:08:40,549\narithmetic on complex numbers.\n\n154\n00:08:40,549 --> 00:08:43,720\nLet's actually think about\nthe implementation.\n\n155\n00:08:43,720 --> 00:08:49,330\nWell we do it just like\nrational numbers.\n\n156\n00:08:49,330 --> 00:08:52,200\nWe come down, we assume\nwe have some\n\n157\n00:08:52,200 --> 00:08:53,840\nconstructors and selectors.\n\n158\n00:08:53,840 --> 00:08:55,330\nWhat would we like?\n\n159\n00:08:55,330 --> 00:08:58,890\nWell let's assume that we make\na data object cloud, which is\n\n160\n00:08:58,890 --> 00:09:02,510\na complex number that has some\nstuff in it, and that we can\n\n161\n00:09:02,510 --> 00:09:05,870\nget out from a complex number\nthe real-part, or the\n\n162\n00:09:05,870 --> 00:09:12,150\nimaginary-part, or the\nmagnitude, or the angle.\n\n163\n00:09:12,150 --> 00:09:14,320\nWe want some ways of making\ncomplex numbers-- not only\n\n164\n00:09:14,320 --> 00:09:16,800\nselectors, but constructors.\n\n165\n00:09:16,800 --> 00:09:20,160\nSo we'll assume we have a thing\ncalled make-rectangular.\n\n166\n00:09:20,160 --> 00:09:24,510\nWhat make-rectangular is going\nto do is take a real-part and\n\n167\n00:09:24,510 --> 00:09:28,610\nan imaginary-part and construct\na complex number\n\n168\n00:09:28,610 --> 00:09:31,920\nwith those parts.\n\n169\n00:09:31,920 --> 00:09:35,010\nSimilarly, we can have\nmake-polar which will take a\n\n170\n00:09:35,010 --> 00:09:42,550\nmagnitude and an angle, and\nconstruct a complex number\n\n171\n00:09:42,550 --> 00:09:44,680\nwhich has that magnitude\nand angle.\n\n172\n00:09:44,680 --> 00:09:45,460\nSo here's a system.\n\n173\n00:09:45,460 --> 00:09:48,910\nWe'll have two constructors\nand four selectors.\n\n174\n00:09:48,910 --> 00:09:55,150\nAnd now, just like before, in\nterms of that abstract data\n\n175\n00:09:55,150 --> 00:09:59,220\nwe'll go ahead and implement our\ncomplex number operations.\n\n176\n00:09:59,220 --> 00:10:03,280\nAnd here you can see translated\ninto Lisp code just\n\n177\n00:10:03,280 --> 00:10:08,330\nthe arithmetic formulas\nI put down before.\n\n178\n00:10:08,330 --> 00:10:13,450\nIf I want to add two complex\nnumbers I will make a complex\n\n179\n00:10:13,450 --> 00:10:16,630\nnumber out of its real-\nand imaginary-parts.\n\n180\n00:10:16,630 --> 00:10:19,680\nThe real part of the complex\nnumber I'm going to make is\n\n181\n00:10:19,680 --> 00:10:23,310\nthe sum of the real-parts.\n\n182\n00:10:23,310 --> 00:10:25,250\nThe imaginary part of the\ncomplex number I'm going to\n\n183\n00:10:25,250 --> 00:10:27,005\nmake is the sum of the\nimaginary-parts.\n\n184\n00:10:27,005 --> 00:10:30,310\n\n\n185\n00:10:30,310 --> 00:10:31,990\nI put those together, make\na complex number.\n\n186\n00:10:31,990 --> 00:10:35,780\nThat's how I implement complex\nnumber addition.\n\n187\n00:10:35,780 --> 00:10:39,650\nSubtraction is essentially\nthe same.\n\n188\n00:10:39,650 --> 00:10:45,140\nAll I do is subtract the parts\nrather than add them.\n\n189\n00:10:45,140 --> 00:10:47,980\nTo multiply two complex\nnumbers, I\n\n190\n00:10:47,980 --> 00:10:49,270\nuse the other formula.\n\n191\n00:10:49,270 --> 00:10:55,350\nI'll make a complex number out\nof a magnitude and angle.\n\n192\n00:10:55,350 --> 00:10:58,740\nThe magnitude is going to be the\nproduct of the magnitudes\n\n193\n00:10:58,740 --> 00:11:00,465\nof the two complex numbers\nI'm multiplying.\n\n194\n00:11:00,465 --> 00:11:03,710\n\n\n195\n00:11:03,710 --> 00:11:06,980\nAnd the angle is going to be the\nsum of the angles of the\n\n196\n00:11:06,980 --> 00:11:09,620\ntwo complex numbers\nI'm multiplying.\n\n197\n00:11:09,620 --> 00:11:11,230\nSo there's multiplication.\n\n198\n00:11:11,230 --> 00:11:17,370\nAnd then division, division\nis almost the same.\n\n199\n00:11:17,370 --> 00:11:19,660\nHere I divide the magnitudes\nand subtract the angles.\n\n200\n00:11:19,660 --> 00:11:28,640\n\n\n201\n00:11:28,640 --> 00:11:31,870\nNow I've implemented\nthe operations.\n\n202\n00:11:31,870 --> 00:11:33,640\nAnd what do we do?\n\n203\n00:11:33,640 --> 00:11:36,060\nWe call on George.\n\n204\n00:11:36,060 --> 00:11:38,070\nWe've done the use, let's\nworry about the\n\n205\n00:11:38,070 --> 00:11:38,800\nrepresentation.\n\n206\n00:11:38,800 --> 00:11:42,200\nWe'll call on George and say to\nGeorge, go ahead and build\n\n207\n00:11:42,200 --> 00:11:45,250\nus a complex number\nrepresentation.\n\n208\n00:11:45,250 --> 00:11:47,770\nWell that's fine.\n\n209\n00:11:47,770 --> 00:11:52,660\nGeorge can say, we'll implement\na complex number\n\n210\n00:11:52,660 --> 00:11:56,400\nsimply as a pair that has\nthe real-part and the\n\n211\n00:11:56,400 --> 00:11:57,200\nimaginary-part.\n\n212\n00:11:57,200 --> 00:12:01,020\nSo if I want to make a complex\nnumber with a certain\n\n213\n00:12:01,020 --> 00:12:03,860\nreal-part and an imaginary-part,\nI'll just use\n\n214\n00:12:03,860 --> 00:12:06,640\ncons to form a pair, and that\nwill-- that's George's\n\n215\n00:12:06,640 --> 00:12:09,780\nrepresentation of a\ncomplex number.\n\n216\n00:12:09,780 --> 00:12:12,420\nSo if I want to get out the\nreal-part of something, I just\n\n217\n00:12:12,420 --> 00:12:14,350\nextract the car,\nthe first part.\n\n218\n00:12:14,350 --> 00:12:16,300\nIf I want to get the\nimaginary-part, I extract the\n\n219\n00:12:16,300 --> 00:12:22,220\ncdr. How do I deal with the\nmagnitude and angle?\n\n220\n00:12:22,220 --> 00:12:25,550\nWell if I want to extract the\nmagnitude of one of these\n\n221\n00:12:25,550 --> 00:12:28,895\nthings, I get the square root\nof the sum of the square of\n\n222\n00:12:28,895 --> 00:12:34,310\nthe car plus the square of the\ncdr. If I want to get the\n\n223\n00:12:34,310 --> 00:12:37,660\nangle, I compute the\narctangent of\n\n224\n00:12:37,660 --> 00:12:39,530\nthe cdr in the car.\n\n225\n00:12:39,530 --> 00:12:42,300\nThis is a list procedure for\ncomputing arctangent.\n\n226\n00:12:42,300 --> 00:12:44,970\n\n\n227\n00:12:44,970 --> 00:12:49,150\nAnd if somebody hands me a\nmagnitude and an angle and\n\n228\n00:12:49,150 --> 00:12:51,670\nsays, make me a complex number,\nwell I compute the\n\n229\n00:12:51,670 --> 00:12:54,280\nreal-part and the\nimaginary-part, or our cosine\n\n230\n00:12:54,280 --> 00:12:58,120\nof a and our sine of\na, and stick them\n\n231\n00:12:58,120 --> 00:13:01,460\ntogether into a pair.\n\n232\n00:13:01,460 --> 00:13:02,260\nOK so we're done.\n\n233\n00:13:02,260 --> 00:13:07,830\nIn fact, what I just did,\nconceptually, is absolutely no\n\n234\n00:13:07,830 --> 00:13:11,710\ndifferent from the rational\nnumber representation that we\n\n235\n00:13:11,710 --> 00:13:12,510\nlooked at last time.\n\n236\n00:13:12,510 --> 00:13:13,910\nIt's the same sort of idea.\n\n237\n00:13:13,910 --> 00:13:18,070\nYou implement the operators,\nyou pick a representation.\n\n238\n00:13:18,070 --> 00:13:20,070\nNothing different.\n\n239\n00:13:20,070 --> 00:13:23,210\nNow let's worry about Martha.\n\n240\n00:13:23,210 --> 00:13:26,670\nSee, Martha has a\ndifferent idea.\n\n241\n00:13:26,670 --> 00:13:29,490\nShe doesn't want to represent a\ncomplex number as a pair of\n\n242\n00:13:29,490 --> 00:13:30,900\na real-part and an\nimaginary-part.\n\n243\n00:13:30,900 --> 00:13:34,170\nWhat she would like to do is\nrepresent a complex number as\n\n244\n00:13:34,170 --> 00:13:39,550\na pair of a magnitude\nand an angle.\n\n245\n00:13:39,550 --> 00:13:42,130\nSo if instead of calling up\nGeorge we ask Martha to design\n\n246\n00:13:42,130 --> 00:13:44,570\nour representation, we get\nsomething like this.\n\n247\n00:13:44,570 --> 00:13:47,160\nWe get make-polar.\n\n248\n00:13:47,160 --> 00:13:50,220\nSure, if I give you a magnitude\nand an angle we're\n\n249\n00:13:50,220 --> 00:13:55,430\njust going to form a pair that\nhas magnitude and angle.\n\n250\n00:13:55,430 --> 00:13:57,680\nIf you want to extract the\nmagnitude, that's easy.\n\n251\n00:13:57,680 --> 00:13:59,780\nYou just pull out the\ncar or the pair.\n\n252\n00:13:59,780 --> 00:14:02,670\nIf you want to extract the\nangle, sure, that's easy.\n\n253\n00:14:02,670 --> 00:14:05,480\nYou just pull out the cdr.\nIf you want to look for\n\n254\n00:14:05,480 --> 00:14:07,660\nreal-parts and imaginary-parts,\nwell then you\n\n255\n00:14:07,660 --> 00:14:08,590\nhave to do some work.\n\n256\n00:14:08,590 --> 00:14:14,580\nIf you want the real-part, you\nhave to get r cosine a.\n\n257\n00:14:14,580 --> 00:14:19,990\nIn other words, r, the car of\nthe pair, times the cosine of\n\n258\n00:14:19,990 --> 00:14:20,910\nthe cdr of the pair.\n\n259\n00:14:20,910 --> 00:14:26,230\nSo this is r times\nthe cosine of a,\n\n260\n00:14:26,230 --> 00:14:28,330\nand that's the real-part.\n\n261\n00:14:28,330 --> 00:14:30,810\nIf you want to get the\nimaginary-part, it's r times\n\n262\n00:14:30,810 --> 00:14:32,660\nthe sine of a.\n\n263\n00:14:32,660 --> 00:14:37,930\nAnd if I hand you a real-part\nand an imaginary-part and say,\n\n264\n00:14:37,930 --> 00:14:42,030\nmake me a complex number\nwith that real-part and\n\n265\n00:14:42,030 --> 00:14:44,170\nimaginary-part, well I figure\nout what the magnitude and\n\n266\n00:14:44,170 --> 00:14:45,540\nangle should be.\n\n267\n00:14:45,540 --> 00:14:48,090\nThe magnitude's the square root\nof the sum of the squares\n\n268\n00:14:48,090 --> 00:14:49,230\nand the angle's the\narctangent.\n\n269\n00:14:49,230 --> 00:14:52,090\nI put those together\nto make a pair.\n\n270\n00:14:52,090 --> 00:14:54,170\nSo there's Martha's idea.\n\n271\n00:14:54,170 --> 00:14:56,690\n\n\n272\n00:14:56,690 --> 00:14:59,680\nWell which is better?\n\n273\n00:14:59,680 --> 00:15:02,850\nWell if you're doing a lot of\nadditions, probably George's\n\n274\n00:15:02,850 --> 00:15:04,810\nis better, because you're doing\na lot of real-parts and\n\n275\n00:15:04,810 --> 00:15:05,850\nimaginary-parts.\n\n276\n00:15:05,850 --> 00:15:07,920\nIf mostly you're going to be\ndoing multiplications and\n\n277\n00:15:07,920 --> 00:15:11,140\ndivisions, then maybe Martha's\nidea is better.\n\n278\n00:15:11,140 --> 00:15:16,590\nOr maybe, and this is the real\npoint, you can't decide.\n\n279\n00:15:16,590 --> 00:15:21,170\nOr maybe you just have to let\nthem both hang around, for\n\n280\n00:15:21,170 --> 00:15:23,480\npersonality reasons.\n\n281\n00:15:23,480 --> 00:15:25,870\nMaybe you just really\ncan't ever decide\n\n282\n00:15:25,870 --> 00:15:28,560\nwhat you would like.\n\n283\n00:15:28,560 --> 00:15:31,520\nAnd again, what we would really\nlike is a system that\n\n284\n00:15:31,520 --> 00:15:32,320\nlooks like this.\n\n285\n00:15:32,320 --> 00:15:37,090\nThat somehow there's George\nover here, who has built\n\n286\n00:15:37,090 --> 00:15:41,470\nrectangular complex numbers.\n\n287\n00:15:41,470 --> 00:15:46,120\nAnd Martha, who has polar\ncomplex numbers.\n\n288\n00:15:46,120 --> 00:15:54,200\nAnd somehow we have operations\nthat can add, and subtract,\n\n289\n00:15:54,200 --> 00:15:59,710\nand multiply, and divide, and it\nshouldn't matter that there\n\n290\n00:15:59,710 --> 00:16:02,790\nare two incompatible\nrepresentations of complex\n\n291\n00:16:02,790 --> 00:16:04,410\nnumbers floating around\nthis system.\n\n292\n00:16:04,410 --> 00:16:09,640\nIn other words, not only like\nan abstraction barrier here\n\n293\n00:16:09,640 --> 00:16:15,770\nthat has things in it like\na real-part, and an\n\n294\n00:16:15,770 --> 00:16:23,830\nimaginary-part, and magnitude,\nand angle.\n\n295\n00:16:23,830 --> 00:16:26,850\nSo not only is there an\nabstraction barrier that hides\n\n296\n00:16:26,850 --> 00:16:30,310\nthe actual representation from\nus, but also there's some kind\n\n297\n00:16:30,310 --> 00:16:33,620\nof vertical barrier here that\nallows both of these\n\n298\n00:16:33,620 --> 00:16:36,270\nrepresentations to\nexist without\n\n299\n00:16:36,270 --> 00:16:38,570\ninterfering with each other.\n\n300\n00:16:38,570 --> 00:16:41,900\nThe idea is that the\nthings in here--\n\n301\n00:16:41,900 --> 00:16:44,120\nreal-part, imaginary-part,\nmagnitude, and angle--\n\n302\n00:16:44,120 --> 00:16:47,310\nwill be generic operators.\n\n303\n00:16:47,310 --> 00:16:50,190\nIf you ask for the real-part,\nit will worry about what\n\n304\n00:16:50,190 --> 00:16:53,880\nrepresentation it's\nlooking at.\n\n305\n00:16:53,880 --> 00:16:56,840\nOK, well how can we do that?\n\n306\n00:16:56,840 --> 00:17:00,290\nThere's actually a really\nobvious idea, if you're used\n\n307\n00:17:00,290 --> 00:17:02,770\nto thinking about\ncomplex numbers.\n\n308\n00:17:02,770 --> 00:17:06,390\nIf you're used to thinking\nabout compound data.\n\n309\n00:17:06,390 --> 00:17:10,690\nSee, suppose you could just tell\nby looking at a complex\n\n310\n00:17:10,690 --> 00:17:13,190\nnumber whether it\nwas constructed\n\n311\n00:17:13,190 --> 00:17:15,790\nby George or Martha.\n\n312\n00:17:15,790 --> 00:17:18,900\nIn other words, so it's not that\nwhat's floating around\n\n313\n00:17:18,900 --> 00:17:20,910\nhere are ordinary, just complex\nnumbers, right?\n\n314\n00:17:20,910 --> 00:17:24,390\nThey're fancy, designer\ncomplex numbers.\n\n315\n00:17:24,390 --> 00:17:27,260\nSo you look at a complex numbers\nas it's not just a\n\n316\n00:17:27,260 --> 00:17:29,190\ncomplex number, it's got a label\non it that says, this\n\n317\n00:17:29,190 --> 00:17:31,450\none is by Martha.\n\n318\n00:17:31,450 --> 00:17:34,480\nOr this is a complex\nnumber by George.\n\n319\n00:17:34,480 --> 00:17:34,700\nRight?\n\n320\n00:17:34,700 --> 00:17:36,860\nThey're signed.\n\n321\n00:17:36,860 --> 00:17:40,155\nSee, and then whenever we looked\nat a complex number we\n\n322\n00:17:40,155 --> 00:17:45,800\ncould just read the label, and\nthen we'd know how you expect\n\n323\n00:17:45,800 --> 00:17:48,030\nto operate on that.\n\n324\n00:17:48,030 --> 00:17:49,850\nIn other words, what\nwe want is not just\n\n325\n00:17:49,850 --> 00:17:51,190\nordinary data objects.\n\n326\n00:17:51,190 --> 00:17:53,120\nWe want to introduce the\nnotion of what's\n\n327\n00:17:53,120 --> 00:17:54,370\ncalled typed data.\n\n328\n00:17:54,370 --> 00:17:59,760\n\n\n329\n00:17:59,760 --> 00:18:03,940\nTyped data means, again, there's\nsome sort of cloud.\n\n330\n00:18:03,940 --> 00:18:08,930\nAnd what it's got in it is an\nordinary data object like\n\n331\n00:18:08,930 --> 00:18:10,180\nwe've been thinking about.\n\n332\n00:18:10,180 --> 00:18:13,180\n\n\n333\n00:18:13,180 --> 00:18:16,540\nPulled out the contents, sort\nof the actual data.\n\n334\n00:18:16,540 --> 00:18:19,320\n\n\n335\n00:18:19,320 --> 00:18:24,220\nBut also a thing called a\ntype, but it's signed by\n\n336\n00:18:24,220 --> 00:18:25,850\neither George or Martha.\n\n337\n00:18:25,850 --> 00:18:28,340\nSo we're going to go from\nregular data to type data.\n\n338\n00:18:28,340 --> 00:18:31,950\n\n\n339\n00:18:31,950 --> 00:18:32,710\nHow do we build that?\n\n340\n00:18:32,710 --> 00:18:33,990\nWell that's easy.\n\n341\n00:18:33,990 --> 00:18:34,980\nWe know how to build clouds.\n\n342\n00:18:34,980 --> 00:18:37,920\nWe build them out of pairs.\n\n343\n00:18:37,920 --> 00:18:41,050\nSo here's a little\nrepresentation that supports\n\n344\n00:18:41,050 --> 00:18:43,510\ntyped data.\n\n345\n00:18:43,510 --> 00:18:49,020\nThere's a thing called take a\ntype and attach it to a piece\n\n346\n00:18:49,020 --> 00:18:51,530\nof contents, and we\njust use cons.\n\n347\n00:18:51,530 --> 00:18:53,770\nAnd if we have a piece of typed\ndata, we can look at the\n\n348\n00:18:53,770 --> 00:18:56,290\ntype, which is the car.\n\n349\n00:18:56,290 --> 00:19:00,460\nWe can look at the contents,\nwhich is the cdr. Now along\n\n350\n00:19:00,460 --> 00:19:05,420\nwith that, the way we use our\ntype data will test, when\n\n351\n00:19:05,420 --> 00:19:07,520\nwe're given a piece of data,\nwhat type it is.\n\n352\n00:19:07,520 --> 00:19:10,510\nSo we have some type\npredicates with us.\n\n353\n00:19:10,510 --> 00:19:13,730\nFor example, to see whether\na complex number is one of\n\n354\n00:19:13,730 --> 00:19:16,860\nGeorge's, whether it's\nrectangular, we just check to\n\n355\n00:19:16,860 --> 00:19:23,850\nsee if the type of that is the\nsymbol rectangular, right?\n\n356\n00:19:23,850 --> 00:19:25,100\nThe symbol rectangular.\n\n357\n00:19:25,100 --> 00:19:27,200\n\n\n358\n00:19:27,200 --> 00:19:30,650\nAnd to check whether a complex\nnumber is one of Martha's, we\n\n359\n00:19:30,650 --> 00:19:33,430\ncheck to see whether the type\nis the symbol polar.\n\n360\n00:19:33,430 --> 00:19:36,460\n\n\n361\n00:19:36,460 --> 00:19:38,710\nSo that's a way to test\nwhat kind of number\n\n362\n00:19:38,710 --> 00:19:40,350\nwe're looking at.\n\n363\n00:19:40,350 --> 00:19:42,070\nNow let's think about\nhow we can use that\n\n364\n00:19:42,070 --> 00:19:43,870\nto build the system.\n\n365\n00:19:43,870 --> 00:19:46,170\nSo let's suppose that George\nand Martha were off working\n\n366\n00:19:46,170 --> 00:19:50,710\nseparately, and each of them\nhad designed their complex\n\n367\n00:19:50,710 --> 00:19:52,640\nnumber representation\npackages.\n\n368\n00:19:52,640 --> 00:19:58,980\nWhat do they have to do to\nbecome part of the system, to\n\n369\n00:19:58,980 --> 00:20:00,140\nexist compatibly?\n\n370\n00:20:00,140 --> 00:20:02,860\nWell it's really pretty easy.\n\n371\n00:20:02,860 --> 00:20:05,970\nRemember, George had\nthis package.\n\n372\n00:20:05,970 --> 00:20:08,980\nHere's George's original\npackage, or half of it.\n\n373\n00:20:08,980 --> 00:20:12,090\nAnd underlined in red are the\nchanges he has to make.\n\n374\n00:20:12,090 --> 00:20:16,010\nSo before, when George made a\ncomplex number out of an x and\n\n375\n00:20:16,010 --> 00:20:20,930\ny, he just put them together\nto make a pair.\n\n376\n00:20:20,930 --> 00:20:24,090\nAnd the only difference is\nthat now he signs them.\n\n377\n00:20:24,090 --> 00:20:26,920\nHe attaches the type,\nwhich is the symbol\n\n378\n00:20:26,920 --> 00:20:30,600\nrectangular to that pair.\n\n379\n00:20:30,600 --> 00:20:33,920\nEverything else George does\nis the same, except that--\n\n380\n00:20:33,920 --> 00:20:35,970\nsee, George and Martha both\nhave procedures named\n\n381\n00:20:35,970 --> 00:20:38,700\nreal-part and imaginary-part.\n\n382\n00:20:38,700 --> 00:20:44,220\nSo to allow them both to exist\nin the same Lisp environment,\n\n383\n00:20:44,220 --> 00:20:45,920\nGeorge had changed the names\nof his procedures.\n\n384\n00:20:45,920 --> 00:20:49,045\nSo we'll say, this is George's\nreal-part procedure.\n\n385\n00:20:49,045 --> 00:20:52,710\nIt's the real-part rectangular\nprocedure, the imaginary-part\n\n386\n00:20:52,710 --> 00:20:55,170\nrectangular procedure.\n\n387\n00:20:55,170 --> 00:20:59,130\nAnd then here's the rest\nof George's package.\n\n388\n00:20:59,130 --> 00:21:02,060\nHe'd had magnitude and angle,\njust renames them magnitude\n\n389\n00:21:02,060 --> 00:21:05,702\nrectangular and angle\nrectangular.\n\n390\n00:21:05,702 --> 00:21:09,860\nAnd Martha has to do basically\nthe same thing.\n\n391\n00:21:09,860 --> 00:21:15,200\nMartha previously, when she made\na complex number out of a\n\n392\n00:21:15,200 --> 00:21:19,270\nmagnitude and angle,\nshe just cons them.\n\n393\n00:21:19,270 --> 00:21:25,330\nNow she attaches the type polar,\nand she changes the\n\n394\n00:21:25,330 --> 00:21:28,100\nname so her real-part procedure\nwon't conflict in\n\n395\n00:21:28,100 --> 00:21:30,710\nname with George's.\n\n396\n00:21:30,710 --> 00:21:34,540\nIt's a real-part-polar,\nimaginary-part-polar,\n\n397\n00:21:34,540 --> 00:21:38,060\nmagnitude polar, and\nangle polar.\n\n398\n00:21:38,060 --> 00:21:45,000\n\n\n399\n00:21:45,000 --> 00:21:46,130\nNow we have the system.\n\n400\n00:21:46,130 --> 00:21:49,160\nRight there's George\nand Martha.\n\n401\n00:21:49,160 --> 00:21:51,050\nAnd now we've got to get some\nkind of manager to look at\n\n402\n00:21:51,050 --> 00:21:52,300\nthese types.\n\n403\n00:21:52,300 --> 00:21:55,050\n\n\n404\n00:21:55,050 --> 00:21:57,530\nHow are these things actually\ngoing to work now that George\n\n405\n00:21:57,530 --> 00:22:00,530\nand Martha have supplied\nus with typed data?\n\n406\n00:22:00,530 --> 00:22:05,260\nWell what we have are a bunch\nof generic selectors.\n\n407\n00:22:05,260 --> 00:22:07,800\nGeneric selectors for complex\nnumbers real-part,\n\n408\n00:22:07,800 --> 00:22:10,630\nimaginary-part, magnitude,\nand angle.\n\n409\n00:22:10,630 --> 00:22:14,140\n\n\n410\n00:22:14,140 --> 00:22:15,410\nLet's look at them\nmore closely.\n\n411\n00:22:15,410 --> 00:22:17,930\n\n\n412\n00:22:17,930 --> 00:22:19,310\nWhat does a real-part do?\n\n413\n00:22:19,310 --> 00:22:24,070\nIf I ask for the real part\nof a complex number,\n\n414\n00:22:24,070 --> 00:22:25,800\nwell I look at it.\n\n415\n00:22:25,800 --> 00:22:26,690\nI look at its type.\n\n416\n00:22:26,690 --> 00:22:27,940\nI say, is it rectangular?\n\n417\n00:22:27,940 --> 00:22:31,020\n\n\n418\n00:22:31,020 --> 00:22:36,970\nIf so, I apply George's real\npart procedure to the contents\n\n419\n00:22:36,970 --> 00:22:38,220\nof that complex number.\n\n420\n00:22:38,220 --> 00:22:41,230\n\n\n421\n00:22:41,230 --> 00:22:43,720\nThis is a number that\nhas a type on it.\n\n422\n00:22:43,720 --> 00:22:46,340\nI strip off the type\nusing contents and\n\n423\n00:22:46,340 --> 00:22:47,590\napply George's procedure.\n\n424\n00:22:47,590 --> 00:22:50,700\n\n\n425\n00:22:50,700 --> 00:22:53,950\nOr is this a polar\ncomplex number?\n\n426\n00:22:53,950 --> 00:22:56,890\nIf I want the real part, I\napply Martha's real part\n\n427\n00:22:56,890 --> 00:22:59,850\nprocedure to the contents\nof that number.\n\n428\n00:22:59,850 --> 00:23:02,260\nSo that's how real part works.\n\n429\n00:23:02,260 --> 00:23:04,670\nAnd then similarly there's\nimaginary-part, which is\n\n430\n00:23:04,670 --> 00:23:06,770\nalmost the same.\n\n431\n00:23:06,770 --> 00:23:09,600\nIt looks at the number and\nif it's rectangular, uses\n\n432\n00:23:09,600 --> 00:23:11,130\nGeorge's imaginary-part\nprocedure.\n\n433\n00:23:11,130 --> 00:23:13,380\nIf it's polar, uses Martha's.\n\n434\n00:23:13,380 --> 00:23:17,240\nAnd then there's a magnitude\nand an angle.\n\n435\n00:23:17,240 --> 00:23:19,880\n\n\n436\n00:23:19,880 --> 00:23:21,130\nSo there's a system.\n\n437\n00:23:21,130 --> 00:23:23,460\n\n\n438\n00:23:23,460 --> 00:23:24,260\nHas three parts.\n\n439\n00:23:24,260 --> 00:23:26,760\nThere's sort of George, and\nMartha, and the manager.\n\n440\n00:23:26,760 --> 00:23:28,970\nAnd that's how you get generic\noperators implemented.\n\n441\n00:23:28,970 --> 00:23:33,500\nLet's look at just a simple\nexample, just to pin it down.\n\n442\n00:23:33,500 --> 00:23:40,240\nBut exactly how this is going to\nwork, suppose you're going\n\n443\n00:23:40,240 --> 00:23:44,460\nto be looking at the complex\nnumber who's real-part is one,\n\n444\n00:23:44,460 --> 00:23:46,090\nand who's imaginary-part\nis two.\n\n445\n00:23:46,090 --> 00:23:50,310\nSo that would be one plus 2i.\n\n446\n00:23:50,310 --> 00:23:56,350\nWhat would happen is up here,\nup here above where the\n\n447\n00:23:56,350 --> 00:23:58,530\noperations have to happen,\nthat number would be\n\n448\n00:23:58,530 --> 00:24:10,320\nrepresented as a pair of 1 and\n2 together with typed data.\n\n449\n00:24:10,320 --> 00:24:11,870\nThat would be the contents.\n\n450\n00:24:11,870 --> 00:24:16,300\nAnd the whole data would be\nthat thing with the symbol\n\n451\n00:24:16,300 --> 00:24:17,960\nrectangular added onto that.\n\n452\n00:24:17,960 --> 00:24:20,980\nAnd that's the way that complex\nnumber would exist in\n\n453\n00:24:20,980 --> 00:24:22,330\nthe system.\n\n454\n00:24:22,330 --> 00:24:26,560\nWhen you went to take the\nreal-part, the manager would\n\n455\n00:24:26,560 --> 00:24:30,270\nlook at this and say, oh\nit's one of George's.\n\n456\n00:24:30,270 --> 00:24:34,440\nHe'll strip off the type\nand hand down to\n\n457\n00:24:34,440 --> 00:24:37,532\nGeorge the pair 1, 2.\n\n458\n00:24:37,532 --> 00:24:41,420\nAnd that's the kind of data\nthat George developed his\n\n459\n00:24:41,420 --> 00:24:42,670\nsystem to use.\n\n460\n00:24:42,670 --> 00:24:44,950\n\n\n461\n00:24:44,950 --> 00:24:46,680\nSo it gets stripped down.\n\n462\n00:24:46,680 --> 00:24:51,240\nLater on, if you ask George to\nconstruct a complex number,\n\n463\n00:24:51,240 --> 00:24:55,370\nGeorge would construct some\ncomplex number as a pair, and\n\n464\n00:24:55,370 --> 00:24:59,630\nbefore he passes it back up\nthrough the manager would\n\n465\n00:24:59,630 --> 00:25:00,880\nattach the type rectangular.\n\n466\n00:25:00,880 --> 00:25:03,920\n\n\n467\n00:25:03,920 --> 00:25:04,650\nSo you see what happens.\n\n468\n00:25:04,650 --> 00:25:05,850\nThere's no confusion\nin this system.\n\n469\n00:25:05,850 --> 00:25:13,780\nIt doesn't matter in the least\nthat the pair 1, 2 means\n\n470\n00:25:13,780 --> 00:25:15,750\nsomething completely different\nin Martha's world.\n\n471\n00:25:15,750 --> 00:25:18,440\nIn Martha's world this pair\nmeans the complex number whose\n\n472\n00:25:18,440 --> 00:25:21,190\nmagnitude is 1 and\nwhose angle is 2.\n\n473\n00:25:21,190 --> 00:25:23,930\nAnd there's no confusion,\nbecause by the time any pair\n\n474\n00:25:23,930 --> 00:25:27,250\nlike this gets handed back\nthrough the manager to the\n\n475\n00:25:27,250 --> 00:25:31,210\nmain system it's going to have\nthe type polar attached.\n\n476\n00:25:31,210 --> 00:25:33,670\nWhereas this one would have the\ntype rectangular attached.\n\n477\n00:25:33,670 --> 00:25:36,930\n\n\n478\n00:25:36,930 --> 00:25:38,180\nOK, let's take a break.\n\n479\n00:25:38,180 --> 00:25:40,770\n\n\n480\n00:25:40,770 --> 00:25:41,057\n[MUSIC-- \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n481\n00:25:41,057 --> 00:25:42,307\nJOHANN SEBASTIAN BACH]\n\n482\n00:25:42,307 --> 00:26:20,210\n\n\n483\n00:26:20,210 --> 00:26:22,080\nWe just looked at\na strategy for\n\n484\n00:26:22,080 --> 00:26:24,150\nimplementing generic operators.\n\n485\n00:26:24,150 --> 00:26:31,400\nThat strategy has a name: it's\ncalled dispatch type.\n\n486\n00:26:31,400 --> 00:26:34,310\n\n\n487\n00:26:34,310 --> 00:26:38,480\nAnd the idea is that you\nbreak your system\n\n488\n00:26:38,480 --> 00:26:39,360\ninto a bunch of pieces.\n\n489\n00:26:39,360 --> 00:26:43,250\nThere's George and Martha, who\nare making representations,\n\n490\n00:26:43,250 --> 00:26:46,320\nand then there's the manager.\n\n491\n00:26:46,320 --> 00:26:49,880\nLooks at the types on the data\nand then dispatches them to\n\n492\n00:26:49,880 --> 00:26:51,990\nthe right person.\n\n493\n00:26:51,990 --> 00:26:55,320\nWell what criticisms can we\nmake of that as a system\n\n494\n00:26:55,320 --> 00:26:56,570\norganization?\n\n495\n00:26:56,570 --> 00:26:58,150\n\n\n496\n00:26:58,150 --> 00:27:00,400\nWell first of all there was this\nlittle, annoying problem\n\n497\n00:27:00,400 --> 00:27:02,350\nthat George and Martha had to\nchange the names of their\n\n498\n00:27:02,350 --> 00:27:04,220\nprocedures.\n\n499\n00:27:04,220 --> 00:27:06,160\nGeorge originally had a\nreal-part procedure, and he\n\n500\n00:27:06,160 --> 00:27:09,110\nhad to go name it real-part\nrectangular so it wouldn't\n\n501\n00:27:09,110 --> 00:27:11,170\ninterfere with Martha's\nreal-part procedure, which is\n\n502\n00:27:11,170 --> 00:27:14,410\nnow named real-part-polar, so it\nwouldn't interfere with the\n\n503\n00:27:14,410 --> 00:27:17,310\nmanager's real-part procedure,\nwho's now named real-part.\n\n504\n00:27:17,310 --> 00:27:19,460\nThat's kind of an annoying\nproblem.\n\n505\n00:27:19,460 --> 00:27:21,270\nBut I'm not going to talk\nabout that one now.\n\n506\n00:27:21,270 --> 00:27:24,450\nWe'll see later on when we think\nabout the structure of\n\n507\n00:27:24,450 --> 00:27:27,480\nLisp names and environments that\nthere really are ways to\n\n508\n00:27:27,480 --> 00:27:30,390\npackage all those so-called name\nspaces separately so they\n\n509\n00:27:30,390 --> 00:27:32,500\ndon't interfere with\neach other.\n\n510\n00:27:32,500 --> 00:27:35,720\nNot going to think about\nthat problem now.\n\n511\n00:27:35,720 --> 00:27:38,740\nThe problem that I actually\nwant to focus on is what\n\n512\n00:27:38,740 --> 00:27:44,510\nhappens when you bring somebody\nnew into the system.\n\n513\n00:27:44,510 --> 00:27:45,320\nWhat has to happen?\n\n514\n00:27:45,320 --> 00:27:47,690\nWell George and Martha\ndon't care.\n\n515\n00:27:47,690 --> 00:27:52,830\nGeorge is sitting there in his\nrectangular world, has his\n\n516\n00:27:52,830 --> 00:27:54,090\nprocedures and his types.\n\n517\n00:27:54,090 --> 00:27:56,260\nMartha sits in her\npolar world.\n\n518\n00:27:56,260 --> 00:27:59,380\nShe doesn't care.\n\n519\n00:27:59,380 --> 00:28:01,540\nBut let's look at the manager.\n\n520\n00:28:01,540 --> 00:28:03,180\nWhat's the manager have to do?\n\n521\n00:28:03,180 --> 00:28:07,360\nThe manager comes through and\nhad these operations.\n\n522\n00:28:07,360 --> 00:28:09,040\nThere was a test\nfor rectangular\n\n523\n00:28:09,040 --> 00:28:10,140\nand a test for polar.\n\n524\n00:28:10,140 --> 00:28:17,210\nIf Harry comes in with some new\nkind of complex number,\n\n525\n00:28:17,210 --> 00:28:20,430\nand Harry has a new type, Harry\ntype complex number, the\n\n526\n00:28:20,430 --> 00:28:25,240\nmanager has to go in and change\nall those procedures.\n\n527\n00:28:25,240 --> 00:28:28,940\nSo the inflexibility in the\nsystem, the place where work\n\n528\n00:28:28,940 --> 00:28:34,890\nhas to happen to accommodate\nchange, is in the manager.\n\n529\n00:28:34,890 --> 00:28:35,990\nThat's pretty annoying.\n\n530\n00:28:35,990 --> 00:28:40,300\nIt's even more annoying when you\nrealize the manager's not\n\n531\n00:28:40,300 --> 00:28:42,590\ndoing anything.\n\n532\n00:28:42,590 --> 00:28:46,690\nThe manager is just being\na paper pusher.\n\n533\n00:28:46,690 --> 00:28:51,760\nLet's look again at these\nprograms. What are they doing?\n\n534\n00:28:51,760 --> 00:28:52,880\nWhat does real-part do?\n\n535\n00:28:52,880 --> 00:28:56,170\nReal-part says, oh, is it the\nkind of complex number that\n\n536\n00:28:56,170 --> 00:28:57,000\nGeorge can handle?\n\n537\n00:28:57,000 --> 00:28:59,410\nIf so, send it off to George.\n\n538\n00:28:59,410 --> 00:29:01,910\nIs it the kind of complex number\nthat Martha can handle?\n\n539\n00:29:01,910 --> 00:29:05,040\nIf so, send it off to Martha.\n\n540\n00:29:05,040 --> 00:29:08,720\nSo it's really annoying that the\nbottleneck in this system,\n\n541\n00:29:08,720 --> 00:29:13,040\nthe thing that's preventing\nflexibility and change, is\n\n542\n00:29:13,040 --> 00:29:15,000\ncompletely in the bureaucracy.\n\n543\n00:29:15,000 --> 00:29:19,700\nIt's not in anybody who's\ndoing any of the work.\n\n544\n00:29:19,700 --> 00:29:23,300\nNot an uncommon situation,\nunfortunately.\n\n545\n00:29:23,300 --> 00:29:24,570\nSee, what's really going on--\n\n546\n00:29:24,570 --> 00:29:28,100\nabstractly in the system,\nthere's a table.\n\n547\n00:29:28,100 --> 00:29:30,150\nSo what's really happening is\nsomewhere there's a table.\n\n548\n00:29:30,150 --> 00:29:32,780\n\n\n549\n00:29:32,780 --> 00:29:34,400\nThere're types.\n\n550\n00:29:34,400 --> 00:29:38,565\nThere's polar and rectangular.\n\n551\n00:29:38,565 --> 00:29:41,550\n\n\n552\n00:29:41,550 --> 00:29:44,380\nAnd Harry's may be over here.\n\n553\n00:29:44,380 --> 00:29:48,050\nAnd there are operators.\n\n554\n00:29:48,050 --> 00:29:50,340\nThere's an operator\nlike real-part.\n\n555\n00:29:50,340 --> 00:29:55,600\n\n\n556\n00:29:55,600 --> 00:30:00,010\nOr imaginary-part.\n\n557\n00:30:00,010 --> 00:30:05,830\nOr a magnitude and angle.\n\n558\n00:30:05,830 --> 00:30:19,280\nAnd sitting in this table are\nthe right procedures.\n\n559\n00:30:19,280 --> 00:30:21,990\nSo sitting here for the type\npolar and real-part is\n\n560\n00:30:21,990 --> 00:30:24,730\nMartha's procedure\nreal-part-polar.\n\n561\n00:30:24,730 --> 00:30:30,570\n\n\n562\n00:30:30,570 --> 00:30:33,740\nAnd over here in the table\nis George's procedure\n\n563\n00:30:33,740 --> 00:30:34,990\nreal-part-rectangular.\n\n564\n00:30:34,990 --> 00:30:37,740\n\n\n565\n00:30:37,740 --> 00:30:40,680\nAnd over here would be, say,\nMartha's procedure\n\n566\n00:30:40,680 --> 00:30:46,780\nmagnitude-polar, and\nGeorge's procedure\n\n567\n00:30:46,780 --> 00:30:49,760\nmagnitude-rectangular,\nright, and so on.\n\n568\n00:30:49,760 --> 00:30:52,390\nThe rest of this table's\nfilled in.\n\n569\n00:30:52,390 --> 00:30:54,260\nAnd that's really\nwhat's going on.\n\n570\n00:30:54,260 --> 00:30:57,630\n\n\n571\n00:30:57,630 --> 00:31:03,380\nSo in some sense, all the\nmanager is doing is acting as\n\n572\n00:31:03,380 --> 00:31:04,630\nthis table.\n\n573\n00:31:04,630 --> 00:31:06,860\n\n\n574\n00:31:06,860 --> 00:31:08,610\nWell how do we fix our system?\n\n575\n00:31:08,610 --> 00:31:12,110\n\n\n576\n00:31:12,110 --> 00:31:13,770\nHow do you fix bureaucracies\na lot of the time?\n\n577\n00:31:13,770 --> 00:31:16,240\nWhat you do is you get\nrid of the manager.\n\n578\n00:31:16,240 --> 00:31:20,170\nWe just take the manager and\nreplace him by a computer.\n\n579\n00:31:20,170 --> 00:31:23,320\nWe're going to automate\nhim out of existence.\n\n580\n00:31:23,320 --> 00:31:25,970\nNamely, instead of having the\nmanager who basically consults\n\n581\n00:31:25,970 --> 00:31:31,020\nthis table, we'll have our\nsystem use the table directly.\n\n582\n00:31:31,020 --> 00:31:32,110\nWhat do I mean by that?\n\n583\n00:31:32,110 --> 00:31:38,730\nLet's assume, again using data\nabstraction, that we have some\n\n584\n00:31:38,730 --> 00:31:40,880\nkind of data structure\nthat's a table.\n\n585\n00:31:40,880 --> 00:31:43,080\nAnd we have ways of sticking\nthings in and ways of getting\n\n586\n00:31:43,080 --> 00:31:44,356\nthings out.\n\n587\n00:31:44,356 --> 00:31:47,000\nAnd to be explicit, let me\nassume that there's an\n\n588\n00:31:47,000 --> 00:31:52,710\noperation called \"put.\" And put\nis going to take, in this\n\n589\n00:31:52,710 --> 00:32:00,130\ncase two things I'll call\n\"keys.\" Key1 and key2.\n\n590\n00:32:00,130 --> 00:32:01,380\nAnd a value.\n\n591\n00:32:01,380 --> 00:32:06,200\n\n\n592\n00:32:06,200 --> 00:32:11,490\nAnd that stores the value in the\ntable under key1 and key2.\n\n593\n00:32:11,490 --> 00:32:15,530\nAnd then we'll assume there's\na thing called \"get,\" such\n\n594\n00:32:15,530 --> 00:32:19,680\nthat if later on I say, get me\nwhat's in the table stored\n\n595\n00:32:19,680 --> 00:32:25,010\nunder key1 and key2, it'll\nretrieve whatever value was\n\n596\n00:32:25,010 --> 00:32:26,730\nstored there.\n\n597\n00:32:26,730 --> 00:32:30,000\nAnd let's not worry about how\ntables are implemented.\n\n598\n00:32:30,000 --> 00:32:33,060\nThat's yet another data\nabstraction, George's problem.\n\n599\n00:32:33,060 --> 00:32:34,700\nAnd maybe we'll see later--\n\n600\n00:32:34,700 --> 00:32:36,970\ntalk about how you might\nactually build tables in Lisp.\n\n601\n00:32:36,970 --> 00:32:40,710\n\n\n602\n00:32:40,710 --> 00:32:44,850\nWell given this organization,\nwhat did George and Martha\n\n603\n00:32:44,850 --> 00:32:47,380\nhave to do?\n\n604\n00:32:47,380 --> 00:32:50,010\nWell when they build their\nsystem, they each have the\n\n605\n00:32:50,010 --> 00:32:52,750\nresponsibility to set\nup their appropriate\n\n606\n00:32:52,750 --> 00:32:55,210\ncolumn in the table.\n\n607\n00:32:55,210 --> 00:33:00,620\nSo what George does, for\nexample, when he defines his\n\n608\n00:33:00,620 --> 00:33:04,020\nprocedures, all he has to do\nis go off and put into the\n\n609\n00:33:04,020 --> 00:33:06,990\ntable under the\ntype-rectangular.\n\n610\n00:33:06,990 --> 00:33:09,820\n\n\n611\n00:33:09,820 --> 00:33:14,100\nAnd the name of the operation\nis real-part, his procedure\n\n612\n00:33:14,100 --> 00:33:16,250\nreal-part-rectangular.\n\n613\n00:33:16,250 --> 00:33:17,780\nSo notice what's going\ninto this table.\n\n614\n00:33:17,780 --> 00:33:22,100\nThe two keys here are symbols,\nrectangular and real-part.\n\n615\n00:33:22,100 --> 00:33:24,400\nThat's the quote.\n\n616\n00:33:24,400 --> 00:33:27,410\nAnd what's going into the table\nis the actual procedure\n\n617\n00:33:27,410 --> 00:33:28,870\nthat he wrote, real-part\nrectangular.\n\n618\n00:33:28,870 --> 00:33:32,040\n\n\n619\n00:33:32,040 --> 00:33:35,000\nAnd then puts an imaginary part\ninto the table, filed\n\n620\n00:33:35,000 --> 00:33:39,370\nunder the keys rectangular-\nand imaginary-part, and\n\n621\n00:33:39,370 --> 00:33:44,020\nmagnitude under the keys\nrectangular magnitude, angle\n\n622\n00:33:44,020 --> 00:33:45,270\nunder rectangular-angle.\n\n623\n00:33:45,270 --> 00:33:47,350\n\n\n624\n00:33:47,350 --> 00:33:50,840\nSo that's what George has to do\nto be part of this system.\n\n625\n00:33:50,840 --> 00:33:54,420\n\n\n626\n00:33:54,420 --> 00:33:57,740\nMartha similarly sets\nup the column and\n\n627\n00:33:57,740 --> 00:33:59,430\nthe table under polar.\n\n628\n00:33:59,430 --> 00:34:02,160\nPolar and real-part.\n\n629\n00:34:02,160 --> 00:34:04,340\nIs the procedure\nreal-part-polar?\n\n630\n00:34:04,340 --> 00:34:09,030\nAnd imaginary-part, and\nmagnitude, and angle.\n\n631\n00:34:09,030 --> 00:34:11,409\nSo this is what Martha has to\ndo to be part of the system.\n\n632\n00:34:11,409 --> 00:34:13,550\nEveryone who makes a\nrepresentation has the\n\n633\n00:34:13,550 --> 00:34:17,840\nresponsibility for setting\nup a column in the table.\n\n634\n00:34:17,840 --> 00:34:19,900\nAnd what does Harry do when\nHarry comes in with his\n\n635\n00:34:19,900 --> 00:34:21,800\nbrilliant idea for implementing\ncomplex numbers?\n\n636\n00:34:21,800 --> 00:34:25,170\nWell he makes whatever procedure\nhe wants and builds\n\n637\n00:34:25,170 --> 00:34:28,550\na new column in this table.\n\n638\n00:34:28,550 --> 00:34:31,330\nOK, well what happened\nto the manager?\n\n639\n00:34:31,330 --> 00:34:34,610\nThe manager has been automated\nout of existence and is\n\n640\n00:34:34,610 --> 00:34:37,110\nreplaced by a procedure\ncalled operate.\n\n641\n00:34:37,110 --> 00:34:40,380\nAnd this is the key procedure\nin the whole system.\n\n642\n00:34:40,380 --> 00:34:45,920\nLet's say define operate.\n\n643\n00:34:45,920 --> 00:34:51,060\n\n\n644\n00:34:51,060 --> 00:34:57,750\nOperate is going to take an\noperation that you want to do,\n\n645\n00:34:57,750 --> 00:35:01,840\nthe name of an operation, and an\nobject that you would like\n\n646\n00:35:01,840 --> 00:35:04,210\nto apply that operation to.\n\n647\n00:35:04,210 --> 00:35:07,400\nSo for example, the real-part\nof some particular complex\n\n648\n00:35:07,400 --> 00:35:09,890\nnumber, what does it do?\n\n649\n00:35:09,890 --> 00:35:12,650\nWell the first thing it does,\nit looks in the table.\n\n650\n00:35:12,650 --> 00:35:20,710\nGoes into the table and tries\nto find a procedure that's\n\n651\n00:35:20,710 --> 00:35:23,320\nstored in the table.\n\n652\n00:35:23,320 --> 00:35:29,830\nSo it gets from the table, using\nas keys the type of the\n\n653\n00:35:29,830 --> 00:35:40,450\nobject and the operator, but\nlooks on the table and sees\n\n654\n00:35:40,450 --> 00:35:42,300\nwhat's stored under the type\nof the object and the\n\n655\n00:35:42,300 --> 00:35:44,440\noperator, sees if anything's\nstored.\n\n656\n00:35:44,440 --> 00:35:45,930\nLet's assume that get\nis implemented.\n\n657\n00:35:45,930 --> 00:35:52,560\nSo if nothing is stored there,\nit'll return the empty list.\n\n658\n00:35:52,560 --> 00:35:55,130\nSo it says, if there's actually\nsomething stored\n\n659\n00:35:55,130 --> 00:36:04,920\nthere, if the procedure here is\nnot no, then it'll take the\n\n660\n00:36:04,920 --> 00:36:11,240\nprocedure that it found in the\ntable and apply it to the\n\n661\n00:36:11,240 --> 00:36:15,120\ncontents of the object.\n\n662\n00:36:15,120 --> 00:36:18,042\n\n\n663\n00:36:18,042 --> 00:36:21,445\nAnd otherwise if there was\nnothing stored there, it'll--\n\n664\n00:36:21,445 --> 00:36:22,435\nwell we can decide.\n\n665\n00:36:22,435 --> 00:36:25,920\nIn this case let's have it put\nout an error message saying,\n\n666\n00:36:25,920 --> 00:36:28,650\nundefined operator.\n\n667\n00:36:28,650 --> 00:36:30,230\nNo operator for this type.\n\n668\n00:36:30,230 --> 00:36:32,770\n\n\n669\n00:36:32,770 --> 00:36:34,285\nOr some appropriate\nerror message.\n\n670\n00:36:34,285 --> 00:36:39,150\n\n\n671\n00:36:39,150 --> 00:36:39,300\nOK?\n\n672\n00:36:39,300 --> 00:36:41,890\nAnd that replaces the manager.\n\n673\n00:36:41,890 --> 00:36:43,960\nHow do we really use it?\n\n674\n00:36:43,960 --> 00:36:48,580\nWell what we say is we'll go\noff and define our generic\n\n675\n00:36:48,580 --> 00:36:50,040\nselectors using operate.\n\n676\n00:36:50,040 --> 00:36:57,140\nWe'll say that the real-part\nof an object is found by\n\n677\n00:36:57,140 --> 00:37:05,010\noperating on the object with\nthe name of the operation\n\n678\n00:37:05,010 --> 00:37:06,260\nbeing real-part.\n\n679\n00:37:06,260 --> 00:37:08,070\n\n\n680\n00:37:08,070 --> 00:37:10,870\nAnd then similarly,\nimaginary-part is operate\n\n681\n00:37:10,870 --> 00:37:16,080\nusing the name imaginary-part\nand magnitude and angle.\n\n682\n00:37:16,080 --> 00:37:17,430\nThat's our implementation.\n\n683\n00:37:17,430 --> 00:37:21,330\nThat plus the tape plus\nthe operate procedure.\n\n684\n00:37:21,330 --> 00:37:23,100\nAnd the table effectively\nreplaces what the\n\n685\n00:37:23,100 --> 00:37:24,150\nmanager used to do.\n\n686\n00:37:24,150 --> 00:37:27,040\nLet's just go through that\nslowly to show you\n\n687\n00:37:27,040 --> 00:37:27,900\nwhat's going on.\n\n688\n00:37:27,900 --> 00:37:33,000\nSuppose I have one of Martha's\ncomplex numbers.\n\n689\n00:37:33,000 --> 00:37:35,520\n\n\n690\n00:37:35,520 --> 00:37:39,100\nIt's got magnitude\n1 and angle 2.\n\n691\n00:37:39,100 --> 00:37:40,220\nAnd it's one of Martha's.\n\n692\n00:37:40,220 --> 00:37:47,120\nSo it's labeled here, polar.\n\n693\n00:37:47,120 --> 00:37:48,000\nLet's call that z.\n\n694\n00:37:48,000 --> 00:37:49,250\nSuppose that's z.\n\n695\n00:37:49,250 --> 00:37:51,770\n\n\n696\n00:37:51,770 --> 00:37:54,320\nAnd suppose with this\nimplementation someone comes\n\n697\n00:37:54,320 --> 00:37:57,110\nup and asks for the\nreal-part of z.\n\n698\n00:37:57,110 --> 00:38:04,870\n\n\n699\n00:38:04,870 --> 00:38:08,920\nWell real-part now is defined\nin terms of operate.\n\n700\n00:38:08,920 --> 00:38:18,470\nSo that's equivalent to saying\noperate with the name of the\n\n701\n00:38:18,470 --> 00:38:27,060\noperator being real-part, the\nsymbol real-part on z.\n\n702\n00:38:27,060 --> 00:38:28,090\nAnd now operate comes.\n\n703\n00:38:28,090 --> 00:38:31,720\nIt's going to look in the table,\nand it's going to try\n\n704\n00:38:31,720 --> 00:38:34,005\nand find something\nstored under--\n\n705\n00:38:34,005 --> 00:38:38,830\n\n\n706\n00:38:38,830 --> 00:38:42,160\nthe operation is going to apply\nby looking in the table\n\n707\n00:38:42,160 --> 00:38:46,225\nunder the type of the object.\n\n708\n00:38:46,225 --> 00:38:48,790\nAnd the type of z is polar.\n\n709\n00:38:48,790 --> 00:38:52,990\nSo it's going to look and say,\ncan I get using polar?\n\n710\n00:38:52,990 --> 00:38:58,250\nAnd the operation name,\nwhich was real-part.\n\n711\n00:38:58,250 --> 00:39:05,960\n\n\n712\n00:39:05,960 --> 00:39:09,490\nIt's going to look in there\nand apply that to\n\n713\n00:39:09,490 --> 00:39:14,930\nthe contents of z.\n\n714\n00:39:14,930 --> 00:39:15,650\nAnd that?\n\n715\n00:39:15,650 --> 00:39:20,350\nIf everything was set up\ncorrectly, this thing is the\n\n716\n00:39:20,350 --> 00:39:21,700\nprocedure that Martha\nput there.\n\n717\n00:39:21,700 --> 00:39:22,950\nThis is real-part-polar.\n\n718\n00:39:22,950 --> 00:39:30,790\n\n\n719\n00:39:30,790 --> 00:39:35,130\nAnd this is z without\nits type.\n\n720\n00:39:35,130 --> 00:39:37,860\nThe thing that Martha originally\ndesigned those\n\n721\n00:39:37,860 --> 00:39:40,340\nprocedures to work on,\nwhich is 1, 2.\n\n722\n00:39:40,340 --> 00:39:43,790\n\n\n723\n00:39:43,790 --> 00:39:47,210\nAnd so operate sort of does\nuniformly what the manager\n\n724\n00:39:47,210 --> 00:39:49,450\nused to do sort of all\nover the system.\n\n725\n00:39:49,450 --> 00:39:52,170\nIt finds the right thing, looks\nin the table, strips off\n\n726\n00:39:52,170 --> 00:39:56,600\nthe type, and passes\nit down into the\n\n727\n00:39:56,600 --> 00:39:59,160\nperson who handles it.\n\n728\n00:39:59,160 --> 00:40:04,980\nThis is another, and, you can\nsee, more flexible for most\n\n729\n00:40:04,980 --> 00:40:07,990\npurposes, way of implementing\ngeneric operators.\n\n730\n00:40:07,990 --> 00:40:15,505\nAnd it's called data-directed\nprogramming.\n\n731\n00:40:15,505 --> 00:40:20,350\n\n\n732\n00:40:20,350 --> 00:40:24,920\nAnd the idea of that is in some\nsense the data objects\n\n733\n00:40:24,920 --> 00:40:27,260\nthemselves, those little complex\nnumbers that are\n\n734\n00:40:27,260 --> 00:40:30,340\nfloating around the system,\nare carrying with them the\n\n735\n00:40:30,340 --> 00:40:35,390\ninformation about how you\nshould operate on them.\n\n736\n00:40:35,390 --> 00:40:36,640\nLet's break for questions.\n\n737\n00:40:36,640 --> 00:40:41,000\n\n\n738\n00:40:41,000 --> 00:40:41,240\nYes.\n\n739\n00:40:41,240 --> 00:40:43,390\nAUDIENCE: What do you have\nstored in that data object?\n\n740\n00:40:43,390 --> 00:40:47,850\nYou have the data itself, you\nhave its type, and you have\n\n741\n00:40:47,850 --> 00:40:49,690\nthe operations for that type?\n\n742\n00:40:49,690 --> 00:40:53,600\nOr where are the operations\nthat you found?\n\n743\n00:40:53,600 --> 00:40:54,980\nPROFESSOR: OK, let me--\n\n744\n00:40:54,980 --> 00:40:56,500\nyeah, that's a good question.\n\n745\n00:40:56,500 --> 00:40:59,700\nBecause it raises other\npossibilities of how\n\n746\n00:40:59,700 --> 00:41:00,750\nyou might do it.\n\n747\n00:41:00,750 --> 00:41:04,200\nAnd of course there are a\nlot of possibilities.\n\n748\n00:41:04,200 --> 00:41:06,820\nIn this particular\nimplementation, what's sitting\n\n749\n00:41:06,820 --> 00:41:11,630\nin this data object, for\nexample, is the data itself--\n\n750\n00:41:11,630 --> 00:41:14,980\nwhich in this case is\na pair of 1 and 2--\n\n751\n00:41:14,980 --> 00:41:16,550\nand also a symbol.\n\n752\n00:41:16,550 --> 00:41:21,140\nThis is the symbol, the word\nP-O-L-A-R, and that's what's\n\n753\n00:41:21,140 --> 00:41:22,390\nsitting in this data object.\n\n754\n00:41:22,390 --> 00:41:24,870\n\n\n755\n00:41:24,870 --> 00:41:26,690\nWhere are the operations\nthemselves?\n\n756\n00:41:26,690 --> 00:41:29,850\nThe operations are sitting\nin the table.\n\n757\n00:41:29,850 --> 00:41:35,450\nSo in this table, the rows and\ncolumns of the table are\n\n758\n00:41:35,450 --> 00:41:38,230\nlabeled by symbols.\n\n759\n00:41:38,230 --> 00:41:40,810\nSo when I store something in\nthis table, the key might be\n\n760\n00:41:40,810 --> 00:41:48,240\nthe symbol polar and the\nsymbol magnitude.\n\n761\n00:41:48,240 --> 00:41:51,310\nAnd I think by writing it this\nway I've been very confusing.\n\n762\n00:41:51,310 --> 00:41:53,160\nBecause what's really\nsitting here isn't--\n\n763\n00:41:53,160 --> 00:41:58,360\nwhen I wrote magnitude polar,\nwhat I mean is the procedure\n\n764\n00:41:58,360 --> 00:41:59,850\nmagnitude polar.\n\n765\n00:41:59,850 --> 00:42:02,580\nAnd probably what I really\nshould have written--\n\n766\n00:42:02,580 --> 00:42:04,200\nexcept it's too small\nfor me to write\n\n767\n00:42:04,200 --> 00:42:05,580\nin this little space--\n\n768\n00:42:05,580 --> 00:42:11,250\nis something like lambda\nof z, the thing that\n\n769\n00:42:11,250 --> 00:42:14,710\nMartha wrote to implement.\n\n770\n00:42:14,710 --> 00:42:16,620\nAnd then you can see from that,\nthere's another way that\n\n771\n00:42:16,620 --> 00:42:20,250\nI alluded to of solving this\nname conflict problem, which\n\n772\n00:42:20,250 --> 00:42:22,380\nis that George and Martha\nnever have to name their\n\n773\n00:42:22,380 --> 00:42:23,150\nprocedures at all.\n\n774\n00:42:23,150 --> 00:42:26,710\nThey can just stick the\nanonymous things generated by\n\n775\n00:42:26,710 --> 00:42:28,660\nlambda directly into\nthe table.\n\n776\n00:42:28,660 --> 00:42:32,540\nThere's also another thing that\nyour question raises, is\n\n777\n00:42:32,540 --> 00:42:36,045\nthe possibility that maybe what\nI would like somehow is\n\n778\n00:42:36,045 --> 00:42:40,120\nto store in this data object not\nthe symbol P-O-L-A-R but\n\n779\n00:42:40,120 --> 00:42:43,520\nmaybe actually all the\noperations themselves.\n\n780\n00:42:43,520 --> 00:42:45,860\nAnd that's another way to\norganize the system, called\n\n781\n00:42:45,860 --> 00:42:48,650\nmessage passing.\n\n782\n00:42:48,650 --> 00:42:49,970\nSo there are a lot of\nways you can do it.\n\n783\n00:42:49,970 --> 00:42:54,640\n\n\n784\n00:42:54,640 --> 00:42:58,040\nAUDIENCE: Therefore if Martha\nand George had used the same\n\n785\n00:42:58,040 --> 00:43:01,230\nprocedure names, it would be\nOK because it wouldn't look\n\n786\n00:43:01,230 --> 00:43:02,560\n[UNINTELLIGIBLE].\n\n787\n00:43:02,560 --> 00:43:03,010\nPROFESSOR: That's right.\n\n788\n00:43:03,010 --> 00:43:04,890\nThat's right.\n\n789\n00:43:04,890 --> 00:43:07,060\nSee, they wouldn't even\nhave to name their\n\n790\n00:43:07,060 --> 00:43:09,470\nprocedures at all.\n\n791\n00:43:09,470 --> 00:43:12,440\nWhat George could have written\ninstead of saying put in the\n\n792\n00:43:12,440 --> 00:43:16,890\ntable under rectangular- and\nreal-part, the procedure\n\n793\n00:43:16,890 --> 00:43:19,660\nreal-part rectangular, George\ncould have written put under\n\n794\n00:43:19,660 --> 00:43:23,080\nrectangular real-part, lambda\nof z, such and such,\n\n795\n00:43:23,080 --> 00:43:24,540\nand such and such.\n\n796\n00:43:24,540 --> 00:43:27,330\nAnd the system would work\ncompletely the same.\n\n797\n00:43:27,330 --> 00:43:31,750\nAUDIENCE: My question is, Martha\ncould have put key1\n\n798\n00:43:31,750 --> 00:43:37,120\nkey2 real-part, and George\ncould have put key1 key2\n\n799\n00:43:37,120 --> 00:43:40,060\nreal-part, and as long as they\ndefined them differently they\n\n800\n00:43:40,060 --> 00:43:41,290\nwouldn't have had any\nconflicts, right?\n\n801\n00:43:41,290 --> 00:43:45,130\nPROFESSOR: Yes, that would all\nbe OK except for the fact that\n\n802\n00:43:45,130 --> 00:43:47,130\nif you imagine George and Martha\ntyping at the same\n\n803\n00:43:47,130 --> 00:43:50,090\nconsole with the same meanings\nfor all their names, and it\n\n804\n00:43:50,090 --> 00:43:51,720\nwould get confused by real-part,\nbut there are ways\n\n805\n00:43:51,720 --> 00:43:52,800\nto arrange that, too.\n\n806\n00:43:52,800 --> 00:43:54,980\nAnd in principle you're\nabsolutely right.\n\n807\n00:43:54,980 --> 00:43:56,290\nIf their names didn't\nconflict--\n\n808\n00:43:56,290 --> 00:43:58,190\nit's the objects that go in\nthe table, not the names.\n\n809\n00:43:58,190 --> 00:44:08,200\n\n\n810\n00:44:08,200 --> 00:44:09,450\nOK, let's take a break.\n\n811\n00:44:09,450 --> 00:44:12,493\n\n\n812\n00:44:12,493 --> 00:44:12,836\n[MUSIC-- \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n813\n00:44:12,836 --> 00:44:14,086\nJOHANN SEBASTIAN BACH]\n\n814\n00:44:14,086 --> 00:45:12,880\n\n\n815\n00:45:12,880 --> 00:45:17,680\nAll right, well we just looked\nat data-directed programming\n\n816\n00:45:17,680 --> 00:45:21,590\nas a way of implementing a\nsystem that does arithmetic on\n\n817\n00:45:21,590 --> 00:45:22,840\ncomplex numbers.\n\n818\n00:45:22,840 --> 00:45:27,420\n\n\n819\n00:45:27,420 --> 00:45:32,880\nSo I had these operations in it\ncalled plus C and minus C,\n\n820\n00:45:32,880 --> 00:45:38,230\nand multiply, and divide,\nand maybe some others.\n\n821\n00:45:38,230 --> 00:45:46,030\nAnd that sat on top of-- and\nthis is the key point-- sat on\n\n822\n00:45:46,030 --> 00:45:50,340\ntop of two different\nrepresentations.\n\n823\n00:45:50,340 --> 00:45:55,110\nA rectangular package here,\nand a polar package.\n\n824\n00:45:55,110 --> 00:45:58,240\n\n\n825\n00:45:58,240 --> 00:45:59,150\nAnd maybe some more.\n\n826\n00:45:59,150 --> 00:46:01,640\nAnd we saw that the whole idea\nis that maybe some more are\n\n827\n00:46:01,640 --> 00:46:04,670\nnow very easy to add.\n\n828\n00:46:04,670 --> 00:46:08,900\nBut that doesn't really show the\npower of this methodology.\n\n829\n00:46:08,900 --> 00:46:10,150\nShows you what's going on.\n\n830\n00:46:10,150 --> 00:46:13,260\nThe power of the methodology\nonly becomes apparent when you\n\n831\n00:46:13,260 --> 00:46:17,080\nstart embedding this in some\nmore complex system.\n\n832\n00:46:17,080 --> 00:46:19,180\nWhat I'm going to do now is\nembed this in some more\n\n833\n00:46:19,180 --> 00:46:20,250\ncomplex system.\n\n834\n00:46:20,250 --> 00:46:23,960\nLet's assume that what we really\nhave is a general kind\n\n835\n00:46:23,960 --> 00:46:25,280\nof arithmetic system.\n\n836\n00:46:25,280 --> 00:46:27,240\nSo called generic arithmetic\nsystem.\n\n837\n00:46:27,240 --> 00:46:32,060\nAnd at the top level here,\nsomebody can say add two\n\n838\n00:46:32,060 --> 00:46:38,450\nthings, or subtract two things,\nor multiply two\n\n839\n00:46:38,450 --> 00:46:41,180\nthings, or divide two things.\n\n840\n00:46:41,180 --> 00:46:44,140\n\n\n841\n00:46:44,140 --> 00:46:47,930\nAnd underneath that there's\nan abstraction barrier.\n\n842\n00:46:47,930 --> 00:46:50,510\nAnd underneath this barrier,\nis, say, a\n\n843\n00:46:50,510 --> 00:46:52,850\ncomplex arithmetic package.\n\n844\n00:46:52,850 --> 00:46:55,110\nAnd you can say, add two\ncomplex numbers.\n\n845\n00:46:55,110 --> 00:46:57,540\nOr you might also have--\nremember we did a rational\n\n846\n00:46:57,540 --> 00:47:00,190\nnumber package-- you might\nhave that sitting there.\n\n847\n00:47:00,190 --> 00:47:03,950\nAnd there might be\na rational thing.\n\n848\n00:47:03,950 --> 00:47:07,760\nAnd the rational number package,\nwell, has the things\n\n849\n00:47:07,760 --> 00:47:08,320\nwe implemented.\n\n850\n00:47:08,320 --> 00:47:15,490\nPlus rat, and times\nrat, and so on.\n\n851\n00:47:15,490 --> 00:47:17,010\nOr you might have ordinary\nLisp numbers.\n\n852\n00:47:17,010 --> 00:47:19,310\nYou might say add\nthree and four.\n\n853\n00:47:19,310 --> 00:47:29,030\nSo we might have ordinary\nnumbers, in which case we have\n\n854\n00:47:29,030 --> 00:47:36,670\nthe Lisp supplied plus, and\nminus, and times, and slash.\n\n855\n00:47:36,670 --> 00:47:39,840\nOK, so we might imagine this\ncomplex number system sitting\n\n856\n00:47:39,840 --> 00:47:43,660\nin a more complicated generic\noperator structure at\n\n857\n00:47:43,660 --> 00:47:44,910\nthe next level up.\n\n858\n00:47:44,910 --> 00:47:47,730\n\n\n859\n00:47:47,730 --> 00:47:49,050\nWell how can we make that?\n\n860\n00:47:49,050 --> 00:47:50,240\nWe already have the\nidea, we're just\n\n861\n00:47:50,240 --> 00:47:52,780\ngoing to do it again.\n\n862\n00:47:52,780 --> 00:47:54,720\nWe've implemented a rational\nnumber package.\n\n863\n00:47:54,720 --> 00:47:56,650\nLet's look at how it\nhas to be changed.\n\n864\n00:47:56,650 --> 00:48:01,590\n\n\n865\n00:48:01,590 --> 00:48:02,660\nIn fact, at this level\nit doesn't have to\n\n866\n00:48:02,660 --> 00:48:03,730\nbe changed at all.\n\n867\n00:48:03,730 --> 00:48:07,180\nThis is exactly the code that\nwe wrote last time.\n\n868\n00:48:07,180 --> 00:48:10,140\nTo add two rational\nnumbers, remember\n\n869\n00:48:10,140 --> 00:48:11,140\nthere was this formula.\n\n870\n00:48:11,140 --> 00:48:14,980\nYou make a rational number\nwhose numerator--\n\n871\n00:48:14,980 --> 00:48:17,330\nthe numerator of the first times\nthe denominator of the\n\n872\n00:48:17,330 --> 00:48:20,486\nsecond, plus the denominator\nof the first times the\n\n873\n00:48:20,486 --> 00:48:21,520\nnumerator of the second.\n\n874\n00:48:21,520 --> 00:48:25,760\nAnd who's denominator is the\nproduct of the denominators.\n\n875\n00:48:25,760 --> 00:48:30,580\nAnd minus rat, and star\nrat, and slash rat.\n\n876\n00:48:30,580 --> 00:48:34,420\nAnd this is exactly the rational\nnumber package that\n\n877\n00:48:34,420 --> 00:48:36,310\nwe made before.\n\n878\n00:48:36,310 --> 00:48:38,390\nWe're ignoring the GCD problem,\nbut let's not worry\n\n879\n00:48:38,390 --> 00:48:40,240\nabout that.\n\n880\n00:48:40,240 --> 00:48:42,980\nAs implementers of this rational\nnumber package, how\n\n881\n00:48:42,980 --> 00:48:45,570\ndo we install it in the generic\narithmetic system?\n\n882\n00:48:45,570 --> 00:48:46,820\nWell that's easy.\n\n883\n00:48:46,820 --> 00:48:48,980\n\n\n884\n00:48:48,980 --> 00:48:51,840\nThere's only one thing we\nhave to do differently.\n\n885\n00:48:51,840 --> 00:48:56,270\nWhereas previously we said that\nto make a rational number\n\n886\n00:48:56,270 --> 00:49:00,960\nyou built a pair of the\nnumerator and denominator,\n\n887\n00:49:00,960 --> 00:49:03,300\nhere we'll not only build the\npair, but we'll sign it.\n\n888\n00:49:03,300 --> 00:49:06,120\nWe'll attach the\ntype rational.\n\n889\n00:49:06,120 --> 00:49:08,940\nThat's the only thing we have\nto do different, make it a\n\n890\n00:49:08,940 --> 00:49:12,380\ntyped data object.\n\n891\n00:49:12,380 --> 00:49:14,500\nAnd now we'll stick our\noperations in the table.\n\n892\n00:49:14,500 --> 00:49:18,920\nWe'll put under the symbol\nrational and the operation add\n\n893\n00:49:18,920 --> 00:49:21,820\nour procedure, plus rat.\n\n894\n00:49:21,820 --> 00:49:23,580\nAnd, again, note this\nis a symbol.\n\n895\n00:49:23,580 --> 00:49:23,930\nRight?\n\n896\n00:49:23,930 --> 00:49:26,830\nQuote, unquote, but the actual\nthing we're putting in the\n\n897\n00:49:26,830 --> 00:49:30,060\ntable is the procedure.\n\n898\n00:49:30,060 --> 00:49:33,700\nAnd for how to subtract,\nwell you subtract\n\n899\n00:49:33,700 --> 00:49:38,270\nrationals with minus rat.\n\n900\n00:49:38,270 --> 00:49:41,090\nAnd multiply, and divide.\n\n901\n00:49:41,090 --> 00:49:43,640\nAnd that is exactly and\nprecisely what we have to do\n\n902\n00:49:43,640 --> 00:49:48,510\nto fit inside this generic\narithmetic system.\n\n903\n00:49:48,510 --> 00:49:51,560\nWell how does the whole\nthing work?\n\n904\n00:49:51,560 --> 00:50:00,170\nSee, what we want to do is have\nsome generic operators.\n\n905\n00:50:00,170 --> 00:50:01,720\nHave add and sub and\n[UNINTELLIGIBLE]\n\n906\n00:50:01,720 --> 00:50:03,990\nbe generic operators.\n\n907\n00:50:03,990 --> 00:50:18,930\nSo we're going to define add and\nsay, to add x and y, that\n\n908\n00:50:18,930 --> 00:50:21,840\nwill be operate--\n\n909\n00:50:21,840 --> 00:50:26,080\n\n\n910\n00:50:26,080 --> 00:50:27,490\nwe were going to call\nit operate-2.\n\n911\n00:50:27,490 --> 00:50:30,350\nThis is our operator procedure,\nbut set up for two\n\n912\n00:50:30,350 --> 00:50:37,261\narguments using add\non x and y.\n\n913\n00:50:37,261 --> 00:50:40,420\nAnd so this is the analog\nto operate.\n\n914\n00:50:40,420 --> 00:50:41,680\nLet's look at the\ncode for second.\n\n915\n00:50:41,680 --> 00:50:42,930\nIt's almost like operate.\n\n916\n00:50:42,930 --> 00:50:46,040\n\n\n917\n00:50:46,040 --> 00:50:51,550\nTo operate with some operator\non an argument 1 and an\n\n918\n00:50:51,550 --> 00:50:56,370\nargument 2, well the first thing\nwe're going to do is\n\n919\n00:50:56,370 --> 00:51:01,900\ncheck and see if the two\narguments have the same type.\n\n920\n00:51:01,900 --> 00:51:06,610\nSo we'll say, is the type of the\nfirst argument the same as\n\n921\n00:51:06,610 --> 00:51:07,860\nthe type of the second\nargument?\n\n922\n00:51:07,860 --> 00:51:10,350\n\n\n923\n00:51:10,350 --> 00:51:15,070\nAnd if they're not, we'll go\noff and complain, and say,\n\n924\n00:51:15,070 --> 00:51:15,670\nthat's an error.\n\n925\n00:51:15,670 --> 00:51:19,140\nWe don't know how to do that.\n\n926\n00:51:19,140 --> 00:51:20,920\nIf they do have the same\ntype, we'll do\n\n927\n00:51:20,920 --> 00:51:22,080\nexactly what we did before.\n\n928\n00:51:22,080 --> 00:51:26,460\nWe'll go look and filed under\nthe type of the argument--\n\n929\n00:51:26,460 --> 00:51:30,420\narg 1 and arg 2 have the same\ntype, so it doesn't matter.\n\n930\n00:51:30,420 --> 00:51:33,640\nSo we'll look in the table,\nfind the procedure.\n\n931\n00:51:33,640 --> 00:51:38,870\nIf there is a procedure there,\nthen we'll apply it to the\n\n932\n00:51:38,870 --> 00:51:43,030\ncontents of the argument 1 and\nthe contents of arg 2.\n\n933\n00:51:43,030 --> 00:51:44,760\nAnd otherwise we'll\nsay, error.\n\n934\n00:51:44,760 --> 00:51:46,890\nUndefined operator.\n\n935\n00:51:46,890 --> 00:51:48,140\nAnd so there's operate-2.\n\n936\n00:51:48,140 --> 00:51:51,326\n\n\n937\n00:51:51,326 --> 00:51:55,160\nAnd that's all we have to do.\n\n938\n00:51:55,160 --> 00:51:57,640\nWe just built the complex\nnumber package before.\n\n939\n00:51:57,640 --> 00:52:00,140\nHow do we embed that complex\nnumber package in\n\n940\n00:52:00,140 --> 00:52:02,140\nthis generic system?\n\n941\n00:52:02,140 --> 00:52:03,390\nAlmost the same.\n\n942\n00:52:03,390 --> 00:52:06,410\n\n\n943\n00:52:06,410 --> 00:52:11,060\nWe make a procedure called\nmake-complex that takes\n\n944\n00:52:11,060 --> 00:52:14,100\nwhatever George and Martha\nhand to us and add the\n\n945\n00:52:14,100 --> 00:52:15,350\ntype-complex.\n\n946\n00:52:15,350 --> 00:52:18,170\n\n\n947\n00:52:18,170 --> 00:52:25,840\nAnd then we say, to add complex\nnumbers, plus complex,\n\n948\n00:52:25,840 --> 00:52:32,240\nwe use our internal procedure,\nplus c, and attach a type,\n\n949\n00:52:32,240 --> 00:52:33,490\nmake that a complex number.\n\n950\n00:52:33,490 --> 00:52:37,560\n\n\n951\n00:52:37,560 --> 00:52:42,840\nSo our original package had\nnames plus c and minus c that\n\n952\n00:52:42,840 --> 00:52:45,250\nwe're using to communicate\nwith George and Martha.\n\n953\n00:52:45,250 --> 00:52:47,730\nAnd then to communicate with the\noutside world, we have a\n\n954\n00:52:47,730 --> 00:52:52,380\nthing called plus-complex\nand minus-complex.\n\n955\n00:52:52,380 --> 00:52:55,920\n\n\n956\n00:52:55,920 --> 00:52:56,530\nAnd so on.\n\n957\n00:52:56,530 --> 00:52:59,000\nAnd the only difference\nis that these return\n\n958\n00:52:59,000 --> 00:53:01,120\nvalues that are tight.\n\n959\n00:53:01,120 --> 00:53:02,850\nSo they can be looked\nat up here.\n\n960\n00:53:02,850 --> 00:53:04,690\nAnd these are internal\noperations.\n\n961\n00:53:04,690 --> 00:53:09,250\n\n\n962\n00:53:09,250 --> 00:53:10,680\nLet's go look at that\nslide again.\n\n963\n00:53:10,680 --> 00:53:13,740\nThere's one more thing we do.\n\n964\n00:53:13,740 --> 00:53:19,280\nAfter defining plus-complex, we\nput under the type complex\n\n965\n00:53:19,280 --> 00:53:23,200\nand the symbol add, that\nprocedure plus complex.\n\n966\n00:53:23,200 --> 00:53:27,130\nAnd then similarly for\nsubtracting complex numbers,\n\n967\n00:53:27,130 --> 00:53:29,130\nand multiplying them,\nand dividing them.\n\n968\n00:53:29,130 --> 00:53:31,700\n\n\n969\n00:53:31,700 --> 00:53:35,250\nOK, how do we install\nordinary numbers?\n\n970\n00:53:35,250 --> 00:53:38,160\nExactly the same way.\n\n971\n00:53:38,160 --> 00:53:40,500\nCome off and say, well we'll\nmake a thing called\n\n972\n00:53:40,500 --> 00:53:41,750\nmake-number.\n\n973\n00:53:41,750 --> 00:53:44,340\n\n\n974\n00:53:44,340 --> 00:53:48,500\nMake-number takes a number and\nattaches a type, which is the\n\n975\n00:53:48,500 --> 00:53:50,260\nsymbol number.\n\n976\n00:53:50,260 --> 00:53:55,300\nWe build a procedure called\nplus-number, which is simply,\n\n977\n00:53:55,300 --> 00:53:59,220\nadd the two things using the\nordinary addition, because in\n\n978\n00:53:59,220 --> 00:54:01,850\nthis case we're talking about\nordinary numbers, and attach a\n\n979\n00:54:01,850 --> 00:54:04,510\ntype to it and make\nthat a number.\n\n980\n00:54:04,510 --> 00:54:08,700\nAnd then we put into the table\nunder the symbol number and\n\n981\n00:54:08,700 --> 00:54:12,550\nthe operation add, this\nprocedure plus-number, and\n\n982\n00:54:12,550 --> 00:54:15,360\nthen the same thing for\nsubtracting, and multiplying,\n\n983\n00:54:15,360 --> 00:54:16,610\nand dividing.\n\n984\n00:54:16,610 --> 00:54:22,750\n\n\n985\n00:54:22,750 --> 00:54:26,060\nLet's look at an example,\njust to make it clear.\n\n986\n00:54:26,060 --> 00:54:32,600\nSuppose, for instance,\nI'm going\n\n987\n00:54:32,600 --> 00:54:34,150\nto perform the operation.\n\n988\n00:54:34,150 --> 00:54:38,220\nSo I sit up here and I'm going\nto perform the operation,\n\n989\n00:54:38,220 --> 00:54:40,930\nwhich looks like multiplying\ntwo complex numbers.\n\n990\n00:54:40,930 --> 00:54:49,786\nSo I would multiply, say,\n3 plus 4i and 2 plus 6i.\n\n991\n00:54:49,786 --> 00:54:51,740\nAnd that's something that\nI might want to take\n\n992\n00:54:51,740 --> 00:54:52,840\nhand that to mul.\n\n993\n00:54:52,840 --> 00:54:57,170\nI'll write mul as my generic\noperator here.\n\n994\n00:54:57,170 --> 00:54:58,280\nHow's that going to work?\n\n995\n00:54:58,280 --> 00:55:05,020\nWell 3 plus 4i, say, sits in\nthe system at this level as\n\n996\n00:55:05,020 --> 00:55:06,250\nsomething that looks\nlike this.\n\n997\n00:55:06,250 --> 00:55:08,280\nLet's say it was one\nof George's.\n\n998\n00:55:08,280 --> 00:55:14,695\nSo it would have a 3 and a 4.\n\n999\n00:55:14,695 --> 00:55:18,490\n\n\n1000\n00:55:18,490 --> 00:55:25,330\nAnd attached to that would be\nGeorge's type, which would say\n\n1001\n00:55:25,330 --> 00:55:29,510\nrectangular, it came\nfrom George.\n\n1002\n00:55:29,510 --> 00:55:31,230\nAnd attached to that--\n\n1003\n00:55:31,230 --> 00:55:35,630\nand this itself would be the\ndata view from the next level\n\n1004\n00:55:35,630 --> 00:55:37,700\nup, which it is--\n\n1005\n00:55:37,700 --> 00:55:41,030\nso that itself would be a\ntype-data object which would\n\n1006\n00:55:41,030 --> 00:55:42,280\nsay complex.\n\n1007\n00:55:42,280 --> 00:55:44,820\n\n\n1008\n00:55:44,820 --> 00:55:49,240\nSo that's what this object would\nlook like up here at the\n\n1009\n00:55:49,240 --> 00:55:52,300\nvery highest level, where\nthe really super-generic\n\n1010\n00:55:52,300 --> 00:55:55,560\noperations are looking at it.\n\n1011\n00:55:55,560 --> 00:55:58,220\nNow what happens, mul\neventually's going to come\n\n1012\n00:55:58,220 --> 00:56:00,400\nalong and say, oh,\nwhat's it's type?\n\n1013\n00:56:00,400 --> 00:56:01,650\nIt's type is complex.\n\n1014\n00:56:01,650 --> 00:56:04,270\n\n\n1015\n00:56:04,270 --> 00:56:08,460\nGo through to operate-2 and say,\noh, what I want to do is\n\n1016\n00:56:08,460 --> 00:56:10,440\napply what's in the table,\nwhich is going to be the\n\n1017\n00:56:10,440 --> 00:56:17,150\nprocedure star complex, on\nthis thing with the type\n\n1018\n00:56:17,150 --> 00:56:17,950\nstripped off.\n\n1019\n00:56:17,950 --> 00:56:22,400\nSo it's going to strip off the\ntype, take that much, and send\n\n1020\n00:56:22,400 --> 00:56:26,288\nthat down into the\ncomplex world.\n\n1021\n00:56:26,288 --> 00:56:28,950\nThe complex world looks at its\noperations and says, oh, I\n\n1022\n00:56:28,950 --> 00:56:31,280\nhave to apply star c.\n\n1023\n00:56:31,280 --> 00:56:34,490\nStar c might say, oh, at some\npoint I want to look at the\n\n1024\n00:56:34,490 --> 00:56:39,420\nmagnitude of this object that\nit's in, that it's got.\n\n1025\n00:56:39,420 --> 00:56:40,160\nAnd they'll say, oh, it's\n\n1026\n00:56:40,160 --> 00:56:41,870\nrectangular, it's one of George's.\n\n1027\n00:56:41,870 --> 00:56:47,340\nSo it'll then strip off the next\nversion of type, and hand\n\n1028\n00:56:47,340 --> 00:56:52,160\nthat down to George to take\nthe magnitude of.\n\n1029\n00:56:52,160 --> 00:56:55,290\nSo you see what's going\non is that there are\n\n1030\n00:56:55,290 --> 00:56:59,320\nthese chains of types.\n\n1031\n00:56:59,320 --> 00:57:01,530\nAnd the length of the chain is\nsort of the number of levels\n\n1032\n00:57:01,530 --> 00:57:05,090\nthat you're going to be going\nup in this table.\n\n1033\n00:57:05,090 --> 00:57:09,590\nAnd what a type tells you, every\ntime you have a vertical\n\n1034\n00:57:09,590 --> 00:57:12,350\nbarrier in this table, where\nthere's some ambiguity about\n\n1035\n00:57:12,350 --> 00:57:15,010\nwhere you should go down to the\nnext level, the type is\n\n1036\n00:57:15,010 --> 00:57:17,440\ntelling you where to go.\n\n1037\n00:57:17,440 --> 00:57:19,950\nAnd then everybody at the\nbottom, as they construct data\n\n1038\n00:57:19,950 --> 00:57:22,810\nand filter it up, they stick\ntheir type back on.\n\n1039\n00:57:22,810 --> 00:57:25,350\n\n\n1040\n00:57:25,350 --> 00:57:30,750\nSo that's the general structure\nof the system.\n\n1041\n00:57:30,750 --> 00:57:33,410\n\n\n1042\n00:57:33,410 --> 00:57:34,820\nOK.\n\n1043\n00:57:34,820 --> 00:57:38,660\nNow that we've got this, let's\ngo and make this thing even\n\n1044\n00:57:38,660 --> 00:57:39,910\nmore complex.\n\n1045\n00:57:39,910 --> 00:57:41,890\n\n\n1046\n00:57:41,890 --> 00:57:46,150\nLet's talk about adding to the\nsystem not only these kinds of\n\n1047\n00:57:46,150 --> 00:57:49,680\nnumbers, but it's also\nmeaningful to start talking\n\n1048\n00:57:49,680 --> 00:57:51,510\nabout adding polynomials.\n\n1049\n00:57:51,510 --> 00:57:53,360\nMight do arithmetic\non polynomials.\n\n1050\n00:57:53,360 --> 00:57:57,570\nLike we could have x to the\nfifteenth plus 2x to the\n\n1051\n00:57:57,570 --> 00:58:04,480\nseventh plus 5.\n\n1052\n00:58:04,480 --> 00:58:06,380\nThat might be some polynomial.\n\n1053\n00:58:06,380 --> 00:58:08,720\nAnd if we have two such gadgets\nwe can add them or\n\n1054\n00:58:08,720 --> 00:58:10,530\nmultiply them.\n\n1055\n00:58:10,530 --> 00:58:12,140\nLet's not worry about\ndividing them.\n\n1056\n00:58:12,140 --> 00:58:15,870\nJust add them, multiply them,\nthen we'll subtract them.\n\n1057\n00:58:15,870 --> 00:58:16,660\nWhat do we have to do?\n\n1058\n00:58:16,660 --> 00:58:21,830\nWell let's think about how we\nmight represent a polynomial.\n\n1059\n00:58:21,830 --> 00:58:24,950\nIt's going to be some\ntyped data object.\n\n1060\n00:58:24,950 --> 00:58:29,690\nSo let's say a polynomial to\nthis system might look like a\n\n1061\n00:58:29,690 --> 00:58:32,000\nthing that starts with\nthe type polynomial.\n\n1062\n00:58:32,000 --> 00:58:33,710\nAnd then maybe it says the\nnext thing is what\n\n1063\n00:58:33,710 --> 00:58:34,550\nvariable its in.\n\n1064\n00:58:34,550 --> 00:58:38,960\nSo I might say I'm a polynomial\nin the variable x.\n\n1065\n00:58:38,960 --> 00:58:40,500\nAnd then it'll have some\ninformation about\n\n1066\n00:58:40,500 --> 00:58:42,250\nwhat the terms are.\n\n1067\n00:58:42,250 --> 00:58:45,620\nAnd there're just tons of ways\nto do this, but one way is to\n\n1068\n00:58:45,620 --> 00:58:51,520\nsay we're going to have a thing\ncalled a term-list. And\n\n1069\n00:58:51,520 --> 00:58:53,700\na term-list--\n\n1070\n00:58:53,700 --> 00:58:54,830\nwell, in our case we'll\nuse something\n\n1071\n00:58:54,830 --> 00:58:56,360\nthat looks like this.\n\n1072\n00:58:56,360 --> 00:58:59,010\nWe'll make it a bunch of pairs\nwhich have an order in a\n\n1073\n00:58:59,010 --> 00:58:59,690\ncoefficient.\n\n1074\n00:58:59,690 --> 00:59:09,070\nSo this polynomial would be\nrepresented by this term-list.\n\n1075\n00:59:09,070 --> 00:59:12,910\nAnd what that means is that\nthis polynomial starts off\n\n1076\n00:59:12,910 --> 00:59:19,710\nwith a term of order 15\nand coefficient 1.\n\n1077\n00:59:19,710 --> 00:59:23,820\n\n\n1078\n00:59:23,820 --> 00:59:26,780\nAnd the next thing in it is\na term of order 7 and\n\n1079\n00:59:26,780 --> 00:59:29,680\ncoefficient 2, a term of order\n0, which is constant in\n\n1080\n00:59:29,680 --> 00:59:31,450\ncoefficient 5.\n\n1081\n00:59:31,450 --> 00:59:35,600\nAnd there are lots and lots of\nways, and lots and lots of\n\n1082\n00:59:35,600 --> 00:59:37,890\ntrade-offs when you really think\nabout making algebraic\n\n1083\n00:59:37,890 --> 00:59:40,570\nmanipulation packages about\nexactly how you should\n\n1084\n00:59:40,570 --> 00:59:41,730\nrepresent these things.\n\n1085\n00:59:41,730 --> 00:59:44,180\nBut this is a fairly\nstandard one.\n\n1086\n00:59:44,180 --> 00:59:47,770\nIt's useful in a lot\nof contexts.\n\n1087\n00:59:47,770 --> 00:59:50,815\nOK, well how do we implement\nour polynomial arithmetic?\n\n1088\n00:59:50,815 --> 00:59:54,270\n\n\n1089\n00:59:54,270 --> 00:59:55,520\nLet's start out.\n\n1090\n00:59:55,520 --> 00:59:57,950\n\n\n1091\n00:59:57,950 --> 01:00:00,760\nWhat we'll do to make\na polynomial--\n\n1092\n01:00:00,760 --> 01:00:05,690\nwe'll first have a way\nto make polynomials.\n\n1093\n01:00:05,690 --> 01:00:08,560\nWe're going to make a polynomial\nout of variable\n\n1094\n01:00:08,560 --> 01:00:13,180\nlike x and term-list. And all\nthat does is we'll package\n\n1095\n01:00:13,180 --> 01:00:14,290\nthem together someway.\n\n1096\n01:00:14,290 --> 01:00:18,740\nWe'll put the variable together\nwith the term list\n\n1097\n01:00:18,740 --> 01:00:21,380\nusing cons, and then attached\nto that the type polynomial.\n\n1098\n01:00:21,380 --> 01:00:26,270\n\n\n1099\n01:00:26,270 --> 01:00:29,280\nOK, how do we add\ntwo polynomials?\n\n1100\n01:00:29,280 --> 01:00:33,330\nTo add a polynomial, p1 and\np2, and then just for\n\n1101\n01:00:33,330 --> 01:00:36,060\nsimplicity let's say\nwe will only add\n\n1102\n01:00:36,060 --> 01:00:37,380\nthings in the same variable.\n\n1103\n01:00:37,380 --> 01:00:40,740\nSo if they have the same\nvariable, and same variable\n\n1104\n01:00:40,740 --> 01:00:43,160\nhere is going to be some\nselector we write, whose\n\n1105\n01:00:43,160 --> 01:00:45,150\ndetails we don't care about.\n\n1106\n01:00:45,150 --> 01:00:48,280\nIf the two polynomials have the\nsame variable, then we'll\n\n1107\n01:00:48,280 --> 01:00:48,810\ndo something.\n\n1108\n01:00:48,810 --> 01:00:52,350\nIf they don't have the same\nvariable, we'll give an error,\n\n1109\n01:00:52,350 --> 01:00:55,480\npolynomials not in the\nsame variable.\n\n1110\n01:00:55,480 --> 01:00:58,120\nAnd if they do have the same\nvariable, what we'll do is\n\n1111\n01:00:58,120 --> 01:01:01,130\nwe'll make a polynomial whose\nvariable is whatever that\n\n1112\n01:01:01,130 --> 01:01:05,570\nvariable is, and whose term-list\nis something we'll\n\n1113\n01:01:05,570 --> 01:01:10,170\ncall sum-terms. Plus terms will\nadd the two term lists.\n\n1114\n01:01:10,170 --> 01:01:13,500\nSo we'll add the two term\nlists to the polynomial.\n\n1115\n01:01:13,500 --> 01:01:16,755\nThat'll give us a term-list.\nWe'll add on, we'll say it's a\n\n1116\n01:01:16,755 --> 01:01:19,500\npolynomial in the variable\nwith that\n\n1117\n01:01:19,500 --> 01:01:22,550\nterm-list. That's plus poly.\n\n1118\n01:01:22,550 --> 01:01:26,360\nAnd then we're going to put in\nour table under the type\n\n1119\n01:01:26,360 --> 01:01:30,520\npolynomial, add them\nusing plus poly.\n\n1120\n01:01:30,520 --> 01:01:31,750\nAnd of course we really\nhaven't done much.\n\n1121\n01:01:31,750 --> 01:01:34,360\nWhat we've really done is pushed\nall the work onto this\n\n1122\n01:01:34,360 --> 01:01:38,480\nthing, plus-terms, which is\nsupposed to add term-lists.\n\n1123\n01:01:38,480 --> 01:01:40,920\nLet's look at that.\n\n1124\n01:01:40,920 --> 01:01:48,900\nHere's an overview of how we\nmight add two term-lists.\n\n1125\n01:01:48,900 --> 01:01:51,860\nSo L1 and L2 were going\nto be two term-lists.\n\n1126\n01:01:51,860 --> 01:01:55,700\nAnd a term-list is a bunch of\npairs, coefficient in order.\n\n1127\n01:01:55,700 --> 01:01:56,950\nAnd it's a big case analysis.\n\n1128\n01:01:56,950 --> 01:01:59,860\n\n\n1129\n01:01:59,860 --> 01:02:03,470\nAnd the first thing we'll check\nfor and see if there are\n\n1130\n01:02:03,470 --> 01:02:07,020\nany terms. We're going to\nrecursively work down these\n\n1131\n01:02:07,020 --> 01:02:09,980\nterm-lists, so eventually we'll\nget to a place where\n\n1132\n01:02:09,980 --> 01:02:12,270\neither L1 or L2 might\nbe empty.\n\n1133\n01:02:12,270 --> 01:02:15,160\nAnd if either one is empty,\nour answer will\n\n1134\n01:02:15,160 --> 01:02:15,850\nbe the other one.\n\n1135\n01:02:15,850 --> 01:02:20,720\nSo if L1 is empty we'll return\nL2, and if L2 is empty\n\n1136\n01:02:20,720 --> 01:02:23,470\nwe'll return L1.\n\n1137\n01:02:23,470 --> 01:02:27,220\nOtherwise there are sort of\nthree interesting cases.\n\n1138\n01:02:27,220 --> 01:02:30,560\nWhat we're going to do is grab\nthe first term in each of\n\n1139\n01:02:30,560 --> 01:02:37,660\nthose lists, called t1 and t2.\n\n1140\n01:02:37,660 --> 01:02:43,090\nAnd we're going to look at\nthree cases, depending on\n\n1141\n01:02:43,090 --> 01:02:47,230\nwhether the order of t1 is\ngreater than the order of t2,\n\n1142\n01:02:47,230 --> 01:02:50,470\nor less than t2, or the same.\n\n1143\n01:02:50,470 --> 01:02:53,290\n\n\n1144\n01:02:53,290 --> 01:02:54,910\nThose are the three cases\nwe're going to look at.\n\n1145\n01:02:54,910 --> 01:02:56,160\nLet's look at this case.\n\n1146\n01:02:56,160 --> 01:02:58,640\n\n\n1147\n01:02:58,640 --> 01:03:03,550\nIf the order of t1 is greater\nthan the order of t2, then\n\n1148\n01:03:03,550 --> 01:03:08,280\nwhat that means is that our\nanswer is going to start with\n\n1149\n01:03:08,280 --> 01:03:11,480\nthis term of the order of t1.\n\n1150\n01:03:11,480 --> 01:03:14,455\nBecause it won't combine with\nany lower order terms. So what\n\n1151\n01:03:14,455 --> 01:03:19,720\nwe do is add the lower order\nterms. We recursively add\n\n1152\n01:03:19,720 --> 01:03:21,900\ntogether all the terms\nin the rest of the\n\n1153\n01:03:21,900 --> 01:03:26,880\nterm-list in L1 and L2.\n\n1154\n01:03:26,880 --> 01:03:30,120\nThat's going to be the lower\norder terms of the answer.\n\n1155\n01:03:30,120 --> 01:03:31,490\nAnd then we're going to\nadjoin to that the\n\n1156\n01:03:31,490 --> 01:03:33,180\nhighest order term.\n\n1157\n01:03:33,180 --> 01:03:35,120\nAnd I'm using here a whole bunch\nof procedures I haven't\n\n1158\n01:03:35,120 --> 01:03:39,360\ndefined, like a adjoin-term, and\nrest-terms, and selectors\n\n1159\n01:03:39,360 --> 01:03:41,410\nthat get order.\n\n1160\n01:03:41,410 --> 01:03:44,730\nBut you can imagine\nwhat those are.\n\n1161\n01:03:44,730 --> 01:03:48,550\nSo if the first term-list has\na higher order than the\n\n1162\n01:03:48,550 --> 01:03:51,830\nsecond, we recursively add all\nthe lower terms and then stick\n\n1163\n01:03:51,830 --> 01:03:55,540\non that last term.\n\n1164\n01:03:55,540 --> 01:03:56,890\nThe other case, the same way.\n\n1165\n01:03:56,890 --> 01:04:05,400\nIf the first term has a smaller\norder, well then we\n\n1166\n01:04:05,400 --> 01:04:07,740\nadd the first term-list and the\nrest of the terms in the\n\n1167\n01:04:07,740 --> 01:04:11,430\nsecond one, and adjoin on\nthis highest order term.\n\n1168\n01:04:11,430 --> 01:04:14,570\n\n\n1169\n01:04:14,570 --> 01:04:16,660\nSo so far nothing's much\nhappened, we've just sort of\n\n1170\n01:04:16,660 --> 01:04:19,700\npushed this thing off into\nadding lower order terms. The\n\n1171\n01:04:19,700 --> 01:04:22,870\nlast case where you actually get\nto a coefficients that you\n\n1172\n01:04:22,870 --> 01:04:24,240\nhave to add, this will\nbe the case where\n\n1173\n01:04:24,240 --> 01:04:27,240\nthe orders are equal.\n\n1174\n01:04:27,240 --> 01:04:30,340\nWhat we do is, well again\nrecursively add the lower\n\n1175\n01:04:30,340 --> 01:04:33,460\norder terms. But now we have to\nreally combine something.\n\n1176\n01:04:33,460 --> 01:04:38,960\nWhat we do is we make a term\nwhose order is the order of\n\n1177\n01:04:38,960 --> 01:04:40,820\nthe term we're looking at.\n\n1178\n01:04:40,820 --> 01:04:44,320\nBy now t1 and t2 have\nthe same order.\n\n1179\n01:04:44,320 --> 01:04:45,090\nThat's its order.\n\n1180\n01:04:45,090 --> 01:04:50,400\nAnd its coefficient is gotten\nby adding the coefficient of\n\n1181\n01:04:50,400 --> 01:04:52,230\nt1 and the coefficient of t2.\n\n1182\n01:04:52,230 --> 01:04:56,360\n\n\n1183\n01:04:56,360 --> 01:04:59,800\nThis is a big recursive working\ndown of terms, but\n\n1184\n01:04:59,800 --> 01:05:03,070\nreally there's only one\ninteresting symbol in this\n\n1185\n01:05:03,070 --> 01:05:05,900\nprocedure, only one\ninteresting idea.\n\n1186\n01:05:05,900 --> 01:05:08,500\nThe interesting idea\nis this add.\n\n1187\n01:05:08,500 --> 01:05:12,390\n\n\n1188\n01:05:12,390 --> 01:05:15,330\nAnd the reason that's\ninteresting is because\n\n1189\n01:05:15,330 --> 01:05:18,220\nsomething completely wonderful\njust happened.\n\n1190\n01:05:18,220 --> 01:05:25,440\nWe reduced adding polynomials,\nnot to sort of plus, but to\n\n1191\n01:05:25,440 --> 01:05:28,820\nthe generic add.\n\n1192\n01:05:28,820 --> 01:05:33,270\nIn other words, by implementing\nit that way, not\n\n1193\n01:05:33,270 --> 01:05:37,530\nonly do we have our system where\nwe can have rational\n\n1194\n01:05:37,530 --> 01:05:42,090\nnumbers, or complex numbers,\nor ordinary numbers, we've\n\n1195\n01:05:42,090 --> 01:05:43,340\njust added on polynomials.\n\n1196\n01:05:43,340 --> 01:05:48,520\n\n\n1197\n01:05:48,520 --> 01:05:51,820\nBut the coefficients of the\npolynomials can be anything\n\n1198\n01:05:51,820 --> 01:05:53,590\nthat the system can add.\n\n1199\n01:05:53,590 --> 01:05:57,450\nSo these could be polynomials\nwhose coefficients are\n\n1200\n01:05:57,450 --> 01:06:04,110\nrational numbers or complex\nnumbers, which in turn could\n\n1201\n01:06:04,110 --> 01:06:11,250\nbe either rectangular, or polar,\nor ordinary numbers.\n\n1202\n01:06:11,250 --> 01:06:19,860\n\n\n1203\n01:06:19,860 --> 01:06:23,460\nSo what I mean precisely\nis our system right now\n\n1204\n01:06:23,460 --> 01:06:30,200\nautomatically can handle things\nlike adding together\n\n1205\n01:06:30,200 --> 01:06:35,830\npolynomials that have this one:\n2/3 of x squared plus\n\n1206\n01:06:35,830 --> 01:06:40,940\n5/17 x plus 11/4.\n\n1207\n01:06:40,940 --> 01:06:44,210\nOr automatically handle\npolynomials that look like 3\n\n1208\n01:06:44,210 --> 01:06:54,160\nplus 2i times x to the fifth\nplus 4 plus 7i, or something.\n\n1209\n01:06:54,160 --> 01:06:56,210\nYou can automatically\nhandle those things.\n\n1210\n01:06:56,210 --> 01:06:57,820\nWhy is that?\n\n1211\n01:06:57,820 --> 01:07:03,280\nThat's merely because, or\nprofoundly because we reduced\n\n1212\n01:07:03,280 --> 01:07:06,790\nadding polynomials to adding\ntheir coefficients.\n\n1213\n01:07:06,790 --> 01:07:09,670\nAnd adding coefficients was\ndone by the generic add\n\n1214\n01:07:09,670 --> 01:07:12,970\noperator, which said, I don't\ncare what your types are as\n\n1215\n01:07:12,970 --> 01:07:15,170\nlong as I know how to add you.\n\n1216\n01:07:15,170 --> 01:07:17,800\nSo automatically for\nfree we get the\n\n1217\n01:07:17,800 --> 01:07:20,880\nability to handle that.\n\n1218\n01:07:20,880 --> 01:07:24,920\nWhat's even better than that,\nbecause remember one of the\n\n1219\n01:07:24,920 --> 01:07:29,870\nthings we did is we put into the\ntable that the way you add\n\n1220\n01:07:29,870 --> 01:07:34,660\npolynomials is using\nplus poly.\n\n1221\n01:07:34,660 --> 01:07:37,480\nThat means that polynomials\nthemselves are\n\n1222\n01:07:37,480 --> 01:07:39,370\nthings that can be added.\n\n1223\n01:07:39,370 --> 01:07:42,110\nSo for instance let\nme write one here.\n\n1224\n01:07:42,110 --> 01:07:45,260\n\n\n1225\n01:07:45,260 --> 01:07:46,510\nHere's a polynomial.\n\n1226\n01:07:46,510 --> 01:07:50,560\n\n\n1227\n01:07:50,560 --> 01:07:55,080\nSo this gadget here I'm\nwriting up, this is a\n\n1228\n01:07:55,080 --> 01:08:02,710\npolynomial in y whose\ncoefficients are\n\n1229\n01:08:02,710 --> 01:08:04,690\npolynomials in x.\n\n1230\n01:08:04,690 --> 01:08:08,610\n\n\n1231\n01:08:08,610 --> 01:08:13,110\nSo you see, simply by saying,\npolynomials are themselves\n\n1232\n01:08:13,110 --> 01:08:15,590\nthings that can be added, we can\ngo off and say, well not\n\n1233\n01:08:15,590 --> 01:08:19,560\nonly can we deal with rationals,\nor complex, or\n\n1234\n01:08:19,560 --> 01:08:22,330\nordinary numbers, but we can\ndeal with polynomials whose\n\n1235\n01:08:22,330 --> 01:08:25,420\ncoefficients are rationals, or\ncomplex, or ordinary numbers,\n\n1236\n01:08:25,420 --> 01:08:31,979\nor polynomials whose\ncoefficients are rationals, or\n\n1237\n01:08:31,979 --> 01:08:37,569\ncomplex, rectangular, polar,\nor ordinary numbers, or\n\n1238\n01:08:37,569 --> 01:08:42,609\npolynomials whose coefficients\nare rationals, complex, or\n\n1239\n01:08:42,609 --> 01:08:43,670\nordinary numbers.\n\n1240\n01:08:43,670 --> 01:08:45,950\nAnd so on, and so\non, and so on.\n\n1241\n01:08:45,950 --> 01:08:50,830\nSo this is sort of an infinite\nor maybe a recursive tower of\n\n1242\n01:08:50,830 --> 01:08:53,880\ntypes that we've built up.\n\n1243\n01:08:53,880 --> 01:08:56,420\nAnd it's all exactly from\nthat one little symbol.\n\n1244\n01:08:56,420 --> 01:08:59,615\nA-D-D. Writing \"add\" instead\nof \"plus\" in\n\n1245\n01:08:59,615 --> 01:09:02,270\nthe polynomial thing.\n\n1246\n01:09:02,270 --> 01:09:04,620\nSlightly different way to\nthink about it is that\n\n1247\n01:09:04,620 --> 01:09:08,740\npolynomials are a constructor\nfor types.\n\n1248\n01:09:08,740 --> 01:09:12,149\nNamely you give it a type, like\ninteger, and it returns\n\n1249\n01:09:12,149 --> 01:09:16,279\nfor you polynomials in x whose\ncoefficients are integers.\n\n1250\n01:09:16,279 --> 01:09:20,010\nAnd the important thing about\nthat is that the operations on\n\n1251\n01:09:20,010 --> 01:09:22,729\npolynomials reduce to the\noperations on the\n\n1252\n01:09:22,729 --> 01:09:23,500\ncoefficients.\n\n1253\n01:09:23,500 --> 01:09:25,840\nAnd there are a lot of\nthings like that.\n\n1254\n01:09:25,840 --> 01:09:28,870\nSo for example, let's go back\nand rational numbers.\n\n1255\n01:09:28,870 --> 01:09:32,410\nWe thought about rational\nnumbers as an integer over an\n\n1256\n01:09:32,410 --> 01:09:34,229\ninteger, but there's\nthe general notion\n\n1257\n01:09:34,229 --> 01:09:36,240\nof a rational object.\n\n1258\n01:09:36,240 --> 01:09:43,010\nLike we might think about 3x\nplus 7 over x squared plus 1.\n\n1259\n01:09:43,010 --> 01:09:47,430\nThat's general rational object\nwhose numerator and\n\n1260\n01:09:47,430 --> 01:09:50,310\ndenominator are polynomials.\n\n1261\n01:09:50,310 --> 01:09:52,990\nAnd to add two of them we use\nthe same formula, numerator\n\n1262\n01:09:52,990 --> 01:09:55,720\ntimes denominator plus\ndenominator times numerator\n\n1263\n01:09:55,720 --> 01:09:57,290\nover product of denominators.\n\n1264\n01:09:57,290 --> 01:09:59,430\nHow could we install\nthat in our system?\n\n1265\n01:09:59,430 --> 01:10:01,820\nWell here's our original\nrational\n\n1266\n01:10:01,820 --> 01:10:04,250\nnumber arithmetic package.\n\n1267\n01:10:04,250 --> 01:10:08,660\nAnd all we have to do in order\nto make the entire system\n\n1268\n01:10:08,660 --> 01:10:12,530\ncontinue working with general\nrational objects, is replace\n\n1269\n01:10:12,530 --> 01:10:16,480\nthese particular pluses and\nstars by the generic operator.\n\n1270\n01:10:16,480 --> 01:10:19,870\nSo if we simply change that\nprocedure to this one, here\n\n1271\n01:10:19,870 --> 01:10:23,100\nwe've changed plus and star\nto add a mul, those are\n\n1272\n01:10:23,100 --> 01:10:28,170\nabsolutely the only change,\nthen suddenly our entire\n\n1273\n01:10:28,170 --> 01:10:34,000\nsystem can start talking about\nobjects that look like this.\n\n1274\n01:10:34,000 --> 01:10:40,350\nSo for example, here is a\nrational object whose\n\n1275\n01:10:40,350 --> 01:10:44,030\nnumerator is a polynomial in\nx whose coefficients are\n\n1276\n01:10:44,030 --> 01:10:47,350\nrational numbers.\n\n1277\n01:10:47,350 --> 01:10:53,740\nOr here is a rational object\nwhose numerator is polynomials\n\n1278\n01:10:53,740 --> 01:11:00,480\nin x whose coefficients are\nrational objects constructed\n\n1279\n01:11:00,480 --> 01:11:03,390\nout of complex numbers.\n\n1280\n01:11:03,390 --> 01:11:04,850\nAnd then there are a lot of\nother things like that.\n\n1281\n01:11:04,850 --> 01:11:07,500\nSee, whenever you have a thing\nwhere the operations reduce to\n\n1282\n01:11:07,500 --> 01:11:10,450\noperations on the pieces,\nanother example would be two\n\n1283\n01:11:10,450 --> 01:11:12,310\nby two matrices.\n\n1284\n01:11:12,310 --> 01:11:17,030\nI have the idea, there might\nbe a matrix here of general\n\n1285\n01:11:17,030 --> 01:11:18,650\nthings that I don't\ncare about.\n\n1286\n01:11:18,650 --> 01:11:25,180\nBut if I add two of them, the\nanswer over here is gotten by\n\n1287\n01:11:25,180 --> 01:11:29,030\nadding this one and that one,\nhowever they like to add.\n\n1288\n01:11:29,030 --> 01:11:31,110\nSo I can implement that\nthe same way.\n\n1289\n01:11:31,110 --> 01:11:33,520\nAnd if I do that, then again\nsuddenly my system can start\n\n1290\n01:11:33,520 --> 01:11:35,480\nhandling things like this.\n\n1291\n01:11:35,480 --> 01:11:39,460\nSo here's a matrix whose\nelements happen to be--\n\n1292\n01:11:39,460 --> 01:11:43,330\nwe'll say this element here\nis a rational object whose\n\n1293\n01:11:43,330 --> 01:11:47,230\nnumerator and denominators\nare polynomials.\n\n1294\n01:11:47,230 --> 01:11:49,510\nAnd all that comes for free.\n\n1295\n01:11:49,510 --> 01:11:52,580\n\n\n1296\n01:11:52,580 --> 01:11:53,920\nWhat's really going on here?\n\n1297\n01:11:53,920 --> 01:11:58,910\nWhat's really going on is\ngetting rid of this manager\n\n1298\n01:11:58,910 --> 01:12:02,060\nwho's sitting there poking his\nnose into who everybody's\n\n1299\n01:12:02,060 --> 01:12:03,120\nbusiness is.\n\n1300\n01:12:03,120 --> 01:12:05,900\nWe built a system that has\ndecentralized control.\n\n1301\n01:12:05,900 --> 01:12:14,350\n\n\n1302\n01:12:14,350 --> 01:12:18,340\nSo when you come into and no\none's poking around saying,\n\n1303\n01:12:18,340 --> 01:12:21,080\ngee, are you in the\nofficial list of\n\n1304\n01:12:21,080 --> 01:12:22,440\npeople who can be added?\n\n1305\n01:12:22,440 --> 01:12:24,850\nRather you say, well go off\nand add yourself how your\n\n1306\n01:12:24,850 --> 01:12:27,810\nparts like to be added.\n\n1307\n01:12:27,810 --> 01:12:31,030\nAnd the result of that is you\ncan get this very, very, very\n\n1308\n01:12:31,030 --> 01:12:33,870\ncomplex hierarchy where a lot\nof things just get done and\n\n1309\n01:12:33,870 --> 01:12:36,482\nrooted to the right place\nautomatically.\n\n1310\n01:12:36,482 --> 01:12:37,732\nLet's stop for questions.\n\n1311\n01:12:37,732 --> 01:12:40,380\n\n\n1312\n01:12:40,380 --> 01:12:43,020\nAUDIENCE: You say you\nget this for free.\n\n1313\n01:12:43,020 --> 01:12:46,920\nOne thing that strikes me is\nthat now you've lost kind of\n\n1314\n01:12:46,920 --> 01:12:50,150\nthe cleanness of the break\nbetween what's on top and\n\n1315\n01:12:50,150 --> 01:12:50,910\nwhat's underneath.\n\n1316\n01:12:50,910 --> 01:12:52,770\nIn other words, now you're\ndefining some of the\n\n1317\n01:12:52,770 --> 01:12:54,850\nlower-level procedures\nin terms of things\n\n1318\n01:12:54,850 --> 01:12:56,610\nabove their own line.\n\n1319\n01:12:56,610 --> 01:13:00,350\nIsn't that dangerous?\n\n1320\n01:13:00,350 --> 01:13:05,440\nOr, if nothing more, a little\nless structured?\n\n1321\n01:13:05,440 --> 01:13:06,125\nPROFESSOR: No, I--\n\n1322\n01:13:06,125 --> 01:13:07,770\nthe question is whether that's\nless structured.\n\n1323\n01:13:07,770 --> 01:13:08,690\nDepends on what you\nmean by structure.\n\n1324\n01:13:08,690 --> 01:13:11,050\nAll this is doing\nis recursion.\n\n1325\n01:13:11,050 --> 01:13:15,780\nSee, it's saying that the\nway you add these\n\n1326\n01:13:15,780 --> 01:13:18,640\nguys is to use that.\n\n1327\n01:13:18,640 --> 01:13:20,520\nAnd that's not less structured,\nit's just a\n\n1328\n01:13:20,520 --> 01:13:22,610\nrecursive structure.\n\n1329\n01:13:22,610 --> 01:13:24,730\nSo I don't think it's\nparticularly any less clean.\n\n1330\n01:13:24,730 --> 01:13:27,250\nAUDIENCE: Now when you want to\nchange the multiplier or the\n\n1331\n01:13:27,250 --> 01:13:31,380\nadd operator, suddenly you've\ngot tremendous consequences\n\n1332\n01:13:31,380 --> 01:13:34,480\nunderneath that you're not\neven sure the extent of.\n\n1333\n01:13:34,480 --> 01:13:37,080\nPROFESSOR: That's right, but\nit depends what you mean.\n\n1334\n01:13:37,080 --> 01:13:38,470\nSee, this goes both ways.\n\n1335\n01:13:38,470 --> 01:13:41,790\n\n\n1336\n01:13:41,790 --> 01:13:44,690\nWhat would be a good example?\n\n1337\n01:13:44,690 --> 01:13:47,500\nI ignored greatest common\ndivisor, for instance.\n\n1338\n01:13:47,500 --> 01:13:50,280\nI ignored that problem just to\nkeep the example simple.\n\n1339\n01:13:50,280 --> 01:13:59,820\nBut if I suddenly decided that\nplus rat here should do a GCD\n\n1340\n01:13:59,820 --> 01:14:04,750\ncomputation and install that,\nthen that immediately becomes\n\n1341\n01:14:04,750 --> 01:14:08,280\navailable to all of these, to\nthat guy, and that guy, and\n\n1342\n01:14:08,280 --> 01:14:11,560\nthat guy, and all\nthe way down.\n\n1343\n01:14:11,560 --> 01:14:13,890\nSo it depends what you mean by\nthe coherence of your system.\n\n1344\n01:14:13,890 --> 01:14:17,030\nIt's certainly true that you\nmight want to have a special\n\n1345\n01:14:17,030 --> 01:14:18,950\ndifferent one that didn't\nfilter down through the\n\n1346\n01:14:18,950 --> 01:14:21,400\ncoefficients, but the nice thing\nabout this particular\n\n1347\n01:14:21,400 --> 01:14:25,440\nexample is that mostly you do.\n\n1348\n01:14:25,440 --> 01:14:27,630\nAUDIENCE: Isn't that the\nproblem, I think, that you're\n\n1349\n01:14:27,630 --> 01:14:32,950\ngetting to tied in with the fact\nthat the structuring, the\n\n1350\n01:14:32,950 --> 01:14:36,330\nrecursiveness of that\nstructuring there is actually\n\n1351\n01:14:36,330 --> 01:14:40,340\nin execution as opposed to just\ndefinition of the actual\n\n1352\n01:14:40,340 --> 01:14:41,590\ntypes themselves?\n\n1353\n01:14:41,590 --> 01:14:44,680\n\n\n1354\n01:14:44,680 --> 01:14:46,120\nPROFESSOR: I think I understand\nthe question.\n\n1355\n01:14:46,120 --> 01:14:48,650\nThe point is that these types\nevolve and get more and more\n\n1356\n01:14:48,650 --> 01:14:50,400\ncomplex as the thing's\nactually running.\n\n1357\n01:14:50,400 --> 01:14:50,730\nIs that what--\n\n1358\n01:14:50,730 --> 01:14:50,990\nAUDIENCE: Yes.\n\n1359\n01:14:50,990 --> 01:14:51,790\nAs it's running.\n\n1360\n01:14:51,790 --> 01:14:51,956\nPROFESSOR: --what\nyou're saying?\n\n1361\n01:14:51,956 --> 01:14:52,090\nYes, the point is--\n\n1362\n01:14:52,090 --> 01:14:54,180\nAUDIENCE: As opposed to\nthe basic definitions.\n\n1363\n01:14:54,180 --> 01:14:54,830\nPROFESSOR: Right.\n\n1364\n01:14:54,830 --> 01:14:57,210\nThe type structure is\nsort of recursive.\n\n1365\n01:14:57,210 --> 01:15:02,770\nIt's not that you can make this\nfinite list of the actual\n\n1366\n01:15:02,770 --> 01:15:04,850\nthings they might look like\nbefore the system runs.\n\n1367\n01:15:04,850 --> 01:15:06,780\nIt's something that evolves.\n\n1368\n01:15:06,780 --> 01:15:09,610\nSo if you want to specify that\nsystem, you have to do in some\n\n1369\n01:15:09,610 --> 01:15:12,275\nother way than by this finite\nlist. You have to do it by a\n\n1370\n01:15:12,275 --> 01:15:13,670\nrecursive structure.\n\n1371\n01:15:13,670 --> 01:15:16,960\nAUDIENCE: Because the basic\nstructure of the types is\n\n1372\n01:15:16,960 --> 01:15:17,900\npretty clean and simple.\n\n1373\n01:15:17,900 --> 01:15:20,125\nPROFESSOR: Right.\n\n1374\n01:15:20,125 --> 01:15:21,460\nYes?\n\n1375\n01:15:21,460 --> 01:15:22,870\nAUDIENCE: I have a question.\n\n1376\n01:15:22,870 --> 01:15:25,980\nI understand once you have your\ndata structure set up,\n\n1377\n01:15:25,980 --> 01:15:29,230\nhow it pulls off complex and\npasses that down, and then\n\n1378\n01:15:29,230 --> 01:15:30,640\npulls off rect, passes\nthat down.\n\n1379\n01:15:30,640 --> 01:15:32,790\nBut if you're just a user and\nyou don't know anything about\n\n1380\n01:15:32,790 --> 01:15:35,610\nrect or polar or whatever, how\ndo you initially set up that\n\n1381\n01:15:35,610 --> 01:15:37,330\ndata structure so that\neverything goes\n\n1382\n01:15:37,330 --> 01:15:38,390\nto the right spot?\n\n1383\n01:15:38,390 --> 01:15:41,210\nIf I just have the equation over\nthere on the left and I\n\n1384\n01:15:41,210 --> 01:15:42,500\njust want to add, multiply\ncomplex numbers--\n\n1385\n01:15:42,500 --> 01:15:43,640\nPROFESSOR: Well that's\nthe wonderful thing.\n\n1386\n01:15:43,640 --> 01:15:47,730\nIf you're just a user\nyou say \"mul.\"\n\n1387\n01:15:47,730 --> 01:15:50,280\nAUDIENCE: And it figures out\nthat I mean complex numbers?\n\n1388\n01:15:50,280 --> 01:15:51,420\nOr how do I tell it\nthat I want--\n\n1389\n01:15:51,420 --> 01:15:51,950\nPROFESSOR: Well you're\ngoing to have in your\n\n1390\n01:15:51,950 --> 01:15:53,050\nhands complex numbers.\n\n1391\n01:15:53,050 --> 01:15:56,490\nSee what you would have at some\nlevel, as a real user, is\n\n1392\n01:15:56,490 --> 01:15:58,370\na constructor for\ncomplex numbers.\n\n1393\n01:15:58,370 --> 01:15:59,470\nAUDIENCE: So then I have to\nmake complex numbers?\n\n1394\n01:15:59,470 --> 01:16:00,350\nPROFESSOR: So you have\nto make them.\n\n1395\n01:16:00,350 --> 01:16:03,180\nWhat you would probably have as\na user is some little thing\n\n1396\n01:16:03,180 --> 01:16:07,390\nin the reader loop, which would\ngive you some plausible\n\n1397\n01:16:07,390 --> 01:16:09,850\nway to type in a complex\nnumber, in\n\n1398\n01:16:09,850 --> 01:16:11,590\nwhatever format you like.\n\n1399\n01:16:11,590 --> 01:16:14,360\nOr it might be that you're\nnever typing them in.\n\n1400\n01:16:14,360 --> 01:16:16,170\nSomeone's just handing\nyou a complex number.\n\n1401\n01:16:16,170 --> 01:16:19,500\nAUDIENCE: OK, so if I had a\ncomplex number that had a\n\n1402\n01:16:19,500 --> 01:16:21,505\npolynomial in it, I'd have to\nmake my polynomial and then\n\n1403\n01:16:21,505 --> 01:16:21,960\nmake my complex number.\n\n1404\n01:16:21,960 --> 01:16:24,220\nPROFESSOR: Right if you wanted\nit constructed from scratch.\n\n1405\n01:16:24,220 --> 01:16:25,710\nAt some point you construct\nthem from scratch.\n\n1406\n01:16:25,710 --> 01:16:27,880\nBut what you don't have to know\nof that is when you have\n\n1407\n01:16:27,880 --> 01:16:32,345\nthe object you can just say\n\"mul.\" And it'll multiply.\n\n1408\n01:16:32,345 --> 01:16:33,279\nYeah?\n\n1409\n01:16:33,279 --> 01:16:36,450\nAUDIENCE: I think the question\nthat was being posed here is,\n\n1410\n01:16:36,450 --> 01:16:40,220\nsay if I want to change my\npresentation of complexes, or\n\n1411\n01:16:40,220 --> 01:16:46,330\nsome operation of complex, how\nmuch real code I will have to\n\n1412\n01:16:46,330 --> 01:16:49,860\ngets around with, or change\nto change it in\n\n1413\n01:16:49,860 --> 01:16:52,270\none specific operation?\n\n1414\n01:16:52,270 --> 01:16:53,490\nPROFESSOR: [UNINTELLIGIBLE]\nwhat you have to change.\n\n1415\n01:16:53,490 --> 01:16:54,690\nAnd the point is that\nyou only have to\n\n1416\n01:16:54,690 --> 01:16:56,070\nchange what you're changing.\n\n1417\n01:16:56,070 --> 01:17:00,320\nSee if Martha decides that\nshe would rather--\n\n1418\n01:17:00,320 --> 01:17:01,440\nlet's see something silly--\n\n1419\n01:17:01,440 --> 01:17:04,040\nlike change the order\nin the pair.\n\n1420\n01:17:04,040 --> 01:17:09,700\nLike angle and magnitude in\nthe other order, she just\n\n1421\n01:17:09,700 --> 01:17:10,970\nmakes that change locally.\n\n1422\n01:17:10,970 --> 01:17:12,750\nAnd the whole thing will\npropagate through the system\n\n1423\n01:17:12,750 --> 01:17:14,790\nin the right way.\n\n1424\n01:17:14,790 --> 01:17:18,040\nOr if suddenly you said, gee, I\nhave another representation\n\n1425\n01:17:18,040 --> 01:17:19,700\nfor rationals.\n\n1426\n01:17:19,700 --> 01:17:22,740\nAnd I'm going to stick it\nhere, by filing those\n\n1427\n01:17:22,740 --> 01:17:24,820\noperations in the table.\n\n1428\n01:17:24,820 --> 01:17:27,220\nThen suddenly all of these\npolynomials whose coefficients\n\n1429\n01:17:27,220 --> 01:17:29,240\nare coefficients of\ncoefficients, or whatever,\n\n1430\n01:17:29,240 --> 01:17:32,970\nalso can automatically have\navailable that representation.\n\n1431\n01:17:32,970 --> 01:17:35,952\nThat's the power of this\nparticular one.\n\n1432\n01:17:35,952 --> 01:17:37,625\nAUDIENCE: I'm not sure if I can\neven pose an intelligent\n\n1433\n01:17:37,625 --> 01:17:38,700\nsounding question.\n\n1434\n01:17:38,700 --> 01:17:42,920\nBut somehow this whole thing\nwent really nicely to this\n\n1435\n01:17:42,920 --> 01:17:44,910\nbeautiful finish where\nall the things seemed\n\n1436\n01:17:44,910 --> 01:17:47,280\nto fall into place.\n\n1437\n01:17:47,280 --> 01:17:48,530\nSort of seemed a little\ncontrived.\n\n1438\n01:17:48,530 --> 01:17:50,930\n\n\n1439\n01:17:50,930 --> 01:17:52,670\nThat's all for the sake,\nI'm sure, of teaching.\n\n1440\n01:17:52,670 --> 01:17:55,100\nI doubt that the guys\nwho first did this--\n\n1441\n01:17:55,100 --> 01:17:56,510\nand I could be wrong--\n\n1442\n01:17:56,510 --> 01:17:59,200\nfigured it all out so that when\nthey just all put it all\n\n1443\n01:17:59,200 --> 01:18:02,410\ntogether, you could all of the\nsudden, blam, do any kind of\n\n1444\n01:18:02,410 --> 01:18:04,860\narithmetic on any\nkind of object.\n\n1445\n01:18:04,860 --> 01:18:07,930\nIt seems like maybe they had\nto play with it for a while\n\n1446\n01:18:07,930 --> 01:18:11,800\nand had to bash it\nand rework it.\n\n1447\n01:18:11,800 --> 01:18:14,120\nAnd it seems like that's the\nkind of problem we're really\n\n1448\n01:18:14,120 --> 01:18:16,540\nfaced with we start trying to\ndesign a really complex\n\n1449\n01:18:16,540 --> 01:18:19,390\nsystem, is having lots of\ndifferent kinds of parts and\n\n1450\n01:18:19,390 --> 01:18:22,730\nnot even knowing what kinds of\noperations we're going to want\n\n1451\n01:18:22,730 --> 01:18:24,620\nto do on those parts.\n\n1452\n01:18:24,620 --> 01:18:27,580\nHow to organize the operations\nin this nice way so that no\n\n1453\n01:18:27,580 --> 01:18:29,630\nmatter what you do, when you\nstart putting them together\n\n1454\n01:18:29,630 --> 01:18:31,700\neverything starts falling\nout for free.\n\n1455\n01:18:31,700 --> 01:18:33,090\nPROFESSOR: OK, well\nthat's certainly a\n\n1456\n01:18:33,090 --> 01:18:34,340\nvery intelligent question.\n\n1457\n01:18:34,340 --> 01:18:37,020\n\n\n1458\n01:18:37,020 --> 01:18:40,560\nOne part is this is a very good\nmethodology that people\n\n1459\n01:18:40,560 --> 01:18:44,590\nhave discovered a lot coming\nfrom symbolic algebra.\n\n1460\n01:18:44,590 --> 01:18:47,590\nBecause there are a lot\nof complications.\n\n1461\n01:18:47,590 --> 01:18:50,710\nTo allow you to implement these\nthings before you decide\n\n1462\n01:18:50,710 --> 01:18:52,130\nwhat you want all the\noperations to\n\n1463\n01:18:52,130 --> 01:18:53,310\nbe, and all of that.\n\n1464\n01:18:53,310 --> 01:18:55,580\nSo in some sense it's an\nanswer that people have\n\n1465\n01:18:55,580 --> 01:18:58,560\ndiscovered by wading\nthrough this stuff.\n\n1466\n01:18:58,560 --> 01:19:02,160\nIn another sense, it is a\nvery contrived example.\n\n1467\n01:19:02,160 --> 01:19:06,240\nAUDIENCE: It seems like to be\nable to do this you do have to\n\n1468\n01:19:06,240 --> 01:19:08,320\nwade through it for a certain\namount of time before you can\n\n1469\n01:19:08,320 --> 01:19:09,010\nbecome good at it.\n\n1470\n01:19:09,010 --> 01:19:12,220\nPROFESSOR: Let me show you how\nterribly contrived this is.\n\n1471\n01:19:12,220 --> 01:19:14,130\nSo you can write all these\nwonderful things.\n\n1472\n01:19:14,130 --> 01:19:17,600\nBut the system that I wrote\nhere, and if we had another\n\n1473\n01:19:17,600 --> 01:19:19,820\nhalf an hour to give this\nlecture I would have given\n\n1474\n01:19:19,820 --> 01:19:23,470\nthis part of it, which says,\nnotice that it breaks down if\n\n1475\n01:19:23,470 --> 01:19:30,880\nI tell it to do something as\nfoolish as add 3 plus 7/2.\n\n1476\n01:19:30,880 --> 01:19:33,980\nBecause what will happen is\nyou'll get to operate-2, and\n\n1477\n01:19:33,980 --> 01:19:36,180\noperate-2 will say, oh\nthis is type number,\n\n1478\n01:19:36,180 --> 01:19:37,560\nand that's type rational.\n\n1479\n01:19:37,560 --> 01:19:38,810\nI don't know how to add them.\n\n1480\n01:19:38,810 --> 01:19:41,530\n\n\n1481\n01:19:41,530 --> 01:19:43,600\nSo you'd like the system at\nleast to be able to say\n\n1482\n01:19:43,600 --> 01:19:48,660\nsomething like, gee,\nbefore you do that\n\n1483\n01:19:48,660 --> 01:19:50,480\nchange that to 3/1.\n\n1484\n01:19:50,480 --> 01:19:52,250\nTurn it into a rational number,\nhand that to the\n\n1485\n01:19:52,250 --> 01:19:53,500\nrational package.\n\n1486\n01:19:53,500 --> 01:19:55,510\n\n\n1487\n01:19:55,510 --> 01:19:58,860\nThat's the thing I didn't talk\nabout in this lecture.\n\n1488\n01:19:58,860 --> 01:20:00,880\nIt's a little bit in the book,\nwhich talks about the problem\n\n1489\n01:20:00,880 --> 01:20:03,390\nof what's called coercion.\n\n1490\n01:20:03,390 --> 01:20:05,310\nWhere you wanted--\n\n1491\n01:20:05,310 --> 01:20:08,280\nsee, having so carefully set\nup all of these types as\n\n1492\n01:20:08,280 --> 01:20:11,720\ndistinct objects, a lot of times\nyou want to also put in\n\n1493\n01:20:11,720 --> 01:20:16,650\nknowledge about how to view\nan ordinary number\n\n1494\n01:20:16,650 --> 01:20:19,110\nas a kind of rational.\n\n1495\n01:20:19,110 --> 01:20:21,620\nOr view an ordinary number\nas a kind of complex.\n\n1496\n01:20:21,620 --> 01:20:24,580\nThat's where the complexity in\nthe system really starts\n\n1497\n01:20:24,580 --> 01:20:27,110\nhappening, where you talk\nabout, see where\n\n1498\n01:20:27,110 --> 01:20:28,420\ndo I put that knowledge?\n\n1499\n01:20:28,420 --> 01:20:30,810\nIs it rational to know that\nordinary numbers might be\n\n1500\n01:20:30,810 --> 01:20:33,130\npieces of [UNINTELLIGIBLE]\nof them?\n\n1501\n01:20:33,130 --> 01:20:38,790\nOr they're terrible, terrible\nexamples, like if I might want\n\n1502\n01:20:38,790 --> 01:20:47,510\nto add a complex number\nto a rational number.\n\n1503\n01:20:47,510 --> 01:20:50,080\n\n\n1504\n01:20:50,080 --> 01:20:50,760\nBad example.\n\n1505\n01:20:50,760 --> 01:20:52,010\n5/7.\n\n1506\n01:20:52,010 --> 01:20:53,860\n\n\n1507\n01:20:53,860 --> 01:20:57,300\nThen somebody's got to know that\nI have to convert these\n\n1508\n01:20:57,300 --> 01:20:59,790\nto another type, which is\ncomplex numbers whose parts\n\n1509\n01:20:59,790 --> 01:21:01,540\nmight be rationals.\n\n1510\n01:21:01,540 --> 01:21:02,680\nAnd who worries about that?\n\n1511\n01:21:02,680 --> 01:21:03,950\nDoes complex worry about that?\n\n1512\n01:21:03,950 --> 01:21:05,030\nDoes rational worry\nabout that?\n\n1513\n01:21:05,030 --> 01:21:06,900\nDoes plus worry about that?\n\n1514\n01:21:06,900 --> 01:21:08,520\nThat's where the real\ncomplexity comes in.\n\n1515\n01:21:08,520 --> 01:21:11,380\nAnd that's where it's pretty\nwell sorted out.\n\n1516\n01:21:11,380 --> 01:21:14,810\nAnd a lot of, in fact, all of\nthis message passing stuff was\n\n1517\n01:21:14,810 --> 01:21:18,460\nmotivated by problems\nlike this.\n\n1518\n01:21:18,460 --> 01:21:21,630\nAnd when you really push it,\npeople are-- somehow the\n\n1519\n01:21:21,630 --> 01:21:25,330\nalgebraic manipulation problem\nseems to be so complex that\n\n1520\n01:21:25,330 --> 01:21:27,410\nthe people who are always at the\nedge of it are exactly in\n\n1521\n01:21:27,410 --> 01:21:28,050\nthe state you said.\n\n1522\n01:21:28,050 --> 01:21:29,940\nThey're wading through this\nthing, mucking around, seeing\n\n1523\n01:21:29,940 --> 01:21:33,470\nwhat they use, trying\nto distill stuff.\n\n1524\n01:21:33,470 --> 01:21:36,030\nAUDIENCE: I just want to come\nback to this issue of\n\n1525\n01:21:36,030 --> 01:21:39,250\ncomplexity once more.\n\n1526\n01:21:39,250 --> 01:21:44,550\nIt certainly seems to be true\nthat you have a great deal of\n\n1527\n01:21:44,550 --> 01:21:49,580\nflexibility in altering the\nlower level kinds of things.\n\n1528\n01:21:49,580 --> 01:21:54,320\nBut it is true that you are,\nin a sense, freezing higher\n\n1529\n01:21:54,320 --> 01:21:55,450\nlevel operations.\n\n1530\n01:21:55,450 --> 01:21:58,510\nOr at least if you change them\nyou don't know where all of\n\n1531\n01:21:58,510 --> 01:22:02,060\nthe changes are going to show\nup, or how they are.\n\n1532\n01:22:02,060 --> 01:22:04,840\nPROFESSOR: OK, that's an\nextremely good question.\n\n1533\n01:22:04,840 --> 01:22:10,130\nWhat I have to do is, if I\ndecide there's a new general\n\n1534\n01:22:10,130 --> 01:22:16,300\noperation called equality test,\nthen all of these people\n\n1535\n01:22:16,300 --> 01:22:19,835\nhave to decide whether or not\nthey would like to have an\n\n1536\n01:22:19,835 --> 01:22:24,650\nequality test by looking\nin the table.\n\n1537\n01:22:24,650 --> 01:22:27,870\nThere're ways to decentralize\nit even more.\n\n1538\n01:22:27,870 --> 01:22:31,430\nThat's what I sort of hinted at\nlast time, where I said you\n\n1539\n01:22:31,430 --> 01:22:34,240\ncould not only have this type as\na symbol, but you actually\n\n1540\n01:22:34,240 --> 01:22:37,850\nmight store in each object\nthe operations\n\n1541\n01:22:37,850 --> 01:22:40,450\nthat it knows of that.\n\n1542\n01:22:40,450 --> 01:22:44,670\nSo you might have things like\ngreatest common divisor, which\n\n1543\n01:22:44,670 --> 01:22:47,540\nis a thing here which is defined\nonly for integers, and\n\n1544\n01:22:47,540 --> 01:22:51,030\nnot in general for\nrational numbers.\n\n1545\n01:22:51,030 --> 01:22:53,110\nSo it might be a very, very\nfragmented system.\n\n1546\n01:22:53,110 --> 01:22:56,570\nAnd then depending on where\nyou want your flexibility,\n\n1547\n01:22:56,570 --> 01:22:58,190\nthere's a whole spectrum\nof places that you\n\n1548\n01:22:58,190 --> 01:22:59,960\ncan build that in.\n\n1549\n01:22:59,960 --> 01:23:02,320\nBut you're pointing at the place\nwhere this starts being\n\n1550\n01:23:02,320 --> 01:23:04,540\nweak, that there has to be some\nagreement on top here\n\n1551\n01:23:04,540 --> 01:23:06,370\nabout these general\noperations.\n\n1552\n01:23:06,370 --> 01:23:08,390\nOr at least people have\nto think about them.\n\n1553\n01:23:08,390 --> 01:23:10,340\nOr you might decide, you might\nhave a table that's very\n\n1554\n01:23:10,340 --> 01:23:14,010\nsparse, that only has\na few things in it.\n\n1555\n01:23:14,010 --> 01:23:15,490\nBut there are lot of ways\nto play that game.\n\n1556\n01:23:15,490 --> 01:23:19,780\n\n\n1557\n01:23:19,780 --> 01:23:21,030\nOK, thank you.\n\n1558\n01:23:21,030 --> 01:23:23,534\n\n\n1559\n01:23:23,534 --> 01:23:23,849\n[MUSIC: \"JESU, JOY OF\nMAN'S DESIRING\" BY\n\n1560\n01:23:23,849 --> 01:23:25,099\nJOHANN SEBASTIAN BACH]\n\n1561\n01:23:25,099 --> 01:23:36,682\n\n"
  },
  {
    "path": "SrtEN/lec5a_512kb.mp4.srt",
    "content": "1\n00:00:00,000 --> 00:00:16,830\n[MUSIC PLAYING]\n\n2\n00:00:16,830 --> 00:00:22,480\nPROFESSOR: Well, so far we've\ninvented enough programming to\n\n3\n00:00:22,480 --> 00:00:24,850\ndo some very complicated\nthings.\n\n4\n00:00:24,850 --> 00:00:28,710\nAnd you surely learned\na lot about\n\n5\n00:00:28,710 --> 00:00:29,760\nprogramming at this point.\n\n6\n00:00:29,760 --> 00:00:32,189\nYou've learned almost all the\nmost important tricks that\n\n7\n00:00:32,189 --> 00:00:34,870\nusually don't get taught to\npeople until they have had a\n\n8\n00:00:34,870 --> 00:00:36,610\nlot of experience.\n\n9\n00:00:36,610 --> 00:00:40,800\nFor example, data directed\nprogramming is a major trick,\n\n10\n00:00:40,800 --> 00:00:42,755\nand yesterday you also saw\nan interpreted language.\n\n11\n00:00:42,755 --> 00:00:45,300\n\n\n12\n00:00:45,300 --> 00:00:50,320\nWe did this all in a computer\nlanguage, at this point, where\n\n13\n00:00:50,320 --> 00:00:54,020\nthere was no assignment\nstatement.\n\n14\n00:00:54,020 --> 00:00:56,790\nAnd presumably, for those of you\nwho've seen your Basic or\n\n15\n00:00:56,790 --> 00:01:00,170\nPascal or whatever, that's\nusually considered the most\n\n16\n00:01:00,170 --> 00:01:02,040\nimportant thing.\n\n17\n00:01:02,040 --> 00:01:03,580\nWell today, we're going to\ndo some thing horrible.\n\n18\n00:01:03,580 --> 00:01:07,370\nWe're going to add an assignment\nstatement.\n\n19\n00:01:07,370 --> 00:01:09,220\nAnd since we can do all these\nwonderful things without it,\n\n20\n00:01:09,220 --> 00:01:11,110\nwhy should we add it?\n\n21\n00:01:11,110 --> 00:01:13,040\nAn important thing to understand\nis that today we're\n\n22\n00:01:13,040 --> 00:01:17,270\ngoing to, first of all, have a\nrule, which is going to always\n\n23\n00:01:17,270 --> 00:01:19,520\nbe obeyed, which is the only\nreason we ever add a feature\n\n24\n00:01:19,520 --> 00:01:23,636\nto our language is because\nthere is a good reason.\n\n25\n00:01:23,636 --> 00:01:27,470\nAnd the good reason is going to\nboil down to the ability,\n\n26\n00:01:27,470 --> 00:01:30,500\nyou now get an ability to break\na problem into pieces\n\n27\n00:01:30,500 --> 00:01:32,010\nthat are different sets of\npieces then you could have\n\n28\n00:01:32,010 --> 00:01:35,380\nbroken it down without that,\ngive you another means of\n\n29\n00:01:35,380 --> 00:01:36,630\ndecomposition.\n\n30\n00:01:36,630 --> 00:01:38,350\n\n\n31\n00:01:38,350 --> 00:01:39,490\nHowever, let's just start.\n\n32\n00:01:39,490 --> 00:01:43,270\nLet me quick begin by reviewing\nthe kind of language\n\n33\n00:01:43,270 --> 00:01:48,240\nthat we have now.\n\n34\n00:01:48,240 --> 00:01:51,310\nWe've been writing what's called\nfunctional programs.\n\n35\n00:01:51,310 --> 00:01:56,770\nAnd functional programs are\na kind of encoding of\n\n36\n00:01:56,770 --> 00:01:58,890\nmathematical truths.\n\n37\n00:01:58,890 --> 00:02:02,420\nFor example, when we look at the\nfactorial procedure that\n\n38\n00:02:02,420 --> 00:02:07,090\nyou see on the slide here, it's\nbasically two clauses.\n\n39\n00:02:07,090 --> 00:02:09,530\nIf n is one, the result is\none, otherwise n times\n\n40\n00:02:09,530 --> 00:02:11,230\nfactorial n minus one.\n\n41\n00:02:11,230 --> 00:02:12,990\nThat's factorial of n.\n\n42\n00:02:12,990 --> 00:02:14,960\nWell, that is factorial of n.\n\n43\n00:02:14,960 --> 00:02:17,120\nAnd written down in some other\nobscure notation that you\n\n44\n00:02:17,120 --> 00:02:22,310\nmight have learned in calculus\nclasses, mathematical logic,\n\n45\n00:02:22,310 --> 00:02:28,090\nwhat you see there is if n\nequals one, for the result of\n\n46\n00:02:28,090 --> 00:02:31,060\nn factorial is one, otherwise,\ngreater than one, n factorial\n\n47\n00:02:31,060 --> 00:02:32,680\nis n times n minus\none factorial.\n\n48\n00:02:32,680 --> 00:02:35,560\nTrue statements, that's\nthe kind of\n\n49\n00:02:35,560 --> 00:02:37,000\nlanguage we've been using.\n\n50\n00:02:37,000 --> 00:02:39,610\nAnd whenever we have true\nstatements of that sort, there\n\n51\n00:02:39,610 --> 00:02:47,490\nis a kind of, a way of\nunderstanding how they work\n\n52\n00:02:47,490 --> 00:02:50,170\nwhich is that such processes\ncan be involved by\n\n53\n00:02:50,170 --> 00:02:51,390\nsubstitution.\n\n54\n00:02:51,390 --> 00:02:56,230\nAnd so we see on the second\nslide here, that the way we\n\n55\n00:02:56,230 --> 00:03:02,010\nunderstand the execution implied\nby those statements in\n\n56\n00:03:02,010 --> 00:03:05,640\narranged in that order, is\nthat you do successive\n\n57\n00:03:05,640 --> 00:03:09,370\nsubstitutions of arguments for\nformal parameters in the body\n\n58\n00:03:09,370 --> 00:03:12,430\nof a procedure.\n\n59\n00:03:12,430 --> 00:03:14,710\nThis is basically a sequence\nof equalities.\n\n60\n00:03:14,710 --> 00:03:17,390\nFactorial four is four times\nfactorial three.\n\n61\n00:03:17,390 --> 00:03:21,290\nThat is four times three times\nfactorial of two and so on.\n\n62\n00:03:21,290 --> 00:03:23,325\nWe're always preserving truth.\n\n63\n00:03:23,325 --> 00:03:26,580\n\n\n64\n00:03:26,580 --> 00:03:29,190\nEven though we're talking about\ntrue statements, there\n\n65\n00:03:29,190 --> 00:03:31,390\nmight be more than one\norganization of these true\n\n66\n00:03:31,390 --> 00:03:34,630\nstatements to describe the\ncomputation of a particular\n\n67\n00:03:34,630 --> 00:03:37,490\nfunction, the computation\nof the value of\n\n68\n00:03:37,490 --> 00:03:38,640\na particular function.\n\n69\n00:03:38,640 --> 00:03:42,460\nSo, for example, looking\nat the next one here.\n\n70\n00:03:42,460 --> 00:03:49,780\nHere is a way of looking\nat the sum of n and m.\n\n71\n00:03:49,780 --> 00:03:52,930\nAnd we did this one by\na recursive process.\n\n72\n00:03:52,930 --> 00:04:00,130\nIt's the increment of the sum\nof the decrement of n and m.\n\n73\n00:04:00,130 --> 00:04:03,780\nAnd, of course, there is some\npiece of mathematical logic\n\n74\n00:04:03,780 --> 00:04:06,240\nhere that describes that.\n\n75\n00:04:06,240 --> 00:04:11,450\nIt's the increment of the sum\nof the decrement of n and m,\n\n76\n00:04:11,450 --> 00:04:13,120\njust like that.\n\n77\n00:04:13,120 --> 00:04:16,440\nSo there's nothing particularly\nmagic about that.\n\n78\n00:04:16,440 --> 00:04:19,059\nAnd, of course, if we can also\nlook at an iterative process\n\n79\n00:04:19,059 --> 00:04:22,920\nfor the same, a program that\nevolves an iterative process,\n\n80\n00:04:22,920 --> 00:04:25,310\nfor the same function.\n\n81\n00:04:25,310 --> 00:04:29,930\nThese are two things that\ncompute the same answer.\n\n82\n00:04:29,930 --> 00:04:34,220\nAnd we have equivalent\nmathematical truths that are\n\n83\n00:04:34,220 --> 00:04:36,720\narranged there.\n\n84\n00:04:36,720 --> 00:04:38,920\nAnd just the way you arrange\nthose truths determine the\n\n85\n00:04:38,920 --> 00:04:40,430\nparticular process.\n\n86\n00:04:40,430 --> 00:04:42,810\nIn the way choose and arrange\nthem determines the process\n\n87\n00:04:42,810 --> 00:04:44,400\nthat's evolved.\n\n88\n00:04:44,400 --> 00:04:47,370\nSo we have the flexibility\nof talking about both the\n\n89\n00:04:47,370 --> 00:04:49,260\nfunction to be computed,\nand the method\n\n90\n00:04:49,260 --> 00:04:50,410\nby which it's computed.\n\n91\n00:04:50,410 --> 00:04:53,580\nSo it's not clear\nwe need more.\n\n92\n00:04:53,580 --> 00:04:55,440\nHowever, today I'm going\nto this awful thing.\n\n93\n00:04:55,440 --> 00:04:59,070\nI'm going to introduce this\nassignment operation.\n\n94\n00:04:59,070 --> 00:05:02,890\nNow, what is this?\n\n95\n00:05:02,890 --> 00:05:07,830\nWell, first of all, there is\ngoing to be another kind of\n\n96\n00:05:07,830 --> 00:05:09,960\nkind of statement, if you\nwill, in a programming\n\n97\n00:05:09,960 --> 00:05:11,210\nlanguage called Set!\n\n98\n00:05:11,210 --> 00:05:13,800\n\n\n99\n00:05:13,800 --> 00:05:16,550\nThings that do things like\nassignment, I'm going to put\n\n100\n00:05:16,550 --> 00:05:18,570\nexclamation points after.\n\n101\n00:05:18,570 --> 00:05:20,990\nWe'll talk about what that\nmeans in a second.\n\n102\n00:05:20,990 --> 00:05:23,370\nThe exclamation point, again\nlike question mark, is an\n\n103\n00:05:23,370 --> 00:05:25,960\narbitrary thing we attach to the\nsymbol which is the name,\n\n104\n00:05:25,960 --> 00:05:28,090\nhas no significance\nto the system.\n\n105\n00:05:28,090 --> 00:05:31,520\nThe only significance is to me\nand you to alert you that this\n\n106\n00:05:31,520 --> 00:05:35,910\nis an assignment of some sort.\n\n107\n00:05:35,910 --> 00:05:39,960\nBut we're going to set a\nvariable to a value.\n\n108\n00:05:39,960 --> 00:05:43,800\n\n\n109\n00:05:43,800 --> 00:05:47,120\nAnd what that's going to mean\nis that there is a time at\n\n110\n00:05:47,120 --> 00:05:48,600\nwhich something happens.\n\n111\n00:05:48,600 --> 00:05:50,100\nHere's a time.\n\n112\n00:05:50,100 --> 00:05:55,030\nIf I have time going this\nway, it's a time access.\n\n113\n00:05:55,030 --> 00:05:58,650\nTime progresses by walking\ndown the page.\n\n114\n00:05:58,650 --> 00:06:01,250\nThen an assignment is the\nfirst thing we have that\n\n115\n00:06:01,250 --> 00:06:06,670\nproduces the difference between\na before and an after.\n\n116\n00:06:06,670 --> 00:06:09,660\nAll the other programs that\nwe've written, that have no\n\n117\n00:06:09,660 --> 00:06:12,400\nassignments in them, the order\nin which they were evaluated\n\n118\n00:06:12,400 --> 00:06:14,590\ndidn't matter.\n\n119\n00:06:14,590 --> 00:06:17,990\nBut assignment is special, it\nproduces a moment in time.\n\n120\n00:06:17,990 --> 00:06:27,980\nSo there is a moment before the\nset occurs and after, such\n\n121\n00:06:27,980 --> 00:06:39,500\nthat after this moment in time,\nthe variable has the\n\n122\n00:06:39,500 --> 00:06:43,320\nvalue, value.\n\n123\n00:06:43,320 --> 00:06:49,310\n\n\n124\n00:06:49,310 --> 00:06:53,340\nIndependent of what value\nit had before, set!\n\n125\n00:06:53,340 --> 00:06:57,660\nchanges the value\nof the variable.\n\n126\n00:06:57,660 --> 00:07:03,150\nUntil this moment, we had\nnothing that changed.\n\n127\n00:07:03,150 --> 00:07:06,910\nSo, for example, one of the\nthings we can think of is that\n\n128\n00:07:06,910 --> 00:07:09,890\nthe procedures we write for\nsomething like factorial are\n\n129\n00:07:09,890 --> 00:07:13,740\nin fact pretty much identical\nto the function factorial.\n\n130\n00:07:13,740 --> 00:07:18,120\nFactorial of four, if I write\nfact4, independent of what\n\n131\n00:07:18,120 --> 00:07:20,920\ncontext it's in, and independent\nof how many times\n\n132\n00:07:20,920 --> 00:07:23,040\nI write it, I always get\nthe same answer.\n\n133\n00:07:23,040 --> 00:07:25,430\nIt's always 24.\n\n134\n00:07:25,430 --> 00:07:30,360\nIt's a unique map from the\nargument to the answer.\n\n135\n00:07:30,360 --> 00:07:33,580\nAnd all the programs we've\nwritten so far are like that.\n\n136\n00:07:33,580 --> 00:07:37,020\nHowever, once I have assignment,\nthat isn't true.\n\n137\n00:07:37,020 --> 00:07:50,070\nSo, for example, if I were to\ndefine count to be one.\n\n138\n00:07:50,070 --> 00:07:55,550\nAnd then I'm going to define\nalso a procedure, a simple\n\n139\n00:07:55,550 --> 00:08:02,960\nprocedure called demo, which\ntakes argument x and does the\n\n140\n00:08:02,960 --> 00:08:03,870\nfollowing operations.\n\n141\n00:08:03,870 --> 00:08:09,650\nIt first sets x to x plus one.\n\n142\n00:08:09,650 --> 00:08:13,160\nMy gosh, this looks just\nlike FORTRAN, right--\n\n143\n00:08:13,160 --> 00:08:14,410\nin a funny syntax.\n\n144\n00:08:14,410 --> 00:08:16,910\n\n\n145\n00:08:16,910 --> 00:08:24,330\nAnd then add to x count, Oh,\nI just made a mistake.\n\n146\n00:08:24,330 --> 00:08:27,010\nI want to say, set! count\nto one plus count.\n\n147\n00:08:27,010 --> 00:08:30,310\n\n\n148\n00:08:30,310 --> 00:08:31,730\nIt's this thing defined here.\n\n149\n00:08:31,730 --> 00:08:34,350\n\n\n150\n00:08:34,350 --> 00:08:36,369\nAnd then plus x count.\n\n151\n00:08:36,369 --> 00:08:40,409\n\n\n152\n00:08:40,409 --> 00:08:42,559\nThen I can try this procedure.\n\n153\n00:08:42,559 --> 00:08:43,880\nLet's run it.\n\n154\n00:08:43,880 --> 00:08:48,125\nSo, suppose I get a prompt\nand I say, demo three.\n\n155\n00:08:48,125 --> 00:08:52,210\n\n\n156\n00:08:52,210 --> 00:08:53,540\nWell, what happens here?\n\n157\n00:08:53,540 --> 00:08:57,020\nThe first thing that happens\nis count is currently one.\n\n158\n00:08:57,020 --> 00:08:59,130\nCurrently, there is a time.\n\n159\n00:08:59,130 --> 00:09:00,710\nWe're talking about time.\n\n160\n00:09:00,710 --> 00:09:02,960\nx gets three.\n\n161\n00:09:02,960 --> 00:09:06,090\nAt this moment, I say,\noh yes, count is\n\n162\n00:09:06,090 --> 00:09:08,690\nincremented, so count is two.\n\n163\n00:09:08,690 --> 00:09:10,710\ntwo plus three is five.\n\n164\n00:09:10,710 --> 00:09:14,460\nSo the answer I get\nout is five.\n\n165\n00:09:14,460 --> 00:09:23,640\nThen I say, demo of\nsay, three again.\n\n166\n00:09:23,640 --> 00:09:24,830\nWhat do I get?\n\n167\n00:09:24,830 --> 00:09:29,310\nWell, now count is two, it's\nnot one anymore, because I\n\n168\n00:09:29,310 --> 00:09:30,760\nhave incremented it.\n\n169\n00:09:30,760 --> 00:09:35,050\nBut now I go through this\nprocess, three goes into x,\n\n170\n00:09:35,050 --> 00:09:38,160\ncount becomes one plus count,\nso that's three now.\n\n171\n00:09:38,160 --> 00:09:42,130\nThe sum of those two is six,\nso the answer is six.\n\n172\n00:09:42,130 --> 00:09:45,760\nAnd what we see is the same\nexpression leads to two\n\n173\n00:09:45,760 --> 00:09:52,170\ndifferent answers, depending\nupon time.\n\n174\n00:09:52,170 --> 00:09:55,040\nSo demo is not a function,\ndoes not compute a\n\n175\n00:09:55,040 --> 00:09:56,290\nmathematical function.\n\n176\n00:09:56,290 --> 00:10:00,020\n\n\n177\n00:10:00,020 --> 00:10:03,180\nIn fact, you could also see why\nnow, of course, this is\n\n178\n00:10:03,180 --> 00:10:05,650\nthe first place where the\nsubstitution model\n\n179\n00:10:05,650 --> 00:10:07,780\nisn't going to work.\n\n180\n00:10:07,780 --> 00:10:11,410\nThis kills the substitution\nmodel dead.\n\n181\n00:10:11,410 --> 00:10:14,060\nYou know, with quotation there\nwere some little problems that\n\n182\n00:10:14,060 --> 00:10:17,380\na philosopher might notice\nwith the substitutions,\n\n183\n00:10:17,380 --> 00:10:19,560\nbecause you have to worry about\nwhat deductions you can\n\n184\n00:10:19,560 --> 00:10:23,070\nmake when you substitute into\nquotes, if you're allowed to\n\n185\n00:10:23,070 --> 00:10:25,150\ndo that at all.\n\n186\n00:10:25,150 --> 00:10:28,590\nBut here the substitution\nmodel is dead, can't do\n\n187\n00:10:28,590 --> 00:10:29,810\nanything at all.\n\n188\n00:10:29,810 --> 00:10:34,490\nBecause, supposing I wanted to\nuse a substitution model to\n\n189\n00:10:34,490 --> 00:10:37,560\nconsider substituting\nfor count?\n\n190\n00:10:37,560 --> 00:10:42,150\nWell, my gosh, if I substitute\nfor here and here, they're\n\n191\n00:10:42,150 --> 00:10:44,540\ndifferent ones.\n\n192\n00:10:44,540 --> 00:10:46,570\nIt's not the same\ncount any more.\n\n193\n00:10:46,570 --> 00:10:47,880\nI get the wrong answer.\n\n194\n00:10:47,880 --> 00:10:51,410\nThe substitution model is\na static phenomenon that\n\n195\n00:10:51,410 --> 00:10:55,560\ndescribes things that are true\nand not things that change.\n\n196\n00:10:55,560 --> 00:10:56,810\nHere, we have truths\nthat change.\n\n197\n00:10:56,810 --> 00:11:01,860\n\n\n198\n00:11:01,860 --> 00:11:06,770\nOK, Well, before I give you\nany understanding of this,\n\n199\n00:11:06,770 --> 00:11:07,870\nthis is very bad.\n\n200\n00:11:07,870 --> 00:11:11,520\nNow, we've lost our model\nof computation.\n\n201\n00:11:11,520 --> 00:11:13,420\nPretty soon, I'm going to have\nto build you a new model of\n\n202\n00:11:13,420 --> 00:11:15,030\ncomputation.\n\n203\n00:11:15,030 --> 00:11:18,710\nBut ours plays with this, just\nnow, in an informal sense.\n\n204\n00:11:18,710 --> 00:11:21,490\nOf course, what you already\nsee is that when I have\n\n205\n00:11:21,490 --> 00:11:24,600\nsomething like assignment, the\nmodel that we're going to need\n\n206\n00:11:24,600 --> 00:11:27,760\nis different from the model that\nwe had before in that the\n\n207\n00:11:27,760 --> 00:11:31,840\nvariables, those symbols like\ncount, or x are no longer\n\n208\n00:11:31,840 --> 00:11:35,010\ngoing to refer to the values\nthey have, but rather to some\n\n209\n00:11:35,010 --> 00:11:37,810\nsort of place where the\nvalue restored.\n\n210\n00:11:37,810 --> 00:11:40,330\nWe're going to have to think\nthat way for a while.\n\n211\n00:11:40,330 --> 00:11:42,290\nAnd it's going to be a\nvery bad thing and\n\n212\n00:11:42,290 --> 00:11:44,590\ncause a lot of trouble.\n\n213\n00:11:44,590 --> 00:11:47,350\nAnd so, as I said, the very fact\nthat we're inventing this\n\n214\n00:11:47,350 --> 00:11:49,750\nbad thing, means that there had\nbetter be a good reason\n\n215\n00:11:49,750 --> 00:11:52,040\nfor it, otherwise, just\na waste of time\n\n216\n00:11:52,040 --> 00:11:53,510\nand a lot of effort.\n\n217\n00:11:53,510 --> 00:11:56,090\nLet's just look at some\nof it just to play.\n\n218\n00:11:56,090 --> 00:11:59,130\nSupposing we write down the\nfunctional version, functional\n\n219\n00:11:59,130 --> 00:12:02,770\nmeaning in the old style,\nof factorial by\n\n220\n00:12:02,770 --> 00:12:04,430\nan iterative process.\n\n221\n00:12:04,430 --> 00:12:09,780\n\n\n222\n00:12:09,780 --> 00:12:26,810\nFactorial of n, we're going to\niterate of m and i, which says\n\n223\n00:12:26,810 --> 00:12:40,030\nif i is greater than n, then\nthe result is m, otherwise,\n\n224\n00:12:40,030 --> 00:12:46,930\nthe result of iterating the\nproduct of i and m.\n\n225\n00:12:46,930 --> 00:12:51,690\nSo m is going to be the product\nthat I'm accumulating.\n\n226\n00:12:51,690 --> 00:12:52,940\nm is the product.\n\n227\n00:12:52,940 --> 00:12:58,170\n\n\n228\n00:12:58,170 --> 00:12:59,990\nAnd the count I'm going\nto increase by one.\n\n229\n00:12:59,990 --> 00:13:04,810\n\n\n230\n00:13:04,810 --> 00:13:12,060\nPlus, ITER, ELSE,\nCOND, define.\n\n231\n00:13:12,060 --> 00:13:13,310\nI'm going to start this up.\n\n232\n00:13:13,310 --> 00:13:17,000\n\n\n233\n00:13:17,000 --> 00:13:18,980\nAnd these days, you should\nhave no trouble reading\n\n234\n00:13:18,980 --> 00:13:21,020\nsomething like this.\n\n235\n00:13:21,020 --> 00:13:23,750\nWhat I have here is a\nproduct there being\n\n236\n00:13:23,750 --> 00:13:26,750\naccumulated and a counter.\n\n237\n00:13:26,750 --> 00:13:29,050\nI start them up both at one.\n\n238\n00:13:29,050 --> 00:13:32,380\nI'm going to buzz the counter\nup, i goes to i plus one every\n\n239\n00:13:32,380 --> 00:13:34,800\ntime around.\n\n240\n00:13:34,800 --> 00:13:38,910\nBut that's only our putting a\ntime on the process, each of\n\n241\n00:13:38,910 --> 00:13:42,840\nthis is just a set of\ntruths, true rules.\n\n242\n00:13:42,840 --> 00:13:47,010\nAnd m is going to get a new\nvalues of i and m, i times m\n\n243\n00:13:47,010 --> 00:13:49,860\neach time around, and eventually\ni is going to be\n\n244\n00:13:49,860 --> 00:13:52,750\nbigger than n, in which case,\nthe answer's going to be m.\n\n245\n00:13:52,750 --> 00:13:55,760\nNow, I'm speaking to you,\nuse time in this.\n\n246\n00:13:55,760 --> 00:13:58,210\nThat's just because I know\nhow the computer works.\n\n247\n00:13:58,210 --> 00:13:59,090\nBut I didn't have to.\n\n248\n00:13:59,090 --> 00:14:01,810\nThis could be a purely\nmathematical description at\n\n249\n00:14:01,810 --> 00:14:03,040\nthis point, because\nsubstitution\n\n250\n00:14:03,040 --> 00:14:05,280\nwill work for this.\n\n251\n00:14:05,280 --> 00:14:08,870\nBut let's set right down a\nsimilar sort of program, using\n\n252\n00:14:08,870 --> 00:14:11,975\nthe same algorithm, but\nwith assignments.\n\n253\n00:14:11,975 --> 00:14:15,296\n\n\n254\n00:14:15,296 --> 00:14:16,940\nSo this is called the\nfunctional version.\n\n255\n00:14:16,940 --> 00:14:23,840\n\n\n256\n00:14:23,840 --> 00:14:25,255\nI want to write down an\nimperative version.\n\n257\n00:14:25,255 --> 00:14:34,150\n\n\n258\n00:14:34,150 --> 00:14:36,010\nFactorial of n.\n\n259\n00:14:36,010 --> 00:14:37,510\nI'm going to create\nmy two variables.\n\n260\n00:14:37,510 --> 00:14:40,120\n\n\n261\n00:14:40,120 --> 00:14:48,230\nLet i initialize itself to one,\nand m be initialized to\n\n262\n00:14:48,230 --> 00:14:50,930\none, similar.\n\n263\n00:14:50,930 --> 00:15:05,840\nWe'll create a loop which has\nCOND greater than i, and if i\n\n264\n00:15:05,840 --> 00:15:07,360\nis greater than n, we're done.\n\n265\n00:15:07,360 --> 00:15:10,910\nAnd the result is m, the product\nI'm accumulating.\n\n266\n00:15:10,910 --> 00:15:19,320\nOtherwise, I'm going to write\ndown three things to do.\n\n267\n00:15:19,320 --> 00:15:22,300\nI'm going to set!\n\n268\n00:15:22,300 --> 00:15:34,610\nm to the product of i and m,\nset! i to the sum of i and\n\n269\n00:15:34,610 --> 00:15:40,610\none, and go around\nthe loop again.\n\n270\n00:15:40,610 --> 00:15:44,890\nLooks very familiar to you\nFORTRAN programmers.\n\n271\n00:15:44,890 --> 00:15:47,760\nELSE, COND, define, funny\nsyntax though.\n\n272\n00:15:47,760 --> 00:15:51,270\n\n\n273\n00:15:51,270 --> 00:15:59,320\nStart the loop up, and\nthat's the program.\n\n274\n00:15:59,320 --> 00:16:02,790\nNow, this program, how\ndo we think about it?\n\n275\n00:16:02,790 --> 00:16:04,690\nWell, let's just say what\nwe're seeing here.\n\n276\n00:16:04,690 --> 00:16:07,820\nThere are two local variables,\ni and m, that have been\n\n277\n00:16:07,820 --> 00:16:10,810\ninitialized to one.\n\n278\n00:16:10,810 --> 00:16:13,120\nEvery time around the loop, I\ntest to see if i is greater\n\n279\n00:16:13,120 --> 00:16:16,040\nthan n, which is the input\nargument, and if so, the\n\n280\n00:16:16,040 --> 00:16:19,240\nresult is the product being\naccumulated in m.\n\n281\n00:16:19,240 --> 00:16:23,640\nHowever, if it's not the end of\nthe loop, if I'm not done,\n\n282\n00:16:23,640 --> 00:16:26,260\nthen what I'm going to do is\nchange the product to be the\n\n283\n00:16:26,260 --> 00:16:29,130\nresult of multiplying i times\nthe current product.\n\n284\n00:16:29,130 --> 00:16:31,530\nWhich is sort of what\nwe were doing here.\n\n285\n00:16:31,530 --> 00:16:33,386\nExcept here I wasn't changing.\n\n286\n00:16:33,386 --> 00:16:38,220\nI was making another copy,\nbecause the substitution model\n\n287\n00:16:38,220 --> 00:16:44,410\nsays, you copy the body of the\nprocedure with the arguments\n\n288\n00:16:44,410 --> 00:16:46,710\nsubstituted for the\nformal parameters.\n\n289\n00:16:46,710 --> 00:16:49,690\nHere I'm not worried about\ncopying, here I've changed the\n\n290\n00:16:49,690 --> 00:16:51,990\nvalue of m.\n\n291\n00:16:51,990 --> 00:16:56,090\nI also then change the value\nof i to i plus one, and go\n\n292\n00:16:56,090 --> 00:16:58,300\nbuzzing around.\n\n293\n00:16:58,300 --> 00:17:01,360\nSeems like essentially the same\nprogram, but there are\n\n294\n00:17:01,360 --> 00:17:03,110\nsome ways of making\nerrors here that\n\n295\n00:17:03,110 --> 00:17:06,160\ndidn't exist until today.\n\n296\n00:17:06,160 --> 00:17:10,660\nFor example, if I were to do\nthe horrible thing of not\n\n297\n00:17:10,660 --> 00:17:15,329\nbeing careful in writing my\nprogram and interchange those\n\n298\n00:17:15,329 --> 00:17:17,890\ntwo assignments, the\nprogram wouldn't\n\n299\n00:17:17,890 --> 00:17:20,339\ncompute the same function.\n\n300\n00:17:20,339 --> 00:17:24,859\nI get a timing error because\nthere's a dependency that m\n\n301\n00:17:24,859 --> 00:17:27,460\ndepends upon having the\nlast value of i.\n\n302\n00:17:27,460 --> 00:17:32,760\nIf I try to i first, then I've\ngot the wrong value of i when\n\n303\n00:17:32,760 --> 00:17:36,060\nI multiply by m.\n\n304\n00:17:36,060 --> 00:17:38,600\nIt's a bug that wasn't available\nuntil this moment,\n\n305\n00:17:38,600 --> 00:17:40,660\nuntil we introduced something\nthat had time in it.\n\n306\n00:17:40,660 --> 00:17:43,470\n\n\n307\n00:17:43,470 --> 00:17:47,650\nSo, as I said, first we need a\nnew model of computation, and\n\n308\n00:17:47,650 --> 00:17:49,790\nsecond, we have to be damn good\nreason for doing this\n\n309\n00:17:49,790 --> 00:17:52,800\nkind of ugly thing.\n\n310\n00:17:52,800 --> 00:17:54,050\nAre there any questions?\n\n311\n00:17:54,050 --> 00:17:58,800\n\n\n312\n00:17:58,800 --> 00:18:00,505\nSpeak loudly, David.\n\n313\n00:18:00,505 --> 00:18:04,220\nAUDIENCE: I'm confused about,\nwe've introduced set now, but\n\n314\n00:18:04,220 --> 00:18:07,630\nwe had let before and\ndefine before.\n\n315\n00:18:07,630 --> 00:18:09,980\nI'm confused about the\ndifference between the three.\n\n316\n00:18:09,980 --> 00:18:14,100\nWouldn't define work in the same\nsituation as set if you\n\n317\n00:18:14,100 --> 00:18:15,280\nintroduced it a bit?\n\n318\n00:18:15,280 --> 00:18:18,230\nPROFESSOR: No, define is\nintended for setting something\n\n319\n00:18:18,230 --> 00:18:20,230\nonce the first time,\nfor making it.\n\n320\n00:18:20,230 --> 00:18:22,790\n\n\n321\n00:18:22,790 --> 00:18:26,440\nYou've never seen me write on a\nblackboard two defines in a\n\n322\n00:18:26,440 --> 00:18:30,940\nrow whose intention was to\nchange the old value of some\n\n323\n00:18:30,940 --> 00:18:31,970\nvariable to a new one.\n\n324\n00:18:31,970 --> 00:18:34,380\nAUDIENCE: Is that by\nconvention or--\n\n325\n00:18:34,380 --> 00:18:38,120\nPROFESSOR: No, it's intention.\n\n326\n00:18:38,120 --> 00:18:41,680\nThe answer is that, for\nexample, internal to a\n\n327\n00:18:41,680 --> 00:18:47,250\nprocedure, two defines in a row\nare illegal, two defines\n\n328\n00:18:47,250 --> 00:18:49,850\nin a row of the same variable.\n\n329\n00:18:49,850 --> 00:18:51,890\nx can't be defined twice.\n\n330\n00:18:51,890 --> 00:18:54,300\nWhether or not a system catches\nthat error is a\n\n331\n00:18:54,300 --> 00:18:58,840\ndifferent question, but I\nlegislate to you that define\n\n332\n00:18:58,840 --> 00:19:00,840\nhappens once on anything.\n\n333\n00:19:00,840 --> 00:19:04,770\nNow, indeed, in interactive\ndebugging, we intend that you\n\n334\n00:19:04,770 --> 00:19:08,460\ninteracting with your computer\nwill redefine things, and so\n\n335\n00:19:08,460 --> 00:19:10,050\nthere's a special\nexception made\n\n336\n00:19:10,050 --> 00:19:11,610\nfor interactive debugging.\n\n337\n00:19:11,610 --> 00:19:18,480\nBut define is intended to mean\nto set up something which will\n\n338\n00:19:18,480 --> 00:19:22,460\nbe forever that value\nafter that point.\n\n339\n00:19:22,460 --> 00:19:26,490\nIt's as if all the defines were\ndone at the beginning.\n\n340\n00:19:26,490 --> 00:19:29,870\nIn fact, the only legal place\nto put a define in Scheme,\n\n341\n00:19:29,870 --> 00:19:32,570\ninternal to a procedure, is\njust at the beginning of a\n\n342\n00:19:32,570 --> 00:19:36,605\nlambda expression,\nthe beginning of\n\n343\n00:19:36,605 --> 00:19:37,855\nthe body of a procedure.\n\n344\n00:19:37,855 --> 00:19:41,750\n\n\n345\n00:19:41,750 --> 00:19:46,670\nNow, let of course does nothing\nlike either of that.\n\n346\n00:19:46,670 --> 00:19:50,520\nI mean, if you look at what's\nhappening with a let, this\n\n347\n00:19:50,520 --> 00:19:52,220\nhappens again exactly once.\n\n348\n00:19:52,220 --> 00:19:56,820\nIt sets up a context where i and\nm are values one and one.\n\n349\n00:19:56,820 --> 00:20:01,630\nThat context exists throughout\nthis scope, this\n\n350\n00:20:01,630 --> 00:20:02,880\nregion of the program.\n\n351\n00:20:02,880 --> 00:20:05,080\n\n\n352\n00:20:05,080 --> 00:20:11,110\nHowever, you don't think of that\nlet as setting i again.\n\n353\n00:20:11,110 --> 00:20:12,350\nIt doesn't change it.\n\n354\n00:20:12,350 --> 00:20:15,390\ni never changes because\nof the let.\n\n355\n00:20:15,390 --> 00:20:18,690\ni gets created because of let.\n\n356\n00:20:18,690 --> 00:20:22,300\nIn fact, the let is a\nvery simple idea.\n\n357\n00:20:22,300 --> 00:20:30,930\nLet does nothing more, Let a\nvariable one to have value\n\n358\n00:20:30,930 --> 00:20:37,660\none; I'll write this down a\nlittle bit more neatly; Let's\n\n359\n00:20:37,660 --> 00:20:43,890\nwrite, var one have value, the\nvalue of expression e1, and\n\n360\n00:20:43,890 --> 00:20:48,470\nvariable two, have this value\nof the expression e2, in an\n\n361\n00:20:48,470 --> 00:21:00,420\nexpression e3, is the same thing\nas a procedure of var\n\n362\n00:21:00,420 --> 00:21:08,460\none and var two, the formal\nparameters, and e3 being the\n\n363\n00:21:08,460 --> 00:21:15,010\nbody, where var one is bound\nto the value of e1, and var\n\n364\n00:21:15,010 --> 00:21:16,820\ntwo gets the value of e2.\n\n365\n00:21:16,820 --> 00:21:19,590\n\n\n366\n00:21:19,590 --> 00:21:22,050\nSo this is, in fact, a perfectly\nunderstandable thing\n\n367\n00:21:22,050 --> 00:21:24,930\nfrom a substitution\npoint of view.\n\n368\n00:21:24,930 --> 00:21:27,300\nThis is really the same\nexpression written in two\n\n369\n00:21:27,300 --> 00:21:28,550\ndifferent ways.\n\n370\n00:21:28,550 --> 00:21:31,820\n\n\n371\n00:21:31,820 --> 00:21:34,220\nIn fact, the way the actual\nsystem works is this gets\n\n372\n00:21:34,220 --> 00:21:37,311\ntranslated into this before\nanything happens.\n\n373\n00:21:37,311 --> 00:21:39,690\nAUDIENCE: OK, I'm still unclear\nas then what makes the\n\n374\n00:21:39,690 --> 00:21:41,360\ndifference between a\nlet and a define.\n\n375\n00:21:41,360 --> 00:21:42,125\nThey could--\n\n376\n00:21:42,125 --> 00:21:45,570\nPROFESSOR: A define is a\nsyntactic sugar, whereby,\n\n377\n00:21:45,570 --> 00:21:48,270\nessentially a bunch of variables\nget created by lets\n\n378\n00:21:48,270 --> 00:21:49,520\nand then set up once.\n\n379\n00:21:49,520 --> 00:21:57,170\n\n\n380\n00:21:57,170 --> 00:21:58,790\nOK, time for the first\nbreak, I think.\n\n381\n00:21:58,790 --> 00:22:00,040\nThank you.\n\n382\n00:22:00,040 --> 00:22:03,480\n\n\n383\n00:22:03,480 --> 00:23:04,430\n[MUSIC PLAYING]\n\n384\n00:23:04,430 --> 00:23:06,530\nWell let's see.\n\n385\n00:23:06,530 --> 00:23:10,520\nI now have to rebuild the model\nof computation, so you\n\n386\n00:23:10,520 --> 00:23:13,690\nunderstand how some such\nmechanical mechanism could\n\n387\n00:23:13,690 --> 00:23:17,600\nwork that can do what we've\njust talked about.\n\n388\n00:23:17,600 --> 00:23:22,730\nI just recently destroyed\nyour substitution model.\n\n389\n00:23:22,730 --> 00:23:25,070\nUnfortunately, this model is\nsignificantly more complicated\n\n390\n00:23:25,070 --> 00:23:26,380\nthan the substitution model.\n\n391\n00:23:26,380 --> 00:23:29,010\nIt's called the environment\nmodel.\n\n392\n00:23:29,010 --> 00:23:32,130\nAnd I'm going to have to\nintroduce some terminology,\n\n393\n00:23:32,130 --> 00:23:34,660\nwhich is very good terminology\nfor you to know anyway.\n\n394\n00:23:34,660 --> 00:23:36,640\nIt's about names.\n\n395\n00:23:36,640 --> 00:23:39,360\nAnd we're going to give names\nto the kinds of names things\n\n396\n00:23:39,360 --> 00:23:42,720\nhave and the way those\nnames are used.\n\n397\n00:23:42,720 --> 00:23:48,290\nSo this is a meta-description,\nif you will.\n\n398\n00:23:48,290 --> 00:23:50,840\nAnyway, there is a pile of an\nunfortunate terminology here,\n\n399\n00:23:50,840 --> 00:23:52,730\nbut we're going to need this\nto understand what's called\n\n400\n00:23:52,730 --> 00:23:54,770\nthe environment model.\n\n401\n00:23:54,770 --> 00:23:58,250\nWe're about to do a little bit\nof boring, dog-work here.\n\n402\n00:23:58,250 --> 00:24:02,280\nLet's look at the first\ntransparency.\n\n403\n00:24:02,280 --> 00:24:08,880\nAnd we see a description\nof a word called bound.\n\n404\n00:24:08,880 --> 00:24:11,980\nAnd we're going to say that a\nvariable, v, is bound in an\n\n405\n00:24:11,980 --> 00:24:16,890\nexpression, e, if the meaning\nof e is unchanged by the\n\n406\n00:24:16,890 --> 00:24:22,520\nuniform replacement of a\nvariable w, not occurring in\n\n407\n00:24:22,520 --> 00:24:25,440\ne, for every occurrence\nof v in e.\n\n408\n00:24:25,440 --> 00:24:28,390\nNow that's a long sentence, so,\nI think, I'm going to have\n\n409\n00:24:28,390 --> 00:24:31,690\nto say a little bit about\nthat before we even fool\n\n410\n00:24:31,690 --> 00:24:33,490\naround at all here.\n\n411\n00:24:33,490 --> 00:24:35,260\nBound variables we're\ntalking about here.\n\n412\n00:24:35,260 --> 00:24:44,030\n\n\n413\n00:24:44,030 --> 00:24:46,710\nAnd you've seen lots of them.\n\n414\n00:24:46,710 --> 00:24:48,170\nYou may not know that you've\nseen lots of them.\n\n415\n00:24:48,170 --> 00:24:51,880\nWell, I suppose in your logic\nyou saw a logical variables\n\n416\n00:24:51,880 --> 00:24:58,210\nlike, for every x there exists\na y such that p is true of x\n\n417\n00:24:58,210 --> 00:24:59,860\nand y from your calculus\nclass.\n\n418\n00:24:59,860 --> 00:25:02,960\n\n\n419\n00:25:02,960 --> 00:25:06,780\nThis variable, x, and this\nvariable, y, are bound,\n\n420\n00:25:06,780 --> 00:25:10,920\nbecause the meaning of this\nexpression does not depend\n\n421\n00:25:10,920 --> 00:25:16,640\nupon the particular letters I\nused to describe x and y.\n\n422\n00:25:16,640 --> 00:25:21,740\nIf I were to change the w for x,\nthen said for every w there\n\n423\n00:25:21,740 --> 00:25:26,420\nexists a y such that p is true\nof w and y, it would be the\n\n424\n00:25:26,420 --> 00:25:29,540\nsame sentence.\n\n425\n00:25:29,540 --> 00:25:30,390\nThat's what it means.\n\n426\n00:25:30,390 --> 00:25:35,690\nOr another case of this that\nyou've seen is integral say,\n\n427\n00:25:35,690 --> 00:25:42,415\nfrom 0 to one of dx over\none plus x square.\n\n428\n00:25:42,415 --> 00:25:46,080\n\n\n429\n00:25:46,080 --> 00:25:47,440\nWell that's something you\nsee all the time.\n\n430\n00:25:47,440 --> 00:25:52,270\nAnd this x is a bound\nvariable.\n\n431\n00:25:52,270 --> 00:25:55,190\nIf I change that to a\nt, the expression is\n\n432\n00:25:55,190 --> 00:25:58,170\nstill the same thing.\n\n433\n00:25:58,170 --> 00:26:04,850\nThis is a 1/4 of the arctan of\none or something like that.\n\n434\n00:26:04,850 --> 00:26:06,620\nYes, that's the arctan of one.\n\n435\n00:26:06,620 --> 00:26:09,380\nSo bound variables are actually\nfairly common, for\n\n436\n00:26:09,380 --> 00:26:13,690\nthose of you who have played\na bit with mathematics.\n\n437\n00:26:13,690 --> 00:26:19,100\nWell, let's go into the\nprogramming world.\n\n438\n00:26:19,100 --> 00:26:22,220\nInstead of the quantifier being\nsomething like, for\n\n439\n00:26:22,220 --> 00:26:25,000\nevery, or there exists, or\nintegral, a quantifier is a\n\n440\n00:26:25,000 --> 00:26:27,570\nsymbol that binds a variable.\n\n441\n00:26:27,570 --> 00:26:30,280\nAnd we are going to use the\nquantifier lambda as being the\n\n442\n00:26:30,280 --> 00:26:33,970\nessential thing that\nbinds variables.\n\n443\n00:26:33,970 --> 00:26:37,730\nAnd so we have some nice\nexamples here like that\n\n444\n00:26:37,730 --> 00:26:43,160\nprocedure of one argument\ny which does\n\n445\n00:26:43,160 --> 00:26:44,370\nthe following thing.\n\n446\n00:26:44,370 --> 00:26:50,300\nIt calls the procedure of one\nargument x, which multiplies x\n\n447\n00:26:50,300 --> 00:26:54,145\nby y, and applies\nthat to three.\n\n448\n00:26:54,145 --> 00:26:58,810\n\n\n449\n00:26:58,810 --> 00:27:00,860\nThat procedure has the property\nthere of two bound\n\n450\n00:27:00,860 --> 00:27:04,790\nvariables in it, x and y.\n\n451\n00:27:04,790 --> 00:27:08,500\nThis quantifier, lambda here,\nbinds this y, and this\n\n452\n00:27:08,500 --> 00:27:12,120\nquantifier, lambda,\nbinds that x.\n\n453\n00:27:12,120 --> 00:27:15,000\nBecause, if I were to take an\narbitrary symbol does not\n\n454\n00:27:15,000 --> 00:27:20,130\noccur in this expression like w\nand replace all y's with w's\n\n455\n00:27:20,130 --> 00:27:23,610\nin this expression, the\nexpression is still the same,\n\n456\n00:27:23,610 --> 00:27:26,240\nthe same procedure.\n\n457\n00:27:26,240 --> 00:27:27,430\nAnd this is an important idea.\n\n458\n00:27:27,430 --> 00:27:30,700\nThe reason why we had such\nthings like that is a kind of\n\n459\n00:27:30,700 --> 00:27:31,500\nmodularity.\n\n460\n00:27:31,500 --> 00:27:34,800\nIf two people are writing\nprograms, and they work\n\n461\n00:27:34,800 --> 00:27:38,150\ntogether, it shouldn't matter\nwhat names they use internal\n\n462\n00:27:38,150 --> 00:27:42,490\nto their own little machines\nthat they're building.\n\n463\n00:27:42,490 --> 00:27:45,960\nAnd so, what I'm really telling\nyou there, is that,\n\n464\n00:27:45,960 --> 00:27:49,490\nfor example, this is equivalent\nto that procedure\n\n465\n00:27:49,490 --> 00:27:54,260\nof one argument y which uses\nthat procedure of one argument\n\n466\n00:27:54,260 --> 00:28:01,200\nd which multiplies z by y.\n\n467\n00:28:01,200 --> 00:28:03,570\nBecause nobody cares what\nI used in here.\n\n468\n00:28:03,570 --> 00:28:06,270\n\n\n469\n00:28:06,270 --> 00:28:08,880\nIt's a nice example.\n\n470\n00:28:08,880 --> 00:28:15,320\nOn the other hand, I have some\nvariables that are not bound.\n\n471\n00:28:15,320 --> 00:28:22,450\nFor example, that procedure\nof one argument x which\n\n472\n00:28:22,450 --> 00:28:27,390\nmultiplies x by y.\n\n473\n00:28:27,390 --> 00:28:32,370\nIn this case, y is not bound.\n\n474\n00:28:32,370 --> 00:28:36,440\nSupposing y had the value three,\nand z had the value\n\n475\n00:28:36,440 --> 00:28:41,420\nfour, then this procedure\nwould be the thing that\n\n476\n00:28:41,420 --> 00:28:44,910\nmultiplies its argument\nby three.\n\n477\n00:28:44,910 --> 00:28:47,793\nIf I were to replace every\ninstance of y with z, I would\n\n478\n00:28:47,793 --> 00:28:50,190\nhave a different procedure\nwhich multiplies every\n\n479\n00:28:50,190 --> 00:28:53,491\nargument that's given by four.\n\n480\n00:28:53,491 --> 00:28:57,810\nAnd, in fact, we have a name\nfor such a variable.\n\n481\n00:28:57,810 --> 00:29:03,680\nHere, we say that a variable, v,\nis free in the expression,\n\n482\n00:29:03,680 --> 00:29:06,200\ne, if the meaning of the\nexpression, e, is changed by\n\n483\n00:29:06,200 --> 00:29:09,355\nthe uniform replacement of a\nvariable, w, not occurring in\n\n484\n00:29:09,355 --> 00:29:13,120\ne for every occurrence\nof v and e.\n\n485\n00:29:13,120 --> 00:29:20,680\nSo that's why this variable\nover here,\n\n486\n00:29:20,680 --> 00:29:22,525\ny, is a free variable.\n\n487\n00:29:22,525 --> 00:29:29,010\n\n\n488\n00:29:29,010 --> 00:29:33,610\nAnd so free variables\nin this expression--\n\n489\n00:29:33,610 --> 00:29:38,690\nAnd other examples of that is\nthat procedure of one argument\n\n490\n00:29:38,690 --> 00:29:43,160\ny, which is just what we had\nbefore, which uses that\n\n491\n00:29:43,160 --> 00:29:48,130\nprocedure of one argument x\nthat multiplies x by y--\n\n492\n00:29:48,130 --> 00:29:51,540\n\n\n493\n00:29:51,540 --> 00:29:52,790\nuse that on three.\n\n494\n00:29:52,790 --> 00:29:56,940\n\n\n495\n00:29:56,940 --> 00:30:00,060\nThis procedure has\na free variable\n\n496\n00:30:00,060 --> 00:30:01,795\nin it which is asterisk.\n\n497\n00:30:01,795 --> 00:30:05,010\n\n\n498\n00:30:05,010 --> 00:30:07,170\nSee, because, if that has\na normal meaning of\n\n499\n00:30:07,170 --> 00:30:11,360\nmultiplication, then if I were\nto replace uniformly all\n\n500\n00:30:11,360 --> 00:30:15,770\nasterisks with pluses, then the\nmeaning of this expression\n\n501\n00:30:15,770 --> 00:30:17,020\nwould change.\n\n502\n00:30:17,020 --> 00:30:19,360\n\n\n503\n00:30:19,360 --> 00:30:22,850\nThat's what you mean\nby a free variable.\n\n504\n00:30:22,850 --> 00:30:26,350\nSo, so far you've learned some\nlogician words which describe\n\n505\n00:30:26,350 --> 00:30:29,020\nthe way names are used.\n\n506\n00:30:29,020 --> 00:30:32,490\nNow, we have to do a little bit\nmore playing around here,\n\n507\n00:30:32,490 --> 00:30:35,200\na little bit more.\n\n508\n00:30:35,200 --> 00:30:38,600\nI want to tell you about the\nregions are over which\n\n509\n00:30:38,600 --> 00:30:39,850\nvariables are defined.\n\n510\n00:30:39,850 --> 00:30:42,270\n\n\n511\n00:30:42,270 --> 00:30:45,260\nYou see, we've been very\ninformal about this up till\n\n512\n00:30:45,260 --> 00:30:48,870\nnow, and, of course, many of you\nhave probably understood\n\n513\n00:30:48,870 --> 00:30:51,960\nvery clearly or most of you,\nthat the x that's being\n\n514\n00:30:51,960 --> 00:30:55,170\ndeclared here is defined\nonly in here.\n\n515\n00:30:55,170 --> 00:30:58,250\n\n\n516\n00:30:58,250 --> 00:31:03,580\nThis x is the defined only in\nhere, and this y is defined\n\n517\n00:31:03,580 --> 00:31:04,830\nonly in here.\n\n518\n00:31:04,830 --> 00:31:07,080\n\n\n519\n00:31:07,080 --> 00:31:08,400\nWe have a name for\nsuch an idea.\n\n520\n00:31:08,400 --> 00:31:11,660\nIt's called a scope.\n\n521\n00:31:11,660 --> 00:31:14,710\nAnd let me give you another\npiece of terminology.\n\n522\n00:31:14,710 --> 00:31:16,050\nIt's a long story.\n\n523\n00:31:16,050 --> 00:31:18,850\nIf x is a bound variable in\ne, then there is a lambda\n\n524\n00:31:18,850 --> 00:31:20,560\nexpression where it is bound.\n\n525\n00:31:20,560 --> 00:31:23,956\nSo the only way you can get a\nbound variable ultimately is\n\n526\n00:31:23,956 --> 00:31:24,970\nby lambda expression.\n\n527\n00:31:24,970 --> 00:31:28,250\nThen you may worry, does\ndefine quite an\n\n528\n00:31:28,250 --> 00:31:29,670\nexception to this?\n\n529\n00:31:29,670 --> 00:31:31,840\nAnd it turns out, we could\nalways arrange things so you\n\n530\n00:31:31,840 --> 00:31:33,100\ndon't need any defines.\n\n531\n00:31:33,100 --> 00:31:34,070\nAnd we'll see that in a while.\n\n532\n00:31:34,070 --> 00:31:36,900\nIt's a very magical thing.\n\n533\n00:31:36,900 --> 00:31:39,000\nSo define really can go away.\n\n534\n00:31:39,000 --> 00:31:42,650\nThe really, only thing that\nmakes names is lambda .\n\n535\n00:31:42,650 --> 00:31:44,350\nThat's its job.\n\n536\n00:31:44,350 --> 00:31:46,865\nAnd what's so amazing about\na lot of things is you can\n\n537\n00:31:46,865 --> 00:31:48,740\ncompute with only lambda.\n\n538\n00:31:48,740 --> 00:31:53,910\nBut, in any case, a lambda\nexpression has a place where\n\n539\n00:31:53,910 --> 00:31:55,880\nit declares a variable.\n\n540\n00:31:55,880 --> 00:31:59,970\nWe call it the formal parameter\nlist or the bound\n\n541\n00:31:59,970 --> 00:32:03,290\nvariable list. We say that the\nlambda expression binds--\n\n542\n00:32:03,290 --> 00:32:04,970\nso it's a verb--\n\n543\n00:32:04,970 --> 00:32:08,730\nbinds the variables declared in\nit's found variable list.\n\n544\n00:32:08,730 --> 00:32:10,580\nIn addition, those parts of\nthe expression where the\n\n545\n00:32:10,580 --> 00:32:15,680\nvariable is defined, which was\ndeclared by some declaration,\n\n546\n00:32:15,680 --> 00:32:20,400\nis called the scope\nof that variable.\n\n547\n00:32:20,400 --> 00:32:22,270\nSo these are scopes.\n\n548\n00:32:22,270 --> 00:32:23,630\nThis is the scope of y.\n\n549\n00:32:23,630 --> 00:32:27,140\n\n\n550\n00:32:27,140 --> 00:32:28,690\nAnd this is the scope of x--\n\n551\n00:32:28,690 --> 00:32:33,030\n\n\n552\n00:32:33,030 --> 00:32:34,280\nthat sort of thing.\n\n553\n00:32:34,280 --> 00:32:41,460\n\n\n554\n00:32:41,460 --> 00:32:47,120\nOK, well, now we have enough\nterminology to begin to\n\n555\n00:32:47,120 --> 00:32:52,360\nunderstand how to make a new\nmodel for computation, because\n\n556\n00:32:52,360 --> 00:32:56,060\nthe key thing going on here\nis that we destroyed the\n\n557\n00:32:56,060 --> 00:32:58,820\nsubstitution model, and we now\nhave to have a model that\n\n558\n00:32:58,820 --> 00:33:03,950\nrepresents the names as\nreferring to places.\n\n559\n00:33:03,950 --> 00:33:06,460\nBecause if we are going to\nchange something, then we have\n\n560\n00:33:06,460 --> 00:33:09,660\na place where it's stored.\n\n561\n00:33:09,660 --> 00:33:14,860\nYou see, if a name only refers\nto a value, and if I tried to\n\n562\n00:33:14,860 --> 00:33:19,280\nchange the name's meaning,\nwell, that's not clear.\n\n563\n00:33:19,280 --> 00:33:23,570\nThere's nothing that is\nthe place that that\n\n564\n00:33:23,570 --> 00:33:25,030\nname referred to.\n\n565\n00:33:25,030 --> 00:33:25,960\nHow am I really saying it?\n\n566\n00:33:25,960 --> 00:33:28,220\nThere is nothing shared\namong all of the\n\n567\n00:33:28,220 --> 00:33:29,840\ninstances of that name.\n\n568\n00:33:29,840 --> 00:33:32,080\nAnd what we really mean,\nby a name, is that we\n\n569\n00:33:32,080 --> 00:33:34,440\nfan something out.\n\n570\n00:33:34,440 --> 00:33:37,350\nWe've given something a name,\nand you have it, and you have\n\n571\n00:33:37,350 --> 00:33:39,470\nit, because I'm given you a\nreference to it, and I've\n\n572\n00:33:39,470 --> 00:33:41,130\ngiven you a reference to it.\n\n573\n00:33:41,130 --> 00:33:43,580\nAnd we'll see a lot\nabout that.\n\n574\n00:33:43,580 --> 00:33:45,986\nSo let me tell you about\nenvironments.\n\n575\n00:33:45,986 --> 00:33:52,140\nI need the overhead projection\nmachine, thank you.\n\n576\n00:33:52,140 --> 00:34:01,590\nAnd so here is a bunch of\nenvironment structures.\n\n577\n00:34:01,590 --> 00:34:06,490\nAn environment is a way of doing\nsubstitutions virtually.\n\n578\n00:34:06,490 --> 00:34:09,639\nIt represents a place where\nsomething is stored which is\n\n579\n00:34:09,639 --> 00:34:11,409\nthe substitutions that\nyou haven't done.\n\n580\n00:34:11,409 --> 00:34:14,540\n\n\n581\n00:34:14,540 --> 00:34:17,639\nIt's a place where everything\naccumulates, where the names\n\n582\n00:34:17,639 --> 00:34:20,600\nof the variables are associated\nwith the values\n\n583\n00:34:20,600 --> 00:34:26,020\nthey have such that when you\nsay, what dose this name mean,\n\n584\n00:34:26,020 --> 00:34:28,090\nyou look it up in\nan environment.\n\n585\n00:34:28,090 --> 00:34:32,420\nSo an environment is a function,\nor a table, or\n\n586\n00:34:32,420 --> 00:34:33,290\nsomething like that.\n\n587\n00:34:33,290 --> 00:34:35,790\nBut it's a structured\nsort of table.\n\n588\n00:34:35,790 --> 00:34:37,125\nIt's made out of things\ncalled frames.\n\n589\n00:34:37,125 --> 00:34:41,050\n\n\n590\n00:34:41,050 --> 00:34:45,210\nFrames are pieces of\nenvironment, and they are\n\n591\n00:34:45,210 --> 00:34:50,270\nchained together, in some nice\nways, by what's called parent\n\n592\n00:34:50,270 --> 00:34:53,940\nlinks or something like that.\n\n593\n00:34:53,940 --> 00:34:57,740\nSo here, we have an environment\nstructure\n\n594\n00:34:57,740 --> 00:35:00,100\nconsisting of three\nenvironments,\n\n595\n00:35:00,100 --> 00:35:05,250\nbasically, a, b, and c.\n\n596\n00:35:05,250 --> 00:35:11,480\nd is also an environment, but\nit's the same one, they share.\n\n597\n00:35:11,480 --> 00:35:14,550\nAnd that's the essence\nof assignment.\n\n598\n00:35:14,550 --> 00:35:18,120\nIf I change a variable, a value\nof a valuable that lives\n\n599\n00:35:18,120 --> 00:35:21,950\nhere, like that one, it should\nbe visible from all places\n\n600\n00:35:21,950 --> 00:35:23,750\nthat you're looking\nat it from.\n\n601\n00:35:23,750 --> 00:35:24,990\nTake this one, x.\n\n602\n00:35:24,990 --> 00:35:28,560\nIf I change the x to four, it's\n\n603\n00:35:28,560 --> 00:35:30,340\nvisible from other places.\n\n604\n00:35:30,340 --> 00:35:32,270\nBut I'm not going to worry\nabout that right now.\n\n605\n00:35:32,270 --> 00:35:34,590\nWe're going to talk a lot about\nthat in a little while.\n\n606\n00:35:34,590 --> 00:35:36,830\nWhat do we have here?\n\n607\n00:35:36,830 --> 00:35:37,990\nWell, these are called frames.\n\n608\n00:35:37,990 --> 00:35:43,270\nHere is a frame, here's a frame,\nand here's a frame.\n\n609\n00:35:43,270 --> 00:35:47,040\na is an environment which\nconsists of the table which is\n\n610\n00:35:47,040 --> 00:35:52,570\nframe two, followed by the\ntable labeled frame one.\n\n611\n00:35:52,570 --> 00:35:59,280\nAnd, in this environment, in\nsay this environment, frame\n\n612\n00:35:59,280 --> 00:36:04,150\ntwo, x and y are bound.\n\n613\n00:36:04,150 --> 00:36:05,920\nThey have values.\n\n614\n00:36:05,920 --> 00:36:07,290\nSorry, in frame one--\n\n615\n00:36:07,290 --> 00:36:15,340\nIn frame two, z is bound, and\nx is bound, and y is bound,\n\n616\n00:36:15,340 --> 00:36:18,560\nbut the value of x that we see,\nlooking from this point\n\n617\n00:36:18,560 --> 00:36:20,940\nof view, is this x.\n\n618\n00:36:20,940 --> 00:36:24,940\nIt's x is seven, rather than\nthis one which is three.\n\n619\n00:36:24,940 --> 00:36:27,660\nWe say that this x\nshadows this x.\n\n620\n00:36:27,660 --> 00:36:31,070\n\n\n621\n00:36:31,070 --> 00:36:33,320\nFrom environment three--\n\n622\n00:36:33,320 --> 00:36:36,460\nfrom frame three, from\nenvironment b, which refers to\n\n623\n00:36:36,460 --> 00:36:42,155\nframe three, we have variables\nn and y bound and also x.\n\n624\n00:36:42,155 --> 00:36:44,740\n\n\n625\n00:36:44,740 --> 00:36:48,630\nThis y shadow this one.\n\n626\n00:36:48,630 --> 00:36:50,580\nSo the value, looking\nfrom this point of\n\n627\n00:36:50,580 --> 00:36:53,410\nview, of y is two.\n\n628\n00:36:53,410 --> 00:36:54,900\nThe value for looking\nfrom this point of\n\n629\n00:36:54,900 --> 00:36:56,500\nview and m is one.\n\n630\n00:36:56,500 --> 00:36:57,620\nAnd the value, looking\nfrom this point of\n\n631\n00:36:57,620 --> 00:36:58,870\nview, of x is three.\n\n632\n00:36:58,870 --> 00:37:02,310\n\n\n633\n00:37:02,310 --> 00:37:04,300\nSo there we have a very\nsimple environment\n\n634\n00:37:04,300 --> 00:37:06,340\nstructure made out of frames.\n\n635\n00:37:06,340 --> 00:37:10,990\nThese correspond to the\napplications of procedures.\n\n636\n00:37:10,990 --> 00:37:14,390\nAnd we'll see that\nin a second.\n\n637\n00:37:14,390 --> 00:37:16,860\nSo now I have to make you some\nother nice little structure\n\n638\n00:37:16,860 --> 00:37:18,110\nthat we build.\n\n639\n00:37:18,110 --> 00:37:20,870\n\n\n640\n00:37:20,870 --> 00:37:25,820\nNext slide, we see an object,\nwhich I'm going to draw\n\n641\n00:37:25,820 --> 00:37:27,850\nprocedures.\n\n642\n00:37:27,850 --> 00:37:30,190\nThis is a procedure.\n\n643\n00:37:30,190 --> 00:37:33,150\nA procedure is made\nout of two parts.\n\n644\n00:37:33,150 --> 00:37:34,515\nIt's sort of like a cons.\n\n645\n00:37:34,515 --> 00:37:37,210\n\n\n646\n00:37:37,210 --> 00:37:38,460\nHowever, it's the two parts.\n\n647\n00:37:38,460 --> 00:37:40,820\n\n\n648\n00:37:40,820 --> 00:37:46,410\nThe first part refers to some\ncode, something that can be\n\n649\n00:37:46,410 --> 00:37:48,940\nexecuted, a set of instructions,\nif you will.\n\n650\n00:37:48,940 --> 00:37:50,750\nYou can think of it that way.\n\n651\n00:37:50,750 --> 00:37:53,830\nAnd the second part is\nthe environment.\n\n652\n00:37:53,830 --> 00:37:57,250\nThe procedure is the\nwhole thing.\n\n653\n00:37:57,250 --> 00:38:01,420\nAnd we're going to have to use\nthis to capture the values of\n\n654\n00:38:01,420 --> 00:38:06,250\nthe free variables that occur\nin the procedure.\n\n655\n00:38:06,250 --> 00:38:08,760\nIf a variable occurs in the\nprocedure it's either bound in\n\n656\n00:38:08,760 --> 00:38:11,170\nthat procedure or free.\n\n657\n00:38:11,170 --> 00:38:16,930\nIf it's bound, then the value\nwill somehow be easy to find.\n\n658\n00:38:16,930 --> 00:38:19,070\nIt will be in some easy\nenvironment to get at.\n\n659\n00:38:19,070 --> 00:38:21,800\nIf it's free, we're going to\nhave to have something that\n\n660\n00:38:21,800 --> 00:38:24,010\ngoes with the procedure that\nsays where we'll go\n\n661\n00:38:24,010 --> 00:38:27,100\nlook for its value.\n\n662\n00:38:27,100 --> 00:38:32,290\nAnd the reasons why are not\nobvious yet, but will be soon.\n\n663\n00:38:32,290 --> 00:38:33,760\nSo here's a procedure object.\n\n664\n00:38:33,760 --> 00:38:40,200\nIt's a composite object\nconsisting of a piece of code\n\n665\n00:38:40,200 --> 00:38:42,750\nand a environment structure.\n\n666\n00:38:42,750 --> 00:38:46,400\nNow I will tell you the new\nrules, the complete new rules,\n\n667\n00:38:46,400 --> 00:38:47,650\nfor evaluation.\n\n668\n00:38:47,650 --> 00:38:50,690\n\n\n669\n00:38:50,690 --> 00:38:53,250\nThe first rule is-- there's\nonly two of them.\n\n670\n00:38:53,250 --> 00:38:57,250\nThese correspond to the\nsubstitution model rules.\n\n671\n00:38:57,250 --> 00:39:00,830\nAnd the first one has to do\nwith how do you apply a\n\n672\n00:39:00,830 --> 00:39:02,570\nprocedure to its arguments?\n\n673\n00:39:02,570 --> 00:39:05,610\n\n\n674\n00:39:05,610 --> 00:39:08,890\nAnd a procedural object is\napplied to a set of arguments\n\n675\n00:39:08,890 --> 00:39:11,270\nby constructing a new frame.\n\n676\n00:39:11,270 --> 00:39:13,860\nThat frame will contain the\nmapping of the former\n\n677\n00:39:13,860 --> 00:39:16,540\nparameters to the actual\nparameters of the arguments\n\n678\n00:39:16,540 --> 00:39:21,490\nthat were supplied\nin the call.\n\n679\n00:39:21,490 --> 00:39:25,320\nAs you know, when we make up\na call to a procedure like\n\n680\n00:39:25,320 --> 00:39:28,670\nlambda x times x y, and we call\nthat with the argument\n\n681\n00:39:28,670 --> 00:39:31,280\nthree, then we're going\nto need some\n\n682\n00:39:31,280 --> 00:39:34,290\nmapping of x to three.\n\n683\n00:39:34,290 --> 00:39:38,490\nIt's the same thing as later\nsubstituting, if you will, the\n\n684\n00:39:38,490 --> 00:39:41,990\nthree for the x in\nthe old model.\n\n685\n00:39:41,990 --> 00:39:45,160\nSo I'm going to build a frame\nwhich contains x equals three\n\n686\n00:39:45,160 --> 00:39:46,550\nas the information\nin that frame.\n\n687\n00:39:46,550 --> 00:39:49,230\n\n\n688\n00:39:49,230 --> 00:39:52,640\nNow, the body of the procedure\nwill then have to be evaluated\n\n689\n00:39:52,640 --> 00:39:54,170\nwhich is this.\n\n690\n00:39:54,170 --> 00:40:04,710\nI will be evaluated in an\nenvironment which is\n\n691\n00:40:04,710 --> 00:40:08,780\nconstructed by adjoining the new\nframe that we just made to\n\n692\n00:40:08,780 --> 00:40:10,450\nthe environment which\nwas part of the\n\n693\n00:40:10,450 --> 00:40:13,100\nprocedure that we applied.\n\n694\n00:40:13,100 --> 00:40:15,670\nSo I'm going to make a little\nexample of that here.\n\n695\n00:40:15,670 --> 00:40:19,220\n\n\n696\n00:40:19,220 --> 00:40:25,110\nSupposing I have some\nenvironment.\n\n697\n00:40:25,110 --> 00:40:27,980\nHere's a frame which\nrepresents it.\n\n698\n00:40:27,980 --> 00:40:30,190\nAnd some procedure-- which I'm\ngoing to draw with circles\n\n699\n00:40:30,190 --> 00:40:33,370\nhere because it's easier\nthan little triangles--\n\n700\n00:40:33,370 --> 00:40:38,940\nSorry, those are rhombuses,\nrhomboidal little pieces of\n\n701\n00:40:38,940 --> 00:40:42,710\nfruit jelly or something.\n\n702\n00:40:42,710 --> 00:40:45,960\nSo here's a procedure which\ntakes this environment.\n\n703\n00:40:45,960 --> 00:40:48,920\nAnd the procedure has a piece\nof code, which is a lambda\n\n704\n00:40:48,920 --> 00:40:55,600\nexpression, which binds x and\ny and then executes an\n\n705\n00:40:55,600 --> 00:40:58,010\nexpression, e.\n\n706\n00:40:58,010 --> 00:40:59,345\nAnd this is the procedure.\n\n707\n00:40:59,345 --> 00:41:01,470\nWe'll call it p.\n\n708\n00:41:01,470 --> 00:41:06,490\nI wish to apply that procedure\nto three and four.\n\n709\n00:41:06,490 --> 00:41:09,790\nSo I want to do p of\nthree and four.\n\n710\n00:41:09,790 --> 00:41:13,210\nWhat I'm going to do, of course,\nis make a new frame.\n\n711\n00:41:13,210 --> 00:41:18,630\nI build a frame which contains\nx equals three,\n\n712\n00:41:18,630 --> 00:41:21,740\nand y equals four.\n\n713\n00:41:21,740 --> 00:41:27,680\nI'm going to connect that frame\nto this frame over here.\n\n714\n00:41:27,680 --> 00:41:31,940\nAnd then this environment, with\nI will call b, is the\n\n715\n00:41:31,940 --> 00:41:34,880\nenvironment in which I will\nevaluate the body of e.\n\n716\n00:41:34,880 --> 00:41:39,940\n\n\n717\n00:41:39,940 --> 00:41:46,890\nNow, e may contain references\nto x and y and other things.\n\n718\n00:41:46,890 --> 00:41:50,790\nx and y will have values\nright here.\n\n719\n00:41:50,790 --> 00:41:55,040\nOther things will have\ntheir values here.\n\n720\n00:41:55,040 --> 00:41:56,920\nHow do we get this frame?\n\n721\n00:41:56,920 --> 00:42:00,110\nThat we do by the construction\nof procedures which is the\n\n722\n00:42:00,110 --> 00:42:01,980\nother rule.\n\n723\n00:42:01,980 --> 00:42:05,500\nAnd I think that's\nthe next slide.\n\n724\n00:42:05,500 --> 00:42:10,000\nRule two, when a lambda\nexpression is evaluated,\n\n725\n00:42:10,000 --> 00:42:11,510\nrelative to a particular\nenvironment--\n\n726\n00:42:11,510 --> 00:42:14,150\n\n\n727\n00:42:14,150 --> 00:42:17,470\nSee, the way I get a procedure\nis by evaluating the lambda\n\n728\n00:42:17,470 --> 00:42:18,300\nexpression.\n\n729\n00:42:18,300 --> 00:42:20,110\nHere's a lambda expression.\n\n730\n00:42:20,110 --> 00:42:22,880\nBy evaluating it, I get\na procedure which I\n\n731\n00:42:22,880 --> 00:42:25,170\ncan apply to three.\n\n732\n00:42:25,170 --> 00:42:28,710\nNow this lambda expression is\nevaluated in an environment\n\n733\n00:42:28,710 --> 00:42:31,820\nwhere y is defined.\n\n734\n00:42:31,820 --> 00:42:33,760\nAnd I want the body of\nthis which contains a\n\n735\n00:42:33,760 --> 00:42:36,680\nfree version of y.\n\n736\n00:42:36,680 --> 00:42:41,790\ny is free in here, it's bound\nover the whole thing, but it's\n\n737\n00:42:41,790 --> 00:42:43,350\nfree over here.\n\n738\n00:42:43,350 --> 00:42:47,440\nI want that y to be this one.\n\n739\n00:42:47,440 --> 00:42:53,150\nI evaluate this body of this\nprocedure in the environment\n\n740\n00:42:53,150 --> 00:42:55,470\nwhere y was created.\n\n741\n00:42:55,470 --> 00:42:57,800\nThat's this kind of thing,\nbecause that was done by\n\n742\n00:42:57,800 --> 00:42:59,140\napplication.\n\n743\n00:42:59,140 --> 00:43:03,490\nNow, if I ever want to look up\nthe value of y, I have to know\n\n744\n00:43:03,490 --> 00:43:04,370\nwhere it is.\n\n745\n00:43:04,370 --> 00:43:07,440\nTherefore, this procedural was\ncreated, the creation of the\n\n746\n00:43:07,440 --> 00:43:09,530\nprocedure which is the result\nof evaluating that lambda\n\n747\n00:43:09,530 --> 00:43:14,480\nexpression had better capture\na pointer or remember the\n\n748\n00:43:14,480 --> 00:43:18,110\nframe in which y was bound.\n\n749\n00:43:18,110 --> 00:43:22,100\nSo that's what this rule\nis telling us.\n\n750\n00:43:22,100 --> 00:43:28,610\nSo, for example, if I happen\nto be evaluating a lambda\n\n751\n00:43:28,610 --> 00:43:37,370\nexpression, lambda expression in\ne, lambda of say, x and y,\n\n752\n00:43:37,370 --> 00:43:43,020\nlet's call it g in e,\nevaluating that.\n\n753\n00:43:43,020 --> 00:43:47,190\nWell, all that means is I now\nconstruct a procedure object.\n\n754\n00:43:47,190 --> 00:43:48,990\ne is some environment.\n\n755\n00:43:48,990 --> 00:43:51,920\ne is something which has\na pointer to it.\n\n756\n00:43:51,920 --> 00:43:56,120\nI construct a procedure object\nthat points up to that\n\n757\n00:43:56,120 --> 00:44:01,830\nenvironment, where the code of\nthat is a lambda expression or\n\n758\n00:44:01,830 --> 00:44:03,180\nwhatever that translates into.\n\n759\n00:44:03,180 --> 00:44:06,330\n\n\n760\n00:44:06,330 --> 00:44:07,580\nAnd this is the procedure.\n\n761\n00:44:07,580 --> 00:44:12,380\n\n\n762\n00:44:12,380 --> 00:44:17,640\nSo this produces for me-- this\nobject here, this environment\n\n763\n00:44:17,640 --> 00:44:21,140\npointer, captures the place\nwhere this lambda expression\n\n764\n00:44:21,140 --> 00:44:25,820\nwas evaluated, where the\ndefinition was used, where the\n\n765\n00:44:25,820 --> 00:44:26,900\ndefinition was used to make a\n\n766\n00:44:26,900 --> 00:44:32,950\nprocedure, to make the procedure.\n\n767\n00:44:32,950 --> 00:44:35,190\nSo it picks up the environment\nfrom the place where that\n\n768\n00:44:35,190 --> 00:44:39,680\nprocedure was defined, stores\nit in the procedure itself,\n\n769\n00:44:39,680 --> 00:44:42,210\nand then when the procedure is\nused, the environment where it\n\n770\n00:44:42,210 --> 00:44:44,990\nwas defined is extended\nwith the new frame.\n\n771\n00:44:44,990 --> 00:44:48,740\n\n\n772\n00:44:48,740 --> 00:44:51,170\nSo this gives us a locus\nfor putting where a\n\n773\n00:44:51,170 --> 00:44:53,090\nvariable has a value.\n\n774\n00:44:53,090 --> 00:44:55,700\nAnd, for example, if there are\nlots of guys pointing in at\n\n775\n00:44:55,700 --> 00:45:01,430\nthat environment, then they\nshare that place.\n\n776\n00:45:01,430 --> 00:45:03,810\nAnd we'll see more\nof that shortly.\n\n777\n00:45:03,810 --> 00:45:08,940\nWell, now you have a new model\nfor understanding the\n\n778\n00:45:08,940 --> 00:45:12,420\nexecution of programs. I suppose\nI'll take questions\n\n779\n00:45:12,420 --> 00:45:14,970\nnow, and then we'll go on and\nuse that for something.\n\n780\n00:45:14,970 --> 00:45:17,802\n\n\n781\n00:45:17,802 --> 00:45:21,870\nAUDIENCE: Is it right to say\nthen, the environment is that\n\n782\n00:45:21,870 --> 00:45:23,695\nlinked chain of frames--\n\n783\n00:45:23,695 --> 00:45:24,580\nPROFESSOR: That's right.\n\n784\n00:45:24,580 --> 00:45:25,650\nAUDIENCE: starting with--\n\n785\n00:45:25,650 --> 00:45:27,076\nworking all the way back?\n\n786\n00:45:27,076 --> 00:45:29,400\nPROFESSOR: Yes, the environment\nis a sequence of\n\n787\n00:45:29,400 --> 00:45:32,470\nframes linked together.\n\n788\n00:45:32,470 --> 00:45:34,700\nAnd the way I like to think\nabout it, it's the pointer to\n\n789\n00:45:34,700 --> 00:45:38,150\nthe first one, because\nonce you've got that\n\n790\n00:45:38,150 --> 00:45:39,400\nyou've got them all.\n\n791\n00:45:39,400 --> 00:45:44,080\n\n\n792\n00:45:44,080 --> 00:45:44,995\nAnybody else?\n\n793\n00:45:44,995 --> 00:45:47,800\nAUDIENCE: Is it possible to\nevaluate a procedure or to\n\n794\n00:45:47,800 --> 00:45:49,300\ndefine a procedure in two\ndifferent environments such\n\n795\n00:45:49,300 --> 00:45:51,580\nthat it will behave\ndifferently, and\n\n796\n00:45:51,580 --> 00:45:52,140\nhave pointers to both--\n\n797\n00:45:52,140 --> 00:45:53,600\nPROFESSOR: Oh, yes.\n\n798\n00:45:53,600 --> 00:45:55,260\nThe same procedure is not going\nto have two different\n\n799\n00:45:55,260 --> 00:45:57,290\nenvironments.\n\n800\n00:45:57,290 --> 00:46:01,895\nThe same code, the same lambda\nexpression can be evaluated in\n\n801\n00:46:01,895 --> 00:46:03,430\ntwo environments producing\ntwo different procedures.\n\n802\n00:46:03,430 --> 00:46:06,220\n\n\n803\n00:46:06,220 --> 00:46:07,140\nEach procedure--\n\n804\n00:46:07,140 --> 00:46:08,690\nAUDIENCE: Their definition\nhas the same name.\n\n805\n00:46:08,690 --> 00:46:09,170\nTheir operation--\n\n806\n00:46:09,170 --> 00:46:11,070\nPROFESSOR: The definition is\nwritten the same, with the\n\n807\n00:46:11,070 --> 00:46:12,570\nsame characters.\n\n808\n00:46:12,570 --> 00:46:16,700\nI can evaluate that set of\ncharacters, whatever, that\n\n809\n00:46:16,700 --> 00:46:19,530\nlist structure that defines,\nthat is the textual\n\n810\n00:46:19,530 --> 00:46:21,340\nrepresentation.\n\n811\n00:46:21,340 --> 00:46:23,650\nI can evaluate that in two\ndifferent environments\n\n812\n00:46:23,650 --> 00:46:25,650\nproducing two different\nprocedures.\n\n813\n00:46:25,650 --> 00:46:31,700\nEach of those procedures has\nits own local sets of\n\n814\n00:46:31,700 --> 00:46:33,490\nvariables, and we'll\nsee that right now.\n\n815\n00:46:33,490 --> 00:46:36,770\n\n\n816\n00:46:36,770 --> 00:46:38,020\nAnybody else?\n\n817\n00:46:38,020 --> 00:46:42,670\n\n\n818\n00:46:42,670 --> 00:46:43,280\nOK, thank you.\n\n819\n00:46:43,280 --> 00:46:44,530\nLet's take a break.\n\n820\n00:46:44,530 --> 00:46:48,750\n\n\n821\n00:46:48,750 --> 00:47:22,870\n[MUSIC PLAYING]\n\n822\n00:47:22,870 --> 00:47:26,670\nWell, now I've done this\nterrible thing to you.\n\n823\n00:47:26,670 --> 00:47:34,600\nI've introduced a very\ncomplicated thing, assignment,\n\n824\n00:47:34,600 --> 00:47:36,680\nwhich destroys most of the\ninteresting mathematical\n\n825\n00:47:36,680 --> 00:47:43,270\nproperties of our programs. Why\nshould I have done this?\n\n826\n00:47:43,270 --> 00:47:46,590\nWhat possible good\ncould this do?\n\n827\n00:47:46,590 --> 00:47:52,490\nClearly not a nice thing, so I\nbetter have a good excuse.\n\n828\n00:47:52,490 --> 00:47:56,150\nWell, let's do a little bit of\nplaying, first of all, with\n\n829\n00:47:56,150 --> 00:47:58,870\nsome very interesting programs\nthat have assignment.\n\n830\n00:47:58,870 --> 00:48:02,000\nUnderstand something special\nabout them that makes them\n\n831\n00:48:02,000 --> 00:48:04,820\nsomewhat valuable.\n\n832\n00:48:04,820 --> 00:48:08,110\nStart with a very simple program\nwhich I'm going to\n\n833\n00:48:08,110 --> 00:48:10,670\ncall make-counter.\n\n834\n00:48:10,670 --> 00:48:26,480\nI'm going to define make-counter\nto be a procedure\n\n835\n00:48:26,480 --> 00:48:31,280\nof one argument n which\nreturns as its value a\n\n836\n00:48:31,280 --> 00:48:34,390\nprocedure of no arguments--\n\n837\n00:48:34,390 --> 00:48:36,840\na procedure that produces\na procedure--\n\n838\n00:48:36,840 --> 00:48:48,600\nwhich sets n to the increment\nof n and returns\n\n839\n00:48:48,600 --> 00:48:50,120\nthat value of n.\n\n840\n00:48:50,120 --> 00:48:55,520\n\n\n841\n00:48:55,520 --> 00:48:57,560\nNow we're going to investigate\nthe behavior of this.\n\n842\n00:48:57,560 --> 00:48:59,840\nIt's a sort of interesting\nthing.\n\n843\n00:48:59,840 --> 00:49:02,150\nIn order to investigate the\nbehavior, I have to make an\n\n844\n00:49:02,150 --> 00:49:05,130\nenvironment model, because\nwe can't understand\n\n845\n00:49:05,130 --> 00:49:06,380\nthis any other way.\n\n846\n00:49:06,380 --> 00:49:08,630\n\n\n847\n00:49:08,630 --> 00:49:10,040\nSo let's just do that.\n\n848\n00:49:10,040 --> 00:49:13,005\nWe start out with\nsome sort of--\n\n849\n00:49:13,005 --> 00:49:15,270\nlet's say there is a global\nenvironment that the machine\n\n850\n00:49:15,270 --> 00:49:16,240\nis born with.\n\n851\n00:49:16,240 --> 00:49:19,720\nGlobal we'll call it.\n\n852\n00:49:19,720 --> 00:49:24,530\nAnd it's going to have in it\na bunch of initial things.\n\n853\n00:49:24,530 --> 00:49:25,820\nWe all know what it's got.\n\n854\n00:49:25,820 --> 00:49:32,930\nIt's got things in it like\nsay, plus, and times, and\n\n855\n00:49:32,930 --> 00:49:39,330\nquotient, and difference,\nand CAR, and et\n\n856\n00:49:39,330 --> 00:49:42,960\ncetera, lots of things.\n\n857\n00:49:42,960 --> 00:49:46,160\nI don't know what they are, some\nvarious squiggles that\n\n858\n00:49:46,160 --> 00:49:51,290\nare the things the machine\nis born with.\n\n859\n00:49:51,290 --> 00:49:56,350\nAnd by doing the definition\nhere, what I plan to do--\n\n860\n00:49:56,350 --> 00:49:57,390\nWell, what am I doing?\n\n861\n00:49:57,390 --> 00:49:59,780\nI'm doing this relative to\nthe global environment.\n\n862\n00:49:59,780 --> 00:50:03,580\nSo here's my environment\npointer.\n\n863\n00:50:03,580 --> 00:50:05,980\nIn order to do that I have\nto evaluate this lambda\n\n864\n00:50:05,980 --> 00:50:08,270\nexpression.\n\n865\n00:50:08,270 --> 00:50:11,490\nThat means I make a\nprocedure object.\n\n866\n00:50:11,490 --> 00:50:13,190\nSo I'm going to make a procedure\nobject here.\n\n867\n00:50:13,190 --> 00:50:17,400\n\n\n868\n00:50:17,400 --> 00:50:21,430\nAnd the procedure object has, as\nthe place it's defined, the\n\n869\n00:50:21,430 --> 00:50:23,820\nglobal environment.\n\n870\n00:50:23,820 --> 00:50:29,880\nThe procedure object contains\nsome code that represents a\n\n871\n00:50:29,880 --> 00:50:33,470\nprocedure of one argument n\nwhich returns a procedure of\n\n872\n00:50:33,470 --> 00:50:35,340\nno arguments which\ndoes something.\n\n873\n00:50:35,340 --> 00:50:38,320\n\n\n874\n00:50:38,320 --> 00:50:44,580\nAnd the define is a way of\nchanging this environment, so\n\n875\n00:50:44,580 --> 00:50:53,230\nthat I now add to it a\nmake-counter, a special rule\n\n876\n00:50:53,230 --> 00:50:55,470\nfor the special thing defined.\n\n877\n00:50:55,470 --> 00:50:59,810\nBut what that is, is\nit gives me that\n\n878\n00:50:59,810 --> 00:51:03,840\npointer to that procedure.\n\n879\n00:51:03,840 --> 00:51:06,370\nSo now the global environment\ncontains make-counter as well.\n\n880\n00:51:06,370 --> 00:51:09,330\n\n\n881\n00:51:09,330 --> 00:51:11,800\nNow, we're going to do\nsome operations.\n\n882\n00:51:11,800 --> 00:51:14,596\nI'm going to use this to\nmake some counters.\n\n883\n00:51:14,596 --> 00:51:17,140\nWe'll see what a counter is.\n\n884\n00:51:17,140 --> 00:51:26,700\nSo let's define c1 to be a\ncounter beginning at 0.\n\n885\n00:51:26,700 --> 00:51:35,440\n\n\n886\n00:51:35,440 --> 00:51:39,660\nWell, we know how to do this\nnow, according to the model.\n\n887\n00:51:39,660 --> 00:51:43,340\nI have to evaluate the\nexpression make-counter in the\n\n888\n00:51:43,340 --> 00:51:47,900\nglobal environment,\nmake-counter of 0.\n\n889\n00:51:47,900 --> 00:51:50,785\nWell, I look up make-counter and\nsee that it's a procedure.\n\n890\n00:51:50,785 --> 00:51:53,630\n\n\n891\n00:51:53,630 --> 00:51:56,010\nI'm going to have to apply\nthat procedure.\n\n892\n00:51:56,010 --> 00:51:59,820\nThe way I apply the procedure\nis by constructing a frame.\n\n893\n00:51:59,820 --> 00:52:02,400\n\n\n894\n00:52:02,400 --> 00:52:12,030\nSo I construct a frame which has\na value for n in it which\n\n895\n00:52:12,030 --> 00:52:16,850\nis 0, and the parent environment\nis the one which\n\n896\n00:52:16,850 --> 00:52:18,810\nis the environment of definition\nof make-counter.\n\n897\n00:52:18,810 --> 00:52:23,890\n\n\n898\n00:52:23,890 --> 00:52:28,400\nSo I've made an environment by\napplying make-counter to 0.\n\n899\n00:52:28,400 --> 00:52:31,580\n\n\n900\n00:52:31,580 --> 00:52:34,700\nNow, I have to evaluate the body\nof make-counter, which is\n\n901\n00:52:34,700 --> 00:52:37,455\nthis lambda expression,\nin that environment.\n\n902\n00:52:37,455 --> 00:52:40,730\n\n\n903\n00:52:40,730 --> 00:52:43,770\nWell evaluating this body,\nthis body is a lambda\n\n904\n00:52:43,770 --> 00:52:46,360\nexpression.\n\n905\n00:52:46,360 --> 00:52:49,570\nEvaluate a lambda expression\nmeans make a procedure object.\n\n906\n00:52:49,570 --> 00:52:50,820\nSo I'm going to make\na procedure object.\n\n907\n00:52:50,820 --> 00:52:56,840\n\n\n908\n00:52:56,840 --> 00:52:59,620\nAnd that procedure object has\nthe environment it was defined\n\n909\n00:52:59,620 --> 00:53:07,656\nin being that, where n\nwas defined to be 0.\n\n910\n00:53:07,656 --> 00:53:11,370\nAnd it has some code, which is\nthe procedure of no arguments\n\n911\n00:53:11,370 --> 00:53:17,622\nwhich does something, that sets\nsomething, and returns n.\n\n912\n00:53:17,622 --> 00:53:22,680\nAnd this thing is going to be\nthe object, which in the\n\n913\n00:53:22,680 --> 00:53:26,020\nglobal environment, will\nhave the name c1.\n\n914\n00:53:26,020 --> 00:53:32,625\nSo we construct a name here, c1,\nand say that equals that.\n\n915\n00:53:32,625 --> 00:53:35,560\n\n\n916\n00:53:35,560 --> 00:53:50,790\nNow, but also make another\ncounter, c2 to be make-counter\n\n917\n00:53:50,790 --> 00:53:53,868\nsay, starting with 10.\n\n918\n00:53:53,868 --> 00:53:57,270\nThen I do essentially\nthe same thing.\n\n919\n00:53:57,270 --> 00:53:59,910\nI apply the make-counter\nprocedure, which I got from\n\n920\n00:53:59,910 --> 00:54:05,690\nhere, to make another frame\nwith n being 10.\n\n921\n00:54:05,690 --> 00:54:10,050\nThat frame has the global\nenvironment as its parent.\n\n922\n00:54:10,050 --> 00:54:16,750\nI then construct a procedure\nwhich has that as it's frame\n\n923\n00:54:16,750 --> 00:54:18,000\nof definition.\n\n924\n00:54:18,000 --> 00:54:20,440\n\n\n925\n00:54:20,440 --> 00:54:23,240\nThe code of it is the procedure\nof no arguments\n\n926\n00:54:23,240 --> 00:54:25,390\nwhich does something.\n\n927\n00:54:25,390 --> 00:54:28,700\nAnd it does a set, and so on.\n\n928\n00:54:28,700 --> 00:54:31,510\nAnd n comes out.\n\n929\n00:54:31,510 --> 00:54:36,950\nAnd c2 is this.\n\n930\n00:54:36,950 --> 00:54:38,780\nWell, you're already beginning\nto see something fairly\n\n931\n00:54:38,780 --> 00:54:40,200\ninteresting.\n\n932\n00:54:40,200 --> 00:54:42,880\nThere are two n's here.\n\n933\n00:54:42,880 --> 00:54:46,330\nThey are not one n.\n\n934\n00:54:46,330 --> 00:54:49,310\nEach time I called make-counter,\nI made another\n\n935\n00:54:49,310 --> 00:54:52,520\ninstance of n.\n\n936\n00:54:52,520 --> 00:54:54,370\nThese are distinct and separate\nfrom each other.\n\n937\n00:54:54,370 --> 00:54:57,880\n\n\n938\n00:54:57,880 --> 00:55:00,783\nNow, let's do some execution,\nuse those counters.\n\n939\n00:55:00,783 --> 00:55:02,735\nI'm going to use\nthose counters.\n\n940\n00:55:02,735 --> 00:55:05,990\n\n\n941\n00:55:05,990 --> 00:55:15,900\nWell, what happens if I\nsay, c1 at this point?\n\n942\n00:55:15,900 --> 00:55:18,420\nWell, I go over here,\nand I say, oh\n\n943\n00:55:18,420 --> 00:55:20,840\nyes, c1 is a procedure.\n\n944\n00:55:20,840 --> 00:55:23,490\nI'm going to call this procedure\non no arguments, but\n\n945\n00:55:23,490 --> 00:55:25,060\nit has no parameters.\n\n946\n00:55:25,060 --> 00:55:27,020\nThat's right.\n\n947\n00:55:27,020 --> 00:55:28,080\nWhat's its body?\n\n948\n00:55:28,080 --> 00:55:29,776\nWell, I have to look over\nhere, because I\n\n949\n00:55:29,776 --> 00:55:30,130\ndidn't write it down.\n\n950\n00:55:30,130 --> 00:55:39,050\nIt said, set n to one plus n\nand return n, increment n.\n\n951\n00:55:39,050 --> 00:55:42,970\nWell, the n it sees\nis this one.\n\n952\n00:55:42,970 --> 00:55:45,490\nSo I increment that n.\n\n953\n00:55:45,490 --> 00:55:50,040\nThat becomes one, and I\nreturn the value one.\n\n954\n00:55:50,040 --> 00:55:53,050\n\n\n955\n00:55:53,050 --> 00:55:58,220\nSupposing I then called c2.\n\n956\n00:55:58,220 --> 00:55:59,820\nWell, what do I do?\n\n957\n00:55:59,820 --> 00:56:03,600\nI say c2 is this procedure which\ndoes the same thing, but\n\n958\n00:56:03,600 --> 00:56:05,450\nhere's the n.\n\n959\n00:56:05,450 --> 00:56:11,140\nIt becomes 11.\n\n960\n00:56:11,140 --> 00:56:15,980\nAnd so I have an 11 which\nis the value.\n\n961\n00:56:15,980 --> 00:56:18,130\nI then can say, let's\ntry c1 again.\n\n962\n00:56:18,130 --> 00:56:21,580\n\n\n963\n00:56:21,580 --> 00:56:29,660\nc1 is this, that's two,\nso the answer is two.\n\n964\n00:56:29,660 --> 00:56:36,560\nAnd c2 gives me a 12 by the same\nmethod, by walking down\n\n965\n00:56:36,560 --> 00:56:38,730\nhere looking at that and saying,\nhere's the n, I'm\n\n966\n00:56:38,730 --> 00:56:39,980\nincrementing.\n\n967\n00:56:39,980 --> 00:56:41,630\n\n\n968\n00:56:41,630 --> 00:56:44,920\nSo what I have are computational\nobjects.\n\n969\n00:56:44,920 --> 00:56:49,780\nThere are two counters,\neach with its own\n\n970\n00:56:49,780 --> 00:56:51,060\nindependent local state.\n\n971\n00:56:51,060 --> 00:56:55,540\n\n\n972\n00:56:55,540 --> 00:56:56,650\nLet's talk about\nthis a little.\n\n973\n00:56:56,650 --> 00:56:58,510\nThis is a strange thing.\n\n974\n00:56:58,510 --> 00:57:01,270\n\n\n975\n00:57:01,270 --> 00:57:04,140\nWhat's an object?\n\n976\n00:57:04,140 --> 00:57:07,560\nIt's not at all obvious\nwhat an object is.\n\n977\n00:57:07,560 --> 00:57:11,720\nWe like to think about\nobjects, because it's\n\n978\n00:57:11,720 --> 00:57:14,800\neconomical to think that way.\n\n979\n00:57:14,800 --> 00:57:18,670\nIt's an intellectual economy.\n\n980\n00:57:18,670 --> 00:57:21,120\nI am an object.\n\n981\n00:57:21,120 --> 00:57:23,610\nYou are an object.\n\n982\n00:57:23,610 --> 00:57:25,030\nWe are not the same object.\n\n983\n00:57:25,030 --> 00:57:27,600\n\n\n984\n00:57:27,600 --> 00:57:32,315\nI can divide the world into\ntwo parts, me and you, and\n\n985\n00:57:32,315 --> 00:57:36,600\nthere's other things as well,\nsuch that most of the things I\n\n986\n00:57:36,600 --> 00:57:41,410\nmight want to discuss about my\nworkings do not involve you,\n\n987\n00:57:41,410 --> 00:57:43,790\nand most of the things I want to\ndiscuss about your workings\n\n988\n00:57:43,790 --> 00:57:45,750\ndon't involve me.\n\n989\n00:57:45,750 --> 00:57:50,990\nI have a blood pressure, a\ntemperature, a respiration\n\n990\n00:57:50,990 --> 00:57:56,900\nrate, a certain amount of\nsugar in my blood, and\n\n991\n00:57:56,900 --> 00:57:59,400\nnumerous, thousands, of state\nvariables-- millions actually,\n\n992\n00:57:59,400 --> 00:58:01,030\nor I don't know how many--\n\n993\n00:58:01,030 --> 00:58:03,040\nhuge numbers of state variables\nin the physical\n\n994\n00:58:03,040 --> 00:58:09,240\nsense which represent the state\nof me as a particle, and\n\n995\n00:58:09,240 --> 00:58:12,770\nyou have gazillions\nof them as well.\n\n996\n00:58:12,770 --> 00:58:17,290\nAnd most of mine are uncoupled\nto most of yours.\n\n997\n00:58:17,290 --> 00:58:21,000\nSo we can compute the properties\nof me without\n\n998\n00:58:21,000 --> 00:58:23,940\nworrying too much about\nthe properties of you.\n\n999\n00:58:23,940 --> 00:58:26,310\nIf we had to work about both\nof us together, than the\n\n1000\n00:58:26,310 --> 00:58:28,460\nnumber of states that we have to\nconsider is the product of\n\n1001\n00:58:28,460 --> 00:58:29,840\nthe number of states you have\nand the number of states I\n\n1002\n00:58:29,840 --> 00:58:32,760\nhave. But this way it's\nalmost a sum.\n\n1003\n00:58:32,760 --> 00:58:36,110\nNow, indeed there are forces\nthat couple us.\n\n1004\n00:58:36,110 --> 00:58:38,420\nI'm talking to you and\nyour state changes.\n\n1005\n00:58:38,420 --> 00:58:41,680\nI'm looking at you and\nmy state changes.\n\n1006\n00:58:41,680 --> 00:58:45,010\nSome of my state variables, a\nvery few of them, therefore,\n\n1007\n00:58:45,010 --> 00:58:46,190\nare coupled to yours.\n\n1008\n00:58:46,190 --> 00:58:48,470\nIf you were to suddenly yell\nvery loud, my blood pressure\n\n1009\n00:58:48,470 --> 00:58:49,720\nwould go up.\n\n1010\n00:58:49,720 --> 00:58:54,320\n\n\n1011\n00:58:54,320 --> 00:58:57,590\nHowever, and it may not be\nalways appropriate to think\n\n1012\n00:58:57,590 --> 00:59:00,360\nabout the world as being made\nout of independent states and\n\n1013\n00:59:00,360 --> 00:59:02,260\nindependent particles.\n\n1014\n00:59:02,260 --> 00:59:05,350\nLots of the bugs that occur in\nthings like quantum mechanics,\n\n1015\n00:59:05,350 --> 00:59:07,660\nor the bugs in our minds that\noccur when we think about\n\n1016\n00:59:07,660 --> 00:59:09,840\nthings like quantum mechanics,\nare due the fact that we are\n\n1017\n00:59:09,840 --> 00:59:11,910\ntrying to think about things\nbeing broken up into\n\n1018\n00:59:11,910 --> 00:59:15,880\nindependent pieces, when in\nfact there's more coupling\n\n1019\n00:59:15,880 --> 00:59:19,750\nthan we see on the surface, or\nthat we want to believe in,\n\n1020\n00:59:19,750 --> 00:59:22,300\nbecause we want to compute\nefficiently and effectively.\n\n1021\n00:59:22,300 --> 00:59:23,780\nWe've been trained to\nthink that way.\n\n1022\n00:59:23,780 --> 00:59:29,336\n\n\n1023\n00:59:29,336 --> 00:59:31,440\nWell, let's see.\n\n1024\n00:59:31,440 --> 00:59:35,140\nHow would we know if we\nhad objects at all?\n\n1025\n00:59:35,140 --> 00:59:37,690\nHow can we tell if\nwe have objects?\n\n1026\n00:59:37,690 --> 00:59:41,770\nConsider some possible\noptical illusions.\n\n1027\n00:59:41,770 --> 00:59:44,805\nThis could be done.\n\n1028\n00:59:44,805 --> 00:59:47,970\nThese pieces of chalk are not\nappropriately identical, but\n\n1029\n00:59:47,970 --> 00:59:49,520\nsupposing you couldn't tell\nthe difference of them by\n\n1030\n00:59:49,520 --> 00:59:52,130\nlooking at them.\n\n1031\n00:59:52,130 --> 00:59:54,290\nWell, there's a possibility\nthat this all a game I'm\n\n1032\n00:59:54,290 --> 00:59:55,725\nplaying with mirrors.\n\n1033\n00:59:55,725 --> 00:59:59,690\nIt's really the same piece\nof chalk, but you're\n\n1034\n00:59:59,690 --> 01:00:01,660\nseeing two of them.\n\n1035\n01:00:01,660 --> 01:00:05,160\nHow would you know if you're\nseeing one or two?\n\n1036\n01:00:05,160 --> 01:00:07,430\nWell, there's only\none way I know.\n\n1037\n01:00:07,430 --> 01:00:10,110\nYou grab one of them and change\nit and see if the other\n\n1038\n01:00:10,110 --> 01:00:11,360\none changed.\n\n1039\n01:00:11,360 --> 01:00:13,580\n\n\n1040\n01:00:13,580 --> 01:00:16,180\nAnd it didn't, so there's\ntwo of them.\n\n1041\n01:00:16,180 --> 01:00:19,070\n\n\n1042\n01:00:19,070 --> 01:00:20,890\nAnd, on the other hand, there\nis some other screwy\n\n1043\n01:00:20,890 --> 01:00:22,580\nproperties of things\nlike that.\n\n1044\n01:00:22,580 --> 01:00:25,040\nLike, how do we know if\nsomething changed?\n\n1045\n01:00:25,040 --> 01:00:28,760\nWe have to look at it before\nand after the change.\n\n1046\n01:00:28,760 --> 01:00:32,200\nThe change is an assignment,\nit's a moment in time.\n\n1047\n01:00:32,200 --> 01:00:34,120\nBut that means we have to know\nit was the same one that we're\n\n1048\n01:00:34,120 --> 01:00:36,540\nlooking at.\n\n1049\n01:00:36,540 --> 01:00:39,270\nSo some very strange, and\nunusual, and obscure, and--\n\n1050\n01:00:39,270 --> 01:00:42,950\nI don't understand the problems\nassociated with\n\n1051\n01:00:42,950 --> 01:00:47,380\nassignment, and change,\nand objects.\n\n1052\n01:00:47,380 --> 01:00:51,420\nThese could get very,\nvery bad.\n\n1053\n01:00:51,420 --> 01:00:56,250\nFor example, here I am, I am\na particular person, a\n\n1054\n01:00:56,250 --> 01:00:57,650\nparticular object.\n\n1055\n01:00:57,650 --> 01:01:02,430\nNow, I can take out my knife,\nand cut my fingernail.\n\n1056\n01:01:02,430 --> 01:01:06,030\nA piece of my fingernail has\nfallen off onto the table.\n\n1057\n01:01:06,030 --> 01:01:11,200\nI believe I am the same person\nI was a second ago, but I'm\n\n1058\n01:01:11,200 --> 01:01:14,490\nnot physically the same\nin the slightest.\n\n1059\n01:01:14,490 --> 01:01:15,620\nI have changed.\n\n1060\n01:01:15,620 --> 01:01:18,180\nWhy am I the same?\n\n1061\n01:01:18,180 --> 01:01:21,070\nWhat is the identity of me?\n\n1062\n01:01:21,070 --> 01:01:22,320\nI don't know.\n\n1063\n01:01:22,320 --> 01:01:25,170\n\n\n1064\n01:01:25,170 --> 01:01:29,770\nExcept for the fact that I have\nsome sort of identity.\n\n1065\n01:01:29,770 --> 01:01:34,770\nAnd so, I think by introducing\nassignment and objects, we\n\n1066\n01:01:34,770 --> 01:01:37,670\nhave opened ourselves up to all\nthe horrible questions of\n\n1067\n01:01:37,670 --> 01:01:40,490\nphilosophy that have been\nplaguing philosophers for some\n\n1068\n01:01:40,490 --> 01:01:43,510\nthousands of years about\nthis sort of thing.\n\n1069\n01:01:43,510 --> 01:01:45,880\nIt's why mathematics\nis a lot cleaner.\n\n1070\n01:01:45,880 --> 01:01:49,590\nLet's look at the best things\nI know to say about actions\n\n1071\n01:01:49,590 --> 01:01:50,840\nand identity.\n\n1072\n01:01:50,840 --> 01:01:52,500\n\n\n1073\n01:01:52,500 --> 01:01:56,050\nWe say that an action, a, had an\neffect on an object, x, or\n\n1074\n01:01:56,050 --> 01:01:59,340\nequivalently, that x was\nchanged by a, if some\n\n1075\n01:01:59,340 --> 01:02:02,410\nproperty, p, which was true\nof x before a, became\n\n1076\n01:02:02,410 --> 01:02:05,100\nfalse of x after a.\n\n1077\n01:02:05,100 --> 01:02:07,750\nLet's test. It still means\nI have to have the\n\n1078\n01:02:07,750 --> 01:02:10,950\nx before and after.\n\n1079\n01:02:10,950 --> 01:02:13,810\nOr, the other way of saying\nthis is, we say that two\n\n1080\n01:02:13,810 --> 01:02:15,460\nobjects x and y are the same\nfor any action which has an\n\n1081\n01:02:15,460 --> 01:02:19,580\neffect on x has the\nsame effect on y.\n\n1082\n01:02:19,580 --> 01:02:22,230\nHowever, objects are very\nuseful, as I said, for\n\n1083\n01:02:22,230 --> 01:02:24,650\nintellectual economy.\n\n1084\n01:02:24,650 --> 01:02:28,350\nOne of the things that's\nincredibly useful about them,\n\n1085\n01:02:28,350 --> 01:02:32,980\nis that the world is, we like\nto think about, made out of\n\n1086\n01:02:32,980 --> 01:02:35,050\nindependent objects with\nindependent local state.\n\n1087\n01:02:35,050 --> 01:02:36,430\nWe like to think that\nway, although it\n\n1088\n01:02:36,430 --> 01:02:39,730\nisn't completely true.\n\n1089\n01:02:39,730 --> 01:02:42,470\nWhen we want to make very\ncomplicated programs that deal\n\n1090\n01:02:42,470 --> 01:02:45,400\nwith such a world, if we want\nthose programs to be\n\n1091\n01:02:45,400 --> 01:02:49,070\nunderstandable by us and also\nto be changeable, so that if\n\n1092\n01:02:49,070 --> 01:02:51,390\nwe change the world we change\nthe program only a little bit,\n\n1093\n01:02:51,390 --> 01:02:53,810\nthen we want there to be\nconnections, isomorphism,\n\n1094\n01:02:53,810 --> 01:02:56,130\nbetween the objects in the world\nand the objects in our\n\n1095\n01:02:56,130 --> 01:02:58,720\nmental model.\n\n1096\n01:02:58,720 --> 01:03:00,960\nThe modularity of the world can\ngive us the modularity in\n\n1097\n01:03:00,960 --> 01:03:02,400\nour programming.\n\n1098\n01:03:02,400 --> 01:03:04,590\nSo we invent things called\nobject-oriented programming\n\n1099\n01:03:04,590 --> 01:03:09,950\nand things like that to provide\nus with that power.\n\n1100\n01:03:09,950 --> 01:03:10,990\nBut it's even easier.\n\n1101\n01:03:10,990 --> 01:03:12,310\nLet's play a little game.\n\n1102\n01:03:12,310 --> 01:03:15,110\nI want to play a little game,\nshow you an even easier\n\n1103\n01:03:15,110 --> 01:03:19,610\nexample of where modularity can\nbe enhanced by using an\n\n1104\n01:03:19,610 --> 01:03:22,960\nassignment statement,\njudiciously.\n\n1105\n01:03:22,960 --> 01:03:26,280\nOne thing I want to enforce and\nimpress on you, is don't\n\n1106\n01:03:26,280 --> 01:03:28,280\nuse assignment statements the\nway you use it in FORTRAN or\n\n1107\n01:03:28,280 --> 01:03:30,930\nBasic or something or Pascal,\nto do the things you don't\n\n1108\n01:03:30,930 --> 01:03:32,180\nhave to do with it.\n\n1109\n01:03:32,180 --> 01:03:34,200\n\n\n1110\n01:03:34,200 --> 01:03:37,010\nIt's not the right way to\nthink for most things.\n\n1111\n01:03:37,010 --> 01:03:39,810\nSometimes it's essential,\nor maybe it's essential.\n\n1112\n01:03:39,810 --> 01:03:42,320\nWe'll see more about that too.\n\n1113\n01:03:42,320 --> 01:03:44,330\nOK, let me show you\na fun game here.\n\n1114\n01:03:44,330 --> 01:03:47,270\n\n\n1115\n01:03:47,270 --> 01:03:51,750\nThere was mathematician by\nthe name of Cesaro--\n\n1116\n01:03:51,750 --> 01:03:54,760\nor Cesaro, Cesaro I\nsuppose it is--\n\n1117\n01:03:54,760 --> 01:03:58,450\nwho figured out a clever\nway of computing pi.\n\n1118\n01:03:58,450 --> 01:04:06,320\nIt turns out that if I take to\nrandom numbers, two integers\n\n1119\n01:04:06,320 --> 01:04:11,110\nat random, and compute the\ngreatest common divisor, their\n\n1120\n01:04:11,110 --> 01:04:13,920\ngreatest common divisor is\neither one or it's not one.\n\n1121\n01:04:13,920 --> 01:04:15,445\nIf it's one, then they have\nno common divisors.\n\n1122\n01:04:15,445 --> 01:04:18,240\n\n\n1123\n01:04:18,240 --> 01:04:21,060\nIf their greatest common\ndivisor is one--\n\n1124\n01:04:21,060 --> 01:04:23,590\nthe probability that two random\nnumbers, two numbers\n\n1125\n01:04:23,590 --> 01:04:26,910\nchosen at random, has as\ngreatest common divisor one is\n\n1126\n01:04:26,910 --> 01:04:29,580\nrelated to pi.\n\n1127\n01:04:29,580 --> 01:04:31,310\nIn fact--\n\n1128\n01:04:31,310 --> 01:04:33,070\nyes, it's very strange--\n\n1129\n01:04:33,070 --> 01:04:34,980\nof course there are other ways\nof computing pi, like dropping\n\n1130\n01:04:34,980 --> 01:04:38,100\npins on flags, and things like\nthat, and sort of the same\n\n1131\n01:04:38,100 --> 01:04:40,110\nkind of thing.\n\n1132\n01:04:40,110 --> 01:04:48,510\nSo the probability of that the\nGCD of number one and number\n\n1133\n01:04:48,510 --> 01:04:55,660\ntwo, two random numbers chosen,\nis 6 over pi squared.\n\n1134\n01:04:55,660 --> 01:04:57,240\nI'm not going to try\nto prove that.\n\n1135\n01:04:57,240 --> 01:05:01,120\nIt's actually not too hard\nand sort of fun.\n\n1136\n01:05:01,120 --> 01:05:03,590\nHow would we estimate\nsuch probability?\n\n1137\n01:05:03,590 --> 01:05:07,340\nWell, the way we do that, the\nway we estimate probabilities,\n\n1138\n01:05:07,340 --> 01:05:09,620\nis by doing lots of experiments,\nand then\n\n1139\n01:05:09,620 --> 01:05:12,260\ncomputing the ratios of the ones\nthat come out one way to\n\n1140\n01:05:12,260 --> 01:05:13,570\nthe total number of\nexperiments we do.\n\n1141\n01:05:13,570 --> 01:05:16,320\n\n\n1142\n01:05:16,320 --> 01:05:19,680\nIt's called Monte Carlo, and\nit's useful in other contexts\n\n1143\n01:05:19,680 --> 01:05:21,280\nfor doing things like integrals\nwhere you have lots\n\n1144\n01:05:21,280 --> 01:05:22,960\nand lots of variables--\n\n1145\n01:05:22,960 --> 01:05:24,780\nthe space which is limiting the\ndimensions you are doing\n\n1146\n01:05:24,780 --> 01:05:26,360\nyou integral in.\n\n1147\n01:05:26,360 --> 01:05:34,680\nBut going back to here, Let's\nlook at this slide, We can use\n\n1148\n01:05:34,680 --> 01:05:40,520\nCesaro's method for estimating\npi with n trials by taking the\n\n1149\n01:05:40,520 --> 01:05:45,850\nsquare root of six over a Monte\nCarlo, a Monte Carlo\n\n1150\n01:05:45,850 --> 01:05:51,410\nexperiment with n trials, using\nCesaro's experiment,\n\n1151\n01:05:51,410 --> 01:05:56,550\nwhere Cesaro's experiment is the\ntest of whether the GCD of\n\n1152\n01:05:56,550 --> 01:05:59,070\ntwo random numbers--\n\n1153\n01:05:59,070 --> 01:06:01,200\nAnd you can see that I've\nalready got some assignments\n\n1154\n01:06:01,200 --> 01:06:03,990\nin here, just by what I wrote.\n\n1155\n01:06:03,990 --> 01:06:07,930\nThe fact that this word rand,\nin parentheses, therefore,\n\n1156\n01:06:07,930 --> 01:06:11,530\nthat procedure call, yields a\ndifferent value than this one,\n\n1157\n01:06:11,530 --> 01:06:13,330\nat least that's what I'm\nassuming by writing this this\n\n1158\n01:06:13,330 --> 01:06:18,590\nway, indicates that this is not\na function, that there's\n\n1159\n01:06:18,590 --> 01:06:20,400\ninternal state in it\nwhich is changing.\n\n1160\n01:06:20,400 --> 01:06:25,110\n\n\n1161\n01:06:25,110 --> 01:06:28,530\nIf the GCD of those two random\nnumbers is equal to one,\n\n1162\n01:06:28,530 --> 01:06:31,530\nthat's the experiment.\n\n1163\n01:06:31,530 --> 01:06:34,330\nSo here I have an experimental\nmethod for estimating the\n\n1164\n01:06:34,330 --> 01:06:36,560\nvalue of pi.\n\n1165\n01:06:36,560 --> 01:06:40,160\nWhere, I can easily divide this\nproblem into two parts.\n\n1166\n01:06:40,160 --> 01:06:43,610\nOne is the specific Monte Carlo\nexperiment of Cesaro,\n\n1167\n01:06:43,610 --> 01:06:46,700\nwhich you just saw, and the\nother is the general technique\n\n1168\n01:06:46,700 --> 01:06:49,320\nof doing Monte Carlo\nexperiments.\n\n1169\n01:06:49,320 --> 01:06:51,190\nAnd that's what this is.\n\n1170\n01:06:51,190 --> 01:06:55,930\nIf I want to do Monte Carlo\nexperiments with n trials, a\n\n1171\n01:06:55,930 --> 01:06:59,590\ncertain number of trials, and\na particular experiment, the\n\n1172\n01:06:59,590 --> 01:07:03,460\nway I do that is I make a little\niterative procedure\n\n1173\n01:07:03,460 --> 01:07:05,960\nwhich has variable the number\nof trials remaining and the\n\n1174\n01:07:05,960 --> 01:07:10,230\nnumber trials that have been\npassed, that I've gotten true.\n\n1175\n01:07:10,230 --> 01:07:13,010\nAnd if the number remaining is\n0, then the answer is the\n\n1176\n01:07:13,010 --> 01:07:16,260\nnumber past divided by this\nwhole number of trials, was\n\n1177\n01:07:16,260 --> 01:07:19,150\nthe estimate of the\nprobability.\n\n1178\n01:07:19,150 --> 01:07:22,140\nAnd if it's not, if I have\nmore trials to do,\n\n1179\n01:07:22,140 --> 01:07:22,870\nthen let's do one.\n\n1180\n01:07:22,870 --> 01:07:23,860\nWe do an experiment.\n\n1181\n01:07:23,860 --> 01:07:27,350\nWe call the procedure which is\nexperiment on no arguments.\n\n1182\n01:07:27,350 --> 01:07:30,870\nWe do the experiment and then,\nif that turned out to be true,\n\n1183\n01:07:30,870 --> 01:07:33,830\nwe go around the loop\ndecrementing the number of\n\n1184\n01:07:33,830 --> 01:07:36,560\nexperiments we have to do by\none and incrementing the\n\n1185\n01:07:36,560 --> 01:07:38,650\nnumber that were passed.\n\n1186\n01:07:38,650 --> 01:07:41,880\nAnd if the experiment was false,\nwe just go around the\n\n1187\n01:07:41,880 --> 01:07:44,700\nloop decrementing the number of\nexperiments remaining and\n\n1188\n01:07:44,700 --> 01:07:48,910\nkeeping the number\npassed the same.\n\n1189\n01:07:48,910 --> 01:07:51,320\nWe start this up iterating\nover the total number of\n\n1190\n01:07:51,320 --> 01:07:55,840\ntrials with 0 experiments\npast. A very\n\n1191\n01:07:55,840 --> 01:07:57,730\nelegant little program.\n\n1192\n01:07:57,730 --> 01:08:00,530\nAnd I don't have to just do this\nwith Cesaro's experiment,\n\n1193\n01:08:00,530 --> 01:08:03,390\nit could be lots of Monte Carlo\nexperiments I might do.\n\n1194\n01:08:03,390 --> 01:08:05,860\nOf course, this depends upon the\nexistence of some sort of\n\n1195\n01:08:05,860 --> 01:08:07,440\nrandom number generator.\n\n1196\n01:08:07,440 --> 01:08:09,960\nAnd random number generators\ngenerally look\n\n1197\n01:08:09,960 --> 01:08:11,210\nsomething like this.\n\n1198\n01:08:11,210 --> 01:08:13,570\n\n\n1199\n01:08:13,570 --> 01:08:17,550\nThere is a random number\ngenerator--\n\n1200\n01:08:17,550 --> 01:08:24,490\nis in fact a procedure which is\ngoing to do something just\n\n1201\n01:08:24,490 --> 01:08:25,710\nlike the counter.\n\n1202\n01:08:25,710 --> 01:08:30,870\nIt's going to update an x to\nthe result of applying some\n\n1203\n01:08:30,870 --> 01:08:34,600\nfunction to x, where this\nfunction is some screwy kind\n\n1204\n01:08:34,600 --> 01:08:38,800\nof function that you might find\nout in Knuth's books on\n\n1205\n01:08:38,800 --> 01:08:41,689\nthe details of programming.\n\n1206\n01:08:41,689 --> 01:08:45,020\nHe does these wonderful books\nthat are full of the details\n\n1207\n01:08:45,020 --> 01:08:47,500\nof programming, because I can't\nremember how to make a\n\n1208\n01:08:47,500 --> 01:08:50,156\nrandom number generator, but I\ncan look it up there, and I\n\n1209\n01:08:50,156 --> 01:08:51,720\ncan find out.\n\n1210\n01:08:51,720 --> 01:08:54,850\nAnd then, eventually, I return\nthe value of x which is the\n\n1211\n01:08:54,850 --> 01:08:58,319\nstate variable internal to the\nrandom number generator.\n\n1212\n01:08:58,319 --> 01:09:00,140\nThat state variable\nis initialized\n\n1213\n01:09:00,140 --> 01:09:03,479\nsomehow, and has a value.\n\n1214\n01:09:03,479 --> 01:09:06,490\nAnd this procedure is defined\nin the context where that\n\n1215\n01:09:06,490 --> 01:09:10,450\nvariable is bound.\n\n1216\n01:09:10,450 --> 01:09:15,930\nSo this is a hidden piece of\nlocal state that you see here.\n\n1217\n01:09:15,930 --> 01:09:21,720\nAnd this procedure is defined\nin that context.\n\n1218\n01:09:21,720 --> 01:09:24,103\nNow, that's a very simple\nthing to do.\n\n1219\n01:09:24,103 --> 01:09:26,020\nAnd it's very nice.\n\n1220\n01:09:26,020 --> 01:09:29,080\nSupposing, I didn't want\nto use assignments.\n\n1221\n01:09:29,080 --> 01:09:30,819\nSupposing, I wanted to write\nthis program without\n\n1222\n01:09:30,819 --> 01:09:32,840\nassignments.\n\n1223\n01:09:32,840 --> 01:09:35,580\nWhat problems would I have?\n\n1224\n01:09:35,580 --> 01:09:37,890\nWell, let's see.\n\n1225\n01:09:37,890 --> 01:09:44,540\nI'd like to use the overhead\nmachine here, thank you.\n\n1226\n01:09:44,540 --> 01:09:45,870\nFirst of all, let's look\nat the whole thing.\n\n1227\n01:09:45,870 --> 01:09:48,140\nIt's a big story.\n\n1228\n01:09:48,140 --> 01:09:51,720\nUnfortunately, which tells you\nthere is something wrong.\n\n1229\n01:09:51,720 --> 01:09:54,255\nIt's at least that big,\nand it's monolithic.\n\n1230\n01:09:54,255 --> 01:09:57,020\n\n\n1231\n01:09:57,020 --> 01:09:59,580\nYou don't have to understand\nor look at the text there\n\n1232\n01:09:59,580 --> 01:10:02,120\nright now to see that\nit's monolithic.\n\n1233\n01:10:02,120 --> 01:10:05,090\nIt isn't a thing which is\nCesaro's experiment.\n\n1234\n01:10:05,090 --> 01:10:10,050\nIt's not pulled out from the\nMonte Carlo process.\n\n1235\n01:10:10,050 --> 01:10:10,890\nIt's not separated.\n\n1236\n01:10:10,890 --> 01:10:12,140\nLet's look why.\n\n1237\n01:10:12,140 --> 01:10:14,350\n\n\n1238\n01:10:14,350 --> 01:10:19,330\nRemember, the constraint here is\nthat every procedure return\n\n1239\n01:10:19,330 --> 01:10:23,070\nthe same value for the\nsame arguments.\n\n1240\n01:10:23,070 --> 01:10:26,800\nEvery procedure represents\na function.\n\n1241\n01:10:26,800 --> 01:10:28,275\nThat's a different kind\nof constraint.\n\n1242\n01:10:28,275 --> 01:10:30,250\nBecause when I have assignments,\nI can change some\n\n1243\n01:10:30,250 --> 01:10:31,840\ninternal state variable.\n\n1244\n01:10:31,840 --> 01:10:35,060\nSo let's see how that causes\nthings to go wrong.\n\n1245\n01:10:35,060 --> 01:10:38,510\nWell, start at the beginning.\n\n1246\n01:10:38,510 --> 01:10:42,950\nThe estimate of pi looks\nsort of the same.\n\n1247\n01:10:42,950 --> 01:10:47,560\nWhat I'm doing is I take the\nsquare root of six over the\n\n1248\n01:10:47,560 --> 01:10:52,990\nrandom GCD test applied to n,\nwhereas that's what this is.\n\n1249\n01:10:52,990 --> 01:10:55,390\nBut here, we are beginning\nto see something funny.\n\n1250\n01:10:55,390 --> 01:10:58,770\nThe random GCD test of a certain\nnumber of trials is\n\n1251\n01:10:58,770 --> 01:11:03,400\njust like we had before, an\niteration on the number of\n\n1252\n01:11:03,400 --> 01:11:06,210\ntrials remaining, the number\nof trials that have been\n\n1253\n01:11:06,210 --> 01:11:10,870\npassed, and another\nvariable x.\n\n1254\n01:11:10,870 --> 01:11:12,370\nWhat's that x?\n\n1255\n01:11:12,370 --> 01:11:14,950\nThat x is the state of the\nrandom number generator.\n\n1256\n01:11:14,950 --> 01:11:18,950\n\n\n1257\n01:11:18,950 --> 01:11:21,150\nAnd it is now going\nto be used here.\n\n1258\n01:11:21,150 --> 01:11:23,890\nThe same random update function\nthat I have over here\n\n1259\n01:11:23,890 --> 01:11:25,890\nis the one I would have used in\na random number generator\n\n1260\n01:11:25,890 --> 01:11:28,510\nif I were building it the other\nway, the one I get out\n\n1261\n01:11:28,510 --> 01:11:31,710\nof Knuth's books.\n\n1262\n01:11:31,710 --> 01:11:33,380\nx is going to get transformed\ninto x1, I\n\n1263\n01:11:33,380 --> 01:11:34,950\nneed two random numbers.\n\n1264\n01:11:34,950 --> 01:11:37,630\nAnd x1 is going to get\ntransformed into x2, I have\n\n1265\n01:11:37,630 --> 01:11:39,550\ntwo random numbers.\n\n1266\n01:11:39,550 --> 01:11:42,620\nI then have to do exactly\nwhat I did before.\n\n1267\n01:11:42,620 --> 01:11:43,870\nI take the GCD of x1 x2.\n\n1268\n01:11:43,870 --> 01:11:48,260\nIf that's one, then I go around\nthe loop with x2 being\n\n1269\n01:11:48,260 --> 01:11:49,520\nthe next value of x.\n\n1270\n01:11:49,520 --> 01:11:54,850\n\n\n1271\n01:11:54,850 --> 01:11:57,740\nYou see what's happened here\nis that the state of the\n\n1272\n01:11:57,740 --> 01:12:00,480\nrandom number generator is no\nlonger confined to the insides\n\n1273\n01:12:00,480 --> 01:12:01,495\nof the random number\ngenerator.\n\n1274\n01:12:01,495 --> 01:12:03,450\nIt has leaked out.\n\n1275\n01:12:03,450 --> 01:12:09,240\nIt has leaked out into my\nprocedure that does the Monte\n\n1276\n01:12:09,240 --> 01:12:10,720\nCarlo experiment.\n\n1277\n01:12:10,720 --> 01:12:13,480\nBut what's worse than that, is\nit's also, because it was\n\n1278\n01:12:13,480 --> 01:12:17,470\ncontained inside my experiment\nitself, Cesaro, it leaked out\n\n1279\n01:12:17,470 --> 01:12:18,090\nof that too.\n\n1280\n01:12:18,090 --> 01:12:21,920\nBecause Cesaro called twice, has\nto have a different value\n\n1281\n01:12:21,920 --> 01:12:24,780\neach time, if I going to have\na legitimate experimental\n\n1282\n01:12:24,780 --> 01:12:31,910\ntest. So Cesaro can't be a\nfunction either, unless I pass\n\n1283\n01:12:31,910 --> 01:12:34,730\nit the seed of the random number\ngenerator that is going\n\n1284\n01:12:34,730 --> 01:12:36,490\nto go wandering around.\n\n1285\n01:12:36,490 --> 01:12:39,740\nSo unfortunately, the seed of\nrandom number generator has\n\n1286\n01:12:39,740 --> 01:12:42,850\nleaked out into Cesaro, from the\nrandom number generator,\n\n1287\n01:12:42,850 --> 01:12:45,465\nthat's leaked into the Monte\nCarlo experiment.\n\n1288\n01:12:45,465 --> 01:12:48,485\nAnd, unfortunately, my Monte\nCarlo experiment here is no\n\n1289\n01:12:48,485 --> 01:12:50,310\nlonger general.\n\n1290\n01:12:50,310 --> 01:12:52,990\nThe Monte Carlo experiment here\nknows how many random\n\n1291\n01:12:52,990 --> 01:12:54,405\nnumbers I need to do\nthe experiment.\n\n1292\n01:12:54,405 --> 01:12:58,530\n\n\n1293\n01:12:58,530 --> 01:13:00,230\nThat's sort of horrible.\n\n1294\n01:13:00,230 --> 01:13:04,090\nI lost an ability to decompose a\nproblem into pieces, because\n\n1295\n01:13:04,090 --> 01:13:10,720\nI wasn't willing to accept the\nlittle loop of information,\n\n1296\n01:13:10,720 --> 01:13:14,720\nthe feedback process, that\nhappens inside the random\n\n1297\n01:13:14,720 --> 01:13:18,000\nnumber generator before that\nwas made by having an\n\n1298\n01:13:18,000 --> 01:13:20,400\nassignment to a state variable\nthat was confined to the\n\n1299\n01:13:20,400 --> 01:13:22,770\nrandom number generator.\n\n1300\n01:13:22,770 --> 01:13:26,070\nSo the fact that the random\nnumber generator is an object,\n\n1301\n01:13:26,070 --> 01:13:29,040\nwith an internal state variable,\nit's affected by\n\n1302\n01:13:29,040 --> 01:13:30,595\nnothing, but it'll give you\nsomething, and it will apply\n\n1303\n01:13:30,595 --> 01:13:34,290\nit's force to you, that was\nwhat we're missing now.\n\n1304\n01:13:34,290 --> 01:13:38,140\n\n\n1305\n01:13:38,140 --> 01:13:42,870\nOK, well I think we've seen\nenough reason for doing this,\n\n1306\n01:13:42,870 --> 01:13:45,510\nand it all sort of looks\nvery wonderful.\n\n1307\n01:13:45,510 --> 01:13:51,840\nWouldn't it be nice if\nassignment was a good thing\n\n1308\n01:13:51,840 --> 01:13:55,440\nand maybe it's worth it,\nbut I'm not sure.\n\n1309\n01:13:55,440 --> 01:13:57,860\nAs Mr. Gilbert and Sullivan\nsaid, things are seldom what\n\n1310\n01:13:57,860 --> 01:14:01,940\nthey seem, skim milk masquerades\nas cream.\n\n1311\n01:14:01,940 --> 01:14:03,655\nAre there any questions?\n\n1312\n01:14:03,655 --> 01:14:17,010\n\n\n1313\n01:14:17,010 --> 01:14:20,120\nAre there any philosophers\nhere?\n\n1314\n01:14:20,120 --> 01:14:21,930\nAnybody want to argue\nabout objects?\n\n1315\n01:14:21,930 --> 01:14:24,590\n\n\n1316\n01:14:24,590 --> 01:14:25,840\nYou're just floored, right?\n\n1317\n01:14:25,840 --> 01:14:29,840\n\n\n1318\n01:14:29,840 --> 01:14:30,805\nAnd you haven't done\nyour homework yet.\n\n1319\n01:14:30,805 --> 01:14:32,055\nYou haven't come up with\na good question.\n\n1320\n01:14:32,055 --> 01:14:36,790\n\n\n1321\n01:14:36,790 --> 01:14:38,040\nOh, well.\n\n1322\n01:14:38,040 --> 01:14:40,110\n\n\n1323\n01:14:40,110 --> 01:14:41,120\nSure, thank you.\n\n1324\n01:14:41,120 --> 01:14:42,370\nLet's take the long break now.\n\n1325\n01:14:42,370 --> 01:15:17,567\n\n"
  },
  {
    "path": "SrtEN/lec5b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:21,170\n\n\n1\n00:00:21,170 --> 00:00:24,550\nPROFESSOR: Well, now that we've\ngiven you some power to\n\n2\n00:00:24,550 --> 00:00:28,340\nmake independent local state\nand to model objects, I\n\n3\n00:00:28,340 --> 00:00:31,610\nthought we'd do a bit of\nprogramming of a very\n\n4\n00:00:31,610 --> 00:00:35,380\ncomplicated kind, just to\nillustrate what you can do\n\n5\n00:00:35,380 --> 00:00:36,630\nwith this sort of thing.\n\n6\n00:00:36,630 --> 00:00:40,430\n\n\n7\n00:00:40,430 --> 00:00:44,080\nI suppose, as I said, we were\nmotivated by physical systems\n\n8\n00:00:44,080 --> 00:00:47,200\nand the ways we like to think\nabout physical systems, which\n\n9\n00:00:47,200 --> 00:00:52,060\nis that there are these things\nthat the world is made out of.\n\n10\n00:00:52,060 --> 00:00:55,570\nAnd each of these things has\nparticular independent local\n\n11\n00:00:55,570 --> 00:00:58,830\nstate, and therefore\nit is a thing.\n\n12\n00:00:58,830 --> 00:01:01,280\nThat's what makes it a thing.\n\n13\n00:01:01,280 --> 00:01:04,410\nAnd then we're going to say\nthat in the model in the\n\n14\n00:01:04,410 --> 00:01:07,900\nworld--we have a world and a\nmodel in our minds and in the\n\n15\n00:01:07,900 --> 00:01:10,940\ncomputer of that world.\n\n16\n00:01:10,940 --> 00:01:13,230\nAnd what I want to make is a\ncorrespondence between the\n\n17\n00:01:13,230 --> 00:01:15,980\nobjects in the world and the\nobjects in the computer, the\n\n18\n00:01:15,980 --> 00:01:18,140\nrelationships between the\nobjects in the world and the\n\n19\n00:01:18,140 --> 00:01:21,200\nrelationships between those same\nobj...--the model objects\n\n20\n00:01:21,200 --> 00:01:24,890\nin the computer, and the\nfunctions that relate things\n\n21\n00:01:24,890 --> 00:01:27,320\nin the world to the functions\nthat relate\n\n22\n00:01:27,320 --> 00:01:28,570\nthings in the computer.\n\n23\n00:01:28,570 --> 00:01:30,840\n\n\n24\n00:01:30,840 --> 00:01:34,740\nThis buys us modularity.\n\n25\n00:01:34,740 --> 00:01:37,786\nIf we really believe the world\nis like that, that it's made\n\n26\n00:01:37,786 --> 00:01:40,120\nout of these little pieces, and\nof course we could arrange\n\n27\n00:01:40,120 --> 00:01:43,085\nour world to be like that, we\ncould only model those things\n\n28\n00:01:43,085 --> 00:01:47,030\nthat are like that, then we can\ninherit the modularity in\n\n29\n00:01:47,030 --> 00:01:50,450\nthe world into our\nprogramming.\n\n30\n00:01:50,450 --> 00:01:53,150\nThat's why we would invent some\nof this object-oriented\n\n31\n00:01:53,150 --> 00:01:55,420\nprogramming.\n\n32\n00:01:55,420 --> 00:01:58,890\nWell, let's take the best\nkind of objects I know.\n\n33\n00:01:58,890 --> 00:02:03,160\nThey're completely--they're\ncompletely wonderful:\n\n34\n00:02:03,160 --> 00:02:10,270\nelectrical systems. Electrical\nsystems really are the\n\n35\n00:02:10,270 --> 00:02:14,220\nphysicist's best,\nbest objects.\n\n36\n00:02:14,220 --> 00:02:16,760\nYou see over here I have some\npiece of machinery.\n\n37\n00:02:16,760 --> 00:02:20,040\nRight here's a piece\nof machinery.\n\n38\n00:02:20,040 --> 00:02:24,270\nAnd it's got an electrical wire\nconnecting one part of\n\n39\n00:02:24,270 --> 00:02:27,190\nthe machinery with another\npart of the machinery.\n\n40\n00:02:27,190 --> 00:02:30,450\nAnd one of the wonderful\nproperties of the electrical\n\n41\n00:02:30,450 --> 00:02:34,610\nworld is that I can say this is\nan object, and this is an\n\n42\n00:02:34,610 --> 00:02:36,040\nobject, and they're--\n\n43\n00:02:36,040 --> 00:02:38,310\nthe connection between\nthem is clear.\n\n44\n00:02:38,310 --> 00:02:41,190\nIn principle, there is no\nconnection that I didn't\n\n45\n00:02:41,190 --> 00:02:44,740\ndescribe with these wires.\n\n46\n00:02:44,740 --> 00:02:48,000\nLet's say if I have light bulbs,\na light bulb and a\n\n47\n00:02:48,000 --> 00:02:51,370\npower supply that's plugged\ninto the outlet.\n\n48\n00:02:51,370 --> 00:02:53,620\nThen the connection is\nperfectly clear.\n\n49\n00:02:53,620 --> 00:02:56,220\nThere's no other connections\nthat we know of.\n\n50\n00:02:56,220 --> 00:02:59,250\nIf I were to tie a knot in the\nwire that connects the light\n\n51\n00:02:59,250 --> 00:03:04,040\nbulb to the power supply, the\nlight remains lit up.\n\n52\n00:03:04,040 --> 00:03:05,290\nIt doesn't care.\n\n53\n00:03:05,290 --> 00:03:08,300\n\n\n54\n00:03:08,300 --> 00:03:11,120\nThat the way the physics is\narranged is such that the\n\n55\n00:03:11,120 --> 00:03:13,790\nconnection can be made abstract,\nat least for low\n\n56\n00:03:13,790 --> 00:03:15,270\nfrequencies and things\nlike that.\n\n57\n00:03:15,270 --> 00:03:17,840\n\n\n58\n00:03:17,840 --> 00:03:20,360\nSo in fact, we have captured all\nof the connections there\n\n59\n00:03:20,360 --> 00:03:22,350\nreally are.\n\n60\n00:03:22,350 --> 00:03:24,310\nWell, as you can go one step\nfurther and talk about the\n\n61\n00:03:24,310 --> 00:03:27,830\nmost abstract types of\nelectrical systems we have,\n\n62\n00:03:27,830 --> 00:03:30,951\ndigital to dual circuits.\n\n63\n00:03:30,951 --> 00:03:34,610\nAnd here there are certain\nkinds of objects.\n\n64\n00:03:34,610 --> 00:03:38,240\nFor example, in digital\ncircuits we\n\n65\n00:03:38,240 --> 00:03:41,092\nhave things like inverters.\n\n66\n00:03:41,092 --> 00:03:43,990\nWe have things like and-gates.\n\n67\n00:03:43,990 --> 00:03:47,210\nWe have things like or-gates.\n\n68\n00:03:47,210 --> 00:03:53,980\nWe connect them together by\nsort-of wires which represent\n\n69\n00:03:53,980 --> 00:03:55,610\nabstract signals.\n\n70\n00:03:55,610 --> 00:03:57,390\nWe don't really care as physical\nvariables whether\n\n71\n00:03:57,390 --> 00:04:00,190\nthese are voltages or currents\nor some combination or\n\n72\n00:04:00,190 --> 00:04:05,160\nanything like that, or water,\nwater pressure.\n\n73\n00:04:05,160 --> 00:04:09,420\nThese abstract variables\nrepresent certain signals.\n\n74\n00:04:09,420 --> 00:04:11,950\nAnd we build systems by\nwiring these things\n\n75\n00:04:11,950 --> 00:04:14,070\ntogether with wires.\n\n76\n00:04:14,070 --> 00:04:17,730\nSo today what I'm going to show\nyou, right now, we're\n\n77\n00:04:17,730 --> 00:04:22,650\ngoing to build up an invented\nlanguage in Lisp, embedded in\n\n78\n00:04:22,650 --> 00:04:24,590\nthe same sense that Henderson's\npicture language\n\n79\n00:04:24,590 --> 00:04:29,780\nwas embedded, which is not the\nsame sense as the language of\n\n80\n00:04:29,780 --> 00:04:32,700\npattern match and substitution\nwas done yesterday.\n\n81\n00:04:32,700 --> 00:04:35,725\nThe pattern match/substitution\nlanguage was interpreted by a\n\n82\n00:04:35,725 --> 00:04:38,160\nLisp program.\n\n83\n00:04:38,160 --> 00:04:40,920\nBut the embedding of Henderson's\nprogram is that we\n\n84\n00:04:40,920 --> 00:04:43,370\njust build up more and more\nprocedures that encapsulate\n\n85\n00:04:43,370 --> 00:04:45,480\nthe structure we want.\n\n86\n00:04:45,480 --> 00:04:49,280\nSo for example here, I'm going\nto have some various primitive\n\n87\n00:04:49,280 --> 00:04:53,026\nkinds of objects, as you see,\nthat one and that one.\n\n88\n00:04:53,026 --> 00:04:55,810\nI'm going to use wires\nto combine them.\n\n89\n00:04:55,810 --> 00:04:58,420\nThe way I represent\nattaching--\n\n90\n00:04:58,420 --> 00:04:59,870\nI can make wires.\n\n91\n00:04:59,870 --> 00:05:01,740\nSo let's say A is a wire.\n\n92\n00:05:01,740 --> 00:05:02,690\nAnd B is a wire.\n\n93\n00:05:02,690 --> 00:05:03,460\nAnd C is a wire.\n\n94\n00:05:03,460 --> 00:05:04,230\nAnd D is a wire.\n\n95\n00:05:04,230 --> 00:05:04,830\nAnd E is wire.\n\n96\n00:05:04,830 --> 00:05:06,880\nAnd S is a wire.\n\n97\n00:05:06,880 --> 00:05:12,380\nWell, an or-gate that has both\ninputs, the inputs being A and\n\n98\n00:05:12,380 --> 00:05:17,940\nB, and the output being Y or\nD, you notate like this.\n\n99\n00:05:17,940 --> 00:05:22,390\nAn and-gate, which has inputs\nA and B and output C, we\n\n100\n00:05:22,390 --> 00:05:24,820\nnotate like that.\n\n101\n00:05:24,820 --> 00:05:29,690\nBy making such a sequence of\ndeclarations, like this, I can\n\n102\n00:05:29,690 --> 00:05:32,750\nwire together an arbitrary\ncircuit.\n\n103\n00:05:32,750 --> 00:05:35,940\nSo I've just told you a set\nof primitives and means of\n\n104\n00:05:35,940 --> 00:05:40,930\ncombination for building digital\ncircuits, when I need\n\n105\n00:05:40,930 --> 00:05:43,690\nmore in a real language\nthan abstraction.\n\n106\n00:05:43,690 --> 00:05:46,766\nAnd so for example,\nhere I have--here\n\n107\n00:05:46,766 --> 00:05:52,240\nI have a half adder.\n\n108\n00:05:52,240 --> 00:05:54,270\nIt's something you all\nknow if you've\n\n109\n00:05:54,270 --> 00:05:56,930\ndone any digital design.\n\n110\n00:05:56,930 --> 00:06:00,830\nIt's used for adding numbers\ntogether on A and B and\n\n111\n00:06:00,830 --> 00:06:03,956\nputting out a sum and a carry.\n\n112\n00:06:03,956 --> 00:06:05,710\nAnd in fact, the wiring\ndiagram is\n\n113\n00:06:05,710 --> 00:06:07,450\nexactly what I told you.\n\n114\n00:06:07,450 --> 00:06:11,410\nA half adder with things that\ncome out of the box-- you see\n\n115\n00:06:11,410 --> 00:06:14,790\nthe box, the boundary, the\nabstraction is always a box.\n\n116\n00:06:14,790 --> 00:06:19,700\nAnd there are things that come\nout of it, A, B, S, and C.\n\n117\n00:06:19,700 --> 00:06:24,950\nThose are the declared\nvariables--declared variables\n\n118\n00:06:24,950 --> 00:06:27,020\nof a lambda expression,\nwhich is the one that\n\n119\n00:06:27,020 --> 00:06:28,270\ndefines half adder.\n\n120\n00:06:28,270 --> 00:06:31,400\n\n\n121\n00:06:31,400 --> 00:06:36,080\nAnd internal to that, I make up\nsome more wires, D and E,\n\n122\n00:06:36,080 --> 00:06:37,760\nwhich I'm going to use for\nthe interconnect--\n\n123\n00:06:37,760 --> 00:06:41,860\nhere E is this one and D is this\nwire, the interconnect\n\n124\n00:06:41,860 --> 00:06:45,100\nthat doesn't come through\nthe walls of the box--\n\n125\n00:06:45,100 --> 00:06:48,790\nand wire things together\nas you just saw.\n\n126\n00:06:48,790 --> 00:06:51,180\nAnd the nice thing about this\nthat I've just shown you is\n\n127\n00:06:51,180 --> 00:06:53,890\nthis language is hierarchical\nin the right way.\n\n128\n00:06:53,890 --> 00:06:55,950\nIf a language isn't hierarchical\nin the right way,\n\n129\n00:06:55,950 --> 00:06:58,850\nif it turns out that a compound\nobject doesn't look\n\n130\n00:06:58,850 --> 00:07:00,820\nlike a primitive, there's\nsomething\n\n131\n00:07:00,820 --> 00:07:02,180\nwrong with the language--\n\n132\n00:07:02,180 --> 00:07:06,300\nat least the way I\nfeel about that.\n\n133\n00:07:06,300 --> 00:07:09,220\nSo here we have--here, instead\nof starting with mathematical\n\n134\n00:07:09,220 --> 00:07:10,900\nfunctions, or things that\ncompute mathematical\n\n135\n00:07:10,900 --> 00:07:13,870\nfunctions, which is what we've\nbeen doing up until now,\n\n136\n00:07:13,870 --> 00:07:15,770\ninstead of starting with\nthings that look like\n\n137\n00:07:15,770 --> 00:07:18,080\nmathematical functions, or\ncompute such things, we are\n\n138\n00:07:18,080 --> 00:07:21,330\nstarting with things that are\nelectrical objects and we\n\n139\n00:07:21,330 --> 00:07:23,350\nbuild up more electrical\nobjects.\n\n140\n00:07:23,350 --> 00:07:26,590\nAnd the glue we're using\nis basically the\n\n141\n00:07:26,590 --> 00:07:30,500\nLisp structure: lambdas.\n\n142\n00:07:30,500 --> 00:07:32,930\nLambda is the ultimate\nglue, if you will.\n\n143\n00:07:32,930 --> 00:07:39,000\nAnd of course, half adder itself\ncan be used in a more\n\n144\n00:07:39,000 --> 00:07:42,250\ncomplicated abstraction called\na full adder, which in fact\n\n145\n00:07:42,250 --> 00:07:46,670\ninvolves two half adders, as you\nsee here, hooked together\n\n146\n00:07:46,670 --> 00:07:50,600\nwith some extra wires, that you\nsee here, S, C1, and C2,\n\n147\n00:07:50,600 --> 00:07:57,340\nand an or-gate, to manufacture\na full adder, which takes a\n\n148\n00:07:57,340 --> 00:08:01,570\ninput number, another input\nnumber, a carry in, and\n\n149\n00:08:01,570 --> 00:08:05,900\nproduces output, a sum\nand a carry out.\n\n150\n00:08:05,900 --> 00:08:09,820\nAnd out of full adders, you can\nmake real adder chains and\n\n151\n00:08:09,820 --> 00:08:12,990\nbig adders.\n\n152\n00:08:12,990 --> 00:08:18,870\nSo we have here a language so\nfar that has primitives, means\n\n153\n00:08:18,870 --> 00:08:22,270\nof combination, and means of\nabstraction to real language.\n\n154\n00:08:22,270 --> 00:08:25,000\nNow, how are we going\nto implement this?\n\n155\n00:08:25,000 --> 00:08:27,070\nWell, let's do it easily.\n\n156\n00:08:27,070 --> 00:08:28,610\nLet's look at the primitives.\n\n157\n00:08:28,610 --> 00:08:31,160\nThe only problem is we have to\nimplement the primitives.\n\n158\n00:08:31,160 --> 00:08:34,270\nNothing else has to be\nimplemented, because we're\n\n159\n00:08:34,270 --> 00:08:37,640\npicking up the means of\ncombination and abstraction\n\n160\n00:08:37,640 --> 00:08:43,417\nfrom Lisp, inheriting them\nin the embedding.\n\n161\n00:08:43,417 --> 00:08:45,860\nOK, so let's look at a\nparticular primitive.\n\n162\n00:08:45,860 --> 00:08:47,400\nAn inverter is a nice one.\n\n163\n00:08:47,400 --> 00:08:51,540\n\n\n164\n00:08:51,540 --> 00:08:54,900\nNow, inverter has two wires\ncoming in, an in and an out.\n\n165\n00:08:54,900 --> 00:08:57,440\n\n\n166\n00:08:57,440 --> 00:09:01,570\nAnd somehow, it's going to have\nto know what to do when a\n\n167\n00:09:01,570 --> 00:09:04,300\nsignal comes in.\n\n168\n00:09:04,300 --> 00:09:07,710\nSo somehow it's going to have\nto tell its input wire--\n\n169\n00:09:07,710 --> 00:09:10,756\nand now we're going to talk\nabout objects and we're going\n\n170\n00:09:10,756 --> 00:09:13,260\nto see this in a little\nmore detail soon--\n\n171\n00:09:13,260 --> 00:09:16,660\nbut it's going to have to tell\nits input wire that when you\n\n172\n00:09:16,660 --> 00:09:20,120\nchange, tell me.\n\n173\n00:09:20,120 --> 00:09:22,720\nSo this object, the object which\nis the inverter has to\n\n174\n00:09:22,720 --> 00:09:25,070\ntell the object which\nis the input wire,\n\n175\n00:09:25,070 --> 00:09:26,870\nhi, my name is George.\n\n176\n00:09:26,870 --> 00:09:30,480\nAnd my, my job is to do\nsomething with results when\n\n177\n00:09:30,480 --> 00:09:31,720\nyou change.\n\n178\n00:09:31,720 --> 00:09:34,730\nSo when you change, you get a\nchange, tell me about it.\n\n179\n00:09:34,730 --> 00:09:37,010\nBecause I've got to do\nsomething with that.\n\n180\n00:09:37,010 --> 00:09:42,200\nWell, that's done down here by\nadding an action on the input\n\n181\n00:09:42,200 --> 00:09:47,020\nwire called invert-in, where\ninvert-in is defined over here\n\n182\n00:09:47,020 --> 00:09:51,660\nto be a procedure of no\narguments, which gets the\n\n183\n00:09:51,660 --> 00:09:56,130\nlogical not of the signal\non the input wire.\n\n184\n00:09:56,130 --> 00:09:59,720\nAnd after some delay, which is\nthe inverter delay, all these\n\n185\n00:09:59,720 --> 00:10:04,110\nelectrical objects have delays,\nwe'll do the following\n\n186\n00:10:04,110 --> 00:10:07,140\nthing-- set the signal on the\noutput wire to the new value.\n\n187\n00:10:07,140 --> 00:10:10,160\n\n\n188\n00:10:10,160 --> 00:10:12,400\nA very simple program.\n\n189\n00:10:12,400 --> 00:10:14,820\nNow, you have to imagine that\nthe output wire has to be\n\n190\n00:10:14,820 --> 00:10:19,650\nsensitive and know that when\nits signal changes, it may\n\n191\n00:10:19,650 --> 00:10:23,840\nhave to tell other guys,\nhey, wake up.\n\n192\n00:10:23,840 --> 00:10:26,050\nMy value has changed.\n\n193\n00:10:26,050 --> 00:10:29,350\nSo when you hook together\ninverter with an and-gate or\n\n194\n00:10:29,350 --> 00:10:31,680\nsomething like that, there has\nto be a lot of communication\n\n195\n00:10:31,680 --> 00:10:34,040\ngoing on in order to\nmake sure that the\n\n196\n00:10:34,040 --> 00:10:36,810\nsignal propagates right.\n\n197\n00:10:36,810 --> 00:10:38,620\nAnd down here is nothing\nvery exciting.\n\n198\n00:10:38,620 --> 00:10:41,100\nThis is just the definition\nof logical not for some\n\n199\n00:10:41,100 --> 00:10:44,170\nparticular representations\nof the logical values--\n\n200\n00:10:44,170 --> 00:10:46,240\n1, 0 in this case.\n\n201\n00:10:46,240 --> 00:10:49,780\nAnd we can look at things more\ncomplicated like and-gates.\n\n202\n00:10:49,780 --> 00:10:55,000\nAnd-gates take two inputs, A1\nand A2, we'll call them, and\n\n203\n00:10:55,000 --> 00:10:56,950\nproduce an output.\n\n204\n00:10:56,950 --> 00:10:59,840\nBut the structure of the\nand-gate is identical to the\n\n205\n00:10:59,840 --> 00:11:00,860\none we just saw.\n\n206\n00:11:00,860 --> 00:11:03,000\nThere's one called an and-action\nprocedure that's\n\n207\n00:11:03,000 --> 00:11:08,570\ndefined, which is the thing that\ngets called when an input\n\n208\n00:11:08,570 --> 00:11:10,910\nis changed.\n\n209\n00:11:10,910 --> 00:11:13,230\nAnd what it does, of course, is\nnothing more than compute\n\n210\n00:11:13,230 --> 00:11:15,900\nthe logical and of the signals\non the inputs.\n\n211\n00:11:15,900 --> 00:11:20,890\nAnd after some delay, called the\nand-gate delay, calls this\n\n212\n00:11:20,890 --> 00:11:25,470\nprocedure, which sets a signal\non the output to a new value.\n\n213\n00:11:25,470 --> 00:11:27,320\nNow, how I implement\nthese things\n\n214\n00:11:27,320 --> 00:11:28,350\nis all wishful thinking.\n\n215\n00:11:28,350 --> 00:11:32,020\nAs you see here, I have an\nassignment operation.\n\n216\n00:11:32,020 --> 00:11:34,570\nIt's not set.\n\n217\n00:11:34,570 --> 00:11:36,820\nIt's a derived assignment\noperation in the same way we\n\n218\n00:11:36,820 --> 00:11:41,140\nhad functions that were derived\nfrom CAR and CDR. So\n\n219\n00:11:41,140 --> 00:11:46,340\nI, by convention, label that\nwith an exclamation point.\n\n220\n00:11:46,340 --> 00:11:50,730\nAnd over here, you see there's\nan action, which is to inform\n\n221\n00:11:50,730 --> 00:11:57,190\nthe wire, called A1 locally in\nthis and-gate, to call the\n\n222\n00:11:57,190 --> 00:12:00,960\nand-action procedure when it\ngets changed, and the wire A2\n\n223\n00:12:00,960 --> 00:12:02,100\nto call the and-action\nprocedure\n\n224\n00:12:02,100 --> 00:12:03,350\nwhen it gets changed.\n\n225\n00:12:03,350 --> 00:12:06,310\n\n\n226\n00:12:06,310 --> 00:12:09,510\nAll very simple.\n\n227\n00:12:09,510 --> 00:12:12,870\nWell, let's talk a little bit\nabout this communication that\n\n228\n00:12:12,870 --> 00:12:18,310\nmust occur between these\nvarious parts.\n\n229\n00:12:18,310 --> 00:12:24,560\nSuppose, for example, I have\na very simple circuit which\n\n230\n00:12:24,560 --> 00:12:34,230\ncontains an and with wires A\nand B. And that connects\n\n231\n00:12:34,230 --> 00:12:40,580\nthrough a wire called C to an\ninverter which has a wire\n\n232\n00:12:40,580 --> 00:12:46,310\noutput called D. What are\nthe comput...--here's\n\n233\n00:12:46,310 --> 00:12:47,360\nthe physical world.\n\n234\n00:12:47,360 --> 00:12:49,860\nIt's an abstraction of\nthe physical world.\n\n235\n00:12:49,860 --> 00:12:52,010\nNow I can buy these out of\nlittle pieces that you get at\n\n236\n00:12:52,010 --> 00:12:54,880\nRadio Shack for a few cents.\n\n237\n00:12:54,880 --> 00:12:57,680\nAnd there are boxes that act\nlike this, which have little\n\n238\n00:12:57,680 --> 00:13:01,530\nnumbers on them like\nLS04 or something.\n\n239\n00:13:01,530 --> 00:13:06,980\nNow supposing I were to\ntry to say what's the\n\n240\n00:13:06,980 --> 00:13:09,010\ncomputational model.\n\n241\n00:13:09,010 --> 00:13:11,610\nWhat is the thing that\ncorresponds to that, that part\n\n242\n00:13:11,610 --> 00:13:15,850\nof reality in the mind of\nus and in the computer?\n\n243\n00:13:15,850 --> 00:13:18,200\nWell, I have to assign for every\nobject in the world an\n\n244\n00:13:18,200 --> 00:13:22,160\nobject in the computer, and for\nevery relationship in the\n\n245\n00:13:22,160 --> 00:13:25,750\nworld between them a\nrelationship in the computer.\n\n246\n00:13:25,750 --> 00:13:28,560\nThat's my goal.\n\n247\n00:13:28,560 --> 00:13:30,900\nSo let's do that.\n\n248\n00:13:30,900 --> 00:13:35,401\nWell, I have some sort of thing\ncalled the signal, A.\n\n249\n00:13:35,401 --> 00:13:37,940\nThis is A. It's a signal.\n\n250\n00:13:37,940 --> 00:13:39,900\nIt's a cloudy thing like that.\n\n251\n00:13:39,900 --> 00:13:42,390\nAnd I have another one down here\nwhich I'm going to call\n\n252\n00:13:42,390 --> 00:13:49,140\nB. It's another signal.\n\n253\n00:13:49,140 --> 00:13:52,070\nNow this signal--these two\nsignals are somehow going to\n\n254\n00:13:52,070 --> 00:13:56,180\nhave to hook together into a\nbox, let's call it this, which\n\n255\n00:13:56,180 --> 00:14:00,320\nis the and-gate, action\nprocedure.\n\n256\n00:14:00,320 --> 00:14:02,040\nThat's the and-gate's\naction procedure.\n\n257\n00:14:02,040 --> 00:14:07,660\n\n\n258\n00:14:07,660 --> 00:14:09,750\nAnd it's going to produce--well,\nit's going to\n\n259\n00:14:09,750 --> 00:14:18,360\ninteract with a signal object,\nwhich we call C--a wire\n\n260\n00:14:18,360 --> 00:14:21,330\nobject, excuse me, we call\nC. And then the--\n\n261\n00:14:21,330 --> 00:14:25,630\nthis is going to put out again,\nor connect to, another\n\n262\n00:14:25,630 --> 00:14:28,240\naction procedure which is one\nassociated with the inverter\n\n263\n00:14:28,240 --> 00:14:30,195\nin the world, not.\n\n264\n00:14:30,195 --> 00:14:32,860\n\n\n265\n00:14:32,860 --> 00:14:39,980\nAnd I'm going to have\nanother--another wire, which\n\n266\n00:14:39,980 --> 00:14:42,970\nwe'll call D.\n\n267\n00:14:42,970 --> 00:14:45,770\nSo here's my layout of stuff.\n\n268\n00:14:45,770 --> 00:14:47,650\nNow we have to say what's inside\nthem and what they have\n\n269\n00:14:47,650 --> 00:14:51,500\nto know to compute.\n\n270\n00:14:51,500 --> 00:14:53,900\nWell, every--every one of these\nwires has to know what\n\n271\n00:14:53,900 --> 00:14:57,340\nthe value of the signal that's\non that wire is.\n\n272\n00:14:57,340 --> 00:14:59,430\nSo there's going to be some\nvariable inside here, we'll\n\n273\n00:14:59,430 --> 00:15:00,680\ncall it signal.\n\n274\n00:15:00,680 --> 00:15:02,670\n\n\n275\n00:15:02,670 --> 00:15:05,840\nAnd he owns a value.\n\n276\n00:15:05,840 --> 00:15:06,870\nSo there must be some\nenvironment\n\n277\n00:15:06,870 --> 00:15:08,656\nassociated with this.\n\n278\n00:15:08,656 --> 00:15:10,550\nAnd for each one of these, there\nmust be an environment\n\n279\n00:15:10,550 --> 00:15:11,800\nthat binds signal.\n\n280\n00:15:11,800 --> 00:15:15,400\n\n\n281\n00:15:15,400 --> 00:15:16,880\nAnd there must be a signal\nhere, therefore.\n\n282\n00:15:16,880 --> 00:15:19,400\n\n\n283\n00:15:19,400 --> 00:15:22,920\nAnd presumably, signal's a value\nthat's either 1 or 0,\n\n284\n00:15:22,920 --> 00:15:24,170\nand signal.\n\n285\n00:15:24,170 --> 00:15:28,000\n\n\n286\n00:15:28,000 --> 00:15:33,140\nNow, we also have to have some\nlist of people to inform if\n\n287\n00:15:33,140 --> 00:15:34,390\nthe signal here changes.\n\n288\n00:15:34,390 --> 00:15:36,660\n\n\n289\n00:15:36,660 --> 00:15:39,300\nWe're going to have\nto inform this.\n\n290\n00:15:39,300 --> 00:15:41,470\nSo I've got that list.\nWe'll call it the\n\n291\n00:15:41,470 --> 00:15:44,500\nAction Procedures, AP.\n\n292\n00:15:44,500 --> 00:15:47,590\nAnd it's presumably a list.\nBut the first thing on the\n\n293\n00:15:47,590 --> 00:15:50,500\nlist, in this case,\nis this guy.\n\n294\n00:15:50,500 --> 00:15:53,730\nAnd the action procedures of\nthis one happens to have some\n\n295\n00:15:53,730 --> 00:15:54,810\nlist of stuff.\n\n296\n00:15:54,810 --> 00:15:57,510\nThere might be other people\nwho are sharing A, who are\n\n297\n00:15:57,510 --> 00:15:59,020\nlooking at it.\n\n298\n00:15:59,020 --> 00:16:02,060\nSo there might be other guys\non this list, like somebody\n\n299\n00:16:02,060 --> 00:16:03,630\nover there that we\ndon't know about.\n\n300\n00:16:03,630 --> 00:16:07,200\nIt's the other guy\nattached to A.\n\n301\n00:16:07,200 --> 00:16:11,230\nAnd the action procedure here\nalso has to point to that, the\n\n302\n00:16:11,230 --> 00:16:13,070\nlist of action procedures.\n\n303\n00:16:13,070 --> 00:16:17,060\nAnd of course, that means this\none, its action procedures has\n\n304\n00:16:17,060 --> 00:16:18,530\nto point up to here.\n\n305\n00:16:18,530 --> 00:16:18,770\nThis is the things--\n\n306\n00:16:18,770 --> 00:16:21,770\nthe people it has to inform.\n\n307\n00:16:21,770 --> 00:16:24,280\nAnd this guy has some too.\n\n308\n00:16:24,280 --> 00:16:25,660\nBut I don't know what they\nare because I didn't\n\n309\n00:16:25,660 --> 00:16:27,190\ndraw it in my diagram.\n\n310\n00:16:27,190 --> 00:16:30,320\nIt's the things connected\nto D.\n\n311\n00:16:30,320 --> 00:16:36,240\nNow, it's also the case that\nwhen the and-action procedure\n\n312\n00:16:36,240 --> 00:16:41,951\nis awakened, saying one of the\npeople who know that you've\n\n313\n00:16:41,951 --> 00:16:44,010\ntold--one of the people you've\ntold to wake you up if their\n\n314\n00:16:44,010 --> 00:16:48,430\nsignal changes, you have to go\nlook and ask them what's their\n\n315\n00:16:48,430 --> 00:16:51,540\nsignal so you can do the\nand, and produce a\n\n316\n00:16:51,540 --> 00:16:52,790\nsignal for this one.\n\n317\n00:16:52,790 --> 00:16:57,090\n\n\n318\n00:16:57,090 --> 00:16:59,760\nSo there has to be, for example,\ninformation here\n\n319\n00:16:59,760 --> 00:17:06,400\nsaying A1, my A1 is this guy,\nand my A2 is this guy.\n\n320\n00:17:06,400 --> 00:17:08,930\n\n\n321\n00:17:08,930 --> 00:17:14,170\nAnd not only that, when I do my\nand, I'm going to have to\n\n322\n00:17:14,170 --> 00:17:16,170\ntell this guy something.\n\n323\n00:17:16,170 --> 00:17:17,420\nSo I need an output--\n\n324\n00:17:17,420 --> 00:17:19,904\n\n\n325\n00:17:19,904 --> 00:17:21,160\nbeing this guy.\n\n326\n00:17:21,160 --> 00:17:25,800\n\n\n327\n00:17:25,800 --> 00:17:29,550\nAnd similarly, this guy's going\nto have a thing called\n\n328\n00:17:29,550 --> 00:17:37,540\nthe input that he interrogates\nto find out what the value of\n\n329\n00:17:37,540 --> 00:17:39,430\nthe signal on the input is, when\nthe signal wakes up and\n\n330\n00:17:39,430 --> 00:17:42,980\nsays, I've changed, and sends\na message this way saying,\n\n331\n00:17:42,980 --> 00:17:43,520\nI've changed.\n\n332\n00:17:43,520 --> 00:17:46,900\nThis guy says, OK, what's\nyour value now?\n\n333\n00:17:46,900 --> 00:17:50,840\nWhen he gets that value, then\nhe's going to have to say, OK,\n\n334\n00:17:50,840 --> 00:17:55,860\noutput changes this guy,\nchanges this guy.\n\n335\n00:17:55,860 --> 00:18:00,600\n\n\n336\n00:18:00,600 --> 00:18:02,481\nAnd so on.\n\n337\n00:18:02,481 --> 00:18:06,240\nAnd so I have to have at least\nthat much connected-ness.\n\n338\n00:18:06,240 --> 00:18:10,260\nNow, let's go back and look, for\nexample, at the and-gate.\n\n339\n00:18:10,260 --> 00:18:13,670\nHere we are back\non this slide.\n\n340\n00:18:13,670 --> 00:18:16,040\nAnd we can see some\nof these parts.\n\n341\n00:18:16,040 --> 00:18:18,470\nFor any particular and-gate,\nthere is an A1, there is an\n\n342\n00:18:18,470 --> 00:18:21,030\nA2, and the output.\n\n343\n00:18:21,030 --> 00:18:21,483\nAnd those are, those are an\nenvironment that was created\n\n344\n00:18:21,483 --> 00:18:30,720\nat the--those produce a frame\nat the time and-gate was\n\n345\n00:18:30,720 --> 00:18:37,200\ncalled, a frame where A1, A2,\nand output are--have as their\n\n346\n00:18:37,200 --> 00:18:41,940\nvalues, they're bound to the\nwires which, they are--which\n\n347\n00:18:41,940 --> 00:18:46,240\nwere passed in.\n\n348\n00:18:46,240 --> 00:18:50,890\nIn that environment, I\nconstructed a procedure--\n\n349\n00:18:50,890 --> 00:18:54,590\nthis one right there.\n\n350\n00:18:54,590 --> 00:18:56,810\nAnd-action procedure was\nconstructed in that\n\n351\n00:18:56,810 --> 00:18:57,780\nenvironment.\n\n352\n00:18:57,780 --> 00:19:00,190\nThat was the result of\nevaluating a lambda\n\n353\n00:19:00,190 --> 00:19:01,620\nexpression.\n\n354\n00:19:01,620 --> 00:19:07,620\nSo it hangs onto the frame\nwhere these were defined.\n\n355\n00:19:07,620 --> 00:19:11,700\nLocal--part of its local\nstate is that.\n\n356\n00:19:11,700 --> 00:19:15,000\nThe and-action procedure,\ntherefore, has access to A1,\n\n357\n00:19:15,000 --> 00:19:17,310\nA2, and output as we see here.\n\n358\n00:19:17,310 --> 00:19:19,645\nA1, A2, and output.\n\n359\n00:19:19,645 --> 00:19:22,360\n\n\n360\n00:19:22,360 --> 00:19:26,030\nNow, we haven't looked\ninside of a wire yet.\n\n361\n00:19:26,030 --> 00:19:29,030\nThat's all that remains.\n\n362\n00:19:29,030 --> 00:19:30,280\nLet's look at a wire.\n\n363\n00:19:30,280 --> 00:19:33,520\n\n\n364\n00:19:33,520 --> 00:19:36,160\nLike the overhead, very good.\n\n365\n00:19:36,160 --> 00:19:39,500\n\n\n366\n00:19:39,500 --> 00:19:40,940\nWell, the wire, again,\nis a, is a\n\n367\n00:19:40,940 --> 00:19:43,090\nsomewhat complicated mess.\n\n368\n00:19:43,090 --> 00:19:46,840\nOoh, wrong one.\n\n369\n00:19:46,840 --> 00:19:49,780\nIt's a big complicated\nmess, like that.\n\n370\n00:19:49,780 --> 00:19:54,720\nBut let's look at it in detail\nand see what's going on.\n\n371\n00:19:54,720 --> 00:19:57,760\nWell, the wire is\none of these.\n\n372\n00:19:57,760 --> 00:20:02,320\nAnd it has to have two things\nthat are part of\n\n373\n00:20:02,320 --> 00:20:05,010\nit, that it's state.\n\n374\n00:20:05,010 --> 00:20:07,390\nOne of them is the signal\nwe see here.\n\n375\n00:20:07,390 --> 00:20:10,670\nIn other words, when we call\nmake-wire to make a wire, then\n\n376\n00:20:10,670 --> 00:20:15,300\nthe first thing we do is we\ncreate some variables which\n\n377\n00:20:15,300 --> 00:20:19,270\nare the signal and the action\nprocedures for this wire.\n\n378\n00:20:19,270 --> 00:20:22,042\n\n\n379\n00:20:22,042 --> 00:20:26,540\nAnd in that context, we define\nvarious functions--or\n\n380\n00:20:26,540 --> 00:20:27,840\nprocedures, excuse\nme, procedures.\n\n381\n00:20:27,840 --> 00:20:32,850\nOne of them is called\nset-my-signal to a new value.\n\n382\n00:20:32,850 --> 00:20:37,930\nAnd what that does is takes\na new value in.\n\n383\n00:20:37,930 --> 00:20:40,360\nIf that's equal to my current\nvalue of my signal, I'm done.\n\n384\n00:20:40,360 --> 00:20:43,460\nOtherwise, I set the signal to\nthe new value and call each of\n\n385\n00:20:43,460 --> 00:20:47,081\nthe action procedures that\nI've been, that I've\n\n386\n00:20:47,081 --> 00:20:48,331\nbeen--what's the right word?--\n\n387\n00:20:48,331 --> 00:20:51,700\n\n\n388\n00:20:51,700 --> 00:20:54,630\nintroduced to.\n\n389\n00:20:54,630 --> 00:21:01,530\nI get introduced when the\nand-gate was applied to me.\n\n390\n00:21:01,530 --> 00:21:04,130\n\n\n391\n00:21:04,130 --> 00:21:07,410\nI add action procedure\nat the bottom.\n\n392\n00:21:07,410 --> 00:21:10,440\nAlso, I have to define a way\nof accepting an action\n\n393\n00:21:10,440 --> 00:21:12,780\nprocedure-- which is what\nyou see here---\n\n394\n00:21:12,780 --> 00:21:18,530\nwhich increments my action\nprocedures using set to the\n\n395\n00:21:18,530 --> 00:21:22,060\nresult of CONSing up a new\nprocess--a procedure, which is\n\n396\n00:21:22,060 --> 00:21:25,760\npassed to me, on to my actions\nprocedures list. And for\n\n397\n00:21:25,760 --> 00:21:27,780\ntechnical reasons, I have to\ncall that procedure one.\n\n398\n00:21:27,780 --> 00:21:29,660\nSo I'm not going to tell you\nanything about that, that has\n\n399\n00:21:29,660 --> 00:21:32,610\nto do with event-driven\nsimulations and getting them\n\n400\n00:21:32,610 --> 00:21:36,950\nstarted, which takes a little\nbit of thinking.\n\n401\n00:21:36,950 --> 00:21:38,690\nAnd finally, I'm going to define\na thing called the\n\n402\n00:21:38,690 --> 00:21:45,390\ndispatcher, which is a way of\npassing a message to a wire,\n\n403\n00:21:45,390 --> 00:21:48,030\nwhich is going to be used to\nextract from it various\n\n404\n00:21:48,030 --> 00:21:53,820\ninformation, like what is the\ncurrent signal value?\n\n405\n00:21:53,820 --> 00:21:57,180\nWhat is the method of\nsetting your signal?\n\n406\n00:21:57,180 --> 00:22:00,100\nI want to get that out of it.\n\n407\n00:22:00,100 --> 00:22:02,600\nHow do I--how do I add another\naction procedure?\n\n408\n00:22:02,600 --> 00:22:05,510\n\n\n409\n00:22:05,510 --> 00:22:08,280\nAnd I'm going to return\nthat dispatch, that\n\n410\n00:22:08,280 --> 00:22:09,940\nprocedure as a value.\n\n411\n00:22:09,940 --> 00:22:12,610\nSo the wire that I've\nconstructed is a message\n\n412\n00:22:12,610 --> 00:22:16,710\naccepting object which accepts\na message like, like what's\n\n413\n00:22:16,710 --> 00:22:19,790\nyour method of adding\naction procedures?\n\n414\n00:22:19,790 --> 00:22:22,270\nIn fact, it'll give me a\nprocedure, which is the add\n\n415\n00:22:22,270 --> 00:22:26,020\naction procedure, which I can\nthen apply to an action\n\n416\n00:22:26,020 --> 00:22:29,010\nprocedure to create another\naction procedure in the wire.\n\n417\n00:22:29,010 --> 00:22:31,620\n\n\n418\n00:22:31,620 --> 00:22:32,820\nSo that's a permission.\n\n419\n00:22:32,820 --> 00:22:37,450\nSo it's given me permission to\nchange your action procedures.\n\n420\n00:22:37,450 --> 00:22:41,710\nAnd in fact, you can\nsee that over here.\n\n421\n00:22:41,710 --> 00:22:43,278\nNext slide.\n\n422\n00:22:43,278 --> 00:22:44,528\nAh.\n\n423\n00:22:44,528 --> 00:22:47,760\n\n\n424\n00:22:47,760 --> 00:22:49,120\nThis is nothing very\ninteresting.\n\n425\n00:22:49,120 --> 00:22:52,040\nThe call each of the action\nprocedures is just a CDRing\n\n426\n00:22:52,040 --> 00:22:53,500\ndown a list. And I'm\nnot going to even\n\n427\n00:22:53,500 --> 00:22:54,990\ntalk about that anymore.\n\n428\n00:22:54,990 --> 00:22:57,560\nWe're too advanced for that.\n\n429\n00:22:57,560 --> 00:23:00,280\nHowever, if I want to\nget a signal from a\n\n430\n00:23:00,280 --> 00:23:02,250\nwire, I ask the wire--\n\n431\n00:23:02,250 --> 00:23:03,090\nwhich is, what is the wire?\n\n432\n00:23:03,090 --> 00:23:05,860\nThe wire is the dispatch\nreturned by creating the wire.\n\n433\n00:23:05,860 --> 00:23:06,830\nIt's a procedure.\n\n434\n00:23:06,830 --> 00:23:12,590\nI call that dispatch on the\nmessage get-signal.\n\n435\n00:23:12,590 --> 00:23:14,770\nAnd what I should expect\nto get is a method\n\n436\n00:23:14,770 --> 00:23:16,900\nof getting a signal.\n\n437\n00:23:16,900 --> 00:23:19,220\nOr actually, I get the signal.\n\n438\n00:23:19,220 --> 00:23:25,800\nIf I want to set a signal, I\nwant to change a signal, then\n\n439\n00:23:25,800 --> 00:23:28,810\nwhat I'm going to do is take a\nwire as an argument and a new\n\n440\n00:23:28,810 --> 00:23:31,120\nvalue for the signal, I'm going\nto ask the wire for\n\n441\n00:23:31,120 --> 00:23:35,660\npermission to set its signal and\nuse that permission, which\n\n442\n00:23:35,660 --> 00:23:38,700\nis a procedure, on\nthe new value.\n\n443\n00:23:38,700 --> 00:23:44,156\nAnd if we go back to the\noverhead here, thank you, if\n\n444\n00:23:44,156 --> 00:23:46,880\nwe go back to the overhead here,\nwe see that the method--\n\n445\n00:23:46,880 --> 00:23:49,720\nif I ask for the method of\nsetting the signal, that's\n\n446\n00:23:49,720 --> 00:23:54,620\nover here, it's set-my-signal,\na procedure that's defined\n\n447\n00:23:54,620 --> 00:23:59,270\ninside the wire, which if we\nlook over here is the thing\n\n448\n00:23:59,270 --> 00:24:02,930\nthat says set my internal value\ncalled the signal, my\n\n449\n00:24:02,930 --> 00:24:08,640\ninternal variable, which is the\nsignal, to the new value,\n\n450\n00:24:08,640 --> 00:24:11,630\nwhich is passed to me as an\nargument, and then call each\n\n451\n00:24:11,630 --> 00:24:13,010\nof the action procedures\nwaking them up.\n\n452\n00:24:13,010 --> 00:24:16,340\n\n\n453\n00:24:16,340 --> 00:24:19,400\nVery simple.\n\n454\n00:24:19,400 --> 00:24:24,310\nGoing back to that slide, we\nalso have the one last thing--\n\n455\n00:24:24,310 --> 00:24:27,810\nwhich I suppose now you can\neasily work out for yourself--\n\n456\n00:24:27,810 --> 00:24:30,100\nis the way you add an action.\n\n457\n00:24:30,100 --> 00:24:36,470\nYou take a wire--a wire and\nan action procedure.\n\n458\n00:24:36,470 --> 00:24:40,050\nAnd I ask the wire for\npermission to add an action.\n\n459\n00:24:40,050 --> 00:24:43,210\nGetting that permission, I use\nthat permission to give it an\n\n460\n00:24:43,210 --> 00:24:45,020\naction procedure.\n\n461\n00:24:45,020 --> 00:24:48,570\nSo that's a real object.\n\n462\n00:24:48,570 --> 00:24:52,460\nThere's a few more details\nabout this.\n\n463\n00:24:52,460 --> 00:24:58,390\nFor example, how am I going\nto control this thing?\n\n464\n00:24:58,390 --> 00:25:01,290\nHow do I do these delays?\n\n465\n00:25:01,290 --> 00:25:02,540\nLet's look at that\nfor a second.\n\n466\n00:25:02,540 --> 00:25:05,275\n\n\n467\n00:25:05,275 --> 00:25:08,360\nThe next one here.\n\n468\n00:25:08,360 --> 00:25:09,570\nLet's see.\n\n469\n00:25:09,570 --> 00:25:15,450\nWe know when we looked at the\nand-gate or the not-gate that\n\n470\n00:25:15,450 --> 00:25:18,770\nwhen a signal changed on the\ninput, there was a delay.\n\n471\n00:25:18,770 --> 00:25:22,060\nAnd then it was going to call\nthe procedure, which was going\n\n472\n00:25:22,060 --> 00:25:23,310\nto change the output.\n\n473\n00:25:23,310 --> 00:25:26,040\n\n\n474\n00:25:26,040 --> 00:25:28,120\nWell, how are we going\nto do this?\n\n475\n00:25:28,120 --> 00:25:30,600\nWe're going to make up some\nmechanism, a fairly\n\n476\n00:25:30,600 --> 00:25:32,840\ncomplicated mechanism at that,\nwhich we're going to have to\n\n477\n00:25:32,840 --> 00:25:34,720\nbe very careful about.\n\n478\n00:25:34,720 --> 00:25:37,390\nBut after a delay, we're\ngoing to do an action.\n\n479\n00:25:37,390 --> 00:25:40,590\nA delay is a number, and an\naction is a procedure.\n\n480\n00:25:40,590 --> 00:25:41,970\nWhat that's going to be is\nthey're going to have a\n\n481\n00:25:41,970 --> 00:25:47,120\nspecial structure called an\nagenda, which is a thing that\n\n482\n00:25:47,120 --> 00:25:49,510\norganizes time and actions.\n\n483\n00:25:49,510 --> 00:25:50,880\nAnd we're going to see\nthat in a while.\n\n484\n00:25:50,880 --> 00:25:53,070\nI don't want to get into\nthat right now.\n\n485\n00:25:53,070 --> 00:25:55,745\nBut the agenda has a\nmoment at which--at\n\n486\n00:25:55,745 --> 00:25:59,130\nwhich something happens.\n\n487\n00:25:59,130 --> 00:26:03,120\nWe're setting up for later at\nsome moment, which is the sum\n\n488\n00:26:03,120 --> 00:26:05,400\nof the time, which is the delay\ntime plus the current\n\n489\n00:26:05,400 --> 00:26:08,460\ntime, which the agenda\nthinks is now.\n\n490\n00:26:08,460 --> 00:26:11,840\nWe're going to set up to do this\naction, and add that to\n\n491\n00:26:11,840 --> 00:26:13,090\nthe agenda.\n\n492\n00:26:13,090 --> 00:26:15,280\n\n\n493\n00:26:15,280 --> 00:26:18,660\nAnd the way this machine will\nnow run is very simple.\n\n494\n00:26:18,660 --> 00:26:20,800\nWe have a thing called\npropagate, which is the way\n\n495\n00:26:20,800 --> 00:26:22,710\nthings run.\n\n496\n00:26:22,710 --> 00:26:25,290\nIf the agenda is empty, we're\ndone--if there's nothing more\n\n497\n00:26:25,290 --> 00:26:27,440\nto be done.\n\n498\n00:26:27,440 --> 00:26:31,690\nOtherwise, we're going to take\nthe first item off the agenda,\n\n499\n00:26:31,690 --> 00:26:34,200\nand that's a procedure\nof no arguments.\n\n500\n00:26:34,200 --> 00:26:36,030\nSo that we're going to see\nextra parentheses here.\n\n501\n00:26:36,030 --> 00:26:39,190\nWe call that on no arguments.\n\n502\n00:26:39,190 --> 00:26:42,200\nThat takes the action.\n\n503\n00:26:42,200 --> 00:26:45,050\nThen we remove that first item\nfrom the agenda, and we go\n\n504\n00:26:45,050 --> 00:26:48,395\naround the propagation loop.\n\n505\n00:26:48,395 --> 00:26:50,750\nSo that's the overall structure\nof this thing.\n\n506\n00:26:50,750 --> 00:26:53,380\n\n\n507\n00:26:53,380 --> 00:26:57,430\nNow, there's a, a few other\nthings we can look at.\n\n508\n00:26:57,430 --> 00:26:59,160\nAnd then we're going to\nlook into the agenda a\n\n509\n00:26:59,160 --> 00:27:00,410\nlittle while from now.\n\n510\n00:27:00,410 --> 00:27:02,800\nNow the overhead again.\n\n511\n00:27:02,800 --> 00:27:04,980\nWell, in order to set this thing\ngoing, I just want to\n\n512\n00:27:04,980 --> 00:27:07,410\nshow you some behavior out\nof this simulator.\n\n513\n00:27:07,410 --> 00:27:10,610\nBy the way, you may think this\nsimulator is very simple, and\n\n514\n00:27:10,610 --> 00:27:12,370\nprobably too simple\nto be useful.\n\n515\n00:27:12,370 --> 00:27:15,730\nThe fact of the matter is that\nthis simulator has been used\n\n516\n00:27:15,730 --> 00:27:18,680\nto manufacture a fairly\nlarge computer.\n\n517\n00:27:18,680 --> 00:27:22,360\nSo this is a real\nlive example.\n\n518\n00:27:22,360 --> 00:27:24,790\nActually, not exactly this\nsimulator, because I'll tell\n\n519\n00:27:24,790 --> 00:27:25,560\nyou the difference.\n\n520\n00:27:25,560 --> 00:27:28,180\nThe difference is that there\nwere many more different kinds\n\n521\n00:27:28,180 --> 00:27:29,820\nof primitives.\n\n522\n00:27:29,820 --> 00:27:33,200\nThere's not just the word\ninverter or and-gate.\n\n523\n00:27:33,200 --> 00:27:37,590\nThere were things like\nedge-triggered, flip-flops,\n\n524\n00:27:37,590 --> 00:27:43,780\nand latches, transparent\nlatches, and adders, and\n\n525\n00:27:43,780 --> 00:27:45,170\nthings like that.\n\n526\n00:27:45,170 --> 00:27:48,510\nAnd the difficulty with that\nis that there's pages and\n\n527\n00:27:48,510 --> 00:27:51,410\npages of the definitions of\nall these primitives with\n\n528\n00:27:51,410 --> 00:27:54,690\nnumbers like LS04.\n\n529\n00:27:54,690 --> 00:27:56,740\nAnd then there's many more\nparameters for them.\n\n530\n00:27:56,740 --> 00:27:58,480\nIt's not just one delay.\n\n531\n00:27:58,480 --> 00:28:00,020\nThere's things like set\nup times and hold\n\n532\n00:28:00,020 --> 00:28:01,220\ntimes and all that.\n\n533\n00:28:01,220 --> 00:28:03,990\nBut with the exception of that\npart of the complexity, the\n\n534\n00:28:03,990 --> 00:28:07,580\nstructure of the simulator that\nwe use for building a\n\n535\n00:28:07,580 --> 00:28:12,290\nreal computer, that works\nis exactly what\n\n536\n00:28:12,290 --> 00:28:15,110\nyou're seeing here.\n\n537\n00:28:15,110 --> 00:28:19,270\nWell in any case, what we have\nhere is a few simple things.\n\n538\n00:28:19,270 --> 00:28:21,580\nLike, there's inverter delays\nbeing set up and\n\n539\n00:28:21,580 --> 00:28:23,030\nmaking a new agenda.\n\n540\n00:28:23,030 --> 00:28:26,470\nAnd then we can make\nsome inputs.\n\n541\n00:28:26,470 --> 00:28:28,220\nThere's input-1, input-2,\na sum and a\n\n542\n00:28:28,220 --> 00:28:29,460\ncarry, which are wires.\n\n543\n00:28:29,460 --> 00:28:32,560\nI'm going to put a special kind\nof object called a probe\n\n544\n00:28:32,560 --> 00:28:37,810\nonto, onto some of the wires,\nonto sum and onto carry.\n\n545\n00:28:37,810 --> 00:28:41,590\nA probe is a, can object that\nhas the property that when you\n\n546\n00:28:41,590 --> 00:28:46,120\nchange a wire it's attached to,\nit types out a message.\n\n547\n00:28:46,120 --> 00:28:47,970\nIt's an easy thing to do.\n\n548\n00:28:47,970 --> 00:28:50,790\nAnd then once we have that, of\ncourse, the way you put the\n\n549\n00:28:50,790 --> 00:28:53,040\nprobe on, the first thing it\ndoes, it says, the current\n\n550\n00:28:53,040 --> 00:28:59,400\nvalue of the sum at time 0 is\n0 because I just noticed it.\n\n551\n00:28:59,400 --> 00:29:02,640\nAnd the value of the carry\nat time 0, this is\n\n552\n00:29:02,640 --> 00:29:05,556\nthe time, is 0.\n\n553\n00:29:05,556 --> 00:29:09,620\nAnd then we go off and we\nbuild some structure.\n\n554\n00:29:09,620 --> 00:29:14,440\nLike, we can build a structure\nhere that says you have a\n\n555\n00:29:14,440 --> 00:29:18,420\nhalf-adder on input-1, input-2,\nsum, and carry.\n\n556\n00:29:18,420 --> 00:29:20,420\nAnd we're going to set the\nsignal on input-1 to 1.\n\n557\n00:29:20,420 --> 00:29:21,880\nWe do some propagation.\n\n558\n00:29:21,880 --> 00:29:25,380\nAt time 8, which you could see\ngoing through this thing if\n\n559\n00:29:25,380 --> 00:29:29,520\nyou wanted to, the new value\nof sum became 1.\n\n560\n00:29:29,520 --> 00:29:31,150\nAnd the thing says I'm done.\n\n561\n00:29:31,150 --> 00:29:32,630\nThat wasn't very interesting.\n\n562\n00:29:32,630 --> 00:29:34,150\nBut we can send it some\nmore signals.\n\n563\n00:29:34,150 --> 00:29:36,590\nLike, we set-signal on\ninput-2 to be one.\n\n564\n00:29:36,590 --> 00:29:39,430\nAnd at that time if we\npropagate, then it carried at\n\n565\n00:29:39,430 --> 00:29:43,280\n11, the carry becomes 1, and\nat 16, the sum's new\n\n566\n00:29:43,280 --> 00:29:45,040\nvalue becomes 0.\n\n567\n00:29:45,040 --> 00:29:48,060\nAnd you might want to work out\nthat, if you like, about the\n\n568\n00:29:48,060 --> 00:29:48,990\ndigital circuitry.\n\n569\n00:29:48,990 --> 00:29:50,620\nIt's true, and it works.\n\n570\n00:29:50,620 --> 00:29:51,535\nAnd it's not very interesting.\n\n571\n00:29:51,535 --> 00:29:53,330\nBut that's the kind\nof behavior we\n\n572\n00:29:53,330 --> 00:29:54,580\nget out of this thing.\n\n573\n00:29:54,580 --> 00:30:01,830\n\n\n574\n00:30:01,830 --> 00:30:06,550\nSo what I've shown you right now\nis a large-scale picture,\n\n575\n00:30:06,550 --> 00:30:10,360\nhow you, at a bigger, big\nscale, you implement an\n\n576\n00:30:10,360 --> 00:30:12,952\nevent-driven simulation\nof some sort.\n\n577\n00:30:12,952 --> 00:30:16,010\nAnd how you might organize it\nto have nice hierarchical\n\n578\n00:30:16,010 --> 00:30:20,220\nstructure allowing you to build\nabstract boxes that you\n\n579\n00:30:20,220 --> 00:30:21,225\ncan instantiate.\n\n580\n00:30:21,225 --> 00:30:23,630\nBut I haven't told you any of\nthe details about how this\n\n581\n00:30:23,630 --> 00:30:25,780\nagenda and things\nlike that work.\n\n582\n00:30:25,780 --> 00:30:28,630\nThat we'll do next.\n\n583\n00:30:28,630 --> 00:30:32,040\nAnd that's going to involve\nchange and mutation of data\n\n584\n00:30:32,040 --> 00:30:34,310\nand things like that.\n\n585\n00:30:34,310 --> 00:30:35,860\nAre there any questions\nnow, before I go on?\n\n586\n00:30:35,860 --> 00:30:47,160\n\n\n587\n00:30:47,160 --> 00:30:47,550\nThank you.\n\n588\n00:30:47,550 --> 00:30:48,800\nLet's take a break.\n\n589\n00:30:48,800 --> 00:31:28,940\n\n\n590\n00:31:28,940 --> 00:31:35,060\nWell, we've been making\na simulation.\n\n591\n00:31:35,060 --> 00:31:39,360\nAnd the simulation is an\nevent-driven simulation where\n\n592\n00:31:39,360 --> 00:31:43,920\nthe objects in the world are the\nobjects in the computer.\n\n593\n00:31:43,920 --> 00:31:46,700\nAnd the changes of state that\nare happening in the world in\n\n594\n00:31:46,700 --> 00:31:53,520\ntime are organized to be time\nin the computer, so that if\n\n595\n00:31:53,520 --> 00:31:56,430\nsomething happens after\nsomething else in the world,\n\n596\n00:31:56,430 --> 00:32:00,910\nthen we have it happen after,\nafter the corresponding events\n\n597\n00:32:00,910 --> 00:32:04,420\nhappen in the same order\nin the computer.\n\n598\n00:32:04,420 --> 00:32:06,070\nThat's where we have\nassignments, when\n\n599\n00:32:06,070 --> 00:32:08,220\nwe make that alignment.\n\n600\n00:32:08,220 --> 00:32:11,860\nRight now I want to show you a\nway of organizing time, which\n\n601\n00:32:11,860 --> 00:32:16,040\nis an agenda or priority queue,\nit's sometimes called.\n\n602\n00:32:16,040 --> 00:32:17,990\nWe'll do some--we'll do\na little bit of just\n\n603\n00:32:17,990 --> 00:32:19,980\nunderstanding what are the\nthings we need to be able to\n\n604\n00:32:19,980 --> 00:32:21,230\ndo to make agendas.\n\n605\n00:32:21,230 --> 00:32:28,330\n\n\n606\n00:32:28,330 --> 00:32:30,310\nAnd so we're going to have--and\nso right now over\n\n607\n00:32:30,310 --> 00:32:31,750\nhere, I'm going to write down\na bunch of primitive\n\n608\n00:32:31,750 --> 00:32:35,960\noperations for manipulating\nagendas.\n\n609\n00:32:35,960 --> 00:32:38,650\nI'm not going to show you the\ncode for them because they're\n\n610\n00:32:38,650 --> 00:32:41,300\nall very simple, and you've got\n\n611\n00:32:41,300 --> 00:32:43,680\nlistings of all that anyway.\n\n612\n00:32:43,680 --> 00:32:44,380\nSo what do we have?\n\n613\n00:32:44,380 --> 00:32:52,880\nWe have things like make-agenda\nwhich produces a\n\n614\n00:32:52,880 --> 00:32:54,130\nnew agenda.\n\n615\n00:32:54,130 --> 00:32:59,860\n\n\n616\n00:32:59,860 --> 00:33:10,950\nWe can ask--we get the\ncurrent-time of an agenda,\n\n617\n00:33:10,950 --> 00:33:12,625\nwhich gives me a\nnumber, a time.\n\n618\n00:33:12,625 --> 00:33:16,990\n\n\n619\n00:33:16,990 --> 00:33:20,650\nWe can get--we can ask whether\nan agenda is empty,\n\n620\n00:33:20,650 --> 00:33:21,900\nempty-agenda.\n\n621\n00:33:21,900 --> 00:33:30,200\n\n\n622\n00:33:30,200 --> 00:33:32,570\nAnd that produces either\na true or a false.\n\n623\n00:33:32,570 --> 00:33:42,590\n\n\n624\n00:33:42,590 --> 00:33:44,720\nWe can add an object\nto an agenda.\n\n625\n00:33:44,720 --> 00:33:52,710\n\n\n626\n00:33:52,710 --> 00:33:55,230\nActually, what we add to an\nagenda is an operation--an\n\n627\n00:33:55,230 --> 00:33:56,910\naction to be done.\n\n628\n00:33:56,910 --> 00:34:03,560\nAnd that takes a time, the\naction itself, and the agenda\n\n629\n00:34:03,560 --> 00:34:04,810\nI want to add it to.\n\n630\n00:34:04,810 --> 00:34:07,850\n\n\n631\n00:34:07,850 --> 00:34:09,280\nThat inserts it in\nthe appropriate\n\n632\n00:34:09,280 --> 00:34:10,719\nplace in the agenda.\n\n633\n00:34:10,719 --> 00:34:14,850\nI can get the first item off an\nagenda, the first thing I\n\n634\n00:34:14,850 --> 00:34:23,259\nhave to do, which is going\nto give me an action.\n\n635\n00:34:23,259 --> 00:34:26,085\n\n\n636\n00:34:26,085 --> 00:34:29,540\nAnd I can remove the first\nitem from an agenda.\n\n637\n00:34:29,540 --> 00:34:31,409\nThat's what I have to be able\nto do with agendas.\n\n638\n00:34:31,409 --> 00:34:33,020\nThat is a big complicated\nmess.\n\n639\n00:34:33,020 --> 00:34:42,530\n\n\n640\n00:34:42,530 --> 00:34:43,780\nFrom an agenda.\n\n641\n00:34:43,780 --> 00:34:45,530\n\n\n642\n00:34:45,530 --> 00:34:48,040\nWell, let's see how we can\norganize this thing as a data\n\n643\n00:34:48,040 --> 00:34:52,528\nstructure a bit.\n\n644\n00:34:52,528 --> 00:34:58,720\nWell, an agenda is going to be\nsome kind of list. And it's\n\n645\n00:34:58,720 --> 00:35:00,190\ngoing to be a list that\nI'm going to have\n\n646\n00:35:00,190 --> 00:35:01,570\nto be able to modify.\n\n647\n00:35:01,570 --> 00:35:05,820\nSo we have to talk about\nmodifying of lists, because\n\n648\n00:35:05,820 --> 00:35:09,590\nI'm going to add things to it,\nand delete things from it, and\n\n649\n00:35:09,590 --> 00:35:11,070\nthings like that.\n\n650\n00:35:11,070 --> 00:35:13,820\nIt's organized by time.\n\n651\n00:35:13,820 --> 00:35:15,570\nIt's probably good to keep\nit in sorted order.\n\n652\n00:35:15,570 --> 00:35:18,330\n\n\n653\n00:35:18,330 --> 00:35:22,170\nBut sometimes there are lots of\nthings that happen at the\n\n654\n00:35:22,170 --> 00:35:23,420\nsame time--approximate\nsame time.\n\n655\n00:35:23,420 --> 00:35:26,440\nWhat I have to do is say, group\nthings by the time at\n\n656\n00:35:26,440 --> 00:35:29,040\nwhich they're supposed\nto happen.\n\n657\n00:35:29,040 --> 00:35:32,780\nSo I'm going to make an agenda\nas a list of segments.\n\n658\n00:35:32,780 --> 00:35:36,780\nAnd so I'm going to draw you a\ndata structure for an agenda,\n\n659\n00:35:36,780 --> 00:35:39,620\na perfectly reasonable one.\n\n660\n00:35:39,620 --> 00:35:41,110\nHere's an agenda.\n\n661\n00:35:41,110 --> 00:35:42,870\nIt's a thing that begins\nwith a name.\n\n662\n00:35:42,870 --> 00:35:47,630\n\n\n663\n00:35:47,630 --> 00:35:49,940\nI'm going to do it right now\nout of list structure.\n\n664\n00:35:49,940 --> 00:35:52,620\n\n\n665\n00:35:52,620 --> 00:35:53,980\nIt's got a header.\n\n666\n00:35:53,980 --> 00:35:55,840\nThere's a reason\nfor the header.\n\n667\n00:35:55,840 --> 00:35:57,630\nWe're going to see\nthe reason soon.\n\n668\n00:35:57,630 --> 00:36:00,680\n\n\n669\n00:36:00,680 --> 00:36:03,750\nAnd it will have a segment.\n\n670\n00:36:03,750 --> 00:36:05,620\nIt will have--it will be\na list of segments.\n\n671\n00:36:05,620 --> 00:36:08,310\n\n\n672\n00:36:08,310 --> 00:36:13,580\nSupposing this agenda has two\nsegments, they're the car's--\n\n673\n00:36:13,580 --> 00:36:18,260\nsuccessive car's of this\nlist. Each segment is\n\n674\n00:36:18,260 --> 00:36:20,250\ngoing to have a time--\n\n675\n00:36:20,250 --> 00:36:24,160\n\n\n676\n00:36:24,160 --> 00:36:26,900\nsay for example, 10--\n\n677\n00:36:26,900 --> 00:36:29,060\nthat says that the things\nthat happen in this\n\n678\n00:36:29,060 --> 00:36:33,320\nsegment are at time 10.\n\n679\n00:36:33,320 --> 00:36:36,670\nAnd what I'm going to have in\nhere is another data structure\n\n680\n00:36:36,670 --> 00:36:39,490\nwhich I'm not going to describe,\nwhich is a queue of\n\n681\n00:36:39,490 --> 00:36:42,240\nthings to do at time 10.\n\n682\n00:36:42,240 --> 00:36:43,330\nIt's a queue.\n\n683\n00:36:43,330 --> 00:36:45,130\nAnd we'll talk about\nthat in a second.\n\n684\n00:36:45,130 --> 00:36:49,530\nBut abstractly, the queue is\njust a list of things to do at\n\n685\n00:36:49,530 --> 00:36:50,200\na particular time.\n\n686\n00:36:50,200 --> 00:36:53,100\nAnd I can add things\nto a queue.\n\n687\n00:36:53,100 --> 00:36:56,140\nThis is a queue.\n\n688\n00:36:56,140 --> 00:36:59,115\nThere's a time, there's\na segment.\n\n689\n00:36:59,115 --> 00:37:02,889\n\n\n690\n00:37:02,889 --> 00:37:06,035\nNow, I may have another segment\nin this agenda.\n\n691\n00:37:06,035 --> 00:37:08,940\n\n\n692\n00:37:08,940 --> 00:37:13,410\nSupposing this is stuff that\nhappens at time 30.\n\n693\n00:37:13,410 --> 00:37:18,020\nIt has, of course, another\nqueue of things that are\n\n694\n00:37:18,020 --> 00:37:23,210\nqueued up to be done\nat time 30.\n\n695\n00:37:23,210 --> 00:37:24,705\nWell, there are various\nthings I have to be\n\n696\n00:37:24,705 --> 00:37:27,090\nable to do to an agenda.\n\n697\n00:37:27,090 --> 00:37:30,410\nSupposing I want to add to an\nagenda another thing to be\n\n698\n00:37:30,410 --> 00:37:33,030\ndone at time 10.\n\n699\n00:37:33,030 --> 00:37:34,700\nWell, that's not very hard.\n\n700\n00:37:34,700 --> 00:37:37,480\nI'm going to walk down\nhere, looking for the\n\n701\n00:37:37,480 --> 00:37:39,730\nsegment of time 10.\n\n702\n00:37:39,730 --> 00:37:42,930\nIt is possible that there is\nno segment of time 10.\n\n703\n00:37:42,930 --> 00:37:45,420\nWe'll cover that case\nin a second.\n\n704\n00:37:45,420 --> 00:37:48,590\nBut if I find a segment of time\n10, then if I want to add\n\n705\n00:37:48,590 --> 00:37:51,070\nanother thing to be done\nat time 10, I just\n\n706\n00:37:51,070 --> 00:37:53,860\nincrease that queue--\n\n707\n00:37:53,860 --> 00:37:56,290\n\"just increase\" isn't such\nan obvious idea.\n\n708\n00:37:56,290 --> 00:38:01,430\nBut I increase the things\nto be done at that time.\n\n709\n00:38:01,430 --> 00:38:02,900\nNow, supposing I want to\nadd something to be\n\n710\n00:38:02,900 --> 00:38:05,140\ndone at time 20.\n\n711\n00:38:05,140 --> 00:38:08,680\nThere is no segment\nfor time 20.\n\n712\n00:38:08,680 --> 00:38:11,340\nI'm going to have to create\na new segment.\n\n713\n00:38:11,340 --> 00:38:13,960\nI want my time 20 segment\nto exist between\n\n714\n00:38:13,960 --> 00:38:17,610\ntime 10 and time 30.\n\n715\n00:38:17,610 --> 00:38:20,170\nWell, that takes\na little work.\n\n716\n00:38:20,170 --> 00:38:21,525\nI'm going to have\nto do a CONS.\n\n717\n00:38:21,525 --> 00:38:24,260\n\n\n718\n00:38:24,260 --> 00:38:28,690\nI'm going to have to make a\nnew element of the agenda\n\n719\n00:38:28,690 --> 00:38:29,940\nlist--list of segments.\n\n720\n00:38:29,940 --> 00:38:33,600\n\n\n721\n00:38:33,600 --> 00:38:35,400\nI'm going to have to change.\n\n722\n00:38:35,400 --> 00:38:37,540\nHere's change.\n\n723\n00:38:37,540 --> 00:38:42,290\nI'm going to have to change\nthe CDR of the CDR of the\n\n724\n00:38:42,290 --> 00:38:50,620\nagenda to point that a new CONS\nof the new segment and\n\n725\n00:38:50,620 --> 00:38:56,657\nthe CDR of the CDR of the CDR of\nthe agenda, the CD-D-D-DR.\n\n726\n00:38:56,657 --> 00:39:02,470\nAnd this is going to have a\nnew segment now of time 20\n\n727\n00:39:02,470 --> 00:39:06,290\nwith its own queue, which now\nhas one element in it.\n\n728\n00:39:06,290 --> 00:39:10,730\n\n\n729\n00:39:10,730 --> 00:39:13,080\nIf I wanted to add something at\nthe end, I'm going to have\n\n730\n00:39:13,080 --> 00:39:20,770\nto replace the CDR of this, of\nthis list with something.\n\n731\n00:39:20,770 --> 00:39:24,040\nWe're going to have to change\nthat piece of data structure.\n\n732\n00:39:24,040 --> 00:39:27,210\nSo I'm going to need new\nprimitives for doing this.\n\n733\n00:39:27,210 --> 00:39:29,550\nBut I'm just showing you\nwhy I need them.\n\n734\n00:39:29,550 --> 00:39:33,390\nAnd finally, if I wanted to add\na thing to be done at time\n\n735\n00:39:33,390 --> 00:39:41,240\n5, I'm going to have to change\nthis one, because I'm going to\n\n736\n00:39:41,240 --> 00:39:44,770\nhave to add it in over here,\nwhich is why I planned ahead\n\n737\n00:39:44,770 --> 00:39:49,400\nand had a header cell,\nwhich has a place.\n\n738\n00:39:49,400 --> 00:39:50,580\nIf I'm going to change things,\nI have to have\n\n739\n00:39:50,580 --> 00:39:53,420\nplaces for the change.\n\n740\n00:39:53,420 --> 00:39:58,600\nI have to have a place\nto make the change.\n\n741\n00:39:58,600 --> 00:40:02,540\nIf I remove things from the\nagenda, that's not so hard.\n\n742\n00:40:02,540 --> 00:40:04,990\nRemoving them from the beginning\nis pretty easy,\n\n743\n00:40:04,990 --> 00:40:07,740\nwhich is the only case I have.\nI can go looking for the\n\n744\n00:40:07,740 --> 00:40:11,220\nfirst, the first segment.\n\n745\n00:40:11,220 --> 00:40:14,510\nI see if it has a\nnon-empty queue.\n\n746\n00:40:14,510 --> 00:40:17,610\nIf it has a non-empty queue,\nwell, I'm going to delete one\n\n747\n00:40:17,610 --> 00:40:20,100\nelement from the queue,\nlike that.\n\n748\n00:40:20,100 --> 00:40:23,460\nIf the queue ever becomes empty,\nthen I have to delete\n\n749\n00:40:23,460 --> 00:40:24,220\nthe whole segment.\n\n750\n00:40:24,220 --> 00:40:28,220\nAnd then this, this changes\nto point to here.\n\n751\n00:40:28,220 --> 00:40:30,540\nSo it's quite a complicated data\nstructure manipulation\n\n752\n00:40:30,540 --> 00:40:36,440\ngoing on, the details of which\nare not really very exciting.\n\n753\n00:40:36,440 --> 00:40:38,920\nNow, let's talk about queues.\n\n754\n00:40:38,920 --> 00:40:41,160\nThey're similar.\n\n755\n00:40:41,160 --> 00:40:44,340\nBecause each of these agendas\nhas a queue in it.\n\n756\n00:40:44,340 --> 00:40:45,590\nWhat's a queue?\n\n757\n00:40:45,590 --> 00:40:49,079\n\n\n758\n00:40:49,079 --> 00:40:51,110\nA queue is going to have\nthe following primitive\n\n759\n00:40:51,110 --> 00:40:52,350\noperations.\n\n760\n00:40:52,350 --> 00:41:02,170\nTo make a queue, this gives\nme a new queue.\n\n761\n00:41:02,170 --> 00:41:07,274\n\n\n762\n00:41:07,274 --> 00:41:12,610\nI'm going to have to be\nable to insert into\n\n763\n00:41:12,610 --> 00:41:16,850\na queue a new item.\n\n764\n00:41:16,850 --> 00:41:24,510\n\n\n765\n00:41:24,510 --> 00:41:27,490\nI'm going to have to be able\nto delete from a queue the\n\n766\n00:41:27,490 --> 00:41:28,740\nfirst item in the queue.\n\n767\n00:41:28,740 --> 00:41:39,988\n\n\n768\n00:41:39,988 --> 00:41:51,320\nAnd I want to be able to get the\nfirst thing in the queue\n\n769\n00:41:51,320 --> 00:41:52,890\nfrom some queue.\n\n770\n00:41:52,890 --> 00:41:55,140\nI also have to be able to test\nwhether a queue is empty.\n\n771\n00:41:55,140 --> 00:42:07,110\n\n\n772\n00:42:07,110 --> 00:42:09,710\nAnd when you invent things like\nthis, I want you to be\n\n773\n00:42:09,710 --> 00:42:13,220\nvery careful to use the kinds\nof conventions I use for\n\n774\n00:42:13,220 --> 00:42:15,120\nnaming things.\n\n775\n00:42:15,120 --> 00:42:18,450\nNotice that I'm careful to say\nthese change something and\n\n776\n00:42:18,450 --> 00:42:19,870\nthat tests it.\n\n777\n00:42:19,870 --> 00:42:24,335\nAnd presumably, I did the\nsame thing over here.\n\n778\n00:42:24,335 --> 00:42:29,240\nOK, and there should be an\nempty test over here.\n\n779\n00:42:29,240 --> 00:42:31,720\nOK, well, how would\nI make a queue?\n\n780\n00:42:31,720 --> 00:42:35,210\nA queue wants to be something\nI can add to at the end of,\n\n781\n00:42:35,210 --> 00:42:37,840\nand pick up the thing\nat the beginning of.\n\n782\n00:42:37,840 --> 00:42:39,290\nI should be able to delete\nfrom the beginning\n\n783\n00:42:39,290 --> 00:42:41,230\nand add to the end.\n\n784\n00:42:41,230 --> 00:42:42,400\nWell, I'm going to show\nyou a very simple\n\n785\n00:42:42,400 --> 00:42:43,740\nstructure for that.\n\n786\n00:42:43,740 --> 00:42:47,080\nWe can make this out\nof CONSes as well.\n\n787\n00:42:47,080 --> 00:42:49,910\nHere's a queue.\n\n788\n00:42:49,910 --> 00:42:55,310\nIt has--it has a queue header,\nwhich contains two parts--\n\n789\n00:42:55,310 --> 00:42:59,610\na front pointer and\na rear pointer.\n\n790\n00:42:59,610 --> 00:43:02,930\n\n\n791\n00:43:02,930 --> 00:43:09,000\nAnd here I have a queue\nwith two items in it.\n\n792\n00:43:09,000 --> 00:43:12,095\nThe first item, I don't know,\nit's perhaps a 1.\n\n793\n00:43:12,095 --> 00:43:16,530\nAnd the second item, I don't\nknow, let's give it a 2.\n\n794\n00:43:16,530 --> 00:43:21,160\n\n\n795\n00:43:21,160 --> 00:43:24,550\nThe reason why I want two\npointers in here, a front\n\n796\n00:43:24,550 --> 00:43:27,570\npointer and a rear pointer,\nis so I can add to the end\n\n797\n00:43:27,570 --> 00:43:31,850\nwithout having to chase down\nfrom the beginning.\n\n798\n00:43:31,850 --> 00:43:34,380\nSo for example, if I wanted to\nadd one more item to this\n\n799\n00:43:34,380 --> 00:43:40,380\nqueue, if I want to add on\nanother item to be worried\n\n800\n00:43:40,380 --> 00:43:44,060\nabout later, all I have to do is\nmake a CONS, which contains\n\n801\n00:43:44,060 --> 00:43:47,530\nthat item, say a 3.\n\n802\n00:43:47,530 --> 00:43:51,340\nThat's for inserting\n3 into the queue.\n\n803\n00:43:51,340 --> 00:44:00,100\nThen I have to change this\npointer here to here.\n\n804\n00:44:00,100 --> 00:44:04,320\nAnd I have to change this one\nto point to the new rear.\n\n805\n00:44:04,320 --> 00:44:09,120\n\n\n806\n00:44:09,120 --> 00:44:11,990\nIf I wish to take the first\nelement of the queue, the\n\n807\n00:44:11,990 --> 00:44:15,130\nfirst item, I just go chasing\ndown the front pointer until I\n\n808\n00:44:15,130 --> 00:44:18,890\nfind the first one\nand pick it up.\n\n809\n00:44:18,890 --> 00:44:22,560\nIf I wish to delete the first\nitem from the queue,\n\n810\n00:44:22,560 --> 00:44:25,240\ndelete-queue, all I do\nis move the front\n\n811\n00:44:25,240 --> 00:44:27,450\npointer along this way.\n\n812\n00:44:27,450 --> 00:44:31,700\nThe new front of the\nqueue is now this.\n\n813\n00:44:31,700 --> 00:44:34,390\nSo queues are very simple too.\n\n814\n00:44:34,390 --> 00:44:39,690\nSo what you see now is that I\nneed a certain number of new\n\n815\n00:44:39,690 --> 00:44:41,350\nprimitive operations.\n\n816\n00:44:41,350 --> 00:44:42,560\nAnd I'm going to give\nthem some names.\n\n817\n00:44:42,560 --> 00:44:45,310\nAnd then we're going to look\ninto how they work, and how\n\n818\n00:44:45,310 --> 00:44:47,350\nthey're used.\n\n819\n00:44:47,350 --> 00:44:56,970\nWe have set the CAR of some\npair, or a thing produced by\n\n820\n00:44:56,970 --> 00:44:58,940\nCONSing, to a new value.\n\n821\n00:44:58,940 --> 00:45:02,370\n\n\n822\n00:45:02,370 --> 00:45:09,920\nAnd set the CDR of a pair\nto a new value.\n\n823\n00:45:09,920 --> 00:45:12,680\n\n\n824\n00:45:12,680 --> 00:45:16,030\nAnd then we're going to look\ninto how they work.\n\n825\n00:45:16,030 --> 00:45:19,720\nI needed setting CAR over\nhere to delete the first\n\n826\n00:45:19,720 --> 00:45:20,960\nelement of the queue.\n\n827\n00:45:20,960 --> 00:45:23,470\nThis is the CAR, and\nI had to set it.\n\n828\n00:45:23,470 --> 00:45:26,300\nI had to be able to set the\nCDR to be able to move the\n\n829\n00:45:26,300 --> 00:45:30,160\nrear pointer, or to be able to\nincrement the queue here.\n\n830\n00:45:30,160 --> 00:45:33,170\nAll of the operations I did were\nmade out of those that I\n\n831\n00:45:33,170 --> 00:45:35,515\njust showed you on the, on\nthe last blackboard.\n\n832\n00:45:35,515 --> 00:45:38,230\n\n\n833\n00:45:38,230 --> 00:45:38,430\nGood.\n\n834\n00:45:38,430 --> 00:45:40,357\nLet's pause the time, and take\na little break then.\n\n835\n00:45:40,357 --> 00:46:38,346\n\n\n836\n00:46:38,346 --> 00:46:42,910\nWhen we originally introduced\npairs made out of CONS, made\n\n837\n00:46:42,910 --> 00:46:48,640\nby CONS, we only said a few\naxioms about them, which were\n\n838\n00:46:48,640 --> 00:46:50,040\nof the form--\n\n839\n00:46:50,040 --> 00:46:52,010\nwhat were they--\n\n840\n00:46:52,010 --> 00:47:06,040\nfor all X and Y, the CAR of the\nCONS of X and Y is X and\n\n841\n00:47:06,040 --> 00:47:15,650\nthe CDR of the CONS of X and Y\nis Y. Now, these say nothing\n\n842\n00:47:15,650 --> 00:47:21,850\nabout whether a CONS has an\nidentity like a person.\n\n843\n00:47:21,850 --> 00:47:25,730\nIn fact, all they say is\nsomething sort of abstract,\n\n844\n00:47:25,730 --> 00:47:29,740\nthat a CONS is the parts\nit's made out of.\n\n845\n00:47:29,740 --> 00:47:32,320\nAnd of course, two things are\nmade out of the same parts,\n\n846\n00:47:32,320 --> 00:47:34,990\nthey're the same, at least\nfrom the point of view of\n\n847\n00:47:34,990 --> 00:47:37,390\nthese axioms.\n\n848\n00:47:37,390 --> 00:47:39,920\nBut by introducing\nassignment--\n\n849\n00:47:39,920 --> 00:47:43,360\nin fact, mutable data is a kind\nof assignment, we have a\n\n850\n00:47:43,360 --> 00:47:45,590\nset CAR and a set CDR--\n\n851\n00:47:45,590 --> 00:47:48,300\nby introducing those, these\naxioms no longer tell the\n\n852\n00:47:48,300 --> 00:47:49,830\nwhole story.\n\n853\n00:47:49,830 --> 00:47:53,250\nAnd they're still true if\nwritten exactly like this.\n\n854\n00:47:53,250 --> 00:47:56,070\nBut they don't tell\nthe whole story.\n\n855\n00:47:56,070 --> 00:48:01,150\nBecause if I'm going to set a\nparticular CAR in a particular\n\n856\n00:48:01,150 --> 00:48:05,810\nCONS, the questions are, well,\nis that setting all CARs and\n\n857\n00:48:05,810 --> 00:48:10,090\nall CONSes of the same\ntwo things or not?\n\n858\n00:48:10,090 --> 00:48:12,610\nIf I--if we use CONSes to make\nup things like rational\n\n859\n00:48:12,610 --> 00:48:19,540\nnumbers, or things like 3 over\n4, supposing I had two\n\n860\n00:48:19,540 --> 00:48:21,570\nthree-fourths.\n\n861\n00:48:21,570 --> 00:48:24,110\nAre they the same one--\n\n862\n00:48:24,110 --> 00:48:25,340\nor are they different?\n\n863\n00:48:25,340 --> 00:48:27,860\nWell, in the case of numbers,\nit doesn't matter.\n\n864\n00:48:27,860 --> 00:48:29,410\nBecause there's no meaning\nto changing the\n\n865\n00:48:29,410 --> 00:48:33,020\ndenominator of a number.\n\n866\n00:48:33,020 --> 00:48:34,670\nWhat you could do is make a\nnumber which has a different\n\n867\n00:48:34,670 --> 00:48:36,840\ndenominator.\n\n868\n00:48:36,840 --> 00:48:38,980\nBut the concept of changing a\nnumber which has to have a\n\n869\n00:48:38,980 --> 00:48:41,570\ndifferent denominator is sort\nof a very weird, and sort of\n\n870\n00:48:41,570 --> 00:48:44,770\nnot supported by what you\nthink of as mathematics.\n\n871\n00:48:44,770 --> 00:48:46,570\nHowever, when these CONSes\nrepresent things in the\n\n872\n00:48:46,570 --> 00:48:50,940\nphysical world, then changing\nsomething like the CAR is like\n\n873\n00:48:50,940 --> 00:48:53,690\nremoving a piece of\nthe fingernail.\n\n874\n00:48:53,690 --> 00:48:57,770\nAnd so CONSes have\nan identity.\n\n875\n00:48:57,770 --> 00:49:01,280\nLet me show you what I mean\nabout identity, first of all.\n\n876\n00:49:01,280 --> 00:49:04,320\nLet's do some little\nexample here.\n\n877\n00:49:04,320 --> 00:49:15,200\nSupposing I define A to\nthe CONS of 1 and 2.\n\n878\n00:49:15,200 --> 00:49:18,040\n\n\n879\n00:49:18,040 --> 00:49:22,510\nWell, what that means, first of\nall, is that somewhere in\n\n880\n00:49:22,510 --> 00:49:27,590\nsome environment I've made a\nsymbol A to have a value which\n\n881\n00:49:27,590 --> 00:49:33,300\nis a pair consisting of pointers\nto a 1 and a pointer\n\n882\n00:49:33,300 --> 00:49:38,120\nto a 2, just like that.\n\n883\n00:49:38,120 --> 00:49:47,220\nNow, supposing I also say define\nB to be the CONS--\n\n884\n00:49:47,220 --> 00:49:53,320\n\n\n885\n00:49:53,320 --> 00:49:58,240\nit doesn't matter, but I like\nit better, it's prettier--\n\n886\n00:49:58,240 --> 00:50:03,970\nof A and A.\n\n887\n00:50:03,970 --> 00:50:07,840\nWell, first of all, I'm using\nthe name A twice.\n\n888\n00:50:07,840 --> 00:50:09,100\nAt this moment, I'm\ngoing to think of\n\n889\n00:50:09,100 --> 00:50:11,300\nCONSes as having identity.\n\n890\n00:50:11,300 --> 00:50:13,690\nThis is the same one.\n\n891\n00:50:13,690 --> 00:50:19,200\nAnd so what that means is I make\nanother pair, which I'm\n\n892\n00:50:19,200 --> 00:50:29,120\ngoing to call B. And it contains\ntwo pointers to A. At\n\n893\n00:50:29,120 --> 00:50:33,260\nthis point, I have three\nnames for this object.\n\n894\n00:50:33,260 --> 00:50:34,790\nA is its name.\n\n895\n00:50:34,790 --> 00:50:37,230\nThe CAR of B is its name.\n\n896\n00:50:37,230 --> 00:50:39,360\nAnd the CDR of B is its name.\n\n897\n00:50:39,360 --> 00:50:41,150\nIt has several aliases,\nthey're called.\n\n898\n00:50:41,150 --> 00:50:44,230\n\n\n899\n00:50:44,230 --> 00:51:01,860\nNow, supposing I do something\nlike set-the-CAR, the CAR of\n\n900\n00:51:01,860 --> 00:51:07,880\nthe CAR of B to 3.\n\n901\n00:51:07,880 --> 00:51:12,750\n\n\n902\n00:51:12,750 --> 00:51:17,830\nWhat that means is I find the\nCAR of B, that's this.\n\n903\n00:51:17,830 --> 00:51:20,935\nI set the CAR of that to\nbe 3, changing this.\n\n904\n00:51:20,935 --> 00:51:24,760\n\n\n905\n00:51:24,760 --> 00:51:29,940\nI've changed A. If I were\nto ask what's the\n\n906\n00:51:29,940 --> 00:51:35,340\nCAR of A--of A now?\n\n907\n00:51:35,340 --> 00:51:42,250\nI would get out 3, even though\nhere we see that A was the\n\n908\n00:51:42,250 --> 00:51:45,290\nCONS of 1 and 2.\n\n909\n00:51:45,290 --> 00:51:48,400\nI caused A to change\nby changing B.\n\n910\n00:51:48,400 --> 00:51:52,010\nThere is sharing here.\n\n911\n00:51:52,010 --> 00:51:54,240\nThat's sometimes what we want.\n\n912\n00:51:54,240 --> 00:51:56,400\nSurely in the queues and things\nlike that, that's\n\n913\n00:51:56,400 --> 00:51:59,560\nexactly what we defined\nour--organized our data\n\n914\n00:51:59,560 --> 00:52:01,790\nstructures to facilitate--\n\n915\n00:52:01,790 --> 00:52:04,350\nsharing.\n\n916\n00:52:04,350 --> 00:52:08,950\nBut inadvertent sharing,\nunanticipated interactions\n\n917\n00:52:08,950 --> 00:52:12,925\nbetween objects, is the source\nof most of the bugs that occur\n\n918\n00:52:12,925 --> 00:52:17,820\nin complicated programs. So by\nintroducing this possibility\n\n919\n00:52:17,820 --> 00:52:22,570\nof things having identity and\nsharing and having multiple\n\n920\n00:52:22,570 --> 00:52:25,190\nnames for the same thing,\nwe get a lot of power.\n\n921\n00:52:25,190 --> 00:52:27,390\nBut we're going to pay\nfor it with lots of\n\n922\n00:52:27,390 --> 00:52:28,640\ncomplexity and bugs.\n\n923\n00:52:28,640 --> 00:52:32,190\n\n\n924\n00:52:32,190 --> 00:52:35,430\nSo also, for example, if I just\nlooked at this just to\n\n925\n00:52:35,430 --> 00:52:43,370\ndrive that home, the CADR of\nB, which has nothing to do\n\n926\n00:52:43,370 --> 00:52:46,560\nwith even the CAR of\nB, apparently.\n\n927\n00:52:46,560 --> 00:52:49,350\nThe CADR of B, what's that?\n\n928\n00:52:49,350 --> 00:52:53,560\nTake that CDR of B and now\ntake the CAR of that.\n\n929\n00:52:53,560 --> 00:52:56,480\nOh, that's 3 also.\n\n930\n00:52:56,480 --> 00:53:01,120\nSo I can have non-local\ninteractions by sharing.\n\n931\n00:53:01,120 --> 00:53:02,480\nAnd I have to be very\ncareful of that.\n\n932\n00:53:02,480 --> 00:53:06,640\n\n\n933\n00:53:06,640 --> 00:53:10,530\nWell, so far, of course, it\nseems I've introduced several\n\n934\n00:53:10,530 --> 00:53:13,030\ndifferent assignment\noperators--\n\n935\n00:53:13,030 --> 00:53:19,480\nset, set CAR, set CDR. Well,\nmaybe I should just get rid of\n\n936\n00:53:19,480 --> 00:53:22,820\nset CAR and set CDR. Maybe\nthey're not worthwhile.\n\n937\n00:53:22,820 --> 00:53:25,680\nWell, the answer is that once\nyou let the camel's nose into\n\n938\n00:53:25,680 --> 00:53:27,170\nthe tent, the rest\nof him follows.\n\n939\n00:53:27,170 --> 00:53:30,160\n\n\n940\n00:53:30,160 --> 00:53:34,600\nAll I have to have is set, and\nI can make all of the--all of\n\n941\n00:53:34,600 --> 00:53:35,850\nthe bad things that\ncan happen.\n\n942\n00:53:35,850 --> 00:53:38,550\n\n\n943\n00:53:38,550 --> 00:53:40,690\nLet's play with that\na little bit.\n\n944\n00:53:40,690 --> 00:53:45,330\nA couple of days ago, when we\nintroduced compound data, you\n\n945\n00:53:45,330 --> 00:53:49,980\nsaw Hal show you a definition\nof CONS in terms\n\n946\n00:53:49,980 --> 00:53:52,480\nof a message acceptor.\n\n947\n00:53:52,480 --> 00:53:57,280\nI'm going to show you even\na more horrible thing, a\n\n948\n00:53:57,280 --> 00:54:04,440\ndefinition of CONS in terms of\nnothing but air, hot air.\n\n949\n00:54:04,440 --> 00:54:07,640\nWhat is the definition of CONS,\nof the old functional\n\n950\n00:54:07,640 --> 00:54:13,330\nkind, in terms of purely\nlambdic expressions,\n\n951\n00:54:13,330 --> 00:54:14,580\nprocedures?\n\n952\n00:54:14,580 --> 00:54:17,190\n\n\n953\n00:54:17,190 --> 00:54:20,630\nBecause I'm going to then modify\nthis definition to get\n\n954\n00:54:20,630 --> 00:54:25,020\nassignment to be only one kind\nof assignment, to get rid of\n\n955\n00:54:25,020 --> 00:54:28,580\nthe set CAR and set CDR\nin terms of set.\n\n956\n00:54:28,580 --> 00:54:41,020\nSo what if I define CONS of X\nand Y to be a procedure of one\n\n957\n00:54:41,020 --> 00:54:44,310\nargument called a message\nM, which calls that\n\n958\n00:54:44,310 --> 00:54:46,320\nmessage on X and Y?\n\n959\n00:54:46,320 --> 00:54:51,120\n\n\n960\n00:54:51,120 --> 00:54:54,080\nThis [? idea ?] was invented by\nAlonzo Church, who was the\n\n961\n00:54:54,080 --> 00:54:56,180\ngreatest programmer of the\n20th century, although he\n\n962\n00:54:56,180 --> 00:54:57,870\nnever saw a computer.\n\n963\n00:54:57,870 --> 00:54:59,130\nIt was done in the 1930s.\n\n964\n00:54:59,130 --> 00:55:02,220\nHe was a logician, I suppose\nat Princeton at the time.\n\n965\n00:55:02,220 --> 00:55:08,660\n\n\n966\n00:55:08,660 --> 00:55:15,690\nDefine CAR of X to be the result\nof applying X to that\n\n967\n00:55:15,690 --> 00:55:24,000\nprocedure of two arguments, A\nand D, which selects A. I will\n\n968\n00:55:24,000 --> 00:55:36,410\ndefine CDR of X to be that\nprocedure, to be the result of\n\n969\n00:55:36,410 --> 00:55:46,670\napplying X to that procedure of\nA and D, which selects D.\n\n970\n00:55:46,670 --> 00:55:50,510\nNow, you may not recognize this\nas CAR, CDR, and CONS.\n\n971\n00:55:50,510 --> 00:55:52,690\nBut I'm going to demonstrate to\nyou that it satisfies the\n\n972\n00:55:52,690 --> 00:55:55,210\noriginal axioms, just once.\n\n973\n00:55:55,210 --> 00:55:58,290\nAnd then we're going to do\nsome playing of games.\n\n974\n00:55:58,290 --> 00:56:09,695\nConsider the problem CAR of\nCONS of, say, 35 and 47.\n\n975\n00:56:09,695 --> 00:56:11,120\nWell, what is that?\n\n976\n00:56:11,120 --> 00:56:14,080\nIt is the result of taking car\nof the result of substituting\n\n977\n00:56:14,080 --> 00:56:19,710\n35 and 47 for X and Y\nin the body of this.\n\n978\n00:56:19,710 --> 00:56:20,690\nWell, that's easy enough.\n\n979\n00:56:20,690 --> 00:56:27,780\nThat's CAR of the result of\nsubstituting into lambda of M,\n\n980\n00:56:27,780 --> 00:56:35,750\nM of 35 and 47.\n\n981\n00:56:35,750 --> 00:56:38,680\nWell, what this is, is the\nresult of substituting this\n\n982\n00:56:38,680 --> 00:56:42,830\nobject for X in the\nbody of that.\n\n983\n00:56:42,830 --> 00:56:48,930\nSo that's just lambda of M--\n\n984\n00:56:48,930 --> 00:56:51,090\nthat's substituted, because\nthis object is being\n\n985\n00:56:51,090 --> 00:56:54,980\nsubstituted for X, which is\nthe beginning of a list,\n\n986\n00:56:54,980 --> 00:56:57,260\nlambda of M--\n\n987\n00:56:57,260 --> 00:57:07,570\nM of 35 and 47, applied to that\nprocedure of A and D,\n\n988\n00:57:07,570 --> 00:57:12,280\nwhich gives me A. Well, that's\nthe result of substituting\n\n989\n00:57:12,280 --> 00:57:15,840\nthis for M here.\n\n990\n00:57:15,840 --> 00:57:22,320\nSo that's the same thing\nas lambda of A, D, A,\n\n991\n00:57:22,320 --> 00:57:26,026\napplied to 35 and 47.\n\n992\n00:57:26,026 --> 00:57:27,560\nOh, well that's 35.\n\n993\n00:57:27,560 --> 00:57:36,000\nThat's substituting 35 for A\nand for 47 for D in A. So I\n\n994\n00:57:36,000 --> 00:57:40,720\ndon't need any data at all,\nnot even numbers.\n\n995\n00:57:40,720 --> 00:57:42,640\nThis is Alonso Church's hack.\n\n996\n00:57:42,640 --> 00:57:52,420\n\n\n997\n00:57:52,420 --> 00:57:56,760\nWell, now we're going to do\nsomething nasty to him.\n\n998\n00:57:56,760 --> 00:57:58,860\nBeing a logician, he\nwouldn't like this.\n\n999\n00:57:58,860 --> 00:58:03,260\nBut as programmers, let's\nlook at the overhead.\n\n1000\n00:58:03,260 --> 00:58:05,390\nAnd here we go.\n\n1001\n00:58:05,390 --> 00:58:09,570\nI'm going to change the\ndefinition of CONS.\n\n1002\n00:58:09,570 --> 00:58:14,520\nIt's almost the same as Alonzo\nChurch's, but not quite.\n\n1003\n00:58:14,520 --> 00:58:16,070\nWhat do we have here?\n\n1004\n00:58:16,070 --> 00:58:20,880\nThe CONS of two arguments, X\nand Y, is going to be that\n\n1005\n00:58:20,880 --> 00:58:25,020\nprocedure of one argument M,\nwhich supplies M to X and Y as\n\n1006\n00:58:25,020 --> 00:58:30,900\nbefore, but also to two\npermissions, the permission to\n\n1007\n00:58:30,900 --> 00:58:35,030\nset X to N and the permission\nto set Y to N, given that I\n\n1008\n00:58:35,030 --> 00:58:40,940\nhave an N.\n\n1009\n00:58:40,940 --> 00:58:44,040\nSo besides the things that\nI had here in Church's\n\n1010\n00:58:44,040 --> 00:58:50,990\ndefinition, what I have is\nthat the thing that CONS\n\n1011\n00:58:50,990 --> 00:58:55,900\nreturns will apply its argument\nto not just the\n\n1012\n00:58:55,900 --> 00:59:00,210\nvalues of the X and Y that the\nCONS is made of, but also\n\n1013\n00:59:00,210 --> 00:59:03,365\npermissions to set X and\nY to new values.\n\n1014\n00:59:03,365 --> 00:59:06,540\n\n\n1015\n00:59:06,540 --> 00:59:09,220\nNow, of course, just\nas before, CAR\n\n1016\n00:59:09,220 --> 00:59:11,690\nis exactly the same.\n\n1017\n00:59:11,690 --> 00:59:14,980\nThe CAR of X is nothing more\nthan applying X, as in\n\n1018\n00:59:14,980 --> 00:59:18,110\nChurch's definition, to a\nprocedure, in this case, of\n\n1019\n00:59:18,110 --> 00:59:22,550\nfour arguments, which selects\nout the first one.\n\n1020\n00:59:22,550 --> 00:59:28,750\nAnd just as we did before, that\nwill be the value of X\n\n1021\n00:59:28,750 --> 00:59:33,470\nthat was contained in the\nprocedure which is the result\n\n1022\n00:59:33,470 --> 00:59:36,260\nof evaluating this lambda\nexpression in the environment\n\n1023\n00:59:36,260 --> 00:59:37,920\nwhere X and Y are defined\nover here.\n\n1024\n00:59:37,920 --> 00:59:41,940\n\n\n1025\n00:59:41,940 --> 00:59:45,640\nThat's the value of CONS.\n\n1026\n00:59:45,640 --> 00:59:47,730\nNow, however, the\nexciting part.\n\n1027\n00:59:47,730 --> 00:59:48,960\nCDR, of course, is the same.\n\n1028\n00:59:48,960 --> 00:59:54,270\nThe exciting part, set CAR and\nset CDR. Well, they're nothing\n\n1029\n00:59:54,270 --> 00:59:55,800\nvery complicated anymore.\n\n1030\n00:59:55,800 --> 01:00:02,700\nSet CAR of a CONS X to a new\nvalue Y is nothing more than\n\n1031\n01:00:02,700 --> 01:00:06,097\napplying that CONS, which is\nthe procedure of four--the\n\n1032\n01:00:06,097 --> 01:00:09,160\nprocedure of one argument which\napplies its argument to\n\n1033\n01:00:09,160 --> 01:00:15,950\nfour things, to a procedure\nwhich is of four arguments--\n\n1034\n01:00:15,950 --> 01:00:19,450\nthe value of X, the value of\nY, permission to set X, the\n\n1035\n01:00:19,450 --> 01:00:21,390\npermission to set Y--\n\n1036\n01:00:21,390 --> 01:00:23,610\nand using it--using that\npermission to set\n\n1037\n01:00:23,610 --> 01:00:26,150\nX to the new value.\n\n1038\n01:00:26,150 --> 01:00:31,650\n\n\n1039\n01:00:31,650 --> 01:00:33,540\nAnd similarly, set-cdr\nis the same thing.\n\n1040\n01:00:33,540 --> 01:00:36,120\n\n\n1041\n01:00:36,120 --> 01:00:38,470\nSo what you've just seen is that\nI didn't introduce any\n\n1042\n01:00:38,470 --> 01:00:40,470\nnew primitives at all.\n\n1043\n01:00:40,470 --> 01:00:43,340\nWhether or not I want to\nimplement it this way is a\n\n1044\n01:00:43,340 --> 01:00:45,340\nmatter of engineering.\n\n1045\n01:00:45,340 --> 01:00:48,080\nAnd the answer is of course I\ndon't implement it this way\n\n1046\n01:00:48,080 --> 01:00:51,680\nfor reasons that have to\ndo with engineering.\n\n1047\n01:00:51,680 --> 01:00:55,170\nHowever in principle, logically,\nonce I introduced\n\n1048\n01:00:55,170 --> 01:00:57,515\none assignment operator,\nI've assigned--I've\n\n1049\n01:00:57,515 --> 01:00:58,765\nintroduced them all.\n\n1050\n01:00:58,765 --> 01:01:05,420\n\n\n1051\n01:01:05,420 --> 01:01:06,670\nAre there any questions?\n\n1052\n01:01:06,670 --> 01:01:09,200\n\n\n1053\n01:01:09,200 --> 01:01:12,040\nYes, David.\n\n1054\n01:01:12,040 --> 01:01:14,860\nAUDIENCE: I can follow you up\nuntil you get--I can follow\n\n1055\n01:01:14,860 --> 01:01:15,740\nall of that.\n\n1056\n01:01:15,740 --> 01:01:19,760\nBut when we bring in the\npermissions, defining CONS in\n\n1057\n01:01:19,760 --> 01:01:24,210\nterms of the lambda N, I don't\nfollow where N gets passed.\n\n1058\n01:01:24,210 --> 01:01:25,100\nPROFESSOR: Oh, I'm sorry.\n\n1059\n01:01:25,100 --> 01:01:26,340\nI'll show you.\n\n1060\n01:01:26,340 --> 01:01:27,360\nLet's follow it.\n\n1061\n01:01:27,360 --> 01:01:29,180\nOf course, we could do\nit on the blackboard.\n\n1062\n01:01:29,180 --> 01:01:30,170\nIt's not so hard.\n\n1063\n01:01:30,170 --> 01:01:32,450\nBut it's also easy here.\n\n1064\n01:01:32,450 --> 01:01:38,520\nSupposing I wish to set-cdr of\nX to Y. See that right there.\n\n1065\n01:01:38,520 --> 01:01:43,680\nset-cdr of X to Y. X is\npresumably a CONS, a thing\n\n1066\n01:01:43,680 --> 01:01:46,890\nresulting from evaluating\nCONS.\n\n1067\n01:01:46,890 --> 01:01:54,030\nTherefore X comes from a place\nover here, that that X is of\n\n1068\n01:01:54,030 --> 01:01:58,110\nthe result of evaluating\nthis lambda expression.\n\n1069\n01:01:58,110 --> 01:01:59,380\nRight?\n\n1070\n01:01:59,380 --> 01:02:04,475\nThat when I evaluated that\nlambda expression, I evaluated\n\n1071\n01:02:04,475 --> 01:02:07,700\nit in an environment\nwhere the arguments\n\n1072\n01:02:07,700 --> 01:02:08,950\nto CONS were defined.\n\n1073\n01:02:08,950 --> 01:02:11,750\n\n\n1074\n01:02:11,750 --> 01:02:14,530\nThat means that as free\nvariables in this lambda\n\n1075\n01:02:14,530 --> 01:02:18,670\nexpression, there is the--there\nare in the frame,\n\n1076\n01:02:18,670 --> 01:02:23,860\nwhich is the parent frame of\nthis lambda expression, the\n\n1077\n01:02:23,860 --> 01:02:27,470\nprocedure resulting from this\nlambda expression, X and Y\n\n1078\n01:02:27,470 --> 01:02:29,250\nhave places.\n\n1079\n01:02:29,250 --> 01:02:31,910\nAnd it's possible to set them.\n\n1080\n01:02:31,910 --> 01:02:35,380\nI set them to an N, which\nis the argument of the\n\n1081\n01:02:35,380 --> 01:02:37,010\npermission.\n\n1082\n01:02:37,010 --> 01:02:43,650\nThe permission is a procedure\nwhich is passed to M, which is\n\n1083\n01:02:43,650 --> 01:02:47,940\nthe argument that the CONS\nobject gets passed.\n\n1084\n01:02:47,940 --> 01:02:54,020\nNow, let's go back here in the\nset-cdr The CONS object, which\n\n1085\n01:02:54,020 --> 01:02:56,230\nis the first argument\nof set-cdr\n\n1086\n01:02:56,230 --> 01:02:57,480\ngets passed an argument.\n\n1087\n01:02:57,480 --> 01:03:00,260\n\n\n1088\n01:03:00,260 --> 01:03:02,910\nThat--there's a procedure of\nfour things, indeed, because\n\n1089\n01:03:02,910 --> 01:03:05,780\nthat's the same thing as this M\nover here, which is applied\n\n1090\n01:03:05,780 --> 01:03:07,920\nto four objects.\n\n1091\n01:03:07,920 --> 01:03:12,970\nThe object over here, SD, is,\nin fact, this permission.\n\n1092\n01:03:12,970 --> 01:03:15,470\n\n\n1093\n01:03:15,470 --> 01:03:19,930\nWhen I use SD, I apply\nit to Y, right there.\n\n1094\n01:03:19,930 --> 01:03:22,910\n\n\n1095\n01:03:22,910 --> 01:03:25,740\nSo that comes from this.\n\n1096\n01:03:25,740 --> 01:03:27,410\nAUDIENCE: So what do you--\n\n1097\n01:03:27,410 --> 01:03:31,420\nPROFESSOR: So to finish that,\nthe N that was here is the Y\n\n1098\n01:03:31,420 --> 01:03:34,160\nwhich is here.\n\n1099\n01:03:34,160 --> 01:03:34,810\nHow's that?\n\n1100\n01:03:34,810 --> 01:03:35,750\nAUDIENCE: Right, OK.\n\n1101\n01:03:35,750 --> 01:03:40,240\nNow, when you do a set-cdr,\nX is the value the\n\n1102\n01:03:40,240 --> 01:03:41,970\nCDR is going to become.\n\n1103\n01:03:41,970 --> 01:03:44,742\nPROFESSOR: The X over here.\n\n1104\n01:03:44,742 --> 01:03:46,200\nI'm sorry, that's not true.\n\n1105\n01:03:46,200 --> 01:03:48,720\nThe X is--set-cdr has\ntwo arguments--\n\n1106\n01:03:48,720 --> 01:03:56,150\nThe CONS I'm changing and the\nvalue I'm changing it to.\n\n1107\n01:03:56,150 --> 01:03:58,320\nSo you have them backwards,\nthat's all.\n\n1108\n01:03:58,320 --> 01:04:01,750\n\n\n1109\n01:04:01,750 --> 01:04:03,000\nAre there any other questions?\n\n1110\n01:04:03,000 --> 01:04:07,880\n\n\n1111\n01:04:07,880 --> 01:04:08,640\nWell, thank you.\n\n1112\n01:04:08,640 --> 01:04:09,890\nIt's time for lunch.\n\n1113\n01:04:09,890 --> 01:04:28,970\n\n"
  },
  {
    "path": "SrtEN/lec6a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:18,550\n\n\n1\n00:00:18,550 --> 00:00:21,230\nPROFESSOR: Well, last time Gerry\nreally let the cat out\n\n2\n00:00:21,230 --> 00:00:22,230\nof the bag.\n\n3\n00:00:22,230 --> 00:00:26,350\nHe introduced the idea\nof assignment.\n\n4\n00:00:26,350 --> 00:00:33,405\nAssignment and state.\n\n5\n00:00:33,405 --> 00:00:37,620\n\n\n6\n00:00:37,620 --> 00:00:41,500\nAnd as we started to see, the\nimplications of introducing\n\n7\n00:00:41,500 --> 00:00:43,860\nassignment and state into the\nlanguage are absolutely\n\n8\n00:00:43,860 --> 00:00:45,350\nfrightening.\n\n9\n00:00:45,350 --> 00:00:47,240\nFirst of all, the substitution\nmodel of\n\n10\n00:00:47,240 --> 00:00:48,865\nevaluation breaks down.\n\n11\n00:00:48,865 --> 00:00:52,210\nAnd we have to use this much\nmore complicated environment\n\n12\n00:00:52,210 --> 00:00:53,780\nmodel and this very mechanistic\nthing with\n\n13\n00:00:53,780 --> 00:00:56,530\ndiagrams, even to say what\nstatements in the programming\n\n14\n00:00:56,530 --> 00:00:58,130\nlanguage mean.\n\n15\n00:00:58,130 --> 00:01:00,260\nAnd that's not a mere\ntechnical point.\n\n16\n00:01:00,260 --> 00:01:03,090\nSee, it's not that we had this\nparticular substitution model\n\n17\n00:01:03,090 --> 00:01:05,200\nand, well, it doesn't quite\nwork, so we have to do\n\n18\n00:01:05,200 --> 00:01:05,870\nsomething else.\n\n19\n00:01:05,870 --> 00:01:10,730\nIt's that nothing like the\nsubstitution model can work.\n\n20\n00:01:10,730 --> 00:01:15,950\nBecause suddenly, a variable\nis not just something that\n\n21\n00:01:15,950 --> 00:01:18,080\nstands for a value.\n\n22\n00:01:18,080 --> 00:01:22,390\nA variable now has to somehow\nspecify a place\n\n23\n00:01:22,390 --> 00:01:23,630\nthat holds a value.\n\n24\n00:01:23,630 --> 00:01:25,885\nAnd the value that's in\nthat place can change.\n\n25\n00:01:25,885 --> 00:01:30,280\n\n\n26\n00:01:30,280 --> 00:01:39,110\nOr for instance, an expression\nlike f of x might have a side\n\n27\n00:01:39,110 --> 00:01:40,410\neffect in it.\n\n28\n00:01:40,410 --> 00:01:44,160\nSo if we say f of x and it has\nsome value, and then later we\n\n29\n00:01:44,160 --> 00:01:48,890\nsay f of x again, we might\nget a different value\n\n30\n00:01:48,890 --> 00:01:49,730\ndepending on the order.\n\n31\n00:01:49,730 --> 00:01:52,780\nSo suddenly, we have to think\nnot only about values but\n\n32\n00:01:52,780 --> 00:01:54,030\nabout time.\n\n33\n00:01:54,030 --> 00:01:57,970\n\n\n34\n00:01:57,970 --> 00:02:02,070\nAnd then things like pairs are\nno longer just their CARs and\n\n35\n00:02:02,070 --> 00:02:02,520\ntheir CDRs.\n\n36\n00:02:02,520 --> 00:02:06,310\nA pair now is not quite its CAR\nand its CDR. It's rather\n\n37\n00:02:06,310 --> 00:02:08,449\nits identity.\n\n38\n00:02:08,449 --> 00:02:11,650\nSo a pair has identity.\n\n39\n00:02:11,650 --> 00:02:12,900\nIt's an object.\n\n40\n00:02:12,900 --> 00:02:21,330\n\n\n41\n00:02:21,330 --> 00:02:26,280\nAnd two pairs that have the same\nCAR and CDR might be the\n\n42\n00:02:26,280 --> 00:02:29,650\nsame or different, because\nsuddenly we have to worry\n\n43\n00:02:29,650 --> 00:02:30,900\nabout sharing.\n\n44\n00:02:30,900 --> 00:02:34,960\n\n\n45\n00:02:34,960 --> 00:02:38,910\nSo all of these things enter\nas soon as we introduce\n\n46\n00:02:38,910 --> 00:02:40,480\nassignment.\n\n47\n00:02:40,480 --> 00:02:43,340\nSee, this is a really far cry\nfrom where we started with\n\n48\n00:02:43,340 --> 00:02:45,400\nsubstitution.\n\n49\n00:02:45,400 --> 00:02:50,420\nIt's a technically harder way\nof looking at things because\n\n50\n00:02:50,420 --> 00:02:52,710\nwe have to think more\nmechanistically about our\n\n51\n00:02:52,710 --> 00:02:53,540\nprogramming language.\n\n52\n00:02:53,540 --> 00:02:55,960\nWe can't just think about\nit as mathematics.\n\n53\n00:02:55,960 --> 00:02:59,860\nIt's philosophically harder,\nbecause suddenly there are all\n\n54\n00:02:59,860 --> 00:03:02,020\nthese funny issues about what\ndoes it mean that something\n\n55\n00:03:02,020 --> 00:03:04,050\nchanges or that two things\nare the same.\n\n56\n00:03:04,050 --> 00:03:07,910\nAnd also, it's programming\nharder, because as Gerry\n\n57\n00:03:07,910 --> 00:03:10,070\nshowed last time, there are all\nthese bugs having to do\n\n58\n00:03:10,070 --> 00:03:14,420\nwith bad sequencing and aliasing\nthat just don't exist\n\n59\n00:03:14,420 --> 00:03:18,210\nin a language where we don't\nworry about objects.\n\n60\n00:03:18,210 --> 00:03:23,635\nWell, how'd we get\ninto this mess?\n\n61\n00:03:23,635 --> 00:03:27,500\nRemember what we did, the reason\nwe got into this is\n\n62\n00:03:27,500 --> 00:03:35,750\nbecause we were looking to\nbuild modular systems. We\n\n63\n00:03:35,750 --> 00:03:40,250\nwanted to build systems that\nfall apart into chunks that\n\n64\n00:03:40,250 --> 00:03:42,760\nseem natural.\n\n65\n00:03:42,760 --> 00:03:46,260\nSo for instance, we want to take\na random number generator\n\n66\n00:03:46,260 --> 00:03:48,660\nand package up the state of that\nrandom number generator\n\n67\n00:03:48,660 --> 00:03:52,840\ninside of it so that we can\nseparate the idea of picking\n\n68\n00:03:52,840 --> 00:03:56,640\nrandom numbers from the general\nMonte Carlo strategy\n\n69\n00:03:56,640 --> 00:03:59,740\nof estimating something and\nseparate that from the\n\n70\n00:03:59,740 --> 00:04:03,060\nparticular way that you work\nwith random numbers in that\n\n71\n00:04:03,060 --> 00:04:06,980\nformula developed by\nCesaro for pi.\n\n72\n00:04:06,980 --> 00:04:11,400\nAnd similarly, when we go off\nand construct some models of\n\n73\n00:04:11,400 --> 00:04:15,440\nthings, if we go off and model\na system that we see in the\n\n74\n00:04:15,440 --> 00:04:19,050\nreal world, we'd like our\nprogram to break into natural\n\n75\n00:04:19,050 --> 00:04:22,310\npieces, pieces that mirror the\nparts of the system that we\n\n76\n00:04:22,310 --> 00:04:24,900\nsee in the real world.\n\n77\n00:04:24,900 --> 00:04:28,780\nSo for example, if we look at\na digital circuit, we say,\n\n78\n00:04:28,780 --> 00:04:33,910\ngee, there's a circuit and\nit has a piece and\n\n79\n00:04:33,910 --> 00:04:35,160\nit has another piece.\n\n80\n00:04:35,160 --> 00:04:40,100\n\n\n81\n00:04:40,100 --> 00:04:43,580\nAnd these different pieces\nsort of have identity.\n\n82\n00:04:43,580 --> 00:04:45,550\nThey have state.\n\n83\n00:04:45,550 --> 00:04:48,580\nAnd the state sits\non these wires.\n\n84\n00:04:48,580 --> 00:04:51,020\nAnd we think of this piece as\nan object that's different\n\n85\n00:04:51,020 --> 00:04:52,610\nfrom that as an object.\n\n86\n00:04:52,610 --> 00:04:54,400\nAnd when we watch the system\nchange, we think about a\n\n87\n00:04:54,400 --> 00:04:57,500\nsignal coming in here and\nchanging a state that might be\n\n88\n00:04:57,500 --> 00:04:59,860\nhere and going here and\ninteracting with a state that\n\n89\n00:04:59,860 --> 00:05:02,170\nmight be stored there,\nand so on and so on.\n\n90\n00:05:02,170 --> 00:05:06,860\n\n\n91\n00:05:06,860 --> 00:05:12,760\nSo what we'd like is we'd like\nto build in the computer\n\n92\n00:05:12,760 --> 00:05:17,340\nsystems that fall into pieces\nthat mirror our view of\n\n93\n00:05:17,340 --> 00:05:19,870\nreality, of the way that the\nactual systems we're modeling\n\n94\n00:05:19,870 --> 00:05:23,365\nseem to fall into pieces.\n\n95\n00:05:23,365 --> 00:05:28,970\nWell, maybe the reason that\nbuilding systems like this\n\n96\n00:05:28,970 --> 00:05:31,600\nseems to introduce such\ntechnical complications has\n\n97\n00:05:31,600 --> 00:05:33,610\nnothing to do with computers.\n\n98\n00:05:33,610 --> 00:05:37,960\nSee, maybe the real reason that\nwe pay such a price to\n\n99\n00:05:37,960 --> 00:05:41,910\nwrite programs that mirror our\nview of reality is that we\n\n100\n00:05:41,910 --> 00:05:44,550\nhave the wrong view\nof reality.\n\n101\n00:05:44,550 --> 00:05:47,460\nSee, maybe time is just\nan illusion, and\n\n102\n00:05:47,460 --> 00:05:50,150\nnothing ever changes.\n\n103\n00:05:50,150 --> 00:05:52,910\nSee, for example, if I take this\nchalk, and we say, gee,\n\n104\n00:05:52,910 --> 00:05:55,820\nthis is an object and\nit has a state.\n\n105\n00:05:55,820 --> 00:05:59,710\nAt each moment it has a position\nand a velocity.\n\n106\n00:05:59,710 --> 00:06:01,240\nAnd if we do something,\nthat state can change.\n\n107\n00:06:01,240 --> 00:06:04,340\n\n\n108\n00:06:04,340 --> 00:06:07,900\nBut if you studied any\nrelativity, for instance, you\n\n109\n00:06:07,900 --> 00:06:09,760\nknow that you don't think of\nthe path of that chalk as\n\n110\n00:06:09,760 --> 00:06:11,340\nsomething that goes on\ninstant by instant.\n\n111\n00:06:11,340 --> 00:06:13,870\nIt's more insightful to think\nof that whole chalk's\n\n112\n00:06:13,870 --> 00:06:16,020\nexistence as a path\nin space-time.\n\n113\n00:06:16,020 --> 00:06:18,040\nthat's all splayed out.\n\n114\n00:06:18,040 --> 00:06:19,840\nThere aren't individual\npositions and velocities.\n\n115\n00:06:19,840 --> 00:06:24,640\nThere's just its unchanging\nexistence in space-time.\n\n116\n00:06:24,640 --> 00:06:28,080\nSimilarly, if we look at this\nelectrical system, if we\n\n117\n00:06:28,080 --> 00:06:32,450\nimagine this electrical system\nis implementing some sort of\n\n118\n00:06:32,450 --> 00:06:35,730\nsignal processing system, the\nsignal processing engineer who\n\n119\n00:06:35,730 --> 00:06:39,010\nput that thing together doesn't\nthink of it as, well,\n\n120\n00:06:39,010 --> 00:06:41,490\nat each instance there's\na voltage coming in.\n\n121\n00:06:41,490 --> 00:06:43,340\nAnd that translates\ninto something.\n\n122\n00:06:43,340 --> 00:06:46,400\nAnd that affects the state over\nhere, which changes the\n\n123\n00:06:46,400 --> 00:06:46,810\nstate over here.\n\n124\n00:06:46,810 --> 00:06:49,060\nNobody putting together a\nsignal processing system\n\n125\n00:06:49,060 --> 00:06:50,420\nthinks about it like that.\n\n126\n00:06:50,420 --> 00:06:56,830\nInstead, you say there's\nthis signal that's\n\n127\n00:06:56,830 --> 00:06:58,060\nsplayed out over time.\n\n128\n00:06:58,060 --> 00:07:01,100\nAnd if this is acting as a\nfilter, this whole thing\n\n129\n00:07:01,100 --> 00:07:09,570\ntransforms this whole thing for\nsome sort of other output.\n\n130\n00:07:09,570 --> 00:07:11,790\nYou don't think of it as what's\nhappening instant by\n\n131\n00:07:11,790 --> 00:07:14,160\ninstant as the state\nof these things.\n\n132\n00:07:14,160 --> 00:07:17,990\nAnd somehow you think of this\nbox as a whole thing, not as\n\n133\n00:07:17,990 --> 00:07:20,980\nlittle pieces sending messages\nof state to each other at\n\n134\n00:07:20,980 --> 00:07:22,230\nparticular instants.\n\n135\n00:07:22,230 --> 00:07:28,250\n\n\n136\n00:07:28,250 --> 00:07:30,130\nWell, today we're going to\nlook at another way to\n\n137\n00:07:30,130 --> 00:07:34,260\ndecompose systems that's more\nlike the signal processing\n\n138\n00:07:34,260 --> 00:07:37,050\nengineer's view of the world\nthan it is like thinking about\n\n139\n00:07:37,050 --> 00:07:41,130\nobjects that communicate\nsending messages.\n\n140\n00:07:41,130 --> 00:07:43,310\nThat's called stream\nprocessing.\n\n141\n00:07:43,310 --> 00:07:54,570\n\n\n142\n00:07:54,570 --> 00:08:01,790\nAnd we're going to start by\nshowing how we can make our\n\n143\n00:08:01,790 --> 00:08:08,550\nprograms more uniform and see\na lot more commonality if we\n\n144\n00:08:08,550 --> 00:08:12,490\nthrow out of these programs\nwhat you might say is an\n\n145\n00:08:12,490 --> 00:08:17,210\ninordinate concern with\nworrying about time.\n\n146\n00:08:17,210 --> 00:08:19,910\nLet me start by comparing\ntwo procedures.\n\n147\n00:08:19,910 --> 00:08:23,260\n\n\n148\n00:08:23,260 --> 00:08:25,690\nThe first one does this.\n\n149\n00:08:25,690 --> 00:08:27,770\nWe imagine that there's\na tree.\n\n150\n00:08:27,770 --> 00:08:30,400\n\n\n151\n00:08:30,400 --> 00:08:33,179\nSay there's a tree\nof integers.\n\n152\n00:08:33,179 --> 00:08:34,429\nIt's a binary tree.\n\n153\n00:08:34,429 --> 00:08:39,100\n\n\n154\n00:08:39,100 --> 00:08:40,230\nSo it looks like this.\n\n155\n00:08:40,230 --> 00:08:44,990\nAnd there's integers in\neach of the nodes.\n\n156\n00:08:44,990 --> 00:08:51,000\nAnd what we would like to\ncompute is for each odd number\n\n157\n00:08:51,000 --> 00:08:54,210\nsitting here, we'd like to find\nthe square and then sum\n\n158\n00:08:54,210 --> 00:08:57,210\nup all those squares.\n\n159\n00:08:57,210 --> 00:08:59,480\nWell, that should be a familiar\nkind of thing.\n\n160\n00:08:59,480 --> 00:09:02,930\nThere's a recursive strategy\nfor doing it.\n\n161\n00:09:02,930 --> 00:09:04,880\nWe look at each leaf, and\neither it's going to\n\n162\n00:09:04,880 --> 00:09:06,690\ncontribute the square of\nthe number if it's odd\n\n163\n00:09:06,690 --> 00:09:08,680\nor 0 if it's even.\n\n164\n00:09:08,680 --> 00:09:13,280\nAnd then recursively, we can say\nat each tree, the sum of\n\n165\n00:09:13,280 --> 00:09:15,330\nall of them is the sum coming\nfrom the right branch and the\n\n166\n00:09:15,330 --> 00:09:17,640\nleft branch, and recursively\ndown through the nodes.\n\n167\n00:09:17,640 --> 00:09:20,360\nAnd that's a familiar way of\nthinking about programming.\n\n168\n00:09:20,360 --> 00:09:23,960\nLet's actually look at\nthat on the slide.\n\n169\n00:09:23,960 --> 00:09:27,960\nWe say to sum the odd squares\nin a tree, well, there's a\n\n170\n00:09:27,960 --> 00:09:30,520\ntest. Either it's a leaf node,\nand we're going to check to\n\n171\n00:09:30,520 --> 00:09:34,710\nsee if it's an integer, and then\neither it's odd, in which\n\n172\n00:09:34,710 --> 00:09:37,160\nwe take the square,\nor else it's 0.\n\n173\n00:09:37,160 --> 00:09:40,260\nAnd then the sum of the whole\nthing is the sum coming from\n\n174\n00:09:40,260 --> 00:09:42,120\nthe left branch and\nthe right branch.\n\n175\n00:09:42,120 --> 00:09:46,340\n\n\n176\n00:09:46,340 --> 00:09:51,560\nOK, well, let me contrast that\nwith a second problem.\n\n177\n00:09:51,560 --> 00:09:55,810\nSuppose I give you an integer\nn, and then some function to\n\n178\n00:09:55,810 --> 00:09:59,270\ncompute of the first of each\ninteger in 1 through n.\n\n179\n00:09:59,270 --> 00:10:01,810\nAnd then I want to collect\ntogether in a list all those\n\n180\n00:10:01,810 --> 00:10:05,600\nfunction values that satisfy\nsome property.\n\n181\n00:10:05,600 --> 00:10:06,880\nThat's a general\nkind of thing.\n\n182\n00:10:06,880 --> 00:10:09,750\nLet's say to be specific, let's\nimagine that for each\n\n183\n00:10:09,750 --> 00:10:11,270\ninteger, k, we're\ngoing to compute\n\n184\n00:10:11,270 --> 00:10:14,210\nthe k Fibonacci number.\n\n185\n00:10:14,210 --> 00:10:17,550\nAnd then we'll see which of\nthose are odd and assemble\n\n186\n00:10:17,550 --> 00:10:19,050\nthose into a list.\n\n187\n00:10:19,050 --> 00:10:20,710\nSo here's a procedure\nthat does that.\n\n188\n00:10:20,710 --> 00:10:23,730\n\n\n189\n00:10:23,730 --> 00:10:26,240\nFind the odd Fibonacci numbers\namong the first n.\n\n190\n00:10:26,240 --> 00:10:28,910\nAnd here is a standard loop the\nway we've been writing it.\n\n191\n00:10:28,910 --> 00:10:30,800\nThis is a recursion.\n\n192\n00:10:30,800 --> 00:10:33,740\nIt's a loop on k, and says if\nk is bigger than n, it's the\n\n193\n00:10:33,740 --> 00:10:36,990\nempty list. Otherwise we compute\nthe k-th Fibonacci\n\n194\n00:10:36,990 --> 00:10:40,370\nnumber, call that f.\n\n195\n00:10:40,370 --> 00:10:45,180\nIf it's odd, we CONS it on\nto the list starting\n\n196\n00:10:45,180 --> 00:10:47,690\nwith the next one.\n\n197\n00:10:47,690 --> 00:10:50,390\nAnd otherwise, we just\ntake the next one.\n\n198\n00:10:50,390 --> 00:10:52,000\nAnd this is the standard\nway we've been\n\n199\n00:10:52,000 --> 00:10:53,000\nwriting iterative loops.\n\n200\n00:10:53,000 --> 00:10:57,600\nAnd we start off calling\nthat loop with 1.\n\n201\n00:10:57,600 --> 00:11:01,600\nOK, so there are\ntwo procedures.\n\n202\n00:11:01,600 --> 00:11:02,900\nThose procedures look\nvery different.\n\n203\n00:11:02,900 --> 00:11:04,390\nThey have very different\nstructures.\n\n204\n00:11:04,390 --> 00:11:07,740\nYet from a certain point of\nview, those procedures are\n\n205\n00:11:07,740 --> 00:11:11,330\nreally doing very much\nthe same thing.\n\n206\n00:11:11,330 --> 00:11:14,930\nSo if I was talking like a\nsignal processing engineer,\n\n207\n00:11:14,930 --> 00:11:25,730\nwhat I might say is that the\nfirst procedure enumerates the\n\n208\n00:11:25,730 --> 00:11:26,980\nleaves of a tree.\n\n209\n00:11:26,980 --> 00:11:31,160\n\n\n210\n00:11:31,160 --> 00:11:33,510\nAnd then we can think of a\nsignal coming out of that,\n\n211\n00:11:33,510 --> 00:11:35,330\nwhich is all the leaves.\n\n212\n00:11:35,330 --> 00:11:43,970\nWe'll filter them to see which\nones are odd, put them through\n\n213\n00:11:43,970 --> 00:11:45,190\nsome kind of filter.\n\n214\n00:11:45,190 --> 00:11:49,000\nWe'll then put them through\na kind of transducer.\n\n215\n00:11:49,000 --> 00:11:51,420\nAnd for each one of those\nthings, we'll take the square.\n\n216\n00:11:51,420 --> 00:11:54,200\n\n\n217\n00:11:54,200 --> 00:11:58,290\nAnd then we'll accumulate\nall of those.\n\n218\n00:11:58,290 --> 00:12:00,570\nWe'll accumulate them by\nsticking them together with\n\n219\n00:12:00,570 --> 00:12:03,340\naddition starting from 0.\n\n220\n00:12:03,340 --> 00:12:07,140\n\n\n221\n00:12:07,140 --> 00:12:08,210\nThat's the first program.\n\n222\n00:12:08,210 --> 00:12:10,620\nThe second program, I can\ndescribe in a very, very\n\n223\n00:12:10,620 --> 00:12:11,780\nsimilar way.\n\n224\n00:12:11,780 --> 00:12:17,450\nI'll say, we'll enumerate the\nnumbers on this interval, for\n\n225\n00:12:17,450 --> 00:12:19,080\nthe interval 1 through n.\n\n226\n00:12:19,080 --> 00:12:22,500\n\n\n227\n00:12:22,500 --> 00:12:28,080\nWe'll, for each one, compute the\nFibonacci number, put them\n\n228\n00:12:28,080 --> 00:12:29,270\nthrough a transducer.\n\n229\n00:12:29,270 --> 00:12:31,780\nWe'll then take the result\nof that, and we'll\n\n230\n00:12:31,780 --> 00:12:35,976\nfilter it for oddness.\n\n231\n00:12:35,976 --> 00:12:39,350\nAnd then we'll take those and\nput them into an accumulator.\n\n232\n00:12:39,350 --> 00:12:41,730\nThis time we'll build up a list,\nso we'll accumulate with\n\n233\n00:12:41,730 --> 00:12:47,110\nCONS starting from\nthe empty list.\n\n234\n00:12:47,110 --> 00:12:50,940\nSo this way of looking at the\nprogram makes the two seem\n\n235\n00:12:50,940 --> 00:12:51,900\nvery, very similar.\n\n236\n00:12:51,900 --> 00:12:55,880\nThe problem is that that\ncommonality is completely\n\n237\n00:12:55,880 --> 00:12:58,050\nobscured when we look at the\nprocedures we wrote.\n\n238\n00:12:58,050 --> 00:13:02,670\nLet's go back and look at some\nodd squares again, and say\n\n239\n00:13:02,670 --> 00:13:06,300\nthings like, where's\nthe enumerator?\n\n240\n00:13:06,300 --> 00:13:08,140\nWhere's the enumerator\nin this program?\n\n241\n00:13:08,140 --> 00:13:11,230\nWell, it's not in one place.\n\n242\n00:13:11,230 --> 00:13:15,990\nIt's a little bit in this\nleaf-node test,\n\n243\n00:13:15,990 --> 00:13:17,160\nwhich is going to stop.\n\n244\n00:13:17,160 --> 00:13:19,380\nIt's a little bit in the\nrecursive structure of the\n\n245\n00:13:19,380 --> 00:13:20,630\nthing itself.\n\n246\n00:13:20,630 --> 00:13:23,150\n\n\n247\n00:13:23,150 --> 00:13:24,120\nWhere's the accumulator?\n\n248\n00:13:24,120 --> 00:13:25,680\nThe accumulator isn't\nin one place either.\n\n249\n00:13:25,680 --> 00:13:32,180\nIt's partly in this 0 and\npartly in this plus.\n\n250\n00:13:32,180 --> 00:13:34,510\nIt's not there as a thing\nthat we can look at.\n\n251\n00:13:34,510 --> 00:13:40,550\nSimilarly, if we look at odd\nFibs, that's also, in some\n\n252\n00:13:40,550 --> 00:13:42,940\nsense, an enumerator and\nan accumulator, but\n\n253\n00:13:42,940 --> 00:13:44,470\nit looks very different.\n\n254\n00:13:44,470 --> 00:13:49,260\nBecause partly, the enumerator\nis here in this greater than\n\n255\n00:13:49,260 --> 00:13:52,100\nsign in the test. And partly\nit's in this whole recursive\n\n256\n00:13:52,100 --> 00:13:55,680\nstructure in the loop, and\nthe way that we call it.\n\n257\n00:13:55,680 --> 00:13:58,100\nAnd then similarly, that's also\nmixed up in there with\n\n258\n00:13:58,100 --> 00:14:01,010\nthe accumulator, which is partly\nover there and partly\n\n259\n00:14:01,010 --> 00:14:03,600\nover there.\n\n260\n00:14:03,600 --> 00:14:09,790\nSo these very, very natural\npieces, these very natural\n\n261\n00:14:09,790 --> 00:14:13,770\nboxes here don't appear in our\nprograms. Because they're kind\n\n262\n00:14:13,770 --> 00:14:14,360\nof mixed up.\n\n263\n00:14:14,360 --> 00:14:16,290\nThe programs don't chop things\nup in the right way.\n\n264\n00:14:16,290 --> 00:14:19,450\n\n\n265\n00:14:19,450 --> 00:14:22,240\nGoing back to this fundamental\nprinciple of computer science\n\n266\n00:14:22,240 --> 00:14:24,620\nthat in order to control\nsomething, you need the name\n\n267\n00:14:24,620 --> 00:14:27,820\nof it, we don't really have\ncontrol over thinking about\n\n268\n00:14:27,820 --> 00:14:30,500\nthings this way because we don't\nhave our hands in them\n\n269\n00:14:30,500 --> 00:14:31,060\nexplicitly.\n\n270\n00:14:31,060 --> 00:14:35,510\nWe don't have a good language\nfor talking about them.\n\n271\n00:14:35,510 --> 00:14:42,850\nWell, let's invent an\nappropriate language in which\n\n272\n00:14:42,850 --> 00:14:44,515\nwe can build these pieces.\n\n273\n00:14:44,515 --> 00:14:48,650\nThe key to the language is these\nguys, is what is these\n\n274\n00:14:48,650 --> 00:14:50,480\nthings I called signals?\n\n275\n00:14:50,480 --> 00:14:52,070\nWhat are these things that\nare flying on the\n\n276\n00:14:52,070 --> 00:14:53,320\narrows between the boxes?\n\n277\n00:14:53,320 --> 00:14:56,880\n\n\n278\n00:14:56,880 --> 00:15:02,840\nWell, those things are going to\nbe data structures called\n\n279\n00:15:02,840 --> 00:15:04,770\nstreams. That's going\nto be the key to\n\n280\n00:15:04,770 --> 00:15:07,980\ninventing this language.\n\n281\n00:15:07,980 --> 00:15:08,600\nWhat's a stream?\n\n282\n00:15:08,600 --> 00:15:10,820\nWell, a stream is, like\nanything else, a data\n\n283\n00:15:10,820 --> 00:15:12,220\nabstraction.\n\n284\n00:15:12,220 --> 00:15:15,000\nSo I should tell you what\nits selectors and\n\n285\n00:15:15,000 --> 00:15:16,870\nconstructors are.\n\n286\n00:15:16,870 --> 00:15:20,185\nFor a stream, we're going to\nhave one constructor that's\n\n287\n00:15:20,185 --> 00:15:21,435\ncalled CONS-stream.\n\n288\n00:15:21,435 --> 00:15:25,690\n\n\n289\n00:15:25,690 --> 00:15:29,060\nCONS-stream is going to put two\nthings together to form a\n\n290\n00:15:29,060 --> 00:15:32,040\nthing called a stream.\n\n291\n00:15:32,040 --> 00:15:34,250\nAnd then to extract things from\nthe stream, we're going\n\n292\n00:15:34,250 --> 00:15:38,010\nto have a selector called\nthe head of the stream.\n\n293\n00:15:38,010 --> 00:15:41,340\nSo if I have a stream, I\ncan take its head or I\n\n294\n00:15:41,340 --> 00:15:44,720\ncan take its tail.\n\n295\n00:15:44,720 --> 00:15:48,290\nAnd remember, I have to tell you\nGeorge's contract here to\n\n296\n00:15:48,290 --> 00:15:53,160\ntell you what the axioms\nare that relate these.\n\n297\n00:15:53,160 --> 00:16:04,080\nAnd it's going to be for any\nx and y, if I form the\n\n298\n00:16:04,080 --> 00:16:11,420\nCONS-stream and take the head,\nthe head of CONS-stream of x\n\n299\n00:16:11,420 --> 00:16:26,590\nand y is going to be x and the\ntail of CONS-stream of x and y\n\n300\n00:16:26,590 --> 00:16:28,440\nis going to be y.\n\n301\n00:16:28,440 --> 00:16:31,180\nSo those are the constructor,\ntwo selectors for\n\n302\n00:16:31,180 --> 00:16:34,750\nstreams, and an axiom.\n\n303\n00:16:34,750 --> 00:16:36,980\nThere's something fishy here.\n\n304\n00:16:36,980 --> 00:16:41,060\nSo you might notice that these\nare exactly the axioms for\n\n305\n00:16:41,060 --> 00:16:46,100\nCONS, CAR, and CDR. If instead\nof writing CONS-stream I wrote\n\n306\n00:16:46,100 --> 00:16:50,810\nCONS and I said head was the\nCAR and tail was the CDR,\n\n307\n00:16:50,810 --> 00:16:52,810\nthose are exactly the\naxioms for pairs.\n\n308\n00:16:52,810 --> 00:16:55,130\nAnd in fact, there's\nanother thing here.\n\n309\n00:16:55,130 --> 00:17:02,930\nWe're going to have a thing\ncalled the-empty-stream, which\n\n310\n00:17:02,930 --> 00:17:08,319\nis like the-empty-list.\n\n311\n00:17:08,319 --> 00:17:10,030\nSo why am I introducing\nthis terminology?\n\n312\n00:17:10,030 --> 00:17:12,780\nWhy don't I just keep talking\nabout pairs and lists?\n\n313\n00:17:12,780 --> 00:17:15,510\nWell, we'll see.\n\n314\n00:17:15,510 --> 00:17:18,440\nFor now, if you like, why don't\nyou just pretend that\n\n315\n00:17:18,440 --> 00:17:21,560\nstreams really are just a\nterminology for lists.\n\n316\n00:17:21,560 --> 00:17:24,890\nAnd we'll see in a little while\nwhy we want to keep this\n\n317\n00:17:24,890 --> 00:17:28,150\nextra abstraction layer and\nnot just call them lists.\n\n318\n00:17:28,150 --> 00:17:32,300\n\n\n319\n00:17:32,300 --> 00:17:34,860\nOK, now that we have streams, we\ncan start constructing the\n\n320\n00:17:34,860 --> 00:17:38,990\npieces of the language to\noperate on streams. And there\n\n321\n00:17:38,990 --> 00:17:41,330\nare a whole bunch of very useful\nthings that we could\n\n322\n00:17:41,330 --> 00:17:42,120\nstart making.\n\n323\n00:17:42,120 --> 00:17:54,850\nFor instance, we'll make our map\nbox to take a stream, s,\n\n324\n00:17:54,850 --> 00:18:00,400\nand a procedure, and to generate\na new stream which\n\n325\n00:18:00,400 --> 00:18:03,640\nhas as its elements the\nprocedure applied to all the\n\n326\n00:18:03,640 --> 00:18:05,666\nsuccessive elements of s.\n\n327\n00:18:05,666 --> 00:18:07,400\nIn fact, we've seen\nthis before.\n\n328\n00:18:07,400 --> 00:18:10,950\nThis is the procedure map\nthat we did with lists.\n\n329\n00:18:10,950 --> 00:18:14,000\nAnd you see it's exactly map,\nexcept we're testing for\n\n330\n00:18:14,000 --> 00:18:14,650\nempty-stream.\n\n331\n00:18:14,650 --> 00:18:15,560\nOh, I forgot to mention that.\n\n332\n00:18:15,560 --> 00:18:19,420\nEmpty-stream is like the null\ntest. So if it's empty, we\n\n333\n00:18:19,420 --> 00:18:20,510\ngenerate the empty stream.\n\n334\n00:18:20,510 --> 00:18:24,700\nOtherwise, we form a new stream\nwhose first element is\n\n335\n00:18:24,700 --> 00:18:28,950\nthe procedure applied to the\nhead of the stream, and whose\n\n336\n00:18:28,950 --> 00:18:31,570\nrest is gotten by mapping along\nwith the procedure down\n\n337\n00:18:31,570 --> 00:18:33,140\nthe tail of the stream.\n\n338\n00:18:33,140 --> 00:18:34,920\nSo that looks exactly like\nthe map procedure\n\n339\n00:18:34,920 --> 00:18:37,030\nwe looked at before.\n\n340\n00:18:37,030 --> 00:18:38,350\nHere's another useful thing.\n\n341\n00:18:38,350 --> 00:18:40,460\nFilter, this is our\nfilter box.\n\n342\n00:18:40,460 --> 00:18:43,890\nWe're going to have a predicate\nand a stream.\n\n343\n00:18:43,890 --> 00:18:46,720\nWe're going to make a new stream\nthat consists of all\n\n344\n00:18:46,720 --> 00:18:48,310\nthe elements of the\noriginal one\n\n345\n00:18:48,310 --> 00:18:50,160\nthat satisfy the predicate.\n\n346\n00:18:50,160 --> 00:18:51,270\nThat's case analysis.\n\n347\n00:18:51,270 --> 00:18:53,140\nWhen there's nothing\nin the stream, we\n\n348\n00:18:53,140 --> 00:18:56,280\nreturn the empty stream.\n\n349\n00:18:56,280 --> 00:19:00,060\nWe test the predicate on\nthe head of the stream.\n\n350\n00:19:00,060 --> 00:19:03,520\nAnd if it's true, we add the\nhead of the stream onto the\n\n351\n00:19:03,520 --> 00:19:08,220\nresult of filtering the\ntail of the stream.\n\n352\n00:19:08,220 --> 00:19:10,870\nAnd otherwise, if that predicate\nwas false, we just\n\n353\n00:19:10,870 --> 00:19:13,500\nfilter the tail of the stream.\n\n354\n00:19:13,500 --> 00:19:16,595\nRight, so there's filter.\n\n355\n00:19:16,595 --> 00:19:18,560\nLet me run through a couple\nmore rather quickly.\n\n356\n00:19:18,560 --> 00:19:20,880\nThey're all in the book and\nyou can look at them.\n\n357\n00:19:20,880 --> 00:19:22,110\nLet me just flash through.\n\n358\n00:19:22,110 --> 00:19:23,260\nHere's accumulate.\n\n359\n00:19:23,260 --> 00:19:27,690\nAccumulate takes a way of\ncombining things and an\n\n360\n00:19:27,690 --> 00:19:31,560\ninitial value in a stream and\nsticks them all together.\n\n361\n00:19:31,560 --> 00:19:33,970\nIf the stream's empty, it's\njust the initial value.\n\n362\n00:19:33,970 --> 00:19:36,930\nOtherwise, we combine the head\nof the stream with the result\n\n363\n00:19:36,930 --> 00:19:39,550\nof accumulating the tail of the\nstream starting from the\n\n364\n00:19:39,550 --> 00:19:40,900\ninitial value.\n\n365\n00:19:40,900 --> 00:19:42,830\nSo that's what I'd use to add\nup everything in the stream.\n\n366\n00:19:42,830 --> 00:19:45,830\nI'd accumulate with plus.\n\n367\n00:19:45,830 --> 00:19:48,060\nHow would I enumerate the\nleaves of a tree?\n\n368\n00:19:48,060 --> 00:19:54,530\nWell, if the tree is just a leaf\nitself, I make something\n\n369\n00:19:54,530 --> 00:19:56,640\nwhich only has that\nnode in it.\n\n370\n00:19:56,640 --> 00:20:01,100\nOtherwise, I append together the\nstuff of enumerating the\n\n371\n00:20:01,100 --> 00:20:04,340\nleft branch and the\nright branch.\n\n372\n00:20:04,340 --> 00:20:08,130\nAnd then append here is like the\nordinary append on lists.\n\n373\n00:20:08,130 --> 00:20:13,190\n\n\n374\n00:20:13,190 --> 00:20:13,850\nYou can look at that.\n\n375\n00:20:13,850 --> 00:20:16,410\nThat's analogous to the\nordinary procedure for\n\n376\n00:20:16,410 --> 00:20:19,150\nappending two lists.\n\n377\n00:20:19,150 --> 00:20:21,810\nHow would I enumerate\nan interval?\n\n378\n00:20:21,810 --> 00:20:24,500\nThis will take two integers, low\nand high, and generate a\n\n379\n00:20:24,500 --> 00:20:28,106\nstream of the integers going\nfrom low to high.\n\n380\n00:20:28,106 --> 00:20:31,890\nAnd we can make a whole\nbunch of pieces.\n\n381\n00:20:31,890 --> 00:20:34,860\nSo that's a little language of\ntalking about streams. Once we\n\n382\n00:20:34,860 --> 00:20:37,670\nhave streams, we can build\nthings for manipulating them.\n\n383\n00:20:37,670 --> 00:20:40,200\nAgain, we're making\na language.\n\n384\n00:20:40,200 --> 00:20:41,270\nAnd now we can start expressing\n\n385\n00:20:41,270 --> 00:20:43,060\nthings in this language.\n\n386\n00:20:43,060 --> 00:20:46,590\nHere's our original procedure\nfor summing the odd\n\n387\n00:20:46,590 --> 00:20:47,310\nsquares in a tree.\n\n388\n00:20:47,310 --> 00:20:52,210\nAnd you'll notice it looks\nexactly now like the block\n\n389\n00:20:52,210 --> 00:20:54,590\ndiagram, like the signal\nprocessing block diagram.\n\n390\n00:20:54,590 --> 00:21:00,230\nSo to sum the odd squares in a\ntree, we enumerate the leaves\n\n391\n00:21:00,230 --> 00:21:01,320\nof the tree.\n\n392\n00:21:01,320 --> 00:21:04,830\nWe filter that for oddness.\n\n393\n00:21:04,830 --> 00:21:06,220\nWe map that for squareness.\n\n394\n00:21:06,220 --> 00:21:09,320\n\n\n395\n00:21:09,320 --> 00:21:12,460\nAnd we accumulate the result\nof that using addition,\n\n396\n00:21:12,460 --> 00:21:14,760\nstarting from 0.\n\n397\n00:21:14,760 --> 00:21:17,290\nSo we can see the pieces\nthat we wanted.\n\n398\n00:21:17,290 --> 00:21:22,050\nSimilarly, the Fibonacci one,\nhow do we get the odd Fibs?\n\n399\n00:21:22,050 --> 00:21:27,900\nWell, we enumerate the interval\nfrom 1 to n, we map\n\n400\n00:21:27,900 --> 00:21:30,920\nalong that, computing the\nFibonacci of each one.\n\n401\n00:21:30,920 --> 00:21:34,810\nWe filter the result of\nthose for oddness.\n\n402\n00:21:34,810 --> 00:21:38,460\nAnd we accumulate all of that\nstuff using CONS starting from\n\n403\n00:21:38,460 --> 00:21:43,650\nthe empty-list.\n\n404\n00:21:43,650 --> 00:21:47,680\nOK, what's the advantage\nof this?\n\n405\n00:21:47,680 --> 00:21:50,260\nWell, for one thing, we now have\npieces that we can start\n\n406\n00:21:50,260 --> 00:21:51,880\nmixing and matching.\n\n407\n00:21:51,880 --> 00:21:58,230\nSo for instance, if I wanted to\nchange this, if I wanted to\n\n408\n00:21:58,230 --> 00:22:00,400\ncompute the squares of the\nintegers and then filter them,\n\n409\n00:22:00,400 --> 00:22:03,810\nall I need to do is pick up a\nstandard piece like this in\n\n410\n00:22:03,810 --> 00:22:06,210\nthat square and put it in.\n\n411\n00:22:06,210 --> 00:22:10,150\nOr if we wanted to do this whole\nFibonacci computation on\n\n412\n00:22:10,150 --> 00:22:12,980\nthe leaves of a tree rather than\na sequence, all I need to\n\n413\n00:22:12,980 --> 00:22:18,030\ndo is replace this enumerator\nwith that one.\n\n414\n00:22:18,030 --> 00:22:20,650\nSee, the advantage of this\nstream processing is that\n\n415\n00:22:20,650 --> 00:22:21,995\nwe're establishing--\n\n416\n00:22:21,995 --> 00:22:25,330\nthis is one of the big themes\nof the course--\n\n417\n00:22:25,330 --> 00:22:35,570\nwe're establishing conventional\ninterfaces that\n\n418\n00:22:35,570 --> 00:22:38,130\nallow us to glue things\ntogether.\n\n419\n00:22:38,130 --> 00:22:41,730\nThings like map and filter are\na standard set of components\n\n420\n00:22:41,730 --> 00:22:43,900\nthat we can start using for\npasting together programs in\n\n421\n00:22:43,900 --> 00:22:45,750\nall sorts of ways.\n\n422\n00:22:45,750 --> 00:22:50,090\nIt allows us to see the\ncommonality of programs.\n\n423\n00:22:50,090 --> 00:22:52,390\nI just ought to mention, I've\nonly showed you two\n\n424\n00:22:52,390 --> 00:22:53,860\nprocedures.\n\n425\n00:22:53,860 --> 00:22:57,800\nBut let me emphasize that this\nway of putting things together\n\n426\n00:22:57,800 --> 00:22:59,780\nwith maps, filters,\nand accumulators\n\n427\n00:22:59,780 --> 00:23:01,410\nis very, very general.\n\n428\n00:23:01,410 --> 00:23:08,010\nIt's the generate and test\nparadigm for programs. And as\n\n429\n00:23:08,010 --> 00:23:11,970\nan example of that, Richard\nWaters, who was at MIT when he\n\n430\n00:23:11,970 --> 00:23:14,060\nwas a graduate student, as part\nof his thesis research\n\n431\n00:23:14,060 --> 00:23:17,700\nwent and analyzed a large chunk\nof the IBM scientific\n\n432\n00:23:17,700 --> 00:23:22,340\nsubroutine library, and\ndiscovered that about 60% of\n\n433\n00:23:22,340 --> 00:23:26,830\nthe programs in it could be\nexpressed exactly in terms\n\n434\n00:23:26,830 --> 00:23:28,940\nusing no more than what\nwe've put here--\n\n435\n00:23:28,940 --> 00:23:30,710\nmap, filter, and accumulate.\n\n436\n00:23:30,710 --> 00:23:31,960\nAll right, let's take a break.\n\n437\n00:23:31,960 --> 00:23:36,620\n\n\n438\n00:23:36,620 --> 00:23:37,870\nQuestions?\n\n439\n00:23:37,870 --> 00:23:40,470\n\n\n440\n00:23:40,470 --> 00:23:43,033\nAUDIENCE: It seems like the\nessence of this whole thing is\n\n441\n00:23:43,033 --> 00:23:45,980\njust that you have a very\nuniform, simple data structure\n\n442\n00:23:45,980 --> 00:23:48,380\nto work with, the stream.\n\n443\n00:23:48,380 --> 00:23:48,920\nPROFESSOR: Right.\n\n444\n00:23:48,920 --> 00:23:51,670\nThe essence is that you, again,\nit's this sense of\n\n445\n00:23:51,670 --> 00:23:53,710\nconventional interfaces.\n\n446\n00:23:53,710 --> 00:23:55,610\nSo you can start putting a\nlot of things together.\n\n447\n00:23:55,610 --> 00:23:59,830\nAnd the stream is as you say,\nthe uniform data structure\n\n448\n00:23:59,830 --> 00:24:00,890\nthat supports that.\n\n449\n00:24:00,890 --> 00:24:03,600\nThis is very much like\nAPL, by the way.\n\n450\n00:24:03,600 --> 00:24:06,330\nAPL is very much the same idea,\nexcept in APL, instead\n\n451\n00:24:06,330 --> 00:24:09,560\nof this stream, you have\narrays and vectors.\n\n452\n00:24:09,560 --> 00:24:13,565\nAnd a lot of the power of APL is\nexactly the same reason of\n\n453\n00:24:13,565 --> 00:24:14,815\nthe power of this.\n\n454\n00:24:14,815 --> 00:24:19,910\n\n\n455\n00:24:19,910 --> 00:24:20,910\nOK, thank you.\n\n456\n00:24:20,910 --> 00:24:22,160\nLet's take a break.\n\n457\n00:24:22,160 --> 00:24:57,470\n\n\n458\n00:24:57,470 --> 00:24:57,610\nAll right.\n\n459\n00:24:57,610 --> 00:25:02,830\nWe've been looking at ways of\norganizing computations using\n\n460\n00:25:02,830 --> 00:25:07,560\nstreams. What I want to do now\nis just show you two somewhat\n\n461\n00:25:07,560 --> 00:25:10,810\nmore complicated examples\nof that.\n\n462\n00:25:10,810 --> 00:25:15,000\nLet's start by thinking about\nthe following kind of utility\n\n463\n00:25:15,000 --> 00:25:16,810\nprocedure that will\ncome in useful.\n\n464\n00:25:16,810 --> 00:25:19,960\nSuppose I've got a stream.\n\n465\n00:25:19,960 --> 00:25:23,730\nAnd the elements of this stream\nare themselves streams.\n\n466\n00:25:23,730 --> 00:25:26,530\nSo the first thing\nmight be 1, 2, 3.\n\n467\n00:25:26,530 --> 00:25:32,600\n\n\n468\n00:25:32,600 --> 00:25:33,880\nSo I've got a stream.\n\n469\n00:25:33,880 --> 00:25:40,100\nAnd each element of the stream\nis itself a stream.\n\n470\n00:25:40,100 --> 00:25:45,580\nAnd what I'd like to do is build\na stream that collects\n\n471\n00:25:45,580 --> 00:25:47,870\ntogether all of the elements,\npulls all of the elements out\n\n472\n00:25:47,870 --> 00:25:50,840\nof these sub-streams and\nstrings them all\n\n473\n00:25:50,840 --> 00:25:52,080\ntogether in one thing.\n\n474\n00:25:52,080 --> 00:25:56,220\nSo just to show you the use of\nthis language, how easy it is,\n\n475\n00:25:56,220 --> 00:25:56,960\ncall that flatten.\n\n476\n00:25:56,960 --> 00:26:13,020\nAnd I can define to flatten this\nstream of streams. Well,\n\n477\n00:26:13,020 --> 00:26:13,960\nwhat is that?\n\n478\n00:26:13,960 --> 00:26:16,240\nThat's just an accumulation.\n\n479\n00:26:16,240 --> 00:26:25,240\nI want to accumulate\nusing append, by\n\n480\n00:26:25,240 --> 00:26:26,450\nsuccessively appending.\n\n481\n00:26:26,450 --> 00:26:36,590\nSo I accumulate using append\nstreams, starting with\n\n482\n00:26:36,590 --> 00:26:54,370\nthe-empty-stream down that\nstream of streams.\n\n483\n00:26:54,370 --> 00:26:58,290\nOK, so there's an example of how\nyou can start using these\n\n484\n00:26:58,290 --> 00:27:00,830\nhigher order things to do some\ninteresting operations.\n\n485\n00:27:00,830 --> 00:27:04,230\nIn fact, there's another\nuseful thing\n\n486\n00:27:04,230 --> 00:27:05,100\nthat I want to do.\n\n487\n00:27:05,100 --> 00:27:18,700\nI want to define a procedure\ncalled flat-map, flat map of\n\n488\n00:27:18,700 --> 00:27:21,840\nsome function and a stream.\n\n489\n00:27:21,840 --> 00:27:23,920\nAnd what this is going\nto do is f will\n\n490\n00:27:23,920 --> 00:27:25,720\nbe a stream of elements.\n\n491\n00:27:25,720 --> 00:27:28,930\nf is going to be a function that\nfor each element in the\n\n492\n00:27:28,930 --> 00:27:31,950\nstream produces another\nstream.\n\n493\n00:27:31,950 --> 00:27:33,950\nAnd what I want to do is take\nall of the elements and all of\n\n494\n00:27:33,950 --> 00:27:36,000\nthose streams and combine\nthem together.\n\n495\n00:27:36,000 --> 00:27:51,350\nSo that's just going to be the\nflatten of map f down s.\n\n496\n00:27:51,350 --> 00:27:54,290\nEach time I apply f to an\nelement of s, I get a stream.\n\n497\n00:27:54,290 --> 00:27:56,690\nIf I map it all the way down, I\nget a stream of streams, and\n\n498\n00:27:56,690 --> 00:27:58,385\nI'll flatten that.\n\n499\n00:27:58,385 --> 00:28:04,670\nWell, I want to use that to\nshow you a new way to do a\n\n500\n00:28:04,670 --> 00:28:06,360\nfamiliar kind of problem.\n\n501\n00:28:06,360 --> 00:28:12,310\nThe problem's going to be like a\nlot of problems you've seen,\n\n502\n00:28:12,310 --> 00:28:14,190\nalthough maybe not this\nparticular one.\n\n503\n00:28:14,190 --> 00:28:15,490\nI'm going to give you\nan integer, n.\n\n504\n00:28:15,490 --> 00:28:18,480\n\n\n505\n00:28:18,480 --> 00:28:31,020\nAnd the problem is going to be\nfind all pairs and integers i\n\n506\n00:28:31,020 --> 00:28:42,740\nand j, between 0 and i, with j\nless than i, up to n, such\n\n507\n00:28:42,740 --> 00:28:51,910\nthat i plus j is prime.\n\n508\n00:28:51,910 --> 00:28:55,740\n\n\n509\n00:28:55,740 --> 00:29:00,520\nSo for example, if n equals 6,\nlet's make a little table\n\n510\n00:29:00,520 --> 00:29:06,640\nhere, i and j and i plus j.\n\n511\n00:29:06,640 --> 00:29:09,700\n\n\n512\n00:29:09,700 --> 00:29:15,520\nSo for, say, i equals 2 and\nj equals 1, I'd get 3.\n\n513\n00:29:15,520 --> 00:29:18,940\nAnd for i equals 3, I could\nhave j equals 2, and that\n\n514\n00:29:18,940 --> 00:29:21,210\nwould be 5.\n\n515\n00:29:21,210 --> 00:29:28,400\nAnd 4 and 1 would be 5 and so\non, up until i goes to 6.\n\n516\n00:29:28,400 --> 00:29:33,640\nAnd what I'd like to return is\nto produce a stream of all the\n\n517\n00:29:33,640 --> 00:29:37,350\ntriples like this, let's\nsay i, j, and i plus j.\n\n518\n00:29:37,350 --> 00:29:41,530\nSo for each n, I want to\ngenerate this stream.\n\n519\n00:29:41,530 --> 00:29:43,680\nOK, well, that's easy.\n\n520\n00:29:43,680 --> 00:29:47,230\nLet's build it up.\n\n521\n00:29:47,230 --> 00:29:50,150\nWe start like this.\n\n522\n00:29:50,150 --> 00:29:55,510\nWe're going to say for\neach i, we're going\n\n523\n00:29:55,510 --> 00:29:56,440\nto generate a stream.\n\n524\n00:29:56,440 --> 00:29:58,830\nFor each i in the interval 1\nthrough n, we're going to\n\n525\n00:29:58,830 --> 00:30:00,660\ngenerate a stream.\n\n526\n00:30:00,660 --> 00:30:02,230\nWhat's that stream\ngoing to be?\n\n527\n00:30:02,230 --> 00:30:04,180\nWe're going to start by\ngenerating all the pairs.\n\n528\n00:30:04,180 --> 00:30:11,840\nSo for each i, we're going to\ngenerate, for each j in the\n\n529\n00:30:11,840 --> 00:30:19,450\ninterval 1 to i minus 1, we'll\ngenerate the pair, or the list\n\n530\n00:30:19,450 --> 00:30:20,710\nwith two elements i and j.\n\n531\n00:30:20,710 --> 00:30:23,780\n\n\n532\n00:30:23,780 --> 00:30:30,712\nSo we map along the interval,\ngenerating the pairs.\n\n533\n00:30:30,712 --> 00:30:33,170\nAnd for each i, that generates\na stream of pairs.\n\n534\n00:30:33,170 --> 00:30:34,590\nAnd we flatmap it.\n\n535\n00:30:34,590 --> 00:30:37,390\nNow we have all the pairs\ni and j, such that i\n\n536\n00:30:37,390 --> 00:30:38,730\nis less than j.\n\n537\n00:30:38,730 --> 00:30:39,850\nSo that builds that.\n\n538\n00:30:39,850 --> 00:30:42,990\nNow we're got to test them.\n\n539\n00:30:42,990 --> 00:30:47,160\nWell, we take that thing we just\nbuilt, the flatmap, and\n\n540\n00:30:47,160 --> 00:30:50,090\nwe filter it to see\nwhether the i--\n\n541\n00:30:50,090 --> 00:30:51,660\nsee, we had an i and a j.\n\n542\n00:30:51,660 --> 00:30:55,180\ni was the first thing in the\nlist, j was the second thing\n\n543\n00:30:55,180 --> 00:30:59,030\nin the list. So we have a\npredicate which says in that\n\n544\n00:30:59,030 --> 00:31:00,870\nlist of two elements\nis the sum of the\n\n545\n00:31:00,870 --> 00:31:02,070\nCAR and the CDR prime.\n\n546\n00:31:02,070 --> 00:31:06,540\nAnd we filter that collection\nof pairs we just built.\n\n547\n00:31:06,540 --> 00:31:09,420\nSo those are the\npairs we want.\n\n548\n00:31:09,420 --> 00:31:13,340\nNow we go ahead and we take the\nresult of that filter and\n\n549\n00:31:13,340 --> 00:31:19,610\nwe map along it, generating the\nlist i and j and i plus j.\n\n550\n00:31:19,610 --> 00:31:22,910\nAnd that's our procedure\nprime-sum-pairs.\n\n551\n00:31:22,910 --> 00:31:24,480\nAnd then just to flash it up,\nhere's the whole procedure.\n\n552\n00:31:24,480 --> 00:31:27,945\n\n\n553\n00:31:27,945 --> 00:31:30,750\nA map, a filter, a flatmap.\n\n554\n00:31:30,750 --> 00:31:34,850\n\n\n555\n00:31:34,850 --> 00:31:36,350\nThere's the whole thing,\neven though this isn't\n\n556\n00:31:36,350 --> 00:31:37,120\nparticularly readable.\n\n557\n00:31:37,120 --> 00:31:40,000\nIt's just expanding\nthat flatmap.\n\n558\n00:31:40,000 --> 00:31:45,090\nSo there's an example which\nillustrates the general point\n\n559\n00:31:45,090 --> 00:31:49,350\nthat nested loops in this\nprocedure start looking like\n\n560\n00:31:49,350 --> 00:31:52,370\ncompositions of flatmaps of\nflatmaps of flatmaps of maps\n\n561\n00:31:52,370 --> 00:31:54,200\nand things.\n\n562\n00:31:54,200 --> 00:31:57,900\nSo not only can we enumerate\nindividual things, but by\n\n563\n00:31:57,900 --> 00:32:00,890\nusing flatmaps, we can do what\nwould correspond to nested\n\n564\n00:32:00,890 --> 00:32:03,230\nloops in most other languages.\n\n565\n00:32:03,230 --> 00:32:06,870\nOf course, it's pretty awful to\nkeep writing these flatmaps\n\n566\n00:32:06,870 --> 00:32:08,410\nof flatmaps of flatmaps.\n\n567\n00:32:08,410 --> 00:32:13,830\nPrime-sum-pairs you saw looked\nfairly complicated, even\n\n568\n00:32:13,830 --> 00:32:15,480\nthough the individual\npieces were easy.\n\n569\n00:32:15,480 --> 00:32:17,800\nSo what you can do, if you\nlike, is introduced some\n\n570\n00:32:17,800 --> 00:32:21,040\nsyntactic sugar that's\ncalled collect.\n\n571\n00:32:21,040 --> 00:32:23,570\nAnd collect is just an\nabbreviation for that nest of\n\n572\n00:32:23,570 --> 00:32:26,160\nflatmaps and filters arranged\nin that particular way.\n\n573\n00:32:26,160 --> 00:32:29,620\nHere's prime-sum-pairs again,\nwritten using collect.\n\n574\n00:32:29,620 --> 00:32:32,670\nIt says to find all those pairs,\nI'm going to collect\n\n575\n00:32:32,670 --> 00:32:40,910\ntogether a result, which is the\nlist i, j, and i plus j,\n\n576\n00:32:40,910 --> 00:32:44,510\nthat's going to be generated as\ni runs through the interval\n\n577\n00:32:44,510 --> 00:32:51,440\nfrom 1 to n and as j runs\nthrough the interval from 1 to\n\n578\n00:32:51,440 --> 00:32:58,040\ni minus 1, such that\ni plus j is prime.\n\n579\n00:32:58,040 --> 00:33:00,690\nSo I'm not going to say what\ncollect does in general.\n\n580\n00:33:00,690 --> 00:33:03,420\nYou can look at that by looking\nat it in the book.\n\n581\n00:33:03,420 --> 00:33:06,010\nBut pretty much, you can see\nthat the pieces of this are\n\n582\n00:33:06,010 --> 00:33:08,820\nthe pieces of that original\nprocedure I wrote.\n\n583\n00:33:08,820 --> 00:33:11,550\nAnd this collect is just some\nsyntactic sugar for\n\n584\n00:33:11,550 --> 00:33:16,310\nautomatically generating that\nnest of flatmaps and flatmaps.\n\n585\n00:33:16,310 --> 00:33:21,120\nOK, well, let me do one more\nexample that shows you the\n\n586\n00:33:21,120 --> 00:33:22,120\nsame kind of thing.\n\n587\n00:33:22,120 --> 00:33:25,740\nHere's a very famous problem\nthat's used to illustrate a\n\n588\n00:33:25,740 --> 00:33:28,980\nlot of so-called backtracking\ncomputer algorithms. This is\n\n589\n00:33:28,980 --> 00:33:30,200\nthe eight queens problem.\n\n590\n00:33:30,200 --> 00:33:32,370\nThis is a chess board.\n\n591\n00:33:32,370 --> 00:33:34,570\nAnd the eight queens problem\nsays, find a way to put down\n\n592\n00:33:34,570 --> 00:33:37,660\neight queens on a chess board\nso that no two are attacking\n\n593\n00:33:37,660 --> 00:33:38,000\neach other.\n\n594\n00:33:38,000 --> 00:33:39,685\nAnd here's a particular\nsolution to the\n\n595\n00:33:39,685 --> 00:33:41,430\neight queens problem.\n\n596\n00:33:41,430 --> 00:33:44,450\nSo I have to make sure to put\ndown queens so that no two are\n\n597\n00:33:44,450 --> 00:33:48,570\nin the same row or the\nsame column or sit\n\n598\n00:33:48,570 --> 00:33:51,410\nalong the same diagonal.\n\n599\n00:33:51,410 --> 00:33:56,400\nNow, there's sort of a standard\nway of doing that.\n\n600\n00:33:56,400 --> 00:33:59,740\n\n\n601\n00:33:59,740 --> 00:34:03,200\nWell, first we need\nto do is below the\n\n602\n00:34:03,200 --> 00:34:04,940\nsurface, at George's level.\n\n603\n00:34:04,940 --> 00:34:07,340\nWe have to find some way to\nrepresent a board, and\n\n604\n00:34:07,340 --> 00:34:08,095\nrepresent positions.\n\n605\n00:34:08,095 --> 00:34:09,800\nAnd we'll not worry\nabout that.\n\n606\n00:34:09,800 --> 00:34:12,540\nBut let's assume that there's\na predicate called safe.\n\n607\n00:34:12,540 --> 00:34:16,040\n\n\n608\n00:34:16,040 --> 00:34:19,090\nAnd what safe is going to do is\ngoing to say given that I\n\n609\n00:34:19,090 --> 00:34:22,520\nhave a bunch of queens down on\nthe chess board, is it OK to\n\n610\n00:34:22,520 --> 00:34:25,400\nput a queen in this\nparticular spot?\n\n611\n00:34:25,400 --> 00:34:32,889\nSo safe is going to take\na row and a column.\n\n612\n00:34:32,889 --> 00:34:34,510\nThat's going to be a place where\nI'm going to try and put\n\n613\n00:34:34,510 --> 00:34:42,370\ndown the next queen, and\nthe rest of positions.\n\n614\n00:34:42,370 --> 00:34:45,420\n\n\n615\n00:34:45,420 --> 00:34:48,679\nAnd what safe will say is given\nthat I already have\n\n616\n00:34:48,679 --> 00:34:53,920\nqueens down in these positions,\nis it safe to put\n\n617\n00:34:53,920 --> 00:34:58,300\nanother queen down in that\nrow and that column?\n\n618\n00:34:58,300 --> 00:34:59,360\nAnd let's not worry\nabout that.\n\n619\n00:34:59,360 --> 00:35:01,380\nThat's George's problem. and\nit's not hard to write.\n\n620\n00:35:01,380 --> 00:35:06,350\nYou just have to check whether\nthis thing contains any things\n\n621\n00:35:06,350 --> 00:35:10,530\non that row or that column\nor in that diagonal.\n\n622\n00:35:10,530 --> 00:35:13,590\nNow, how would you organize\nthe program given that?\n\n623\n00:35:13,590 --> 00:35:18,010\nAnd there's sort of a\ntraditional way to organize it\n\n624\n00:35:18,010 --> 00:35:20,116\ncalled backtracking.\n\n625\n00:35:20,116 --> 00:35:27,570\nAnd it says, well, let's think\nabout all the ways of putting\n\n626\n00:35:27,570 --> 00:35:31,290\nthe first queen down in\nthe first column.\n\n627\n00:35:31,290 --> 00:35:32,580\nThere are eight ways.\n\n628\n00:35:32,580 --> 00:35:35,880\nWell, let's say try\nthe first column.\n\n629\n00:35:35,880 --> 00:35:37,300\nTry column 1, row 1.\n\n630\n00:35:37,300 --> 00:35:41,300\nThese branches are going to\nrepresent the possibilities at\n\n631\n00:35:41,300 --> 00:35:43,360\neach level.\n\n632\n00:35:43,360 --> 00:35:45,875\nSo I'll try and put a queen\ndown in the first column.\n\n633\n00:35:45,875 --> 00:35:48,360\nAnd now given that it's in the\nfirst column, I'll try and put\n\n634\n00:35:48,360 --> 00:35:49,980\nthe next queen down in\nthe first column.\n\n635\n00:35:49,980 --> 00:35:53,035\n\n\n636\n00:35:53,035 --> 00:35:55,470\nI'll try and put the first\nqueen, the one in the first\n\n637\n00:35:55,470 --> 00:35:56,920\ncolumn, down in the first row.\n\n638\n00:35:56,920 --> 00:35:59,050\nI'm sorry.\n\n639\n00:35:59,050 --> 00:36:00,780\nAnd then given that, we'll\nput the next queen down\n\n640\n00:36:00,780 --> 00:36:01,390\nin the first row.\n\n641\n00:36:01,390 --> 00:36:02,090\nAnd that's no good.\n\n642\n00:36:02,090 --> 00:36:04,200\nSo I'll back up to here.\n\n643\n00:36:04,200 --> 00:36:06,280\nAnd I'll say, oh, can I put the\nfirst queen down in the\n\n644\n00:36:06,280 --> 00:36:07,510\nsecond row?\n\n645\n00:36:07,510 --> 00:36:08,550\nWell, that's no good.\n\n646\n00:36:08,550 --> 00:36:09,760\nOh, can I put it down\nin the third row?\n\n647\n00:36:09,760 --> 00:36:12,790\nWell, that's good.\n\n648\n00:36:12,790 --> 00:36:14,290\nWell, now can I put the\nnext queen down\n\n649\n00:36:14,290 --> 00:36:15,380\nin the first column?\n\n650\n00:36:15,380 --> 00:36:18,030\nWell, I can't visualize this\nchess board anymore, but I\n\n651\n00:36:18,030 --> 00:36:19,195\nthink that's right.\n\n652\n00:36:19,195 --> 00:36:20,450\nAnd I try the next one.\n\n653\n00:36:20,450 --> 00:36:24,170\nAnd at each place, I go as far\ndown this tree as I can.\n\n654\n00:36:24,170 --> 00:36:25,640\nAnd I back up.\n\n655\n00:36:25,640 --> 00:36:28,970\nIf I get down to here and find\nno possibilities below there,\n\n656\n00:36:28,970 --> 00:36:31,740\nI back all the way up to here,\nand now start again generating\n\n657\n00:36:31,740 --> 00:36:33,260\nthis sub-tree.\n\n658\n00:36:33,260 --> 00:36:35,050\nAnd I sort of walk around.\n\n659\n00:36:35,050 --> 00:36:37,870\nAnd finally, if I ever manage to\nget all the way down, I've\n\n660\n00:36:37,870 --> 00:36:40,090\nfound a solution.\n\n661\n00:36:40,090 --> 00:36:45,020\nSo that's a typical sort of\nparadigm that's used a lot in\n\n662\n00:36:45,020 --> 00:36:45,930\nAI programming.\n\n663\n00:36:45,930 --> 00:36:47,300\nIt's called backtracking\nsearch.\n\n664\n00:36:47,300 --> 00:36:57,470\n\n\n665\n00:36:57,470 --> 00:37:03,860\nAnd it's really unnecessary.\n\n666\n00:37:03,860 --> 00:37:06,550\nYou saw me get confused when I\nwas visualizing this thing.\n\n667\n00:37:06,550 --> 00:37:08,550\nAnd you see the complication.\n\n668\n00:37:08,550 --> 00:37:10,760\nThis is a complicated\nthing to say.\n\n669\n00:37:10,760 --> 00:37:12,390\nWhy is it complicated?\n\n670\n00:37:12,390 --> 00:37:16,190\nIts because somehow this program\nis too inordinately\n\n671\n00:37:16,190 --> 00:37:18,580\nconcerned with time.\n\n672\n00:37:18,580 --> 00:37:19,200\nIt's too much--\n\n673\n00:37:19,200 --> 00:37:21,670\nI try this one, and I try this\none, and I go back to the last\n\n674\n00:37:21,670 --> 00:37:22,320\npossibility.\n\n675\n00:37:22,320 --> 00:37:24,340\nAnd that's a complicated\nthing.\n\n676\n00:37:24,340 --> 00:37:28,590\nIf I stop worrying about time\nso much, then there's a much\n\n677\n00:37:28,590 --> 00:37:31,200\nsimpler way to describe this.\n\n678\n00:37:31,200 --> 00:37:40,320\nIt says, let's imagine that I\nhave in my hands the tree down\n\n679\n00:37:40,320 --> 00:37:43,400\nto k minus 1 levels.\n\n680\n00:37:43,400 --> 00:37:50,670\nSee, suppose I had in my hands\nall possible ways to put down\n\n681\n00:37:50,670 --> 00:37:53,560\nqueens in the first k columns.\n\n682\n00:37:53,560 --> 00:37:54,610\nSuppose I just had that.\n\n683\n00:37:54,610 --> 00:37:57,070\nLet's not worry about\nhow we get it.\n\n684\n00:37:57,070 --> 00:37:59,200\nWell, then, how do\nI extend that?\n\n685\n00:37:59,200 --> 00:38:01,420\nHow do I find all possible ways\nto put down queens in the\n\n686\n00:38:01,420 --> 00:38:02,480\nnext column?\n\n687\n00:38:02,480 --> 00:38:03,620\nIt's really easy.\n\n688\n00:38:03,620 --> 00:38:12,210\nFor each of these positions I\nhave, I think about putting\n\n689\n00:38:12,210 --> 00:38:16,160\ndown a queen in each row\nto make the next thing.\n\n690\n00:38:16,160 --> 00:38:18,930\nAnd then for each one I put\ndown, I filter those by the\n\n691\n00:38:18,930 --> 00:38:22,080\nones that are safe.\n\n692\n00:38:22,080 --> 00:38:24,190\nSo instead of thinking about\nthis tree as generated step by\n\n693\n00:38:24,190 --> 00:38:26,860\nstep, suppose I had\nit all there.\n\n694\n00:38:26,860 --> 00:38:29,680\n\n\n695\n00:38:29,680 --> 00:38:32,990\nAnd to extend it from level k\nminus 1 to level k, I just\n\n696\n00:38:32,990 --> 00:38:36,840\nneed to extend each thing in\nall possible ways and only\n\n697\n00:38:36,840 --> 00:38:37,800\nkeep the ones that are safe.\n\n698\n00:38:37,800 --> 00:38:39,300\nAnd that will give me\nthe tree to level k.\n\n699\n00:38:39,300 --> 00:38:41,675\nAnd that's a recursive strategy\nfor solving the eight\n\n700\n00:38:41,675 --> 00:38:44,530\nqueens problem.\n\n701\n00:38:44,530 --> 00:38:45,780\nAll right, well, let's\nlook at it.\n\n702\n00:38:45,780 --> 00:38:50,280\n\n\n703\n00:38:50,280 --> 00:38:54,360\nTo solve the eight queens\nproblem on a board of some\n\n704\n00:38:54,360 --> 00:39:00,390\nspecified size, we write\na sub-procedure called\n\n705\n00:39:00,390 --> 00:39:01,030\nfill-columns.\n\n706\n00:39:01,030 --> 00:39:04,050\nFill-columns is going to\nput down queens up\n\n707\n00:39:04,050 --> 00:39:06,086\nthrough column k.\n\n708\n00:39:06,086 --> 00:39:07,700\nAnd here's the pattern\nof the recursion.\n\n709\n00:39:07,700 --> 00:39:12,990\nI'm going to call fill-columns\nwith the size eventually.\n\n710\n00:39:12,990 --> 00:39:15,630\nSo fill-columns says how to put\ndown queens safely in the\n\n711\n00:39:15,630 --> 00:39:19,255\nfirst k columns of this chess\nboard with a size number of\n\n712\n00:39:19,255 --> 00:39:20,360\nrows in it.\n\n713\n00:39:20,360 --> 00:39:22,946\nIf k is equal to 0, well,\nthen I don't have to\n\n714\n00:39:22,946 --> 00:39:23,940\nput anything down.\n\n715\n00:39:23,940 --> 00:39:26,710\nSo my solution is just\nan empty chess board.\n\n716\n00:39:26,710 --> 00:39:28,070\nOtherwise, I'm going\nto do some stuff.\n\n717\n00:39:28,070 --> 00:39:30,522\nAnd I'm going to use collect.\n\n718\n00:39:30,522 --> 00:39:31,772\nAnd here's the collect.\n\n719\n00:39:31,772 --> 00:39:34,530\n\n\n720\n00:39:34,530 --> 00:39:40,590\nI find all ways to put\ndown queens in the\n\n721\n00:39:40,590 --> 00:39:41,910\nfirst k minus 1 columns.\n\n722\n00:39:41,910 --> 00:39:43,320\nAnd this was just\nwhat I set for.\n\n723\n00:39:43,320 --> 00:39:48,880\nImagine I have this tree down\nto k minus 1 levels.\n\n724\n00:39:48,880 --> 00:39:53,230\nAnd then I find all ways of\ntrying a row, that's just each\n\n725\n00:39:53,230 --> 00:39:54,130\nof the possible rows.\n\n726\n00:39:54,130 --> 00:39:58,040\nThey're size rows, so that's\nenumerate interval.\n\n727\n00:39:58,040 --> 00:40:03,950\nAnd now what I do is I collect\ntogether the new row I'm going\n\n728\n00:40:03,950 --> 00:40:08,950\nto try and column k with\nthe rest of the queens.\n\n729\n00:40:08,950 --> 00:40:10,200\nI adjoin a position.\n\n730\n00:40:10,200 --> 00:40:11,290\nThis is George's problem.\n\n731\n00:40:11,290 --> 00:40:13,640\nAn adjoined position\nis like safe.\n\n732\n00:40:13,640 --> 00:40:16,530\nIt's a thing that takes a row\nand a column and the rest of\n\n733\n00:40:16,530 --> 00:40:19,660\nthe positions and makes a\nnew position collection.\n\n734\n00:40:19,660 --> 00:40:26,230\nSo I adjoin a position of a new\nrow and a new column to\n\n735\n00:40:26,230 --> 00:40:30,310\nthe rest of the queens, where\nthe rest of the queens runs\n\n736\n00:40:30,310 --> 00:40:32,870\nthrough all possible ways\nof solving the problem\n\n737\n00:40:32,870 --> 00:40:34,620\nin k minus 1 columns.\n\n738\n00:40:34,620 --> 00:40:39,730\nAnd the new row runs through all\npossible rows such that it\n\n739\n00:40:39,730 --> 00:40:43,240\nwas safe to put one there.\n\n740\n00:40:43,240 --> 00:40:46,500\nAnd that's the whole program.\n\n741\n00:40:46,500 --> 00:40:49,840\nThere's the whole procedure.\n\n742\n00:40:49,840 --> 00:40:51,990\nNot only that, that doesn't just\nsolve the eight queens\n\n743\n00:40:51,990 --> 00:40:56,010\nproblem, it gives you\nall solutions to the\n\n744\n00:40:56,010 --> 00:40:56,680\neight queens problem.\n\n745\n00:40:56,680 --> 00:40:58,480\nWhen you're done, you\nhave a stream.\n\n746\n00:40:58,480 --> 00:41:00,650\nAnd the elements of that stream\nare all possible ways\n\n747\n00:41:00,650 --> 00:41:01,900\nof solving that problem.\n\n748\n00:41:01,900 --> 00:41:05,310\n\n\n749\n00:41:05,310 --> 00:41:06,260\nWhy is that simpler?\n\n750\n00:41:06,260 --> 00:41:10,170\nWell, we threw away the whole\nidea that this is some process\n\n751\n00:41:10,170 --> 00:41:12,720\nthat happens in time\nwith state.\n\n752\n00:41:12,720 --> 00:41:14,420\nAnd we just said it's a whole\ncollection of stuff.\n\n753\n00:41:14,420 --> 00:41:18,260\nAnd that's why it's simpler.\n\n754\n00:41:18,260 --> 00:41:20,110\nWe've changed our view.\n\n755\n00:41:20,110 --> 00:41:22,820\nRemember, that's where\nwe started today.\n\n756\n00:41:22,820 --> 00:41:26,230\nWe've changed our view of what\nit is we're trying to model.\n\n757\n00:41:26,230 --> 00:41:30,570\nwe stop modeling things that\nevolve in time and have steps\n\n758\n00:41:30,570 --> 00:41:31,750\nand have state.\n\n759\n00:41:31,750 --> 00:41:33,990\nAnd instead, we're trying to\nmodel this global thing like\n\n760\n00:41:33,990 --> 00:41:37,950\nthe whole flight of the\nchalk, rather than its\n\n761\n00:41:37,950 --> 00:41:40,750\nstate at each instant.\n\n762\n00:41:40,750 --> 00:41:42,000\nAny questions?\n\n763\n00:41:42,000 --> 00:41:43,810\n\n\n764\n00:41:43,810 --> 00:41:46,190\nAUDIENCE: It looks to me like\nbacktracking would be\n\n765\n00:41:46,190 --> 00:41:49,970\nsearching for the first solution\nit can find, whereas\n\n766\n00:41:49,970 --> 00:41:54,030\nthis recursive search would be\nlooking for all solutions.\n\n767\n00:41:54,030 --> 00:41:58,090\nAnd it seems that if you have a\nlarge enough area to search,\n\n768\n00:41:58,090 --> 00:42:01,360\nthat the second is going\nto become impossible.\n\n769\n00:42:01,360 --> 00:42:07,610\nPROFESSOR: OK, the answer to\nthat question is the whole\n\n770\n00:42:07,610 --> 00:42:08,570\nrest of this lecture.\n\n771\n00:42:08,570 --> 00:42:10,540\nIt's exactly the\nright question.\n\n772\n00:42:10,540 --> 00:42:13,522\n\n\n773\n00:42:13,522 --> 00:42:15,540\nAnd without trying to anticipate\nthe lecture too\n\n774\n00:42:15,540 --> 00:42:19,910\nmuch, you should start being\nsuspicious at this point, and\n\n775\n00:42:19,910 --> 00:42:22,220\nexactly those kinds\nof suspicions.\n\n776\n00:42:22,220 --> 00:42:24,830\nIt's wonderful, but isn't it\nso terribly inefficient?\n\n777\n00:42:24,830 --> 00:42:28,100\nThat's where we're going.\n\n778\n00:42:28,100 --> 00:42:30,020\nSo I won't answer now, but\nI'll answer later.\n\n779\n00:42:30,020 --> 00:42:33,350\n\n\n780\n00:42:33,350 --> 00:42:34,600\nOK, let's take a break.\n\n781\n00:42:34,600 --> 00:43:29,650\n\n\n782\n00:43:29,650 --> 00:43:35,600\nWell, by now you should be\nstarting to get suspicious.\n\n783\n00:43:35,600 --> 00:43:41,450\nSee, I've showed your this\nsimple, elegant way of putting\n\n784\n00:43:41,450 --> 00:43:46,440\nprograms together, very unlike\nthese other traditional\n\n785\n00:43:46,440 --> 00:43:50,490\nprograms that sum the odd\nsquares or compute the odd\n\n786\n00:43:50,490 --> 00:43:53,740\nFibonacci numbers.\n\n787\n00:43:53,740 --> 00:43:57,080\nVery unlike these programs that\nmix up the enumerator and\n\n788\n00:43:57,080 --> 00:44:00,440\nthe filter and the\naccumulator.\n\n789\n00:44:00,440 --> 00:44:04,770\nAnd by mixing it up, we don't\nhave all of these wonderful\n\n790\n00:44:04,770 --> 00:44:07,990\nconceptual advantages of these\nstreams pieces, these\n\n791\n00:44:07,990 --> 00:44:09,840\nwonderful mix and match\ncomponents for putting\n\n792\n00:44:09,840 --> 00:44:13,800\ntogether lots and lots\nof programs.\n\n793\n00:44:13,800 --> 00:44:15,810\nOn the other hand, most of the\nprograms you've seen look like\n\n794\n00:44:15,810 --> 00:44:18,340\nthese ugly ones.\n\n795\n00:44:18,340 --> 00:44:19,460\nWhy's that?\n\n796\n00:44:19,460 --> 00:44:23,705\nCan it possibly be that computer\nscientists are so\n\n797\n00:44:23,705 --> 00:44:28,370\nobtuse that they don't notice\nthat if you'd merely did this\n\n798\n00:44:28,370 --> 00:44:33,620\nthing, then you can get this\ngreat programming elegance?\n\n799\n00:44:33,620 --> 00:44:36,760\nThere's got to be a catch.\n\n800\n00:44:36,760 --> 00:44:39,510\nAnd it's actually pretty easy\nto see what the catch is.\n\n801\n00:44:39,510 --> 00:44:42,030\nLet's think about the\nfollowing problem.\n\n802\n00:44:42,030 --> 00:44:47,510\nSuppose I tell you to find the\nsecond prime between 10,000\n\n803\n00:44:47,510 --> 00:44:51,020\nand 1 million, or if your\ncomputer's larger, say between\n\n804\n00:44:51,020 --> 00:44:54,105\n10,000 and 100 billion,\nor something.\n\n805\n00:44:54,105 --> 00:44:55,550\nAnd you say, oh, that's easy.\n\n806\n00:44:55,550 --> 00:44:57,080\nI can do that with a stream.\n\n807\n00:44:57,080 --> 00:45:01,530\nAll I do is I enumerate\nthe interval\n\n808\n00:45:01,530 --> 00:45:04,160\nfrom 10,000 to 1 million.\n\n809\n00:45:04,160 --> 00:45:06,800\nSo I get all those integers\nfrom 10,000 to 1 million.\n\n810\n00:45:06,800 --> 00:45:10,520\nI filter them for prime-ness, so\ntest all of them and see if\n\n811\n00:45:10,520 --> 00:45:11,762\nthey're prime.\n\n812\n00:45:11,762 --> 00:45:13,170\nAnd I take the second element.\n\n813\n00:45:13,170 --> 00:45:16,130\nThat's the head of the tail.\n\n814\n00:45:16,130 --> 00:45:17,380\nWell, that's clearly\npretty ridiculous.\n\n815\n00:45:17,380 --> 00:45:21,660\n\n\n816\n00:45:21,660 --> 00:45:24,620\nWe'd not even have room in the\nmachine to store the integers\n\n817\n00:45:24,620 --> 00:45:27,040\nin the first place, much\nless to test them.\n\n818\n00:45:27,040 --> 00:45:29,810\nAnd then I only want\nthe second one.\n\n819\n00:45:29,810 --> 00:45:36,500\nSee, the power of this\ntraditional programming style\n\n820\n00:45:36,500 --> 00:45:39,860\nis exactly its weakness, that\nwe're mixing up the\n\n821\n00:45:39,860 --> 00:45:45,090\nenumerating and the testing\nand the accumulating.\n\n822\n00:45:45,090 --> 00:45:46,670\nSo we don't do it all.\n\n823\n00:45:46,670 --> 00:45:52,580\nSo the very thing that makes\nit conceptually ugly is the\n\n824\n00:45:52,580 --> 00:45:55,210\nvery thing that makes\nit efficient.\n\n825\n00:45:55,210 --> 00:45:57,800\nIt's this mixing up.\n\n826\n00:45:57,800 --> 00:45:59,840\nSo it seems that all I've done\nthis morning so far is just\n\n827\n00:45:59,840 --> 00:46:00,420\nconfuse you.\n\n828\n00:46:00,420 --> 00:46:02,930\nI showed you this wonderful\nway that programming might\n\n829\n00:46:02,930 --> 00:46:05,840\nwork, except that it doesn't.\n\n830\n00:46:05,840 --> 00:46:09,040\nWell, here's where the wonderful\nthing happens.\n\n831\n00:46:09,040 --> 00:46:13,210\nIt turns out in this game that\nwe really can have our cake\n\n832\n00:46:13,210 --> 00:46:14,870\nand eat it too.\n\n833\n00:46:14,870 --> 00:46:20,280\nAnd what I mean by that is\nthat we really can write\n\n834\n00:46:20,280 --> 00:46:24,210\nstream programs exactly like the\nones I wrote and arrange\n\n835\n00:46:24,210 --> 00:46:28,830\nthings so that when the machine\nactually runs, it's as\n\n836\n00:46:28,830 --> 00:46:31,690\nefficient as running this\ntraditional programming style\n\n837\n00:46:31,690 --> 00:46:36,310\nthat mixes up the generation\nand the test.\n\n838\n00:46:36,310 --> 00:46:40,770\nWell, that sounds\npretty magic.\n\n839\n00:46:40,770 --> 00:46:43,690\nThe key to this is that\nstreams are not lists.\n\n840\n00:46:43,690 --> 00:46:48,090\n\n\n841\n00:46:48,090 --> 00:46:50,070\nWe'll see this carefully in a\nsecond, but for now, let's\n\n842\n00:46:50,070 --> 00:46:52,115\ntake a look at that\nslide again.\n\n843\n00:46:52,115 --> 00:46:55,060\nThe image you should have here\nof this signal processing\n\n844\n00:46:55,060 --> 00:47:00,940\nsystem is that what's going to\nhappen is there's this box\n\n845\n00:47:00,940 --> 00:47:05,360\nthat has the integers\nsitting in it.\n\n846\n00:47:05,360 --> 00:47:08,680\nAnd there's this filter that's\nconnected to it and it's\n\n847\n00:47:08,680 --> 00:47:10,940\ntugging on them.\n\n848\n00:47:10,940 --> 00:47:13,680\nAnd then there's someone who's\ntugging on this stuff saying\n\n849\n00:47:13,680 --> 00:47:16,790\nwhat comes out of the filter.\n\n850\n00:47:16,790 --> 00:47:19,630\nAnd the image you should have\nis that someone says, well,\n\n851\n00:47:19,630 --> 00:47:24,590\nwhat's the first prime, and\ntugs on this filter.\n\n852\n00:47:24,590 --> 00:47:28,020\nAnd the filter tugs\non the integers.\n\n853\n00:47:28,020 --> 00:47:29,830\nAnd you look only at that much,\nand then say, oh, I\n\n854\n00:47:29,830 --> 00:47:30,930\nreally wanted the second one.\n\n855\n00:47:30,930 --> 00:47:33,710\nWhat's the second prime?\n\n856\n00:47:33,710 --> 00:47:37,730\nAnd that no computation gets\ndone except when you tug on\n\n857\n00:47:37,730 --> 00:47:40,500\nthese things.\n\n858\n00:47:40,500 --> 00:47:41,410\nLet me try that again.\n\n859\n00:47:41,410 --> 00:47:43,815\nThis is a little device.\n\n860\n00:47:43,815 --> 00:47:46,400\nThis is a little stream machine\ninvented by Eric\n\n861\n00:47:46,400 --> 00:47:49,830\nGrimson who's been teaching\nthis course at MIT.\n\n862\n00:47:49,830 --> 00:47:52,940\nAnd the image is here's a stream\nof stuff, like a whole\n\n863\n00:47:52,940 --> 00:47:54,780\nbunch of the integers.\n\n864\n00:47:54,780 --> 00:47:58,700\nAnd here's some processing\nelements.\n\n865\n00:47:58,700 --> 00:48:02,600\nAnd if, say, it's filter of\nfilter of map, or something.\n\n866\n00:48:02,600 --> 00:48:05,570\n\n\n867\n00:48:05,570 --> 00:48:08,760\nAnd if I really tried to\nimplement that with streams as\n\n868\n00:48:08,760 --> 00:48:11,520\nlists, what I'd say is, well,\nI've got this list of things,\n\n869\n00:48:11,520 --> 00:48:12,670\nand now I do the first filter.\n\n870\n00:48:12,670 --> 00:48:14,070\nSo do all this processing.\n\n871\n00:48:14,070 --> 00:48:18,570\nAnd I take this and I process\nand I process and I process\n\n872\n00:48:18,570 --> 00:48:19,610\nand I process.\n\n873\n00:48:19,610 --> 00:48:21,910\nAnd now I'm got this\nnew stream.\n\n874\n00:48:21,910 --> 00:48:24,070\nNow I take that result\nin my hand someplace.\n\n875\n00:48:24,070 --> 00:48:25,260\nAnd I put that through\nthe second one.\n\n876\n00:48:25,260 --> 00:48:28,110\nAnd I process the whole thing.\n\n877\n00:48:28,110 --> 00:48:29,510\nAnd there's this new stream.\n\n878\n00:48:29,510 --> 00:48:32,130\n\n\n879\n00:48:32,130 --> 00:48:35,230\nAnd then I take the result and\nI put it all the way through\n\n880\n00:48:35,230 --> 00:48:36,360\nthis one the same way.\n\n881\n00:48:36,360 --> 00:48:41,760\nThat's what would happen to\nthese stream programs if\n\n882\n00:48:41,760 --> 00:48:43,860\nstreams were just lists.\n\n883\n00:48:43,860 --> 00:48:46,065\nBut in fact, streams aren't\nlists, they're streams. And\n\n884\n00:48:46,065 --> 00:48:47,240\nthe image you should have\nis something a little\n\n885\n00:48:47,240 --> 00:48:50,230\nbit more like this.\n\n886\n00:48:50,230 --> 00:48:55,880\nI've got these gadgets connected\nup by this data\n\n887\n00:48:55,880 --> 00:48:57,130\nthat's flowing out of them.\n\n888\n00:48:57,130 --> 00:48:59,960\n\n\n889\n00:48:59,960 --> 00:49:04,190\nAnd here's my original source\nof the streams. It might be\n\n890\n00:49:04,190 --> 00:49:05,980\nstarting to generate\nthe integers.\n\n891\n00:49:05,980 --> 00:49:07,580\nAnd now, what happens\nif I want a result?\n\n892\n00:49:07,580 --> 00:49:10,200\nI tug on the end here.\n\n893\n00:49:10,200 --> 00:49:13,090\nAnd this element says, gee,\nI need some more data.\n\n894\n00:49:13,090 --> 00:49:15,830\nSo this one comes here\nand tugs on that one.\n\n895\n00:49:15,830 --> 00:49:17,890\nAnd it says, gee, I need\nsome more data.\n\n896\n00:49:17,890 --> 00:49:19,960\nAnd this one tugs on this\nthing, which might be a\n\n897\n00:49:19,960 --> 00:49:21,640\nfilter, and says, gee, I\nneed some more data.\n\n898\n00:49:21,640 --> 00:49:24,755\nAnd only as much of this thing\nat the end here gets generated\n\n899\n00:49:24,755 --> 00:49:25,780\nas I tugged.\n\n900\n00:49:25,780 --> 00:49:28,030\nAnd only as much of this stuff\ngoes through the processing\n\n901\n00:49:28,030 --> 00:49:30,760\nunits as I'm pulling\non the end I need.\n\n902\n00:49:30,760 --> 00:49:33,720\nThat's the image you should have\nof the difference between\n\n903\n00:49:33,720 --> 00:49:36,580\nimplementing what we're actually\ngoing to do and if\n\n904\n00:49:36,580 --> 00:49:37,830\nstreams were lists.\n\n905\n00:49:37,830 --> 00:49:40,600\n\n\n906\n00:49:40,600 --> 00:49:42,430\nWell, how do we make\nthis thing?\n\n907\n00:49:42,430 --> 00:49:43,400\nI hope you have the image.\n\n908\n00:49:43,400 --> 00:49:44,947\nThe trick is how to make it.\n\n909\n00:49:44,947 --> 00:49:47,930\n\n\n910\n00:49:47,930 --> 00:49:52,080\nWe want to arrange for a stream\nto be a data structure\n\n911\n00:49:52,080 --> 00:49:55,670\nthat computes itself\nincrementally, an on-demand\n\n912\n00:49:55,670 --> 00:49:56,920\ndata structure.\n\n913\n00:49:56,920 --> 00:49:59,220\n\n\n914\n00:49:59,220 --> 00:50:02,700\nAnd the basic idea is, again,\none of the very basic ideas\n\n915\n00:50:02,700 --> 00:50:04,490\nthat we're seeing throughout\nthe whole course.\n\n916\n00:50:04,490 --> 00:50:07,440\nAnd that is that there's not\na firm distinction between\n\n917\n00:50:07,440 --> 00:50:09,240\nprograms and data.\n\n918\n00:50:09,240 --> 00:50:12,260\nSo what a stream is going to be\nis simultaneously this data\n\n919\n00:50:12,260 --> 00:50:15,270\nstructure that you think of,\nlike the stream of the leaves\n\n920\n00:50:15,270 --> 00:50:16,810\nof this tree.\n\n921\n00:50:16,810 --> 00:50:18,880\nBut at the same time, it's\ngoing to be a very clever\n\n922\n00:50:18,880 --> 00:50:23,550\nprocedure that has the method\nof computing in it.\n\n923\n00:50:23,550 --> 00:50:25,930\nWell, let me try this.\n\n924\n00:50:25,930 --> 00:50:28,460\nIt's going to turn out that we\ndon't need any more mechanism.\n\n925\n00:50:28,460 --> 00:50:31,150\nWe already have everything we\nneed simply from the fact that\n\n926\n00:50:31,150 --> 00:50:32,770\nwe know how to handle\nprocedures\n\n927\n00:50:32,770 --> 00:50:35,460\nas first-class objects.\n\n928\n00:50:35,460 --> 00:50:36,880\nWell, let's go back\nto the key.\n\n929\n00:50:36,880 --> 00:50:39,030\nThe key is, remember, we\nhad these operations.\n\n930\n00:50:39,030 --> 00:50:48,080\nCONS-stream and head and tail.\n\n931\n00:50:48,080 --> 00:50:51,580\nWhen I started, I said you can\nthink about this as CONS and\n\n932\n00:50:51,580 --> 00:50:53,340\nthink about this as CAR and\nthink about that as\n\n933\n00:50:53,340 --> 00:50:55,080\nCDR, but it's not.\n\n934\n00:50:55,080 --> 00:50:57,550\nNow, let's look at what\nthey really are.\n\n935\n00:50:57,550 --> 00:51:09,360\nWell, CONS-stream of x and y is\ngoing to be an abbreviation\n\n936\n00:51:09,360 --> 00:51:19,540\nfor the following thing.\n\n937\n00:51:19,540 --> 00:51:24,470\nCONS form a pair, ordinary CONS,\nof x to a thing called\n\n938\n00:51:24,470 --> 00:51:28,000\ndelay of y.\n\n939\n00:51:28,000 --> 00:51:31,188\n\n\n940\n00:51:31,188 --> 00:51:34,670\nAnd before I explain that, let\nme go and write the rest. The\n\n941\n00:51:34,670 --> 00:51:39,790\nhead of a stream is going\nto be just the CAR.\n\n942\n00:51:39,790 --> 00:51:42,380\n\n\n943\n00:51:42,380 --> 00:51:47,610\nAnd the tail of a stream is\ngoing to be a thing called\n\n944\n00:51:47,610 --> 00:51:56,120\nforce the CDR of the stream.\n\n945\n00:51:56,120 --> 00:51:58,060\nNow let me explain this.\n\n946\n00:51:58,060 --> 00:52:01,420\nDelay is going to be a\nspecial magic thing.\n\n947\n00:52:01,420 --> 00:52:06,240\nWhat delay does is take an\nexpression and produce a\n\n948\n00:52:06,240 --> 00:52:08,380\npromise to compute\nthat expression\n\n949\n00:52:08,380 --> 00:52:10,600\nwhen you ask for it.\n\n950\n00:52:10,600 --> 00:52:11,980\nIt doesn't do any computation\nhere.\n\n951\n00:52:11,980 --> 00:52:14,820\nIt just gives you\na rain check.\n\n952\n00:52:14,820 --> 00:52:17,110\nIt produces a promise.\n\n953\n00:52:17,110 --> 00:52:23,280\nAnd CONS-stream says I'm going\nto put together in a pair x\n\n954\n00:52:23,280 --> 00:52:25,360\nand a promise to compute y.\n\n955\n00:52:25,360 --> 00:52:28,230\n\n\n956\n00:52:28,230 --> 00:52:30,200\nNow, if I want the head, that's\njust the CAR that I put\n\n957\n00:52:30,200 --> 00:52:31,840\nin the pair.\n\n958\n00:52:31,840 --> 00:52:34,350\nAnd the key is that the\ntail is going to be--\n\n959\n00:52:34,350 --> 00:52:39,110\nforce calls in that promise.\n\n960\n00:52:39,110 --> 00:52:43,690\nTail says, well, take\nthat promise and now\n\n961\n00:52:43,690 --> 00:52:44,610\ncall in that promise.\n\n962\n00:52:44,610 --> 00:52:47,430\nAnd then we compute\nthat thing.\n\n963\n00:52:47,430 --> 00:52:48,740\nThat's how this is\ngoing to work.\n\n964\n00:52:48,740 --> 00:52:51,550\nThat's what CONS-stream, head,\nand tail really are.\n\n965\n00:52:51,550 --> 00:52:54,196\n\n\n966\n00:52:54,196 --> 00:52:55,570\nNow, let's see how this works.\n\n967\n00:52:55,570 --> 00:52:58,410\nAnd we'll go through this\nfairly carefully.\n\n968\n00:52:58,410 --> 00:53:01,990\nWe're going to see how this\nworks in this example of\n\n969\n00:53:01,990 --> 00:53:08,650\ncomputing the second prime\nbetween 10,000 and a million.\n\n970\n00:53:08,650 --> 00:53:11,610\nOK, so we start off and we\nhave this expression.\n\n971\n00:53:11,610 --> 00:53:15,820\n\n\n972\n00:53:15,820 --> 00:53:20,380\nThe second prime-- the head of\nthe tail of the result of\n\n973\n00:53:20,380 --> 00:53:24,060\nfiltering for primality\nthe integers between\n\n974\n00:53:24,060 --> 00:53:26,710\n10,000 and 1 million.\n\n975\n00:53:26,710 --> 00:53:28,400\nNow, what is that?\n\n976\n00:53:28,400 --> 00:53:35,790\nWhat that is, that interval\nbetween 10,000 and 1 million,\n\n977\n00:53:35,790 --> 00:53:37,480\nwell, if you trace through\nenumerate interval, there\n\n978\n00:53:37,480 --> 00:53:40,250\nbuilds a CONS-stream.\n\n979\n00:53:40,250 --> 00:53:45,880\nAnd the CONS-stream is the CONS\nof 10,000 to a promise to\n\n980\n00:53:45,880 --> 00:53:54,480\ncompute the integers between\n10,001 and 1 million.\n\n981\n00:53:54,480 --> 00:53:55,750\nSo that's what this\nexpression is.\n\n982\n00:53:55,750 --> 00:53:57,640\nHere I'm using the substitution\nmodel.\n\n983\n00:53:57,640 --> 00:53:59,690\nAnd we can use the substitution\nmodel because we\n\n984\n00:53:59,690 --> 00:54:01,010\ndon't have side effects\nand state.\n\n985\n00:54:01,010 --> 00:54:04,270\n\n\n986\n00:54:04,270 --> 00:54:07,860\nSo I have CONS of 10,000 to a\npromise to compute the rest of\n\n987\n00:54:07,860 --> 00:54:08,380\nthe integers.\n\n988\n00:54:08,380 --> 00:54:09,850\nSo only one integer, so\nfar, got enumerated.\n\n989\n00:54:09,850 --> 00:54:14,380\n\n\n990\n00:54:14,380 --> 00:54:16,580\nWell, I'm going to filter that\nthing for primality.\n\n991\n00:54:16,580 --> 00:54:19,900\n\n\n992\n00:54:19,900 --> 00:54:22,360\nAgain, you go back and look\nat the filter code.\n\n993\n00:54:22,360 --> 00:54:25,460\nWhat the filter will first\ndo is test the head.\n\n994\n00:54:25,460 --> 00:54:31,580\nSo in this case, the filter will\ntest 10,000 and say, oh,\n\n995\n00:54:31,580 --> 00:54:33,500\n10,000's not prime.\n\n996\n00:54:33,500 --> 00:54:36,260\nTherefore, what I have\nto do recursively\n\n997\n00:54:36,260 --> 00:54:39,220\nis filter the tail.\n\n998\n00:54:39,220 --> 00:54:42,550\nAnd what's the tail of it, well,\nthat's the tail of this\n\n999\n00:54:42,550 --> 00:54:46,340\npair with a promise in it.\n\n1000\n00:54:46,340 --> 00:54:49,680\nTail now comes in and says,\nwell, I'm going to force that.\n\n1001\n00:54:49,680 --> 00:54:53,790\nI'm going to force that promise,\nwhich means now I'm\n\n1002\n00:54:53,790 --> 00:55:00,880\ngoing to compute the integers\nbetween 10,001 and 1 million.\n\n1003\n00:55:00,880 --> 00:55:02,970\nOK, so this filter now\nis looking at that.\n\n1004\n00:55:02,970 --> 00:55:07,810\n\n\n1005\n00:55:07,810 --> 00:55:10,100\nThat enumerate itself, well, now\nwe're back in the original\n\n1006\n00:55:10,100 --> 00:55:11,960\nenumerate situation.\n\n1007\n00:55:11,960 --> 00:55:16,920\nThe enumerate is the CONS of the\nfirst thing, 10,001, onto\n\n1008\n00:55:16,920 --> 00:55:19,740\na promise to compute the rest.\n\n1009\n00:55:19,740 --> 00:55:23,060\nSo now the primality filter is\ngoing to go look at 10,001.\n\n1010\n00:55:23,060 --> 00:55:25,120\nIt's going to decide if\nit likes that or not.\n\n1011\n00:55:25,120 --> 00:55:27,550\nIt turns out 10,001\nisn't prime.\n\n1012\n00:55:27,550 --> 00:55:29,610\nSo it'll force it again\nand again and again.\n\n1013\n00:55:29,610 --> 00:55:32,920\n\n\n1014\n00:55:32,920 --> 00:55:37,100\nAnd finally, I think the first\nprime it hits is 10,009.\n\n1015\n00:55:37,100 --> 00:55:40,465\nAnd at that point, it'll stop.\n\n1016\n00:55:40,465 --> 00:55:42,500\nAnd that will be the first\nprime, and then eventually,\n\n1017\n00:55:42,500 --> 00:55:45,240\nit'll need the second prime.\n\n1018\n00:55:45,240 --> 00:55:47,030\nSo at that point, it\nwill go again.\n\n1019\n00:55:47,030 --> 00:55:51,880\nSo you see what happens is that\nno more gets generated\n\n1020\n00:55:51,880 --> 00:55:53,130\nthan you actually need.\n\n1021\n00:55:53,130 --> 00:55:56,690\n\n\n1022\n00:55:56,690 --> 00:56:00,060\nThat enumerator is not going to\ngenerate any more integers\n\n1023\n00:56:00,060 --> 00:56:02,410\nthan the filter asks it for as\nit's pulling in things to\n\n1024\n00:56:02,410 --> 00:56:04,930\ncheck for primality.\n\n1025\n00:56:04,930 --> 00:56:07,290\nAnd the filter is not going to\ngenerate any more stuff than\n\n1026\n00:56:07,290 --> 00:56:11,255\nyou ask it for, which is\nthe head of the tail.\n\n1027\n00:56:11,255 --> 00:56:17,180\nYou see, what's happened is\nwe've put that mixing of\n\n1028\n00:56:17,180 --> 00:56:20,130\ngeneration and test into what\nactually happens in the\n\n1029\n00:56:20,130 --> 00:56:24,250\ncomputer, even though that's\nnot apparently what's\n\n1030\n00:56:24,250 --> 00:56:28,160\nhappening from looking\nat our programs.\n\n1031\n00:56:28,160 --> 00:56:30,230\nOK, well, that seemed easy.\n\n1032\n00:56:30,230 --> 00:56:33,326\nAll of this mechanism got put\ninto this magic delay.\n\n1033\n00:56:33,326 --> 00:56:36,900\nSo you're saying, gee, that must\nbe where the magic is.\n\n1034\n00:56:36,900 --> 00:56:39,070\nBut see there's no magic\nthere either.\n\n1035\n00:56:39,070 --> 00:56:40,610\nYou know what delay is.\n\n1036\n00:56:40,610 --> 00:56:50,040\nDelay on some expression is\njust an abbreviation for--\n\n1037\n00:56:50,040 --> 00:56:53,400\n\n\n1038\n00:56:53,400 --> 00:56:56,490\nwell, what's a promise to\ncompute an expression?\n\n1039\n00:56:56,490 --> 00:57:00,700\nLambda of nil, procedure of no\narguments, which is that\n\n1040\n00:57:00,700 --> 00:57:03,000\nexpression.\n\n1041\n00:57:03,000 --> 00:57:03,930\nThat's what a procedure is.\n\n1042\n00:57:03,930 --> 00:57:06,050\nIt says I'm going to compute\nan expression.\n\n1043\n00:57:06,050 --> 00:57:07,460\nWhat's force?\n\n1044\n00:57:07,460 --> 00:57:10,800\nHow do I take up a promise?\n\n1045\n00:57:10,800 --> 00:57:15,890\nWell, force of some procedure,\na promise, is just run it.\n\n1046\n00:57:15,890 --> 00:57:18,710\n\n\n1047\n00:57:18,710 --> 00:57:20,120\nDone.\n\n1048\n00:57:20,120 --> 00:57:23,580\nSo there's no magic\nthere at all.\n\n1049\n00:57:23,580 --> 00:57:26,440\nWell, what have we done?\n\n1050\n00:57:26,440 --> 00:57:29,510\nWe said the old style,\ntraditional style of\n\n1051\n00:57:29,510 --> 00:57:30,960\nprogramming is more efficient.\n\n1052\n00:57:30,960 --> 00:57:35,260\nAnd the stream thing is\nmore perspicuous.\n\n1053\n00:57:35,260 --> 00:57:40,070\nAnd we managed to make the\nstream procedures run like the\n\n1054\n00:57:40,070 --> 00:57:43,350\nother procedures\nby using delay.\n\n1055\n00:57:43,350 --> 00:57:46,880\nAnd the thing that delay did\nfor us was to de-couple the\n\n1056\n00:57:46,880 --> 00:57:52,150\napparent order of events in our\nprograms from the actual\n\n1057\n00:57:52,150 --> 00:57:54,440\norder of events that happened\nin the machine.\n\n1058\n00:57:54,440 --> 00:57:56,540\nThat's really what\ndelay is doing.\n\n1059\n00:57:56,540 --> 00:57:58,290\nThat's exactly the\nwhole point.\n\n1060\n00:57:58,290 --> 00:58:04,720\nWe've given up the idea that our\nprocedures, as they run,\n\n1061\n00:58:04,720 --> 00:58:09,182\nor as we look at them, mirror\nsome clear notion of time.\n\n1062\n00:58:09,182 --> 00:58:12,960\nAnd by giving that up, we give\ndelay the freedom to arrange\n\n1063\n00:58:12,960 --> 00:58:16,690\nthe order of events in the\ncomputation the way it likes.\n\n1064\n00:58:16,690 --> 00:58:17,610\nThat's the whole idea.\n\n1065\n00:58:17,610 --> 00:58:20,640\nWe de-couple the apparent\norder of events in our\n\n1066\n00:58:20,640 --> 00:58:24,200\nprograms from the actual order\nof events in the computer.\n\n1067\n00:58:24,200 --> 00:58:25,770\nOK, well there's one\nmore detail.\n\n1068\n00:58:25,770 --> 00:58:27,750\nIt's just a technical detail,\nbut it's actually\n\n1069\n00:58:27,750 --> 00:58:29,730\nan important one.\n\n1070\n00:58:29,730 --> 00:58:32,190\nAs you run through these\nrecursive programs unwinding,\n\n1071\n00:58:32,190 --> 00:58:35,360\nyou'll see a lot of things that\nlook like tail of the\n\n1072\n00:58:35,360 --> 00:58:39,320\ntail of the tail.\n\n1073\n00:58:39,320 --> 00:58:41,840\nThat's the kind of thing that\nwould happen as I go CONSing\n\n1074\n00:58:41,840 --> 00:58:43,860\ndown a stream all the way.\n\n1075\n00:58:43,860 --> 00:58:47,170\nAnd if each time I'm doing that,\neach time to compute a\n\n1076\n00:58:47,170 --> 00:58:51,830\ntail, I evaluate a procedure\nwhich then has to go\n\n1077\n00:58:51,830 --> 00:58:54,270\nre-compute its tail, and\nre-compute its tail and\n\n1078\n00:58:54,270 --> 00:58:56,380\nrecompute its tail each time,\nyou can see that's very\n\n1079\n00:58:56,380 --> 00:58:59,610\ninefficient compared to just\nhaving a list where the\n\n1080\n00:58:59,610 --> 00:59:02,510\nelements are all there, and I\ndon't have to re-compute each\n\n1081\n00:59:02,510 --> 00:59:05,290\ntail every time I get\nthe next tail.\n\n1082\n00:59:05,290 --> 00:59:15,030\nSo there's one little hack to\nslightly change what delay is,\n\n1083\n00:59:15,030 --> 00:59:17,380\nand make it a thing which is--\n\n1084\n00:59:17,380 --> 00:59:20,390\nI'll write it this way.\n\n1085\n00:59:20,390 --> 00:59:27,360\nThe actual implementation, delay\nis an abbreviation for\n\n1086\n00:59:27,360 --> 00:59:31,000\nthis thing, memo-proc\nof a procedure.\n\n1087\n00:59:31,000 --> 00:59:35,150\nMemo-proc is a special thing\nthat transforms a procedure.\n\n1088\n00:59:35,150 --> 00:59:39,250\nWhat it does is it takes a\nprocedure of no arguments and\n\n1089\n00:59:39,250 --> 00:59:42,190\nit transforms it into a\nprocedure that'll only have to\n\n1090\n00:59:42,190 --> 00:59:44,806\ndo its computation once.\n\n1091\n00:59:44,806 --> 00:59:48,700\nAnd what I mean by that is,\nyou give it a procedure.\n\n1092\n00:59:48,700 --> 00:59:51,950\nThe result of memo-proc will be\na new procedure, which the\n\n1093\n00:59:51,950 --> 00:59:55,370\nfirst time you call it, will\nrun the original procedure,\n\n1094\n00:59:55,370 --> 01:00:00,040\nremember what result it got, and\nthen from ever on after,\n\n1095\n01:00:00,040 --> 01:00:01,610\nwhen you call it, it just\nwon't have to do the\n\n1096\n01:00:01,610 --> 01:00:02,360\ncomputation.\n\n1097\n01:00:02,360 --> 01:00:05,200\nIt will have cached that\nresult someplace.\n\n1098\n01:00:05,200 --> 01:00:06,550\nAnd here's an implementation\nof memo-proc.\n\n1099\n01:00:06,550 --> 01:00:11,210\n\n\n1100\n01:00:11,210 --> 01:00:12,710\nOnce you have the idea, it's\neasy to implement.\n\n1101\n01:00:12,710 --> 01:00:15,830\nMemo-proc is this little\nthing that has two\n\n1102\n01:00:15,830 --> 01:00:17,390\nlittle flags in there.\n\n1103\n01:00:17,390 --> 01:00:20,320\nIt says, have I already\nbeen run?\n\n1104\n01:00:20,320 --> 01:00:23,620\nAnd initially it says, no, I\nhaven't already been run.\n\n1105\n01:00:23,620 --> 01:00:29,070\nAnd what was the result I got\nthe last time I was run?\n\n1106\n01:00:29,070 --> 01:00:32,200\nSo memo-proc takes a procedure\ncalled proc, and it returns a\n\n1107\n01:00:32,200 --> 01:00:34,360\nnew procedure of no arguments.\n\n1108\n01:00:34,360 --> 01:00:38,610\nProc is supposed to be a\nprocedure of no arguments.\n\n1109\n01:00:38,610 --> 01:00:42,970\nAnd it says, oh, if I'm not\nalready run, then I'm going to\n\n1110\n01:00:42,970 --> 01:00:44,430\ndo a sequence of things.\n\n1111\n01:00:44,430 --> 01:00:48,450\nI'm going to compute proc,\nI'm going to save that.\n\n1112\n01:00:48,450 --> 01:00:51,140\nI'm going to stash that in\nthe variable result.\n\n1113\n01:00:51,140 --> 01:00:53,510\nI'm going to make a note to\nmyself that I've already been\n\n1114\n01:00:53,510 --> 01:00:56,610\nrun, and then I'll return\nthe result.\n\n1115\n01:00:56,610 --> 01:00:59,010\nSo that's if you compute it\nif it's not already run.\n\n1116\n01:00:59,010 --> 01:01:01,040\nIf you call it and it's already\nbeen run, it just\n\n1117\n01:01:01,040 --> 01:01:03,420\nreturns the result.\n\n1118\n01:01:03,420 --> 01:01:08,400\nSo that's a little clever\nhack called memoization.\n\n1119\n01:01:08,400 --> 01:01:12,100\nAnd in this case, it short\ncircuits having to re-compute\n\n1120\n01:01:12,100 --> 01:01:15,270\nthe tail of the tail of the tail\nof the tail of the tail.\n\n1121\n01:01:15,270 --> 01:01:17,810\nSo there isn't even that\nkind of inefficiency.\n\n1122\n01:01:17,810 --> 01:01:20,590\nAnd in fact, the streams will\nrun with pretty much the same\n\n1123\n01:01:20,590 --> 01:01:24,210\nefficiency as the other\nprograms precisely.\n\n1124\n01:01:24,210 --> 01:01:28,110\nAnd remember, again, the whole\nidea of this is that we've\n\n1125\n01:01:28,110 --> 01:01:32,390\nused the fact that there's no\nreally good dividing line\n\n1126\n01:01:32,390 --> 01:01:33,610\nbetween procedures and data.\n\n1127\n01:01:33,610 --> 01:01:36,510\nWe've written data structures\nthat, in fact, are sort of\n\n1128\n01:01:36,510 --> 01:01:38,760\nlike procedures.\n\n1129\n01:01:38,760 --> 01:01:45,280\nAnd what that's allowed us to\ndo is take an example of a\n\n1130\n01:01:45,280 --> 01:01:49,620\ncommon control structure,\nin this place iteration.\n\n1131\n01:01:49,620 --> 01:01:52,460\nAnd we've built a data structure\nwhich, since itself\n\n1132\n01:01:52,460 --> 01:01:54,530\nis a procedure, kind of has\nthis iteration control\n\n1133\n01:01:54,530 --> 01:01:55,496\nstructure in it.\n\n1134\n01:01:55,496 --> 01:01:58,650\nAnd that's really what\nstreams are.\n\n1135\n01:01:58,650 --> 01:01:59,900\nOK, questions?\n\n1136\n01:01:59,900 --> 01:02:03,950\n\n\n1137\n01:02:03,950 --> 01:02:06,110\nAUDIENCE: Your description\nof tail-tail-tail, if I\n\n1138\n01:02:06,110 --> 01:02:10,050\nunderstand it correctly, force\nis actually execution of a\n\n1139\n01:02:10,050 --> 01:02:13,052\nprocedure, if it's done without\nthis memo-proc thing.\n\n1140\n01:02:13,052 --> 01:02:16,380\nAnd you implied that memo-proc\ngets around that problem.\n\n1141\n01:02:16,380 --> 01:02:20,580\nDoesn't it only get around it\nif tail-tail-tail is always\n\n1142\n01:02:20,580 --> 01:02:22,550\nexecuting exactly the same--\n\n1143\n01:02:22,550 --> 01:02:23,500\nPROFESSOR: Oh, that's--\n\n1144\n01:02:23,500 --> 01:02:23,910\nsure.\n\n1145\n01:02:23,910 --> 01:02:26,050\nAUDIENCE: I guess I\nmissed that point.\n\n1146\n01:02:26,050 --> 01:02:26,540\nPROFESSOR: Oh, sure.\n\n1147\n01:02:26,540 --> 01:02:27,790\nI mean the point is--\n\n1148\n01:02:27,790 --> 01:02:31,160\n\n\n1149\n01:02:31,160 --> 01:02:31,290\nyeah.\n\n1150\n01:02:31,290 --> 01:02:34,160\nI mean I have to do a\ncomputation to get the answer.\n\n1151\n01:02:34,160 --> 01:02:37,590\nBut the point is, once I've\nfound the tail of the stream,\n\n1152\n01:02:37,590 --> 01:02:39,530\nto get the tail of the tail,\nI shouldn't have had to\n\n1153\n01:02:39,530 --> 01:02:42,980\nre-compute the first tail.\n\n1154\n01:02:42,980 --> 01:02:45,370\nSee, and if I didn't use\nmemo-proc, that re-computation\n\n1155\n01:02:45,370 --> 01:02:46,460\nwould have been done.\n\n1156\n01:02:46,460 --> 01:02:47,710\nAUDIENCE: I understand now.\n\n1157\n01:02:47,710 --> 01:02:50,830\n\n\n1158\n01:02:50,830 --> 01:02:52,550\nAUDIENCE: In one of your\nexamples, you mentioned that\n\n1159\n01:02:52,550 --> 01:02:55,010\nwe were able to use the\nsubstitution model because\n\n1160\n01:02:55,010 --> 01:02:56,830\nthere are no side effects.\n\n1161\n01:02:56,830 --> 01:03:01,040\nWhat if we had a single\nprocessing unit--\n\n1162\n01:03:01,040 --> 01:03:03,620\nif we had a side effect,\nif we had a state?\n\n1163\n01:03:03,620 --> 01:03:09,120\nCould we still practically\nbuild the stream model?\n\n1164\n01:03:09,120 --> 01:03:09,530\nPROFESSOR: Maybe.\n\n1165\n01:03:09,530 --> 01:03:10,540\nThat's a hard question.\n\n1166\n01:03:10,540 --> 01:03:15,540\nI'm going to talk a little bit\nlater about the places where\n\n1167\n01:03:15,540 --> 01:03:18,960\nsubstitution and side effects\ndon't really mix very well.\n\n1168\n01:03:18,960 --> 01:03:21,170\nBut in general, I think the\nanswer is unless you're very\n\n1169\n01:03:21,170 --> 01:03:23,920\ncareful, any amount of side\neffect is going to mess up\n\n1170\n01:03:23,920 --> 01:03:25,170\neverything.\n\n1171\n01:03:25,170 --> 01:03:35,490\n\n\n1172\n01:03:35,490 --> 01:03:36,150\nAUDIENCE: Sorry, I didn't\nquite understand\n\n1173\n01:03:36,150 --> 01:03:39,410\nthe memo-proc operation.\n\n1174\n01:03:39,410 --> 01:03:41,990\nWhen do you execute\nthe lambda?\n\n1175\n01:03:41,990 --> 01:03:46,270\nIn other words, when memo-proc\nis executed, just this lambda\n\n1176\n01:03:46,270 --> 01:03:47,600\nexpression is being generated.\n\n1177\n01:03:47,600 --> 01:03:50,390\nBut it's not clear to me\nwhen it's executed.\n\n1178\n01:03:50,390 --> 01:03:51,350\nPROFESSOR: Right.\n\n1179\n01:03:51,350 --> 01:03:53,890\nWhat memo-proc does-- remember,\nthe thing that's\n\n1180\n01:03:53,890 --> 01:03:57,290\ngoing into memo-proc, the thing\nproc, is a procedure of\n\n1181\n01:03:57,290 --> 01:03:57,930\nno arguments.\n\n1182\n01:03:57,930 --> 01:04:00,390\nAnd someday, you're\ngoing to call it.\n\n1183\n01:04:00,390 --> 01:04:03,350\nMemo-proc translates that\nprocedure into another\n\n1184\n01:04:03,350 --> 01:04:05,110\nprocedure of no arguments,\nwhich someday\n\n1185\n01:04:05,110 --> 01:04:06,620\nyou're going to call.\n\n1186\n01:04:06,620 --> 01:04:09,890\nThat's that lambda.\n\n1187\n01:04:09,890 --> 01:04:17,370\nSo here, where I initially\nbuilt as my tail of the\n\n1188\n01:04:17,370 --> 01:04:20,680\nstream, say, this procedure\nof no arguments, which\n\n1189\n01:04:20,680 --> 01:04:24,100\nsomeday I'll call.\n\n1190\n01:04:24,100 --> 01:04:27,130\nInstead, I'm going to have\nthe tail of the stream be\n\n1191\n01:04:27,130 --> 01:04:30,650\nmemo-proc of it, which\nsomeday I'll call.\n\n1192\n01:04:30,650 --> 01:04:35,340\nSo that lambda of nil, that gets\ncalled when you call the\n\n1193\n01:04:35,340 --> 01:04:40,990\nmemo-proc, when you call the\nresult of that memo-proc,\n\n1194\n01:04:40,990 --> 01:04:44,400\nwhich would be ordinarily when\nyou would have called the\n\n1195\n01:04:44,400 --> 01:04:47,642\noriginal thing that\nyou set it.\n\n1196\n01:04:47,642 --> 01:04:49,690\nAUDIENCE: OK, the reason I ask\nis I had a feeling that when\n\n1197\n01:04:49,690 --> 01:04:52,610\nyou call memo-proc, you just\nreturn this lambda.\n\n1198\n01:04:52,610 --> 01:04:53,770\nPROFESSOR: That's right.\n\n1199\n01:04:53,770 --> 01:04:58,100\nWhen you call memo-proc,\nyou return the lambda.\n\n1200\n01:04:58,100 --> 01:05:00,090\nYou never evaluate the\nexpression at all, until the\n\n1201\n01:05:00,090 --> 01:05:02,270\nfirst time that you would\nhave evaluated it.\n\n1202\n01:05:02,270 --> 01:05:07,590\n\n\n1203\n01:05:07,590 --> 01:05:10,000\nAUDIENCE: Do I understand it\nright that you actually have\n\n1204\n01:05:10,000 --> 01:05:12,980\nto build the list up, but\nthe elements of the\n\n1205\n01:05:12,980 --> 01:05:14,240\nlist don't get evaluated?\n\n1206\n01:05:14,240 --> 01:05:15,630\nThe expressions don't\nget evaluated?\n\n1207\n01:05:15,630 --> 01:05:18,540\nBut at each stage, you actually\nare building a list.\n\n1208\n01:05:18,540 --> 01:05:19,750\nPROFESSOR: That's--\n\n1209\n01:05:19,750 --> 01:05:20,700\nI really should have\nsaid this.\n\n1210\n01:05:20,700 --> 01:05:22,270\nThat's a really good point.\n\n1211\n01:05:22,270 --> 01:05:23,660\nNo, it's not quite right.\n\n1212\n01:05:23,660 --> 01:05:25,080\nBecause what happens is this.\n\n1213\n01:05:25,080 --> 01:05:26,890\nLet me draw this as pairs.\n\n1214\n01:05:26,890 --> 01:05:29,710\nSuppose I'm going to make a\nbig stream, like enumerate\n\n1215\n01:05:29,710 --> 01:05:32,740\ninterval, 1 through 1 billion.\n\n1216\n01:05:32,740 --> 01:05:43,045\nWhat that is, is a pair with\na 1 and a promise.\n\n1217\n01:05:43,045 --> 01:05:46,520\n\n\n1218\n01:05:46,520 --> 01:05:47,890\nThat's exactly what it is.\n\n1219\n01:05:47,890 --> 01:05:49,140\nNothing got built up.\n\n1220\n01:05:49,140 --> 01:05:51,600\n\n\n1221\n01:05:51,600 --> 01:05:56,370\nWhen I go and force this,\nand say, what happens?\n\n1222\n01:05:56,370 --> 01:06:00,530\nWell, this thing is now also\nrecursively a CONS.\n\n1223\n01:06:00,530 --> 01:06:07,770\nSo that this promise now is the\nnext thing, which is a 2\n\n1224\n01:06:07,770 --> 01:06:11,350\nand a promise to do more.\n\n1225\n01:06:11,350 --> 01:06:14,470\nAnd so on and so on and so on.\n\n1226\n01:06:14,470 --> 01:06:18,200\nSo nothing gets built up until\nyou walk down the stream.\n\n1227\n01:06:18,200 --> 01:06:20,790\nBecause what's sitting here is\nnot the list, but a promise to\n\n1228\n01:06:20,790 --> 01:06:24,250\ngenerate the list.\nAnd by promise,\n\n1229\n01:06:24,250 --> 01:06:25,500\ntechnically I mean procedure.\n\n1230\n01:06:25,500 --> 01:06:28,050\n\n\n1231\n01:06:28,050 --> 01:06:30,485\nSo it doesn't get built up.\n\n1232\n01:06:30,485 --> 01:06:34,280\nYeah, I should have said\nthat before this point.\n\n1233\n01:06:34,280 --> 01:06:34,490\nOK.\n\n1234\n01:06:34,490 --> 01:06:34,790\nThank you.\n\n1235\n01:06:34,790 --> 01:06:36,340\nLet's take a break.\n\n1236\n01:06:36,340 --> 01:06:55,828\n\n"
  },
  {
    "path": "SrtEN/lec6b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:20,970\n\n\n1\n00:00:20,970 --> 00:00:24,580\nPROFESSOR: OK, well, we've been\nlooking at streams, this\n\n2\n00:00:24,580 --> 00:00:28,870\nsignal processing way of putting\nsystems together.\n\n3\n00:00:28,870 --> 00:00:35,200\nAnd remember, the key idea is\nthat we decouple the apparent\n\n4\n00:00:35,200 --> 00:00:38,480\norder of events in our programs\nfrom the actual order\n\n5\n00:00:38,480 --> 00:00:40,635\nof events in the computer.\n\n6\n00:00:40,635 --> 00:00:43,630\nAnd that means that we can start\ndealing with very long\n\n7\n00:00:43,630 --> 00:00:46,340\nstreams and only having\nto generate\n\n8\n00:00:46,340 --> 00:00:47,500\nthe elements on demand.\n\n9\n00:00:47,500 --> 00:00:50,310\nThat sort of on-demand\ncomputation is built into the\n\n10\n00:00:50,310 --> 00:00:51,560\nstream's data structure.\n\n11\n00:00:51,560 --> 00:00:54,450\n\n\n12\n00:00:54,450 --> 00:00:55,990\nSo if we have a very long\nstream, we only\n\n13\n00:00:55,990 --> 00:00:58,040\ncompute what we need.\n\n14\n00:00:58,040 --> 00:01:00,750\nThe things only get computed\nwhen we actually ask for them.\n\n15\n00:01:00,750 --> 00:01:02,110\nWell, what are examples?\n\n16\n00:01:02,110 --> 00:01:04,800\nAre they actually\nasking for them?\n\n17\n00:01:04,800 --> 00:01:11,050\nFor instance, we might ask for\nthe n-th element of a stream.\n\n18\n00:01:11,050 --> 00:01:16,360\n\n\n19\n00:01:16,360 --> 00:01:18,130\nHere's a procedure that\ncomputes the n-th\n\n20\n00:01:18,130 --> 00:01:20,400\nelement of a stream.\n\n21\n00:01:20,400 --> 00:01:23,810\nAn integer n, the n-th element\nof some stream s, and we just\n\n22\n00:01:23,810 --> 00:01:25,570\nrecursively walk down\nthe stream.\n\n23\n00:01:25,570 --> 00:01:27,960\nAnd the end of 0, we\ncompute the head.\n\n24\n00:01:27,960 --> 00:01:32,350\nOtherwise, it's the n-th the\nminus 1 element of the tail of\n\n25\n00:01:32,350 --> 00:01:34,310\nthe stream.\n\n26\n00:01:34,310 --> 00:01:36,570\nThose two are just like for\nLisp, but the difference is\n\n27\n00:01:36,570 --> 00:01:39,580\nthose elements aren't going to\nget computed until we walk\n\n28\n00:01:39,580 --> 00:01:41,700\ndown, taking successive n-ths.\n\n29\n00:01:41,700 --> 00:01:43,630\nSo that's one way\nthat the stream\n\n30\n00:01:43,630 --> 00:01:45,910\nelements might get forced.\n\n31\n00:01:45,910 --> 00:01:47,980\nAnd another way, here's\na little procedure\n\n32\n00:01:47,980 --> 00:01:49,300\nthat prints a stream.\n\n33\n00:01:49,300 --> 00:01:54,150\nWe say print a stream, so\nto print a stream s.\n\n34\n00:01:54,150 --> 00:01:55,315\nWell, what do we do?\n\n35\n00:01:55,315 --> 00:01:58,270\nWe print the head of the stream,\nand that will cause\n\n36\n00:01:58,270 --> 00:01:59,720\nthe head to be computed.\n\n37\n00:01:59,720 --> 00:02:04,990\nAnd then we recursively print\nstream the tail of the stream.\n\n38\n00:02:04,990 --> 00:02:07,190\nAnd if we're already done,\nmaybe we have to return\n\n39\n00:02:07,190 --> 00:02:09,660\nsomething about the\nmessage done.\n\n40\n00:02:09,660 --> 00:02:12,250\nOK, and then so if you make a\nstream, you could say here's\n\n41\n00:02:12,250 --> 00:02:14,310\nthe stream, this very\nlong stream.\n\n42\n00:02:14,310 --> 00:02:16,990\nAnd then you say print the\nstream, and the elements of\n\n43\n00:02:16,990 --> 00:02:20,550\nthe stream will get computed\nsuccessively as that print\n\n44\n00:02:20,550 --> 00:02:21,320\ncalls them.\n\n45\n00:02:21,320 --> 00:02:24,680\nThey won't get all computed\ninitially.\n\n46\n00:02:24,680 --> 00:02:30,190\nSo in this way, we can deal with\nsome very long streams.\n\n47\n00:02:30,190 --> 00:02:33,600\nWell, how long can\na stream be?\n\n48\n00:02:33,600 --> 00:02:36,360\nWell, it can be infinitely\nlong.\n\n49\n00:02:36,360 --> 00:02:38,920\nLet's look at an example\nhere on the computer.\n\n50\n00:02:38,920 --> 00:02:43,400\nI could walk up to this\ncomputer, and I could say--\n\n51\n00:02:43,400 --> 00:02:52,270\nhow about we'll define the\nstream of integers starting\n\n52\n00:02:52,270 --> 00:02:56,170\nwith some number N, the stream\nof positive integers starting\n\n53\n00:02:56,170 --> 00:02:57,420\nwith some number n.\n\n54\n00:02:57,420 --> 00:02:59,760\n\n\n55\n00:02:59,760 --> 00:03:12,990\nAnd that's cons-stream\nof n onto the\n\n56\n00:03:12,990 --> 00:03:19,010\nintegers from one more.\n\n57\n00:03:19,010 --> 00:03:24,680\n\n\n58\n00:03:24,680 --> 00:03:25,930\nSo there are the integers.\n\n59\n00:03:25,930 --> 00:03:28,800\n\n\n60\n00:03:28,800 --> 00:03:31,500\nThen I could say let's\nget all the integers.\n\n61\n00:03:31,500 --> 00:03:34,410\n\n\n62\n00:03:34,410 --> 00:03:43,330\ndefine the stream of integers\nto be the integers\n\n63\n00:03:43,330 --> 00:03:44,580\nstarting with 1.\n\n64\n00:03:44,580 --> 00:03:48,840\n\n\n65\n00:03:48,840 --> 00:03:54,950\nAnd now if I say something like\nwhat's the what's the\n\n66\n00:03:54,950 --> 00:04:02,995\n20th integer.\n\n67\n00:04:02,995 --> 00:04:07,270\nSo it's 21 because we\nstart counting at 0.\n\n68\n00:04:07,270 --> 00:04:09,450\nOr I can do more complicated\nthings.\n\n69\n00:04:09,450 --> 00:04:10,840\nLet me to define a little\npredicate here.\n\n70\n00:04:10,840 --> 00:04:13,740\n\n\n71\n00:04:13,740 --> 00:04:19,160\nHow about define no-seven.\n\n72\n00:04:19,160 --> 00:04:22,126\nIt's going to test an\ninteger, and it's\n\n73\n00:04:22,126 --> 00:04:23,376\ngoing to say it's not.\n\n74\n00:04:23,376 --> 00:04:28,820\n\n\n75\n00:04:28,820 --> 00:04:38,175\nI take the remainder of\nx by 7, I don't get 0.\n\n76\n00:04:38,175 --> 00:04:41,890\n\n\n77\n00:04:41,890 --> 00:04:50,360\nAnd then I could say define the\nintegers with no sevens to\n\n78\n00:04:50,360 --> 00:04:58,885\nbe, take all the integers and\nfilter them to have no sevens.\n\n79\n00:04:58,885 --> 00:05:11,570\n\n\n80\n00:05:11,570 --> 00:05:14,060\nSo now I've got the stream of\nall the integers that are not\n\n81\n00:05:14,060 --> 00:05:16,360\ndivisible by seven.\n\n82\n00:05:16,360 --> 00:05:25,420\nSo if I say what's the 100th\ninteger and the list not\n\n83\n00:05:25,420 --> 00:05:28,320\ndivisible by seven, I get 117.\n\n84\n00:05:28,320 --> 00:05:35,270\nOr if I'd like to say well,\ngee, what are all of them?\n\n85\n00:05:35,270 --> 00:05:39,810\nSo I could say print stream\nall these integers with no\n\n86\n00:05:39,810 --> 00:05:41,700\nseven, it goes off printing.\n\n87\n00:05:41,700 --> 00:05:45,100\n\n\n88\n00:05:45,100 --> 00:05:47,070\nYou may have to wait a very\nlong time to see them all.\n\n89\n00:05:47,070 --> 00:05:52,670\n\n\n90\n00:05:52,670 --> 00:05:56,040\nWell, you can start asking, gee,\nis it really true that\n\n91\n00:05:56,040 --> 00:05:59,080\nthis data structure with\nthe integers is\n\n92\n00:05:59,080 --> 00:06:01,100\nreally all the integers?\n\n93\n00:06:01,100 --> 00:06:04,053\nAnd let me draw a picture of\nthat program I just wrote.\n\n94\n00:06:04,053 --> 00:06:08,170\n\n\n95\n00:06:08,170 --> 00:06:09,980\nHere's the definition of the\nintegers again that I just\n\n96\n00:06:09,980 --> 00:06:14,850\ntyped in, Right it's a cons of\nthe first integer under the\n\n97\n00:06:14,850 --> 00:06:18,120\ninteger starting with the\nrest. Now, we can make a\n\n98\n00:06:18,120 --> 00:06:19,775\npicture of that and see\nwhat it looks like.\n\n99\n00:06:19,775 --> 00:06:22,720\n\n\n100\n00:06:22,720 --> 00:06:26,270\nConceptually, what I have is\na box that's the integer\n\n101\n00:06:26,270 --> 00:06:27,420\nstarting with n.\n\n102\n00:06:27,420 --> 00:06:31,900\nIt takes in some number\nn, and it's going to\n\n103\n00:06:31,900 --> 00:06:35,050\nreturn a stream of--\n\n104\n00:06:35,050 --> 00:06:37,705\nthis infinite stream of all\nintegers starting with n.\n\n105\n00:06:37,705 --> 00:06:38,690\nAnd what do I do?\n\n106\n00:06:38,690 --> 00:06:42,470\nWell, this is an integers\nfrom box.\n\n107\n00:06:42,470 --> 00:06:45,070\n\n\n108\n00:06:45,070 --> 00:06:45,800\nWhat's it got in it?\n\n109\n00:06:45,800 --> 00:06:54,110\nWell, it takes in this n,\nand it increments it.\n\n110\n00:06:54,110 --> 00:06:58,030\n\n\n111\n00:06:58,030 --> 00:07:01,920\nAnd then it puts the result\ninto recursively another\n\n112\n00:07:01,920 --> 00:07:03,170\ninteger's from box.\n\n113\n00:07:03,170 --> 00:07:06,870\n\n\n114\n00:07:06,870 --> 00:07:10,630\nIt takes the result of that and\nthe original n and puts\n\n115\n00:07:10,630 --> 00:07:14,270\nthose together with a cons\nand forms a stream.\n\n116\n00:07:14,270 --> 00:07:18,530\nSo that's a picture of\nthat program I wrote.\n\n117\n00:07:18,530 --> 00:07:18,780\nLet's see.\n\n118\n00:07:18,780 --> 00:07:21,380\nThese kind of diagrams we\nfirst saw drawn by Peter\n\n119\n00:07:21,380 --> 00:07:23,320\nHenderson, the same guy who\ndid the Escher language.\n\n120\n00:07:23,320 --> 00:07:26,170\nWe call them Henderson diagrams.\nAnd the convention\n\n121\n00:07:26,170 --> 00:07:28,530\nhere is that you put these\nthings together.\n\n122\n00:07:28,530 --> 00:07:33,260\nAnd the solid lines are things\ncoming out are streams, and\n\n123\n00:07:33,260 --> 00:07:37,270\ndotted lines are initial\nvalues going in.\n\n124\n00:07:37,270 --> 00:07:39,440\nSo this one has the shape of--\n\n125\n00:07:39,440 --> 00:07:41,820\nit takes in some integer,\nsome initial value,\n\n126\n00:07:41,820 --> 00:07:43,070\nand outputs a stream.\n\n127\n00:07:43,070 --> 00:07:46,410\n\n\n128\n00:07:46,410 --> 00:07:48,380\nAgain, you can ask.\n\n129\n00:07:48,380 --> 00:07:49,710\nIs that data structure integers\n\n130\n00:07:49,710 --> 00:07:52,340\nreally all the integers?\n\n131\n00:07:52,340 --> 00:07:55,190\nOr is it is something that's\ncleverly arranged so that\n\n132\n00:07:55,190 --> 00:07:58,190\nwhenever you look for an integer\nyou find it there?\n\n133\n00:07:58,190 --> 00:07:59,780\nThat's sort of a philosophical\nquestion, right?\n\n134\n00:07:59,780 --> 00:08:03,090\nIf something is there whenever\nyou look, is it\n\n135\n00:08:03,090 --> 00:08:04,450\nreally there or not?\n\n136\n00:08:04,450 --> 00:08:07,970\nIt's sort of the same sense\nin which the money in your\n\n137\n00:08:07,970 --> 00:08:09,420\nsavings account is\nin the bank.\n\n138\n00:08:09,420 --> 00:08:12,380\n\n\n139\n00:08:12,380 --> 00:08:19,830\nWell, let me do another\nexample.\n\n140\n00:08:19,830 --> 00:08:22,040\nGee, we started the course\nwith an algorithm from\n\n141\n00:08:22,040 --> 00:08:25,910\nAlexandria, which was Heron of\nAlexandria's algorithm for\n\n142\n00:08:25,910 --> 00:08:28,470\ncomputing the square root.\n\n143\n00:08:28,470 --> 00:08:32,030\nLet's take a look at another\nAlexandrian algorithm.\n\n144\n00:08:32,030 --> 00:08:37,860\nThis one is Eratosthenes method\nfor computing all of\n\n145\n00:08:37,860 --> 00:08:39,110\nthe primes.\n\n146\n00:08:39,110 --> 00:08:41,169\n\n\n147\n00:08:41,169 --> 00:08:42,830\nIt is called the Sieve\nof Eratosthenes.\n\n148\n00:08:42,830 --> 00:08:51,830\nAnd what you do is you start\nout, and you list all the\n\n149\n00:08:51,830 --> 00:08:53,880\nintegers, say, starting\nwith 2.\n\n150\n00:08:53,880 --> 00:08:55,890\nAnd then you take the first\ninteger, and you say, oh,\n\n151\n00:08:55,890 --> 00:08:57,310\nthat's prime.\n\n152\n00:08:57,310 --> 00:08:59,600\nAnd then you go look at the\nrest, and you cross out all\n\n153\n00:08:59,600 --> 00:09:01,230\nthe things divisible by 2.\n\n154\n00:09:01,230 --> 00:09:05,250\nSo I cross out this\nand this and this.\n\n155\n00:09:05,250 --> 00:09:07,260\nThis takes a long time because\nI have to do it\n\n156\n00:09:07,260 --> 00:09:11,160\nfor all of the integers.\n\n157\n00:09:11,160 --> 00:09:19,680\nSo I go through the entire list\nof integers, crossing the\n\n158\n00:09:19,680 --> 00:09:22,010\nones divisible by 2.\n\n159\n00:09:22,010 --> 00:09:25,400\nAnd now when I finish with all\nof the integers, I go back and\n\n160\n00:09:25,400 --> 00:09:27,040\nlook and say what\nam I left with?\n\n161\n00:09:27,040 --> 00:09:29,330\nWell, the first thing that\nstarts there is 3.\n\n162\n00:09:29,330 --> 00:09:30,770\nSo 3 is a prime.\n\n163\n00:09:30,770 --> 00:09:33,950\nAnd now I go back through what\nI'm left with, and I cross out\n\n164\n00:09:33,950 --> 00:09:35,120\nall the things divisible by 3.\n\n165\n00:09:35,120 --> 00:09:44,050\nSo let's see, 9 and 15 and 21\nand 27 and 33 and so on.\n\n166\n00:09:44,050 --> 00:09:45,350\nI won't finish.\n\n167\n00:09:45,350 --> 00:09:47,250\nThen I see what I'm left with.\n\n168\n00:09:47,250 --> 00:09:50,860\nAnd the next one I have is 5.\n\n169\n00:09:50,860 --> 00:09:53,470\nNow I can through the rest,\nand I find the first one\n\n170\n00:09:53,470 --> 00:09:54,540\nthat's divisible by 5.\n\n171\n00:09:54,540 --> 00:09:56,590\nI cross out from the remainder\nall the ones that are\n\n172\n00:09:56,590 --> 00:09:58,030\ndivisible by 5.\n\n173\n00:09:58,030 --> 00:10:01,890\nAnd I do that, and then I\ngo through and find 7.\n\n174\n00:10:01,890 --> 00:10:04,170\nGo through all the rest, cross\nout things divisible 7, and I\n\n175\n00:10:04,170 --> 00:10:06,810\nkeep doing that forever.\n\n176\n00:10:06,810 --> 00:10:08,100\nAnd when I'm done, what\nI'm left with is a\n\n177\n00:10:08,100 --> 00:10:10,120\nlist of all the primes.\n\n178\n00:10:10,120 --> 00:10:15,430\nSo that's the Sieve\nof Eratosthenes.\n\n179\n00:10:15,430 --> 00:10:17,930\nLet's look at it as a\ncomputer program.\n\n180\n00:10:17,930 --> 00:10:19,550\nIt's a procedure called sieve.\n\n181\n00:10:19,550 --> 00:10:27,910\n\n\n182\n00:10:27,910 --> 00:10:30,480\nNow, I just write what I did.\n\n183\n00:10:30,480 --> 00:10:34,510\nI'll say to sieve\nsome stream s.\n\n184\n00:10:34,510 --> 00:10:38,770\n\n\n185\n00:10:38,770 --> 00:10:41,280\nI'm going to build a stream\nwhose first element is the\n\n186\n00:10:41,280 --> 00:10:41,870\nhead of this.\n\n187\n00:10:41,870 --> 00:10:44,930\nRemember, I always found the\nfirst thing I was left with,\n\n188\n00:10:44,930 --> 00:10:48,480\nand the rest of it is the result\nof taking the tail of\n\n189\n00:10:48,480 --> 00:10:54,030\nthis, filtering it to throw away\nall the things that are\n\n190\n00:10:54,030 --> 00:10:59,020\ndivisible by the head of this,\nand now sieving the result.\n\n191\n00:10:59,020 --> 00:11:01,980\nThat's just what I did.\n\n192\n00:11:01,980 --> 00:11:05,560\nAnd now to get the infinite\nstream of times, we just sieve\n\n193\n00:11:05,560 --> 00:11:06,900\nall the integers starting\nfrom 2.\n\n194\n00:11:06,900 --> 00:11:14,920\n\n\n195\n00:11:14,920 --> 00:11:16,300\nLet's try that.\n\n196\n00:11:16,300 --> 00:11:19,760\nWe can actually do it.\n\n197\n00:11:19,760 --> 00:11:23,170\nI typed in the definition of\nsieve before, I hope, so I can\n\n198\n00:11:23,170 --> 00:11:35,340\nsay something like define the\nprimes to be the result of\n\n199\n00:11:35,340 --> 00:11:41,350\nsieving the integers\nstarting with 2.\n\n200\n00:11:41,350 --> 00:11:46,760\n\n\n201\n00:11:46,760 --> 00:11:48,100\nSo now I've got this\nlist of primes.\n\n202\n00:11:48,100 --> 00:11:50,990\nThat's all of the\nprimes, right?\n\n203\n00:11:50,990 --> 00:12:01,010\nSo, if for example, what's the\n20th prime in that list?\n\n204\n00:12:01,010 --> 00:12:02,540\n73.\n\n205\n00:12:02,540 --> 00:12:05,080\nSee, and that little pause, it\nwas only at the point when I\n\n206\n00:12:05,080 --> 00:12:06,500\nstarted asking for\nthe 20th prime is\n\n207\n00:12:06,500 --> 00:12:07,750\nthat it started computing.\n\n208\n00:12:07,750 --> 00:12:10,370\n\n\n209\n00:12:10,370 --> 00:12:14,960\nOr I can say here let's look\nat all of the primes.\n\n210\n00:12:14,960 --> 00:12:22,780\n\n\n211\n00:12:22,780 --> 00:12:25,350\nAnd there it goes computing\nall of the primes.\n\n212\n00:12:25,350 --> 00:12:26,970\nOf course, it will take a while\nagain if I want to look\n\n213\n00:12:26,970 --> 00:12:28,570\nat all of them, so\nlet's stop it.\n\n214\n00:12:28,570 --> 00:12:32,030\n\n\n215\n00:12:32,030 --> 00:12:33,130\nLet me draw you a\npicture of that.\n\n216\n00:12:33,130 --> 00:12:34,890\nWell, I've got a picture\nof that.\n\n217\n00:12:34,890 --> 00:12:37,900\nWhat's that program\nreally look like?\n\n218\n00:12:37,900 --> 00:12:39,550\nAgain, some practice with\nthese diagrams, I\n\n219\n00:12:39,550 --> 00:12:42,610\nhave a sieve box.\n\n220\n00:12:42,610 --> 00:12:43,560\nHow does sieve work?\n\n221\n00:12:43,560 --> 00:12:44,810\nIt takes in a stream.\n\n222\n00:12:44,810 --> 00:12:48,850\n\n\n223\n00:12:48,850 --> 00:12:50,870\nIt splits off the head\nfrom the tail.\n\n224\n00:12:50,870 --> 00:12:53,500\nAnd the first thing that's going\nto come out of the sieve\n\n225\n00:12:53,500 --> 00:12:54,970\nis the head of the\noriginal stream.\n\n226\n00:12:54,970 --> 00:12:57,796\n\n\n227\n00:12:57,796 --> 00:13:02,550\nThen it also takes the\nhead and uses that.\n\n228\n00:13:02,550 --> 00:13:03,850\nIt takes the stream.\n\n229\n00:13:03,850 --> 00:13:07,290\nIt filters the tail and uses\nthe head to filter for\n\n230\n00:13:07,290 --> 00:13:09,152\nnondivisibility.\n\n231\n00:13:09,152 --> 00:13:11,710\nIt takes the result of\nnondivisibility and puts it\n\n232\n00:13:11,710 --> 00:13:15,130\nthrough another sieve box and\nputs the result together.\n\n233\n00:13:15,130 --> 00:13:17,890\nSo you can think of this sieve a\nfilter, but notice that it's\n\n234\n00:13:17,890 --> 00:13:19,650\nan infinitely recursive\nfilter.\n\n235\n00:13:19,650 --> 00:13:23,560\nBecause inside the sieve box\nis another sieve box, and\n\n236\n00:13:23,560 --> 00:13:27,130\ninside that is another sieve\nbox and another sieve box.\n\n237\n00:13:27,130 --> 00:13:28,960\nSo you see we start getting\nsome very powerful things.\n\n238\n00:13:28,960 --> 00:13:32,390\nWe're starting to mix this\nsignal processing view of the\n\n239\n00:13:32,390 --> 00:13:35,760\nworld with things like recursion\nthat come from\n\n240\n00:13:35,760 --> 00:13:36,690\ncomputation.\n\n241\n00:13:36,690 --> 00:13:39,210\nAnd there are all sorts of\ninteresting things you can do\n\n242\n00:13:39,210 --> 00:13:40,970\nthat are like this.\n\n243\n00:13:40,970 --> 00:13:42,220\nAll right, any questions?\n\n244\n00:13:42,220 --> 00:13:48,190\n\n\n245\n00:13:48,190 --> 00:13:49,440\nOK, let's take a break.\n\n246\n00:13:49,440 --> 00:14:28,820\n\n\n247\n00:14:28,820 --> 00:14:31,440\nWell, we've been looking at a\ncouple of examples of stream\n\n248\n00:14:31,440 --> 00:14:32,690\nprogramming.\n\n249\n00:14:32,690 --> 00:14:34,790\n\n\n250\n00:14:34,790 --> 00:14:39,920\nAll the stream procedures that\nwe've looked at so far have\n\n251\n00:14:39,920 --> 00:14:41,490\nthe same kind of character.\n\n252\n00:14:41,490 --> 00:14:44,470\nWe've been writing these\nrecursive procedures that kind\n\n253\n00:14:44,470 --> 00:14:46,820\nof generate these stream\nelements one at a time and put\n\n254\n00:14:46,820 --> 00:14:50,030\nthem together in cons-streams.\nSo we've been thinking a lot\n\n255\n00:14:50,030 --> 00:14:51,000\nabout generators.\n\n256\n00:14:51,000 --> 00:14:53,970\nThere's another way to think\nabout stream processing, and\n\n257\n00:14:53,970 --> 00:14:57,840\nthat's to focus not on programs\nthat sort of process\n\n258\n00:14:57,840 --> 00:15:00,840\nthese elements as you walk down\nthe stream, but on things\n\n259\n00:15:00,840 --> 00:15:07,350\nthat kind of process the\nstreams all at once.\n\n260\n00:15:07,350 --> 00:15:09,950\nTo show you what I mean, let\nme start by defining two\n\n261\n00:15:09,950 --> 00:15:12,410\nprocedures that will\ncome in handy.\n\n262\n00:15:12,410 --> 00:15:17,580\nThe first one's called add\nstreams. Add streams takes two\n\n263\n00:15:17,580 --> 00:15:22,330\nstreams: s1 and s2.\n\n264\n00:15:22,330 --> 00:15:22,460\nand.\n\n265\n00:15:22,460 --> 00:15:27,240\nIt's going to produce a stream\nwhose elements are the are the\n\n266\n00:15:27,240 --> 00:15:32,970\ncorresponding sums. We just sort\nof add them element-wise.\n\n267\n00:15:32,970 --> 00:15:36,810\nIf either stream is empty, we\njust return the other one.\n\n268\n00:15:36,810 --> 00:15:42,000\nOtherwise, we're going to make a\nnew stream whose head is the\n\n269\n00:15:42,000 --> 00:15:46,890\nsum of the two heads and whose\ntail is the result of\n\n270\n00:15:46,890 --> 00:15:50,090\nrecursively adding the tails.\n\n271\n00:15:50,090 --> 00:15:52,100\nSo that will produce the\nelement-wise sum of two\n\n272\n00:15:52,100 --> 00:15:53,150\nstreams.\n\n273\n00:15:53,150 --> 00:15:55,830\nAnd then another useful\nthing to have\n\n274\n00:15:55,830 --> 00:15:57,500\naround is scale stream.\n\n275\n00:15:57,500 --> 00:16:04,150\nScale stream takes some constant\nnumber in a stream s\n\n276\n00:16:04,150 --> 00:16:08,140\nand is going to produce the\nstream of elements of s\n\n277\n00:16:08,140 --> 00:16:09,710\nmultiplied by this constant.\n\n278\n00:16:09,710 --> 00:16:14,320\nAnd that's easy, that's just\na map of the function of an\n\n279\n00:16:14,320 --> 00:16:17,040\nelement that multiplies it by\nthe constant, and we map that\n\n280\n00:16:17,040 --> 00:16:18,290\ndown the stream.\n\n281\n00:16:18,290 --> 00:16:20,520\n\n\n282\n00:16:20,520 --> 00:16:23,630\nSo given those two, let me\nshow you what I mean by\n\n283\n00:16:23,630 --> 00:16:27,910\nprograms that operate on\nstreams all at once.\n\n284\n00:16:27,910 --> 00:16:30,200\nLet's look at this.\n\n285\n00:16:30,200 --> 00:16:31,680\nSuppose I write this.\n\n286\n00:16:31,680 --> 00:16:32,930\nI say define--\n\n287\n00:16:32,930 --> 00:16:36,618\n\n\n288\n00:16:36,618 --> 00:16:39,590\nI'll call it ones--\n\n289\n00:16:39,590 --> 00:16:52,190\nto be cons-stream\nof 1 onto ones.\n\n290\n00:16:52,190 --> 00:16:54,860\n\n\n291\n00:16:54,860 --> 00:16:56,950\nWhat's that?\n\n292\n00:16:56,950 --> 00:17:00,530\nThat's going to be an infinite\nstream of ones because the\n\n293\n00:17:00,530 --> 00:17:03,330\nfirst thing is 1.\n\n294\n00:17:03,330 --> 00:17:07,819\nAnd the tail of it is a thing\nwhose first thing is 1 and\n\n295\n00:17:07,819 --> 00:17:11,220\nwhose tail is a thing whose\nfirst thing is 1 and so on and\n\n296\n00:17:11,220 --> 00:17:11,780\nso on and so on.\n\n297\n00:17:11,780 --> 00:17:15,130\nSo that's an infinite\nstream of ones.\n\n298\n00:17:15,130 --> 00:17:17,380\nAnd now using that, let me give\nyou another definition of\n\n299\n00:17:17,380 --> 00:17:18,599\nthe integers.\n\n300\n00:17:18,599 --> 00:17:28,270\nWe can define the\nintegers to be--\n\n301\n00:17:28,270 --> 00:17:32,820\nwell, the first integer we'll\ntake to be 1, this cons-stream\n\n302\n00:17:32,820 --> 00:17:42,790\nof 1 onto the element-wise sum\nonto add streams of the\n\n303\n00:17:42,790 --> 00:17:48,270\nintegers to ones.\n\n304\n00:17:48,270 --> 00:17:54,950\n\n\n305\n00:17:54,950 --> 00:18:01,240\nThe integers are a thing whose\nfirst element is 1, and the\n\n306\n00:18:01,240 --> 00:18:04,940\nrest of them you get by taking\nthose integers and\n\n307\n00:18:04,940 --> 00:18:06,640\nincrementing each one by one.\n\n308\n00:18:06,640 --> 00:18:10,400\nSo the second element of the\nintegers is the first element\n\n309\n00:18:10,400 --> 00:18:13,940\nof the integers incremented\nby one.\n\n310\n00:18:13,940 --> 00:18:15,830\nAnd the rest of that is the\nnext one, and the third\n\n311\n00:18:15,830 --> 00:18:19,690\nelement of that is the same as\nthe first element of the tail\n\n312\n00:18:19,690 --> 00:18:25,050\nof the integers incremented by\none, which is the same as the\n\n313\n00:18:25,050 --> 00:18:28,930\nfirst element of the original\nintegers incremented by one\n\n314\n00:18:28,930 --> 00:18:31,250\nand incremented by one\nagain and so on.\n\n315\n00:18:31,250 --> 00:18:35,240\n\n\n316\n00:18:35,240 --> 00:18:36,310\nThat looks pretty suspicious.\n\n317\n00:18:36,310 --> 00:18:40,150\nSee, notice that it works\nbecause of delay.\n\n318\n00:18:40,150 --> 00:18:42,480\nSee, this looks like--\n\n319\n00:18:42,480 --> 00:18:43,870\nlet's take a look at ones.\n\n320\n00:18:43,870 --> 00:18:46,810\nThis looks like it couldn't even\nbe processed because it's\n\n321\n00:18:46,810 --> 00:18:49,410\nsuddenly saying in order to know\nwhat ones is, I say it's\n\n322\n00:18:49,410 --> 00:18:51,130\ncons-stream of something\nonto ones.\n\n323\n00:18:51,130 --> 00:18:53,220\nThe reason that works is because\nof that very sneaky\n\n324\n00:18:53,220 --> 00:18:55,250\nhidden delay in there.\n\n325\n00:18:55,250 --> 00:18:58,870\nBecause what this really is,\nremember, cons-stream is just\n\n326\n00:18:58,870 --> 00:19:00,290\nan abbreviation.\n\n327\n00:19:00,290 --> 00:19:08,785\nThis really is cons of\n1 onto delay of ones.\n\n328\n00:19:08,785 --> 00:19:12,140\n\n\n329\n00:19:12,140 --> 00:19:15,500\nSo how does that work?\n\n330\n00:19:15,500 --> 00:19:18,020\nYou say I'm going\nto define ones.\n\n331\n00:19:18,020 --> 00:19:20,700\nFirst I see what ones is\nsupposed to be defined as.\n\n332\n00:19:20,700 --> 00:19:27,320\nWell, ones is supposed to be\ndefined as a cons whose first\n\n333\n00:19:27,320 --> 00:19:30,070\npart is 1 and whose second part\nis, well, it's a promise\n\n334\n00:19:30,070 --> 00:19:32,710\nto compute something that\nI don't worry about yet.\n\n335\n00:19:32,710 --> 00:19:34,680\nSo it doesn't bother me that\nat the point I do this\n\n336\n00:19:34,680 --> 00:19:37,270\ndefinition, ones\nisn't defined.\n\n337\n00:19:37,270 --> 00:19:40,670\nHaving run the definition\nnow, ones is defined.\n\n338\n00:19:40,670 --> 00:19:44,920\nSo that when I go and look at\nthe tail of it, it's defined.\n\n339\n00:19:44,920 --> 00:19:46,590\nIt's very sneaky.\n\n340\n00:19:46,590 --> 00:19:48,470\nAnd an integer is\nthe same way.\n\n341\n00:19:48,470 --> 00:19:52,060\nI can refer to integers here\nbecause hidden way down--\n\n342\n00:19:52,060 --> 00:19:53,210\nbecause of this cons-stream.\n\n343\n00:19:53,210 --> 00:19:56,200\nIt's the cons-stream of 1\nonto something that I\n\n344\n00:19:56,200 --> 00:19:57,050\ndon't worry that yet.\n\n345\n00:19:57,050 --> 00:19:58,970\nSo I don't look at it, and I\ndon't notice that integers\n\n346\n00:19:58,970 --> 00:20:01,320\nisn't defined at the point\nwhere I try and run the\n\n347\n00:20:01,320 --> 00:20:02,570\ndefinition.\n\n348\n00:20:02,570 --> 00:20:06,320\n\n\n349\n00:20:06,320 --> 00:20:08,700\nOK, let me draw a picture of\nthat integers thing because it\n\n350\n00:20:08,700 --> 00:20:12,430\nstill maybe seems a\nlittle bit shaky.\n\n351\n00:20:12,430 --> 00:20:15,020\nWhat do I do?\n\n352\n00:20:15,020 --> 00:20:23,490\nI've got the stream of ones, and\nthat sort of comes in and\n\n353\n00:20:23,490 --> 00:20:25,340\ngoes into an adder that's\ngoing to be\n\n354\n00:20:25,340 --> 00:20:26,590\nthis add streams thing.\n\n355\n00:20:26,590 --> 00:20:29,310\n\n\n356\n00:20:29,310 --> 00:20:33,260\nAnd that goes in--\n\n357\n00:20:33,260 --> 00:20:35,760\nthat's going to put\nout the integers.\n\n358\n00:20:35,760 --> 00:20:40,760\n\n\n359\n00:20:40,760 --> 00:20:45,280\nAnd the other thing that goes\ninto the adder here is the\n\n360\n00:20:45,280 --> 00:20:48,060\ninteger, so there's a little\nfeedback loop.\n\n361\n00:20:48,060 --> 00:20:51,930\nAnd all I need to start it off\nis someplace I've got a stick\n\n362\n00:20:51,930 --> 00:20:53,180\nthat initial 1.\n\n363\n00:20:53,180 --> 00:20:57,100\n\n\n364\n00:20:57,100 --> 00:21:00,000\nIn a real signal processing\nthing, this might be a delay\n\n365\n00:21:00,000 --> 00:21:02,910\nelement with that was\ninitialized to 1.\n\n366\n00:21:02,910 --> 00:21:07,860\nBut there's a picture of\nthat ones program.\n\n367\n00:21:07,860 --> 00:21:09,860\nAnd in fact, that looks\na lot like--\n\n368\n00:21:09,860 --> 00:21:13,910\nif you've seen real signal block\ndiagram things, that\n\n369\n00:21:13,910 --> 00:21:17,360\nlooks a lot like accumulators,\nfinite state accumulators.\n\n370\n00:21:17,360 --> 00:21:21,640\nAnd in fact, we can modify this\na little bit to change\n\n371\n00:21:21,640 --> 00:21:25,700\nthis into something that\nintegrates a stream or a\n\n372\n00:21:25,700 --> 00:21:27,440\nfinite state accumulator,\nhowever you like\n\n373\n00:21:27,440 --> 00:21:28,440\nto think about it.\n\n374\n00:21:28,440 --> 00:21:30,370\nSo instead of the ones coming\nin and getting out the\n\n375\n00:21:30,370 --> 00:21:35,460\nintegers, what we'll do is say\nthere's a stream s coming in,\n\n376\n00:21:35,460 --> 00:21:43,210\nand we're going to get out the\nintegral of this, successive\n\n377\n00:21:43,210 --> 00:21:45,700\nvalues of that, and it looks\nalmost the same.\n\n378\n00:21:45,700 --> 00:21:49,220\nThe only thing we're going to\ndo is when s comes in here,\n\n379\n00:21:49,220 --> 00:21:53,010\nbefore we just add it in we're\ngoing to multiply it\n\n380\n00:21:53,010 --> 00:21:54,260\nby some number dt.\n\n381\n00:21:54,260 --> 00:21:57,680\n\n\n382\n00:21:57,680 --> 00:21:58,790\nAnd now what we have\nhere, this is\n\n383\n00:21:58,790 --> 00:22:00,000\nexactly the same thing.\n\n384\n00:22:00,000 --> 00:22:04,020\nWe have a box, which\nis an integrator.\n\n385\n00:22:04,020 --> 00:22:09,790\n\n\n386\n00:22:09,790 --> 00:22:15,250\nAnd it takes in a stream s, and\ninstead of 1 here, we can\n\n387\n00:22:15,250 --> 00:22:19,980\nput the additional value\nfor the integral.\n\n388\n00:22:19,980 --> 00:22:23,940\nAnd that one looks very much\nlike a signal processing block\n\n389\n00:22:23,940 --> 00:22:25,270\ndiagram program.\n\n390\n00:22:25,270 --> 00:22:27,980\nIn fact, here's the procedure\nthat looks exactly like that.\n\n391\n00:22:27,980 --> 00:22:31,490\n\n\n392\n00:22:31,490 --> 00:22:34,010\nFind the integral of a stream.\n\n393\n00:22:34,010 --> 00:22:36,350\nSo an integral's going to take\na stream and produce a new\n\n394\n00:22:36,350 --> 00:22:39,560\nstream, and it takes\nin an initial value\n\n395\n00:22:39,560 --> 00:22:42,230\nand some time constant.\n\n396\n00:22:42,230 --> 00:22:43,040\nAnd what do we do?\n\n397\n00:22:43,040 --> 00:22:45,560\nWell, we internally define this\nthing int, and we make\n\n398\n00:22:45,560 --> 00:22:47,850\nthis internal name so\nwe can feed it back,\n\n399\n00:22:47,850 --> 00:22:49,400\nloop it around itself.\n\n400\n00:22:49,400 --> 00:22:52,380\nAnd int is defined to be\nsomething that starts out at\n\n401\n00:22:52,380 --> 00:22:58,500\nthe initial value, and\nthe rest of it is\n\n402\n00:22:58,500 --> 00:23:01,280\ngotten by adding together.\n\n403\n00:23:01,280 --> 00:23:03,980\nWe take our input stream,\nscale it by dt,\n\n404\n00:23:03,980 --> 00:23:06,880\nand add that to int.\n\n405\n00:23:06,880 --> 00:23:09,130\nAnd now we'll return from all\nthat the value of integral is\n\n406\n00:23:09,130 --> 00:23:10,690\nthis thing int.\n\n407\n00:23:10,690 --> 00:23:13,240\nAnd we use this internal\ndefinition syntax so we could\n\n408\n00:23:13,240 --> 00:23:14,670\nwrite a little internal\ndefinition\n\n409\n00:23:14,670 --> 00:23:15,920\nthat refers to itself.\n\n410\n00:23:15,920 --> 00:23:21,880\n\n\n411\n00:23:21,880 --> 00:23:23,710\nWell, there are all sorts\nof things we can do.\n\n412\n00:23:23,710 --> 00:23:25,500\nLet's try this one.\n\n413\n00:23:25,500 --> 00:23:26,895\nhow about the Fibonacci\nnumbers.\n\n414\n00:23:26,895 --> 00:23:32,625\nYou can say define fibs.\n\n415\n00:23:32,625 --> 00:23:36,350\n\n\n416\n00:23:36,350 --> 00:23:37,985\nWell, what are the Fibonacci\nnumbers?\n\n417\n00:23:37,985 --> 00:23:48,840\nThey're something that starts\nout with 0, and\n\n418\n00:23:48,840 --> 00:23:50,090\nthe next one is 1.\n\n419\n00:23:50,090 --> 00:23:56,260\n\n\n420\n00:23:56,260 --> 00:24:06,470\nAnd the rest of the Fibonacci\nnumbers are gotten by adding\n\n421\n00:24:06,470 --> 00:24:11,000\nthe Fibonacci numbers\nto their own tail.\n\n422\n00:24:11,000 --> 00:24:17,570\n\n\n423\n00:24:17,570 --> 00:24:20,580\nThere's a definition of\nthe Fibonacci numbers.\n\n424\n00:24:20,580 --> 00:24:21,430\nHow does that work?\n\n425\n00:24:21,430 --> 00:24:25,520\nWell, we start off, and someone\nsays compute for us\n\n426\n00:24:25,520 --> 00:24:30,490\nthe Fibonacci numbers, and we're\ngoing to tell you it\n\n427\n00:24:30,490 --> 00:24:31,870\nstarts out with 0 and 1.\n\n428\n00:24:31,870 --> 00:24:35,790\n\n\n429\n00:24:35,790 --> 00:24:40,320\nAnd everything after the 0 and\n1 is gotten by summing two\n\n430\n00:24:40,320 --> 00:24:44,580\nstreams. One is the fibs\nthemselves, and the other one\n\n431\n00:24:44,580 --> 00:24:45,830\nis the tail of the fibs.\n\n432\n00:24:45,830 --> 00:24:48,870\n\n\n433\n00:24:48,870 --> 00:24:52,430\nSo if I know that these start\nout with 0 and 1, I know that\n\n434\n00:24:52,430 --> 00:24:56,435\nthe fibs now start out with 0\nand 1, and the tail of the\n\n435\n00:24:56,435 --> 00:24:58,360\nfibs start out with 1.\n\n436\n00:24:58,360 --> 00:25:00,850\nSo as soon as I know that, I\nknow that the next one here is\n\n437\n00:25:00,850 --> 00:25:04,600\n0 plus 1 is 1, and that tells me\nthat the next one here is 1\n\n438\n00:25:04,600 --> 00:25:06,300\nand the next one here is 1.\n\n439\n00:25:06,300 --> 00:25:09,390\nAnd as soon as I know that, I\nknow that the next one is 2.\n\n440\n00:25:09,390 --> 00:25:11,700\nSo the next one here is 2 and\nthe next one here is 2.\n\n441\n00:25:11,700 --> 00:25:12,950\nAnd this is 3.\n\n442\n00:25:12,950 --> 00:25:14,720\n\n\n443\n00:25:14,720 --> 00:25:18,530\nThis one goes to 3,\nand this is 5.\n\n444\n00:25:18,530 --> 00:25:21,500\nSo it's a perfectly sensible\ndefinition.\n\n445\n00:25:21,500 --> 00:25:22,830\nIt's a one-line definition.\n\n446\n00:25:22,830 --> 00:25:25,590\nAnd again, I could walk over to\nthe computer and type that\n\n447\n00:25:25,590 --> 00:25:28,650\nin, exactly that, and then say\nprint stream the Fibonacci\n\n448\n00:25:28,650 --> 00:25:30,150\nnumbers, and they all\ncome flying out.\n\n449\n00:25:30,150 --> 00:25:32,790\n\n\n450\n00:25:32,790 --> 00:25:34,120\nSee, this is a lot\nlike learning\n\n451\n00:25:34,120 --> 00:25:36,810\nabout recursion again.\n\n452\n00:25:36,810 --> 00:25:41,350\nInstead of thinking that\nrecursive procedures, we have\n\n453\n00:25:41,350 --> 00:25:45,160\nrecursively defined\ndata objects.\n\n454\n00:25:45,160 --> 00:25:48,150\nBut that shouldn't surprise you\nat all, because by now,\n\n455\n00:25:48,150 --> 00:25:50,020\nyou should be coming to really\nbelieve that there's no\n\n456\n00:25:50,020 --> 00:25:53,090\ndifference really between\nprocedures and data.\n\n457\n00:25:53,090 --> 00:25:55,550\nIn fact, in some sense, the\nunderlying streams are\n\n458\n00:25:55,550 --> 00:25:57,240\nprocedures sitting there,\nalthough we don't think of\n\n459\n00:25:57,240 --> 00:25:58,210\nthem that way.\n\n460\n00:25:58,210 --> 00:26:00,910\nSo the fact that we have\nrecursive procedures, well,\n\n461\n00:26:00,910 --> 00:26:03,630\nthen it should be natural that\nwe have recursive data, too.\n\n462\n00:26:03,630 --> 00:26:07,840\n\n\n463\n00:26:07,840 --> 00:26:09,720\nOK, well, this is\nall pretty neat.\n\n464\n00:26:09,720 --> 00:26:13,120\nUnfortunately, there are\nproblems that streams aren't\n\n465\n00:26:13,120 --> 00:26:14,990\ngoing to solve.\n\n466\n00:26:14,990 --> 00:26:17,580\nLet me show you one of them.\n\n467\n00:26:17,580 --> 00:26:21,190\nSee, in the same way, let's\nimagine that we're building an\n\n468\n00:26:21,190 --> 00:26:26,810\nanalog computer to solve some\ndifferential equation like,\n\n469\n00:26:26,810 --> 00:26:33,720\nsay, we want to solve the\nequation y prime dy dt is y\n\n470\n00:26:33,720 --> 00:26:36,390\nsquared, and I'm going to give\nyou some initial value.\n\n471\n00:26:36,390 --> 00:26:38,030\nI'll tell you y of 0 equals 1.\n\n472\n00:26:38,030 --> 00:26:41,060\n\n\n473\n00:26:41,060 --> 00:26:43,690\nLet's say dt is equal\nto something.\n\n474\n00:26:43,690 --> 00:26:46,770\n\n\n475\n00:26:46,770 --> 00:26:49,530\nNow, in the old days, people\nbuilt analog computers to\n\n476\n00:26:49,530 --> 00:26:51,040\nsolve these kinds of things.\n\n477\n00:26:51,040 --> 00:26:53,020\nAnd the way you do that\nis really simple.\n\n478\n00:26:53,020 --> 00:27:01,030\nYou get yourself an integrator,\nlike that one, an\n\n479\n00:27:01,030 --> 00:27:03,055\nintegrator box.\n\n480\n00:27:03,055 --> 00:27:08,530\nAnd we put in the initial\nvalue y of 0 is 1.\n\n481\n00:27:08,530 --> 00:27:10,900\nAnd now if we feed something\nin and get something out,\n\n482\n00:27:10,900 --> 00:27:13,890\nwe'll say, gee, what we're\ngetting out is the answer.\n\n483\n00:27:13,890 --> 00:27:18,420\nAnd what we're going to feed in\nis the derivative, and the\n\n484\n00:27:18,420 --> 00:27:21,490\nderivative is supposed to be\nthe square of the answer.\n\n485\n00:27:21,490 --> 00:27:31,070\nSo if we take these values and\nmap using square, and if I\n\n486\n00:27:31,070 --> 00:27:38,750\nfeed this around, that's how I\nbuild a block diagram for an\n\n487\n00:27:38,750 --> 00:27:42,910\nanalog computer that solves this\ndifferential equation.\n\n488\n00:27:42,910 --> 00:27:45,630\nNow, what we'd like to do is\nwrite a stream program that\n\n489\n00:27:45,630 --> 00:27:47,230\nlooks exactly like that.\n\n490\n00:27:47,230 --> 00:27:49,390\nAnd what do I mean exactly\nlike that?\n\n491\n00:27:49,390 --> 00:28:08,100\nWell, I'd say define y to be the\nintegral of dy starting at\n\n492\n00:28:08,100 --> 00:28:13,790\n1 with 0.001 as a time step.\n\n493\n00:28:13,790 --> 00:28:16,805\nAnd I'd like to say\nthat says this.\n\n494\n00:28:16,805 --> 00:28:19,635\nAnd then I'd like to say, well,\ndy is gotten by mapping\n\n495\n00:28:19,635 --> 00:28:20,850\nthe square along y.\n\n496\n00:28:20,850 --> 00:28:33,510\nSo define dy to be map\nsquare along y.\n\n497\n00:28:33,510 --> 00:28:36,270\nSo there's a stream description\nof this analog\n\n498\n00:28:36,270 --> 00:28:41,410\ncomputer, and unfortunately,\nit doesn't work.\n\n499\n00:28:41,410 --> 00:28:43,715\nAnd you can see why it doesn't\nwork because when I come in\n\n500\n00:28:43,715 --> 00:28:49,550\nand say define y to be the\nintegral of dy, it says, oh,\n\n501\n00:28:49,550 --> 00:28:51,190\nthe integral of y-- huh?\n\n502\n00:28:51,190 --> 00:28:53,710\nOh, that's undefined.\n\n503\n00:28:53,710 --> 00:28:56,860\nSo I can't write this definition\nbefore I've\n\n504\n00:28:56,860 --> 00:28:58,770\nwritten this one.\n\n505\n00:28:58,770 --> 00:29:00,600\nOn the other hand, if I try and\nwrite this one first, it\n\n506\n00:29:00,600 --> 00:29:03,580\nsays, oh, I define y to be the\nmap of square along y?\n\n507\n00:29:03,580 --> 00:29:05,770\nOh, that's not defined yet.\n\n508\n00:29:05,770 --> 00:29:07,730\nSo I can't write this one first,\nand I can't write that\n\n509\n00:29:07,730 --> 00:29:11,580\none first. So I can't quite\nplay this game.\n\n510\n00:29:11,580 --> 00:29:17,560\n\n\n511\n00:29:17,560 --> 00:29:20,460\nWell, is there a way out?\n\n512\n00:29:20,460 --> 00:29:22,200\nSee, we can do that with ones.\n\n513\n00:29:22,200 --> 00:29:27,820\nSee, over here, we did this\nthing ones, and we were able\n\n514\n00:29:27,820 --> 00:29:30,990\nto define ones in terms of ones\nbecause of this delay\n\n515\n00:29:30,990 --> 00:29:34,770\nthat was built inside because\ncons-stream had a delay.\n\n516\n00:29:34,770 --> 00:29:36,070\nNow, why's it sensible?\n\n517\n00:29:36,070 --> 00:29:37,970\nWhy's it sensible for\ncons-stream to be built with\n\n518\n00:29:37,970 --> 00:29:40,730\nthis delay?\n\n519\n00:29:40,730 --> 00:29:43,940\nThe reason is that cons-stream\ncan do a useful thing without\n\n520\n00:29:43,940 --> 00:29:45,950\nlooking at its tail.\n\n521\n00:29:45,950 --> 00:29:49,050\nSee, if I say this is\ncons-stream of 1 onto\n\n522\n00:29:49,050 --> 00:29:52,340\nsomething without knowing\nanything about something, I\n\n523\n00:29:52,340 --> 00:29:54,870\nknow that the stream\nstarts off with 1.\n\n524\n00:29:54,870 --> 00:29:56,660\nThat's why it was sensible\nto build something like\n\n525\n00:29:56,660 --> 00:29:57,910\ncons-stream.\n\n526\n00:29:57,910 --> 00:29:59,960\n\n\n527\n00:29:59,960 --> 00:30:02,610\nSo we put a delay in there,\nand that allows us to have\n\n528\n00:30:02,610 --> 00:30:06,320\nthis sort of self-referential\ndefinition.\n\n529\n00:30:06,320 --> 00:30:08,190\nWell, integral is a little\nbit the same way.\n\n530\n00:30:08,190 --> 00:30:14,620\nSee, notice for an\nintegral, I can--\n\n531\n00:30:14,620 --> 00:30:17,580\nlet's go back and look at\nintegral for a second.\n\n532\n00:30:17,580 --> 00:30:24,010\nSee, notice integral, it makes\nsense to say what's the first\n\n533\n00:30:24,010 --> 00:30:27,390\nthing in the integral without\nknowing the stream that you're\n\n534\n00:30:27,390 --> 00:30:28,970\nintegrating.\n\n535\n00:30:28,970 --> 00:30:30,770\nBecause the first thing in the\nintegral is always going to be\n\n536\n00:30:30,770 --> 00:30:33,140\nthe initial value that\nyou're handed.\n\n537\n00:30:33,140 --> 00:30:37,090\nSo integral could be a procedure\nlike cons-stream.\n\n538\n00:30:37,090 --> 00:30:39,830\nYou could define it, and then\neven before it knows what it's\n\n539\n00:30:39,830 --> 00:30:44,360\nsupposed to be integrating, it\nknows enough to say what its\n\n540\n00:30:44,360 --> 00:30:46,710\ninitial value is.\n\n541\n00:30:46,710 --> 00:30:49,150\nSo we can make a smarter\nintegral, which is aha, you're\n\n542\n00:30:49,150 --> 00:30:51,390\ngoing to give me a stream to\nintegrate and an initial\n\n543\n00:30:51,390 --> 00:30:54,140\nvalue, but I really don't have\nto look at that stream that\n\n544\n00:30:54,140 --> 00:30:56,430\nI'm supposed to integrate until\nyou ask me to work down\n\n545\n00:30:56,430 --> 00:30:58,430\nthe stream.\n\n546\n00:30:58,430 --> 00:31:00,870\nIn other words, integral can be\nlike cons-stream, and you\n\n547\n00:31:00,870 --> 00:31:02,690\ncan expect that there's\ngoing to be a\n\n548\n00:31:02,690 --> 00:31:03,710\ndelay around its integrand.\n\n549\n00:31:03,710 --> 00:31:05,610\nAnd we can write that.\n\n550\n00:31:05,610 --> 00:31:07,650\nHere's a procedure\nthat does that.\n\n551\n00:31:07,650 --> 00:31:09,810\nAnother version of integral,\nand this is almost like the\n\n552\n00:31:09,810 --> 00:31:13,960\nprevious one, except the stream\nit's going to get in is\n\n553\n00:31:13,960 --> 00:31:17,110\ngoing to expect to be\na delayed object.\n\n554\n00:31:17,110 --> 00:31:18,850\nAnd how does this\nintegral work?\n\n555\n00:31:18,850 --> 00:31:21,340\nWell, the little thing it's\ngoing to define inside of\n\n556\n00:31:21,340 --> 00:31:25,350\nitself says on the cons-stream,\nthe initial value\n\n557\n00:31:25,350 --> 00:31:29,750\nis the initial value, but only\ninside of that cons-stream,\n\n558\n00:31:29,750 --> 00:31:32,300\nand remember, there's going to\nbe a hidden delay inside here.\n\n559\n00:31:32,300 --> 00:31:34,950\n\n\n560\n00:31:34,950 --> 00:31:38,260\nOnly inside of that cons-stream\nwill I start\n\n561\n00:31:38,260 --> 00:31:43,180\nlooking at what the actual\ndelayed object is.\n\n562\n00:31:43,180 --> 00:31:45,970\nSo my answer is the first\nthing's the initial value.\n\n563\n00:31:45,970 --> 00:31:50,280\nIf anybody now asks me for my\ntail, at that point, I'm going\n\n564\n00:31:50,280 --> 00:31:52,680\nto force that delayed object--\n\n565\n00:31:52,680 --> 00:31:54,500\nand I'll call that s--\n\n566\n00:31:54,500 --> 00:31:58,300\nand I do the add streams. So\nthis is an integral which is\n\n567\n00:31:58,300 --> 00:31:59,260\nsort of like cons-stream.\n\n568\n00:31:59,260 --> 00:32:04,120\nIt's not going to actually try\nand see what you handed it as\n\n569\n00:32:04,120 --> 00:32:06,080\nthe thing to integrate\nuntil you look\n\n570\n00:32:06,080 --> 00:32:07,330\npast the first element.\n\n571\n00:32:07,330 --> 00:32:10,120\n\n\n572\n00:32:10,120 --> 00:32:13,900\nAnd if we do that and we can\nmake this work, all we have to\n\n573\n00:32:13,900 --> 00:32:24,120\ndo here is say define y to the\nintegral of delay of y, of\n\n574\n00:32:24,120 --> 00:32:27,090\ndelay of dy.\n\n575\n00:32:27,090 --> 00:32:33,380\nSo y is going to be the integral\nof delay of dy\n\n576\n00:32:33,380 --> 00:32:35,280\nstarting at 1, and now\nthis will work.\n\n577\n00:32:35,280 --> 00:32:38,190\nBecause I type in the definition\nof y, and that\n\n578\n00:32:38,190 --> 00:32:40,840\nsays, oh, I'm supposed to use\nthe integral of something I\n\n579\n00:32:40,840 --> 00:32:44,600\ndon't care about right now\nbecause it's a delay.\n\n580\n00:32:44,600 --> 00:32:46,320\nAnd these things, now\nyou define dy.\n\n581\n00:32:46,320 --> 00:32:47,550\nNow, y is defined.\n\n582\n00:32:47,550 --> 00:32:51,700\nSo when I define dy, it can\nsee that definition for y.\n\n583\n00:32:51,700 --> 00:32:52,840\nEverything is now started up.\n\n584\n00:32:52,840 --> 00:32:54,920\nBoth streams have their\nfirst element.\n\n585\n00:32:54,920 --> 00:32:57,030\nAnd then when I start mapping\ndown, looking at successive\n\n586\n00:32:57,030 --> 00:33:00,590\nelements, both y and\ndy are defined.\n\n587\n00:33:00,590 --> 00:33:02,820\nSo there's a little game you\ncan play that goes a little\n\n588\n00:33:02,820 --> 00:33:06,700\nbit beyond just using the delay\nthat's hidden inside\n\n589\n00:33:06,700 --> 00:33:08,660\nstreams. Questions?\n\n590\n00:33:08,660 --> 00:33:13,178\n\n\n591\n00:33:13,178 --> 00:33:14,428\nOK, let's take a break.\n\n592\n00:33:14,428 --> 00:34:07,300\n\n\n593\n00:34:07,300 --> 00:34:11,739\nWell, just before the break,\nI'm not sure if you noticed\n\n594\n00:34:11,739 --> 00:34:14,320\nit, but something nasty\nstarted to happen.\n\n595\n00:34:14,320 --> 00:34:21,040\nWe've been going along with the\nstreams and divorcing time\n\n596\n00:34:21,040 --> 00:34:24,580\nin the programs from time in\nthe computers, and all that\n\n597\n00:34:24,580 --> 00:34:27,840\ndivorcing got hidden inside the\nstreams. And then at the\n\n598\n00:34:27,840 --> 00:34:30,429\nvery end, we saw that sometimes\nin order to really\n\n599\n00:34:30,429 --> 00:34:32,580\ntake advantage of this\nmethod, you have to\n\n600\n00:34:32,580 --> 00:34:34,389\npull out other delays.\n\n601\n00:34:34,389 --> 00:34:36,480\nYou have to write some explicit\ndelays that are not\n\n602\n00:34:36,480 --> 00:34:39,030\nhidden inside that\ncons-stream.\n\n603\n00:34:39,030 --> 00:34:41,400\nAnd I did a very simple example\nwith differential\n\n604\n00:34:41,400 --> 00:34:44,150\nequations, but if you have some\nvery complicated system\n\n605\n00:34:44,150 --> 00:34:47,310\nwith all kinds of self-loops,\nit becomes very, very\n\n606\n00:34:47,310 --> 00:34:49,929\ndifficult to see where you\nneed those delays.\n\n607\n00:34:49,929 --> 00:34:52,389\nAnd if you leave them out by\nmistake, it becomes very, very\n\n608\n00:34:52,389 --> 00:34:55,550\ndifficult to see why the thing\nmaybe isn't working.\n\n609\n00:34:55,550 --> 00:35:00,330\nSo that's kind of mess, that\nby getting this power and\n\n610\n00:35:00,330 --> 00:35:03,030\nallowing us to use delay,\nwe end up with some very\n\n611\n00:35:03,030 --> 00:35:05,080\ncomplicated programming\nsometimes, because it can't\n\n612\n00:35:05,080 --> 00:35:08,690\nall be hidden inside\nthe streams.\n\n613\n00:35:08,690 --> 00:35:11,036\nWell, is there a way\nout of that?\n\n614\n00:35:11,036 --> 00:35:13,480\nYeah, there is a way\nout of that.\n\n615\n00:35:13,480 --> 00:35:17,230\nWe could change the language so\nthat all procedures acted\n\n616\n00:35:17,230 --> 00:35:22,320\nlike cons-stream, so that every\nprocedure automatically\n\n617\n00:35:22,320 --> 00:35:25,450\nhas an implicit delay around\nits arguments.\n\n618\n00:35:25,450 --> 00:35:27,520\nAnd what would that mean?\n\n619\n00:35:27,520 --> 00:35:30,760\nThat would mean when you call\na procedure, the arguments\n\n620\n00:35:30,760 --> 00:35:32,210\nwouldn't get evaluated.\n\n621\n00:35:32,210 --> 00:35:34,820\nInstead, they'd only be\nevaluated when you need them,\n\n622\n00:35:34,820 --> 00:35:36,830\nso they might be passed off to\nsome other procedure, which\n\n623\n00:35:36,830 --> 00:35:39,260\nwouldn't evaluate them either.\n\n624\n00:35:39,260 --> 00:35:42,150\nSo all these procedures would\nbe passing promises around.\n\n625\n00:35:42,150 --> 00:35:44,970\nAnd then finally maybe when you\nfinally got down to having\n\n626\n00:35:44,970 --> 00:35:48,040\nto look at the value of\nsomething that was handed to a\n\n627\n00:35:48,040 --> 00:35:50,720\nprimitive operator would you\nactually start calling in all\n\n628\n00:35:50,720 --> 00:35:52,380\nthose promises.\n\n629\n00:35:52,380 --> 00:35:54,400\nIf we did that, since everything\nwould have a\n\n630\n00:35:54,400 --> 00:35:58,220\nuniform delay, then you wouldn't\nhave to write any\n\n631\n00:35:58,220 --> 00:36:00,370\nexplicit delays, because it\nwould be automatically built\n\n632\n00:36:00,370 --> 00:36:02,920\ninto the way the\nlanguage works.\n\n633\n00:36:02,920 --> 00:36:05,870\nOr another way to say that,\ntechnically what I'm\n\n634\n00:36:05,870 --> 00:36:09,130\ndescribing is what's called--\n\n635\n00:36:09,130 --> 00:36:12,720\nif we did that, our language\nwould be so-called\n\n636\n00:36:12,720 --> 00:36:22,270\nnormal-order evaluation language\nversus what we've\n\n637\n00:36:22,270 --> 00:36:24,260\nactually been working\nwith, which is\n\n638\n00:36:24,260 --> 00:36:25,510\ncalled applicative order--\n\n639\n00:36:25,510 --> 00:36:31,240\n\n\n640\n00:36:31,240 --> 00:36:34,560\nversus applicative-order\nevaluation.\n\n641\n00:36:34,560 --> 00:36:36,835\nAnd remember the substitution\nmodel for applicative order.\n\n642\n00:36:36,835 --> 00:36:40,690\nIt says when you go and evaluate\na combination, you\n\n643\n00:36:40,690 --> 00:36:43,590\nfind the values of\nall the pieces.\n\n644\n00:36:43,590 --> 00:36:46,430\nYou evaluate the arguments and\nthen you substitute them in\n\n645\n00:36:46,430 --> 00:36:47,600\nthe body of the procedure.\n\n646\n00:36:47,600 --> 00:36:49,890\nNormal order says no,\ndon't do that.\n\n647\n00:36:49,890 --> 00:36:53,980\nWhat you do is effectively\nsubstitute in the body of the\n\n648\n00:36:53,980 --> 00:36:56,640\nprocedure, but instead of\nevaluating the arguments, you\n\n649\n00:36:56,640 --> 00:36:58,640\njust put a promise to\ncompute them there.\n\n650\n00:36:58,640 --> 00:37:01,030\nOr another way to say that is\nyou take the expressions for\n\n651\n00:37:01,030 --> 00:37:03,370\nthe arguments, if you like,\nand substitute them in the\n\n652\n00:37:03,370 --> 00:37:06,320\nbody of the procedure and go on,\nand never really simplify\n\n653\n00:37:06,320 --> 00:37:09,340\nanything until you get down\nto a primitive operator.\n\n654\n00:37:09,340 --> 00:37:11,840\nSo that would be a normal-order\nlanguage.\n\n655\n00:37:11,840 --> 00:37:13,490\nWell, why don't we do that?\n\n656\n00:37:13,490 --> 00:37:16,550\nBecause if we did, we'd get all\nthe advantages of delayed\n\n657\n00:37:16,550 --> 00:37:18,940\nevaluation with none\nof the mess.\n\n658\n00:37:18,940 --> 00:37:22,250\nIn fact, if we did that and\ncons was just a delayed\n\n659\n00:37:22,250 --> 00:37:24,710\nprocedure, that would make cons\nthe same as cons-stream.\n\n660\n00:37:24,710 --> 00:37:27,240\nWe wouldn't need streams of\nall because lists would\n\n661\n00:37:27,240 --> 00:37:30,675\nautomatically be streams. That's\nhow lists would behave,\n\n662\n00:37:30,675 --> 00:37:32,350\nand data structures would\nbehave that way.\n\n663\n00:37:32,350 --> 00:37:35,270\nEverything would behave\nthat way, right?\n\n664\n00:37:35,270 --> 00:37:38,510\nYou'd never really do any\ncomputation until you actually\n\n665\n00:37:38,510 --> 00:37:41,020\nneeded the answer.\n\n666\n00:37:41,020 --> 00:37:42,780\nYou wouldn't have to worry\nabout all these explicit\n\n667\n00:37:42,780 --> 00:37:44,790\nannoying delays.\n\n668\n00:37:44,790 --> 00:37:47,160\nWell, why don't we do that?\n\n669\n00:37:47,160 --> 00:37:49,230\nFirst of all, I should say\npeople do do that.\n\n670\n00:37:49,230 --> 00:37:51,850\nThere's some very beautiful\nlanguages.\n\n671\n00:37:51,850 --> 00:37:56,170\nOne of the very nicest is a\nlanguage called Miranda, which\n\n672\n00:37:56,170 --> 00:38:00,710\nis developed by David Turner\nat the University of Kent.\n\n673\n00:38:00,710 --> 00:38:01,930\nAnd that's how this\nlanguage works.\n\n674\n00:38:01,930 --> 00:38:06,430\nIt's a normal-order language and\nits data structures, which\n\n675\n00:38:06,430 --> 00:38:09,250\nlook like lists, are actually\nstreams. And you write\n\n676\n00:38:09,250 --> 00:38:11,710\nordinary procedures in Miranda,\nand they do these\n\n677\n00:38:11,710 --> 00:38:13,950\nprime things and eight\nqueens things, just\n\n678\n00:38:13,950 --> 00:38:14,970\nwithout anything special.\n\n679\n00:38:14,970 --> 00:38:17,790\nIt's all built in there.\n\n680\n00:38:17,790 --> 00:38:19,040\nBut there's a price.\n\n681\n00:38:19,040 --> 00:38:21,190\n\n\n682\n00:38:21,190 --> 00:38:23,170\nRemember how we got here.\n\n683\n00:38:23,170 --> 00:38:26,380\nWe're decoupling time\nin the programs\n\n684\n00:38:26,380 --> 00:38:27,480\nfrom time in the machines.\n\n685\n00:38:27,480 --> 00:38:30,400\nAnd if we put delay, that sort\nof decouples it everywhere,\n\n686\n00:38:30,400 --> 00:38:33,140\nnot just in streams. Remember\nwhat we're trying to do.\n\n687\n00:38:33,140 --> 00:38:36,900\nWe're trying to think about\nprogramming as a way to\n\n688\n00:38:36,900 --> 00:38:39,300\nspecify processes.\n\n689\n00:38:39,300 --> 00:38:41,690\nAnd if we give up too much time,\nour language becomes\n\n690\n00:38:41,690 --> 00:38:47,030\nmore elegant, but it becomes a\nlittle bit less expressive.\n\n691\n00:38:47,030 --> 00:38:51,480\nThere are certain distinctions\nthat we can't draw.\n\n692\n00:38:51,480 --> 00:38:53,980\nOne of them, for instance,\nis iteration.\n\n693\n00:38:53,980 --> 00:38:58,630\nRemember this old procedure,\niterative factorial, that we\n\n694\n00:38:58,630 --> 00:39:01,230\nlooked at quite a\nlong time ago.\n\n695\n00:39:01,230 --> 00:39:03,410\nIterative factorial had a thing,\nand it said there was\n\n696\n00:39:03,410 --> 00:39:06,290\nan internal procedure, and there\nwas a state which was a\n\n697\n00:39:06,290 --> 00:39:09,970\nproduct and a counter,\nand we iterate that\n\n698\n00:39:09,970 --> 00:39:12,120\ngoing around the loop.\n\n699\n00:39:12,120 --> 00:39:13,880\nAnd we said that was an\niterative procedure because it\n\n700\n00:39:13,880 --> 00:39:15,730\ndidn't build up state.\n\n701\n00:39:15,730 --> 00:39:19,630\nAnd the reason it didn't build\nup state is because this iter\n\n702\n00:39:19,630 --> 00:39:23,900\nthat's called is just passing\nthese things around to itself.\n\n703\n00:39:23,900 --> 00:39:26,130\nOr in the substitution model,\nyou could see in the\n\n704\n00:39:26,130 --> 00:39:29,480\nsubstitution model that Jerry\ndid, that in an iterative\n\n705\n00:39:29,480 --> 00:39:31,660\nprocedure, that state doesn't\nhave to grow.\n\n706\n00:39:31,660 --> 00:39:33,030\nAnd in fact, we said\nit doesn't,\n\n707\n00:39:33,030 --> 00:39:34,840\nso this is an iteration.\n\n708\n00:39:34,840 --> 00:39:37,890\nBut now think about this exact\nsame text if we had a\n\n709\n00:39:37,890 --> 00:39:41,150\nnormal-order language.\n\n710\n00:39:41,150 --> 00:39:44,230\nWhat would happen is this\nwould no longer be an\n\n711\n00:39:44,230 --> 00:39:45,650\niterative procedure?\n\n712\n00:39:45,650 --> 00:39:47,790\nAnd if you really think about\nthe details of the\n\n713\n00:39:47,790 --> 00:39:51,460\nsubstitution model, which I'm\nnot going to do here, this\n\n714\n00:39:51,460 --> 00:39:52,330\nexpression would grow.\n\n715\n00:39:52,330 --> 00:39:53,280\nWhy would it grow?\n\n716\n00:39:53,280 --> 00:39:56,740\nIt's because when iter calls\nitself, it calls itself with\n\n717\n00:39:56,740 --> 00:39:58,080\nthis product.\n\n718\n00:39:58,080 --> 00:40:00,210\nIf it's a normal-order language,\nthat multiplication\n\n719\n00:40:00,210 --> 00:40:02,510\nis not going to get done.\n\n720\n00:40:02,510 --> 00:40:04,790\nThat's going to say I'm to call\nmyself with a promise to\n\n721\n00:40:04,790 --> 00:40:06,670\ncompute this product.\n\n722\n00:40:06,670 --> 00:40:09,760\nAnd now iter goes\naround again.\n\n723\n00:40:09,760 --> 00:40:13,680\nAnd I'm going to call myself\nwith a promise to compute this\n\n724\n00:40:13,680 --> 00:40:18,400\nproduct where now one of the\none factors is a promise.\n\n725\n00:40:18,400 --> 00:40:19,430\nAnd I call myself again.\n\n726\n00:40:19,430 --> 00:40:22,580\nAnd if you write out the\nsubstitution model for that\n\n727\n00:40:22,580 --> 00:40:26,430\niterative process, you'll see\nexactly the same growth in\n\n728\n00:40:26,430 --> 00:40:29,080\nstate, all those promises that\nare getting remembered that\n\n729\n00:40:29,080 --> 00:40:31,790\nhave to get called in\nat the very end.\n\n730\n00:40:31,790 --> 00:40:35,690\nSo one of the disadvantages\nis that you can't\n\n731\n00:40:35,690 --> 00:40:36,980\nreally express iteration.\n\n732\n00:40:36,980 --> 00:40:39,610\nMaybe that's a little\ntheoretical reason why not,\n\n733\n00:40:39,610 --> 00:40:43,510\nbut in fact, people who are\ntrying to write real operating\n\n734\n00:40:43,510 --> 00:40:46,750\nsystems in these languages are\nrunning into exactly these\n\n735\n00:40:46,750 --> 00:40:51,650\ntypes of problems. Like it's\nperfectly possible to\n\n736\n00:40:51,650 --> 00:40:54,610\nimplement a text editor in\nlanguages like these.\n\n737\n00:40:54,610 --> 00:40:58,830\nBut after you work a while, you\nsuddenly have 3 megabytes\n\n738\n00:40:58,830 --> 00:41:01,240\nof stuff, which is--\n\n739\n00:41:01,240 --> 00:41:04,470\nI guess they call them the\ndragging tail problem of\n\n740\n00:41:04,470 --> 00:41:07,320\npeople who are looking at these,\nof promises that sort\n\n741\n00:41:07,320 --> 00:41:09,260\nof haven't been called in\nbecause you couldn't quite\n\n742\n00:41:09,260 --> 00:41:10,230\nexpress an iteration.\n\n743\n00:41:10,230 --> 00:41:14,330\nAnd one of the research\nquestions in these kinds of\n\n744\n00:41:14,330 --> 00:41:17,930\nlanguages are figuring out the\nright compiler technology to\n\n745\n00:41:17,930 --> 00:41:20,110\nget rid of the so-called\ndragging tails.\n\n746\n00:41:20,110 --> 00:41:23,940\nIt's not simple.\n\n747\n00:41:23,940 --> 00:41:28,520\nBut there's another kind of more\nstriking issue about why\n\n748\n00:41:28,520 --> 00:41:30,100\nyou just don't go ahead\nand make your\n\n749\n00:41:30,100 --> 00:41:32,056\nlanguage normal order.\n\n750\n00:41:32,056 --> 00:41:37,440\nAnd the reason is that\nnormal-order evaluation and\n\n751\n00:41:37,440 --> 00:41:42,000\nside effects just don't mix.\n\n752\n00:41:42,000 --> 00:41:45,350\nThey just don't go together\nvery well.\n\n753\n00:41:45,350 --> 00:41:48,360\nSomehow, you can't--\n\n754\n00:41:48,360 --> 00:41:51,500\nit's sort of you can't\nsimultaneously go around\n\n755\n00:41:51,500 --> 00:41:55,990\ntrying to model objects with\nlocal state and change and at\n\n756\n00:41:55,990 --> 00:41:58,520\nthe same time do these\nnormal-order tricks of\n\n757\n00:41:58,520 --> 00:42:00,400\nde-coupling time.\n\n758\n00:42:00,400 --> 00:42:02,010\nLet me just show you\na really simple\n\n759\n00:42:02,010 --> 00:42:03,790\nexample, very, very simple.\n\n760\n00:42:03,790 --> 00:42:07,520\nSuppose we had a normal-order\nlanguage.\n\n761\n00:42:07,520 --> 00:42:09,550\nAnd I'm going to start\nout in this language.\n\n762\n00:42:09,550 --> 00:42:10,520\nThis is now normal order.\n\n763\n00:42:10,520 --> 00:42:13,570\nI'm going to define x to be 0.\n\n764\n00:42:13,570 --> 00:42:15,750\nIt's just some variable\nI'll initialize.\n\n765\n00:42:15,750 --> 00:42:18,610\nAnd now I'm going to define this\nlittle funny function,\n\n766\n00:42:18,610 --> 00:42:22,640\nwhich is an identity function.\n\n767\n00:42:22,640 --> 00:42:25,520\nAnd what it does, it keeps track\nof the last time you\n\n768\n00:42:25,520 --> 00:42:26,770\ncalled it using x.\n\n769\n00:42:26,770 --> 00:42:31,620\n\n\n770\n00:42:31,620 --> 00:42:34,390\nSo the identity of n just\nreturns n, but it\n\n771\n00:42:34,390 --> 00:42:36,760\nsets x to be n.\n\n772\n00:42:36,760 --> 00:42:40,050\nAnd now I'll define a little\nincrement function, which is a\n\n773\n00:42:40,050 --> 00:42:42,580\nvery little, simple scenario.\n\n774\n00:42:42,580 --> 00:42:44,780\nNow, imagine I'm interacting\nwith this in the normal-order\n\n775\n00:42:44,780 --> 00:42:47,230\nlanguage, and I type\nthe following.\n\n776\n00:42:47,230 --> 00:42:52,940\nI say define y to be increment\nthe identity function of 3, so\n\n777\n00:42:52,940 --> 00:42:54,190\ny is going to be 4.\n\n778\n00:42:54,190 --> 00:42:57,410\n\n\n779\n00:42:57,410 --> 00:42:59,520\nNow, I say what's x?\n\n780\n00:42:59,520 --> 00:43:02,720\nWell, x should have been the\nvalue that was remembered last\n\n781\n00:43:02,720 --> 00:43:04,710\nwhen I called the identity\nfunction.\n\n782\n00:43:04,710 --> 00:43:06,500\nSo you'd expect to say,\nwell, x is 3 at this\n\n783\n00:43:06,500 --> 00:43:08,530\npoint, but it's not.\n\n784\n00:43:08,530 --> 00:43:13,460\nBecause when I defined y here,\nwhat I really defined y to be\n\n785\n00:43:13,460 --> 00:43:17,000\nincrement of a promise\nto do this thing.\n\n786\n00:43:17,000 --> 00:43:19,050\nSo I didn't look at y,\nso that identity\n\n787\n00:43:19,050 --> 00:43:21,560\nfunction didn't get run.\n\n788\n00:43:21,560 --> 00:43:24,070\nSo if I type in this definition\nand look at x, I'm\n\n789\n00:43:24,070 --> 00:43:25,320\ngoing to get 0.\n\n790\n00:43:25,320 --> 00:43:28,360\n\n\n791\n00:43:28,360 --> 00:43:33,120\nNow, if I go look at y and say\nwhat's y, say y is 4, looking\n\n792\n00:43:33,120 --> 00:43:36,180\nat y, that very active looking\nat y caused the identity\n\n793\n00:43:36,180 --> 00:43:38,342\nfunction to be run.\n\n794\n00:43:38,342 --> 00:43:40,740\nAnd now x will get\nremembered as 3.\n\n795\n00:43:40,740 --> 00:43:42,020\nSo here x will be 0.\n\n796\n00:43:42,020 --> 00:43:43,280\nHere, x will be 3.\n\n797\n00:43:43,280 --> 00:43:47,890\nThat's a tiny, little, simple\nscenario, but you can see what\n\n798\n00:43:47,890 --> 00:43:52,640\nkind of a mess that's going to\nmake for debugging interactive\n\n799\n00:43:52,640 --> 00:43:57,100\nprograms when you have\nnormal-order evaluation.\n\n800\n00:43:57,100 --> 00:43:59,690\nIt's very confusing.\n\n801\n00:43:59,690 --> 00:44:03,200\nBut it's very confusing for a\nvery deep reason, which is\n\n802\n00:44:03,200 --> 00:44:07,250\nthat the whole idea of putting\nin delays is that\n\n803\n00:44:07,250 --> 00:44:09,780\nyou throw away time.\n\n804\n00:44:09,780 --> 00:44:11,750\nThat's why we can have these\ninfinite processes.\n\n805\n00:44:11,750 --> 00:44:13,870\nSince we've thrown away time, we\ndon't have to wait for them\n\n806\n00:44:13,870 --> 00:44:17,790\nto run, right?\n\n807\n00:44:17,790 --> 00:44:21,000\nWe decouple the order of events\nin the computer from\n\n808\n00:44:21,000 --> 00:44:23,730\nwhat we write in our programs.\nBut when we talk about state\n\n809\n00:44:23,730 --> 00:44:26,910\nand set and change, that's\nexactly what we do want\n\n810\n00:44:26,910 --> 00:44:28,760\ncontrol of.\n\n811\n00:44:28,760 --> 00:44:32,960\nSo it's almost as if there's\nthis fundamental contradiction\n\n812\n00:44:32,960 --> 00:44:34,570\nin what you want.\n\n813\n00:44:34,570 --> 00:44:38,710\nAnd that brings us back to these\nsort of philosophical\n\n814\n00:44:38,710 --> 00:44:40,720\nmutterings about what is it that\nyou're trying to model\n\n815\n00:44:40,720 --> 00:44:42,410\nand how do you look\nat the world.\n\n816\n00:44:42,410 --> 00:44:45,890\nOr sometimes this is called\nthe debate over functional\n\n817\n00:44:45,890 --> 00:44:47,140\nprogramming.\n\n818\n00:44:47,140 --> 00:44:53,570\n\n\n819\n00:44:53,570 --> 00:44:57,730\nA so-called purely functional\nlanguage is one that just\n\n820\n00:44:57,730 --> 00:45:00,440\ndoesn't have any side effects.\n\n821\n00:45:00,440 --> 00:45:02,450\nSince you have no side effects,\nthere's no assignment\n\n822\n00:45:02,450 --> 00:45:06,360\noperator, so there are no\nterrible consequences of it.\n\n823\n00:45:06,360 --> 00:45:07,930\nYou can use a substitution-like\nthing.\n\n824\n00:45:07,930 --> 00:45:11,120\nPrograms really are like\nmathematics and not like\n\n825\n00:45:11,120 --> 00:45:12,640\nmodels in the real\nworld, not like\n\n826\n00:45:12,640 --> 00:45:15,050\nobjects in the real world.\n\n827\n00:45:15,050 --> 00:45:16,100\nThere are a lot of\nwonderful things\n\n828\n00:45:16,100 --> 00:45:17,170\nabout functional languages.\n\n829\n00:45:17,170 --> 00:45:19,240\nSince there's no time, you never\nhave any synchronization\n\n830\n00:45:19,240 --> 00:45:23,140\nproblems. And if you want to put\nsomething into a parallel\n\n831\n00:45:23,140 --> 00:45:26,820\nalgorithm, you can run the\npieces of that parallel\n\n832\n00:45:26,820 --> 00:45:29,260\nprocessing any way you want.\n\n833\n00:45:29,260 --> 00:45:31,235\nThere's just never any\nsynchronization to worry that,\n\n834\n00:45:31,235 --> 00:45:33,640\nand it's a very congenial\nenvironment for doing this.\n\n835\n00:45:33,640 --> 00:45:35,450\nThe price is you give\nup assignment.\n\n836\n00:45:35,450 --> 00:45:39,060\n\n\n837\n00:45:39,060 --> 00:45:41,460\nSo an advocate of a functional\nlanguage would say, gee,\n\n838\n00:45:41,460 --> 00:45:44,520\nthat's just a tiny\nprice to pay.\n\n839\n00:45:44,520 --> 00:45:45,690\nYou probably shouldn't\nuse assignment\n\n840\n00:45:45,690 --> 00:45:46,510\nmost of the time anyway.\n\n841\n00:45:46,510 --> 00:45:49,360\nAnd if you just give up\nassignment, you can be in this\n\n842\n00:45:49,360 --> 00:45:54,190\nmuch, much nicer world than\nthis place with objects.\n\n843\n00:45:54,190 --> 00:45:56,300\nWell, what's the rejoinder\nto that?\n\n844\n00:45:56,300 --> 00:46:00,300\nRemember how we got\ninto this mess.\n\n845\n00:46:00,300 --> 00:46:04,440\nWe started trying to model\nthings that had local state.\n\n846\n00:46:04,440 --> 00:46:06,840\nSo remember Jerry's random\nnumber generator.\n\n847\n00:46:06,840 --> 00:46:10,000\nThere was this random number\ngenerator that had some little\n\n848\n00:46:10,000 --> 00:46:12,290\nstate in it to compute the next\nrandom number and the\n\n849\n00:46:12,290 --> 00:46:14,080\nnext random number and the\nnext random number.\n\n850\n00:46:14,080 --> 00:46:17,830\nAnd we wanted to hide that state\naway from the Cesaro\n\n851\n00:46:17,830 --> 00:46:21,050\ncompute part process, and that's\nwhy we needed set.\n\n852\n00:46:21,050 --> 00:46:24,070\nWe wanted to package that\nstated modularly.\n\n853\n00:46:24,070 --> 00:46:26,920\nWell, a functional programming\nperson would say, well, you're\n\n854\n00:46:26,920 --> 00:46:27,560\njust all wet.\n\n855\n00:46:27,560 --> 00:46:28,810\nI mean, you can write\na perfectly\n\n856\n00:46:28,810 --> 00:46:29,840\ngood modular program.\n\n857\n00:46:29,840 --> 00:46:33,250\nIt's just you're thinking\nabout modularity wrong.\n\n858\n00:46:33,250 --> 00:46:35,420\nYou're hung up in this next\nrandom number and the next\n\n859\n00:46:35,420 --> 00:46:36,880\nrandom number and the\nnext random number.\n\n860\n00:46:36,880 --> 00:46:39,880\nWhy don't you just say let's\nwrite a program.\n\n861\n00:46:39,880 --> 00:46:42,990\nLet's write an enumerator\nwhich just generates an\n\n862\n00:46:42,990 --> 00:46:44,445\ninfinite stream of\nrandom numbers.\n\n863\n00:46:44,445 --> 00:46:49,010\n\n\n864\n00:46:49,010 --> 00:46:52,970\nWe can sort of have that stream\nall at once, and that's\n\n865\n00:46:52,970 --> 00:46:54,540\ngoing to be our source\nof random numbers.\n\n866\n00:46:54,540 --> 00:46:56,770\nAnd then if you like, you can\nput that through some sort of\n\n867\n00:46:56,770 --> 00:46:58,530\nprocessor, which is--\n\n868\n00:46:58,530 --> 00:46:59,530\nI don't know--\n\n869\n00:46:59,530 --> 00:47:06,880\na Cesaro test, and that\ncan do what it wants.\n\n870\n00:47:06,880 --> 00:47:16,320\nAnd what would come out of there\nwould be a stream of\n\n871\n00:47:16,320 --> 00:47:28,140\nsuccessive approximations\nto pi.\n\n872\n00:47:28,140 --> 00:47:31,600\nSo as we looked further down\nthis stream, we'd tug on this\n\n873\n00:47:31,600 --> 00:47:34,420\nCesaro thing, and it\nwould pull out more\n\n874\n00:47:34,420 --> 00:47:35,540\nand more random numbers.\n\n875\n00:47:35,540 --> 00:47:37,200\nAnd the further and further we\nlook down the stream, the\n\n876\n00:47:37,200 --> 00:47:39,720\nbetter an approximation\nwe'd get to pi.\n\n877\n00:47:39,720 --> 00:47:41,850\nAnd it would do exactly the same\nas the other computation,\n\n878\n00:47:41,850 --> 00:47:43,890\nexcept we're thinking about\nthe modularity different.\n\n879\n00:47:43,890 --> 00:47:46,360\nWe're saying imagine we had all\nthose infinite streams of\n\n880\n00:47:46,360 --> 00:47:49,400\nrandom numbers all at once.\n\n881\n00:47:49,400 --> 00:47:53,860\nYou can see the details of this\nprocedure in the book.\n\n882\n00:47:53,860 --> 00:47:56,940\nSimilarly, there are other\nthings that we tend to get\n\n883\n00:47:56,940 --> 00:48:00,730\nlocked into on this one and that\none and the next one and\n\n884\n00:48:00,730 --> 00:48:03,280\nthe next one, which don't\nhave to be that way.\n\n885\n00:48:03,280 --> 00:48:07,930\nLike you might think about like\na banking system, which\n\n886\n00:48:07,930 --> 00:48:08,900\nis a very simple idea.\n\n887\n00:48:08,900 --> 00:48:10,960\nImagine we have a program\nthat sort of\n\n888\n00:48:10,960 --> 00:48:12,210\nrepresents a bank account.\n\n889\n00:48:12,210 --> 00:48:18,810\n\n\n890\n00:48:18,810 --> 00:48:22,860\nThe bank account might\nhave in it--\n\n891\n00:48:22,860 --> 00:48:26,020\nif we looked at this in a sort\nof message-passing view of the\n\n892\n00:48:26,020 --> 00:48:29,070\nworld, we'd say a bank account\nis an object that has some\n\n893\n00:48:29,070 --> 00:48:31,510\nlocal state in there, which\nis the balance, say.\n\n894\n00:48:31,510 --> 00:48:34,110\n\n\n895\n00:48:34,110 --> 00:48:37,640\nAnd a user using this system\ncomes and sends a transaction\n\n896\n00:48:37,640 --> 00:48:41,230\nrequest. So the user sends a\ntransaction request, like\n\n897\n00:48:41,230 --> 00:48:43,970\ndeposit some money, and the\nbank account maybe--\n\n898\n00:48:43,970 --> 00:48:45,850\nlet's say the bank account\nalways responds with what the\n\n899\n00:48:45,850 --> 00:48:48,560\ncurrent balance is.\n\n900\n00:48:48,560 --> 00:48:50,360\nThe user says let's deposits\nsome money, and the bank\n\n901\n00:48:50,360 --> 00:48:54,350\naccount sends back a message\nwhich is the balance.\n\n902\n00:48:54,350 --> 00:48:57,970\nAnd the user says deposit some\nmore, and the bank account\n\n903\n00:48:57,970 --> 00:48:59,150\nsends back a message.\n\n904\n00:48:59,150 --> 00:49:00,900\nAnd just like the random number\ngenerator, you'd say,\n\n905\n00:49:00,900 --> 00:49:03,200\ngee, we would like to use set.\n\n906\n00:49:03,200 --> 00:49:06,150\nWe'd like to have balance be a\npiece of local state inside\n\n907\n00:49:06,150 --> 00:49:08,110\nthis bank account because we\nwant to separate the state of\n\n908\n00:49:08,110 --> 00:49:09,570\nthe user from the state\nof the bank account.\n\n909\n00:49:09,570 --> 00:49:13,280\n\n\n910\n00:49:13,280 --> 00:49:16,420\nWell, that's the\nmessage-processing view.\n\n911\n00:49:16,420 --> 00:49:20,030\nThere's a stream view with that\nthing, which does the\n\n912\n00:49:20,030 --> 00:49:22,740\nsame thing without any\nset or side effects.\n\n913\n00:49:22,740 --> 00:49:29,380\nAnd the idea is again we don't\nthink about anything having\n\n914\n00:49:29,380 --> 00:49:31,180\nlocal state.\n\n915\n00:49:31,180 --> 00:49:33,640\nWe think about the bank account\nas something that's\n\n916\n00:49:33,640 --> 00:49:38,640\ngoing to process a stream\nof transaction requests.\n\n917\n00:49:38,640 --> 00:49:40,670\nSo think about this bank account\nnot as something that\n\n918\n00:49:40,670 --> 00:49:44,510\ngoes message by message, but\nsomething that takes in a\n\n919\n00:49:44,510 --> 00:49:46,610\nstream of transaction\nrequests like maybe\n\n920\n00:49:46,610 --> 00:49:49,490\nsuccessive deposit announced.\n\n921\n00:49:49,490 --> 00:49:55,940\n1, 2, 2, 4, those might be\nsuccessive amounts to deposit.\n\n922\n00:49:55,940 --> 00:49:58,570\nAnd then coming out of\nit is the successive\n\n923\n00:49:58,570 --> 00:50:03,770\nbalances 1, 3, 5, 9.\n\n924\n00:50:03,770 --> 00:50:05,550\nSo we think of the bank account\nnot as something that\n\n925\n00:50:05,550 --> 00:50:09,970\nhas state, but something that\nacts sort of on the infinite\n\n926\n00:50:09,970 --> 00:50:10,820\nstream of requests.\n\n927\n00:50:10,820 --> 00:50:12,370\nBut remember, we've\nthrown away time.\n\n928\n00:50:12,370 --> 00:50:17,950\nSo what we can do is if the\nuser's here, we can have this\n\n929\n00:50:17,950 --> 00:50:21,530\ninfinite stream of requests\nbeing generated one at a time\n\n930\n00:50:21,530 --> 00:50:27,000\ncoming from the user and this\ntransaction stream coming back\n\n931\n00:50:27,000 --> 00:50:30,010\non a printer being printed\none at a time.\n\n932\n00:50:30,010 --> 00:50:33,850\nAnd if we drew a little line\nhere, right there to the user,\n\n933\n00:50:33,850 --> 00:50:36,910\nthe user couldn't tell\nthat this system\n\n934\n00:50:36,910 --> 00:50:39,560\ndoesn't have state.\n\n935\n00:50:39,560 --> 00:50:41,410\nIt looks just like the\nother one, but\n\n936\n00:50:41,410 --> 00:50:42,660\nthere's no state in there.\n\n937\n00:50:42,660 --> 00:50:45,120\n\n\n938\n00:50:45,120 --> 00:50:48,510\nAnd by the way, just to show\nyou, here's an actual\n\n939\n00:50:48,510 --> 00:50:52,240\nimplementation of this-- we'll\ncall it make deposit account\n\n940\n00:50:52,240 --> 00:50:53,835\nbecause you can only deposit.\n\n941\n00:50:53,835 --> 00:50:57,430\nIt takes an initial balance and\nthen a stream of deposits\n\n942\n00:50:57,430 --> 00:51:00,020\nyou might make.\n\n943\n00:51:00,020 --> 00:51:00,820\nAnd what is it?\n\n944\n00:51:00,820 --> 00:51:04,580\nWell, it's just cons-stream of\nthe balance onto make a new\n\n945\n00:51:04,580 --> 00:51:08,490\naccount stream whose initial\nbalance is the old balance\n\n946\n00:51:08,490 --> 00:51:14,020\nplus the first thing in the\ndeposit stream and make\n\n947\n00:51:14,020 --> 00:51:16,470\ndeposit account works on the\nrest of which is the tail of\n\n948\n00:51:16,470 --> 00:51:18,300\nthe deposit stream.\n\n949\n00:51:18,300 --> 00:51:24,650\nSo there's sort of a very\ntypical message-passing,\n\n950\n00:51:24,650 --> 00:51:26,700\nobject-oriented thing\nthat's done without\n\n951\n00:51:26,700 --> 00:51:28,790\nside effects at all.\n\n952\n00:51:28,790 --> 00:51:32,250\nThere are very many things\nyou can do this way.\n\n953\n00:51:32,250 --> 00:51:36,400\nWell, can you do everything\nwithout assignment?\n\n954\n00:51:36,400 --> 00:51:40,050\nCan everybody go over to purely\nfunctional languages?\n\n955\n00:51:40,050 --> 00:51:44,450\nWell, we don't know, but there\nseem to be places where purely\n\n956\n00:51:44,450 --> 00:51:48,100\nfunctional programming\nbreaks down.\n\n957\n00:51:48,100 --> 00:51:50,030\nWhere it starts hurting is\nwhen you have things like\n\n958\n00:51:50,030 --> 00:51:53,520\nthis, but you also mix it up\nwith the other things that we\n\n959\n00:51:53,520 --> 00:51:56,300\nhad to worry that, which are\nobjects and sharing and two\n\n960\n00:51:56,300 --> 00:51:58,850\nindependent agents\nbeing the same.\n\n961\n00:51:58,850 --> 00:52:00,850\nSo under a typical one, suppose\nyou want to extend\n\n962\n00:52:00,850 --> 00:52:02,960\nthis bank account.\n\n963\n00:52:02,960 --> 00:52:04,210\nSo here's a bank account.\n\n964\n00:52:04,210 --> 00:52:12,220\n\n\n965\n00:52:12,220 --> 00:52:15,410\nBank accounts take in a stream\nof transaction requests and\n\n966\n00:52:15,410 --> 00:52:18,780\nput out streams of, say,\nbalances or responses to that.\n\n967\n00:52:18,780 --> 00:52:21,020\nBut suppose you want to model\nthe fact that this is a joint\n\n968\n00:52:21,020 --> 00:52:26,090\nbank account between two\nindependent people.\n\n969\n00:52:26,090 --> 00:52:31,890\nSo suppose there are two people,\nsay, Bill and Dave,\n\n970\n00:52:31,890 --> 00:52:33,140\nwho have a joint bank account.\n\n971\n00:52:33,140 --> 00:52:35,960\n\n\n972\n00:52:35,960 --> 00:52:36,850\nHow would you model this?\n\n973\n00:52:36,850 --> 00:52:40,460\nWell, Bill puts out a stream of\ntransaction requests, and\n\n974\n00:52:40,460 --> 00:52:42,390\nDave puts out a stream of\ntransaction requests, and\n\n975\n00:52:42,390 --> 00:52:45,880\nsomehow, they have to merge\ninto this bank account.\n\n976\n00:52:45,880 --> 00:52:48,370\nSo what you might do is write\na little stream processing\n\n977\n00:52:48,370 --> 00:52:58,660\nthing called merge, which sort\nof takes these, merges them\n\n978\n00:52:58,660 --> 00:53:01,190\ntogether, produces a single\nstream for the bank account.\n\n979\n00:53:01,190 --> 00:53:03,610\nNow they're both talking to\nthe same bank account.\n\n980\n00:53:03,610 --> 00:53:06,600\nThat's all great, but how\ndo you write merge?\n\n981\n00:53:06,600 --> 00:53:09,730\nWhat's this procedure merge?\n\n982\n00:53:09,730 --> 00:53:12,760\nYou want to do something\nthat's reasonable.\n\n983\n00:53:12,760 --> 00:53:14,380\nYour first guess might be\nto say, well, we'll take\n\n984\n00:53:14,380 --> 00:53:20,050\nalternate requests from Bill and\nDave. But what happens if\n\n985\n00:53:20,050 --> 00:53:21,950\nsuddenly in the middle of this\nthing, Dave goes away on\n\n986\n00:53:21,950 --> 00:53:24,150\nvacation for two years?\n\n987\n00:53:24,150 --> 00:53:27,690\nThen Bill's sort of stuck.\n\n988\n00:53:27,690 --> 00:53:29,750\nSo what you want to do is--\nwell, it's hard to describe.\n\n989\n00:53:29,750 --> 00:53:33,380\nWhat you want to do is what\npeople call fair merge.\n\n990\n00:53:33,380 --> 00:53:38,410\n\n\n991\n00:53:38,410 --> 00:53:41,850\nThe idea of fair merge is it\nsort of should do them\n\n992\n00:53:41,850 --> 00:53:43,930\nalternately, but if there's\nnothing waiting here, it\n\n993\n00:53:43,930 --> 00:53:46,010\nshould take one twice.\n\n994\n00:53:46,010 --> 00:53:48,450\nNotice I can't even say that\nwithout talking about time.\n\n995\n00:53:48,450 --> 00:53:51,300\n\n\n996\n00:53:51,300 --> 00:53:55,970\nSo one of the other active\nresearcher areas in functional\n\n997\n00:53:55,970 --> 00:54:00,480\nlanguages is inventing little\nthings like fair merge and\n\n998\n00:54:00,480 --> 00:54:04,650\nmaybe some others, which will\ntake the places where I used\n\n999\n00:54:04,650 --> 00:54:08,050\nto need side effects and objects\nand sort of hide them\n\n1000\n00:54:08,050 --> 00:54:11,160\naway in some very well-defined\nmodules of the system so that\n\n1001\n00:54:11,160 --> 00:54:14,430\nall the problems of assignment\ndon't sort of leak out all\n\n1002\n00:54:14,430 --> 00:54:16,760\nover the system but are captured\nin some fairly\n\n1003\n00:54:16,760 --> 00:54:18,010\nwell-understood things.\n\n1004\n00:54:18,010 --> 00:54:20,780\n\n\n1005\n00:54:20,780 --> 00:54:23,410\nMore generally, I think what\nyou're seeing is that we're\n\n1006\n00:54:23,410 --> 00:54:25,960\nrunning across what I think\nis a very basic problem in\n\n1007\n00:54:25,960 --> 00:54:29,450\ncomputer science, which is how\nto define languages that\n\n1008\n00:54:29,450 --> 00:54:36,240\nsomehow can talk about delayed\nevaluation, but also be able\n\n1009\n00:54:36,240 --> 00:54:37,280\nto reflect this view\nthat there are\n\n1010\n00:54:37,280 --> 00:54:38,360\nobjects in the world.\n\n1011\n00:54:38,360 --> 00:54:41,230\nHow do we somehow get both?\n\n1012\n00:54:41,230 --> 00:54:43,040\nAnd I think that's a\nvery hard problem.\n\n1013\n00:54:43,040 --> 00:54:46,750\nAnd it may be that it's a very\nhard problem that has almost\n\n1014\n00:54:46,750 --> 00:54:49,260\nnothing to do with computer\nscience, that it really is a\n\n1015\n00:54:49,260 --> 00:54:51,950\nproblem having to do with two\nvery incompatible ways of\n\n1016\n00:54:51,950 --> 00:54:53,840\nlooking at the world.\n\n1017\n00:54:53,840 --> 00:54:55,090\nOK, questions?\n\n1018\n00:54:55,090 --> 00:55:17,556\n\n\n1019\n00:55:17,556 --> 00:55:20,610\nAUDIENCE: You mentioned\nearlier that once you\n\n1020\n00:55:20,610 --> 00:55:23,930\nintroduce assignment, the\ngeneral rule for using the\n\n1021\n00:55:23,930 --> 00:55:25,890\nsubstitution model\nis you can't.\n\n1022\n00:55:25,890 --> 00:55:27,570\nUnless you're very careful,\nyou can't.\n\n1023\n00:55:27,570 --> 00:55:28,260\nPROFESSOR: Right.\n\n1024\n00:55:28,260 --> 00:55:32,550\nAUDIENCE: Is there a set of\ntechniques or a set of\n\n1025\n00:55:32,550 --> 00:55:37,030\nguidelines for localizing the\neffects of assignment so that\n\n1026\n00:55:37,030 --> 00:55:40,300\nthe very careful becomes\ndefined?\n\n1027\n00:55:40,300 --> 00:55:42,890\nPROFESSOR: I don't know.\n\n1028\n00:55:42,890 --> 00:55:45,430\nLet me think.\n\n1029\n00:55:45,430 --> 00:55:50,150\nWell, certainly, there was an\nassignment inside memo proc,\n\n1030\n00:55:50,150 --> 00:55:51,480\nbut that was sort\nof hidden away.\n\n1031\n00:55:51,480 --> 00:55:53,480\nIt ended up not making\nany difference.\n\n1032\n00:55:53,480 --> 00:55:57,385\nPart of the reason for that is\nonce this thing triggered that\n\n1033\n00:55:57,385 --> 00:55:58,990\nit had run and gotten\nan answer, that\n\n1034\n00:55:58,990 --> 00:56:00,390\nanswer will never change.\n\n1035\n00:56:00,390 --> 00:56:02,080\nSo that was sort of a\none-time assignment.\n\n1036\n00:56:02,080 --> 00:56:05,020\nSo one very general thing you\ncan do is if you only do\n\n1037\n00:56:05,020 --> 00:56:08,750\nwhat's called a one-time\nassignment and never change\n\n1038\n00:56:08,750 --> 00:56:11,250\nanything, then you\ncan do better.\n\n1039\n00:56:11,250 --> 00:56:17,156\nOne of the problems in this\nmerge thing, people have--\n\n1040\n00:56:17,156 --> 00:56:18,490\nlet me see if this is right.\n\n1041\n00:56:18,490 --> 00:56:22,910\nI think it's true that with\nfair merge, with just fair\n\n1042\n00:56:22,910 --> 00:56:27,060\nmerge, you can begin effectively\nsimulating\n\n1043\n00:56:27,060 --> 00:56:30,820\nassignment in the rest\nof the language.\n\n1044\n00:56:30,820 --> 00:56:33,630\nIt seems like anything you\ndo to go outside--\n\n1045\n00:56:33,630 --> 00:56:36,440\nI'm not quite sure that's true\nfor fair merge, but it's true\n\n1046\n00:56:36,440 --> 00:56:38,500\nof a little bit more\ngeneral things that\n\n1047\n00:56:38,500 --> 00:56:39,520\npeople have been doing.\n\n1048\n00:56:39,520 --> 00:56:42,630\nSo it might be that any little\nbit you put in, suddenly if\n\n1049\n00:56:42,630 --> 00:56:44,610\nthey allow you to build\narbitrary stuff, it's almost\n\n1050\n00:56:44,610 --> 00:56:47,970\nas bad as having assignment\naltogether.\n\n1051\n00:56:47,970 --> 00:56:51,590\nBut that's an area that people\nare thinking about now.\n\n1052\n00:56:51,590 --> 00:56:57,010\nAUDIENCE: I guess I don't see\nthe problem here with merge if\n\n1053\n00:56:57,010 --> 00:57:00,930\nI call Bill, if Bill is a\nprocedure, then Bill is going\n\n1054\n00:57:00,930 --> 00:57:03,690\nto increment the bank account\nor build the list that 's\n\n1055\n00:57:03,690 --> 00:57:04,730\ngoing to put in the\nnext element.\n\n1056\n00:57:04,730 --> 00:57:07,170\nIf I call Dave twice in a\nrow, that will do that.\n\n1057\n00:57:07,170 --> 00:57:09,350\nI'm not sure where fair merge\nhas to be involved.\n\n1058\n00:57:09,350 --> 00:57:10,150\nPROFESSOR: The problem\nis imagine\n\n1059\n00:57:10,150 --> 00:57:11,200\nthese really as people.\n\n1060\n00:57:11,200 --> 00:57:13,490\nSee, here I have the user who's\ninteracting with this\n\n1061\n00:57:13,490 --> 00:57:14,850\nbank account.\n\n1062\n00:57:14,850 --> 00:57:15,960\nPut in a request,\nget an answer.\n\n1063\n00:57:15,960 --> 00:57:17,070\nPut in a request,\nget an answer.\n\n1064\n00:57:17,070 --> 00:57:18,200\nAUDIENCE: Right.\n\n1065\n00:57:18,200 --> 00:57:20,860\nPROFESSOR: But if the only way\nI can process request is to\n\n1066\n00:57:20,860 --> 00:57:22,290\nalternate them from\ntwo people--\n\n1067\n00:57:22,290 --> 00:57:24,220\nAUDIENCE: Well, why would\nyou alternate them?\n\n1068\n00:57:24,220 --> 00:57:25,070\nPROFESSOR: Why don't I?\n\n1069\n00:57:25,070 --> 00:57:26,140\nAUDIENCE: Yes.\n\n1070\n00:57:26,140 --> 00:57:26,580\nWhy do you?\n\n1071\n00:57:26,580 --> 00:57:27,640\nPROFESSOR: Think of them\nas real people, right?\n\n1072\n00:57:27,640 --> 00:57:29,280\nThis guy might go\naway for a year.\n\n1073\n00:57:29,280 --> 00:57:32,700\nAnd you're sitting here at the\nbank account window, and you\n\n1074\n00:57:32,700 --> 00:57:34,040\ncan't put in two requests\nbecause it's\n\n1075\n00:57:34,040 --> 00:57:35,480\nwaiting for this guy.\n\n1076\n00:57:35,480 --> 00:57:37,380\nAUDIENCE: Why does it have\nto be waiting for one?\n\n1077\n00:57:37,380 --> 00:57:39,110\nPROFESSOR: Because it's trying\nto compute a function.\n\n1078\n00:57:39,110 --> 00:57:41,720\nI have to define a function.\n\n1079\n00:57:41,720 --> 00:57:44,210\nAnother way to say that is the\nanswer to what comes out of\n\n1080\n00:57:44,210 --> 00:57:51,690\nthis merge box is not a function\nof what goes in.\n\n1081\n00:57:51,690 --> 00:57:53,490\nBecause, see, what would\nthe function be?\n\n1082\n00:57:53,490 --> 00:58:03,470\nSuppose he puts in 1, 1, 1, 1,\nand he puts in 2, 2, 2, 2.\n\n1083\n00:58:03,470 --> 00:58:05,910\nWhat's the answer\nsupposed to be?\n\n1084\n00:58:05,910 --> 00:58:08,740\nIt's not good enough to say\nit's 1, 2, 1, 2, 1, 2.\n\n1085\n00:58:08,740 --> 00:58:09,390\nAUDIENCE: I understand.\n\n1086\n00:58:09,390 --> 00:58:11,560\nBut when Bill puts\nin 1, 1 goes in.\n\n1087\n00:58:11,560 --> 00:58:13,950\nWhen Dave puts in 2 twice,\n2 goes in twice.\n\n1088\n00:58:13,950 --> 00:58:15,090\nWhen Bill puts in--\n\n1089\n00:58:15,090 --> 00:58:15,450\nPROFESSOR: Right.\n\n1090\n00:58:15,450 --> 00:58:17,140\nAUDIENCE: Why can't\nit be hooked to\n\n1091\n00:58:17,140 --> 00:58:18,680\nthe time of the input--\n\n1092\n00:58:18,680 --> 00:58:20,100\nthe actual procedural--\n\n1093\n00:58:20,100 --> 00:58:23,980\nPROFESSOR: Because I\ndon't have time.\n\n1094\n00:58:23,980 --> 00:58:26,900\nSee, all I can say is I'm going\nto define a function.\n\n1095\n00:58:26,900 --> 00:58:28,150\nI don't have time.\n\n1096\n00:58:28,150 --> 00:58:32,070\n\n\n1097\n00:58:32,070 --> 00:58:34,690\nThere's no concept if it's going\nto alternate, except if\n\n1098\n00:58:34,690 --> 00:58:38,420\nnobody's there, it's going\nto wait a while for him.\n\n1099\n00:58:38,420 --> 00:58:41,910\nIt's just going to say I have\nthe stream of requests, the\n\n1100\n00:58:41,910 --> 00:58:44,580\ntimeless infinite streams of\nall the requests that Dave\n\n1101\n00:58:44,580 --> 00:58:47,810\nwould have made, right?\n\n1102\n00:58:47,810 --> 00:58:49,710\nAnd the timeless infinite stream\nof all the requests\n\n1103\n00:58:49,710 --> 00:58:51,690\nBill would have made, and I\nwant to operate on them.\n\n1104\n00:58:51,690 --> 00:58:53,510\nSee, that's how this bank\naccount is working.\n\n1105\n00:58:53,510 --> 00:58:56,710\n\n\n1106\n00:58:56,710 --> 00:58:59,120\nAnd the problem is that these\npoor people who are sitting at\n\n1107\n00:58:59,120 --> 00:59:02,180\nthe bank account windows\nhave the\n\n1108\n00:59:02,180 --> 00:59:05,340\nmisfortune to exist in time.\n\n1109\n00:59:05,340 --> 00:59:08,490\nThey don't see their infinite\nstream of all the requests\n\n1110\n00:59:08,490 --> 00:59:10,070\nthey would have ever made.\n\n1111\n00:59:10,070 --> 00:59:11,550\nThey're waiting now, and\nthey want an answer.\n\n1112\n00:59:11,550 --> 00:59:14,290\n\n\n1113\n00:59:14,290 --> 00:59:16,340\nSo if you're sitting there--\n\n1114\n00:59:16,340 --> 00:59:20,360\nif this is the screen operation\non some time-sharing\n\n1115\n00:59:20,360 --> 00:59:22,940\nsystem and it's working\nfunctionally, you want an\n\n1116\n00:59:22,940 --> 00:59:25,290\nanswer then when you\ntalk the character.\n\n1117\n00:59:25,290 --> 00:59:26,940\nYou don't want it to have to\nwait for everybody in the\n\n1118\n00:59:26,940 --> 00:59:28,990\nwhole system to have typed one\ncharacter before it can get\n\n1119\n00:59:28,990 --> 00:59:30,910\naround to service you.\n\n1120\n00:59:30,910 --> 00:59:33,890\nSo that's the problem.\n\n1121\n00:59:33,890 --> 00:59:36,850\nI mean, the fact that people\nlive in time, apparently.\n\n1122\n00:59:36,850 --> 00:59:38,620\nIf they didn't, it wouldn't\nbe a problem.\n\n1123\n00:59:38,620 --> 00:59:49,100\n\n\n1124\n00:59:49,100 --> 00:59:52,240\nAUDIENCE: I'm afraid I miss the\npoint of having no time in\n\n1125\n00:59:52,240 --> 00:59:54,740\nthis banking transaction.\n\n1126\n00:59:54,740 --> 00:59:56,880\nIsn't time very important?\n\n1127\n00:59:56,880 --> 01:00:00,790\nFor instance, the sequence\nof events.\n\n1128\n01:00:00,790 --> 01:00:07,150\nIf Dave take out $100,\nthen the timing\n\n1129\n01:00:07,150 --> 01:00:08,400\nsequence should be important.\n\n1130\n01:00:08,400 --> 01:00:11,260\nHow do you treat transactions\nas streams?\n\n1131\n01:00:11,260 --> 01:00:14,260\nPROFESSOR: Well, that's\nthe thing I'm saying.\n\n1132\n01:00:14,260 --> 01:00:17,510\nThis is an example\nwhere you can't.\n\n1133\n01:00:17,510 --> 01:00:18,610\nYou can't.\n\n1134\n01:00:18,610 --> 01:00:21,410\nThe point is what comes out of\nhere is simply not a function\n\n1135\n01:00:21,410 --> 01:00:24,170\nof the stream going in here and\nthe stream going in here.\n\n1136\n01:00:24,170 --> 01:00:26,660\nIt's a function of the stream\ngoing in here and the stream\n\n1137\n01:00:26,660 --> 01:00:29,670\ngoing in here and some kind of\ninformation about time, which\n\n1138\n01:00:29,670 --> 01:00:31,610\nis precisely what a normal-order\nlanguage won't\n\n1139\n01:00:31,610 --> 01:00:32,860\nlet you say.\n\n1140\n01:00:32,860 --> 01:00:34,810\n\n\n1141\n01:00:34,810 --> 01:00:36,950\nAUDIENCE: In order to brings\nthis back into a more\n\n1142\n01:00:36,950 --> 01:00:40,476\nfunctional perspective, could we\njust explicitly time stamp\n\n1143\n01:00:40,476 --> 01:00:44,390\nall the inputs from Bill and\nDave and define fair merge to\n\n1144\n01:00:44,390 --> 01:00:46,400\njust be the sort on\nthose time stamps?\n\n1145\n01:00:46,400 --> 01:00:49,150\n\n\n1146\n01:00:49,150 --> 01:00:49,550\nPROFESSOR: Yeah, you\ncan do that.\n\n1147\n01:00:49,550 --> 01:00:50,600\nYou can do that sort of thing.\n\n1148\n01:00:50,600 --> 01:00:53,830\nAnother thing you could say is\nimagine that really what this\n\n1149\n01:00:53,830 --> 01:00:59,070\nfunction is, is that it does a\nread every microsecond, and\n\n1150\n01:00:59,070 --> 01:01:00,110\nthen if there's none\nthere, that's\n\n1151\n01:01:00,110 --> 01:01:00,970\nconsidered an empty one.\n\n1152\n01:01:00,970 --> 01:01:03,610\nThat's about equivalent\nto what you said.\n\n1153\n01:01:03,610 --> 01:01:07,110\nAnd yes, you can do that,\nbut that's a clg.\n\n1154\n01:01:07,110 --> 01:01:09,480\nSo it's not quite only\nimplementation\n\n1155\n01:01:09,480 --> 01:01:10,170\nwe're worried about.\n\n1156\n01:01:10,170 --> 01:01:12,830\nWe're worried about expressive\npower in the language, and\n\n1157\n01:01:12,830 --> 01:01:15,630\nwhat we're running across is a\nreal mismatch between what we\n\n1158\n01:01:15,630 --> 01:01:18,824\ncan say easily and what\nwe'd like to say.\n\n1159\n01:01:18,824 --> 01:01:20,790\nAUDIENCE: It sounds like where\nwe're getting hung up with\n\n1160\n01:01:20,790 --> 01:01:23,480\nthat is the fact it expects one\ninput from both Bill and\n\n1161\n01:01:23,480 --> 01:01:26,080\nDave at the same time.\n\n1162\n01:01:26,080 --> 01:01:28,530\nPROFESSOR: It's not quite one,\nbut it's anything you define.\n\n1163\n01:01:28,530 --> 01:01:31,000\nSo you can say Dave can go\ntwice as often, but if\n\n1164\n01:01:31,000 --> 01:01:36,110\nanything you predefine, it's\nnot the right thing.\n\n1165\n01:01:36,110 --> 01:01:39,880\nYou can't decide at some\nparticular function of their\n\n1166\n01:01:39,880 --> 01:01:41,930\ninput requests.\n\n1167\n01:01:41,930 --> 01:01:44,870\nWorse yet, I mean, worse yet,\nthere are things that even\n\n1168\n01:01:44,870 --> 01:01:47,290\nmerge can't do.\n\n1169\n01:01:47,290 --> 01:01:49,170\nOne thing you might want to do\nthat's even more general is\n\n1170\n01:01:49,170 --> 01:01:52,470\nsuddenly you add somebody else\nto this bank account system.\n\n1171\n01:01:52,470 --> 01:01:56,030\nYou go and you add John to\nthis bank account system.\n\n1172\n01:01:56,030 --> 01:01:58,250\nAnd now there's yet another\nstream that's going to come\n\n1173\n01:01:58,250 --> 01:02:02,040\ninto the picture at some time\nwhich we haven't prespecified.\n\n1174\n01:02:02,040 --> 01:02:04,050\nSo that's something even fair\nmerge can't do, and they're\n\n1175\n01:02:04,050 --> 01:02:05,662\nthings called--\n\n1176\n01:02:05,662 --> 01:02:07,220\nI forget--\n\n1177\n01:02:07,220 --> 01:02:08,860\nnatagers or something.\n\n1178\n01:02:08,860 --> 01:02:11,790\nThat's a generalization of\nfair merge to allow that.\n\n1179\n01:02:11,790 --> 01:02:14,140\nThere's a whole sort of research\ndiscipline saying how\n\n1180\n01:02:14,140 --> 01:02:16,790\nfar can you push this functional\nperspective by\n\n1181\n01:02:16,790 --> 01:02:19,580\nadding more and more\nmechanism?\n\n1182\n01:02:19,580 --> 01:02:21,470\nAnd how far does that go before\nthe whole thing breaks\n\n1183\n01:02:21,470 --> 01:02:25,610\ndown and you might as well\nbeen using set anyway.\n\n1184\n01:02:25,610 --> 01:02:28,960\nAUDIENCE: You need to set him\nup on automatic deposit.\n\n1185\n01:02:28,960 --> 01:02:39,630\n[LAUGHTER]\n\n1186\n01:02:39,630 --> 01:02:40,880\nPROFESSOR: OK, thank you.\n\n1187\n01:02:40,880 --> 01:03:00,115\n\n"
  },
  {
    "path": "SrtEN/lec7a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:15,314\n\n\n1\n00:00:15,314 --> 00:00:17,580\nPROFESSOR: Well today we're\ngoing to learn about something\n\n2\n00:00:17,580 --> 00:00:18,410\nquite amazing.\n\n3\n00:00:18,410 --> 00:00:22,950\nWe're going to understand what\nwe mean by a program a little\n\n4\n00:00:22,950 --> 00:00:26,800\nbit more profoundly than\nwe have up till now.\n\n5\n00:00:26,800 --> 00:00:30,650\nUp till now, we've been thinking\nof programs as\n\n6\n00:00:30,650 --> 00:00:32,729\ndescribing machines.\n\n7\n00:00:32,729 --> 00:00:38,800\nSo for example, looking at this\nstill store, we see here\n\n8\n00:00:38,800 --> 00:00:42,800\nis a program for factorial.\n\n9\n00:00:42,800 --> 00:00:46,970\nAnd what it is, is a character\nstring description, if you\n\n10\n00:00:46,970 --> 00:00:49,520\nwill, of the wiring\ndiagram of a\n\n11\n00:00:49,520 --> 00:00:52,230\npotentially infinite machine.\n\n12\n00:00:52,230 --> 00:00:53,870\nAnd we can look at that\na little bit and\n\n13\n00:00:53,870 --> 00:00:55,130\njust see the idea.\n\n14\n00:00:55,130 --> 00:00:58,950\nThat this is a sort of compact\nnotation which says, if n is\n\n15\n00:00:58,950 --> 00:01:00,170\n0, the result is one.\n\n16\n00:01:00,170 --> 00:01:03,800\nWell here comes n coming into\nthis machine, and if it's 0,\n\n17\n00:01:03,800 --> 00:01:06,720\nthen I control this switch in\nsuch a way that the switch\n\n18\n00:01:06,720 --> 00:01:09,340\nallows the output to be one.\n\n19\n00:01:09,340 --> 00:01:12,970\nOtherwise, it's n times\nfactorial of n minus one.\n\n20\n00:01:12,970 --> 00:01:15,920\nWell, I'm computing factorial of\nn minus one and multiplying\n\n21\n00:01:15,920 --> 00:01:19,350\nthat by n, and, in the case that\nit's not 0, this switch\n\n22\n00:01:19,350 --> 00:01:21,900\nmakes the output come\nfrom there.\n\n23\n00:01:21,900 --> 00:01:24,460\nOf course, this is a machine\nwith a potentially infinite\n\n24\n00:01:24,460 --> 00:01:27,300\nnumber of parts, because\nfactorial occurs within\n\n25\n00:01:27,300 --> 00:01:31,070\nfactorial, so we don't know\nhow deep it has to be.\n\n26\n00:01:31,070 --> 00:01:36,480\nBut that's basically what our\nnotation for programs really\n\n27\n00:01:36,480 --> 00:01:38,310\nmeans to us at this point.\n\n28\n00:01:38,310 --> 00:01:41,810\nIt's a character string\ndescription, if you will, of a\n\n29\n00:01:41,810 --> 00:01:44,900\nwiring diagram that could also\nbe drawn some other way.\n\n30\n00:01:44,900 --> 00:01:47,520\nAnd, in fact, many people have\nproposed to me, programming\n\n31\n00:01:47,520 --> 00:01:49,490\nlanguages look graphical\nlike this.\n\n32\n00:01:49,490 --> 00:01:51,500\nI'm not sure I believe there\nare many advantages.\n\n33\n00:01:51,500 --> 00:01:54,470\nThe major disadvantage, of\ncourse, is that it takes up\n\n34\n00:01:54,470 --> 00:01:57,360\nmore space on a page, and,\ntherefore, it's harder to pack\n\n35\n00:01:57,360 --> 00:02:01,090\ninto a listing or to\nedit very well.\n\n36\n00:02:01,090 --> 00:02:05,300\nBut in any case, there's\nsomething very remarkable that\n\n37\n00:02:05,300 --> 00:02:08,810\ncan happen in the competition\nworld which is that you can\n\n38\n00:02:08,810 --> 00:02:10,450\nhave something called\na universal machine.\n\n39\n00:02:10,450 --> 00:02:18,340\nIf we look at the second\nslide, what we see is a\n\n40\n00:02:18,340 --> 00:02:21,260\nspecial machine called eval.\n\n41\n00:02:21,260 --> 00:02:23,670\nThere is a machine called eval,\nand I'm going to show it\n\n42\n00:02:23,670 --> 00:02:25,720\nto you today.\n\n43\n00:02:25,720 --> 00:02:27,780\nIt's very simple.\n\n44\n00:02:27,780 --> 00:02:30,490\nWhat is remarkable is that it\nwill fit on the blackboard.\n\n45\n00:02:30,490 --> 00:02:33,350\n\n\n46\n00:02:33,350 --> 00:02:38,310\nHowever, eval is a machine\nwhich takes as input a\n\n47\n00:02:38,310 --> 00:02:40,450\ndescription of another\nmachine.\n\n48\n00:02:40,450 --> 00:02:42,620\nIt could take the wiring\ndiagram of a\n\n49\n00:02:42,620 --> 00:02:46,490\nfactorial machine as input.\n\n50\n00:02:46,490 --> 00:02:52,020\nHaving done so, it becomes a\nsimulator for the factorial\n\n51\n00:02:52,020 --> 00:02:58,910\nmachine such that, if you put\na six in, out comes a 720.\n\n52\n00:02:58,910 --> 00:03:02,130\nThat's a very remarkable\nsort of machine.\n\n53\n00:03:02,130 --> 00:03:04,560\nAnd the most amazing part of\nit is that it fits on a\n\n54\n00:03:04,560 --> 00:03:05,590\nblackboard.\n\n55\n00:03:05,590 --> 00:03:10,070\nBy contrast, one could imagine\nin the analog electronics\n\n56\n00:03:10,070 --> 00:03:17,180\nworld a very different machine,\na machine which also\n\n57\n00:03:17,180 --> 00:03:20,440\nwas, in some sense, universal,\nwhere you gave a circuit\n\n58\n00:03:20,440 --> 00:03:24,830\ndiagram as one of the inputs,\nfor example, of this little\n\n59\n00:03:24,830 --> 00:03:28,050\nlow-pass filter, one-pole\nlow-pass filter.\n\n60\n00:03:28,050 --> 00:03:30,230\nAnd you can imagine that\nyou could, for\n\n61\n00:03:30,230 --> 00:03:32,030\nexample, scan this out--\n\n62\n00:03:32,030 --> 00:03:37,950\nthe scan lines are the signal\nthat's describing what this\n\n63\n00:03:37,950 --> 00:03:40,770\nmachine is to simulate--\n\n64\n00:03:40,770 --> 00:03:43,040\nthen the analog of that which\nis made out of electrical\n\n65\n00:03:43,040 --> 00:03:45,540\ncircuits, should configure\nitself into a filter that has\n\n66\n00:03:45,540 --> 00:03:47,010\nthe frequency response\nspecified\n\n67\n00:03:47,010 --> 00:03:49,890\nby the circuit diagram.\n\n68\n00:03:49,890 --> 00:03:52,520\nThat's a very hard machine to\nmake, and, surely, there's no\n\n69\n00:03:52,520 --> 00:03:55,670\nchance that I could put\nit on a blackboard.\n\n70\n00:03:55,670 --> 00:03:58,430\nSo we're going to see an\namazing thing today.\n\n71\n00:03:58,430 --> 00:04:01,240\nWe're going to see,\non the blackboard,\n\n72\n00:04:01,240 --> 00:04:02,790\nthe universal machine.\n\n73\n00:04:02,790 --> 00:04:06,780\nAnd we'll see that among other\nthings, it's extremely simple.\n\n74\n00:04:06,780 --> 00:04:10,070\nNow, we're getting very close\nto the real spirit in the\n\n75\n00:04:10,070 --> 00:04:11,280\ncomputer at this point.\n\n76\n00:04:11,280 --> 00:04:14,110\nSo I have to show a certain\namount of reverence and\n\n77\n00:04:14,110 --> 00:04:16,970\nrespect, so I'm going to wear\na suit jacket for the only\n\n78\n00:04:16,970 --> 00:04:20,470\ntime that you'll ever see me\nwear a suit jacket here.\n\n79\n00:04:20,470 --> 00:04:25,730\nAnd I think I'm also going to\nput on an appropriate hat for\n\n80\n00:04:25,730 --> 00:04:26,980\nthe occasion.\n\n81\n00:04:26,980 --> 00:04:28,780\n\n\n82\n00:04:28,780 --> 00:04:31,390\nNow, this is a lecturer which\nI have to warn you--\n\n83\n00:04:31,390 --> 00:04:34,140\n\n\n84\n00:04:34,140 --> 00:04:37,690\nlet's see, normally, people\nunder 40 and who don't have\n\n85\n00:04:37,690 --> 00:04:40,370\nseveral children are advised\nto be careful.\n\n86\n00:04:40,370 --> 00:04:44,170\nIf they're really worried, they\nshould leave. Because\n\n87\n00:04:44,170 --> 00:04:46,890\nthere's a certain amount of\nmysticism that will appear\n\n88\n00:04:46,890 --> 00:04:50,140\nhere which may be disturbing\nand cause\n\n89\n00:04:50,140 --> 00:04:51,820\ntrouble in your minds.\n\n90\n00:04:51,820 --> 00:04:57,300\nWell in any case, let's see,\nI wish to write for you the\n\n91\n00:04:57,300 --> 00:05:02,510\nevaluator for Lisp.\n\n92\n00:05:02,510 --> 00:05:05,020\nNow the evaluator isn't\nvery complicated.\n\n93\n00:05:05,020 --> 00:05:08,240\nIt's very much like all the\nprograms we've seen already.\n\n94\n00:05:08,240 --> 00:05:10,860\nThat's the amazing part of it.\n\n95\n00:05:10,860 --> 00:05:15,370\nIt's going to be-- and I'm going\nto write it right here--\n\n96\n00:05:15,370 --> 00:05:16,620\nit's a program called eval.\n\n97\n00:05:16,620 --> 00:05:22,900\n\n\n98\n00:05:22,900 --> 00:05:28,780\nAnd it's a procedure of two\narguments in expression of an\n\n99\n00:05:28,780 --> 00:05:30,030\nenvironment.\n\n100\n00:05:30,030 --> 00:05:31,860\n\n\n101\n00:05:31,860 --> 00:05:33,130\nAnd like every interesting\n\n102\n00:05:33,130 --> 00:05:34,940\nprocedure, it's a case analysis.\n\n103\n00:05:34,940 --> 00:05:40,460\n\n\n104\n00:05:40,460 --> 00:05:44,210\nBut before I start on this, I\nwant to tell you some things.\n\n105\n00:05:44,210 --> 00:05:46,880\nThe program we're going to write\non the blackboard is\n\n106\n00:05:46,880 --> 00:05:52,450\nugly, dirty, disgusting, not the\nway I would write this is\n\n107\n00:05:52,450 --> 00:05:54,210\na professional.\n\n108\n00:05:54,210 --> 00:05:57,940\nIt is written with concrete\nsyntax, meaning you've got\n\n109\n00:05:57,940 --> 00:05:59,630\nreally to use lots of CARs and\nCDRs which is exactly what I\n\n110\n00:05:59,630 --> 00:06:02,550\ntold you not to do.\n\n111\n00:06:02,550 --> 00:06:07,180\nThat's on purpose in this case,\nbecause I want it to be\n\n112\n00:06:07,180 --> 00:06:11,010\nsmall, compact, fit on the\nblackboard so you can get the\n\n113\n00:06:11,010 --> 00:06:12,420\nwhole thing.\n\n114\n00:06:12,420 --> 00:06:15,800\nSo I don't want to use long\nnames like I normally use.\n\n115\n00:06:15,800 --> 00:06:19,580\nI want to use CAR-CDR\nbecause it's short.\n\n116\n00:06:19,580 --> 00:06:20,950\nNow, that's a trade-off.\n\n117\n00:06:20,950 --> 00:06:23,570\nI don't want you writing\nprograms like this.\n\n118\n00:06:23,570 --> 00:06:26,090\nThis is purely for an effect.\n\n119\n00:06:26,090 --> 00:06:27,530\nNow, you're going to have to\nwork a little harder to read\n\n120\n00:06:27,530 --> 00:06:29,270\nit, but I'm going to try\nto make it clear\n\n121\n00:06:29,270 --> 00:06:31,270\nas I'm writing it.\n\n122\n00:06:31,270 --> 00:06:32,395\nI'm also--\n\n123\n00:06:32,395 --> 00:06:34,960\nthis is a pretty much complete\ninterpreter, but there's going\n\n124\n00:06:34,960 --> 00:06:36,290\nto be room for putting\nin more things--\n\n125\n00:06:36,290 --> 00:06:39,160\nI'm going to leave out\ndefinition and assignment,\n\n126\n00:06:39,160 --> 00:06:45,310\njust because they are not\nessential, for a mathematical\n\n127\n00:06:45,310 --> 00:06:51,670\nreason I'll show you later and\nalso they take up more space.\n\n128\n00:06:51,670 --> 00:06:54,170\nBut, in any case, what\ndo we have to do?\n\n129\n00:06:54,170 --> 00:06:57,160\nWe have to do a dispatch which\nbreaks the types of\n\n130\n00:06:57,160 --> 00:07:02,030\nexpressions up into particular\nclasses.\n\n131\n00:07:02,030 --> 00:07:03,525\nSo that's what we're\ngoing to have here.\n\n132\n00:07:03,525 --> 00:07:05,150\nWell, what expressions\nare there?\n\n133\n00:07:05,150 --> 00:07:06,810\nLet's look at the kinds\nof expressions.\n\n134\n00:07:06,810 --> 00:07:10,420\nWe can have things like\nthe numeral three.\n\n135\n00:07:10,420 --> 00:07:12,720\nWhat do I want that to do?\n\n136\n00:07:12,720 --> 00:07:15,640\nI can make choices, but I think\nright now, I want it to\n\n137\n00:07:15,640 --> 00:07:17,050\nbe a three.\n\n138\n00:07:17,050 --> 00:07:18,860\nThat's what I want.\n\n139\n00:07:18,860 --> 00:07:19,800\nSo that's easy enough.\n\n140\n00:07:19,800 --> 00:07:27,520\nThat means I want, if the\nthing is a number, the\n\n141\n00:07:27,520 --> 00:07:30,720\nexpression, that I want\nthe expression\n\n142\n00:07:30,720 --> 00:07:31,970\nitself as the answer.\n\n143\n00:07:31,970 --> 00:07:35,420\n\n\n144\n00:07:35,420 --> 00:07:37,700\nNow the next possibility\nis things that we\n\n145\n00:07:37,700 --> 00:07:39,390\nrepresent as symbols.\n\n146\n00:07:39,390 --> 00:07:47,614\nExamples of symbols are things\nlike x, n, eval, number, x.\n\n147\n00:07:47,614 --> 00:07:49,630\nWhat do I mean them to be?\n\n148\n00:07:49,630 --> 00:07:51,690\nThose are things that stand\nfor other things.\n\n149\n00:07:51,690 --> 00:07:54,770\nThose are the variables\nof our language.\n\n150\n00:07:54,770 --> 00:07:58,540\nAnd so I want to be able to say,\nfor example, that x, for\n\n151\n00:07:58,540 --> 00:08:02,930\nexample, transforms to it's\nvalue which might be three.\n\n152\n00:08:02,930 --> 00:08:07,920\nOr I might ask something\nlike car.\n\n153\n00:08:07,920 --> 00:08:09,710\nI want to have as its value--\n\n154\n00:08:09,710 --> 00:08:17,380\nbe something like some\nprocedure, which I don't know\n\n155\n00:08:17,380 --> 00:08:20,440\nwhat is inside there, perhaps\na machine language code or\n\n156\n00:08:20,440 --> 00:08:23,100\nsomething like that.\n\n157\n00:08:23,100 --> 00:08:24,430\nSo, well, that's easy enough.\n\n158\n00:08:24,430 --> 00:08:27,890\nI'm going to push that\noff on someone else.\n\n159\n00:08:27,890 --> 00:08:33,370\nIf something is a symbol, if\nthe expression is a symbol,\n\n160\n00:08:33,370 --> 00:08:38,140\nthen I want the answer to be\nthe result, looking up the\n\n161\n00:08:38,140 --> 00:08:40,159\nexpression in the environment.\n\n162\n00:08:40,159 --> 00:08:46,480\n\n\n163\n00:08:46,480 --> 00:08:52,410\nNow the environment is a\ndictionary which maps the\n\n164\n00:08:52,410 --> 00:08:54,060\nsymbol names to their values.\n\n165\n00:08:54,060 --> 00:08:56,280\nAnd that's all it is.\n\n166\n00:08:56,280 --> 00:08:57,530\nHow it's done?\n\n167\n00:08:57,530 --> 00:08:59,760\nWell, we'll see that later.\n\n168\n00:08:59,760 --> 00:09:01,670\nIt's very easy.\n\n169\n00:09:01,670 --> 00:09:03,630\nIt's easy to make data\nstructures that are tables of\n\n170\n00:09:03,630 --> 00:09:04,670\nvarious sorts.\n\n171\n00:09:04,670 --> 00:09:07,080\nBut it's only a table, and this\nis the access routine for\n\n172\n00:09:07,080 --> 00:09:10,040\nsome table.\n\n173\n00:09:10,040 --> 00:09:12,720\nWell, the next thing, another\nkind of expression--\n\n174\n00:09:12,720 --> 00:09:14,870\nyou have things that are\ndescribed constants that are\n\n175\n00:09:14,870 --> 00:09:17,430\nnot numbers, like 'foo.\n\n176\n00:09:17,430 --> 00:09:20,170\n\n\n177\n00:09:20,170 --> 00:09:22,450\nWell, for my convenience,\nI want to syntactically\n\n178\n00:09:22,450 --> 00:09:31,520\ntransform that into a list\nstructure which is, quote foo.\n\n179\n00:09:31,520 --> 00:09:35,140\n\n\n180\n00:09:35,140 --> 00:09:39,950\nA quoted object, whatever it is,\nis going to be actually an\n\n181\n00:09:39,950 --> 00:09:43,550\nabbreviation, which is not\npart of the evaluator but\n\n182\n00:09:43,550 --> 00:09:46,960\nhappens somewhere else, an\nabbreviation for an expression\n\n183\n00:09:46,960 --> 00:09:48,780\nthat looks like this.\n\n184\n00:09:48,780 --> 00:09:52,120\nThis way, I can test for the\ntype of the expression as\n\n185\n00:09:52,120 --> 00:09:55,615\nbeing a quotation by examining\nthe car of the expression.\n\n186\n00:09:55,615 --> 00:09:58,460\n\n\n187\n00:09:58,460 --> 00:10:01,650\nSo I'm not going to worry about\nthat in the evaluator.\n\n188\n00:10:01,650 --> 00:10:02,780\nIt's happening somewhere\nearlier in\n\n189\n00:10:02,780 --> 00:10:05,540\nthe reader or something.\n\n190\n00:10:05,540 --> 00:10:18,620\nIf the expression of the\nexpression is quote, then what\n\n191\n00:10:18,620 --> 00:10:25,140\nI want, I want quote foo to\nitself evaluate to foo.\n\n192\n00:10:25,140 --> 00:10:27,530\nIt's a constant.\n\n193\n00:10:27,530 --> 00:10:30,645\nThis is just a way of saying\nthat this evaluates to itself.\n\n194\n00:10:30,645 --> 00:10:33,150\n\n\n195\n00:10:33,150 --> 00:10:33,660\nWhat is that?\n\n196\n00:10:33,660 --> 00:10:37,330\nThat's the second of the list.\nIt's the second element of the\n\n197\n00:10:37,330 --> 00:10:41,604\nlist. The second element of the\nlist is it's CADR. So I'm\n\n198\n00:10:41,604 --> 00:10:51,290\njust going to write\nhere, CADR.\n\n199\n00:10:51,290 --> 00:10:52,510\nWhat else do we have here?\n\n200\n00:10:52,510 --> 00:10:56,040\nWe have lambda expressions,\nfor example,\n\n201\n00:10:56,040 --> 00:11:04,160\nlambda of x plus x y.\n\n202\n00:11:04,160 --> 00:11:05,910\nWell, I going have to have some\nrepresentation for the\n\n203\n00:11:05,910 --> 00:11:08,610\nprocedure which is the value of\nan expression, of a lambda\n\n204\n00:11:08,610 --> 00:11:09,600\nexpression.\n\n205\n00:11:09,600 --> 00:11:13,030\nThe procedure here is not\nthe expression lambda x.\n\n206\n00:11:13,030 --> 00:11:16,170\nThat's the description of it,\nthe textual description.\n\n207\n00:11:16,170 --> 00:11:18,800\nHowever, what what I going\nto expect to see here is\n\n208\n00:11:18,800 --> 00:11:20,930\nsomething which contains an\nenvironment as one of its\n\n209\n00:11:20,930 --> 00:11:27,360\nparts if I'm implementing\na lexical language.\n\n210\n00:11:27,360 --> 00:11:30,790\nAnd so what I'd like to see\nis some type flags.\n\n211\n00:11:30,790 --> 00:11:33,440\nI'm going to have to be able\nto distinguish procedures\n\n212\n00:11:33,440 --> 00:11:37,190\nlater, procedures which were\nproduced by lambdas, from ones\n\n213\n00:11:37,190 --> 00:11:39,060\nthat may be primitive.\n\n214\n00:11:39,060 --> 00:11:42,440\nAnd so I'm going to have some\nflag, which I'll just\n\n215\n00:11:42,440 --> 00:11:44,935\narbitrarily call closure, just\nfor historical reasons.\n\n216\n00:11:44,935 --> 00:11:47,760\n\n\n217\n00:11:47,760 --> 00:11:49,920\nNow, to say what parts of\nthis are important.\n\n218\n00:11:49,920 --> 00:11:51,970\nI'm going to need to know\nthe bound variable\n\n219\n00:11:51,970 --> 00:11:54,220\nlist and the body.\n\n220\n00:11:54,220 --> 00:12:00,870\nWell, that's the CDR of this, so\nit's going to be x and plus\n\n221\n00:12:00,870 --> 00:12:03,795\nx y and some environment.\n\n222\n00:12:03,795 --> 00:12:08,170\n\n\n223\n00:12:08,170 --> 00:12:13,980\nNow this is not something that\nusers should ever see, this is\n\n224\n00:12:13,980 --> 00:12:16,680\npurely a representation,\ninternally,\n\n225\n00:12:16,680 --> 00:12:18,520\nfor a procedure object.\n\n226\n00:12:18,520 --> 00:12:22,010\nIt contains a bound variable\nlist, a body, and an\n\n227\n00:12:22,010 --> 00:12:26,340\nenvironment, and some type tag\nsaying, I am a procedure.\n\n228\n00:12:26,340 --> 00:12:28,080\nI'm going to make one now.\n\n229\n00:12:28,080 --> 00:12:43,720\nSo if the CAR of the expression\nis quote lambda,\n\n230\n00:12:43,720 --> 00:12:45,970\nthen what I'm going\nto put here is--\n\n231\n00:12:45,970 --> 00:12:58,860\nI'm going to make a list of\nclosure, the CDR of the\n\n232\n00:12:58,860 --> 00:13:07,520\nprocedure description was\neverything except the lambda,\n\n233\n00:13:07,520 --> 00:13:10,250\nand the current environment.\n\n234\n00:13:10,250 --> 00:13:14,470\nThis implements the rule\nfor environments in the\n\n235\n00:13:14,470 --> 00:13:15,190\nenvironment model.\n\n236\n00:13:15,190 --> 00:13:17,980\nIt has to do with construction\nof procedures from lambda\n\n237\n00:13:17,980 --> 00:13:19,210\nexpressions.\n\n238\n00:13:19,210 --> 00:13:22,180\nThe environment that was\naround at the time the\n\n239\n00:13:22,180 --> 00:13:25,940\nevaluator encountered the\nlambda expression is the\n\n240\n00:13:25,940 --> 00:13:30,990\nenvironment where the procedure\nresulting interprets\n\n241\n00:13:30,990 --> 00:13:32,240\nit's free variables.\n\n242\n00:13:32,240 --> 00:13:34,720\n\n\n243\n00:13:34,720 --> 00:13:35,920\nSo that's part of that.\n\n244\n00:13:35,920 --> 00:13:38,120\nAnd so we have to capture that\nenvironment as part of the\n\n245\n00:13:38,120 --> 00:13:39,210\nprocedure object.\n\n246\n00:13:39,210 --> 00:13:41,750\nAnd we'll see how that\ngets used later.\n\n247\n00:13:41,750 --> 00:13:45,140\nThere are also conditional\nexpressions of things like\n\n248\n00:13:45,140 --> 00:13:54,520\nCOND of say, p one, e\none, p two, e two.\n\n249\n00:13:54,520 --> 00:13:57,670\nWhere this is a predicate, a\npredicate is a thing that is\n\n250\n00:13:57,670 --> 00:14:00,930\neither true or false, and the\nexpression to be evaluated if\n\n251\n00:14:00,930 --> 00:14:03,480\nthe predicate is true.\n\n252\n00:14:03,480 --> 00:14:05,516\nA set of clauses, if you\nwill, that's the\n\n253\n00:14:05,516 --> 00:14:06,790\nname for such a thing.\n\n254\n00:14:06,790 --> 00:14:09,360\nSo I'm going put that\nsomewhere else.\n\n255\n00:14:09,360 --> 00:14:12,420\nWe're going to worry about that\nin another piece of code.\n\n256\n00:14:12,420 --> 00:14:13,670\nSo EQ--\n\n257\n00:14:13,670 --> 00:14:15,900\n\n\n258\n00:14:15,900 --> 00:14:24,710\nif the CAR of the expression is\nCOND, then I'm going to do\n\n259\n00:14:24,710 --> 00:14:30,800\nnothing more than evaluate\nthe COND, the CDR of the\n\n260\n00:14:30,800 --> 00:14:32,050\nexpression.\n\n261\n00:14:32,050 --> 00:14:34,080\n\n\n262\n00:14:34,080 --> 00:14:38,380\nThat's all the clauses in the\nenvironment that I'm given.\n\n263\n00:14:38,380 --> 00:14:41,430\n\n\n264\n00:14:41,430 --> 00:14:46,480\nWell, there's one more case,\narbitrary thing like the sum\n\n265\n00:14:46,480 --> 00:14:53,380\nof x and three, where this\nis an operator applied to\n\n266\n00:14:53,380 --> 00:14:56,590\noperands, and there's nothing\nspecial about it.\n\n267\n00:14:56,590 --> 00:14:59,850\nIt's not one of the special\ncases, the special forms.\n\n268\n00:14:59,850 --> 00:15:09,650\nThese are the special forms.\n\n269\n00:15:09,650 --> 00:15:12,480\nAnd if I were writing here a\nprofessional program, again, I\n\n270\n00:15:12,480 --> 00:15:14,370\nwould somehow make this\ndata directed.\n\n271\n00:15:14,370 --> 00:15:16,690\nSo there wouldn't be a sequence\nof conditionals here,\n\n272\n00:15:16,690 --> 00:15:20,290\nthere'd be a dispatch on some\nbits if I were trying to do\n\n273\n00:15:20,290 --> 00:15:22,360\nthis in a more professional\nway.\n\n274\n00:15:22,360 --> 00:15:25,750\nSo that, in fact, I can add to\nthe thing without changing my\n\n275\n00:15:25,750 --> 00:15:26,710\nprogram much.\n\n276\n00:15:26,710 --> 00:15:29,850\nSo, for example, they would run\nfast, but I'm not worried\n\n277\n00:15:29,850 --> 00:15:31,280\nabout that.\n\n278\n00:15:31,280 --> 00:15:34,890\nHere we're trying to look\nat this in its entirety.\n\n279\n00:15:34,890 --> 00:15:37,360\nSo it's else.\n\n280\n00:15:37,360 --> 00:15:38,560\nWell, what do we do?\n\n281\n00:15:38,560 --> 00:15:40,965\nIn this case, I have to somehow\ndo an addition.\n\n282\n00:15:40,965 --> 00:15:44,350\n\n\n283\n00:15:44,350 --> 00:15:46,565\nWell, I could find out\nwhat the plus is.\n\n284\n00:15:46,565 --> 00:15:50,550\nI have to find out what the\nx and the three are.\n\n285\n00:15:50,550 --> 00:15:53,330\nAnd then I have to apply the\nresult of finding what the\n\n286\n00:15:53,330 --> 00:15:56,360\nplus is to the result of\nfinding out what the x\n\n287\n00:15:56,360 --> 00:15:58,020\nand the three are.\n\n288\n00:15:58,020 --> 00:15:59,830\nWe'll have a name for that.\n\n289\n00:15:59,830 --> 00:16:11,280\nSo I'm going to apply the result\nof evaluating the CAR\n\n290\n00:16:11,280 --> 00:16:13,270\nof the expression--\n\n291\n00:16:13,270 --> 00:16:17,210\nthe car of the expression\nis the operator--\n\n292\n00:16:17,210 --> 00:16:20,480\nin the environment given.\n\n293\n00:16:20,480 --> 00:16:24,050\nSo evaluating the operator\ngets me the procedure.\n\n294\n00:16:24,050 --> 00:16:27,290\nNow I have to evaluate all the\noperands to get the arguments.\n\n295\n00:16:27,290 --> 00:16:34,710\nI'll call that EVLIST, the CDR\nof the operands, of the\n\n296\n00:16:34,710 --> 00:16:38,835\nexpression, with respect\nto the environment.\n\n297\n00:16:38,835 --> 00:16:41,940\n\n\n298\n00:16:41,940 --> 00:16:43,290\nEVLIST will come up later--\n\n299\n00:16:43,290 --> 00:16:48,070\nEVLIST, apply, COND pair,\nCOND, lambda, define.\n\n300\n00:16:48,070 --> 00:16:50,900\n\n\n301\n00:16:50,900 --> 00:16:53,630\nSo that what you are seeing here\nnow is pretty much all\n\n302\n00:16:53,630 --> 00:16:56,590\nthere is in the evaluator\nitself.\n\n303\n00:16:56,590 --> 00:17:01,370\nIt's the case dispatch on the\ntype of the expression with\n\n304\n00:17:01,370 --> 00:17:07,470\nthe default being a general\napplication or a combination.\n\n305\n00:17:07,470 --> 00:17:17,520\n\n\n306\n00:17:17,520 --> 00:17:20,089\nNow there is lots of things\nwe haven't defined yet.\n\n307\n00:17:20,089 --> 00:17:21,780\nLet's just look at them\nand see what they are.\n\n308\n00:17:21,780 --> 00:17:25,480\nWe're going to have to do\nthis later, evcond.\n\n309\n00:17:25,480 --> 00:17:27,579\nWe have to write apply.\n\n310\n00:17:27,579 --> 00:17:29,120\nWe're going to have to\nwrite EVLIST. We're\n\n311\n00:17:29,120 --> 00:17:31,790\ngoing to write LOOKUP.\n\n312\n00:17:31,790 --> 00:17:33,430\nI think that's everything,\nisn't there?\n\n313\n00:17:33,430 --> 00:17:35,860\nEverything else is something\nwhich is simple, or primitive,\n\n314\n00:17:35,860 --> 00:17:38,570\nor something like that.\n\n315\n00:17:38,570 --> 00:17:42,360\nAnd, of course, we could many\nmore special forms here, but\n\n316\n00:17:42,360 --> 00:17:44,450\nthat would be a bad idea in\ngeneral in a language.\n\n317\n00:17:44,450 --> 00:17:46,730\nYou make a language very\ncomplicated by putting a lot\n\n318\n00:17:46,730 --> 00:17:47,690\nof things in there.\n\n319\n00:17:47,690 --> 00:17:49,830\nThe number of reserve words\nthat should exist in a\n\n320\n00:17:49,830 --> 00:17:52,540\nlanguage should be no more than\na person could remember\n\n321\n00:17:52,540 --> 00:17:54,010\non his fingers and toes.\n\n322\n00:17:54,010 --> 00:17:56,820\nAnd I get very upset with\nlanguages which have hundreds\n\n323\n00:17:56,820 --> 00:17:59,410\nof reserve words.\n\n324\n00:17:59,410 --> 00:18:00,710\nBut that's where the\nreserve words go.\n\n325\n00:18:00,710 --> 00:18:04,750\n\n\n326\n00:18:04,750 --> 00:18:06,430\nWell, now let's get to\nthe next part of\n\n327\n00:18:06,430 --> 00:18:09,640\nthis, the kernel, apply.\n\n328\n00:18:09,640 --> 00:18:11,590\nWhat else is this doing?\n\n329\n00:18:11,590 --> 00:18:17,020\nWell, apply's job is to take a\nprocedure and apply it to its\n\n330\n00:18:17,020 --> 00:18:19,500\narguments after both have been\nevaluated to come up with a\n\n331\n00:18:19,500 --> 00:18:22,560\nprocedure and the arguments\nrather the operator symbols\n\n332\n00:18:22,560 --> 00:18:25,360\nand the operand symbols,\nwhatever they are--\n\n333\n00:18:25,360 --> 00:18:26,610\nsymbolic expressions.\n\n334\n00:18:26,610 --> 00:18:33,270\n\n\n335\n00:18:33,270 --> 00:18:40,810\nSo we will define apply to be a\nprocedure of two arguments,\n\n336\n00:18:40,810 --> 00:18:43,280\na procedure and arguments.\n\n337\n00:18:43,280 --> 00:18:47,110\n\n\n338\n00:18:47,110 --> 00:18:48,080\nAnd what does it do?\n\n339\n00:18:48,080 --> 00:18:49,720\nIt does nothing very\ncomplicated.\n\n340\n00:18:49,720 --> 00:18:50,970\nIt's got two cases.\n\n341\n00:18:50,970 --> 00:18:53,580\n\n\n342\n00:18:53,580 --> 00:18:55,095\nEither the procedure\nis primitive--\n\n343\n00:18:55,095 --> 00:19:02,970\n\n\n344\n00:19:02,970 --> 00:19:06,930\nAnd I don't know exactly\nhow that is done.\n\n345\n00:19:06,930 --> 00:19:10,930\nIt's possible there's some type\ninformation just like we\n\n346\n00:19:10,930 --> 00:19:14,110\nmade closure for, here, being\nthe description of the type of\n\n347\n00:19:14,110 --> 00:19:16,810\na compound thing--\n\n348\n00:19:16,810 --> 00:19:18,550\nprobably so.\n\n349\n00:19:18,550 --> 00:19:21,360\nBut it is not essential how that\nworks, and, in fact, it\n\n350\n00:19:21,360 --> 00:19:24,140\nturns out, as you probably know\nor have deduced, that you\n\n351\n00:19:24,140 --> 00:19:27,350\ndon't need any primitives\nanyway.\n\n352\n00:19:27,350 --> 00:19:30,732\nYou can compute anything without\nthem because some of\n\n353\n00:19:30,732 --> 00:19:33,190\nthe lambda that I've\nbeen playing with.\n\n354\n00:19:33,190 --> 00:19:34,750\nBut it's nice to have them.\n\n355\n00:19:34,750 --> 00:19:36,630\nSo here we're going to do\nsome magic which I'm\n\n356\n00:19:36,630 --> 00:19:38,060\nnot going to explain.\n\n357\n00:19:38,060 --> 00:19:42,860\nGo to machine language,\napply primop.\n\n358\n00:19:42,860 --> 00:19:44,850\nHere's how it adds.\n\n359\n00:19:44,850 --> 00:19:46,100\nExecute an add instruction.\n\n360\n00:19:46,100 --> 00:19:50,360\n\n\n361\n00:19:50,360 --> 00:19:52,840\nHowever, the interesting part\nof a language is the glue by\n\n362\n00:19:52,840 --> 00:19:54,940\nwhich the predicates\nare glued together.\n\n363\n00:19:54,940 --> 00:19:56,910\nSo let's look at that.\n\n364\n00:19:56,910 --> 00:20:01,210\nWell, the other possibility is\nthat this is a compound made\n\n365\n00:20:01,210 --> 00:20:05,140\nup by executing a lambda\nexpression, this\n\n366\n00:20:05,140 --> 00:20:07,620\nis a compound procedure.\n\n367\n00:20:07,620 --> 00:20:10,110\nWell, we'll check its type.\n\n368\n00:20:10,110 --> 00:20:23,010\nIf it is closure, if it's one of\nthose, then I have to do an\n\n369\n00:20:23,010 --> 00:20:24,500\neval of the body.\n\n370\n00:20:24,500 --> 00:20:28,960\nThe way I do this, the way I\ndeal with this at all, is the\n\n371\n00:20:28,960 --> 00:20:31,210\nway I evaluate the application\nof a procedure to its\n\n372\n00:20:31,210 --> 00:20:34,400\narguments, is by evaluating the\nbody of the procedure in\n\n373\n00:20:34,400 --> 00:20:37,050\nthe environment resulting from\nextending the environment of\n\n374\n00:20:37,050 --> 00:20:39,670\nthe procedure with the bindings\nof the formal\n\n375\n00:20:39,670 --> 00:20:43,010\nparameters of the procedure\nto the arguments that\n\n376\n00:20:43,010 --> 00:20:44,260\nwere passed to it.\n\n377\n00:20:44,260 --> 00:20:47,030\n\n\n378\n00:20:47,030 --> 00:20:48,280\nThat was a long sentence.\n\n379\n00:20:48,280 --> 00:20:51,130\n\n\n380\n00:20:51,130 --> 00:20:52,822\nWell that's easy enough.\n\n381\n00:20:52,822 --> 00:20:56,214\nNow here's going to be\na lot of CAR-CDRing.\n\n382\n00:20:56,214 --> 00:20:59,400\nI have to get the body\nof the procedure.\n\n383\n00:20:59,400 --> 00:21:02,960\nWhere's the body of the\nprocedure in here?\n\n384\n00:21:02,960 --> 00:21:05,490\nWell here's the CAR, here's\nthe CDR is the\n\n385\n00:21:05,490 --> 00:21:06,130\nwhole rest of this.\n\n386\n00:21:06,130 --> 00:21:09,130\nSo here's the CADR. And so I\nsee, what I have here is the\n\n387\n00:21:09,130 --> 00:21:11,430\nbody is the second element\nof the second\n\n388\n00:21:11,430 --> 00:21:13,200\nelement of the procedure.\n\n389\n00:21:13,200 --> 00:21:19,170\nSo it's the CADR of the\nCADR or the CADADR.\n\n390\n00:21:19,170 --> 00:21:27,495\nIt's the C-A-D-A-D-R, CADADR\nof the procedure.\n\n391\n00:21:27,495 --> 00:21:30,260\n\n\n392\n00:21:30,260 --> 00:21:35,170\nTo evaluate the body in the\nresult of binding that's\n\n393\n00:21:35,170 --> 00:21:39,080\nmaking up more environment,\nwell I need the formal\n\n394\n00:21:39,080 --> 00:21:43,500\nparameters of the of the\nprocedure, what is that?\n\n395\n00:21:43,500 --> 00:21:48,780\nThat's the CAR of the CDR.\nIt's horrible isn't it?\n\n396\n00:21:48,780 --> 00:21:52,440\n\n\n397\n00:21:52,440 --> 00:21:55,440\n--of the procedure.\n\n398\n00:21:55,440 --> 00:22:00,370\nBind that to the arguments\nthat were passed in the\n\n399\n00:22:00,370 --> 00:22:04,540\nenvironment, which is passed\nalso as part of the procedure.\n\n400\n00:22:04,540 --> 00:22:09,670\nWell, that's the CAR of the\nCDR of the CDR of this,\n\n401\n00:22:09,670 --> 00:22:16,315\nCADDR, of the procedure.\n\n402\n00:22:16,315 --> 00:22:20,290\n\n\n403\n00:22:20,290 --> 00:22:26,490\nBind, eval, pair, COND,\nlamda, define--\n\n404\n00:22:26,490 --> 00:22:29,370\nNow, of course, if I were being\nreally a neat character,\n\n405\n00:22:29,370 --> 00:22:33,490\nand I was being very careful, I\nwould actually put an extra\n\n406\n00:22:33,490 --> 00:22:36,540\ncase here for checking for\ncertain errors like, did you\n\n407\n00:22:36,540 --> 00:22:39,000\ntry to apply one\nto an argument?\n\n408\n00:22:39,000 --> 00:22:42,570\nYou get a undefined\nprocedure type.\n\n409\n00:22:42,570 --> 00:22:45,500\nSo I may as well\ndo that anyway.\n\n410\n00:22:45,500 --> 00:22:57,610\n--else, some sort of\nerror, like that.\n\n411\n00:22:57,610 --> 00:23:02,620\nNow, of course, again, in some\nsort of more real system,\n\n412\n00:23:02,620 --> 00:23:06,770\nwritten for professional\nreasons, this would be written\n\n413\n00:23:06,770 --> 00:23:10,750\nwith a case analysis done by\nsome sort of dispatch.\n\n414\n00:23:10,750 --> 00:23:13,250\nOver here, I would probably have\nother cases like, is this\n\n415\n00:23:13,250 --> 00:23:16,220\ncompiled code?\n\n416\n00:23:16,220 --> 00:23:17,020\nIt's very important.\n\n417\n00:23:17,020 --> 00:23:19,530\nI might have distinguished the\nkind of code that's produced\n\n418\n00:23:19,530 --> 00:23:23,150\nby a directly evaluating a\nlambda in interpretation from\n\n419\n00:23:23,150 --> 00:23:25,190\ncode that was produced by\nsomebody's compiler or\n\n420\n00:23:25,190 --> 00:23:25,880\nsomething like that.\n\n421\n00:23:25,880 --> 00:23:27,230\nAnd we'll talk about\nthat later.\n\n422\n00:23:27,230 --> 00:23:28,710\nOr is this a piece Fortran\nprogram I have\n\n423\n00:23:28,710 --> 00:23:30,510\nto go off and execute.\n\n424\n00:23:30,510 --> 00:23:31,820\nIt's a perfectly possible\nthing, at this\n\n425\n00:23:31,820 --> 00:23:32,920\npoint, to do that.\n\n426\n00:23:32,920 --> 00:23:36,070\nIn fact, in this concrete syntax\nevaluator I'm writing\n\n427\n00:23:36,070 --> 00:23:42,600\nhere, there's an assumption\nbuilt in that this is Lisp,\n\n428\n00:23:42,600 --> 00:23:44,360\nbecause I'm using\nCARs and CDRs.\n\n429\n00:23:44,360 --> 00:23:46,750\nCAR means the operator, and\nCDR means the operand.\n\n430\n00:23:46,750 --> 00:23:50,500\nIn the text, there is an\nabstract syntax evaluator for\n\n431\n00:23:50,500 --> 00:23:52,160\nwhich these could be--\n\n432\n00:23:52,160 --> 00:23:54,310\nthese are given abstract names\nlike operator, and operand,\n\n433\n00:23:54,310 --> 00:23:56,160\nand all these other things\nare like that.\n\n434\n00:23:56,160 --> 00:24:00,320\nAnd, in that case, you could\nreprogram it to be ALGOL with\n\n435\n00:24:00,320 --> 00:24:01,570\nno problem.\n\n436\n00:24:01,570 --> 00:24:03,760\n\n\n437\n00:24:03,760 --> 00:24:07,410\nWell, here we have added another\ncouple of things that\n\n438\n00:24:07,410 --> 00:24:08,660\nwe haven't defined.\n\n439\n00:24:08,660 --> 00:24:10,810\n\n\n440\n00:24:10,810 --> 00:24:13,800\nI don't think I'll worry about\nthese at all, however, this\n\n441\n00:24:13,800 --> 00:24:15,050\none will be interesting later.\n\n442\n00:24:15,050 --> 00:24:17,930\n\n\n443\n00:24:17,930 --> 00:24:20,550\nLet's just proceed through\nthis and get it done.\n\n444\n00:24:20,550 --> 00:24:21,810\nThere's only two more\nblackboards so it\n\n445\n00:24:21,810 --> 00:24:23,060\ncan't be very long.\n\n446\n00:24:23,060 --> 00:24:27,056\n\n\n447\n00:24:27,056 --> 00:24:30,070\nIt's carefully tailored\nto exactly fit.\n\n448\n00:24:30,070 --> 00:24:30,980\nWell, what do we have left?\n\n449\n00:24:30,980 --> 00:24:33,730\nWe have to define EVLIST,\nwhich is over here.\n\n450\n00:24:33,730 --> 00:24:40,620\nAnd EVLIST is nothing more than\na map down a bunch of\n\n451\n00:24:40,620 --> 00:24:44,240\noperands producing arguments.\n\n452\n00:24:44,240 --> 00:24:45,820\nBut I'm going to write it out.\n\n453\n00:24:45,820 --> 00:24:47,445\nAnd one of the reasons I'm going\nto write this out is for\n\n454\n00:24:47,445 --> 00:24:51,820\na mystical reason, which is I\nwant to make this evaluator so\n\n455\n00:24:51,820 --> 00:24:53,610\nsimple that it can understand\nitself.\n\n456\n00:24:53,610 --> 00:24:56,450\n\n\n457\n00:24:56,450 --> 00:25:00,230\nI'm going to really worry\nabout that a little bit.\n\n458\n00:25:00,230 --> 00:25:02,850\nSo let's write it\nout completely.\n\n459\n00:25:02,850 --> 00:25:04,890\nSee, I don't want to worry about\nwhether or not the thing\n\n460\n00:25:04,890 --> 00:25:06,080\ncan pass functional arguments.\n\n461\n00:25:06,080 --> 00:25:08,980\nThe value evaluator is not\ngoing to use them.\n\n462\n00:25:08,980 --> 00:25:10,880\nThe evaluator is not going to\nproduce functional values.\n\n463\n00:25:10,880 --> 00:25:12,310\nSo even if there were a\ndifferent, alternative\n\n464\n00:25:12,310 --> 00:25:16,510\nlanguage that were very close\nto this, this evaluates a\n\n465\n00:25:16,510 --> 00:25:19,830\ncomplex language like Scheme\nwhich does allow procedural\n\n466\n00:25:19,830 --> 00:25:24,070\narguments, procedural values,\nand procedural data.\n\n467\n00:25:24,070 --> 00:25:28,100\nBut even if I were evaluating\nALGOL, which doesn't allow\n\n468\n00:25:28,100 --> 00:25:31,580\nprocedural values, I could\nuse this evaluator.\n\n469\n00:25:31,580 --> 00:25:32,870\nAnd this evaluator\nis not making any\n\n470\n00:25:32,870 --> 00:25:34,050\nassumptions about that.\n\n471\n00:25:34,050 --> 00:25:36,580\nAnd, in fact, if this value were\nto be restricted to not\n\n472\n00:25:36,580 --> 00:25:37,700\nbeing able to that, it wouldn't\nmatter, because it\n\n473\n00:25:37,700 --> 00:25:40,640\ndoesn't use any of those\nclever things.\n\n474\n00:25:40,640 --> 00:25:44,070\nSo that's why I'm arranging\nthis to be super simple.\n\n475\n00:25:44,070 --> 00:25:45,970\nThis is sort of the kernel\nof all possible language\n\n476\n00:25:45,970 --> 00:25:47,810\nevaluators.\n\n477\n00:25:47,810 --> 00:25:49,420\nHow about that?\n\n478\n00:25:49,420 --> 00:25:50,670\nEvlist--\n\n479\n00:25:50,670 --> 00:25:52,525\n\n\n480\n00:25:52,525 --> 00:25:53,820\nwell, what is it?\n\n481\n00:25:53,820 --> 00:25:56,300\nIt's the procedure of two\narguments, l and an\n\n482\n00:25:56,300 --> 00:26:06,260\nenvironment, where l is a list\nsuch that if the list of\n\n483\n00:26:06,260 --> 00:26:12,380\narguments is the empty list,\nthen the result is the empty\n\n484\n00:26:12,380 --> 00:26:21,480\nlist. Otherwise, I want to\ncons up the result of\n\n485\n00:26:21,480 --> 00:26:31,880\nevaluating the CAR of the\nlist of operands in the\n\n486\n00:26:31,880 --> 00:26:33,260\nenvironment.\n\n487\n00:26:33,260 --> 00:26:36,360\nSo I want the first operand\nevaluated, and I'm going to\n\n488\n00:26:36,360 --> 00:26:40,735\nmake a list of the results by\nCONSing that onto the result\n\n489\n00:26:40,735 --> 00:26:48,880\nof this EVLISTing as a CDR\nrecursion, the CDR of the list\n\n490\n00:26:48,880 --> 00:26:50,130\nrelative to the same\nenvironment.\n\n491\n00:26:50,130 --> 00:26:53,350\n\n\n492\n00:26:53,350 --> 00:26:57,960\nEvlist, cons, else, COND,\nlambda, define--\n\n493\n00:26:57,960 --> 00:27:00,950\n\n\n494\n00:27:00,950 --> 00:27:03,620\nAnd I have one more that I want\nto put on the blackboard.\n\n495\n00:27:03,620 --> 00:27:05,470\nIt's the essence of\nthis whole thing.\n\n496\n00:27:05,470 --> 00:27:08,130\nAnd there's some sort\nof next layer down.\n\n497\n00:27:08,130 --> 00:27:14,540\n\n\n498\n00:27:14,540 --> 00:27:15,770\nConditionals--\n\n499\n00:27:15,770 --> 00:27:17,500\nconditionals are the only thing\nleft that are sort of\n\n500\n00:27:17,500 --> 00:27:18,880\nsubstantial.\n\n501\n00:27:18,880 --> 00:27:22,320\nThen below that, we have to\nworry about things like lookup\n\n502\n00:27:22,320 --> 00:27:25,530\nand bind, and we'll look\nat that in a second.\n\n503\n00:27:25,530 --> 00:27:29,030\nBut of the substantial stuff at\nthis level of detail, next\n\n504\n00:27:29,030 --> 00:27:31,600\nimportant thing is how you\ndeal with conditionals.\n\n505\n00:27:31,600 --> 00:27:33,330\nWell, how do we have a\nconditional thing?\n\n506\n00:27:33,330 --> 00:27:37,670\n\n\n507\n00:27:37,670 --> 00:27:44,720\nIt's a procedure of a set of\nclauses and an environment.\n\n508\n00:27:44,720 --> 00:27:47,340\n\n\n509\n00:27:47,340 --> 00:27:49,820\nAnd what does it do?\n\n510\n00:27:49,820 --> 00:28:03,310\nIt says, if I've no more\nclauses, well, I have to give\n\n511\n00:28:03,310 --> 00:28:04,520\nthis a value.\n\n512\n00:28:04,520 --> 00:28:06,540\nIt could be that it\nwas an error.\n\n513\n00:28:06,540 --> 00:28:08,030\nSupposing it run off\nthe end of a\n\n514\n00:28:08,030 --> 00:28:10,060\nconditional, it's pretty arbitrary.\n\n515\n00:28:10,060 --> 00:28:13,650\nIt's up to me as programmer to\nchoose what I want to happen.\n\n516\n00:28:13,650 --> 00:28:15,940\nIt's convenient for me, right\nnow, to write down that this\n\n517\n00:28:15,940 --> 00:28:20,100\nhas a value which is the empty\nlist, doesn't matter.\n\n518\n00:28:20,100 --> 00:28:21,530\nFor error checking,\nsome people might\n\n519\n00:28:21,530 --> 00:28:23,110\nprefer something else.\n\n520\n00:28:23,110 --> 00:28:25,570\nBut the interesting things\nare the following ones.\n\n521\n00:28:25,570 --> 00:28:27,450\nIf I've got an else clause--\n\n522\n00:28:27,450 --> 00:28:31,420\n\n\n523\n00:28:31,420 --> 00:28:34,120\nYou see, if I have a list of\nclauses, then each clause is a\n\n524\n00:28:34,120 --> 00:28:37,480\nlist. And so the predicate\npart is\n\n525\n00:28:37,480 --> 00:28:40,265\nthe CAAR of the clauses.\n\n526\n00:28:40,265 --> 00:28:43,560\n\n\n527\n00:28:43,560 --> 00:28:48,070\nIt's the CAR, which is the first\npart of the first clause\n\n528\n00:28:48,070 --> 00:28:51,090\nin the list of clauses.\n\n529\n00:28:51,090 --> 00:28:55,900\nIf it's an else, then it means\nI want my result of the\n\n530\n00:28:55,900 --> 00:28:58,400\nconditional to be the result\nof evaluating the matching\n\n531\n00:28:58,400 --> 00:28:59,800\nexpression.\n\n532\n00:28:59,800 --> 00:29:10,610\nSo I eval the CADR. So this is\nthe first clause, the second\n\n533\n00:29:10,610 --> 00:29:12,830\nelement of it, CADAR--\n\n534\n00:29:12,830 --> 00:29:16,360\nCADAR of a CAR--\n\n535\n00:29:16,360 --> 00:29:22,195\nof the clauses, with respect\nto the environment.\n\n536\n00:29:22,195 --> 00:29:26,620\n\n\n537\n00:29:26,620 --> 00:29:29,630\nNow the next possibility\nis more interesting.\n\n538\n00:29:29,630 --> 00:29:34,860\nIf it's false, if the first\npredicate in the predicate\n\n539\n00:29:34,860 --> 00:29:38,840\nlist is not an else, and it's\nnot false, if it's not the\n\n540\n00:29:38,840 --> 00:29:42,050\nword else, and if it's\nnot a false thing--\n\n541\n00:29:42,050 --> 00:29:44,360\nLet's write down what it is\nif it's a false thing.\n\n542\n00:29:44,360 --> 00:29:49,590\nIf the result of evaluating\nthe first\n\n543\n00:29:49,590 --> 00:29:52,900\npredicate, the clauses--\n\n544\n00:29:52,900 --> 00:29:55,490\n\n\n545\n00:29:55,490 --> 00:30:01,630\nrespect the environment, if that\nevaluation yields false,\n\n546\n00:30:01,630 --> 00:30:04,180\nthen it means, I want to look\nat the next clause.\n\n547\n00:30:04,180 --> 00:30:05,990\nSo I want to discard\nthe first one.\n\n548\n00:30:05,990 --> 00:30:15,450\nSo we just go around loop,\nevcond, the CDR of the clauses\n\n549\n00:30:15,450 --> 00:30:16,700\nrelative to that environment.\n\n550\n00:30:16,700 --> 00:30:21,240\n\n\n551\n00:30:21,240 --> 00:30:27,740\nAnd otherwise, I had a true\nclause, in which case, what I\n\n552\n00:30:27,740 --> 00:30:40,710\nwant is to evaluate the CADAR\nof the clauses relative to\n\n553\n00:30:40,710 --> 00:30:41,960\nthat environment.\n\n554\n00:30:41,960 --> 00:30:48,200\n\n\n555\n00:30:48,200 --> 00:30:51,210\nBoy, it's almost done.\n\n556\n00:30:51,210 --> 00:30:53,730\nIt's quite close to done.\n\n557\n00:30:53,730 --> 00:30:56,210\nI think we're going to\nfinish this part off.\n\n558\n00:30:56,210 --> 00:30:59,530\nSo just buzzing through this\nevaluator, but so far you're\n\n559\n00:30:59,530 --> 00:31:01,220\nseeing almost everything.\n\n560\n00:31:01,220 --> 00:31:04,040\nLet's look at the next\ntransparency here.\n\n561\n00:31:04,040 --> 00:31:08,980\n\n\n562\n00:31:08,980 --> 00:31:11,980\nHere is bind.\n\n563\n00:31:11,980 --> 00:31:15,460\nBind is for making more table.\n\n564\n00:31:15,460 --> 00:31:19,260\nAnd what we are going to\ndo here is make a--\n\n565\n00:31:19,260 --> 00:31:22,800\nwe're going to make a no-frame\nfor an environment structure.\n\n566\n00:31:22,800 --> 00:31:26,230\nThe environment structure is\ngoing to be represented as a\n\n567\n00:31:26,230 --> 00:31:28,080\nlist of frames.\n\n568\n00:31:28,080 --> 00:31:30,520\nSo given an existing environment\nstructure, I'm\n\n569\n00:31:30,520 --> 00:31:32,500\ngoing to make a new environment\nstructure by\n\n570\n00:31:32,500 --> 00:31:35,270\nconsing a new frame onto the\nexisting environment\n\n571\n00:31:35,270 --> 00:31:38,700\nstructure, where the new frame\nconsists of the result of\n\n572\n00:31:38,700 --> 00:31:41,940\npairing up the variables, which\nare the bound variables\n\n573\n00:31:41,940 --> 00:31:45,610\nof the procedure I'm applying,\nto the values which are the\n\n574\n00:31:45,610 --> 00:31:49,690\narguments that were passed\nthat procedure.\n\n575\n00:31:49,690 --> 00:31:53,260\nThis is just making a list,\nadding a new element to our\n\n576\n00:31:53,260 --> 00:31:56,070\nlist of frames, which is an\nenvironment structure, to make\n\n577\n00:31:56,070 --> 00:31:58,391\na new environment.\n\n578\n00:31:58,391 --> 00:32:01,540\nWhere pair-up is very simple.\n\n579\n00:32:01,540 --> 00:32:04,610\nPair-up is nothing more than if\nI have a list of variables\n\n580\n00:32:04,610 --> 00:32:07,830\nand a list of values, well, if\nI run out of variables and if\n\n581\n00:32:07,830 --> 00:32:09,720\nI run out of values,\neverything's OK.\n\n582\n00:32:09,720 --> 00:32:12,990\nOtherwise, I've given\ntoo many arguments.\n\n583\n00:32:12,990 --> 00:32:15,390\nIf I've not run out of\nvariables, but I've run out of\n\n584\n00:32:15,390 --> 00:32:18,560\nvalues, that I have\ntoo few arguments.\n\n585\n00:32:18,560 --> 00:32:20,695\nAnd in the general case, where\nI don't have any errors, and\n\n586\n00:32:20,695 --> 00:32:26,860\nI'm not done, then I really am\njust adding a new pair of the\n\n587\n00:32:26,860 --> 00:32:32,810\nfirst variable with the first\nargument, the first value,\n\n588\n00:32:32,810 --> 00:32:37,780\nonto a list resulting from\npairing-up the rest of the\n\n589\n00:32:37,780 --> 00:32:42,950\nvariables with the rest\nof the values.\n\n590\n00:32:42,950 --> 00:32:46,620\nLookup is of course\nequally simple.\n\n591\n00:32:46,620 --> 00:32:50,230\nIf I have to look up a symbol\nin an environment, well, if\n\n592\n00:32:50,230 --> 00:32:54,650\nthe environment is empty, then\nI've got an unbound variable.\n\n593\n00:32:54,650 --> 00:32:59,770\nOtherwise, what I'm going to do\nis use a special pair list\n\n594\n00:32:59,770 --> 00:33:02,540\nlookup procedure, which we'll\nhave very shortly, of the\n\n595\n00:33:02,540 --> 00:33:05,930\nsymbol in the first frame\nof the environment.\n\n596\n00:33:05,930 --> 00:33:07,670\nSince I know the environment is\nnot empty, it must have a\n\n597\n00:33:07,670 --> 00:33:09,200\nfirst frame.\n\n598\n00:33:09,200 --> 00:33:11,140\nSo I lookup the symbol\nin the first frame.\n\n599\n00:33:11,140 --> 00:33:15,150\nThat becomes the value\ncell here.\n\n600\n00:33:15,150 --> 00:33:19,860\nAnd then, if the value cell is\nempty, if there is no such\n\n601\n00:33:19,860 --> 00:33:22,150\nvalue cell, then I have to\ncontinue and look at the rest\n\n602\n00:33:22,150 --> 00:33:23,720\nof the frames.\n\n603\n00:33:23,720 --> 00:33:25,990\nIt means there was nothing\nfound there.\n\n604\n00:33:25,990 --> 00:33:29,740\nSo that's a property of ASSQ is\nit returns emptiness if it\n\n605\n00:33:29,740 --> 00:33:32,010\ndoesn't find something.\n\n606\n00:33:32,010 --> 00:33:35,175\nbut if it did find something,\nthen I'm going to use the CDR\n\n607\n00:33:35,175 --> 00:33:38,080\nof the value cell here, which is\nthe thing that was the pair\n\n608\n00:33:38,080 --> 00:33:41,050\nconsisting of the variable\nand the value.\n\n609\n00:33:41,050 --> 00:33:45,000\nSo the CDR of it is\nthe value part.\n\n610\n00:33:45,000 --> 00:33:47,970\nFinally, ASSQ is something\nyou've probably seen already.\n\n611\n00:33:47,970 --> 00:33:52,400\nASSQ takes a symbol and a list\nof pairs, and if the list is\n\n612\n00:33:52,400 --> 00:33:53,760\nempty, it's empty.\n\n613\n00:33:53,760 --> 00:33:57,850\nIf the symbol is the first\nthing in the list--\n\n614\n00:33:57,850 --> 00:33:59,820\nThat's an error.\n\n615\n00:33:59,820 --> 00:34:04,160\nThat should be CAAR, C-A-A-R.\nEverybody note that.\n\n616\n00:34:04,160 --> 00:34:07,730\n\n\n617\n00:34:07,730 --> 00:34:08,980\nRight there, OK?\n\n618\n00:34:08,980 --> 00:34:13,121\n\n\n619\n00:34:13,121 --> 00:34:17,150\nAnd in any case, if the symbol\nis the CAAR of the A list,\n\n620\n00:34:17,150 --> 00:34:22,340\nthen I want the first, the first\npair, in the A list. So,\n\n621\n00:34:22,340 --> 00:34:26,300\nin other words, if this is the\nkey matching the right entry,\n\n622\n00:34:26,300 --> 00:34:30,429\notherwise, I want to look up\nthat symbol in the rest. Sorry\n\n623\n00:34:30,429 --> 00:34:35,190\nfor producing a bug,\nbugs appear.\n\n624\n00:34:35,190 --> 00:34:38,389\nWell, in any case, you're\npretty much seeing\n\n625\n00:34:38,389 --> 00:34:39,639\nthe whole thing now.\n\n626\n00:34:39,639 --> 00:34:41,880\n\n\n627\n00:34:41,880 --> 00:34:45,150\nIt's a very beautiful thing,\neven though it's written in an\n\n628\n00:34:45,150 --> 00:34:49,600\nugly style, being the kernel\nof every language.\n\n629\n00:34:49,600 --> 00:34:50,210\nI suggest that we just--\n\n630\n00:34:50,210 --> 00:34:51,460\nlet's look at it for a while.\n\n631\n00:34:51,460 --> 00:34:56,749\n\n\n632\n00:34:56,749 --> 00:35:49,750\n[MUSIC PLAYING]\n\n633\n00:35:49,750 --> 00:35:51,000\nAre there any questions?\n\n634\n00:35:51,000 --> 00:36:01,180\n\n\n635\n00:36:01,180 --> 00:36:04,044\nAlright, I suppose it's time\nto take a small break then.\n\n636\n00:36:04,044 --> 00:36:56,780\n[MUSIC PLAYING]\n\n637\n00:36:56,780 --> 00:36:59,390\nOK, now we're just going to do\na little bit of practice\n\n638\n00:36:59,390 --> 00:37:03,470\nunderstanding what it is\nwe've just shown you.\n\n639\n00:37:03,470 --> 00:37:05,700\nWhat we're going to do is go\nthrough, in detail, an\n\n640\n00:37:05,700 --> 00:37:09,720\nevaluation by informally\nsubstituting through the\n\n641\n00:37:09,720 --> 00:37:11,500\ninterpreter.\n\n642\n00:37:11,500 --> 00:37:14,160\nAnd since we have no assignments\nor definitions in\n\n643\n00:37:14,160 --> 00:37:18,470\nthis interpreter, we have no\npossible side effects, and so\n\n644\n00:37:18,470 --> 00:37:23,200\nthe we can do substitution with\nimpunity and not worry\n\n645\n00:37:23,200 --> 00:37:25,330\nabout results.\n\n646\n00:37:25,330 --> 00:37:28,800\nSo the particular problem I'd\nlike to look at is it an\n\n647\n00:37:28,800 --> 00:37:30,690\ninteresting one.\n\n648\n00:37:30,690 --> 00:37:41,910\nIt's the evaluation of quote,\nopen, open, open, lambda of x,\n\n649\n00:37:41,910 --> 00:37:55,100\nlambda of y plus x y, lambda,\nlambda, applied to three,\n\n650\n00:37:55,100 --> 00:37:58,640\napplied to four, in some\nglobal environment\n\n651\n00:37:58,640 --> 00:37:59,890\nwhich I'll call e0.\n\n652\n00:37:59,890 --> 00:38:04,930\n\n\n653\n00:38:04,930 --> 00:38:07,900\nSo what we have here is a\nprocedure of one argument x,\n\n654\n00:38:07,900 --> 00:38:10,980\nwhich produces as its value a\nprocedure of one argument y,\n\n655\n00:38:10,980 --> 00:38:14,300\nwhich adds x to y.\n\n656\n00:38:14,300 --> 00:38:17,960\nWe are applying the procedure\nof one argument x to three.\n\n657\n00:38:17,960 --> 00:38:21,400\nSo x should become three.\n\n658\n00:38:21,400 --> 00:38:23,590\nAnd the result of that should\nbe procedure of one argument\n\n659\n00:38:23,590 --> 00:38:26,167\ny, which will then apply to 4.\n\n660\n00:38:26,167 --> 00:38:28,910\n\n\n661\n00:38:28,910 --> 00:38:31,480\nAnd there is a very simple\ncase, they will\n\n662\n00:38:31,480 --> 00:38:34,790\nthen add those results.\n\n663\n00:38:34,790 --> 00:38:36,860\nAnd now in order to do that, I\nwant to make a very simple\n\n664\n00:38:36,860 --> 00:38:37,660\nenvironment model.\n\n665\n00:38:37,660 --> 00:38:41,200\nAnd at this point, you should\nalready have in your mind the\n\n666\n00:38:41,200 --> 00:38:44,460\nenvironments that\nthis produces.\n\n667\n00:38:44,460 --> 00:38:48,810\nBut we're going to start out\nwith a global environment,\n\n668\n00:38:48,810 --> 00:38:56,740\nwhich I'll call e0,\nwhich is that.\n\n669\n00:38:56,740 --> 00:39:00,550\nAnd it's going to have in it\nthings, definitions for plus,\n\n670\n00:39:00,550 --> 00:39:07,390\nand times, and--\n\n671\n00:39:07,390 --> 00:39:08,560\nusing Greek letters, isn't that\n\n672\n00:39:08,560 --> 00:39:11,290\ninteresting, for the objects--\n\n673\n00:39:11,290 --> 00:39:27,330\nand minus, and quotient, and\nCAR, and CDR, and CONS, and\n\n674\n00:39:27,330 --> 00:39:30,480\nEQ, and everything else you\nmight imagine in a global\n\n675\n00:39:30,480 --> 00:39:31,270\nenvironment.\n\n676\n00:39:31,270 --> 00:39:34,590\nIt's got something there for\neach of those things,\n\n677\n00:39:34,590 --> 00:39:39,220\nsomething the machine is\nborn with, that's e0.\n\n678\n00:39:39,220 --> 00:39:42,940\nNow what does it mean to\ndo this evaluation?\n\n679\n00:39:42,940 --> 00:39:46,120\nWell, we go through the set of\nspecial forms. First of all,\n\n680\n00:39:46,120 --> 00:39:48,670\nthis is not a number.\n\n681\n00:39:48,670 --> 00:39:50,380\nThis is not a symbol.\n\n682\n00:39:50,380 --> 00:39:53,210\n\n\n683\n00:39:53,210 --> 00:39:56,520\nGee, it's not a quoted\nexpression.\n\n684\n00:39:56,520 --> 00:40:00,080\nThis is a quoted expression,\nbut that's not what I\n\n685\n00:40:00,080 --> 00:40:00,600\ninterested in.\n\n686\n00:40:00,600 --> 00:40:02,700\nThe question is, whether or not\nthe thing which is quoted\n\n687\n00:40:02,700 --> 00:40:05,890\nis quoted expression?\n\n688\n00:40:05,890 --> 00:40:07,960\nI'm evaluating an expression.\n\n689\n00:40:07,960 --> 00:40:11,410\nThis just says it's this\nparticular expression.\n\n690\n00:40:11,410 --> 00:40:12,660\nThis is not a quoted\nexpression.\n\n691\n00:40:12,660 --> 00:40:15,230\n\n\n692\n00:40:15,230 --> 00:40:19,120\nIt's not a thing that\nbegins with lambda.\n\n693\n00:40:19,120 --> 00:40:22,030\nIt's not a thing that\nbegins with COND.\n\n694\n00:40:22,030 --> 00:40:24,630\nTherefore, it's an application\nof its\n\n695\n00:40:24,630 --> 00:40:26,310\nof an operated operands.\n\n696\n00:40:26,310 --> 00:40:28,570\nIt's a combination.\n\n697\n00:40:28,570 --> 00:40:35,230\nThe combination thus has this\nas the operator and this is\n\n698\n00:40:35,230 --> 00:40:36,480\nthe operands.\n\n699\n00:40:36,480 --> 00:40:40,130\n\n\n700\n00:40:40,130 --> 00:40:43,540\nWell, that means that what I'm\ngoing to do is transform this\n\n701\n00:40:43,540 --> 00:40:54,010\ninto apply of eval, of quote,\nopen, open lambda of\n\n702\n00:40:54,010 --> 00:40:58,180\nx, lambda of y--\n\n703\n00:40:58,180 --> 00:40:59,980\nI'm evaluating the operator--\n\n704\n00:40:59,980 --> 00:41:13,610\nplus x y, in the environment,\nalso e0, with the operands\n\n705\n00:41:13,610 --> 00:41:16,330\nthat I'm going to apply this\nto, the arguments being the\n\n706\n00:41:16,330 --> 00:41:24,450\nresult of EVLIST, the list\ncontaining four, fin e0.\n\n707\n00:41:24,450 --> 00:41:29,010\n\n\n708\n00:41:29,010 --> 00:41:33,010\nI'm using this funny notation\nhere for e0 because this\n\n709\n00:41:33,010 --> 00:41:36,840\nshould be that environment.\n\n710\n00:41:36,840 --> 00:41:38,640\nI haven't a name for it, because\nI have no environment\n\n711\n00:41:38,640 --> 00:41:39,890\nto name it in.\n\n712\n00:41:39,890 --> 00:41:41,960\n\n\n713\n00:41:41,960 --> 00:41:44,630\nSo this is just a representation\nof what would\n\n714\n00:41:44,630 --> 00:41:47,730\nbe a quoted expression,\nif you will.\n\n715\n00:41:47,730 --> 00:41:53,040\nThe data structure, which is the\nenvironment, goes there.\n\n716\n00:41:53,040 --> 00:41:55,850\nWell, that's what we're\nseeing here.\n\n717\n00:41:55,850 --> 00:41:57,370\nWell in order to do this,\nI have to do this, and\n\n718\n00:41:57,370 --> 00:41:59,610\nI have to do that.\n\n719\n00:41:59,610 --> 00:42:03,770\nWell this one's easy, so why\ndon't we do that one first.\n\n720\n00:42:03,770 --> 00:42:07,780\nThis turns into apply\nof eval-- just\n\n721\n00:42:07,780 --> 00:42:09,520\ncopying something now.\n\n722\n00:42:09,520 --> 00:42:11,000\nMost of the substitution\nrule is copying.\n\n723\n00:42:11,000 --> 00:42:18,530\n\n\n724\n00:42:18,530 --> 00:42:22,100\nSo I'm going to not say the\nwords when I copy, because\n\n725\n00:42:22,100 --> 00:42:23,350\nit's faster.\n\n726\n00:42:23,350 --> 00:42:26,100\n\n\n727\n00:42:26,100 --> 00:42:34,130\nAnd then the EVLIST is going to\nturn into a cons, of eval,\n\n728\n00:42:34,130 --> 00:42:36,160\nof four, in e0--\n\n729\n00:42:36,160 --> 00:42:38,780\n\n\n730\n00:42:38,780 --> 00:42:42,260\nbecause it was not\nan empty list--\n\n731\n00:42:42,260 --> 00:42:48,910\nonto the result of EVLISTing,\non the empty list, in e0.\n\n732\n00:42:48,910 --> 00:42:52,580\n\n\n733\n00:42:52,580 --> 00:42:54,550\nAnd I'm going to start leaving\nout steps soon, because it's\n\n734\n00:42:54,550 --> 00:42:55,800\ngoing to get boring.\n\n735\n00:42:55,800 --> 00:42:59,870\n\n\n736\n00:42:59,870 --> 00:43:05,025\nBut this is basically the same\nthing as apply, of eval--\n\n737\n00:43:05,025 --> 00:43:07,640\n\n\n738\n00:43:07,640 --> 00:43:10,230\nI'm going to keep doing this--\n\n739\n00:43:10,230 --> 00:43:20,240\nthe lambda of x, the lambda of\ny, plus xy, 3, close, e0.\n\n740\n00:43:20,240 --> 00:43:21,490\nI'm a pretty good machine.\n\n741\n00:43:21,490 --> 00:43:24,690\n\n\n742\n00:43:24,690 --> 00:43:27,410\nWell, eval of four,\nthat's meets the\n\n743\n00:43:27,410 --> 00:43:28,790\nquestion, is it a number.\n\n744\n00:43:28,790 --> 00:43:35,280\nSo that's cons, cons of 4.\n\n745\n00:43:35,280 --> 00:43:37,110\nAnd EVLIST of the empty\nlist is the empty\n\n746\n00:43:37,110 --> 00:43:39,240\nlist, so that's this.\n\n747\n00:43:39,240 --> 00:43:43,270\n\n\n748\n00:43:43,270 --> 00:43:46,170\nAnd that's very simple to\nunderstand, because that means\n\n749\n00:43:46,170 --> 00:43:48,710\nthe list containing\nfour itself.\n\n750\n00:43:48,710 --> 00:43:56,340\nSo this is nothing more than\napply of eval, quote, open,\n\n751\n00:43:56,340 --> 00:44:06,590\nopen, lambda of x, lambda of y,\nplus x y, three applied to,\n\n752\n00:44:06,590 --> 00:44:11,678\ne0, applied to the list four--\n\n753\n00:44:11,678 --> 00:44:13,940\nbang.\n\n754\n00:44:13,940 --> 00:44:15,190\nSo that's that step.\n\n755\n00:44:15,190 --> 00:44:18,100\n\n\n756\n00:44:18,100 --> 00:44:20,360\nNow let's look at the next,\nmore interesting thing.\n\n757\n00:44:20,360 --> 00:44:23,070\nWhat do I do to evaluate that?\n\n758\n00:44:23,070 --> 00:44:27,780\nEvaluating this means\nI have to evaluate--\n\n759\n00:44:27,780 --> 00:44:29,460\nWell, it's not.\n\n760\n00:44:29,460 --> 00:44:31,680\nIt's nothing but\nan application.\n\n761\n00:44:31,680 --> 00:44:33,570\nIt's not one of the\nspecial things.\n\n762\n00:44:33,570 --> 00:44:37,660\nIf the application of this\noperator, which we see here--\n\n763\n00:44:37,660 --> 00:44:40,270\nhere's the operator--\n\n764\n00:44:40,270 --> 00:44:46,570\napplied to this operands,\nthat combination.\n\n765\n00:44:46,570 --> 00:44:51,390\nBut we know how to do that,\nbecause that's the last case\n\n766\n00:44:51,390 --> 00:44:52,370\nof the conditional.\n\n767\n00:44:52,370 --> 00:44:56,480\nSo substituting in for this\nevaluation, it's apply of eval\n\n768\n00:44:56,480 --> 00:45:01,160\nof the operator in the EVLIST\nof the operands.\n\n769\n00:45:01,160 --> 00:45:12,100\nWell, it's apply, of apply, of\neval, of quote, open, lambda\n\n770\n00:45:12,100 --> 00:45:23,780\nof x, lambda of y, plus\nx y, lambda, lambda,\n\n771\n00:45:23,780 --> 00:45:25,350\nin environment e0.\n\n772\n00:45:25,350 --> 00:45:30,520\n\n\n773\n00:45:30,520 --> 00:45:32,730\nI'm going to short circuit the\nevaluation of the operands ,\n\n774\n00:45:32,730 --> 00:45:35,230\nbecause they're the same\nas they were before.\n\n775\n00:45:35,230 --> 00:45:38,080\nI got a list containing\nthree, apply that, and\n\n776\n00:45:38,080 --> 00:45:39,330\napply that to four.\n\n777\n00:45:39,330 --> 00:45:42,780\n\n\n778\n00:45:42,780 --> 00:45:44,410\nWell let's see.\n\n779\n00:45:44,410 --> 00:45:49,450\nEval of a lambda expression\nproduces a procedure object.\n\n780\n00:45:49,450 --> 00:45:52,030\n\n\n781\n00:45:52,030 --> 00:46:04,530\nSo this is apply, of apply, of\nthe procedure object closure,\n\n782\n00:46:04,530 --> 00:46:09,420\nwhich contains the body of the\nprocedure, x, which is\n\n783\n00:46:09,420 --> 00:46:12,130\nlambda-- which binds\nx [UNINTELLIGIBLE]\n\n784\n00:46:12,130 --> 00:46:17,230\nthe internals of the body, it\nreturns the procedure of one\n\n785\n00:46:17,230 --> 00:46:20,630\nargument y, which adds x to y.\n\n786\n00:46:20,630 --> 00:46:23,210\n\n\n787\n00:46:23,210 --> 00:46:27,930\nEnvironment e0 is now captured\nin it, because this was\n\n788\n00:46:27,930 --> 00:46:30,340\nevaluated with respect to e0.\n\n789\n00:46:30,340 --> 00:46:33,040\ne0 is part now of the\nclosure object.\n\n790\n00:46:33,040 --> 00:46:40,050\nApply that to open, three,\nclose, apply, to open, 4,\n\n791\n00:46:40,050 --> 00:46:41,300\nclose, apply.\n\n792\n00:46:41,300 --> 00:46:47,390\n\n\n793\n00:46:47,390 --> 00:46:50,220\nSo going from this step to this\nstep meant that I made up\n\n794\n00:46:50,220 --> 00:46:55,060\na procedure object which\ncaptured in it e0 as part of\n\n795\n00:46:55,060 --> 00:46:57,150\nthe procedure object.\n\n796\n00:46:57,150 --> 00:46:58,620\nNow, we're going to pass\nthose to apply.\n\n797\n00:46:58,620 --> 00:47:00,480\nWe have to apply this procedure\n\n798\n00:47:00,480 --> 00:47:02,710\nto that set of arguments.\n\n799\n00:47:02,710 --> 00:47:07,380\nWell, but that procedure\nis not primitive.\n\n800\n00:47:07,380 --> 00:47:10,500\nIt's, in fact, a thing which has\ngot the tag closure, and,\n\n801\n00:47:10,500 --> 00:47:13,710\ntherefore, what we have\nto do is do a bind.\n\n802\n00:47:13,710 --> 00:47:15,830\nWe have to bind.\n\n803\n00:47:15,830 --> 00:47:21,850\nA new environment is made at\nthis point, which has as its\n\n804\n00:47:21,850 --> 00:47:26,980\nparent environment the one\nover here, e0, that\n\n805\n00:47:26,980 --> 00:47:28,230\nenvironment.\n\n806\n00:47:28,230 --> 00:47:30,320\n\n\n807\n00:47:30,320 --> 00:47:31,570\nAnd we'll call this one, e1.\n\n808\n00:47:31,570 --> 00:47:34,620\n\n\n809\n00:47:34,620 --> 00:47:36,040\nNow what's bound in there?\n\n810\n00:47:36,040 --> 00:47:38,620\nx is bound to three.\n\n811\n00:47:38,620 --> 00:47:41,480\nSo I have x equal three.\n\n812\n00:47:41,480 --> 00:47:42,730\nThat's what's in there.\n\n813\n00:47:42,730 --> 00:47:44,940\n\n\n814\n00:47:44,940 --> 00:47:46,240\nAnd we'll call that e1.\n\n815\n00:47:46,240 --> 00:47:51,940\nSo what this transforms into\nis an eval of the body of\n\n816\n00:47:51,940 --> 00:47:56,740\nthis, which is this, the body\nof that procedure, in the\n\n817\n00:47:56,740 --> 00:48:00,290\nenvironment that you just saw.\n\n818\n00:48:00,290 --> 00:48:11,480\nSo that's an apply, of eval,\nquote, open, lambda of y, plus\n\n819\n00:48:11,480 --> 00:48:12,750\nx y-- the body--\n\n820\n00:48:12,750 --> 00:48:15,270\n\n\n821\n00:48:15,270 --> 00:48:16,520\nin e1.\n\n822\n00:48:16,520 --> 00:48:20,660\n\n\n823\n00:48:20,660 --> 00:48:26,040\nAnd apply the result of that\nto four, open, close, 4--\n\n824\n00:48:26,040 --> 00:48:28,680\nlist of arguments.\n\n825\n00:48:28,680 --> 00:48:31,600\nWell, that's sensible enough\nbecause evaluating a lambda, I\n\n826\n00:48:31,600 --> 00:48:33,110\nknow what to do.\n\n827\n00:48:33,110 --> 00:48:43,680\nThat means I apply, the\nprocedure which is closure,\n\n828\n00:48:43,680 --> 00:48:52,150\nbinds one argument y, adds x to\ny, with e1 captured in it.\n\n829\n00:48:52,150 --> 00:48:55,790\n\n\n830\n00:48:55,790 --> 00:48:57,800\nAnd you should really\nsee this.\n\n831\n00:48:57,800 --> 00:49:00,140\nI somehow manufactured\na closure.\n\n832\n00:49:00,140 --> 00:49:01,790\nI should've put this here.\n\n833\n00:49:01,790 --> 00:49:03,040\nThere was one over here too.\n\n834\n00:49:03,040 --> 00:49:06,230\n\n\n835\n00:49:06,230 --> 00:49:08,080\nWell, there's one here now.\n\n836\n00:49:08,080 --> 00:49:13,710\nI've captured e1, and this is\nthe procedure of one argument\n\n837\n00:49:13,710 --> 00:49:17,880\ny, whatever this is.\n\n838\n00:49:17,880 --> 00:49:20,435\nThat's what that is there,\nthat closure.\n\n839\n00:49:20,435 --> 00:49:23,040\n\n\n840\n00:49:23,040 --> 00:49:26,230\nI'm going to apply\nthat to four.\n\n841\n00:49:26,230 --> 00:49:30,690\n\n\n842\n00:49:30,690 --> 00:49:31,940\nWell, that's easy enough.\n\n843\n00:49:31,940 --> 00:49:36,830\n\n\n844\n00:49:36,830 --> 00:49:39,720\nThat means I have to make a\nnew environment by copying\n\n845\n00:49:39,720 --> 00:49:45,030\nthis pointer, which was the\npointer of the procedure,\n\n846\n00:49:45,030 --> 00:49:49,540\nwhich binds y equal 4 with\nthat environment.\n\n847\n00:49:49,540 --> 00:49:52,460\nAnd here's my new environment,\nwhich I'll call e2.\n\n848\n00:49:52,460 --> 00:49:55,870\n\n\n849\n00:49:55,870 --> 00:49:58,990\nAnd, of course, this application\nthen is evaluate\n\n850\n00:49:58,990 --> 00:50:01,910\nthe body in e2.\n\n851\n00:50:01,910 --> 00:50:10,830\nSo this is eval, the body,\nwhich is plus x y, in the\n\n852\n00:50:10,830 --> 00:50:13,710\nenvironment e2.\n\n853\n00:50:13,710 --> 00:50:22,220\nBut this is an application, so\nthis is the apply, of eval,\n\n854\n00:50:22,220 --> 00:50:37,340\nplus in e2, an EVLIST, quote,\nopen, x y, in e2.\n\n855\n00:50:37,340 --> 00:50:44,880\n\n\n856\n00:50:44,880 --> 00:50:45,590\nWell, but let's see.\n\n857\n00:50:45,590 --> 00:50:52,480\nThat is apply, the\nobject which is a\n\n858\n00:50:52,480 --> 00:50:54,190\nresult of that and plus.\n\n859\n00:50:54,190 --> 00:50:57,920\nSo here we are in e2, plus is\nnot here, it's not here, oh,\n\n860\n00:50:57,920 --> 00:51:01,780\nyes, but's here as some\nprimitive operator.\n\n861\n00:51:01,780 --> 00:51:04,745\nSo it's the primitive operator\nfor addition.\n\n862\n00:51:04,745 --> 00:51:08,490\n\n\n863\n00:51:08,490 --> 00:51:14,370\nApply that to the result of\nevaluating x and y in e2.\n\n864\n00:51:14,370 --> 00:51:18,340\nBut we can see that x is\nthree and y is four.\n\n865\n00:51:18,340 --> 00:51:23,936\nSo that's a three\nand four, here.\n\n866\n00:51:23,936 --> 00:51:26,280\nAnd that magically produces\nfor me a seven.\n\n867\n00:51:26,280 --> 00:51:30,520\n\n\n868\n00:51:30,520 --> 00:51:33,460\nI wanted to go through this so\nyou would see, essentially,\n\n869\n00:51:33,460 --> 00:51:36,960\none important ingredient, which\nis what's being passed\n\n870\n00:51:36,960 --> 00:51:40,470\naround, and who owns what,\nand what his job is.\n\n871\n00:51:40,470 --> 00:51:41,700\nSo what do we have here?\n\n872\n00:51:41,700 --> 00:51:46,520\nWe have eval, and we have apply,\nthe two main players.\n\n873\n00:51:46,520 --> 00:51:49,370\n\n\n874\n00:51:49,370 --> 00:51:52,320\nAnd there is a big loop the\ngoes around like this.\n\n875\n00:51:52,320 --> 00:52:00,780\nWhich is eval produces\na procedure and\n\n876\n00:52:00,780 --> 00:52:06,270\narguments for apply.\n\n877\n00:52:06,270 --> 00:52:09,710\nNow some things eval\ncould do by itself.\n\n878\n00:52:09,710 --> 00:52:10,860\nThose are little self\nthings here.\n\n879\n00:52:10,860 --> 00:52:12,700\nThey're not interesting.\n\n880\n00:52:12,700 --> 00:52:16,240\nAlso eval evaluates all of the\narguments, one after another.\n\n881\n00:52:16,240 --> 00:52:17,650\nThat's not very interesting.\n\n882\n00:52:17,650 --> 00:52:21,540\nApply can apply some procedures\nlike plus, not very\n\n883\n00:52:21,540 --> 00:52:22,300\ninteresting.\n\n884\n00:52:22,300 --> 00:52:25,520\nHowever, if apply can't apply\na procedure like plus, it\n\n885\n00:52:25,520 --> 00:52:32,880\nproduces an expression and\nenvironment for eval.\n\n886\n00:52:32,880 --> 00:52:35,470\n\n\n887\n00:52:35,470 --> 00:52:39,770\nThe procedural arguments wrap up\nessentially the state of a\n\n888\n00:52:39,770 --> 00:52:43,740\ncomputation and, certainly, the\nexpression of environment.\n\n889\n00:52:43,740 --> 00:52:45,600\nAnd so what we're actually going\nto do next is not the\n\n890\n00:52:45,600 --> 00:52:47,570\ncomplete state, because\nit doesn't say\n\n891\n00:52:47,570 --> 00:52:48,820\nwho wants the answers.\n\n892\n00:52:48,820 --> 00:52:51,280\n\n\n893\n00:52:51,280 --> 00:52:53,500\nBut what we're going to do--\nit's always got something like\n\n894\n00:52:53,500 --> 00:52:56,580\nan expression of environment or\nprocedure and arguments as\n\n895\n00:52:56,580 --> 00:52:58,970\nthe main loop that we're\ngoing around.\n\n896\n00:52:58,970 --> 00:53:01,500\nThere are minor little sub\nloops like eval through\n\n897\n00:53:01,500 --> 00:53:11,030\nEVLIST, or eval through evcond,\nor apply through a\n\n898\n00:53:11,030 --> 00:53:12,280\nprimitive apply.\n\n899\n00:53:12,280 --> 00:53:16,140\n\n\n900\n00:53:16,140 --> 00:53:18,500\nBut they're not the\nessential things.\n\n901\n00:53:18,500 --> 00:53:21,860\nSo that's what I wanted\nyou to see.\n\n902\n00:53:21,860 --> 00:53:23,110\nAre there any questions?\n\n903\n00:53:23,110 --> 00:53:25,930\n\n\n904\n00:53:25,930 --> 00:53:28,690\nYes.\n\n905\n00:53:28,690 --> 00:53:32,670\nAUDIENCE: I'm trying to\nunderstand how x got down to\n\n906\n00:53:32,670 --> 00:53:37,070\nthree instead of four.\n\n907\n00:53:37,070 --> 00:53:38,540\nAt the early part of the--\n\n908\n00:53:38,540 --> 00:53:41,310\nPROFESSOR: Here.\n\n909\n00:53:41,310 --> 00:53:43,310\nYou want to know how x\ngot down to three?\n\n910\n00:53:43,310 --> 00:53:49,770\nAUDIENCE: Because x is the outer\nprocedure, and x and y\n\n911\n00:53:49,770 --> 00:53:51,040\nare the inner procedure.\n\n912\n00:53:51,040 --> 00:53:52,570\nPROFESSOR: Fine.\n\n913\n00:53:52,570 --> 00:53:55,280\nWell, I was very careful\nand mechanical.\n\n914\n00:53:55,280 --> 00:53:57,350\nFirst of all, I should write\nthose procedures again for\n\n915\n00:53:57,350 --> 00:54:00,610\nyou, pretty printed.\n\n916\n00:54:00,610 --> 00:54:02,260\nFirst order of business, because\nyou're probably not\n\n917\n00:54:02,260 --> 00:54:03,830\nreading them well.\n\n918\n00:54:03,830 --> 00:54:08,500\nSo I have here that\nprocedure of--\n\n919\n00:54:08,500 --> 00:54:11,280\nwas it x over there--\n\n920\n00:54:11,280 --> 00:54:12,690\nwhich is--\n\n921\n00:54:12,690 --> 00:54:20,710\nvalue of that procedure of y,\nwhich adds x to y, lambda,\n\n922\n00:54:20,710 --> 00:54:25,380\nlambda, applied that to three,\ntakes the result of that, and\n\n923\n00:54:25,380 --> 00:54:26,140\napplied that to four.\n\n924\n00:54:26,140 --> 00:54:28,810\nIs that not what I wrote?\n\n925\n00:54:28,810 --> 00:54:34,170\nNow, you should immediately\nsee that here is an\n\n926\n00:54:34,170 --> 00:54:35,150\napplication--\n\n927\n00:54:35,150 --> 00:54:37,400\nlet me get a white\npiece of chalk--\n\n928\n00:54:37,400 --> 00:54:40,735\nhere is an application,\na combination.\n\n929\n00:54:40,735 --> 00:54:44,300\n\n\n930\n00:54:44,300 --> 00:54:48,270\nThat combination has this\nas the operator\n\n931\n00:54:48,270 --> 00:54:51,040\nand this as the operand.\n\n932\n00:54:51,040 --> 00:54:54,900\nThe three is going in\nfor the x here.\n\n933\n00:54:54,900 --> 00:54:58,720\nThe result of this is a\nprocedure of one argument y,\n\n934\n00:54:58,720 --> 00:55:01,530\nwhich gets applied to four.\n\n935\n00:55:01,530 --> 00:55:04,190\nSo you just weren't reading\nthe expression right.\n\n936\n00:55:04,190 --> 00:55:11,580\nThe way you see that over here\nis that here I have the actual\n\n937\n00:55:11,580 --> 00:55:13,340\nprocedure object, x.\n\n938\n00:55:13,340 --> 00:55:18,980\nIt's getting applied to three,\nthe list containing three.\n\n939\n00:55:18,980 --> 00:55:20,350\nWhat I'm left over with\nis something which\n\n940\n00:55:20,350 --> 00:55:24,080\ngets applied to four.\n\n941\n00:55:24,080 --> 00:55:25,330\nAre there any other questions?\n\n942\n00:55:25,330 --> 00:55:28,600\n\n\n943\n00:55:28,600 --> 00:55:30,900\nTime for our next small\nbreak then.\n\n944\n00:55:30,900 --> 00:55:33,735\nThank you.\n\n945\n00:55:33,735 --> 00:56:08,410\n[MUSIC PLAYING]\n\n946\n00:56:08,410 --> 00:56:14,730\nLet's see, at this point, you\nshould be getting the feeling,\n\n947\n00:56:14,730 --> 00:56:16,630\nwhat's this nonsense\nthis Sussman\n\n948\n00:56:16,630 --> 00:56:17,960\ncharacter is feeding me?\n\n949\n00:56:17,960 --> 00:56:20,740\n\n\n950\n00:56:20,740 --> 00:56:24,800\nThere's an awful lot of\nstrange nonsense here.\n\n951\n00:56:24,800 --> 00:56:28,300\nAfter all, he purported to\nexplain to me Lisp, and he\n\n952\n00:56:28,300 --> 00:56:30,892\nwrote me a Lisp program\non the blackboard.\n\n953\n00:56:30,892 --> 00:56:33,560\nThe Lisp program was intended\nto be interpreted for Lisp,\n\n954\n00:56:33,560 --> 00:56:35,280\nbut you need a Lisp interpreter\nin order to\n\n955\n00:56:35,280 --> 00:56:38,370\nunderstand that program.\n\n956\n00:56:38,370 --> 00:56:41,160\nHow could that program have told\nme anything there is to\n\n957\n00:56:41,160 --> 00:56:44,150\nbe known about Lisp?\n\n958\n00:56:44,150 --> 00:56:45,795\nHow is that not completely\nvacuous?\n\n959\n00:56:45,795 --> 00:56:48,490\n\n\n960\n00:56:48,490 --> 00:56:50,990\nIt's a very strange thing.\n\n961\n00:56:50,990 --> 00:56:52,430\nDoes it tell me anything\nat all?\n\n962\n00:56:52,430 --> 00:56:56,070\n\n\n963\n00:56:56,070 --> 00:56:59,230\nWell, you see, the whole thing\nis sort of like these Escher's\n\n964\n00:56:59,230 --> 00:57:03,105\nhands that we see\non this slide.\n\n965\n00:57:03,105 --> 00:57:06,180\n\n\n966\n00:57:06,180 --> 00:57:11,750\nYes, eval and apply each sort\nof draw each other and\n\n967\n00:57:11,750 --> 00:57:15,690\nconstruct the real thing,\nwhich can sit\n\n968\n00:57:15,690 --> 00:57:17,110\nout and draw itself.\n\n969\n00:57:17,110 --> 00:57:19,300\nEscher was a very brilliant man,\nhe just didn't know the\n\n970\n00:57:19,300 --> 00:57:20,550\nnames of these spirits.\n\n971\n00:57:20,550 --> 00:57:23,910\n\n\n972\n00:57:23,910 --> 00:57:27,700\nWell, I'm going to do now, is\nI'm going to try to convince\n\n973\n00:57:27,700 --> 00:57:33,060\nyou that both this mean\nsomething, and, as a aside,\n\n974\n00:57:33,060 --> 00:57:36,090\nI'm going to show you why you\ndon't need definitions.\n\n975\n00:57:36,090 --> 00:57:38,760\nJust turns out that that sort of\nfalls out, why definitions\n\n976\n00:57:38,760 --> 00:57:42,990\nare not essential in a\nmathematical sense for doing\n\n977\n00:57:42,990 --> 00:57:44,890\nall the things we need\nto do for computing.\n\n978\n00:57:44,890 --> 00:57:49,070\n\n\n979\n00:57:49,070 --> 00:57:50,690\nWell, let's see here.\n\n980\n00:57:50,690 --> 00:57:54,870\nConsider the following small\nprogram, what does it mean?\n\n981\n00:57:54,870 --> 00:57:57,035\nThis is a program for computing\nexponentials.\n\n982\n00:57:57,035 --> 00:58:07,270\n\n\n983\n00:58:07,270 --> 00:58:13,350\nThe exponential of x to\nthe nth power is if--\n\n984\n00:58:13,350 --> 00:58:16,910\n\n\n985\n00:58:16,910 --> 00:58:22,070\nand is zero, then the\nresult is one.\n\n986\n00:58:22,070 --> 00:58:29,520\nOtherwise, I want the product\nof x and the result of\n\n987\n00:58:29,520 --> 00:58:33,930\nexponentiating x to the\nn minus one power.\n\n988\n00:58:33,930 --> 00:58:42,858\n\n\n989\n00:58:42,858 --> 00:58:46,630\nI think I got it right.\n\n990\n00:58:46,630 --> 00:58:49,470\nNow this is a recursive\ndefinition.\n\n991\n00:58:49,470 --> 00:58:53,930\nIt's a definition of the\nexponentiation procedure in\n\n992\n00:58:53,930 --> 00:58:56,410\nterms of itself.\n\n993\n00:58:56,410 --> 00:59:00,710\nAnd, as it has been mentioned\nbefore, your high school\n\n994\n00:59:00,710 --> 00:59:03,010\ngeometry teacher probably\ngave you a hard time\n\n995\n00:59:03,010 --> 00:59:05,650\nabout things like that.\n\n996\n00:59:05,650 --> 00:59:07,910\nWas that justified?\n\n997\n00:59:07,910 --> 00:59:13,430\nWhy does this self referential\ndefinition make any sense?\n\n998\n00:59:13,430 --> 00:59:15,060\nWell, first of all, I'm going to\nconvince you that your high\n\n999\n00:59:15,060 --> 00:59:17,600\nschool geometry teacher was\nI telling you nonsense.\n\n1000\n00:59:17,600 --> 00:59:20,370\n\n\n1001\n00:59:20,370 --> 00:59:24,490\nConsider the following set\nof definitions here.\n\n1002\n00:59:24,490 --> 00:59:33,070\nx plus y equals three, and\nx minus y equal one.\n\n1003\n00:59:33,070 --> 00:59:36,170\nWell, gee, this tells you x in\nterms of y, and this one tells\n\n1004\n00:59:36,170 --> 00:59:37,490\nyou y in terms of\nx, presumably.\n\n1005\n00:59:37,490 --> 00:59:40,150\n\n\n1006\n00:59:40,150 --> 00:59:42,950\nAnd yet this happens to have a\nunique solution in x and y.\n\n1007\n00:59:42,950 --> 00:59:55,910\n\n\n1008\n00:59:55,910 --> 01:00:06,600\nHowever, I could also write\ntwo x plus two y is six.\n\n1009\n01:00:06,600 --> 01:00:09,610\nThese two equations have an\ninfinite number solutions.\n\n1010\n01:00:09,610 --> 01:00:15,730\n\n\n1011\n01:00:15,730 --> 01:00:21,520\nAnd I could write you, for\nexample, x minus y equal 2,\n\n1012\n01:00:21,520 --> 01:00:24,070\nand these two equations\nhave no solutions.\n\n1013\n01:00:24,070 --> 01:00:29,820\n\n\n1014\n01:00:29,820 --> 01:00:32,350\nWell, I have here three sets\nof simultaneous linear\n\n1015\n01:00:32,350 --> 01:00:39,510\nequations, this set, this\nset, and this set.\n\n1016\n01:00:39,510 --> 01:00:42,900\nBut they have different\nnumbers of solutions.\n\n1017\n01:00:42,900 --> 01:00:45,760\nThe number of solutions is not\nin the form of the equations.\n\n1018\n01:00:45,760 --> 01:00:48,350\nThey all three sets have\nthe same form.\n\n1019\n01:00:48,350 --> 01:00:50,205\nThe number of solutions\nis in the content.\n\n1020\n01:00:50,205 --> 01:00:53,000\n\n\n1021\n01:00:53,000 --> 01:00:55,510\nI can't tell by looking at the\nform of a definition whether\n\n1022\n01:00:55,510 --> 01:00:59,660\nit makes sense, only by\nits detailed content.\n\n1023\n01:00:59,660 --> 01:01:02,170\nWhat are the coefficients,\nfor example, in the\n\n1024\n01:01:02,170 --> 01:01:05,100\ncase of linear equations?\n\n1025\n01:01:05,100 --> 01:01:07,440\nSo I shouldn't expect to be\nable to tell looking at\n\n1026\n01:01:07,440 --> 01:01:11,500\nsomething like this, from some\nsimple things like, oh yes,\n\n1027\n01:01:11,500 --> 01:01:16,030\nEXPT is the solution of this\nrecursion equation.\n\n1028\n01:01:16,030 --> 01:01:22,110\nExpt is the procedure which\nif substituted in here,\n\n1029\n01:01:22,110 --> 01:01:26,040\ngives me EXPT back.\n\n1030\n01:01:26,040 --> 01:01:30,750\nI can't tell, looking at this\nform, whether or not there's a\n\n1031\n01:01:30,750 --> 01:01:33,970\nsingle, unique solution for\nEXPT, an infinite number of\n\n1032\n01:01:33,970 --> 01:01:37,200\nsolutions, or no solutions.\n\n1033\n01:01:37,200 --> 01:01:38,930\nIt's got to be how it\ncounts and things\n\n1034\n01:01:38,930 --> 01:01:40,490\nlike that, the details.\n\n1035\n01:01:40,490 --> 01:01:42,900\nAnd it's harder in programming\nthan linear algebra.\n\n1036\n01:01:42,900 --> 01:01:45,210\nThere aren't too many theorems\nabout it in programming.\n\n1037\n01:01:45,210 --> 01:01:48,450\n\n\n1038\n01:01:48,450 --> 01:01:50,990\nWell, I want to rewrite these\nequations a little\n\n1039\n01:01:50,990 --> 01:01:53,970\nbit, these over here.\n\n1040\n01:01:53,970 --> 01:01:55,560\nBecause what we're\ninvestigating is\n\n1041\n01:01:55,560 --> 01:01:56,770\nequations like this.\n\n1042\n01:01:56,770 --> 01:01:58,820\nBut I want to play a little with\nequations like this that\n\n1043\n01:01:58,820 --> 01:02:02,050\nwe understand, just so we\nget some insight into\n\n1044\n01:02:02,050 --> 01:02:04,730\nthis kind of question.\n\n1045\n01:02:04,730 --> 01:02:07,870\nWe could rewrite our equations\nhere, say these two, the ones\n\n1046\n01:02:07,870 --> 01:02:17,070\nthat are interesting, as x\nequals three minus y, and y\n\n1047\n01:02:17,070 --> 01:02:19,380\nequals x minus one.\n\n1048\n01:02:19,380 --> 01:02:22,010\n\n\n1049\n01:02:22,010 --> 01:02:24,050\nWhat do we call this\ntransformation?\n\n1050\n01:02:24,050 --> 01:02:26,095\nThis is a linear transformation,\nt.\n\n1051\n01:02:26,095 --> 01:02:29,430\n\n\n1052\n01:02:29,430 --> 01:02:35,390\nThen what we're getting here\nis an equation x y\n\n1053\n01:02:35,390 --> 01:02:37,370\nequals t of x y.\n\n1054\n01:02:37,370 --> 01:02:42,990\n\n\n1055\n01:02:42,990 --> 01:02:44,560\nWhat am I looking for?\n\n1056\n01:02:44,560 --> 01:02:47,040\nI'm looking for a fixed\npoint of t.\n\n1057\n01:02:47,040 --> 01:02:59,350\nThe solution is a fixed\npoint of t.\n\n1058\n01:02:59,350 --> 01:03:01,910\n\n\n1059\n01:03:01,910 --> 01:03:04,830\nSo the methods we should have\nfor looking for solutions to\n\n1060\n01:03:04,830 --> 01:03:09,230\nequations, if I can do it by\nfixed points, might be\n\n1061\n01:03:09,230 --> 01:03:10,880\napplicable.\n\n1062\n01:03:10,880 --> 01:03:13,710\nIf I have a means of finding a\nsolution to an equations by\n\n1063\n01:03:13,710 --> 01:03:15,690\nfixed points--\n\n1064\n01:03:15,690 --> 01:03:18,620\njust, might not work--\n\n1065\n01:03:18,620 --> 01:03:21,160\nbut it might be applicable to\ninvestigating solutions of\n\n1066\n01:03:21,160 --> 01:03:22,410\nequations like this.\n\n1067\n01:03:22,410 --> 01:03:27,240\n\n\n1068\n01:03:27,240 --> 01:03:30,260\nBut what I want you to feel is\nthat this is an equation.\n\n1069\n01:03:30,260 --> 01:03:32,930\nIt's an expression with several\ninstances of various\n\n1070\n01:03:32,930 --> 01:03:39,020\nnames which puts a constraint on\nthe name, saying what that\n\n1071\n01:03:39,020 --> 01:03:42,770\nname could have as its value,\nrather than some sort of\n\n1072\n01:03:42,770 --> 01:03:45,010\nmechanical process of\nsubstitution right now.\n\n1073\n01:03:45,010 --> 01:03:47,740\n\n\n1074\n01:03:47,740 --> 01:03:51,220\nThis is an equation which I'm\ngoing to try to solve.\n\n1075\n01:03:51,220 --> 01:03:53,960\nWell, let's play around\nand solve it.\n\n1076\n01:03:53,960 --> 01:03:57,800\nFirst of all, I want to write\ndown the function which\n\n1077\n01:03:57,800 --> 01:04:00,320\ncorresponds to t.\n\n1078\n01:04:00,320 --> 01:04:02,670\nFirst I want to write down the\nfunction which corresponds to\n\n1079\n01:04:02,670 --> 01:04:06,960\nt whose fixed point is the\nanswer to this question.\n\n1080\n01:04:06,960 --> 01:04:11,950\n\n\n1081\n01:04:11,950 --> 01:04:14,240\nWell, let's consider the\nfollowing procedure f.\n\n1082\n01:04:14,240 --> 01:04:16,870\n\n\n1083\n01:04:16,870 --> 01:04:19,340\nI claim it computes\nthat function.\n\n1084\n01:04:19,340 --> 01:04:26,860\nf is that procedure of one\nargument g, which is that\n\n1085\n01:04:26,860 --> 01:04:33,430\nprocedure of two arguments\nx and n.\n\n1086\n01:04:33,430 --> 01:04:42,410\nWhich have the property that if\nn is zero, then the result\n\n1087\n01:04:42,410 --> 01:04:56,050\nis one, otherwise, the result\nis the product of x and g,\n\n1088\n01:04:56,050 --> 01:05:00,690\napplied to x, and minus n1.\n\n1089\n01:05:00,690 --> 01:05:03,370\n\n\n1090\n01:05:03,370 --> 01:05:07,900\ng, times, else, COND,\nlambda, lambda--\n\n1091\n01:05:07,900 --> 01:05:11,900\n\n\n1092\n01:05:11,900 --> 01:05:17,230\nHere f is a procedure, which\nif I had a solution to that\n\n1093\n01:05:17,230 --> 01:05:23,640\nequation, if I had a good\nexponentiation procedure, and\n\n1094\n01:05:23,640 --> 01:05:29,500\nI applied f to that procedure,\nthen the result would be a\n\n1095\n01:05:29,500 --> 01:05:30,930\ngood exponentiation procedure.\n\n1096\n01:05:30,930 --> 01:05:37,460\n\n\n1097\n01:05:37,460 --> 01:05:39,420\nBecause, what does it do?\n\n1098\n01:05:39,420 --> 01:05:44,200\nWell, all it is is exposing g\nwere a good exponentiation\n\n1099\n01:05:44,200 --> 01:05:48,010\nprocedure, well then this would\nproduce, as its value, a\n\n1100\n01:05:48,010 --> 01:05:51,650\nprocedure to arguments x and n,\nsuch that if n were 0, the\n\n1101\n01:05:51,650 --> 01:05:53,360\nresult would be one, which\nis certainly true of\n\n1102\n01:05:53,360 --> 01:05:54,670\nexponentiation.\n\n1103\n01:05:54,670 --> 01:05:57,730\nOtherwise, it will be the result\nof multiplying x by the\n\n1104\n01:05:57,730 --> 01:06:01,750\nexponentiation procedure given\nto me with x and n minus one\n\n1105\n01:06:01,750 --> 01:06:03,470\nas arguments.\n\n1106\n01:06:03,470 --> 01:06:05,680\nSo if this computed the correct\nexponentiation for n\n\n1107\n01:06:05,680 --> 01:06:10,500\nminus one, then this would be\nthe correct exponentiation for\n\n1108\n01:06:10,500 --> 01:06:13,370\nexponent n, so this would\nhave been the right\n\n1109\n01:06:13,370 --> 01:06:14,620\nexponentiation procedure.\n\n1110\n01:06:14,620 --> 01:06:17,500\n\n\n1111\n01:06:17,500 --> 01:06:26,560\nSo what I really want to say\nhere is E-X-P-T is a fixed\n\n1112\n01:06:26,560 --> 01:06:32,320\npoint of f.\n\n1113\n01:06:32,320 --> 01:06:37,550\n\n\n1114\n01:06:37,550 --> 01:06:40,060\nNow our problem is there might\nbe more than one fixed point.\n\n1115\n01:06:40,060 --> 01:06:43,270\nThere might be no\nfixed points.\n\n1116\n01:06:43,270 --> 01:06:44,810\nI have to go hunting for\nthe fixed points.\n\n1117\n01:06:44,810 --> 01:06:48,290\n\n\n1118\n01:06:48,290 --> 01:06:49,540\nGot to solve this equation.\n\n1119\n01:06:49,540 --> 01:06:52,160\n\n\n1120\n01:06:52,160 --> 01:06:55,580\nWell there are various ways\nto hunt for fixed points.\n\n1121\n01:06:55,580 --> 01:06:58,080\nOf course, the one we played\nwith at the beginning of this\n\n1122\n01:06:58,080 --> 01:07:00,815\nterm worked for cosine.\n\n1123\n01:07:00,815 --> 01:07:06,080\n\n\n1124\n01:07:06,080 --> 01:07:09,235\nGo into radians mode on your\ncalculator and push cosine,\n\n1125\n01:07:09,235 --> 01:07:12,990\nand just keep doing it, and you\nget to some number which\n\n1126\n01:07:12,990 --> 01:07:16,090\nis about 0.73 or 0.74.\n\n1127\n01:07:16,090 --> 01:07:17,340\nI can't remember which.\n\n1128\n01:07:17,340 --> 01:07:22,900\n\n\n1129\n01:07:22,900 --> 01:07:27,170\nBy iterating a function, whose\nfixed point I'm searching for,\n\n1130\n01:07:27,170 --> 01:07:32,090\nit is sometimes the case that\nthat function will converge in\n\n1131\n01:07:32,090 --> 01:07:33,770\nproducing the fixed point.\n\n1132\n01:07:33,770 --> 01:07:39,910\nI think we luck out in this\ncase, so let's look for it.\n\n1133\n01:07:39,910 --> 01:07:48,030\nLet's look at this slide.\n\n1134\n01:07:48,030 --> 01:07:51,390\nConsider the following sequence\nof procedures.\n\n1135\n01:07:51,390 --> 01:07:56,400\n\n\n1136\n01:07:56,400 --> 01:08:02,940\ne0 over here is the procedure\nwhich does nothing at all.\n\n1137\n01:08:02,940 --> 01:08:05,390\nIt's the procedure which\nproduces an error for any\n\n1138\n01:08:05,390 --> 01:08:07,780\narguments you give it.\n\n1139\n01:08:07,780 --> 01:08:09,030\nIt's basically useless.\n\n1140\n01:08:09,030 --> 01:08:14,480\n\n\n1141\n01:08:14,480 --> 01:08:20,080\nWell, however, I can make\nan approximation.\n\n1142\n01:08:20,080 --> 01:08:22,930\nLet's consider it the worst\npossible approximation to\n\n1143\n01:08:22,930 --> 01:08:26,990\nexponentiation, because\nit does nothing.\n\n1144\n01:08:26,990 --> 01:08:34,170\nWell, supposing I substituted e0\nfor g by calling f, as you\n\n1145\n01:08:34,170 --> 01:08:37,380\nsee over here on e0.\n\n1146\n01:08:37,380 --> 01:08:40,729\nSo you see over here,\nhave e0 there.\n\n1147\n01:08:40,729 --> 01:08:43,859\nThen gee, what's e1?\n\n1148\n01:08:43,859 --> 01:08:47,189\ne1 is a procedure which\nexponentiate things to the 0th\n\n1149\n01:08:47,189 --> 01:08:49,325\npower, with no trouble.\n\n1150\n01:08:49,325 --> 01:08:52,420\nIt gets the right answer,\nanything to the zero is one,\n\n1151\n01:08:52,420 --> 01:08:54,250\nand it makes an error\non anything else.\n\n1152\n01:08:54,250 --> 01:08:57,390\n\n\n1153\n01:08:57,390 --> 01:09:06,040\nWell, now what if I take e1 and\nI substitute if for g by\n\n1154\n01:09:06,040 --> 01:09:07,310\ncalling f on e1?\n\n1155\n01:09:07,310 --> 01:09:10,500\n\n\n1156\n01:09:10,500 --> 01:09:15,670\nOh gosh, I have here a procedure\nof two arguments.\n\n1157\n01:09:15,670 --> 01:09:18,250\nNow remember e1 was appropriate\nfor taking\n\n1158\n01:09:18,250 --> 01:09:24,200\nexponentiations of 0, for\nraising to the 0 exponent.\n\n1159\n01:09:24,200 --> 01:09:27,910\nSo here, is n is 0, the result\nis one, so this guy is good\n\n1160\n01:09:27,910 --> 01:09:29,520\nfor that too.\n\n1161\n01:09:29,520 --> 01:09:32,479\nHowever, I can use something for\nraising to the 0th power\n\n1162\n01:09:32,479 --> 01:09:35,979\nto multiply it by x to raise\nsomething to the first power.\n\n1163\n01:09:35,979 --> 01:09:39,670\nSo e2 is good for both\npower 0 and one.\n\n1164\n01:09:39,670 --> 01:09:43,800\n\n\n1165\n01:09:43,800 --> 01:09:47,899\nAnd e3 is constructed from\ne2 in the same way.\n\n1166\n01:09:47,899 --> 01:09:52,240\nAnd e3, of course, by the same\nargument is good for powers 0,\n\n1167\n01:09:52,240 --> 01:09:55,120\none, and two.\n\n1168\n01:09:55,120 --> 01:10:00,140\nAnd so I will assert for you,\nwithout proof, because the\n\n1169\n01:10:00,140 --> 01:10:02,520\nproof is horribly difficult.\n\n1170\n01:10:02,520 --> 01:10:04,050\nAnd that's the sort of thing\nthat people called\n\n1171\n01:10:04,050 --> 01:10:07,710\ndenotational semanticists do.\n\n1172\n01:10:07,710 --> 01:10:10,265\nThis great idea was invented\nby Scott and Strachey.\n\n1173\n01:10:10,265 --> 01:10:14,240\n\n\n1174\n01:10:14,240 --> 01:10:17,110\nThey're very famous\nmathematician types who\n\n1175\n01:10:17,110 --> 01:10:21,030\ninvented the interpretation\nfor these programs that we\n\n1176\n01:10:21,030 --> 01:10:24,240\nhave that I'm talking to\nyou about right now.\n\n1177\n01:10:24,240 --> 01:10:28,950\nAnd they proved, by topology\nthat there is such a fixed\n\n1178\n01:10:28,950 --> 01:10:32,220\npoint in the cases\nthat we want.\n\n1179\n01:10:32,220 --> 01:10:41,180\nBut the assertion is E-X-P-T\nis limit as n goes\n\n1180\n01:10:41,180 --> 01:10:43,680\nto infinity of em.\n\n1181\n01:10:43,680 --> 01:10:47,900\nand And that we've constructed\nthis by the following way.\n\n1182\n01:10:47,900 --> 01:10:50,520\n\n\n1183\n01:10:50,520 --> 01:10:57,530\n--is Well, it's f of, f\nof, f of, f of, f of--\n\n1184\n01:10:57,530 --> 01:11:01,120\nf applied to anything at all.\n\n1185\n01:11:01,120 --> 01:11:04,070\nIt didn't matter what that was,\nbecause, in fact, this\n\n1186\n01:11:04,070 --> 01:11:05,320\nalways produces an error.\n\n1187\n01:11:05,320 --> 01:11:07,540\n\n\n1188\n01:11:07,540 --> 01:11:08,790\nApplied to this--\n\n1189\n01:11:08,790 --> 01:11:12,840\n\n\n1190\n01:11:12,840 --> 01:11:16,380\nThat's by infinite\nnesting of f's.\n\n1191\n01:11:16,380 --> 01:11:19,760\nSo now my problem is to make\nsome infinite things.\n\n1192\n01:11:19,760 --> 01:11:22,590\n\n\n1193\n01:11:22,590 --> 01:11:24,920\nWe need some infinite things.\n\n1194\n01:11:24,920 --> 01:11:28,980\nHow am I going to nest up an f\nan infinite number of times?\n\n1195\n01:11:28,980 --> 01:11:32,380\nI'd better construct this.\n\n1196\n01:11:32,380 --> 01:11:32,930\nWell, I don't know.\n\n1197\n01:11:32,930 --> 01:11:34,810\nHow would I make an infinite\nloop at all?\n\n1198\n01:11:34,810 --> 01:11:37,090\nLet's take a very simple\ninfinite loop, the simplest\n\n1199\n01:11:37,090 --> 01:11:38,340\ninfinite loop imaginable.\n\n1200\n01:11:38,340 --> 01:11:43,550\n\n\n1201\n01:11:43,550 --> 01:11:48,070\nIf I were to take that procedure\nof one argument x\n\n1202\n01:11:48,070 --> 01:11:57,580\nwhich applies x to x and apply\nthat to the procedure of one\n\n1203\n01:11:57,580 --> 01:12:05,320\nargument x which applies\nx to x, then this\n\n1204\n01:12:05,320 --> 01:12:07,440\nis an infinite loop.\n\n1205\n01:12:07,440 --> 01:12:09,980\nThe reason why this is an\ninfinite loop is as follows.\n\n1206\n01:12:09,980 --> 01:12:14,390\nThe way I understand this is I\nsubstitute the argument for\n\n1207\n01:12:14,390 --> 01:12:18,850\nthe formal parameter\nin the body.\n\n1208\n01:12:18,850 --> 01:12:22,590\nBut if I do that, I take for\neach of these x's, I\n\n1209\n01:12:22,590 --> 01:12:25,740\nsubstitute one of these, making\na copy of the original\n\n1210\n01:12:25,740 --> 01:12:28,410\nexpression I just started\nwith, the\n\n1211\n01:12:28,410 --> 01:12:29,660\nsimplest infinite loop.\n\n1212\n01:12:29,660 --> 01:12:35,440\n\n\n1213\n01:12:35,440 --> 01:12:40,750\nNow I want to tell you about a\nparticular operator which is\n\n1214\n01:12:40,750 --> 01:12:43,090\nconstructed by a perturbation\nfrom this infinite loop.\n\n1215\n01:12:43,090 --> 01:12:47,040\n\n\n1216\n01:12:47,040 --> 01:12:48,290\nI'll call it y.\n\n1217\n01:12:48,290 --> 01:12:52,290\n\n\n1218\n01:12:52,290 --> 01:12:56,680\nThis is called Curry's\nParadoxical Combinator of y\n\n1219\n01:12:56,680 --> 01:13:00,510\nafter a fellow by the name of\nCurry, who was a logician of\n\n1220\n01:13:00,510 --> 01:13:04,480\nthe 1930s also.\n\n1221\n01:13:04,480 --> 01:13:08,670\nAnd if I have a procedure of\none argument f, what's it\n\n1222\n01:13:08,670 --> 01:13:09,330\ngoing to have in it?\n\n1223\n01:13:09,330 --> 01:13:13,420\nIt's going to have a kind of\ninfinite loop in it, which is\n\n1224\n01:13:13,420 --> 01:13:21,670\nthat procedure of one argument\nx which applies f to x of x,\n\n1225\n01:13:21,670 --> 01:13:25,820\napplied to that procedure of one\nargument x, which applies\n\n1226\n01:13:25,820 --> 01:13:27,899\nf to f of x.\n\n1227\n01:13:27,899 --> 01:13:32,300\n\n\n1228\n01:13:32,300 --> 01:13:34,590\nNow what's this do?\n\n1229\n01:13:34,590 --> 01:13:42,950\nSuppose we apply y to F. Well,\nthat's easy enough.\n\n1230\n01:13:42,950 --> 01:13:46,910\nThat's this capital\nF over here.\n\n1231\n01:13:46,910 --> 01:13:48,670\nWell, the easiest thing\nto say there is, I\n\n1232\n01:13:48,670 --> 01:13:49,920\nsubstitute F for here.\n\n1233\n01:13:49,920 --> 01:13:55,320\n\n\n1234\n01:13:55,320 --> 01:13:58,460\nSo that's going to give\nme, basically--\n\n1235\n01:13:58,460 --> 01:14:02,800\nbecause then I'm going to\nsubstitute this for x in here.\n\n1236\n01:14:02,800 --> 01:14:08,970\n\n\n1237\n01:14:08,970 --> 01:14:10,810\nLet me actually do it in steps,\nso you can see it\n\n1238\n01:14:10,810 --> 01:14:11,730\ncompletely.\n\n1239\n01:14:11,730 --> 01:14:15,020\nI'm going to be very careful.\n\n1240\n01:14:15,020 --> 01:14:27,510\nThis is open, open, lambda of\nx , capital F, x, x, applied\n\n1241\n01:14:27,510 --> 01:14:37,910\nto itself, F of x of x.\n\n1242\n01:14:37,910 --> 01:14:45,600\nSubstituting this for this in\nhere, this is F applied to--\n\n1243\n01:14:45,600 --> 01:14:47,040\nwhat is it--\n\n1244\n01:14:47,040 --> 01:14:53,850\nsubstituting this in here, open,\nopen, lambda of x, F, of\n\n1245\n01:14:53,850 --> 01:15:08,910\nx and x, applied to lambda of\nx, F of x of x, F, lambda,\n\n1246\n01:15:08,910 --> 01:15:11,510\npair, F.\n\n1247\n01:15:11,510 --> 01:15:13,420\nOh, but what is this?\n\n1248\n01:15:13,420 --> 01:15:17,490\nThis thing over here that\nI just computed, is\n\n1249\n01:15:17,490 --> 01:15:20,030\nthis thing over here.\n\n1250\n01:15:20,030 --> 01:15:23,370\nBut I just wrapped another\nF around it.\n\n1251\n01:15:23,370 --> 01:15:27,850\nSo by applying y to F, I make\nan infinite series of F's.\n\n1252\n01:15:27,850 --> 01:15:30,520\nIf I just let this run forever,\nI'll just keep making\n\n1253\n01:15:30,520 --> 01:15:33,170\nmore and more F's outside.\n\n1254\n01:15:33,170 --> 01:15:35,600\nI ran an infinite loop which\nis useless, but it doesn't\n\n1255\n01:15:35,600 --> 01:15:36,855\nmatter that the inside\nis useless.\n\n1256\n01:15:36,855 --> 01:15:40,220\n\n\n1257\n01:15:40,220 --> 01:15:53,900\nSo y of F is F applied to y of\nF. So y is a magical thing\n\n1258\n01:15:53,900 --> 01:15:58,840\nwhich, when applied to some\nfunction, produces the object\n\n1259\n01:15:58,840 --> 01:16:03,200\nwhich is the fixed point of that\nfunction, if it exists,\n\n1260\n01:16:03,200 --> 01:16:04,450\nand if this all works.\n\n1261\n01:16:04,450 --> 01:16:07,910\n\n\n1262\n01:16:07,910 --> 01:16:10,380\nBecause, indeed, if I take y of\nF and put it into F, I get\n\n1263\n01:16:10,380 --> 01:16:11,630\ny of F out.\n\n1264\n01:16:11,630 --> 01:16:16,240\n\n\n1265\n01:16:16,240 --> 01:16:20,750\nNow I want you to think this\nin terms of the eval-apply\n\n1266\n01:16:20,750 --> 01:16:23,860\ninterpreter for a bit.\n\n1267\n01:16:23,860 --> 01:16:28,540\nI wrote down a whole bunch of\nrecursion equations out there.\n\n1268\n01:16:28,540 --> 01:16:30,210\nThey're simultaneous in\nthe same way these are\n\n1269\n01:16:30,210 --> 01:16:31,470\nsimultaneous equations.\n\n1270\n01:16:31,470 --> 01:16:33,310\nExponentiation was not a\nsimultaneous equation.\n\n1271\n01:16:33,310 --> 01:16:38,150\nIt was only one variable I was\nlooking for a meaning for.\n\n1272\n01:16:38,150 --> 01:16:41,210\nBut what Lisp is is the fixed\npoint of the process which\n\n1273\n01:16:41,210 --> 01:16:44,740\nsays, if I knew what Lisp was\nand substituted it in for\n\n1274\n01:16:44,740 --> 01:16:47,780\neval, and apply, and so on, on\nthe right hand sides of all\n\n1275\n01:16:47,780 --> 01:16:51,930\nthose recursion equations, then\nif it was a real good\n\n1276\n01:16:51,930 --> 01:16:55,340\nLisp, is a real one, then\nthe left hand side\n\n1277\n01:16:55,340 --> 01:16:58,220\nwould also be Lisp.\n\n1278\n01:16:58,220 --> 01:16:59,565\nSo I made sense of\nthat definition.\n\n1279\n01:16:59,565 --> 01:17:02,420\n\n\n1280\n01:17:02,420 --> 01:17:05,410\nNow whether or not there's an\nanswer isn't so obvious.\n\n1281\n01:17:05,410 --> 01:17:07,740\nI can't attack that.\n\n1282\n01:17:07,740 --> 01:17:09,160\nNow these arguments that\nI'm giving you\n\n1283\n01:17:09,160 --> 01:17:10,660\nnow are quite dangerous.\n\n1284\n01:17:10,660 --> 01:17:13,570\nLet's look over here.\n\n1285\n01:17:13,570 --> 01:17:14,610\nThese are limit arguments.\n\n1286\n01:17:14,610 --> 01:17:17,020\nWe're talking about limits, and\nit's really calculus, or\n\n1287\n01:17:17,020 --> 01:17:21,255\ntopology, or something like\nthat, a kind of analysis.\n\n1288\n01:17:21,255 --> 01:17:23,380\nNow here's an argument\nthat you all believe.\n\n1289\n01:17:23,380 --> 01:17:27,010\nAnd I want to make sure you\nrealize that I could be\n\n1290\n01:17:27,010 --> 01:17:29,660\nbullshitting you.\n\n1291\n01:17:29,660 --> 01:17:30,910\nWhat is this?\n\n1292\n01:17:30,910 --> 01:17:34,250\n\n\n1293\n01:17:34,250 --> 01:17:40,300\nu is the sum of 1/2, 1/4, and\n1/8, and so on, the sum of a\n\n1294\n01:17:40,300 --> 01:17:42,820\ngeometric series.\n\n1295\n01:17:42,820 --> 01:17:44,820\nAnd, of course, I could\nplay a game here.\n\n1296\n01:17:44,820 --> 01:17:47,570\nu minus one is 1/2, plus 1/4,\nplus 1/8, and so on.\n\n1297\n01:17:47,570 --> 01:17:53,590\n\n\n1298\n01:17:53,590 --> 01:17:56,190\nWhat I could do here--\n\n1299\n01:17:56,190 --> 01:17:56,680\noops.\n\n1300\n01:17:56,680 --> 01:17:58,920\nThere is a parentheses\nerror here.\n\n1301\n01:17:58,920 --> 01:18:02,740\nBut I can put here two times u\nminus one is one plus 1/2,\n\n1302\n01:18:02,740 --> 01:18:03,990\nplus 1/4, plus 1/8.\n\n1303\n01:18:03,990 --> 01:18:07,570\n\n\n1304\n01:18:07,570 --> 01:18:08,820\nCan I fix that?\n\n1305\n01:18:08,820 --> 01:18:14,010\n\n\n1306\n01:18:14,010 --> 01:18:16,125\nYes, well.\n\n1307\n01:18:16,125 --> 01:18:19,520\n\n\n1308\n01:18:19,520 --> 01:18:27,850\nBut that gives me back two\ntimes u minus one is u,\n\n1309\n01:18:27,850 --> 01:18:30,300\ntherefore, we conclude\nthat u is two.\n\n1310\n01:18:30,300 --> 01:18:31,830\nAnd this actually is true.\n\n1311\n01:18:31,830 --> 01:18:33,910\nThere's no problem like that.\n\n1312\n01:18:33,910 --> 01:18:38,540\nBut supposing I did something\ndifferent.\n\n1313\n01:18:38,540 --> 01:18:39,740\nSupposing I start up with\nsomething which\n\n1314\n01:18:39,740 --> 01:18:41,470\nmanifestly has no sum.\n\n1315\n01:18:41,470 --> 01:18:47,390\nv is one, plus two, plus four,\nplus 8, plus dot, dot, dot.\n\n1316\n01:18:47,390 --> 01:18:49,560\nWell, v minus one is surely two,\nplus four, plus eight,\n\n1317\n01:18:49,560 --> 01:18:52,010\nplus dot, dot, dot.\n\n1318\n01:18:52,010 --> 01:18:57,410\nv minus one over two, gee,\nthat looks like v again.\n\n1319\n01:18:57,410 --> 01:19:01,070\nFrom that I should be able\nto conclude that--\n\n1320\n01:19:01,070 --> 01:19:03,070\nthat's also wrong, apparently.\n\n1321\n01:19:03,070 --> 01:19:04,510\nv equals minus one.\n\n1322\n01:19:04,510 --> 01:19:12,455\n\n\n1323\n01:19:12,455 --> 01:19:15,280\nThat should be a minus one.\n\n1324\n01:19:15,280 --> 01:19:16,735\nAnd that's certainly\na false conclusion.\n\n1325\n01:19:16,735 --> 01:19:22,000\n\n\n1326\n01:19:22,000 --> 01:19:27,300\nSo when you play with limits,\narguments that may work in one\n\n1327\n01:19:27,300 --> 01:19:30,750\ncase they may not work\nin some other case.\n\n1328\n01:19:30,750 --> 01:19:32,240\nYou have to be very careful.\n\n1329\n01:19:32,240 --> 01:19:35,752\nThe arguments have to\nbe well formed.\n\n1330\n01:19:35,752 --> 01:19:40,790\nAnd I don't know, in general,\nwhat the story is about\n\n1331\n01:19:40,790 --> 01:19:43,270\narguments like this.\n\n1332\n01:19:43,270 --> 01:19:46,060\nWe can read a pile of topology\nand find out.\n\n1333\n01:19:46,060 --> 01:19:49,750\nBut, surely, at least you\nunderstand now, why it might\n\n1334\n01:19:49,750 --> 01:19:52,230\nbe some meaning to the things\nwe've been writing on the\n\n1335\n01:19:52,230 --> 01:19:53,260\nblackboard.\n\n1336\n01:19:53,260 --> 01:19:56,480\nAnd you understand what\nthat might mean.\n\n1337\n01:19:56,480 --> 01:20:02,900\nSo, I suppose, it's almost about\ntime for you to merit\n\n1338\n01:20:02,900 --> 01:20:05,720\nbeing made a member of the\ngrand recursive order of\n\n1339\n01:20:05,720 --> 01:20:09,320\nlambda calculus hackers.\n\n1340\n01:20:09,320 --> 01:20:10,820\nThis is the badge.\n\n1341\n01:20:10,820 --> 01:20:14,540\nBecause you now understand, for\nexample, what it says at\n\n1342\n01:20:14,540 --> 01:20:21,890\nthe very top, y F equals\nF y F. Thank you.\n\n1343\n01:20:21,890 --> 01:20:24,710\nAre there any questions?\n\n1344\n01:20:24,710 --> 01:20:25,150\nYes, Lev.\n\n1345\n01:20:25,150 --> 01:20:28,250\nAUDIENCE: With this, it seems\nthat then there's no need to\n\n1346\n01:20:28,250 --> 01:20:31,330\ndefine, as you imply,\nto just remember a\n\n1347\n01:20:31,330 --> 01:20:34,090\nvalue, to apply it later.\n\n1348\n01:20:34,090 --> 01:20:35,850\nDefines were kind of\na side-effect it\n\n1349\n01:20:35,850 --> 01:20:36,490\nseemed in the language.\n\n1350\n01:20:36,490 --> 01:20:37,075\n[INTERPOSING]\n\n1351\n01:20:37,075 --> 01:20:39,300\nare order dependent.\n\n1352\n01:20:39,300 --> 01:20:42,820\nDoes this eliminate the\nside-effect from the\n\n1353\n01:20:42,820 --> 01:20:43,150\n[INTERPOSING]\n\n1354\n01:20:43,150 --> 01:20:46,010\nPROFESSOR: The answer is, this\nis not the way these things\n\n1355\n01:20:46,010 --> 01:20:49,180\nwere implemented.\n\n1356\n01:20:49,180 --> 01:20:53,830\nDefine, indeed is implemented as\nan operation that actually\n\n1357\n01:20:53,830 --> 01:20:59,000\nmodifies an environment\nstructure, changes the frame\n\n1358\n01:20:59,000 --> 01:21:03,690\nthat the define is\nexecuted in.\n\n1359\n01:21:03,690 --> 01:21:08,440\nAnd there are many reasons for\nthat, but a lot of this has to\n\n1360\n01:21:08,440 --> 01:21:11,340\ndo with making an interactive\nsystem.\n\n1361\n01:21:11,340 --> 01:21:14,750\nWhat this is saying is that if\nyou've made a system, and you\n\n1362\n01:21:14,750 --> 01:21:17,210\nknow you're not going to do any\ndebugging or anything like\n\n1363\n01:21:17,210 --> 01:21:20,930\nthat, and you know everything\nthere is all at once, and you\n\n1364\n01:21:20,930 --> 01:21:21,930\nwant to say, what is\nthe meaning of a\n\n1365\n01:21:21,930 --> 01:21:24,090\nfinal set of equations?\n\n1366\n01:21:24,090 --> 01:21:25,790\nThis gives you a\nmeaning for it.\n\n1367\n01:21:25,790 --> 01:21:27,740\nBut in order to make an\ninteractive system, where you\n\n1368\n01:21:27,740 --> 01:21:29,430\ncan change the meaning of one\nthing without changing\n\n1369\n01:21:29,430 --> 01:21:33,580\neverything else, incrementally,\nyou can't do\n\n1370\n01:21:33,580 --> 01:21:35,000\nthat by implementing\nit this way.\n\n1371\n01:21:35,000 --> 01:21:40,990\n\n\n1372\n01:21:40,990 --> 01:21:41,860\nYes.\n\n1373\n01:21:41,860 --> 01:21:44,650\nAUDIENCE: Another question\non your danger slide.\n\n1374\n01:21:44,650 --> 01:21:47,350\nIt seemed that the two examples\nthat you gave had to\n\n1375\n01:21:47,350 --> 01:21:50,300\ndo with convergence and\nnon-convergence?\n\n1376\n01:21:50,300 --> 01:21:53,380\nAnd that may or may not have\nsomething to do with function\n\n1377\n01:21:53,380 --> 01:21:55,600\ntheory in a way which would\nlead you to think of it in\n\n1378\n01:21:55,600 --> 01:21:59,710\nterms of linear systems, or\nnon-linear systems. How does\n\n1379\n01:21:59,710 --> 01:22:03,140\nthis convergence relate to being\nable to see a priori\n\n1380\n01:22:03,140 --> 01:22:05,430\nwhat properties of that\nmight be violated?\n\n1381\n01:22:05,430 --> 01:22:07,680\nPROFESSOR: I don't know.\n\n1382\n01:22:07,680 --> 01:22:10,610\nThe answer is, I don't know\nunder what circumstances.\n\n1383\n01:22:10,610 --> 01:22:13,660\nI don't know how to translate\nthat into less than an\n\n1384\n01:22:13,660 --> 01:22:16,910\nhour of talk more.\n\n1385\n01:22:16,910 --> 01:22:19,850\nWhat are the conditions under\nwhich, for which we know that\n\n1386\n01:22:19,850 --> 01:22:22,720\nthese things converge?\n\n1387\n01:22:22,720 --> 01:22:25,230\nAnd v, all that was telling you\nthat arguments that are\n\n1388\n01:22:25,230 --> 01:22:30,420\nbased on convergence are flaky\nif you don't know the\n\n1389\n01:22:30,420 --> 01:22:32,810\nconvergence beforehand.\n\n1390\n01:22:32,810 --> 01:22:34,440\nYou can make wrong arguments.\n\n1391\n01:22:34,440 --> 01:22:37,810\nYou can make deductions, as if\nyou know the answer, and not\n\n1392\n01:22:37,810 --> 01:22:40,690\nbe stopped somewhere by some\nobvious contradiction.\n\n1393\n01:22:40,690 --> 01:22:43,635\nAUDIENCE: So can we say then\nthat if F is a convergent\n\n1394\n01:22:43,635 --> 01:22:46,230\nmathematical expression,\nthen the recursion\n\n1395\n01:22:46,230 --> 01:22:47,690\nproperty can be--\n\n1396\n01:22:47,690 --> 01:22:52,740\nPROFESSOR: Well, I think there's\na technical kind of F,\n\n1397\n01:22:52,740 --> 01:22:55,150\nthere is a technical description\nof those F's that\n\n1398\n01:22:55,150 --> 01:23:00,790\nhave the property that when\nyou iteratively apply them\n\n1399\n01:23:00,790 --> 01:23:03,020\nlike this, you converge.\n\n1400\n01:23:03,020 --> 01:23:08,470\nThings that are monotonic,\nand continuous, and\n\n1401\n01:23:08,470 --> 01:23:09,370\nI forgot what else.\n\n1402\n01:23:09,370 --> 01:23:12,010\nThere is a whole bunch of little\nconditions like that\n\n1403\n01:23:12,010 --> 01:23:13,430\nwhich have this property.\n\n1404\n01:23:13,430 --> 01:23:15,820\nNow the real problem is deducing\nfrom looking at the\n\n1405\n01:23:15,820 --> 01:23:19,020\nF, its definition here, whether\nnot it has those\n\n1406\n01:23:19,020 --> 01:23:22,010\nproperties, and that's\nvery hard.\n\n1407\n01:23:22,010 --> 01:23:23,280\nThe properties are easy.\n\n1408\n01:23:23,280 --> 01:23:24,580\nYou can write them down.\n\n1409\n01:23:24,580 --> 01:23:26,930\nYou can look in a book\nby Joe Stoy.\n\n1410\n01:23:26,930 --> 01:23:28,660\nIt's a great book--\n\n1411\n01:23:28,660 --> 01:23:29,910\nStoy.\n\n1412\n01:23:29,910 --> 01:23:31,780\n\n\n1413\n01:23:31,780 --> 01:23:37,360\nIt's called, The Scott-Strachey\nMethod of\n\n1414\n01:23:37,360 --> 01:23:41,800\nDenotational Semantics, and it's\nby Joe Stoy, MIT Press.\n\n1415\n01:23:41,800 --> 01:23:47,960\n\n\n1416\n01:23:47,960 --> 01:23:50,630\nAnd he works out all this in\ngreat detail, enough to\n\n1417\n01:23:50,630 --> 01:23:51,880\nhorrify you.\n\n1418\n01:23:51,880 --> 01:23:55,080\n\n\n1419\n01:23:55,080 --> 01:23:56,330\nBut it really is readable.\n\n1420\n01:23:56,330 --> 01:24:09,150\n\n\n1421\n01:24:09,150 --> 01:24:11,490\nOK, well, thank you.\n\n1422\n01:24:11,490 --> 01:24:13,780\nTime for the bigger\nbreak, I suppose.\n\n1423\n01:24:13,780 --> 01:24:36,991\n\n"
  },
  {
    "path": "SrtEN/lec7b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:00,994\n\n\n1\n00:00:00,994 --> 00:00:16,401\n[MUSIC PLAYING]\n\n2\n00:00:16,401 --> 00:00:19,520\nPROFESSOR: Well, let's see.\n\n3\n00:00:19,520 --> 00:00:21,800\nWhat we did so far was\na lot of fun, was\n\n4\n00:00:21,800 --> 00:00:23,050\nit useful for anything?\n\n5\n00:00:23,050 --> 00:00:26,330\n\n\n6\n00:00:26,330 --> 00:00:29,380\nI suppose the answer\nis going to be yes.\n\n7\n00:00:29,380 --> 00:00:33,930\nIf these metacircular\ninterpreters are a valuable\n\n8\n00:00:33,930 --> 00:00:35,180\nthing to play with.\n\n9\n00:00:35,180 --> 00:00:38,050\n\n\n10\n00:00:38,050 --> 00:00:41,300\nWell, there have been times I\nspend 50% of my time, over a\n\n11\n00:00:41,300 --> 00:00:46,590\nyear, trying various design\nalternatives by experimenting\n\n12\n00:00:46,590 --> 00:00:49,600\nwith them with metacircular\ninterpreters--\n\n13\n00:00:49,600 --> 00:00:52,570\nmetacircular interpreters like\nthe sort you just saw.\n\n14\n00:00:52,570 --> 00:00:55,910\nMetacircular is because they\nare defined in terms of\n\n15\n00:00:55,910 --> 00:00:58,830\nthemselves in such a way that\nthe language they interpret\n\n16\n00:00:58,830 --> 00:01:01,270\ncontains itself.\n\n17\n00:01:01,270 --> 00:01:04,080\nSuch interpreters are a\nconvenient medium for\n\n18\n00:01:04,080 --> 00:01:06,800\nexploring language issues.\n\n19\n00:01:06,800 --> 00:01:11,010\nIf you want to try adding a new\nfeature, it's sort of a\n\n20\n00:01:11,010 --> 00:01:15,490\nsnap, it's easy, you just do\nit and see what happens.\n\n21\n00:01:15,490 --> 00:01:17,710\nYou play with that language for\na while you say, gee, I'm\n\n22\n00:01:17,710 --> 00:01:21,090\ndidn't like that, you\nthrow it away.\n\n23\n00:01:21,090 --> 00:01:24,640\nOr you might want to see what\nthe difference is if you'd\n\n24\n00:01:24,640 --> 00:01:30,080\nmake a slight difference in the\nbinding strategy, or some\n\n25\n00:01:30,080 --> 00:01:33,720\nmore complicated things\nthat might occur.\n\n26\n00:01:33,720 --> 00:01:36,810\nIn fact, these metacircular\ninterpreters are an excellent\n\n27\n00:01:36,810 --> 00:01:44,030\nmedium for people exchanging\nideas about language design,\n\n28\n00:01:44,030 --> 00:01:46,960\nbecause they're pretty easy to\nunderstand, and they're short,\n\n29\n00:01:46,960 --> 00:01:49,690\nand compact, and simple.\n\n30\n00:01:49,690 --> 00:01:54,360\nIf I have some idea that I want\nsomebody to criticize\n\n31\n00:01:54,360 --> 00:02:00,770\nlike say, Dan Friedman at\nIndiana, I'd write a little\n\n32\n00:02:00,770 --> 00:02:04,260\nmetacircular interpreter and\nsend him some network mail\n\n33\n00:02:04,260 --> 00:02:05,450\nwith this interpreter in it.\n\n34\n00:02:05,450 --> 00:02:07,900\nHe could whip it up on his\nmachine and play with it and\n\n35\n00:02:07,900 --> 00:02:11,940\nsay, that's no good.\n\n36\n00:02:11,940 --> 00:02:13,706\nAnd then send it back to me and\nsay, well, why don't you\n\n37\n00:02:13,706 --> 00:02:16,880\ntry this one, it's\na little better.\n\n38\n00:02:16,880 --> 00:02:20,160\nSo I want to show you some\nof that technology.\n\n39\n00:02:20,160 --> 00:02:24,750\nSee, because, really, it's the\nessential, simple technology\n\n40\n00:02:24,750 --> 00:02:27,760\nfor getting started in designing\nyour own languages\n\n41\n00:02:27,760 --> 00:02:30,790\nfor particular purposes.\n\n42\n00:02:30,790 --> 00:02:34,210\nLet's start by adding a very\nsimple feature to a Lisp.\n\n43\n00:02:34,210 --> 00:02:40,640\n\n\n44\n00:02:40,640 --> 00:02:42,800\nNow, one thing I want\nto tell you about is\n\n45\n00:02:42,800 --> 00:02:44,370\nfeatures, before I start.\n\n46\n00:02:44,370 --> 00:02:49,560\n\n\n47\n00:02:49,560 --> 00:02:53,100\nThere are many languages that\nhave made a mess of themselves\n\n48\n00:02:53,100 --> 00:02:56,620\nby adding huge numbers\nof features.\n\n49\n00:02:56,620 --> 00:03:00,620\nComputer scientists have a joke\nabout bugs that transform\n\n50\n00:03:00,620 --> 00:03:02,520\nit to features all the time.\n\n51\n00:03:02,520 --> 00:03:05,030\n\n\n52\n00:03:05,030 --> 00:03:10,120\nBut I like to think of it is\nthat many systems suffer from\n\n53\n00:03:10,120 --> 00:03:12,820\nwhat's called creeping\nfeaturism.\n\n54\n00:03:12,820 --> 00:03:17,740\nWhich is that George has a pet\nfeature he'd like in the\n\n55\n00:03:17,740 --> 00:03:20,170\nsystem, so he adds it.\n\n56\n00:03:20,170 --> 00:03:23,480\nAnd then Harry says, gee, this\nsystem is no longer what\n\n57\n00:03:23,480 --> 00:03:26,640\nexactly I like, so I'm going\nto add my favorite feature.\n\n58\n00:03:26,640 --> 00:03:30,710\nAnd then Jim adds his\nfavorite feature.\n\n59\n00:03:30,710 --> 00:03:35,280\nAnd, after a while, the thing\nhas a manual 500 pages long\n\n60\n00:03:35,280 --> 00:03:37,790\nthat no one can understand.\n\n61\n00:03:37,790 --> 00:03:40,780\nAnd sometimes it's the same\nperson who writes all of these\n\n62\n00:03:40,780 --> 00:03:44,830\nfeatures and produces this\nterribly complicated thing.\n\n63\n00:03:44,830 --> 00:03:48,250\nIn some cases, like editors,\nit's sort of reasonable to\n\n64\n00:03:48,250 --> 00:03:51,940\nhave lots of features, because\nthere are a lot of things you\n\n65\n00:03:51,940 --> 00:03:55,730\nwant to be able to do and\nmany of them arbitrary.\n\n66\n00:03:55,730 --> 00:04:00,440\nBut in computer languages, I\nthink it's a disaster to have\n\n67\n00:04:00,440 --> 00:04:01,690\ntoo much stuff in them.\n\n68\n00:04:01,690 --> 00:04:04,110\n\n\n69\n00:04:04,110 --> 00:04:06,860\nThe other alternative you get\ninto is something called\n\n70\n00:04:06,860 --> 00:04:12,300\nfeeping creaturism, which is\nwhere you have a box which has\n\n71\n00:04:12,300 --> 00:04:17,370\na display, a fancy display, and\na mouse, and there is all\n\n72\n00:04:17,370 --> 00:04:21,010\nsorts of complexity associated\nwith all this fancy IO.\n\n73\n00:04:21,010 --> 00:04:24,430\nAnd your computer language\nbecomes a dismal, little, tiny\n\n74\n00:04:24,430 --> 00:04:26,430\nthing that barely works because\nof all the swapping,\n\n75\n00:04:26,430 --> 00:04:30,080\nand disk twitching, and so on,\ncaused by your Windows system.\n\n76\n00:04:30,080 --> 00:04:32,650\nAnd every time you go near the\ncomputer, the mouse process\n\n77\n00:04:32,650 --> 00:04:35,910\nwakes up and says, gee do you\nhave something for me to do,\n\n78\n00:04:35,910 --> 00:04:37,440\nand then it goes\nback to sleep.\n\n79\n00:04:37,440 --> 00:04:40,210\nAnd if you accidentally push\nmouse with you elbow, a big\n\n80\n00:04:40,210 --> 00:04:41,600\npuff of smoke comes out\nof your computer\n\n81\n00:04:41,600 --> 00:04:42,940\nand things like that.\n\n82\n00:04:42,940 --> 00:04:46,030\nSo two ways to disastrously\ndestroy a\n\n83\n00:04:46,030 --> 00:04:47,500\nsystem by adding features.\n\n84\n00:04:47,500 --> 00:04:49,730\nBut try right now to add a\nlittle, simple feature.\n\n85\n00:04:49,730 --> 00:04:52,300\n\n\n86\n00:04:52,300 --> 00:04:54,350\nThis actually is a good\none, and in fact,\n\n87\n00:04:54,350 --> 00:04:57,250\nreal Lisps have it.\n\n88\n00:04:57,250 --> 00:05:03,420\nAs you've seen, there are\nprocedures like plus and times\n\n89\n00:05:03,420 --> 00:05:05,430\nthat take any number\nof arguments.\n\n90\n00:05:05,430 --> 00:05:09,440\nSo we can write things like the\nsum of the product of a\n\n91\n00:05:09,440 --> 00:05:17,540\nand x and x, and the product\nof b and x and c.\n\n92\n00:05:17,540 --> 00:05:21,210\nAs you can see here, addition\ntakes three arguments or two\n\n93\n00:05:21,210 --> 00:05:24,230\narguments, multiplication takes\ntwo arguments or three\n\n94\n00:05:24,230 --> 00:05:27,290\narguments, taking numbers of\narguments all of which are to\n\n95\n00:05:27,290 --> 00:05:30,000\nbe treated in the same way.\n\n96\n00:05:30,000 --> 00:05:32,300\nThis is a valuable thing,\n\n97\n00:05:32,300 --> 00:05:34,960\nindefinite numbers of arguments.\n\n98\n00:05:34,960 --> 00:05:40,460\nYet the particular Lisp system\nthat I showed you is one where\n\n99\n00:05:40,460 --> 00:05:43,600\nthe numbers of arguments is\nfixed, because I had to match\n\n100\n00:05:43,600 --> 00:05:45,910\nthe arguments against the\nformal parameters in the\n\n101\n00:05:45,910 --> 00:05:47,850\nbinder, where there's\na pairup.\n\n102\n00:05:47,850 --> 00:05:50,810\n\n\n103\n00:05:50,810 --> 00:05:53,460\nWell, I'd like to be able to\ndefine new procedures like\n\n104\n00:05:53,460 --> 00:05:58,590\nthis that can have any\nnumber of arguments.\n\n105\n00:05:58,590 --> 00:06:01,150\nWell there's several parts\nto this problem.\n\n106\n00:06:01,150 --> 00:06:03,870\nThe first part is coming\nup with the syntactic\n\n107\n00:06:03,870 --> 00:06:10,620\nspecification, some way of\nnotating the additional\n\n108\n00:06:10,620 --> 00:06:15,480\narguments, of which you don't\nknow how many there are.\n\n109\n00:06:15,480 --> 00:06:17,980\nAnd then there's the other\nthing, which is once we've\n\n110\n00:06:17,980 --> 00:06:21,940\nnotated it, how are we going to\ninterpret that notation so\n\n111\n00:06:21,940 --> 00:06:26,980\nas to do the right thing,\nwhatever the right thing is?\n\n112\n00:06:26,980 --> 00:06:29,230\nSo let's consider an example\nof a sort of thing we might\n\n113\n00:06:29,230 --> 00:06:30,480\nwant to be able to do.\n\n114\n00:06:30,480 --> 00:06:33,070\n\n\n115\n00:06:33,070 --> 00:06:36,380\nSo an example might be, that\nI might want to be able to\n\n116\n00:06:36,380 --> 00:06:40,490\ndefine a procedure which is a\nprocedure of one required\n\n117\n00:06:40,490 --> 00:06:45,820\nargument x and a bunch of\narguments, I don't know how\n\n118\n00:06:45,820 --> 00:06:49,090\nmany there are, called y.\n\n119\n00:06:49,090 --> 00:07:00,725\nSo x is required, and there are\nmany y's, many argument--\n\n120\n00:07:00,725 --> 00:07:04,710\n\n\n121\n00:07:04,710 --> 00:07:05,990\ny will be the list of them.\n\n122\n00:07:05,990 --> 00:07:14,480\n\n\n123\n00:07:14,480 --> 00:07:17,370\nNow, with such a thing, we might\nbe able to say something\n\n124\n00:07:17,370 --> 00:07:20,720\nlike, map--\n\n125\n00:07:20,720 --> 00:07:22,590\nI'm going to do something\nto every one--\n\n126\n00:07:22,590 --> 00:07:30,055\nof that procedure of one\nargument u, which multiplies x\n\n127\n00:07:30,055 --> 00:07:36,890\nby u, and we'll apply\nthat to y.\n\n128\n00:07:36,890 --> 00:07:41,020\nI've used a dot here to indicate\nthat the thing after\n\n129\n00:07:41,020 --> 00:07:46,300\nthis is a list of all the\nrest of the arguments.\n\n130\n00:07:46,300 --> 00:07:47,745\nI'm making a syntactic\nspecification.\n\n131\n00:07:47,745 --> 00:07:53,320\n\n\n132\n00:07:53,320 --> 00:07:56,870\nNow, what this depends upon, the\nreason why this is sort of\n\n133\n00:07:56,870 --> 00:08:01,440\na reasonable thing to do, is\nbecause this happens to be a\n\n134\n00:08:01,440 --> 00:08:04,640\nsyntax that's used in\nthe Lisp reader for\n\n135\n00:08:04,640 --> 00:08:08,631\nrepresenting conses.\n\n136\n00:08:08,631 --> 00:08:11,080\nWe've never introduced\nthat before.\n\n137\n00:08:11,080 --> 00:08:13,680\nYou may have seen when playing\nwith the system that if you\n\n138\n00:08:13,680 --> 00:08:16,740\ncons two things together, you\nget the first, space, dot, the\n\n139\n00:08:16,740 --> 00:08:19,800\nsecond, space--\n\n140\n00:08:19,800 --> 00:08:23,880\nthe first, space, dot, space,\nthe second with parentheses\n\n141\n00:08:23,880 --> 00:08:26,980\naround the whole thing.\n\n142\n00:08:26,980 --> 00:08:36,350\nSo that, for example, this x dot\ny corresponds to a pair,\n\n143\n00:08:36,350 --> 00:08:41,870\nwhich has got an x in\nit and a y in it.\n\n144\n00:08:41,870 --> 00:08:45,520\nThe other notations that you've\nseen so far are things\n\n145\n00:08:45,520 --> 00:08:55,720\nlike a procedure of arguments x\nand y and z which do things,\n\n146\n00:08:55,720 --> 00:08:57,590\nand that looks like--\n\n147\n00:08:57,590 --> 00:09:02,000\n\n\n148\n00:09:02,000 --> 00:09:04,910\nJust looking at the bound\nvariable list, it looks like\n\n149\n00:09:04,910 --> 00:09:18,280\nthis, x, y, z, and\nthe empty thing.\n\n150\n00:09:18,280 --> 00:09:22,590\nIf I have a list of arguments I\nwish to match this against,\n\n151\n00:09:22,590 --> 00:09:26,110\nsupposing, I have a list of\narguments one, two, three, I\n\n152\n00:09:26,110 --> 00:09:36,300\nwant to match these against. So\nI might have here a list of\n\n153\n00:09:36,300 --> 00:09:46,380\nthree things, one, two, three.\n\n154\n00:09:46,380 --> 00:09:48,990\n\n\n155\n00:09:48,990 --> 00:09:54,220\nAnd I want to match x, y, z\nagainst one, two, three.\n\n156\n00:09:54,220 --> 00:09:56,830\nWell, it's clear that the one\nmatches the x, because I can\n\n157\n00:09:56,830 --> 00:10:00,130\njust sort of follow the\nstructure, and the two matches\n\n158\n00:10:00,130 --> 00:10:05,480\nthe y, and the three\nmatches the z.\n\n159\n00:10:05,480 --> 00:10:09,560\nBut now, supposing I were to\ncompare this x dot y--\n\n160\n00:10:09,560 --> 00:10:12,460\nthis is x dot y--\n\n161\n00:10:12,460 --> 00:10:16,010\nsupposing I compare that with\na list of three arguments,\n\n162\n00:10:16,010 --> 00:10:18,510\none, two, three.\n\n163\n00:10:18,510 --> 00:10:20,000\nLet's look at that again.\n\n164\n00:10:20,000 --> 00:10:28,000\n\n\n165\n00:10:28,000 --> 00:10:30,930\nOne, two, three--\n\n166\n00:10:30,930 --> 00:10:34,970\nWell, I can walk along here and\nsay, oh yes, x matches the\n\n167\n00:10:34,970 --> 00:10:43,740\none, the y matches the list,\nwhich is two and three.\n\n168\n00:10:43,740 --> 00:10:47,150\nSo the notation I'm choosing\nhere is one that's very\n\n169\n00:10:47,150 --> 00:10:50,160\nnatural for Lisp system.\n\n170\n00:10:50,160 --> 00:10:52,660\n\n\n171\n00:10:52,660 --> 00:10:54,790\nBut I'm going to choose this as\na notation for representing\n\n172\n00:10:54,790 --> 00:10:56,040\na bunch of arguments.\n\n173\n00:10:56,040 --> 00:10:58,290\n\n\n174\n00:10:58,290 --> 00:11:00,770\nNow, there's an alternative\npossibility.\n\n175\n00:11:00,770 --> 00:11:03,560\nIf I don't want to take one\nspecial out, or two special\n\n176\n00:11:03,560 --> 00:11:07,300\nones out or something like that,\nif I don't want to do\n\n177\n00:11:07,300 --> 00:11:11,420\nthat, if I want to talk about\njust the list of all the\n\n178\n00:11:11,420 --> 00:11:16,950\narguments like in addition, well\nthen the argument list\n\n179\n00:11:16,950 --> 00:11:20,370\nI'm going to choose to be that\nprocedure of all the arguments\n\n180\n00:11:20,370 --> 00:11:25,140\nx which does something with x.\n\n181\n00:11:25,140 --> 00:11:29,190\nAnd which, for example, if I\ntake the procedure, which\n\n182\n00:11:29,190 --> 00:11:35,040\ntakes all the arguments x and\nreturned the list of them,\n\n183\n00:11:35,040 --> 00:11:45,850\nthat's list. That's the\nprocedure list.\n\n184\n00:11:45,850 --> 00:11:46,840\nHow does this work?\n\n185\n00:11:46,840 --> 00:11:49,610\nWell, indeed what I had as the\nbound variable list in this\n\n186\n00:11:49,610 --> 00:11:52,450\ncase, whatever it is,\nis being matched\n\n187\n00:11:52,450 --> 00:11:55,140\nagainst a list of arguments.\n\n188\n00:11:55,140 --> 00:11:57,145\nThis symbol now is all\nof the arguments.\n\n189\n00:11:57,145 --> 00:12:01,490\n\n\n190\n00:12:01,490 --> 00:12:03,830\nAnd so this is the choice I'm\nmaking for a particular\n\n191\n00:12:03,830 --> 00:12:08,060\nsyntactic specification, for the\ndescription of procedures\n\n192\n00:12:08,060 --> 00:12:10,285\nwhich take indefinite numbers\nof arguments.\n\n193\n00:12:10,285 --> 00:12:13,190\n\n\n194\n00:12:13,190 --> 00:12:18,420\nThere are two cases of it,\nthis one and this one.\n\n195\n00:12:18,420 --> 00:12:21,330\nWhen you make syntactic\nspecifications, it's important\n\n196\n00:12:21,330 --> 00:12:26,410\nthat it's unambiguous, that\nneither of these can be\n\n197\n00:12:26,410 --> 00:12:31,100\nconfused with a representation\nwe already have, this one.\n\n198\n00:12:31,100 --> 00:12:33,610\n\n\n199\n00:12:33,610 --> 00:12:38,350\nI can always tell whether\nI have a fixed number of\n\n200\n00:12:38,350 --> 00:12:41,180\nexplicitly named arguments\nmade by these formal\n\n201\n00:12:41,180 --> 00:12:45,470\nparameters, or a fixed number\nof named formal parameters\n\n202\n00:12:45,470 --> 00:12:49,240\nfollowed by a thing which picks\nup all the rest of them,\n\n203\n00:12:49,240 --> 00:12:54,620\nor a list of all the arguments\nwhich will be matched against\n\n204\n00:12:54,620 --> 00:12:57,170\nthis particular formal parameter\ncalled x, because\n\n205\n00:12:57,170 --> 00:12:58,465\nthese are syntactically\ndistinguishable.\n\n206\n00:12:58,465 --> 00:13:02,250\n\n\n207\n00:13:02,250 --> 00:13:05,960\nMany languages make terrible\nerrors in that form where\n\n208\n00:13:05,960 --> 00:13:08,340\nwhole segments of interpretation\nare cut off,\n\n209\n00:13:08,340 --> 00:13:14,560\nbecause there are syntactic\nambiguities in the language.\n\n210\n00:13:14,560 --> 00:13:16,330\nThey are the traditional\nproblems with ALGOL like\n\n211\n00:13:16,330 --> 00:13:22,810\nlanguages having to do with\nthe nesting of ifs in the\n\n212\n00:13:22,810 --> 00:13:25,060\npredicate part.\n\n213\n00:13:25,060 --> 00:13:30,510\nIn any case, now, so I've told\nyou about the syntax, now,\n\n214\n00:13:30,510 --> 00:13:35,250\nwhat are we going to do about\nthe semantics of this?\n\n215\n00:13:35,250 --> 00:13:36,590\nHow do we interpret it?\n\n216\n00:13:36,590 --> 00:13:38,440\nWell this is just super easy.\n\n217\n00:13:38,440 --> 00:13:39,900\nI'm going to modify\nthe metacircular\n\n218\n00:13:39,900 --> 00:13:43,396\ninterpreter to do it.\n\n219\n00:13:43,396 --> 00:13:46,020\nAnd that's a one liner.\n\n220\n00:13:46,020 --> 00:13:47,590\nThere it is.\n\n221\n00:13:47,590 --> 00:13:49,560\nI'm changing the way\nyou pair things up.\n\n222\n00:13:49,560 --> 00:13:56,390\n\n\n223\n00:13:56,390 --> 00:14:06,070\nHere's the procedure that\npairs the variables, the\n\n224\n00:14:06,070 --> 00:14:12,090\nformal parameters, with the\narguments that were passed\n\n225\n00:14:12,090 --> 00:14:16,080\nfrom the last description of the\nmetacircular interpreter.\n\n226\n00:14:16,080 --> 00:14:18,960\n\n\n227\n00:14:18,960 --> 00:14:20,840\nAnd here's some things\nthat are the same\n\n228\n00:14:20,840 --> 00:14:22,670\nas they were before.\n\n229\n00:14:22,670 --> 00:14:25,880\nIn other words, if the list of\nvariables is empty, then if\n\n230\n00:14:25,880 --> 00:14:31,050\nthe list of values is empty,\nthen I have an empty list.\n\n231\n00:14:31,050 --> 00:14:36,890\nOtherwise, I have too many\narguments, that is, if I have\n\n232\n00:14:36,890 --> 00:14:41,580\nempty variables but\nnot empty values.\n\n233\n00:14:41,580 --> 00:14:47,713\nIf I have empty values, but the\nvariables are not empty, I\n\n234\n00:14:47,713 --> 00:14:50,090\nhave too few arguments.\n\n235\n00:14:50,090 --> 00:14:51,340\nThe variables are a symbol--\n\n236\n00:14:51,340 --> 00:14:55,620\n\n\n237\n00:14:55,620 --> 00:14:58,130\ninteresting case--\n\n238\n00:14:58,130 --> 00:15:04,040\nthen, what I should do is say,\noh yes, this is the special\n\n239\n00:15:04,040 --> 00:15:06,255\ncase that I have a\nsymbolic tail.\n\n240\n00:15:06,255 --> 00:15:09,010\n\n\n241\n00:15:09,010 --> 00:15:14,900\nI have here a thing just like\nwe looked over here.\n\n242\n00:15:14,900 --> 00:15:18,630\nThis is a tail which\nis a symbol, y.\n\n243\n00:15:18,630 --> 00:15:20,730\nIt's not a nil.\n\n244\n00:15:20,730 --> 00:15:24,290\nIt's not the empty list. Here's\na symbolic tail that is\n\n245\n00:15:24,290 --> 00:15:25,600\njust the very beginning\nof the tail.\n\n246\n00:15:25,600 --> 00:15:27,790\nThere is nothing else.\n\n247\n00:15:27,790 --> 00:15:36,540\nIn that case, I wish to match\nthat variable with all the\n\n248\n00:15:36,540 --> 00:15:44,500\nvalues and add that to the\npairing that I'm making.\n\n249\n00:15:44,500 --> 00:15:47,660\nOtherwise, I go through the\nnormal arrangement of making\n\n250\n00:15:47,660 --> 00:15:48,910\nup the whole pairing.\n\n251\n00:15:48,910 --> 00:15:52,020\n\n\n252\n00:15:52,020 --> 00:15:54,510\nI suppose that's very simple.\n\n253\n00:15:54,510 --> 00:15:57,080\nAnd that's all there is to it.\n\n254\n00:15:57,080 --> 00:15:58,330\nAnd now I'll answer\nsome questions.\n\n255\n00:15:58,330 --> 00:16:02,620\n\n\n256\n00:16:02,620 --> 00:16:04,220\nThe first one--\n\n257\n00:16:04,220 --> 00:16:06,600\nAre there any questions?\n\n258\n00:16:06,600 --> 00:16:06,950\nYes?\n\n259\n00:16:06,950 --> 00:16:10,450\nAUDIENCE: Could you explain\nthat third form?\n\n260\n00:16:10,450 --> 00:16:12,590\nPROFESSOR: This one?\n\n261\n00:16:12,590 --> 00:16:15,280\nWell, maybe we should look\nat the thing as a\n\n262\n00:16:15,280 --> 00:16:18,570\npiece of list structure.\n\n263\n00:16:18,570 --> 00:16:22,400\nThis is a procedure which\ncontains a lambda.\n\n264\n00:16:22,400 --> 00:16:25,970\n\n\n265\n00:16:25,970 --> 00:16:27,110\nI'm just looking at\nthe list structure\n\n266\n00:16:27,110 --> 00:16:31,090\nwhich represents this.\n\n267\n00:16:31,090 --> 00:16:32,730\nHere's x.\n\n268\n00:16:32,730 --> 00:16:33,980\nThese are our symbols.\n\n269\n00:16:33,980 --> 00:16:37,410\n\n\n270\n00:16:37,410 --> 00:16:39,580\nAnd then the body is\nnothing but x.\n\n271\n00:16:39,580 --> 00:16:44,840\n\n\n272\n00:16:44,840 --> 00:16:48,040\nIf I were looking for the bound\nvariable list part of\n\n273\n00:16:48,040 --> 00:16:52,400\nthis procedure, I would go\nlooking at the CADR, and I'd\n\n274\n00:16:52,400 --> 00:16:54,010\nfind a symbol.\n\n275\n00:16:54,010 --> 00:16:56,750\nSo the, naturally, which is\nthis pairup thing I just\n\n276\n00:16:56,750 --> 00:17:01,570\nshowed you, is going to be\nmatching a symbolic object\n\n277\n00:17:01,570 --> 00:17:05,760\nagainst a list of arguments\nthat were passed.\n\n278\n00:17:05,760 --> 00:17:09,559\nAnd it will bind that symbol\nto the list of arguments.\n\n279\n00:17:09,559 --> 00:17:13,910\n\n\n280\n00:17:13,910 --> 00:17:18,560\nIn this case, if I'm looking\nfor it, the match will be\n\n281\n00:17:18,560 --> 00:17:20,920\nagainst this in the bound\nvariable list position.\n\n282\n00:17:20,920 --> 00:17:24,140\n\n\n283\n00:17:24,140 --> 00:17:27,020\nNow, if what this does is it\ngets a list of arguments and\n\n284\n00:17:27,020 --> 00:17:31,450\nreturns it, that's list. That's\nwhat the procedure is.\n\n285\n00:17:31,450 --> 00:17:34,510\n\n\n286\n00:17:34,510 --> 00:17:36,140\nOh well, thank you.\n\n287\n00:17:36,140 --> 00:17:37,830\nLet's take a break.\n\n288\n00:17:37,830 --> 00:18:20,358\n[MUSIC PLAYING]\n\n289\n00:18:20,358 --> 00:18:23,260\nPROFESSOR: Well let's see.\n\n290\n00:18:23,260 --> 00:18:24,760\nNow, I'm going to tell you\nabout a rather more\n\n291\n00:18:24,760 --> 00:18:32,440\nsubstantial variation, one\nthat's a famous variation that\n\n292\n00:18:32,440 --> 00:18:38,250\nmany early Lisps had.\n\n293\n00:18:38,250 --> 00:18:41,770\nIt's called dynamic binding\nof variables.\n\n294\n00:18:41,770 --> 00:18:44,680\nAnd we'll investigate a little\nbit about that right now.\n\n295\n00:18:44,680 --> 00:18:47,620\n\n\n296\n00:18:47,620 --> 00:18:49,710\nI'm going to first introduce\nthis by showing you the sort\n\n297\n00:18:49,710 --> 00:18:53,740\nof thing that would make\nsomeone want this idea.\n\n298\n00:18:53,740 --> 00:18:56,680\nI'm not going to tell what it is\nyet, I'm going to show you\n\n299\n00:18:56,680 --> 00:18:58,640\nwhy you might want it.\n\n300\n00:18:58,640 --> 00:19:02,100\nSuppose, for example, we looked\nat the sum procedure\n\n301\n00:19:02,100 --> 00:19:08,140\nagain for summing up\na bunch of things.\n\n302\n00:19:08,140 --> 00:19:15,860\nTo be that procedure, of a term,\nlower bound, method of\n\n303\n00:19:15,860 --> 00:19:25,560\ncomputing the next index, and\nupper bound, such that, if a\n\n304\n00:19:25,560 --> 00:19:34,020\nis greater than b then the\nresult is 0, otherwise, it's\n\n305\n00:19:34,020 --> 00:19:40,680\nthe sum, of the term, procedure,\napplied to a and\n\n306\n00:19:40,680 --> 00:19:51,925\nthe result of adding up, terms,\nwith the next a being\n\n307\n00:19:51,925 --> 00:20:06,970\nthe a, the next procedure passed\nalong, and the upper\n\n308\n00:20:06,970 --> 00:20:08,220\nbound being passed along.\n\n309\n00:20:08,220 --> 00:20:14,510\n\n\n310\n00:20:14,510 --> 00:20:15,760\nBlink, blink, blink--\n\n311\n00:20:15,760 --> 00:20:18,900\n\n\n312\n00:20:18,900 --> 00:20:23,350\nNow, when I use this sum\nprocedure, I can use it, for\n\n313\n00:20:23,350 --> 00:20:25,450\nexample, like this.\n\n314\n00:20:25,450 --> 00:20:38,680\nWe can define the sum of the\npowers to be, for example, sum\n\n315\n00:20:38,680 --> 00:20:43,240\nof a bunch of powers x to the\nn, to be that procedure\n\n316\n00:20:43,240 --> 00:20:45,970\nof a, b, and n--\n\n317\n00:20:45,970 --> 00:20:48,150\nlower bound, the upper\nbound, and n--\n\n318\n00:20:48,150 --> 00:20:54,530\nwhich is sum, of lambda of x,\nthe procedure of one argument\n\n319\n00:20:54,530 --> 00:21:05,720\nx, which exponentiates x to\nthe n, with the a, the\n\n320\n00:21:05,720 --> 00:21:11,440\nincrementer, and b, being\npassed along.\n\n321\n00:21:11,440 --> 00:21:16,340\nSo we're adding up x\nto n, given an x.\n\n322\n00:21:16,340 --> 00:21:19,740\nx takes on values from a to\nb, incrementing by one.\n\n323\n00:21:19,740 --> 00:21:22,940\n\n\n324\n00:21:22,940 --> 00:21:24,300\nI can also write the--\n\n325\n00:21:24,300 --> 00:21:27,670\n\n\n326\n00:21:27,670 --> 00:21:29,780\nThat's right.\n\n327\n00:21:29,780 --> 00:21:31,910\nProduct, excuse me.\n\n328\n00:21:31,910 --> 00:21:33,220\nThe product of a bunch\nof powers.\n\n329\n00:21:33,220 --> 00:21:38,080\n\n\n330\n00:21:38,080 --> 00:21:40,020\nIt's a strange name.\n\n331\n00:21:40,020 --> 00:21:41,960\nI'm going to leave it there.\n\n332\n00:21:41,960 --> 00:21:43,210\nWeird--\n\n333\n00:21:43,210 --> 00:21:45,760\n\n\n334\n00:21:45,760 --> 00:21:50,890\nI write up what I have.\nI'm sure that's right.\n\n335\n00:21:50,890 --> 00:21:53,720\nAnd if I want the product\nof a bunch of powers--\n\n336\n00:21:53,720 --> 00:21:58,630\n\n\n337\n00:21:58,630 --> 00:22:03,400\nThat was 12 brain cells,\nthat double-take.\n\n338\n00:22:03,400 --> 00:22:06,890\nI can for example use the\nprocedure which is like sum,\n\n339\n00:22:06,890 --> 00:22:10,080\nwhich is for making products,\nbut it's similar to that, that\n\n340\n00:22:10,080 --> 00:22:11,450\nyou've seen before.\n\n341\n00:22:11,450 --> 00:22:16,725\nThere's a procedure of three\narguments again.\n\n342\n00:22:16,725 --> 00:22:24,080\nWhich is the product of terms\nthat are constructed, or\n\n343\n00:22:24,080 --> 00:22:26,480\nfactors in this case,\nconstructed from\n\n344\n00:22:26,480 --> 00:22:35,970\nexponentiating x to the n,\nwhere I start with a, I\n\n345\n00:22:35,970 --> 00:22:37,850\nincrement, and I go to b.\n\n346\n00:22:37,850 --> 00:22:41,530\n\n\n347\n00:22:41,530 --> 00:22:48,690\nNow, there's some sort of thing\nhere that should disturb\n\n348\n00:22:48,690 --> 00:22:50,750\nyou immediately.\n\n349\n00:22:50,750 --> 00:22:53,180\nThese look the same.\n\n350\n00:22:53,180 --> 00:22:56,590\nWhy am I writing this\ncode so many times?\n\n351\n00:22:56,590 --> 00:23:01,270\nHere I am, in the same boat\nI've been in before.\n\n352\n00:23:01,270 --> 00:23:03,810\nWouldn't it be nice to make\nan abstraction here?\n\n353\n00:23:03,810 --> 00:23:05,980\nWhat's an example of a good\nabstraction to make?\n\n354\n00:23:05,980 --> 00:23:08,470\nWell, I see some codes\nthat's identical.\n\n355\n00:23:08,470 --> 00:23:11,080\nHere's one, and here's\nanother.\n\n356\n00:23:11,080 --> 00:23:14,450\n\n\n357\n00:23:14,450 --> 00:23:17,090\nAnd so maybe I should be\nable to pull that out.\n\n358\n00:23:17,090 --> 00:23:21,580\nI should be able to say, oh\nyes, the sum of the powers\n\n359\n00:23:21,580 --> 00:23:23,350\ncould be written in terms\nof something called\n\n360\n00:23:23,350 --> 00:23:25,710\nthe nth power procedure.\n\n361\n00:23:25,710 --> 00:23:28,690\nImagine somebody wanted to write\na slightly different\n\n362\n00:23:28,690 --> 00:23:30,030\nprocedure that looks\nlike this.\n\n363\n00:23:30,030 --> 00:23:37,630\n\n\n364\n00:23:37,630 --> 00:23:49,300\nThe sum powers to be a procedure\nof a, b, and n, as\n\n365\n00:23:49,300 --> 00:23:53,556\nthe result of summing\nup the nth power.\n\n366\n00:23:53,556 --> 00:23:59,720\nWe're going to give a name to\nthat idea, for starting at a,\n\n367\n00:23:59,720 --> 00:24:02,170\ngoing by one, and ending at b.\n\n368\n00:24:02,170 --> 00:24:06,000\n\n\n369\n00:24:06,000 --> 00:24:12,480\nAnd similarly, I might want to\nwrite the product powers this\n\n370\n00:24:12,480 --> 00:24:16,270\nway, abstracting\nout this idea.\n\n371\n00:24:16,270 --> 00:24:17,520\nI might want this.\n\n372\n00:24:17,520 --> 00:24:22,100\n\n\n373\n00:24:22,100 --> 00:24:35,350\nProduct powers, to be a\nprocedure of a, b, and n,\n\n374\n00:24:35,350 --> 00:24:47,540\nwhich is the product of the nth\npower operation on a with\n\n375\n00:24:47,540 --> 00:24:56,380\nthe incrementation and b being\nmy arguments for the\n\n376\n00:24:56,380 --> 00:24:58,380\nanalogous-thing product.\n\n377\n00:24:58,380 --> 00:25:02,840\nAnd I'd like to be able to\ndefine, I'd like to be able to\n\n378\n00:25:02,840 --> 00:25:04,680\ndefine nth power--\n\n379\n00:25:04,680 --> 00:25:05,930\nI'll put it over here.\n\n380\n00:25:05,930 --> 00:25:11,215\n\n\n381\n00:25:11,215 --> 00:25:12,990\nI'll put it at the top.\n\n382\n00:25:12,990 --> 00:25:25,410\n\n\n383\n00:25:25,410 --> 00:25:30,630\n--to be, in fact, my procedure\nof one argument x which is the\n\n384\n00:25:30,630 --> 00:25:35,390\nresult of exponentiating\nx to the n.\n\n385\n00:25:35,390 --> 00:25:38,640\nBut I have a problem.\n\n386\n00:25:38,640 --> 00:25:44,160\nMy environment model, that is my\nmeans of interpretation for\n\n387\n00:25:44,160 --> 00:25:47,010\nthe language that we've defined\nso far, does not give\n\n388\n00:25:47,010 --> 00:25:48,810\nme a meaning for this n.\n\n389\n00:25:48,810 --> 00:25:52,520\n\n\n390\n00:25:52,520 --> 00:26:06,410\nBecause, as you know, this n\nis free in this procedure.\n\n391\n00:26:06,410 --> 00:26:09,600\nThe environment model tells us\nthat the meaning of a free\n\n392\n00:26:09,600 --> 00:26:13,760\nvariable is determined in the\nenvironment in which this\n\n393\n00:26:13,760 --> 00:26:16,640\nprocedure is defined.\n\n394\n00:26:16,640 --> 00:26:18,120\nIn a way I have written it,\nassuming these things are\n\n395\n00:26:18,120 --> 00:26:22,830\ndefined on the blackboard as\nis, this is defined in the\n\n396\n00:26:22,830 --> 00:26:25,850\nglobal environment, where\nthere is no end.\n\n397\n00:26:25,850 --> 00:26:28,720\nTherefore, n is unbound\nvariable.\n\n398\n00:26:28,720 --> 00:26:33,390\nBut it's perfectly clear, to\nmost of us, that we would like\n\n399\n00:26:33,390 --> 00:26:36,220\nit to be this n and this n.\n\n400\n00:26:36,220 --> 00:26:38,990\n\n\n401\n00:26:38,990 --> 00:26:42,840\nOn the other hand,\nit would be nice.\n\n402\n00:26:42,840 --> 00:26:45,290\nCertainly we've got to be\ncareful here of keeping this\n\n403\n00:26:45,290 --> 00:26:51,005\nto be this, and this one\nover here, wherever it\n\n404\n00:26:51,005 --> 00:26:52,900\nis to be this one.\n\n405\n00:26:52,900 --> 00:26:57,390\n\n\n406\n00:26:57,390 --> 00:27:01,360\nWell, the desire to make\nthis work has led to\n\n407\n00:27:01,360 --> 00:27:04,040\na very famous bug.\n\n408\n00:27:04,040 --> 00:27:07,310\nI'll tell you about\nthe famous bug.\n\n409\n00:27:07,310 --> 00:27:10,660\nLook at this slide.\n\n410\n00:27:10,660 --> 00:27:13,990\nThis is an idea called\ndynamic binding.\n\n411\n00:27:13,990 --> 00:27:17,980\nWhere, instead of the free\nvariable being interpreted in\n\n412\n00:27:17,980 --> 00:27:22,820\nthe environment of definition\nof a procedure, the free\n\n413\n00:27:22,820 --> 00:27:25,770\nvariable is interpreted as\nhaving its value in the\n\n414\n00:27:25,770 --> 00:27:29,125\nenvironment of the caller\nof the procedure.\n\n415\n00:27:29,125 --> 00:27:31,850\n\n\n416\n00:27:31,850 --> 00:27:36,680\nSo what you have is a system\nwhere you search up the chain\n\n417\n00:27:36,680 --> 00:27:41,990\nof callers of a particular\nprocedure, and, of course, in\n\n418\n00:27:41,990 --> 00:27:45,240\nthis case, since nth power is\ncalled from inside product\n\n419\n00:27:45,240 --> 00:27:46,010\nwhatever it is--\n\n420\n00:27:46,010 --> 00:27:48,140\nI had to write our own sum\nwhich is the analogous\n\n421\n00:27:48,140 --> 00:27:50,530\nprocedure--\n\n422\n00:27:50,530 --> 00:27:55,300\nand product is presumably called\nfrom product powers, as\n\n423\n00:27:55,300 --> 00:27:58,490\nyou see over here, then since\nproduct powers bind with\n\n424\n00:27:58,490 --> 00:28:03,220\nvariable n , then nth powers\nn would be derived\n\n425\n00:28:03,220 --> 00:28:04,470\nthrough that chain.\n\n426\n00:28:04,470 --> 00:28:08,140\n\n\n427\n00:28:08,140 --> 00:28:12,600\nSimilarly, this n, the nth power\nin n in this case, would\n\n428\n00:28:12,600 --> 00:28:15,800\ncome through nth power here\nbeing called from inside sum.\n\n429\n00:28:15,800 --> 00:28:19,730\nYou can see it being called\nfrom inside sum here.\n\n430\n00:28:19,730 --> 00:28:22,900\nIt's called term here.\n\n431\n00:28:22,900 --> 00:28:28,930\nBut sum was called from inside\nof sum powers, which bound n.\n\n432\n00:28:28,930 --> 00:28:35,245\nTherefore, there would be an n\navailable for that n to get\n\n433\n00:28:35,245 --> 00:28:36,495\nit's value from.\n\n434\n00:28:36,495 --> 00:28:39,430\n\n\n435\n00:28:39,430 --> 00:28:43,630\nWhat we have below this white\nline plus over here, is what's\n\n436\n00:28:43,630 --> 00:28:46,540\ncalled a dynamic binding\nview of the world.\n\n437\n00:28:46,540 --> 00:28:50,850\nIf that works, that's a\ndynamic binding view.\n\n438\n00:28:50,850 --> 00:28:55,310\nNow, let's take a look, for\nexample, at just what it takes\n\n439\n00:28:55,310 --> 00:28:55,990\nto implement that.\n\n440\n00:28:55,990 --> 00:28:57,480\nThat's real easy.\n\n441\n00:28:57,480 --> 00:29:01,400\nIn fact, the very first Lisps\nthat had any interpretations\n\n442\n00:29:01,400 --> 00:29:04,440\nof the free variables at all,\nhad dynamic binding\n\n443\n00:29:04,440 --> 00:29:06,490\ninterpretations for the\nfree variables.\n\n444\n00:29:06,490 --> 00:29:09,570\nAPL has dynamic binding\ninterpretation for the free\n\n445\n00:29:09,570 --> 00:29:15,220\nvariables, not lexical\nor static binding.\n\n446\n00:29:15,220 --> 00:29:18,790\nSo, of course, the change\nis in eval.\n\n447\n00:29:18,790 --> 00:29:22,780\nAnd it's really in two places.\n\n448\n00:29:22,780 --> 00:29:27,760\nFirst of all, one thing we see,\nis that things become a\n\n449\n00:29:27,760 --> 00:29:29,010\nlittle simpler.\n\n450\n00:29:29,010 --> 00:29:32,460\n\n\n451\n00:29:32,460 --> 00:29:34,930\nIf I don't have to have the\nenvironment be the environment\n\n452\n00:29:34,930 --> 00:29:38,490\nof definition for procedure, the\nprocedure need not capture\n\n453\n00:29:38,490 --> 00:29:42,030\nthe environment at the\ntime it's defined.\n\n454\n00:29:42,030 --> 00:29:47,900\nAnd so if we look here at this\nslide, we see that the clause\n\n455\n00:29:47,900 --> 00:29:51,890\nfor a lambda expression, which\nis the way a procedure is\n\n456\n00:29:51,890 --> 00:29:57,820\ndefined, does not make up a\nthing which has a type closure\n\n457\n00:29:57,820 --> 00:30:01,290\nand a attached environment\nstructure.\n\n458\n00:30:01,290 --> 00:30:02,540\nIt's just the expression\nitself.\n\n459\n00:30:02,540 --> 00:30:06,440\nAnd we'll decompose that some\nother way somewhere else.\n\n460\n00:30:06,440 --> 00:30:12,210\nThe other thing we see is the\napplicator must be able to get\n\n461\n00:30:12,210 --> 00:30:14,290\nthe environment of the caller.\n\n462\n00:30:14,290 --> 00:30:19,560\nThe caller of a procedure\nis right here.\n\n463\n00:30:19,560 --> 00:30:22,810\nIf the expression we're\nevaluating is anpplication or\n\n464\n00:30:22,810 --> 00:30:25,680\na combination, then we're going\nto call a procedure\n\n465\n00:30:25,680 --> 00:30:26,980\nwhich is the value\nof the operator.\n\n466\n00:30:26,980 --> 00:30:29,840\n\n\n467\n00:30:29,840 --> 00:30:33,100\nThe environment of the caller\nis the environment we have\n\n468\n00:30:33,100 --> 00:30:35,890\nright here, available now.\n\n469\n00:30:35,890 --> 00:30:38,570\nSo all I have to do is pass\nthat environment to the\n\n470\n00:30:38,570 --> 00:30:41,490\napplicator, to apply.\n\n471\n00:30:41,490 --> 00:30:44,680\nAnd if we look at that here,\nthe only change we have to\n\n472\n00:30:44,680 --> 00:30:49,720\nmake is that fellow takes that\nenvironment and uses that\n\n473\n00:30:49,720 --> 00:30:57,240\nenvironment for the purpose of\nextending that environment\n\n474\n00:30:57,240 --> 00:31:00,100\nwhen abiding the formal\nparameters of the procedure to\n\n475\n00:31:00,100 --> 00:31:04,560\nthe arguments that were passed,\nnot an environment\n\n476\n00:31:04,560 --> 00:31:06,810\nthat was captured in\nthe procedure.\n\n477\n00:31:06,810 --> 00:31:09,780\nThe reason why the first Lisps\nwere implemented this way, is\n\n478\n00:31:09,780 --> 00:31:14,130\nthe sort of the obvious,\naccidental implementation.\n\n479\n00:31:14,130 --> 00:31:15,990\nAnd, of course, as usual,\npeople got used to\n\n480\n00:31:15,990 --> 00:31:17,250\nit and liked it.\n\n481\n00:31:17,250 --> 00:31:18,730\nAnd there were some people\nsaid, this is\n\n482\n00:31:18,730 --> 00:31:21,590\nthe way to do it.\n\n483\n00:31:21,590 --> 00:31:25,870\nUnfortunately that causes some\nserious problems. The most\n\n484\n00:31:25,870 --> 00:31:31,240\nimportant, serious problem in\nusing dynamic binding is\n\n485\n00:31:31,240 --> 00:31:35,460\nthere's a modularity crisis\nthat's involved it.\n\n486\n00:31:35,460 --> 00:31:38,370\nIf two people are working\ntogether on some big system,\n\n487\n00:31:38,370 --> 00:31:41,580\nthen an important thing to want\nis that the names used by\n\n488\n00:31:41,580 --> 00:31:44,580\neach one don't interfere with\nthe names of the other.\n\n489\n00:31:44,580 --> 00:31:47,930\n\n\n490\n00:31:47,930 --> 00:31:51,060\nIt's important that when I\ninvent some segment of code\n\n491\n00:31:51,060 --> 00:31:54,985\nthat no one can make my code\nstop working by using my names\n\n492\n00:31:54,985 --> 00:31:59,850\nthat I use internal to my code,\ninternal to his code.\n\n493\n00:31:59,850 --> 00:32:03,140\nHowever, dynamic binding\nviolates that particular\n\n494\n00:32:03,140 --> 00:32:06,670\nmodularity constraint\nin a clear way.\n\n495\n00:32:06,670 --> 00:32:12,540\nConsider, for example, what\nhappens over here.\n\n496\n00:32:12,540 --> 00:32:17,590\nSuppose it was the case\nthat I decided to\n\n497\n00:32:17,590 --> 00:32:19,810\nchange the word next.\n\n498\n00:32:19,810 --> 00:32:25,870\nSupposing somebody is writing\nsum, and somebody else is\n\n499\n00:32:25,870 --> 00:32:28,970\ngoing to use sum.\n\n500\n00:32:28,970 --> 00:32:33,790\nThe writer of sum has a choice\nof what names he may use.\n\n501\n00:32:33,790 --> 00:32:36,760\nLet's say, I'm that writer.\n\n502\n00:32:36,760 --> 00:32:39,300\nWell, by gosh, just happens I\ndidn't want to call this next.\n\n503\n00:32:39,300 --> 00:32:41,500\nI called it n.\n\n504\n00:32:41,500 --> 00:32:48,140\nSo all places where you see\nnext, I called it n.\n\n505\n00:32:48,140 --> 00:32:49,940\nWhoops.\n\n506\n00:32:49,940 --> 00:32:51,700\nI changed nothing about the\nspecifications of this\n\n507\n00:32:51,700 --> 00:32:56,110\nprogram, but this program\nstops working.\n\n508\n00:32:56,110 --> 00:32:59,730\nNot only that, unfortunately,\nthis one does too.\n\n509\n00:32:59,730 --> 00:33:02,260\nWhy do these programs\nstop working?\n\n510\n00:33:02,260 --> 00:33:04,480\nWell, it's sort of clear.\n\n511\n00:33:04,480 --> 00:33:09,890\nInstead of chasing out the value\nof the n that occurs in\n\n512\n00:33:09,890 --> 00:33:16,450\nnth power over here or over\nhere, through the environment\n\n513\n00:33:16,450 --> 00:33:19,940\nof definition, where this one is\nalways linked to this one,\n\n514\n00:33:19,940 --> 00:33:21,660\nif it was through the\nenvironment of definition,\n\n515\n00:33:21,660 --> 00:33:24,370\nbecause here is the\ndefinition.\n\n516\n00:33:24,370 --> 00:33:27,320\nThis lambda expression was\nexecuted in the environment\n\n517\n00:33:27,320 --> 00:33:30,700\nwhere that n was defined.\n\n518\n00:33:30,700 --> 00:33:33,150\nIf instead of doing that, I have\nto chase through the call\n\n519\n00:33:33,150 --> 00:33:37,320\nchain, then look what horrible\nthing happens.\n\n520\n00:33:37,320 --> 00:33:44,780\nWell, this was called from\ninside sum as term, term a.\n\n521\n00:33:44,780 --> 00:33:47,350\nI'm looking for a value of n.\n\n522\n00:33:47,350 --> 00:33:50,700\nInstead of getting this\none, I get that one.\n\n523\n00:33:50,700 --> 00:33:53,430\nSo by changing the insides of\nthis program, this program\n\n524\n00:33:53,430 --> 00:33:54,680\nstops working.\n\n525\n00:33:54,680 --> 00:33:56,770\n\n\n526\n00:33:56,770 --> 00:33:58,770\nSo I no longer have\na quantifier,\n\n527\n00:33:58,770 --> 00:34:00,020\nas I described before.\n\n528\n00:34:00,020 --> 00:34:02,700\n\n\n529\n00:34:02,700 --> 00:34:05,430\nThe lambda symbol is supposed\nto be a quantifier.\n\n530\n00:34:05,430 --> 00:34:09,650\nA thing which has the property\nthat the names that are bound\n\n531\n00:34:09,650 --> 00:34:14,739\nby it are unimportant, that I\ncan uniformly substitute any\n\n532\n00:34:14,739 --> 00:34:18,230\nnames for these throughout this\nthing, so long as they\n\n533\n00:34:18,230 --> 00:34:21,699\ndon't occur in here, the new\nnames, and the meaning of this\n\n534\n00:34:21,699 --> 00:34:24,040\nexpression should remain\nunchanged.\n\n535\n00:34:24,040 --> 00:34:26,050\nI've just changed the meaning of\nthe expression by changing\n\n536\n00:34:26,050 --> 00:34:28,690\nthe one of the names.\n\n537\n00:34:28,690 --> 00:34:32,170\nSo lambda is no longer\na well defined idea.\n\n538\n00:34:32,170 --> 00:34:34,550\nIt's a very serious problem.\n\n539\n00:34:34,550 --> 00:34:40,850\nSo for that reason, I and my\nbuddies have given up this\n\n540\n00:34:40,850 --> 00:34:43,650\nparticular kind of abstraction,\nwhich I would\n\n541\n00:34:43,650 --> 00:34:48,090\nlike to have, in favor of\na modularity principle.\n\n542\n00:34:48,090 --> 00:34:52,310\nBut this is the kind of\nexperiment you can do if you\n\n543\n00:34:52,310 --> 00:34:54,530\nwant to play with these\ninterpreters.\n\n544\n00:34:54,530 --> 00:34:58,270\nYou can try them out this way,\nthat way, and the other way.\n\n545\n00:34:58,270 --> 00:35:00,070\nYou see what makes\na nicer language.\n\n546\n00:35:00,070 --> 00:35:02,680\n\n\n547\n00:35:02,680 --> 00:35:04,990\nSo that's a very important\nthing to be able to do.\n\n548\n00:35:04,990 --> 00:35:07,260\nNow, I would like to give you\na feeling for I think the\n\n549\n00:35:07,260 --> 00:35:10,880\nright thing to do is here.\n\n550\n00:35:10,880 --> 00:35:14,190\nHow are you going to I get\nthis kind of power in a\n\n551\n00:35:14,190 --> 00:35:16,280\nlexical system?\n\n552\n00:35:16,280 --> 00:35:18,610\nAnd the answer is, of course,\nwhat I really want is a\n\n553\n00:35:18,610 --> 00:35:21,790\nsomething that makes up for\nme an exponentiator for a\n\n554\n00:35:21,790 --> 00:35:23,690\nparticular n.\n\n555\n00:35:23,690 --> 00:35:26,280\nGiven an n, it will make\nme an exponentiator.\n\n556\n00:35:26,280 --> 00:35:28,170\nOh, but that's easy too.\n\n557\n00:35:28,170 --> 00:35:30,570\nIn other words, I can write\nmy program this way.\n\n558\n00:35:30,570 --> 00:35:35,450\n\n\n559\n00:35:35,450 --> 00:35:40,720\nI'm going to define a thing\ncalled PGEN, which is a\n\n560\n00:35:40,720 --> 00:35:45,240\nprocedure of n which produces\nfor me an exponentiator.\n\n561\n00:35:45,240 --> 00:35:50,240\n\n\n562\n00:35:50,240 --> 00:35:51,490\n--x to the n.\n\n563\n00:35:51,490 --> 00:35:56,900\n\n\n564\n00:35:56,900 --> 00:36:00,310\nGiven that I have that, then I\ncan capture the abstraction I\n\n565\n00:36:00,310 --> 00:36:04,090\nwanted even better, because now\nit's encapsulated in a way\n\n566\n00:36:04,090 --> 00:36:07,890\nwhere I can't be destroyed\nby a change of names.\n\n567\n00:36:07,890 --> 00:36:20,200\nI can define some powers to be a\nprocedure again of a, b, and\n\n568\n00:36:20,200 --> 00:36:28,070\nn which is the sum of the term\nfunction generated by using\n\n569\n00:36:28,070 --> 00:36:37,590\nthis generator, PGEN, n, with\na, incrementer, and b.\n\n570\n00:36:37,590 --> 00:36:42,490\n\n\n571\n00:36:42,490 --> 00:36:57,100\nAnd I can define the product of\npowers to be a procedure of\n\n572\n00:36:57,100 --> 00:37:09,010\na, b, and n which is the product\nPGEN, n, with a,\n\n573\n00:37:09,010 --> 00:37:11,150\nincrement, and b.\n\n574\n00:37:11,150 --> 00:37:14,340\nNow, of course, this is a very\nsimple example where this\n\n575\n00:37:14,340 --> 00:37:17,280\nobject that I'm trying to\nabstract over is small.\n\n576\n00:37:17,280 --> 00:37:20,100\nBut it could be a 100\nlines of code.\n\n577\n00:37:20,100 --> 00:37:22,350\nAnd so, the purpose\nof this is, of\n\n578\n00:37:22,350 --> 00:37:23,670\ncourse, to make it simple.\n\n579\n00:37:23,670 --> 00:37:25,630\nI'd give a name to it, it's\njust that here it's a\n\n580\n00:37:25,630 --> 00:37:28,200\nparameterized name.\n\n581\n00:37:28,200 --> 00:37:31,460\nIt's a name that depends upon,\nexplicitly, the lexically\n\n582\n00:37:31,460 --> 00:37:34,050\napparent value of n.\n\n583\n00:37:34,050 --> 00:37:37,130\n\n\n584\n00:37:37,130 --> 00:37:40,210\nSo you can think of this\nas a long name.\n\n585\n00:37:40,210 --> 00:37:45,150\nAnd here, I've solved my problem\nby naming the term\n\n586\n00:37:45,150 --> 00:37:49,220\ngeneration procedures\nwithin an n in them.\n\n587\n00:37:49,220 --> 00:37:55,080\n\n\n588\n00:37:55,080 --> 00:37:57,140\nAre there any questions?\n\n589\n00:37:57,140 --> 00:37:58,380\nOh, yes, David.\n\n590\n00:37:58,380 --> 00:38:04,820\nAUDIENCE: Is the only solution\nto the problem you raise to\n\n591\n00:38:04,820 --> 00:38:06,470\ncreate another procedure?\n\n592\n00:38:06,470 --> 00:38:09,020\nIn other words, can this only\nwork in languages that are\n\n593\n00:38:09,020 --> 00:38:12,402\ncapable of defining objects\nas procedures?\n\n594\n00:38:12,402 --> 00:38:13,765\nPROFESSOR: Oh, I see.\n\n595\n00:38:13,765 --> 00:38:16,530\n\n\n596\n00:38:16,530 --> 00:38:20,530\nMy solution to making this\nabstraction, when I didn't\n\n597\n00:38:20,530 --> 00:38:23,950\nwant include the procedure\ninside the body, depends upon\n\n598\n00:38:23,950 --> 00:38:28,190\nmy ability to return a procedure\nor export one.\n\n599\n00:38:28,190 --> 00:38:30,410\nAnd that's right.\n\n600\n00:38:30,410 --> 00:38:33,550\nIf I don't have that, then I\njust don't have this ability\n\n601\n00:38:33,550 --> 00:38:39,490\nto make an abstraction in\na way where I don't have\n\n602\n00:38:39,490 --> 00:38:40,930\npossibilities of symbol\nconflicts that were\n\n603\n00:38:40,930 --> 00:38:43,000\nunanticipated.\n\n604\n00:38:43,000 --> 00:38:45,610\nThat's right.\n\n605\n00:38:45,610 --> 00:38:52,690\nI consider being able to return\nthe procedural value\n\n606\n00:38:52,690 --> 00:38:57,780\nand, therefore, to sort of have\nfirst class procedures,\n\n607\n00:38:57,780 --> 00:39:01,840\nin general, as being essential\nto doing very good modular\n\n608\n00:39:01,840 --> 00:39:03,700\nprogramming.\n\n609\n00:39:03,700 --> 00:39:07,440\nNow, indeed there are many other\nways to skin this cat.\n\n610\n00:39:07,440 --> 00:39:10,500\nWhat you can do is take for each\nof the bad things that\n\n611\n00:39:10,500 --> 00:39:13,420\nyou have to worry about, you\ncan make a special feature\n\n612\n00:39:13,420 --> 00:39:15,840\nthat covers that thing.\n\n613\n00:39:15,840 --> 00:39:17,930\nYou can make a package system.\n\n614\n00:39:17,930 --> 00:39:22,240\nYou can make a module system\nas in Ada, et cetera.\n\n615\n00:39:22,240 --> 00:39:26,440\nAnd all of those work, or they\ncover little regions of it.\n\n616\n00:39:26,440 --> 00:39:28,820\nThe thing is that returning\nprocedures as values cover all\n\n617\n00:39:28,820 --> 00:39:35,820\nof those problems. And so it's\nthe simplest mechanism that\n\n618\n00:39:35,820 --> 00:39:40,110\ngives you the best modularity,\ngives you all of the known\n\n619\n00:39:40,110 --> 00:39:45,590\nmodularity mechanisms.\n\n620\n00:39:45,590 --> 00:39:48,248\nWell, I suppose it's time for\nthe next break, thank you.\n\n621\n00:39:48,248 --> 00:40:41,871\n[MUSIC PLAYING]\n\n622\n00:40:41,871 --> 00:40:43,690\nPROFESSOR: Well, yesterday\nwhen you learned about\n\n623\n00:40:43,690 --> 00:40:52,110\nstreams, Hal worried to you\nabout the order of evaluation\n\n624\n00:40:52,110 --> 00:40:55,420\nand delayed arguments\nto procedures.\n\n625\n00:40:55,420 --> 00:41:00,620\nThe way we played with streams\nyesterday, it was the\n\n626\n00:41:00,620 --> 00:41:07,170\nresponsibility of the caller and\nthe callee to both agree\n\n627\n00:41:07,170 --> 00:41:12,180\nthat an argument was delayed,\nand the callee must force the\n\n628\n00:41:12,180 --> 00:41:15,250\nargument if it needs\nthe answer.\n\n629\n00:41:15,250 --> 00:41:18,400\nSo there had to be a lot of\nhand shaking between the\n\n630\n00:41:18,400 --> 00:41:26,100\ndesigner of a procedure and user\nof it over delayedness.\n\n631\n00:41:26,100 --> 00:41:29,670\nThat turns out, of course, to\nbe a fairly bad thing, it\n\n632\n00:41:29,670 --> 00:41:33,120\nworks all right with streams.\nBut as a general thing, what\n\n633\n00:41:33,120 --> 00:41:37,520\nyou want is an idea to have a\nlocus, a decision, a design\n\n634\n00:41:37,520 --> 00:41:40,580\ndecision in general, to have\na place where it's made,\n\n635\n00:41:40,580 --> 00:41:45,900\nexplicitly, and notated\nin a clear way.\n\n636\n00:41:45,900 --> 00:41:48,780\nAnd so it's not a very good\nidea to have to have an\n\n637\n00:41:48,780 --> 00:41:52,670\nagreement, between the person\nwho writes a procedure and the\n\n638\n00:41:52,670 --> 00:41:56,730\nperson who calls it, about such\ndetails as, maybe, the\n\n639\n00:41:56,730 --> 00:41:59,500\narguments of evaluation, the\norder of evaluation.\n\n640\n00:41:59,500 --> 00:42:00,750\nAlthough, that's not so bad.\n\n641\n00:42:00,750 --> 00:42:02,920\nI mean, we have other such\nagreements like,\n\n642\n00:42:02,920 --> 00:42:04,540\nthe input's a number.\n\n643\n00:42:04,540 --> 00:42:07,650\nBut it would be nice if only one\nof these guys could take\n\n644\n00:42:07,650 --> 00:42:11,020\nresponsibility, completely.\n\n645\n00:42:11,020 --> 00:42:15,510\nNow this is not a new idea.\n\n646\n00:42:15,510 --> 00:42:22,020\nALGOL 60 had two different ways\nof calling a procedure.\n\n647\n00:42:22,020 --> 00:42:25,590\nThe arguments could be passed\nby name or by value.\n\n648\n00:42:25,590 --> 00:42:31,110\nAnd what that meant was that a\nname argument was delayed.\n\n649\n00:42:31,110 --> 00:42:34,020\nThat when you passed an argument\nby name, that its\n\n650\n00:42:34,020 --> 00:42:39,620\nvalue would only be obtained if\nyou accessed that argument.\n\n651\n00:42:39,620 --> 00:42:42,290\n\n\n652\n00:42:42,290 --> 00:42:45,870\nSo what I'd like to do now is\nshow you, first of all, a\n\n653\n00:42:45,870 --> 00:42:48,040\nlittle bit about, again, we're\ngoing to make a modification\n\n654\n00:42:48,040 --> 00:42:50,320\nto a language.\n\n655\n00:42:50,320 --> 00:42:53,370\nIn this case, we're going\nto add a feature.\n\n656\n00:42:53,370 --> 00:42:56,900\nWe're going to add the feature\nof, by name parameters, if you\n\n657\n00:42:56,900 --> 00:43:00,430\nwill, or delayed parameters.\n\n658\n00:43:00,430 --> 00:43:05,580\nBecause, in fact, the default\nin our Lisp system is by the\n\n659\n00:43:05,580 --> 00:43:08,220\nvalue of a pointer.\n\n660\n00:43:08,220 --> 00:43:10,530\nA pointer is copied, but\nthe data structure it\n\n661\n00:43:10,530 --> 00:43:13,410\npoints at is not.\n\n662\n00:43:13,410 --> 00:43:17,580\nBut I'd like to, in fact, show\nyou is how you add name\n\n663\n00:43:17,580 --> 00:43:19,990\narguments as well.\n\n664\n00:43:19,990 --> 00:43:23,100\nNow again, why would we\nneed such a thing?\n\n665\n00:43:23,100 --> 00:43:26,930\nWell supposing we wanted to\ninvent certain kinds of what\n\n666\n00:43:26,930 --> 00:43:29,720\notherwise would be special\nforms, reserve words?\n\n667\n00:43:29,720 --> 00:43:32,180\nBut I'd rather not take\nup reserve words.\n\n668\n00:43:32,180 --> 00:43:36,360\nI want procedures that can\ndo things like if.\n\n669\n00:43:36,360 --> 00:43:39,420\nIf is special, or cond,\nor whatever it is.\n\n670\n00:43:39,420 --> 00:43:40,600\nIt's the same thing.\n\n671\n00:43:40,600 --> 00:43:43,080\nIt's special in that it\ndetermines whether or not to\n\n672\n00:43:43,080 --> 00:43:48,360\nevaluate the consequent or the\nalternative based on the value\n\n673\n00:43:48,360 --> 00:43:50,840\nof the predicate part\nof an expression.\n\n674\n00:43:50,840 --> 00:43:54,230\nSo taking the value of one thing\ndetermines whether or\n\n675\n00:43:54,230 --> 00:43:57,270\nnot to do something else.\n\n676\n00:43:57,270 --> 00:44:00,240\nWhereas all the procedures like\nplus, the ones that we\n\n677\n00:44:00,240 --> 00:44:05,900\ncan define right now, evaluate\nall of their arguments before\n\n678\n00:44:05,900 --> 00:44:08,670\napplication.\n\n679\n00:44:08,670 --> 00:44:11,750\nSo, for example, supposing I\nwish to be able to define\n\n680\n00:44:11,750 --> 00:44:19,452\nsomething like the reverse\nof if in terms of if.\n\n681\n00:44:19,452 --> 00:44:20,702\nCall it unless.\n\n682\n00:44:20,702 --> 00:44:24,890\n\n\n683\n00:44:24,890 --> 00:44:26,760\nWe've a predicate, a\nconsequent, and an\n\n684\n00:44:26,760 --> 00:44:28,190\nalternative.\n\n685\n00:44:28,190 --> 00:44:30,995\nNow what I would like to sort of\nbe able to do is say-- oh,\n\n686\n00:44:30,995 --> 00:44:32,440\nI'll do it in terms of cond.\n\n687\n00:44:32,440 --> 00:44:41,660\nCond, if not the predicate,\nthen take the consequent,\n\n688\n00:44:41,660 --> 00:44:45,350\notherwise, take the\nalternative.\n\n689\n00:44:45,350 --> 00:44:51,290\n\n\n690\n00:44:51,290 --> 00:44:54,320\nNow, what I'd like this to\nmean, is supposing I do\n\n691\n00:44:54,320 --> 00:44:56,920\nsomething like this.\n\n692\n00:44:56,920 --> 00:45:05,860\nI'd like this unless say if\nequals one, 0, then the answer\n\n693\n00:45:05,860 --> 00:45:11,350\nis two, otherwise, the quotient\nof one and 0.\n\n694\n00:45:11,350 --> 00:45:15,980\n\n\n695\n00:45:15,980 --> 00:45:20,170\nWhat I'd like that to mean is\nthe result of substituting\n\n696\n00:45:20,170 --> 00:45:23,450\nequal one, 0, and two, and\nthe quotient of one, 0\n\n697\n00:45:23,450 --> 00:45:25,580\nfor p, c, and a.\n\n698\n00:45:25,580 --> 00:45:28,750\nI'd like that to mean, and this\nis funny, I'd like it to\n\n699\n00:45:28,750 --> 00:45:40,940\ntransform into or mean cond\nnot equal one, 0, then the\n\n700\n00:45:40,940 --> 00:45:48,910\nresult is two, otherwise\nI want it to be the\n\n701\n00:45:48,910 --> 00:45:51,160\nquotient one and 0.\n\n702\n00:45:51,160 --> 00:45:54,480\n\n\n703\n00:45:54,480 --> 00:45:56,210\nNow, you know that if I\nwere to type this into\n\n704\n00:45:56,210 --> 00:45:59,970\nLisp, I'd get a two.\n\n705\n00:45:59,970 --> 00:46:02,910\nThere's no problem with that.\n\n706\n00:46:02,910 --> 00:46:05,940\nHowever, if I were to type this\ninto Lisp, because all\n\n707\n00:46:05,940 --> 00:46:09,590\nthe arguments are evaluated\nbefore I start, then I'm going\n\n708\n00:46:09,590 --> 00:46:10,840\nto get an error out of this.\n\n709\n00:46:10,840 --> 00:46:13,380\n\n\n710\n00:46:13,380 --> 00:46:16,130\nSo that if the substitutions\nwork at all, of course, I\n\n711\n00:46:16,130 --> 00:46:16,880\nwould get the right answer.\n\n712\n00:46:16,880 --> 00:46:20,160\nBut here's a case where the\nsubstitutions don't work.\n\n713\n00:46:20,160 --> 00:46:22,920\n\n\n714\n00:46:22,920 --> 00:46:23,860\nI don't get the wrong answer.\n\n715\n00:46:23,860 --> 00:46:24,670\nI get no answer.\n\n716\n00:46:24,670 --> 00:46:25,920\nI get an error.\n\n717\n00:46:25,920 --> 00:46:28,420\n\n\n718\n00:46:28,420 --> 00:46:31,860\nNow, however, I'd like to be\nable to make my definition so\n\n719\n00:46:31,860 --> 00:46:34,270\nthat this kind of thing works.\n\n720\n00:46:34,270 --> 00:46:36,010\nWhat I want to do\nis say something\n\n721\n00:46:36,010 --> 00:46:39,930\nspecial about c and a.\n\n722\n00:46:39,930 --> 00:46:42,715\nI want them to be delayed\nautomatically.\n\n723\n00:46:42,715 --> 00:46:46,300\n\n\n724\n00:46:46,300 --> 00:46:51,520\nI don't want them to be\nevaluated at the time I call.\n\n725\n00:46:51,520 --> 00:46:52,980\nSo I'm going to make a\ndeclaration, and then I'm\n\n726\n00:46:52,980 --> 00:46:55,600\ngoing to see how to implement\nsuch a declaration.\n\n727\n00:46:55,600 --> 00:46:58,870\nBut again, I want you to say\nto yourself, oh, this is an\n\n728\n00:46:58,870 --> 00:47:02,140\ninteresting kluge he's\nadding in here.\n\n729\n00:47:02,140 --> 00:47:05,750\nThe piles of kluges make\na big complicated mess.\n\n730\n00:47:05,750 --> 00:47:08,240\nAnd is this going to\nfoul up something\n\n731\n00:47:08,240 --> 00:47:10,120\nelse that might occur.\n\n732\n00:47:10,120 --> 00:47:13,860\nFirst of all, is it\nsyntactically unambiguous?\n\n733\n00:47:13,860 --> 00:47:16,120\nWell, it will be syntactically\nunambiguous with what we've\n\n734\n00:47:16,120 --> 00:47:17,840\nseen so far.\n\n735\n00:47:17,840 --> 00:47:21,670\nBut what I'm going to do may,\nin fact, cause trouble.\n\n736\n00:47:21,670 --> 00:47:25,450\nIt may be that the thing I had\nwill conflict with type\n\n737\n00:47:25,450 --> 00:47:28,700\ndeclarations I might want to add\nin the future for giving\n\n738\n00:47:28,700 --> 00:47:31,730\nsome system, some compiler or\nsomething, the ability to\n\n739\n00:47:31,730 --> 00:47:34,300\noptimize given the\ntypes are known.\n\n740\n00:47:34,300 --> 00:47:37,130\nOr it might conflict with other\ntypes of declarations I\n\n741\n00:47:37,130 --> 00:47:40,570\nmight want to make about\nthe formal parameters.\n\n742\n00:47:40,570 --> 00:47:44,520\nSo I'm not making a general\nmechanism here where I can add\n\n743\n00:47:44,520 --> 00:47:44,925\ndeclarations.\n\n744\n00:47:44,925 --> 00:47:46,750\nAnd I would like to be\nable to do that.\n\n745\n00:47:46,750 --> 00:47:51,010\nBut I don't want to talk\nabout that right now.\n\n746\n00:47:51,010 --> 00:47:53,680\nSo here I'm going to do, I'm\ngoing to build a kluge.\n\n747\n00:47:53,680 --> 00:47:57,050\n\n\n748\n00:47:57,050 --> 00:48:08,770\nSo we're going to define\nunless of a predicate--\n\n749\n00:48:08,770 --> 00:48:10,180\nand I'm going to call\nthese by name--\n\n750\n00:48:10,180 --> 00:48:12,810\n\n\n751\n00:48:12,810 --> 00:48:14,930\nthe consequent, and name\nthe alternative.\n\n752\n00:48:14,930 --> 00:48:19,850\n\n\n753\n00:48:19,850 --> 00:48:22,670\nHuh, huh--\n\n754\n00:48:22,670 --> 00:48:25,280\nI got caught in the corner.\n\n755\n00:48:25,280 --> 00:48:31,240\n\n\n756\n00:48:31,240 --> 00:48:37,165\nIf not p then the result\nis c, else--\n\n757\n00:48:37,165 --> 00:48:40,110\n\n\n758\n00:48:40,110 --> 00:48:41,360\nthat's what I'd like.\n\n759\n00:48:41,360 --> 00:48:44,670\n\n\n760\n00:48:44,670 --> 00:48:49,500\nWhere I can explicitly declare\ncertain of the parameters to\n\n761\n00:48:49,500 --> 00:48:51,650\nbe delayed, to be\ncomputed later.\n\n762\n00:48:51,650 --> 00:48:55,008\n\n\n763\n00:48:55,008 --> 00:48:57,910\nNow, this is actually a very\ncomplicated modification to an\n\n764\n00:48:57,910 --> 00:49:00,450\ninterpreter rather than\na simple one.\n\n765\n00:49:00,450 --> 00:49:05,270\nThe ones you saw before, dynamic\nbinding or adding\n\n766\n00:49:05,270 --> 00:49:07,630\nindefinite argument procedures,\n\n767\n00:49:07,630 --> 00:49:09,280\nis relatively simple.\n\n768\n00:49:09,280 --> 00:49:12,120\nBut this one changes\na basic strategy.\n\n769\n00:49:12,120 --> 00:49:18,070\nThe problem here is that our\ninterpreter, as written,\n\n770\n00:49:18,070 --> 00:49:24,420\nevaluates a combination by\nevaluating the procedure, the\n\n771\n00:49:24,420 --> 00:49:26,910\noperator producing the\nprocedure, and evaluating the\n\n772\n00:49:26,910 --> 00:49:31,410\noperands producing the\narguments, and then doing\n\n773\n00:49:31,410 --> 00:49:36,110\napply of the procedure\nto the arguments.\n\n774\n00:49:36,110 --> 00:49:40,540\nHowever, here, I don't want to\nevaluate the operands to\n\n775\n00:49:40,540 --> 00:49:44,640\nproduce the arguments until\nafter I examined the procedure\n\n776\n00:49:44,640 --> 00:49:46,810\nto see what the procedure's\ndeclarations look like.\n\n777\n00:49:46,810 --> 00:49:49,590\n\n\n778\n00:49:49,590 --> 00:49:52,680\nSo let's look at that.\n\n779\n00:49:52,680 --> 00:49:57,480\nHere we have a changed\nevaluator.\n\n780\n00:49:57,480 --> 00:50:02,110\nI'm starting with the simple\nlexical evaluator, not\n\n781\n00:50:02,110 --> 00:50:06,730\ndynamic, but we're going to have\nto do something sort of\n\n782\n00:50:06,730 --> 00:50:09,750\nsimilar in some ways.\n\n783\n00:50:09,750 --> 00:50:13,710\nBecause of the fact that,\nif I delay a procedure--\n\n784\n00:50:13,710 --> 00:50:15,790\nI'm sorry-- delay an argument\nto a procedure, I'm going to\n\n785\n00:50:15,790 --> 00:50:19,360\nhave to attach and environment\nto it.\n\n786\n00:50:19,360 --> 00:50:23,380\nRemember how Hal implemented\ndelay.\n\n787\n00:50:23,380 --> 00:50:28,650\nHal implemented delay as being\na procedure of no arguments\n\n788\n00:50:28,650 --> 00:50:31,180\nwhich does some expression.\n\n789\n00:50:31,180 --> 00:50:32,670\nThat's what delay of\nthe expression is.\n\n790\n00:50:32,670 --> 00:50:35,370\n\n\n791\n00:50:35,370 --> 00:50:36,620\n--of that expression.\n\n792\n00:50:36,620 --> 00:50:39,180\n\n\n793\n00:50:39,180 --> 00:50:40,950\nThis turned into something\nlike this.\n\n794\n00:50:40,950 --> 00:50:44,520\n\n\n795\n00:50:44,520 --> 00:50:47,760\nNow, however, if I evaluate a\nlambda expression, I have to\n\n796\n00:50:47,760 --> 00:50:49,010\ncapture the environment.\n\n797\n00:50:49,010 --> 00:50:51,410\n\n\n798\n00:50:51,410 --> 00:50:56,920\nThe reason why is because there\nare variables in there\n\n799\n00:50:56,920 --> 00:51:00,280\nwho's meaning I wish to derive\nfrom the context where this\n\n800\n00:51:00,280 --> 00:51:01,530\nwas written.\n\n801\n00:51:01,530 --> 00:51:04,010\n\n\n802\n00:51:04,010 --> 00:51:06,095\nSo that's why a lambda\ndoes the job.\n\n803\n00:51:06,095 --> 00:51:08,070\nIt's the right thing.\n\n804\n00:51:08,070 --> 00:51:17,070\nAnd such that the forcing of a\ndelayed expression was same\n\n805\n00:51:17,070 --> 00:51:21,090\nthing as calling that\nwith no arguments.\n\n806\n00:51:21,090 --> 00:51:24,100\nIt's just the opposite\nof this.\n\n807\n00:51:24,100 --> 00:51:28,120\nProducing an environment of the\ncall which is, in fact,\n\n808\n00:51:28,120 --> 00:51:31,713\nthe environment where this was\ndefined with an extra frame in\n\n809\n00:51:31,713 --> 00:51:33,132\nit that's empty.\n\n810\n00:51:33,132 --> 00:51:36,240\nI don't care about that.\n\n811\n00:51:36,240 --> 00:51:42,460\nWell, if we go back to this\nslide, since it's the case, if\n\n812\n00:51:42,460 --> 00:51:45,290\nwe look at this for a second,\neverything is the same as it\n\n813\n00:51:45,290 --> 00:51:51,980\nwas before except the case of\napplications or combinations.\n\n814\n00:51:51,980 --> 00:51:54,680\nAnd combinations are going\nto do two things.\n\n815\n00:51:54,680 --> 00:51:58,010\nOne, is I have to evaluate\nthe procedure--\n\n816\n00:51:58,010 --> 00:52:00,425\nforget the procedure-- by\nevaluating the operator.\n\n817\n00:52:00,425 --> 00:52:02,380\nThat's what you see\nright here.\n\n818\n00:52:02,380 --> 00:52:04,990\nI have to make sure that that's\ncurrent, that is not a\n\n819\n00:52:04,990 --> 00:52:08,530\ndelayed object, and evaluate\nthat to the point where it's\n\n820\n00:52:08,530 --> 00:52:10,730\nforced now.\n\n821\n00:52:10,730 --> 00:52:18,460\nAnd then I have to somehow apply\nthat to the operands.\n\n822\n00:52:18,460 --> 00:52:20,040\nBut I have to keep the\nenvironment, pass that\n\n823\n00:52:20,040 --> 00:52:21,530\nenvironmental along.\n\n824\n00:52:21,530 --> 00:52:23,710\nSo some of those operands\nI may have to delay.\n\n825\n00:52:23,710 --> 00:52:29,302\nI may have to attach that\nenvironment to those operands.\n\n826\n00:52:29,302 --> 00:52:32,990\nThis is a rather complicated\nthing happening here.\n\n827\n00:52:32,990 --> 00:52:34,240\nLooking at that in apply.\n\n828\n00:52:34,240 --> 00:52:36,400\n\n\n829\n00:52:36,400 --> 00:52:39,370\nApply, well it has a\nprimitive procedure\n\n830\n00:52:39,370 --> 00:52:42,610\nthing just like before.\n\n831\n00:52:42,610 --> 00:52:44,390\nBut the compound one is a\nlittle more interesting.\n\n832\n00:52:44,390 --> 00:52:47,250\n\n\n833\n00:52:47,250 --> 00:52:50,920\nI have to evaluate the body,\njust as before, in an\n\n834\n00:52:50,920 --> 00:52:56,010\nenvironment which is the result\nof binding some formal\n\n835\n00:52:56,010 --> 00:53:00,290\nparameters to arguments\nin the environment.\n\n836\n00:53:00,290 --> 00:53:01,530\nThat's true.\n\n837\n00:53:01,530 --> 00:53:03,070\nThe environment is the\none that comes from\n\n838\n00:53:03,070 --> 00:53:03,820\nthe procedure now.\n\n839\n00:53:03,820 --> 00:53:08,040\nIt's a lexical language,\nstatically bound.\n\n840\n00:53:08,040 --> 00:53:11,230\nHowever, one thing I have\nto do is strip off the\n\n841\n00:53:11,230 --> 00:53:12,960\ndeclarations to get the names\nof the variables.\n\n842\n00:53:12,960 --> 00:53:15,450\nThat's what this guy\ndoes, vnames.\n\n843\n00:53:15,450 --> 00:53:17,940\nAnd the other thing I have\nto do is process these\n\n844\n00:53:17,940 --> 00:53:21,770\ndeclarations, deciding which\nof these operands--\n\n845\n00:53:21,770 --> 00:53:24,150\nthat's the operands now, as\nopposed to the arguments--\n\n846\n00:53:24,150 --> 00:53:28,010\nwhich of these operands to\nevaluate, and which of them\n\n847\n00:53:28,010 --> 00:53:33,770\nare to be encapsulated in\ndelays of some sort.\n\n848\n00:53:33,770 --> 00:53:37,280\n\n\n849\n00:53:37,280 --> 00:53:40,720\nThe other thing you see here is\nthat we got a primitive, a\n\n850\n00:53:40,720 --> 00:53:43,170\nprimitive like plus, had better\n\n851\n00:53:43,170 --> 00:53:45,820\nget at the real operands.\n\n852\n00:53:45,820 --> 00:53:47,690\nSo here is a place where we're\ngoing to have to force them.\n\n853\n00:53:47,690 --> 00:53:49,306\nAnd we're going to look at what\nevlist is going to have\n\n854\n00:53:49,306 --> 00:53:51,340\nto do a bunch of forces.\n\n855\n00:53:51,340 --> 00:53:52,780\nSo we have two different\nkinds of evlist now.\n\n856\n00:53:52,780 --> 00:53:55,980\nWe have evlist and gevlist.\nGevlist is going to wrap\n\n857\n00:53:55,980 --> 00:53:59,870\ndelays around some things and\nforce others, evaluate others.\n\n858\n00:53:59,870 --> 00:54:07,900\nAnd this guy's going to do\nsome forcing of things.\n\n859\n00:54:07,900 --> 00:54:10,770\nJust looking at this a little\nbit, this is a game you must\n\n860\n00:54:10,770 --> 00:54:12,250\nplay for yourself, you know.\n\n861\n00:54:12,250 --> 00:54:14,870\nIt's not something that you're\ngoing to see all possible\n\n862\n00:54:14,870 --> 00:54:19,730\nvariations on an evaluator\ntalking to me.\n\n863\n00:54:19,730 --> 00:54:21,410\nWhat you have to do is\ndo this for yourself.\n\n864\n00:54:21,410 --> 00:54:24,610\nAnd after you feel this, you\nplay this a bit, you get to\n\n865\n00:54:24,610 --> 00:54:26,580\nsee all the possible design\ndecisions and what they might\n\n866\n00:54:26,580 --> 00:54:29,930\nmean, and how they interact\nwith each other.\n\n867\n00:54:29,930 --> 00:54:33,160\nSo what languages might\nhave in them.\n\n868\n00:54:33,160 --> 00:54:35,340\nAnd what are some of the\nconsistent sets that make a\n\n869\n00:54:35,340 --> 00:54:37,200\nlegitimate language.\n\n870\n00:54:37,200 --> 00:54:39,135\nWhereas what things are\ncomplicated kluges that are\n\n871\n00:54:39,135 --> 00:54:41,850\njust piles of junk.\n\n872\n00:54:41,850 --> 00:54:45,050\nSo evlist of course, over here,\njust as I said, is a\n\n873\n00:54:45,050 --> 00:54:49,450\nlist of operands which are going\nto be undelayed after\n\n874\n00:54:49,450 --> 00:54:50,750\nevaluation.\n\n875\n00:54:50,750 --> 00:54:53,600\nSo these are going to\nbe forced, whatever\n\n876\n00:54:53,600 --> 00:54:56,050\nthat's going to mean.\n\n877\n00:54:56,050 --> 00:54:58,490\nAnd gevlist, which is\nthe next thing--\n\n878\n00:54:58,490 --> 00:55:01,320\n\n\n879\n00:55:01,320 --> 00:55:04,040\nThank you.\n\n880\n00:55:04,040 --> 00:55:09,810\nWhat we see here, well there's\na couple of possibilities.\n\n881\n00:55:09,810 --> 00:55:13,750\nEither it's a normal, ordinary\nthing, a symbol sitting there\n\n882\n00:55:13,750 --> 00:55:18,020\nlike the predicate in the\nunless, and that's\n\n883\n00:55:18,020 --> 00:55:19,390\nwhat we have here.\n\n884\n00:55:19,390 --> 00:55:21,710\nIn which case, this is intended\nto be evaluated in\n\n885\n00:55:21,710 --> 00:55:23,340\napplicative order.\n\n886\n00:55:23,340 --> 00:55:25,630\nAnd it's, essentially, just\nwhat we had before.\n\n887\n00:55:25,630 --> 00:55:30,400\nIt's mapping eval down the\nlist. In other words, I\n\n888\n00:55:30,400 --> 00:55:35,690\nevaluate the first expression\nand continue gevlisting the\n\n889\n00:55:35,690 --> 00:55:37,900\nCDR of the expression\nin the environment.\n\n890\n00:55:37,900 --> 00:55:43,600\nHowever, it's possible that\nthis is a name parameter.\n\n891\n00:55:43,600 --> 00:55:47,320\nIf it's a name parameter, I want\nto put a delay in which\n\n892\n00:55:47,320 --> 00:55:53,480\ncombines that expression, which\nI'm calling by name,\n\n893\n00:55:53,480 --> 00:55:59,250\nwith the environment that's\navailable at this time and\n\n894\n00:55:59,250 --> 00:56:02,790\npassing that as the parameter.\n\n895\n00:56:02,790 --> 00:56:04,350\nAnd this is part of the\nmapping process\n\n896\n00:56:04,350 --> 00:56:05,600\nthat you see here.\n\n897\n00:56:05,600 --> 00:56:09,070\n\n\n898\n00:56:09,070 --> 00:56:12,040\nThe only other interesting\nplace in this\n\n899\n00:56:12,040 --> 00:56:14,700\ninterpreter is cond.\n\n900\n00:56:14,700 --> 00:56:16,440\nPeople tend to write this thing,\nand then they leave\n\n901\n00:56:16,440 --> 00:56:18,550\nthis one out.\n\n902\n00:56:18,550 --> 00:56:20,510\nThere's a place where\nyou have to force.\n\n903\n00:56:20,510 --> 00:56:25,260\nConditionals have to know\nwhether or not the answer is\n\n904\n00:56:25,260 --> 00:56:25,990\ntrue or false.\n\n905\n00:56:25,990 --> 00:56:28,550\nIt's like a primitive.\n\n906\n00:56:28,550 --> 00:56:31,890\nWhen you do a conditional,\nyou have to force.\n\n907\n00:56:31,890 --> 00:56:32,880\nNow, I'm not going to\nlook at any more\n\n908\n00:56:32,880 --> 00:56:34,350\nof this in any detail.\n\n909\n00:56:34,350 --> 00:56:36,750\nIt isn't very exciting.\n\n910\n00:56:36,750 --> 00:56:38,990\nAnd what's left is how\nyou make delays.\n\n911\n00:56:38,990 --> 00:56:42,680\nWell, delays are data structures\nwhich contain an\n\n912\n00:56:42,680 --> 00:56:44,840\nexpression, an environment,\nand a type on them.\n\n913\n00:56:44,840 --> 00:56:46,680\nAnd it says they're a thunk.\n\n914\n00:56:46,680 --> 00:56:50,100\nThat comes from ALGOL language,\nand it's claimed to\n\n915\n00:56:50,100 --> 00:56:52,970\nbe the sound of something\nbeing pushed on a stack.\n\n916\n00:56:52,970 --> 00:56:53,410\nI don't know.\n\n917\n00:56:53,410 --> 00:56:57,830\nI was not an ALGOLician or an\nALGOLite or whatever, so I\n\n918\n00:56:57,830 --> 00:56:58,740\ndon't know.\n\n919\n00:56:58,740 --> 00:57:00,270\nBut that's what was claimed.\n\n920\n00:57:00,270 --> 00:57:03,400\nAnd undelay is something which\nwill recursively undelay\n\n921\n00:57:03,400 --> 00:57:07,860\nthunks until the thunk becomes\nsomething which isn't a thunk.\n\n922\n00:57:07,860 --> 00:57:09,930\nThis is the way you implement\na call by name\n\n923\n00:57:09,930 --> 00:57:12,050\nlike thing in ALGOL.\n\n924\n00:57:12,050 --> 00:57:15,210\nAnd that's about all there is.\n\n925\n00:57:15,210 --> 00:57:16,460\nAre there any questions?\n\n926\n00:57:16,460 --> 00:57:26,840\n\n\n927\n00:57:26,840 --> 00:57:27,560\nAUDIENCE: Gerry?\n\n928\n00:57:27,560 --> 00:57:29,626\nPROFESSOR: Yes, Vesko?\n\n929\n00:57:29,626 --> 00:57:33,900\nAUDIENCE: I noticed you avoided\ncalling by name in the\n\n930\n00:57:33,900 --> 00:57:38,480\nprimitive procedures,\nI was wondering what\n\n931\n00:57:38,480 --> 00:57:39,350\ncause you have on that?\n\n932\n00:57:39,350 --> 00:57:40,070\nYou never need that?\n\n933\n00:57:40,070 --> 00:57:44,720\nPROFESSOR: Vesko is asking if\nit's ever reasonable to call a\n\n934\n00:57:44,720 --> 00:57:47,140\nprimitive procedure by name?\n\n935\n00:57:47,140 --> 00:57:49,270\nThe answer is, yes.\n\n936\n00:57:49,270 --> 00:57:51,680\nThere's one particular case\nwhere it's reasonable,\n\n937\n00:57:51,680 --> 00:57:52,930\nactually two.\n\n938\n00:57:52,930 --> 00:57:56,050\n\n\n939\n00:57:56,050 --> 00:57:59,250\nConstruction of a data structure\nlike cons where\n\n940\n00:57:59,250 --> 00:58:01,100\nmaking an array if you\nhave arrays with\n\n941\n00:58:01,100 --> 00:58:03,690\nany number of elements.\n\n942\n00:58:03,690 --> 00:58:07,440\nIt's unnecessary to evaluate\nthose arguments.\n\n943\n00:58:07,440 --> 00:58:10,180\nAll you need is promises to\nevaluate those arguments if\n\n944\n00:58:10,180 --> 00:58:11,160\nyou look at them.\n\n945\n00:58:11,160 --> 00:58:17,310\nIf I cons together two things,\nthen I could cons together the\n\n946\n00:58:17,310 --> 00:58:21,830\npromises just as easily as I can\ncons together the things.\n\n947\n00:58:21,830 --> 00:58:23,720\nAnd it's not even when\nI CAR CDR them that I\n\n948\n00:58:23,720 --> 00:58:24,840\nhave to look at them.\n\n949\n00:58:24,840 --> 00:58:26,150\nThat just gets out\nthe promises and\n\n950\n00:58:26,150 --> 00:58:28,260\npasses them to somebody.\n\n951\n00:58:28,260 --> 00:58:31,320\nThat's why the lambda calculus\ndefinition, the Alonzo Church\n\n952\n00:58:31,320 --> 00:58:34,420\ndefinition of CAR, CDR,\nand cons makes sense.\n\n953\n00:58:34,420 --> 00:58:36,630\nIt's because no work is done\nin CAR, CDR, and cons, it's\n\n954\n00:58:36,630 --> 00:58:40,760\njust shuffling data, it's just\nrouting, if you will.\n\n955\n00:58:40,760 --> 00:58:42,960\nHowever, the things that do\nhave to look at data are\n\n956\n00:58:42,960 --> 00:58:45,280\nthings like plus.\n\n957\n00:58:45,280 --> 00:58:47,910\nBecause they have a look at the\nbits that the numbers are\n\n958\n00:58:47,910 --> 00:58:50,220\nmade out of, unless they're\nlambda calculus\n\n959\n00:58:50,220 --> 00:58:52,460\nnumbers which are funny.\n\n960\n00:58:52,460 --> 00:58:54,630\nThey have to look at the bits\nto be able to crunch them\n\n961\n00:58:54,630 --> 00:58:55,880\ntogether to do the add.\n\n962\n00:58:55,880 --> 00:58:59,210\n\n\n963\n00:58:59,210 --> 00:59:03,280\nSo, in fact, data constructors,\ndata selectors,\n\n964\n00:59:03,280 --> 00:59:08,500\nand, in fact, things that\nside-effect data objects don't\n\n965\n00:59:08,500 --> 00:59:13,300\nneed to do any forcing in the\nlaziest possible interpreters.\n\n966\n00:59:13,300 --> 00:59:16,460\n\n\n967\n00:59:16,460 --> 00:59:18,700\nOn the other hand predicates\non data structures have to.\n\n968\n00:59:18,700 --> 00:59:21,710\n\n\n969\n00:59:21,710 --> 00:59:23,560\nIs this a pair?\n\n970\n00:59:23,560 --> 00:59:24,640\nOr is it a symbol?\n\n971\n00:59:24,640 --> 00:59:25,690\nWell, you better find out.\n\n972\n00:59:25,690 --> 00:59:26,940\nYou got to look at it then.\n\n973\n00:59:26,940 --> 00:59:30,300\n\n\n974\n00:59:30,300 --> 00:59:31,550\nAny other questions?\n\n975\n00:59:31,550 --> 00:59:40,050\n\n\n976\n00:59:40,050 --> 00:59:41,610\nOh, well, I suppose it's\ntime for a break.\n\n977\n00:59:41,610 --> 00:59:42,106\nThank you.\n\n978\n00:59:42,106 --> 01:00:02,950\n[MUSIC PLAYING]\n\n979\n01:00:02,950 --> 01:00:04,200\nand\n\n980\n01:00:04,200 --> 01:00:05,972\n\n"
  },
  {
    "path": "SrtEN/lec8a_512kb.mp4.srt",
    "content": "1\n00:00:00,000 --> 00:00:17,814\n[MUSIC PLAYING BY J.S. BACH]\n\n2\n00:00:17,814 --> 00:00:20,040\nPROFESSOR: The last time we\nbegan having a look at how\n\n3\n00:00:20,040 --> 00:00:22,132\nlanguages are constructed.\n\n4\n00:00:22,132 --> 00:00:26,050\nRemember the main point that an\nevaluator for, LISP, say,\n\n5\n00:00:26,050 --> 00:00:27,580\nhas two main elements.\n\n6\n00:00:27,580 --> 00:00:36,350\nThere is EVAL, and EVAL's job\nis to take in an expression\n\n7\n00:00:36,350 --> 00:00:43,820\nand an environment and turn that\ninto a procedure and some\n\n8\n00:00:43,820 --> 00:00:46,635\narguments and pass that\noff to APPLY.\n\n9\n00:00:46,635 --> 00:00:49,410\n\n\n10\n00:00:49,410 --> 00:00:52,250\nAnd APPLY takes the procedure\nin the arguments, turns that\n\n11\n00:00:52,250 --> 00:00:55,680\nback into, in a general case,\nanother expression to be\n\n12\n00:00:55,680 --> 00:00:58,280\nevaluated in another environment\nand passes that\n\n13\n00:00:58,280 --> 00:01:00,770\noff to EVAL, which passes it\nto APPLY, and there's this\n\n14\n00:01:00,770 --> 00:01:02,750\nwhole big circle where things\ngo around and around and\n\n15\n00:01:02,750 --> 00:01:05,519\naround until you get either to\nsome very primitive data or to\n\n16\n00:01:05,519 --> 00:01:07,740\na primitive procedure.\n\n17\n00:01:07,740 --> 00:01:12,080\nSee, what this cycle has to do\nwith is unwinding the means of\n\n18\n00:01:12,080 --> 00:01:15,020\ncombination and the means of\nabstraction in the language.\n\n19\n00:01:15,020 --> 00:01:17,870\nSo for instance, you have\na procedure in LISP-- a\n\n20\n00:01:17,870 --> 00:01:21,320\nprocedure is a general way of\nsaying, I want to be able to\n\n21\n00:01:21,320 --> 00:01:25,392\nevaluate this expression for\nany value of the arguments,\n\n22\n00:01:25,392 --> 00:01:27,670\nand that's sort of what's\ngoing on here.\n\n23\n00:01:27,670 --> 00:01:28,510\nThat's what APPLY does.\n\n24\n00:01:28,510 --> 00:01:30,770\nIt says the general thing coming\nin with the arguments\n\n25\n00:01:30,770 --> 00:01:33,380\nreduces to the expression that's\nthe body, and then if\n\n26\n00:01:33,380 --> 00:01:35,790\nthat's a compound expression\nor another procedure\n\n27\n00:01:35,790 --> 00:01:40,440\napplication, the thing will go\naround and around the circle.\n\n28\n00:01:40,440 --> 00:01:43,040\nAnyway, that's sort of the basic\nstructure of gee, pretty\n\n29\n00:01:43,040 --> 00:01:45,120\nmuch any interpreter.\n\n30\n00:01:45,120 --> 00:01:46,720\nThe other thing that you saw\nis once you have the\n\n31\n00:01:46,720 --> 00:01:49,080\ninterpreter in your hands, you\nhave all this power to start\n\n32\n00:01:49,080 --> 00:01:49,870\nplaying with the language.\n\n33\n00:01:49,870 --> 00:01:53,390\nSo you can make it dynamically\nscoped, or you can put in\n\n34\n00:01:53,390 --> 00:01:55,960\nnormal order evaluation, or you\ncan add new forms to the\n\n35\n00:01:55,960 --> 00:01:57,680\nlanguage, whatever you like.\n\n36\n00:01:57,680 --> 00:02:00,570\nOr more generally, there's this\nnotion of metalinguistic\n\n37\n00:02:00,570 --> 00:02:07,930\nabstraction, which says that\npart of your perspective as an\n\n38\n00:02:07,930 --> 00:02:09,970\nengineer, as a software\nengineer, but as an engineer\n\n39\n00:02:09,970 --> 00:02:15,270\nin general is that you can gain\ncontrol of complexity by\n\n40\n00:02:15,270 --> 00:02:18,010\ninventing new languages\nsometimes.\n\n41\n00:02:18,010 --> 00:02:22,830\nSee, one way to think about\ncomputer programming is that\n\n42\n00:02:22,830 --> 00:02:25,170\nit only incidentally has\nto do with getting a\n\n43\n00:02:25,170 --> 00:02:26,440\ncomputer to do something.\n\n44\n00:02:26,440 --> 00:02:29,220\nPrimarily what a computer\nprogram has to do with, it's a\n\n45\n00:02:29,220 --> 00:02:33,270\nway of expressing ideas with\ncommunicating ideas.\n\n46\n00:02:33,270 --> 00:02:36,300\nAnd sometimes when you want to\ncommunicate new kinds of\n\n47\n00:02:36,300 --> 00:02:39,770\nideas, you'd like to invent new\nmodes of expressing that.\n\n48\n00:02:39,770 --> 00:02:44,300\nWell, today we're going to apply\nthis framework to build\n\n49\n00:02:44,300 --> 00:02:45,730\na new language.\n\n50\n00:02:45,730 --> 00:02:48,140\nSee, once we have the basic idea\nof the interpreter, you\n\n51\n00:02:48,140 --> 00:02:50,830\ncan pretty much go build any\nlanguage that you like.\n\n52\n00:02:50,830 --> 00:02:54,370\nSo for example, we can go\noff and build Pascal.\n\n53\n00:02:54,370 --> 00:02:58,820\nAnd gee, we would worry about\nsyntax and parsing and various\n\n54\n00:02:58,820 --> 00:03:01,450\nkinds of compiler optimizations,\nand there are\n\n55\n00:03:01,450 --> 00:03:05,580\npeople who make honest livings\ndoing that, but at the level\n\n56\n00:03:05,580 --> 00:03:09,100\nof abstraction that we're\ntalking, a Pascal interpreter\n\n57\n00:03:09,100 --> 00:03:13,020\nwould not look very different at\nall from what you saw Gerry\n\n58\n00:03:13,020 --> 00:03:15,350\ndo last time.\n\n59\n00:03:15,350 --> 00:03:18,190\nInstead of that, we'll spend\ntoday building a really\n\n60\n00:03:18,190 --> 00:03:23,400\ndifferent language, a language\nthat encourages you to think\n\n61\n00:03:23,400 --> 00:03:26,980\nabout programming not in terms\nof procedures, but in a really\n\n62\n00:03:26,980 --> 00:03:29,090\ndifferent way.\n\n63\n00:03:29,090 --> 00:03:33,650\nAnd the lecture today is going\nto be at two levels\n\n64\n00:03:33,650 --> 00:03:34,810\nsimultaneously.\n\n65\n00:03:34,810 --> 00:03:37,210\nOn the one hand, I'm going to\nshow you what this language\n\n66\n00:03:37,210 --> 00:03:40,410\nlooks like, and on the other\nhand, I'll show you how it's\n\n67\n00:03:40,410 --> 00:03:41,010\nimplemented.\n\n68\n00:03:41,010 --> 00:03:43,250\nAnd we'll build an\nimplementation in LISP and see\n\n69\n00:03:43,250 --> 00:03:44,220\nhow that works.\n\n70\n00:03:44,220 --> 00:03:48,730\nAnd you should be drawing\nlessons on two levels.\n\n71\n00:03:48,730 --> 00:03:52,190\nThe first is to realize\njust how different a\n\n72\n00:03:52,190 --> 00:03:53,790\nlanguage can be.\n\n73\n00:03:53,790 --> 00:03:57,830\nSo if you think that the jump\nfrom Fortran to LISP is a big\n\n74\n00:03:57,830 --> 00:04:01,560\ndeal, you haven't seen\nanything yet.\n\n75\n00:04:01,560 --> 00:04:05,660\nAnd secondly, you'll see that\neven with such a very\n\n76\n00:04:05,660 --> 00:04:08,590\ndifferent language, which will\nturn out to not have\n\n77\n00:04:08,590 --> 00:04:12,260\nprocedures at all and not talk\nabout functions at all, there\n\n78\n00:04:12,260 --> 00:04:16,570\nwill still be this basic cycle\nof eval and apply that's\n\n79\n00:04:16,570 --> 00:04:19,170\nunwinds the means of combination\nand the means an\n\n80\n00:04:19,170 --> 00:04:20,950\nabstraction.\n\n81\n00:04:20,950 --> 00:04:24,430\nAnd then thirdly, as kind of a\nminor but elegant technical\n\n82\n00:04:24,430 --> 00:04:27,720\npoint, you'll see a nice\nuse of streams to avoid\n\n83\n00:04:27,720 --> 00:04:28,970\nbacktracking.\n\n84\n00:04:28,970 --> 00:04:32,330\n\n\n85\n00:04:32,330 --> 00:04:35,860\nOK, well, I said that this\nlanguage is very different.\n\n86\n00:04:35,860 --> 00:04:41,620\nTo explain that, let's go back\nto the very first idea that we\n\n87\n00:04:41,620 --> 00:04:44,710\ntalked about in this course, and\nthat was the idea of the\n\n88\n00:04:44,710 --> 00:04:48,780\ndistinction between the\ndeclarative knowledge of\n\n89\n00:04:48,780 --> 00:04:50,240\nmathematics--\n\n90\n00:04:50,240 --> 00:04:55,470\nthe definition of a square root\nas a mathematical truth--\n\n91\n00:04:55,470 --> 00:04:59,080\nand the idea that computer\nscience talks about the how to\n\n92\n00:04:59,080 --> 00:04:59,810\nknowledge--\n\n93\n00:04:59,810 --> 00:05:03,700\ncontrast that definition of\nsquare root with a program to\n\n94\n00:05:03,700 --> 00:05:05,970\ncompute a square root.\n\n95\n00:05:05,970 --> 00:05:08,042\nThat's where we started off.\n\n96\n00:05:08,042 --> 00:05:11,830\nWell, wouldn't it be great if\nyou could somehow bridge this\n\n97\n00:05:11,830 --> 00:05:16,030\ngap and make a programming\nlanguage which sort of did\n\n98\n00:05:16,030 --> 00:05:20,510\nthings, but you talked about\nit in terms of truth, in\n\n99\n00:05:20,510 --> 00:05:22,380\ndeclarative terms?\n\n100\n00:05:22,380 --> 00:05:24,110\nSo that would be a programming\nlanguage in\n\n101\n00:05:24,110 --> 00:05:27,690\nwhich you specify facts.\n\n102\n00:05:27,690 --> 00:05:28,880\nYou tell it what is.\n\n103\n00:05:28,880 --> 00:05:30,950\nYou say what is true.\n\n104\n00:05:30,950 --> 00:05:34,220\nAnd then when you want an\nanswer, somehow the language\n\n105\n00:05:34,220 --> 00:05:38,560\nhas built into it automatically\ngeneral kinds of\n\n106\n00:05:38,560 --> 00:05:41,200\nhow to knowledge so it can just\ntake your facts and it\n\n107\n00:05:41,200 --> 00:05:44,180\ncan evolve these methods on\nits on using the facts you\n\n108\n00:05:44,180 --> 00:05:46,200\ngave it and maybe some general\nrules of logic.\n\n109\n00:05:46,200 --> 00:05:49,330\n\n\n110\n00:05:49,330 --> 00:05:53,920\nSo for instance, I might go up\nto this program and start\n\n111\n00:05:53,920 --> 00:05:55,645\ntelling it some things.\n\n112\n00:05:55,645 --> 00:06:08,920\nSo I might tell it that the\nson of Adam is Abel.\n\n113\n00:06:08,920 --> 00:06:17,660\nAnd I might tell it that the\nson of Adam is Cain.\n\n114\n00:06:17,660 --> 00:06:24,670\nAnd I might tell it that the\nson of Cain is Enoch.\n\n115\n00:06:24,670 --> 00:06:27,502\n\n\n116\n00:06:27,502 --> 00:06:37,550\nAnd I might tell it that the son\nof Enoch is Irad, and all\n\n117\n00:06:37,550 --> 00:06:41,190\nthrough the rest of our chapter\nwhatever of Genesis,\n\n118\n00:06:41,190 --> 00:06:45,010\nwhich ends up ending in Adah, by\nthe way, and this shows the\n\n119\n00:06:45,010 --> 00:06:48,760\ngenealogy of Adah from Cain.\n\n120\n00:06:48,760 --> 00:06:52,520\nAnyway, once you tell\nit these facts, you\n\n121\n00:06:52,520 --> 00:06:53,510\nmight ask it things.\n\n122\n00:06:53,510 --> 00:06:58,560\nYou might go up to your language\nand say, who's the\n\n123\n00:06:58,560 --> 00:07:00,420\nson of Adam?\n\n124\n00:07:00,420 --> 00:07:03,480\nAnd you can very easily imagine\nhaving a little\n\n125\n00:07:03,480 --> 00:07:06,460\ngeneral purpose search program\nwhich would be able to go\n\n126\n00:07:06,460 --> 00:07:08,800\nthrough and in response to that\nsay, oh yeah, there are\n\n127\n00:07:08,800 --> 00:07:10,930\ntwo answers: the son of\nAdam is Abel and the\n\n128\n00:07:10,930 --> 00:07:14,140\nson of Adam is Cain.\n\n129\n00:07:14,140 --> 00:07:19,350\nOr you might say, based on the\nvery same facts, who is Cain\n\n130\n00:07:19,350 --> 00:07:21,950\nthe son of?\n\n131\n00:07:21,950 --> 00:07:25,520\nAnd then you can imagine\ngenerating another slightly\n\n132\n00:07:25,520 --> 00:07:29,510\ndifferent search program which\nwould be able to go through\n\n133\n00:07:29,510 --> 00:07:33,760\nand checked for who is\nCain, and son of, and\n\n134\n00:07:33,760 --> 00:07:35,890\ncome up with Adam.\n\n135\n00:07:35,890 --> 00:07:40,300\nOr you might say, what's\nthe relationship\n\n136\n00:07:40,300 --> 00:07:42,070\nbetween Cain and Enoch?\n\n137\n00:07:42,070 --> 00:07:46,340\nAnd again, a minor variant\non that search program.\n\n138\n00:07:46,340 --> 00:07:48,160\nYou could figure out that\nit said son of.\n\n139\n00:07:48,160 --> 00:07:52,880\n\n\n140\n00:07:52,880 --> 00:07:56,960\nBut even here in this very\nsimple example, what you see\n\n141\n00:07:56,960 --> 00:08:00,460\nis that a single fact, see, a\nsingle fact like the son of\n\n142\n00:08:00,460 --> 00:08:04,230\nAdam is Cain can be\nused to answer\n\n143\n00:08:04,230 --> 00:08:06,520\ndifferent kinds of questions.\n\n144\n00:08:06,520 --> 00:08:10,540\nYou can say, who's the son of,\nor you can say who's the son\n\n145\n00:08:10,540 --> 00:08:12,220\nof Adam, or you can say\nwhat's the relation\n\n146\n00:08:12,220 --> 00:08:12,970\nbetween Adam and Cain?\n\n147\n00:08:12,970 --> 00:08:17,370\nThose are different questions\nbeing run by different\n\n148\n00:08:17,370 --> 00:08:22,474\ntraditional procedures all\nbased on the same fact.\n\n149\n00:08:22,474 --> 00:08:24,960\nAnd that's going to be the\nessence of the power of this\n\n150\n00:08:24,960 --> 00:08:30,050\nprogramming style, that one\npiece of declarative knowledge\n\n151\n00:08:30,050 --> 00:08:33,150\ncan be used as the basis for\na lot of different kinds of\n\n152\n00:08:33,150 --> 00:08:36,440\nhow-to knowledge, as opposed\nto the kinds of procedures\n\n153\n00:08:36,440 --> 00:08:39,010\nwe're writing where you sort of\ntell it what input you're\n\n154\n00:08:39,010 --> 00:08:41,490\ngiving it and what\nanswer you want.\n\n155\n00:08:41,490 --> 00:08:43,710\nSo for instance, our square\nroot program can perfectly\n\n156\n00:08:43,710 --> 00:08:48,900\nwell answer the question, what's\nthe square root of 144?\n\n157\n00:08:48,900 --> 00:08:51,290\nBut in principle, the\nmathematical definition of\n\n158\n00:08:51,290 --> 00:08:52,830\nsquare root tells you\nother things.\n\n159\n00:08:52,830 --> 00:08:57,590\nLike it could say, what is\n17 the square root of?\n\n160\n00:08:57,590 --> 00:08:58,590\nAnd that would be have\nto be answered\n\n161\n00:08:58,590 --> 00:09:01,920\nby a different program.\n\n162\n00:09:01,920 --> 00:09:05,700\nSo the mathematical definition,\nor in general, the\n\n163\n00:09:05,700 --> 00:09:09,540\nfacts that you give it are\nsomehow unbiased as to what\n\n164\n00:09:09,540 --> 00:09:10,900\nthe question is.\n\n165\n00:09:10,900 --> 00:09:13,240\nWhereas the programs we tend to\nwrite specifically because\n\n166\n00:09:13,240 --> 00:09:15,230\nthey are how-to knowledge\ntend to be looking\n\n167\n00:09:15,230 --> 00:09:17,700\nfor a specific answer.\n\n168\n00:09:17,700 --> 00:09:19,530\nSo that's going to be one\ncharacteristic of what we're\n\n169\n00:09:19,530 --> 00:09:21,810\ntalking about.\n\n170\n00:09:21,810 --> 00:09:23,480\nWe can go on.\n\n171\n00:09:23,480 --> 00:09:26,420\nWe can imagine that we've\ngiven our language\n\n172\n00:09:26,420 --> 00:09:27,710\nsome sort of facts.\n\n173\n00:09:27,710 --> 00:09:30,020\nNow let's give it some\nrules of inference.\n\n174\n00:09:30,020 --> 00:09:35,100\nWe can say, for instance,\nif the--\n\n175\n00:09:35,100 --> 00:09:36,510\nmake up some syntax here--\n\n176\n00:09:36,510 --> 00:09:41,580\nif the son of x is y--\n\n177\n00:09:41,580 --> 00:09:45,650\nI'll put question marks to\nindicate variables here--\n\n178\n00:09:45,650 --> 00:10:01,800\nif the son of x is y and the\nson of y is z, then the\n\n179\n00:10:01,800 --> 00:10:09,320\ngrandson of x is z.\n\n180\n00:10:09,320 --> 00:10:15,370\nSo I can imagine telling my\nmachine that rule and then\n\n181\n00:10:15,370 --> 00:10:17,680\nbeing able to say, for\ninstance, who's\n\n182\n00:10:17,680 --> 00:10:20,610\nthe grandson of Adam?\n\n183\n00:10:20,610 --> 00:10:24,790\nOr who is Irad the\ngrandson of?\n\n184\n00:10:24,790 --> 00:10:28,080\nOr deduce all grandson\nrelationships you possibly can\n\n185\n00:10:28,080 --> 00:10:29,330\nfrom this information.\n\n186\n00:10:29,330 --> 00:10:31,220\n\n\n187\n00:10:31,220 --> 00:10:34,580\nWe can imagine somehow the\nlanguage knowing how to do\n\n188\n00:10:34,580 --> 00:10:35,830\nthat automatically.\n\n189\n00:10:35,830 --> 00:10:42,640\n\n\n190\n00:10:42,640 --> 00:10:45,200\nLet me give you maybe a little\nbit more concrete example.\n\n191\n00:10:45,200 --> 00:10:49,610\n\n\n192\n00:10:49,610 --> 00:10:53,700\nHere's a procedure that merges\ntwo sorted lists.\n\n193\n00:10:53,700 --> 00:11:01,370\nSo x and y are two, say, lists\nof numbers, lists of distinct\n\n194\n00:11:01,370 --> 00:11:04,780\nnumbers, if you like, that\nare in increasing order.\n\n195\n00:11:04,780 --> 00:11:08,560\nAnd what merge does is take\ntwo such lists and combine\n\n196\n00:11:08,560 --> 00:11:10,040\nthem into a list where\neverything's in increasing\n\n197\n00:11:10,040 --> 00:11:15,330\norder, and this is a pretty easy\nprograms that you ought\n\n198\n00:11:15,330 --> 00:11:16,390\nto be able to write.\n\n199\n00:11:16,390 --> 00:11:18,860\nIt says, if x is empty,\nthe answer is y.\n\n200\n00:11:18,860 --> 00:11:21,180\nIf y is empty, the\nanswer is x.\n\n201\n00:11:21,180 --> 00:11:22,990\nOtherwise, you compare the\nfirst two elements.\n\n202\n00:11:22,990 --> 00:11:25,540\nSo you pick out the first thing\nin x and the first thing\n\n203\n00:11:25,540 --> 00:11:31,060\nin y, and then depending on\nwhich of those first elements\n\n204\n00:11:31,060 --> 00:11:35,500\nis less, you stick the lower\none on to the result a\n\n205\n00:11:35,500 --> 00:11:40,150\nrecursively merging, either\nchopping the first one off x\n\n206\n00:11:40,150 --> 00:11:42,400\nor chopping the first\none off y.\n\n207\n00:11:42,400 --> 00:11:43,960\nThat's a standard\nkind of program.\n\n208\n00:11:43,960 --> 00:11:46,470\n\n\n209\n00:11:46,470 --> 00:11:48,620\nLet's look at the logic.\n\n210\n00:11:48,620 --> 00:11:51,660\nLet's forget about the program\nand look at the logic on which\n\n211\n00:11:51,660 --> 00:11:53,820\nthat procedure is based.\n\n212\n00:11:53,820 --> 00:11:56,860\nSee, there's some logic which\nsays, gee, if the first one is\n\n213\n00:11:56,860 --> 00:12:00,240\nless, then we get the answer by\nsticking something onto the\n\n214\n00:12:00,240 --> 00:12:03,350\nresult of recursively merging\nthe rest. So let's try and be\n\n215\n00:12:03,350 --> 00:12:05,420\nexplicit about what that\nlogic is that's\n\n216\n00:12:05,420 --> 00:12:08,430\nmaking the program work.\n\n217\n00:12:08,430 --> 00:12:10,130\nSo here's one piece.\n\n218\n00:12:10,130 --> 00:12:13,820\nHere's the piece of the program\nwhich recursively\n\n219\n00:12:13,820 --> 00:12:19,980\nchops down x if the first\nthing in x is smaller.\n\n220\n00:12:19,980 --> 00:12:22,030\nAnd if you want to be very\nexplicit about what the logic\n\n221\n00:12:22,030 --> 00:12:27,120\nis there, what's really going on\nis a deduction, which says,\n\n222\n00:12:27,120 --> 00:12:31,790\nif you know that some list, that\nwe'll call cdr of x, and\n\n223\n00:12:31,790 --> 00:12:40,480\ny merged to form z, and you know\nthat a is less than the\n\n224\n00:12:40,480 --> 00:12:47,570\nfirst thing in y, then you know\nthat if you put a onto\n\n225\n00:12:47,570 --> 00:12:55,820\nthe cdr of x, then that result\nand y merge to form a onto z.\n\n226\n00:12:55,820 --> 00:12:58,720\nAnd what that is, that's the\nunderlying piece of logic--\n\n227\n00:12:58,720 --> 00:13:01,620\nI haven't written it as a\nprogram, I wrote it a sort of\n\n228\n00:13:01,620 --> 00:13:05,480\ndeduction that's underneath this\nparticular clause that\n\n229\n00:13:05,480 --> 00:13:09,410\nsays we can use the\nrecursion there.\n\n230\n00:13:09,410 --> 00:13:11,910\nAnd then similar, here's\nthe other clause\n\n231\n00:13:11,910 --> 00:13:14,000\njust to complete it.\n\n232\n00:13:14,000 --> 00:13:16,880\nThe other clause is based on\nthis piece of logic, which is\n\n233\n00:13:16,880 --> 00:13:19,460\nalmost the same and I won't go\nthrough it, and then there's\n\n234\n00:13:19,460 --> 00:13:22,730\nthe n cases where we tested for\nnull, and that's based on\n\n235\n00:13:22,730 --> 00:13:26,920\nthe idea that for any x, x and\nthe empty list merge to form\n\n236\n00:13:26,920 --> 00:13:30,740\nan x, or for any y, the empty\nlist and y merge to form y.\n\n237\n00:13:30,740 --> 00:13:33,360\n\n\n238\n00:13:33,360 --> 00:13:39,340\nOK, so there's a piece of\nprocedure and the logic on\n\n239\n00:13:39,340 --> 00:13:41,740\nwhich it's based.\n\n240\n00:13:41,740 --> 00:13:44,750\nAnd notice a big difference.\n\n241\n00:13:44,750 --> 00:13:51,050\nThe procedure looked\nlike this: it\n\n242\n00:13:51,050 --> 00:13:52,900\nsaid there was a box--\n\n243\n00:13:52,900 --> 00:13:55,410\nand all the things we've been\ndoing have the characteristic\n\n244\n00:13:55,410 --> 00:13:57,890\nwe have boxes and things going\nin and things going out--\n\n245\n00:13:57,890 --> 00:14:04,480\nthere was this box called merge,\nand in came an x and y,\n\n246\n00:14:04,480 --> 00:14:07,550\nand out came an answer.\n\n247\n00:14:07,550 --> 00:14:09,340\nThat's the character of the\nprocedure that we wrote.\n\n248\n00:14:09,340 --> 00:14:13,160\n\n\n249\n00:14:13,160 --> 00:14:14,660\nThese rules don't\nlook like that.\n\n250\n00:14:14,660 --> 00:14:17,620\nThese rules talk about\na relation.\n\n251\n00:14:17,620 --> 00:14:23,030\nThere's some sort of relation\nthat in those slides I called\n\n252\n00:14:23,030 --> 00:14:25,370\nmrege-to-form.\n\n253\n00:14:25,370 --> 00:14:29,200\nSo I said x and y merge\nto form z, and\n\n254\n00:14:29,200 --> 00:14:32,610\nsomehow this is a function.\n\n255\n00:14:32,610 --> 00:14:32,850\nRight?\n\n256\n00:14:32,850 --> 00:14:36,070\nThe answer is a function of x\nand y, and here what I have is\n\n257\n00:14:36,070 --> 00:14:39,720\na relation between\nthree things.\n\n258\n00:14:39,720 --> 00:14:43,120\nAnd I'm not going to specify\nwhich is the input and which\n\n259\n00:14:43,120 --> 00:14:44,200\nis the output.\n\n260\n00:14:44,200 --> 00:14:48,690\nAnd the reason I want to say\nthat is because in principle,\n\n261\n00:14:48,690 --> 00:14:51,300\nwe could use exactly those same\nlogic rules to answer a\n\n262\n00:14:51,300 --> 00:14:54,570\nlot of different questions.\n\n263\n00:14:54,570 --> 00:14:56,750\nSo we can say, for instance--\n\n264\n00:14:56,750 --> 00:14:59,050\nimagine giving our machine\nthose rules of logic.\n\n265\n00:14:59,050 --> 00:15:01,400\nNot the program, the underlying\nrules of logic.\n\n266\n00:15:01,400 --> 00:15:04,750\nThen it ought to be\nable to say--\n\n267\n00:15:04,750 --> 00:15:06,770\nwe could ask it--\n\n268\n00:15:06,770 --> 00:15:20,910\n1, 3, 7 and 2, 4, 8 merge\nto form what?\n\n269\n00:15:20,910 --> 00:15:23,880\nAnd that's a question it ought\nto be able to answer.\n\n270\n00:15:23,880 --> 00:15:26,480\nThat's exactly the same\nquestion that our list\n\n271\n00:15:26,480 --> 00:15:28,180\nprocedure answered.\n\n272\n00:15:28,180 --> 00:15:33,750\nBut the exact same rules should\nalso be able to answer\n\n273\n00:15:33,750 --> 00:15:41,760\na question like this: 1, 3, 7\nand what merged to form 1, 2,\n\n274\n00:15:41,760 --> 00:15:45,560\n3, 4, 7, 8?\n\n275\n00:15:45,560 --> 00:15:48,120\nThe same rules of logic can\nanswer this, although the\n\n276\n00:15:48,120 --> 00:15:50,880\nprocedure we wrote can't\nanswer that question.\n\n277\n00:15:50,880 --> 00:15:56,070\nOr we might be able to\nsay what and what\n\n278\n00:15:56,070 --> 00:16:07,900\nelse merge to form--\n\n279\n00:16:07,900 --> 00:16:13,780\nwhat and what else merge to\nform 1, 2, 3, 4, 7, 8?\n\n280\n00:16:13,780 --> 00:16:16,320\nAnd the thing should be able\nto go through, if it really\n\n281\n00:16:16,320 --> 00:16:20,470\ncan apply that logic, and deduce\nall, whatever is, 2 to\n\n282\n00:16:20,470 --> 00:16:22,540\nthe sixth answers to\nthat question.\n\n283\n00:16:22,540 --> 00:16:25,600\n\n\n284\n00:16:25,600 --> 00:16:28,790\nIt could be 1 and the rest, or\nit could be 1, 2 and the rest.\n\n285\n00:16:28,790 --> 00:16:32,490\nOr it could be 1 and 3 and 7 and\nthe rest. There's a whole\n\n286\n00:16:32,490 --> 00:16:33,410\nbunch of answers.\n\n287\n00:16:33,410 --> 00:16:36,830\nAnd in principle, the\nlogic should be\n\n288\n00:16:36,830 --> 00:16:38,550\nenough to deduce that.\n\n289\n00:16:38,550 --> 00:16:44,540\nSo there are going to be two big\ndifferences in the kind of\n\n290\n00:16:44,540 --> 00:16:48,370\nprogram we're going to look\nat and not only list, but\n\n291\n00:16:48,370 --> 00:16:49,850\nessentially all the programming\nyou've probably\n\n292\n00:16:49,850 --> 00:16:54,150\ndone so far in pretty much any\nlanguage you can think of.\n\n293\n00:16:54,150 --> 00:16:57,620\nThe first is, we're not going\nto be computing functions.\n\n294\n00:16:57,620 --> 00:17:00,800\n\n\n295\n00:17:00,800 --> 00:17:03,770\nWe're not going to be talking\nabout things that take input\n\n296\n00:17:03,770 --> 00:17:04,410\nand output.\n\n297\n00:17:04,410 --> 00:17:06,890\nWe're going to be talking\nabout relations.\n\n298\n00:17:06,890 --> 00:17:09,180\nAnd that means in principle,\nthese relations don't have\n\n299\n00:17:09,180 --> 00:17:11,089\ndirectionality.\n\n300\n00:17:11,089 --> 00:17:14,569\nSo the knowledge that you\nspecify to answer this\n\n301\n00:17:14,569 --> 00:17:19,220\nquestion, that same knowledge\nshould also allow you to\n\n302\n00:17:19,220 --> 00:17:21,345\nanswer these other questions\nand conversely.\n\n303\n00:17:21,345 --> 00:17:26,310\n\n\n304\n00:17:26,310 --> 00:17:30,590\nAnd the second issue is that\nsince we're talking about\n\n305\n00:17:30,590 --> 00:17:33,150\nrelations, these\nrelations don't\n\n306\n00:17:33,150 --> 00:17:35,610\nnecessarily have one answer.\n\n307\n00:17:35,610 --> 00:17:37,480\nSo that third question down\nthere doesn't have a\n\n308\n00:17:37,480 --> 00:17:39,415\nparticular answer, it has a\nwhole bunch of answers.\n\n309\n00:17:39,415 --> 00:17:42,270\n\n\n310\n00:17:42,270 --> 00:17:44,640\nWell, that's where\nwe're going.\n\n311\n00:17:44,640 --> 00:17:48,620\nThis style of programming, by\nthe way, is called logic\n\n312\n00:17:48,620 --> 00:17:51,310\nprogramming, for kind\nof obvious reasons.\n\n313\n00:17:51,310 --> 00:17:56,160\n\n\n314\n00:17:56,160 --> 00:18:02,440\nAnd people who do logic\nprogramming say that-- they\n\n315\n00:18:02,440 --> 00:18:04,150\nhave this little phrase-- they\nsay the point of logic\n\n316\n00:18:04,150 --> 00:18:10,190\nprogramming is that you use\nlogic to express what is true,\n\n317\n00:18:10,190 --> 00:18:15,190\nyou use logic to check whether\nsomething is true, and you use\n\n318\n00:18:15,190 --> 00:18:19,200\nlogic to find out\nwhat is true.\n\n319\n00:18:19,200 --> 00:18:23,300\nThe best known logic programming\nlanguage, as you\n\n320\n00:18:23,300 --> 00:18:25,780\nprobably know, is\ncalled Prolog.\n\n321\n00:18:25,780 --> 00:18:31,010\nThe language that we're going\nto implement this morning is\n\n322\n00:18:31,010 --> 00:18:33,110\nsomething we call the query\nlanguage, and it essentially\n\n323\n00:18:33,110 --> 00:18:35,320\nhas the essence of prologue.\n\n324\n00:18:35,320 --> 00:18:38,340\nIt can do about the same stuff,\nalthough it's a lot\n\n325\n00:18:38,340 --> 00:18:42,390\nslower because we're going to\nimplement it in LISP rather\n\n326\n00:18:42,390 --> 00:18:44,210\nthan building a particular\ncompiler.\n\n327\n00:18:44,210 --> 00:18:47,510\nWe're going to interpret it on\ntop of the LISP interpreter.\n\n328\n00:18:47,510 --> 00:18:48,950\nBut other than that,\nit can do about the\n\n329\n00:18:48,950 --> 00:18:49,750\nsame stuff as prolog.\n\n330\n00:18:49,750 --> 00:18:52,160\nIt has about the same power\nand about the same\n\n331\n00:18:52,160 --> 00:18:54,696\nlimitations.\n\n332\n00:18:54,696 --> 00:18:56,120\nAll right, let's break\nfor question.\n\n333\n00:18:56,120 --> 00:19:00,040\n\n\n334\n00:19:00,040 --> 00:19:04,010\nSTUDENT: Yes, could you please\nrepeat what the three things\n\n335\n00:19:04,010 --> 00:19:06,720\nyou use logic programming\nto find?\n\n336\n00:19:06,720 --> 00:19:09,120\nIn other words, to find what is\ntrue, learn what is true--\n\n337\n00:19:09,120 --> 00:19:09,840\nwhat is the?\n\n338\n00:19:09,840 --> 00:19:10,520\nPROFESSOR: Right.\n\n339\n00:19:10,520 --> 00:19:15,850\nSort of a logic programmer's\nlittle catechism.\n\n340\n00:19:15,850 --> 00:19:22,610\nYou use logic to express what\nis true, like these rules.\n\n341\n00:19:22,610 --> 00:19:26,120\nYou use logic to check whether\nsomething is true, and that's\n\n342\n00:19:26,120 --> 00:19:28,550\nthe kind of question I\ndidn't answer here.\n\n343\n00:19:28,550 --> 00:19:29,720\nI might say--\n\n344\n00:19:29,720 --> 00:19:33,620\nanother question I could put\ndown here is to say, is it\n\n345\n00:19:33,620 --> 00:19:41,400\ntrue that 1, 3, 7 and 2, 4, 8\nmerge to form 1, 2, 6, 10 And\n\n346\n00:19:41,400 --> 00:19:45,690\nthat same logic should\nbe enough to say no.\n\n347\n00:19:45,690 --> 00:19:49,190\nSo I use logic to check what is\ntrue, and then you also use\n\n348\n00:19:49,190 --> 00:19:50,480\nlogic to find out what's true.\n\n349\n00:19:50,480 --> 00:20:04,060\n\n\n350\n00:20:04,060 --> 00:20:04,570\nAll right.\n\n351\n00:20:04,570 --> 00:20:06,138\nLet's break.\n\n352\n00:20:06,138 --> 00:20:22,106\n[MUSIC PLAYING BY J.S. BACH]\n\n353\n00:20:22,106 --> 00:20:47,590\n[MUSIC ENDS]\n\n354\n00:20:47,590 --> 00:21:02,901\n[MUSIC PLAYING BY J.S. BACH]\n\n355\n00:21:02,901 --> 00:21:06,810\nPROFESSOR: OK, let's go ahead\nand take a look at this query\n\n356\n00:21:06,810 --> 00:21:10,520\nlanguage and operation.\n\n357\n00:21:10,520 --> 00:21:12,890\nThe first thing you might\nnotice, when I put up that\n\n358\n00:21:12,890 --> 00:21:15,390\nlittle biblical database, is\nthat it's nice to be able to\n\n359\n00:21:15,390 --> 00:21:18,900\nask this language questions\nin relation to some\n\n360\n00:21:18,900 --> 00:21:21,330\ncollection of facts.\n\n361\n00:21:21,330 --> 00:21:26,060\nSo let's start off and make a\nlittle collection of facts.\n\n362\n00:21:26,060 --> 00:21:31,700\nThis is a tiny fragment of\npersonnel records for a Boston\n\n363\n00:21:31,700 --> 00:21:34,440\nhigh tech company, and here's\na piece of the personnel\n\n364\n00:21:34,440 --> 00:21:37,500\nrecords of Ben Bitdiddle.\n\n365\n00:21:37,500 --> 00:21:41,470\nAnd Ben Bitdiddle is the\ncomputer wizard in this\n\n366\n00:21:41,470 --> 00:21:44,660\ncompany, he's the underpaid\ncomputer\n\n367\n00:21:44,660 --> 00:21:46,420\nwizard in this company.\n\n368\n00:21:46,420 --> 00:21:49,330\nHis supervisor is all\nOliver Warbucks,\n\n369\n00:21:49,330 --> 00:21:52,150\nand here's his address.\n\n370\n00:21:52,150 --> 00:21:55,220\nSo the format is we're giving\nthis information: job, salary,\n\n371\n00:21:55,220 --> 00:21:57,300\nsupervisor, address.\n\n372\n00:21:57,300 --> 00:21:59,250\nAnd there are some other\nconventions.\n\n373\n00:21:59,250 --> 00:22:01,570\nComputer here means that Ben\nworks in the computer\n\n374\n00:22:01,570 --> 00:22:03,590\ndivision, and his\nposition in the\n\n375\n00:22:03,590 --> 00:22:06,440\ncomputer division is wizard.\n\n376\n00:22:06,440 --> 00:22:07,580\nHere's somebody else.\n\n377\n00:22:07,580 --> 00:22:13,860\nAlyssa, Alyssa P. Hacker is a\ncomputer programmer, and she\n\n378\n00:22:13,860 --> 00:22:17,550\nworks for Ben, and she\nlives in Cambridge.\n\n379\n00:22:17,550 --> 00:22:19,990\nAnd there's another programmer\nwho works for Ben\n\n380\n00:22:19,990 --> 00:22:22,820\nwho's Lem E. Tweakit.\n\n381\n00:22:22,820 --> 00:22:26,330\nAnd there's a programmer\ntrainee, who is Louis\n\n382\n00:22:26,330 --> 00:22:30,100\nReasoner, and he works\nfor Alyssa.\n\n383\n00:22:30,100 --> 00:22:34,830\nAnd the big wheel of the company\ndoesn't work for\n\n384\n00:22:34,830 --> 00:22:37,010\nanybody, right?\n\n385\n00:22:37,010 --> 00:22:38,110\nThat's Oliver Warbucks.\n\n386\n00:22:38,110 --> 00:22:43,080\nAnyway, what we're going to do\nis ask questions about that\n\n387\n00:22:43,080 --> 00:22:44,971\nlittle world.\n\n388\n00:22:44,971 --> 00:22:47,410\nAnd that'll be a sample\nworld that we're\n\n389\n00:22:47,410 --> 00:22:48,660\ngoing to do logic in.\n\n390\n00:22:48,660 --> 00:22:51,420\n\n\n391\n00:22:51,420 --> 00:22:55,810\nLet me just write up here, for\nprobably the last time, what I\n\n392\n00:22:55,810 --> 00:22:57,600\nsaid is the very most important\nthing you should get\n\n393\n00:22:57,600 --> 00:23:00,760\nout of this course, and that\nis, when somebody tells you\n\n394\n00:23:00,760 --> 00:23:03,440\nabout a language,\nyou say, fine--\n\n395\n00:23:03,440 --> 00:23:15,050\nwhat are the primitives, what\nare the means of combination,\n\n396\n00:23:15,050 --> 00:23:18,480\nhow do you put the primitives\ntogether, and then how do you\n\n397\n00:23:18,480 --> 00:23:24,690\nabstract them, how do you\nabstract the compound pieces\n\n398\n00:23:24,690 --> 00:23:26,740\nso you can use them as pieces\nto make something more\n\n399\n00:23:26,740 --> 00:23:28,500\ncomplicated?\n\n400\n00:23:28,500 --> 00:23:31,440\nAnd we've said this a whole\nbunch of times already, but\n\n401\n00:23:31,440 --> 00:23:32,690\nit's worth saying again.\n\n402\n00:23:32,690 --> 00:23:36,210\n\n\n403\n00:23:36,210 --> 00:23:36,670\nLet's start.\n\n404\n00:23:36,670 --> 00:23:38,040\nThe primitives.\n\n405\n00:23:38,040 --> 00:23:41,660\nWell, there's really only one\nprimitive, and the primitive\n\n406\n00:23:41,660 --> 00:23:44,400\nin this language is\ncalled a query.\n\n407\n00:23:44,400 --> 00:23:46,810\nA primitive query.\n\n408\n00:23:46,810 --> 00:23:48,060\nLet's look at some primitive\nqueries.\n\n409\n00:23:48,060 --> 00:23:52,160\n\n\n410\n00:23:52,160 --> 00:23:53,100\nJob x.\n\n411\n00:23:53,100 --> 00:23:55,550\nWho is a computer programmer?\n\n412\n00:23:55,550 --> 00:24:04,700\nOr find every fact in the\ndatabase that matches job of\n\n413\n00:24:04,700 --> 00:24:06,640\nthe x is computer programmer.\n\n414\n00:24:06,640 --> 00:24:08,470\nAnd you see a little\nsyntax here.\n\n415\n00:24:08,470 --> 00:24:11,330\nThings without question marks\nare meant to be literal,\n\n416\n00:24:11,330 --> 00:24:13,940\nquestion mark x means that's a\nvariable, and this thing will\n\n417\n00:24:13,940 --> 00:24:18,110\nmatch, for example, the fact\nthat Alyssa P. Hacker is a\n\n418\n00:24:18,110 --> 00:24:21,930\ncomputer programmer, or\nx is Alyssa P. Hacker.\n\n419\n00:24:21,930 --> 00:24:26,820\n\n\n420\n00:24:26,820 --> 00:24:29,170\nOr more generally, I could\nhave something with two\n\n421\n00:24:29,170 --> 00:24:30,750\nvariables in it.\n\n422\n00:24:30,750 --> 00:24:39,530\nI could say, the job of x is\ncomputer something, and\n\n423\n00:24:39,530 --> 00:24:42,140\nthat'll match computer wizard.\n\n424\n00:24:42,140 --> 00:24:44,865\nSo there's something here: type\nwill match wizard, or\n\n425\n00:24:44,865 --> 00:24:49,390\ntype will match programmer,\nor x might match\n\n426\n00:24:49,390 --> 00:24:50,370\nvarious certain things.\n\n427\n00:24:50,370 --> 00:24:53,270\nSo there are, in our little\nexample, only three facts in\n\n428\n00:24:53,270 --> 00:24:55,150\nthat database that\nmatch that query.\n\n429\n00:24:55,150 --> 00:24:59,210\n\n\n430\n00:24:59,210 --> 00:25:04,910\nLet's see, just to show you some\nsyntax, the same query,\n\n431\n00:25:04,910 --> 00:25:11,490\nthis query doesn't match the job\nof x, doesn't match Lewis\n\n432\n00:25:11,490 --> 00:25:13,200\nReasoner, the reason for that\nis when I write something\n\n433\n00:25:13,200 --> 00:25:17,160\nhere, what I mean is that this\nis going to be a list of two\n\n434\n00:25:17,160 --> 00:25:22,730\nsymbols, of which the first is\nthe word computer, and the\n\n435\n00:25:22,730 --> 00:25:24,810\nsecond can be anything.\n\n436\n00:25:24,810 --> 00:25:28,130\nAnd Lewis's job description here\nhas three symbols, so it\n\n437\n00:25:28,130 --> 00:25:30,340\ndoesn't match.\n\n438\n00:25:30,340 --> 00:25:35,360\nAnd just to show you a little\nbit of syntax, the more\n\n439\n00:25:35,360 --> 00:25:37,920\ngeneral thing I might want to\ntype is a thing with a dot\n\n440\n00:25:37,920 --> 00:25:42,550\nhere, and this is just standard\nthis notation for\n\n441\n00:25:42,550 --> 00:25:46,560\nsaying, this is a list, of which\nthe first element is the\n\n442\n00:25:46,560 --> 00:25:49,350\nword computers, and THE\nREST, is something\n\n443\n00:25:49,350 --> 00:25:50,600\nthat I'll call type.\n\n444\n00:25:50,600 --> 00:25:53,730\n\n\n445\n00:25:53,730 --> 00:25:56,930\nSo this one would match.\n\n446\n00:25:56,930 --> 00:26:00,000\nLewis's job is computer\nprogrammer trainee, and type\n\n447\n00:26:00,000 --> 00:26:04,690\nhere would be the cdr of this\nlist. It would be the list\n\n448\n00:26:04,690 --> 00:26:06,960\nprogrammer trainee.\n\n449\n00:26:06,960 --> 00:26:08,410\nAnd that kind of dot\nprocessing is done\n\n450\n00:26:08,410 --> 00:26:10,460\nautomatically by the\nLISP reader.\n\n451\n00:26:10,460 --> 00:26:15,900\n\n\n452\n00:26:15,900 --> 00:26:17,760\nWell, let's actually try this.\n\n453\n00:26:17,760 --> 00:26:20,810\nThe idea is I'm going to type\nin queries in this language,\n\n454\n00:26:20,810 --> 00:26:23,630\nand answers will come out.\n\n455\n00:26:23,630 --> 00:26:25,180\nLet's look at this.\n\n456\n00:26:25,180 --> 00:26:30,000\nI can go up and say, who works\nin the computer division?\n\n457\n00:26:30,000 --> 00:26:39,730\nJob of x is computer dot y.\n\n458\n00:26:39,730 --> 00:26:42,562\nDoesn't matter what I call\nthe dummy variables.\n\n459\n00:26:42,562 --> 00:26:45,690\nIt says the answers to that, and\nit's found four answers.\n\n460\n00:26:45,690 --> 00:26:48,650\n\n\n461\n00:26:48,650 --> 00:26:51,380\nOr I can go off and say, tell\nme about everybody's\n\n462\n00:26:51,380 --> 00:26:52,505\nsupervisor.\n\n463\n00:26:52,505 --> 00:26:56,610\nSo I'll put in the query,\nthe primitive query, the\n\n464\n00:26:56,610 --> 00:26:59,390\nsupervisor of x is y.\n\n465\n00:26:59,390 --> 00:27:02,860\n\n\n466\n00:27:02,860 --> 00:27:05,540\nThere are all the supervisor\nrelationships I know.\n\n467\n00:27:05,540 --> 00:27:08,830\nOr I could go type in, who\nlives in Cambridge?\n\n468\n00:27:08,830 --> 00:27:20,670\nSo I can say, the address of x\nis Cambridge dot anything.\n\n469\n00:27:20,670 --> 00:27:25,090\n\n\n470\n00:27:25,090 --> 00:27:26,585\nAnd only one person lives\nin Cambridge.\n\n471\n00:27:26,585 --> 00:27:30,820\n\n\n472\n00:27:30,820 --> 00:27:32,170\nOK, so those are primitive\nqueries.\n\n473\n00:27:32,170 --> 00:27:34,460\nAnd you see what happens to\nbasic interaction with the\n\n474\n00:27:34,460 --> 00:27:38,140\nsystem is you type in a query,\nand it types out\n\n475\n00:27:38,140 --> 00:27:39,620\nall possible answers.\n\n476\n00:27:39,620 --> 00:27:43,100\nOr another way to say that: it\nfinds out all the possible\n\n477\n00:27:43,100 --> 00:27:45,330\nvalues of those variables x and\ny or t or whatever I've\n\n478\n00:27:45,330 --> 00:27:50,380\ncalled them, and it types out\nall ways of taking that query\n\n479\n00:27:50,380 --> 00:27:53,080\nand instantiating it--\n\n480\n00:27:53,080 --> 00:27:56,250\nremember that from the rule\nsystem lecture-- instantiates\n\n481\n00:27:56,250 --> 00:27:59,150\nthe query with all possible\nvalues for those variables and\n\n482\n00:27:59,150 --> 00:28:01,000\nthen types out all of them.\n\n483\n00:28:01,000 --> 00:28:02,370\nAnd there are a lot\nof ways you can\n\n484\n00:28:02,370 --> 00:28:03,350\narrange a logic language.\n\n485\n00:28:03,350 --> 00:28:06,010\nProlog, for instance, does\nsomething slightly different.\n\n486\n00:28:06,010 --> 00:28:08,980\nRather than typing back your\nquery, prolog would type out,\n\n487\n00:28:08,980 --> 00:28:12,230\nx equals this and y equals that,\nor x sequels this and y\n\n488\n00:28:12,230 --> 00:28:12,650\nequals that.\n\n489\n00:28:12,650 --> 00:28:16,430\nAnd that's a very surface level\nthing, you can decide\n\n490\n00:28:16,430 --> 00:28:19,070\nwhat you like.\n\n491\n00:28:19,070 --> 00:28:20,760\nOK.\n\n492\n00:28:20,760 --> 00:28:21,340\nAll right.\n\n493\n00:28:21,340 --> 00:28:23,390\nSo the primitives in\nthis language?\n\n494\n00:28:23,390 --> 00:28:24,570\nOnly one, right?\n\n495\n00:28:24,570 --> 00:28:27,230\nPrimitive query.\n\n496\n00:28:27,230 --> 00:28:31,360\n\n\n497\n00:28:31,360 --> 00:28:31,650\nOK.\n\n498\n00:28:31,650 --> 00:28:34,330\nMeans of combination.\n\n499\n00:28:34,330 --> 00:28:39,770\nLet's look at some compound\nqueries in this language.\n\n500\n00:28:39,770 --> 00:28:41,790\nHere's one.\n\n501\n00:28:41,790 --> 00:28:47,250\nThis one says, tell me all the\npeople who work in the\n\n502\n00:28:47,250 --> 00:28:49,810\ncomputer division.\n\n503\n00:28:49,810 --> 00:28:52,610\nTell me all the people who work\nin the computer division\n\n504\n00:28:52,610 --> 00:28:53,860\ntogether with their\nsupervisors.\n\n505\n00:28:53,860 --> 00:28:56,800\n\n\n506\n00:28:56,800 --> 00:29:00,220\nThe way I write that is\nthe query is and.\n\n507\n00:29:00,220 --> 00:29:04,920\nAnd the job of the x is computer\nsomething or other.\n\n508\n00:29:04,920 --> 00:29:07,560\nAnd job of x is computer\ndot y.\n\n509\n00:29:07,560 --> 00:29:11,650\nAnd the supervisor of x is z.\n\n510\n00:29:11,650 --> 00:29:13,570\nTell me all the people in\nthe computer division--\n\n511\n00:29:13,570 --> 00:29:16,460\nthat's this-- together with\ntheir supervisors.\n\n512\n00:29:16,460 --> 00:29:20,290\nAnd notice in this query I\nhave three variables--\n\n513\n00:29:20,290 --> 00:29:23,660\nx, y, and z.\n\n514\n00:29:23,660 --> 00:29:29,450\nAnd this x is supposed to\nbe the same as that x.\n\n515\n00:29:29,450 --> 00:29:31,560\nSo x works in the computer\ndivision, and the\n\n516\n00:29:31,560 --> 00:29:34,810\nsupervisor of x is z.\n\n517\n00:29:34,810 --> 00:29:37,250\nLet's try another one.\n\n518\n00:29:37,250 --> 00:29:39,005\nSo one means of combination\nis and.\n\n519\n00:29:39,005 --> 00:29:41,540\n\n\n520\n00:29:41,540 --> 00:29:45,790\nWho are all the people who\nmake more than $30,000?\n\n521\n00:29:45,790 --> 00:29:51,640\nAnd the salary of some person\np is some amount a.\n\n522\n00:29:51,640 --> 00:29:54,590\n\n\n523\n00:29:54,590 --> 00:30:00,600\nAnd when I go and look at a,\na is greater than $30,000.\n\n524\n00:30:00,600 --> 00:30:06,300\nAnd LISP value here is a little\npiece of interface that\n\n525\n00:30:06,300 --> 00:30:10,600\ninterfaces the query language\nto the underlying LISP.\n\n526\n00:30:10,600 --> 00:30:13,540\nAnd what the LISP value allows\nyou to do is call any LISP\n\n527\n00:30:13,540 --> 00:30:17,180\npredicate inside a query.\n\n528\n00:30:17,180 --> 00:30:19,110\nSo here I'm using the LISP\npredicate greater than, so I\n\n529\n00:30:19,110 --> 00:30:21,020\nsay LISP value.\n\n530\n00:30:21,020 --> 00:30:21,750\nThis I say and.\n\n531\n00:30:21,750 --> 00:30:28,190\nSo all the people whose salary\nis greater than $30,000.\n\n532\n00:30:28,190 --> 00:30:31,270\nOr here's a more complicated\none.\n\n533\n00:30:31,270 --> 00:30:36,150\nTell me all the people who work\nin the computer division\n\n534\n00:30:36,150 --> 00:30:38,560\nwho do not have a supervisor\nwho works in\n\n535\n00:30:38,560 --> 00:30:39,810\nthe computer division.\n\n536\n00:30:39,810 --> 00:30:42,790\n\n\n537\n00:30:42,790 --> 00:30:45,510\nand x works in the computer\ndivision.\n\n538\n00:30:45,510 --> 00:30:47,780\nThe job of x is computer\ndot y.\n\n539\n00:30:47,780 --> 00:30:55,570\nAnd it's not the case that both\nx has a supervisor z and\n\n540\n00:30:55,570 --> 00:30:59,620\nthe job of z is computer\nsomething or other.\n\n541\n00:30:59,620 --> 00:31:04,050\nAll right, so again, this x has\ngot to be that x, and this\n\n542\n00:31:04,050 --> 00:31:05,710\nz is going to be that z.\n\n543\n00:31:05,710 --> 00:31:09,390\n\n\n544\n00:31:09,390 --> 00:31:11,380\nAnd then you see another means\na combination, not.\n\n545\n00:31:11,380 --> 00:31:17,272\n\n\n546\n00:31:17,272 --> 00:31:20,880\nAll right, well, let's\nlook at that.\n\n547\n00:31:20,880 --> 00:31:22,400\nIt works the same way.\n\n548\n00:31:22,400 --> 00:31:33,110\nI can go up to the machine and\nsay and the job of the x is\n\n549\n00:31:33,110 --> 00:31:35,400\ncomputer dot y.\n\n550\n00:31:35,400 --> 00:31:38,480\n\n\n551\n00:31:38,480 --> 00:31:46,600\nAnd the supervisor of x is z.\n\n552\n00:31:46,600 --> 00:31:50,794\nAnd I typed that in\nlike a query.\n\n553\n00:31:50,794 --> 00:31:55,680\nAnd what it types back, what\nyou see are the queries I\n\n554\n00:31:55,680 --> 00:31:58,930\ntyped in instantiated by\nall possible answers.\n\n555\n00:31:58,930 --> 00:32:02,000\nAnd then you see there\nare a lot of answers.\n\n556\n00:32:02,000 --> 00:32:02,190\nAll right.\n\n557\n00:32:02,190 --> 00:32:05,230\nSo the means of combination\nin this language--\n\n558\n00:32:05,230 --> 00:32:07,550\nand this is why it's called\na logic language--\n\n559\n00:32:07,550 --> 00:32:09,800\nare logical operations.\n\n560\n00:32:09,800 --> 00:32:16,120\nMeans of combinations are things\nlike AND and NOT and\n\n561\n00:32:16,120 --> 00:32:18,490\nthere's one I didn't show\nyou, which is OR.\n\n562\n00:32:18,490 --> 00:32:24,310\nAnd then I showed you LISP\nvalue, which is not logic, of\n\n563\n00:32:24,310 --> 00:32:26,365\ncourse, but is a little special\nhack to interface that\n\n564\n00:32:26,365 --> 00:32:29,250\nto LISP so you can\nget more power.\n\n565\n00:32:29,250 --> 00:32:32,690\nThose are the means\nof combination.\n\n566\n00:32:32,690 --> 00:32:34,160\nOK, the means of abstraction.\n\n567\n00:32:34,160 --> 00:32:35,410\nWhat we'd like to do--\n\n568\n00:32:35,410 --> 00:32:38,330\n\n\n569\n00:32:38,330 --> 00:32:42,260\nlet's go back for second and\nlook at that last slide.\n\n570\n00:32:42,260 --> 00:32:45,010\nWe might like to take very\ncomplicated thing, the idea\n\n571\n00:32:45,010 --> 00:32:48,800\nthat someone works in a division\nbut does not have a\n\n572\n00:32:48,800 --> 00:32:52,400\nsupervisor in the division.\n\n573\n00:32:52,400 --> 00:32:56,090\nAnd as before, name that.\n\n574\n00:32:56,090 --> 00:32:58,800\nWell, if someone works in a\ndivision and does not have a\n\n575\n00:32:58,800 --> 00:33:00,950\nsupervisor who works in that\ndivision, that means that\n\n576\n00:33:00,950 --> 00:33:02,750\nperson is a big shot.\n\n577\n00:33:02,750 --> 00:33:08,370\nSo let's make a rule that\nsomebody x is a big shot in\n\n578\n00:33:08,370 --> 00:33:16,760\nsome department if x works in\nthe department and it's not\n\n579\n00:33:16,760 --> 00:33:19,610\nthe case that x has a supervisor\nwho works in the\n\n580\n00:33:19,610 --> 00:33:21,510\ndepartment.\n\n581\n00:33:21,510 --> 00:33:22,940\nSo this is our means\nof abstraction.\n\n582\n00:33:22,940 --> 00:33:24,190\nThis is a rule.\n\n583\n00:33:24,190 --> 00:33:26,220\n\n\n584\n00:33:26,220 --> 00:33:27,580\nAnd a rule has three parts.\n\n585\n00:33:27,580 --> 00:33:30,970\n\n\n586\n00:33:30,970 --> 00:33:33,450\nThe thing that says\nit's a rule.\n\n587\n00:33:33,450 --> 00:33:37,530\nAnd then there's the conclusion\nof the rule.\n\n588\n00:33:37,530 --> 00:33:40,000\nAnd then there's the\nbody of the rule.\n\n589\n00:33:40,000 --> 00:33:42,150\nAnd you can read this as a piece\nof logic which says, if\n\n590\n00:33:42,150 --> 00:33:46,940\nyou know that the body of the\nrule is true, then you can\n\n591\n00:33:46,940 --> 00:33:49,470\nconclude that the conclusion\nis true.\n\n592\n00:33:49,470 --> 00:33:52,640\nOr in order to deduce that\nx is a big shot in some\n\n593\n00:33:52,640 --> 00:33:57,480\ndepartment, it's enough\nto verify that.\n\n594\n00:33:57,480 --> 00:33:58,820\nSo that's what rules\nlook like.\n\n595\n00:33:58,820 --> 00:34:03,280\n\n\n596\n00:34:03,280 --> 00:34:07,180\nLet's go back and look at that\nmerge example that I did\n\n597\n00:34:07,180 --> 00:34:08,110\nbefore the break.\n\n598\n00:34:08,110 --> 00:34:11,610\nLet's look at how that would\nlook in terms of rules.\n\n599\n00:34:11,610 --> 00:34:14,030\nI'm going to take the logic I\nput up and just change it into\n\n600\n00:34:14,030 --> 00:34:15,500\na bunch of rules\nin this format.\n\n601\n00:34:15,500 --> 00:34:18,739\n\n\n602\n00:34:18,739 --> 00:34:19,350\nWe have a rule.\n\n603\n00:34:19,350 --> 00:34:21,710\nRemember, there was this\nthing merge-to-form.\n\n604\n00:34:21,710 --> 00:34:28,489\nThere is a rule that says,\nthe empty list and y\n\n605\n00:34:28,489 --> 00:34:29,620\nmerge to form y.\n\n606\n00:34:29,620 --> 00:34:30,870\nThis is the rule conclusion.\n\n607\n00:34:30,870 --> 00:34:33,210\n\n\n608\n00:34:33,210 --> 00:34:36,650\nAnd notice this particular\nrule has no body.\n\n609\n00:34:36,650 --> 00:34:40,010\nAnd in this language, a rule\nwith no body is something that\n\n610\n00:34:40,010 --> 00:34:41,239\nis always true.\n\n611\n00:34:41,239 --> 00:34:42,510\nYou can always assume\nthat's true.\n\n612\n00:34:42,510 --> 00:34:45,190\n\n\n613\n00:34:45,190 --> 00:34:47,530\nAnd there was another piece of\nlogic that said anything in\n\n614\n00:34:47,530 --> 00:34:49,460\nthe empty list merged to\nform the anything.\n\n615\n00:34:49,460 --> 00:34:50,900\nThat's this.\n\n616\n00:34:50,900 --> 00:34:55,510\nA rule y and the empty\nlist merge to form y.\n\n617\n00:34:55,510 --> 00:34:58,060\nThose corresponded to the two\nend cases in our merge\n\n618\n00:34:58,060 --> 00:35:00,890\nprocedure, but now we're talking\nabout logic, not about\n\n619\n00:35:00,890 --> 00:35:03,490\nprocedures.\n\n620\n00:35:03,490 --> 00:35:07,560\nThen we had another rule, which\nsaid if you know how\n\n621\n00:35:07,560 --> 00:35:09,830\nshorter things merge, you\ncan put them together.\n\n622\n00:35:09,830 --> 00:35:15,340\nSo this says, if you have a list\nx and y and z, and if you\n\n623\n00:35:15,340 --> 00:35:19,530\nwant to deduce that a dot x--\nthis means constant a onto x,\n\n624\n00:35:19,530 --> 00:35:23,160\nor a list whose first thing\nis a and whose rest is x--\n\n625\n00:35:23,160 --> 00:35:26,230\nso if you want to deduce that\na dot x and b dot y merge to\n\n626\n00:35:26,230 --> 00:35:27,480\nform b dot c--\n\n627\n00:35:27,480 --> 00:35:30,570\n\n\n628\n00:35:30,570 --> 00:35:34,070\nthat would say you merge these\ntwo lists a x and b y and\n\n629\n00:35:34,070 --> 00:35:37,680\nyou're going to get something\nthat starts with b--\n\n630\n00:35:37,680 --> 00:35:41,880\nyou can deduce that if you know\nthat it's the case both\n\n631\n00:35:41,880 --> 00:35:48,690\nthat a dot x and y merge to form\nz and a is larger than b.\n\n632\n00:35:48,690 --> 00:35:52,610\nSo when I merge them, b will\ncome first in the list. That's\n\n633\n00:35:52,610 --> 00:35:56,050\na little translation of the\nlogic rule that I wrote in\n\n634\n00:35:56,050 --> 00:35:57,960\npseudo-English before.\n\n635\n00:35:57,960 --> 00:35:59,870\nAnd then just for completeness,\n\n636\n00:35:59,870 --> 00:36:03,130\nhere's the other case.\n\n637\n00:36:03,130 --> 00:36:08,170\na dot x and b dot y merge to\nform a dot z if x and b dot y\n\n638\n00:36:08,170 --> 00:36:12,190\nmerged to form z and\nb is larger than a.\n\n639\n00:36:12,190 --> 00:36:15,610\nSo that's a little program that\nI've typed in in this\n\n640\n00:36:15,610 --> 00:36:17,416\nlanguage, and now let's\nlook at it run.\n\n641\n00:36:17,416 --> 00:36:21,900\n\n\n642\n00:36:21,900 --> 00:36:27,740\nSo I typed in the merge rules\nbefore, and I could use this\n\n643\n00:36:27,740 --> 00:36:28,510\nlike a procedure.\n\n644\n00:36:28,510 --> 00:36:39,590\nI could say merge to form\n1 and 3 and 2 and 7.\n\n645\n00:36:39,590 --> 00:36:43,330\nSo here I'm using it like\nthe LISP procedure.\n\n646\n00:36:43,330 --> 00:36:46,940\nNow it's going to think about\nthat for a while and apply\n\n647\n00:36:46,940 --> 00:36:48,190\nthese rules.\n\n648\n00:36:48,190 --> 00:36:50,780\n\n\n649\n00:36:50,780 --> 00:36:52,800\nSo it found an answer.\n\n650\n00:36:52,800 --> 00:36:55,370\nNow it's going to see if there\nare any other answers but it\n\n651\n00:36:55,370 --> 00:36:57,810\ndoesn't know a priori there's\nonly one answer.\n\n652\n00:36:57,810 --> 00:37:00,790\nSo it's sitting here checking\nall possibilities, and it\n\n653\n00:37:00,790 --> 00:37:01,970\nsays, no more.\n\n654\n00:37:01,970 --> 00:37:02,775\nDone.\n\n655\n00:37:02,775 --> 00:37:05,210\nSo there I've used those\nrules like a procedure.\n\n656\n00:37:05,210 --> 00:37:08,340\nOr remember the whole point is\nthat I can ask different kinds\n\n657\n00:37:08,340 --> 00:37:10,220\nof questions.\n\n658\n00:37:10,220 --> 00:37:24,590\nI could say merge to form, let's\nsee, how about 2 and a.\n\n659\n00:37:24,590 --> 00:37:29,440\nSome list of two elements which\nI know starts with 2,\n\n660\n00:37:29,440 --> 00:37:34,600\nand the other thing I don't\nknow, and x and some other\n\n661\n00:37:34,600 --> 00:37:39,510\nlist merge to form\na 1, 2, 3 and 4.\n\n662\n00:37:39,510 --> 00:37:42,760\n\n\n663\n00:37:42,760 --> 00:37:44,590\nSo now it's going to\nthink about that.\n\n664\n00:37:44,590 --> 00:37:45,840\nIt's got to find--\n\n665\n00:37:45,840 --> 00:37:48,070\n\n\n666\n00:37:48,070 --> 00:37:49,095\nso it found one possibility.\n\n667\n00:37:49,095 --> 00:37:53,830\nIt said a could be 3, and x\ncould be the list 1, 4.\n\n668\n00:37:53,830 --> 00:37:57,220\nAnd now, again, it's got to\ncheck because it doesn't a\n\n669\n00:37:57,220 --> 00:37:59,050\npriori know that there\naren't any other\n\n670\n00:37:59,050 --> 00:38:00,300\npossibilities going on.\n\n671\n00:38:00,300 --> 00:38:03,680\n\n\n672\n00:38:03,680 --> 00:38:10,660\nOr like I said, I could say\nsomething like merge to form,\n\n673\n00:38:10,660 --> 00:38:17,275\nlike, what and what else merge\nto form 1, 2, 3, 4, 5?\n\n674\n00:38:17,275 --> 00:38:24,340\n\n\n675\n00:38:24,340 --> 00:38:25,590\nNow it's going to think\nabout that.\n\n676\n00:38:25,590 --> 00:38:28,490\n\n\n677\n00:38:28,490 --> 00:38:30,310\nAnd there are a lot of answers\nthat it might get.\n\n678\n00:38:30,310 --> 00:38:35,180\n\n\n679\n00:38:35,180 --> 00:38:37,920\nAnd what you see is here you're\nreally paying the price\n\n680\n00:38:37,920 --> 00:38:39,170\nof slowness.\n\n681\n00:38:39,170 --> 00:38:42,210\n\n\n682\n00:38:42,210 --> 00:38:43,880\nAnd kind of for three reasons.\n\n683\n00:38:43,880 --> 00:38:47,630\nOne is that this language\nis doubly interpreted.\n\n684\n00:38:47,630 --> 00:38:50,100\nWhereas in a real\nimplementation, you would go\n\n685\n00:38:50,100 --> 00:38:52,190\ncompile this down to primitive\noperations.\n\n686\n00:38:52,190 --> 00:38:56,410\nThe other reason is that this\nparticular algorithm for\n\n687\n00:38:56,410 --> 00:38:58,380\nmerges is doubly recursive.\n\n688\n00:38:58,380 --> 00:39:01,020\nSo it's going to take\na very long time.\n\n689\n00:39:01,020 --> 00:39:06,710\nAnd eventually, this is going\nto go through and find--\n\n690\n00:39:06,710 --> 00:39:07,130\nfind what?\n\n691\n00:39:07,130 --> 00:39:08,730\nTwo to the fifth possible\nanswers.\n\n692\n00:39:08,730 --> 00:39:12,140\n\n\n693\n00:39:12,140 --> 00:39:14,830\nAnd you see they come out in\nsome fairly arbitrary order,\n\n694\n00:39:14,830 --> 00:39:17,100\ndepending on which order\nit's going to be\n\n695\n00:39:17,100 --> 00:39:20,160\ntrying these rules.\n\n696\n00:39:20,160 --> 00:39:21,530\nIn fact, what we're going\nto do when they edit the\n\n697\n00:39:21,530 --> 00:39:24,310\nvideotape is speed\nall this up.\n\n698\n00:39:24,310 --> 00:39:26,600\nDon't you like taking\nout these weights?\n\n699\n00:39:26,600 --> 00:39:28,250\nAnd don't you wish you could\ndo that in your demos?\n\n700\n00:39:28,250 --> 00:39:32,840\n\n\n701\n00:39:32,840 --> 00:39:34,260\nAnyway, it's still\ngrinding there.\n\n702\n00:39:34,260 --> 00:39:39,220\n\n\n703\n00:39:39,220 --> 00:39:41,170\nAnyway, there are 32\npossibilities--\n\n704\n00:39:41,170 --> 00:39:42,630\nwe won't wait for it to\nprint out all of them.\n\n705\n00:39:42,630 --> 00:39:47,850\n\n\n706\n00:39:47,850 --> 00:39:49,410\nOK, so the needs of abstraction\nin this\n\n707\n00:39:49,410 --> 00:39:50,660\nlanguage are rules.\n\n708\n00:39:50,660 --> 00:39:53,630\n\n\n709\n00:39:53,630 --> 00:39:57,410\nSo we take some bunch of things\nthat are put together\n\n710\n00:39:57,410 --> 00:40:00,350\nwith logic and we name them.\n\n711\n00:40:00,350 --> 00:40:02,080\nAnd you can think of\nthat as naming a\n\n712\n00:40:02,080 --> 00:40:03,410\nparticular pattern of logic.\n\n713\n00:40:03,410 --> 00:40:05,810\nOr you can think of that as\nsaying, if you want to deduce\n\n714\n00:40:05,810 --> 00:40:10,660\nsome conclusion, you can apply\nthose rules of logic.\n\n715\n00:40:10,660 --> 00:40:13,420\nAnd those are three elements\nof this language.\n\n716\n00:40:13,420 --> 00:40:15,670\nLet's break now, and then we'll\ntalk about how it's\n\n717\n00:40:15,670 --> 00:40:16,920\nactually implemented.\n\n718\n00:40:16,920 --> 00:40:22,747\n\n\n719\n00:40:22,747 --> 00:40:27,380\nSTUDENT: Does using LISP value\nprimitive or whatever\n\n720\n00:40:27,380 --> 00:40:31,770\ninterfere with your means to go\nboth directions on a query?\n\n721\n00:40:31,770 --> 00:40:33,530\nPROFESSOR: OK, that's a--\n\n722\n00:40:33,530 --> 00:40:37,840\nthe question is, does using LISP\nvalue interfere with the\n\n723\n00:40:37,840 --> 00:40:40,090\nability to go both directions\non the query?\n\n724\n00:40:40,090 --> 00:40:43,850\nWe haven't really talked about\nthe implementation yet, but\n\n725\n00:40:43,850 --> 00:40:46,890\nthe answer is, yes, it can.\n\n726\n00:40:46,890 --> 00:40:50,510\nIn general, as we'll\nsee at the end--\n\n727\n00:40:50,510 --> 00:40:53,330\nalthough I really won't\nto go into details--\n\n728\n00:40:53,330 --> 00:40:58,140\nit's fairly complicated,\nespecially when you use either\n\n729\n00:40:58,140 --> 00:40:59,780\nnot or LISP value--\n\n730\n00:40:59,780 --> 00:41:04,310\nor actually, if you use anything\nbesides only and, it\n\n731\n00:41:04,310 --> 00:41:07,350\nbecomes very complicated\nto say when\n\n732\n00:41:07,350 --> 00:41:08,700\nthese things will work.\n\n733\n00:41:08,700 --> 00:41:10,360\nThey won't work quite\nin all situations.\n\n734\n00:41:10,360 --> 00:41:14,300\nI'll talk about that at the end\nof the second half today.\n\n735\n00:41:14,300 --> 00:41:17,180\nBut the answer to your question\nis, yes, by dragging\n\n736\n00:41:17,180 --> 00:41:22,000\nin a lot more power from LISP\nvalue, you lose some of the\n\n737\n00:41:22,000 --> 00:41:24,170\nprincipal power of logic\nprogramming.\n\n738\n00:41:24,170 --> 00:41:28,090\nThat's a trade-off that\nyou have to make.\n\n739\n00:41:28,090 --> 00:41:30,390\nOK, let's take a break.\n\n740\n00:41:30,390 --> 00:41:49,844\n\n"
  },
  {
    "path": "SrtEN/lec8b_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:18,910\n\n\n1\n00:00:18,910 --> 00:00:20,900\nPROFESSOR: All right, well,\nwe've seen how the query\n\n2\n00:00:20,900 --> 00:00:22,502\nlanguage works.\n\n3\n00:00:22,502 --> 00:00:26,280\nNow, let's talk about how\nit's implemented.\n\n4\n00:00:26,280 --> 00:00:29,470\nYou already pretty much can\nguess what's going on there.\n\n5\n00:00:29,470 --> 00:00:32,810\nAt the bottom of it, there's\na pattern matcher.\n\n6\n00:00:32,810 --> 00:00:35,180\nAnd we looked at a pattern\nmatcher when we did the\n\n7\n00:00:35,180 --> 00:00:38,110\nrule-based control language.\n\n8\n00:00:38,110 --> 00:00:41,520\nJust to remind you, here are\nsome sample patterns.\n\n9\n00:00:41,520 --> 00:00:45,010\nThis is a pattern that will\nmatch any list of three things\n\n10\n00:00:45,010 --> 00:00:48,930\nof which the first is a and the\nsecond is c and the middle\n\n11\n00:00:48,930 --> 00:00:50,650\none can be anything.\n\n12\n00:00:50,650 --> 00:00:52,310\nSo in this little\npattern-matching syntax,\n\n13\n00:00:52,310 --> 00:00:54,050\nthere's only one distinction\nyou make.\n\n14\n00:00:54,050 --> 00:00:57,830\nThere's either literal things\nor variables, and variables\n\n15\n00:00:57,830 --> 00:00:59,080\nbegin with question mark.\n\n16\n00:00:59,080 --> 00:01:01,370\n\n\n17\n00:01:01,370 --> 00:01:04,900\nSo this matches any list of\nthree things of which the\n\n18\n00:01:04,900 --> 00:01:06,500\nfirst is a and the\nsecond is c.\n\n19\n00:01:06,500 --> 00:01:11,010\nThis one matches any list of\nthree things of which the\n\n20\n00:01:11,010 --> 00:01:12,530\nfirst is the symbol job.\n\n21\n00:01:12,530 --> 00:01:14,210\nThe second can be anything.\n\n22\n00:01:14,210 --> 00:01:16,750\nAnd the third is a list of two\nthings of which the first is\n\n23\n00:01:16,750 --> 00:01:20,480\nthe symbol computer and the\nsecond can be anything.\n\n24\n00:01:20,480 --> 00:01:25,100\nAnd this one, this next one\nmatches any list of three\n\n25\n00:01:25,100 --> 00:01:29,120\nthings, and the only difference\nis, here, the third\n\n26\n00:01:29,120 --> 00:01:32,280\nlist, the first is the symbol\ncomputer, and then there's\n\n27\n00:01:32,280 --> 00:01:36,430\nsome rest of the list. So this\nmeans two elements and this\n\n28\n00:01:36,430 --> 00:01:37,860\nmeans arbitrary number.\n\n29\n00:01:37,860 --> 00:01:39,996\nAnd our language implementation\nisn't even\n\n30\n00:01:39,996 --> 00:01:42,310\ngoing to have to worry about\nimplementing this dot because\n\n31\n00:01:42,310 --> 00:01:44,050\nthat's automatically done\nby Lisp's reader.\n\n32\n00:01:44,050 --> 00:01:48,340\n\n\n33\n00:01:48,340 --> 00:01:50,310\nRemember matchers also have\nsome consistency in them.\n\n34\n00:01:50,310 --> 00:01:53,010\nThis match is a list of\nthree things of which\n\n35\n00:01:53,010 --> 00:01:54,430\nthe first is a.\n\n36\n00:01:54,430 --> 00:01:56,280\nAnd the second and third can be\nanything, but they have to\n\n37\n00:01:56,280 --> 00:01:57,940\nbe the same thing.\n\n38\n00:01:57,940 --> 00:01:59,600\nThey're both called x.\n\n39\n00:01:59,600 --> 00:02:02,730\nAnd this matches a list of four\nthings of which the first\n\n40\n00:02:02,730 --> 00:02:05,590\nis the fourth and the second\nis the same as the third.\n\n41\n00:02:05,590 --> 00:02:09,685\nAnd this last one matches any\nlist that begins with a.\n\n42\n00:02:09,685 --> 00:02:14,040\nThe first thing is a, and the\nrest can be anything.\n\n43\n00:02:14,040 --> 00:02:16,750\nSo that's just a review of\npattern matcher syntax that\n\n44\n00:02:16,750 --> 00:02:18,780\nyou've already seen.\n\n45\n00:02:18,780 --> 00:02:21,490\nAnd remember, that's implemented\nby some procedure\n\n46\n00:02:21,490 --> 00:02:22,740\ncalled match.\n\n47\n00:02:22,740 --> 00:02:24,870\n\n\n48\n00:02:24,870 --> 00:02:35,695\nAnd match takes a pattern and\nsome data and a dictionary.\n\n49\n00:02:35,695 --> 00:02:43,200\n\n\n50\n00:02:43,200 --> 00:02:50,470\nAnd match asks the question is\nthere any way to match this\n\n51\n00:02:50,470 --> 00:02:55,170\npattern against this data object\nsubject to the bindings\n\n52\n00:02:55,170 --> 00:02:58,160\nthat are already in\nthis dictionary?\n\n53\n00:02:58,160 --> 00:03:03,200\nSo, for instance, if we're going\nto match the pattern x,\n\n54\n00:03:03,200 --> 00:03:18,080\ny, y, x against the data a, b,\nb, a subject to a dictionary,\n\n55\n00:03:18,080 --> 00:03:22,010\nthat says x equals a.\n\n56\n00:03:22,010 --> 00:03:25,260\nThen the matcher would say,\nyes, that's consistent.\n\n57\n00:03:25,260 --> 00:03:28,410\nThese match, and it's consistent\nwith what's in the\n\n58\n00:03:28,410 --> 00:03:30,320\ndictionary to say\nthat x equals a.\n\n59\n00:03:30,320 --> 00:03:34,810\nAnd the result of the match is\nthe extended dictionary that\n\n60\n00:03:34,810 --> 00:03:39,490\nsays x equals a and\ny equals b.\n\n61\n00:03:39,490 --> 00:03:42,860\nSo a matcher takes in pattern\ndata dictionary, puts out an\n\n62\n00:03:42,860 --> 00:03:45,590\nextended dictionary if it\nmatches, or if it doesn't\n\n63\n00:03:45,590 --> 00:03:46,840\nmatch, says that it fails.\n\n64\n00:03:46,840 --> 00:03:51,620\nSo, for example, if I use the\nsame pattern here, if I say\n\n65\n00:03:51,620 --> 00:04:02,450\nthis x, y, y, x match a, b, b, a\nwith the dictionary y equals\n\n66\n00:04:02,450 --> 00:04:06,665\na, then the matcher would\nput out fail.\n\n67\n00:04:06,665 --> 00:04:12,150\n\n\n68\n00:04:12,150 --> 00:04:15,100\nWell, you've already seen the\ncode for a pattern matcher so\n\n69\n00:04:15,100 --> 00:04:19,040\nI'm not going to go over it, but\nit's the same thing we've\n\n70\n00:04:19,040 --> 00:04:21,190\nbeen doing before.\n\n71\n00:04:21,190 --> 00:04:23,220\nYou saw that in the system\non rule-based control.\n\n72\n00:04:23,220 --> 00:04:24,950\nIt's essentially the\nsame matcher.\n\n73\n00:04:24,950 --> 00:04:28,415\nIn fact, I think the syntax is\na little bit simpler because\n\n74\n00:04:28,415 --> 00:04:30,490\nwe're not worrying about\narbitrary constants and\n\n75\n00:04:30,490 --> 00:04:31,400\nexpressions and things.\n\n76\n00:04:31,400 --> 00:04:32,690\nThere's just variables\nand constants.\n\n77\n00:04:32,690 --> 00:04:35,790\n\n\n78\n00:04:35,790 --> 00:04:39,610\nOK, well, given that, what's\na primitive query?\n\n79\n00:04:39,610 --> 00:04:42,970\n\n\n80\n00:04:42,970 --> 00:04:46,720\nPrimitive query is going to be\na rather complicated thing.\n\n81\n00:04:46,720 --> 00:04:48,100\nIt's going to be--\n\n82\n00:04:48,100 --> 00:05:03,490\nlet's think about the query\njob of x is d dot y.\n\n83\n00:05:03,490 --> 00:05:06,850\n\n\n84\n00:05:06,850 --> 00:05:09,400\nThat's a query we\nmight type in.\n\n85\n00:05:09,400 --> 00:05:11,095\nThat's going to be implemented\nin the system.\n\n86\n00:05:11,095 --> 00:05:14,270\n\n\n87\n00:05:14,270 --> 00:05:15,700\nWe'll think of it as\nthis little box.\n\n88\n00:05:15,700 --> 00:05:18,880\nHere's the primitive query.\n\n89\n00:05:18,880 --> 00:05:32,070\nWhat this little box is going\nto do is take in two streams\n\n90\n00:05:32,070 --> 00:05:34,030\nand put out a stream.\n\n91\n00:05:34,030 --> 00:05:37,310\nSo the shape of a primitive\nquery is that it's a thing\n\n92\n00:05:37,310 --> 00:05:41,120\nwhere two streams come in\nand one stream goes out.\n\n93\n00:05:41,120 --> 00:05:43,240\nWhat these streams are\ngoing to be is\n\n94\n00:05:43,240 --> 00:05:45,925\ndown here is the database.\n\n95\n00:05:45,925 --> 00:05:51,600\n\n\n96\n00:05:51,600 --> 00:05:56,180\nSo we imagine all the things\nin the database sort of\n\n97\n00:05:56,180 --> 00:06:00,330\nsitting there in a stream and\nthis thing sucks on them.\n\n98\n00:06:00,330 --> 00:06:02,800\nSo what are some things that\nmight be in the database?\n\n99\n00:06:02,800 --> 00:06:22,440\nOh, job of Alyssa is\nsomething and some\n\n100\n00:06:22,440 --> 00:06:25,770\nother job is something.\n\n101\n00:06:25,770 --> 00:06:29,800\nSo imagine all of the facts in\nthe database sitting there in\n\n102\n00:06:29,800 --> 00:06:32,040\nthe stream.\n\n103\n00:06:32,040 --> 00:06:33,400\nThat's what comes in here.\n\n104\n00:06:33,400 --> 00:06:38,510\nWhat comes in here is a stream\nof dictionaries.\n\n105\n00:06:38,510 --> 00:06:48,855\nSo one particular dictionary\nmight say y equals programmer.\n\n106\n00:06:48,855 --> 00:06:55,470\n\n\n107\n00:06:55,470 --> 00:06:59,170\nNow, what the query does when\nit gets in a dictionary from\n\n108\n00:06:59,170 --> 00:07:06,090\nthis stream, it finds all\npossible ways of matching the\n\n109\n00:07:06,090 --> 00:07:11,390\nquery against whatever is coming\nin from the database.\n\n110\n00:07:11,390 --> 00:07:15,420\nIt looks at the query as a\npattern, matches it against\n\n111\n00:07:15,420 --> 00:07:20,870\nany fact from the database or\nall possible ways of finding\n\n112\n00:07:20,870 --> 00:07:24,830\nand matching the database with\nrespect to this dictionary\n\n113\n00:07:24,830 --> 00:07:27,550\nthat's coming in.\n\n114\n00:07:27,550 --> 00:07:30,940\nSo for each fact in the\ndatabase, it calls the matcher\n\n115\n00:07:30,940 --> 00:07:35,110\nusing the pattern, fact,\nand dictionary.\n\n116\n00:07:35,110 --> 00:07:38,950\nAnd every time it gets a good\nmatch, it puts out the\n\n117\n00:07:38,950 --> 00:07:40,420\nextended dictionary.\n\n118\n00:07:40,420 --> 00:07:44,610\nSo, for example, if this one\ncomes in and it finds a match,\n\n119\n00:07:44,610 --> 00:07:48,710\nout will come a dictionary that\nin this case will have y\n\n120\n00:07:48,710 --> 00:07:52,970\nequals programmer and\nx equals something.\n\n121\n00:07:52,970 --> 00:07:56,740\n\n\n122\n00:07:56,740 --> 00:07:59,410\ny is programmer, x is\nsomething, and d\n\n123\n00:07:59,410 --> 00:08:01,430\nis whatever it found.\n\n124\n00:08:01,430 --> 00:08:03,520\nAnd that's all.\n\n125\n00:08:03,520 --> 00:08:07,240\nAnd, of course, it's going to\ntry this for every fact in the\n\n126\n00:08:07,240 --> 00:08:07,980\ndictionary.\n\n127\n00:08:07,980 --> 00:08:09,250\nSo it might find lots of them.\n\n128\n00:08:09,250 --> 00:08:14,110\nIt might find another one that\nsays y equals programmer and x\n\n129\n00:08:14,110 --> 00:08:16,355\nequals, and d equals.\n\n130\n00:08:16,355 --> 00:08:20,040\n\n\n131\n00:08:20,040 --> 00:08:22,750\nSo for one frame coming\nin, it might put out--\n\n132\n00:08:22,750 --> 00:08:24,600\nfor one dictionary coming in,\nit might put out a lot of\n\n133\n00:08:24,600 --> 00:08:30,470\ndictionaries, or it might\nput out none.\n\n134\n00:08:30,470 --> 00:08:34,620\nIt might have something\nthat wouldn't match\n\n135\n00:08:34,620 --> 00:08:39,320\nlike x equals FOO.\n\n136\n00:08:39,320 --> 00:08:42,730\nThis one might not match\nanything in which case nothing\n\n137\n00:08:42,730 --> 00:08:47,510\nwill go into this stream\ncorresponding to this frame.\n\n138\n00:08:47,510 --> 00:08:53,560\nOr what you might do is put in\nan empty frame, and an empty\n\n139\n00:08:53,560 --> 00:08:55,905\nframe says try matching\nall ways--\n\n140\n00:08:55,905 --> 00:08:59,930\n\n\n141\n00:08:59,930 --> 00:09:02,880\nfind all possible ways of\nmatching the query against\n\n142\n00:09:02,880 --> 00:09:05,470\nsomething in the database\nsubject to no previous\n\n143\n00:09:05,470 --> 00:09:07,570\nrestrictions.\n\n144\n00:09:07,570 --> 00:09:10,620\nAnd if you think about what that\nmeans, that's just the\n\n145\n00:09:10,620 --> 00:09:13,980\ncomputation that's done when you\ntype in a query right off.\n\n146\n00:09:13,980 --> 00:09:16,650\nIt tries to find all matches.\n\n147\n00:09:16,650 --> 00:09:19,370\nSo a primitive query sets\nup this mechanism.\n\n148\n00:09:19,370 --> 00:09:23,920\nAnd what the language does, when\nyou type in the query at\n\n149\n00:09:23,920 --> 00:09:27,440\nthe top level, it takes this\nmechanism, feeds in one single\n\n150\n00:09:27,440 --> 00:09:33,130\nempty dictionary, and then for\neach thing that comes out\n\n151\n00:09:33,130 --> 00:09:39,330\ntakes the original query and\ninstantiates the result with\n\n152\n00:09:39,330 --> 00:09:41,810\nall the different dictionaries,\nproducing a new\n\n153\n00:09:41,810 --> 00:09:44,990\nstream of instantiated\npatterns here.\n\n154\n00:09:44,990 --> 00:09:48,170\nAnd that's what gets printed\non the terminal.\n\n155\n00:09:48,170 --> 00:09:53,510\nThat's the basic mechanism\ngoing on there.\n\n156\n00:09:53,510 --> 00:09:56,870\nWell, why is that\nso complicated?\n\n157\n00:09:56,870 --> 00:10:00,310\nYou probably can think of a lot\nsimpler ways to arrange\n\n158\n00:10:00,310 --> 00:10:03,010\nthis match for a primitive query\nrather than having all\n\n159\n00:10:03,010 --> 00:10:04,725\nof these streams floating\naround.\n\n160\n00:10:04,725 --> 00:10:07,290\nAnd the answer is--\n\n161\n00:10:07,290 --> 00:10:10,860\nyou probably guess already.\n\n162\n00:10:10,860 --> 00:10:15,660\nThe answer is this thing extends\nelegantly to implement\n\n163\n00:10:15,660 --> 00:10:17,790\nthe means of combination.\n\n164\n00:10:17,790 --> 00:10:22,470\nSo, for instance, suppose I\ndon't only want to do this.\n\n165\n00:10:22,470 --> 00:10:27,230\nI don't want to say who to be\neverybody's job description.\n\n166\n00:10:27,230 --> 00:10:39,140\nSuppose I want to say AND the\njob of x is d dot y and the\n\n167\n00:10:39,140 --> 00:10:48,800\nsupervisor of x is z.\n\n168\n00:10:48,800 --> 00:10:52,550\nNow, supervisor of x is z is\ngoing to be another primitive\n\n169\n00:10:52,550 --> 00:10:57,830\nquery that has the same shape\nto take in a stream of data\n\n170\n00:10:57,830 --> 00:11:02,570\nobjects, a stream of initial\ndictionaries, which are the\n\n171\n00:11:02,570 --> 00:11:05,930\nrestrictions to try and use when\nyou match, and it's going\n\n172\n00:11:05,930 --> 00:11:08,700\nto put out a stream\nof dictionaries.\n\n173\n00:11:08,700 --> 00:11:11,680\nSo that's what this primitive\nquery looks like.\n\n174\n00:11:11,680 --> 00:11:12,910\nAnd how do I implement\nthe AND?\n\n175\n00:11:12,910 --> 00:11:13,450\nWell, it's simple.\n\n176\n00:11:13,450 --> 00:11:14,880\nI just hook them together.\n\n177\n00:11:14,880 --> 00:11:17,790\nI take the output of this one,\nand I put that to the\n\n178\n00:11:17,790 --> 00:11:19,830\ninput of that one.\n\n179\n00:11:19,830 --> 00:11:21,545\nAnd I take the dictionary\nhere and I fan it out.\n\n180\n00:11:21,545 --> 00:11:26,570\n\n\n181\n00:11:26,570 --> 00:11:29,610\nAnd then you see how that's\ngoing to work, because what's\n\n182\n00:11:29,610 --> 00:11:32,820\ngoing to happen is a frame will\nnow come in here, which\n\n183\n00:11:32,820 --> 00:11:37,920\nhas a binding for x, y, and d.\n\n184\n00:11:37,920 --> 00:11:40,030\nAnd then when this one gets\nit, it'll say, oh, gee,\n\n185\n00:11:40,030 --> 00:11:45,530\nsubject to these restrictions,\nwhich now already have values\n\n186\n00:11:45,530 --> 00:11:52,340\nin the dictionary for y and\nx and d, it looks in the\n\n187\n00:11:52,340 --> 00:11:56,080\ndatabase and says, gee, can I\nfind any supervisor facts?\n\n188\n00:11:56,080 --> 00:12:00,120\nAnd if it finds any, out will\ncome dictionaries which have\n\n189\n00:12:00,120 --> 00:12:09,340\nbindings for y and x\nand d and z now.\n\n190\n00:12:09,340 --> 00:12:12,070\n\n\n191\n00:12:12,070 --> 00:12:16,430\nAnd then notice that because the\nframes coming in here have\n\n192\n00:12:16,430 --> 00:12:19,440\nthese restrictions, that's the\nthing that assures that when\n\n193\n00:12:19,440 --> 00:12:26,470\nyou do the AND, this x will mean\nthe same thing as that x.\n\n194\n00:12:26,470 --> 00:12:30,520\nBecause by the time something\ncomes floating in here, x has\n\n195\n00:12:30,520 --> 00:12:34,460\na value that you have to match\nagainst consistently.\n\n196\n00:12:34,460 --> 00:12:36,250\nAnd then you remember from the\ncode from the matcher, there\n\n197\n00:12:36,250 --> 00:12:38,570\nwas something in the way the\nmatcher did dictionaries that\n\n198\n00:12:38,570 --> 00:12:40,710\narrange consistent matches.\n\n199\n00:12:40,710 --> 00:12:44,260\nSo there's AND.\n\n200\n00:12:44,260 --> 00:12:48,570\nThe important point to notice\nis the general shape.\n\n201\n00:12:48,570 --> 00:12:52,600\nLook at what happened: the AND\nof two queries, say, P and Q.\n\n202\n00:12:52,600 --> 00:13:00,465\nHere's P and Q. The AND\nof two queries, well,\n\n203\n00:13:00,465 --> 00:13:01,190\nit looks like this.\n\n204\n00:13:01,190 --> 00:13:05,120\nEach query takes in a stream\nfrom the database, a stream of\n\n205\n00:13:05,120 --> 00:13:10,230\ninputs, and puts out a\nstream of outputs.\n\n206\n00:13:10,230 --> 00:13:14,320\nAnd the important point to\nnotice is that if I draw a box\n\n207\n00:13:14,320 --> 00:13:26,500\naround this thing and say this\nis AND of P and Q, then that\n\n208\n00:13:26,500 --> 00:13:32,360\nbox has exactly the same\noverall shape.\n\n209\n00:13:32,360 --> 00:13:34,200\nIt's something that takes in\na stream from the database.\n\n210\n00:13:34,200 --> 00:13:37,020\nHere it's going to get fanned\nout inside, but from the\n\n211\n00:13:37,020 --> 00:13:38,160\noutside you don't see that.\n\n212\n00:13:38,160 --> 00:13:42,230\nIt takes an input stream and\nputs out an output stream.\n\n213\n00:13:42,230 --> 00:13:43,570\nSo this is AND.\n\n214\n00:13:43,570 --> 00:13:46,020\nAnd then similarly, OR\nwould look like this.\n\n215\n00:13:46,020 --> 00:13:48,030\nOR would--\n\n216\n00:13:48,030 --> 00:13:49,840\nalthough I didn't show\nyou examples of OR.\n\n217\n00:13:49,840 --> 00:13:55,970\nOR would say can I find all ways\nof matching P or Q. So I\n\n218\n00:13:55,970 --> 00:13:58,070\nhave P and Q. Each will\nhave their shape.\n\n219\n00:13:58,070 --> 00:14:04,460\n\n\n220\n00:14:04,460 --> 00:14:08,720\nAnd the way OR is implemented\nis I'll\n\n221\n00:14:08,720 --> 00:14:12,500\ntake my database stream.\n\n222\n00:14:12,500 --> 00:14:13,490\nI'll fan it out.\n\n223\n00:14:13,490 --> 00:14:19,870\nI'll put one into P and one into\nQ. I'll take my initial\n\n224\n00:14:19,870 --> 00:14:21,980\nquery stream coming\nin and fan it out.\n\n225\n00:14:21,980 --> 00:14:26,750\n\n\n226\n00:14:26,750 --> 00:14:29,460\nSo I'll look at all the answers\nI might get from P and\n\n227\n00:14:29,460 --> 00:14:32,950\nall the answers I might get\nfrom Q, and I'll put them\n\n228\n00:14:32,950 --> 00:14:35,280\nthrough some sort of thing that\nappends them or merges\n\n229\n00:14:35,280 --> 00:14:41,080\nthe result into one stream, and\nthat's what will come out.\n\n230\n00:14:41,080 --> 00:14:48,240\nAnd this whole thing from\nthe outside is OR.\n\n231\n00:14:48,240 --> 00:14:52,350\n\n\n232\n00:14:52,350 --> 00:14:55,540\nAnd again, you see it has the\nsame overall shape when looked\n\n233\n00:14:55,540 --> 00:14:56,790\nat from the outside.\n\n234\n00:14:56,790 --> 00:15:01,000\n\n\n235\n00:15:01,000 --> 00:15:02,020\nWhat's NOT?\n\n236\n00:15:02,020 --> 00:15:04,310\nNOT works kind of\nthe same way.\n\n237\n00:15:04,310 --> 00:15:14,690\nIf I have some query P, I take\nthe primitive query for P.\n\n238\n00:15:14,690 --> 00:15:19,600\nHere, I'm going to implement NOT\nP. And NOT's just going to\n\n239\n00:15:19,600 --> 00:15:20,720\nact as a filter.\n\n240\n00:15:20,720 --> 00:15:27,050\nI'll take in the database and\nmy original stream of\n\n241\n00:15:27,050 --> 00:15:32,210\ndictionaries coming in, and what\nNOT P will do is it will\n\n242\n00:15:32,210 --> 00:15:39,020\nfilter these guys.\n\n243\n00:15:39,020 --> 00:15:41,850\nAnd the way it will filter it,\nit will say when I get in a\n\n244\n00:15:41,850 --> 00:15:45,540\ndictionary here, I'll find all\nthe matches, and if I find\n\n245\n00:15:45,540 --> 00:15:47,460\nany, I'll throw it away.\n\n246\n00:15:47,460 --> 00:15:49,670\nAnd if I don't find any matches\nto something coming in\n\n247\n00:15:49,670 --> 00:15:52,500\nhere, I'll just pass\nthat through, so\n\n248\n00:15:52,500 --> 00:15:55,560\nNOT is a pure filter.\n\n249\n00:15:55,560 --> 00:15:56,890\nSo AND is--\n\n250\n00:15:56,890 --> 00:15:59,090\nthink of these sort\nof electoral\n\n251\n00:15:59,090 --> 00:15:59,980\nresistors or something.\n\n252\n00:15:59,980 --> 00:16:04,960\nAND is series combination and\nOR is parallel combination.\n\n253\n00:16:04,960 --> 00:16:06,780\nAnd then NOT is not going\nto extend any\n\n254\n00:16:06,780 --> 00:16:07,460\ndictionaries at all.\n\n255\n00:16:07,460 --> 00:16:08,750\nIt's just going to filter it.\n\n256\n00:16:08,750 --> 00:16:10,220\nIt's going to throw away\nthe ones for which it\n\n257\n00:16:10,220 --> 00:16:12,640\nfinds a way to match.\n\n258\n00:16:12,640 --> 00:16:14,540\nAnd list value is sort\nof the same way.\n\n259\n00:16:14,540 --> 00:16:16,600\nThe filter's a little\nmore complicated.\n\n260\n00:16:16,600 --> 00:16:19,640\nIt applies to predicate.\n\n261\n00:16:19,640 --> 00:16:22,610\nThe major point to notice here,\nand it's a major point\n\n262\n00:16:22,610 --> 00:16:24,980\nwe've looked at before, is\nthis idea of closure.\n\n263\n00:16:24,980 --> 00:16:28,490\n\n\n264\n00:16:28,490 --> 00:16:32,280\nThe things that we build as a\nmeans of combination have the\n\n265\n00:16:32,280 --> 00:16:36,470\nsame overall structure\nas the primitive\n\n266\n00:16:36,470 --> 00:16:39,750\nthings that we're combining.\n\n267\n00:16:39,750 --> 00:16:42,950\nSo the AND of two things when\nlooked at from the outside has\n\n268\n00:16:42,950 --> 00:16:44,630\nthe same shape.\n\n269\n00:16:44,630 --> 00:16:48,790\nAnd what that means is that this\nbox here could be an AND\n\n270\n00:16:48,790 --> 00:16:51,560\nor an OR or a NOT or something\nbecause it has the same shape\n\n271\n00:16:51,560 --> 00:16:54,950\nto interface to the\nlarger things.\n\n272\n00:16:54,950 --> 00:16:57,370\nIt's the same thing that allowed\nus to get complexity\n\n273\n00:16:57,370 --> 00:17:00,980\nin the Escher picture language\nor allows you to immediately\n\n274\n00:17:00,980 --> 00:17:04,170\nbuild up these complicated\nstructures just out of pairs.\n\n275\n00:17:04,170 --> 00:17:06,280\nIt's closure.\n\n276\n00:17:06,280 --> 00:17:10,920\nAnd that's the thing that\nallowed me to do what by now\n\n277\n00:17:10,920 --> 00:17:12,829\nyou took for granted when I\nsaid, gee, there's a query\n\n278\n00:17:12,829 --> 00:17:15,369\nwhich is AND of job and salary,\nand I said, oh,\n\n279\n00:17:15,369 --> 00:17:17,190\nthere's another one,\nwhich is AND of\n\n280\n00:17:17,190 --> 00:17:19,260\njob, a NOT of something.\n\n281\n00:17:19,260 --> 00:17:22,185\nThe fact that I can do that is\na direct consequence of this\n\n282\n00:17:22,185 --> 00:17:25,230\nclosure principle.\n\n283\n00:17:25,230 --> 00:17:29,520\nOK, let's break and\nthen we'll go on.\n\n284\n00:17:29,520 --> 00:17:30,710\nAUDIENCE: Where does the\ndictionary come from?\n\n285\n00:17:30,710 --> 00:17:35,140\nPROFESSOR: The dictionary\ncomes initially from\n\n286\n00:17:35,140 --> 00:17:36,030\nwhat you type in.\n\n287\n00:17:36,030 --> 00:17:40,390\nSo when you start this up, the\nfirst thing it does is set up\n\n288\n00:17:40,390 --> 00:17:41,090\nthis whole structure.\n\n289\n00:17:41,090 --> 00:17:45,000\nIt puts in one empty\ndictionary.\n\n290\n00:17:45,000 --> 00:17:48,560\nAnd if all you have is one\nprimitive query, then what\n\n291\n00:17:48,560 --> 00:17:50,330\nwill come out is a bunch\nof dictionaries with\n\n292\n00:17:50,330 --> 00:17:52,310\nthings filled in.\n\n293\n00:17:52,310 --> 00:17:55,330\nThe general situation that I\nhave here is when this is in\n\n294\n00:17:55,330 --> 00:17:59,710\nthe middle of some nest\nof combined things.\n\n295\n00:17:59,710 --> 00:18:02,380\n\n\n296\n00:18:02,380 --> 00:18:03,790\nLet's look at the picture\nover here.\n\n297\n00:18:03,790 --> 00:18:06,730\nThis supervisor query gets\nin some dictionary.\n\n298\n00:18:06,730 --> 00:18:08,730\nWhere did this one come from?\n\n299\n00:18:08,730 --> 00:18:13,480\nThis dictionary came from the\nfact that I'm looking at the\n\n300\n00:18:13,480 --> 00:18:16,260\noutput of this primitive\nquery.\n\n301\n00:18:16,260 --> 00:18:20,370\nSo maybe to be very specific,\nif I literally typed in just\n\n302\n00:18:20,370 --> 00:18:23,820\nthis query at the top level,\nthis AND, what would actually\n\n303\n00:18:23,820 --> 00:18:26,400\nhappen is it would build this\nstructure and start up this\n\n304\n00:18:26,400 --> 00:18:31,770\nwhole thing with one\nempty dictionary.\n\n305\n00:18:31,770 --> 00:18:33,850\nAnd now this one would process,\nand a whole bunch of\n\n306\n00:18:33,850 --> 00:18:38,640\ndictionaries would come out with\nx, y's and d's in them.\n\n307\n00:18:38,640 --> 00:18:40,190\nRun it through this one.\n\n308\n00:18:40,190 --> 00:18:42,160\nSo now that's the input\nto this one.\n\n309\n00:18:42,160 --> 00:18:45,040\nThis one would now put\nout some other stuff.\n\n310\n00:18:45,040 --> 00:18:50,110\nAnd if this itself were buried\nin some larger thing, like an\n\n311\n00:18:50,110 --> 00:18:54,860\nOR of something, then\nthat would go feed\n\n312\n00:18:54,860 --> 00:18:56,110\ninto the next one.\n\n313\n00:18:56,110 --> 00:18:58,560\n\n\n314\n00:18:58,560 --> 00:19:00,780\nSo you initially get only one\nempty dictionary when you\n\n315\n00:19:00,780 --> 00:19:03,380\nstart it, but as you're in the\nmiddle of processing these\n\n316\n00:19:03,380 --> 00:19:05,640\ncompounds things, that's where\nthese cascades of dictionaries\n\n317\n00:19:05,640 --> 00:19:07,660\nstart getting generated.\n\n318\n00:19:07,660 --> 00:19:11,030\nAUDIENCE: Dictionaries only\ncome about as a result of\n\n319\n00:19:11,030 --> 00:19:12,280\nusing the queries?\n\n320\n00:19:12,280 --> 00:19:15,120\n\n\n321\n00:19:15,120 --> 00:19:18,280\nOr do they become--\n\n322\n00:19:18,280 --> 00:19:23,220\ndo they stay someplace in space\nlike the database does?\n\n323\n00:19:23,220 --> 00:19:24,980\nAre these temporary items?\n\n324\n00:19:24,980 --> 00:19:28,030\nPROFESSOR: They're created\ntemporarily in the matcher.\n\n325\n00:19:28,030 --> 00:19:29,880\nReally, they're someplace\nin storage.\n\n326\n00:19:29,880 --> 00:19:32,430\nInitially, someone creates\na thing called the empty\n\n327\n00:19:32,430 --> 00:19:36,740\ndictionary that gets initially\nfed to this match procedure,\n\n328\n00:19:36,740 --> 00:19:39,150\nand then the match procedure\nbuilds some dictionaries, and\n\n329\n00:19:39,150 --> 00:19:40,950\nthey get passed on and on.\n\n330\n00:19:40,950 --> 00:19:43,526\nAUDIENCE: OK, so they'll\ngo way after the match?\n\n331\n00:19:43,526 --> 00:19:44,680\nPROFESSOR: They'll go\naway when no one\n\n332\n00:19:44,680 --> 00:19:45,930\nneeds them again, yeah.\n\n333\n00:19:45,930 --> 00:19:51,900\n\n\n334\n00:19:51,900 --> 00:19:54,230\nAUDIENCE: It appears that the\nAND performs some redundant\n\n335\n00:19:54,230 --> 00:19:56,050\nsearches of the database.\n\n336\n00:19:56,050 --> 00:19:58,660\nIf the first clause matched,\nlet's say, the third element\n\n337\n00:19:58,660 --> 00:20:01,820\nand not on the first two\nelements, the second clause is\n\n338\n00:20:01,820 --> 00:20:04,890\ngoing to look at those first two\nelements again, discarding\n\n339\n00:20:04,890 --> 00:20:06,700\nthem because they don't match.\n\n340\n00:20:06,700 --> 00:20:10,000\nThe match is already\nin the dictionary.\n\n341\n00:20:10,000 --> 00:20:12,920\nWould it makes sense to carry\nthe data element from the\n\n342\n00:20:12,920 --> 00:20:14,450\ndatabase along with\nthe dictionary?\n\n343\n00:20:14,450 --> 00:20:17,120\n\n\n344\n00:20:17,120 --> 00:20:18,550\nPROFESSOR: Well, in general,\nthere are other ways to\n\n345\n00:20:18,550 --> 00:20:21,220\narrange this search, and\nthere's some analysis\n\n346\n00:20:21,220 --> 00:20:21,740\nthat you can do.\n\n347\n00:20:21,740 --> 00:20:24,600\nI think there's a problem in the\nbook, which talks about a\n\n348\n00:20:24,600 --> 00:20:27,680\ndifferent way that you can\ncascade AND to eliminate\n\n349\n00:20:27,680 --> 00:20:29,850\nvarious kinds of redundancies.\n\n350\n00:20:29,850 --> 00:20:31,380\nThis one is meant to be--\n\n351\n00:20:31,380 --> 00:20:33,910\nwas mainly meant to be very\nsimple so you can see how they\n\n352\n00:20:33,910 --> 00:20:34,650\nfit together.\n\n353\n00:20:34,650 --> 00:20:35,380\nBut you're quite right.\n\n354\n00:20:35,380 --> 00:20:38,370\nThere are redundancies here\nthat you can get rid of.\n\n355\n00:20:38,370 --> 00:20:41,190\nThat's another reason why this\nlanguage is somewhat slow.\n\n356\n00:20:41,190 --> 00:20:42,930\nThere are a lot smarter\nthings you can do.\n\n357\n00:20:42,930 --> 00:20:45,590\nWe're just trying to show you\na very simple, in principle,\n\n358\n00:20:45,590 --> 00:20:46,840\nimplementation.\n\n359\n00:20:46,840 --> 00:20:51,220\n\n\n360\n00:20:51,220 --> 00:20:53,716\nAUDIENCE: Did you model this\nlanguage on Prolog, or did it\n\n361\n00:20:53,716 --> 00:20:55,150\njust come out looking\nlike Prolog?\n\n362\n00:20:55,150 --> 00:21:04,960\n\n\n363\n00:21:04,960 --> 00:21:06,380\nPROFESSOR: Well, Jerry insulted\na whole bunch of\n\n364\n00:21:06,380 --> 00:21:08,750\npeople yesterday, so I might\nas well say that the MIT\n\n365\n00:21:08,750 --> 00:21:11,460\nattitude towards Prolog is\nsomething that people did in\n\n366\n00:21:11,460 --> 00:21:15,030\nabout 1971 and decided that it\nwasn't really the right thing\n\n367\n00:21:15,030 --> 00:21:16,120\nand stopped.\n\n368\n00:21:16,120 --> 00:21:22,640\nSo we modeled this on the sort\nof natural way that this thing\n\n369\n00:21:22,640 --> 00:21:26,655\nwas done in about 1971, except\nat that point, we didn't do it\n\n370\n00:21:26,655 --> 00:21:33,020\nwith streams. After we were\nusing it for about six months,\n\n371\n00:21:33,020 --> 00:21:35,360\nwe discovered that it had all\nthese problems, some of which\n\n372\n00:21:35,360 --> 00:21:37,330\nI'll talk about later.\n\n373\n00:21:37,330 --> 00:21:40,310\nAnd we said, gee, Prolog must\nhave fixed those, and then we\n\n374\n00:21:40,310 --> 00:21:41,250\nfound out that it didn't.\n\n375\n00:21:41,250 --> 00:21:43,460\nSo this does about the\nsame thing as Prolog.\n\n376\n00:21:43,460 --> 00:21:44,950\nAUDIENCE: Does Prolog\nuse streams?\n\n377\n00:21:44,950 --> 00:21:46,200\nPROFESSOR: No.\n\n378\n00:21:46,200 --> 00:21:48,540\n\n\n379\n00:21:48,540 --> 00:21:51,040\nIn how it behaves, it behaves\na lot like Prolog.\n\n380\n00:21:51,040 --> 00:21:53,800\nProlog uses a backtracking\nstrategy.\n\n381\n00:21:53,800 --> 00:21:55,910\nBut the other thing that's\nreally good about Prolog that\n\n382\n00:21:55,910 --> 00:21:59,950\nmakes it a usable thing is that\nthere's a really very,\n\n383\n00:21:59,950 --> 00:22:04,830\nvery well-engineered compiler\ntechnology that makes it run\n\n384\n00:22:04,830 --> 00:22:09,260\nfast. So although you saw the\nmerge spitting out these\n\n385\n00:22:09,260 --> 00:22:13,080\nanswers very, very slowly, a\nreal Prolog will run very,\n\n386\n00:22:13,080 --> 00:22:16,800\nvery fast. Because even though\nit's sort of doing this, the\n\n387\n00:22:16,800 --> 00:22:19,600\nreal work that went into\nProlog is a very, very\n\n388\n00:22:19,600 --> 00:22:20,850\nexcellent compiler effort.\n\n389\n00:22:20,850 --> 00:22:24,460\n\n\n390\n00:22:24,460 --> 00:22:25,710\nLet's take a break.\n\n391\n00:22:25,710 --> 00:23:16,650\n\n\n392\n00:23:16,650 --> 00:23:20,410\nWe've looked at the primitive\nqueries and the ways that\n\n393\n00:23:20,410 --> 00:23:24,300\nstreams are used to implement\nthe means of combination: AND\n\n394\n00:23:24,300 --> 00:23:26,950\nand OR and NOT.\n\n395\n00:23:26,950 --> 00:23:29,580\nNow, let go on to the means\nof abstraction.\n\n396\n00:23:29,580 --> 00:23:31,280\nRemember, the means of\nabstraction in this\n\n397\n00:23:31,280 --> 00:23:32,570\nlanguage are rules.\n\n398\n00:23:32,570 --> 00:23:35,150\n\n\n399\n00:23:35,150 --> 00:23:42,580\nSo z is a boss in division d\nif there's some x who has a\n\n400\n00:23:42,580 --> 00:23:48,900\njob in division d and z is\nthe supervisor of x.\n\n401\n00:23:48,900 --> 00:23:52,260\nThat's what it means for\nsomeone to be a boss.\n\n402\n00:23:52,260 --> 00:23:54,780\nAnd in effect, if you think\nabout what we're doing with\n\n403\n00:23:54,780 --> 00:23:58,660\nrelation to this, there's the\nquery we wrote-- the job of x\n\n404\n00:23:58,660 --> 00:24:02,150\nis in d and the supervisor\nof x is z--\n\n405\n00:24:02,150 --> 00:24:05,330\nwhat we in effect want to do\nis take this whole mess and\n\n406\n00:24:05,330 --> 00:24:24,070\ndraw a box around it and say\nthis whole thing inside the\n\n407\n00:24:24,070 --> 00:24:33,900\nbox is boss of z\nin division d.\n\n408\n00:24:33,900 --> 00:24:35,250\nThat's in effect what\nwe want to do.\n\n409\n00:24:35,250 --> 00:24:38,720\n\n\n410\n00:24:38,720 --> 00:24:45,690\nSo, for instance, if we've\ndone that, and we want to\n\n411\n00:24:45,690 --> 00:24:49,410\ncheck whether or not it's true\nthat Ben Bitdiddle is a boss\n\n412\n00:24:49,410 --> 00:25:00,730\nin the computer division, so if\nI want to say boss of Ben\n\n413\n00:25:00,730 --> 00:25:05,850\nBitdiddle in the computer\ndivision, imagine typing that\n\n414\n00:25:05,850 --> 00:25:10,860\nin as query to the system, in\neffect what we want to do is\n\n415\n00:25:10,860 --> 00:25:28,920\nset up a dictionary here, which\nhas z to Ben Bitdiddle\n\n416\n00:25:28,920 --> 00:25:33,045\nand d to computer.\n\n417\n00:25:33,045 --> 00:25:37,340\n\n\n418\n00:25:37,340 --> 00:25:38,720\nWhere did that dictionary\ncome from?\n\n419\n00:25:38,720 --> 00:25:40,710\nLet's look at the slide\nfor one second.\n\n420\n00:25:40,710 --> 00:25:44,750\nThat dictionary came from\nmatching the query that said\n\n421\n00:25:44,750 --> 00:25:47,720\nboss of Ben Bitdiddle and\ncomputer onto the conclusion\n\n422\n00:25:47,720 --> 00:25:51,650\nof the rule: boss of z and d.\n\n423\n00:25:51,650 --> 00:25:54,190\nSo we match the query to the\nconclusion of the rule.\n\n424\n00:25:54,190 --> 00:26:00,330\nThat gives us a dictionary, and\nthat's the thing that we\n\n425\n00:26:00,330 --> 00:26:03,180\nwould now like to put into\nthis whole big thing and\n\n426\n00:26:03,180 --> 00:26:06,670\nprocess and see if anything\ncomes out the other side.\n\n427\n00:26:06,670 --> 00:26:11,330\nIf anything comes out,\nit'll be true.\n\n428\n00:26:11,330 --> 00:26:12,370\nThat's the basic idea.\n\n429\n00:26:12,370 --> 00:26:17,020\nSo in general, the way we\nimplement a rule is we match\n\n430\n00:26:17,020 --> 00:26:21,860\nthe conclusion of the rule\nagainst something we might\n\n431\n00:26:21,860 --> 00:26:23,580\nwant to check it's true.\n\n432\n00:26:23,580 --> 00:26:26,790\nThat match gives us a\ndictionary, and with respect\n\n433\n00:26:26,790 --> 00:26:36,470\nto that dictionary, we process\nthe body of the rule.\n\n434\n00:26:36,470 --> 00:26:40,110\nWell, that's really all\nthere is, except for\n\n435\n00:26:40,110 --> 00:26:43,070\ntwo technical points.\n\n436\n00:26:43,070 --> 00:26:46,580\nThe first technical point is\nthat I might have said\n\n437\n00:26:46,580 --> 00:26:47,510\nsomething else.\n\n438\n00:26:47,510 --> 00:26:52,490\nI might have said who's the boss\nin the computer division?\n\n439\n00:26:52,490 --> 00:26:56,270\nSo I might say boss of who\nin computer division.\n\n440\n00:26:56,270 --> 00:27:00,329\n\n\n441\n00:27:00,329 --> 00:27:03,920\nAnd if I did that, what I would\nreally like to do in\n\n442\n00:27:03,920 --> 00:27:09,280\neffect is start up this\ndictionary with a match that\n\n443\n00:27:09,280 --> 00:27:17,370\nsort of says, well, d\nis computer and z is\n\n444\n00:27:17,370 --> 00:27:18,620\nwhatever who is.\n\n445\n00:27:18,620 --> 00:27:21,700\n\n\n446\n00:27:21,700 --> 00:27:23,220\nAnd our matcher won't\nquite do that.\n\n447\n00:27:23,220 --> 00:27:28,580\nThat's not quite matching\na pattern against data.\n\n448\n00:27:28,580 --> 00:27:31,310\nIt's matching two patterns and\nsaying are they consistent or\n\n449\n00:27:31,310 --> 00:27:33,480\nnot or what ways make\nthem consistent.\n\n450\n00:27:33,480 --> 00:27:35,940\nIn other words, what we need\nis not quite a pattern\n\n451\n00:27:35,940 --> 00:27:38,450\nmatcher, but something\na little bit more\n\n452\n00:27:38,450 --> 00:27:39,740\ngeneral called a unifier.\n\n453\n00:27:39,740 --> 00:27:44,420\n\n\n454\n00:27:44,420 --> 00:27:47,190\nAnd a unifier is a slight\ngeneralization\n\n455\n00:27:47,190 --> 00:27:49,530\nof a pattern matcher.\n\n456\n00:27:49,530 --> 00:27:55,390\nWhat a unifier does is take two\npatterns and say what's\n\n457\n00:27:55,390 --> 00:27:59,020\nthe most general thing you can\nsubstitute for the variables\n\n458\n00:27:59,020 --> 00:28:04,060\nin those two patterns to make\nthem satisfy the pattern\n\n459\n00:28:04,060 --> 00:28:05,680\nsimultaneously?\n\n460\n00:28:05,680 --> 00:28:08,900\nLet me give you an example.\n\n461\n00:28:08,900 --> 00:28:13,940\nIf I have the pattern\ntwo-element list, which is x\n\n462\n00:28:13,940 --> 00:28:18,220\nand x, so I have a two-element\nlist where both elements are\n\n463\n00:28:18,220 --> 00:28:20,670\nthe same and otherwise I don't\ncare what they are, and I\n\n464\n00:28:20,670 --> 00:28:23,790\nunify that against the pattern\nthat says there's a\n\n465\n00:28:23,790 --> 00:28:27,010\ntwo-element list, and the first\none is a and something\n\n466\n00:28:27,010 --> 00:28:33,830\nin c and the second one is a\nand b and z, then what the\n\n467\n00:28:33,830 --> 00:28:36,960\nunifier should tell me is, oh\nyeah, in that dictionary, x\n\n468\n00:28:36,960 --> 00:28:43,440\nhas to be a, b, c, and y has\nto be d and z has to be c.\n\n469\n00:28:43,440 --> 00:28:45,660\nThose are the restrictions I'd\nhave to put on the values of\n\n470\n00:28:45,660 --> 00:28:48,880\nx, y, and z to make these two\nunify, or in other words, to\n\n471\n00:28:48,880 --> 00:28:55,420\nmake this match x and\nmake this match x.\n\n472\n00:28:55,420 --> 00:28:58,540\nThe unifier should be\nable to deduce that.\n\n473\n00:28:58,540 --> 00:28:59,730\nBut the unifier may--\n\n474\n00:28:59,730 --> 00:29:01,080\nthere are more complicated\nthings.\n\n475\n00:29:01,080 --> 00:29:03,810\nI might have said something a\nlittle bit more complicated.\n\n476\n00:29:03,810 --> 00:29:07,170\nI might have said there's a list\nwith two elements, and\n\n477\n00:29:07,170 --> 00:29:10,080\nthey're both the same, and\nthey should unify against\n\n478\n00:29:10,080 --> 00:29:12,650\nsomething of this form.\n\n479\n00:29:12,650 --> 00:29:16,890\nAnd the unifier should be able\nto deduce from that.\n\n480\n00:29:16,890 --> 00:29:19,570\nLike that y would have to be\nb. y would have to be b.\n\n481\n00:29:19,570 --> 00:29:24,340\nBecause these two are the same,\nso y's got to be b.\n\n482\n00:29:24,340 --> 00:29:28,940\nAnd v here would have to be a.\n\n483\n00:29:28,940 --> 00:29:31,450\nAnd z and w can be anything,\nbut they have\n\n484\n00:29:31,450 --> 00:29:32,700\nto be the same thing.\n\n485\n00:29:32,700 --> 00:29:35,710\n\n\n486\n00:29:35,710 --> 00:29:40,680\nAnd x would have to be b,\nfollowed by a, followed by\n\n487\n00:29:40,680 --> 00:29:44,680\nwhatever w is or whatever\nz is, which is the same.\n\n488\n00:29:44,680 --> 00:29:48,260\nSo you see, the unifier somehow\nhas to deduce things\n\n489\n00:29:48,260 --> 00:29:50,880\nto unify these patterns.\n\n490\n00:29:50,880 --> 00:29:52,880\nSo you might think there's some\nkind of magic deduction\n\n491\n00:29:52,880 --> 00:29:55,850\ngoing on, but there's not.\n\n492\n00:29:55,850 --> 00:29:59,100\nA unifier is basically a very\nsimple modification of a\n\n493\n00:29:59,100 --> 00:30:00,150\npattern matcher.\n\n494\n00:30:00,150 --> 00:30:02,530\nAnd if you look in the book,\nyou'll see something like\n\n495\n00:30:02,530 --> 00:30:05,350\nthree or four lines of code\nadded to the pattern matcher\n\n496\n00:30:05,350 --> 00:30:08,280\nyou just saw to handle\nthe symmetric case.\n\n497\n00:30:08,280 --> 00:30:11,920\nRemember, the pattern matcher\nhas a place where it says is\n\n498\n00:30:11,920 --> 00:30:14,980\nthis variable matching\na constant.\n\n499\n00:30:14,980 --> 00:30:16,420\nAnd if so, it checks\nin the dictionary.\n\n500\n00:30:16,420 --> 00:30:18,970\nThere's only one other clause in\nthe unifier, which says is\n\n501\n00:30:18,970 --> 00:30:22,760\nthis variable matching a\nvariable, in which case you go\n\n502\n00:30:22,760 --> 00:30:24,740\nlook in the dictionary and see\nif that's consistent with\n\n503\n00:30:24,740 --> 00:30:27,030\nwhat's in the dictionary.\n\n504\n00:30:27,030 --> 00:30:31,450\nSo all the, quote, deduction\nthat's in this language, if\n\n505\n00:30:31,450 --> 00:30:33,780\nyou sort of look at it, sort\nof sits in the rule\n\n506\n00:30:33,780 --> 00:30:37,220\napplications, which, if you\nlook at that, sits in the\n\n507\n00:30:37,220 --> 00:30:42,500\nunifier, which, if you look at\nthat under a microscope, sits\n\n508\n00:30:42,500 --> 00:30:45,260\nessentially in the\npattern matcher.\n\n509\n00:30:45,260 --> 00:30:47,410\nThere's no magic at all\ngoing on in there.\n\n510\n00:30:47,410 --> 00:30:51,930\nAnd the, quote, deduction that\nyou see is just the fact that\n\n511\n00:30:51,930 --> 00:30:54,610\nthere's this recursion,\nwhich is unwinding the\n\n512\n00:30:54,610 --> 00:30:56,030\nmatches bit by bit.\n\n513\n00:30:56,030 --> 00:30:58,670\nSo it looks like this thing is\nbeing very clever, but in\n\n514\n00:30:58,670 --> 00:31:02,140\nfact, it's not being\nvery clever at all.\n\n515\n00:31:02,140 --> 00:31:03,420\nThere are cases where a unifier\n\n516\n00:31:03,420 --> 00:31:04,880\nmight have to be clever.\n\n517\n00:31:04,880 --> 00:31:06,130\nLet me show you one more.\n\n518\n00:31:06,130 --> 00:31:11,070\n\n\n519\n00:31:11,070 --> 00:31:17,530\nSuppose I want to unify a list\nof two elements, x and x, with\n\n520\n00:31:17,530 --> 00:31:24,370\na thing that says it's y\nfollowed by a dot y.\n\n521\n00:31:24,370 --> 00:31:27,120\nNow, if you think of what that\nwould have to mean, it would\n\n522\n00:31:27,120 --> 00:31:32,230\nhave to mean that x had better\nbe the same as y, but also x\n\n523\n00:31:32,230 --> 00:31:35,160\nhad better be the same as a list\nwhose first element is a\n\n524\n00:31:35,160 --> 00:31:37,330\nand whose rest is y.\n\n525\n00:31:37,330 --> 00:31:42,460\nAnd if you think about what that\nwould have to mean, it\n\n526\n00:31:42,460 --> 00:31:44,710\nwould have to mean that y is\nthe infinite list of a's.\n\n527\n00:31:44,710 --> 00:31:47,500\n\n\n528\n00:31:47,500 --> 00:31:53,100\nIn some sense, in order to do\nthat unification, I have to\n\n529\n00:31:53,100 --> 00:32:01,840\nsolve the fixed-point equation\ncons of a to y is equal to y.\n\n530\n00:32:01,840 --> 00:32:04,570\n\n\n531\n00:32:04,570 --> 00:32:07,290\nAnd in general, I wrote\na very simple one.\n\n532\n00:32:07,290 --> 00:32:11,260\nReally doing unification might\nhave to solve an arbitrary\n\n533\n00:32:11,260 --> 00:32:15,530\nfixed-point equation:\nf of y equals y.\n\n534\n00:32:15,530 --> 00:32:18,750\nAnd basically, you can't do that\nand make the thing finite\n\n535\n00:32:18,750 --> 00:32:20,570\nall the time.\n\n536\n00:32:20,570 --> 00:32:25,140\nSo how does the logic language\nhandle that?\n\n537\n00:32:25,140 --> 00:32:26,850\nThe answer is it doesn't.\n\n538\n00:32:26,850 --> 00:32:28,730\nIt just punts.\n\n539\n00:32:28,730 --> 00:32:32,280\nAnd there's a little check in\nthe unifier, which says, oh,\n\n540\n00:32:32,280 --> 00:32:35,520\nis this one of the hard cases\nwhich when I go to match\n\n541\n00:32:35,520 --> 00:32:38,650\nthings would involve solving\na fixed-point equation?\n\n542\n00:32:38,650 --> 00:32:42,840\nAnd in this case, I will\nthrow up my hands.\n\n543\n00:32:42,840 --> 00:32:47,990\nAnd if that check were not in\nthere, what would happen?\n\n544\n00:32:47,990 --> 00:32:50,590\nIn most cases is that the\nunifier would just go into an\n\n545\n00:32:50,590 --> 00:32:53,740\ninfinite loop.\n\n546\n00:32:53,740 --> 00:32:56,800\nAnd other logic programming\nlanguages work like that.\n\n547\n00:32:56,800 --> 00:32:58,220\nSo there's really no magic.\n\n548\n00:32:58,220 --> 00:33:00,100\nThe easy case is done\nin a matcher.\n\n549\n00:33:00,100 --> 00:33:02,960\nThe hard case is not\ndone at all.\n\n550\n00:33:02,960 --> 00:33:05,115\nAnd that's about the state\nof this technology.\n\n551\n00:33:05,115 --> 00:33:12,840\n\n\n552\n00:33:12,840 --> 00:33:15,250\nLet me just say again formally\nhow rules work now that I\n\n553\n00:33:15,250 --> 00:33:17,390\ntalked about unifiers.\n\n554\n00:33:17,390 --> 00:33:25,260\nSo the official definition is\nthat to apply a rule, we--\n\n555\n00:33:25,260 --> 00:33:28,270\nwell, let's start using some\nwords we've used before.\n\n556\n00:33:28,270 --> 00:33:33,280\nLet's talk about sticking\ndictionaries into these big\n\n557\n00:33:33,280 --> 00:33:40,090\nboxes of query things as\nevaluating these large queries\n\n558\n00:33:40,090 --> 00:33:43,850\nrelative to an environment\nor a frame.\n\n559\n00:33:43,850 --> 00:33:45,350\nSo when you think of that\ndictionary, what's the\n\n560\n00:33:45,350 --> 00:33:46,720\ndictionary after all?\n\n561\n00:33:46,720 --> 00:33:48,180\nIt's a bunch of meanings\nfor symbols.\n\n562\n00:33:48,180 --> 00:33:51,800\nThat's what we've been calling\nframes or environments.\n\n563\n00:33:51,800 --> 00:33:55,430\nWhat does it mean to do some\nprocessing relevant to an\n\n564\n00:33:55,430 --> 00:33:55,970\nenvironment?\n\n565\n00:33:55,970 --> 00:33:58,310\nThat's what we've been\ncalling evaluation.\n\n566\n00:33:58,310 --> 00:34:03,030\nSo we can say the way that you\napply a rule is to evaluate\n\n567\n00:34:03,030 --> 00:34:07,730\nthe rule body relative to an\nenvironment that's formed by\n\n568\n00:34:07,730 --> 00:34:13,230\nunifying the rule conclusion\nwith the given query.\n\n569\n00:34:13,230 --> 00:34:16,340\nAnd the thing I want you to\nnotice is the complete formal\n\n570\n00:34:16,340 --> 00:34:20,760\nsimilarity to the net of\ncircular evaluator or the\n\n571\n00:34:20,760 --> 00:34:21,630\nsubstitution model.\n\n572\n00:34:21,630 --> 00:34:27,100\nTo apply a procedure, we\nevaluate the procedure body\n\n573\n00:34:27,100 --> 00:34:31,040\nrelative to an environment\nthat's formed by blinding the\n\n574\n00:34:31,040 --> 00:34:34,560\nprocedure parameters\nto the arguments.\n\n575\n00:34:34,560 --> 00:34:36,760\nThere's a complete formal\nsimilarity here between the\n\n576\n00:34:36,760 --> 00:34:40,870\nrules, rule application, and\nprocedure application even\n\n577\n00:34:40,870 --> 00:34:43,650\nthough these things are\nvery, very different.\n\n578\n00:34:43,650 --> 00:34:47,290\nAnd again, you have the\nEVAL APPLY loop.\n\n579\n00:34:47,290 --> 00:34:49,445\nEVAL and APPLY.\n\n580\n00:34:49,445 --> 00:34:53,360\n\n\n581\n00:34:53,360 --> 00:34:57,050\nSo in general, I might be\nprocessing some combined\n\n582\n00:34:57,050 --> 00:35:01,050\nexpression that will turn into a\nrule application, which will\n\n583\n00:35:01,050 --> 00:35:03,090\ngenerate some dictionaries or\nframes or environments--\n\n584\n00:35:03,090 --> 00:35:05,360\nwhatever you want to call them--\nfrom match, which will\n\n585\n00:35:05,360 --> 00:35:08,660\nthen be the input to some big\ncompound thing like this.\n\n586\n00:35:08,660 --> 00:35:13,580\nThis has pieces of it and may\nhave other rule applications.\n\n587\n00:35:13,580 --> 00:35:16,220\nAnd you have essentially the\nsame cycle even though there's\n\n588\n00:35:16,220 --> 00:35:19,680\nnothing here at all that\nlooks like procedures.\n\n589\n00:35:19,680 --> 00:35:22,120\nIt really has to do with the\nfact you've built a language\n\n590\n00:35:22,120 --> 00:35:24,150\nwhose means of combination\nand abstraction\n\n591\n00:35:24,150 --> 00:35:25,490\nunwind in certain ways.\n\n592\n00:35:25,490 --> 00:35:28,770\n\n\n593\n00:35:28,770 --> 00:35:33,840\nAnd then in general, what\nhappens at the very top level,\n\n594\n00:35:33,840 --> 00:35:37,280\nyou might have rules in your\ndatabase also, so things in\n\n595\n00:35:37,280 --> 00:35:40,460\nthis database might be rules.\n\n596\n00:35:40,460 --> 00:35:42,920\nThere are ways to check\nthat things are true.\n\n597\n00:35:42,920 --> 00:35:46,750\nSo it might come in here and\nhave to do a rule check.\n\n598\n00:35:46,750 --> 00:35:48,580\nAnd then there's some control\nstructure which says, well,\n\n599\n00:35:48,580 --> 00:35:50,130\nyou look at some rules, and\nyou look at some data\n\n600\n00:35:50,130 --> 00:35:51,965\nelements, and you look at some\nrules and data elements, and\n\n601\n00:35:51,965 --> 00:35:53,350\nthese fan out and out and out.\n\n602\n00:35:53,350 --> 00:35:56,520\nSo it becomes essentially\nimpossible to say what order\n\n603\n00:35:56,520 --> 00:35:59,300\nit's looking at these things in,\nwhether it's breadth first\n\n604\n00:35:59,300 --> 00:36:00,245\nor depth first or anything.\n\n605\n00:36:00,245 --> 00:36:03,650\nAnd it's even more impossible\nbecause the actual order is\n\n606\n00:36:03,650 --> 00:36:08,900\nsomehow buried in the delays of\nthe streams. So what's very\n\n607\n00:36:08,900 --> 00:36:11,270\nhard to tell from this is the\norder in which it's scanned.\n\n608\n00:36:11,270 --> 00:36:13,330\nBut what's true, because you're\nlooking at the stream\n\n609\n00:36:13,330 --> 00:36:15,820\nview, is that all of them\neventually get looked at.\n\n610\n00:36:15,820 --> 00:36:24,980\n\n\n611\n00:36:24,980 --> 00:36:28,150\nLet me just mention one tiny\ntechnical problem.\n\n612\n00:36:28,150 --> 00:36:37,530\n\n\n613\n00:36:37,530 --> 00:36:44,960\nSuppose I tried saying boss of\ny is computer, then a funny\n\n614\n00:36:44,960 --> 00:36:45,780\nthing would happen.\n\n615\n00:36:45,780 --> 00:36:53,680\nAs I stuck a dictionary with\ny in here, I might get--\n\n616\n00:36:53,680 --> 00:36:59,350\nthis y is not the same as that\ny, which was the other piece\n\n617\n00:36:59,350 --> 00:37:01,580\nof somebody's job description.\n\n618\n00:37:01,580 --> 00:37:04,380\nSo if I really only did\nliterally what I said, we'd\n\n619\n00:37:04,380 --> 00:37:09,990\nget some variable conflict\nproblems. So I lied to you a\n\n620\n00:37:09,990 --> 00:37:10,930\nlittle bit.\n\n621\n00:37:10,930 --> 00:37:12,900\nNotice that problem is\nexactly a problem\n\n622\n00:37:12,900 --> 00:37:14,360\nwe've run into before.\n\n623\n00:37:14,360 --> 00:37:20,505\nIt is precisely the need for\nlocal variables in a language.\n\n624\n00:37:20,505 --> 00:37:22,490\nWhen I have the sum of\nsquares, that x had\n\n625\n00:37:22,490 --> 00:37:24,960\nbetter not be that x.\n\n626\n00:37:24,960 --> 00:37:28,620\nThat's exactly the same\nas this y had\n\n627\n00:37:28,620 --> 00:37:31,800\nbetter not be that y.\n\n628\n00:37:31,800 --> 00:37:33,100\nAnd we know how to solve that.\n\n629\n00:37:33,100 --> 00:37:34,730\nThat was this whole environment\nmodel, and we\n\n630\n00:37:34,730 --> 00:37:37,710\nbuilt chains of frames and all\nsorts of things like that.\n\n631\n00:37:37,710 --> 00:37:39,270\nThere's a much more brutal\nway to solve it.\n\n632\n00:37:39,270 --> 00:37:41,730\nIn the query language, we\ndidn't even do that.\n\n633\n00:37:41,730 --> 00:37:43,540\nWe did something completely\nbrutal.\n\n634\n00:37:43,540 --> 00:37:48,520\nWe said every time you apply a\nrule, rename consistently all\n\n635\n00:37:48,520 --> 00:37:51,100\nthe variables in the rule to\nsome new unique names that\n\n636\n00:37:51,100 --> 00:37:55,720\nwon't conflict with anything.\n\n637\n00:37:55,720 --> 00:37:58,150\nThat's conceptually simpler,\nbut really brutal and not\n\n638\n00:37:58,150 --> 00:37:59,970\nparticularly efficient.\n\n639\n00:37:59,970 --> 00:38:03,700\nBut notice, we could have\ngotten rid of all of our\n\n640\n00:38:03,700 --> 00:38:08,030\nenvironment structures if we\ndefined for procedures in Lisp\n\n641\n00:38:08,030 --> 00:38:09,180\nthe same thing.\n\n642\n00:38:09,180 --> 00:38:10,580\nIf every time we applied\na procedure and did the\n\n643\n00:38:10,580 --> 00:38:13,410\nsubstitution model we renamed\nall the variables in the\n\n644\n00:38:13,410 --> 00:38:15,830\nprocedure, then we never would\nhave had to worry about local\n\n645\n00:38:15,830 --> 00:38:19,040\nvariables because they\nwould never arise.\n\n646\n00:38:19,040 --> 00:38:21,240\nOK, well, that would be\ninefficient, and it's\n\n647\n00:38:21,240 --> 00:38:23,870\ninefficient here in the query\nlanguage, too, but we did it\n\n648\n00:38:23,870 --> 00:38:25,610\nto keep it simple.\n\n649\n00:38:25,610 --> 00:38:26,860\nLet's break for questions.\n\n650\n00:38:26,860 --> 00:38:30,880\n\n\n651\n00:38:30,880 --> 00:38:34,870\nAUDIENCE: When you started this\nsection, you emphasized\n\n652\n00:38:34,870 --> 00:38:40,390\nhow powerful our APPLY EVAL\nmodel was that we could use it\n\n653\n00:38:40,390 --> 00:38:41,170\nfor any language.\n\n654\n00:38:41,170 --> 00:38:42,790\nAnd then you say we're going to\nhave this language which is\n\n655\n00:38:42,790 --> 00:38:43,950\nso different.\n\n656\n00:38:43,950 --> 00:38:46,440\nIt turns out that this language,\nas you just pointed\n\n657\n00:38:46,440 --> 00:38:47,880\nout, is very much the same.\n\n658\n00:38:47,880 --> 00:38:49,710\nI'm wondering if you're arguing\nthat all languages end\n\n659\n00:38:49,710 --> 00:38:53,810\nup coming down to this you can\napply a rule or apply a\n\n660\n00:38:53,810 --> 00:38:57,030\nprocedure or some\nkind of apply?\n\n661\n00:38:57,030 --> 00:38:59,150\nPROFESSOR: I would say that\npretty much any language where\n\n662\n00:38:59,150 --> 00:39:03,210\nyou really are building up these\nmeans of combination and\n\n663\n00:39:03,210 --> 00:39:06,120\ngiving them simpler names and\nyou're saying anything of the\n\n664\n00:39:06,120 --> 00:39:10,430\nsort, like here's a general kind\nof expression, like how\n\n665\n00:39:10,430 --> 00:39:13,180\nto square something, almost\nanything that you\n\n666\n00:39:13,180 --> 00:39:14,880\nwould call a procedure.\n\n667\n00:39:14,880 --> 00:39:16,360\nIf that's got to have\nparts, you have to\n\n668\n00:39:16,360 --> 00:39:18,020\nunwind those parts.\n\n669\n00:39:18,020 --> 00:39:20,830\nYou have to have some kind of\norganization which says when I\n\n670\n00:39:20,830 --> 00:39:24,892\nlook at the abstract variables\nor tags or whatever you want\n\n671\n00:39:24,892 --> 00:39:28,490\nto call them that might stand\nfor particular things, you\n\n672\n00:39:28,490 --> 00:39:29,720\nhave to keep track of that,\nand that's going to be\n\n673\n00:39:29,720 --> 00:39:31,720\nsomething like an environment.\n\n674\n00:39:31,720 --> 00:39:34,670\nAnd then if you say this part\ncan have parts which I have to\n\n675\n00:39:34,670 --> 00:39:37,440\nunwind, you've got to have\nsomething like this cycle.\n\n676\n00:39:37,440 --> 00:39:39,970\n\n\n677\n00:39:39,970 --> 00:39:44,000\nAnd lots and lots of languages\nhave that character when they\n\n678\n00:39:44,000 --> 00:39:45,590\nsort of get put together\nin this way.\n\n679\n00:39:45,590 --> 00:39:47,610\nThis language again really is\ndifferent because there's\n\n680\n00:39:47,610 --> 00:39:50,690\nnothing like procedures\non the outside.\n\n681\n00:39:50,690 --> 00:39:52,080\nWhen you go below the surface\nand you see the\n\n682\n00:39:52,080 --> 00:39:54,870\nimplementation, of course, it\nstarts looking the same.\n\n683\n00:39:54,870 --> 00:39:56,950\nBut from the outside, it's a\nvery different world view.\n\n684\n00:39:56,950 --> 00:39:58,650\nYou're not computing functions\nof inputs.\n\n685\n00:39:58,650 --> 00:40:03,970\n\n\n686\n00:40:03,970 --> 00:40:07,920\nAUDIENCE: You mentioned earlier\nthat when you build\n\n687\n00:40:07,920 --> 00:40:10,660\nall of these rules in pattern\nmatcher and with the delayed\n\n688\n00:40:10,660 --> 00:40:13,900\naction of streams, you really\nhave no way to know in what\n\n689\n00:40:13,900 --> 00:40:15,495\norder things are evaluated.\n\n690\n00:40:15,495 --> 00:40:15,940\nPROFESSOR: Right.\n\n691\n00:40:15,940 --> 00:40:19,470\nAUDIENCE: And that would\nindicate then that you should\n\n692\n00:40:19,470 --> 00:40:21,850\nonly express declarative\nknowledge that's true for\n\n693\n00:40:21,850 --> 00:40:23,950\nall-time, no-time sequence\nbuilt into it.\n\n694\n00:40:23,950 --> 00:40:27,440\nOtherwise, these things\nget all--\n\n695\n00:40:27,440 --> 00:40:28,490\nPROFESSOR: Yes.\n\n696\n00:40:28,490 --> 00:40:28,820\nYes.\n\n697\n00:40:28,820 --> 00:40:32,100\nThe question is this really is\nset up for doing declarative\n\n698\n00:40:32,100 --> 00:40:37,190\nknowledge, and as I presented\nit-- and I'll show you some of\n\n699\n00:40:37,190 --> 00:40:40,830\nthe ugly warts under this\nafter the break.\n\n700\n00:40:40,830 --> 00:40:43,070\nAs I presented it, it's\njust doing logic.\n\n701\n00:40:43,070 --> 00:40:45,720\nAnd in principle, if it were\nlogic, it wouldn't matter what\n\n702\n00:40:45,720 --> 00:40:48,840\norder it's getting done.\n\n703\n00:40:48,840 --> 00:40:52,840\nAnd it's quite true when you\nstart doing things where you\n\n704\n00:40:52,840 --> 00:40:55,380\nhave side effects like adding\nthings to the database and\n\n705\n00:40:55,380 --> 00:40:59,990\ntaking things out, and we'll see\nsome others, you use that\n\n706\n00:40:59,990 --> 00:41:01,290\nkind of control.\n\n707\n00:41:01,290 --> 00:41:02,940\nSo, for example, contrasting\nwith Prolog.\n\n708\n00:41:02,940 --> 00:41:05,720\nSay Prolog has various features\nwhere you really\n\n709\n00:41:05,720 --> 00:41:09,640\nexploit the order\nof evaluation.\n\n710\n00:41:09,640 --> 00:41:11,770\nAnd people write Prolog\nprograms that way.\n\n711\n00:41:11,770 --> 00:41:14,420\nThat turns out to be very\ncomplicated in Prolog,\n\n712\n00:41:14,420 --> 00:41:15,940\nalthough if you're\nan expert Prolog\n\n713\n00:41:15,940 --> 00:41:18,590\nprogrammer, you can do it.\n\n714\n00:41:18,590 --> 00:41:20,210\nHowever, here I don't think\nyou can do it at all.\n\n715\n00:41:20,210 --> 00:41:22,890\nIt's very complicated because\nyou really are giving up\n\n716\n00:41:22,890 --> 00:41:27,150\ncontrol over any prearranged\norder of trying things.\n\n717\n00:41:27,150 --> 00:41:29,210\nAUDIENCE: Now, that would\nindicate then that you have a\n\n718\n00:41:29,210 --> 00:41:30,670\nfunctional mapping.\n\n719\n00:41:30,670 --> 00:41:34,870\nAnd when you started out this\nlecture, you said that we\n\n720\n00:41:34,870 --> 00:41:36,635\nexpress the declarative\nknowledge which is a relation,\n\n721\n00:41:36,635 --> 00:41:38,810\nand we don't talk about the\ninputs and the outputs.\n\n722\n00:41:38,810 --> 00:41:41,390\n\n\n723\n00:41:41,390 --> 00:41:43,370\nPROFESSOR: Well, there's a\npun on functional, right?\n\n724\n00:41:43,370 --> 00:41:46,560\nThere's function in the sense\nof no side effects and not\n\n725\n00:41:46,560 --> 00:41:48,700\ndepending on what order\nis going on.\n\n726\n00:41:48,700 --> 00:41:50,720\nAnd then there's functional in\nthe sense of mathematical\n\n727\n00:41:50,720 --> 00:41:52,220\nfunction, which means\ninput and output.\n\n728\n00:41:52,220 --> 00:41:56,510\nAnd it's just that pun that\nyou're making, I think.\n\n729\n00:41:56,510 --> 00:41:58,520\nAUDIENCE: I'm a little unclear\non what you're doing with\n\n730\n00:41:58,520 --> 00:42:01,270\nthese two statements, the\ntwo boss statements.\n\n731\n00:42:01,270 --> 00:42:06,416\nIs the first one building up\nthe database and the second\n\n732\n00:42:06,416 --> 00:42:09,150\none a query or--\n\n733\n00:42:09,150 --> 00:42:12,440\nPROFESSOR: OK, I'm sorry.\n\n734\n00:42:12,440 --> 00:42:14,130\nWhat I meant here, if I\ntype something like\n\n735\n00:42:14,130 --> 00:42:16,200\nthis in as a query--\n\n736\n00:42:16,200 --> 00:42:19,470\nI should have given an example\nway at the very beginning.\n\n737\n00:42:19,470 --> 00:42:25,100\nIf I type in job, Ben Bitdiddle,\ncomputer wizard,\n\n738\n00:42:25,100 --> 00:42:28,570\nwhat the processing will do is\nif it finds a match, it'll\n\n739\n00:42:28,570 --> 00:42:31,600\nfind a match to that exact\nthing, and it'll type out a\n\n740\n00:42:31,600 --> 00:42:34,220\njob, Ben Bitdiddle,\ncomputer wizard.\n\n741\n00:42:34,220 --> 00:42:37,400\nIf it doesn't find a match,\nit won't find anything.\n\n742\n00:42:37,400 --> 00:42:40,100\nSo what I should have said is\nthe way you use the query\n\n743\n00:42:40,100 --> 00:42:43,610\nlanguage to check whether\nsomething is true, remember,\n\n744\n00:42:43,610 --> 00:42:45,130\nthat's one of the things\nyou want to do in logic\n\n745\n00:42:45,130 --> 00:42:47,990\nprogramming, is you type in\nyour query and either that\n\n746\n00:42:47,990 --> 00:42:50,680\ncomes out or it doesn't.\n\n747\n00:42:50,680 --> 00:42:52,940\nSo what I was trying to\nillustrate here, I wanted to\n\n748\n00:42:52,940 --> 00:42:55,220\nstart with a very simple\nexample before\n\n749\n00:42:55,220 --> 00:42:57,480\ntalking about unifiers.\n\n750\n00:42:57,480 --> 00:43:00,260\nSo what I should have said, if I\njust wanted to check whether\n\n751\n00:43:00,260 --> 00:43:02,820\nthis is true, I could type that\nin and see if anything\n\n752\n00:43:02,820 --> 00:43:04,854\ncame out\n\n753\n00:43:04,854 --> 00:43:06,290\nAUDIENCE: And then\nthe second one--\n\n754\n00:43:06,290 --> 00:43:07,830\nPROFESSOR: The second one\nwould be a real query.\n\n755\n00:43:07,830 --> 00:43:10,770\nAUDIENCE: A real query, yeah.\n\n756\n00:43:10,770 --> 00:43:12,380\nPROFESSOR: What would come out,\nsee, it would go in here\n\n757\n00:43:12,380 --> 00:43:17,480\nsay with FOO, and in would go\nframe that says z is bound to\n\n758\n00:43:17,480 --> 00:43:19,560\nwho and d is bound\nto computer.\n\n759\n00:43:19,560 --> 00:43:21,400\nAnd this will pass through, and\nthen by the time it got\n\n760\n00:43:21,400 --> 00:43:23,250\nout of here, who would\npick up a binding.\n\n761\n00:43:23,250 --> 00:43:26,950\n\n\n762\n00:43:26,950 --> 00:43:31,950\nAUDIENCE: On the unifying thing\nthere, I still am not\n\n763\n00:43:31,950 --> 00:43:36,460\nsure what happens\nwith who and z.\n\n764\n00:43:36,460 --> 00:43:37,850\nIf the unifying--\n\n765\n00:43:37,850 --> 00:43:39,490\nthe rule here says--\n\n766\n00:43:39,490 --> 00:43:42,070\n\n\n767\n00:43:42,070 --> 00:43:44,920\nOK, so you say that you can't\nmake question mark equal to\n\n768\n00:43:44,920 --> 00:43:46,260\nquestion mark who.\n\n769\n00:43:46,260 --> 00:43:46,410\nPROFESSOR: Right.\n\n770\n00:43:46,410 --> 00:43:48,360\nThat's what the matcher\ncan't do.\n\n771\n00:43:48,360 --> 00:43:52,550\nBut what this will mean to a\nunifier is that there's an\n\n772\n00:43:52,550 --> 00:43:53,800\nenvironment with three\nvariables.\n\n773\n00:43:53,800 --> 00:43:56,690\n\n\n774\n00:43:56,690 --> 00:43:58,520\nd here is computer.\n\n775\n00:43:58,520 --> 00:44:01,830\nz is whatever who is.\n\n776\n00:44:01,830 --> 00:44:09,180\nSo if later on in the matcher\nroutine it said, for example,\n\n777\n00:44:09,180 --> 00:44:14,110\nwho has to be 3, then when I\nlooked up in the dictionary,\n\n778\n00:44:14,110 --> 00:44:18,360\nit will say, oh, z is 3 because\nit's the same as who.\n\n779\n00:44:18,360 --> 00:44:20,500\nAnd that's in some sense the\nonly thing you need to do to\n\n780\n00:44:20,500 --> 00:44:22,640\nextend the unifier\nto a matcher.\n\n781\n00:44:22,640 --> 00:44:23,830\nAUDIENCE: OK, because it looked\nlike when you were\n\n782\n00:44:23,830 --> 00:44:26,000\ntelling how to unify it, it\nlooked like you would put the\n\n783\n00:44:26,000 --> 00:44:27,955\nthings together in such a way\nthat you'd actually solve and\n\n784\n00:44:27,955 --> 00:44:29,770\nhave a value for both of them.\n\n785\n00:44:29,770 --> 00:44:32,230\nAnd what it looks like now is\nthat you're actually pass a\n\n786\n00:44:32,230 --> 00:44:34,860\ndictionary with two variables\nand the variables are linked.\n\n787\n00:44:34,860 --> 00:44:35,130\nPROFESSOR: Right.\n\n788\n00:44:35,130 --> 00:44:37,580\nIt only looks like you're\nsolving for both of them\n\n789\n00:44:37,580 --> 00:44:40,540\nbecause you're sort of looking\nat the whole solution at once.\n\n790\n00:44:40,540 --> 00:44:42,790\nIf you sort of watch the thing\ngetting built up recursively,\n\n791\n00:44:42,790 --> 00:44:44,980\nit's merely this.\n\n792\n00:44:44,980 --> 00:44:46,620\nAUDIENCE: OK, so you\ndo pass off that\n\n793\n00:44:46,620 --> 00:44:48,400\ndictionary with two variables?\n\n794\n00:44:48,400 --> 00:44:49,110\nPROFESSOR: That's right.\n\n795\n00:44:49,110 --> 00:44:50,190\nAUDIENCE: And link?\n\n796\n00:44:50,190 --> 00:44:50,560\nPROFESSOR: Right.\n\n797\n00:44:50,560 --> 00:44:54,055\nIt just looks like an\nordinary dictionary.\n\n798\n00:44:54,055 --> 00:44:57,450\nAUDIENCE: When you're talking\nabout the unifier, is it that\n\n799\n00:44:57,450 --> 00:45:02,785\nthere are some cases or some\npoints that you are not able\n\n800\n00:45:02,785 --> 00:45:04,725\nto use by them?\n\n801\n00:45:04,725 --> 00:45:05,220\nPROFESSOR: Right.\n\n802\n00:45:05,220 --> 00:45:10,100\nAUDIENCE: Can you just by\nbuilding the rules or writing\n\n803\n00:45:10,100 --> 00:45:15,582\nthe forms know in advance if\nyou are going to be able to\n\n804\n00:45:15,582 --> 00:45:18,540\nsolve to get the unification\nor not?\n\n805\n00:45:18,540 --> 00:45:23,560\nCan you add some properties\neither to the rules itself or\n\n806\n00:45:23,560 --> 00:45:26,730\nto the formula that you're\nwriting so that you avoid the\n\n807\n00:45:26,730 --> 00:45:30,090\nproblem of not finding\nunification?\n\n808\n00:45:30,090 --> 00:45:32,870\nPROFESSOR: I mean, you can\nagree, I think, to write in a\n\n809\n00:45:32,870 --> 00:45:35,390\nfairly restricted way where\nyou won't run into it.\n\n810\n00:45:35,390 --> 00:45:36,870\nSee, because what\nyou're getting--\n\n811\n00:45:36,870 --> 00:45:39,760\nsee, the place where you get\ninto problems is when you--\n\n812\n00:45:39,760 --> 00:45:45,020\nwell, again, you're trying to\nmatch things like that against\n\n813\n00:45:45,020 --> 00:45:47,600\nthings where these\nhave structure,\n\n814\n00:45:47,600 --> 00:45:55,300\nwhere a, y, b, y something.\n\n815\n00:45:55,300 --> 00:45:58,980\n\n\n816\n00:45:58,980 --> 00:46:00,570\nSo this is the kind of\nplace where you're\n\n817\n00:46:00,570 --> 00:46:03,070\ngoing to get into trouble.\n\n818\n00:46:03,070 --> 00:46:06,370\nAUDIENCE: So you can do\nthat syntactically?\n\n819\n00:46:06,370 --> 00:46:09,320\nPROFESSOR: So you can kind of\nwatch your rules in the kinds\n\n820\n00:46:09,320 --> 00:46:11,561\nof things that your writing.\n\n821\n00:46:11,561 --> 00:46:14,460\nAUDIENCE: So that's the problem\nthat the builder of\n\n822\n00:46:14,460 --> 00:46:16,310\nthe database has to\nbe concerned?\n\n823\n00:46:16,310 --> 00:46:17,560\nPROFESSOR: That's a problem.\n\n824\n00:46:17,560 --> 00:46:19,930\n\n\n825\n00:46:19,930 --> 00:46:21,580\nIt's a problem either-- not\nquite the builder of the\n\n826\n00:46:21,580 --> 00:46:24,270\ndatabase, the person who is\nexpressing the rules, or the\n\n827\n00:46:24,270 --> 00:46:25,800\nbuilder of the database.\n\n828\n00:46:25,800 --> 00:46:29,230\nWhat the unifier actually does\nis you can check at the next\n\n829\n00:46:29,230 --> 00:46:32,710\nlevel down when you actually get\nto the unifier and you'll\n\n830\n00:46:32,710 --> 00:46:34,940\nsee in the code where it looks\nup in the dictionary.\n\n831\n00:46:34,940 --> 00:46:37,260\nIf it sort of says what\ndoes y have to be?\n\n832\n00:46:37,260 --> 00:46:40,690\nOh, does y have to be something\nthat contains a y as\n\n833\n00:46:40,690 --> 00:46:41,960\nits expression?\n\n834\n00:46:41,960 --> 00:46:45,120\nAt that point, the unifier and\nsay, oh my God, I'm trying to\n\n835\n00:46:45,120 --> 00:46:46,240\nsolve a fixed-point equation.\n\n836\n00:46:46,240 --> 00:46:49,220\nI'll give it up here.\n\n837\n00:46:49,220 --> 00:46:50,940\nAUDIENCE: You make the\ndistinction between the rules\n\n838\n00:46:50,940 --> 00:46:51,910\nin the database.\n\n839\n00:46:51,910 --> 00:46:56,950\nAre the rules added\nto the database?\n\n840\n00:46:56,950 --> 00:46:57,870\nPROFESSOR: Yes.\n\n841\n00:46:57,870 --> 00:46:58,870\nYes, I should have said that.\n\n842\n00:46:58,870 --> 00:47:01,540\nOne way to think about rules\nis that they're just other\n\n843\n00:47:01,540 --> 00:47:03,890\nthings in the database.\n\n844\n00:47:03,890 --> 00:47:06,050\nSo if you want to check the\nthings that have to be checked\n\n845\n00:47:06,050 --> 00:47:08,935\nin the database, they're kind\nof virtual facts that are in\n\n846\n00:47:08,935 --> 00:47:09,445\nthe database.\n\n847\n00:47:09,445 --> 00:47:12,510\nAUDIENCE: But in that\nexplanation, you made the\n\n848\n00:47:12,510 --> 00:47:18,230\ndifferentiation between database\nand the rules itself.\n\n849\n00:47:18,230 --> 00:47:20,490\nPROFESSOR: Yeah, I probably\nshould not have done that.\n\n850\n00:47:20,490 --> 00:47:22,440\nThe only reason to do that\nis in terms of the\n\n851\n00:47:22,440 --> 00:47:23,540\nimplementation.\n\n852\n00:47:23,540 --> 00:47:25,220\nWhen you look at the\nimplementation, there's a part\n\n853\n00:47:25,220 --> 00:47:28,120\nwhich says check either\nprimitive assertions in the\n\n854\n00:47:28,120 --> 00:47:30,470\ndatabase or check rules.\n\n855\n00:47:30,470 --> 00:47:33,510\nAnd then the real reason why\nyou can't tell what order\n\n856\n00:47:33,510 --> 00:47:38,010\nthings are going to come out\nin and is that the rules\n\n857\n00:47:38,010 --> 00:47:42,240\ndatabase and the data database\nsort of get merged in a kind\n\n858\n00:47:42,240 --> 00:47:44,600\nof delayed evaluation way.\n\n859\n00:47:44,600 --> 00:47:46,320\nAnd so that's what makes the\norder very complicated.\n\n860\n00:47:46,320 --> 00:47:55,440\n\n\n861\n00:47:55,440 --> 00:47:56,690\nOK, let's break.\n\n862\n00:47:56,690 --> 00:48:33,160\n\n\n863\n00:48:33,160 --> 00:48:35,520\nWe've just seen how the\nlogic language works\n\n864\n00:48:35,520 --> 00:48:37,230\nand how rules work.\n\n865\n00:48:37,230 --> 00:48:40,120\nNow, let's turn to a more\nprofound question.\n\n866\n00:48:40,120 --> 00:48:43,180\nWhat do these things mean?\n\n867\n00:48:43,180 --> 00:48:47,240\nThat brings us to the subtlest,\nmost devious part of\n\n868\n00:48:47,240 --> 00:48:51,420\nthis whole query language\nbusiness, and that is that\n\n869\n00:48:51,420 --> 00:48:53,570\nit's not quite what\nit seems to be.\n\n870\n00:48:53,570 --> 00:48:59,750\nAND and OR and NOT and the\nlogical implication of rules\n\n871\n00:48:59,750 --> 00:49:05,400\nare not really the AND and\nOR and NOT and logical\n\n872\n00:49:05,400 --> 00:49:07,690\nimplication of logic.\n\n873\n00:49:07,690 --> 00:49:09,910\nLet me give you an\nexample of that.\n\n874\n00:49:09,910 --> 00:49:12,960\nCertainly, if we have two things\nin logic, it ought to\n\n875\n00:49:12,960 --> 00:49:22,225\nbe the case that AND of P and Q\nis the same as AND of Q and\n\n876\n00:49:22,225 --> 00:49:28,920\nP and that OR of P and Q is the\nsame as OR of Q and P. But\n\n877\n00:49:28,920 --> 00:49:30,100\nlet's look here.\n\n878\n00:49:30,100 --> 00:49:32,180\nHere's an example.\n\n879\n00:49:32,180 --> 00:49:38,200\nLet's talk about somebody\noutranking somebody else in\n\n880\n00:49:38,200 --> 00:49:40,140\nour little database\norganization.\n\n881\n00:49:40,140 --> 00:49:47,890\nWe'll say s is outranked by b or\nif either the supervisor of\n\n882\n00:49:47,890 --> 00:49:51,100\nthis is b or there's some middle\nmanager here, that\n\n883\n00:49:51,100 --> 00:49:55,640\nsupervisor of s is m, and\nm is outranked by b.\n\n884\n00:49:55,640 --> 00:49:59,830\n\n\n885\n00:49:59,830 --> 00:50:02,310\nSo there's one way to define\nrule outranked by.\n\n886\n00:50:02,310 --> 00:50:06,300\nOr we can write exactly the\nsame thing, except at the\n\n887\n00:50:06,300 --> 00:50:11,630\nbottom here, we reversed the\norder of these two clauses.\n\n888\n00:50:11,630 --> 00:50:14,180\nAnd certainly if this were\nlogic, those ought to mean the\n\n889\n00:50:14,180 --> 00:50:16,690\nsame thing.\n\n890\n00:50:16,690 --> 00:50:20,060\nHowever, in our particular\nimplementation, if you say\n\n891\n00:50:20,060 --> 00:50:23,800\nsomething like who's outranked\nby Ben Bitdiddle, what you'll\n\n892\n00:50:23,800 --> 00:50:27,870\nfind is that this rule will\nwork perfectly well and\n\n893\n00:50:27,870 --> 00:50:31,030\ngenerate answers, whereas\nthis rule will go\n\n894\n00:50:31,030 --> 00:50:34,110\ninto an infinite loop.\n\n895\n00:50:34,110 --> 00:50:37,230\nAnd the reason for that is that\nthis will come in and\n\n896\n00:50:37,230 --> 00:50:39,400\nsay, oh, who's outranked\nby Ben Bitdiddle?\n\n897\n00:50:39,400 --> 00:50:41,920\n\n\n898\n00:50:41,920 --> 00:50:45,790\nFind an s which is outranked\nby b, where b is Ben\n\n899\n00:50:45,790 --> 00:50:50,330\nBitdiddle, which is going to\nhappen in it a subproblem.\n\n900\n00:50:50,330 --> 00:50:55,710\nOh gee, find an m such as m is\noutranked by Ben Bitdiddle\n\n901\n00:50:55,710 --> 00:50:58,560\nwith no restrictions on m.\n\n902\n00:50:58,560 --> 00:51:01,910\nSo this will say in order to\nsolve this problem, I solve\n\n903\n00:51:01,910 --> 00:51:04,570\nexactly the same problem.\n\n904\n00:51:04,570 --> 00:51:06,010\nAnd then after I've solved\nthat, I'll check for a\n\n905\n00:51:06,010 --> 00:51:08,000\nsupervisory relationship.\n\n906\n00:51:08,000 --> 00:51:10,290\nWhereas this one won't get into\nthat, because before it\n\n907\n00:51:10,290 --> 00:51:14,010\ntries to find this outranked by,\nit'll already have had a\n\n908\n00:51:14,010 --> 00:51:15,260\nrestriction on m here.\n\n909\n00:51:15,260 --> 00:51:18,560\n\n\n910\n00:51:18,560 --> 00:51:21,190\nSo these two things which ought\nto mean the same, in\n\n911\n00:51:21,190 --> 00:51:22,860\nfact, one goes into\nan infinite loop.\n\n912\n00:51:22,860 --> 00:51:26,720\nOne does not.\n\n913\n00:51:26,720 --> 00:51:30,630\nThat's a very extreme case of\na general thing that you'll\n\n914\n00:51:30,630 --> 00:51:35,970\nfind in logic programming that\nif you start changing the\n\n915\n00:51:35,970 --> 00:51:39,910\norder of the things in the\nANDs or ORs, you'll find\n\n916\n00:51:39,910 --> 00:51:42,240\ntremendous differences\nin efficiency.\n\n917\n00:51:42,240 --> 00:51:45,860\nAnd we just saw an infinitely\nbig difference in efficiency\n\n918\n00:51:45,860 --> 00:51:47,110\nand an infinite loop.\n\n919\n00:51:47,110 --> 00:51:49,190\n\n\n920\n00:51:49,190 --> 00:51:52,220\nAnd there are similar things\nhaving to do with the order in\n\n921\n00:51:52,220 --> 00:51:54,070\nwhich you enter rules.\n\n922\n00:51:54,070 --> 00:51:55,980\nThe order in which it happens\nto look at rules in the\n\n923\n00:51:55,980 --> 00:51:59,140\ndatabase may vastly change the\nefficiency with which it gets\n\n924\n00:51:59,140 --> 00:52:01,860\nout answers or, in fact, send\nit into an infinite loop for\n\n925\n00:52:01,860 --> 00:52:03,840\nsome orderings.\n\n926\n00:52:03,840 --> 00:52:08,370\nAnd this whole thing has to do\nwith the fact that you're\n\n927\n00:52:08,370 --> 00:52:10,950\nchecking these rules\nin some order.\n\n928\n00:52:10,950 --> 00:52:13,690\nAnd some rules may lead to\nreally long paths of\n\n929\n00:52:13,690 --> 00:52:15,180\nimplication.\n\n930\n00:52:15,180 --> 00:52:16,440\nOthers might not.\n\n931\n00:52:16,440 --> 00:52:18,480\nAnd you don't know a priori\nwhich ones are good and which\n\n932\n00:52:18,480 --> 00:52:19,300\nones are bad.\n\n933\n00:52:19,300 --> 00:52:21,270\nAnd there's a whole bunch of\nresearch having to do with\n\n934\n00:52:21,270 --> 00:52:24,840\nthat, mostly having to do with\nthinking about making parallel\n\n935\n00:52:24,840 --> 00:52:26,970\nimplementations of logic\nprogramming languages.\n\n936\n00:52:26,970 --> 00:52:29,330\nAnd in some sense, what you'd\nlike to do is check all rules\n\n937\n00:52:29,330 --> 00:52:31,870\nin parallel and whichever\nones get answers,\n\n938\n00:52:31,870 --> 00:52:32,620\nyou bubble them up.\n\n939\n00:52:32,620 --> 00:52:34,600\nAnd if some go down\ninfinite deductive\n\n940\n00:52:34,600 --> 00:52:36,290\nchanged, well, you just--\n\n941\n00:52:36,290 --> 00:52:38,440\nyou know, memory is cheap and\nprocessors are cheap, and you\n\n942\n00:52:38,440 --> 00:52:40,550\njust let them buzz for as\nfor as long as you want.\n\n943\n00:52:40,550 --> 00:52:43,510\n\n\n944\n00:52:43,510 --> 00:52:47,660\nThere's a deeper problem,\nthough, in comparing this\n\n945\n00:52:47,660 --> 00:52:50,870\nlogic language to real logic.\n\n946\n00:52:50,870 --> 00:52:54,260\nThe example I just showed you,\nit went into an infinite loop\n\n947\n00:52:54,260 --> 00:52:58,370\nmaybe, but at least it didn't\ngive the wrong answer.\n\n948\n00:52:58,370 --> 00:53:02,980\nThere's an actual deeper\nproblem when we start\n\n949\n00:53:02,980 --> 00:53:07,460\ncomparing, seriously comparing\nthis logic language with real\n\n950\n00:53:07,460 --> 00:53:09,490\nclassical logic.\n\n951\n00:53:09,490 --> 00:53:14,030\nSo let's sort of review\nreal classical logic.\n\n952\n00:53:14,030 --> 00:53:22,140\nAll humans are mortal.\n\n953\n00:53:22,140 --> 00:53:24,390\nThat's pretty classical logic.\n\n954\n00:53:24,390 --> 00:53:26,410\nThen maybe we'll continue\nin the very\n\n955\n00:53:26,410 --> 00:53:29,120\nbest classical tradition.\n\n956\n00:53:29,120 --> 00:53:31,010\nWe'll say all--\n\n957\n00:53:31,010 --> 00:53:32,740\nlet's make it really\nclassical.\n\n958\n00:53:32,740 --> 00:53:41,690\nAll Greeks are human, which\nhas the syllogism that\n\n959\n00:53:41,690 --> 00:53:48,060\nSocrates is a Greek.\n\n960\n00:53:48,060 --> 00:53:49,210\nAnd then what do\nyou write here?\n\n961\n00:53:49,210 --> 00:53:51,890\nI think three dots,\nclassical logic.\n\n962\n00:53:51,890 --> 00:54:01,360\nTherefore, then the syllogism,\nSocrates is mortal.\n\n963\n00:54:01,360 --> 00:54:05,880\nSo there's some real honest\nclassical logic.\n\n964\n00:54:05,880 --> 00:54:12,570\nLet's compare that with our\nclassical logic database.\n\n965\n00:54:12,570 --> 00:54:16,270\nSo here's a classical\nlogic database.\n\n966\n00:54:16,270 --> 00:54:18,030\nSocrates is a Greek.\n\n967\n00:54:18,030 --> 00:54:19,600\nPlato is a Greek.\n\n968\n00:54:19,600 --> 00:54:24,120\nZeus is a Greek, and\nZeus is a god.\n\n969\n00:54:24,120 --> 00:54:30,780\nAnd all humans are mortal.\n\n970\n00:54:30,780 --> 00:54:32,880\nTo show that something is\nmortal, it's enough to show\n\n971\n00:54:32,880 --> 00:54:34,650\nthat it's human.\n\n972\n00:54:34,650 --> 00:54:35,900\nAll humans are fallible.\n\n973\n00:54:35,900 --> 00:54:38,900\n\n\n974\n00:54:38,900 --> 00:54:40,980\nAnd all Greeks are humans\nis not quite right.\n\n975\n00:54:40,980 --> 00:54:45,920\nThis says that all Greeks who\nare not gods are human.\n\n976\n00:54:45,920 --> 00:54:47,820\nSo to show something's human,\nit's enough to show it's a\n\n977\n00:54:47,820 --> 00:54:49,320\nGreek and not a god.\n\n978\n00:54:49,320 --> 00:54:54,470\nAnd the address of any Greek\ngod is Mount Olympus.\n\n979\n00:54:54,470 --> 00:54:57,390\nSo there's a little classical\nlogic database.\n\n980\n00:54:57,390 --> 00:54:59,490\nAnd indeed, that would\nwork fairly well.\n\n981\n00:54:59,490 --> 00:55:05,420\nIf we type that in and say is\nSocrates mortal or Socrates\n\n982\n00:55:05,420 --> 00:55:06,910\nfallible or mortal?\n\n983\n00:55:06,910 --> 00:55:07,690\nIt'll say yes.\n\n984\n00:55:07,690 --> 00:55:09,710\nIs Plato mortal and fallible.\n\n985\n00:55:09,710 --> 00:55:10,680\nIt'll say yes.\n\n986\n00:55:10,680 --> 00:55:12,210\nIf we say is Zeus mortal?\n\n987\n00:55:12,210 --> 00:55:14,900\nIt won't find anything.\n\n988\n00:55:14,900 --> 00:55:16,640\nAnd it'll work perfectly well.\n\n989\n00:55:16,640 --> 00:55:20,120\nHowever, suppose we want\nto extend this.\n\n990\n00:55:20,120 --> 00:55:25,070\nLet's define what it means for\nsomeone to be a perfect being.\n\n991\n00:55:25,070 --> 00:55:27,020\nLet's say rule: a\nperfect being.\n\n992\n00:55:27,020 --> 00:55:34,050\n\n\n993\n00:55:34,050 --> 00:55:35,480\nAnd I think this is right.\n\n994\n00:55:35,480 --> 00:55:38,570\nIf you're up on your medieval\nscholastic philosophy, I\n\n995\n00:55:38,570 --> 00:55:41,350\nbelieve that perfect beings\nare ones who were neither\n\n996\n00:55:41,350 --> 00:55:44,100\nmortal nor fallible.\n\n997\n00:55:44,100 --> 00:55:59,300\nAND NOT mortal x,\nNOT fallible x.\n\n998\n00:55:59,300 --> 00:56:03,340\nSo we'll define this system\nto teach it what a\n\n999\n00:56:03,340 --> 00:56:05,790\nperfect being is.\n\n1000\n00:56:05,790 --> 00:56:09,110\nAnd now what we're going to do\nis he ask for the address of\n\n1001\n00:56:09,110 --> 00:56:11,750\nall the perfect beings.\n\n1002\n00:56:11,750 --> 00:56:23,680\nAND the address of x is\ny and x is perfect.\n\n1003\n00:56:23,680 --> 00:56:26,590\nAnd so what we're generating\nhere is the world's most\n\n1004\n00:56:26,590 --> 00:56:32,050\nexclusive mailing list. For the\naddress of all the perfect\n\n1005\n00:56:32,050 --> 00:56:33,830\nthings, we might have\ntyped this in.\n\n1006\n00:56:33,830 --> 00:56:36,240\nOr we might type in this.\n\n1007\n00:56:36,240 --> 00:56:52,140\nWe'll say AND perfect of x and\nthe address of x is y.\n\n1008\n00:56:52,140 --> 00:56:55,190\nWell, suppose we type all that\nin and we try this query.\n\n1009\n00:56:55,190 --> 00:56:57,650\nThis query is going to\ngive us an answer.\n\n1010\n00:56:57,650 --> 00:56:59,745\nThis query will say, yeah,\nMount Olympus.\n\n1011\n00:56:59,745 --> 00:57:04,230\n\n\n1012\n00:57:04,230 --> 00:57:06,740\nThis query, in fact, is going\nto give us nothing.\n\n1013\n00:57:06,740 --> 00:57:11,640\nIt will say no addresses\nof perfect beings.\n\n1014\n00:57:11,640 --> 00:57:12,510\nNow, why is that?\n\n1015\n00:57:12,510 --> 00:57:14,230\nWhy is there a difference?\n\n1016\n00:57:14,230 --> 00:57:15,690\nThis is not an infinite\nloop question.\n\n1017\n00:57:15,690 --> 00:57:19,145\nThis is a different\nanswer question.\n\n1018\n00:57:19,145 --> 00:57:21,790\nThe reason is that if you\nremember the implementation of\n\n1019\n00:57:21,790 --> 00:57:25,880\nNOT, NOT acted as a filter.\n\n1020\n00:57:25,880 --> 00:57:29,040\nNOT said I'm going to take some\npossible dictionaries,\n\n1021\n00:57:29,040 --> 00:57:32,480\nsome possible frames, some\npossible answers, and filter\n\n1022\n00:57:32,480 --> 00:57:35,070\nout the ones that happened to\nsatisfy some condition, and\n\n1023\n00:57:35,070 --> 00:57:36,520\nthat's how I implement NOT.\n\n1024\n00:57:36,520 --> 00:57:40,730\nIf you think about what's going\non here, I'll build this\n\n1025\n00:57:40,730 --> 00:57:46,470\nquery box where the output of an\naddress piece gets fed into\n\n1026\n00:57:46,470 --> 00:57:47,720\na perfect piece.\n\n1027\n00:57:47,720 --> 00:57:50,290\n\n\n1028\n00:57:50,290 --> 00:57:52,880\nWhat will happen is the address\npiece will set up some\n\n1029\n00:57:52,880 --> 00:57:55,290\nthings of everyone whose\naddress I know.\n\n1030\n00:57:55,290 --> 00:57:59,880\nThose will get filtered by the\nNOTs inside perfect here.\n\n1031\n00:57:59,880 --> 00:58:03,230\nSo it will throw out the ones\nwhich happened to be either\n\n1032\n00:58:03,230 --> 00:58:04,910\nmortal or fallible.\n\n1033\n00:58:04,910 --> 00:58:07,700\nIn the other order what happens\nis I set this up,\n\n1034\n00:58:07,700 --> 00:58:09,520\nstarted up with an\nempty frame.\n\n1035\n00:58:09,520 --> 00:58:12,000\nThe perfect in here doesn't find\nanything for the NOTs to\n\n1036\n00:58:12,000 --> 00:58:13,920\nfilter, so nothing comes\nout here at all.\n\n1037\n00:58:13,920 --> 00:58:18,830\n\n\n1038\n00:58:18,830 --> 00:58:20,940\nAnd there's sort of nothing\nthere that gets fed into the\n\n1039\n00:58:20,940 --> 00:58:21,940\naddress thing.\n\n1040\n00:58:21,940 --> 00:58:24,260\nSo here, I don't\nget an answer.\n\n1041\n00:58:24,260 --> 00:58:25,620\nAnd again, the reason\nfor that is NOT\n\n1042\n00:58:25,620 --> 00:58:27,440\nisn't generating anything.\n\n1043\n00:58:27,440 --> 00:58:28,800\nNOT's only throwing\nout things.\n\n1044\n00:58:28,800 --> 00:58:31,160\nAnd if I never started up with\nanything, there's nothing for\n\n1045\n00:58:31,160 --> 00:58:32,020\nit to throw out.\n\n1046\n00:58:32,020 --> 00:58:33,770\nSo out of this thing, I\nget the wrong answer.\n\n1047\n00:58:33,770 --> 00:58:37,200\n\n\n1048\n00:58:37,200 --> 00:58:37,970\nHow can you fix that?\n\n1049\n00:58:37,970 --> 00:58:39,070\nWell, there are ways\nto fix that.\n\n1050\n00:58:39,070 --> 00:58:41,410\nSo you might say, well,\nthat's sort of stupid.\n\n1051\n00:58:41,410 --> 00:58:43,700\nWhy are you just doing\nall your NOT\n\n1052\n00:58:43,700 --> 00:58:44,900\nstuff at the beginning?\n\n1053\n00:58:44,900 --> 00:58:48,220\nThe right way to implement NOT\nis to realize that when you\n\n1054\n00:58:48,220 --> 00:58:51,360\nhave conditions like NOT, you\nshould generate all your\n\n1055\n00:58:51,360 --> 00:58:54,140\nanswers first, and then with\neach of these dictionaries\n\n1056\n00:58:54,140 --> 00:58:58,560\npass along until at the very\nend I'll do filtering.\n\n1057\n00:58:58,560 --> 00:59:01,560\nAnd there are implementations\nof logic languages that work\n\n1058\n00:59:01,560 --> 00:59:04,050\nlike that that solve this\nparticular problem.\n\n1059\n00:59:04,050 --> 00:59:06,660\n\n\n1060\n00:59:06,660 --> 00:59:10,030\nHowever, there's a more profound\nproblem, which is\n\n1061\n00:59:10,030 --> 00:59:12,530\nwhich one of these is\nthe right answer?\n\n1062\n00:59:12,530 --> 00:59:15,320\nIs it Mount Olympus\nor is it nothing?\n\n1063\n00:59:15,320 --> 00:59:19,420\nSo you might say it's Mount\nOlympus, because after all,\n\n1064\n00:59:19,420 --> 00:59:23,220\nZeus is in that database,\nand Zeus was\n\n1065\n00:59:23,220 --> 00:59:24,805\nneither mortal nor fallible.\n\n1066\n00:59:24,805 --> 00:59:29,550\n\n\n1067\n00:59:29,550 --> 00:59:43,310\nSo you might say Zeus wants to\nsatisfy NOT mortal Zeus or NOT\n\n1068\n00:59:43,310 --> 00:59:44,120\nfallible Zeus.\n\n1069\n00:59:44,120 --> 00:59:47,638\nBut let's actually look\nat that database.\n\n1070\n00:59:47,638 --> 00:59:49,320\nLet's look at it.\n\n1071\n00:59:49,320 --> 00:59:51,275\nThere's no way--\n\n1072\n00:59:51,275 --> 00:59:54,810\nhow does it know that Zeus\nis not fallible?\n\n1073\n00:59:54,810 --> 00:59:57,930\nThere's nothing in\nthere about that.\n\n1074\n00:59:57,930 --> 00:59:59,410\nWhat's in there is that\nhumans are fallible.\n\n1075\n00:59:59,410 --> 01:00:02,390\n\n\n1076\n01:00:02,390 --> 01:00:04,430\nHow does it know that\nZeus is not mortal?\n\n1077\n01:00:04,430 --> 01:00:07,980\nThere's nothing in\nthere about that.\n\n1078\n01:00:07,980 --> 01:00:12,000\nIt just said I don't have\nany rule, which--\n\n1079\n01:00:12,000 --> 01:00:13,820\nthe only way I can deduce\nsomething's mortal is if it's\n\n1080\n01:00:13,820 --> 01:00:16,690\nhuman, and that's all it really\nknows about mortal.\n\n1081\n01:00:16,690 --> 01:00:20,060\nAnd in fact, if you remember\nyour classical mythology, you\n\n1082\n01:00:20,060 --> 01:00:25,300\nknow that the Greek gods were\nnot mortal but fallible.\n\n1083\n01:00:25,300 --> 01:00:30,850\nSo the answer is not\nin the rules there.\n\n1084\n01:00:30,850 --> 01:00:32,100\nSee, why does it deduce that?\n\n1085\n01:00:32,100 --> 01:00:34,710\n\n\n1086\n01:00:34,710 --> 01:00:37,330\nSee, Socrates would certainly\nnot have made\n\n1087\n01:00:37,330 --> 01:00:40,080\nthis error of logic.\n\n1088\n01:00:40,080 --> 01:00:43,370\nWhat NOT needs in this\nlanguage is not NOT.\n\n1089\n01:00:43,370 --> 01:00:44,930\nIt's not the NOT of logic.\n\n1090\n01:00:44,930 --> 01:00:48,950\nWhat NOT needs in this language\nis not deducible from\n\n1091\n01:00:48,950 --> 01:00:55,140\nthings in the database as\nopposed to not true.\n\n1092\n01:00:55,140 --> 01:00:57,300\nThat's a very big difference.\n\n1093\n01:00:57,300 --> 01:00:59,250\nSubtle, but big.\n\n1094\n01:00:59,250 --> 01:01:03,080\nSo, in fact, this is perfectly\nhappy to say not anything that\n\n1095\n01:01:03,080 --> 01:01:04,610\nit doesn't know about.\n\n1096\n01:01:04,610 --> 01:01:06,900\nSo if you ask it is it not\ntrue that Zeus likes\n\n1097\n01:01:06,900 --> 01:01:07,830\nchocolate ice cream?\n\n1098\n01:01:07,830 --> 01:01:10,251\nIt will say sure,\nit's not true.\n\n1099\n01:01:10,251 --> 01:01:12,850\nOr anything else or anything\nit doesn't know about.\n\n1100\n01:01:12,850 --> 01:01:18,280\nNOT means not deducible from\nthe things you've told me.\n\n1101\n01:01:18,280 --> 01:01:22,760\nIn a world where you're\nidentifying not deducible\n\n1102\n01:01:22,760 --> 01:01:25,800\nwith, in fact, not true, this\nis called the closed world\n\n1103\n01:01:25,800 --> 01:01:27,050\nassumption.\n\n1104\n01:01:27,050 --> 01:01:36,870\n\n\n1105\n01:01:36,870 --> 01:01:38,320\nThe closed world assumption.\n\n1106\n01:01:38,320 --> 01:01:43,550\nAnything that I cannot deduce\nfrom what I know\n\n1107\n01:01:43,550 --> 01:01:46,500\nis not true, right?\n\n1108\n01:01:46,500 --> 01:01:49,290\nIf I don't know anything about\nx, the x isn't true.\n\n1109\n01:01:49,290 --> 01:01:51,420\nThat's very dangerous.\n\n1110\n01:01:51,420 --> 01:01:52,860\nFrom a logical point of view,\nfirst of all, it doesn't\n\n1111\n01:01:52,860 --> 01:01:54,480\nreally makes sense.\n\n1112\n01:01:54,480 --> 01:01:58,860\nBecause if I don't know anything\nabout x, I'm willing\n\n1113\n01:01:58,860 --> 01:02:00,240\nto say not x.\n\n1114\n01:02:00,240 --> 01:02:03,850\nBut am I willing to\nsay not not x?\n\n1115\n01:02:03,850 --> 01:02:04,500\nWell, sure, I don't\nknow anything\n\n1116\n01:02:04,500 --> 01:02:06,470\nabout that either maybe.\n\n1117\n01:02:06,470 --> 01:02:09,450\nSo not not x is not necessarily\nthe same as x and\n\n1118\n01:02:09,450 --> 01:02:13,120\nso on and so on and so on, so\nthere's some sort of funny\n\n1119\n01:02:13,120 --> 01:02:15,970\nbias in there.\n\n1120\n01:02:15,970 --> 01:02:17,290\nSo that's sort of funny.\n\n1121\n01:02:17,290 --> 01:02:22,840\nThe second thing, if you start\nbuilding up real reasoning\n\n1122\n01:02:22,840 --> 01:02:27,210\nprograms based on this, think\nhow dangerous that is.\n\n1123\n01:02:27,210 --> 01:02:33,420\nYou're saying I know I'm in a\nposition to deduce everything\n\n1124\n01:02:33,420 --> 01:02:37,780\ntrue that's relevant\nto this problem.\n\n1125\n01:02:37,780 --> 01:02:41,590\nI'm reasoning, and built into my\nreasoning mechanism is the\n\n1126\n01:02:41,590 --> 01:02:45,160\nassumption that anything that I\ndon't know can't possibly be\n\n1127\n01:02:45,160 --> 01:02:48,860\nrelevant to this\nproblem, right?\n\n1128\n01:02:48,860 --> 01:02:52,350\nThere are a lot of big\norganizations that work like\n\n1129\n01:02:52,350 --> 01:02:54,720\nthat, right?\n\n1130\n01:02:54,720 --> 01:02:56,830\nMost corporate marketing\ndivisions work like that.\n\n1131\n01:02:56,830 --> 01:03:00,560\nYou know the consequences\nto that.\n\n1132\n01:03:00,560 --> 01:03:04,490\nSo it's very dangerous to start\nreally typing in these\n\n1133\n01:03:04,490 --> 01:03:08,750\nbig logical implication systems\nand going on what they\n\n1134\n01:03:08,750 --> 01:03:10,500\nsay, because they have\nthis really limiting\n\n1135\n01:03:10,500 --> 01:03:12,600\nassumption built in.\n\n1136\n01:03:12,600 --> 01:03:14,905\nSo you have to be very, very\ncareful about that.\n\n1137\n01:03:14,905 --> 01:03:16,560\nAnd that's a deep problem.\n\n1138\n01:03:16,560 --> 01:03:19,570\nThat's not a problem about we\ncan make a little bit cleverer\n\n1139\n01:03:19,570 --> 01:03:22,360\nimplementation and do the\nfilters and organize the\n\n1140\n01:03:22,360 --> 01:03:23,840\ninfinite loops to make\nthem go away.\n\n1141\n01:03:23,840 --> 01:03:25,920\nIt's a different kind\nof problem.\n\n1142\n01:03:25,920 --> 01:03:27,060\nIt's a different semantics.\n\n1143\n01:03:27,060 --> 01:03:31,910\nSo I think to wrap this up, it's\nfair to say that logic\n\n1144\n01:03:31,910 --> 01:03:34,650\nprogramming I think is a\nterrifically exciting idea,\n\n1145\n01:03:34,650 --> 01:03:38,010\nthe idea that you can bridge\nthis gap from the imperative\n\n1146\n01:03:38,010 --> 01:03:42,300\nto the declarative, that you\ncan start talking about\n\n1147\n01:03:42,300 --> 01:03:46,900\nrelations and really get\ntremendous power by going\n\n1148\n01:03:46,900 --> 01:03:48,570\nabove the abstraction\nof what's my input\n\n1149\n01:03:48,570 --> 01:03:50,560\nand what's my output.\n\n1150\n01:03:50,560 --> 01:03:55,160\nAnd linked to logic, the problem\nis it's a goal that I\n\n1151\n01:03:55,160 --> 01:03:58,080\nthink has yet to be realized.\n\n1152\n01:03:58,080 --> 01:04:02,740\nAnd probably one of the very\nmost interesting research\n\n1153\n01:04:02,740 --> 01:04:06,530\nquestions going on now in\nlanguages is how do you\n\n1154\n01:04:06,530 --> 01:04:09,460\nsomehow make a real\nlogic language?\n\n1155\n01:04:09,460 --> 01:04:11,940\nAnd secondly, how do you bridge\nthe gap from this world\n\n1156\n01:04:11,940 --> 01:04:16,020\nof logic and relations to the\nworlds of more traditional\n\n1157\n01:04:16,020 --> 01:04:18,680\nlanguages and somehow combine\nthe power of both.\n\n1158\n01:04:18,680 --> 01:04:19,930\nOK, let's break.\n\n1159\n01:04:19,930 --> 01:04:23,750\n\n\n1160\n01:04:23,750 --> 01:04:25,675\nAUDIENCE: Couldn't you solve\nthat last problem by having\n\n1161\n01:04:25,675 --> 01:04:27,430\nthe extra rules that imply it?\n\n1162\n01:04:27,430 --> 01:04:30,060\nThe problem here is you have the\ndefinition of something,\n\n1163\n01:04:30,060 --> 01:04:32,210\nbut you don't have the\ndefinition of its opposite.\n\n1164\n01:04:32,210 --> 01:04:35,890\nIf you include in the database\nsomething that says something\n\n1165\n01:04:35,890 --> 01:04:38,780\nimplies mortal x, something\nelse implies not mortal x,\n\n1166\n01:04:38,780 --> 01:04:40,370\nhaven't you basically\nsolved the problem?\n\n1167\n01:04:40,370 --> 01:04:43,370\n\n\n1168\n01:04:43,370 --> 01:04:45,660\nPROFESSOR: But the issue\nis do you put a finite\n\n1169\n01:04:45,660 --> 01:04:46,910\nnumber of those in?\n\n1170\n01:04:46,910 --> 01:04:50,740\n\n\n1171\n01:04:50,740 --> 01:04:54,980\nAUDIENCE: If things are\nspecified always in pairs--\n\n1172\n01:04:54,980 --> 01:04:55,970\nPROFESSOR: But the impression\nis then what do\n\n1173\n01:04:55,970 --> 01:04:57,220\nyou do about deduction?\n\n1174\n01:04:57,220 --> 01:05:00,200\n\n\n1175\n01:05:00,200 --> 01:05:03,400\nYou can't specify NOTs.\n\n1176\n01:05:03,400 --> 01:05:05,930\nBut the problem is, in a big\nsystem, it turns out that\n\n1177\n01:05:05,930 --> 01:05:07,960\nmight not be a finite\nnumber of things.\n\n1178\n01:05:07,960 --> 01:05:12,820\n\n\n1179\n01:05:12,820 --> 01:05:15,290\nThere are also sort\nof two issues.\n\n1180\n01:05:15,290 --> 01:05:16,690\nPartly it might not be finite.\n\n1181\n01:05:16,690 --> 01:05:21,510\nPartly it might be that's\nnot what you want.\n\n1182\n01:05:21,510 --> 01:05:23,790\nSo a good example would be\nsuppose I want to do\n\n1183\n01:05:23,790 --> 01:05:25,120\nconnectivity.\n\n1184\n01:05:25,120 --> 01:05:28,050\nI want a reason about\nconnectivity.\n\n1185\n01:05:28,050 --> 01:05:32,100\nAnd I'm going to tell you\nthere's four things: a and b\n\n1186\n01:05:32,100 --> 01:05:35,480\nand c and d.\n\n1187\n01:05:35,480 --> 01:05:39,740\nAnd I'll tell you a is connected\nto b and c's\n\n1188\n01:05:39,740 --> 01:05:43,200\nconnected to d.\n\n1189\n01:05:43,200 --> 01:05:45,260\nAnd now I'll tell you\nis a connected to d?\n\n1190\n01:05:45,260 --> 01:05:46,780\nThat's the question.\n\n1191\n01:05:46,780 --> 01:05:49,360\nThere's an example where I would\nlike something like the\n\n1192\n01:05:49,360 --> 01:05:50,610\nclosed world assumption.\n\n1193\n01:05:50,610 --> 01:05:54,200\n\n\n1194\n01:05:54,200 --> 01:05:57,630\nThat's a tiny toy, but a lot of\ntimes, I want to be able to\n\n1195\n01:05:57,630 --> 01:05:59,800\nsay something like anything\nthat I haven't told you,\n\n1196\n01:05:59,800 --> 01:06:01,340\nassume is not true.\n\n1197\n01:06:01,340 --> 01:06:04,260\n\n\n1198\n01:06:04,260 --> 01:06:06,990\nSo it's not as simple as you\nonly want to put in explicit\n\n1199\n01:06:06,990 --> 01:06:09,470\nNOTs all over the place.\n\n1200\n01:06:09,470 --> 01:06:11,200\nIt's that sometimes it\nreally isn't clear\n\n1201\n01:06:11,200 --> 01:06:14,150\nwhat you even want.\n\n1202\n01:06:14,150 --> 01:06:17,160\nThat having to specify both\neverything and not everything\n\n1203\n01:06:17,160 --> 01:06:20,960\nis too precise, and then you get\ndown into problems there.\n\n1204\n01:06:20,960 --> 01:06:24,420\nBut there are a lot of\napproaches that explicitly put\n\n1205\n01:06:24,420 --> 01:06:26,510\nin NOTs and reason\nbased on that.\n\n1206\n01:06:26,510 --> 01:06:28,070\nSo it's a very good idea.\n\n1207\n01:06:28,070 --> 01:06:31,620\nIt's just that then it starts\nbecoming a little cumbersome\n\n1208\n01:06:31,620 --> 01:06:33,490\nin the very large problems\nyou'd like to use.\n\n1209\n01:06:33,490 --> 01:06:43,460\n\n\n1210\n01:06:43,460 --> 01:06:45,410\nAUDIENCE: I'm not sure how\ndirectly related to the\n\n1211\n01:06:45,410 --> 01:06:48,840\nargument this is, but one of\nyour points was that one of\n\n1212\n01:06:48,840 --> 01:06:51,100\nthe dangers of the closed rule\nis you never really know all\n\n1213\n01:06:51,100 --> 01:06:53,840\nthe things that are there.\n\n1214\n01:06:53,840 --> 01:06:55,930\nYou never really know\nall the parts to it.\n\n1215\n01:06:55,930 --> 01:06:58,160\nIsn't that a major problem\nwith any programming?\n\n1216\n01:06:58,160 --> 01:07:01,110\nI always write programs where I\nassume that I've got all the\n\n1217\n01:07:01,110 --> 01:07:04,430\ncases, and so I check for them\nall or whatever, and somewhere\n\n1218\n01:07:04,430 --> 01:07:05,750\ndown the road, I find\nout that I didn't\n\n1219\n01:07:05,750 --> 01:07:07,390\ncheck for one of them.\n\n1220\n01:07:07,390 --> 01:07:08,540\nPROFESSOR: Well, sure,\nit's true.\n\n1221\n01:07:08,540 --> 01:07:14,630\nBut the problem here is it's\nthat assumption which is the\n\n1222\n01:07:14,630 --> 01:07:16,610\nthing that you're making if you\nbelieve you're identifying\n\n1223\n01:07:16,610 --> 01:07:19,600\nthis with logic.\n\n1224\n01:07:19,600 --> 01:07:20,510\nSo you're quite right.\n\n1225\n01:07:20,510 --> 01:07:22,220\nIt's a situation you're\nnever in.\n\n1226\n01:07:22,220 --> 01:07:24,420\nThe problem is if you're\nstarting to believe that what\n\n1227\n01:07:24,420 --> 01:07:27,305\nthis is doing is logic and you\nlook at the rules you write\n\n1228\n01:07:27,305 --> 01:07:30,200\ndown and say what can I deduce\nfrom them, you have to be very\n\n1229\n01:07:30,200 --> 01:07:33,470\ncareful to remember that NOT\nmeans something else.\n\n1230\n01:07:33,470 --> 01:07:35,510\nAnd it means something else\nbased on an assumption which\n\n1231\n01:07:35,510 --> 01:07:39,030\nis probably not true.\n\n1232\n01:07:39,030 --> 01:07:41,170\nAUDIENCE: Do I understand you\ncorrectly that you cannot fix\n\n1233\n01:07:41,170 --> 01:07:44,510\nthis problem without killing\noff all possibilities of\n\n1234\n01:07:44,510 --> 01:07:47,990\ninference through\naltering NOT?\n\n1235\n01:07:47,990 --> 01:07:49,370\nPROFESSOR: No, that's\nnot quite right.\n\n1236\n01:07:49,370 --> 01:07:50,620\nThere are other--\n\n1237\n01:07:50,620 --> 01:07:52,710\n\n\n1238\n01:07:52,710 --> 01:07:56,340\nthere are ways to do logic\nwith real NOTs.\n\n1239\n01:07:56,340 --> 01:07:58,540\nThere are actually\nways to do that.\n\n1240\n01:07:58,540 --> 01:08:01,610\nBut they're very inefficient\nas far as anybody knows.\n\n1241\n01:08:01,610 --> 01:08:02,860\nAnd they're much more--\n\n1242\n01:08:02,860 --> 01:08:05,390\n\n\n1243\n01:08:05,390 --> 01:08:09,240\nthe, quote, inference in here is\nbuilt into this unifier and\n\n1244\n01:08:09,240 --> 01:08:11,980\nthis pattern matching\nunification algorithm.\n\n1245\n01:08:11,980 --> 01:08:16,590\nThere are ways to automate\nreal logical reasoning.\n\n1246\n01:08:16,590 --> 01:08:19,460\nBut it's not based on that,\nand logic programming\n\n1247\n01:08:19,460 --> 01:08:21,420\nlanguages don't tend to do\nthat because it's very\n\n1248\n01:08:21,420 --> 01:08:23,850\ninefficient as far\nas anybody knows.\n\n1249\n01:08:23,850 --> 01:08:29,390\n\n\n1250\n01:08:29,390 --> 01:08:30,640\nAll right, thank you.\n\n1251\n01:08:30,640 --> 01:08:43,903\n\n"
  },
  {
    "path": "SrtEN/lec9a_512kb.mp4.srt",
    "content": "0\n00:00:00,000 --> 00:00:02,190\n\n\n1\n00:00:02,190 --> 00:00:02,550\n[MUSIC PLAYING - \"JESU, JOY OF\nMAN'S DESIRING\" BY JOHANN\n\n2\n00:00:02,550 --> 00:00:03,800\nSEBASTIAN BACH]\n\n3\n00:00:03,800 --> 00:00:17,260\n\n\n4\n00:00:17,260 --> 00:00:20,520\nPROFESSOR: Well, up 'til now, I\nsuppose, we've been learning\n\n5\n00:00:20,520 --> 00:00:26,690\nabout a lot of techniques for\norganizing big programs,\n\n6\n00:00:26,690 --> 00:00:33,180\nsymbolic manipulation a bit,\nsome of the technology that\n\n7\n00:00:33,180 --> 00:00:36,250\nyou use for establishing\nlanguages, one in terms of\n\n8\n00:00:36,250 --> 00:00:39,340\nanother, which is used for\norganizing very large\n\n9\n00:00:39,340 --> 00:00:43,160\nprograms. In fact, the nicest\nprograms I know look more like\n\n10\n00:00:43,160 --> 00:00:47,310\na pile of languages than like\na decomposition of a problem\n\n11\n00:00:47,310 --> 00:00:49,900\ninto parts.\n\n12\n00:00:49,900 --> 00:00:52,880\nWell, I suppose at this point,\nthere are still, however, a\n\n13\n00:00:52,880 --> 00:00:56,260\nfew mysteries about how this\nsort of stuff works.\n\n14\n00:00:56,260 --> 00:01:02,410\nAnd so what we'd like to do now\nis diverge from the plan\n\n15\n00:01:02,410 --> 00:01:06,060\nof telling you how to organize\nbig programs, and rather tell\n\n16\n00:01:06,060 --> 00:01:09,870\nyou something about the\nmechanisms by which these\n\n17\n00:01:09,870 --> 00:01:12,196\nthings can be made to work.\n\n18\n00:01:12,196 --> 00:01:18,652\nThe main reason for this is\ndemystification, if you will,\n\n19\n00:01:18,652 --> 00:01:21,930\nthat we have a lot of mysteries\nleft, like exactly\n\n20\n00:01:21,930 --> 00:01:27,260\nhow it is the case that a\nprogram is controlled, how a\n\n21\n00:01:27,260 --> 00:01:30,760\ncomputer knows what the next\nthing to do is, or\n\n22\n00:01:30,760 --> 00:01:32,430\nsomething like that.\n\n23\n00:01:32,430 --> 00:01:36,410\nAnd what I'd like to do now is\nmake that clear to you, that\n\n24\n00:01:36,410 --> 00:01:38,580\neven if you've never played\nwith a physical computer\n\n25\n00:01:38,580 --> 00:01:44,660\nbefore, the mechanism is really\nvery simple, and that\n\n26\n00:01:44,660 --> 00:01:47,650\nyou can understand it completely\nwith no trouble.\n\n27\n00:01:47,650 --> 00:01:51,390\nSo I'd like to start by\nimagining that we--\n\n28\n00:01:51,390 --> 00:01:53,190\nwell, the way we're going to do\nthis, by the way, is we're\n\n29\n00:01:53,190 --> 00:01:57,320\ngoing to take some very simple\nLisp programs, very simple\n\n30\n00:01:57,320 --> 00:02:02,160\nLisp programs, and transform\nthem into hardware.\n\n31\n00:02:02,160 --> 00:02:05,260\nI'm not going to worry about\nsome intermediate step of\n\n32\n00:02:05,260 --> 00:02:07,560\ngoing through some existing\ncomputer machine language and\n\n33\n00:02:07,560 --> 00:02:10,960\nthen showing you how that\ncomputer works, because that's\n\n34\n00:02:10,960 --> 00:02:12,750\nnot as illuminating.\n\n35\n00:02:12,750 --> 00:02:16,310\nSo what I'm really going to\nshow you is how a piece of\n\n36\n00:02:16,310 --> 00:02:21,130\nmachinery can be built to do a\njob that you have written down\n\n37\n00:02:21,130 --> 00:02:22,040\nas a program.\n\n38\n00:02:22,040 --> 00:02:25,760\nThat program is, in fact, a\ndescription of a machine.\n\n39\n00:02:25,760 --> 00:02:28,600\nWe're going to start with a very\nsimple program, proceed\n\n40\n00:02:28,600 --> 00:02:32,250\nto show you some simple\nmechanisms, proceed to a few\n\n41\n00:02:32,250 --> 00:02:36,660\nmore complicated programs, and\nthen later show you a not very\n\n42\n00:02:36,660 --> 00:02:40,360\ncomplicated program, how the\nevaluator transforms into a\n\n43\n00:02:40,360 --> 00:02:41,230\npiece of hardware.\n\n44\n00:02:41,230 --> 00:02:43,390\nAnd of course at that point,\nyou have made the universal\n\n45\n00:02:43,390 --> 00:02:47,510\ntransition and can execute any\nprogram imaginable with a\n\n46\n00:02:47,510 --> 00:02:48,800\npiece of well-defined\nhardware.\n\n47\n00:02:48,800 --> 00:02:51,392\n\n\n48\n00:02:51,392 --> 00:02:54,320\nWell, let's start up now, give\nyou a real concrete feeling\n\n49\n00:02:54,320 --> 00:02:55,440\nfor this sort of thing.\n\n50\n00:02:55,440 --> 00:02:59,600\nLet's start with a very\nsimple program.\n\n51\n00:02:59,600 --> 00:03:00,850\nHere's Euclid's algorithm.\n\n52\n00:03:00,850 --> 00:03:03,880\n\n\n53\n00:03:03,880 --> 00:03:06,140\nIt's actually a little\nbit more modern\n\n54\n00:03:06,140 --> 00:03:06,770\nthan Euclid's algorithm.\n\n55\n00:03:06,770 --> 00:03:09,010\nEuclid's algorithm for computing\nthe greatest common\n\n56\n00:03:09,010 --> 00:03:14,300\ndivisor of two numbers was\ninvented 350 BC, I think.\n\n57\n00:03:14,300 --> 00:03:15,550\nIt's the oldest known\nalgorithm.\n\n58\n00:03:15,550 --> 00:03:19,320\n\n\n59\n00:03:19,320 --> 00:03:23,440\nBut here we're going to talk\nabout GCD of A and B, the\n\n60\n00:03:23,440 --> 00:03:27,380\nGreatest Common Divisor or two\nnumbers, A and B. And the\n\n61\n00:03:27,380 --> 00:03:29,500\nalgorithm is extremely simple.\n\n62\n00:03:29,500 --> 00:03:38,170\nIf B is 0, then the result is\ngoing to be A. Otherwise, the\n\n63\n00:03:38,170 --> 00:03:52,990\nresult is the GCD of B and the\nremainder when A is divided by\n\n64\n00:03:52,990 --> 00:03:58,530\nB.\n\n65\n00:03:58,530 --> 00:04:02,030\nSo this we have here is a very\nsimple iterative process.\n\n66\n00:04:02,030 --> 00:04:05,550\nThis a simple recursive\nprocedure, recursively defined\n\n67\n00:04:05,550 --> 00:04:08,340\nprocedure, recursive definition,\nwhich yields an\n\n68\n00:04:08,340 --> 00:04:09,990\niterative process.\n\n69\n00:04:09,990 --> 00:04:13,840\nAnd the way it works is that\nevery step, it determines\n\n70\n00:04:13,840 --> 00:04:15,996\nwhether B was zero.\n\n71\n00:04:15,996 --> 00:04:21,660\nAnd if B is 0, we got the answer\nin A. Otherwise, we\n\n72\n00:04:21,660 --> 00:04:25,060\nmake another step where A is\nthe old B, and B is the\n\n73\n00:04:25,060 --> 00:04:31,110\nremainder of the old A divided\nby the old B. Very simple.\n\n74\n00:04:31,110 --> 00:04:33,900\nNow this, I've already told you\nsome of the mechanism by\n\n75\n00:04:33,900 --> 00:04:34,860\njust saying it that way.\n\n76\n00:04:34,860 --> 00:04:36,360\nI set it in time.\n\n77\n00:04:36,360 --> 00:04:39,710\nI said there are certain steps,\nand that, in fact, one\n\n78\n00:04:39,710 --> 00:04:42,510\nof the things you can see here\nis that one of the reasons why\n\n79\n00:04:42,510 --> 00:04:46,960\nthis is iterative is nothing is\nneeded of the last step to\n\n80\n00:04:46,960 --> 00:04:49,490\nget the answer.\n\n81\n00:04:49,490 --> 00:04:54,230\nAll of the information that's\nneeded to run this algorithm\n\n82\n00:04:54,230 --> 00:04:57,540\nis in A and B. It has two\nwell-defined state variables.\n\n83\n00:04:57,540 --> 00:05:00,470\n\n\n84\n00:05:00,470 --> 00:05:04,370\nSo I'm going to define a machine\nfor you that can\n\n85\n00:05:04,370 --> 00:05:06,560\ncompute you GCDs.\n\n86\n00:05:06,560 --> 00:05:07,120\nNow let's see.\n\n87\n00:05:07,120 --> 00:05:10,010\nEvery computer that's ever\nbeen made that's a\n\n88\n00:05:10,010 --> 00:05:13,490\nsingle-process computer, as\nopposed to a multiprocessor of\n\n89\n00:05:13,490 --> 00:05:17,840\nsome sort, is made according\nto the same plan.\n\n90\n00:05:17,840 --> 00:05:21,630\nThe plan is the computer has two\nparts, a part called the\n\n91\n00:05:21,630 --> 00:05:25,910\ndatapaths, and a part called\nthe controller.\n\n92\n00:05:25,910 --> 00:05:28,960\nThe datapaths correspond to a\ncalculator that you might\n\n93\n00:05:28,960 --> 00:05:31,580\nhave. It contains certain\nregisters that remember\n\n94\n00:05:31,580 --> 00:05:33,560\nthings, and you've all\nused calculators.\n\n95\n00:05:33,560 --> 00:05:37,030\nIt has some buttons on\nit and some lights.\n\n96\n00:05:37,030 --> 00:05:39,010\nAnd so by pushing the various\nbuttons, you can cause\n\n97\n00:05:39,010 --> 00:05:42,080\noperations to happen inside\nthere among the registers, and\n\n98\n00:05:42,080 --> 00:05:45,160\nsome of the results\nto be displayed.\n\n99\n00:05:45,160 --> 00:05:46,250\nThat's completely mechanical.\n\n100\n00:05:46,250 --> 00:05:50,900\nYou could imagine that box has\nno intelligence in it.\n\n101\n00:05:50,900 --> 00:05:52,400\nNow it might be very impressive\nthat it can produce\n\n102\n00:05:52,400 --> 00:05:57,670\nthe sine of a number, but that\nat least is apparently\n\n103\n00:05:57,670 --> 00:05:58,970\npossibly mechanical.\n\n104\n00:05:58,970 --> 00:06:00,685\nAt least, I could open that\nup in the same way I'm\n\n105\n00:06:00,685 --> 00:06:02,690\nabout to open GCD.\n\n106\n00:06:02,690 --> 00:06:04,830\nSo this may have a whole\ncomputer inside of it, but\n\n107\n00:06:04,830 --> 00:06:05,940\nthat's not interesting.\n\n108\n00:06:05,940 --> 00:06:08,200\nAddition is certainly simple.\n\n109\n00:06:08,200 --> 00:06:10,890\nThat can be done without\nany further mechanism.\n\n110\n00:06:10,890 --> 00:06:15,080\nNow also, if we were to look\nat the other half, the\n\n111\n00:06:15,080 --> 00:06:18,190\ncontroller, that's a part\nthat's dumb, too.\n\n112\n00:06:18,190 --> 00:06:20,350\nIt pushes the buttons.\n\n113\n00:06:20,350 --> 00:06:21,920\nIt pushes them according to the\nsequence, which is written\n\n114\n00:06:21,920 --> 00:06:26,290\ndown on a piece of paper,\nand observes the lights.\n\n115\n00:06:26,290 --> 00:06:29,210\nAnd every so often, it comes to\na place in a sequence that\n\n116\n00:06:29,210 --> 00:06:32,370\nsays, if light A is on,\ndo this sequence.\n\n117\n00:06:32,370 --> 00:06:34,620\nOtherwise, do that sequence.\n\n118\n00:06:34,620 --> 00:06:37,950\nAnd thereby, there's no\ncomplexity there either.\n\n119\n00:06:37,950 --> 00:06:42,510\nWell, let's just draw that and\nsee what we feel about that.\n\n120\n00:06:42,510 --> 00:06:48,270\nSo for computing GCDs, what I\nwant you to think about is\n\n121\n00:06:48,270 --> 00:06:50,310\nthat there are these\nregisters.\n\n122\n00:06:50,310 --> 00:06:53,240\nA register is a place where I\nstore a number, in this case.\n\n123\n00:06:53,240 --> 00:06:56,810\nAnd this one's called a.\n\n124\n00:06:56,810 --> 00:06:58,700\nAnd then there's another\none for storing b.\n\n125\n00:06:58,700 --> 00:07:03,170\n\n\n126\n00:07:03,170 --> 00:07:04,820\nNow we have to see what things\nwe can do with these\n\n127\n00:07:04,820 --> 00:07:08,150\nregisters, and they're not\nentirely obvious what you can\n\n128\n00:07:08,150 --> 00:07:09,840\ndo with them.\n\n129\n00:07:09,840 --> 00:07:10,940\nWell, we have to see\nwhat things we\n\n130\n00:07:10,940 --> 00:07:11,890\nneed to do with them.\n\n131\n00:07:11,890 --> 00:07:14,030\nWe're looking at the problem\nwe're trying to solve.\n\n132\n00:07:14,030 --> 00:07:17,100\nOne of the important things\nfor designing a computer,\n\n133\n00:07:17,100 --> 00:07:20,810\nwhich I think most designers\ndon't do, is you study the\n\n134\n00:07:20,810 --> 00:07:23,910\nproblem you want to solve and\nthen use what you learn from\n\n135\n00:07:23,910 --> 00:07:25,970\nstudying the problem you want\nto solve to put in the\n\n136\n00:07:25,970 --> 00:07:28,260\nmechanisms needed to solve\nit in the computer you're\n\n137\n00:07:28,260 --> 00:07:32,140\nbuilding, no more no less.\n\n138\n00:07:32,140 --> 00:07:34,440\nNow it may be that the problem\nyou're trying to solve is\n\n139\n00:07:34,440 --> 00:07:37,200\neverybody's problem, in which\ncase you have to build in a\n\n140\n00:07:37,200 --> 00:07:40,190\nuniversal interpreter\nof some language.\n\n141\n00:07:40,190 --> 00:07:42,580\nBut you shouldn't put any more\nin than required to build the\n\n142\n00:07:42,580 --> 00:07:44,540\nuniversal interpreter\nof some language.\n\n143\n00:07:44,540 --> 00:07:47,025\nWe'll worry about that\nin a second.\n\n144\n00:07:47,025 --> 00:07:49,930\nOK, going back to\nhere, let's see.\n\n145\n00:07:49,930 --> 00:07:51,640\nWhat do we have to\nbe able to do?\n\n146\n00:07:51,640 --> 00:07:56,580\nWell, somehow, we have to be\nable to get B into A. We have\n\n147\n00:07:56,580 --> 00:07:59,260\nto be able to get the old value\nof B into the value of\n\n148\n00:07:59,260 --> 00:08:03,340\nA. So we have to have some path\nby which stuff can flow,\n\n149\n00:08:03,340 --> 00:08:07,390\nwhatever this information\nis, from b to a.\n\n150\n00:08:07,390 --> 00:08:10,520\nI'm going to draw that with by\nan arrow saying that it is\n\n151\n00:08:10,520 --> 00:08:13,640\npossible to move the contents\nof b into a, replacing the\n\n152\n00:08:13,640 --> 00:08:15,120\nvalue of a.\n\n153\n00:08:15,120 --> 00:08:17,660\nAnd there's a little button\nhere which you push which\n\n154\n00:08:17,660 --> 00:08:19,710\nallows that to happen.\n\n155\n00:08:19,710 --> 00:08:23,070\nThat's what the little\nx is here.\n\n156\n00:08:23,070 --> 00:08:25,110\nNow it's also the case that I\nhave to be able to compute the\n\n157\n00:08:25,110 --> 00:08:27,000\nremainder of a and b.\n\n158\n00:08:27,000 --> 00:08:28,860\nNow that may be a complicated\nmess.\n\n159\n00:08:28,860 --> 00:08:31,960\nOn the other hand, I'm going\nto make it a small box.\n\n160\n00:08:31,960 --> 00:08:34,890\nIf we have to, we may open up\nthat box and look inside and\n\n161\n00:08:34,890 --> 00:08:37,740\nsee what it is.\n\n162\n00:08:37,740 --> 00:08:39,580\nSo here, I'm going to have a\nlittle box, which I'm going to\n\n163\n00:08:39,580 --> 00:08:46,440\ndraw this way, which we'll\ncall the remainder.\n\n164\n00:08:46,440 --> 00:08:48,265\nAnd it's going to take in a.\n\n165\n00:08:48,265 --> 00:08:50,910\n\n\n166\n00:08:50,910 --> 00:08:54,370\nThat's going to take in b.\n\n167\n00:08:54,370 --> 00:08:59,660\nAnd it's going to put out\nsomething, the remainder of a\n\n168\n00:08:59,660 --> 00:09:02,290\ndivided by b.\n\n169\n00:09:02,290 --> 00:09:04,050\nAnother thing we have to see\nhere is that we have to be\n\n170\n00:09:04,050 --> 00:09:08,000\nable to test whether\nb is equal to 0.\n\n171\n00:09:08,000 --> 00:09:10,020\nWell, that means somebody's\ngot to be looking at--\n\n172\n00:09:10,020 --> 00:09:13,390\na thing that's looking\nat the value of b.\n\n173\n00:09:13,390 --> 00:09:17,390\nI have a light bulb here which\nlights up if b equals 0.\n\n174\n00:09:17,390 --> 00:09:21,110\n\n\n175\n00:09:21,110 --> 00:09:24,030\nThat's its job.\n\n176\n00:09:24,030 --> 00:09:27,250\nAnd finally, I suppose, because\nof the fact that we\n\n177\n00:09:27,250 --> 00:09:30,640\nwant the new value of a to be\nthe old value of b, and\n\n178\n00:09:30,640 --> 00:09:33,820\nsimultaneously the new value of\nb to be something I've done\n\n179\n00:09:33,820 --> 00:09:38,160\nwith a, and if I plan to make\nmy machine such that\n\n180\n00:09:38,160 --> 00:09:41,620\neverything happens one at a\ntime, one motion at a time,\n\n181\n00:09:41,620 --> 00:09:44,526\nand I can't put two numbers in\na register, then I have to\n\n182\n00:09:44,526 --> 00:09:46,300\nhave another place to put one\nwhile I'm interchanging.\n\n183\n00:09:46,300 --> 00:09:49,534\n\n\n184\n00:09:49,534 --> 00:09:50,000\nOK?\n\n185\n00:09:50,000 --> 00:09:52,490\nI can't interchange the two\nthings in my hands, unless I\n\n186\n00:09:52,490 --> 00:09:54,730\neither put two in one hand and\nthen pull it back the other\n\n187\n00:09:54,730 --> 00:09:57,960\nway, or unless I put one down,\npick it up, and put the other\n\n188\n00:09:57,960 --> 00:10:02,930\none, like that, unless I'm a\njuggler, which I'm not, as you\n\n189\n00:10:02,930 --> 00:10:06,200\ncan see, in which case I have a\n\n190\n00:10:06,200 --> 00:10:08,850\npossibility of timing errors.\n\n191\n00:10:08,850 --> 00:10:11,500\nIn fact, much of the type of\ncomputer design people do\n\n192\n00:10:11,500 --> 00:10:15,260\ninvolves timing errors, of some\npotential timing errors,\n\n193\n00:10:15,260 --> 00:10:17,840\nwhich I don't much like.\n\n194\n00:10:17,840 --> 00:10:22,500\nSo for that reason, I have to\nhave a place to put the second\n\n195\n00:10:22,500 --> 00:10:23,410\none of them down.\n\n196\n00:10:23,410 --> 00:10:25,820\nSo I have a place called t,\nwhich is a register just for\n\n197\n00:10:25,820 --> 00:10:30,470\ntemporary, t, with\na button on it.\n\n198\n00:10:30,470 --> 00:10:32,450\nAnd then I'll take the result of\nthat, since I have to take\n\n199\n00:10:32,450 --> 00:10:35,640\nthat and put into b, over here,\nwe'll take the result of\n\n200\n00:10:35,640 --> 00:10:39,300\nthat and go like this,\nand a button here.\n\n201\n00:10:39,300 --> 00:10:42,430\n\n\n202\n00:10:42,430 --> 00:10:47,600\nSo that's the datapaths\nof a GCD machine.\n\n203\n00:10:47,600 --> 00:10:49,740\nNow what's the controller?\n\n204\n00:10:49,740 --> 00:10:52,280\nController's a very\nsimple thing, too.\n\n205\n00:10:52,280 --> 00:10:53,710\nThe machine has a state.\n\n206\n00:10:53,710 --> 00:10:59,010\nThe way I like to visualize that\nis that I've got a maze.\n\n207\n00:10:59,010 --> 00:11:01,680\nAnd the maze has a\nbunch of places\n\n208\n00:11:01,680 --> 00:11:04,430\nconnected by directed arrows.\n\n209\n00:11:04,430 --> 00:11:08,430\nAnd what I have is a marble,\nwhich represents the state of\n\n210\n00:11:08,430 --> 00:11:10,740\nthe controller.\n\n211\n00:11:10,740 --> 00:11:13,256\nThe marble rolls around\nin the maze.\n\n212\n00:11:13,256 --> 00:11:17,150\nOf course, this analogy breaks\ndown for energy reasons.\n\n213\n00:11:17,150 --> 00:11:19,310\nI sometimes have to pump the\nmarble up to the top, because\n\n214\n00:11:19,310 --> 00:11:22,000\nit's going to otherwise be a\nperpetual motion machine.\n\n215\n00:11:22,000 --> 00:11:24,270\nBut not worrying about\nthat, this is\n\n216\n00:11:24,270 --> 00:11:26,080\nnot a physical analogy.\n\n217\n00:11:26,080 --> 00:11:27,680\nThis marble rolls around.\n\n218\n00:11:27,680 --> 00:11:30,180\nAnd every time it rolls around\ncertain bumpers, like in a\n\n219\n00:11:30,180 --> 00:11:34,830\npinball machine, it pushes\none of these buttons.\n\n220\n00:11:34,830 --> 00:11:36,810\nAnd every so often, it comes\nto a place, which is a\n\n221\n00:11:36,810 --> 00:11:40,250\ndivision, where it has\nto make a choice.\n\n222\n00:11:40,250 --> 00:11:42,360\nAnd there's a flap, which\nis controlled by this.\n\n223\n00:11:42,360 --> 00:11:46,000\n\n\n224\n00:11:46,000 --> 00:11:48,820\nSo that's a really mechanical\nway of thinking about it.\n\n225\n00:11:48,820 --> 00:11:50,980\nOf course, controllers these\ndays, are not built that way\n\n226\n00:11:50,980 --> 00:11:51,840\nin real computers.\n\n227\n00:11:51,840 --> 00:11:54,090\nThey're built with\na little bit of\n\n228\n00:11:54,090 --> 00:11:56,610\nROM and a state register.\n\n229\n00:11:56,610 --> 00:11:59,726\nBut there was a time, like the\nDEC PDP-6, where that's how\n\n230\n00:11:59,726 --> 00:12:01,400\nyou built the controller\nof a machine.\n\n231\n00:12:01,400 --> 00:12:06,800\nThere was a bit that ran around\nthe delay line, and it\n\n232\n00:12:06,800 --> 00:12:08,580\ntriggered things\nas it went by.\n\n233\n00:12:08,580 --> 00:12:09,860\nAnd it would come back\nto the beginning and\n\n234\n00:12:09,860 --> 00:12:11,990\nget fed round again.\n\n235\n00:12:11,990 --> 00:12:13,630\nAnd of course, there were all\nsorts of great bugs you could\n\n236\n00:12:13,630 --> 00:12:17,670\nhave like two bits going\naround, two marbles.\n\n237\n00:12:17,670 --> 00:12:19,260\nAnd then the machine has\nlost its marbles.\n\n238\n00:12:19,260 --> 00:12:20,980\nThat happens, too.\n\n239\n00:12:20,980 --> 00:12:21,935\nOh, well.\n\n240\n00:12:21,935 --> 00:12:24,570\nSo anyway, for this machine,\nwhat I have\n\n241\n00:12:24,570 --> 00:12:25,940\nto do is the following.\n\n242\n00:12:25,940 --> 00:12:27,690\nI'm going to start\nmy maze here.\n\n243\n00:12:27,690 --> 00:12:30,520\n\n\n244\n00:12:30,520 --> 00:12:35,460\nAnd the first thing I've got\nto do, in a notation which\n\n245\n00:12:35,460 --> 00:12:41,540\nmany of you are familiar with,\nis b equal to zero, a test.\n\n246\n00:12:41,540 --> 00:12:44,540\nAnd there's a possibility,\neither yes, in\n\n247\n00:12:44,540 --> 00:12:45,790\nwhich case I'm done.\n\n248\n00:12:45,790 --> 00:12:49,790\n\n\n249\n00:12:49,790 --> 00:12:53,220\nOtherwise, if no, then\nI'm going have to\n\n250\n00:12:53,220 --> 00:12:54,725\nroll over some bumpers.\n\n251\n00:12:54,725 --> 00:12:57,420\nI'm going to do it in\nthe following order.\n\n252\n00:12:57,420 --> 00:13:04,050\nI want to do this interchange\ngame.\n\n253\n00:13:04,050 --> 00:13:07,360\nNow first, since I need both a\nand b, but then the first--\n\n254\n00:13:07,360 --> 00:13:08,670\nand this is not necessary--\n\n255\n00:13:08,670 --> 00:13:11,070\nI want to collect this.\n\n256\n00:13:11,070 --> 00:13:13,240\nThis is the thing that's\ngoing to go into b.\n\n257\n00:13:13,240 --> 00:13:15,680\nSo I'm going to say, take this,\nwhich depends upon both\n\n258\n00:13:15,680 --> 00:13:19,150\na and b, and put the remainder\ninto here.\n\n259\n00:13:19,150 --> 00:13:22,940\nSo I'm going to push this button\nfirst. Then, I'm going\n\n260\n00:13:22,940 --> 00:13:26,460\nto transfer b to a, push that\nbutton, and then I transfer\n\n261\n00:13:26,460 --> 00:13:32,030\nthe temporary into b,\npush that button.\n\n262\n00:13:32,030 --> 00:13:37,750\nSo a very sequential machine,\nit's very inefficient.\n\n263\n00:13:37,750 --> 00:13:39,810\nBut that's fine right now.\n\n264\n00:13:39,810 --> 00:13:42,305\nWe're going to name the buttons,\nt gets remainder.\n\n265\n00:13:42,305 --> 00:13:46,750\n\n\n266\n00:13:46,750 --> 00:13:50,036\na gets b.\n\n267\n00:13:50,036 --> 00:13:55,470\nAnd b gets t.\n\n268\n00:13:55,470 --> 00:13:59,150\nAnd then I'm going to go around\nhere and it's to go\n\n269\n00:13:59,150 --> 00:14:01,620\nback to start.\n\n270\n00:14:01,620 --> 00:14:03,870\nAnd if you look, what\nare we seeing here?\n\n271\n00:14:03,870 --> 00:14:05,080\nWe're seeing the various--\n\n272\n00:14:05,080 --> 00:14:07,400\nwhat I really have is some sort\nof mechanical connection,\n\n273\n00:14:07,400 --> 00:14:13,620\nwhere t gets r controls\nthis thing.\n\n274\n00:14:13,620 --> 00:14:16,830\n\n\n275\n00:14:16,830 --> 00:14:20,910\nAnd I have here that a gets b\ncontrols this fellow over\n\n276\n00:14:20,910 --> 00:14:28,120\nhere, and this fellow\nover here.\n\n277\n00:14:28,120 --> 00:14:31,090\nBoy, that's absolutely\npessimal,\n\n278\n00:14:31,090 --> 00:14:32,630\nthe inverse of optimal.\n\n279\n00:14:32,630 --> 00:14:34,590\nEvery line heads across every\nother line the way I drew it.\n\n280\n00:14:34,590 --> 00:14:38,540\n\n\n281\n00:14:38,540 --> 00:14:41,150\nI suppose this goes\nhere, b gets t.\n\n282\n00:14:41,150 --> 00:14:45,690\n\n\n283\n00:14:45,690 --> 00:14:48,040\nNow I'd like to run\nthis machine.\n\n284\n00:14:48,040 --> 00:14:50,260\nBut before I run the machine,\nI want to write down a\n\n285\n00:14:50,260 --> 00:14:52,243\ndescription of this controller,\njust so you can\n\n286\n00:14:52,243 --> 00:14:54,160\nsee that these things, of\ncourse, as usual, can be\n\n287\n00:14:54,160 --> 00:14:56,560\nwritten down in some nice\nlanguage, so that we don't\n\n288\n00:14:56,560 --> 00:14:59,010\nhave to always draw these\ndiagrams. One of the problems\n\n289\n00:14:59,010 --> 00:15:00,710\nwith diagrams is that they\ntake up a lot of space.\n\n290\n00:15:00,710 --> 00:15:03,220\nAnd for a machine this small,\nit takes two blackboards.\n\n291\n00:15:03,220 --> 00:15:05,690\nFor a machine that's the\nevaluator machine, I have\n\n292\n00:15:05,690 --> 00:15:08,320\ntrouble putting it into\nthis room, even though\n\n293\n00:15:08,320 --> 00:15:09,900\nit isn't very big.\n\n294\n00:15:09,900 --> 00:15:11,550\nSo I'm going to make a little\nlanguage for this that's just\n\n295\n00:15:11,550 --> 00:15:17,530\na description of that,\nsaying define a\n\n296\n00:15:17,530 --> 00:15:24,420\nmachine we'll call GCD.\n\n297\n00:15:24,420 --> 00:15:25,970\nOf course, once we have\nsomething like this, we have a\n\n298\n00:15:25,970 --> 00:15:27,220\nsimulator for it.\n\n299\n00:15:27,220 --> 00:15:29,630\nAnd the reason why we want to\nbuild a language in this form,\n\n300\n00:15:29,630 --> 00:15:31,500\nis because all of a sudden\nwe can manipulate these\n\n301\n00:15:31,500 --> 00:15:33,210\nexpressions that I'm\nwriting down.\n\n302\n00:15:33,210 --> 00:15:35,970\nAnd then of course I can write\nthings that can algebraically\n\n303\n00:15:35,970 --> 00:15:38,730\nmanipulate these things,\nsimulate them, all that sort\n\n304\n00:15:38,730 --> 00:15:41,255\nof things that I might want to\ndo, perhaps transform them as\n\n305\n00:15:41,255 --> 00:15:43,630\na layout, who knows.\n\n306\n00:15:43,630 --> 00:15:48,185\nOnce I have a nice\nrepresentation of registers,\n\n307\n00:15:48,185 --> 00:15:56,326\nit has certain registers, which\nwe can call A, B, and T.\n\n308\n00:15:56,326 --> 00:15:57,576\nAnd there's a controller.\n\n309\n00:15:57,576 --> 00:16:02,190\n\n\n310\n00:16:02,190 --> 00:16:04,910\nActually, a better language,\nwhich would be more explicit,\n\n311\n00:16:04,910 --> 00:16:09,440\nwould be one which named\nevery button also and\n\n312\n00:16:09,440 --> 00:16:10,420\nsaid what it did.\n\n313\n00:16:10,420 --> 00:16:13,390\nLike, this button causes the\ncontents of T to go to the\n\n314\n00:16:13,390 --> 00:16:16,310\ncontents of B. Well I don't want\nto do that, because it's\n\n315\n00:16:16,310 --> 00:16:18,410\nactually harder to read\nto do that, and it\n\n316\n00:16:18,410 --> 00:16:19,510\ntakes up more space.\n\n317\n00:16:19,510 --> 00:16:21,710\nSo I'm going to have that in\nthe instructions written in\n\n318\n00:16:21,710 --> 00:16:23,290\nthe controller.\n\n319\n00:16:23,290 --> 00:16:26,460\nIt's going to be implicit\nwhat the operations are.\n\n320\n00:16:26,460 --> 00:16:29,990\nThey can be deduced by reading\nthese and collecting together\n\n321\n00:16:29,990 --> 00:16:33,500\nall the different things\nthat can be done.\n\n322\n00:16:33,500 --> 00:16:35,482\nWell, let's just look at\nwhat these things are.\n\n323\n00:16:35,482 --> 00:16:42,550\nThere's a little loop that we\ngo around which says branch,\n\n324\n00:16:42,550 --> 00:16:47,430\nthis is the representation of\nthe little flap that decides\n\n325\n00:16:47,430 --> 00:16:58,010\nwhich way you go here, if 0\nfetch of B, the contents of B,\n\n326\n00:16:58,010 --> 00:17:00,790\nand if the contents of\nB is 0, then go to a\n\n327\n00:17:00,790 --> 00:17:03,640\nplace called done.\n\n328\n00:17:03,640 --> 00:17:06,030\nNow, one thing you're seeing\nhere, this looks very much\n\n329\n00:17:06,030 --> 00:17:08,170\nlike a traditional computer\nlanguage.\n\n330\n00:17:08,170 --> 00:17:13,099\nAnd what you're seeing here\nis things like labels that\n\n331\n00:17:13,099 --> 00:17:17,609\nrepresent places in a sequence\nwritten down as a sequence.\n\n332\n00:17:17,609 --> 00:17:21,700\nThe reason why they're needed\nis because over here, I've\n\n333\n00:17:21,700 --> 00:17:23,329\nwritten something with loops.\n\n334\n00:17:23,329 --> 00:17:26,569\nBut if I'm writing English text,\nor something like that,\n\n335\n00:17:26,569 --> 00:17:28,580\nit's hard to refer to a place.\n\n336\n00:17:28,580 --> 00:17:31,440\nI don't have arrows.\n\n337\n00:17:31,440 --> 00:17:33,450\nArrows are represented by giving\nnames to the places\n\n338\n00:17:33,450 --> 00:17:35,680\nwhere the arrows terminate, and\nthen referring to them by\n\n339\n00:17:35,680 --> 00:17:37,620\nthose names.\n\n340\n00:17:37,620 --> 00:17:39,860\nNow this is just an encoding.\n\n341\n00:17:39,860 --> 00:17:43,150\nThere's nothing magical about\nthings like that.\n\n342\n00:17:43,150 --> 00:17:45,310\nNext thing we're going to do is\nwe're going to say, how do\n\n343\n00:17:45,310 --> 00:17:46,840\nwe do T gets R?\n\n344\n00:17:46,840 --> 00:17:49,030\nOh, that's easy enough,\nassign.\n\n345\n00:17:49,030 --> 00:17:51,930\n\n\n346\n00:17:51,930 --> 00:17:56,400\nWe assign to T the remainder.\n\n347\n00:17:56,400 --> 00:18:01,470\nAssign is the name\nof the button.\n\n348\n00:18:01,470 --> 00:18:03,140\nThat's the button-pusher.\n\n349\n00:18:03,140 --> 00:18:05,910\nAssign to T the remainder, and\nhere's the representation of\n\n350\n00:18:05,910 --> 00:18:17,550\nthe operation, when we divide\nthe fetch of A by the fetch of\n\n351\n00:18:17,550 --> 00:18:23,478\nB.\n\n352\n00:18:23,478 --> 00:18:35,560\nAnd we're also going to assign\nto A the fetch of B, assign to\n\n353\n00:18:35,560 --> 00:18:50,140\nB the result of getting the\ncontents of T. And now I have\n\n354\n00:18:50,140 --> 00:18:53,280\nto refer to the beginning\nhere.\n\n355\n00:18:53,280 --> 00:18:55,760\nI see, why don't I call that\nloop like I have here?\n\n356\n00:18:55,760 --> 00:19:05,390\n\n\n357\n00:19:05,390 --> 00:19:07,610\nSo that's that reference\nto that arrow.\n\n358\n00:19:07,610 --> 00:19:08,950\nAnd when we're done,\nwe're done.\n\n359\n00:19:08,950 --> 00:19:14,340\nWe go to here, which is\nthe end of the thing.\n\n360\n00:19:14,340 --> 00:19:18,090\nSo here's just a written\nrepresentation of this\n\n361\n00:19:18,090 --> 00:19:21,660\nfragment of machinery that\nwe've drawn here.\n\n362\n00:19:21,660 --> 00:19:25,490\nNow the next thing I'd like\nto do is run this.\n\n363\n00:19:25,490 --> 00:19:27,620\nI want us to feel it running.\n\n364\n00:19:27,620 --> 00:19:31,010\nNever done this before,\nyou got to do it once.\n\n365\n00:19:31,010 --> 00:19:33,100\nSo let's take a particular\nproblem.\n\n366\n00:19:33,100 --> 00:19:38,580\nSuppose we want to compute\nthe GCD of a equals 30\n\n367\n00:19:38,580 --> 00:19:42,210\nand b equals 42.\n\n368\n00:19:42,210 --> 00:19:45,860\nI have no idea what\nthat is right now.\n\n369\n00:19:45,860 --> 00:19:50,530\nBut a 30 and b is 42.\n\n370\n00:19:50,530 --> 00:19:52,410\nSo that's how I start\nthis thing up.\n\n371\n00:19:52,410 --> 00:19:54,240\nWell, what's the first\nthing I do?\n\n372\n00:19:54,240 --> 00:19:57,590\nI say is B equal to 0, no.\n\n373\n00:19:57,590 --> 00:20:01,500\nThen assign to T the remainder\nof the fetch of A and the\n\n374\n00:20:01,500 --> 00:20:05,640\nfetch of B. Well the remainder\nof 30 when divided by\n\n375\n00:20:05,640 --> 00:20:11,130\n42 is itself 30.\n\n376\n00:20:11,130 --> 00:20:12,920\nPush that button.\n\n377\n00:20:12,920 --> 00:20:17,100\nNow the marble has\nrolled to here.\n\n378\n00:20:17,100 --> 00:20:21,220\nA gets B. That pushes\nthis button.\n\n379\n00:20:21,220 --> 00:20:26,360\nSo 42 moves into here.\n\n380\n00:20:26,360 --> 00:20:29,870\nB gets C. Push that button.\n\n381\n00:20:29,870 --> 00:20:32,225\nThe 30 goes here.\n\n382\n00:20:32,225 --> 00:20:34,660\nLet met just interchange them.\n\n383\n00:20:34,660 --> 00:20:38,280\nNow let's see, go back\nto the beginning.\n\n384\n00:20:38,280 --> 00:20:40,200\nB 0, no.\n\n385\n00:20:40,200 --> 00:20:43,230\nT gets the remainder.\n\n386\n00:20:43,230 --> 00:20:47,240\nI suppose the remainder when\ndividing 42 by 30 is 12.\n\n387\n00:20:47,240 --> 00:20:48,530\nI push that one.\n\n388\n00:20:48,530 --> 00:20:54,360\nNext thing I do is allow the\n30 to go to here, push this\n\n389\n00:20:54,360 --> 00:20:55,950\none, allow the 12\nto go to here.\n\n390\n00:20:55,950 --> 00:20:59,550\n\n\n391\n00:20:59,550 --> 00:21:00,380\nGo around this thing.\n\n392\n00:21:00,380 --> 00:21:01,530\nIs that done?\n\n393\n00:21:01,530 --> 00:21:02,360\nNo.\n\n394\n00:21:02,360 --> 00:21:05,080\nHow about--\n\n395\n00:21:05,080 --> 00:21:08,850\nso now I have to find out the\nremainder of 30 divided by 12.\n\n396\n00:21:08,850 --> 00:21:12,420\nAnd I believe that's 6.\n\n397\n00:21:12,420 --> 00:21:15,916\nSo 6 goes here on this\nbutton push.\n\n398\n00:21:15,916 --> 00:21:18,550\nThen the next thing I push\nis this one, which the\n\n399\n00:21:18,550 --> 00:21:23,730\n12 goes into here.\n\n400\n00:21:23,730 --> 00:21:25,090\nThen I push this button.\n\n401\n00:21:25,090 --> 00:21:26,340\nThe 6 gets into here.\n\n402\n00:21:26,340 --> 00:21:29,850\n\n\n403\n00:21:29,850 --> 00:21:32,100\nIs 6 equal to 0?\n\n404\n00:21:32,100 --> 00:21:33,420\nNo.\n\n405\n00:21:33,420 --> 00:21:34,380\nOK.\n\n406\n00:21:34,380 --> 00:21:38,380\nSo then at that point, the next\nthing to do is divide it.\n\n407\n00:21:38,380 --> 00:21:40,660\nOoh, this has got a\nremainder of 0.\n\n408\n00:21:40,660 --> 00:21:42,360\nLooks like we're almost done.\n\n409\n00:21:42,360 --> 00:21:44,360\nMove the 6 over here next.\n\n410\n00:21:44,360 --> 00:21:47,230\n\n\n411\n00:21:47,230 --> 00:21:49,090\n0 over here.\n\n412\n00:21:49,090 --> 00:21:50,200\nIs the answer 0?\n\n413\n00:21:50,200 --> 00:21:51,340\nYes.\n\n414\n00:21:51,340 --> 00:21:54,470\nB is 0, therefore the\nanswer is in A.\n\n415\n00:21:54,470 --> 00:21:56,610\nThe answer is 6.\n\n416\n00:21:56,610 --> 00:21:58,400\nAnd indeed that's right, because\nif we look at the\n\n417\n00:21:58,400 --> 00:22:07,060\noriginal problem, what we have\nis 30 is 2 times 3 times 5,\n\n418\n00:22:07,060 --> 00:22:11,670\nand 42 is 2 times 3 times 7.\n\n419\n00:22:11,670 --> 00:22:15,090\nSo the greatest common divisor\nis 2 times 3, which is 6.\n\n420\n00:22:15,090 --> 00:22:18,380\n\n\n421\n00:22:18,380 --> 00:22:20,780\nNow normally, we write one other\nlittle line here, just\n\n422\n00:22:20,780 --> 00:22:23,770\nto make it a little bit clearer,\nwhich is that we\n\n423\n00:22:23,770 --> 00:22:29,760\nleave in a connection saying\nthat this light is the guy\n\n424\n00:22:29,760 --> 00:22:31,010\nthat that flap looks at.\n\n425\n00:22:31,010 --> 00:22:34,050\n\n\n426\n00:22:34,050 --> 00:22:38,440\nOf course, any real machine\nhas a lot more complicated\n\n427\n00:22:38,440 --> 00:22:41,350\nthings in it than what\nI've just shown you.\n\n428\n00:22:41,350 --> 00:22:47,980\nLet's look for a second at\nthe first still store.\n\n429\n00:22:47,980 --> 00:22:50,190\nWow.\n\n430\n00:22:50,190 --> 00:22:52,850\nWell you see, for example, one\nthing we might want to do is\n\n431\n00:22:52,850 --> 00:22:56,840\nworry about the operations\nthat are of IO form.\n\n432\n00:22:56,840 --> 00:23:01,980\nAnd we may have to collect\nsomething from the outside.\n\n433\n00:23:01,980 --> 00:23:06,310\nSo a state machine that we might\nhave, the controller may\n\n434\n00:23:06,310 --> 00:23:11,190\nhave to, for example, get a\nvalue from something and put\n\n435\n00:23:11,190 --> 00:23:13,490\nregister a to load it up.\n\n436\n00:23:13,490 --> 00:23:17,070\nI have to master load up\nregister b with another value.\n\n437\n00:23:17,070 --> 00:23:19,900\nAnd then later, when I'm done,\nI might want to print the\n\n438\n00:23:19,900 --> 00:23:20,970\nanswer out.\n\n439\n00:23:20,970 --> 00:23:26,250\nAnd of course, that might be\neither simple or complicated.\n\n440\n00:23:26,250 --> 00:23:28,320\nI'm writing, assuming print\nis very simple, and\n\n441\n00:23:28,320 --> 00:23:29,880\nread is very simple.\n\n442\n00:23:29,880 --> 00:23:31,700\nBut in fact, in the real\nworld, those are very\n\n443\n00:23:31,700 --> 00:23:34,930\ncomplicated operations, usually\nmuch, much larger and\n\n444\n00:23:34,930 --> 00:23:37,080\nmore complicated than the thing\nyou're doing as your\n\n445\n00:23:37,080 --> 00:23:38,330\nproblem you're trying\nto solve.\n\n446\n00:23:38,330 --> 00:23:41,670\n\n\n447\n00:23:41,670 --> 00:23:45,060\nOn the other hand, I can\nremember a time when, I\n\n448\n00:23:45,060 --> 00:23:49,320\nremember using IBM 7090 computer\nof sorts, where\n\n449\n00:23:49,320 --> 00:23:53,600\nthings like read and write of\na single object, a single\n\n450\n00:23:53,600 --> 00:23:58,040\nnumber, a number, is a primitive\noperation of the IO\n\n451\n00:23:58,040 --> 00:23:59,065\ncontroller.\n\n452\n00:23:59,065 --> 00:24:00,400\nOK?\n\n453\n00:24:00,400 --> 00:24:02,330\nAnd so we have that kind\nof thing in there.\n\n454\n00:24:02,330 --> 00:24:08,360\nAnd in such a machine, well,\nwhat are we really doing?\n\n455\n00:24:08,360 --> 00:24:11,110\nWe're just saying that there's\na source over here called\n\n456\n00:24:11,110 --> 00:24:14,660\n\"read,\" which is an operation\nwhich always has a value.\n\n457\n00:24:14,660 --> 00:24:17,480\nWe have to think about this as\nalways having a value which\n\n458\n00:24:17,480 --> 00:24:21,660\ncan be gated into either\nregister a or b.\n\n459\n00:24:21,660 --> 00:24:24,290\nAnd print is some sort of thing\nwhich when you gate it\n\n460\n00:24:24,290 --> 00:24:27,410\nappropriately, when you push the\nbutton on it, will cause a\n\n461\n00:24:27,410 --> 00:24:31,660\nprint of the value that's\ncurrently in register a.\n\n462\n00:24:31,660 --> 00:24:33,050\nNothing very exciting.\n\n463\n00:24:33,050 --> 00:24:36,110\nSo that's one sort of thing you\nmight want to have. But\n\n464\n00:24:36,110 --> 00:24:37,260\nthese are also other\nthings that are\n\n465\n00:24:37,260 --> 00:24:38,320\na little bit worrisome.\n\n466\n00:24:38,320 --> 00:24:41,050\nLike I've used here some\ncomplicated mechanisms.\n\n467\n00:24:41,050 --> 00:24:43,850\nWhat you see here\nis remainder.\n\n468\n00:24:43,850 --> 00:24:44,690\nWhat is that?\n\n469\n00:24:44,690 --> 00:24:46,920\nThat may not be so obvious\nhow to compute.\n\n470\n00:24:46,920 --> 00:24:49,860\nIt may be something which when\nyou open it up, you get a\n\n471\n00:24:49,860 --> 00:24:51,880\nwhole machine.\n\n472\n00:24:51,880 --> 00:24:52,720\nOK?\n\n473\n00:24:52,720 --> 00:24:54,540\nIn fact, that's true.\n\n474\n00:24:54,540 --> 00:24:59,570\nFor example, if I write down the\nprogram for remainder, the\n\n475\n00:24:59,570 --> 00:25:04,480\nsimplest program for it is\nby repeated subtraction.\n\n476\n00:25:04,480 --> 00:25:06,380\nBecause of course, division\ncan be done by repeated\n\n477\n00:25:06,380 --> 00:25:09,800\nsubtraction of numbers,\nof integers.\n\n478\n00:25:09,800 --> 00:25:30,270\nSo the remainder of N divided by\nD is nothing more than if N\n\n479\n00:25:30,270 --> 00:25:34,920\nis less than D, then the result\nis N. Otherwise, it's\n\n480\n00:25:34,920 --> 00:25:48,350\nthe remainder when we subtract\nD from N with respect to D,\n\n481\n00:25:48,350 --> 00:25:52,160\nwhen divided by D. Gee,\nthis looks just\n\n482\n00:25:52,160 --> 00:25:56,890\nlike the GCD program.\n\n483\n00:25:56,890 --> 00:25:59,750\nOf course, it's not a very nice\nway to do remainders.\n\n484\n00:25:59,750 --> 00:26:01,525\nYou'd really want to use\nsomething like binary notation\n\n485\n00:26:01,525 --> 00:26:05,550\nand shift and things like that\nin a practical computer.\n\n486\n00:26:05,550 --> 00:26:09,060\nBut the point of that is that\nif I open this thing up, I\n\n487\n00:26:09,060 --> 00:26:11,880\nmight find inside of\nit a computer.\n\n488\n00:26:11,880 --> 00:26:13,510\nOh, we know how to do that.\n\n489\n00:26:13,510 --> 00:26:15,640\nWe just made one.\n\n490\n00:26:15,640 --> 00:26:17,400\nAnd it could be another\nthing just like this.\n\n491\n00:26:17,400 --> 00:26:20,030\nOn the other hand, we might want\nto make a more efficient\n\n492\n00:26:20,030 --> 00:26:22,810\nor better-structured machine,\nor maybe make use of some of\n\n493\n00:26:22,810 --> 00:26:25,340\nthe registers more than once,\nor some horrible mess like\n\n494\n00:26:25,340 --> 00:26:27,550\nthat that hardware designers\nlike to do, and\n\n495\n00:26:27,550 --> 00:26:29,250\nfor very good reasons.\n\n496\n00:26:29,250 --> 00:26:32,990\nSo for example, here's a machine\nthat you see, which\n\n497\n00:26:32,990 --> 00:26:35,050\nyou're not supposed to\nbe able to read.\n\n498\n00:26:35,050 --> 00:26:37,520\nIt's a little bit complicated.\n\n499\n00:26:37,520 --> 00:26:41,830\nBut what it is is the\nintegration of the remainder\n\n500\n00:26:41,830 --> 00:26:44,210\ninto the GCD machine.\n\n501\n00:26:44,210 --> 00:26:46,020\nAnd it takes, in fact,\nno more registers.\n\n502\n00:26:46,020 --> 00:26:48,360\nThere are three registers\nin the datapaths.\n\n503\n00:26:48,360 --> 00:26:49,050\nOK?\n\n504\n00:26:49,050 --> 00:26:51,550\nBut now there's a subtractor.\n\n505\n00:26:51,550 --> 00:26:53,020\nThere are two things\nthat are tested.\n\n506\n00:26:53,020 --> 00:26:57,250\nIs b equal to 0, or\nis t less than b?\n\n507\n00:26:57,250 --> 00:27:00,800\nAnd then the controller, which\nyou see over here, is not much\n\n508\n00:27:00,800 --> 00:27:01,850\nmore complicated.\n\n509\n00:27:01,850 --> 00:27:07,040\nBut it has two loops in it, one\nof which is the main one\n\n510\n00:27:07,040 --> 00:27:10,370\nfor doing the GCD, and one of\nwhich is the subtraction loop\n\n511\n00:27:10,370 --> 00:27:14,030\nfor doing the remainder\nsub-operation.\n\n512\n00:27:14,030 --> 00:27:17,190\nAnd there are ways, of course,\nof, if you think about it,\n\n513\n00:27:17,190 --> 00:27:19,920\ntaking the remainder program.\n\n514\n00:27:19,920 --> 00:27:22,270\nIf I take remainder, as you see\nover there, as a lambda\n\n515\n00:27:22,270 --> 00:27:25,920\nexpression, substitute it in for\nremainder over here in the\n\n516\n00:27:25,920 --> 00:27:30,910\nGCD program, then do some\nsimplification by substituting\n\n517\n00:27:30,910 --> 00:27:34,670\na and b for remainder\nin there, then I\n\n518\n00:27:34,670 --> 00:27:36,630\ncan unwind this loop.\n\n519\n00:27:36,630 --> 00:27:41,660\nAnd I can get this piece of\nmachinery by basically, a\n\n520\n00:27:41,660 --> 00:27:44,700\nlittle bit of algebraic\nsimplification on the lambda\n\n521\n00:27:44,700 --> 00:27:45,950\nexpressions.\n\n522\n00:27:45,950 --> 00:27:48,550\n\n\n523\n00:27:48,550 --> 00:27:50,140\nSo I suppose you've seen\nyour first very\n\n524\n00:27:50,140 --> 00:27:52,280\nsimple machines now.\n\n525\n00:27:52,280 --> 00:27:53,530\nAre there any questions?\n\n526\n00:27:53,530 --> 00:28:02,700\n\n\n527\n00:28:02,700 --> 00:28:05,360\nGood.\n\n528\n00:28:05,360 --> 00:28:06,610\nThis looks easy, doesn't it?\n\n529\n00:28:06,610 --> 00:28:10,200\n\n\n530\n00:28:10,200 --> 00:28:10,550\nThank you.\n\n531\n00:28:10,550 --> 00:28:11,350\nI suppose, take a break.\n\n532\n00:28:11,350 --> 00:28:11,760\n[MUSIC PLAYING - \"JESU, JOY OF\nMAN'S DESIRING\" BY JOHANN\n\n533\n00:28:11,760 --> 00:28:13,010\nSEBASTIAN BACH]\n\n534\n00:28:13,010 --> 00:28:47,310\n\n\n535\n00:28:47,310 --> 00:28:49,480\nPROFESSOR: Well, let's see.\n\n536\n00:28:49,480 --> 00:28:52,750\nNow you know how to make an\niterative procedure, or a\n\n537\n00:28:52,750 --> 00:28:53,930\nprocedure that yields\nan iterative\n\n538\n00:28:53,930 --> 00:28:57,770\nprocess, turn into a machine.\n\n539\n00:28:57,770 --> 00:28:59,750\nI suppose the next thing we\nwant to do is worry about\n\n540\n00:28:59,750 --> 00:29:02,690\nthings that reveal recursive\nprocesses.\n\n541\n00:29:02,690 --> 00:29:04,695\nSo let's play with a simple\nfactorial procedure.\n\n542\n00:29:04,695 --> 00:29:10,894\n\n\n543\n00:29:10,894 --> 00:29:24,690\nWe define factorial of N to be\nif n is 1, the result is 1,\n\n544\n00:29:24,690 --> 00:29:26,830\nusing 1 right now to decrease\nthe amount of work I have to\n\n545\n00:29:26,830 --> 00:29:33,940\ndo to simulate it, else it's\ntimes N factorial N minus 1.\n\n546\n00:29:33,940 --> 00:29:42,520\n\n\n547\n00:29:42,520 --> 00:29:47,440\nAnd what's different with this\nprogram, as you know, is that\n\n548\n00:29:47,440 --> 00:29:51,050\nafter I've computed factorial\nof N minus 1 here, I have to\n\n549\n00:29:51,050 --> 00:29:52,260\ndo something to the result.\n\n550\n00:29:52,260 --> 00:29:56,000\nI have to multiply it by N.\n\n551\n00:29:56,000 --> 00:30:00,160\nSo the only way I can visualize\nwhat this machine is\n\n552\n00:30:00,160 --> 00:30:02,360\ndoing, because of the fact--\n\n553\n00:30:02,360 --> 00:30:05,320\nthink of it this way, that I\nhave a machine out here which\n\n554\n00:30:05,320 --> 00:30:07,530\nsomehow needs a factorial\nmachine in order to compute\n\n555\n00:30:07,530 --> 00:30:09,320\nits answer.\n\n556\n00:30:09,320 --> 00:30:12,550\nBut this machine, the outer\nmachine, has to exist before\n\n557\n00:30:12,550 --> 00:30:16,800\nand after the factorial machine,\nwhich is inside.\n\n558\n00:30:16,800 --> 00:30:20,080\nWhereas in the iterative case,\nthe outer machine doesn't need\n\n559\n00:30:20,080 --> 00:30:25,170\nto exist after the inner machine\nis running, because\n\n560\n00:30:25,170 --> 00:30:26,580\nyou never need to go\nback to the outer\n\n561\n00:30:26,580 --> 00:30:28,640\nmachine to do anything.\n\n562\n00:30:28,640 --> 00:30:31,200\nSo here we have a problem where\nwe have a machine which\n\n563\n00:30:31,200 --> 00:30:34,090\nhas the same machine\ninside of it, an\n\n564\n00:30:34,090 --> 00:30:35,340\ninfinitely large machine.\n\n565\n00:30:35,340 --> 00:30:40,390\n\n\n566\n00:30:40,390 --> 00:30:42,310\nAnd it's got other things\ninside of it, like a\n\n567\n00:30:42,310 --> 00:30:47,240\nmultiplier, which takes some\ninputs, and there's a minus 1\n\n568\n00:30:47,240 --> 00:30:50,690\nbox, and things like that.\n\n569\n00:30:50,690 --> 00:30:54,370\nYou can imagine that's\nwhat it looks like.\n\n570\n00:30:54,370 --> 00:30:57,340\nBut the important thing is that\nhere I have something\n\n571\n00:30:57,340 --> 00:31:00,360\nthat happens before and after,\nin the outer machine, the\n\n572\n00:31:00,360 --> 00:31:02,540\nexecution of the\ninner machine.\n\n573\n00:31:02,540 --> 00:31:05,570\nSo this machine has\nto have a life.\n\n574\n00:31:05,570 --> 00:31:13,490\nIt has to exist on both times\nsides of this machine.\n\n575\n00:31:13,490 --> 00:31:16,770\nSo somehow, I have to have a\nplace to store the things that\n\n576\n00:31:16,770 --> 00:31:20,030\nthis thing needs to run.\n\n577\n00:31:20,030 --> 00:31:24,140\nInfinite objects don't exist\nin the real world.\n\n578\n00:31:24,140 --> 00:31:27,020\nWhat we have to do is arrange\nan illusion that we have an\n\n579\n00:31:27,020 --> 00:31:28,540\ninfinite object, we\nhave an infinite\n\n580\n00:31:28,540 --> 00:31:31,830\namount of hardware somewhere.\n\n581\n00:31:31,830 --> 00:31:36,280\nNow of course, illusion's\nall that really matters.\n\n582\n00:31:36,280 --> 00:31:39,370\nIf we can arrange that every\ntime you look at some infinite\n\n583\n00:31:39,370 --> 00:31:44,800\nobject, the part of it that\nyou look at is there, then\n\n584\n00:31:44,800 --> 00:31:47,390\nit's as infinite as\nyou need it to be.\n\n585\n00:31:47,390 --> 00:31:49,830\nAnd of course, one of the things\nwe might want to do,\n\n586\n00:31:49,830 --> 00:31:53,890\njust look at this thing over\nhere, is the organization that\n\n587\n00:31:53,890 --> 00:32:01,390\nwe've had so far involves having\na part of the machine,\n\n588\n00:32:01,390 --> 00:32:05,140\nwhich is the controller, which\nsits right over here, which is\n\n589\n00:32:05,140 --> 00:32:09,170\nperfectly finite and\nvery simple.\n\n590\n00:32:09,170 --> 00:32:11,070\nWe have some datapaths,\nwhich consist of\n\n591\n00:32:11,070 --> 00:32:13,080\nregisters and operators.\n\n592\n00:32:13,080 --> 00:32:16,190\nAnd what I propose to do here is\ndecompose the machine into\n\n593\n00:32:16,190 --> 00:32:19,260\ntwo parts, such that there is a\npart which is fundamentally\n\n594\n00:32:19,260 --> 00:32:22,770\nfinite, and some part where a\ncertain amount of infinite\n\n595\n00:32:22,770 --> 00:32:24,230\nstuff can be kept.\n\n596\n00:32:24,230 --> 00:32:27,050\nOn the other hand this is very\nsimple and really isn't\n\n597\n00:32:27,050 --> 00:32:29,430\ninfinite, but it's\njust very large.\n\n598\n00:32:29,430 --> 00:32:31,840\nBut it's so simple that it could\nbe cheaply reproduced in\n\n599\n00:32:31,840 --> 00:32:37,550\nsuch large amounts, we call it\nmemory, that we can make a\n\n600\n00:32:37,550 --> 00:32:40,710\nstructure called a stack out of\nit which will allow us to,\n\n601\n00:32:40,710 --> 00:32:43,280\nin fact, simulate the existence\nof an infinite\n\n602\n00:32:43,280 --> 00:32:44,650\nmachine which is made\nout of a recursive\n\n603\n00:32:44,650 --> 00:32:48,340\nnest of many machines.\n\n604\n00:32:48,340 --> 00:32:51,760\nAnd the way it's going to work\nis that we're going to store\n\n605\n00:32:51,760 --> 00:32:56,290\nin this place called the stack\nthe information required after\n\n606\n00:32:56,290 --> 00:33:00,400\nthe inner machine runs to resume\nthe operation of the\n\n607\n00:33:00,400 --> 00:33:01,650\nouter machine.\n\n608\n00:33:01,650 --> 00:33:03,840\n\n\n609\n00:33:03,840 --> 00:33:06,760\nSo it will remember the\nimportant things about the\n\n610\n00:33:06,760 --> 00:33:09,510\nlife of the outer machine that\nwill be needed for this\n\n611\n00:33:09,510 --> 00:33:11,390\ncomputation.\n\n612\n00:33:11,390 --> 00:33:15,380\nSince, of course, these machines\nare nested in a\n\n613\n00:33:15,380 --> 00:33:20,320\nrecursive manner, then in fact\nthe stack will only be\n\n614\n00:33:20,320 --> 00:33:25,330\naccessed in a manner which is\nthe last thing that goes in is\n\n615\n00:33:25,330 --> 00:33:26,580\nthe first thing that\ncomes out.\n\n616\n00:33:26,580 --> 00:33:29,330\n\n\n617\n00:33:29,330 --> 00:33:31,510\nSo we'll only need to access\nsome little part\n\n618\n00:33:31,510 --> 00:33:34,930\nof this stack memory.\n\n619\n00:33:34,930 --> 00:33:36,810\nOK, well, let's do it.\n\n620\n00:33:36,810 --> 00:33:38,750\nI'm going to build you a\ndatapath now, and I'm going to\n\n621\n00:33:38,750 --> 00:33:40,370\nwrite the controller.\n\n622\n00:33:40,370 --> 00:33:42,090\nAnd then we're going\nto execute this to\n\n623\n00:33:42,090 --> 00:33:43,510\nsee how you do it.\n\n624\n00:33:43,510 --> 00:33:47,900\nSo the factorial machine\nisn't so bad.\n\n625\n00:33:47,900 --> 00:33:52,660\nIt's going to have a register\ncalled the value, where the\n\n626\n00:33:52,660 --> 00:33:59,890\nanswer is going to be stored,\nand a registered called N,\n\n627\n00:33:59,890 --> 00:34:02,330\nwhich is where the number I'm\ntaking factorial will be\n\n628\n00:34:02,330 --> 00:34:04,165\nstored, factorial of.\n\n629\n00:34:04,165 --> 00:34:09,780\nAnd it will be necessary in some\ninstances to connect VAL\n\n630\n00:34:09,780 --> 00:34:11,760\nto N.\n\n631\n00:34:11,760 --> 00:34:16,389\nIn fact, one nice case of this\nis if I just said over here,\n\n632\n00:34:16,389 --> 00:34:19,139\nN, because that would be\nright for N equal 1N.\n\n633\n00:34:19,139 --> 00:34:21,389\nAnd I could just move\nthe answer over\n\n634\n00:34:21,389 --> 00:34:23,909\nthere if that's important.\n\n635\n00:34:23,909 --> 00:34:26,980\nI'm not worried about\nthat right now.\n\n636\n00:34:26,980 --> 00:34:29,060\nAnd there are things I have\nto be able to do.\n\n637\n00:34:29,060 --> 00:34:32,650\nLike I have to be able to, as\nwe see here, multiply N by\n\n638\n00:34:32,650 --> 00:34:36,350\nsomething in VAL, because\nVAL is the result\n\n639\n00:34:36,350 --> 00:34:38,290\nof computing factorial.\n\n640\n00:34:38,290 --> 00:34:41,429\nAnd I have to put the result\nback into VAL.\n\n641\n00:34:41,429 --> 00:34:45,639\nSo here we can see that the\nresult of computing a\n\n642\n00:34:45,639 --> 00:34:48,070\nfactorial is N times the result\n\n643\n00:34:48,070 --> 00:34:50,690\nof computing a factorial.\n\n644\n00:34:50,690 --> 00:34:52,770\nVAL will be the representation\nof the answer\n\n645\n00:34:52,770 --> 00:34:55,199\nof the inner factorial.\n\n646\n00:34:55,199 --> 00:35:02,525\nAnd so I'm going to have to have\na multiplier here, which\n\n647\n00:35:02,525 --> 00:35:09,350\nis going to sample the value of\nN and the value of VAL and\n\n648\n00:35:09,350 --> 00:35:17,170\nput the result back into\nVAL like that.\n\n649\n00:35:17,170 --> 00:35:20,618\nI'm also going to have to be\nable to see if N is 1.\n\n650\n00:35:20,618 --> 00:35:22,230\nSo I need a light bulb.\n\n651\n00:35:22,230 --> 00:35:28,200\n\n\n652\n00:35:28,200 --> 00:35:31,270\nAnd I suppose the other thing\nI'm going to need to have is a\n\n653\n00:35:31,270 --> 00:35:38,260\nway of decrementing N. So I'm\ngoing to have a decrementer,\n\n654\n00:35:38,260 --> 00:35:46,620\nwhich takes N and is going to\nput back the result into N.\n\n655\n00:35:46,620 --> 00:35:49,550\nThat's pretty much what\nI need in my machine.\n\n656\n00:35:49,550 --> 00:35:51,985\nNow, there's a little\nbit else I need.\n\n657\n00:35:51,985 --> 00:35:55,620\nIt's a little bit more\ncomplicated, because I'm also\n\n658\n00:35:55,620 --> 00:35:58,925\ngoing to need a way to store, to\nsave away, the things that\n\n659\n00:35:58,925 --> 00:36:02,600\nare going to be needed for\nresuming the computation of a\n\n660\n00:36:02,600 --> 00:36:06,250\nfactorial after I've done\na sub-factorial.\n\n661\n00:36:06,250 --> 00:36:07,230\nWhat's that?\n\n662\n00:36:07,230 --> 00:36:09,850\nOne thing I need is N.\n\n663\n00:36:09,850 --> 00:36:11,870\nSo I'm going to build here\na thing called a stack.\n\n664\n00:36:11,870 --> 00:36:14,700\n\n\n665\n00:36:14,700 --> 00:36:24,130\nThe stack is a bunch of stuff\nthat I'm going to write in\n\n666\n00:36:24,130 --> 00:36:25,380\nsequentially.\n\n667\n00:36:25,380 --> 00:36:27,410\n\n\n668\n00:36:27,410 --> 00:36:28,916\nI don't how long it is.\n\n669\n00:36:28,916 --> 00:36:32,890\nThe longer it is, the better\nmy illusion of infinity.\n\n670\n00:36:32,890 --> 00:36:36,036\nAnd I'm going to have to have a\nway of getting stuff out of\n\n671\n00:36:36,036 --> 00:36:39,515\nN and into the stack\nand vice versa.\n\n672\n00:36:39,515 --> 00:36:44,740\nSo I'm going to need a\nconnection like this, which is\n\n673\n00:36:44,740 --> 00:36:52,500\ntwo-way, whereby I can save\nthe value of N and then\n\n674\n00:36:52,500 --> 00:36:55,820\nrestore it some other time\nthrough that connection.\n\n675\n00:36:55,820 --> 00:36:58,100\nThis is the stack.\n\n676\n00:36:58,100 --> 00:37:02,790\nI also need a way of remembering\nwhere I was in the\n\n677\n00:37:02,790 --> 00:37:08,530\ncomputation of factorial\nin the outer program.\n\n678\n00:37:08,530 --> 00:37:11,090\nNow in the case of\nthis machine, it\n\n679\n00:37:11,090 --> 00:37:14,090\nisn't very much a problem.\n\n680\n00:37:14,090 --> 00:37:18,020\nFactorial always returns, has to\ngo back to the place where\n\n681\n00:37:18,020 --> 00:37:21,650\nwe multiply by N, except for the\nlast time, when it has to\n\n682\n00:37:21,650 --> 00:37:23,110\nreturn to whatever needs\nthe factorial or\n\n683\n00:37:23,110 --> 00:37:25,660\ngo to done or stop.\n\n684\n00:37:25,660 --> 00:37:28,245\nHowever, in general, I'm going\nto have to remember where I\n\n685\n00:37:28,245 --> 00:37:30,570\nhave been, because I might have\ncomputed factorial from\n\n686\n00:37:30,570 --> 00:37:31,770\nsomewhere else.\n\n687\n00:37:31,770 --> 00:37:36,070\nI have to go back to that place\nand continue there.\n\n688\n00:37:36,070 --> 00:37:37,990\nSo I'm going to have to have\nsome way of taking the place\n\n689\n00:37:37,990 --> 00:37:41,500\nwhere the marble is in the\nfinite state controller, the\n\n690\n00:37:41,500 --> 00:37:45,390\nstate of the controller,\nand storing that in\n\n691\n00:37:45,390 --> 00:37:47,400\nthe stack as well.\n\n692\n00:37:47,400 --> 00:37:49,840\nAnd I'm going to have to have\nways of restoring that back to\n\n693\n00:37:49,840 --> 00:37:51,870\nthe state of the-- the marble.\n\n694\n00:37:51,870 --> 00:37:53,570\nSo I have to have something that\nmoves the marble to the\n\n695\n00:37:53,570 --> 00:37:54,310\nright place.\n\n696\n00:37:54,310 --> 00:37:57,462\nWell, we're going to have a\nplace which is the marble now.\n\n697\n00:37:57,462 --> 00:38:09,220\nAnd it's called the continue\nregister, called continue,\n\n698\n00:38:09,220 --> 00:38:11,480\nwhich is the place to\nput the marble next\n\n699\n00:38:11,480 --> 00:38:14,260\ntime I go to continue.\n\n700\n00:38:14,260 --> 00:38:16,140\nThat's what that's for.\n\n701\n00:38:16,140 --> 00:38:17,990\nAnd so there's got to be some\npath from that into the\n\n702\n00:38:17,990 --> 00:38:19,240\ncontroller.\n\n703\n00:38:19,240 --> 00:38:22,910\n\n\n704\n00:38:22,910 --> 00:38:29,074\nI also have to have some way of\nsaving that on the stack.\n\n705\n00:38:29,074 --> 00:38:32,120\nAnd I have to have some way\nof setting that up to have\n\n706\n00:38:32,120 --> 00:38:36,860\nvarious constants, a certain\nfixed number of constants.\n\n707\n00:38:36,860 --> 00:38:38,840\nAnd that's very easy\nto arrange.\n\n708\n00:38:38,840 --> 00:38:40,180\nSo let's have some\nconstants here.\n\n709\n00:38:40,180 --> 00:38:41,430\nWe'll call this one\nafter-fact.\n\n710\n00:38:41,430 --> 00:38:47,430\n\n\n711\n00:38:47,430 --> 00:38:50,890\nAnd that's a constant which\nwe'll get into the continue\n\n712\n00:38:50,890 --> 00:38:54,010\nregister, and also another\none called fact-done.\n\n713\n00:38:54,010 --> 00:39:05,210\n\n\n714\n00:39:05,210 --> 00:39:08,130\nSo this is the machine\nI want to build.\n\n715\n00:39:08,130 --> 00:39:10,810\nThat's its datapaths, at least.\nAnd it mixes a little\n\n716\n00:39:10,810 --> 00:39:12,790\nwith the controller here,\nbecause of the fact that I\n\n717\n00:39:12,790 --> 00:39:15,220\nhave to remember where\nI was and restore\n\n718\n00:39:15,220 --> 00:39:17,300\nmyself to that place.\n\n719\n00:39:17,300 --> 00:39:19,310\nBut let's write the program\nnow which represents the\n\n720\n00:39:19,310 --> 00:39:20,390\ncontroller.\n\n721\n00:39:20,390 --> 00:39:22,760\nI'm not going to write the\ndefine machine thing and the\n\n722\n00:39:22,760 --> 00:39:24,890\nregister list, because that's\nnot very interesting.\n\n723\n00:39:24,890 --> 00:39:28,020\nI'm just going to write down the\nsequence of instructions\n\n724\n00:39:28,020 --> 00:39:30,920\nthat constitute the\ncontroller.\n\n725\n00:39:30,920 --> 00:39:41,510\nSo we have assign, to set\nup, continue to done.\n\n726\n00:39:41,510 --> 00:39:44,476\n\n\n727\n00:39:44,476 --> 00:40:01,150\nWe have a loop which says branch\nif equal 1 fetch N, if\n\n728\n00:40:01,150 --> 00:40:06,300\nN is 1, then go to the base\nstep of the induction, the\n\n729\n00:40:06,300 --> 00:40:08,050\nsimple case.\n\n730\n00:40:08,050 --> 00:40:10,740\nOtherwise, I have to remember\nthe things that are necessary\n\n731\n00:40:10,740 --> 00:40:14,265\nto perform a sub-factorial.\n\n732\n00:40:14,265 --> 00:40:16,280\nI'm going to go over here,\nand I have to perform a\n\n733\n00:40:16,280 --> 00:40:17,570\nsub-factorial.\n\n734\n00:40:17,570 --> 00:40:21,750\nSo I have to remember what's\nneeded after I will\n\n735\n00:40:21,750 --> 00:40:24,000\nbe done with that.\n\n736\n00:40:24,000 --> 00:40:25,510\nSee, I'm about to do\nsomething terrible.\n\n737\n00:40:25,510 --> 00:40:29,430\nI'm about to change the value of\nN. But this guy has to know\n\n738\n00:40:29,430 --> 00:40:32,780\nthe old value of N. But\nin order to make the\n\n739\n00:40:32,780 --> 00:40:35,790\nsub-factorial work, I have to\nchange the value of N. So I\n\n740\n00:40:35,790 --> 00:40:38,000\nhave to remember\nthe old value.\n\n741\n00:40:38,000 --> 00:40:40,850\nAnd I also have to remember\nwhere I've been.\n\n742\n00:40:40,850 --> 00:40:42,100\nSo I save up continue.\n\n743\n00:40:42,100 --> 00:40:47,705\n\n\n744\n00:40:47,705 --> 00:40:50,260\nAnd this is an instruction\nthat says, put\n\n745\n00:40:50,260 --> 00:40:53,580\nsomething in the stack.\n\n746\n00:40:53,580 --> 00:40:56,760\nSave the contents of the\ncontinuation register, which\n\n747\n00:40:56,760 --> 00:40:59,830\nin this case is done, because\nlater I'm going to change\n\n748\n00:40:59,830 --> 00:41:00,970\nthat, too, because I\nneed to go back to\n\n749\n00:41:00,970 --> 00:41:03,550\nafter-fact, as well.\n\n750\n00:41:03,550 --> 00:41:05,040\nWe'll see that.\n\n751\n00:41:05,040 --> 00:41:10,380\nWe save N, because I'm going\nto need that for later.\n\n752\n00:41:10,380 --> 00:41:31,422\nAssign to N the decrement of\nfetch N. Assign continue,\n\n753\n00:41:31,422 --> 00:41:37,690\nwe're going to look at this now,\nto after, we'll call it.\n\n754\n00:41:37,690 --> 00:41:39,890\nThat's a good name for this, a\nlittle bit easier and shorter,\n\n755\n00:41:39,890 --> 00:41:41,140\nand fits in here.\n\n756\n00:41:41,140 --> 00:41:52,772\n\n\n757\n00:41:52,772 --> 00:41:55,330\nNow look what I'm doing here.\n\n758\n00:41:55,330 --> 00:42:00,065\nI'm saying, if the answer\nis 1, I'm done.\n\n759\n00:42:00,065 --> 00:42:02,150\nI'm going to have to just\nget the answer.\n\n760\n00:42:02,150 --> 00:42:06,160\nOtherwise, I'm going to save the\ncontinuation, save N, make\n\n761\n00:42:06,160 --> 00:42:08,940\nN one less than N, remember\nI'm going to come back to\n\n762\n00:42:08,940 --> 00:42:10,530\nsomeplace else, and\ngo back and start\n\n763\n00:42:10,530 --> 00:42:11,780\ndoing another factorial.\n\n764\n00:42:11,780 --> 00:42:13,980\n\n\n765\n00:42:13,980 --> 00:42:16,050\nHowever, I've got a different\nmachine [? in me ?] now.\n\n766\n00:42:16,050 --> 00:42:18,380\nN is 1, and continue\nis something else.\n\n767\n00:42:18,380 --> 00:42:22,160\n\n\n768\n00:42:22,160 --> 00:42:23,590\nN is N minus 1.\n\n769\n00:42:23,590 --> 00:42:28,660\nNow after I'm done with\nthat, I can go there.\n\n770\n00:42:28,660 --> 00:42:34,130\nI will restore the old value of\nN, which is the opposite of\n\n771\n00:42:34,130 --> 00:42:38,360\nthis save over here.\n\n772\n00:42:38,360 --> 00:42:39,610\nI will restore the\ncontinuation.\n\n773\n00:42:39,610 --> 00:42:49,660\n\n\n774\n00:42:49,660 --> 00:42:54,320\nI will then go to here.\n\n775\n00:42:54,320 --> 00:43:03,310\nI will assign to the VAL\nregister the product\n\n776\n00:43:03,310 --> 00:43:08,130\nof N and fetch VAL.\n\n777\n00:43:08,130 --> 00:43:13,520\n\n\n778\n00:43:13,520 --> 00:43:19,790\nVAL fetch product assign.\n\n779\n00:43:19,790 --> 00:43:21,440\nAnd then I will be done.\n\n780\n00:43:21,440 --> 00:43:26,570\nI will have my answer to the\nsub-factorial in VAL.\n\n781\n00:43:26,570 --> 00:43:30,140\nAt that point, I'm going to\nreturn by going to the place\n\n782\n00:43:30,140 --> 00:43:33,640\nwhere the continuation\nis pointing.\n\n783\n00:43:33,640 --> 00:43:35,300\nThat says, go to\nfetch continue.\n\n784\n00:43:35,300 --> 00:43:45,870\n\n\n785\n00:43:45,870 --> 00:43:49,470\nAnd then I have finally\na base step, which is\n\n786\n00:43:49,470 --> 00:43:50,730\nthe immediate answer.\n\n787\n00:43:50,730 --> 00:44:02,570\nAssign to VAL fetch N, and\ngo to fetch continue.\n\n788\n00:44:02,570 --> 00:44:12,670\n\n\n789\n00:44:12,670 --> 00:44:13,920\nAnd then I'm done.\n\n790\n00:44:13,920 --> 00:44:18,640\n\n\n791\n00:44:18,640 --> 00:44:20,820\nNow let's see how this executes\non a very simple\n\n792\n00:44:20,820 --> 00:44:25,570\ncase, because then we'll see\nthe use of this stack to do\n\n793\n00:44:25,570 --> 00:44:26,890\nthe job we need.\n\n794\n00:44:26,890 --> 00:44:28,820\nThis is statically what it's\ndoing, but we have look\n\n795\n00:44:28,820 --> 00:44:31,340\ndynamically at this.\n\n796\n00:44:31,340 --> 00:44:32,300\nSo let's see.\n\n797\n00:44:32,300 --> 00:44:36,730\nFirst thing we do is\ncontinue gets done.\n\n798\n00:44:36,730 --> 00:44:38,300\nThe way that happened\nis I pushed this.\n\n799\n00:44:38,300 --> 00:44:40,122\nLet's call that done\nthe way I have it.\n\n800\n00:44:40,122 --> 00:44:46,390\n\n\n801\n00:44:46,390 --> 00:44:47,030\nI push that button.\n\n802\n00:44:47,030 --> 00:44:48,950\nDone goes into there.\n\n803\n00:44:48,950 --> 00:44:52,550\nNow I also have to set\nthis thing up to\n\n804\n00:44:52,550 --> 00:44:53,850\nhave an initial value.\n\n805\n00:44:53,850 --> 00:45:00,192\nLet's consider a factorial\nof three, a simple case.\n\n806\n00:45:00,192 --> 00:45:03,010\nAnd we're going to start\nout with our stack\n\n807\n00:45:03,010 --> 00:45:05,900\ngrowing over here.\n\n808\n00:45:05,900 --> 00:45:08,520\nStacks have their own little\ninternal state saying where\n\n809\n00:45:08,520 --> 00:45:12,770\nthey are, where the next place\nI'm going to write is.\n\n810\n00:45:12,770 --> 00:45:14,590\nSo now we say, is N 1?\n\n811\n00:45:14,590 --> 00:45:16,110\nThe answer is no.\n\n812\n00:45:16,110 --> 00:45:19,066\nSo now I'm going to save\ncontinue, bang.\n\n813\n00:45:19,066 --> 00:45:22,080\nNow that done goes in here.\n\n814\n00:45:22,080 --> 00:45:26,660\nAnd this moves to here, the next\nplace I'm going to write.\n\n815\n00:45:26,660 --> 00:45:29,950\nSave N 3.\n\n816\n00:45:29,950 --> 00:45:30,750\nOK?\n\n817\n00:45:30,750 --> 00:45:34,240\nAssign to N the decrement\nof N. That means\n\n818\n00:45:34,240 --> 00:45:35,940\nI've pushed this button.\n\n819\n00:45:35,940 --> 00:45:37,320\nThis becomes 2.\n\n820\n00:45:37,320 --> 00:45:40,400\n\n\n821\n00:45:40,400 --> 00:45:42,580\nAssign to continue aft.\n\n822\n00:45:42,580 --> 00:45:43,610\nSo I've pushed that button.\n\n823\n00:45:43,610 --> 00:45:44,860\nAft goes in here.\n\n824\n00:45:44,860 --> 00:45:49,140\n\n\n825\n00:45:49,140 --> 00:45:54,830\nOK, now go to loop, bang,\nso up to here.\n\n826\n00:45:54,830 --> 00:45:56,570\nIs N 1?\n\n827\n00:45:56,570 --> 00:45:57,780\nNo.\n\n828\n00:45:57,780 --> 00:45:59,490\nSo I have to save continue.\n\n829\n00:45:59,490 --> 00:46:00,600\nWhat's continue?\n\n830\n00:46:00,600 --> 00:46:01,530\nContinue is aft.\n\n831\n00:46:01,530 --> 00:46:02,780\nPush this button.\n\n832\n00:46:02,780 --> 00:46:04,030\nSo this moves to here.\n\n833\n00:46:04,030 --> 00:46:08,490\n\n\n834\n00:46:08,490 --> 00:46:11,460\nI have to save N.\nN is over here.\n\n835\n00:46:11,460 --> 00:46:12,280\nI got to 2.\n\n836\n00:46:12,280 --> 00:46:13,655\nPush that button.\n\n837\n00:46:13,655 --> 00:46:16,050\nSo a 2 gets written there.\n\n838\n00:46:16,050 --> 00:46:20,060\nAnd then this thing\nmoves down here.\n\n839\n00:46:20,060 --> 00:46:24,214\nOK, save N. Assign N to\nthe decrement of N.\n\n840\n00:46:24,214 --> 00:46:25,464\nThis becomes a 1.\n\n841\n00:46:25,464 --> 00:46:29,240\n\n\n842\n00:46:29,240 --> 00:46:31,370\nAssign continue to aft.\n\n843\n00:46:31,370 --> 00:46:34,960\nA-F-T gets written\nthere again.\n\n844\n00:46:34,960 --> 00:46:36,520\nGo to loop.\n\n845\n00:46:36,520 --> 00:46:37,930\nIs N equal to 1?\n\n846\n00:46:37,930 --> 00:46:41,160\nOh, yes, the answer is 1.\n\n847\n00:46:41,160 --> 00:46:44,160\nOK, go to base step.\n\n848\n00:46:44,160 --> 00:46:51,100\nAssign to VAL fetch of N. Bang,\n1 gets put in there.\n\n849\n00:46:51,100 --> 00:46:52,200\nGo to fetch continue.\n\n850\n00:46:52,200 --> 00:46:53,680\nSo we look in continue.\n\n851\n00:46:53,680 --> 00:46:55,350\nBasically, I'm pushing a button\nover here that goes to\n\n852\n00:46:55,350 --> 00:46:57,130\nthe controller.\n\n853\n00:46:57,130 --> 00:46:59,580\nThe continue becomes aft, and\nall of a sudden, the program's\n\n854\n00:46:59,580 --> 00:47:02,640\nrunning here.\n\n855\n00:47:02,640 --> 00:47:06,650\nI now have to restore the outer\nversion of factorial.\n\n856\n00:47:06,650 --> 00:47:07,550\nSo we go here.\n\n857\n00:47:07,550 --> 00:47:12,410\nWe say, restore N. So restore\nN means take the contents\n\n858\n00:47:12,410 --> 00:47:13,940\nthat's here.\n\n859\n00:47:13,940 --> 00:47:19,190\nPush this button, and it goes\ninto here, 2, and the\n\n860\n00:47:19,190 --> 00:47:22,230\npointer moves up.\n\n861\n00:47:22,230 --> 00:47:24,810\nRestore continue, pretty easy.\n\n862\n00:47:24,810 --> 00:47:27,020\nGo push this button.\n\n863\n00:47:27,020 --> 00:47:31,280\nAnd then aft gets written\nin here again.\n\n864\n00:47:31,280 --> 00:47:32,640\nThat means this thing\nmoves up.\n\n865\n00:47:32,640 --> 00:47:35,190\nI've gotten rid of something\nelse on my stack.\n\n866\n00:47:35,190 --> 00:47:42,240\n\n\n867\n00:47:42,240 --> 00:47:45,930\nRight, then I go to here, which\nsays, assign to VAL the\n\n868\n00:47:45,930 --> 00:47:47,850\nproduct of N an VAL.\n\n869\n00:47:47,850 --> 00:47:50,970\nSo I push this button\nover here, bang.\n\n870\n00:47:50,970 --> 00:47:55,920\n2 times 1 gives me a 2,\nget written there.\n\n871\n00:47:55,920 --> 00:47:57,540\nGo to fetch continue.\n\n872\n00:47:57,540 --> 00:47:59,190\nContinue is aft.\n\n873\n00:47:59,190 --> 00:48:01,290\nI go to aft.\n\n874\n00:48:01,290 --> 00:48:06,640\nAft says restore N. Do your\nrestore N, means I take the\n\n875\n00:48:06,640 --> 00:48:11,030\nvalue over here, which is 3,\npush this up to here, and move\n\n876\n00:48:11,030 --> 00:48:17,715\nit into here, N. Now it's\npushing that button.\n\n877\n00:48:17,715 --> 00:48:20,200\nThe next thing I do is\nrestore continue.\n\n878\n00:48:20,200 --> 00:48:22,830\nContinue is now going\nto become done.\n\n879\n00:48:22,830 --> 00:48:27,260\nSo this moves up here when\nI push this button.\n\n880\n00:48:27,260 --> 00:48:30,470\nDone may or may be there\nanymore, I'm not interested,\n\n881\n00:48:30,470 --> 00:48:31,720\nbut it certainly is here.\n\n882\n00:48:31,720 --> 00:48:35,800\n\n\n883\n00:48:35,800 --> 00:48:39,590\nNext thing I do is assign to VAL\nthe product of the fetch\n\n884\n00:48:39,590 --> 00:48:41,440\nof N and the fetch of VAL.\n\n885\n00:48:41,440 --> 00:48:44,300\nThat's pushing this button\nover here, bang.\n\n886\n00:48:44,300 --> 00:48:46,520\n2 times 3 is 6.\n\n887\n00:48:46,520 --> 00:48:47,870\nSo I get a 6 over here.\n\n888\n00:48:47,870 --> 00:48:52,020\n\n\n889\n00:48:52,020 --> 00:48:54,140\nAnd go to fetch continue,\nwhoops, I go to\n\n890\n00:48:54,140 --> 00:48:55,020\ndone, and I'm done.\n\n891\n00:48:55,020 --> 00:48:58,950\nAnd my answer is 6, as you can\nsee in the VAL register.\n\n892\n00:48:58,950 --> 00:49:02,380\nAnd in fact, the stack\nis in the state it\n\n893\n00:49:02,380 --> 00:49:03,630\noriginally was in.\n\n894\n00:49:03,630 --> 00:49:07,735\n\n\n895\n00:49:07,735 --> 00:49:09,850\nNow there's a bit of discipline\nin using these\n\n896\n00:49:09,850 --> 00:49:13,620\nthings like stacks that we\nhave to be careful of.\n\n897\n00:49:13,620 --> 00:49:16,260\nAnd we'll see that in\nthe next segment.\n\n898\n00:49:16,260 --> 00:49:17,340\nBut first I want to ask\nif there are any\n\n899\n00:49:17,340 --> 00:49:18,590\nquestions for this.\n\n900\n00:49:18,590 --> 00:49:28,560\n\n\n901\n00:49:28,560 --> 00:49:30,170\nAre there any questions?\n\n902\n00:49:30,170 --> 00:49:30,630\nYes, Ron.\n\n903\n00:49:30,630 --> 00:49:32,780\nAUDIENCE: What happens when you\nroll off the end of the\n\n904\n00:49:32,780 --> 00:49:33,640\nstack with--\n\n905\n00:49:33,640 --> 00:49:35,030\nPROFESSOR: What do you\nmean, roll off of?\n\n906\n00:49:35,030 --> 00:49:36,090\nAUDIENCE: Well, the\nlargest number--\n\n907\n00:49:36,090 --> 00:49:38,860\na larger starting point of N\nrequires more memory, correct?\n\n908\n00:49:38,860 --> 00:49:39,440\nPROFESSOR: Oh, yes.\n\n909\n00:49:39,440 --> 00:49:41,530\nWell, I need to have a\nlong enough stack.\n\n910\n00:49:41,530 --> 00:49:43,843\nYou say, what if I violate\nmy illusion?\n\n911\n00:49:43,843 --> 00:49:44,550\nAUDIENCE: Yes.\n\n912\n00:49:44,550 --> 00:49:48,210\nPROFESSOR: Well, then the\nmagic doesn't work.\n\n913\n00:49:48,210 --> 00:49:51,640\nThe truth of the matter is that\nevery machine is finite.\n\n914\n00:49:51,640 --> 00:49:56,480\nAnd for a procedure like this,\nthere's a limit to the number\n\n915\n00:49:56,480 --> 00:49:59,950\nof sub-factorials\nI could have.\n\n916\n00:49:59,950 --> 00:50:02,970\nRemember when we were doing the\ny-operator a while ago, we\n\n917\n00:50:02,970 --> 00:50:05,750\npointed out that there was a\nsequence of exponentiation\n\n918\n00:50:05,750 --> 00:50:07,390\nprocedures, each of which was\na little better than the\n\n919\n00:50:07,390 --> 00:50:08,350\nprevious one.\n\n920\n00:50:08,350 --> 00:50:10,530\nWell, we're now seeing\nhow we implement that\n\n921\n00:50:10,530 --> 00:50:13,090\nmathematical idea.\n\n922\n00:50:13,090 --> 00:50:15,620\nThe limiting process is only\nso good as as far as\n\n923\n00:50:15,620 --> 00:50:17,990\nyou take the limit.\n\n924\n00:50:17,990 --> 00:50:19,420\nIf you think about it,\nwhat am I using here?\n\n925\n00:50:19,420 --> 00:50:26,340\nI'm using about two pieces of\nmemory for every recursion of\n\n926\n00:50:26,340 --> 00:50:29,100\nthis process.\n\n927\n00:50:29,100 --> 00:50:31,920\nIf we try to compute factorial\nof 10,000, that's\n\n928\n00:50:31,920 --> 00:50:33,180\nnot a lot of memory.\n\n929\n00:50:33,180 --> 00:50:36,080\nOn the other hand, it's\nan awful big number.\n\n930\n00:50:36,080 --> 00:50:39,180\nSo the question is, is that a\nvaluable thing in this case.\n\n931\n00:50:39,180 --> 00:50:42,480\nBut it really turns out not to\nbe a terrible limit, because\n\n932\n00:50:42,480 --> 00:50:45,085\nmemory is el cheapo, and people\nare pretty expensive.\n\n933\n00:50:45,085 --> 00:50:48,130\n\n\n934\n00:50:48,130 --> 00:50:51,050\nOK, thank you, let's\ntake a break.\n\n935\n00:50:51,050 --> 00:50:51,410\n[MUSIC PLAYING - \"JESU, JOY OF\nMAN'S DESIRING\" BY JOHANN\n\n936\n00:50:51,410 --> 00:50:52,660\nSEBASTIAN BACH]\n\n937\n00:50:52,660 --> 00:51:55,176\n\n\n938\n00:51:55,176 --> 00:51:58,351\nPROFESSOR: Well, let's see.\n\n939\n00:51:58,351 --> 00:52:02,770\nWhat I've shown you now is how\nto do a simple iterative\n\n940\n00:52:02,770 --> 00:52:05,640\nprocess and a simple\nrecursive process.\n\n941\n00:52:05,640 --> 00:52:09,760\nI just want to summarize the\ndesign of simple machines for\n\n942\n00:52:09,760 --> 00:52:12,470\nspecific applications by showing\nyou a little bit more\n\n943\n00:52:12,470 --> 00:52:15,870\ncomplicated design, that of\na thing that does doubly\n\n944\n00:52:15,870 --> 00:52:19,015\nrecursive Fibonacci, because\nit will indicate to us, and\n\n945\n00:52:19,015 --> 00:52:22,870\nwe'll understand, a bit about\nthe conventions required for\n\n946\n00:52:22,870 --> 00:52:26,400\nmaking stacks operate\ncorrectly.\n\n947\n00:52:26,400 --> 00:52:27,110\nSo let's see.\n\n948\n00:52:27,110 --> 00:52:28,830\nI'm just going to write down,\nfirst of all, the program I'm\n\n949\n00:52:28,830 --> 00:52:30,080\ngoing to translate.\n\n950\n00:52:30,080 --> 00:52:34,150\n\n\n951\n00:52:34,150 --> 00:52:41,190\nI need a Fibonacci procedure,\nit's very simple, which says,\n\n952\n00:52:41,190 --> 00:52:50,390\nif N is less than 2, the result\nis N, otherwise it's\n\n953\n00:52:50,390 --> 00:52:59,965\nthe sum of Fib of N minus\n1 and Fib of N minus 2.\n\n954\n00:52:59,965 --> 00:53:07,240\n\n\n955\n00:53:07,240 --> 00:53:09,290\nThat's the plan I have here.\n\n956\n00:53:09,290 --> 00:53:11,180\nAnd we're just going\nto write down the\n\n957\n00:53:11,180 --> 00:53:13,070\ncontroller for such a machine.\n\n958\n00:53:13,070 --> 00:53:16,240\nWe're going to assume that there\nare registers, N, which\n\n959\n00:53:16,240 --> 00:53:20,510\nholds the number we're taking\nFibonacci of, VAL, which is\n\n960\n00:53:20,510 --> 00:53:23,630\nwhere the answer is going to get\nput, and continue, which\n\n961\n00:53:23,630 --> 00:53:26,810\nis the thing that's linked to\nthe controller, like before.\n\n962\n00:53:26,810 --> 00:53:31,740\nBut I'm not going to draw\nanother physical datapath,\n\n963\n00:53:31,740 --> 00:53:32,995\nbecause it's pretty much\nthe same as the\n\n964\n00:53:32,995 --> 00:53:34,360\nlast one you've seen.\n\n965\n00:53:34,360 --> 00:53:37,070\nAnd of course, one of the most\namazing things about\n\n966\n00:53:37,070 --> 00:53:40,700\ncomputation is that after a\nwhile, you build up a little\n\n967\n00:53:40,700 --> 00:53:42,126\nmore features and a few more\nfeatures, and all of the\n\n968\n00:53:42,126 --> 00:53:44,860\nsudden, you've got everything\nyou need.\n\n969\n00:53:44,860 --> 00:53:48,290\nSo it's remarkable that it just\ngets there so fast. I\n\n970\n00:53:48,290 --> 00:53:51,810\ndon't need much more to make\na universal computer.\n\n971\n00:53:51,810 --> 00:53:53,630\nBut in any case, let's look\nat the controller for the\n\n972\n00:53:53,630 --> 00:53:55,060\nFibonacci thing.\n\n973\n00:53:55,060 --> 00:54:01,680\nFirst thing I want to do is\nstart the thing up by assign\n\n974\n00:54:01,680 --> 00:54:10,230\nto continue a place called done,\ncalled Fib-done here.\n\n975\n00:54:10,230 --> 00:54:13,709\n\n\n976\n00:54:13,709 --> 00:54:16,630\nSo that means that somewhere\nover here, I'm going to have a\n\n977\n00:54:16,630 --> 00:54:21,610\nlabel, Fib-done, which is the\nplace where I go when I want\n\n978\n00:54:21,610 --> 00:54:24,120\nthe machine to stop.\n\n979\n00:54:24,120 --> 00:54:25,395\nThat's what that is.\n\n980\n00:54:25,395 --> 00:54:26,795\nAnd I'm going to\nmake up a loop.\n\n981\n00:54:26,795 --> 00:54:31,110\n\n\n982\n00:54:31,110 --> 00:54:33,490\nIt's a place I'm going to go\nto in order to start up\n\n983\n00:54:33,490 --> 00:54:35,470\ncomputing a Fib.\n\n984\n00:54:35,470 --> 00:54:38,210\nWhatever is in N at this point,\nFibonacci will be\n\n985\n00:54:38,210 --> 00:54:41,320\ncomputed of, and we will return\nto the place specified\n\n986\n00:54:41,320 --> 00:54:42,570\nby continue.\n\n987\n00:54:42,570 --> 00:54:46,070\n\n\n988\n00:54:46,070 --> 00:54:48,640\nSo what you're going to see\nhere at this place, what I\n\n989\n00:54:48,640 --> 00:54:52,650\nwant here is the contract that\nsays, I'm going to write this\n\n990\n00:54:52,650 --> 00:55:00,230\nwith a comment syntax, the\ncontract is N contains arg,\n\n991\n00:55:00,230 --> 00:55:02,100\nthe argument.\n\n992\n00:55:02,100 --> 00:55:09,325\nContinue is the recipient.\n\n993\n00:55:09,325 --> 00:55:12,812\n\n\n994\n00:55:12,812 --> 00:55:14,290\nAnd that's where it is.\n\n995\n00:55:14,290 --> 00:55:17,370\n\n\n996\n00:55:17,370 --> 00:55:20,430\nAt this point, if I ever go to\nthis place, I'm expecting this\n\n997\n00:55:20,430 --> 00:55:24,820\nto be true, the argument for\ncomputing the Fibonacci.\n\n998\n00:55:24,820 --> 00:55:26,450\nNow the next thing I want\nto do is to branch.\n\n999\n00:55:26,450 --> 00:55:30,220\n\n\n1000\n00:55:30,220 --> 00:55:32,070\nAnd if N is less than 2--\n\n1001\n00:55:32,070 --> 00:55:34,930\n\n\n1002\n00:55:34,930 --> 00:55:38,730\nby the way, I'm using what\nlooks like Lisp syntax.\n\n1003\n00:55:38,730 --> 00:55:41,310\nThis is not Lisp.\n\n1004\n00:55:41,310 --> 00:55:42,750\nThis does not run.\n\n1005\n00:55:42,750 --> 00:55:46,120\nWhat I'm writing here does not\nrun as a simple Lisp program.\n\n1006\n00:55:46,120 --> 00:55:49,710\nThis is a representation\nof another language.\n\n1007\n00:55:49,710 --> 00:55:52,030\nThe reason I'm using the syntax\nof parentheses and so\n\n1008\n00:55:52,030 --> 00:55:56,100\non is because I tend to use\na Lisp system to write an\n\n1009\n00:55:56,100 --> 00:55:59,380\ninterpreter for this which\nallows me to simulate the\n\n1010\n00:55:59,380 --> 00:56:03,380\nmachine I'm trying to build.\n\n1011\n00:56:03,380 --> 00:56:05,170\nI don't want to confuse\nthis to think that\n\n1012\n00:56:05,170 --> 00:56:06,940\nthis is Lisp code.\n\n1013\n00:56:06,940 --> 00:56:09,510\nIt's just I'm using a lot\nof the pieces of Lisp.\n\n1014\n00:56:09,510 --> 00:56:12,880\nI'm embedding a language in\nLisp, using Lisp as pieces to\n\n1015\n00:56:12,880 --> 00:56:16,620\nmake my process of making\nmy simulator easy.\n\n1016\n00:56:16,620 --> 00:56:18,900\nSo I'm inheriting from Lisp\nall of its properties.\n\n1017\n00:56:18,900 --> 00:56:22,700\nFetch of N 2, I want\nto go to a place\n\n1018\n00:56:22,700 --> 00:56:25,985\ncalled immediate answer.\n\n1019\n00:56:25,985 --> 00:56:27,235\nIt's the base step.\n\n1020\n00:56:27,235 --> 00:56:33,150\n\n\n1021\n00:56:33,150 --> 00:56:37,750\nNow, that's somewhere over\nhere, just above done.\n\n1022\n00:56:37,750 --> 00:56:39,330\nAnd we'll see it later.\n\n1023\n00:56:39,330 --> 00:56:41,480\nNow, in the general case, which\nis the part I'm going to\n\n1024\n00:56:41,480 --> 00:56:44,860\nwrite down now, let's\njust do it.\n\n1025\n00:56:44,860 --> 00:56:46,370\nWell, first of all, I'm\ngoing to have to\n\n1026\n00:56:46,370 --> 00:56:49,420\ncall Fibonacci twice.\n\n1027\n00:56:49,420 --> 00:56:51,300\nIn each case--\n\n1028\n00:56:51,300 --> 00:56:53,640\nwell, in one case at least, I'm\ngoing to have to know what\n\n1029\n00:56:53,640 --> 00:56:56,310\nto do to come back and\ndo the next one.\n\n1030\n00:56:56,310 --> 00:57:01,600\nI have to remember, have I done\nthe first Fib, or have I\n\n1031\n00:57:01,600 --> 00:57:04,500\ndone the second one?\n\n1032\n00:57:04,500 --> 00:57:06,630\nDo I have to come back to the\nplace where I do the second\n\n1033\n00:57:06,630 --> 00:57:08,240\nFib, or do I have to come\nback to the place\n\n1034\n00:57:08,240 --> 00:57:09,490\nwhere I do the add?\n\n1035\n00:57:09,490 --> 00:57:12,140\n\n\n1036\n00:57:12,140 --> 00:57:14,810\nIn the first case, over the\nfirst Fibonacci, I'm going to\n\n1037\n00:57:14,810 --> 00:57:16,980\nneed the value of N for\ncomputing for the second one.\n\n1038\n00:57:16,980 --> 00:57:20,010\n\n\n1039\n00:57:20,010 --> 00:57:22,996\nSo I have to store some\nof these things up.\n\n1040\n00:57:22,996 --> 00:57:25,820\nSo first I'm going\nto save continue.\n\n1041\n00:57:25,820 --> 00:57:27,265\nThat's who needs the answer.\n\n1042\n00:57:27,265 --> 00:57:31,320\n\n\n1043\n00:57:31,320 --> 00:57:33,560\nAnd the reason I'm doing that is\nbecause I'm about to assign\n\n1044\n00:57:33,560 --> 00:57:42,870\ncontinue to the place\nwhich is the place I\n\n1045\n00:57:42,870 --> 00:57:44,130\nwant to go to after.\n\n1046\n00:57:44,130 --> 00:57:46,870\n\n\n1047\n00:57:46,870 --> 00:57:52,510\nLet's call it Fib-N-minus-1,\nbig long name,\n\n1048\n00:57:52,510 --> 00:57:53,760\nclassic Lisp name.\n\n1049\n00:57:53,760 --> 00:57:57,700\n\n\n1050\n00:57:57,700 --> 00:58:00,900\nBecause I'm going to compute\nthe first Fib of N minus 1,\n\n1051\n00:58:00,900 --> 00:58:02,440\nand then after that, I\nwant to come back and\n\n1052\n00:58:02,440 --> 00:58:03,960\ndo something else.\n\n1053\n00:58:03,960 --> 00:58:08,050\nThat's the place I want to go\nto after I've done the first\n\n1054\n00:58:08,050 --> 00:58:11,106\nFibonacci calculation.\n\n1055\n00:58:11,106 --> 00:58:15,030\nAnd I want to do a save of N,\nbecause I'm going to need it\n\n1056\n00:58:15,030 --> 00:58:19,130\nlater, after that.\n\n1057\n00:58:19,130 --> 00:58:21,480\nNow I'm going to, at this point,\nget ready to do the\n\n1058\n00:58:21,480 --> 00:58:23,230\nFibonacci of N minus 1.\n\n1059\n00:58:23,230 --> 00:58:33,950\nSo assign to N the difference\nof the fetch of N and 1.\n\n1060\n00:58:33,950 --> 00:58:38,110\n\n\n1061\n00:58:38,110 --> 00:58:40,270\nNow I'm ready to go back\nto doing the Fib loop.\n\n1062\n00:58:40,270 --> 00:58:47,630\n\n\n1063\n00:58:47,630 --> 00:58:50,195\nHave I satisfied my contract?\n\n1064\n00:58:50,195 --> 00:58:51,770\nAnd the answer is yes.\n\n1065\n00:58:51,770 --> 00:58:57,210\nN contains N minus 1, which\nis what I need.\n\n1066\n00:58:57,210 --> 00:59:01,370\nContinue contains a place I want\nto go to when I'm done\n\n1067\n00:59:01,370 --> 00:59:04,100\nwith calculating N minus 1.\n\n1068\n00:59:04,100 --> 00:59:05,440\nSo I've satisfied\nthe contract.\n\n1069\n00:59:05,440 --> 00:59:11,580\nAnd therefore, I can write\ndown here a label,\n\n1070\n00:59:11,580 --> 00:59:12,830\nafter-Fib-N-minus-1.\n\n1071\n00:59:12,830 --> 00:59:20,490\n\n\n1072\n00:59:20,490 --> 00:59:22,690\nNow what am I going\nto do here?\n\n1073\n00:59:22,690 --> 00:59:25,660\nHere's a place where I now\nhave to get ready to do\n\n1074\n00:59:25,660 --> 00:59:26,910\nFib of N minus 2.\n\n1075\n00:59:26,910 --> 00:59:29,270\n\n\n1076\n00:59:29,270 --> 00:59:31,780\nBut in order to do a Fib of N\nminus 2, look, I don't know.\n\n1077\n00:59:31,780 --> 00:59:33,810\nI've clobbered my N over here.\n\n1078\n00:59:33,810 --> 00:59:36,610\nAnd presumably my N is counted\ndown all the way to 1 or 0 or\n\n1079\n00:59:36,610 --> 00:59:39,780\nsomething at this point.\n\n1080\n00:59:39,780 --> 00:59:43,030\nSo I don't know what the value\nof N in the N register is.\n\n1081\n00:59:43,030 --> 00:59:45,640\nI want the value of N that was\non the stack that I saved over\n\n1082\n00:59:45,640 --> 00:59:49,520\nhere so that could restore\nit over here.\n\n1083\n00:59:49,520 --> 00:59:53,880\nI saved up the value of N, which\nis this value of N at\n\n1084\n00:59:53,880 --> 00:59:56,340\nthis point, so that I could\nrestore it after computing Fib\n\n1085\n00:59:56,340 --> 00:59:59,360\nof N minus 1, so that I could\ncount that down to N minus 2\n\n1086\n00:59:59,360 --> 01:00:01,810\nand then compute Fib\nof N minus 2.\n\n1087\n01:00:01,810 --> 01:00:03,060\nSo let's restore that.\n\n1088\n01:00:03,060 --> 01:00:08,830\n\n\n1089\n01:00:08,830 --> 01:00:11,130\nRestore of N.\n\n1090\n01:00:11,130 --> 01:00:16,200\nNow I'm about to do something\nwhich is superstitious, and we\n\n1091\n01:00:16,200 --> 01:00:18,520\nwill remove it shortly.\n\n1092\n01:00:18,520 --> 01:00:22,390\nI am about to finish the\nsequence of doing the\n\n1093\n01:00:22,390 --> 01:00:24,800\nsubroutine call, if you will.\n\n1094\n01:00:24,800 --> 01:00:28,510\nI'm going to say, well, I also\nsaved up the continuation,\n\n1095\n01:00:28,510 --> 01:00:31,600\nsince I'm going to\nrestore it now.\n\n1096\n01:00:31,600 --> 01:00:32,970\nBut actually, I don't have\nto, because I'm not\n\n1097\n01:00:32,970 --> 01:00:34,610\ngoing to need it.\n\n1098\n01:00:34,610 --> 01:00:36,260\nWe'll fix that in a second.\n\n1099\n01:00:36,260 --> 01:00:46,590\nSo we'll do a restore of\ncontinue, which is what I\n\n1100\n01:00:46,590 --> 01:00:48,020\nwould in general need to do.\n\n1101\n01:00:48,020 --> 01:00:50,240\nAnd we're just going to see\nwhat you would call in the\n\n1102\n01:00:50,240 --> 01:00:52,540\ncompiler world a peephole\noptimization, which says,\n\n1103\n01:00:52,540 --> 01:00:55,420\nwhoops, you didn't\nhave to do that.\n\n1104\n01:00:55,420 --> 01:00:59,720\nOK, so the next thing I see\nhere is that I have to get\n\n1105\n01:00:59,720 --> 01:01:02,770\nready now to do Fibonacci\nof N minus 2.\n\n1106\n01:01:02,770 --> 01:01:05,050\nBut I don't have to\nsave N anymore.\n\n1107\n01:01:05,050 --> 01:01:07,140\nThe reason why I don't have to\nsave N anymore is because I\n\n1108\n01:01:07,140 --> 01:01:09,690\ndon't need N after I've done Fib\nof N minus 2, because the\n\n1109\n01:01:09,690 --> 01:01:13,540\nnext thing I do is add.\n\n1110\n01:01:13,540 --> 01:01:16,500\nSo I'm just going to set\nup my N that way.\n\n1111\n01:01:16,500 --> 01:01:28,990\nAssign N minus difference\nof fetch N and 2.\n\n1112\n01:01:28,990 --> 01:01:31,850\n\n\n1113\n01:01:31,850 --> 01:01:35,440\nNow I have to finish the\nsetup for calling\n\n1114\n01:01:35,440 --> 01:01:36,950\nFibonacci of N minus 2.\n\n1115\n01:01:36,950 --> 01:01:48,330\nWell, I have to save up continue\nand assign continue,\n\n1116\n01:01:48,330 --> 01:02:03,050\ncontinue, to the place which is\nafter Fib N 2, that place\n\n1117\n01:02:03,050 --> 01:02:05,320\nover here somewhere.\n\n1118\n01:02:05,320 --> 01:02:08,650\nHowever, I've got to\nbe very careful.\n\n1119\n01:02:08,650 --> 01:02:12,470\nThe old value, the value of Fib\nof N minus 1, I'm going to\n\n1120\n01:02:12,470 --> 01:02:15,300\nneed later.\n\n1121\n01:02:15,300 --> 01:02:18,480\nThe value of Fibonacci of N\nminus 1, I'm going to need.\n\n1122\n01:02:18,480 --> 01:02:21,880\nAnd I can't clobber it, because\nI'm going to have to\n\n1123\n01:02:21,880 --> 01:02:24,150\nadd it to the value of\nFib of N minus 2.\n\n1124\n01:02:24,150 --> 01:02:27,720\nThat's in the value register,\nso I'm going to save it.\n\n1125\n01:02:27,720 --> 01:02:33,780\nSo I have to save this right\nnow, save up VAL.\n\n1126\n01:02:33,780 --> 01:02:39,547\nAnd now I can go off to my\nsubroutine, go to Fib loop.\n\n1127\n01:02:39,547 --> 01:02:44,220\n\n\n1128\n01:02:44,220 --> 01:02:49,460\nNow before I go any further\nand finish this program, I\n\n1129\n01:02:49,460 --> 01:02:52,340\njust want to look at this\nsegment so far and see, oh\n\n1130\n01:02:52,340 --> 01:02:55,520\nyes, there's a sequence of\ninstructions here, if you\n\n1131\n01:02:55,520 --> 01:03:01,580\nwill, that I can do\nsomething about.\n\n1132\n01:03:01,580 --> 01:03:06,010\nHere I have a restore of\ncontinue, a save of continue,\n\n1133\n01:03:06,010 --> 01:03:09,200\nand then an assign of continue,\nwith no other\n\n1134\n01:03:09,200 --> 01:03:10,640\nreferences to continue\nin between.\n\n1135\n01:03:10,640 --> 01:03:13,840\n\n\n1136\n01:03:13,840 --> 01:03:15,520\nThe restore followed\nby the save\n\n1137\n01:03:15,520 --> 01:03:16,770\nleaves the stack unchanged.\n\n1138\n01:03:16,770 --> 01:03:19,090\n\n\n1139\n01:03:19,090 --> 01:03:21,250\nThe only difference is that I\nset the continue register to a\n\n1140\n01:03:21,250 --> 01:03:24,330\nvalue, which is the value\nthat was on the stack.\n\n1141\n01:03:24,330 --> 01:03:27,360\nSince I now clobber that value,\nas in it was never\n\n1142\n01:03:27,360 --> 01:03:31,710\nreferenced, these instructions\nare unnecessary.\n\n1143\n01:03:31,710 --> 01:03:35,390\nSo we will remove these.\n\n1144\n01:03:35,390 --> 01:03:38,550\n\n\n1145\n01:03:38,550 --> 01:03:40,210\nBut I couldn't have seen\nthat unless I had\n\n1146\n01:03:40,210 --> 01:03:41,460\nwritten them down.\n\n1147\n01:03:41,460 --> 01:03:43,780\n\n\n1148\n01:03:43,780 --> 01:03:45,590\nWas that really true?\n\n1149\n01:03:45,590 --> 01:03:48,610\nWell, I don't know.\n\n1150\n01:03:48,610 --> 01:03:51,560\nOK, so we've now gone\noff to compute\n\n1151\n01:03:51,560 --> 01:03:53,660\nFibonacci of N minus 2.\n\n1152\n01:03:53,660 --> 01:04:05,070\nSo after that, what are\nwe going to do?\n\n1153\n01:04:05,070 --> 01:04:07,010\nWell, I suppose the first\nthing we have to do--\n\n1154\n01:04:07,010 --> 01:04:07,960\nwe've got two things.\n\n1155\n01:04:07,960 --> 01:04:09,460\nWe've got a thing in\nthe value register\n\n1156\n01:04:09,460 --> 01:04:10,920\nwhich is now valuable.\n\n1157\n01:04:10,920 --> 01:04:12,610\nWe also have a thing on the\nstack that can be restored\n\n1158\n01:04:12,610 --> 01:04:14,815\ninto the value register.\n\n1159\n01:04:14,815 --> 01:04:17,630\nAnd what I have to be careful\nwith now is I want to shuffle\n\n1160\n01:04:17,630 --> 01:04:19,470\nthis right so I can\ndo the multiply.\n\n1161\n01:04:19,470 --> 01:04:21,600\nNow there are various\nconventions I might use, but\n\n1162\n01:04:21,600 --> 01:04:24,510\nI'm going to be very picky and\nsay, I'm only going to restore\n\n1163\n01:04:24,510 --> 01:04:26,740\ninto a register I've\nsaved from.\n\n1164\n01:04:26,740 --> 01:04:30,020\nIf that's the case, I have\nto do a shuffle here.\n\n1165\n01:04:30,020 --> 01:04:32,950\nIt's the same problem with how\nmany hands I have. So I'm\n\n1166\n01:04:32,950 --> 01:04:37,800\ngoing to assign to N, because\nI'm not going to need N\n\n1167\n01:04:37,800 --> 01:04:45,440\nanymore, N is useless, the\ncurrent value of VAL, which\n\n1168\n01:04:45,440 --> 01:04:47,340\nwas the value of Fib\nof N minus 2.\n\n1169\n01:04:47,340 --> 01:04:52,950\n\n\n1170\n01:04:52,950 --> 01:04:56,180\nAnd I'm going to restore\nthe value register now.\n\n1171\n01:04:56,180 --> 01:05:01,850\n\n\n1172\n01:05:01,850 --> 01:05:06,290\nThis restore matches this\nsave. And if you're very\n\n1173\n01:05:06,290 --> 01:05:09,820\ncareful and examine very\ncarefully what goes on,\n\n1174\n01:05:09,820 --> 01:05:13,840\nrestores and saves are\nalways matched.\n\n1175\n01:05:13,840 --> 01:05:15,660\nNow there's an outstanding save,\nof course, that we have\n\n1176\n01:05:15,660 --> 01:05:19,000\nto get rid of soon.\n\n1177\n01:05:19,000 --> 01:05:20,590\nAnd so I restored the\nvalue register.\n\n1178\n01:05:20,590 --> 01:05:34,850\nNow I restore the continue one,\nwhich matches this one,\n\n1179\n01:05:34,850 --> 01:05:41,300\ndot, dot, dot, dot, dot, dot,\ndot, down to here, restoring\n\n1180\n01:05:41,300 --> 01:05:42,860\nthat continuation.\n\n1181\n01:05:42,860 --> 01:05:46,600\nThat continuation is a\ncontinuation of Fib of N,\n\n1182\n01:05:46,600 --> 01:05:48,330\nwhich is the problem I was\ntrying to solve, a major\n\n1183\n01:05:48,330 --> 01:05:49,665\nproblem I'm trying to solve.\n\n1184\n01:05:49,665 --> 01:05:52,670\nSo that's the guy I have to go\nback to who wants Fib of N. I\n\n1185\n01:05:52,670 --> 01:05:55,470\nsaved them all the way up here\nwhen I realized N was\n\n1186\n01:05:55,470 --> 01:05:57,360\nnot less than 2.\n\n1187\n01:05:57,360 --> 01:06:00,840\nAnd so I had to do a complicated\noperation.\n\n1188\n01:06:00,840 --> 01:06:03,240\nNow I've got everything\nI need to do it.\n\n1189\n01:06:03,240 --> 01:06:17,470\nSo I'm going to restore that,\nassign to VAL the sum of fetch\n\n1190\n01:06:17,470 --> 01:06:28,335\nVAL and fetch of N, and\ngo to continue.\n\n1191\n01:06:28,335 --> 01:06:38,260\n\n\n1192\n01:06:38,260 --> 01:06:45,750\nSo now I've returned from\ncomputing Fibonacci of N, the\n\n1193\n01:06:45,750 --> 01:06:47,110\ngeneral case.\n\n1194\n01:06:47,110 --> 01:06:51,230\nNow what's left is we have to\nfix up a few details, like\n\n1195\n01:06:51,230 --> 01:07:03,750\nthere's the base case of this\ninduction, immediate answer,\n\n1196\n01:07:03,750 --> 01:07:13,710\nwhich is nothing more than\nassign to VAL fetch of N,\n\n1197\n01:07:13,710 --> 01:07:17,120\nbecause N was less than 2, and\ntherefore, the answer is N in\n\n1198\n01:07:17,120 --> 01:07:26,095\nour original program, and\nreturn continue--\n\n1199\n01:07:26,095 --> 01:07:31,460\n\n\n1200\n01:07:31,460 --> 01:07:34,800\nbobble, bobble almost--\n\n1201\n01:07:34,800 --> 01:07:36,130\nand finally Fib done.\n\n1202\n01:07:36,130 --> 01:07:43,460\n\n\n1203\n01:07:43,460 --> 01:07:45,640\nSo that's a fairly complicated\nprogram.\n\n1204\n01:07:45,640 --> 01:07:47,950\nAnd the reason I wanted you see\nto that is because I want\n\n1205\n01:07:47,950 --> 01:07:51,740\nyou to see the particular\nflavors of stack discipline\n\n1206\n01:07:51,740 --> 01:07:52,965\nthat I was obeying.\n\n1207\n01:07:52,965 --> 01:07:57,240\nIt was first of all, I don't\nwant to take anything that I'm\n\n1208\n01:07:57,240 --> 01:08:00,395\nnot going to need later.\n\n1209\n01:08:00,395 --> 01:08:01,850\nI was being very careful.\n\n1210\n01:08:01,850 --> 01:08:03,940\nAnd it's very important.\n\n1211\n01:08:03,940 --> 01:08:07,095\nAnd there are all sorts of other\ndisciplines people make\n\n1212\n01:08:07,095 --> 01:08:10,520\nwith frames and things like that\nof some sort, where you\n\n1213\n01:08:10,520 --> 01:08:12,280\nsave all sorts of junk you're\nnot going to need later and\n\n1214\n01:08:12,280 --> 01:08:15,830\nrestore it because, in some\nsense, it's easier to do that.\n\n1215\n01:08:15,830 --> 01:08:19,109\nThat's going to lead to various\ndisasters, which we'll\n\n1216\n01:08:19,109 --> 01:08:21,740\nsee a little later.\n\n1217\n01:08:21,740 --> 01:08:23,560\nIt's crucial to say exactly\nwhat you're\n\n1218\n01:08:23,560 --> 01:08:24,810\ngoing to need later.\n\n1219\n01:08:24,810 --> 01:08:26,899\n\n\n1220\n01:08:26,899 --> 01:08:29,859\nIt's an important idea.\n\n1221\n01:08:29,859 --> 01:08:34,020\nAnd the responsibility of that\nis whoever saves something is\n\n1222\n01:08:34,020 --> 01:08:36,930\nthe guy who restores it,\nbecause he needs it.\n\n1223\n01:08:36,930 --> 01:08:40,130\nAnd in such discipline, you\ncan see what things are\n\n1224\n01:08:40,130 --> 01:08:46,940\nunnecessary, operations\nthat are unimportant.\n\n1225\n01:08:46,940 --> 01:08:49,950\nNow, one other thing I want to\ntell you about that's very\n\n1226\n01:08:49,950 --> 01:08:54,120\nsimple is that, of course, the\npicture you see is not the\n\n1227\n01:08:54,120 --> 01:08:55,350\nwhole picture.\n\n1228\n01:08:55,350 --> 01:08:58,430\nSupposing I had systems that\nhad things like other\n\n1229\n01:08:58,430 --> 01:09:06,080\noperations, CAR, CDR, cons,\nbuilding a vector and\n\n1230\n01:09:06,080 --> 01:09:10,000\nreferencing the nth element of\nit, or things like that.\n\n1231\n01:09:10,000 --> 01:09:14,229\nWell, at this level of detail,\nwhatever it is, we can\n\n1232\n01:09:14,229 --> 01:09:15,520\nconceptualize those\nas primitive\n\n1233\n01:09:15,520 --> 01:09:18,299\noperations in the datapath.\n\n1234\n01:09:18,299 --> 01:09:21,020\nIn other words, we could say\nthat some machine that, for\n\n1235\n01:09:21,020 --> 01:09:25,460\nexample, has the append machine,\nwhich has to do cons\n\n1236\n01:09:25,460 --> 01:09:29,870\nof the CAR of x with the append\nof the CDR of x and y,\n\n1237\n01:09:29,870 --> 01:09:31,149\nwell, gee, that's exactly\nthe same as\n\n1238\n01:09:31,149 --> 01:09:33,630\nthe factorial structure.\n\n1239\n01:09:33,630 --> 01:09:36,133\nWell, it's got about\nthe same structure.\n\n1240\n01:09:36,133 --> 01:09:37,270\nAnd what do we have?\n\n1241\n01:09:37,270 --> 01:09:41,590\nWe have some sort of things in\nit which may be registers, x\n\n1242\n01:09:41,590 --> 01:09:45,490\nand y, and then x has to somehow\nmove to y sometimes, x\n\n1243\n01:09:45,490 --> 01:09:46,939\nhas to get the value of y.\n\n1244\n01:09:46,939 --> 01:09:48,000\nAnd then we may have\nto be able to do\n\n1245\n01:09:48,000 --> 01:09:51,700\nsomething which is a cons.\n\n1246\n01:09:51,700 --> 01:09:57,760\nI don't remember if I need to\nlike this is in this system,\n\n1247\n01:09:57,760 --> 01:10:01,420\nbut cons is sort of like\nsubtract or add or something.\n\n1248\n01:10:01,420 --> 01:10:03,800\nIt combines two things,\nproducing a thing which is the\n\n1249\n01:10:03,800 --> 01:10:07,600\ncons, which we may then\nthink goes into there.\n\n1250\n01:10:07,600 --> 01:10:14,920\nAnd then maybe a thing called\nthe CAR, which will produce--\n\n1251\n01:10:14,920 --> 01:10:16,920\nI can get the CAR\nor something.\n\n1252\n01:10:16,920 --> 01:10:20,150\nAnd maybe I can get the CDR\nof something, and so on.\n\n1253\n01:10:20,150 --> 01:10:22,730\nBut we shouldn't be too afraid\nof saying things this way,\n\n1254\n01:10:22,730 --> 01:10:27,330\nbecause the worst that could\nhappen is if we open up cons,\n\n1255\n01:10:27,330 --> 01:10:31,770\nwhat we're going to find\nis some machine.\n\n1256\n01:10:31,770 --> 01:10:33,750\nAnd cons may in fact overlap\nwith CAR and CDR, and it\n\n1257\n01:10:33,750 --> 01:10:38,660\nalways does, in the same way\nthat plus and minus overlap,\n\n1258\n01:10:38,660 --> 01:10:41,210\nand really the same business.\n\n1259\n01:10:41,210 --> 01:10:42,950\nCons, CAR, and CDR are going to\noverlap, and we're going to\n\n1260\n01:10:42,950 --> 01:10:48,630\nfind a little controller, a\nlittle datapath, which may\n\n1261\n01:10:48,630 --> 01:10:53,300\nhave some registers in it,\nsome stuff like that.\n\n1262\n01:10:53,300 --> 01:10:56,650\nAnd maybe inside it, there may\nalso be an infinite part, a\n\n1263\n01:10:56,650 --> 01:10:59,440\npart that's semi-infinite or\nsomething, which is a lot of\n\n1264\n01:10:59,440 --> 01:11:02,030\nvery uniform stuff, which\nwe'll call memory.\n\n1265\n01:11:02,030 --> 01:11:06,570\n\n\n1266\n01:11:06,570 --> 01:11:09,330\nAnd I wouldn't be so horrified\nif that were the way it works.\n\n1267\n01:11:09,330 --> 01:11:13,320\nIn fact, it does, and we'll\ntalk about that later.\n\n1268\n01:11:13,320 --> 01:11:14,570\nSo are there any questions?\n\n1269\n01:11:14,570 --> 01:11:24,340\n\n\n1270\n01:11:24,340 --> 01:11:25,665\nGee, what an unquestioning\naudience.\n\n1271\n01:11:25,665 --> 01:11:28,670\n\n\n1272\n01:11:28,670 --> 01:11:30,330\nSuppose I tell you a horrible\npile of lies.\n\n1273\n01:11:30,330 --> 01:11:39,690\n\n\n1274\n01:11:39,690 --> 01:11:41,990\nOK.\n\n1275\n01:11:41,990 --> 01:11:42,520\nWell, thank you.\n\n1276\n01:11:42,520 --> 01:11:44,230\nLet's take our break.\n\n1277\n01:11:44,230 --> 01:11:47,230\n[MUSIC PLAYING - \"JESU, JOY OF\nMAN'S DESIRING\" BY JOHANN\n\n1278\n01:11:47,230 --> 01:11:48,780\nSEBASTIAN BACH]\n\n1279\n01:11:48,780 --> 01:11:56,124\n\n"
  },
  {
    "path": "SrtEN/lec9b_512kb.mp4.srt",
    "content": "﻿1\r\n00:00:15,840 --> 00:00:20,260\r\nPROFESSOR: Well, I hope you appreciate that we have\r\n\r\n2\r\n00:00:20,260 --> 00:00:24,562\r\ninducted you into some real magic,\r\n\r\n3\r\n00:00:24,562 --> 00:00:29,500\r\nthe magic of building languages, really building new languages.\r\n\r\n4\r\n00:00:29,500 --> 00:00:31,275\r\nWhat have we looked at? We've looked at \r\n\r\n5\r\n00:00:31,275 --> 00:00:38,925\r\nan Escher picture language:\r\n\r\n6\r\n00:00:38,925 --> 00:00:42,141\r\nthis language invented by Peter Henderson.\r\n\r\n7\r\n00:00:42,141 --> 00:00:47,600\r\nWe looked at digital logic language.\r\n\r\n8\r\n00:00:53,000 --> 00:00:56,944\r\nLet's see.We've looked at the query language.\r\n\r\n9\r\n00:00:59,700 --> 00:01:04,700\r\nAnd the thing you should realize is, even though these were toy examples,  \r\n\r\n10\r\n00:01:04,700 --> 00:01:08,250\r\nthey really are the kernels of really useful things.\r\n\r\n11\r\n00:01:08,250 --> 00:01:12,375\r\nSo, for instance, the Escher picture language was taken by\r\n\r\n12\r\n00:01:12,375 --> 00:01:14,450\r\nHenry Wu, who's a student at MIT, \r\n\r\n13\r\n00:01:14,450 --> 00:01:20,350\r\nand developed into a real language for laying out PC boards, \r\n\r\n14\r\n00:01:20,350 --> 00:01:23,244\r\nbased just on extending those structures.\r\n\r\n15\r\n00:01:23,244 --> 00:01:26,350\r\nAnd the digital logic language, Jerry mentioned when he showed it to you,\r\n\r\n16\r\n00:01:26,350 --> 00:01:30,850\r\nwas really extended to be used as the basis for a simulator \r\n\r\n17\r\n00:01:30,850 --> 00:01:33,460\r\nthat was used to design a real computer.\r\n\r\n18\r\n00:01:33,460 --> 00:01:37,510\r\nAnd the query language, of course, is kind of the germ of prologue.\r\n\r\n19\r\n00:01:37,510 --> 00:01:39,425\r\nSo we built all of these languages, \r\n\r\n20\r\n00:01:39,425 --> 00:01:42,300\r\nthey're all based on LISP.\r\n\r\n21\r\n00:01:43,630 --> 00:01:45,275\r\nA lot of people ask \r\n\r\n22\r\n00:01:45,275 --> 00:01:48,606\r\nwhat particular problems is LISP good for solving for?\r\n\r\n23\r\n00:01:48,606 --> 00:01:53,450\r\nThe answer is LISP is not good for solving any particular problems.\r\n\r\n24\r\n00:01:53,450 --> 00:01:56,213\r\nWhat LISP is good for is constructing within it\r\n\r\n25\r\n00:01:56,213 --> 00:01:59,175\r\nthe right language to solve the problems you want to solve,\r\n\r\n26\r\n00:01:59,175 --> 00:02:01,470\r\nand that's how you should think about it.\r\n\r\n27\r\n00:02:01,470 --> 00:02:04,326\r\nSo all of these languages were based on LISP.\r\n\r\n28\r\n00:02:04,326 --> 00:02:06,925\r\nNow, what's LISP based on?\r\n\r\n29\r\n00:02:06,925 --> 00:02:09,400\r\nWhere's that come from? Well, we looked at that too.\r\n\r\n30\r\n00:02:09,400 --> 00:02:22,935\r\nWe looked at the meta-circular evaluator \r\n\r\n31\r\n00:02:22,935 --> 00:02:25,810\r\nand said well, LISP is based on LISP.\r\n\r\n32\r\n00:02:25,810 --> 00:02:28,275\r\nAnd when we start looking at that, \r\n\r\n33\r\n00:02:28,275 --> 00:02:29,950\r\nwe've got to do some real magic, right?\r\n\r\n34\r\n00:02:29,950 --> 00:02:31,660\r\nSo what does that mean, right?\r\n\r\n35\r\n00:02:31,660 --> 00:02:37,350\r\nWhy operators, and fixed points, and the idea that\r\n\r\n36\r\n00:02:37,350 --> 00:02:41,000\r\nwhat this means is that LISP is somehow the fixed-point equation\r\n\r\n37\r\n00:02:41,000 --> 00:02:47,400\r\nfor this funny set of things which are defined in terms of themselves.\r\n\r\n38\r\n00:02:47,400 --> 00:02:49,070\r\nNow, it's real magic.\r\n\r\n39\r\n00:02:49,070 --> 00:02:52,625\r\nWell, today, for a final piece of magic, \r\n\r\n40\r\n00:02:52,625 --> 00:03:01,852\r\nwe're going to make all the magic go away.\r\n\r\n41\r\n00:03:06,430 --> 00:03:09,770\r\nWe already know how to do that.\r\n\r\n42\r\n00:03:09,770 --> 00:03:13,135\r\nThe idea is, we're going to take the register machine architecture\r\n\r\n43\r\n00:03:13,135 --> 00:03:15,500\r\nand show how to implement LISP on terms of that.\r\n\r\n44\r\n00:03:15,500 --> 00:03:21,325\r\nAnd, remember, the idea of the register machine is that\r\n\r\n45\r\n00:03:21,325 --> 00:03:24,800\r\nthere's a fixed and finite part of the machine.\r\n\r\n46\r\n00:03:24,800 --> 00:03:27,050\r\nThere's a finite-state controller, which does some\r\n\r\n47\r\n00:03:27,050 --> 00:03:30,510\r\nparticular thing with a particular amount of hardware.\r\n\r\n48\r\n00:03:30,510 --> 00:03:33,550\r\nThere are particular data paths, the operation the machine does \r\n\r\n49\r\n00:03:33,550 --> 00:03:37,725\r\nAnd then, in order to implement recursion and sustain the illusion of infinity, \r\n\r\n50\r\n00:03:37,725 --> 00:03:42,060\r\nthere's some large amount of memory, which is the stack.\r\n\r\n51\r\n00:03:42,060 --> 00:03:47,025\r\nSo, if we implement LISP in terms of a register machine,\r\n\r\n52\r\n00:03:47,025 --> 00:03:49,850\r\nthen everything ought to become, at this point,completely concrete.\r\n\r\n53\r\n00:03:49,850 --> 00:03:51,650\r\nAll the magic should go away.\r\n\r\n54\r\n00:03:51,650 --> 00:03:55,140\r\nAnd, by the end of this talk, I want you get the feeling\r\n\r\n55\r\n00:03:55,140 --> 00:03:59,675\r\nthat, as opposed to this very mysterious meta-circular evaluator\r\n\r\n56\r\n00:03:59,675 --> 00:04:02,850\r\nthat a LISP evaluator really is something that's concrete enough\r\n\r\n57\r\n00:04:02,850 --> 00:04:04,720\r\nthat you can hold in the palm of your hand.\r\n\r\n58\r\n00:04:04,720 --> 00:04:06,450\r\nYou should be able to imagine holding\r\n\r\n59\r\n00:04:06,450 --> 00:04:09,546\r\nholding a LISP interpreter there.\r\n\r\n60\r\n00:04:09,546 --> 00:04:10,950\r\nAll right, how are we going to do this?\r\n\r\n61\r\n00:04:10,950 --> 00:04:13,960\r\nWe already have all the ingredients.\r\n\r\n62\r\n00:04:13,960 --> 00:04:17,450\r\nSee, what you learned last time from Jerry \r\n\r\n63\r\n00:04:17,450 --> 00:04:22,600\r\nis how to take any particular couple of LISP procedures\r\n\r\n64\r\n00:04:22,600 --> 00:04:28,210\r\nand hand-translate them into something that runs on a register machine.\r\n\r\n65\r\n00:04:28,210 --> 00:04:30,525\r\nSo, to implement all of LISP on a register machine,\r\n\r\n66\r\n00:04:30,525 --> 00:04:33,600\r\nall we have to do is take the particular procedures \r\n\r\n67\r\n00:04:33,600 --> 00:04:36,050\r\nthat are the meta-circular evaluator \r\n\r\n68\r\n00:04:36,050 --> 00:04:38,825\r\nand hand-translate them for a register machine.\r\n\r\n69\r\n00:04:38,825 --> 00:04:42,320\r\nAnd that does all of LISP, right?\r\n\r\n70\r\n00:04:42,320 --> 00:04:45,380\r\nSo, in principle, we already know how to do this.\r\n\r\n71\r\n00:04:45,380 --> 00:04:51,275\r\nAnd, indeed, it's going to be no different, in kind, from\r\n\r\n72\r\n00:04:51,275 --> 00:04:54,670\r\nfrom translating, say, recursive factorial or recursive Fibonacci. \r\n\r\n73\r\n00:04:54,670 --> 00:04:56,840\r\nIt's just bigger and there's more of it.\r\n\r\n74\r\n00:04:56,840 --> 00:05:01,375\r\nSo it'd just be more details,  but nothing really conceptually new. \r\n\r\n75\r\n00:05:01,375 --> 00:05:04,876\r\nAnd also, when we've done that, and the thing is completely explicit,\r\n\r\n76\r\n00:05:04,876 --> 00:05:06,990\r\nand we see how to implement LISP in terms of\r\n\r\n77\r\n00:05:06,990 --> 00:05:10,085\r\nthe actual sequential register operations, \r\n\r\n78\r\n00:05:10,085 --> 00:05:14,810\r\nthat's going to be our final most explicit model of LISP in this course. \r\n\r\n79\r\n00:05:14,810 --> 00:05:16,950\r\nAnd, remember, that's a progression through this course. \r\n\r\n80\r\n00:05:16,950 --> 00:05:20,100\r\nWe started out with substitution,  which is sort of like algebra. \r\n\r\n81\r\n00:05:20,100 --> 00:05:21,838\r\nAnd then we went to the environment model,\r\n\r\n82\r\n00:05:21,838 --> 00:05:26,125\r\nwhich talked about the actual frames and how they got linked together. \r\n\r\n83\r\n00:05:26,125 --> 00:05:31,080\r\nAnd then we made that more concrete in the meta-circular evaluator. \r\n\r\n84\r\n00:05:31,080 --> 00:05:34,360\r\nThere are things the meta-circular evaluator doesn't tell us. \r\n\r\n85\r\n00:05:34,360 --> 00:05:36,090\r\nYou should realize that.\r\n\r\n86\r\n00:05:36,090 --> 00:05:40,420\r\nFor instance, it left unanswered the question of how\r\n\r\n87\r\n00:05:40,420 --> 00:05:45,175\r\na procedure, like recursive factorial here,\r\n\r\n88\r\n00:05:45,175 --> 00:05:47,210\r\nsomehow takes space that grows.\r\n\r\n89\r\n00:05:47,210 --> 00:05:51,948\r\nOn the other hand, a procedure which also looks syntactically recursive,\r\n\r\n90\r\n00:05:51,948 --> 00:05:56,760\r\ncalled fact-iter, somehow doesn't take space.We justify ,\r\n\r\n91\r\n00:05:56,760 --> 00:06:00,500\r\nWe justify that it doesn't need to take space\r\n\r\n92\r\n00:06:00,500 --> 00:06:01,960\r\nby showing the substitution model.\r\n\r\n93\r\n00:06:01,960 --> 00:06:07,275\r\nBut we didn't really say how it happens that the machine manages to do that, \r\n\r\n94\r\n00:06:07,275 --> 00:06:09,161\r\nthat that has to do with the details \r\n\r\n95\r\n00:06:09,161 --> 00:06:12,250\r\nof how arguments are passed to procedures.\r\n\r\n96\r\n00:06:12,250 --> 00:06:15,846\r\nAnd that's the thing we didn't see in the meta-circular evaluator precisely\r\n\r\n97\r\n00:06:15,846 --> 00:06:19,700\r\nbecause the way arguments got passed to procedures in this LISP \r\n\r\n98\r\n00:06:19,700 --> 00:06:25,050\r\ndepended on the way arguments got passed to procedures in this LISP. \r\n\r\n99\r\n00:06:26,070 --> 00:06:30,740\r\nBut, now, that's going to become extremely explicit.\r\n\r\n100\r\n00:06:30,740 --> 00:06:31,230\r\nOK.\r\n\r\n101\r\n00:06:31,230 --> 00:06:34,426\r\nWell, before going on to the evaluator, \r\n\r\n102\r\n00:06:34,426 --> 00:06:37,600\r\nlet me just give you a sense of what a whole LISP system looks like \r\n\r\n103\r\n00:06:37,600 --> 00:06:39,086\r\nso you can see the parts we're going to talk about \r\n\r\n104\r\n00:06:39,086 --> 00:06:43,250\r\nand the parts we're not going to talk about.\r\n\r\n105\r\n00:06:43,250 --> 00:06:48,675\r\nLet's see, over here is a happy LISP user,\r\n\r\n106\r\n00:06:48,675 --> 00:06:53,245\r\nand the LISP user is talking to something called the reader.\r\n\r\n107\r\n00:07:00,360 --> 00:07:14,170\r\nThe reader's job in life is to take characters from the user\r\n\r\n108\r\n00:07:14,170 --> 00:07:17,960\r\nand turn them into data structures in something called\r\n\r\n109\r\n00:07:17,960 --> 00:07:21,405\r\na list structure memory.\r\n\r\n110\r\n00:07:29,783 --> 00:07:32,653\r\nAll right, so the reader is going to take \r\n\r\n111\r\n00:07:32,653 --> 00:07:36,953\r\nsymbols, parentheses, and A's and B's, and 1s and 3s that you type in, \r\n\r\n112\r\n00:07:36,953 --> 00:07:39,150\r\nand turn these into actual list structure:\r\n\r\n113\r\n00:07:39,150 --> 00:07:39,156\r\npairs, and pointers, and things. \r\n\r\n114\r\n00:07:39,156 --> 00:07:42,340\r\npairs, and pointers, and things. \r\n\r\n115\r\n00:07:42,340 --> 00:07:45,850\r\nAnd so, by the time evaluator is going, there are no characters in the world. \r\n\r\n116\r\n00:07:45,850 --> 00:07:49,480\r\nAnd, of course, in more modern list systems, there's sort of\r\n\r\n117\r\n00:07:49,480 --> 00:07:52,325\r\na big morass here that might sit between the user and the reader:\r\n\r\n118\r\n00:07:52,325 --> 00:07:54,775\r\nWindows systems, and top levels, \r\n\r\n119\r\n00:07:54,775 --> 00:07:56,280\r\nand mice, and all kinds of things.\r\n\r\n120\r\n00:07:56,280 --> 00:07:59,590\r\nBut conceptually, characters are coming in.\r\n\r\n121\r\n00:07:59,590 --> 00:08:05,525\r\nAll right, the reader transforms these into pointers\r\n\r\n122\r\n00:08:05,525 --> 00:08:08,275\r\npointers to stuff in this memory, \r\n\r\n123\r\n00:08:08,275 --> 00:08:12,445\r\nand that's what the evaluator sees\r\n\r\n124\r\n00:08:15,300 --> 00:08:17,090\r\nOK? \r\n\r\n125\r\n00:08:17,090 --> 00:08:17,300\r\nThe evaluator has a bunch of helpers.\r\n\r\n126\r\n00:08:17,300 --> 00:08:19,780\r\nThe evaluator has a bunch of helpers.\r\n\r\n127\r\n00:08:19,780 --> 00:08:23,080\r\nIt has all possible primitive operators you might want.\r\n\r\n128\r\n00:08:23,080 --> 00:08:28,400\r\nSo there's a completely separate box,\r\n\r\n129\r\n00:08:28,400 --> 00:08:32,225\r\na floating point unit, \r\n\r\n130\r\n00:08:32,225 --> 00:08:35,960\r\nor all sorts of things, which do the primitive operators.\r\n\r\n131\r\n00:08:35,960 --> 00:08:37,548\r\nAnd, if you want more special primitives, \r\n\r\n132\r\n00:08:37,548 --> 00:08:42,080\r\nyou build more primitive operators, but they're separate from the evaluator.\r\n\r\n133\r\n00:08:42,080 --> 00:08:45,025\r\nThe evaluator finally gets an answer\r\n\r\n134\r\n00:08:45,025 --> 00:08:50,450\r\nand communicates that to the printer.\r\n\r\n135\r\n00:08:50,780 --> 00:08:52,265\r\nAnd now, the printer's job in life is to take\r\n\r\n136\r\n00:08:52,265 --> 00:08:55,318\r\nthis list structure coming from the evaluator, \r\n\r\n137\r\n00:08:55,318 --> 00:08:57,614\r\nand turn it back into characters,\r\n\r\n138\r\n00:09:01,700 --> 00:09:04,075\r\nand communicate them to the user through \r\n\r\n139\r\n00:09:04,075 --> 00:09:05,750\r\nwhatever interface there is.\r\n\r\n140\r\n00:09:08,050 --> 00:09:12,670\r\nOK. Well, today, what we're going to talk about is this evaluator.  \r\n\r\n141\r\n00:09:12,670 --> 00:09:15,200\r\nThe primitive operators have nothing particular to do with LISP,\r\n\r\n142\r\n00:09:15,200 --> 00:09:19,175\r\nthey're however you like to implement primitive operations. \r\n\r\n143\r\n00:09:19,175 --> 00:09:22,187\r\nThe reader and printer are actually complicated, \r\n\r\n144\r\n00:09:22,187 --> 00:09:24,420\r\nbut we're not going to talk about them.\r\n\r\n145\r\n00:09:24,420 --> 00:09:27,100\r\nThey sort of have to do with details of how you might build\r\n\r\n146\r\n00:09:27,100 --> 00:09:29,900\r\nbuild up list structure from characters.\r\n\r\n147\r\n00:09:29,900 --> 00:09:32,490\r\nSo that is a long story, but we're not going to talk about it,\r\n\r\n148\r\n00:09:32,490 --> 00:09:36,930\r\nthe list structure memory, we'll talk about next time.\r\n\r\n149\r\n00:09:36,930 --> 00:09:40,125\r\nSo, pretty much, except for the details of reading and printing,\r\n\r\n150\r\n00:09:40,125 --> 00:09:43,250\r\nthe only mystery that's going to be left after you see the evaluator\r\n\r\n151\r\n00:09:43,250 --> 00:09:46,295\r\nis how you build list structure on conventional memories. \r\n\r\n152\r\n00:09:46,295 --> 00:09:50,580\r\nBut we'll worry about that next time too.\r\n\r\n153\r\n00:09:50,580 --> 00:09:51,830\r\nOK.\r\n\r\n154\r\n00:09:53,350 --> 00:09:56,110\r\nWell, let's start talking about the evaluator.\r\n\r\n155\r\n00:09:56,110 --> 00:09:59,775\r\nThe one that we're going to show you, of course, is not,\r\n\r\n156\r\n00:09:59,775 --> 00:10:01,120\r\nI think, nothing special about it.\r\n\r\n157\r\n00:10:01,120 --> 00:10:04,810\r\nIt's just a particular register machine that runs LISP. \r\n\r\n158\r\n00:10:04,810 --> 00:10:09,890\r\nAnd it has seven registers, and here are the seven registers. \r\n\r\n159\r\n00:10:09,890 --> 00:10:14,925\r\nThere's a register, called EXP, and its job is to \r\n\r\n160\r\n00:10:14,925 --> 00:10:18,370\r\nhold the expression to be evaluated.\r\n\r\n161\r\n00:10:18,370 --> 00:10:21,750\r\nAnd by that, I mean it's going to hold a pointer\r\n\r\n162\r\n00:10:21,750 --> 00:10:23,764\r\nto someplace in list structure memory that holds\r\n\r\n163\r\n00:10:23,764 --> 00:10:26,550\r\nthe expression to be evaluated.\r\n\r\n164\r\n00:10:26,550 --> 00:10:31,000\r\nThere's a register, called ENV, which holds the environment\r\n\r\n165\r\n00:10:31,000 --> 00:10:34,070\r\nin which this expression is to be evaluated.\r\n\r\n166\r\n00:10:34,070 --> 00:10:38,240\r\nAnd, again, I made a pointer. The environment is some data structure. \r\n\r\n167\r\n00:10:38,240 --> 00:10:40,425\r\nThere's a register, called FUN, which will \r\n\r\n168\r\n00:10:40,425 --> 00:10:44,350\r\nwhich will hold the procedure to be applied when you go to apply a procedure.\r\n\r\n169\r\n00:10:44,350 --> 00:10:47,325\r\nA register, called ARGL, \r\n\r\n170\r\n00:10:47,325 --> 00:10:50,200\r\nwhich wants the list of evaluated arguments.\r\n\r\n171\r\n00:10:50,200 --> 00:10:53,140\r\nWhat you can start seeing here is the basic structure of the evaluator. \r\n\r\n172\r\n00:10:53,140 --> 00:10:54,490\r\nRemember how evaluators work.\r\n\r\n173\r\n00:10:54,490 --> 00:10:57,670\r\nThere's a piece that takes expressions and environments,\r\n\r\n174\r\n00:10:57,670 --> 00:10:59,100\r\nand there's a piece that takes\r\n\r\n175\r\n00:10:59,100 --> 00:11:03,480\r\nfunctions, or procedures and arguments.\r\n\r\n176\r\n00:11:03,480 --> 00:11:07,294\r\nAnd going back and forth around here is the eval/apply loop. \r\n\r\n177\r\n00:11:07,294 --> 00:11:10,000\r\nSo those are the basic pieces of the eval and apply.\r\n\r\n178\r\n00:11:10,000 --> 00:11:11,610\r\nThen there's some other things, there's continue.\r\n\r\n179\r\n00:11:11,610 --> 00:11:15,340\r\nYou just saw before how the continue register is used to\r\n\r\n180\r\n00:11:15,340 --> 00:11:18,750\r\nimplement recursion and stack discipline.\r\n\r\n181\r\n00:11:18,750 --> 00:11:23,925\r\nThere's a register that's going to hold the result of some evaluation. \r\n\r\n182\r\n00:11:23,925 --> 00:11:26,555\r\nAnd then, besides that, there's one temporary register, \r\n\r\n183\r\n00:11:26,555 --> 00:11:29,280\r\ncalled UNEV, which typically, in the evaluator,\r\n\r\n184\r\n00:11:29,280 --> 00:11:30,625\r\nis going to be used to hold \r\n\r\n185\r\n00:11:30,625 --> 00:11:33,950\r\ntemporary pieces of the expression you're working on, \r\n\r\n186\r\n00:11:33,950 --> 00:11:37,150\r\nwhich you haven't gotten around to evaluate yet, right? \r\n\r\n187\r\n00:11:37,150 --> 00:11:40,646\r\nSo there's my machine: a seven-register machine.\r\n\r\n188\r\n00:11:40,646 --> 00:11:42,981\r\nAnd, of course, you might want to make a machine with\r\n\r\n189\r\n00:11:42,981 --> 00:11:44,846\r\na lot more registers to get better performance, \r\n\r\n190\r\n00:11:44,846 --> 00:11:48,480\r\nbut this is just a tiny, minimal one.\r\n\r\n191\r\n00:11:48,480 --> 00:11:49,780\r\nWell, how about the data paths?\r\n\r\n192\r\n00:11:49,780 --> 00:11:55,100\r\nThis machine has a lot of special operations for LISP.\r\n\r\n193\r\n00:11:55,100 --> 00:12:00,120\r\nSo, here are some typical data paths.\r\n\r\n194\r\n00:12:00,120 --> 00:12:03,320\r\nA typical one might be, oh, assign to the VAL register\r\n\r\n195\r\n00:12:03,320 --> 00:12:06,710\r\nthe contents of the EXP register.\r\n\r\n196\r\n00:12:06,710 --> 00:12:11,900\r\nIn terms of those diagrams you saw, that's a little button on some arrow. \r\n\r\n197\r\n00:12:11,900 --> 00:12:13,699\r\nHere's a more complicated one.\r\n\r\n198\r\n00:12:13,699 --> 00:12:18,810\r\nIt says branch, if the thing in the expression register is\r\n\r\n199\r\n00:12:18,810 --> 00:12:23,550\r\na conditional to some label here, called the ev-conditional. \r\n\r\n200\r\n00:12:23,550 --> 00:12:26,230\r\nAnd you can imagine this implemented in a lot of different ways. \r\n\r\n201\r\n00:12:26,230 --> 00:12:30,600\r\nYou might imagine this conditional test as a special purpose sub-routine,  \r\n\r\n202\r\n00:12:30,600 --> 00:12:33,845\r\nand conditional might be represented as some data abstraction\r\n\r\n203\r\n00:12:33,845 --> 00:12:36,610\r\nthat you don't care about at this level of detail.\r\n\r\n204\r\n00:12:36,610 --> 00:12:37,980\r\nSo that might be done as a sub-routine.\r\n\r\n205\r\n00:12:37,980 --> 00:12:40,900\r\nThis might be a machine with hardware-types, \r\n\r\n206\r\n00:12:40,900 --> 00:12:45,350\r\nand conditional might be testing some bits for a particular code.\r\n\r\n207\r\n00:12:45,350 --> 00:12:46,417\r\nThere are all sorts of ways that's \r\n\r\n208\r\n00:12:46,417 --> 00:12:50,190\r\nbeneath the level of abstraction we're looking at. \r\n\r\n209\r\n00:12:50,190 --> 00:12:53,247\r\nAnother kind of operation, and there are a lot of different operations\r\n\r\n210\r\n00:12:53,247 --> 00:12:56,840\r\nassigned to EXP, the first clause of what's in EXP. \r\n\r\n211\r\n00:12:56,840 --> 00:12:59,260\r\nThis might be part of processing a conditional.\r\n\r\n212\r\n00:12:59,260 --> 00:13:04,258\r\nAnd, again, first clause is some selector whose details we don't care about. \r\n\r\n213\r\n00:13:04,258 --> 00:13:06,300\r\nAnd you can, again, imagine that as a sub-routine\r\n\r\n214\r\n00:13:06,300 --> 00:13:09,180\r\nwhich'll do some list operations, or you can imagine that as\r\n\r\n215\r\n00:13:09,180 --> 00:13:12,170\r\nsomething that's built directly into hardware.\r\n\r\n216\r\n00:13:12,170 --> 00:13:15,222\r\nThe reason I keep saying you can imagine it built directly into hardware\r\n\r\n217\r\n00:13:15,222 --> 00:13:18,360\r\nis even though there are a lot of operations,\r\n\r\n218\r\n00:13:18,360 --> 00:13:19,740\r\nthere are still a fixed number of them.\r\n\r\n219\r\n00:13:19,740 --> 00:13:22,370\r\nI forget how many, maybe 150.\r\n\r\n220\r\n00:13:22,370 --> 00:13:26,167\r\nSo, it's plausible to think of building these directly into hardware. \r\n\r\n221\r\n00:13:26,167 --> 00:13:28,275\r\nHere's a more complicated one.\r\n\r\n222\r\n00:13:28,275 --> 00:13:31,500\r\nYou can see this has to do with looking up the values of variables. \r\n\r\n223\r\n00:13:31,500 --> 00:13:35,550\r\nIt says assign to the VAL register the result of looking up\r\n\r\n224\r\n00:13:35,550 --> 00:13:39,025\r\nthe variable value of some particular expression, \r\n\r\n225\r\n00:13:39,025 --> 00:13:42,600\r\nwhich,in this case, is supposed to be a variable in some environment. \r\n\r\n226\r\n00:13:42,600 --> 00:13:46,280\r\nAnd this'll be some operation that searches through \r\n\r\n227\r\n00:13:46,280 --> 00:13:49,325\r\nthe environment structure, however it is represented, \r\n\r\n228\r\n00:13:49,325 --> 00:13:52,019\r\nand goes and looks up that variable.\r\n\r\n229\r\n00:13:52,019 --> 00:13:55,790\r\nAnd, again, that's below the level of detail that we're thinking about. \r\n\r\n230\r\n00:13:55,790 --> 00:13:57,300\r\nThis has to do with the details of \r\n\r\n231\r\n00:13:57,300 --> 00:14:00,075\r\nthe data structures for representing environments. \r\n\r\n232\r\n00:14:00,075 --> 00:14:03,679\r\nBut, anyway, there is this fixed and finite number \r\n\r\n233\r\n00:14:03,679 --> 00:14:06,325\r\nof operations in the register machine.\r\n\r\n234\r\n00:14:08,500 --> 00:14:11,720\r\nWell, what's its overall structure?\r\n\r\n235\r\n00:14:11,720 --> 00:14:14,675\r\nThose are some typical operations.\r\n\r\n236\r\n00:14:14,675 --> 00:14:16,442\r\nRemember what we have to do, \r\n\r\n237\r\n00:14:16,442 --> 00:14:20,172\r\nwe have to take the meta-circular evaluator--\r\n\r\n238\r\n00:14:20,172 --> 00:14:22,767\r\nand here's a piece of the meta-circular evaluator.\r\n\r\n239\r\n00:14:22,767 --> 00:14:28,050\r\nThis is the one using abstract syntax that's in the book.\r\n\r\n240\r\n00:14:28,050 --> 00:14:33,500\r\nIt's a little bit different from the one that Jerry shows you. \r\n\r\n241\r\n00:14:33,500 --> 00:14:37,874\r\nAnd the main thing to remember about the evaluator is that\r\n\r\n242\r\n00:14:37,874 --> 00:14:43,425\r\nit's doing some sort of case analysis on the kinds of expressions: \r\n\r\n243\r\n00:14:43,425 --> 00:14:48,560\r\nso if it's either self-evaluated, or quoted, or whatever else. \r\n\r\n244\r\n00:14:48,560 --> 00:14:50,864\r\nAnd then, in the general case where\r\n\r\n245\r\n00:14:50,864 --> 00:14:53,550\r\nthe expression it's looking at is an application, \r\n\r\n246\r\n00:14:53,550 --> 00:14:55,750\r\nthere's some tricky recursions going on.\r\n\r\n247\r\n00:14:55,750 --> 00:15:00,730\r\nFirst of all, eval has to call itself both to evaluate the\r\n\r\n248\r\n00:15:00,730 --> 00:15:05,880\r\noperator and to evaluate all the operands.\r\n\r\n249\r\n00:15:05,880 --> 00:15:10,850\r\nSo there's this sort of red recursion of values walking down the tree\r\n\r\n250\r\n00:15:10,850 --> 00:15:12,270\r\nthat's really the easy recursion.\r\n\r\n251\r\n00:15:12,270 --> 00:15:14,750\r\nThat's just a val walking down this tree of expressions.\r\n\r\n252\r\n00:15:14,750 --> 00:15:16,305\r\nThen, in the evaluator, there's a hard recursion.\r\n\r\n253\r\n00:15:16,305 --> 00:15:21,650\r\nThere's the red to green. Eval calls apply. \r\n\r\n254\r\n00:15:22,470 --> 00:15:26,450\r\nThat's the case where evaluating a procedure or argument \r\n\r\n255\r\n00:15:26,450 --> 00:15:30,370\r\nreduces to applying the procedure to the list of arguments. \r\n\r\n256\r\n00:15:30,370 --> 00:15:33,875\r\nAnd then, apply comes over here.\r\n\r\n257\r\n00:15:34,770 --> 00:15:37,650\r\nApply takes a procedure and arguments\r\n\r\n258\r\n00:15:37,650 --> 00:15:41,051\r\nand, in the general case where there's a compound procedure, \r\n\r\n259\r\n00:15:41,051 --> 00:15:44,560\r\napply goes around and green calls red. Eval --\r\n\r\n260\r\n00:15:44,560 --> 00:15:48,170\r\nApply comes around and calls eval again.\r\n\r\n261\r\n00:15:48,170 --> 00:15:51,330\r\nEval's the body of the procedure in the result of\r\n\r\n262\r\n00:15:51,330 --> 00:15:55,485\r\nextending the environment with the parameters of the procedure\r\n\r\n263\r\n00:15:55,485 --> 00:15:57,379\r\nby binding the arguments.\r\n\r\n264\r\n00:15:59,620 --> 00:16:01,626\r\nExcept in the primitive case, where it just calls something else\r\n\r\n265\r\n00:16:01,626 --> 00:16:05,980\r\nprimitive-apply, which is not really the business of the evaluator. \r\n\r\n266\r\n00:16:05,980 --> 00:16:11,249\r\nSo this sort of red to green, to red to green, that's the\r\n\r\n267\r\n00:16:11,249 --> 00:16:13,975\r\nthat's the eval/apply loop, \r\n\r\n268\r\n00:16:13,975 --> 00:16:19,475\r\nand that's the thing that we're going to want to see in the evaluator.\r\n\r\n269\r\n00:16:19,475 --> 00:16:21,079\r\nWell, it won't surprise you at all that \r\n\r\n270\r\n00:16:21,079 --> 00:16:27,470\r\nthe two big pieces of this evaluator correspond to eval and apply.\r\n\r\n271\r\n00:16:27,470 --> 00:16:29,548\r\nThere's a piece called eval-dispatch, \r\n\r\n272\r\n00:16:29,548 --> 00:16:31,913\r\nand a piece called apply-dispatch.\r\n\r\n273\r\n00:16:31,913 --> 00:16:34,095\r\nAnd, before we get into the details of the code, \r\n\r\n274\r\n00:16:34,095 --> 00:16:37,760\r\nthe way to understand this is to think, again, in terms of\r\n\r\n275\r\n00:16:37,760 --> 00:16:41,870\r\nthese pieces of the evaluator having contracts with the rest of the world. \r\n\r\n276\r\n00:16:41,870 --> 00:16:45,780\r\nWhat do they do from the outside before getting into the grungy details? \r\n\r\n277\r\n00:16:45,780 --> 00:16:51,300\r\nWell, the contract for eval-dispatch-- remember, it corresponds to eval. \r\n\r\n278\r\n00:16:51,300 --> 00:16:54,100\r\nIt's got to evaluate an expression in an environment.\r\n\r\n279\r\n00:16:54,100 --> 00:16:56,525\r\nSo, in particular, what this one is going to do,\r\n\r\n280\r\n00:16:56,525 --> 00:16:59,920\r\neval-dispatch will assume that, when you call it, that\r\n\r\n281\r\n00:16:59,920 --> 00:17:03,640\r\nthe expression you want to evaluate is in the EXP register. \r\n\r\n282\r\n00:17:03,640 --> 00:17:07,750\r\nThe environment in which you want the evaluation to take place\r\n\r\n283\r\n00:17:07,750 --> 00:17:09,569\r\nis in the ENV register. \r\n\r\n284\r\n00:17:09,569 --> 00:17:11,899\r\nAnd continue tells you the place where the machine should\r\n\r\n285\r\n00:17:11,899 --> 00:17:14,575\r\ngo next when the evaluation is done.\r\n\r\n286\r\n00:17:17,440 --> 00:17:21,070\r\nEval-dispatch's contract is that it'll actually perform that evaluation, \r\n\r\n287\r\n00:17:21,070 --> 00:17:26,619\r\nand, at the end of which, it'll end up at the place specified by continue. \r\n\r\n288\r\n00:17:26,619 --> 00:17:29,825\r\nThe result of the evaluation will be in the VAL register.\r\n\r\n289\r\n00:17:29,825 --> 00:17:32,964\r\nAnd it just warns you, it makes no promises about\r\n\r\n290\r\n00:17:32,964 --> 00:17:35,230\r\nwhat happens to the registers.\r\n\r\n291\r\n00:17:35,230 --> 00:17:37,490\r\nAll other registers might be destroyed.\r\n\r\n292\r\n00:17:37,490 --> 00:17:41,412\r\nSo, there's one piece, OK?\r\n\r\n293\r\n00:17:41,412 --> 00:17:45,925\r\nTogether, the pieces, apply-dispatch that corresponds to apply,\r\n\r\n294\r\n00:17:45,925 --> 00:17:48,731\r\nit's got to apply a procedure to some arguments, \r\n\r\n295\r\n00:17:48,731 --> 00:17:51,434\r\nso it assumes that this register, ARGL,\r\n\r\n296\r\n00:17:51,434 --> 00:17:54,540\r\ncontains a list of the evaluated arguments.\r\n\r\n297\r\n00:17:54,540 --> 00:17:57,220\r\nFUN contains the procedure.\r\n\r\n298\r\n00:17:57,220 --> 00:17:59,500\r\nThose correspond to the arguments to the apply\r\n\r\n299\r\n00:17:59,500 --> 00:18:02,300\r\nprocedure in the meta-circular evaluator.\r\n\r\n300\r\n00:18:03,970 --> 00:18:07,676\r\nAnd apply, in this particular evaluator, we're going to use a discipline which says\r\n\r\n301\r\n00:18:07,676 --> 00:18:12,556\r\nthe place the machine should go to next when apply is done \r\n\r\n302\r\n00:18:12,556 --> 00:18:17,070\r\nis, at the moment apply-dispatch is called at the top of the stack\r\n\r\n303\r\n00:18:17,070 --> 00:18:21,840\r\nthat's just discipline for the way this particular machine's organized. \r\n\r\n304\r\n00:18:21,840 --> 00:18:23,700\r\nAnd now apply's contract is given all that.\r\n\r\n305\r\n00:18:23,700 --> 00:18:25,540\r\nIt'll perform the application.\r\n\r\n306\r\n00:18:25,540 --> 00:18:28,890\r\nThe result of that application will end up in VAL.\r\n\r\n307\r\n00:18:28,890 --> 00:18:31,120\r\nThe stack will be popped.\r\n\r\n308\r\n00:18:31,120 --> 00:18:34,841\r\nAnd, again, the contents of all the other registers may be destroyed.\r\n\r\n309\r\n00:18:34,841 --> 00:18:39,760\r\nAll right? So that's the basic organization of this machine.\r\n\r\n310\r\n00:18:39,760 --> 00:18:41,110\r\nLet's break for a little bit and see if there are any\r\n\r\n311\r\n00:18:41,110 --> 00:18:42,700\r\nquestions, and then we'll do a real example.\r\n\r\n312\r\n00:19:47,850 --> 00:19:50,175\r\nWell, let's take the register machine now, \r\n\r\n313\r\n00:19:50,175 --> 00:19:52,175\r\nand actually step through,\r\n\r\n314\r\n00:19:52,200 --> 00:19:58,708\r\nand really, in real detail, so you see completely concrete\r\n\r\n315\r\n00:19:58,708 --> 00:20:03,400\r\nhow some expressions are evaluated, all right?\r\n\r\n316\r\n00:20:03,400 --> 00:20:09,300\r\nSo, let's start with a very simple expression.\r\n\r\n317\r\n00:20:09,620 --> 00:20:14,150\r\nLet's evaluate the expression 1.\r\n\r\n318\r\n00:20:18,775 --> 00:20:21,279\r\nAnd we need an environment, so let's imagine that \r\n\r\n319\r\n00:20:21,279 --> 00:20:24,025\r\nsomewhere there's an environment, we'll call it E,0.\r\n\r\n320\r\n00:20:30,260 --> 00:20:35,620\r\nAnd just, since we'll use these later, \r\n\r\n321\r\n00:20:35,620 --> 00:20:38,360\r\nwe obviously don't really need anything to evaluate 1.\r\n\r\n322\r\n00:20:38,360 --> 00:20:41,202\r\nBut, just for reference later, let's assume that E,0 has in it\r\n\r\n323\r\n00:20:41,202 --> 00:20:49,140\r\nan X that's bound to 3 and a Y that's bound to 4, OK?\r\n\r\n324\r\n00:20:49,140 --> 00:20:53,700\r\nAnd now what we're going to do is we're going to evaluate 1\r\n\r\n325\r\n00:20:53,700 --> 00:20:59,650\r\nin this environment, and so the ENV register has a pointer\r\n\r\n326\r\n00:20:59,650 --> 00:21:03,560\r\nto this environment, E,0, all right?\r\n\r\n327\r\n00:21:03,560 --> 00:21:05,650\r\nSo let's watch that thing go.\r\n\r\n328\r\n00:21:05,650 --> 00:21:08,260\r\nWhat I'm going to do is step through the code.\r\n\r\n329\r\n00:21:08,260 --> 00:21:09,782\r\nAnd, let's see, I'll be the controller.\r\n\r\n330\r\n00:21:09,782 --> 00:21:12,980\r\nAnd now what I need, since this gets rather complicated,\r\n\r\n331\r\n00:21:12,980 --> 00:21:16,830\r\nis a very little execution unit.\r\n\r\n332\r\n00:21:16,830 --> 00:21:21,310\r\nSo here's the execution unit, OK?\r\n\r\n333\r\n00:21:22,624 --> 00:21:23,874\r\nOK.\r\n\r\n334\r\n00:21:27,088 --> 00:21:28,590\r\nOK.\r\n\r\n335\r\n00:21:28,590 --> 00:21:30,533\r\nAll right, now we're going to start.\r\n\r\n336\r\n00:21:30,533 --> 00:21:33,700\r\nWe're going to start the machine at eval-dispatch, right? \r\n\r\n337\r\n00:21:33,700 --> 00:21:35,875\r\nThat's the beginning of this.\r\n\r\n338\r\n00:21:35,875 --> 00:21:39,320\r\nEval-dispatch is going to look at the expression in dispatch,\r\n\r\n339\r\n00:21:39,320 --> 00:21:40,875\r\njust like eval \r\n\r\n340\r\n00:21:40,875 --> 00:21:41,760\r\nwhere we look at the very first thing.\r\n\r\n341\r\n00:21:41,760 --> 00:21:47,950\r\nWe branch on whether or not this expression is self-evaluating. \r\n\r\n342\r\n00:21:47,950 --> 00:21:52,171\r\nSelf-evaluating is some abstraction we put into the machine-- \r\n\r\n343\r\n00:21:52,171 --> 00:21:53,515\r\nit's going to be true for numbers--\r\n\r\n344\r\n00:21:53,515 --> 00:21:56,775\r\nto a place called ev-self-eval, right?\r\n\r\n345\r\n00:21:56,775 --> 00:22:00,010\r\nSo me, being the controller, looks at ev-self-eval, \r\n\r\n346\r\n00:22:00,010 --> 00:22:02,607\r\nso we'll go over to there.\r\n\r\n347\r\n00:22:02,607 --> 00:22:08,128\r\nEv-self-eval says fine, assign to val \r\n\r\n348\r\n00:22:08,128 --> 00:22:15,220\r\nwhatever is in the expression unit, OK?\r\n\r\n349\r\n00:22:15,220 --> 00:22:17,600\r\nAnd I have a bug \r\n\r\n350\r\n00:22:17,600 --> 00:22:17,650\r\nbecause what I didn't do when I initialized this machine\r\n\r\n351\r\n00:22:17,650 --> 00:22:21,625\r\nbecause what I didn't do when I initialized this machine\r\n\r\n352\r\n00:22:21,625 --> 00:22:24,650\r\nis also say what's supposed to happen when it's done, \r\n\r\n353\r\n00:22:24,650 --> 00:22:27,640\r\nso I should have started out the machine with\r\n\r\n354\r\n00:22:27,640 --> 00:22:32,050\r\ndone being in the continue register, OK?\r\n\r\n355\r\n00:22:32,050 --> 00:22:33,079\r\nSo we assign to VAL.\r\n\r\n356\r\n00:22:33,079 --> 00:22:38,000\r\nAnd now go to fetch of continue, and now change-- \r\n\r\n357\r\n00:22:38,000 --> 00:22:40,000\r\nOK.\r\n\r\n358\r\n00:22:40,000 --> 00:22:42,160\r\nOK, let's try something harder.\r\n\r\n359\r\n00:22:42,160 --> 00:22:44,787\r\nLet's reset the machine here, \r\n\r\n360\r\n00:22:44,787 --> 00:22:51,562\r\nand we'll put in the expression register, X, OK?\r\n\r\n361\r\n00:22:56,710 --> 00:22:59,610\r\nStart again at eval-dispatch.\r\n\r\n362\r\n00:22:59,610 --> 00:23:01,690\r\nCheck, is it self-evaluating?\r\n\r\n363\r\n00:23:01,690 --> 00:23:02,650\r\nNo.\r\n\r\n364\r\n00:23:02,650 --> 00:23:04,630\r\nIs it a variable?\r\n\r\n365\r\n00:23:04,630 --> 00:23:05,560\r\nYes.\r\n\r\n366\r\n00:23:05,560 --> 00:23:08,380\r\nWe go off to ev-variable.\r\n\r\n367\r\n00:23:08,380 --> 00:23:12,131\r\nIt says assign to VAL,\r\n\r\n368\r\n00:23:12,131 --> 00:23:16,150\r\nlook up the variable value in the expression register, OK?\r\n\r\n369\r\n00:23:21,075 --> 00:23:23,625\r\nGo to fetch of continue.\r\n\r\n370\r\n00:23:23,625 --> 00:23:24,875\r\nPROFESSOR: Done.\r\n\r\n371\r\n00:23:27,252 --> 00:23:28,950\r\nPROFESSOR: OK.\r\n\r\n372\r\n00:23:28,950 --> 00:23:29,430\r\nAll right.\r\n\r\n373\r\n00:23:29,430 --> 00:23:31,330\r\nWell, that's the basic idea.\r\n\r\n374\r\n00:23:31,330 --> 00:23:32,688\r\nThat's a simple operation of the machine.\r\n\r\n375\r\n00:23:32,688 --> 00:23:36,070\r\nNow, let's actually do something a little bit more interesting. \r\n\r\n376\r\n00:23:36,070 --> 00:23:49,678\r\nLet's look at the expression the sum of x and y.\r\n\r\n377\r\n00:23:49,678 --> 00:23:50,130\r\nOK.\r\n\r\n378\r\n00:23:50,130 --> 00:23:54,350\r\nAnd now we'll see how you start unrolling these expression trees.\r\n\r\n379\r\n00:23:56,625 --> 00:23:59,434\r\nWell, start again at eval-dispatch.\r\n\r\n380\r\n00:24:04,610 --> 00:24:05,935\r\nSelf-evaluating?\r\n\r\n381\r\n00:24:05,935 --> 00:24:06,850\r\nNo.\r\n\r\n382\r\n00:24:06,850 --> 00:24:07,850\r\nVariable? No. \r\n\r\n383\r\n00:24:07,850 --> 00:24:10,270\r\nAll the other special forms which I didn't write down,\r\n\r\n384\r\n00:24:10,270 --> 00:24:12,480\r\nlike quote, and lambda, and set, and whatever,\r\n\r\n385\r\n00:24:12,480 --> 00:24:13,260\r\nit's none of those.\r\n\r\n386\r\n00:24:13,260 --> 00:24:15,889\r\nIt turns out to be an application,\r\n\r\n387\r\n00:24:15,889 --> 00:24:19,970\r\nso we go off to ev-application, OK?\r\n\r\n388\r\n00:24:19,970 --> 00:24:25,580\r\nEv-application, remember what it's going to do overall.\r\n\r\n389\r\n00:24:25,580 --> 00:24:28,310\r\nIt is going to evaluate the operator.\r\n\r\n390\r\n00:24:28,310 --> 00:24:32,225\r\nIt's going to evaluate the arguments,\r\n\r\n391\r\n00:24:32,225 --> 00:24:35,060\r\nand then it's going to go apply them.\r\n\r\n392\r\n00:24:35,060 --> 00:24:37,887\r\nSo, before we start, since we're being very literal, \r\n\r\n393\r\n00:24:37,887 --> 00:24:40,435\r\nwe'd better remember that, somewhere in this environment,\r\n\r\n394\r\n00:24:40,435 --> 00:24:44,475\r\nit's linked to another environment in which\r\n\r\n395\r\n00:24:44,475 --> 00:24:51,475\r\nplus is bound to the primitive procedure plus \r\n\r\n396\r\n00:24:51,475 --> 00:24:55,340\r\nbefore we get an unknown variable in our machine.\r\n\r\n397\r\n00:24:55,340 --> 00:24:58,625\r\nOK, so we're at ev-application.\r\n\r\n398\r\n00:24:59,700 --> 00:25:04,405\r\nOK, assign to UNEV the operands \r\n\r\n399\r\n00:25:04,405 --> 00:25:07,920\r\nof what's in the expression register, OK?\r\n\r\n400\r\n00:25:07,920 --> 00:25:09,230\r\nThose are the operands.\r\n\r\n401\r\n00:25:09,230 --> 00:25:13,225\r\nUNEV's a temporary register where we're going to save them. \r\n\r\n402\r\n00:25:13,225 --> 00:25:13,860\r\nPROFESSOR: I'm assigning.\r\n\r\n403\r\n00:25:13,860 --> 00:25:18,070\r\nPROFESSOR: Assign to x the operator.\r\n\r\n404\r\n00:25:18,070 --> 00:25:21,849\r\nNow, notice we've destroyed that expression in x, \r\n\r\n405\r\n00:25:21,849 --> 00:25:25,820\r\nbut the piece that we need is now in UNEV. OK.\r\n\r\n406\r\n00:25:25,820 --> 00:25:28,750\r\nNow, we're going to get set up to recursively evaluate the operator. \r\n\r\n407\r\n00:25:28,750 --> 00:25:32,825\r\nSave the continue register on the stack.\r\n\r\n408\r\n00:25:34,870 --> 00:25:37,600\r\nSave the environment.\r\n\r\n409\r\n00:25:40,520 --> 00:25:43,594\r\nSave UNEV. \r\n\r\n410\r\n00:25:49,409 --> 00:25:56,234\r\nOK, assign to continue a label called eval-args.\r\n\r\n411\r\n00:26:01,400 --> 00:26:01,950\r\nNow, what have we done?\r\n\r\n412\r\n00:26:01,950 --> 00:26:04,380\r\nWe've set up for a recursive call. \r\n\r\n413\r\n00:26:04,380 --> 00:26:06,280\r\nWe're about to go to eval-dispatch.\r\n\r\n414\r\n00:26:06,280 --> 00:26:10,230\r\nWe've set up for a recursive call to eval-dispatch.\r\n\r\n415\r\n00:26:10,230 --> 00:26:11,020\r\nWhat did we do?\r\n\r\n416\r\n00:26:11,020 --> 00:26:14,425\r\nWe took the things we're going to need later,\r\n\r\n417\r\n00:26:14,425 --> 00:26:16,363\r\nthose operands that were in UNEV;\r\n\r\n418\r\n00:26:16,363 --> 00:26:19,073\r\nthe environment in which we're going to eventually have to, \r\n\r\n419\r\n00:26:19,073 --> 00:26:22,129\r\nmaybe, evaluate those operands;\r\n\r\n420\r\n00:26:22,129 --> 00:26:25,265\r\nthe place we eventually want to go to, which, in this case, was done;\r\n\r\n421\r\n00:26:25,265 --> 00:26:27,275\r\nwe've saved them on the stack.\r\n\r\n422\r\n00:26:27,275 --> 00:26:28,724\r\nThe reason we saved them on the stack is because\r\n\r\n423\r\n00:26:28,724 --> 00:26:33,550\r\neval-dispatch makes no promises about what registers it may destroy. \r\n\r\n424\r\n00:26:33,550 --> 00:26:35,020\r\nSo all that stuff is saved on the stack.\r\n\r\n425\r\n00:26:35,020 --> 00:26:37,380\r\nNow, we've set up eval-dispatch's contract.\r\n\r\n426\r\n00:26:37,380 --> 00:26:40,964\r\nThere's a new expression, which is the operator plus;\r\n\r\n427\r\n00:26:40,964 --> 00:26:44,250\r\na new environment, although, in this case, it's the same one;\r\n\r\n428\r\n00:26:44,250 --> 00:26:47,600\r\nand a new place to go to when you're done, which is eval-args. \r\n\r\n429\r\n00:26:47,600 --> 00:26:48,130\r\nSo that's set up.\r\n\r\n430\r\n00:26:48,130 --> 00:26:50,890\r\nNow, we're going to go off to eval-dispatch.\r\n\r\n431\r\n00:26:50,890 --> 00:26:53,090\r\nHere we are back at eval-dispatch.\r\n\r\n432\r\n00:26:53,090 --> 00:26:54,490\r\nIt's not self-evaluating.\r\n\r\n433\r\n00:26:54,490 --> 00:27:00,147\r\nOh, it's a variable, so we'd better go off to ev-variable, right? \r\n\r\n434\r\n00:27:00,147 --> 00:27:02,880\r\nEv-variable is assigned to VAL.\r\n\r\n435\r\n00:27:02,880 --> 00:27:08,770\r\nLook up the variable value of the expression, OK?\r\n\r\n436\r\n00:27:08,770 --> 00:27:13,000\r\nSo VAL is the primitive procedure plus, OK?\r\n\r\n437\r\n00:27:13,000 --> 00:27:15,020\r\nAnd go to fetch of continue.\r\n\r\n438\r\n00:27:15,020 --> 00:27:16,050\r\nPROFESSOR: Eval-args.\r\n\r\n439\r\n00:27:16,050 --> 00:27:19,340\r\nPROFESSOR: Right, which is now eval-args not done.\r\n\r\n440\r\n00:27:19,340 --> 00:27:23,071\r\nSo we come back here at eval-args, and what do we do?\r\n\r\n441\r\n00:27:23,071 --> 00:27:29,050\r\nWe're going to restore the stuff that we saved, so we restore UNEV.\r\n\r\n442\r\n00:27:29,050 --> 00:27:32,900\r\nAnd notice, there, it wasn't necessary, although, in general, it would be. \r\n\r\n443\r\n00:27:32,900 --> 00:27:35,430\r\nIt might be some arbitrary evaluation that happened.\r\n\r\n444\r\n00:27:35,430 --> 00:27:54,900\r\nWe restore ENV. OK, we assign to FUN fetch of VAL.\r\n\r\n445\r\n00:27:58,620 --> 00:28:04,340\r\nOK, now, we're going to go off and start evaluating some arguments. \r\n\r\n446\r\n00:28:04,340 --> 00:28:08,330\r\nWell, first thing we'd better do is save FUN because some\r\n\r\n447\r\n00:28:08,330 --> 00:28:13,675\r\narbitrary stuff might happen in that evaluation.\r\n\r\n448\r\n00:28:15,330 --> 00:28:20,750\r\nWe initialize the argument list. Assign to argl an empty argument list, \r\n\r\n449\r\n00:28:20,750 --> 00:28:25,460\r\nand go to eval-arg-loop, OK?\r\n\r\n450\r\n00:28:25,460 --> 00:28:29,580\r\nAt eval-arg-loop, the idea of this is we're going to\r\n\r\n451\r\n00:28:29,580 --> 00:28:33,540\r\nevaluate the pieces of the expressions that are in UNEV, one by one, \r\n\r\n452\r\n00:28:33,540 --> 00:28:35,688\r\nand move them from unevaluated in UNEV \r\n\r\n453\r\n00:28:35,688 --> 00:28:38,090\r\nto evaluated in the arg list, OK?\r\n\r\n454\r\n00:28:38,090 --> 00:28:42,400\r\nSo we save argl.\r\n\r\n455\r\n00:28:43,950 --> 00:28:49,145\r\nWe assign to x the first operand of the stuff in UNEV.\r\n\r\n456\r\n00:28:53,772 --> 00:28:55,890\r\nNow, we check and see if that was the last operand.\r\n\r\n457\r\n00:28:55,890 --> 00:28:59,190\r\nIn this case, it is not, all right?\r\n\r\n458\r\n00:28:59,190 --> 00:29:02,975\r\nSo we save the environment.\r\n\r\n459\r\n00:29:07,850 --> 00:29:13,500\r\nWe save UNEV because those are all things we might need later. \r\n\r\n460\r\n00:29:13,500 --> 00:29:15,800\r\nWe're going to need the environment to do some more evaluations. \r\n\r\n461\r\n00:29:15,800 --> 00:29:20,340\r\nWe're going to need UNEV to look at what the rest of those arguments were. \r\n\r\n462\r\n00:29:20,340 --> 00:29:26,053\r\nWe're going to assign continue a place called accumulate-args, or accumulate-arg. \r\n\r\n463\r\n00:29:30,898 --> 00:29:36,810\r\nOK, now, we've set up for another call to eval-dispatch, OK? \r\n\r\n464\r\n00:29:36,810 --> 00:29:39,125\r\nAll right, now, let me short-circuit this\r\n\r\n465\r\n00:29:39,125 --> 00:29:41,090\r\nso we don't go through the details of eval-dispatch.\r\n\r\n466\r\n00:29:41,090 --> 00:29:45,103\r\nEval-dispatch's contract says I'm going to end up,\r\n\r\n467\r\n00:29:45,103 --> 00:29:48,240\r\nthe world will end up, with the value of evaluating this expression\r\n\r\n468\r\n00:29:48,240 --> 00:29:50,270\r\nin this environment in the VAL register,\r\n\r\n469\r\n00:29:50,270 --> 00:29:51,320\r\nand I'll end up there.\r\n\r\n470\r\n00:29:51,320 --> 00:29:58,010\r\nSo we short-circuit all of this, and a 3 ends up in VAL.\r\n\r\n471\r\n00:29:58,010 --> 00:29:59,768\r\nAnd, when we return from eval-dispatch,\r\n\r\n472\r\n00:29:59,768 --> 00:30:02,110\r\nwe're going to return to accumulate-arg.\r\n\r\n473\r\n00:30:02,110 --> 00:30:03,555\r\nPROFESSOR: Accumulate-arg.\r\n\r\n474\r\n00:30:06,185 --> 00:30:08,720\r\nPROFESSOR: With 3 in the VAL register, OK?\r\n\r\n475\r\n00:30:08,720 --> 00:30:10,650\r\nSo that short-circuited that evaluation.\r\n\r\n476\r\n00:30:10,650 --> 00:30:11,320\r\nNow, what do we do?\r\n\r\n477\r\n00:30:11,320 --> 00:30:13,689\r\nWe're going to go back and look at the rest of the arguments,\r\n\r\n478\r\n00:30:13,689 --> 00:30:15,609\r\nso we restore UNEV. \r\n\r\n479\r\n00:30:17,513 --> 00:30:28,650\r\nWe restore ENV. We restore argl.\r\n\r\n480\r\n00:30:28,650 --> 00:30:29,170\r\nOne thing.\r\n\r\n481\r\n00:30:29,170 --> 00:30:30,536\r\nPROFESSOR: Oops!\r\n\r\n482\r\n00:30:30,536 --> 00:30:31,290\r\nParity error.\r\n\r\n483\r\n00:30:31,290 --> 00:30:33,465\r\n[LAUGHTER]\r\n\r\n484\r\n00:30:33,465 --> 00:30:34,905\r\nPROFESSOR: Restore argl.\r\n\r\n485\r\n00:30:41,650 --> 00:30:42,900\r\nPROFESSOR: OK.\r\n\r\n486\r\n00:30:45,570 --> 00:30:50,400\r\nOK, we assign to argl consing on \r\n\r\n487\r\n00:30:50,400 --> 00:30:53,130\r\nfetch of the value register to what's in argl.\r\n\r\n488\r\n00:30:58,985 --> 00:31:05,025\r\nOK, we assign to UNEV the rest of the operands in fetch of UNEV, \r\n\r\n489\r\n00:31:08,700 --> 00:31:11,516\r\nand we go back to eval-arg-loop.\r\n\r\n490\r\n00:31:11,516 --> 00:31:12,280\r\nPROFESSOR: Eval-arg-loop.\r\n\r\n491\r\n00:31:12,280 --> 00:31:13,530\r\nPROFESSOR: OK.\r\n\r\n492\r\n00:31:15,880 --> 00:31:17,375\r\nNow, we're about to do the next argument, \r\n\r\n493\r\n00:31:17,375 --> 00:31:19,800\r\nso the first thing we do is save argl.\r\n\r\n494\r\n00:31:25,400 --> 00:31:31,803\r\nOK, we assign to x the first operand of fetch of UNEV. \r\n\r\n495\r\n00:31:34,650 --> 00:31:38,925\r\nOK,we test and see if that's the last operand.In this case, it is\r\n\r\n496\r\n00:31:38,925 --> 00:31:43,173\r\nso we're going to go to a special place that says evaluate the last argument  \r\n\r\n497\r\n00:31:43,173 --> 00:31:44,965\r\nbecause, notice,after evaluating the argument, \r\n\r\n498\r\n00:31:44,965 --> 00:31:47,446\r\nwe don't need the environment any more.\r\n\r\n499\r\n00:31:47,446 --> 00:31:50,250\r\nThat's going to be the difference.\r\n\r\n500\r\n00:31:50,250 --> 00:31:52,054\r\nSo here, at eval-last-arg, \r\n\r\n501\r\n00:31:52,054 --> 00:31:55,382\r\nwhich is assigned to continue accumulate-last-arg, \r\n\r\n502\r\n00:32:04,275 --> 00:32:06,900\r\nnow, we're set up again for eval-dispatch.\r\n\r\n503\r\n00:32:06,900 --> 00:32:08,620\r\nWe've got a place to go to when we're done.\r\n\r\n504\r\n00:32:08,620 --> 00:32:09,840\r\nWe've got an expression.\r\n\r\n505\r\n00:32:09,840 --> 00:32:11,330\r\nWe've got an environment.\r\n\r\n506\r\n00:32:11,330 --> 00:32:14,370\r\nOK, so we'll short-circuit the call to eval-dispatch.\r\n\r\n507\r\n00:32:14,370 --> 00:32:16,700\r\nAnd what'll happen is there's a y there,\r\n\r\n508\r\n00:32:16,700 --> 00:32:21,060\r\nit's 4 in that environment, so VAL will end up with 4 in it.\r\n\r\n509\r\n00:32:21,060 --> 00:32:25,450\r\nAnd, then, we're going to end up at accumulate-last-arg, OK?\r\n\r\n510\r\n00:32:25,450 --> 00:32:30,525\r\nSo, at accumulate-last-arg, we restore argl.\r\n\r\n511\r\n00:32:41,490 --> 00:32:45,835\r\nWe assign to argl cons of fetch of the new value onto it, \r\n\r\n512\r\n00:32:45,835 --> 00:32:49,850\r\nso we cons a 4 onto that.\r\n\r\n513\r\n00:32:49,850 --> 00:32:53,446\r\nWe restore what was saved in the function register.\r\n\r\n514\r\n00:32:53,446 --> 00:32:56,277\r\nAnd notice, in this case, it had not been destroyed, \r\n\r\n515\r\n00:32:56,277 --> 00:32:59,132\r\nbut in general, it will be.\r\n\r\n516\r\n00:32:59,132 --> 00:33:02,850\r\nAnd now, we're ready to go off to apply-dispatch, all right?\r\n\r\n517\r\n00:33:02,850 --> 00:33:04,510\r\nSo we've just gone through the eval.\r\n\r\n518\r\n00:33:04,510 --> 00:33:07,980\r\nWe evaluated the argument, the operator, and the arguments,\r\n\r\n519\r\n00:33:07,980 --> 00:33:09,580\r\nand now, we're about to apply them.\r\n\r\n520\r\n00:33:09,580 --> 00:33:17,481\r\nSo we come off to apply-dispatch here, OK?\r\n\r\n521\r\n00:33:17,481 --> 00:33:20,575\r\nWe come off to apply-dispatch, \r\n\r\n522\r\n00:33:20,575 --> 00:33:23,450\r\nand we're going to check whether it's a primitive or a compound procedure.\r\n\r\n523\r\n00:33:23,450 --> 00:33:24,116\r\nPROFESSOR: Yes.\r\n\r\n524\r\n00:33:24,116 --> 00:33:24,830\r\nPROFESSOR: All right.\r\n\r\n525\r\n00:33:24,830 --> 00:33:27,375\r\nSo, in this case, it's a primitive procedure, \r\n\r\n526\r\n00:33:27,375 --> 00:33:29,790\r\nand we go off to primitive-apply.\r\n\r\n527\r\n00:33:29,790 --> 00:33:34,130\r\nSo we go off to primitive-apply, and it says\r\n\r\n528\r\n00:33:34,130 --> 00:33:38,360\r\nassign to VAL the result of applying primitive procedure\r\n\r\n529\r\n00:33:38,360 --> 00:33:40,940\r\nof the function to the argument list.\r\n\r\n530\r\n00:33:40,940 --> 00:33:42,540\r\nPROFESSOR: I don't know how to add.\r\n\r\n531\r\n00:33:42,540 --> 00:33:43,995\r\nI'm just an execution unit.\r\n\r\n532\r\n00:33:43,995 --> 00:33:45,350\r\nPROFESSOR: Well, I don't know how to add either.\r\n\r\n533\r\n00:33:45,350 --> 00:33:48,360\r\nI'm just the evaluator, so we need a primitive operator.\r\n\r\n534\r\n00:33:48,360 --> 00:33:50,925\r\nLet's see, so the primitive operator, what's the\r\n\r\n535\r\n00:33:50,925 --> 00:33:52,605\r\nWhat's the sum of 3 and 4?\r\n\r\n536\r\n00:33:52,605 --> 00:33:53,205\r\nAUDIENCE: 7.\r\n\r\n537\r\n00:33:53,205 --> 00:33:55,050\r\nPROFESSOR: OK, 7.\r\n\r\n538\r\n00:33:55,050 --> 00:33:55,999\r\nPROFESSOR: Thank you.\r\n\r\n539\r\n00:33:58,837 --> 00:34:00,850\r\nPROFESSOR: Now, we restore continue, \r\n\r\n540\r\n00:34:11,275 --> 00:34:12,900\r\nand we go to fetch of continue.\r\n\r\n541\r\n00:34:12,900 --> 00:34:13,880\r\nPROFESSOR: Done.\r\n\r\n542\r\n00:34:13,880 --> 00:34:14,929\r\nPROFESSOR: OK.\r\n\r\n543\r\n00:34:14,929 --> 00:34:18,413\r\nWell, that was in as much detail as you will ever see.\r\n\r\n544\r\n00:34:18,413 --> 00:34:21,590\r\nWe'll never do it in as much detail again.\r\n\r\n545\r\n00:34:21,590 --> 00:34:25,233\r\nOne very important thing to notice is that \r\n\r\n546\r\n00:34:25,233 --> 00:34:29,780\r\nwe just executed a recursive procedure, right?\r\n\r\n547\r\n00:34:29,780 --> 00:34:31,172\r\nThis whole thing, we used a stack \r\n\r\n548\r\n00:34:31,172 --> 00:34:33,070\r\nand the evaluator was recursive.\r\n\r\n549\r\n00:34:33,070 --> 00:34:36,480\r\nA lot of people think the reason that you need a stack\r\n\r\n550\r\n00:34:36,480 --> 00:34:39,090\r\nand recursion in an evaluator is because you might be\r\n\r\n551\r\n00:34:39,090 --> 00:34:42,150\r\nevaluating recursive procedures like factorial or Fibonacci. \r\n\r\n552\r\n00:34:42,150 --> 00:34:43,670\r\nIt's not true.\r\n\r\n553\r\n00:34:43,670 --> 00:34:46,110\r\nSo you notice we did recursion here, and all we evaluated was\r\n\r\n554\r\n00:34:46,110 --> 00:34:48,010\r\nplus X, Y, all right?\r\n\r\n555\r\n00:34:48,010 --> 00:34:51,219\r\nThe reason that you need recursion in the evaluator is\r\n\r\n556\r\n00:34:51,219 --> 00:34:54,450\r\nbecause the evaluation process, itself, is recursive, all right? \r\n\r\n557\r\n00:34:54,450 --> 00:34:57,760\r\nIt's not because the procedure that you might be evaluating in LISP \r\n\r\n558\r\n00:34:57,760 --> 00:34:59,270\r\nis a recursive procedure.\r\n\r\n559\r\n00:34:59,270 --> 00:35:00,411\r\nSo that's an important thing \r\n\r\n560\r\n00:35:00,411 --> 00:35:03,010\r\nthat people get confused about a lot.\r\n\r\n561\r\n00:35:03,010 --> 00:35:06,280\r\nThe other thing to notice is that, when we're done here,\r\n\r\n562\r\n00:35:06,280 --> 00:35:07,120\r\nwe're really done.\r\n\r\n563\r\n00:35:07,120 --> 00:35:10,878\r\nNot only are we at done, but \r\n\r\n564\r\n00:35:10,878 --> 00:35:13,810\r\nthere's no accumulated stuff on the stack, right?\r\n\r\n565\r\n00:35:13,810 --> 00:35:17,170\r\nThe machine is back to its initial state, all right?\r\n\r\n566\r\n00:35:17,170 --> 00:35:19,715\r\nSo that's part of what it means to be done.\r\n\r\n567\r\n00:35:19,715 --> 00:35:26,410\r\nAnother way to say that is the evaluation process has reduced\r\n\r\n568\r\n00:35:26,410 --> 00:35:33,245\r\nthe expression, plus X, Y, to the value here, 7.\r\n\r\n569\r\n00:35:33,245 --> 00:35:36,010\r\nAnd by reduced, I mean a very particular thing.\r\n\r\n570\r\n00:35:36,010 --> 00:35:38,180\r\nIt means that there's nothing left on the stack.\r\n\r\n571\r\n00:35:38,180 --> 00:35:40,743\r\nThe machine is now in the same state, \r\n\r\n572\r\n00:35:40,743 --> 00:35:42,723\r\nexcept there's something in the value register.\r\n\r\n573\r\n00:35:42,723 --> 00:35:44,520\r\nIt's not part of a sub-problem of anything.\r\n\r\n574\r\n00:35:44,520 --> 00:35:46,210\r\nThere's nothing to go back to.\r\n\r\n575\r\n00:35:46,210 --> 00:35:46,440\r\nOK.\r\n\r\n576\r\n00:35:46,440 --> 00:35:47,690\r\nLet's break.\r\n\r\n577\r\n00:35:49,712 --> 00:35:50,159\r\nQuestion?\r\n\r\n578\r\n00:35:50,159 --> 00:35:54,027\r\nAUDIENCE: The question here, in the stack,\r\n\r\n579\r\n00:35:54,027 --> 00:35:55,820\r\nis because the data may be recursive.\r\n\r\n580\r\n00:35:55,820 --> 00:35:59,312\r\nYou may have embedded expressions, for instance.\r\n\r\n581\r\n00:35:59,312 --> 00:36:02,080\r\nPROFESSOR: Yes, because you might have embedded expressions. \r\n\r\n582\r\n00:36:02,080 --> 00:36:04,774\r\nBut, again, don't confuse that \r\n\r\n583\r\n00:36:04,774 --> 00:36:07,718\r\nwith what people sometimes mean by the data may be recursive, \r\n\r\n584\r\n00:36:07,718 --> 00:36:12,930\r\nwhich is to say you have these list-structured, recursive data list operations. \r\n\r\n585\r\n00:36:12,930 --> 00:36:13,804\r\nThat has nothing to do with it.\r\n\r\n586\r\n00:36:13,804 --> 00:36:17,363\r\nIt's simply that the expressions contain sub-expressions. \r\n\r\n587\r\n00:36:17,363 --> 00:36:19,618\r\nYeah?\r\n\r\n588\r\n00:36:19,618 --> 00:36:23,457\r\nAUDIENCE: Why is it that the order of the arguments in the arg list got reversed? \r\n\r\n589\r\n00:36:23,457 --> 00:36:27,260\r\nPROFESSOR: Ah! Yes, I should've mentioned that. \r\n\r\n590\r\n00:36:27,260 --> 00:36:29,075\r\nHere, the reason the order is reversed--\r\n\r\n591\r\n00:36:32,507 --> 00:36:36,050\r\nit's a question of what you mean by reversed.\r\n\r\n592\r\n00:36:36,050 --> 00:36:40,624\r\nI believe it was Newton.\r\n\r\n593\r\n00:36:40,624 --> 00:36:43,800\r\nIn the very early part of optics, people realized that,\r\n\r\n594\r\n00:36:43,800 --> 00:36:45,500\r\nwhen you look through the lens of your eye, \r\n\r\n595\r\n00:36:45,500 --> 00:36:46,730\r\nthe image was up-side down.\r\n\r\n596\r\n00:36:46,730 --> 00:36:48,044\r\nAnd there was a lot of argument about\r\n\r\n597\r\n00:36:48,044 --> 00:36:51,280\r\nwhy that didn't mean you saw things up-side down.\r\n\r\n598\r\n00:36:51,280 --> 00:36:52,860\r\nSo it's sort of the same issue.\r\n\r\n599\r\n00:36:52,860 --> 00:36:54,810\r\nReversed from what?\r\n\r\n600\r\n00:36:54,810 --> 00:36:57,940\r\nSo we just need some convention.\r\n\r\n601\r\n00:36:57,940 --> 00:37:01,730\r\nThe reason that they're coming at 4, 3 is because we're\r\n\r\n602\r\n00:37:01,730 --> 00:37:04,520\r\ntaking UNEV and consing the result onto argl.\r\n\r\n603\r\n00:37:04,520 --> 00:37:06,771\r\nSo you have to realize you've made that convention.\r\n\r\n604\r\n00:37:06,771 --> 00:37:09,987\r\nThe place that you have to realize that--\r\n\r\n605\r\n00:37:09,987 --> 00:37:11,230\r\nwell, there's actually two places.\r\n\r\n606\r\n00:37:11,230 --> 00:37:12,910\r\nOne is in apply-primitive-operator,\r\n\r\n607\r\n00:37:12,910 --> 00:37:16,610\r\nwhich has to realize that the arguments to primitives go in,\r\n\r\n608\r\n00:37:16,610 --> 00:37:19,490\r\nin the opposite order from the way you're writing them down.\r\n\r\n609\r\n00:37:19,490 --> 00:37:21,008\r\nAnd the other one is, we'll see later \r\n\r\n610\r\n00:37:21,008 --> 00:37:24,016\r\nwhen you actually go to bind a function's parameters, \r\n\r\n611\r\n00:37:24,016 --> 00:37:25,745\r\nyou should realize the arguments are going to come in \r\n\r\n612\r\n00:37:25,745 --> 00:37:28,870\r\nfrom the opposite order of the variables to which you're binding them.\r\n\r\n613\r\n00:37:28,870 --> 00:37:31,830\r\nSo, if you just keep track of that, there's no problem.\r\n\r\n614\r\n00:37:31,830 --> 00:37:33,900\r\nAlso, this is completely arbitrary \r\n\r\n615\r\n00:37:33,900 --> 00:37:37,420\r\nbecause, if we'd done, say, an iteration through a vector assigning them, \r\n\r\n616\r\n00:37:37,420 --> 00:37:40,730\r\nthey might come out in the other order, OK?\r\n\r\n617\r\n00:37:40,730 --> 00:37:45,085\r\nSo it's just a convention of the way this particular evaluator works. \r\n\r\n618\r\n00:37:45,085 --> 00:37:46,335\r\nAll right, let's take a break.\r\n\r\n619\r\n00:38:41,840 --> 00:38:45,609\r\nWe just saw evaluating an expression and, \r\n\r\n620\r\n00:38:45,609 --> 00:38:46,950\r\nof course, that was very simple one.\r\n\r\n621\r\n00:38:46,950 --> 00:38:50,247\r\nBut, in essence, it would be no different\r\n\r\n622\r\n00:38:50,247 --> 00:38:52,039\r\nif it was some big nested expression, \r\n\r\n623\r\n00:38:52,039 --> 00:38:55,130\r\nso there would just be deeper recursion on the stack.\r\n\r\n624\r\n00:38:55,130 --> 00:38:56,470\r\nBut what I want to do now is show you the last piece.\r\n\r\n625\r\n00:38:56,470 --> 00:39:01,013\r\nI want to walk you around this eval and apply loop, right?\r\n\r\n626\r\n00:39:01,013 --> 00:39:03,000\r\nThat's the thing we haven't seen, really.\r\n\r\n627\r\n00:39:03,000 --> 00:39:05,200\r\nWe haven't seen any compound procedures\r\n\r\n628\r\n00:39:05,200 --> 00:39:07,925\r\nwhere evalutation of procedure reduces to \r\n\r\n629\r\n00:39:07,925 --> 00:39:12,250\r\nwhere applying of procedure reduces to evaluating the body of the procedure, \r\n\r\n630\r\n00:39:12,250 --> 00:39:15,810\r\nso let's just suppose we had this.\r\n\r\n631\r\n00:39:15,810 --> 00:39:18,075\r\nSuppose we were looking at the procedure \r\n\r\n632\r\n00:39:18,075 --> 00:39:33,995\r\ndefine F of A and B to be the sum of A and B. \r\n\r\n633\r\n00:39:33,995 --> 00:39:37,325\r\nSo, as we typed in that procedure previously,\r\n\r\n634\r\n00:39:37,325 --> 00:39:42,275\r\nand now we're going to evaluate F of X and Y\r\n\r\n635\r\n00:39:42,275 --> 00:39:44,209\r\nagain, in this environment, E,0,\r\n\r\n636\r\n00:39:44,209 --> 00:39:47,280\r\nwhere X is bound to 3 and Y is bound to 4.\r\n\r\n637\r\n00:39:50,650 --> 00:39:53,825\r\nWhen the defined is executed, remember, there's a lambda here,\r\n\r\n638\r\n00:39:53,825 --> 00:39:55,950\r\nand lambdas create procedures.\r\n\r\n639\r\n00:39:55,950 --> 00:40:00,815\r\nAnd, basically, what will happen is, in E,0, \r\n\r\n640\r\n00:40:00,815 --> 00:40:03,563\r\nwe'll end up with a binding for F,\r\n\r\n641\r\n00:40:03,563 --> 00:40:07,151\r\nwhich will say F is a procedure,\r\n\r\n642\r\n00:40:07,151 --> 00:40:16,495\r\nand its args are A and B, and its body is plus a,b.\r\n\r\n643\r\n00:40:17,843 --> 00:40:21,053\r\nSo that's what the environment would have looked like \r\n\r\n644\r\n00:40:21,053 --> 00:40:22,675\r\nhad we made that definition.\r\n\r\n645\r\n00:40:24,225 --> 00:40:28,600\r\nThen, when we go to evaluate F of X and Y, \r\n\r\n646\r\n00:40:28,600 --> 00:40:31,615\r\nwe'll go through exactly the same process that we did before.\r\n\r\n647\r\n00:40:31,615 --> 00:40:33,096\r\nIt's even the same expression.\r\n\r\n648\r\n00:40:33,096 --> 00:40:36,030\r\nThe only difference is that F, instead of having primitive\r\n\r\n649\r\n00:40:36,030 --> 00:40:39,250\r\n\"plus\" in it, will have this thing.\r\n\r\n650\r\n00:40:41,040 --> 00:40:43,600\r\nAnd so we'll go through exactly the same process,\r\n\r\n651\r\n00:40:43,600 --> 00:40:47,864\r\nexcept this time, when we end up at apply-dispatch, \r\n\r\n652\r\n00:40:47,864 --> 00:40:50,285\r\nthe function register, instead of having primitive plus, \r\n\r\n653\r\n00:40:50,285 --> 00:40:54,300\r\nwill have a thing that will represent it saying procedure,\r\n\r\n654\r\n00:40:54,300 --> 00:41:06,275\r\nwhere the args are A and B, and the body is plus A, B.\r\n\r\n655\r\n00:41:07,875 --> 00:41:11,092\r\nAnd, again, what I mean, by its ENV, I mean there's a pointer to it,\r\n\r\n656\r\n00:41:11,092 --> 00:41:13,280\r\nso don't worry that I'm writing a lot of stuff there. \r\n\r\n657\r\n00:41:13,280 --> 00:41:15,636\r\nThere's a pointer to this procedure data structure.\r\n\r\n658\r\n00:41:17,170 --> 00:41:20,960\r\nOK, so, we're in exactly the same situation.\r\n\r\n659\r\n00:41:20,960 --> 00:41:26,480\r\nWe get to apply-dispatch, so, here, we come to apply-dispatch. \r\n\r\n660\r\n00:41:26,480 --> 00:41:30,010\r\nLast time, we branched off to a primitive procedure.\r\n\r\n661\r\n00:41:30,010 --> 00:41:34,550\r\nHere, it says oh, we now have a compound procedure, \r\n\r\n662\r\n00:41:34,550 --> 00:41:36,911\r\nso we're going to go off to compound-apply.\r\n\r\n663\r\n00:41:38,475 --> 00:41:40,075\r\nNow, what's compound-apply?\r\n\r\n664\r\n00:41:41,925 --> 00:41:45,090\r\nWell, remember what the meta-circular evaluator did?\r\n\r\n665\r\n00:41:45,090 --> 00:41:49,903\r\nCompound-apply said we're going to evaluate\r\n\r\n666\r\n00:41:49,903 --> 00:41:54,120\r\nthe body of the procedure in some new environment.\r\n\r\n667\r\n00:41:54,120 --> 00:41:56,730\r\nWhere does that new environment come from?\r\n\r\n668\r\n00:41:56,730 --> 00:42:01,362\r\nWe take the environment that was packaged with the procedure, \r\n\r\n669\r\n00:42:03,029 --> 00:42:05,791\r\nwe bind the parameters of the procedure \r\n\r\n670\r\n00:42:05,791 --> 00:42:09,759\r\nto the arguments that we're passing in,\r\n\r\n671\r\n00:42:09,759 --> 00:42:14,990\r\nand use that as a new frame to extend the procedure environment.\r\n\r\n672\r\n00:42:14,990 --> 00:42:21,630\r\nAnd that's the environment in which we evaluate the procedure body, right? \r\n\r\n673\r\n00:42:21,630 --> 00:42:24,470\r\nThat's going around the apply/eval loop.\r\n\r\n674\r\n00:42:24,470 --> 00:42:27,988\r\nThat's apply coming back to call eval, all right?\r\n\r\n675\r\n00:42:30,910 --> 00:42:32,860\r\nOK.\r\n\r\n676\r\n00:42:32,860 --> 00:42:36,787\r\nSo, now, that's all we have to do in compound-apply.\r\n\r\n677\r\n00:42:36,787 --> 00:42:37,720\r\nWhat are we going to do?\r\n\r\n678\r\n00:42:37,720 --> 00:42:40,975\r\nWe're going to manufacture a new environment.\r\n\r\n679\r\n00:42:43,550 --> 00:42:46,768\r\nAnd we're going to manufacture a new environment that,\r\n\r\n680\r\n00:42:46,768 --> 00:42:48,310\r\nlet's see, that we'll call E,1.\r\n\r\n681\r\n00:42:52,900 --> 00:42:57,310\r\nE,1 is going to be some environment where the\r\n\r\n682\r\n00:42:57,310 --> 00:43:01,765\r\nwhere the parameters of the procedure, where A is bound to 3\r\n\r\n683\r\n00:43:01,765 --> 00:43:05,768\r\nand B is bound to 4, and it's linked to E,0 \r\n\r\n684\r\n00:43:05,768 --> 00:43:09,270\r\nbecause that's where f is defined.\r\n\r\n685\r\n00:43:09,270 --> 00:43:12,050\r\nAnd, in this environment, we're going to evaluate the body of the procedure. \r\n\r\n686\r\n00:43:12,050 --> 00:43:13,870\r\nSo let's look at that, all right?\r\n\r\n687\r\n00:43:16,525 --> 00:43:20,690\r\nAll right, here we are at compound-apply, which says\r\n\r\n688\r\n00:43:20,690 --> 00:43:24,500\r\nassign to the expression register\r\n\r\n689\r\n00:43:24,500 --> 00:43:28,163\r\nthe body of the procedure that's in the function register.\r\n\r\n690\r\n00:43:28,163 --> 00:43:42,450\r\nSo I assign to the expression register the procedure body, OK? \r\n\r\n691\r\n00:43:42,450 --> 00:43:45,825\r\nThat's going to be evaluated in an environment\r\n\r\n692\r\n00:43:45,825 --> 00:43:51,300\r\nwhich is formed by making some bindings\r\n\r\n693\r\n00:43:51,300 --> 00:43:53,673\r\nusing information determined by the procedure--\r\n\r\n694\r\n00:43:53,673 --> 00:43:55,320\r\nthat's what's in FUN--\r\n\r\n695\r\n00:43:55,320 --> 00:43:57,800\r\nand the argument list.\r\n\r\n696\r\n00:43:57,800 --> 00:44:00,230\r\nAnd let's not worry about exactly what that does, \r\n\r\n697\r\n00:44:00,230 --> 00:44:01,930\r\nbut you can see the information's there.\r\n\r\n698\r\n00:44:01,930 --> 00:44:05,948\r\nSo make bindings will say oh, the procedure, itself,\r\n\r\n699\r\n00:44:05,948 --> 00:44:07,950\r\nhad an environment attached to it.\r\n\r\n700\r\n00:44:07,950 --> 00:44:09,320\r\nI didn't write that quite here.\r\n\r\n701\r\n00:44:09,320 --> 00:44:11,300\r\nI should've said in environment\r\n\r\n702\r\n00:44:11,300 --> 00:44:13,660\r\nbecause every procedure gets built with an environment.\r\n\r\n703\r\n00:44:13,660 --> 00:44:16,600\r\nSo, from that environment, it knows \r\n\r\n704\r\n00:44:16,600 --> 00:44:19,290\r\nwhat the procedure's definition environment is.\r\n\r\n705\r\n00:44:19,290 --> 00:44:21,830\r\nIt knows what the arguments are.\r\n\r\n706\r\n00:44:21,830 --> 00:44:24,280\r\nIt looks at argl, and then you see a reversal convention here. \r\n\r\n707\r\n00:44:24,280 --> 00:44:27,062\r\nIt just has to know that argl is reversed,\r\n\r\n708\r\n00:44:27,062 --> 00:44:29,990\r\nand it builds this frame, E,1.\r\n\r\n709\r\n00:44:29,990 --> 00:44:33,364\r\nAll right, so, let's assume that that's what make bindings returns,\r\n\r\n710\r\n00:44:33,364 --> 00:44:36,225\r\nso it assigns to ENV this thing, E,1.\r\n\r\n711\r\n00:44:41,490 --> 00:44:46,890\r\nAll right, the next thing it says is restore continue.\r\n\r\n712\r\n00:44:46,890 --> 00:44:48,760\r\nRemember what continue was here?\r\n\r\n713\r\n00:44:48,760 --> 00:44:52,240\r\nIt got put up in the last segment.\r\n\r\n714\r\n00:44:52,240 --> 00:44:54,020\r\nContinue got stored.\r\n\r\n715\r\n00:44:54,020 --> 00:44:56,565\r\nThat was the original done, which said what are you going to do \r\n\r\n716\r\n00:44:56,565 --> 00:44:59,920\r\nafter you're done with this particular application?\r\n\r\n717\r\n00:44:59,920 --> 00:45:01,560\r\nIt was one of the very first things that happened\r\n\r\n718\r\n00:45:01,560 --> 00:45:03,920\r\nwhen we evaluated the application.\r\n\r\n719\r\n00:45:03,920 --> 00:45:06,860\r\nAnd now, finally, we're going to restore continue.\r\n\r\n720\r\n00:45:06,860 --> 00:45:09,290\r\nRemember apply-dispatch's contract.\r\n\r\n721\r\n00:45:09,290 --> 00:45:12,035\r\nIt assumes that where it should go to next was on the stack,\r\n\r\n722\r\n00:45:12,035 --> 00:45:13,590\r\nand there it was on the stack.\r\n\r\n723\r\n00:45:13,590 --> 00:45:19,940\r\nContinue has done, and now we're going to go back to eval-dispatch. \r\n\r\n724\r\n00:45:19,940 --> 00:45:20,970\r\nWe're set up again.\r\n\r\n725\r\n00:45:20,970 --> 00:45:25,511\r\nWe have an expression, an environment, and a place to go to. \r\n\r\n726\r\n00:45:25,511 --> 00:45:29,940\r\nWe're not going to go through that because it's sort of the same expression. \r\n\r\n727\r\n00:45:35,167 --> 00:45:39,342\r\nOK, but the thing, again, to notice is, at this point, \r\n\r\n728\r\n00:45:39,342 --> 00:45:44,830\r\nwe have reduced the original expression, F,X,Y, right?\r\n\r\n729\r\n00:45:44,830 --> 00:45:48,755\r\nWe've reduced evaluating F,X,Y in environment E,0 \r\n\r\n730\r\n00:45:48,755 --> 00:45:52,670\r\nto evaluate plus A, B in E,1.\r\n\r\n731\r\n00:45:52,670 --> 00:45:55,720\r\nAnd notice, nothing's on the stack, right?\r\n\r\n732\r\n00:45:55,720 --> 00:45:56,830\r\nIt's a reduction.\r\n\r\n733\r\n00:45:56,830 --> 00:46:01,769\r\nAt this point, the machine does not contain, as part of its state, \r\n\r\n734\r\n00:46:01,769 --> 00:46:05,493\r\nthe fact that it's in the middle of evaluating some procedure called f,\r\n\r\n735\r\n00:46:05,493 --> 00:46:07,669\r\nthat's gone, right?\r\n\r\n736\r\n00:46:07,669 --> 00:46:13,072\r\nThere's no accumulated state, OK?\r\n\r\n737\r\n00:46:13,072 --> 00:46:14,370\r\nAgain, that's a very important idea.\r\n\r\n738\r\n00:46:14,370 --> 00:46:18,396\r\nThat's the meaning of, when we used to write in the substitution model,\r\n\r\n739\r\n00:46:18,396 --> 00:46:21,350\r\nthis expression reduces to that expression. \r\n\r\n740\r\n00:46:21,350 --> 00:46:22,660\r\nAnd you don't have to remember anything.\r\n\r\n741\r\n00:46:22,660 --> 00:46:24,500\r\nAnd here, you see the meaning of reduction.\r\n\r\n742\r\n00:46:24,500 --> 00:46:26,160\r\nAt this point, there is nothing on the stack.\r\n\r\n743\r\n00:46:31,590 --> 00:46:35,240\r\nSee, that has very important consequences.\r\n\r\n744\r\n00:46:35,240 --> 00:46:38,325\r\nLet's go back and look at iterative factorial,\r\n\r\n745\r\n00:46:40,425 --> 00:46:45,130\r\nall right? Remember, this was some sort of loop and doing iter.\r\n\r\n746\r\n00:46:45,130 --> 00:46:49,430\r\nAnd we kept saying that's an iterative procedure, right?\r\n\r\n747\r\n00:46:49,430 --> 00:47:04,660\r\nAnd what we wrote, remember, are things like, we said,\r\n\r\n748\r\n00:47:04,660 --> 00:47:12,360\r\nfact-iter of 5.\r\n\r\n749\r\n00:47:12,360 --> 00:47:19,030\r\nWe wrote things like reduces to iter of 1, and 1, and 5,\r\n\r\n750\r\n00:47:19,030 --> 00:47:25,324\r\nwhich reduces to iter of 1, and 2, and 5, \r\n\r\n751\r\n00:47:25,324 --> 00:47:27,079\r\nand so on, and so on, and so on.\r\n\r\n752\r\n00:47:27,079 --> 00:47:28,175\r\nAnd we kept saying well, look,\r\n\r\n753\r\n00:47:28,175 --> 00:47:31,720\r\nyou don't have to build up any storage to do that.\r\n\r\n754\r\n00:47:31,720 --> 00:47:35,040\r\nAnd we waved our hands, and said in principle, there's no storage needed. \r\n\r\n755\r\n00:47:35,040 --> 00:47:36,170\r\nNow, you see no storage needed.\r\n\r\n756\r\n00:47:36,170 --> 00:47:39,090\r\nEach of these is a real reduction, right?\r\n\r\n757\r\n00:47:39,090 --> 00:47:42,825\r\nAs you walk through these expressions,\r\n\r\n758\r\n00:47:47,300 --> 00:47:51,370\r\nAs you walk through these expressions, what you'll see\r\n\r\n759\r\n00:47:51,370 --> 00:47:53,751\r\nare these expressions on the stack \r\n\r\n760\r\n00:47:53,751 --> 00:47:56,425\r\nin some particular environment, \r\n\r\n761\r\n00:47:56,425 --> 00:48:00,023\r\nand then these expressions in the EXP register \r\n\r\n762\r\n00:48:00,023 --> 00:48:01,575\r\nin some particular environment. \r\n\r\n763\r\n00:48:01,575 --> 00:48:04,365\r\nAnd, at each point, there'll be no accumulated stuff on the stack \r\n\r\n764\r\n00:48:04,365 --> 00:48:06,100\r\nbecause each one's a real reduction, OK?\r\n\r\n765\r\n00:48:09,135 --> 00:48:10,581\r\nAll right, so, for example, \r\n\r\n766\r\n00:48:10,581 --> 00:48:13,460\r\njust to go through it in a little bit more care,\r\n\r\n767\r\n00:48:13,460 --> 00:48:17,108\r\nif I start out with an expression that says something like, \r\n\r\n768\r\n00:48:17,825 --> 00:48:34,400\r\noh, say, fact-iter of 5 in some environment\r\n\r\n769\r\n00:48:41,900 --> 00:48:46,810\r\nthat will, at some point, create an environment\r\n\r\n770\r\n00:48:46,810 --> 00:48:48,549\r\nin which n is down to 5.\r\n\r\n771\r\n00:48:51,340 --> 00:48:52,590\r\nLet's call that--\r\n\r\n772\r\n00:48:55,750 --> 00:49:02,757\r\nAnd, at some point, the machine will reduce this whole thing \r\n\r\n773\r\n00:49:02,757 --> 00:49:07,673\r\nto a thing that says that's really iter \r\n\r\n774\r\n00:49:07,673 --> 00:49:15,875\r\nof 1, and 1, and n, evaluated in this environment, E,1\r\n\r\n775\r\n00:49:15,875 --> 00:49:17,160\r\nwith nothing on the stack.\r\n\r\n776\r\n00:49:17,160 --> 00:49:20,710\r\nSee, at this moment, the machine is not remembering\r\n\r\n777\r\n00:49:20,710 --> 00:49:22,500\r\nthat evaluating this expression, iter--\r\n\r\n778\r\n00:49:25,000 --> 00:49:29,366\r\nwhich is the loop-- is part of this thing called iterative factorial. \r\n\r\n779\r\n00:49:29,366 --> 00:49:30,590\r\nIt's not remembering that.\r\n\r\n780\r\n00:49:30,590 --> 00:49:33,170\r\nIt's just reducing the expression to that, right?\r\n\r\n781\r\n00:49:33,170 --> 00:49:38,050\r\nIf we look again at the body of iterative factorial,\r\n\r\n782\r\n00:49:38,050 --> 00:49:42,810\r\nthis expression has reduced to that expression.\r\n\r\n783\r\n00:49:42,810 --> 00:49:44,060\r\nOh, I shouldn't have the n there.\r\n\r\n784\r\n00:49:46,590 --> 00:49:53,340\r\nIt's a slightly different convention from the slide to the program, OK? \r\n\r\n785\r\n00:49:53,340 --> 00:49:56,124\r\nAnd, then, what's the body of iter?\r\n\r\n786\r\n00:49:56,124 --> 00:49:58,625\r\nWell, iter's going to be an if, \r\n\r\n787\r\n00:49:58,625 --> 00:50:00,060\r\nand I won't go through the details of if. \r\n\r\n788\r\n00:50:00,060 --> 00:50:02,225\r\nIt'll evaluate the predicate.\r\n\r\n789\r\n00:50:02,225 --> 00:50:03,810\r\nIn this case, it'll be false.\r\n\r\n790\r\n00:50:03,810 --> 00:50:09,850\r\nAnd this iter will now reduce to the expression\r\n\r\n791\r\n00:50:09,850 --> 00:50:21,620\r\niter of whatever it says, star, counter product, and--\r\n\r\n792\r\n00:50:21,620 --> 00:50:22,650\r\nwhat does it say--\r\n\r\n793\r\n00:50:22,650 --> 00:50:32,975\r\nplus counter 1 in some other environment, by this time, E,2, \r\n\r\n794\r\n00:50:32,975 --> 00:50:43,200\r\nwhere E,2 will be set up having bindings for product and counter, right? \r\n\r\n795\r\n00:50:43,200 --> 00:50:45,140\r\nAnd it'll reduce to that, right?\r\n\r\n796\r\n00:50:45,140 --> 00:50:47,156\r\nIt won't be remembering that it's part of \r\n\r\n797\r\n00:50:47,156 --> 00:50:49,340\r\nsomething that it has to return to.\r\n\r\n798\r\n00:50:49,340 --> 00:50:53,053\r\nAnd when iter calls iter again, it'll reduce to another thing that looks like this\r\n\r\n799\r\n00:50:53,053 --> 00:50:59,160\r\nin some environment, E,3, which has new bindings for product and counter. \r\n\r\n800\r\n00:50:59,160 --> 00:51:08,450\r\nSo, if you're wondering, see, if you've always been queasy\r\n\r\n801\r\n00:51:08,450 --> 00:51:10,678\r\nabout how it is we've been saying those procedures\r\n\r\n802\r\n00:51:10,678 --> 00:51:12,458\r\nthat look syntactically recursive, \r\n\r\n803\r\n00:51:12,458 --> 00:51:18,100\r\nare, in fact, iterative, run in constant space,\r\n\r\n804\r\n00:51:18,100 --> 00:51:19,750\r\nwell, I don't know if this makes you less queasy, \r\n\r\n805\r\n00:51:19,750 --> 00:51:21,230\r\nbut at least it shows you what's happening.\r\n\r\n806\r\n00:51:21,230 --> 00:51:22,830\r\nThere really isn't any buildup there.\r\n\r\n807\r\n00:51:25,910 --> 00:51:27,984\r\nNow, you might ask well, is there buildup\r\n\r\n808\r\n00:51:27,984 --> 00:51:31,710\r\nin principle in these environment frames?\r\n\r\n809\r\n00:51:31,710 --> 00:51:32,375\r\nAnd the answer is yeah,\r\n\r\n810\r\n00:51:32,375 --> 00:51:32,443\r\nyou have to make these new environment frames, \r\n\r\n811\r\n00:51:32,443 --> 00:51:33,848\r\nyou have to make these new environment frames, \r\n\r\n812\r\n00:51:33,848 --> 00:51:36,440\r\nbut you don't have to hang onto them when you're done. \r\n\r\n813\r\n00:51:36,440 --> 00:51:40,720\r\nThey can be garbage collected, or the space can be reused automatically. \r\n\r\n814\r\n00:51:40,720 --> 00:51:43,250\r\nBut you see the control structure of the evaluator\r\n\r\n815\r\n00:51:43,250 --> 00:51:47,020\r\nis really using this idea that you actually have a reduction,\r\n\r\n816\r\n00:51:47,020 --> 00:51:50,132\r\nso these procedures really are iterative procedures.\r\n\r\n817\r\n00:51:50,132 --> 00:51:51,382\r\nAll right, let's stop for questions.\r\n\r\n818\r\n00:52:02,288 --> 00:52:03,538\r\nAll right, let's break.\r\n\r\n819\r\n00:52:48,770 --> 00:52:52,775\r\nLet me contrast the iterative procedure\r\n\r\n820\r\n00:52:52,775 --> 00:52:56,000\r\njust so you'll see where space does build up with a recursive procedure, \r\n\r\n821\r\n00:52:56,000 --> 00:52:58,030\r\nso you can see the difference.\r\n\r\n822\r\n00:52:58,030 --> 00:53:02,880\r\nLet's look at the evaluation of recursive factorial, all right? \r\n\r\n823\r\n00:53:02,880 --> 00:53:07,220\r\nSo, here's fact-recursive, or standard factorial definition.\r\n\r\n824\r\n00:53:07,220 --> 00:53:09,910\r\nWe said this one is still a recursive procedure, \r\n\r\n825\r\n00:53:09,910 --> 00:53:13,750\r\nbut this is actually a recursive process.\r\n\r\n826\r\n00:53:13,750 --> 00:53:16,566\r\nAnd then, just to link it back to the way we started, \r\n\r\n827\r\n00:53:16,566 --> 00:53:20,530\r\nwe said oh, you can see that it's going to be recursive process\r\n\r\n828\r\n00:53:20,530 --> 00:53:22,122\r\nby the substitution model \r\n\r\n829\r\n00:53:22,122 --> 00:53:30,450\r\nbecause, if I say recursive factorial of 5, \r\n\r\n830\r\n00:53:30,450 --> 00:53:36,000\r\nthat turns into 5 times--\r\n\r\n831\r\n00:53:36,000 --> 00:53:37,989\r\nwhat is it, fact-rec, or record fact--\r\n\r\n832\r\n00:53:42,620 --> 00:53:54,230\r\n5 times recursive factorial of 4, which turns into 5 times 4\r\n\r\n833\r\n00:53:54,230 --> 00:54:08,090\r\ntimes fact-rec of 3, which returns into 5 times 4 times 3\r\n\r\n834\r\n00:54:08,090 --> 00:54:15,240\r\ntimes, and so on, right?\r\n\r\n835\r\n00:54:15,240 --> 00:54:18,100\r\nThe idea is there was this chain of stuff building up,\r\n\r\n836\r\n00:54:18,100 --> 00:54:21,520\r\nwhich justified, in the substitution model, the fact that it's recursive. \r\n\r\n837\r\n00:54:21,520 --> 00:54:24,180\r\nAnd now, let's actually see that chain of stuff build up\r\n\r\n838\r\n00:54:24,180 --> 00:54:27,465\r\nand where it is in the machine, OK?\r\n\r\n839\r\n00:54:27,465 --> 00:54:30,230\r\nAll right, well, let's imagine we're going to start out again. \r\n\r\n840\r\n00:54:30,230 --> 00:54:41,451\r\nWe'll tell it to evaluate recursive factorial of 5\r\n\r\n841\r\n00:54:41,451 --> 00:54:45,000\r\nin some environment, again, E,0 \r\n\r\n842\r\n00:54:45,000 --> 00:54:49,275\r\nwhere recursive factorial is defined, OK?\r\n\r\n843\r\n00:54:49,275 --> 00:54:52,490\r\nWell, now we know what's eventually going to happen.\r\n\r\n844\r\n00:54:52,490 --> 00:54:53,925\r\nThis is going to come along,\r\n\r\n845\r\n00:54:53,925 --> 00:54:57,071\r\nit'll evaluate those things, figure out it's a procedure, \r\n\r\n846\r\n00:54:57,071 --> 00:55:00,255\r\nbuild somewhere over here an environment, E,1,\r\n\r\n847\r\n00:55:00,255 --> 00:55:06,725\r\nwhich has n bound to 5, which hangs off of E,0, \r\n\r\n848\r\n00:55:07,800 --> 00:55:10,847\r\nwhich would be, presumably, the definition environment \r\n\r\n849\r\n00:55:10,847 --> 00:55:12,847\r\nof recursive factorial, OK? \r\n\r\n850\r\n00:55:14,610 --> 00:55:19,670\r\nAnd, in this environment, it's going to go off and evaluate the body. \r\n\r\n851\r\n00:55:19,670 --> 00:55:27,000\r\nSo, again, the evaluation here will reduce to \r\n\r\n852\r\n00:55:27,000 --> 00:55:29,950\r\nevaluating the body in E,1.\r\n\r\n853\r\n00:55:29,950 --> 00:55:33,530\r\nThat's going to look at an if, and I won't go through the details of if. \r\n\r\n854\r\n00:55:33,530 --> 00:55:34,880\r\nIt'll look at the predicate.\r\n\r\n855\r\n00:55:34,880 --> 00:55:37,840\r\nIt'll decide it eventually has to evaluate the alternative.\r\n\r\n856\r\n00:55:37,840 --> 00:55:41,300\r\nSo this whole thing, again, will reduce to\r\n\r\n857\r\n00:55:41,300 --> 00:55:47,139\r\nthe alternative of recursive factorial, the alternative clause, \r\n\r\n858\r\n00:55:47,139 --> 00:55:53,075\r\nwhich says that this whole thing reduces to times n \r\n\r\n859\r\n00:55:53,075 --> 00:56:08,720\r\nof recursive factorial of n minus 1 in the environment E,1, OK?\r\n\r\n860\r\n00:56:08,720 --> 00:56:11,200\r\nSo the original expression, now, is going to reduce to\r\n\r\n861\r\n00:56:11,200 --> 00:56:13,754\r\nevaluating that expression, all right?\r\n\r\n862\r\n00:56:13,754 --> 00:56:16,280\r\nNow we have an application.\r\n\r\n863\r\n00:56:16,280 --> 00:56:18,225\r\nWe did an application before.\r\n\r\n864\r\n00:56:18,225 --> 00:56:20,390\r\nRemember what happens in an application?\r\n\r\n865\r\n00:56:20,390 --> 00:56:21,975\r\nThe first thing you do is you go off and you \r\n\r\n866\r\n00:56:21,975 --> 00:56:25,350\r\nsave the value of the continue register on the stack.\r\n\r\n867\r\n00:56:25,350 --> 00:56:27,365\r\nSo the stack here is going to have done in it.\r\n\r\n868\r\n00:56:29,980 --> 00:56:35,130\r\nAnd then you're going to set up to evaluate the sub-parts, OK? \r\n\r\n869\r\n00:56:35,130 --> 00:56:37,200\r\nSo here we go off to evaluate the sub-parts.\r\n\r\n870\r\n00:56:39,375 --> 00:56:41,450\r\nFirst thing we're going to do is evaluate the operator.\r\n\r\n871\r\n00:56:44,490 --> 00:56:47,250\r\nWhat happens when we evaluate an operator?\r\n\r\n872\r\n00:56:47,250 --> 00:56:51,480\r\nWell, we arrange things so that the operator ends up in the expression register. \r\n\r\n873\r\n00:56:51,480 --> 00:56:54,630\r\nThe environments in the ENV register continue someplace\r\n\r\n874\r\n00:56:54,630 --> 00:56:56,590\r\nwhere we're going to go evaluate the arguments.\r\n\r\n875\r\n00:56:56,590 --> 00:56:59,520\r\nAnd, on the stack, we've saved the original continue, \r\n\r\n876\r\n00:56:59,520 --> 00:57:01,720\r\nwhich is where we wanted to be when we're all done.\r\n\r\n877\r\n00:57:01,720 --> 00:57:03,400\r\nAnd then the things we needed\r\n\r\n878\r\n00:57:03,400 --> 00:57:05,807\r\nwhen we're going to get done evaluating the operator,\r\n\r\n879\r\n00:57:05,807 --> 00:57:08,333\r\nthe things we'll need to evaluate the arguments, namely, \r\n\r\n880\r\n00:57:08,333 --> 00:57:14,000\r\nthe environment and those arguments, those unevaluated arguments, \r\n\r\n881\r\n00:57:14,000 --> 00:57:15,620\r\nso there they are sitting on the stack.\r\n\r\n882\r\n00:57:15,620 --> 00:57:18,370\r\nAnd we're about to go off to evaluate the operator.\r\n\r\n883\r\n00:57:23,130 --> 00:57:26,920\r\nWell, when we return from this particular call--\r\n\r\n884\r\n00:57:26,920 --> 00:57:29,380\r\nso we're about to call eval-dispatch here--\r\n\r\n885\r\n00:57:29,380 --> 00:57:32,730\r\nwhen we return from this call, the value of that operator,\r\n\r\n886\r\n00:57:32,730 --> 00:57:36,275\r\nwhich, in this case, is going to be the primitive multiplier procedure, \r\n\r\n887\r\n00:57:36,275 --> 00:57:42,800\r\nwill end up in the FUN register, all right?\r\n\r\n888\r\n00:57:42,800 --> 00:57:44,530\r\nWe're going to evaluate some arguments.\r\n\r\n889\r\n00:57:44,530 --> 00:57:47,730\r\nThey will evaluate n here.\r\n\r\n890\r\n00:57:47,730 --> 00:57:50,250\r\nThat'll give us 5, in this case.\r\n\r\n891\r\n00:57:50,250 --> 00:57:52,900\r\nWe're going to put that in the argl register,\r\n\r\n892\r\n00:57:52,900 --> 00:57:57,460\r\nand then we'll go off to evaluate the second operand.\r\n\r\n893\r\n00:57:57,460 --> 00:58:00,365\r\nSo, at the point where we go off to evaluate the second operand--\r\n\r\n894\r\n00:58:00,365 --> 00:58:03,633\r\nand I'll skip details like computing, and minus 1, and all of that--\r\n\r\n895\r\n00:58:03,633 --> 00:58:06,385\r\nbut, when we go off to evaluate the second operand,\r\n\r\n896\r\n00:58:06,385 --> 00:58:10,737\r\nthat will eventually reduce to another call to fact-recursive.\r\n\r\n897\r\n00:58:12,000 --> 00:58:16,525\r\nAnd, what we've got on the stack here is\r\n\r\n898\r\n00:58:16,525 --> 00:58:19,942\r\nthe operator from that combination that we're going to use it in \r\n\r\n899\r\n00:58:19,942 --> 00:58:23,790\r\nand the other argument, OK?\r\n\r\n900\r\n00:58:23,790 --> 00:58:30,200\r\nSo, now, we're set up for another call to recursive factorial. \r\n\r\n901\r\n00:58:30,200 --> 00:58:31,438\r\nAnd, when we're done with this one, \r\n\r\n902\r\n00:58:31,438 --> 00:58:33,935\r\nwe're going to go to accumulate the last arg.\r\n\r\n903\r\n00:58:33,935 --> 00:58:35,200\r\nAnd remember what that'll do?\r\n\r\n904\r\n00:58:35,200 --> 00:58:36,425\r\nThat'll say oh, \r\n\r\n905\r\n00:58:36,425 --> 00:58:36,450\r\nwhatever the result of this has to get combined with that, \r\n\r\n906\r\n00:58:36,450 --> 00:58:39,281\r\nwhatever the result of this has to get combined with that, \r\n\r\n907\r\n00:58:39,281 --> 00:58:41,690\r\nand we're going to multiply them.\r\n\r\n908\r\n00:58:41,690 --> 00:58:45,720\r\nBut, notice now, we're at another recursive factorial.\r\n\r\n909\r\n00:58:45,720 --> 00:58:49,325\r\nWe're about to call eval-dispatch again,\r\n\r\n910\r\n00:58:49,325 --> 00:58:53,700\r\nexcept we haven't really reduced it because there's stuff on the stack now. \r\n\r\n911\r\n00:58:53,700 --> 00:58:55,244\r\nThe stuff on the stack says oh, when you get back, \r\n\r\n912\r\n00:58:55,244 --> 00:58:58,430\r\nyou'd better multiply it by the 5 you had hanging there.\r\n\r\n913\r\n00:58:58,430 --> 00:59:07,125\r\nSo, when we go off to make another call, \r\n\r\n914\r\n00:59:07,125 --> 00:59:09,300\r\nwe evaluate the n minus 1.\r\n\r\n915\r\n00:59:09,300 --> 00:59:11,256\r\nThat gives us another environment \r\n\r\n916\r\n00:59:11,256 --> 00:59:14,600\r\nin which the new n's going to be down to 4.\r\n\r\n917\r\n00:59:14,600 --> 00:59:18,930\r\nAnd we're about to call eval-dispatch again, right?\r\n\r\n918\r\n00:59:18,930 --> 00:59:21,350\r\nWe get another call.\r\n\r\n919\r\n00:59:21,350 --> 00:59:26,040\r\nThat 4 is going to end up in the same situation.\r\n\r\n920\r\n00:59:26,040 --> 00:59:30,020\r\nWe'll end up with another call to fact-recursive n.\r\n\r\n921\r\n00:59:30,020 --> 00:59:32,684\r\nAnd sitting on the stack will be the stuff from the original one \r\n\r\n922\r\n00:59:32,684 --> 00:59:35,360\r\nand, now, the subsidiary one we're doing.\r\n\r\n923\r\n00:59:35,360 --> 00:59:36,910\r\nAnd both of them are waiting for the same thing.\r\n\r\n924\r\n00:59:36,910 --> 00:59:40,600\r\nThey're going to go to accumulate a last argument.\r\n\r\n925\r\n00:59:40,600 --> 00:59:43,258\r\nAnd then, of course, when we go to the fourth call, \r\n\r\n926\r\n00:59:43,258 --> 00:59:45,640\r\nthe same thing happens, right?\r\n\r\n927\r\n00:59:45,640 --> 00:59:47,300\r\nAnd this goes on, and on, and on.\r\n\r\n928\r\n00:59:47,300 --> 00:59:50,075\r\nAnd what you see here on the stack, \r\n\r\n929\r\n00:59:50,107 --> 00:59:52,225\r\nexactly what's sitting here on the stack,\r\n\r\n930\r\n00:59:52,225 --> 00:59:54,960\r\nthe thing that says times and 5.\r\n\r\n931\r\n00:59:54,960 --> 01:00:00,470\r\nAnd what you're going to do with that is accumulate that into a last argument. \r\n\r\n932\r\n01:00:00,470 --> 01:00:02,760\r\nThat's exactly this, right?\r\n\r\n933\r\n01:00:02,760 --> 01:00:05,650\r\nThis is exactly where that stuff is hanging.\r\n\r\n934\r\n01:00:05,650 --> 01:00:11,659\r\nEffectively, the operator you're going to apply,\r\n\r\n935\r\n01:00:11,659 --> 01:00:13,625\r\nthe other argument \r\n\r\n936\r\n01:00:13,672 --> 01:00:15,300\r\nthat it's got to be multiplied by when you get back\r\n\r\n937\r\n01:00:15,300 --> 01:00:16,879\r\nand the parentheses, \r\n\r\n938\r\n01:00:16,879 --> 01:00:19,620\r\nwhich says yeah, what you wanted to do was accumulate them. \r\n\r\n939\r\n01:00:19,620 --> 01:00:22,560\r\nSo, you see, the substitution model is not such a lie.\r\n\r\n940\r\n01:00:22,560 --> 01:00:27,198\r\nThat really is, in some sense, what's sitting right on the stack. \r\n\r\n941\r\n01:00:27,198 --> 01:00:29,046\r\nOK.\r\n\r\n942\r\n01:00:29,046 --> 01:00:33,260\r\nAll right, so that, in some sense, should explain for you,\r\n\r\n943\r\n01:00:33,260 --> 01:00:36,596\r\nor at least convince you, that, \r\n\r\n944\r\n01:00:36,596 --> 01:00:39,870\r\nsomehow, this evaluator is managing \r\n\r\n945\r\n01:00:39,870 --> 01:00:42,959\r\nto take these procedures and execute some of them iteratively\r\n\r\n946\r\n01:00:42,959 --> 01:00:46,410\r\nand some of them recursively, even though,\r\n\r\n947\r\n01:00:46,410 --> 01:00:49,215\r\nas syntactically, they look like recursive procedures.\r\n\r\n948\r\n01:00:49,215 --> 01:00:50,660\r\nHow's it managing to do that?\r\n\r\n949\r\n01:00:50,660 --> 01:00:53,725\r\nWell, the basic reason it's managing to do that\r\n\r\n950\r\n01:00:53,725 --> 01:01:01,090\r\nis the evaluator is set up to save only what it needs later.\r\n\r\n951\r\n01:01:01,090 --> 01:01:04,670\r\nSo, for example, at the point where you've reduced\r\n\r\n952\r\n01:01:04,670 --> 01:01:07,683\r\nevaluating an expression and an environment \r\n\r\n953\r\n01:01:07,683 --> 01:01:10,525\r\nto applying a procedure to some arguments, \r\n\r\n954\r\n01:01:10,525 --> 01:01:13,375\r\nit doesn't need that original environment anymore \r\n\r\n955\r\n01:01:13,375 --> 01:01:17,675\r\nbecause any environment stuff will be packaged inside the procedures \r\n\r\n956\r\n01:01:17,675 --> 01:01:20,160\r\nwhere the application's going to happen.\r\n\r\n957\r\n01:01:20,160 --> 01:01:23,656\r\nAll right, similarly, when you're going along evaluating an argument list, \r\n\r\n958\r\n01:01:23,656 --> 01:01:25,910\r\nwhen you've finished evaluating the list,\r\n\r\n959\r\n01:01:25,910 --> 01:01:28,200\r\nwhen you're finished evaluating the last argument,\r\n\r\n960\r\n01:01:28,200 --> 01:01:31,500\r\nyou don't need that argument list any more, right?\r\n\r\n961\r\n01:01:31,500 --> 01:01:32,941\r\nAnd you don't need the environment where \r\n\r\n962\r\n01:01:32,941 --> 01:01:36,690\r\nthose arguments would be evaluated, OK?\r\n\r\n963\r\n01:01:36,690 --> 01:01:40,890\r\nSo the basic reason that this interpreter is being so smart\r\n\r\n964\r\n01:01:40,890 --> 01:01:43,050\r\nis that it's not being smart at all, it's being stupid.\r\n\r\n965\r\n01:01:43,050 --> 01:01:46,010\r\nIt's just saying I'm only going to save what I really need. \r\n\r\n966\r\n01:01:48,700 --> 01:01:51,000\r\nWell, let me show you here.\r\n\r\n967\r\n01:01:54,880 --> 01:01:58,310\r\nHere's the actual thing that's making a tail recursive.\r\n\r\n968\r\n01:01:58,310 --> 01:02:00,135\r\nRemember, it's the restore of continue.\r\n\r\n969\r\n01:02:00,135 --> 01:02:08,800\r\nIt's saying when I go off to evaluate the procedure body,\r\n\r\n970\r\n01:02:08,800 --> 01:02:11,252\r\nI should tell eval to come back to \r\n\r\n971\r\n01:02:11,252 --> 01:02:15,170\r\nthe place where that original evaluation was supposed to come back to.\r\n\r\n972\r\n01:02:15,170 --> 01:02:17,700\r\nSo, in some sense, you want to say what's the actual line\r\n\r\n973\r\n01:02:17,700 --> 01:02:18,770\r\nthat makes a tail recursive?\r\n\r\n974\r\n01:02:18,770 --> 01:02:19,920\r\nIt's that one.\r\n\r\n975\r\n01:02:19,920 --> 01:02:23,680\r\nIf I wanted to build a non-tail recursive evaluator,\r\n\r\n976\r\n01:02:23,680 --> 01:02:27,124\r\nfor some strange reason, all I would need to do is,\r\n\r\n977\r\n01:02:27,124 --> 01:02:32,750\r\ninstead of restoring continue at this point, I'd set up a label down here\r\n\r\n978\r\n01:02:32,750 --> 01:02:37,455\r\ncalled, \"Where to come back after you've finished applying the procedure.\"\r\n\r\n979\r\n01:02:37,455 --> 01:02:39,920\r\nInstead, I'd set continue to that. \r\n\r\n980\r\n01:02:39,920 --> 01:02:41,299\r\nI'd go to eval-dispatch, \r\n\r\n981\r\n01:02:41,299 --> 01:02:43,790\r\nand then eval-dispatch would come back here.\r\n\r\n982\r\n01:02:43,790 --> 01:02:47,920\r\nAt that point, I would restore continue and go to the original one. \r\n\r\n983\r\n01:02:47,920 --> 01:02:51,075\r\nSo here, the only consequence of that \r\n\r\n984\r\n01:02:51,075 --> 01:02:52,840\r\nwould be to make it non-tail recursive.\r\n\r\n985\r\n01:02:52,840 --> 01:02:54,629\r\nIt would give you exactly the same answers, \r\n\r\n986\r\n01:02:54,629 --> 01:02:56,656\r\nexcept if you did that iterative factorial\r\n\r\n987\r\n01:02:56,656 --> 01:02:59,875\r\nand all those iterative procedures, it would execute recursively.\r\n\r\n988\r\n01:03:02,900 --> 01:03:05,760\r\nWell, I lied to you a little bit, but just a little bit,\r\n\r\n989\r\n01:03:05,760 --> 01:03:08,550\r\nbecause I showed you a slightly over-simplified evaluator\r\n\r\n990\r\n01:03:08,550 --> 01:03:11,225\r\nwhere it assumes that each procedure --\r\n\r\n991\r\n01:03:11,225 --> 01:03:13,890\r\neach procedure body has only one expression.\r\n\r\n992\r\n01:03:13,890 --> 01:03:17,870\r\nRemember, in general, a procedure has a sequence of expressions in it. \r\n\r\n993\r\n01:03:17,870 --> 01:03:20,490\r\nSo there's nothing really conceptually new.\r\n\r\n994\r\n01:03:20,490 --> 01:03:22,725\r\nLet me just show you the actual evaluator\r\n\r\n995\r\n01:03:22,725 --> 01:03:24,730\r\nthat handles sequences of expressions.\r\n\r\n996\r\n01:03:28,470 --> 01:03:32,075\r\nThis is compound-apply now, and the only difference from the old one\r\n\r\n997\r\n01:03:32,075 --> 01:03:35,980\r\nis that, instead of going off to eval directly,\r\n\r\n998\r\n01:03:35,980 --> 01:03:38,039\r\nit takes the whole body of the procedure, \r\n\r\n999\r\n01:03:38,039 --> 01:03:40,151\r\nwhich, in this case, is a sequence of expressions, \r\n\r\n1000\r\n01:03:40,151 --> 01:03:42,325\r\nand goes off to eval-sequence.\r\n\r\n1001\r\n01:03:42,325 --> 01:03:47,907\r\nAnd eval-sequence is a little loop that, basically, \r\n\r\n1002\r\n01:03:47,907 --> 01:03:49,980\r\ndoes these evaluations one at a time.\r\n\r\n1003\r\n01:03:52,630 --> 01:03:53,900\r\nSo it does an evaluation.\r\n\r\n1004\r\n01:03:53,900 --> 01:03:58,440\r\nSays oh, when I come back, I'd better come back here to do the next one. \r\n\r\n1005\r\n01:03:58,440 --> 01:04:01,038\r\nAnd, when I'm all done, when I want to get the last expression,\r\n\r\n1006\r\n01:04:01,038 --> 01:04:06,410\r\nI just restore my continue and go off to eval-dispatch. \r\n\r\n1007\r\n01:04:06,410 --> 01:04:08,200\r\nAnd, again, if you wanted for some reason to\r\n\r\n1008\r\n01:04:08,200 --> 01:04:10,492\r\nbreak tail recursion in this evaluator, \r\n\r\n1009\r\n01:04:10,492 --> 01:04:14,900\r\nall you need to do is not handle the last expression, especially. \r\n\r\n1010\r\n01:04:14,900 --> 01:04:17,247\r\nJust say, after you've done the last expression,\r\n\r\n1011\r\n01:04:17,247 --> 01:04:21,900\r\ncome back to some other place after which you restore continue.\r\n\r\n1012\r\n01:04:21,900 --> 01:04:26,550\r\nAnd, for some reason, a lot of LISP evaluators tended to work that way. \r\n\r\n1013\r\n01:04:26,550 --> 01:04:28,545\r\nAnd the only consequence of that is that \r\n\r\n1014\r\n01:04:28,545 --> 01:04:31,614\r\niterative procedures built up stack.\r\n\r\n1015\r\n01:04:31,614 --> 01:04:35,670\r\nAnd it's not clear why that happened.\r\n\r\n1016\r\n01:04:35,670 --> 01:04:36,210\r\nAll right.\r\n\r\n1017\r\n01:04:36,210 --> 01:04:38,095\r\nWell, let me just sort of summarize, \r\n\r\n1018\r\n01:04:38,095 --> 01:04:41,120\r\nsince this is a lot of details in a big program.\r\n\r\n1019\r\n01:04:41,120 --> 01:04:44,040\r\nBut the main point is that it's no different,\r\n\r\n1020\r\n01:04:44,040 --> 01:04:47,060\r\nconceptually, from translating any other program.\r\n\r\n1021\r\n01:04:47,060 --> 01:04:50,156\r\nAnd the main idea is that we have this universal evaluator program,\r\n\r\n1022\r\n01:04:50,156 --> 01:04:51,870\r\nthe meta-circular evaluator.\r\n\r\n1023\r\n01:04:51,870 --> 01:04:54,560\r\nIf we translate that into LISP, then we have all of LISP. \r\n\r\n1024\r\n01:04:54,560 --> 01:04:57,980\r\nAnd that's all we did, OK?\r\n\r\n1025\r\n01:04:57,980 --> 01:04:59,680\r\nThe second point is that the magic's gone away.\r\n\r\n1026\r\n01:04:59,680 --> 01:05:01,970\r\nThere should be no more magic in this whole system, right?\r\n\r\n1027\r\n01:05:01,970 --> 01:05:08,720\r\nIn principle, it should all be very clear except, maybe, for\r\n\r\n1028\r\n01:05:08,720 --> 01:05:10,940\r\nhow list structured memory works, and\r\n\r\n1029\r\n01:05:10,940 --> 01:05:12,640\r\nwe'll see that later.\r\n\r\n1030\r\n01:05:12,640 --> 01:05:15,450\r\nBut that's not very hard.\r\n\r\n1031\r\n01:05:15,450 --> 01:05:18,720\r\nThe third point is that all this tail recursion came from\r\n\r\n1032\r\n01:05:18,720 --> 01:05:22,550\r\nthe discipline of eval being very careful \r\n\r\n1033\r\n01:05:22,550 --> 01:05:25,870\r\nto save only what it needs next time.\r\n\r\n1034\r\n01:05:25,870 --> 01:05:28,180\r\nIt's not some arbitrary thing where we're saying well,\r\n\r\n1035\r\n01:05:28,180 --> 01:05:29,864\r\nwhenever we call a sub-routine, \r\n\r\n1036\r\n01:05:29,864 --> 01:05:33,940\r\nwe'll save all the registers in the world and come back, right?\r\n\r\n1037\r\n01:05:33,940 --> 01:05:37,150\r\nSee, sometimes it pays to really worry about efficiency.\r\n\r\n1038\r\n01:05:37,150 --> 01:05:40,459\r\nAnd, when you're down in the guts of your evaluator machine, \r\n\r\n1039\r\n01:05:40,459 --> 01:05:42,560\r\nit really pays to think about things like that\r\n\r\n1040\r\n01:05:42,560 --> 01:05:45,230\r\nbecause it makes big consequences.\r\n\r\n1041\r\n01:05:45,230 --> 01:05:47,842\r\nWell, I hope what this has done\r\n\r\n1042\r\n01:05:47,842 --> 01:05:52,560\r\nis really made the evaluator seem concrete, right?\r\n\r\n1043\r\n01:05:52,560 --> 01:05:56,631\r\nI hope you really believe that somebody could hold a LISP\r\n\r\n1044\r\n01:05:56,631 --> 01:05:59,075\r\nLISP evaluator in the palm of their hand.\r\n\r\n1045\r\n01:05:59,075 --> 01:06:02,540\r\nMaybe to help you believe that, here's a LISP evaluator\r\n\r\n1046\r\n01:06:02,540 --> 01:06:06,160\r\nthat I'm holding the palm of my hand, right?\r\n\r\n1047\r\n01:06:06,160 --> 01:06:10,738\r\nAnd this is a chip which is actually\r\n\r\n1048\r\n01:06:10,738 --> 01:06:13,700\r\nquite a bit more complicated than the evaluator I showed you.\r\n\r\n1049\r\n01:06:17,815 --> 01:06:19,200\r\nMaybe, here's a better picture of it.\r\n\r\n1050\r\n01:06:22,070 --> 01:06:24,730\r\nWhat there is, is you can see the same overall structure.\r\n\r\n1051\r\n01:06:24,730 --> 01:06:26,940\r\nThis is a register array.\r\n\r\n1052\r\n01:06:26,940 --> 01:06:27,910\r\nThese are the data paths.\r\n\r\n1053\r\n01:06:27,910 --> 01:06:29,800\r\nHere's a finite state controller.\r\n\r\n1054\r\n01:06:29,800 --> 01:06:32,810\r\nAnd again, finite state, that's all there is.\r\n\r\n1055\r\n01:06:32,810 --> 01:06:34,160\r\nAnd somewhere there's external memory\r\n\r\n1056\r\n01:06:34,160 --> 01:06:35,750\r\nthat'll worry about things.\r\n\r\n1057\r\n01:06:35,750 --> 01:06:37,552\r\nAnd this particular one is very complicated \r\n\r\n1058\r\n01:06:37,552 --> 01:06:39,664\r\nbecause it's trying to run LISP fast. \r\n\r\n1059\r\n01:06:39,664 --> 01:06:42,976\r\nAnd it has some very, very fast parallel operations in there \r\n\r\n1060\r\n01:06:42,976 --> 01:06:46,650\r\nlike, if you want to index into an array, \r\n\r\n1061\r\n01:06:46,650 --> 01:06:50,362\r\nsimultaneously check that the index is an integer, \r\n\r\n1062\r\n01:06:50,362 --> 01:06:52,863\r\ncheck that it doesn't exceed the array bands, \r\n\r\n1063\r\n01:06:52,863 --> 01:06:57,120\r\nand go off and do the memory access, and do all those things simultaneously. \r\n\r\n1064\r\n01:06:57,120 --> 01:06:58,970\r\nAnd then, later, if they're all OK, actually\r\n\r\n1065\r\n01:06:58,970 --> 01:07:00,420\r\nget the value there.\r\n\r\n1066\r\n01:07:00,420 --> 01:07:02,327\r\nSo there are a lot of complicated operations \r\n\r\n1067\r\n01:07:02,327 --> 01:07:06,550\r\nin these data paths for making LISP run in parallel.\r\n\r\n1068\r\n01:07:06,550 --> 01:07:10,640\r\nIt's a completely non-risk philosophy of evaluating LISP.\r\n\r\n1069\r\n01:07:10,640 --> 01:07:13,740\r\nAnd then, this microcode is pretty complicated.\r\n\r\n1070\r\n01:07:13,740 --> 01:07:17,740\r\nLet's see, there's what?\r\n\r\n1071\r\n01:07:17,740 --> 01:07:24,079\r\nThere's about 389 instructions of 220-bit microcode sitting here \r\n\r\n1072\r\n01:07:24,079 --> 01:07:27,940\r\nbecause these are very complicated data paths.\r\n\r\n1073\r\n01:07:27,940 --> 01:07:33,580\r\nAnd the whole thing has about 89,000 transistors, OK?\r\n\r\n1074\r\n01:07:33,580 --> 01:07:33,840\r\nOK.\r\n\r\n1075\r\n01:07:33,840 --> 01:07:37,970\r\nWell, I hope that that takes away a lot of the mystery.\r\n\r\n1076\r\n01:07:37,970 --> 01:07:39,240\r\nMaybe somebody wants to look at this.\r\n\r\n1077\r\n01:07:42,048 --> 01:07:43,298\r\nYeah.\r\n\r\n1078\r\n01:07:46,260 --> 01:07:46,480\r\nOK.\r\n\r\n1079\r\n01:07:46,480 --> 01:07:47,730\r\nLet's stop.\r\n\r\n1080\r\n01:07:55,890 --> 01:07:57,815\r\nQuestions?\r\n\r\n1081\r\n01:07:57,815 --> 01:08:00,420\r\nAUDIENCE: OK, now, it sounds like what you're saying is that, \r\n\r\n1082\r\n01:08:00,420 --> 01:08:04,600\r\nwith the restore continue put in the proper place, that\r\n\r\n1083\r\n01:08:04,600 --> 01:08:09,422\r\nprocedures that would invoke a recursive process \r\n\r\n1084\r\n01:08:09,422 --> 01:08:12,675\r\nnow invoke an integer process \r\n\r\n1085\r\n01:08:12,675 --> 01:08:15,165\r\njust by the way that the eval signature is?\r\n\r\n1086\r\n01:08:15,165 --> 01:08:17,549\r\nPROFESSOR: I think the way I'd prefer to put it is that,\r\n\r\n1087\r\n01:08:17,549 --> 01:08:20,557\r\nwith restore continue put in the wrong place, \r\n\r\n1088\r\n01:08:20,557 --> 01:08:25,880\r\nyou can cause any syntactically-looking recursive procedure, in fact,\r\n\r\n1089\r\n01:08:25,880 --> 01:08:28,029\r\nto build up stack as it runs.\r\n\r\n1090\r\n01:08:28,029 --> 01:08:33,150\r\nBut there's no reason for that, \r\n\r\n1091\r\n01:08:33,150 --> 01:08:35,660\r\nso you might want to play around with it.\r\n\r\n1092\r\n01:08:35,660 --> 01:08:38,185\r\nYou can just switch around two or three instructions \r\n\r\n1093\r\n01:08:38,185 --> 01:08:41,129\r\nin the way compound-apply comes back, \r\n\r\n1094\r\n01:08:41,129 --> 01:08:45,060\r\nand you'll get something which isn't tail recursive.\r\n\r\n1095\r\n01:08:45,060 --> 01:08:47,670\r\nBut the thing I wanted to emphasize is there's no magic.\r\n\r\n1096\r\n01:08:47,670 --> 01:08:52,455\r\nIt's not as if there's some very clever pre-processing program\r\n\r\n1097\r\n01:08:52,455 --> 01:08:57,425\r\nthat's looking at this procedure, factorial iter, and say oh, gee, \r\n\r\n1098\r\n01:08:57,425 --> 01:09:01,060\r\nI really notice that I don't have to push stack in order to do this. \r\n\r\n1099\r\n01:09:01,060 --> 01:09:03,760\r\nSome people think that that's what's going on.\r\n\r\n1100\r\n01:09:03,760 --> 01:09:05,383\r\nIt's something much, much more dumb than that, \r\n\r\n1101\r\n01:09:05,383 --> 01:09:08,880\r\nit's this one place you're putting the restore instruction.\r\n\r\n1102\r\n01:09:08,880 --> 01:09:10,353\r\nIt's just automatic.\r\n\r\n1103\r\n01:09:10,353 --> 01:09:11,603\r\nAUDIENCE: OK.\r\n\r\n1104\r\n01:09:14,217 --> 01:09:17,850\r\nAUDIENCE: But that's not affecting the time complexity is it? \r\n\r\n1105\r\n01:09:17,850 --> 01:09:18,275\r\nPROFESSOR: No.\r\n\r\n1106\r\n01:09:18,275 --> 01:09:21,810\r\nAUDIENCE: It's just that it's handling it recursively\r\n\r\n1107\r\n01:09:21,810 --> 01:09:23,020\r\ninstead of iteratively.\r\n\r\n1108\r\n01:09:23,020 --> 01:09:27,179\r\nBut, in terms of the order of time it takes to finish the operation, \r\n\r\n1109\r\n01:09:27,179 --> 01:09:29,220\r\nit's the same one way or the other, right?\r\n\r\n1110\r\n01:09:29,220 --> 01:09:29,920\r\nPROFESSOR: Yes.\r\n\r\n1111\r\n01:09:29,920 --> 01:09:32,609\r\nTail recursion is not going to change the time complexity of anything \r\n\r\n1112\r\n01:09:32,609 --> 01:09:36,029\r\nbecause, in some sense, it's the same algorithm that's going on. \r\n\r\n1113\r\n01:09:36,029 --> 01:09:41,210\r\nWhat it's doing is really making this thing run as an iteration, right? \r\n\r\n1114\r\n01:09:41,210 --> 01:09:44,750\r\nNot going to run out of memory counting up to a giant number\r\n\r\n1115\r\n01:09:44,750 --> 01:09:47,683\r\nsimply because the stack would get pushed.\r\n\r\n1116\r\n01:09:47,683 --> 01:09:51,640\r\nSee, the thing you really have to believe is that, when we write-- \r\n\r\n1117\r\n01:09:51,640 --> 01:09:53,781\r\nsee, we've been writing all these things called iterations,\r\n\r\n1118\r\n01:09:53,781 --> 01:09:57,990\r\ninfinite loops, define loop to be called loop.\r\n\r\n1119\r\n01:10:00,325 --> 01:10:03,650\r\nThat's is as much an iteration \r\n\r\n1120\r\n01:10:03,650 --> 01:10:07,630\r\nas if we wrote do forever loop, right?\r\n\r\n1121\r\n01:10:07,630 --> 01:10:09,280\r\nIt's just syntactic sugar as the difference.\r\n\r\n1122\r\n01:10:09,280 --> 01:10:14,730\r\nThese things are real, honest to god, iterations, right?\r\n\r\n1123\r\n01:10:14,730 --> 01:10:16,681\r\nThey don't change the time complexity, but they \r\n\r\n1124\r\n01:10:16,681 --> 01:10:18,535\r\nturn them into real iterations.\r\n\r\n1125\r\n01:10:21,686 --> 01:10:23,800\r\nAll right, thank you.\r\n\r\n"
  },
  {
    "path": "Sub/lec10a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 10A: Compilation\n\n\n\n[MUSIC PLAYING] PROFESSOR: Last time, we took a look at an explicit control evaluator for\nLisp, and that bridged the gap between all these high-level languages like Lisp and the\n\nquery language and all of that stuff, bridged the gap between that and a conve ntional\nregister machine. And in fact, you can think of the explicit control evaluator either as, say,\n\nthe code for a Lisp interpreter if you wanted to implement it in the assembly language of\nsome conventional register transfer machine, or, if you like, you can think of it as the\n\nmicrocode of some machine that's going to be specially designed to run Lisp.\n\n\n\n\nIn either case, what we're doing is we're taking a machine that speaks some low-level\n\nlanguage, and we're raising the machine to a high- level language like Lisp by writing an\ninterpreter. So for instance, here, conceptually, is a special purpose machine for computing\n\nfactorials. It takes in five and puts out 120. And what this special purpose machine is is\nactually a Lisp interpreter that's configured itself to run factorials, because you fit into it a\n\ndescription of the factorial machine.\n\n\n\n\nSo that's what an interpreter is. It configures itself to emulate a machine whose description\n\nyou read in. Now, inside the Lisp interpreter, what's that? Well, that might be your general\nregister language interpreter that configures itself to behave like a Lisp interpreter, because\n\nyou put in a whole bunch of instructions in register language. This is the explicit control\nevaluator. And then it also has some sort of library, a library of primitive operators and Lisp\n\noperations and all sorts of things like that. That's the general strategy of interpretation.\n\n\n\n\nAnd the point is, what we're doing is we're writing an interpreter to raise the machine to the\n\nlevel of the programs that we want to write. Well, there's another strategy, a different one,\nwhich is compilation. Compilation's a little bit different. Here --here we might have produced\n\na special purpose machine for, for computing factorials, starting with some sort of m achine\n\nthat speaks register language, except we're going to do a different strategy.\n\n\n\n\nWe take our factorial program. We use that as the source code into a compiler. What the\ncompiler will do is translate that factorial program into some register machine language.\n\nAnd this will now be not the explicit control evaluator for Lisp, this will be some register\n\nlanguage for computing factorials. So this is the translation of that.\nThat will go into some sort of loader which will combine this code with code selected from\n\nthe library to do things like primitive multiplication. And then we'll produce a load module\nwhich configures the register language machine to be a special purpose factorial machine.\n\nSo that's a, that's a different strategy. In interpretation, we're raising the machine to the\nlevel of our language, like Lisp. In compilation, we're taking our program and lowering it to\n\nthe language that's spoken by the machine.\n\n\n\n\nWell, how do these two strategies compare? The compiler can produce code that will\n\nexecute more efficiently. The essential reason for that is that if you think about the register\noperations that are running, the interpreter has to produce register operations which, in\n\nprinciple, are going to be general enough to execute any Lisp procedure.Whereas the\ncompiler only has to worry about producing a special bunch of register operations for, for\n\ndoing the particular Lisp procedure that you've compiled.\n\n\n\n\nOr another way to say that is that the interpreter is a general purpose simulator, that when\n\nyou read in a Lisp procedure, then those can simulate the program described by that, by\nthat procedure. So the interpreter is worrying about making a general purpose simulator,\n\nwhereas the compiler, in effect, is configuring the thing to be the machine tha t the\n\ninterpreter would have been simulating. So the compiler can be faster.\n\n\n\n\nOn the other hand, the interpreter is a nicer environment for debugging. And the reason for\nthat is that we've got the source code actually there. We're interpreting it. That's what we're\n\nworking with. And we also have the library around. See, the interpreter--the library sitting\n\nthere is part of the interpreter. The compiler only pulls out from the library what it needs to\nrun the program.\n\n\n\n\nSo if you're in the middle of debugging, and you might like to write a little extra program to\n\nexamine some run time data structure or to produce some computation that you didn't think\n\nof when you wrote the program, the interpreter can do that perfectly well, whereas the\ncompiler can't. So there are sort of dual, dual advantages. The compiler will produce code\n\nthat executes faster. The interpreter is a better environment for debugging.\n\n\n\n\nAnd most Lisp systems end up having both, end up being configured so you have an\ninterpreter that you use when you're developing your code. Then you can speed it up by\n\ncompiling. And very often, you can arrange that compiled code and interpreted code can call\n\neach other. We'll see how to do that. That's not hard.\nIn fact, the way we'll-- in the compiler we're going to make, the way we'll arrange for\n\ncompiled coding and interpreted code to call, to call each other, is that we'll have the\ncompiler use exactly the same register conventions as the interpreter. Well, the idea of a\n\ncompiler is very much like the idea of an interpreter or evaluator. It's the same thing. See,\nthe evaluator walks over the code and performs some register operations. That's what we\n\ndid yesterday.\n\n\n\n\nWell, the compiler essentially would like to walk over the code and   produce the register\n\noperations that the evaluator would have done were it evaluating the thing. And that gives\nus a model for how to implement a zeroth-order compiler, a very bad compiler but\n\nessentially a compiler. A model for doing that is you just take the evaluator, you run it over\nthe code, but instead of executing the actual operations, you just save them away. And\n\nthat's your compiled code.\n\n\n\n\nSo let me give you an example of that. Suppose we're going to compile--suppose we want\n\nto compile the expression f of x. So let's assume that we've got f of x in the x register and\nsomething in the environment register. And now imagine starting up the evaluator. Well, it\n\nlooks at the expression and it sees that it's an application. And it branches to a place in the\n\nevaluator code we saw called ev-application. And then it begins. It stores away the\noperands and unev, and then it's going to put the operator in exp, and it's going to go\n\nrecursively evaluate it.\n\n\n\n\nThat's the process that we walk through. And if you start looking at the code, you start\n\nseeing some register operations. You see assign to unev the operands, assign to exp the\noperator, save the environment, generate that, and so on. Well, if we look on the overhead\n\nhere, we can see, we can see those operations starting to be produced. Here's sort of the\nfirst real operation that the evaluator would have done. It pulls the operands out of the exp\n\nregister and assigns it to unev. And then it assigns something to the expression register,\nand it saves continue, and it saves env.\n\n\n\n\n\nAnd all I'm doing here is writing down the register assignments that the evaluator would\nhave done in executing that code. And can zoom out a little bit. Altogether, there are about\n\n19 operations there. And this is the--this will be the piece of code up until the point where\nthe evaluator branches off to apply-dispatch. And in fact, in this compiler, we're not going to\n\nworry about apply-dispatch at all. We're going to have everything--we're going to have both\ninterpreted code and compiled code. Always evaluate procedures, always apply procedures\n\nby going to apply-dispatch. That will easily allow interpreted code and compiled code to call\neach other.\nWell, in principle, that's all we need to do. You just run the evaluator. So the compiler's a lot\n\nlike the evaluator. You run it, except it stashes away these operations instead of actually\nexecuting them. Well, that's not, that's not quite true. There's only one little lie in that.\n\n\n\n\n\nWhat you have to worry about is if you have a, a predicate. If you have some kind of test\nyou want to do, obviously, at the point when you're compiling it, you don't know which\n\nbranch of these--of a conditional like this you're going to do. So you can't say which one the\nevaluator would have done. So all you do there is very simple. You compile both branches.\n\n\n\n\n\nSo you compile a structure that looks like this. That'll compile into something that says, the\ncode, the code for P. And it puts its results in, say, the val register. So you walk the\n\ninterpreter over the predicate and make sure that the result would go into the val register.\nAnd then you compile an instruction that says, branch if, if val is true, to a place we'll call\n\nlabel one.\n\n\n\n\nThen we, we will put the code for B to walk the interpreter--walk the interpreter over B. And\n\nthen go to put in an instruction that says, go to the next thing, whatever, whatever was\nsupposed to happen after this thing was done. You put in that instruction. And here you put\n\nlabel one. And here you put the code for A. And you put go to next thing.\n\n\n\n\nSo that's how you treat a conditional. You generate a little block like that. And other than\n\nthat, this zeroth-order compiler is the same as the evaluator. It's just stashing away the\ninstructions instead of executing them. That seems pretty simple, but we've gained\n\nsomething by that. See, already that's going to be more efficient than the evaluator.\nBecause, if you watch the evaluator run, it's not only generating the register operations we\n\nwrote down, it's also doing things to decide which ones to generate.\n\n\n\n\nSo the very first thing it does, say, here for instance, is go do some tests and decide that\n\nthis is an application, and then branch off to the place that, that handles applications. In\nother words, what the evaluator's doing is simultaneously analyzing the code to see what to\n\ndo, and running these operations. And when you-- if you run the evaluator a million times,\nthat analysis phase happens a million times, whereas in the compiler, it's happened once,\n\nand then you just have the register operations themselves.\n\n\n\n\nOk, that's a, a zeroth-order compiler, but it is a wretched, wretched compiler. It's really\n\ndumb. Let's--let's go back and, and look at this overhead. So look at look at some of the\noperations this thing is doing. We're supposedly looking at the operations and interpreting f\nof x. Now, look here what it's doing. For example, here it assigns to exp the operator in\n\nfetch of exp. But see, there's no reason to do that, because this is-- the compiler knows that\nthe operator, fetch of exp, is f right here.\n\n\n\n\n\nSo there's no reason why this instruction should say that. It should say, we'll assign to exp,\nf. Or in fact, you don't need exp at all. There's no reason it should have exp at all. What,\n\nwhat did exp get used for? Well, if we come down here, we're going to assign to val, look up\nthe stuff in exp in the environment. So what we really should do is get rid of the exp\n\nregister altogether, and just change this instruction to say, assign to val, look up the\nvariable value of the symbol f in the environment.\n\n\n\n\n\nSimilarly, back up here, we don't need unev at all, because we know what the operands of\nfetch of exp are for this piece of code. It's the, it's the list x. So in some sense, you don't\n\nwant unev and exp at all. See, what they really are in some sense, those aren't registers of\nthe actual machine that's supposed to run. Those are registers that have to do with\n\narranging the thing that can simulate that machine.\n\n\n\n\nSo they're always going to hold expressions which, from the compiler's point of view, are\n\njust constants, so can be put right into the code. So you can forget about all the operations\nworrying about exp and unev and just use those constants. Similarly, again, if we go, go\n\nback and look here, there are things like assign to continue eval-args. Now, that has\nnothing to do with anything. That was just the evaluator keeping track of where it should go\n\nnext, to evaluate the arguments in some, in some application.\n\n\n\n\nBut of course, that's irrelevant to the compiler, because you-- the analysis phase will have\n\nalready done that. So this is completely irrelevant. So a lot of these, these assignments to\ncontinue have not to do where the running machine is supposed to continue in keeping\n\ntrack of its state. It has to, to do with where the evaluator analysis should continue, and\n\nthose are completely irrelevant. So we can get rid of them.\n\n\n\n\nOk, well, if we, if we simply do that, make those kinds of optimizations, get rid, get rid of\nworrying about exp and unev, and get rid of these irrelevant register assignments to\n\ncontinue, then we can take this literal code, these sort of 19 instructions that the, that the\nevaluator would have done, and then replace them. Let's look at the, at theslide. Replace\n\nthem by--we get rid of about half of them. And again, this is just sort of filtering what the\n\nevaluator would have done by getting rid of the irrelevant stuff.\nAnd you see, for instance, here the--where the evaluator said, assign val, look up variable\n\nvalue, fetch of exp, here we have put in the constant f. Here we've put in the constant x. So\nthere's a, there's a little better compiler. It's still pretty dumb. It's still doing a lot of dumb\n\nthings. Again, if we go look at the slide again, look at the very beginning here, we see a\nsave the environment, assign something to the val register, and restore the environment.\n\n\n\n\n\nWhere'd that come from? That came from the evaluator back here saying, oh, I'm in the\nmiddle of evaluating an application. So I'm going to recursively call eval dispatch. So I'd\n\nbetter save the thing I'm going to need later, which is the environment. This was the result\nof recursively calling eval dispatch. It was evaluating the symbol f in that case.\n\n\n\n\n\nThen it came back from eval dispatch, restored the environment. But in fact, the actual\nthing it ended up doing in the evaluation is not going to hurt the environment at all. So\n\nthere's no reason to be saving the environment and restoring the environment here.\nSimilarly, here I'm saving the argument list. That's a piece of the argument evaluation loop,\n\nsaving the argument list, and here you restore it.\n\n\n\n\nBut the actual thing that you ended up doing didn't trash the argument list. So there was no\n\nreason to save it. So another way to say, another way to say that is that the, the evaluator\nhas to be maximally pessimistic, because as far from its point of view it's just going off to\n\nevaluate something. So it better save what it's going to need later.\n\n\n\n\nBut once you've done the analysis, the compiler is in a position to say, well, what actually\n\ndid I need to save? And doesn't need to do any-- it doesn't need to be as careful as the\nevaluator, because it knows what it actually needs. Well, in any case, if we do that and\n\neliminate all those redundant saves and restores, then we can get it down to this. And you\nsee there are actually only three instructions that we actually need, down from the initial 11\n\nor so, or the initial 20 or so in the original one.\n\n\n\n\nAnd that's just saying, of those register operations, which ones did we actually need? Let\n\nme just sort of summarize that in another way, just to show you in a little better picture.\nHere's a picture of starting-- This is looking at all the saves and restores. So here's the\n\nexpression, f of x, and then this traces through, on the bottom here, the various places in\nthe evaluator that were passed when the evaluation happened.\n\n\n\n\n\nAnd then here, here you see arrows. Arrow down means register saved. So the first thing\nthat happened is the environment got saved. And over here, the environment got restored.\nAnd these-- so there are all the pairs of stack operations. Now, if you go ahead and say,\n\nwell, let's remember that we don't--that unev, for instance, is a completely useless register.\nAnd if we use the constant structure of the code, well, we don't need, we don't need to save\n\nunev. We don't need unev at all.\n\n\n\n\nAnd then, depending on how we set up the discipline of the--of calling other things that\n\napply, we may or may not need to save continue. That's the first step I did. And then we\ncan look and see what's actually, what's actually needed. See, we don't-- didn't really need\n\nto save env or cross-evaluating f, because it wouldn't, it wouldn't trash it. So if we take\nadvantage of that, and see the evaluation of f here, doesn't really need to worry about,\n\nabout hurting env. And similarly, the evaluation of x here, when the evaluator did that it\nsaid, oh, I'd better preserve the function register around that, because I might need it later.\n\nAnd I better preserve the argument list.\n\n\n\n\nWhereas the compiler is now in a position to know, well, we didn't really need to save-- to\n\ndo those saves and restores. So in fact, all of the stack operations done by the evaluator\nturned out to be unnecessary or overly pessimistic. And the compiler is in a position to know\n\nthat. Well that's the basic idea. We take the evaluator, we eliminate the things that you\n\ndon't need, that in some sense have nothing to do with the compiler at all, just the\nevaluator, and then you see which stack operations are unnecessary.\n\n\n\n\nThat's the basic structure of the compiler that's described in the book. Let me just show you\n\nhow that examples a little bit too simple. To see how you, how you actually save a lot, let's\n\nlook at a little bit mor e complicated expression. F of G of X and 1. And I'm not going to go\nthrough all the code. There's a, there's a fair pile of it. I think there are, there are\n\nsomething like 16 pairs of register saves and restores as the evaluator walks through that.\nHere's a diagram of them.\n\n\n\n\n\nLet's see. You see what's going on. You start out by--the evaluator says, oh, I'm about to\ndo an application. I'll preserve the environment. I'll restore it here. Then I'm about to do the\n\nfirst operand. Here it recursively goes to the evaluator. The evaluator says, oh, this is an\napplication, I'll save the environment, do the operator of that combination, restore it here.\n\n\n\n\nThis save--this restore matches that save. And so on. There's unev here, which turns out to\n\nbe completely unnecessary, continues getting bumped around here. The function register is\n\ngetting, getting saved across the first operands, across the operands. All sorts of things are\ngoing on. But if you say, well, what of those really were the business of the compiler as\n\nopposed to the evaluator, you get rid of a whole bunch.\nAnd then on top of that, if you say things like, the evaluation of F doesn't hurt the\nenvironment register, or simply looking up the symbol X, you don't have to protect the\n\nfunction register against that. So you come down to just a couple of, a couple of pairs here.\nAnd still, you can do a little better.\n\n\n\n\n\nLook what's going on here with the environment register. The environment register comes\nalong and says, oh, here's a combination. This evaluator, by the way, doesn't know\n\nanything about G. So here it says, so it says, I'd better save the environment register,\nbecause evaluating G might be some arbitrary piece of code that would trash it, and I'm\n\ngoing to need it later, after this argument, for doing the second argument. So that's why\n\nthis one didn't go away, because the compiler made no assumptions about what G would\ndo.\n\n\n\n\nOn the other hand, if you look at what the second argument is, that's just looking up one.\n\nThat doesn't need this environment register. So there's no reason to save it. So in fact, you\n\ncan get rid of that one, too. And from this whole pile of, of register operations, if you simply\ndo a little bit of reasoning like that, you get down to, I think, just two pairs of saves and\n\nrestores. And those, in fact, could go away further if you, if you knew something about G.\n\n\n\n\nSo again, the general idea is that the reason the compiler can be better is that the\n\ninterpreter doesn't know what it's about to encounter. It has to be maximally pessimistic in\nsaving things to protect itself. The compiler only has to deal with what actually had to be\n\nsaved. And there are two reasons that something might not have to be saved. One is that\nwhat you're protecting it against, in fact, didn't trash the register, like it was just a variable\n\nlook-up. And the other one is, that the thing that you were saving it for might turn out not\nto actually need it.\n\n\n\n\n\nSo those are the two basic pieces of knowledge that the compiler can take advantage of in\nmaking the code more efficient. Let's break for questions.\n\n\n\n\nAUDIENCE: You kept saying that the uneval register, unev register didn't need to be used at\n\nall. Does that mean that you could just map a six-register machine? Or is that, in this\n\nparticular example, it didn't need to be used?\n\n\n\n\nPROFESSOR: For the compiler, you could generate code for the six-register, five, right?\nBecause that exp goes away also. Assuming--yeah, you can get rid of both exp and unev,\nbecause, see, those are data structures of the evaluator. Those are all things that would be\n\nconstants from the point of view of the compiler. The only thing is this particular compiler is\nset up so that interpreted code and compiled code can coexist.\n\n\n\n\n\nSo the way to think about it is, is maybe you build a chip which is the evaluator, and what\nthe compiler might do is generate code for that chip. It just wouldn't use two of the\n\nregisters. All right, let's take a break.\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\nWe just looked at what the compiler is supposed to do. Now let's very briefly look at how,\n\nhow this gets accomplished. And I'm going to give no details. There's, there's a giant pile of\ncode in the book that gives all the details. But what I want to do is just show you the, the\n\nessential idea here. Worry about the details some other time.\n\n\n\n\nLet's imagine that we're compiling an expression that looks like there's some operator, and\n\nthere are two arguments. Now, the-- what's the code that the compiler should generate?\nWell, first of all, it should r ecursively go off and compile the operator. So it says, I'll compile\n\nthe operator. And where I'm going to need that is to be in the function register, eventually.\n\nSo I'll compile some instructions that will compile the operator and end up with the result i n\nthe function register.\n\n\n\n\nThe next thing it's going to do, another piece is to say, well, I have to compile the first\n\nargument. So it calls itself recursively. And let's say the result will go into val. And then\n\nwhat it's going to need to do is start setting up the argument list. So it'll say, assign to argl\ncons of fetch-- so it generates this literal instruction-- fetch of val onto empty list.\n\n\n\n\nHowever, it might have to work-- when it gets here, it's going to need the environment. It's\n\ngoing to need whatever environment was here in order to do this evaluation of the first\n\nargument. So it has to ensure that the compilation of this operand, or it has to protect the\nfunction register against whatever might happen in the compilation of this operand.\n\n\n\n\nSo it puts a note here and says, oh, this piece should be done preserving the environment\n\nregister. Similarly, here, after it gets done compiling the first operand, it's going to say, I\nbetter compile-- I'm going to need to know the environment for the second operand. So it\nputs a little note here, saying, yeah, this is also done preserving env. Now it goes on and\n\nsays, well, the next chunk of code is the one that's going to compile the second argument.\n\n\n\n\nAnd let's say it'll compile it with a targeted to val, as they say. And then it'll generate the\n\nliteral instruction, building up the argument list. So it'll say, assign to argl cons of the new\nvalue it just got onto the old argument list. However, in order to have the old argument list,\n\nit better have arranged that the argument list didn't get trashed by whatever happened in\nhere.\n\n\n\n\n\nSo it puts a little note here and says, oh, this has to be done preserving argl. Now it's got\nthe argument list set up. And it's all ready to go to apply dispatch. It generates thi s literal\n\ninstruction. Because now it's got the arguments in argl and the operator in fun, but wait, it's\nonly got the operator in fun if it had ensured that this block of code didn't trash what was in\n\nthe function register.\n\n\n\n\nSo it puts a little note here and says, oh, yes, all this stuff here had better be done\n\npreserving the function register. So that's the little--so when it starts ticking--so basically,\nwhat the compiler does is append a whole bunch of code sequences. See, what it's got in it\n\nis little primitive pieces of things, like how to look up a symbol, how to do a conditional.\nThose are all little pieces of things.\n\n\n\n\n\nAnd then it appends them together in this sort of discipline. So the basic means of\ncombining things is to append two code sequences. That's what's going on here. And it's a\n\nlittle bit tricky. The idea is that it appends two code sequences, taking care to preserve a\nregister. So the actual append operation looks like this. What it wants to do is say, if --\n\nhere's what it means to append two code sequences. So if sequence one needs register-- I\nshould change this. Append sequence one to sequence two, preserving some register. Let\n\nme say, and. So it's clear that sequence one comes first.\n\n\n\n\nSo if sequence two needs the register and sequence one modifies the register, then the\n\ninstructions that the compiler spits out are, save the register. Here's the code. You generate\nthis code. Save the register, and then you put out the recursively compiled stuff for\n\nsequence one. And then you restore the register.\n\n\n\n\nAnd then you put out the recursively compiled stuff for sequence two. That's in the case\n\nwhere you need to do it. Sequence two actually needs the register, and sequence one\nactually clobbers it. So that's sort of if. Otherwise, all you spit out is sequence one followed\nby sequence two. So that's the basic operation for sticking together these bits of code\n\nfragments, these bits of instructions into a sequence.\n\n\n\n\nAnd you see, from this point of view, the difference between the interpreter and the\n\ncompiler, in some sense, is that where the compiler has these preserving notes, and says,\nmaybe I'll actually generate the saves and restores and maybe I won't, the interpreter being\n\nmaximally pessimistic always has a save and restore here. That's the essential difference.\n\n\n\n\nWell, in order to do this, of course, the compiler needs some theory of what code sequences\n\nneed and modifier registers. So the tiny little fragments that you put in, like the basic\nprimitive code fragments, say, what are the operations that you do when you look up a\n\nvariable? What are the sequence of things that you do when you compile a constant or\napply a function? Those have little notations in there about what they need and what they\n\nmodify.\n\n\n\n\nSo the bottom-level data structures-- Well, I'll say this. A code sequence to the compiler\n\nlooks like this. It has the actual sequence of instructions. And then, along with it, there's the\nset of registers modified. And then there's the set of registers needed. So that's the\n\ninformation the compiler has that it draws on in order to be able to do this operation.\n\n\n\n\nAnd where do those come from? Well, those come from, you might expect, for the very\n\nprimitive ones, we're going to put them in by hand. And then, when we combine two\nsequences, we'll figure out what these things should be. So for example, a very primitive\n\none, let's see. How about doing a register assignment.\n\n\n\n\nSo a primitive sequence might say, oh, it's code fragment. Its code instruction is assigned\n\nto R1, fetch of R2. So this is an example. That might be an example of a sequence of\ninstructions. And along with that, it'll say, oh, what I need to remember is that that modifies\n\nR1, and then it needs R2. So when you're first building this compiler, you put in little\nfragments of stuff like that.\n\n\n\n\n\nAnd now, when it combines two sequences, if I'm going to combine, let's say, sequence\none, that modifies a bunch of registers M1, and needs a bunch of registers N1. And I'm\n\ngoing to combine that with sequence two. That modifies a bunch of registers M2, and needs\na bunch of registers N2.\nThen, well, we can reason it out. The new code fragment, sequence one, and-- followed by\n\nsequence two, well, what's it going to modify? The things that it will modify are the things\nthat are modified either by sequence one or sequence two. So the union of these two sets\n\nare what the new thing modifies. And then you say, well, what is this--what registers is it\ngoing to need?\n\n\n\n\n\nIt's going to need the things that are, first of all, needed by sequence one. Sowhat it needs\nis sequence one. And then, well, not quite all of the ones that are needed by sequence one.\n\nWhat it needs are the ones that are needed by sequence two that have not been set up by\nsequence one. So it's sort of the union of the things that se quence two needs minus the\n\nones that sequence one modifies. Because it worries about setting them up.\n\n\n\n\nSo there's the basic structure of the compiler. The way you do register optimizations is you\n\nhave some strategies for what needs to be preserved. That depends on a data structure.\nWell, it depends on the operation of what it means to put things together. Preserving\n\nsomething, that depends on knowing what registers are needed and modified by these code\nfragments.\n\n\n\n\n\nThat depends on having little data structures, which say, a code sequence is the actual\ninstructions, what they modify and what they need. That comes from, at the primitive level,\n\nbuilding it in. At the primitive level, it's going to be completely obvious what something\nneeds and modifies. Plus, this particular way that says, when I build up bigger ones, here's\n\nhow I generate the new set of registers modified and the new set of registers needed.\n\n\n\n\nAnd that's the whole-- well, I shouldn't say that's the whole thing. That's the whole thing\n\nexcept for about 30 pages of details in the book. But it is a perfectly usable rudimentary\ncompiler. Let me kind of show you what it does.\n\n\n\n\n\nSuppose we start out with recursive factorial. And these slides are going to be much too\nsmall to read. I just want to flash through the code and show you about how much it is.\n\nThat starts out with--here's a first block of it, where it compiles a procedure entry and does\na bunch of assignments. And this thing is basically up through the part where it sets up to\n\ndo the predicate and test whether the predicate's true.\n\n\n\n\nThe second part is what results from-- in the recursive call to fact of n minus one. And this\n\nlast part is coming back from that and then taking care of the constant case. So that's about\nhow much code it would produce for factorial.\nWe could make this compiler much, much better, of course. The main way we could make it\nbetter is to allow the compiler to make any assumptions at all about what happens when\n\nyou call a procedure. So this compiler, for instance, doesn't even know, say, that\nmultiplication is something that could be coded in line. Instead, it sets up this whole\n\nmechanism. It goes to apply-dispatch.\n\n\n\n\nThat's a tremendous waste, because what you do every time you go to apply-dispatch is\n\nyou have to concept this argument list, because it's a very general thing you're going to. In\nany real compiler, of course, you're going to have registers for holding arguments. And\n\nyou're going to start preserving and saving the way you use those registers similar to the\n\nsame strategy here.\n\n\n\n\nSo that's probably the very main way that this particular compiler in the book could be\nfixed. There are other things like looking up variable values and making more efficient\n\nprimitive operations and all sorts of things. Essentially,a good Lisp compiler can absorb an\n\narbitrary amount of effort. And probably one of the reasons that Lisp is slow with compared\nto languages like FORTRAN is that, if you look over history at the amount of effort that's\n\ngone into building Lisp compilers, it's nowhere near the amount of effort that's gone into\nFORTRAN compilers. And maybe that's something that will change over the next couple of\n\nyears.\n\n\n\n\nOK, let's break. Questions?\n\n\n\n\nAUDIENCE: One of the very first classes-- I don't know if it was during class or after class-\n\nyou showed me the, say, addition has a primitive that we don't see, and-percent add or\n\nsomething like that. Is that because, if you're doing inline code you'd want to just do it for\ntwo operators, operands? But if you had more operands, you'd want to do something\n\nspecial?\n\n\n\n\nPROFESSOR: Yeah, you're looking in the actual scheme implementation. There's a plus, and\na plus is some operator. And then if you go look inside the code for plus, you see something\n\ncalled-- I forget-- and-percent plus or something like that. And what's going on there is that\n\nparticular kind of optimization. Because, see, general plus takes an arbitrary number of\narguments.\nSo the most general plus says, oh, if I have an argument list, I'd better cons it up in some\n\nlist and then figure out how many there were or something like that. That's terribly\ninefficient, especially since most of the time you're probably adding two numbers. You don't\n\nwant to really have to cons this argument list. So what you'd like to do is build the code for\nplus with a bunch of entries.\n\n\n\n\n\nSo most of what it's doing is the same. However, there might be a special entry that you'd\ngo to if you knew there were only two arguments. And those you'll put in registers. They\n\nwon't be in an argument list and you won't have to [UNINTELLIGIBLE]. That's how a lot of\nthese things work. OK, let's take a break.\n\n\n\n\n\n[MUSIC PLAYING]\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec10b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 10B: Storage Allocation and Garbage Collection\n\n\n\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH] PROFESSOR:\nWell, there's one bit of mystery left, which I'd like to get rid of right now. And that's that\n\nwe've been blithely doing things like cons assuming there's always another one. That we've\nbeen doing these things like car-ing and cdr-ing and assuming that we had some idea how\n\nthis can be done. Now indeed we said that that's equivalent to having procedures. But that\ndoesn't really solve the problem, because the procedure need all sortsof complicated\n\nmechanisms like environment structures and things like that to work. And those were\nultimately made out of conses in the model that we had, so that really doesn't solve the\n\nproblem.\n\n\n\n\nNow the problem here is the glue the data structure's made out of. What kind of possible\n\nthing could it be? We've been showing you things like a machine, a computer that has a\ncontroller, and some registers, and maybe a stack. And we haven't said anything about, for\n\nexample, larger memory. And I think that's what we have to worry about right now.\n\n\n\n\nBut just to make it perfectly clear that this is an inessential, purely implementational thing,\n\nI'd like to show you, for example, how you can do it all with the numbers. That's an easy\none. Famous fellow by the name of Godel, a logician at the end of the 1930s, invented a\n\nvery clever way of encoding the complicated expressions as numbers. For example-- I'm not\nsaying exactly what Godel's scheme is, because he didn't use words like cons. He had other\n\nkinds of ways of combining to make expressions. But he said, I'm going to assign a number\n\nto every algebraic expression. And the way I'm going to manufacture these numbers is by\ncombining the numbers of the parts.\n\n\n\n\nSo for example, what we were doing our world, we could saythat if objects are represented\n\nby numbers, then cons of x and y could be represented by 2 to the x times 2 to the y.\n\nBecause then we could extract the parts. We could say, for example, that then car of, say, x\nis the number of factors of 2 in x. And of course cdr is the same thing. It's the number of\n\nfactors of 3 in x.\n\n\n\n\nNow this is a perfectly reasonable scheme, except for the fact that the numbers rapidly get\n\nto be much larger in number of digits than the number of protons in the universe. So there's\nno easy way to use this scheme other than the theoretical one. On the other hand, there\n\nare other ways of representing these things. We have been thinking in terms of little boxes.\nWe've been thinking about our cons structures as looking sort of like this. They're little\n\npigeon holes with things in them. And of course we arrange them in little trees. I wish that\nthe semiconductor manufacturers would supply me with something appropriate for this, but\n\nactually what they do supply me with is a linear memory.\n\n\n\n\nMemory is sort of a big pile of pigeonholes, pigeonholes like this. Each of which can hold a\n\ncertain sized object, a fixed size object. So, for example, a complicated list with 25\nelements won't fit in one of these. However, each of these is indexed by an address. So the\n\naddress might be zero here, one here, two here, three here, and so on. That we write these\ndown as numbers is unimportant. What matters is that they're distinct as a way to get to\n\nthe next one. And inside of each of these, we can stuff something into these pigeonholes.\nThat's what memory is like, for those of you who haven't built a computer.\n\n\n\n\n\nNow the problem is how are we going to impose on this type of structure, this nice tree\nstructure. Well it's not very hard, and there have been numerous schemes involved in this.\n\nThe most important one is to say, well assuming that the semiconductor manufacturer\nallows me to arrange my memory so that one of these pigeonholes is big enough to hold the\n\naddress of another I haven't made. Now it actually has to be a little bit bigger because I\n\nhave to also install or store some information as to a tag which describes the kind of thing\nthat's there. And we'll see that in a second. And of course if the semiconductor\n\nmanufacturer doesn't arrange it so I can do that, then of course I can, with some\ncleverness, arrange combinations of these to fit together in that way.\n\n\n\n\n\nSo we're going to have to imagine imposing this complicated tree structure on our nice\nlinear memory. If we look at the first still store, we seea classic scheme for doing that. It's\n\na standard way of representing Lisp structures in a linear memory. What we do is we divide\nthis memory into two parts. An array called the cars, and an array called the cdrs. Now\n\nwhether those happen to be sequential addresses or whatever, it's not important. That's\nsomebody's implementation details. But there are two arrays here. Linear arrays indexed by\n\nsequential indices like this. What is stored in each of these pigeonholes is a typed object.\n\n\n\n\nAnd what we have here are types which begin with letters like p, standing for a pair. Or n,\n\nstanding for a number. Or e, standing for an empty list. The end of the list. And so if we\nwish to represent an object like this, the list beginning with 1, 2 and then having a 3 and a\n\n4 as its second and third elements. A list containing a list as its first part and then two\nnumbers as a second and third parts. Then of course we draw it sort of like this these days,\n\nin box-and-pointer notation. And you see, these are the three cells that have as their car\npointer the object which is either 1, 2 or 3 or 4.\nAnd then of course the 1, 2, the car of this entire structure, is itself a substructure which\n\ncontains a sublist like that. What I'm about to do is put down places which are-- I'm going\nto assign indices. Like this 1, over here, represents the index of this cell. But that pointer\n\nthat we see here is a reference to the pair of pigeonholes in the cars and the cdrs that are\nlabeled by 1 in my linear memory down here.\n\n\n\n\n\nSo if I wish to impose this structure on my linear memory, what I do is I say, oh yes, why\ndon't we drop this into cell 1? I pick one. There's 1. And that says that its car, I'm going to\n\nassign it to be a pair. It's a pair, which is in index 5. And the cdr, which is this one over\nhere, is a pair which I'm going to stick into place 2. p2. And take a look at p2. Oh yes, well\n\np2 is a thing whose car is the number 3, so as you see, an n3. And whose cdr, over here, is\na pair, which lives in place 4. So that's what this p4 is. p4 is a number whose value is 4 in\n\nits car and whose cdr is an empty list right there. And that ends it.\n\n\n\n\nSo this is the traditional way of representing this kind of binary tree in a linear memory.\n\nNow the next question, of course, that we might want to worry about is just a little bit of\nimplementation. That means that when I write procedures of the form assigned a,\n\n[UNINTELLIGIBLE] procedures-- lines of register machine code of the form assigned a, the\n\ncar of [UNINTELLIGIBLE] b, what I really mean is addressing these elements. And so we're\ngoing to think of that as a abbreviation for it.\n\n\n\n\nNow of course in order to write that down I'm going to introduce some sort of a structure\n\ncalled a vector. And we're going to have something which will reference a vector, just so we\n\ncan write it down. Which takes the name of the vector, or the-- I don't think that name is\nthe right word. Which takes the vector and the index, and I have to have a way of setting\n\none of those with something called a vector set, I don't really care. But let's look, for\nexample, at then that kind of implementation of car and cdr.\n\n\n\n\n\nSo for example if I happen to have a register b, which contains the type index of a pair, and\ntherefore it is the pointer to a pair, then I could take the car of that and if I-- write this\n\ndown-- I might put that in register a. What that really is is a representation of the assign to\na, the value of vector reffing-- or array indexing, if you will-- or something, the cars object-\n\n- whatever that is-- with the index, b. And similarly for cdr. And we can do the same thing\nfor assignment to data structures, if we need to do that sort of thing at all. It's not too hard\n\nto build that.\n\n\n\n\nWell now the next question is how are we going to do allocation. And every so often I say I\n\nwant a cons. Now conses don't grow on trees. Or maybe they should. But I have to have\nsome way of getting the next one. I have to have some idea of if their memory is unused\nthat I might want to allocate from. And there are many schemes for doing this. And the\n\nparticular thing I'm showing you right now is not essential. However it's convenient and has\nbeen done many times. One scheme's was called the free list allocation scheme. What that\n\nmeans is that all of the free memory that there is in the world is linked together in a linked\nlist, just like all the other stuff. And whenever you need a free cell to make a new cons, you\n\ngrab the first, one make the free list be the cdr of it, and then allocate that.\n\n\n\n\nAnd so what that looks like is something like this. Here we have the free list starting in 6.\n\nAnd what that is is a pointer-off to say 8. So what it says is, this one is free and the next\none is an 8. This one is free and the next one is in 3, the next one that's free. That one's\n\nfree and the next one is in 0. That one's free and the next one's in 15. Something like that.\nWe can imagine having such a structure.\n\n\n\n\n\nGiven that we have something like that, then it's possible to just get one when you need it.\nAnd so a program for doing cons, this is what cons might turn into. To assign to a register A\n\nthe result of cons-ing, a B onto C, the value in this containing B and the value containing C,\nwhat we have to do is get the current [? type ?] ahead of the freelist, make the free list be\n\nits cdr. Then we have to change the cars to be the thing we're making up to be in A to be\n\nthe B, the thing in B. And we have to make change the cdrs of the thing that's in A to be C.\nAnd then what we have in A is the right new frob, whatever it is. The object that we want.\n\n\n\n\nNow there's a little bit of a cheat here that I haven't told you about, which is somewhere\n\naround here I haven't set that I've the type of the thing that I'm cons -ing up to be a pair,\n\nand I ought to. So there should be some sort of bits here are being set, and I just haven't\nwritten that down. We could have arranged it, of course, for the free lift to be made outof\n\npairs. And so then there's no problem with that. But that sort of-- again, an inessential\ndetail in a way some particular programmer or architect or whatever might manufacture his\n\nmachine or Lisp system.\n\n\n\n\nSo for example, just looking at this, to allocate given that I had already the structure that\n\nyou saw before, supposing I wanted to allocate a new cell, which is going to be\nrepresentation of list one, one, two, where already one two was the car of the list we were\n\nplaying with before. Well that's not so hard. I stored that one and one, so p1 one is the\nrepresentation of this. This is p5. That's going to be the cdr of this. Now we're going to pull\n\nsomething off the free list, but remember the free list started at six. The new free list after\nthis allocation is eight, a free list beginning at eight. And of course in six now we have a\n\nnumber one, which is what we wanted, with its cdr being the pair starting in location five.\nAnd that's no big deal.\nSo the only problem really remaining here is, well, I don't have an infinitely large memory.\n\nIf I do this for a little while, say, for example, supposing it takes me a microsecond to do a\ncons, and I have a million cons memory then I'm only going to run out in a second, and\n\nthat's pretty bad. So what we do to prevent that disaster, that ecological disaster, talk\nabout right after questions. Are there any questions? Yes.\n\n\n\n\n\nAUDIENCE: In the environment diagrams that we were drawing we would use the body of\nprocedures, and you would eventually wind up with things that were no longer useful in that\n\nstructure. How is that represented?\n\n\n\n\nPROFESSOR: There's two problems here. One you were asking is that material becomes\n\nuseless. We'll talk about that in a second. That has to do with how to prevent ecological\ndisasters. If I make a lot of garbage I have to somehow be able to clean up after myself.\n\nAnd we'll talk about that in a second. The other question you're asking is how you represent\nthe environments, I think.\n\n\n\n\n\nAUDIENCE: Yes.\n\n\n\n\nPROFESSOR: OK. And the environment structures can be represented in arbitrary ways.\n\nThere are lots of them. I mean, here I'm just telling you about list cells. Of course every\nreal system has vectors of arbitrary length as well as the vectors of length, too, which\n\nrepresent list cells. And the environment structures that one uses in a professionally written\nLisp system tend to be vectors which contain a number of elements approximately equal to\n\nthe number of arguments-- a little bit more because you need certain glue. So remember,\nthe environment [UNINTELLIGIBLE] frames. The frames are constructed by applying a\n\nprocedure. In doing so, an allocation is made of a place which is the number of arguments\nlong plus [? unglue ?] that gets linked into a chain. It's just like algol at that level. There\n\nany other questions? OK. Thank you, and let's take a short break.\n\n\n\n\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n\n\n\n\nPROFESSOR: Well, as I just said, computer memories supplied by the semiconductor\nmanufacturers are finite. And that's quite a pity. It might not always be that way. Just for a\n\nquick calculation, you can see that it's possible that if [? memory ?] prices keep going at the\nrate they're going that if you still took a microsecond second to do a cons, then -- first of all,\n\neverybody should know that there's about pi times ten to the seventh seconds in a year.\nAnd so that would be ten to the seventh plus ten to the sixth is ten to the thirteenth. So\nthere's maybe ten to the fourteenth conses in the life of a machine. If there was ten to the\n\nfourteenth words of memory on your machine, you'd never run out.\n\n\n\n\nAnd that's not completely unreasonable. Ten to the fourteenth is not a very large number. I\n\ndon't think it is. But then again I like to play with astronomy. It's at least ten to the\neighteenth centimeters between us and the nearest star. But the thing I'm about to worry\n\nabout is, at least in the current economic state of affairs, ten to the fourteenth pieces of\nmemory is expensive. And so I suppose what we have to do is make do with much smaller.\n\nMemories\n\n\n\n\nNow in general we want to have an illusion of infinity. All we need to do is arrange it so that\n\nwhenever you look, the thing is there. That's really an important idea. A person or a\ncomputer lives only a finite amount of time and can only take a finite number of looks at\n\nsomething. And so you really only need a finite amount of stuff. But you have to arrange it\nso no matter how much there is, how much you really claim there is, there's always enough\n\nstuff so that when you take a look, it's there. And so you only need a finite amount.\n\n\n\n\nBut let's see. One problem is, as was brought up, that there are possible ways that there is\n\nlots of stuff that we make that we don't need. And we could recycle the material out of\nwhich its made. An example is the fact that we're building environment structures, and we\n\ndo so every time we call a procedure. We have built in it a environment frame. That\nenvironment frame doesn't necessarily have a very long lifetime. Its lifetime, meaning its\n\nusefulness, may exist only over the invocation of the procedure. Or if the procedure exports\n\nanother procedure by returning it as a value and that procedure is defined inside of it, well\nthen the lifetime of the frame of the outer procedure still is only the lifetime of the\n\nprocedure which was exported.\n\n\n\n\nAnd so ultimately, a lot of that is garbage. There are other ways of producing garbage as\n\nwell. Users produce garbage. An example of user garbage is something like this. If we write\na program to, for example, append two lists together, well one way to do it is to reverse the\n\nfirst list onto the empty list and reverse that onto the second list. Now that's not terribly\nbad way of doing it. And however, the intermediate result, which is the reversal of the first\n\nlist as done by this program, is never going to be accessed ever again after it's copied back\non to the second. It's an intermediate result. It's going to be hard to ever see how anybody\n\nwould ever be able to access it. In fact, it will go away.\n\n\n\n\nNow if we make a lot of garbage like that, and we should be allowed to, then there's got to\n\nbe some way to reclaim that garbage. Well, what I'd like to tell you about now is a very\nclever technique whereby a Lisp system can prove a small theorem every so often on the [?\nforum, ?] the following piece of junk will never be accessed again. It can have no affect on\n\nthe future of the computation. It's actually based on a very simple idea.\n\n\n\n\nWe've designed our computers to look sort of like this. There's some data path, which\n\ncontains the registers. There are things like x, and env, and val, and so on. And there's one\nhere called stack, some sort which points off to a structure somewhere, which is the stack.\n\nAnd we'll worry about that in a second. There's some finite controller, finite state machine\ncontroller. And there's some control signals that go this way and predicate results that come\n\nthis way, not the interesting part.\n\n\n\n\nThere's some sort of structured memory, which I just told you how to make, which may\n\ncontain a stack. I didn't tell you how to make things of arbitrary shape, only pairs. But in\nfact with what I've told you can simulate a stack by a big list. I don't plan to do that, it's not\n\na nice way to do it. But we could have something like that. We have all sorts of little data\nstructures in here that are hooked together in funny ways. They connect to other things.\n\nAnd so on. And ultimately things up there are pointers to these. The things that are in the\nregisters are pointers off to the data structures that live in this Lisp structure memory.\n\n\n\n\n\nNow the truth of the matter is that the entire consciousness of this machine is in these\nregisters. There is no possible way that the machine, if done correctly, if built correctly, can\n\naccess anything in this Lisp structure memory unless the thing in that Lisp structure\nmemory is connected by a sequence of data structures to the registers. If it's accessibleby\n\nlegitimate data structure selectors from the pointers that are stored in these registers.\n\nThings like array references, perhaps. Or cons cell references, cars and cdrs.\n\n\n\n\nBut I can't just talk about a random place in this memory, because I can't get to it. These\nare being arbitrary names I'm not allowed to count, at least as I'm evaluating expressions.\n\nIf that's the case then there's a very simple theorem to be proved. Which is, if I start with\n\nall lead pointers that are in all these registers and recursively chase out, marking all the\nplaces I can get to by selectors, then eventually I mark everything they can be gotten to.\n\nAnything which is not so marked is garbage and can be recycled. Very simple. Cannot affect\nthe future of the computation.\n\n\n\n\nSo let me show you that in a particular example. Now that means I'm going to have to\n\nappend to my description of the list structure a mark. And so here, for example, is a Lisp\n\nstructured memory. And in this Lisp structured memory is a Lisp structure beginning ina\nplace I'm going to call-- this is the root. Now it doesn't really have to have a root. It could\n\nbe a bunch of them, like all the registers. But I could cleverly arrange it so all the registers,\nall the things that are in old registers are also at the right moment put into this root\n\nstructure, and then we've got one pointer to it. I don't really care.\n\n\n\n\nSo the idea is we're going to cons up stuff until our free list is empty. We've run out of\n\nthings. Now we're going to do this process of proving the theorem that a certain percentage\nof the memory has got crap in it. And then we're going to recycle that to grow new trees, a\n\nstandard use of such garbage.\n\n\n\n\nSo in any case, what do we have here? Well we have some data structure which starts out\n\nover here one. And in fact it has a car in five, and its cdr is in two. And all the marks start\nout at zero. Well let's start marking, just to play this game. OK. So for example, since I can\n\naccess one from the root I will mark that. Let me mark it. Bang. That's marked. Now since I\nhave a five here I can go to five and see, well I'll mark that. Bang. That's useful stuff.\n\n\n\n\n\nBut five references as a number in its car, I'm not interested in marking numbers but its cdr\nis seven. So I can mark that. Bang. Seven is the empty list, the only thing that references,\n\nand it's got a number in its car. Not interesting. Well now let's go back here. I forgot about\nsomething. Two. See in other words, if I'm looking at cell one, cell one contains a two right\n\nover here. A reference to two. That means I should go mark two. Bang. Two contains a\nreference to four. It's got a number in its car, I'm not interested in that, so I'm going to go\n\nmark that. Four refers to seven through its car, and is empty in its cdr, but I've already\nmarked that one so I don't have to mark it again. This is all the accessible structure from\n\nthat place. Simple recursive mark algorithm.\n\n\n\n\nNow there are some unhappinesses about that algorithm, and we can worry about that a\n\nsecond. But basically you'll see that all the things that have not been marked are places\nthat are free, and I could recycle. So the next stage after that is going to be to scan through\n\nall of my memory, looking for things that are not marked. Every time I come across a\n\nmarked thing I unmark it, and every time I come across an unmarked thing I'm going to\nlink it together in my free list. Classic, very simple algorithm.\n\n\n\n\nSo let's see. Is that very simple? Yes it is. I'm not going to go through the code in any\n\ndetail, but I just want to show you about how long it is. Let's look at the mark phase. Here's\nthe first part of the mark phase. We pick up the root. We're going to use that as a recursive\n\nprocedure call. We're going to sweep from there, after when we're done with marking. And\n\nthen we're going to do a little couple of instructions that do this checking out on the marks\nand changing the marks and things like that, according to the algorithm I've just shown\n\nyou. It comes out here. You have to mark the cars of things and you also have to be able to\nmark the cdrs of things. That's the entire mark phase.\nI'll just tell you a little story about this. The old DEC PDP-6 computer, this was the way that\nthe mark-sweep garbage collection, as it was, was written. The program was so small that\n\nwith the data that it needed, with the registers that it needed to manipulate the memory, it\nfit into the fast registers of the machine, which were 16. The whole program. And you could\n\nexecute instructions in the fast registers. So it's an extremely small program, and it could\n\nrun very fast.\n\n\n\n\nNow unfortunately, of course, this program, because the fact that it's recursive in the way\nthat you do something first and then you do something after that, you have to work on the\n\ncars and then the cdrs, it requires auxiliary memory. So Lisp systems-- those requires a\n\nstack for marking. Lisp systems that are built this way have a limit to the depth of rec ursion\nyou can have in data structures in either the car or the cdr, and that doesn't work very\n\nnicely.\n\n\n\n\nOn the other hand, you never notice it if it's big enough. And that's certainly been the case\n\nfor most Maclisp, for example, which ran Macsyma where you could deal with expressions of\nthousands of elements long. These are algebraic expressions with thousand of terms. And\n\nthere's no problem with that. Such, the garbage collector does work.\n\n\n\n\nOn the other hand, there's a very clever modification to this algorithm, which I will not\n\ndescribe, by Peter Deutsch and Schorr and Waite-- Herb Schorr from IBM and Waite, who I\ndon't know. That algorithm allows you to build-- you do can do this without auxiliary\n\nmemory, by remembering as you walk the data structureswhere you came from by\nreversing the pointers as you go down and crawling up the reverse pointers as you go up.\n\nIt's a rather tricky algorithm. The first time you write it-- or in fact, the first three times you\nwrite it it has a terrible bug in it. And it's also rather slow, because it's complicated. It takes\n\nabout six times as many memory references to do the sorts of things that we're talking\nabout.\n\n\n\n\n\nWell now once I've done this marking phase, and I get into a position where things look like\nthis, let's look-- yes. Here we have the mark done, just as I did it. Now we have to perform\n\nthe sweep phase. And I described to you what this sweep is like. I'm going to walk down\nfrom one end of memory or the other, I don't care where, scanning every cell that's inthe\n\nmemory. And as I scan these cells, I'm going to link them together, if they are free, into the\nfree list. And if they're not free, I'm going to unmark them so the marks become zero.\nAnd in fact what I get-- well the program is not very complicated. It looks sort of like this --\n\nit's a little longer. Here's the first piece of it. This one's coming down from the top of\nmemory. I don't want you to try to understand this at this point. It's rather simple. It's a\n\nvery simple algorithm, but there's pieces of it that just sort of look like this. They're all sort\nof obvious. And after we've done the sweep, we get an answer that looks like that.\n\n\n\n\n\nNow there are some disadvantages with mark-sweep algorithms of this sort. Serious ones.\nOne important disadvantage is that your memories get larger and larger. As you say,\n\naddress spaces get larger and larger, you're willing to represent more and more stuff, then\nit gets very costly to scan all of memory. What you'd really like to do is only scan useful\n\nstuff. It would even be better if you realized that some stuff was known to be good and\nuseful, and you don't have to look at it more than once or twice. Or very rarely. Whereas\n\nother stuff that you're not so sure about, you can look at more detail every time you want\n\nto do this, want to garbage collect.\n\n\n\n\nWell there are algorithms that are organized in this way. Let me tell you about a famous old\nalgorithm which allows you only look at the part of memory which is known to be useful.\n\nAnd which happens to be the fastest known garbage collector algorithm. This is the Minsky-\n\nFeinchel-Yochelson garbage collector algorithm. It was invented by Minsky in 1961 or '60 or\nsomething, for the RLE PDP-1 Lisp, which had 4,096 words of list memory, and a drum. And\n\nthe whole idea was to garbage collect this terrible memory.\n\n\n\n\nWhat Minsky realized was the easiest way to do this is to scan the memory in the same\n\nsense, walking the good structure, copying it out into the drum, compacted. And then when\nwe were done copying it all out, then you swap that back into your memory. Now whether\n\nor you not use a drum, or another piece of memory, or something like that isn't important.\nIn fact, I don't think people use drums anymore for anything.\n\n\n\n\n\nBut this algorithm basically depends upon having about twice as much address space as\nyou're actually using. And so what you have is some, initially, some mixture of useful data\n\nand garbage. So this is called fromspace. And this is a mixture of crud. Some of it's\nimportant and some of it isn't.\n\n\n\n\nNow there's another place which is hopefully big enough, if we recall, tospace, which is\n\nwhere we're copying to. And what happens is-- and I'm not going to go through this detail.\n\nIt's in our book quite explicitly. There's a root point where you start from. And the ide  a is\nthat you start with the root. You copy the first thing you see, the first thing that the root\n\npoints at, to the beginning of tospace. The first thing is a pair or something like, a data\nstructure.\nYou then also leave behind a broken heart saying, I moved this object from here to here,\ngiving the place where it moved to. This is called a broken heart because a friend of mine\n\nwho implemented one of these in 1966 was a very romantic character and called it a broken\nheart.\n\n\n\n\n\nBut in any case, the next thing you do is now you have a new free pointer which is here,\nand you start scanning. You scan this data structure you just copied. And every time you\n\nencounter a pointer in it, you treat it as if it was the root pointer here. Oh, I'm sorry. The\nother thing you do is you now move the root pointer to there.\n\n\n\n\n\nSo now you scan this, and everything you see you treat as it were the root pointer. So if\nyou see something, well it points up into there somewhere. Is it pointing at a thing which\n\nyou've not copied yet? Is there a broken heart there? If there's a broken heart there and it's\nsomething you have copied, you've just replaced this pointer with the thing a broken heart\n\npoints at. If this thing has not been copied, you copy it to the next place over here. Move\n\nyour free pointer over here, and then leave a broken heart behind and scan.\n\n\n\n\nAnd eventually when the scant pointer hits the free pointer, everything in memory has been\ncopied. And then there's a whole bunch of empty space up here, which you could either\n\nmake into a free list, if that's what you want to do. But generally you don't in this kind of\n\nsystem. In this system you sequentially allocate your memory. That is a very, very nice\nalgorithm, and sort of the one we use in the scheme that you've been using. And it's\n\nexpected-- I believe no one has found a faster algorithm than that.\n\n\n\n\nThere are very simple modifications to this algorithm invented by Henry Baker which allow\n\none to run this algorithm in real time, meaning you don't have to stop to garbage collect.\nBut you could interleave the consing that the machine does when its running with steps of\n\nthe garbage collection process, so that the garbage collector's distributed, and the machine\ndoesn't have to stop, and garbage collecting can start.\n\n\n\n\nOf course in the case of machines with virtual memory where a lot of it is in inaccessible\n\nplaces, this becomes a very expensive process. And there have been numerous attempts to\n\nmake this much better. There is a nice paper, for those ofyou who are interested, by Moon\nand other people which describes a modification to the incremental Minsky -Feinchel-\n\nYochelson algorithm, and modification the Baker algorithm which is more efficient for virtual\nmemory systems.\nWell I think now the mystery to this is sort of gone. And I'd like to see if there are any\nquestions. Yes.\n\n\n\n\n\nAUDIENCE: I saw one of you run the garbage collector on the systems upstairs, and it\nseemed to me to run extremely fast. Did the whole thing take-- does it sweep through all of\n\nmemory?\n\n\n\n\nPROFESSOR: No. It swept through exactly what was needed to copy the useful structure.\n\nIt's a copying collector. And it is very fast. On the whole, I suppose to copy -- in a Bobcat--\nto copy, I think, a three megabyte thing or something is less than a second, real time.\n\nReally, these are very small programs. One thing you should realise is that garbage\ncollectors have to be small. Not because they have to be fast, but because no one can\n\ndebug a complicated garbage collector. A garbage collector, if it doesn't work, will trash\nyour memory in such a way that you cannot figure out what the hell happened. You need an\n\naudit trail. Because it rearranges everything, and how do you know what happened there?\n\n\n\n\nSo this is the only kind of program that it really, seriously matters if you stare at it long\n\nenough so you believe that it works. And sort of prove it to yourself. So there's no way to\ndebug it. And that takes it being small enough so you can hold it in your head. Garbage\n\ncollectors are special in this way. So every reasonable garbage collector has gotten small,\n\nand generally small programs are fast. Yes.\n\n\n\n\nAUDIENCE: Can you repeat the name of this technique once again?\n\n\n\n\nPROFESSOR: That's the Minsky-Feinchel-Yochelson garbage collector.\n\n\n\n\n\nAUDIENCE: You got that?\n\n\n\n\nPROFESSOR: Minsky invented it in '61 for the RLE PDP-1. A version of it was developed and\nelaborated to be used in Multics Maclisp by Feinchel and Yochelson in somewhere around\n\n1968 or '69.\n\n\n\n\nOK. Let's take a break.\n[MUSIC: \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n\n\n\nPROFESSOR: Well we've come to the end of this subject, and we've already shown you a\n\nuniversal machine which is down to evaluator. It's down to the level of detail you could\nimagine you could make one. This is a particular implementation of Lisp, built on one of\n\nthose scheme chips that was talked about yesterday, sitting over here. This is mostly\ninterface to somebody's memory with a little bit of timing and other such stuff. But this\n\nfellow actually ran Lisp at a fairly reasonable rate, as interpretive. It ran Lisp as fast as a\nDEC PDP-10 back in 1979. And so it's gotten pretty hardware. Pretty concrete.\n\n\n\n\n\nWe've also downed you a bit with the things you can compute. But is it the case that th ere\nare things we can't compute? And so I'd like to end this with showing you some things that\n\nyou'd like be able to compute that you can't. The answer is yes, there are things you can't\ncompute.\n\n\n\n\n\nFor example, something you'd really like is-- if you're writing [UNINTELLIGIBLE], you'd like\na program that would check that the thing you're going to do will work. Wouldn't that be\n\nnice? You'd like something that would catch infinite loops, for example, in programs that\nwere written by users. But in general you can't write such a program that will read any\n\nprogram and determine whether or not it's an infinite loop.\n\n\n\n\nLet me show you that. It's a little bit of a minor mathematics. Let's imagine that we just had\n\na mathematical function before we start. And there isone, called s, which takes a procedure\nand its argument, a. And what s does is it determines whether or not it's safe to run p on a.\n\nAnd what I mean by that is this: it's true if p applied to a will converge to a value without an\n\nerror. And it's false if p of a loops forever or makes an error.\n\n\n\n\nNow that's surely a function. There is some for every procedure and for every argument you\ncould give it that is either true or false that it converges without making an error. And you\n\ncould make a giant table of them. But the question is, can you write a procedure that\ncompute the values of this function? Well let's assume that we can.\n\n\n\n\n\nSuppose that we have a procedure called \"safe\" that computes the value of s. Now I'm\ngoing to show you by several methods that you can't do this. The easiest one, or the first\n\none, let's define a procedure called diag1. Given that we have safe, we can define diag1 to\nbe the procedure of one argument, p, which has the following properties. If if it's safe to\napply p to itself, then I wish to have an infinite loop. Otherwise I'm going to return 3.\n\nRemember it was 42. What's the answer to the big question? Where of course we know\nwhat an infinite loop is. Infinite loop, to be a procedure of no arguments, which is that nice\n\nlambda calculus loop. Lambda of x, x of x, applied to lambda of x, x of x. So there's nothing\nleft to the imagination here.\n\n\n\n\n\nWell let's see what the story is. I'm supposing it's the case that we worry about the\nprocedure called diag1 applied to diag1. Well what could it possibly be? Well I don't know.\n\nWe're going to substitute diag1 for p in the body here. Well is it safe to compute diag1 of\ndiag1? I don't know. There are two possibilities. If it's safe to compute diag1 of diag1 that\n\nmeans it shouldn't loop. That means I go to here, but then I produce an infinite loop. So it\ncan't be safe. But if it's not safe to compute diag1 of diag1 then the answer to this is 3. But\n\nthat's diag1 of diag1, so it had to be safe.\n\n\n\n\nSo therefore by contradiction you cannot produce safe. For those of you who were boggled\n\nby that one I'm going to say it again, in a different way. Listen to one more alternative.\nLet's define diag2. These are named diag because of Cantor's diagonal argument. These are\n\ninstances of a famous argument which was originally used by Cantor in the late part of the\n\nlast century to prove that the real numbers were not countable, that there are too many\nreal numbers to be counted by integers. That there are more points on a line, for example,\n\nthan there are counting numbers. It may or may not be obvious, and I don't want to get\ninto that now.\n\n\n\n\n\nBut diag2 is again a procedure of one argument p. It's almost the same as the previous one,\nwhich is, if it's safe to compute p on p, then I'm going to produce-- then I want to compute\n\nsome other things other than p of p. Otherwise I'm going to put out false. Where other then\nit says, whatever p of p, I'm going to put out something else.\n\n\n\n\n\nI can give you an example of a definition of other than which I think works. Let's see. Yes.\nWhere other than be a procedure of one argument x which says, if its eq x to, say, quote a,\n\nthen the answer is quote b. Otherwise it's quote a. That always produces something which\nis not what its argument is. That's all it is. That's all I wanted.\n\n\n\n\nWell now let's consider this one, diag2 of diag2. Well look. This only does something\n\ndangerous, like calling p of p, if it's safe to do so. So if safe defined at all, if you can define\n\nsuch a procedure, safe, then this procedure is always defined and thereforesafe on any\ninputs. So diag2 of diag2 must reduce to other than diag2 of diag2. And that doesn't make\n\nsense, so we have a contradiction, and therefore we can't define safe.\nI just waned to do that twice, slightly differently, so you wouldn't feel that the first one was\na trick. They may be both tricks, but they're at least slightly different.\n\n\n\n\n\nSo I suppose that pretty much wraps it up. I've just proved what we call the halting\ntheorem, and I suppose with that we're going to halt. I hope you have a good time. Are\n\nthere any questions? Yes.\n\n\n\n\nAUDIENCE: What is the value of s of diag1?\n\n\n\n\nPROFESSOR: Of what?\n\n\n\n\n\nAUDIENCE: S of diag1. If you said s is a function and we can [INTERPOSING VOICES]\n\n\n\n\nPROFESSOR: Oh, I don't know. I don't know. It's a function, but I don't know how to\n\ncompute it. I can't do it. I'm just a machine, too. Right? There's no machine that in\nprinciple-- it might be that in that particular case you just asked, with some thinkin g I could\n\nfigure it out. But in general I can't compute the value of s any better than any other\nmachine can. There is such a function, it's just that no machine can be built to compute it.\n\n\n\n\n\nNow there's a way of saying that that should not be surprising. Going through this-- I mean,\nI don't have time to do this here, but the number of functions is very large. If there's a\n\ncertain number of answers possible and a certain number of inputs possible, then it's the\nnumber of answers raised to the number inputs is the number of possible functions. On one\n\nvariable. Now that's always bigger than the thing you're raising to, the exponent. The\nnumber of functions is larger than the number of programs that one can write, by an infinity\n\ncounting argument. And it's much larger. So there must be a lot of functions that can't be\n\ncomputed by programs.\n\n\n\n\nAUDIENCE: A few moments ago you were talking about specifications and automatic\ngeneration of solutions. Do you see any steps between specifications and solutions?\n\n\n\n\n\nPROFESSOR: Steps between. You mean, you're saying, how you go about constructing\ndevices given that have specifications for the device? Sure.\nAUDIENCE: There's a lot of software engineering that goes through specifications through\nmany layers of design and then implementation.\n\n\n\n\n\nPROFESSOR: Yes?\n\n\n\n\nAUDIENCE: I was curious if you think that's realistic.\n\n\n\n\nPROFESSOR: Well I think that some of it's realistic and some of it isn't. I mean, surely if I\n\nwant to build an electrical filter and I have a rather interesting possibility. Supposing I want\nto build a thing that matches some power output to the radio transmitter, to some antenna.\n\nAnd I'm really out of this power-- it's output tube out here. And the problem is that they\n\nhave different impedances. I want them to match the impedances. I also want to make a\nfilter in there which is going to get rid of some harmonic radiation.\n\n\n\n\nWell one old-fashioned technique for doing this is called image impedances, or something\n\nlike that. And what you do is you say you have a basic module called an L-section. Looks\n\nlike this. If I happen to connect this to some resistance, r, and if I make this impedance x,\nxl, and if it happens to be q times r, then this produces a low pass filter with a q square plus\n\none impedance match. Just what I need. Because now I can take two of these, hook them\ntogether like this. OK, and I take another one and I'll hook them together like that. And I\n\nhave two L-sections hooked together. And this will step the impedance down to one that I\nknow, and this will step it up to one I know. Each of these is a low pass filter getting rid of\n\nsome harmonics. It's good filter, it's called a pie -section filter. Great.\n\n\n\n\nExcept for the fact that in doing what I just did, I've made a terrible inefficiency in this\n\nsystem. I've made two coils where I should have made one. And the problem with most\nsoftware engineering art is that there's no mechanism, other than peephole optimization\n\nand compilers, for getting rid of the redundant parts that are constructed when doing top\ndown design. It's even worse, there are lots of very important structures that you can't\n\nconstruct at all this way.\n\n\n\n\nSo I think that the standard top down design is a rather shallow business. Doesn't really\n\ncapture what people want to do in design. I'll give you another electrical example. Electrical\nexamples are so much clearer than computational examples, because computation\n\nexamples require a certain degree of complexity to explain them. But one of my favorite\nexamples in the electrical world is how would I ever come up with the output stage of this\ninter-stage connection in an IF amplifier. It's a little transistor here, and let's see. Well I'm\n\ngoing to have a tank, and I'm going to hook this up to, say, I'm going to link-couple that to\nthe input of the next stage.\n\n\n\n\n\nHere's a perfectly plausible plan-- well except for the fact that since I put that going up I\nshould make that going that way. Here's a perfectly plausible plan for a -- no I shouldn't. I'm\n\ndumb. Excuse me. Doesn't matter. The point is [UNINTELLIGIBLE] plan for a couple\n[UNINTELLIGIBLE] stages together. Now what the problem is is what's this hierarchically?\n\nIt's not one thing. Hierarchically it doesn't make any sense at all. It's the inductance of a\ntuned circuit, it's the primary of a transformer, and it'salso the DC path by which bias\n\nconditions get to the collector of that transistor. And there's no simple top -down design\nthat's going to produce a structure like that with so many overlapping uses for a particular\n\nthing.\n\n\n\n\nPlaying Scrabble, where you have to do triple word scores, or whatever, is not so easy in\n\ntop-down design strategy. Yet most of real engineering is based on getting the most oomph\nfor effort. And that's what you're seeing here. Yeah?\n\n\n\n\n\nAUDIENCE: Is this the last question?\n\n\n\n\n[LAUGHTER]\n\n\n\n\nPROFESSOR: Apparently so. Thank you.\n\n\n\n\n\n[APPLAUSE]\n\n\n\n\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec1a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 1A: Overview and Introduction to Lisp\n\n\n\n[MUSIC PLAYING] PROFESSOR: I'd like to welcome you to this course on computer science.\nActually, that's a terrible way to start. Computer science is a terrible name for this business.\n\nFirst of all, it's not a science. It might be engineering or it might be art, but we'll actually\nsee that computer so-called science actually has a lot in common with magic, and we'll see\n\nthat in this course.\n\n\n\n\nSo it's not a science. It's also not really very much about computers. And it's not about\n\ncomputers in the same sense that physics is not really about particle accelerators, and\nbiology is not really about microscopes and petri dishes. And it's not about computers in the\n\nsame sense that geometry is not really about using surveying instruments.\n\n\n\n\nIn fact, there's a lot of commonality between computer science and geometry. Geometry,\n\nfirst of all, is another subject with a lousy name. The name comes from Gaia, meaning the\nEarth, and metron, meaning to measure. Geometry originally meant measuring the Earth or\n\nsurveying.\n\n\n\n\nAnd the reason for that was that, thousands of years ago, the Egyptian priesthood\n\ndeveloped the rudiments of geometry in order to figure out how to restore the boundaries of\nfields that were destroyed in the annual flooding of the Nile. And to the Egyptians who did\n\nthat, geometry really was the use of surveying instruments.\n\n\n\n\nNow, the reason that we think computer science is about computers is pretty much the\n\nsame reason that the Egyptians thought geometry was about surveying instruments. And\nthat is, when some field is just getting started and you don't really understand it very well,\n\nit's very easy to confuse the essence of what you're doing with the tools that you use. And\nindeed, on some absolute scale of things, we probably know less about the essence of\n\ncomputer science than the ancient Egyptians really knew about geometry.\n\n\n\n\nWell, what do I mean by the essence of computer science? What do I mean by the essence\n\nof geometry? See, it's certainly true that these Egyptians went off and used surveying\ninstruments, but when we look back on them after a couple of thousand years, we say, gee,\n\nwhat they were doing, the important stuff they were doing, was to begin to formalize\nnotions about space and time, to start a way of talking about mathematical truths formally.\nThat led to the axiomatic method. That led to sort of all of modern mathematics, figuring\n\nout a way to talk precisely about so-called declarative knowledge, what is true.\n\n\n\n\nWell, similarly, I think in the future people will look back and say, yes, those primitives in\n\nthe 20th century were fiddling around with these gadgets called computers, but really what\nthey were doing is starting to learn how to formalize intuitions about process, how to do\n\nthings, starting to develop a way to talk precisely about how-to knowledge, as opposed to\ngeometry that talks about what is true.\n\n\n\n\n\nLet me give you an example of that. Let's take a look. Here is a piece of mathematics that\nsays what a square root is. The square root of X is the number Y, such that Y squared is\n\nequal to X and Y is greater than 0. Now, that's a fine piece of mathematics, but just telling\nyou what a square root is doesn't really say anything about how you might go out and find\n\none.\n\n\n\n\nSo let's contrast that with a piece of imperative knowledge, how you might go out and find a\n\nsquare root. This, in fact, also comes from Egypt, not ancient, ancient Egypt. This is an\nalgorithm due to Heron of Alexandria, called how to find a square root by successive\n\naveraging. And what it says is that, in order to find a square root, you make a guess, y ou\nimprove that guess-- and the way you improve the guess is to average the guess and X\n\nover the guess, and we'll talk a little bit later about why that's a reasonable thing -- and you\nkeep improving the guess until it's good enough.\n\n\n\n\n\nThat's a method. That's how to do something as opposed to declarative knowledge that says\nwhat you're looking for. That's a process. Well, what's a process in general? It's kind of hard\n\nto say. You can think of it as like a magical spirit that sort of lives in the computer and does\nsomething. And the thing that directs a process is a pattern of rules called a procedure.\n\n\n\n\n\nSo procedures are the spells, if you like, that control these magical spirits that are the\nprocesses. I guess you know everyone needs a magical language, and sorcerers, real\n\nsorcerers, use ancient Arcadian or Sumerian or Babylonian or whatever. We're going to\nconjure our spirits in a magical language called Lisp, which is a language designed for\n\ntalking about, for casting the spells that are procedures to direct the processes.\n\n\n\n\nNow, it's very easy to learn Lisp. In fact, in a few minutes, I'm going to teach you,\n\nessentially, all of Lisp. I'm going to teach you, essentially, all of the rules. And you shouldn't\nfind that particularly surprising. That's sort of like saying it's very easy to learn the rules of\nchess. And indeed, in a few minutes, you can tell somebody the rules of chess. But of\n\ncourse, that's very different from saying you understand the implications of those rules and\nhow to use those rules to become a masterful chess player.\n\n\n\n\n\nWell, Lisp is the same way. We're going to state the rules in a few minutes, and it'll be very\neasy to see. But what's really hard is going to be the implications of those rules, how you\n\nexploit those rules to be a master programmer. And the implications of those rules are\ngoing to take us the, well, the whole rest of the subject and, of course, way beyond.\n\n\n\n\n\nOK, so in computer science, we're in the business of formalizing this sort of how-to\nimperative knowledge, how to do stuff. And the real issues of computer science are, of\n\ncourse, not telling people how to do square roots. Because if that was all it was, there\nwouldn't be no big deal. The real problems come when we try to build very, very large\n\nsystems, computer programs that are thousands of pages long, so long that nobody can\nreally hold them in their heads all at once.\n\n\n\n\n\nAnd the only reason that that's possible is because there are techniques for controlling the\ncomplexity of these large systems. And these techniques that are controlling complexity are\n\nwhat this course is really about. And in some sense, that's really what computer science is\nabout.\n\n\n\n\n\nNow, that may seem like a very strange thing to say. Because after all, a lot of people\nbesides computer scientists deal with controlling complexity. A large airliner is an extremely\n\ncomplex system, and the aeronautical engineers who design that are dealing with immense\ncomplexity. But there's a difference between that kind of complexity and what we deal with\n\nin computer science.\n\n\n\n\nAnd that is that computer science, in some sense, isn't real. You see, when an engineer is\n\ndesigning a physical system, that's made out of real parts. The engineers who worry about\nthat have to address problems of tolerance and approximation and noise in the system. So\n\nfor example, as an electrical engineer, I can go off and easily build a one-stage amplifier or\na two-stage amplifier, and I can imagine cascading a lot of them to build a million -stage\n\namplifier. But it's ridiculous to build such a thing, because long before the millionth stage,\nthe thermal noise in those components way at the beginning is going to get amplified and\n\nmake the whole thing meaningless.\nComputer science deals with idealized components. We know as much as we want about\n\nthese little program and data pieces that we're fitting things together. We don't have to\nworry about tolerance. And that means that, in building a large program, there's not all that\n\nmuch difference between what I can build and what I can imagine, because the parts are\nthese abstract entities that I know as much as I want.\n\n\n\n\n\nI know about them as precisely as I'd like. So as opposed to other kinds of engineering,\nwhere the constraints on what you can build are the constraints of physical systems, th e\n\nconstraints of physics and noise and approximation, the constraints imposed in building\nlarge software systems are the limitations of our own minds.\n\n\n\n\n\nSo in that sense, computer science is like an abstract form of engineering. It's the kind of\nengineering where you ignore the constraints that are imposed by reality. Well, what are\n\nsome of these techniques? They're not special to computer science. First technique, which is\nused in all of engineering, is a kind of abstraction called black- box abstraction. Take\n\nsomething and build a box about it.\n\n\n\n\nLet's see, for example, if we looked at that square root method, I might want to take that\n\nand build a box. That sort of says, to find the square root of X. And that might be a whole\ncomplicated set of rules. And that might end up being a kind of thing where I can put in,\n\nsay, 36 and say, what's the square root of 36? And out comes 6.\n\n\n\n\nAnd the important thing is that I'd like to design that so that if George comes along and\n\nwould like to compute, say, the square root of A plus the square root of B, he can take this\nthing and use it as a module without having to look inside and build something that looks\n\nlike this, like an A and a B and a square root box and another square root box and then\nsomething that adds that would put out the answer.\n\n\n\n\n\nAnd you can see, just from the fact that I want to do that, is from George's point of view,\nthe internals of what's in here should not be important. So for instance, it shouldn't matter\n\nthat, when I wrote this, I said I want to find the square root of X. I could have said the\nsquare root of Y, or the square root of A, or anything at all. That's the fundamental notion of\n\nputting something in a box using black-box abstraction to suppress detail.\n\n\n\n\nAnd the reason for that is you want to go off and build bigger boxes. Now, there's another\n\nreason for doing black-box abstraction other than you want to suppress detail for building\nbigger boxes. Sometimes you want to say that your way of doing something, your how -to\nmethod, is an instance of a more general thing, and you'd like your language to be able to\n\nexpress that generality.\n\n\n\n\nLet me show you another example sticking with square roots. Let's go back and take\n\nanother look at that slide with the square root algorithm on it. Remember what that says.\nThat says, in order to do something, I make a guess, and I improve that guess, and I sort\n\nof keep improving that guess. So there's the general strategy of, I'm looking for something,\nand the way I find it is that I keep improving it. Now, that's a particular case of another kind\n\nof strategy for finding a fixed point of something.\n\n\n\n\nSo you have a fixed point of a function. A fixed point of a function is something, is a value.\n\nA fixed point of a function F is a value Y, such that F of Y equals Y. And the way I might do\nthat is start with a guess. And then if I want something that doesn't change when I keep\n\napplying F, is I'll keep applying F over and over until that result doesn't change very much.\nSo there's a general strategy.\n\n\n\n\n\nAnd then, for example, to compute the square root of X, I can try and find a fixed point of\nthe function which takes Y to the average of X/Y. And the idea that is that if I really had Y\n\nequal to the square root of X, then Y and X/Y would be the same value. They'd both be the\nsquare root of X, because X over the square root of X is the square root of X.\n\n\n\n\n\nAnd so the average if Y were equal to the square of X, then the average wouldn't change.\nSo the square root of X is a fixed point of that particular function. Now, what I'd like to\n\nhave, I'd like to express the general strategy for finding fixed points. So what I might\nimagine doing, is to find, is to be able to use my language to define a box that says \"fixed\n\npoint,\" just like I could make a box that says \"square root.\" And I'd like to be able to\nexpress this in my language.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nSo I'd like to express not only the imperative how-to knowledge of a particular thing like\n\nsquare root, but I'd like to be able to express the imperative knowledge of how to do a\ngeneral thing like how to find fixed point. And in fact, let's go back and look at that slide\n\nagain.\nSee, not only is this a piece of imperative knowledge, how to find a fixed point, but over\nhere on the bottom, there's another piece of imperative knowledge which says, one way to\n\ncompute square root is to apply this general fixed point method. So I'd like to also be able\nto express that imperative knowledge. What would that look like?\n\n\n\n\n\nThat would say, this fixed point box is such that if I input to it the function that ta kes Y to\nthe average of Y and X/Y, then what should come out of that fixed point box is a method for\n\nfinding square roots. So in these boxes we're building, we're not only building boxes that\nyou input numbers and output numbers, we're going to be building in boxes that, in effect,\n\ncompute methods like finding square root.\n\n\n\n\nAnd my take is their inputs functions, like Y goes to the average of Y and X/Y. The reason\n\nwe want to do that, the reason this is a procedure, will end up being a procedure, as we'll\nsee, whose value is another procedure, the reason we want to do that is because\n\nprocedures are going to be our ways of talking about imperative knowledge. And the way to\n\nmake that very powerful is to be able to talk about other kinds of knowledge.\n\n\n\n\nSo here is a procedure that, in effect, talks about another procedure, a general strategy that\nitself talks about general strategies. Well, our first topic in this course -- there'll be three\n\nmajor topics-- will be black-box abstraction. Let's look at that in a little bit more detail.\n\nWhat we're going to do is we will start out talking about how Lisp is built up out of primitive\nobjects. What does the language supply with us? And we'll see that there are primitive\n\nprocedures and primitive data.\n\n\n\n\nThen we're going to see, how do you take those primitives and combine them to make more\n\ncomplicated things, means of combination? And what we'll see is that there are ways of\nputting things together, putting primitive procedures together to make more complicated\n\nprocedures. And we'll see how to put primitive data together to make compound data.\n\n\n\n\nThen we'll say, well, having made those compounds things, how do you abstract them? How\ndo you put those black boxes around them so you can use them as components in more\n\ncomplex things? And we'll see that's done by defining procedures and a technique for\n\ndealing with compound data called data abstraction.\n\n\n\n\nAnd then, what's maybe the most important thing, is going from just the rules to how does\nan expert work? How do you express common patterns of doing things, like saying, well,\nthere's a general method of fixed point and square root is a particular case of that? And\n\nwe're going to use-- I've already hinted at it-- something called higher-order procedures,\nnamely procedures whose inputs and outputs are themselves procedures. And then we'll\n\nalso see something very interesting. We'll see, as we go further and further on and become\nmore abstract, there'll be very-- well, the line between what we consider to be data and\n\nwhat we consider to be procedures is going to blur at an incredible rate.\n\n\n\n\nWell, that's our first subject, black-box abstraction. Let's look at the second topic. I can\n\nintroduce it like this. See, suppose I want to express the idea-- remember, we're talking\nabout ideas-- suppose I want to express the idea that I can take something and multiply it\n\nby the sum of two other things. So for example, I might say, if I had 1 and 3 and multiply\nthat by 2, I get 8. But I'm talking about the general idea of what's called linear combi nation,\n\nthat you can add two things and multiply them by something else.\n\n\n\n\nIt's very easy when I think about it for numbers, but suppose I also want to use that same\n\nidea to think about, I could add two vectors, a1 and a2, and then scale them by some factor\nx and get another vector. Or I might say, I want to think about a1 and a2 as being\n\npolynomials, and I might want to add those two polynomials and then multiply them by 2 to\n\nget a more complicated one.\n\n\n\n\nOr a1 and a2 might be electrical signals, and I might want to think about summing those\ntwo electrical signals and then putting the whole thing through an amplifier, multiplying it\n\nby some factor of 2 or something. The idea is I want to think about the general notion of\n\nthat.\n\n\n\n\nNow, if our language is going to be good language for expressing those kind of general\nideas, if I really, really can do that, I'd like to be able to say I'm going to multiply by x the\n\nsum of a1 and a2, and I'd like that to express the general idea of all different kinds of things\n\nthat a1 and a2 could be. Now, if you think about that, there's a problem, because after all,\nthe actual primitive operations that go on in the machine are obviously going to be different\n\nif I'm adding two numbers than if I'm adding two polynomials, or if I'm adding the\nrepresentation of two electrical signals or wave forms.\n\n\n\n\nSomewhere, there has to be the knowledge of the kinds of various things that you can add\n\nand the ways of adding them. Now, to construct such a system, the question is, where do I\n\nput that knowledge? How do I think about the different kinds of choices I have? An d if\ntomorrow George comes up with a new kind of object that might be added and multiplied,\n\nhow do I add George's new object to the system without screwing up everything that was\nalready there?\nWell, that's going to be the second big topic, the way of controlling that kind of complexity.\nAnd the way you do that is by establishing conventional interfaces, agreed upon ways of\n\nplugging things together. Just like in electrical engineering, people have standard\nimpedances for connectors, and then you know if y ou build something with one of those\n\nstandard impedances, you can plug it together with something else.\n\n\n\n\nSo that's going to be our second large topic, conventional interfaces. What we're going to\n\nsee is, first, we're going to talk about the problem of generic operations, which is the one I\nalluded to, things like \"plus\" that have to work with all different kinds of data. So we talk\n\nabout generic operations. Then we're going to talk about really large-scale structures. How\n\ndo you put together very large programs that model the kinds of complex systems in the\nreal world that you'd like to model?\n\n\n\n\nAnd what we're going to see is that there are two very important metaphors for putting\n\ntogether such systems. One is called object-oriented programming, where you sort of think\n\nof your system as a kind of society full of little things that interact by sending information\nbetween them. And then the second one is operations on aggregates, called streams, where\n\nyou think of a large system put together kind of like a signal processing engineer puts\ntogether a large electrical system.\n\n\n\n\n\nThat's going to be our second topic. Now, the third thing we're going to come to, the third\nbasic technique for controlling complexity, is making new languages. Because sometimes,\n\nwhen you're sort of overwhelmed by the complexity of a design, the way that you control\nthat complexity is to pick a new design language. And the purpose of the new design\n\nlanguage will be to highlight different aspects of the system. It will suppress some kinds of\ndetails and emphasize other kinds of details.\n\n\n\n\n\nThis is going to be the most magical part of the course. We're going to start out by actually\nlooking at the technology for building new computer languages. The first thing we're going\n\nto do is actually build in Lisp. We're going to express in Lisp the process of interpreting Lisp\nitself. And that's going to be a very sort of self-circular thing. There's a little mystical\n\nsymbol that has to do with that. The process of interpreting Lisp is sort of a giant whe el of\ntwo processes, apply and eval, which sort of constantly reduce expressions to each other.\n\n\n\n\n\nThen we're going to see all sorts of other magical things. Here's another magical symbol.\nThis is sort of the Y operator, which is, in some sense, the expression of infinity inside our\n\nprocedural language. We'll take a look at that. In any case, this section of the course is\ncalled Metalinguistic Abstraction, abstracting by talking about how you construct new\n\nlanguages.\n\n\n\n\nAs I said, we're going to start out by looking at the process of interpretation. We're going to\n\nlook at this apply-eval loop, and build Lisp. Then, just to show you that this is very general,\nwe're going to use exactly the same technology to build a very different kind of language, a\n\nso-called logic programming language, where you don't really talk about procedures at all\nthat have inputs and outputs. What you do is talk about relations between things.\n\n\n\n\n\nAnd then finally, we're going to talk about how you implement these things very concretely\non the very simplest kind of machines. We'll see something like this. This is a picture of a\n\nchip, which is the Lisp interpreter that we will be talking about then in hardware. Well,\nthere's an outline of the course, three big topics. Black-box abstraction, conventional\n\ninterfaces, metalinguistic abstraction. Now, let's take a break now and then we'll get\nstarted.\n\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\nLet's actually start in learning Lisp now. Actually, we'll start out by learning something much\n\nmore important, maybe the very most important thing in this course, which is not Lisp, in\nparticular, of course, but rather a general framework for thinking about languages that I\n\nalready alluded to. When somebody tells you they're going to show you a language, what\nyou should say is, what I'd like you to tell me is what are the primitive elements? What does\n\nthe language come with?\n\n\n\n\nThen, what are the ways you put those together? What are the means of combination?\n\nWhat are the things that allow you to take these primitive elements and build bigger things\nout of them? What are the ways of putting things together?\n\n\n\n\n\nAnd then, what are the means of abstraction? How do we take those complicated things and\ndraw those boxes around them? How do we name them so that we can now use them as if\n\nthey were primitive elements in making still more complex things? And so on, and so on,\nand so on. So when someone says to you, gee, I have a great new computer language, you\n\ndon't say, how many characters does it take to invert a matrix? It's irrelevant.\nWhat you say is, if the language did not come with matrices built in or with something else\n\nbuilt in, how could I then build that thing? What are the means of combination which would\nallow me to do that? And then, what are the means of abstraction which allow me then to\n\nuse those as elements in making more complicated things yet?\n\n\n\n\nWell, we're going to see that Lisp has some primitive data and some primitive procedures.\n\nIn fact, let's really start. And here's a piece of primitive data in Lisp, number 3. Actually, if\nI'm being very pedantic, that's not the number 3. That's some symbol that represents\n\nPlato's concept of the number 3. And here's another. Here's some more primitive data in\nLisp, 17.4. Or actually, some representation of 17.4.\n\n\n\n\n\nAnd here's another one, 5. Here's another primitive object that's built in Lisp, addition.\nActually, to use the same kind of pedantic-- this is a name for the primitive method of\n\nadding things. Just like this is a name for Plato's number 3, this is a name for Plato's\nconcept of how you add things. So those are some primitive elements. I can put them\n\ntogether. I can say, gee, what's the sum of 3 and 17.4 and 5?\n\n\n\n\nAnd the way I do that is to say, let's apply the sum operator to these three numbers. And I\n\nshould get, what? 8, 17. 25.4. So I should be able to ask Lisp what the value of this is, and\nit will return 25.4. Let's introduce some names. This thing that I typed is called a\n\ncombination. And a combination consists, in general, of applying an operator -- so this is an\noperator-- to some operands. These are the operands.\n\n\n\n\n\nAnd of course, I can make more complex things. The reason I can get complexity out of this\nis because the operands themselves, in general, can be combinations. So for instance, I\n\ncould say, what is the sum of 3 and the product of 5 and 6 and 8 and 2? And I should get--\nlet's see-- 30, 40, 43. So Lisp should tell me that that's 43.\n\n\n\n\n\nForming combinations is the basic needs of combination that we'll be looking at. And then,\nwell, you see some syntax here. Lisp uses what's called prefix notation, which means that\n\nthe operator is written to the left of the operands. It's just a convention. And notice, it's\nfully parenthesized. And the parentheses make it completely unambiguous. So by looking at\n\nthis, I can see that there's the operator, and there are 1, 2, 3, 4 operands.\n\n\n\n\nAnd I can see that the second operand here is itself some combination that has one\n\noperator and two operands. Parentheses in Lisp are a little bit, or are very unlike\nparentheses in conventional mathematics. In mathematics, we sort of use them to mean\ngrouping, and it sort of doesn't hurt if sometimes you leave out parentheses if people\n\nunderstand that that's a group. And in general, it doesn't hurt if you put in extra\nparentheses, because that maybe makes the grouping more distinct.\n\n\n\n\n\nLisp is not like that. In Lisp, you cannot leave out parentheses, and you cannot put in extra\nparentheses, because putting in parentheses always means, exactly and precisely, this is a\n\ncombination which has meaning, applying operators to operands. And if I left this out, if I\nleft those parentheses out, it would mean something else.\n\n\n\n\n\nIn fact, the way to think about this, is really what I'm doing when I write something like this\nis writing a tree. So this combination is a tree that has a plus and then a 3 and then a\n\nsomething else and an 8 and a 2. And then this som ething else here is itself a little subtree\nthat has a star and a 5 and a 6.\n\n\n\n\n\nAnd the way to think of that is, really, what's going on are we're writing these trees, and\nparentheses are just a way to write this two-dimensional structure as a linear character\n\nstring. Because at least when Lisp first started and people had teletypes or punch cards or\nwhatever, this was more convenient. Maybe if Lisp started today, the syntax of Lisp would\n\nlook like that.\n\n\n\n\nWell, let's look at what that actually looks like on the computer. Here I have a Lisp\n\ninteraction set up. There's a editor. And on the top, I'm going to type some values and ask\nLisp what they are. So for instance, I can say to Lisp, what's the value of that symbol?\n\nThat's 3. And I ask Lisp to evaluate it. And there you see Lisp has returned on the bottom,\nand said, oh yeah, that's 3.\n\n\n\n\n\nOr I can say, what's the sum of 3 and 4 and 8? What's that combination? And ask Lisp to\nevaluate it. That's 15. Or I can type in something more complicated. I can say, what's the\n\nsum of the product of 3 and the sum of 7 and 19.5? And you'll notice here that Lisp has\nsomething built in that helps me keep track of all these parentheses. Watch as I type the\n\nnext closed parentheses, which is going to close the combination starting with the star. The\nopening one will flash.\n\n\n\n\n\nHere, I'll rub those out and do it again. Type close, and you see that closes the plus. Close\nagain, that closes the star. Now I'm back to the sum, and maybe I'm going to add that all to\n\n4. That closes the plus. Now I have a complete combination, and I can ask Lisp for the value\nof that.\nThat kind of paren balancing is something that's built into a lot of Lisp systems to help you\nkeep track, because it is kind of hard just by hand doing all these parentheses. There's\n\nanother kind of convention for keeping track of parentheses. Let me write another\ncomplicated combination. Let's take the sum of the product of 3 and 5 and add that to\n\nsomething.\n\n\n\n\nAnd now what I'm going to do is I'm going to indent so that the operands are written\n\nvertically. Which the sum of that and the product of 47 and-- let's say the product of 47\nwith a difference of 20 and 6.8. That means subtract 6.8 from 20. And then you see the\n\nparentheses close. Close the minus. Close the star.\n\n\n\n\nAnd now let's get another operator. You see the Lisp editor here is indenting to the right\n\nposition automatically to help me keep track. I'll do that again. I'll close that last\nparentheses again. You see it balances the plus. Now I can say, what's the value of that?\n\n\n\n\n\nSo those two things, indenting to the right level, which is called pretty printing, and flashing\nparentheses, are two things that a lot of Lisp systems have built in to help you keep track.\n\nAnd you should learn how to use them. Well, those are the primitives. There's a means of\ncombination. Now let's go up to the means of abstraction.\n\n\n\n\n\nI'd like to be able to take the idea that I do some combination like this, and abstract it and\ngive it a simple name, so I can use that as an element. And I do that in Lisp with \"define.\"\n\nSo I can say, for example, define A to be the product of 5 and 5. And now I could say, for\nexample, to Lisp, what is the product of A and A? And this should be 25, and this should be\n\n625.\n\n\n\n\nAnd then, crucial thing, I can now use A-- here I've used it in a combination-- but I could\n\nuse that in other more complicated things that I name in turn. So I could say, define B to be\nthe sum of, we'll say, A and the product of 5 and A. And then close the plus.\n\n\n\n\n\nLet's take a look at that on the computer and see how that looks. So I'll just type what I\nwrote on the board. I could say, define A to be the product of 5 and 5. And I'll tell that to\n\nLisp. And notice what Lisp responded there with was an A in the bottom. In general, when\nyou type in a definition in Lisp, it responds with the symbol being defined.\nNow I could say to Lisp, what is the product of A and A? And it says that's 625. I can define\n\nB to be the sum of A and the product of 5 and A. Close a paren closes the star. Close the\nplus. Close the \"define.\" Lisp says, OK, B, there on the bottom. And now I can say to Lisp,\n\nwhat's the value of B?\n\n\n\n\nAnd I can say something more complicated, like what's the sum of A and the quotient of B\n\nand 5? That slash is divide, another primitive operator. I've divided B by 5, added it to A.\nLisp says, OK, that's 55.\n\n\n\n\n\nSo there's what it looks like. There's the basic means of defining something. It's the\nsimplest kind of naming, bu t it's not really very powerful. See, what I'd really like to name--\n\nremember, we're talking about general methods-- I'd like to name, oh, the general idea\nthat, for example, I could multiply 5 by 5, or 6 by 6, or 1,001 by 1,001, 1,001.7 by 1,001.7.\n\nI'd like to be able to name the general idea of multiplying something by itself.\n\n\n\n\nWell, you know what that is. That's called squaring. And the way I can do that in Lisp is I\n\ncan say, define to square something x, multiply x by itself. And then having done that, I\ncould say to Lisp, for example, what's the square of 10? And Lisp will say 100.\n\n\n\n\n\nSo now let's actually look at that a little more closely. Right, there's the definition of square.\nTo square something, multiply it by itself. You see this x here. That x is kind of a pronoun,\n\nwhich is the something that I'm going to square. And what I do with it is I multiply x, I\nmultiply it by itself.\n\n\n\n\n\nOK. So there's the notation for defining a procedure. Actually, this is a little bit confusing,\nbecause this is sort of how I might use square. And I say square root of x or square root of\n\n10, but it's not making it very clear that I'm actually naming something. So let me write this\ndefinition in another way that makes it a little bit more clear that I'm naming something. I'll\n\nsay, \"define\" square to be lambda of x times xx.\n\n\n\n\nHere, I'm naming something square, just like over here, I'm naming something A. The thing\n\nthat I'm naming square-- here, the thing I named A was the value of this combination.\nHere, the thing that I'm naming square is this thing that begins with lambda, and lambda is\n\nLisp's way of saying make a procedure.\nLet's look at that more closely on the slide. The way I read that definition is to say, I define\n\nsquare to be make a procedure-- that's what the lambda is-- make a procedure with an\nargument named x. And what it does is return the results of multiplying x by itself. Now, in\n\ngeneral, we're going to be using this top form of defining, just because it's a little bit more\nconvenient. But don't lose sight of the fact that it's really this.\n\n\n\n\n\nIn fact, as far as the Lisp interpreter's concerned, there's no difference between typing this\nto it and typing this to it. And there's a word for that, sort of syntactic sugar. What syntactic\n\nsugar means, it's having somewhat more convenient surface forms for typing something.\n\n\n\n\nSo this is just really syntactic sugar for this underlying Greek thing with the lambda. And\n\nthe reason you should remember that is don't forget that, when I write something like this,\nI'm really naming something. I'm naming something square, and the something that I'm\n\nnaming square is a procedure that's getting constructed.\n\n\n\n\nWell, let's look at that on the computer, too. So I'll come and I'll say, define square of x to\n\nbe times xx. Now I'll tell Lisp that. It says \"square.\" See, I've named something \"square.\"\nNow, having done that, I can ask Lisp for, what's the square of 1,001? Or in general, I could\n\nsay, what's the square of the sum of 5 and 7? The square of 12's 144.\n\n\n\n\nOr I can use square itself as an element in some combination. I can say, what's the sum of\n\nthe square of 3 and the square of 4? 9 and 16 is 25. Or I can use square as an element in\nsome much more complicated thing. I can say, what's the square of, the sqare of, the\n\nsquare of 1,001?\n\n\n\n\nAnd there's the square of the square of the square of 1,001. Or I can say to Lisp, what is\n\nsquare itself? What's the value of that? And Lisp returns some conventional way of telling\nme that that's a procedure. It says, \"compound procedure square.\" Remember, the value of\n\nsquare is this procedure, and the thing with the stars and the brackets are just Lisp's\nconventional way of describing that.\n\n\n\n\n\nLet's look at two more examples of defining. Here are two more procedures. I can define the\naverage of x and y to be the sum of x and y divided by 2. Or having had average and mean\n\nsquare, having had average and square, I can use that to talk about the mean square of\nsomething, which is the average of the square of x and the square of y.\nSo for example, having done that, I could say, what's the mean square of 2 and 3? And I\n\nshould get the average of 4 and 9, which is 6.5. The key thing here is that, having defined\nsquare, I can use it as if it were primitive. So if we look here on the slide, if I look at mean\n\nsquare, the person defining mean square doesn't have to know, at this point, whether\nsquare was something built into the language or whether it was a procedure that was\n\ndefined.\n\n\n\n\nAnd that's a key thing in Lisp, that you do not make arbitrary distinctions between things\n\nthat happen to be primitive in the language and things that happen to be built in. A person\nusing that shouldn't even have to know. So the things you construct get used with all the\n\npower and flexibility as if they were primitives. In fact, you can drive that home by looking\non the computer one more time.\n\n\n\n\n\nWe talked about plus. And in fact, if I come here on the computer screen and say, what is\nthe value of plus? Notice what Lisp types out. On the bottom there, it typed out, \"compound\n\nprocedure plus.\" Because, in this system, it turns out that the addition operator is itself a\ncompound procedure. And if I didn't just type that in, you'd never know that, and it\n\nwouldn't make any difference anyway. We don't care. It's below the level of the abstraction\n\nthat we're dealing with.\n\n\n\n\nSo the key thing is you cannot tell, should not be able to tell, in general, the difference\nbetween things that are built in and things that are compound. Why is that? Because the\n\nthings that are compound have an abstraction wrapper wrapped around them. We've seen\n\nalmost all the elements of Lisp now. There's only one more we have to look at, and that is\nhow to make a case analysis.\n\n\n\n\nLet me show you what I mean. We might want to think about the mathematical definition of\n\nthe absolute value functions. I might say the absolute value of x is the function which has\n\nthe property that it's negative of x. For x less than 0, it's 0 for x equal to 0. And it's x for x\ngreater than 0. And Lisp has a way of making case analyses.\n\n\n\n\nLet me define for you absolute value. Say define the absolute value of x is conditional. This\n\nmeans case analysis, COND. If x is less than 0, the answer is negate x. What I've written\nhere is a clause. This whole thing is a conditional clause, and it has two p arts. This part here\n\nis a predicate or a condition.\nThat's a condition. And the condition is expressed by something called a predicate, and a\n\npredicate in Lisp is some sort of thing that returns either true or false. Andyou see Lisp has\na primitive procedure, less-than, that tests whether something is true or false.\n\n\n\n\n\nAnd the other part of a clause is an action or a thing to do, in the case where that's true.\nAnd here, what I'm doing is negating x. The negation operator,the minus sign in Lisp is a\n\nlittle bit funny. If there's two or more arguments, if there's two arguments it subtracts the\nsecond one from the first, and we saw that. And if there's one argument, it negates it. So\n\nthis corresponds to that.\n\n\n\n\nAnd then there's another COND clause. It says, in the case where x is equal to 0, the\n\nanswer is 0. And in the case where x is greater than 0, the answer is x. Close that clause.\nClose the COND. Close the definition. And there's the definition of absolute value. And you\n\nsee it's the case analysis that looks very much like the case analysis you use in\nmathematics.\n\n\n\n\n\nThere's a somewhat different way of writing a restricted case analysis. Often, you have a\ncase analysis where you only have one case, where you test something,and then\n\ndepending on whether it's true or false, you do something. And here's another definition of\nabsolute value which looks almost the same, which says, if x is less than 0, the result is\n\nnegate x. Otherwise, the answer is x. And we'll be using \"if\" alot.\n\n\n\n\nBut again, the thing to remember is that this form of absolute value that you're looking at\n\nhere, and then this one over here that I wrote on the board, are essentially the same. And\n\"if\" and COND are-- well, whichever way you like it. You can thin k of COND as syntactic\n\nsugar for \"if,\" or you can think of \"if\" as syntactic sugar for COND, and it doesn't make any\ndifference. The person implementing a Lisp system will pick one and implement the other in\n\nterms of that. And it doesn't matter which one you pick.\n\n\n\n\nWhy don't we break now, and then take some questions. How come sometimes when I write\n\ndefine, I put an open paren here and say, define open paren something or other, and\nsometimes when I write this, I don't put an open paren? The answer is, this particular form\n\nof \"define,\" where you say define some expression, is this very special thing for defining\nprocedures. But again, what it really means is I'm defining this symbol, square, to be that.\n\n\n\n\n\nSo the way you should think about it is what \"define\" does is you write \"define,\" and the\nsecond thing you write is the symbol here-- no open paren-- the symbol you're defining and\nwhat you're defining it to be. That's like here and like here. That's sort of the basic way you\n\nuse \"define.\" And then, there's this special syntactic trick which allows you to define\nprocedures that look like this. So the difference is, it's whether or not you're defining a\n\nprocedure.\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\nWell, believe it or not, you actually now know enough Lisp to write essentially any numerical\n\nprocedure that you'd write in a language like FORTRAN or Basic or whatever, or, essentially,\n\nany other language. And you're probably saying, that's not believable, because you know\nthat these languages have things like \"for statements,\" and \"do until while\" or something.\n\n\n\n\nBut we don't really need any of that. In fact, we're not going to use any of that in this\n\ncourse. Let me show you. Again, looking back at square root, let's go back to this square\n\nroot algorithm of Heron of Alexandria. Remember what that said. It said, to find an\napproximation to the square root of X, you make a guess, you improve that guess by\n\naveraging the guess and X over the guess. You keep improving that until the guess is good\nenough. I already alluded to the idea. The idea is that, if the initial guess that you took was\n\nactually equal to the square root of X, then G here would be equal to X/G.\n\n\n\n\nSo if you hit the square root, averaging them wouldn't change it. If the G that you picked\n\nwas larger than the square root of X, then X/G will be smaller than the square root of X, so\nthat when you average G and X/G, you get something in between. So if you pick a G that's\n\ntoo small, your answer will be too large. If you pick a G that's too large, if your G is larger\nthan the square root of X and X/G will be smaller than the square root of X.\n\n\n\n\n\nSo averaging always gives you something in between. And then, it's not quite trivial, but it's\npossible to show that, in fact, if G misses the square root of X by a little bit, the averag e of\n\nG and X/G will actually keep getting closer to the square root of X. So if you keep doing this\nenough, you'll eventually get as close as you want.\n\n\n\n\n\nAnd then there's another fact, that you can always start out this process by using 1 as an\ninitial guess. And it'll always converge to the square root of X. So that's this method of\n\nsuccessive averaging due to Heron of Alexandria. Let's write it in Lisp.\nWell, the central idea is, what does it mean to try a guess for the square root of X? Let's\n\nwrite that. So we'll say, define to try a guess for the square root of X, what do we do? We'll\nsay, if the guess is good enough to be a guess for the square root of X, then, as an answer,\n\nwe'll take the guess. Otherwise, we will try the improved guess. We'll improve that guess\nfor the square root of X, and we'll try that as a guess for the square root of X. Close the\n\n\"try.\" Close the \"if.\" Close the \"define.\" So that's how we try a guess.\n\n\n\n\nAnd then, the next part of the process said, in order to compute square roots, we'll say,\n\ndefine to compute the square root of X, we will try 1 as a guess for the square root of X.\nWell, we have to define a couple more things. We have to say, how is a guess good enough?\n\nAnd how do we improve a guess? So let's look at that.\n\n\n\n\nThe algorithm to improve a guess for the square root of X, we average-- that was the\n\nalgorithm-- we average the guess with the quotient of dividing X by the guess. That's how\nwe improve a guess. And to tell whether a guess is good enough, well, we have to decide\n\nsomething. This is supposed to be a guess for the square root of X, so one possible thing\nyou can do is say, when you take that guess and square it, do you get something very close\n\nto X? So one way to say that is to say, I square the guess, subtract X from that, and see if\n\nthe absolute value of that whole thing is less than some small number, which depends on\nmy purposes.\n\n\n\n\nSo there's a complete procedure for how to compute the square root of X. Let's look at the\n\nstructure of that a little bit. I have the whole thing. I have the notion of how to compute a\n\nsquare root. That's some kind of module. That's some kind of black box. It's defined in\nterms of how to try a guess for the square root of X.\n\n\n\n\n\"Try\" is defined in terms of, well, telling whether something is good enough and telling how\n\nto improve something. So good enough. \"Try\" is defined in terms of \"good enough\" and\n\n\"improve.\" And let's see what else I fill in. Well, I'll go down thtree. \"Good enough\" was\ndefined in terms of absolute value, and square. And improve was defined in terms of\n\nsomething called averaging and then some other primitive operator.\n\n\n\n\nSquare root's defined in terms of \"try.\" \"Try\" is defined in terms of \"good enough\" and\n\"improve,\" but also \"try\" itself. So \"try\" is also defined in terms of how to try itself. Well,\n\nthat may give you some problems. Your high school geometry teacher probably told you\n\nthat it's naughty to try and define things in terms of themselves, because it doesn't make\nsense. But that's false.\nSometimes it makes perfect sense to define things in terms of themselves. And this is the\n\ncase. And we can look at that. We could write down what this means, and say, suppose I\nasked Lisp what the square root of 2 is. What's the square root of 2 mean? Well, that means\n\nI try 1 as a guess for the square root of 2.\n\n\n\n\nNow I look. I say, gee, is 1 a good enough guess for the square root of 2? And that depends\n\non the test that \"good enough\" does. And in this case, \"good enough\" will say, no, 1 is not a\ngood enough guess for the square root of 2. So that will reduce to saying, I have to try an\n\nimproved-- improve 1 as a guess for the square root of 2, and try that as a guess for the\nsquare root of 2. Improving 1 as a guess for the square root of 2 means I average 1 and 2\n\ndivided by 1. So this is going to be average. This piece here will be the average of 1 and the\nquotient of 2 by 1. That's this piece here.\n\n\n\n\n\nAnd this is 1.5. So this square root of 2 reduces to trying 1 for the square root of 2, which\nreduces to trying 1.5 as a guess for the square root of 2. So that makes sense. Let's look at\n\nthe rest of the process. If I try 1.5, that reduces. 1.5 turns out to be not good enough as a\nguess for the square root of 2. So that reduces to trying the average of 1.5 and 2 divided by\n\n1.5 as a guess for the square root of 2.\n\n\n\n\nThat average turns out to be 1.333. So this whole thing reduces to trying 1.333 as a guess\n\nfor the square root of 2. And then so on. That reduces to a nother called a \"good enough,\"\n1.4 something or other. And then it keeps going until the process finally stops with\n\nsomething that \"good enough\" thinks is good enough, which, in this case, is 1.4142\n\nsomething or other.\n\n\n\n\nSo the process makes perfect sense. This, by the way, is called a recursive definition. And\nthe ability to make recursive definitions is a source of incredible power. And as you can\n\nalready see I've hinted at, it's the thing that effectively allows you to do these infinite\n\ncomputations that go on until something is true, without having any other constricts other\nthan the ability to call a procedure.\n\n\n\n\nWell, let's see, there's one more thing. Let me show you a variant of this definition of\n\nsquare root here on the slide. Here's sort of the sam e thing. What I've done here is\npackaged the definitions of \"improve\" and \"good enough\" and \"try\" inside \"square root.\" So,\n\nin effect, what I've done is I've built a square root box. So I've built a box that's the square\n\nroot procedure that someone can use. They might put in 36 and get out 6. And then,\npackaged inside this box are the definitions of \"try\" and \"good enough\" and \"improve.\"\nSo they're hidden inside this box. And the reason for doing that is that, if someone's using\n\nthis square root, if George is using this square root, George probably doesn't care very\nmuch that, when I implemented square root, I had things inside there called \"try\" and \"good\n\nenough\" and \"improve.\" And in fact, Harry might have a cube root procedure that has \"try\"\nand \"good enough\" and \"improve.\" And in order to not get the whole system confused, it'd\n\nbe good for Harry to package his internal procedures inside his cube root procedure.\n\n\n\n\nWell, this is called block structure, this particular way of packaging internals inside ofa\n\ndefinition. And let's go back and look at the slide again. The way to read this kind of\nprocedure is to say, to define \"square root,\" well, inside that definition, I'll have the\n\ndefinition of an \"improve\" and the definition of \"good enough\" and the defin ition of \"try.\"\nAnd then, subject to those definitions, the way I do square root is to try 1.\n\n\n\n\n\nAnd notice here, I don't have to say 1 as a guess for the square root of X, because since it's\nall inside the square root, it sort of has this X known.\n\n\n\n\n\nLet me summarize. We started out with the idea that what we're going to be doing is\nexpressing imperative knowledge. And in fact, here's a slide that summarizes the way we\n\nlooked at Lisp. We started out by looking at some primitive elements in addition and\nmultiplication, some predicates for testing whether something is less-than or something's\n\nequal.\n\n\n\n\nAnd in fact, we saw really sneakily in the system we're actually using, these aren't actually\n\nprimitives, but it doesn't matter. What matters is we're going to use them as if they're\nprimitives. We're not going to look inside. We also have some primitive data and some\n\nnumbers. We saw some means of composition, means of combination, the basic one being\ncomposing functions and building combinations with operato rs and operands.\n\n\n\n\n\nAnd there were some other things, like COND and \"if\" and \"define.\" But the main thing\nabout \"define,\" in particular, was that it was the means of abstraction. It was the way that\n\nwe name things. You can also see from this slide not only where we've been, but holes we\nhave to fill in. At some point, we'll have to talk about how you combine primitive data to get\n\ncompound data, and how you abstract data so you can use large globs of data as if they\nwere primitive. So that's where we're going.\n\n\n\n\n\nBut before we do that, for the next couple of lectures we're going to be talking about, first\nof all, how it is that you make a link between these procedures we write and the processes\nthat happen in the machine. And then, how it is that you start usin g the power of Lisp to\n\ntalk not only about these individual little computations, but about general conventional\nmethods of doing things.\n\n\n\n\n\nOK, are there any questions?\n\n\n\n\nAUDIENCE: Yes. If we defined A using parentheses instead of as we did, what would be the\ndifference?\n\n\n\n\n\nPROFESSOR: If I wrote this, if I wrote that, what I would be doing is defining a procedure\nnamed A. In this case, a procedure of no arguments, which, when I ran it, would give me\n\nback 5 times 5.\n\n\n\n\nAUDIENCE: Right. I mean, you come up with the same thing, except for you really got a\n\ndifferent--\n\n\n\n\nPROFESSOR: Right. And the difference would be, in the old one-- Let me be a little bit\n\nclearer here. Let's call this A, like here. And pretend here, just for contrast, I wrote, define\nD to be the product of 5 and 5. And the difference between those, let's think about\n\ninteractions with the Lisp interpreter. I could type in A and Lisp would return 25. I could\ntype in D, if I just typed in D, Lisp would return compound procedure D, because that's\n\nwhat it is. It's a procedure.\n\n\n\n\nI could run D. I could say, what's the value of running D? Here is a combination with no\n\noperands. I see there are no operands. I didn't put any after D. And it would say, oh, that's\n25. Or I could say, just for completeness, if I typed in, what's the value of running A? I get\n\nan error. The error would be the same one as over there. It'd be the error would say, sorry,\n25, which is the value of A, is not an operator that I can apply to something.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec1b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 1B: Procedures and Processes; Substitution Model\n\n\n\n[MUSIC PLAYING BY J.S. BACH] PROFESSOR: Hi. You've seen that the job of a programmer\nis to design processes that accomplish particular goals, such as finding the square roots of\n\nnumbers or other sorts of things you might want to do. We haven't introduced anything else\nyet. Of course, the way in which a programmer does this is by constructing spells, which are\n\nconstructed out of procedures and expressions. And that these spells are somehow direct a\nprocess to accomplish the goal that was intended by the programmer. In order for the\n\nprogrammer to do this effectively, he has to understand the relationship between the\nparticular things that he writes, these particular spells, and the behavior of the process that\n\nhe's attempting to control.\n\n\n\n\nSo what we're doing this lecture is attempt to establish that connecti on in as clear a way as\n\npossible. What we will particularly do is understand how particular patterns of procedures\nand expressions cause particular patterns of execution, particular behaviors from the\n\nprocesses.\n\n\n\n\nLet's get down to that. I'm going to start with a very simple program. This is a program to\n\ncompute the sum of the squares of two numbers. And we'll define the sum of the squares of\nx and y to be the sum of the square of x-- I'm going to write it that way-- and the square of\n\ny where the square of x is the product of x and x. Now, supposing I were to say something\nto this, like, to the system after having defined these things, of the form, the sum of the\n\nsquares of 3 and 4, I am hoping that I will get out a 25. Because the square of 3 is 9, and\n\nthe square of 4 is 16, and 25 is the sum of those.\n\n\n\n\nBut how does that happen? If we're going to understand processes and how we control\nthem, then we have to have a mapping from the mechanisms of this procedure into the way\n\nin which these processes behave. What we're going to have is a formal, or semi-formal,\n\nmechanical model whereby you understand how a machine could, in fact, in principle, do\nthis. Whether or not the actual machine really does what I'm about to tell you is completely\n\nirrelevant at this moment.\n\n\n\n\nIn fact, this is an engineering model in the same way that, electrical resistor, we write down\n\na model v equals i r, it's approximately true. It's not really true. If I put up current through\nthe resistor it goes boom. So the voltage is not always proportional to the current, but for\n\nsome purposes the model is appropriate. In particular, the model we're going to describe\nright now, which I call the substitution model, is the simplest model that we have for\n\nunderstanding how procedures work and how processes work. How procedures yield\nprocesses. And that substitution model will be accurate for most of the things we'll be\n\ndealing with in the next few days. But eventually, it will become impossible to sustain the\nillusion that that's the way the machine works, and we'll go to other more specific and\n\nparticular models that will show more detail.\n\n\n\n\nOK, well, the first thing, of course, is we say, what are the things we have here? We have\n\nsome cryptic symbols. And these cryptic symbols are made out of pieces. There are kinds of\nexpressions. So let's write down here the kinds of expressions there are. And we have-- and\n\nso far I see things like numbers. I see things like symbols like that.\n\n\n\n\nWe have seen things before like lambda expressions, but they're not here. I'm going to\n\nleave them out. Lambda expressions, we'll worry about them later. Things like definitions.\nThings like conditionals. And finally, things like combinations.\n\n\n\n\n\nThese kinds of expressions are-- I'll worry about later-- these are special forms. There are\nparticular rules for each of these. I'm going to tell you, however, the rules for doing a\n\ngeneral case. How does one evaluate a combination? Because, in fact, over here, all I really\nhave are combinations and some symbols and numbers. And the sim ple things like a\n\nnumber, well, it will evaluate to itself.\n\n\n\n\nIn the model I will have for you, the symbols will disappear. They won't be there at the time\n\nwhen you need them, when you need to get at them. So the only thing I really have to\nexplain to you is, how do we evaluate combinations?\n\n\n\n\n\nOK, let's see. So first I want to get the first slide. Here is the rule for evaluating an\napplication. What we have is a rule that says, to evaluate a combination, there are two\n\nparts, three parts to the rule. The combination has several parts. It has operators and it\nhas operands. The operator returns into a procedure. If we evaluate the operator, we will\n\nget a procedure. And you saw, for example, how I'll type at the machine and out came\ncompound procedure something or other.\n\n\n\n\n\nAnd the operands produce arguments. Once we've gotten the operator evaluated to get a\nprocedure, and the argument is evaluated to get argument-- the operand's value to get\n\narguments-- we apply the procedure to these arguments by copying the body of the\nprocedure, which is the expression that the procedure is defined in terms of. What is it\nsupposed to do? Substituting the argument supplied for the formal parameters of the\n\nprocedure, the formal parameters being the names defined by the declaration of the\nprocedure. Then we evaluate the resulting new body, the body resulting from copying the\n\nold body with the substitutions made.\n\n\n\n\nIt's a very simple rule, and we're going to do it very formally for a little while. Because for\n\nthe next few lectures, what I want you to do is to say, if I don't understand something, if I\ndon't understand something, be very mechanical and do this.\n\n\n\n\n\nSo let's see. Let's consider a particular evaluation, the one we were talking about before.\nThe sum of the squares of 3 and 4. What does that mean? It says, take-- well, I could find\n\nout what's on the square-- it's some procedure, and I'm not going to worry about the\nrepresentation, and I'm not going to write it on the blackboard for you. And I have that 3\n\nrepresents some number, but if I have to repeat that number, I can't tell you the number.\nThe number itself is some abstract thing. There's a numeral which represents it, which I'll\n\ncall 3, and I'll use that in my substitution.\n\n\n\n\nAnd 4 is also a number. I'm going to substitute 3 for x and 4 for y in the body of this\n\nprocedure that you see over here. Here's the body of the procedure. It corresponds to this\ncombination, which is an addition.\n\n\n\n\n\nSo what that reduces to, as a reduction step, we call it, is the sum of the square of 3 and\nthe square of 4. Now, what's the next step I have to do here? I say, well, I have to evaluate\n\nthis. According to my rule, which you just saw on that overhead or slide, what we had was\nthat we have to evaluate the operands-- and here are the operands, here's one and here's\n\nthe next operand-- and how we have to evaluate procedure. The order doesn't matter. And\nthen we're going to apply the procedure, which is plus, and magically somehow that's going\n\nto produce the answer. I'm not to open up plus and look inside of it.\n\n\n\n\nHowever, in order to evaluate the operand, let's pick some arbitrary order and do them. I'm\n\ngoing to go from right to left. Well, in order to evaluate this operand, I have to evaluate the\nparts of it by the same rule. And the parts are I have to find out what square is-- it's some\n\nprocedure, which has a formal parameter x. And also, I have an operand which is 4, which I\nhave to substitute for x in the body of square.\n\n\n\n\n\nSo the next step is basically to say that this is the sum of the square of 3 and the product of\n4 and 4. Of course, I could open up asterisk if I liked-- the multiplication operation -- but I'm\nnot going to do that. I'm going to consider that primitive. And, of course, at any level of\n\ndetail, if you look inside this machine, you're going to find that there's multiple levels below\nthat that you don't know about.\n\n\n\n\n\nBut one of the things we have to learn how to do is ignore details. The key to understanding\ncomplicated things is to know what not to look at and what not compute and what not to\n\nthink. So we're going to stop this one here and say, oh, yes, this is the product of two\nthings. We're going to do it now.\n\n\n\n\n\nSo this is nothing more than the sum of the square of 3 and 16. And now I have another\nthing I have to evaluate, but that square of 3, well, it's the same thing. That's the sum of\n\nthe product of 3 and 3 and 16, which is the sum of 9 and 16, which is 25.\n\n\n\n\nSo now you see the basic method of doing substitutions. And I warn you that this is not a\n\nperfect description of what the computer does. But it's a good enough description for the\nproblems that we're going to have in the next few lectures that you should think about this\n\nreligiously. And this is how the machine works for now. Later we'll get more detailed.\n\n\n\n\nNow, of course, I made a specific choice of the order of evaluation here. There are other\n\npossibilities. If we go back to the telestrator here and look atthe substitution rule, we see\nthat I evaluated the operator to get the procedures, and I evaluated the operands to get the\n\narguments first, before I do the application. It's entirely possible, and there are alternate\nrules called normal order evaluation whereby you can do the substitution of the expressions\n\nwhich are the operands for the formal parameters inside the body first. And you'll get also\nthe same answer.\n\n\n\n\n\nBut right now, for concreteness, and because this is the way our machine really does it, Im     '\ngoing to give you this rule, which has a particular order. But that order is to some extent\n\narbitrary, too. In the long run, there are some reasons why you might pick one order or\nanother, and we'll get to that later in the subject.\n\n\n\n\n\nOK, well now the only other thing I have to tell you about just to understand what's going\non is let's look at the rule for conditionals. Conditionals are very simple, and I'd like to\n\nexamine this. A conditional is something that is if -- there's also cond, of course-- but I'm\ngoing to give names to the parts of the expression. There's a predicate, which is a thing that\n\nis either true or false. And there's a consequent, which is the thing you do if the predicate is\ntrue. And there's an alternative, which is the thing you do if the predicate is false.\nIt's important, by the way, to get names for, to get names for, the parts of things, or the\nparts of expressions. One of the things that every sorcerer will tell you is if you have the\n\nname of a spirit, you have power over it. So you have to learn these names so that we can\ndiscuss these things.\n\n\n\n\n\nSo here we have a predicate, a consequent, and an alternative. And, using such words, we\nsee that an if expression, the problems you evaluate to the predicate expression, if that\n\nyields true, then you then go on to evaluate the consequent. Otherwise, you evaluate the\nalternative expression.\n\n\n\n\n\nSo I'd like to illustrate that now in the context of a particular little program. Going to write\ndown a program which we're going to see many times. This is the sum of x and y done by\n\nwhat's called Peano arithmetic, which is all we're doing is incrementing and decrementing.\nAnd we're going to see this for a little bit. It's a very important program.\n\n\n\n\n\nIf x equals o, then the result is y. Otherwise, this is the sum of the decrement of x and the\nincrement of y. We're going to look at this a lot more in the future.\n\n\n\n\n\nLet's look at the overhead. So here we have this procedure, and we're going to look at how\nwe do the substitutions, the sequence of substitutions. Well, I'm going to try and add\n\ntogether 3 and 4. Well, using the first rule that I showed you, we substitute 3 for x and 4\nfour y in the body of this procedure. The body of the procedure is the thing that begins with\n\nif and finishes over here. So what we get is, of course, if 3 is 0, then the result is 4.\nOtherwise, it's the sum of the decrement of 3 and the increment of 4.\n\n\n\n\n\nBut I'm not going to worry about these yet because 3 is not 0. So the answer is not 4.\nTherefore, this if reduces to an evaluation of the expression, the sum to the decrement of 3\n\nand the increment of 4. Continuing with my evaluation, the increment I presume to be\nprimitive, and so I get a 5 there. OK, and then the decrement is also primitive, and Iget a\n\n2. And so I change the problem into a simpler problem. Instead of adding 3 to 4, I'm adding\n2 to 5. The reason why this is a simpler problem is because I'm counting down on x, and\n\neventually, then, x will be 0.\n\n\n\n\nSo, so much for the substitution rule. In general, I'm not going to write down intermediate\n\nsteps when using substitutions having to do with ifs, because they just expand things to\nbecome complicated. What we will be doing is saying, oh, yes, the sum of 3 and 4 results in\nthe sum of 2 and 5 and reduces to the sum of 2 and 5, which, in fact, reduces to the sum of\n\n1 and 6, which reduces to the sum of 0 and 7 over here, which reduces to a 7. That's what\nwe're going to be seeing.\n\n\n\n\n\nAre there any questions for the first segment yet? Yes?\n\n\n\n\nSTUDENT: You're using 1 plus and minus 1 plus. Are those primitive operations?\n\n\n\n\nPROFESSOR: Yes. One of the things you're going to be seeing in this subject is I'm going to,\n\nwithout thinking about it, introduce more and more primitive operations. There's\npresumably some large library of primitive operations somewhere. But it doesn't matter that\n\nthey're primitive-- there may be some manual that lists them all. If I tell you what they do,\nyou say, oh, yes, I know what they do. So one of them is the decrementor -- minus 1 plus--\n\nand the other operation is increment, which is 1 plus.\n\n\n\n\nThank you. That's the end of the first segment.\n\n\n\n\n\n[MUSIC PLAYING BY J.S. BACH]\n\n\n\n\nPROFESSOR: Now that we have a reasonably mechanical way of understanding how a\n\nprogram made out of procedures and expressions evolves a process, I'd like to develop\nsome intuition about how particular programs evolve particular processes, what the shapes\n\nof programs have to be in order to get particular shaped processes. This is a question\nabout, really, pre-visualizing.\n\n\n\n\n\nThat's a word from photography. I used to be interested in photography a lot, and one of\nthe things you discover when you start trying to learn about photography is that you say,\n\ngee, I'd like to be a creative photographer. Now, I know the rules, I push buttons, and I\nadjust the aperture and things like that. But the key to being a creative person, partly, is to\n\nbe able to do analysis at some level. To say, how do I know what it is that I'm going to get\non the film before I push the button. Can I imagine in my mind the resulting image very\n\nprecisely and clearly as a consequence of the particular framing, of the aperture I choose, of\nthe focus, and things like that?\nThat's part of the art of doing this sort of thing. And learning a lot of that involves things\n\nlike test strips. You take very simple images that have varying degrees of density in them,\nfor example, and examine what those look like on a piece of paper when you print them\n\nout. You find out what is the range of contrasts that you can actually see. And what, in a\nreal scene, would correspond to the various levels and zones that you have of density in an\n\nimage.\n\n\n\n\nWell, today I want to look at some very particular test strips, and I suppose one of them I\n\nsee here is up on the telestrator, so we should switch to that. There's a very important, very\nimportant pair of programs for understanding what's going on in the evolution of a process\n\nby the execution of a program. What we have here are two procedures that are almost\nidentical. Almost n o difference between them at all. It's a few characters that distinguish\n\nthem. These are two ways of adding numbers together.\n\n\n\n\nThe first one, which you see here, the first one is the sum of two numbers -- just what we\n\ndid before-- is, if the first one is 0 , it's the answer of the second one. Otherwise, it's the\nsum of the decrement of the first and the increment of the second. And you may think of\n\nthat as having two piles. And the way I'm adding these numbers together to make a third\n\npile is by moving marbles from one to the other. Nothing more than that. And eventually,\nwhen I run out of one, then the other is the sum.\n\n\n\n\nHowever, the second procedure here doesn't do it that way. It says if the first number is 0,\n\nthen the answer is the second. Otherwise, it's the increment of the sum of the decrement of\n\nthe first number and the second. So what this says is add together the decrement of the\nfirst number and the second-- a simpler problem, no doubt-- and then change that result to\n\nincrement it.\n\n\n\n\nAnd so this means that if you think about this in terms of piles, it means I'm holding in my\n\nhand the things to be added later. And then I'm going to add them in. As I slowly decrease\none pile to 0, I've got what's left here, and then I'm going to add them back. Two dif ferent\n\nways of adding. The nice thing about these two programs is that they're almost identical.\nThe only thing is where I put the increment. A couple of characters moved around.\n\n\n\n\nNow I want to understand the kind of behavior we're going to get from each of these\n\nprograms. Just to get them firmly in your mind-- I usually don't want to be this careful-- but\n\njust to get them firmly in your mind, I'm going to write the programs again on the\nblackboard, and then I'm going to evolve a process. And you're going to see what happens.\n\nWe're going to look at the shape of the process as a consequence of the program.\nSo the program we started with is this: the sum of x and y says if x is 0, then the result is\ny. Otherwise, it's the sum of the decrement of x and the increment of y.\n\n\n\n\n\nNow, supposing we wish to do this addition of 3 and 4, the sum of 3 and 4, well, what is\nthat? It says that I have to substitute the arguments for the formal parameters in the body.\n\nI'm doing that in my mind. And I say, oh, yes, 3 is substituted for x, but 3 is not 0, so I'm\ngoing to go directly to this part and write down the simplified consequent here. Because I'm\n\nreally interested in the behavior of addition.\n\n\n\n\nWell, what is that? That therefore turns into the sum of 2 and 5. In other wo rds, I've\n\nreduced this problem to this problem. Then I reduce this problem to the sum of 1 and 6,\nand then, going around again once, I get the sum of 0 and 7. And that's one where x equals\n\n0 so the result is y, and so I write down here a 7. So this is the behavior of the process\nevolved by trying to add together 3 and 4 with this program.\n\n\n\n\n\nFor the other program, which is over here, I will define the sum of x and y. And what is it?\nIf x is 0, then the result is y-- almost the same-- otherwise the increment of the sum of the\n\ndecrement of x and y. No. I don't have my balancer in front of me.\n\n\n\n\nOK, well, let's do it now. The sum of 3 and 4. Well, this is actually a little more interesting.\n\nOf course, 3 is not 0 as before, so that results in the increment of thesum of the decrement\nof x, which is 2 and 4, which is the increment of the sum of 1 and -- whoops: the increment\n\nof the increment.\n\n\n\n\nWhat I have to do now is compute what this means. I have to evaluate this. Or what that is,\n\nthe result of substituting 2 and 4 for x and y here. But that is the increment of the sum of 1\nand 4, which is-- well, now I have to expand this. Ah, but that's the increment of the\n\nincrement of the increment of the sum of 0 and 4.\n\n\n\n\nAh, but now I'm beginning to find things I can do. The increment of the increment of the\n\nincrement of-- well, the sum of 0 and 4 is 4. The increment of 4 is 5. So this is the\nincrement of the increment of 5, which is the increment of 6, which is 7. Two different ways\n\nof computing sums.\nNow, let's see. These processes have very different shapes. I want you to feel these shapes.\n\nIt's the feeling for the shapes that matters. What's some things we can see about this? Well,\nsomehow this is sort of straight. It goes this way-- straight. This right edge doesn't vary\n\nparticularly in size.\n\n\n\n\nWhereas this one, I see that this thing gets bigger and then it gets smaller. So I don't know\n\nwhat that means yet, but what are we seeing? We're seeing here that somehow these\nincrements are expanding out and then contracting back. I'm building up a bunch of them\n\nto do later. I can't do them now. There's things to be deferred.\n\n\n\n\nWell, let's see. I can imagine an abstract machine. There's some physical machine, perhaps,\n\nthat could be built to do it, which, in fact, executes these programs exactly as I tell you,\nsubstituting character strings in like this. Such a machine, the number of such steps is an\n\napproximation of the amount of time it takes. So this way is time. And the width of the\nthing is how much I have to remember in order to continue the process. And this much is\n\nspace. And what we see here is a process that takes a time which is proportional to the\nargument x. Because if I made x larger by 1, then I'd had an extra line.\n\n\n\n\n\nSo this is a process which is space-- sorry-- time. The time of this process is what we say\norder of x. That means it is proportional to x by some constant of proportionality, and I'm\n\nnot particularly interested in what the constant is. The other thing we se e here is that the\namount of space this takes up is constant, it's proportional to 1. So the space complexity of\n\nthis is order of 1.\n\n\n\n\nWe have a name for such a process. Such a process is called an iteration. And what matters\n\nhere is not that some particular machine I designed here and talked to you about and called\na substitution machine or whatever-- substitution model-- managed to do this in constant\n\nspace. What really matters is this tells us a bound. Any machine could do this in constant\n\nspace. This algorithm represented by this procedure is executable in constant space.\n\n\n\n\nNow, of course, the model is ignoring some things, standard sorts of things. Like numbers\nthat are bigger take up more space and so on. But that's a level of abstraction at which I'm\n\ncutting off. How do you represent numbers? I'm considering every number to be the same\nsize. And numbers grow slowly for the amount of space they take up and their size.\n\n\n\n\n\nNow, this algorithm is different in its complexity. As we can see here, this algorit hm has a\ntime complexity which is also proportional to the input argument x. That's because if I were\nto add 1 to 3, if I made a larger problem, which is larger by 1 here, then I'd add a line at\n\nthe top and I'd add a line at the bottom. And the fact that it's a constant amount, like this is\ntwice as many lines as that, is not interesting at the level of detail I'm talking about right\n\nnow.\n\n\n\n\nSo this is a time complexity order of the input argument x. And space complexity, well, this\n\nis more interesting. I happen to have some overhead, which you see over here, which is\nconstant approximately. Constant overhead. But then I have something which increases and\n\ndecreases and is proportional to the input argument x. The input argument x is 3. That's\nwhy there are three deferred increments sitting around here. See? So the space complexity\n\nhere is also order x.\n\n\n\n\nAnd this kind of process, named for the kind of process, this is a recursion. A linear\n\nrecursion, I will call it, because of the fact that it's proportional to the input argument in\nboth time and space. This could have been a linear iteration.\n\n\n\n\n\nSo then what's the essence of this matter? This matter isn't so obvious. Maybe there are\nother models by which we can describe the differences between iterative and recursive\n\nprocesses. Because this is hard now. Remember, we have-- those are both recursive\ndefinitions. What we're seeing there are both recursive definitions, definitions that refer to\n\nthe thing being defined in the definition. But they lead to different sh ape processes. There's\nnothing special about the fact that the definition is recursive that leads to a recursive\n\nprocess.\n\n\n\n\nOK. Let's think of another model. I'm going to talk to you about bureaucracy. Bureaucracy\n\nis sort of interesting. Here we see on a slide an iteration. An iteration is sort of a fun kind of\nprocess.\n\n\n\n\n\nImagine that there's a fellow called GJS-- that stands for me-- and he's got a problem: he\nwants to add together 3 and 4. This fella here wants to add together 3 and 4. Well, the way\n\nhe's going to do it-- he's lazy-- is he's going to find somebody else to help him do it. They\nway he finds someone else to-- he finds someone else to help him do it and says, well, give\n\nme the answer to 3 and 4 and return the result to me. He makes a little piece of paper and\nsays, here, here's a piece of paper-- you go ahead and solve this problem and give the\n\nresult back to me.\nAnd this guy, of course, is lazy, too. He doesn't want to see this piece of paper again. He\n\nsays, oh, yes, produce a new problem, which is the sum of 2 ad 5, and return the result\nback to GJS. I don't want to see it again. This guy does not want to see this piece of paper.\n\nAnd then this fellow makes a new problem, which is the addition of the sum of 1 and 6, and\nhe give it to this fella and says, produce that answer and returned it to GJS. And that\n\nproduces a problem, which is to add together 0 and 7, and give the result to GJS. This fella\nfinally just says, oh, yeah, the answer is 7, and sends it back to GJS. That's what an\n\niteration is.\n\n\n\n\nBy contrast, a recursion is a slightly different kind of process. This one involves more\n\nbureaucracy. It keeps more people busy. It keeps more people employed. Perhaps it's\nbetter for that reason.\n\n\n\n\n\nBut here it is: I want the answer to the problem 3 and 4. So I make a piece of paper that\nsays, give the result back to me. Give it to this fella. This fellow says, oh, yes, I will\n\nremember that I have to add later, and I want to get the answer the problem 2 plus 4, give\nthat one to Harry, and have the results sent back to me-- I'm Joe. When the answer comes\n\nback from Harry, which is a 6, I will then do the increment and give that 7 back to GJS. So\n\nthere are more pieces of paper outstanding in the recursive process than the iteration.\n\n\n\n\nThere's another way to think about what an iteration is and the difference between an\niteration and a recursion. You see, the question is, how much stuff is under the table? If I\n\nwere to stop-- supposing I were to kill this computer right now, OK? And at this point I lose\n\nthe state of affairs, well, I could continue the computation from this point but everything I\nneed to continue the computation is in the valuables that were defined in the procedure that\n\nthe programmer wrote for me. An iteration is a system that has all of itsstate in explicit\nvariables.\n\n\n\n\n\nWhereas the recursion is not quite the same. If I were to lose this pile of junk over here,\nand all I was left with was the sum of 1 and 4, that's not enough information to continue the\n\nprocess of computing out the 7 from the original problem of adding together 3 of 4. Besides\nthe information that's in the variables of the formal parameters of the program, there is also\n\ninformation under the table belonging to the computer, which is what things have been\ndeferred for later.\n\n\n\n\n\nAnd, of course, there's a physical analogy to this, which is in differential equations, for\nexample, when we talk about something like drawing a circle. Try to draw a circle, you\n\nmake that out of a differential equation which says the change in my state as a function of\nmy current state. So if my current state corresponds to particular values of y and x, then I\n\ncan compute from them a derivative which says how the state must change.\n\n\n\n\nAnd, in fact, you can see this was a circle because if I happen to be, say, at this place over\n\nhere, at 1, 0, for example, on this graph, then it means that the derivative of y is x, which\nwe see over here. That's 1, so I'm going up. And the derivative of x is minus y, which\n\nmeans I'm going backwards. I'm actually doing nothing at this point, then I start going\nbackwards as y increases.\n\n\n\n\n\nSo that's how you make a circle. And the interesting thing to see is a little program that will\ndraw a circle by this method. Actually, this won't draw a circle because it's a forward oil or\n\nintegrator and will eventually spiral out and all that. But it'll draw a circle for a while before\nit starts spiraling.\n\n\n\n\n\nHowever, what we see here is two state variables, x and y. And there's an iteration that\nsays, in order to circle, given an x and y, what I want is to circle with the next values of x\n\nand y being the old value of x decrement by y times dt where dt is the time step and the old\nvalue of y being implemented by x times dt, giving me the new values of x and y.\n\n\n\n\n\nSo now you have a feeling for at least two different kinds of processes that can be evolved\nby almost the same program. And with a little bit of perturbation analysis like this, how you\n\nchange a program a little bit and see how the process changes, that's how we get some\nintuition. Pretty soon we're going to use that intuition to build big, hairy, complicated\n\nsystems.\n\n\n\n\nThank you.\n\n\n\n\n[MUSIC PLAYING BY J.S. BACH]\n\n\n\n\n\nPROFESSOR: Well, you've just seen a simple perturbational analysis of some programs. I\ntook a program that was very similar to another program and looked at them both and saw\n\nhow they evolved processes. I want to show you some variety by showing you some other\nprocesses and shapes they may have. Again, we're going to take very simple things,\n\nprograms that you wouldn't want to ever write. They would be probably the worst way of\ncomputing some of the things we're going to compute. But I'm just going to show you these\nthings for the purpose of feeling out how to program represents itself as the rule for the\n\nevolution of a process.\n\n\n\n\nSo let's consider a fun thing, the Fibonacci numbers. You probably know about the Fibonacci\n\nnumbers. Somebody, I can't remember who, was interested in the growth of piles of\nrabbits. And for some reason or other, the piles of rabbits tend to grow exponenti ally, as we\n\nknow.\n\n\n\n\nAnd we have a nice model for this process, is that we start with two numbers, 0 and 1. And\n\nthen every number after this is the sum of the two previous. So we have here a 1. Then the\nsum of these two is 2. The sum of those two is 3. The sum of those two is 5. The sum of\n\nthose two is 8. The sum of those two is 13. This is 21. 34. 55. Et cetera.\n\n\n\n\nIf we start numbering these numbers, say this is the zeroth one, the first one, the second\n\none, the third one, the fourth one, et cetera. This isthe 10th one, the 10th Fibonacci\nnumber. These numbers grow very fast. Just like rabbits. Why rabbits grow this way I'm not\n\ngoing to hazard a guess.\n\n\n\n\nNow, I'm going to try to write for you the very simplest program that computes Fibonacci\n\nnumbers. What I want is a program that, given an n, will produce for me Fibonacci event.\nOK? I'll write it right here. I want the Fibonacci of n, which means the -- this is the n, and\n\nthis is Fibonacci of n. And here's the story. If n is less than 2, then the result is n. Because\nthat's what these are. That's how you start it up. Otherwise, the result is the sum of Fib of n\n\nminus 1 and the Fibonacci number, n minus 2.\n\n\n\n\nSo this is a very simple, direct specification of the description of Fibonacci numbers that I\n\ngave you when I introduced those numbers. It represents the recurrence relation in the\nsimplest possible way.\n\n\n\n\n\nNow, how do we use such a thing? Let's draw this process. Let's figure out what this does.\nLet's consider something very simple by computing Fibonacci of 4. To compute Fibonacci of\n\n4, what do I do?\n\n\n\n\nWell, it says I have-- it's not less than 2. Therefore it's the sum of two things. Well, in order\nto compute that I have to compute, then, Fibonacci of 3 and Fibonacci of 2. In order to\n\ncompute Fibonacci of 3, I have to compute Fibonacci of 2 and Fibonacci of 1. In order to\ncompute Fibonacci of 2, I have to compute Fibonacci of 1 and Fibonacci of 0. In order to\n\ncompute Fibonacci of 1, well, the answer is 1. That's from the base case of this recursion.\nAnd in order to compute Fibonacci of 0, well, that answer is 0, from the same base. And\n\nhere is a 1. And Fibonacci of 2 is really the sum of Fibonacci of 1. And Fib of 0, in order to\ncompute that, I get a 1, and here I've got a 0.\n\n\n\n\n\nI've built a tree. Now, we can observe some things about this tree. We can see why this is\nan extremely bad way to compute Fibonacci numbers. Because in order to compute\n\nFibonacci of 4, I had to compute Fibonacci of 2's sub-tree twice.\n\n\n\n\nIn fact, in order way to add one more, supposing I want to do Fibonacci of 5, what I really\n\nhave to do then is compute Fibonacci of 4 plus Fibonacci of 3. But Fibonacci of 3's sub-tree\nhas already been built. This is a prescription for a process that's exponential in time. To add\n\n1, I have to multiply by something because I take a proportion of the existing thing and add\nit to itself to add one more step. So this is a thing whose time complexity is order of --\n\nactually, it turns out to be Fibonacci-- of n.\n\n\n\n\n\n\nThere's a thing that grows exactly at Fibonacci numbers. It's a horrible thing. You wouldn't\nwant to do it. The reason why the time has to grow that way is because we're presuming in\n\nthe model-- the substitution model that I gave you, which I'm not doing formally here, I\nsort of now spit it out in a simple way-- but presuming that everything is done sequentially.\n\nThat every one of these nodes in this tree has to be examined. And so since the number of\n\nnodes in this tree grows exponentially, because I add a proportion of the existing nodes to\nthe nodes I already have to add 1, then I know I've got an exponential explosion here.\n\n\n\n\nNow, let's see if we can think of how much space this takes up. Well, it's not so bad. It\n\ndepends on how much we have to remember in order to continue this thing running. Well,\n\nthat's not so hard. It says, gee, in order to know where I am in this tree, I have to have a\npath back to the root. In other words, in order to-- let's consider the path I would have to\n\nexecute this.\n\n\n\n\nI'd say, oh, yes, I'm going to go down here. I don't care which direction I go. I have to do\nthis. I have to then do this. I have to traverse this tree in a sort of funny way. I'm going to\n\nwalk this nice little path. I come back to here. Well, I've got to remember where I'm going\n\nto be next. I've got to keep that in mind. So I have to know what I've done. I have to know\nwhat's left. In order to compute Fibonacci of 4, at some point I'm going to have to be down\n\nhere. And I have to remember that I have to go back and then go back to here to do an\naddition. And then go back to here to do an addition to something I haven't touched yet.\nThe amount of space that takes up is the path, the longest path. How long it is. And that\ngrows as n. So the space-- because that's the length of the deepest line through the tree--\n\nthe space is order of n. It's a pretty bad process.\n\n\n\n\nNow, one thing I want to see from this is a feeling of what's going on here. Why are there --\n\nhow is this program related to this process? Well, what are we seeing here? There really are\nonly two sorts of things this program does. This program consists of two rules, if you will.\n\nOne rule that says Fibonacci of n is this sum that you see over here, which is a node that's\nshaped like this. It says that I break up something into two parts. Under some condition\n\nover here that n is greater than 2, then the node breaks up into two parts. Less than 2. No.\n\nGreater than 2. Yes.\n\n\n\n\nThe other possibility is that I have a reduction that looks like this. And that's this case. If it's\nless than 2, the answer is n itself.\n\n\n\n\n\nSo what we're seeing here is that the process that got built locally at every place is an\ninstance of this rule. Here's one instance of the rule. Here is another instance of the rule.\n\n\n\n\n\nAnd the reason why people think of programming as being hard, of course, is because\nyou're writing down a general rule, which is going to be used for lots of instances, that a\n\nparticular instance-- it's going to control each particular instance for you. You've got to write\ndown something that's a general in terms of variables, and you have to think of all the\n\nthings that could possibly fit in those variables, and all those have to lead to the process\nyou want to work. Locally, you have to break up your process into things that can be\n\nrepresented in terms of these very specific local rules.\n\n\n\n\nWell, let's see. Fibonaccis are, of course, not much fun. Yes, they are. You get something\n\ncalled the golden ratio, and we may even see a lot of that some time.\n\n\n\n\nWell, let's talk about another thing. There's a famous game called the T owers of Hanoi,\n\nbecause I want to teach you how to think about these recursively.\n\n\n\n\nThe problem is this one: I have a bunch of disks, I have a bunch of spikes, and it's rumored\n\nthat somewhere in the Orient there is a 64-high tower, and the job of various monks or\nsomething is to move these spikes in some complicated pattern so eventually -- these disks-\n\n- so eventually I moved all of the disks from one spike to the other. And if it's 64 high, and\nit's going to take 2 to the 64th moves, then it's a long time. They claim that the universe\n\nends when this is done.\n\n\n\n\nWell, let's see. The way in which you would construct a recursive process is by wishful\n\nthinking. You have to believe.\n\n\n\n\nSo, the idea. Supposing I want to move this pile from here to here, from spike one to spike\n\ntwo, well, that's not so hard. See, supposing somehow, by some magic-- because I've got a\nsimpler problem-- I move a three-high pile to here-- I can only move one disk at a time, so\n\nidentifying how I did it. But supposing I could do that, well, then I could just pick up this\ndisk and move it here. And now I have a simple problem. I have to move a three-high tower\n\nto here, which is no problem. So by two moves of a three high tower plus one move of a\nsingle object, I can move the tower from here to here.\n\n\n\n\n\nNow, whether or not-- this is not obvious in any deep way that this works. And why? Now,\nwhy is it the case that I can presume, maybe, that I can move the three-high tower? Well,\n\nthe answer is because I'm always counting down, and eventually I get down to zero -high\ntower, and a zero-high tower requires no moves.\n\n\n\n\n\nSo let's write the algorithm for that. Very easy. I'm going to label these towers with\nnumbers, but it doesn't matter what they're labelled with. And the problem is to move an n -\n\nhigh tower from a spike called From to a spike called To with a particular spike called Spare.\nThat's what we're going to do.\n\n\n\n\n\nUsing the algorithm I informally described to you, move of a n-high tower from From to To\nwith a Spare. Well, I've got two cases, and this is a case analysis, just like it is in all the\n\nother things we've done.\n\n\n\n\nIf n is 0, then-- I'm going to put out some answers-- Done, we'll say. I don't know what\n\nthat means. Because we'll never use that answer for anything. We're going to do these\nmoves. Else. I'm going to do a move. Move a tower of height less than n, the decrement of\n\nn height. Now, I'm going to move it to the Spare tower. The whole idea now is to move this\nfrom here to here, to the Spare tower-- so from From to Spare-- using To as a spare tower.\nLater, somewhere later, I'm going to move that same n-high tower, after I've done this.\n\nGoing to move that same n minus one-high tower from the Spare tower to the To tower\nusing the From tower as my spare. So the Spare tower to the To tower using the From as\n\nthe spare.\n\n\n\n\nAll I have to do now is when I've gotten it in this condition, between these two moves of a\n\nwhole tower-- I've got it into that condition-- now I just have to move one disk. So I'm\ngoing to say that some things are printing a move and I don't care how it works. From the\n\nTo.\n\n\n\n\nNow, you see the reason why I'm bringing this up at this moment is this is an almost\n\nidentical program to this one in some sense. It's not computing the same mathematical\nquantity, it's not exactly the same tree, but it's going to produce a tree. The general way of\n\nmaking these moves is going to lead to an exponential tree.\n\n\n\n\nWell, let's do this four -high. I have my little crib sheet here ot herwise I get confused. Well,\n\nwhat I'm going to put in is the question of move a tower of height four from one to spike\ntwo using spike three as a spare. That's all I'm really going to do. You know, let's just do it.\n\nI'm not going to worry about writing out the traits of this. You can do that yourself because\nit's very simple.\n\n\n\n\n\nI'm going to move disk one to disk three. And how do I get to move disk one to disk three?\nHow do I know that? Well, I suppose I have to look at the trace a little bit. What am I do ing\n\nhere? Well, and this is not -- n is not zero. So I'm going to look down here. This is going to\nrequire doing two moves. I'm only going to look at the first one. It's going to require\n\nmoving-- why do I have move tower? It makes it harder for me to move.I'm going to move\na three-high tower from the from place, which is four, to the spare, which is two, using\n\nthree as my-- no, using from--\n\n\n\n\nSTUDENT: [INAUDIBLE PHRASE].\n\n\n\n\n\nPROFESSOR: Yes. I'm sorry.\n\n\n\n\nFrom two-- from one to three using two as my spare. That's right. And then there's another\nmove over here afterwards. So now I say, oh, yes, that requires me moving a two-high\n\ntower from one to two using three as a spare. And so, are the same, and that's going to\nrequire me moving and one-high tower from one to three using two as a spare. Well, and\n\nthen there's lots of other things to be done.\n\n\n\n\nSo I move my one-high tower from one to three using two as a spare, which I didn't do\n\nanything with. Well, this thing just proceeds very simply. I move this from one to two. And I\nmove this disk from three to two. And I don't really want to do it, but I move from one to\n\nthree. Then I move two to one. Then I move two to three. Then one to three. One to two.\nThree to two. Three to one. This all got worked out beforehand, of course. Two to one.\n\nThree to two. One to three.\n\n\n\n\nSTUDENT: [INAUDIBLE PHRASE].\n\n\n\n\nPROFESSOR: Oh, one to three. Excuse me. Thank you.\n\n\n\n\n\nOne to two. And then three to two. Whew.\n\n\n\n\nNow what I'd like you to think about, you just saw a recursive algorithm for doing this, and\n\nit takes exponential time, of course. Now, I don't know if there's any algorithm that doesn't\ntake exponential time-- it has to. As I'm doing one operation-- I can only move one thing at\n\na time-- there's no algorithm that's not going to take exponential time.\n\n\n\n\nBut can you write an iterative algorithm rather than a recursive algorithm for doing this?\n\nOne of the sort of little things I like to think about. Can you write one that, in fact, doesn't\nbreak this problem into two sub-problems the way I described, but rather proceeds a step\n\nat a time using a more local rule? That might be fun.\n\n\n\n\nThank you so much for the third segment.\n\n\n\n\nAre there questions?\n\n\n\n\n\nSTUDENT: [INAUDIBLE] a way to reduce a tree or recursion problem, how do you save the\nimmediate work you have done in computing the Fibonacci number?\nPROFESSOR: Oh, well, in fact, one of the ways to do is what you just said. You said, I save\nthe intermediate work. OK? Well, let me tell you-- this, again, we'll see later -- but suppose\n\nit's the case that anytime I compute anything, any one of these Fibonacci numbers, I\nremember the table that takes only linear time to look up the answer. Then if I ever see it\n\nagain, instead of doing the expansional tree, I look it up. I've just transformed my problem\n\ninto a problem that's much simpler.\n\n\n\n\nNow, of course, there are the way to do this, a s well. That one's called memoization, and\nyou'll see it sometime later in this term. But I suppose there's a very simple linear time,\n\nand, in fact, iterative model for computing Fibonaccis, and that's another thing you should\n\nsit down and work out. That's important. It's important to see how to do this. I want you to\npractice.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec2a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 2A: Higher-order Procedures\n\n\n\nPROFESSOR: Well, yesterday was easy. You learned all of the rules of programming and\nlived. Almost all of them. And so at this point, you're now certified programmers -- it says.\n\nHowever, I suppose what we did is we, aah, sort of got you a little bit of into an easy state.\nHere, you still believe it's possible that this might be programming in BASIC or Pascal with\n\njust a funny syntax. Today, that illusion-- or you can no longer support that belief. What\nwe're going to do today is going to completely smash that.\n\n\n\n\n\nSo let's start out by writing a few programs on the blackboard that have a lot in common\nwith each other. What we're going to do is try to make them abstractions that are not ones\n\nthat are easy to make in most languages. Let's start with some very si mple ones that you\ncan make in most languages.\n\n\n\n\n\nSupposing I want to write the mathematical expression which adds up a bunch of integers.\nSo if I wanted to write down and say the sum from i equal a to b on i. Now, you know that\n\nthat's an easy thing to compute in a closed form for it, and I'm not interested in that. But\nI'm going to write a program that adds up those integers.\n\n\n\n\n\nWell, that's rather easy to do to say I want to define the sum of the integers from a to b to\nbe-- well, it's the following two possibilities. If a is greater than b, well, then there's nothing\n\nto be done and the answer is zero. This is how you're going to have to think recursively.\nYou're going to say if I have an easy case that I know the answer to, just write it down.\n\nOtherwise, I'm going to try to reduce this problem to a simpler problem. And maybe in this\ncase, I'm going to make a subproblem of the simpler problem and then do something to\n\nthe result. So the easiest way to do this is say that I'm going to add the index, which in this\ncase is a, to the result of adding up the integers from a plus 1 to b.\n\n\n\n\n\nNow, at this point, you should have no trouble looking at such a definition. Indeed, coming\nup with such a thing might be a little hard in synthesis, but being able to read it at this point\n\nshould be easy. And what it says to you is, well, here is the subproblem I'm going to solve.\nI'm going to try to add up the integers, one fewer integer than I added up for the the whole\n\nproblem. I'm adding up the one fewer one, and that subproblem, once I've solved it, I'm\n\ngoing to add a to that, and that will be the answer to this problem. And the simplest case, I\ndon't have to do any work.\nNow, I'm also going to write down another simple one just like this, which is the\nmathematical expression, the sum of the square from i equal a to b. And again, it's a very\n\nsimple program. And indeed, it starts the same way. If a is greater than b, then the answer\nis zero. And, of course, we're beginning to see that there's something wrong with me writing\n\nthis down again. It's the same program. It's the sum of the square of a and the sum of the\n\nsquare of the increment and b.\n\n\n\n\nNow, if you look at these things, these programs are almost identical. There's not much to\ndistinguish them. They have the same first clause of the conditional and the same predicate\n\nand the same consequence, and the alternatives are very similar, too. They only differ by\n\nthe fact that where here I have a, here, I have the square of a. The only other difference,\nbut this one's sort of unessential is in the name of this procedure is sum int, whereas the\n\nname of the procedure is sum square. So the things that vary between these two are very\nsmall.\n\n\n\n\n\nNow, wherever you see yourself writing the same thing down more than once, there's\nsomething wrong, and you shouldn't be doing it. And the reason is not because it's a waste\n\nof time to write something down more than once. It's because there's some idea here, a\nvery simple idea, which has to do with the sigma notation-- this much-- not depending upon\n\nwhat it is I'm adding up. And I would like to be able to-- always, whenever trying to make\ncomplicated systems and understand them, it's crucial to divide the things up into as many\n\npieces as I can, each of which I understand separately. I would like to understand the way\nof adding things up independently of what it is I'm adding up so I can do that having\n\ndebugged it once and understood it once and having been able to share that among many\n\ndifferent uses of it.\n\n\n\n\nHere, we have another example. This is Leibnitz's formula for finding pi over 8. It's a funny,\nugly mess. What is it? It's something like 1 over 1 times 3 plus 1 over 5 times 7 plus 1 over\n\n9 times 11 plus-- and for some reason, things like this tend to have interesting values like\npi over 8. But what do we see here? It's the same program or almost the same program.\n\nIt's a sum. So we're seeing the figure notation, although over here, we're dealing with\n\nincrementing by 4, so it's a slightly different problem, which means that over here, I have\nto change a by 4, as you see right over here. It's not by 1.\n\n\n\n\nThe other thing, of course, is that the thing that's represented by square in the previous\n\nsum of squares, or a when adding up the integers. Well, here, I have a different thing I'm\n\nadding up, a different term, which is 1 over a times a plus 2. But the rest of this program is\nidentical. Well, any time we have a bunch of things like this that are identical, we're going\n\nto have to come up with some sort of abstraction to cover them.\nIf you think about this, what you've learned so far is the rules of some language, some\nprimitive, some means of combination, almost all of them, the means of abstraction, almost\n\nall of them. But what you haven't learned is common patterns of usage.\n\n\n\n\nNow, most of the time, you learn idioms when learning a language, which is a common\n\npattern that mean things that are useful to know in a flash. And if you build a great number\nof them, if you're a FORTRAN programmer, of course, everybody knows how to-- what do\n\nyou do, for example, to get an integer which is the biggest integer in something. It's a\nclassic thing. Every FORTRAN programmer knows how to do that. And if you don't know\n\nthat, you're in real hot water because it takes a long time to think it out. However, one of\n\nthe things you can do in this language that we're showing you is not only do you know\nsomething like that, but you give the knowledge of that a name. And so that's what we're\n\ngoing to be going after right now.\n\n\n\n\nOK, well, let's see what these things have in common. Right over here we have what\n\nappears to be a general pattern, a general pattern which covers all of the cases we've seen\nso far. There is a sum procedure, which is being defined. It has two arguments, which are a\n\nlower bound and an upper bound. The lower bound is tested to be greater than the upper\nbound, and if it is greater, then the result is zero. Otherwise, we're going to do something\n\nto the lower bound, which is the index of the conversation, and add that result to the result\nof following the procedure recursively on our lower bound incremented by some next\n\noperation with the same upper bound as I had before.\n\n\n\n\nSo this is a general pattern, and what I'd like to do is be able to name this general pattern a\n\nbit. Well, that's sort of easy, because one of the things I'm going to do right now is-- there's\nnothing very special about numbers. Numbers are just one kind of data. It seems to me\n\nperfectly reasonable to give all sorts of names to all kinds of data, for example, procedures.\nAnd now many languages allow you have procedural arguments, and right now, we're going\n\nto talk about procedural arguments. They're very easy to deal with. And shortly, we'll do\nsome remarkable things that are not like procedural arguments.\n\n\n\n\n\nSo here, we'll define our sigma notation. This is called sum and it takes a term, an A, a next\nterm, and B as arguments. So it takes four arguments, and there was nothing particularly\n\nspecial about me writing this in lowercase. I hope that it doesn't confuse you, so I' ll write it\nin uppercase right now. The machine doesn't care.\nBut these two arguments are different. These are not numbers. These are going to be\n\nprocedures for computing something given a number. Term will be a procedure which, when\ngiven an index, will produce the value of the term for that index. Next will be given an\n\nindex, which will produce the next index. This will be for counting. And it's very simple. It's\nexactly what you see. If A is greater than B, then the result is 0. Otherwise, it's the sum of\n\nterm applied to A and the sum of term, next index.\n\n\n\n\nLet me write it this way. Now, I'd like you to see something, first of all. I was writing here,\n\nand I ran out of space. What I did is I start indenting according to the Pretty-printing rule,\nwhich says that I align all of the arguments of the procedure so I can see which ones go\n\ntogether. And this is just something I do automatically, and I want you to learn how to do\nthat, too, so your programs can be read and understood.\n\n\n\n\n\nHowever, what do we have here? We have four arguments: the procedure, the lower index-\n- lower bound index-- the way to get the next index, and the upper bound. What's passed\n\nalong on the recursive call is indeed the same procedure because I'm going to need it again,\nthe next index, which is using the next procedure to compute it, the procedure for\n\ncomputing next, which I also have to have separately, and that's different. The procedure\n\nfor computing next is different from the next index, which is the result of using next on the\nlast index. And I also have to pass along the upper bound. So this captures both of these\n\nand the other nice program that we are playing with.\n\n\n\n\nSo using this, we can write down the original program as instances of sum very simply. A\n\nand B. Well, I'm going to need an identity procedure here because ,ahh, the sum of the\nintegers requires me to in this case compute a term for every integer, but the term\n\nprocedure doesn't want to do anything to that integer. So the identity procedure on A is A\nor X or whatever, and I want to say the sum of using identity of the term procedure and\n\nusing A as the initial index and the incrementer being the way to get the next index and B\nbeing the high bound, the upper bound. This procedure does exactly the same as the sum\n\nof the integers over here, computes the same answer.\n\n\n\n\nNow, one thing you should see, of course, is that there's nothing very special over here\n\nabout what I used as the formal parameter. I could have, for example, written this X. It\ndoesn't matter. I just wanted you to see that this name does not conflict with this one at all.\n\nIt's an internal name.\n\n\n\n\nFor the second procedure here, the sum of the squares, it's even a little bit easier. And what\n\ndo we have to do? Nothing more than add up the squares, this is the procedure that each\nindex will be given, will be given each-- yes. Each index will have this done to it to get the\nterm. That's the thing that maps against term over here. Then I have A as the lower bound,\n\nthe incrementer as the next term method, and B as the upper bound.\n\n\n\n\nAnd finally, just for the thing that we did about pi sums, pi sums are sort of-- well, it's even\n\neasier to think about them this way because I don't have to think. What I'm doing is\nseparating the thing I'm adding up from the method of doing the addition. And so we have\n\nhere, for example, pi sum A B of the sum of things. I'm going to write the terms procedure\nhere explicitly without giving it a name. This is done anonymously. I don't necessarily have\n\nto give a name to something if I just want to use it once.\n\n\n\n\nAnd, of course, I can write sort of a expression that produces a procedure. I'm going to\n\nwrite the Greek lambda letter here instead of L-A-M-B-D-A in general to avoid taking up a\nlot of space on blackboards. But unfortunately, we don't have lambda keys on our\n\nkeyboards. Maybe we can convince our friends in the computer industry that this is an\nimportant. Lambda of i is the quotient of 1 and the product of i and the sum of i 2, starting\n\nat a with the way of incrementing being that procedure of an index i, which adds i to 4, and\nb being the upper bound. So you can see that this notation, the invention of the procedure\n\nthat takes a procedural argument, allows us to compress a lot of these procedures into one\n\nthing. This procedure, sums, covers a whole bunch of ideas.\n\n\n\n\nNow, just why is this important? I tried to say before that it helps us divide a problem into\ntwo pieces, and indeed, it does, for example, if someone came up with a different way of\n\nimplementing this, which, of course, one might . Here, for example, an iterative\n\nimplementation of sum. Iterative implementation for some reason might be better than the\nrecursive implementation. But the important thing is that it's different.\n\n\n\n\nNow, supposing I had written my program this way that you see on the blackboard on the\n\nleft. That's correct, the left. Well, then if I want to change the method of addition, then I'd\n\nhave to change each of these. Whereas if I write them like this that you see here, then the\nmethod by which I did the addition is encapsulated in the procedure sum. That\n\ndecomposition allows me to independently change one part of the program and prove it\nperhaps without changing the other part that was written for some of the other cases.\n\nThank you. Are there any questions? Yes, sir.\n\n\n\n\nAUDIENCE: Would you go over next A and next again on--\nPROFESSOR: Yes. It's the same problem. I'm sure you're going to-- you're going to have to\n\nwork on this. This is hard the first time you've ever seen something like this.\n\n\n\n\nWhat I have here is a-- procedures can be named by variables. Procedures are not special.\n\nActually, sum square is a variable, which has gotten a value, which is a procedure. This is\ndefine sum square to be lambda of A and B something. So the procedure can be named.\n\nTherefore, they can be passed from one to another, one procedure to another, as\narguments. Well, what we're doing here is we're passing the procedure term as an\n\nargument to sum just when we get it around in the next recursive.\n\n\n\n\nHere, we're passing the procedure next as an argument also. However, here we're using the\n\nprocedure next. That's what the parentheses mean. We're applying next to A to get the next\nvalue of A. If you look at what next is mapped against, remember that the way you think\n\nabout this is that you substitute the arguments for the formal parameters in the body. If\nyou're ever confused, think of the thing that way.\n\n\n\n\n\nWell, over here, with sum of the integers. I substitute identity for a term and 1 plus the\nincrementer for next in the body. Well, the identity procedure on A is what I get here.\n\nIdentity is being passed along, and here, I have increment 1 plus being applied to A and 1\nplus is being passed along. Does that clarify the situation?\n\n\n\n\n\nAUDIENCE: We could also define explicitly those two functions, then pass them.\n\n\n\n\nPROFESSOR: Sure. What we can do is we could have given names to them, just like I did\n\nhere. In fact, I gave you various ways so you could see it, a variety. Here, I define the thing\nwhich I passed the name of. I referenced it by its name. But the thing is, in fact, that\n\nprocedure, one argument X, which is X. And the identity procedure is just lambda of X X.\nAnd that's what you're seeing here. Here, I happened to just write its canonical name there\n\nfor you to see. Is it OK if we take our five-minute break?\n\n\n\n\n\n\nAs I said, computers to make people happy, not people to make computers happy. And for\nthe most part, the reason why we introduce all this abstraction stuff is to make it so that\n\nprograms can be more easily written and more easily read. Let's try to understand what's\nthe most complicated program we've seen so far using a little bit of this abstraction stuff.\nIf you look at the slide, this is the Heron of Alexandria's method of computing square roots\n\nthat we saw yesterday. And let's see. Well, in any case, this program is a little complicated.\nAnd at the current state of your thinking, you just can't look at that and say, oh, this\n\nobviously means something very clear. It's not obvious from looking at the program what\nit's computing. There's some loop here inside try, and a loop does something about trying\n\nthe improvement of y. There's something called improve, which does some averaging and\nquotienting and things like that. But what's the real idea? Can we make it clear what the\n\nidea is? Well, I think we can. I think we can use abstraction that we have learned about so\n\nfar to clarify what's going on.\n\n\n\n\nNow, what we have mathematically is a procedure for improving a guess for square roots.\nAnd if y is a guess for a square root, then what we want to get we'll call a function f. This is\n\nthe means of improvement. I want to get y plus x/y over 2, so the average of y and x\n\ndivided by y as the improved value for the square root of x such that-- one thing you can\nnotice about this function f is that f of the square root of f is in fact the square root of x. In\n\nother words, if I take the square root of x and substitute it for y here, I see the square root\nof x plus x divided by the square of x, which is the square root of x. That's 2 times the\n\nsquare root of x divided by 2, is the square root of x.\n\n\n\n\nSo, in fact, what we're really looking for is we're looking for a fixed point, a fixed point of\n\nthe function f. A fixed point is a place which has the property that if you put it into the\nfunction, you get the same value out. Now, I suppose if I were giving some nice, boring\n\nlecture, and you happened to have in front of you an HP -35 desk calculator like I used to\nhave when I went to boring lectures. And if you think it was really boring, you put it into\n\nradians mode, and you hit cosine, and you hit cosine, and you hit cosine. And eventually,\nyou end up with 0.734 or something like that. 0.743, I don't remember what exactly, and it\n\ngets closer and closer to that. Some functions have the property that you can find their\n\nfixed point by iterating the function, and that's essentially what's happening in the square\nroot program by Heron's method.\n\n\n\n\nSo let's see if we can write that down, that idea. Now, I'm not going to say how I compute\n\nfixed points yet. There might be more than one way. But the first thing to do is I'm going to\nsay what I just said. I'm going to say it specifically, the square root. The square root of x is\n\nthe fixed point of that procedure which takes an argument y and averages of x divided by y\n\nwith y. And we're going to start up with the initial guess for the fixed point of 1. It doesn't\nmatter where it starts. A theorem having to do with square roots.\n\n\n\n\nSo what you're seeing here is I'm just trying to write out by wishful thinking. I don't know\n\nhow I'm going to make fixed point happen. We'll worry about that later. But if somehow I\nhad a way of finding the fixed point of the function computed by this procedure, then I\n\nwould have-- that would be the square root that I'm looking for.\n\n\n\n\nOK, well, now let's see how we're going to write-- how we're going to come up with fixed\n\npoints. Well, it's very simple, actually. I'm going to write an abbreviated version here just so\nwe understand it. I'm going to find the fixed point of a function f-- actually, the fixed point\n\nof the function computed by the procedure whose name will be f in this procedure. How's\nthat? A long sentence-- starting with a particular starting value.\n\n\n\n\n\nWell, I'm going to have a little loop inside here, which is going to push the button on the\ncalculator repeatedly, hoping that it will eventually converge. And we will say here internal\n\nloops are written by defining internal procedures. Well, one thing I'm going to have to do is\nI'm going to have to say whether I'm done. And the way I'm going to decide when I'm done\n\nis when the old value and the new value are close enough so I can't distinguish them\nanymore. That's the standard thing you do on the calculator unless you look at more\n\nprecision, and eventually, you run out of precision.\n\n\n\n\nSo the old value and new value, and I'm going to stay here if I can't distinguish them if\n\nthey're close enough, and we'll have to worry about what that is soon. The old value and\nthe new value are close enough to each other and let's pick the new value as the answer.\n\nOtherwise, I'm going to iterate around again with the next value of old being the current\nvalue of new and the next value of new being the result of calling f on new. And so this is\n\nmy iteration loop that pushes the button on the calculator. I basically think of it as having\n\ntwo registers on the calculator: old and new. And in each step, new becomes old, and new\ngets F of new. So this is the thing where I'm getting the next value.\n\n\n\n\nAnd now, I'm going to start this thing up by giving two values. I wrote down on the\n\nblackboard to be slow so you can see this. This is the first time you've seen something quite\n\nthis complicated, I think. However, we might want to see the whole thing over here in this\ntransparency or slide or whatever. What we have is all of the details that are required to\n\nmake this thing work. I have a way of getting a tolerance for a close enough procedure,\nwhich we see here. The close enough procedure, it tests whether u and v are close enough\n\nby seeing if the absolute value of the difference in u and v is less than the given tolerance,\nOK? And here is the iteration loop that I just wrote on the blackboard and the initialization\n\nfor it, which is right there. It's very simple.\n\n\n\n\nBut let's see. I haven't told you enough. It's actually easier than this. There is more\n\nstructure to this problem than I've already told you. Like why should this work? Why should\nit converge? There's a hairy theorem in mathematics tied up in what I've written here. Why\nis it that I should assume that by iterating averaging the quotient of x and y and y that I\n\nshould get the right answer? It isn't so obvious.\n\n\n\n\nSurely there are other things, other procedures, which compute functions whose fixed\n\npoints would also be the square root. For example, the obvious one will be a new function g,\nwhich maps y to x/y. That's even simpler. The fixed point of g is surely the square root also,\n\nand it's a simpler procedure.\n\n\n\n\nWhy am I not using it? Well, I suppose you know. Supposing x is 2 and I start out with 1,\n\nand if I divide 1 into 2, I get 2. And then if I divide 2 into 2, I get 1. If I divide 1 into 2, I\nget 2, and 2 into 2, I get 1, and I never get any closer to the square root. It just oscillates.\n\nSo what we have is a signal processing system, an electrical circuit which is oscillating, and\nI want to damp out these oscillations. Well, I can do that.\n\n\n\n\n\nSee, what I'm really doing here when I'm taking my average, the average is averaging the\nlast two values of something which oscillates, getting something in between. The classic\n\nway is damping out oscillations in a signal processing system. So why don't we write down\nthe strategy that I just said in a more clear way? Well, that's easy enough.\n\n\n\n\n\nI'm going to define the square root of x to be a fixed point of the procedure resulting from\naverage damping. So I have a procedure resulting from average damp of the procedure,\n\nthat procedure of y, which divides x by y starting out at 1. Ah, but average damp is a\nspecial procedure that's going to take a procedure as its argument and return a procedure\n\nas its value. It's a generalization that says given a procedure, it's the thing which produces\na procedure which averages the last value and the value before and after running the\n\nprocedure. You can use it for anything if you want to damp out oscillations. So let's write\nthat down. It's very easy.\n\n\n\n\n\nAnd stylistically here, I'm going to use lambda notation because it's much easier to think\nwhen you're dealing with procedure, the mid-line procedures, to understand that the\n\nprocedures are the objects I'm dealing with, so I'm going to use lambda notation here. Not\nalways. I don't always use it, but very specifically here to expand on that idea, to elucidate\n\nit.\n\n\n\n\nWell, average damp is a procedure, which takes a procedure as its argument, which we will\n\ncall f. And what does it produce? It produces as its value-- the body of this procedure is a\nthing which produces a procedure, the construct of the procedures right here, of o ne\n\nargument x, which averages f of x with x.\n\n\n\n\nThis is a very special thing. I think for the first time you're seeing a procedure which\n\nproduces a procedure as its value. This procedure takes the procedure f and does something\nto it to produce a new procedure of one argument x, which averages f-- this f-- applied to x\n\nand x itself. Using the context here, I apply average damping to the procedure, which just\ndivides x by y. It's a division. And I'm finding to fixed point of that, and that's a clearer way\n\nof writing down what I wrote down over here, wherever it was. Here, because it tells why I\nam writing this down.\n\n\n\n\n\nI suppose this to some extent really clarifies what Heron of Alexandria was up to. I suppose\nI'll stop now. Are there any questions?\n\n\n\n\n\nAUDIENCE: So when you define average damp, don't you need to have a variable on f?\n\n\n\n\nPROFESSOR: Ah, the question was, and here we're having-- again, you've got to learn\nabout the syntax. The question was when defining average damp, don't you have to have a\n\nvariable defined with f? What you are asking about is the formal parameter of f?\n\n\n\n\nAUDIENCE: Yeah.\n\n\n\n\n\nPROFESSOR: OK. The formal parameter of f is here. The formal parameter of f--\n\n\n\n\nAUDIENCE: The formal parameter of average damp.\n\n\n\n\nPROFESSOR: F is being used to apply it to an argument, right? It's indeed true that f must\n\nhave a formal parameter. Let's find out what f's formal parameter is.\n\n\n\n\nAUDIENCE: The formal parameter of average damp.\nPROFESSOR: Oh, f is the formal parameter of average damp. I'm sorry. You're just\n\nconfusing a syntactic thing. I could have written this the other way. Actually, I didn't\nunderstand your question. Of course, I could have written it this other way. Those are\n\nidentical notations. This is a different w ay of writing this. You're going to have to get used to\nlambda notation because I'm going to use it.\n\n\n\n\n\nWhat it says here, I'm defining the name average damp to name the procedure whose of\none argument f. That's the formal parameter of the procedure averagedamp. What define\n\ndoes is it says give this name a value. Here is the value of for it. That there happens to be a\nfunny syntax to make that easier in some cases is purely convenience. But the reason why I\n\nwrote it this way here is to emphasize that I'm dealing with a procedure that takes a\nprocedure as its argument and produces a procedure as its value.\n\n\n\n\n\nAUDIENCE: I don't understand why you use lambda twice. Can you just use one lambda and\ntake two arguments f and x?\n\n\n\n\n\nPROFESSOR: No.\n\n\n\n\nAUDIENCE: You can't?\n\n\n\n\nPROFESSOR: No, that would be a different thing. If I were to write the procedure lambda of\n\nf and x, the average of f of x and x, that would not be something which would be allowed to\ntake a procedure as an argument and produce a procedure as its value. That would be a\n\nthing that takes a procedure as its argument and numbers its argument and produces a new\n\nnumber. But what I'm producing here is a procedure to fit in the procedure slot over here,\nwhich is going to be used over here. So the number has to come from here. This is the thing\n\nthat's going to eventually end up in the x. And if you're confused, you should do some\nsubstitution and see for yourself. Yes?\n\n\n\n\n\nAUDIENCE: Will you please show the definition for average damp without using lambda\nnotation in both cases.\n\n\n\n\nPROFESSOR: I can't make a very simple one like that. Let me do it for you, though. I can\n\nget rid of this lambda easily. I don't want to be-- actually, I'm lying to you. I don't want to\ndo what you want because I think it's more confusing than you think. I'm not going to write\n\nwhat you want.\nSo we'll have to get a name. FOO of x to be of F of x and x and return as a value FOO. This\nis equivalent, but I've had to make an arbitrary name up. This is equivalent to this without\n\nany lambdas. Lambda is very convenient for naming anonymous procedures. It's the\nanonymous name of something. Now, if you really want to know a cute way of doing this,\n\nwe'll talk about it later. We're going to have to define the anonymous procedure. Any other\n\nquestions? And so we go for our break again.\n\n\n\n\nSo now we've seen how to use high-order procedures, they're called. That's procedures that\ntake procedural arguments and produce procedural values to help us clarify and abstract\n\nsome otherwise complicated processes. I suppose what I'd like to do now is have a bit of\n\nfun with that and sort of a little practice as well. So let's play with this square root thing\neven more. Let's elaborate it and understand what's going on and make use of this kind of\n\nprogramming style.\n\n\n\n\nOne thing that you might know is that there is a general method called Newton's method\n\nthe purpose of which is to find the roots-- that's the zeroes-- of functions. So, for example,\nto find a y such that f of y equals 0, we start with some guess. This is Newton's method.\n\nAnd the guess we start with we'll call y0, and then we will iterate the following expression.\n\n\n\n\ny n plus 1-- this is a difference equation-- is yn minus f of yn over the derivative with\n\nrespect to y of f evaluated at y equal yn. Very strange notation. I must say ugh. The\nderivative of f with respect to y is a function. I'm having a little bit of unha ppiness with that,\n\nbut that's all right. It turns out in the programming language world, the notation is much\nclearer.\n\n\n\n\n\nNow, what is this? People call it Newton's method. It's a method for finding the roots of the\nfunction f. And it, of course, sometimes converges, and when it does, it does so very fast.\n\nAnd sometimes, it doesn't converge, and, oh well, we have to do something else. But let's\ntalk about square root by Newton's method.\n\n\n\n\nWell, that's rather interesting. Let's do exactly the same thing we di d last time: a bit of\n\nwishful thinking. We will apply Newton's method, assuming we knew how to do it. You don't\n\nknow how to do it yet. Well, let's go. What do I have here? The square root of x. It's\nNewton's method applied to a procedure which will represent that function of y, which\n\ncomputes that function of y. Well, that procedure is that procedure of y, which is the\ndifference between x and the square of y. Indeed, if I had a value of y for which this was\nzero, then y would be the square root of x. See that? OK, I'm going to start this out\n\nsearching at 1. Again, completely arbitrary property of square roots that I can do that.\n\n\n\n\nNow, how am I going to compute Newton's method? Well, this is the method. I have it right\n\nhere. In fact, what I'm doing is looking for a fixed point of some procedure. This procedure\ninvolves some complicated expressions in terms of other complicated things. Well, I'm\n\ntrying to find the fixed point of this. I want to find the values of y, which if I put y in here, I\nget the same value out here up to some degree of accuracy. Well, I already have a fixed\n\npoint process around to do that. And so, let's just define Newton's method over here.\n\n\n\n\nA procedure which computes a function and a guess, initial guess. Now, I'm going to have\n\nto do something here. I'm going to need the derivative of the function. I'm going to need a\nprocedure which computes the derivative of the function computed by the given a procedure\n\nf. I'm trying to be very careful about what I'm saying. I don't want to mix up the word\nprocedure and function. Function is a mathematical word. It says I'm mapping from values\n\nto other values, a set of ordered pairs. But sometimes, I'll accidentally mix those up.\nProcedures compute functions.\n\n\n\n\n\nSo I'm going to define the derivative of f to be by wishful thinking again. I don't know how\nI'm going to do it. Let's worry about that later-- of F. So if F is a procedure, which happens\n\nto be this one over here for a square root, then DF will be the derivative of it, which is also\nthe derivative of the function computed by that procedure. DF will be a procedure that\n\ncomputes the derivative of the function computed by the procedure F. And then given that,\n\nI will just go looking for a fixed point.\n\n\n\n\nWhat is the fixed point I'm looking for? It's the one for that procedure of one argument x,\nwhich I compute by subtracting x. That's the old-- that's the yn here. The quotient of f of x\n\nand df of x, starting out with the original guess. That's all very simple.\n\n\n\n\nNow, I have one part left that I haven't written, and I want you to see the process by which\n\nI write these things, because this is really true. I start out with some mathematical idea,\nperhaps. By wishful thinking, I assume that by some magic I can do something that I have\n\na name for. I'm not going to worry about how I do it yet. Then I go walking down here and\nsay, well, by some magic, I'm somehow going to figure how to do that, but I'm going to\n\nwrite my program anyway. Wishful thinking, essential to good engineering, and certainly\n\nessential to a good computer science.\nSo anyway, how many of you wished that your computer ran faster? Well, the derivative\n\nisn't so bad either. Sort of like average damping. The derivative is a procedure that takes a\nprocedure that computes a function as its argument, and it produces a procedure that\n\ncomputes a function, which needs one argument x. Well, you all know this definition. It's f\nof x plus delta x minus f of x over delta x, right? For some small delta x. So that's the\n\nquotient of the difference of f of the sum of x and dx minus f point x divided by dx. I think\nthe thing was lining up correctly when I balanced the parentheses.\n\n\n\n\n\nNow, I want you to look at this. Just look. I suppose I haven't told you what dx is.\nSomewhere in the world I'm going to have to write down something like that. I'm not\n\ninterested. This is a procedure which takes a procedure and produces an approximation, a\nprocedure that computes an approximation of the derivative of the function computed by\n\nthe procedure given by the standard methods that you all know and love.\n\n\n\n\nNow, it may not be the case that doing this operation is such a good way of approximating a\n\nderivative. Numerical analysts here should jump on me and say don't do that. Computing\nderivatives produces noisy answers, which is true. However, this again is for the sake of\n\nunderstanding. Look what we've got. We started out with what is apparently a\n\nmathematically complex thing. and. In a few blackboards full, we managed to decompose\nthe problem of computing square roots by the way you were taught in your college calculus\n\nclass-- Newton's method-- so that it can be understood. It's clear.\n\n\n\n\nLet's look at the structure of what it is we've got. Let's look at this slide. This is a diagram of\n\nthe machine described by the program on the blackboard. There's a machine described\nhere. And what have I got? Over here is the Newton's method function f that we have on\n\nthe left-most blackboard. It's the thing that takes an argument called y and puts out the\ndifference between x and the square of y, where x is some sort of free variable that comes\n\nin from the outside by some magic. So the square root routine picks up an x, and builds this\nprocedure, which I have the x rolled up in it by substitution.\n\n\n\n\n\nNow, this procedure in the cloud is fed in as the f into the Newton's method which is here,\nthis box. The f is fanned out. Part of it goes into something else, and the other part of it\n\ngoes through a derivative process into something else to produce a proc edure, which\ncomputes the function which is the iteration function of Newton's method when we use the\n\nfixed point method. So this procedure, which contains it by substitution -- remember,\nNewton's method over here, Newton's method builds this procedure, andNewton's method\n\nhas in it defined f and df, so those are captured over here: f and df. Starting with this\nprocedure, I can now feed this to the fixed point process within an initial guess coming out\n\nfrom the outside from square root to produce the squareroot of x. So what we've built is a\n\nvery powerful engine, which allows us to make nice things like this.\nNow, I want to end this with basically an idea of Chris Strachey, one of the grandfathers of\ncomputer science. He's a logician who lived in the -- I suppose about 10 years ago or 15\n\nyears ago, he died. I don't remember exactly when. He's one of the inventors of something\ncalled denotational semantics. He was a great advocate of making procedures or functions\n\nfirst-class citizens in a programming languag e.\n\n\n\n\nSo here's the rights and privileges of first-class citizens in a programming language. It\n\nallows you to make any abstraction you like if you have functions as first -class citizens. The\nfirst-class citizens must be able to be named by variables. And you're seeing me doing that\n\nall the time. Here's a nice variable which names a procedure which computes something.\n\nThey have to be passed as arguments to procedures. We've certainly seen that. We have to\nbe able to return them as values from procedures. And I suppose we've seen that. We\n\nhaven't yet seen anything about data structures. We will soon, but it's also the case that in\norder to have a first-class citizen in a programming language, the object has to be allowed\n\nto be part of a data structure. We're going to see that soon.\n\n\n\n\nSo I just want to close with this and say having things like procedures as first-class data\n\nstructures, first-class data, allows one to make powerful abstractions, which encode general\nmethods like Newton's method in very clear way. Are there any questions? Yes.\n\n\n\n\n\nAUDIENCE: Could you put derivative instead of df directly in the fixed point?\n\n\n\n\nPROFESSOR: Oh, sure. Yes, I could have put deriv of f right here, no question. Any time you\nsee something defined, you can put the thing that the definition is there because you get\n\nthe same result. In fact, what that would look like, it's interesting.\n\n\n\n\nAUDIENCE: Lambda.\n\n\n\n\n\nPROFESSOR: Huh?\n\n\n\n\nAUDIENCE: You could put the lambda expression in there.\nPROFESSOR: I could also put derivative of f here. It would look interesting because of the\n\nopen paren, open paren, deriv of f, closed paren on an x. Now, that would have the bad\nproperty of computing the derivative many times, because every time I would run this\n\nprocedure, I would compute the derivative again. However, the two open parens here both\nwould be meaningful. I want you to understand syntactically that that's a sensible thing.\n\nBecause if was to rewrite this program-- and I should do it right here just so you see\nbecause that's a good question-- of F and guess to be fixed point of that procedure of one\n\nargument x, which subtracts from x the quotient of F applied to x and the deriv of F applied\n\nto x. This is guess.\n\n\n\n\nThis is a perfectly legitimate program, because what I have here-- remember the evaluation\nrule. The evaluation rule is evaluate all of the parts of the combination: the operator and\n\nthe operands. This is the operator of this combination. Evaluating this operator will, of\n\ncourse, produce the derivative of F.\n\n\n\n\nAUDIENCE: To get it one step further, you could put the lambda expression there, too.\n\n\n\n\nPROFESSOR: Oh, of course. Any time I take something which is define, I can put the thing\n\nit's defined to be in the place where the thing defined is. I can't remember which is\ndefiniens and which is definiendum. When I'm trying to figure out how to do a lecture about\n\nthis in a freshman class, I use such words and tell everybody it's fun to tell their friends.\nOK, I think that's it.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed thismaterial in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec2b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 2B: Compound Data\n\n\n\n[MUSIC PLAYING] PROFESSOR: Well, so far in this course we've been talking about\nprocedures, and then just to remind you of this framework that we introduced for talking\n\nabout languages, we talked about the primitive things that are built into the system. W e\nmentioned some means of combination by which you take the primitive things and you\n\nmake more complicated things. And then we talked about the means of abstraction, how\nyou can take those complicated things and name them so you can use them as simple\n\nbuilding blocks.\n\n\n\n\nAnd then last time you saw we went even beyond that. We saw that by using higher order\n\nprocedures, you can actually express general methods for computing things. Like the\nmethod of doing something by fixed points, or Newton's method, and so the incredible\n\nexpressive power you can get just by combining these means of abstraction.\n\n\n\n\nAnd the crucial idea in all of this is the one that we build a layered system. So for instance,\n\nif we're writing the square root procedure, somewhere the square root procedure uses a\nprocedure called good-enough, and between those there is some sort of abstraction\n\nboundary. It's almost as if we go out and in writing square root, we go and make a contract\nwith George, and tell George that his job is to write good-enough, and so long as good-\n\nenough works, we don't care what it does. We don't care exactly how it's implemented.\nThere are levels of detail here that are George's concern and not ours. So for instance,\n\nGeorge might use an absolute value procedure that's written by Harry, and we don't much\n\ncare about that or even know that, maybe, Harry exists.\n\n\n\n\nSo the crucial idea is that when we're building things, we divorce the task of building things\nfrom the task of implementing the parts. And in a large system, of course, we have\n\nabstraction barriers like this at lots, and lots, and lots of levels. And that's the idea that\n\nwe've been using so far over and over in implementing procedures.\n\n\n\n\nWell, now what we're going to do is look at the same issues for data. We're going to see\nthat the system has primitive data. In fact, we've already seen that. We've talked about\n\nnumbers as primitive data. And then we're going to see their means of combination for\n\ndata. There's glue that allows you to put primitive data together to make more complicated,\nkind of compound data. And then we're going to see a methodology for abstraction that's a\n\nvery good thing to use when you start building up data in terms of simpler data.\nAnd again, the key idea is that you're going to build the system in layers and set up\nabstraction barriers that isolate the details at the lower layers from the thing that's going on\n\nat the upper layers. The details at the lower layers, the ideas, they won't matter. They're\ngoing to be George's concern because he signed this contract with us for how the stuff that\n\nhe implements behaves, and how he implements the thing is his problem.\n\n\n\n\nAll right, well let's look at an example. And the example I'm going to talk about is a system\n\nthat does arithmetic on rational numbers. And what I have in mind is that we should have\nsomething in the computer that allows us to ask it, like, what's the sum of 1/2 and 1/4, and\n\nsomehow the system should say, yeah, that's 3/4. Or we should be able to say what's 3/4\n\ntimes 2/3, and the system should be able to say, yeah, that's 1/2. Right? And you know\nwhat I have in mind. And you also know how to do this from, I don't know, fifth grade or\n\nsixth grade.\n\n\n\n\nThere are these formulas that say if I have some fraction which is a numerator over a\n\ndenominator, and I want to add that to some other fraction which is another numerator\nover another denominator, then the answer is the numerator of the first times the\n\ndenominator of the second, plus the numerator of the second times the denominator of the\nfirst. That's the numerator of the answer, and the denominator is the product of the two\n\ndenominators.\n\n\n\n\nRight? So there's something from fifth or sixth grade fraction arithmetic. And then similarly,\n\nif I want to multiply two things, n1 over d1 multiplied by n2 over d2 is the product of the\nnumerators over the product of the denominators.\n\n\n\n\n\nSo it's no problem at all, but it's absolutely no problem to think about what computation you\nwant to make in adding and multiplying these fractions. But as soon as we go to im plement\n\nit, we run up across something. We don't have what a rational number is. So we said that\nthe system gives us individual numbers, so we can have 5 and 3, but somehow we don't\n\nhave a way of saying there's a thing that has both a 3 and a 4 in it, or both a 2 and a 3. It's\nalmost as if we'd like to imagine that somehow there are these clouds, and a cloud\n\nsomehow has both a numerator and a denominator in it, and that's what we'd like to work\nin terms of.\n\n\n\n\n\nWell, how are we going to solve that problem? We're going to solve that problem by using\nthis incredibly powerful design strategy that you've already seen us use over and over. And\n\nthat's the strategy of wishful thinking. Just like before when we didn't have a procedure, we\nsaid, well, let's imagine tha t that procedure already exists. We'll say, well, let's imagine that\n\nwe have these clouds.\n\n\n\n\nNow more precisely what I mean is let's imagine that we have three procedures, one called\n\nmake-RAT. make-RAT is going to take as arguments two numbers, so I'll call them\nnumerator and denominator, and it'll return for us a cloud -- one of these clouds. I don't\n\nreally know what a cloud is. It's whatever make-RAT returns, that's its business.\n\n\n\n\nAnd then we're going to say, suppose we've got one of these clouds, we have a procedure\n\ncalled numer, which takes in a cloud that has an n and a d in it, whatever a clo ud is, and I\ndon't know what it is, and returns for us the numerator part. And then we'll assume we\n\nhave a procedure denom, which again takes in a cloud, whatever a cloud is, and returns for\nus the denominator [? required. ?]\n\n\n\n\n\nThis is just like before, when if we're building a square root, we assume that we have good\nenough. Right? And what we'll say is, we'll go find George, and we'll say to George, well, it's\n\nyour business to make us these procedures. And how you choose to implement these\nclouds, that's your problem. We don't want to know.\n\n\n\n\n\nWell, having pushed this task off onto George, then it's pretty easy to do the other part.\nOnce we've got the clouds, it's pretty easy to write the thing that does say addition of\n\nrational numbers. You can just say define, well, let's say +RAT. Define +RAT, which will\ntake in two rational numbers, x and y. x and y are each these clouds.\n\n\n\n\n\nAnd what does it do? Well, it's going to return for us a rational number. What rational\nnumber is it? Well, we've got the formulas there. The numerator of it is the sum of the\n\nproduct of the numerator of x and the denominator of y. It's one thing in the sum. And the\nother thing in the numerator is the product of the numerator of y and the denominator of x.\n\nThe star, close the plus.\n\n\n\n\nRight, that's the first argument to make-RAT, which is the numerator of the thing I'm\n\nconstructing. And then the rest of the thing goes into make-RAT is the denominator of the\nanswer, which is the product of the denominator of x and the denominator of y. Like that.\n\nOK? So there is the analog of doing rational number addition. And it's no problem at all,\nassuming that we have these clouds.\nAnd of course, we can do multiplication in the same way. Define how to get the product of\n\ntwo rational numbers, call it *RAT. Takes in two of these clouds, x and y, it returns a\nrational number, make-RAT, whose numerator is the product of the numerators-- numerator\n\nof x times the numerator of y. And the denominator of the thing it's going to return is the\nproduct of the denominators.\n\n\n\n\n\nWell, except that I haven't told you what these clouds are, that's all there is to it. See, what\ndid I do? I assumed by wishful thinking that I had a new kind of data object. And in\n\nparticular, I assumed I had ways of creating these data obje cts. Make-RAT creates one of\nthese things. This is called a constructor. All right, I have a thing that constructs such data\n\nobjects. And then I assume I have things that, having made these things, I have ways of\ngetting the parts out. Those are called selectors.\n\n\n\n\n\nAnd so formally, what I said is I assumed I had procedures that are constructors and\nselectors for these data objects, and then I went off and used them. That's no different in\n\nkind from saying I assume I have a procedure good-enough, and I go use it to implement\nsquare root.\n\n\n\n\n\nOK, well before we go on, let's ask the question of why do we want to do this in the first\nplace? See, why do we want a procedure like +RAT that takes in two rational numbers and\n\nreturns a rational number? See, another way to think about this is, well, here's this formula.\nAnd I've also got to implement something that adds rational numbers.\n\n\n\n\n\nOne other way to think about is, well, there's this thing, and I type in four numbers, an n1,\nand a d1, and an n2, and a d2. And it sets some registers in the machine to this numerator\n\nand this denominator. So I might say, well, why don't I just add rational numbers by I type\nin four numbers, numerators and denominators, and get out two numbers, which is a\n\nnumerator and a denominator.\n\n\n\n\nWhy are we worrying about building things like this anyway? Well, the answer is, suppose\n\nyou want to think about expressing something like this, suppose I'd like to express the idea\nof taking two rational numbers, x plus y, say, and multiplying that by the sum of two other\n\nrational numbers. Well, the way I do it, having things like +RAT and *RAT, is I'd say, oh\nyeah, what that is is just the product. That's *RAT of the sum of x and y and the sum of s\n\nand t.\nSo except for syntax, I get an expression that looks like the way I want to think about it\n\nmathematically. I want to say there are two numbers. There's a thing which is the sum of\nthem, and there's a thing which is the sum of these two. That's this and this. And then I\n\nmultiply them. So I get an expression that matches this expression.\n\n\n\n\nIf I did the other thing, if I said, well, the way I want to think about this is I type into my\n\nmachine four numbers, which are the numerators and the denominators of x and y, and\nthen four more numbers, which are the numerators and denominators of s and t. And then\n\nwhat I'd be sitting with is, well, what would I do? I'd add these, and somehow I'd have to\nhave two temporary variables, which are the numerators and denominators of this sum, and\n\nI'd go off and store them someplace.\n\n\n\n\nAnd then I'd go over here, I'd type in four more numbers, I'd get two more temporary\n\nvariables, which are the numerators and denominators of s and t. And then finally, I put\nthose together by multiplying them. You see, what's starting to happen, there are all these\n\ntemporary variables, which are sort of the guts of the internals of these rational numbers\nthat start hanging out all over the system.\n\n\n\n\n\nAnd of course, if I had more and more complicated expressions, there'd be more and more\nguts hanging out that confuse my programming. And those of you who sort of programmed\n\nthings like that, where you're just adding numbers in assembly language, you sort of see\nyou have to suddenly be concerned with these temporary variables.\n\n\n\n\n\nBut more importantly than confusing my programming, they're going to confuse my mind.\nBecause the whole name of this game is that we'd like the programming language to\n\nexpress the concepts that we have in our heads, like rational numbers are things that you\ncan add and then take that result and multiply them.\n\n\n\n\n\nLet's break for questions. Yeah?\n\n\n\n\nAUDIENCE: I don't quite see the need- when we had make-RAT with the numerator and\n\ndenominator, we had to have the numerator and denominator to pass as parameters to\ncreate the cloud, and then we extracted to get back what we had to have originally.\n\n\n\n\nPROFESSOR: That's right. So the question is, I sort of have the numerator and the\n\ndenominator, why am I worrying about having the cloud given that I have to get the pieces\nout? That's sort of what I tried to say at the end, but let me try and say it again, because\n\nthat's really the crucial question.\n\n\n\n\nThe point is, I want to carry this numerator and denominator around together all the time.\n\nAnd it's almost as if I want to know, yeah, there's a numerator and denominator in there,\nbut also, I would like to say, fine, but from another point of view, that's x. And I carry x\n\naround, and I name it as x, and I hold it. And I can say things like, the sum of x and y,\nrather than just have-- see, it's not so bad when I only think about x, but if I have a system\n\nwith 10 rational numbers, suddenly I have 20 numerators and denominators, which are not\nnecessarily-- if I don't link them, then it's just 20 arbitrary numbers that are not linked in\n\nany particular way.\n\n\n\n\nIt's a lot like saying, well, I have these instructions that are the body of the procedures,\n\nwhy do I want to package them and say it's the procedure? It's exactly the same idea.\n\n\n\n\nNo? OK. Let's break, let's just stretch and get somebody-- [INAUDIBLE]\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\n\nOK, well, we've been working on this rational number arithmetic system, and then what we\ndid, the important thing about what we did, is we thought about the problem by breaking it\n\ninto two pieces. We said, assume there is this contract with George, and George has figured\nout the way to how to construct these clouds, provided us procedures make-RAT, which was\n\na constructor, and selectors, which are numerator and denominator. And then in terms of\n\nthat, we went off and implemented addition and multiplication of rational numbers.\n\n\n\n\nWell, now let's go look at George's problem. How can we go and package together a\nnumerator and a denominator and actually make one of these clouds? See, what we need is\n\na kind of glue, a glue for data objects that allows us to put things together. And Lisp\n\nprovides such a glue, and that glue is called list structure. List structure is a way of gluing\nthings together, and more precisely, Lisp provides a way of constructing things called pairs.\n\n\n\n\nThere's a primitive operator in Lisp called cons. We can take a look at it. There's a thing\n\ncalled cons. Cons is an operator which takes in two arguments called x and y, and it returns\nfor us a thing called a pair. All right, so a thing called a pair that has a first part a second\n\npart.\nSo cons takes two objects. There's a thing called a pair. The first part of the cons is x, and\nthe second part of the cons is y. And that's what it builds. And then we also assume we\n\nhave ways of getting things out. If you're given a pair, there's a thing called car, and car of\na pair, p, gives you out the first part of the pair, p. And there's a thing called cdr, and cdr of\n\nthe pair, p, gives you the second part of the pair, p. OK, so that's how we construct things.\n\n\n\n\nThere's also a conventional way of drawing pictures of these things. Just like we write down\n\nthat as the conventional way of writing Plato's idea of two, the way we could draw a\ndiagram to represent cons of two and three is like this. We draw a little box. And so here's\n\nthe box we're talking about, and this box has two arrows coming out of it. And say the first\n\npart of this pair is 2, and the second part of this pair is 3. And this notation has a name, it's\ncalled box and pointer notation.\n\n\n\n\nBy the way, let me say right now that a lot of people get confused that there's some\n\nsignificance to the geometric way I drew these pointers, the directions. Like some people\n\nthink it'd be different if I took this pointer and turned it up here, and put the 3 out here.\nThat has no significance. All right? It's merely you have a bunch of arrows, these pointers,\n\nand the boxes. The only issue is how they're connected, not the geometric arrangement of\nwhether I write the pointer across, or up, or down.\n\n\n\n\n\nNow it's completely un-obvious, probably, why that's called list structure. We're not actually\ngoing to talk about that today. We'll see that next time.\n\n\n\n\nSo those are pairs, there's cons that constructs them. And what I'm going to know about\n\ncons, and car, and cdr, is precisely that if I have any x and y, all right, if I have any things x\n\nand y, and I use cons to construct a pair, then the car of that pair is going to be x, the thing\nI put in, and the cdr of that pair is going to be y. That's the behavior of these operators,\n\ncons, car, and cdr.\n\n\n\n\nGiven them, it's pretty clear how George can go off and construct his rational numbers.\nAfter all, all he has to do-- remember George's problem was to implement make-RAT,\n\nnumerator, and denom. So all George has to do is say define make-RAT of some n and a d--\n\nso all I have to do is cons them. That's cons of n and d.\n\n\n\n\nAnd then if I want to get the numerator out, I would say define the numerator, numer, of\nsome rational number, x. If the rational number's implemented as a pair, then all Ihave to\ndo is get out the car of x. And then similarly, define the denom is going to be the cdr, the\n\nother thing I put into the pair.\n\n\n\n\nWell, now we're in business. That's a complete implementation of rational numbers. Let's\n\nuse it. Suppose I want to say, so I want to think about how to add 1/2 plus 1/4 and watch\nthe system work. Well, the way I'd use that is I'd say, well, maybe define a. I have to make\n\na 1/2. Well, that's a rational number with numerator 1 and denominator 2, so a will be\nmake-RAT of 1 and 2.\n\n\n\n\n\nAnd then I'll construct the 1/4. I'll say define d to be make-RAT of 1 and 4. And if I'd like to\nlook at the answer-- well, assuming I don't have a special thing that prints rational\n\nnumbers, or I could make one-- I could say, for instance, define the answer to be +RAT of a\nand b, and now I can say, what's the answer? What are the numerators and denominators\n\nof the answer?\n\n\n\n\nSo if I'm adding 1/2 and 1/4, I'll say, what is the numerator of the answer? And the system\n\nis going to type out, well, 6. Bad news. And if I say what's the denominator of the answer,\nthe system's going to type out 8. So instead of what I would really like, which is for it to say\n\nthat 1/2 and 1/4 is 3/4, this foolish machine is going to say, no, it's 6/8.\n\n\n\n\nWell, that's sort of bad news. Where's the bug? Why does it do that, after all? Well, it's the\n\nway that we just had +RAT. +RAT just took the-- it said you add the numerator times the\ndenominator, you add that to the numerator times the denominator, and put that over the\n\nproduct of the two denominators, and that's why you get 6/8.\n\n\n\n\nSo what was wrong with our implementation of +RAT? What's wrong with that rational\n\nnumber arithmetic stuff that we did before the break? Well, the answer is one way to look at\nit is absolutely nothing's wrong. That's perfectly good implementation. It follows the sixth\n\ngrade, fifth grade mathematic for adding fractions.\n\n\n\n\nOne thing we can say is, well, that's George's problem. Like, boy, wasn't George dumb to\n\nsay that he can make a rational number simply by sticking together the numerator and the\ndenominator? Wouldn't it be better for George, when he made a rational number, to reduce\n\nthe stuff to lowest terms? And what I mean is, wouldn't it be better for George, instead of\nusing this version of make-RAT, to use this one on the slide? Or instead of just saying cons\n\ntogether n and d, what you do is compute the greatest common divisor of n and d, and gcd\nis the procedure which, well, for all we care is a primitive, which computes the greatest\n\ncommon divisor of two numbers.\n\n\n\n\nSo the way I can construct a rational number is get the greatest common divisor of the two\n\nnumbers, and I'm going to call that g, and then instead of consing together n and d, I'll\ndivide them through. I'll cons together the quotient of n by the the gcd and the quotient of\n\nd by the gcd. And that will reduce the rational number to lowest terms. So when I do this\naddition, when +RAT calls make-RAT-- and for the definition of +RAT it had a make-RAT in\n\nthere-- just by the fact that it's constructing that, the thing will get reduced to lowest terms\nautomatically.\n\n\n\n\n\nOK, that is a complete system. For rational number arithmetic, let's look at what we've\ndone. All right, we said we want to build rational number arithmetic, and we had a thing\n\ncalled +RAT. We implemented that. And I showed you multiplying rational numbers, and\nalthough I didn't put them up there, presumably we'd like to have something that subtracts\n\nrational numbers, and I don't know, all sorts of things. Things that test equality in division,\nand maybe things that print rational numbers in some particular way.\n\n\n\n\n\nAnd we implemented those in terms of pairs. These pairs, cons, car, and cdr that are built\ninto Lisp. But the important thing is that between these and these, we set up an abstraction\n\nbarrier. We set up a layer of abstraction.\n\n\n\n\nAnd what was that layer of abstraction? That layer of abstraction was precisely the\n\nconstructor and the selectors. This layer was make-RAT, and numer, and denom. This\nmethodology, another way to say what it's doing, is that we are separating the way\n\nsomething is used, separating the use of data objects, from the representation of data\nobjects. So up here, we have the way that rational numbers are used, do arithmetic on\n\nthem. Down here, we have the way that they're represented, and they're separated by this\n\nboundary. The boundary is the constructors and selectors.\n\n\n\n\nAnd this methodology has a name. This is called data abstraction. Data abstraction is sort of\nthe programming methodology of setting up data objects by postulating constructors and\n\nselectors to isolate use from representation. Well, so why? I mean, after all, we didn't have\nto do it this way. It's perfectly possible to do rational number addition without having any\n\ncompound data objects, and here on the slide is one example.\nWe certainly could have defined +RAT, which takes in things x and y, and we'll say, well\n\nwhat are these rational numbers really? So really, they're just pairs, and the numerator's\nthe car and the denominator's the cdr. So what we'll do is we'll take the car of x times the\n\ncdr of y, multiply them. Take the car of y times the cdr of x, multiply them. Add them. Take\nthe cdr of x and the cdr of y, multiply them, and then constitute together. Well, that sort of\n\ndoes the same thing.\n\n\n\n\nBut this ignores the problem of reducing things to lowest terms, but let's not worry about\n\nthat for a minute. But so what? Why don't we do it that way? Right? After all, there are sort\nof fewer procedures to define, and it's a lot more straightforward. It saves all this self -\n\nrighteous BS about talking about data abstraction. We just sort of do it. I mean, who\nknows, maybe it's even marginally more efficient depending on whatever compiler were\n\nusing for this.\n\n\n\n\nWhat's the point of isolating the use from the representation? Well, it goes back to this\n\nnotion of naming. Remember, one of the most important principles in programming is the\nsame as one of the most important principles in sorcery, all right? That's if you have the\n\nname of the spirit, you get control over it.\n\n\n\n\nAnd if you go back and look at the slide, you see what's in there is we have this thing +RAT,\n\nbut nowhere in the system, if I have a +RAT and a -RAT and a *RAT, and things that look\nlike that, nowhere in the system do I have a thing that I can point at which is a rational\n\nnumber. I don't have, in a system like that, the idea of rational number as a conceptual\n\nentity.\n\n\n\n\nWell, what's the advantage of that? What's the advantage of isolating the idea of rational\nnumbers as a conceptual entity, and really naming it with make-RAT, numerator, and\n\ndenominator. Well, one advantage is you might want to have alternative representations.\n\nSee, before I showed you that one way George can solve this things not reduced to lowest\nterms problem, is when you build a rational number, you divide up by the greatest common\n\ndenominator.\n\n\n\n\nAnother way to do that is shown over here. I can have an alternative representation for\nrational numbers where when you make a rational number, you just cons them. However,\n\nwhen you go to select out the numerator, at that point you compute the gcd of the stuff\n\nthat's sitting in that pair, and divide out by the gcd. And similarly, when I get the\ndenominator, at that point when I go to get the denominator, I'll divide out by the gcd.\nSo the difference would be in the old representation, when ans was constructed here, say\n\nwhat's 6 and 8, in the first way, the 6 and 8 would have got reduced when they got stuck\ninto that pair, numerator would select out 3. And in the way I just showed you, well, ans\n\nwould get 6 and 8 put in, and then at the point where I said numera tor, some computation\nwould get done to put out 3 instead of 6. So those are two different ways I might do it.\n\n\n\n\n\nWhich one's better? Well, it depends, right? If I'm making a system where I am mostly\nconstructing rational numbers and hardly ever looking at them, then it's probably better not\n\nto do that gcd computation when I construct them. If I'm doing a system where I look at\nthings a lot more than I construct them, then it's probably better to do the work when I\n\nconstruct them. So there's a choice there.\n\n\n\n\nBut the real issue is that you might not be able to decide at the moment you're worrying\n\nabout these rational numbers. See, in general, as systems designers, you're forced with the\nnecessity to make decisions about how you're going to do things, and in general, the way\n\nyou'd like to retain flexibility is to never make up your mind about anything until you're\nforced to do it.\n\n\n\n\n\nThe problem is, there's a very, very narrow line between deferring decisions and outright\nprocrastination. So you'd like to make progress, but also at the same time, never be bound\n\nby the consequences of your decisions. Data abstraction's one way of doing this. What we\ndid is we used wishful thinking. See, we gave a name to the decision. We said, make-RAT,\n\nnumerator, and denominator will stand for however it's going to be done, and however it's\n\ngoing to be done is George's problem.\n\n\n\n\nBut really, what that was doing is giving a name to the decision of how we're going to do it,\nand then continuing as if we made the decision. And then eventually, when we really\n\nwanted it to work, coming back and facing what we really had to do. And in fact, we'll see a\n\ncouple times from now that you may never have to choose any particular representation,\never, ever. Anyway, that's a very powerful design technique. It's the key to the reason\n\npeople use data abstraction. And we're going to see that idea again and again. Let's stop for\nquestions.\n\n\n\n\nAUDIENCE: What does this decision making through abstraction layers do to the axiom of\n\ndo all your design before any of your code?\nPROFESSOR: Well, that's someone's axiom, and I bet that's the axiom of someone who\n\nhasn't implemented very large computer systems very much. I said that computer science\nis a lot like magic, and it's sort of good that it's like magic. There's a bad part of computer\n\nscience that's a lot like religion. And in general, I think people who really believe that you\ndesign everything before you implement it basically are people who haven't designed very\n\nmany things.\n\n\n\n\nThe real power is that you can pretend that you've made the decision and then later on\n\nfigure out which one is right, which decision you ought to have made. And when you can do\nthat, you have the best of both worlds.\n\n\n\n\n\nAUDIENCE: Can you explain the difference between let and define?\n\n\n\n\nPROFESSOR: Oh, OK. Let is a way to establish local names. Let me give you sort of the half\n\nanswer. And I'll say, later on we can talk about the whole very complicated thing. But the\nbig difference for now is that, see, when you're typing at Lisp, you're typing in this\n\nenvironment where you're making definitions. And when you say define a to be 5, if I say\ndefine a to be 5, then from then on the thing will remember that a is 5.\n\n\n\n\n\nLet is a way to set up a local context where there's a definition. So if I type something like,\nsaying let a-- no, I shouldn't say a-- if I said let z be 10, and within that context, tell me\n\nwhat the sum of z and z is. So if I typed in this expression to Lisp, and then this would put\nout 20. However, then if I said what's z, the computer would say that's an unbound\n\nvariable.\n\n\n\n\nSo let is a way of setting up a context where you can make definitions. But those definitions\n\nare local to this context. And of course, if I'd said a in here, I'd still get 20. But this a would\nnot interfere at all with this one. So if I type this, and then type this, and then say what's a?\n\na will still be 5. So there's some other subtle differencesbetween let and define, but that's\nthe most important one.\n\n\n\n\n\nAll right, well, we've looked at implementing this little system for doing arithmetic on\nrational numbers as an example of this methodology of data abstraction. And that's a way\n\nof controlling complexity in large systems. But, see, like procedure definition, and like all\nthe ways we're going to talk about for controlling complexity, the real power of these things\n\nshow up not when you sort of do these things in themselves, like it's not such a gre at thing\nthat we've done rational number arithmetic, it's that you can use these as building blocks\n\nfor making more complicated things.\n\n\n\n\nSo it's no wonderful idea that you can just put two numbers together to form a pair. If\n\nthat's all you ever wanted to do, there are tons of ways that you can do that. The real issue\nis can you do that in such a way so that the things that you build become building blocks for\n\ndoing something even more complex? So whenever someone shows you a method for\ncontrolling complexity, you should say, yeah, that's great, but what can I build with it?\n\n\n\n\n\nSo for example, let me just run through another thing that's a lot like the rational number\none. Suppose we would like to represent points in the plane. You sort of say, well, there'sa\n\npoint, and we're going to call that point p. And that point might have coordinates, like this\nmight be the point 1 comma 2. The x-coordinate might be 1, and it's y-coordinate might be\n\n2. And we'll make a little system for manipulating points in the plane.\n\n\n\n\nAnd again, we can do that-- here's a little example of that. It can represent vectors, the\n\nsame as points in the plane, and we'll say, yep, there's a constructor called make-vector,\nmake-vector's going to take two coordinates, and here we can implementthem if we like as\n\npairs, but the important thing is that there's a constructor. And then given some vector, p,\nwe can find its x-coordinate, or we can get its y-coordinate. So there's a constructor and\n\nselectors for points in the plane.\n\n\n\n\nWell, given points in the plane, we might want to use them to build something. So for\n\ninstance, we might want to talk about, we might have a point, p, and a point, q, and p\nmight be the point 1, 2, and q might be the point 2, 3. And we might want to talk about the\n\nline segment that starts at p and ends at q. And that might be the segment s. So we might\nwant to build points for vectors in terms of numbers, and segments in terms of vectors. So\n\nwe can represent line segments in exactly the same way.\n\n\n\n\nAll right, so the line segment from p to q, we'll say there's a constructor, make-segment.\n\nAnd make up names for the selectors, the starting point of the segment and the ending\npoint of the segment. And again, we can implement a segment using cons as a pair of\n\npoints, and car and cdr get out the two points that we put together to get the segment.\n\n\n\n\nWell, now having done that, we can have some operations on them. Like we could say,\n\nwhat's the midpoint of a line segment? So here's the midpoint of a line segment, that's\ngoing to be the points whose coordinates are the averages of the coordinates of the\n\nendpoints. OK, there's the midpoint.\n\n\n\n\nSo to get the midpoint of a line segment, s, we'll just say grab the starting point to the\n\nsegment, grab the ending point of the segment, and now make a vector-- make a point\nwhose coordinates are the average of the x-coordinate of the first point and the x-\n\ncoordinate of the second point, and whose y-coordinate is the average of the y-coordinates.\nSo there's an implementation of midpoint.\n\n\n\n\n\nAnd then similarly, we can build something like the length of the segment. The length of the\nsegment is a thing whose-- use Pythagoras's rule, the length of the segment is the square\n\nroot of the d x squared plus d y squared. We'll say to get the length of a line segment, we'll\nlet dx be the difference of the x-coordinate of one endpoint and the x-coordinate of the\n\nother endpoint, and we'll let dy be the difference of the y-coordinates. And then we'll take\nthe square root of the sum of the squares of dx and dy, that's what this says. All right, so\n\nthere's an implementation of length.\n\n\n\n\nAnd again, what we built is a layered system. We built a system which has, well, say up\n\nhere there's segments. And then there's an abstraction barrier. The abstraction barrier\nseparates the implementation of segments from the implementation of vectors and points,\n\nand what that abstraction barrier is are the constructors and selectors. It's make-segment,\nand segment-start, and segment-end.\n\n\n\n\n\nAnd then there are vectors. And vectors in turn are built on top of pairs and numbers. So I'll\nsay pairs and numbers. And that has its own abstraction barrier, which is make-vector, and\n\nx-coordinate, and y-coordinate. So we have, again, a layered system. You're starting to see\nthat there are layers here.\n\n\n\n\n\nI ought to mention, there is a very important thing that I kind of took for granted. And it's\nsort of so natural, but on the other hand it's a very important thing. Notice that in order to\n\nrepresent this segment s, I said this segment is a pair of points.\n\n\n\n\nAnd a point is a pair of numbers. And if I were going to draw the box and pointers structure\n\nfor that, I would say, oh, the segment is, given those particular representations that I\nshowed you, I'd say this segment s is a pair, and the first thing in the pair is a vector, and\n\nthe vector is a pair of numbers. And that's this, that's p. And the other thing i n the segment\nis q, which is itself a pair of numbers.\nSo I almost took it for granted when I said that cons allows you to put things together. But\nit's very easy to not appreciate that, because notice, some of the things I can put together\n\ncan themselves be pairs. And let me introduce a word that I'll talk about more next time,\nit's one of my favorite words, called closure. And by closure I mean that the means of\n\ncombination in your system are such that when you put things together using them, like we\n\nmake a pair, you can then put those together with the same means of combination. So I\ncan have not only a pair of numbers, but I can have a pair of pairs.\n\n\n\n\nSo for instance, making arrays in a language like Fortran is not a closed means of\n\ncombination, because I can make an array of numbers, but I can't make an array of arrays.\n\nAnd one of the things that you should ask, one of your tests of quality for a means of\ncombination that someone shows you, is gee, are the things you make closed under that\n\nmeans of combination? So pairs would not be nearly so interesting if all I could do was\nmake a pair of numbers. I couldn't build very much structure at all.\n\n\n\n\n\nOK, well, we'll come back to that. I just wanted to mention it now. You'll hear a lot about\nclosure later on.\n\n\n\n\nYou can also see the potential for losing control of complexity as you have a layered system\n\nif you don't use data abstraction. Let's go back and look at this slide for length. Length\n\nworks and is a simple thing because I can say, when I want to get th is value, I can say, oh,\nthat is the x-coordinate of the first endpoint of the segment. And each of these things, each\n\nof these selectors, x-coordinate and endpoint, stand for a decision choice whose details I\ndon't have to look at.\n\n\n\n\n\nSo I could perfectly well, again, just like rational numbers I did before, I could say, oh well,\ngee, a segment really is a pair of pairs. And the x-coordinate of the first endpoint or the\n\nsegment really is the -- well, what is it? It's the car of the car of the segment. So I could\nperfectly well go and redefine length. I could say, define the length of some segment s.\n\n\n\n\nAnd I could start off writing something like, well, we'll let dx be-- well, what's it have to be?\n\nIt's got to be the difference of the two coordinates, so that's the difference of, the first one\n\nis the car of the car of s, subtracted from the first one, the car of the other half of it, the cdr\nof s. All right, and then dy would be-- well, let's see, I'd get the y-coordinate, so it'd be the\n\ndifference of the cdr of the car of s, and the cdr of the cdr of s, sort of go on.\nYou can see that's much harder to read than the program I had before. But worse than that,\n\nsuppose you'd gone and implemented length? And then the next day, George comes to you\nand says, I'm sorry, I changed my mind. I want to write points with the x-coordinate first.\n\nSo you come back you stare at this code and say, oh gee, what was that? That was the car,\nso I have to change this to cdr, and this is cdr, and this now has to be car. And this has to\n\nbe car.\n\n\n\n\nAnd you sort of do that, and then the next day George comes back and says, sorry, the\n\nguys designing the display would like lines to be painted in the opposite direction, so I have\nto write the endpoint first in the order. And then you come back and you stare at this code,\n\nand say, gee, what was it talking about? Oh yeah, well I've got to change this one to cdr,\nand this one becomes car, this one comes car, and this becomes cdr.\n\n\n\n\n\nAnd you go up and do that, and then the next day, George comes back and says, I'm sorry,\nwhat I really meant is that the segments always have to be painted from left to right on the\n\nscreen. And then you sort of, it's clear, you just go and punch George in the mouth at that\npoint. But you see, as soon as we have a 10 layer system, you see how that complexity\n\nimmediately builds up to the point where even something like this gets out of control.\n\n\n\n\nSo again, the way we've gotten out of that is we've named that spirit. We built a system\n\nwhere there is a thing, which is the representation choice for how you're going to talk about\nvectors. And choices about that representation are localized right there. They don't have\n\ntheir guts spilling over into things like how you compute the length and how you compute\n\nthe midpoint. And that's the real power of this system. OK, we're explicit about them, so\nthat we have control over them. All right, questions?\n\n\n\n\nAUDIENCE: What happens in the case where you don't want to be treating objects in terms\n\nof pairs? For instance, in three-dimensional space, you'd have three coordinates. Or even in\n\nthe case where you have n-dimensional space, what happens?\n\n\n\n\nPROFESSOR: Right, OK. Well, this is a preview of what I'll say tomorrow. But the point is,\nonce you have two things, you have as many things as you want. All right? Because if I\n\nwant to make three things, I could start making things like a pair whose first thing is 1, and\nwhose second thing is another pair that, say, has 2 and 3 in it. And so on, a hundred things.\n\nI can nest them out of pairs.\nI made a pretty arbitrary decision about how to do it, and you can immediately see there\n\nare lots of ways to do that. What we'll start talking about next time are conventions for how\nto do things like that. But notice that what this really depends on is I can make pairs of\n\npairs. If all I could do was make pairs of numbers, I'd be stuck.\n\n\n\n\nOK. Let's break.\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\n\nAll right, well, we've just gone off and done a couple of simple examples of data abstraction.\nNow I want to do something more complicated. We're going to talk about what it means.\n\nAnd this will be harder, because it's always much harder in computer programming to talk\nabout what something means than to go off and do it.\n\n\n\n\n\nBut let's go back to almost the very beginning. Let's go back to the point where I said, we\njust assumed that there were procedures, make-RAT, and numer, and denom. Let's go back\n\nto where we had this, at the very beginning, constructors and selectors, and wh en often\ndefined the rational number arithmetic. And remember, I said at that point we were sort of\n\ndone, except for George. Well, what is it that we'd actually done at that point? What was it\n\nthat was done?\n\n\n\n\nWell, what I want to say is, what was done after we'd implemented the operations and\nterms of these, was that we had defined a rational number representation in terms of\n\nabstract data.\n\n\n\n\nWhat do I mean by abstract data? Well, the idea is that at that point, when we had our\n\n+RAT and our *RAT, that any implementation of make-RAT, and numerator, and\ndenominator that George supplied us with, could be the basis for a rational number\n\nrepresentation. Like, it wasn't our concern where you divided through to get the greatest\n\ncommon denominator, or any of that.\n\n\n\n\nSo the idea is that what we built is a rational arithmetic system that would sit on top of any\nrepresentation. What do I mean by any representation? I mean, certainly it can't be the\n\ncase that all I mean is George can reach in a bag and pull out three arbitrary procedures\nand say, well, fine, now that's the implementation. That can't be what I mean.\nWhat I've got to mean is that there's some way of saying whether three procedures are\ngoing to be suitable as a basis for rational number representation. If we think about it, what\n\nsuitable might mean is if I have to assume something like this, I have to say that if x is the\nresult of say, doing make-RAT of n and d, then the numerator of x divided by the\n\ndenominator of x is equal to n over d.\n\n\n\n\nSee, what that is is that's George's contract. What we mean by writing a contract for\n\nrational numbers, if you think about it, this is the right thing. And the two ones we showed\ndo the right thing. See, if I'm taking out greatest common divisors, it doesn't matter\n\nwhether I take them out or not, or the place where I take them, because the idea is I'm\n\ngoing to divide through.\n\n\n\n\nBut see, this is George's contract. So what we really say to George is your business is to go\noff and find us three procedures, make-RAT, and numerator, and denominator, that fulfill\n\nthis contract for any choice of n and d. And that's what we mean by we can use that as the\n\nbasis for a rational number representation. And other than that, it fulfills this contract. We\ndon't care how he does it. It's not our business. It's below the layer of abstraction.\n\n\n\n\nIn fact, if we want to say, what is a rational number really? See, what's it really, without\n\nhaving to talk about going below the layer of abstraction, what we're forced into saying is a\n\nrational number really is sort of this axiom, is three procedures, make-RAT, numerator, and\ndenominator, that satisfy this axiom. In some sense, abstractly, that's what a rational\n\nnumber is really.\n\n\n\n\nThat's sort of easy words to listen to, because what you have in your head, of course, is\n\nwell, for all this thing about saying that's what a rational number is really, you actual ly just\nsaw that we built rational numbers. See, what we really did is we built rational numbers on\n\ntop of pairs. So for all I'm saying abstractly, we can say a rational number really is just this\naxiom. You can listen to that comfortably, because you're saying, well, yeah, but really it's\n\nactually pairs, and I'm just annoying you by trying to be abstract.\n\n\n\n\nWell, let me, as an antidote for that, let me do something that I think is really going to\n\nterrify you. I mean, it's really going to bring you face to face with the sort of existential\nreality of this abstraction that we're talking about. And what I'm going to talk about is, what\n\nare pairs really? See, what did I tell you about pairs? I tricked you, right?\nI said that Lisp has this primitive called cons that builds pairs. But what did I really tell you\n\nabout? If you go back and said, let's look on this slide, all I really told you about pairs is\nthat there happens to be this property, these properties of cons, car, and cdr. And all I\n\nreally said about pairs is that there's a thing called cons, and a thing called car, and a thing\ncalled cdr.\n\n\n\n\n\nAnd it is the case that if I build cons of x, y and take car of it, I get x. And if I build cons of\nx, y and get cdr of it, I get y. And even though I lulled you into thinking that there's\n\nsomething in Lisp that does that, so you pretended you knew what it was, in fact, I didn't\ntell you any more about pairs than this tells you about rational numbers. It's just some\n\naxiom for pairs.\n\n\n\n\nWell, to drive that home, let me really scare you, and show you what we might build pairs in\n\nterms of. And what you're going to see is that we can build rational numbers, and line\nsegments, and vectors, and all of this stuff in terms of pairs, and we're going to see below\n\nhere that pairs can be built out of nothing at all. Pure abstraction.\n\n\n\n\nSo let me show you on this slide an implementation of cons, car, and cdr. And we'll look at\n\nit again in a second, but notice that their procedure definitions of cons, car, and cdr, you\ndon't see any data in there, what you see is a lambda. So cons here is going to return -- is a\n\nprocedure that returns a procedure, just like average [UNINTELLIGIBLE].\n\n\n\n\nCons of a and b returns a procedure of an argument called pick, and it says, if pick is equal\n\nto 1, I'm going to return a, and if pick is equal to 2, I'm going to return b, and that's what\ncons is going to be. Car of a thing x, car of a pair x, is going to be x applied to 1. And notice\n\nthat makes sense. You might not understand why or how I'm doing such a thing, but at\nleast it makes sense, because the thing constructed by cons is a procedure, and car applies\n\nthat to 1.\n\n\n\n\nAnd similarly, cdr applies that thing to 2. OK, now I claimed that this is a representation of\n\ncons, car, and cdr, and notice there's no data in it. All right, it's built out of air. It's just\nprocedures. There's no data objects at all in that representation. Well, what could that\n\npossibly mean? Well, if you really believe this stuff, then you have to believe that in order to\nshow that that's a representation for cons, car, and cdr, all I have to do is show that it\n\nsatisfies the axiom.\nSee, all I should have to convince you of is, for example, that gee, that car of cons of 37\n\nand 49 is 37 for arbitrary values of 37 and 49. And cdr the same way. See, if I really can\ndemonstrate to you that that weird procedure definition, in terms of [? air ?], has the\n\nproperty that it satisfies this, then you just have to grant me that that is a possible\nimplementation of cons, car, and cdr, on which I can build everything else.\n\n\n\n\n\nWell, let's look at that. And this will be practice in the substitution model. How could we\ncheck this? We sort of know how to do that. It's just the same substitution model. Let's\n\nlook. We start out, and we say, what's car of cons of 37 and 49? What do we do? Cons is\nsome procedure. Its value is cons was a procedure of a and b. The thing returned by cons is\n\nits procedure body with 37 and 49 substituted for the parameters. It'll be 37 substituted for\na and 49 substituted for b.\n\n\n\n\n\nSo this expression has the same meaning as this expression. Its car of, and the body of\ncons was this thing that started with lambda. And it says, so if pick is equal to 1, where pick\n\nis this other argument, if pick is equal to 1, it's 37, that's where a was, and if pick is equal\nto 2, it's 49. So that's the first step. I'm just going through mechanical substitution. And\n\nremember, at this point in the course, if you're confused about what things mean, go\n\nmechanically through the substitution model.\n\n\n\n\nWell, what is this reduced to? Car said, take your argument, which in this case is this, and\napply it to 1. That was the definition of car. So if I look at car, if I do that, the answer is,\n\nwell, it's that argument, this was the argument to car, applied to 1. Well, what does that\n\nmean? I take 1, and I substitute it in the body here for this value of pick, which is the name\nof the argument, what do I get? Well, I get the thing that says if 1 equals 1 it's 37, and if 1\n\nequals 2 it's 49, so the answer's 37. And similarly, if I'd taken cdr, that would apply it to 2,\nand I'd get 49.\n\n\n\n\n\nSo you see, what I've demonstrated is that that completely weird implementation of cons,\ncar, and cdr, satisfies the axioms. So it's a perfectly valid way of building, in fact, all of the\n\ndata objects we're going to see in Lisp. So they all, if you like, can be built on sort of\nexistential nothing. And as far as you know, that's how it works. You couldn't tell. If all\n\nyou're ever going to do with pairs is construct them with cons and look at them with car and\ncdr, you couldn't possibly tell how this thing works.\n\n\n\n\n\nNow, it might give you a sort of warm feeling inside if I say, well, yeah, in fact, for various\nreasons there happens to be a primitive called cons, car, and cdr, and if it's too scary, if this\n\nkind of stuff is too scary, you don't have to look inside of it. So that might make you feel\nbetter, but the point is, it really could work this way, and it wouldn't make any difference to\nthe system at all. So in some sense, we don't need data at all to build these data\n\nabstractions. We can do everything in terms of procedures.\n\n\n\n\nOK, well, why did I terrify you in this way? First, I really want to reinforce this idea of\n\nabstraction, that you really can do these things abstractly. Secondly, I want to introduce an\nidea we're going to see more and more of in this course, which is we're going to blur the\n\nline between what's data and what's a procedure.\n\n\n\n\nSee, in this funny implementation it turned out that cons of something happened to be\n\nrepresented in terms of a procedure, even though we think of it as data. While here that's\nsort of a mathematical trick, but one of the things we'll see is that a lot of the very\n\nimportant programming techniques that we're going to get to sort of depend very crucially\non blurring this traditional line between what you consider a procedure and what you\n\nconsider data. We're going to see more and more of that, especially next time.\n\n\n\n\nOK, questions?\n\n\n\n\nAUDIENCE: If you asked the system to print a, what would happen?\n\n\n\n\n\nPROFESSOR: The question is, what would happen if I asked the system to print a. Given\nthis representation, you already know the answer. The answer is compound procedure a,\n\njust like last time. It'd say compound procedure. It might say a little bit more. It might say\ncompound procedure lambda or something or other, dependingon details of how I named\n\nit. But it's a procedure.\n\n\n\n\nAnd the only reason for that is I haven't told the system anything special about how to print\n\nsuch things. Now, it's in fact true that with the actual implementation of cons that to be\nbuilt in the system, it would print something else. It would print, say, this is a pair.\n\n\n\n\n\nAUDIENCE: When you define cons, and then you pass it into values, how does it know\nwhere to look for the cons, because you can use cons over and over again? How does it\n\nknow where to look to know which a and b it's supposed to pull back out? I don't know if\nI'm expressing that quite right. Where is it stored?\nPROFESSOR: OK, the question is, I sort of have a cons with a 37 and a 49, and I might\n\nmake another cons with a 1 and a 2, and I might have one called a, and I might have one\ncalled b. And the question is, how does it know? And why don't they get confused? And\n\nthat's a very good question. See, you have to really believe that the procedures are objects.\n\n\n\n\nIt's sort of like saying -- let's try another simpler example. Suppose I ask for the square root\n\nof 3. So I asked for the square root of 5, and then I ask for the square of 20. You're\nprobably not the least bit bothered that I can take square root and apply it to 5, and then I\n\ncan take square root and apply it to 20. And there's sort of no issue, gee, doesn't it get\nconfused about whether it's working on 5 or 20? There's no issue about that because you're\n\nthinking of a procedure which goes off and does something.\n\n\n\n\nNow, in some sense you're asking me the same question. But it's really bothering you, and\n\nit's bothering you for a really good reason. Because when I write that, you're saying gee,\nthis is, I know, sort of a procedure. But it's not a procedure that's just running. It's ju st sort\n\nof a procedure sitting there. And how can it be that sometimes this procedure has 37 and\n49, and there might be another one which has 5 and 6 in there, and why don't they get\n\nconfused?\n\n\n\n\nSo there's something very, very important that's bothering you. And it's really crucial to\n\nwhat's going on. We're suddenly saying that procedures are not just the act of doing\nsomething. Procedures are conceptual entities, objects, and if I built cons of 37 and 49,\n\nthat's a particular procedure that sits there. And it's different from cons of 3 and 4. That's\n\nanother procedure that sits there.\n\n\n\n\nAUDIENCE: Both of them exist independently.\n\n\n\n\nPROFESSOR: And exists independently.\n\n\n\n\n\nAUDIENCE: And they both can be referenced by car and cdr.\n\n\n\n\nPROFESSOR: And they both would be referenced by car and cdr. Just like I could increment\nthis, and I could increment that. They're objects. And that's sort of where we're going. See,\n\nthe fact that you're asking the question shows that you're really starting to think about the\nimplications of what's going on. It's the difference between saying a procedure is just the\n\nact of doing something. And a procedure is a real object that has existence.\nAUDIENCE: So when the procedure gets built, the actual values are now substituted for a\nand b--\n\n\n\n\n\nPROFESSOR: That's right.\n\n\n\n\nAUDIENCE: And then that procedure exists as lambda, and pick is what's actually passed in.\n\n\n\n\nPROFESSOR: Yes, when cons gets called, and the result of cons is a new procedure that's\n\nconstructed, that new procedure has an argument that's called pick.\n\n\n\n\nAUDIENCE: But it no longer has an a and b. The a and b are the actual values that are\n\npassed through.\n\n\n\n\nPROFESSOR: And it has-- right, according to the substitution model, what it now has is not\n\nthose arbitrary names a and b, it somehow has that 37 and 49 in there. But you're right,\nthat's a hard thing to think about it, and it's different from the way you've been thinking\n\nabout procedures.\n\n\n\n\nAUDIENCE: And if I have again cons of 37 and 49, it's a different [UNINTELLIGIBLE]?\n\n\n\n\nPROFESSOR: And if you make another cons of 37 and 49, you're into a wonderful\n\nphilosophical problem, which is going to be what the lecture about halfway through this\n\ncourse is about. Which is, if I cons 37 and 49, and I do it agai n, is that the same thing, or is\nit a different thing? And how could you tell? And when could it possibly matter?\n\n\n\n\nAnd that's sort of like saying, is that the same thing as this? Or is this the same thing as\n\nthat? It's the same kind of question. And that's a very, very deep question. And I can't\n\nanswer in less than an hour. But we will.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec3a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 3A: Henderson Escher Example\n\n\n\n[MUSIC PLAYING] PROFESSOR: Well, last time we talked about compound data, and there\nwere two main points to that business. First of all, there was a methodology of data\n\nabstraction, and the point of that was that you could isolate the way that data objects are\nused from the way that they're represented: this idea that there's this guy, George, and you\n\ngo out make a contract with him; and it's his business to represent the data objects; and at\nthe moment you are using them, you don't think about George's problem. And then\n\nsecondly, there was this particular way that Lisp has of gluing together things to form\nobjects called pairs, and that's done with cons, car and cdr. And the way that cons, car and\n\ncdr are implemented is basically irrelevant.\n\n\n\n\nThat's sort of George's problem of how to build those things. It could be done as primitives.\n\nIt could be done using procedures in some weird way, but we're not going to worry about\nthat. And as an example, we looked at rational number arithmetic. We looked at vectors,\n\nand here's just a review of vectors. Here's an operation that takes the sum of of two\n\nvectors, so we want to add this vector, v1, and this vector, v2, and we get the sum. And the\nsum is the vector whose coordinates are the sum of the coordinates of the pieces you're\n\nadding. So I can say, to define make-vect, right, to add two vectors I make a vector, whose\nx coordinate is the sum of the two x coordinates, and whose y coordinate is the sum of the\n\ntwo y coordinates.\n\n\n\n\nAnd then similarly, we could have an operation that scales vectors, so here's a procedure\n\nscale that multiplies a vector, v, by some number, s. So here's v, v goes from there to there\nand I scale v, and I get a vector in the same direction that's longer. And again, to scale a\n\nvector, I multiply the successive coordinates. So I make a vector, whose x coordinate is the\nscale factor times the x coordinate and whose y coordinate is the scale factor times the y\n\ncoordinate. So those are two operations that are implemented using the representation of\nvectors.\n\n\n\n\n\nAnd the representation of vectors, for instance, is something that we can build in terms of\npairs. So George has gone out and implemented for us make-vector and x coordinate and y\n\ncoordinate, and this could be done, for instance, using cons, car and cdr; and notice here, I\nwrote this in a slightly different way. The procedures we've seen before, I've said something\n\nlike say, make-vector of x and y: cons of x and y. And here I just wrote make-vector cons.\nAnd that means something slightly different. Previously we'd say, define make-vector to be\n\na procedure that takes two arguments, x and y, and does cons of x and y. And here I am\nsaying define make-vector to be the thing that cons is, and that's almost the same as the\n\nother way we've been writing things. And I just want you to get used to the idea that\nprocedures can be objects, and that you can name them. OK, well there's vector\n\nrepresentation, and again, if that was all there was to it, this would all be pretty boring.\n\n\n\n\nAnd the point is, remember, that you can use cons to glue together not just numbers to\n\nform pairs, but to glue together arbitrary things. So for instance, if we'd like to represent a\nline segment, say the line segment that goes from a certain vector: say, the segment from\n\nthe vector 2,3 to the point represented by the vector 5,1. If we want to represent that line\nsegment, then we can build that as a pair of pairs. So again, we can represent line\n\nsegments.\n\n\n\n\nWe can make a constructor that makes a segment using cons, selects out the start of a\n\nsegment, selects out the end point of the segment; and then if we actually look at that, if\nwe peel away the abstraction layers, and say what's that really is a pair of pairs, we'd say\n\nwell that's a pair. Here's the segment. It's car, right, it's car pointer is a pair, and it's cdr is\n\nalso a pair, and then what the car is-- here's the car, that itself is a pair of 2 and 3. And\nsimilarly the cdr is a pair of 2 and 3. And let me remind you again, that a lot of people have\n\nsome idea that if I'd taken this arrow and somehow written it to point down, that would\nmean something else. That's irrelevant. It's only how these are connected and not whether\n\nthis arrow happens to go vertically or horizontally.\n\n\n\n\nAnd again just to remind you, there was this notion of closure. See, closure was the thing\n\nthat allowed us to start building up complexity, that didn't trap us in pairs. Particularly what\nI mean is the things that we make, having combined things using cons to get a pair, those\n\nthings themselves can be combined using cons to make more complicated things. Or as a\nmathematician might say, the set of data objects in List is closed under the operation of\n\nforming pairs. That's the thing that allows us to build complexity. And that seems obvious,\nbut remember, a lot of the things in the computer languages that people use are not closed.\n\n\n\n\n\nSo for example, forming arrays in basic and Fortran is not a closed operation, because you\ncan make an array of numbers or character strings or something, but you can't make an\n\narray of arrays. And when you look at means of combination, you should be should be\nasking yourself whether things are closed under that means of combination. Well in any\n\ncase, because we can form pairs of pairs, we can start using pairs to glue things toge ther in\nall sorts of different ways. So for instance if I'd like to glue together the four things, 1, 2, 3\n\nand 4, there are a lot of ways I can do it. I could, for example, like we did with that line\n\nsegment, I could make a pair that had a 1 and a 2 and a 3 and a 4, right?\nOr if I liked, I could do something like this. I could make a pair, whose first thing is a pair,\nwhose car is 1, and his cdr is itself a pair that has the 2 and the 3, and then I could put the\n\n4 up here. So you see, there are a lot of different ways that I can start using pairs to glue\nthings together, and so it'll be a good idea to establish some kind of conventions, right, that\n\nallow us to deal with this thing in some conventional way, so we're not constantly making\n\nan ad hoc choice. And List has a particular convention for representing a sequence of things\nas, essentially, a chain of pairs, and that's called a List.\n\n\n\n\nAnd what a List is is essentially just a convention for representing a sequence. I would\n\nrepresent the sequence 1, 2, 3 and 4 by a sequence of pairs. I'd put 1 here and then the cdr\n\nof this would point to another pair whose car was the next thing in the sequence, and the\ncdr would point to another pair whose car was the next thing in the sequence-- so there's 3-\n\n- and then another one. So for each item in the sequence, I'll get a pair. And now there are\nno more, so I put a special marker that means there's nothing more in the List. OK, so\n\nthat's a conventional way to glue things together if you want to represent a sequence, right.\nAnd what it is is a bunch of pairs, the successive cars of each pair are the items that you\n\nwant to glue together, and the cdr pointer points to the next pair.\n\n\n\n\nNow if I actually wanted to construct that, what I would type into List is this: I'd actually\n\nconstruct that as saying, well this thing is the cons of 1 onto the cons of 2 onto the cons of\n3 onto the cons of 4 onto, well, this thing nil. And what nil is is  a name for the end of List\n\nmarker. It's a special name, which means this is the end of the List. OK, so that's how I\nwould actually construct that. Of course, it's a terrible drag to constantly have to write\n\nsomething like the cons of 1 onto the cons of 2 onto the cons of 3, whenever you want to\n\nmake this thing.\n\n\n\n\nSo List has an operation that's called List, and List is just an abbreviation for this nest of\nconses. So I could say, I could construct that by saying that is the List of 1, 2, 3 and 4. And\n\nall this is is another way, a piece of syntactic sugar, a more convenient way for writing that\nchain of conses-- cons of cons of cons of cons of cons of cons onto nil. So for example, I\n\ncould build this thing and say, I'll define 1-TO-4 to be the List of 1, 2, 3 and 4. OK, well\n\nnotice some of the consequences of using this convention. First of all if I have this List, this\n1, 2, 3 and 4, the car of the whole thing is the first element in the List, right. How do I get\n\n2? Well, 2 would be the car of the cdr of this thing 1-TO-4, it would be 2, right. I take this\nthing, I take the cdr of it, which is this much, and the car of that is 2, and then similarly,\n\nthe car of the cdr of the cdr of 1-TO-4, cdr, cdr, car-- would give me 3, and so on.\n\n\n\n\nLet's take a look at that on the computer screen for a second. I could come up to List, and I\n\ncould type define 1-TO-4 to be the List of 1, 2, 3 and 4, right. And I'll tell that to List, and it\nsays, fine, that's the definition of 1-TO-4. And I could say, for instance, what's the car of the\n\ncdr of the cdr of 1-TO-4, close paren, close paren. Right, so the car of the cdr of the cdr\nwould be 3. Right, or I could say, what's 1-TO-4 itself. And you see what List typed out is 1,\n\n2, 3, 4, enclosed in parentheses, and this notation, typing the elements of the List enclosed\nin parentheses is List's conventional way for printing back this chain of pairs that represents\n\na sequence.\n\n\n\n\nSo for example, if I said, what's the cdr of 1-TO-4, that's going to be the rest of the List.\n\nThat's the thing pointed to by the first pair, which is, again, a sequence that starts off with\n2. Or for example, I go off and say, what's the cdr of the cdr of 1-TO-4; then that's 3,4. Or\n\nif I say, what's the cdr of the cdr of the cdr of the cdr of 1-TO-4, and I'm down there looking\nat the end of List pointer itself, and List prints that as just open paren, close paren. You can\n\nthink of that as a List with nothing in there. All right, see at the end what I did there was I\n\nlooked at the cdr of the cdr of the cdr of 1-TO-4, and I'm just left with the end of List\npointer itself. And that gets printed as open close.\n\n\n\n\nAll right, well that's a conventional way you can see for working down a List by taking\n\nsuccessive cdrs of things. It's called cdring down a List. And of course it's pretty much of a\n\ndrag to type all those cdrs by hand. You don't do that. You write procedures that do that.\nAnd in fact one very, very common thing to do in List is to write procedures that, sort of,\n\ntake a List of things and do something to every element in List, and return you a List of the\nresults.\n\n\n\n\n\nSo what I mean for example, is I might write a procedure called Scale-List, and Scale-List I\nmight say I want to scale by 10 the entire List 1-TO-4, and that would return for me the List\n\n10, 20, 30, 40. [UNINTELLIGIBLE PHRASE] Right, it returns List, and well you can see that\nthere's going to be some kind of recursive strategy for doing it. How would I actually write\n\nthat procedure? The idea would be, well if you'd like to build up a List where you've\nmultiplied every element by 10, what you'd say is well you imagine that you'd taken the\n\nrest of the List-- right, the thing represented by the cdr of the List, and suppose I'd already\nbuilt a List where each of these was multiplied by 10-- that would be Scale-List of the cdr of\n\nthe List. And then all I have to do is multiply the car of the List by 10, and then cons that\nonto the rest, and I'll get a List.\n\n\n\n\n\nRight and then similarly, to have scaled the cdr of the List, I'll scale the cdr of that and cons\nonto that 2 multiplied by 10. And finally when I get all the way down to the end, and I only\n\nhave this end of List pointer. All right, this thing whose name is nil -- well I just returned an\nend of List pointer. So there's a recursive strategy for doing that.Here's the actual\n\nprocedure that does that. Right, this is an example of the general strategy of cdr -ing down a\n\nList and so called cons-ing up the result, right.\nSo to Scale a List l by some scale factor s, what do I do? Well there's a test, and List ha s\nthe predicate called null. Null means is this thing the end of List pointer, or another way to\n\nthink of that is are there any elements in this List, right. But in any case if I'm looking at the\nend of List pointer, then I just return the end of List pointer. I just return nil, otherwise I\n\ncons together the result of doing what I'm going to do to the first element in the List,\n\nnamely taking the car of l and multiplying it by s, and I cons that onto recursively scaling\nthe rest of the List.\n\n\n\n\nOK, so again, the general idea is that you recursively do something to the rest of the List, to\n\nthe cdr of the List, and then you cons that onto actually doing something to the first\n\nelement of the List. When you get down to the end here, you return the end of List pointer,\nand that's a general pattern for doing something to a List. Well of course you should know\n\nby now that the very fact that there's a general pattern there means I shouldn't be writing\nthis procedure at all. What I should do is write a procedure that's the general pattern itself\n\nthat says, do something to everything in the List and define this thing in terms of that.\n\n\n\n\nRight, make some higher order procedure, and here's the higher order procedure that does\n\nthat. It's called MAP, and what MAP does is it takes a List, takes a List l, and it takes a\nprocedure p, and it returns the List of the elements gotten by applying p to each successive\n\nelement in the List. All right, so p to v1, p to v2, p of en. Right, so I think of taking this List\nand transforming it by applying p to each element. And you see all this procedure is is\n\nexactly the general strategy I said. Instead of multiply by 10, it's do the procedure. If the\nList is empty, return nil. Otherwise, apply p to the first element of the List. Right, apply p to\n\ncar of l, and cons that onto the result of applying p to everything in the cdr of the List, so\n\nthat's a general procedure called MAP. And I could define Scale-List in terms of MAP. Let me\nshow you that first.\n\n\n\n\nBut I could say Scale-List is another way to define it is just MAP along the List by the\n\nprocedure, which takes an item and multiplies it by s. Right, so this is really the way I\nshould think about scaling the List, build that actual recursion into the general strategy, not\n\nto every particular procedure I write. And of course, one of the values of doing this is that\n\nyou start to see commonality. Right, again you're capturing general patterns of usage. For\ninstance, if I said MAP, the square procedure, down this List 1-TO-4, then I'd end up with 1,\n\n4, 9 and 16. Right, or if I said MAP down this List, lambda of x plus x10, if I MAP that down\n1-TO-4, then I'd get the List where everything had 10 added to it: right, so I'd get 11, 12,\n\n13, 14. And you can see that's going to be a very, very common idea: doing something to\nevery element in the List.\nOne thing you might think about is writing MAP in an iterative style. The one I wrote\n\nhappens to evolve a recursive process, but we could just as easily have made one that\nevolves an iterative process. But see the interesting thing about it is that once you start\n\nthinking in terms of MAP -- see, once you say scale is just MAP, you stop thinking about\nwhether it's iterative or recursive, and you just say, well there's this aggregate, there's this\n\nList, and what I do is transform every item in the List, and I stop thinking about the\nparticular control structure in order.\n\n\n\n\n\nThat's a very, very important idea, and it, I guess it really comes out of APL. It's, sort of,\nthe really important idea in APL that you stop thinking about control structures, and you\n\nstart thinking about operations on aggregates, and then about halfway through this course,\nwe'll see when we talk about something called stream processing, how that view of the\n\nworld really comes into its glory. This is just us a, sort of, cute idea. But we'll see much\n\nmore applications of that later on. Well let me mention that there's something that's very\nsimilar to MAP that's also a useful idea, and that's-- see, MAP says I take a List, I apply\n\nsomething to each item, and I return a List of the successive values.\n\n\n\n\nThere's another thing I might do, which is very, very similar, which is take a List and some\n\naction you want to do and then do it to each item in the List in sequence. Don't make a List\nof the values, just do this particular action, and that's something that's very much like MAP.\n\nIt's called for-each, and for-each takes a procedure and a List, and what it's going to do is\ndo something to every item in the List. So basically what it does: it says if th e List is not\n\nempty, right, if the List is not null, then what I do is, I apply my procedure to the first item\nin the List, and then I do this thing to the rest of the List. I apply for-each to the cdr of the\n\nList.\n\n\n\n\nAll right, so I do it to the first of the List, do it to the rest of the List, and of course, when I\n\ncall it recursively, that's going to do it to the rest of the rest of the List and so on. And\nfinally, when I get done, I have to just do something to say I'm done, so we'll return the\n\nmessage \"done.\" So that's very, very similar to MAP. It's mostly different in what it returns.\nAnd so for example, if I had some procedure that printed things on the screen, if I wanted\n\nto print everything in the List, I could say for-each, print this List. Or if I had a List of\nfigures, and I wanted to draw them on the display, I could say for-each, display on the\n\nscreen this figure. Let's take questions.\n\n\n\n\nAUDIENCE: Does it create a new copy with something done to it, unless you explicitly tell it\n\nto do that? Is that correct?\nPROFESSOR: Right. Yeah, that's right. For-each does not create a List. It just sort of does\n\nsomething. So if you have a bunch of things you want to do and you're not worried about\nvalues like printing s omething, or drawing something on the screen, or ringing the bell on\n\nthe terminal, or for something, you can say for-each, you know, do this for-each of those\nthings in the List, whereas MAP actually builds you this new collection of values that you\n\nmight want to use. It's just a subtle difference between them.\n\n\n\n\nAUDIENCE: Could you write MAP using for-each, so that you did some sort of cons or\n\nsomething to build the List back up?\n\n\n\n\nPROFESSOR: Well, sort of. I mean, I probably could. I can't think of how to do it right\n\noffhand, but yeah, I could arrange something.\n\n\n\n\nAUDIENCE: The vital difference between MAP and for-each is one is recursive and the other\n\nis not in the sense you defined early yesterday, I believe.\n\n\n\n\nPROFESSOR: Yeah, about MAP and for-each and recursion. Yeah, that's a good point. For\nthe MAP procedure I wrote, that happens to be a recursive process. And the reason for that\n\nis that when you've done this thing to the rest of the List, you're waiting for that value so\n\nthat you can stick it on to the beginning of the List, whereas for-each doesn't really have\nany values to wait for. So that turns out to be an iterative process. That's not fundamental.\n\nI could have defined MAP so that it's evolved by an iterative process. I just didn't happen to.\n\n\n\n\nAUDIENCE: If you were to cons for each with a List that had embedded Lists, I imagine it\n\nwould work, right? It would give you the internal elements of each of those internal Lists?\n\n\n\n\nPROFESSOR: OK, the question is if I [UNINTELLIGIBLE] for each or MAP, for that matter,\nwith a List that had Lists in it-- although we haven't really looked at that yet-- would that\n\nwork. The answer is yes in the sense I mean work and no in the sense that you mean work,\n\nbecause all that-- see if I give you a List, where hanging off here is, you know, is something\nthat's not a number, maybe another List or you know, another cons or something, for -each\n\njust says do something to each item in this List. It goes down successively looking at the\ncdrs.\n\n\n\n\nAUDIENCE: OK.\nPROFESSOR: And as far as it's concerned, the first item in this List is whatever is hanging\noff here.\n\n\n\n\n\nAUDIENCE: Mhm.\n\n\n\n\nPROFESSOR: That might or might not be the right thing.\n\n\n\n\nAUDIENCE: So it wouldn't go down into the--\n\n\n\n\n\nPROFESSOR: Absolutely not. I could certainly write something else. There's another, what\nyou're looking for is a common pattern of usage called tree recursion, where you take a List,\n\nand you actually go all the way down to the what's called the leaves of the tree. And you\ncould write such a thing, but that's not for-each and it's not MAP. Remember, these things\n\nare really being very simple minded. OK, no more questions? All right, let's break.\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\n\nPROFESSOR: What I'd like to do now is spend the rest of this time talking about one\nexample, and this example, I think, pretty much summarizes everything that we've done up\n\nuntil now: all right, and that's List structure and issues of abstraction, and representation\nand capturing commonality with higher order procedures, and also is going to introduce\n\nsomething we haven't really talked about a lot yet-- what I said is the major third theme in\nthis course: meta-linguistic abstraction, which is the idea that one of the ways of tackling\n\ncomplexity in engineering design is to build a suitable powerful language.\n\n\n\n\nYou might recall what I said was pretty much the very most important thing that we're\n\ngoing to tell you in this course is that when you think about a language, you think about it\nin terms of what are the primitives; what are the means of combination-- right, what are\n\nthe things that allow you to build bigger things; and then what are the means of\nabstraction. How do you take those bigger things that you've built and put black boxes\n\naround them and use them as elements in making something even more complicated?\nNow the particular language I'm going to talk about is an example that was made up by a\n\nfriend of ours called Peter Henderson. Peter Henderson is at the University of Stirling in\nScotland. And what this language is about is making figures that sort of look like this. This\n\nis this is a woodcut by Escher called \"Square Limit.\" You, sort of, see it has this complicated,\nkind of, recursive, sort of, recursive kind of figure, where there's this fish pattern in the\n\nmiddle and things sort of bleed out smaller and smaller in self similar ways.\n\n\n\n\nAnyway, Peter Henderson's language was for describing figures that look like that and\n\ndesigning new ones that look like that and drawing them on a display screen. There's\nanother theme that we'll see illustrated by this example, and that's the issue of what Gerry\n\nand I have already mentioned a lot: that there's no real difference, in some sense, between\nprocedures and data. And anyway I hope by the end of this morning, if you're not a lready,\n\nyou will be completely confused about what the difference between procedures and data\n\nare, if you're not confused about that already.\n\n\n\n\nWell in any case, let's start describing Peter's language. I should start by telling you what\nthe primitives are. This language is very simple because there's only one primitive. A\n\nprimitive is not quite what you think it is. There's only one primitive called a picture, and a\n\npicture is not quite what you think it is. Here's an example. This is a picture of George. The\nidea is that a picture in this language is going to be something that draws a figure scaled to\n\nfit a rectangle that you specify.\n\n\n\n\nSo here you see in [? Saint ?] [? Lawrence's ?] outline of a rectangle, that's not really part\n\nof the picture, but the picture-- you'll give it a rectangle, and it will draw this figure scaled\nto fit the rectangle. So for example, there's George, and here, this is also George. It's the\n\nsame picture, right, just scaled to fit a different rectangle. Here's George as a fat kid.That's\nthe same George. It's all the same figure. All of these three things are the same picture in\n\nthis language. I'm just giving it different rectangles to scale itself in. OK, those are the\nprimitives. That is the primitive.\n\n\n\n\n\nNow let's start talking about the means of combination and the operations. There is, for\nexample, an operation called Rotate. And what Rotate does is, if I have a picture, say a\n\npicture that draws an \"A\" in some rectangle that I give it, the Rotate of that-- say the\nRotate by 90 degrees would, if I give it a rectangle, draw the same image, but again, scaled\n\nto fit that rectangle. So that's Rotate by 90 degrees. There's another operation called Flip\nthat can flip something, either horizontally or vertically. All right, so those are,sort of,\n\noperations, or you can think of those as means of combination of one element.\nI can put things together. There's a means of combination called Beside, and what Beside\n\ndoes: it'll take two pictures, let's say A and B-- and by picture I mean something that's\ngoing to draw an image in a specified rectangle-- and what Beside will do-- I have to say,\n\nBeside of A and B, the side of two pictures and some number, s. And s will be a number\nbetween zero and one. And Beside will draw a picture that looks like this. It will take the\n\nrectangle you give it and scale its base by s. Say s is 0.5.\n\n\n\n\nAnd then over here it will draw-- it'll put the first picture, and over here it'll put the second\n\npicture. Or for instance if I gave it a different value of s, if I said Beside with a 0.25, it\nwould do the same thing, except the A would be much skinnier. So it would draw something\n\nlike that. So there's a means of combination Beside, and similarly there's an Above, which\ndoes the same thing except it puts them vertically instead of horizontally.\n\n\n\n\n\nWell let's look at that. All right, there's George and his kid brother, which is, right,\nconstructed by taking George and putting him Beside the Above-- taking the empty picture,\n\nand there's a thing called the empty picture, which does the obvious thing-- putting the\nempty picture above a copy of George, and then putting that whole thing Beside George.\n\nHere's something called P which is, again, George Beside Flipping George, I think,\n\nhorizontally in this case, and then Rotating the whole result 180 degrees and putting them\nBeside one another with the basic rectangle divided at 0.5, right, and I can call that P. And\n\nthen I can take P, and put it above the Flipped copy of itself, and I can call that Q.\n\n\n\n\nNotice how rapidly that we've built up complexity, just in, you know, 15 seconds, you've\n\ngotten from George to that thing Q. Why is that? How are how we able to do that so fast?\nThe answer is the closure property. See, it's the fact that when I take a picture and put it\n\nBeside another picture, that's then, again, a picture that I can go and Rotate and Flip or put\nAbove something else. Right, and when I take that element P, which is the Beside or the\n\nFlip or the Rotate of something, that's, again, a picture. Right, the world of pictur es is\nclosed under those means of combination. So whenever I have something, I can turn right\n\naround and use that as an element in something else. So maybe better than List and\nsegments, that just gives you an image for how fast you can build up complexity , because\n\noperations are closed.\n\n\n\n\nOK, well before we go on with building more things, let's talk about how this language is\n\nactually implemented. The basic element that sits under the table here is a thing called a\nrectangle, and what a rectangle is going to be, it's a thing that specified by an origin that's\n\ngoing to be some vector that says where the rectangle starts. And then there's going to be\nsome other vector that I'm going to call the horizontal part of the rectangle, and another\n\npicture called the vertical part of the rectangle. And those three pieces are the elements:\nwhere the lower vertex is, how you get to the next vertex over here, and how you get to\n\nthe vertex over there. The three vectors specify a rectangle.\n\n\n\n\nNow to actually build rectangles, what I'll assume is that we have a constructor called\n\n\"make rectangle,\" or \"make-rect,\" and selectors for horiz and vert and origin that get out\nthe pieces of that rectangle. And well, you know a lot of ways you can do thi s now. You can\n\ndo it by using pairs in some way or other standard List or not. But in any case, the\nimplementation of these things, that's George's problem. It's just a data representation\n\nproblem. So let's assume we have these rectangles to work with. OK.\n\n\n\n\nNow the idea of this, remember what's got to happen. Somehow we have to worry about\n\ntaking the figure and scaling it to fit some rectangle that you give it, that's the basic thing\nyou have to arrange, that these pictures can do. How do we think about that? Well, one way\n\nto think about that is that any time I give you a rectangle, that defines, in some sense, a\ntransformation from the standard square into that rectangle. Let me say what I mean. By\n\nthe standard square, I'll mean something, which is a square whose coordinates are 0,0, and\n1,0, and 0,1 and 1,1. And there's some sort of the obvious scaling transformation, which\n\nmaps this to that and this to that, and sort of, stretches everything uniformly.\n\n\n\n\nSo we take a line segment like this and end up mapping it to a line segment like that, so\n\nsome point xy goes to some other point up there. And although it's not important, with a\nlittle vector algebra, you could write that formula. The thing that xy goes to, the point that\n\nxy goes to is gotten by taking the origin of the rectangle and then adding that as a vector\n\nto-- well, take x, the x coordinate, which is something between zero and one, multiply that\nby the horizontal vector of the rectangle; and take the y coordinate, which is also something\n\nbetween zero and one and multiply that by the vertical vector of the rectangle. That's just a\nlittle linear algebra. Anyway, that's the formula, which is the right obvious transformation\n\nthat takes things into the unit square, into the interior of that rectangle.\n\n\n\n\nOK well, let's actually look at that as a procedure. So what we want is the thing which tells\n\nus that particular transformation that a rectangle defines. So here's the procedure. I'll call it\ncoordinate-map. Coordinate-map is the thing that takes as its argument a rectangle and\n\nreturns for you a procedure on points. Right, so for each rectangle you get a way of\ntransforming a point xy into that rectangle. And how do you get it? Well I just-- writing in\n\nList what I wrote there on the blackboard-- I add to the origin of the rectangle the result of\nadding-- I take the horizontal part of the rectangle; I scale that by the x coordinate of the\n\npoint. I take the vertical vector of the rectangle. I scale that by the y coordinate of the\npoint, and then add all those three things up.\nThat's the procedure. That is the procedure that I'm going to apply to a point. And this\n\nwhole thing is generated for each rectangle. So any rectangle defines a coordinate MAP,\nwhich is a procedure on points. OK. All right, so for example , George here, my original\n\nGeorge, might have been something that I specified by segments in the unit square, and\nthen for each rectangle I give this thing, I'm going to draw those segments inside that\n\nrectangle. How actually do I do that? Well I take each segment in my original reference\nGeorge that was specified, and to each of the end points of those segments, I applied the\n\ncoordinate MAP of the particular rectangle I want to draw it in. So for example, this lower\n\nrectangle, this George as a fat kid rectangle, has its coordinate MAP.\n\n\n\n\nAnd if I want to draw this image, what I do is for each segment here, say for this segment,\nI transformed that point by the coordinate MAP, transform that point by the coordinate MAP.\n\nThat will give me this point and that point and draw the segment between them. Right,\n\nthat's the idea. Right, and if I give it a different rectangle like this one, that's a different\ncoordinate MAP, so I get a different image of those line segments. Well how do we actually\n\nget a picture to start with?\n\n\n\n\nI can build a picture to start with out of a List of line segments initially. Here's a procedure\n\nthat builds what I'll call a primitive picture, meaning one I, sort of, got that didn't come out\nof Beside or Rotate or something. It starts with a List of line segments, and now it does\n\nwhat I said. What's a picture have to be? First of all it's a procedure that's defined on\nrectangles. What does it do? It says for each-- this is going to be a List of line segments--\n\nfor each segment, for each s, which is a segment in this List of segments, well it draws a\nline. What line does it draw? It gets the start point of that segment, transforms that by the\n\ncoordinate MAP of the rectangle.\n\n\n\n\nThat's the first new point it wants to do. Then it takes the endpoint of the segment,\n\ntransforms that by the coordinate MAP of the rectangle, and then draws a line between.\nLet's assume drawline is some primitive that's built into the system that actually draws a\n\nline on the display. All right, so it transforms the endpoints by the coordinate MAP of the\nrectangle, draws a line between them, does that for each s in this List of segments. And\n\nnow remember again, a picture is a procedure that takes a rectangle as argument. So when\nyou hand it a rectangle, this is what it does: draws those lines. All right, so there's-- how\n\nwould I actually use this thing?\n\n\n\n\nLet's make it a little bit more concrete. Right, I would say for instance, define R to be make -\n\nrectangle of some stuff, and I'd have to specify some vectors here using make-vector. And\nthen I could say, define say, G to be make-picture, and then some stuff. And what I'd have\n\nto specify here is a List of line segments, right, using make segment. Make-segment might\n\nbe made out of vectors, and vectors might be made out of points. And then if I actually\nwanted to see the image of G inside a rectangle, well a picture is a procedure that takes a\n\nrectangle as argument. So if I then called G with an input of R, that would cause whatever\nimage G is worrying about to be drawn inside the rectangle R. Right, so that's how you'd\n\nuse that.\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\nPROFESSOR: Well why is it that I say this example is nice? You probably don't think it's\n\nnice. You probably think it's more weird than nice. Right, representing these pictures as\n\nprocedures, which do complicated things with rectangles. So why is it nice? The reason it's\nnice is that once you've implemented the primitives in this way, the means of combination\n\njust fall out by implementing procedures. Let me show you what I mean. Suppose wewant\nto implement Beside. So I'd like to -- suppose I've got a picture. Let's call it P1. P1 is going\n\nto be-- and now remember what a picture really is. It's a thing that if you can hand it some\nrectangle, it will cause an image to be drawn in whatever rectangle you hand it.\n\n\n\n\n\nAnd suppose P2 two is some other picture, and you hand that a rectangle. And whatever\nrectangle you hand it, it draws some picture. And now if I'd like to implement Beside of P1\n\nand P2 with a scale factor A, well what does that have to be? That's got to be picture. It's\ngot to be a thing that you hand it a rectangle, and it draws something in that rectangle. So\n\nif hand Beside this rectangle-- let's hand it a rectangle. Well what's it going to do? it's going\nto take this rectangle and split it into two at a ratio of A and one minus A. And it will say, oh\n\nsure, now I've got two rectangles. And now it goes off to P1 and says P1, well draw yourself\n\nin this rectangle, and goes off to P2, and says, P2, fine, draw yourself in this rectangle.\n\n\n\n\nThe only computation it has to do is figure out what these rectangles are. Remember a\nrectangle is specified by an origin and a horizontal vector and a vertical vector, so it's got to\n\nfigure out what these things are. So for this first rectangle, the origin turns out to be the\n\norigin of the original rectangle, and the vertical vector is the same as the vertical vector of\nthe original rectangle. The horizontal vector is the horizontal vector of the original rectangle\n\nscaled by A. And that's the first rectangle.\n\n\n\n\nThe second rectangle, the origin is the original origin plus that horizontal vector scaled by A.\nThe horizontal vector of the second rectangle is the rest of the horizontal vector of the first\n\none, which is 1 minus A times the original H, and the ve rtical vector is still v. But basically it\n\ngoes and constructs these two rectangles, and the important point is having constructed the\nrectangles, it says OK, p1, you draw yourself in there, and p2, you draw yourself in there,\n\nand that's all Beside has to do. All right, let's look at that piece of code. Beside of a picture\nand another picture with some scaling ratio is first of all, since it's a picture, a procedure\n\nthat's going to take a rectangle as argument.\n\n\n\n\nWhat's it going to do? It says, p1 draw yourself in some rectangle and p2 draw yourself in\n\nsome other rectangle. And now what are those rectangles? Well here's the computation. It\nmakes a rectangle, and this is the algebra I just did on the board: the origin, so mething;\n\nthe horizontal vector, something; and the vertical vector, something. And for p2, the\nrectangle it wants has some other origin and horizontal vector and vertical vector. But the\n\nimportant point is that all it's saying is, p1, go do your thing in one rectangle, and p2, go do\nyour thing in another rectangle. That's all the Beside has to do.\n\n\n\n\n\nOK, similarly Rotate-- see if I have this picture A, and I want to look at say rotating A by 90\ndegrees, what that should mean is, well take this rectangle, which is origin and horizontal\n\nvector and vertical vector, and now pretend that it's really the rectangle that looks like this,\nwhich has an origin and a horizontal vector up here, and a vertical vector there, and now\n\ndraw yourself with respect to that rectangle. Let me show you that as a procedure.\n\n\n\n\nAll right, so we'll Rotate 90 of the picture, because again, a procedure for rectangle, which\n\nsays, OK picture, draw yourself in some rectangle; and then this algebra is the\ntransformation on the rectangle. It's the one which makes it look like the rectangle is\n\nsideways, the origin is someplace else and the vertical vector is someplace else, and the\nhorizontal vector is someplace else, and vertical vector is someplace else. OK? OK. OK,\n\nagain notice, the crucial thing that's going on here is you're using the representation of\n\npictures as procedures to automatically get the closure property, because what happens is,\nBeside just has this thing p1. Beside doesn't care if that's a primitive picture or it's line\n\nsegments or if p1 is, itself, the result of doing Aboves or Besides or Rotates.\n\n\n\n\nAll Beside has to know about, say, p1 is that if you hand p1 a rectangle, it will cause\n\nsomething to be drawn. And above that level, Beside just doesn't-- it's none of its business\nhow p1 accomplishes that drawing. All right, so you're using the procedural representation\n\nto ensure this closure. OK. So implementing pictures as procedures makes these means of\ncombination, you know, both pretty simple and also, I think, elegant. But that's not the real\n\npunchline. The real punchline comes when you look at the means of abstraction in this\nlanguage. Because what have we done? We've implemented the means of combination\n\nthemselves as procedures.\n\n\n\n\nAnd what that means is that when we go to abstract in this language, everything that List\n\nsupplies us for manipulating procedures is automatically available to do things in this picture\nlanguage. The technical term I want to say is not only is this language implemented in List,\nobviously it is, but the language is nicely embedded in List. What I mean is by embedding\n\nthe language in this way, all the power of List is automatically available as an extension to\nwhatever you want to do.\n\n\n\n\n\nAnd what do I mean by that? Example: say, suppose I want to make a thing that takes four\npictures A, B, C and D, and makes a configuration that looks like this. Well you might call\n\nthat, you know, four pictures or something, four-pict configuration. How do I do that? Well I\ncan obviously do that. I just write a procedure that takes B above D and A above C and puts\n\nthose things beside each other. So I automatically have List's ability to do procedure\ncomposition. And I didn't have to make that specifically in the picture language. It's\n\nautomatic from the fact that the means of combination are themselves procedures.\n\n\n\n\nOr suppose I wanted to do something a little bit more complicated. I wanted to put in a\n\nparameter so that for each of these, I could independently specify a rotation by 90 degrees.\nThat's just putting a parameter in the procedure. It's automatically there. Right, it\n\nautomatically comes from the embedding. Or even more, suppose I wanted to, you know,\nuse recursion.\n\n\n\n\n\nLet's look at a recursive means of combination on pictures. I could say define -- let's see if\nyou can figure out what this one is-- suppose I say define what it means to right-push a\n\npicture, right-push a picture and some integer N and some scale factor A. I'll define this to\nsay if N equals 0, then the answer is the picture. Otherwise I'm going to put -- oops, name\n\nchange: P. Otherwise, I'm going to take P and put it beside the results of recursively right-\n\npushing P with N minus 1 and A and use a scale factor of A. OK, so if N0 , it's P. Otherwise I\nput P with a scale factor of A-- I'm sorry I didn't align this right-- recursively beside the\n\nresult of right-pushing P, N minus 1 times with a scale factor of A.\n\n\n\n\nThere's a recursive means of combination. What's that look like? Well, here's what it looks\n\nlike. There's George right-pushed against himself twice with a scale factor of 0.75. OK.\nWhere'd that come from? How did I get all this fancy recursion? And the answer is just\n\nautomatic, absolutely automatic. Since these are procedures, the embedding says, well\nsure, I can define recursive procedures. I didn't have to arrange that. And of course, we can\n\ndo more complicated things of the same sort. I could make something that does an up -\npush. Right, that sort of goes like this, by recursively putting something above.\n\n\n\n\n\nOr I could make something that, sort of, was this scheme. I might start out with a picture\nand then, sort of, recursively both push it aside and above, and that might put something\n\nthere. And then up here I put the same recursive thing, and I might end up with something\nlike this. Right, so there's a procedure that's a little bit more complicated than right- push\n\nbut not much. I just do an Above and a Beside, rather than just a Beside.\n\n\n\n\nNow if I take that and apply that with the idea of putting four pictures together, which I can\n\nsurely do; and I go and I apply that to Q, which we defined before, right, what I end up with\nthis is this thing, which is, sort of, the square limit of Q, done twice. Right, and then we can\n\ncompare that with Escher's \"Square Limit.\" And you see, it's sort of the same idea. Escher's\nis, of course, much, much prettier. If we go back and look at George, right, if we go look at\n\nGeorge here-- see, I started with a fairly arbitrary design, this picture of George and did\nthings with it.\n\n\n\n\n\nRight, whereas if we go look at the Escher picture, right, the Escher picture is not an\narbitrary design. It's this very, very clever thing, so that when you take this fish body and\n\nRotate it and shrink it down, it bleeds into the next one really nicely. And of course with\nGeorge, I didn't really do anything like that. So if we look at George, right, there's a little bit\n\nof match up, but not very nice, and it's pretty arbitrary. One very nice project, by the way,\nwould be to write a procedure that could take some basic figure like this George thing and\n\nstart moving the ends of the lines around, so you got a really nice one when you went and\n\ndid that \"Square Limit\" process. That'd be a really nice thing to think about.\n\n\n\n\nWell so, we can combine things. We can recursive procedures. We can do all kindsof things,\nand that's all automatic. Right, the important point, the difference between merely\n\nimplementing something in a language and embedding something in the language, so that\n\nyou don't lose the original power of the language, and what List is great at, see List is a\nlousy language for doing any particular problem. What it's good for is figuring out the right\n\nlanguage that you want and embedding that in List. That's the real power of this approach\nto design.\n\n\n\n\n\nOf course, we can go further. See, you saw the other thing that we can do in List is capture\ngeneral methods of doing things as higher order procedures. And you probably just from me\n\ndrawing it got the idea that right-push and the analogous thing where you push something\nup and up and up and up and this corner push thing are all generalizations of a common\n\nkind of idea. So just to illustrate and give you practice in looking at a fairly convoluted use\nof higher order procedures, let me show you the general idea of pushing some means of\n\ncombination to recursively repeat it.\n\n\n\n\nSo here's a good one to puzzle out. We'll define it what it means to push using a means of\n\ncombination. Comb is going to be something like the Beside or Above. Well what's that\ngoing to be. That's going to be a procedure, remember what Beside actually was, right. It\ntook a picture, took two pictures and a scale factor. Using that I produced something that\n\ntook a level number and a picture and a scale factor, that I called right-push. So this is\ngoing to be something that takes a picture, a level number and a scale factor, and it's going\n\nto say-- I'm going to do some repeated operation. I'm going to repeatedly apply the\nprocedure which takes a picture and applies the means of combination to the pictu re and\n\nthe original picture and the one I took in here and the scale factor, and I do the thing which\nrepeats this procedure N times, and I apply that whole thing to my original picture.\n\n\n\n\n\nRepeated here, in case you haven't seen it, is another higher orderprocedure that takes a\nprocedure and a number and returns for you another procedure that applies this procedure\n\nN times. And I think some of you have already written repeated as an exercise, but if you\nhaven't, it's a very good exercise in thinking about higher order procedures. But in any\n\ncase, the result of this repeated is what I apply to picture. And having done that, that's\n\ngoing to capture-- that is the thing, the way I got from the idea of Beside to the idea of\nright-push So having done that, I could say define right-push to be push of Beside. Or if I\n\nsay, define up-push to be push of Beside, I'd get the analogous thing or define corner-push\nto be push of some appropriate thing that did both the Beside and Above, or I could push\n\nanything. Anyway this is, if you're having trouble with lambdas, this is an excellent exercise\nin figuring out what this means.\n\n\n\n\n\nOK, well there's a lot to learn from this example. The main point I've been dwelling on is the\nnotion of nicely embedding a language inside another language. Right, so that all the power\n\nof this language like List of the surrounding language is still accessible to you and appears\nas a natural extension of the language that you built. That's one thing that this example\n\nshows very well. OK. Another thing is, if you go back and think about that, what's\nprocedures and what's data. You know, by the time we get up to here, my God, what's\n\ngoing on. I mean, this is some procedure, and it takes a picture and an argument, and\n\nwhat's a picture. Well, a picture itself, as you remember, was a procedure, and that took a\nrectangle. And a rectangle is some abstraction.\n\n\n\n\nAnd I hope now that by now you're completely lost as to the question of what in the system\n\nis procedure and what's data. You see, there isn't any difference. There really isn't. And you\nmight think of a picture sometimes as a procedure and sometimes as data, but that's just,\n\nsort of, you know, making you feel comfortable. It's really both in some sense or neither in\n\nsome sense. OK, there's a more general point about the structure of the system as creating\na language, viewing the engineering design process as one of creating language or rather\n\none of creating a sort of sequence of layers of language. You see, there's this methodology,\nor maybe I should say mythology, that's, sort of, charitably called software, quote,\n\nengineering.\nAll right, and what does it say, it's says well, you go and you figure out your task, and you\n\nfigure out exactly what you want to do. And once you figure out exactly what you want to\ndo, you find out that it breaks out into three sub-tasks, and you go and you start working\n\non-- and you work on this sub-task, and you figure out exactly what that is. And you find\nout that that breaks down into three sub-tasks, and you specify them completely, and you\n\ngo and you work on those two, and you work on this sub -one, and you specify that exactly.\nAnd then finally when you're done, you come back way up here, and you work on your\n\nsecond sub-task, and specify that out and work it out. And then you end up with-- you end\n\nup at the end with this beautiful edifice.\n\n\n\n\nRight, you end up with a marvelous tree, where you've broken your task into sub-tasks and\nbroken each of these into sub-tasks and broken those into sub-tasks, right. And each of\n\nthese nodes is exactly and precisely defined to do the wonderful, beautiful task to make it\n\nfit into the whole edifice, right. That's this mythology. See only a computer scientist could\npossibly believe that you build a complex system like that, right. Contrast that with this\n\nHenderson example. It didn't work like that.\n\n\n\n\nWhat happened was that there was a sequence of layers of language. What happened?\n\nThere was a layer of a thing that allowed us to build primitive pictures. There's primitive\npictures and that was a language. I didn't say much about it. We talked about how to\n\nconstruct George, but that was a language where you talked about vectors and line\nsegments and points and where they sat in the unit square. And then on top of that, right,\n\non top of that-- so this is the language of primitive pictures. Right, talking about line\nsegments in particular pictures in the unit square. On top of that was a whole language.\n\nThere was a language of geometric combinators, a language of geometric positions, which\ntalks about things like Above and Beside and right-push and Rotate. And those things, sort\n\nof, happened with reference to the things that are talked about in this language.\n\n\n\n\nAnd then if we like, we saw that above that there was sort of a language of schemes of\n\ncombination. For example, push, which talked about repeatedly doing something over with\na scale factor. And the things that were being discussed in that language were, sort of, the\n\nthings that happened down here. So what you have is, at each level, the objects that are\nbeing talked about are the things that were erected at the previous level. What's the\n\ndifference between this thing and this thing? The answer is that over here in the tree, each\n\nnode, and in fact, each decomposition down here, is being designed to do a specific task,\nwhereas in the other scheme, what you have is a full range of linguistic power at each level.\n\n\n\n\nSee what's happening there, at any level, it's not being set up to do a particular task. It's\n\nbeing set up to talk about a whole range of things. The consequence of that for design is\n\nthat something that's designed in that method is likely to be more robust, where by robust,\nI mean that if you go and make some change in your description, it's more likely to be\n\ncaptured by a corresponding change, in the way that the language is implemented at the\nnext level up, right, because you've made these levels full. So you're not talking about a\n\nparticular thing like Beside. You've given yourself a whole vocabulary to express things of\nthat sort, so if you go and change your specifications a little bit, it's more likely that your\n\nmethodology will able to adapt to capture that change, whereas a design like this is not\ngoing to be robust, because if I go and change something that's in here, that migh t affect\n\nthe entire way that I decomposed everything down, further down the tree.\n\n\n\n\nRight, so very big difference in outlook in decomposition, levels of language rather than,\n\nsort of, a strict hierarchy. Not only that, but when you have levels of language you've given\nyourself a different vocabularies for talking about the design at different levels. So if we go\n\nback and look at George one last time, if I wanted to change this picture George, see\n\nsuddenly I have a whole different ways of describing the change. Like for example, I may\nwant to go to the basic primitive design and move the endpoint of some vector. That's a\n\nchange that I would discuss at the lowest level. I would say the endpoint is somewhere else.\n\n\n\n\nOr I might come up and say, well the next thing I wanted to do, this little replicated\n\nelement, I might want to do by something else. I might want to put a scale factor in that\nBeside. That's a change that I would discuss at the next level of design, the level of\n\ncombinators. Or I might want to say, I might want to change the basic way that I took this\npattern and made some recursive decomposition, maybe not bleeding out toward the\n\ncorners or something else. That would be a change that I would discuss at the highest level.\nAnd because I've structured the system to be this way, I have all these vocabularies for\n\ntalking about change in different ways and a lot of flexibility to decide which one's\nappropriate.\n\n\n\n\n\nOK, well that's sort of a big point about the difference in software methodology that comes\nout from List, and it all comes, again, out of the notion that really, the design process is not\n\nso much implementing programs as implementing languages. And that's really the powerful\nof List. OK, thank you. Let's take a break.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec3b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 3B: Symbolic Differentiation; Quotation\n\n\n\n[MUSIC PLAYING] PROFESSOR: Well, Hal just told us how you build robust systems. The\nkey idea was-- I'm sure that many of you don't really assimilate that yet-- but the key idea\n\nis that in order to make a system that's robust, it has to be insensitive to sm all changes,\nthat is, a small change in the problem should lead to only a small change in the solution.\n\nThere ought   to be a continuity. The space of solutions ought to be continuous in this space\nof problems.\n\n\n\n\n\nThe way he was explaining how to do that was instead of solving a particular problem at\nevery level of decomposition of the problem at the subproblems, where you solve the class\n\nof problems, which are a neighborhood of the particular problem that you're trying to solve.\nThe way you do that is by producing a language at that level of detail in which the solutions\n\nto that class of problems is representable in that language. Therefore when you makes\nmore changes to the problem you're trying to solve, you generally have to make only small\n\nlocal changes to the solution you've constructed, because at the level of detail you're\n\nworking, there's a language where you can express the various solutions to alternate\nproblems of the same type.\n\n\n\n\nWell that's the beginning of a very important idea, the most important perhaps idea that\n\nmakes computer science more powerful than most of the other kinds of engineering\ndisciplines we know about. What we've seen so far is sort of how to use embedding of\n\nlanguages. And, of course, the power of embedding languages partly comes from\n\nprocedures like this one that I showed you yesterday.\n\n\n\n\nWhat you see here is the derivative program that we described yesterday. It's a procedure\nthat takes a procedure as an argument and returns a procedure as a value. And using such\n\nthings is very nice. You can make things like push combinators and all that sort of wonderful\n\nthing that you saw last time.\n\n\n\n\nHowever, now I'm going to really muddy the waters. See this confuses the issue of what's\nthe procedure and what is data, but not very badly. What we really want to do is confuse it\n\nvery badly. And the best way to do that is to get involved with the manipulation of the\n\nalgebraic expressions that the procedures themselves are expressed in.\nSo at this point, I want to talk about instead of things like on this slide, the derivative\n\nprocedure being a thing that manipulates a procedure-- this is a numerical method you see\nhere. And what you're seeing is a representation of the numerical approximation to the\n\nderivative. That's what's here. In fact what I'd like to talk about is instead things that look\nlike this. And what we have here are rules from a calculus book.\n\n\n\n\n\nThese are rules for finding the derivatives of the expressions that one might write in some\nalgebraic language. It says things like a derivative of a constant is 0. The derivative of the\n\nvaluable with respect to which you are taking the derivative is 1. The derivative of a\nconstant times the function is the constant times the derivative of the function, and things\n\nlike that. These are exact expressions. These are not numerical approximations. Can we\nmake programs? And, in fact, it's very easy to make programs that manipulate these\n\nexpressions.\n\n\n\n\nWell let's see. Let's look at these rules in some detail. You all have seen these rules in your\n\nelementary calculus class at one time or another. And you know from calculus that it's easy\nto produce derivatives of arbitrary expressions. You also know from your elementary\n\ncalculus that it's hard to produce integrals. Yet integrals and derivatives are opposites of\n\neach other. They're inverse operations. And they have the same rules. What is special about\nthese rules that makes it possible for one to produce derivatives easily and integrals why it's\n\nso hard? Let's think about that very simply.\n\n\n\n\nLook at these rules. Every one of these rules, when used in the direction for taking\n\nderivatives, which is in the direction of this arrow, the left side is matched against your\nexpression, and the right side is the thing which is the derivative of that expression. The\n\narrow is going that way. In each of these rules, the expressions on the right -hand side of\nthe rule that are contained within derivatives are subexpressions, are proper\n\nsubexpressions, of the expression on the left-hand side.\n\n\n\n\nSo here we see the derivative of the sum, with is the expression on the left-hand side is the\n\nsum of the derivatives of the pieces. So the rule of moving to the right are reduction rules.\nThe problem becomes easier. I turn a big complicated problem it's lots of smaller problems\n\nand then combine the results, a perfect place for recursion to work.\n\n\n\n\nIf I'm going in the other direction like this, if I'm trying to produce integrals, well there are\n\nseveral problems you see here. First of all, if I try to integrate an expression like asum,\nmore than one rule matches. Here's one that matches. Here's one that matches. I don't\n\nknow which one to take. And they may be different. I may get to explore different things.\nAlso, the expressions become larger in that direction. And when the expressions become\nlarger, then there's no guarantee that any particular path I choose will terminate, because\n\nwe will only terminate by accidental cancellation. So that's why integrals are complicated\nsearches and hard to do.\n\n\n\n\n\nRight now I don't want to do anything as hard as that. Let's work on derivatives for a while.\nWell, these roles are ones you know for the most part hopefully. So let's see if we can write\n\na program which is these rules. And that should be very easy. Just write the program. See,\nbecause while I showed you is that it's a reduction rule, it's something appropriate for a\n\nrecursion. And, of course, what we have for each of these rules is we have a case in some\ncase analysis.\n\n\n\n\n\nSo I'm just going to write this program down. Now, of course, I'm going to be saying\nsomething you have to believe. Right? What you have to believe is I can represent these\n\nalgebraic expressions, that I can grab their parts, that I can put them together. We've\ninvented list structures so that you can do that. But you don't want to worry about that\n\nnow. Right now I'm going to write the program that encapsulates these rules independent of\nthe representation of the algebraic expressions.\n\n\n\n\n\nYou have a derivative of an expression with respect to a variable. This is a different thing\nthan the derivative of the function. That's what we saw last time, that numerical\n\napproximation. It's something you can't open up a function. It's just the answers. The\nderivative of an expression is the way it's written. And therefore it's a syntactic\n\nphenomenon. And so a lot of what we're going to be doing today is worrying about syntax,\n\nsyntax of expressions and things like that.\n\n\n\n\nWell, there's a case analysis. Anytime we do anything complicated thereby a recursion, we\npresumably need a case analysis. It's the essential way to begin. And that's usually a\n\nconditional of some large kind. Well, what are their possibilities? the first rule that you saw\n\nis this something a constant? And what I'm asking is, is the expression a constant with\nrespect to the variable given? If so, the result is 0, because the derivative represents the\n\nrate of change of something.\n\n\n\n\nIf, however, the expression that I'm taking the derivative of is the variable I'm varying,\nthen this is the same variable, the expression var, then the rate of change of the expression\n\nwith respect to the variable is 1. It's the same 1.\nWell now there are a couple of other possibilities. It could, for example, be a sum. Well, I\n\ndon't know how I'm going to express sums yet. Actually I do. But I haven't told you yet. But\nis it a sum? I'm imagining that there's some way of telling. I'm doing a dispatch on the type\n\nof the expression here, absolutely essential in building languages. Languages are made out\nof different expressions. And soon we're going to see that in our more powerful methods of\n\nbuilding languages on languages.\n\n\n\n\nIs an expression a sum? If it's a sum, well, we know the rule for derivative of the sum is the\n\nsum of the derivatives of the parts. One of them is calledthe addend and the other is the\naugend. But I don't have enough space on the blackboard to such long names. So I'll call\n\nthem A1 and A2.\n\n\n\n\nI want to make a sum. Do you remember which is the sum for end or the menu end? Or\n\nwas it the dividend and the divisor or something like that? Make sum of the derivative of the\nA1, I'll call it. It's the addend of the expression with respect to the variable, and the\n\nderivative of the A2 of the expression, because the two arguments, the addition with\nrespect to the variable.\n\n\n\n\n\nAnd another rule that we know is product rule, which is, if the expression is a product. By\nthe way, it's a good idea when you're defining things, when you're defining predicates, to\n\ngive them a name that ends in a question mark. This question mark doesn't mean anything.\nIt's for us as an agreement. It's a conventional interface between humans so you can read\n\nmy programs more easily. So I want you to, when you write programs, if you define a\n\npredicate procedure, that's something that rings true of false, it should have a name which\nends in question mark. The list doesn't care. I care.\n\n\n\n\nI want to make a sum. Because the derivative of a product is the sum of the first times the\n\nderivative of the second plus the second times the derivative of the first.Make a sum of two\n\nthings, a product of, well, I'm going to say the M1 of the expression, and the derivative of\nthe M2 of the expression with respect to the variable, and the product of the derivative of\n\nM1, the multiplier of the expression, with respect to the variable. It's the product of that\nand the multiplicand, M2, of the expression. Make that product. Make the sum. Close that\n\ncase.\n\n\n\n\nAnd, of course, I could add as many cases as I like here for a complete set of rules you\n\nmight find in a calculus book. So this is what it takes to encapsulate those rules. And you\nsee, you have to realize there's a lot of wishful thinking here. I haven't told you anything\n\nabout how I'm going to make these representations. Now, once I've decided that this is my\nset of rules, I think it's time to play with the representation. Let's attack that/\nWell, first of all, I'm going to play a pun. It's an important pun. It's a key to a sort of\npowerful idea. If I want to represent sums, and products, and differences, and quotients,\n\nand things like that, why not use the same language as I'm writing my program in? I write\nmy program in algebraic expressions that look like the sum of the product on a and the\n\nproduct of x and x, and things like that. And the product of b and x and c, whatever, make\n\nthat a sum of the product. Right now I don't want to have procedures with unknown\nnumbers of arguments, a product of b and x and c.\n\n\n\n\nThis is list structure. And the reason why this is nice, is because any one of these objects\n\nhas a property. I know where the car is. The car is the operator. And the operands are the\n\nsuccessive cdrs the successive cars of the cdrs of the list that this is. It makes it very\nconvenient. I have to parse it. It's been done for me. I'm using the embedding and Lisp to\n\nadvantage.\n\n\n\n\nSo, for example, let's start using list structure to write down the representation that I'm\n\nimplicitly assuming here. Well I have to define various things that are implied in this\nrepresentation. Like I have to find out how to do a constant, how you do same variable.\n\nLet's do those first. That's pretty easy enough. Now I'm going to be introducing lots of\nprimitives here, because these are the primitives that come with list structure.\n\n\n\n\n\nOK, you define a constant. And what I mean by a constant, an expression that's constant\nwith respect to a veritable, is that the expression is something simple. I can't take it into\n\npieces, and yet it isn't that variable. I can't break it up, and yet it isn't that variable. That\ndoes not mean that there may be other expressions that are more complicated that are\n\nconstants. It's just that I'm going to look at the primitive constants in this way.\n\n\n\n\nSo what this is, is it says that's it's the and. I can combine predicate expressions which\n\nreturn true or false with and. Something atomic, The expression is atomic, meaning it\ncannot be broken into parts. It doesn't have a car and a cdr. It's not a list. It adds a special\n\ntest built into the system. And it's not identically equal to that variable. I'm representing my\nvariable by things that are symbols which cannot be broken into pieces, things like x, and y,\n\nthings like this. Whereas, of course, something like this can be broken up into pieces.\n\n\n\n\nAnd the same variable of an expression with respect to a variable is, in fact, an atomic\n\nexpression. I want to have an atomic expression, which is identical. I don't want to look\ninside this stuff anymore. These are primitive maybe. But it doesn't matter. I'm using things\n\nthat are given to me with a language. I'm not terribly interest in them\nNow how do we deal with sums? Ah, something very interesting will happen. A sum is\nsomething which is not atomic and begins with the plus symbol. That's what it means. So\n\nhere, I will define. An question is a sum if and it's not atomic and it's head, it's beginning,\nits car of the expression is the symbol plus.\n\n\n\n\n\nNow you're about to see something you haven't seen before, this quotation. Why do I have\nthat quotation there? Say your name,\n\n\n\n\n\nAUDIENCE: Susanna.\n\n\n\n\nPROFESSOR: Louder.\n\n\n\n\nAUDIENCE: Susanna\n\n\n\n\n\nPROFESSOR: Say your name.\n\n\n\n\nAUDIENCE: Your name.\n\n\n\n\nPROFESSOR: Louder.\n\n\n\n\n\nAUDIENCE: Your name.\n\n\n\n\nPROFESSOR: OK. What I'm showing you here is that the words of English are ambiguous. I\n\nwas saying, say your name. I was also possibly saying say, your name. But that cannot be\ndistinguished in speech. However, we do have a notation in writing, which is quotation for\n\ndistinguishing these two possible meanings.\n\n\n\n\nIn particular, over here, in Lisp we have a notation for distinguish ing these meetings. If I\n\nwere to just write a plus here, a plus symbol, I would be asking, is the first element of the\nexpression, is the operator position of the expression, the addition operator? I don't know. I\nwould have to have written the addition operator there, which I can't write. However, this\n\nway I'm asking, is this the symbolic object plus, which normally stands for the addition\noperator? That's what I want. That's the question I want to ask. Now before I go any\n\nfurther, I want to point out the quotation is a very complex concept, and adding it to a\nlanguage causes a great deal of troubles.\n\n\n\n\n\nConsider the next slide. Here's a deduction which we should all agree with. We have, Alyssa\nis smart and Alyssa is George's mother. This is an equality, is. From those two, we can\n\ndeduce that George's mother is smart. Because we can always substitute equals for equals\nin expressions. Or can we?\n\n\n\n\n\nHere's a case where we have \"Chicago\" has seven letters. The quotation means that I'm\ndiscussing the word Chicago, not what the word represents. Here I have that Chicago is the\n\nbiggest city in Illinois. As a consequence of this, I would like to deduce that the biggest city\nin Illinois has seven letters. But that's manifestly false. Wow, it works.\n\n\n\n\n\nOK, so once we have things like that, our language gets much more complicated. Because\nit's no longer true that things we tend to like to do with languages, like substituting equals\n\nfor equals and getting right answers, are going to work without being very careful. We c an't\nsubstitute into what's called referentially opaque contexts, of which a quotation is the\n\nprototypical type of referentially opaque context. If you know what that means, you can\nconsult a philosopher. Presumably there is one in the room.\n\n\n\n\n\nIn any case, let's continue now, now that we at least have an operational understanding of\na 2000-year-old issue that has to do with name, and mention, and all sorts of things like\n\nthat. I have to define what I mean, how to make a sum of two things, an a1 and a2. And\nI'm going to do this very simply. It's a list of the symbol plus, and a1, and a2. And I can\n\ndetermine the first element. Define a1 to be cadr. I've just introduced another primitive.\n\nThis is the car of the cdr of something.\n\n\n\n\nYou might want to know why car and cdr are names of these primitives, and why they've\nsurvived, even though they're much better ideas like left and right. We could have called\n\nthem things like that. Well, first of all, the names come from the fact that in the great past,\nwhen Lisp was invented, I suppose in '58 or something, it was on a 704 or something like\n\nthat, which had a machine. It was a machine that had an address register and a decrement\n\nregister. And these were the contents of the address register and the decrement register.\nSo it's an historical accident.\nNow why have these names survived? It's because Lisp programmers like to talk to each\n\nother over the phone. And if you want to have a long sequence of cars and cdrs you might\nsay, cdaddedr, which can be understood. But left of right or right of left is not so clear if you\n\nget good at it. So that's why we have these words. All of them up to four deep are defined\ntypically in a Lisp system. A2 to be-- and, of course, you can see that if I looked at one of\n\nthese expressions like the sum of 3 and 5, what that is is a list containing the symbol plus,\nand a number 3, and a number 5. Then the car is the symbol plus. The car of the cdr. Well I\n\ntake the cdr and then I take the car. And that's how I get to the 3. That's the first\n\nargument. And the car of the cdr of the cdr gets me to this one, the 5.\n\n\n\n\nAnd similarly, of course, I can define what's going on with products. Let's do that very\nquickly. Is the expression a product? Yes if and if it's true, that's it's not atomic and it's EQ\n\nquote, the asterisk symbol, which is the operator for multiplication.\n\n\n\n\nMake product of an M1 and an M2 to be list, quote, the asterisk operation and M1 and M2.\n\nand I define M1 to be cadr and M2 to be caddr. You get to be a good Lisp programmer\nbecause you start talking that way. I cdr down lists and console them up and so on.\n\n\n\n\n\nNow, now that we have essentially a complete program for finding derivatives, you can add\nmore rules if you like. What kind of behavior do we get out of it? I'll have to clear that x.\n\nWell, supposing I define foo here to be the sum of the product of ax square and bx plus c.\nThat's the same thing we see here as the algebraic expression written in the more\n\nconventional notation over there.\n\n\n\n\nWell, the derivative of foo with respect to x, which we can see over here, is this horrible,\n\nhorrendous mess. I would like it to be 2ax plus b. But it's not. It's equivalent to it. What is\nit? I have here, what do I have? I have the derivative of the product of x and x. Over here\n\nis, of course, the sum of x times 1 and 1 times x.\n\n\n\n\nNow, well, it's the first times the derivative of the second plus the second times the\n\nderivative of the first. It's right. That's 2x of course. a times 2x is 2ax plus 0X square\ndoesn't count plus B over here plus a bunch of 0's. Well the answer is right. But I give\n\npeople take off points on an exam for that, sadly enough. Let's worry about that in the next\nsegment. Are there any questions? Yes?\nAUDIENCE: If you had left the quote when you put the plus, then would that be referring to\n\nthe procedure plus and could you do a comparison between that procedure and some other\nprocedure if you wanted to?\n\n\n\n\n\nPROFESSOR: Yes. Good question. If I had left this quotation off at this point, if I had left\nthat quotation off at that point, then I would be referring here to the procedure which is the\n\nthing that plus is defined to be.\n\n\n\n\nAnd indeed, I could compare some procedures with each other for identity. Now what that\n\nmeans is not clear right now. I don't like to think about it. Because I don't know exactly\nwhat it would need to compare procedures. There are reasons why that may make no sense\n\nat all. However, the symbols, we understand. And so that's why I put that quote in. I want\nto talk about the symbol that's apparent on the page. Any other questions? OK. Thank you.\n\nLet's take a break.\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\nPROFESSOR: Well, let's see. We've just developed a fairly plausible program for computing\n\nthe derivatives of algebraic expressions. It's an incomplete program, if you would like to add\n\nmore rules. And perhaps you might extend it to deal with uses of addition with any number\nof arguments and multiplication with any of the number of arguments. And that's all rather\n\neasy.\n\n\n\n\nHowever, there was a little fly in that ointment. We go back to this slide. We see that the\n\nexpressions that we get are rather bad. This is a rather bad expression. How do we get such\nan expression? Why do we have that expression? Let's look at this expression in some\n\ndetail. Let's find out where all the pieces come from. As we see here, we have a sum-- just\nwhat I showed you at the end of the last time-- of X times 1 plus 1 time X. That is a\n\nderivative of this product. The produce of a times that, where a does not depend up on x,\nand therefore is constant with respect to x, is this sum, which goes from here all the way\n\nthrough here and through here. Because it is the first thing times the derivative of the\nsecond plus the derivative of the first times the second as the program we wrote on the\n\nblackboard indicated we should do.\n\n\n\n\nAnd, of course, the product of bx over here manifests itself as B times 1 plus 0 times X\n\nbecause we see that B does not depend upon X. And so the derivative of B is this 0, and the\nderivative of X with respect itself is the 1. And, of course, the derivative of the sums over\n\nhere turn into these two sums of the derivatives of the parts.\n\n\n\n\nSo what we're seeing here is exactly the thing I was trying to tell you about with Fibonacci\n\nnumbers a while ago, that the form of the process is expanded from the local rules that you\nsee in the procedure, that the procedure represents a set of local rules for the expansion of\n\nthis process. And here, the process left behind some stuff, which is the answer. And it was\nconstructed by the walk it takes of the tree structure, which is the expression. So every part\n\nin the answer we see here derives from some part of the problem.\n\n\n\n\nNow, we can look at, for example, the derivative of foo, which is ax square plus bx plus c,\n\nwith respect to other things, like here, for example, we can see that the derivative of foo\nwith respect to a. And it's very similar. It's, in fact, the identical algebraic expression,\n\nexcept for the fact that theses 0's and 1's are in different places. Because the only degree of\nfreedom we have in this tree walk is what's constant with respect to the variable we're\n\ntaking the derivative with respect to and was the same variable.\n\n\n\n\nIn other words, if we go back to this blackboard and we look, we have no choice what to do\n\nwhen we take the derivative of the sum or a product. The only interesting place here is, is\nthe expression the variable, or is the expression a constant with respect to that variable for\n\nvery, very small expressions? In which case we get various1's and 0's, which if we go back\nto this slide, we can see that the 0's that appear here, for example, this 1 over here in\n\nderivative of foo with respect to A, which gets us an X square, because that 1 gets the\n\nmultiply of X and X into the answer, that 1 is 0. Over here, we're not taking the derivative\nof foo with respect to c. But the shapes of these expressions are the same. See all those\n\nshapes. They're the same.\n\n\n\n\nWell is there anything wrong with our rules? No. They're the right rules. We've been through\n\nthis one before. One of the things you're going to begin to discover is that there aren't too\nmany good ideas. When we were looking at rational numbers yesterday, the problem was\n\nthat we got 6/8 rather then 3/4. The answer was unsimplified. The problem, of course, is\nvery similar. There are things I'd like to be identical by simplification that don't become\n\nidentical. And yet the rules for doing addition a multiplication of rational numbers were\ncorrect.\n\n\n\n\n\nSo the way we might solve this problem is do the thing we did last time, which always\nworks. If something worked last time it ought to work again. It's changed representation.\n\nPerhaps in the representation we could put in a simplification step that produces a simplified\nrepresentation. This may not always work, of course. I'm not trying to say that it always\n\nworks. But it's one of the pieces of artillery we have in our war against complexity.\n\n\n\n\nYou see, because we solved our problem very carefully. What we've done, is we've divided\n\nthe world in several parts. There are derivatives rules and general rules for algebra of some\nsort at this level of detail. and i have an abstraction barrier. And i have the representation\n\nof the algebraic expressions, list structure.\n\n\n\n\nAnd in this barrier, I have the interface procedures. I have constant, and things like same   -\n\nvar. I have things like sum, make-sum. I have A1, A2. I have products and things like that,\nall the other things I might need for various kinds of algebraic expressions.\n\n\n\n\nMaking this barrier allows me to arbitrarily change the representation without changing the\n\nrules that are written in terms of that representation. So if I can make the problem go\n\naway by changing representation, the composition of the problem into these two parts has\nhelped me a great deal.\n\n\n\n\nSo let's take a very simple case of this. What was one of the problems? Let's go back to this\n\ntransparency again. And we see here, oh yes, there's horrible things like here is the sum of\n\nan expression and 0. Well that's no reason to think of it as anything other than the\nexpression itself. Why should the summation operation have made up this edition? It can be\n\nsmarter than that. Or here, for example, is a multiplication of something by 1. It's another\nthing like that. Or here is a product of something with 0, which is certainly 0. So we won't\n\nhave to make this construction.\n\n\n\n\nSo why don't we just do that? We need to change the way the representation works, almost\n\nhere. Make-sum to be. Well, now it's not something so simple. I'm not going to make a li st\ncontaining the symbol plus and things unless I need to.\n\n\n\n\n\nWell, what are the possibilities? I have some sort of cases here. If I have numbers, if\nanyone is a number-- and here's another primitive I've just introduced, it's possible to tell\n\nwhether something's number-- and if number A2, meaning they're not symbolic\nexpressions, then why not do the addition now? The result is just a plus of A1 and A2.\n\n\n\n\nI'm not asking if these represent numbers. Of course all of these symbols represent\n\nnumbers. I'm talking about whether the one I've got is the number 3 right now. An d, for\nexample, supposing A1 is a number, and it's equal to 0, well then the answer is just A2.\n\nThere is no reason to make anything up. And if A2 is a number, and equal A20, then the\nresult is A1.\n\n\n\n\n\nAnd only if I can't figure out something better to do with this situation, well, I can start a\nlist. Otherwise I want the representation to be the list containing the quoted symbol plus,\n\nand A1, and A2.\n\n\n\n\nAnd, of course, a very similar thing can be done for products. And I think I'll avoid boring\n\nyou with them. I was going to write it on the blackboard. I don't think it's necessary. You\nknow what to do. It's very simple.\n\n\n\n\nBut now, let's just see the kind of results we get out of changing our program in this way.\n\nWell, here's the derivatives after having just changed the constructors for expressions. The\n\nsame foo, aX square plus bX plus c, and what I get is nothing more than the derivative of\nthat is 2aX plus B.\n\n\n\n\nWell, it's not completely simplified. I would like to collect common terms and sums. Well,\n\nthat's more work. And, of course, programs to do this sort of thing are huge and\n\ncomplicated. Algebraic simplification, it's a very complicated mess. There's a very famous\nprogram you may have heard of called Maxima developed at MIT in the past, which is 5,000\n\npages of Lisp code, mostly the algebraic simplification operations.\n\n\n\n\nThere we see the derivative of foo. In fact, X is at something I wouldn't take off more than\n\n1 point for on an elementary calculus class. And the derivative of foo with respect to a, well\nit's gone down to X times X, which isn't so bad. And the derivative of foo with respect to b is\n\njust X itself. And the derivative of foo with respect to c comes out 1. So I'm pretty pleased\nwith this.\n\n\n\n\n\nWhat you've seen is, of course, a little bit contrived, carefully organized example to show\nyou how we can manipulate algebraic expressions, how we do that abstractly in terms of\n\nabstract syntax rather than concrete syntax and how we can use the abstraction to control\nwhat goes on in building these expressions.\n\n\n\n\nBut the real story isn't just such a simple thing as that. The real story is, in fact, that I'm\n\nmanipulating these expressions. And the expressions are the same expressions-- going back\nto the slide-- as the ones that are Lisp expressions. There's a pun here. I've chosen my\n\nrepresentation to be the same as the representation in my language of similar things. By\ndoing so, I've invoked a necessity. I created the necessity to have things like quotation\n\nbecause of the fact that my language is capable of writing expressions that talk about\nexpressions of the language. I need to have something that says, this is an expression I'm\n\ntalking about rather than this expression is talking about something, and I want to talk\nabout that.\n\n\n\n\n\nSo quotation stops and says, I'm talking about this expression itself. Now, given that power,\nif I can manipulate expressions of the language, I can begin to build even much more\n\npowerful layers upon layers of languages. Because I can write languages that not only are\nembedded in Lisp or whatever language you start with, but languages that are completely\n\ndifferent, that are just, if we say, interpreted in Lisp or something like that.\n\n\n\n\nWe'll get to understand those words more in the future. But right now I just want to leave\n\nyou with the fact that we've hit a line which gives us tremendous power. And this point\nwe've bought a sledgehammer. We have to be careful to what flies when we apply it. Thank\n\nyou.\n\n\n\n\n[MUSIC PLAYING]\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed thismaterial in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec4a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 4A: Pattern Matching and Rule-based Substitution\n\n\n\nPROFESSOR: Well, yesterday we learned a bit about symbolic manipulation, and we wrote a\nrather stylized program to implement a pile of calculus rule from the calculus book. Here on\n\nthe transparencies, we see a bunch of calculus rules from such a book. And, of course, what\nwe did is sort of translate these rules into the language of the computer. But, of course,\n\nthat's a sort of funny strategy. Why should we have to translate these rules into the\nlanguage of the computer? And what do I really mean by that?\n\n\n\n\n\n\nThese are--the program we wrote yesterday was very stylized. It was a conditional, a\n\ndispatch on the type of the expression as observed by the rules. What we see here are rules\nthat say if the object being the derivative is being taken of, if that expres sion is a constant,\n\nthen do one thing. If it's a variable, do another thing. If it's a product of a constant times a\nvariable, do something and so on. There's sort of a dispatch there on a type.\n\n\n\n\n\nWell, since it has such a stylized behavior and structure, is there some other way of writing\nthis program that's more clear? Well, what's a rule, first of all? What are these rules?\n\n\n\n\n\nLet's think about that. Rules have parts. If you look at these rules in detail, what you see,\nfor example, is the rule has a left-hand side and a right-hand side. Each of these rules has a\n\nleft-hand side and the right-hand side. The left-hand side is somehow compared with the\nexpression you're trying to take the derivative of. The right-hand side is the replacement for\n\nthat expression. So all rules on this page are something like this.\n\n\n\n\nI have patterns, and somehow, I have to produce, given a pattern, a skeleton. This is a\n\nrule. A pattern is something that matches, and a skeleton is something you substitute into\nin order to get a new expression. So what that means is that the pattern is matched against\n\nthe expression, which is the source expression. And the result of the application of the rule\nis to produce a new expression, which I'll call a target, by instantiation of a skeleton. T hat's\n\ncalled instantiation. So that is the process by which these rules are described.\n\n\n\n\nWhat I'd like to do today is build a language and a means of interpreting that language, a\n\nmeans of executing that language, where that language allows us to directly express these\nrules. And what we're going to do is instead of bringing the rules to the level of the\ncomputer by writing a program that is those rules in the computer's language -- at the\n\nmoment, in a Lisp-- we're going to bring the computer to the level of us by writing a way by\nwhich the computer can understand rules of this sort.\n\n\n\n\n\nThis is slightly emphasizing the idea that we had last time that we're trying to make a\nsolution to a class of problems rather than a particular one. The problem is if I want to write\n\nrules for a different piece of mathematics, say, to simple algebraic simplification or\nsomething like that, or manipulation of trigonometric functions, I would have to write a\n\ndifferent program in using yesterday's method. Whereas I would like to encapsulate all of\nthe things that are common to both of those programs, meaning the idea of matching,\n\ninstantiation, the control structure, which turns out to be very complicated for such a thing,\nI'd like to encapsulate that separately from the rules themselves.\n\n\n\n\n\nSo let's look at, first of all, a representation. I'd like to use the overhead here. I'd lik--\nthere it is. I'd like to look at a representation of the rules of calculus for derivatives in a sort\n\nof simple language that I'm writing right here. Now, I'm going to avoid--I'm going to avoid\nworrying about syntax. We can easily pretty this, and I'm not interested in making -- this is\n\nindeed ugly. This doesn't look like the beautiful text set dx by dt or something that I'd like\n\nto write, but that's not essential. That's sort of an accidental phenomenon.\n\n\n\n\nHere, we're just worrying about the fact that the structure of the rules is that there is a left-\nhand side here, represents the thing I want to match against the derivative expression. This\n\nis the representation I'm going to say for the derivative of a constant, which we will call c\n\nwith respect to the variable we will call v. And what we will get on the right- hand side is 0.\nSo this represents a rule.\n\n\n\n\nThe next rule will be the derivative of a variable, which we will call v with respect to the\n\nsame variable v, and we get a 1. However, if we have the derivative of a variable called u\n\nwith respect to a different variables v, we will get 0. I just want you look at these rules a\nlittle bit and see how they fit together. For example, over here, we're going to have the\n\nderivative of the sum of an expression called x1 and an expression called x2. These things\nthat begin with question marks are called pattern variables in the language that we're\n\ninventing, and you see we're just making it up, so pattern variables for matching.\n\n\n\n\nAnd so in this-- here we have the derivative of the sum of the expression which we will call\n\nx1. And the expression we will call x2 with respect to the variable we call v will be-- here is\nthe right-hand side: the sum of the derivative of that expression x1 with respect to v -- the\n\nright-hand side is the skeleton-- and the derivative of x2 with respect to v. Colons here will\nstand for substitution objects. They're--we'll call them skeleton evaluations.\nSo let me put up here on the blackboard for a second some syntax so we'll know what's\ngoing on for this rule language. First of all, we're going to have to worry about the pattern\n\nmatching. We're going to have things like a symbol like foo matches exactly itself. The\nexpression f of a and b will be used to match any list whose first element is f, whose second\n\nelement is a, and whose third element is b.\n\n\n\n\nAlso, another thing we might have in a pattern is that-- a question mark with some variable\n\nlike x. And what that means, it says matches anything, which we will call x. Question mark c\nx will match only constants. So this is something which matches a constant colon x. And\n\nquestion mark v x will match a variable, which we call x.\n\n\n\n\nThis is sort of the language we're making up now. If I match two things against each other,\n\nthen they are compared element by element. But elements in the pattern may contain these\nsyntactic variables, pattern variables, which will be used to match arbitrary objects. And\n\nwe'll get that object as the value in the name x here, for example.\n\n\n\n\nNow, when we make skeletons for instantiation. Well, then we have things like this. foo, a\n\nsymbol, instantiates to itself. Something which is a list like f of a and b, instantiates to --\nwell, f instantiates to a 3-list, a list of three elements, okay, which are the results of\n\ninstantiating each of f, a, and b. And x well--we instantiate to the value of x as in the\n\nmatched pattern.\n\n\n\n\nSo going back to the overhead here, we see--we see that all of those kinds of objects, we\nsee here a pattern variable which matches a constant, a pattern variable which matches a\n\nvariable, a pattern variable which will match anything. And if we have two instances of the\n\nsame name, like this is the derivative of the expression which is a variable only whose name\nwill be v with respect to some arbitrary expression which we will call v, since this v appears\n\ntwice, we're going to want that to mean they have to be the same.\n\n\n\n\nThe only consistent match is that those are the same. So here, we're making up a language.\nAnd in fact, that's a very nice thing to be doing. It's so much fun to make up a language.\n\nAnd you do this all the time. And the really most powerful design things you ever do are\n\nsort of making up a language to solve problems like this.\n\n\n\n\nNow, here we go back here and look at some of these rules. Well, there's a whole set of\nthem. I mean, there's one for addition and one for multiplication, just like we had before.\nThe derivative of the product of x1 and x2 with respect to v is the sum of the product of x1\n\nand the derivative x2 with respect to v and the product of the derivative of x1 and x2. And\nhere we have exponentiation. And, of course, we run off the end down here. We get as\n\nmany as we like. But the whole thing over here, I'm giving this --this list of rules the name\n\"derivative rules.\"\n\n\n\n\n\nWhat would we do with such a thing once we have it? Well, one of the nicest ideas, first of\nall, is I'm going to write for you, and we're going to play with it all day. What I'm going to\n\nwrite for you is a program called simplifier, the general-purpose simplifier. And we're going\nto say something like define dsimp to be a simplifier of the derivative rules. And what\n\nsimplifier is going to do is, given a set of rules, it will producfor me a procedure which will\nsimplify expressions containing the things that are referred to by these rules.\n\n\n\n\n\nSo here will be a procedure constructed for your purposes to simplify things with derivatives\nin them such that, after that, if we're typing at some list system, and we get a prompt, and\n\nwe say dsimp, for example, of the derivative of the sum of x and y with respect to x -- note\nthe quote here because I'm talking about the expression which is the derivative -- then I will\n\nget back as a result plus 1 0. Because the derivative of x plus y is the derivative of x plus\n\nderivative y. The derivative of x with respect to x is 1. The derivative of y with respect to x\nis 0. It's not what we're going to get. I haven't put any simplification at that level --\n\nalgebraic simplification -- yet.\n\n\n\n\nOf course, once we have such a thing, then we can--then we can look at other rules. So, for\n\nexample, we can, if we go to the slide, OK? Here, for example, are other rules that we\nmight have, algebraic manipulation rules, one s that would be used for simplifying algebraic\n\nexpressions. For example, just looking at some of these, the left-hand side says any\noperator applied to a constant e1 and a constant e2 is the result of evaluating that operator\n\non the constants e1 and e2. Or an operator, applied to e1, any expression e1 and a\nconstant e2, is going to move the constant forward. So that'll turn into the operator with e2\n\nfollowed by e1. Why I did that, I don't know. It wouldn't work if I had division, for example.\nSo there's a bug in the rules, if you like.\n\n\n\n\n\nSo the sum of 0 and e is e. The product of 1 and any expression e is e. The product of 0 and\nany expression e is 0. Just looking at some more of these rules, we could have arbitrarily\n\ncomplicated ones. We could have things like the product of the constant e1 and any\nconstant e2 with e3 is the result of multiplying the result of--multiplying now the constants\n\ne1 and e2 together and putting e3 there. So it says combine the constants that I had, which\nwas if I had a product of e1 and e2 and e3 just multiply--I mean and e1 and e2 are both\n\nconstants, multiply them.\nAnd you can make up the rules as you like. There are lots of them here. There are things as\n\ncomplicated, for example, as-- oh, I suppose down here some distributive law, you see. The\nproduct of any object c and the sum of d and e gives the result as the same as the sum of\n\nthe product of c and d and the product of c and e.\n\n\n\n\nNow, what exactly these rules are doesn't very much interest me. We're going to be writing\n\nthe language that will allow us to interpret these rules so that we can, in fact, make up\nwhatever rules we like, another whole language of programming. Well, let's see. I haven't\n\ntold you how we're going to do this. And, of course, for a while, we're going to work on that.\nBut there's a real question of what is--what am I going to do at all at a large scale? How do\n\nthese rules work? How is the simplifier program going to manipulate these rules with your\nexpression to produce a reasonable answer?\n\n\n\n\n\nWell, first, I'd like to think about these rules as being some sort of deck of them. So here I\nhave a whole bunch of rules, right? Each rule-- here's a rule-- has a pattern and a skeleton.\n\nI'm trying to make up a control structure for this.\n\n\n\n\nNow, what I have is a matcher, and I have something which is an instantiater. And I'm\n\ngoing to pass from the matcher to the instantiater some set of meaning for the pattern\nvariables, a dictionary, I'll call it. A dictionary, which will say x was matched a gainst the\n\nfollowing subexpression and y was matched against another following subexpression. And\nfrom the instantiater, I will be making expressions, and they will go into the matcher. They\n\nwill be expressions. And the patterns of the rules will be fed into the matcher, and the\n\nskeletons from the same rule will be fed into the instantiater.\n\n\n\n\nNow, this is a little complicated because when you have something like an algebraic\nexpression, where someth--the rules are intended to be able to allow you to substitute\n\nequal for equal. These are equal transformation rules. So all subexpressions of the\n\nexpression should be looked at. You give it an expression, this thing, and the rules should\nbe cycled around.\n\n\n\n\nFirst of all, for every subexpression of the expressionyou feed in, all of the rules must be\n\ntried and looked at. And if any rule matches, then this process occurs. The dictionary--the\ndictionary is to have some values in it. The instantiater makes a new expression, which is\n\nbasically replaces that part of the expression that was matched in your original expression.\n\nAnd then, then, of course, we're going to recheck that, going to go around these rules\nagain, seeing if that could be simplified further. And then, then we're going to do that for\n\nevery subexpression until the thing no longer changes.\nYou can think of this as sort of an organic process. You've got some sort of stew, right?\nYou've got bacteria or something, or enzymes in some, in some gooey mess. And there's\n\nthese--and these enzymes change things. They attach to your expression, change it, and\nthen they go away. And they have to match. The key-in-lock phenomenon. They match,\n\nthey change it, they go away. You can imagine it as a parallel process of some sort. So you\n\nstick an expression into this mess, and after a while, you take it out, and it's been\nsimplified. And it just keeps changing until it no longer can be changed. But these enzymes\n\ncan attach to any part of the, of the expression.\n\n\n\n\nOK, at this point, I'd like to stop and ask for questions. Yes.\n\n\n\n\nAUDIENCE: This implies that the matching program and the instantiation program are\n\nseparate programs; is that right? Or is that-- they are.\n\n\n\n\nPROFESSOR: They're separate little pieces. They fit together in a larger structure.\n\n\n\n\n\nAUDIENCE: So I'm going through and matching and passing the information about what I\nmatched to an instantiater, which makes the changes. And then I pass that back to the\n\nmatcher?\n\n\n\n\nPROFESSOR: It won't make a change. It will make a new expression, which has, which has\n\nsubstituted the values of the pattern variable that were matched on the left-hand side for\nthe variables that are mentioned, the skeleton variables or evaluation variables or whatever\n\nI called them, on the right-hand side.\n\n\n\n\nAUDIENCE: And then that's passed back into the matcher?\n\n\n\n\nPROFESSOR: Then this is going to go around again. This is going to go through this mess\n\nuntil it no longer changes.\n\n\n\n\nAUDIENCE: And it seems that there would be a danger of getting into a recursive loop.\nPROFESSOR: Yes. Yes, if you do not write your rules nicely, you are-- indeed, in any\n\nprogramming language you invent, if it's sufficiently powerful to do anything, you can write\nprograms that will go into infinite loops. And indeed, writing a program for doing algebraic\n\nmanipulation for long will produce infinite loops. Go ahead.\n\n\n\n\nAUDIENCE: Some language designers feel that this feature is so important that it should\n\nbecome part of the basic language, for example, scheme in this case. What are your\nthoughts on--\n\n\n\n\n\nPROFESSOR: Which language feature?\n\n\n\n\nAUDIENCE: The pairs matching. It's all application of such rules should be--\n\n\n\n\nPROFESSOR: Oh, you mean like Prolog?\n\n\n\n\n\nAUDIENCE: Like Prolog, but it becomes a more general--\n\n\n\n\nPROFESSOR: It's possible. OK, I think my feeling about that is that I would like to teach you\nhow to do it so you don't depend upon some language designer.\n\n\n\n\n\nAUDIENCE: OK.\n\n\n\n\nPROFESSOR: You make it yourself. You can roll your own. Thank you.\n\n\n\n\nWell, let's see. Now we have to tell you how it works. It conveniently breaks up into various\n\npieces. I'd like to look now at the matcher. The matcher has the following basic structure.\n\nIt's a box that takes as its input an expression and a pattern, and it turns out a dictionary.\n\n\n\n\nA dictionary, remember, is a mapping of pattern variables to the values that were found by\nmatching, and it puts out another dictionary, which is the result of augmenting this\n\ndictionary by what was found in matching this expression against this pattern. So that's the\nmatcher.\nNow, this is a rather complicated program, and we can look at it on the overhead over here\nand see, ha, ha, it's very complicated. I just want you to look at the shape of it. It's too\n\ncomplicated to look at except in pieces. However, it's a fairly large, complicated program\nwith a lot of sort of indented structure. At the largest scale-- you don't try to read those\n\ncharacters, but at the largest scale, you see that there is a case analysis, which is all these\n\ncases lined up. What we're now going to do is look at this in a bit more detail, attempting to\nunderstand how it works.\n\n\n\n\nLet's go now to the first slide, showing some of the structure of the matcher at a large\n\nscale. And we see that the matcher, the matcher takes as its input a pattern, an expression,\n\nand a dictionary. And there is a case analysis here, which is made out of several cases,\nsome of which have been left out over here, and the general case, which I'd like you to see.\n\n\n\n\nLet's consider this general case. It's a very important pattern. The problem is that we have\n\nto examine two trees simultaneously. One of the trees is the tree of the expression, and the\n\nother is the tree of the pattern. We have to compare them with each other so that the\nsubexpressions of the expression are matched against subexpressions of the pattern.\n\n\n\n\nLooking at that in a bit more detail, suppose I had a pattern, a pattern, which was the sum\n\nof the product of a thing which we will call x and a thing which we will call y, and the sum of\n\nthat, and the same thing we call y. So we're looking for a sum of a product whose second--\nwhose second argument is the same as the second argument of the sum. That's a thing you\n\nmight be looking for. Well, that, as a pattern, looks like this. There is a tree, which consists\nof a sum, and a product with a pattern variable question mark x and question mark y, the\n\nother pattern variable, and question mark y, just looking at the same, just writing down the\nlist structure in a different way.\n\n\n\n\n\nNow, suppose we were matching that against an expression which matches it, the sum of,\nsay, the product of 3 and x and, say, x. That's another tree. It's the sum of the product of 3\n\nand x and of x. So what I want to do is traverse these two trees simultaneously. And what\nI'd like to do is walk them like this. I'm going to say are these the same? This is a\n\ncomplicated object. Let's look at the left branches. Well, that could be the car. How does\nthat look? Oh yes, the plus looks just fine. But the next thing here is a complicated thing.\n\nLet's look at that. Oh yes, that's pretty fine, too. They're both asterisks.\n\n\n\n\nNow, whoops! My pattern variable, it matches against the 3. Remember, x equals 3 now.\n\nThat's in my dictionary, and the dictionary's going to follow along with me: x equals three.\nAh yes, x equals 3 and y equals x, different x. The pattern x is the expression x, the pattern\n\ny. Oh yes, the pattern variable y, I've already got a value for it. It's x. Is this an x? Oh\nyeah, sure it is. That's fine. Yep, done. I now have a dictionary, which I've accumulated by\n\nmaking this walk.\n\n\n\n\nWell, now let's look at this general case here and see how that works. Here we have it. I\n\ntake in a pattern variable--a pattern, an expression, and a dictionary. And now I'm going to\ndo a complicated thing here, which is the general case. The expression is made out of two\n\nparts: a left and a right half, in general. Anything that's complicated is made out of two\npieces in a Lisp system.\n\n\n\n\n\nWell, now what do we have here? I'm going to match the car's of the two expressions\nagainst each other with respect to the dictionary I already have, producing a dictionary as\n\nits value, which I will then use for matching the cdr's against each other. So that's how the\ndictionary travels, threads the entire structure. And then theresult of that is the dictionary\n\nfor the match of the car and the cdr, and that's what's going to be returned as a value.\n\n\n\n\nNow, at any point, a match might fail. It may be the case, for example, if we go back and\n\nlook at an expression that doesn't quite match, like supposing this was a 4. Well, now these\ntwo don't match any more, because the x that had to be-- sorry, the y that had to be x here\n\nand this y has to be 4. But x and 4 were not the same object syntactically. So this wouldn't\nmatch, and that would be rejected sometimes, so matches may fail.\n\n\n\n\n\nNow, of course, because this matcher takes the dictionary from the previous match as\ninput, it must be able to propagate the failures. And so that's what the first clause of this\n\nconditional does.\n\n\n\n\nIt's also true that if it turned out that the pattern was not atomic-- see, if the pattern was\n\natomic, I'd go into this stuff, which we haven't looked at yet. But if the pattern is not atomic\nand the expression is atomic-- it's not made out of pieces-- then that must be a failure, and\n\nso we go over here. If the pattern is not atomic and the pattern is not a pattern variable -- I\nhave to remind myself of that-- then we go over here. So that way, failures may occur.\n\n\n\n\n\nOK, so now let's look at the insides of this thing. Well, the first place to look is what\nhappens if I have an atomic pattern? That's very simple. A pattern that's not made out of\n\nany pieces: foo. That's a nice atomic pattern. Well, here's what we see. If the pattern is\natomic, then if the expression is atomic, then if they are the same thing, then the dictionary\nI get is the same one as I had before. Nothing's changed. It's just that I matched plus\n\nagainst plus, asterisk against asterisk, x against x. That's all fine.\n\n\n\n\nHowever, if the pattern is not the one which is the expression, if I have two separate atomic\n\nobjects, then it was matching plus against asterisk, which case I fail. Or if it turns out that\nthe pattern is atomic but the expression is complicated, it's not atomic, then I get a failure.\n\nThat's very simple.\n\n\n\n\nNow, what about the various kinds of pattern variables? We had three kinds. I give them\n\nthe names. They're arbitrary constants, arbitrary variables, and arbitrary expressions. A\nquestion mark x is an arbitrary expression. A question mark cx is an arbitrary constant, and\n\na question mark vx is an arbitrary variable.\n\n\n\n\nWell, what do we do here? Looking at this, we see that if I have an arbitrary constant, if the\n\npattern is an arbitrary constant, then it had better be the case that the expressi on had\nbetter be a constant. If the expression is not a constant, then that match fails. If it is a\n\nconstant, however, then I wish to extend the dictionary. I wish to extend the dictionary with\nthat pattern being remembered to be that expression using the old dictionary as a starting\n\npoint.\n\n\n\n\nSo really, for arbitrary variables, I have to check first if the expression is a variable by\n\nmatching against. If so, it's worth extending the dictionary so that the pattern is\nremembered to be matched against that expression, given the original dictionary, and this\n\nmakes a new dictionary.\n\n\n\n\nNow, it has to check. There's a sorts of failure inside extend dictionary, which is that-- if one\n\nof these pattern variables already has a value and I'm trying to match the thing ag ainst\nsomething else which is not equivalent to the one that I've already matched it against once,\n\nthen a failure will come flying out of here, too. And I will see that some time.\n\n\n\n\nAnd finally, an arbitrary expression does not have to check anything synta ctic about the\n\nexpression that's being matched, so all it does is it's an extension of the dictionary.\n\n\n\n\nSo you've just seen a complete, very simple matcher. Now, one of the things that's rather\nremarkable about this is people pay an awful lot of money these days for someone to make\n\na, quote, AI expert system that has nothing more in it than a matcher and maybe an\ninstantiater like this. But it's very easy to do, and now, of course, you can start up a little\n\nstart-up company and make a couple of megabucks in the next week taking some people\nfor a ride. 20 years ago, this was remarkable, this kind of program. But now, this is sort of\n\neasy. You can teach it to freshmen.\n\n\n\n\nWell, now there's an instantiater as well. The problem is they're all going off and making\n\nmore money than I do. But that's always been true of universities. As expression, the\npurpose of the instantiater is to make expressions given a dictionary and a skeleton. And\n\nthat's not very hard at all. We'll see that very simply in the next, the next slide here.\n\n\n\n\nTo instantiate a skeleton, given a particular dictionary-- oh, this is easy. We're going to do a\n\nrecursive tree walk over the skeleton. And for everything which is a skeleton variable -- I\ndon't know, call it a skeleton evaluation. That's the name and the abstract syntax that I give\n\nit in this program: a skeleton evaluation, a thing beginning with a colon in the rules. For\nanything of that case, I'm going to look up the answer in the dictionary, and we'll worry\n\nabout that in a second. Let's look at this as a whole.\n\n\n\n\nHere, I have-- I'm going to instantiate a skeleton, given a dictionary. Well, I'm going to\n\ndefine some internal loop right there, and it's going to do something very simple. Even if a\nskeleton--even if a skeleton is simple and atomic, in which case it's nothing more than\n\ngiving the skeleton back as an answer, or in the general case, it's complicated, in which\ncase I'm going to make up the expression which is the result of instantiating-- calling this\n\nloop recursively-- instantiating the car of the skeleton and the cdr.\n\n\n\n\nSo here is a recursive tree walk. However, if it turns out to be a skeleton evaluation, a colon\n\nexpression in the skeleton, then what I'm going to do is find the expression that's in the\ncolon-- the CADR in this case. It's a piece of abstract syntax here, so I can change my\n\nrepresentation of rules. I'm going to evaluate that relative to this dictionary, whatever\n\nevaluation means. We'll find out a lot about that sometime. And the result of that is my\nanswer. so. I start up this loop-- here's my initialization -- by calling it with the whole\n\nskeleton, and this will just do a recursive decomposition into pieces.\n\n\n\n\nNow, one more little b it of detail is what happens inside evaluate? I can't tell you that in\ngreat detail. I'll tell you a little bit of it. Later, we're going to see--look into this in much\n\nmore detail. To evaluate some form, some expression with respect to a dictionary, if the\n\nexpression is an atomic object, well, I'm going to go look it up. Nothing very exciting there.\nOtherwise, I'm going to do something complicated here, which is I'm going to apply a\n\nprocedure which is the result of looking up the operator part in somethingthat we're going\nto find out about someday.\nI want you realize you're seeing magic now. This magic will become clear very soon, but not\ntoday. Then I'm looking at--looking up all the pieces, all the arguments to that in the\n\ndictionary. So I don't want you to look at this in detail. I want you to say that there's more\ngoing on here, and we're going to see more about this. But it's-- the magic is going to stop.\n\nThis part has to do with Lisp, and it's the end of that.\n\n\n\n\nOK, so now we know about matching and instantiation. Are there any questions for this\n\nsegment?\n\n\n\n\nAUDIENCE: I have a question.\n\n\n\n\n\nPROFESSOR: Yes.\n\n\n\n\nAUDIENCE: Is it possible to bring up a previous slide? It's about this define match pattern.\n\n\n\n\nPROFESSOR: Yes. You'd like to see the overall slide define match pattern. Can somebody\n\nput up the-- no, the overhead. That's the biggest scale one. What part would you like to\nsee?\n\n\n\n\n\nAUDIENCE: Well, the top would be fine. Any of the parts where you're passing failed.\n\n\n\n\nPROFESSOR: Yes.\n\n\n\n\nAUDIENCE: The idea is to pass failed back to the dictionary; is that right?\n\n\n\n\n\nPROFESSOR: The dictionary is the answer to a match, right? And it is either some mapping\nor there's no match. It doesn't match.\n\n\n\n\n\nAUDIENCE: Right.\nPROFESSOR: So what you're seeing over here is, in fact, because the fact that a match may\nhave another match pass in the dictionary, as you see in the general case down here. Here's\n\nthe general case where a match passes another match to the dictionary. When I match the\ncdr's, I match them in the dictionary that is resulting from matching the car's. OK, that's\n\nwhat I have here. So because of that, if the match of the car's fails, then it may be\n\nnecessary that the match of the cdr's propagates that failure, and that's what the first line\nis.\n\n\n\n\nAUDIENCE: OK, well, I'm still unclear what matches-- what comes out of one instance of the\n\nmatch?\n\n\n\n\nPROFESSOR: One of two possibilities. Either the symbol failed, which means there is no\n\nmatch.\n\n\n\n\nAUDIENCE: Right.\n\n\n\n\n\nPROFESSOR: Or some mapping, which is an abstract thing right now, and you should know\nabout the structure of it, which relates the pattern variables to their values as picked up in\n\nthe match.\n\n\n\n\nAUDIENCE: OK, so it is--\n\n\n\n\nPROFESSOR: That's constructed by extend dictionary.\n\n\n\n\n\nAUDIENCE: So the recursive nature brings about the fact that if ever a failed gets passed\nout of any calling of match, then the first condition will pick it up --\n\n\n\n\n\nPROFESSOR: And just propagate it along without any further ado, right.\n\n\n\n\nAUDIENCE: Oh, right. OK.\nPROFESSOR: That's just the fastest way to get that failure out of there. Yes.\n\n\n\n\nAUDIENCE: If I don't fail, that means that I've matched a pattern, and I run the procedure\n\nextend dict and then pass in the pattern in the expression. But the substitution will not be\n\nmade at that point; is that right? I'm just--\n\n\n\n\nPROFESSOR: No, no. There's no substitution being there because there's no skeleton to be\nsubstituted in.\n\n\n\n\n\nAUDIENCE: Right. So what--\n\n\n\n\nPROFESSOR: All you've got there is we're making up the dictionary for later substitution.\n\n\n\n\nAUDIENCE: And what would the dictionary look like? Is it ordered pairs?\n\n\n\n\n\nPROFESSOR: That's--that's not told to you. We're being abstract.\n\n\n\n\nAUDIENCE: OK.\n\n\n\n\nPROFESSOR: Why do you want to know? What it is, it's a function. It's a function.\n\n\n\n\n\nAUDIENCE: Well, the reason I want to know is--\n\n\n\n\nPROFESSOR: A function abstractly is a set of ordered pairs. It could be implemented as a\n\nset of list pairs. It could be implemented as some fancy table mechanism. It could be\nimplemented as a function. And somehow, I'm building up a function. But I'm not telling\n\nyou. That's up to George, who's going to build that later.\n\n\n\n\nI know you really badly want to write concrete things. I'm not going to let you do that.\nAUDIENCE: Well, let me at least ask, what is the important information there that's being\n\npassed to extend dict? I want to pass the pattern I found--\n\n\n\n\nPROFESSOR: Yes. The pattern that's matched against the expression. You want to have the\n\npattern, which happens to be in those cases pattern variables, right? All of those three\ncases for extend dict are pattern variables.\n\n\n\n\nAUDIENCE: Right.\n\n\n\n\n\nPROFESSOR: So you have a pattern variable that is to be given a value in a dictionary.\n\n\n\n\nAUDIENCE: Mm-hmm.\n\n\n\n\nPROFESSOR: The value is the expression that it matched against. The dictionary is the set\n\nof things I've already figured out that I have memorized or learned. And I am going to\n\nmake a new dictionary, which is extended from the originalone by having that pattern\nvariable have a value with the new dictionary.\n\n\n\n\nAUDIENCE: I guess what I don't understand is why can't the substitution be made right as\n\nsoon as you find--\n\n\n\n\nPROFESSOR: How do I know what I'm going to substitute? I don't know anything about this\n\nskeleton. This pattern, this matcher is an independent unit.\n\n\n\n\nAUDIENCE: Oh, I see. OK.\n\n\n\n\n\nPROFESSOR: Right?\n\n\n\n\nAUDIENCE: Yeah.\nPROFESSOR: I take the matcher. I apply the matcher. If it matches, then it was worth doing\n\ninstantiation.\n\n\n\n\nAUDIENCE: OK, good. Yeah.\n\n\n\n\nPROFESSOR: OK?\n\n\n\n\n\nAUDIENCE: Can you just do that answer again using that example on the board? You know,\nwhat you just passed back to the matcher.\n\n\n\n\n\nPROFESSOR: Oh yes. OK, yes. You're looking at this example. At this point when I' m\ntraversing this structure, I get to here: x. I have some dictionary, presumably an empty\n\ndictionary at this point if this is the whole expression. So I have an empty dictionary, and\nI've matched x against 3. So now, after this point, the dictionary contains x is 3, OK?\n\n\n\n\n\nNow, I continue walking along here. I see y. Now, this is a particular x, a pattern x. I see y,\na pattern y. The dictionary says, oh yes, the pattern y is the symbol x because I've got a\n\nmatch there. So the dictionary now contains at this point two entries. The pattern x is 3,\nand the pattern y is the expression x. Now, I get that, I can walk along further. I say, oh,\n\npattern y also wants to be 4. But that isn't possible, producing a failure. Thank you. Let's\ntake a break.\n\n\n\n\n\nOK, you're seeing your first very big and hairy program. Now, of course, one of the goals of\nthis subsegment is to get you to be able to read something like this and not be afraid of it.\n\nThis one's only about four pages of code. By the end of the subject, I hope a 50 -page\nprogram will not look particularly frightening. But I don't expect-- and I don't want you to\n\nthink that I expect you to be getting it as it's coming out. You're supposed to feel the flavor\nof this, OK? And then you're supposed to think about it because it is a big program. There's\n\na lot of stuff inside this program.\n\n\n\n\nNow, I've told you about the language we're implementing, the pattern match substitution\n\nlanguage. I showed you some rules. And I've told you about matching and instantiation,\nwhich are the two halves of how a rule works. Now we have to understand the cont rol\n\nstructure by which the rules are applied to the expressions so as to do algebraic\nsimplification.\nNow, that's also a big complicated mess. The problem is that there is a variety of\ninterlocking, interwoven loops, if you will, involved in this. For on e thing, I have to apply-- I\n\nhave to examine every subexpression of my expression that I'm trying to simplify. That we\nknow how to do. It's a car cdr recursion of some sort, or something like that, and some sort\n\nof tree walk. And that's going to be happening.\n\n\n\n\nNow, for every such place, every node that I get to in doing my traversal of the expression\n\nI'm trying to simplify, I want to apply all of the rules. Every rule is going to look at every\nnode. I'm going to rotate the rules around.\n\n\n\n\n\nNow, either a rule will or will not match. If the rule does not match, then it's not very\ninteresting. If the rule does match, then I'm going to replace that node in the expression by\n\nan alternate expression. I'm actually going to make a new expression, which contains --\neverything contains that new value, the result of substituting into the skeleton, instantiating\n\nthe skeleton for that rule at this level. But no one knows whether that thing that I\n\ninstantiated there is in simplified form. So we're going to have to simplify   that, somehow to\ncall the simplifier on the thing that I just constructed. And then when that's done, then I\n\nsort of can build that into the expression I want as my answer.\n\n\n\n\nNow, there is a basic idea here, which I will call a garbage - in, garbage-out simplifier. It's a\n\nkind of recursive simplifier. And what happens is the way you simplify something is that\nsimple objects like variables are simple. Compound objects, well, I don't know. What I'm\n\ngoing to do is I'm going to build up from simple objects, trying to make simple things by\nassuming that the pieces they're made out of are simple. That's what's happening here.\n\n\n\n\n\nWell, now, if we look at the first slide -- no, overhead, overhead. If we look at the overhead,\nwe see a very complicated program like we saw before for the matcher, so complicated that\n\nyou can't read it like that. I just want you to get the feel of the shape of it, and the shape of\nit is that this program has various subprograms in it. One of them--this part is the part for\n\ntraversing the expression, and this part is the part for trying rules.\n\n\n\n\nNow, of course, we can look at that in some more detail. Let's look at--let's look at the first\n\ntransparency, right? The simplifier is made out of several parts. Now, remember at the very\nbeginning, the simplifier is the thing which takes a rules--a set of rules and produces a\n\nprogram which will simplify it relative to them.\nSo here we have our simplifier. It takes a rule set. And in the context where that rule set is\n\ndefined, there are various other definitions that are done here. And then the result of this\nsimplifier procedure is, in fact, one of the procedures that was defined. Simplify x. What I'm\n\nreturning as the value of calling the simplifier on a set of rules is a procedure, the simplify x\nprocedure, which is defined in that context, which is a simplification procedure appropriate\n\nfor using those set of rules. That's what I have there.\n\n\n\n\nNow, the first two of these procedures, this one and this one, are together going to be the\n\nrecursive traversal of an expression. This one is the general simplification for any\nexpression, and this is the thing which simplifies a list of parts of an expression. Nothing\n\nmore. For each of those, we're going to do something complicated, which involves trying the\nrules.\n\n\n\n\n\nNow, we should look at the various parts. Well let's look first at the recursive traversal of an\nexpression. And this is done in a sort of simple way. This is a little nest of recursive\n\nprocedures. And what we have here are two procedures-- one for simplifying an expression,\nand one for simplifying parts of an expression. And the way this works is very simple. If the\n\nexpression I'm trying to simplify is a compound expression, I'm going to simplify all the\n\nparts of it. And that's calling--that procedure, simplify parts, is going to make up a new\nexpression with all the parts simplified, which I'm then going to try the rules on over here.\n\n\n\n\nIf it turns out that the expression is not compound, if it's simple, like just a symbol or\n\nsomething like pi, then in any case, I'm going to try the rules on it because it might be that\n\nI want in my set of rules to expand pi to 3.14159265358979, dot, dot, dot. But I may not.\nBut there is no reason not to do it.\n\n\n\n\nNow, if I want to simplify the parts, well, that's easy too. Either the expression is an empty\n\none, there's no more parts, in which case I have the empty expression. Otherwise, I'm\n\ngoing to make a new expression by cons, which is the result of simplifying the first part of\nthe expression, the car, and simplifying the rest of the expression, which is the cdr.\n\n\n\n\nNow, the reason why I'm showing you this sort of stuff this way is because I want you get\n\nthe feeling for the various patterns that are very important when writing programs. And this\ncould be written a different way. There's another way to write simplified expressions so\n\nthere would be only one of them. There would only be one little procedure here. Let me just\n\nwrite that on the blackboard to give you a feeling for that.\nThis in another idiom, if you will. To simplify an expression called x, what am I going to do?\n\nI'm going to try the rules on the following situation. If-- on the following expression--\ncompound, just like we had before. If the expression is compound, well, what am I going to\n\ndo? I'm going to simplify all the parts. But I already have a cdr recursion, a common\npattern of usage, which has been captured as a high -order procedure. It's called map. So I'll\n\njust write that here.\n\n\n\n\nMap simplify the expression, all the parts of the expression. This says apply the\n\nsimplification operation, which is this one, every part of the expression, and then that cuts\nthose up into a list. It's every element of the list which the expression is assumed to be\n\nmade out of, and otherwise, I have the expression. So I don't need the helper procedure,\nsimplify parts, because that's really this. So sometimes, you just write it this way. It doesn't\n\nmatter very much.\n\n\n\n\nWell, now let's take a look at -- let's just look at how you try rules. If you look at this slide,\n\nwe see this is a complicated mess also. I'm trying rules on an expression. It turns out the\nexpression I'm trying it on is some subexpression now of the expression I started with.\n\nBecause the thing I just arranged allowed us to try every subexpression.\n\n\n\n\nSo now here we're taking in a subexpression of the expression we started with. That's what\n\nthis is. And what we're going to define here is a procedure called scan, which is going to try\nevery rule. And we're going to start it up on the whole set of rules. This is going to go cdr-\n\ning down the rules, if you will, looking for a rule to apply. And when it finds one, it'll do the\n\njob.\n\n\n\n\nWell, let's take a look at how try rules works. It's very simple: thescan rules. Scan rules,\nthe way of scanning. Well, is it so simple? It's a big program, of course. We take a bunch of\n\nrules, which is a sublist of the list of rules. We've tried some of them already, and they've\n\nnot been appropriate, so we get to some here. We get to move to the next one. If there are\nno more rules, well then, there's nothing I can do with this expression, and it's simplified.\n\n\n\n\nHowever, if it turns out that there are still rules to be done, then let's match the pattern of\n\nthe first rule against the expression using the empty dictionary to start with and use that as\nthe dictionary. If that happens to be a failure, try the rest of the rules. That's all it says\n\nhere. It says discard that rule. Otherwise, well, I'm going to get the skeleton ofthe first\n\nrule, instantiate that relative to the dictionary, and simplify the result, and that's the\nexpression I want.\nSo although that was a complicated program, every complicated program is made out of a\n\nlot of simple pieces. Now, the pattern of recursions here is very complicated. And one of the\nmost important things is not to think about that. If you try to think about the actual pattern\n\nby which this does something, you're going to get very confused. I would. This is not a\nmatter of you can do this with practice. These patterns are hard. But you don't have to\n\nthink about it. The key to this-- it's very good programming and very good design-- is to\nknow what not to think about.\n\n\n\n\n\nThe fact is, going back to this slide, I don't have to think about it because I have\nspecifications in my mind for what simplify x does. I don't have to know how it does it. And\n\nit may, in fact, call scan somehow through try rules, which it does. And somehow, I've got\nanother recursion going on here. But since I know that sim plify x is assumed by wishful\n\nthinking to produce the simplified result, then I don't have to think about it anymore. I've\n\nused it. I've used it in a reasonable way. I will get a reasonable answer. And you have to\nlearn how to program that way-- with abandon.\n\n\n\n\nWell, there's very little left of this thing. All there is left is a few details associated with what\n\na dictionary is. And those of you who've been itching to know what a dictionary is, well, I\n\nwill flip it up and not tell you anything about it. Dictionaries are easy. It's represented in\nterms of something else called an A list, which is a particular pattern of usage for making\n\ntables in lists. They're easy. They're made out of pairs, as was asked a bit ago. And there\nare special procedures for dealing with such things called assq, and you can find them in\n\nmanuals.\n\n\n\n\nI'm not terribly excited about it. The only interesting thing here in extend dictionary is I\n\nhave to extend the dictionary with a pattern, a datum, and a dictionary. This pattern is, in\nfact, at this point a pattern variable. And what do I want to do? I want to pull out the name\n\nof that pattern variable, the pattern variable name, and I'm going to look up in the\ndictionary and see if it already has a value. If not, I'm going to add a new on e in. If it does\n\nhave one, if it has a value, then it had better be equal to the one that was already stored\naway. And if that's the case, the dictionary is what I expected it to be. Otherwise, I fail. So\n\nthat's easy, too. If you open up any program, you're going to find inside of it lots of little\npieces, all of which are easy.\n\n\n\n\n\nSo at this point, I suppose, I've just told you some million-dollar valuable information. And I\nsuppose at this point we're pretty much done with this program. I'd like to ask ab out\n\nquestions.\nAUDIENCE: Yes, can you give me the words that describe the specification for a simplified\n\nexpression?\n\n\n\n\nPROFESSOR: Sure. A simplified expression takes an expression and produces a simplified\n\nexpression. That's it, OK? How it does it is very easy. In compound expressions, all the\npieces are simplified, and then the rules are tried on the result. And for simple expressions,\n\nyou just try all the rules.\n\n\n\n\nAUDIENCE: So an expression is simplified by virtue of the rules?\n\n\n\n\nPROFESSOR: That's, of course, true.\n\n\n\n\n\nAUDIENCE: Right.\n\n\n\n\nPROFESSOR: And the way this works is that simplifi expression, as you see here, what it\n\ndoes is it breaks the expression down into the smallest pieces, simplifies building up from\nthe bottom using the rules to be the simplifier, to do the manipulations, an d constructs a\n\nnew expression as the result. Eventually, one of things you see is that the rules themselves,\nthe try rules, call a simplified expression on the results when it changes something, the\n\nresults of a match. I'm sorry, the results of instantiation of a skeleton for a rule that has\nmatched. So the spec of a simplified expression is that any expression you put into it comes\n\nout simplified according to those rules. Thank you. Let's take a break.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed thismaterial in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec4b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 4B: Generic Operators\n\n\n\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH] PROFESSOR: So\nfar in this course we've been talking a lot about data abstraction. And remember the idea is\n\nthat we build systems that have these horizontal barriers in them, these abstraction barriers\nthat separate use, the way you might use some data object, from the way you might\n\nrepresent it. Or another way to think of that is up here you have the boss who's going to be\nusing some sort of data object. And down here is George who's implemented it. Now this\n\nnotion of separating use from representation so you can think about these two problems\nseparately is a very, very powerful programming methodology, data abstraction.\n\n\n\n\n\nOn the other hand, it's not really sufficient for really complex systems. And the problem\nwith this is George. Or actually, the problem is that there are a lot of Georges. Let's be\n\nconcrete. Let's suppose there is George, and there's also Martha. OK, now George and\nMartha are both working on this system, both designing representations, and absolutely are\n\nincompatible. They wouldn't cooperate on a representation under any circumstances.\n\n\n\n\nAnd the problem is you would like to have some system where both George and Martha are\n\ndesigning representations, and yet, if you're above this abstraction barrier you don't want to\nhave to worry about that, whether something is done by George or by Martha. And you\n\ndon't want George and Martha to interfere with each other. Somehow in designing a\nsystem, you not only want these horizontal barriers, but you also want some kind of vertical\n\nbarrier to keep George and Martha separate.\n\n\n\n\nLet me be a little bit more concrete. Imagine that you're thinking about personnel records\n\nfor a large company with a lot of loosely linked divisions that don't cooper ate very well\neither. And imagine even that this company is formed by merging a whole bunch of\n\ncompanies that already have their personnel record system set up. And imagine that once\n\nthese divisions are all linked in some kind of very sophisticated satelli te network, and all\nthese databases are put together. And what you'd like to do is, from any place in the\n\ncompany, to be able to say things like, oh, what's the name in a personnel record? Or,\nwhat's the job description in a personnel record? And not haveto worry about the fact that\n\neach division obviously is going to have completely separate conventions for how you might\nimplement these records. From this point you don't want to know about that.\nWell how could you possibly do that? One way, of course, is to send down an edict from\n\nsomewhere that everybody has to change their format to some fixed compatible thing.\nThat's what people often try, and of course it never works. Another thing that you might\n\nwant to do is somehow arrange it so you can have these vertical barriers. So that when you\nask for the name of a personnel record, somehow, whatever format it happens to be, name\n\nwill figure out how to do the right thing. We want name to be, so-called, a generic operator.\nGeneric operator means what it sort of precisely does depends on the kind of data that it's\n\nlooking at.\n\n\n\n\nMore than that, you'd like to design the system so that the next time a new division comes\n\ninto the company they don't have to make any big changes in what they're already doing to\nlink into this system, and the rest of the company doesn't have to make any big changes to\n\nadmit their stuff to the system. So that's the problem you should be thinking about. Like it's\n\nsort of just your work. You want to be able to include new things by making minimal\nchanges.\n\n\n\n\nOK, well that's the problem that we'll be talking about today. And you should have this sort\n\nof distributed personnel record system in your mind. But actually the one I'll be talking\n\nabout is a problem that's a little bit more self-contained than that. that'll bring up the\nissues, I think, more clearly. That's the problem of doing a system that does arithmetic on\n\ncomplex numbers. So let's take a look here.\n\n\n\n\nJust as a little review, there are things called complex numbers. Complex numberyou can\n\nthink of as a point in the plane, or z. And you can represent a point either by its real-part\nand its imaginary-part. So if this is z and its real-part is this much, and its imaginary-part is\n\nthat much, and you write z equals x plus iy.\n\n\n\n\nOr another way to represent a complex number is by saying, what's the distance from the\n\norigin, and what's the angle? So that represents a complex number as its radius times an\nangle. This one's called -- the original one's called rectangular form, rectangular\n\nrepresentation, real- and imaginary-part, or polar representation. Magnitude and angle--\nand if you know the real- and imaginary-part, you can figure out the magnitude and angle.\n\nIf you know x and y, you can get r by this formula. Square root of sum of the squa res, and\nyou can get the angle as an arctangent.\n\n\n\n\n\nOr conversely, if you knew r and A you could figure out x and y. x is r times the cosine of A,\nand y is r times the sine of A. All right, so there's these two. They're complex numbers. You\n\ncan think of them either in polar form or rectangular form. What we would like to do is\nmake a system that does arithmetic on complex numbers. In other words, what we'd like --\njust like the rational number example-- is to have some operations plus c, which is going to\n\ntake two complex numbers and add them, subtract them, and multiply them, and divide\nthem.\n\n\n\n\n\nOK, well there's little bit of mathematics behind it. What are the actual formulas for\nmanipulating such things? And it's sort of not important where they come from, b ut just as\n\nan implementer let's see-- if you want to add two complex numbers it's pretty easy to get\nits real-part and its imaginary-part. The real-part of the sum of two complex numbers, the\n\nreal-part of the z1 plus z2 is the real-part of z1 plus the real-part of z2. And the imaginary-\npart of z1 plus z2 is the imaginary part of z1 plus the imaginary part of z2. So it's pretty\n\neasy to add complex numbers. You just add the corresponding parts and make a new\ncomplex number with those parts.\n\n\n\n\n\nIf you want to multiply them, it's kind of nice to do it in polar form. Because if you have two\ncomplex numbers, the magnitude of their product is here, the product of the magnitudes.\n\nAnd the angle of the product is the sum of the angles. So that's sort of mathematics that\nallows you to do arithmetic on complex numbers.\n\n\n\n\n\nLet's actually think about the implementation. Well we do it just like rational numbers. We\ncome down, we assume we have some constructors and selectors. What would we like? Well\n\nlet's assume that we make a data object cloud, which is a complex number that has some\nstuff in it, and that we can get out from a complex number the real-part, or the imaginary-\n\npart, or the magnitude, or the angle.\n\n\n\n\nWe want some ways of making complex numbers-- not only selectors, but constructors. So\n\nwe'll assume we have a thing called make-rectangular. What make-rectangular is going to\ndo is take a real-part and an imaginary-part and construct a complex number with those\n\nparts. Similarly, we can have make-polar which will take a magnitude and an angle, and\n\nconstruct a complex number which has that magnitude and angle.\n\n\n\n\nSo here's a system. We'll have two constructors and four selectors. And now, just like\nbefore, in terms of that abstract data we'll go ahead and implement our complex number\n\noperations. And here you can see translated into Lisp code just the arithmetic formulas I put\ndown before. If I want to add two complex numbers I will make a complex number out of its\n\nreal- and imaginary-parts. The real part of the complex number I'm going to make is the\n\nsum of the real-parts. The imaginary part of the complex number I'm going to make is the\nsum of the imaginary-parts. I put those together, make a complex number. That's how I\n\nimplement complex number addition.\nSubtraction is essentially the same. All I do is subtract the parts rather than add them. To\nmultiply two complex numbers, I use the other formula. I'll make a complex number out of\n\na magnitude and angle. The magnitude is going to be the product of the magnitudes of the\ntwo complex numbers I'm multiplying. And the angle is going to be the sum of the angles of\n\nthe two complex numbers I'm multiplying. So there's multiplication.\n\n\n\n\nAnd then division, division is almost the same. Here I divide the magnitudes and subtract\n\nthe angles.\n\n\n\n\nNow I've implemented the operations. And what do we do? We call on George. We've done\n\nthe use, let's worry about the representation. We'll call on George and say to George, go\nahead and build us a complex number representation. Well that's fine. George can say, we'll\n\nimplement a complex number simply as a pair that has the real-part and the imaginary-\npart. So if I want to make a complex number with a certain real-part and an imaginary-part,\n\nI'll just use cons to form a pair, and that will-- that's George's representation of a complex\n\nnumber.\n\n\n\n\nSo if I want to get out the real-part of something, I just extract the car, the first part. If I\nwant to get the imaginary-part, I extract the cdr. How do I deal with the magnitude and\n\nangle? Well if I want to extract the magnitude of one of these things, I get the square root\n\nof the sum of the square of the car plus the square of the cdr. If I want to get the angle, I\ncompute the arctangent of the cdr in the car. This is a list procedure for computing\n\narctangent. And if somebody hands me a magnitude and an angle and says, make me a\ncomplex number, well I compute the real-part and the imaginary-part, or our cosine of a\n\nand our sine of a, and stick them together into a pair.\n\n\n\n\nOK so we're done. In fact, what I just did, conceptually, is absolutely no different from the\n\nrational number representation that we looked at last time. It's the same sort of idea. You\nimplement the operators, you pick a representation. Nothing different.\n\n\n\n\nNow let's worry about Martha. See, Martha has a different idea. She doesn't want to\n\nrepresent a complex number as a pair of a real-part and an imaginary-part. What she would\n\nlike to do is represent a complex number as a pair of a magnitude and an angle. So if\ninstead of calling up George we ask Martha to design our representation, we get something\n\nlike this. We get make-polar. Sure, if I give you a magnitude and an angle we're just going\nto form a pair that has magnitude and angle.\nIf you want to extract the magnitude, that's easy. You just pull out the car or the pair. If\nyou want to extract the angle, sure, that's easy. You just pull out the cdr. If you want to\n\nlook for real-parts and imaginary-parts, well then you have to do some work. If you want\nthe real-part, you have to get r cosine a. In other words, r, the car of the pair, times the\n\ncosine of the cdr of the pair. So this is r times the cosine of a, and that's the real -part. If\n\nyou want to get the imaginary-part, it's r times the sine of a.\n\n\n\n\nAnd if I hand you a real-part and an imaginary-part and say, make me a complex number\nwith that real-part and imaginary-part, well I figure out what the magnitude and angle\n\nshould be. The magnitude's the square root of the sum of the squares and the angle's the\n\narctangent. I put those together to make a pair. So there's Martha's idea.\n\n\n\n\nWell which is better? Well if you're doing a lot of additions, probably George's is better,\nbecause you're doing a lot of real-parts and imaginary-parts. If mostly you're going to be\n\ndoing multiplications and divisions, then maybe Martha's idea is better. Or maybe, and this\n\nis the real point, you can't decide. Or maybe you just have to let them both hang around,\nfor personality reasons. Maybe you just really can't ever decide what you would like.\n\n\n\n\nAnd again, what we would really like is a system that looks like this. That somehow there's\n\nGeorge over here, who has built rectangular complex numbers. And Martha, who has polar\n\ncomplex numbers. And somehow we have operations that can add, and subtract, and\nmultiply, and divide, and it shouldn't matter that there are two incompatible representations\n\nof complex numbers floating around this system.\n\n\n\n\nIn other words, not only like an abstraction barrier here that has things in it like a real -part,\n\nand an imaginary-part, and magnitude, and angle. So not only is there an abstraction\nbarrier that hides the actual representation from us, but also there's some kind of vertical\n\nbarrier here that allows both of these representations to exist without interfering with each\nother.\n\n\n\n\nThe idea is that the things in here-- real-part, imaginary-part, magnitude, and angle-- will\n\nbe generic operators. If you ask for the real-part, it will worry about what representation it's\n\nlooking at.\n\n\n\n\nOK, well how can we do that? There's actually a really obvious idea, if you're used to\nthinking about complex numbers. If you're used to thinking about compound data. See,\nsuppose you could just tell by looking at a complex number whether it was constructed by\n\nGeorge or Martha. In other words, so it's not that what's floating around here are ordinary,\njust complex numbers, right? They're fancy, designer complex numbers.\n\n\n\n\n\nSo you look at a complex numbers as it's not just a complex number, it's got a label on it\nthat says, this one is by Martha. Or this is a complex number by George. Right? They're\n\nsigned. See, and then whenever we looked at a complex number we could just read the\nlabel, and then we'd know how you expect to operate on that. In other words, what we\n\nwant is not just ordinary data objects. We want to introduce the notion of what's called\ntyped data. Typed data means, again, there's some sort of cloud. And what it's got in it i s\n\nan ordinary data object like we've been thinking about. Pulled out the contents, sort of the\nactual data. But also a thing called a type, but it's signed by either George or Martha. So\n\nwe're going to go from regular data to type data.\n\n\n\n\nHow do we build that? Well that's easy. We know how to build clouds. We build them out of\n\npairs. So here's a little representation that supports typed data. There's a thing called take\na type and attach it to a piece of contents, and we just use cons. And if we have a piec e of\n\ntyped data, we can look at the type, which is the car. We can look at the contents, which is\n\nthe cdr. Now along with that, the way we use our type data will test, when we're given a\npiece of data, what type it is. So we have some type predicates with us.\n\n\n\n\nFor example, to see whether a complex number is one of George's, whether it's rectangular,\n\nwe just check to see if the type of that is the symbol rectangular, right? The symbol\n\nrectangular. And to check whether a complex number is one of Martha's, wecheck to see\nwhether the type is the symbol polar. So that's a way to test what kind of number we're\n\nlooking at.\n\n\n\n\nNow let's think about how we can use that to build the system. So let's suppose that George\n\nand Martha were off working separately, and each of them had designed their complex\nnumber representation packages. What do they have to do to become part of the system, to\n\nexist compatibly? Well it's really pretty easy. Remember, George had this package. Here's\nGeorge's original package, or half of it. And underlined in red are the changes he has to\n\nmake. So before, when George made a complex number out of an x and y, he just put them\ntogether to make a pair. And the only difference is that now he signs them. He attaches the\n\ntype, which is the symbol rectangular to that pair.\n\n\n\n\nEverything else George does is the same, except that-- see, George and Martha both have\n\nprocedures named real-part and imaginary-part. So to allow them both to exist in the same\nLisp environment, George had changed the names of hi s procedures. So we'll say, this is\nGeorge's real-part procedure. It's the real-part rectangular procedure, the imaginary-part\n\nrectangular procedure. And then here's the rest of George's package. He'd had magnitude\nand angle, just renames them magnitude rectangular and angle rectangular.\n\n\n\n\n\nAnd Martha has to do basically the same thing. Martha previously, when she made a\ncomplex number out of a magnitude and angle, she just cons them. Now she attaches the\n\ntype polar, and she changes the name so her real -part procedure won't conflict in name\nwith George's. It's a real-part-polar, imaginary-part-polar, magnitude polar, and angle\n\npolar.\n\n\n\n\nNow we have the system. Right there's George and Martha. And now we've got to get some\n\nkind of manager to look at these types. How are these things actually going to work now\nthat George and Martha have supplied us with typed data? Well what we have are a bunch\n\nof generic selectors. Generic selectors for complex numbers real-part, imaginary-part,\nmagnitude, and angle. Let's look at them more closely.\n\n\n\n\n\nWhat does a real-part do? If I ask for the real part of a complex number, well I look at it. I\nlook at its type. I say, is it rectangular? If so, I apply George's real part procedure to the\n\ncontents of that complex number. This is a number that has a type on it. I strip off the type\nusing contents and apply George's procedure.\n\n\n\n\n\nOr is this a polar complex number? If I want the real part, I apply Martha's real part\nprocedure to the contents of that number. So that's how real part works. And then similarly\n\nthere's imaginary-part, which is almost the same. It looks at the number and if it's\nrectangular, uses George's imaginary-part procedure. If it's polar, uses Martha's. And then\n\nthere's a magnitude and an angle.\n\n\n\n\nSo there's a system. Has three parts. There's sort of George, and Martha, and the manager.\n\nAnd that's how you get generic operators implemented. Let's look at just a simple example,\njust to pin it down. But exactly how this is going to work, suppose you're going to be\n\nlooking at the complex number who's real-part is one, and who's imaginary-part is two. So\nthat would be one plus 2i. What would happen is up here, up here above where the\n\noperations have to happen, that number would be represented as a pair of 1 and 2 together\nwith typed data. That would be the contents. And the whole data would be that thing with\n\nthe symbol rectangular added onto that. And that's the way that complex number would\n\nexist in the system.\nWhen you went to take the real-part, the manager would look at this and say, oh it's one of\n\nGeorge's. He'll strip off the type and hand down to George the pair 1, 2. And that's the kind\nof data that George developed his system to use. So it gets stripped down. Later on, if you\n\nask George to construct a complex number, George would construct some complex number\nas a pair, and before he passes it back up through the manager would attach the type\n\nrectangular.\n\n\n\n\nSo you see what happens. There's no confusion in this system. It doesn't matter in the least\n\nthat the pair 1, 2 means something completely different in Martha's world. In Martha's world\nthis pair means the complex number whose magnitude is 1 and whose angl e is 2. And\n\nthere's no confusion, because by the time any pair like this gets handed back through the\nmanager to the main system it's going to have the type polar attached. Whereas this one\n\nwould have the type rectangular attached.\n\n\n\n\nOK, let's take a break.\n\n\n\n\n\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n\n\n\nWe just looked at a strategy for implementing generic operators. That strategy has a name:\n\nit's called dispatch type. And the idea is that you break your system into a bunch of pieces.\nThere's George and Martha, who are making representations, and then there's the manager.\n\nLooks at the types on the data and then dispatches them to the right person.\n\n\n\n\nWell what criticisms can we make of that as a system organization? Well first of all the re\n\nwas this little, annoying problem that George and Martha had to change the names of their\nprocedures. George originally had a real-part procedure, and he had to go name it real-part\n\nrectangular so it wouldn't interfere with Martha's real-part procedure, which is now named\nreal-part-polar, so it wouldn't interfere with the manager's real-part procedure, who's now\n\nnamed real-part. That's kind of an annoying problem. But I'm not going to talk about that\none now. We'll see later on when we think about the st ructure of Lisp names and\n\nenvironments that there really are ways to package all those so-called name spaces\nseparately so they don't interfere with each other. Not going to think about that problem\n\nnow.\n\n\n\n\nThe problem that I actually want to focus on is what happens when you bring somebody\n\nnew into the system. What has to happen? Well George and Martha don't care. George is\nsitting there in his rectangular world, has his procedures and his types. Martha sits in her\n\npolar world. She doesn't care.\n\n\n\n\nBut let's look at the manager. What's the manager have to do? The manager comes through\n\nand had these operations. There was a test for rectangular and a test for polar. If Harry\ncomes in with some new kind of complex number, and Harry has a new type, Harry type\n\ncomplex number, the manager has to go in and change all those procedures. So the\ninflexibility in the system, the place where work has to happen to accommodate change, is\n\nin the manager. That's pretty annoying.\n\n\n\n\nIt's even more annoying when you realize the manager's not doing anything. The manager\n\nis just being a paper pusher. Let's look again at these programs. What are they doing? What\ndoes real-part do? Real-part says, oh, is it the kind of complex number that George can\n\nhandle? If so, send it off to George. Is it the kind of complex number that Martha can\nhandle? If so, send it off to Martha. So it's really annoying that the bottleneck in this\n\nsystem, the thing that's preventing flexibility and change, is completely in the bureaucracy.\nIt's not in anybody who's doing any of the work. Not an uncommon situation, unfortunately.\n\n\n\n\n\nSee, what's really going on -- abstractly in the system, there's a table. So what's really\nhappening is somewhere there's a table. There're types. There's polar and rectangular. And\n\nHarry's may be over here. And there are operators. There's an operator like real-part. Or\nimaginary-part. Or a magnitude and angle. And sitting in this table are the right procedures.\n\nSo sitting here for the type polar and real-part is Martha's procedure real-part-polar. And\n\nover here in the table is George's procedure real-part-rectangular. And over here would be,\nsay, Martha's procedure magnitude-polar, and George's procedure magnitude-rectangular,\n\nright, and so on. The rest of this table's filled in. And that's really what's going on.\n\n\n\n\nSo in some sense, all the manager is doing is acting as this table. Well how do we fix our\n\nsystem? How do you fix bureaucracies a lot of the time? What you do is you get rid of the\nmanager. We just take the manager and replace him by a computer. We're going to\n\nautomate him out of existence. Namely, instead of having the manager who basically\nconsults this table, we'll have our system use the table directly.\n\n\n\n\nWhat do I mean by that? Let's assume, again using data abstraction, that we have some\n\nkind of data structure that's a table. And we have ways of sticking things in and ways of\n\ngetting things out. And to be explicit, let me assume that there's an operation called \"put.\"\nAnd put is going to take, in this case two things I'll call \"keys.\" Key1 and key2. And a value.\n\nAnd that stores the value in the table under key1 and key2. And then we'll assume there's a\nthing called \"get,\" such that if later on I say, get me what's in the table stored under key1\nand key2, it'll retrieve whatever value was stored there. And let's not worry about how\n\ntables are implemented. That's yet another data abstraction, George's problem. And maybe\nwe'll see later-- talk about how you might actually build tables in Lisp.\n\n\n\n\n\nWell given this organization, what did George and Martha have to do? Well when they build\ntheir system, they each have the responsibility to set up their appropriate column in the\n\ntable. So what George does, for example, when he defines his procedures, all he has to do\nis go off and put into the table under the type-rectangular. And the name of the operation is\n\nreal-part, his procedure real-part-rectangular.\n\n\n\n\nSo notice what's going into this table. The two keys here are symbols, rectangular and rea-      l\n\npart. That's the quote. And what's going into the table is the actual procedure that he\nwrote, real-part rectangular. And then puts an imaginary part into the table, filed under the\n\nkeys rectangular- and imaginary-part, and magnitude under the keys rectangular\nmagnitude, angle under rectangular-angle. So that's what George has to do to be part of\n\nthis system.\n\n\n\n\nMartha similarly sets up the column and the table under polar. Polar and real-part. Is the\n\nprocedure real-part-polar? And imaginary-part, and magnitude, and angle. So this is what\nMartha has to do to be part of the system. Everyone who makes a representation has the\n\nresponsibility for setting up a column in the table.\n\n\n\n\nAnd what does Harry do when Harry comes in with his brilliant idea for implementing\n\ncomplex numbers? Well he makes whatever procedure he wants and builds a new column in\nthis table.\n\n\n\n\n\nOK, well what happened to the manager? The manager has been automated ou t of\nexistence and is replaced by a procedure called operate. And this is the key procedure in the\n\nwhole system. Let's say define operate. Operate is going to take an operation that you want\nto do, the name of an operation, and an object that you would like to apply that operation\n\nto. So for example, the real-part of some particular complex number, what does it do?\n\n\n\n\nWell the first thing it does, it looks in the table. Goes into the table and tries to find a\n\nprocedure that's stored in the table. So it gets from the table, using as keys the type of the\nobject and the operator, but looks on the table and sees what's stored under the type of the\n\nobject and the operator, sees if anything's stored. Let's assume that get is implemented. So\nif nothing is stored there, it'll return the empty list. So it says, if there's actually something\nstored there, if the procedure here is not no, then it'll take the procedure that it found in the\n\ntable and apply it to the contents of the object. And otherwise if there was nothing stored\nthere, it'll-- well we can decide. In this case let's have it put out an error message saying,\n\nundefined operator. No operator for this type. Or some appropriate error message.\n\n\n\n\nOK? And that replaces the manager. How do we really use it? Well what we say is we'll go\n\noff and define our generic selectors using operate. We'll say that the real-part of an object is\nfound by operating on the object with the name of the operation being real -part. And then\n\nsimilarly, imaginary -part is operate using the name imaginary-part and magnitude and\nangle. That's our implementation. That plus the tape plus the operate procedure. And the\n\ntable effectively replaces what the manager used to do.\n\n\n\n\nLet's just go through that slowly to show you what's going on. Suppose I have one of\n\nMartha's complex numbers. It's got magnitude 1 and angle 2. And it's one of Martha's. So\nit's labeled here, polar. Let's call that z. Suppose that's z. And suppose with this\n\nimplementation someone comes up and asks for the real-part of z. Well real-part now is\ndefined in terms of operate. So that's equivalent to saying operate with the name of the\n\noperator being real-part, the symbol real-part on z. And now operate comes. It's going to\n\nlook in the table, and it's going to try and find something stored under-- the operation is\ngoing to apply by looking in the table under the type of the object. And the type of z is\n\npolar. So it's going to look and say, can I get using polar? And the operation name, which\nwas real-part. It's going to look in there and apply that to the contents of z. And that? If\n\neverything was set up correctly, this thing is the procedure that Martha put there. This is\nreal-part-polar. And this is z without its type. The thing that Martha originally designed\n\nthose procedures to work on, which is 1, 2.\n\n\n\n\nAnd so operate sort of does uniformly what the manager used to do sort of all over the\n\nsystem. It finds the right thing, looks in the table, strips off the type, and passes it down\ninto the person who handles it.\n\n\n\n\n\nThis is another, and, you can see, more flexible for most purposes, way of implementing\ngeneric operators. And it's called data-directed programming. And the idea of that is in\n\nsome sense the data objects themselves, those little complex numbers that are floating\naround the system, are carrying with them the information about how you should operate\n\non them.\n\n\n\n\nLet's break for questions. Yes.\nAUDIENCE: What do you have stored in that data object? You have the data itself, you have\n\nits type, and you have the operations for that type? Or where are the operations that you\nfound?\n\n\n\n\n\nPROFESSOR: OK, let me-- yeah, that's a good question. Because it raises other possibilities\nof how you might do it. And of course there are a lot of possibilities. In this particular\n\nimplementation, w hat's sitting in this data object, for example, is the data itself-- which in\nthis case is a pair of 1 and 2-- and also a symbol. This is the symbol, the word P-O-L-A-R,\n\nand that's what's sitting in this data object.\n\n\n\n\nWhere are the operations themselves? The operations are sitting in the table. So in this\n\ntable, the rows and columns of the table are labeled by symbols. So when I store something\nin this table, the key might be the symbol polar and the symbol magnitude. And I think by\n\nwriting it this way I'v e been very confusing. Because what's really sitting here isn't-- when I\nwrote magnitude polar, what I mean is the procedure magnitude polar. And probably what I\n\nreally should have written-- except it's too small for me to write in this little space-- is\nsomething like lambda of z, the thing that Martha wrote to implement. And then you can\n\nsee from that, there's another way that I alluded to of solving this name conflict problem,\n\nwhich is that George and Martha never have to name their procedures at all. They can just\nstick the anonymous things generated by lambda directly into the table.\n\n\n\n\nThere's also another thing that your question raises, is the possibility that maybe what I\n\nwould like somehow is to store in this data object not the symbol P-O-L-A-R but maybe\n\nactually all the operations themselves. And that's another way to organize the system,\ncalled message passing. So there are a lot of ways you can do it.\n\n\n\n\nAUDIENCE: Therefore if Martha and George had used the same procedure names, it would\n\nbe OK because it wouldn't look [UNINTELLIGIBLE].\n\n\n\n\nPROFESSOR: That's right. That's right. See, they wouldn't even have to name their\n\nprocedures at all. What George could have written instead of saying put in the table under\nrectangular- and real-part, the procedure real-part rectangular, George could have written\n\nput under rectangular real-part, lambda of z, such and such, and such and such. And the\nsystem would work completely the same.\nAUDIENCE: My question is, Martha could have put key1 key2 real-part, and George could\n\nhave put key1 key2 real-part, and as long as they defined them differently they wouldn't\nhave had any conflicts, right?\n\n\n\n\n\nPROFESSOR: Yes, that would all be OK except for the fact that if you imagine George and\nMartha typing at the same console with the same meanings for all their names, and it would\n\nget confused by real-part, but there are ways to arrange that, too. And in principle you're\nabsolutely right. If their names didn't conflict-- it's the objects that go in the table, not the\n\nnames.\n\n\n\n\nOK, let's take a break.\n\n\n\n\n[MUSIC-- \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n\n\n\n\nAll right, well we just looked at data-directed programming as a way of implementing a\nsystem that does arithmetic on complex numbers. So I had these operations in it called plus\n\nC and minus C, and multiply, and divide, and maybe some others. And that sat on top of --\nand this is the key point-- sat on top of two different representations. A rectangular package\n\nhere, and a polar package. And maybe some more. And we saw that the whole idea is that\n\nmaybe some more are now very easy to add.\n\n\n\n\nBut that doesn't really show the power of this methodology. Shows you what's going on.\nThe power of the methodology only becomes apparent when you start embedding this in\n\nsome more complex system. What I'm going to do now is embed this in some more\n\ncomplex system. Let's assume that what we really have is a general kind of arithmetic\nsystem. So called generic arithmetic system. And at the top level here, somebody can say\n\nadd two things, or subtract two things, or multiply two things, or divide two things. And\nunderneath that there's an abstraction barrier. And underneath this barrier, is, say, a\n\ncomplex arithmetic package. And you can say, add two complex numbers.\n\n\n\n\nOr you might also have-- remember we did a rational number package-- you might have\n\nthat sitting there. And there might be a rational thing. And the rational number package,\nwell, has the things we implemented. Plus rat, and times rat, and so on. Or you might have\n\nordinary Lisp numbers. You might say add three and four. So we might have ordinary\nnumbers, in which case we have the Lisp supplied plus, and minus, and times, and slash.\nOK, so we might imagine this complex number system sitting in a more complicated generic\n\noperator structure at the next level up. Well how can we make that? We already have the\nidea, we're just going to do it again. We've implemented a rational number package. Let's\n\nlook at how it has to be changed.\n\n\n\n\nIn fact, at this level it doesn't have to be changed at all. This is exactly the code that we\n\nwrote last time. To add two rational numbers, remember there was this formula. You make\na rational number whose numerator-- the numerator of the first times the denominator of\n\nthe second, plus the denominator of the first times the numerator of the second. And who's\ndenominator is the product of the denominators. And minus rat, and star rat, and slash rat.\n\nAnd this is exactly the rational number package that we made before. We're ignoring the\nGCD problem, but let's not worry about that.\n\n\n\n\n\nAs implementers of this rational number package, how do we install it in the generic\narithmetic system? Well that's easy. There's only one thing we haveto do differently.\n\nWhereas previously we said that to make a rational number you built a pair of the\nnumerator and denominator, here we'll not only build the pair, but we'll sign it. We'll attach\n\nthe type rational. That's the only thing we have to do different, make it a typed data object.\n\n\n\n\nAnd now we'll stick our operations in the table. We'll put under the symbol rational and the\n\noperation add our procedure, plus rat. And, again, note this is a symbol. Right? Quote,\nunquote, but the actual thing we're putting in the table is the procedure. And for how to\n\nsubtract, well you subtract rationals with minus rat. And multiply, and divide. And that is\n\nexactly and precisely what we have to do to fit inside this generic arithmetic system.\n\n\n\n\nWell how does the whole thing work? See, what we want to do is have some generic\noperators. Have add and sub and [UNINTELLIGIBLE] be generic operators. So we're going\n\nto define add and say, to add x and y, that will be operate-- we were going to call it\n\noperate-2. This is our operator procedure, but set up for two arguments using add on x and\ny. And so this is the analog to operate.\n\n\n\n\nLet's look at the code for second. It's almost like operate. To operate with some operator on\n\nan argument 1 and an argument 2, well the first thin g we're going to do is check and see if\nthe two arguments have the same type. So we'll say, is the type of the first argument the\n\nsame as the type of the second argument? And if they're not, we'll go off and complain, and\n\nsay, that's an error. We don't know how to do that.\nIf they do have the same type, we'll do exactly what we did before. We'll go look and filed\n\nunder the type of the argument-- arg 1 and arg 2 have the same type, so it doesn't matter.\nSo we'll look in the table, find the procedure. If there is a procedure there, then we'll apply\n\nit to the contents of the argument 1 and the contents of arg 2. And otherwise we'll say,\nerror. Undefined operator. And so there's operate-2. And that's all we have to do.\n\n\n\n\n\nWe just built the complex number package before. How do we embed that complex number\npackage in this generic system? Almost the same. We make a procedure called make-\n\ncomplex that takes whatever George and Martha hand to us and add the type-complex. And\nthen we say, to add complex numbers, plus complex, we use our internal procedure, plus c,\n\nand attach a type, make that a complex number.\n\n\n\n\nSo our original package had names plus c and minus c that we're using to communicate\n\nwith George and Martha. And then to communicate with the outside world, we have a thing\ncalled plus-complex and minus-complex. And so on. And the only difference is that these\n\nreturn values that are tight. So they can be looked at up here. And these are internal\noperations.\n\n\n\n\n\nLet's go look at that slide again. There's one more thing we do. After defining plus-complex,\nwe put under the type complex and the symbol add, that procedure plus complex. And then\n\nsimilarly for subtracting complex numbers, and multiplying them, and dividing them.\n\n\n\n\nOK, how do we install ordinary numbers? Exactly the same way. Come off and say, well\n\nwe'll make a thing called make-number. Make-number takes a number and attaches a type,\nwhich is the symbol number. We build a procedure called plus-number, which is simply, add\n\nthe two things using the ordinary addition, because in this case we're talking about ordinary\nnumbers, and attach a type to it and make that a number. And then we put into the table\n\nunder the symbol number and the operation add, this procedure plus-number, and then the\n\nsame thing for subtracting, and multiplying, and dividing.\n\n\n\n\nLet's look at an example, just to make it clear. Suppose, for instance, I'm going to perform\nthe operation. So I sit up here and I'm going to perform the operation, which lookslike\n\nmultiplying two complex numbers. So I would multiply, say, 3 plus 4i and 2 plus 6i. And\nthat's something that I might want to take hand that to mul. I'll write mul as my generic\n\noperator here.\nHow's that going to work? Well 3 plus 4i, say, sits in t he system at this level as something\n\nthat looks like this. Let's say it was one of George's. So it would have a 3 and a 4. And\nattached to that would be George's type, which would say rectangular, it came from\n\nGeorge. And attached to that-- and this itself would be the data view from the next level up,\nwhich it is-- so that itself would be a type-data object which would say complex. So that's\n\nwhat this object would look like up here at the very highest level, where the really super-\ngeneric operations are looking at it.\n\n\n\n\n\nNow what happens, mul eventually's going to come along and say, oh, what's it's type? It's\ntype is complex. Go through to operate-2 and say, oh, what I want to do is apply what's in\n\nthe table, which is going to be the procedure star complex,on this thing with the type\nstripped off. So it's going to strip off the type, take that much, and send that down into the\n\ncomplex world.\n\n\n\n\nThe complex world looks at its operations and says, oh, I have to apply star c. Star c might\n\nsay, oh, at some point I want to look at the magnitude of this object that it's in, that it's\ngot. And they'll say, oh, it's rectangular, it's one of George's. So it'll then strip off the next\n\nversion of type, and hand that down to George to take the magnitude of.\n\n\n\n\nSo you see what's going on is that there are these chains of types. And the length of the\n\nchain is sort of the number of levels that you're going to be going up in this table. And what\na type tells you, every time you have a vertical barrier in this table, where there's some\n\nambiguity about where you should go down to the next level, the type is telling you where\n\nto go. And then everybody at the bottom, as they construct data and filter it up, they stick\ntheir type back on. So that's the general structure of the system.\n\n\n\n\nOK. Now that we've got this, let's go and make this thing even more complex. Let's talk\n\nabout adding to the system not only these kinds of numbers, but it's also meaningful to\n\nstart talking about adding polynomials. Might do arithmetic on polynomials. Like we could\nhave x to the fifteenth plus 2x to the seventh plus 5. That might be some polynomial. And if\n\nwe have two such gadgets we can add them or multiply them. Let's not worry about\ndividing them. Just add them, multiply them, then we'll subtract them.\n\n\n\n\n\n\nWhat do we have to do? Well let's think about how we might represent a polynomial. It's\n\ngoing to be some typed data object. So let's say a polynomial to this system might look like\na thing that starts with the type polynomial. And then maybe it says the next thing is what\n\nvariable its in. So I might say I'm a polynomial in the variable x. And then it'll have some\ninformation about what the terms are.\nAnd there're just tons of ways to do this, but one way is to say we're going to have a thing\ncalled a term-list. And a term-list-- well, in our case we'll use something that looks like this.\n\nWe'll make it a bunch of pairs which have an order in a coefficient. So this polynomial would\nbe represented by this term-list. And what that means is that this polynomial starts off with\n\na term of order 15 and coefficient 1. And the next thing in it is a term of order 7 and\n\ncoefficient 2, a term of order 0, which is constant in coefficient 5.\n\n\n\n\nAnd there are lots and lots of ways, and lots and lots of trade-offs when you really think\nabout making algebraic manipulation packages about exactly how you should represent\n\nthese things. But this is a fairly standard one. It's useful in a lot of contexts.\n\n\n\n\nOK, well how do we implement our polynomial arithmetic? Let's start       out. What we'll do to\n\nmake a polynomial-- we'll first have a way to make polynomials. We're going to make a\npolynomial out of variable like x and term -list. And all that does is we'll package them\n\ntogether someway. We'll put the variable together with the term list using cons, and then\n\nattached to that the type polynomial.\n\n\n\n\nOK, how do we add two polynomials? To add a polynomial, p1 and p2, and then just for\nsimplicity let's say we will only add things in the same variable. So if they have the same\n\nvariable, and same variable here is going to be some selector we write, whose details we\n\ndon't care about. If the two polynomials have the same variable, then we'll do something. If\nthey don't have the same variable, we'll give an error, polynomials not in the same variable.\n\n\n\n\nAnd if they do have the same variable, what we'll do is we'll make a polynomial whose\n\nvariable is whatever that variable is, and whose term-list is something we'll call sum -terms.\n\nPlus terms will add the two term lists. So we'll add the two term lists to the polynomial.\nThat'll give us a term-list. We'll add on, we'll say it's a polynomial in the variable with that\n\nterm-list. That's plus poly. And then we're going to put in our table under the type\npolynomial, add them using plus poly. And of course we really haven't done much. What\n\nwe've really done is pushed all the work onto this thing, plus-terms, which is supposed to\nadd term-lists.\n\n\n\n\n\nLet's look at that. Here's an overview of how we might add two term-lists. So L1 and L2\nwere going to be two term-lists. And a term-list is a bunch of pairs, coefficient in orde r. And\n\nit's a big case analysis. And the first thing we'll check for and see if there are any terms.\nWe're going to recursively work down these term -lists, so eventually we'll get to a place\nwhere either L1 or L2 might be empty. And if either one is empty,our answer will be the\n\nother one. So if L1 is empty we'll return L2, and if L2 is empty we'll return L1.\n\n\n\n\nOtherwise there are sort of three interesting cases. What we're going to do is grab the first\n\nterm in each of those lists, called t1 and t2. And we're going to look at three cases,\ndepending on whether the order of t1 is greater than the order of t2, or less than t2, or the\n\nsame. Those are the three cases we're going to look at.\n\n\n\n\nLet's look at this case. If the order of t1 is greater than the order of t2, then what that\n\nmeans is that our answer is going to start with this term of the order of t1. Because it won't\ncombine with any lower order terms. So what we do is add the lower order terms. We\n\nrecursively add together all the terms in the rest of theterm-list in L1 and L2. That's going\nto be the lower order terms of the answer. And then we're going to adjoin to that the\n\nhighest order term.\n\n\n\n\nAnd I'm using here a whole bunch of procedures I haven't defined, like a adjoin- term, and\n\nrest-terms, and selectors that get order. But you can imagine what those are. So if the first\nterm-list has a higher order than the second, we recursively add all the lower terms and\n\nthen stick on that last term. The other case, the same way. If the first term has a smaller\norder, well then we add the first term-list and the rest of the terms in the second one, and\n\nadjoin on this highest order term.\n\n\n\n\nSo so far nothing's much happened, we've just sort of pushed this thing off into adding\n\nlower order terms. The last case where you actually get to a coefficients that you have to\nadd, this will be the case where the orders are equal. What we do is, well again recursively\n\nadd the lower order terms. But now we have to really combine something. What we do is\nwe make a term whose order is the order of the term we're looking at. By now t1 and t2\n\nhave the same order. That's its order. And its coefficient is gotten by adding the coefficient\n\nof t1 and the coefficient of t2.\n\n\n\n\nThis is a big recursive working down of terms, but really there's only one interesting symbol\nin this procedure, only one interesting idea. The interesting idea is this add. And the reason\n\nthat's interesting is because something completely wonderful just happened. We reduced\nadding polynomials, not to sort of plus, but to the generic add. In other words, by\n\nimplementing it that way, not only do we have our system where we can have rational\n\nnumbers, or complex numbers, or ordinary numbers, we've just added on polynomials. But\nthe coefficients of the polynomials can be anything that the system can add. So these could\n\nbe polynomials whose coefficients are rational numbers or complex numbers, which in turn\ncould be either rectangular, or polar, or ordinary numbers.\nSo what I mean precisely is our system right now automatically can handle things like\nadding together polynomials that have this one: 2/3 of x squared plus 5/17 x plus 11/4. Or\n\nautomatically handle polynomials that look like 3 plus 2i times x to the fifth plus 4 plus 7i,\nor something. You can automatically handle those things. Why is that? That's merely\n\nbecause, or profoundly because we reduced adding polynomials to adding their coefficients.\n\nAnd adding coefficients was done by the generic add operator, which said, I don't care what\nyour types are as long as I know how to add you. So automatically for free we get the\n\nability to handle that.\n\n\n\n\nWhat's even better than that, because remember one of the things we did is we put into the\n\ntable that the way you add polynomials is using plus poly. That means that polynomia ls\nthemselves are things that can be added. So for instance let me write one here. Here's a\n\npolynomial. So this gadget here I'm writing up, this is a polynomial in y whose coefficients\nare polynomials in x. So you see, simply by saying, polynomials are the mselves things that\n\ncan be added, we can go off and say, well not only can we deal with rationals, or complex,\nor ordinary numbers, but we can deal with polynomials whose coefficients are rationals, or\n\ncomplex, or ordinary numbers, or polynomials whose coefficients are rationals, or complex,\nrectangular, polar, or ordinary numbers, or polynomials whose coefficients are rationals,\n\ncomplex, or ordinary numbers. And so on, and so on, and so on.\n\n\n\n\nSo this is sort of an infinite or maybe a recursive tower of types that we've built up. And it's\n\nall exactly from that one little symbol. A -D-D. Writing \"add\" instead of \"plus\" in the\npolynomial thing.\n\n\n\n\n\nSlightly different way to think about it is that polynomials are a constructor for types.\nNamely you give it a type, like integer, and it returns for you polynomials in x whose\n\ncoefficients are integers. And the important thing about that is that the operations on\npolynomials reduce to the operations on the coefficients. And there are a lot of things like\n\nthat.\n\n\n\n\nSo for example, let's go back and rational numbers. We thought about rational numbers as\n\nan integer over an integer, but there's the general notion of a rational object. Like we might\nthink about 3x plus 7 over x squared plus 1. That's general rational object wh ose numerator\n\nand denominator are polynomials. And to add two of them we use the same formula,\nnumerator times denominator plus denominator times numerator over product of\n\ndenominators.\nHow could we install that in our system? Well here's our original rational number arithmetic\n\npackage. And all we have to do in order to make the entire system continue working with\ngeneral rational objects, is replace these particular pluses and stars by the generic operator.\n\nSo if we simply change that procedure to this one, here we've changed plus and star to add\na mul, those are absolutely the only change, then suddenly our entire system can start\n\ntalking about objects that look like this.\n\n\n\n\nSo for example, here is a rational object whose numerator is a polynomial in x whose\n\ncoefficients are rational numbers. Or here is a rational object whose numerator is\npolynomials in x whose coefficients are rational objects constructed out of complex\n\nnumbers. And then there are a lot of other things like that.\n\n\n\n\nSee, whenever you have a thing where the operations reduce to operations on the pieces,\n\nanother example would be two by two matrices. I have the idea, there might be a matrix\nhere of general things that I don't care about. But if I add two of them, the answer over\n\nhere is gotten by adding this one and that one, however they like to add. So I can\nimplement that the same way. And if I do that, then again suddenly my system can start\n\nhandling things like this. So here's a matrix whose elements happen to be-- we'll say this\n\nelement here is a rational object whose numerator and denominators are polynomials. And\nall that comes for free.\n\n\n\n\nWhat's really going on here? What's really going on is getting rid of this manager who's\n\nsitting there poking his nose into who everybody's business is. We built a system that has\n\ndecentralized control. So when you come into and no one's poking around saying, gee, are\nyou in the official list of people who can be added? Rather you say, well go off and add\n\nyourself how your parts like to be added. And the result of that is you can get this very,\nvery, very complex hierarchy where a lot of things just get done and rooted to the right\n\nplace automatically.\n\n\n\n\nLet's stop for questions.\n\n\n\n\nAUDIENCE: You say you get this for free. One thing that strikes me is that now you've lost\n\nkind of the cleanness of the break between what's on top and what's underneath. In other\nwords, now you're defining some of the lower-level procedures in terms of things above\n\ntheir own line. Isn't that dangerous? Or, if nothing more, a little less structured?\nPROFESSOR: No, I-- the question is whether that's less structured. Depends on what you\n\nmean by structure. All this is doing is recursion. See, it's saying that the way you add these\nguys is to use that. And that's not less structured, it's just a recursive structure. So I don't\n\nthink it's particularly any less clean.\n\n\n\n\nAUDIENCE: Now when you want to change the multiplier or the add operator, suddenly\n\nyou've got tremendous consequences underneath that you're not even sure the extent of.\n\n\n\n\nPROFESSOR: That's right, but it depends what you mean. See, this goes both ways. What\n\nwould be a good example? I ignored greatest common divisor, for instance. I ignored that\nproblem just to keep the example simple. But if I suddenly decided that plus rat here should\n\ndo a GCD computation and install that, then that immediately becomes available to all of\nthese, to that guy, and that guy, and that guy, and all the way down.\n\n\n\n\n\nSo it depends what you mean by the coherence of your system. It's certainly true that you\nmight want to have a special different one that didn't filter down through the coefficients,\n\nbut the nice thing about this particular example is that mostly you do.\n\n\n\n\n\n\nAUDIENCE: Isn't that the problem, I think, that you're getting to tied in with the fact that\nthe structuring, the recursiveness of that structuring there is actually in execution as\n\nopposed to just definition of the actual types themselves?\n\n\n\n\nPROFESSOR: I think I understand the question. The point is that these types evolve and get\n\nmore and more complex as the thing's actually running. Is that what --\n\n\n\n\nAUDIENCE: Yes. As it's running.\n\n\n\n\nPROFESSOR: --what you're saying? Yes, the point is--\n\n\n\n\nAUDIENCE: As opposed to the basic definitions.\nPROFESSOR: Right. The type structure is sort of recursive. It's not that you can make this\n\nfinite list of the actual things they might look like before the system runs. It's something\nthat evolves. So if you want to specify that system, you have to do in some other way than\n\nby this finite list. You have to do it by a recursive structure.\n\n\n\n\nAUDIENCE: Because the basic structure of the types is pretty clean and simple.\n\n\n\n\nPROFESSOR: Right. Yes?\n\n\n\n\n\nAUDIENCE: I have a question. I understand once you have your dat a structure set up, how\nit pulls off complex and passes that down, and then pulls off rect, passes that down. But if\n\nyou're just a user and you don't know anything about rect or polar or whatever, how do you\ninitially set up that data structure so that everything goes to the right spot? If I just have\n\nthe equation over there on the left and I just want to add, multiply complex numbers --\n\n\n\n\nPROFESSOR: Well that's the wonderful thing. If you're just a user you say \"mul.\"\n\n\n\n\n\nAUDIENCE: And it figures out that I mean complex numbers? Or how do I tell it that I want-\n-\n\n\n\n\n\nPROFESSOR: Well you're going to have in your hands complex numbers. See what you\nwould have at some level, as a real user, is a constructor for complex numbers.\n\n\n\n\nAUDIENCE: So then I have to make complex numbers?\n\n\n\n\n\nPROFESSOR: So you have to make them. What you would probably have as a user is some\nlittle thing in the reader loop, which would give you some plausible way to type in a complex\n\nnumber, in whatever format you like. Or it might be that you're never typing them in.\nSomeone's just handing you a complex number.\n\n\n\n\n\nAUDIENCE: OK, so if I had a complex number that had a polynomial in it, I'd have to make\nmy polynomial and then make my complex number.\nPROFESSOR: Right if you wanted it constructed from scratch. At some point you construct\nthem from scratch. But what you don't have to know of that is when you have the object\n\nyou can just say \"mul.\" And it'll multiply. Yeah?\n\n\n\n\nAUDIENCE: I think the question that was being posed here is, say if I want to change my\n\npresentation of complexes, or some operation of complex, how much real code I will have to\ngets around with, or change to change it in one specific operation?\n\n\n\n\n\nPROFESSOR: [UNINTELLIGIBLE] what you have to change. And the point is that you only\nhave to change what you're changing. See if Martha decides that she would rather -- let's\n\nsee something silly -- like change the order in the pair. Like angle and magnitude in the\nother order, she just makes that change locally. And the whole thing will propagate through\n\nthe system in the right way. Or if suddenly you said, gee, I have another representation for\nrationals. And I'm going to stick it here, by filing those operations in the table. Then\n\nsuddenly all of these polynomials whose coefficients are co efficients of coefficients, or\n\nwhatever, also can automatically have available that representation. That's the power of\nthis particular one.\n\n\n\n\nAUDIENCE: I'm not sure if I can even pose an intelligent sounding question. But somehow\n\nthis whole thing went really nicely to this beautiful finish where all the things seemed to fall\n\ninto place. Sort of seemed a little contrived. That's all for the sake, I'm sure, of teaching. I\ndoubt that the guys who first did this-- and I could be wrong-- figured it all out so that\n\nwhen they just all put it all together, you could all of the sudden, blam, do any kind of\narithmetic on any kind of object. It seems like maybe they had to play with it for a while\n\nand had to bash it and rework it.\n\n\n\n\nAnd it seems like that's the kind of problem we're really faced with we start trying to design\n\na really complex system, is having lots of different kinds of parts and not even knowing\nwhat kinds of operations we're going to want to do on those parts. How to organize the\n\noperations in this nice way so that no matter what you do, when you start putting them\ntogether everything starts falling out for free.\n\n\n\n\n\nPROFESSOR: OK, well that's certainly a very intelligent question. One part is this is a very\ngood methodology that people have discovered a lot coming from symbolic algebra.\n\nBecause there are a lot of complications. To allow you to implement these things before you\ndecide what you want all the operations to be, and all of that. So in some sense it's an\nanswer that people have discovered by wading through this stuff. In another sense, it is a\n\nvery contrived example.\n\n\n\n\nAUDIENCE: It seems like to be able to do this you do have to wade through it for a certain\n\namount of time before you can become good at it.\n\n\n\n\nPROFESSOR: Let me show you how terribly contrived this is. So you can write all these\nwonderful things. But the system that I wrote here, and if we had another half an hour to\n\ngive this lecture I would have given this part of it, which says, notice that it breaks down if I\n\ntell it to do something as foolish as add 3 plus 7/2. Because what will happen is you'll get to\noperate-2, and operate-2 will say, oh this is type number, and that's type rational. I don't\n\nknow how to add them.\n\n\n\n\nSo you'd like the system at least to be able to say something like, gee, before you do that\n\nchange that to 3/1. Turn it into a rational number, hand that to the rational package. That's\nthe thing I didn't talk about in this lecture. It's a little bit in the book, which talks about the\n\nproblem of what's called coercion. Where you wanted-- see, having so carefully set up all of\nthese types as distinct objects, a lot of times you want to also put in knowledge about how\n\nto view an ordinary number as a kind of rational. Or view an ordinary number as a kind of\ncomplex. That's where the complexity in the system really starts happening, where you talk\n\nabout, see where do I put that knowledge? Is it rational to know that ordinary numbers\nmight be pieces of [UNINTELLIGIBLE] of them?\n\n\n\n\n\nOr they're terrible, terrible examples, like if I might want to add a complex number to a\nrational number. Bad example. 5/7. Then somebody's got to know that I have to convert\n\nthese to another type, which is complex numbers whose parts might be rationals. And who\nworries about that? Does complex worry about that? Does rational worry about that? Does\n\nplus worry about that?\n\n\n\n\nThat's where the real complexity comes in. And that's where it's pretty well sorted out. And\n\na lot of, in fact, all of this message passing stuff was motivated by problems like this. And\nwhen you really push it, people are-- somehow the algebraic manipulation problem seems\n\nto be so complex that the people who are always at the edge of it are exactly in the state\nyou said. They're wading through this thing, mucking around, seeing what they use, trying\n\nto distill stuff.\nAUDIENCE: I just want to come back to this issue of complexity once more. It certainly\n\nseems to be true that you have a great deal of flexibility in altering the lower level kindsof\nthings. But it is true that you are, in a sense, freezing higher level operations. Or at least if\n\nyou change them you don't know where all of the changes are going to show up, or how\nthey are.\n\n\n\n\n\nPROFESSOR: OK, that's an extremely good question. What I have to do is, if I decide\nthere's a new general operation called equality test, then all of these people have to decide\n\nwhether or not they would like to have an equality test by looking in the table. There're\nways to decentralize it even more. That's what I sort of hinted at last time, where I said you\n\ncould not only have this type as a symbol, but you actually might store in each object the\noperations that it knows of that.\n\n\n\n\n\nSo you might have things like greatest common divisor, which is a thing here whi ch is\ndefined only for integers, and not in general for rational numbers. So it might be a very,\n\nvery fragmented system. And then depending on where you want your flexibility, there's a\nwhole spectrum of places that you can build that in. But you're pointing at the place where\n\nthis starts being weak, that there has to be some agreement on top here about these\n\ngeneral operations. Or at least people have to think about them. Or you might decide, you\nmight have a table that's very sparse, that only has a few things in it. But there are lot of\n\nways to play that game. OK, thank you.\n\n\n\n\n[MUSIC: \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec5a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 5A: Assignment, State, and Side-effects\n\n\n\n[MUSIC PLAYING] PROFESSOR: Well, so far we've invented enough programming to do\nsome very complicated things. And you surely learned a lot about programming at this\n\npoint. You've learned almost all the most important tricks that usually don't get taught to\npeople until they have had a lot of experience. For example, data directed programming is a\n\nmajor trick, and yesterday you also saw an interpreted language.\n\n\n\n\nWe did this all in a computer language, at this point, where there was no assignment\n\nstatement. And presumably, for those of you who've seen your Basic or Pascal or whatever,\nthat's usually considered the most important thing. Well today, we're going to do some\n\nthing horrible. We're going to add an assignment statement.\n\n\n\n\nAnd since we can do all these wonderful things without it, why should we add it? An\n\nimportant thing to understand is that today we're going to, first of all, have a rule, which is\ngoing to always be obeyed, which is the only reason we ever add a feature to our language\n\nis because there is a good reason. And the good reason is going to boil down to the ability,\nyou now get an ability to break a problem into pieces that are different sets of pieces then\n\nyou could have broken it down without that, give you another means of decomposition.\n\n\n\n\nHowever, let's just start. Let me quick begin by reviewing the kind of language that we have\n\nnow. We've been writing what's called functional programs. And functional programs are a\nkind of encoding of mathematical truths. For example, when we look at the factorial\n\nprocedure that you see on the slide here, it's basically two clauses. If n is one, the result is\none, otherwise n times factorial n minus one. That's factorial of n. Well, that is factorial of n.\n\n\n\n\n\nAnd written down in some other obscure notation that you might have learned in calculus\nclasses, mathematical logic, what you see there is if n equals one, for the result of n\n\nfactorial is one, otherwise, greater than one, n factorial is n times n minus one factorial.\n\n\n\n\nTrue statements, that's the kind of language we've been using. And whenever we have true\n\nstatements of that sort, there is a kind of, a way of understanding how they work which is\nthat such processes can be involved by substitution.\nAnd so we see on the second slide here, that the way we understand the execution implied\n\nby those statements in arranged in that order, is that you do successive substitutions of\narguments for formal parameters in the body of a procedure.\n\n\n\n\n\nThis is basically a sequence of equalities. Factorial four is four times factorial three. That is\nfour times three times factorial of two and so on. We're always preserving truth. Even\n\nthough we're talking about true statements, there might be more than one organization of\nthese true statements to describe the computation of a particular function, the computation\n\nof the value of a particular function.\n\n\n\n\nSo, for example, looking at the next one here. Here is a way of looking at the sum of n and\n\nm. And we did this one by a recursive process. It's the increment of the sum of the\ndecrement of n and m. And, of course, there is some piece of mathematical logic here that\n\ndescribes that. It's the increment of the sum of the decrement of n and m, just like that. So\nthere's nothing particularly magic about that.\n\n\n\n\n\nAnd, of course, if we can also look at an iterative process for the same, a program that\nevolves an iterative process, for the same function. These are two things that compute the\n\nsame answer. And we have equivalent mathematical truths that are arranged there. And\njust the way you arrange those truths determine the particular process. In the way choose\n\nand arrange them determines the process that's evolved.\n\n\n\n\nSo we have the flexibility of talking about both the function to be computed, and the\n\nmethod by which it's computed. So it's not clear we need more. However, today I'm going\nto this awful thing. I'm going to introduce this assignment operation.\n\n\n\n\n\nNow, what is this? Well, first of all, there is going to be another kind of kind of statement, if\nyou will, in a programming language called Set! Things that do things like assignment, I'm\n\ngoing to put exclamation points after. We'll talk about what that means in a second. The\nexclamation point, again like question mark, is an arbitrary thing we attach to the symbol\n\nwhich is the name, has no significance to the system. The only significance is to me and you\nto alert you that this is an assignment of some sort.\n\n\n\n\n\nBut we're going to set a variable to a value. And what that's going to mean is that there is a\ntime at which something happens. Here's a time. If I have time going this way, it's a time\n\naccess. Time progresses by walking down the page. Then an assignment is the first thing\nwe have that produces the difference between a before and an after.\nAll the other programs that we've written, that have no assignments in them, the order in\nwhich they were evaluated didn't matter. But assignment is special, it produces a moment\n\nin time. So there is a moment before the set occurs and after, such that after this moment\nin time, the variable has the value, value. Independent of what value it had before, set!\n\nchanges the value of the variable.\n\n\n\n\nUntil this moment, we had nothing that changed. So, for example, one of the things we can\n\nthink of is that the procedures we write for something like factorial are in fact pretty much\nidentical to the function factorial. Factorial of four, if I write fact4, independent of what\n\ncontext it's in, and independent of how many times I write it, I always get the same answer.\n\nIt's always 24. It's a unique map from the argument to the answer.\n\n\n\n\nAnd all the programs we've written so far are like that. However, once I have assignment,\nthat isn't true. So, for example, if I were to define count to be one. And then I'm going to\n\ndefine also a procedure, a simple procedure called demo, which takes argument x and does\n\nthe following operations. It first sets x to x plus one. My gosh, this looksjust like FORTRAN,\nright-- in a funny syntax. And then add to x count, Oh, I just made a mistake.\n\n\n\n\nI want to say, set! count to one plus count. It's this thing defined here. And then plus x\n\ncount. Then I can try this procedure. Let's run it. So, suppose I get a prompt and I say,\n\ndemo three.\n\n\n\n\nWell, what happens here? The first thing that happens is count is currently one. Currently,\nthere is a time. We're talking about time. x gets three. At this moment, I say, oh yes, count\n\nis incremented, so count is two. two plus three is five. So the answer I get out is five. Then\n\nI say, demo of say, three again.\n\n\n\n\nWhat do I get? Well, now count is two, it's not one anymore, because I have incremented it.\nBut now I go through this process, three goes into x, count becomes one plus count, so\n\nthat's three now. The sum of those two is six, so the answer is six.\n\n\n\n\nAnd what we see is the same expression leads to two different answers, depending upon\n\ntime. So demo is not a function, does not compute a mathematical function. In fact, you\ncould also see why now, of course, this is the first place where the substitution model isn't\n\ngoing to work. This kills the substitution model dead.\nYou know, with quotation there were some little problems that a philosopher might notice\nwith the substitutions, because you have to worry about what deductions you can make\n\nwhen you substitute into quotes, if you're allowed to do that at all. But here the substitution\nmodel is dead, can't do anything at all.\n\n\n\n\n\nBecause, supposing I wanted to use a substitution model to consider substituting for count?\nWell, my gosh, if I substitute for here and here, they're different ones. It's not the same\n\ncount any more. I get the wrong answer. The substitution model is a static phenomenon\nthat describes things that are true and not things that change. Here, we have truths that\n\nchange.\n\n\n\n\nOK, Well, before I give you any understanding of this, this is very bad. Now, we've lost our\n\nmodel of computation. Pretty soon, I'm going to have to build you a new model of\ncomputation. But ours plays with this, just now, in an informal sense. Of course, what you\n\nalready see is that when I have something like assignment, the model that we're going to\n\nneed is different from the model that we had before in that the variables, thosesymbols like\ncount, or x are no longer going to refer to the values they have, but rather to some sort of\n\nplace where the value restored.\n\n\n\n\nWe're going to have to think that way for a while. And it's going to be a very bad thing and\n\ncause a lot of trouble. And so, as I said, the very fact that we're inventing this bad thing,\nmeans that there had better be a good reason for it, otherwise, just a waste of time and a\n\nlot of effort.\n\n\n\n\nLet's just look at some of it just to play. Supposing we write down the functional version,\n\nfunctional meaning in the old style, of factorial by an iterative process. Factorial of n, we're\ngoing to iterate of m and i, which says if i is greater than n, then the result is m, otherwise,\n\nthe result of iterating the product of i and m. So m is going to be the product that I'm\naccumulating. m is the product. And the count I'm going to increase by one. Plus, ITER,\n\nELSE, COND, define.\n\n\n\n\nI'm going to start this up. And these days, you should have no trouble reading something\n\nlike this. What I have here is a product there being accumulated and a counter. I start them\nup both at one. I'm going to buzz the counter up, i goes to i plus one every time around.\n\nBut that's only our putting a time on the process, each of this is just a set of truths, true\nrules. And m is going to get a new values of i and m, i times m each time around, and\n\neventually i is going to be bigger than n, in which case, the answer's going to be m.\nNow, I'm speaking to you, use time in this. That's just because I know how the computer\nworks. But I didn't have to. This could be a purely mathematical description at this point,\n\nbecause substitution will work for this.\n\n\n\n\nBut let's set right down a similar sort of program, using the same algorithm, but with\n\nassignments. So this is called the functional version. I want to write down an imperative\nversion. Factorial of n. I'm going to create my two variables. Let i initialize itse lf to one, and\n\nm be initialized to one, similar.\n\n\n\n\nWe'll create a loop which has COND greater than i, and if i is greater than n, we're done.\n\nAnd the result is m, the product I'm accumulating. Otherwise, I'm going to write down three\nthings to do. I'm going to set! m to the product of i and m, set! i to the sum of i and one,\n\nand go around the loop again. Looks very familiar to you FORTRAN programmers. ELSE,\nCOND, define, funny syntax though. Start the loop up, and that's the program.\n\n\n\n\n\nNow, this program, how do we think about it? Well, let's just say what we're seeing here.\nThere are two local variables, i and m, that have been initialized to one. Every time around\n\nthe loop, I test to see if i is greater than n, which is the input argument, and if so, the re sult\nis the product being accumulated in m. However, if it's not the end of the loop, if I'm not\n\ndone, then what I'm going to do is change the product to be the result of multiplying i times\n\nthe current product.\n\n\n\n\nWhich is sort of what we were doing here. Except here I wasn't changing. I was making\nanother copy, because the substitution model says, you copy the body of the procedure with\n\nthe arguments substituted for the formal parameters. Here I'm not worried about copying,\n\nhere I've changed the value of m. I also then change the value of i to i plus one, and go\nbuzzing around.\n\n\n\n\nSeems like essentially the same program, but there are some ways of making errors here\n\nthat didn't exist until today. For example, if I were to do the horrible thing of not being\ncareful in writing my program and interchange those two assignments, the program\n\nwouldn't compute the same function.\n\n\n\n\nI get a timing error because there's a dependency that m depends upon having the last\n\nvalue of i. If I try to i first, then I've got the wrong value of i when I multiply by m. It's a\nbug that wasn't available until this moment, until we introduced something that had time in\n\nit.\n\n\n\n\nSo, as I said, first we need a new model of computation, and second, we have to be damn\n\ngood reason for doing this kind of ugly thing. Are there any questions? Speak loudly, David.\n\n\n\n\nAUDIENCE: I'm confused about, we've introduced set now, but we had let before and define\nbefore. I'm confused about the difference between the three. Wouldn't define work in the\n\nsame situation as set if you introduced it a bit?\n\n\n\n\nPROFESSOR: No, define is intended for setting something once the first time, for making it.\n\nYou've never seen me write on a blackboard two defines in a row whose intention was to\nchange the old value of some variable to a new one.\n\n\n\n\n\nAUDIENCE: Is that by convention or--\n\n\n\n\nPROFESSOR: No, it's intention. The answer is that, for example, internal to a procedure, two\n\ndefines in a row are illegal, two defines in a row of the same variable. x can't be defined\ntwice. Whether or not a system catches that error is a different question, but I legislate to\n\nyou that define happens once on anything.\n\n\n\n\nNow, indeed, in interactive debugging, we intend that you interacting with your computer\n\nwill redefine things, and so there's a special exception made for interactive debugging. But\ndefine is intended to mean to set up something which will be forever that value after that\n\npoint. It's as if all the defines were done at the beginning. In fact, the only legal place to put\na define in Scheme, internal to a procedure, is just at the beginning of a lambda expression,\n\nthe beginning of the body of a procedure.\n\n\n\n\nNow, let of course does nothing like either of that. I mean, if you look at what's happening\n\nwith a let, this happens again exactly once. It sets up a context where i and m are values\none and one. That context exists throughout this scope, this region of t he program.\n\nHowever, you don't think of that let as setting i again. It doesn't change it. i never changes\nbecause of the let. i gets created because of let.\nIn fact, the let is a very simple idea. Let does nothing more, Let a variable one to have\n\nvalue one; I'll write this down a little bit more neatly; Let's write, var one have value, the\nvalue of expression e1, and variable two, have this value of the expression e2, in an\n\nexpression e3, is the same thing as a procedure of var one and var two, the formal\nparameters, and e3 being the body, where var one is bound to the value of e1, and var two\n\ngets the value of e2.\n\n\n\n\nSo this is, in fact, a perfectly understandable thing from a substitution point of view. This is\n\nreally the same expression written in two different ways. In fact, the way the actual system\nworks is this gets translated into this before anything happens.\n\n\n\n\n\n\nAUDIENCE: OK, I'm still unclear as then what makes the difference between a let and a\n\ndefine. They could--\n\n\n\n\nPROFESSOR: A define is a syntactic sugar, whereby, essentially a bunch of variables get\n\ncreated by lets and then set up once. OK, time for the first break, I think. Thank you.\n[MUSIC PLAYING]\n\n\n\n\n\nWell let's see. I now have to rebuild the model of computation, so you understand how\nsome such mechanical mechanism could work that can do what we've just talked about. I\n\njust recently destroyed your substitution model. Unfortunately, this model is significantly\nmore complicated than the substitution model.\n\n\n\n\n\nIt's called the environment model. And I'm going to have to introduce some terminology,\nwhich is very good terminology for you to know anyway. It's about names. And we're going\n\nto give names to the kinds of names things have and the way those names are used. So\nthis is a meta-description, if you will. Anyway, there is a pile of an unfortunate terminology\n\nhere, but we're going to need this to understand what's called the environment model.\nWe're about to do a little bit of boring, dog-work here.\n\n\n\n\n\nLet's look at the first transparency. And we see a description of a word called bound. And\nwe're going to say that a variable, v, is bound in an expression, e, if the meaning of e is\n\nunchanged by the uniform replacement of a variable w, not occurring in e, for every\noccurrence of v in e. Now that's a long sentence, so, I think, I'm going to have to say a little\n\nbit about that before we even fool around at all here.\nBound variables we're talking about here. And you've seen lots of them. You may not know\n\nthat you've seen lots of them. Well, I suppose in your logic you saw a logical variables like,\nfor every x there exists a y such that p is true of x and y from your calculus class. This\n\nvariable, x, and this variable, y, are bound, because the meaning of this expression does\nnot depend upon the particular letters I used to describe x and y. If I were to change the w\n\nfor x, then said for every w there exists a y such that p is true of w and y, it would be the\nsame sentence. That's what it means.\n\n\n\n\n\nOr another case of this that you've seen is integral say, from 0 to one of dx over one plus x\nsquare. Well that's something you see all the time. And this x is a bound variable. If I\n\nchange that to a t, the expression is still the same thing. This is a 1/4 of the arctan of one\nor something like that. Yes, that's the arctan of one. So bound variables are actually fairly\n\ncommon, for those of you who have played a bit with mathematics.\n\n\n\n\nWell, let's go into the programming world. Instead of the quantifier being something like, for\n\nevery, or there exists, or integral, a quantifier is a symbol that binds a variable. And we are\ngoing to use the quantifier lambda as being the essential thing that binds variables.\n\n\n\n\n\nAnd so we have some nice examples here like that procedure of one argument y which does\nthe following thin g. It calls the procedure of one argument x, which multiplies x by y, and\n\napplies that to three. That procedure has the property there of two bound variables in it, x\nand y. This quantifier, lambda here, binds this y, and this quantifier, lambda, binds tha t x.\n\nBecause, if I were to take an arbitrary symbol does not occur in this expression like w and\n\nreplace all y's with w's in this expression, the expression is still the same, the same\nprocedure.\n\n\n\n\nAnd this is an important idea. The reason why we had such things like that is a kind of\n\nmodularity. If two people are writing programs, and they work together, it shouldn't matter\n\nwhat names they use internal to their own little machines that they're building. And so,\nwhat I'm really telling you there, is that, for example, this is equivalent to that procedure of\n\none argument y which uses that procedure of one argument d which multiplies z by y.\nBecause nobody cares what I used in here. It's a nice example.\n\n\n\n\nOn the other hand, I have some variables that are not b ound. For example, that procedure\n\nof one argument x which multiplies x by y. In this case, y is not bound. Supposing y had the\n\nvalue three, and z had the value four, then this procedure would be the thing that multiplies\nits argument by three. If I were to replace every instance of y with z, I would have a\n\ndifferent procedure which multiplies every argument that's given by four.\nAnd, in fact, we have a name for such a variable. Here, we say that a variable, v, is free in\nthe expression, e, if the meaning of the expression, e, is changed by the uniform\n\nreplacement of a variable, w, not occurring in e for every occurrence of v and e.\n\n\n\n\nSo that's why this variable over here, y, is a free variable. And so free variables in this\n\nexpression-- And other examples of that is that procedure of one argument y, which is just\nwhat we had before, which uses that procedure of one argument x that multiplies x by y--\n\nuse that on three. This procedure has a free variable in it which is asterisk. See, because, if\nthat has a normal meaning of multiplication, then if I were to replace uniformly all asterisks\n\nwith pluses, then the meaning of this expression would change. That's what you mean by a\n\nfree variable.\n\n\n\n\nSo, so far you've learned some logician words which describe the way names are used.\nNow, we have to do a little bit more playing around here, a little bit more. I want to tell you\n\nabout the regions are over which variables are defined.\n\n\n\n\nYou see, we've been very informal about this up till now, and, of course, many of you have\n\nprobably understood very clearly or most of you, that the x that's being declared here is\ndefined only in here. This x is the defined only in here, and this y is defined only in here. We\n\nhave a name for such an idea. It's called a scope.\n\n\n\n\nAnd let me give you another piece of terminology. It's a long story. If x is a bound variable\n\nin e, then there is a lambda expression where it is bound. So the only way you can get a\nbound variable ultimately is by lambda expression. Then you may worry, does define quite\n\nan exception to this? And it turns out, we could always arrange things so you don't need\n\nany defines. And we'll see that in a while. It's a very magical thing. So define really can go\naway. The really, only thing that makes names is lambda . That's its job. And what's so\n\namazing about a lot of things is you can compute with only lambda.\n\n\n\n\nBut, in any case, a lambda expression has a place where it declares a variable. We call it the\nformal parameter list or the bound variable list. We say that the lambda expression binds --\n\nso it's a verb-- binds the variables declared in it's found variable list. In addition, those\n\nparts of the expression where the variable is defined, which was declared by some\ndeclaration, is called the scope of that variable. So these are scopes. This is the scope of y.\n\nAnd this is the scope of x-- that sort of thing.\nOK, well, now we have enough terminology to begin to understand how to make a new\n\nmodel for computation, because the key thing going on here is that we destroyed the\nsubstitution model, and we now have to have a model that represents the names as\n\nreferring to places. Because if we are going to change something, then we have a place\nwhere it's stored.\n\n\n\n\n\nYou see, if a name only refers to a value, and if I tried to change the name's meaning, well,\nthat's not clear. There's nothing that is the place that that name referred to. How am I\n\nreally saying it? There is nothing shared among all of the instances of that name. And what\nwe really mean, by a name, is that we fan something out. We've given something a name,\n\nand you have it, and you have it, because I'm given you a reference to it, and I've give n\nyou a reference to it. And we'll see a lot about that.\n\n\n\n\n\nSo let me tell you about environments. I need the overhead projection machine, thank you.\nAnd so here is a bunch of environment structures. An environment is a way of doing\n\nsubstitutions virtually. It represents a place where something is stored which is the\nsubstitutions that you haven't done. It's a place where everything accumulates, where the\n\nnames of the variables are associated with the values they have such that when you say,\n\nwhat dose this name mean, you look it up in an environment.\n\n\n\n\nSo an environment is a function, or a table, or something like that. But it's a structured sort\nof table. It's made out of things called frames. Frames are pieces of environment, and they\n\nare chained together, in some nice ways, by what's called parent links or something like\n\nthat.\n\n\n\n\nSo here, we have an environment structure consisting of three environments, basically, a,\nb, and c. d is also an environment, but it's the same one, they share. And that's the essen ce\n\nof assignment. If I change a variable, a value of a valuable that lives here, like that one, it\n\nshould be visible from all places that you're looking at it from. Take this one, x. If I change\nthe x to four, it's visible from other places. But I'm not going to worry about that right now.\n\nWe're going to talk a lot about that in a little while.\n\n\n\n\nWhat do we have here? Well, these are called frames. Here is a frame, here's a frame, and\nhere's a frame. a is an environment which consists of the table which is frame two, followed\n\nby the table labeled frame one. And, in this environment, in say this environment, frame\n\ntwo, x and y are bound. They have values. Sorry, in frame one -- In frame two, z is bound,\nand x is bound, and y is bound, but the value of x that we see, looking from this point of\n\nview, is this x. It's x is seven, rather than this one which is three. We say that this x\nshadows this x. From environment three-- from frame three, from environment b, which\nrefers to frame three, we have variables n and y bound and also x. This y shadow this one.\n\nSo the value, looking from this point of view, of y is two. The value for looking from this\npoint of view and m is one. And the value, looking from this point of view, of x is three.\n\n\n\n\n\nSo there we have a very simple environment structure made out of frames. These\ncorrespond to the applications of procedures. And we'll see that in a second. So now I have\n\nto make you some other nice little structure that we build.\n\n\n\n\nNext slide, we see an object, which I'm going to draw procedures. This is a procedure. A\n\nprocedure is made out of two parts. It's sort of like a cons. However, it's the two parts. The\nfirst part refers to some code, something that can be executed, a set of instructions, if you\n\nwill. You can think of it that way. And the second part is the environment. The procedure is\nthe whole thing. And we're going to have to use this to capture the values of the free\n\nvariables that occur in the procedure. If a variable occurs in the procedure it's either bound\nin that procedure or free. If it's bound, then the value will somehow be easy to find. It will\n\nbe in some easy environment to get at. If it's free, we're going to have to have something\nthat goes with the procedure that says where we'll go look for its value. And the reasons\n\nwhy are not obvious yet, but will be soon.\n\n\n\n\nSo here's a procedure object. It's a composite object consisting of a piece of code and a\n\nenvironment structure. Now I will tell you the new rules, the complete new rules, for\nevaluation. The first rule is-- there's only two of them. These correspond to the substitution\n\nmodel rules. And the first one has to do with how do you apply a procedure to its\n\narguments? And a procedural object is applied to a set of arguments by constructing a new\nframe. That frame will contain the mapping of the former parameters to the actual\n\nparameters of the arguments that were supplied in the call.\n\n\n\n\nAs you know, when we make up a call to a procedure like lambda x times x y, and we call\n\nthat with the argument three, then we're going to need some mapping of x to three. It's the\nsame thing as later substituting, if you will, the three for the x in the old model. So I'm\n\ngoing to build a frame which contains x equals three as the information in that frame.\n\n\n\n\nNow, the body of the procedure will then have to be evaluated which is this. I will be\nevaluated in an environment which is constructed by adjoining the new frame that we just\n\nmade to the environment which was part of the procedure that we applied.\nSo I'm going to make a little example of that here. Supposing I have some environ ment.\n\nHere's a frame which represents it. And some procedure-- which I'm going to draw with\ncircles here because it's easier than little triangles-- Sorry, those are rhombuses,\n\nrhomboidal little pieces of fruit jelly or something.\n\n\n\n\nSo here's a procedure which takes this environment. And the procedure has a piece of code,\n\nwhich is a lambda expression, which binds x and y and then executes an expression, e. And\nthis is the procedure. We'll call it p. I wish to apply that procedure to three and four. So I\n\nwant to do p of three and four.\n\n\n\n\nWhat I'm going to do, of course, is make a new frame. I build a frame which contains x\n\nequals three, and y equals four. I'm going to connect that frame to this frame over here.\nAnd then this environment, with I will call b, is the environment in which I will evaluate the\n\nbody of e. Now, e may contain references to x and y and other things. x and y will have\nvalues right here. Other things will have their values here.\n\n\n\n\n\nHow do we get this frame? That we do by the construction of procedures which is the other\nrule. And I think that's the next slide. Rule two, when a lambda expression is evaluated,\n\nrelative to a particular environment-- See, the way I get a procedure is by evaluating the\nlambda expression.\n\n\n\n\n\nHere's a lambda expression. By evaluating it, I get a procedure which I can apply to three.\nNow this lambda expression is evaluated in an environment where y is defined. And I want\n\nthe body of this which contains a free version of y. y is free in here, it's bound over the\nwhole thing, but it's free over here. I want that y to be this one. I evaluate this body of this\n\nprocedure in the environment where y was created. That's this kind of thing, because that\nwas done by application.\n\n\n\n\n\nNow, if I ever want to look up the value of y, I have to know where it is. Therefore, this\nprocedural was created, the creation of the procedure which is the result of evaluating that\n\nlambda expression had better capture a pointer or remember the frame in which y was\nbound. So that's what this rule is telling us.\n\n\n\n\n\nSo, for example, if I happen to be evaluating a lambda expression, lambda expression in e,\nlambda of say, x and y, let's call it g in e, evaluating that. Well, all that means is I now\n\nconstruct a procedure object. e is some environment. e issomething which has a pointer to\nit. I construct a procedure object that points up to that environment, where the code of that\n\nis a lambda expression or whatever that translates into. And this is the procedure.\n\n\n\n\nSo this produces for me-- this object here, this environment pointer, captures the place\n\nwhere this lambda expression was evaluated, where the definition was used, where the\ndefinition was used to make a procedure, to make the procedure. So it picks up the\n\nenvironment from the place where that procedure was defined, stores it in the procedure\nitself, and then when the procedure is used, the environment where it was defined is\n\nextended with the new frame.\n\n\n\n\nSo this gives us a locus for putting where a variable has a value. And, for example, if there\n\nare lots of guys pointing in at that environment, then they share that place. And we'll see\nmore of that shortly.\n\n\n\n\n\nWell, now you have a new model for understanding the execution of programs. I suppose I'll\ntake questions now, and then we'll go on and use that for something.\n\n\n\n\nAUDIENCE: Is it right to say then, the environment is that linked chain of frames --\n\n\n\n\n\nPROFESSOR: That's right.\n\n\n\n\nAUDIENCE: starting with-- working all the way back?\n\n\n\n\nPROFESSOR: Yes, the environment is a sequence of frames linked together. And the way I\n\nlike to think about it, it's the pointer to the first one, because once you've got that you've\n\ngot them all. Anybody else?\n\n\n\n\nAUDIENCE: Is it possible to evaluate a procedure or to define a procedure in two different\nenvironments such that it will behave differently, and have pointers to both --\n\n\n\n\n\nPROFESSOR: Oh, yes. The same procedure is not going to have two different environments.\nThe same code, the same lambda expression can be evaluated in two environments\n\nproducing two different procedures. Each procedure--\nAUDIENCE: Their definition has the same name. Their operation--\n\n\n\n\nPROFESSOR: The definition is written the same, with the same characters. I can evaluate\n\nthat set of characters, whatever, that list structure that defines, that is the textual\nrepresentation. I can evaluate that in two different environments producing two different\n\nprocedures. Each of those procedures has its own local sets of variables, and we'll see that\nright now. Anybody else? OK, thank you. Let's take a break. [MUSIC PLAYING]\n\n\n\n\n\nWell, now I've done this terrible thing to you. I've introduced a very complicated thing,\nassignment, which destroys most of the interesting mathematical properties of our\n\nprograms. Why should I have done this? What possible good could this do? Clearly not a\nnice thing, so I better have a good excuse. Well, let's do a little bit of playing, first of all,\n\nwith some very interesting programs that have assignment. Understand s omething special\nabout them that makes them somewhat valuable.\n\n\n\n\n\nStart with a very simple program which I'm going to call make-counter. I'm going to define\nmake-counter to be a procedure of one argument n which returns as its value a procedure\n\nof no arguments-- a procedure that produces a procedure-- which sets n to the increment of\nn and returns that value of n.\n\n\n\n\n\nNow we're going to investigate the behavior of this. It's a sort of interesting thing. In order\nto investigate the behavior, I have to make an environment model, because we can't\n\nunderstand this any other way. So let's just do that.\n\n\n\n\nWe start out with some sort of-- let's say there is a global environment that the machine is\n\nborn with. Global we'll call it. And it's going to have in it a bunch of initial things. We all\nknow what it's got. It's got things in it like say, plus, and times, and quotient, and\n\ndifference, and CAR, and et cetera, lots of things. I don't know what they are, some various\nsquiggles that are the things the machine is born with. And by doing the definition here,\n\nwhat I plan to do--\n\n\n\n\nWell, what am I doing? I'm doing this relative to the global environment. So here's my\n\nenvironment pointer. In order to do that I have to evaluate this lambda expression. That\nmeans I make a procedure object.\nSo I'm going to make a procedure object here. And the procedure object has, as the place\n\nit's defined, the global environment. The procedure object contains some code that\nrepresents a procedure of one argument n which returns a procedure ofno arguments\n\nwhich does something. And the define is a way of changing this environment, so that I now\nadd to it a make-counter, a special rule for the special thing defined. But what that is, is it\n\ngives me that pointer to that procedure. So now the global environment contains make-\ncounter as well.\n\n\n\n\n\nNow, we're going to do some operations. I'm going to use this to make some counters. We'll\nsee what a counter is. So let's define c1 to be a counter beginning at 0. Well, we know how\n\nto do this now, according to the model. I have to evaluate the expression make-counter in\nthe global environment, make-counter of 0.\n\n\n\n\n\nWell, I look up make-counter and see that it's a procedure. I'm going to have to apply that\nprocedure. The way I apply the procedure is by constructing a frame. So I construct a frame\n\nwhich has a value for n in it which is 0, and the parent environment is the one which is the\nenvironment of definition of make-counter. So I've made an environment by applying make-\n\ncounter to 0.\n\n\n\n\nNow, I have to evaluate the body of make-counter, which is this lambda expression, in that\n\nenvironment. Well evaluating this body, this body is a lambda expression. Evaluate a\nlambda expression means make a procedure object. So I'm going to make a procedure\n\nobject.\n\n\n\n\nAnd that procedure object has the environment it was defined in being that, where n was\n\ndefined to be 0. And it has some code, which is the procedure of no arguments which does\nsomething, that sets something, and returns n. And this thing is going to be the object,\n\nwhich in the global environment, will have the name c1. So we construct a name here, c1,\n\nand say that equals that.\n\n\n\n\nNow, but also make another counter, c2 to be make-counter say, starting with 10. Then I\ndo essentially the same thing. I apply the make-counter procedure, which I got from here,\n\nto make another frame with n being 10. That frame has the global environment as its\nparent. I then construct a procedure which has that as it's frame of definition. The code of it\n\nis the procedure of no arguments which does something. And it does a set, and so on. And\n\nn comes out. And c2 is this.\nWell, you're already beginning to see something fairly interesting. There are two n's here.\n\nThey are not one n. Each time I called make-counter, I made another instance of n. These\nare distinct and separate from each other. Now, let's do some execution, use those\n\ncounters. I'm going to use those counters.\n\n\n\n\nWell, what happens if I say, c1 at this point? Well, I go over here, and I say, oh yes, c1 is a\n\nprocedure. I'm going to call this procedure on no arguments, but it has no parameters.\nThat's right. What's its body? Well, I have to look over here, because I didn't write it down.\n\nIt said, set n to one plus n and return n, increment n.\n\n\n\n\nWell, the n it sees is this one. So I increment that n. That becomes one, and I return the\n\nvalue one. Supposing I then called c2. Well, what do I do? I say c2 is this procedure which\ndoes the same thing, but here's the n. It becomes 11. And so I have an 11 which is the\n\nvalue. I then can say, let's try c1 again. c1 is this, that's two, so the answer is two. And c2\ngives me a 12 by the same method, by walking down here looking at that and saying,\n\nhere's the n, I'm incrementing.\n\n\n\n\nSo what I have are computational objects. There are two counters, each with its own\n\nindependent local state. Let's talk about this a little. This is a strange thing. What's an\nobject? It's not at all obvious what an object is. We like to think about objects, because it's\n\neconomical to think that way. It's an intellectual economy. I am an object. You are an\nobject. We are not the same object.\n\n\n\n\n\nI can divide the world into two parts, me and you, and there's other things as well, such\nthat most of the things I might want to discuss about my workings do not involve you, and\n\nmost of the things I want to discuss about your workings don't involve me. I have a blood\npressure, a temperature, a respiration rate, a certain amount of sugar in my blood, and\n\nnumerous, thousands, of state variables-- millions actually, or I don't know how many--\n\nhuge numbers of state variables in the physical sense which represent the state of me as a\nparticle, and you have gazillions of them as well.\n\n\n\n\nAnd most of mine are uncoupled to most of yours. So we can compute the properties of me\n\nwithout worrying too much about the properties of you. If we had to work about both of us\ntogether, than the number of states that we have to consider is the product of the number\n\nof states you have and the number of states I have. But this way it's almost a sum.\nNow, indeed there are forces that couple us. I'm talking to you and your state changes. I'm\n\nlooking at you and my state changes. Some of my state variables, a very few of them,\ntherefore, are coupled to yours. If you were to suddenly yell very loud, my blood pressure\n\nwould go up.\n\n\n\n\nHowever, and it may not be always appropriate to think about the world as being made out\n\nof independent states and independent particles. Lots of the bugs that occur in things like\nquantum mechanics, or the bugs in our minds that occur when we think about things like\n\nquantum mechanics, are due the fact that we are trying to think about things b eing broken\nup into independent pieces, when in fact there's more coupling than we see on the surface,\n\nor that we want to believe in, because we want to compute efficiently and effectively. We've\nbeen trained to think that way.\n\n\n\n\n\nWell, let's see. How would we know if we had objects at all? How can we tell if we have\nobjects? Consider some possible optical illusions. This could be done. These pieces of chalk\n\nare not appropriately identical, but supposing you couldn't tell the difference of them by\nlooking at them. Well, there's a possibility that this all a game I'm playing with mirrors. It's\n\nreally the same piece of chalk, but you're seeing two of them. How would you know if you're\n\nseeing one or two? Well, there's only one way I know. You grab one of them and change it\nand see if the other one changed. And it didn't, so there's two of them.\n\n\n\n\nAnd, on the other hand, there is some other screwy properties of things like that. Like, how\n\ndo we know if something changed? We have to look at it before and after the change. The\n\nchange is an assignment, it's a moment in time. But that means we have to know it was\nthe same one that we're looking at. So some very strange, and unusual, and obscure, and --\n\nI don't understand the problems associated with assignment, and change, and objects.\nThese could get very, very bad.\n\n\n\n\n\nFor example, here I am, I am a particular person, a particular object. Now, I can take out\nmy knife, and cut my fingernail. A piece of my fingernail has fallen off onto the table. I\n\nbelieve I am the same person I was a second ago, but I'm not physically the same in the\nslightest.\n\n\n\n\nI have changed. Why am I the same? What is the identity of me? I don't know. Except for\n\nthe fact that I have some sort of identity. And so, I think by introducing assignment and\n\nobjects, we have opened ourselves up to all the horrible questions of philosophy that have\nbeen plaguing philosophers for some thousands of years about this sort of thing. It's why\n\nmathematics is a lot cleaner.\nLet's look at the best things I know to say about actions and identity. We say that an action,\na, had an effect on an object, x, or equivalently, that x was changed by a, if some property,\n\np, which was true of x before a, became false of x after a. Let's test. It still means I have to\nhave the x before and after. Or, the other way of saying this is, we say that two objects x\n\nand y are the same for any action which has an effect on x has the same effect on y.\n\n\n\n\nHowever, objects are very useful, as I said, for intellectual economy. One of the things\n\nthat's incredibly useful about them, is that the world is, we like to think about, made out of\nindependent objects with independent local state. We like to think that way, although it isn't\n\ncompletely true.\n\n\n\n\nWhen we want to make very complicated programs that deal with such a world, if we want\n\nthose programs to be understandable by us and also to be changeable, so that if we change\nthe world we change the program only a little bit, then we want there to be connections,\n\nisomorphism, between the objects in the world and the objects in our mental model. The\n\nmodularity of the world can give us the modularity in our programming. So we invent things\ncalled object-oriented programming and things like that to provide us with that power.\n\n\n\n\nBut it's even easier. Let's play a little game. I want to play a little game,show you an even\n\neasier example of where modularity can be enhanced by using an assignment statement,\n\njudiciously. One thing I want to enforce and impress on you, is don't use assignment\nstatements the way you use it in FORTRAN or Basic or something or Pascal, to do the things\n\nyou don't have to do with it. It's not the right way to think for most things. Sometimes it's\nessential, or maybe it's essential. We'll see more about that too.\n\n\n\n\n\nOK, let me show you a fun game here. There was mathematician by the nam e of Cesaro--\nor Cesaro, Cesaro I suppose it is-- who figured out a clever way of computing pi. It turns\n\nout that if I take to random numbers, two integers at random, and compute the greatest\ncommon divisor, their greatest common divisor is either one or it's not one. If it's one, then\n\nthey have no common divisors. If their greatest common divisor is one-- the probability that\ntwo random numbers, two numbers chosen at random, has as greatest common divisor one\n\nis related to pi.\n\n\n\n\nIn fact-- yes, it's very strange-- of course there are other ways of computing pi, like\n\ndropping pins on flags, and things like that, and sort of the same kind of thing. So the\nprobability of that the GCD of number one and number two, two random numbers chosen, is\n6 over pi squared. I'm not going to try to prove that. It's actually not too hard and sort of\n\nfun.\n\n\n\n\nHow would we estimate such probability? Well, the way we do that, the way we estimate\n\nprobabilities, is by doing lots of experiments, and then computing the ratios of the ones that\ncome out one way to the total number of experiments we do. It's called Monte Carlo, and\n\nit's useful in other contexts for doing things like integrals where you have lots and lots of\nvariables-- the space which is limiting the dimensions you are do ing you integral in.\n\n\n\n\n\nBut going back to here, Let's look at this slide, We can use Cesaro's method for estimating\npi with n trials by taking the square root of six over a Monte Carlo, a Monte Carlo\n\nexperiment with n trials, using Cesaro's experiment, where Cesaro's experiment is the test\nof whether the GCD of two random numbers-- And you can see that I've already got some\n\nassignments in here, just by what I wrote. The fact that this word rand, in parentheses,\ntherefore, that procedure call, yields a different value than this one, at least that's what I'm\n\nassuming by writing this this way, indicates that this is not a function, that there's internal\nstate in it which is changing. If the GCD of those two random numbers is equal to one,\n\nthat's the experiment.\n\n\n\n\nSo here I have an experimental method for estimating the value of pi. Where, I can easily\n\ndivide this problem into two parts. One is the specific Monte Carlo experiment of Cesaro,\nwhich you just saw, and the other is the general technique of doing Monte Carlo\n\nexperiments. And that's what this is.\n\n\n\n\nIf I want to do Monte Carlo experiments with n trials, a certain number of trials, and a\n\nparticular experiment, the way I do that is I make a little iterative procedure which has\nvariable the number of trials remaining and the number trials that have been passed, that\n\nI've gotten true. And if the number remaining is 0, then the answer is the number past\n\ndivided by this whole number of trials, was the estimate of the probability. And if it's not, if\nI have more trials to do, then let's do one.\n\n\n\n\nWe do an experiment. We call the procedure which is experiment on no arguments. We do\n\nthe experiment and then, if that turned out to be true, we go around the loop decrementing\nthe number of experiments we have to do by one and incrementing the number that were\n\npassed.\nAnd if the experiment was false, we just go around the loop decrementing the number of\n\nexperiments remaining and keeping the number passed the same. We start this up iterating\nover the total number of trials with 0 experiments past. A very elegant little program. And I\n\ndon't have to just do this with Cesaro's experiment, it could be lots of Monte Carlo\nexperiments I might do.\n\n\n\n\n\nOf course, this depends upon the existence of some sort of random number generator. And\nrandom number generators generally look something like this. There is a random number\n\ngenerator-- is in fact a procedure which is going to do something just like the counter. It's\ngoing to update an x to the result of applying some function to x, where this function is\n\nsome screwy kind of function that you might find out in Knuth's books on the details of\nprogramming. He does these wonderful books that are full of the details of programming,\n\nbecause I can't remember how to make a random number generator, but I can look it up\n\nthere, and I can find out.\n\n\n\n\nAnd then, eventually, I return the value of x which is the state variable internal to the\nrandom number generator. That state variable is initialized somehow, and has a value. And\n\nthis procedure is defined in the context where that variable is bound. So this is a hidden\n\npiece of local state that you see here. And this procedure is defined in that context.\n\n\n\n\nNow, that's a very simple thing to do. And it's very nice. Supposing, I didn't want to use\nassignments. Supposing, I wanted to write this program without assignments. What\n\nproblems would I have? Well, let's see. I'd like to use the overhead machine here, thank\n\nyou.\n\n\n\n\nFirst of all, let's look at the whole thing. It's a big story. Unfortunately, which tells you there\nis something wrong. It's at least that big, and it's monolithic. You don't have to understand\n\nor look at the text there right now to see that it's monolithic. It isn't a thing which is\n\nCesaro's experiment. It's not pulled out from the Monte Carlo process. It's not separated.\n\n\n\n\nLet's look why. Remember, the constraint here is that every procedure return the same\nvalue for the same arguments. Every procedure represents a function. That's a different\n\nkind of constraint. Because when I have assignments, I can change some internal state\nvariable.\nSo let's see how that causes things to go wrong. Well, start at the beginning. The estimate\n\nof pi looks sort of the same. What I'm doing is I take the square root of six over the random\nGCD test applied to n, whereas that's what this is.\n\n\n\n\n\nBut here, we are beginning to see something funny. The random GCD test of a certain\nnumber of trials is just like we had before, an iteration on the number of trials remaining,\n\nthe number of trials that have been passed, and another variable x.\n\n\n\n\nWhat's that x? That x is the state of the random number generator. And it is now going to\n\nbe used here. The same random update function that I have over here is the one I would\nhave used in a random number generator if I were building it the other way, the one I get\n\nout of Knuth's books. x is going to get transformed into x1, I need two random numbers.\nAnd x1 is going to get transformed into x2, I have two random numbers. I then have to do\n\nexactly what I did before. I take the GCD of x1 x2. If that's one, then I go around the loop\nwith x2 being the next value of x.\n\n\n\n\n\nYou see what's happened here is that the state of the random number generator is no\nlonger confined to the insides of the random number generator. It has leaked out. It has\n\nleaked out into my procedure that does the Monte Carlo experiment. But what's worse than\nthat, is it's also, because it was contained inside my experiment itself, Cesaro, it leaked out\n\nof that too. Because Cesaro called twice, has to have a different value each time, if I going\nto have a legitimate experimental test. So Cesaro can't be a function either, unless I pass it\n\nthe seed of the random number generator that is going to go wandering around.\n\n\n\n\nSo unfortunately, the seed of random number generator has leaked out into Cesaro, from\n\nthe random number generator, that's leaked into the Monte Carlo experiment. And,\nunfortunately, my Monte Carlo experiment here is no longergeneral. The Monte Carlo\n\nexperiment here knows how many random numbers I need to do the experiment.\n\n\n\n\nThat's sort of horrible. I lost an ability to decompose a problem into pieces, because I\n\nwasn't willing to accept the little loop of information, the feedback process, that happens\ninside the random number generator before that was made by having an assignment to a\n\nstate variable that was confined to the random number generator. So the fact that the\nrandom number generator is an object, with an internal state variable, it's affected by\n\nnothing, but it'll give you something, and it will apply it's force to you, that was what we're\n\nmissing now.\nOK, well I think we've seen enough reason for doing this, and it all sort of looks very\n\nwonderful. Wouldn't it be nice if assignment was a good thing and maybe it's worth it, but\nI'm not sure. As Mr. Gilbert and Sullivan said, things are seldom what they seem, skim milk\n\nmasquerades as cream.\n\n\n\n\nAre there any questions? Are there any philosophers here? Anybody want to argue about\n\nobjects? You're just floored, right? And you haven't done your homework yet. You haven't\ncome up with a good question. Oh, well. Sure, thank you. Let's take the long break now.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed thismaterial in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec5b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 5B: Computational Objects\n\n\n\nPROFESSOR: Well, now that we've given you some power to make independent local state\nand to model objects, I thought we'd do a bit of programming of a very complicated kind,\n\njust to illustrate what you can do with this sort of thing. I suppose, as I said, we were\nmotivated by physical systems and the ways we like to think about physical systems, which\n\nis that there are these things that the world is made out of. And each of these things has\nparticular independent local state, and therefore it is a thing. That's what makes it a thing.\n\n\n\n\n\nAnd then we're going to say that in the model in the world--we have a world and a model in\nour minds and in the computer of that world. And what I want to make is a correspondence\n\nbetween the objects in the world and the objects in the computer, the relationships between\nthe objects in the world and the relationships between those same obj... --the model objects\n\nin the computer, and the functions that relate things in the world to the functions that relate\nthings in the computer.\n\n\n\n\n\nThis buys us modularity. If we really believe the world is like that, that it's made out of\nthese little pieces, and of course we could arrange our world to be like that, we could only\n\nmodel those things that are like that, then we can inherit the modularity in the world into\nour programming. That's why we would invent some of this object -oriented programming.\n\n\n\n\n\nWell, let's take the best kind of objects I know. They're completely--they're completely\nwonderful: electrical systems. Electrical systems really are the physicist's best, best objects.\n\nYou see over here I have some piece of machinery. Right here's a piece of machinery. And\nit's got an electrical wire connecting one part of the machinery with another part of the\n\nmachinery. And one of the wonderful properties of the electrical world is that I can say this\nis an object, and this is an object, and they're-- the connection between them is clear. In\n\nprinciple, there is no connection that I didn't describe with these wires.\n\n\n\n\nLet's say if I have light b ulbs, a light bulb and a power supply that's plugged into the outlet.\n\nThen the connection is perfectly clear. There's no other connections that we know of. If I\nwere to tie a knot in the wire that connects the light bulb to the power supply, the light\n\nremains lit up. It doesn't care. That the way the physics is arranged is such that the\n\nconnection can be made abstract, at least for low frequencies and things like that. So in\nfact, we have captured all of the connections there really are.\nWell, as you can go one step further and talk about the most abstract types of electrical\nsystems we have, digital to dual circuits. And here there are certain kinds of objects. For\n\nexample, in digital circuits we have things like inverters. We have things like and -gates. We\nhave things like or-gates. We connect them together by sort-of wires which represent\n\nabstract signals. We don't really care as physical variables whether these are voltages or\n\ncurrents or some combination or anything like that, or water, water pressure. These\nabstract variables represent certain signals. And we build systems by wiring these things\n\ntogether with wires.\n\n\n\n\nSo today what I'm going to show you, right now, we're going to build up an invented\n\nlanguage in Lisp, embedded in the same sense that Henderson's picture language was\nembedded, which is not the same sense as the language of pattern match and substitution\n\nwas done yesterday. The pattern match/substitution language was interpreted by a Lisp\nprogram. But the embedding of Henderson's program is that we just build up more and\n\nmore procedures that encapsulate the structure we want.\n\n\n\n\nSo for example here, I'm going to have some various primitive kinds of objects, as you see,\n\nthat one and that one. I'm going to use wires to combine them. The way I represent\nattaching-- I can make wires. So let's say A is a wire. And B is a wire. And C is a wire. And\n\nD is a wire. And E is wire. And S is a wire.\n\n\n\n\nWell, an or-gate that has both inputs, the inputs being A and B, and the output being Y or\n\nD, you notate like this. An and-gate, which has inputs A and B and output C, we notate like\nthat. By making such a sequence of declarations, like this, I can wire together an arbitrary\n\ncircuit. So I've just told you a set of primitives and means of combination for build ing digital\ncircuits, when I need more in a real language than abstraction.\n\n\n\n\n\nAnd so for example, here I have--here I have a half adder. It's something you all know if\nyou've done any digital design. It's used for adding numbers together on A and B and\n\nputting out a sum and a carry. And in fact, the wiring diagram is exactly what I told you. A\nhalf adder with things that come out of the box-- you see the box, the boundary, the\n\nabstraction is always a box. And there are things that come out of it, A, B, S, a nd C. Those\nare the declared variables--declared variables of a lambda expression, which is the one that\n\ndefines half adder.\n\n\n\n\nAnd internal to that, I make up some more wires, D and E, which I'm going to use for the\n\ninterconnect-- here E is this one and D is this wire, the interconnect that doesn't come\nthrough the walls of the box-- and wire things together as you just saw. And the nice thing\n\nabout this that I've just shown you is this language is hierarchical in the right way. If a\nlanguage isn't hierarchical in the right way, if it turns out that a compound object doesn't\n\nlook like a primitive, there's something wrong with the language -- at least the way I feel\nabout that.\n\n\n\n\n\nSo here we have--here, instead of starting with mathematical functions, or things that\ncompute mathematical functions, which is what we've been doing up until now, instead of\n\nstarting with things that look like mathematical functions, or compute such thing s, we are\nstarting with things that are electrical objects and we build up more electrical objects. And\n\nthe glue we're using is basically the Lisp structure: lambdas. Lambda is the ultimate glue, if\nyou will.\n\n\n\n\n\nAnd of course, half adder itself can be used in a more complicated abstraction called a full\nadder, which in fact involves two half adders, as you see here, hooked together with some\n\nextra wires, that you see here, S, C1, and C2, and an or-gate, to manufacture a full adder,\nwhich takes a input number, another input number, a carry in, and produces output, a sum\n\nand a carry out. And out of full adders, you can make real adder chains and big adders.\n\n\n\n\nSo we have here a language so far that has primitives, means of combination, and means of\n\nabstraction to real language. Now, how are we going to implement this? Well, let's do it\neasily. Let's look at the primitives. The only problem is we have to implement the\n\nprimitives. Nothing else has to be implemented, because we're picking up the means of\n\ncombination and abstraction from Lisp, inheriting them in the embedding.\n\n\n\n\nOK, so let's look at a particular primitive. An inverter is a nice one. Now, inverter has two\nwires coming in, an in and an out. And somehow, it's going to have to know what to do\n\nwhen a signal comes in. So somehow it's going to have to tell its input wire -- and now we're\n\ngoing to talk about objects and we're going to see this in a little more detail soon -- but it's\ngoing to have to tell its input wire that when you change, tell me. So this object, the object\n\nwhich is the inverter has to tell the object which is the input wire, hi, my name is George.\nAnd my, my job is to do something with results when you change. So when you change,\n\nyou get a change, tell me about it. Because I've got to do something with that.\n\n\n\n\nWell, that's done down here by adding an action on the input wire called invert- in, where\n\ninvert-in is defined over here to be a procedure of no arguments, which gets the logical not\nof the signal on the input wire. And after some delay,which is the inverter delay, all these\n\nelectrical objects have delays, we'll do the following thing -- set the signal on the output wire\nto the new value. A very simple program.\nNow, you have to imagine that the output wire has to be sensitive and know that when its\nsignal changes, it may have to tell other guys, hey, wake up. My value has changed. So\n\nwhen you hook together inverter with an and-gate or something like that, there has to be a\nlot of communication going on in order to make sure that the signal propagates right. And\n\ndown here is nothing very exciting. This is just the definition of logical not for some\n\nparticular representations of the logical values-- 1, 0 in this case.\n\n\n\n\nAnd we can look at things more complicated like and-gates. And-gates take two inputs, A1\nand A2, we'll call them, and produce an output. But the structure of the and -gate is identical\n\nto the one we just saw. There's one called an and-action procedure that's defined, which is\n\nthe thing that gets called when an input is changed. And what it does, of course, is nothing\nmore than compute the logical and of the signals on the inputs. And after some delay, called\n\nthe and-gate delay, calls this procedure, which sets a signal on the output to a new value.\n\n\n\n\nNow, how I implement these things is all wishful thinking. As you see here, I have an\n\nassignment operation. It's not set. It's a derived assignment operation in the same way we\nhad functions that were derived from CAR and CDR. So I, by convention, label that with an\n\nexclamation point. And over here, you see there's an action, which is to inform the wire,\ncalled A1 locally in this and -gate, to call the and-action procedure when it gets changed,\n\nand the wire A2 to call the and-action procedure when it gets changed. All very simple.\n\n\n\n\nWell, let's talk a little bit about this communication that must occur between these various\n\nparts. Suppose, for example, I have a very simple circuit which contains an and with wires A\nand B. And that connects through a wire called C to an inverter which h as a wire output\n\ncalled D. What are the comput...--here's the physical world. It's an abstraction of the\nphysical world. Now I can buy these out of little pieces that you get at Radio Shack for a few\n\ncents. And there are boxes that act like this, which have little numbers on them like LS04 or\nsomething.\n\n\n\n\n\nNow supposing I were to try to say what's the computational model. What is the thing that\ncorresponds to that, that part of reality in the mind of us and in the computer? Well, I have\n\nto assign for every object in the world an object in the computer, and for every relationship\nin the world between them a relationship in the computer. That's my goal.\n\n\n\n\n\nSo let's do that. Well, I have some sort of thing called the signal, A. This is A. It's a signal.\nIt's a cloudy thing like that. And I have another one down here which I'm going to call B.\n\nIt's another signal. Now this signal--these two signals are somehow going to have to hook\ntogether into a box, let's call it this, which is the and-gate, action procedure. That's the and-\n\ngate's action procedure.\n\n\n\n\nAnd it's going to produce--well, it's going to interact with a signal object, which we call C --a\n\nwire object, excuse me, we call C. And then the-- this is going to put out again, or connect\nto, another action procedure which is one associated with the inverter in the world, not. And\n\nI'm going to have another--another wire, which we'll call D.\n\n\n\n\nSo here's my layout of stuff. Now we have to say what's inside them and what they have to\n\nknow to compute. Well, every--every one of these wires has to know what the value of the\nsignal that's on that wire is. So there's going to be some variable inside here, we'll call it\n\nsignal. And he owns a value. So there must be some environment associated with this. And\nfor each one of these, there must be an environment that binds signal. And there must be a\n\nsignal here, therefore. And presumably, signal's a value that's either 1 or 0, and signal.\n\n\n\n\nNow, we also have to have some list of people to inform if the signal here changes. We're\n\ngoing to have to inform this. So I've got that list. We'll call it the Action Procedures, AP. And\nit's presumably a list. But the first thing on the list, in this case, is this guy. And the action\n\nprocedures of this one happens to have some list of stuff. There might be other people who\nare sharing A, who are looking at it. So there might be other guys on this list, like\n\nsomebody over there that we don't know about. It's the other guy attached to A.\n\n\n\n\nAnd the action procedure here also has to point to that, the list of action procedures. And of\n\ncourse, that means this one, its action procedures has to point up to here. This is the\nthings-- the people it has to inform. And this guy has some too. But I don't know what they\n\nare because I didn't draw it in my diagram. It's the things connected to D.\n\n\n\n\nNow, it's also the case that when the and-action procedure is awakened, saying one of the\n\npeople who know that you've told--one of the people you've told to wake you up if their\nsignal changes, you have to go look and ask them what's their signal so you can do the and,\n\nand produce a signal for this one. So there has to be, for example, information here saying\nA1, my A1 is this guy, and my A2 is this guy. And not only that, when I do my and, I'm\n\ngoing to have to tell this guy something. So I need an output-- being this guy.\n\n\n\n\nAnd similarly, this guy's going to have a thing called the input that he interrogates to find\n\nout what the value of the signal on the input is, when the signal wakes up and says, I've\nchanged, and sends a message this way saying, I've changed. This guy says, OK, what's\nyour value now? When he gets that value, then he's going to have to say, OK, output\n\nchanges this guy, changes this guy. And so on. And so I have to have at least that much\nconnected-ness.\n\n\n\n\n\nNow, let's go back and look, for example, at the and-gate. Here we are back on this slide.\nAnd we can see some of these parts. For any particular and-gate, there is an A1, there is an\n\nA2, and the output. And those are, those are an environment that was created at the --those\nproduce a frame at the time and-gate was called, a frame where A1, A2, and output are--\n\nhave as their values, they're bound to the wires which, they are--which were passed in. In\nthat environment, I constructed a procedure-- this one right there. And-action procedure\n\nwas constructed in that environment. That was the result of evaluating a lambda\nexpression.\n\n\n\n\n\nSo it hangs onto the frame where these were defined. Local--part of its local state is that.\nThe and-action procedure, therefore, has access to A1, A2, and output as we see here. A1,\n\nA2, and output.\n\n\n\n\nNow, we haven't looked inside of a wire yet. That's all that remains. Let's look at a wire.\n\nLike the overhead, very good. Well, the wire, again, is a, is a somewhat complicated mess.\nOoh, wrong one. It's a big complicated mess, like that. But let's look at it in detail and see\n\nwhat's going on.\n\n\n\n\nWell, the wire is one of these. And it has to have two things that are part of it, that it's\n\nstate. One of them is the signal we see here. In other words, when we call make-wire to\nmake a wire, then the first thing we do is we create some variables which are the signal and\n\nthe action procedures for this wire. And in that context, we define various functions--or\nprocedures, excuse me, procedures.\n\n\n\n\n\nOne of them is called set-my-signal to a new value. And what that does is takes a new value\nin. If that's equal to my current value of my signal, I'm done. Otherwise, I set the signal to\n\nthe new value and call each of the action procedures that I've been, that I've been--what's\nthe right word?-- introduced to. I get introduced when the and-gate was applied to me. I\n\nadd action procedure at the bottom.\n\n\n\n\nAlso, I have to define a way of accepting an action procedure-- which is what you see here--\n\n- which increments my action procedures using set to the result of CONSing up a new\nprocess--a procedure, which is passed to me, on to my actions procedures list. And for\ntechnical reasons, I have to call that procedure one. So I'm not going to tell you anything\n\nabout that, that has to do with event-driven simulations and getting them started, which\ntakes a little bit of thinking.\n\n\n\n\n\nAnd finally, I'm going to define a thing called the dispatcher, which is a wa y of passing a\nmessage to a wire, which is going to be used to extract from it various information, like\n\nwhat is the current signal value? What is the method of setting your signal? I want to get\nthat out of it. How do I--how do I add another action procedure? And I'm going to return\n\nthat dispatch, that procedure as a value.\n\n\n\n\nSo the wire that I've constructed is a message accepting object which accepts a message\n\nlike, like what's your method of adding action procedures? In fact, it'll give me a procedure,\nwhich is the add action procedure, which I can then apply to an action procedure to create\n\nanother action procedure in the wire. So that's a permission. So it's given me permission to\nchange your action procedures.\n\n\n\n\n\nAnd in fact, you can see that over here. Next slide. Ah. This is nothing very interesting. The\ncall each of the action procedures is just a CDRing down a list. And I'm not going to even\n\ntalk about that anymore. We're too advanced for that. However, if I want to get a signal\nfrom a wire, I ask the wire-- which is, what is the wire? The wire is the dispatch returned by\n\ncreating the wire. It's a procedure. I call that dispatch on the message get- signal. And what\nI should expect to get is a method of getting a signal. Or actually, I get the signal.\n\n\n\n\n\nIf I want to set a signal, I want to change a signal, then what I'm going to do is take a wire\nas an argument and a new value for the signal, I'm going to ask the wire for permission to\n\nset its signal and use that permission, which is a procedure, on the new value. And if we go\nback to the overhead here, thank you, if we go back to the overhead here, we see that the\n\nmethod-- if I ask for the method of setting the signal, that's over here, it's set-my-signal, a\n\nprocedure that's defined inside the wire, which if we look over here is the thing that says set\nmy internal value called the signal, my internal variable, which is the signal, to the new\n\nvalue, which is passed to me as an argument, and then call each of the action procedures\nwaking them up. Very simple.\n\n\n\n\nGoing back to that slide, we also have the one last thing-- which I suppose now you can\n\neasily work out for yourself-- is the way you add an action. You take a wire--a wire and an\n\naction procedure. And I ask the wire for permission to add an action. Getting that\npermission, I use that permission to give it an action procedure. So that's a real object.\nThere's a few more details about this. For example, how am I going to control this thing?\n\nHow do I do these delays? Let's look at that for a second. The next one here. Let's see. We\nknow when we looked at the and-gate or the not-gate that when a signal changed on the\n\ninput, there was a delay. And then it was going to call the procedure, which was going to\nchange the output.\n\n\n\n\n\nWell, how are we going to do this? We're going to make up some mechanism, a fairly\ncomplicated mechanism at that, which we're going to have to be very careful about. But\n\nafter a delay, we're going to do an action. A delay is a number, and an action is a\nprocedure. What that's going to be is they're going to have a special structure called an\n\nagenda, which is a thing that organizes time and actions. And we're going to see that in a\nwhile. I don't want to get into that right now.\n\n\n\n\n\nBut the agenda has a moment at which--at which something happens. We're setting up for\nlater at some moment, which is the sum of the time, which is the delay time plus the\n\ncurrent time, which the agenda thinks is now. We're going to set up to do this action, and\nadd that to the agenda.\n\n\n\n\n\nAnd the way this machine will now run is very simple. We have a thing called propagate,\nwhich is the way things run. If the agenda is empty, we're done--if there's nothing more to\n\nbe done. Otherwise, we're going to take the first item off the agenda, and that's a\nprocedure of no arguments. So that we're going to see extra parentheses here. We call that\n\non no arguments. That takes the action. Then we remove that first item from the agenda,\n\nand we go around the propagation loop. So that's the overall structure of this thing.\n\n\n\n\nNow, there's a, a few other things we can look at. And then we're going to look into the\nagenda a little while from now. Now the overhead again. Well, in order to set this thing\n\ngoing, I just want to show you some behavior out of this simulator. By the way, you may\n\nthink this simulator is very simple, and probably too simple to be useful. The fact of the\nmatter is that this simulator has been used to manufacture a fairly large computer. So this\n\nis a real live example.\n\n\n\n\nActually, not exactly this simulator, because I'll tell you the difference. The difference is that\nthere were many more different kinds of primitives. There's not just the word inverter or\n\nand-gate. There were things like edge-triggered, flip-flops, and latches, transparent latches,\n\nand adders, and things like that. And the difficulty with that is that there's pages and pages\nof the definitions of all these primitives with numbers like LS04. And then there's many\n\nmore parameters for them. It's not just one delay. There's things like set up times and hold\ntimes and all that. But with the exception of that part of the complexity, the structure of the\nsimulator that we use for building a real computer, that works is exactly what you're seeing\n\nhere.\n\n\n\n\nWell in any case, what we have here is a few simple things. Like, there's inverter delays\n\nbeing set up and making a new agenda. And then we can make some inputs. There's input-\n1, input-2, a sum and a carry, which are wires. I'm going to put a special kind of object\n\ncalled a probe onto, onto some of the wires, onto sum and onto carry. A probe is a, can\nobject that has the property that when you change a wire it's attached to, it types out a\n\nmessage. It's an easy thing to do.\n\n\n\n\nAnd then once we have that, of course, the way you put the probe on, the first thing it\n\ndoes, it says, the current value of the sum at time 0 is 0 because I just noticed it. And the\nvalue of the carry at time 0, this is the time, is 0. And then we go off and we build some\n\nstructure. Like, we can build a structure here that says you have a half -adder on input-1,\ninput-2, sum, and carry. And we're going to set the signal on input -1 to 1. We do some\n\npropagation. At time 8, which you could see going through this thing if you wanted to, the\nnew value of sum became 1. And the thing says I'm done. That wasn't very interesting.\n\n\n\n\n\nBut we can send it some more signals. Like, we set-signal on input-2 to be one. And at that\ntime if we propagate, then it carried at 11, the carry becomes 1, and at 16, the sum's new\n\nvalue becomes 0. And you might want to work out that, if you like, about the digital\ncircuitry. It's true, and it works. And it's not very interesting. But that's the kind of behavior\n\nwe get out of this thing.\n\n\n\n\nSo what I've shown you right now is a large-scale picture, how you, at a bigger, big scale,\n\nyou implement an event-driven simulation of some sort. And how you might organize it to\nhave nice hierarchical structure allowing you to build abstract boxes that you can\n\ninstantiate. But I haven't told you any of the details about how this agenda and things like\n\nthat work. That we'll do next. And that's going to involve change and mutation of data and\nthings like that. Are there any questions now, before I go on? Thank you. Let's take a\n\nbreak.\n\n\n\n\nWell, we've been making a simulation. And the simulation is an event -driven simulation\nwhere the objects in the world are the objects in the computer. And the changes of state\n\nthat are happening in the world in time are organized to be time in the computer, so that if\n\nsomething happens after something else in the world, then we have it happen after, after\nthe corresponding events happen in the same order inthe computer. That's where we have\n\nassignments, when we make that alignment.\nRight now I want to show you a way of organizing time, which is an agenda or priority\nqueue, it's sometimes called. We'll do some --we'll do a little bit of just understanding what\n\nare the things we need to be able to do to make agendas. And so we're going to have--and\nso right now over here, I'm going to write down a bunch of primitive operations for\n\nmanipulating agendas. I'm not going to show you the code for them because they' re all very\n\nsimple, and you've got listings of all that anyway.\n\n\n\n\nSo what do we have? We have things like make-agenda which produces a new agenda. We\ncan ask--we get the current-time of an agenda, which gives me a number, a time. We can\n\nget--we can ask whether an agenda is empty, empty-agenda. And that produces either a\n\ntrue or a false.\n\n\n\n\nWe can add an object to an agenda. Actually, what we add to an agenda is an operation--an\naction to be done. And that takes a time, the action itself, and the agenda I want to add it\n\nto. That inserts it in the appropriate place in the agenda. I can get the first item off an\n\nagenda, the first thing I have to do, which is going to give me an action. And I can remove\nthe first item from an agenda. That's what I have to be able to do with agendas. That is a\n\nbig complicated mess. From an agenda.\n\n\n\n\nWell, let's see how we can organize this thing as a data structure a bit. Well, an agenda is\n\ngoing to be some kind of list. And it's going to be a list that I'm going to have to be able to\nmodify. So we have to talk about modifying of lists, because I'm going to add things to it,\n\nand delete things from it, and things like that. It's organized by time. It's probably good to\nkeep it in sorted order.\n\n\n\n\n\nBut sometimes there are lots of things that happen at the same time--approximate same\ntime. What I have to do is say, group things by the time at which they're supposed to\n\nhappen. So I'm going to make an agenda as a list of segments. And so I'm going to draw\nyou a data structure for an agenda, a perfectly reasonable one.\n\n\n\n\nHere's an agenda. It's a thing that begins with a name. I'm going to do it right now out of\n\nlist structure. It's got a header. There's a reason for the header. We're going to see the\n\nreason soon.\n\n\n\n\nAnd it will have a segment. It will have--it will be a list of segments. Supposing this agenda\nhas two segments, they're the car's-- successive car's of this list. Each segment is going to\nhave a time-- say for example, 10-- that says that the things that happen in this segment\n\nare at time 10.\n\n\n\n\nAnd what I'm going to have in here is another data structure which I'm not going to\n\ndescribe, which is a queue of things to do at time 10. It's a queue. And we'll talk about that\nin a second. But abstractly, the queue is just a list of things to do at a particular time. And I\n\ncan add things to a queue. This is a queue. There's a time, there's a segment.\n\n\n\n\nNow, I may have another segment in this agenda. Supposing this is stuff that happens at\n\ntime 30. It has, of course, another queue of things that are queued up to be done at time\n30. Well, there are various things I have to be able to do to an agenda.\n\n\n\n\nSupposing I want to add to an agenda another thing to be done at time 10. Well, that's not\n\nvery hard. I'm going to walk down here, looking for the segment of time 10. It is possible\n\nthat there is no segment of time 10. We'll cover that case in a second. But if I find a\nsegment of time 10, then if I want to add another thing to be done at time 10, I just\n\nincrease that queue-- \"just increase\" isn't such an obvious idea. But I increase the things to\nbe done at that time.\n\n\n\n\n\nNow, supposing I want to add something to be done at time 20. There is no segment for\ntime 20. I'm going to have to create a new segment. I want my time 20 segment to exist\n\nbetween time 10 and time 30. Well, that takes a little work. I'm going to have to do a\nCONS. I'm going to have to make a new element of the agenda list--list of segments. I'm\n\ngoing to have to change. Here's change. I'm going to have to change the CDR of the CDR of\nthe agenda to point that a new CONS of the new segment and the CDR of the CDR of the\n\nCDR of the agenda, the CD-D-D-DR.\n\n\n\n\nAnd this is going to have a new segment now of time 20 with its own queue, which now has\n\none element in it. If I wanted to add something at the end, I'm going to have to replace the\nCDR of this, of this list with something. We're going to have to change that piece of data\n\nstructure. So I'm going to need new primitives for doing this. But I'm just showing you why\nI need them.\n\n\n\n\n\nAnd finally, if I wanted to add a thing to be done at time 5, I'm going to have to change this\none, because I'm going to have to add it in over here, which is why I planned ahead and\n\nhad a header cell, which has a place. If I'm going to change things, I have to have places\nfor the change. I have to have a place to make the change.\nIf I remove things from the agenda, that's not so hard. Removing them from the beginning\nis pretty easy, which is the only case I have. I can go looking for the first, the first segment.\n\nI see if it has a non-empty queue. If it has a non-empty queue, well, I'm going to delete\none element from the queue, like that. If the queue ever becomes empty, then I have to\n\ndelete the whole segment. And then this, this changes to point to here. So it's quite a\n\ncomplicated data structure manipulation going on, the details of which are not really very\nexciting.\n\n\n\n\nNow, let's talk about queues. They're similar. Because each of these agendas has a queue in\n\nit. What's a queue? A queue is going to have the following primitive operations. To make a\n\nqueue, this gives me a new queue. I'm going to have to be able to insert into a queue a\nnew item. I'm going to have to be able to delete from a queue the first item in the queue.\n\nAnd I want to be able to get the first thing in the queue from some queue. I also have to be\nable to test whether a queue is empty.\n\n\n\n\n\nAnd when you invent things like this, I want you to be very careful to use the kinds of\nconventions I use for naming things. Notice that I'm careful to say these change something\n\nand that tests it. And presumably, I did the same thing over here. OK, and there should be\nan empty test over here.\n\n\n\n\n\nOK, well, how would I make a queue? A queue wants to be something I can add to at the\nend of, and pick up the thing at the beginning of. I should be able to delete from the\n\nbeginning and add to the end. Well, I'm going to show you a very simple structure for that.\nWe can make this out of CONSes as well.\n\n\n\n\n\nHere's a queue. It has--it has a queue header, which contains two parts-- a front pointer\nand a rear pointer. And here I have a queue with two items in it. The first item, I don't\n\nknow, it's perhaps a 1. And the second item, I don't know, let's give it a 2. The reason why\nI want two pointers in here, a front pointer and a rear pointer, is so I can add to the end\n\nwithout having to chase down from the beginning.\n\n\n\n\nSo for example, if I wanted to add one more item to this queue, if I want to add on another\n\nitem to be worried about later, all I have to do is make a CONS, which contains that item,\nsay a 3. That's for inserting 3 into the queue. Then I have to change this pointer here to\n\nhere. And I have to change this one to point to the new rear.\nIf I wish to take the first element of the queue, the first item, I just go chasing down the\n\nfront pointer until I find the first one and pick it up. If I wish to delete the first item from the\nqueue, delete-queue, all I do is move the front pointer along this way. The new front of the\n\nqueue is now this. So queues are very simple too.\n\n\n\n\nSo what you see now is that I need a certain number of new primitive operations. And I'm\n\ngoing to give them some names. And then we're going to look into how they work, and how\nthey're used. We have set the CAR of some pair, or a thing produced by CONSing, to a new\n\nvalue. And set the CDR of a pair to a new value. And then we're going to look into how they\nwork.\n\n\n\n\n\nI needed setting CAR over here to delete the first element of the queue. Thisis the CAR,\nand I had to set it. I had to be able to set the CDR to be able to move the rear pointer, or to\n\nbe able to increment the queue here. All of the operations I did were made out of those that\nI just showed you on the, on the last blackboard. Good. Let's pause the time, and take a\n\nlittle break then.\n\n\n\n\nWhen we originally introduced pairs made out of CONS, made by CONS, we only said a few\n\naxioms about them, which were of the form-- what were they-- for all X and Y, the CAR of\nthe CONS of X and Y is X and the CDR of the CONS of X and Y is Y. Now, these say nothing\n\nabout whether a CONS has an identity like a person. In fact, all they say is something sort\nof abstract, that a CONS is the parts it's made out of. And of course, two things are made\n\nout of the same parts, they're the same, at least from the point of view of these axioms.\n\n\n\n\nBut by introducing assignment-- in fact, mutable data is a kind of assignment, we have a\n\nset CAR and a set CDR-- by introducing those, these axioms no longer tell the whole story.\nAnd they're still true if written exactly like this. But they don't tell the whole story. Because\n\nif I'm going to set a particular CAR in a particular CONS, the questions are, well, is that\n\nsetting all CARs and all CONSes of the same two things or not? If I--if we use CONSes to\nmake up things like rational numbers, or things like 3 over 4, supposing I had two three -\n\nfourths. Are they the same one-- or are they different?\n\n\n\n\nWell, in the case of numbers, it doesn't matter. Because there's no meaning to changing the\ndenominator of a number. What you could do is make a number which has a different\n\ndenominator. But the concept of changing a number which has to have a different\n\ndenominator is sort of a very weird, and sort of not supported by what you think of as\nmathematics. However, when these CONSes represent things in the physical world, then\n\nchanging something like the CAR is like removing a piece of the fingernail. And so CONSes\nhave an identity.\nLet me show you what I mean about identity, first of all. Let's do some little example here.\nSupposing I define A to the CONS of 1 and 2. Well, what that means, first of all, is that\n\nsomewhere in some environment I've made a symbol A to have a value which is a pair\nconsisting of pointers to a 1 and a pointer to a 2, just like that. Now, supposing I also say\n\ndefine B to be the CONS-- it doesn't matter, but I like it better, it's prettier-- of A and A.\n\n\n\n\nWell, first of all, I'm using the name A twice. At this moment, I'm going to think of CONSes\n\nas having identity. This is the same one. And so what that means is I make another pair,\nwhich I'm going to call B. And it contains two pointers to A. At this point, I have three\n\nnames for this object. A is its name. The CAR of B is its name. And the CDR of B is its name.\n\nIt has several aliases, they're called.\n\n\n\n\nNow, supposing I do something like set-the-CAR, the CAR of the CAR of B to 3. What that\nmeans is I find the CAR of B, that's this. I set the CAR of that to be 3, changing this. I've\n\nchanged A. If I were to ask what's the CAR of A--of A now? I would get out 3, even though\n\nhere we see that A was the CONS of 1 and 2.\n\n\n\n\nI caused A to change by changing B. There is sharing here. That's sometimes what we want.\nSurely in the queues and things like that, that's exactly what we defined our--organized our\n\ndata structures to facilitate-- sharing. But inadvertent sharing, unanticipated interactions\n\nbetween objects, is the source of most of the bugs that occur in complicated programs. So\nby introducing this possibility of things having identity and sharing and having multiple\n\nnames for the same thing, we get a lot of power. But we're going to pay for it with lots of\ncomplexity and bugs.\n\n\n\n\n\nSo also, for example, if I just looked at this just to drive that home, the CADR of B, which\nhas nothing to do with even the CAR of B, apparently. The CADR of B, what's that? Take\n\nthat CDR of B and now take the CAR of that. Oh, that's 3 also. So I can have non-local\ninteractions by sharing. And I have to be very careful of that.\n\n\n\n\nWell, so far, of course, it seems I've introduced several different assignment operators--\n\nset, set CAR, set CDR. Well, maybe I should just get rid of set CAR and set CDR. Maybe\n\nthey're not worthwhile. Well, the answer is that once you let the camel's nose into the tent,\nthe rest of him follows. All I have to have is set, and I can make all of the --all of the bad\n\nthings that can happen.\nLet's play with that a little bit. A couple of days ago, when we introduced compound data,\n\nyou saw Hal show you a definition of CONS in terms of a message acceptor. I'm going to\nshow you even a more horrible thing, a definition of CONS in terms of nothing but air, hot\n\nair. What is the definition of CONS, of the old functional kind, in terms of purely lambdic\nexpressions, procedures? Because I'm going to then modify this definition to get assignment\n\nto be only one kind of assignment, to get rid of the set CAR and set CDR in terms of set.\n\n\n\n\nSo what if I define CONS of X and Y to be a procedure of one argument called a message M,\n\nwhich calls that message on X and Y? This [? idea ?] was invented by Alonzo Church, who\nwas the greatest programmer of the 20th century, although he never saw a computer. It\n\nwas done in the 1930s. He was a logician, I suppose at Princeton at the time. Define CAR of\nX to be the result of applying X to that procedure of two arguments, A and D, which selects\n\nA. I will define CDR of X to be that procedure, to be the result of applying X to that\n\nprocedure of A and D, which selects D.\n\n\n\n\nNow, you may not recognize this as CAR, CDR, and CONS. But I'm going to demonstrate to\nyou that it satisfies the original axioms, just once. And then we're going to do some playing\n\nof games. Consider the problem CAR of CONS of, say, 35 and 47. Well, what is that? It is\n\nthe result of taking car of the result of substituting 35 and 47 for X and Y in the body of\nthis. Well, that's easy enough. That's CAR of the result of substituting into lambda of M, M\n\nof 35 and 47.\n\n\n\n\nWell, what this is, is the result of substituting this object for X in the body of that. So that's\n\njust lambda of M-- that's substituted, because this object is being substituted for X, which is\nthe beginning of a list, lambda of M-- M of 35 and 47, applied to that procedure of A and D,\n\nwhich gives me A. Well, that's the result of substituting this for M here. So that's the same\nthing as lambda of A, D, A, applied to 35 and 47. Oh, well that's 35. That's substituting 35\n\nfor A and for 47 for D in A. So I don't need any data at all, not even numbers. This is Alonso\nChurch's hack.\n\n\n\n\n\nWell, now we're going to do something nasty to him. Being a logician, he wouldn't like this.\nBut as programmers, let's look at the overhead. And here we go. I'm going to change the\n\ndefinition of CONS. It's almost the same as Alonzo Church's, but not quite. What do we\nhave here? The CONS of two arguments, X and Y, is going to be that procedure of one\n\nargument M, which supplies M to X and Y as before, but also to two permissions, the\npermission to set X to N and the permission to set Y to N, given that I have an N.\n\n\n\n\n\nSo besides the things that I had here in Church's definition, what I have is that the thing\nthat CONS returns will apply its argument to not just the values of the X and Y that the\nCONS is made of, but also permissions to set X and Y to new values. Now, of course, just as\n\nbefore, CAR is exactly the same. The CAR of X is nothing more than applying X, as in\nChurch's definition, to a procedure, in this case, of four arguments, which selects out the\n\nfirst one. And just as we did before, that will be the value of X that was contained in the\nprocedure which is the result of evaluating this lambda expression in the environment\n\nwhere X and Y are defined over here. That's the value of CONS.\n\n\n\n\nNow, however, the exciting part. CDR, of course, is the same. The exciting part, set CAR\n\nand set CDR. Well, they're nothing very complicated anymore. Set CAR of a CONS X to a\nnew value Y is nothing more than applying that CONS, which is the procedure of four--the\n\nprocedure of one argument which applies its argument to four things, to a procedure which\nis of four arguments-- the value of X, the value of Y, permission to set X, the permission to\n\nset Y-- and using it--using that permission to set X to the new value. And similarly, set-cdr\n\nis the same thing.\n\n\n\n\nSo what you've just seen is that I didn't introduce any new primitives at all. Whether or not\nI want to implement it this way is a matter of engineering. And the answer is of course I\n\ndon't implement it this way for reasons that have to do with engineering. However in\n\nprinciple, logically, once I introduced one assignment operator, I've assigned--I've\nintroduced them all. Are there any questions? Yes, David.\n\n\n\n\nAUDIENCE: I can follow you up until you get--I can follow all of that. But when we bring in\n\nthe permissions, defining CONS in terms of the lambda N, I don't follow where N gets\n\npassed.\n\n\n\n\nPROFESSOR: Oh, I'm sorry. I'll show you. Let's follow it. Of course, we could do it on the\nblackboard. It's not so hard. But it's also easy here.\n\n\n\n\n\nSupposing I wish to set-cdr of X to Y. See that right there. set-cdr of X to Y. X is\npresumably a CONS, a thing resulting from evaluating CONS. Therefore X comes from a\n\nplace over here, that that X is of the result of evaluating this lambda expression. Right?\nThat when I evaluated that lambda expression, I evaluated it in an environment where the\n\narguments to CONS were defined.\n\n\n\n\nThat means that as free variables in this lambda expression, there is the--there are in the\n\nframe, which is the parent frame of this lambda expression, the procedure resulting from\nthis lambda expression, X and Y have places. And it's possible to set them. I set them to an\nN, which is the argument of the permission. The permission is a procedure which is passed\n\nto M, which is the argument that the CONS object gets passed.\n\n\n\n\nNow, let's go back here in the set-cdr The CONS object, which is the first argument of set-\n\ncdr gets passed an argument. That--there's a procedure of four things, indeed, because\nthat's the same thing as this M over here, which is applied to four objects. The object over\n\nhere, SD, is, in fact, this permission. When I use SD, I apply it to Y, right there. So that\ncomes from this.\n\n\n\n\n\nAUDIENCE: So what do you--\n\n\n\n\nPROFESSOR: So to finish that, the N that was here is the Y which is here. How's that?\n\n\n\n\nAUDIENCE: Right, OK. Now, when you do a set-cdr, X is the value the CDR is going to\n\nbecome.\n\n\n\n\nPROFESSOR: The X over here. I'm sorry, that's not true. The X is--set-cdr has two\n\narguments-- The CONS I'm changing and the value I'm changing it to. So you have them\nbackwards, that's all. Are there any other questions? Well, thank you. It's time for lunc h.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec6a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 6A: Streams, Part 1\n\n\n\n1\n00:00:00,000 --> 00:00:18,550\n\n2\n00:00:18,550 --> 00:00:21,230\n教授：好的，上次Gerry教授揭晓了秘密。\nPROFESSOR: Well, last time Gerry\nreally let the cat out\n\n3\n00:00:21,230 --> 00:00:22,230\nof the bag.\n\n4\n00:00:22,230 --> 00:00:26,350\n他介绍赋值这个概念。\nHe introduced the idea\nof assignment.\n\n5\n00:00:26,350 --> 00:00:33,405\n赋值和状态。\nAssignment and state.\n\n6\n00:00:33,405 --> 00:00:37,620\n\n7\n00:00:37,620 --> 00:00:41,500\n就像我们看到的那样,把赋值和状态介绍\nAnd as we started to see, the\nimplications of introducing\n\n8\n00:00:41,500 --> 00:00:43,860\n进语言的含义是绝对惊世骇俗的\nassignment and state into the\nlanguage are absolutely\n\n9\n00:00:43,860 --> 00:00:45,350\nfrightening.\n\n10\n00:00:45,350 --> 00:00:47,240\n首先，计算的替换模型无法工作\nFirst of all, the substitution\nmodel of\n\n11\n00:00:47,240 --> 00:00:48,865\nevaluation breaks down.\n\n12\n00:00:48,865 --> 00:00:52,210\n我们就不得不使用更加复杂的环境模型\nAnd we have to use this much\nmore complicated environment\n\n13\n00:00:52,210 --> 00:00:53,780\n和这种带图解的机械化东西\nmodel and this very mechanistic\nthing with\n\n14\n00:00:53,780 --> 00:00:56,530\n甚至说明了声明在编程语言中的意思\ndiagrams, even to say what\nstatements in the programming\n\n15\n00:00:56,530 --> 00:00:58,130\nlanguage mean.\n\n16\n00:00:58,130 --> 00:01:00,260\n那不仅仅是技术上的一点\nAnd that's not a mere\ntechnical point.\n\n17\n00:01:00,260 --> 00:01:03,090\n看 我们没有这样特定的替换模型\nSee, it's not that we had this\nparticular substitution model\n\n18\n00:01:03,090 --> 00:01:05,200\n并且 这不能完全工作\nand, well, it doesn't quite\nwork, so we have to do\n\n19\n00:01:05,200 --> 00:01:05,870\n所以我们不得不做些别的\nsomething else.\n\n20\n00:01:05,870 --> 00:01:10,730\n替换模型啥都不能做\nIt's that nothing like the\nsubstitution model can work.\n\n21\n00:01:10,730 --> 00:01:15,950\n因为突然地，一个变量无法代表一个值\nBecause suddenly, a variable\nis not just something that\n\n22\n00:01:15,950 --> 00:01:18,080\nstands for a value.\n\n23\n00:01:18,080 --> 00:01:22,390\n一个变量现在不得不以某种方法来指定一个位置来存放一个值\nA variable now has to somehow\nspecify a place\n\n24\n00:01:22,390 --> 00:01:23,630\nthat holds a value.\n\n25\n00:01:23,630 --> 00:01:25,885\n在那个地方的值可以改变\nAnd the value that's in\nthat place can change.\n\n26\n00:01:25,885 --> 00:01:30,280\n\n27\n00:01:30,280 --> 00:01:39,110\n或者举个例子，，一个类似fx的表达式可能有副作用\nOr for instance, an expression\nlike f of x might have a side\n\n28\n00:01:39,110 --> 00:01:40,410\neffect in it.\n\n29\n00:01:40,410 --> 00:01:44,160\n所以如果我们说f（x）可以得到某些值\nSo if we say f of x and it has\nsome value, and then later we\n\n30\n00:01:44,160 --> 00:01:48,890\n那么然后 我们再求一次f（x）可能会得到一个取决于顺序的不同结果\nsay f of x again, we might\nget a different value\n\n31\n00:01:48,890 --> 00:01:49,730\ndepending on the order.\n\n32\n00:01:49,730 --> 00:01:52,780\n所以 突然地 我们不但需要想到值，还要想的时间\nSo suddenly, we have to think\nnot only about values but\n\n33\n00:01:52,780 --> 00:01:54,030\nabout time.\n\n34\n00:01:54,030 --> 00:01:57,970\n\n35\n00:01:57,970 --> 00:02:02,070\n并且 像序对这样的东西，已经不再是它们的cars\nAnd then things like pairs are\nno longer just their CARs and\n\n36\n00:02:02,070 --> 00:02:02,520\n和cdrs了\ntheir CDRs.\n\n37\n00:02:02,520 --> 00:02:06,310\n一个序对现在不仅仅是它的car和cdr了\nA pair now is not quite its CAR\nand its CDR. It's rather\n\n38\n00:02:06,310 --> 00:02:08,449\n而是它的“同一”\nits identity.\n\n39\n00:02:08,449 --> 00:02:11,650\n所以一个序对有“同一”\nSo a pair has identity.\n\n40\n00:02:11,650 --> 00:02:12,900\n这是一个对象\nIt's an object.\n\n41\n00:02:12,900 --> 00:02:21,330\n\n42\n00:02:21,330 --> 00:02:26,280\n两个有相同car和cdr的序列可能相同或不同\nAnd two pairs that have the same\nCAR and CDR might be the\n\n43\n00:02:26,280 --> 00:02:29,650\n因为 突然地 我们不得不担心“共享”\nsame or different, because\nsuddenly we have to worry\n\n44\n00:02:29,650 --> 00:02:30,900\nabout sharing.\n\n45\n00:02:30,900 --> 00:02:34,960\n\n46\n00:02:34,960 --> 00:02:38,910\n所以所有的这些东西和赋值一起被介绍\nSo all of these things enter\nas soon as we introduce\n\n47\n00:02:38,910 --> 00:02:40,480\nassignment.\n\n48\n00:02:40,480 --> 00:02:43,340\n这和我们说代换的时候差别悬殊\nSee, this is a really far cry\nfrom where we started with\n\n49\n00:02:43,340 --> 00:02:45,400\nsubstitution.\n\n50\n00:02:45,400 --> 00:02:50,420\n这是在技术上更加困难的一种看待事情的方法\nIt's a technically harder way\nof looking at things because\n\n51\n00:02:50,420 --> 00:02:52,710\n因为 我们不得不更加机械地思考我们的程序语言\nwe have to think more\nmechanistically about our\n\n52\n00:02:52,710 --> 00:02:53,540\nprogramming language.\n\n53\n00:02:53,540 --> 00:02:55,960\n我们不能仅仅的用数学来思考它。\nWe can't just think about\nit as mathematics.\n\n54\n00:02:55,960 --> 00:02:59,860\n这在哲学上更加困难  因为突然 这里会出现一些\nIt's philosophically harder,\nbecause suddenly there are all\n\n55\n00:02:59,860 --> 00:03:02,020\n搞笑的问题 关于一些东西改变或者这两个东西是一样的是什么意思\nthese funny issues about what\ndoes it mean that something\n\n56\n00:03:02,020 --> 00:03:04,050\nchanges or that two things\nare the same.\n\n57\n00:03:04,050 --> 00:03:07,910\n并且 这在编程上更加困难\nAnd also, it's programming\nharder, because as Gerry\n\n58\n00:03:07,910 --> 00:03:10,070\n因为就像Gerry上次展示的那样\nshowed last time, there are all\nthese bugs having to do\n\n59\n00:03:10,070 --> 00:03:14,420\n在一种我们不用担心对象的语言中不存在 那些由别名和坏的顺序造成的bugs\nwith bad sequencing and aliasing\nthat just don't exist\n\n60\n00:03:14,420 --> 00:03:18,210\n\nin a language where we don't\nworry about objects.\n\n61\n00:03:18,210 --> 00:03:23,635\n我们是怎样陷入这样的困境呢\nWell, how'd we get\ninto this mess?\n\n62\n00:03:23,635 --> 00:03:27,500\n记住我们以前做的 我们陷入困境的原因是\nRemember what we did, the reason\nwe got into this is\n\n63\n00:03:27,500 --> 00:03:35,750\n因为我们想要去建造模块化的系统\nbecause we were looking to\nbuild modular systems. We\n\n64\n00:03:35,750 --> 00:03:40,250\n我们想要建造一个看起来自然崩碎的数据块\nwanted to build systems that\nfall apart into chunks that\n\n65\n00:03:40,250 --> 00:03:42,760\nseem natural.\n\n66\n00:03:42,760 --> 00:03:46,260\n举个例子 我们想要拿一个随机数生成器\nSo for instance, we want to take\na random number generator\n\n67\n00:03:46,260 --> 00:03:48,660\n并打包那个随机数生成器的状态\nand package up the state of that\nrandom number generator\n\n68\n00:03:48,660 --> 00:03:52,840\n我们可以把用蒙特卡罗方法生成随机数\ninside of it so that we can\nseparate the idea of picking\n\n69\n00:03:52,840 --> 00:03:56,640\n的计算过程和随机数按照\nrandom numbers from the general\nMonte Carlo strategy\n\n70\n00:03:56,640 --> 00:03:59,740\ncesaro的公式计算pi的计算过程分离开\nof estimating something and\nseparate that from the\n\n71\n00:03:59,740 --> 00:04:03,060\nparticular way that you work\nwith random numbers in that\n\n72\n00:04:03,060 --> 00:04:06,980\nformula developed by\nCesaro for pi.\n\n73\n00:04:06,980 --> 00:04:11,400\n相似的 当我们动身去构建一些东西的模型\nAnd similarly, when we go off\nand construct some models of\n\n74\n00:04:11,400 --> 00:04:15,440\n如果我们动身去构建一个我们在现实看到的系统模型\nthings, if we go off and model\na system that we see in the\n\n75\n00:04:15,440 --> 00:04:19,050\n我们想要把我们的程序分散为自然的元件\nreal world, we'd like our\nprogram to break into natural\n\n76\n00:04:19,050 --> 00:04:22,310\n来反映我们在真实世界看到的系统的部分\npieces, pieces that mirror the\nparts of the system that we\n\n77\n00:04:22,310 --> 00:04:24,900\nsee in the real world.\n\n78\n00:04:24,900 --> 00:04:28,780\n所以举一个例子 如果我们看一下这个电子电路\nSo for example, if we look at\na digital circuit, we say,\n\n79\n00:04:28,780 --> 00:04:33,910\n我们可以说 挖 这里有一个电路 它这里有一个元件\ngee, there's a circuit and\nit has a piece and\n\n80\n00:04:33,910 --> 00:04:35,160\n并且那里还有一个另一个元件\nit has another piece.\n\n81\n00:04:35,160 --> 00:04:40,100\n\n82\n00:04:40,100 --> 00:04:43,580\n这些不同的元件在某种程度上有“同一”\nAnd these different pieces\nsort of have identity.\n\n83\n00:04:43,580 --> 00:04:45,550\n它们有状态\nThey have state.\n\n84\n00:04:45,550 --> 00:04:48,580\n状态附在电线上\nAnd the state sits\non these wires.\n\n85\n00:04:48,580 --> 00:04:51,020\n我们把这个元件看成一个不同于其他对象的对象\nAnd we think of this piece as\nan object that's different\n\n86\n00:04:51,020 --> 00:04:52,610\nfrom that as an object.\n\n87\n00:04:52,610 --> 00:04:54,400\n当我们看到系统改变时 \nAnd when we watch the system\nchange, we think about a\n\n88\n00:04:54,400 --> 00:04:57,500\n我们想着 信号从这里过来 并且可能在这里改变了一个状态\nsignal coming in here and\nchanging a state that might be\n\n89\n00:04:57,500 --> 00:04:59,860\n并且到了这里 与一个可能储存在这里的状态相互作用\nhere and going here and\ninteracting with a state that\n\n90\n00:04:59,860 --> 00:05:02,170\n等等等等\nmight be stored there,\nand so on and so on.\n\n91\n00:05:02,170 --> 00:05:06,860\n\n92\n00:05:06,860 --> 00:05:12,760\n所以我们想要做的是 我们想要建立一个分散为许多元件的计算机系统来映射我们对现实的观念\nSo what we'd like is we'd like\nto build in the computer\n\n93\n00:05:12,760 --> 00:05:17,340\n\nsystems that fall into pieces\nthat mirror our view of\n\n94\n00:05:17,340 --> 00:05:19,870\n我们构造的真实系统看起来变为许多元件\nreality, of the way that the\nactual systems we're modeling\n\n95\n00:05:19,870 --> 00:05:23,365\nseem to fall into pieces.\n\n96\n00:05:23,365 --> 00:05:28,970\n好吧  可能像这样构建系统的原因\nWell, maybe the reason that\nbuilding systems like this\n\n97\n00:05:28,970 --> 00:05:31,600\n看起来介绍如此复杂的科技对计算机没有用\nseems to introduce such\ntechnical complications has\n\n98\n00:05:31,600 --> 00:05:33,610\nnothing to do with computers.\n\n99\n00:05:33,610 --> 00:05:37,960\n看，或许我们付出了这样的代价去写我们对现实的反映程序\nSee, maybe the real reason that\nwe pay such a price to\n\n100\n00:05:37,960 --> 00:05:41,910\n是我们有对现实错误的理解\nwrite programs that mirror our\nview of reality is that we\n\n101\n00:05:41,910 --> 00:05:44,550\nhave the wrong view\nof reality.\n\n102\n00:05:44,550 --> 00:05:47,460\n看 或许时间仅仅是错觉\nSee, maybe time is just\nan illusion, and\n\n103\n00:05:47,460 --> 00:05:50,150\n什么东西都没有改变\nnothing ever changes.\n\n104\n00:05:50,150 --> 00:05:52,910\n看 打个比方 如果我拿起这支粉笔，然后说\nSee, for example, if I take this\nchalk, and we say, gee,\n\n105\n00:05:52,910 --> 00:05:55,820\n挖  这是一个对象 并且它有状态\nthis is an object and\nit has a state.\n\n106\n00:05:55,820 --> 00:05:59,710\n在每个时刻 它有位置和速度\nAt each moment it has a position\nand a velocity.\n\n107\n00:05:59,710 --> 00:06:01,240\n如果我们对它做了一些事情 它的状态就会改变\nAnd if we do something,\nthat state can change.\n\n108\n00:06:01,240 --> 00:06:04,340\n\n109\n00:06:04,340 --> 00:06:07,900\n但是如果你学习过相对论 比如\nBut if you studied any\nrelativity, for instance, you\n\n110\n00:06:07,900 --> 00:06:09,760\n你知道 你不会认为粉笔的路径如同某些东西\nknow that you don't think of\nthe path of that chalk as\n\n111\n00:06:09,760 --> 00:06:11,340\n随着时间运动\nsomething that goes on\ninstant by instant.\n\n112\n00:06:11,340 --> 00:06:13,870\n把整个粉笔的存在性作为时空中的路径是很有见解的\nIt's more insightful to think\nof that whole chalk's\n\n113\n00:06:13,870 --> 00:06:16,020\nexistence as a path\nin space-time.\n\n114\n00:06:16,020 --> 00:06:18,040\n那全部张开了\nthat's all splayed out.\n\n115\n00:06:18,040 --> 00:06:19,840\n这里没有单体的位置和速度\nThere aren't individual\npositions and velocities.\n\n116\n00:06:19,840 --> 00:06:24,640\n这里仅仅是 在时空中它们的不变的存在性\nThere's just its unchanging\nexistence in space-time.\n\n117\n00:06:24,640 --> 00:06:28,080\n相似的，如果我们看这些电子系统\nSimilarly, if we look at this\nelectrical system, if we\n\n118\n00:06:28,080 --> 00:06:32,450\n如果我们想象这些电子系统是一个实现一些类似信号处理系统\nimagine this electrical system\nis implementing some sort of\n\n119\n00:06:32,450 --> 00:06:35,730\n把这些东西放在一起的信号处理工程师\nsignal processing system, the\nsignal processing engineer who\n\n120\n00:06:35,730 --> 00:06:39,010\n不这样想\nput that thing together doesn't\nthink of it as, well,\n\n121\n00:06:39,010 --> 00:06:41,490\n好吧 在每个瞬间 这里有电压过来\nat each instance there's\na voltage coming in.\n\n122\n00:06:41,490 --> 00:06:43,340\n并且转换成了某些东西\nAnd that translates\ninto something.\n\n123\n00:06:43,340 --> 00:06:46,400\n这在这里影响了状态，在这里改变了状态\nAnd that affects the state over\nhere, which changes the\n\n124\n00:06:46,400 --> 00:06:46,810\nstate over here.\n\n125\n00:06:46,810 --> 00:06:49,060\n把信号处理系统放在一起的人中没有人会这么想\nNobody putting together a\nsignal processing system\n\n126\n00:06:49,060 --> 00:06:50,420\nthinks about it like that.\n\n127\n00:06:50,420 --> 00:06:56,830\n作为代替 你说这里有信号在时间上伸展\nInstead, you say there's\nthis signal that's\n\n128\n00:06:56,830 --> 00:06:58,060\nsplayed out over time.\n\n129\n00:06:58,060 --> 00:07:01,100\n如果 这表现的像filter 这整个东西\nAnd if this is acting as a\nfilter, this whole thing\n\n130\n00:07:01,100 --> 00:07:09,570\n转换了这整个东西为了一些其他的输出\ntransforms this whole thing for\nsome sort of other output.\n\n131\n00:07:09,570 --> 00:07:11,790\n你不会把它想成状态随着时间的变化\nYou don't think of it as what's\nhappening instant by\n\n132\n00:07:11,790 --> 00:07:14,160\ninstant as the state\nof these things.\n\n133\n00:07:14,160 --> 00:07:17,990\n以某种方式 你把这个盒子做为一整个东西\nAnd somehow you think of this\nbox as a whole thing, not as\n\n134\n00:07:17,990 --> 00:07:20,980\n而不是一个个在某个特定时刻互相传递状态的元件\nlittle pieces sending messages\nof state to each other at\n\n135\n00:07:20,980 --> 00:07:22,230\n\nparticular instants.\n\n136\n00:07:22,230 --> 00:07:28,250\n\n137\n00:07:28,250 --> 00:07:30,130\n现在 我们准备用另一种比思考交流传递信息的物体更加像信号处理工程师看待世界的方式去分解系统\nWell, today we're going to\nlook at another way to\n\n138\n00:07:30,130 --> 00:07:34,260\n\ndecompose systems that's more\nlike the signal processing\n\n139\n00:07:34,260 --> 00:07:37,050\n\nengineer's view of the world\nthan it is like thinking about\n\n140\n00:07:37,050 --> 00:07:41,130\nobjects that communicate\nsending messages.\n\n141\n00:07:41,130 --> 00:07:43,310\n那个被叫做流处理\nThat's called stream\nprocessing.\n\n142\n00:07:43,310 --> 00:07:54,570\n\n143\n00:07:54,570 --> 00:08:01,790\n我们打算开始展示我们如何编写更加均匀的程序\nAnd we're going to start by\nshowing how we can make our\n\n144\n00:08:01,790 --> 00:08:08,550\n并且看更多的共性\nprograms more uniform and see\na lot more commonality if we\n\n145\n00:08:08,550 --> 00:08:12,490\n如果我们抛出这些程序\nthrow out of these programs\nwhat you might say is an\n\n146\n00:08:12,490 --> 00:08:17,210\n你们可能说的是对时间的过度关心\ninordinate concern with\nworrying about time.\n\n147\n00:08:17,210 --> 00:08:19,910\n让我们用对比两个过程来开始\nLet me start by comparing\ntwo procedures.\n\n148\n00:08:19,910 --> 00:08:23,260\n\n149\n00:08:23,260 --> 00:08:25,690\n第一个做了这些\nThe first one does this.\n\n150\n00:08:25,690 --> 00:08:27,770\n我们想象这里有棵树\nWe imagine that there's\na tree.\n\n151\n00:08:27,770 --> 00:08:30,400\n\n152\n00:08:30,400 --> 00:08:33,179\n假定这是一个整数的树\nSay there's a tree\nof integers.\n\n153\n00:08:33,179 --> 00:08:34,429\n这是一个二叉树\nIt's a binary tree.\n\n154\n00:08:34,429 --> 00:08:39,100\n\n155\n00:08:39,100 --> 00:08:40,230\n所以这长得像这样\nSo it looks like this.\n\n156\n00:08:40,230 --> 00:08:44,990\n并且 在每个树的节点上有整数\nAnd there's integers in\neach of the nodes.\n\n157\n00:08:44,990 --> 00:08:51,000\n我们将要计算的事 对于每个在这里的奇数\nAnd what we would like to\ncompute is for each odd number\n\n158\n00:08:51,000 --> 00:08:54,210\n我们想要得到它们的平方 然后再得到它们基于平方的和\nsitting here, we'd like to find\nthe square and then sum\n\n159\n00:08:54,210 --> 00:08:57,210\nup all those squares.\n\n160\n00:08:57,210 --> 00:08:59,480\n好吧 那应该是很常见的东西\nWell, that should be a familiar\nkind of thing.\n\n161\n00:08:59,480 --> 00:09:02,930\n做这个我们有一个递归策略\nThere's a recursive strategy\nfor doing it.\n\n162\n00:09:02,930 --> 00:09:04,880\n我们看每个叶子\nWe look at each leaf, and\neither it's going to\n\n163\n00:09:04,880 --> 00:09:06,690\n它们要么贡献数字的平方\ncontribute the square of\nthe number if it's odd\n\n164\n00:09:06,690 --> 00:09:08,680\n如果它是奇数或者 如果是偶数那么就是0\nor 0 if it's even.\n\n165\n00:09:08,680 --> 00:09:13,280\n然后做递归，我们可以说在每个树上\nAnd then recursively, we can say\nat each tree, the sum of\n\n166\n00:09:13,280 --> 00:09:15,330\n所有东西的和是从右括号到左括号\nall of them is the sum coming\nfrom the right branch and the\n\n167\n00:09:15,330 --> 00:09:17,640\n然后随着叶的节点向下递归\nleft branch, and recursively\ndown through the nodes.\n\n168\n00:09:17,640 --> 00:09:20,360\n这是一个很常见的方法去思考编程\nAnd that's a familiar way of\nthinking about programming.\n\n169\n00:09:20,360 --> 00:09:23,960\n让我们看一下课件\nLet's actually look at\nthat on the slide.\n\n170\n00:09:23,960 --> 00:09:27,960\n我们说 在树上求奇数平方的和 好吧\nWe say to sum the odd squares\nin a tree, well, there's a\n\n171\n00:09:27,960 -—> 00:09:30,520\n这里有一个测试 要么这是叶节点 并且我们将要去检查 看看它是不是整数\ntest. Either it's a leaf node,\nand we're going to check to\n\n172\n00:09:30,520 --> 00:09:34,710\n然后要么这是奇数 我们把它平方 要么就是0\nsee if it's an integer, and then\neither it's odd, in which\n\n173\n00:09:34,710 --> 00:09:37,160\nwe take the square,\nor else it's 0.\n\n174\n00:09:37,160 --> 00:09:40,260\n然后 所有东西加起来的和是来自左右括号的和\nAnd then the sum of the whole\nthing is the sum coming from\n\n175\n00:09:40,260 --> 00:09:42,120\nthe left branch and\nthe right branch.\n\n176\n00:09:42,120 --> 00:09:46,340\n\n177\n00:09:46,340 --> 00:09:51,560\n好的 让我们用第二个问题来对比\nOK, well, let me contrast that\nwith a second problem.\n\n178\n00:09:51,560 --> 00:09:55,810\n假设我给你一个整数n \nSuppose I give you an integer\nn, and then some function to\n\n179\n00:09:55,810 --> 00:09:59,270\n然后再给出一些函数来计算第一个每个在1到n中整数\ncompute of the first of each\ninteger in 1 through n.\n\n180\n00:09:59,270 --> 00:10:01,810\n然后 我想要将它们这些满足一些性质的所有函数值收集起来放到列表中\nAnd then I want to collect\ntogether in a list all those\n\n181\n00:10:01,810 --> 00:10:05,600\nfunction values that satisfy\nsome property.\n\n182\n00:10:05,600 --> 00:10:06,880\n就是这样\nThat's a general\nkind of thing.\n\n183\n00:10:06,880 --> 00:10:09,750\n让我们说得具体点 让我们想象\nLet's say to be specific, let's\nimagine that for each\n\n184\n00:10:09,750 --> 00:10:11,270\n对于每个整数k 我们将要\ninteger, k, we're\ngoing to compute\n\n185\n00:10:11,270 --> 00:10:14,210\n计算出第k个斐波那契数\nthe k Fibonacci number.\n\n186\n00:10:14,210 --> 00:10:17,550\n然后我们将会看到哪些是奇数\nAnd then we'll see which of\nthose are odd and assemble\n\n187\n00:10:17,550 --> 00:10:19,050\n并将其分配进列表\nthose into a list.\n\n188\n00:10:19,050 --> 00:10:20,710\n这里有一个可以做上面这件事的过程\nSo here's a procedure\nthat does that.\n\n189\n00:10:20,710 --> 00:10:23,730\n\n190\n00:10:23,730 --> 00:10:26,240\n在第一个n之中 找到奇的斐波那契数\nFind the odd Fibonacci numbers\namong the first n.\n\n191\n00:10:26,240 --> 00:10:28,910\n这是我们写的标准循环方法\nAnd here is a standard loop the\nway we've been writing it.\n\n192\n00:10:28,910 --> 00:10:30,800\n这是一个递归\nThis is a recursion.\n\n193\n00:10:30,800 --> 00:10:33,740\n这是一个在k上的循环 我们可以说 如果k比n大\nIt's a loop on k, and says if\nk is bigger than n, it's the\n\n194\n00:10:33,740 --> 00:10:36,990\n这将会是一个空列表 否则我们将会求出第k个斐波那契数\nempty list. Otherwise we compute\nthe k-th Fibonacci\n\n195\n00:10:36,990 --> 00:10:40,370\n把那个叫做f\nnumber, call that f.\n\n196\n00:10:40,370 --> 00:10:45,180\n如果这是一个奇数 我们可以使用cons将其变成list\nIf it's odd, we CONS it on\nto the list starting\n\n197\n00:10:45,180 --> 00:10:47,690\n并以下一个作为开始\nwith the next one.\n\n198\n00:10:47,690 --> 00:10:50,390\n否则 我们就取下一个数字\nAnd otherwise, we just\ntake the next one.\n\n199\n00:10:50,390 --> 00:10:52,000\n这是一个写iterative loop的标准方法\nAnd this is the standard\nway we've been\n\n200\n00:10:52,000 --> 00:10:53,000\nwriting iterative loops.\n\n201\n00:10:53,000 --> 00:10:57,600\n我们用1来开始循环\nAnd we start off calling\nthat loop with 1.\n\n202\n00:10:57,600 --> 00:11:01,600\n所以我们现在有两个过程\nOK, so there are\ntwo procedures.\n\n203\n00:11:01,600 --> 00:11:02,900\n这两个过程看起来很不同\nThose procedures look\nvery different.\n\n204\n00:11:02,900 --> 00:11:04,390\n他们有两个非常不同的结构\nThey have very different\nstructures.\n\n205\n00:11:04,390 --> 00:11:07,740\n但在某些程度上\nYet from a certain point of\nview, those procedures are\n\n206\n00:11:07,740 --> 00:11:11,330\n那些过程做了相同的事\nreally doing very much\nthe same thing.\n\n207\n00:11:11,330 --> 00:11:14,930\n所以 如果我像信号处理工程师那样说话的话\nSo if I was talking like a\nsignal processing engineer,\n\n208\n00:11:14,930 --> 00:11:25,730\n我会说的可能是第一个过程\nwhat I might say is that the\nfirst procedure enumerates the\n\n209\n00:11:25,730 --> 00:11:26,980\nenumerate了树中的例子\nleaves of a tree.\n\n210\n00:11:26,980 --> 00:11:31,160\n\n211\n00:11:31,160 --> 00:11:33,510\n然后 我们可以想象 一个信号从那里出来\nAnd then we can think of a\nsignal coming out of that,\n\n212\n00:11:33,510 --> 00:11:35,330\n它是所有的树节点\nwhich is all the leaves.\n\n213\n00:11:35,330 --> 00:11:43,970\n我们将会对其进行filter 看看哪些是奇数\nWe'll filter them to see which\nones are odd, put them through\n\n214\n00:11:43,970 --> 00:11:45,190\n把这些放进类似的filter\nsome kind of filter.\n\n215\n00:11:45,190 --> 00:11:49,000\n我们将会把它们放入transducer\nWe'll then put them through\na kind of transducer.\n\n216\n00:11:49,000 --> 00:11:51,420\n对于每个这样的东西 我们将会对其做平方运算\nAnd for each one of those\nthings, we'll take the square.\n\n217\n00:11:51,420 --> 00:11:54,200\n\n218\n00:11:54,200 --> 00:11:58,290\n然后我们会对所有的这些东西做累加操作\nAnd then we'll accumulate\nall of those.\n\n219\n00:11:58,290 --> 00:12:00,570\n我们将要把这些东西粘住通过从0开始的加法来累加它们\nWe'll accumulate them by\nsticking them together with\n\n220\n00:12:00,570 --> 00:12:03,340\naddition starting from 0.\n\n221\n00:12:03,340 --> 00:12:07,140\n\n222\n00:12:07,140 --> 00:12:08,210\n这是第一个程序\nThat's the first program.\n\n223\n00:12:08,210 --> 00:12:10,620\n第二个程序 我可以用极其相似的方法来形容\nThe second program, I can\ndescribe in a very, very\n\n224\n00:12:10,620 --> 00:12:11,780\nsimilar way.\n\n225\n00:12:11,780 --> 00:12:17,450\n我会说 我们将在这段1-n的区间中enumerate数字\nI'll say, we'll enumerate the\nnumbers on this interval, for\n\n226\n00:12:17,450 --> 00:12:19,080\n\nthe interval 1 through n.\n\n227\n00:12:19,080 --> 00:12:22,500\n\n228\n00:12:22,500 --> 00:12:28,080\n对于每一个 我们将要计算出斐波那契数\nWe'll, for each one, compute the\nFibonacci number, put them\n\n229\n00:12:28,080 --> 00:12:29,270\n并把它们放进transducer中\nthrough a transducer.\n\n230\n00:12:29,270 --> 00:12:31,780\n我们将会得到相应的结果\nWe'll then take the result\nof that, and we'll\n\n231\n00:12:31,780 --> 00:12:35,976\n并且我们将会为了奇数性而filter它\nfilter it for oddness.\n\n232\n00:12:35,976 --> 00:12:39,35\n然后我门把它们放进accumulator\nAnd then we'll take those and\nput them into an accumulator.\n\n233\n00:12:39,350 --> 00:12:41,730\n这回 我们将会做一个列表\nThis time we'll build up a list,\nso we'll accumulate with\n\n234\n00:12:41,730 --> 00:12:47,110\n所以 我们将会用cons从空列表中进行累加\nCONS starting from\nthe empty list.\n\n235\n00:12:47,110 --> 00:12:50,940\n所以 从这个角度看程序 使这两个程序\nSo this way of looking at the\nprogram makes the two seem\n\n236\n00:12:50,940 --> 00:12:51,900\n看起来非常相似\nvery, very similar.\n\n237\n00:12:51,900 --> 00:12:55,880\nThe problem is that that\ncommonality is completely\n\n238\n00:12:55,880 --> 00:12:58,050\n当我们看我们写的程序 这个问题的共同性是完全的被遮蔽的\nobscured when we look at the\nprocedures we wrote.\n\n239\n00:12:58,050 --> 00:13:02,670\n让我们返回 并再次查看一些奇数的平方\nLet's go back and look at some\nodd squares again, and say\n\n240\n00:13:02,670 --> 00:13:06,300\n然后说 enumerator在哪里\nthings like, where's\nthe enumerator?\n\n241\n00:13:06,300 --> 00:13:08,140\n在这个程序里 enumerator在哪里\nWhere's the enumerator\nin this program?\n\n242\n00:13:08,140 --> 00:13:11,230\n它不在一个地方\nWell, it's not in one place.\n\n243\n00:13:11,230 --> 00:13:15,990\n其中的一部分在这个左节点的测试中\nIt's a little bit in this\nleaf-node test,\n\n244\n00:13:15,990 --> 00:13:17,160\n这将要停止\nwhich is going to stop.\n\n245\n00:13:17,160 --> 00:13:19,380\n其中的一小部分在这个东西本身的递归结构中\nIt's a little bit in the\nrecursive structure of the\n\n246\n00:13:19,380 --> 00:13:20,630\nthing itself.\n\n247\n00:13:20,630 --> 00:13:23,150\n\n248\n00:13:23,150 --> 00:13:24,120\naccumulator在哪里\nWhere's the accumulator?\n\n249\n00:13:24,120 --> 00:13:25,680\naccumulator也不在一个地方\nThe accumulator isn't\nin one place either.\n\n250\n00:13:25,680 --> 00:13:32,180\n这东西的一部分在0这 一部分在加号\nIt's partly in this 0 and\npartly in this plus.\n\n251\n00:13:32,180 --> 00:13:34,510\n不在我们看到的那个东西那里\nIt's not there as a thing\nthat we can look at.\n\n252\n00:13:34,510 --> 00:13:40,550\n相似的 如果我们查看奇数斐波那契数\nSimilarly, if we look at odd\nFibs, that's also, in some\n\n253\n00:13:40,550 --> 00:13:42,940\n这在某些程度上 也是一个enumerator和一个accumulator\nsense, an enumerator and\nan accumulator, but\n\n254\n00:13:42,940 --> 00:13:44,470\n但这看起来不一样\nit looks very different.\n\n255\n00:13:44,470 --> 00:13:49,260\n因为部分地 enumerator在这测试中大于的符号\nBecause partly, the enumerator\nis here in this greater than\n\n256\n00:13:49,260 --> 00:13:52,100\n部分地 在整个循环的递归结构\nsign in the test. And partly\nit's in this whole recursive\n\n257\n00:13:52,100 --> 00:13:55,680\nstructure in the loop, and\nthe way that we call it.\n\n258\n00:13:55,680 --> 00:13:58,100\n相似得  accumulator也像这样混合在一起\nAnd then similarly, that's also\nmixed up in there with\n\n259\n00:13:58,100 --> 00:14:01,010\n部分的在这里 部分的在这里\nthe accumulator, which is partly\nover there and partly\n\n260\n00:14:01,010 --> 00:14:03,600\nover there.\n\n261\n00:14:03,600 --> 00:14:09,790\n所以 这些非常非常自然的元件\nSo these very, very natural\npieces, these very natural\n\n262\n00:14:09,790 --> 00:14:13,770\n这个很自然的盒子不会在我们的程序中出现\nboxes here don't appear in our\nprograms. Because they're kind\n\n263\n00:14:13,770 --> 00:14:14,360\n因为这些东西混合在一起了\nof mixed up.\n\n264\n00:14:14,360 --> 00:14:16,290\n程序没有正确地将东西切成小块\nThe programs don't chop things\nup in the right way.\n\n265\n00:14:16,290 --> 00:14:19,450\n\n266\n00:14:19,450 --> 00:14:22,240\n让我们回想一下计算机科学的基本定理\nGoing back to this fundamental\nprinciple of computer science\n\n267\n00:14:22,240 --> 00:14:24,620\n为了去控制某样东西 你需要\nthat in order to control\nsomething, you need the name\n\n268\n00:14:24,620 --> 00:14:27,820\n给它命名  我们真的在用这种方法来思考时没有控制\nof it, we don't really have\ncontrol over thinking about\n\n269\n00:14:27,820 --> 00:14:30,500\n因为显式上，我们在那里面没有我们的手\nthings this way because we don't\nhave our hands in them\n\n270\n00:14:30,500 --> 00:14:31,060\nexplicitly.\n\n271\n00:14:31,060 --> 00:14:35,510\n我们没有好的语言来说它们\nWe don't have a good language\nfor talking about them.\n\n272\n00:14:35,510 --> 00:14:42,850\n好吧 让我们发明一个合适的 可以建造这些元件的语言\nWell, let's invent an\nappropriate language in which\n\n273\n00:14:42,850 --> 00:14:44,515\nwe can build these pieces.\n\n274\n00:14:44,515 --> 00:14:48,650\n语言的关键是这些东西\nThe key to the language is these\nguys, is what is these\n\n275\n00:14:48,650 --> 00:14:50,480\n这是一个被我叫做信号的东西\nthings I called signals?\n\n276\n00:14:50,480 --> 00:14:52,070\n在盒子中的数组上面飞的东西是什么鬼\nWhat are these things that\nare flying on the\n\n277\n00:14:52,070 --> 00:14:53,320\narrows between the boxes?\n\n278\n00:14:53,320 --> 00:14:56,880\n\n279\n00:14:56,880 --> 00:15:02,840\n这些东西将变成一种叫流的数据结构\nWell, those things are going to\nbe data structures called\n\n280\n00:15:02,840 --> 00:15:04,770\n那将变成发明这个语言的关键\nstreams. That's going\nto be the key to\n\n281\n00:15:04,770 --> 00:15:07,980\ninventing this language.\n\n282\n00:15:07,980 --> 00:15:08,600\n什么是流\nWhat's a stream?\n\n283\n00:15:08,600 --> 00:15:10,820\n好吧 一个流是 像其他东西一样\nWell, a stream is, like\nanything else, a data\n\n284\n00:15:10,820 --> 00:15:12,220\n一个数据抽象\nabstraction.\n\n285\n00:15:12,220 --> 00:15:15,000\n所以我们应该告诉你什么是selectors\nSo I should tell you what\nits selectors and\n\n286\n00:15:15,000 --> 00:15:16,870\n什么是constructors\nconstructors are.\n\n287\n00:15:16,870 --> 00:15:20,185\n对于一个流 我们将会有一个constructor\nFor a stream, we're going to\nhave one constructor that's\n\n288\n00:15:20,185 --> 00:15:21,435\n叫做 cons流\ncalled CONS-stream.\n\n289\n00:15:21,435 --> 00:15:25,690\n\n290\n00:15:25,690 --> 00:15:29,060\ncons流将会将两个东西合在一起变为一个叫流的东西\nCONS-stream is going to put two\nthings together to form a\n\n291\n00:15:29,060 --> 00:15:32,040\nthing called a stream.\n\n292\n00:15:32,040 --> 00:15:34,250\n然后 从流中抽离东西\nAnd then to extract things from\nthe stream, we're going\n\n293\n00:15:34,250 --> 00:15:38,010\n我们将会有一个selector 被叫做流的头\nto have a selector called\nthe head of the stream.\n\n294\n00:15:38,010 --> 00:15:41,340\n所以如果我有一个流 我可以带这个头\nSo if I have a stream, I\ncan take its head or I\n\n295\n00:15:41,340 --> 00:15:44,720\n或者带这个尾\ncan take its tail.\n\n296\n00:15:44,720 --> 00:15:48,290\n请记住 我不得不在这里告诉你乔治的合同来告诉你\nAnd remember, I have to tell you\nGeorge's contract here to\n\n297\n00:15:48,290 --> 00:15:53,160\n什么是与这个相关的公理\ntell you what the axioms\nare that relate these.\n\n298\n00:15:53,160 --> 00:16:04,080\n对于所有的x和y\nAnd it's going to be for any\nx and y, if I form the\n\n299\n00:16:04,080 --> 00:16:11,420\n如果我造了一个con流并取其头  x和y的cons流的头\nCONS-stream and take the head,\nthe head of CONS-stream of x\n\n300\n00:16:11,420 --> 00:16:26,590\n将会变成x 并且x和y的cons流的尾将会变成y\nand y is going to be x and the\ntail of CONS-stream of x and y\n\n301\n00:16:26,590 --> 00:16:28,440\nis going to be y.\n\n302\n00:16:28,440 --> 00:16:31,180\n所以那些是对于流的constructor  对于流的2个selectors\nSo those are the constructor,\ntwo selectors for\n\n303\n00:16:31,180 --> 00:16:34,750\n和一条公理\nstreams, and an axiom.\n\n304\n00:16:34,750 --> 00:16:36,980\n这里有一些可疑\nThere's something fishy here.\n\n305\n00:16:36,980 --> 00:16:41,060\n你有可能发现这些完全是cons car cdr的公理\nSo you might notice that these\nare exactly the axioms for\n\n306\n00:16:41,060 --> 00:16:46,100\n如果写cons流\nCONS, CAR, and CDR. If instead\nof writing CONS-stream I wrote\n\n307\n00:16:46,100 --> 00:16:50,810\n并且我说头是car 尾是cdr\nCONS and I said head was the\nCAR and tail was the CDR,\n\n308\n00:16:50,810 --> 00:16:52,810\n这些完全是序对的公理\nthose are exactly the\naxioms for pairs.\n\n309\n00:16:52,810 --> 00:16:55,130\n事实上 这里还有另一个东西\nAnd in fact, there's\nanother thing here.\n\n310\n00:16:55,130 --> 00:17:02,930\n我们将会有一个像空列表的东西 叫空流\nWe're going to have a thing\ncalled the-empty-stream, which\n\n311\n00:17:02,930 --> 00:17:08,319\n像空列表\nis like the-empty-list.\n\n312\n00:17:08,319 --> 00:17:10,030\n为什么我介绍这个术语呢\nSo why am I introducing\nthis terminology?\n\n313\n00:17:10,030 --> 00:17:12,780\n为什么我不继续说序对和列表呢？\nWhy don't I just keep talking\nabout pairs and lists?\n\n314\n00:17:12,780 --> 00:17:15,510\n好吧 我们将会看到\nWell, we'll see.\n\n315\n00:17:15,510 --> 00:17:18,440\n就现在来说 如果你喜欢 为什么不把流假装\nFor now, if you like, why don't\nyou just pretend that\n\n316\n00:17:18,440 --> 00:17:21,560\n看成列表的一种术语\nstreams really are just a\nterminology for lists.\n\n317\n00:17:21,560 --> 00:17:24,890\n而且我们等等将会看到 为什么我们想要保持这个额外的抽象层\nAnd we'll see in a little while\nwhy we want to keep this\n\n318\n00:17:24,890 --> 00:17:28,150\n而不仅仅是叫这个为列表\nextra abstraction layer and\nnot just call them lists.\n\n319\n00:17:28,150 --> 00:17:32,300\n\n320\n00:17:32,300 --> 00:17:34,860\n好的 现在我们有了流 我们可以开始构建\nOK, now that we have streams, we\ncan start constructing the\n\n321\n00:17:34,860 --> 00:17:38,990\n语言的元件来作用在流上\npieces of the language to\noperate on streams. And there\n\n322\n00:17:38,990 --> 00:17:41,330\n有很多有用的东西我们可以开始做\nare a whole bunch of very useful\nthings that we could\n\n323\n00:17:41,330 --> 00:17:42,120\nstart making.\n\n324\n00:17:42,120 --> 00:17:54,850\n举个例子 我们将会做我们的map box 来带一个流s\nFor instance, we'll make our map\nbox to take a stream, s,\n\n325\n00:17:54,850 --> 00:18:00,400\n和一个过程 并且生成一个新的流\nand a procedure, and to generate\na new stream which\n\n326\n00:18:00,400 --> 00:18:03,640\n那过程作用在s所有的后继节点上\nhas as its elements the\nprocedure applied to all the\n\n327\n00:18:03,640 --> 00:18:05,666\n作用在s所有的后继节点上\nsuccessive elements of s.\n\n328\n00:18:05,666 --> 00:18:07,400\n事实上 我们已经见过了\nIn fact, we've seen\nthis before.\n\n329\n00:18:07,400 --> 00:18:10,950\n这是我们的过程 这个过程map\n了我们在列表中做的\nThis is the procedure map\nthat we did with lists.\n\n330\n00:18:10,950 --> 00:18:14,000\n你看 这完全是map 除了我们要对空流进行测试\nAnd you see it's exactly map,\nexcept we're testing for\n\n331\n00:18:14,000 --> 00:18:14,650\nempty-stream.\n\n332\n00:18:14,650 --> 00:18:15,560\n噢 我忘记说了\nOh, I forgot to mention that.\n\n333\n00:18:15,560 --> 00:18:19,420\n空流就像null测试 所以如果它是空的\nEmpty-stream is like the null\ntest. So if it's empty, we\n\n334\n00:18:19,420 --> 00:18:20,510\n我们生成新的空流\ngenerate the empty stream.\n\n335\n00:18:20,510 --> 00:18:24,700\n否则 我们做一个新的流 这个流的第一个元素\nOtherwise, we form a new stream\nwhose first element is\n\n336\n00:18:24,700 --> 00:18:28,950\n是过程作用在流的头\nthe procedure applied to the\nhead of the stream, and whose\n\n337\n00:18:28,950 --> 00:18:31,570\n剩下的将会沿着过程一直map到流的尾部\nrest is gotten by mapping along\nwith the procedure down\n\n338\n00:18:31,570 --> 00:18:33,140\nthe tail of the stream.\n\n339\n00:18:33,140 --> 00:18:34,920\n所以这和我们以前看过的map过程完全一样\nSo that looks exactly like\nthe map procedure\n\n340\n00:18:34,920 --> 00:18:37,030\nwe looked at before.\n\n341\n00:18:37,030 --> 00:18:38,350\n这里还有另一个有用的东西\nHere's another useful thing.\n\n342\n00:18:38,350 --> 00:18:40,460\nfilter 这是我们的filter box\nFilter, this is our\nfilter box.\n\n343\n00:18:40,460 --> 00:18:43,890\n我们将会有一个谓词和一个流\nWe're going to have a predicate\nand a stream.\n\n344\n00:18:43,890 --> 00:18:46,720\n我们将会做一个新的包涵所有的满足于谓语元素的流\nWe're going to make a new stream\nthat consists of all\n\n345\n00:18:46,720 --> 00:18:48,310\nthe elements of the\noriginal one\n\n346\n00:18:48,310 --> 00:18:50,160\nthat satisfy the predicate.\n\n347\n00:18:50,160 --> 00:18:51,270\n这里是案例分析\nThat's case analysis.\n\n348\n00:18:51,270 --> 00:18:53,140\n当在流中什么都没有\nWhen there's nothing\nin the stream, we\n\n349\n00:18:53,140 --> 00:18:56,280\n我返回一个空的流\nreturn the empty stream.\n\n350\n00:18:56,280 --> 00:19:00,060\n我们检测在流的头上的谓词\nWe test the predicate on\nthe head of the stream.\n\n351\n00:19:00,060 --> 00:19:03,520\n并且如果这是对的 我们将流的头加在\nAnd if it's true, we add the\nhead of the stream onto the\n\n352\n00:19:03,520 --> 00:19:08,220\nfilter流尾的结果\nresult of filtering the\ntail of the stream.\n\n353\n00:19:08,220 --> 00:19:10,870\n否则 如果那个谓词是错的\nAnd otherwise, if that predicate\nwas false, we just\n\n354\n00:19:10,870 --> 00:19:13,500\n我们只需要filter流的尾部\nfilter the tail of the stream.\n\n355\n00:19:13,500 --> 00:19:16,595\n是的 这里是filter\nRight, so there's filter.\n\n356\n00:19:16,595 --> 00:19:18,560\n让我快速的运行完这一对\nLet me run through a couple\nmore rather quickly.\n\n357\n00:19:18,560 --> 00:19:20,880\n这些在书里都有 你可以去看下\nThey're all in the book and\nyou can look at them.\n\n358\n00:19:20,880 --> 00:19:22,110\n让我们过一遍\nLet me just flash through.\n\n359\n00:19:22,110 --> 00:19:23,260\n这里是accumulate\nHere's accumulate.\n\n360\n00:19:23,260 --> 00:19:27,690\naccumulate使用一种连接的方式\nAccumulate takes a way of\ncombining things and an\n\n361\n00:19:27,690 --> 00:19:31,560\n将流中的初始值粘合在一起\ninitial value in a stream and\nsticks them all together.\n\n362\n00:19:31,560 --> 00:19:33,970\n如果流是空的 那么这仅仅是初始值\nIf the stream's empty, it's\njust the initial value.\n\n363\n00:19:33,970 --> 00:19:36,930\n否则 我们连接流的头和累加从初始值开始的流的尾部的结果\nOtherwise, we combine the head\nof the stream with the result\n\n364\n00:19:36,930 --> 00:19:39,550\nof accumulating the tail of the\nstream starting from the\n\n365\n00:19:39,550 --> 00:19:40,900\ninitial value.\n\n366\n00:19:40,900 --> 00:19:42,830\n所以 我们将会将所有东西都加进流\nSo that's what I'd use to add\nup everything in the stream.\n\n367\n00:19:42,830 --> 00:19:45,830\n我会使用加法来进行累加\nI'd accumulate with plus.\n\n368\n00:19:45,830 --> 00:19:48,060\n我如何enumerate树上的叶子呢\nHow would I enumerate the\nleaves of a tree?\n\n369\n00:19:48,060 --> 00:19:54,530\n如果树仅仅只是叶本身\nWell, if the tree is just a leaf\nitself, I make something\n\n370\n00:19:54,530 --> 00:19:56,640\n我制作一个只有节点的东西\nwhich only has that\nnode in it.\n\n371\n00:19:56,640 --> 00:20:01,100\n否则 我把从左括号到右括号的东西附加起来\nOtherwise, I append together the\nstuff of enumerating the\n\n372\n00:20:01,100 --> 00:20:04,340\nleft branch and the\nright branch.\n\n373\n00:20:04,340 --> 00:20:08,130\n然后 在这里附加就像普通在列表中的附加\nAnd then append here is like the\nordinary append on lists.\n\n374\n00:20:08,130 --> 00:20:13,190\n\n375\n00:20:13,190 --> 00:20:13,850\n你可以看这里\nYou can look at that.\n\n376\n00:20:13,850 --> 00:20:16,410\n这类似于普通附加两个列表的过程\nThat's analogous to the\nordinary procedure for\n\n377\n00:20:16,410 --> 00:20:19,150\nappending two lists.\n\n378\n00:20:19,150 --> 00:20:21,810\n我如何来enumerate间距\nHow would I enumerate\nan interval?\n\n379\n00:20:21,810 --> 00:20:24,500\n这将会用到两个数 一小一大\nThis will take two integers, low\nand high, and generate a\n\n380\n00:20:24,500 --> 00:20:28,106\n并且生成从小到大的整数流\nstream of the integers going\nfrom low to high.\n\n381\n00:20:28,106 --> 00:20:31,890\n然后我们可得到整个一串元件\nAnd we can make a whole\nbunch of pieces.\n\n382\n00:20:31,890 --> 00:20:34,860\n所以 那是我们说的流的一点点小语言\nSo that's a little language of\ntalking about streams. Once we\n\n383\n00:20:34,860 --> 00:20:37,670\n当我们有了流 我们可以制作东西来操纵它们\nhave streams, we can build\nthings for manipulating them.\n\n384\n00:20:37,670 --> 00:20:40,200\n再说一下 我们正在制作语言\nAgain, we're making\na language.\n\n385\n00:20:40,200 --> 00:20:41,270\n现在我们可以用这种语言来表达东西\nAnd now we can start expressing\n\n386\n00:20:41,270 --> 00:20:43,060\nthings in this language.\n\n387\n00:20:43,060 --> 00:20:46,590\n这里是在树中累加奇数平方的原始过程\nHere's our original procedure\nfor summing the odd\n\n388\n00:20:46,590 --> 00:20:47,310\nsquares in a tree.\n\n389\n00:20:47,310 --> 00:20:52,210\n你将会注意到 这完全像方框图\nAnd you'll notice it looks\nexactly now like the block\n\n390\n00:20:52,210 --> 00:20:54,590\n像信号处理中的方框图\ndiagram, like the signal\nprocessing block diagram.\n\n391\n00:20:54,590 --> 00:21:00,230\n所以把奇数的平方在树中求和\nSo to sum the odd squares in a\ntree, we enumerate the leaves\n\n392\n00:21:00,230 --> 00:21:01,320\n我们enumerate了数中的叶子\nof the tree.\n\n393\n00:21:01,320 --> 00:21:04,830\n我们为了保持奇数性进行filter\nWe filter that for oddness.\n\n394\n00:21:04,830 --> 00:21:06,220\n我们为了平方性进行map\nWe map that for squareness.\n\n395\n00:21:06,220 --> 00:21:09,320\n\n396\n00:21:09,320 --> 00:21:12,460\n并且我们使用加法对结果进行累加\nAnd we accumulate the result\nof that using addition,\n\n397\n00:21:12,460 --> 00:21:14,760\n从0开始\nstarting from 0.\n\n398\n00:21:14,760 --> 00:21:17,290\n所以我们可以看到我们想要的元件\nSo we can see the pieces\nthat we wanted.\n\n399\n00:21:17,290 --> 00:21:22,050\n相似的 斐波那契数 我们怎样得到奇数的斐波那契数\nSimilarly, the Fibonacci one,\nhow do we get the odd Fibs?\n\n400\n00:21:22,050 --> 00:21:27,900\n我们从1到n枚举间距 并沿着那里进行map\nWell, we enumerate the interval\nfrom 1 to n, we map\n\n401\n00:21:27,900 --> 00:21:30,920\n计算每个的斐波那契数\nalong that, computing the\nFibonacci of each one.\n\n402\n00:21:30,920 --> 00:21:34,810\n我们为了奇数性对那些结果进行filter\nWe filter the result of\nthose for oddness.\n\n403\n00:21:34,810 --> 00:21:38,460\n并且我们使用从空列表开始的cons累积了所有的这些东西\nAnd we accumulate all of that\nstuff using CONS starting from\n\n404\n00:21:38,460 --> 00:21:43,650\nthe empty-list.\n\n405\n00:21:43,650 --> 00:21:47,680\n好吧 那这个有神马优势\nOK, what's the advantage\nof this?\n\n406\n00:21:47,680 --> 00:21:50,260\n嗯 首先 我们现在有元件 并且我们可以开始\nWell, for one thing, we now have\npieces that we can start\n\n407\n00:21:50,260 --> 00:21:51,880\n混合和匹配\nmixing and matching.\n\n408\n00:21:51,880 --> 00:21:58,230\n举个例子 如果我想要改变它\nSo for instance, if I wanted to\nchange this, if I wanted to\n\n409\n00:21:58,230 --> 00:22:00,400\n如果我想要得到整数的平方 然后进行filter\ncompute the squares of the\nintegers and then filter them,\n\n410\n00:22:00,400 --> 00:22:03,810\n我需要做的是从那个平方中拿起像这样的标准元件 然后放进去\nall I need to do is pick up a\nstandard piece like this in\n\n411\n00:22:03,810 --> 00:22:06,210\nthat square and put it in.\n\n412\n00:22:06,210 --> 00:22:10,150\n或者 如果我们想要计算整个在树上的斐波那契计算而不是一个序列\nOr if we wanted to do this whole\nFibonacci computation on\n\n413\n00:22:10,150 --> 00:22:12,980\n\nthe leaves of a tree rather than\na sequence, all I need to\n\n414\n00:22:12,980 --> 00:22:18,030\n我需要做的是用那个替换这个enumerator\ndo is replace this enumerator\nwith that one.\n\n415\n00:22:18,030 --> 00:22:20,650\n看 流处理的优势是\nSee, the advantage of this\nstream processing is that\n\n416\n00:22:20,650 --> 00:22:21,995\n我们建立了－－\nwe're establishing--\n\n417\n00:22:21,995 --> 00:22:25,330\n这是我们课程中一个比较大的课题\nthis is one of the big themes\nof the course--\n\n418\n00:22:25,330 --> 00:22:35,570\n我们正在建立符合我们直觉的接口 并且这个接口允许我们把东西粘在一起\nwe're establishing conventional\ninterfaces that\n\n419\n00:22:35,570 --> 00:22:38,130\nallow us to glue things\ntogether.\n\n420\n00:22:38,130 --> 00:22:41,730\n像map和filter这样的东西是一个标准的组件集合\nThings like map and filter are\na standard set of components\n\n421\n00:22:41,730 --> 00:22:43,900\n我们可以开始使用这个 并用各种各样的方法去粘合程序\nthat we can start using for\npasting together programs in\n\n422\n00:22:43,900 --> 00:22:45,750\nall sorts of ways.\n\n423\n00:22:45,750 --> 00:22:50,090\n这让我们看到程序的共性\nIt allows us to see the\ncommonality of programs.\n\n424\n00:22:50,090 --> 00:22:52,390\n我应该说一下 我只展示给你们2个过程\nI just ought to mention, I've\nonly showed you two\n\n425\n00:22:52,390 --> 00:22:53,860\nprocedures.\n\n426\n00:22:53,860 --> 00:22:57,800\n但是 让我强调一下\nBut let me emphasize that this\nway of putting things together\n\n427\n00:22:57,800 --> 00:22:59,780\n这种用maps filters和accumulators 把东西放在一起的方法\nwith maps, filters,\nand accumulators\n\n428\n00:22:59,780 --> 00:23:01,410\n是非常非常普通的\nis very, very general.\n\n429\n00:23:01,410 --> 00:23:08,010\n这是程序产生和测试的范式\nIt's the generate and test\nparadigm for programs. And as\n\n430\n00:23:08,010 --> 00:23:11,970\n作为一个列子 曾经的麻省理工研究生 Richard Waters\nan example of that, Richard\nWaters, who was at MIT when he\n\n431\n00:23:11,970 --> 00:23:14,060\n\nwas a graduate student, as part\nof his thesis research\n\n432\n00:23:14,060 --> 00:23:17,700\n他把分析一个大块的ibm科学图书管子程序作为它理论研究的一部分\nwent and analyzed a large chunk\nof the IBM scientific\n\n433\n00:23:17,700 --> 00:23:22,340\n他发现 大约百分之60的程序\nsubroutine library, and\ndiscovered that about 60% of\n\n434\n00:23:22,340 --> 00:23:26,830\n可以用不超过我们放在这里的知识完整的表达\nthe programs in it could be\nexpressed exactly in terms\n\n435\n00:23:26,830 --> 00:23:28,940\nusing no more than what\nwe've put here--\n\n436\n00:23:28,940 --> 00:23:30,710\nmap filter accumulate\nmap, filter, and accumulate.\n\n437\n00:23:30,710 --> 00:23:31,960\n好的 下面进入休息时间\nAll right, let's take a break.\n\n438\n00:23:31,960 --> 00:23:36,620\n\n439\n00:23:36,620 --> 00:23:37,870\n有神马问题\nQuestions?\n\n440\n00:23:37,870 --> 00:23:40,470\n\n441\n00:23:40,470 --> 00:23:43,030\n学僧 ：看起来这货的本质只是\nAUDIENCE: It seems like the\nessence of this whole thing is\n\n442\n00:23:43,033 --> 00:23:45,980\n你有一个非常均匀简单的数据结构来进行工作 这个数据结构叫流\njust that you have a very\nuniform, simple data structure\n\n443\n00:23:45,980 --> 00:23:48,380\nto work with, the stream.\n\n444\n00:23:48,380 --> 00:23:48,920\n教授：是的\nPROFESSOR: Right.\n\n445\n00:23:48,920 --> 00:23:51,670\n本质就是这个\nThe essence is that you, again,\nit's this sense of\n\n446\n00:23:51,670 --> 00:23:53,710\n再说一下 这个就是感觉符合直觉的接口\nconventional interfaces.\n\n447\n00:23:53,710 --> 00:23:55,610\n所以你可以开始把很多东西放在一起\nSo you can start putting a\nlot of things together.\n\n448\n00:23:55,610 --> 00:23:59,830\n流就像你所说的那样 一种均衡的数据结构来支持它\nAnd the stream is as you say,\nthe uniform data structure\n\n449\n00:23:59,830 --> 00:24:00,890\nthat supports that.\n\n450\n00:24:00,890 --> 00:24:03,600\n顺便说一下 这非常像APL\nThis is very much like\nAPL, by the way.\n\n451\n00:24:03,600 --> 00:24:06,330\nAPL是一个几乎相同的思想 除了在APL中\nAPL is very much the same idea,\nexcept in APL, instead\n\n452\n00:24:06,330 --> 00:24:09,560\n你可以使用数组和向量来代替这个流\nof this stream, you have\narrays and vectors.\n\n453\n00:24:09,560 --> 00:24:13,565\n并且APL许多的威力的原因完全和这个一样\nAnd a lot of the power of APL is\nexactly the same reason of\n\n454\n00:24:13,565 --> 00:24:14,815\nthe power of this.\n\n455\n00:24:14,815 --> 00:24:19,910\n\n456\n00:24:19,910 --> 00:24:20,910\n好的 谢谢\nOK, thank you.\n\n457\n00:24:20,910 --> 00:24:22,160\n休息一下\nLet's take a break.\n\n458\n00:24:22,160 --> 00:24:57,470\n\n459\n00:24:57,470 --> 00:24:57,610\n好的\nAll right.\n\n460\n00:24:57,610 --> 00:25:02,830\n我们已经看到使用流来做组织计算\nWe've been looking at ways of\norganizing computations using\n\n461\n00:25:02,830 --> 00:25:07,560\n我现在想要做的只是展示给你们\nstreams. What I want to do now\nis just show you two somewhat\n\n462\n00:25:07,560 --> 00:25:10,810\n两个更加复杂的例子\nmore complicated examples\nof that.\n\n463\n00:25:10,810 --> 00:25:15,000\n让我们开始思考下面重要有用的过程\nLet's start by thinking about\nthe following kind of utility\n\n464\n00:25:15,000 --> 00:25:16,810\nprocedure that will\ncome in useful.\n\n465\n00:25:16,810 --> 00:25:19,960\n假设我有一个流\nSuppose I've got a stream.\n\n466\n00:25:19,960 --> 00:25:23,730\n流中的元素本身就是一个流\nAnd the elements of this stream\nare themselves streams.\n\n467\n00:25:23,730 --> 00:25:26,530\n所以一开始可能是1，2，3\nSo the first thing\nmight be 1, 2, 3.\n\n468\n00:25:26,530 --> 00:25:32,600\n\n469\n00:25:32,600 --> 00:25:33,880\n我得到了一个流\nSo I've got a stream.\n\n470\n00:25:33,880 --> 00:25:40,100\n并且每个流中的元素它本身就是一个流\nAnd each element of the stream\nis itself a stream.\n\n471\n00:25:40,100 --> 00:25:45,580\n我想要做的是 建造一个流\nAnd what I'd like to do is build\na stream that collects\n\n472\n00:25:45,580 --> 00:25:47,870\n它收集了所有的元素 将所有的元素脱离这个子流\ntogether all of the elements,\npulls all of the elements out\n\n473\n00:25:47,870 --> 00:25:50,840\n然后把它们进行字符串化变成一个东西\nof these sub-streams and\nstrings them all\n\n474\n00:25:50,840 --> 00:25:52,080\ntogether in one thing.\n\n475\n00:25:52,080 --> 00:25:56,220\n只是展示给你这个语言的作用 真简单\nSo just to show you the use of\nthis language, how easy it is,\n\n476\n00:25:56,220 --> 00:25:56,960\n把那个叫做flatten\ncall that flatten.\n\n477\n00:25:56,960 --> 00:26:13,020\n然后我可以定义过程来flatten这个流中流\nAnd I can define to flatten this\nstream of streams. Well,\n\n478\n00:26:13,020 --> 00:26:13,960\n这是什么鬼\nwhat is that?\n\n479\n00:26:13,960 --> 00:26:16,240\n那只是一个accumulation\nThat's just an accumulation.\n\n480\n00:26:16,240 --> 00:26:25,240\n我想使用附加做累加\nI want to accumulate\nusing append, by\n\n481\n00:26:25,240 --> 00:26:26,450\n通过连续的附加\nsuccessively appending.\n\n482\n00:26:26,450 --> 00:26:36,590\n所以 我使用了 附加流进行累加\nSo I accumulate using append\nstreams, starting with\n\n483\n00:26:36,590 --> 00:26:54,370\n从空流往下到 流中流\nthe-empty-stream down that\nstream of streams.\n\n484\n00:26:54,370 --> 00:26:58,290\n这里有一个你怎样开始使用这些更高阶的东西去做一些有趣的操作的例子\nOK, so there's an example of how\nyou can start using these\n\n485\n00:26:58,290 --> 00:27:00,830\nhigher order things to do some\ninteresting operations.\n\n486\n00:27:00,830 --> 00:27:04,230\n事实上 我还想做另一个有趣的东西\nIn fact, there's another\nuseful thing\n\n487\n00:27:04,230 --> 00:27:05,100\nthat I want to do.\n\n488\n00:27:05,100 --> 00:27:18,700\n我想要定义一个叫flat-map的过程\nI want to define a procedure\ncalled flat-map, flat map of\n\n489\n00:27:18,700 --> 00:27:21,840\n一些函数和一个流的flat map\nsome function and a stream.\n\n490\n00:27:21,840 --> 00:27:23,920\nf将会变成一个有一些元素的流\nAnd what this is going\nto do is f will\n\n491\n00:27:23,920 --> 00:27:25,720\nbe a stream of elements.\n\n492\n00:27:25,720 --> 00:27:28,930\nf将会变成一个函数\nf is going to be a function that\nfor each element in the\n\n493\n00:27:28,930 --> 00:27:31,950\n这个函数在流中的每个元素可以产生另一个流\nstream produces another\nstream.\n\n494\n00:27:31,950 --> 00:27:33,950\n我想要做的是把所有的元素和所有的流合并起来\nAnd what I want to do is take\nall of the elements and all of\n\n495\n00:27:33,950 --> 00:27:36,000\nthose streams and combine\nthem together.\n\n496\n00:27:36,000 --> 00:27:51,350\n所以那个只将会是直到s的flatten of map f\nSo that's just going to be the\nflatten of map f down s.\n\n497\n00:27:51,350 --> 00:27:54,290\n每次我调用对元素s调用f 我得到一个流\nEach time I apply f to an\nelement of s, I get a stream.\n\n498\n00:27:54,290 --> 00:27:56,690\n如果我像下做map 我将会得到一个流中流\nIf I map it all the way down, I\nget a stream of streams, and\n\n499\n00:27:56,690 --> 00:27:58,385\n并且我将会将它flatten\nI'll flatten that.\n\n500\n00:27:58,385 --> 00:28:04,670\n好 我想要使用这个来展示给你们一种新的方法来熟悉这样的问题\nWell, I want to use that to\nshow you a new way to do a\n\n501\n00:28:04,670 --> 00:28:06,360\nfamiliar kind of problem.\n\n502\n00:28:06,360 --> 00:28:12,310\n这个问题和你以前见过的许多问题一样\nThe problem's going to be like a\nlot of problems you've seen,\n\n503\n00:28:12,310 --> 00:28:14,190\n虽然这个可能不是很特别\nalthough maybe not this\nparticular one.\n\n504\n00:28:14,190 --> 00:28:15,490\n我将会给你一个整数n\nI'm going to give you\nan integer, n.\n\n505\n00:28:15,490 --> 00:28:18,480\n\n506\n00:28:18,480 --> 00:28:31,020\n我们的问题是找到所有的序对和整数i和j\nAnd the problem is going to be\nfind all pairs and integers i\n\n507\n00:28:31,020 --> 00:28:42,740\n取值为0-i j小于i 一直到n\nand j, between 0 and i, with j\nless than i, up to n, such\n\n508\n00:28:42,740 --> 00:28:51,910\n并且可以满足i＋j是素数\nthat i plus j is prime.\n\n509\n00:28:51,910 --> 00:28:55,740\n\n510\n00:28:55,740 --> 00:29:00,520\n举个例子 如果n＝6 让我在这里做个小表格\nSo for example, if n equals 6,\nlet's make a little table\n\n511\n00:29:00,520 --> 00:29:06,640\n这里i,j,i+j\nhere, i and j and i plus j.\n\n512\n00:29:06,640 --> 00:29:09,700\n\n513\n00:29:09,700 --> 00:29:15,520\n我们可以假设 i=2 j=1 我门可以得到i+j=3\nSo for, say, i equals 2 and\nj equals 1, I'd get 3.\n\n514\n00:29:15,520 --> 00:29:18,940\n对于i=3 我可以使j＝2\nAnd for i equals 3, I could\nhave j equals 2, and that\n\n515\n00:29:18,940 --> 00:29:21,210\n那么i＋j＝5\nwould be 5.\n\n516\n00:29:21,210 --> 00:29:28,400\n如果i＝4 j＝1 i＋j＝5 等等 直到i到了6\nAnd 4 and 1 would be 5 and so\non, up until i goes to 6.\n\n517\n00:29:28,400 --> 00:29:33,640\n我想要返回去产生三倍数像这样的一个流\nAnd what I'd like to return is\nto produce a stream of all the\n\n518\n00:29:33,640 --> 00:29:37,350\n让我们说 i j i+j\ntriples like this, let's\nsay i, j, and i plus j.\n\n519\n00:29:37,350 --> 00:29:41,530\n所以对于每个n 我想要产生这个流\nSo for each n, I want to\ngenerate this stream.\n\n520\n00:29:41,530 --> 00:29:43,680\n好的 这简单\nOK, well, that's easy.\n\n521\n00:29:43,680 --> 00:29:47,230\n让我们做吧\nLet's build it up.\n\n522\n00:29:47,230 --> 00:29:50,150\n我们像这样开始\nWe start like this.\n\n523\n00:29:50,150 --> 00:29:55,510\n我们会说 对于每个i 我们将会产生一个流\nWe're going to say for\neach i, we're going\n\n524\n00:29:55,510 --> 00:29:56,440\nto generate a stream.\n\n525\n00:29:56,440 --> 00:29:58,830\n对于每个1到n的i 我们将会产生一个流\nFor each i in the interval 1\nthrough n, we're going to\n\n526\n00:29:58,830 --> 00:30:00,660\ngenerate a stream.\n\n527\n00:30:00,660 --> 00:30:02,230\n这个流将会变成什么呢\nWhat's that stream\ngoing to be?\n\n528\n00:30:02,230 --> 00:30:04,180\n我们将会以产生所有的序对开始\nWe're going to start by\ngenerating all the pairs.\n\n529\n00:30:04,180 --> 00:30:11,840\n所以 对于我们产生的每个i \nSo for each i, we're going to\ngenerate, for each j in the\n\n530\n00:30:11,840 --> 00:30:19,450\n都有在这个1到i－1的区间里每个j 我们将会产生序对\ninterval 1 to i minus 1, we'll\ngenerate the pair, or the list\n\n531\n00:30:19,450 --> 00:30:20,710\n或者是一个有两个元素i 和j的列表\nwith two elements i and j.\n\n532\n00:30:20,710 --> 00:30:23,780\n\n533\n00:30:23,780 --> 00:30:30,712\n所以我们map整个区间 生成这些序对\nSo we map along the interval,\ngenerating the pairs.\n\n534\n00:30:30,712 --> 00:30:33,170\n对于每个产生一个序对的流的i\nAnd for each i, that generates\na stream of pairs.\n\n535\n00:30:33,170 --> 00:30:34,590\n然后我们flatmap它\nAnd we flatmap it.\n\n536\n00:30:34,590 --> 00:30:37,390\n现在 我们已经拥有了所有i和j的序对\nNow we have all the pairs\ni and j, such that i\n\n537\n00:30:37,390 --> 00:30:38,730\n并且i比j小\nis less than j.\n\n538\n00:30:38,730 --> 00:30:39,850\n就像这样搞\nSo that builds that.\n\n539\n00:30:39,850 --> 00:30:42,990\n现在我们对其来个测试\nNow we're got to test them.\n\n540\n00:30:42,990 --> 00:30:47,160\n我们把我们刚刚建的东西拿出 flatmap\nWell, we take that thing we just\nbuilt, the flatmap, and\n\n541\n00:30:47,160 --> 00:30:50,090\n并且我们把它进行filter 这个i是否\nwe filter it to see\nwhether the i--\n\n542\n00:30:50,090 --> 00:30:51,660\n看 我们有一个i和j\nsee, we had an i and a j.\n\n543\n00:30:51,660 --> 00:30:55,180\ni是列表中的第一个东西 j是第二个\ni was the first thing in the\nlist, j was the second thing\n\n544\n00:30:55,180 --> 00:30:59,030\n在列表中 我们有一个谓词\nin the list. So we have a\npredicate which says in that\n\n545\n00:30:59,030 --> 00:31:00,870\n这个谓词表示 在这个由2个元素构成的列表是car和cdr素数的和\nlist of two elements\nis the sum of the\n\n546\n00:31:00,870 --> 00:31:02,070\nCAR and the CDR prime.\n\n547\n00:31:02,070 --> 00:31:06,540\n并且我们对序对的集合进行filter\nAnd we filter that collection\nof pairs we just built.\n\n548\n00:31:06,540 --> 00:31:09,420\n所以 那些是我们想要的序对\nSo those are the\npairs we want.\n\n549\n00:31:09,420 --> 00:31:13,340\n现在 我们继续 把filter后的结构沿着它进行map\nNow we go ahead and we take the\nresult of that filter and\n\n550\n00:31:13,340 --> 00:31:19,610\n生成列表i和j i+j\nwe map along it, generating the\nlist i and j and i plus j.\n\n551\n00:31:19,610 --> 00:31:22,910\n这就是我们的程序 prime-sum-pairs\nAnd that's our procedure\nprime-sum-pairs.\n\n552\n00:31:22,910 --> 00:31:24,480\n然后只需要过一遍  这就是我们整个过程了\nAnd then just to flash it up,\nhere's the whole procedure.\n\n553\n00:31:24,480 --> 00:31:27,945\n\n554\n00:31:27,945 --> 00:31:30,750\n一个map 一个filter 一个flatmap\nA map, a filter, a flatmap.\n\n555\n00:31:30,750 --> 00:31:34,850\n\n556\n00:31:34,850 --> 00:31:36,350\n所有的东西都在这里了\nThere's the whole thing,\neven though this isn't\n\n557\n00:31:36,350 --> 00:31:37,120\n即使这个可读性不高\nparticularly readable.\n\n558\n00:31:37,120 --> 00:31:40,000\n这只是一个flatmap的延伸\nIt's just expanding\nthat flatmap.\n\n559\n00:31:40,000 --> 00:31:45,090\n这里有一个表现嵌套循环的过程\nSo there's an example which\nillustrates the general point\n\n560\n00:31:45,090 --> 00:31:49,350\n它开始像maps和那些东西的flatmaps的flatmaps的flatmaps\n\nthat nested loops in this\nprocedure start looking like\n\n561\n00:31:49,350 --> 00:31:52,370\ncompositions of flatmaps of\nflatmaps of flatmaps of maps\n\n562\n00:31:52,370 --> 00:31:54,200\nand things.\n\n563\n00:31:54,200 --> 00:31:57,900\n所以我们不仅仅要枚举单个个体\nSo not only can we enumerate\nindividual things, but by\n\n564\n00:31:57,900 --> 00:32:00,890\n还要通过使用flatmaps 使我们做一些与大部分其他语言的对应的嵌套循环\nusing flatmaps, we can do what\nwould correspond to nested\n\n565\n00:32:00,890 --> 00:32:03,230\nloops in most other languages.\n\n566\n00:32:03,230 --> 00:32:06,870\n当然 一直写这个flatmaps中的flatmaps很烦\nOf course, it's pretty awful to\nkeep writing these flatmaps\n\n567\n00:32:06,870 --> 00:32:08,410\nof flatmaps of flatmaps.\n\n568\n00:32:08,410 --> 00:32:13,830\n你看的这个prime-sum-pairs很复杂\nPrime-sum-pairs you saw looked\nfairly complicated, even\n\n569\n00:32:13,830 --> 00:32:15,480\n虽然单个个体很容易\nthough the individual\npieces were easy.\n\n570\n00:32:15,480 --> 00:32:17,800\n所以如果你喜欢 你可以用一些叫collect的语法糖\nSo what you can do, if you\nlike, is introduced some\n\n571\n00:32:17,800 --> 00:32:21,040\nsyntactic sugar that's\ncalled collect.\n\n572\n00:32:21,040 --> 00:32:23,570\ncollect只是一个对于嵌套的flatmaps的缩写\nAnd collect is just an\nabbreviation for that nest of\n\n573\n00:32:23,570 --> 00:32:26,160\n\nflatmaps and filters arranged\nin that particular way.\n\n574\n00:32:26,160 --> 00:32:29,620\n这里还是prime-sum-pairs 不过是用collect来做的\nHere's prime-sum-pairs again,\nwritten using collect.\n\n575\n00:32:29,620 --> 00:32:32,670\n它的意思是为了找到所有的序对 我将要整和一个答案\nIt says to find all those pairs,\nI'm going to collect\n\n576\n00:32:32,670 --> 00:32:40,910\n这个答案是列表i j 和i+j\ntogether a result, which is the\nlist i, j, and i plus j,\n\n577\n00:32:40,910 --> 00:32:44,510\n那将会生成i的值为1到n\nthat's going to be generated as\ni runs through the interval\n\n578\n00:32:44,510 --> 00:32:51,440\nj的值是1到i到1\nfrom 1 to n and as j runs\nthrough the interval from 1 to\n\n579\n00:32:51,440 --> 00:32:58,040\n并令i＋j是素数\ni minus 1, such that\ni plus j is prime.\n\n580\n00:32:58,040 --> 00:33:00,690\n所以我将不会说 我会使用一般的collect\nSo I'm not going to say what\ncollect does in general.\n\n581\n00:33:00,690 --> 00:33:03,420\n你可以在书上看到它\nYou can look at that by looking\nat it in the book.\n\n582\n00:33:03,420 --> 00:33:06,010\n但是 很显然 你可以看到这些元件是我写的原始过程的元件\nBut pretty much, you can see\nthat the pieces of this are\n\n583\n00:33:06,010 --> 00:33:08,820\nthe pieces of that original\nprocedure I wrote.\n\n584\n00:33:08,820 --> 00:33:11,550\n这个collect只是一些自动生成嵌套flatmaps的语法糖\nAnd this collect is just some\nsyntactic sugar for\n\n585\n00:33:11,550 --> 00:33:16,310\nautomatically generating that\nnest of flatmaps and flatmaps.\n\n586\n00:33:16,310 --> 00:33:21,120\n好 让我再做一个和上面差不多的例子\nOK, well, let me do one more\nexample that shows you the\n\n587\n00:33:21,120 --> 00:33:22,120\nsame kind of thing.\n\n588\n00:33:22,120 --> 00:33:25,740\n这里是一个非常著名的问题\nHere's a very famous problem\nthat's used to illustrate a\n\n589\n00:33:25,740 --> 00:33:28,980\n这个问题以前是为了展示许多叫回溯法的计算机算法\nlot of so-called backtracking\ncomputer algorithms. This is\n\n590\n00:33:28,980 --> 00:33:30,200\n这是一个八皇后的问题\nthe eight queens problem.\n\n591\n00:33:30,200 --> 00:33:32,370\n这里是棋盘\nThis is a chess board.\n\n592\n00:33:32,370 --> 00:33:34,570\n八皇后问题说\nAnd the eight queens problem\nsays, find a way to put down\n\n593\n00:33:34,570 --> 00:33:37,660\n找到一种八皇后两两不相攻击的方法\neight queens on a chess board\nso that no two are attacking\n\n594\n00:33:37,660 --> 00:33:38,000\neach other.\n\n595\n00:33:38,000 --> 00:33:39,685\n这里有一个特别的方法来解决这个八皇后问题\nAnd here's a particular\nsolution to the\n\n596\n00:33:39,685 --> 00:33:41,430\neight queens problem.\n\n597\n00:33:41,430 --> 00:33:44,450\n所以 我得保证放置皇后 并且\nSo I have to make sure to put\ndown queens so that no two are\n\n598\n00:33:44,450 --> 00:33:48,570\n没有皇后在同一列或行或在同一个对角线\nin the same row or the\nsame column or sit\n\n599\n00:33:48,570 --> 00:33:51,410\nalong the same diagonal.\n\n600\n00:33:51,410 --> 00:33:56,400\n现在有个做这个的标准的方法\nNow, there's sort of a standard\nway of doing that.\n\n601\n00:33:56,400 --> 00:33:59,740\n\n602\n00:33:59,740 --> 00:34:03,200\n首先我们要做的是\nWell, first we need\nto do is below the\n\n603\n00:34:03,200 --> 00:34:04,940\n站在george的层面\nsurface, at George's level.\n\n604\n00:34:04,940 --> 00:34:07,340\n我们得找一个方法来表示棋盘和位置\nWe have to find some way to\nrepresent a board, and\n\n605\n00:34:07,340 --> 00:34:08,095\n\nrepresent positions.\n\n606\n00:34:08,095 --> 00:34:09,800\n我们不需要担心那个\nAnd we'll not worry\nabout that.\n\n607\n00:34:09,800 --> 00:34:12,540\n但是让我们假设有一个叫safe的谓词\nBut let's assume that there's\na predicate called safe.\n\n608\n00:34:12,540 --> 00:34:16,040\n\n609\n00:34:16,040 --> 00:34:19,090\nsafe所作的是\nAnd what safe is going to do is\ngoing to say given that I\n\n610\n00:34:19,090 --> 00:34:22,520\n我有一串皇后放在棋盘上\nhave a bunch of queens down on\nthe chess board, is it OK to\n\n611\n00:34:22,520 --> 00:34:25,400\n把queen放在特定的点上是好的吗\nput a queen in this\nparticular spot?\n\n612\n00:34:25,400 --> 00:34:32,889\n所以safe将会带一行一列\nSo safe is going to take\na row and a column.\n\n613\n00:34:32,889 --> 00:34:34,510\n那将会是我尝试放置下一个皇后的地方和剩下的地方\nThat's going to be a place where\nI'm going to try and put\n\n614\n00:34:34,510 --> 00:34:42,370\ndown the next queen, and\nthe rest of positions.\n\n615\n00:34:42,370 --> 00:34:45,420\n\n616\n00:34:45,420 --> 00:34:48,679\nsafe说的是 我已经把皇后放在这个位置上\nAnd what safe will say is given\nthat I already have\n\n617\n00:34:48,679 --> 00:34:53,920\nqueens down in these positions,\nis it safe to put\n\n618\n00:34:53,920 --> 00:34:58,300\n那么 把皇后放在那个行或列是safe吗\nanother queen down in that\nrow and that column?\n\n619\n00:34:58,300 --> 00:34:59,360\n让我们不要再担心这个问题\nAnd let's not worry\nabout that.\n\n620\n00:34:59,360 --> 00:35:01,380\n这个是乔治的问题 这也不难写\nThat's George's problem. and\nit's not hard to write.\n\n621\n00:35:01,380 --> 00:35:06,350\n你只需要检查 这货是不是包含\nYou just have to check whether\nthis thing contains any things\n\n622\n00:35:06,350 --> 00:35:10,530\n一些在那个行 列或对角线中的东西\non that row or that column\nor in that diagonal.\n\n623\n00:35:10,530 --> 00:35:13,590\n现在你将要怎样组织程序呢\nNow, how would you organize\nthe program given that?\n\n624\n00:35:13,590 --> 00:35:18,010\n这里有一个传统的方法来解决这个问题\nAnd there's sort of a\ntraditional way to organize it\n\n625\n00:35:18,010 --> 00:35:20,116\n我们把它叫做回溯法 它的意思是\ncalled backtracking.\n\n626\n00:35:20,116 --> 00:35:27,570\n让我们把第一个皇后放在第一个列上\nAnd it says, well, let's think\nabout all the ways of putting\n\n627\n00:35:27,570 --> 00:35:31,290\nthe first queen down in\nthe first column.\n\n628\n00:35:31,290 --> 00:35:32,580\n这里有八种方法\nThere are eight ways.\n\n629\n00:35:32,580 --> 00:35:35,880\n让我们来试一下第一个\nWell, let's say try\nthe first column.\n\n630\n00:35:35,880 --> 00:35:37,300\n来试试第一行第一列\nTry column 1, row 1.\n\n631\n00:35:37,300 --> 00:35:41,300\n这些分支可以表示每个的可能性\nThese branches are going to\nrepresent the possibilities at\n\n632\n00:35:41,300 --> 00:35:43,360\neach level.\n\n633\n00:35:43,360 --> 00:35:45,875\n所以我将会尝试并把皇后放在第一列中\nSo I'll try and put a queen\ndown in the first column.\n\n634\n00:35:45,875 --> 00:35:48,360\n现在 我们已经把它放在第一列了\nAnd now given that it's in the\nfirst column, I'll try and put\n\n635\n00:35:48,360 --> 00:35:49,980\n我们讲尝试把下一个皇后放在第一列\nthe next queen down in\nthe first column.\n\n636\n00:35:49,980 --> 00:35:53,035\n\n637\n00:35:53,035 --> 00:35:55,470\n我们将尝试并且把第一个皇后\nI'll try and put the first\nqueen, the one in the first\n\n638\n00:35:55,470 --> 00:35:56,920\n第一列的皇后 方在第一行\ncolumn, down in the first row.\n\n639\n00:35:56,920 --> 00:35:59,050\n不好意思\nI'm sorry.\n\n640\n00:35:59,050 --> 00:36:00,780\n然后 我们将把下一个皇后放在第一行\nAnd then given that, we'll\nput the next queen down\n\n641\n00:36:00,780 --> 00:36:01,390\nin the first row.\n\n642\n00:36:01,390 --> 00:36:02,090\n这样不好\nAnd that's no good.\n\n643\n00:36:02,090 --> 00:36:04,200\n所以我将要返回到这里\nSo I'll back up to here.\n\n644\n00:36:04,200 --> 00:36:06,280\n我会说 我能把第一个皇后放在第二行吗\nAnd I'll say, oh, can I put the\nfirst queen down in the\n\n645\n00:36:06,280 --> 00:36:07,510\nsecond row?\n\n646\n00:36:07,510 --> 00:36:08,550\n好吧 这样也不好\nWell, that's no good.\n\n647\n00:36:08,550 --> 00:36:09,760\n喔 我能把这个放在第三行嘛\nOh, can I put it down\nin the third row?\n\n648\n00:36:09,760 --> 00:36:12,790\n好 这样不错\nWell, that's good.\n\n649\n00:36:12,790 --> 00:36:14,290\n现在 我能把第一个皇后放在第一列吗\nWell, now can I put the\nnext queen down\n\n650\n00:36:14,290 --> 00:36:15,380\nin the first column?\n\n651\n00:36:15,380 --> 00:36:18,030\n我不能再想象棋盘\nWell, I can't visualize this\nchess board anymore, but I\n\n652\n00:36:18,030 --> 00:36:19,195\n但是我觉得这样是对的\nthink that's right.\n\n653\n00:36:19,195 --> 00:36:20,450\n并且 我将尝试下一个\nAnd I try the next one.\n\n654\n00:36:20,450 --> 00:36:24,170\n在每个地方 我尽可能的沿着数向下\nAnd at each place, I go as far\ndown this tree as I can.\n\n655\n00:36:24,170 --> 00:36:25,640\n然后倒退\nAnd I back up.\n\n656\n00:36:25,640 --> 00:36:28,970\n如果我到了这里 并且发现我不能再往下了\nIf I get down to here and find\nno possibilities below there,\n\n657\n00:36:28,970 --> 00:36:31,740\n我返回到这里 再次开始生成这个子树\nI back all the way up to here,\nand now start again generating\n\n658\n00:36:31,740 --> 00:36:33,260\nthis sub-tree.\n\n659\n00:36:33,260 --> 00:36:35,050\n并且我四处绕\nAnd I sort of walk around.\n\n660\n00:36:35,050 --> 00:36:37,870\n最后 如果我可以一路求解下来\nAnd finally, if I ever manage to\nget all the way down, I've\n\n661\n00:36:37,870 --> 00:36:40,090\n我将会得到答案\nfound a solution.\n\n662\n00:36:40,090 --> 00:36:45,020\n这就是以前在人工智能编程中传统的范式\nSo that's a typical sort of\nparadigm that's used a lot in\n\n663\n00:36:45,020 --> 00:36:45,930\nAI programming.\n\n664\n00:36:45,930 --> 00:36:47,300\n这叫做回溯查找\nIt's called backtracking\nsearch.\n\n665\n00:36:47,300 --> 00:36:57,470\n\n666\n00:36:57,470 --> 00:37:03,860\n这真得没有必要\nAnd it's really unnecessary.\n\n667\n00:37:03,860 --> 00:37:06,550\n你看当我想象的这个东西时 我感到疑惑了\nYou saw me get confused when I\nwas visualizing this thing.\n\n668\n00:37:06,550 --> 00:37:08,550\n你也看到了这个复杂性\nAnd you see the complication.\n\n669\n00:37:08,550 --> 00:37:10,760\n这个东西很难说\nThis is a complicated\nthing to say.\n\n670\n00:37:10,760 --> 00:37:12,390\n为什么难呢\nWhy is it complicated?\n\n671\n00:37:12,390 --> 00:37:16,190\n因为这个很花时间\nIts because somehow this program\nis too inordinately\n\n672\n00:37:16,190 --> 00:37:18,580\nconcerned with time.\n\n673\n00:37:18,580 --> 00:37:19,200\n太tmd的久了\nIt's too much--\n\n674\n00:37:19,200 --> 00:37:21,670\n我尝试了这个 又尝试了那个\nI try this one, and I try this\none, and I go back to the last\n\n675\n00:37:21,670 --> 00:37:22,320\n然后 我返回到最前面的可能\npossibility.\n\n676\n00:37:22,320 --> 00:37:24,340\n这是一个复杂的事\nAnd that's a complicated\nthing.\n\n677\n00:37:24,340 --> 00:37:28,590\n如果我停止担心思考时间\nIf I stop worrying about time\nso much, then there's a much\n\n678\n00:37:28,590 --> 00:37:31,200\n我将会得到一个更简单的方法来表述这个\nsimpler way to describe this.\n\n679\n00:37:31,200 --> 00:37:40,320\n这个方法是 让我们想象 我有一个有k－1层的树\nIt says, let's imagine that I\nhave in my hands the tree down\n\n680\n00:37:40,320 --> 00:37:43,400\nto k minus 1 levels.\n\n681\n00:37:43,400 --> 00:37:50,670\n看在第一个k列中 所有的放置皇后的可能性都在我手中了\nSee, suppose I had in my hands\nall possible ways to put down\n\n682\n00:37:50,670 --> 00:37:53,560\nqueens in the first k columns.\n\n683\n00:37:53,560 --> 00:37:54,610\n假设我有了那个\nSuppose I just had that.\n\n684\n00:37:54,610 --> 00:37:57,070\n让我们不要担心我们如何能搞到它\nLet's not worry about\nhow we get it.\n\n685\n00:37:57,070 --> 00:37:59,200\n好吧 我怎样进行扩充呢\nWell, then, how do\nI extend that?\n\n686\n00:37:59,200 --> 00:38:01,420\n我怎样找到所有在下一个列中放皇后的可能性呢\nHow do I find all possible ways\nto put down queens in the\n\n687\n00:38:01,420 --> 00:38:02,480\nnext column?\n\n688\n00:38:02,480 --> 00:38:03,620\n这简单\nIt's really easy.\n\n689\n00:38:03,620 --> 00:38:12,210\n对于我有的每个位置\nFor each of these positions I\nhave, I think about putting\n\n690\n00:38:12,210 --> 00:38:16,160\n我想把皇后放在每个行中来做下一个东西\ndown a queen in each row\nto make the next thing.\n\n691\n00:38:16,160 --> 00:38:18,930\n然后 对于每个我放置的 我使用safe来进行filter\nAnd then for each one I put\ndown, I filter those by the\n\n692\n00:38:18,930 --> 00:38:22,080\nones that are safe.\n\n693\n00:38:22,080 --> 00:38:24,190\n所以代替 把树想成一步步生成的\nSo instead of thinking about\nthis tree as generated step by\n\n694\n00:38:24,190 --> 00:38:26,860\n假设我已经拥有了它\nstep, suppose I had\nit all there.\n\n695\n00:38:26,860 --> 00:38:29,680\n\n696\n00:38:29,680 --> 00:38:32,990\n为了从k-1到k扩充它\nAnd to extend it from level k\nminus 1 to level k, I just\n\n697\n00:38:32,990 --> 00:38:36,840\n我只需要用所有的可能方法来扩充每个东西\nneed to extend each thing in\nall possible ways and only\n\n698\n00:38:36,840 --> 00:38:37,800\n且只保留安全的东西\nkeep the ones that are safe.\n\n699\n00:38:37,800 --> 00:38:39,300\n这将会给我一个k层树\nAnd that will give me\nthe tree to level k.\n\n700\n00:38:39,300 --> 00:38:41,675\n这是一个解决八皇后问题的递归策略\nAnd that's a recursive strategy\nfor solving the eight\n\n701\n00:38:41,675 --> 00:38:44,530\nqueens problem.\n\n702\n00:38:44,530 --> 00:38:45,780\n好的 我们来看看\nAll right, well, let's\nlook at it.\n\n703\n00:38:45,780 --> 00:38:50,280\n\n704\n00:38:50,280 --> 00:38:54,360\n在特定大小的棋盘中解决八皇后问题\nTo solve the eight queens\nproblem on a board of some\n\n705\n00:38:54,360 --> 00:39:00,390\n我们写一个叫填满列的子过程 fill-colums\nspecified size, we write\na sub-procedure called\n\n706\n00:39:00,390 --> 00:39:01,030\nfill-columns.\n\n707\n00:39:01,030 --> 00:39:04,050\n这个过程将会把皇后\nFill-columns is going to\nput down queens up\n\n708\n00:39:04,050 --> 00:39:06,086\n一直放置到列k\nthrough column k.\n\n709\n00:39:06,086 --> 00:39:07,700\n这里是递归的模式\nAnd here's the pattern\nof the recursion.\n\n710\n00:39:07,700 --> 00:39:12,990\n最后 我将会调用有大小的填充列的方法\nI'm going to call fill-columns\nwith the size eventually.\n\n711\n00:39:12,990 --> 00:39:15,630\n所以fill-columns说 怎样才能把皇后\nSo fill-columns says how to put\ndown queens safely in the\n\n712\n00:39:15,630 --> 00:39:19,255\n安全的放置在这个棋盘中第一个k列 并且\nfirst k columns of this chess\nboard with a size number of\n\n713\n00:39:19,255 --> 00:39:20,360\nrows in it.\n\n714\n00:39:20,360 --> 00:39:22,946\n如果k＝0 那么我们啥都不用干\nIf k is equal to 0, well,\nthen I don't have to\n\n715\n00:39:22,946 --> 00:39:23,940\nput anything down.\n\n716\n00:39:23,940 --> 00:39:26,710\n我的结果只是一个空的棋盘\nSo my solution is just\nan empty chess board.\n\n717\n00:39:26,710 --> 00:39:28,070\n否则 我将会做一些其他的事\nOtherwise, I'm going\nto do some stuff.\n\n718\n00:39:28,070 --> 00:39:30,522\n我将会用collect\nAnd I'm going to use collect.\n\n719\n00:39:30,522 --> 00:39:31,772\n这里有collect\nAnd here's the collect.\n\n720\n00:39:31,772 --> 00:39:34,530\n\n721\n00:39:34,530 --> 00:39:40,590\n我找到了所有在第k-1列中放皇后的方法\nI find all ways to put\ndown queens in the\n\n722\n00:39:40,590 --> 00:39:41,910\nfirst k minus 1 columns.\n\n723\n00:39:41,910 --> 00:39:43,320\n这里只是我设置的\nAnd this was just\nwhat I set for.\n\n724\n00:39:43,320 --> 00:39:48,880\n想象我有这样的树往下到k-1层\nImagine I have this tree down\nto k minus 1 levels.\n\n725\n00:39:48,880 --> 00:39:53,230\n然后我找到所有尝试行的方法\nAnd then I find all ways of\ntrying a row, that's just each\n\n726\n00:39:53,230 --> 00:39:54,130\n那只是每个可能行\nof the possible rows.\n\n727\n00:39:54,130 --> 00:39:58,040\n他是一定尺寸的行 所以那时enumerate 间距\nThey're size rows, so that's\nenumerate interval.\n\n728\n00:39:58,040 --> 00:40:03,950\n现在我要做的是 我把我将要尝试的新的行和列k用剩下的皇后进行整合\nAnd now what I do is I collect\ntogether the new row I'm going\n\n729\n00:40:03,950 --> 00:40:08,950\nto try and column k with\nthe rest of the queens.\n\n730\n00:40:08,950 --> 00:40:10,200\n我邻接了位置\nI adjoin a position.\n\n731\n00:40:10,200 --> 00:40:11,290\n这是乔治的问题\nThis is George's problem.\n\n732\n00:40:11,290 --> 00:40:13,640\n一个邻接的问题和safe差不多\nAn adjoined position\nis like safe.\n\n733\n00:40:13,640 --> 00:40:16,530\n我们所做的事 是拿一行一列 和剩下的位置 然后做一个新的位置集合\nIt's a thing that takes a row\nand a column and the rest of\n\n734\n00:40:16,530 --> 00:40:19,660\nthe positions and makes a\nnew position collection.\n\n735\n00:40:19,660 --> 00:40:26,230\n所以 对于剩下的皇后 我邻接了一个新行和列的位置\nSo I adjoin a position of a new\nrow and a new column to\n\n736\n00:40:26,230 --> 00:40:30,310\n剩下的皇后可以用尝试所有可能性的方法在k－1列来做\nthe rest of the queens, where\nthe rest of the queens runs\n\n737\n00:40:30,310 --> 00:40:32,870\nthrough all possible ways\nof solving the problem\n\n738\n00:40:32,870 --> 00:40:34,620\nin k minus 1 columns.\n\n739\n00:40:34,620 --> 00:40:39,730\n新的行运行了所有行的可能性\nAnd the new row runs through all\npossible rows such that it\n\n740\n00:40:39,730 --> 00:40:43,240\n使得放在这里安全\nwas safe to put one there.\n\n741\n00:40:43,240 --> 00:40:46,500\n这就是整个程序了\nAnd that's the whole program.\n\n742\n00:40:46,500 --> 00:40:49,840\n这是整个过程\nThere's the whole procedure.\n\n743\n00:40:49,840 --> 00:40:51,990\n不仅仅是这样 这不仅仅解决八皇后问题\nNot only that, that doesn't just\nsolve the eight queens\n\n744\n00:40:51,990 --> 00:40:56,010\n还顺手给出了八皇后问题的所有解\nproblem, it gives you\nall solutions to the\n\n745\n00:40:56,010 --> 00:40:56,680\neight queens problem.\n\n746\n00:40:56,680 --> 00:40:58,480\n当你搞定了 你就有一个流\nWhen you're done, you\nhave a stream.\n\n747\n00:40:58,480 --> 00:41:00,650\n流中的元素是解决这个问题的所有可能性\nAnd the elements of that stream\nare all possible ways\n\n748\n00:41:00,650 --> 00:41:01,900\nof solving that problem.\n\n749\n00:41:01,900 --> 00:41:05,310\n\n750\n00:41:05,310 --> 00:41:06,260\n为什么这个更加简单呢\nWhy is that simpler?\n\n751\n00:41:06,260 --> 00:41:10,170\n好吧 我们抛出了整个想法 这个想法是一些在时间中发生的，有状态的过程\nWell, we threw away the whole\nidea that this is some process\n\n752\n00:41:10,170 --> 00:41:12,720\nthat happens in time\nwith state.\n\n753\n00:41:12,720 --> 00:41:14,420\n并且 我们只会说 这是东西的整个集合\nAnd we just said it's a whole\ncollection of stuff.\n\n754\n00:41:14,420 --> 00:41:18,260\n这就是更加简单的原因\nAnd that's why it's simpler.\n\n755\n00:41:18,260 --> 00:41:20,110\n我们改变了我们的观念\nWe've changed our view.\n\n756\n00:41:20,110 --> 00:41:22,820\n记住我们今天开始的地方\nRemember, that's where\nwe started today.\n\n757\n00:41:22,820 --> 00:41:26,230\n我们搞变了我们的这我们尝试去建模的东西是什么的观念\nWe've changed our view of what\nit is we're trying to model.\n\n758\n00:41:26,230 --> 00:41:30,570\n我们停止对随着时间的发展的，并有过程和状态的物体进行建模\nwe stop modeling things that\nevolve in time and have steps\n\n759\n00:41:30,570 --> 00:41:31,750\nand have state.\n\n760\n00:41:31,750 --> 00:41:33,990\n作为替代 我们尽力给像粉笔飞行这样的全局的东西进行建模\nAnd instead, we're trying to\nmodel this global thing like\n\n761\n00:41:33,990 --> 00:41:37,950\nthe whole flight of the\nchalk, rather than its\n\n762\n00:41:37,950 --> 00:41:40,750\n而不是它们的在每个时间的状态\nstate at each instant.\n\n763\n00:41:40,750 --> 00:41:42,000\n有神马问题\nAny questions?\n\n764\n00:41:42,000 --> 00:41:43,810\n\n765\n00:41:43,810 --> 00:41:46,190\n在我看来 回溯法将会找到它能找到的第一个解\nAUDIENCE: It looks to me like\nbacktracking would be\n\n766\n00:41:46,190 --> 00:41:49,970\nsearching for the first solution\nit can find, whereas\n\n767\n00:41:49,970 --> 00:41:54,030\n但是这个递归搜索将会查找所有的解\nthis recursive search would be\nlooking for all solutions.\n\n768\n00:41:54,030 --> 00:41:58,090\n而且看起来 如果你有足够大的空间去查找\nAnd it seems that if you have a\nlarge enough area to search,\n\n769\n00:41:58,090 --> 00:42:01,360\n第二个将会变得不可能\nthat the second is going\nto become impossible.\n\n770\n00:42:01,360 --> 00:42:07,610\n好的 这个问题的解就是我们剩下这节课所要讲的内容\nPROFESSOR: OK, the answer to\nthat question is the whole\n\n771\n00:42:07,610 --> 00:42:08,570\nrest of this lecture.\n\n772\n00:42:08,570 --> 00:42:10,540\n这是一个好问题\nIt's exactly the\nright question.\n\n773\n00:42:10,540 --> 00:42:13,522\n\n774\n00:42:13,522 --> 00:42:15,540\n如果你不尝试提前预见到后面的课\nAnd without trying to anticipate\nthe lecture too\n\n775\n00:42:15,540 --> 00:42:19,910\n你应该开始怀疑这个点\nmuch, you should start being\nsuspicious at this point, and\n\n776\n00:42:19,910 --> 00:42:22,220\n这个的确是令人怀疑的\nexactly those kinds\nof suspicions.\n\n777\n00:42:22,220 --> 00:42:24,830\n这是好的 但是这不是非常的不方便吗\nIt's wonderful, but isn't it\nso terribly inefficient?\n\n778\n00:42:24,830 --> 00:42:28,100\n这是我们现在进行的\nThat's where we're going.\n\n779\n00:42:28,100 --> 00:42:30,020\n所以我现在不说 等等再揭晓答案\nSo I won't answer now, but\nI'll answer later.\n\n780\n00:42:30,020 --> 00:42:33,350\n\n781\n00:42:33,350 --> 00:42:34,600\n让我们休息一下\nOK, let's take a break.\n\n782\n00:42:34,600 --> 00:43:29,650\n\n783\n00:43:29,650 --> 00:43:35,600\n现在你应该开始怀疑了\nWell, by now you should be\nstarting to get suspicious.\n\n784\n00:43:35,600 --> 00:43:41,450\n看 我已经展示了这个简单优雅的将程序放在一起的方法\nSee, I've showed your this\nsimple, elegant way of putting\n\n785\n00:43:41,450 --> 00:43:46,440\n不像这些另外的累积奇数的传统方法或者算奇数的斐波那契数\nprograms together, very unlike\nthese other traditional\n\n786\n00:43:46,440 --> 00:43:50,490\n\nprograms that sum the odd\nsquares or compute the odd\n\n787\n00:43:50,490 --> 00:43:53,740\nFibonacci numbers.\n\n788\n00:43:53,740 --> 00:43:57,080\n也不像这些混合enumerator filter 和accumulator的方法\nVery unlike these programs that\nmix up the enumerator and\n\n789\n00:43:57,080 --> 00:44:00,440\nthe filter and the\naccumulator.\n\n790\n00:44:00,440 --> 00:44:04,770\n通过混合 我们没有所有这些美妙的概念上的这些流元件的优点\nAnd by mixing it up, we don't\nhave all of these wonderful\n\n791\n00:44:04,770 --> 00:44:07,990\nconceptual advantages of these\nstreams pieces, these\n\n792\n00:44:07,990 --> 00:44:09,840\n这些为了把许多程序整合在一起的美妙的混合和匹配部件\nwonderful mix and match\ncomponents for putting\n\n793\n00:44:09,840 --> 00:44:13,800\ntogether lots and lots\nof programs.\n\n794\n00:44:13,800 --> 00:44:15,810\n再另一方面 你能见到的所有程序大部分都和这个屌丝程序一样\nOn the other hand, most of the\nprograms you've seen look like\n\n795\n00:44:15,810 --> 00:44:18,340\nthese ugly ones.\n\n796\n00:44:18,340 --> 00:44:19,460\n为什么呢\nWhy's that?\n\n797\n00:44:19,460 --> 00:44:23,705\n计算机科学家们可能没有注意到如果你仅仅做了这个事\nCan it possibly be that computer\nscientists are so\n\n798\n00:44:23,705 --> 00:44:28,370\nobtuse that they don't notice\nthat if you'd merely did this\n\n799\n00:44:28,370 --> 00:44:33,620\n然后你可以获得这个这个程序的优雅性吗\nthing, then you can get this\ngreat programming elegance?\n\n800\n00:44:33,620 --> 00:44:36,760\n这里得有一个catch\nThere's got to be a catch.\n\n801\n00:44:36,760 --> 00:44:39,510\n并且事实上 我们可以很容易看到 什么是catch\nAnd it's actually pretty easy\nto see what the catch is.\n\n802\n00:44:39,510 --> 00:44:42,030\n让我们想一下下面的问题\nLet's think about the\nfollowing problem.\n\n803\n00:44:42,030 --> 00:44:47,510\n假设我告诉你找到在10000－一百万里第二个素数\nSuppose I tell you to find the\nsecond prime between 10,000\n\n804\n00:44:47,510 --> 00:44:51,020\n或者如果你的计算机足够强大\nand 1 million, or if your\ncomputer's larger, say between\n\n805\n00:44:51,020 --> 00:44:54,105\n比如说10000到1000亿\n10,000 and 100 billion,\nor something.\n\n806\n00:44:54,105 --> 00:44:55,550\n然后你说 这很容易\nAnd you say, oh, that's easy.\n\n807\n00:44:55,550 --> 00:44:57,080\n我能用流来搞定\nI can do that with a stream.\n\n808\n00:44:57,080 --> 00:45:01,530\n我需要做的就是枚举从10000到1百万\nAll I do is I enumerate\nthe interval\n\n809\n00:45:01,530 --> 00:45:04,160\nfrom 10,000 to 1 million.\n\n810\n00:45:04,160 --> 00:45:06,800\n然后我得到了所有从10000到1百万中挑选的数字\nSo I get all those integers\nfrom 10,000 to 1 million.\n\n811\n00:45:06,800 --> 00:45:10,520\n我们为了素数性对它们进行filter操作 然后检测所有的数 看看是不是素数\nI filter them for prime-ness, so\ntest all of them and see if\n\n812\n00:45:10,520 --> 00:45:11,762\nthey're prime.\n\n813\n00:45:11,762 --> 00:45:13,170\n然后我拿出第二个元素\nAnd I take the second element.\n\n814\n00:45:13,170 --> 00:45:16,130\n这是尾部的第一个\nThat's the head of the tail.\n\n815\n00:45:16,130 --> 00:45:17,380\n这就非常搞笑了\nWell, that's clearly\npretty ridiculous.\n\n816\n00:45:17,380 --> 00:45:21,660\n\n817\n00:45:21,660 --> 00:45:24,620\n在一开始我们甚至没有在机器中有存放整数的地方\nWe'd not even have room in the\nmachine to store the integers\n\n818\n00:45:24,620 --> 00:45:27,040\n更不用说来检测他们了\nin the first place, much\nless to test them.\n\n819\n00:45:27,040 --> 00:45:29,810\n然后我只要第二个\nAnd then I only want\nthe second one.\n\n820\n00:45:29,810 --> 00:45:36,500\n这种传统的编程风格的威力也有它的弱点\nSee, the power of this\ntraditional programming style\n\n821\n00:45:36,500 --> 00:45:39,860\nis exactly its weakness, that\nwe're mixing up the\n\n822\n00:45:39,860 --> 00:45:45,090\n那是我们混合了enumerating testing accumulating\nenumerating and the testing\nand the accumulating.\n\n823\n00:45:45,090 --> 00:45:46,670\n所以我们不做所有的事\nSo we don't do it all.\n\n824\n00:45:46,670 --> 00:45:52,580\n所以使它在概念上更加丑陋的这个东西使它更加有效\nSo the very thing that makes\nit conceptually ugly is the\n\n825\n00:45:52,580 --> 00:45:55,210\nvery thing that makes\nit efficient.\n\n826\n00:45:55,210 --> 00:45:57,800\n是这样混合的\nIt's this mixing up.\n\n827\n00:45:57,800 --> 00:45:59,840\n所以这看起来我们在早上讲的所有的这些东西只会使你们疑惑\nSo it seems that all I've done\nthis morning so far is just\n\n828\n00:45:59,840 --> 00:46:00,420\nconfuse you.\n\n829\n00:46:00,420 --> 00:46:02,930\n我展示给你们这个优雅的编程方法可能可以工作\nI showed you this wonderful\nway that programming might\n\n830\n00:46:02,930 --> 00:46:05,840\n除了那个不行\nwork, except that it doesn't.\n\n831\n00:46:05,840 --> 00:46:09,040\n好吧 这里是美好的事发生的地方\nWell, here's where the wonderful\nthing happens.\n\n832\n00:46:09,040 --> 00:46:13,210\n在这个游戏里 我门真正可以吃蛋糕 并吃它\nIt turns out in this game that\nwe really can have our cake\n\n833\n00:46:13,210 --> 00:46:14,870\nand eat it too.\n\n834\n00:46:14,870 --> 00:46:20,280\n我的意思是 我们真的可以完全像我写和安排的那样使用流编程\nAnd what I mean by that is\nthat we really can write\n\n835\n00:46:20,280 --> 00:46:24,210\nstream programs exactly like the\nones I wrote and arrange\n\n836\n00:46:24,210 --> 00:46:28,830\n当机器真正运行\nthings so that when the machine\nactually runs, it's as\n\n837\n00:46:28,830 --> 00:46:31,690\n它运行起来和混合generation和test传统编程风格一样有效率\nefficient as running this\ntraditional programming style\n\n838\n00:46:31,690 --> 00:46:36,310\nthat mixes up the generation\nand the test.\n\n839\n00:46:36,310 --> 00:46:40,770\n好吧 那听起来很神奇\nWell, that sounds\npretty magic.\n\n840\n00:46:40,770 --> 00:46:43,690\n这个的关键是流不是列表\nThe key to this is that\nstreams are not lists.\n\n841\n00:46:43,690 --> 00:46:48,090\n\n842\n00:46:48,090 --> 00:46:50,070\n等等 我们将会小心的看到\nWe'll see this carefully in a\nsecond, but for now, let's\n\n843\n00:46:50,070 --> 00:46:52,115\n但现在 让我们再次看看幻灯片\ntake a look at that\nslide again.\n\n844\n00:46:52,115 --> 00:46:55,060\n你应该有的信号处理系统的图片是\nThe image you should have here\nof this signal processing\n\n845\n00:46:55,060 --> 00:47:00,940\nsystem is that what's going to\nhappen is there's this box\n\n846\n00:47:00,940 --> 00:47:05,360\n在这里有一个盒子里面有一个整数\nthat has the integers\nsitting in it.\n\n847\n00:47:05,360 --> 00:47:08,680\n这里有这个filter来连接\nAnd there's this filter that's\nconnected to it and it's\n\n848\n00:47:08,680 --> 00:47:10,940\n并且这个揪住了它们\ntugging on them.\n\n849\n00:47:10,940 --> 00:47:13,680\n然后 那里有揪住这个东西的某人\nAnd then there's someone who's\ntugging on this stuff saying\n\n850\n00:47:13,680 --> 00:47:16,790\n说 那个从filter中出来\nwhat comes out of the filter.\n\n851\n00:47:16,790 --> 00:47:19,630\n你应该有的图片是 \nAnd the image you should have\nis that someone says, well,\n\n852\n00:47:19,630 --> 00:47:24,590\n某些人说 好吧 第一个素数是什么\nwhat's the first prime, and\ntugs on this filter.\n\n853\n00:47:24,590 --> 00:47:28,020\n并且这个filter揪住了整数\nAnd the filter tugs\non the integers.\n\n854\n00:47:28,020 --> 00:47:29,830\n并且你只看这些\nAnd you look only at that much,\nand then say, oh, I\n\n855\n00:47:29,830 --> 00:47:30,930\n然后说 噢 我真的想要第二个\nreally wanted the second one.\n\n856\n00:47:30,930 --> 00:47:33,710\n第二个素数是什么\nWhat's the second prime?\n\n857\n00:47:33,710 --> 00:47:37,730\n没有计算完成 除了当你揪住那些东西\nAnd that no computation gets\ndone except when you tug on\n\n858\n00:47:37,730 --> 00:47:40,500\nthese things.\n\n859\n00:47:40,500 --> 00:47:41,410\n让我们再来试试\nLet me try that again.\n\n860\n00:47:41,410 --> 00:47:43,815\n这是一个小的设备\nThis is a little device.\n\n861\n00:47:43,815 --> 00:47:46,400\n这是一个由Eric Grimson 发明的小型的流机器\nThis is a little stream machine\ninvented by Eric\n\n862\n00:47:46,400 --> 00:47:49,830\n这个大神曾经在麻省理工教这门课\nGrimson who's been teaching\nthis course at MIT.\n\n863\n00:47:49,830 --> 00:47:52,940\n并且这里的图片是一个东西的流\nAnd the image is here's a stream\nof stuff, like a whole\n\n864\n00:47:52,940 --> 00:47:54,780\n像一串整数\nbunch of the integers.\n\n865\n00:47:54,780 --> 00:47:58,700\n并且这里有一些处理中的元素\nAnd here's some processing\nelements.\n\n866\n00:47:58,700 --> 00:48:02,600\n并且 如果说 资格赛map的filter的filter或者一些东西\nAnd if, say, it's filter of\nfilter of map, or something.\n\n867\n00:48:02,600 --> 00:48:05,570\n\n868\n00:48:05,570 --> 00:48:08,760\n并且如果我真的尝试用流作为列表实现\nAnd if I really tried to\nimplement that with streams as\n\n869\n00:48:08,760 --> 00:48:11,520\n我想说得是 我已有了这个列表\nlists, what I'd say is, well,\nI've got this list of things,\n\n870\n00:48:11,520 --> 00:48:12,670\n现在 我开始使用第一个filter\nand now I do the first filter.\n\n871\n00:48:12,670 --> 00:48:14,070\n做所有的这些处理\nSo do all this processing.\n\n872\n00:48:14,070 --> 00:48:18,570\n并且我拿这个来一直进行不断处理\nAnd I take this and I process\nand I process and I process\n\n873\n00:48:18,570 --> 00:48:19,610\nand I process.\n\n874\n00:48:19,610 --> 00:48:21,910\n现在 我已经得到了这个新的流\nAnd now I'm got this\nnew stream.\n\n875\n00:48:21,910 --> 00:48:24,070\n现在我把这结果放在我手上某处\nNow I take that result\nin my hand someplace.\n\n876\n00:48:24,070 --> 00:48:25,260\n并且把第二个和那个接通\nAnd I put that through\nthe second one.\n\n877\n00:48:25,260 --> 00:48:28,110\n然后 我处理整个东西\nAnd I process the whole thing.\n\n878\n00:48:28,110 --> 00:48:29,510\n这个有一个新的流\nAnd there's this new stream.\n\n879\n00:48:29,510 --> 00:48:32,130\n\n880\n00:48:32,130 --> 00:48:35,230\n然后 我拿那个结果  并且我把它和这个用相同方法接通\nAnd then I take the result and\nI put it all the way through\n\n881\n00:48:35,230 --> 00:48:36,360\nthis one the same way.\n\n882\n00:48:36,360 --> 00:48:41,760\n这些将会是流编程将会发生的\nThat's what would happen to\nthese stream programs if\n\n883\n00:48:41,760 --> 00:48:43,860\n如果流只是一个列表\nstreams were just lists.\n\n884\n00:48:43,860 --> 00:48:46,065\n但是实际上 流不是列表 这只是流\nBut in fact, streams aren't\nlists, they're streams. And\n\n885\n00:48:46,065 --> 00:48:47,240\n你将会有的图是一种有点更像这个的东西\nthe image you should have\nis something a little\n\n886\n00:48:47,240 --> 00:48:50,230\nbit more like this.\n\n887\n\n00:48:50,230 --> 00:48:55,880\n我通过数据把这些小玩意连接\nI've got these gadgets connected\nup by this data\n\n888\n00:48:55,880 --> 00:48:57,130\n那个将会从它们那里流出\nthat's flowing out of them.\n\n889\n00:48:57,130 --> 00:48:59,960\n\n890\n00:48:59,960 --> 00:49:04,190\n这里是我原始的流的来源\nAnd here's my original source\nof the streams. It might be\n\n891\n00:49:04,190 --> 00:49:05,980\n这可能开始生成整数\nstarting to generate\nthe integers.\n\n892\n00:49:05,980 --> 00:49:07,580\n现在 如果我想要一个结果 会发生什么呢\nAnd now, what happens\nif I want a result?\n\n893\n00:49:07,580 --> 00:49:10,200\n我把在这里最后的东西揪住\nI tug on the end here.\n\n894\n00:49:10,200 --> 00:49:13,090\n这个元素说 挖 我需要更多的数据\nAnd this element says, gee,\nI need some more data.\n\n895\n00:49:13,090 --> 00:49:15,830\n所以 这个到这里 并且揪住那个\nSo this one comes here\nand tugs on that one.\n\n896\n00:49:15,830 --> 00:49:17,890\n并且它说 挖 我需要更多的数据\nAnd it says, gee, I need\nsome more data.\n\n897\n00:49:17,890 --> 00:49:19,960\n并且这个揪住了这个可能是一个filter的东西 \nAnd this one tugs on this\nthing, which might be a\n\n898\n00:49:19,960 --> 00:49:21,640\n并且说 挖 我需要更多的数据\nfilter, and says, gee, I\nneed some more data.\n\n899\n00:49:21,640 --> 00:49:24,755\n并且只当 这些在这里的最后的东西和我揪住一样多时\nAnd only as much of this thing\nat the end here gets generated\n\n900\n00:49:24,755 --> 00:49:25,780\nas I tugged.\n\n901\n00:49:25,780 --> 00:49:28,030\n并且只当 这些通过处理单元的东西和我抓得一样多时\nAnd only as much of this stuff\ngoes through the processing\n\n902\n00:49:28,030 --> 00:49:30,760\nunits as I'm pulling\non the end I need.\n\n903\n00:49:30,760 --> 00:49:33,720\n那才是你应该有的画面\nThat's the image you should have\nof the difference between\n\n904\n00:49:33,720 --> 00:49:36,580\n实现你到底该怎样做的区别\nimplementing what we're actually\ngoing to do and if\n\n905\n00:49:36,580 --> 00:49:37,830\n并且如果流是列表的话\nstreams were lists.\n\n906\n00:49:37,830 --> 00:49:40,600\n\n907\n00:49:40,600 --> 00:49:42,430\n好吧 我们怎样做这些事\nWell, how do we make\nthis thing?\n\n908\n00:49:42,430 --> 00:49:43,400\n我希望你能有这些图片\nI hope you have the image.\n\n909\n00:49:43,400 --> 00:49:44,947\n窍门是怎样做它\nThe trick is how to make it.\n\n910\n00:49:44,947 --> 00:49:47,930\n\n911\n00:49:47,930 --> 00:49:52,080\n我们想要处理这个流 将它变成数据结构递增计算它本身\nWe want to arrange for a stream\nto be a data structure\n\n912\n00:49:52,080 --> 00:49:55,670\nthat computes itself\nincrementally, an on-demand\n\n913\n00:49:55,670 --> 00:49:56,920\n按需数据结构\ndata structure.\n\n914\n00:49:56,920 --> 00:49:59,220\n\n915\n00:49:59,220 --> 00:50:02,700\n并且基本思想是 \nAnd the basic idea is, again,\none of the very basic ideas\n\n916\n00:50:02,700 --> 00:50:04,490\n再说一下 这个整个课的基本思想是\nthat we're seeing throughout\nthe whole course.\n\n917\n00:50:04,490 --> 00:50:07,440\n那是 在程序和数据之间没有严格的界限\nAnd that is that there's not\na firm distinction between\n\n918\n00:50:07,440 --> 00:50:09,240\nprograms and data.\n\n919\n00:50:09,240 --> 00:50:12,260\n流将会同步这些数据\nSo what a stream is going to be\nis simultaneously this data\n\n920\n00:50:12,260 --> 00:50:15,270\n像这个树的叶子的流\nstructure that you think of,\nlike the stream of the leaves\n\n921\n00:50:15,270 --> 00:50:16,810\nof this tree.\n\n922\n00:50:16,810 --> 00:50:18,880\n但同时 这将会变成聪明的并有计算方法在其中的过程\nBut at the same time, it's\ngoing to be a very clever\n\n923\n00:50:18,880 --> 00:50:23,550\nprocedure that has the method\nof computing in it.\n\n924\n00:50:23,550 --> 00:50:25,930\n好吧 让我们来试试这个\nWell, let me try this.\n\n925\n00:50:25,930 --> 00:50:28,460\n这个结果是 我们不要更加多的原理\nIt's going to turn out that we\ndon't need any more mechanism.\n\n926\n00:50:28,460 --> 00:50:31,150\n我们已经从一个事实中有了我们需要的所有东西\nWe already have everything we\nneed simply from the fact that\n\n927\n00:50:31,150 --> 00:50:32,770\n我们知道如何处理作为第一级对象的过程\nwe know how to handle\nprocedures\n\n928\n00:50:32,770 --> 00:50:35,460\nas first-class objects.\n\n929\n00:50:35,460 --> 00:50:36,880\n好吧 让我们看下这个key\nWell, let's go back\nto the key.\n\n930\n00:50:36,880 --> 00:50:39,030\n关键是 记住 我们有这些操作\nThe key is, remember, we\nhad these operations.\n\n931\n00:50:39,030 --> 00:50:48,080\ncons流 头和尾\nCONS-stream and head and tail.\n\n932\n00:50:48,080 --> 00:50:51,580\n当我开始 我说 你可以将这个想象成cons \nWhen I started, I said you can\nthink about this as CONS and\n\n933\n00:50:51,580 --> 00:50:53,340\n把那个想象成car 把那个相信成cdr\nthink about this as CAR and\nthink about that as\n\n934\n00:50:53,340 --> 00:50:55,080\n但这不是\nCDR, but it's not.\n\n935\n00:50:55,080 --> 00:50:57,550\n现在 让我们看看这些到底是什么\nNow, let's look at what\nthey really are.\n\n936\n00:50:57,550 --> 00:51:09,360\nx和y的cons流将变成接下来东西的缩写\nWell, CONS-stream of x and y is\ngoing to be an abbreviation\n\n937\n00:51:09,360 --> 00:51:19,540\nfor the following thing.\n\n938\n00:51:19,540 --> 00:51:24,470\ncons产生一个序对 普通的cons\nCONS form a pair, ordinary CONS,\nof x to a thing called\n\n939\n00:51:24,470 --> 00:51:28,000\n由一个x和一个delay y构成\ndelay of y.\n\n940\n00:51:28,000 --> 00:51:31,188\n\n941\n00:51:31,188 --> 00:51:34,670\n在我解释那个之前，让我们来写剩余的部分\nAnd before I explain that, let\nme go and write the rest. The\n\n942\n00:51:34,670 --> 00:51:39,790\n流的头将会变成car\nhead of a stream is going\nto be just the CAR.\n\n943\n00:51:39,790 --> 00:51:42,380\n\n944\n00:51:42,380 --> 00:51:47,610\n流的尾部将会变成一种叫 force 流的cdr\nAnd the tail of a stream is\ngoing to be a thing called\n\n945\n00:51:47,610 --> 00:51:56,120\nforce the CDR of the stream.\n\n946\n00:51:56,120 --> 00:51:58,060\n现在让我解释这些\nNow let me explain this.\n\n947\n00:51:58,060 --> 00:52:01,420\n延时将会变成一件特别神奇的事\nDelay is going to be a\nspecial magic thing.\n\n948\n00:52:01,420 --> 00:52:06,240\n延时做的是拿一个表达式产生一个计算当你要求表达式的承诺\nWhat delay does is take an\nexpression and produce a\n\n949\n00:52:06,240 --> 00:52:08,380\npromise to compute\nthat expression\n\n950\n00:52:08,380 --> 00:52:10,600\nwhen you ask for it.\n\n951\n00:52:10,600 --> 00:52:11,980\n在这里不做任何计算\nIt doesn't do any computation\nhere.\n\n952\n00:52:11,980 --> 00:52:14,820\n这仅仅给你一个延时\nIt just gives you\na rain check.\n\n953\n00:52:14,820 --> 00:52:17,110\n这产生了一个承诺\nIt produces a promise.\n\n954\n00:52:17,110 --> 00:52:23,280\ncons流说 我将做一个x\nAnd CONS-stream says I'm going\nto put together in a pair x\n\n955\n00:52:23,280 --> 00:52:25,360\n和一个承诺的序对来计算y\nand a promise to compute y.\n\n956\n00:52:25,360 --> 00:52:28,230\n\n957\n00:52:28,230 --> 00:52:30,200\n现在 如果你想要头 这只是序对里的car\nNow, if I want the head, that's\njust the CAR that I put\n\n958\n00:52:30,200 --> 00:52:31,840\nin the pair.\n\n959\n00:52:31,840 --> 00:52:34,350\n这个的关键是 尾将会在承诺中force调用\nAnd the key is that the\ntail is going to be--\n\n960\n00:52:34,350 --> 00:52:39,110\nforce calls in that promise.\n\n961\n00:52:39,110 --> 00:52:43,690\n尾说 好吧 取得这个承诺  然后 在那个承诺中调用\nTail says, well, take\nthat promise and now\n\n962\n00:52:43,690 --> 00:52:44,610\ncall in that promise.\n\n963\n00:52:44,610 --> 00:52:47,430\n然后我们计算那个东西\nAnd then we compute\nthat thing.\n\n964\n00:52:47,430 --> 00:52:48,740\n这就是工作的方法\nThat's how this is\ngoing to work.\n\n965\n00:52:48,740 --> 00:52:51,550\n那个就是cons流 头 和 尾了\nThat's what CONS-stream, head,\nand tail really are.\n\n966\n00:52:51,550 --> 00:52:54,196\n\n967\n00:52:54,196 --> 00:52:55,570\n现在 让我们来看看这个怎样工作\nNow, let's see how this works.\n\n968\n00:52:55,570 --> 00:52:58,410\n我们将会非常小心地过一遍\nAnd we'll go through this\nfairly carefully.\n\n969\n00:52:58,410 --> 00:53:01,990\n在这个 计算在一万和一百万之间的第二个素数 的例子中 我们将会看到这是如何工作的\nWe're going to see how this\nworks in this example of\n\n970\n00:53:01,990 --> 00:53:08,650\ncomputing the second prime\nbetween 10,000 and a million.\n\n971\n\n00:53:08,650 --> 00:53:11,610\nok 让我们开始    我们有这个表达式\nOK, so we start off and we\nhave this expression.\n\n972\n00:53:11,610 --> 00:53:15,820\n\n973\n00:53:15,820 --> 00:53:20,380\n第二个素数－－ 为在一万和一百万的整数素数性进行filtering\nThe second prime-- the head of\nthe tail of the result of\n\n974\n00:53:20,380 --> 00:53:24,060\nfiltering for primality\nthe integers between\n\n975\n00:53:24,060 --> 00:53:26,710\n10,000 and 1 million.\n\n976\n00:53:26,710 --> 00:53:28,400\n现在 那是什么\nNow, what is that?\n\n977\n00:53:28,400 --> 00:53:35,790\n这是一万和一百万之间的间距\nWhat that is, that interval\nbetween 10,000 and 1 million,\n\n978\n00:53:35,790 --> 00:53:37,480\n好吧 如果你探查enumerate的间距\nwell, if you trace through\nenumerate interval, there\n\n979\n00:53:37,480 --> 00:53:40,250\n这里建立了一个cons流\nbuilds a CONS-stream.\n\n980\n00:53:40,250 --> 00:53:45,880\n并且 cons流是10000的cons的许诺来计算10001到一百万\nAnd the CONS-stream is the CONS\nof 10,000 to a promise to\n\n981\n00:53:45,880 --> 00:53:54,480\ncompute the integers between\n10,001 and 1 million.\n\n982\n00:53:54,480 --> 00:53:55,750\n所以 那就是这个表达式了\nSo that's what this\nexpression is.\n\n983\n00:53:55,750 --> 00:53:57,640\n这里 我使用代换模型\nHere I'm using the substitution\nmodel.\n\n984\n00:53:57,640 --> 00:53:59,690\n我们能使用代换模型的原因是因为我们没有副作用和状态\nAnd we can use the substitution\nmodel because we\n\n985\n00:53:59,690 --> 00:54:01,010\ndon't have side effects\nand state.\n\n986\n00:54:01,010 --> 00:54:04,270\n\n987\n00:54:04,270 --> 00:54:07,860\n所以 我们有一个10000的cons的许诺来计算剩余的整数\nSo I have CONS of 10,000 to a\npromise to compute the rest of\n\n988\n00:54:07,860 --> 00:54:08,380\nthe integers.\n\n989\n00:54:08,380 --> 00:54:09,850\n所以到现在为止只有一个整数得到了enumerated\nSo only one integer, so\nfar, got enumerated.\n\n990\n00:54:09,850 --> 00:54:14,380\n\n991\n00:54:14,380 --> 00:54:16,580\n好的 我将会为了素数性来filter这些东西\nWell, I'm going to filter that\nthing for primality.\n\n992\n00:54:16,580 --> 00:54:19,900\n\n993\n00:54:19,900 --> 00:54:22,360\n再次 你将会回去看过了filter代码\nAgain, you go back and look\nat the filter code.\n\n994\n00:54:22,360 --> 00:54:25,460\nfilter首先测试头\nWhat the filter will first\ndo is test the head.\n\n995\n00:54:25,460 --> 00:54:31,580\n所以在这种情况下 filter将会测试一万\nSo in this case, the filter will\ntest 10,000 and say, oh,\n\n996\n00:54:31,580 --> 00:54:33,500\n然后说一万不是素数\n10,000's not prime.\n\n997\n00:54:33,500 --> 00:54:36,260\n所以我不得不递归的过滤尾\nTherefore, what I have\nto do recursively\n\n998\n00:54:36,260 --> 00:54:39,220\nis filter the tail.\n\n999\n00:54:39,220 --> 00:54:42,550\n这个是什么的尾呢 好吧 这是这个有许诺序对的尾序对的尾\nAnd what's the tail of it, well,\nthat's the tail of this\n\n1000\n00:54:42,550 --> 00:54:46,340\npair with a promise in it.\n\n1001\n00:54:46,340 --> 00:54:49,680\n尾进来了 然后说 好吧 我将要迫使那个\nTail now comes in and says,\nwell, I'm going to force that.\n\n1002\n00:54:49,680 --> 00:54:53,790\n我将要迫使那个许诺 它的意思是\nI'm going to force that promise,\nwhich means now I'm\n\n1003\n00:54:53,790 --> 00:55:00,880\n现在我将要计算10001到一百万之中的整数\ngoing to compute the integers\nbetween 10,001 and 1 million.\n\n1004\n00:55:00,880 --> 00:55:02,970\n好的 所以这个filter现在着眼于那里\nOK, so this filter now\nis looking at that.\n\n1005\n00:55:02,970 --> 00:55:07,810\n\n1006\n00:55:07,810 --> 00:55:10,100\n那个枚举了它本身 好吧 现在我们回到原始枚举情况\nThat enumerate itself, well, now\nwe're back in the original\n\n1007\n00:55:10,100 --> 00:55:11,960\nenumerate situation.\n\n1008\n00:55:11,960 --> 00:55:16,920\nenumerate是第一个东西的cons 10001\nThe enumerate is the CONS of the\nfirst thing, 10,001, onto\n\n1009\n00:55:16,920 --> 00:55:19,740\n映射到一个许诺来计算剩下的\na promise to compute the rest.\n\n1010\n00:55:19,740 --> 00:55:23,060\n所以 现在原始的filter将会着眼于10001\nSo now the primality filter is\ngoing to go look at 10,001.\n\n1011\n00:55:23,060 --> 00:55:25,120\n这将要决定它像那个还是不像\nIt's going to decide if\nit likes that or not.\n\n1012\n00:55:25,120 --> 00:55:27,550\n这个结果是10001不是素数\nIt turns out 10,001\nisn't prime.\n\n1013\n00:55:27,550 --> 00:55:29,610\n所以我将会再次连续不断的进行force\nSo it'll force it again\nand again and again.\n\n1014\n00:55:29,610 --> 00:55:32,920\n\n1015\n00:55:32,920 --> 00:55:37,100\n最后 我觉得第一个素数会是10009\nAnd finally, I think the first\nprime it hits is 10,009.\n\n1016\n00:55:37,100 --> 00:55:40,465\n然后 在这个点上 它将会停止\nAnd at that point, it'll stop.\n\n1017\n00:55:40,465 --> 00:55:42,500\n那个将会变成第一个素数\nAnd that will be the first\nprime, and then eventually,\n\n1018\n00:55:42,500 --> 00:55:45,240\n最后 这将需要第二个素数\nit'll need the second prime.\n\n1019\n00:55:45,240 --> 00:55:47,030\n所以在那个点上\nSo at that point, it\nwill go again.\n\n1020\n00:55:47,030 --> 00:55:51,880\n所以你会发现生成的不会比你实际需要的多\nSo you see what happens is that\nno more gets generated\n\n1021\n00:55:51,880 --> 00:55:53,130\nthan you actually need.\n\n1022\n00:55:53,130 --> 00:55:56,690\n\n1023\n00:55:56,690 --> 00:56:00,060\n那个enumerator将不会比filter生成更多整数\nThat enumerator is not going to\ngenerate any more integers\n\n1024\n00:56:00,060 --> 00:56:02,410\n引入东西来检测素数性\nthan the filter asks it for as\nit's pulling in things to\n\n1025\n00:56:02,410 --> 00:56:04,930\ncheck for primality.\n\n1026\n00:56:04,930 --> 00:56:07,290\n并且这个filter将不会生成比你要求更多的东西\nAnd the filter is not going to\ngenerate any more stuff than\n\n1027\n00:56:07,290 --> 00:56:11,255\n这是尾的头\nyou ask it for, which is\nthe head of the tail.\n\n1028\n00:56:11,255 --> 00:56:17,180\n你看 我们把混合的生成和测试放入计算机\nYou see, what's happened is\nwe've put that mixing of\n\n1029\n00:56:17,180 --> 00:56:20,130\n并且检测在电脑中究竟发生了什么\ngeneration and test into what\nactually happens in the\n\n1030\n00:56:20,130 --> 00:56:24,250\n虽然 那个从我们的程序看来不是很明显\ncomputer, even though that's\nnot apparently what's\n\n1031\n00:56:24,250 --> 00:56:28,160\nhappening from looking\nat our programs.\n\n1032\n00:56:28,160 --> 00:56:30,230\n好的 那看起来简单\nOK, well, that seemed easy.\n\n1033\n00:56:30,230 --> 00:56:33,326\n所有的这些机制会被放入这个神奇的delay中\nAll of this mechanism got put\ninto this magic delay.\n\n1034\n00:56:33,326 --> 00:56:36,900\n所以 你会说 那将会是有魔法的地方\nSo you're saying, gee, that must\nbe where the magic is.\n\n1035\n00:56:36,900 --> 00:56:39,070\n但是看这里也没有魔法\nBut see there's no magic\nthere either.\n\n1036\n00:56:39,070 --> 00:56:40,610\n你知道什么是delay\nYou know what delay is.\n\n1037\n00:56:40,610 --> 00:56:50,040\n在一些表达式上的delay只是一个缩略词\nDelay on some expression is\njust an abbreviation for--\n\n1038\n00:56:50,040 --> 00:56:53,400\n\n1039\n00:56:53,400 --> 00:56:56,490\n好吧 计算表达式的primise是什么\nwell, what's a promise to\ncompute an expression?\n\n1040\n00:56:56,490 --> 00:57:00,700\nlambda of nil 一个没有参数的过程\nLambda of nil, procedure of no\narguments, which is that\n\n1041\n00:57:00,700 --> 00:57:03,000\n就是那个表达式\nexpression.\n\n1042\n00:57:03,000 --> 00:57:03,930\n那就是这个过程\nThat's what a procedure is.\n\n1043\n00:57:03,930 --> 00:57:06,050\n我将会计算一个表达式\nIt says I'm going to compute\nan expression.\n\n1044\n00:57:06,050 --> 00:57:07,460\n什么是force\nWhat's force?\n\n1045\n00:57:07,460 --> 00:57:10,800\n我怎么着手一个许诺\nHow do I take up a promise?\n\n1046\n00:57:10,800 --> 00:57:15,890\n好的 一些过程的force   一个许诺 只是运行它\nWell, force of some procedure,\na promise, is just run it.\n\n1047\n00:57:15,890 --> 00:57:18,710\n\n1048\n00:57:18,710 --> 00:57:20,120\n做好了\nDone.\n\n1049\n00:57:20,120 --> 00:57:23,580\n所以 这里完全没有魔法\nSo there's no magic\nthere at all.\n\n1050\n00:57:23,580 --> 00:57:26,440\n好吧 我们做了啥\nWell, what have we done?\n\n1051\n00:57:26,440 --> 00:57:29,510\n我们说 老风格\nWe said the old style,\ntraditional style of\n\n1052\n00:57:29,510 --> 00:57:30,960\n传统的编程风格将会是更加有效的\nprogramming is more efficient.\n\n1053\n00:57:30,960 --> 00:57:35,260\n流是更加的清晰明白的\nAnd the stream thing is\nmore perspicuous.\n\n1054\n00:57:35,260 --> 00:57:40,070\n并且我们使用delay设法使流过程运行的像其他的过程一样\nAnd we managed to make the\nstream procedures run like the\n\n1055\n00:57:40,070 --> 00:57:43,350\nother procedures\nby using delay.\n\n1056\n00:57:43,350 --> 00:57:46,880\ndelay为我们做的事是在我们从发生在机器中的真实顺序中程序事务上表面的顺序上进行解耦\nAnd the thing that delay did\nfor us was to de-couple the\n\n1057\n00:57:46,880 --> 00:57:52,150\napparent order of events in our\nprograms from the actual\n\n1058\n00:57:52,150 --> 00:57:54,440\norder of events that happened\nin the machine.\n\n1059\n00:57:54,440 --> 00:57:56,540\n那就是delay所做的\nThat's really what\ndelay is doing.\n\n1060\n00:57:56,540 --> 00:57:58,290\n就是这样\nThat's exactly the\nwhole point.\n\n1061\n00:57:58,290 --> 00:58:04,720\n我们放弃了当我们的过程开始运行的想法\nWe've given up the idea that our\nprocedures, as they run,\n\n1062\n00:58:04,720 --> 00:58:09,182\n或者 当我们看到它们 映射一些时间的清晰概念\nor as we look at them, mirror\nsome clear notion of time.\n\n1063\n00:58:09,182 --> 00:58:12,960\n然后 通过放弃那个 我们给delay自由来处理在计算事件的顺序\nAnd by giving that up, we give\ndelay the freedom to arrange\n\n1064\n00:58:12,960 --> 00:58:16,690\nthe order of events in the\ncomputation the way it likes.\n\n1065\n00:58:16,690 --> 00:58:17,610\n整个思想就是这样\nThat's the whole idea.\n\n1066\n00:58:17,610 --> 00:58:20,640\n我们de-couple在我们程序上事件表面上的顺序\nWe de-couple the apparent\norder of events in our\n\n1067\n00:58:20,640 --> 00:58:24,200\nprograms from the actual order\nof events in the computer.\n\n1068\n00:58:24,200 --> 00:58:25,770\n好的 这里还有一个细节\nOK, well there's one\nmore detail.\n\n1069\n00:58:25,770 --> 00:58:27,750\n这是是技术上的细节\nIt's just a technical detail,\nbut it's actually\n\n1070\n00:58:27,750 --> 00:58:29,730\n但是 这个其实是很重要的\nan important one.\n\n1071\n00:58:29,730 --> 00:58:32,190\n当你运行了这些递归循环的程序\nAs you run through these\nrecursive programs unwinding,\n\n1072\n00:58:32,190 --> 00:58:35,360\n你将会看到很多像这个的东西 像尾部的尾部的尾部\nyou'll see a lot of things that\nlook like tail of the\n\n1073\n00:58:35,360 --> 00:58:39,320\ntail of the tail.\n\n1074\n00:58:39,320 --> 00:58:41,840\n当我使用consing往下到一个流  这将是会发生的事\nThat's the kind of thing that\nwould happen as I go CONSing\n\n1075\n00:58:41,840 --> 00:58:43,860\ndown a stream all the way.\n\n1076\n00:58:43,860 --> 00:58:47,170\n并且如果 我每次做那个事\nAnd if each time I'm doing that,\neach time to compute a\n\n1077\n00:58:47,170 --> 00:58:51,830\n每次计算尾部 我求出一个过程的值\ntail, I evaluate a procedure\nwhich then has to go\n\n1078\n00:58:51,830 --> 00:58:54,270\n然后 不得不再次计算那个尾部 然后再次计算那个尾部\nre-compute its tail, and\nre-compute its tail and\n\n1079\n00:58:54,270 --> 00:58:56,380\n然后每次计算那个尾部 \nrecompute its tail each time,\nyou can see that's very\n\n1080\n00:58:56,380 --> 00:58:59,610\n你可以看到那真是非常的不方便 \ninefficient compared to just\nhaving a list where the\n\n1081\n00:58:59,610 --> 00:59:02,510\n并且 我得到下一个尾部 我不需要每次再次计算每个尾\nelements are all there, and I\ndon't have to re-compute each\n\n1082\n00:59:02,510 --> 00:59:05,290\ntail every time I get\nthe next tail.\n\n1083\n00:59:05,290 --> 00:59:15,030\n所以这个小小的改变 改变了delay\nSo there's one little hack to\nslightly change what delay is,\n\n1084\n00:59:15,030 --> 00:59:17,380\n并且使这个事－－\nand make it a thing which is--\n\n1085\n00:59:17,380 --> 00:59:20,390\n我将会使用这种方法来写\nI'll write it this way.\n\n1086\n00:59:20,390 --> 00:59:27,360\n真实的实现 延时是一个对这个东西的缩略词\nThe actual implementation, delay\nis an abbreviation for\n\n1087\n00:59:27,360 --> 00:59:31,000\nmemo-proc的过程\nthis thing, memo-proc\nof a procedure.\n\n1088\n00:59:31,000 --> 00:59:35,150\nmemo-proc是一个特别的东西 这个东西转换了一个过程\nMemo-proc is a special thing\nthat transforms a procedure.\n\n1089\n00:59:35,150 --> 00:59:39,250\n拿一个没有参数的过程\nWhat it does is it takes a\nprocedure of no arguments and\n\n1090\n00:59:39,250 --> 00:59:42,190\n然后把它转换进一个过程\nit transforms it into a\nprocedure that'll only have to\n\n1091\n00:59:42,190 --> 00:59:44,806\n这个过程只需要做一次计算\ndo its computation once.\n\n1092\n00:59:44,806 --> 00:59:48,700\n我的意思是  你给它一个过程\nAnd what I mean by that is,\nyou give it a procedure.\n\n1093\n00:59:48,700 --> 00:59:51,950\nmemo-proc的结果 将会是一个新的过程\nThe result of memo-proc will be\na new procedure, which the\n\n1094\n00:59:51,950 --> 00:59:55,370\n第一次调用这个过程后 将会运行院士的过程\nfirst time you call it, will\nrun the original procedure,\n\n1095\n00:59:55,370 --> 01:00:00,040\n记住得到的结果  \nremember what result it got, and\nthen from ever on after,\n\n1096\n01:00:00,040 --> 01:00:01,610\n当你调用它 这将不会做这个计算\nwhen you call it, it just\nwon't have to do the\n\n1097\n01:00:01,610 --> 01:00:02,360\ncomputation.\n\n1098\n01:00:02,360 --> 01:00:05,200\n这将会在某个地点cached结果\nIt will have cached that\nresult someplace.\n\n1099\n01:00:05,200 --> 01:00:06,550\n这个是memo-proc的实现\nAnd here's an implementation\nof memo-proc.\n\n1100\n01:00:06,550 --> 01:00:11,210\n\n1101\n01:00:11,210 --> 01:00:12,710\n当你有了这个想法 实现就变得简单了\nOnce you have the idea, it's\neasy to implement.\n\n1102\n01:00:12,710 --> 01:00:15,830\nmemo-proc就是这个有两个flags的小东西\nMemo-proc is this little\nthing that has two\n\n1103\n01:00:15,830 --> 01:00:17,390\nlittle flags in there.\n\n1104\n01:00:17,390 --> 01:00:20,320\n它说 我已经开始运行了吗\nIt says, have I already\nbeen run?\n\n1105\n01:00:20,320 --> 01:00:23,620\n一开始它说 不 我还没有开始运行\nAnd initially it says, no, I\nhaven't already been run.\n\n1106\n01:00:23,620 --> 01:00:29,070\n上次 我运行的结果是什么\nAnd what was the result I got\nthe last time I was run?\n\n1107\n01:00:29,070 --> 01:00:32,200\n所以 memo-proc用一个叫proc的过程\nSo memo-proc takes a procedure\ncalled proc, and it returns a\n\n1108\n01:00:32,200 --> 01:00:34,360\n这个过程返回了一个没有参数的新的过程\nnew procedure of no arguments.\n\n1109\n01:00:34,360 --> 01:00:38,610\nprov被认为是一个没有参数的过程\nProc is supposed to be a\nprocedure of no arguments.\n\n1110\n01:00:38,610 --> 01:00:42,970\n他说 如果我没有已经运行\nAnd it says, oh, if I'm not\nalready run, then I'm going to\n\n1111\n01:00:42,970 --> 01:00:44,430\n然后我将会做一个序列的事情\ndo a sequence of things.\n\n1112\n01:00:44,430 --> 01:00:48,450\n我将会计算proc 我将会保存那个\nI'm going to compute proc,\nI'm going to save that.\n\n1113\n01:00:48,450 --> 01:00:51,140\n我将会存储那个在变量的结果\nI'm going to stash that in\nthe variable result.\n\n1114\n01:00:51,140 --> 01:00:53,510\n我将会为我做一个笔记 来表示 我已经运行了\nI'm going to make a note to\nmyself that I've already been\n\n1115\n01:00:53,510 --> 01:00:56,610\n然后 我将会返回结果\nrun, and then I'll return\nthe result.\n\n1116\n01:00:56,610 --> 01:00:59,010\n所以 那时如果你计算它  如果它没有运行\nSo that's if you compute it\nif it's not already run.\n\n1117\n01:00:59,010 --> 01:01:01,040\n如果你调用它 并且这个已经运行了\nIf you call it and it's already\nbeen run, it just\n\n1118\n01:01:01,040 --> 01:01:03,420\n这个只会返回结果\nreturns the result.\n\n1119\n01:01:03,420 --> 01:01:08,400\n所以 这是一个有点聪明的hack叫memoization\nSo that's a little clever\nhack called memoization.\n\n1120\n01:01:08,400 --> 01:01:12,100\n在这个情况 \nAnd in this case, it short\ncircuits having to re-compute\n\n1121\n01:01:12,100 --> 01:01:15,270\n这短路不得不再次计算尾部的尾部的尾部等等等等\nthe tail of the tail of the tail\nof the tail of the tail.\n\n1122\n01:01:15,270 --> 01:01:17,810\n这里甚至不是那么无效率\nSo there isn't even that\nkind of inefficiency.\n\n1123\n01:01:17,810 --> 01:01:20,590\n事实上 流将会和上一个程序有一样的效率\nAnd in fact, the streams will\nrun with pretty much the same\n\n1124\n01:01:20,590 --> 01:01:24,210\nefficiency as the other\nprograms precisely.\n\n1125\n01:01:24,210 --> 01:01:28,110\n记住 再说一下 这整个思想是\nAnd remember, again, the whole\nidea of this is that we've\n\n1126\n01:01:28,110 --> 01:01:32,390\n我们使用了一个事实：过程和数据之间没有一个合适的分界线\nused the fact that there's no\nreally good dividing line\n\n1127\n01:01:32,390 --> 01:01:33,610\nbetween procedures and data.\n\n1128\n01:01:33,610 --> 01:01:36,510\n我们写的数据结构在事实上 都在某些方面像过程\nWe've written data structures\nthat, in fact, are sort of\n\n1129\n01:01:36,510 --> 01:01:38,760\nlike procedures.\n\n1130\n01:01:38,760 --> 01:01:45,280\n允许我们做的是 在这个iteration位置带一个普遍的控制结构的例子\nAnd what that's allowed us to\ndo is take an example of a\n\n1131\n01:01:45,280 --> 01:01:49,620\ncommon control structure,\nin this place iteration.\n\n1132\n01:01:49,620 --> 01:01:52,460\n并且 我们建造了一个数据结构\nAnd we've built a data structure\nwhich, since itself\n\n1133\n01:01:52,460 --> 01:01:54,530\n因为它本身是一个过程\nis a procedure, kind of has\nthis iteration control\n\n1134\n01:01:54,530 --> 01:01:55,496\n里面有这个iteration控制结构\nstructure in it.\n\n1135\n01:01:55,496 --> 01:01:58,650\n那个就是流了\nAnd that's really what\nstreams are.\n\n1136\n01:01:58,650 --> 01:01:59,900\n好的 有什么问题\nOK, questions?\n\n1137\n01:01:59,900 --> 01:02:03,950\n\n1138\n01:02:03,950 --> 01:02:06,110\n你的尾尾尾描述 \nAUDIENCE: Your description\nof tail-tail-tail, if I\n\n1139\n01:02:06,110 --> 01:02:10,050\n如果我理解的是对的\nunderstand it correctly, force\nis actually execution of a\n\n1140\n01:02:10,050 --> 01:02:13,052\nforce只是一个过程的执行 如果它被完成没有使用这个memo-proc\nprocedure, if it's done without\nthis memo-proc thing.\n\n1141\n01:02:13,052 --> 01:02:16,380\n并且 你暗示那个memo-proc 避免了这个问题\nAnd you implied that memo-proc\ngets around that problem.\n\n1142\n01:02:16,380 --> 01:02:20,580\n这个\nDoesn't it only get around it\nif tail-tail-tail is always\n\n1143\n01:02:20,580 --> 01:02:22,550\n如果 尾尾尾 总是完全一样的执行\nexecuting exactly the same--\n\n1144\n01:02:22,550 --> 01:02:23,500\n欧  那个是－－\nPROFESSOR: Oh, that's--\n\n1145\n01:02:23,500 --> 01:02:23,910\n是的\nsure.\n\n1146\n01:02:23,910 --> 01:02:26,050\n我估计 我漏掉了这点\nAUDIENCE: I guess I\nmissed that point.\n\n1147\n01:02:26,050 --> 01:02:26,540\n欧 是的\nPROFESSOR: Oh, sure.\n\n1148\n01:02:26,540 --> 01:02:27,790\n我的意思是\nI mean the point is--\n\n1149\n01:02:27,790 --> 01:02:31,160\n\n1150\n01:02:31,160 --> 01:02:31,290\n是的\nyeah.\n\n1151\n01:02:31,290 --> 01:02:34,160\n我的意思是 我不得不做这个计算来得到答案\nI mean I have to do a\ncomputation to get the answer.\n\n1152\n01:02:34,160 --> 01:02:37,590\n但是这个点是  当我找到流的尾部\nBut the point is, once I've\nfound the tail of the stream,\n\n1153\n01:02:37,590 --> 01:02:39,530\n来得到 尾的尾\nto get the tail of the tail,\nI shouldn't have had to\n\n1154\n01:02:39,530 --> 01:02:42,980\n我不应该不得不再次计算第一个尾\nre-compute the first tail.\n\n1155\n01:02:42,980 --> 01:02:45,370\n看 如果我没有使用memo-proc\nSee, and if I didn't use\nmemo-proc, that re-computation\n\n1156\n01:02:45,370 --> 01:02:46,460\n那个再次计算将会被做完\nwould have been done.\n\n1157\n01:02:46,460 --> 01:02:47,710\n我理解了\nAUDIENCE: I understand now.\n\n1158\n01:02:47,710 --> 01:02:50,830\n\n1159\n01:02:50,830 --> 01:02:52,550\n在你的一个例子中\nAUDIENCE: In one of your\nexamples, you mentioned that\n\n1160\n01:02:52,550 --> 01:02:55,010\n你提到 我们可以使用替换模型\nwe were able to use the\nsubstitution model because\n\n1161\n01:02:55,010 --> 01:02:56,830\n因为这里没有副作用\nthere are no side effects.\n\n1162\n01:02:56,830 --> 01:03:01,040\n如果 我们有一个单个处理单元\nWhat if we had a single\nprocessing unit--\n\n1163\n01:03:01,040 --> 01:03:03,620\n如果 我们有一个副作用  如果我们有状态\nif we had a side effect,\nif we had a state?\n\n1164\n01:03:03,620 --> 01:03:09,120\n我们可以建立流模型吗\nCould we still practically\nbuild the stream model?\n\n1165\n01:03:09,120 --> 01:03:09,530\n可能吧\nPROFESSOR: Maybe.\n\n1166\n01:03:09,530 --> 01:03:10,540\n这是一个难题\nThat's a hard question.\n\n1167\n01:03:10,540 --> 01:03:15,540\n我们等等再来谈这个替换和副作用没有完全结合好的地方\nI'm going to talk a little bit\nlater about the places where\n\n1168\n01:03:15,540 --> 01:03:18,960\nsubstitution and side effects\ndon't really mix very well.\n\n1169\n01:03:18,960 --> 01:03:21,170\n但是一般的 我觉得这个答案 除非你非常小心\nBut in general, I think the\nanswer is unless you're very\n\n1170\n01:03:21,170 --> 01:03:23,920\n任何数量的副作用将会把每个事情搞糟\ncareful, any amount of side\neffect is going to mess up\n\n1171\n01:03:23,920 --> 01:03:25,170\neverything.\n\n1172\n01:03:25,170 --> 01:03:35,490\n\n1173\n01:03:35,490 --> 01:03:36,150\n学生：不好意思 我没有完全理解 memo-proc操作\nAUDIENCE: Sorry, I didn't\nquite understand\n\n1174\n01:03:36,150 --> 01:03:39,410\nthe memo-proc operation.\n\n1175\n01:03:39,410 --> 01:03:41,990\n你什么时候执行lambda\nWhen do you execute\nthe lambda?\n\n1176\n01:03:41,990 --> 01:03:46,270\n换句话说 当memo-proc被执行\nIn other words, when memo-proc\nis executed, just this lambda\n\n1177\n01:03:46,270 --> 01:03:47,600\nexpression is being generated.\n\n1178\n01:03:47,600 --> 01:03:50,390\n但死 当这个被执行 这个对我不清楚\nBut it's not clear to me\nwhen it's executed.\n\n1179\n01:03:50,390 --> 01:03:51,350\n教授：好的\nPROFESSOR: Right.\n\n1180\n01:03:51,350 --> 01:03:53,890\nmemo-proc做的是   记住\nWhat memo-proc does-- remember,\nthe thing that's\n\n1181\n01:03:53,890 --> 01:03:57,290\n进入memo-proc的东西\ngoing into memo-proc, the thing\nproc, is a procedure of\n\n1182\n01:03:57,290 --> 01:03:57,930\n是proc  是一个没有参数的过程\nno arguments.\n\n1183\n01:03:57,930 --> 01:04:00,390\n某些时候 你将会调用它\nAnd someday, you're\ngoing to call it.\n\n1184\n01:04:00,390 --> 01:04:03,350\nmemo-proc转换那个过程到另一个没有参数 并且你以后会调用的过程\nMemo-proc translates that\nprocedure into another\n\n1185\n01:04:03,350 --> 01:04:05,110\nprocedure of no arguments,\nwhich someday\n\n1186\n01:04:05,110 --> 01:04:06,620\n\nyou're going to call.\n\n1187\n01:04:06,620 --> 01:04:09,890\n那个是lambda\nThat's that lambda.\n\n1188\n01:04:09,890 --> 01:04:17,370\n所以这里 当我一开始建立我流的尾部\nSo here, where I initially\nbuilt as my tail of the\n\n1189\n01:04:17,370 --> 01:04:20,680\n我们以后会调用的没有参数的过程\nstream, say, this procedure\nof no arguments, which\n\n1190\n01:04:20,680 --> 01:04:24,100\nsomeday I'll call.\n\n1191\n01:04:24,100 --> 01:04:27,130\n反而 我将会有流的尾是它的memo-proc\nInstead, I'm going to have\nthe tail of the stream be\n\n1192\n01:04:27,130 --> 01:04:30,650\n这个东西将会在我们以后调用\nmemo-proc of it, which\nsomeday I'll call.\n\n1193\n01:04:30,650 --> 01:04:35,340\nnil的lambda被调用  当你调用memo-proc\nSo that lambda of nil, that gets\ncalled when you call the\n\n1194\n01:04:35,340 --> 01:04:40,990\n当你调用那个memo-proc的结果\nmemo-proc, when you call the\nresult of that memo-proc,\n\n1195\n01:04:40,990 --> 01:04:44,400\n那个结果将会是一般地 当你想要调用你设置的原始的东西\nwhich would be ordinarily when\nyou would have called the\n\n1196\n01:04:44,400 --> 01:04:47,642\noriginal thing that\nyou set it.\n\n1197\n01:04:47,642 --> 01:04:49,690\n好吧 我问这个的原因是\nAUDIENCE: OK, the reason I ask\nis I had a feeling that when\n\n1198\n01:04:49,690 --> 01:04:52,610\n我有一种感觉 当你调用memo-proc  你只需要返回这个lambda\nyou call memo-proc, you just\nreturn this lambda.\n\n1199\n01:04:52,610 --> 01:04:53,770\n教授：对的\nPROFESSOR: That's right.\n\n1200\n01:04:53,770 --> 01:04:58,100\n当你调用memo-proc 你返回lambda\nWhen you call memo-proc,\nyou return the lambda.\n\n1201\n01:04:58,100 --> 01:05:00,090\n你从不计算表达式\nYou never evaluate the\nexpression at all, until the\n\n1202\n01:05:00,090 --> 01:05:02,270\n直到你第一次计算它\nfirst time that you would\nhave evaluated it.\n\n1203\n01:05:02,270 --> 01:05:07,590\n\n1204\n01:05:07,590 --> 01:05:10,000\n学生： 不知道我理解的对不对\nAUDIENCE: Do I understand it\nright that you actually have\n\n1205\n01:05:10,000 --> 01:05:12,980\n你实际建造了一个列表 但是列表中的元素没有被计算\nto build the list up, but\nthe elements of the\n\n1206\n01:05:12,980 --> 01:05:14,240\nlist don't get evaluated?\n\n1207\n01:05:14,240 --> 01:05:15,630\n表达式没有被计算？\nThe expressions don't\nget evaluated?\n\n1208\n01:05:15,630 --> 01:05:18,540\n但是在每个阶段  你实际上建立了一个列表\nBut at each stage, you actually\nare building a list.\n\n1209\n01:05:18,540 --> 01:05:19,750\n教授： 那个是\nPROFESSOR: That's--\n\n1210\n01:05:19,750 --> 01:05:20,700\n我真的应该说的\nI really should have\nsaid this.\n\n1211\n01:05:20,700 --> 01:05:22,270\n这个真不错\nThat's a really good point.\n\n1212\n01:05:22,270 --> 01:05:23,660\n不 这不是很正确的\nNo, it's not quite right.\n\n1213\n01:05:23,660 --> 01:05:25,080\n因为就是这样发生的\nBecause what happens is this.\n\n1214\n01:05:25,080 --> 01:05:26,890\n让我们把这个画成序对\nLet me draw this as pairs.\n\n1215\n01:05:26,890 --> 01:05:29,710\n假设 我将造一个大的流\nSuppose I'm going to make a\nbig stream, like enumerate\n\n1216\n01:05:29,710 --> 01:05:32,740\n像enumerate 间距1到1百万\ninterval, 1 through 1 billion.\n\n1217\n01:05:32,740 --> 01:05:43,045\n那个是 一个1和一个许诺的序对\nWhat that is, is a pair with\na 1 and a promise.\n\n1218\n01:05:43,045 --> 01:05:46,520\n\n1219\n01:05:46,520 --> 01:05:47,890\n完全就是这样\nThat's exactly what it is.\n\n1220\n01:05:47,890 --> 01:05:49,140\n什么都没有被建成\nNothing got built up.\n\n1221\n01:05:49,140 --> 01:05:51,600\n\n1222\n01:05:51,600 --> 01:05:56,370\n当我force这个 然后说 会发生什么\nWhen I go and force this,\nand say, what happens?\n\n1223\n01:05:56,370 --> 01:06:00,530\n好的 这个东西现在也递归一个cons\nWell, this thing is now also\nrecursively a CONS.\n\n1224\n01:06:00,530 --> 01:06:07,770\n所以 这个许诺诺现在是下一个东西 是2和一个许诺\nSo that this promise now is the\nnext thing, which is a 2\n\n1225\n01:06:07,770 --> 01:06:11,350\nand a promise to do more.\n\n1226\n01:06:11,350 --> 01:06:14,470\n等等等等\nAnd so on and so on and so on.\n\n1227\n01:06:14,470 --> 01:06:18,200\n所以 知道你走道流 没有东西被建造\nSo nothing gets built up until\nyou walk down the stream.\n\n1228\n01:06:18,200 --> 01:06:20,790\n因为这里不是列表\nBecause what's sitting here is\nnot the list, but a promise to\n\n1229\n01:06:20,790 --> 01:06:24,250\n而是一个产生列表的许诺\ngenerate the list.\nAnd by promise,\n\n1230\n01:06:24,250 --> 01:06:25,500\n并且通过许诺  我的意思是过程 在技术上的\ntechnically I mean procedure.\n\n1231\n01:06:25,500 --> 01:06:28,050\n\n1232\n01:06:28,050 --> 01:06:30,485\n所以 这没有建成\nSo it doesn't get built up.\n\n1233\n01:06:30,485 --> 01:06:34,280\n是的 我应该在这点之前说过了\nYeah, I should have said\nthat before this point.\n\n1234\n01:06:34,280 --> 01:06:34,490\n好的\nOK.\n\n1235\n01:06:34,490 --> 01:06:34,790\n谢谢大家\nThank you.\n\n1236\n01:06:34,790 --> 01:06:36,340\n下面进入休息时间\nLet's take a break.\n\n1237\n01:06:36,340 --> 01:06:55,828\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed thismaterial in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms\n"
  },
  {
    "path": "Sub/lec6b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 6B: Streams, Part 2\n\n\n\nPROFESSOR: OK, well, we've been looking at streams, this signal processing way of putting\nsystems together. And remember, the key idea is that we decouple the apparent order of\n\nevents in our programs from the actual order of events in the computer. And that means\nthat we can start dealing with very long streams and only having to generate the elements\n\non demand. That sort of on-demand computation is built into the stream's data structure.\nSo if we have a very long stream, we only compute what we need. The things only get\n\ncomputed when we actually ask for them.\n\n\n\n\nWell, what are examples? Are they actually asking for them? For instance, we might ask for\n\nthe n-th element of a stream. Here's a procedure that computes the n-th element of a\nstream. An integer n, the n-th element of some stream s, and we just recursively walk down\n\nthe stream. And the end of 0, we compute the head. Otherwise, it's the n-th the minus 1\nelement of the tail of the stream. Those two are just like for Lisp, but the difference is those\n\nelements aren't going to get computed until we walk down, taking successive n -ths. So\n\nthat's one way that the stream elements might get forced.\n\n\n\n\nAnd another way, here's a little procedure that prints a stream. We say print a stream, so to\nprint a stream s. Well, what do we do? We print the head of the stream, and that will cause\n\nthe head to be computed. And then we recursively print stream the tail of the stream. And if\nwe're already done, maybe we have to return something about the message done. OK, and\n\nthen so if you make a stream, you could say here's the stream, this very long stream. And\n\nthen you say print the stream, and the elements of the stream will get computed\nsuccessively as that print calls them. They won't get all computed initially. So in this way,\n\nwe can deal with some very long streams. Well, how long can a stream be? Well, it can be\ninfinitely long.\n\n\n\n\n\nLet's look at an example here on the computer. I could walk up to this computer, and I\ncould say-- how about we'll define the stream of integers starting with some number N, the\n\nstream of positive integers starting with some number n. And that's cons-stream of n onto\nthe integers from one more. So there are the integers.\n\n\n\n\n\nThen I could say let's get all the integers. define the stream of integersto be the integers\nstarting with 1. And now if I say something like what's the what's the 20th integer. So it's\n\n21 because we start counting at 0.\nOr I can do more complicated things. Let me to define a little predicate here. How about\ndefine no-seven. It's going to test an integer, and it's going to say it's not. I take the\n\nremainder of x by 7, I don't get 0. And then I could say define the integers with no sevens\nto be, take all the integers and filter them to have no sevens.\n\n\n\n\n\nSo now I've got the stream of all the integers that are not divisible by seven. So if I say\nwhat's the 100th integer and the list not divisible by seven, I get 117. Or if I'd like to say\n\nwell, gee, what are all of them? So I could say print stream all these integers with no seven,\nit goes off printing. You may have to wait a very long time to see them all.\n\n\n\n\n\nWell, you can start asking, gee, is it really true that this data structure with the integers is\nreally all the integers? And let me draw a picture of that program I just wrote. Here's the\n\ndefinition of the integers again that I just typed in, Right it's a cons of the first integer under\nthe integer starting with the rest. Now, we can make a picture of that and see what it looks\n\nlike.\n\n\n\n\nConceptually, what I have is a box that's the integer starting with n. It takes in some\n\nnumber n, and it's going to return a stream of-- this infinite stream of all integers starting\nwith n. And what do I do? Well, this is an integers from box. What's it got in it? Well, it\n\ntakes in this n, and it increments it. And then it puts the result into recursively another\n\ninteger's from box. It takes the result of that and the original n and puts those together\nwith a cons and forms a stream. So that's a picture of that program I wrote.\n\n\n\n\nLet's see. These kind of diagrams we first saw drawn by Peter Henderson, the same guy\n\nwho did the Escher language. We call them Henderson diagrams. And the convention here is\n\nthat you put these things together. And the solid lines are things coming out are streams,\nand dotted lines are initial values going in. So this one has the shape of -- it takes in some\n\ninteger, some initial value, and outputs a stream.\n\n\n\n\nAgain, you can ask. Is that data structure integers really all the integers? Or is it is\nsomething that's cleverly arranged so that whenever you look for an integer you find it\n\nthere? That's sort of a philosophical question, right? If something is there whenever you\n\nlook, is it really there or not? It's sort of the same sense in which the money in your savings\naccount is in the bank.\nWell, let me do another example. Gee, we started the course with an algorithm from\n\nAlexandria, which was Heron of Alexandria's algorithm for computing the square root. Let's\ntake a look at another Alexandrian algorithm. This one is Eratosthenes method for\n\ncomputing all of the primes. It is called the Sieve of Eratosthenes. And what you do is you\nstart out, and you list all the integers, say, starting with 2. And then you take the first\n\ninteger, and you say, oh, that's prime. And then you go look at the rest, and you cross out\nall the things divisible by 2. So I cross out this and this and this. This takes a long time\n\nbecause I have to do it for all of the integers. So I go through the entire list of integers,\n\ncrossing the ones divisible by 2.\n\n\n\n\nAnd now when I finish with all of the integers, I go back and look and say what am I left\nwith? Well, the first thing that starts there is 3. So 3 is a prime. And now I go back through\n\nwhat I'm left with, and I cross out all the things divisible by 3. So let's see, 9 a nd 15 and 21\n\nand 27 and 33 and so on. I won't finish. Then I see what I'm left with. And the next one I\nhave is 5. Now I can through the rest, and I find the first one that's divisible by 5. I cross\n\nout from the remainder all the ones that are divisible by 5. And I do that, and then I go\nthrough and find 7. Go through all the rest, cross out things divisible 7, and I keep doing\n\nthat forever. And when I'm done, what I'm left with is a list of all the primes. So that's the\nSieve of Eratosthenes.\n\n\n\n\n\nLet's look at it as a computer program. It's a procedure called sieve. Now, I just write what\nI did. I'll say to sieve some stream s. I'm going to build a stream whose first element is the\n\nhead of this. Remember, I always found the first thing I was left with, and th e rest of it is\nthe result of taking the tail of this, filtering it to throw away all the things that are divisible\n\nby the head of this, and now sieving the result. That's just what I did.\n\n\n\n\nAnd now to get the infinite stream of times, we just sieve all the integers starting from 2.\n\nLet's try that. We can actually do it. I typed in the definition of sieve before, I hope, so I can\nsay something like define the primes to be the result of sieving the integers starting with 2.\n\nSo now I've got this list of primes. That's all of the primes, right? So, if for example, what's\nthe 20th prime in that list? 73. See, and that little pause, it was only at the point when I\n\nstarted asking for the 20th prime is that it started computing. Or I can say here let's look at\nall of the primes. And there it goes computing all of the primes. Of course, it will take a\n\nwhile again if I want to look at all of them, so let's stop it.\n\n\n\n\nLet me draw you a picture of that. Well, I've got a picture of that. What's that program\n\nreally look like? Again, some practice with these diagrams, I have a sieve box. How does\nsieve work? It takes in a stream. It splits off the head from the tail. And the first thing that's\n\ngoing to come out of the sieve is the head of the original stream. Then it also takes the\n\nhead and uses that. It takes the stream. It filters the tail and uses the head to filter for\nnondivisibility. It takes the result of nondivisibility and puts it through another sieve box and\n\nputs the result together. So you can think of this sieve a filter, but notice that it's an\ninfinitely recursive filter. Because inside the sieve box is another sieve box, and inside that\n\nis another sieve box and another sieve box.\n\n\n\n\nSo you see we start getting some very powerful things. We're starting to mix th is signal\n\nprocessing view of the world with things like recursion that come from computation. And\nthere are all sorts of interesting things you can do that are like this. All right, any questions?\n\nOK, let's take a break.\n\n\n\n\nWell, we've been looking at a couple of examples of stream programming. All the stream\n\nprocedures that we've looked at so far have the same kind of character. We've been writing\nthese recursive procedures that kind of generate these stream elements one at a time and\n\nput them together in cons-streams. So we've been thinking a lot about generators. There's\nanother way to think about stream processing, and that's to focus not on programs that sort\n\nof process these elements as you walk down the stream, but on things that kind of process\nthe streams all at once.\n\n\n\n\n\nTo show you what I mean, let me start by defining two procedures that will come in handy.\nThe first one's called add streams. Add streams takes two streams: s1 and s2. and. It's\n\ngoing to produce a stream whose elements are the are thecorresponding sums. We just\nsort of add them element-wise. If either stream is empty, we just return the other one.\n\nOtherwise, we're going to make a new stream whose head is the sum of the two heads and\n\nwhose tail is the result of recursively adding the tails. So that will produce the element-wise\nsum of two streams.\n\n\n\n\nAnd then another useful thing to have around is scale stream. Scale stream takes some\n\nconstant number in a stream s and is going to produce the stream of elements of s\n\nmultiplied by this constant. And that's easy, that's just a map of the function of an element\nthat multiplies it by the constant, and we map that down the stream.\n\n\n\n\nSo given those two, let me show you what I mean by programs that operate on streams all\n\nat once. Let's look at this. Suppose I write this. I say define-- I'll call it ones-- to be cons-\nstream of 1 onto ones. What's that? That's going to be an infinite stream of ones because\n\nthe first thing is 1. And the tail of it is a thing whose first thing is 1 and whose tail is a thing\n\nwhose first thing is 1 and so on and so on and so on. So that's an infinite stream of ones.\nAnd now using that, let me give you another definition of the integers. We can define the\n\nintegers to be-- well, the first integer we'll take to be 1, this cons-stream of 1 onto the\nelement-wise sum onto add streams of the integers to ones. The integers are a thing whose\n\nfirst element is 1, and the rest of them you get by taking those integers and incrementing\neach one by one. So the second element of the integers is the first element of the integers\n\nincremented by one. And the rest of that is the next one, and the third element of that is\nthe same as the first element of the tail of the integers incremented by one, which is the\n\nsame as the first element of the original integers incremented by one and incremented by\n\none again and so on.\n\n\n\n\nThat looks pretty suspicious. See, notice that it works because of delay. See, this looks like-\n- let's take a look at ones. This looks like it couldn't even be processed becau se it's suddenly\n\nsaying in order to know what ones is, I say it's cons-stream of something onto ones. The\n\nreason that works is because of that very sneaky hidden delay in there. Because what this\nreally is, remember, cons-stream is just an abbreviation. This really is cons of 1 onto delay\n\nof ones.\n\n\n\n\nSo how does that work? You say I'm going to define ones. First I see what ones is supposed\n\nto be defined as. Well, ones is supposed to be defined as a cons whose first part is 1 and\nwhose second part is, well, it's a promise to compute something that I don't worry about\n\nyet. So it doesn't bother me that at the point I do this definition, ones isn't defined. Having\nrun the definition now, ones is defined. So that when I go and look at the tail of it, it's\n\ndefined. It's very sneaky. And an integer is the same way. I can refer to integers here\nbecause hidden way down-- because of this cons-stream. It's the cons-stream of 1 onto\n\nsomething that I don't worry that yet. So I don't look at it, and I don't notice that inte gers\nisn't defined at the point where I try and run the definition.\n\n\n\n\n\nOK, let me draw a picture of that integers thing because it still maybe seems a little bit\nshaky. What do I do? I've got the stream of ones, and that sort of comes in and goes into\n\nan adder that's going to be this add streams thing. And that goes in-- that's going to put\nout the integers. And the other thing that goes into the adder here is the integer, so there's\n\na little feedback loop. And all I need to start it off is someplace I've go t a stick that initial 1.\n\n\n\n\nIn a real signal processing thing, this might be a delay element with that was initialized to\n\n1. But there's a picture of that ones program. And in fact, that looks a lot like -- if you've\nseen real signal block diagram things, that looks a lot like accumulators, finite state\n\naccumulators. And in fact, we can modify this a little bit to change this into something that\nintegrates a stream or a finite state accumulator, however you like to think about it.\nSo instead of the ones coming in and getting out the integers, what we'll do is say there's a\n\nstream s coming in, and we're going to get out the integral of this, successive values of\nthat, and it looks almost the same. The only thing we're going to do is when s comes in\n\nhere, before we just add it in we're going to multiply it by some number dt. And now what\nwe have here, this is exactly the same thing. We have a box, which is an integrator. And it\n\ntakes in a stream s, and instead of 1 here, we can put the additional value for the integral.\n\n\n\n\nAnd that one looks very much like a signal processing block diagram program. In fact,\n\nhere's the procedure that looks exactly like that. Find the integral of a stream. So an\nintegral's going to take a stream and produce a new stream, and it takes in an initial value\n\nand some time constant. And what do we do? Well, we internally define this thing int, and\nwe make this internal name so we can feed it back, loop it around itself. And int is defined\n\nto be something that starts out at the initial value, and the rest of it is gotten by adding\n\ntogether. We take our input stream, scale it by dt, and add that to int. And now we'll return\nfrom all that the value of integral is this thing int. And we use this internal definition syntax\n\nso we could write a little internal definition that refers to itself.\n\n\n\n\nWell, there are all sorts of things we can do. Let's try this one. how about the Fibonacci\n\nnumbers. You can say define fibs. Well, what are the Fibonacci numbers? They're something\nthat starts out with 0, and the next one is 1. And the rest of the Fibonacci numbers are\n\ngotten by adding the Fibonacci numbers to their own tail. There's a definition of the\nFibonacci numbers.\n\n\n\n\n\nHow does that work? Well, we start off, and someone says compute for us the Fibonacci\nnumbers, and we're going to tell you it starts out with 0 and 1. And everything after the 0\n\nand 1 is gotten by summing two streams. One is the fibs themselves, and the other one is\nthe tail of the fibs.\n\n\n\n\n\nSo if I know that these start out with 0 and 1, I know that the fibs now start out with 0 and\n1, and the tail of the fibs start out with 1. So as soon as I know that, I know that the next\n\none here is 0 plus 1 is 1, and that tells me that the next one here is 1 and the next one here\nis 1. And as soon as I know that, I know that the next one is 2. So the next one here is 2\n\nand the next one here is 2. And this is 3. This one goes to 3, and this is 5. So it's a perfectly\nsensible definition. It's a one -line definition. And again, I could walk over to the computer\n\nand type that in, exactly that, and then say print stream the Fibonacci numbers, and they\nall come flying out.\n\n\n\n\n\nSee, this is a lot like learning about recursion again. Instead of thinking that recursive\nprocedures, we have recursively defined data objects. But that shouldn't s urprise you at all,\nbecause by now, you should be coming to really believe that there's no difference really\n\nbetween procedures and data. In fact, in some sense, the underlying streams are\nprocedures sitting there, although we don't think of them that way. So the fact that we have\n\nrecursive procedures, well, then it should be natural that we have recursive data, too.\n\n\n\n\nOK, well, this is all pretty neat. Unfortunately, there are problems that streams aren't going\n\nto solve. Let me show you one of them. See, in the same way, let's imagine that we're\nbuilding an analog computer to solve some differential equation like, say, we want to solve\n\nthe equation y prime dy dt is y squared, and I'm going to give you some initial value. I'll tell\nyou y of 0 equals 1. Let's say dt is equal to something.\n\n\n\n\n\nNow, in the old days, people built analog computers to solve these kinds of things. And the\nway you do that is really simple. You get yourself an integrator, like that one, an integrator\n\nbox. And we put in the initial value y of 0 is 1. And now if we feed something in and get\nsomething out, we'll say, gee, what we're getting out is the answer. And what we're going\n\nto feed in is the derivative, and the derivative is supposed to be the square of the answer.\nSo if we take these values and map using square, and if I feed this around, that's how I\n\nbuild a block diagram for an analog computer that solves this differential equation.\n\n\n\n\nNow, what we'd like to do is write a stream program that looks exactly like that. And what\n\ndo I mean exactly like that? Well, I'd say define y to be the integral of dy starting at 1 with\n0.001 as a time step. And I'd like to say that says this. And then I'd like to say, well, dy is\n\ngotten by mapping the square along y. So define dy to be map square along y. So there's a\n\nstream description of this analog computer, and unfortunately, it doesn't work.\n\n\n\n\nAnd you can see why it doesn't work because when I come in and say define y to be the\nintegral of dy, it says, oh, the integral of y-- huh? Oh, that's undefined. So I can't write this\n\ndefinition before I've written this one. On the other hand, if I try and write this one first, it\n\nsays, oh, I define y to be the map of square along y? Oh, that's not defined yet. So I can't\nwrite this one first, and I can't write that one first. So I can't quite play this game.\n\n\n\n\nWell, is there a way out? See, we can do that with ones. See, over here, we did this thing\n\nones, and we were able to define ones in terms of ones because of this delay that was built\ninside because cons-stream had a delay. Now, why's it sensible? Why's it sensible for cons-\n\nstream to be built with this delay? The reason is that cons-stream can do a useful thing\n\nwithout looking at its tail. See, if I say this is cons -stream of 1 onto something without\nknowing anything about something, I know that the stream starts off with 1. That's why it\n\nwas sensible to build something like cons-stream. So we put a delay in there, and that\nallows us to have this sort of self-referential definition.\nWell, integral is a little bit the same way. See, notice for an integral, I can-- let's go back\nand look at integral for a second. See, notice integral, it makes sense to say what's the first\n\nthing in the integral without knowing the stream that you're integrating. Because the first\nthing in the integral is always going to be the initial value that you're handed. So integral\n\ncould be a procedure like cons-stream. You could define it, and then even before it knows\n\nwhat it's supposed to be integrating, it knows enough to say what its initial value is.\n\n\n\n\nSo we can make a smarter integral, which is aha, you're going to give me a stream to\nintegrate and an initial value, but I really don't have to look at that stream that I'm\n\nsupposed to integrate until you ask me to work down the stream. In other words, integral\n\ncan be like cons-stream, and you can expect that there's going to be a delay around its\nintegrand. And we can write that. Here's a procedure that does that.\n\n\n\n\nAnother version of integral, and this is almost like the previous one, except the stream it's\n\ngoing to get in is going to expect to be a delayed object. And how does this integral work?\n\nWell, the little thing it's going to define inside of itself says on t he cons-stream, the initial\nvalue is the initial value, but only inside of that cons -stream, and remember, there's going\n\nto be a hidden delay inside here. Only inside of that cons-stream will I start looking at what\nthe actual delayed object is.\n\n\n\n\n\nSo my answer is the first thing's the initial value. If anybody now asks me for my tail, at\nthat point, I'm going to force that delayed object-- and I'll call that s-- and I do the add\n\nstreams. So this is an integral which is sort of like cons-stream. It's not going to actually try\nand see what you handed it as the thing to integrate until you look past the first element.\n\nAnd if we do that and we can make this work, all we have to do here is say define y to the\nintegral of delay of y, of delay of dy. So y is going to be the integral of delay of dy starting\n\nat 1, and now this will work. Because I type in the definition of y, and that says, oh, I'm\nsupposed to use the integral of something I don't care about right now because it's a delay.\n\n\n\n\n\nAnd these things, now you define dy. Now, y is defined. So when I define dy, it can see that\ndefinition for y. Everything is now started up. Both streams have their first element. And\n\nthen when I start mapping down, looking at successive elements, both y and dy are\ndefined. So there's a little game you can play that goes a little bit beyond just using the\n\ndelay that's hidden inside streams. Questions? OK, let's take a break.\n\n\n\n\nWell, just before the break, I'm not sure if you noticed it, but something nasty started to\n\nhappen. We've been going along with the streams and divorcing time in the programs from\ntime in the computers, and all that divorcing got hidden inside the streams. And then at the\n\nvery end, we saw that sometimes in order to really take advantage of this method, you\nhave to pull out other delays. You have to write some explicit delays that are not hidden\n\ninside that cons-stream.\n\n\n\n\nAnd I did a very simple example with differential equations, but if you have some very\n\ncomplicated system with all kinds of self -loops, it becomes very, very difficult to see where\nyou need those delays. And if you leave them out by mistake, it becomes very, very difficult\n\nto see why the thing maybe isn't working. So that's kind of mess, that by getting this power\nand allowing us to use delay, we end up with some very complicated programming\n\nsometimes, because it can't all be hidden inside the streams.\n\n\n\n\nWell, is there a way out of that? Yeah, there is a way out of that. We could change the\n\nlanguage so that all procedures acted like cons-stream, so that every procedure\nautomatically has an implicit delay around its arguments. And what would that mean? That\n\nwould mean when you call a procedure, the arguments wouldn't get evaluated. Instead,\nthey'd only be evaluated when you need them, so they might be passed off to some other\n\nprocedure, which wouldn't evaluate them either.\n\n\n\n\nSo all these procedures would be passing promises around. And then finally maybe when\n\nyou finally got down to having to look at the value of something that was handed to a\nprimitive operator would you actually start calling in all those promises. If we did that, since\n\neverything would have a uniform delay, then you wouldn't have to write any explicit delays,\n\nbecause it would be automatically built into the way the language works.\n\n\n\n\nOr another way to say that, technically what I'm describing is what's called -- if we did that,\nour language would be so-called normal-order evaluation language versus what we've\n\nactually been working with, which is called applicative order-- versus applicative-order\n\nevaluation.\n\n\n\n\nAnd remember the substitution model for applicative order. It says when you go and\nevaluate a combination, you find the values of all the pieces. You evaluate the arguments\n\nand then you substitute them in the body of the procedure. Normal order says no, don't do\nthat. What you do is effectively substitute in the body of the procedure, but instead of\n\nevaluating the arguments, you just put a promise to compute them there. Or another way\n\nto say that is you take the expressions for the arguments, if you like, and substitute them in\nthe body of the procedure and go on, and never really simplify anything until you get down\n\nto a primitive operator. So that would be a normal-order language.\nWell, why don't we do that? Because if we did, we'd get all the advantages of delayed\nevaluation with none of the mess. In fact, if we did that and cons was just a delayed\n\nprocedure, that would make cons the same as cons-stream. We wouldn't need streams of\nall because lists would automatically be streams. That's how lists would behave, and data\n\nstructures would behave that way. Everything would behave that way, right? You'd never\n\nreally do any computation until you actually needed the answer. You wouldn't have to worry\nabout all these explicit annoying delays. Well, why don't we do that?\n\n\n\n\nFirst of all, I should say people do do that. There's some very beautiful languages. One of\n\nthe very nicest is a language called Miranda, which is developed by David Turner at the\n\nUniversity of Kent. And that's how this language works. It's a normal-order language and its\ndata structures, which look like lists, are actually streams. And you write ordinary\n\nprocedures in Miranda, and they do these prime things and eight queens things, just\nwithout anything special. It's all built in there. But there's a price.\n\n\n\n\n\nRemember how we got here. We're decoupling time in the programs from time in the\nmachines. And if we put delay, that sort of decouples it everywhere, not just in streams.\n\nRemember what we're trying to do. We're trying to think about programming as a way to\nspecify processes. And if we give up too much time, our language becomes more elegant,\n\nbut it becomes a little bit less expressive. There are certain distinctions that we can't draw.\n\n\n\n\nOne of them, for instance, is iteration. Remember this old procedure, iterative factorial, that\n\nwe looked at quite a long time ago. Iterative factorial had a thing, and it said there was an\ninternal procedure, and there was a state which was a product and a counter, and we\n\niterate that going around the loop. And we said that was an iterative procedure because it\ndidn't build up state. And the reason it didn't build up state is because this iter that's called\n\nis just passing these things around to itself. Or in the substitution model, you could see in\nthe substitution model that Jerry did, that in an iterative procedure, that state doesn't have\n\nto grow. And in fact, we said it doesn't, so this is an iteration.\n\n\n\n\nBut now think about this exact same text if we had a normal-order language. What would\n\nhappen is this would no longer be an iterative procedure? And if you really think about the\ndetails of the substitution model, which I'm not going to do here, this expression would\n\ngrow. Why would it grow? It's because when iter calls itself, it calls itself with this product.\nIf it's a normal-order language, that multiplication is not going to get done. That's going to\n\nsay I'm to call myself with a promise to compute this product. And now iter goes around\n\nagain. And I'm going to call myself wit h a promise to compute this product where now one\nof the one factors is a promise. And I call myself again. And if you write out the substitution\nmodel for that iterative process, you'll see exactly the same growth in state, all those\n\npromises that are getting remembered that have to get called in at the very end.\n\n\n\n\nSo one of the disadvantages is that you can't really express iteration. Maybe that's a little\n\ntheoretical reason why not, but in fact, people who are trying to write real operating\nsystems in these languages are running into exactly these types of problems. Like it's\n\nperfectly possible to implement a text editor in languages like these. But after you work a\nwhile, you suddenly have 3 megabytes of stuff, which is -- I guess they call them the\n\ndragging tail problem of people who are looking at these, of promises that sort of haven't\nbeen called in because you couldn't quite express an iteration. And one of the research\n\nquestions in these kinds of languages are figuring out the right compiler technology to get\nrid of the so-called dragging tails. It's not simple.\n\n\n\n\n\nBut there's another kind of more striking issue about why you just don't go ahead and make\nyour language normal order. And the reason is that normal -order evaluation and side effects\n\njust don't mix. They just don't go together very well. Somehow, you can't-- it's sort of you\ncan't simultaneously go around trying to model objects with local state and change and at\n\nthe same time do these normal-order tricks of de-coupling time. Let me just show you a\n\nreally simple example, very, very simple.\n\n\n\n\nSuppose we had a normal-order language. And I'm going to start out in this language. This\nis now normal order. I'm going to define x to be 0. It's just some variable I'll initialize. And\n\nnow I'm going to define this little funny function, which is an identity functio n. And what it\n\ndoes, it keeps track of the last time you called it using x. So the identity of n just returns n,\nbut it sets x to be n. And now I'll define a little increment function, which is a very little,\n\nsimple scenario.\n\n\n\n\nNow, imagine I'm interacting with this in the normal-order language, and I type the\n\nfollowing. I say define y to be increment the identity function of 3, so y is going to be 4.\nNow, I say what's x? Well, x should have been the value that was remembered last when I\n\ncalled the identity function. So you'd expect to say, well, x is 3 at this point, but it's not.\nBecause when I defined y here, what I really defined y to be increment of a promise to do\n\nthis thing. So I didn't look at y, so that identity function didn't get run. So if I type in this\ndefinition and look at x, I'm going to get 0.\n\n\n\n\n\nNow, if I go look at y and say what's y, say y is 4, looking at y, that very active looking at y\ncaused the identity function to be run. And now x will get remembered as 3. So here x will\n\nbe 0. Here, x will be 3. That's a tiny, little, simple scenario, but you can see what kind of a\nmess that's going to make for debugging interactive programs when you have normal-order\n\nevaluation.\n\n\n\n\nIt's very confusing. But it's very confusing for a very deep reason, which is that the whole\n\nidea of putting in delays is that you throw away time. That's why we can have these infinite\nprocesses. Since we've thrown away time, we don't have to wait for them to run, right? We\n\ndecouple the order of events in the computer from what we write in our programs. But\nwhen we talk about state and set and change, that's exactly what we do want control of. So\n\nit's almost as if there's this fundamental contradiction in what you want.\n\n\n\n\nAnd that brings us back to these sort of philosophical mutterings about what is it that you're\n\ntrying to model and how do you look at the world. Or sometimes this is called the debate\nover functional programming. A so-called purely functional language is one that just doesn't\n\nhave any side effects. Since you have no side effects, there's no assignment operator, so\nthere are no terrible consequences of it. You can use a substitution-like thing. Programs\n\nreally are like mathematics and not like models in the real world, not like objects in the real\nworld.\n\n\n\n\n\nThere are a lot of wonderful things about functional languages. Since there's no time, you\nnever have any synchronization problems. And if you want to put something into a parallel\n\nalgorithm, you can run the pieces of that parallel processing any way you want. There's just\nnever any synchronization to worry that, and it's a very congenial environment for doing\n\nthis. The price is you give up assignment. So an advocate of a functional language would\n\nsay, gee, that's just a tiny price to pay. You probably shouldn't use assignment most of the\ntime anyway. And if you just give up assignment, you can be in this much, much nicer world\n\nthan this place with objects.\n\n\n\n\nWell, what's the rejoinder to that? Remember how we got into this mess. We started trying\n\nto model things that had local state. So remember Jerry's random number generator. There\nwas this random number generator that had some little state in it to compute the next\n\nrandom number and the next random number and the next random number. And we\nwanted to hide that state away from the Cesaro compute part process, and that's why we\n\nneeded set. We wanted to package that stated modularly.\n\n\n\n\nWell, a functional programming person would say, well, you're just all wet. I mean, you can\n\nwrite a perfectly good modular program. It's just you're thinking about modularity wrong.\nYou're hung up in this next random number and the next random number and the next\n\nrandom number. Why don't you just say let's write a program. Let's write an enumerator\nwhich just generates an infinite stream of random numbers. We can sort of have that\nstream all at once, and that's going to be our source of random numbers. And then if you\n\nlike, you can put that through some sort of processor, which is -- I don't know-- a Cesaro\ntest, and that can do what it wants.\n\n\n\n\n\nAnd what would come out of there would be a stream of successive approximations to pi. So\nas we looked further down this stream, we'd tug on this Cesaro thing, and it would pull out\n\nmore and more random numbers. And the further and further we look down the stream, the\nbetter an approximation we'd get to pi. And it would do exactly the same as the other\n\ncomputation, except we're thinking about the modularity different. We're saying imagine we\nhad all those infinite streams of random numbers all at once. You can see the details of this\n\nprocedure in the book.\n\n\n\n\nSimilarly, there are other things that we tend to get locked into on this one and that one\n\nand the next one and the next one, which don't have to be that way. Like you might think\nabout like a banking system, which is a very simple idea. Imagine we have a program that\n\nsort of represents a bank account. The bank account might have in it -- if we looked at this\nin a sort of message-passing view of the world, we'd say a bank account is an object that\n\nhas some local state in there, which is the balance, say.\n\n\n\n\nAnd a user using this system comes and sends a transaction request. So the user sends a\n\ntransaction request, like deposit some money, and the bank account maybe -- let's say the\nbank account always responds with what the current balance is. The user says let's deposits\n\nsome money, and the bank account sends back a message which is the balance. And the\n\nuser says deposit some more, and the bank account sends back a message. And just like\nthe random number generator, you'd say, gee, we would like to use set. We'd like to have\n\nbalance be a piece of local state inside this bank account because we want to separate the\nstate of the user from the state of the bank account.\n\n\n\n\n\nWell, that's the message-processing view. There's a stream view with that thing, which does\nthe same thing without any set or side effects. And the idea is again we don't think about\n\nanything having local state. We think about the bank account as something that's going to\nprocess a stream of transaction requests. So think about this bank account not as\n\nsomething that goes message by message, but something that takes in a stream of\ntransaction requests like maybe successive deposit announced. 1, 2, 2, 4, those might be\n\nsuccessive amounts to deposit. And then coming out of it is the successive balances 1, 3, 5,\n9.\n\n\n\n\n\nSo we think of the bank account not as something that has state, but something that acts\nsort of on the infinite stream of requests. But remember, we've thrown away time. So what\nwe can do is if the user's here, we can have this infinite stream of requestsbeing generated\n\none at a time coming from the user and this transaction stream coming back on a printer\nbeing printed one at a time. And if we drew a little line here, right there to the user, the\n\nuser couldn't tell that this system doesn't have state. It looks just like the other one, but\nthere's no state in there.\n\n\n\n\n\nAnd by the way, just to show you, here's an actual implementation of this -- we'll call it\nmake deposit account because you can only deposit. It takes an initial balance and then a\n\nstream of deposits you might make. And what is it? Well, it's just cons-stream of the\nbalance onto make a new account stream whose initial balance is the old balance plus the\n\nfirst thing in the deposit stream and make deposit account works on the rest of which is the\ntail of the deposit stream. So there's sort of a very typical message-passing, object-oriented\n\nthing that's done without side effects at all. There are very many things you can do this\n\nway.\n\n\n\n\nWell, can you do everything without assignment? Can everybody g o over to purely\nfunctional languages? Well, we don't know, but there seem to be places where purely\n\nfunctional programming breaks down. Where it starts hurting is when you have things like\n\nthis, but you also mix it up with the other things that we had to worry that, which are\nobjects and sharing and two independent agents being the same.\n\n\n\n\nSo under a typical one, suppose you want to extend this bank account. So here's a bank\n\naccount. Bank accounts take in a stream of transaction requests and put out stream s of,\n\nsay, balances or responses to that. But suppose you want to model the fact that this is a\njoint bank account between two independent people. So suppose there are two people, say,\n\nBill and Dave, who have a joint bank account. How would you model this?\n\n\n\n\nWell, Bill puts out a stream of transaction requests, and Dave puts out a stream of\n\ntransaction requests, and somehow, they have to merge into this bank account. So what\nyou might do is write a little stream processing thing called merge, which sort of takes\n\nthese, merges them together, produces a single stream for the bank account. Now they're\nboth talking to the same bank account. That's all great, but how do you write merge?\n\nWhat's this procedure merge? You want to do something that's reasonable.\n\n\n\n\nYour first guess might be to say, well, we'll take alternate requests from Bill and Dave. But\n\nwhat happens if suddenly in the middle of this thing, Dave goes away on vacation for two\nyears? Then Bill's sort of stuck. So what you want to do is-- well, it's hard to describe. What\n\nyou want to do is what people call fair merge. The idea of fair merge is it sort of should do\nthem alternately, but if there's nothing waiting here, it should take one twice.\nNotice I can't even say that without talking about time. So one of the other active\nresearcher areas in functional languages is inventing little things like fair merge and maybe\n\nsome others, which will take the places where I used to need side effects and objects and\nsort of hide them away in some very well-defined modules of the system so that all the\n\nproblems of assignment don't sort of leak out all over the system but are captured in some\n\nfairly well-understood things.\n\n\n\n\nMore generally, I think what you're seeing is that we're running across what I think is a v ery\nbasic problem in computer science, which is how to define languages that somehow can talk\n\nabout delayed evaluation, but also be able to reflect this view that there are objects in the\n\nworld. How do we somehow get both? And I think that's a very hard problem. And it may be\nthat it's a very hard problem that has almost nothing to do with computer science, that it\n\nreally is a problem having to do with two very incompatible ways of looking at the world.\nOK, questions?\n\n\n\n\n\nAUDIENCE: You mentioned earlier that once you introduce assignment, the general rule for\nusing the substitution model is you can't. Unless you're very careful, you can't.\n\n\n\n\nPROFESSOR: Right.\n\n\n\n\n\nAUDIENCE: Is there a set of techniques or a set of guidelines for localizing the effects of\nassignment so that the very careful becomes defined?\n\n\n\n\n\nPROFESSOR: I don't know. Let me think. Well, certainly, there was an assignment inside\nmemo proc, but that was sort of hidden away. It ended up not making any difference. Part\n\nof the reason for that is once this thing triggered that it had run and gotten an answer, that\nanswer will never change. So that was sort of a one-time assignment. So one very general\n\nthing you can do is if you only do what's called a one-time assignment and never change\nanything, then you can do better.\n\n\n\n\n\nOne of the problems in this merge thing, people have-- let me see if this is right. I think it's\ntrue that with fair merge, with just fair merge, you can begin effectively simulating\n\nassignment in the rest of the language. It seems likeanything you do to go outside-- I'm\nnot quite sure that's true for fair merge, but it's true of a little bit more general things that\n\npeople have been doing. So it might be that any little bit you put in, suddenly if they allow\nyou to build arbitrary stuff, it's almost as bad as having assignment altogether. But that's\n\nan area that people are thinking about now.\n\n\n\n\nAUDIENCE: I guess I don't see the problem here with merge if I call Bill, if Bill is a\n\nprocedure, then Bill is going to increment the bank account or build the list that 's going to\nput in the next element. If I call Dave twice in a row, that will do that. I'm not sure where\n\nfair merge has to be involved.\n\n\n\n\nPROFESSOR: The problem is imagine these really as people. See, here I have the user\n\nwho's interacting with this bank account. Put in a request, get an answer. Put in a request,\nget an answer.\n\n\n\n\nAUDIENCE: Right.\n\n\n\n\n\nPROFESSOR: But if the only way I can process request is to alternate them from two\npeople--\n\n\n\n\n\nAUDIENCE: Well, why would you alternate them?\n\n\n\n\nPROFESSOR: Why don't I?\n\n\n\n\nAUDIENCE: Yes. Why do you?\n\n\n\n\n\nPROFESSOR: Think of them as real people, right? This guy might go away for a year. And\nyou're sitting here at the bank account window, and you can't put in two requests because\n\nit's waiting for this guy.\n\n\n\n\nAUDIENCE: Why does it have to be waiting for one?\n\n\n\n\nPROFESSOR: Because it's trying to compute a function. I have to define a function. Another\n\nway to say that is the answer to what comes out of this merge box is not a function of what\ngoes in. Because, see, what would the function be? Suppose he puts in 1, 1, 1, 1, and he\nputs in 2, 2, 2, 2. What's the answer supposed to be? It's not good enough to say it's 1, 2,\n\n1, 2, 1, 2.\n\n\n\n\nAUDIENCE: I understand. But when Bill puts in 1, 1 goes in. When Dave puts in 2 twice, 2\n\ngoes in twice. When Bill puts in--\n\n\n\n\nPROFESSOR: Right.\n\n\n\n\nAUDIENCE: Why can't it be hooked to the time of the input-- the actual procedural--\n\n\n\n\n\nPROFESSOR: Because I don't have time. See, all I can say is I'm going to define a function.\nI don't have time. There's no concept if it's going to alternate, except if nobody's there, it's\n\ngoing to wait a while for him. It's just going to say I have the stream of requests, the\ntimeless infinite streams of all the requests that Dave would have made, right? And the\n\ntimeless infinite stream of all the requests Bill would have made, and I want to operate on\nthem. See, that's how this bank account is working.\n\n\n\n\n\nAnd the problem is that these poor people who are sitting at the bank account windows\nhave the misfortune to exist in time. They don't see their infinite stream of all the requests\n\nthey would have ever made. They're waiting now, and they want an answer. So if you're\nsitting there-- if this is the screen operation on some time-sharing system and it's working\n\nfunctionally, you want an answer then when you talk the character. You don't want it to\nhave to wait for everybody in the whole system to have typed one character before it can\n\nget around to service you. So that's the problem. I mean, the fact that people live in time,\n\napparently. If they didn't, it wouldn't be a problem.\n\n\n\n\nAUDIENCE: I'm afraid I miss the point of having no time in this banking transaction. Isn't\ntime very important? For instance, the sequence of events. If Dave take out $100, then the\n\ntiming sequence should be important. How do you treat transactions as streams?\n\n\n\n\nPROFESSOR: Well, that's the thing I'm saying. This is an example where you can't. You\n\ncan't. The point is what comes out of here is simply not a function of the stream going in\nhere and the stream going in here. It's a function of the stream going in here and the\n\nstream going in here and some kind of information about time, which is precisely what a\nnormal-order language won't let you say.\nAUDIENCE: In order to brings this back into a more functional perspective, could we just\nexplicitly time stamp all the inputs from Bill and Dave and define fair merge to just be the\n\nsort on those time stamps?\n\n\n\n\nPROFESSOR: Yeah, you can do that. You can do that sort of thing. Another thing you could\n\nsay is imagine that really what this function is, is that it does a read every microsecond, and\nthen if there's none there, that's considered an empty one. That's about equivalent to what\n\nyou said. And yes, you can do that, but that's a clg. So it's not quite only implementation\nwe're worried about. We're worried about expressive power in the language, and what we're\n\nrunning across is a real mismatch between what we can say easily and what we'd like to\n\nsay.\n\n\n\n\nAUDIENCE: It sounds like where we're getting hung up with that is the fact it expects one\ninput from both Bill and Dave at the same time.\n\n\n\n\n\nPROFESSOR: It's not quite one, but it's anything you define. So you can say Dave can go\ntwice as often, but if anything you predefine, it's not the right thing. You can't decide at\n\nsome particular function of their input requests. Worse yet, I mean, worse yet, there are\nthings that even merge can't do. One thing you might want to do that's even more general\n\nis suddenly you add somebody else to this bank account system. You go and you add John\n\nto this bank account system. And now there's yet another stream that's going to come into\nthe picture at some time which we haven't prespecified.\n\n\n\n\nSo that's something even fair merge can't do, and they're things called-- I forget-- natagers\n\nor something. That's a generalization of fair merge to allow that. There's a whole sort of\n\nresearch discipline saying how far can you push this functional perspective by adding more\nand more mechanism? And how far does that go before the whole thing breaks down and\n\nyou might as well been using set anyway.\n\n\n\n\nAUDIENCE: You need to set him up on automatic deposit.\n\n\n\n\n[LAUGHTER]\n\n\n\n\n\nPROFESSOR: OK, thank you.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec7a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 7A: Metacircular Evaluator, Part 1\n\n\n\nPROFESSOR: Well today we're going to learn about something quite amazing. We're going\nto understand what we mean by a program a little bit more profoundly than we have up till\n\nnow. Up till now, we've been thinking of programs as describing machines.\n\n\n\n\nSo for example, looking at this still store, we see here is a program for factorial. And what it\n\nis, is a character string description, if you will, of the wiring diagram of a potentially infinite\nmachine. And we can look at that a little bit and just see the idea. That this is a sort of\n\ncompact notation which says, if n is 0, the result is one.\n\n\n\n\nWell here comes n coming into this machine, and if it's 0, then I control this switch in such a\n\nway that the switch allows the output to be one. Otherwise, it's n times factorial of n min us\none. Well, I'm computing factorial of n minus one and multiplying that by n, and, in the case\n\nthat it's not 0, this switch makes the output come from there.\n\n\n\n\nOf course, this is a machine with a potentially infinite number of parts, because factorial\n\noccurs within factorial, so we don't know how deep it has to be. But that's basically what our\nnotation for programs really means to us at this point. It's a character string description, if\n\nyou will, of a wiring diagram that could also be drawn some other way.\n\n\n\n\nAnd, in fact, many people have proposed to me, programming languages look graphical like\nthis. I'm not sure I believe there are many advantages. The major disadvantage, of course,\n\nis that it takes up more space on a page, and, therefore, it's harder to pack into a listing or\n\nto edit very well.\n\n\n\n\nBut in any case, there's something very remarkable that can happen in the competition\nworld which is that you can have something called a universal machine. If we look at the\n\nsecond slide, what we see is a special machine called eval.\n\n\n\n\nThere is a machine called eval, and I'm going to show it to you today. It's very simple. What\n\nis remarkable is that it will fit on the blackboard. However, eval is a machine which takes as\ninput a description of another machine.\nIt could take the wiring diagram of a factorial machine as input. Having done so, it becomes\na simulator for the factorial machine such that, if you put a six in, out comes a 720. That's a\n\nvery remarkable sort of machine. And the most amazing part of itis that it fits on a\nblackboard.\n\n\n\n\n\nBy contrast, one could imagine in the analog electronics world a very different machine, a\nmachine which also was, in some sense, universal, where you gave a circuit diagram as one\n\nof the inputs, for example, of this little low-pass filter, one-pole low-pass filter. And you can\nimagine that you could, for example, scan this out -- the scan lines are the signal that's\n\ndescribing what this machine is to simulate-- then the analog of that which is made out of\n\nelectrical circuits, should configure itself into a filter that has the frequency response\nspecified by the circuit diagram. That's a very hard machine to make, and, surely, there's no\n\nchance that I could put it on a blackboard.\n\n\n\n\nSo we're going to see an amazing thing today. We're going to see, on the blackboard, the\n\nuniversal machine. And we'll see that among other things, it's extremely simple.\n\n\n\n\nNow, we're getting very close to the real spirit in the computer at this point. So I have to\nshow a certain amount of reverence and respect, so I'm going to wear a suit jacket for the\n\nonly time that you'll ever see me wear a suit jacket here. And I think I'm also going to put\n\non an appropriate hat for the occasion. Now, this is a lecturer which I have to warn you --\nlet's see, normally, people under 40 and who don't have several children are advised to be\n\ncareful. If they're really worried, they should leave. Because there's a certain amount of\nmysticism that will appear here which may be disturbing and cause trouble in your minds .\n\n\n\n\n\nWell in any case, let's see, I wish to write for you the evaluator for Lisp. Now the evaluator\nisn't very complicated. It's very much like all the programs we've seen already. That's the\n\namazing part of it. It's going to be-- and I'm going to write it right here-- it's a program\ncalled eval. And it's a procedure of two arguments in expression of an environment. And like\n\nevery interesting procedure, it's a case analysis.\n\n\n\n\nBut before I start on this, I want to tel l you some things. The program we're going to write\n\non the blackboard is ugly, dirty, disgusting, not the way I would write this is a professional.\nIt is written with concrete syntax, meaning you've got really to use lots of CARs and CDRs\n\nwhich is exactly what I told you not to do. That's on purpose in this case, because I want it\nto be small, compact, fit on the blackboard so you can get the whole thing. So I don't want\n\nto use long names like I normally use. I want to use CAR -CDR because it's short.\nNow, that's a trade-off. I don't want you writing programs like this. This is purely for an\neffect. Now, you're going to have to work a little harder to read it, but I'm going to try to\n\nmake it clear as I'm writing it. I'm also-- this is a pretty much complete interpreter, but\nthere's going to be room for putting in more things-- I'm going to leave out definition and\n\nassignment, just because they are not essential, for a mathematical reason I'll show you\n\nlater and also they take up more space.\n\n\n\n\nBut, in any case, what do we have to do? We have to do a dispatch which breaks the types\nof expressions up into particular classes. So that's what we're going to have here. Well,\n\nwhat expressions are there? Let's look at the kinds of expressions.\n\n\n\n\nWe can have things like the numeral three. What do I want that to do? I can make choices,\n\nbut I think right now, I want it to be a three. That's what I want. So that's easy enough.\nThat means I want, if the thing is a number, the expression, that I want the expression\n\nitself as the answer.\n\n\n\n\nNow the next possibility is things that we represent as symbols. Examples of symbols are\n\nthings like x, n, eval, number, x. What do I mean them to be? Those are things that stand\nfor other things. Those are the variables of our language.\n\n\n\n\n\nAnd so I want to be able to say, for example, that x, for example, transforms to it's value\nwhich might be three. Or I might ask something like car. I want to have as its value -- be\n\nsomething like some procedure, which I don't know what is inside there, perhaps a machine\nlanguage code or something like that. So, well, that's easy enough. I'm going to push that\n\noff on someone else. If something is a symbol, if the expression is a symbol, then I want\n\nthe answer to be the result, looking up the expression in the environment.\n\n\n\n\nNow the environment is a dictionary which maps the symbol names to their values. And\nthat's all it is. How it's done? Well, we'll see that later. It's very easy. It's easy to make data\n\nstructures that are tables of various sorts. But it's only a table, and this is the access\nroutine for some table.\n\n\n\n\n\nWell, the next thing, another kind of expression-- you have things that are described\nconstants that are not numbers, like 'foo. Well, for my convenience, I want to syntactically\n\ntransform that into a list structure which is, quote foo.\nA quoted object, whatever it is, is going to be actually an abbreviation, which is not part of\nthe evaluator but happens somewhere else, an abbreviation for an expression that looks like\n\nthis. This way, I can test for the type of the expression as being a quotation by examining\nthe car of the expression. So I'm not going to worry about that in the evaluator. It's\n\nhappening somewhere earlier in the reader or something.\n\n\n\n\nIf the expression of the expression is quote, then what I want, I want quote foo to itself\n\nevaluate to foo. It's a constant. This is just a way of saying that this evaluates to itself.\nWhat is that? That's the second of the list. It's the second element of the list. The second\n\nelement of the list is it's CADR. So I'm just going to write here, CADR.\n\n\n\n\nWhat else do we have here? We have lambda expressions, for example, lambda of x plus x\n\ny. Well, I going have to have some representation for the procedure which is the value of an\nexpression, of a lambda expression. The procedure here is not the expression lambda x.\n\nThat's the description of it, the textual description.\n\n\n\n\nHowever, what what I going to expect to see here is something which contains an\n\nenvironment as one of its parts if I'm implementing a lexical language. And so what I'd like\nto see is some type flags. I'm going to have to be able to distinguish procedures later,\n\nprocedures which were produced by lambdas, from ones that may be primitive. And so I'm\n\ngoing to have some flag, which I'll jus t arbitrarily call closure, just for historical reasons.\n\n\n\n\nNow, to say what parts of this are important. I'm going to need to know the bound variable\nlist and the body. Well, that's the CDR of this, so it's going to be x and plus x y and some\n\nenvironment. Now this is not something that users should ever see, this is purely a\n\nrepresentation, internally, for a procedure object. It contains a bound variable list, a body,\nand an environment, and some type tag saying, I am a procedure.\n\n\n\n\nI'm going to make one now. So if the CAR of the expression is quote lambda, then what I'm\n\ngoing to put here is-- I'm going to make a list of closure, the CDR of the procedure\ndescription was everything except the lambda, and the current environment.\n\n\n\n\n\nThis implements the rule for environments in the environment model. It has to do with\nconstruction of procedures from lambda expressions. The environment that was around at\n\nthe time the evaluator encountered the lambda expression is the environment where the\nprocedure resulting interprets it's free variables. So that's part of that. And so we have to\ncapture that environment as part of the procedure object. And we'll see how that gets used\n\nlater.\n\n\n\n\nThere are also conditional expressions of things like COND of say,    p one, e one, p two, e\n\ntwo. Where this is a predicate, a predicate is a thing that is either true or false, and the\nexpression to be evaluated if the predicate is true. A set of clauses, if you will, that's the\n\nname for such a thing. So I'm going put that somewhere else. We're going to worry about\nthat in another piece of code.\n\n\n\n\n\nSo EQ-- if the CAR of the expression is COND, then I'm going to do nothing more than\nevaluate the COND, the CDR of the expression. That's all the clauses in the environment\n\nthat I'm given.\n\n\n\n\nWell, there's one more case, arbitrary thing like the sum of x and three, where this is an\n\noperator applied to operands, and there's nothing special about it. It's not one of the special\ncases, the special forms. These are the special forms.\n\n\n\n\nAnd if I were writing here a professional program, again, I would somehow make this data\n\ndirected. So there wouldn't be a sequence of conditionals here, there'd be a dispatch on\n\nsome bits if I were trying to do this in a more professional way. So that, in   fact, I can add to\nthe thing without changing my program much. So, for example, they would run fast, but I'm\n\nnot worried about that.\n\n\n\n\nHere we're trying to look at this in its entirety. So it's else. Well, what do we do? In this\n\ncase, I have to somehow do an addition. Well, I could find out what the plus is. I have to\nfind out what the x and the three are. And then I have to apply the result of finding what\n\nthe plus is to the result of finding out what the x and the three are. We'll have a name for\nthat.\n\n\n\n\n\nSo I'm going to apply the result of evaluating the CAR of the expression-- the car of the\nexpression is the operator-- in the environment given. So evaluating the operator gets me\n\nthe procedure. Now I have to evaluate all the operands to get the arguments. I'll call that\nEVLIST, the CDR of the operands, of the expression, with respect to the environment.\n\nEVLIST will come up later-- EVLIST, apply, COND pair, COND, lambda, define.\nSo that what you are seeing here now is pretty much all there is in the evaluator itself. It's\n\nthe case dispatch on the type of the expression with the default being a general application\nor a combination.\n\n\n\n\n\nNow there is lots of things we haven't defined yet. Let's just look at them and see what they\nare. We're going to have to do this later, evcond. We have to write apply. We're going to\n\nhave to write EVLIST. We're going to write LOOKUP. I think that's everything, isn't there?\nEverything else is something which is simple, or primitive, or something like that.\n\n\n\n\n\nAnd, of course, we could many more special forms here, but that would be a bad idea in\ngeneral in a language. You make a language very complicated by putting a lot of things in\n\nthere. The number of reserve words that should exist in a language should be no more than\na person could remember on his fingers and toes. And I get very upset with languages\n\nwhich have hundreds of reserve words. But that's where the reserve words go.\n\n\n\n\nWell, now let's get to the next part of this, the kernel, apply. What else is this doing? Well,\n\napply's job is to take a procedure and apply it to its arguments after both have been\nevaluated to come up with a procedure and the arguments rather the operator symbols and\n\nthe operand symbols, whatever they are-- symbolic expressions.\n\n\n\n\nSo we will define apply to be a procedure of two arguments, a procedure and arguments.\n\nAnd what does it do? It does nothing very complicated. It's got two cases. Either the\nprocedure is primitive-- And I don't know exactly how that is done.\n\n\n\n\n\nIt's possible there's some type information just like we made closure for, here, being the\ndescription of the type of a compound thing-- probably so. But it is not essential how that\n\nworks, and, in fact, it turns out, as you probably know or have deduced, that you don't need\nany primitives anyway. You can compute anything without them because some of the\n\nlambda that I've been playing with. But it's nice to have them.\n\n\n\n\nSo here we're going to do some magic which I'm not going to explain. Go to machine\n\nlanguage, apply primop. Here's how it adds. Execute an add instruction. However, the\ninteresting part of a language is the glue by which the predicates are glued together.\nSo let's look at that. Well, the other possibility is that this is a compound made up by\n\nexecuting a lambda expression, this is a compound procedure. Well, we'll check its type. If\nit is closure, if it's one of those, then I have to do an eval of the body. The way I do this,\n\nthe way I deal with this at all, is the way I evaluate the application of a procedure to its\narguments, is by evaluating the body of the procedure in the environment resulting from\n\nextending the environment of the procedure with the bindings of the formal parameters of\nthe procedure to the arguments that were passed to it. That was a long senten ce.\n\n\n\n\n\nWell that's easy enough. Now here's going to be a lot of CAR-CDRing. I have to get the\nbody of the procedure. Where's the body of the procedure in here? Well here's the CAR,\n\nhere's the CDR is the whole rest of this. So here's the CADR. And so I see,what I have here\nis the body is the second element of the second element of the procedure. So it's the CADR\n\nof the CADR or the CADADR.\n\n\n\n\nIt's the C-A-D-A-D-R, CADADR of the procedure. To evaluate the body in the result of\n\nbinding that's making up more environment, well I need the formal parameters of the of\nthe procedure, what is that? That's the CAR of the CDR. It's horrible isn't it? --of the\n\nprocedure. Bind that to the arguments that were passed in the environment, which is\n\npassed also as part of the procedure. Well, that's the CAR of the CDR of the CDR of this,\nCADADR, of the procedure. Bind, eval, pair, COND, lamda, define--\n\n\n\n\nNow, of course, if I were being really a neat character, and I was being very careful, I would\n\nactually put an extra case here for checking for certain errors like, did you try to apply one\n\nto an argument? You get a undefined procedure type. So I may as well do that anyway. --\nelse, some sort of error, like that.\n\n\n\n\nNow, of course, again, in some sort of more real system, written for professional reasons,\n\nthis would be written with a case analysis done by some sort of dispatch. Over here, I would\n\nprobably have other cases like, is this compiled code? It's very important.\n\n\n\n\nI might have distinguished the kind of code that's produced by a directly evaluating a\nlambda in interpretation from code that was produced by somebody's compiler or something\n\nlike that. And we'll talk about that later. Or is this a piece Fortran program I have to go off\nand execute. It's a perfectly possible thing, at this point, to do that.\n\n\n\n\n\nIn fact, in this concrete syntax evaluator I'm writing here, there's an assumption built in\nthat this is Lisp, because I'm using CARs and CDRs. CAR means the operator, and CDR\nmeans the operand. In the text, there is an abstract syntax evaluator for which these could\n\nbe-- these are given abstract names like operator, and operand, and all these other things\nare like that. And, in that case, you could reprogram it to be ALGOL with no problem.\n\n\n\n\n\nWell, here we have added another couple of things that we haven't defined. I don't think I'll\nworry about these at all, however, this one will be interesting later. Let's just proceed\n\nthrough this and get it done. There's only two more blackboards so it can't be very long. It's\ncarefully tailored to exactly fit.\n\n\n\n\n\nWell, what do we have left? We have to define EVLIST, which is over here. And EVLIST is\nnothing more than a map down a bunch of operands producing arguments. But I'm going to\n\nwrite it out. And one of the reasons I'm going to writethis out is for a mystical reason,\nwhich is I want to make this evaluator so simple that it can understand itself. I'm going to\n\nreally worry about that a little bit.\n\n\n\n\nSo let's write it out completely. See, I don't want to worry about whether or not the th ing\n\ncan pass functional arguments. The value evaluator is not going to use them. The evaluator\nis not going to produce functional values. So even if there were a different, alternative\n\nlanguage that were very close to this, this evaluates a complex langua ge like Scheme which\ndoes allow procedural arguments, procedural values, and procedural data.\n\n\n\n\n\nBut even if I were evaluating ALGOL, which doesn't allow procedural values, I could use this\nevaluator. And this evaluator is not making any assumptions about that. And, in fact, if this\n\nvalue were to be restricted to not being able to that, it wouldn't matter, because it doesn't\nuse any of those clever things. So that's why I'm arranging this to be super simple. This is\n\nsort of the kernel of all possible language evaluators. How about that?\n\n\n\n\nEvlist-- well, what is it? It's the procedure of two arguments, l and an environment, where l\n\nis a list such that if the list of arguments is the empty list, then the result is the empty list.\nOtherwise, I want to cons up the result of evaluating the CAR of the list of operands in the\n\nenvironment. So I want the first operand evaluated, and I'm going to make a list of the\nresults by CONSing that onto the result of this EVLISTing as a CDR recursion, the CDR of\n\nthe list relative to the same environment. Evlist, cons, else, COND, lambda, define--\n\n\n\n\nAnd I have one more that I want to put on the blackboard. It's the essence of this whole\n\nthing. And there's some sort of next layer down. Conditionals-- conditionals are the only\nthing left that are sort of substantial. Then below that, we have to worry about things like\nlookup and bind, and we'll look at that in a second. But of the substantial stuff at this level\n\nof detail, next important thing is how you deal with conditionals.\n\n\n\n\nWell, how do we have a conditional thing? It's a procedure of a set of clauses and an\n\nenvironment. And what does it do? It says, if I've no more clauses, well, I have to give this\na value. It could be that it was an error. Supposing it run off the end of a conditional, it's\n\npretty arbitrary. It's up to me as programmer to choose what I want to happen. It's\nconvenient for me, right now, to write down that this has a value which is the empty list,\n\ndoesn't matter. For error checking, some people might prefer something else.\n\n\n\n\nBut the interesting things are the following ones. If I've got an else clause -- You see, if I\n\nhave a list of clauses, then each clause is a list. And so the predicate part is the CAAR of the\nclauses. It's the CAR, which is the first part of the first clause in the list of clauses. If it's an\n\nelse, then it means I want my result of the conditional to be the result of evaluating the\nmatching expression. So I eval the CADR. So this is the first clause, the second element of\n\nit, CADAR-- CADAR of a CAR-- of the clauses, with respect to the environment.\n\n\n\n\nNow the next possibility is more interesting. If it's false, if the first predicate in the predicate\n\nlist is not an else, and it's not false, if it's not the word else, and if it's not a false thing--\nLet's write down what it is if it's a false thing. If the result of evaluating the first predicate,\n\nthe clauses-- respect the environment, if that evaluation yields false, then it means, I want\nto look at the next clause. So I want to discard the first one. So we just go around loop,\n\nevcond, the CDR of the clauses relative to that environment. And otherwise, I had a true\n\nclause, in which case, what I want is to evaluate the CADAR of the clauses relative to that\nenvironment.\n\n\n\n\nBoy, it's almost done. It's quite close to done. I think we're going to finish this part off. So\n\njust buzzing through this evaluator, but so far you're seeing almost everything. Let's look at\n\nthe next transparency here.\n\n\n\n\nHere is bind. Bind is for making more table. And what we are going to do here is make a--\nwe're going to make a no-frame for an environment structure. The environment structure is\n\ngoing to be represented as a list of frames. So given an existing environment structure, I'm\ngoing to make a new environment structure by consing a new frame onto the existing\n\nenvironment structure, where the new frame consists of the result of pairing up the\n\nvariables, which are the bound variables of the procedure I'm applying, to the values which\nare the arguments that were passed that procedure.\nThis is just making a list, adding a new element to our list of frames, which is an\n\nenvironment structure, to make a new environment. Where pair-up is very simple. Pair -up\nis nothing more than if I have a list of variables and a list of value s, well, if I run out of\n\nvariables and if I run out of values, everything's OK. Otherwise, I've given too many\narguments.\n\n\n\n\n\nIf I've not run out of variables, but I've run out of values, that I have too few arguments.\nAnd in the general case, where I don't have any errors, and I'm not done, then I really am\n\njust adding a new pair of the first variable with the first argument, the first value, onto a list\nresulting from pairing -up the rest of the variables with the rest of the values.\n\n\n\n\n\nLookup is of course equally simple. If I have to look up a symbol in an environment, well, if\nthe environment is empty, then I've got an unbound variable. Otherwise, what I'm going to\n\ndo is use a special pair list lookup procedure, which we'll have very shortly, of the symbol n    i\nthe first frame of the environment. Since I know the environment is not empty, it must\n\nhave a first frame.\n\n\n\n\nSo I lookup the symbol in the first frame. That becomes the value cell here. And then, if the\n\nvalue cell is empty, if there is no such value cell , then I have to continue and look at the\nrest of the frames. It means there was nothing found there.\n\n\n\n\n\nSo that's a property of ASSQ is it returns emptiness if it doesn't find something. but if it did\nfind something, then I'm going to use the CDR of the value cell here, which is the thing that\n\nwas the pair consisting of the variable and the value. So the CDR of it is the value part.\n\n\n\n\nFinally, ASSQ is something you've probably seen already. ASSQ takes a symbol and a list of\n\npairs, and if the list is empty, it's empty. If the symbol is the first thing in the list-- That's\nan error. That should be CAAR, C-A-A-R. Everybody note that. Right there, OK?\n\n\n\n\n\nAnd in any case, if the symbol is the CAAR of the A list, then I want the first, the first pair,\nin the A list. So, in other words, if this is the key matching the right entry, otherwise, I\n\nwant to look up that symbol in the rest. Sorry for producing a bug, bugs appear.\n\n\n\n\nWell, in any case, you're pretty much seeing the whole thing now. It's a very beautiful\nthing, even though it's written in an ugly style, being the kernel of every language. I\n\nsuggest that we just-- let's look at it for a while.\n[MUSIC PLAYING]\n\n\n\n\nAre there any questions? Alright, I suppose it's time to take a small break then. [MUSIC\n\nPLAYING]\n\n\n\n\nOK, now we're just going to do a little bit of practice understanding what it is we've just\n\nshown you. What we're going to do is go through, in detail, an evaluation by informally\nsubstituting through the interpreter. And since we have no assignments ordefinitions in this\n\ninterpreter, we have no possible side effects, and so the we can do substitution with\nimpunity and not worry about results.\n\n\n\n\n\nSo the particular problem I'd like to look at is it an interesting one. It's the evaluation of\nquote, open, open, open, lambda of x, lambda of y plus x y, lambda, lambda, applied to\n\nthree, applied to four, in some global environment which I'll call e0.\n\n\n\n\nSo what we have here is a procedure of one argument x, which produces as its value a\n\nprocedure of one argument y, which adds x to y. We are applying the procedure of one\nargument x to three. So x should become three. And the result of that should be procedure\n\nof one argument y, which will then apply to 4. And there is a very simple case, they will\nthen add those results.\n\n\n\n\n\nAnd now in order to do that, I want to make a very simple environment model. And at this\npoint, you should already have in your mind the environments that this produces. But we're\n\ngoing to start out with a global environment, which I'll call e0, which is that. And it's going\nto have in it things, definitions for plus, and times, and-- using Greek letters, isn't that\n\ninteresting, for the objects-- and minus, and quotient, and CAR, and CDR, and CONS, and\nEQ, and everything else you might imagine in a global environment. It's got something\n\nthere for each of those things, something the machine is born with, that's e0.\n\n\n\n\nNow what does it mean to do this evaluation? Well, we go through the set of special forms.\n\nFirst of all, this is not a number. This is not a symbol. Gee, it's not a quoted expression. This\nis a quoted expression, but that's not what I interested in. The question is, whether or not\n\nthe thing which is quoted is quoted expression? I'm evaluating an expression. This just says\nit's this particular expression. This is not a quoted expression. It's not a thing that begins\n\nwith lambda. It's not a thing that begins with COND. Therefore, it's an application of its of\nan operated operands. It's a combination.\nThe combination thus has this as the operator and this is the operands. Well, that means\nthat what I'm going to do is transform this into apply of eval, of quote, open, open lambda\n\nof x, lambda of y-- I'm evaluating the operator-- plus x y, in the environment, also e0, with\nthe operands that I'm going to apply this to, the arguments being the result of EVLIST, the\n\nlist containing four, fin e0.\n\n\n\n\nI'm using this funny notation here for e0 because this should be that environment. I haven't\n\na name for it, because I have no environment to name it in.So this is just a representation\nof what would be a quoted expression, if you will. The data structure, which is the\n\nenvironment, goes there.\n\n\n\n\nWell, that's what we're seeing here. Well in order to do this, I have to do this, and I have to\n\ndo that. Well this one's easy, so why don't we do that one first. This turns into apply of\neval-- just copying something now. Most of the substitution rule is copying. So I'm going to\n\nnot say the words when I copy, because it's faster. And then the EVLIST is going to tur n\n\ninto a cons, of eval, of four, in e0-- because it was not an empty list-- onto the result of\nEVLISTing, on the empty list, in e0.\n\n\n\n\nAnd I'm going to start leaving out steps soon, because it's going to get boring. But this is\n\nbasically the same thing as apply, of eval-- I'm going to keep doing this-- the lambda of x,\n\nthe lambda of y, plus xy, 3, close, e0. I'm a pretty good machine.\n\n\n\n\nWell, eval of four, that's meets the question, is it a number. So that's cons, cons of 4. And\nEVLIST of the empty list is the empty list, so that's this. And that's very simple to\n\nunderstand, because that means the list containing four itself. So this is nothing more than\n\napply of eval, quote, open, open, lambda of x, lambda of y, plus x y, three applied to, e0,\napplied to the list four-- bang. So that's that step.\n\n\n\n\nNow let's look at the next, more interesting thing. What do I do to evaluate that? Evaluating\n\nthis means I have to evaluate-- Well, it's not. It's nothing but an application. It's not one of\nthe special things. If the application of this operator, which we see here-- here's the\n\noperator-- applied to this operands, that combination. But we know how to do that, because\n\nthat's the last case of the conditional. So substituting in for this evaluation, it's apply of eval\nof the operator in the EVLIST of the operands.\nWell, it's apply, of apply, of eval, of quote, open, lambda of x, lambda of y, plus x y,\n\nlambda, lambda, in environment e0. I'm going to short circuit the evaluation of the\noperands , because they're the same as they were before. I got a list containing three,\n\napply that, and apply that to four.\n\n\n\n\nWell let's see. Eval of a lambda expression produces a procedure object. So this is apply, of\n\napply, of the procedure object closure, which contains the body of the procedure, x, which is\nlambda-- which binds x [UNINTELLIGIBLE] the internals of the body, it returns the\n\nprocedure of one argument y, which adds x to y. Environment e0 is now captured in it,\nbecause this was evaluated with respect to e0. e0 is part now ofthe closure object. Apply\n\nthat to open, three, close, apply, to open, 4, close, apply.\n\n\n\n\nSo going from this step to this step meant that I made up a procedure object which\n\ncaptured in it e0 as part of the procedure object. Now, we're going to pass those to apply.\nWe have to apply this procedure to that set of arguments. Well, but that procedure is not\n\nprimitive. It's, in fact, a thing which has got the tag closure, and, therefore, what we have\nto do is do a bind.\n\n\n\n\n\nWe have to bind. A new environment is made at this point, which has as its parent\nenvironment the one over here, e0, that environment. And we'll call this one, e1. Now\n\nwhat's bound in there? x is bound to three. So I have x equal three. That's what's in there.\nAnd we'll call that e1. So what this transforms into is an eval of the body of this, which is\n\nthis, the body of that procedure, in the environment that you just saw.\n\n\n\n\nSo that's an apply, of eval, quote, open, lambda of y, plus x y-- the body-- in e1. And apply\n\nthe result of that to four, open, close, 4-- list of arguments. Well, that's sensible enough\nbecause evaluating a lambda, I know what to do.\n\n\n\n\n\nThat means I apply, the procedure which is closure, binds one argument y, adds x to y, with\ne1 captured in it. And you should really see this. I somehow manufactured a closure. I\n\nshould've put this here. There was one over here too. Well, there's one here now. I've\ncaptured e1, and this is the procedure of one argument y, whatever this is. That's what that\n\nis there, that closure.\n\n\n\n\nI'm going to apply that to four. Well, that's easy enough. That means I have to make a new\n\nenvironment by copying this pointer, which was the pointer of the procedure, which binds y\nequal 4 with that environment. And here's my new environment, whic h I'll call e2. And, of\n\ncourse, this application then is evaluate the body in e2.\n\n\n\n\nSo this is eval, the body, which is plus x y, in the environment e2. But this is an application,\n\nso this is the apply, of eval, plus in e2, an EVLIST, quote, open, x y, in e2. Well, but let's\nsee. That is apply, the object which is a result of that and plus. So here we are in e2, plus is\n\nnot here, it's not here, oh, yes, but's here as some primitive operator. So it's the primitive\noperator for addition. Apply that to the result of evaluating x and y in e2. But we can see\n\nthat x is three and y is four. So that's a three and four, here. And that magically produces\nfor me a seven.\n\n\n\n\n\nI wanted to go through this so you would see, essentially, one important ingredient, which\nis what's being passed around, and who owns what, and what his job is. So what do we\n\nhave here? We have eval, and we have apply, the two main players. And there is a big loop\nthe goes around like this. Which is eval produces a procedure and arguments for apply.\n\n\n\n\n\nNow some things eval could do by itself. Those are little self things here. They're not\ninteresting. Also eval evaluates all of the arguments, one after another. That's not very\n\ninteresting. Apply can apply some procedures like plus, not very interestin g. However, if\napply can't apply a procedure like plus, it produces an expression and environment for eval.\n\nThe procedural arguments wrap up essentially the state of a computation and, certainly, the\nexpression of environment.\n\n\n\n\n\nAnd so what we're actually going to do next is not the complete state, because it doesn't\nsay who wants the answers. But what we're going to do-- it's always got something like an\n\nexpression of environment or procedure and arguments as the main loop that we're going\naround.\n\n\n\n\n\nThere are minor little sub loops like eval through EVLIST, or eval through evcond, or apply\nthrough a primitive apply. But they're not the essential things. So that's what I wanted you\n\nto see. Are there any questions? Yes.\n\n\n\n\nAUDIENCE: I'm trying to understand how x got down to three instead of four. At the early\n\npart of the--\n\n\n\n\nPROFESSOR: Here. You want to know how x got down to three?\nAUDIENCE: Because x is the outer procedure, and x and y are the inner procedure.\n\n\n\n\nPROFESSOR: Fine. Well, I was very careful and mechanical. First of all, I should write those\n\nprocedures again for you, pretty printed. First order of business, because you're probably\nnot reading them well.\n\n\n\n\n\nSo I have here that procedure of-- was it x over there-- which is-- value of that procedure\nof y, which adds x to y, lambda, lambda, applied that to three, takes the result of that, and\n\napplied that to four. Is that not what I wrote?\n\n\n\n\nNow, you should immediately see that here is an application-- let me get a white piece of\n\nchalk-- here is an application, a combination. That combination has this as the operator and\nthis as the operand. The three is going in for the x here. The result of this is a procedureof\n\none argument y, which gets applied to four. So you just weren't reading the expression\nright.\n\n\n\n\n\nThe way you see that over here is that here I have the actual procedure object, x. It's\ngetting applied to three, the list containing three. What I'm left over with is something\n\nwhich gets applied to four. Are there any other questions? Time for our next small break\nthen. Thank you. [MUSIC PLAYING]\n\n\n\n\n\nLet's see, at this point, you should be getting the feeling, what's this nonsense this Sussman\ncharacter is feeding me? There's an awful lot of strange nonsense here. After all, he\n\npurported to explain to me Lisp, and he wrote me a Lisp program on the blackboard.\n\n\n\n\nThe Lisp program was intended to be interpreted for Lisp, but you need a Lisp interpreter in\n\norder to understand that program. How could that program have told me anything there is\nto be known about Lisp? How is that not completely vacuous? It's a very strange thing.\n\nDoes it tell me anything at all?\n\n\n\n\nWell, you see, the whole thing is sort of like these Escher's hands that we see on this slide.\nYes, eval and apply each sort of draw each other and construct the real thing, which can sit\n\nout and draw itself. Escher was a very brilliant man, he just didn't know the names of these\n\nspirits.\nWell, I'm going to do now, is I'm going to try to convince you that both this mean\nsomething, and, as a aside, I'm going to show you why you don't need definitions. Just\n\nturns out that that sort of falls out, why definitions are not essential in a mathematical\nsense for doing all the things we need to do for computing.\n\n\n\n\n\nWell, let's see here. Consider the following small program, what does it mean? This is a\nprogram for computing exponentials.\n\n\n\n\n\nThe exponential of x to the nth power is if-- and is zero, then the result is one. Otherwise, I\nwant the product of x and the result of exponentiating x to the n minus one power. I think I\n\ngot it right.\n\n\n\n\nNow this is a recursive definition. It's a definition of the exponentiation procedure in terms\n\nof itself. And, as it has been mentioned before, your high school geometry teacher probably\ngave you a hard time about things like that. Was that justified? Why does this self\n\nreferential definition make any sense?\n\n\n\n\nWell, first of all, I'm going to convince you that your high school geometry teacher was I\n\ntelling you nonsense. Consider the following set of definitions here. x plus y equals three,\nand x minus y equal one. Well, gee, this tells you x in terms of y, and this one tells you y in\n\nterms of x, presumably. And yet this happens to have a unique solution in x and y.\n\n\n\n\nHowever, I could also write two x plus two y is six. These two equations have an infinite\n\nnumber solutions. And I could write you, for example, x minus y equal 2, and these two\nequations have no solutions.\n\n\n\n\n\nWell, I have here three sets of simultaneous linear equations, this set, this set, and this set.\nBut they have different numbers of solutions. The number of solutions is not in the form of\n\nthe equations. They all three sets have the same form. The number of solutionsis in the\ncontent.\n\n\n\n\nI can't tell by looking at the form of a definition whether it makes sense, only by its detailed\n\ncontent. What are the coefficients, for example, in the case of linear equations? So I\n\nshouldn't expect to be able to tell looking at something like this, from some simple things\nlike, oh yes, EXPT is the solution of this recursion equation. Expt is the procedure which if\n\nsubstituted in here, gives me EXPT back.\n\n\n\n\nI can't tell, looking at this form, whether or not there's a single, unique solution for EXPT,\n\nan infinite number of solutions, or no solutions. It's got to be how it counts and things like\nthat, the details. And it's harder in programming than linear algebra. Th ere aren't too many\n\ntheorems about it in programming.\n\n\n\n\nWell, I want to rewrite these equations a little bit, these over here. Because what we're\n\ninvestigating is equations like this. But I want to play a little with equations like this that we\nunderstand, just so we get some insight into this kind of question. We could rewrite our\n\nequations here, say these two, the ones that are interesting, as x equals three minus y, and\ny equals x minus one. What do we call this transformation? This is a linear transform ation,\n\nt.\n\n\n\n\nThen what we're getting here is an equation x y equals t of x y. What am I looking for? I'm\n\nlooking for a fixed point of t. The solution is a fixed point of t.\n\n\n\n\nSo the methods we should have for looking for solutions to equations, if I can doit by fixed\n\npoints, might be applicable. If I have a means of finding a solution to an equations by fixed\npoints-- just, might not work-- but it might be applicable to investigating solutions of\n\nequations like this.\n\n\n\n\nBut what I want you to feel is that this is an equation. It's an expression with several\n\ninstances of various names which puts a constraint on the name, saying what that name\ncould have as its value, rather than some sort of mechanical process of substitution right\n\nnow. This is an equation which I'm going to try to solve.\n\n\n\n\nWell, let's play around and solve it. First of all, I want to write down the function which\n\ncorresponds to t. First I want to write down the function which corresponds to t whose fixed\npoint is the answer to this question. Well, let's consider the following procedure f. I claim it\n\ncomputes that function. f is that procedure of one argument g, which is that procedure of\ntwo arguments x and n. Which have the property that if n is zero, then the result is one,\n\notherwise, the result is the product of x and g, applied to x, and minus n1. g, times, else,\nCOND, lambda, lambda--\nHere f is a procedure, which if I had a solution to that equation, if I had a good\n\nexponentiation procedure, and I applied f to that procedure, then the result would be a good\nexponentiation procedure. Because, what does it do? Well, all it is is exposing g were a good\n\nexponentiation procedure, well then this would produce, as its value, a procedure to\narguments x and n, such that if n were 0, the result woul d be one, which is certainly true of\n\nexponentiation. Otherwise, it will be the result of multiplying x by the exponentiation\nprocedure given to me with x and n minus one as arguments. So if this computed the\n\ncorrect exponentiation for n minus one, then thi s would be the correct exponentiation for\n\nexponent n, so this would have been the right exponentiation procedure.\n\n\n\n\nSo what I really want to say here is E-X-P-T is a fixed point of f. Now our problem is there\nmight be more than one fixed point. There might be no fixed points. I have to go hunting\n\nfor the fixed points. Got to solve this equation.\n\n\n\n\nWell there are various ways to hunt for fixed points. Of course, the one we played with at\n\nthe beginning of this term worked for cosine. Go into radians mode on your calculator and\npush cosine, and just keep doing it, and you get to some number which is about 0.73 or\n\n0.74. I can't remember which. By iterating a function, whose fixed point I'm searching for, it\n\nis sometimes the case that that function will converge in producing the fixed point.\n\n\n\n\nI think we luck out in this case, so let's look for it. Let's look at this slide. Consider the\nfollowing sequence of procedures. e0 over here is the procedure which does nothing at all.\n\nIt's the procedure which produces an error for any arguments you give it. It's basically\n\nuseless. Well, however, I can make an approximation. Let's consider it the worst possible\napproximation to exponentiation, because it does nothing.\n\n\n\n\nWell, supposing I substituted e0 for g by calling f, as you see over here on e0. So you see\n\nover here, have e0 there. Then gee, what's e1? e1 is a procedure which exponentiate things\n\nto the 0th power, with no trouble. It gets the right answer, anything to the zero is one, and\nit makes an error on anything else.\n\n\n\n\nWell, now what if I take e1 and I substitute if for g by calling f on e1? Oh gosh, I have here\n\na procedure of two arguments. Now remember e1 was appropriate for taking\nexponentiations of 0, for raising to the 0 exponent. So here, is n is 0, the resultis one, so\n\nthis guy is good for that too. However, I can use something for raising to the 0th power to\n\nmultiply it by x to raise something to the first power. So e2 is good for both power 0 and\none.\nAnd e3 is constructed from e2 in the same way. And e3, of course, by the same argument is\n\ngood for powers 0, one, and two. And so I will assert for you, without proof, because the\nproof is horribly difficult. And that's the sort of thing that people called denotational\n\nsemanticists do. This great idea was invented by Scott and Strachey. They're very famous\nmathematician types who invented the interpretation for these programs that we have that\n\nI'm talking to you about right now. And they proved, by topology that there is such a fixed\npoint in the cases that we want.\n\n\n\n\n\nBut the assertion is E-X-P-T is limit as n goes to infinity of em. and And that we've\nconstructed this by the following way. --is Well, it's f of, f of, f of, f of, f of-- f applied to\n\nanything at all. It didn't matter what that was, because, in fact, this always produces an\nerror. Applied to this-- That's by infinite nesting of f's.\n\n\n\n\n\nSo now my problem is to make some infinite things. We need some infinite things. How am\nI going to nest up an f an infinite number of times? I'd better construct this. Well, I don't\n\nknow. How would I make an infinite loop at all?\n\n\n\n\nLet's take a very simple infinite loop, the simplest infinite loop imaginable. If I were to take\n\nthat procedure of one argument x which applies x to x and apply that to the procedure of\none argument x which applies x to x, then this is an infinite loop.\n\n\n\n\n\nThe reason why this is an infinite loop is as follows. The way I understand this is I substitute\nthe argument for the formal parameter in the body. But if I do that, I take for each of these\n\nx's, I substitute one of these, making a copy of the original expression I just started with,\nthe simplest infinite loop.\n\n\n\n\n\nNow I want to tell you about a particular operator which is constructed by a perturbation\nfrom this infinite loop. I'll call it y. This is called Curry's Paradoxical Combinator of y after a\n\nfellow by the name of Curry, who was a logician of the 1930s also. And if I have a\nprocedure of one argument f, what's it going to have in it? It's going to have a kind of\n\ninfinite loop in it, which is that procedure of one argument x which applies f to x of x,\napplied to that procedure of one argument x, which applies f to f of x.\n\n\n\n\n\nNow what's this do? Suppose we apply y to F. Well, that's easy enough. That's this capital F\nover here. Well, the easiest thing to say there is, I substitute F for here. So that's going to\n\ngive me, basically -- because then I'm going to substitute this for x in here.\nLet me actually do it in steps, so you can see it completely. I'm going to be very careful.\n\nThis is open, open, lambda of x , capital F, x, x, applied to itself, F of x of x. Substituting\nthis for this in here, this is F applied to-- what is it-- substituting this in here, open, open,\n\nlambda of x, F, of x and x, applied to lambda of x, F of x of x, F, lambda, pair, F.\n\n\n\n\nOh, but what is this? This thing over here that I just computed, is this thing over here. But I\n\njust wrapped another F around it. So by applying y to F, I make an infinite series of F's. If I\njust let this run forever, I'll just keep making more and more F's outside. I ran an infinite\n\nloop which is useless, but it doesn't matter that the inside is useless.\n\n\n\n\nSo y of F is F applied to y of F. So y is a magical thing which, when applied to some\n\nfunction, produces the object which is the fixed point of that function, if it exists, and if this\nall works. Because, indeed, if I take y of F and put it into F, I get y of F out.\n\n\n\n\n\nNow I want you to think this in terms of the eval-apply interpreter for a bit. I wrote down a\nwhole bunch of recursion equations out there. They're simultaneous in the same way these\n\nare simultaneous equations. Exponentiation was not a simultaneous equation. It was only\none variable I was looking for a meaning for.\n\n\n\n\n\nBut what Lisp is is the fixed point of the process which says, if I knew what Lisp was and\nsubstituted it in for eval, and apply, and so on, on the right hand sides of all those recursion\n\nequations, then if it was a real good Lisp, is a real one, then the left hand side would also be\nLisp. So I made sense of that definition. Now whether or not there's an answer isn't so\n\nobvious. I can't attack that.\n\n\n\n\nNow these arguments that I'm giving you now are quite dangerous. Let's look over here.\n\nThese are limit arguments. We're talking about limits, and it's really calculus, or topology,\nor something like that, a kind of analysis. Now here's an argument that you all believe. And\n\nI want to make sure you realize that I could be bullshitting you.\n\n\n\n\nWhat is this? u is the sum of 1/2, 1/4, and 1/8, and so on, the sum of a geometric series.\n\nAnd, of course, I could play a game here. u minus one is 1/2, plus 1/4, plus 1/8, and so on.\nWhat I could do here-- oops. There is a parentheses error here. But I can put here two\n\ntimes u minus one is one plus 1/2, plus 1/4, plus 1/8. Can I fix that? Yes, well. But that\ngives me back two times u minus one is u, therefore, we conclude that u is two. And this\n\nactually is true. There's no problem like that. But supposing I did something different.\nSupposing I start up with something which manifestly has no sum. v is one, plus two, plus\n\nfour, plus 8, plus dot, dot, dot. Well, v minus one is surely two, plus four, plus eight, plus\ndot, dot, dot. v minus one over two, gee, that looks like v again. From that I should be able\n\nto conclude that-- that's also wrong, apparently. v equals minus one. That should be a\nminus one. And that's certainly a false conclusion.\n\n\n\n\n\nSo when you play with limits, arguments that may work in one case they may not work in\nsome other case. You have to be very careful. The arguments have to be well formed. And I\n\ndon't know, in general, what the story is about arguments like this. We can read a pile of\ntopology and find out.\n\n\n\n\n\nBut, surely, at least you understand now, why it might be some meaning to the things\nwe've been writing on the blackboard. And you understand what that might mean. So, I\n\nsuppose, it's almost about time for you to merit being made a member of the grand\nrecursive order of lambda calculus hackers. This is the badge. Because you now understand,\n\nfor example, what it says at the very top, y F equals F y F. Thank you. Are there any\nquestions? Yes, Lev.\n\n\n\n\n\nAUDIENCE: With this, it seems that then there's no need to define, as you imply, to just\nremember a value, to apply it later. Defines were kind of a side-effect it seemed in the\n\nlanguage. [INTERPOSING] are order dependent. Does this eliminate the side-effect from the\n[INTERPOSING]\n\n\n\n\n\nPROFESSOR: The answer is, this is not the way these things were implemented. Define,\nindeed is implemented as an operation that actually modifies an environment structure,\n\nchanges the frame that the define is executed in. And there are many reasons for that, but\na lot of this has to do with making an interactive system. What this is saying is that if\n\nyou've made a system, and you know you're not going to do any debugging or anything like\n\nthat, and you know everything there is all at once, and you want to say, what is the\nmeaning of a final set of equations? This gives you a meaning for it. But in order to make an\n\ninteractive system, where you can change the meaning of one thing without changing\neverything else, incrementally, you can't do that by implementing it this way. Yes.\n\n\n\n\nAUDIENCE: Another question on your danger slide. It seemed that the two examples that\n\nyou gave had to do with convergence and non-convergence? And that may or may not have\n\nsomething to do with function theory in a way which would lead you to think of it in terms of\nlinear systems, or non-linear systems. How does this convergence relate to being able to\n\nsee a priori what properties of that might be violated?\nPROFESSOR: I don't know. The answer is, I don't know under what circumstances. I don't\nknow how to translate that into less than an hour of talk more. What are the conditions\n\nunder which, for which we know that these things converge? And v, all that was telling you\nthat arguments that are based on convergence are flaky if you don't know the convergence\n\nbeforehand. You can make wrong arguments. You can make deductions, as if you know the\n\nanswer, and not be stopped somewhere by some obvious contradiction.\n\n\n\n\nAUDIENCE: So can we say then that if F is a convergent mathematical expression, then the\nrecursion property can be--\n\n\n\n\n\nPROFESSOR: Well, I think there's a technical kind of F, there is a technical description of\nthose F's that have the property that when you iteratively apply them like this, you\n\nconverge. Things that are monotonic, and continuous, and I forgot what el se. There is a\nwhole bunch of little conditions like that which have this property. Now the real problem is\n\ndeducing from looking at the F, its definition here, whether not it has those properties, and\n\nthat's very hard. The properties are easy. You can write them down.\n\n\n\n\nYou can look in a book by Joe Stoy. It's a great book-- Stoy. It's called, The Scott-Strachey\nMethod of Denotational Semantics, and it's by Joe Stoy, MIT Press. And he works out all this\n\nin great detail, enough to horrify you. But it reallyis readable.\n\n\n\n\nOK, well, thank you. Time for the bigger break, I suppose.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation f ormat:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec7b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 7B: Metacircular Evaluator, Part 2\n\n\n\n[MUSIC PLAYING] PROFESSOR: Well, let's see. What we did so far was a lot of fun, was it\nuseful for anything? I suppose the answer is going to be yes. If these metacircular\n\ninterpreters are a valuable thing to play with. Well, there have been times I spend 50% of\nmy time, over a year, trying various design alternatives by experimenting with them with\n\nmetacircular interpreters-- metacircular interpreters like the sort you just saw. Metacircular\nis because they are defined in terms of themselves in such a way that the language they\n\ninterpret contains itself.\n\n\n\n\nSuch interpreters are a convenient medium for exploring language issues. If you want to try\n\nadding a new feature, it's sort of a snap, it's easy, you just do it and see what happens. You\nplay with that language for a while you say, gee, I'm didn't like that, you throw it away. Or\n\nyou might want to see what the difference is if you'd make a slight difference in the binding\nstrategy, or some more complicated things that might occur.\n\n\n\n\n\nIn fact, these metacircular interpreters are an excellent medium for people exchanging\nideas about language design, because they're pretty easy to understand, and they're short,\n\nand compact, and simple. If I have some idea that I want somebody to criticize like say,\nDan Friedman at Indiana, I'd write a little metacircular interpreter and send him some\n\nnetwork mail with this interpreter in it. He could whip it up on his machine and play with it\nand say, that's no good. And then send it back to me and say, well, why don't you try this\n\none, it's a little better.\n\n\n\n\nSo I want to show you some of that technology. See, because, really, it's the essential,\n\nsimple technology for getting started in designing your own languages for particular\npurposes. Let's start by adding a very simple feature to a Lisp. Now, one thing I want to tell\n\nyou about is features, before I start.\n\n\n\n\nThere are many languages that have made a mess of themselves by adding huge numbers\n\nof features. Computer scientists have a joke about bugs that transform it to features all the\ntime. But I like to think of it is that many systems suffer from what's called creeping\n\nfeaturism.\nWhich is that George has a pet feature he'd like in the system, so he adds it. And then\n\nHarry says, gee, this system is no longer what exactly I like, so I'm going to add my\nfavorite feature. And then Jim adds his favorite feature. And, after a while, the thing has a\n\nmanual 500 pages long that no one can understand.\n\n\n\n\nAnd sometimes it's the same person who writes all of these features and produces this\n\nterribly complicated thing. In some cases, like editors, it's sort of reasonable to have lots of\nfeatures, because there are a lot of things you want to be able to do and many of them\n\narbitrary. But in computer languages, I think it's a disaster to have too much stuff in them.\n\n\n\n\nThe other alternative you get into is something called feeping creaturism, which is where\n\nyou have a box which has a display, a fancy display, and a mouse, and there is all sorts of\ncomplexity associated with all this fancy IO. And your computer language becomes a\n\ndismal, little, tiny thing that barely works because of all the swapping, and disk twitching,\nand so on, caused by your Windows system.\n\n\n\n\n\nAnd every time you go near the computer, the mouse process wakes up and says, gee do\nyou have something for me to do, and then it goes back to sleep. And if you accidentally\n\npush mouse with you elbow, a big puff of smoke comes out of your computer and things like\nthat. So two ways to disastrously destroy a system by adding features.\n\n\n\n\n\nBut try right now to add a little, simple feature. This actually is a good one, and in fact, real\nLisps have it. As you've seen, there are procedures like plus and times that take any\n\nnumber of arguments. So we can write things like the sum of the product of a and x and x,\nand the product of b and x and c.\n\n\n\n\n\nAs you can see here, addition takes three arguments or two arguments, multiplication takes\ntwo arguments or three arguments, taking numbers of arguments all of which are to be\n\ntreated in the same way. This is a valuable thing, indefinite numbers of arguments.\n\n\n\n\nYet the particular Lisp system that I showed you is one where the numbers of arguments is\n\nfixed, because I had to match the arguments against the formal parameters in the binder,\nwhere there's a pairup. Well, I'd like to be able to define new procedures like this that can\n\nhave any number of arguments. Well there's several parts to this problem. The first part is\ncoming up with the syntactic specification, some way of notating the additional arguments,\n\nof which you don't know how many there are. And then there's the other thing, which is\nonce we've notated it, how are we going to interpret that notation so as to do the right\n\nthing, whatever the right thing is?\n\n\n\n\nSo let's consider an example of a sort of thing we might want to be able to do. So an\n\nexample might be, that I might want to be able to define a procedure which is a procedure\nof one required argument x and a bunch of arguments, I don't know how many there are,\n\ncalled y. So x is required, and there are many y's, many argument-- y will be the list of\nthem.\n\n\n\n\n\nNow, with such a thing, we might be able to say something like, map-- I'm going to do\nsomething to every one-- of that procedure of one argument u, which multiplies x by u, and\n\nwe'll apply that to y. I've used a dot here to indicate that the thing after this is a list of all\nthe rest of the arguments. I'm making a syntactic specification.\n\n\n\n\n\nNow, what this depends upon, the reason why this is sort of a reasonable thing to do, is\nbecause this happens to be a syntax that's used in the Lisp reader for representing conses.\n\nWe've never introduced that before. You may have seen when playing with the system that\nif you cons two things together, you get the first, space, dot, the second, space -- the first,\n\nspace, dot, space, the second with parentheses around the whole thing.\n\n\n\n\nSo that, for example, this x dot y corresponds to a pair, which has got an x in it and a y in\n\nit. The other notations that you've seen so far are things like a procedure of arguments x\nand y and z which do things, and that looks like-- Just looking at the bound variable list, it\n\nlooks like this, x, y, z, and the empty thing.\n\n\n\n\nIf I have a list of arguments I wish to match this against, supposing, I have a list of\n\narguments one, two, three, I want to match these against. So I might have here a list of\nthree things, one, two, three. And I want to match x, y, z against one, two, three.\n\n\n\n\n\nWell, it's clear that the one matches the x, because I can just sort of follow the structure,\nand the two matches the y, and the three matches the z. But now, supposing I were to\n\ncompare this x dot y-- this is x dot y-- supposing I compare that with a list of three\narguments, one, two, three. Let's look at that again. One, two, three--\nWell, I can walk along here and say, oh yes, x matches the one, the y matches the list,\n\nwhich is two and three. So the notation I'm choosing here is one that's very natural for Lisp\nsystem. But I'm going to choose this as a notation for representing a bunch of arguments.\n\n\n\n\n\nNow, there's an alternative possibility. If I don't want to take one special out, or two special\nones out or something like that, if I don't want to do that, if I want to talk about just the list\n\nof all the arguments like in addition, well then the argument list I'm g oing to choose to be\nthat procedure of all the arguments x which does something with x. And which, for\n\nexample, if I take the procedure, which takes all the arguments x and returned the list of\nthem, that's list. That's the procedure list.\n\n\n\n\n\nHow does this work? Well, indeed what I had as the bound variable list in this case,\nwhatever it is, is being matched against a list of arguments. This symbol now is all of the\n\narguments. And so this is the choice I'm making for a particular syntactic specification, for\nthe description of procedures which take indefinite numbers of arguments.\n\n\n\n\n\nThere are two cases of it, this one and this one. When you make syntactic specifications, it's\nimportant that it's unambiguous, that neither of these can be confused with a\n\nrepresentation we already have, this one. I can always tell whether I have a fixed number\nof explicitly named arguments made by these formal parameters, or a fixed number of\n\nnamed formal parameters followed by a thing which picks up all the rest of them, or a li st of\nall the arguments which will be matched against this particular formal parameter called x,\n\nbecause these are syntactically distinguishable.\n\n\n\n\nMany languages make terrible errors in that form where whole segments of interpretation\n\nare cut off, because there are syntactic ambiguities in the language. They are the traditional\nproblems with ALGOL like languages having to do with the nesting of ifs in the predicate\n\npart.\n\n\n\n\nIn any case, now, so I've told you about the syntax, now, what are we going to do ab out\n\nthe semantics of this? How do we interpret it? Well this is just super easy. I'm going to\nmodify the metacircular interpreter to do it. And that's a one liner. There it is. I'm changing\n\nthe way you pair things up. Here's the procedure that pairs the variables, the formal\nparameters, with the arguments that were passed from the last description of the\n\nmetacircular interpreter.\nAnd here's some things that are the same as they were before. In other words, if the list of\n\nvariables is empty, then if the list of values is empty, then I have an empty list. Otherwise,\nI have too many arguments, that is, if I have empty variables but not empty values. If I\n\nhave empty values, but the variables are not empty, I have too few arguments.\n\n\n\n\nThe variables are a symbol-- interesting case-- then, what I should do is say, oh yes, this is\n\nthe special case that I have a symbolic tail. I have here a thing just like we looked over\nhere. This is a tail which is a symbol, y. It's not a nil. It's not the empty list. Here's a\n\nsymbolic tail that is just the very beginning of the tail. There is nothing else.\n\n\n\n\nIn that case, I wish to match that variable with all the values and add that to the pairing\n\nthat I'm making. Otherwise, I go through the normal arrangement of making up the whole\npairing. I suppose that's very simple. And that's all there is to it. And now I'll answer some\n\nquestions. The first one-- Are there any questions? Yes?\n\n\n\n\nAUDIENCE: Could you explain that third form?\n\n\n\n\nPROFESSOR: This one? Well, maybe we should look at the thing as a piece of list structure.\n\nThis is a procedure which contains a lambda. I'm just looking at the list structure which\n\nrepresents this. Here's x. These are our symbols. And then the body is nothing but x. If I\nwere looking for the bound variable list part of this procedure, I would go looking at the\n\nCADR, and I'd find a symbol. So the, naturally, which is this pairup thing I just showed you,\nis going to be matching a symbolic object against a list of arguments that were passed. And\n\nit will bind that symbol to the list of arguments.\n\n\n\n\nIn this case, if I'm looking for it, the match will be against this in the bound variable list\n\nposition. Now, if what this does is it gets a list of arguments and returns it, that's list. Tha t's\nwhat the procedure is. Oh well, thank you. Let's take a break.\n\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\nPROFESSOR: Well let's see. Now, I'm going to tell you about a rather more substantial\nvariation, one that's a famous variation that many early Lisps had. It's called dyn amic\n\nbinding of variables. And we'll investigate a little bit about that right now. I'm going to first\nintroduce this by showing you the sort of thing that would make someone want this idea.\nI'm not going to tell what it is yet, I'm going to show you why you might want it. Suppose,\nfor example, we looked at the sum procedure again for summing up a bunch of things. To\n\nbe that procedure, of a term, lower bound, method of computing the next index, and upper\nbound, such that, if a is greater than b then the r esult is 0, otherwise, it's the sum, of the\n\nterm, procedure, applied to a and the result of adding up, terms, with the next a being the\n\na, the next procedure passed along, and the upper bound being passed along. Blink, blink,\nblink--\n\n\n\n\nNow, when I use this sum procedure, I can use it, for example, like this. We can define the\n\nsum of the powers to be, for example, sum of a bunch of powers x to the n, to be that\n\nprocedure of a, b, and n-- lower bound, the upper bound, and n-- which is sum, of lambda\nof x, the procedure of one argument x, which exponentiates x to the n, with the a, the\n\nincrementer, and b, being passed along.\n\n\n\n\nSo we're adding up x to n, given an x. x takes on values from a to b, incrementing by one. I\n\ncan also write the-- That's right. Product, excuse me. The product of a bunch of powers. It's\na strange name. I'm going to leave it there. Weird-- I write up what I have. I'm sure that's\n\nright. And if I want the product of a bunch of powers-- That was 12 brain cells, that double-\ntake.\n\n\n\n\n\nI can for example use the procedure which is like sum, which is for making products, but it's\nsimilar to that, that you've seen before. There's a procedure of three arguments again.\n\nWhich is the product of terms that are constructed, or factors in this case, constructed from\nexponentiating x to the n, where I start with a, I increment, and I go to b.\n\n\n\n\n\nNow, there's some sort of thing here that should disturb you immediately. These look the\nsame. Why am I writing this code so many times? Here I am, in the same boat I've been in\n\nbefore. Wouldn't it be nice to make an abstraction here? What's an example of a good\nabstraction to make? Well, I see some codes that's identical. Here's one, and here's\n\nanother.\n\n\n\n\nAnd so maybe I should be able to pull that out. I should be able to say, oh yes, the sum of\n\nthe powers could be written in terms of something called the nth power procedure. Imagine\nsomebody wanted to write a slightly different procedure that looks like this. The sum\n\npowers to be a procedure of a, b, and n, as the result of summing up the nth power. We're\ngoing to give a name to that idea, for starting at a, going by one, and ending at b.\nAnd similarly, I might want to write the product powers this way, abstracting out this idea. I\nmight want this. Product powers, to be a procedure of a, b, and n, which is the product of\n\nthe nth power operation on a with the incrementation and b being my arguments for the\nanalogous-thing product.\n\n\n\n\n\nAnd I'd like to be able to define, I'd like to be able to define nth power--I'll put it over here.\nI'll put it at the top. --to be, in fact, my procedure of one argument x which is the result of\n\nexponentiating x to the n. But I have a problem. My environment model, that is my means\nof interpretation for the language that we've defined so far, does not give me a meaning for\n\nthis n. Because, as you know, this n is free in this procedure.\n\n\n\n\nThe environment model tells us that the meaning of a free variable is determined in the\n\nenvironment in which this procedure is defined. In a way I have written it, assuming these\nthings are defined on the blackboard as is, this is defined in the global environment, where\n\nthere is no end. Therefore, n is unbound variable.\n\n\n\n\nBut it's perfectly clear, to most of us, that we would like it to be this n and this n. On the\n\nother hand, it would be nice. Certainly we've got to be careful here of keeping this to be\nthis, and this one over here, wherever it is to be this one.\n\n\n\n\n\nWell, the desire to make this work has led to a very famous bug. I'll tell you about the\nfamous bug. Look at this slide. This is an idea called dynamic binding. Where, instead of the\n\nfree variable being interpreted in the environment of definition of a procedure, the free\nvariable is interpreted as having its value in the environment of the caller of the procedure.\n\n\n\n\n\nSo what you have is a system where you search up the chain of callers of a particular\nprocedure, and, of course, in this case, since nth power is called from inside product\n\nwhatever it is-- I had to write our own sum which is the analogous procedure -- and product\nis presumably called from product powers, as you see over here, then since product powers\n\nbind with variable n , then nth powers n would be derived through that chain.\n\n\n\n\nSimilarly, this n, the nth power in n in this case, would come through nth power here being\n\ncalled from inside sum. You can see it being called from inside sum here. It's called term\nhere. But sum was called from inside of sum powers, which bound n. Therefore, there would\n\nbe an n available for that n to get it's value from.\nWhat we have below this white line plus over here, is what's called a dynamic binding view\nof the world. If that works, that's a dynamic binding view. Now, let's take a look, for\n\nexample, at just what it takes to implement that. That's real easy.\n\n\n\n\nIn fact, the very first Lisps that had any interpretations of the free variables at all, had\n\ndynamic binding interpretations for the free variables. APL has dynamic binding\ninterpretation for the free variables, not lexical or static binding. So, of course, the change\n\nis in eval. And it's really in two places.\n\n\n\n\nFirst of all, one thing we see, is that things become a little simpler. If I don't have to have\n\nthe environment be the environment of definition for procedure, the procedure need not\ncapture the environment at the time it's defined. And so if we look here at this slide, we see\n\nthat the clause for a lambda expression, which is the way a procedure is defined, do es not\nmake up a thing which has a type closure and a attached environment structure. It's just\n\nthe expression itself. And we'll decompose that some other way somewhere else.\n\n\n\n\nThe other thing we see is the applicator must be able to get the environment of the caller.\n\nThe caller of a procedure is right here. If the expression we're evaluating is anpplication or a\ncombination, then we're going to call a procedure which is the value of the operator. The\n\nenvironment of the caller is the environment we have right here, available now.\n\n\n\n\nSo all I have to do is pass that environment to the applicator, to apply. And if we look at\n\nthat here, the only change we have to make is that fellow takes that environment and uses\nthat environment for the purpose of extending that environment when abiding the formal\n\nparameters of the procedure to the arguments that were passed, not an environment that\n\nwas captured in the procedure.\n\n\n\n\nThe reason why the first Lisps were implemented this way, is the sort of the obvious,\naccidental implementation. And, of course, as usual, people got used to it and liked it. And\n\nthere were some people said, this is the way to do it. Unfortunately that causes some\nserious problems. The most important, serious problem in using dynamic binding is there' s\n\na modularity crisis that's involved it.\n\n\n\n\nIf two people are working together on some big system, then an important thing to want is\n\nthat the names used by each one don't interfere with the names of the other. It's important\nthat when I invent some segment of code that no one can make my code stop working by\n\nusing my names that I use internal to my code, internal to his code.\n\n\n\n\nHowever, dynamic binding violates that particular modularity constraint in a clear way.\n\nConsider, for example, what happens over here. Suppose it was the case that I decided to\nchange the word next. Supposing somebody is writing sum, and somebody else is going to\n\nuse sum.\n\n\n\n\nThe writer of sum has a choice of what names he may use. Let'ssay, I'm that writer. Well,\n\nby gosh, just happens I didn't want to call this next. I called it n. So all places where you\nsee next, I called it n. Whoops. I changed nothing about the specifications of this program,\n\nbut this program stops working. Not only that, unfortunately, this one does too.\n\n\n\n\nWhy do these programs stop working? Well, it's sort of clear. Instead of chasing out the\n\nvalue of the n that occurs in nth power over here or over here, through the environment of\ndefinition, where this one is always linked to this one, if it was through the environment of\n\ndefinition, because here is the definition. This lambda expression was executed in the\nenvironment where that n was defined. If instead of doing that, I have to chase through the\n\ncall chain, then look what horrible thing happens.\n\n\n\n\nWell, this was called from inside sum as term, term a. I'm looking for a value of n. Instead\n\nof getting this one, I get that one. So by changing the insides of this program, this program\nstops working. So I no longer have a quantifier, as I described before. The lambda symbol is\n\nsupposed to be a quantifier. A thing which has the property that the names that are bound\nby it are unimportant, that I can uniformly substitute any names for these throughout this\n\nthing, so long as they don't occur in here, the new names, and the meaning of this\nexpression should remain unchanged.\n\n\n\n\n\nI've just changed the meaning of the expression by changing the one of the names. So\nlambda is no longer a well defined idea. It's a very serious problem. So for that reason, I\n\nand my buddies have given up this particular kind of abstraction, which I would like to have,\nin favor of a modularity principle.\n\n\n\n\n\nBut this is the kind of experiment you can do if you want to play with these interpreters.\nYou can try them out this way, that way, and the other way. You see what makes a nicer\n\nlanguage. So that's a very important thing to be able to do. Now, I would like to give you a\nfeeling for I think the right thing to do is here.\nHow are you going to I get this kind of power in a lexical system? And the answer is, of\ncourse, what I really want is a something that makes up for me an exponentiator for a\n\nparticular n. Given an n, it will make me an exponentiator. Oh, but that's easy too. In other\nwords, I can write my program this way. I'm going to define a thing called PGEN, which is a\n\nprocedure of n which produces for me an exponentiator.--x to the n.\n\n\n\n\nGiven that I have that, then I can capture the abstraction I wanted even better, because\n\nnow it's encapsulated in a way where I can't be destroyed by a change of names. I can\ndefine some powers to be a procedure again of a, b, and n which is the sum of the term\n\nfunction generated by using this generator, PGEN, n, with a, incrementer, and b. And I can\n\ndefine the product of powers to be a procedure of a, b, and n which is the product PGEN, n,\nwith a, increment, and b.\n\n\n\n\nNow, of course, this is a very simple example where this object that I'm trying to abstract\n\nover is small. But it could be a 100 lines of code. And so, the purpose of this is, of course, to\n\nmake it simple. I'd give a name to it, it's just that here it's a parameterized name. It's a\nname that depends upon, explicitly, the lexically apparent value of n. So you can think of\n\nthis as a long name. And here, I've solved my problem by naming the term generation\nprocedures within an n in them.\n\n\n\n\n\nAre there any questions? Oh, yes, David.\n\n\n\n\nAUDIENCE: Is the only solution to the problem you raise to create another procedure? In\nother words, can this only work in languages that are capable of defining objects as\n\nprocedures?\n\n\n\n\nPROFESSOR: Oh, I see. My solution to making this abstraction, when I didn't want include\n\nthe procedure inside the body, depends upon my ability to return a procedure or export\none. And that's right. If I don't have that, then I just don't have this ability to make an\n\nabstraction in a way where I don't have possibilities of symbol conflicts that were\nunanticipated. That's right. I consider being able to return the procedural value and,\n\ntherefore, to sort of have first class procedures, in general, as being essential to doing very\n\ngood modular programming.\n\n\n\n\nNow, indeed there are many other ways to skin this cat. What you can do is take for each of\nthe bad things that you have to worry about, you can make a special feature that covers\nthat thing. You can make a package system. You can make a module system as in Ada, et\n\ncetera. And all of those work, or they cover little regions of it. The thing is that returning\nprocedures as values cover all of those problems. And so it's the simplest mechanism that\n\ngives you the best modularity, gives you all of the known modularity mechanisms.\n\n\n\n\nWell, I suppose it's time for the next break, thank you.\n\n\n\n\n[MUSIC PLAYING]\n\n\n\n\n\nPROFESSOR: Well, yesterday when you learned about streams, Hal worried to you about\nthe order of evaluation and delayed arguments to procedures. The way we played with\n\nstreams yesterday, it was the responsibility of the caller and the callee to both agree that an\nargument was delayed, and the callee must force the argument if it needs the answer. So\n\nthere had to be a lot of hand shaking between the designer of a procedure and user of it\n\nover delayedness.\n\n\n\n\nThat turns out, of course, to be a fairly bad thing, it works all right with streams. But as a\ngeneral thing, what you want is an idea to have a locus, a decision, a design decision in\n\ngeneral, to have a place where it's made, explicitly, and notated in a clear way. And so it's\n\nnot a very good idea to have to have an agreement, between the person who writes a\nprocedure and the person who calls it, about such details as, maybe, the arguments of\n\nevaluation, the order of evaluation.\n\n\n\n\nAlthough, that's not so bad. I mean, we have other such agreements like, the input's a\n\nnumber. But it would be nice if only one of these guys could take responsibility, completely.\nNow this is not a new idea.\n\n\n\n\nALGOL 60 had two different ways of calling a procedure. The arguments could be passed by\n\nname or by value. And what that meant was that a name argument was delayed. That when\n\nyou passed an argument by name, that its value would only be obtained if you accessed\nthat argument.\n\n\n\n\nSo what I'd like to do now is show you, first of all, a little bit about, again, we're going to\n\nmake a modification to a language. In this case, we're going to add a feature. We're going\nto add the feature of, by name parameters, if you will, or delayed parameters. Because, in\n\nfact, the default in our Lisp system is by the value of a pointer. A pointer is copied, but the\ndata structure it points at is not. But I'd like to, in fact, show you is how you add name\n\narguments as well.\n\n\n\n\nNow again, why would we need such a thing? Well supposing we wanted to invent certain\n\nkinds of what otherwise would be special forms, reserve words? But I'd rather not take up\nreserve words. I want procedures that can do things like if.\n\n\n\n\nIf is special, or cond, or whatever it is. It's the same thing. It's special in that it determines\n\nwhether or not to evaluate the consequent or the alternative based on the value of the\n\npredicate part of an expression. So taking the value of one thing determines whether or not\nto do something else.\n\n\n\n\nWhereas all the procedures like plus, the ones that we can define right now, evaluate all of\n\ntheir arguments before application. So, for example, supposing I wish to be able to define\n\nsomething like the reverse of if in terms of if. Call it unless. We've a predicate, a\nconsequent, and an alternative.\n\n\n\n\nNow what I would like to sort of be able to do is say-- oh, I'll do it in terms of cond. Cond, if\n\nnot the predicate, then take the consequent, otherwise, take the alternative. Now, what I'd\n\nlike this to mean, is supposing I do something like this. I'd like this unless say if equals one,\n0, then the answer is two, otherwise, the quotient of one and 0.\n\n\n\n\nWhat I'd like that to mean is the result of substituting equal one, 0, and two, and the\n\nquotient of one, 0 for p, c, and a. I'd like that to mean, and this is funny, I'd like it to\n\ntransform into or mean cond not equal one, 0, then the result is two, otherwise I want it to\nbe the quotient one and 0.\n\n\n\n\nNow, you know that if I were to type this into Lisp, I'd get a two. There's no problem with\n\nthat. However, if I were to type this into Lisp, because all the arguments are evaluated\n\nbefore I start, then I'm going to get an error out of this. So that if the substitutions work at\nall, of course, I would get the right answer. But here's a case where the substitutions don't\n\nwork. I don't get the wrong answer. I get no answer. I get an error.\n\n\n\n\nNow, however, I'd like to be able to make my definition so that this kind of thing works.\nWhat I want to do is say something special about c and a. I want them to be delayed\n\nautomatically. I don't want them to be evaluated at the time I call.\nSo I'm going to make a declaration, and then I'm going to see how to implement such a\ndeclaration. But again, I want you to say to yourself, oh, this is an interesting kluge he's\n\nadding in here. The piles of kluges make a big complicated mess. And is this going to foul\nup something else that might occur. First of all, is it syntactically unambiguous? Well, it will\n\nbe syntactically unambiguous with what we've seen so far.\n\n\n\n\nBut what I'm going to do may, in fact, cause trouble. It may be that the thing I had will\n\nconflict with type declarations I might want to add in the future for giving some system,\nsome compiler or something, the ability to optimize given the types are known. Or it might\n\nconflict with other types of declarations I might want to make about the formal parameters.\n\nSo I'm not making a general mechanism here where I can add declarations. And I would\nlike to be able to do that. But I don't want to talk about that right now.\n\n\n\n\nSo here I'm going to do, I'm going to build a kluge. So we're going to define unless of a\n\npredicate-- and I'm going to call these by name-- the consequent, and name the\n\nalternative. Huh, huh-- I got caught in the corner. If not p then the result is c, else-- that's\nwhat I'd like. Where I can explicitly declare certain of the parameters to be delayed, to be\n\ncomputed later.\n\n\n\n\nNow, this is actually a very complicated modification to an interpreter rather than a simple\n\none. The ones you saw before, dynamic binding or addi ng indefinite argument procedures,\nis relatively simple. But this one changes a basic strategy. The problem here is that our\n\ninterpreter, as written, evaluates a combination by evaluating the procedure, the operator\nproducing the procedure, and evaluating the operands producing the arguments, and then\n\ndoing apply of the procedure to the arguments.\n\n\n\n\nHowever, here, I don't want to evaluate the operands to produce the arguments until after I\n\nexamined the procedure to see what the procedure's declarations looklike. So let's look at\nthat. Here we have a changed evaluator. I'm starting with the simple lexical evaluator, not\n\ndynamic, but we're going to have to do something sort of similar in some ways. Because of\nthe fact that, if I delay a procedure-- I'm sorry-- delay an argument to a procedure, I'm\n\ngoing to have to attach and environment to it.\n\n\n\n\nRemember how Hal implemented delay. Hal implemented delay as being a procedure of no\n\narguments which does some expression. That's what delay of the expression is. --of that\nexpression. This turned into something like this.\nNow, however, if I evaluate a lambda expression, I have to capture the environment. The\nreason why is because there are variables in there who's meaning I wish to derive from the\n\ncontext where this was written.\n\n\n\n\nSo that's why a lambda does the job. It's the right thing. And such that the forcing of a\n\ndelayed expression was same thing as calling that with no arguments. It's just the opposite\nof this. Producing an environment of the call which is, in fact, the environment where this\n\nwas defined with an extra frame in it that's empty. I don't care about that.\n\n\n\n\nWell, if we go back to this slide, since it's the case, if we look at this for a second,\n\neverything is the same as it was before except the caseof applications or combinations. And\ncombinations are going to do two things. One, is I have to evaluate the procedure -- forget\n\nthe procedure-- by evaluating the operator. That's what you see right here. I have to make\nsure that that's current, that is not a delayed object, and evaluate that to the point where\n\nit's forced now. And then I have to somehow apply that to the operands. But I have to keep\n\nthe environment, pass that environmental along. So some of those operands I may have to\ndelay. I may have to attach that environment to those operands.\n\n\n\n\nThis is a rather complicated thing happening here. Looking at that in apply. Apply, well it\n\nhas a primitive procedure thing just like before. But the compound one is a little more\n\ninteresting. I have to evaluate the body, just as before, in an environment which is the\nresult of binding some formal parameters to arguments in the environment. That's true.\n\n\n\n\nThe environment is the one that comes from the procedure now. It's a lexical language,\n\nstatically bound. However, one thing I have to do is strip off the declarations to get the\n\nnames of the variables. That's what this guy does, vnames. And the other thing I have to do\nis process these declarations, deciding which of these operands-- that's the operands now,\n\nas opposed to the arguments-- which of these operands to evaluate, and which of them are\nto be encapsulated in delays of some sort.\n\n\n\n\nThe other thing you see here is that we got a primitive, a primitive like plus, had better get\n\nat the real operands. So here is a place where we're going to have to force them. And we're\n\ngoing to look at what evlist is going to have to do a bunch of forces.\n\n\n\n\nSo we have two different kinds of evlist now. We have evlist and gevlist. Gevlist is going to\nwrap delays around some things and force others, evaluate others. And this guy's going to\ndo some forcing of things. Just looking at this a little bit, this is a game you must play for\n\nyourself, you know. It's not something that you're going to see all possible variations on an\nevaluator talking to me. What you have to do is do this for yourself. And after you feel this,\n\nyou play this a bit, you get to see all the possible design decisions and what they might\nmean, and how they interact with each other. So what languages might have in them. And\n\nwhat are some of the consistent sets that make a legitimate language. Whereas what things\nare complicated kluges that are just piles of junk.\n\n\n\n\n\nSo evlist of course, over here, just as I said, is a list of operands which are going to be\nundelayed after evaluation. So these are going to be forced, whatever that's going to mean.\n\nAnd gevlist, which is the next thing-- Thank you.\n\n\n\n\nWhat we see here, well there's a couple of possibilities. Either it's a normal, ordinary thing,\n\na symbol sitting there like the predicate in the unless, and that's what we have here. In\nwhich case, this is intended to be evaluated in applicative order. And it's, essentially, just\n\nwhat we had before. It's mapping eval down the list. In other words, I evaluate the first\nexpression and continue gevlisting the CDR of the expression in the environment.\n\n\n\n\n\nHowever, it's possible that this is a name parameter. If it's a name parameter, I want to put\na delay in which combines that expression, which I'm calling by name, with the envi ronment\n\nthat's available at this time and passing that as the parameter. And this is part of the\nmapping process that you see here.\n\n\n\n\n\nThe only other interesting place in this interpreter is cond. People tend to write this thing,\nand then they leave this one out. There's a place where you have to force. Conditionals\n\nhave to know whether or not the answer is true or false. It's like a primitive. When you do a\nconditional, you have to force.\n\n\n\n\n\nNow, I'm not going to look at any more of this in any detail. It isn't very exciting. And\nwhat's left is how you make delays. Well, delays are data structures which contain an\n\nexpression, an environment, and a type on them.\n\n\n\n\nAnd it says they're a thunk. That comes from ALGOL language, and it's claimed to be the\n\nsound of something being pushed on a stack. I don't know. I was not an ALGOLician or an\nALGOLite or whatever, so I don't know. But that's what was claimed.\nAnd undelay is something which will recursively undelay thunks until the thunk becomes\n\nsomething which isn't a thunk. This is the way you implement a call by name like thing in\nALGOL. And that's about all there is.\n\n\n\n\n\nAre there any questions?\n\n\n\n\nAUDIENCE: Gerry?\n\n\n\n\nPROFESSOR: Yes, Vesko?\n\n\n\n\n\nAUDIENCE: I noticed you avoided calling by name in the primitive procedures, I was\nwondering what cause you have on that? You never need that?\n\n\n\n\nPROFESSOR: Vesko is asking if it's ever reasonable to call a primitive procedure by name?\n\nThe answer is, yes. There's one particular case where it's reasonable, actually two.\n\nConstruction of a data structure like cons where making an array if you have arrays with\nany number of elements. It's unnecessary to evaluate tho se arguments. All you need is\n\npromises to evaluate those arguments if you look at them. If I cons together two things,\nthen I could cons together the promises just as easily as I can cons together the things. And\n\nit's not even when I CAR CDR them that I have to look at them. That just gets out the\npromises and passes them to somebody.\n\n\n\n\n\nThat's why the lambda calculus definition, the Alonzo Church definition of CAR, CDR, and\ncons makes sense. It's because no work is done in CAR, CDR, and cons, it's just shuffling\n\ndata, it's just routing, if you will.\n\n\n\n\nHowever, the things that do have to look at data are things like plus. Because they have a\n\nlook at the bits that the numbers are made out of, unless they're lambda calculus numbers\nwhich are funny. They have to look at the bits to be able to crunch them together to do the\n\nadd.\n\n\n\n\nSo, in fact, data constructors, data selectors, and, in fact, things that side -effect data\n\nobjects don't need to do any forcing in the laziest possible interpreters. On the other hand\npredicates on data structures have to. Is this a pair? Or is it a symbol? Well, you better find\nout. You got to look at it then. Any other questions? Oh, well, I suppose it's time for a\n\nbreak. Thank you. [MUSIC PLAYING] and\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec8a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 8A: Logic Programming, Part 1\n\n\n\n[MUSIC PLAYING BY J.S. BACH] PROFESSOR: The last time we began having a look at how\nlanguages are constructed. Remember the main point that an evaluator for, LISP, say, has\n\ntwo main elements. There is EVAL, and EVAL's job is to take in an expression and an\nenvironment and turn that into a procedure and some arguments and pass that off to\n\nAPPLY. And APPLY takes the procedure in the arguments, turns that back into, in a general\ncase, another expression to be evaluated in another environment and passes that of f to\n\nEVAL, which passes it to APPLY, and there's this whole big circle where things go around\nand around and around until you get either to some very primitive data or to a primitive\n\nprocedure.\n\n\n\n\nSee, what this cycle has to do with is unwinding the means o f combination and the means\n\nof abstraction in the language. So for instance, you have a procedure in LISP-- a procedure\nis a general way of saying, I want to be able to evaluate this expression for any value of the\n\narguments, and that's sort of what's going on here. That's what APPLY does. It says the\n\ngeneral thing coming in with the arguments reduces to the expression that's the body, and\nthen if that's a compound expression or another procedure application, the thing will go\n\naround and around the circle. Anyway, that's sort of the basic structure of gee, pretty much\nany interpreter.\n\n\n\n\nThe other thing that you saw is once you have the interpreter in your hands, you have all\n\nthis power to start playing with the language. So you can make it dynamically scoped , or\n\nyou can put in normal order evaluation, or you can add new forms to the language,\nwhatever you like. Or more generally, there's this notion of metalinguistic abstraction, which\n\nsays that part of your perspective as an engineer, as a software engineer,but as an\nengineer in general is that you can gain control of complexity by inventing new languages\n\nsometimes. See, one way to think about computer programming is that it only incidentally\nhas to do with getting a computer to do something. Primarily what a computer program has\n\nto do with, it's a way of expressing ideas with communicating ideas. And sometimes when\nyou want to communicate new kinds of ideas, you'd like to invent new modes of expressing\n\nthat.\n\n\n\n\nWell, today we're going to apply this framework to build a new language. See, once we have\n\nthe basic idea of the interpreter, you can pretty much go build any language that you like.\nSo for example, we can go off and build Pascal. And gee, we would worry about syntax and\n\nparsing and various kinds of compiler optimizations, and there are people who make honest\nlivings doing that, but at the level of abstraction that we're talking, a Pascal interpreter\n\nwould not look very different at all from what you saw Gerry do last time.\n\n\n\n\nInstead of that, we'll spend today building a really different language, a language that\n\nencourages you to think about programming not in terms of procedures, but in a really\ndifferent way. And the lecture today is going to be at two levels simultaneously. On the one\n\nhand, I'm going to show you what this language looks like, and on the other hand, I'll show\nyou how it's implemented. And we'll build an implementation in LISP and see how that\n\nworks.\n\n\n\n\nAnd you should be drawing lessons on two levels. The first is to realize just how diff erent a\n\nlanguage can be. So if you think that the jump from Fortran to LISP is a big deal, you\nhaven't seen anything yet. And secondly, you'll see that even with such a very different\n\nlanguage, which will turn out to not have procedures at all and not talk about functions at\nall, there will still be this basic cycle of eval and apply that's unwinds the means of\n\ncombination and the means an abstraction. And then thirdly, as kind of a minor but elegant\ntechnical point, you'll see a nice use of streams to avoid backtracking.\n\n\n\n\n\nOK, well, I said that this language is very different. To explain that, let's go back to the very\nfirst idea that we talked about in this course, and that was the idea of the distinction\n\nbetween the declarative knowledge of mathematics-- the definition of a square root as a\nmathematical truth-- and the idea that computer science talks about the how to knowledge-\n\n- contrast that definition of square root with a program to compute a square root. That's\n\nwhere we started off. Well, wouldn't it be great if you could somehow bridge this gap and\nmake a programming language which sort of did things, but you talked about it in terms of\n\ntruth, in declarative terms? So that would be a programming language in which you specify\nfacts. You tell it what is. You say what is true. And then when you want an answer,\n\nsomehow the language has built into it automatically general kinds of how to knowledge so\nit can just take your facts and it can evolve these methods on its on using the facts you\n\ngave it and maybe some general rules of logic.\n\n\n\n\nSo for instance, I might go up to this program and start telling it some things. So I might\n\ntell it that the son of Adam is Abel. And I might tell it that the son of Adam is Cain. And I\nmight tell it that the son of Cain is Enoch. And I might tell it that the son of Enoch is Irad,\n\nand all through the rest of our chapter whatever of Genesis, which ends up ending in Adah,\nby the way, and this shows the genealogy of Adah from Cain.\n\n\n\n\n\nAnyway, once you tell it these facts, you might ask it things. You might go up to your\nlanguage and say, who's the son of Adam? And you can very easily imagine having a little\ngeneral purpose search program which would be able to go through and in response to that\n\nsay, oh yeah, there are two answers: the son of Adam is Abel and the son of Adam is Cain.\nOr you might say, based on the very same facts, who is Cain the son of? And then you can\n\nimagine generating another slightly different search program which would be able to go\nthrough and checked for who is Cain, and son of, and come up with Adam. Or you might\n\nsay, what's the relationship between Cain and Enoch? And again, a minor variant on that\nsearch program. You could figure out that it said son of.\n\n\n\n\n\nBut even here in this very simple example, what you see is that a single fact, see, a single\nfact like the son of Adam is Cain can be used to answer different kinds of questions. You can\n\nsay, who's the son of, or you can say who's the son of Adam, or you can say what's the\nrelation between Adam and Cain? Those are different questions being run by different\n\ntraditional procedures all based on the same fact.\n\n\n\n\nAnd that's going to be the essence of the power of this programming style, that one piece of\n\ndeclarative knowledge can be used as the basis for a lot of different kinds of how-to\nknowledge, as opposed to the kinds of procedures we're writing where you sort of tell it\n\nwhat input you're giving it and what answer you want. So for instance, our square root\n\nprogram can perfectly well answer the question, what's the square root of 144? But in\nprinciple, the mathematical definition of square root tells you other things. Like it could say,\n\nwhat is 17 the square root of? And that would be have to be answered by a different\nprogram. So the mathematical definition, or in general, the facts that you give it are\n\nsomehow unbiased as to what the question is. Whereas the programs we tend to write\nspecifically because they are how-to knowledge tend to be looking for a specific answer. So\n\nthat's going to be one characteristic of what we're talking about.\n\n\n\n\nWe can go on. We can imagine that we've given our language some sort of facts. Now let's\n\ngive it some rules of inference. We can say, for instance, if the-- make up some syntax\nhere-- if the son of x is y-- I'll put question marks to indicate variables here-- if the son of x\n\nis y and the son of y is z, then the grandson of x is z. So I can imagine telling my machine\nthat rule and then being able to say, for instance, who's the grandson of Adam? Or who is\n\nIrad the grandson of? Or deduce all grandson relationships you possibly can from this\ninformation. We can imagine somehow the language knowing how to do that automatically.\n\n\n\n\n\nLet me give you maybe a little bit more concrete example. Here's a procedure that merges\ntwo sorted lists. So x and y are two, say, lists of numbers, lists of distinct numbers, if you\n\nlike, that are in increasing order. And what merge does is take two such lists and combine\nthem into a list where everything's in increasing order, and this is a pretty easy programs\n\nthat you ought to be able to write. It says, if x is empty, the answer is y. If y is empty, the\n\nanswer is x. Otherwise, you compare the first two elements. So you pick out the first thing\nin x and the first thing in y, and then depending on which of those first elements is less, you\n\nstick the lower one on to the result a recursively merging, either chopping the first one off x\nor chopping the first one off y. That's a standard kind of program.\n\n\n\n\n\nLet's look at the logic. Let's forget about the program and look at the logic on which that\nprocedure is based. See, there's some logic which says, gee, if the first one is less, then we\n\nget the answer by sticking something onto the result of recursively merging the rest. So\nlet's try and be explicit about what that logic is that's making the program work.\n\n\n\n\n\nSo here's one piece. Here's the piece of the program which recursively chops down x if the\nfirst thing in x is smaller. And if you want to be very explicit about what the logic is there,\n\nwhat's really going on is a deduction, which says, if you know that some list, that we'll call\ncdr of x, and y merged to form z, and you know that a is less than the first thing in y, then\n\nyou know that if you put a onto the cdr of x, then that result and y merge to form a onto z.\nAnd what that is, that's the underlying piece of logic-- I haven't written it as a program, I\n\nwrote it a sort of deduction that's underneath this particular clause that says we can use the\nrecursion there. And then similar, here's the other clause just to complete it. The other\n\nclause is based on this piece of logic, which is almost the same and I won't go through it,\n\nand then there's the n cases where we tested for null, and that's based on the idea that for\nany x, x and the empty list merge to form an x, or for any y, the empty list and y merge to\n\nform y.\n\n\n\n\nOK, so there's a piece of procedure and the logic on which it's based. And notice a big\n\ndifference. The procedure looked like this: it said there was a box-- and all the things we've\nbeen doing have the characteristic we have boxes and things going in and things going out -\n\n- there was this box called merge, and in came an x and y, and out came an answer. That's\nthe character of the procedure that we wrote. These rules don't look likethat. These rules\n\ntalk about a relation. There's some sort of relation that in those slides I called mrege  -to-\nform. So I said x and y merge to form z, and somehow this is a function. Right? The answer\n\nis a function of x and y, and here what I have is a relation between three things. And I'm\nnot going to specify which is the input and which is the output. And the reason I want to say\n\nthat is because in principle, we could use exactly those same logic rules to answer a lot of\ndifferent questions.\n\n\n\n\n\nSo we can say, for instance-- imagine giving our machine those rules of logic. Not the\nprogram, the underlying rules of logic. Then it ought to be able to say-- we could ask it-- 1,\n\n3, 7 and 2, 4, 8 merge to form what? And that's a question it ought to be able to answer.\nThat's exactly the same question that our list procedure answered.\nBut the exact same rules should also be able to answer a question like this: 1, 3, 7 and\n\nwhat merged to form 1, 2, 3, 4, 7, 8? The same rules of logic can answer this, although the\nprocedure we wrote can't answer that question. Or we might be able to say what and what\n\nelse merge to form-- what and what else merge to form 1, 2, 3, 4, 7, 8? And the thing\nshould be able to go through, if it really can apply that logic, and deduce all, whatever is, 2\n\nto the sixth answers to that question. It could be 1 and the rest, or it could be 1, 2 and the\nrest. Or it could be 1 and 3 and 7 and the rest. There's a whole bunch of answers. And in\n\nprinciple, the logic should be enough to deduce that.\n\n\n\n\nSo there are going to be two big differences in the kind of program we're going to look at\n\nand not only list, but essentially all the programming you've probably done so far in pretty\nmuch any language you can think of. The first is, we're not going to be computing functions.\n\nWe're not going to be talking about things that take input and output. We're going to be\n\ntalking about relations. And that means in principle, these relations don't have\ndirectionality. So the knowledge that you specify to answer this question, that same\n\nknowledge should also allow you to answer these other questions and conversely.\n\n\n\n\nAnd the second issue is that since we're talking about relations, these relations don't\n\nnecessarily have one answer. So that third question down there doe sn't have a particular\nanswer, it has a whole bunch of answers.\n\n\n\n\nWell, that's where we're going. This style of programming, by the way, is called logic\n\nprogramming, for kind of obvious reasons. And people who do logic programming say that--\n\nthey have this little phrase-- they say the point of logic programming is that you use logic to\nexpress what is true, you use logic to check whether something is true, and you use logic to\n\nfind out what is true. The best known logic programming language, as you probably know,\nis called Prolog. The language that we're going to implement this morning is something we\n\ncall the query language, and it essentially has the essence of prologue. It can do about the\nsame stuff, although it's a lot slower because we're going to implement it in LISP rather\n\nthan building a particular compiler. We're going to interpret it on top of the LISP interpreter.\nBut other than that, it can do about the same stuff as prolog. It has about the same power\n\nand about the same limitations.\n\n\n\n\nAll right, let's break for question.\n\n\n\n\n\nSTUDENT: Yes, could you please repeat what the three things you use logic programming to\nfind? In other words, to find what is true, learn what is true-- what is the?\nPROFESSOR: Right. Sort of a logic programmer's little catechism. You use logic to express\n\nwhat is true, like these rules. You use logic to check whether something is true, and that's\nthe kind of question I didn't answer here. I might say-- another question I could put down\n\nhere is to say, is it true that 1, 3, 7 and 2, 4, 8 merge to form 1, 2, 6, 10 And that same\nlogic should be enough to say no. So I use logic to check what is true, and then you also\n\nuse logic to find out what's true.\n\n\n\n\nAll right. Let's break.\n\n\n\n\n\n[MUSIC PLAYING BY J.S. BACH]\n\n\n\n\n[MUSIC ENDS]\n\n\n\n\n[MUSIC PLAYING BY J.S. BACH]\n\n\n\n\n\nPROFESSOR: OK, let's go ahead and take a look at this query language and operation. The\nfirst thing you might notice, when I put up that little biblical database, is that it's nice to be\n\nable to ask this language questions in relation to some collection of facts. So let's start off\nand make a little collection of facts. This is a tiny fragment of personnel records for a Boston\n\nhigh tech company, and here's a piece of the personnel records of Ben Bitdiddle. And Ben\nBitdiddle is the computer wizard in this company, he's the underpaid computer wizard in\n\nthis company. His supervisor is all Oliver Warbucks, and here's his address.\n\n\n\n\nSo the format is we're giving this information: job, salary, supervisor, address. And there\n\nare some other conventions. Computer here means that Ben works in the computer\ndivision, and his position in the computer division is wizard.\n\n\n\n\n\nHere's somebody else. Alyssa, Alyssa P. Hacker is a computer programmer, and she works\nfor Ben, and she lives in Cambridge. And there's another programmer who works for Ben\n\nwho's Lem E. Tweakit. And there's a programmer trainee, who is Louis Reasoner, and he\nworks for Alyssa. And the big wheel of the company doesn't work for anybody, right? That's\n\nOliver Warbucks.\n\n\n\n\nAnyway, what we're going to do is ask questions about that little world. And that'll be a\n\nsample world that we're going to do logic in. Let me just write up here, for probably the last\ntime, what I said is the very most important thing you should get out of this course, and\n\nthat is, when somebody tells you about a language, you say, fine-- what are the primitives,\nwhat are the means of combination, how do you put the primitives together, and then how\n\ndo you abstract them, how do you abstract the compound pieces so you can use them as\npieces to make something more complicated? And we've said this a whole bunch of times\n\nalready, but it's worth saying again.\n\n\n\n\nLet's start. The primitives. Well, there's really only one primitive, and the primitive in this\n\nlanguage is called a query. A primitive query. Let's look at some primitive queries. Job x.\nWho is a computer programmer? Or find every fact in the database that matches job of the\n\nx is computer programmer. And you see a little syntax here. Things without question marks\nare meant to be literal, question mark x means that's a variable, and this thing will match,\n\nfor example, the fact that Alyssa P. Hacker is a computer programmer, or x is Alyssa P.\n\nHacker. Or more generally, I could have something with two variables in it. I could say, the\njob of x is computer something, and that'll match computer wizard. So there's something\n\nhere: type will match wizard, or type will match programmer, or x might match various\ncertain things. So there are, in our little example, only threefacts in that database that\n\nmatch that query.\n\n\n\n\nLet's see, just to show you some syntax, the same query, this query doesn't match the job\n\nof x, doesn't match Lewis Reasoner, the reason for that is when I write something here,\nwhat I mean is that this is going to be a list of two symbols, of which the first is the word\n\ncomputer, and the second can be anything. And Lewis's job description here has three\nsymbols, so it doesn't match.\n\n\n\n\n\nAnd just to show you a little bit of syntax, the more general thing I might want to type is a\nthing with a dot here, and this is just standard this notation for saying, this is a list, of\n\nwhich the first element is the word computers, and THE REST, is something that I'll call\ntype. So this one would match. Lewis's job is computer programmer trainee, and type here\n\nwould be the cdr of this list. It would be the list programmer trainee. And that kind of dot\nprocessing is done automatically by the LISP reader.\n\n\n\n\n\nWell, let's actually try this. The idea is I'm going to type in queriein this language, and\nanswers will come out. Let's look at this. I can go up and say, who works in the computer\n\ndivision? Job of x is computer dot y. Doesn't matter what I call the dummy variables. It says\nthe answers to that, and it's found four answers. Or I can go off and say, tell me about\n\neverybody's supervisor.\nSo I'll put in the query, the primitive query, the supervisor of x is y. There are all the\n\nsupervisor relationships I know. Or I could go type in, who lives in Cambridge? So I can say,\nthe address of x is Cambridge dot anything. And only one person lives in Cambridge.\n\n\n\n\n\nOK, so those are primitive queries. And you see what happens to basic interaction with the\nsystem is you type in a query, and it types out all possible answers. Or another way to say\n\nthat: it finds out all the possible values of those variables x and y or t or whatever I've\ncalled them, and it types out all ways of taking that query and instantiating it-- remember\n\nthat from the rule system lecture-- instantiates the query with all possible values for those\nvariables and then types out all of them.\n\n\n\n\n\nAnd there are a lot of ways you can arrange a logic language. Prolog, for instance, does\nsomething slightly different. Rather than typing back your query, prolog would type out, x\n\nequals this and y equals that, or x sequels this and y equals that. And that's a very surface\nlevel thing, you can decide what you like. OK.\n\n\n\n\n\nAll right. So the primitives in this language? Only one, right? Primitive query.\n\n\n\n\nOK. Means of combination. Let's look at some compound queries in this language. Here's\n\none. This one says, tell me all the people who work in the computer division. Tell me all the\npeople who work in the computer division together with their supervisors. The way I write\n\nthat is the query is and. And the job of the x is computer something or other. And job of x is\ncomputer dot y. And the supervisor of x is z.\n\n\n\n\n\nTell me all the people in the computer division -- that's this-- together with their supervisors.\nAnd notice in this query I have three variables-- x, y, and z. And this x is supposed to be\n\nthe same as that x. So x works in the computer division, and the supervisor of x is z.\n\n\n\n\nLet's try another one. So one means of combination is and.\n\n\n\n\nWho are all the people who make more than $30,000? And the salary of some person p is\n\nsome amount a. And when I go and look at a, a is greater than $30,000. And LISP value\nhere is a little piece of interface that interfaces the query language to the underlying LISP.\n\nAnd what the LISP value allows you to do is call any LISP predicate inside a query. So here\nI'm using the LISP predicate greater than, so I say LISP value. This I say and. So all the\n\npeople whose salary is greater than $30,000.\nOr here's a more complicated one. Tell me all the people whowork in the computer division\nwho do not have a supervisor who works in the computer division. and x works in the\n\ncomputer division. The job of x is computer dot y. And it's not the case that both x has a\nsupervisor z and the job of z is computer something or other. All right, so again, this x has\n\ngot to be that x, and this z is going to be that z.\n\n\n\n\nAnd then you see another means a combination, not. All right, well, let's look at that. It\n\nworks the same way.\n\n\n\n\nI can go up to the machine and say and the job of the x is computer dot y. And the\n\nsupervisor of x is z. And I typed that in like a query. And what it types back, what you see\nare the queries I typed in instantiated by all possible answers. And then you see there are a\n\nlot of answers.\n\n\n\n\nAll right. So the means of combination in this language-- and this is why it's called a logic\n\nlanguage-- are logical operations. Means of combinations are things like AND and NOT and\nthere's one I didn't show you, which is OR. And then I showed you LISP value, which is not\n\nlogic, of course, but is a little special hack to interface that to LISP so you can get more\npower. Those are the means of combination.\n\n\n\n\n\nOK, the means of abstraction. What we'd like to do-- let's go back for second and look at\nthat last slide. We might like to take very complicated thing, the idea that someone works in\n\na division but does not have a supervisor in the division. And as before, name that. Well, if\nsomeone works in a division and does not have a supervisor who works in that division, that\n\nmeans that person is a big shot. So let's make a rule that somebody x is a big shot in some\n\ndepartment if x works in the department and it's not the case that x has a supervisor who\nworks in the department.\n\n\n\n\nSo this is our means of abstraction. This is a rule. And a rule has three parts. The thing that\n\nsays it's a rule. And then there's the conclusion of the rule. And then there's the body of the\nrule. And you can read this as a piece of logic which says, if you know that the body of the\n\nrule is true, then you can conclude that the conclusion is true. Or in order to deduce that x\n\nis a big shot in some department, it's enough to verify that. So that's what rules look like.\nLet's go back and look at that merge example that I did before the break. Let's look at how\n\nthat would look in terms of rules. I'm going to take the logic I put up and just change it into\na bunch of rules in this format.\n\n\n\n\n\nWe have a rule. Remember, there was this thing merge-to-form. There is a rule that says,\nthe empty list and y merge to form y. This is the rule conclusion. And notice this particular\n\nrule has no body. And in this language, a rule with no body is something that is always true.\nYou can always assume that's true.\n\n\n\n\n\nAnd there was another piece of logic that said anything in the empty list merged to form the\nanything. That's this. A rule y and the empty list merge to form y. Those corresponded to\n\nthe two end cases in our merge procedure, but now we're talking about logic, not about\nprocedures.\n\n\n\n\n\nThen we had another rule, which said if you know how shorter things merge, you can put\nthem together. So this says, if you have a list x and y and z, and if you want to deduce that\n\na dot x-- this means constant a onto x, or a list whose first thing is a an d whose rest is x--\nso if you want to deduce that a dot x and b dot y merge to form b dot c-- that would say\n\nyou merge these two lists a x and b y and you're going to get something that starts with b--\nyou can deduce that if you know that it's the case bot h that a dot x and y merge to form z\n\nand a is larger than b.\n\n\n\n\nSo when I merge them, b will come first in the list. That's a little translation of the logic rule\n\nthat I wrote in pseudo-English before.\n\n\n\n\nAnd then just for completeness, here's the other case. a dot x and b dot y merge to form a\n\ndot z if x and b dot y merged to form z and b is larger than a. So that's a little program that\nI've typed in in this language, and now let's look at it run.\n\n\n\n\n\nSo I typed in the merge rules before, and I could use this like a procedure. I could say\nmerge to form 1 and 3 and 2 and 7. So here I'm using it like the LISP procedure. Now it's\n\ngoing to think about that for a while and apply these rules. So it found an answer. Now it's\ngoing to see if there are any other answers but it doesn't know a priori there's only one\n\nanswer. So it's sitting here checking all possibilities, and it says, no more. Done.\nSo there I've used those rules like a procedure. Or remember the whole point is that I can\n\nask different kinds of questions. I could say merge to form, let's see, how about 2 and a.\nSome list of two elements which I know starts with 2, and the other thing I don't know, and\n\nx and some other list merge to form a 1, 2, 3 and 4. So now it's going to think about that.\nIt's got to find-- so it found one possibility. It said a could be 3, and x could be the list 1, 4.\n\nAnd now, again, it's got to check because it doesn't a priori know that there aren't any other\npossibilities going on.\n\n\n\n\n\nOr like I said, I could say something like mer ge to form, like, what and what else merge to\nform 1, 2, 3, 4, 5? Now it's going to think about that. And there are a lot of answers that it\n\nmight get. And what you see is here you're really paying the price of slowness. And kind of\nfor three reasons. One is that this language is doubly interpreted. Whereas in a real\n\nimplementation, you would go compile this down to primitive operations. The other reason\n\nis that this particular algorithm for merges is doubly recursive. So it's going to take a very\nlong time. And eventually, this is going to go through and find-- find what? Two to the fifth\n\npossible answers.\n\n\n\n\nAnd you see they come out in some fairly arbitrary order, depending on which order it's\n\ngoing to be trying these rules. In fact, what we're going to do when they edit the videotape\nis speed all this up. Don't you like taking out these weights? And don't you wish you could\n\ndo that in your demos?\n\n\n\n\nAnyway, it's still grinding there. Anyway, there are 32 possibilities-- we won't wait for it to\n\nprint out all of them.\n\n\n\n\nOK, so the needs of abstraction in this language are rules. So we take some bunch of things\nthat are put together with logic and we name them. And you can think of that as naming a\n\nparticular pattern of logic. Or you can think of that as saying, if you want to deduce some\n\nconclusion, you can apply those rules of logic. And those are three elements of this\nlanguage.\n\n\n\n\nLet's break now, and then we'll talk about how it's actually implemented.\n\n\n\n\n\nSTUDENT: Does using LISP value primitive or whateverinterfere with your means to go\nboth directions on a query?\nPROFESSOR: OK, that's a-- the question is, does using LISP value interfere with the ability\n\nto go both directions on the query? We haven't really talked about the implementation yet,\nbut the answer is, yes, it can. In general, as we'll see at the end-- although I really won't to\n\ngo into details-- it's fairly complicated, especially when you use either not or LISP value-- or\nactually, if you use anything besides only and, it becomes very complicat ed to say when\n\nthese things will work. They won't work quite in all situations. I'll talk about that at the end\nof the second half today.\n\n\n\n\n\nBut the answer to your question is, yes, by dragging in a lot more power from LISP value,\nyou lose some of the principal power of logic programming. That's a trade-off that you have\n\nto make.\n\n\n\n\nOK, let's take a break.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec8b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 8B: Logic Programming, Part 2\n\n\n\nPROFESSOR: All right, well, we've seen how the query language works. Now, let's talk about\nhow it's implemented. You already pretty much can guess what's going on there. At the\n\nbottom of it, there's a pattern matcher. And we looked at a pattern matcher whe n we did\nthe rule-based control language.\n\n\n\n\n\nJust to remind you, here are some sample patterns. This is a pattern that will match any list\nof three things of which the first is a and the second is c and the middle one can be\n\nanything. So in this little pattern-matching syntax, there's only one distinction you make.\nThere's either literal things or variables, and variables begin with question mark.\n\n\n\n\n\nSo this matches any list of three things of which the first is a and the second is c. This one\nmatches any list of three things of which the first is the symbol job. The second can be\n\nanything. And the third is a list of two things of which the first is the symbol computer and\nthe second can be anything. And this one, this next one matches any list of three things ,\n\nand the only difference is, here, the third list, the first is the symbol computer, and then\nthere's some rest of the list. So this means two elements and this means arbitrary number.\n\nAnd our language implementation isn't even going to have to worry abou t implementing this\ndot because that's automatically done by Lisp's reader.\n\n\n\n\n\nRemember matchers also have some consistency in them. This match is a list of three\nthings of which the first is a. And the second and third can be anything, but they have to be\n\nthe same thing. They're both called x. And this matches a list of four things of which the\nfirst is the fourth and the second is the same as the third. And this last one matches any list\n\nthat begins with a. The first thing is a, and the rest can be anything. So that's just a review\nof pattern matcher syntax that you've already seen.\n\n\n\n\n\nAnd remember, that's implemented by some procedure called match. And match takes a\npattern and some data and a dictionary. And match asks the question is there any way to\n\nmatch this pattern against this data object subject to the bindings that are already in this\ndictionary?\n\n\n\n\n\nSo, for instance, if we're going to match the pattern x, y, y, x against the data a, b, b, a\nsubject to a dictionary, that says x equals a. Then the matcher would say, yes, that's\nconsistent. These match, and it's consistent with what's in the dictionary to say that x\n\nequals a. And the result of the match is the extended dictionary that says x equals a and y\nequals b. So a matcher takes in pattern data dictionary, puts out an extended dictionary if it\n\nmatches, or if it doesn't match, says that it fails. So, for example, if I use the same pattern\nhere, if I say this x, y, y, x match a, b, b, a with the dictionary y equals a, then the matcher\n\nwould put out fail.\n\n\n\n\nWell, you've already seen the code for a pattern matcher so I'm not going to go over it, but\n\nit's the same thing we've been doing before. You saw that in the system on rule -based\ncontrol. It's essentially the same matcher. In fact, I think the syntax is a little bit simpler\n\nbecause we're not worrying about arbitrary constants and expressions and things. There's\njust variables and constants.\n\n\n\n\n\nOK, well, given that, what's a primitive query? Primitive query is going to be a rather\ncomplicated thing. It's going to be-- let's think about the query job of x is d dot y. That's a\n\nquery we might type in. That's going to be implemented in the system. We'll think of it as\nthis little box. Here's the primitive query.\n\n\n\n\n\nWhat this little box is going to do is take in two streams and put out a stream. So the shape\nof a primitive query is that it's a thing where two streams come in and one stream goes out.\n\nWhat these streams are going to be is down here is the database. So we imagine all the\nthings in the database sort of sitting there in a stream and this thing sucks on them. So\n\nwhat are some things that might be in the database? Oh, job of Alyssa is something and\n\nsome other job is something. So imagine all of the facts in the database sitting there in the\nstream. That's what comes in here.\n\n\n\n\nWhat comes in here is a stream of dictionaries. So one particular dictionary might say y\n\nequals programmer. Now, what the query does when it gets in a dictionary from this\n\nstream, it finds all possible ways of matching the query against whatever is coming in from\nthe database. It looks at the query as a pattern, matches it against any fact from the\n\ndatabase or all possible ways of finding and matching the database with respect to this\ndictionary that's coming in. So for each fact in the database, it calls the matcher using the\n\npattern, fact, and dictionary. And every time it gets a good match, it puts out the extended\ndictionary.\n\n\n\n\n\nSo, for example, if this one comes in and it finds a match, out will come a dictionary that in\nthis case will have y equals programmer and x equals something. y is programmer, x is\n\nsomething, and d is whatever it found. And that's all. And, of course, it's going to try this for\nevery fact in the dictionary. So it might find lots of them. It might find another one that\n\nsays y equals programmer and x equals, and d equals.\n\n\n\n\nSo for one frame coming in, it might put out-- for one dictionary coming in, it might put out\n\na lot of dictionaries, or it might put out none. It might have something that wouldn't match\nlike x equals FOO. This one might not match anything in which case no thing will go into this\n\nstream corresponding to this frame. Or what you might do is put in an empty frame, and an\nempty frame says try matching all ways-- find all possible ways of matching the query\n\nagainst something in the database subject to no previous restrictions. And if you think about\nwhat that means, that's just the computation that's done when you type in a query right off.\n\nIt tries to find all matches.\n\n\n\n\nSo a primitive query sets up this mechanism. And what the language does, when you type\n\nin the query at the top level, it takes this mechanism, feeds in one single empty dictionary,\nand then for each thing that comes out takes the original query and instantiates the result\n\nwith all the different dictionaries, producing a new stream of instantiated patterns here. And\nthat's what gets printed on the terminal. That's the basic mechanism going on there.\n\n\n\n\n\nWell, why is that so complicated? You probably can think of a lot simpler ways to arrange\nthis match for a primitive query rather than having all of these streams floating around. And\n\nthe answer is-- you probably guess already. The answer is this thing extends elegantly to\nimplement the means of combination. So, for instance, suppose I don't only want to do this.\n\nI don't want to say who to be everybody's job description.\n\n\n\n\nSuppose I want to say AND the job of x is d dot y and the supervisor of x is z. Now,\n\nsupervisor of x is z is going to be another primitive query that has the same shape to take\nin a stream of data objects, a stream of initial dictionaries, which are the restrictions to try\n\nand use when you match, and it's going to put out a stream of dictionaries. So that's what\n\nthis primitive query looks like. And how do I implement the AND? Well, it's simple. I just\nhook them together. I take the output of this one, and I put that to the input of that one.\n\nAnd I take the dictionary here and I fan it out.\n\n\n\n\nAnd then you see how that's going to work, because what's going to happen is a frame will\nnow come in here, which has a binding for x, y, and d. And then when this one gets it, it'll\n\nsay, oh, gee, subject to these restrictions, which now already have values in the dictionary\n\nfor y and x and d, it looks in the database and says, gee, can I find any supervisor facts?\nAnd if it finds any, out will come dictionaries which have bindings for y and x and d and z\n\nnow.\nAnd then notice that because the frames coming in here have these restrictions, that's the\nthing that assures that when you do the AND, this x will mean the same thing as that x.\n\nBecause by the time something comes floating in here, x has a value that you have to\nmatch against consistently. And then you remember from the code from the matcher, there\n\nwas something in the way the matcher did dictionaries that arrange consistent matches. So\n\nthere's AND.\n\n\n\n\nThe important point to notice is the general shape. Look at what happened: the AND of two\nqueries, say, P and Q. Here's P and Q. The AND of two queries, well, it looks like this. Each\n\nquery takes in a stream from the database, a stream of inputs, and puts out a stream of\n\noutputs. And the important point to notice is that if I draw a box around this thing and say\nthis is AND of P and Q, then that box has exactly the same overall shape. It's something\n\nthat takes in a stream from the database. Here it's going to get fanned out inside, but from\nthe outside you don't see that. It takes an input stream and puts out an output stream.\n\n\n\n\n\nSo this is AND. And then similarly, OR would look like this. OR would -- although I didn't\nshow you examples of OR. OR would say can I find all ways of matching P or Q. So I have P\n\nand Q. Each will have their shape. And the way OR is implemented is I'll take my database\nstream. I'll fan it out. I'll put one into P and one into Q. I'll take my initial query stream\n\ncoming in and fan it out. So I'll look at all the answers I might get from P and all the\nanswers I might get from Q, and I'll put them through some sort of thing that appends\n\nthem or merges the result into one stream, and that's what will come out. And this whole\nthing from the outside is OR. And again, you see it has the same overall shape when looked\n\nat from the outside.\n\n\n\n\nWhat's NOT? NOT works kind of the same way. If I have some query P, I take the primitive\n\nquery for P. Here, I'm going to implement NOT P. And NOT'sjust going to act as a filter. I'll\ntake in the database and my original stream of dictionaries coming in, and what NOT P will\n\ndo is it will filter these guys. And the way it will filter it, it will say when I get in a dictionary\nhere, I'll find all the matches, and if I find any, I'll throw it away. And if I don't find any\n\nmatches to something coming in here, I'll just pass that through, so NOT is a pure filter.\n\n\n\n\nSo AND is-- think of these sort of electoral resistors or something. AND is series\n\ncombination and OR is parallel combination. And then NOT is not going to extend any\ndictionaries at all. It's just going to filter it. It's going to throw away the ones for which it\n\nfinds a way to match. And list value is sort of the same way. The filter's a little more\n\ncomplicated. It applies to predicate.\nThe major point to notice here, and it's a major point we've looked at before, is this idea of\n\nclosure. The things that we build as a means of combination have the same overall structure\nas the primitive things that we're combining. So the AND of two things when looked at from\n\nthe outside has the same shape. And what that means is that this box here could be an AND\nor an OR or a NOT or something because it has the same shape to interface to the larger\n\nthings.\n\n\n\n\nIt's the same thing that allowed us to get complexity in the Escher picture language or\n\nallows you to immediately build up these complicated structures just out of pairs. It's\nclosure. And that's the thing that allowed me to do what by now you took for gran ted when\n\nI said, gee, there's a query which is AND of job and salary, and I said, oh, there's another\none, which is AND of job, a NOT of something. The fact that I can do that is a direct\n\nconsequence of this closure principle. OK, let's break and then we'll go on.\n\n\n\n\nAUDIENCE: Where does the dictionary come from?\n\n\n\n\n\nPROFESSOR: The dictionary comes initially from what you type in. So when you start this\nup, the first thing it does is set up this whole structure. It puts in one empty dictionary. And\n\nif all you have is one primitive query, then what will come out is a bunch of dictionaries with\nthings filled in. The general situation that I have here is when this is in the middle of some\n\nnest of combined things.\n\n\n\n\nLet's look at the picture over here. This supervisor query gets in some dictionary. Where did\n\nthis one come from? This dictionary came from the fact that I'm looking at the output of this\nprimitive query. So maybe to be very specific, if I literally typedin just this query at the top\n\nlevel, this AND, what would actually happen is it would build this structure and start up this\nwhole thing with one empty dictionary. And now this one would process, and a whole bunch\n\nof dictionaries would come out with x, y's and d's in them. Run it through this one.\n\n\n\n\nSo now that's the input to this one. This one would now put out some other stuff. And if this\n\nitself were buried in some larger thing, like an OR of something, then that would go feed\ninto the next one. So you initially get only one empty dictionary when you start it, but as\n\nyou're in the middle of processing these compounds things, that's where these cascades of\ndictionaries start getting generated.\nAUDIENCE: Dictionaries only come about as a result of using t he queries? Or do they\n\nbecome-- do they stay someplace in space like the database does? Are these temporary\nitems?\n\n\n\n\n\nPROFESSOR: They're created temporarily in the matcher. Really, they're someplace in\nstorage. Initially, someone creates a thing called theempty dictionary that gets initially fed\n\nto this match procedure, and then the match procedure builds some dictionaries, and they\nget passed on and on.\n\n\n\n\n\nAUDIENCE: OK, so they'll go way after the match?\n\n\n\n\nPROFESSOR: They'll go away when no one needs them again, yeah.\n\n\n\n\nAUDIENCE: It appears that the AND performs some redundant searches of the database. If\n\nthe first clause matched, let's say, the third element and not on the first two elements, the\nsecond clause is going to look at those first two elements again, discarding them because\n\nthey don't match. The match is already in the dictionary. Would it makes sense to carry the\ndata element from the database along with the dictionary?\n\n\n\n\n\nPROFESSOR: Well, in general, there are other ways to arrange this search, and there's\nsome analysis that you can do. I think there's a problem in the book, which talks about a\n\ndifferent way that you can cascade AND to eliminate various kinds of redundancies. This one\nis meant to be-- was mainly meant to be very simple so you can see how they fit together.\n\nBut you're quite right. There are redundancies here that you can get rid of. That's another\n\nreason why this language is somewhat slow. There are a lot smarter things you can do.\nWe're just trying to show you a very simple, in principle, implementation.\n\n\n\n\nAUDIENCE: Did you model this language on Prolog, or did it just come out looking like\n\nProlog?\n\n\n\n\nPROFESSOR: Well, Jerry insulted a whole bunch of people yesterday, so I might as well say\n\nthat the MIT attitude towards Prolog is something that people did in about 1971 and decided\nthat it wasn't really the right thing and stopped. So we modeled this on the sort of natural\n\nway that this thing was done in about 1971, except at that point, we didn't do it with\nstreams. After we were using it for about six months, we discovered that it had all these\nproblems, some of which I'll talk about later. And we said, gee, Prolog must have fixed\n\nthose, and then we found out that it didn't. So this does about the same thing as Prolog.\n\n\n\n\nAUDIENCE: Does Prolog use streams?\n\n\n\n\nPROFESSOR: No. In how it behaves, it behaves a lot like Prolog. Prolog uses a backtracking\n\nstrategy. But the other thing that's really good about Prolog that makes it a usable thing is\nthat there's a really very, very well-engineered compiler technology that makes it run fast.\n\nSo although you saw the merge spitting out these answers very, very slowly, a real Prolog\n\nwill run very, very fast. Because even though it's sort of doing this, the real work that went\ninto Prolog is a very, very excellent compiler effort. Let's take a break.\n\n\n\n\nWe've looked at the primitive queries and the ways that streams are used to implement the\n\nmeans of combination: AND and OR and NOT. Now, let go on to the means of abstraction.\n\nRemember, the means of abstraction in this language are rules. So z is a boss in division d\nif there's some x who has a job in division d and z is the supervisor of x. That's what it\n\nmeans for someone to be a boss.\n\n\n\n\nAnd in effect, if you think about what we're doing with relation to this, there's the query we\n\nwrote-- the job of x is in d and the supervisor of x is z-- what we in effect want to do is take\nthis whole mess and draw a box around it and say this whole thing inside the box is boss of\n\nz in division d. That's in effect what we want to do.\n\n\n\n\nSo, for instance, if we've done that, and we want to check whether or not it's true that Ben\n\nBitdiddle is a boss in the computer division, so if I want to say boss of Ben Bitdiddle in the\ncomputer division, imagine typing that in as query to the system, in effect what we want to\n\ndo is set up a dictionary here, which has z to Ben Bitdiddle and d to computer. Where did\nthat dictionary come from? Let's look at the slide for one second.\n\n\n\n\n\nThat dictionary came from matching the query that said boss of Ben Bitdi ddle and computer\nonto the conclusion of the rule: boss of z and d. So we match the query to the conclusion of\n\nthe rule. That gives us a dictionary, and that's the thing that we would now like to put into\nthis whole big thing and process and see if anything comes out the other side. If anything\n\ncomes out, it'll be true. That's the basic idea.\nSo in general, the way we implement a rule is we match the conclusion of the rule against\n\nsomething we might want to check it's true. That match gives us a dictionary, and with\nrespect to that dictionary, we process the body of the rule.\n\n\n\n\n\nWell, that's really all there is, except for two technical points. The first technical point is that\nI might have said something else. I might have said who's the boss in the computer\n\ndivision? So I might say boss of who in computer division. And if I did that, what I would\nreally like to do in effect is start up this dictionary with a match that sort of says, well, d is\n\ncomputer and z is whatever who is. And our matcher won't quite do that. That's not quite\nmatching a pattern against data. It's matching two patterns and saying are they consistent\n\nor not or what ways make them consistent.\n\n\n\n\nIn other words, what we need is not quite a pattern matcher, but something a little bit more\n\ngeneral called a unifier. And a unifier is a slight generalization of a pattern matcher. What a\nunifier does is take two patterns and say what's the most general thing you can substitute\n\nfor the variables in those two patterns to make them satisfy the pattern simultaneously? Let\nme give you an example.\n\n\n\n\n\nIf I have the pattern two-element list, which is x and x, so I have a two-element list where\nboth elements are the same and otherwise I don't care what they are, and I unify that\n\nagainst the pattern that says there's a two-element list, and the first one is a and\nsomething in c and the second one is a and b and z, then what the unifier should tell me is,\n\noh yeah, in that dictionary, x has to be a, b, c, and y has to be d and z has to be c. Those\n\nare the restrictions I'd have to put on the values of x, y, and z to make these two unify, or\nin other words, to make this match x and make this match x. The unifier should be able to\n\ndeduce that.\n\n\n\n\nBut the unifier may-- there are more complicated things. I might have said something a\n\nlittle bit more complicated. I might have said there's a list with two elements, and they're\nboth the same, and they should unify against something of this form. And the unifier should\n\nbe able to deduce from that. Like that y would have to be b. y would have to be b. Because\nthese two are the same, so y's got to be b. And v here would have to be a. And z and w can\n\nbe anything, but they have to be the same thing. And x would have to be b, followed by a,\nfollowed by whatever w is or whatever z is, which is the same. So you see, the unifier\n\nsomehow has to deduce things to unify these patterns. So you might think there's some\nkind of magic deduction going on, but there's not.\n\n\n\n\n\nA unifier is basically a very simple modification of a pattern matche r. And if you look in the\nbook, you'll see something like three or four lines of code added to the pattern matcher you\njust saw to handle the symmetric case. Remember, the pattern matcher has a place where\n\nit says is this variable matching a constant. And if so, it checks in the dictionary. There's\nonly one other clause in the unifier, which says is this variable matching a variable, in which\n\ncase you go look in the dictionary and see if that's consistent with what's in the dictionary.\n\n\n\n\nSo all the, quote, deduction that's in this language, if you sort of look at it, sort of sits in the\n\nrule applications, which, if you look at that, sits in the unifier, which, if you look at that\nunder a microscope, sits essentially in the pattern matcher. There's no magic at all going on\n\nin there. And the, quote, deduction that you see is just the fact that there's this recursion,\nwhich is unwinding the matches bit by bit. So it looks like this thing is being very clever, but\n\nin fact, it's not being very clever at all.\n\n\n\n\nThere are cases where a unifier might have to be clever. Let me show you one more.\n\nSuppose I want to unify a list of two elements, x and x, with a thing that says it's y followed\nby a dot y. Now, if you think of what that would have to mean, it would have to mean that x\n\nhad better be the same as y, but also x had better be the same as a list whose first element\nis a and whose rest is y. And if you think about what that would have to mean, it would\n\nhave to mean that y is the infinite list of a's. In some sense, in order to do that unification, I\n\nhave to solve the fixed-point equation cons of a to y is equal to y.\n\n\n\n\nAnd in general, I wrote a very simple one. Really doing unification might have to solve an\narbitrary fixed-point equation: f of y equals y. And basically, you can't do that and make the\n\nthing finite all the time. So how does the logic language handle that? The answer is it\n\ndoesn't. It just punts. And there's a little check in the unifier, which says, oh, is this one of\nthe hard cases which when I go to match things would involve solving a fixed -point\n\nequation?\n\n\n\n\nAnd in this case, I will throw up my hands. And if that check were not in there, what would\n\nhappen? In most cases is that the unifier would just go into an infinite loop. And other logic\nprogramming languages work like that. So there's really no magic. The easy case is done in\n\na matcher. The hard case is not done at all. And that's about the state of this technology.\n\n\n\n\nLet me just say again formally how rules work now that I talked about unifiers. So the\nofficial definition is that to apply a rule, we -- well, let's start using some words we've used\n\nbefore. Let's talk about sticking dictionaries into these big boxes of query things as\n\nevaluating these large queries relative to an environment or a frame. So when you think of\nthat dictionary, what's the dictionary after all? It's a bunch of meanings for symbols. That's\n\nwhat we've been calling frames or environments.\nWhat does it mean to do some processing relevant to an environment? That's what we'v e\nbeen calling evaluation. So we can say the way that you apply a rule is to evaluate the rule\n\nbody relative to an environment that's formed by unifying the rule conclusion with the given\nquery. And the thing I want you to notice is the complete formal similarity to the net of\n\ncircular evaluator or the substitution model.\n\n\n\n\nTo apply a procedure, we evaluate the procedure body relative to an environment that's\n\nformed by blinding the procedure parameters to the arguments. There's a complete formal\nsimilarity here between the rules, rule application, and procedure application even though\n\nthese things are very, very different. And again, you have the EVAL APPLY loop. EVAL and\n\nAPPLY.\n\n\n\n\nSo in general, I might be processing some combined expression that will turn into a rule\napplication, which will generate some dictionaries or frames or environments-- whatever\n\nyou want to call them-- from match, which will then be the input to some big compound\n\nthing like this. This has pieces of it and may have other rule applications. And you have\nessentially the same cycle even though there's nothing here at all that looks like\n\nprocedures. It really has to do with the fact you've built a language whose means of\ncombination and abstraction unwind in certain ways.\n\n\n\n\n\nAnd then in general, what happens at the very top level, you might have rules in your\ndatabase also, so things in this database might be rules. There are ways to check that\n\nthings are true. So it might come in here and have to do a rule check. And then there's\nsome control structure which says, well, you look at some rules, and you look atsome data\n\nelements, and you look at some rules and data elements, and these fan out and out and\nout.\n\n\n\n\n\nSo it becomes essentially impossible to say what order it's looking at these things in,\nwhether it's breadth first or depth first or anything. And it's even more impossible because\n\nthe actual order is somehow buried in the delays of the streams. So what's very hard to tell\nfrom this is the order in which it's scanned. But what's true, because you're looking at the\n\nstream view, is that all of them eventually get looked at.\n\n\n\n\nLet me just mention one tiny technical problem. Suppose I tried saying boss of y is\n\ncomputer, then a funny thing would happen. As I stuck a dictionary with y in here, I might\nget-- this y is not the same as that y, which was the other piece of somebody's job\ndescription. So if I really only did literally what I said, we'd get some variable conflict\n\nproblems. So I lied to you a little bit.\n\n\n\n\nNotice that problem is exactly a problem we've run into before. It is precisely the need for\n\nlocal variables in a language. When I have the sum of squares, that x had better not be that\nx. That's exactly the same as this y had better not be that y. And we know how to solve\n\nthat. That was this whole environment model, and we built chains of frames and a ll sorts of\nthings like that.\n\n\n\n\n\nThere's a much more brutal way to solve it. In the query language, we didn't even do that.\nWe did something completely brutal. We said every time you apply a rule, rename\n\nconsistently all the variables in the rule to some new unique names that won't conflict with\nanything. That's conceptually simpler, but really brutal and not particularly efficient.\n\n\n\n\n\nBut notice, we could have gotten rid of all of our environment structures if we defined for\nprocedures in Lisp the same thing. If every time we applied a procedure and did the\n\nsubstitution model we renamed all the variables in the procedure, then we never would\nhave had to worry about local variables because they would never arise. OK, well, that\n\nwould be inefficient, and it's inefficient here in the query language, too, but we did it to\nkeep it simple. Let's break for questions.\n\n\n\n\n\nAUDIENCE: When you started this section, you emphasized how powerful our APPLY EVAL\nmodel was that we could use it for any language. And then you say we're going to have this\n\nlanguage which is so different. It turns out that this language, as you just pointed out, is\nvery much the same. I'm wondering if you're arguing that all languages end up coming\n\ndown to this you can apply a rule or apply a procedure or some kind of apply?\n\n\n\n\nPROFESSOR: I would say that pretty much any language where you really are building up\n\nthese means of combination and giving them simpler names and you're saying anything of\nthe sort, like here's a general kind of expression, likehow to square something, almost\n\nanything that you would call a procedure. If that's got to have parts, you have to unwind\nthose parts. You have to have some kind of organization which says when I look at the\n\nabstract variables or tags or whatever you want to call them that might stand for particular\nthings, you have to keep track of that, and that's going to be something like an\n\nenvironment. And then if you say this part can have parts which I have to unwind, you've\n\ngot to have something like this cycle.\nAnd lots and lots of languages have that character when they sort of get put together in this\n\nway. This language again really is different because there's nothing like procedures on the\noutside. When you go below the surface and you see the implementatio n, of course, it starts\n\nlooking the same. But from the outside, it's a very different world view. You're not\ncomputing functions of inputs.\n\n\n\n\n\nAUDIENCE: You mentioned earlier that when you build all of these rules in pattern matcher\nand with the delayed action of streams, you really have no way to know in what order\n\nthings are evaluated.\n\n\n\n\nPROFESSOR: Right.\n\n\n\n\nAUDIENCE: And that would indicate then that you should only express declarative\n\nknowledge that's true for all-time, no-time sequence built into it. Otherwise, these things\n\nget all--\n\n\n\n\nPROFESSOR: Yes. Yes. The question is this really is set up for doing declarative knowledge,\nand as I presented it-- and I'll show you some of the ugly warts under this after the break.\n\nAs I presented it, it's just doing logic. And in principle, if it welogic, it wouldn't matter\n\nwhat order it's getting done. And it's quite true when you start doing things where you have\nside effects like adding things to the database and taking things out, and we'll see some\n\nothers, you use that kind of control.\n\n\n\n\nSo, for example, contrasting with Prolog. Say Prolog has various features where you really\n\nexploit the order of evaluation. And people write Prolog programs that way. That turns out\nto be very complicated in Prolog, although if you're an expert Prolog programmer, you can\n\ndo it. However, here I don't think you can do it at all. It's very complicated because you\nreally are giving up control over any prearranged order of trying things.\n\n\n\n\n\nAUDIENCE: Now, that would indicate then that you have a functional mapping. And when\nyou started out this lecture, you said that we express the declarative knowledge which is a\n\nrelation, and we don't talk about the inputs and the outputs.\n\n\n\n\nPROFESSOR: Well, there's a pun on functional, right? There's function in the sense of no\nside effects and not depending on what order is going on. And then there's functional in the\nsense of mathematical function, which means input and output. And it's just that pun that\n\nyou're making, I think.\n\n\n\n\nAUDIENCE: I'm a little unclear on what you're doing with these two statements, the two\n\nboss statements. Is the first one building up the database and the second one a query or --\n\n\n\n\nPROFESSOR: OK, I'm sorry. What I meant here, if I type something like this in as a query --\nI should have given an example way at the very beginning. If I type in job, Ben Bitdiddle,\n\ncomputer wizard, what the processing will do is if it finds a match, it'll find a match to that\n\nexact thing, and it'll type out a job, Ben Bitdiddle, computer wizard. If it doesn't find a\nmatch, it won't find anything.\n\n\n\n\nSo what I should have said is the way you use the query language to check whether\n\nsomething is true, remember, that's one of the things you want to do in logic programming,\n\nis you type in your query and either that comes out or it doesn't. So what I was trying to\nillustrate here, I wanted to start with a very simple example before talking about unifiers.\n\nSo what I should have said, if I just wanted to check whether this is true, I could type that\nin and see if anything came out\n\n\n\n\n\nAUDIENCE: And then the second one--\n\n\n\n\nPROFESSOR: The second one would be a real query.\n\n\n\n\nAUDIENCE: A real query, yeah.\n\n\n\n\n\nPROFESSOR: What would come out, see, it would go in here say with FOO, and in would go\nframe that says z is bound to who and d is bound to computer. And this will pass through,\n\nand then by the time it got out of here, who would pick up a binding.\n\n\n\n\nAUDIENCE: On the unifying thing there, I still am not sure what happens with who and z. If\nthe unifying-- the rule here says-- OK, so you say that you can't make question mark equal\n\nto question mark who.\nPROFESSOR: Right. That's what the matcher can't do. But what this will mean to a unifier is\n\nthat there's an environment with three variables. d here is computer. z is whatever who is.\nSo if later on in the matcher routine it said, for example, who has to be 3, then when I\n\nlooked up in the dictionary, it will say, oh, z is 3 because it's the same as who. And that's in\nsome sense the only thing you need to do to extend the unifier to a matcher.\n\n\n\n\n\nAUDIENCE: OK, because it looked like when you were telling how to unify it, it looked like\nyou would put the things together in such a way that you'd actually solve and have a value\n\nfor both of them. And what it looks like now is that you're actually pass a dicti onary with\ntwo variables and the variables are linked.\n\n\n\n\n\nPROFESSOR: Right. It only looks like you're solving for both of them because you're sort of\nlooking at the whole solution at once. If you sort of watch the thing getting built up\n\nrecursively, it's merely this.\n\n\n\n\nAUDIENCE: OK, so you do pass off that dictionary with two variables?\n\n\n\n\nPROFESSOR: That's right.\n\n\n\n\n\nAUDIENCE: And link?\n\n\n\n\nPROFESSOR: Right. It just looks like an ordinary dictionary.\n\n\n\n\nAUDIENCE: When you're talking about the unifier, is it that there are some cases or some\n\npoints that you are not able to use by them?\n\n\n\n\nPROFESSOR: Right.\n\n\n\n\n\nAUDIENCE: Can you just by building the rules or writing the forms know in advance if you\nare going to be able to solve to get the unification or not? Can you add some properties\n\neither to the rules itself or to the formula that you're writing so that you avoid the problem\nof not finding unification?\nPROFESSOR: I mean, you can agree, I think, to write in a fairly restricted way where you\nwon't run into it. See, because what you're getting -- see, the place where you get into\n\nproblems is when you-- well, again, you're trying to match things like that against things\nwhere these have structure, where a, y, b, y something. So this is the kind of place where\n\nyou're going to get into trouble.\n\n\n\n\nAUDIENCE: So you can do that syntactically?\n\n\n\n\n\nPROFESSOR: So you can kind of watch your rules in the kinds of things that your writing.\n\n\n\n\nAUDIENCE: So that's the problem that the builder of the database has to be concerned?\n\n\n\n\nPROFESSOR: That's a problem. It's a problem either-- not quite the builder of the database,\n\nthe person who is expressing the rules, or the builder of the database. What the unifier\nactually does is you can check at the next level down when you actually get to the unifier\n\nand you'll see in the code where it looks up in the dictionary. If it sort of says what does y\n\nhave to be? Oh, does y have to be something that contains a y as its expression? At that\npoint, the unifier and say, oh my God, I'm trying to solve a fixed-point equation. I'll give it\n\nup here.\n\n\n\n\nAUDIENCE: You make the distinction between the rules in the database. Are the rules added\n\nto the database?\n\n\n\n\nPROFESSOR: Yes. Yes, I should have said that. One way to think about rules is that they're\njust other things in the database. So if you want to check the things that have to be\n\nchecked in the database, they're kind of virtual facts that are in the database .\n\n\n\n\nAUDIENCE: But in that explanation, you made the differentiation between database and the\n\nrules itself.\n\n\n\n\nPROFESSOR: Yeah, I probably should not have done that. The only reason to do that is in\n\nterms of the implementation. When you look at the implementation, there's a part which\nsays check either primitive assertions in the database or check rules. And then the real\nreason why you can't tell what order things are going to come out in and is that the rules\n\ndatabase and the data database sort of get merged in a kind of delayed evaluation way.\nAnd so that's what makes the order very complicated. OK, let's break.\n\n\n\n\n\nWe've just seen how the logic language works and how rules work. Now, let's turn to a\nmore profound question.\n\n\n\n\nWhat do these things mean? That brings us to the subtlest, most devious part of this whole\n\nquery language business, and that is that it's not quite what it seems to be. AND and OR\n\nand NOT and the logical implication of rules are not really the AND and OR and NOT and\nlogical implication of logic. Let me give you an example of that.\n\n\n\n\nCertainly, if we have two things in logic, it ought to be the case that AND of P and Q is the\n\nsame as AND of Q and P and that OR of P and Q is the same as OR of Q and P. But let's look\n\nhere. Here's an example. Let's talk about somebody outranking somebody else in our little\ndatabase organization.\n\n\n\n\nWe'll say s is outranked by b or if either the supervisor of this is b or there's some middle\n\nmanager here, that supervisor of s is m, and m is outranked by b. So there's one way to\n\ndefine rule outranked by. Or we can write exactly the same thing, except at the bottom\nhere, we reversed the order of these two clauses. And certainly if this were logic, those\n\nought to mean the same thing.\n\n\n\n\nHowever, in our particular implementation, if you say something like who's outranked by\n\nBen Bitdiddle, what you'll find is that this rule will work perfectly well and generate answers,\nwhereas this rule will go into an infinite loop. And the reason for that is that this will come in\n\nand say, oh, who's outranked by Ben Bitdiddle? Find an s which is outranked by b, where b\nis Ben Bitdiddle, which is going to happen in it a subproblem. Oh gee, find an m such as m\n\nis outranked by Ben Bitdiddle with no restrictions on m.\n\n\n\n\nSo this will say in order to solve this problem, I solve exactly the same problem. And then\n\nafter I've solved that, I'll check for a supervisory relationship. Whereas this one won't get\ninto that, because before it tries to find this outranked by, it'll already have had a re striction\n\non m here. So these two things which ought to mean the same, in fact, one goes into an\ninfinite loop. One does not.\nThat's a very extreme case of a general thing that you'll find in logic programming that if\n\nyou start changing the order of the things in the ANDs or ORs, you'll find tremendous\ndifferences in efficiency. And we just saw an infinitely big difference in efficiency and an\n\ninfinite loop.\n\n\n\n\nAnd there are similar things having to do with the order in which you enter rules. The order\n\nin which it happens to look at rules in the database may vastly change the efficiency with\nwhich it gets out answers or, in fact, send it into an infinite loop for some orderings. And\n\nthis whole thing has to do with the fact that you're checking these rules i n some order. And\nsome rules may lead to really long paths of implication. Others might not. And you don't\n\nknow a priori which ones are good and which ones are bad.\n\n\n\n\nAnd there's a whole bunch of research having to do with that, mostly having to do with\n\nthinking about making parallel implementations of logic programming languages. And in\nsome sense, what you'd like to do is check all rules in parallel and whichever ones get\n\nanswers, you bubble them up. And if some go down infinite deductive changed, well, y ou\njust-- you know, memory is cheap and processors are cheap, and you just let them buzz for\n\nas for as long as you want.\n\n\n\n\nThere's a deeper problem, though, in comparing this logic language to real logic. The\n\nexample I just showed you, it went into an infinite loop maybe, but at least it didn't give the\nwrong answer. There's an actual deeper problem when we start comparing, seriously\n\ncomparing this logic language with real classical logic. So let's sort of review real classical\n\nlogic.\n\n\n\n\nAll humans are mortal. That's pretty classical logic. Then maybe we'll continue in the very\nbest classical tradition. We'll say all-- let's make it really classical. All Greeks are human,\n\nwhich has the syllogism that Socrates is a Greek. And then what do you write here? I thi nk\n\nthree dots, classical logic. Therefore, then the syllogism, Socrates is mortal. So there's\nsome real honest classical logic.\n\n\n\n\nLet's compare that with our classical logic database. So here's a classical logic database.\n\nSocrates is a Greek. Plato is a Greek. Zeus is a Greek, and Zeus is a god. And all humans\nare mortal. To show that something is mortal, it's enough to show that it's human. All\n\nhumans are fallible. And all Greeks are humans is not quite right. This says that all Greeks\n\nwho are not gods are human. So to show something's human, it's enough to show it's a\nGreek and not a god. And the address of any Greek god is Mount Olympus. So there's a\n\nlittle classical logic database. And indeed, that would work fairly well. If we type that in and\nsay is Socrates mortal or Socrates fallible or mortal? It'll say yes. Is Plato mortal and\nfallible. It'll say yes. If we say is Zeus mortal? It won't find anything. And it'll work perfectly\n\nwell.\n\n\n\n\nHowever, suppose we want to extend this. Let's define what it means for someone to be a\n\nperfect being. Let's say rule: a perfect being. And I think this is right. If you're up on your\nmedieval scholastic philosophy, I believe that perfect beings are ones who were neither\n\nmortal nor fallible. AND NOT mortal x, NOT fallible x.\n\n\n\n\nSo we'll define this system to teach it what a perfect being is. And now what we're going to\n\ndo is he ask for the address of all the perfect beings. AND the address of x is y and x is\nperfect. And so what we're generating here is the world's most exclusive mailing list. For the\n\naddress of all the perfect things, we might have typed this in. Or we might type in this. We'll\nsay AND perfect of x and the address of x is y.\n\n\n\n\n\nWell, suppose we type all that in and we try this query. This query is going to give us an\nanswer. This query will say, yeah, Mount Olympus. This query, in fact, is going to give us\n\nnothing. It will say no addresses of perfect beings.\n\n\n\n\nNow, why is that? Why is there a difference? This is not an infinite loop question. This is a\n\ndifferent answer question. The reason is that if you remember the implementation of NOT,\nNOT acted as a filter. NOT said I'm going to take some possible dictionaries, some possible\n\nframes, some possible answers, and filter out the ones that happened to satisfy some\ncondition, and that's how I implement NOT. If you think about what's going on here, I'll\n\nbuild this query box where the output of an address piece gets fed into a perfect piece.\nWhat will happen is the address piece will set up some things of everyone whose address I\n\nknow. Those will get filtered by the NOTs inside perfect here. So it will throw out the ones\nwhich happened to be either mortal or fallible.\n\n\n\n\n\nIn the other order what happens is I set this up, started up with an empty frame. The\nperfect in here doesn't find anything for the NOTs to filter, so nothing comes out here at all.\n\nAnd there's sort of nothing there that gets fed into the address thing. So here, I don't get\nan answer. And again, the reason for that is NOT isn't generating anything. NOT's only\n\nthrowing out things. And if I never started up with anything, there's nothing for it to throw\nout. So out of this thing, I get the wrong answer.\n\n\n\n\n\nHow can you fix that? Well, there are ways to fix that. So you might say, well, that's sort of\nstupid. Why are you just doing all your NOT stuff at the beginning? The right way to\nimplement NOT is to realize that when you have conditions like NOT, you should generate\n\nall your answers first, and then with each of these dictionaries pass along until at the very\nend I'll do filtering. And there are implementations of logic languages that work like that\n\nthat solve this particular problem.\n\n\n\n\nHowever, there's a more profound problem, which is which one of these is the right answer?\n\nIs it Mount Olympus or is it nothing? So you might say it's Mount Olympus, because after\nall, Zeus is in that database, and Zeus was neither mortal nor fallible. So you might say\n\nZeus wants to satisfy NOT mortal Zeus or NOT fallible Zeus. But let's actually look at that\ndatabase. Let's look at it.\n\n\n\n\n\nThere's no way-- how does it know that Zeus is not fallible? There's nothing in there about\nthat. What's in there is that humans are fallible. How does it know that Zeus is not mortal?\n\nThere's nothing in there about that. It just said I don't have any rule, which -- the only way I\ncan deduce something's mortal is if it's human, and that's all it really knows about mor tal.\n\nAnd in fact, if you remember your classical mythology, you know that the Greek gods were\nnot mortal but fallible. So the answer is not in the rules there.\n\n\n\n\n\nSee, why does it deduce that? See, Socrates would certainly not have made this error of\nlogic. What NOT needs in this language is not NOT. It's not the NOT of logic. What NOT\n\nneeds in this language is not deducible from things in the database as opposed to not true.\nThat's a very big difference. Subtle, but big.\n\n\n\n\n\nSo, in fact, this is perfectly happy to say not anything that it doesn't know about. So if you\nask it is it not true that Zeus likes chocolate ice cream? It will say sure, it's not true. Or\n\nanything else or anything it doesn't know about. NOT means not deducible from the things\nyou've told me. In a world where you're identifying not deducible with, in fact, not true, this\n\nis called the closed world assumption.\n\n\n\n\nThe closed world assumption. Anything that I cannot deduce from what I know is not true,\n\nright? If I don't know anything about x, the x isn't true. That's very dangerous. From a\nlogical point of view, first of all, it doesn't really makes sense. Because if I don't know\n\nanything about x, I'm willing to say not x. But am I willing to say not not x? Well, sure, I\ndon't know anything about that either maybe. So not not x is not necessarily the same as x\n\nand so on and so on and so on, so there's some sort of funny bias in there. So that's sort of\n\nfunny.\nThe second thing, if you start building up real reasoning programs based on this, thi nk how\n\ndangerous that is. You're saying I know I'm in a position to deduce everything true that's\nrelevant to this problem. I'm reasoning, and built into my reasoning mechanism is the\n\nassumption that anything that I don't know can't possibly be relevant to this problem, right?\n\n\n\n\nThere are a lot of big organizations that work like that, right? Most corporate marketing\n\ndivisions work like that. You know the consequences to that. So it's very dangerous to start\nreally typing in these big logical implication sy stems and going on what they say, because\n\nthey have this really limiting assumption built in. So you have to be very, very careful about\nthat. And that's a deep problem. That's not a problem about we can make a little bit\n\ncleverer implementation and do the filters and organize the infinite loops to make them go\naway. It's a different kind of problem. It's a different semantics.\n\n\n\n\n\nSo I think to wrap this up, it's fair to say that logic programming I think is a terrifically\nexciting idea, the idea that you can bridge this gap from the imperative to the declarative,\n\nthat you can start talking about relations and really get tremendous power by going above\nthe abstraction of what's my input and what's my output. And linked to logic, the problem is\n\nit's a goal that I think has yet to be realized.\n\n\n\n\nAnd probably one of the very most interesting research questions going on now in\n\nlanguages is how do you somehow make a real logic language? And secondly, how do you\nbridge the gap from this world of logic and relations to the worlds of more traditional\n\nlanguages and somehow combine the power of both. OK, let's break.\n\n\n\n\nAUDIENCE: Couldn't you solve that last problem by having the extra rules that imply it? The\n\nproblem here is you have the definition of something, but you don't have the definition of its\nopposite. If you include in the database something that says something implies mortal x,\n\nsomething else implies not mortal x, haven't you basically solved the problem?\n\n\n\n\nPROFESSOR: But the issue is do you put a finite number of those in?\n\n\n\n\n\nAUDIENCE: If things are specified always in pairs --\n\n\n\n\nPROFESSOR: But the impression is then what do you do about deduction? You can't specify\nNOTs. But the problem is, in a big system, it turns out that might not be a finite number of\nthings. There are also sort of two issues. Partly it might not be finite. Partly it might be\n\nthat's not what you want.\n\n\n\n\nSo a good example would be suppose I want to do connectivity. I want a reason about\n\nconnectivity. And I'm going to tell you there's four things: a and b and c and d. And I'll tell\nyou a is connected to b and c's connected to d. And now I'll tell you is a connected to d?\n\nThat's the question.\n\n\n\n\nThere's an example where I would like something like the closed world assumption. That's a\n\ntiny toy, but a lot of times, I want to be able to say something like anything that I haven't\ntold you, assume is not true. So it's not as simple as you only want to put in explicit NOTs\n\nall over the place. It's that sometimes it really isn't clear what you even want. That having\nto specify both everything and not everything is too precise, and then you get down into\n\nproblems there. But there are a lot of approaches that explicitly put in NOTs and reason\nbased on that. So it's a very good idea. It's just that then it starts becoming a little\n\ncumbersome in the very large problems you'd like to use.\n\n\n\n\nAUDIENCE: I'm not sure how directly related to the argument this is, but one of your points\n\nwas that one of the dangers of the closed rule is you never really know all the things that\nare there. You never really know all the parts to it. Isn't that a major problem with any\n\nprogramming? I always write programs where I assume that I've got all the cases, and so I\ncheck for them all or whatever, and somewhere down the road, I find out that I didn't check\n\nfor one of them.\n\n\n\n\nPROFESSOR: Well, sure, it's true. But the problem here is it's that assumptio n which is the\n\nthing that you're making if you believe you're identifying this with logic. So you're quite\nright. It's a situation you're never in. The problem is if you're starting to believe that what\n\nthis is doing is logic and you look at the rules you write down and say what can I deduce\n\nfrom them, you have to be very careful to remember that NOT means something else. And\nit means something else based on an assumption which is probably not true.\n\n\n\n\nAUDIENCE: Do I understand you correctly that you cannot fix this problem without killing off\n\nall possibilities of inference through altering NOT?\n\n\n\n\nPROFESSOR: No, that's not quite right. There are other-- there are ways to do logic with\n\nreal NOTs. There are actually ways to do that. But they're very inefficientas far as anybody\nknows. And they're much more-- the, quote, inference in here is built into this unifier and\nthis pattern matching unification algorithm. There are ways to automate real logical\n\nreasoning. But it's not based on that, and logic programming languages don't tend to do\nthat because it's very inefficient as far as anybody knows. All right, thank you.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed this material in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec9a.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 9A: Register Machines\n\n\n\n[MUSIC PLAYING - \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\nPROFESSOR: Well, up 'til now, I suppose, we've been learning about a lot of techniques for\n\norganizing big programs, symbolic manipulation a bit, some of the technology that you use\nfor establishing languages, one in terms of another, which is used for organizing very large\n\nprograms. In fact, the nicest programs I know look more like a pile of languages than like a\ndecomposition of a problem into parts. Well, I suppose at this point, there are still,\n\nhowever, a few mysteries about how this sort of stuff works.\n\n\n\n\nAnd so what we'd like to do now is diverge from the plan of telling you how to organize big\n\nprograms, and rather tell you something about the mechanisms by which these things can\nbe made to work. The main reason for this is demystification, if you will, that we have a lot\n\nof mysteries left, like exactly how it is the case that a program is controlled, how a\ncomputer knows what the next thing to do is, or something like that. And what I'd like to do\n\nnow is make that clear to you, that even if you've never played with a physical computer\n\nbefore, the mechanism is really very simple, and that you can understand it completely with\nno trouble.\n\n\n\n\nSo I'd like to start by imagining that we-- well, the way we're going to do this, by the way,\n\nis we're going to take some very simple Lisp programs, very simple Lisp programs, and\ntransform them into hardware. I'm not going to worry about some intermediate step of\n\ngoing through some existing computer machine language and then showing you how that\n\ncomputer works, because that's not as illuminating. So what I'm really going to show you is\nhow a piece of machinery can be built to do a job that you have written down as a program.\n\nThat program is, in fact, a description of a machine.\n\n\n\n\nWe're going to start with a very simple program, proceed to show you some simple\n\nmechanisms, proceed to a few more complicated programs, and then later show you a not\nvery complicated program, how the evaluator transformsinto a piece of hardware. And of\n\ncourse at that point, you have made the universal transition and can execute any program\nimaginable with a piece of well- defined hardware.\n\n\n\n\n\nWell, let's start up now, give you a real concrete feeling for this sort of thing.Let's start with\na very simple program. Here's Euclid's algorithm. It's actually a little bit more modern than\nEuclid's algorithm. Euclid's algorithm for computing the greatest common divisor of two\n\nnumbers was invented 350 BC, I think. It's the oldest known algorithm.\n\n\n\n\nBut here we're going to talk about GCD of A and B, the Greatest Common Divisor or two\n\nnumbers, A and B. And the algorithm is extremely simple. If B is 0, then the result is going\nto be A. Otherwise, the result is the GCD of B and the remainder when A is divided by B.\n\n\n\n\nSo this we have here is a very simple iterative process. This a simple recursive procedure,\n\nrecursively defined procedure, recursive definition, which yields an iterative process. And\n\nthe way it works is that every step, it determines whether B was zero. And if B is 0, we got\nthe answer in A. Otherwise, we make another step where A is the old B, and B is the\n\nremainder of the old A divided by the old B. Very simple.\n\n\n\n\nNow this, I've already told you some of the mechanism by jus t saying it that way. I set it in\n\ntime. I said there are certain steps, and that, in fact, one of the things you can see here is\nthat one of the reasons why this is iterative is nothing is needed of the last step to get the\n\nanswer. All of the information that's needed to run this algorithm is in A and B. It has two\nwell-defined state variables.\n\n\n\n\n\nSo I'm going to define a machine for you that can compute you GCDs. Now let's see. Every\ncomputer that's ever been made that's a single-process computer, as opposed to a\n\nmultiprocessor of some sort, is made according to the same plan. The plan is the computer\nhas two parts, a part called the datapaths, and a part called the controller.\n\n\n\n\n\nThe datapaths correspond to a calculator that you might have. It contains certa in registers\nthat remember things, and you've all used calculators. It has some buttons on it and some\n\nlights. And so by pushing the various buttons, you can cause operations to happen inside\nthere among the registers, and some of the results to be displayed.\n\n\n\n\n\nThat's completely mechanical. You could imagine that box has no intelligence in it. Now it\nmight be very impressive that it can produce the sine of a number, but that at least is\n\napparently possibly mechanical. At least, I could open that up in the same way I'm about to\nopen GCD.\n\n\n\n\nSo this may have a whole computer inside of it, but that's not interesting. Addition is\n\ncertainly simple. That can be done without any further mechanism.\nNow also, if we were to look at the other half, the controller, that's a part that's dumb, too.\nIt pushes the buttons. It pushes them according to the sequence, which is written down on\n\na piece of paper, and observes the lights.\n\n\n\n\nAnd every so often, it comes to a place in a sequence that says, if light A is on, do this\n\nsequence. Otherwise, do that sequence. And thereby, there's no complexity there either.\nWell, let's just draw that and see what we feel about that.\n\n\n\n\n\nSo for computing GCDs, what I want you to think about is that there are these registers. A\nregister is a place where I store a number, in this case. And this one's called a. And then\n\nthere's another one for storing b.\n\n\n\n\nNow we have to see what things we can do with these registers, and they're not entirely\n\nobvious what you can do with them. Well, we have to see what things we need to do with\nthem. We're looking at the problem we're trying to solve.\n\n\n\n\n\nOne of the important things for designing a computer, which I think most designers don't\ndo, is you study the problem you want to solve and then use what you learn from studying\n\nthe problem you want to solve to put in the mechanisms needed to solve it in the computer\nyou're building, no more no less. Now it may be that the problem you're trying to sol ve is\n\neverybody's problem, in which case you have to build in a universal interpreter of some\nlanguage. But you shouldn't put any more in than required to build the universal interpreter\n\nof some language. We'll worry about that in a second.\n\n\n\n\nOK, going back to here, let's see. What do we have to be able to do? Well, somehow, we\n\nhave to be able to get B into A. We have to be able to get the old value of B into the value\nof A. So we have to have some path by which stuff can flow, whatever this information is,\n\nfrom b to a. I'm going to draw that with by an arrow saying that it is possible to move the\ncontents of b into a, replacing the value of a. And there's a little button here which you push\n\nwhich allows that to happen. That's what the little x is here.\n\n\n\n\nNow it's also the case that I have to be able to compute the remainder of a and b. Now that\n\nmay be a complicated mess. On the other hand, I'm going to make it a small box. If we\nhave to, we may open up that box and look inside and see what it is.\nSo here, I'm going to have a little box, which I'm going to draw this way, which we'll call the\n\nremainder. And it's going to take in a. That's going to take in b. And it's going to put out\nsomething, the remainder of a divided by b.\n\n\n\n\n\nAnother thing we have to see here is that we have to be able to test whether b is equal to\n0. Well, that means somebody's got to be looking at-- a thing that's looking at the value of\n\nb. I have a light bulb here which lights up if b equals 0. That's its job.\n\n\n\n\nAnd finally, I suppose, because of the fact that we want the new value of a to be the old\n\nvalue of b, and simultaneously the new value of b to be something I've done with a, and if I\nplan to make my machine such that everything happens one at a time, one motion at a\n\ntime, and I can't put two numbers in a register, then I have to have another place to put\none while I'm interchanging. OK? I can't interchange the two things in my hands, unless I\n\neither put two in one hand and then pull it back the other way, or unless I put one down,\npick it up, and put the other one, like that, unless I'm a juggler, which I'm not, as you can\n\nsee, in which case I have a possibility of timing errors. In fact, much of the type of\ncomputer design people do involves timing errors, of some potential timing errors, which I\n\ndon't much like.\n\n\n\n\nSo for that reason, I have to have a place to put the second one of them down. So I have a\n\nplace called t, which is a register just for temporary, t, with a button on it. And then I'll take\nthe result of that, since I have to take that and put into b, over here, we'll take the result of\n\nthat and go like this, and a button here. So that's the datapaths of a GCD machine.\n\n\n\n\nNow what's the controller? Controller's a very simple thing, too. The machine has a state.\n\n\n\n\n\nThe way I like to visualize that is that I've got a maze. And the maze has a bunch of places\nconnected by directed arrows. And what I have is a marble, which represents the state of\n\nthe controller. The marble rolls around in the maze. Of course, this analogy breaksdown for\nenergy reasons. I sometimes have to pump the marble up to the top, because it's going to\n\notherwise be a perpetual motion machine. But not worrying about that, this is not a physical\nanalogy.\n\n\n\n\n\nThis marble rolls around. And every time it rolls around certain bumpers, like in a pinball\nmachine, it pushes one of these buttons. And every so often, it comes to a place, which is a\n\ndivision, where it has to make a choice. And there's a flap, which is c ontrolled by this. So\nthat's a really mechanical way of thinking about it.\nOf course, controllers these days, are not built that way in real computers. They're built with\na little bit of ROM and a state register. But there was a time, like the DEC PDP-6, where\n\nthat's how you built the controller of a machine. There was a bit that ran around the delay\nline, and it triggered things as it went by. And it would come back to the beginning and get\n\nfed round again.\n\n\n\n\nAnd of course, there were all sorts of great bugs you could have like two bits going around,\n\ntwo marbles. And then the machine has lost its marbles. That happens, too. Oh, well.\n\n\n\n\nSo anyway, for this machine, what I have to do is the following. I'm going to start my maze\n\nhere. And the first thing I've got to do, in a notation which many of you are familiar with, is\nb equal to zero, a test. And there's a possibility, either yes, in which case I'm done.\n\nOtherwise, if no, then I'm going have to roll over some bumpers.\n\n\n\n\nI'm going to do it in the following order. I want to do this interchange game. Now first, since\n\nI need both a and b, but then the first-- and this is not necessary-- I want to collect this.\nThis is the thing that's going to go into b. So I'm going to say, take this, which depends\n\nupon both a and b, and put the remainder into here. So I'm going to push this button first.\nThen, I'm going to transfer b to a, push that button, and then I transfer the temporary into\n\nb, push that button. So a very sequential machine, it's very inefficient. But th at's fine right\n\nnow.\n\n\n\n\nWe're going to name the buttons, t gets remainder. a gets b. And b gets t. And then I'm\ngoing to go around here and it's to go back to start.\n\n\n\n\n\nAnd if you look, what are we seeing here? We're seeing the various-- what I really have is\nsome sort of mechanical connection, where t gets r controls this thing. And I have here that\n\na gets b controls this fellow over here, and this fellow over here.\n\n\n\n\nBoy, that's absolutely pessimal, the inverse of optimal. Every line heads across every othe    r\n\nline the way I drew it. I suppose this goes here, b gets t.\n\n\n\n\nNow I'd like to run this machine. But before I run the machine, I want to write down a\n\ndescription of this controller, just so you can see that these things, of course, as usual, can\nbe written down in some nice language, so that we don't have to always draw these\n\ndiagrams. One of the problems with diagrams is that they take up a lot of space. And for a\nmachine this small, it takes two blackboards. For a machine that's the evaluator machine, I\n\nhave trouble putting it into this room, even though it isn't very big. So I'm going to make a\nlittle language for this that's just a description of that, saying define a machine we'll call\n\nGCD.\n\n\n\n\nOf course, once we have something like this, we have a simulator for it. And the reason why\n\nwe want to build a language in this form, is because all of a sudden we can manipulate\nthese expressions that I'm writing down. And then of course I can write things that can\n\nalgebraically manipulate these things, simulate them, all that sort of things that I might\nwant to do, perhaps transform them as a layout, who knows. Once I have a nice\n\nrepresentation of registers, it has certain registers, which we can call A, B, and T. And\n\nthere's a controller.\n\n\n\n\nActually, a better language, which would be more explicit, would be one which named every\nbutton also and said what it did. Like, this button causes the contents of T to go to the\n\ncontents of B. Well I don't want to do that, because it's actually harder to read to do that,\n\nand it takes up more space. So I'm going to have that in the instructions written in the\ncontroller.\n\n\n\n\nIt's going to be implicit what the operations are. They can be deduced by reading these and\n\ncollecting together all the different things that can be done. Well, let's just look at what\n\nthese things are. There's a little loop that we go around which says branch, this is the\nrepresentation of the little flap that decides which way you go here, if 0 fetch of B, the\n\ncontents of B, and if the contents of B is 0, then go to a place called done.\n\n\n\n\nNow, one thing you're seeing here, this looks very much like a traditional computer\n\nlanguage. And what you're seeing here is things like labels that represent places in a\nsequence written down as a sequence. The reason why they're needed is because over\n\nhere, I've written something with loops.\n\n\n\n\nBut if I'm writing English text, or something like that, it's hard to refer to a place. I don't\nhave arrows. Arrows are represented by giving names to the places where the arrows\n\nterminate, and then referring to them by those names. Now this is just an encoding. There's\n\nnothing magical about things like that.\nNext thing we're going to do is we're going to say, how do we do T gets R? Oh, that's easy\n\nenough, assign. We assign to T the remainder. Assign is the name of the button. That's the\nbutton-pusher. Assign to T the remainder, and here's the representation ofthe operation,\n\nwhen we divide the fetch of A by the fetch of B.\n\n\n\n\nAnd we're also going to assign to A the fetch of B, assign to B the result of getting the\n\ncontents of T. And now I have to refer to the beginning here. I see, why don't I call that\nloop like I have here? So that's that reference to that arrow. And when we're done, we're\n\ndone. We go to here, which is the end of the thing.\n\n\n\n\nSo here's just a written representation of this fragment of machinery that we've drawn here.\n\nNow the next thing I'd like to do is run this. I want us to feel it running. Never done this\nbefore, you got to do it once.\n\n\n\n\n\nSo let's take a particular problem. Suppose we want to compute the GCD of a equals 30 and\nb equals 42. I have no idea what that is right now. But a 30 and b is 42. So that's how I\n\nstart this thing up.\n\n\n\n\nWell, what's the first thing I do? I say is B equal to 0, no. Then assign to T the remainder of\n\nthe fetch of A and the fetch of B. Well the remainder of 30 when divided by 42 is itself 30.\nPush that button.\n\n\n\n\nNow the marble has rolled to here. A gets B. That pushes this button. So 42 moves into\n\nhere.\n\n\n\n\nB gets C. Push that button. The 30 goes here. Let met just interchange them.\n\n\n\n\n\nNow let's see, go back to the beginning. B 0, no. T gets the remainder. I suppose the\nremainder when dividing 42 by 30 is 12. I push that one.\n\n\n\n\nNext thing I do is allow the 30 to go to here, push this one, allow the 12 to go to here. Go\n\naround this thing. Is that done? No. How about-- so now I have to find out the remainder of\n\n30 divided by 12. And I believe that's 6. So 6 goes here on this button push. Then the next\nthing I push is this one, which the 12 goes into here.\nThen I push this button. The 6 gets into here. Is 6 equal to 0? No. OK.\n\n\n\n\nSo then at that point, the next thing to do is divide it. Ooh, this has got a remainder of 0.\n\nLooks like we're almost done.\n\n\n\n\nMove the 6 over here next. 0 over here. Is the answer 0? Yes. B is 0, therefore the answer\n\nis in A.\n\n\n\n\nThe answer is 6. And indeed that's right, because if we look at the original problem, what\nwe have is 30 is 2 times 3 times 5, and 42 is 2 times 3 times 7. So the greatest common\n\ndivisor is 2 times 3, which is 6.\n\n\n\n\nNow normally, we write one other little line here, just to make it a little bit clearer, which is\n\nthat we leave in a connection saying that this light is the guy that that flap looks at. Of\ncourse, any real machine has a lot more complicated things in it than what I've just shown\n\nyou. Let's look for a second at the first still store.\n\n\n\n\nWow. Well you see, for example, one thing we might want to do is worry about the\n\noperations that are of IO form. And we may have to collect something from the outside. So\na state machine that we might have, the controller may have to, for example, get a value\n\nfrom something and put register a to load it up. I have to master load up register b with\n\nanother value.\n\n\n\n\nAnd then later, when I'm done, I might want to print the answer out. And of course, that\nmight be either simple or complicated. I'm writing, assuming print is very simple, and read\n\nis very simple. But in fact, in the real world, those are very complicated operations, usually\n\nmuch, much larger and more complicated than the thing you're doing as your problem\nyou're trying to solve.\n\n\n\n\nOn the other hand, I can remember a time when, I remember using IBM 7090 computer of\n\nsorts, where things like read and write of a single object, a single number, a number, is a\nprimitive operation of the IO controller. OK?\nAnd so we have that kind of thing in there. And in such a machine, well, what are we really\n\ndoing? We're just saying that there's a source over here called \"read,\" which is an operation\nwhich always has a value. We have to think about this as always having a value which can\n\nbe gated into either register a or b. And print is some sort of thing which when you gate it\nappropriately, when you push the button on it, will cause a print of the value that's currently\n\nin register a. Nothing very exciting.\n\n\n\n\nSo that's one sort of thing you might want to have. But these are also other things that are\n\na little bit worrisome. Like I've used here some complicated mechanisms.\n\n\n\n\nWhat you see here is remainder. What is that? That may not be so obvious how to compute.\n\nIt may be something which when you open it up, you get a whole machine. OK? In fact,\nthat's true.\n\n\n\n\n\nFor example, if I write down the program for remainder, the simplest program for it is by\nrepeated subtraction. Because of course, division can be done by repeated subtraction of\n\nnumbers, of integers. So the remainder of N divided by D is nothing more than if N is less\nthan D, then the result is N. Otherwise, it's the remainder when we subtract D from N with\n\nrespect to D, when divided by D. Gee, this looks just like the GCD program.\n\n\n\n\nOf course, it's not a very nice way to do remainders. You'd really want to use something like\n\nbinary notation and shift and things like that in a practical computer. But the point of that is\nthat if I open this thing up, I might find inside of it a computer.\n\n\n\n\n\nOh, we know how to do that. We just made one. And it could be another thing just like this.\n\n\n\n\nOn the other hand, we might want to make a more efficient or better-structured machine,\nor maybe make use of some of the registers more than once, or some horrible mess like\n\nthat that hardware designers like to do, and for very good reasons. So for example, here's a\n\nmachine that you see, which you're not supposed to be able to read. It's a little bit\ncomplicated. But what it is is the integration of the remainder into the GCD machine. A nd it\n\ntakes, in fact, no more registers. There are three registers in the datapaths. OK?\n\n\n\n\nBut now there's a subtractor. There are two things that are tested. Is b equal to 0, or is t\nless than b?\nAnd then the controller, which you see over here, is not much more complicated. But it has\ntwo loops in it, one of which is the main one for doing the GCD, and one of which is the\n\nsubtraction loop for doing the remainder sub-operation. And there are ways, of course, of, if\nyou think about it, taking the remainder program. If I take remainder, as you see over\n\nthere, as a lambda expression, substitute it in for remainder over here in the GCD program,\n\nthen do some simplification by substituting a and b for remainder in there, then I can\nunwind this loop. And I can get this piece of machinery by basically, a little bit of algebraic\n\nsimplification on the lambda expressions.\n\n\n\n\nSo I suppose you've seen your first very simple machines now. Are there any questions?\n\nGood. This looks easy, doesn't it? Thank you. I suppose, take a break.\n\n\n\n\n[MUSIC PLAYING - \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\n\n\n\n\nPROFESSOR: Well, let's see. Now you know how to make an iterative procedure, or a\n\nprocedure that yields an iterative process, turn into a machine. I suppose the next thing we\nwant to do is worry about things that reveal recursive processes. So let's play w ith a simple\n\nfactorial procedure.\n\n\n\n\nWe define factorial of N to be if n is 1, the result is 1, using 1 right now to decrease the\n\namount of work I have to do to simulate it, else it's times N factorial N minus 1. And what's\ndifferent with this program, as you know, is that after I've computed factorial of N minus 1\n\nhere, I have to do something to the result. I have to multiply it by N.\n\n\n\n\nSo the only way I can visualize what this machine is doing, because of the fact -- think of it\n\nthis way, that I have a machine out here which somehow needs a factorial machine in order\nto compute its answer. But this machine, the outer machine, has to exist before and after\n\nthe factorial machine, which is inside. Whereas in the iterative case, the outer machine\ndoesn't need to exist after the inner machine is running, because you never need to go back\n\nto the outer machine to do anything.\n\n\n\n\nSo here we have a problem where we have a machine which has the same machine inside\n\nof it, an infinitely large machine. And it's got other t hings inside of it, like a multiplier, which\ntakes some inputs, and there's a minus 1 box, and things like that. You can imagine that's\n\nwhat it looks like.\nBut the important thing is that here I have something that happens before and after, in the\nouter machine, the execution of the inner machine. So this machine has to have a life. It\n\nhas to exist on both times sides of this machine.\n\n\n\n\nSo somehow, I have to have a place to store the things that this thing needs to run. Infinite\n\nobjects don't exist in the real world. What we have to do is arrange an illusion that we have\nan infinite object, we have an infinite amount of hardware somewhere.\n\n\n\n\n\nNow of course, illusion's all that really matters. If we can arrange that every time you look\nat some infinite object, the part of it that you look at is there, then it's as infinite as you\n\nneed it to be. And of course, one of the things we might want to do, just look at this thing\nover here, is the organization that we've had so far involves having a part of the machine,\n\nwhich is the controller, which sits right over here, which is perfectly finite and very simple.\nWe have some datapaths, which consist of registers and operators. And what I propose to\n\ndo here is decompose the machine into two parts, such that there is a part which is\n\nfundamentally finite, and some part where a certain amount of infinite stuff can be kept.\n\n\n\n\nOn the other hand this is very simple and really isn't infinite, but it's just very large. But it's\nso simple that it could be cheaply reproduced in such large amounts, we call it memory,\n\nthat we can make a structure called a stack out of it which will allow us to, in fact, simulate\n\nthe existence of an infinite machine which is made out of a recursive nest of many\nmachines. And the way it's going to work is that we're going to store in this place called the\n\nstack the information required after the inner machine runs to resume the operation of the\nouter machine.\n\n\n\n\n\nSo it will remember the important things about the life of the outer machine that will be\nneeded for this computation. Since, of course, these machines are nested in a recursive\n\nmanner, then in fact the stack will only be accessed in a manner which is the last thing that\ngoes in is the first thing that comes out. So we'll only need to access some little part of this\n\nstack memory.\n\n\n\n\nOK, well, let's do it. I'm going to build you a datapath now, and I'm going to write the\n\ncontroller. And then we're going to execute this to see how you do it. So the factorial\nmachine isn't so bad. It's going to have a register called the value, where the answer is\n\ngoing to be stored, and a registered called N, which is where the number I'm taking factorial\nwill be stored, factorial of. And it will be necessary in some instances to connect VAL to N.\nIn fact, one nice case of this is if I just said over here, N, because that would be right for N\nequal 1N. And I could just move the answer over there if that's important. I'm not worried\n\nabout that right now.\n\n\n\n\nAnd there are things I have to be able to do. Like I have tobe able to, as we see here,\n\nmultiply N by something in VAL, because VAL is the result of computing factorial. And I have\nto put the result back into VAL.\n\n\n\n\n\nSo here we can see that the result of computing a factorial is N times the result of\ncomputing a factorial. VAL will be the representation of the answer of the inner factorial.\n\nAnd so I'm going to have to have a multiplier here, which is going to sample the value of N\nand the value of VAL and put the result back into VAL like that.\n\n\n\n\n\nI'm also going to have to be able to see if N is 1. So I need a light bulb. And I suppose the\nother thing I'm going to need to have is a way of decrementing N. So I'm going to have a\n\ndecrementer, which takes N and is going to put back the result into N. That's pretty much\nwhat I need in my machine.\n\n\n\n\n\nNow, there's a little bit else I need. It's a little bit more complicated, because I'm also going\nto need a way to store, to save away, the things that are going to be needed for resuming\n\nthe computation of a factorial after I've done a sub-factorial. What's that? One thing I need\nis N.\n\n\n\n\n\nSo I'm going to build here a thing called a stack. The stack is a bunch of stuff that I'm going\nto write in sequentially. I don't how long it is. The longer it is, the better my illusion of\n\ninfinity. And I'm going to have to have a way of getting stuff out of N and into the stack and\nvice versa. So I'm going to need a connection like this, which is two -way, whereby I can\n\nsave the value of N and then restore it some other time through that connection. This is the\nstack.\n\n\n\n\n\nI also need a way of remembering where I was in the computation of factorial in the outer\nprogram. Now in the case of this machine, it isn't very much a problem. Factorial always\n\nreturns, has to go back to the place where we multiply by N, except for the last time, when\nit has to return to whatever needs the factorial or go to done or stop. However, in general,\n\nI'm going to have to remember where I have been, because I might have computed\nfactorial from somewhere else. I have to go back to that place and continue there.\nSo I'm going to have to have some way of taking the place where the marble is in the finite\nstate controller, the state of the controller, and storing that in the stack as well. And I'm\n\ngoing to have to have ways of restoring that back to the state of the-- the marble. So I\nhave to have something that moves the marble to the right place.\n\n\n\n\n\nWell, we're going to have a place which is the marble now. And it's called the continue\nregister, called continue, which is the place to put the marble nexttime I go to continue.\n\nThat's what that's for. And so there's got to be some path from that into the controller.\n\n\n\n\nI also have to have some way of saving that on the stack. And I have to have some way of\n\nsetting that up to have various constants, a certain fixed number of constants. And that's\nvery easy to arrange. So let's have some constants here. We'll call this one after-fact. And\n\nthat's a constant which we'll get into the continue register, and also another one called fact-\ndone.\n\n\n\n\n\nSo this is the machine I want to build. That's its datapaths, at least. And it mixes a little\nwith the controller here, because of the fact that I have to remember where I was and\n\nrestore myself to that place.\n\n\n\n\nBut let's write the program now which represents the controller.I'm not going to write the\n\ndefine machine thing and the register list, because that's not very interesting. I'm just going\nto write down the sequence of instructions that constitute the controller.\n\n\n\n\n\nSo we have assign, to set up, continue to done. We have a loop which says branch if equal\n1 fetch N, if N is 1, then go to the base step of the induction, the simple case.\n\n\n\n\n\nOtherwise, I have to remember the things that are necessary to perform a sub -factorial. I'm\ngoing to go over here, and I have to perform a sub-factorial. So I have to remember what's\n\nneeded after I will be done with that.\n\n\n\n\nSee, I'm about to do something terrible. I'm about to change the value of N. But this guy\nhas to know the old value of N. But in order to make the sub-factorial work, I have to\n\nchange the value of N. So I have to remember the old value. And I also have to remember\n\nwhere I've been. So I save up continue.\nAnd this is an instruction that says, put something in the stack. Save the contents of the\ncontinuation register, which in this case is done, because later I'm going to change that,\n\ntoo, because I need to go back to after-fact, as well. We'll see that.\n\n\n\n\nWe save N, because I'm going to need that for later. Assign to N the decrement of fetch N.\n\nAssign continue, we're going to look at this now, to after, we'll call it. That's a good name\nfor this, a little bit easier and shorter, and fits in here.\n\n\n\n\n\nNow look what I'm doing here. I'm saying, if the answer is 1, I'm done. I'm going to have to\njust get the answer. Otherwise, I'm going to save the continuation, save N, make N one less\n\nthan N, remember I'm going to come back to someplace else, and go back and start doing\nanother factorial.\n\n\n\n\n\nHowever, I've got a different machine [? in me ?] now. N is 1, and continue is something\nelse. N is N minus 1.\n\n\n\n\n\nNow after I'm done with that, I can go there. I will restore the old value of N, which is the\nopposite of this save over here. I will restore the continuation.\n\n\n\n\nI will then go to here. I will assign to the VAL register the product of N and fetch VAL. VAL\n\nfetch product assign.\n\n\n\n\nAnd then I will be done. I will have my answer to the sub -factorial in VAL. At that point, I'm\n\ngoing to return by going to the place where the continuation is pointing. That says, go to\nfetch continue.\n\n\n\n\n\nAnd then I have finally a base step, which is the immediate answer. Assign to VAL fetch N,\nand go to fetch continue. And then I'm done.\n\n\n\n\n\nNow let's see how this executes on a very simple case, because then we'll see the use of\nthis stack to do the job we need. This is statically what it's doing, but we have look\n\ndynamically at this. So let's see.\nFirst thing we do is continue gets done. The way that happened is I pushed this. Let's call\nthat done the way I have it. I push that button. Done goes into there.\n\n\n\n\n\nNow I also have to set this thing up to have an initial value. Let's consider a factorial of\nthree, a simple case. And we're going to start out with our stack growing over here. Stacks\n\nhave their own little internal state saying where they are, where the next place I'm going to\nwrite is.\n\n\n\n\n\nSo now we say, is N 1? The answer is no. So now I'm going to save continue, bang. Now\nthat done goes in here. And this moves to here, the next place I'm going to write.\n\n\n\n\n\nSave N 3. OK? Assign to N the decrement of N. That means I've pushed this button. This\nbecomes 2.\n\n\n\n\nAssign to continue aft. So I've pushed that button. Aft goes in here.\n\n\n\n\n\nOK, now go to loop, bang, so up to here. Is N 1? No.\n\n\n\n\nSo I have to save continue. What's continue? Continue is aft. Push this button. So this\n\nmoves to here.\n\n\n\n\nI have to save N. N is over here. I got to 2. Push that button. So a 2 gets written there. And\n\nthen this thing moves down here.\n\n\n\n\nOK, save N. Assign N to the decrement of N. This becomes a 1. Assign continue to aft. A -F-T\ngets written there again.\n\n\n\n\n\nGo to loop. Is N equal to 1? Oh, yes, the answer is 1.\n\n\n\n\nOK, go to base step. Assign to VAL fetch of N. Bang, 1 gets put in there.\nGo to fetch continue. So we look in continue. Basically, I'm pushing a button over here that\ngoes to the controller. The continue becomes aft, and all of a sudden, the program's running\n\nhere.\n\n\n\n\nI now have to restore the outer version of factorial. So we go here. We say, restore N. So\n\nrestore N means take the contents that's here. Push this button, and it goes into here, 2,\nand the pointer moves up.\n\n\n\n\n\nRestore continue, pretty easy. Go push this button. And then aft gets written in here again.\nThat means this thing moves up. I've gotten rid of something else on my stack.\n\n\n\n\n\nRight, then I go to here, which says, assign to VAL the product of N an VAL. So I push this\nbutton over here, bang. 2 times 1 gives me a 2, get written there.\n\n\n\n\nGo to fetch continue. Continue is aft. I go to aft. Aft says restore N. Do your restore N,\n\nmeans I take the value over here, which is 3, push this up to here, and move it into here,\n\nN. Now it's pushing that button.\n\n\n\n\nThe next thing I do is restore continue. Continue is now going to becom e done. So this\nmoves up here when I push this button. Done may or may be there anymore, I'm not\n\ninterested, but it certainly is here.\n\n\n\n\nNext thing I do is assign to VAL the product of the fetch of N and the fetch of VAL. That's\n\npushing this button over here, bang. 2 times 3 is 6. So I get a 6 over here.\n\n\n\n\nAnd go to fetch continue, whoops, I go to done, and I'm done. And my answer is 6, as you\n\ncan see in the VAL register. And in fact, the stack is in the state it originally was in.\n\n\n\n\nNow there's a bit of discipline in using these things like stacks that we have to be careful of.\n\nAnd we'll see that in the next segment. But first I want to ask if there are any questions for\nthis. Are there any questions? Yes, Ron.\nAUDIENCE: What happens when you roll off the end of the stack with--\n\n\n\n\nPROFESSOR: What do you mean, roll off of?\n\n\n\n\n\nAUDIENCE: Well, the largest number-- a larger starting point of N requires more memory,\ncorrect?\n\n\n\n\n\nPROFESSOR: Oh, yes. Well, I need to have a long enough stack. You say, what if I violate\nmy illusion?\n\n\n\n\n\nAUDIENCE: Yes.\n\n\n\n\nPROFESSOR: Well, then the magic doesn't work. The truth of the matter is that every\nmachine is finite. And for a procedure like this, there's a limit to the number of sub-\n\nfactorials I could have.\n\n\n\n\nRemember when we were doing the y-operator a while ago, we pointed out that there was a\n\nsequence of exponentiation procedures, each of which was a little better than the previous\none. Well, we're now seeing how we implement that mathematical idea. The limiting process\n\nis only so good as as far as you take the limit.\n\n\n\n\nIf you think about it, what am I using here? I'm using about two pieces of memory for every\n\nrecursion of this process. If we try to compute factorial of 10,000, that's not a lot of\nmemory. On the other hand, it's an awful big number.\n\n\n\n\n\nSo the question is, is that a valuable thing in this case. But it really turns out not to be a\nterrible limit, because memory is el cheapo, and people are pretty expensive. OK, thank\n\nyou, let's take a break.\n\n\n\n\n[MUSIC PLAYING - \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\nPROFESSOR: Well, let's see. What I've shown you now is how to do a simple iterative\n\nprocess and a simple recursive process. I just want to summarize the design of simple\nmachines for specific applications by showing you a little bit more complicated design, that\n\nof a thing that does doubly recursive Fibonacci, because it will indicate to us, and we'll\nunderstand, a bit about the conventions required for making stacks operate correctly.\n\n\n\n\n\nSo let's see. I'm just going to write down, first of all, the program I'm going to translate. I\nneed a Fibonacci procedure, it's very simple, which says, if N is less than 2, the result is N,\n\notherwise it's the sum of Fib of N minus 1 and Fib of N minus 2. That's the plan I have here.\n\n\n\n\nAnd we're just going to write down the controller for such a machine. We're going to\n\nassume that there are registers, N, which holds the number we're taking Fibonacci of, VAL,\nwhich is where the answer is going to get put, and continue, which is the thing that's linked\n\nto the controller, like before. But I'm not going to draw another physical datapath, because\nit's pretty much the same as the last one you've seen.\n\n\n\n\n\nAnd of course, one of the most amazing things about computation is that after a while, you\nbuild up a little more features and a few more features, and all of the sudden, you've got\n\neverything you need. So it's remarkable that it just gets there so fast. I don't need much\nmore to make a universal computer.\n\n\n\n\n\nBut in any case, let's look at the controller for the Fibonacci thing. First thing I want to do is\nstart the thing up by assign to continue a place called done, called Fib-done here. So that\n\nmeans that somewhere over here, I'm going to have a label, Fib-done, which is the place\nwhere I go when I want the machine to stop. That's what that is.\n\n\n\n\n\nAnd I'm going to make up a loop. It's a place I'm going to go to in order to start up\ncomputing a Fib. Whatever is in N at this point, Fibonacci will be computed of, and we will\n\nreturn to the place specified by continue.\n\n\n\n\nSo what you're going to see here at this place, what I want here is the contract that says,\n\nI'm going to write this with a comment syntax, the contract is N contains arg, the\nargument. Continue is the recipient. And that's where it is. At this point, if I ever go to this\n\nplace, I'm expecting this to be true, the argument for computing the Fibonacci.\nNow the next thing I want to do is to branch. And if N is less than 2-- by the way, I'm using\n\nwhat looks like Lisp syntax. This is not Lisp. This does not run . What I'm writing here does\nnot run as a simple Lisp program. This is a representation of another language.\n\n\n\n\n\nThe reason I'm using the syntax of parentheses and so on is because I tend to use a Lisp\nsystem to write an interpreter for this which allows meto simulate the machine I'm trying\n\nto build. I don't want to confuse this to think that this is Lisp code. It's just I'm using a lot of\nthe pieces of Lisp. I'm embedding a language in Lisp, using Lisp as pieces to make my\n\nprocess of making my simulator easy. So I'm inheriting from Lisp all of its properties.\n\n\n\n\nFetch of N 2, I want to go to a place called immediate answer. It's the base step. Now,\n\nthat's somewhere over here, just above done. And we'll see it later.\n\n\n\n\nNow, in the general case, which is the part I'm going to write down now, let's just do it.\n\nWell, first of all, I'm going to have to call Fibonacci twice. In each case -- well, in one case at\nleast, I'm going to have to know what to do to come back and do the next one. I have to\n\nremember, have I done the first Fib, or have I done the second one? Do I have to come\nback to the place where I do the second Fib, or do I have to come back to the place where I\n\ndo the add?\n\n\n\n\nIn the first case, over the first Fibonacci, I'm going to need the value of N for c omputing for\n\nthe second one. So I have to store some of these things up. So first I'm going to save\ncontinue. That's who needs the answer. And the reason I'm doing that is because I'm about\n\nto assign continue to the place which is the place I want to go to after.\n\n\n\n\nLet's call it Fib-N-minus-1, big long name, classic Lisp name. Because I'm going to compute\n\nthe first Fib of N minus 1, and then after that, I want to come back and do something else.\nThat's the place I want to go to after I've done the first Fibonacci calculation. And I want to\n\ndo a save of N, because I'm going to need it later, after that.\n\n\n\n\nNow I'm going to, at this point, get ready to do the Fibonacci of N minus 1. So assign to N\n\nthe difference of the fetch of N and 1. Now I'm ready to go back to doing the Fib loop.\n\n\n\n\nHave I satisfied my contract? And the answer is yes. N contains N minus 1, which is what I\nneed. Continue contains a place I want to go to when I'm done with calculating N minus 1.\nSo I've satisfied the contract. And therefore, I can write down here a label, after-Fib-N-\n\nminus-1.\n\n\n\n\nNow what am I going to do here? Here's a place where I now have to get ready to do Fib of\n\nN minus 2. But in order to do a Fib of N minus 2, look, I don't know. I've clobbered my N\nover here. And presumably my N is counted down all the way to 1 or 0 or something at this\n\npoint. So I don't know what the value of N in the N register is.\n\n\n\n\nI want the value of N that was on the stack that I saved over here so that could restore it\n\nover here. I saved up the value of N, which is this value of N at this point, so that I could\nrestore it after computing Fib of N minus 1, so that I could count that down to N minus 2\n\nand then compute Fib of N minus 2. So let's restore that. Restore of N.\n\n\n\n\nNow I'm about to do something which is superstitious, and we will remove it shortly. I am\n\nabout to finish the sequence of doing the subroutine call, if you will. I'm going to say, well, I\nalso saved up the continuation, since I'm going to restore it now.\n\n\n\n\n\n\nBut actually, I don't have to, because I'm not going to need it. We'll fix that in a second. So\n\nwe'll do a restore of continue, which is what I would in general need to do. And we're just\ngoing to see what you would call in the compiler world a peephole optimization, which says,\n\nwhoops, you didn't have to do that.\n\n\n\n\nOK, so the next thing I see here is that I have to get ready now to do Fibonacci of N minus\n\n2. But I don't have to save N anymore. The reason why I don't have to save N anymore is\nbecause I don't need N after I've done Fib of N minus 2, because the next thing I do is add.\n\nSo I'm just going to set up my N that way. Assign N minus difference of fetch N and 2.\n\n\n\n\nNow I have to finish the setup for calling Fibonacci of N minus 2. Well, I have to save up\n\ncontinue and assign continue, continue, to the place which is after Fib N 2, that place over\nhere somewhere. However, I've got to be very careful. The old value, thevalue of Fib of N\n\nminus 1, I'm going to need later.\n\n\n\n\nThe value of Fibonacci of N minus 1, I'm going to need. And I can't clobber it, because I'm\ngoing to have to add it to the value of Fib of N minus 2. That's in the value register, so I'm\ngoing to save it. So I have to save this right now, save up VAL. And now I can go off to my\n\nsubroutine, go to Fib loop.\n\n\n\n\nNow before I go any further and finish this program, I just want to look at this segment so\n\nfar and see, oh yes, there's a sequence of instructions here, if you will, that I can do\nsomething about. Here I have a restore of continue, a save of continue, and then an assign\n\nof continue, with no other references to continue in between. The restore followed by the\nsave leaves the stack unchanged.\n\n\n\n\n\nThe only difference is that I set the continue register to a value, which is the value that was\non the stack. Since I now clobber that value, as in it was never referenced, these\n\ninstructions are unnecessary. So we will remove these.\n\n\n\n\nBut I couldn't have seen that unless I had written them down. Was that really true? Well, I\n\ndon't know.\n\n\n\n\nOK, so we've now gone off to compute Fibonacci of N minus 2. So after that, what are we\ngoing to do? Well, I suppose the first thing we have to do-- we've got two things. We've got\n\na thing in the value register which is now valuable. We also have a thing on the stack that\n\ncan be restored into the value register. And what I have to be careful with now is I want to\nshuffle this right so I can do the multiply.\n\n\n\n\nNow there are various conventions I might use, but I'm going to be very picky and say, I'm\n\nonly going to restore into a register I've saved from. If that's the case, I have to do a\n\nshuffle here. It's the same problem with how many hands I have. So I'm going to assign to\nN, because I'm not going to need N anymore, N is useless, the current value of VAL, which\n\nwas the value of Fib of N minus 2.\n\n\n\n\nAnd I'm going to restore the value register now. This restore matches this save. And if\n\nyou're very careful and examine very carefully what goes on, restores and saves are always\nmatched. Now there's an outstanding save, of course, that we have to get rid of soon.\n\n\n\n\nAnd so I restored the value register. Now I restore the continue one, which matches this\n\none, dot, dot, dot, dot, dot, dot, dot, down to here, restoring that continuation. That\ncontinuation is a continuation of Fib of N, which is the problem I was trying to solve, a\n\nmajor problem I'm trying to solve. So that's the guy I have to go back to who wants Fib of\nN. I saved them all the way up here when I realized N was not less than 2. And so I had to\n\ndo a complicated operation.\n\n\n\n\nNow I've got everything I need to do it. So I'm going to restore that, assign to VAL the sum\n\nof fetch VAL and fetch of N, and go to continue. So now I've re turned from computing\nFibonacci of N, the general case. Now what's left is we have to fix up a few details, like\n\nthere's the base case of this induction, immediate answer, which is nothing more than\nassign to VAL fetch of N, because N was less than 2, and therefore, the answer is N in our\n\noriginal program, and return continue-- bobble, bobble almost-- and finally Fib done.\n\n\n\n\nSo that's a fairly complicated program. And the reason I wanted you see to that is because I\n\nwant you to see the particular flavors of stack discipline that I was obeying. It was first of\nall, I don't want to take anything that I'm not going to need later. I was being very careful.\n\nAnd it's very important. And there are all sorts of other disciplines people make with frames\nand things like that of some sort, where you save all sorts of junk you're not going to need\n\nlater and restore it because, in some sense, it's easier to do that. That's going to lead to\nvarious disasters, which we'll see a little later.\n\n\n\n\n\nIt's crucial to say exactly what you're going to need later. It's an important idea. And the\nresponsibility of that is whoever saves something is the guy who restores it, because he\n\nneeds it. And in such discipline, you can see what things are unnecessary, operations that\nare unimportant.\n\n\n\n\n\nNow, one other thing I want to tell you about that's very simple is that, of course, the\npicture you see is not the whole picture. Supposing I had systems that had things like other\n\noperations, CAR, CDR, cons, building a vector and referencing the nth element of it, or\nthings like that. Well, at this level of detail, whatever it is, we can conceptualize those as\n\nprimitive operations in the datapath. In other words, we could say that some machine that,\n\nfor example, has the append machine, which has to do cons of the CAR of x with the append\nof the CDR of x and y, well, gee, that's exactly the same as the factorial structure. Well, it's\n\ngot about the same structure.\n\n\n\n\nAnd what do we have? We have some sort of things in it which may be registers, x and y,\nand then x has to somehow move to y sometimes, x has to get the value of y. And then we\n\nmay have to be able to do something which is a cons. I don't remember if I need to like this\n\nis in this system, but cons is sort of like subtract or add or something. It combines two\nthings, producing a thing which is the cons, which we may then think goes into there. And\n\nthen maybe a thing called the CAR, which will produce-- I can get the CAR or something.\nAnd maybe I can get the CDR of something, and so on.\nBut we shouldn't be too afraid of saying things this way, because the worst that could\nhappen is if we open up cons, what we're going to find is some machine. And cons may in\n\nfact overlap with CAR and CDR, and it always does, in the same way that plus and minus\noverlap, and really the same business. Cons, CAR, and CDR are going to overlap, and we're\n\ngoing to find a little controller, a little datapath, which may have some registers in it, some\n\nstuff like that. And maybe inside it, there may also be an infinite part, a part that's semi-\ninfinite or something, which is a lot of very uniform stuff, which we'll call memory.\n\n\n\n\nAnd I wouldn't be so horrified if that were the way it works. In fact, it does, and we'll talk\n\nabout that later. So are there any questions?\n\n\n\n\nGee, what an unquestioning audience. Suppose I tell you a horrible pile of lies. OK. Well,\n\nthank you. Let's take our break.\n\n\n\n\n[MUSIC PLAYING - \"JESU, JOY OF MAN'S DESIRING\" BY JOHANN SEBASTIAN BACH]\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed thismaterial in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Sub/lec9b.txt",
    "content": "MIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\nTranscript – 9B: Explicit-control Evaluator\n\n\n\nPROFESSOR: Well, I hope you appreciate that we have inducted you into some real magic,\nthe magic of building languages, really building new languages. What have we looked at?\n\nWe've looked at an Escher picture language: this language invented by Peter Hende rson.\nWe looked at digital logic language. Let's see. We've looked at the query language.\n\n\n\n\n\nAnd the thing you should realize is, even though these were toy examples, they really are\nthe kernels of really useful things. So, for instance, the Escher picturelanguage was taken\n\nby Henry Wu, who's a student at MIT, and developed into a real language for laying out PC\nboards based just on extending those structures. And the digital logic language, Jerry\n\nmentioned when he showed it to you, was really extended to be used as the basis for a\nsimulator that was used to design a real computer. And the query language, of course, is\n\nkind of the germ of prologue.\n\n\n\n\nSo we built all of these languages, they're all based on LISP. A lot of people ask what\n\nparticular problems is LISP good for solving for? The answer is LISP is not good for solving\nany particular problems. What LISP is good for is constructing within it the right language to\n\nsolve the problems you want to solve, and that's how you should think about it.\n\n\n\n\nSo all of these languages were based on LISP. Now, what's LISP based on? Where's that\n\ncome from? Well, we looked at that too. We looked at the meta-circular evaluator and said\nwell, LISP is based on LISP. And when we start looking at that, we've got to do some re al\n\nmagic, right? So what does that mean, right? Why operators, and fixed points, and the idea\nthat what this means is that LISP is somehow the fixed-point equation for this funny set of\n\nthings which are defined in terms of themselves. Now, it's real magic.\n\n\n\n\nWell, today, for a final piece of magic, we're going to make all the magic go away. We\n\nalready know how to do that. The idea is, we're going to take the register machine\narchitecture and show how to implement LISP on terms of that. And, remember, the id ea of\n\nthe register machine is that there's a fixed and finite part of the machine. There's a finit-\nstate controller, which does some particular thing with a particular amount of hardware.\n\nThere are particular data paths: the operation the machine does. And then, in order to\n\nimplement recursion and sustain the illusion of infinity, there's some large amount of\nmemory, which is the stack.\nSo, if we implement LISP in terms of a register machine, then everything ought to become,\nat this point, completely concrete. All the magic should go away. And, by the end of this\n\ntalk, I want you get the feeling that, as opposed to this very mysterious meta -circular\nevaluator, that a LISP evaluator really is something that's concrete enough that you can\n\nhold in the palm of your hand. You should be able to imagine holding a LISP interpreter\n\nthere.\n\n\n\n\nAll right, how are we going to do this? We already have all the ingredients. See, what you\nlearned last time from Jerry is how to take any particular couple of LISP procedures and\n\nhand-translate them into something that runs on a register machine. So, to implement all of\n\nLISP on a register machine, all we have to do is take the particular procedures that are the\nmeta-circular evaluator and hand-translate them for a register machine. And that does all of\n\nLISP, right? So, in principle, we already know how to do this. And, indeed, it's going to be\nno different, in kind, from translating, say, recursive factorial or recursive Fibonacci. It's just\n\nbigger and there's more of it. So it'd just be more details, but nothing really conceptually\nnew.\n\n\n\n\n\nAll right, also, when we've done that, and the thing is completely explicit, and we see how\nto implement LISP in terms of the actual sequential register operations, that's going to be\n\nour final most explicit model of LISP in this course. And, remember, that's a progression\nthrough this course. We started out with substitution, which is sort of like algebra. And then\n\nwe went to the environment model, which talked about the actual frames and how th ey got\nlinked together. And then we made that more concrete in the meta-circular evaluator.\n\n\n\n\n\nThere are things the meta-circular evaluator doesn't tell us. You should realize that. For\ninstance, it left unanswered the question of how a procedure, like recu rsive factorial here ,\n\nsomehow takes space that grows. On the other hand, a procedure which also looks\nsyntactically recursive, called fact-iter, somehow doesn't take space. We justify that it\n\ndoesn't need to take space by showing the substitution model. But we didn't really say how\nit happens that the machine manages to do that, that that has to do with the details of how\n\narguments are passed to procedures. And that's the thing we didn't see in the meta -circular\n\nevaluator precisely because the way arguments got passed to procedures in this LISP\ndepended on the way arguments got passed to procedures in this LISP. But, now, that's\n\ngoing to become extremely explicit.\n\n\n\n\nOK. Well, before going on to the evaluator, let me just give you a sense of what a whole\n\nLISP system looks like so you can see the parts we're going to talk about and the parts\nwe're not going to talk about. Let's see, over here is a happy LISP user, and the LISP user is\ntalking to something called the reader. The reader's job in life is to take characters from the\n\nuser and turn them into data structures in something called a list structure memory.\n\n\n\n\nAll right, so the reader is going to take symbols, parentheses, and A's and B's, and ones and\n\nthrees that you type in, and turn these into actual lis t structure: pairs, and pointers, and\nthings. And so, by the time evaluator is going, there are no characters in the world. And, of\n\ncourse, in more modern list systems, there's sort of a big morass here that might sit\nbetween the user and the reader: Windows systems, and top levels, and mice, and all kinds\n\nof things. But conceptually, characters are coming in.\n\n\n\n\nAll right, the reader transforms these into pointers to stuff in this memory, and that's what\n\nthe evaluator sees, OK? The evaluator has a bunch of helpers. It has all possible primitive\noperators you might want. So there's a completely separate box, a floating point unit, or all\n\nsorts of things, which do the primitive operators. And, if you want more special primitives,\nyou build more primitive operators, but they're separate from the evaluator. The evaluator\n\nfinally gets an answer and communicates that to the printer. And now, the printer's job in\nlife is to take this list structure coming from the evaluator, and turn it back into characters,\n\nand communicate them to the user through whatever interface there is.\n\n\n\n\nOK. Well, today, what we're going to talk about is this evaluator. The primitive operators\n\nhave nothing particular to do with LISP, they're however you like to implement primitive\noperations. The reader and printer are actually complicated, but we're not going to talk\n\nabout them. They sort of have to do with details of how you might build up list structure\n\nfrom characters. So that is a long story, but we're not going to talk about it. The list\nstructure memory, we'll talk about next time. So, pretty much, except for the details of\n\nreading and printing, the only mystery that's going to be left after you see the evaluator is\nhow you build list structure on conventional memories. But we'll worry about that next time\n\ntoo.\n\n\n\n\nOK. Well, let's start talking about the evaluator. The one that we're going to sho w you, of\n\ncourse, is not, I think, nothing special about it. It's just a particular register machine that\nruns LISP. And it has seven registers, and here are the seven registers. There's a register,\n\ncalled EXP, and its job is to hold the expression to be evaluated. And by that, I mean it's\ngoing to hold a pointer to someplace in list structure memory that holds the expression to\n\nbe evaluated.\n\n\n\n\nThere's a register, called ENV, which holds the environment in which this expression is to be\n\nevaluated. And, again, I made a pointer. The environment is some data structure. There's a\nregister, called FUN, which will hold the procedure to be applied when you go to apply a\n\nprocedure. A register, called ARGL, which wants the list of evaluated arguments.\n\n\n\n\nWhat you can start seeing here is the basic structure of the evaluator. Remember how\n\nevaluators work. There's a piece that takes expressions and environments, and there's a\npiece that takes functions, or procedures and arguments. And going back and forth around\n\nhere is the eval/apply loop. So those are the basic pieces of the eval and apply.\n\n\n\n\nThen there's some other things, there's continue. You just saw before how the continue\n\nregister is used to implement recursion and stack discipline. There's a register that's goin g\nto hold the result of some evaluation. And then, besides that, there's one temporary\n\nregister, called UNEV, which typically, in the evaluator, is going to be used to hold\ntemporary pieces of the expression you're working on, which you haven't gotten arou nd to\n\nevaluate yet, right? So there's my machine: a seven-register machine. And, of course, you\nmight want to make a machine with a lot more registers to get better performance, but this\n\nis just a tiny, minimal one.\n\n\n\n\nWell, how about the data paths? This machine has a lot of special operations for LISP. So,\n\nhere are some typical data paths. A typical one might be, oh, assign to the VAL register the\ncontents of the EXP register. In terms of those diagrams you saw, that's a little button on\n\nsome arrow.\n\n\n\n\nHere's a more complicated one. It says branch, if the thing in the expression register is a\n\nconditional to some label here, called the ev -conditional. And you can imagine this\nimplemented in a lot of different ways. You might imagine this conditional test as a   special\n\npurpose sub-routine, and conditional might be represented as some data abstraction that\nyou don't care about at this level of detail. So that might be done as a sub-routine. This\n\nmight be a machine with hardware-types, and conditional might be testing some bits for a\n\nparticular code. There are all sorts of ways that's beneath the level of abstraction we're\nlooking at.\n\n\n\n\nAnother kind of operation, and there are a lot of different operations assigned to EXP, the\n\nfirst clause of what's in EXP. This might be part of processing a conditional. And, again, first\nclause is some selector whose details we don't care about. And you can, again, imagine that\n\nas a sub-routine which'll do some list operations, or you can imagine that as something\n\nthat's built directly into hardware. The reason I keep saying you can imagine it built directly\ninto hardware is even though there are a lot of operations, there are still a fixed number of\n\nthem. I forget how many, maybe 150. So, it's plausible to think of building these d irectly\ninto hardware.\nHere's a more complicated one. You can see this has to do with looking up the values of\nvariables. It says assign to the VAL register the result of looking up the variable value of\n\nsome particular expression, which, in this case, is supposed to be a variable in some\nenvironment. And this'll be some operation that searches through the environment\n\nstructure, however it is represented, and goes and looks up that variable. And, again, that's\n\nbelow the level of detail that we're thinking about. This has to do with the details of the data\nstructures for representing environments.\n\n\n\n\nBut, anyway, there is this fixed and finite number of operations in the register machine.\n\nWell, what's its overall structure? Those are some typical operations.Remember what we\n\nhave to do, we have to take the meta-circular evaluator-- and here's a piece of the meta-\ncircular evaluator. This is the one using abstract syntax that's in the book. It's a little bit\n\ndifferent from the one that Jerry shows you. And themain thing to remember about the\nevaluator is that it's doing some sort of case analysis on the kinds of expressions: so if it's\n\neither self-evaluated, or quoted, or whatever else. And then, in the general case where the\nexpression it's looking at is an application, there's some tricky recursions going on.\n\n\n\n\n\nFirst of all, eval has to call itself both to evaluate the operator and to evaluate all the\noperands. So there's this sort of red recursion of values walking down the tree that's really\n\nthe easy recursion. That's just a val walking down this tree of expressions. Then, in the\nevaluator, there's a hard recursion. There's the red to green. Eval calls apply. That's the\n\ncase where evaluating a procedure or argument reduces to applying the procedure to the\nlist of arguments.\n\n\n\n\n\nAnd then, apply comes over here. Apply takes a procedure and arguments and, in the\ngeneral case where there's a compound procedure, apply goes around and green calls red.\n\nApply comes around and calls eval again. Eval's the body of the procedure in the result of\nextending the environment with the parameters of the procedure by binding the arguments.\n\nExcept in the primitive case, where it just calls something else primitive -apply, which is not\nreally the business of the evaluator. So this sort of red to green, to red to green, that's the\n\neval/apply loop, and that's the thing that we're going to want to see in the evaluator.\n\n\n\n\nAll right. Well, it won't surprise you at all that the two big pieces of this evaluator\n\ncorrespond to eval and apply. There's a piece called eval-dispatch, and a piece called apply-\ndispatch. And, before we get into the details of the code, the way to understand this is to\n\nthink, again, in terms of these pieces of the evaluator having contracts with the rest of the\n\nworld. What do they do from the outside before getting into the grungy details?\nWell, the contract for eval-dispatch-- remember, it corresponds to eval. It's got to evaluate\n\nan expression in an environment. So, in particular, what this one is going to do, eval -\ndispatch will assume that, when you call it, that the expression you want to evaluate is in\n\nthe EXP register. The environment in which you want the evaluation to take place is in the\nENV register. And continue tells you the place where the machine should go next when the\n\nevaluation is done. Eval-dispatch's contract is that it'll actually perform that evaluation, and,\nat the end of which, it'll end up at the place specified by continue. The result of the\n\nevaluation will be in the VAL register. And it just warns you, it makes no promises about\n\nwhat happens to the registers. All other registers might be destroyed. So, there's one piece,\nOK?\n\n\n\n\nTogether, the pieces, apply-dispatch that corresponds to apply, it's got to apply a procedure\n\nto some arguments, so it assumes that this register, ARGL, contains a list of the evaluated\n\narguments. FUN contains the procedure. Those correspond to the arguments to the apply\nprocedure in the meta-circular evaluator.\n\n\n\n\nAnd apply, in this particular evaluator, we're going to use a discipline which says the place\n\nthe machine should go to next when apply is done is, at the moment apply-dispatch is\n\ncalled at the top of the stack, that's just discipline for the way this particular machine's\norganized. And now apply's contract is given all that. It'll perform the application. The result\n\nof that application will end up in VAL. The stack will be popped. And, again, the contents of\nall the other registers may be destroyed, all right? So that's the basic organization of this\n\nmachine. Let's break for a little bit and see if there are any questions, and then we'll do a\nreal example.\n\n\n\n\n\nWell, let's take the register machine now, and actually step through, and really, in real\ndetail, so you see completely concrete how some expressions are evaluated, all right? So,\n\nlet's start with a very simple expression. Let's evaluate the expression 1. And we need an\nenvironment, so let's imagine that somewhere there's an environment, we'll call it E,0. And\n\njust, since we'll use these later, we obviously don't really need anything to evaluate 1. But,\njust for reference later, let's assume that E,0 has in it an X that's bound to 3 and a Y that's\n\nbound to 4, OK?\n\n\n\n\nAnd now what we're going to do is we're going to evaluate 1 in this environment, and so the\n\nENV register has a pointer to this environment, E,0, all right? So let's watch that thing go.\nWhat I'm going to do is step through the code. And, let's see, I'll be the controller. And now\n\nwhat I need, since this gets rather complicated, is a very little execution unit. So here's the\nexecution unit, OK? OK.\nOK. All right, now we're goin g to start. We're going to start the machine at eval-dispatch,\n\nright? That's the beginning of this. Eval-dispatch is going to look at the expression in\ndispatch, just like eval where we look at the very first thing. We branch on whether or not\n\nthis expression is self-evaluating. Self-evaluating is some abstraction we put into the\nmachine-- it's going to be true for numbers-- to a place called ev-self-eval, right?\n\n\n\n\n\nSo me, being the controller, looks at ev-self-eval, so we'll go over to there. Ev-self-eval\nsays fine, assign to val whatever is in the expression unit, OK? And I have a bug because\n\nwhat I didn't do when I initialized this machine is also say what's supposed to happen when\nit's done, so I should have started out the machine with done being in the continue register,\n\nOK? So we assign to VAL. And now go to fetch of continue, and now change -- OK.\n\n\n\n\nOK, let's try something harder. Let's reset the machine here, and we'll put in the expression\n\nregister, X, OK? Start again at eval-dispatch. Check, is it self-evaluating? No. Is it a\nvariable? Yes. We go off to ev-variable. It says assign to VAL, look up the variable value in\n\nthe expression register, OK? Go to fetch of continue.\n\n\n\n\nPROFESSOR: Done.\n\n\n\n\n\nPROFESSOR: OK. All right. Well, that's the basic idea. That's a simple operation of the\nmachine. Now, let's actually do something a little bit more interesting. Let's look at the\n\nexpression the sum of x and y. OK. And now we'll see how you start unrolling these\nexpression trees, OK?\n\n\n\n\n\nWell, start again at eval-dispatch, all right? Self-evaluating? No. Variable? No. All the other\nspecial forms which I didn't write down, like quote, and lambda, and set, and whatever, it's\n\nnone of those. It turns out to be an application, so we go off to ev-application, OK? Ev-\napplication, remember what it's going to do overall. It is going to evaluate the operator. It's\n\ngoing to evaluate the arguments, and then it's going to go apply them. So, before we start,\nsince we're being very literal, we'd better remember that, somewhere in thisenvironment,\n\nit's linked to another environment in which plus is bound to the primitive procedure plus\nbefore we get an unknown variable in our machine.\n\n\n\n\n\nOK, so we're at ev-application. OK, assign to UNEV the operands of what's in the expression\nregister, OK? Those are the operands. UNEV's a temporary register where we're going to\n\nsave them.\nPROFESSOR: I'm assigning.\n\n\n\n\nPROFESSOR: Assign to x the operator. Now, notice we've destroyed that expression in x,\n\nbut the piece that we need is now in UNEV. OK. Now, we're going to get set up to\n\nrecursively evaluate the operator. Save the continue register on the stack. Save the\nenvironment. Save UNEV. OK, assign to continue a label called eval -args.\n\n\n\n\nNow, what have we done? We've set up for a recursive call. We're about to go to eval-\n\ndispatch. We've set up for a recursive call to eval-dispatch. What did we do? We took the\n\nthings we're going to need later, those operands that were in UNEV; the environme nt in\nwhich we're going to eventually have to, maybe, evaluate those operands; the place we\n\neventually want to go to, which, in this case, was done; we've saved them on the stack. The\nreason we saved them on the stack is because eval-dispatch makes no promises about what\n\nregisters it may destroy. So all that stuff is saved on the stack.\n\n\n\n\nNow, we've set up eval-dispatch's contract. There's a new expression, which is the operator\n\nplus; a new environment, although, in this case, it's the same one; and a new p lace to go to\nwhen you're done, which is eval-args. So that's set up. Now, we're going to go off to eval-\n\ndispatch. Here we are back at eval-dispatch. It's not self-evaluating. Oh, it's a variable, so\nwe'd better go off to ev-variable, right? Ev-variable is assigned to VAL. Look up the variable\n\nvalue of the expression, OK? So VAL is the primitive procedure plus, OK? And go to fetch of\ncontinue.\n\n\n\n\n\nPROFESSOR: Eval-args.\n\n\n\n\nPROFESSOR: Right, which is now eval-args not done. So we come back here at eval-args,\n\nand what do we do? We're going to restore the stuff that we saved, so we restore UNEV.\nAnd notice, there, it wasn't necessary, although, in general, it would be. It might be some\n\narbitrary evaluation that happened. We restore ENV. OK, we assign to FUN fetch o f VAL.\n\n\n\n\nOK, now, we're going to go off and start evaluating some arguments. Well, first thing we'd\n\nbetter do is save FUN because some arbitrary stuff might happen in that evaluation. We\ninitialize the argument list. Assign to argl an empty argument list, and go to eval-arg-loop,\n\nOK? At eval-arg-loop, the idea of this is we're going to evaluate the pieces of the\nexpressions that are in UNEV, one by one, and move them from unevaluated in UNEV to\n\nevaluated in the arg list, OK? So we save argl. We assign to x the first operand of the stuff\nin UNEV.\nNow, we check and see if that was the last operand. In this case, it is not, all right? So we\nsave the environment. We save UNEV because those are all things we might need later.\n\nWe're going to need the environment to do some more evaluations. We're going to need\nUNEV to look at what the rest of those arguments were. We're going to assign continue a\n\nplace called accumulate-args, or accumulate-arg.\n\n\n\n\nOK, now, we've set up for another call to eval-dispatch, OK? All right, now, let me short-\n\ncircuit this so we don't go through the details of eval-dispatch. Eval-dispatch's contract says\nI'm going to end up, the world will end up, with the value of evaluating this expression in\n\nthis environment in the VAL register, and I'll end up there. So we short-circuit all of this,\n\nand a 3 ends up in VAL. And, when we return from eval -dispatch, we're going to return to\naccumulate-arg.\n\n\n\n\nPROFESSOR: Accumulate-arg.\n\n\n\n\n\nPROFESSOR: With 3 in the VAL register, OK? So that short-circuited that evaluation. Now,\nwhat do we do? We're going to go back and look at the rest of the arguments, so we restore\n\nUNEV. We restore ENV. We restore argl. One thing.\n\n\n\n\nPROFESSOR: Oops! Parity error.\n\n\n\n\n\n[LAUGHTER]\n\n\n\n\nPROFESSOR: Restore argl.\n\n\n\n\nPROFESSOR: OK. OK, we assign to argl consing on fetch of the value register to what's in\n\nargl. OK, we assign to UNEV the rest of the operands in fetch of UNEV, and we go back to\neval-arg-loop.\n\n\n\n\n\nPROFESSOR: Eval-arg-loop.\nPROFESSOR: OK. Now, we're about to do the next argument, so the first thing we do is\n\nsave argl. OK, we assign to x the first operand of fetch of UNEV. OK, we test and see if\nthat's the last operand. In this case, it is, so we're going to go to a special pl ace that says\n\nevaluate the last argument because, notice, after evaluating the argument, we don't need\nthe environment any more. That's going to be the difference.\n\n\n\n\n\nSo here, at eval-last-arg, which is assigned to accumulate-last-arg, now, we're set up again\nfor eval-dispatch. We've got a place to go to when we're done. We've got an expression.\n\nWe've got an environment. OK, so we'll short-circuit the call to eval-dispatch. And what'll\nhappen is there's a y there, it's 4 in that environment, so VAL will endup with 4 in it. And,\n\nthen, we're going to end up at accumulate-last-arg, OK? So, at accumulate-last-arg, we\nrestore argl. We assign to argl cons of fetch of the new value onto it, so we cons a 4 onto\n\nthat. We restore what was saved in the function register. And notice, in this case, it had not\n\nbeen destroyed, but, in general, it will be.\n\n\n\n\nAnd now, we're ready to go off to apply-dispatch, all right? So we've just gone through the\neval. We evaluated the argument, the operator, and the arguments, and now, we're about\n\nto apply them. So we come off to apply-dispatch here, OK? We come off to apply-dispatch,\n\nand we're going to check whether it's a primitive or a compound procedure.\n\n\n\n\nPROFESSOR: Yes.\n\n\n\n\nPROFESSOR: All right. So, in this case, it's a primitive procedure, and we go off to primitive-\n\napply. So we go off to primitive-apply, and it says assign to VAL the result of applying\nprimitive procedure of the function to the argument list.\n\n\n\n\n\nPROFESSOR: I don't know how to add. I'm just an execution unit.\n\n\n\n\nPROFESSOR: Well, I don't know how to add either. I'm just the evaluator, so we need a\n\nprimitive operator. Let's see, so the primitive operator, what's the sum of 3 and 4?\n\n\n\n\nAUDIENCE: 7.\n\n\n\n\nPROFESSOR: OK, 7.\nPROFESSOR: Thank you.\n\n\n\n\nPROFESSOR: Now, we restore continue, and we go to fetch of continue.\n\n\n\n\nPROFESSOR: Done.\n\n\n\n\n\nPROFESSOR: OK. Well, that was in as much detail as you will ever see. We'll never do it in\nas much detail again. One very important thing to notice is that we just executed a\n\nrecursive procedure, right? This whole thing, we used a stack and the evaluator was\nrecursive. A lot of people think the reason that you need a stack and recursion in an\n\nevaluator is because you might be evaluating recursive procedures like factorial or\n\nFibonacci. It's not true. So you notice we did recursion here, and all we evaluated was plus\nX, Y, all right? The reason that you need recursion in the evaluator is because the\n\nevaluation process, itself, is recursive, all right? It's not because the procedure that you\nmight be evaluating in LISP is a recursive procedure. So that's an important thing that\n\npeople get confused about a lot.\n\n\n\n\nThe other thing to notice is that, when we're done here, we're really done. Not only are we\n\nat done, but there's no accumulated stuff on the stack, right? The machine is back to its\ninitial state, all right? So that's part of what it means to be done. Another way to say that is\n\nthe evaluation process has reduced the expression, plus X, Y, to the value here, 7. And by\nreduced, I mean a very particular thing. It means that there's nothing left on the stack. The\n\nmachine is now in the same state, except there's something in the value register. It's not\npart of a sub-problem of anything. There's nothing to go back to. OK. Let's break. Question?\n\n\n\n\n\nAUDIENCE: The question here, in the stack, is because the data may be recursive. You may\nhave embedded expressions, for instance.\n\n\n\n\n\nPROFESSOR: Yes, because you might have embedded expressions. But, again, don't\nconfuse that with what people sometimes mean by the data may be recursive, which is to\n\nsay you have these list-structured, recursive data list operations. That has nothing to do\nwith it. It's simply that the expressions contain sub-expressions. Yeah?\n\n\n\n\n\nAUDIENCE: Why is it that the order of the arguments in the arg list got reversed?\nPROFESSOR: Ah! Yes, I should've mentioned that. Here, the reason the order is reversed--\nit's a question of what you mean by reversed. I believe it was Newton. In the very early\n\npart of optics, people realized that, when you look through the lens of your eye, the image\nwas up-side down. And there was a lot of argument about why that didn't mean you saw\n\nthings up-side down. So it's sort of the same issue. Reversed from what? So we just need\n\nsome convention. The reason that they're coming at 4, 3 is because we're taking UNEV and\nconsing the result onto argl. So you have to realize you've made that convention.\n\n\n\n\nThe place that you have to realize that-- well, there's actually two places. One is in apply -\n\nprimitive-operator, which has to realize that the arguments to primitives go in, in the\n\nopposite order from the way you're writing them down. And the other one is, we'll see later\nwhen you actually go to bind a function's parameters, you should realize the arguments are\n\ngoing to come in from the opposite order of the variables to which you're binding them. So,\nif you just keep track of that, there's no problem. Also, this is completely arbitrary because,\n\nif we'd done, say, an iteration through a vector assigning them, they might come out in the\nother order, OK? So it's just a convention of the way this particular evaluator works. All\n\nright, let's take a break.\n\n\n\n\nWe just saw evaluating an expression and, of course, that was very simple one. But, in\n\nessence, it would be no different if it was some big nested expression, so there would just\nbe deeper recursion on the stack. But what I want to do now is show you the last piece. I\n\nwant to walk you around this eval and apply loop, right? That's the thing we haven't seen,\nreally. We haven't seen any compound procedures where applying a procedure reduces to\n\nevaluating the body of the procedure, so let's just suppose we had this. Suppose we were\n\nlooking at the procedure define F of A and B to be the sum of A and B. So, as we typed in\nthat procedure previously, and now we're going to evaluate F of X and Y, again, in this\n\nenvironment, E,0, where X is bound to 3 and Y is bound to 4.\n\n\n\n\nWhen the defined is executed, remember, there's a lambda here, and lambdas create\nprocedures. And, basically, what will happen is, in E,0, we'll end up with a binding for F,\n\nwhich will say F is a procedure, and its args are A and B, and its body is plus a,b. So that's\n\nwhat the environment would have looked like had we made that definition.\n\n\n\n\nThen, when we go to evaluate F of X and Y, we'll go through exactly the same process that\nwe did before. It's even the same expression. The only difference is that F, instead of\n\nhaving primitive plus in it, will have this thing. And so we'll go through exactly the same\n\nprocess, except this time, when we end up at apply-dispatch, the function register, instead\nof having primitive plus, will have a thing that will represent it saying procedure, where the\n\nargs are A and B, and the body is plus A, B. And, again, what I mean, by its ENV, I mean\nthere's a pointer to it, so don't worry that I'm writing a lot of stuff there. There's a pointer\n\nto this procedure data structure.\n\n\n\n\nOK, so, we're in exactly the same situation. We get to apply-dispatch, so, here, we come to\n\napply-dispatch. Last time, we branched off to a primitive procedure. Here, it says oh, we\nnow have a compound procedure, so we're going to go off to compound-apply. Now, what's\n\ncompound-apply? Well, remember what the meta-circular evaluator did? Compound-apply\nsaid we're going to evaluate the body of the procedure in some new environment.\n\n\n\n\n\nWhere does that new environment come from? We take the environment that was packaged\nwith the procedure, we bind the parameters of the procedure to the arguments that we're\n\npassing in, and use that as a new frame to extend the procedure environment. And that's\nthe environment in which we evaluate the procedure body, right? That's going around the\n\napply/eval loop. That's apply coming back to call eval, all right?\n\n\n\n\nOK. So, now, that's all we have to do in compound-apply. What are we going to do? We're\n\ngoing to manufacture a new environment. And we're going to manufacture a new\nenvironment, let's see, that we'll call E,1. E,1 is going to be some environment where the\n\nparameters of the procedure, where A is bound to 3 and B is bound to 4, and it's linked to\nE,0 because that's where f is defined. And, in this environment, we're going to evaluate the\n\nbody of the procedure.\n\n\n\n\nSo let's look at that, all right? All right, here we are at compound-apply, which says assign\n\nto the expression register the body of the procedure that's in the function register. So I\nassign to the expression register the procedure body, OK? That's going to be evaluated in\n\nan environment which is formed by making some bindings using information determined by\nthe procedure-- that's what's in FUN-- and the argument list.\n\n\n\n\n\nAnd let's not worry about exactly what that does, but you can see the information's there.\nSo make bindings will say oh, the procedure, itself, had an environme nt attached to it. I\n\ndidn't write that quite here. I should've said in environment because every procedure gets\nbuilt with an environment. So, from that environment, it knows what the procedure's\n\ndefinition environment is. It knows what the arguments are. It looks at argl, and then you\nsee a reversal convention here. It just has to know that argl is reversed, and it builds this\n\nframe, E,1. All right, so, let's assume that that's what make bindings returns, so it assigns\n\nto ENV this thing, E,1.\nAll right, the next thing it says is restore continue. Remember what continue was here? It\n\ngot put up in the last segment. Continue got stored. That was the original done, which said\nwhat are you going to do after you're done with this particular application? It was one of the\n\nvery first things that happened when we evaluated the application.\n\n\n\n\nAnd now, finally, we're going to restore continue. Remember apply-dispatch's contract. It\n\nassumes that where it should go to next was on the stack, and there it was on the stack.\nContinue has done, and now we're going to go back to eval-dispatch. We're set up again.\n\nWe have an expression, an environment, and a place to go to. We're not going to go\nthrough that because it's sort of the same expression.\n\n\n\n\n\nOK, but the thing, again, to notice is, at this point, we have reduced the original expression,\nF,X,Y, right? We've reduced evaluating F,X,Y in environment E,0 to evaluate plus A, B in\n\nE,1. And notice, nothing's on the stack, right? It's a reduction. At this point, the machine\ndoes not contain, as part of its state, the fact that it's in the middle of evaluat ing some\n\nprocedure called f, that's gone, right? There's no accumulated state, OK?\n\n\n\n\nAgain, that's a very important idea. That's the meaning of, when we used to write in the\n\nsubstitution model, this expression reduces to that expression. And you don't have to\nremember anything. And here, you see the meaning of reduction. At this point, there is\n\nnothing on the stack. See, that has very important consequences. Let's go back and look at\niterative factorial, all right?\n\n\n\n\n\nRemember, this was some sort of loop and doing iter. And we kept saying that's an iterative\nprocedure, right? And what we wrote, remember, are things like, we said, fact-iter of 5. We\n\nwrote things like reduces to iter of 1, and 1, and 5, which reduces to iter of 1, and 2, and 5,\nand so on, and so on, and so on. And we kept saying well, look, you don't have to build up\n\nany storage to do that. And we waved our hands, and said in principle, there's no storage\n\nneeded. Now, you see no storage needed. Each of these is a real reduction, right?\n\n\n\n\nAs you walk through these expressions, what you'll see are these expressions on the stack\nin some particular environment, and then these expressions in the EXP register in some\n\nparticular environment. And, at each point, there'll be no accumulated stuff on the stack\nbecause each one's a real reduction, OK?\n\n\n\n\n\nAll right, so, for example, just to go through it in a little bit more care, if I start out with an\nexpression that says something like, oh, say, fact-iter of 5 in some environment that will, at\nsome point, create an environment in which n is down to 5. Let's call that -- And, at some\n\npoint, the machine will reduce this whole thing to a thing that says that's really iter of 1,\nand 1, and n, evaluated in this environment, E,1 with nothing on the stack. See, at th is\n\nmoment, the machine is not remembering that evaluating this expression, iter -- which is\nthe loop-- is part of this thing called iterative factorial. It's not remembering that. It's just\n\nreducing the expression to that, right? If we look again at the body of iterative factorial, this\nexpression has reduced to that expression. Oh, I shouldn't have the n there. It's a slightly\n\ndifferent convention from the slide to the program, OK?\n\n\n\n\nAnd, then, what's the body of iter? Well, iter's going to be an it, and I won't go through the\n\ndetails of if. It'll evaluate the predicate. In this case, it'll be false. And this iter will now\nreduce to the expression iter of whatever it says, star, counter product, and-- what does it\n\nsay-- plus counter 1 in some other environment, by this time, E,2, where E,2 will be set up\n\nhaving bindings for product and counter, right? And it'll reduce to that, right? It won't be\nremembering that it's part of something that it has to return to. And when iter calls iter\n\nagain, it'll reduce to another thing that looks like this in some environment, E,3, which has\nnew bindings for product and counter. So, if you're wondering, see, if you've always been\n\nqueasy about how it is we've been saying those procedures, that look syntactically\nrecursive, are, in fact, iterative, run in constant space, well, I don't know if this makes you\n\nless queasy, but at least it shows you what's happening. There really isn't any buildup\nthere.\n\n\n\n\n\nNow, you might ask well, is there buildup in principle in these environment frames? And the\nanswer is yeah, you have to make these new environment frames, but you don't have to\n\nhang onto them when you're done. They can be garbage collected, or the space can be\nreused automatically. But you see the control structure of the evaluator is really using this\n\nidea that you actually have a reduction, so these procedures really are iterative procedures.\n\nAll right, let's stop for questions. All right, let's break.\n\n\n\n\nLet me contrast the iterative procedure just so you'll see where space doesbuild up with a\nrecursive procedure, so you can see the difference. Let's look at the evaluation of recursive\n\nfactorial, all right? So, here's fact-recursive, or standard factorial definition. We said this one\nis still a recursive procedure, but this is actually a recursive process.\n\n\n\n\n\nAnd then, just to link it back to the way we started, we said oh, you can see that it's going\nto be recursive process by the substitution model because, if I say recursive factorial of 5,\n\nthat turns into 5 times-- what is it, fact-rec, or record fact-- 5 times recursive factorial of 4,\nwhich turns into 5 times 4 times fact-rec of 3, which returns into 5 times 4 times 3 times,\n\nand so on, right? The idea is there was this chain of stuff building up, which justified, in the\nsubstitution model, the fact that it's recursive. And now, let's actually see that chain of stuff\n\nbuild up and where it is in the machine, OK?\n\n\n\n\nAll right, well, let's imagine we're going to start out again. We'll tell it to evaluate recursive\n\nfactorial of 5 in some environment, again, E,0 where recursive factorial is defined, OK? Well,\nnow we know what's eventually going to happen. This is going to come along, it'll evaluate\n\nthose things, figure out it's a procedure, build somewhere over here an environment, E,1       ,\nwhich has n bound to 5, which hangs off of E,0, which would be, presumably, the definition\n\nenvironment of recursive factorial, OK?\n\n\n\n\nAnd, in this environment, it's going to go off and evaluate the body. So, again, the\n\nevaluation here will reduce to evaluating the body in E,1. That's going to look at an if, and I\nwon't go through the details of if. It'll look at the predicate. It'll decide it eventually has to\n\nevaluate the alternative. So this whole thing, again, will reduce to the alternative of\nrecursive factorial, the alternative clause, which says that this whole thing reduces to times\n\nn of recursive factorial of n minus 1 in the environment E,1, OK? So the original expression,\nnow, is going to reduce to evaluating that expression, all right?\n\n\n\n\n\nNow we have an application. We did an application before. Remember what happens in an\napplication? The first thing you do is you go off and you save the value of the continue\n\nregister on the stack. So the stack here is going to have done in it. And then you're goi ng to\nset up to evaluate the sub-parts, OK? So here we go off to evaluate the sub-parts.\n\n\n\n\n\nFirst thing we're going to do is evaluate the operator. What happens when we evaluate an\noperator? Well, we arrange things so that the operator ends up in the expression register.\n\nThe environments in the ENV register continue someplace where we're going to go evaluate\nthe arguments. And, on the stack, we've saved the original continue, which is where we\n\nwanted to be when we're all done. And then the things we needed when we're going to get\n\ndone evaluating the operator, the things we'll need to evaluate the arguments, namely, the\nenvironment and those arguments, those unevaluated arguments, so there they are sitting\n\non the stack. And we're about to go off to evaluate the operator.\n\n\n\n\nWell, when we return from this particular call-- so we're about to call eval-dispatch here--\nwhen we return from this call, the value of that operator, which, in this case, is going to be\n\nthe primitive multiplier procedure, will end up in the FUN register,all right? We're going to\n\nevaluate some arguments. They will evaluate in here. That'll give us 5, in this case. We're\ngoing to put that in the argl register, and then we'll go off to evaluate the second operand.\nSo, at the point where we go off to evaluate the second operand-- and I'll skip details like\n\ncomputing, and minus 1, and all of that-- but, when we go off to evaluate the second\noperand, that will eventually reduce to another call to fact-recursive. And, what we've got\n\non the stack here is the operator from that combination that we're going to use it in and the\nother argument, OK? So, now, we're set up for another call to recursive factorial. And, when\n\nwe're done with this one, we're going to go to accumulate the last arg. And remember what\nthat'll do? That'll say oh, whatever the result of this has to get combined with that, and\n\nwe're going to multiply them.\n\n\n\n\nBut, notice now, we're at another recursive factorial. We're about to call eval-dispatch\n\nagain, except we haven't really reduced it becausethere's stuff on the stack now. The stuff\non the stack says oh, when you get back, you'd better multiply it by the 5 you had hanging\n\nthere. So, when we go off to make another call, we evaluate the n minus 1. That gives us\n\nanother environment in which the new n's going to be down to 4. And we're about to call\neval-dispatch again, right?\n\n\n\n\nWe get another call. That 4 is going to end up in the same situation. We'll end up with\n\nanother call to fact-recursive n. And sitting on the stack will be the stuff from the original\n\none and, now, the subsidiary one we're doing. And both of them are waiting for the same\nthing. They're going to go to accumulate a last argument. And then, of course, when we go\n\nto the fourth call, the same thing happens, right? And this goes on, and on, and on.\n\n\n\n\nAnd what you see here on the stack, exactly what's sitting here on the stack, the thing that\n\nsays times and 5. And what you're going to do with that is accumulate that into a last\nargument. That's exactly this, right? This is exactly where that stuff is hanging. Effectively,\n\nthe operator you're going to apply, the other argument that it's got to be multiplied by\nwhen you get back and the parentheses, which says yeah, what you wanted to do was\n\naccumulate them. So, you see, the substituti on model is not such a lie. That really is, in\nsome sense, what's sitting right on the stack. OK.\n\n\n\n\n\nAll right, so that, in some sense, should explain for you, or at least convince you, that,\nsomehow, this evaluator is managing to take these procedures andexecute some of them\n\niteratively and some of them recursively, even though, as syntactically, they look like\nrecursive procedures. How's it managing to do that? Well, the basic reason it's managing to\n\ndo that is the evaluator is set up to save only what it needs later.\n\n\n\n\nSo, for example, at the point where you've reduced evaluating an expression and an\n\nenvironment to applying a procedure to some arguments, it doesn't need that original\nenvironment anymore because any environment stuff will be packaged inside the\nprocedures where the application's going to happen. All right, similarly, when you're going\n\nalong evaluating an argument list, when you've finished evaluating the list, when you're\nfinished evaluating the last argument, you don't need that argument l ist any more, right?\n\nAnd you don't need the environment where those arguments would be evaluated, OK? So\nthe basic reason that this interpreter is being so smart is that it's not being smart at all, it's\n\nbeing stupid. It's just saying I'm only going to save what I really need.\n\n\n\n\nWell, let me show you here. Here's the actual thing that's making a tail recursive.\n\nRemember, it's the restore of continue. It's saying when I go off to evaluate the procedure\nbody, I should tell eval to come back to the place where that original evaluation was\n\nsupposed to come back to. So, in some sense, you want to say what's the actual line that\nmakes a tail recursive? It's that one.\n\n\n\n\n\nIf I wanted to build a non-tail recursive evaluator, for some strange reason, all I would need\nto do is, instead of restoring continue at this point, I'd set up a label down here called,\n\n\"Where to come back after you've finished applying the procedure.\" Instead, I'd set\ncontinue to that. I'd go to eval-dispatch, and then eval-dispatch would come back here. At\n\nthat point, I would restore continue and go to the original one. So here, the only\n\nconsequence of that would be to make it non-tail recursive. It would give you exactly the\nsame answers, except, if you did that iterative factorial and all those i terative procedures, it\n\nwould execute recursively.\n\n\n\n\nWell, I lied to you a little bit, but just a little bit, because I showed you a slightly over -\n\nsimplified evaluator where it assumes that each procedure body has only one expression.\nRemember, in general, a procedure has a sequence of expressions in it. So there's nothing\n\nreally conceptually new. Let me just show you the actual evaluator that handles sequences\nof expressions.\n\n\n\n\n\nThis is compound-apply now, and the only difference from the old one is that, instead of\ngoing off to eval directly, it takes the whole body of the procedure, which, in this case, is a\n\nsequence of expressions, and goes off to eval-sequence. And eval-sequence is a little loop\nthat, basically, does these evaluations one at a time. So it does an evaluation. Says oh,\n\nwhen I come back, I'd better come back here to do the next one. And, when I'm all done,\nwhen I want to get the last expression, I just restore my continue and go off to eval -\n\ndispatch.\n\n\n\n\nAnd, again, if you wanted for some reason to break tail recursion in this evaluator, all you\n\nneed to do is not handle the last expression, especially. Just say, after you've done the last\nexpression, come back to some other place after which you restore continue. And, for some\nreason, a lot of LISP evaluators tended to work that way. And the only consequence of that\n\nis that iterative procedures built up stack. And it's not clear why that happened.\n\n\n\n\nAll right. Well, let me just sort of summarize, since this is a lot of details in a big program.\n\nBut the main point is that it's no different, conceptually, from translating any other\nprogram. And the main idea is that we have this universal evaluator program, the meta-\n\ncircular evaluator. If we translate that into LISP, then we have all of LISP. And that's all we\ndid, OK?\n\n\n\n\n\nThe second point is that the magic's gone away. There should be no more magic in this\nwhole system, right? In principle, it should all be very clear except, maybe, for how list\n\nstructured memory works, and we'll see that later. But that's not very hard.\n\n\n\n\nThe third point is that all this tail recursion came from the discipline of eval being very\n\ncareful to save only what it needs next time. It's not some arbitrary thing where we're\nsaying well, whenever we call a sub-routine, we'll save all the registers in the world and\n\ncome back, right? See, sometimes it pays to really worry about efficiency. And, when you're\ndown in the guts of your evaluator machine, it really pays to think about things like that\n\nbecause it makes big consequences.\n\n\n\n\nWell, I hope what this has done is really made the evaluator seem concrete, right? I hope\n\nyou really believe that somebody could hold a LISP evaluator in the palm of their hand.\nMaybe to help you believe that, here's a LISP evaluator that I'm holding the palm of my\n\nhand, right? And this is a chip which is actually quite a bit more complicated than the\nevaluator I showed you. Maybe, here's a better picture of it. What there is, is you can see\n\nthe same overall structure. This is a register array. These are the data paths. Here'sa finite\nstate controller. And again, finite state, that's all there is. And somewhere there's external\n\nmemory that'll worry about things.\n\n\n\n\nAnd this particular one is very complicated because it's trying to run LISP fast. And it has\n\nsome very, very fast parallel operations in there like, if you want to index into an array,\nsimultaneously check that the index is an integer, check that it doesn't exceed the array\n\nbands, and go off and do the memory access, and do all those things simultaneously. And\nthen, later, if they're all OK, actually get the value there. So there are a lot of complicated\n\noperations in these data paths for making LISP run in parallel. It's a completely non -risk\n\nphilosophy of evaluating LISP.\nAnd then, this microcode is pretty complicated. Let's see, there's what? There's about 389\n\ninstructions of 220-bit microcode sitting here because these are very complicated data\npaths. And the whole thing has about 89,000 transistors, OK? OK. Well, I hope that that\n\ntakes away a lot of the mystery. Maybe somebody wants to look at this. Yeah. OK. Let's\nstop. Questions?\n\n\n\n\n\nAUDIENCE: OK, now, it sounds like what you're saying is that, with the restore continue put\nin the proper place, that procedures that would invoke a recursive process now invoke an\n\ninteger process just by the way that the eval signature is?\n\n\n\n\nPROFESSOR: I think the way I'd prefer to put it is that, with restore continue put in the\n\nwrong place, you can cause any syntactically-looking recursive procedure, in fact, to build\nup stack as it runs. But there's no reason for that, so you might want to play around with it.\n\nYou can just switch around two or three instructions in the way compound -apply comes\nback, and you'll get something which isn't tail recursive.\n\n\n\n\n\nBut the thing I wanted to emphasize is there's no magic. It's not as if there's some very\nclever pre-processing program that's looking at this procedure, factorial iter, and say oh,\n\ngee, I really notice that I don't have to push stack in order to do this. Some people think\nthat that's what's going on. It's something much, much more dumb than that, it's this one\n\nplace you're putting the restore instruction. It's just automatic.\n\n\n\n\nAUDIENCE: OK.\n\n\n\n\n\nAUDIENCE: But that's not affecting the time complexity is it?\n\n\n\n\nPROFESSOR: No.\n\n\n\n\nAUDIENCE: It's just that it's handling it recursively instead of iteratively. But, in terms of\n\nthe order of time it takes to finish the operation, it's the same one way or the other, right?\n\n\n\n\nPROFESSOR: Yes. Tail recursion is not going to change the time complexity of anything\n\nbecause, in some sense, it's the same algorithm that's going on. What it's doing is really\nmaking this thing run as an iteration, right? Not going to run out of memory counting up to\n\na giant number simply because the stack would get pushed.\nSee, the thing you really have to believe is that, when we write-- see, we've been writing all\nthese things called iterations, infinite loops, define loop to be called loop. That's is as much\n\nan iteration as if we wrote do forever loop, right? It's just syntactic sugar as the difference.\nThese things are real, honest to god, iterations, right? They don't change the time\n\ncomplexity, but they turn them into real iterations. All right, thank you.\nMIT OpenCourseWare\nhttp://ocw.mit.edu\n\n\n6.001 Structure and Interpretation of Computer Programs, Spring 2005\n\n\n\n\n\nPlease use the following citation format:\n\n       Eric Grimson, Peter Szolovits, and Trevor Darrell, 6.001 Structure and\n\n       Interpretation of Computer Programs, Spring 2005. (Massachusetts Institute\n       of Technology: MIT OpenCourseWare).    http://ocw.mit.edu (accessed MM DD,\n       YYYY). License: Creative Commons Attribution-Noncommercial-Share Alike.\n\n\nNote: Please use the actual date you accessed thismaterial in your citation.\n\n\n\nFor more information about citing these materials or our Terms of Use, visit:\nhttp://ocw.mit.edu/terms"
  },
  {
    "path": "Tools/con2table.rb",
    "content": "#!/usr/bin/env ruby\n# *encoding: UTF-8*\n\nrequire 'json'\n\ndef avatar(contributor)\n  \"![](#{contributor['avatar']})\"\nend\n\ndef name(contributor)\n  \"[#{contributor['name']}](https://github.com/#{contributor['name']})\"\nend\n\ndb = JSON.parse(File.open('contributor.json').read)\n\nresult = db.each_slice(5).map do |line|\n  row = \"\"\n  row << \"|\" + line.map {|contri| avatar(contri)}.join(\"|\") + \"|\\n\"\n  row << \"|\" + line.map {|contri| name(contri)}.join(\"|\") + \"|\" \nend.join(\"\\n\")\n\nputs result"
  },
  {
    "path": "Tools/contributor.json",
    "content": "[\n\t{\"name\": \"DeathKing\",\n\t \"avatar\": \"https://avatars0.githubusercontent.com/u/895809?s=120\"},\n\t{\"name\": \"ChingfanTsou\",\n\t \"avatar\": \"https://avatars1.githubusercontent.com/u/2025499?s=120\"},\n\t{\"name\": \"endyul\",\n\t \"avatar\": \"https://avatars2.githubusercontent.com/u/1056031?s=120\"},\n\t{\"name\": \"mut0u\",\n\t \"avatar\": \"https://avatars0.githubusercontent.com/u/1238353?s=120\"},\t \n\t{\"name\": \"DreamAndDead\",\n\t \"avatar\": \"https://avatars1.githubusercontent.com/u/5028822?s=120\"},\n\t{\"name\": \"rtmagic\",\n\t \"avatar\": \"https://avatars2.githubusercontent.com/u/13829499?s=120\"},\n\t{\"name\": \"Windfarer\",\n\t \"avatar\": \"https://avatars2.githubusercontent.com/u/7036121?s=120\"},\n\t{\"name\": \"Rezhe\",\n\t \"avatar\": \"https://avatars1.githubusercontent.com/u/30205820?s=120\"},\n\t{\"name\": \"ustcscgy\",\n\t \"avatar\": \"https://avatars3.githubusercontent.com/u/2822054?s=120\"} \n]"
  },
  {
    "path": "Tools/download-sicp-movies.sh",
    "content": "# Script by bjartwoIf\n# From https://gist.github.com/bjartwolf/3471090\nwget http://ia700402.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec1a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec1b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec2a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec2b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec3a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec3b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec4a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec4b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec5a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec5b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec6a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec6b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec7a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec7b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec8a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec8b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec9a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec9b.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec10a.mp4\nwget http://ia700401.us.archive.org/8/items/MIT_Structure_of_Computer_Programs_1986/lec10b.mp4"
  },
  {
    "path": "Tools/lec.json",
    "content": "[\n    {\n        \"id\":         \"Lec1a\",\n        \"title\":      \"Lisp概览\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XNTEzMDAyMTU2.html\",\n        \"youtube\":    \"https://youtu.be/IcZSFewqr9k\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_1.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1kTmeMgR\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/109WuY4ONSZddFXyE2hQGwg\",\n        \"translator\": [\"DeathKing\"]\n    },\n    {\n        \"id\":         \"Lec1b\",\n        \"title\":      \"计算过程\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XNTMxODY1NTg4.html\",\n        \"youtube\":    \"https://youtu.be/WuK9NmA3aq0\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_2.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1o6G0Qgi\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1C3muRwhMdK8yioHWw5P-1Q\",\n        \"translator\": [\"ChingfanTsou\"]\n    },\n    {\n        \"id\":         \"Lec2a\",\n        \"title\":      \"高阶过程\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XNzAzNjI1NjU2.html\",\n        \"youtube\":    \"https://youtu.be/mrgcGvOI1bs\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_3.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1jG3HI8A\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1MHiHVHfwq6x8rylBVDGV0A\",\n        \"translator\": [\"endyul\"]\n    },\n    {\n        \"id\":         \"Lec2b\",\n        \"title\":      \"复合数据\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XNzAzNjg4Mjk2.html\",\n        \"youtube\":    \"https://youtu.be/ufTdeiz9dMw\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_4.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1o6HgNgu\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1DfX7DJ_pMd7AtMlJwqyoRg\",\n        \"translator\": [\"DeathKing\"]\n    },\n    {\n        \"id\":         \"Lec3a\",\n        \"title\":      \"Henderson-Escher的例子\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XODk4NjUwODMy.html\",\n        \"youtube\":    \"https://youtu.be/YCR03O5EUdI\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_5.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1bnHBWmz\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1bOJvDO\",\n        \"translator\": [\"DeathKing\", \"Michael Savior\"]\n    },\n    {\n        \"id\":         \"Lec3b\",\n        \"title\":      \"符号化求导系统：引用\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XODk4NjUwODA0.html\",\n        \"youtube\":    \"https://youtu.be/cgGbiMptQM0\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_6.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1o6Jry9G\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1mhS2EV2\",\n        \"translator\": [\"DeathKing\"]\n    },\n    {\n        \"id\":         \"Lec4a\",\n        \"title\":      \"模式匹配：基于规则的代换\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMTM4NTY5NzE3Ng.html\",\n        \"youtube\":    \"https://youtu.be/zSxepaPtNQY\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_7.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1c0Hjs1U\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1U9E33yRr5mIqrdTOjnJeGA\",\n        \"translator\": [\"DeathKing\", \"Michael Savior\"]\n    },\n    {\n        \"id\":         \"Lec4b\",\n        \"title\":      \"通用运算符\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMTQ3NDEwODUyNA==.html\",\n        \"youtube\":    \"https://youtu.be/RlfZridRcw0\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_8.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1mhyap3E\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1vAv8Hi46f9ku2y7LHPpzzw\",\n        \"translator\": [\"rtmagic\"]\n    },\n    {\n        \"id\":         \"Lec5a\",\n        \"title\":      \"赋值，状态和副作用\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMTczMjIxNTM2NA==.html\",\n        \"youtube\":    \"https://youtu.be/ozss6dvq7ZU\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_9.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1sl7wgqx\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1boWiMWB\",\n        \"translator\": [\"Windfarer\"]\n    },\n    {\n        \"id\":         \"Lec5b\",\n        \"title\":      \"计算对象\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMjY0NzE3NzQ2MA==.html\",\n        \"youtube\":    \"https://youtu.be/2Iz7agtk614\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_10.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1kVG8SNP\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1c1FRLIg\",\n        \"translator\": [\"DreamAndDead\"]\n    },\n    {\n        \"id\":         \"Lec6a\",\n        \"title\":      \"流 I\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMjg4NTkwNzU3Ng==.html\",\n        \"youtube\":    \"https://youtu.be/z7jvvATswFE\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_11.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1hs7rNwg\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1pLlvcLH\",\n        \"translator\": [\"DreamAndDead\"]\n    },\n    {\n        \"id\":         \"Lec6b\",\n        \"title\":      \"流 II\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzAyMjI0MjAzNg==.html\",\n        \"youtube\":    \"https://youtu.be/0lQ6fThLhYw\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_12.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1micH5OW\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1b3kbWq\",\n        \"translator\": [\"DreamAndDead\"]\n    },\n    {\n        \"id\":         \"Lec7a\",\n        \"title\":      \"元循环求值器 I\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzAzODg2ODczNg==.html\",\n        \"youtube\":    \"https://youtu.be/RXUqgWJES0w\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_13.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1kUYGlVp\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1kV1M0ab\",\n        \"translator\": [\"DeathKing\", \"DreamAndDead\"]\n    },\n    {\n        \"id\":         \"Lec7b\",\n        \"title\":      \"元循环求值器 II\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzA2NDQ5MjkxMg==.html\",\n        \"youtube\":    \"https://youtu.be/HNaAEv8Xjx8\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_14.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1eSrNSNS\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1qYBgrIO\",\n        \"translator\": [\"DeathKing\", \"DreamAndDead\"]\n    },\n    {\n        \"id\":         \"Lec8a\",\n        \"title\":      \"逻辑式程序设计 I\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzIyODg0NTEwNA==.html\",\n        \"youtube\":    \"https://youtu.be/VNH95lmCHdE\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_15.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1i5aQQVj\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1dFlOqrB\",\n        \"translator\": [\"DeathKing\"]\n    },\n    {\n        \"id\":         \"Lec8b\",\n        \"title\":      \"逻辑式程序设计 II\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzQ4MDA1OTE3Mg==.html\",\n        \"youtube\":    \"https://youtu.be/mcik1gEEyqA\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_16.html\",\n        \"baidu\":      \"https://pan.baidu.com/s/1P6b00XxTfaaQX5GxSbROjg\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1MN5ZDrnnKeE0XeMqAY6x0Q\",\n        \"translator\": [\"DeathKing\"]\n    },\n    {\n        \"id\":         \"Lec9a\",\n        \"title\":      \"寄存机器\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzU3MzA5Mzg0OA==.html\",\n        \"youtube\":    \"https://youtu.be/oR2PwG0xh_g\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_17.html\",\n        \"baidu\":      \"#\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1AFM6__x4oGq3XtI_fa3ZGQ\",\n        \"translator\": [\"DeathKing\"]\n    },\n    {\n        \"id\":         \"Lec9b\",\n        \"title\":      \"显式控制求值器\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzcxMDAzMTA1Mg==.html\",\n        \"youtube\":    \"https://youtu.be/mrRcB4uY75M\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_18.html\",\n        \"baidu\":      \"#\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1bHhuJdEQyE9Fyw06Y6tOZw\",\n        \"translator\": [\"DeathKing\", \"rtmagic\"]\n    },\n    {\n        \"id\":         \"Lec10a\",\n        \"title\":      \"编译\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzYyNTcxNDYwOA==.html\",\n        \"youtube\":    \"https://youtu.be/vBEkYVrtfBE\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_19.html\",\n        \"baidu\":      \"#\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1IWkeR7gM5jiVFPMVhdZ4fg\",\n        \"translator\": [\"Windfarer\"]\n    }\n    ,\n    {\n        \"id\":         \"Lec10b\",\n        \"title\":      \"存储分配与垃圾收集\",\n        \"youku\":      \"https://v.youku.com/v_show/id_XMzc3NjI4MzQ4NA==.html\",\n        \"youtube\":    \"https://youtu.be/HNjPAzmSho8\",\n        \"bilibili\":   \"https://www.bilibili.com/video/av8515129/index_20.html\",\n        \"baidu\":      \"#\",\n        \"baidu-mp4\":  \"https://pan.baidu.com/s/1LKoXNWFD9lFclgNKeCBxsg\",\n        \"translator\": [\"Windfarer\"]\n    }\n]"
  },
  {
    "path": "Tools/lec2tabel.rb",
    "content": "#!/usr/bin/env ruby\n# *encoding: UTF-8*\n\nrequire 'json'\n\nAUTHORS = {\n  \"ChingfanTsou\"   => \"https://github.com/ChingfanTsou\",\n  \"DeathKing\"      => \"https://github.com/DeathKing\",\n  \"endyul\"         => \"https://github.com/endyul\",\n  \"Michael Savior\" => \"https://github.com/mut0u\",\n  \"rtmagic\"        => \"https://github.com/rtmagic\",\n  \"Windfarer\"      => \"https://github.com/Windfarer\",\n  \"DreamAndDead\"   => \"https://github.com/DreamAndDead\",\n}\n\n# [优酷] [YouTube] [bilibili] [MP4-内嵌字幕]\nFORMAT = \"| %-s | %-s | %-s %-s %-s %-s | %-s |\"\n\nICON = {\n  \"youtube\" => \"https://cloud.githubusercontent.com/assets/895809/7487454/7bcde098-f3ea-11e4-85be-d267459c4974.png\",\n  \"youku\"   => \"https://cloud.githubusercontent.com/assets/895809/7487453/7ad84a02-f3ea-11e4-9af4-2f8c4dc8679d.png\",\n  \"baidu\"   => \"https://cloud.githubusercontent.com/assets/895809/7487452/7aca0af0-f3ea-11e4-97a2-9ad4af3c6e2e.png\"\n}\n\ndef render_authors(authors)\n  res = []\n  authors.each do |a|\n    res << (AUTHORS.has_key?(a) ? render_as_mdlink(a, AUTHORS[a]) : a)\n  end\n  res.join(\", \")\nend\n\ndef render_as_mdlink(text, link=nil)\n  (link.nil? || link == '#')  ? text : \"[#{text}](#{link})\"\nend\n\ndef render_as_mdpic(alt, link)\n  \"![#{alt}](#{link})\"\nend\n\ndef render_as_mdpiclink(picurl, text, link)\n  render_as_mdlink render_as_mdpic(text, picurl), link\nend\n\ndef itemize(row)\n  FORMAT % [\n    row[\"id\"],\n    \"《\" + row[\"title\"] + \"》\",\n    render_as_mdlink(\" [优酷] \",      row[\"youku\"]),\n    render_as_mdlink(\" [YouTube] \",  row[\"youtube\"]),\n    render_as_mdlink(\" [bilibili] \", row[\"bilibili\"]),\n    render_as_mdlink(\" [MP4] \",      row[\"baidu-mp4\"]),\n    render_authors(row[\"translator\"])\n  ]\nend\n\ndef table_head\n  \"| 编号 | 标题 | 下载地址 | 译者 |\"\nend\n\ndef divider\n  \"| ---- | ---- |:-----------------------:| ---- |\"\nend\n\ncontent = File.open('lec.json').read\n\ndb = JSON.parse(content)\n\nputs table_head\nputs divider\n\ndb.each do |row|\n  puts itemize(row)\nend\n\n"
  },
  {
    "path": "Tools/merge.rb",
    "content": "#!/usr/bin/env ruby\n\n# MERGE.RB: merge two subtitles into one.\n#\n# usage: merge file1 file2 [output_file]\n#\n# options: -b   backup original file\nrequire_relative 'util'\n\nclass IO\n\n  def each_unit(lines)\n    result = []\n    each_line do |line|\n      result << line\n      if result.size == lines\n        yield result\n        result = []\n      end\n    end\n    result << \"\" until result.size == lines\n    yield result\n  end\n\nend\n\nSubUnit = Struct.new(:number, :timeline, :content, :tag)\n\ntarget = ARGV[2]\n\nunless ARGV.size >= 3\n  backup_file File.expand_path(ARGV[0])\n  backup_file File.expand_path(ARGV[1])\n  target = ARGV[0]\nend\n\nchn = []\neng = []\n\nopen(ARGV[0]).each_unit(4) do |u|\n  number, timeline, content, _ = *u\n  chn << SubUnit.new(number, timeline, content, 'chn')\nend\n\nopen(ARGV[1]).each_unit(4) do |u|\n  number, timeline, content, _ = *u\n  eng << SubUnit.new(number, timeline, content, 'eng')\nend\n\n# actual_merge\nmerged = []\nchn.zip(eng) do |p|\n  chn, eng = *p\n  if chn.timeline != eng.timeline\n    puts \"Some thing unmatched found:\"\n    puts \"[CHN %4s %30s]%s\" % [chn.number, chn.timeline, chn.content]\n    puts \"[ENG %4s %30s]%s\" % [eng.number, eng.timeline, eng.content]\n    puts \"Aborted!\"\n    exit(0)\n  end\n  chn.content = \"#{chn.content}#{eng.content}\"\n  merged << chn\nend\n\nopen(target, \"w\") do |f|\n  merged.each do |m|\n    f.puts m.number\n    f.puts m.timeline\n    f.puts m.content\n    f.puts \"\\n\"\n  end\nend\n"
  },
  {
    "path": "Tools/pdf2txt.rb",
    "content": "#!/usr/bin/env ruby\n\n# Gist from: https://gist.github.com/blazeeboy/9722831\n\n#begin\n  require 'pdf/reader'\n  require 'fileutils'\n#ensure\n # puts \"Oops! Must something went wrong.\"\n#  puts \"I think you should try `gem install pdf-reader` before excute this.\"\n#  exit\n#end\n\n# credits to :\n#   https://github.com/yob/pdf-reader/blob/master/examples/text.rb\n# usage example: \n#   ruby pdf2txt.rb /path-to-file/file1.pdf [/path-to-file/file2.pdf..]\n\nDir.foreach(ARGV.first) do |filename|\n  next if [\".\", \"..\"].include? filename\n  PDF::Reader.open(filename) do |reader|\n \n    puts \"Converting : #{filename}\"\n    pageno = 0\n    txt = reader.pages.map do |page| \n \n      pageno += 1\n      begin\n        print \"Converting Page #{pageno}/#{reader.page_count}\\r\"\n        page.text \n      rescue\n        puts \"Page #{pageno}/#{reader.page_count} Failed to convert\"\n        ''\n      end\n \n    end # pages map\n \n    puts \"\\nWriting text to disk\"\n    File.write filename+'.txt', txt.join(\"\\n\")\n \n  end # reader\n \nend # each"
  },
  {
    "path": "Tools/separate.rb",
    "content": "#!/usr/bin/env ruby\n# encoding: utf-8\n\nif ARGV.empty?\n    puts \"Separate - 分割单个双语字幕为两个字幕。\"\n    puts \"用法: separate srt_file\"\n    puts \"说明：如果出错了，尝试调整一下newline。\"\n    puts \"Writen by DeathKing\"\n    exit\nend\n\neng = []\nchn = []\ncont = []\n\n# 换行符，由于文件比较混乱，有时需要自行调整\n# 如有问题，可以尝试调整为 \\n、\\r、\\r\\n中的其它值\nnewline = \"\\n\" \n\nopen(ARGV[0]).each_line do |line|\n    if line == newline\n        # 一个块 \n        eng << cont[0] << cont[1]\n        chn << cont[0] << cont[1]\n        # 非字幕块，即为制作信息时的处理\n        # 把内容全拷贝到中文字幕文件中\n        # 英文字幕用newline占位\n        if cont.size != 4\n            for i in 2...cont.size\n                chn << cont[i]\n            end\n            chn << newline\n            eng << newline << newline\n        else\n            # 拷贝到对应文件中去\n            chn << cont[2] << newline\n            eng << cont[3] << newline\n        end\n        cont.clear\n    else\n        cont << line\n    end\nend\n\nfilename = ARGV[0].split(\".\")[0]\neng_file = \"#{filename}_eng.srt\"\nchn_file = \"#{filename}_chn.srt\" \n\nopen(eng_file, \"w\").puts(eng.join)\nopen(chn_file, \"w\").puts(chn.join)\n"
  },
  {
    "path": "Tools/split.pl",
    "content": "#! /usr/bin/perl\nuse 5.010;\nuse utf8;\nuse warnings;\nuse strict;\n\nmy $srt_file = shift(@ARGV);\nopen SRT, '<:encoding(UTF-8)', $srt_file;\n\nmy @text = <SRT>;\n\nclose SRT;\n\nif (@ARGV) {\n    $srt_file = shift(@ARGV);\n}\n\nopen NEWSRT, '>:encoding(UTF-8)', $srt_file;\n\nforeach my $line (@text) {\n    chomp($line);\n    $line =~ s/((?:[,.?!;:])|(?:-+))\\s/$1\\n\\n\\n\\n/g;\n    print NEWSRT $line;\n}\n\nclose NEWSRT;\n"
  },
  {
    "path": "Tools/split.rb",
    "content": "#!/usr/bin/env ruby\n# encoding: utf-8\nrequire_relative 'util'\n\ndef help\n  doc = <<-HELP\n\n  HELP\nend\n\n\nfilename = ARGV.first\n\nbackup_file(filename)\n\nputs File.open(filename).each_line.map do |line|\n  line.gsub! \"\\n\", \"\"\n  line.gsub! \". \", \".\\n\"\n  line.strip!\n  line\nend.join"
  },
  {
    "path": "Tools/timeline.rb",
    "content": "#!/usr/bin/env ruby\n# --* encoding: utf-8 *--\nrequire 'fileutils'\n\ncont = []\nblock = []\ncounter, flag = 1, false\nnewline = \"\\n\"\ntemplate = \"%d#{newline}00:00:00,000 --> 00:00:00,000#{newline}\"\n\nif ARGV.empty?\n    puts \"Timeline - 为字幕添加初始化时间轴。\"\n    puts \"用法： timeline /path/to/your/file.srt\"\n    puts \"说明：本地会备份一个文件。如果使用出现了问题，请尝试调整newline。\"\n    puts \"\\nWriten by DeathKing\"\n    exit\nend\n\nFileUtils.cp ARGV[0], ARGV[0] + \".backup\"\nopen(ARGV[0]).each_line do |line|\n    if line == newline and !flag\n        cont << sprintf(template, counter) << block.clone << newline\n        flag = true\n        counter += 1\n        block.clear\n    else\n        block << line\n        flag = false\n    end\nend\n\nopen(ARGV[0], \"w\").puts(cont.join)\n"
  },
  {
    "path": "Tools/util.rb",
    "content": "# --* encoding: utf-8 *--\nrequire 'fileutils'\n\ndef backup_filename(filename)\n  filename + \".backup\"\nend\n\ndef backup_file(filename)\n  FileUtils.cp(filename, backup_filename(filename))\nend"
  }
]